From 9109c032f024c8de693373e35ba108c8b9032a15 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 1 Jul 2020 01:22:24 +0200 Subject: [PATCH 0001/1751] Fix to allow writing payload w/o dictionary in CTF --- .../Common/include/DetectorsCommonDataFormats/EncodedBlocks.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 3d4d2ae2f392c..3474a5954adf6 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -128,9 +128,9 @@ struct Block { int nStored = 0; // total payload: data + dictionary length W* payload = nullptr; //[nStored]; - W* getData() { return payload + nDict; } + W* getData() { return payload ? (payload + nDict) : (payload = reinterpret_cast(registry->getFreeBlockStart())); } W* getDict() { return nDict ? payload : nullptr; } - const W* getData() const { return payload + nDict; } + const W* getData() const { return payload ? (payload + nDict) : nullptr; } const W* getDict() const { return nDict ? payload : nullptr; } int getNData() const { return nStored - nDict; } int getNDict() const { return nDict; } From a48b032fd80cb8dd9ab745eeed74a37f3f28bbfd Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 30 Jun 2020 12:10:51 +0200 Subject: [PATCH 0002/1751] Improved embedding benchmark * able to benchmark local + network scenario * in network scenario do asyncronous network cp together with signal production * somewhat specific to EOS at the moment and needs further generalization for real GRID usage --- prodtests/embedding_benchmark.sh | 142 +++++++++++++++++++++++-------- 1 file changed, 108 insertions(+), 34 deletions(-) diff --git a/prodtests/embedding_benchmark.sh b/prodtests/embedding_benchmark.sh index 5e2e3ba51900a..47035b7e8a09e 100755 --- a/prodtests/embedding_benchmark.sh +++ b/prodtests/embedding_benchmark.sh @@ -37,7 +37,7 @@ taskwrapper() { # launch the actual command in the background echo "Launching task: ${command} &> $logfile &" - command="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh /usr/bin/time --output=${logfile}_time '${command}'" + command="TIME=\"#walltime %e %M\" ${O2_ROOT}/share/scripts/monitor-mem.sh /usr/bin/time --output=${logfile}_time '${command}'" eval ${command} &> $logfile & # THE NEXT PART IS THE SUPERVISION PART @@ -106,18 +106,19 @@ taskwrapper() { # default number of events -nevS=100 # nevents signal -nevBG=10 # nevents background +nevS=${nevS:-100} # nevents signal +nevBG=${nevBG:-10} # nevents background NCPUS=8 # default on GRID # default interaction rates in kHz intRate=50 -generS="pythia8hf" -generBG="pythia8hi" +generS=${generS:-"pythia8hf"} +generBG=${generBG:-"pythia8hi"} +scenario=${scenario:-"local"} # or network # default sim engine -engine="TGeant3" +engine=${engine:-"TGeant3"} # options to pass to every workflow gloOpt=" -b --run " @@ -129,6 +130,34 @@ Usage() exit } +CACHEPATH="/eos/user/a/aliperf/simulation/mock_data/background_cache/1" + +# function performing network transfer of kinematic background files --> needed for signal production +Fetch_Background_EOS_Kine() { + echo "Start Fetching background kinematics" + eos cp root://eosuser.cern.ch//${CACHEPATH}/o2simbg_Kine.root . + echo "Fetching background kinematics finished" +} + +# function performing network transfer of hits background files --> needed for digitization +Fetch_Background_EOS_Hits() { + echo "Start Fetching background hits" + # better do this with an xrootd query but should be ok to start from + export EOS_MGM_URL=root://eosuser.cern.ch + eos cp ${CACHEPATH}/o2simbg_geometry.root . + eos cp ${CACHEPATH}/o2simbg_grp.root . + eos cp ${CACHEPATH}/o2simbg_Hits*.root . + echo "Fetching background hits finished" +} + +# Upload to EOS +Upload_Background_EOS() { + echo "Start uploading background event" + export EOS_MGM_URL=root://eosuser.cern.ch + eos cp o2simbg* ${CACHEPATH} + echo "Uploading background hits finished" +} + while [ $# -gt 0 ] ; do case $1 in -e) engine=$2; shift 2 ;; @@ -137,33 +166,78 @@ while [ $# -gt 0 ] ; do esac done -echo "Running background simulation for $nevBG $collSyst events with $generBG generator and engine $engine" -taskwrapper sim_bg.log o2-sim -j ${NCPUS} -n"$nevBG" --configKeyValue "Diamond.width[2]=6." -g "$generBG" -e "$engine" -o o2simbg --skipModules ZDC -# extract time - -echo "Running signal simulation for $nevS $collSyst events with $generS generator and engine $engine" -taskwrapper sim_s.log o2-sim -j ${NCPUS} -n"$nevS" --configKeyValue "Diamond.width[2]=6." -g "$generS" -e "$engine" -o o2sims --embedIntoFile o2simbg_Kine.root --skipModules ZDC -# extract time - -echo "Running digitization for $intRate kHz interaction rate" -# We run the digitization in stages in order to use -# the given number of CPUs in a good way. The order and sequence here can be modified and improvements will be -# achievable when "REST" contains more parallelism. TPC and TRD should use the resources fully already. -intRate=$((1000*(intRate))); -taskwrapper digi_TPC.log o2-sim-digitizer-workflow --tpc-lanes ${NCPUS} --onlyDet TPC $gloOpt --sims o2simbg,o2sims -n ${nevS} --interactionRate $intRate --disable-mc -taskwrapper digi_TRD.log o2-sim-digitizer-workflow --onlyDet TRD $gloOpt --configKeyValues="TRDSimParams.digithreads=${NCPUS}" --sims o2simbg,o2sims -n ${nevS} --interactionRate $intRate --disable-mc -taskwrapper digi_REST.log o2-sim-digitizer-workflow --skipDet TRD,TPC $gloOpt --sims o2simbg,o2sims -n ${nevS} --interactionRate $intRate --disable-mc - -# extract gain from embedding procedure and background reusage by analysing reported times: -transporttime_BG=`awk '/walltime/{print $2}' sim_bg.log_time` -transporttime_S=`awk '/walltime/{print $2}' sim_s.log_time` -digi_time_TPC=`awk '/walltime/{print $2}' digi_TPC.log_time` -digi_time_TRD=`awk '/walltime/{print $2}' digi_TRD.log_time` -digi_time_REST=`awk '/walltime/{print $2}' digi_REST.log_time` - -echo "$transporttime_BG $transporttime_S $digi_time_TPC $digi_time_TRD $digi_time_REST" | awk -v nS="${nevS}" -v nB="${nevBG}" '//{noembed=($1*nS/(1.*nB) + $2) + $3 + $4 + $5;embed=($1 + $2) + $3 + $4 + $5; print "NBG "nB " NSignal "nS" Ordinary-time "noembed," Embed-time "embed" Ratio ",noembed/embed }' - -# TODO: compare this to scenario where we fetch background events from the network! -# Run this actually containerized to fix the CPU + MEMORY space. +produce_background() +{ + echo "Running background simulation for $nevBG $collSyst events with $generBG generator and engine $engine" + taskwrapper sim_bg.log o2-sim -j ${NCPUS} -n"$nevBG" --configKeyValue "Diamond.width[2]=6." -g "$generBG" -e "$engine" -o o2simbg --skipModules ZDC --seed ${SEED:-1} +} + +produce_signal() +{ + echo "Running signal simulation for $nevS $collSyst events with $generS generator and engine $engine" + taskwrapper sim_s.log o2-sim -j ${NCPUS} -n"$nevS" --configKeyValue "Diamond.width[2]=6." -g "$generS" -e "$engine" -o o2sims --embedIntoFile o2simbg_Kine.root --skipModules ZDC --seed ${SEED:-1} +} + +do_transport_local() +{ + produce_background + Upload_Background_EOS + produce_signal +} + +do_transport_usecachedBG() +{ + echo "Start fetching background kinematics" + Fetch_Background_EOS_Kine & + KINE_PID=$! + + Fetch_Background_EOS_Hits & + HITS_PID=$! + + wait ${KINE_PID} + produce_signal + + wait ${HITS_PID} +} + +digitize() { + echo "Running digitization for $intRate kHz interaction rate" + # We run the digitization in stages in order to use + # the given number of CPUs in a good way. The order and sequence here can be modified and improvements will be + # achievable when "REST" contains more parallelism. TPC and TRD should use the resources fully already. + intRate=$((1000*(intRate))); + taskwrapper digi_TPC.log o2-sim-digitizer-workflow --tpc-lanes ${NCPUS} --onlyDet TPC $gloOpt --sims o2simbg,o2sims -n ${nevS} --interactionRate $intRate --disable-mc -- + taskwrapper digi_TRD.log o2-sim-digitizer-workflow --onlyDet TRD $gloOpt --configKeyValues="TRDSimParams.digithreads=${NCPUS}" --sims o2simbg,o2sims -n ${nevS} --interactionRate $intRate --disable-mc --incontext collisioncontext.root + taskwrapper digi_REST.log o2-sim-digitizer-workflow --skipDet TRD,TPC $gloOpt --sims o2simbg,o2sims -n ${nevS} --interactionRate $intRate --disable-mc --incontext collisioncontext.root +} + +if [[ "${scenario}" == "local" ]]; then + do_transport_local + digitize + + # extract gain from embedding procedure and background reusage by analysing reported times: + transporttime_BG=`awk '/walltime/{print $2}' sim_bg.log_time` + transporttime_S=`awk '/walltime/{print $2}' sim_s.log_time` + digi_time_TPC=`awk '/walltime/{print $2}' digi_TPC.log_time` + digi_time_TRD=`awk '/walltime/{print $2}' digi_TRD.log_time` + digi_time_REST=`awk '/walltime/{print $2}' digi_REST.log_time` + echo "$transporttime_BG $transporttime_S $digi_time_TPC $digi_time_TRD $digi_time_REST" + echo "$transporttime_BG $transporttime_S $digi_time_TPC $digi_time_TRD $digi_time_REST" | awk -v nS="${nevS}" -v nB="${nevBG}" '//{digi=$3+$4+$5;noembed=($1*nS/(1.*nB) + $2) + digi;embed=($1 + $2) + digi; embedCachedIO=($2 + digi);print "NBG "nB " NSignal "nS" Ordinary-time "noembed," Embed-time "embed" Embed-time (cached optimal) "embedCachedIO" Ratio ",noembed/embed" Ratio optimal"noembed/embedCachedIO }' +fi + +if [[ "${scenario}" == "network" ]]; then + # Scenario where we fetch background events from the network! + do_transport_usecachedBG + + digitize + + # extract gain from embedding procedure and background reusage by analysing reported times: + transporttime_S=`awk '/walltime/{print $2}' sim_s.log_time` + digi_time_TPC=`awk '/walltime/{print $2}' digi_TPC.log_time` + digi_time_TRD=`awk '/walltime/{print $2}' digi_TRD.log_time` + digi_time_REST=`awk '/walltime/{print $2}' digi_REST.log_time` + + echo "$transporttime_S $digi_time_TPC $digi_time_TRD $digi_time_REST" +fi rm localhost* From 692bb808b46cafc39a86369ea3a6938952c8a112 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 25 Jun 2020 12:14:57 +0200 Subject: [PATCH 0003/1751] DPL: make MessageContext and related Services This introduces a few hook points which can be used by a Service to add functionality in the following moments: * Before the DataProcessor processing callback is invoked. * After the DataProcessor processing callback is invoked. * Before the End of Stream callback is invoked. * After the End of Stream callback is invoked. This means that we have enough configurability to move the various MessageContext, ArrowContext, RawBufferContext to be Services, with all the derived advantages: * No need to have the DataProcessing device know about the various messaging backends. * We can disable the Messaging backends if needed / improving memory usage. Moreover this also introduces a TracingInfrastructure service which removing such a responsibility from the DataProcessingDevice. --- Framework/Core/CMakeLists.txt | 3 +- .../include/Framework/CommonMessageBackends.h | 30 ++++ .../Core/include/Framework/CommonServices.h | 3 +- .../Core/include/Framework/ContextRegistry.h | 108 ------------- .../Core/include/Framework/DataAllocator.h | 38 ++--- .../include/Framework/DataProcessingDevice.h | 20 ++- .../Core/include/Framework/ServiceSpec.h | 46 +++++- Framework/Core/src/CommonMessageBackends.cxx | 145 ++++++++++++++++++ Framework/Core/src/CommonServices.cxx | 76 ++++++++- Framework/Core/src/DataAllocator.cxx | 52 +++---- Framework/Core/src/DataProcessingDevice.cxx | 107 +++++++------ Framework/Core/src/runDataProcessing.cxx | 2 + .../Core/test/benchmark_ContextRegistry.cxx | 58 ------- Framework/Core/test/test_ContextRegistry.cxx | 38 ----- Framework/Core/test/test_DataAllocator.cxx | 2 +- Framework/Core/test/test_TableBuilder.cxx | 4 +- 16 files changed, 404 insertions(+), 328 deletions(-) create mode 100644 Framework/Core/include/Framework/CommonMessageBackends.h delete mode 100644 Framework/Core/include/Framework/ContextRegistry.h create mode 100644 Framework/Core/src/CommonMessageBackends.cxx delete mode 100644 Framework/Core/test/benchmark_ContextRegistry.cxx delete mode 100644 Framework/Core/test/test_ContextRegistry.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 0c389d10daa68..bed0229de9cb0 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -31,6 +31,7 @@ o2_add_library(Framework src/ChannelSpecHelpers.cxx src/CommonDataProcessors.cxx src/CommonServices.cxx + src/CommonMessageBackends.cxx src/CompletionPolicy.cxx src/CompletionPolicyHelpers.cxx src/ComputingResourceHelpers.cxx @@ -149,7 +150,6 @@ foreach(t ComputingResourceHelpers ConfigParamStore ConfigParamRegistry - ContextRegistry DataDescriptorMatcher DataProcessorSpec DataRefUtils @@ -243,7 +243,6 @@ o2_add_test(unittest_SimpleOptionsRetriever NAME # benchmarks foreach(b - ContextRegistry DataDescriptorMatcher DataRelayer DeviceMetricsInfo diff --git a/Framework/Core/include/Framework/CommonMessageBackends.h b/Framework/Core/include/Framework/CommonMessageBackends.h new file mode 100644 index 0000000000000..0348807ea737c --- /dev/null +++ b/Framework/Core/include/Framework/CommonMessageBackends.h @@ -0,0 +1,30 @@ +// 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_COMMONMESSAGEBACKENDS_H_ +#define O2_FRAMEWORK_COMMONMESSAGEBACKENDS_H_ + +#include "Framework/ServiceSpec.h" +#include "Framework/TypeIdHelpers.h" + +namespace o2::framework +{ + +/// A few ServiceSpecs data sending backends +struct CommonMessageBackends { + // Create spec for backend used to send Arrow messages + static ServiceSpec arrowBackendSpec(); + static ServiceSpec fairMQBackendSpec(); + static ServiceSpec stringBackendSpec(); + static ServiceSpec rawBufferBackendSpec(); +}; + +} // namespace o2::framework + +#endif // O2_FRAMEWORK_COMMONMESSAGEBACKENDS_H_ diff --git a/Framework/Core/include/Framework/CommonServices.h b/Framework/Core/include/Framework/CommonServices.h index 25b33dd0dca32..f4aedfe6828c0 100644 --- a/Framework/Core/include/Framework/CommonServices.h +++ b/Framework/Core/include/Framework/CommonServices.h @@ -38,7 +38,7 @@ struct CommonServices { }; } - static ServiceConfigure noConfiguration() + static ServiceConfigureCallback noConfiguration() { return [](InitContext&, void* service) -> void* { return service; }; } @@ -54,6 +54,7 @@ struct CommonServices { static ServiceSpec callbacksSpec(); static ServiceSpec timesliceIndex(); static ServiceSpec dataRelayer(); + static ServiceSpec tracingSpec(); static std::vector defaultServices(); static std::vector requiredServices(); diff --git a/Framework/Core/include/Framework/ContextRegistry.h b/Framework/Core/include/Framework/ContextRegistry.h deleted file mode 100644 index a3e2e3ffd7898..0000000000000 --- a/Framework/Core/include/Framework/ContextRegistry.h +++ /dev/null @@ -1,108 +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. - -#ifndef FRAMEWORK_CONTEXTREGISTRY_H -#define FRAMEWORK_CONTEXTREGISTRY_H - -#include "Framework/TypeIdHelpers.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace o2 -{ -namespace framework -{ - -/// @class ContextRegistry -/// Instances are registered by pointer and are not owned by the registry -/// Decouples getting the various contextes from the actual type -/// of context, so that the DataAllocator does not need to know -/// about the various serialization methods. -/// -class ContextRegistry -{ - public: - /// The maximum distance a entry can be from the optimal slot. - constexpr static int MAX_DISTANCE = 8; - /// The number of slots in the hashmap. - constexpr static int MAX_CONTEXT = 32; - /// The mask to use to calculate the initial slot id. - constexpr static int MAX_CONTEXT_MASK = MAX_CONTEXT - 1; - - ContextRegistry(); - - template - ContextRegistry(Types*... instances) - { - mRegistryKey.fill(0); - mRegistryValue.fill(nullptr); - set(std::forward(instances)...); - } - - template - T* get() const - { - constexpr auto typeHash = TypeIdHelpers::uniqueId>(); - return reinterpret_cast(get(typeHash)); - } - - template - void set(T* instance, Types*... more) - { - set(instance); - set(std::forward(more)...); - } - - template - void set(T* instance) - { - static_assert(std::is_void::value == false, "can not register a void object"); - auto typeHash = TypeIdHelpers::uniqueId>(); - set(reinterpret_cast(instance), typeHash); - } - - void* get(uint32_t typeHash) const - { - auto id = typeHash & MAX_CONTEXT_MASK; - for (uint8_t i = 0; i < MAX_DISTANCE; ++i) { - if (mRegistryKey[i + id] == typeHash) { - return mRegistryValue[i + id]; - } - } - return nullptr; - } - - void set(void* instance, uint32_t typeHash) - { - auto id = typeHash & MAX_CONTEXT_MASK; - for (uint8_t i = 0; i < MAX_DISTANCE; ++i) { - if (mRegistryValue[i + id] == nullptr) { - mRegistryKey[i + id] = typeHash; - mRegistryValue[i + id] = instance; - return; - } - } - } - - private: - std::array mRegistryKey; - std::array mRegistryValue; -}; - -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_CONTEXTREGISTRY_H diff --git a/Framework/Core/include/Framework/DataAllocator.h b/Framework/Core/include/Framework/DataAllocator.h index 3f838289ce2a3..4881fc945e84c 100644 --- a/Framework/Core/include/Framework/DataAllocator.h +++ b/Framework/Core/include/Framework/DataAllocator.h @@ -10,7 +10,6 @@ #ifndef FRAMEWORK_DATAALLOCATOR_H #define FRAMEWORK_DATAALLOCATOR_H -#include "Framework/ContextRegistry.h" #include "Framework/MessageContext.h" #include "Framework/StringContext.h" #include "Framework/RawBufferContext.h" @@ -25,6 +24,7 @@ #include "Framework/Traits.h" #include "Framework/SerializationMethods.h" #include "Framework/CheckTypes.h" +#include "Framework/ServiceRegistry.h" #include "Headers/DataHeader.h" #include @@ -57,7 +57,7 @@ namespace o2 { namespace framework { -class ContextRegistry; +class ServiceRegistry; #define ERROR_STRING \ "data type T not supported by API, " \ @@ -81,7 +81,7 @@ class DataAllocator using SubSpecificationType = o2::header::DataHeader::SubSpecificationType; DataAllocator(TimingInfo* timingInfo, - ContextRegistry* contextes, + ServiceRegistry* contextes, const AllowedOutputRoutes& routes); DataChunk& newChunk(const Output&, size_t); @@ -104,20 +104,20 @@ class DataAllocator // has a root dictionary, so non-serialized transmission is preferred using ValueType = typename T::value_type; std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); // Note: initial payload size is 0 and will be set by the context before sending FairMQMessagePtr headerMessage = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodNone, 0); - return context->add>(std::move(headerMessage), channel, 0, std::forward(args)...).get(); + return context.add>(std::move(headerMessage), channel, 0, std::forward(args)...).get(); } else if constexpr (has_root_dictionary::value == true && is_messageable::value == false) { // Extended support for types implementing the Root ClassDef interface, both TObject // derived types and others std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); // Note: initial payload size is 0 and will be set by the context before sending FairMQMessagePtr headerMessage = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodROOT, 0); - return context->add>(std::move(headerMessage), channel, std::forward(args)...).get(); + return context.add>(std::move(headerMessage), channel, std::forward(args)...).get(); } else if constexpr (std::is_base_of_v) { std::string* s = new std::string(args...); adopt(spec, s); @@ -155,10 +155,10 @@ class DataAllocator auto [nElements] = std::make_tuple(args...); auto size = nElements * sizeof(T); std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); FairMQMessagePtr headerMessage = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodNone, size); - return context->add>(std::move(headerMessage), channel, 0, nElements).get(); + return context.add>(std::move(headerMessage), channel, 0, nElements).get(); } } else if constexpr (std::is_same_v>) { if constexpr (std::is_base_of_v) { @@ -234,7 +234,7 @@ class DataAllocator delete tmpPtr; }; - mContextRegistry->get()->addRawBuffer(std::move(header), std::move(payload), std::move(channel), std::move(lambdaSerialize), std::move(lambdaDestructor)); + mRegistry->get().addRawBuffer(std::move(header), std::move(payload), std::move(channel), std::move(lambdaSerialize), std::move(lambdaDestructor)); } /// Send a snapshot of an object, depending on the object type it is serialized before. @@ -259,7 +259,7 @@ class DataAllocator template void snapshot(const Output& spec, T const& object) { - auto proxy = mContextRegistry->get()->proxy(); + auto proxy = mRegistry->get().proxy(); FairMQMessagePtr payloadMessage; auto serializationType = o2::header::gSerializationMethodNone; if constexpr (is_messageable::value == true) { @@ -382,8 +382,8 @@ class DataAllocator o2::pmr::FairMQMemoryResource* getMemoryResource(const Output& spec) { std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); - auto context = mContextRegistry->get(); - return *context->proxy().getTransport(channel); + auto& context = mRegistry->get(); + return *context.proxy().getTransport(channel); } //make a stl (pmr) vector @@ -404,15 +404,15 @@ class DataAllocator // and put it in the queue to be sent at the end of the processing std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); - auto context = mContextRegistry->get(); - FairMQMessagePtr payloadMessage = o2::pmr::getMessage(std::forward(container), *context->proxy().getTransport(channel)); + auto& context = mRegistry->get(); + FairMQMessagePtr payloadMessage = o2::pmr::getMessage(std::forward(container), *context.proxy().getTransport(channel)); FairMQMessagePtr headerMessage = headerMessageFromOutput(spec, channel, // o2::header::gSerializationMethodNone, // payloadMessage->GetSize() // ); - context->add(std::move(headerMessage), std::move(payloadMessage), channel); + context.add(std::move(headerMessage), std::move(payloadMessage), channel); } /// snapshot object and route to output specified by OutputRef @@ -431,18 +431,18 @@ class DataAllocator o2::header::DataHeader* findMessageHeader(const Output& spec) { - return mContextRegistry->get()->findMessageHeader(spec); + return mRegistry->get().findMessageHeader(spec); } o2::header::DataHeader* findMessageHeader(OutputRef&& ref) { - return mContextRegistry->get()->findMessageHeader(getOutputByBind(std::move(ref))); + return mRegistry->get().findMessageHeader(getOutputByBind(std::move(ref))); } private: AllowedOutputRoutes mAllowedOutputRoutes; TimingInfo* mTimingInfo; - ContextRegistry* mContextRegistry; + ServiceRegistry* mRegistry; std::string const& matchDataHeader(const Output& spec, size_t timeframeId); FairMQMessagePtr headerMessageFromOutput(Output const& spec, // diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index 39b95ab01d0da..42de40d501aca 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -12,16 +12,11 @@ #include "Framework/AlgorithmSpec.h" #include "Framework/ConfigParamRegistry.h" -#include "Framework/ContextRegistry.h" #include "Framework/DataAllocator.h" #include "Framework/DataRelayer.h" #include "Framework/DeviceSpec.h" #include "Framework/DataProcessingStats.h" #include "Framework/ExpirationHandler.h" -#include "Framework/MessageContext.h" -#include "Framework/ArrowContext.h" -#include "Framework/StringContext.h" -#include "Framework/RawBufferContext.h" #include "Framework/ServiceRegistry.h" #include "Framework/InputRoute.h" #include "Framework/ForwardRoute.h" @@ -53,6 +48,7 @@ class DataProcessingDevice : public FairMQDevice void ResetTask() final; bool ConditionalRun() final; void SetErrorPolicy(enum TerminationPolicy policy) { mErrorPolicy = policy; } + void bindService(ServiceSpec const& spec, void* service); protected: bool doRun(); @@ -73,18 +69,20 @@ class DataProcessingDevice : public FairMQDevice std::unique_ptr mConfigRegistry; ServiceRegistry& mServiceRegistry; TimingInfo mTimingInfo; - MessageContext mFairMQContext; - StringContext mStringContext; - ArrowContext mDataFrameContext; - RawBufferContext mRawBufferContext; - ContextRegistry mContextRegistry; DataAllocator mAllocator; DataRelayer* mRelayer = nullptr; std::vector mExpirationHandlers; std::vector mCompleted; + /// Callbacks for services to be executed before every process method invokation + std::vector mPreProcessingHandles; + /// Callbacks for services to be executed after every process method invokation + std::vector mPostProcessingHandles; + /// Callbacks for services to be executed before every EOS user callback invokation + std::vector mPreEOSHandles; + /// Callbacks for services to be executed after every EOS user callback invokation + std::vector mPostEOSHandles; int mErrorCount; - int mProcessingCount; uint64_t mLastSlowMetricSentTimestamp = 0; /// The timestamp of the last time we sent slow metrics uint64_t mLastMetricFlushedTimestamp = 0; /// The timestamp of the last time we actually flushed metrics uint64_t mBeginIterationTimestamp = 0; /// The timestamp of when the current ConditionalRun was started diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index d1e0998bde052..2a7029a0a03bd 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -26,6 +26,8 @@ struct InitContext; struct DeviceSpec; struct ServiceRegistry; struct DeviceState; +struct ProcessingContext; +struct EndOfStreamContext; /// Handle to the service hash must be calculated /// using TypeIdHelper::uniqueId() so that @@ -41,7 +43,13 @@ using ServiceInit = std::function; +using ServiceConfigureCallback = std::function; + +/// A callback which is executed before each processing loop. +using ServiceProcessingCallback = std::function; + +/// A callback which is executed before the end of stream loop. +using ServiceEOSCallback = std::function; /// The kind of service we are asking for enum struct ServiceKind { @@ -53,14 +61,46 @@ enum struct ServiceKind { Stream }; -/// A declaration of a service to be used by the associated DataProcessor +/// A specification for a Service. +/// A Service is a utility class which does not perform +/// data processing itself, but it can be used by the data processor +/// to carry out common tasks (e.g. monitoring) or by the framework +/// to perform data processing related ancillary work (e.g. send +/// messages after a computation happended). struct ServiceSpec { + /// Name of the service std::string name; + /// Callback to initialise the service. ServiceInit init; - ServiceConfigure configure; + /// Callback to configure the service. + ServiceConfigureCallback configure; + /// Callback executed before actual processing happens. + ServiceProcessingCallback preProcessing = nullptr; + /// Callback executed once actual processing happened. + ServiceProcessingCallback postProcessing = nullptr; + /// Callback executed before the end of stream callback of the user happended + ServiceEOSCallback preEOS = nullptr; + /// Callback executed after the end of stream callback of the user happended + ServiceEOSCallback postEOS = nullptr; + /// Kind of service being specified. ServiceKind kind; }; +struct ServiceConfigureHandle { + ServiceConfigureCallback callback; + void* service; +}; + +struct ServiceProcessingHandle { + ServiceProcessingCallback callback; + void* service; +}; + +struct ServiceEOSHandle { + ServiceEOSCallback callback; + void* service; +}; + } // namespace o2::framework #endif // O2_FRAMEWORK_SERVICESPEC_H_ diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx new file mode 100644 index 0000000000000..b4870e5993f68 --- /dev/null +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -0,0 +1,145 @@ +// 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/CommonMessageBackends.h" +#include "Framework/MessageContext.h" +#include "Framework/ArrowContext.h" +#include "Framework/StringContext.h" +#include "Framework/RawBufferContext.h" +#include "Framework/DataProcessor.h" +#include "Framework/ServiceRegistry.h" +#include "Framework/RawDeviceService.h" +#include "Framework/DeviceSpec.h" +#include "Framework/EndOfStreamContext.h" + +#include + +namespace o2::framework +{ + +struct EndOfStreamContext; +struct ProcessingContext; + +namespace +{ +template +struct CommonMessageBackendsHelpers { + static ServiceInit createCallback() + { + return [](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions& options) { + auto& device = services.get(); + return ServiceHandle{TypeIdHelpers::uniqueId(), new T(FairMQDeviceProxy{device.device()})}; + }; + } + + static ServiceProcessingCallback sendCallback() + { + return [](ProcessingContext& ctx, void* service) { + T* context = reinterpret_cast(service); + auto& device = ctx.services().get(); + DataProcessor::doSend(*device.device(), *context); + }; + } + + static ServiceProcessingCallback clearContext() + { + return [](ProcessingContext&, void* service) { + T* context = reinterpret_cast(service); + context->clear(); + }; + } + + static ServiceEOSCallback clearContextEOS() + { + return [](EndOfStreamContext&, void* service) { + T* context = reinterpret_cast(service); + context->clear(); + }; + } + + static ServiceEOSCallback sendCallbackEOS() + { + return [](EndOfStreamContext& ctx, void* service) { + T* context = reinterpret_cast(service); + auto& device = ctx.services().get(); + DataProcessor::doSend(*device.device(), *context); + }; + } +}; +} // namespace + +o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() +{ + return ServiceSpec{"arrow-backend", + CommonMessageBackendsHelpers::createCallback(), + CommonServices::noConfiguration(), + CommonMessageBackendsHelpers::clearContext(), + CommonMessageBackendsHelpers::sendCallback(), + CommonMessageBackendsHelpers::clearContextEOS(), + CommonMessageBackendsHelpers::sendCallbackEOS(), + ServiceKind::Serial}; +} + +o2::framework::ServiceSpec CommonMessageBackends::fairMQBackendSpec() +{ + return ServiceSpec{"fairmq-backend", + [](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions&) -> ServiceHandle { + auto& device = services.get(); + auto context = new MessageContext(FairMQDeviceProxy{device.device()}); + auto& spec = services.get(); + + auto dispatcher = [&device](FairMQParts&& parts, std::string const& channel, unsigned int index) { + DataProcessor::doSend(*device.device(), std::move(parts), channel.c_str(), index); + }; + + auto matcher = [policy = spec.dispatchPolicy](o2::header::DataHeader const& header) { + if (policy.triggerMatcher == nullptr) { + return true; + } + return policy.triggerMatcher(Output{header}); + }; + + if (spec.dispatchPolicy.action == DispatchPolicy::DispatchOp::WhenReady) { + context->init(DispatchControl{dispatcher, matcher}); + } + return ServiceHandle{TypeIdHelpers::uniqueId(), context}; + }, + CommonServices::noConfiguration(), + CommonMessageBackendsHelpers::clearContext(), + CommonMessageBackendsHelpers::sendCallback(), + CommonMessageBackendsHelpers::clearContextEOS(), + CommonMessageBackendsHelpers::sendCallbackEOS(), + ServiceKind::Serial}; +} + +o2::framework::ServiceSpec CommonMessageBackends::stringBackendSpec() +{ + return ServiceSpec{"string-backend", + CommonMessageBackendsHelpers::createCallback(), + CommonServices::noConfiguration(), + CommonMessageBackendsHelpers::clearContext(), + CommonMessageBackendsHelpers::sendCallback(), + CommonMessageBackendsHelpers::clearContextEOS(), + CommonMessageBackendsHelpers::sendCallbackEOS(), + ServiceKind::Serial}; +} + +o2::framework::ServiceSpec CommonMessageBackends::rawBufferBackendSpec() +{ + return ServiceSpec{"raw-backend", + CommonMessageBackendsHelpers::createCallback(), + CommonServices::noConfiguration(), + CommonMessageBackendsHelpers::clearContext(), + CommonMessageBackendsHelpers::sendCallback(), + CommonMessageBackendsHelpers::clearContextEOS(), + CommonMessageBackendsHelpers::sendCallbackEOS(), + ServiceKind::Serial}; +} + +} // namespace o2::framework diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 6ba2a33344c9a..b925677063a01 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -16,6 +16,9 @@ #include "Framework/DeviceSpec.h" #include "Framework/LocalRootFileService.h" #include "Framework/DataRelayer.h" +#include "Framework/Signpost.h" +#include "Framework/CommonMessageBackends.h" +#include "../src/DataProcessingStatus.h" #include #include @@ -41,6 +44,10 @@ o2::framework::ServiceSpec CommonServices::monitoringSpec() return ServiceHandle{TypeIdHelpers::uniqueId(), service}; }, noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -49,6 +56,10 @@ o2::framework::ServiceSpec CommonServices::infologgerContextSpec() return ServiceSpec{"infologger-contex", simpleServiceInit(), noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -125,6 +136,10 @@ o2::framework::ServiceSpec CommonServices::infologgerSpec() return ServiceHandle{TypeIdHelpers::uniqueId(), infoLoggerService}; }, noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -141,6 +156,10 @@ o2::framework::ServiceSpec CommonServices::configurationSpec() ConfigurationFactory::getConfiguration(backend).release()}; }, noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -153,6 +172,10 @@ o2::framework::ServiceSpec CommonServices::controlSpec() new TextControlService(services, state)}; }, noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -162,6 +185,10 @@ o2::framework::ServiceSpec CommonServices::rootFileSpec() "localrootfile", simpleServiceInit(), noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -175,6 +202,10 @@ o2::framework::ServiceSpec CommonServices::parallelSpec() new ParallelContext(spec.rank, spec.nSlots)}; }, noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -184,6 +215,10 @@ o2::framework::ServiceSpec CommonServices::timesliceIndex() "timesliceindex", simpleServiceInit(), noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -193,6 +228,10 @@ o2::framework::ServiceSpec CommonServices::callbacksSpec() "callbacks", simpleServiceInit(), noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -209,6 +248,37 @@ o2::framework::ServiceSpec CommonServices::dataRelayer() services.get())}; }, noConfiguration(), + nullptr, + nullptr, + nullptr, + nullptr, + ServiceKind::Serial}; +} + +struct TracingInfrastructure { + int processingCount; +}; + +o2::framework::ServiceSpec CommonServices::tracingSpec() +{ + return ServiceSpec{ + "tracing", + [](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { + return ServiceHandle{TypeIdHelpers::uniqueId(), new TracingInfrastructure()}; + }, + noConfiguration(), + [](ProcessingContext&, void* service) { + TracingInfrastructure* t = reinterpret_cast(service); + StateMonitoring::moveTo(DataProcessingStatus::IN_DPL_USER_CALLBACK); + t->processingCount += 1; + }, + [](ProcessingContext&, void* service) { + TracingInfrastructure* t = reinterpret_cast(service); + StateMonitoring::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); + t->processingCount += 1; + }, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -224,7 +294,11 @@ std::vector CommonServices::defaultServices() rootFileSpec(), parallelSpec(), callbacksSpec(), - dataRelayer()}; + dataRelayer(), + CommonMessageBackends::fairMQBackendSpec(), + CommonMessageBackends::arrowBackendSpec(), + CommonMessageBackends::stringBackendSpec(), + CommonMessageBackends::rawBufferBackendSpec()}; } } // namespace o2::framework diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index d2086c8ac0529..f1885b7c898f3 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -26,9 +26,7 @@ #include -namespace o2 -{ -namespace framework +namespace o2::framework { using DataHeader = o2::header::DataHeader; @@ -36,11 +34,11 @@ using DataDescription = o2::header::DataDescription; using DataProcessingHeader = o2::framework::DataProcessingHeader; DataAllocator::DataAllocator(TimingInfo* timingInfo, - ContextRegistry* contextRegistry, + ServiceRegistry* contextRegistry, const AllowedOutputRoutes& routes) : mAllowedOutputRoutes{routes}, mTimingInfo{timingInfo}, - mContextRegistry{contextRegistry} + mRegistry{contextRegistry} { } @@ -63,13 +61,13 @@ std::string const& DataAllocator::matchDataHeader(const Output& spec, size_t tim DataChunk& DataAllocator::newChunk(const Output& spec, size_t size) { std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); FairMQMessagePtr headerMessage = headerMessageFromOutput(spec, channel, // o2::header::gSerializationMethodNone, // size // ); - auto& co = context->add>(std::move(headerMessage), channel, 0, size); + auto& co = context.add>(std::move(headerMessage), channel, 0, size); return co; } @@ -85,8 +83,8 @@ void DataAllocator::adoptChunk(const Output& spec, char* buffer, size_t size, fa ); // FIXME: how do we want to use subchannels? time based parallelism? - auto context = mContextRegistry->get(); - context->add(std::move(headerMessage), channel, 0, buffer, size, freefn, hint); + auto& context = mRegistry->get(); + context.add(std::move(headerMessage), channel, 0, buffer, size, freefn, hint); } FairMQMessagePtr DataAllocator::headerMessageFromOutput(Output const& spec, // @@ -102,9 +100,9 @@ FairMQMessagePtr DataAllocator::headerMessageFromOutput(Output const& spec, dh.payloadSerializationMethod = method; DataProcessingHeader dph{mTimingInfo->timeslice, 1}; - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); - auto channelAlloc = o2::pmr::getTransportAllocator(context->proxy().getTransport(channel, 0)); + auto channelAlloc = o2::pmr::getTransportAllocator(context.proxy().getTransport(channel, 0)); return o2::pmr::getMessage(o2::header::Stack{channelAlloc, dh, dph, spec.metaHeader}); } @@ -119,11 +117,11 @@ void DataAllocator::addPartToContext(FairMQMessagePtr&& payloadMessage, const Ou const DataHeader* cdh = o2::header::get(headerMessage->GetData()); DataHeader* dh = const_cast(cdh); dh->payloadSize = payloadMessage->GetSize(); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); // make_scoped creates the context object inside of a scope handler, since it goes out of // scope immediately, the created object is scheduled and can be directly sent if the context // is configured with the dispatcher callback - context->make_scoped(std::move(headerMessage), std::move(payloadMessage), channel); + context.make_scoped(std::move(headerMessage), std::move(payloadMessage), channel); } void DataAllocator::adopt(const Output& spec, std::string* ptr) @@ -133,7 +131,7 @@ void DataAllocator::adopt(const Output& spec, std::string* ptr) // the correct payload size is set later when sending the // StringContext, see DataProcessor::doSend auto header = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodNone, 0); - mContextRegistry->get()->addString(std::move(header), std::move(payload), channel); + mRegistry->get().addString(std::move(header), std::move(payload), channel); assert(payload.get() == nullptr); } @@ -141,9 +139,9 @@ void DataAllocator::adopt(const Output& spec, TableBuilder* tb) { std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); auto header = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodArrow, 0); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); - auto creator = [device = context->proxy().getDevice()](size_t s) -> std::unique_ptr { return device->NewMessage(s); }; + auto creator = [device = context.proxy().getDevice()](size_t s) -> std::unique_ptr { return device->NewMessage(s); }; auto buffer = std::make_shared(creator); /// To finalise this we write the table to the buffer. @@ -161,8 +159,7 @@ void DataAllocator::adopt(const Output& spec, TableBuilder* tb) } }; - assert(context); - context->addBuffer(std::move(header), buffer, std::move(finalizer), channel); + context.addBuffer(std::move(header), buffer, std::move(finalizer), channel); } void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) @@ -171,9 +168,9 @@ void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) LOG(INFO) << "DataAllocator::adopt channel " << channel.c_str(); auto header = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodArrow, 0); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); - auto creator = [device = context->proxy().getDevice()](size_t s) -> std::unique_ptr { + auto creator = [device = context.proxy().getDevice()](size_t s) -> std::unique_ptr { return device->NewMessage(s); }; auto buffer = std::make_shared(creator); @@ -197,17 +194,16 @@ void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) } }; - assert(context); - context->addBuffer(std::move(header), buffer, std::move(finalizer), channel); + context.addBuffer(std::move(header), buffer, std::move(finalizer), channel); } void DataAllocator::adopt(const Output& spec, std::shared_ptr ptr) { std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); auto header = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodArrow, 0); - auto context = mContextRegistry->get(); + auto& context = mRegistry->get(); - auto creator = [device = context->proxy().getDevice()](size_t s) -> std::unique_ptr { + auto creator = [device = context.proxy().getDevice()](size_t s) -> std::unique_ptr { return device->NewMessage(s); }; auto buffer = std::make_shared(creator); @@ -221,14 +217,13 @@ void DataAllocator::adopt(const Output& spec, std::shared_ptr ptr) } }; - assert(context); - context->addBuffer(std::move(header), buffer, std::move(writer), channel); + context.addBuffer(std::move(header), buffer, std::move(writer), channel); } void DataAllocator::snapshot(const Output& spec, const char* payload, size_t payloadSize, o2::header::SerializationMethod serializationMethod) { - auto proxy = mContextRegistry->get()->proxy(); + auto& proxy = mRegistry->get().proxy(); FairMQMessagePtr payloadMessage(proxy.createMessage(payloadSize)); memcpy(payloadMessage->GetData(), payload, payloadSize); @@ -261,5 +256,4 @@ bool DataAllocator::isAllowed(Output const& query) return false; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 16fc85850e4f2..541fd4286ce19 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -82,31 +82,13 @@ DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegist mStatelessProcess{spec.algorithm.onProcess}, mError{spec.algorithm.onError}, mConfigRegistry{nullptr}, - mFairMQContext{FairMQDeviceProxy{this}}, - mStringContext{FairMQDeviceProxy{this}}, - mDataFrameContext{FairMQDeviceProxy{this}}, - mRawBufferContext{FairMQDeviceProxy{this}}, - mContextRegistry{&mFairMQContext, &mStringContext, &mDataFrameContext, &mRawBufferContext}, - mAllocator{&mTimingInfo, &mContextRegistry, spec.outputs}, + mAllocator{&mTimingInfo, ®istry, spec.outputs}, mServiceRegistry{registry}, - mErrorCount{0}, - mProcessingCount{0} + mErrorCount{0} { StateMonitoring::start(); - auto dispatcher = [this](FairMQParts&& parts, std::string const& channel, unsigned int index) { - DataProcessor::doSend(*this, std::move(parts), channel.c_str(), index); - }; - auto matcher = [policy = spec.dispatchPolicy](o2::header::DataHeader const& header) { - if (policy.triggerMatcher == nullptr) { - return true; - } - return policy.triggerMatcher(Output{header}); - }; - - if (spec.dispatchPolicy.action == DispatchPolicy::DispatchOp::WhenReady) { - mFairMQContext.init(DispatchControl{dispatcher, matcher}); - } + /// FIXME: move erro handling to a service? if (mError != nullptr) { mErrorHandling = [& errorCallback = mError, &serviceRegistry = mServiceRegistry](std::exception& e, InputRecord& record) { @@ -519,16 +501,14 @@ bool DataProcessingDevice::doRun() } sendRelayerMetrics(); flushMetrics(); - mContextRegistry.get()->clear(); - mContextRegistry.get()->clear(); - mContextRegistry.get()->clear(); - mContextRegistry.get()->clear(); EndOfStreamContext eosContext{mServiceRegistry, mAllocator}; + for (auto& eosHandle : mPreEOSHandles) { + eosHandle.callback(eosContext, eosHandle.service); + } mServiceRegistry.get()(CallbackService::Id::EndOfStream, eosContext); - DataProcessor::doSend(*this, *mContextRegistry.get()); - DataProcessor::doSend(*this, *mContextRegistry.get()); - DataProcessor::doSend(*this, *mContextRegistry.get()); - DataProcessor::doSend(*this, *mContextRegistry.get()); + for (auto& eosHandle : mPostEOSHandles) { + eosHandle.callback(eosContext, eosHandle.service); + } for (auto& channel : mSpec.outputChannels) { DataProcessingHelpers::sendEndOfStream(*this, channel); } @@ -671,22 +651,17 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector currentSetOfInputs; auto& allocator = mAllocator; - auto& context = *mContextRegistry.get(); auto& device = *this; auto& errorCallback = mError; auto& errorCount = mErrorCount; auto& forwards = mSpec.forwards; auto& inputsSchema = mSpec.inputs; - auto& processingCount = mProcessingCount; - auto& rdfContext = *mContextRegistry.get(); auto& relayer = *mRelayer; auto& serviceRegistry = mServiceRegistry; auto& statefulProcess = mStatefulProcess; auto& statelessProcess = mStatelessProcess; - auto& stringContext = *mContextRegistry.get(); auto& timingInfo = mTimingInfo; auto& timesliceIndex = mServiceRegistry.get(); - auto& rawContext = *mContextRegistry.get(); // These duplicate references are created so that each function // does not need to know about the whole class state, but I can @@ -745,40 +720,34 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector::moveTo(DataProcessingStatus::IN_DPL_USER_CALLBACK); statefulProcess(processContext); - StateMonitoring::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); - processingCount++; } if (statelessProcess) { - ProcessingContext processContext{record, serviceRegistry, allocator}; - StateMonitoring::moveTo(DataProcessingStatus::IN_DPL_USER_CALLBACK); statelessProcess(processContext); - StateMonitoring::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); - processingCount++; } - DataProcessor::doSend(device, context); - DataProcessor::doSend(device, stringContext); - DataProcessor::doSend(device, rdfContext); - DataProcessor::doSend(device, rawContext); + for (auto& handle : postHandles) { + handle.callback(processContext, handle.service); + } }; // I need a preparation step which gets the current timeslice id and // propagates it to the various contextes (i.e. the actual entities which // create messages) because the messages need to have the timeslice id into // it. - auto prepareAllocatorForCurrentTimeSlice = [&timingInfo, &stringContext, &rdfContext, &rawContext, &context, &relayer, ×liceIndex](TimesliceSlot i) { + auto prepareAllocatorForCurrentTimeSlice = [&timingInfo, &relayer, ×liceIndex](TimesliceSlot i) { auto timeslice = timesliceIndex.getTimesliceForSlot(i); timingInfo.timeslice = timeslice.value; - context.clear(); - stringContext.clear(); - rdfContext.clear(); - rawContext.clear(); }; // When processing them, timers will have to be cleaned up @@ -918,6 +887,10 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector().send(Metric{mErrorCount, "errors"}.addTag(Key::Subsystem, Value::DPL)); } +void DataProcessingDevice::bindService(ServiceSpec const& spec, void* service) +{ + if (spec.preProcessing) { + mPreProcessingHandles.push_back(ServiceProcessingHandle{spec.preProcessing, service}); + } + if (spec.postProcessing) { + mPostProcessingHandles.push_back(ServiceProcessingHandle{spec.postProcessing, service}); + } + if (spec.preEOS) { + mPreEOSHandles.push_back(ServiceEOSHandle{spec.preEOS, service}); + } + if (spec.postEOS) { + mPostEOSHandles.push_back(ServiceEOSHandle{spec.postEOS, service}); + } +} + } // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 055b9a4a41bb2..1ca888af2292e 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -672,11 +672,13 @@ int doChild(int argc, char** argv, const o2::framework::DeviceSpec& spec, Termin serviceRegistry.get().setDevice(device.get()); r.fDevice = std::move(device); fair::Logger::SetConsoleColor(false); + /// Create all the requested services and initialise them for (auto& service : spec.services) { LOG(info) << "Initialising service " << service.name; auto handle = service.init(serviceRegistry, *deviceState.get(), r.fConfig); serviceRegistry.registerService(handle.hash, handle.instance); + dynamic_cast(r.fDevice.get())->bindService(service, handle.instance); } }; diff --git a/Framework/Core/test/benchmark_ContextRegistry.cxx b/Framework/Core/test/benchmark_ContextRegistry.cxx deleted file mode 100644 index bdbfbf0185ead..0000000000000 --- a/Framework/Core/test/benchmark_ContextRegistry.cxx +++ /dev/null @@ -1,58 +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. -#include - -#include "Framework/ContextRegistry.h" -#include "Framework/ArrowContext.h" -#include "Framework/StringContext.h" -#include "Framework/RawBufferContext.h" -#include "Framework/MessageContext.h" -#include - -using namespace o2::framework; - -// A simple test where an input is provided -// and the subsequent InputRecord is immediately requested. -static void BM_ContextRegistrySingleGet(benchmark::State& state) -{ - FairMQDeviceProxy proxy(nullptr); - ArrowContext c0(proxy); - StringContext c1(proxy); - RawBufferContext c2(proxy); - MessageContext c3(proxy); - ContextRegistry registry({&c0, &c1, &c2, &c3}); - - for (auto _ : state) { - registry.get(); - } -} - -BENCHMARK(BM_ContextRegistrySingleGet); - -// A simple test where an input is provided -// and the subsequent InputRecord is immediately requested. -static void BM_ContextRegistryMultiGet(benchmark::State& state) -{ - FairMQDeviceProxy proxy(nullptr); - ArrowContext c0(proxy); - StringContext c1(proxy); - RawBufferContext c2(proxy); - MessageContext c3(proxy); - ContextRegistry registry({&c0, &c1, &c2, &c3}); - - for (auto _ : state) { - registry.get(); - registry.get(); - } -} - -BENCHMARK(BM_ContextRegistryMultiGet); - -BENCHMARK_MAIN(); diff --git a/Framework/Core/test/test_ContextRegistry.cxx b/Framework/Core/test/test_ContextRegistry.cxx deleted file mode 100644 index fa521f08adb46..0000000000000 --- a/Framework/Core/test/test_ContextRegistry.cxx +++ /dev/null @@ -1,38 +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. - -#define BOOST_TEST_MODULE Test Framework ContextRegistry -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK - -#include -#include "Framework/ContextRegistry.h" -#include "Framework/ArrowContext.h" -#include "Framework/StringContext.h" -#include "Framework/RawBufferContext.h" -#include "Framework/MessageContext.h" -#include - -using namespace o2::framework; - -BOOST_AUTO_TEST_CASE(TestContextRegistry) -{ - FairMQDeviceProxy proxy(nullptr); - ArrowContext c0(proxy); - StringContext c1(proxy); - RawBufferContext c2(proxy); - MessageContext c3(proxy); - ContextRegistry registry({&c0, &c1, &c2, &c3}); - - BOOST_REQUIRE_EQUAL(&c0, registry.get()); - BOOST_REQUIRE_EQUAL(&c1, registry.get()); - BOOST_REQUIRE_EQUAL(&c2, registry.get()); - BOOST_REQUIRE_EQUAL(&c3, registry.get()); -} diff --git a/Framework/Core/test/test_DataAllocator.cxx b/Framework/Core/test/test_DataAllocator.cxx index fde705c275dac..448ab70bd4626 100644 --- a/Framework/Core/test/test_DataAllocator.cxx +++ b/Framework/Core/test/test_DataAllocator.cxx @@ -42,7 +42,7 @@ using namespace o2::framework; void doTypeChecks() { TimingInfo* timingInfo = nullptr; - ContextRegistry* contextes = nullptr; + ServiceRegistry* contextes = nullptr; std::vector routes; DataAllocator allocator(timingInfo, contextes, routes); const Output output{"TST", "DUMMY", 0, Lifetime::Timeframe}; diff --git a/Framework/Core/test/test_TableBuilder.cxx b/Framework/Core/test/test_TableBuilder.cxx index 9bee17e6f11ed..018847df84641 100644 --- a/Framework/Core/test/test_TableBuilder.cxx +++ b/Framework/Core/test/test_TableBuilder.cxx @@ -345,10 +345,8 @@ BOOST_AUTO_TEST_CASE(TestSoAIntegration) BOOST_AUTO_TEST_CASE(TestDataAllocatorReturnType) { - TimingInfo* timingInfo = nullptr; - ContextRegistry* contextes = nullptr; std::vector routes; - DataAllocator allocator(timingInfo, contextes, routes); + DataAllocator allocator(nullptr, nullptr, routes); const Output output{"TST", "DUMMY", 0, Lifetime::Timeframe}; // we require reference to object owned by allocator context static_assert(std::is_lvalue_reference(output))>::value); From 1fd4163a0a34c9155f695960784a6b7e0eeb496d Mon Sep 17 00:00:00 2001 From: noferini Date: Fri, 26 Jun 2020 09:17:22 +0200 Subject: [PATCH 0004/1751] add external options (sim_challenge) for manage multi-threads --- prodtests/sim_challenge.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 8e4369f21e8da..1b990a457378b 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -124,6 +124,11 @@ engine="TGeant3" # options to pass to every workflow gloOpt=" -b --run " +# option to set the number of sim workers +simWorker="" + +# option to set the number of tpc-lanes +tpcLanes="" Usage() { @@ -139,6 +144,8 @@ while [ $# -gt 0 ] ; do -r) intRate=$2; shift 2 ;; -e) engine=$2; shift 2 ;; -f) fromstage=$2; shift 2 ;; + -j) simWorker="-j $2"; shift 2 ;; + -l) tpcLanes="--tpc-lanes $2"; shift 2 ;; -h) Usage ;; *) echo "Wrong input"; Usage; esac @@ -180,7 +187,7 @@ fi if [ "$dosim" == "1" ]; then #--------------------------------------------------- echo "Running simulation for $nev $collSyst events with $gener generator and engine $engine" - taskwrapper sim.log o2-sim -n"$nev" --configKeyValue "Diamond.width[2]=6." -g "$gener" -e "$engine" + taskwrapper sim.log o2-sim -n"$nev" --configKeyValue "Diamond.width[2]=6." -g "$gener" -e "$engine" $simWorker ##------ extract number of hits root -q -b -l ${O2_ROOT}/share/macro/analyzeHits.C > hitstats.log @@ -189,7 +196,7 @@ fi if [ "$dodigi" == "1" ]; then echo "Running digitization for $intRate kHz interaction rate" intRate=$((1000*(intRate))); - taskwrapper digi.log o2-sim-digitizer-workflow $gloOpt --interactionRate $intRate + taskwrapper digi.log o2-sim-digitizer-workflow $gloOpt --interactionRate $intRate $tpcLanes echo "Return status of digitization: $?" # existing checks #root -b -q O2/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C+ From 2fde1c2afe387843a583eed7ffd69d6218da2bbe Mon Sep 17 00:00:00 2001 From: stheckel <50136746+stheckel@users.noreply.github.com> Date: Wed, 1 Jul 2020 20:41:00 +0200 Subject: [PATCH 0005/1751] TPC QC tasks on Tracks and PID: fix phi range (#3920) * TPC QC tasks on Tracks and PID: fix phi range o Phi range has been changed from -pi to +pi now to 0 to 2pi o This is changed here in the TPC O2 QC tasks o In addition, the hard coded cut on TPC clusters in the tracks task is switched off for the tests during TPC pre-commissioning * TPC QC tasks: clang format --- Detectors/TPC/qc/src/PID.cxx | 14 +++++++------- Detectors/TPC/qc/src/Tracks.cxx | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Detectors/TPC/qc/src/PID.cxx b/Detectors/TPC/qc/src/PID.cxx index 029280b49bc4f..c5ef72a00a7fa 100644 --- a/Detectors/TPC/qc/src/PID.cxx +++ b/Detectors/TPC/qc/src/PID.cxx @@ -33,20 +33,20 @@ void PID::initializeHistograms() mHist1D.emplace_back("hNClusters", "; # of clusters; counts", 160, 0, 1600); //| mHist1D[0] mHist1D.emplace_back("hdEdxTot", "; dEdxTot (a.u.); counts", 200, 0, 200); //| mHist1D[1] mHist1D.emplace_back("hdEdxMax", "; dEdxMax (a.u.); counts", 200, 0, 200); //| mHist1D[2] - mHist1D.emplace_back("hPhi", "; #phi (rad); counts", 180, -M_PI, M_PI); //| mHist1D[3] + mHist1D.emplace_back("hPhi", "; #phi (rad); counts", 180, 0., 2 * M_PI); //| mHist1D[3] mHist1D.emplace_back("hTgl", "; tan#lambda; counts", 60, -2, 2); //| mHist1D[4] mHist1D.emplace_back("hSnp", "; sin p; counts", 60, -2, 2); //| mHist1D[5] - mHist2D.emplace_back("hdEdxVsPhi", "dEdx (a.u.) vs #phi (rad); #phi (rad); dEdx (a.u.)", 180, -M_PI, M_PI, 300, 0, 300); //| mHist2D[0] - mHist2D.emplace_back("hdEdxVsTgl", "dEdx (a.u.) vs tan#lambda; tan#lambda; dEdx (a.u.)", 60, -2, 2, 300, 0, 300); //| mHist2D[1] - mHist2D.emplace_back("hdEdxVsncls", "dEdx (a.u.) vs ncls; ncls; dEdx (a.u.)", 80, 0, 160, 300, 0, 300); //| mHist2D[2] + mHist2D.emplace_back("hdEdxVsPhi", "dEdx (a.u.) vs #phi (rad); #phi (rad); dEdx (a.u.)", 180, 0., 2 * M_PI, 300, 0, 300); //| mHist2D[0] + mHist2D.emplace_back("hdEdxVsTgl", "dEdx (a.u.) vs tan#lambda; tan#lambda; dEdx (a.u.)", 60, -2, 2, 300, 0, 300); //| mHist2D[1] + mHist2D.emplace_back("hdEdxVsncls", "dEdx (a.u.) vs ncls; ncls; dEdx (a.u.)", 80, 0, 160, 300, 0, 300); //| mHist2D[2] const auto logPtBinning = helpers::makeLogBinning(30, 0.1, 10); if (logPtBinning.size() > 0) { mHist2D.emplace_back("hdEdxVsp", "dEdx (a.u.) vs p (G#it{e}V/#it{c}); p (G#it{e}V/#it{c}); dEdx (a.u.)", logPtBinning.size() - 1, logPtBinning.data(), 300, 0, 300); //| mHist2D[3] } - //mHist2D.emplace_back("hdedxVsphiMIPA","; #phi (rad); dedx (a.u.)", 180,-M_PI,M_PI,25,35,60); //| mHist2D[4] - //mHist2D.emplace_back("hdedxVsphiMIPC","; #phi (rad); dedx (a.u.)", 180,-M_PI,M_PI,25,35,60); //| mHist2D[5] + //mHist2D.emplace_back("hdedxVsphiMIPA","; #phi (rad); dedx (a.u.)", 180,0.,2*M_PI,25,35,60); //| mHist2D[4] + //mHist2D.emplace_back("hdedxVsphiMIPC","; #phi (rad); dedx (a.u.)", 180,0.,2*M_PI,25,35,60); //| mHist2D[5] } //______________________________________________________________________________ @@ -99,4 +99,4 @@ void PID::dumpToFile(const std::string filename) f->WriteObject(&hist, hist.GetName()); } f->Close(); -} \ No newline at end of file +} diff --git a/Detectors/TPC/qc/src/Tracks.cxx b/Detectors/TPC/qc/src/Tracks.cxx index 82b7a07f1642a..6b24975cd88a3 100644 --- a/Detectors/TPC/qc/src/Tracks.cxx +++ b/Detectors/TPC/qc/src/Tracks.cxx @@ -30,18 +30,18 @@ void Tracks::initializeHistograms() mHist1D.emplace_back("hNClustersBeforeCuts", "Number of clusters before cuts;# TPC clusters", 160, -0.5, 159.5); mHist1D.emplace_back("hNClustersAfterCuts", "Number of clusters after cuts;# TPC clusters", 160, -0.5, 159.5); mHist1D.emplace_back("hEta", "Pseudorapidity;eta", 400, -2., 2.); - mHist1D.emplace_back("hPhiAside", "Azimuthal angle, A side;phi", 360, -M_PI, M_PI); - mHist1D.emplace_back("hPhiCside", "Azimuthal angle, C side;phi", 360, -M_PI, M_PI); + mHist1D.emplace_back("hPhiAside", "Azimuthal angle, A side;phi", 360, 0., 2 * M_PI); + mHist1D.emplace_back("hPhiCside", "Azimuthal angle, C side;phi", 360, 0., 2 * M_PI); mHist1D.emplace_back("hPt", "Transverse momentum;p_T", 200, 0., 10.); mHist1D.emplace_back("hSign", "Sign of electric charge;charge sign", 3, -1.5, 1.5); mHist2D.emplace_back("h2DNClustersEta", "Number of clusters vs. eta;eta;# TPC clusters", 400, -2., 2., 160, -0.5, 159.5); - mHist2D.emplace_back("h2DNClustersPhiAside", "Number of clusters vs. phi, A side ;phi;# TPC clusters", 360, -M_PI, M_PI, 160, -0.5, 159.5); - mHist2D.emplace_back("h2DNClustersPhiCside", "Number of clusters vs. phi, C side ;phi;# TPC clusters", 360, -M_PI, M_PI, 160, -0.5, 159.5); + mHist2D.emplace_back("h2DNClustersPhiAside", "Number of clusters vs. phi, A side ;phi;# TPC clusters", 360, 0., 2 * M_PI, 160, -0.5, 159.5); + mHist2D.emplace_back("h2DNClustersPhiCside", "Number of clusters vs. phi, C side ;phi;# TPC clusters", 360, 0., 2 * M_PI, 160, -0.5, 159.5); mHist2D.emplace_back("h2DNClustersPt", "Number of clusters vs. p_T;p_T;# TPC clusters", 200, 0., 10., 160, -0.5, 159.5); - mHist2D.emplace_back("h2DEtaPhi", "Tracks in eta vs. phi;phi;eta", 360, -M_PI, M_PI, 400, -2., 2.); - mHist2D.emplace_back("h2DEtaPhiNeg", "Negative tracks in eta vs. phi;phi;eta", 360, -M_PI, M_PI, 400, -2., 2.); - mHist2D.emplace_back("h2DEtaPhiPos", "Positive tracks in eta vs. phi;phi;eta", 360, -M_PI, M_PI, 400, -2., 2.); + mHist2D.emplace_back("h2DEtaPhi", "Tracks in eta vs. phi;phi;eta", 360, 0., 2 * M_PI, 400, -2., 2.); + mHist2D.emplace_back("h2DEtaPhiNeg", "Negative tracks in eta vs. phi;phi;eta", 360, 0., 2 * M_PI, 400, -2., 2.); + mHist2D.emplace_back("h2DEtaPhiPos", "Positive tracks in eta vs. phi;phi;eta", 360, 0., 2 * M_PI, 400, -2., 2.); } //______________________________________________________________________________ @@ -70,9 +70,9 @@ bool Tracks::processTrack(const o2::tpc::TrackTPC& track) // ===| cuts |=== // hard coded cuts. Should be more configural in future - if (nCls < 20) { - return false; - } + //if (nCls < 20) { + // return false; + //} // ===| 1D histogram filling |=== mHist1D[1].Fill(nCls); From c935968123a3aecdc6eb8578540a7a4fbc11bc40 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 1 Jul 2020 11:31:06 +0200 Subject: [PATCH 0006/1751] DPL Driver: drop unneeded field More cleanups from moving to libuv. --- Framework/Core/src/DriverInfo.h | 2 -- Framework/Core/src/runDataProcessing.cxx | 23 ++++++++--------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Framework/Core/src/DriverInfo.h b/Framework/Core/src/DriverInfo.h index 2c3f8083ce5b2..15c6aed26d091 100644 --- a/Framework/Core/src/DriverInfo.h +++ b/Framework/Core/src/DriverInfo.h @@ -74,8 +74,6 @@ enum struct DriverState { struct DriverInfo { /// Stack with the states to be processed next. std::vector states; - /// The first unused file descriptor - int maxFd; // Signal handler for children struct sigaction sa_handle_child; diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 1ca888af2292e..58cbd621bb4a6 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -241,11 +241,9 @@ int calculateExitCode(std::vector& infos) return exitCode; } -int createPipes(int maxFd, int* pipes) +void createPipes(int* pipes) { auto p = pipe(pipes); - maxFd = maxFd > pipes[0] ? maxFd : pipes[0]; - maxFd = maxFd > pipes[1] ? maxFd : pipes[1]; if (p == -1) { std::cerr << "Unable to create PIPE: "; @@ -265,7 +263,6 @@ int createPipes(int maxFd, int* pipes) // Kill immediately both the parent and all the children kill(-1 * getpid(), SIGKILL); } - return maxFd; } // We don't do anything in the signal handler but @@ -302,8 +299,7 @@ void spawnRemoteDevice(std::string const& forwardedStdin, DeviceSpec const& spec, DeviceControl& control, DeviceExecution& execution, - std::vector& deviceInfos, - int& maxFd) + std::vector& deviceInfos) { LOG(INFO) << "Starting " << spec.id << " as remote device"; DeviceInfo info; @@ -353,16 +349,16 @@ void spawnDevice(std::string const& forwardedStdin, DeviceControl& control, DeviceExecution& execution, std::vector& deviceInfos, - int& maxFd, uv_loop_t* loop, + uv_loop_t* loop, std::vector handles) { int childstdin[2]; int childstdout[2]; int childstderr[2]; - maxFd = createPipes(maxFd, childstdin); - maxFd = createPipes(maxFd, childstdout); - maxFd = createPipes(maxFd, childstderr); + createPipes(childstdin); + createPipes(childstdout); + createPipes(childstderr); // If we have a framework id, it means we have already been respawned // and that we are in a child. If not, we need to fork and re-exec, adding @@ -966,15 +962,13 @@ int runStateMachine(DataProcessorSpecs const& workflow, for (size_t di = 0; di < deviceSpecs.size(); ++di) { if (deviceSpecs[di].resource.hostname != driverInfo.deployHostname) { spawnRemoteDevice(forwardedStdin.str(), - deviceSpecs[di], controls[di], deviceExecutions[di], infos, - driverInfo.maxFd); + deviceSpecs[di], controls[di], deviceExecutions[di], infos); } else { spawnDevice(forwardedStdin.str(), deviceSpecs[di], controls[di], deviceExecutions[di], infos, - driverInfo.maxFd, loop, pollHandles); + loop, pollHandles); } } - driverInfo.maxFd += 1; assert(infos.empty() == false); LOG(INFO) << "Redeployment of configuration done."; } break; @@ -1593,7 +1587,6 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, initialiseDriverControl(varmap, driverControl); DriverInfo driverInfo; - driverInfo.maxFd = 0; driverInfo.states.reserve(10); driverInfo.sigintRequested = false; driverInfo.sigchldRequested = false; From 9355dc740facaa36f7e00803a00ccf9f853c1448 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 1 Jul 2020 10:41:57 +0200 Subject: [PATCH 0007/1751] DPL: make sure we call TGrid::Connect() when needed If we spot that at least one of the AOD files starts with alien://, we force invoke TGrid::Connect(). --- Framework/Core/src/AODReaderHelpers.cxx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 278b0b818bf36..cfc4afe7cc267 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -230,11 +231,35 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector reques }}; } +namespace +{ +void checkAndEnableAlien(std::string const& filename) +{ + // Check if filename is an alien file or if it contains alien files, + // TGrid::Connect if that is the case. + if (filename.rfind("alien://", 0) == 0) { + LOG(debug) << "AliEn file requested. Enabling support."; + TGrid::Connect("alien://"); + } + if (filename.rfind("@", 0) == 0) { + std::ifstream filenames(filename); + for (std::string line; std::getline(filenames, line);) { + if (line.rfind("alien://", 0) == 0) { + LOG(debug) << "AliEn file requested. Enabling support."; + TGrid::Connect("alien://"); + break; + } + } + } +} +} // namespace + AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() { auto callback = AlgorithmSpec{adaptStateful([](ConfigParamRegistry const& options, DeviceSpec const& spec) { auto filename = options.get("aod-file"); + checkAndEnableAlien(filename); // create a DataInputDirector auto didir = std::make_shared(filename); From 202c07b1980e49961e3631dcac1d04330f0c6bcf Mon Sep 17 00:00:00 2001 From: Paul Buehler Date: Wed, 1 Jul 2020 22:07:46 +0200 Subject: [PATCH 0008/1751] run time watchdog (#3927) . stopd processing at time frame boundaries if expected run time for next time frame is expected to exceed a given run time limit . run time limit is given in seconds by command line option time-limit --- .../Core/include/Framework/AODReaderHelpers.h | 44 +++++++++++++++++++ Framework/Core/src/AODReaderHelpers.cxx | 19 ++++++-- Framework/Core/src/WorkflowHelpers.cxx | 1 + 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/Framework/Core/include/Framework/AODReaderHelpers.h b/Framework/Core/include/Framework/AODReaderHelpers.h index 812e22beb669c..ef0460febe28c 100644 --- a/Framework/Core/include/Framework/AODReaderHelpers.h +++ b/Framework/Core/include/Framework/AODReaderHelpers.h @@ -13,6 +13,7 @@ #include "Framework/TableBuilder.h" #include "Framework/AlgorithmSpec.h" +#include namespace o2 { @@ -21,6 +22,49 @@ namespace framework namespace readers { +struct RuntimeWatchdog { + int numberTimeFrames; + uint64_t startTime; + uint64_t lastTime; + double runTime; + uint64_t runTimeLimit; + + RuntimeWatchdog(Long64_t limit) + { + numberTimeFrames = -1; + startTime = uv_hrtime(); + lastTime = startTime; + runTime = 0.; + runTimeLimit = limit; + } + + bool update() + { + numberTimeFrames++; + if (runTimeLimit <= 0) { + return true; + } + + auto nowTime = uv_hrtime(); + + // time spent to process the time frame + double time_spent = numberTimeFrames < 1 ? (double)(nowTime - lastTime) / 1.E9 : 0.; + runTime += time_spent; + lastTime = nowTime; + + return ((double)(lastTime - startTime) / 1.E9 + runTime / (numberTimeFrames + 1)) < runTimeLimit; + } + + void printOut() + { + LOGP(INFO, "RuntimeWatchdog"); + LOGP(INFO, " run time limit: {}", runTimeLimit); + LOGP(INFO, " number of time frames: {}", numberTimeFrames); + LOGP(INFO, " estimated run time per time frame: {}", (numberTimeFrames >= 0) ? runTime / (numberTimeFrames + 1) : 0.); + LOGP(INFO, " estimated total run time: {}", (double)(lastTime - startTime) / 1.E9 + ((numberTimeFrames >= 0) ? runTime / (numberTimeFrames + 1) : 0.)); + } +}; + struct AODReaderHelpers { static AlgorithmSpec rootFileReaderCallback(); static AlgorithmSpec aodSpawnerCallback(std::vector requested); diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index cfc4afe7cc267..aa31efa4f0f90 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -270,6 +270,9 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() } } + // get the run time watchdog + auto* watchdog = new RuntimeWatchdog(options.get("time-limit")); + // analyze type of requested tables uint64_t readMask = calculateReadMask(spec.outputs, header::DataOrigin{"AOD"}); std::vector unknowns; @@ -280,14 +283,24 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() auto counter = std::make_shared(0); return adaptStateless([readMask, unknowns, - counter, + watchdog, didir](DataAllocator& outputs, ControlService& control, DeviceSpec const& device) { + // check if RuntimeLimit is reached + if (!watchdog->update()) { + LOGP(INFO, "Run time exceeds run time limit of {} seconds!", watchdog->runTimeLimit); + LOGP(INFO, "Stopping after time frame {}.", watchdog->numberTimeFrames - 1); + didir->closeInputFiles(); + control.endOfStream(); + control.readyToQuit(QuitRequest::All); + return; + } + // Each parallel reader reads the files whose index is associated to // their inputTimesliceId assert(device.inputTimesliceId < device.maxInputTimeslices); - size_t fi = (*counter * device.maxInputTimeslices) + device.inputTimesliceId; - *counter += 1; + size_t fi = (watchdog->numberTimeFrames * device.maxInputTimeslices) + device.inputTimesliceId; + // check if EoF is reached if (didir->atEnd(fi)) { LOGP(INFO, "All input files processed"); didir->closeInputFiles(); diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 3f578cabb6506..275f4746cac23 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -205,6 +205,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext readers::AODReaderHelpers::rootFileReaderCallback(), {ConfigParamSpec{"aod-file", VariantType::String, "aod.root", {"Input AOD file"}}, ConfigParamSpec{"json-file", VariantType::String, {"json configuration file"}}, + ConfigParamSpec{"time-limit", VariantType::Int64, 0ll, {"Maximum run time limit in seconds"}}, ConfigParamSpec{"start-value-enumeration", VariantType::Int64, 0ll, {"initial value for the enumeration"}}, ConfigParamSpec{"end-value-enumeration", VariantType::Int64, -1ll, {"final value for the enumeration"}}, ConfigParamSpec{"step-value-enumeration", VariantType::Int64, 1ll, {"step between one value and the other"}}}}; From 4e4752eca260df172de58759d23d3937816a51e5 Mon Sep 17 00:00:00 2001 From: knopers8 Date: Thu, 2 Jul 2020 09:25:09 +0200 Subject: [PATCH 0009/1751] [QC-356] Data Sampling: increase the maximum amount of allowed policy inputs (#3875) --- Framework/Core/src/DataSamplingPolicy.cxx | 11 +++++------ Framework/Core/test/test_DataSampling.cxx | 12 ++++++------ Framework/Core/test/test_DataSamplingPolicy.cxx | 12 ++++++------ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Framework/Core/src/DataSamplingPolicy.cxx b/Framework/Core/src/DataSamplingPolicy.cxx index 5e69f90f91baf..2a6684a16397c 100644 --- a/Framework/Core/src/DataSamplingPolicy.cxx +++ b/Framework/Core/src/DataSamplingPolicy.cxx @@ -71,11 +71,6 @@ void DataSamplingPolicy::configure(const ptree& config) mPaths.push_back({inputSpec, outputSpec}); } - - if (outputId > 9) { - LOG(ERROR) << "Maximum 10 inputs in DataSamplingPolicy are supported. Call the developers if you really need more."; - break; - } } mConditions.clear(); @@ -155,6 +150,10 @@ header::DataOrigin DataSamplingPolicy::createPolicyDataOrigin() header::DataDescription DataSamplingPolicy::createPolicyDataDescription(std::string policyName, size_t id) { + if (id > 99) { + throw std::runtime_error("Maximum 100 inputs in DataSamplingPolicy are supported. Call the developers if you really need more."); + } + if (policyName.size() > 14) { LOG(WARNING) << "DataSamplingPolicy name '" << policyName << "' is longer than 14 characters, we have to trim it. " << "Use a shorter policy name to avoid potential output name conflicts."; @@ -162,7 +161,7 @@ header::DataDescription DataSamplingPolicy::createPolicyDataDescription(std::str } header::DataDescription outputDescription; - outputDescription.runtimeInit(std::string(policyName + "-" + std::to_string(id)).c_str()); + outputDescription.runtimeInit((policyName + std::to_string(id)).c_str()); return outputDescription; } diff --git a/Framework/Core/test/test_DataSampling.cxx b/Framework/Core/test/test_DataSampling.cxx index 9f7ecddbc36e0..ecbd1414f5308 100644 --- a/Framework/Core/test/test_DataSampling.cxx +++ b/Framework/Core/test/test_DataSampling.cxx @@ -65,13 +65,13 @@ BOOST_AUTO_TEST_CASE(DataSamplingSimpleFlow) auto output = std::find_if(disp->outputs.begin(), disp->outputs.end(), [](const OutputSpec& out) { - return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters-0", 0}) && out.lifetime == Lifetime::Timeframe; + return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters0", 0}) && out.lifetime == Lifetime::Timeframe; }); BOOST_CHECK(output != disp->outputs.end()); output = std::find_if(disp->outputs.begin(), disp->outputs.end(), [](const OutputSpec& out) { - return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters-1", 0}) && out.lifetime == Lifetime::Timeframe; + return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters1", 0}) && out.lifetime == Lifetime::Timeframe; }); BOOST_CHECK(output != disp->outputs.end()); @@ -124,13 +124,13 @@ BOOST_AUTO_TEST_CASE(DataSamplingParallelFlow) auto output = std::find_if(disp->outputs.begin(), disp->outputs.end(), [](const OutputSpec& out) { - return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters-0", 0}) && out.lifetime == Lifetime::Timeframe; + return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters0", 0}) && out.lifetime == Lifetime::Timeframe; }); BOOST_CHECK(output != disp->outputs.end()); output = std::find_if(disp->outputs.begin(), disp->outputs.end(), [](const OutputSpec& out) { - return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters-1", 0}) && out.lifetime == Lifetime::Timeframe; + return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters1", 0}) && out.lifetime == Lifetime::Timeframe; }); BOOST_CHECK(output != disp->outputs.end()); @@ -205,9 +205,9 @@ BOOST_AUTO_TEST_CASE(InputSpecsForPolicy) std::vector inputs = DataSampling::InputSpecsForPolicy(configFilePath, "tpcclusters"); BOOST_CHECK_EQUAL(inputs.size(), 2); - BOOST_CHECK(DataSpecUtils::match(inputs[0], ConcreteDataTypeMatcher{"DS", "tpcclusters-0"})); + BOOST_CHECK(DataSpecUtils::match(inputs[0], ConcreteDataTypeMatcher{"DS", "tpcclusters0"})); BOOST_CHECK_EQUAL(inputs[0].binding, "clusters"); - BOOST_CHECK(DataSpecUtils::match(inputs[1], ConcreteDataTypeMatcher{"DS", "tpcclusters-1"})); + BOOST_CHECK(DataSpecUtils::match(inputs[1], ConcreteDataTypeMatcher{"DS", "tpcclusters1"})); BOOST_CHECK_EQUAL(inputs[1].binding, "clusters_p"); std::unique_ptr config = ConfigurationFactory::getConfiguration(configFilePath); diff --git a/Framework/Core/test/test_DataSamplingPolicy.cxx b/Framework/Core/test/test_DataSamplingPolicy.cxx index cc003cf8caad9..b4ff8846331ec 100644 --- a/Framework/Core/test/test_DataSamplingPolicy.cxx +++ b/Framework/Core/test/test_DataSamplingPolicy.cxx @@ -72,11 +72,11 @@ BOOST_AUTO_TEST_CASE(DataSamplingPolicyConfiguration) policy.configure(config); BOOST_CHECK_EQUAL(policy.getName(), "my_policy"); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "my_policy-0", 33})); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "my_policy-1", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "my_policy0", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "my_policy1", 33})); const auto& map = policy.getPathMap(); - BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "CHLEB", 33})).second == (OutputSpec{"DS", "my_policy-0", 33})); - BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "MLEKO", 33})).second == (OutputSpec{"DS", "my_policy-1", 33})); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "CHLEB", 33})).second == (OutputSpec{"DS", "my_policy0", 33})); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "MLEKO", 33})).second == (OutputSpec{"DS", "my_policy1", 33})); BOOST_CHECK_EQUAL(map.size(), 2); BOOST_CHECK(policy.match(ConcreteDataMatcher{"TST", "CHLEB", 33})); @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(DataSamplingPolicyConfiguration) config.put("id", "too-long-policy-name"); policy.configure(config); BOOST_CHECK_EQUAL(policy.getName(), "too-long-polic"); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "too-long-polic-0", 33})); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "too-long-polic-1", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "too-long-polic0", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "too-long-polic1", 33})); BOOST_CHECK_EQUAL(policy.getPathMap().size(), 2); // previous paths should be cleared } From cafdef00f03386756f78814ec9f591a4b7a8add8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 2 Jul 2020 09:25:36 +0200 Subject: [PATCH 0010/1751] Add script to upload initial timestamps from file (#3923) --- .../Scripts/insert_Run2_run_to_timestamps.py | 94 +++++++++++++ Analysis/Scripts/update_ccdb.py | 129 ++++++++++++------ 2 files changed, 178 insertions(+), 45 deletions(-) create mode 100755 Analysis/Scripts/insert_Run2_run_to_timestamps.py diff --git a/Analysis/Scripts/insert_Run2_run_to_timestamps.py b/Analysis/Scripts/insert_Run2_run_to_timestamps.py new file mode 100755 index 0000000000000..4959000f1ba93 --- /dev/null +++ b/Analysis/Scripts/insert_Run2_run_to_timestamps.py @@ -0,0 +1,94 @@ +#!/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): + 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 __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, verbose=0): + """ + 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. + """ + infile = open(input_file_name) + run_list = [] + for i in infile: + i = i.strip() + 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) + entry = run_timestamp(run, start, stop) + if entry not in run_list: + run_list.append(entry) + for i in run_list: + print("Setting run", i) + cmd = "o2-analysiscore-makerun2timestamp" + cmd += f" --run {i.run}" + cmd += f" --timestamp {i.start}" + cmd += f" {extra_args}" + if verbose: + print(cmd) + subprocess.run(cmd.split()) + + +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') + parser.add_argument('--verbose', '-v', action='count', default=0) + args = parser.parse_args() + main(args.input_file_name, args.extra_args, verbose=args.verbose) diff --git a/Analysis/Scripts/update_ccdb.py b/Analysis/Scripts/update_ccdb.py index 00b32ef5bc477..a3cd525175908 100755 --- a/Analysis/Scripts/update_ccdb.py +++ b/Analysis/Scripts/update_ccdb.py @@ -19,87 +19,126 @@ 3) old object with validity [requested_upper_bound, old_upper_validity] Author: Nicolo' Jacazio on 2020-06-22 TODO add support for 3 files update -TODO add support for user input """ import subprocess from datetime import datetime import matplotlib.pyplot as plt +import argparse def convert_timestamp(ts): - return datetime.utcfromtimestamp(ts/1000).strftime('%Y-%m-%d %H:%M:%S') + """ + Converts the timestamp in milliseconds in human readable format + """ + return datetime.utcfromtimestamp(ts/1000).strftime('%Y-%m-%d %H:%M:%S') -def get_ccdb_obj(path, timestamp, dest = "/tmp/"): - print("Getting obj", path, "with timestamp", - timestamp, convert_timestamp(timestamp)) - cmd=f"o2-ccdb-downloadccdbfile --path {path} --dest {dest} --timestamp {timestamp}" +def get_ccdb_obj(path, timestamp, dest="/tmp/", verbose=0): + """ + Gets the ccdb object from 'path' and 'timestamp' and downloads it into 'dest' + """ + if verbose: + print("Getting obj", path, "with timestamp", + timestamp, convert_timestamp(timestamp)) + cmd = f"o2-ccdb-downloadccdbfile --path {path} --dest {dest} --timestamp {timestamp}" subprocess.run(cmd.split()) -def get_ccdb_obj_validity(path, dest = "/tmp/", verbose = True): - cmd=f"o2-ccdb-inspectccdbfile {dest}{path}/snapshot.root" - process=subprocess.Popen(cmd.split(), stdout = subprocess.PIPE) - output, error=process.communicate() - output=output.decode("utf-8").split("\n") - error=error.decode("utf-8").split("\n") if error is not None else error +def get_ccdb_obj_validity(path, dest="/tmp/", verbose=0): + """ + Gets the timestamp validity for an object downloaded from CCDB. + Returns a list with the initial and end timestamps. + """ + cmd = f"o2-ccdb-inspectccdbfile {dest}{path}/snapshot.root" + process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) + output, error = process.communicate() + output = output.decode("utf-8").split("\n") + error = error.decode("utf-8").split("\n") if error is not None else error if verbose: print("out:") print(*output, "\n") print("err:") print(error) - result=list(filter(lambda x: x.startswith('Valid-'), output)) + result = list(filter(lambda x: x.startswith('Valid-'), output)) ValidFrom = result[0].split() ValidUntil = result[1].split() - print(*output, sep="\n") return [int(ValidFrom[-1]), int(ValidUntil[-1])] - return {ValidFrom[0]: ValidFrom[-1], ValidUntil[0]: ValidUntil[-1]} def upload_ccdb_obj(path, timestamp_from, timestamp_until, dest="/tmp/", meta=""): + """ + Uploads a new object to CCDB in the 'path' using the validity timestamp specified + """ print("Uploading obj", path, "with timestamp", [timestamp_from, timestamp_until], convert_timestamp(timestamp_from), convert_timestamp(timestamp_until)) - key=path.split("/")[-1] - cmd=f"o2-ccdb-upload -f {dest}{path}/snapshot.root " + key = path.split("/")[-1] + cmd = f"o2-ccdb-upload -f {dest}{path}/snapshot.root " cmd += f"--key {key} --path {path} " cmd += f"--starttimestamp {timestamp_from} --endtimestamp {timestamp_until} --meta \"{meta}\"" subprocess.run(cmd.split()) -def main(path, timestamp_from, timestamp_until): +def main(path, timestamp_from, timestamp_until, verbose=0, show=False): + """ + Used to upload a new object to CCDB in 'path' valid from 'timestamp_from' to 'timestamp_until' + Gets the object from CCDB specified in 'path' and for 'timestamp_from-1' + Gets the object from CCDB specified in 'path' and for 'timestamp_until+1' + If required plots the situation before and after the update + """ get_ccdb_obj(path, timestamp_from-1) - val_before=get_ccdb_obj_validity(path) + val_before = get_ccdb_obj_validity(path, verbose=verbose) get_ccdb_obj(path, timestamp_until+1) - val_after=get_ccdb_obj_validity(path) - overlap_before=val_before[1] > timestamp_from - overlap_after=val_after[0] < timestamp_until - print(overlap_before, overlap_after) - trimmed_before=val_before if not overlap_before else [ + val_after = get_ccdb_obj_validity(path, verbose=verbose) + overlap_before = val_before[1] > timestamp_from + overlap_after = val_after[0] < timestamp_until + if verbose: + if overlap_before: + print("Previous objects overalps") + if overlap_after: + print("Next objects overalps") + trimmed_before = val_before if not overlap_before else [ val_before[0], timestamp_from - 1] trimmed_after = val_after if not overlap_after else [ timestamp_until+1, val_after[1]] - fig, ax = plt.subplots() - - def bef_af(v, y): - return [v[0] - 1] + v + [v[1] + 1], [0, y, y, 0] - if True: - ax.plot(*bef_af(val_before, 0.95), label='before') - ax.plot(*bef_af(val_after, 1.05), label='after') - if False: - ax.plot(*bef_af(trimmed_before, 0.9), label='trimmed before') - ax.plot(*bef_af(trimmed_after, 1.1), label='trimmed after') - ax.plot(*bef_af([timestamp_from, timestamp_until], 1), label='object') - xlim = 10000000 - plt.xlim([timestamp_from-xlim, timestamp_until+xlim]) - plt.ylim(0, 2) - plt.xlabel('Timestamp') - plt.ylabel('Validity') - plt.legend() - plt.show() + if show: + fig, ax = plt.subplots() + fig + + def bef_af(v, y): + return [v[0] - 1] + v + [v[1] + 1], [0, y, y, 0] + if True: + ax.plot(*bef_af(val_before, 0.95), label='before') + ax.plot(*bef_af(val_after, 1.05), label='after') + if False: + ax.plot(*bef_af(trimmed_before, 0.9), label='trimmed before') + ax.plot(*bef_af(trimmed_after, 1.1), label='trimmed after') + ax.plot(*bef_af([timestamp_from, timestamp_until], 1), label='object') + xlim = 10000000 + plt.xlim([timestamp_from-xlim, timestamp_until+xlim]) + plt.ylim(0, 2) + plt.xlabel('Timestamp') + plt.ylabel('Validity') + plt.legend() + plt.show() if __name__ == "__main__": - main("qc/TOF/TOFTaskCompressed/hDiagnostic", - 1588946517161 + 10000000, - 1588946517161 + 40000000) + parser = argparse.ArgumentParser( + description="Uploads timestamp non overlapping objects to CCDB." + "Basic example: `./update_ccdb.py qc/TOF/TOFTaskCompressed/hDiagnostic 1588956517161 1588986517161 --show --verbose`") + parser.add_argument('path', metavar='path_to_object', type=str, + help='Path of the object in the CCDB repository') + parser.add_argument('timestamp_from', metavar='from_timestamp', type=int, + help='Timestamp of start for the new object to use') + parser.add_argument('timestamp_until', metavar='until_timestamp', type=int, + help='Timestamp of stop for the new object to use') + parser.add_argument('--verbose', '-v', action='count', default=0) + parser.add_argument('--show', '-s', action='count', default=0) + + args = parser.parse_args() + main(path=args.path, + timestamp_from=args.timestamp_from, + timestamp_until=args.timestamp_until, + verbose=args.verbose, + show=args.show) From 529e1e4edee8e7f506b1ad636a8d8d3c955b68cb Mon Sep 17 00:00:00 2001 From: Paul Buehler Date: Thu, 2 Jul 2020 09:57:57 +0200 Subject: [PATCH 0011/1751] implementaion of a DataInputDirector constructor with a vector of data files as input variable --- Analysis/Tutorials/src/aodwriter.cxx | 2 +- .../include/Framework/DataInputDirector.h | 1 + Framework/Core/src/DataInputDirector.cxx | 9 ++++ .../Core/test/test_DataInputDirector.cxx | 50 ++++++++++++++++--- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/Analysis/Tutorials/src/aodwriter.cxx b/Analysis/Tutorials/src/aodwriter.cxx index 7b5ecbde6d6f2..72df95cc46cf5 100644 --- a/Analysis/Tutorials/src/aodwriter.cxx +++ b/Analysis/Tutorials/src/aodwriter.cxx @@ -139,7 +139,7 @@ struct ATask { table_uno(phi, eta, mom); table_due(ok, phi, eta, mom, pt); table_tre(phi, eta, mom, id); - LOGF(INFO, "Values (%i): (%i %f, %f, %f, %f, %i)", cnt, ok, eta, phi, mom, pt, id); + //LOGF(INFO, "Values (%i): (%i %f, %f, %f, %f, %i)", cnt, ok, eta, phi, mom, pt, id); cnt++; } diff --git a/Framework/Core/include/Framework/DataInputDirector.h b/Framework/Core/include/Framework/DataInputDirector.h index 36634a3b4a40f..2147c495e07d5 100644 --- a/Framework/Core/include/Framework/DataInputDirector.h +++ b/Framework/Core/include/Framework/DataInputDirector.h @@ -75,6 +75,7 @@ struct DataInputDirector { DataInputDirector(); DataInputDirector(std::string inputFile); + DataInputDirector(std::vector inputFiles); void reset(); void createDefaultDataInputDescriptor(); diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index a123c37704e2b..75abb8053dec6 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -144,6 +144,15 @@ DataInputDirector::DataInputDirector(std::string inputFile) createDefaultDataInputDescriptor(); } +DataInputDirector::DataInputDirector(std::vector inputFiles) +{ + for (auto inputFile : inputFiles) { + mdefaultInputFiles.emplace_back(inputFile); + } + + createDefaultDataInputDescriptor(); +} + void DataInputDirector::reset() { mdataInputDescriptors.clear(); diff --git a/Framework/Core/test/test_DataInputDirector.cxx b/Framework/Core/test/test_DataInputDirector.cxx index 5b01b583bcfc9..c1d38d56a270e 100644 --- a/Framework/Core/test/test_DataInputDirector.cxx +++ b/Framework/Core/test/test_DataInputDirector.cxx @@ -48,18 +48,56 @@ BOOST_AUTO_TEST_CASE(TestDatainputDirector) jf << R"(})" << std::endl; jf.close(); - DataInputDirector didir; - BOOST_CHECK(didir.readJson(jsonFile)); - //didir.printOut(); printf("\n\n"); + DataInputDirector didir1; + BOOST_CHECK(didir1.readJson(jsonFile)); + //didir1.printOut(); printf("\n\n"); - BOOST_CHECK_EQUAL(didir.getNumberInputDescriptors(), 2); + BOOST_CHECK_EQUAL(didir1.getNumberInputDescriptors(), 2); auto dh = DataHeader(DataDescription{"DUE"}, DataOrigin{"AOD"}, DataHeader::SubSpecificationType{0}); - BOOST_CHECK_EQUAL(didir.getInputFilename(dh, 1), "Bresults_1.root"); + BOOST_CHECK_EQUAL(didir1.getInputFilename(dh, 1), "Bresults_1.root"); - auto didesc = didir.getDataInputDescriptor(dh); + auto didesc = didir1.getDataInputDescriptor(dh); BOOST_CHECK(didesc); BOOST_CHECK_EQUAL(didesc->getNumberInputfiles(), 2); + + // test initialization with "std::vector inputFiles" + // in this case "resfile" of the InputDataDirector in the json file must be + // empty, otherwise files specified in the json file will be added to the + // list of input files + jf.open("testO2config.json", std::ofstream::out); + jf << R"({)" << std::endl; + jf << R"( "InputDirector": {)" << std::endl; + jf << R"delimiter( "fileregex": "(Ares)(.*)",)delimiter" << std::endl; + jf << R"( "InputDescriptors": [)" << std::endl; + jf << R"( {)" << std::endl; + jf << R"( "table": "AOD/UNO/0",)" << std::endl; + jf << R"( "treename": "uno")" << std::endl; + jf << R"( },)" << std::endl; + jf << R"( {)" << std::endl; + jf << R"( "table": "AOD/DUE/0",)" << std::endl; + jf << R"( "treename": "due",)" << std::endl; + jf << R"delimiter( "fileregex": "(Bres)(.*)")delimiter" << std::endl; + jf << R"( })" << std::endl; + jf << R"( ])" << std::endl; + jf << R"( })" << std::endl; + jf << R"(})" << std::endl; + jf.close(); + + std::vector inputFiles = {"Aresults_0.root", + "Aresults_1.root", + "Bresults_0.root", + "Aresults_2.root", + "Bresults_1.root", + "Bresults_2.root"}; + DataInputDirector didir2(inputFiles); + BOOST_CHECK(didir2.readJson(jsonFile)); + + BOOST_CHECK_EQUAL(didir2.getInputFilename(dh, 1), "Bresults_1.root"); + + didesc = didir2.getDataInputDescriptor(dh); + BOOST_CHECK(didesc); + BOOST_CHECK_EQUAL(didesc->getNumberInputfiles(), 3); } From de79ce6df3f4cb40006881d69070e3541029f241 Mon Sep 17 00:00:00 2001 From: Iouri Belikov Date: Mon, 29 Jun 2020 16:05:23 +0200 Subject: [PATCH 0012/1751] Now DisplayTrack.C works compact clusters --- .../ITSMFT/ITS/macros/test/CMakeLists.txt | 16 ++-- .../ITSMFT/ITS/macros/test/DisplayTrack.C | 92 ++++++++++++------- cmake/O2RootMacroExclusionList.cmake | 1 - 3 files changed, 67 insertions(+), 42 deletions(-) diff --git a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt index 054e0e3be7e97..05f4171cbe5a5 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt @@ -58,14 +58,14 @@ o2_add_test_root_macro(CheckTracks.C O2::DataFormatsITSMFT LABELS its) -#o2_add_test_root_macro(DisplayTrack.C -# PUBLIC_LINK_LIBRARIES O2::ITSBase -# O2::DataFormatsITSMFT -# O2::ITSMFTSimulation -# O2::DataFormatsITS -# O2::MathUtils -# O2::SimulationDataFormat -# LABELS its) +o2_add_test_root_macro(DisplayTrack.C + PUBLIC_LINK_LIBRARIES O2::ITSBase + O2::DataFormatsITSMFT + O2::ITSMFTSimulation + O2::DataFormatsITS + O2::MathUtils + O2::SimulationDataFormat + LABELS its) #o2_add_test_root_macro(dictionary_integrity_test.C # PUBLIC_LINK_LIBRARIES O2::DataFormatsITSMFT diff --git a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C index 91493769a5746..c29742199485f 100644 --- a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C +++ b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C @@ -17,18 +17,21 @@ #include #include "ITSBase/GeometryTGeo.h" -#include "DataFormatsITSMFT/Cluster.h" +#include "DataFormatsITSMFT/CompCluster.h" +#include "DataFormatsITSMFT/TopologyDictionary.h" #include "ITSMFTSimulation/Hit.h" +#include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITS/TrackITS.h" #include "MathUtils/Cartesian3D.h" #include "MathUtils/Utils.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "DetectorsCommonDataFormats/NameConf.h" #endif using namespace std; -void DisplayTrack(Int_t event = 0, Int_t track = 0, std::string tracfile = "o2trac_its.root", std::string clusfile = "o2clus_its.root", std::string hitfile = "o2sim_HitsITS.root", std::string inputGeom = "") +void DisplayTrack(Int_t event = 0, Int_t track = 0, std::string tracfile = "o2trac_its.root", std::string clusfile = "o2clus_its.root", std::string hitfile = "o2sim_HitsITS.root", std::string inputGeom = "", std::string dictfile = "") { using namespace o2::base; using namespace o2::its; @@ -47,21 +50,24 @@ void DisplayTrack(Int_t event = 0, Int_t track = 0, std::string tracfile = "o2tr o2::base::GeometryManager::loadGeometry(inputGeom); } - gGeoManager->GetVolume("obSuppCyl")->SetInvisible(); - gGeoManager->GetVolume("ibSuppCyl")->SetInvisible(); - gGeoManager->GetVolume("ITSUStave0_StaveStruct")->SetInvisible(); - gGeoManager->GetVolume("ITSUStave1_StaveStruct")->SetInvisible(); - gGeoManager->GetVolume("ITSUStave2_StaveStruct")->SetInvisible(); + gGeoManager->GetVolume("IBCYSSCylinderFoam")->SetInvisible(); gGeoManager->GetVolume("ITSUHalfStave0")->SetTransparency(50); + gGeoManager->GetVolume("ITSUHalfStave0")->SetLineColor(2); gGeoManager->GetVolume("ITSUHalfStave1")->SetTransparency(50); + gGeoManager->GetVolume("ITSUHalfStave1")->SetLineColor(2); gGeoManager->GetVolume("ITSUHalfStave2")->SetTransparency(50); + gGeoManager->GetVolume("ITSUHalfStave2")->SetLineColor(2); gGeoManager->GetVolume("ITSUHalfStave3")->SetTransparency(50); + gGeoManager->GetVolume("ITSUHalfStave3")->SetLineColor(2); gGeoManager->GetVolume("ITSUHalfStave4")->SetTransparency(50); + gGeoManager->GetVolume("ITSUHalfStave4")->SetLineColor(2); gGeoManager->GetVolume("ITSUHalfStave5")->SetTransparency(50); + gGeoManager->GetVolume("ITSUHalfStave5")->SetLineColor(2); gGeoManager->GetVolume("ITSUHalfStave6")->SetTransparency(50); + gGeoManager->GetVolume("ITSUHalfStave6")->SetLineColor(2); - TGeoNode* tnode = gGeoManager->GetTopVolume()->FindNode("ITSV_2"); + TGeoNode* tnode = gGeoManager->GetVolume("barrel")->FindNode("ITSV_2"); TEveGeoTopNode* evenode = new TEveGeoTopNode(gGeoManager, tnode); evenode->SetVisLevel(4); gEve->AddGlobalElement(evenode); @@ -98,11 +104,10 @@ void DisplayTrack(Int_t event = 0, Int_t track = 0, std::string tracfile = "o2tr tree->GetEvent(event); - Int_t nc = hitArr->size(), n = 0; - while (nc--) { - Hit& c = (*hitArr)[nc]; - if (c.GetTrackID() == track) { - points->SetNextPoint(c.GetX(), c.GetY(), c.GetZ()); + Int_t n = 0; + for (const auto& h : *hitArr) { + if (h.GetTrackID() == track) { + points->SetNextPoint(h.GetX(), h.GetY(), h.GetZ()); n++; } } @@ -122,40 +127,59 @@ void DisplayTrack(Int_t event = 0, Int_t track = 0, std::string tracfile = "o2tr points = new TEvePointSet(s.data()); points->SetMarkerColor(kMagenta); - std::vector* clusArr = nullptr; - tree->SetBranchAddress("ITSCluster", &clusArr); + std::vector* clusArr = nullptr; + tree->SetBranchAddress("ITSClusterComp", &clusArr); + if (dictfile.empty()) { + dictfile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, "", ".bin"); + } + o2::itsmft::TopologyDictionary dict; + std::ifstream file(dictfile.c_str()); + if (file.good()) { + LOG(INFO) << "Running with dictionary: " << dictfile.c_str(); + dict.readBinaryFile(dictfile); + } else { + LOG(INFO) << "Cannot run without the dictionary !"; + return; + } + + // ROFrecords + std::vector* rofRecVecP = nullptr; + tree->SetBranchAddress("ITSClustersROF", &rofRecVecP); + // Cluster MC labels o2::dataformats::MCTruthContainer* clsLabArr = nullptr; tree->SetBranchAddress("ITSClusterMCTruth", &clsLabArr); - int tf = 0; - int lastTF = tree->GetEntries(); - for (; tf < lastTF; ++tf) { - tree->GetEvent(tf); - int nc = clusArr->size(); - for (int i = 0; i < nc; i++) { // Find the TF containing this MC event - auto mclab = (clsLabArr->getLabels(i))[0]; + tree->GetEvent(0); + int nc = clusArr->size(); + int offset = 0; + for (auto& rof : *rofRecVecP) { + offset = rof.getFirstEntry(); + for (int i = 0; i < rof.getNEntries(); i++) { // Find the TF containing this MC event + auto mclab = (clsLabArr->getLabels(offset + i))[0]; auto id = mclab.getEventID(); if (id == event) goto found; } } - std::cout << "Time Frame containing the MC event " << event << " was not found" << std::endl; + std::cout << "RO frame containing the MC event " << event << " was not found" << std::endl; found: - std::cout << "MC event " << event << " found in the Time Frame #" << tf << std::endl; o2::its::GeometryTGeo* gman = GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2GRot)); // request cached transforms + gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::L2G)); // request cached transforms nc = clusArr->size(); n = 0; - while (nc--) { - Cluster& c = (*clusArr)[nc]; - auto lab = (clsLabArr->getLabels(nc))[0]; - auto gloC = c.getXYZGloRot(*gman); // convert from tracking to global frame + for (int i = 0; i < nc; i++) { + const auto& c = (*clusArr)[i]; + auto lab = (clsLabArr->getLabels(i))[0]; if (lab.getEventID() != event) continue; if (lab.getTrackID() == track) { + auto pattID = c.getPatternID(); + auto locC = dict.getClusterCoordinates(c); + auto chipID = c.getSensorID(); + auto gloC = gman->getMatrixL2G(chipID) * locC; points->SetNextPoint(gloC.X(), gloC.Y(), gloC.Z()); n++; } @@ -184,7 +208,7 @@ found: o2::dataformats::MCTruthContainer* trkLabArr = nullptr; tree->SetBranchAddress("ITSTrackMCTruth", &trkLabArr); - tree->GetEvent(tf); + tree->GetEvent(0); Int_t nt = trkArr->size(); n = 0; @@ -198,9 +222,11 @@ found: Int_t nc = t.getNumberOfClusters(); int idxRef = t.getFirstClusterEntry(); while (n < nc) { - Int_t idx = (*clIdx)[idxRef++]; - Cluster& c = (*clusArr)[idx]; - auto gloC = c.getXYZGloRot(*gman); // convert from tracking to global frame + Int_t idx = (*clIdx)[idxRef + n]; + auto& c = (*clusArr)[offset + idx]; + auto locC = dict.getClusterCoordinates(c); + auto chipID = c.getSensorID(); + auto gloC = gman->getMatrixL2G(chipID) * locC; points->SetNextPoint(gloC.X(), gloC.Y(), gloC.Z()); n++; } diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 9b19cd6922f4f..ec76028afb545 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -21,7 +21,6 @@ list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Detectors/ITSMFT/ITS/macros/test/rootlogon.C Detectors/ITSMFT/ITS/macros/test/CheckCOG.C # temporary exclude until fix for full Clusters elimination Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C # temporary exclude until fix for full Clusters elimination - Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C # temporary exclude until fix for full Clusters elimination Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C # temporary exclude until fix for full Clusters elimination Detectors/MUON/MCH/Simulation/macros/rootlogon.C Detectors/Passive/macro/PutFrameInTop.C From f6eb43d5386f10f76bd04333181ea894d0ead42d Mon Sep 17 00:00:00 2001 From: Iouri Belikov Date: Tue, 30 Jun 2020 11:33:20 +0200 Subject: [PATCH 0013/1751] Removing obsolete rootlogon.C's. --- Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C | 56 -------------------- Detectors/ITSMFT/ITS/macros/test/rootlogon.C | 15 ------ cmake/O2RootMacroExclusionList.cmake | 2 - 3 files changed, 73 deletions(-) delete mode 100644 Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C delete mode 100644 Detectors/ITSMFT/ITS/macros/test/rootlogon.C diff --git a/Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C b/Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C deleted file mode 100644 index 984d84075423f..0000000000000 --- a/Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C +++ /dev/null @@ -1,56 +0,0 @@ -{ - std::cout << "\n *** This is ITS visualisation ! ***\n\n"; - gROOT->LoadMacro("./DisplayEvents.C+g"); - std::vector digifiles{ - "data-ep4-link0", - "data-ep4-link1", - "data-ep4-link2", - "data-ep4-link3", - "data-ep4-link4", - "data-ep4-link5", - "data-ep4-link6", - "data-ep4-link7", - "data-ep4-link8", - "data-ep4-link9", - "data-ep4-link10", - "data-ep4-link11", - "data-ep5-link0", - "data-ep5-link1", - "data-ep5-link2", - "data-ep5-link3", - "data-ep5-link4", - "data-ep5-link5", - "data-ep5-link6", - "data-ep5-link7", - "data-ep5-link8", - "data-ep5-link9", - "data-ep5-link10", - "data-ep5-link11"}; - std::vector clusfiles{ - "data-ep4-link0.root", - "data-ep4-link1.root", - "data-ep4-link2.root", - "data-ep4-link3.root", - "data-ep4-link4.root", - "data-ep4-link5.root", - "data-ep4-link6.root", - "data-ep4-link7.root", - "data-ep4-link8.root", - "data-ep4-link9.root", - "data-ep4-link10.root", - "data-ep4-link11.root", - "data-ep5-link0.root", - "data-ep5-link1.root", - "data-ep5-link2.root", - "data-ep5-link3.root", - "data-ep5-link4.root", - "data-ep5-link5.root", - "data-ep5-link6.root", - "data-ep5-link7.root", - "data-ep5-link8.root", - "data-ep5-link9.root", - "data-ep5-link10.root", - "data-ep5-link11.root"}; - init(0, 132, digifiles, true, clusfiles); - gEve->GetBrowser()->GetTabRight()->SetTab(1); -} diff --git a/Detectors/ITSMFT/ITS/macros/test/rootlogon.C b/Detectors/ITSMFT/ITS/macros/test/rootlogon.C deleted file mode 100644 index 0ac3dadc99efa..0000000000000 --- a/Detectors/ITSMFT/ITS/macros/test/rootlogon.C +++ /dev/null @@ -1,15 +0,0 @@ -#if !defined(__CLING__) || defined(__ROOTCLING__) -#include -#include "TSystem.h" -#endif - -void rootlogon() -{ - cout << endl; - cout << endl; - cout << "ATTENTION: ./rootlogon.C has been used !\n"; - cout << endl; - cout << endl; - - gSystem->SetIncludePath("-I$O2_ROOT/../../ms_gsl/latest/include -I$O2_ROOT/../../FairLogger/latest/include -I$O2_ROOT/../../FairMQ/latest/include/fairmq"); -} diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index ec76028afb545..694831a22ad86 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -17,8 +17,6 @@ include(O2GetListOfMacros) # list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST - Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C - Detectors/ITSMFT/ITS/macros/test/rootlogon.C Detectors/ITSMFT/ITS/macros/test/CheckCOG.C # temporary exclude until fix for full Clusters elimination Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C # temporary exclude until fix for full Clusters elimination Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C # temporary exclude until fix for full Clusters elimination From dbba7379da91c6911b1dc13f9a1ce320c5230951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 2 Jul 2020 12:44:19 +0200 Subject: [PATCH 0014/1751] Add base class for TOF pid in analysis tasks (#3918) * Add TOF PID Response * Add spectra TOF task * Add info to TOF pid table * Add task to check exp/computed times consistency --- Analysis/DataModel/CMakeLists.txt | 6 +- Analysis/DataModel/include/PID/PIDResponse.h | 150 +++++++++++++++++ Analysis/DataModel/include/PID/PIDTOF.h | 163 +++++++++++++++++++ Analysis/DataModel/src/PIDTOF.cxx | 67 ++++++++ Analysis/Tasks/CMakeLists.txt | 5 + Analysis/Tasks/spectraTOF.cxx | 154 ++++++++++++++++++ 6 files changed, 542 insertions(+), 3 deletions(-) create mode 100644 Analysis/DataModel/include/PID/PIDResponse.h create mode 100644 Analysis/DataModel/include/PID/PIDTOF.h create mode 100644 Analysis/DataModel/src/PIDTOF.cxx create mode 100644 Analysis/Tasks/spectraTOF.cxx diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index a33849ddf1ed2..fa2097783e236 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -10,10 +10,10 @@ o2_add_library(AnalysisDataModel SOURCES src/dummy.cxx + src/PIDTOF.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src - PUBLIC_LINK_LIBRARIES - O2::Framework - ) + PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats + ) o2_add_executable(dump-aod-data-model SOURCES src/dumpDataModel.cxx diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/PID/PIDResponse.h new file mode 100644 index 0000000000000..c207a5cc1eeeb --- /dev/null +++ b/Analysis/DataModel/include/PID/PIDResponse.h @@ -0,0 +1,150 @@ +// 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 to provide PID response +/// \file PIDResponse.h +/// \author Nicolo' Jacazio +/// + +#ifndef O2_FRAMEWORK_PIDRESPONSE_H_ +#define O2_FRAMEWORK_PIDRESPONSE_H_ + +// O2 includes +#include "Framework/ASoA.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" +#include "PID/PIDTOF.h" +#include "ReconstructionDataFormats/PID.h" + +namespace o2::aod +{ + +namespace pidTOFbeta +{ +DECLARE_SOA_COLUMN(Beta, beta, float); +DECLARE_SOA_COLUMN(BetaError, betaerror, float); +// +DECLARE_SOA_COLUMN(ExpBetaEl, expbetael, float); +DECLARE_SOA_COLUMN(ExpBetaElError, expbetaelerror, float); +// +DECLARE_SOA_COLUMN(SeparationBetaEl, separationbetael, float); +DECLARE_SOA_DYNAMIC_COLUMN(DiffBetaEl, diffbetael, [](float beta, float expbetael) -> float { return beta - expbetael; }); +} // namespace pidTOFbeta + +namespace pidTOF +{ +// Expected times +DECLARE_SOA_COLUMN(ExpTimeEl, expTimeEl, float); +DECLARE_SOA_COLUMN(ExpTimeMu, expTimeMu, float); +DECLARE_SOA_COLUMN(ExpTimePi, expTimePi, float); +DECLARE_SOA_COLUMN(ExpTimeKa, expTimeKa, float); +DECLARE_SOA_COLUMN(ExpTimePr, expTimePr, float); +DECLARE_SOA_COLUMN(ExpTimeDe, expTimeDe, float); +DECLARE_SOA_COLUMN(ExpTimeTr, expTimeTr, float); +DECLARE_SOA_COLUMN(ExpTimeHe, expTimeHe, float); +DECLARE_SOA_COLUMN(ExpTimeAl, expTimeAl, float); +// Expected sigma +DECLARE_SOA_COLUMN(ExpSigmaEl, expSigmaEl, float); +DECLARE_SOA_COLUMN(ExpSigmaMu, expSigmaMu, float); +DECLARE_SOA_COLUMN(ExpSigmaPi, expSigmaPi, float); +DECLARE_SOA_COLUMN(ExpSigmaKa, expSigmaKa, float); +DECLARE_SOA_COLUMN(ExpSigmaPr, expSigmaPr, float); +DECLARE_SOA_COLUMN(ExpSigmaDe, expSigmaDe, float); +DECLARE_SOA_COLUMN(ExpSigmaTr, expSigmaTr, float); +DECLARE_SOA_COLUMN(ExpSigmaHe, expSigmaHe, float); +DECLARE_SOA_COLUMN(ExpSigmaAl, expSigmaAl, float); +// NSigma +DECLARE_SOA_COLUMN(NSigmaEl, nSigmaEl, float); +DECLARE_SOA_COLUMN(NSigmaMu, nSigmaMu, float); +DECLARE_SOA_COLUMN(NSigmaPi, nSigmaPi, float); +DECLARE_SOA_COLUMN(NSigmaKa, nSigmaKa, float); +DECLARE_SOA_COLUMN(NSigmaPr, nSigmaPr, float); +DECLARE_SOA_COLUMN(NSigmaDe, nSigmaDe, float); +DECLARE_SOA_COLUMN(NSigmaTr, nSigmaTr, float); +DECLARE_SOA_COLUMN(NSigmaHe, nSigmaHe, float); +DECLARE_SOA_COLUMN(NSigmaAl, nSigmaAl, float); +} // namespace pidTOF + +using namespace pidTOFbeta; +DECLARE_SOA_TABLE(pidRespTOFbeta, "AOD", "pidRespTOFbeta", + Beta, BetaError, + ExpBetaEl, ExpBetaElError, + SeparationBetaEl, + DiffBetaEl); +using namespace pidTOF; +DECLARE_SOA_TABLE(pidRespTOF, "AOD", "pidRespTOF", + ExpTimeEl, ExpTimeMu, ExpTimePi, ExpTimeKa, ExpTimePr, ExpTimeDe, ExpTimeTr, ExpTimeHe, ExpTimeAl, + ExpSigmaEl, ExpSigmaMu, ExpSigmaPi, ExpSigmaKa, ExpSigmaPr, ExpSigmaDe, ExpSigmaTr, ExpSigmaHe, ExpSigmaAl, + NSigmaEl, NSigmaMu, NSigmaPi, NSigmaKa, NSigmaPr, NSigmaDe, NSigmaTr, NSigmaHe, NSigmaAl); + +} // namespace o2::aod + +using namespace o2; +using namespace o2::framework; +using namespace o2::pid; +using namespace o2::framework::expressions; +using namespace o2::track; + +struct pidTOFTask { + Produces tofpid; + Produces tofpidbeta; + + void process(aod::Collision const& collision, soa::Join const& tracks) + { + LOGF(info, "Tracks for collision: %d", tracks.size()); + tof::EventTime evt = tof::EventTime(); + evt.SetEvTime(0, collision.collisionTime()); + evt.SetEvTimeReso(0, collision.collisionTimeRes()); + evt.SetEvTimeMask(0, collision.collisionTimeMask()); + tof::Response resp = tof::Response(); + resp.SetEventTime(evt); + for (auto i : tracks) { + resp.UpdateTrack(i.p(), i.tofExpMom() / tof::Response::kCSPEED, i.length(), i.tofSignal()); + tofpidbeta(resp.GetBeta(), + resp.GetBetaExpectedSigma(), + resp.GetExpectedBeta(PID::Electron), + resp.GetBetaExpectedSigma(), + resp.GetBetaNumberOfSigmas(PID::Electron)); + tofpid( + resp.GetExpectedSignal(PID::Electron), + resp.GetExpectedSignal(PID::Muon), + resp.GetExpectedSignal(PID::Pion), + resp.GetExpectedSignal(PID::Kaon), + resp.GetExpectedSignal(PID::Proton), + resp.GetExpectedSignal(PID::Deuteron), + resp.GetExpectedSignal(PID::Triton), + resp.GetExpectedSignal(PID::Helium3), + resp.GetExpectedSignal(PID::Alpha), + resp.GetExpectedSigma(PID::Electron), + resp.GetExpectedSigma(PID::Muon), + resp.GetExpectedSigma(PID::Pion), + resp.GetExpectedSigma(PID::Kaon), + resp.GetExpectedSigma(PID::Proton), + resp.GetExpectedSigma(PID::Deuteron), + resp.GetExpectedSigma(PID::Triton), + resp.GetExpectedSigma(PID::Helium3), + resp.GetExpectedSigma(PID::Alpha), + resp.GetNumberOfSigmas(PID::Electron), + resp.GetNumberOfSigmas(PID::Muon), + resp.GetNumberOfSigmas(PID::Pion), + resp.GetNumberOfSigmas(PID::Kaon), + resp.GetNumberOfSigmas(PID::Proton), + resp.GetNumberOfSigmas(PID::Deuteron), + resp.GetNumberOfSigmas(PID::Triton), + resp.GetNumberOfSigmas(PID::Helium3), + resp.GetNumberOfSigmas(PID::Alpha)); + } + } +}; + +#endif // O2_FRAMEWORK_PIDRESPONSE_H_ diff --git a/Analysis/DataModel/include/PID/PIDTOF.h b/Analysis/DataModel/include/PID/PIDTOF.h new file mode 100644 index 0000000000000..caad4a18bd780 --- /dev/null +++ b/Analysis/DataModel/include/PID/PIDTOF.h @@ -0,0 +1,163 @@ +// 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 PIDTOF.h +/// \author Nicolo' Jacazio +/// + +#ifndef O2_FRAMEWORK_PIDTOF_H_ +#define O2_FRAMEWORK_PIDTOF_H_ + +// ROOT includes +#include "Rtypes.h" +#include "TMath.h" + +// O2 includes +#include "Framework/Logger.h" +#include "ReconstructionDataFormats/PID.h" + +namespace o2::pid::tof +{ + +/// \brief Class to handle the event times available for PID +class EventTime +{ + public: + EventTime() = default; + ~EventTime() = default; + + /// Setter for the event time in momentum bin i + void SetEvTime(int i, float evtime) { mEvTime[i] = evtime; } + /// Setter for the event time resolution in momentum bin i + void SetEvTimeReso(int i, float evtimereso) { mEvTimeReso[i] = evtimereso; } + /// Setter for the event time mask in momentum bin i + void SetEvTimeMask(int i, int mask) { mEvTimeMask[i] = mask; } + /// Getter for the event time in momentum bin i + float GetEvTime(int i) const { return mEvTime[i]; } + /// Getter for the event time resolution in momentum bin i + float GetEvTimeReso(int i) const { return mEvTimeReso[i]; } + /// Getter for the momentum bin index + uint GetMomBin(float mom) const; + /// Getter for the event time for the momentum requested + float GetEvTime(float mom) const { return mEvTime[GetMomBin(mom)]; } + /// Getter for the event time resolution for the momentum requested + float GetEvTimeReso(float mom) const { return mEvTimeReso[GetMomBin(mom)]; } + + private: + static const uint mNmomBins = 1; /// Number of momentum bin + static constexpr float mMomBins[mNmomBins + 1] = {0, 100}; /// Momentum bins + float mEvTime[mNmomBins]; /// Evtime (best, T0, T0-TOF, ...) of the event as a function of p + float mEvTimeReso[mNmomBins]; /// Evtime (best, T0, T0-TOF, ...) resolution as a function of p + int mEvTimeMask[mNmomBins]; /// Mask withthe T0 used (0x1=T0-TOF,0x2=T0A,0x3=TOC) for p bins +}; + +/// \brief Class to handle the parametrization of the detector response +class Param +{ + public: + Param() = default; + ~Param() = default; + + /// Setter for expected time resolution + void SetTimeResolution(float res) { mSigma = res; } + /// Getter for expected time resolution + float GetTimeResolution() const { return mSigma; } + + // Tracking resolution for expected times + /// Setter for resolution parametrization + void SetTrackParameter(uint ip, float value) { ip < mParDim ? mPar[ip] = value : 0.f; }; + /// Getter for resolution parametrization + float GetTrackParameter(uint ip) { return ip < mParDim ? mPar[ip] : -999.f; }; + + /// Getter for the expected resolution. + /// Returns the expected sigma of the PID signal for the specified + /// particle mass/Z. + /// If the operation is not possible, return a negative value. + double GetExpectedSigma(float mom, float tof, float evtimereso, float massZ) const; + + private: + double mSigma; /// intrinsic TOF resolution + static constexpr uint mParDim = 4; + float mPar[mParDim] = {0.008, 0.008, 0.002, 40.0}; /// parameter for expected time resolutions +}; + +/// \brief Class to handle the the TOF detector response +class Response +{ + public: + Response() = default; + ~Response() = default; + + /// Updater for the TOF response to setup the track parameters + /// i.e. sets the track of interest + void UpdateTrack(float mom, float tofexpmom, float length, float tofsignal) + { + mMomentum = mom; + mTOFExpMomentum = tofexpmom; + mLength = length; + mTOFSignal = tofsignal; + }; + + /// Setter for the event time information in the parametrization + void SetEventTime(EventTime& evtime) { mEventTime = evtime; }; + /// Getter for the event time information in the parametrization + EventTime GetEventTime() const { return mEventTime; }; + /// Setter for the resolution parametrization + void SetParam(Param& evtime) { mParam = evtime; }; + /// Getter for the resolution parametrization + Param GetParam() const { return mParam; }; + + // TOF beta + /// Computes the beta of a track given a length, a time measurement and an event time + static float GetBeta(float length, float time, float evtime); + /// Gets the beta for the track of interest + float GetBeta() const { return GetBeta(mLength, mTOFSignal, mEventTime.GetEvTime(mMomentum)); } + /// Computes the expected uncertainty on the beta measurement + static float GetBetaExpectedSigma(float length, float time, float evtime, float sigmat = 80); + /// Gets the expected uncertainty on the beta measurement of the track of interest + float GetBetaExpectedSigma(float sigmat = 80) const { return GetBetaExpectedSigma(mLength, mTOFSignal, mEventTime.GetEvTime(mMomentum), sigmat); } + /// Gets the expected beta for a given mass hypothesis (no energy loss taken into account) + static float GetExpectedBeta(float mom, float mass); + /// Gets the expected beta given the particle index (no energy loss taken into account) + float GetExpectedBeta(o2::track::PID::ID id) const { return GetExpectedBeta(mMomentum, o2::track::PID::getMass2Z(id)); } + /// Gets the number of sigmas with respect the approximate beta (no energy loss taken into account) + float GetBetaNumberOfSigmas(o2::track::PID::ID id, float sigmat = 80) { return (GetBeta() - GetExpectedBeta(id)) / GetBetaExpectedSigma(sigmat); } + + // TOF expected times + /// Computes the expected time of a track, given it TOF expected momentum + static float ComputeExpectedTime(float tofexpmom, float length, float massZ); + /// Gets the expected signal of the track of interest under the PID assumption + float GetExpectedSignal(o2::track::PID::ID id) const { return ComputeExpectedTime(mTOFExpMomentum, mLength, o2::track::PID::getMass2Z(id)); } + + // Expected resolution + /// Gets the expected resolution of the measurement + float GetExpectedSigma(o2::track::PID::ID id) const { return mParam.GetExpectedSigma(mMomentum, mTOFSignal, mEventTime.GetEvTimeReso(mMomentum), o2::track::PID::getMass2Z(id)); } + + // Nsigma + float GetNumberOfSigmas(o2::track::PID::ID id) const { return (mTOFSignal - mEventTime.GetEvTime(mMomentum) - GetExpectedSignal(id)) / GetExpectedSigma(id); } + + // double GetMismatchProbability(double time, double eta) const; + // Utility values + static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; /// Speed of light in TOF units (cm/ps) + private: + Param mParam; /// Parametrization of the TOF signal + // Event of interest information + EventTime mEventTime; /// Event time object + // Track of interest information + float mMomentum; /// Momentum of the track of interest + float mTOFExpMomentum; /// TOF expected momentum of the track of interest + float mLength; /// Track of interest integrated length + float mTOFSignal; /// Track of interest integrated length +}; + +} // namespace o2::pid::tof + +#endif // O2_FRAMEWORK_PIDTOF_H_ diff --git a/Analysis/DataModel/src/PIDTOF.cxx b/Analysis/DataModel/src/PIDTOF.cxx new file mode 100644 index 0000000000000..c22fbccaeb164 --- /dev/null +++ b/Analysis/DataModel/src/PIDTOF.cxx @@ -0,0 +1,67 @@ +// 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 "PID/PIDTOF.h" + +namespace o2::pid::tof +{ + +//_________________________________________________________________________ +uint EventTime::GetMomBin(float mom) const +{ + for (int i = 0; i < mNmomBins; i++) + if (abs(mom) < mMomBins[i + 1]) + return i; + return mNmomBins - 1; +} + +//_________________________________________________________________________ +double Param::GetExpectedSigma(float mom, float time, float evtimereso, float mass) const +{ + mom = abs(mom); + if (mom <= 0) + return -999; + double dpp = mPar[0] + mPar[1] * mom + mPar[2] * mass / mom; //mean relative pt resolution; + double sigma = dpp * time / (1. + mom * mom / (mass * mass)); + return TMath::Sqrt(sigma * sigma + mPar[3] * mPar[3] / mom / mom + mSigma * mSigma + evtimereso * evtimereso); +} + +//_________________________________________________________________________ +float Response::ComputeExpectedTime(float tofexpmom, float length, float massZ) +{ + const float energy = sqrt((massZ * massZ) + (tofexpmom * tofexpmom)); + return length * energy / (kCSPEED * tofexpmom); +} + +//_________________________________________________________________________ +float Response::GetBeta(float length, float time, float evtime) +{ + if (time <= 0) + return -999.f; + return length / (time - evtime) / kCSPEED; +} + +//_________________________________________________________________________ +float Response::GetBetaExpectedSigma(float length, float time, float evtime, float sigmat) +{ + if (time <= 0) + return -999.f; + return GetBeta(length, time, evtime) / (time - evtime) * sigmat; +} + +//_________________________________________________________________________ +float Response::GetExpectedBeta(float mom, float mass) +{ + if (mom > 0) + return mom / TMath::Sqrt(mom * mom + mass * mass); + return 0; +} + +} // namespace o2::pid::tof diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 6126bc02e3d76..e4d4e4462bb6c 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -48,6 +48,11 @@ o2_add_dpl_workflow(taskdzero PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing COMPONENT_NAME Analysis) +o2_add_dpl_workflow(spectra-tof + SOURCES spectraTOF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(validation SOURCES validation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase diff --git a/Analysis/Tasks/spectraTOF.cxx b/Analysis/Tasks/spectraTOF.cxx new file mode 100644 index 0000000000000..0ceab235380c5 --- /dev/null +++ b/Analysis/Tasks/spectraTOF.cxx @@ -0,0 +1,154 @@ +// 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 includes +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" + +// ROOT includes +#include + +#define DOTH1F(OBJ, ...) \ + OutputObj OBJ{TH1F(#OBJ, __VA_ARGS__)}; +#define DOTH2F(OBJ, ...) \ + OutputObj OBJ{TH2F(#OBJ, __VA_ARGS__)}; + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct TOFPIDQATask { + // Track quantities + DOTH1F(hp_NoCut, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hp_TrkCut, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hp_TOFCut, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + // TOF Quantities + DOTH1F(hlength_NoCut, ";Track Length (cm);Tracks", 100, 0, 1000); + DOTH1F(htime_NoCut, ";TOF Time (ns);Tracks", 1000, 0, 600); + DOTH1F(hevtime_NoCut, ";Event time (ns);Tracks", 100, -2, 2); + DOTH2F(hp_pTOFexp_NoCut, ";#it{p} (GeV/#it{c});#it{p}_{Exp TOF} (GeV/#it{c});Tracks", 100, 0, 20, 100, 0, 20); + // T-Texp + DOTH2F(htimediffEl_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e});Tracks", 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffMu_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu});Tracks", 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffPi_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi});Tracks", 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffKa_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K});Tracks", 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffPr_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p});Tracks", 100, 0, 5, 100, -1000, 1000); + // NSigma + DOTH2F(hnsigmaEl_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e})/N_{sigma e};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaMu_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu})/N_{sigma #mu};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaPi_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi})/N_{sigma #pi};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaKa_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K})/N_{sigma K};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaPr_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p})/N_{sigma p};Tracks", 100, 0, 5, 100, -10, 10); + // Beta + DOTH2F(hp_beta, ";#it{p} (GeV/#it{c});TOF #beta;Tracks", 100, 0, 20, 100, 0, 2); + + void process(aod::Collision const& collision, soa::Join const& tracks) + { + for (auto i : tracks) { + hp_NoCut->Fill(i.p()); + // Track selection + UChar_t clustermap = i.itsClusterMap(); + bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); + if (issel) + hp_TrkCut->Fill(i.p()); + issel = issel && (i.flags() & 0x2000); //kTOFout + issel = issel && (i.flags() & 0x80000000); //kTIME + if (issel) + hp_TOFCut->Fill(i.p()); + hp_pTOFexp_NoCut->Fill(i.p(), i.tofExpMom() / (TMath::C() * 1.0e2f * 1.0e-12f)); + // + hlength_NoCut->Fill(i.length()); + htime_NoCut->Fill(i.tofSignal() / 1000); + // + hevtime_NoCut->Fill(collision.collisionTime() / 1000); + // hevtime_NoCut->Fill(collision.collisionTime0() / 1000); + // + htimediffEl_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimeEl()); + htimediffMu_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimeMu()); + htimediffPi_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimePi()); + htimediffKa_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimeKa()); + htimediffPr_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimePr()); + // + hnsigmaEl_NoCut->Fill(i.p(), i.nSigmaEl()); + hnsigmaMu_NoCut->Fill(i.p(), i.nSigmaMu()); + hnsigmaPi_NoCut->Fill(i.p(), i.nSigmaPi()); + hnsigmaKa_NoCut->Fill(i.p(), i.nSigmaKa()); + hnsigmaPr_NoCut->Fill(i.p(), i.nSigmaPr()); + // Beta + hp_beta->Fill(i.p(), i.beta()); + } + } +}; + +struct SpectraTask { + // Pt + DOTH1F(hpt_El, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hpt_Pi, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hpt_Ka, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hpt_Pr, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); + // P + DOTH1F(hp_El, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hp_Pi, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hp_Ka, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hp_Pr, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + // + DOTH1F(hlength_El, ";Track Length (cm);Tracks", 100, 0, 1000); + DOTH1F(htime_El, ";TOF Time (ns);Tracks", 1000, 0, 600); + // DOTH1F(hevtime_El, ";Event time (ns);Tracks", 100, -2, 2); + // + DOTH2F(hp_beta_El, ";#it{p} (GeV/#it{c});#beta - #beta_{el};Tracks", 100, 0, 20, 100, -0.01, 0.01); + DOTH2F(hp_betasigma_El, ";#it{p} (GeV/#it{c});(#beta - #beta_{el})/#sigma;Tracks", 100, 0, 20, 100, -5, 5); + + // Filter trk_filter = (aod::track::tpcNClsFindable > 70); + + void process(soa::Join const& tracks) + { + for (auto i : tracks) { + UChar_t clustermap = i.itsClusterMap(); + bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); + issel = issel && (i.flags() & 0x2000); //kTOFout + issel = issel && (i.flags() & 0x80000000); //kTIME + if (!issel) + continue; + if (TMath::Abs(i.nSigmaPi()) < 3) { + hp_El->Fill(i.p()); + hpt_El->Fill(i.pt()); + } else if (TMath::Abs(i.nSigmaKa()) < 3) { + hp_Ka->Fill(i.p()); + hpt_Ka->Fill(i.pt()); + } else if (TMath::Abs(i.nSigmaPr()) < 3) { + hp_Pr->Fill(i.p()); + hpt_Pr->Fill(i.pt()); + } + if (TMath::Abs(i.separationbetael() < 1.f)) { + hp_El->Fill(i.p()); + hpt_El->Fill(i.pt()); + // + hlength_El->Fill(i.length()); + htime_El->Fill(i.tofSignal() / 1000); + // + hp_beta_El->Fill(i.p(), i.diffbetael()); + hp_betasigma_El->Fill(i.p(), i.separationbetael()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask("pidTOF-task"), + adaptAnalysisTask("tofpidqa-task"), + adaptAnalysisTask("filterEl-task")}; +} From 706641e91d7d4ee26b4f821951e4a636a8bac6a4 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 2 Jul 2020 20:17:30 +0200 Subject: [PATCH 0015/1751] DPL: use TFile::Open to open files (#3931) Fixes opening alien:/// files. --- Framework/Core/src/DataInputDirector.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index a123c37704e2b..8c96e70171510 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -48,10 +48,10 @@ TFile* DataInputDescriptor::getInputFile(int counter) if (mcurrentFile) { if (mcurrentFile->GetName() != mfilenames[counter]) { closeInputFile(); - mcurrentFile = new TFile(mfilenames[counter].c_str()); + mcurrentFile = TFile::Open(mfilenames[counter].c_str()); } } else { - mcurrentFile = new TFile(mfilenames[counter].c_str()); + mcurrentFile = TFile::Open(mfilenames[counter].c_str()); } } else { closeInputFile(); From 22ac6c81f8870ab3b44d16d81d8914c5755e6e7f Mon Sep 17 00:00:00 2001 From: mkruegerGitHub Date: Fri, 3 Jul 2020 10:17:56 +0200 Subject: [PATCH 0016/1751] revert back from bool columns to make track selection work again (#3935) Co-authored-by: Mario Kruger --- Analysis/DataModel/include/Analysis/TrackSelectionTables.h | 4 ++-- Analysis/Tasks/trackselection.cxx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h index 7b9e95162fa10..5a242860ca34e 100644 --- a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h @@ -21,8 +21,8 @@ DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); // Columns to store track filter decisions -DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, bool); -DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, bool); +DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, uint8_t); +DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, uint8_t); } // namespace track DECLARE_SOA_TABLE(TracksExtended, "AOD", "TRACKEXTENDED", track::DcaXY, diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index efa4eca4c7448..d94d1974a0ebb 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -122,8 +122,8 @@ struct TrackSelectionTask { void process(soa::Join const& tracks) { for (auto& track : tracks) { - filterTable(globalTracks.IsSelected(track), - globalTracksSDD.IsSelected(track)); + filterTable((uint8_t)globalTracks.IsSelected(track), + (uint8_t)globalTracksSDD.IsSelected(track)); } } }; From 8eb2f8071a3a63599b094489ecb7db62e587441d Mon Sep 17 00:00:00 2001 From: AllaMaevskaya Date: Mon, 29 Jun 2020 16:11:19 +0300 Subject: [PATCH 0017/1751] fix event number in Digitizer --- .../FIT/FT0/simulation/src/Digitizer.cxx | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx index 74c8fa29c073f..106eff553174e 100644 --- a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx @@ -121,12 +121,6 @@ Digitizer::CFDOutput Digitizer::get_time(const std::vector& times, float is_positive = cfd_val > 0.0f; } } - if (!result.particle) { - LOG(DEBUG) << "CFD failed to find peak "; - for (auto t : times) { - LOG(DEBUG) << t << ", dead time " << deadTime; - } - } return result; } @@ -160,7 +154,11 @@ void Digitizer::process(const std::vector* hits, { ; //Calculating signal time, amplitude in mean_time +- time_gate -------------- - flush(digitsBC, digitsCh, label); + LOG(DEBUG) << " process firstBCinDeque " << firstBCinDeque << " mIntRecord " << mIntRecord; + if (firstBCinDeque != mIntRecord) { + flush(digitsBC, digitsCh, label); + } + Int_t parent = -10; for (auto const& hit : *hits) { if (hit.GetEnergyLoss() > 0) @@ -170,17 +168,19 @@ void Digitizer::process(const std::vector* hits, Bool_t is_A_side = (hit_ch < 4 * mParameters.nCellsA); Float_t time_compensate = is_A_side ? mParameters.A_side_cable_cmps : mParameters.C_side_cable_cmps; Double_t hit_time = hit.GetTime() - time_compensate; + if (hit_time > 250) + continue; //not collect very slow particles auto relBC = o2::InteractionRecord{hit_time}; if (mCache.size() <= relBC.bc) { mCache.resize(relBC.bc + 1); } mCache[relBC.bc].hits.emplace_back(BCCache::particle{hit_ch, hit_time - relBC.bc2ns()}); - //charge particles in MCLabel Int_t parentID = hit.GetTrackID(); - if (parentID != parent) + if (parentID != parent) { mCache[relBC.bc].labels.emplace(parentID, mEventID, mSrcID, hit_ch); - parent = parentID; + parent = parentID; + } } } @@ -209,7 +209,6 @@ void Digitizer::storeBC(BCCache& bc, channel_times.resize(channel_end - channel_begin); std::transform(channel_begin, channel_end, channel_times.begin(), [](BCCache::particle const& p) { return p.hit_time; }); int chain = (std::rand() % 2) ? 1 : 0; - auto cfd = get_time(channel_times, mDeadTimes[ipmt].intrec.bc2ns() - firstBCinDeque.bc2ns() + mDeadTimes[ipmt].deadTime); @@ -224,7 +223,7 @@ void Digitizer::storeBC(BCCache& bc, float amp = is_time_in_signal_gate ? mParameters.mV_2_Nchannels * charge : 0; if (amp > 4095) amp = 4095; - LOG(DEBUG) << "bc " << firstBCinDeque.bc << ", ipmt " << ipmt << ", smeared_time " << smeared_time << " nStored " << nStored; + LOG(INFO) << mEventID << " bc " << firstBCinDeque.bc << ", ipmt " << ipmt << ", smeared_time " << smeared_time << " nStored " << nStored; digitsCh.emplace_back(ipmt, smeared_time, int(amp), chain); nStored++; @@ -260,7 +259,7 @@ void Digitizer::storeBC(BCCache& bc, triggers.setTriggers(is_A, is_C, isVertex, is_Central, is_SemiCentral, int8_t(n_hit_A), int8_t(n_hit_C), amplA, amplC, timeA, timeC); - digitsBC.emplace_back(first, nStored, firstBCinDeque, triggers, mEventID); + digitsBC.emplace_back(first, nStored, firstBCinDeque, triggers, mEventID - 1); size_t const nBC = digitsBC.size(); for (auto const& lbl : bc.labels) labels.addElement(nBC - 1, lbl); @@ -280,7 +279,7 @@ void Digitizer::flush(std::vector& digitsBC, std::vector& digitsCh, o2::dataformats::MCTruthContainer& labels) { - LOG(DEBUG) << "firstBCinDeque " << firstBCinDeque << " mIntRecord " << mIntRecord; + assert(firstBCinDeque <= mIntRecord); while (firstBCinDeque < mIntRecord && !mCache.empty()) { storeBC(mCache.front(), digitsBC, digitsCh, labels); @@ -294,8 +293,8 @@ void Digitizer::flush_all(std::vector& digitsBC, std::vector& digitsCh, o2::dataformats::MCTruthContainer& labels) { - LOG(INFO) << "firstBCinDeque " << firstBCinDeque << " mIntRecord " << mIntRecord; - assert(firstBCinDeque <= mIntRecord); + assert(firstBCinDeque < mIntRecord); + ++mEventID; while (!mCache.empty()) { storeBC(mCache.front(), digitsBC, digitsCh, labels); mCache.pop_front(); @@ -314,7 +313,7 @@ void Digitizer::initParameters() // set up tables with sinc function values (times noiseVar) for (size_t i = 0, n = mSincTable.size(); i < n; ++i) { float const time = i / float(n) * mParameters.mNoisePeriod; // [0 .. 1/mParameters.mNoisePeriod) - std::cout << "initParameters " << i << "/" << n << " " << time << std::endl; + LOG(DEBUG) << "initParameters " << i << "/" << n << " " << time; // we make a table of sinc values between -num_noise_samples and 2*num_noise_samples mSincTable[i].resize(3 * mNumNoiseSamples); for (int j = -mNumNoiseSamples; j < 2 * mNumNoiseSamples; ++j) { From 0d56f22c7de659ff4b3a42861582fcd90b9cbbb9 Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Tue, 30 Jun 2020 17:39:16 +0200 Subject: [PATCH 0018/1751] Remove dependencies on full clusters --- Detectors/ITSMFT/ITS/macros/test/CheckCOG.C | 169 ------------ .../ITSMFT/ITS/macros/test/CheckLUtime.C | 65 +++-- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 249 +++++++++--------- .../macros/test/dictionary_integrity_test.C | 2 - cmake/O2RootMacroExclusionList.cmake | 3 +- 5 files changed, 162 insertions(+), 326 deletions(-) delete mode 100644 Detectors/ITSMFT/ITS/macros/test/CheckCOG.C diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckCOG.C b/Detectors/ITSMFT/ITS/macros/test/CheckCOG.C deleted file mode 100644 index 052c3f1496790..0000000000000 --- a/Detectors/ITSMFT/ITS/macros/test/CheckCOG.C +++ /dev/null @@ -1,169 +0,0 @@ -/// \file CheckCOG.C -/// Macros to test the generation of a dictionary of topologies. Three dictionaries are generated: one with signal-cluster only, one with noise-clusters only and one with all the clusters. - -#if !defined(__CLING__) || defined(__ROOTCLING__) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "MathUtils/Utils.h" -#include "ITSBase/GeometryTGeo.h" -#include "DataFormatsITSMFT/Cluster.h" -#include "DataFormatsITSMFT/CompCluster.h" -#include "DataFormatsITSMFT/TopologyDictionary.h" -#include "MathUtils/Cartesian3D.h" -#include "DetectorsCommonDataFormats/NameConf.h" - -#endif - -void CheckCOG(std::string clusfile = "o2clus_its.root", std::string inputGeom = "", std::string dictionary_file = "") -{ - gStyle->SetOptStat(0); - using namespace o2::base; - using namespace o2::its; - - using o2::itsmft::Cluster; - using o2::itsmft::CompCluster; - using o2::itsmft::CompClusterExt; - using o2::itsmft::TopologyDictionary; - - if (dictionary_file.empty()) { - dictionary_file = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, "", ".bin"); - } - - // Geometry - o2::base::GeometryManager::loadGeometry(inputGeom); - auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); // request cached transforms - - // Clusters - TFile* file1 = TFile::Open(clusfile.data()); - TTree* clusTree = (TTree*)gFile->Get("o2sim"); - std::vector* compclusArr = nullptr; - clusTree->SetBranchAddress("ITSClusterComp", &compclusArr); - std::vector* patternsPtr = nullptr; - auto pattBranch = clusTree->GetBranch("ITSClusterPatt"); - if (pattBranch) { - pattBranch->SetAddress(&patternsPtr); - } - - int nevCl = clusTree->GetEntries(); // clusters in cont. readout may be grouped as few events per entry - int ievC = 0; - int lastReadHitEv = -1; - - TopologyDictionary dict; - std::ifstream file(dictionary_file.c_str()); - if (file.good()) { - LOG(INFO) << "Running with dictionary: " << dictionary_file.c_str(); - dict.readBinaryFile(dictionary_file); - } else { - LOG(INFO) << "Running without dictionary !"; - } - - TH1F* hTotalX = new TH1F("hTotalX", "All entries;x_{full} - x_{compact} (#mum);counts", 81, -40.5, 40.5); - TH1F* hTotalZ = new TH1F("hTotalZ", "All entries;z_{full} - z_{compact} (#mum);counts", 81, -40.5, 40.5); - TH1F* hCommonX = new TH1F("hCommonX", "Common topologies;x_{full} - x_{compact} (#mum);counts", 81, -40.5, 40.5); - TH1F* hCommonZ = new TH1F("hCommonZ", "Common topologies;z_{full} - z_{compact} (#mum);counts", 81, -40.5, 40.5); - TH1F* hGroupX = new TH1F("hGroupX", "Groups;x_{full} - x_{compact} (#mum);counts", 81, -40.5, 40.5); - TH1F* hGroupZ = new TH1F("hGroupZ", "Groups;z_{full} - z_{compact} (#mum);counts", 81, -40.5, 40.5); - std::ofstream fOut("COGdebug.txt"); - TCanvas* cTotal = new TCanvas("cTotal", "All topologies"); - cTotal->Divide(2, 1); - TCanvas* cCommon = new TCanvas("cCommon", "Common topologies"); - cCommon->Divide(2, 1); - TCanvas* cGroup = new TCanvas("cGroup", "Gourps of rare topologies"); - cGroup->Divide(2, 1); - for (ievC = 0; ievC < nevCl; ievC++) { - clusTree->GetEvent(ievC); - int nc = compclusArr->size(); - printf("processing cluster event %d\n", ievC); - - std::vector::const_iterator pattIdx; - if (patternsPtr) - pattIdx = patternsPtr->begin(); - for (int i = 0; i < nc; i++) { - // cluster is in tracking coordinates always - Cluster& c = (*clusArr)[i]; - const auto locC = c.getXYZLoc(*gman); // convert from tracking to local frame - - float dx, dz; - Point3D locComp; - CompClusterExt& cComp = (*compclusArr)[i]; - auto pattID = cComp.getPatternID(); - fOut << Form("groupID: %d\n", pattID); - if (pattID != CompCluster::InvalidPatternID) { - Point3D locComp = dict.getClusterCoordinates(cComp); - - float xComp = locComp.X(); - float zComp = locComp.Z(); - - dx = (locC.X() - xComp) * 10000; - dz = (locC.Z() - zComp) * 10000; - - hTotalX->Fill(dx); - hTotalZ->Fill(dz); - - fOut << Form("groupID: %d\n", cComp.getPatternID()); - fOut << Form("is group: %o\n", dict.isGroup(cComp.getPatternID())); - fOut << Form("x_full: %.4f x_comp: %.4f dx: %.4f x_shift: %.4f\n", locC.X(), xComp, dx / 10000, dict.getXCOG(cComp.getPatternID())); - fOut << Form("z_full: %.4f z_comp: %.4f dZ: %.4f z_shift: %.4f\n", locC.Z(), zComp, dz / 10000, dict.getZCOG(cComp.getPatternID())); - fOut << dict.getPattern(cComp.getPatternID()); - fOut << Form("***************************************\n"); - - if (dict.isGroup(cComp.getPatternID())) { - if (patternsPtr) { // Restore the full pixel pattern information from the auxiliary branch - o2::itsmft::ClusterPattern patt(pattIdx); - auto locCl = dict.getClusterCoordinates(cComp, patt); - dx = (locC.X() - locCl.X()) * 10000; - dz = (locC.Z() - locCl.Z()) * 10000; - } - hGroupX->Fill(dx); - hGroupZ->Fill(dz); - } else { - hCommonX->Fill(dx); - hCommonZ->Fill(dz); - } - } - } - } - TFile output_file("COG_diff.root", "recreate"); - hTotalX->Write(); - hTotalZ->Write(); - hGroupX->Write(); - hGroupZ->Write(); - hCommonX->Write(); - hCommonZ->Write(); - cTotal->cd(1); - gPad->SetLogy(); - hTotalX->Draw(); - cTotal->cd(2); - gPad->SetLogy(); - hTotalZ->Draw(); - cTotal->Print("cTotal.pdf"); - cCommon->cd(1); - gPad->SetLogy(); - hCommonX->Draw(); - cCommon->cd(2); - gPad->SetLogy(); - hCommonZ->Draw(); - cCommon->Print("cCommon.pdf"); - cGroup->cd(1); - gPad->SetLogy(); - hGroupX->Draw(); - cGroup->cd(2); - gPad->SetLogy(); - hGroupZ->Draw(); - cGroup->Print("cGroup.pdf"); - cTotal->Write(); - cCommon->Write(); - cGroup->Write(); -} diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C b/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C index fdfcabfe8a22d..03ed999201e71 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C @@ -1,5 +1,5 @@ /// \file CheckLUtime.C -/// \brief Macro to measure the time necessaty for the identification of the topology IDs of the clusters generated in an event. A dictionary of topologies must be provided as input. +/// \brief Macro to measure the time necessaty for the identification of the topology IDs of the clusters generated in an event. A dictionary of topologies must be provided as input. An input file with the pattern for ALL the clusters must be provuded. #if !defined(__CLING__) || defined(__ROOTCLING__) #include @@ -16,8 +16,9 @@ #include "TStopwatch.h" #include "ITSMFTReconstruction/LookUp.h" -#include "DataFormatsITSMFT/Cluster.h" +#include "DataFormatsITSMFT/ClusterPattern.h" #include "DataFormatsITSMFT/CompCluster.h" +#include "DataFormatsITSMFT/ROFRecord.h" #include "DetectorsCommonDataFormats/NameConf.h" #endif @@ -26,13 +27,23 @@ using namespace std; void CheckLUtime(std::string clusfile = "o2clus_its.root", std::string dictfile = "") { - using o2::itsmft::Cluster; + using o2::itsmft::ClusterPattern; using o2::itsmft::CompClusterExt; using o2::itsmft::LookUp; + using ROFRec = o2::itsmft::ROFRecord; + + TStopwatch sw; + sw.Start(); if (dictfile.empty()) { dictfile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, "", ".bin"); } + std::ifstream file(dictfile.c_str()); + if (file.good()) { + LOG(INFO) << "Running with dictionary: " << dictfile.c_str(); + } else { + LOG(INFO) << "Running without dictionary !"; + } LookUp finder(dictfile.c_str()); ofstream time_output("time.txt"); @@ -40,32 +51,34 @@ void CheckLUtime(std::string clusfile = "o2clus_its.root", std::string dictfile realtime.open("realtime.txt", std::ofstream::out | std::ofstream::app); cputime.open("cputime.txt", std::ofstream::out | std::ofstream::app); - TStopwatch timerLookUp; - // Clusters - TFile* file1 = TFile::Open(clusfile.data()); - TTree* clusTree = (TTree*)gFile->Get("o2sim"); - std::vector* clusArr = nullptr; - clusTree->SetBranchAddress("ITSClusterComp", &clusArr); + TFile* fileCl = TFile::Open(clusfile.data()); + TTree* clusTree = (TTree*)fileCl->Get("o2sim"); std::vector* patternsPtr = nullptr; auto pattBranch = clusTree->GetBranch("ITSClusterPatt"); if (pattBranch) { pattBranch->SetAddress(&patternsPtr); } - Int_t nevCl = clusTree->GetEntries(); // clusters in cont. readout may be grouped as few events per entry - int ievC = 0, ievH = 0; + // ROFrecords + std::vector rofRecVec, *rofRecVecP = &rofRecVec; + clusTree->SetBranchAddress("ITSClustersROF", &rofRecVecP); + clusTree->GetEntry(0); + int nROFRec = (int)rofRecVec.size(); + + auto pattIdx = patternsPtr->cbegin(); + + int nClusters = 0; + + for (int irof = 0; irof < nROFRec; irof++) { + const auto& rofRec = rofRecVec[irof]; + + rofRec.print(); - for (ievC = 0; ievC < nevCl; ievC++) { - clusTree->GetEvent(ievC); - Int_t nc = clusArr->size(); - printf("processing cluster event %d\n", ievC); - bool restart = false; - restart = (ievC == 0) ? true : false; - timerLookUp.Start(restart); - auto pattIdx = patternsPtr->cbegin(); - for (int i = 0; i < nc; i++) { - CompClusterExt& c = (*clusArr)[i]; + for (int icl = 0; icl < rofRec.getNEntries(); icl++) { + nClusters++; + int clEntry = rofRec.getFirstEntry() + icl; // entry of icl-th cluster of this ROF in the vector of clusters + // do we read MC data? auto rowSpan = *pattIdx++; auto columnSpan = *pattIdx++; int nBytes = (rowSpan * columnSpan) >> 3; @@ -77,12 +90,12 @@ void CheckLUtime(std::string clusfile = "o2clus_its.root", std::string dictfile } finder.findGroupID(rowSpan, columnSpan, patt); } - timerLookUp.Stop(); } - realtime << timerLookUp.RealTime() / nevCl << std::endl; + sw.Stop(); + realtime << sw.RealTime() / nClusters << std::endl; realtime.close(); - cputime << timerLookUp.CpuTime() / nevCl << std::endl; + cputime << sw.CpuTime() / nClusters << std::endl; cputime.close(); - time_output << "Real time (s): " << timerLookUp.RealTime() / nevCl << "CPU time (s): " << timerLookUp.CpuTime() / nevCl << std::endl; - std::cout << "Real time (s): " << timerLookUp.RealTime() / nevCl << " CPU time (s): " << timerLookUp.CpuTime() / nevCl << std::endl; + time_output << "Real time (s): " << sw.RealTime() / nClusters << "CPU time (s): " << sw.CpuTime() / nClusters << std::endl; + std::cout << "Real time (s): " << sw.RealTime() / nClusters << " CPU time (s): " << sw.CpuTime() / nClusters << std::endl; } diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index fe1fc4381a44b..7bc28be4c4d70 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -21,7 +21,6 @@ #include "ITSMFTReconstruction/BuildTopologyDictionary.h" #include "DataFormatsITSMFT/CompCluster.h" #include "DataFormatsITSMFT/ClusterTopology.h" -#include "DataFormatsITSMFT/TopologyDictionary.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "ITSMFTSimulation/Hit.h" #include "MathUtils/Cartesian3D.h" @@ -29,11 +28,14 @@ #include "SimulationDataFormat/MCTruthContainer.h" #include "DetectorsCommonDataFormats/NameConf.h" #include - #endif -void CheckTopologies(std::string clusfile = "o2clus_its.root", std::string hitfile = "o2sim_HitsITS.root", std::string inputGeom = "") +void CheckTopologies(std::string clusfile = "o2clus_its.root", + std::string hitfile = "o2sim_HitsITS.root", + std::string inputGeom = "") { + const int QEDSourceID = 99; // Clusters from this MC source correspond to QED electrons + using namespace o2::base; using namespace o2::its; @@ -49,13 +51,9 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", std::string hitfi std::vector hitVecPool; std::vector mc2hitVec; - const int QEDSourceID = 99; // Clusters from this MC source correspond to QED electrons - TStopwatch sw; sw.Start(); - std::ofstream output_check("check_topologies.txt"); - // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); @@ -65,19 +63,17 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", std::string hitfi // Hits TFile* fileH = nullptr; TTree* hitTree = nullptr; - std::vector* hitArray = nullptr; if (!hitfile.empty() && !gSystem->AccessPathName(hitfile.c_str())) { fileH = TFile::Open(hitfile.data()); hitTree = (TTree*)fileH->Get("o2sim"); - hitTree->SetBranchAddress("ITSHit", &hitArray); mc2hitVec.resize(hitTree->GetEntries()); hitVecPool.resize(hitTree->GetEntries(), nullptr); } // Clusters - TFile* FileCl = TFile::Open(clusfile.data()); - TTree* clusTree = (TTree*)FileCl->Get("o2sim"); + TFile* fileCl = TFile::Open(clusfile.data()); + TTree* clusTree = (TTree*)fileCl->Get("o2sim"); std::vector* clusArr = nullptr; clusTree->SetBranchAddress("ITSClusterComp", &clusArr); std::vector* patternsPtr = nullptr; @@ -99,107 +95,104 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", std::string hitfi } clusTree->GetEntry(0); - Int_t nevCl = clusTree->GetEntries(); // clusters in cont. readout may be grouped as few events per entry - Int_t nevH = 0; // hits are stored as one event per entry - if (hitTree) { - nevH = hitTree->GetEntries(); - } - int ievC = 0, ievH = 0; - int lastReadHitEv = -1; - // Topologies dictionaries: 1) all clusters 2) signal clusters only 3) noise clusters only BuildTopologyDictionary completeDictionary; BuildTopologyDictionary signalDictionary; BuildTopologyDictionary noiseDictionary; - for (ievC = 0; ievC < nevCl; ievC++) { - clusTree->GetEvent(ievC); - - int nROFRec = (int)rofRecVec.size(); - std::vector mcEvMin(nROFRec, hitTree ? hitTree->GetEntries() : 0), mcEvMax(nROFRec, -1); + int nROFRec = (int)rofRecVec.size(); + std::vector mcEvMin(nROFRec, hitTree->GetEntries()), mcEvMax(nROFRec, -1); - if (clusLabArr) { // >> build min and max MC events used by each ROF - for (int imc = mc2rofVec.size(); imc--;) { - const auto& mc2rof = mc2rofVec[imc]; - if (mc2rof.rofRecordID < 0) { - continue; // this MC event did not contribute to any ROF + if (clusLabArr) { // >> build min and max MC events used by each ROF + for (int imc = mc2rofVec.size(); imc--;) { + const auto& mc2rof = mc2rofVec[imc]; + if (mc2rof.rofRecordID < 0) { + continue; // this MC event did not contribute to any ROF + } + for (int irfd = mc2rof.maxROF - mc2rof.minROF + 1; irfd--;) { + int irof = mc2rof.rofRecordID + irfd; + if (mcEvMin[irof] > imc) { + mcEvMin[irof] = imc; } - for (int irfd = mc2rof.maxROF - mc2rof.minROF + 1; irfd--;) { - int irof = mc2rof.rofRecordID + irfd; - if (mcEvMin[irof] > imc) { - mcEvMin[irof] = imc; - } - if (mcEvMax[irof] < imc) { - mcEvMax[irof] = imc; - } + if (mcEvMax[irof] < imc) { + mcEvMax[irof] = imc; } } - } // << build min and max MC events used by each ROF - - auto pattIdx = patternsPtr->cbegin(); - - for (int irof = 0; irof < nROFRec; irof++) { - const auto& rofRec = rofRecVec[irof]; - rofRec.print(); - if (clusLabArr) { // >> read and map MC events contributing to this ROF - for (int im = mcEvMin[irof]; im <= mcEvMax[irof]; im++) { - if (!hitVecPool[im]) { - hitTree->SetBranchAddress("ITSHit", &hitVecPool[im]); - hitTree->GetEntry(im); - auto& mc2hit = mc2hitVec[im]; - const auto* hitArray = hitVecPool[im]; - for (int ih = hitArray->size(); ih--;) { - const auto& hit = (*hitArray)[ih]; - uint64_t key = (uint64_t(hit.GetTrackID()) << 32) + hit.GetDetectorID(); - mc2hit.emplace(key, ih); - } + } + } // << build min and max MC events used by each ROF + + auto pattIdx = patternsPtr->cbegin(); + for (int irof = 0; irof < nROFRec; irof++) { + const auto& rofRec = rofRecVec[irof]; + + rofRec.print(); + + if (clusLabArr) { // >> read and map MC events contributing to this ROF + for (int im = mcEvMin[irof]; im <= mcEvMax[irof]; im++) { + if (!hitVecPool[im]) { + hitTree->SetBranchAddress("ITSHit", &hitVecPool[im]); + hitTree->GetEntry(im); + auto& mc2hit = mc2hitVec[im]; + const auto* hitArray = hitVecPool[im]; + for (int ih = hitArray->size(); ih--;) { + const auto& hit = (*hitArray)[ih]; + uint64_t key = (uint64_t(hit.GetTrackID()) << 32) + hit.GetDetectorID(); + mc2hit.emplace(key, ih); } } - } // << cache MC events contributing to this ROF - - for (int icl = 0; icl < rofRec.getNEntries(); icl++) { - int clEntry = rofRec.getFirstEntry() + icl; // entry of icl-th cluster of this ROF in the vector of clusters - // do we read MC data? - const auto& cluster = (*clusArr)[clEntry]; - ClusterTopology topology; - o2::itsmft::ClusterPattern pattern(pattIdx); - topology.setPattern(pattern); - //output_check << "iEv: " << ievC << " / " << nevCl << " iCl: " << clEntry << " / " << clusArr->size() << std::endl; - // output_check << topology << std::endl; - - const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern); - float dx = BuildTopologyDictionary::IgnoreVal * 2, dz = BuildTopologyDictionary::IgnoreVal * 2; // to not use unassigned dx,dy - if (clusLabArr) { - const auto& lab = (clusLabArr->getLabels(clEntry))[0]; - auto srcID = lab.getSourceID(); - if (lab.isValid() && srcID != QEDSourceID) { // use MC truth info only for non-QED and non-noise clusters - int trID = lab.getTrackID(); - const auto& mc2hit = mc2hitVec[lab.getEventID()]; - const auto* hitArray = hitVecPool[lab.getEventID()]; - Int_t chipID = cluster.getSensorID(); - uint64_t key = (uint64_t(trID) << 32) + chipID; - auto hitEntry = mc2hit.find(key); - if (hitEntry != mc2hit.end()) { - const auto& hit = (*hitArray)[hitEntry->second]; - auto locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local - auto locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); - locH.SetXYZ(0.5 * (locH.X() + locHsta.X()), 0.5 * (locH.Y() + locHsta.Y()), 0.5 * (locH.Z() + locHsta.Z())); - const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern); - dx = locH.X() - locC.X(); - dz = locH.Z() - locC.Z(); - } else { - printf("Failed to find MC hit entry for Tr:%d chipID:%d\n", trID, chipID); - continue; - } - signalDictionary.accountTopology(topology, dx, dz); + } + } // << cache MC events contributing to this ROF + + for (int icl = 0; icl < rofRec.getNEntries(); icl++) { + int clEntry = rofRec.getFirstEntry() + icl; // entry of icl-th cluster of this ROF in the vector of clusters + // do we read MC data? + + const auto& cluster = (*clusArr)[clEntry]; + + ClusterTopology topology; + o2::itsmft::ClusterPattern pattern(pattIdx); + topology.setPattern(pattern); + + float dX = BuildTopologyDictionary::IgnoreVal, dZ = BuildTopologyDictionary::IgnoreVal; + if (clusLabArr) { + const auto& lab = (clusLabArr->getLabels(clEntry))[0]; + auto srcID = lab.getSourceID(); + if (lab.isValid() && srcID != QEDSourceID) { // use MC truth info only for non-QED and non-noise clusters + auto trID = lab.getTrackID(); + const auto& mc2hit = mc2hitVec[lab.getEventID()]; + const auto* hitArray = hitVecPool[lab.getEventID()]; + Int_t chipID = cluster.getSensorID(); + uint64_t key = (uint64_t(trID) << 32) + chipID; + auto hitEntry = mc2hit.find(key); + if (hitEntry != mc2hit.end()) { + const auto& hit = (*hitArray)[hitEntry->second]; + auto locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local + auto locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); + locH.SetXYZ(0.5 * (locH.X() + locHsta.X()), 0.5 * (locH.Y() + locHsta.Y()), 0.5 * (locH.Z() + locHsta.Z())); + const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern); + dX = locH.X() - locC.X(); + dZ = locH.Z() - locC.Z(); } else { - noiseDictionary.accountTopology(topology, dx, dz); + printf("Failed to find MC hit entry for Tr:%d chipID:%d\n", trID, chipID); } + signalDictionary.accountTopology(topology, dX, dZ); + } else { + noiseDictionary.accountTopology(topology, dX, dZ); } - completeDictionary.accountTopology(topology, dx, dz); - } // Loop over clusters of a single ROF - } // loop over ROFs - } // loop over eventually multiple entries (TFs) + } + completeDictionary.accountTopology(topology, dX, dZ); + } + // clean MC cache for events which are not needed anymore + int irfNext = irof; + while ((++irfNext < nROFRec) && mcEvMax[irfNext] < 0) { + } // find next ROF having MC contribution + int limMC = irfNext == nROFRec ? hitVecPool.size() : mcEvMin[irfNext]; // can clean events up to this + for (int imc = mcEvMin[irof]; imc < limMC; imc++) { + delete hitVecPool[imc]; + hitVecPool[imc] = nullptr; + mc2hitVec[imc].clear(); + } + } auto dID = o2::detectors::DetID::ITS; @@ -219,40 +212,40 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", std::string hitfi hComplete->Draw("hist"); hComplete->Write(); cComplete->Write(); + TCanvas* cNoise = nullptr; TCanvas* cSignal = nullptr; TH1F* hNoise = nullptr; TH1F* hSignal = nullptr; - if (clusLabArr) { - noiseDictionary.setThreshold(0.0001); - noiseDictionary.groupRareTopologies(); - noiseDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".bin")); - noiseDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".txt")); - noiseDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".root")); - signalDictionary.setThreshold(0.0001); - signalDictionary.groupRareTopologies(); - signalDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".bin")); - signalDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".txt")); - signalDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".root")); - cNoise = new TCanvas("cNoise", "Distribution of noise topologies"); - cNoise->cd(); - cNoise->SetLogy(); - o2::itsmft::TopologyDictionary::getTopologyDistribution(noiseDictionary.getDictionary(), hNoise, "hNoise"); - hNoise->SetDirectory(0); - hNoise->Draw("hist"); - histogramOutput.cd(); - hNoise->Write(); - cNoise->Write(); - cSignal = new TCanvas("cSignal", "cSignal"); - cSignal->cd(); - cSignal->SetLogy(); - o2::itsmft::TopologyDictionary::getTopologyDistribution(signalDictionary.getDictionary(), hSignal, "hSignal"); - hSignal->SetDirectory(0); - hSignal->Draw("hist"); - histogramOutput.cd(); - hSignal->Write(); - cSignal->Write(); - } + noiseDictionary.setThreshold(0.0001); + noiseDictionary.groupRareTopologies(); + noiseDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".bin")); + noiseDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".txt")); + noiseDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".root")); + signalDictionary.setThreshold(0.0001); + signalDictionary.groupRareTopologies(); + signalDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".bin")); + signalDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".txt")); + signalDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".root")); + cNoise = new TCanvas("cNoise", "Distribution of noise topologies"); + cNoise->cd(); + cNoise->SetLogy(); + o2::itsmft::TopologyDictionary::getTopologyDistribution(noiseDictionary.getDictionary(), hNoise, "hNoise"); + hNoise->SetDirectory(0); + hNoise->Draw("hist"); + histogramOutput.cd(); + hNoise->Write(); + cNoise->Write(); + cSignal = new TCanvas("cSignal", "cSignal"); + cSignal->cd(); + cSignal->SetLogy(); + o2::itsmft::TopologyDictionary::getTopologyDistribution(signalDictionary.getDictionary(), hSignal, "hSignal"); + hSignal->SetDirectory(0); + hSignal->Draw("hist"); + histogramOutput.cd(); + hSignal->Write(); + cSignal->Write(); + sw.Stop(); sw.Print(); } diff --git a/Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C b/Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C index f7ee3557dd3ba..c78e9cdd8b99d 100644 --- a/Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C +++ b/Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C @@ -5,14 +5,12 @@ #include #include #include -#include "DataFormatsITSMFT/Cluster.h" #include "DataFormatsITSMFT/ClusterPattern.h" #include "DataFormatsITSMFT/TopologyDictionary.h" #include "ITSMFTReconstruction/LookUp.h" #include "DetectorsCommonDataFormats/NameConf.h" #endif -using o2::itsmft::Cluster; using o2::itsmft::ClusterPattern; using o2::itsmft::LookUp; using o2::itsmft::TopologyDictionary; diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 694831a22ad86..f7f67fe62c508 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -17,7 +17,8 @@ include(O2GetListOfMacros) # list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST - Detectors/ITSMFT/ITS/macros/test/CheckCOG.C # temporary exclude until fix for full Clusters elimination + Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C + Detectors/ITSMFT/ITS/macros/test/rootlogon.C Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C # temporary exclude until fix for full Clusters elimination Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C # temporary exclude until fix for full Clusters elimination Detectors/MUON/MCH/Simulation/macros/rootlogon.C From 389b91638a63c7c056b522e34d32accd95862fdb Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Thu, 2 Jul 2020 18:14:03 +0200 Subject: [PATCH 0019/1751] Add protection against clusters with ID --- .../ITSMFT/ITS/macros/test/CheckLUtime.C | 11 +++ .../ITSMFT/ITS/macros/test/CheckTopologies.C | 69 +++++++++++-------- cmake/O2RootMacroExclusionList.cmake | 2 - 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C b/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C index 03ed999201e71..7c4096d7286c6 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C @@ -29,6 +29,7 @@ void CheckLUtime(std::string clusfile = "o2clus_its.root", std::string dictfile { using o2::itsmft::ClusterPattern; using o2::itsmft::CompClusterExt; + using o2::itsmft::CompCluster; using o2::itsmft::LookUp; using ROFRec = o2::itsmft::ROFRecord; @@ -54,6 +55,8 @@ void CheckLUtime(std::string clusfile = "o2clus_its.root", std::string dictfile // Clusters TFile* fileCl = TFile::Open(clusfile.data()); TTree* clusTree = (TTree*)fileCl->Get("o2sim"); + std::vector* clusArr = nullptr; + clusTree->SetBranchAddress("ITSClusterComp", &clusArr); std::vector* patternsPtr = nullptr; auto pattBranch = clusTree->GetBranch("ITSClusterPatt"); if (pattBranch) { @@ -79,6 +82,14 @@ void CheckLUtime(std::string clusfile = "o2clus_its.root", std::string dictfile nClusters++; int clEntry = rofRec.getFirstEntry() + icl; // entry of icl-th cluster of this ROF in the vector of clusters // do we read MC data? + + const auto& cluster = (*clusArr)[clEntry]; + + if (cluster.getPatternID() != CompCluster::InvalidPatternID) { + LOG(WARNING) << "Clusters have already been generated with a dictionary! Quitting"; + return; + } + auto rowSpan = *pattIdx++; auto columnSpan = *pattIdx++; int nBytes = (rowSpan * columnSpan) >> 3; diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index 7bc28be4c4d70..4318ed1155f7d 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -27,6 +27,7 @@ #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "DetectorsCommonDataFormats/NameConf.h" +#include "Framework/Logger.h" #include #endif @@ -42,6 +43,7 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", using o2::itsmft::BuildTopologyDictionary; using o2::itsmft::ClusterTopology; using o2::itsmft::CompClusterExt; + using o2::itsmft::CompCluster; using o2::itsmft::Hit; using ROFRec = o2::itsmft::ROFRecord; using MC2ROF = o2::itsmft::MC2ROFRecord; @@ -149,6 +151,11 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", const auto& cluster = (*clusArr)[clEntry]; + if (cluster.getPatternID() != CompCluster::InvalidPatternID) { + LOG(WARNING) << "Clusters have already been generated with a dictionary! Quitting"; + return; + } + ClusterTopology topology; o2::itsmft::ClusterPattern pattern(pattIdx); topology.setPattern(pattern); @@ -218,34 +225,36 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", TH1F* hNoise = nullptr; TH1F* hSignal = nullptr; - noiseDictionary.setThreshold(0.0001); - noiseDictionary.groupRareTopologies(); - noiseDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".bin")); - noiseDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".txt")); - noiseDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".root")); - signalDictionary.setThreshold(0.0001); - signalDictionary.groupRareTopologies(); - signalDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".bin")); - signalDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".txt")); - signalDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".root")); - cNoise = new TCanvas("cNoise", "Distribution of noise topologies"); - cNoise->cd(); - cNoise->SetLogy(); - o2::itsmft::TopologyDictionary::getTopologyDistribution(noiseDictionary.getDictionary(), hNoise, "hNoise"); - hNoise->SetDirectory(0); - hNoise->Draw("hist"); - histogramOutput.cd(); - hNoise->Write(); - cNoise->Write(); - cSignal = new TCanvas("cSignal", "cSignal"); - cSignal->cd(); - cSignal->SetLogy(); - o2::itsmft::TopologyDictionary::getTopologyDistribution(signalDictionary.getDictionary(), hSignal, "hSignal"); - hSignal->SetDirectory(0); - hSignal->Draw("hist"); - histogramOutput.cd(); - hSignal->Write(); - cSignal->Write(); - sw.Stop(); - sw.Print(); + if (clusLabArr) { + noiseDictionary.setThreshold(0.0001); + noiseDictionary.groupRareTopologies(); + noiseDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".bin")); + noiseDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".txt")); + noiseDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".root")); + signalDictionary.setThreshold(0.0001); + signalDictionary.groupRareTopologies(); + signalDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".bin")); + signalDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".txt")); + signalDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".root")); + cNoise = new TCanvas("cNoise", "Distribution of noise topologies"); + cNoise->cd(); + cNoise->SetLogy(); + o2::itsmft::TopologyDictionary::getTopologyDistribution(noiseDictionary.getDictionary(), hNoise, "hNoise"); + hNoise->SetDirectory(0); + hNoise->Draw("hist"); + histogramOutput.cd(); + hNoise->Write(); + cNoise->Write(); + cSignal = new TCanvas("cSignal", "cSignal"); + cSignal->cd(); + cSignal->SetLogy(); + o2::itsmft::TopologyDictionary::getTopologyDistribution(signalDictionary.getDictionary(), hSignal, "hSignal"); + hSignal->SetDirectory(0); + hSignal->Draw("hist"); + histogramOutput.cd(); + hSignal->Write(); + cSignal->Write(); + sw.Stop(); + sw.Print(); + } } diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index f7f67fe62c508..5b0fb440a072e 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -17,8 +17,6 @@ include(O2GetListOfMacros) # list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST - Detectors/ITSMFT/ITS/macros/EVE/rootlogon.C - Detectors/ITSMFT/ITS/macros/test/rootlogon.C Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C # temporary exclude until fix for full Clusters elimination Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C # temporary exclude until fix for full Clusters elimination Detectors/MUON/MCH/Simulation/macros/rootlogon.C From acbd0585fae3e50e47319d6938d7cf5a1d3041f6 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 30 Jun 2020 15:09:22 +0200 Subject: [PATCH 0020/1751] GPU: Tune parameters for NVIDIA Turing GPUs --- GPU/Common/GPUDefGPUParameters.h | 6 +++--- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 648711a132111..17e76172eaaff 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -93,8 +93,8 @@ #define GPUCA_LB_GPUTPCCFDecodeZS 64, 8 #define GPUCA_LB_GPUTPCCFGather 1024, 1 #define GPUCA_LB_GPUTPCGMMergerTrackFit 32, 8 - #define GPUCA_LB_GPUTPCGMMergerFollowLoopers 256, 1 - #define GPUCA_LB_GPUTPCGMMergerSliceRefit 64 + #define GPUCA_LB_GPUTPCGMMergerFollowLoopers 128, 4 + #define GPUCA_LB_GPUTPCGMMergerSliceRefit 64, 5 #define GPUCA_LB_GPUTPCGMMergerUnpackResetIds 256 #define GPUCA_LB_GPUTPCGMMergerUnpackGlobal 256 #define GPUCA_LB_GPUTPCGMMergerResolve_step0 256 @@ -109,7 +109,7 @@ #define GPUCA_LB_GPUTPCGMMergerMergeBorders_step2 256 #define GPUCA_LB_GPUTPCGMMergerMergeCE 256 #define GPUCA_LB_GPUTPCGMMergerLinkGlobalTracks 256 - #define GPUCA_LB_GPUTPCGMMergerCollect 256, 2 + #define GPUCA_LB_GPUTPCGMMergerCollect 128, 2 #define GPUCA_LB_GPUTPCGMMergerSortTracks 256 #define GPUCA_LB_GPUTPCGMMergerSortTracksQPt 256 #define GPUCA_LB_GPUTPCGMMergerSortTracksPrepare 256 diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 680438a7adcf2..1ad0c557b5689 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1970,7 +1970,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) runKernel(GetGridAuto(0), krnlRunRangeNone, krnlEventNone, -1); } if (param().rec.loopInterpolationInExtraPass) { - runKernel(GetGridBlk(Merger.NOutputTracks(), 0), krnlRunRangeNone, krnlEventNone); + runKernel(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); } if (doGPU && !doGPUall) { TransferMemoryResourcesToHost(RecoStep::TPCMerging, &Merger, 0); From df44fdffae79870b354fe301006881b9fecfa3a4 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 2 Jul 2020 09:54:49 +0200 Subject: [PATCH 0021/1751] GPU: Make inclusion of clusterizer in double-pipeline optional --- GPU/GPUTracking/Base/GPUSettings.cxx | 1 + GPU/GPUTracking/Base/GPUSettings.h | 1 + GPU/GPUTracking/Global/GPUChainTracking.cxx | 12 ++++++------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettings.cxx b/GPU/GPUTracking/Base/GPUSettings.cxx index 529cd9b008ed0..5b3cabcd1c482 100644 --- a/GPU/GPUTracking/Base/GPUSettings.cxx +++ b/GPU/GPUTracking/Base/GPUSettings.cxx @@ -114,4 +114,5 @@ void GPUSettingsDeviceProcessing::SetDefaults() tpccfGatherKernel = true; prefetchTPCpageScan = false; doublePipeline = false; + doublePipelineClusterizer = true; } diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index e34d721e3cfb0..2b637a9eed481 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -175,6 +175,7 @@ struct GPUSettingsDeviceProcessing { bool tpccfGatherKernel; // Use a kernel instead of the DMA engine to gather the clusters char prefetchTPCpageScan; // Prefetch headers during TPC page scan bool doublePipeline; // Use a double-pipeline driven by 2 threads + bool doublePipelineClusterizer; // Include the input data of the clusterizer in the double-pipeline }; } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 1ad0c557b5689..9c915ff37edc8 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1000,7 +1000,7 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) if (mRec->IsGPU()) { processorsShadow()->tpcClusterer[iSlice].SetNMaxDigits(processors()->tpcClusterer[iSlice].mPmemory->counters.nDigits, mCFContext->nPagesFragmentMax, nDigitsFragment[iSlice]); } - if (mPipelineNotifyCtx) { + if (mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { mPipelineNotifyCtx->rec->AllocateRegisteredForeignMemory(processors()->tpcClusterer[iSlice].mZSOffsetId, mRec); mPipelineNotifyCtx->rec->AllocateRegisteredForeignMemory(processors()->tpcClusterer[iSlice].mZSId, mRec); } else { @@ -1028,7 +1028,7 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) } } - if (mPipelineNotifyCtx) { + if (mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { mCFContext->ptrSave[iSlice].zsOffsetHost = processors()->tpcClusterer[iSlice].mPzsOffsets; mCFContext->ptrSave[iSlice].zsOffsetDevice = processorsShadow()->tpcClusterer[iSlice].mPzsOffsets; @@ -1048,7 +1048,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) mRec->PushNonPersistentMemory(); const auto& threadContext = GetThreadContext(); bool doGPU = GetRecoStepsGPU() & RecoStep::TPCClusterFinding; - if (RunTPCClusterizer_prepare(mPipelineNotifyCtx)) { + if (RunTPCClusterizer_prepare(mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer)) { return 1; } @@ -1059,7 +1059,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { SetupGPUProcessor(&processors()->tpcClusterer[iSlice], true); // Now we allocate } - if (mPipelineNotifyCtx) { + if (mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { RunTPCClusterizer_prepare(true); // Restore some pointers, allocated by the other pipeline, and set to 0 by SetupGPUProcessor (since not allocated in this pipeline) } @@ -2031,7 +2031,7 @@ int GPUChainTracking::RunTPCCompression() GPUTPCCompression& Compressor = processors()->tpcCompressor; GPUTPCCompression& CompressorShadow = doGPU ? processorsShadow()->tpcCompressor : Compressor; const auto& threadContext = GetThreadContext(); - if (mPipelineFinalizationCtx) { + if (mPipelineFinalizationCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { RecordMarker(&mEvents->single, 0); } Compressor.mNMaxClusterSliceRow = 0; @@ -2051,7 +2051,7 @@ int GPUChainTracking::RunTPCCompression() runKernel(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); runKernel(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); TransferMemoryResourcesToHost(myStep, &Compressor, 0); - if (mPipelineFinalizationCtx) { + if (mPipelineFinalizationCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { SynchronizeEvents(&mEvents->single); ReleaseEvent(&mEvents->single); ((GPUChainTracking*)GetNextChainInQueue())->RunTPCClusterizer_prepare(false); From b0dfab8267ca3d0150305e274cc4da20ac22281f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 2 Jul 2020 13:30:12 +0200 Subject: [PATCH 0022/1751] GPU: Move all time-frame related unique_ptrs into the iomemory struct --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 28 +++++++++---------- GPU/GPUTracking/Global/GPUChainTracking.h | 13 ++++----- GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 17 +++++------ 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 9c915ff37edc8..36eb67992ab53 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -610,8 +610,9 @@ void GPUChainTracking::AllocateIOMemory() AllocateIOMemoryHelper(mIOPtrs.nSliceTracks[i], mIOPtrs.sliceTracks[i], mIOMem.sliceTracks[i]); AllocateIOMemoryHelper(mIOPtrs.nSliceClusters[i], mIOPtrs.sliceClusters[i], mIOMem.sliceClusters[i]); } - AllocateIOMemoryHelper(mClusterNativeAccess->nClustersTotal, mClusterNativeAccess->clustersLinear, mIOMem.clustersNative); - mIOPtrs.clustersNative = mClusterNativeAccess->nClustersTotal ? mClusterNativeAccess.get() : nullptr; + AllocateIOMemoryHelper(mIOMem.clusterNativeAccess->nClustersTotal, mIOMem.clusterNativeAccess->clustersLinear, mIOMem.clustersNative); + mIOMem.clusterNativeAccess.reset(new ClusterNativeAccess); + mIOPtrs.clustersNative = mIOMem.clusterNativeAccess->nClustersTotal ? mIOMem.clusterNativeAccess.get() : nullptr; AllocateIOMemoryHelper(mIOPtrs.nMCLabelsTPC, mIOPtrs.mcLabelsTPC, mIOMem.mcLabelsTPC); AllocateIOMemoryHelper(mIOPtrs.nMCInfosTPC, mIOPtrs.mcInfosTPC, mIOMem.mcInfosTPC); AllocateIOMemoryHelper(mIOPtrs.nMergedTracks, mIOPtrs.mergedTracks, mIOMem.mergedTracks); @@ -672,11 +673,11 @@ int GPUChainTracking::ConvertNativeToClusterData() void GPUChainTracking::ConvertNativeToClusterDataLegacy() { - ClusterNativeAccess* tmp = mClusterNativeAccess.get(); + ClusterNativeAccess* tmp = mIOMem.clusterNativeAccess.get(); if (tmp != mIOPtrs.clustersNative) { *tmp = *mIOPtrs.clustersNative; } - GPUReconstructionConvert::ConvertNativeToClusterData(mClusterNativeAccess.get(), mIOMem.clusterData, mIOPtrs.nClusterData, processors()->calibObjects.fastTransform, param().continuousMaxTimeBin); + GPUReconstructionConvert::ConvertNativeToClusterData(mIOMem.clusterNativeAccess.get(), mIOMem.clusterData, mIOPtrs.nClusterData, processors()->calibObjects.fastTransform, param().continuousMaxTimeBin); for (unsigned int i = 0; i < NSLICES; i++) { mIOPtrs.clusterData[i] = mIOMem.clusterData[i].get(); if (GetDeviceProcessingSettings().registerStandaloneInputMemory) { @@ -691,7 +692,7 @@ void GPUChainTracking::ConvertNativeToClusterDataLegacy() void GPUChainTracking::ConvertRun2RawToNative() { - GPUReconstructionConvert::ConvertRun2RawToNative(*mClusterNativeAccess, mIOMem.clustersNative, mIOPtrs.rawClusters, mIOPtrs.nRawClusters); + GPUReconstructionConvert::ConvertRun2RawToNative(*mIOMem.clusterNativeAccess, mIOMem.clustersNative, mIOPtrs.rawClusters, mIOPtrs.nRawClusters); for (unsigned int i = 0; i < NSLICES; i++) { mIOPtrs.rawClusters[i] = nullptr; mIOPtrs.nRawClusters[i] = 0; @@ -700,9 +701,9 @@ void GPUChainTracking::ConvertRun2RawToNative() mIOPtrs.nClusterData[i] = 0; mIOMem.clusterData[i].reset(nullptr); } - mIOPtrs.clustersNative = mClusterNativeAccess.get(); + mIOPtrs.clustersNative = mIOMem.clusterNativeAccess.get(); if (GetDeviceProcessingSettings().registerStandaloneInputMemory) { - if (mRec->registerMemoryForGPU(mIOMem.clustersNative.get(), mClusterNativeAccess->nClustersTotal * sizeof(*mClusterNativeAccess->clustersLinear))) { + if (mRec->registerMemoryForGPU(mIOMem.clustersNative.get(), mIOMem.clusterNativeAccess->nClustersTotal * sizeof(*mIOMem.clusterNativeAccess->clustersLinear))) { throw std::runtime_error("Error registering memory for GPU"); } } @@ -711,12 +712,11 @@ void GPUChainTracking::ConvertRun2RawToNative() void GPUChainTracking::ConvertZSEncoder(bool zs12bit) { #ifdef HAVE_O2HEADERS - mTPCZSSizes.reset(new unsigned int[NSLICES * GPUTrackingInOutZS::NENDPOINTS]); - mTPCZSPtrs.reset(new void*[NSLICES * GPUTrackingInOutZS::NENDPOINTS]); - mTPCZS.reset(new GPUTrackingInOutZS); - GPUReconstructionConvert::RunZSEncoder(*mIOPtrs.tpcPackedDigits, &mTPCZSBuffer, mTPCZSSizes.get(), nullptr, nullptr, param(), zs12bit, true); - GPUReconstructionConvert::RunZSEncoderCreateMeta(mTPCZSBuffer.get(), mTPCZSSizes.get(), mTPCZSPtrs.get(), mTPCZS.get()); - mIOPtrs.tpcZS = mTPCZS.get(); + mIOMem.tpcZSmeta2.reset(new GPUTrackingInOutZS::GPUTrackingInOutZSMeta); + mIOMem.tpcZSmeta.reset(new GPUTrackingInOutZS); + GPUReconstructionConvert::RunZSEncoder(*mIOPtrs.tpcPackedDigits, &mIOMem.tpcZSpages, &mIOMem.tpcZSmeta2->n[0][0], nullptr, nullptr, param(), zs12bit, true); + GPUReconstructionConvert::RunZSEncoderCreateMeta(mIOMem.tpcZSpages.get(), &mIOMem.tpcZSmeta2->n[0][0], &mIOMem.tpcZSmeta2->ptr[0][0], mIOMem.tpcZSmeta.get()); + mIOPtrs.tpcZS = mIOMem.tpcZSmeta.get(); if (GetDeviceProcessingSettings().registerStandaloneInputMemory) { for (unsigned int i = 0; i < NSLICES; i++) { for (unsigned int j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { @@ -733,7 +733,7 @@ void GPUChainTracking::ConvertZSEncoder(bool zs12bit) void GPUChainTracking::ConvertZSFilter(bool zs12bit) { - GPUReconstructionConvert::RunZSFilter(mIOMem.tpcDigits, mIOPtrs.tpcPackedDigits->tpcDigits, mDigitMap->nTPCDigits, mIOPtrs.tpcPackedDigits->nTPCDigits, param(), zs12bit); + GPUReconstructionConvert::RunZSFilter(mIOMem.tpcDigits, mIOPtrs.tpcPackedDigits->tpcDigits, mIOMem.digitMap->nTPCDigits, mIOPtrs.tpcPackedDigits->nTPCDigits, param(), zs12bit); } void GPUChainTracking::LoadClusterErrors() { param().LoadClusterErrors(); } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 5780a331fd6a8..8321b224d429e 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -89,13 +89,16 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega InOutMemory(InOutMemory&&); InOutMemory& operator=(InOutMemory&&); - std::unique_ptr tpcZSpages; + std::unique_ptr tpcZSpages; + std::unique_ptr tpcZSpagesChar; // Same as above, but as char (needed for reading dumps, but deprecated, since alignment can be wrong) std::unique_ptr tpcZSmeta; std::unique_ptr tpcZSmeta2; std::unique_ptr tpcDigits[NSLICES]; + std::unique_ptr digitMap; std::unique_ptr clusterData[NSLICES]; std::unique_ptr rawClusters[NSLICES]; std::unique_ptr clustersNative; + std::unique_ptr clusterNativeAccess; std::unique_ptr sliceTracks[NSLICES]; std::unique_ptr sliceClusters[NSLICES]; std::unique_ptr mcLabelsTPC; @@ -227,13 +230,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega std::unique_ptr mMatLUTU; // Material Lookup Table std::unique_ptr mTRDGeometryU; // TRD Geometry - // Ptr to internal reconstruction data objects - std::unique_ptr mClusterNativeAccess; // Internal memory for clusterNativeAccess - std::unique_ptr mDigitMap; // Internal memory for digit-map, if needed - std::unique_ptr mTPCZSBuffer; // Memory to store TPC ZS pages - std::unique_ptr mTPCZSSizes; // Array with TPC ZS numbers of pages - std::unique_ptr mTPCZSPtrs; // Array with pointers to TPC ZS pages - std::unique_ptr mTPCZS; // TPC ZS Data Structure + std::unique_ptr mClusterNativeAccess; GPUOutputControl* mOutputCompressedClusters = nullptr; GPUOutputControl* mOutputClustersNative = nullptr; diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index d98debac29e6e..2e327e8e5e29f 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -150,19 +150,20 @@ int GPUChainTracking::ReadData(const char* filename) ReadData(fp, mIOPtrs.rawClusters, mIOPtrs.nRawClusters, mIOMem.rawClusters, InOutPointerType::RAW_CLUSTERS, ptrRawClusters); int nClustersTotal = 0; #ifdef HAVE_O2HEADERS - if (ReadData(fp, &mClusterNativeAccess->clustersLinear, &mClusterNativeAccess->nClustersTotal, &mIOMem.clustersNative, InOutPointerType::CLUSTERS_NATIVE)) { - r = fread(&mClusterNativeAccess->nClusters[0][0], sizeof(mClusterNativeAccess->nClusters[0][0]), NSLICES * GPUCA_ROW_COUNT, fp); - mClusterNativeAccess->setOffsetPtrs(); - mIOPtrs.clustersNative = mClusterNativeAccess.get(); + mIOMem.clusterNativeAccess.reset(new ClusterNativeAccess); + if (ReadData(fp, &mIOMem.clusterNativeAccess->clustersLinear, &mIOMem.clusterNativeAccess->nClustersTotal, &mIOMem.clustersNative, InOutPointerType::CLUSTERS_NATIVE)) { + r = fread(&mIOMem.clusterNativeAccess->nClusters[0][0], sizeof(mIOMem.clusterNativeAccess->nClusters[0][0]), NSLICES * GPUCA_ROW_COUNT, fp); + mIOMem.clusterNativeAccess->setOffsetPtrs(); + mIOPtrs.clustersNative = mIOMem.clusterNativeAccess.get(); } - mDigitMap.reset(new GPUTrackingInOutDigits); - if (ReadData(fp, mDigitMap->tpcDigits, mDigitMap->nTPCDigits, mIOMem.tpcDigits, InOutPointerType::TPC_DIGIT)) { - mIOPtrs.tpcPackedDigits = mDigitMap.get(); + mIOMem.digitMap.reset(new GPUTrackingInOutDigits); + if (ReadData(fp, mIOMem.digitMap->tpcDigits, mIOMem.digitMap->nTPCDigits, mIOMem.tpcDigits, InOutPointerType::TPC_DIGIT)) { + mIOPtrs.tpcPackedDigits = mIOMem.digitMap.get(); } const char* ptr; size_t total; char* ptrZSPages; - if (ReadData(fp, &ptr, &total, &mIOMem.tpcZSpages, InOutPointerType::TPC_ZS, &ptrZSPages)) { + if (ReadData(fp, &ptr, &total, &mIOMem.tpcZSpagesChar, InOutPointerType::TPC_ZS, &ptrZSPages)) { GPUTrackingInOutZS::GPUTrackingInOutZSCounts counts; r = fread(&counts, sizeof(counts), 1, fp); mIOMem.tpcZSmeta.reset(new GPUTrackingInOutZS); From 3a8c26bfbb350d9bbdf056c3583845a882eae9e3 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 2 Jul 2020 15:10:01 +0200 Subject: [PATCH 0023/1751] GPU: Add option to standalone benchmark to preload multiple events into host memory --- GPU/GPUTracking/Standalone/qconfigoptions.h | 1 + GPU/GPUTracking/Standalone/standalone.cxx | 285 +++++++++++--------- 2 files changed, 162 insertions(+), 124 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index 7800fa610e296..494ac73c11e04 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -181,6 +181,7 @@ AddOption(testSync, bool, false, "sync", 0, "Test settings for synchronous phase AddOption(timeFrameTime, bool, false, "tfTime", 0, "Print some debug information about time frame processing time") AddOption(controlProfiler, bool, false, "controlProfiler", 0, "Issues GPU profiler stop and start commands to profile only the relevant processing part") AddOption(alternateBorderSort, int, -1, "alternateBorderSort", 0, "Alternative implementation for sorting of border tracks") +AddOption(preloadEvents, bool, false, "preloadEvents", 0, "Preload events into host memory before start processing") AddHelp("help", 'h') AddHelpAll("helpall", 'H') AddSubConfig(structConfigTF, configTF) diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 629377b79eb81..d4553429f11ab 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -86,6 +86,9 @@ std::unique_ptr tf; int nEventsInDirectory = 0; std::atomic nIteration, nIterationEnd; +std::vector ioPtrEvents; +std::vector ioMemEvents; + void SetCPUAndOSSettings() { #ifdef FE_DFL_DISABLE_SSE_DENORMS_ENV // Flush and load denormals to zero in any case @@ -188,7 +191,7 @@ int ReadConfiguration(int argc, char** argv) printf("Cannot run asynchronous processing with double pipeline\n"); return 1; } - if (configStandalone.configProc.doublePipeline && (configStandalone.runs < 3 || !configStandalone.outputcontrolmem)) { + if (configStandalone.configProc.doublePipeline && (configStandalone.runs < 4 || !configStandalone.outputcontrolmem)) { printf("Double pipeline mode needs at least 3 runs per event and external output\n"); return 1; } @@ -535,7 +538,7 @@ int ReadEvent(int n) { char filename[256]; snprintf(filename, 256, "events/%s/" GPUCA_EVDUMP_FILE ".%d.dump", configStandalone.EventsDir, n); - if (configStandalone.inputcontrolmem) { + if (configStandalone.inputcontrolmem && !configStandalone.preloadEvents) { rec->SetInputControl(inputmemory.get(), configStandalone.inputcontrolmem); } int r = chainTracking->ReadData(filename); @@ -551,6 +554,65 @@ int ReadEvent(int n) return 0; } +int LoadEvent(int iEvent, int x) +{ + if (configStandalone.configTF.bunchSim) { + if (tf->LoadCreateTimeFrame(iEvent)) { + return 1; + } + } else if (configStandalone.configTF.nMerge) { + if (tf->LoadMergedEvents(iEvent)) { + return 1; + } + } else { + if (ReadEvent(iEvent)) { + return 1; + } + } + bool encodeZS = configStandalone.encodeZS == -1 ? (chainTracking->mIOPtrs.tpcPackedDigits && !chainTracking->mIOPtrs.tpcZS) : (bool)configStandalone.encodeZS; + bool zsFilter = configStandalone.zsFilter == -1 ? (!encodeZS && chainTracking->mIOPtrs.tpcPackedDigits) : (bool)configStandalone.zsFilter; + if (encodeZS || zsFilter) { + if (!chainTracking->mIOPtrs.tpcPackedDigits) { + printf("Need digit input to run ZS\n"); + return 1; + } + if (zsFilter) { + chainTracking->ConvertZSFilter(configStandalone.zs12bit); + } + if (encodeZS) { + chainTracking->ConvertZSEncoder(configStandalone.zs12bit); + } + } + if (!configStandalone.configRec.runTransformation) { + chainTracking->mIOPtrs.clustersNative = nullptr; + } else { + for (int i = 0; i < chainTracking->NSLICES; i++) { + if (chainTracking->mIOPtrs.rawClusters[i]) { + if (configStandalone.DebugLevel >= 2) { + printf("Converting Legacy Raw Cluster to Native\n"); + } + chainTracking->ConvertRun2RawToNative(); + break; + } + } + } + + if (configStandalone.stripDumpedEvents) { + if (chainTracking->mIOPtrs.tpcZS) { + chainTracking->mIOPtrs.tpcPackedDigits = nullptr; + } + } + + if (!rec->GetParam().earlyTpcTransform && chainTracking->mIOPtrs.clustersNative == nullptr && chainTracking->mIOPtrs.tpcPackedDigits == nullptr && chainTracking->mIOPtrs.tpcZS == nullptr) { + printf("Need cluster native data for on-the-fly TPC transform\n"); + return 1; + } + + ioPtrEvents[x] = chainTracking->mIOPtrs; + ioMemEvents[x] = std::move(chainTracking->mIOMem); + return 0; +} + void OutputStat(GPUChainTracking* t, long long int* nTracksTotal = nullptr, long long int* nClustersTotal = nullptr) { int nTracks = 0, nAttachedClusters = 0, nAttachedClustersFitted = 0, nAdjacentClusters = 0; @@ -586,7 +648,7 @@ void OutputStat(GPUChainTracking* t, long long int* nTracksTotal = nullptr, long printf("Output Tracks: %d (%d / %d / %d / %d clusters (fitted / attached / adjacent / total))%s\n", nTracks, nAttachedClustersFitted, nAttachedClusters, nAdjacentClusters, nCls, trdText); } -int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, int runs, const GPUTrackingInOutPointers& ioPtrs, long long int* nTracksTotal, long long int* nClustersTotal, int threadId = 0, HighResTimer* timerPipeline = nullptr) +int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, int runs, int iEvent, long long int* nTracksTotal, long long int* nClustersTotal, int threadId = 0, HighResTimer* timerPipeline = nullptr) { int iRun = 0, iteration = 0; while ((iteration = nIteration.fetch_add(1)) < runs) { @@ -601,8 +663,9 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, if (configStandalone.testSyncAsync) { printf("Running synchronous phase\n"); } + const GPUTrackingInOutPointers& ioPtrs = ioPtrEvents[!configStandalone.preloadEvents ? 0 : configStandalone.configProc.doublePipeline ? (iteration % ioPtrEvents.size()) : (iEvent - configStandalone.StartEvent)]; chainTrackingUse->mIOPtrs = ioPtrs; - if (iteration == (configStandalone.configProc.doublePipeline ? 1 : (configStandalone.runs - 1))) { + if (iteration == (configStandalone.configProc.doublePipeline ? 2 : (configStandalone.runs - 1))) { if (configStandalone.configProc.doublePipeline) { timerPipeline->Start(); } @@ -684,6 +747,7 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, if (configStandalone.configProc.doublePipeline) { recUse->ClearAllocatedMemory(); } + nIteration.store(runs); return 0; } @@ -770,86 +834,58 @@ int main(int argc, char** argv) if (configStandalone.eventGenerator) { genEvents::RunEventGenerator(chainTracking); - return 1; + return 0; + } + + int nEvents = configStandalone.NEvents; + if (configStandalone.configTF.bunchSim) { + nEvents = configStandalone.NEvents > 0 ? configStandalone.NEvents : 1; } else { - int nEvents = configStandalone.NEvents; - if (configStandalone.configTF.bunchSim) { - nEvents = configStandalone.NEvents > 0 ? configStandalone.NEvents : 1; - } else { - if (nEvents == -1 || nEvents > nEventsInDirectory) { - if (nEvents >= 0) { - printf("Only %d events available in directors %s (%d events requested)\n", nEventsInDirectory, configStandalone.EventsDir, nEvents); - } - nEvents = nEventsInDirectory; - } - if (configStandalone.configTF.nMerge > 1) { - nEvents /= configStandalone.configTF.nMerge; + if (nEvents == -1 || nEvents > nEventsInDirectory) { + if (nEvents >= 0) { + printf("Only %d events available in directors %s (%d events requested)\n", nEventsInDirectory, configStandalone.EventsDir, nEvents); } + nEvents = nEventsInDirectory; + } + if (configStandalone.configTF.nMerge > 1) { + nEvents /= configStandalone.configTF.nMerge; } + } - for (int iRun = 0; iRun < configStandalone.runs2; iRun++) { - if (configStandalone.configQA.inputHistogramsOnly) { - chainTracking->ForceInitQA(); - break; - } - if (configStandalone.runs2 > 1) { - printf("RUN2: %d\n", iRun); - } - long long int nTracksTotal = 0; - long long int nClustersTotal = 0; - int nEventsProcessed = 0; + ioPtrEvents.resize(configStandalone.preloadEvents ? (nEvents - configStandalone.StartEvent) : 1); + ioMemEvents.resize(configStandalone.preloadEvents ? (nEvents - configStandalone.StartEvent) : 1); + if (configStandalone.preloadEvents) { + printf("Preloading events"); + fflush(stdout); + for (int i = 0; i < nEvents - configStandalone.StartEvent; i++) { + LoadEvent(configStandalone.StartEvent + i, i); + printf(" %d", i); + fflush(stdout); + } + printf("\n"); + } - for (int iEvent = configStandalone.StartEvent; iEvent < nEvents; iEvent++) { - if (iEvent != configStandalone.StartEvent) { - printf("\n"); - } + for (int iRunOuter = 0; iRunOuter < configStandalone.runs2; iRunOuter++) { + if (configStandalone.configQA.inputHistogramsOnly) { + chainTracking->ForceInitQA(); + break; + } + if (configStandalone.runs2 > 1) { + printf("RUN2: %d\n", iRunOuter); + } + long long int nTracksTotal = 0; + long long int nClustersTotal = 0; + int nEventsProcessed = 0; + + for (int iEvent = configStandalone.StartEvent; iEvent < nEvents; iEvent++) { + if (iEvent != configStandalone.StartEvent) { + printf("\n"); + } + if (!configStandalone.preloadEvents) { HighResTimer timerLoad; timerLoad.Start(); - if (configStandalone.configTF.bunchSim) { - if (tf->LoadCreateTimeFrame(iEvent)) { - break; - } - } else if (configStandalone.configTF.nMerge) { - if (tf->LoadMergedEvents(iEvent)) { - break; - } - } else { - if (ReadEvent(iEvent)) { - break; - } - } - bool encodeZS = configStandalone.encodeZS == -1 ? (chainTracking->mIOPtrs.tpcPackedDigits && !chainTracking->mIOPtrs.tpcZS) : (bool)configStandalone.encodeZS; - bool zsFilter = configStandalone.zsFilter == -1 ? (!encodeZS && chainTracking->mIOPtrs.tpcPackedDigits) : (bool)configStandalone.zsFilter; - if (encodeZS || zsFilter) { - if (!chainTracking->mIOPtrs.tpcPackedDigits) { - printf("Need digit input to run ZS\n"); - goto breakrun; - } - if (zsFilter) { - chainTracking->ConvertZSFilter(configStandalone.zs12bit); - } - if (encodeZS) { - chainTracking->ConvertZSEncoder(configStandalone.zs12bit); - } - } - if (!configStandalone.configRec.runTransformation) { - chainTracking->mIOPtrs.clustersNative = nullptr; - } else { - for (int i = 0; i < chainTracking->NSLICES; i++) { - if (chainTracking->mIOPtrs.rawClusters[i]) { - if (configStandalone.DebugLevel >= 2) { - printf("Converting Legacy Raw Cluster to Native\n"); - } - chainTracking->ConvertRun2RawToNative(); - break; - } - } - } - - if (configStandalone.stripDumpedEvents) { - if (chainTracking->mIOPtrs.tpcZS) { - chainTracking->mIOPtrs.tpcPackedDigits = nullptr; - } + if (LoadEvent(iEvent, 0)) { + goto breakrun; } if (configStandalone.dumpEvents) { char fname[1024]; @@ -868,65 +904,66 @@ int main(int argc, char** argv) ev.continuousMaxTimeBin = chainTracking->mIOPtrs.tpcZS ? GPUReconstructionConvert::GetMaxTimeBin(*chainTracking->mIOPtrs.tpcZS) : chainTracking->mIOPtrs.tpcPackedDigits ? GPUReconstructionConvert::GetMaxTimeBin(*chainTracking->mIOPtrs.tpcPackedDigits) : GPUReconstructionConvert::GetMaxTimeBin(*chainTracking->mIOPtrs.clustersNative); printf("Max time bin set to %d\n", (int)ev.continuousMaxTimeBin); rec->UpdateEventSettings(&ev); + if (recAsync) { + recAsync->UpdateEventSettings(&ev); + } + if (recPipeline) { + recPipeline->UpdateEventSettings(&ev); + } } } - if (!rec->GetParam().earlyTpcTransform && chainTracking->mIOPtrs.clustersNative == nullptr && chainTracking->mIOPtrs.tpcPackedDigits == nullptr && chainTracking->mIOPtrs.tpcZS == nullptr) { - printf("Need cluster native data for on-the-fly TPC transform\n"); - goto breakrun; - } - printf("Loading time: %'d us\n", (int)(1000000 * timerLoad.GetCurrentElapsedTime())); + } + printf("Processing Event %d\n", iEvent); - printf("Processing Event %d\n", iEvent); - GPUTrackingInOutPointers ioPtrSave = chainTracking->mIOPtrs; - - nIteration.store(0); - nIterationEnd.store(0); - double pipelineWalltime = 1.; - if (configStandalone.configProc.doublePipeline) { - HighResTimer timerPipeline; - if (RunBenchmark(rec, chainTracking, 1, ioPtrSave, &nTracksTotal, &nClustersTotal)) { - goto breakrun; - } - nIteration.store(1); - nIterationEnd.store(1); - auto pipeline1 = std::async(std::launch::async, RunBenchmark, rec, chainTracking, configStandalone.runs, ioPtrSave, &nTracksTotal, &nClustersTotal, 0, &timerPipeline); - auto pipeline2 = std::async(std::launch::async, RunBenchmark, recPipeline, chainTrackingPipeline, configStandalone.runs, ioPtrSave, &nTracksTotal, &nClustersTotal, 1, &timerPipeline); - if (pipeline1.get() || pipeline2.get()) { - goto breakrun; - } - pipelineWalltime = timerPipeline.GetElapsedTime() / (configStandalone.runs - 1); - printf("Pipeline wall time: %f, %d iterations, %f per event\n", timerPipeline.GetElapsedTime(), configStandalone.runs - 1, pipelineWalltime); - } else { - if (RunBenchmark(rec, chainTracking, configStandalone.runs, ioPtrSave, &nTracksTotal, &nClustersTotal)) { - goto breakrun; - } + nIteration.store(0); + nIterationEnd.store(0); + double pipelineWalltime = 1.; + if (configStandalone.configProc.doublePipeline) { + HighResTimer timerPipeline; + if (RunBenchmark(rec, chainTracking, 1, iEvent, &nTracksTotal, &nClustersTotal) || RunBenchmark(recPipeline, chainTrackingPipeline, 2, iEvent, &nTracksTotal, &nClustersTotal)) { + goto breakrun; } - nEventsProcessed++; - - if (configStandalone.timeFrameTime) { - double nClusters = chainTracking->GetTPCMerger().NMaxClusters(); - if (nClusters > 0) { - double nClsPerTF = 550000. * 1138.3; - double timePerTF = (configStandalone.configProc.doublePipeline ? pipelineWalltime : ((configStandalone.DebugLevel ? rec->GetStatKernelTime() : rec->GetStatWallTime()) / 1000000.)) * nClsPerTF / nClusters; - double nGPUsReq = timePerTF / 0.02277; - char stat[1024]; - snprintf(stat, 1024, "Sync phase: %.2f sec per 256 orbit TF, %.1f GPUs required", timePerTF, nGPUsReq); - if (configStandalone.testSyncAsync) { - timePerTF = (configStandalone.DebugLevel ? recAsync->GetStatKernelTime() : recAsync->GetStatWallTime()) / 1000000. * nClsPerTF / nClusters; - snprintf(stat + strlen(stat), 1024 - strlen(stat), " - Async phase: %f sec per TF", timePerTF); - } - printf("%s (Measured %s time - Extrapolated from %d clusters to %d)\n", stat, configStandalone.DebugLevel ? "kernel" : "wall", (int)nClusters, (int)nClsPerTF); + auto pipeline1 = std::async(std::launch::async, RunBenchmark, rec, chainTracking, configStandalone.runs, iEvent, &nTracksTotal, &nClustersTotal, 0, &timerPipeline); + auto pipeline2 = std::async(std::launch::async, RunBenchmark, recPipeline, chainTrackingPipeline, configStandalone.runs, iEvent, &nTracksTotal, &nClustersTotal, 1, &timerPipeline); + if (pipeline1.get() || pipeline2.get()) { + goto breakrun; + } + pipelineWalltime = timerPipeline.GetElapsedTime() / (configStandalone.runs - 2); + printf("Pipeline wall time: %f, %d iterations, %f per event\n", timerPipeline.GetElapsedTime(), configStandalone.runs - 2, pipelineWalltime); + } else { + if (RunBenchmark(rec, chainTracking, configStandalone.runs, iEvent, &nTracksTotal, &nClustersTotal)) { + goto breakrun; + } + } + nEventsProcessed++; + + if (configStandalone.timeFrameTime) { + double nClusters = chainTracking->GetTPCMerger().NMaxClusters(); + if (nClusters > 0) { + double nClsPerTF = 550000. * 1138.3; + double timePerTF = (configStandalone.configProc.doublePipeline ? pipelineWalltime : ((configStandalone.DebugLevel ? rec->GetStatKernelTime() : rec->GetStatWallTime()) / 1000000.)) * nClsPerTF / nClusters; + double nGPUsReq = timePerTF / 0.02277; + char stat[1024]; + snprintf(stat, 1024, "Sync phase: %.2f sec per 256 orbit TF, %.1f GPUs required", timePerTF, nGPUsReq); + if (configStandalone.testSyncAsync) { + timePerTF = (configStandalone.DebugLevel ? recAsync->GetStatKernelTime() : recAsync->GetStatWallTime()) / 1000000. * nClsPerTF / nClusters; + snprintf(stat + strlen(stat), 1024 - strlen(stat), " - Async phase: %f sec per TF", timePerTF); } + printf("%s (Measured %s time - Extrapolated from %d clusters to %d)\n", stat, configStandalone.DebugLevel ? "kernel" : "wall", (int)nClusters, (int)nClsPerTF); } } - if (nEventsProcessed > 1) { - printf("Total: %lld clusters, %lld tracks\n", nClustersTotal, nTracksTotal); + + if (configStandalone.preloadEvents && configStandalone.configProc.doublePipeline) { + break; } } + if (nEventsProcessed > 1) { + printf("Total: %lld clusters, %lld tracks\n", nClustersTotal, nTracksTotal); + } } -breakrun: +breakrun: if (rec->GetDeviceProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { rec->PrintMemoryMax(); } From d31e3d84e64f668279cf96e71ac61e6198fabcc6 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 3 Jul 2020 14:44:21 +0200 Subject: [PATCH 0024/1751] GPU: Fix race condition in double pipeline (global ptr to clustersNative from previous TF overwritten while still in use) --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 21 ++++++++++++------- .../TPCClusterFinder/GPUTPCCFChainContext.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 36eb67992ab53..e43e98b31e633 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -956,6 +956,7 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) processorsShadow()->tpcClusterer[iSlice].mPzsOffsets = mCFContext->ptrSave[iSlice].zsOffsetDevice; processorsShadow()->tpcClusterer[iSlice].mPzs = mCFContext->ptrSave[iSlice].zsDevice; } + processorsShadow()->ioPtrs.clustersNative = mCFContext->ptrClusterNativeSave; return 0; } const auto& threadContext = GetThreadContext(); @@ -1021,10 +1022,9 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) GPUInfo("Event has %lld TPC Digits", (long long int)mRec->MemoryScalers()->nTPCdigits); } mCFContext->fragmentFirst = CfFragment{std::max(mCFContext->tpcMaxTimeBin + 1, TPC_MAX_FRAGMENT_LEN), TPC_MAX_FRAGMENT_LEN}; - for (int lane = 0; lane < GetDeviceProcessingSettings().nTPCClustererLanes && lane < NSLICES; lane++) { - unsigned int iSlice = lane; + for (int iSlice = 0; iSlice < GetDeviceProcessingSettings().nTPCClustererLanes && iSlice < NSLICES; iSlice++) { if (mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice]) { - mCFContext->nextPos[iSlice] = RunTPCClusterizer_transferZS(iSlice, mCFContext->fragmentFirst, GetDeviceProcessingSettings().nTPCClustererLanes + lane); + mCFContext->nextPos[iSlice] = RunTPCClusterizer_transferZS(iSlice, mCFContext->fragmentFirst, GetDeviceProcessingSettings().nTPCClustererLanes + iSlice); } } @@ -1334,6 +1334,14 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) tmpNative->setOffsetPtrs(); mIOPtrs.clustersNative = tmpNative; } + + if (mPipelineNotifyCtx) { + SynchronizeStream(mRec->NStreams() - 2); // Must finish before updating ioPtrs in (global) constant memory + std::lock_guard lock(mPipelineNotifyCtx->mutex); + mPipelineNotifyCtx->ready = true; + mPipelineNotifyCtx->cond.notify_one(); + } + if (buildNativeGPU) { processorsShadow()->ioPtrs.clustersNative = mInputsShadow->mPclusterNativeAccess; WriteToConstantMemory(RecoStep::TPCClusterFinding, (char*)&processors()->ioPtrs - (char*)processors(), &processorsShadow()->ioPtrs, sizeof(processorsShadow()->ioPtrs), 0); @@ -1354,13 +1362,9 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } mRec->MemoryScalers()->nTPCHits = nClsTotal; mRec->PopNonPersistentMemory(RecoStep::TPCClusterFinding); - if (mPipelineNotifyCtx) { - SynchronizeStream(mRec->NStreams() - 2); mRec->UnblockStackedMemory(); - std::lock_guard lock(mPipelineNotifyCtx->mutex); - mPipelineNotifyCtx->ready = true; - mPipelineNotifyCtx->cond.notify_one(); + mPipelineNotifyCtx = nullptr; } #endif @@ -2055,6 +2059,7 @@ int GPUChainTracking::RunTPCCompression() SynchronizeEvents(&mEvents->single); ReleaseEvent(&mEvents->single); ((GPUChainTracking*)GetNextChainInQueue())->RunTPCClusterizer_prepare(false); + ((GPUChainTracking*)GetNextChainInQueue())->mCFContext->ptrClusterNativeSave = processorsShadow()->ioPtrs.clustersNative; } SynchronizeStream(0); o2::tpc::CompressedClusters* O = Compressor.mOutput; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChainContext.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChainContext.h index 46500a63969ac..7a01918708164 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChainContext.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChainContext.h @@ -51,6 +51,7 @@ struct GPUTPCCFChainContext { CfFragment fragmentFirst; std::pair nextPos[GPUCA_NSLICES]; PtrSave ptrSave[GPUCA_NSLICES]; + const o2::tpc::ClusterNativeAccess* ptrClusterNativeSave; void prepare(bool tpcZS, const CfFragment& fragmentMax) { From 52aedc715ff94eb59ed133ed046bff71abcdf82d Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 3 Jul 2020 13:35:03 +0200 Subject: [PATCH 0025/1751] Eliminate obsolete options of raw-file-reader No need for options message-per-tf (must be always sent as a multipart of HBFs) and output-per-link (must be always sent per output_channel) --- Detectors/MUON/MCH/Workflow/README.md | 2 +- Detectors/MUON/MID/Workflow/README.md | 4 +- Detectors/Raw/README.md | 16 ++-- .../Raw/include/DetectorsRaw/RawFileReader.h | 2 +- Detectors/Raw/src/RawFileReaderWorkflow.cxx | 82 ++++++------------- Detectors/Raw/src/RawFileReaderWorkflow.h | 2 +- Detectors/Raw/src/rawfile-reader-workflow.cxx | 6 +- 7 files changed, 40 insertions(+), 74 deletions(-) diff --git a/Detectors/MUON/MCH/Workflow/README.md b/Detectors/MUON/MCH/Workflow/README.md index cae197321fb29..4fa24678409c0 100644 --- a/Detectors/MUON/MCH/Workflow/README.md +++ b/Detectors/MUON/MCH/Workflow/README.md @@ -18,7 +18,7 @@ ## Example of DPL chain: -`o2-raw-file-reader-workflow --conf file-reader.cfg --loop 0 --message-per-tf -b | o2-mch-raw-to-digits-workflow -b | o2-mch-digits-to-preclusters-workflow -b | o2-mch-preclusters-sink-workflow -b` +`o2-raw-file-reader-workflow --conf file-reader.cfg --loop 0 -b | o2-mch-raw-to-digits-workflow -b | o2-mch-digits-to-preclusters-workflow -b | o2-mch-preclusters-sink-workflow -b` where the `file-reader.cfg` looks like this: diff --git a/Detectors/MUON/MID/Workflow/README.md b/Detectors/MUON/MID/Workflow/README.md index 6ac5affc46b45..f980e6b61428f 100644 --- a/Detectors/MUON/MID/Workflow/README.md +++ b/Detectors/MUON/MID/Workflow/README.md @@ -33,7 +33,7 @@ Notice that the executable also generate a configuration file that is needed to ### Reconstruction from raw data To reconstruct the raw data (either from converted MC digits or real data), run: ```bash -o2-raw-file-reader-workflow --conf mid_raw.cfg --message-per-tf | o2-mid-reco-workflow +o2-raw-file-reader-workflow --conf mid_raw.cfg | o2-mid-reco-workflow ``` ## Timing @@ -44,4 +44,4 @@ An example output is the following: Processing time / 90 ROFs: full: 3.55542 us tracking: 2.02182 us ``` Two timing values are provided: one is for the full execution of the device (including retrieval and sending of the DPL messages) and one which concerns only the execution of the algorithm (the tracking algorithm in the above example) -The timing refers to the time needed to process one read-out-frame, i.e. one event. \ No newline at end of file +The timing refers to the time needed to process one read-out-frame, i.e. one event. diff --git a/Detectors/Raw/README.md b/Detectors/Raw/README.md index dfd756fc048b6..5acc3d60b2a72 100644 --- a/Detectors/Raw/README.md +++ b/Detectors/Raw/README.md @@ -230,6 +230,8 @@ dataOrigin = ITS #optional, if missing then default is used dataDescription = RAWDATA filePath = path_and_name_of_the_data_file0 +# for CRU detectors the "readoutCard" record below is optional +# readoutCard = CRU [input-1] dataOrigin = TPC @@ -238,6 +240,14 @@ filePath = path_and_name_of_the_data_file1 [input-2] filePath = path_and_name_of_the_data_file2 +[input-1-RORC] +dataOrigin = EMC +filePath = path_and_name_of_the_data_fileX +# for RORC detectors the record below is obligatory +readoutCard = RORC + + + #... # [input-XXX] blocks w/o filePath will be ignoder, XXX is irrelevant @@ -290,8 +300,6 @@ o2-raw-file-reader-workflow --loop arg (=1) loop N times (infinite for N<0) --min-tf arg (=0) min TF ID to process --max-tf arg (=4294967295) max TF ID to process - --message-per-tf send TF of each link as a single FMQ message rather than multipart with message per HB - --output-per-link send message per Link rather than per FMQ output route --delay arg (=0) delay in seconds between consecutive TFs sending --configKeyValues arg semicolon separated key=value strings @@ -315,10 +323,6 @@ If `--loop` argument is provided, data will be re-played in loop. The delay (in At every invocation of the device `processing` callback a full TimeFrame for every link will be added as N-HBFs parts (one for each HBF in the TF) to the multipart relayed by the `FairMQ` channel. -In case the `--message-per-tf` option is asked, the whole TF is sent as the only part of the `FairMQPart`. - -Instead of sending a single output (for multiple links) per output route (which means their data will be received together) one can request sending an output per link -by using option `--output-per-link`. The standard use case of this workflow is to provide the input for other worfklows using the piping, e.g. ```cpp diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index 79c2da6c7afa4..d5705907e4bca 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -92,7 +92,7 @@ class RawFileReader //================================================================================ using RDHAny = header::RDHAny; - using RDH = o2::header::RAWDataHeaderV4; + using RDH = o2::header::RAWDataHeader; using OrigDescCard = std::tuple; using InputsMap = std::map>; diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index 50852fd66d8f8..09cde324278e3 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -42,25 +42,18 @@ using namespace o2::raw; namespace o2f = o2::framework; namespace o2h = o2::header; -class rawReaderSpecs : public o2f::Task +class RawReaderSpecs : public o2f::Task { public: - explicit rawReaderSpecs(const std::string& config, bool tfAsMessage = false, bool outPerRoute = true, int loop = 1, uint32_t delay_us = 0, + explicit RawReaderSpecs(const std::string& config, int loop = 1, uint32_t delay_us = 0, uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t buffSize = 1024L * 1024L) - : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mHBFPerMessage(!tfAsMessage), mOutPerRoute(outPerRoute), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mReader(std::make_unique(config)) + : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mReader(std::make_unique(config)) { mReader->setCheckErrors(errmap); mReader->setMaxTFToRead(maxTF); mReader->setBufferSize(buffSize); LOG(INFO) << "Will preprocess files with buffer size of " << buffSize << " bytes"; LOG(INFO) << "Number of loops over whole data requested: " << mLoop; - if (mHBFPerMessage) { - LOG(INFO) << "Every link TF will be sent as multipart of HBF messages"; - } else { - LOG(INFO) << "HBF of single TF of each link will be sent as a single message"; - } - LOG(INFO) << "A message per " << (mOutPerRoute ? "route" : "link") << " will be sent"; - LOG(INFO) << "Delay of " << mDelayUSec << " microseconds will be added between TFs"; } void init(o2f::InitContext& ic) final @@ -103,10 +96,6 @@ class rawReaderSpecs : public o2f::Task int nlinks = mReader->getNLinks(); std::unordered_map> messagesPerRoute; - std::vector> messagesPerLink; - if (!mOutPerRoute) { - messagesPerLink.resize(nlinks); - } if (tfID > mMaxTFID) { if (mReader->getNTimeFrames() && --mLoop) { @@ -144,18 +133,18 @@ class rawReaderSpecs : public o2f::Task o2h::DataHeader hdrTmpl(link.description, link.origin, link.subspec); // template with 0 size int nhb = link.getNHBFinTF(); hdrTmpl.payloadSerializationMethod = o2h::gSerializationMethodNone; - hdrTmpl.splitPayloadParts = mHBFPerMessage ? nhb : 1; + hdrTmpl.splitPayloadParts = nhb; while (hdrTmpl.splitPayloadIndex < hdrTmpl.splitPayloadParts) { - tfSize += hdrTmpl.payloadSize = mHBFPerMessage ? link.getNextHBFSize() : link.getNextTFSize(); + tfSize += hdrTmpl.payloadSize = link.getNextHBFSize(); o2::header::Stack headerStack{hdrTmpl, o2::framework::DataProcessingHeader{mTFIDaccum}}; auto hdMessage = device->NewMessage(headerStack.size()); memcpy(hdMessage->GetData(), headerStack.data(), headerStack.size()); auto plMessage = device->NewMessage(hdrTmpl.payloadSize); - auto bread = mHBFPerMessage ? link.readNextHBF(reinterpret_cast(plMessage->GetData())) : link.readNextTF(reinterpret_cast(plMessage->GetData())); + auto bread = link.readNextHBF(reinterpret_cast(plMessage->GetData())); if (bread != hdrTmpl.payloadSize) { LOG(ERROR) << "Link " << il << " read " << bread << " bytes instead of " << hdrTmpl.payloadSize << " expected in TF=" << mTFIDaccum << " part=" << hdrTmpl.splitPayloadIndex; @@ -175,18 +164,10 @@ class rawReaderSpecs : public o2f::Task reinterpret_cast(hdMessage->GetData())->firstTForbit = hdrTmpl.firstTForbit; } FairMQParts* parts = nullptr; - if (mOutPerRoute) { - parts = messagesPerRoute[link.fairMQChannel].get(); // FairMQParts* - if (!parts) { - messagesPerRoute[link.fairMQChannel] = std::make_unique(); - parts = messagesPerRoute[link.fairMQChannel].get(); - } - } else { // message per link - parts = messagesPerLink[il].get(); // FairMQParts* - if (!parts) { - messagesPerLink[il] = std::make_unique(); - parts = messagesPerLink[il].get(); - } + parts = messagesPerRoute[link.fairMQChannel].get(); // FairMQParts* + if (!parts) { + messagesPerRoute[link.fairMQChannel] = std::make_unique(); + parts = messagesPerRoute[link.fairMQChannel].get(); } parts->AddPart(std::move(hdMessage)); parts->AddPart(std::move(plMessage)); @@ -201,24 +182,13 @@ class rawReaderSpecs : public o2f::Task usleep(mDelayUSec); } - if (mOutPerRoute) { - for (auto& msgIt : messagesPerRoute) { - LOG(INFO) << "Sending " << msgIt.second->Size() / 2 << " parts to channel " << msgIt.first; - device->Send(*msgIt.second.get(), msgIt.first); - } - } else { - for (int il = 0; il < nlinks; il++) { - auto& link = mReader->getLink(il); - auto* parts = messagesPerLink[il].get(); // FairMQParts* - if (parts) { - LOG(INFO) << "Sending " << parts->Size() / 2 << " parts to channel " << link.fairMQChannel << " for " << link.describe(); - device->Send(*parts, link.fairMQChannel); - } - } + for (auto& msgIt : messagesPerRoute) { + LOG(INFO) << "Sending " << msgIt.second->Size() / 2 << " parts to channel " << msgIt.first; + device->Send(*msgIt.second.get(), msgIt.first); } LOGF(INFO, "Sent payload of %zu bytes in %zu parts in %zu messages for TF %d", tfSize, tfNParts, - (mOutPerRoute ? messagesPerRoute.size() : messagesPerLink.size()), mTFIDaccum); + messagesPerRoute.size(), mTFIDaccum); sentSize += tfSize; sentMessages += tfNParts; @@ -240,38 +210,34 @@ class rawReaderSpecs : public o2f::Task uint32_t mDelayUSec = 0; // Delay in microseconds between TFs uint32_t mMinTFID = 0; // 1st TF to extract uint32_t mMaxTFID = 0xffffffff; // last TF to extrct - bool mHBFPerMessage = true; // true: send TF as multipart of HBFs, false: single message per TF - bool mOutPerRoute = true; // true: send 1 large output route, otherwise 1 outpur per link bool mDone = false; // processing is over or not std::unique_ptr mReader; // matching engine }; -o2f::DataProcessorSpec getReaderSpec(std::string config, bool tfAsMessage, bool outPerRoute, int loop, uint32_t delay_us, uint32_t errmap, +o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, size_t buffSize) { // check which inputs are present in files to read - o2f::Outputs outputs; + o2f::DataProcessorSpec spec; + spec.name = "raw-file-reader"; + if (!config.empty()) { auto conf = o2::raw::RawFileReader::parseInput(config); for (const auto& entry : conf) { const auto& ordescard = entry.first; if (!entry.second.empty()) { // origin and decription for files to process - outputs.emplace_back(o2f::OutputSpec(o2f::ConcreteDataTypeMatcher{std::get<0>(ordescard), std::get<1>(ordescard)})); + spec.outputs.emplace_back(o2f::OutputSpec(o2f::ConcreteDataTypeMatcher{std::get<0>(ordescard), std::get<1>(ordescard)})); } } } - return o2f::DataProcessorSpec{ - "raw-file-reader", - o2f::Inputs{}, - outputs, - o2f::AlgorithmSpec{o2f::adaptFromTask(config, tfAsMessage, outPerRoute, loop, delay_us, errmap, minTF, maxTF, buffSize)}, - o2f::Options{}}; + spec.algorithm = o2f::adaptFromTask(config, loop, delay_us, errmap, minTF, maxTF, buffSize); + + return spec; } -o2f::WorkflowSpec o2::raw::getRawFileReaderWorkflow(std::string inifile, bool tfAsMessage, bool outPerRoute, - int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, size_t buffSize) +o2f::WorkflowSpec o2::raw::getRawFileReaderWorkflow(std::string inifile, int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, size_t buffSize) { o2f::WorkflowSpec specs; - specs.emplace_back(getReaderSpec(inifile, tfAsMessage, outPerRoute, loop, delay_us, errmap, minTF, maxTF, buffSize)); + specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize)); return specs; } diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.h b/Detectors/Raw/src/RawFileReaderWorkflow.h index 7f1b201211a03..0ae9dbeecf252 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.h +++ b/Detectors/Raw/src/RawFileReaderWorkflow.h @@ -20,7 +20,7 @@ namespace o2 namespace raw { -framework::WorkflowSpec getRawFileReaderWorkflow(std::string inifile, bool tfAsMessage = false, bool outPerRoute = true, +framework::WorkflowSpec getRawFileReaderWorkflow(std::string inifile, int loop = 1, uint32_t delay_us = 0, uint32_t errMap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t bufferSize = 1024L * 1024L); diff --git a/Detectors/Raw/src/rawfile-reader-workflow.cxx b/Detectors/Raw/src/rawfile-reader-workflow.cxx index 956863d1ac46e..75c72fd1068c7 100644 --- a/Detectors/Raw/src/rawfile-reader-workflow.cxx +++ b/Detectors/Raw/src/rawfile-reader-workflow.cxx @@ -27,8 +27,6 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"min-tf", VariantType::Int64, 0L, {"min TF ID to process"}}); options.push_back(ConfigParamSpec{"max-tf", VariantType::Int64, 0xffffffffL, {"max TF ID to process"}}); options.push_back(ConfigParamSpec{"loop", VariantType::Int, 1, {"loop N times (infinite for N<0)"}}); - options.push_back(ConfigParamSpec{"message-per-tf", VariantType::Bool, false, {"send TF of each link as a single FMQ message rather than multipart with message per HB"}}); - options.push_back(ConfigParamSpec{"output-per-link", VariantType::Bool, false, {"send message per Link rather than per FMQ output route"}}); options.push_back(ConfigParamSpec{"delay", VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); options.push_back(ConfigParamSpec{"buffer-size", VariantType::Int64, 1024L * 1024L, {"buffer size for files preprocessing"}}); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}); @@ -52,8 +50,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) uint32_t maxTF = uint32_t(configcontext.options().get("max-tf")); uint32_t minTF = uint32_t(configcontext.options().get("min-tf")); uint64_t buffSize = uint64_t(configcontext.options().get("buffer-size")); - auto tfAsMessage = configcontext.options().get("message-per-tf"); - auto outPerRoute = !configcontext.options().get("output-per-link"); uint32_t errmap = 0; for (int i = RawFileReader::NErrorsDefined; i--;) { @@ -66,5 +62,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); uint32_t delay_us = uint32_t(1e6 * configcontext.options().get("delay")); // delay in microseconds - return std::move(o2::raw::getRawFileReaderWorkflow(inifile, tfAsMessage, outPerRoute, loop, delay_us, errmap, minTF, maxTF, buffSize)); + return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize)); } From f5940021a55a6ead24713665225055f11344a6c3 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 3 Jul 2020 21:00:01 +0200 Subject: [PATCH 0026/1751] raw-file-reader can send TF data to non-DPL FMQ channel provide e.g. --session default --raw-channel-config "name=raw-reader,type=push,method=bind,address=ipc://@rr-to-dpl,transport=shmem,rateLogging=1" --- Detectors/Raw/README.md | 12 +++++ Detectors/Raw/src/RawFileReaderWorkflow.cxx | 50 +++++++++++++------ Detectors/Raw/src/RawFileReaderWorkflow.h | 7 +-- Detectors/Raw/src/rawfile-reader-workflow.cxx | 5 +- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/Detectors/Raw/README.md b/Detectors/Raw/README.md index 5acc3d60b2a72..20b26467f49fa 100644 --- a/Detectors/Raw/README.md +++ b/Detectors/Raw/README.md @@ -301,6 +301,8 @@ o2-raw-file-reader-workflow --min-tf arg (=0) min TF ID to process --max-tf arg (=4294967295) max TF ID to process --delay arg (=0) delay in seconds between consecutive TFs sending + --buffer-size arg (=1048576) buffer size for files preprocessing + --raw-channel-config arg optional raw FMQ channel for non-DPL output --configKeyValues arg semicolon separated key=value strings # to suppress various error checks / reporting @@ -328,6 +330,16 @@ The standard use case of this workflow is to provide the input for other worfklo ```cpp o2-raw-file-reader-workflow --input-conf myConf.cfg | o2-dpl-raw-parser ``` +Option `--raw-channel-config forces the reader to send all data (single FairMQParts containing the whole TF) to raw FairMQ channel, emulating the messages from the DataDistribution. +To inject such a data to DPL one should use a parallel process starting with `o2-dpl-raw-proxy`. An example (note `--session default` added to every executable): + +```bash +[Terminal 1]> o2-dpl-raw-proxy --session default -b --dataspec "A:TOF/RAWDATA;B:ITS/RAWDATA;C:MFT/RAWDATA;D:TPC/RAWDATA;E:FT0/RAWDATA" --channel-config "name=readout-proxy,type=pull,method=connect,address=ipc://@rr-to-dpl,transport=shmem,rateLogging=1" | o2-dpl-raw-parser --session default --input-spec "A:TOF/RAWDATA;B:ITS/RAWDATA;C:MFT/RAWDATA;D:TPC/RAWDATA;E:FT0/RAWDATA" +``` + +```bash +[Terminal 2]> o2-raw-file-reader-workflow --session default --loop 1000 --delay 3 --input-conf raw/rawAll.cfg --raw-channel-config "name=raw-reader,type=push,method=bind,address=ipc://@rr-to-dpl,transport=shmem,rateLogging=1" --shm-segment-size 16000000000 +``` ## Raw data file checker (standalone executable) diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index 09cde324278e3..3717db7244a11 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -46,8 +46,8 @@ class RawReaderSpecs : public o2f::Task { public: explicit RawReaderSpecs(const std::string& config, int loop = 1, uint32_t delay_us = 0, - uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t buffSize = 1024L * 1024L) - : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mReader(std::make_unique(config)) + uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t buffSize = 1024L * 1024L, const std::string& rawChannelName = "") + : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mReader(std::make_unique(config)), mRawChannelName(rawChannelName) { mReader->setCheckErrors(errmap); mReader->setMaxTFToRead(maxTF); @@ -76,7 +76,11 @@ class RawReaderSpecs : public o2f::Task auto device = ctx.services().get().device(); assert(device); - auto findOutputChannel = [&ctx](RawFileReader::LinkData& link, size_t timeslice) { + auto findOutputChannel = [&ctx, this](RawFileReader::LinkData& link, size_t timeslice) { + if (!this->mRawChannelName.empty()) { + link.fairMQChannel = this->mRawChannelName; + return true; + } auto outputRoutes = ctx.services().get().spec().outputs; for (auto& oroute : outputRoutes) { LOG(DEBUG) << "comparing with matcher to route " << oroute.matcher << " TSlice:" << oroute.timeslice; @@ -211,33 +215,51 @@ class RawReaderSpecs : public o2f::Task uint32_t mMinTFID = 0; // 1st TF to extract uint32_t mMaxTFID = 0xffffffff; // last TF to extrct bool mDone = false; // processing is over or not + std::string mRawChannelName = ""; // name of optional non-DPL channel std::unique_ptr mReader; // matching engine }; o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t delay_us, uint32_t errmap, - uint32_t minTF, uint32_t maxTF, size_t buffSize) + uint32_t minTF, uint32_t maxTF, size_t buffSize, const std::string& rawChannelConfig) { // check which inputs are present in files to read o2f::DataProcessorSpec spec; spec.name = "raw-file-reader"; - - if (!config.empty()) { - auto conf = o2::raw::RawFileReader::parseInput(config); - for (const auto& entry : conf) { - const auto& ordescard = entry.first; - if (!entry.second.empty()) { // origin and decription for files to process - spec.outputs.emplace_back(o2f::OutputSpec(o2f::ConcreteDataTypeMatcher{std::get<0>(ordescard), std::get<1>(ordescard)})); + std::string rawChannelName = ""; + if (rawChannelConfig.empty()) { + if (!config.empty()) { + auto conf = o2::raw::RawFileReader::parseInput(config); + for (const auto& entry : conf) { + const auto& ordescard = entry.first; + if (!entry.second.empty()) { // origin and decription for files to process + spec.outputs.emplace_back(o2f::OutputSpec(o2f::ConcreteDataTypeMatcher{std::get<0>(ordescard), std::get<1>(ordescard)})); + } } } + } else { + auto nameStart = rawChannelConfig.find("name="); + if (nameStart == std::string::npos) { + throw std::runtime_error("raw channel name is not provided"); + } + nameStart += strlen("name="); + auto nameEnd = rawChannelConfig.find(",", nameStart + 1); + if (nameEnd == std::string::npos) { + nameEnd = rawChannelConfig.size(); + } + rawChannelName = rawChannelConfig.substr(nameStart, nameEnd - nameStart); + spec.options = {o2f::ConfigParamSpec{"channel-config", o2f::VariantType::String, rawChannelConfig, {"Out-of-band channel config"}}}; + LOG(INFO) << "Will send output to non-DPL channel " << rawChannelConfig; } - spec.algorithm = o2f::adaptFromTask(config, loop, delay_us, errmap, minTF, maxTF, buffSize); + + spec.algorithm = o2f::adaptFromTask(config, loop, delay_us, errmap, minTF, maxTF, buffSize, rawChannelName); return spec; } -o2f::WorkflowSpec o2::raw::getRawFileReaderWorkflow(std::string inifile, int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, size_t buffSize) +o2f::WorkflowSpec o2::raw::getRawFileReaderWorkflow(std::string inifile, int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, + size_t buffSize, const std::string& rawChannelConfig) { o2f::WorkflowSpec specs; - specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize)); + specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize, rawChannelConfig)); return specs; } diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.h b/Detectors/Raw/src/RawFileReaderWorkflow.h index 0ae9dbeecf252..6a62f4eeec98b 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.h +++ b/Detectors/Raw/src/RawFileReaderWorkflow.h @@ -14,15 +14,16 @@ /// @file RawFileReaderWorkflow.h #include "Framework/WorkflowSpec.h" +class string; namespace o2 { namespace raw { -framework::WorkflowSpec getRawFileReaderWorkflow(std::string inifile, - int loop = 1, uint32_t delay_us = 0, uint32_t errMap = 0xffffffff, - uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t bufferSize = 1024L * 1024L); +framework::WorkflowSpec getRawFileReaderWorkflow(std::string inifile, int loop = 1, uint32_t delay_us = 0, uint32_t errMap = 0xffffffff, + uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t bufferSize = 1024L * 1024L, + const std::string& rawChannelConfig = ""); } // namespace raw } // namespace o2 diff --git a/Detectors/Raw/src/rawfile-reader-workflow.cxx b/Detectors/Raw/src/rawfile-reader-workflow.cxx index 75c72fd1068c7..b8501184b5ba8 100644 --- a/Detectors/Raw/src/rawfile-reader-workflow.cxx +++ b/Detectors/Raw/src/rawfile-reader-workflow.cxx @@ -29,6 +29,7 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"loop", VariantType::Int, 1, {"loop N times (infinite for N<0)"}}); options.push_back(ConfigParamSpec{"delay", VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); options.push_back(ConfigParamSpec{"buffer-size", VariantType::Int64, 1024L * 1024L, {"buffer size for files preprocessing"}}); + options.push_back(ConfigParamSpec{"raw-channel-config", VariantType::String, "", {"optional raw FMQ channel for non-DPL output"}}); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}); // options for error-check suppression @@ -50,7 +51,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) uint32_t maxTF = uint32_t(configcontext.options().get("max-tf")); uint32_t minTF = uint32_t(configcontext.options().get("min-tf")); uint64_t buffSize = uint64_t(configcontext.options().get("buffer-size")); - + std::string rawChannelConfig = configcontext.options().get("raw-channel-config"); uint32_t errmap = 0; for (int i = RawFileReader::NErrorsDefined; i--;) { auto ei = RawFileReader::ErrTypes(i); @@ -62,5 +63,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); uint32_t delay_us = uint32_t(1e6 * configcontext.options().get("delay")); // delay in microseconds - return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize)); + return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize, rawChannelConfig)); } From 50f1f51530da9171dc390464d699136fea8c7f10 Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan Date: Sun, 5 Jul 2020 18:01:26 +0200 Subject: [PATCH 0027/1751] Account for timeslice in FMQ ChannelRetriever of ExternalFairMQDeviceProxy (#3943) Co-authored-by: shahoian --- .../Framework/ExternalFairMQDeviceProxy.h | 3 +- .../Core/src/ExternalFairMQDeviceProxy.cxx | 39 +++++++++++++------ .../test_ExternalFairMQDeviceWorkflow.cxx | 8 +++- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h b/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h index 305163c5138d8..45f22623ad0f4 100644 --- a/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h +++ b/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h @@ -21,9 +21,10 @@ namespace o2 { namespace framework { + /// A callback function to retrieve the FairMQChannel name to be used for sending /// messages of the specified OutputSpec -using ChannelRetriever = std::function; +using ChannelRetriever = std::function; using InjectorFunction = std::function; struct InputChannelSpec; diff --git a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx index 50ed80d7bcd42..cd76cdd6c391d 100644 --- a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx +++ b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx @@ -104,13 +104,13 @@ void sendOnChannel(FairMQDevice& device, FairMQParts& messages, std::string cons messages.fParts.clear(); } -void sendOnChannel(FairMQDevice& device, FairMQParts& messages, OutputSpec const& spec, ChannelRetriever& channelRetriever) +void sendOnChannel(FairMQDevice& device, FairMQParts& messages, OutputSpec const& spec, DataProcessingHeader::StartTime tslice, ChannelRetriever& channelRetriever) { // Note: DPL is only setting up one instance of a channel while FairMQ allows to have an // array of channels, the index is 0 in the call - auto channel = channelRetriever(spec); + auto channel = channelRetriever(spec, tslice); if (channel.empty()) { - LOG(WARNING) << "can not find matching channel for " << DataSpecUtils::describe(spec); + LOG(WARNING) << "can not find matching channel for " << DataSpecUtils::describe(spec) << " timeslice " << tslice; return; } sendOnChannel(device, messages, channel); @@ -118,7 +118,12 @@ void sendOnChannel(FairMQDevice& device, FairMQParts& messages, OutputSpec const void sendOnChannel(FairMQDevice& device, o2::header::Stack&& headerStack, FairMQMessagePtr&& payloadMessage, OutputSpec const& spec, ChannelRetriever& channelRetriever) { - auto channelName = channelRetriever(spec); + const auto* dph = o2::header::get(headerStack.data()); + if (!dph) { + LOG(ERROR) << "Header Stack does not follow the O2 data model, DataProcessingHeader missing"; + return; + } + auto channelName = channelRetriever(spec, dph->startTime); constexpr auto index = 0; if (channelName.empty()) { LOG(WARNING) << "can not find matching channel for " << DataSpecUtils::describe(spec); @@ -144,10 +149,17 @@ void sendOnChannel(FairMQDevice& device, o2::header::Stack&& headerStack, FairMQ void sendOnChannel(FairMQDevice& device, FairMQMessagePtr&& headerMessage, FairMQMessagePtr&& payloadMessage, OutputSpec const& spec, ChannelRetriever& channelRetriever) { + // const auto* dph = o2::header::get( *reinterpret_cast(headerMessage->GetData()) ); + const auto* dph = o2::header::get(headerMessage->GetData()); + if (!dph) { + LOG(ERROR) << "Header does not follow the O2 data model, DataProcessingHeader missing"; + return; + } + auto tslice = dph->startTime; FairMQParts out; out.AddPart(std::move(headerMessage)); out.AddPart(std::move(payloadMessage)); - sendOnChannel(device, out, spec, channelRetriever); + sendOnChannel(device, out, spec, tslice, channelRetriever); } InjectorFunction o2DataModelAdaptor(OutputSpec const& spec, uint64_t startTime, uint64_t step) @@ -211,20 +223,25 @@ InjectorFunction dplModelAdaptor(std::vector const& filterSpecs, boo continue; } - auto dh = o2::header::get(parts.At(msgidx * 2)->GetData()); + const auto dh = o2::header::get(parts.At(msgidx * 2)->GetData()); if (!dh) { LOG(ERROR) << "data on input " << msgidx << " does not follow the O2 data model, DataHeader missing"; continue; } + const auto dph = o2::header::get(parts.At(msgidx * 2)->GetData()); + if (!dph) { + LOG(ERROR) << "data on input " << msgidx << " does not follow the O2 data model, DataProcessingHeader missing"; + continue; + } LOG(DEBUG) << msgidx << ": " << DataSpecUtils::describe(OutputSpec{dh->dataOrigin, dh->dataDescription, dh->subSpecification}) << " part " << dh->splitPayloadIndex << " of " << dh->splitPayloadParts << " payload " << parts.At(msgidx * 2 + 1)->GetSize(); OutputSpec query{dh->dataOrigin, dh->dataDescription, dh->subSpecification}; - LOG(DEBUG) << "processing " << DataSpecUtils::describe(OutputSpec{dh->dataOrigin, dh->dataDescription, dh->subSpecification}) << " part " << dh->splitPayloadIndex << " of " << dh->splitPayloadParts; + LOG(DEBUG) << "processing " << DataSpecUtils::describe(OutputSpec{dh->dataOrigin, dh->dataDescription, dh->subSpecification}) << " time slice " << dph->startTime << " part " << dh->splitPayloadIndex << " of " << dh->splitPayloadParts; for (auto const& spec : filterSpecs) { // filter on the specified OutputSpecs, the default value is a ConcreteDataTypeMatcher with origin and description 'any' if (DataSpecUtils::match(spec, OutputSpec{{header::gDataOriginAny, header::gDataDescriptionAny}}) || DataSpecUtils::match(spec, query)) { - auto channelName = channelRetriever(query); + auto channelName = channelRetriever(query, dph->startTime); if (channelName.empty()) { LOG(WARNING) << "can not find matching channel, not able to adopt " << DataSpecUtils::describe(query); break; @@ -325,7 +342,7 @@ DataProcessorSpec specifyExternalFairMQDeviceProxy(char const* name, char const* defaultChannelConfig, std::function)> + ChannelRetriever)> converter) { DataProcessorSpec spec; @@ -356,10 +373,10 @@ DataProcessorSpec specifyExternalFairMQDeviceProxy(char const* name, // Converter should pump messages auto handler = [device, converter, outputRoutes = std::move(outputRoutes)](FairMQParts& inputs, int) { - auto channelRetriever = [outputRoutes = std::move(outputRoutes)](OutputSpec const& query) -> std::string { + auto channelRetriever = [outputRoutes = std::move(outputRoutes)](OutputSpec const& query, DataProcessingHeader::StartTime timeslice) -> std::string { for (auto& route : outputRoutes) { LOG(DEBUG) << "matching: " << DataSpecUtils::describe(query) << " to route " << DataSpecUtils::describe(route.matcher); - if (DataSpecUtils::match(route.matcher, query)) { + if (DataSpecUtils::match(route.matcher, query) && ((timeslice % route.maxTimeslices) == route.timeslice)) { return route.channel; } } diff --git a/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx b/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx index 0bf001a15f806..71b080c669d75 100644 --- a/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx +++ b/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx @@ -133,11 +133,15 @@ std::vector defineDataProcessing(ConfigContext const& config) LOG(ERROR) << "data on input " << msgidx << " does not follow the O2 data model, DataHeader missing"; return; } - + auto dph = o2::header::get(inputs.At(msgidx)->GetData()); + if (!dph) { + LOG(ERROR) << "data on input " << msgidx << " does not follow the O2 data model, DataProcessingHeader missing"; + return; + } // Note: we want to run both the output and input proxy in the same workflow and thus we need // different data identifiers and change the data origin in the forwarding OutputSpec query{"PRX", dh->dataDescription, dh->subSpecification}; - auto channelName = channelRetriever(query); + auto channelName = channelRetriever(query, dph->startTime); ASSERT_ERROR(!channelName.empty()); LOG(DEBUG) << "using channel '" << channelName << "' for " << DataSpecUtils::describe(OutputSpec{dh->dataOrigin, dh->dataDescription, dh->subSpecification}); if (channelName.empty()) { From 08291aeedca0cffa4ee4f110800876a5dfe9f187 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 5 Jul 2020 18:03:52 +0200 Subject: [PATCH 0028/1751] DPL: drop obsolete function (#3936) --- Framework/Core/src/DataProcessingDevice.cxx | 26 +-------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 541fd4286ce19..670e815811629 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -716,31 +716,6 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector Date: Sun, 5 Jul 2020 18:04:24 +0200 Subject: [PATCH 0029/1751] DPL: add support for Tracy profiler / debugger (#3932) Useful to debug multithreaded payloads and in general to have some insight about DPL. Requires AliceO2Group/DebugGUI > v0.2.0 and to pass -DDPL_ENABLE_TRACING. --- CMakeLists.txt | 4 + Framework/Core/src/DataProcessingDevice.cxx | 83 ++++++++++++++++--- .../Core/src/FrameworkGUIDeviceInspector.cxx | 9 ++ .../Foundation/include/Framework/Tracing.h | 43 ++++++++++ 4 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 Framework/Foundation/include/Framework/Tracing.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 616f9bb7b7872..891b0567293fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,10 @@ if (DPL_TESTS_BATCH_MODE) set(DPL_WORKFLOW_TESTS_EXTRA_OPTIONS -b) endif() +if (DPL_ENABLE_TRACING) + add_definitions(-DDPL_ENABLE_TRACING) +endif() + # include macros and functions that are used in the following subdirectories' # CMakeLists.txt include(O2AddExecutable) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 670e815811629..6f24a9ecda026 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -32,6 +32,12 @@ #include "ScopedExit.h" +#ifdef DPL_ENABLE_TRACING +#define TRACY_ENABLE +#include +#endif +#include + #include #include #include @@ -119,18 +125,22 @@ DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegist void on_socket_polled(uv_poll_t* poller, int status, int events) { switch (events) { - case UV_READABLE: + case UV_READABLE: { + ZoneScopedN("socket readable event"); LOG(debug) << "socket polled UV_READABLE: " << (char*)poller->data; - break; - case UV_WRITABLE: + } break; + case UV_WRITABLE: { + ZoneScopedN("socket writeable"); LOG(debug) << "socket polled UV_WRITEABLE"; - break; - case UV_DISCONNECT: + } break; + case UV_DISCONNECT: { + ZoneScopedN("socket disconnect"); LOG(debug) << "socket polled UV_DISCONNECT"; - break; - case UV_PRIORITIZED: + } break; + case UV_PRIORITIZED: { + ZoneScopedN("socket prioritized"); LOG(debug) << "socket polled UV_PRIORITIZED"; - break; + } break; } // We do nothing, all the logic for now stays in DataProcessingDevice::doRun() } @@ -144,6 +154,8 @@ void on_socket_polled(uv_poll_t* poller, int status, int events) /// * Invoke the actual init callback, which returns the processing callback. void DataProcessingDevice::Init() { + TracyAppInfo("foo", 3); + ZoneScopedN("DataProcessingDevice::Init"); mRelayer = &mServiceRegistry.get(); // For some reason passing rateLogging does not work anymore. // This makes sure we never have more than one notification per minute. @@ -231,6 +243,7 @@ void DataProcessingDevice::Init() void on_signal_callback(uv_signal_t* handle, int signum) { + ZoneScopedN("Signal callaback"); LOG(debug) << "Signal " << signum << "received." << std::endl; } @@ -343,15 +356,19 @@ bool DataProcessingDevice::ConditionalRun() // so that devices which do not have a timer can still start an // enumeration. if (mState.loop) { + ZoneScopedN("uv idle"); uv_run(mState.loop, mWasActive ? UV_RUN_NOWAIT : UV_RUN_ONCE); } - return DataProcessingDevice::doRun(); + auto result = DataProcessingDevice::doRun(); + FrameMark; + return result; } /// We drive the state loop ourself so that we will be able to support /// non-data triggers like those which are time based. bool DataProcessingDevice::doRun() { + ZoneScopedN("doRun"); /// This will send metrics for the relayer at regular intervals of /// 5 seconds, in order to avoid overloading the system. auto sendRelayerMetrics = [relayerStats = mRelayer->getStats(), @@ -363,6 +380,7 @@ bool DataProcessingDevice::doRun() if (currentTime - lastSent < 5000) { return; } + ZoneScopedN("send metrics"); auto& monitoring = registry.get(); O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::SEND, 0, 0, O2_SIGNPOST_BLUE); @@ -402,6 +420,7 @@ bool DataProcessingDevice::doRun() if (currentTime - lastFlushed < 1000) { return; } + ZoneScopedN("flush metrics"); auto& monitoring = registry.get(); O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); @@ -561,6 +580,7 @@ bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info auto getInputTypes = [& stats = mStats, &parts, &info]() -> std::optional> { stats.inputParts = parts.Size(); + TracyPlot("messages received", (int64_t)parts.Size()); if (parts.Size() % 2) { return std::nullopt; } @@ -585,7 +605,9 @@ bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info LOGP(error, "DataHeader payloadSize mismatch"); continue; } + TracyPlot("payload size", (int64_t)dh->payloadSize); auto dph = o2::header::get(parts.At(pi)->GetData()); + TracyAlloc(parts.At(pi + 1)->GetData(), parts.At(pi + 1)->GetSize()); if (!dph) { results[hi] = InputType::Invalid; LOGP(error, "Header stack does not contain DataProcessingHeader"); @@ -744,11 +766,34 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector(input.header); + if (sih) { + continue; + } + + auto dh = o2::header::get(input.header); + if (!dh) { + continue; + } + TracyFree(input.payload); + } + }; + // This is how we do the forwarding, i.e. we push // the inputs which are shared between this device and others // to the next one in the daisy chain. // FIXME: do it in a smarter way than O(N^2) auto forwardInputs = [&reportError, &forwards, &device, ¤tSetOfInputs](TimesliceSlot slot, InputRecord& record) { + ZoneScopedN("forward inputs"); assert(record.size() == currentSetOfInputs.size()); // we collect all messages per forward in a map and send them together std::unordered_map forwardedParts; @@ -864,8 +909,11 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector) +#define DPL_HAS_TRACING +#include +#else +#define ZoneScoped \ + while (false) { \ + } +#define FrameMark \ + while (false) { \ + } +#define TracyPlot(...) \ + while (false) { \ + } +#define ZoneScopedN(...) \ + while (false) { \ + } +#define ZoneScopedNS(...) \ + while (false) { \ + } +#define TracyAlloc(...) \ + while (false) { \ + } +#define TracyFree(...) \ + while (false) { \ + } +#define TracyAppInfo(...) \ + while (false) { \ + } +#endif + +#endif // O2_FRAMEWORK_TRACING_H_ From 819699279cfa435387c31f334881892005bcecf3 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Mon, 6 Jul 2020 00:36:31 +0200 Subject: [PATCH 0030/1751] DPL Analysis: implementation of expression columns with new functions (#3930) --- Analysis/Tasks/correlationsCollection.cxx | 20 ++++---- Analysis/Tasks/jetfinder.cxx | 6 +-- Analysis/Tutorials/src/filters.cxx | 29 +++++------- Analysis/Tutorials/src/histograms.cxx | 6 +-- .../include/Framework/AnalysisDataModel.h | 31 ++++++------ Framework/Core/include/Framework/BasicOps.h | 7 +++ .../Core/include/Framework/Expressions.h | 47 +++++++++++++++++++ Framework/Core/src/ExpressionHelpers.h | 17 +++++-- Framework/Core/src/Expressions.cxx | 2 +- .../Core/test/test_AnalysisDataModel.cxx | 10 ++-- Framework/Core/test/test_Expressions.cxx | 16 +++---- 11 files changed, 122 insertions(+), 69 deletions(-) diff --git a/Analysis/Tasks/correlationsCollection.cxx b/Analysis/Tasks/correlationsCollection.cxx index f53fa25b68d3e..fb61687e217a3 100644 --- a/Analysis/Tasks/correlationsCollection.cxx +++ b/Analysis/Tasks/correlationsCollection.cxx @@ -166,7 +166,7 @@ struct CorrelationTask { //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta2(), track1.phi(), track1.phi2(), track1.pt(), track1.pt2()); double eventValues[3]; - eventValues[0] = track1.pt2(); + eventValues[0] = track1.pt(); eventValues[1] = collision.centV0M(); eventValues[2] = collision.posZ(); @@ -195,8 +195,8 @@ struct CorrelationTask { double values[6] = {0}; values[0] = track1.etam() - track2.etam(); - values[1] = track1.pt2(); - values[2] = track2.pt2(); + values[1] = track1.pt(); + values[2] = track2.pt(); values[3] = collision.centV0M(); values[4] = track1.phim() - track2.phim(); @@ -228,7 +228,7 @@ struct CorrelationTask { // LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta2(), track1.phi(), track1.phi2(), track1.pt(), track1.pt2()); double eventValues[3]; - eventValues[0] = track1.pt2(); + eventValues[0] = track1.pt(); eventValues[1] = 0; // collision.v0mult(); eventValues[2] = collision.posZ(); @@ -255,8 +255,8 @@ struct CorrelationTask { double values[6] = {0}; values[0] = track1.etam() - track2.etam(); - values[1] = track1.pt2(); - values[2] = track2.pt2(); + values[1] = track1.pt(); + values[2] = track2.pt(); values[3] = 0; // collision.v0mult(); values[4] = track1.phim() - track2.phim(); @@ -372,8 +372,8 @@ struct CorrelationTask { tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); } - float e1squ = m0_1 * m0_1 + track1.pt2() * track1.pt2() * (1.0 + 1.0 / tantheta1 / tantheta1); - float e2squ = m0_2 * m0_2 + track2.pt2() * track2.pt2() * (1.0 + 1.0 / tantheta2 / tantheta2); + float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.ptm() * track2.ptm() * (TMath::Cos(track1.phim() - track2.phim()) + 1.0 / tantheta1 / tantheta2))); @@ -462,14 +462,14 @@ struct CorrelationTask { } } - qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt2() - track2.pt2())); + qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); if (dphistarminabs < cfgTwoTrackCut && TMath::Abs(deta) < cfgTwoTrackCut) { //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt2(), track1.charge(), track2.phi2(), track2.pt2(), track2.charge(), bSign); return true; } - qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt2() - track2.pt2())); + qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); } } diff --git a/Analysis/Tasks/jetfinder.cxx b/Analysis/Tasks/jetfinder.cxx index 9959d0cd407c5..7145cd58541c0 100644 --- a/Analysis/Tasks/jetfinder.cxx +++ b/Analysis/Tasks/jetfinder.cxx @@ -64,11 +64,9 @@ struct JetFinderTask { fastjet::AreaDefinition areaDefBkg{areaType, ghostSpec}; fastjet::Selector selBkg = fastjet::SelectorAbsRapMax(rapBkg); - // TODO: use abs, eventually use pt // TODO: use values from configurables // TODO: add eta cuts - Filter trackCuts = (aod::track::signed1Pt < 10.f) && - (aod::track::signed1Pt > -10.f); + Filter trackCuts = aod::track::pt > 0.1f; std::unique_ptr bge; std::unique_ptr sub; @@ -96,7 +94,7 @@ struct JetFinderTask { std::vector inputParticles; for (auto& track : fullTracks) { - auto energy = std::sqrt(track.p2() + mPionSquared); + auto energy = std::sqrt(track.p() * track.p() + mPionSquared); inputParticles.emplace_back(track.px(), track.py(), track.pz(), energy); inputParticles.back().set_user_index(track.globalIndex()); } diff --git a/Analysis/Tutorials/src/filters.cxx b/Analysis/Tutorials/src/filters.cxx index 1b5ea6bdae3f2..186373ef34a6c 100644 --- a/Analysis/Tutorials/src/filters.cxx +++ b/Analysis/Tutorials/src/filters.cxx @@ -15,11 +15,10 @@ namespace o2::aod { namespace etaphi { -DECLARE_SOA_COLUMN(Eta, eta2, float); -DECLARE_SOA_COLUMN(Phi, phi2, float); +DECLARE_SOA_COLUMN(NPhi, nphi, float); } // namespace etaphi -DECLARE_SOA_TABLE(EtaPhi, "AOD", "ETAPHI", - etaphi::Eta, etaphi::Phi); +DECLARE_SOA_TABLE(TPhi, "AOD", "ETAPHI", + etaphi::NPhi); } // namespace o2::aod using namespace o2; @@ -31,12 +30,12 @@ using namespace o2::framework::expressions; // FIXME: this should really inherit from AnalysisTask but // we need GCC 7.4+ for that struct ATask { - Produces etaphi; + Produces etaphi; void process(aod::Tracks const& tracks) { for (auto& track : tracks) { - etaphi(track.eta(), track.phi()); + etaphi(track.phi()); } } }; @@ -45,24 +44,22 @@ struct BTask { float fPI = static_cast(M_PI); float ptlow = 0.5f; float ptup = 2.0f; - Filter ptFilter_a = aod::track::pt2 > (ptlow * ptlow); - Filter ptFilter_b = aod::track::pt2 < (ptup * ptup); + Filter ptFilter_a = aod::track::pt > ptlow; + Filter ptFilter_b = aod::track::pt < ptup; - // Filter ptFilter = ((aod::track::signed1Pt < 1.0f / ptlow) && (aod::track::signed1Pt > 1.0f / ptup)) || ((aod::track::signed1Pt < -1.0f / ptup) && (aod::track::signed1Pt < -1.0f / ptlow)); float etalow = -1.0f; float etaup = 1.0f; - Filter etafilter = (aod::etaphi::eta2 < etaup) && (aod::etaphi::eta2 > etalow); + Filter etafilter = (aod::track::eta < etaup) && (aod::track::eta > etalow); - // Filter etaFilter = (aod::track::tgl < tan(0.5f * fPI - 2.0f * atan(exp(etalow)))) && (aod::track::tgl > tan(0.5f * fPI - 2.0f * atan(exp(etaup)))); float philow = 1.0f; float phiup = 2.0f; - Filter phifilter = (aod::etaphi::phi2 < phiup) && (aod::etaphi::phi2 > philow); + Filter phifilter = (aod::etaphi::nphi < phiup) && (aod::etaphi::nphi > philow); - void process(aod::Collision const& collision, soa::Filtered> const& tracks) + void process(aod::Collision const& collision, soa::Filtered> const& tracks) { LOGF(INFO, "Collision: %d [N = %d]", collision.globalIndex(), tracks.size()); for (auto& track : tracks) { - LOGF(INFO, "id = %d; eta: %.3f < %.3f < %.3f; phi: %.3f < %.3f < %.3f; pt: %.3f < %.3f < %.3f", track.collisionId(), etalow, track.eta2(), etaup, philow, track.phi2(), phiup, ptlow, track.pt(), ptup); + LOGF(INFO, "id = %d; eta: %.3f < %.3f < %.3f; phi: %.3f < %.3f < %.3f; pt: %.3f < %.3f < %.3f", track.collisionId(), etalow, track.eta(), etaup, philow, track.nphi(), phiup, ptlow, track.pt(), ptup); } } }; @@ -70,6 +67,6 @@ struct BTask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask("produce-etaphi"), - adaptAnalysisTask("consume-etaphi")}; + adaptAnalysisTask("produce-normalizedphi"), + adaptAnalysisTask("consume-normalizedphi")}; } diff --git a/Analysis/Tutorials/src/histograms.cxx b/Analysis/Tutorials/src/histograms.cxx index 17a4efa2e9151..01b775f85c426 100644 --- a/Analysis/Tutorials/src/histograms.cxx +++ b/Analysis/Tutorials/src/histograms.cxx @@ -70,9 +70,9 @@ struct CTask { void process(aod::Tracks const& tracks) { for (auto& track : tracks) { - if (track.pt2() < pTCut * pTCut) + if (track.pt() < pTCut) continue; - ptH->Fill(std::sqrt(track.pt2())); + ptH->Fill(track.pt()); trZ->Fill(track.z()); } } @@ -93,7 +93,7 @@ struct DTask { auto pHist = dynamic_cast(list->At(0)); auto etaHist = dynamic_cast(list->At(1)); - pHist->Fill(std::sqrt(track.p2())); + pHist->Fill(track.p()); etaHist->Fill(track.eta()); } }; diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 0c372371666db..684d62446c95a 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -83,17 +83,20 @@ DECLARE_SOA_COLUMN(Z, z, float); DECLARE_SOA_COLUMN(Snp, snp, float); DECLARE_SOA_COLUMN(Tgl, tgl, float); DECLARE_SOA_COLUMN(Signed1Pt, signed1Pt, float); -DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float snp, float alpha) -> float { - float phi = std::asin(snp) + alpha; - constexpr float twopi = 2.0 * M_PI; +DECLARE_SOA_EXPRESSION_COLUMN(RawPhi, phiraw, float, nasin(aod::track::snp) + aod::track::alpha); +// FIXME: dynamic column pending inclusion of conditional nodes +DECLARE_SOA_DYNAMIC_COLUMN(NormalizedPhi, phi, [](float phi) -> float { + constexpr float twopi = 2.0f * static_cast(M_PI); if (phi < 0) phi += twopi; if (phi > twopi) phi -= twopi; return phi; }); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float tgl) -> float { return std::log(std::tan(0.25f * static_cast(M_PI) - 0.5f * std::atan(tgl))); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float signed1Pt) -> float { return std::abs(1.0f / signed1Pt); }); +// FIXME: have float constants like pi defined somewhere +DECLARE_SOA_EXPRESSION_COLUMN(Eta, eta, float, nlog(ntan(0.25f * static_cast(M_PI) - 0.5f * natan(aod::track::tgl)))); +DECLARE_SOA_EXPRESSION_COLUMN(Pt, pt, float, nabs(1.f / aod::track::signed1Pt)); + DECLARE_SOA_DYNAMIC_COLUMN(Charge, charge, [](float signed1Pt) -> short { return (signed1Pt > 0) ? 1 : -1; }); DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float signed1Pt, float snp, float alpha) -> float { auto pt = 1.f / std::abs(signed1Pt); @@ -113,12 +116,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float signed1Pt, float tgl) -> float { auto pt = 1.f / std::abs(signed1Pt); return pt * tgl; }); -DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float signed1Pt, float tgl) -> float { - return std::sqrt(1.f + tgl * tgl) / std::abs(signed1Pt); -}); -DECLARE_SOA_EXPRESSION_COLUMN(P2, p2, float, (1.f + aod::track::tgl * aod::track::tgl) / (aod::track::signed1Pt * aod::track::signed1Pt)); -DECLARE_SOA_EXPRESSION_COLUMN(Pt2, pt2, float, (1.f / aod::track::signed1Pt) * (1.f / aod::track::signed1Pt)); +DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, nsqrt((1.f + aod::track::tgl * aod::track::tgl) / nabs(aod::track::signed1Pt))); // TRACKPARCOV TABLE definition DECLARE_SOA_COLUMN(SigmaY, sigmaY, float); @@ -202,17 +201,17 @@ DECLARE_SOA_TABLE_FULL(StoredTracks, "Tracks", "AOD", "TRACKPAR", track::X, track::Alpha, track::Y, track::Z, track::Snp, track::Tgl, track::Signed1Pt, - track::Phi, - track::Eta, - track::Pt, + track::NormalizedPhi, track::Px, track::Py, track::Pz, - track::P, track::Charge); -DECLARE_SOA_EXTENDED_TABLE(Tracks, StoredTracks, "TRACKPAR", aod::track::Pt2, - aod::track::P2); +DECLARE_SOA_EXTENDED_TABLE(Tracks, StoredTracks, "TRACKPAR", + aod::track::Pt, + aod::track::P, + aod::track::Eta, + aod::track::RawPhi); DECLARE_SOA_TABLE_FULL(StoredTracksCov, "TracksCov", "AOD", "TRACKPARCOV", track::SigmaY, track::SigmaZ, track::SigmaSnp, track::SigmaTgl, track::Sigma1Pt, diff --git a/Framework/Core/include/Framework/BasicOps.h b/Framework/Core/include/Framework/BasicOps.h index 29ba6ad29907e..f6bbc0ebe4f08 100644 --- a/Framework/Core/include/Framework/BasicOps.h +++ b/Framework/Core/include/Framework/BasicOps.h @@ -26,9 +26,16 @@ enum BasicOp : unsigned int { Equal, NotEqual, Power, + Sqrt, Exp, Log, Log10, + Sin, + Cos, + Tan, + Asin, + Acos, + Atan, Abs }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index fe8681c283da5..d883155768f21 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -301,6 +301,18 @@ inline Node operator+(T left, Node right) return Node{OpNode{BasicOp::Addition}, LiteralNode{left}, std::move(right)}; } +template <> +inline Node operator+(Node left, BindingNode right) +{ + return Node{OpNode{BasicOp::Addition}, std::move(left), right}; +} + +template <> +inline Node operator+(BindingNode left, Node right) +{ + return Node{OpNode{BasicOp::Addition}, left, std::move(right)}; +} + template inline Node operator-(Node left, T right) { @@ -320,6 +332,11 @@ inline Node npow(Node left, T right) } /// unary operations on nodes +inline Node nsqrt(Node left) +{ + return Node{OpNode{BasicOp::Sqrt}, std::move(left)}; +} + inline Node nexp(Node left) { return Node{OpNode{BasicOp::Exp}, std::move(left)}; @@ -340,6 +357,36 @@ inline Node nabs(Node left) return Node{OpNode{BasicOp::Abs}, std::move(left)}; } +inline Node nsin(Node left) +{ + return Node{OpNode{BasicOp::Sin}, std::move(left)}; +} + +inline Node ncos(Node left) +{ + return Node{OpNode{BasicOp::Cos}, std::move(left)}; +} + +inline Node ntan(Node left) +{ + return Node{OpNode{BasicOp::Tan}, std::move(left)}; +} + +inline Node nasin(Node left) +{ + return Node{OpNode{BasicOp::Asin}, std::move(left)}; +} + +inline Node nacos(Node left) +{ + return Node{OpNode{BasicOp::Acos}, std::move(left)}; +} + +inline Node natan(Node left) +{ + return Node{OpNode{BasicOp::Atan}, std::move(left)}; +} + /// A struct, containing the root of the expression tree struct Filter { Filter(Node&& node_) : node{std::make_unique(std::move(node_))} {} diff --git a/Framework/Core/src/ExpressionHelpers.h b/Framework/Core/src/ExpressionHelpers.h index 44bf582808323..d42adc77b0f35 100644 --- a/Framework/Core/src/ExpressionHelpers.h +++ b/Framework/Core/src/ExpressionHelpers.h @@ -32,11 +32,18 @@ static std::array binaryOperationsMap = { "greater_than_or_equal_to", "equal", "not_equal", - "power", - "exp", - "log", - "log10", - "abs"}; + "powerf", + "sqrtf", + "expf", + "logf", + "log10f", + "sinf", + "cosf", + "tanf", + "asinf", + "acosf", + "atanf", + "absf"}; struct DatumSpec { /// datum spec either contains an index, a value of a literal or a binding label diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 5204caab15a52..5e6457ea7e22b 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -433,7 +433,7 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, tree = gandiva::TreeExprBuilder::MakeAnd({leftNode, rightNode}); break; default: - if (it->op < BasicOp::Exp) { + if (it->op < BasicOp::Sqrt) { if (it->type != atype::BOOL) { leftNode = insertUpcastNode(leftNode, it->left.type); rightNode = insertUpcastNode(rightNode, it->right.type); diff --git a/Framework/Core/test/test_AnalysisDataModel.cxx b/Framework/Core/test/test_AnalysisDataModel.cxx index f458bdadcc524..c517d571875bd 100644 --- a/Framework/Core/test/test_AnalysisDataModel.cxx +++ b/Framework/Core/test/test_AnalysisDataModel.cxx @@ -28,8 +28,10 @@ using namespace o2::aod; BOOST_AUTO_TEST_CASE(TestJoinedTables) { TableBuilder trackBuilder; - auto trackWriter = trackBuilder.cursor(); - trackWriter(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + //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(); TableBuilder trackParCovBuilder; @@ -37,13 +39,13 @@ BOOST_AUTO_TEST_CASE(TestJoinedTables) trackParCovWriter(0, 7, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4); auto covs = trackParCovBuilder.finalize(); - using Test = Join; + using Test = Join; Test tests{0, tracks, covs}; BOOST_REQUIRE(tests.asArrowTable()->num_columns() != 0); BOOST_REQUIRE_EQUAL(tests.asArrowTable()->num_columns(), tracks->num_columns() + covs->num_columns()); - auto tests2 = join(StoredTracks{tracks}, StoredTracksCov{covs}); + auto tests2 = join(Tracks{tracks}, StoredTracksCov{covs}); 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_Expressions.cxx b/Framework/Core/test/test_Expressions.cxx index c50ba227efd0e..5be7c48fab751 100644 --- a/Framework/Core/test/test_Expressions.cxx +++ b/Framework/Core/test/test_Expressions.cxx @@ -144,29 +144,25 @@ BOOST_AUTO_TEST_CASE(TestGandivaTreeCreation) BOOST_CHECK_EQUAL(gandiva_expression->ToString(), "float multiply((float) fTgl, float divide((const float) 1 raw(3f800000), (float) fSigned1Pt))"); auto projector = createProjector(schema, pzspecs, resfield); - Projector pte = o2::aod::track::Pt2::Projector(); + Projector pte = o2::aod::track::Pt::Projector(); auto ptespecs = createOperations(std::move(pte)); BOOST_REQUIRE_EQUAL(ptespecs[0].left, (DatumSpec{1u, atype::FLOAT})); - BOOST_REQUIRE_EQUAL(ptespecs[0].right, (DatumSpec{2u, atype::FLOAT})); + BOOST_REQUIRE_EQUAL(ptespecs[0].right, (DatumSpec{})); BOOST_REQUIRE_EQUAL(ptespecs[0].result, (DatumSpec{0u, atype::FLOAT})); BOOST_REQUIRE_EQUAL(ptespecs[1].left, (DatumSpec{LiteralNode::var_t{1.f}, atype::FLOAT})); BOOST_REQUIRE_EQUAL(ptespecs[1].right, (DatumSpec{std::string{"fSigned1Pt"}, atype::FLOAT})); - BOOST_REQUIRE_EQUAL(ptespecs[1].result, (DatumSpec{2u, atype::FLOAT})); - - BOOST_REQUIRE_EQUAL(ptespecs[2].left, (DatumSpec{LiteralNode::var_t{1.f}, atype::FLOAT})); - BOOST_REQUIRE_EQUAL(ptespecs[2].right, (DatumSpec{std::string{"fSigned1Pt"}, atype::FLOAT})); - BOOST_REQUIRE_EQUAL(ptespecs[2].result, (DatumSpec{1u, atype::FLOAT})); + BOOST_REQUIRE_EQUAL(ptespecs[1].result, (DatumSpec{1u, atype::FLOAT})); auto infield3 = o2::aod::track::Signed1Pt::asArrowField(); - auto resfield2 = o2::aod::track::Pt2::asArrowField(); + auto resfield2 = o2::aod::track::Pt::asArrowField(); auto schema2 = std::make_shared(std::vector{infield3, resfield2}); auto gandiva_tree2 = createExpressionTree(ptespecs, schema2); auto gandiva_expression2 = makeExpression(gandiva_tree2, resfield2); - BOOST_CHECK_EQUAL(gandiva_expression2->ToString(), "float multiply(float divide((const float) 1 raw(3f800000), (float) fSigned1Pt), float divide((const float) 1 raw(3f800000), (float) fSigned1Pt))"); + BOOST_CHECK_EQUAL(gandiva_expression2->ToString(), "float absf(float divide((const float) 1 raw(3f800000), (float) fSigned1Pt))"); auto projector_b = createProjector(schema2, ptespecs, resfield2); auto schema_p = o2::soa::createSchemaFromColumns(o2::aod::Tracks::persistent_columns_t{}); - auto projector_alt = o2::framework::expressions::createProjectors(o2::framework::pack{}, schema_p); + auto projector_alt = o2::framework::expressions::createProjectors(o2::framework::pack{}, schema_p); } From a4f9bd4b9fa90e6415400089c2d157858ae593e1 Mon Sep 17 00:00:00 2001 From: klapidus <33128171+klapidus@users.noreply.github.com> Date: Mon, 6 Jul 2020 08:23:31 +0200 Subject: [PATCH 0031/1751] basic test machine info added: ncpus, average load (#3883) Co-authored-by: Kirill Lapidus --- scripts/py-analysis-benchmark.py | 103 ++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 28 deletions(-) diff --git a/scripts/py-analysis-benchmark.py b/scripts/py-analysis-benchmark.py index 3b89be3ff2f69..7eb73e71852c8 100644 --- a/scripts/py-analysis-benchmark.py +++ b/scripts/py-analysis-benchmark.py @@ -1,3 +1,16 @@ +""" +Script for the local benchmarking of the o2 analysis tasks, +running them with multiple processing jobs (NCORES) +and multiple readers (NREADERS) over input files (INPUT_FILE). +Tasks to be benchmarked are in the BENCHMARK_TASKS dict. + +Usage: python3 py-analysis-benchmark.py + +Ouput: CSV file (OUTPUT_CSV) with benchmarking results: +'tname', 'ncores', 'nreaders', 'time_mean' (s), 'time_std' (s), +'input_size' (MB), 'input_length', 'timestamp', 'cpu_load', 'ncpu', 'machine' +""" + import csv from datetime import datetime import itertools @@ -7,55 +20,85 @@ import subprocess import timeit -O2_ROOT = os.environ.get('O2_ROOT') -if not O2_ROOT: - print('O2_ROOT not found') - raise ValueError - -INPUT_FILE = '@filelist.txt' -OUTPUT_CSV = 'benchmark_data.csv' -with open(INPUT_FILE[1:],'r') as f: - fnames = f.readlines() - input_size = round(sum([os.stat(l.strip('\n')).st_size for l in fnames])/1024/1024) - input_length = len(fnames) +def get_cl_output(cmd) -> str: + try: + output_ = str(subprocess.check_output(cmd, shell=True), 'utf-8') + except subprocess.CalledProcessError: + output_ = '' + return output_.strip('\n') -NCORES = [1, 2, 4] -NREADERS = [1, 2, 4] -NTRIALS = 3 -CPU_SELECTION = False +def get_cpu_load(): + uptime_ = get_cl_output('uptime') + load_last_15 = uptime_.split(' ')[-1] + return load_last_15 -SHA256SUM_TASK = Template('cat ${file_list} | xargs -P ${n} -n1 -I{} sha256sum {}') -#COMPOSITE_TASK = Template('o2-analysis-trackselection -b --pipeline track-selection:${n},track-extension:${n} --aod-file ${file_list} --readers ${n} | o2-analysistutorial-histogram-track-selection -b --pipeline histogram-track-selection:${n} --select=0') +def get_timestamp(): + return datetime.now().strftime("%m/%d/%Y %H:%M") + + +def get_time_std(t_res): + try: + std_ = stat.stdev(t_res) + except stat.StatisticsError: + std_ = -1 + return std_ + +#benchmarking setup +INPUT_FILE = '@filelist.txt' +OUTPUT_CSV = 'benchmark_data.csv' +NCORES = [1, 2, 4] +NREADERS = [1, 2, 4] +NTRIALS = 2 +LARGE_SHM_SEGMENT_SIZE = False +CPU_SELECTION = False + +#tasks to be benchmarked BENCHMARK_TASKS = { + 'o2-analysistutorial-void': '-b --pipeline void:${n}', 'o2-analysistutorial-histograms': '-b --pipeline eta-and-phi-histograms:${n},pt-histogram:${n},etaphi-histogram:${n}', 'o2-analysis-trackselection': '-b --pipeline track-selection:${n},track_extension:${n}', - #'o2-analysis-vertexing-hf': '-b --pipeline vertexerhf-candidatebuildingDzero:${n},vertexerhf-decayvertexbuilder2prong:${n}', + 'o2-analysis-correlations': '-b --pipeline correlation-task:${n}', + #'o2-analysis-vertexing-hf': '-b --pipeline vertexerhf-candidatebuildingDzero:${n},vertexerhf-decayvertexbuilder2prong:${n}' } - + + +O2_ROOT = os.environ.get('O2_ROOT') +if not O2_ROOT: + print('O2_ROOT not found') + raise ValueError + +MACHINE = get_cl_output('hostname') +NCPU = get_cl_output('grep processor /proc/cpuinfo | wc -l') +with open(INPUT_FILE[1:],'r') as f: + fnames = f.readlines() + INPUT_SIZE = round(sum([os.stat(l.strip('\n')).st_size for l in fnames])/1024/1024) + INPUT_LENGTH = len(fnames) + + +SHA256SUM_TASK = Template('cat ${file_list} | xargs -P ${n} -n1 -I{} sha256sum {}') +#COMPOSITE_TASK = Template('o2-analysis-trackselection -b --pipeline track-selection:${n},track-extension:${n} --aod-file ${file_list} --readers ${n} | o2-analysistutorial-histogram-track-selection -b --pipeline histogram-track-selection:${n} --select=0') + for k in BENCHMARK_TASKS: BENCHMARK_TASKS[k] = Template(BENCHMARK_TASKS[k]) with open(OUTPUT_CSV, 'w') as f: writer = csv.writer(f) - writer.writerow(['tname', 'ncores', 'nreaders', 'time_mean', 'time_std', 'input_size', 'input_length']) + writer.writerow(('tname', 'ncores', 'nreaders', 'time_mean', 'time_std', + 'input_size', 'input_length', 'timestamp', 'cpu_load', 'ncpu', 'machine')) for ncores in NCORES: cmd_sha256sum = SHA256SUM_TASK.substitute(file_list=INPUT_FILE[1:], n=str(ncores)) t = timeit.Timer('os.system(cmd_sha256sum)', globals=globals()) t_res = t.repeat(NTRIALS, 1) - writer.writerow( ('sha256sum', ncores, -1, stat.mean(t_res), stat.stdev(t_res), input_size, input_length) ) + writer.writerow( ('sha256sum', ncores, -1, stat.mean(t_res), get_time_std(t_res), + INPUT_SIZE, INPUT_LENGTH, get_timestamp(), get_cpu_load(), NCPU, MACHINE) ) for ncores, nreaders in itertools.product(NCORES, NREADERS): - - #cmd_composite = COMPOSITE_TASK.substitute(file_list=INPUT_FILE,n=str(ncores)) - #t = timeit.Timer('os.system(cmd_composite)', globals=globals()) - #t_res = t.repeat(NTRIALS, 1) - #writer.writerow( ('analysistutorial-histogram-track-selection', ncores, nreaders, stat.mean(t_res), stat.stdev(t_res), input_size, input_length) ) - + for tname, targ in BENCHMARK_TASKS.items(): targ = targ.substitute(n=str(ncores)) cmd_list = [tname] + targ.split(' ') @@ -65,13 +108,17 @@ cmd_list = ['taskset','-c','5,15'] + cmd_list elif ncores == 4: cmd_list = ['taskset','-c','1,3,11,13'] + cmd_list + + if LARGE_SHM_SEGMENT_SIZE: + cmd_list += ['--shm-segment-size', str(16000000000)] cmd_list += ['--aod-file', INPUT_FILE] cmd_list += ['--readers', str(nreaders)] t = timeit.Timer('subprocess.run(cmd_list)', globals=globals()) t_res = t.repeat(NTRIALS, 1) - writer.writerow( (tname[3:], ncores, nreaders, stat.mean(t_res), stat.stdev(t_res), input_size, input_length) ) + writer.writerow( (tname[3:], ncores, nreaders, stat.mean(t_res), get_time_std(t_res), + INPUT_SIZE, INPUT_LENGTH, get_timestamp(), get_cpu_load(), NCPU, MACHINE) ) #alinsure #numa0 0-11,24-35 From 6a4d31d2122b8eb7c839300cee6be05b9d705855 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 6 Jul 2020 08:55:43 +0200 Subject: [PATCH 0032/1751] DPL: cleanup shmem using FairMQ 1.4.20 API (#3945) --- Framework/Core/src/runDataProcessing.cxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 58cbd621bb4a6..2936222fa1da8 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -63,6 +63,9 @@ #include "FairMQDevice.h" #include +#if __has_include() +#include +#endif #include "options/FairMQProgOptions.h" #include @@ -284,6 +287,11 @@ static void handle_sigint(int) /// Helper to invoke shared memory cleanup void cleanupSHM(std::string const& uniqueWorkflowId) { +#if __has_include() + using namespace fair::mq::shmem; + Monitor::Cleanup(SessionId{"dpl_" + uniqueWorkflowId}); +#else + // Old code, invoking external fairmq-shmmonitor auto shmCleanup = fmt::format("fairmq-shmmonitor --cleanup -s dpl_{} 2>&1 >/dev/null", uniqueWorkflowId); LOG(debug) << "Cleaning up shm memory session with " << shmCleanup; @@ -291,6 +299,7 @@ void cleanupSHM(std::string const& uniqueWorkflowId) if (result != 0) { LOG(error) << "Unable to cleanup shared memory, run " << shmCleanup << "by hand to fix"; } +#endif } static void handle_sigchld(int) { sigchld_requested = true; } From 914de17b21e87bd591c361e07b77ac83a6792a46 Mon Sep 17 00:00:00 2001 From: Jorge Lopez Date: Mon, 6 Jul 2020 05:48:48 -0400 Subject: [PATCH 0033/1751] TRD: Fix bug due to changes in #3758 (#3890) * fix bug due to changes in #3758 * improved volume name handling * use constants rather than hard-coded numbers * use sscanf for parsing the volume information --- Detectors/TRD/base/src/TRDGeometry.cxx | 2 + Detectors/TRD/simulation/src/Detector.cxx | 74 ++++++++++++----------- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/Detectors/TRD/base/src/TRDGeometry.cxx b/Detectors/TRD/base/src/TRDGeometry.cxx index 017b720437362..f849b3d188599 100644 --- a/Detectors/TRD/base/src/TRDGeometry.cxx +++ b/Detectors/TRD/base/src/TRDGeometry.cxx @@ -2561,6 +2561,8 @@ void TRDGeometry::fillMatrixCache(int mask) } std::string volPath; + // keep in mind that changing this path can affect behaviour in Detector.cxx + // see: https://github.com/AliceO2Group/AliceO2/pull/3890 const std::string vpStr{"ALIC_1/barrel_1/B077_1/BSEGMO"}; const std::string vpApp1{"_1/BTRD"}; const std::string vpApp2{"_1"}; diff --git a/Detectors/TRD/simulation/src/Detector.cxx b/Detectors/TRD/simulation/src/Detector.cxx index cc203d6842a6e..268435a339626 100644 --- a/Detectors/TRD/simulation/src/Detector.cxx +++ b/Detectors/TRD/simulation/src/Detector.cxx @@ -8,18 +8,23 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "TRDSimulation/Detector.h" + +#include "TRDBase/TRDCommonParam.h" +#include "TRDBase/TRDGeometry.h" +#include "TRDSimulation/TRsim.h" + +#include "CommonUtils/ShmAllocator.h" +#include "SimulationDataFormat/Stack.h" +#include "FairVolume.h" +#include "FairRootManager.h" + #include #include + #include #include -#include "FairVolume.h" -#include "FairRootManager.h" -#include "SimulationDataFormat/Stack.h" -#include "CommonUtils/ShmAllocator.h" -#include "TRDBase/TRDCommonParam.h" -#include "TRDBase/TRDGeometry.h" -#include "TRDSimulation/Detector.h" -#include "TRDSimulation/TRsim.h" +#include using namespace o2::trd; @@ -89,37 +94,38 @@ bool Detector::ProcessHits(FairVolume* v) // Inside sensitive volume ? bool drRegion = false; bool amRegion = false; - const TString cIdSensDr = "J"; - const TString cIdSensAm = "K"; - const TString cIdCurrent = fMC->CurrentVolName(); - if (cIdCurrent[1] == cIdSensDr) { - drRegion = true; + char idRegion; + int cIdChamber; + int r1 = std::sscanf(fMC->CurrentVolName(), "U%1s%d", &idRegion, &cIdChamber); + if (r1 != 2) { + LOG(FATAL) << "Something went wrong with the geometry volume name " << fMC->CurrentVolName(); } - if (cIdCurrent[1] == cIdSensAm) { + if (idRegion == 'J') { + drRegion = true; + } else if (idRegion == 'K') { amRegion = true; - } - if (!drRegion && !amRegion) { + } else { return false; } - // Determine the dectector number - int sector, det; - // The plane number and chamber number - char cIdChamber[3]; - cIdChamber[0] = cIdCurrent[2]; - cIdChamber[1] = cIdCurrent[3]; - cIdChamber[2] = 0; - // The det-sec number (0 – 29) - const int idChamber = mGeom->getDetectorSec(atoi(cIdChamber)); - // The sector number (0 - 17), according to the standard coordinate system - TString cIdPath = fMC->CurrentVolPath(); - char cIdSector[3]; - cIdSector[0] = cIdPath[21]; - cIdSector[1] = cIdPath[22]; - cIdSector[2] = 0; - sector = atoi(cIdSector); - // The detector number (0 – 539) - det = mGeom->getDetector(mGeom->getLayer(idChamber), mGeom->getStack(idChamber), sector); + const int idChamber = mGeom->getDetectorSec(cIdChamber); + if (idChamber < 0 || idChamber > 29) { + LOG(FATAL) << "Chamber ID out of bounds"; + } + + int sector; + int r2 = std::sscanf(fMC->CurrentVolOffName(7), "BTRD%d", §or); + if (r2 != 1) { + LOG(FATAL) << "Something went wrong with the geometry volume name " << fMC->CurrentVolOffName(7); + } + if (sector < 0 || sector >= kNsector) { + LOG(FATAL) << "Sector out of bounds"; + } + // The detector number (0 - 539) + int det = mGeom->getDetector(mGeom->getLayer(idChamber), mGeom->getStack(idChamber), sector); + if (det < 0 || det >= kNdet) { + LOG(FATAL) << "Detector number out of bounds"; + } // 0: InFlight 1: Entering 2: Exiting int trkStat = 0; From 8ab4bdfcbace19439ab5438af07530a321f30187 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 6 Jul 2020 18:55:18 +0200 Subject: [PATCH 0034/1751] DPL: fix 100% CPU utilization when timepipeline idle (#3946) The issue seems to be that UV_READABLE events are triggereded on a socket which should be used for writing. Such a socket should not really be subscribing to such events, but it happens because the rfind is not taking into account the _tX. This prevents from subscribing in the first place. --- Framework/Core/src/DataProcessingDevice.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 6f24a9ecda026..b3e20056a9c14 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -276,7 +276,7 @@ void DataProcessingDevice::InitTask() continue; } // We only watch receiving sockets. - if (x.first.rfind("from_" + mSpec.name + "_to", 0) == 0) { + if (x.first.rfind("from_" + mSpec.name + "_", 0) == 0) { LOG(debug) << x.first << " is to send data. Not polling." << std::endl; continue; } @@ -306,7 +306,7 @@ void DataProcessingDevice::InitTask() LOG(debug) << x.first << " is an internal channel. Not polling." << std::endl; continue; } - assert(x.first.rfind("from_" + mSpec.name + "_to", 0) == 0); + assert(x.first.rfind("from_" + mSpec.name + "_", 0) == 0); // We assume there is always a ZeroMQ socket behind. int zmq_fd = 0; size_t zmq_fd_len = sizeof(zmq_fd); From dd303318fe3b5fd592209324f747b49ae57a17da Mon Sep 17 00:00:00 2001 From: Jorge Lopez Date: Mon, 6 Jul 2020 15:59:10 -0400 Subject: [PATCH 0035/1751] Update Detector.cxx Related to #3890, and just for the code quality: we want a single character rather than an array with at the most one character. --- Detectors/TRD/simulation/src/Detector.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TRD/simulation/src/Detector.cxx b/Detectors/TRD/simulation/src/Detector.cxx index 268435a339626..f9b8e4bb9a634 100644 --- a/Detectors/TRD/simulation/src/Detector.cxx +++ b/Detectors/TRD/simulation/src/Detector.cxx @@ -96,7 +96,7 @@ bool Detector::ProcessHits(FairVolume* v) bool amRegion = false; char idRegion; int cIdChamber; - int r1 = std::sscanf(fMC->CurrentVolName(), "U%1s%d", &idRegion, &cIdChamber); + int r1 = std::sscanf(fMC->CurrentVolName(), "U%c%d", &idRegion, &cIdChamber); if (r1 != 2) { LOG(FATAL) << "Something went wrong with the geometry volume name " << fMC->CurrentVolName(); } From e00d80d6bec5bd7a5a84dd8a92d6d4beaf67dcb7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 6 Jul 2020 01:05:22 +0200 Subject: [PATCH 0036/1751] DPL: improve tracing information --- Framework/Core/src/DataProcessingDevice.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index b3e20056a9c14..50eef7982a0e8 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -78,6 +78,7 @@ namespace o2::framework /// Watching stdin for commands probably a better approach. void idle_timer(uv_timer_t* handle) { + ZoneScopedN("Idle timer"); } DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegistry& registry, DeviceState& state) @@ -154,7 +155,7 @@ void on_socket_polled(uv_poll_t* poller, int status, int events) /// * Invoke the actual init callback, which returns the processing callback. void DataProcessingDevice::Init() { - TracyAppInfo("foo", 3); + TracyAppInfo(mSpec.name.data(), mSpec.name.size()); ZoneScopedN("DataProcessingDevice::Init"); mRelayer = &mServiceRegistry.get(); // For some reason passing rateLogging does not work anymore. @@ -454,7 +455,10 @@ bool DataProcessingDevice::doRun() } } mWasActive = false; - mServiceRegistry.get()(CallbackService::Id::ClockTick); + { + ZoneScopedN("CallbackService::Id::ClockTick"); + mServiceRegistry.get()(CallbackService::Id::ClockTick); + } // Whether or not we had something to do. // Notice that fake input channels (InputChannelState::Pull) cannot possibly @@ -552,6 +556,7 @@ void DataProcessingDevice::ResetTask() /// boilerplate which the user does not need to care about at top level. bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info) { + ZoneScopedN("DataProcessingDevice::handleData"); assert(mSpec.inputChannels.empty() == false); assert(parts.Size() > 0); @@ -666,6 +671,7 @@ bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info bool DataProcessingDevice::tryDispatchComputation(std::vector& completed) { + ZoneScopedN("DataProcessingDevice::tryDispatchComputation"); // This is the actual hidden state for the outer loop. In case we decide we // want to support multithreaded dispatching of operations, I can simply // move these to some thread local store and the rest of the lambdas From 0c7a744589ac9e243a7e4e489ac1c6e17db15eab Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 6 Jul 2020 02:05:11 +0200 Subject: [PATCH 0037/1751] DPL: reflow DataProcessingDevice --- Framework/Core/src/DataProcessingDevice.cxx | 132 ++++++++++---------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 50eef7982a0e8..b13551b1c940c 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -905,90 +905,90 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector Date: Tue, 7 Jul 2020 11:12:38 +0200 Subject: [PATCH 0038/1751] DPL: allow connecting to profiler directly --- Framework/Core/include/Framework/DeviceInfo.h | 15 +++++++-------- Framework/Core/src/DataProcessingDevice.cxx | 1 - Framework/Core/src/DriverInfo.h | 2 ++ .../Core/src/FrameworkGUIDeviceInspector.cxx | 10 ++++++++-- Framework/Core/src/runDataProcessing.cxx | 12 +++++++++++- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceInfo.h b/Framework/Core/include/Framework/DeviceInfo.h index 9fed22b0b5f29..8d384b36d1b23 100644 --- a/Framework/Core/include/Framework/DeviceInfo.h +++ b/Framework/Core/include/Framework/DeviceInfo.h @@ -7,8 +7,8 @@ // 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_DEVICEINFO_H -#define FRAMEWORK_DEVICEINFO_H +#ifndef O2_FRAMEWORK_DEVICEINFO_H_ +#define O2_FRAMEWORK_DEVICEINFO_H_ #include "Framework/LogParsingHelpers.h" #include "Framework/Metric2DViewIndex.h" @@ -23,9 +23,7 @@ #include #include -namespace o2 -{ -namespace framework +namespace o2::framework { struct DeviceInfo { @@ -67,8 +65,9 @@ struct DeviceInfo { boost::property_tree::ptree currentConfig; /// Current provenance for the configuration keys boost::property_tree::ptree currentProvenance; + /// Port to use to connect to tracy profiler + short tracyPort; }; -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_DEVICEINFO_H +} // namespace o2::framework +#endif // O2_FRAMEWORK_DEVICEINFO_H_ diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index b13551b1c940c..27e76c9b4b197 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -695,7 +695,6 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector(); StateMonitoring::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); auto metricFlusher = make_scope_guard([]() noexcept -> void { StateMonitoring::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); diff --git a/Framework/Core/src/DriverInfo.h b/Framework/Core/src/DriverInfo.h index 15c6aed26d091..272b9daccfd88 100644 --- a/Framework/Core/src/DriverInfo.h +++ b/Framework/Core/src/DriverInfo.h @@ -129,6 +129,8 @@ struct DriverInfo { float frameLatency; /// The unique id used for ipc communications std::string uniqueWorkflowId = ""; + /// Last port used for tracy + short tracyPort = 8086; }; } // namespace o2::framework diff --git a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx index 5642982a5be8a..dcf8aac9a45fe 100644 --- a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx +++ b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx @@ -20,6 +20,7 @@ #include "DebugGUI/imgui.h" #include #include +#include namespace o2 { @@ -156,6 +157,9 @@ void displayDeviceInspector(DeviceSpec const& spec, } else { ImGui::Text("Pid: %d (exit status: %d)", info.pid, info.exitStatus); } +#ifdef DPL_ENABLE_TRACING + ImGui::Text("Tracy Port: %d", info.tracyPort); +#endif ImGui::Text("Rank: %zu/%zu%%%zu/%zu", spec.rank, spec.nSlots, spec.inputTimesliceId, spec.maxInputTimeslices); if (ImGui::Button("Attach debugger")) { @@ -197,8 +201,10 @@ void displayDeviceInspector(DeviceSpec const& spec, ImGui::SameLine(); #if DPL_ENABLE_TRACING if (ImGui::Button("Tracy")) { - setenv("O2DPLTRACING", "tracy-profiler &", 0); - int retVal = system(getenv("O2DPLTRACING")); + std::string tracyPort = std::to_string(info.tracyPort); + auto cmd = fmt::format("tracy-profiler -p {} -a 127.0.0.1 &", info.tracyPort); + LOG(debug) << cmd; + int retVal = system(cmd.c_str()); (void)retVal; } #endif diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 2936222fa1da8..4428f81b0a3cc 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -355,6 +355,7 @@ void log_callback(uv_poll_t* handle, int status, int events) /// new child void spawnDevice(std::string const& forwardedStdin, DeviceSpec const& spec, + DriverInfo& driverInfo, DeviceControl& control, DeviceExecution& execution, std::vector& deviceInfos, @@ -369,6 +370,11 @@ void spawnDevice(std::string const& forwardedStdin, createPipes(childstdout); createPipes(childstderr); + // FIXME: this might not work when more than one DPL driver on the same + // machine. Hopefully we do not care. + // Not how the first port is actually used to broadcast clients. + driverInfo.tracyPort++; + // If we have a framework id, it means we have already been respawned // and that we are in a child. If not, we need to fork and re-exec, adding // the framework-id as one of the options. @@ -393,6 +399,8 @@ void spawnDevice(std::string const& forwardedStdin, dup2(childstdin[0], STDIN_FILENO); dup2(childstdout[1], STDOUT_FILENO); dup2(childstderr[1], STDERR_FILENO); + auto portS = std::to_string(driverInfo.tracyPort); + setenv("TRACY_PORT", portS.c_str(), 1); execvp(execution.args[0], execution.args.data()); } @@ -419,6 +427,7 @@ void spawnDevice(std::string const& forwardedStdin, info.dataRelayerViewIndex = Metric2DViewIndex{"data_relayer", 0, 0, {}}; info.variablesViewIndex = Metric2DViewIndex{"matcher_variables", 0, 0, {}}; info.queriesViewIndex = Metric2DViewIndex{"data_queries", 0, 0, {}}; + info.tracyPort = driverInfo.tracyPort; deviceInfos.emplace_back(info); // Let's add also metrics information for the given device @@ -974,7 +983,8 @@ int runStateMachine(DataProcessorSpecs const& workflow, deviceSpecs[di], controls[di], deviceExecutions[di], infos); } else { spawnDevice(forwardedStdin.str(), - deviceSpecs[di], controls[di], deviceExecutions[di], infos, + deviceSpecs[di], driverInfo, + controls[di], deviceExecutions[di], infos, loop, pollHandles); } } From 1a49ff85a4013d5cbfdfb5ffacf3e501934aa79d Mon Sep 17 00:00:00 2001 From: noferini Date: Mon, 6 Jul 2020 14:35:06 +0200 Subject: [PATCH 0039/1751] fix for float truncation affecting timing in large timeframe numbers --- Detectors/TOF/base/include/TOFBase/Geo.h | 8 ++++---- Detectors/TOF/simulation/src/Digitizer.cxx | 21 +++++++-------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/Detectors/TOF/base/include/TOFBase/Geo.h b/Detectors/TOF/base/include/TOFBase/Geo.h index 1b26ca3dc20b3..66dcc3feea9e8 100644 --- a/Detectors/TOF/base/include/TOFBase/Geo.h +++ b/Detectors/TOF/base/include/TOFBase/Geo.h @@ -62,10 +62,10 @@ class Geo static constexpr Int_t RAW_PAGE_MAX_SIZE = 8192; - static constexpr Float_t BC_TIME = o2::constants::lhc::LHCBunchSpacingNS; // bunch crossing in ns - static constexpr Float_t BC_TIME_INV = 1. / BC_TIME; // inv bunch crossing in ns - static constexpr Float_t BC_TIME_INPS = BC_TIME * 1000; // bunch crossing in ps - static constexpr Float_t BC_TIME_INPS_INV = 1. / BC_TIME_INPS; // inv bunch crossing in ps + static constexpr Double_t BC_TIME = o2::constants::lhc::LHCBunchSpacingNS; // bunch crossing in ns + static constexpr Double_t BC_TIME_INV = 1. / BC_TIME; // inv bunch crossing in ns + static constexpr Double_t BC_TIME_INPS = BC_TIME * 1000; // bunch crossing in ps + static constexpr Double_t BC_TIME_INPS_INV = 1. / BC_TIME_INPS; // inv bunch crossing in ps static constexpr int BC_IN_ORBIT = o2::constants::lhc::LHCMaxBunches; // N. bunch crossing in 1 orbit static constexpr Int_t NPADX = 48; diff --git a/Detectors/TOF/simulation/src/Digitizer.cxx b/Detectors/TOF/simulation/src/Digitizer.cxx index 34f1c58c8d08a..e7f7c9bf4f2f3 100644 --- a/Detectors/TOF/simulation/src/Digitizer.cxx +++ b/Detectors/TOF/simulation/src/Digitizer.cxx @@ -271,16 +271,19 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, // Decalibrate time -= mCalibApi->getTimeDecalibration(channel, tot); //TODO: to be checked that "-" is correct, and we did not need "+" instead :-) + // let's move from time to bc, tdc + Int_t nbc = Int_t(time * Geo::BC_TIME_INPS_INV); // time elapsed in number of bunch crossing //Digit newdigit(time, channel, (time - Geo::BC_TIME_INPS * nbc) * Geo::NTDCBIN_PER_PS, tot * Geo::NTOTBIN_PER_NS, nbc); int tdc = int((time - Geo::BC_TIME_INPS * nbc) * Geo::NTDCBIN_PER_PS); // additional check to avoid very rare truncation - if (tdc < 0) { + while (tdc < 0) { nbc--; tdc += 1024; - } else if (tdc >= 1024) { + } + while (tdc >= 1024) { nbc++; tdc -= 1024; } @@ -353,12 +356,7 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, mcTruthContainer = mMCTruthContainerNext[isnext - 1]; } - int eventcounter = mReadoutWindowCurrent + isnext; - int hittimeTDC = (nbc - eventcounter * Geo::BC_IN_WINDOW) * 1024 + tdc; // time in TDC bin within the TOF WINDOW - if (hittimeTDC < 0) - LOG(ERROR) << "1) Negative hit " << hittimeTDC << ", something went wrong in filling readout window: isnext=" << isnext << ", isIfOverlap=" << isIfOverlap; - else - fillDigitsInStrip(strips, mcTruthContainer, channel, tdc, tot, nbc, istrip, trackID, mEventID, mSrcID); + fillDigitsInStrip(strips, mcTruthContainer, channel, tdc, tot, nbc, istrip, trackID, mEventID, mSrcID); if (isIfOverlap > -1 && isIfOverlap < MAXWINDOWS) { // fill also a second readout window because of the overlap if (!isIfOverlap) { @@ -369,12 +367,7 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, mcTruthContainer = mMCTruthContainerNext[isIfOverlap - 1]; } - int eventcounter = mReadoutWindowCurrent + isIfOverlap; - int hittimeTDC = (nbc - eventcounter * Geo::BC_IN_WINDOW) * 1024 + tdc; // time in TDC bin within the TOF WINDOW - if (hittimeTDC < 0) - LOG(ERROR) << "2) Negative hit " << hittimeTDC << ", something went wrong in filling readout window: isnext=" << isnext << ", isIfOverlap=" << isIfOverlap; - else - fillDigitsInStrip(strips, mcTruthContainer, channel, tdc, tot, nbc, istrip, trackID, mEventID, mSrcID); + fillDigitsInStrip(strips, mcTruthContainer, channel, tdc, tot, nbc, istrip, trackID, mEventID, mSrcID); } } //______________________________________________________________________ From 6268b7709a38e35ad87df4bdaf0483c8ef7a97d6 Mon Sep 17 00:00:00 2001 From: noferini Date: Mon, 6 Jul 2020 17:47:02 +0200 Subject: [PATCH 0040/1751] use interactionTimeRecord instead of double time in TOF digitization --- .../TOF/base/include/TOFBase/WindowFiller.h | 5 ++-- Detectors/TOF/reconstruction/src/Decoder.cxx | 1 - Detectors/TOF/simulation/src/Digitizer.cxx | 27 +++++++------------ .../src/TOFDigitizerSpec.cxx | 2 +- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index aedf8820ebc74..f84ee5023f22b 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -15,6 +15,7 @@ #include "TOFBase/Digit.h" #include "TOFBase/Strip.h" #include "DetectorsRaw/HBFUtils.h" +#include "CommonDataFormat/InteractionRecord.h" namespace o2 { @@ -34,7 +35,7 @@ class WindowFiller Int_t getCurrentReadoutWindow() const { return mReadoutWindowCurrent; } void setCurrentReadoutWindow(Double_t value) { mReadoutWindowCurrent = value; } - void setEventTime(double value) + void setEventTime(InteractionTimeRecord value) { mEventTime = value; } @@ -54,7 +55,7 @@ class WindowFiller Int_t mReadoutWindowCurrent = 0; Int_t mFirstOrbit = 0; Int_t mFirstBunch = 0; - Double_t mEventTime; + InteractionTimeRecord mEventTime; bool mContinuous = true; bool mFutureToBeSorted = false; diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index 195da9757df91..57ae82ae5d384 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -233,7 +233,6 @@ bool Decoder::decode() // return a vector of digits in a TOF readout window auto start = std::chrono::high_resolution_clock::now(); // start from the beginning of the timeframe - mEventTime = 0; // loop over CRUs for (int icru = 0; icru < NCRU; icru++) { diff --git a/Detectors/TOF/simulation/src/Digitizer.cxx b/Detectors/TOF/simulation/src/Digitizer.cxx index e7f7c9bf4f2f3..46eded78bd297 100644 --- a/Detectors/TOF/simulation/src/Digitizer.cxx +++ b/Detectors/TOF/simulation/src/Digitizer.cxx @@ -88,9 +88,9 @@ int Digitizer::process(const std::vector* hits, std::vector* dig // hits array of TOF hits for a given simulated event // digits passed from external to be filled, in continuous readout mode we will push it on mDigitsPerTimeFrame vector of vectors of digits - // printf("process event time = %f with %ld hits\n",mEventTime,hits->size()); + // printf("process event time = %f with %ld hits\n",mEventTime.getTimeNS(),hits->size()); - Int_t readoutwindow = Int_t((mEventTime - Geo::BC_TIME * (Geo::OVERLAP_IN_BC + 2)) * Geo::READOUTWINDOW_INV); // event time shifted by 2 BC as safe margin before to change current readout window to account for decalibration + Int_t readoutwindow = Int_t((mEventTime.getTimeNS() - Geo::BC_TIME * (Geo::OVERLAP_IN_BC + 2)) * Geo::READOUTWINDOW_INV); // event time shifted by 2 BC as safe margin before to change current readout window to account for decalibration if (mContinuous && readoutwindow > mReadoutWindowCurrent) { // if we are moving in future readout windows flush previous ones (only for continuous readout mode) digits->clear(); @@ -104,7 +104,7 @@ int Digitizer::process(const std::vector* hits, std::vector* dig for (auto& hit : *hits) { //TODO: put readout window counting/selection - processHit(hit, mEventTime); + processHit(hit, mEventTime.getTimeOffsetWrtBC()); } // end loop over hits if (!mContinuous) { // fill output container per event @@ -278,15 +278,10 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, int tdc = int((time - Geo::BC_TIME_INPS * nbc) * Geo::NTDCBIN_PER_PS); - // additional check to avoid very rare truncation - while (tdc < 0) { - nbc--; - tdc += 1024; - } - while (tdc >= 1024) { - nbc++; - tdc -= 1024; - } + // add orbit and bc + nbc += mEventTime.toLong(); + + // printf("orbit = %d -- bc = %d -- nbc = (%d) %d\n",mEventTime.orbit,mEventTime.bc, mEventTime.toLong(),nbc); // printf("tdc = %d\n",tdc); @@ -298,9 +293,7 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, if (mContinuous) { isnext = nbc / Geo::BC_IN_WINDOW - mReadoutWindowCurrent; - // isnext = Int_t(time * 1E-3 * Geo::READOUTWINDOW_INV) - mReadoutWindowCurrent; // to be replaced with uncalibrated time isIfOverlap = (nbc - Geo::OVERLAP_IN_BC) / Geo::BC_IN_WINDOW - mReadoutWindowCurrent; - // isIfOverlap = Int_t((time - Geo::BC_TIME_INPS * Geo::OVERLAP_IN_BC) * 1E-3 * Geo::READOUTWINDOW_INV) - mReadoutWindowCurrent; // to be replaced with uncalibrated time; if (isnext == isIfOverlap) isIfOverlap = -1; @@ -314,7 +307,7 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, if (isnext < 0) { LOG(ERROR) << "error: isnext =" << isnext << "(current window = " << mReadoutWindowCurrent << ")" - << " nbc = " << nbc << " -- event time = " << mEventTime << "\n"; + << " nbc = " << nbc << " -- event time = " << mEventTime.getTimeNS() << "\n"; return; } @@ -658,7 +651,7 @@ void Digitizer::test(const char* geo) hit->SetEnergyLoss(0.0001); - Int_t ndigits = processHit(*hit, mEventTime); + Int_t ndigits = processHit(*hit, mEventTime.getTimeOffsetWrtBC()); h3->Fill(ndigits); hpadAll->Fill(xlocal, zlocal); @@ -753,7 +746,7 @@ void Digitizer::testFromHits(const char* geo, const char* hits) hit->SetEnergyLoss(t->GetLeaf("o2root.TOF.TOFHit.mELoss")->GetValue(j)); - Int_t ndigits = processHit(*hit, mEventTime); + Int_t ndigits = processHit(*hit, mEventTime.getTimeOffsetWrtBC()); h3->Fill(ndigits); for (Int_t k = 0; k < ndigits; k++) { diff --git a/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx index aa5c4087e146c..e2df6005a7f38 100644 --- a/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx @@ -125,7 +125,7 @@ class TOFDPLDigitizerTask : public o2::base::BaseDPLDigitizer // loop over all composite collisions given from context // (aka loop over all the interaction records) for (int collID = 0; collID < timesview.size(); ++collID) { - mDigitizer->setEventTime(timesview[collID].getTimeNS()); + mDigitizer->setEventTime(timesview[collID]); // for each collision, loop over the constituents event and source IDs // (background signal merging is basically taking place here) From 6b9838339c7acf0b8d8d7f5cbf74734aeafcc0d6 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 2 Jul 2020 18:15:35 +0200 Subject: [PATCH 0041/1751] Add ever-incrementing TF counter and runNumber to DataHeader The DataHeader::firstTForbit will not be unique when the same TFs are replayed in loop, this counter will resolve the ambiguity. runNumber is needed for conversion of firstTForbit to abs. timestamp --- .../Headers/include/Headers/DataHeader.h | 32 +++++++++++++++---- DataFormats/Headers/src/DataHeader.cxx | 7 ++-- DataFormats/Headers/test/testDataHeader.cxx | 6 ++-- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/DataFormats/Headers/include/Headers/DataHeader.h b/DataFormats/Headers/include/Headers/DataHeader.h index 525b1f377fb91..8e79fa2c70394 100644 --- a/DataFormats/Headers/include/Headers/DataHeader.h +++ b/DataFormats/Headers/include/Headers/DataHeader.h @@ -666,9 +666,11 @@ struct DataHeader : public BaseHeader { using SplitPayloadPartsType = uint32_t; using PayloadSizeType = uint64_t; using TForbitType = uint32_t; + using TFCounterType = uint32_t; + using RunNumberType = uint32_t; //static data for this header type/version - static constexpr uint32_t sVersion{2}; + static constexpr uint32_t sVersion{3}; static constexpr o2::header::HeaderType sHeaderType{String2("DataHead")}; static constexpr o2::header::SerializationMethod sSerializationMethod{gSerializationMethodNone}; @@ -711,10 +713,20 @@ struct DataHeader : public BaseHeader { //___NEW STUFF GOES BELOW /// - /// first orbit of time frame as unique identifier within the run + /// first orbit of time frame, since v2 /// TForbitType firstTForbit; + /// + /// ever incrementing TF counter, allows to disentangle even TFs with same firstTForbit in case of replay, since v3 + /// + TFCounterType tfCounter; + + /// + /// run number TF belongs to, since v3 + /// + RunNumberType runNumber; + //___the functions: //__________________________________________________________________________________________________ constexpr DataHeader() @@ -726,7 +738,9 @@ struct DataHeader : public BaseHeader { subSpecification(0), splitPayloadIndex(0), payloadSize(0), - firstTForbit{0} + firstTForbit{0}, + tfCounter(0), + runNumber(0) { } @@ -740,7 +754,9 @@ struct DataHeader : public BaseHeader { subSpecification(subspec), splitPayloadIndex(0), payloadSize(size), - firstTForbit{0} + firstTForbit{0}, + tfCounter(0), + runNumber(0) { } @@ -754,7 +770,9 @@ struct DataHeader : public BaseHeader { subSpecification(subspec), splitPayloadIndex(partIndex), payloadSize(size), - firstTForbit{0} + firstTForbit{0}, + tfCounter(0), + runNumber(0) { } @@ -808,8 +826,8 @@ static_assert(sizeof(BaseHeader) == 32, "BaseHeader struct must be of size 32"); static_assert(sizeof(DataOrigin) == 4, "DataOrigin struct must be of size 4"); -static_assert(sizeof(DataHeader) == 88, - "DataHeader struct must be of size 88"); +static_assert(sizeof(DataHeader) == 96, + "DataHeader struct must be of size 96"); static_assert(gSizeMagicString == sizeof(BaseHeader::magicStringInt), "Size mismatch in magic string union"); static_assert(sizeof(BaseHeader::sMagicString) == sizeof(BaseHeader::magicStringInt), diff --git a/DataFormats/Headers/src/DataHeader.cxx b/DataFormats/Headers/src/DataHeader.cxx index 3401697725e9b..4e66265fc0372 100644 --- a/DataFormats/Headers/src/DataHeader.cxx +++ b/DataFormats/Headers/src/DataHeader.cxx @@ -54,13 +54,16 @@ void o2::header::BaseHeader::throwInconsistentStackError() const //__________________________________________________________________________________________________ void o2::header::DataHeader::print() const { - printf("Data header version %i, flags: %i\n", headerVersion, flags); + printf("Data header version %u, flags: %u\n", headerVersion, flags); printf(" origin : %s\n", dataOrigin.str); printf(" serialization: %s\n", payloadSerializationMethod.str); printf(" description : %s\n", dataDescription.str); printf(" sub spec. : %llu\n", (long long unsigned int)subSpecification); - printf(" header size : %i\n", headerSize); + printf(" header size : %d\n", headerSize); printf(" payloadSize : %llu\n", (long long unsigned int)payloadSize); + printf(" firstTFOrbit : %u\n", firstTForbit); + printf(" tfCounter : %u\n", tfCounter); + printf(" runNumber : %u\n", runNumber); } //__________________________________________________________________________________________________ diff --git a/DataFormats/Headers/test/testDataHeader.cxx b/DataFormats/Headers/test/testDataHeader.cxx index 6fc03a054d831..6c41a77ea7779 100644 --- a/DataFormats/Headers/test/testDataHeader.cxx +++ b/DataFormats/Headers/test/testDataHeader.cxx @@ -236,9 +236,9 @@ BOOST_AUTO_TEST_CASE(DataHeader_test) << "size " << std::setw(2) << sizeof(dh.payloadSize) << " at " << (char*)(&dh.payloadSize) - (char*)(&dh) << std::endl; } - // DataHeader must have size 88 - static_assert(sizeof(DataHeader) == 88, - "DataHeader struct must be of size 88"); + // DataHeader must have size 96 + static_assert(sizeof(DataHeader) == 96, + "DataHeader struct must be of size 96"); DataHeader dh2; BOOST_CHECK(dh == dh2); DataHeader dh3{gDataDescriptionInvalid, gDataOriginInvalid, DataHeader::SubSpecificationType{0}, 0}; From 64f59951b89181109ee0dd8159062ca50bfccb37 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 2 Jul 2020 18:15:39 +0200 Subject: [PATCH 0042/1751] Set the tfCounter in RawDataReader and CTFReader --- .../include/CTFWorkflow/CTFReaderSpec.h | 1 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 2 ++ Detectors/Raw/src/RawFileReaderWorkflow.cxx | 26 ++++++++++--------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h b/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h index 967013d91b3b1..607d952cdc48e 100644 --- a/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h +++ b/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h @@ -40,6 +40,7 @@ class CTFReaderSpec : public o2::framework::Task private: DetID::mask_t mDets; // detectors std::vector mInput; // input files + uint32_t mTFCounter = 0; size_t mNextToProcess = 0; TStopwatch mTimer; }; diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 6d351421854cb..3f51c63322e67 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -94,6 +94,7 @@ void CTFReaderSpec::run(ProcessingContext& pc) throw std::runtime_error(o2::utils::concat_string("failed to find output message header for ", label)); } hd->firstTForbit = ctfHeader.firstTForbit; + hd->tfCounter = mTFCounter; }; // send CTF Header @@ -133,6 +134,7 @@ void CTFReaderSpec::run(ProcessingContext& pc) LOGF(INFO, "CTF reading total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } + mTFCounter++; } ///_______________________________________ diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index 3717db7244a11..4ecbaa1180890 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -107,7 +107,7 @@ class RawReaderSpecs : public o2f::Task tfID = 0; LOG(INFO) << "Starting new loop " << loopsDone << " from the beginning of data"; } else { - LOGF(INFO, "Finished: payload of %zu bytes in %zu messages sent for %d TFs", sentSize, sentMessages, mTFIDaccum); + LOGF(INFO, "Finished: payload of %zu bytes in %zu messages sent for %d TFs", sentSize, sentMessages, mTFCounter); ctx.services().get().endOfStream(); ctx.services().get().readyToQuit(o2f::QuitRequest::Me); mDone = true; @@ -125,12 +125,12 @@ class RawReaderSpecs : public o2f::Task // read next time frame size_t tfNParts = 0, tfSize = 0; - LOG(INFO) << "Reading TF#" << mTFIDaccum << " (" << tfID << " at iteration " << loopsDone << ')'; + LOG(INFO) << "Reading TF#" << mTFCounter << " (" << tfID << " at iteration " << loopsDone << ')'; for (int il = 0; il < nlinks; il++) { auto& link = mReader->getLink(il); - if (!findOutputChannel(link, mTFIDaccum)) { // no output channel + if (!findOutputChannel(link, mTFCounter)) { // no output channel continue; } @@ -142,7 +142,7 @@ class RawReaderSpecs : public o2f::Task while (hdrTmpl.splitPayloadIndex < hdrTmpl.splitPayloadParts) { tfSize += hdrTmpl.payloadSize = link.getNextHBFSize(); - o2::header::Stack headerStack{hdrTmpl, o2::framework::DataProcessingHeader{mTFIDaccum}}; + o2::header::Stack headerStack{hdrTmpl, o2::framework::DataProcessingHeader{mTFCounter}}; auto hdMessage = device->NewMessage(headerStack.size()); memcpy(hdMessage->GetData(), headerStack.data(), headerStack.size()); @@ -151,7 +151,7 @@ class RawReaderSpecs : public o2f::Task auto bread = link.readNextHBF(reinterpret_cast(plMessage->GetData())); if (bread != hdrTmpl.payloadSize) { LOG(ERROR) << "Link " << il << " read " << bread << " bytes instead of " << hdrTmpl.payloadSize - << " expected in TF=" << mTFIDaccum << " part=" << hdrTmpl.splitPayloadIndex; + << " expected in TF=" << mTFCounter << " part=" << hdrTmpl.splitPayloadIndex; } // check if the RDH to send corresponds to expected orbit if (hdrTmpl.splitPayloadIndex == 0) { @@ -164,8 +164,10 @@ class RawReaderSpecs : public o2f::Task link.origin.as(), link.description.as(), link.subspec); } } - hdrTmpl.firstTForbit = hbOrbRead + loopsDone * nhbexp; // for next parts - reinterpret_cast(hdMessage->GetData())->firstTForbit = hdrTmpl.firstTForbit; + hdrTmpl.firstTForbit = hbOrbRead; // will be picked for the + hdrTmpl.tfCounter = mTFCounter; // following parts + reinterpret_cast(hdMessage->GetData())->firstTForbit = hbOrbRead; // but need to fix + reinterpret_cast(hdMessage->GetData())->tfCounter = mTFCounter; // for the 1st one } FairMQParts* parts = nullptr; parts = messagesPerRoute[link.fairMQChannel].get(); // FairMQParts* @@ -178,11 +180,11 @@ class RawReaderSpecs : public o2f::Task hdrTmpl.splitPayloadIndex++; // prepare for next tfNParts++; } - LOGF(DEBUG, "Added %d parts for TF#%d(%d in iteration %d) of %s/%s/0x%u", hdrTmpl.splitPayloadParts, mTFIDaccum, tfID, + LOGF(DEBUG, "Added %d parts for TF#%d(%d in iteration %d) of %s/%s/0x%u", hdrTmpl.splitPayloadParts, mTFCounter, tfID, loopsDone, link.origin.as(), link.description.as(), link.subspec); } - if (mTFIDaccum) { // delay sending + if (mTFCounter) { // delay sending usleep(mDelayUSec); } @@ -192,12 +194,12 @@ class RawReaderSpecs : public o2f::Task } LOGF(INFO, "Sent payload of %zu bytes in %zu parts in %zu messages for TF %d", tfSize, tfNParts, - messagesPerRoute.size(), mTFIDaccum); + messagesPerRoute.size(), mTFCounter); sentSize += tfSize; sentMessages += tfNParts; mReader->setNextTFToRead(++tfID); - ++mTFIDaccum; + ++mTFCounter; } uint32_t getMinTFID() const { return mMinTFID; } @@ -210,7 +212,7 @@ class RawReaderSpecs : public o2f::Task private: int mLoop = 0; // once last TF reached, loop while mLoop>=0 - size_t mTFIDaccum = 0; // TFId accumulator (accounts for looping) + uint32_t mTFCounter = 0; // TFId accumulator (accounts for looping) uint32_t mDelayUSec = 0; // Delay in microseconds between TFs uint32_t mMinTFID = 0; // 1st TF to extract uint32_t mMaxTFID = 0xffffffff; // last TF to extrct From d9a2a5b12e6b3b901248286f451e03a1eb34c77b Mon Sep 17 00:00:00 2001 From: Roberto Preghenella Date: Mon, 6 Jul 2020 12:09:28 +0200 Subject: [PATCH 0043/1751] Changes related to HepMC3 upgrade to 3.2.2 --- Generators/CMakeLists.txt | 14 ++++++++ .../include/Generators/GeneratorHepMC.h | 18 ++++++++++ Generators/src/GeneratorHepMC.cxx | 35 +++++++++++++++++++ dependencies/FindHepMC3.cmake | 28 +++++++++++++++ dependencies/O2SimulationDependencies.cmake | 17 +++++++-- 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 dependencies/FindHepMC3.cmake diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index 05054953ca90d..fc33264049b34 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -20,6 +20,10 @@ if(HepMC_FOUND) set(hepmcTarget MC::HepMC) endif() +if(HepMC3_FOUND) + set(hepmcTarget MC::HepMC3) +endif() + o2_add_library(Generators SOURCES src/Generator.cxx src/Trigger.cxx @@ -40,6 +44,7 @@ o2_add_library(Generators $<$:src/GeneratorPythia8Param.cxx> $<$:src/DecayerPythia8Param.cxx> $<$:src/GeneratorHepMC.cxx> + $<$:src/GeneratorHepMC.cxx> PUBLIC_LINK_LIBRARIES FairRoot::Base O2::SimConfig O2::CommonUtils O2::SimulationDataFormat ${pythia6Target} ${pythiaTarget} ${hepmcTarget} FairRoot::Gen @@ -55,6 +60,11 @@ endif() if(HepMC_FOUND) target_compile_definitions(${targetName} PUBLIC GENERATORS_WITH_HEPMC3) + target_compile_definitions(${targetName} PUBLIC GENERATORS_WITH_HEPMC3_DEPRECATED) +endif() + +if(HepMC3_FOUND) + target_compile_definitions(${targetName} PUBLIC GENERATORS_WITH_HEPMC3) endif() set(headers @@ -89,6 +99,10 @@ if(HepMC_FOUND) list(APPEND headers include/Generators/GeneratorHepMC.h) endif() +if(HepMC3_FOUND) + list(APPEND headers include/Generators/GeneratorHepMC.h) +endif() + o2_target_root_dictionary(Generators HEADERS ${headers}) o2_add_test_root_macro(share/external/extgen.C diff --git a/Generators/include/Generators/GeneratorHepMC.h b/Generators/include/Generators/GeneratorHepMC.h index 0176bc3525aa3..cca39d7d2f02e 100644 --- a/Generators/include/Generators/GeneratorHepMC.h +++ b/Generators/include/Generators/GeneratorHepMC.h @@ -16,12 +16,21 @@ #include "Generators/Generator.h" #include +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED namespace HepMC { class Reader; class GenEvent; class FourVector; } // namespace HepMC +#else +namespace HepMC3 +{ +class Reader; +class GenEvent; +class FourVector; +} // namespace HepMC3 +#endif namespace o2 { @@ -60,14 +69,23 @@ class GeneratorHepMC : public Generator Bool_t importParticles() override; /** methods **/ +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED const HepMC::FourVector getBoostedVector(const HepMC::FourVector& vector, Double_t boost); +#else + const HepMC3::FourVector getBoostedVector(const HepMC3::FourVector& vector, Double_t boost); +#endif /** HepMC interface **/ std::ifstream mStream; //! std::string mFileName; Int_t mVersion; +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED HepMC::Reader* mReader; //! HepMC::GenEvent* mEvent; //! +#else + HepMC3::Reader* mReader; //! + HepMC3::GenEvent* mEvent; //! +#endif ClassDefOverride(GeneratorHepMC, 1); diff --git a/Generators/src/GeneratorHepMC.cxx b/Generators/src/GeneratorHepMC.cxx index e738f4dc18d99..fc970adcfc5ce 100644 --- a/Generators/src/GeneratorHepMC.cxx +++ b/Generators/src/GeneratorHepMC.cxx @@ -10,6 +10,8 @@ /// \author R+Preghenella - August 2017 +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED + #include "Generators/GeneratorHepMC.h" #include "HepMC/ReaderAscii.h" #include "HepMC/ReaderAsciiHepMC2.h" @@ -27,6 +29,19 @@ #undef DEBUG #endif +#else + +#include "Generators/GeneratorHepMC.h" +#include "HepMC3/ReaderAscii.h" +#include "HepMC3/ReaderAsciiHepMC2.h" +#include "HepMC3/GenEvent.h" +#include "HepMC3/GenParticle.h" +#include "HepMC3/GenVertex.h" +#include "HepMC3/FourVector.h" +#include "TParticle.h" + +#endif + #include "FairLogger.h" #include "FairPrimaryGenerator.h" #include @@ -44,7 +59,11 @@ GeneratorHepMC::GeneratorHepMC() { /** default constructor **/ +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED mEvent = new HepMC::GenEvent(); +#else + mEvent = new HepMC3::GenEvent(); +#endif mInterface = reinterpret_cast(mEvent); mInterfaceName = "hepmc"; } @@ -56,7 +75,11 @@ GeneratorHepMC::GeneratorHepMC(const Char_t* name, const Char_t* title) { /** constructor **/ +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED mEvent = new HepMC::GenEvent(); +#else + mEvent = new HepMC3::GenEvent(); +#endif mInterface = reinterpret_cast(mEvent); mInterfaceName = "hepmc"; } @@ -89,7 +112,11 @@ Bool_t GeneratorHepMC::generateEvent() if (mReader->failed()) return kFALSE; /** set units to desired output **/ +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED mEvent->set_units(HepMC::Units::GEV, HepMC::Units::MM); +#else + mEvent->set_units(HepMC3::Units::GEV, HepMC3::Units::MM); +#endif /** success **/ return kTRUE; @@ -163,10 +190,18 @@ Bool_t GeneratorHepMC::Init() switch (mVersion) { case 2: mStream.close(); +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED mReader = new HepMC::ReaderAsciiHepMC2(mFileName); +#else + mReader = new HepMC3::ReaderAsciiHepMC2(mFileName); +#endif break; case 3: +#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED mReader = new HepMC::ReaderAscii(mStream); +#else + mReader = new HepMC3::ReaderAscii(mStream); +#endif break; default: LOG(FATAL) << "Unsupported HepMC version: " << mVersion << std::endl; diff --git a/dependencies/FindHepMC3.cmake b/dependencies/FindHepMC3.cmake new file mode 100644 index 0000000000000..3f9233814f66d --- /dev/null +++ b/dependencies/FindHepMC3.cmake @@ -0,0 +1,28 @@ +# 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. + +# use the HepMCConfig.cmake provided by the HepMC3 installation to create a +# single target HepMC with the include directories and libraries we need + +find_package(HepMC3 NO_MODULE) +if(NOT HepMC3_FOUND) + return() +endif() + +add_library(HepMC3 IMPORTED INTERFACE) + +set_target_properties(HepMC3 + PROPERTIES + INTERFACE_LINK_LIBRARIES "${HEPMC3_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${HEPMC3_INCLUDE_DIR}") + +# Promote the imported target to global visibility (so we can alias it) +set_target_properties(HepMC3 PROPERTIES IMPORTED_GLOBAL TRUE) +add_library(MC::HepMC3 ALIAS HepMC3) diff --git a/dependencies/O2SimulationDependencies.cmake b/dependencies/O2SimulationDependencies.cmake index 7231c58706de8..0370093c14d4f 100644 --- a/dependencies/O2SimulationDependencies.cmake +++ b/dependencies/O2SimulationDependencies.cmake @@ -69,8 +69,19 @@ set_package_properties(VGM PROPERTIES TYPE ${mcPackageRequirement}) find_package(HepMC MODULE) set_package_properties(HepMC PROPERTIES - TYPE ${mcPackageRequirement} DESCRIPTION - "the HepMC3 event record package") + TYPE OPTIONAL DESCRIPTION + "the HepMC3 event record package (deprecated old find_package call)") + +find_package(HepMC3 MODULE) +set_package_properties(HepMC3 + PROPERTIES + TYPE OPTIONAL DESCRIPTION + "the HepMC3 event record package") + +if(HepMC_FOUND AND HepMC3_FOUND) + message(ERROR "Both HepMC3 packages have been found, something is wrong") +endif() + set(doBuildSimulation OFF) if(pythia_FOUND @@ -79,7 +90,7 @@ if(pythia_FOUND AND Geant4_FOUND AND Geant4VMC_FOUND AND VGM_FOUND - AND HepMC_FOUND) + AND (HepMC_FOUND OR HepMC3_FOUND)) set(doBuildSimulation ON) endif() From 6631dcc9c4ba62fb25a6aa192a0fca018ed46671 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Tue, 7 Jul 2020 15:15:32 +0200 Subject: [PATCH 0044/1751] DPL Analysis: prevent crashes in Filtered with empty tables in grouping --- Framework/Core/include/Framework/ASoA.h | 27 ++++++++++++++++--------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 5241809b4a4e7..9d602b2ba49fa 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -889,11 +889,6 @@ class Table return RowViewSentinel{mEnd}; } - unfiltered_iterator iteratorAt(uint64_t i) - { - return mBegin + (i - mOffset); - } - filtered_iterator filtered_begin(SelectionVector selection) { // Note that the FilteredIndexPolicy will never outlive the selection which @@ -903,9 +898,9 @@ class Table return filtered_iterator(mColumnChunks, {selection, mOffset}); } - RowViewSentinel filtered_end(SelectionVector selection) + unfiltered_iterator iteratorAt(uint64_t i) { - return RowViewSentinel{selection.size()}; + return mBegin + (i - mOffset); } unfiltered_const_iterator begin() const @@ -1340,17 +1335,25 @@ class Filtered : public T Filtered(std::vector>&& tables, SelectionVector&& selection, uint64_t offset = 0) : T{std::move(tables), offset}, mSelectedRows{std::forward(selection)}, - mFilteredBegin{table_t::filtered_begin(mSelectedRows)}, mFilteredEnd{mSelectedRows.size()} { + if (tableSize() == 0) { + mFilteredBegin = mFilteredEnd; + } else { + mFilteredBegin = table_t::filtered_begin(mSelectedRows); + } } Filtered(std::vector>&& tables, framework::expressions::Selection selection, uint64_t offset = 0) : T{std::move(tables), offset}, mSelectedRows{copySelection(selection)}, - mFilteredBegin{table_t::filtered_begin(mSelectedRows)}, mFilteredEnd{mSelectedRows.size()} { + if (tableSize() == 0) { + mFilteredBegin = mFilteredEnd; + } else { + mFilteredBegin = table_t::filtered_begin(mSelectedRows); + } } Filtered(std::vector>&& tables, gandiva::NodePtr const& tree, uint64_t offset = 0) @@ -1358,9 +1361,13 @@ class Filtered : public T mSelectedRows{copySelection(framework::expressions::createSelection(this->asArrowTable(), framework::expressions::createFilter(this->asArrowTable()->schema(), framework::expressions::makeCondition(tree))))}, - mFilteredBegin{table_t::filtered_begin(mSelectedRows)}, mFilteredEnd{mSelectedRows.size()} { + if (tableSize() == 0) { + mFilteredBegin = mFilteredEnd; + } else { + mFilteredBegin = table_t::filtered_begin(mSelectedRows); + } } iterator begin() From bb1b8bd8a598afc99e226dc28ea637760e1e6cdd Mon Sep 17 00:00:00 2001 From: saganatt <8majak8@gmail.com> Date: Wed, 8 Jul 2020 11:00:52 +0200 Subject: [PATCH 0045/1751] DPL Analysis: add partitions (#3944) --- Analysis/Tutorials/CMakeLists.txt | 5 + Analysis/Tutorials/src/partitions.cxx | 66 +++++++++ .../Core/include/Framework/AnalysisTask.h | 133 +++++++++++++++++- 3 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 Analysis/Tutorials/src/partitions.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index b3717f9ccfe94..ac029f4c7427b 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -62,6 +62,11 @@ o2_add_dpl_workflow(filters PUBLIC_LINK_LIBRARIES O2::Framework COMPONENT_NAME AnalysisTutorial) +o2_add_dpl_workflow(partitions + SOURCES src/partitions.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + COMPONENT_NAME AnalysisTutorial) + o2_add_dpl_workflow(aodwriter SOURCES src/aodwriter.cxx PUBLIC_LINK_LIBRARIES O2::Framework diff --git a/Analysis/Tutorials/src/partitions.cxx b/Analysis/Tutorials/src/partitions.cxx new file mode 100644 index 0000000000000..50806e953095f --- /dev/null +++ b/Analysis/Tutorials/src/partitions.cxx @@ -0,0 +1,66 @@ +// 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" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// This is a very simple example showing how to iterate over tracks +// and create a new collection for them. +// FIXME: this should really inherit from AnalysisTask but +// we need GCC 7.4+ for that +struct ATask { + float fPI = static_cast(M_PI); + float ptlow = 0.5f; + float ptup = 2.0f; + Filter ptFilter_a = aod::track::pt > ptlow; + Filter ptFilter_b = aod::track::pt < ptup; + + float etalow = -1.0f; + float etaup = 1.0f; + Filter etafilter = (aod::track::eta < etaup) && (aod::track::eta > etalow); + + float philow = 1.0f; + float phiup = 2.0f; + Partition> leftPhiP = aod::track::phiraw < philow; + Partition> midPhiP = aod::track::phiraw >= philow && aod::track::phiraw < phiup; + Partition> rightPhiP = aod::track::phiraw >= phiup; + + void process(aod::Collision const& collision, soa::Filtered const& tracks) + { + auto& leftPhi = leftPhiP.getPartition(); + auto& midPhi = midPhiP.getPartition(); + auto& rightPhi = rightPhiP.getPartition(); + LOGF(INFO, "Collision: %d [N = %d] [left phis = %d] [mid phis = %d] [right phis = %d]", + collision.globalIndex(), tracks.size(), leftPhi.size(), midPhi.size(), rightPhi.size()); + + 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); + } + 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); + } + 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); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask("consume-tracks")}; +} diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 74c833c0164cf..169a677aecd02 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -20,6 +20,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/DataProcessorSpec.h" #include "Framework/Expressions.h" +#include "../src/ExpressionHelpers.h" #include "Framework/EndOfStreamContext.h" #include "Framework/Logger.h" #include "Framework/HistogramRegistry.h" @@ -262,6 +263,97 @@ struct Configurable { } }; +template +struct Partition { + Partition(expressions::Node&& node) + { + auto filter = expressions::Filter(std::move(node)); + auto schema = o2::soa::createSchemaFromColumns(typename T::table_t::persistent_columns_t{}); + expressions::Operations ops = createOperations(filter); + if (isSchemaCompatible(schema, ops)) { + mTree = createExpressionTree(ops, schema); + } else { + throw std::runtime_error("Partition filter does not match declared table type"); + } + } + + void setTable(const T& table) + { + mFiltered.reset(new o2::soa::Filtered{{table.asArrowTable()}, mTree}); + } + + template + void bindExternalIndices(Ts*... tables) + { + if (mFiltered != nullptr) { + mFiltered->bindExternalIndices(tables...); + } + } + + template + void getBoundToExternalIndices(T2& table) + { + if (mFiltered != nullptr) { + table.bindExternalIndices(mFiltered.get()); + } + } + + o2::soa::Filtered& getPartition() + { + return *mFiltered; + } + + gandiva::NodePtr mTree; + std::unique_ptr> mFiltered; +}; + +template +struct PartitionManager { + template + static void setPartition(ANY&, T2s&... tables) + { + } + + template + static void bindExternalIndices(ANY&, Ts*... tables) + { + } + + template + static void getBoundToExternalIndices(ANY& partition, Ts&... tables) + { + } +}; + +template +struct PartitionManager> { + template + static void doSetPartition(Partition& partition, T2& table) + { + if constexpr (std::is_same_v) { + partition.setTable(table); + } + } + + template + static void setPartition(Partition& partition, T2s&... tables) + { + (doSetPartition(partition, tables), ...); + } + + template + static void bindExternalIndices(Partition& partition, Ts*... tables) + { + partition.bindExternalIndices(tables...); + } + + template + static void getBoundToExternalIndices(Partition& partition, Ts&... tables) + { + partition.getBoundToExternalIndices(tables...); + } +}; + struct AnalysisTask { }; @@ -291,7 +383,7 @@ struct AnalysisDataProcessorBuilder { if constexpr (framework::is_specialization::value) { eInfos.push_back({At, o2::soa::createSchemaFromColumns(typename dT::table_t::persistent_columns_t{}), nullptr}); } else if constexpr (soa::is_soa_iterator_t
::value) { - if (std::is_same_v) { + if constexpr (std::is_same_v) { eInfos.push_back({At, o2::soa::createSchemaFromColumns(typename dT::table_t::persistent_columns_t{}), nullptr}); } } @@ -589,10 +681,23 @@ struct AnalysisDataProcessorBuilder { template static void invokeProcess(Task& task, InputRecord& inputs, R (C::*)(Grouping, Associated...), std::vector const& infos) { + auto tupledTask = o2::framework::to_tuple_refs(task); using G = std::decay_t; auto groupingTable = AnalysisDataProcessorBuilder::bindGroupingTable(inputs, &C::process, infos); + + // set filtered tables for partitions with grouping + std::apply([&groupingTable](auto&... x) { + (PartitionManager>::setPartition(x, groupingTable), ...); + }, + tupledTask); + if constexpr (sizeof...(Associated) == 0) { // single argument to process + std::apply([&groupingTable](auto&... x) { + (PartitionManager>::bindExternalIndices(x, &groupingTable), ...); + (PartitionManager>::getBoundToExternalIndices(x, groupingTable), ...); + }, + tupledTask); if constexpr (soa::is_soa_iterator_t::value) { for (auto& element : groupingTable) { task.process(*element); @@ -609,6 +714,12 @@ struct AnalysisDataProcessorBuilder { auto associatedTables = AnalysisDataProcessorBuilder::bindAssociatedTables(inputs, &C::process, infos); auto binder = [&](auto&& x) { x.bindExternalIndices(&groupingTable, &std::get>(associatedTables)...); + std::apply([&x](auto&... t) { + (PartitionManager>::setPartition(t, x), ...); + (PartitionManager>::bindExternalIndices(t, &x), ...); + (PartitionManager>::getBoundToExternalIndices(t, x), ...); + }, + tupledTask); }; groupingTable.bindExternalIndices(&std::get>(associatedTables)...); @@ -617,22 +728,38 @@ struct AnalysisDataProcessorBuilder { auto slicer = GroupSlicer(groupingTable, associatedTables); for (auto& slice : slicer) { auto associatedSlices = slice.associatedTables(); + std::apply( [&](auto&&... x) { (binder(x), ...); }, associatedSlices); + // bind partitions and grouping table + std::apply([&groupingTable](auto&... x) { + (PartitionManager>::bindExternalIndices(x, &groupingTable), ...); + (PartitionManager>::getBoundToExternalIndices(x, groupingTable), ...); + }, + tupledTask); + invokeProcessWithArgs(task, slice.groupingElement(), associatedSlices); } } else { // non-grouping case + std::apply( [&](auto&&... x) { (binder(x), ...); }, associatedTables); + // bind partitions and grouping table + std::apply([&groupingTable](auto&... x) { + (PartitionManager>::bindExternalIndices(x, &groupingTable), ...); + (PartitionManager>::getBoundToExternalIndices(x, groupingTable), ...); + }, + tupledTask); + invokeProcessWithArgs(task, groupingTable, associatedTables); } } @@ -645,9 +772,8 @@ struct AnalysisDataProcessorBuilder { } }; -template +template struct FilterManager { - template static bool createExpressionTrees(ANY&, std::vector&) { return false; @@ -658,7 +784,6 @@ template <> struct FilterManager { static bool createExpressionTrees(expressions::Filter const& filter, std::vector& expressionInfos) { - updateExpressionInfos(filter, expressionInfos); return true; } From 0657bf4a02db8a0b83e4de0768c723d5071f4092 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 8 Jul 2020 03:10:36 +0200 Subject: [PATCH 0046/1751] raw-file-reader will create part per SP in FMQ multiparts To create part per HBF use option --part-per-hbf --- Detectors/Raw/README.md | 6 +- .../Raw/include/DetectorsRaw/RawFileReader.h | 2 + Detectors/Raw/src/RawFileReader.cxx | 55 +++++++++++++++++++ Detectors/Raw/src/RawFileReaderWorkflow.cxx | 54 +++++++++--------- Detectors/Raw/src/RawFileReaderWorkflow.h | 3 +- Detectors/Raw/src/rawfile-reader-workflow.cxx | 6 +- 6 files changed, 95 insertions(+), 31 deletions(-) diff --git a/Detectors/Raw/README.md b/Detectors/Raw/README.md index 20b26467f49fa..6b94e1f94cc43 100644 --- a/Detectors/Raw/README.md +++ b/Detectors/Raw/README.md @@ -302,6 +302,8 @@ o2-raw-file-reader-workflow --max-tf arg (=4294967295) max TF ID to process --delay arg (=0) delay in seconds between consecutive TFs sending --buffer-size arg (=1048576) buffer size for files preprocessing + --super-page-size arg (=1048576) super-page size for FMQ parts definition + --part-per-hbf FMQ parts per superpage (default) of HBF --raw-channel-config arg optional raw FMQ channel for non-DPL output --configKeyValues arg semicolon separated key=value strings @@ -323,8 +325,8 @@ scheme. If `--loop` argument is provided, data will be re-played in loop. The delay (in seconds) can be added between sensding of consecutive TFs to avoid pile-up of TFs. -At every invocation of the device `processing` callback a full TimeFrame for every link will be added as N-HBFs parts (one for each HBF in the TF) to the multipart -relayed by the `FairMQ` channel. +At every invocation of the device `processing` callback a full TimeFrame for every link will be added as a multi-part `FairMQ` message and relayed by the relevant channel. +By default each part will be a single CRU super-page of the link. This behaviour can be changed by providing `part-per-hbf` option, in which case each HBF will be added as a separate HBF. The standard use case of this workflow is to provide the input for other worfklows using the piping, e.g. ```cpp diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index d5705907e4bca..a73840d731df2 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -155,10 +155,12 @@ class RawFileReader size_t getLargestTF() const; size_t getNextHBFSize() const; size_t getNextTFSize() const; + size_t getNextTFSuperPagesStat(std::vector& parts) const; int getNHBFinTF() const; size_t readNextHBF(char* buff); size_t readNextTF(char* buff); + size_t readNextSuperPage(char* buff); size_t skipNextHBF(); size_t skipNextTF(); diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index c3f711cb3a7f0..1307022fd85c0 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -71,6 +71,31 @@ void RawFileReader::LinkData::print(bool verbose, const std::string& pref) const } } +//____________________________________________ +size_t RawFileReader::LinkData::getNextTFSuperPagesStat(std::vector& parts) const +{ + // get stat. of superpages for this link in this TF. We treat as a start of a superpage the discontinuity in the link data, new TF + // or continuous data exceeding a threshold (e.g. 1MB) + size_t sz = 0; + int nSP = 0; + int ibl = nextBlock2Read, nbl = blocks.size(); + parts.clear(); + while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { + if (ibl > nextBlock2Read && (blocks[ibl].testFlag(LinkBlock::StartSP) || + (sz + blocks[ibl].size) > reader->mNominalSPageSize || + (blocks[ibl - 1].offset + blocks[ibl - 1].size) < blocks[ibl].offset)) { // new superpage + parts.push_back(sz); + sz = 0; + } + sz += blocks[ibl].size; + ibl++; + } + if (sz) { + parts.push_back(sz); + } + return parts.size(); +} + //____________________________________________ size_t RawFileReader::LinkData::getNextHBFSize() const { @@ -200,6 +225,36 @@ int RawFileReader::LinkData::getNHBFinTF() const return nHB; } +//____________________________________________ +size_t RawFileReader::LinkData::readNextSuperPage(char* buff) +{ + // read data of the next complete HB, buffer of getNextHBFSize() must be allocated in advance + size_t sz = 0; + int ibl = nextBlock2Read, nbl = blocks.size(); + auto tfID = blocks[nextBlock2Read].tfID; + bool error = false; + + while (ibl < nbl) { + const auto& blc = blocks[ibl]; + if (ibl > nextBlock2Read && (blc.tfID != blocks[nextBlock2Read].tfID || + blc.testFlag(LinkBlock::StartSP) || + (sz + blc.size) > reader->mNominalSPageSize || + blocks[ibl - 1].offset + blocks[ibl - 1].size < blc.offset)) { // new superpage or TF + break; + } + ibl++; + auto fl = reader->mFiles[blc.fileID]; + if (fseek(fl, blc.offset, SEEK_SET) || fread(buff + sz, 1, blc.size, fl) != blc.size) { + LOGF(ERROR, "Failed to read for the %s a bloc:", describe()); + blc.print(); + error = true; + } + sz += blc.size; + } + nextBlock2Read = ibl; + return error ? 0 : sz; // in case of the error we ignore the data +} + //____________________________________________ size_t RawFileReader::LinkData::getLargestSuperPage() const { diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index 4ecbaa1180890..6e77f572d17d8 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -46,12 +46,15 @@ class RawReaderSpecs : public o2f::Task { public: explicit RawReaderSpecs(const std::string& config, int loop = 1, uint32_t delay_us = 0, - uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t buffSize = 1024L * 1024L, const std::string& rawChannelName = "") - : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mReader(std::make_unique(config)), mRawChannelName(rawChannelName) + uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, + size_t spSize = 1024L * 1024L, size_t buffSize = 1024L * 1024L, + const std::string& rawChannelName = "") + : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mPartPerSP(partPerSP), mReader(std::make_unique(config)), mRawChannelName(rawChannelName) { mReader->setCheckErrors(errmap); mReader->setMaxTFToRead(maxTF); mReader->setBufferSize(buffSize); + mReader->setNominalSPageSize(spSize); LOG(INFO) << "Will preprocess files with buffer size of " << buffSize << " bytes"; LOG(INFO) << "Number of loops over whole data requested: " << mLoop; } @@ -72,7 +75,6 @@ class RawReaderSpecs : public o2f::Task if (mDone) { return; } - int nhbexp = HBFUtils::Instance().getNOrbitsPerTF(); auto device = ctx.services().get().device(); assert(device); @@ -122,10 +124,14 @@ class RawReaderSpecs : public o2f::Task for (int il = 0; il < nlinks; il++) { mReader->getLink(il).rewindToTF(tfID); } + std::vector partsSP; + const auto& hbfU = HBFUtils::Instance(); // read next time frame size_t tfNParts = 0, tfSize = 0; LOG(INFO) << "Reading TF#" << mTFCounter << " (" << tfID << " at iteration " << loopsDone << ')'; + o2::header::Stack dummyStack{o2h::DataHeader{}, o2::framework::DataProcessingHeader{0}}; // dummy stack to just to get stack size + auto hstackSize = dummyStack.size(); for (int il = 0; il < nlinks; il++) { auto& link = mReader->getLink(il); @@ -135,40 +141,33 @@ class RawReaderSpecs : public o2f::Task } o2h::DataHeader hdrTmpl(link.description, link.origin, link.subspec); // template with 0 size - int nhb = link.getNHBFinTF(); + int nParts = mPartPerSP ? link.getNextTFSuperPagesStat(partsSP) : link.getNHBFinTF(); hdrTmpl.payloadSerializationMethod = o2h::gSerializationMethodNone; - hdrTmpl.splitPayloadParts = nhb; + hdrTmpl.splitPayloadParts = nParts; while (hdrTmpl.splitPayloadIndex < hdrTmpl.splitPayloadParts) { - tfSize += hdrTmpl.payloadSize = link.getNextHBFSize(); - o2::header::Stack headerStack{hdrTmpl, o2::framework::DataProcessingHeader{mTFCounter}}; - - auto hdMessage = device->NewMessage(headerStack.size()); - memcpy(hdMessage->GetData(), headerStack.data(), headerStack.size()); + tfSize += hdrTmpl.payloadSize = mPartPerSP ? partsSP[hdrTmpl.splitPayloadIndex] : link.getNextHBFSize(); + auto hdMessage = device->NewMessage(hstackSize); auto plMessage = device->NewMessage(hdrTmpl.payloadSize); - auto bread = link.readNextHBF(reinterpret_cast(plMessage->GetData())); + auto bread = mPartPerSP ? link.readNextSuperPage(reinterpret_cast(plMessage->GetData())) : link.readNextHBF(reinterpret_cast(plMessage->GetData())); if (bread != hdrTmpl.payloadSize) { LOG(ERROR) << "Link " << il << " read " << bread << " bytes instead of " << hdrTmpl.payloadSize << " expected in TF=" << mTFCounter << " part=" << hdrTmpl.splitPayloadIndex; } // check if the RDH to send corresponds to expected orbit if (hdrTmpl.splitPayloadIndex == 0) { - uint32_t hbOrbRead = o2::raw::RDHUtils::getHeartBeatOrbit(plMessage->GetData()); - if (link.cruDetector) { - uint32_t hbOrbExpected = mReader->getOrbitMin() + tfID * nhbexp; - if (hbOrbExpected != hbOrbRead) { - LOGF(ERROR, "Expected orbit=%u but got %u for %d-th HBF in TF#%d of %s/%s/0x%u", - hbOrbExpected, hbOrbRead, hdrTmpl.splitPayloadIndex, tfID, - link.origin.as(), link.description.as(), link.subspec); - } - } - hdrTmpl.firstTForbit = hbOrbRead; // will be picked for the + auto ir = o2::raw::RDHUtils::getHeartBeatIR(plMessage->GetData()); + auto tfid = hbfU.getTF(ir); + hdrTmpl.firstTForbit = hbfU.getIRTF(tfid).orbit; // will be picked for the hdrTmpl.tfCounter = mTFCounter; // following parts - reinterpret_cast(hdMessage->GetData())->firstTForbit = hbOrbRead; // but need to fix - reinterpret_cast(hdMessage->GetData())->tfCounter = mTFCounter; // for the 1st one + // reinterpret_cast(hdMessage->GetData())->firstTForbit = hdrTmpl.firstTForbit; // hack to fix already filled headers + // reinterpret_cast(hdMessage->GetData())->tfCounter = mTFCounter; // at the moment don't use it } + o2::header::Stack headerStack{hdrTmpl, o2::framework::DataProcessingHeader{mTFCounter}}; + memcpy(hdMessage->GetData(), headerStack.data(), headerStack.size()); + FairMQParts* parts = nullptr; parts = messagesPerRoute[link.fairMQChannel].get(); // FairMQParts* if (!parts) { @@ -216,13 +215,14 @@ class RawReaderSpecs : public o2f::Task uint32_t mDelayUSec = 0; // Delay in microseconds between TFs uint32_t mMinTFID = 0; // 1st TF to extract uint32_t mMaxTFID = 0xffffffff; // last TF to extrct + bool mPartPerSP = true; // fill part per superpage bool mDone = false; // processing is over or not std::string mRawChannelName = ""; // name of optional non-DPL channel std::unique_ptr mReader; // matching engine }; o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t delay_us, uint32_t errmap, - uint32_t minTF, uint32_t maxTF, size_t buffSize, const std::string& rawChannelConfig) + uint32_t minTF, uint32_t maxTF, bool partPerSP, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) { // check which inputs are present in files to read o2f::DataProcessorSpec spec; @@ -253,15 +253,15 @@ o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t dela LOG(INFO) << "Will send output to non-DPL channel " << rawChannelConfig; } - spec.algorithm = o2f::adaptFromTask(config, loop, delay_us, errmap, minTF, maxTF, buffSize, rawChannelName); + spec.algorithm = o2f::adaptFromTask(config, loop, delay_us, errmap, minTF, maxTF, partPerSP, spSize, buffSize, rawChannelName); return spec; } o2f::WorkflowSpec o2::raw::getRawFileReaderWorkflow(std::string inifile, int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, - size_t buffSize, const std::string& rawChannelConfig) + bool partPerSP, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) { o2f::WorkflowSpec specs; - specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize, rawChannelConfig)); + specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, spSize, buffSize, rawChannelConfig)); return specs; } diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.h b/Detectors/Raw/src/RawFileReaderWorkflow.h index 6a62f4eeec98b..bbe3a808512d5 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.h +++ b/Detectors/Raw/src/RawFileReaderWorkflow.h @@ -22,7 +22,8 @@ namespace raw { framework::WorkflowSpec getRawFileReaderWorkflow(std::string inifile, int loop = 1, uint32_t delay_us = 0, uint32_t errMap = 0xffffffff, - uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, size_t bufferSize = 1024L * 1024L, + uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, + size_t spSize = 1024L * 1024L, size_t bufferSize = 1024L * 1024L, const std::string& rawChannelConfig = ""); } // namespace raw diff --git a/Detectors/Raw/src/rawfile-reader-workflow.cxx b/Detectors/Raw/src/rawfile-reader-workflow.cxx index b8501184b5ba8..7962b0f50c7c4 100644 --- a/Detectors/Raw/src/rawfile-reader-workflow.cxx +++ b/Detectors/Raw/src/rawfile-reader-workflow.cxx @@ -29,6 +29,8 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"loop", VariantType::Int, 1, {"loop N times (infinite for N<0)"}}); options.push_back(ConfigParamSpec{"delay", VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); options.push_back(ConfigParamSpec{"buffer-size", VariantType::Int64, 1024L * 1024L, {"buffer size for files preprocessing"}}); + options.push_back(ConfigParamSpec{"super-page-size", VariantType::Int64, 1024L * 1024L, {"super-page size for FMQ parts definition"}}); + options.push_back(ConfigParamSpec{"part-per-hbf", VariantType::Bool, false, {"FMQ parts per superpage (default) of HBF"}}); options.push_back(ConfigParamSpec{"raw-channel-config", VariantType::String, "", {"optional raw FMQ channel for non-DPL output"}}); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}); // options for error-check suppression @@ -51,6 +53,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) uint32_t maxTF = uint32_t(configcontext.options().get("max-tf")); uint32_t minTF = uint32_t(configcontext.options().get("min-tf")); uint64_t buffSize = uint64_t(configcontext.options().get("buffer-size")); + uint64_t spSize = uint64_t(configcontext.options().get("super-page-size")); + bool partPerSP = !configcontext.options().get("part-per-hbf"); std::string rawChannelConfig = configcontext.options().get("raw-channel-config"); uint32_t errmap = 0; for (int i = RawFileReader::NErrorsDefined; i--;) { @@ -63,5 +67,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); uint32_t delay_us = uint32_t(1e6 * configcontext.options().get("delay")); // delay in microseconds - return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, buffSize, rawChannelConfig)); + return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, spSize, buffSize, rawChannelConfig)); } From 0bf085a82b8f07861d9bfaf8976b6f18f8ef2965 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 6 Jul 2020 11:34:00 +0200 Subject: [PATCH 0047/1751] GPU: Use OpenMP pragma if instead of changing the thread count to 1 --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 ++-- GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx | 4 ++-- GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index e43e98b31e633..251841a23e8f8 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1474,7 +1474,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() int streamMap[NSLICES]; bool error = false; - GPUCA_OPENMP(parallel for num_threads(doGPU || GetDeviceProcessingSettings().ompKernels ? 1 : GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().nThreads)) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { GPUTPCTracker& trk = processors()->tpcTrackers[iSlice]; GPUTPCTracker& trkShadow = doGPU ? processorsShadow()->tpcTrackers[iSlice] : trk; @@ -1731,7 +1731,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } } else { mSliceSelectorReady = NSLICES; - GPUCA_OPENMP(parallel for num_threads(doGPU || GetDeviceProcessingSettings().ompKernels ? 1 : GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().nThreads)) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { if (param().rec.GlobalTracking) { GlobalTracking(iSlice, 0); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx index 33f29d5ea5bdd..1fe68b7b95fa5 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx @@ -23,7 +23,7 @@ template <> GPUdii() void GPUTPCGMMergerTrackFit::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, int mode) { const int iEnd = mode == -1 ? merger.Memory()->nRetryRefit : merger.NOutputTracks(); - GPUCA_OPENMP(parallel for num_threads(merger.GetRec().GetDeviceProcessingSettings().ompKernels ? 1 : merger.GetRec().GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().nThreads)) for (int ii = get_global_id(0); ii < iEnd; ii += get_global_size(0)) { const int i = mode == -1 ? merger.RetryRefitIds()[ii] : mode ? merger.TrackOrderProcess()[ii] : ii; GPUTPCGMTrackParam::RefitTrack(merger.OutputTracks()[i], i, &merger, mode == -1); @@ -33,7 +33,7 @@ GPUdii() void GPUTPCGMMergerTrackFit::Thread<0>(int nBlocks, int nThreads, int i template <> GPUdii() void GPUTPCGMMergerFollowLoopers::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger) { - GPUCA_OPENMP(parallel for num_threads(merger.GetRec().GetDeviceProcessingSettings().ompKernels ? 1 : merger.GetRec().GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().nThreads)) for (unsigned int i = get_global_id(0); i < merger.Memory()->nLoopData; i += get_global_size(0)) { GPUTPCGMTrackParam::RefitLoop(&merger, i); } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx index d4756f20b2562..c13e91238f5bd 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx @@ -23,7 +23,7 @@ using namespace GPUCA_NAMESPACE::gpu; template <> GPUdii() void GPUTRDTrackerKernels::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) { - GPUCA_OPENMP(parallel for num_threads(processors.trdTracker.GetRec().GetDeviceProcessingSettings().ompKernels ? 1 : processors.trdTracker.GetRec().GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!processors.trdTracker.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(processors.trdTracker.GetRec().GetDeviceProcessingSettings().nThreads)) for (int i = get_global_id(0); i < processors.trdTracker.NTracks(); i += get_global_size(0)) { processors.trdTracker.DoTrackingThread(i, get_global_id(0)); } From 6efbfea963e79d74645747f1f15d7e1d75e2a435 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 6 Jul 2020 13:00:01 +0200 Subject: [PATCH 0048/1751] GPU: OpenCL doesn't support long long int --- GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h | 2 +- GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx | 2 +- GPU/GPUTracking/Standalone/tools/testCL.sh | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h index 8b4e685b3a34e..74e2634589100 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h @@ -62,7 +62,7 @@ class GPUTPCCompressionKernels : public GPUKernelTemplate using Vec16 = unsigned short; using Vec32 = unsigned int; - using Vec64 = unsigned long long int; + using Vec64 = unsigned long int; using Vec128 = uint4; template diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx index a38db5d671e53..3daa92c3d6217 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx @@ -350,7 +350,7 @@ GPUd() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int i } GPUbarrier(); - constexpr float maxVal = (((long long int)1 << (sizeof(cahit) < 3 ? sizeof(cahit) * 8 : 24)) - 1); // Stay within float precision in any case! + constexpr float maxVal = (((long int)1 << (sizeof(cahit) < 3 ? sizeof(cahit) * 8 : 24)) - 1); // Stay within float precision in any case! constexpr float packingConstant = 1.f / (maxVal - 2.); const float y0 = row.mGrid.YMin(); const float z0 = row.mGrid.ZMin(); diff --git a/GPU/GPUTracking/Standalone/tools/testCL.sh b/GPU/GPUTracking/Standalone/tools/testCL.sh index d963dbf108e52..257591d3de3e5 100755 --- a/GPU/GPUTracking/Standalone/tools/testCL.sh +++ b/GPU/GPUTracking/Standalone/tools/testCL.sh @@ -9,9 +9,10 @@ LLVM_SPIRV=llvm-spirv #COMPILER=/home/qon/clang-build/install/bin/clang++ #LLVM_SPIRV=/home/qon/clang-build/SPIRV-LLVM-Translator/build/tools/llvm-spirv/llvm-spirv -INCLUDES="-I../. -I../Base -I../SliceTracker -I../Common -I../Merger -I../TRDTracking -I../ITS -I../dEdx -I../TPCConvert -I../TPCFastTransformation -I../DataCompression -I../TPCClusterFinder \ +INCLUDES="-I../. -I../Base -I../SliceTracker -I../Common -I../Merger -I../TRDTracking -I../ITS -I../dEdx -I../TPCConvert -I../TPCFastTransformation -I../DataCompression -I../TPCClusterFinder -I../Global -I ../GPUUtils \ -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/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" DEFINES="-DGPUCA_STANDALONE -DGPUCA_GPULIBRARY=OCL -DNDEBUG -D__OPENCLCPP__ -DHAVE_O2HEADERS -DGPUCA_TPC_GEOMETRY_O2" FLAGS="-O3 -cl-denorms-are-zero -cl-mad-enable -cl-no-signed-zeros -ferror-limit=1000 -Xclang -finclude-default-header -Dcl_clang_storage_class_specifiers" From bab521d2b0bb454b13fb26d7b0d8b942adf834df Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 8 Jul 2020 12:41:45 +0200 Subject: [PATCH 0049/1751] GPU: Fix some configuration parameter checks --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 ++++ GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 25 ++++++++++----------- GPU/GPUTracking/Standalone/standalone.cxx | 8 +++---- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 9b9cad6be1152..aff7bbee78381 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -236,7 +236,7 @@ int GPUReconstruction::InitPhaseBeforeDevice() if (param().rec.NonConsecutiveIDs) { param().rec.DisableRefitAttachment = 0xFF; } - if (!(mRecoStepsGPU & RecoStep::TPCMerging)) { + if (!(mRecoStepsGPU & RecoStep::TPCMerging) || !param().rec.mergerReadFromTrackerDirectly) { mDeviceProcessingSettings.fullMergerOnGPU = false; } if (mDeviceProcessingSettings.debugLevel || !mDeviceProcessingSettings.fullMergerOnGPU) { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 251841a23e8f8..f33a6ef1bf5f7 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -270,6 +270,10 @@ bool GPUChainTracking::ValidateSettings() GPUError("incompatible settings for non consecutive ids"); return false; } + if (!param().rec.mergerReadFromTrackerDirectly && GetDeviceProcessingSettings().ompKernels) { + GPUError("OMP Kernels require mergerReadFromTrackerDirectly"); + return false; + } if (param().continuousMaxTimeBin > (int)GPUSettings::TPC_MAX_TF_TIME_BIN) { GPUError("configure max time bin exceeds 256 orbits"); return false; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 10177cf926e5c..cadc3ca115fe2 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -461,7 +461,7 @@ GPUd() void GPUTPCGMMerger::UnpackSliceGlobal(int nBlocks, int nThreads, int iBl } else if (itr > nLocalTracks) { sliceTr = sliceTr->GetNextTrack(); } - int localId = TrackIds[(sliceTr->LocalTrackId() >> 24) * mNMaxSingleSliceTracks + (sliceTr->LocalTrackId() & 0xFFFFFF)]; + int localId = TrackIds[(sliceTr->LocalTrackId() >> 24) * mNMaxSingleSliceTracks | (sliceTr->LocalTrackId() & 0xFFFFFF)]; if (localId == -1) { continue; } @@ -481,11 +481,10 @@ GPUd() void GPUTPCGMMerger::UnpackSliceGlobal(int nBlocks, int nThreads, int iBl GPUd() void GPUTPCGMMerger::UnpackResetIds(int nBlocks, int nThreads, int iBlock, int iThread, int iSlice) { int* TrackIds = (int*)mTmpMem; - const GPUTPCTracker& trk = GetConstantMem()->tpcTrackers[iSlice]; unsigned int nLocalTracks = Param().rec.mergerReadFromTrackerDirectly ? trk.CommonMemory()->nLocalTracks : mkSlices[iSlice]->NLocalTracks(); for (unsigned int i = iBlock * nThreads + iThread; i < nLocalTracks; i += nBlocks * nThreads) { - TrackIds[iSlice * mNMaxSingleSliceTracks + i] = -1; + TrackIds[iSlice * mNMaxSingleSliceTracks | i] = -1; } } @@ -531,7 +530,7 @@ GPUd() void GPUTPCGMMerger::RefitSliceTracks(int nBlocks, int nThreads, int iBlo track.SetGlobalTrackId(0, -1); track.SetGlobalTrackId(1, -1); unsigned int myTrack = CAMath::AtomicAdd(&mMemory->nUnpackedTracks, 1u); - TrackIds[iSlice * mNMaxSingleSliceTracks + sliceTr->LocalTrackId()] = myTrack; + TrackIds[iSlice * mNMaxSingleSliceTracks | sliceTr->LocalTrackId()] = myTrack; mSliceTrackInfos[myTrack] = track; } if (!Param().rec.mergerReadFromTrackerDirectly) { @@ -539,6 +538,15 @@ GPUd() void GPUTPCGMMerger::RefitSliceTracks(int nBlocks, int nThreads, int iBlo } } +GPUd() void GPUTPCGMMerger::LinkGlobalTracks(int nBlocks, int nThreads, int iBlock, int iThread) +{ + for (int itr = SliceTrackInfoGlobalFirst(0) + iBlock * nThreads + iThread; itr < SliceTrackInfoGlobalLast(NSLICES - 1); itr += nThreads * nBlocks) { + GPUTPCGMSliceTrack& globalTrack = mSliceTrackInfos[itr]; + GPUTPCGMSliceTrack& localTrack = mSliceTrackInfos[globalTrack.LocalTrackId()]; + localTrack.SetGlobalTrackId(localTrack.GlobalTrackId(0) != -1, itr); // Todo: broken in parallel + } +} + GPUd() void GPUTPCGMMerger::MakeBorderTracks(int nBlocks, int nThreads, int iBlock, int iThread, int iBorder, GPUTPCGMBorderTrack** B, GPUAtomic(unsigned int) * nB, bool useOrigTrackParam) { //* prepare slice tracks for merging with next/previous/same sector @@ -1397,15 +1405,6 @@ struct GPUTPCGMMerger_CompareClusterIds { } }; -GPUd() void GPUTPCGMMerger::LinkGlobalTracks(int nBlocks, int nThreads, int iBlock, int iThread) -{ - for (int itr = SliceTrackInfoGlobalFirst(0) + iBlock * nThreads + iThread; itr < SliceTrackInfoGlobalLast(NSLICES - 1); itr += nThreads * nBlocks) { - GPUTPCGMSliceTrack& globalTrack = mSliceTrackInfos[itr]; - GPUTPCGMSliceTrack& localTrack = mSliceTrackInfos[globalTrack.LocalTrackId()]; - localTrack.SetGlobalTrackId(localTrack.GlobalTrackId(0) != -1, itr); - } -} - GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int iBlock, int iThread) { diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index d4553429f11ab..10d985c8215f5 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -216,10 +216,13 @@ int ReadConfiguration(int argc, char** argv) printf("Can only produce QA pdf output when input files are specified!\n"); return 1; } + if (configStandalone.configQA.inputHistogramsOnly) { + configStandalone.configRec.rundEdx = false; + } if (configStandalone.eventDisplay) { configStandalone.noprompt = 1; } - if (configStandalone.DebugLevel >= 4) { + if (configStandalone.DebugLevel >= 4 && !configStandalone.configProc.ompKernels) { configStandalone.OMPThreads = 1; } @@ -350,9 +353,6 @@ int SetupReconstruction() } recSet.loopInterpolationInExtraPass = configStandalone.configRec.loopInterpolationInExtraPass; recSet.mergerReadFromTrackerDirectly = configStandalone.configRec.mergerReadFromTrackerDirectly; - if (!recSet.mergerReadFromTrackerDirectly) { - devProc.fullMergerOnGPU = false; - } if (configStandalone.OMPThreads != -1) { devProc.nThreads = configStandalone.OMPThreads; From 189e2785cfd2d32fc5437a8f8cb8f73b85b5c044 Mon Sep 17 00:00:00 2001 From: Ivana Hrivnacova Date: Fri, 3 Jul 2020 18:23:39 +0200 Subject: [PATCH 0050/1751] Activate support for zero magnetic fields in Geant4 simulation --- Detectors/gconfig/g4config.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/gconfig/g4config.in b/Detectors/gconfig/g4config.in index b5f576a2dc6f1..28ffdb67fdfb2 100644 --- a/Detectors/gconfig/g4config.in +++ b/Detectors/gconfig/g4config.in @@ -14,6 +14,7 @@ /mcDet/setIsMaxStepInLowDensityMaterials true /mcDet/setMaxStepInLowDensityMaterials 10 m /mcMagField/setConstDistance 1 mm +/mcDet/setIsZeroMagField true # optical From 47b1df42e2d3f2a755b5fd3eea2d1ca56ca72378 Mon Sep 17 00:00:00 2001 From: carlos-soncco <33285924+carlos-soncco@users.noreply.github.com> Date: Wed, 8 Jul 2020 08:40:41 -0500 Subject: [PATCH 0051/1751] MFT: add new geometry version (#3928) --- Detectors/ITSMFT/MFT/base/src/HalfCone.cxx | 1267 ++++++++++++++++---- 1 file changed, 1009 insertions(+), 258 deletions(-) diff --git a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx index 64712be2d2c9b..edcd91be1b5ac 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx @@ -12,7 +12,7 @@ /// \brief Class building geometry of one half of one MFT half-cone /// \author sbest@pucp.pe, eric.endress@gmx.de, franck.manso@clermont.in2p3.fr /// \Carlos csoncco@pucp.edu.pe -/// \date 13/03/2019 +/// \date 01/07/2020 #include "TGeoManager.h" #include "TGeoMatrix.h" @@ -50,7 +50,35 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) auto* HalfConeVolume = new TGeoVolumeAssembly("HalfConeVolume"); + TGeoElement* Silicon = new TGeoElement("Silicon", "Silicon", 14, 28.0855); + TGeoElement* Iron = new TGeoElement("Iron", "Iron", 26, 55.845); + TGeoElement* Copper = new TGeoElement("Copper", "Copper", 29, 63.546); + TGeoElement* Manganese = + new TGeoElement("Manganese", "Manganese", 25, 54.938049); + TGeoElement* Magnesium = + new TGeoElement("Magnesium", "Magnesium", 12, 24.3050); + TGeoElement* Zinc = new TGeoElement("Zinc", "Zinc", 30, 65.39); + TGeoElement* Titanium = new TGeoElement("Titanium", "Titanium", 22, 47.867); + TGeoElement* Chromium = new TGeoElement("Chromium", "Chromium", 24, 51.9961); + TGeoElement* Aluminum = new TGeoElement("Aluminum", "Aluminum", 13, 26981538); + + TGeoMixture* alu5083 = new TGeoMixture("alu5083", 9, 2.650); // g/cm3 + alu5083->AddElement(Iron, 0.004); + alu5083->AddElement(Silicon, 0.004); + alu5083->AddElement(Copper, 0.001); + alu5083->AddElement(Manganese, 0.002); + alu5083->AddElement(Magnesium, 0.0025); + alu5083->AddElement(Zinc, 0.0025); + alu5083->AddElement(Titanium, 0.0015); + alu5083->AddElement(Chromium, 0.0010); + alu5083->AddElement(Aluminum, 0.9815); + // alu5083->SetTemperature(); // 25. + alu5083->SetDensity(2.65); // g/cm3 + alu5083->SetState(TGeoMaterial::kMatStateSolid); + TGeoMedium* kMedAlu = gGeoManager->GetMedium("MFT_Alu$"); + TGeoMedium* malu5083 = + new TGeoMedium("malu5083", 2, alu5083); // name, numer medio, material // Rotation TGeoRotation* rot1 = new TGeoRotation("rot1", 180, -180, 0); @@ -68,7 +96,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) TGeoRotation* rot_base = new TGeoRotation("rot_base", 180, 180, 0); // rail_r rot_base->RegisterYourself(); - TGeoCombiTrans* combi1 = new TGeoCombiTrans(0, -10.3, 1.29, rot1); // y=-10.80 belt + TGeoCombiTrans* combi1 = + new TGeoCombiTrans(0, -10.3, 1.29, rot1); // y=-10.80 belt combi1->RegisterYourself(); TGeoCombiTrans* combi2 = new TGeoCombiTrans(-16.8, 0., 0., rot2); combi2->RegisterYourself(); @@ -96,7 +125,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) TGeoCombiTrans* acombi_1h_mb0 = new TGeoCombiTrans(5.2, 0, 0, rot_1hole_mb0); acombi_1h_mb0->SetName("acombi_1h_mb0"); acombi_1h_mb0->RegisterYourself(); - TGeoCombiTrans* bcombi_1h_mb0 = new TGeoCombiTrans(-5.2, 0, 0, rot_1hole_mb0); //y= + TGeoCombiTrans* bcombi_1h_mb0 = + new TGeoCombiTrans(-5.2, 0, 0, rot_1hole_mb0); // y= bcombi_1h_mb0->SetName("bcombi_1h_mb0"); bcombi_1h_mb0->RegisterYourself(); @@ -109,31 +139,53 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) rot_2hole_mb0->SetName("rot_2hole_mb0"); rot_2hole_mb0->RegisterYourself(); - TGeoCombiTrans* combi_2hole_mb0 = new TGeoCombiTrans(6.7, 0, 0, rot_2hole_mb0); + TGeoCombiTrans* combi_2hole_mb0 = + new TGeoCombiTrans(6.7, 0, 0, rot_2hole_mb0); combi_2hole_mb0->SetName("combi_2hole_mb0"); combi_2hole_mb0->RegisterYourself(); - TGeoCombiTrans* combi_2hole_mb0_b = new TGeoCombiTrans(-6.7, 0, 0, rot_2hole_mb0); //y= + TGeoCombiTrans* combi_2hole_mb0_b = + new TGeoCombiTrans(-6.7, 0, 0, rot_2hole_mb0); // y= combi_2hole_mb0_b->SetName("combi_2hole_mb0_b"); combi_2hole_mb0_b->RegisterYourself(); // shape for cross_mb0.. - // TGeoShape* box_mb0 = new TGeoBBox("s_box_mb0", x_boxmb0 / 2, y_boxmb0 / 2, z_boxmb0 / 2); + // TGeoShape* box_mb0 = new TGeoBBox("s_box_mb0", x_boxmb0 / 2, y_boxmb0 / 2, + // z_boxmb0 / 2); new TGeoBBox("box_mb0", x_boxmb0 / 2, y_boxmb0 / 2, z_boxmb0 / 2); new TGeoTube("hole1_mb0", radin_1hmb0, radout_1hmb0, high_1hmb0 / 2); new TGeoTube("hole2_mb0", radin_2hmb0, radout_2hmb0, high_2hmb0 / 2); + /// composite shape for mb0 - ///composite shape for mb0 - - auto* c_mb0_Shape_0 = new TGeoCompositeShape("c_mb0_Shape_0", "box_mb0 - hole1_mb0:acombi_1h_mb0 - hole1_mb0:bcombi_1h_mb0 - hole2_mb0:combi_2hole_mb0 - hole2_mb0:combi_2hole_mb0_b"); + auto* c_mb0_Shape_0 = new TGeoCompositeShape( + "c_mb0_Shape_0", + "box_mb0 - hole2_mb0:combi_2hole_mb0 - " + "hole2_mb0:combi_2hole_mb0_b"); //- hole1_mb0:acombi_1h_mb0 - + // hole1_mb0:bcombi_1h_mb0 - auto* cross_mb0_Volume = new TGeoVolume("cross_mb0_Volume", c_mb0_Shape_0, kMedAlu); + /// auto* cross_mb0_Volume = new TGeoVolume("cross_mb0_Volume", c_mb0_Shape_0, + /// kMedAlu); + auto* cross_mb0_Volume = + new TGeoVolume("cross_mb0_Volume", c_mb0_Shape_0, malu5083); Cross_mb0->AddNode(cross_mb0_Volume, 1); // 2nd piece cross beam MFT (cbeam) auto* Cross_mft = new TGeoVolumeAssembly("Cross_mft"); + auto* Cross_mft_2 = new TGeoVolumeAssembly("Cross_mft_2"); + auto* Cross_mft_3 = new TGeoVolumeAssembly("Cross_mft_3"); + auto* Cross_mft_4 = new TGeoVolumeAssembly("Cross_mft_4"); + + // 2020_cross_beam + // tub-main + Double_t radin_cb = 0.; + Double_t radout_cb = 0.3; + Double_t high_cb = 14.2; + + TGeoRotation* rot_cb = new TGeoRotation("rot_cb", 90, 90, 0); + rot_cb->SetName("rot_cb"); + rot_cb->RegisterYourself(); // using the same "box" of the 1 piece // 2hole coaxial @@ -143,24 +195,45 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) // same rotation in tub aximatAl "rot_2hole_mb0" - TGeoCombiTrans* combi_hole_1cbeam = new TGeoCombiTrans(6.8, 0, 0, rot_2hole_mb0); + TGeoCombiTrans* combi_hole_1cbeam = + new TGeoCombiTrans(6.8, 0, 0, rot_2hole_mb0); combi_hole_1cbeam->SetName("combi_hole_1cbeam"); combi_hole_1cbeam->RegisterYourself(); - TGeoCombiTrans* combi_hole_2cbeam = new TGeoCombiTrans(-6.8, 0, 0, rot_2hole_mb0); + TGeoCombiTrans* combi_hole_2cbeam = + new TGeoCombiTrans(-6.8, 0, 0, rot_2hole_mb0); combi_hole_2cbeam->SetName("combi_hole_2cbeam"); combi_hole_2cbeam->RegisterYourself(); // shape for shape cross beam - new TGeoTube("hole_cbeam", radin_hole_cbeam, radout_hole_cbeam, high_hole_cbeam / 2); + new TGeoTube("hole_cbeam", radin_hole_cbeam, radout_hole_cbeam, + high_hole_cbeam / 2); + new TGeoTube("s_cb", radin_cb, radout_cb, high_cb / 2); // new // composite shape for cross beam (using the same box of mb0) - auto* c_cbeam_Shape = new TGeoCompositeShape("c_cbeam_Shape", "box_mb0 - hole_cbeam:combi_hole_1cbeam - hole_cbeam:combi_hole_2cbeam"); - - auto* Cross_mft_Volume = new TGeoVolume("Cross_mft_Volume", c_cbeam_Shape, kMedAlu); + /// auto* c_cbeam_Shape = new TGeoCompositeShape("c_cbeam_Shape", "box_mb0 - + /// hole_cbeam:combi_hole_1cbeam - hole_cbeam:combi_hole_2cbeam"); + auto* c_cbeam_Shape = new TGeoCompositeShape( + "c_cbeam_Shape", + " s_cb:rot_cb - hole_cbeam:combi_hole_1cbeam - " + "hole_cbeam:combi_hole_2cbeam"); + + /// auto* Cross_mft_Volume = new TGeoVolume("Cross_mft_Volume", c_cbeam_Shape, + /// kMedAlu); + auto* Cross_mft_Volume = + new TGeoVolume("Cross_mft_Volume", c_cbeam_Shape, malu5083); + auto* Cross_mft_Volume_2 = + new TGeoVolume("Cross_mft_Volume_2", c_cbeam_Shape, malu5083); + auto* Cross_mft_Volume_3 = + new TGeoVolume("Cross_mft_Volume_3", c_cbeam_Shape, malu5083); + auto* Cross_mft_Volume_4 = + new TGeoVolume("Cross_mft_Volume_4", c_cbeam_Shape, malu5083); Cross_mft->AddNode(Cross_mft_Volume, 1); + Cross_mft_2->AddNode(Cross_mft_Volume_2, 1); + Cross_mft_3->AddNode(Cross_mft_Volume_3, 1); + Cross_mft_4->AddNode(Cross_mft_Volume_4, 1); // 3th piece Framework front @@ -168,6 +241,69 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) auto* Fra_front_L = new TGeoVolumeAssembly("Fra_front_L"); auto* Fra_front_R = new TGeoVolumeAssembly("Fra_front_R"); + // new fra_front seg tub + Double_t radin_fwf = 15.2; + Double_t radout_fwf = 15.9; + Double_t high_fwf = 0.6; + Double_t ang_in_fwf = 180. + 21.0; // 21.44 + Double_t ang_fin_fwf = 180 + 60.21; // + + // box to quit -inferior part + Double_t x_box_qdown = 1.6; + Double_t y_box_qdown = 1.6; + Double_t z_box_qdown = 0.65; + + TGeoTranslation* tr_qdown = + new TGeoTranslation("tr_qdown", -7.1, -13.7985, 0.); + tr_qdown->RegisterYourself(); + + // box to add -inferior part + Double_t x_box_addown = 1.83; + Double_t y_box_addown = 0.6; + Double_t z_box_addown = 0.6; + + TGeoTranslation* tr_addown = + new TGeoTranslation("tr_addown", -8.015, -12.6985, 0.); + tr_addown->RegisterYourself(); + //// + TGeoXtru* tria_fwf = new TGeoXtru(2); + tria_fwf->SetName("tria_fwf"); + + Double_t x_tria_fwf[3] = {-13.2, -10.3, -10.3}; + Double_t y_tria_fwf[3] = {-8.0, -11.4, -8.0}; + tria_fwf->DefinePolygon(3, x_tria_fwf, y_tria_fwf); + tria_fwf->DefineSection(0, -0.3, 0., 0., 1); + tria_fwf->DefineSection(1, 0.3, 0., 0., 1); + ////////// + TGeoXtru* top_adfwf = new TGeoXtru(2); + top_adfwf->SetName("top_adfwf"); + + Double_t x_top_adfwf[4] = {-14.8, -14.2, -14.2, -14.8}; + Double_t y_top_adfwf[4] = {-3.6 - 0.12, -3.6 - 0.12, -5.56, + -5.83}; // 5.52 , 5.9 --5.83 + top_adfwf->DefinePolygon(4, x_top_adfwf, y_top_adfwf); + top_adfwf->DefineSection(0, -0.3, 0., 0., + 1); //(plane,-zplane/ +zplane, x0, y0,(x/y)) + top_adfwf->DefineSection(1, 0.3, 0., 0., 1); + + // box to quit up part + Double_t x_q_upbox = 0.4; + Double_t y_q_upbox = 4.; + Double_t z_q_upbox = 1.; + + TGeoTranslation* tr_q_upbox = + new TGeoTranslation("tr_q_upbox", -14.8 - 0.2, -3.6 - 0.6, 0.); + tr_q_upbox->RegisterYourself(); + + TGeoRotation* rot_180yR = + new TGeoRotation("rot_180yR", 180, -180, 0); // half0 + rot_180yR->RegisterYourself(); + TGeoCombiTrans* combi_fwb_R = new TGeoCombiTrans(0, 0, 0, rot_180yR); + combi_fwb_R->SetName("combi_fwb_R"); + combi_fwb_R->RegisterYourself(); + + /////////////////////////////////////////// + Double_t x_box_up = 0.6; // cm Double_t y_box_up = 0.605; Double_t z_box_up = 2.84; @@ -218,11 +354,20 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) tr_tubdown->RegisterYourself(); // shape for framewor front + auto* fwf_tub = new TGeoTubeSeg("fwf_tub", radin_fwf, radout_fwf, + high_fwf / 2, ang_in_fwf, ang_fin_fwf); + auto* box_qdown = new TGeoBBox("box_qdown", x_box_qdown / 2, y_box_qdown / 2, + z_box_qdown / 2); + auto* box_addown = new TGeoBBox("box_addown", x_box_addown / 2, + y_box_addown / 2, z_box_addown / 2); + auto* q_upbox = + new TGeoBBox("q_upbox", x_q_upbox / 2, y_q_upbox / 2, z_q_upbox / 2); new TGeoBBox("box_up", x_box_up / 2, y_box_up / 2, z_box_up / 2); new TGeoTube("tub_up", 0., dia_tub_up / 2, high_tub_up / 2); // - new TGeoTubeSeg("seg_tub", radin_segtub, radout_segtub, high_segtub / 2, ang_in_segtub, ang_fin_segtub); + new TGeoTubeSeg("seg_tub", radin_segtub, radout_segtub, high_segtub / 2, + ang_in_segtub, ang_fin_segtub); new TGeoBBox("boxB_down", x_boxB_down / 2, y_boxB_down / 2, z_boxB_down / 2); @@ -231,32 +376,74 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) new TGeoTube("tubdown", 0., dia_tubdown / 2, high_tubdown / 2); // Composite shapes for Fra_front - new TGeoCompositeShape("fra_front_Shape_0", "box_up:tr1_up + seg_tub:combi_3b + boxB_down:tr3_box + boxA_down:tr_2_box"); - auto* fra_front_Shape_1 = new TGeoCompositeShape("fra_front_Shape_1", "fra_front_Shape_0 - tubdown:tr_tubdown - tub_up:combi_3a"); + new TGeoCompositeShape("fra_front_Shape_0", + "box_up:tr1_up + seg_tub:combi_3b + boxB_down:tr3_box " + "+ boxA_down:tr_2_box"); + + auto* fra_front_Shape_1 = new TGeoCompositeShape( + "fra_front_Shape_1", + "fra_front_Shape_0 - tubdown:tr_tubdown - tub_up:combi_3a"); - TGeoRotation* rot_z180x90 = new TGeoRotation("rot_z180x90", 180, 90, 0); //half0_R + TGeoRotation* rot_z180x90 = + new TGeoRotation("rot_z180x90", 180, 90, 0); // half0_R rot_z180x90->RegisterYourself(); - TGeoRotation* rot_halfR = new TGeoRotation("rot_halfR", 180, 180, 0); // half0_R + TGeoRotation* rot_halfR = + new TGeoRotation("rot_halfR", 180, 180, 0); // half0_R rot_halfR->RegisterYourself(); - TGeoCombiTrans* combi_front_L = new TGeoCombiTrans(-7.1, -16.2, 32.5 + 0.675, rot_90x); // x=7.35, y=0, z=15.79 + /// TGeoCombiTrans* combi_front_L = new TGeoCombiTrans(-7.1, -16.2, 32.5 + + /// 0.675, rot_90x); // x=7.35, y=0, z=15.79 + TGeoCombiTrans* combi_front_L = + new TGeoCombiTrans(-7.1, -16.2, 32.5 + 0.675, rot_90x); + combi_front_L->SetName("combi_front_L"); combi_front_L->RegisterYourself(); - TGeoCombiTrans* combi_front_R = new TGeoCombiTrans(7.1, -16.2, 32.5 + 0.675, rot_z180x90); //x=7.35, y=0, z=15.79 + TGeoTranslation* tr_ff = new TGeoTranslation( + "tr_ff", 0, -2.5 - 0.31, 32.5 + 0.675); // 7.1 , -16.2 z32.5 + tr_ff->RegisterYourself(); + // TGeoRotation *rot_180yR = new TGeoRotation("rot_180yR", 180,-180,0); // + // half0 rot_180yR->RegisterYourself(); + + // TGeoCombiTrans* combi_front_R = new TGeoCombiTrans(7.1, -16.2, 32.5 + + // 0.675, rot_z180x90); //x=7.35, y=0, z=15.79 + TGeoCombiTrans* combi_front_R = + new TGeoCombiTrans(0, -2.5 - 0.31, 32.5 + 0.675, rot_180yR); combi_front_R->SetName("combi_front_R"); combi_front_R->RegisterYourself(); - // auto * fra_front_Shape_3 = new TGeoCompositeShape("fra_front_Shape_3","fra_front_Shape_2:rot_halfR "); + auto* fra_front_Shape_2 = new TGeoCompositeShape( + "Fra_front_Shape_2", + "fwf_tub - box_qdown:tr_qdown + box_addown:tr_addown + tria_fwf + " + "top_adfwf - q_upbox:tr_q_upbox"); - auto* Fra_front_Volume = new TGeoVolume("Fra_front_Volume", fra_front_Shape_1, kMedAlu); + // auto * fra_front_Shape_3 = new + // TGeoCompositeShape("Fra_front_Shape_3","Fra_front_Shape_2 + + // Fra_front_Shape_2:combi_front_R "); - Fra_front_L->AddNode(Fra_front_Volume, 1, combi_front_L); - Fra_front_R->AddNode(Fra_front_Volume, 1, combi_front_R); + auto* fra_front_Shape_3 = new TGeoCompositeShape( + "Fra_front_Shape_3", "Fra_front_Shape_2 + Fra_front_Shape_2:rot_180yR"); - Fra_front->AddNode(Fra_front_L, 1); - Fra_front->AddNode(Fra_front_R, 2); + // auto * fra_front_Shape_3 = new + // TGeoCompositeShape("fra_front_Shape_3","fra_front_Shape_2:rot_halfR "); + + /// auto* Fra_front_Volume = new TGeoVolume("Fra_front_Volume", + /// fra_front_Shape_1, kMedAlu); + auto* Fra_front_Volume_R = + new TGeoVolume("Fra_front_Volume_R", fra_front_Shape_2, malu5083); + auto* Fra_front_Volume_L = + new TGeoVolume("Fra_front_Volume_L", fra_front_Shape_2, malu5083); + + auto* Fra_front_Volume_RL = + new TGeoVolume("Fra_front_Volume_RL", fra_front_Shape_3, malu5083); + + // Fra_front_L->AddNode(Fra_front_Volume, 1, tr_ff); + // Fra_front_R->AddNode(Fra_front_Volume, 1, combi_front_R); + + // Fra_front->AddNode(Fra_front_L, 1); + // Fra_front->AddNode(Fra_front_R, 2); + Fra_front->AddNode(Fra_front_Volume_RL, 1, tr_ff); // 4th piece "BASE" framework half support @@ -314,20 +501,23 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t yc_box = 5.772; Double_t zc_box = 1.4; - TGeoTranslation* tr_cbox = new TGeoTranslation("tr_cbox", -xc_box / 2, -radout_disc + 0.888, 0); + TGeoTranslation* tr_cbox = + new TGeoTranslation("tr_cbox", -xc_box / 2, -radout_disc + 0.888, 0); tr_cbox->RegisterYourself(); // box 4 lamine 1 Double_t x_labox = 60.0; Double_t y_labox = 30.3; Double_t z_labox = 0.305; - TGeoTranslation* tr_la = new TGeoTranslation("tr_la", 0, -y_labox / 2 - 9.3, high_disc / 2); + TGeoTranslation* tr_la = + new TGeoTranslation("tr_la", 0, -y_labox / 2 - 9.3, high_disc / 2); tr_la->RegisterYourself(); // box 5 lamin 2 Double_t x_2labox = 51.2; Double_t y_2labox = 2.8; // C-B Double_t z_2labox = 0.303; - TGeoTranslation* tr_2la = new TGeoTranslation("tr_2la", 0, -8.1, high_disc / 2); // + TGeoTranslation* tr_2la = + new TGeoTranslation("tr_2la", 0, -8.1, high_disc / 2); // tr_2la->RegisterYourself(); // circular border C SEG_BORD @@ -337,57 +527,67 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t high_bord = 1.355; // 13.5 Double_t ang_in_bord = 0; Double_t ang_fin_bord = 90; - // TGeoRotation *rot_bord1 = new TGeoRotation("rot_bord1", ang_in_1hole +0.0167,0,0); + // TGeoRotation *rot_bord1 = new TGeoRotation("rot_bord1", ang_in_1hole + // +0.0167,0,0); TGeoRotation* rot1_bord1 = new TGeoRotation("rot1_bord1", 14.8, 0, 0); rot1_bord1->RegisterYourself(); - TGeoCombiTrans* combi_bord1 = new TGeoCombiTrans(-26.7995, -13.0215, 0, rot1_bord1); // y= + TGeoCombiTrans* combi_bord1 = + new TGeoCombiTrans(-26.7995, -13.0215, 0, rot1_bord1); // y= combi_bord1->SetName("combi_bord1"); combi_bord1->RegisterYourself(); TGeoRotation* rot2_bord1 = new TGeoRotation("rot2_bord1", -50, 0, 0); rot2_bord1->RegisterYourself(); - TGeoCombiTrans* combi2_bord1 = new TGeoCombiTrans(-21.3795, -20.7636, 0, rot2_bord1); // y= + TGeoCombiTrans* combi2_bord1 = + new TGeoCombiTrans(-21.3795, -20.7636, 0, rot2_bord1); // y= combi2_bord1->SetName("combi2_bord1"); combi2_bord1->RegisterYourself(); // TGeoRotation* rot1_bord2 = new TGeoRotation("rot1_bord2", 250, 0, 0); rot1_bord2->RegisterYourself(); - TGeoCombiTrans* combi1_bord2 = new TGeoCombiTrans(-9.0527, -23.3006, 0, rot1_bord2); // y= + TGeoCombiTrans* combi1_bord2 = + new TGeoCombiTrans(-9.0527, -23.3006, 0, rot1_bord2); // y= combi1_bord2->SetName("combi1_bord2"); combi1_bord2->RegisterYourself(); // e|°____°| TGeoRotation* rot_cent_bord = new TGeoRotation("rot_cent_bord", 90, 0, 0); rot_cent_bord->RegisterYourself(); - TGeoCombiTrans* combi_cent_bord = new TGeoCombiTrans(-6.5, -27.094, 0, rot_cent_bord); // y= + TGeoCombiTrans* combi_cent_bord = + new TGeoCombiTrans(-6.5, -27.094, 0, rot_cent_bord); // y= combi_cent_bord->SetName("combi_cent_bord"); combi_cent_bord->RegisterYourself(); // box tonge Double_t x_tong = 2.0; - Double_t y_tong = 2.81; + Double_t y_tong = 1.5; Double_t z_tong = 1.35; - TGeoTranslation* tr_tong = new TGeoTranslation("tr_tong", 0, -28.6, 0); // + TGeoTranslation* tr_tong = new TGeoTranslation("tr_tong", 0, -26.75, 0); // tr_tong->RegisterYourself(); // circular central hole1 to conexion with other parts Double_t radin_hole1 = 0; Double_t radout_hole1 = 0.4; Double_t high_hole1 = 1.36; - TGeoTranslation* tr_hole1 = new TGeoTranslation("tr_hole1", 0, -28.0, 0); // tonge + TGeoTranslation* tr_hole1 = + new TGeoTranslation("tr_hole1", 0, -28.0, 0); // tonge tr_hole1->RegisterYourself(); - TGeoTranslation* tr2_hole1 = new TGeoTranslation("tr2_hole1", -26.5, -8.5, 0); // left + TGeoTranslation* tr2_hole1 = + new TGeoTranslation("tr2_hole1", -26.5, -8.5, 0); // left tr2_hole1->RegisterYourself(); - TGeoTranslation* tr3_hole1 = new TGeoTranslation("tr3_hole1", 26.5, -8.5, 0); // right + TGeoTranslation* tr3_hole1 = + new TGeoTranslation("tr3_hole1", 26.5, -8.5, 0); // right tr3_hole1->RegisterYourself(); // circular hole2 ; hole2 r=6.7 Double_t radin_hole2 = 0; - Double_t radout_hole2 = 0.335; // diameter 6.7 - Double_t high_hole2 = 1.36; // 13.5 - TGeoTranslation* tr1_hole2 = new TGeoTranslation("tr1_hole2", -28.0, -8.5, 0); // + Double_t radout_hole2 = 0.335; // diameter 6.7 + Double_t high_hole2 = 1.36; // 13.5 + TGeoTranslation* tr1_hole2 = + new TGeoTranslation("tr1_hole2", -28.0, -8.5, 0); // tr1_hole2->RegisterYourself(); - TGeoTranslation* tr2_hole2 = new TGeoTranslation("tr2_hole2", 28.0, -8.5, 0); // + TGeoTranslation* tr2_hole2 = + new TGeoTranslation("tr2_hole2", 28.0, -8.5, 0); // tr2_hole2->RegisterYourself(); //////////// hole "0" two tubs together @@ -398,10 +598,19 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t radin_T2 = 0; Double_t radout_T2 = 1.1; Double_t high_T2 = 1.2; // dz 6 + // seg tong xy + Double_t radin_ccut = 27.5; + Double_t radout_ccut = 29.; // 304 + Double_t high_ccut = 1.4; /// 13.5 + Double_t ang_in_ccut = 260; + Double_t ang_fin_ccut = 280; // shape for base - new TGeoTubeSeg("disc", radin_disc, radout_disc, high_disc / 2, ang_in_disc, ang_fin_disc); + new TGeoTubeSeg("disc", radin_disc, radout_disc, high_disc / 2, ang_in_disc, + ang_fin_disc); + new TGeoTubeSeg("c_cut", radin_ccut, radout_ccut, high_ccut / 2, ang_in_ccut, + ang_fin_ccut); new TGeoBBox("box1", x_1box / 2, y_1box / 2, z_1box / 2); new TGeoBBox("box2", x_2box / 2, y_2box / 2, z_2box / 2); @@ -411,10 +620,14 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) new TGeoBBox("cbox", xc_box / 2, yc_box / 2, zc_box / 2); new TGeoBBox("tongbox", x_tong / 2, y_tong / 2, z_tong / 2); - new TGeoTubeSeg("seg_1hole", radin_1hole, radout_1hole, high_1hole / 2, ang_in_1hole, ang_fin_1hole); // r_in,r_out,dZ,ang,ang - new TGeoTubeSeg("seg_2hole", radin_2hole, radout_2hole, high_2hole / 2, ang_in_2hole, ang_fin_2hole); - new TGeoTubeSeg("seg_3hole", radin_3hole, radout_3hole, high_3hole / 2, ang_in_3hole, ang_fin_3hole); // y|u| - new TGeoTubeSeg("seg_bord", radin_bord, radout_bord, high_bord / 2, ang_in_bord, ang_fin_bord); + new TGeoTubeSeg("seg_1hole", radin_1hole, radout_1hole, high_1hole / 2, + ang_in_1hole, ang_fin_1hole); // r_in,r_out,dZ,ang,ang + new TGeoTubeSeg("seg_2hole", radin_2hole, radout_2hole, high_2hole / 2, + ang_in_2hole, ang_fin_2hole); + new TGeoTubeSeg("seg_3hole", radin_3hole, radout_3hole, high_3hole / 2, + ang_in_3hole, ang_fin_3hole); // y|u| + new TGeoTubeSeg("seg_bord", radin_bord, radout_bord, high_bord / 2, + ang_in_bord, ang_fin_bord); new TGeoTube("circ_hole1", radin_hole1, radout_hole1, high_hole1 / 2); @@ -424,125 +637,219 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) // composite shape for base - new TGeoCompositeShape("base_Shape_0", " disc - box1 - box2 - box3 - circ_holeB:tr1_holeB - circ_holeB:tr2_holeB"); - new TGeoCompositeShape("base_Shape_1", "(seg_1hole - seg_bord:combi_bord1 - seg_bord:combi2_bord1) + seg_2hole -seg_bord:combi1_bord2 + cbox:tr_cbox"); + // new TGeoCompositeShape("base_Shape_0", " disc - box1 - box2 - box3 - + // circ_holeB:tr1_holeB - circ_holeB:tr2_holeB"); + new TGeoCompositeShape("base_Shape_0", " disc - box1 - box2 - box3"); + new TGeoCompositeShape( + "base_Shape_1", + "(seg_1hole - seg_bord:combi_bord1 - seg_bord:combi2_bord1) + seg_2hole " + "-seg_bord:combi1_bord2 + cbox:tr_cbox"); - new TGeoCompositeShape("base_Shape_2", " seg_3hole + seg_bord:combi_cent_bord"); // seg_bord:combi_cent_bord + new TGeoCompositeShape( + "base_Shape_2", + " seg_3hole + seg_bord:combi_cent_bord"); // seg_bord:combi_cent_bord new TGeoCompositeShape("base_Shape_3", " labox1:tr_la + labox2:tr_2la "); - auto* base_Shape_4 = new TGeoCompositeShape("base_Shape_4", "base_Shape_0 - base_Shape_1 - base_Shape_1:rot1 + base_Shape_2 + tongbox:tr_tong - circ_hole1:tr_hole1 - circ_hole1:tr2_hole1 - circ_hole1:tr3_hole1 - circ_hole2:tr1_hole2 - circ_hole2:tr2_hole2 - base_Shape_3 "); - - // auto * base_Shape_5 = new TGeoCompositeShape("base_Shape_5","disc-box1 -box2 -box3 -seg_1hole -seg_2hole +seg_3hole -seg_1hole:rot1-seg_2hole:rot1 - cbox:tr_cbox - labox:tr_la - labox2:tr_2la + seg_bord "); - - // auto * base0_Volume = new TGeoVolume("base0_Volume",base_Shape_0,kMedAlu); - // auto * base1_Volume = new TGeoVolume("base1_Volume",base_Shape_1,kMedAlu); - // auto * base2_Volume = new TGeoVolume("base2_Volume",base_Shape_2,kMedAlu); - // auto * base3_Volume = new TGeoVolume("base3_Volume",base_Shape_3,kMedAlu); - - auto* base4_Volume = new TGeoVolume("base4_Volume", base_Shape_4, kMedAlu); + /// auto* base_Shape_4 = new TGeoCompositeShape("base_Shape_4", "base_Shape_0 + /// - base_Shape_1 - base_Shape_1:rot1 + base_Shape_2 + tongbox:tr_tong - + /// circ_hole1:tr_hole1 - circ_hole1:tr2_hole1 - circ_hole1:tr3_hole1 - + /// circ_hole2:tr1_hole2 - circ_hole2:tr2_hole2 - base_Shape_3 "); + auto* base_Shape_4 = new TGeoCompositeShape( + "base_Shape_4", + "base_Shape_0 - base_Shape_1 - base_Shape_1:rot1 + base_Shape_2 - " + "base_Shape_3 + tongbox:tr_tong - c_cut"); //- circ_hole1:tr_hole1 - + // circ_hole1:tr2_hole1 - + // circ_hole1:tr3_hole1 - + // circ_hole2:tr1_hole2 - + // circ_hole2:tr2_hole2 + + // auto * base_Shape_5 = new TGeoCompositeShape("base_Shape_5","disc-box1 + // -box2 -box3 -seg_1hole -seg_2hole +seg_3hole -seg_1hole:rot1-seg_2hole:rot1 + // - cbox:tr_cbox - labox:tr_la - labox2:tr_2la + seg_bord "); + + auto* base4_Volume = new TGeoVolume("base4_Volume", base_Shape_4, malu5083); base->AddNode(base4_Volume, 2, rot_base); // base->AddNode(base4_Volume,2); - // 5th piece MIDLE Framework midle - - auto* midle = new TGeoVolumeAssembly("Midle"); - auto* midle_L = new TGeoVolumeAssembly("Midle_L"); - auto* midle_R = new TGeoVolumeAssembly("Midle_R"); + // 5th piece middle Framework middle + + auto* middle = new TGeoVolumeAssembly("middle"); + auto* middle_L = new TGeoVolumeAssembly("middle_L"); + auto* middle_R = new TGeoVolumeAssembly("middle_R"); + + ////new2020 framework middle + Double_t radin_fwm = 14.406; + Double_t radout_fwm = 15.185; // + Double_t high_fwm = 0.6; /// + Double_t ang_in_fwm = 180. + 12.93; + Double_t ang_fin_fwm = 180. + 58.65; + + ////box add up + Double_t x_fwm_1box = 0.8; // dx=4 + Double_t y_fwm_1box = 1.45; + Double_t z_fwm_1box = 0.6; // 6.5 -> 6.6 to quit + TGeoTranslation* tr_fwm_1box = + new TGeoTranslation("tr_fwm_1box", -14.4, -3.398 + 1.45 / 2, 0); // 81 + tr_fwm_1box->RegisterYourself(); + + ////box quit down + Double_t x_fwm_2box = 0.8; // dx=4 + Double_t y_fwm_2box = 1.2; + Double_t z_fwm_2box = 0.7; // 6.5 -> 6.6 to quit + TGeoTranslation* tr_fwm_2box = + new TGeoTranslation("tr_fwm_2box", -14.4 + 6.9, -3.398 - 9.1, 0); // 81 + tr_fwm_2box->RegisterYourself(); + + //// + TGeoXtru* tria_fwm = new TGeoXtru(2); + tria_fwm->SetName("tria_fwm"); + + Double_t x_tria_fwm[3] = {-13.5, -10., -10.}; + Double_t y_tria_fwm[3] = {-5.94, -5.94, -10.8}; + tria_fwm->DefinePolygon(3, x_tria_fwm, y_tria_fwm); + tria_fwm->DefineSection(0, -0.3, 0., 0., 1); + tria_fwm->DefineSection(1, 0.3, 0., 0., 1); + ////////// // box up to quit and to join - Double_t x_midle = 0.8; //dx=4 - Double_t y_midle = 3.495; //y=34.9 - Double_t z_midle = 0.62; //z=6 + Double_t x_middle = 0.8; // dx=4 + Double_t y_middle = 3.495; // y=34.9 + Double_t z_middle = 0.62; // z=6 // tr1 to join with arc - TGeoTranslation* tr1_midle_box = new TGeoTranslation("tr1_midle_box", -14.4, -0.745, 0); // -152,-17.45,0 - tr1_midle_box->RegisterYourself(); + TGeoTranslation* tr1_middle_box = + new TGeoTranslation("tr1_middle_box", -14.4, -0.745, 0); // -152,-17.45,0 + tr1_middle_box->RegisterYourself(); // tr2 to quiet - TGeoTranslation* tr2_midle_box = new TGeoTranslation("tr2_midle_box", -15.2, -0.745, 0); // -152,-17.45,0 - tr2_midle_box->RegisterYourself(); + TGeoTranslation* tr2_middle_box = + new TGeoTranslation("tr2_middle_box", -15.2, -0.745, 0); // -152,-17.45,0 + tr2_middle_box->RegisterYourself(); // box down_1 - Double_t x_midle_d1box = 0.4; // dx=4 - Double_t y_midle_d1box = 0.28; - Double_t z_midle_d1box = 0.66; - TGeoTranslation* tr_midle_d1box = new TGeoTranslation("tr_midle_d1box", -7.3, -11.96, 0.); // 81 - tr_midle_d1box->RegisterYourself(); + Double_t x_middle_d1box = 0.4; // dx=4 + Double_t y_middle_d1box = 0.28; + Double_t z_middle_d1box = 0.66; + TGeoTranslation* tr_middle_d1box = + new TGeoTranslation("tr_middle_d1box", -7.3, -11.96, 0.); // 81 + tr_middle_d1box->RegisterYourself(); // box down_2 - Double_t x_midle_d2box = 0.8; // dx=4 - Double_t y_midle_d2box = 1.0; - Double_t z_midle_d2box = 0.66; // - TGeoTranslation* tr_midle_d2box = new TGeoTranslation("tr_midle_d2box", -7.5, -12.6249, 0); // 81 - tr_midle_d2box->RegisterYourself(); + Double_t x_middle_d2box = 0.8; // dx=4 + Double_t y_middle_d2box = 1.0; + Double_t z_middle_d2box = 0.66; // + TGeoTranslation* tr_middle_d2box = + new TGeoTranslation("tr_middle_d2box", -7.5, -12.6249, 0); // 81 + tr_middle_d2box->RegisterYourself(); // arc circ part - Double_t radin_midle = 14.0; - Double_t radout_midle = 15.0; // - Double_t high_midle = 0.6; // - Double_t ang_in_midle = 180; - Double_t ang_fin_midle = 238.21; // alfa=57.60 + Double_t radin_middle = 14.0; + Double_t radout_middle = 15.0; // + Double_t high_middle = 0.6; // + Double_t ang_in_middle = 180; + Double_t ang_fin_middle = 238.21; // alfa=57.60 - // circular hole1 ; hole_midle d=3.5 + // circular hole1 ; hole_middle d=3.5 Double_t radin_mid_1hole = 0.; Double_t radout_mid_1hole = 0.175; // diameter 3.5 Double_t high_mid_1hole = 1.5; // 2.4 TGeoRotation* rot_mid_1hole = new TGeoRotation("rot_mid_1hole", 90, 90, 0); rot_mid_1hole->RegisterYourself(); - TGeoCombiTrans* combi_mid_1tubhole = new TGeoCombiTrans(-14.2, 0.325, 0, rot_mid_1hole); // + TGeoCombiTrans* combi_mid_1tubhole = + new TGeoCombiTrans(-14.2, 0.325, 0, rot_mid_1hole); // combi_mid_1tubhole->SetName("combi_mid_1tubhole"); combi_mid_1tubhole->RegisterYourself(); - // circular hole2 ; hole_midle d=3 + // circular hole2 ; hole_middle d=3 Double_t radin_mid_2hole = 0.; Double_t radout_mid_2hole = 0.15; // diameter 3 Double_t high_mid_2hole = 1.8; // - TGeoCombiTrans* combi_mid_2tubhole = new TGeoCombiTrans(-7.7, -12.355, 0, rot_mid_1hole); //x=81 + TGeoCombiTrans* combi_mid_2tubhole = + new TGeoCombiTrans(-7.7, -12.355, 0, rot_mid_1hole); // x=81 combi_mid_2tubhole->SetName("combi_mid_2tubhole"); combi_mid_2tubhole->RegisterYourself(); - // shape for midle - new TGeoBBox("midle_box", x_midle / 2, y_midle / 2, z_midle / 2); + // shape for middle + new TGeoBBox("middle_box", x_middle / 2, y_middle / 2, z_middle / 2); - new TGeoBBox("midle_d1box", x_midle_d1box / 2, y_midle_d1box / 2, z_midle_d1box / 2); + new TGeoBBox("middle_d1box", x_middle_d1box / 2, y_middle_d1box / 2, + z_middle_d1box / 2); - new TGeoBBox("midle_d2box", x_midle_d2box / 2, y_midle_d2box / 2, z_midle_d2box / 2); + new TGeoBBox("middle_d2box", x_middle_d2box / 2, y_middle_d2box / 2, + z_middle_d2box / 2); - new TGeoTubeSeg("arc_midle", radin_midle, radout_midle, high_midle / 2, ang_in_midle, ang_fin_midle); + new TGeoTubeSeg("arc_middle", radin_middle, radout_middle, high_middle / 2, + ang_in_middle, ang_fin_middle); - new TGeoTube("mid_1tubhole", radin_mid_1hole, radout_mid_1hole, high_mid_1hole / 2); + new TGeoTube("mid_1tubhole", radin_mid_1hole, radout_mid_1hole, + high_mid_1hole / 2); - new TGeoTube("mid_2tubhole", radin_mid_2hole, radout_mid_2hole, high_mid_2hole / 2); + new TGeoTube("mid_2tubhole", radin_mid_2hole, radout_mid_2hole, + high_mid_2hole / 2); - // composite shape for midle + auto* tube_fwm = new TGeoTubeSeg("tube_fwm", radin_fwm, radout_fwm, + high_fwm / 2, ang_in_fwm, ang_fin_fwm); + auto* fwm_1box = + new TGeoBBox("fwm_1box", x_fwm_1box / 2, y_fwm_1box / 2, z_fwm_1box / 2); + auto* fwm_2box = + new TGeoBBox("fwm_2box", x_fwm_2box / 2, y_fwm_2box / 2, z_fwm_2box / 2); - new TGeoCompositeShape("midle_Shape_0", " arc_midle + midle_box:tr1_midle_box - midle_box:tr2_midle_box - midle_d1box:tr_midle_d1box - midle_d2box:tr_midle_d2box"); + // composite shape for middle - auto* midle_Shape_1 = new TGeoCompositeShape("midle_Shape_1", " midle_Shape_0 -mid_1tubhole:combi_mid_1tubhole-mid_2tubhole:combi_mid_2tubhole"); + new TGeoCompositeShape( + "middle_Shape_0", + " arc_middle + middle_box:tr1_middle_box - middle_box:tr2_middle_box - " + "middle_d1box:tr_middle_d1box - middle_d2box:tr_middle_d2box"); - TGeoRotation* rot_midlez = new TGeoRotation("rot_midley", 180, 180, 0); - rot_midlez->RegisterYourself(); - TGeoCombiTrans* combi_midle_L = new TGeoCombiTrans(0, -7.625, 24.15 + 0.675, rot_90x); // x=7.35, y=0, z=15.79- 0,-7.625,24.15+0.675-80) - combi_midle_L->SetName("combi_midle_L"); - combi_midle_L->RegisterYourself(); + auto* middle_Shape_1 = new TGeoCompositeShape( + "middle_Shape_1", + " middle_Shape_0 " + "-mid_1tubhole:combi_mid_1tubhole-mid_2tubhole:combi_mid_2tubhole"); - TGeoTranslation* tr_midle_L = new TGeoTranslation("tr_midle_L", 0, -7.625, 24.15 + 0.675); // -152,-17.45,0 - tr_midle_L->RegisterYourself(); + TGeoRotation* rot_middlez = new TGeoRotation("rot_middley", 180, 180, 0); + rot_middlez->RegisterYourself(); + TGeoCombiTrans* combi_middle_L = new TGeoCombiTrans( + 0, -7.625, 24.15 + 0.675, + rot_90x); // x=7.35, y=0, z=15.79- 0,-7.625,24.15+0.675-80) + combi_middle_L->SetName("combi_middle_L"); + combi_middle_L->RegisterYourself(); - TGeoCombiTrans* combi_midle_R = new TGeoCombiTrans(0, -7.625, 24.15 + 0.675, rot_midlez); // x=7.35, y=0, z=15.79 - combi_midle_R->SetName("combi_midle_R"); - combi_midle_R->RegisterYourself(); + TGeoTranslation* tr_middle_L = new TGeoTranslation( + "tr_middle_L", 0, -4.45 - 0.1, 24.85 + 0.675); //+2.5,, -152,-17.45,0 + tr_middle_L->RegisterYourself(); - auto* midle_Volume = new TGeoVolume("midle_Volume", midle_Shape_1, kMedAlu); + TGeoCombiTrans* combi_middle_R = + new TGeoCombiTrans(0, -4.45 - 0.1, 24.85 + 0.675, + rot_middlez); // x=7.35, y=0, z=15.79 y7.625 ++2.5 + combi_middle_R->SetName("combi_middle_R"); + combi_middle_R->RegisterYourself(); - midle_L->AddNode(midle_Volume, 1, tr_midle_L); - midle_R->AddNode(midle_Volume, 1, combi_midle_R); + auto* middle_Shape_3 = new TGeoCompositeShape( + "middle_Shape_3", + " tube_fwm + fwm_1box:tr_fwm_1box - fwm_2box:tr_fwm_2box +tria_fwm"); - // midle->AddNode(midle_Volume,1); - midle->AddNode(midle_L, 1); - midle->AddNode(midle_R, 2); + auto* middle_Shape_4 = new TGeoCompositeShape( + "middle_Shape_4", + " tube_fwm + fwm_1box:tr_fwm_1box - fwm_2box:tr_fwm_2box +tria_fwm"); + + // auto* middle_Volume = new TGeoVolume("middle_Volume", middle_Shape_1, + // kMedAlu); + auto* middle_Volume_L = + new TGeoVolume("middle_Volume_L", middle_Shape_3, malu5083); + auto* middle_Volume_R = + new TGeoVolume("middle_Volume_R", middle_Shape_4, malu5083); + + TGeoTranslation* tr_middle = new TGeoTranslation( + "tr_middle", 0, -4.45 - 0.1, 24.85 + 0.675); //+2.5,, -152,-17.45,0 + tr_middle->RegisterYourself(); + + middle_L->AddNode(middle_Volume_L, 1, tr_middle); + middle_R->AddNode(middle_Volume_R, 1, combi_middle_R); // combi_midle_R + + middle->AddNode(middle_L, 1); + middle->AddNode(middle_R, 2); // new piece _/ \_ // Support_rail_L & Support_rail_R @@ -553,45 +860,51 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) auto* rail_L = new TGeoVolumeAssembly("rail_L"); // box down_2 - Double_t x_RL_1box = 3.0; // dx=15 - Double_t y_RL_1box = 1.21; // dy=6, -dy=6 - Double_t z_RL_1box = 0.8; // dz=4 to quit - TGeoTranslation* tr_RL_1box = new TGeoTranslation(0, y_RL_1box / 2, 1.825); // 81 + Double_t x_RL_1box = 3.0; // dx=15 + Double_t y_RL_1box = 1.21; // dy=6, -dy=6 + Double_t z_RL_1box = 0.8; // dz=4 to quit + TGeoTranslation* tr_RL_1box = + new TGeoTranslation(0, y_RL_1box / 2, 1.825); // 81 tr_RL_1box->SetName("tr_RL_1box"); tr_RL_1box->RegisterYourself(); TGeoXtru* xtru_RL1 = new TGeoXtru(2); xtru_RL1->SetName("S_XTRU_RL1"); - Double_t x_RL1[5] = {-1.5, 1.5, 0.5, 0.5, -1.5}; // 93,93,73,73,-15}; //vertices - Double_t y_RL1[5] = {1.2, 1.2, 2.2, 8.2, 8.2}; // 357.5,357.5,250.78,145.91}; + Double_t x_RL1[5] = {-1.5, 1.5, 0.5, 0.5, + -1.5}; // 93,93,73,73,-15}; //vertices + Double_t y_RL1[5] = {1.2, 1.2, 2.2, 8.2, 8.2}; // 357.5,357.5,250.78,145.91}; xtru_RL1->DefinePolygon(5, x_RL1, y_RL1); - xtru_RL1->DefineSection(0, -2.225, 0., 0., 1); // (plane,-zplane/ +zplane, x0, y0,(x/y)) + xtru_RL1->DefineSection(0, -2.225, 0., 0., + 1); // (plane,-zplane/ +zplane, x0, y0,(x/y)) xtru_RL1->DefineSection(1, 2.225, 0., 0., 1); - TGeoXtru* xtru_RL2 = new TGeoXtru(2); - xtru_RL2->SetName("S_XTRU_RL2"); + /// TGeoXtru* xtru_RL2 = new TGeoXtru(2); + /// xtru_RL2->SetName("S_XTRU_RL2"); - Double_t x_RL2[8] = {-1.5, 0.5, 0.5, 9.3, 9.3, 7.3, 7.3, -1.5}; // vertices - Double_t y_RL2[8] = {8.2, 8.2, 13.863, 24.35, 35.75, 35.75, 25.078, 14.591}; + /// Double_t x_RL2[8] = {-1.5, 0.5, 0.5, 9.3, 9.3, 7.3, 7.3, -1.5}; // + /// vertices Double_t y_RL2[8] = + /// {8.2, 8.2, 13.863, 24.35, 35.75, 35.75, 25.078, 14.591}; - xtru_RL2->DefinePolygon(8, x_RL2, y_RL2); + /// xtru_RL2->DefinePolygon(8, x_RL2, y_RL2); - xtru_RL2->DefineSection(0, 0.776, 0, 0, 1); // (plane,-zplane/+zplane, x0, y0,(x/y)) - xtru_RL2->DefineSection(1, 2.225, 0, 0, 1); + /// xtru_RL2->DefineSection(0, 0.776, 0, 0, 1); // (plane,-zplane/+zplane, x0, + /// y0,(x/y)) xtru_RL2->DefineSection(1, 2.225, 0, 0, 1); // box knee - Double_t x_RL_kneebox = 1.5; // dx=7.5 - Double_t y_RL_kneebox = 3.5; // dy=17.5 - Double_t z_RL_kneebox = 1.5; // dz=7.5 to quit - TGeoTranslation* tr_RL_kneebox = new TGeoTranslation(0, 0, 0); // 81 x =-2.5, y=145.91 + Double_t x_RL_kneebox = 1.5; // dx=7.5 + Double_t y_RL_kneebox = 3.5; // dy=17.5 + Double_t z_RL_kneebox = 1.5; // dz=7.5 to quit + TGeoTranslation* tr_RL_kneebox = + new TGeoTranslation(0, 0, 0); // 81 x =-2.5, y=145.91 tr_RL_kneebox->SetName("tr_RL_kneebox"); tr_RL_kneebox->RegisterYourself(); TGeoRotation* rot_knee = new TGeoRotation("rot_knee", -40, 0, 0); rot_knee->SetName("rot_knee"); rot_knee->RegisterYourself(); - TGeoCombiTrans* combi_knee = new TGeoCombiTrans(0.96, 1.75 + 0.81864, 0, rot_knee); // y= + TGeoCombiTrans* combi_knee = + new TGeoCombiTrans(0.96, 1.75 + 0.81864, 0, rot_knee); // y= combi_knee->SetName("combi_knee"); combi_knee->RegisterYourself(); // quit diagona-> qdi @@ -601,7 +914,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) TGeoRotation* rot_qdi = new TGeoRotation("rot_qdi", 0, 24.775, 0); rot_qdi->RegisterYourself(); - TGeoCombiTrans* combi_qdi = new TGeoCombiTrans(0, 5.579, -2.087, rot_qdi); // y= + TGeoCombiTrans* combi_qdi = + new TGeoCombiTrans(0, 5.579, -2.087, rot_qdi); // y= combi_qdi->SetName("combi_qdi"); combi_qdi->RegisterYourself(); // knee small @@ -613,7 +927,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t y_3RL[6] = {-1.75, -1.75, 1.203, 3.465, 4.4311, 1.75}; xtru3_RL->DefinePolygon(6, x_3RL, y_3RL); - xtru3_RL->DefineSection(0, -0.75, 0, 0, 1); // (plane,-zplane/+zplane, x0, y0,(x/y)) + xtru3_RL->DefineSection(0, -0.75, 0, 0, + 1); // (plane,-zplane/+zplane, x0, y0,(x/y)) xtru3_RL->DefineSection(1, 0.76, 0, 0, 1); TGeoTranslation* tr_vol3_RL = new TGeoTranslation(-0.25, 12.66, 0); // @@ -628,7 +943,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) TGeoRotation* rot_RL1hole = new TGeoRotation("rot_RL1hole", 0, 0, 0); rot_RL1hole->RegisterYourself(); - TGeoCombiTrans* combi_RL1hole = new TGeoCombiTrans(0.7, 0.6, 1.85, rot_RL1hole); //y= + TGeoCombiTrans* combi_RL1hole = + new TGeoCombiTrans(0.7, 0.6, 1.85, rot_RL1hole); // y= combi_RL1hole->SetName("combi_RL1hole"); combi_RL1hole->RegisterYourself(); // similar hole for R Join. @@ -639,36 +955,133 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) TGeoRotation* rot_ir_RL = new TGeoRotation("rot_ir_RL", 90, 90, 0); rot_ir_RL->RegisterYourself(); // in y = l_253.5 - 6. enter in (0,6,0) - TGeoCombiTrans* combi_ir1_RL = new TGeoCombiTrans(8.62, 24.75, 1.5, rot_ir_RL); + TGeoCombiTrans* combi_ir1_RL = + new TGeoCombiTrans(8.62, 24.75, 1.5, rot_ir_RL); combi_ir1_RL->SetName("combi_ir1_RL"); combi_ir1_RL->RegisterYourself(); TGeoCombiTrans* combi_ir2_RL = new TGeoCombiTrans(8.6, 33.15, 1.5, rot_ir_RL); combi_ir2_RL->SetName("combi_ir2_RL"); combi_ir2_RL->RegisterYourself(); + // + // 1) modification + TGeoXtru* xtru_RL2 = new TGeoXtru(2); + xtru_RL2->SetName("S_XTRU_RL2"); + + // modi the arm L---> new L + Double_t x_RL2[8] = {-1.5, 0.5, 0.5, 9.3, 9.3, 7.3, 7.3, -1.5}; + Double_t y_RL2[8] = {8.2, 8.2, 13.863, 24.35, 25.65, 25.65, 25.078, 14.591}; + + xtru_RL2->DefinePolygon(8, x_RL2, y_RL2); + xtru_RL2->DefineSection(0, 0.7752, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) 0.775 + xtru_RL2->DefineSection(1, 2.225, 0, 0, 1); + + // 2) modi adding box new element 1 box + TGeoXtru* adi1_RL = new TGeoXtru(2); + adi1_RL->SetName("S_ADI1_RL"); + + Double_t x_adi1RL[4] = {-1.5, -1.5, 0.5, 0.5}; + Double_t y_adi1RL[4] = {2.2, 13.863, 13.863, 2.2}; + + /// Double_t x_adi1RL[4]={-0.5,-0.5,1.5,1.5}; //vertices + ////Double_t y_adi1RL[4]={2.2,13.86,13.86,2.2}; + + adi1_RL->DefinePolygon(4, x_adi1RL, y_adi1RL); + adi1_RL->DefineSection(0, -0.75, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) + adi1_RL->DefineSection(1, 0.775, 0, 0, 1); // 0.76 + + //// 3) modi adding new knee new element 2 new knee + TGeoXtru* adi2_RL = new TGeoXtru(2); // + adi2_RL->SetName("S_ADI2_RL"); + Double_t x_adi2RL[6] = {-1.5, 0.5, 9.3, 9.3, 7.8, 7.8}; + Double_t y_adi2RL[6] = {13.863, 13.863, 24.35, 25.65, 25.65, 25.078}; + + adi2_RL->DefinePolygon(6, x_adi2RL, y_adi2RL); + adi2_RL->DefineSection(0, -0.75, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) + adi2_RL->DefineSection(1, 0.7755, 0, 0, 1); // 0.76, 0.775 + + // 4)modi to quit ---> trap + Double_t RL_dx1 = 2.66; // at -z + Double_t RL_dx2 = 1; // dat +z + Double_t RL_dy = 2.2; // dz=7.5 to quit + Double_t RL_dz = 1.5; // dz=1.5 to quit + // auto *trap1 = new TGeoTrd1("TRAP1",RL_dx1,RL_dx2 ,RL_dy ,RL_dz); + + TGeoRotation* rot_RL_Z50 = new TGeoRotation("rot_RL_Z50", 50, 0, 0); + rot_RL_Z50->RegisterYourself(); + TGeoCombiTrans* combi_RL_trap = + new TGeoCombiTrans(5, 18.633, -1.5 - 0.025, rot_RL_Z50); // y= + combi_RL_trap->SetName("combi_RL_trap"); + combi_RL_trap->RegisterYourself(); + + ///// 5) modi to quit inferior part box + Double_t x_qinf_box = 10.66; // + Double_t y_qinf_box = 10.2; // + Double_t z_qinf_box = 3.; // dz =1.5 + auto* s_RL_qinf_box = new TGeoBBox("S_RL_QINF_BOX", x_qinf_box / 2, + y_qinf_box / 2, z_qinf_box / 2); + TGeoCombiTrans* combi_RL_qbox = + new TGeoCombiTrans(7, 23., -1.5 - 0.025, rot_RL_Z50); // y= , z=-0.75-0.75 + combi_RL_qbox->SetName("combi_RL_qbox"); + combi_RL_qbox->RegisterYourself(); + + // 6) modi. add penta face z + TGeoXtru* pentfa_RL = new TGeoXtru(2); // not work + pentfa_RL->SetName("S_PENTFA_RL"); + Double_t x_pentfaRL[5] = {-1., -1., 0.13, 1., 1.}; + Double_t y_pentfaRL[5] = {1.125, 0.045, -1.125, -1.125, 1.125}; // 1.125 + + pentfa_RL->DefinePolygon(5, x_pentfaRL, y_pentfaRL); + pentfa_RL->DefineSection(0, -5.05, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) // 0.75 + pentfa_RL->DefineSection(1, 5.055, 0, 0, 1); // 0.76.. 0.9036 + + TGeoRotation* rot_X90 = new TGeoRotation("rot_X90", 0, 90, 0); + rot_X90->RegisterYourself(); + TGeoCombiTrans* combi_RL_pent = new TGeoCombiTrans( + 8.3, 30.705, 1.125 - 0.025, rot_X90); // x =8.3 , z= 1.125 + combi_RL_pent->SetName("combi_RL_pent"); + combi_RL_pent->RegisterYourself(); + // // shape for Rail L geom new TGeoBBox("RL_1box", x_RL_1box / 2, y_RL_1box / 2, z_RL_1box / 2); - new TGeoBBox("RL_kneebox", x_RL_kneebox / 2, y_RL_kneebox / 2, z_RL_kneebox / 2); // no_ used + new TGeoBBox("RL_kneebox", x_RL_kneebox / 2, y_RL_kneebox / 2, + z_RL_kneebox / 2); // no_ used new TGeoBBox("qdi_box", x_qdi_box / 2, y_qdi_box / 2, z_qdi_box / 2); - - // auto *s_RL1hole=new TGeoTube("S_RL1HOLE",radin_RL1hole,radout_RL1hole,high_RL1hole/2); - // auto *s_irL_hole=new TGeoTube("S_irL_HOLE",radin_ir_railL,radout_ir_railL,high_ir_railL/2); + new TGeoTrd1("TRAP1", RL_dx1, RL_dx2, RL_dy, RL_dz); + // auto *s_RL1hole=new + // TGeoTube("S_RL1HOLE",radin_RL1hole,radout_RL1hole,high_RL1hole/2); auto + // *s_irL_hole=new + // TGeoTube("S_irL_HOLE",radin_ir_railL,radout_ir_railL,high_ir_railL/2); // composite shape for rail L - auto* RL_Shape_0 = new TGeoCompositeShape("RL_Shape_0", " xtru3_RL:tr_vol3_RL + S_XTRU_RL1 + S_XTRU_RL2 + RL_1box:tr_RL_1box - qdi_box:combi_qdi"); + auto* RL_Shape_0 = new TGeoCompositeShape( + "RL_Shape_0", + " S_XTRU_RL1 + S_XTRU_RL2 + RL_1box:tr_RL_1box - " + "qdi_box:combi_qdi + " + "S_ADI1_RL + S_ADI2_RL - TRAP1:combi_RL_trap - " + "S_RL_QINF_BOX:combi_RL_qbox + " + "S_PENTFA_RL:combi_RL_pent"); // xtru3_RL:tr_vol3_RL + // + - TGeoVolume* rail_L_vol0 = new TGeoVolume("RAIL_L_VOL0", RL_Shape_0, kMedAlu); + TGeoVolume* rail_L_vol0 = new TGeoVolume("RAIL_L_VOL0", RL_Shape_0, malu5083); + // TGeoVolume* rail_L_vol0 = new TGeoVolume("RAIL_L_VOL0", RL_Shape_0, + // kMedAlu); rail_L->AddNode(rail_L_vol0, 1, new TGeoTranslation(0., 0., 1.5)); // piece 7th RAIL RIGHT // auto *rail_R = new TGeoVolumeAssembly("rail_R"); - Double_t x_RR_1box = 3.0; // dx=15 - Double_t y_RR_1box = 1.2; // dy=6, -dy=6 - Double_t z_RR_1box = 0.8; // dz=4 to quit - TGeoTranslation* tr_RR_1box = new TGeoTranslation("tr_RR_1box", 0, 0.6, 1.825); // 81 + Double_t x_RR_1box = 3.0; // dx=15 + Double_t y_RR_1box = 1.2; // dy=6, -dy=6 + Double_t z_RR_1box = 0.8; // dz=4 to quit + TGeoTranslation* tr_RR_1box = + new TGeoTranslation("tr_RR_1box", 0, 0.6, 1.825); // 81 tr_RR_1box->RegisterYourself(); TGeoXtru* part_RR1 = new TGeoXtru(2); @@ -680,34 +1093,39 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t y_RR1[5] = {1.2, 2.2, 8.2, 8.2, 1.2}; // 357.5,357.5,250.78,145.91}; part_RR1->DefinePolygon(5, x_RR1, y_RR1); - part_RR1->DefineSection(0, -2.225, 0, 0, 1); // (plane,-zplane/ +zplane, x0, y0,(x/y)) + part_RR1->DefineSection(0, -2.225, 0, 0, + 1); // (plane,-zplane/ +zplane, x0, y0,(x/y)) part_RR1->DefineSection(1, 2.225, 0, 0, 1); - TGeoXtru* part_RR2 = new TGeoXtru(2); - part_RR2->SetName("part_RR2"); + // TGeoXtru* part_RR2 = new TGeoXtru(2); + // part_RR2->SetName("part_RR2"); // TGeoVolume *vol_RR2 = gGeoManager->MakeXtru("part_RR2",Al,2); // TGeoXtru *xtru_RR2 = (TGeoXtru*)vol_RR2->GetShape(); - Double_t x_RR2[8] = {-0.5, -0.5, -9.3, -9.3, -7.3, -7.3, 1.5, 1.5}; // K,E,F,G,H,I,J,L // vertices - Double_t y_RR2[8] = {8.2, 13.863, 24.35, 35.75, 35.75, 25.078, 14.591, 8.2}; + // Double_t x_RR2[8] = {-0.5, -0.5, -9.3, -9.3, -7.3, -7.3, 1.5, 1.5}; // + // K,E,F,G,H,I,J,L // vertices Double_t y_RR2[8] = + // {8.2, 13.863, 24.35, 35.75, 35.75, 25.078, 14.591, 8.2}; - part_RR2->DefinePolygon(8, x_RR2, y_RR2); - part_RR2->DefineSection(0, 0.776, 0, 0, 1); // (plane,-zplane/+zplane, x0, y0,(x/y)) - part_RR2->DefineSection(1, 2.225, 0, 0, 1); + // part_RR2->DefinePolygon(8, x_RR2, y_RR2); + // part_RR2->DefineSection(0, 0.776, 0, 0, 1); // (plane,-zplane/+zplane, x0, + // y0,(x/y)) part_RR2->DefineSection(1, 2.225, 0, 0, 1); // knee (small) TGeoXtru* part_RR3 = new TGeoXtru(2); part_RR3->SetName("part_RR3"); - Double_t x_3RR[6] = {1.0, 1.0, -1.2497, -2.2138, -0.5, -0.5}; // R,Q,P,O,N.M // vertices + Double_t x_3RR[6] = {1.0, 1.0, -1.2497, + -2.2138, -0.5, -0.5}; // R,Q,P,O,N.M // vertices Double_t y_3RR[6] = {10.91, 14.41, 17.0911, 15.9421, 13.86, 10.91}; part_RR3->DefinePolygon(6, x_3RR, y_3RR); - part_RR3->DefineSection(0, -0.75, 0, 0, 1); // (plane,-zplane/+zplane, x0, y0,(x/y)) + part_RR3->DefineSection(0, -0.75, 0, 0, + 1); // (plane,-zplane/+zplane, x0, y0,(x/y)) part_RR3->DefineSection(1, 0.78, 0, 0, 1); - TGeoTranslation* tr_vol3_RR = new TGeoTranslation("tr_vol3_RR", -0.25, 12.66, 0); // + TGeoTranslation* tr_vol3_RR = + new TGeoTranslation("tr_vol3_RR", -0.25, 12.66, 0); // tr_vol3_RR->RegisterYourself(); // quit diagona-> qdi @@ -717,7 +1135,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) TGeoRotation* rot_Rqdi = new TGeoRotation("rot_Rqdi", 0, 24.775, 0); rot_Rqdi->RegisterYourself(); - TGeoCombiTrans* combi_Rqdi = new TGeoCombiTrans(0, 5.579, -2.087, rot_Rqdi); // y= + TGeoCombiTrans* combi_Rqdi = + new TGeoCombiTrans(0, 5.579, -2.087, rot_Rqdi); // y= combi_Rqdi->SetName("combi_Rqdi"); combi_Rqdi->RegisterYourself(); @@ -726,7 +1145,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t radout_a_rail = 0.325; // diameter 3.5 Double_t high_a_rail = 0.82; // - TGeoTranslation* tr_a_RR = new TGeoTranslation("tr_a_RR", -0.7, 0.6, 1.825); // right + TGeoTranslation* tr_a_RR = + new TGeoTranslation("tr_a_RR", -0.7, 0.6, 1.825); // right tr_a_RR->RegisterYourself(); // circular hole_ir. diameter=M3 (3 mm)) prof trou:8, tar:6mm Double_t radin_ir_rail = 0.; @@ -735,18 +1155,22 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) TGeoRotation* rot_ir_RR = new TGeoRotation("rot_ir_RR", 90, 90, 0); rot_ir_RR->RegisterYourself(); // in y = l_253.5 - 6. center in (0,6,0) - TGeoCombiTrans* combi_ir_RR = new TGeoCombiTrans(-8.62, 24.75, 1.5, rot_ir_RR); + TGeoCombiTrans* combi_ir_RR = + new TGeoCombiTrans(-8.62, 24.75, 1.5, rot_ir_RR); combi_ir_RR->SetName("combi_ir_RR"); combi_ir_RR->RegisterYourself(); - TGeoCombiTrans* combi_ir2_RR = new TGeoCombiTrans(-8.6, 33.15, 1.5, rot_ir_RR); + TGeoCombiTrans* combi_ir2_RR = + new TGeoCombiTrans(-8.6, 33.15, 1.5, rot_ir_RR); combi_ir2_RR->SetName("combi_ir2_RR"); combi_ir2_RR->RegisterYourself(); - TGeoCombiTrans* combi_rail_R = new TGeoCombiTrans(24.1, -1.825, 0, rot_90x); // y= + TGeoCombiTrans* combi_rail_R = + new TGeoCombiTrans(24.1, -1.825, 0, rot_90x); // y= combi_rail_R->SetName("combi_rail_R"); combi_rail_R->RegisterYourself(); - TGeoCombiTrans* combi_rail_L = new TGeoCombiTrans(-24.1, -1.825, 0, rot_90x); // y= + TGeoCombiTrans* combi_rail_L = + new TGeoCombiTrans(-24.1, -1.825, 0, rot_90x); // y= combi_rail_L->SetName("combi_rail_L"); combi_rail_L->RegisterYourself(); @@ -755,29 +1179,129 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) tr_sr_l->RegisterYourself(); TGeoTranslation* tr_sr_r = new TGeoTranslation("tr_sr_r", 15.01, 0, 0); // tr_sr_r->RegisterYourself(); + // + //////// new modfi b /////// cut arm + TGeoXtru* part_RR2 = new TGeoXtru(2); + part_RR2->SetName("part_RR2"); + //-TGeoVolume *vol_RR2 = gGeoManager->MakeXtru("S_XTRU_RR2",Al,2); + //-TGeoXtru *xtru_RR2 = (TGeoXtru*)vol_RR2->GetShape(); + // 1b) modi, reducing arm + // 1b) modi, reducing arm + Double_t x_RR2[8] = {-0.5, -0.5, -9.3, -9.3, + -7.3, -7.3, 1.5, 1.5}; // K,E,F,G,H,I,J,L//vertices + Double_t y_RR2[8] = {8.2, 13.863, 24.35, 25.65, + 25.65, 25.078, 14.591, 8.2}; // 35.75, 35.75 -->25.65 + + part_RR2->DefinePolygon(8, x_RR2, y_RR2); + part_RR2->DefineSection(0, 0.776, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) + part_RR2->DefineSection(1, 2.225, 0, 0, 1); + + // 2b) modi adding box new element 1 box + TGeoXtru* adi1_RR = new TGeoXtru(2); + adi1_RR->SetName("S_ADI1_RR"); + + Double_t x_adi1RR[4] = {-0.5, -.5, 1.5, 1.5}; // vertices + Double_t y_adi1RR[4] = {2.2, 13.863, 13.863, 2.2}; + + adi1_RR->DefinePolygon(4, x_adi1RR, y_adi1RR); + adi1_RR->DefineSection(0, -0.75, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) + adi1_RR->DefineSection(1, 0.775, 0, 0, 1); // 0.76 + + // 3b) modi adding new knee new element 2 new knee + TGeoXtru* adi2_RR = new TGeoXtru(2); // + adi2_RR->SetName("S_ADI2_RR"); + Double_t x_adi2RR[6] = {1.5, -0.5, -9.3, -9.3, -7.8, -7.8}; + Double_t y_adi2RR[6] = {13.863, 13.863, 24.35, 25.65, 25.65, 25.078}; + + adi2_RR->DefinePolygon(6, x_adi2RR, y_adi2RR); + adi2_RR->DefineSection(0, -0.75, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) + adi2_RR->DefineSection(1, 0.7755, 0, 0, 1); // 0.775 + + // 4)modi to quit ---> trap + // Double_t RL_dx1=2.66; //at -z (defined in rail L) + // Double_t RL_dx2=1; // dat +z + // Double_t RL_dy=2.2; // dz=7.5 to quit + // Double_t RL_dz=1.5; // dz=1.5 to quit + // auto *trap1 = new TGeoTrd1("TRAP1",RL_dx1,RL_dx2 ,RL_dy ,RL_dz); + TGeoRotation* rot_RR_Z310 = new TGeoRotation("rot_RR_Z310", -50, 0, 0); + rot_RR_Z310->RegisterYourself(); + TGeoCombiTrans* combi_RR_trap = + new TGeoCombiTrans(-5, 18.633, -1.5 - 0.025, rot_RR_Z310); // y= + combi_RR_trap->SetName("combi_RR_trap"); + combi_RR_trap->RegisterYourself(); + + // 5) modi to quit inferior part box + // Double_t x_qinf_box=10.66; // defined in RL + // Double_t y_qinf_box=10.2; // + /// Double_t z_qinf_box=3.; // dz =1.5 + /// auto *s_RL_qinf_box =new TGeoBBox("S_RL_QINF_BOX", + /// x_qinf_box/2,y_qinf_box/2,z_qinf_box/2); + TGeoCombiTrans* combi_RR_qbox = + new TGeoCombiTrans(-7, 23., -1.5 - 0.025, rot_RR_Z310); // rot to RR + combi_RR_qbox->SetName("combi_RR_qbox"); + combi_RR_qbox->RegisterYourself(); + + // 6) modi. add penta face z + TGeoXtru* pentfa_RR = new TGeoXtru(2); + pentfa_RR->SetName("S_PENTFA_RR"); + Double_t x_pentfaRR[5] = {1., 1., -0.13, -1., -1.}; + Double_t y_pentfaRR[5] = {1.125, 0.045, -1.125, -1.125, 1.125}; // 1.125 + + pentfa_RR->DefinePolygon(5, x_pentfaRR, y_pentfaRR); + pentfa_RR->DefineSection(0, -5.05, 0, 0, + 1); //(plane,-zplane/+zplane, x0, y0,(x/y)) // 0.75 + pentfa_RR->DefineSection(1, 5.055, 0, 0, 1); // 0.76.. 0.9036 + + // TGeoRotation *rot_X90 = new TGeoRotation("rot_X90", 0,90,0); + // rot_X90->RegisterYourself(); + TGeoCombiTrans* combi_RR_pent = new TGeoCombiTrans( + -8.3, 30.705, 1.125 - 0.025, rot_X90); // x =8.3 , z= 1.125 + combi_RR_pent->SetName("combi_RR_pent"); + combi_RR_pent->RegisterYourself(); // shape for rail R new TGeoBBox("RR_1box", x_RR_1box / 2, y_RR_1box / 2, z_RR_1box / 2); - // auto *s_qdi_Rbox =new TGeoBBox("S_QDI_RBOX", x_qdi_Rbox/2,y_qdi_Rbox/2,z_qdi_Rbox/2); + // auto *s_qdi_Rbox =new TGeoBBox("S_QDI_RBOX", + // x_qdi_Rbox/2,y_qdi_Rbox/2,z_qdi_Rbox/2); - // auto *s_ir_hole=new TGeoTube("S_ir_HOLE",radin_ir_rail,radout_ir_rail,high_ir_rail/2); + // auto *s_ir_hole=new + // TGeoTube("S_ir_HOLE",radin_ir_rail,radout_ir_rail,high_ir_rail/2); - // auto *s_cc_hole=new TGeoTube("S_CC_HOLE",radin_cc_rail,radout_cc_rail,high_cc_rail/2); + // auto *s_cc_hole=new + // TGeoTube("S_CC_HOLE",radin_cc_rail,radout_cc_rail,high_cc_rail/2); // composite shape for rail R - new TGeoCompositeShape("RR_Shape_0", "RR_1box:tr_RR_1box + part_RR1 + part_RR2 + part_RR3 - qdi_box:combi_qdi "); - - // auto * RR_Shape_0 = new TGeoCompositeShape("RR_Shape_0","RR_1box:tr_RR_1box+ S_part_RR1 + part_RR2 +part_RR3- qdi_box:combi_qdi + S_ir_HOLE:combi_ir_RR +S_ir_HOLE:combi_ir2_RR "); //-RR_1box:tr_RL_1box- S_b_HOLE:tr_b_RR -S_CC_HOLE:combi_cc2_RR + new TGeoCompositeShape( + "RR_Shape_0", + "RR_1box:tr_RR_1box + part_RR1 + part_RR2 - qdi_box:combi_qdi + " + "S_ADI1_RR + S_ADI2_RR - TRAP1:combi_RR_trap - " + "S_RL_QINF_BOX:combi_RR_qbox +S_PENTFA_RR:combi_RR_pent "); // quit + + // part_RR3 + // old knee + + // auto * RR_Shape_0 = new + // TGeoCompositeShape("RR_Shape_0","RR_1box:tr_RR_1box+ S_part_RR1 + part_RR2 + // +part_RR3- qdi_box:combi_qdi + S_ir_HOLE:combi_ir_RR + // +S_ir_HOLE:combi_ir2_RR "); //-RR_1box:tr_RL_1box- S_b_HOLE:tr_b_RR + // -S_CC_HOLE:combi_cc2_RR // JOIN only for show L and R parts - auto* rail_L_R_Shape = new TGeoCompositeShape("RAIL_L_R_Shape", " RL_Shape_0:combi_rail_L + RR_Shape_0:combi_rail_R"); + auto* rail_L_R_Shape = new TGeoCompositeShape( + "RAIL_L_R_Shape", " RL_Shape_0:combi_rail_L + RR_Shape_0:combi_rail_R"); - TGeoVolume* rail_L_R_vol0 = new TGeoVolume("RAIL_L_R_VOL0", rail_L_R_Shape, kMedAlu); + TGeoVolume* rail_L_R_vol0 = + new TGeoVolume("RAIL_L_R_VOL0", rail_L_R_Shape, malu5083); + // TGeoVolume* rail_L_R_vol0 = new TGeoVolume("RAIL_L_R_VOL0", rail_L_R_Shape, + // kMedAlu); TGeoRotation* rot_rLR = new TGeoRotation("rot_rLR", 180, 180, 0); rot_rLR->RegisterYourself(); - TGeoCombiTrans* combi_rLR = new TGeoCombiTrans(0, -6.9, -0.5, rot_rLR); // 0,-6.9,-0.5-80 + TGeoCombiTrans* combi_rLR = + new TGeoCombiTrans(0, -6.9, -0.5, rot_rLR); // 0,-6.9,-0.5-80 combi_rLR->SetName("combi_rLR"); combi_rLR->RegisterYourself(); @@ -787,6 +1311,22 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) auto* sup_rail_MBL = new TGeoVolumeAssembly("sup_rail_MBL"); + /// new sup_rail_MB_L 2020 -------------------------------- + + TGeoXtru* sup_MB_L = new TGeoXtru(2); + sup_MB_L->SetName("sup_MB_L"); + + // vertices a,b,c,d,e,f,g,h new... + Double_t x_sMB_L[11] = {0., 0., 8.12, 24.55, 24.55, 28.25, + 28.25, 34.55, 34.55, 31.737, 6.287}; + Double_t y_sMB_L[11] = {0., 1.8, 1.8, 9.934, 12.6, 12.6, + 13.4, 13.4, 12.6, 12.6, 0.}; + + sup_MB_L->DefinePolygon(11, x_sMB_L, y_sMB_L); + sup_MB_L->DefineSection(0, -0.4, 0, 0, + 1); //(plane, -zplane/ +zplane,x0,y0,(x/y)) + sup_MB_L->DefineSection(1, 0.4, 0, 0, 1); + TGeoXtru* part_MBL_0 = new TGeoXtru(2); part_MBL_0->SetName("part_MBL_0"); // V-MBL_0 @@ -795,53 +1335,71 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t y[8] = {-0.4, 0.4, 0.4, 13.0, 13.0, 12.2, 12.2, -0.4}; part_MBL_0->DefinePolygon(8, x, y); - part_MBL_0->DefineSection(0, -0.4, 0, 0, 1); // (plane, -zplane/ +zplane,x0,y0,(x/y)) + part_MBL_0->DefineSection(0, -0.4, 0, 0, + 1); // (plane, -zplane/ +zplane,x0,y0,(x/y)) part_MBL_0->DefineSection(1, 0.4, 0, 0, 1); TGeoRotation* rot1_MBL_0 = new TGeoRotation("rot1_MBL_0", -90, -90, 90); rot1_MBL_0->RegisterYourself(); // quit box in diag - Double_t x_mb_box = 0.8; // dx=4 - Double_t y_mb_box = 0.8; // dy=4 - Double_t z_mb_box = 0.81; // dz=4 to quit - TGeoTranslation* tr_mb_box = new TGeoTranslation("tr_mb_box", 24.05, 9.55, 0); // 240.5 + Double_t x_mb_box = 0.8; // dx=4 + Double_t y_mb_box = 0.8; // dy=4 + Double_t z_mb_box = 0.81; // dz=4 to quit + TGeoTranslation* tr_mb_box = + new TGeoTranslation("tr_mb_box", 24.05, 9.55, 0); // 240.5 tr_mb_box->RegisterYourself(); // lateral hole-box - Double_t x_lat_box = 0.7; //dx=0.35 - Double_t y_lat_box = 1.8; // dy=0.9 - Double_t z_lat_box = 0.2; // dz=0.1 - TGeoTranslation* tr_lat1L_box = new TGeoTranslation("tr_lat1L_box", 4.6, 0, 0.4); // + Double_t x_lat_box = 0.7; // dx=0.35 + Double_t y_lat_box = 1.8; // dy=0.9 + Double_t z_lat_box = 0.2; // dz=0.1 + TGeoTranslation* tr_lat1L_box = + new TGeoTranslation("tr_lat1L_box", 4.6, 0, 0.4); // tr_lat1L_box->RegisterYourself(); - TGeoTranslation* tr_lat2L_box = new TGeoTranslation("tr_lat2L_box", 9.6, 1.65, 0.4); // + TGeoTranslation* tr_lat2L_box = + new TGeoTranslation("tr_lat2L_box", 9.6, 1.65, 0.4); // tr_lat2L_box->RegisterYourself(); - TGeoTranslation* tr_lat3L_box = new TGeoTranslation("tr_lat3L_box", 18.53, 6.1, 0.4); // + /// TGeoTranslation* tr_lat3L_box = new + /// TGeoTranslation("tr_lat3L_box", 18.53, 6.1, 0.4); // + TGeoTranslation* tr_lat3L_box = + new TGeoTranslation("tr_lat3L_box", 17.35, 5.923, 0.4); // 18.53 tr_lat3L_box->RegisterYourself(); - TGeoTranslation* tr_lat4L_box = new TGeoTranslation("tr_lat4L_box", 26.45, 10, 0.4); // + TGeoTranslation* tr_lat4L_box = + new TGeoTranslation("tr_lat4L_box", 26.45, 10, 0.4); // tr_lat4L_box->RegisterYourself(); - TGeoTranslation* tr_lat5L_box = new TGeoTranslation("tr_lat5L_box", 29.9, 11.6, 0.4); // + TGeoTranslation* tr_lat5L_box = + new TGeoTranslation("tr_lat5L_box", 29.9, 11.6, 0.4); // tr_lat5L_box->RegisterYourself(); - TGeoTranslation* tr_lat1R_box = new TGeoTranslation("tr_lat1R_box", 4.6, 0, -0.4); // + TGeoTranslation* tr_lat1R_box = + new TGeoTranslation("tr_lat1R_box", 4.6, 0, -0.4); // tr_lat1R_box->RegisterYourself(); - TGeoTranslation* tr_lat2R_box = new TGeoTranslation("tr_lat2R_box", 9.6, 1.65, -0.4); // + TGeoTranslation* tr_lat2R_box = + new TGeoTranslation("tr_lat2R_box", 9.6, 1.65, -0.4); // tr_lat2R_box->RegisterYourself(); - TGeoTranslation* tr_lat3R_box = new TGeoTranslation("tr_lat3R_box", 18.53, 6.1, -0.4); // + /// TGeoTranslation* tr_lat3R_box = new + /// TGeoTranslation("tr_lat3R_box", 18.53, 6.1, -0.4); // + TGeoTranslation* tr_lat3R_box = + new TGeoTranslation("tr_lat3R_box", 17.35, 5.923, -0.4); // tr_lat3R_box->RegisterYourself(); - TGeoTranslation* tr_lat4R_box = new TGeoTranslation("tr_lat4R_box", 26.45, 10, -0.4); // + TGeoTranslation* tr_lat4R_box = + new TGeoTranslation("tr_lat4R_box", 26.45, 10, -0.4); // tr_lat4R_box->RegisterYourself(); - TGeoTranslation* tr_lat5R_box = new TGeoTranslation("tr_lat5R_box", 29.9, 11.6, -0.4); // + TGeoTranslation* tr_lat5R_box = + new TGeoTranslation("tr_lat5R_box", 29.9, 11.6, -0.4); // tr_lat5R_box->RegisterYourself(); // circular hole_1mbl. diameter=3.5 H9 Double_t radin_1mb = 0.; - Double_t radout_1mb = 0.175; // diameter 3.5mm _0.35 cm - Double_t high_1mb = 2.825; // dh=+/- 4 - TGeoTranslation* tr1_mb = new TGeoTranslation("tr1_mb", 18.48, 6.1, 0.); // right + Double_t radout_1mb = 0.175; // diameter 3.5mm _0.35 cm + Double_t high_1mb = 2.825; // dh=+/- 4 + TGeoTranslation* tr1_mb = + new TGeoTranslation("tr1_mb", 18.48, 6.1, 0.); // right tr1_mb->RegisterYourself(); - TGeoTranslation* tr2_mb = new TGeoTranslation("tr2_mb", 24.15, 8.9, 0.); // right + TGeoTranslation* tr2_mb = + new TGeoTranslation("tr2_mb", 24.15, 8.9, 0.); // right tr2_mb->RegisterYourself(); // circular hole_2mbl inclined and hole-up.diameter=M3 (3 mm)) prof , tar:8mm @@ -859,7 +1417,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) tr_mbr->RegisterYourself(); // hole up || hup - TGeoCombiTrans* combi_hup_mb = new TGeoCombiTrans(32.5, 12.6, 0, rot_90x); //y= + TGeoCombiTrans* combi_hup_mb = + new TGeoCombiTrans(32.5, 12.6, 0, rot_90x); // y= combi_hup_mb->SetName("combi_hup_mb"); combi_hup_mb->RegisterYourself(); @@ -870,33 +1429,56 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) new TGeoBBox("lat_box", x_lat_box / 2, y_lat_box / 2, z_lat_box / 2); // composite shape for rail_MB R + L - - // auto * MB_Shape_0 = new TGeoCompositeShape("MB_Shape_0"," V_MBL_0 - mb_box:tr_mb_box - hole_1mbl:tr1_mb + hole_1mbl:tr2_mb -hole_2mbl:combi_hup_mb "); - new TGeoCompositeShape("MB_Shape_0", "part_MBL_0 - mb_box:tr_mb_box - hole_1mbl:tr1_mb - hole_2mbl:combi_hup_mb"); - - new TGeoCompositeShape("MB_Shape_0L", "MB_Shape_0 - lat_box:tr_lat1L_box - lat_box:tr_lat2L_box - lat_box:tr_lat3L_box - lat_box:tr_lat4L_box - lat_box:tr_lat5L_box"); - - new TGeoCompositeShape("MB_Shape_0R", "MB_Shape_0 - lat_box:tr_lat1R_box - lat_box:tr_lat2R_box - lat_box:tr_lat3R_box - lat_box:tr_lat4R_box - lat_box:tr_lat5R_box"); - - new TGeoCompositeShape("MB_Shape_1L", "MB_Shape_0L:rot1_MBL_0 - hole_2mbl"); // one piece "completed" + auto* MB_Shape_0 = new TGeoCompositeShape( + "MB_Shape_0", " sup_MB_L - hole_2mbl:combi_hup_mb "); // new2020 + auto* MB_Shape_0L = new TGeoCompositeShape( + "MB_Shape_0L", "MB_Shape_0 - lat_box:tr_lat3L_box "); + auto* MB_Shape_0R = new TGeoCompositeShape( + "MB_Shape_0R", "MB_Shape_0 - lat_box:tr_lat3R_box "); + + // auto * MB_Shape_0 = new TGeoCompositeShape("MB_Shape_0"," V_MBL_0 - + // mb_box:tr_mb_box - hole_1mbl:tr1_mb + hole_1mbl:tr2_mb + // -hole_2mbl:combi_hup_mb "); + ////new TGeoCompositeShape("MB_Shape_0", "part_MBL_0 - mb_box:tr_mb_box - + /// hole_1mbl:tr1_mb - hole_2mbl:combi_hup_mb"); + + /// new TGeoCompositeShape("MB_Shape_0L", "MB_Shape_0 - lat_box:tr_lat1L_box - + /// lat_box:tr_lat2L_box - lat_box:tr_lat3L_box - lat_box:tr_lat4L_box - + /// lat_box:tr_lat5L_box"); + + /// new TGeoCompositeShape("MB_Shape_0R", "MB_Shape_0 - lat_box:tr_lat1R_box - + /// lat_box:tr_lat2R_box - lat_box:tr_lat3R_box - lat_box:tr_lat4R_box - + /// lat_box:tr_lat5R_box"); + + new TGeoCompositeShape( + "MB_Shape_1L", + "MB_Shape_0L:rot1_MBL_0 - hole_2mbl"); // one piece "completed" // left and right new TGeoCompositeShape("MB_Shape_1R", "MB_Shape_0R:rot1_MBL_0 - hole_2mbl"); - auto* MB_Shape_2 = new TGeoCompositeShape("MB_Shape_2", " MB_Shape_1L:tr_mbl + MB_Shape_1R:tr_mbr "); + auto* MB_Shape_2 = new TGeoCompositeShape( + "MB_Shape_2", " MB_Shape_1L:tr_mbl + MB_Shape_1R:tr_mbr "); - // TGeoVolume *sup_rail_MBL_vol0 = new TGeoVolume("SUPPORT_MBL_VOL0",MB_Shape_0,Al); - TGeoVolume* sup_rail_MBL_vol = new TGeoVolume("SUPPORT_MBL_VOL", MB_Shape_2, kMedAlu); + // TGeoVolume *sup_rail_MBL_vol0 = new + // TGeoVolume("SUPPORT_MBL_VOL0",MB_Shape_0,Al); + TGeoVolume* sup_rail_MBL_vol = + new TGeoVolume("SUPPORT_MBL_VOL", MB_Shape_2, malu5083); sup_rail_MBL->AddNode(sup_rail_MBL_vol, 1, rot_halfR); auto* stair = new TGeoVolumeAssembly("stair"); - stair->AddNode(sup_rail_MBL, 1, new TGeoTranslation(0, 0 - 28.8, 0 + 0.675)); - stair->AddNode(Cross_mft, 2, new TGeoTranslation(0, -28.8, 4.55 + 0.675)); - stair->AddNode(Cross_mb0, 3, new TGeoTranslation(0, 1.65 - 28.8, 9.55 + 0.675)); - stair->AddNode(Cross_mb0, 4, new TGeoTranslation(0, 6.1 - 28.8, 18.48 + 0.675)); - stair->AddNode(Cross_mft, 6, new TGeoTranslation(0, 10.0 - 28.8, 26.4 + 0.675)); - stair->AddNode(Cross_mft, 7, new TGeoTranslation(0, 11.6 - 28.8, 29.85 + 0.675)); + stair->AddNode(sup_rail_MBL, 1, + new TGeoTranslation(0, 0 - 28.8 - 0.4, 0 + 0.675)); + stair->AddNode(Cross_mft, 1, new TGeoTranslation(0, -28.8, 4.55 + 0.675)); + stair->AddNode(Cross_mft_2, 2, + new TGeoTranslation(0, 1.65 - 28.8, 9.55 + 0.675)); + stair->AddNode(Cross_mb0, 4, + new TGeoTranslation(0, 5.423 - 28.8, 17.35 + 0.675)); // 6.1 + stair->AddNode(Cross_mft_3, 5, + new TGeoTranslation(0, 11.7 - 28.8, 25.55 + 0.675)); + stair->AddNode(Cross_mft_4, 6, + new TGeoTranslation(0, 12.5 - 28.8, 29.05 + 0.675)); Double_t t_final_x; Double_t t_final_y; @@ -908,8 +1490,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) if (half == 0) { t_final_x = 0; - t_final_y = 0; - t_final_z = -80; + t_final_y = 0.0; + t_final_z = -80 - 0.675 - 0.15; r_final_x = 0; r_final_y = 0; @@ -918,18 +1500,158 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) if (half == 1) { t_final_x = 0; - t_final_y = 0; - t_final_z = -80; + t_final_y = 0.0; + t_final_z = -80 - 0.675 - 0.15; r_final_x = 0; r_final_y = 0; r_final_z = 180; } - auto* t_final = new TGeoTranslation("t_final", t_final_x, t_final_y, t_final_z); + auto* t_final = + new TGeoTranslation("t_final", t_final_x, t_final_y, t_final_z); auto* r_final = new TGeoRotation("r_final", r_final_x, r_final_y, r_final_z); auto* c_final = new TGeoCombiTrans(*t_final, *r_final); + // 9th new 2020 ELEMENT middle framework back ----------------------------- + auto* frame_back = new TGeoVolumeAssembly("frame_back"); + /// variables + // rectangular box1 to quit + Double_t x_box_fwb = 15.8; // dx= 7.2 cm + Double_t y_box_fwb = 5; + Double_t z_box_fwb = 1; + + // rectangular box2 to add + Double_t x_box2_fwb = 1.9; // dx= 7.2 cm + Double_t y_box2_fwb = 0.5; + Double_t z_box2_fwb = 0.6; + + ///// holes tub 1hole tranversal + Double_t radin_fwb = 25.75; + Double_t radout_fwb = 26.75; // diameter 3.5 H9 (0.35cm) + Double_t high_fwb = 0.6; /// + + // seg tub_back + Double_t radin_stub = 23.6; // 25.75 + Double_t radout_stub = 24.4; // 26.05 + Double_t high_stub = 0.6; + Double_t ang_in_stub = 288.9; // 270 + 19.56 + Double_t ang_fin_stub = 342.; // 360-17.56 + + TGeoRotation* rot_1hole_fwb = new TGeoRotation("rot_1hole_fwb", 0, 90, 0); + rot_1hole_fwb->RegisterYourself(); + /// h= hole + TGeoCombiTrans* acombi_fwb = new TGeoCombiTrans(5.2, 0, 0, rot_1hole_fwb); + acombi_fwb->SetName("acombi_1h_fwb"); + acombi_fwb->RegisterYourself(); + + TGeoTranslation* tr_box_y24 = + new TGeoTranslation("tr_box_y24", 0, -24., 0.); // + tr_box_y24->RegisterYourself(); + + TGeoTranslation* tr_box2_fwb = new TGeoTranslation( + "tr_box2_fwb", 24.4 - 1.9 / 2, -7.121 - 0.5 / 2, 0.); // + tr_box2_fwb->RegisterYourself(); + + TGeoRotation* rot_Z180_X180 = new TGeoRotation("rot_Z180_X180", 180, 180, 0); + rot_Z180_X180->RegisterYourself(); + + TGeoTranslation* tr_fb = + new TGeoTranslation("tr_fb", 0, -2.3 - 0.06, 13.85 + 0.675); // + tr_fb->RegisterYourself(); + + // + auto* q_box_fwb = + new TGeoBBox("q_box_fwb", x_box_fwb / 2, y_box_fwb / 2, z_box_fwb / 2); + auto* box2_fwb = + new TGeoBBox("box2_fwb", x_box2_fwb / 2, y_box2_fwb / 2, z_box2_fwb / 2); + auto* s_tub_fwb = + new TGeoTube("s_tub_fwb", radin_fwb, radout_fwb, high_fwb / 2); + // auto *s_ctub_fwb=new + // TGeoTube("S_ctub_fwb",radin_fwb,radout_fwb,high_2hole_mb0/2); + auto* s_stub_fwb = + new TGeoTubeSeg("s_stub_fwb", radin_stub, radout_stub, high_stub / 2, + ang_in_stub, ang_fin_stub); // r_in,r_out,dZ,ang,ang + + /// composite shape for mb0 + + auto* fwb_Shape_0 = new TGeoCompositeShape( + "fwb_Shape_0", + " s_stub_fwb - q_box_fwb:tr_box_y24 + box2_fwb:tr_box2_fwb "); + auto* fwb_Shape_1 = new TGeoCompositeShape( + "fwb_Shape_1", "fwb_Shape_0 + fwb_Shape_0:rot_Z180_X180"); + + auto* fwb_Volume = + new TGeoVolume("fwb_Volume", fwb_Shape_1, malu5083); // malu5083 + frame_back->AddNode(fwb_Volume, 1, tr_fb); + + //////////////////////////////////////////////// + /// 10 th colonne_support_MB012 new 2020 + auto* colonne_mb = new TGeoVolumeAssembly("colonne_mb"); + /// variables + // rectangular box + Double_t x_box_cmb = 1.9; // dx= 7.2 cm + Double_t y_box_cmb = 0.6; + Double_t z_box_cmb = 2.2033; + + ///// holes tub 1hole tranversal + Double_t radin_c_mb = 0.; + Double_t radout_c_mb = 0.3; // diameter 3.5 H9 (0.35cm) + Double_t high_c_mb = 2.2033; /// + + TGeoRotation* rot_1c_mb0 = new TGeoRotation("rot_1c_mb0", 0, 90, 0); + rot_1c_mb0->RegisterYourself(); + /// h= hole + TGeoCombiTrans* acombi_1c_mb0 = new TGeoCombiTrans(0.95, 0, 0, rot_1c_mb0); + acombi_1c_mb0->SetName("acombi_1c_mb0"); + acombi_1c_mb0->RegisterYourself(); + TGeoCombiTrans* bcombi_1c_mb0 = + new TGeoCombiTrans(-0.95, 0, 0, rot_1c_mb0); // y= + bcombi_1c_mb0->SetName("bcombi_1c_mb0"); + bcombi_1c_mb0->RegisterYourself(); + + // box to cut + Double_t x_boxq_cmb = 3.; // dx= 7.2 cm + Double_t y_boxq_cmb = 1.05; + Double_t z_boxq_cmb = 4.; + + TGeoRotation* rot_X19 = new TGeoRotation("rot_X19", 0, -19, 0); + rot_X19->RegisterYourself(); + TGeoCombiTrans* combi_qbox = + new TGeoCombiTrans(0, +2.1 / 2 + 0.5, 0, rot_X19); // x =8.3 , z= 1.125 + combi_qbox->SetName("combi_qbox"); + combi_qbox->RegisterYourself(); + + // shapes + + auto* box_cmb = + new TGeoBBox("box_cmb", x_box_cmb / 2, y_box_cmb / 2, z_box_cmb / 2); + auto* tub_cmb = + new TGeoTube("tub_cmb", radin_c_mb, radout_c_mb, high_c_mb / 2); + auto* boxq_cmb = + new TGeoBBox("boxq_cmb", x_boxq_cmb / 2, y_boxq_cmb / 2, z_boxq_cmb / 2); + + // auto *s_2hole_mb0=new + // TGeoTube("S_2HOLE_MB0",radin_2hole_mb0,radout_2hole_mb0,high_2hole_mb0/2); + + /// composite shape for mb0 + + auto* c_mb_Shape_0 = + new TGeoCompositeShape( + "box_cmb:rot_1c_mb0 + tub_cmb:acombi_1c_mb0 + " + "tub_cmb:bcombi_1c_mb0 - boxq_cmb:combi_qbox"); + + TGeoTranslation* tr_cmb = new TGeoTranslation( + "tr_cmb", 0, 5.923 - 28.8 + 2.2033 / 2 - 0.2, 17.35 + 0.675); // + tr_cmb->RegisterYourself(); + /////////////////// + // auto * cross_mb0_Volume = new + // TGeoVolume("cross_mb0_Volume",c_mb0_Shape_0,Al); // + auto* colonne_mb_Volume = + new TGeoVolume("colonne_mb_Volume", c_mb_Shape_0, malu5083); // malu5083 + colonne_mb->AddNode(colonne_mb_Volume, 1, tr_cmb); + + // auto* Half_3 = new TGeoVolumeAssembly("Half_3"); // Shell radii @@ -937,18 +1659,25 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Float_t Shell_rmin = 37.5 + .7; // Rotations and translations - auto* tShell_0 = new TGeoTranslation("tShell_0", 0., 0., 3.1 + (25.15 + 1.) / 2.); - auto* tShell_1 = new TGeoTranslation("tShell_1", 0., 0., -1.6 - (25.15 + 1.) / 2.); - auto* tShellHole = new TGeoTranslation("tShellHole", 0., 0., 2. / 2. + (25.15 + 1.) / 2.); - auto* tShellHole_0 = new TGeoTranslation("tShellHole_0", 0., -6.9, -26.1 / 2. - 6.2 / 2. - .1); - auto* tShellHole_1 = new TGeoTranslation("tShellHole_1", 0., 0., -26.1 / 2. - 6.2 / 2. - .1); + auto* tShell_0 = + new TGeoTranslation("tShell_0", 0., 0., 3.1 + (25.15 + 1.) / 2.); + auto* tShell_1 = + new TGeoTranslation("tShell_1", 0., 0., -1.6 - (25.15 + 1.) / 2.); + auto* tShellHole = + new TGeoTranslation("tShellHole", 0., 0., 2. / 2. + (25.15 + 1.) / 2.); + auto* tShellHole_0 = + new TGeoTranslation("tShellHole_0", 0., -6.9, -26.1 / 2. - 6.2 / 2. - .1); + auto* tShellHole_1 = + new TGeoTranslation("tShellHole_1", 0., 0., -26.1 / 2. - 6.2 / 2. - .1); auto* tShell_Cut = new TGeoTranslation("tShell_Cut", 0., 25. / 2., 0.); auto* tShell_Cut_1 = new TGeoTranslation("tShell_Cut_1", -23., 0., -8.); - auto* tShell_Cut_1_inv = new TGeoTranslation("tShell_Cut_1_inv", 23., 0., -8.); + auto* tShell_Cut_1_inv = + new TGeoTranslation("tShell_Cut_1_inv", 23., 0., -8.); auto* Rz = new TGeoRotation("Rz", 50., 0., 0.); auto* Rz_inv = new TGeoRotation("Rz_inv", -50., 0., 0.); auto* RShell_Cut = new TGeoRotation("RShell_Cut", 90., 90. - 24., -7.5); - auto* RShell_Cut_inv = new TGeoRotation("RShell_Cut_inv", 90., 90. + 24., -7.5); + auto* RShell_Cut_inv = + new TGeoRotation("RShell_Cut_inv", 90., 90. + 24., -7.5); auto* cShell_Cut = new TGeoCombiTrans(*tShell_Cut_1, *RShell_Cut); auto* cShell_Cut_inv = new TGeoCombiTrans(*tShell_Cut_1_inv, *RShell_Cut_inv); @@ -968,37 +1697,57 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) cShell_Cut_inv->RegisterYourself(); // Basic shapes for Half_3 - TGeoShape* Shell_0 = new TGeoTubeSeg("Shell_0", Shell_rmax / 2. - .1, Shell_rmax / 2., 6.2 / 2., 12., 168.); - TGeoShape* Shell_1 = new TGeoTubeSeg("Shell_1", Shell_rmin / 2. - .1, Shell_rmin / 2., 3.2 / 2., 0., 180.); - new TGeoConeSeg("Shell_2", (25.15 + 1.0) / 2., Shell_rmin / 2. - .1, Shell_rmin / 2., Shell_rmax / 2. - .1, Shell_rmax / 2., 0., 180.); - TGeoShape* Shell_3 = new TGeoTube("Shell_3", 0., Shell_rmin / 2. + .1, .1 / 2.); - TGeoShape* ShellHole_0 = new TGeoTrd1("ShellHole_0", 17.5 / 4., 42.5 / 4., 80. / 2., (25.15 + 1.) / 2.); - TGeoShape* ShellHole_1 = new TGeoBBox("ShellHole_1", 42.5 / 4., 80. / 2., 2. / 2. + 0.00001); - TGeoShape* ShellHole_2 = new TGeoBBox("ShellHole_2", 58.9 / 4., (Shell_rmin - 2.25) / 2., .4 / 2. + 0.00001); - TGeoShape* ShellHole_3 = new TGeoBBox("ShellHole_3", 80. / 4., (Shell_rmin - 11.6) / 2., .4 / 2. + 0.00001); + TGeoShape* Shell_0 = new TGeoTubeSeg("Shell_0", Shell_rmax / 2. - .1, + Shell_rmax / 2., 6.2 / 2., 12., 168.); + TGeoShape* Shell_1 = new TGeoTubeSeg("Shell_1", Shell_rmin / 2. - .1, + Shell_rmin / 2., 3.2 / 2., 0., 180.); + new TGeoConeSeg("Shell_2", (25.15 + 1.0) / 2., Shell_rmin / 2. - .1, + Shell_rmin / 2., Shell_rmax / 2. - .1, Shell_rmax / 2., 0., + 180.); + TGeoShape* Shell_3 = + new TGeoTube("Shell_3", 0., Shell_rmin / 2. + .1, .1 / 2.); + TGeoShape* ShellHole_0 = new TGeoTrd1("ShellHole_0", 17.5 / 4., 42.5 / 4., + 80. / 2., (25.15 + 1.) / 2.); + TGeoShape* ShellHole_1 = + new TGeoBBox("ShellHole_1", 42.5 / 4., 80. / 2., 2. / 2. + 0.00001); + TGeoShape* ShellHole_2 = new TGeoBBox( + "ShellHole_2", 58.9 / 4., (Shell_rmin - 2.25) / 2., .4 / 2. + 0.00001); + TGeoShape* ShellHole_3 = new TGeoBBox( + "ShellHole_3", 80. / 4., (Shell_rmin - 11.6) / 2., .4 / 2. + 0.00001); // For the extra cut, not sure if this is the shape (apprx. distances) TGeoShape* Shell_Cut_0 = new TGeoTube("Shell_Cut_0", 0., 3.5, 5. / 2.); - TGeoShape* Shell_Cut_1 = new TGeoBBox("Shell_Cut_1", 7. / 2., 25. / 2., 5. / 2.); + TGeoShape* Shell_Cut_1 = + new TGeoBBox("Shell_Cut_1", 7. / 2., 25. / 2., 5. / 2.); // Composite shapes for Half_3 - auto* Half_3_Shape_0 = new TGeoCompositeShape("Half_3_Shape_0", "Shell_Cut_0+Shell_Cut_1:tShell_Cut"); - new TGeoCompositeShape("Half_3_Shape_1", "Shell_2 - Half_3_Shape_0:cShell_Cut - Half_3_Shape_0:cShell_Cut_inv"); - auto* Half_3_Shape_2 = new TGeoCompositeShape("Half_3_Shape_2", "ShellHole_0+ShellHole_1:tShellHole"); - new TGeoCompositeShape("Half_3_Shape_3", "Shell_3:tShellHole_1 -(ShellHole_2:tShellHole_1 + ShellHole_3:tShellHole_0)"); - auto* Half_3_Shape_4 = new TGeoCompositeShape("Half_3_Shape_4", - "(Shell_0:tShell_0 + Half_3_Shape_1+ Shell_1:tShell_1) - (Half_3_Shape_2 + " - "Half_3_Shape_2:Rz + Half_3_Shape_2:Rz_inv)+Half_3_Shape_3"); - - auto* Half_3_Volume = new TGeoVolume("Half_3_Volume", Half_3_Shape_4, kMedAlu); - // Position of the piece relative to the origin which for this code is the center of the the Framework piece (See - // Half_2) + auto* Half_3_Shape_0 = new TGeoCompositeShape( + "Half_3_Shape_0", "Shell_Cut_0+Shell_Cut_1:tShell_Cut"); + new TGeoCompositeShape( + "Half_3_Shape_1", + "Shell_2 - Half_3_Shape_0:cShell_Cut - Half_3_Shape_0:cShell_Cut_inv"); + auto* Half_3_Shape_2 = new TGeoCompositeShape( + "Half_3_Shape_2", "ShellHole_0+ShellHole_1:tShellHole"); + new TGeoCompositeShape("Half_3_Shape_3", + "Shell_3:tShellHole_1 -(ShellHole_2:tShellHole_1 + " + "ShellHole_3:tShellHole_0)"); + auto* Half_3_Shape_4 = new TGeoCompositeShape( + "Half_3_Shape_4", + "(Shell_0:tShell_0 + Half_3_Shape_1+ Shell_1:tShell_1) - (Half_3_Shape_2 " + "+ " + "Half_3_Shape_2:Rz + Half_3_Shape_2:Rz_inv)+Half_3_Shape_3"); + + auto* Half_3_Volume = + new TGeoVolume("Half_3_Volume", Half_3_Shape_4, kMedAlu); + // Position of the piece relative to the origin which for this code is the + // center of the the Framework piece (See Half_2) // Half_3->AddNode(Half_3_Volume, 1, new TGeoTranslation(0., 0., -19.)); - TGeoRotation* rot_z180 = new TGeoRotation("rot_z180", 0, 180, 0); // orig: (180,0,0) + TGeoRotation* rot_z180 = + new TGeoRotation("rot_z180", 0, 180, 0); // orig: (180,0,0) rot_z180->RegisterYourself(); // in y = l_253.5 - 6. center in (0,6,0) - TGeoCombiTrans* combi_coat = new TGeoCombiTrans(0, 0, 19.5 - 0.45, rot_z180); // TGeoCombiTrans(0,0, -19.5,rot_z180) // -0.5 ->0.45 + TGeoCombiTrans* combi_coat = new TGeoCombiTrans(0, 0, 19.5 - 0.45, rot_z180); combi_coat->SetName("combi_coat"); combi_coat->RegisterYourself(); @@ -1009,9 +1758,11 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) HalfConeVolume->AddNode(base, 2, c_final); HalfConeVolume->AddNode(rail_L_R, 3, c_final); // R&L HalfConeVolume->AddNode(Fra_front, 4, c_final); - HalfConeVolume->AddNode(midle, 5, c_final); // - HalfConeVolume->AddNode(Half_3, 6, c_final); - // HalfConeVolume->AddNode(Half_3,8, new TGeoCombiTrans(0,0,0-0.5,rot_halfR)); //-0.675 + HalfConeVolume->AddNode(middle, 5, c_final); // + HalfConeVolume->AddNode(frame_back, 6, c_final); // + HalfConeVolume->AddNode(colonne_mb, 7, c_final); // + + // HalfConeVolume->AddNode(Half_3, 6, c_final); return HalfConeVolume; } From a45b70ea91136bd0dab5f468b650f0780888eb9d Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Thu, 9 Jul 2020 07:25:27 +0200 Subject: [PATCH 0052/1751] DPL Analysis: Spawn<> template for user-defined extended tables (#3958) --- Analysis/Tutorials/src/filters.cxx | 23 +++- Framework/Core/include/Framework/ASoA.h | 92 +++++++++++---- .../Core/include/Framework/AnalysisTask.h | 107 +++++++++++++++++- .../Core/include/Framework/Expressions.h | 19 ++++ Framework/Core/src/AODReaderHelpers.cxx | 46 +------- Framework/Core/src/ExpressionHelpers.h | 19 ---- 6 files changed, 215 insertions(+), 91 deletions(-) diff --git a/Analysis/Tutorials/src/filters.cxx b/Analysis/Tutorials/src/filters.cxx index 186373ef34a6c..fb7762708a1e7 100644 --- a/Analysis/Tutorials/src/filters.cxx +++ b/Analysis/Tutorials/src/filters.cxx @@ -16,9 +16,11 @@ namespace o2::aod namespace etaphi { DECLARE_SOA_COLUMN(NPhi, nphi, float); +DECLARE_SOA_EXPRESSION_COLUMN(CosPhi, cosphi, float, ncos(aod::etaphi::nphi)); } // namespace etaphi -DECLARE_SOA_TABLE(TPhi, "AOD", "ETAPHI", +DECLARE_SOA_TABLE(TPhi, "AOD", "TPHI", etaphi::NPhi); +DECLARE_SOA_EXTENDED_TABLE_USER(EPhi, TPhi, "EPHI", aod::etaphi::CosPhi); } // namespace o2::aod using namespace o2; @@ -30,17 +32,18 @@ using namespace o2::framework::expressions; // FIXME: this should really inherit from AnalysisTask but // we need GCC 7.4+ for that struct ATask { - Produces etaphi; - + Produces tphi; void process(aod::Tracks const& tracks) { for (auto& track : tracks) { - etaphi(track.phi()); + tphi(track.phi()); } } }; struct BTask { + Spawns ephi; + float fPI = static_cast(M_PI); float ptlow = 0.5f; float ptup = 2.0f; @@ -64,9 +67,19 @@ struct BTask { } }; +struct CTask { + void process(aod::Collision const&, soa::Join const& tracks) + { + for (auto& track : tracks) { + LOGF(INFO, "%.3f == %.3f", track.cosphi(), std::cos(track.phi())); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask("produce-normalizedphi"), - adaptAnalysisTask("consume-normalizedphi")}; + adaptAnalysisTask("consume-normalizedphi"), + adaptAnalysisTask("consume-spawned")}; } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 9d602b2ba49fa..604bc73f7cc28 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1232,28 +1232,34 @@ using ConcatBase = decltype(concat(std::declval(), std::declval())); #define DECLARE_SOA_TABLE(_Name_, _Origin_, _Description_, ...) \ DECLARE_SOA_TABLE_FULL(_Name_, #_Name_, _Origin_, _Description_, __VA_ARGS__); -#define DECLARE_SOA_EXTENDED_TABLE(_Name_, _Table_, _Description_, ...) \ - using _Name_ = o2::soa::JoinBase<_Table_, o2::soa::Table<__VA_ARGS__>>; \ - \ - struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ - using table_t = _Name_; \ - using base_table_t = _Table_; \ - using expression_pack_t = framework::pack<__VA_ARGS__>; \ - static constexpr char const* mLabel = #_Name_; \ - static constexpr char const mOrigin[4] = "DYN"; \ - static constexpr char const mDescription[16] = _Description_; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_> { \ - using metadata = _Name_##Metadata; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_::unfiltered_iterator> { \ - using metadata = _Name_##Metadata; \ +#define DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, _Origin_, _Description_, ...) \ + using _Name_ = o2::soa::JoinBase<_Table_, o2::soa::Table<__VA_ARGS__>>; \ + \ + struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ + using table_t = _Name_; \ + using base_table_t = _Table_; \ + using expression_pack_t = framework::pack<__VA_ARGS__>; \ + static constexpr char const* mLabel = #_Name_; \ + static constexpr char const mOrigin[4] = _Origin_; \ + static constexpr char const mDescription[16] = _Description_; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_> { \ + using metadata = _Name_##Metadata; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_::unfiltered_iterator> { \ + using metadata = _Name_##Metadata; \ }; +#define DECLARE_SOA_EXTENDED_TABLE(_Name_, _Table_, _Description_, ...) \ + DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "DYN", _Description_, __VA_ARGS__) + +#define DECLARE_SOA_EXTENDED_TABLE_USER(_Name_, _Table_, _Description_, ...) \ + DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "AOD", _Description_, __VA_ARGS__) + namespace o2::soa { template @@ -1443,6 +1449,52 @@ auto filter(T&& t, framework::expressions::Filter const& expr) return Filtered(t.asArrowTable(), expr); } +/// Expression-based column generator to materialize columns +template +auto spawner(framework::pack columns, arrow::Table* atable) +{ + arrow::TableBatchReader reader(*atable); + std::shared_ptr batch; + arrow::ArrayVector v; + std::vector chunks(sizeof...(C)); + + auto projectors = framework::expressions::createProjectors(columns, atable->schema()); + while (true) { + auto s = reader.ReadNext(&batch); + if (!s.ok()) { + throw std::runtime_error(fmt::format("Cannot read batches from table {}", s.ToString())); + } + if (batch == nullptr) { + break; + } + s = projectors->Evaluate(*batch, arrow::default_memory_pool(), &v); + if (!s.ok()) { + throw std::runtime_error(fmt::format("Cannot apply projector {}", s.ToString())); + } + for (auto i = 0u; i < sizeof...(C); ++i) { + chunks[i].emplace_back(v.at(i)); + } + } + std::vector> arrays(sizeof...(C)); + for (auto i = 0u; i < sizeof...(C); ++i) { + arrays[i] = std::make_shared(chunks[i]); + } + + auto extra_schema = o2::soa::createSchemaFromColumns(columns); + std::vector> new_fields; + std::vector> new_columns; + auto original_columns = atable->columns(); + auto original_fields = atable->schema()->fields(); + std::copy(original_fields.begin(), original_fields.end(), std::back_inserter(new_fields)); + std::copy(original_columns.begin(), original_columns.end(), std::back_inserter(new_columns)); + for (auto i = 0u; i < framework::pack_size(columns); ++i) { + new_columns.push_back(arrays[i]); + new_fields.emplace_back(extra_schema->field(i)); + } + auto new_schema = std::make_shared(new_fields); + return arrow::Table::Make(new_schema, new_columns); +} + } // namespace o2::soa #endif // O2_FRAMEWORK_ASOA_H_ diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 169a677aecd02..cd3056424216c 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -121,8 +121,8 @@ struct WritingCursor> { int64_t mCount = -1; }; -/// This helper class allow you to declare things which will be crated by a -/// give analysis task. Notice how the actual cursor is implemented by the +/// This helper class allows you to declare things which will be created by a +/// given analysis task. Notice how the actual cursor is implemented by the /// means of the WritingCursor helper class, from which produces actually /// derives. template @@ -142,6 +142,58 @@ struct Produces> : WritingCursor +struct Spawns { + using metadata = typename aod::MetadataTrait::metadata; + using base_table_t = typename metadata::base_table_t; + using expression_pack_t = typename metadata::expression_pack_t; + using base_metadata = typename aod::MetadataTrait::metadata; + + constexpr expression_pack_t pack() + { + return expression_pack_t{}; + } + + InputSpec const base_spec() + { + return InputSpec{ + base_metadata::tableLabel(), + header::DataOrigin{base_metadata::origin()}, + header::DataDescription{base_metadata::description()}}; + } + + constexpr const char* base_label() + { + return base_metadata::tableLabel(); + } + + OutputSpec const spec() const + { + return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; + } + + OutputRef ref() const + { + return OutputRef{metadata::tableLabel(), 0}; + } + T* operator->() + { + return table.get(); + } + T& operator*() + { + return *table.get(); + } + + auto asArrowTable() + { + return table->asArrowTable(); + } + std::shared_ptr table = nullptr; +}; + /// This helper class allows you to declare things which will be created by a /// given analysis task. Currently wrapped objects are limited to be TNamed /// descendants. Objects will be written to a ROOT file at the end of the @@ -886,6 +938,34 @@ struct OutputManager> { } }; +template +struct OutputManager> { + static bool appendOutput(std::vector& outputs, Spawns& what, uint32_t) + { + outputs.emplace_back(what.spec()); + return true; + } + + static bool prepare(ProcessingContext& pc, Spawns& what) + { + auto original_table = pc.inputs().get(what.base_label())->asArrowTable(); + what.table = std::make_shared(o2::soa::spawner(what.pack(), original_table.get())); + return true; + } + + static bool finalize(ProcessingContext&, Spawns&) + { + return true; + } + + static bool postRun(EndOfStreamContext& eosc, Spawns& what) + { + using metadata = typename std::decay_t::metadata; + eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); + return true; + } +}; + template class has_instance { @@ -967,6 +1047,24 @@ struct OptionManager> { } }; +/// Manager template to facilitate extended tables spawning +template +struct SpawnManager { + static bool requestInputs(std::vector&, T const&) { return false; } +}; + +template +struct SpawnManager> { + static bool requestInputs(std::vector& inputs, Spawns& spawns) + { + auto base_spec = spawns.base_spec(); + if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { + inputs.emplace_back(base_spec); + } + return true; + } +}; + // SFINAE test template class has_process @@ -1047,6 +1145,11 @@ DataProcessorSpec adaptAnalysisTask(char const* name, Args&&... args) }, tupledTask); } + //request base tables for spawnable extended tables + std::apply([&inputs](auto&... x) { + return (SpawnManager>::requestInputs(inputs, x), ...); + }, + tupledTask); std::apply([&outputs, &hash](auto&... x) { return (OutputManager>::appendOutput(outputs, x, hash), ...); }, tupledTask); std::apply([&options, &hash](auto&... x) { return (OptionManager>::appendOption(options, x), ...); }, tupledTask); diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index d883155768f21..c5c5cfb972fb6 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -433,6 +433,25 @@ void updateExpressionInfos(expressions::Filter const& filter, std::vector +std::shared_ptr createProjectors(framework::pack, gandiva::SchemaPtr schema) +{ + std::shared_ptr projector; + auto s = gandiva::Projector::Make( + schema, + {makeExpression( + framework::expressions::createExpressionTree( + framework::expressions::createOperations(C::Projector()), + schema), + C::asArrowField())...}, + &projector); + if (s.ok()) { + return projector; + } else { + throw std::runtime_error(fmt::format("Failed to create projector: {}", s.ToString())); + } +} } // namespace o2::framework::expressions #endif // O2_FRAMEWORK_EXPRESSIONS_H_ diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index aa31efa4f0f90..c8771181e6ea4 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -141,39 +141,6 @@ std::vector getListOfUnknown(std::vector const& routes return unknows; } -/// Expression-based column generator to materialize columns -template -auto spawner(framework::pack columns, arrow::Table* atable) -{ - arrow::TableBatchReader reader(*atable); - std::shared_ptr batch; - arrow::ArrayVector v; - std::vector chunks(sizeof...(C)); - - auto projectors = framework::expressions::createProjectors(columns, atable->schema()); - while (true) { - auto s = reader.ReadNext(&batch); - if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot read batches from table {}", s.ToString())); - } - if (batch == nullptr) { - break; - } - s = projectors->Evaluate(*batch, arrow::default_memory_pool(), &v); - if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot apply projector {}", s.ToString())); - } - for (auto i = 0u; i < sizeof...(C); ++i) { - chunks[i].emplace_back(v.at(i)); - } - } - std::vector> results(sizeof...(C)); - for (auto i = 0u; i < sizeof...(C); ++i) { - results[i] = std::make_shared(chunks[i]); - } - return results; -} - AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector requested) { return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { @@ -204,19 +171,8 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector reques auto maker = [&](auto metadata) { using metadata_t = decltype(metadata); using expressions = typename metadata_t::expression_pack_t; - auto extra_schema = o2::soa::createSchemaFromColumns(expressions{}); auto original_table = pc.inputs().get(input.binding)->asArrowTable(); - auto original_fields = original_table->schema()->fields(); - std::vector> fields; - auto arrays = spawner(expressions{}, original_table.get()); - std::vector> columns = original_table->columns(); - std::copy(original_fields.begin(), original_fields.end(), std::back_inserter(fields)); - for (auto i = 0u; i < framework::pack_size(expressions{}); ++i) { - columns.push_back(arrays[i]); - fields.emplace_back(extra_schema->field(i)); - } - auto new_schema = std::make_shared(fields); - return arrow::Table::Make(new_schema, columns); + return o2::soa::spawner(expressions{}, original_table.get()); }; if (description == header::DataDescription{"TRACKPAR"}) { diff --git a/Framework/Core/src/ExpressionHelpers.h b/Framework/Core/src/ExpressionHelpers.h index d42adc77b0f35..5797a94180b3c 100644 --- a/Framework/Core/src/ExpressionHelpers.h +++ b/Framework/Core/src/ExpressionHelpers.h @@ -96,25 +96,6 @@ struct ColumnOperationSpec { result.type = type; } }; - -template -std::shared_ptr createProjectors(framework::pack, gandiva::SchemaPtr schema) -{ - std::shared_ptr projector; - auto s = gandiva::Projector::Make( - schema, - {makeExpression( - framework::expressions::createExpressionTree( - framework::expressions::createOperations(C::Projector()), - schema), - C::asArrowField())...}, - &projector); - if (s.ok()) { - return projector; - } else { - throw std::runtime_error(fmt::format("Failed to create projector: {}", s.ToString())); - } -} } // namespace o2::framework::expressions #endif // O2_FRAMEWORK_EXPRESSIONS_HELPERS_H_ From db3ce9b71c46ac8811a924d13f94b32b01db2283 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 9 Jul 2020 01:22:31 +0200 Subject: [PATCH 0053/1751] Multiple fixes in RawFileReader * Create messages with FMQ channel transort * Create buffer for every input file * In part-per-super-page mode read s-page as single chunk * Add timers --- .../Raw/include/DetectorsRaw/RawFileReader.h | 93 ++++++++++--------- Detectors/Raw/src/RawFileReader.cxx | 15 ++- Detectors/Raw/src/RawFileReaderWorkflow.cxx | 59 ++++++++---- Detectors/Raw/src/rawfile-reader-workflow.cxx | 2 +- 4 files changed, 99 insertions(+), 70 deletions(-) diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index a73840d731df2..e2a1e3e6d6a58 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -103,12 +103,12 @@ class RawFileReader StartHB = 0x1 << 1, StartSP = 0x1 << 2, EndHB = 0x1 << 3 }; - size_t offset = 0; // where data of the block starts - uint32_t size = 0; // block size - uint32_t tfID = 0; // tf counter (from 0) - IR ir = 0; // ir starting the block - uint16_t fileID = 0; // file id where the block is located - uint8_t flags = 0; // different flags + size_t offset = 0; //! where data of the block starts + uint32_t size = 0; //! block size + uint32_t tfID = 0; //! tf counter (from 0) + IR ir = 0; //! ir starting the block + uint16_t fileID = 0; //! file id where the block is located + uint8_t flags = 0; //! different flags LinkBlock() = default; LinkBlock(int fid, size_t offs) : offset(offs), fileID(fid) {} void setFlag(uint8_t fl, bool v = true) @@ -124,26 +124,26 @@ class RawFileReader //===================================================================================== struct LinkData { - RDHAny rdhl; // RDH with the running info of the last RDH seen - LinkSpec_t spec = 0; // Link subspec augmented by its origin - LinkSubSpec_t subspec = 0; // subspec according to DataDistribution - uint32_t nTimeFrames = 0; - uint32_t nHBFrames = 0; - uint32_t nSPages = 0; - uint64_t nCRUPages = 0; - bool cruDetector = true; // CRU vs RORC detector - bool continuousRO = true; - - o2::header::DataOrigin origin = o2::header::gDataOriginInvalid; - o2::header::DataDescription description = o2::header::gDataDescriptionInvalid; - std::string fairMQChannel{}; // name of the fairMQ channel for the output - int nErrors = 0; - std::vector blocks; + RDHAny rdhl; //! RDH with the running info of the last RDH seen + LinkSpec_t spec = 0; //! Link subspec augmented by its origin + LinkSubSpec_t subspec = 0; //! subspec according to DataDistribution + uint32_t nTimeFrames = 0; //! + uint32_t nHBFrames = 0; //! + uint32_t nSPages = 0; //! + uint64_t nCRUPages = 0; //! + bool cruDetector = true; //! CRU vs RORC detector + bool continuousRO = true; //! + + o2::header::DataOrigin origin = o2::header::gDataOriginInvalid; //! + o2::header::DataDescription description = o2::header::gDataDescriptionInvalid; //! + std::string fairMQChannel{}; //! name of the fairMQ channel for the output + int nErrors = 0; //! + std::vector blocks; //! // // transient info during processing - bool openHB = false; - int nHBFinTF = 0; - int nextBlock2Read = 0; // next block which should be read + bool openHB = false; //! + int nHBFinTF = 0; //! + int nextBlock2Read = 0; //! next block which should be read LinkData() = default; template @@ -170,12 +170,12 @@ class RawFileReader std::string describe() const; private: - const RawFileReader* reader = nullptr; + const RawFileReader* reader = nullptr; //! }; //===================================================================================== - RawFileReader(const std::string& config = "", int verbosity = 0); + RawFileReader(const std::string& config = "", int verbosity = 0, size_t buffsize = 50 * 1024UL); ~RawFileReader() { clear(); } void loadFromInputsMap(const InputsMap& inp); @@ -239,28 +239,29 @@ class RawFileReader static constexpr o2::header::DataDescription DEFDataDescription = o2::header::gDataDescriptionRawData; static constexpr ReadoutCardType DEFCardType = CRU; - o2::header::DataOrigin mDefDataOrigin = DEFDataOrigin; - o2::header::DataDescription mDefDataDescription = DEFDataDescription; - ReadoutCardType mDefCardType = CRU; + o2::header::DataOrigin mDefDataOrigin = DEFDataOrigin; //! + o2::header::DataDescription mDefDataDescription = DEFDataDescription; //! + ReadoutCardType mDefCardType = CRU; //! - std::vector mFileNames; // input file names - std::vector mFiles; // input file handlers - std::vector mDataSpecs; // data origin and description for every input file + readout card type + std::vector mFileNames; //! input file names + std::vector mFiles; //! input file handlers + std::vector> mFileBuffers; //! buffers for input files + std::vector mDataSpecs; //! data origin and description for every input file + readout card type bool mInitDone = false; - std::unordered_map mLinkEntries; // mapping between RDH specs and link entry in the mLinksData - std::vector mLinksData; // info on links data in the files - std::vector mOrderedIDs; // links entries ordered in Specs - uint32_t mMaxTFToRead = 0xffffffff; // max TFs to process - uint32_t mNTimeFrames = 0; // total number of time frames - uint32_t mNextTF2Read = 0; // next TF to read - uint32_t mOrbitMin = 0xffffffff; // lowest orbit seen by any link - uint32_t mOrbitMax = 0; // highest orbit seen by any link - size_t mBufferSize = 1024 * 1024; // size of the buffer for files preprocessing - int mNominalSPageSize = 0x1 << 20; // expected super-page size in B - int mCurrentFileID = 0; // current file being processed - long int mPosInFile = 0; // current position in the file - bool mMultiLinkFile = false; // was > than 1 link seen in the file? - uint32_t mCheckErrors = 0; // mask for errors to check + std::unordered_map mLinkEntries; //! mapping between RDH specs and link entry in the mLinksData + std::vector mLinksData; //! info on links data in the files + std::vector mOrderedIDs; //! links entries ordered in Specs + uint32_t mMaxTFToRead = 0xffffffff; //! max TFs to process + uint32_t mNTimeFrames = 0; //! total number of time frames + uint32_t mNextTF2Read = 0; //! next TF to read + uint32_t mOrbitMin = 0xffffffff; //! lowest orbit seen by any link + uint32_t mOrbitMax = 0; //! highest orbit seen by any link + size_t mBufferSize = 5 * 1024UL; //! size of the buffer for files reading + int mNominalSPageSize = 0x1 << 20; //! expected super-page size in B + int mCurrentFileID = 0; //! current file being processed + long int mPosInFile = 0; //! current position in the file + bool mMultiLinkFile = false; //! was > than 1 link seen in the file? + uint32_t mCheckErrors = 0; //! mask for errors to check int mVerbosity = 0; ClassDefNV(RawFileReader, 1); diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index 1307022fd85c0..b8278cdaa98d1 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -243,13 +243,15 @@ size_t RawFileReader::LinkData::readNextSuperPage(char* buff) break; } ibl++; - auto fl = reader->mFiles[blc.fileID]; - if (fseek(fl, blc.offset, SEEK_SET) || fread(buff + sz, 1, blc.size, fl) != blc.size) { + sz += blc.size; + } + if (sz) { + auto fl = reader->mFiles[blocks[nextBlock2Read].fileID]; + if (fseek(fl, blocks[nextBlock2Read].offset, SEEK_SET) || fread(buff, 1, sz, fl) != sz) { LOGF(ERROR, "Failed to read for the %s a bloc:", describe()); - blc.print(); + blocks[nextBlock2Read].print(); error = true; } - sz += blc.size; } nextBlock2Read = ibl; return error ? 0 : sz; // in case of the error we ignore the data @@ -446,7 +448,7 @@ bool RawFileReader::LinkData::preprocessCRUPage(const RDHAny& rdh, bool newSPage //====================== methods of RawFileReader ======================== //_____________________________________________________________________ -RawFileReader::RawFileReader(const std::string& config, int verbosity) : mVerbosity(verbosity) +RawFileReader::RawFileReader(const std::string& config, int verbosity, size_t buffSize) : mVerbosity(verbosity), mBufferSize(buffSize) { if (!config.empty()) { auto inp = parseInput(config); @@ -573,7 +575,10 @@ bool RawFileReader::addFile(const std::string& sname, o2::header::DataOrigin ori LOG(ERROR) << "Cannot add new files after initialization"; return false; } + mFileBuffers.push_back(std::make_unique(mBufferSize)); auto inFile = fopen(sname.c_str(), "rb"); + setvbuf(inFile, mFileBuffers.back().get(), _IOFBF, mBufferSize); + bool ok = true; if (!inFile) { LOG(ERROR) << "Failed to open input file " << sname; diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index 6e77f572d17d8..b1aba7550ee52 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -27,7 +27,7 @@ #include "Headers/Stack.h" #include "RawFileReaderWorkflow.h" // not installed - +#include #include #include @@ -47,22 +47,27 @@ class RawReaderSpecs : public o2f::Task public: explicit RawReaderSpecs(const std::string& config, int loop = 1, uint32_t delay_us = 0, uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, - size_t spSize = 1024L * 1024L, size_t buffSize = 1024L * 1024L, + size_t spSize = 1024L * 1024L, size_t buffSize = 5 * 1024UL, const std::string& rawChannelName = "") - : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mPartPerSP(partPerSP), mReader(std::make_unique(config)), mRawChannelName(rawChannelName) + : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mPartPerSP(partPerSP), mReader(std::make_unique(config, 0, buffSize)), mRawChannelName(rawChannelName) { mReader->setCheckErrors(errmap); mReader->setMaxTFToRead(maxTF); - mReader->setBufferSize(buffSize); mReader->setNominalSPageSize(spSize); LOG(INFO) << "Will preprocess files with buffer size of " << buffSize << " bytes"; LOG(INFO) << "Number of loops over whole data requested: " << mLoop; + for (int i = NTimers; i--;) { + mTimer[i].Stop(); + mTimer[i].Reset(); + } } void init(o2f::InitContext& ic) final { assert(mReader); + mTimer[TimerInit].Start(); mReader->init(); + mTimer[TimerInit].Stop(); if (mMaxTFID >= mReader->getNTimeFrames()) { mMaxTFID = mReader->getNTimeFrames() - 1; } @@ -71,10 +76,11 @@ class RawReaderSpecs : public o2f::Task void run(o2f::ProcessingContext& ctx) final { assert(mReader); - static size_t loopsDone = 0, sentSize = 0, sentMessages = 0; if (mDone) { return; } + auto tTotStart = mTimer[TimerTotal].CpuTime(), tIOStart = mTimer[TimerIO].CpuTime(); + mTimer[TimerTotal].Start(false); auto device = ctx.services().get().device(); assert(device); @@ -105,11 +111,15 @@ class RawReaderSpecs : public o2f::Task if (tfID > mMaxTFID) { if (mReader->getNTimeFrames() && --mLoop) { - loopsDone++; + mLoopsDone++; tfID = 0; - LOG(INFO) << "Starting new loop " << loopsDone << " from the beginning of data"; + LOG(INFO) << "Starting new loop " << mLoopsDone << " from the beginning of data"; } else { - LOGF(INFO, "Finished: payload of %zu bytes in %zu messages sent for %d TFs", sentSize, sentMessages, mTFCounter); + mTimer[TimerTotal].Stop(); + LOGF(INFO, "Finished: payload of %zu bytes in %zu messages sent for %d TFs", mSentSize, mSentMessages, mTFCounter); + for (int i = 0; i < NTimers; i++) { + LOGF(INFO, "Timing for %15s: Cpu: %.3e Real: %.3e s in %d slots", TimerName[i], mTimer[i].CpuTime(), mTimer[i].RealTime(), mTimer[i].Counter() - 1); + } ctx.services().get().endOfStream(); ctx.services().get().readyToQuit(o2f::QuitRequest::Me); mDone = true; @@ -129,7 +139,7 @@ class RawReaderSpecs : public o2f::Task // read next time frame size_t tfNParts = 0, tfSize = 0; - LOG(INFO) << "Reading TF#" << mTFCounter << " (" << tfID << " at iteration " << loopsDone << ')'; + LOG(INFO) << "Reading TF#" << mTFCounter << " (" << tfID << " at iteration " << mLoopsDone << ')'; o2::header::Stack dummyStack{o2h::DataHeader{}, o2::framework::DataProcessingHeader{0}}; // dummy stack to just to get stack size auto hstackSize = dummyStack.size(); @@ -148,14 +158,16 @@ class RawReaderSpecs : public o2f::Task while (hdrTmpl.splitPayloadIndex < hdrTmpl.splitPayloadParts) { tfSize += hdrTmpl.payloadSize = mPartPerSP ? partsSP[hdrTmpl.splitPayloadIndex] : link.getNextHBFSize(); - - auto hdMessage = device->NewMessage(hstackSize); - auto plMessage = device->NewMessage(hdrTmpl.payloadSize); + auto fmqFactory = device->GetChannel(link.fairMQChannel, 0).Transport(); + auto hdMessage = fmqFactory->CreateMessage(hstackSize, fair::mq::Alignment{64}); + auto plMessage = fmqFactory->CreateMessage(hdrTmpl.payloadSize, fair::mq::Alignment{64}); + mTimer[TimerIO].Start(false); auto bread = mPartPerSP ? link.readNextSuperPage(reinterpret_cast(plMessage->GetData())) : link.readNextHBF(reinterpret_cast(plMessage->GetData())); if (bread != hdrTmpl.payloadSize) { LOG(ERROR) << "Link " << il << " read " << bread << " bytes instead of " << hdrTmpl.payloadSize << " expected in TF=" << mTFCounter << " part=" << hdrTmpl.splitPayloadIndex; } + mTimer[TimerIO].Stop(); // check if the RDH to send corresponds to expected orbit if (hdrTmpl.splitPayloadIndex == 0) { auto ir = o2::raw::RDHUtils::getHeartBeatIR(plMessage->GetData()); @@ -180,22 +192,23 @@ class RawReaderSpecs : public o2f::Task tfNParts++; } LOGF(DEBUG, "Added %d parts for TF#%d(%d in iteration %d) of %s/%s/0x%u", hdrTmpl.splitPayloadParts, mTFCounter, tfID, - loopsDone, link.origin.as(), link.description.as(), link.subspec); + mLoopsDone, link.origin.as(), link.description.as(), link.subspec); } if (mTFCounter) { // delay sending usleep(mDelayUSec); } - for (auto& msgIt : messagesPerRoute) { LOG(INFO) << "Sending " << msgIt.second->Size() / 2 << " parts to channel " << msgIt.first; device->Send(*msgIt.second.get(), msgIt.first); } + mTimer[TimerTotal].Stop(); + + LOGF(INFO, "Sent payload of %zu bytes in %zu parts in %zu messages for TF %d | Timing (total/IO): %.3e / %.3e", tfSize, tfNParts, + messagesPerRoute.size(), mTFCounter, mTimer[TimerTotal].CpuTime() - tTotStart, mTimer[TimerIO].CpuTime() - tIOStart); - LOGF(INFO, "Sent payload of %zu bytes in %zu parts in %zu messages for TF %d", tfSize, tfNParts, - messagesPerRoute.size(), mTFCounter); - sentSize += tfSize; - sentMessages += tfNParts; + mSentSize += tfSize; + mSentMessages += tfNParts; mReader->setNextTFToRead(++tfID); ++mTFCounter; @@ -215,10 +228,20 @@ class RawReaderSpecs : public o2f::Task uint32_t mDelayUSec = 0; // Delay in microseconds between TFs uint32_t mMinTFID = 0; // 1st TF to extract uint32_t mMaxTFID = 0xffffffff; // last TF to extrct + size_t mLoopsDone = 0; + size_t mSentSize = 0; + size_t mSentMessages = 0; bool mPartPerSP = true; // fill part per superpage bool mDone = false; // processing is over or not std::string mRawChannelName = ""; // name of optional non-DPL channel std::unique_ptr mReader; // matching engine + + enum TimerIDs { TimerInit, + TimerTotal, + TimerIO, + NTimers }; + static constexpr std::string_view TimerName[] = {"Init", "Total", "IO"}; + TStopwatch mTimer[NTimers]; }; o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t delay_us, uint32_t errmap, diff --git a/Detectors/Raw/src/rawfile-reader-workflow.cxx b/Detectors/Raw/src/rawfile-reader-workflow.cxx index 7962b0f50c7c4..8d56b8e3aca4d 100644 --- a/Detectors/Raw/src/rawfile-reader-workflow.cxx +++ b/Detectors/Raw/src/rawfile-reader-workflow.cxx @@ -28,7 +28,7 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"max-tf", VariantType::Int64, 0xffffffffL, {"max TF ID to process"}}); options.push_back(ConfigParamSpec{"loop", VariantType::Int, 1, {"loop N times (infinite for N<0)"}}); options.push_back(ConfigParamSpec{"delay", VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); - options.push_back(ConfigParamSpec{"buffer-size", VariantType::Int64, 1024L * 1024L, {"buffer size for files preprocessing"}}); + options.push_back(ConfigParamSpec{"buffer-size", VariantType::Int64, 5 * 1024L, {"buffer size for files preprocessing"}}); options.push_back(ConfigParamSpec{"super-page-size", VariantType::Int64, 1024L * 1024L, {"super-page size for FMQ parts definition"}}); options.push_back(ConfigParamSpec{"part-per-hbf", VariantType::Bool, false, {"FMQ parts per superpage (default) of HBF"}}); options.push_back(ConfigParamSpec{"raw-channel-config", VariantType::String, "", {"optional raw FMQ channel for non-DPL output"}}); From 8f992402e58dd37686277402f45035bbb778da4a Mon Sep 17 00:00:00 2001 From: Sean Date: Wed, 17 Jun 2020 13:42:22 +0200 Subject: [PATCH 0054/1751] fix trd tracklet plots, textual output of tracklet parameters when choosing to display --- Detectors/TRD/base/include/TRDBase/Tracklet.h | 2 +- Detectors/TRD/base/src/Tracklet.cxx | 2 +- .../TRD/simulation/src/TrapSimulator.cxx | 19 ++++++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Detectors/TRD/base/include/TRDBase/Tracklet.h b/Detectors/TRD/base/include/TRDBase/Tracklet.h index f417dd9bce22c..0a3e14de509e4 100644 --- a/Detectors/TRD/base/include/TRDBase/Tracklet.h +++ b/Detectors/TRD/base/include/TRDBase/Tracklet.h @@ -69,7 +69,7 @@ class Tracklet // ----- Getters for contents of tracklet word ----- int getYbin() const; // in units of 160 um - int getdY() const; // in units of 140 um + float getdY() const; // in units of 140 um int getZbin() const { return ((mROB >> 1) << 2) | (mMCM >> 2); } int getPID() const { return mPID; } diff --git a/Detectors/TRD/base/src/Tracklet.cxx b/Detectors/TRD/base/src/Tracklet.cxx index 110c2566d9123..d7ec1f82ff2bc 100644 --- a/Detectors/TRD/base/src/Tracklet.cxx +++ b/Detectors/TRD/base/src/Tracklet.cxx @@ -81,7 +81,7 @@ int Tracklet::getYbin() const return mY; } -int Tracklet::getdY() const +float Tracklet::getdY() const { return mdY; } diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index b166661faadd2..f61d0b8c9fc8b 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -670,8 +670,8 @@ void TrapSimulator::draw(int choice, int index) // PLOTTRACKLETS - plot tracklets if (!checkInitialized()) return; - TFile* rootfile = new TFile(Form("Spectra_%i.root", index), "RECREATE"); - TCanvas* c1 = new TCanvas("c1"); + TFile* rootfile = new TFile("trdtrackletplots.root", "UPDATE"); + TCanvas* c1 = new TCanvas(Form("canvas_%i_%i:%i:%i_%i", index, mDetector, mRobPos, mMcmPos, mTrackletArray.size())); TH2F* hist = new TH2F(Form("mcmdata_%i", index), Form("Data of MCM %i on ROB %i in detector %i ", mMcmPos, mRobPos, mDetector), FeeParam::getNadcMcm(), @@ -700,15 +700,15 @@ void TrapSimulator::draw(int choice, int index) hist->SetBinContent(iAdc + 1, iTimeBin + 1, mADCR[iAdc * mNTimeBin + iTimeBin] >> mgkAddDigits); } } + hist->Draw("COLZ"); } else { for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { histfiltered->SetBinContent(iAdc + 1, iTimeBin + 1, mADCF[iAdc * mNTimeBin + iTimeBin] >> mgkAddDigits); } } + histfiltered->Draw("COLZ"); } - hist->Draw("CONT4Z"); - histfiltered->Draw("CONT4Z"); if ((choice & PLOTHITS) != 0) { TGraph* grHits = new TGraph(); @@ -722,6 +722,11 @@ void TrapSimulator::draw(int choice, int index) if ((choice & PLOTTRACKLETS) != 0) { TLine* trklLines = new TLine[4]; + LOG(info) << "Tracklet start for index : " << index; + if (mTrackletArray.size() > 0) + LOG(info) << "Tracklet : for " << mTrackletArray[0].getDetector() << "::" << mTrackletArray[0].getROB() << " : " << mTrackletArray[0].getMCM(); + else + LOG(info) << "Tracklet : for trackletarray size of zero "; for (int iTrkl = 0; iTrkl < mTrackletArray.size(); iTrkl++) { Tracklet trkl = mTrackletArray[iTrkl]; float padWidth = 0.635 + 0.03 * (mDetector % 6); @@ -741,12 +746,12 @@ void TrapSimulator::draw(int choice, int index) trklLines[iTrkl].SetY2(t1); trklLines[iTrkl].SetLineColor(2); trklLines[iTrkl].SetLineWidth(2); - LOG(info) << "Tracklet " << iTrkl << ": y = " << trkl.getY() << ", dy = " << (trkl.getdY() * 140e-4) << " offset : " << offset; + LOG(info) << "Tracklet " << iTrkl << ": y = " << trkl.getY() << ", dy = " << (((float)trkl.getdY()) * 140e-4) << " offset : " << offset << "for a det:rob:mcm combo of : " << mDetector << ":" << mRobPos << ":" << mMcmPos; LOG(info) << "Tracklet " << iTrkl << ": x1,y1,x2,y2 :: " << trklLines[iTrkl].GetX1() << "," << trklLines[iTrkl].GetY1() << "," << trklLines[iTrkl].GetX2() << "," << trklLines[iTrkl].GetY2(); - LOG(info) << "Tracklet " << iTrkl << ": t0 : " << t0 << ", t1 " << t1 << ", padwidth:" << padWidth << ", slope:" << slope; - + LOG(info) << "Tracklet " << iTrkl << ": t0 : " << t0 << ", t1 " << t1 << ", padwidth:" << padWidth << ", slope:" << slope << ", ndrift:" << ndrift << " which comes from : " << mTrapConfig->getDmemUnsigned(mgkDmemAddrNdrift, mDetector, mRobPos, mMcmPos) << " shifted 5 to the right "; trklLines[iTrkl].Draw(); } + LOG(info) << "Tracklet end ..."; } c1->Write(); rootfile->Close(); From 75dc43b83c9e1a54cd9015edcd73f35245ee10ee Mon Sep 17 00:00:00 2001 From: Sean Date: Wed, 17 Jun 2020 17:15:05 +0200 Subject: [PATCH 0055/1751] fix type mistmatch, trackletarray can only ever 3 or less. --- Detectors/TRD/simulation/src/TrapSimulator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index f61d0b8c9fc8b..cf24778285715 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -671,7 +671,7 @@ void TrapSimulator::draw(int choice, int index) if (!checkInitialized()) return; TFile* rootfile = new TFile("trdtrackletplots.root", "UPDATE"); - TCanvas* c1 = new TCanvas(Form("canvas_%i_%i:%i:%i_%i", index, mDetector, mRobPos, mMcmPos, mTrackletArray.size())); + TCanvas* c1 = new TCanvas(Form("canvas_%i_%i:%i:%i_%i", index, mDetector, mRobPos, mMcmPos, (int)mTrackletArray.size())); TH2F* hist = new TH2F(Form("mcmdata_%i", index), Form("Data of MCM %i on ROB %i in detector %i ", mMcmPos, mRobPos, mDetector), FeeParam::getNadcMcm(), From 88a98e2a7927438831e4e46c6c1d5abb38ba4900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 9 Jul 2020 15:53:59 +0200 Subject: [PATCH 0056/1751] Improve run => timestamp conversion (#3956) * Improve output messages * Add check on milliseconds * Fix conversion from ns to ms * Add inspector for run2timestamp converter --- Analysis/Core/src/InsertNewRunToTimestamp.cxx | 2 +- Analysis/Core/src/RunToTimestamp.cxx | 4 +- .../Scripts/insert_Run2_run_to_timestamps.py | 59 ++++++++++++++++--- .../Scripts/inspect_Run2_run_to_timestamps.py | 34 +++++++++++ Analysis/Tasks/timestamp.cxx | 2 +- 5 files changed, 91 insertions(+), 10 deletions(-) create mode 100755 Analysis/Scripts/inspect_Run2_run_to_timestamps.py diff --git a/Analysis/Core/src/InsertNewRunToTimestamp.cxx b/Analysis/Core/src/InsertNewRunToTimestamp.cxx index 5753f3bd1da31..7a061c8abecc6 100644 --- a/Analysis/Core/src/InsertNewRunToTimestamp.cxx +++ b/Analysis/Core/src/InsertNewRunToTimestamp.cxx @@ -82,7 +82,7 @@ int main(int argc, char* argv[]) 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; + LOG(INFO) << "Retrieved run number to timestamp converter from ccdb url " << url; } if (vm["update"].as()) diff --git a/Analysis/Core/src/RunToTimestamp.cxx b/Analysis/Core/src/RunToTimestamp.cxx index ac9af576820ee..6b9a21f51468b 100644 --- a/Analysis/Core/src/RunToTimestamp.cxx +++ b/Analysis/Core/src/RunToTimestamp.cxx @@ -51,7 +51,9 @@ long RunToTimestamp::getTimestamp(uint runNumber) const void RunToTimestamp::print() const { LOG(INFO) << "Printing run number -> timestamp conversion"; + int counter = 0; for (auto e : mMap) { - LOG(INFO) << "Run number: " << e.first << " timestamp: " << e.second << "\n"; + 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/Scripts/insert_Run2_run_to_timestamps.py b/Analysis/Scripts/insert_Run2_run_to_timestamps.py index 4959000f1ba93..198104f0b1745 100755 --- a/Analysis/Scripts/insert_Run2_run_to_timestamps.py +++ b/Analysis/Scripts/insert_Run2_run_to_timestamps.py @@ -34,6 +34,9 @@ def __init__(self, run, start, 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: @@ -41,6 +44,26 @@ def check(self): 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}" @@ -48,15 +71,21 @@ def __eq__(self, other): return self.run == other.run -def main(input_file_name, extra_args, verbose=0): +def main(input_file_name, extra_args, input_in_seconds=0, verbose=0): """ - Given an input file with line by line runs and start and stop timestamps it updates the dedicated CCDB object + 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. + verbose flag can be set to 1, 2 to increase the debug level """ infile = open(input_file_name) + if verbose: + print(f"Reading run to timestamp from input file '{input_file_name}'") run_list = [] - for i in infile: + for line_no, i in enumerate(infile): i = i.strip() + if verbose == 2: + print(f"Line number {line_no}: {i}") i = i.split() run = i[1] if not run.isdigit(): @@ -67,7 +96,13 @@ def main(input_file_name, extra_args, verbose=0): stop = i[8] if not stop.isdigit(): raise ValueError("Read stop is not a number", stop) - entry = run_timestamp(run, start, 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) for i in run_list: @@ -76,6 +111,10 @@ def main(input_file_name, extra_args, verbose=0): cmd += f" --run {i.run}" cmd += f" --timestamp {i.start}" cmd += f" {extra_args}" + cmd += " -p Analysis/Core/RunToTimestamp" + if i == run_list[-1]: + # Printing the status of the converter as a last step + cmd += " -v 1" if verbose: print(cmd) subprocess.run(cmd.split()) @@ -88,7 +127,13 @@ def main(input_file_name, extra_args, verbose=0): 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') - parser.add_argument('--verbose', '-v', action='count', default=0) + 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('--verbose', '-v', action='count', + default=0, help="Verbose mode 0, 1, 2") args = parser.parse_args() - main(args.input_file_name, args.extra_args, verbose=args.verbose) + 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 new file mode 100755 index 0000000000000..dbc34abae02ec --- /dev/null +++ b/Analysis/Scripts/inspect_Run2_run_to_timestamps.py @@ -0,0 +1,34 @@ +#!/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/timestamp.cxx b/Analysis/Tasks/timestamp.cxx index d105fdedd46cf..75b9242f3af99 100644 --- a/Analysis/Tasks/timestamp.cxx +++ b/Analysis/Tasks/timestamp.cxx @@ -48,7 +48,7 @@ struct TimestampTask { long timestamp = converter->getTimestamp(bc.runNumber()); InteractionRecord current(bc.globalBC(), 0); InteractionRecord initial = o2::raw::HBFUtils::Instance().getFirstIR(); - timestamp += 1000 * (current - initial).bc2ns(); + timestamp += 1000000 * (current - initial).bc2ns(); ts_table(timestamp); } }; From ec9466910a642965d30e19a1a25d014b29d77b67 Mon Sep 17 00:00:00 2001 From: Kavaldrin <37471854+Kavaldrin@users.noreply.github.com> Date: Thu, 9 Jul 2020 16:53:57 +0200 Subject: [PATCH 0057/1751] DPL: add resources monitoring (#3879) --- Framework/Core/CMakeLists.txt | 1 + .../include/Framework/DeviceMetricsInfo.h | 4 + Framework/Core/include/Framework/DeviceSpec.h | 1 + Framework/Core/src/DeviceMetricsInfo.cxx | 30 +++++++ Framework/Core/src/DeviceSpecHelpers.cxx | 14 ++- Framework/Core/src/DeviceSpecHelpers.h | 9 +- Framework/Core/src/DriverInfo.h | 2 + Framework/Core/src/FrameworkGUIDebugger.cxx | 30 +++++++ .../Core/src/ResourcesMonitoringHelper.cxx | 87 +++++++++++++++++++ .../Core/src/ResourcesMonitoringHelper.h | 69 +++++++++++++++ Framework/Core/src/runDataProcessing.cxx | 56 +++++++----- 11 files changed, 276 insertions(+), 27 deletions(-) create mode 100644 Framework/Core/src/ResourcesMonitoringHelper.cxx create mode 100644 Framework/Core/src/ResourcesMonitoringHelper.h diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index bed0229de9cb0..5433d6af42da2 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -91,6 +91,7 @@ o2_add_library(Framework src/PropertyTreeHelpers.cxx src/RCombinedDS.cxx src/ReadoutAdapter.cxx + src/ResourcesMonitoringHelper.cxx src/SimpleResourceManager.cxx src/StreamOperators.cxx src/TMessageSerializer.cxx diff --git a/Framework/Core/include/Framework/DeviceMetricsInfo.h b/Framework/Core/include/Framework/DeviceMetricsInfo.h index 54d89668f975a..7e6781b114b07 100644 --- a/Framework/Core/include/Framework/DeviceMetricsInfo.h +++ b/Framework/Core/include/Framework/DeviceMetricsInfo.h @@ -27,6 +27,7 @@ enum class MetricType { Int = 0, String = 1, Float = 2, + Uint64 = 3, Unknown }; @@ -36,6 +37,7 @@ struct MetricInfo { enum MetricType type; size_t storeIdx; // Index in the actual store size_t pos; // Last position in the circular buffer + size_t filledMetrics; }; // We keep only fixed lenght strings for metrics, as in the end this is not @@ -61,6 +63,7 @@ struct ParsedMetricMatch { MetricType type; int intValue; float floatValue; + uint64_t uint64Value; char const* beginStringValue; char const* endStringValue; }; @@ -71,6 +74,7 @@ struct DeviceMetricsInfo { // We keep the size of each metric to 4096 bytes. No need for more // for the debug GUI std::vector> intMetrics; + std::vector> uint64Metrics; std::vector> stringMetrics; // We do not keep so many strings as metrics as history is less relevant. std::vector> floatMetrics; std::vector> timestamps; diff --git a/Framework/Core/include/Framework/DeviceSpec.h b/Framework/Core/include/Framework/DeviceSpec.h index c4b254c194be1..3ba159076b9a8 100644 --- a/Framework/Core/include/Framework/DeviceSpec.h +++ b/Framework/Core/include/Framework/DeviceSpec.h @@ -61,6 +61,7 @@ struct DeviceSpec { CompletionPolicy completionPolicy; DispatchPolicy dispatchPolicy; ComputingResource resource; + unsigned short resourceMonitoringInterval; }; } // namespace framework diff --git a/Framework/Core/src/DeviceMetricsInfo.cxx b/Framework/Core/src/DeviceMetricsInfo.cxx index 523cd8a69d50f..32d8bf6ff5184 100644 --- a/Framework/Core/src/DeviceMetricsInfo.cxx +++ b/Framework/Core/src/DeviceMetricsInfo.cxx @@ -93,6 +93,13 @@ bool DeviceMetricsHelper::parseMetric(std::string_view const s, ParsedMetricMatc match.beginStringValue = spaces[1] + 1; match.endStringValue = *(space - 2); break; + case MetricType::Uint64: + match.uint64Value = strtoul(spaces[1] + 1, &ep, 10); + if (ep != *(space - 2)) { + return false; + } + break; + default: return false; } @@ -115,6 +122,7 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, switch (match.type) { case MetricType::Float: case MetricType::Int: + case MetricType::Uint64: break; case MetricType::String: { auto lastChar = std::min(match.endStringValue - match.beginStringValue, StringMetric::MAX_SIZE - 1); @@ -143,6 +151,7 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, MetricInfo metricInfo; metricInfo.pos = 0; metricInfo.type = match.type; + metricInfo.filledMetrics = 0; // Add a new empty buffer for it of the correct kind switch (match.type) { case MetricType::Int: @@ -157,6 +166,11 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, metricInfo.storeIdx = info.floatMetrics.size(); info.floatMetrics.emplace_back(std::array{}); break; + case MetricType::Uint64: + metricInfo.storeIdx = info.uint64Metrics.size(); + info.uint64Metrics.emplace_back(std::array{}); + break; + default: return false; }; @@ -206,6 +220,7 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, info.timestamps[metricIndex][metricInfo.pos] = match.timestamp; // Update the position where to write the next metric metricInfo.pos = (metricInfo.pos + 1) % info.intMetrics[metricInfo.storeIdx].size(); + ++metricInfo.filledMetrics; } break; case MetricType::String: { info.stringMetrics[metricInfo.storeIdx][metricInfo.pos] = stringValue; @@ -213,6 +228,7 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, // so that we do not update timestamps for broken metrics info.timestamps[metricIndex][metricInfo.pos] = match.timestamp; metricInfo.pos = (metricInfo.pos + 1) % info.stringMetrics[metricInfo.storeIdx].size(); + ++metricInfo.filledMetrics; } break; case MetricType::Float: { info.floatMetrics[metricInfo.storeIdx][metricInfo.pos] = match.floatValue; @@ -222,7 +238,20 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, // so that we do not update timestamps for broken metrics info.timestamps[metricIndex][metricInfo.pos] = match.timestamp; metricInfo.pos = (metricInfo.pos + 1) % info.floatMetrics[metricInfo.storeIdx].size(); + ++metricInfo.filledMetrics; } break; + case MetricType::Uint64: { + info.uint64Metrics[metricInfo.storeIdx][metricInfo.pos] = match.uint64Value; + info.max[metricIndex] = std::max(info.max[metricIndex], (float)match.uint64Value); + info.min[metricIndex] = std::min(info.min[metricIndex], (float)match.uint64Value); + // Save the timestamp for the current metric we do it here + // so that we do not update timestamps for broken metrics + info.timestamps[metricIndex][metricInfo.pos] = match.timestamp; + // Update the position where to write the next metric + metricInfo.pos = (metricInfo.pos + 1) % info.uint64Metrics[metricInfo.storeIdx].size(); + ++metricInfo.filledMetrics; + } break; + default: return false; break; @@ -256,6 +285,7 @@ std::ostream& operator<<(std::ostream& oss, MetricType const& val) oss << "string"; break; case MetricType::Int: + case MetricType::Uint64: oss << "float"; break; case MetricType::Unknown: diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index be49cf0eeb670..5831c672d2944 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -646,13 +646,14 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector& devices, // Construct the list of actual devices we want, given a workflow. // // FIXME: make start port configurable? -void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(WorkflowSpec const& workflow, +void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workflow, std::vector const& channelPolicies, std::vector const& completionPolicies, std::vector const& dispatchPolicies, std::vector& devices, ResourceManager& resourceManager, - std::string const& uniqueWorkflowId) + std::string const& uniqueWorkflowId, + unsigned short resourcesMonitoringInterval) { std::vector availableForwardsInfo; @@ -729,6 +730,10 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(WorkflowSpec const& workf } } + for (auto& device : devices) { + device.resourceMonitoringInterval = resourcesMonitoringInterval; + } + auto findDeviceIndex = [&deviceIndex](size_t processorIndex, size_t timeslice) { for (auto& deviceEdge : deviceIndex) { if (deviceEdge.processorIndex != processorIndex) { @@ -968,6 +973,11 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, tmpArgs.emplace_back("dpl_" + uniqueWorkflowId); } + if (spec.resourceMonitoringInterval > 0) { + tmpArgs.emplace_back(std::string("--resources-monitoring")); + tmpArgs.emplace_back(std::to_string(spec.resourceMonitoringInterval)); + } + // We create the final option list, depending on the channels // which are present in a device. for (auto& arg : tmpArgs) { diff --git a/Framework/Core/src/DeviceSpecHelpers.h b/Framework/Core/src/DeviceSpecHelpers.h index a17da50053910..b9a92d2f173a1 100644 --- a/Framework/Core/src/DeviceSpecHelpers.h +++ b/Framework/Core/src/DeviceSpecHelpers.h @@ -48,7 +48,8 @@ struct DeviceSpecHelpers { std::vector const& dispatchPolicies, std::vector& devices, ResourceManager& resourceManager, - std::string const& uniqueWorkflowId); + std::string const& uniqueWorkflowId, + unsigned short resourcesMonitoringInterval = 0); static void dataProcessorSpecs2DeviceSpecs( const WorkflowSpec& workflow, @@ -56,10 +57,12 @@ struct DeviceSpecHelpers { std::vector const& completionPolicies, std::vector& devices, ResourceManager& resourceManager, - std::string const& uniqueWorkflowId) + std::string const& uniqueWorkflowId, + unsigned short resourcesMonitoringInterval = 0) { std::vector dispatchPolicies = DispatchPolicy::createDefaultPolicies(); - dataProcessorSpecs2DeviceSpecs(workflow, channelPolicies, completionPolicies, dispatchPolicies, devices, resourceManager, uniqueWorkflowId); + dataProcessorSpecs2DeviceSpecs(workflow, channelPolicies, completionPolicies, + dispatchPolicies, devices, resourceManager, uniqueWorkflowId, resourcesMonitoringInterval); } /// Helper to provide the channel configuration string for an input channel diff --git a/Framework/Core/src/DriverInfo.h b/Framework/Core/src/DriverInfo.h index 272b9daccfd88..80907e71e9519 100644 --- a/Framework/Core/src/DriverInfo.h +++ b/Framework/Core/src/DriverInfo.h @@ -129,6 +129,8 @@ struct DriverInfo { float frameLatency; /// The unique id used for ipc communications std::string uniqueWorkflowId = ""; + /// Metrics gathering interval + unsigned short resourcesMonitoringInterval; /// Last port used for tracy short tracyPort = 8086; }; diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/Core/src/FrameworkGUIDebugger.cxx index 56f3e8542c8ea..11e2ffa70b4c2 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/Core/src/FrameworkGUIDebugger.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include "Framework/ConfigContext.h" #include "Framework/ConfigParamRegistry.h" #include "DebugGUI/imgui.h" @@ -220,6 +221,13 @@ void displayDeviceMetrics(const char* label, ImVec2 canvasSize, std::string cons metricType = MetricType::Int; metricSize = metricsInfos[mi].intMetrics[metric.storeIdx].size(); } break; + case MetricType::Uint64: { + data.size = metricsInfos[mi].uint64Metrics[metric.storeIdx].size(); + data.Y = metricsInfos[mi].uint64Metrics[metric.storeIdx].data(); + data.type = MetricType::Uint64; + metricType = MetricType::Uint64; + metricSize = metricsInfos[mi].uint64Metrics[metric.storeIdx].size(); + } break; case MetricType::Float: { data.size = metricsInfos[mi].floatMetrics[metric.storeIdx].size(); data.Y = metricsInfos[mi].floatMetrics[metric.storeIdx].data(); @@ -251,6 +259,8 @@ void displayDeviceMetrics(const char* label, ImVec2 canvasSize, std::string cons assert(pos >= 0 && pos < 1024); if (histoData->type == MetricType::Int) { return static_cast(histoData->Y)[pos]; + } else if (histoData->type == MetricType::Uint64) { + return static_cast(histoData->Y)[pos]; } else if (histoData->type == MetricType::Float) { return static_cast(histoData->Y)[pos]; } else { @@ -328,6 +338,10 @@ void metricsTableRow(std::vector columnInfos, ImGui::Text("%i (%i)", metricsInfo.intMetrics[info.index][row], info.index); ImGui::NextColumn(); } break; + case MetricType::Uint64: { + ImGui::Text("%" PRIu64 " (%i)", metricsInfo.uint64Metrics[info.index][row], info.index); + ImGui::NextColumn(); + } break; case MetricType::Float: { ImGui::Text("%f (%i)", metricsInfo.floatMetrics[info.index][row], info.index); ImGui::NextColumn(); @@ -389,6 +403,22 @@ void historyBar(gui::WorkspaceGUIState& globalGUIState, ImGui::PlotLines(("##" + currentMetricName).c_str(), getter, &data, data.size); ImGui::NextColumn(); } break; + case MetricType::Uint64: { + HistoData data; + data.mod = metricsInfo.timestamps[i].size(); + data.first = metric.pos - data.mod; + data.size = metricsInfo.uint64Metrics[metric.storeIdx].size(); + data.points = metricsInfo.uint64Metrics[metric.storeIdx].data(); + + auto getter = [](void* hData, int idx) -> float { + auto histoData = reinterpret_cast*>(hData); + size_t pos = (histoData->first + static_cast(idx)) % histoData->mod; + assert(pos >= 0 && pos < 1024); + return histoData->points[pos]; + }; + ImGui::PlotLines(("##" + currentMetricName).c_str(), getter, &data, data.size); + ImGui::NextColumn(); + } break; case MetricType::Float: { HistoData data; data.mod = metricsInfo.timestamps[i].size(); diff --git a/Framework/Core/src/ResourcesMonitoringHelper.cxx b/Framework/Core/src/ResourcesMonitoringHelper.cxx new file mode 100644 index 0000000000000..b1630e9a48e3a --- /dev/null +++ b/Framework/Core/src/ResourcesMonitoringHelper.cxx @@ -0,0 +1,87 @@ +// 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 "ResourcesMonitoringHelper.h" +#include +#include +#include +#include + +using namespace o2::framework; + +bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector& metrics, const std::vector& specs) noexcept +{ + + assert(metrics.size() == specs.size()); + + if (metrics.empty()) { + return false; + } + + std::vector performanceMetrics = monitoring::ProcessMonitor::getAvailableMetricsNames(); + + boost::property_tree::ptree root; + for (unsigned int idx = 0; idx < metrics.size(); ++idx) { + + const auto& deviceMetrics = metrics[idx]; + boost::property_tree::ptree deviceRoot; + + for (const auto& metricLabel : deviceMetrics.metricLabelsIdx) { + + //check if we are interested + if (std::find(std::begin(performanceMetrics), std::end(performanceMetrics), metricLabel.label) == std::end(performanceMetrics)) { + continue; + } + + //if so + + boost::property_tree::ptree metricNode; + + switch (deviceMetrics.metrics[metricLabel.index].type) { + case MetricType::Int: + metricNode = fillNodeWithValue(deviceMetrics, deviceMetrics.intMetrics, + metricLabel.index, deviceMetrics.metrics[metricLabel.index].storeIdx); + break; + + case MetricType::Float: + metricNode = fillNodeWithValue(deviceMetrics, deviceMetrics.floatMetrics, + metricLabel.index, deviceMetrics.metrics[metricLabel.index].storeIdx); + break; + + case MetricType::String: + metricNode = fillNodeWithValue(deviceMetrics, deviceMetrics.stringMetrics, + metricLabel.index, deviceMetrics.metrics[metricLabel.index].storeIdx); + break; + + case MetricType::Uint64: + metricNode = fillNodeWithValue(deviceMetrics, deviceMetrics.uint64Metrics, + metricLabel.index, deviceMetrics.metrics[metricLabel.index].storeIdx); + break; + + default: + continue; + } + deviceRoot.add_child(metricLabel.label, metricNode); + } + + root.add_child(specs[idx].name, deviceRoot); + } + + std::ofstream file("performanceMetrics.json", std::ios::out); + if (file.is_open()) { + boost::property_tree::json_parser::write_json(file, root); + } else { + return false; + } + + file.close(); + + return true; +} \ No newline at end of file diff --git a/Framework/Core/src/ResourcesMonitoringHelper.h b/Framework/Core/src/ResourcesMonitoringHelper.h new file mode 100644 index 0000000000000..5b784be195a3d --- /dev/null +++ b/Framework/Core/src/ResourcesMonitoringHelper.h @@ -0,0 +1,69 @@ +// 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 __RESOURCES_MONITORING_MANAGER__H__ +#define __RESOURCES_MONITORING_MANAGER__H__ + +#include +#include "Framework/DeviceMetricsInfo.h" +#include "Monitoring/ProcessMonitor.h" +#include +#include "Framework/DeviceSpec.h" + +namespace o2 +{ +namespace framework +{ + +class ResourcesMonitoringHelper +{ + public: + static bool dumpMetricsToJSON(const std::vector& metrics, const std::vector& specs) noexcept; + static bool isResourcesMonitoringEnabled(unsigned short interval) noexcept { return interval > 0; } + + private: + template + static boost::property_tree::ptree fillNodeWithValue(const DeviceMetricsInfo& deviceMetrics, + const T& metricsStorage, size_t labelIndex, size_t storageIndex); + + template + inline static T retriveValue(T val) + { + return val; + } + inline static std::string retriveValue(const std::reference_wrapper val) + { + return std::string(val.get().data); + } + + ResourcesMonitoringHelper() = delete; +}; + +template +boost::property_tree::ptree ResourcesMonitoringHelper::fillNodeWithValue(const DeviceMetricsInfo& deviceMetrics, + const T& metricsStorage, size_t labelIndex, size_t storageIndex) +{ + + unsigned int loopRange = std::min(deviceMetrics.metrics[labelIndex].filledMetrics, metricsStorage.size()); + boost::property_tree::ptree metricNode; + + for (unsigned int idx = 0; idx < loopRange; ++idx) { + boost::property_tree::ptree values; + values.add("timestamp", deviceMetrics.timestamps[labelIndex][idx]); + values.add("value", retriveValue(std::cref(metricsStorage[storageIndex][idx]))); + metricNode.push_back(std::make_pair("", values)); + } + return metricNode; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 4428f81b0a3cc..2d6c07abd29f4 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -60,6 +60,7 @@ #include #include #include +#include "ResourcesMonitoringHelper.h" #include "FairMQDevice.h" #include @@ -677,6 +678,9 @@ int doChild(int argc, char** argv, const o2::framework::DeviceSpec& spec, Termin serviceRegistry.registerService(simpleRawDeviceService.get()); serviceRegistry.registerService(&spec); + if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(spec.resourceMonitoringInterval)) { + serviceRegistry.get().enableProcessMonitoring(spec.resourceMonitoringInterval); + } // The decltype stuff is to be able to compile with both new and old // FairMQ API (one which uses a shared_ptr, the other one a unique_ptr. decltype(r.fDevice) device; @@ -908,7 +912,9 @@ int runStateMachine(DataProcessorSpecs const& workflow, driverInfo.dispatchPolicies, deviceSpecs, *resourceManager, - driverInfo.uniqueWorkflowId); + driverInfo.uniqueWorkflowId, + driverInfo.resourcesMonitoringInterval); + // This should expand nodes so that we can build a consistent DAG. } catch (std::runtime_error& e) { std::cerr << "Invalid workflow: " << e.what() << std::endl; @@ -1076,6 +1082,10 @@ int runStateMachine(DataProcessorSpecs const& workflow, } break; case DriverState::EXIT: { + if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(driverInfo.resourcesMonitoringInterval)) { + LOG(INFO) << "Dumping performance metrics to performanceMetrics.json file"; + ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, deviceSpecs); + } // This is a clean exit. Before we do so, if required, // we dump the configuration of all the devices so that // we can reuse it @@ -1399,27 +1409,28 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, enum TerminationPolicy errorPolicy; bpo::options_description executorOptions("Executor options"); const char* helpDescription = "print help: short, full, executor, or processor name"; - executorOptions.add_options() // - ("help,h", bpo::value()->implicit_value("short"), helpDescription) // - ("quiet,q", bpo::value()->zero_tokens()->default_value(false), "quiet operation") // - ("stop,s", bpo::value()->zero_tokens()->default_value(false), "stop before device start") // - ("single-step", bpo::value()->zero_tokens()->default_value(false), "start in single step mode") // - ("batch,b", bpo::value()->zero_tokens()->default_value(isatty(fileno(stdout)) == 0), "batch processing mode") // - ("hostname", bpo::value()->default_value("localhost"), "hostname to deploy") // - ("resources", bpo::value()->default_value(""), "resources allocated for the workflow") // - ("start-port,p", bpo::value()->default_value(22000), "start port to allocate") // - ("port-range,pr", bpo::value()->default_value(1000), "ports in range") // - ("completion-policy,c", bpo::value(&policy)->default_value(TerminationPolicy::QUIT), // - "what to do when processing is finished: quit, wait") // - ("error-policy", bpo::value(&errorPolicy)->default_value(TerminationPolicy::QUIT), // - "what to do when a device has an error: quit, wait") // - ("graphviz,g", bpo::value()->zero_tokens()->default_value(false), "produce graph output") // - ("timeout,t", bpo::value()->default_value(0), "forced exit timeout (in seconds)") // - ("dds,D", bpo::value()->zero_tokens()->default_value(false), "create DDS configuration") // - ("dump-workflow,dump", bpo::value()->zero_tokens()->default_value(false), "dump workflow as JSON") // - ("dump-workflow-file", bpo::value()->default_value("-"), "file to which do the dump") // - ("run", bpo::value()->zero_tokens()->default_value(false), "run workflow merged so far") // - ("o2-control,o2", bpo::value()->zero_tokens()->default_value(false), "create O2 Control configuration"); + executorOptions.add_options() // + ("help,h", bpo::value()->implicit_value("short"), helpDescription) // // + ("quiet,q", bpo::value()->zero_tokens()->default_value(false), "quiet operation") // // + ("stop,s", bpo::value()->zero_tokens()->default_value(false), "stop before device start") // // + ("single-step", bpo::value()->zero_tokens()->default_value(false), "start in single step mode") // // + ("batch,b", bpo::value()->zero_tokens()->default_value(isatty(fileno(stdout)) == 0), "batch processing mode") // // + ("hostname", bpo::value()->default_value("localhost"), "hostname to deploy") // // + ("resources", bpo::value()->default_value(""), "resources allocated for the workflow") // // + ("start-port,p", bpo::value()->default_value(22000), "start port to allocate") // // + ("port-range,pr", bpo::value()->default_value(1000), "ports in range") // // + ("completion-policy,c", bpo::value(&policy)->default_value(TerminationPolicy::QUIT), // // + "what to do when processing is finished: quit, wait") // // + ("error-policy", bpo::value(&errorPolicy)->default_value(TerminationPolicy::QUIT), // // + "what to do when a device has an error: quit, wait") // // + ("graphviz,g", bpo::value()->zero_tokens()->default_value(false), "produce graph output") // // + ("timeout,t", bpo::value()->default_value(0), "forced exit timeout (in seconds)") // // + ("dds,D", bpo::value()->zero_tokens()->default_value(false), "create DDS configuration") // // + ("dump-workflow,dump", bpo::value()->zero_tokens()->default_value(false), "dump workflow as JSON") // // + ("dump-workflow-file", bpo::value()->default_value("-"), "file to which do the dump") // // + ("run", bpo::value()->zero_tokens()->default_value(false), "run workflow merged so far") // // + ("o2-control,o2", bpo::value()->zero_tokens()->default_value(false), "create O2 Control configuration") // + ("resources-monitoring", bpo::value()->default_value(0), "enable cpu/memory monitoring for provided interval in seconds"); // // some of the options must be forwarded by default to the device executorOptions.add(DeviceSpecHelpers::getForwardedDeviceOptions()); @@ -1625,6 +1636,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, driverInfo.timeout = varmap["timeout"].as(); driverInfo.deployHostname = varmap["hostname"].as(); driverInfo.resources = varmap["resources"].as(); + driverInfo.resourcesMonitoringInterval = varmap["resources-monitoring"].as(); // FIXME: should use the whole dataProcessorInfos, actually... driverInfo.processorInfo = dataProcessorInfos; From 3e788c10f0e74db322564d030becad5a51b424d1 Mon Sep 17 00:00:00 2001 From: Iouri Belikov Date: Sun, 5 Jul 2020 18:50:19 +0200 Subject: [PATCH 0058/1751] Increase cluster's maximal row and column spans --- .../ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h index 7e0a5f1446a00..585efe56deaad 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h @@ -38,7 +38,9 @@ class BuildTopologyDictionary; class ClusterPattern { public: - static constexpr int MaxPatternBits = 32 * 16; + static constexpr uint8_t MaxRowSpan = 128; + static constexpr uint8_t MaxColSpan = 128; + static constexpr int MaxPatternBits = MaxRowSpan * MaxColSpan; static constexpr int MaxPatternBytes = MaxPatternBits / 8; static constexpr int SpanMask = 0x7fff; static constexpr int TruncateMask = 0x8000; From 1d397a9a749ef7e40e68ea297fb236cea38bbb66 Mon Sep 17 00:00:00 2001 From: Iouri Belikov Date: Sun, 5 Jul 2020 12:40:56 +0200 Subject: [PATCH 0059/1751] Stream huge clusters in pieces --- .../include/ITSMFTReconstruction/Clusterer.h | 5 + .../common/reconstruction/src/Clusterer.cxx | 120 ++++++++++-------- 2 files changed, 75 insertions(+), 50 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h index 206cff40aa820..6f1ef5b7f8550 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h @@ -129,6 +129,11 @@ class Clusterer curr[row] = lastIndex; // store index of the new precluster in the current column buffer } + void streamCluster(uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, + int npix, uint16_t chipID, + CompClusCont* compClusPtr, PatternCont* patternsPtr, + MCTruth* labelsClusPtr, int nlab); + void fetchMCLabels(int digID, const MCTruth* labelsDig, int& nfilled); void initChip(const ChipPixelData* curChipData, uint32_t first); void updateChip(const ChipPixelData* curChipData, uint32_t ip); diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index 27832c45ec84d..44c487c6a5091 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -199,7 +199,7 @@ void Clusterer::ClustererThread::process(uint16_t chip, uint16_t nChips, CompClu //__________________________________________________ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClusCont* compClusPtr, - PatternCont* patternsPtr, const MCTruth* labelsDigPtr, MCTruth* labelsClusPTr) + PatternCont* patternsPtr, const MCTruth* labelsDigPtr, MCTruth* labelsClusPtr) { auto clustersCount = compClusPtr->size(); const auto& pixData = curChipData->getData(); @@ -218,7 +218,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus if (npix < pixArrBuff.size()) { pixArrBuff[npix++] = pix; // needed for cluster topology adjustBoundingBox(pix.getRowDirect(), pix.getCol(), rowMin, rowMax, colMin, colMax); - if (labelsClusPTr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second + if (labelsClusPtr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab); } next = pixEntry.first; @@ -236,7 +236,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus if (npix < pixArrBuff.size()) { pixArrBuff[npix++] = pix; // needed for cluster topology adjustBoundingBox(pix.getRowDirect(), pix.getCol(), rowMin, rowMax, colMin, colMax); - if (labelsClusPTr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second + if (labelsClusPtr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab); } next = pixEntry.first; @@ -244,73 +244,93 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus } preClusterIndices[i2] = -1; } - uint16_t rowSpan = rowMax - rowMin + 1, colSpan = colMax - colMin + 1; - uint16_t colSpanW = colSpan, rowSpanW = rowSpan; - if (colSpan * rowSpan > ClusterPattern::MaxPatternBits) { // need to store partial info - // will curtail largest dimension - if (colSpan > rowSpan) { - if ((colSpanW = ClusterPattern::MaxPatternBits / rowSpan) == 0) { - colSpanW = 1; - rowSpanW = ClusterPattern::MaxPatternBits; - } - } else { - if ((rowSpanW = ClusterPattern::MaxPatternBits / colSpan) == 0) { - rowSpanW = 1; - colSpanW = ClusterPattern::MaxPatternBits; - } - } + + auto chipID = curChipData->getChipID(); + uint16_t colSpan = (colMax - colMin + 1); + uint16_t rowSpan = (rowMax - rowMin + 1); + if (colSpan <= o2::itsmft::ClusterPattern::MaxColSpan && + rowSpan <= o2::itsmft::ClusterPattern::MaxRowSpan) { + streamCluster(rowMin, rowSpan, colMin, colSpan, npix, chipID, + compClusPtr, patternsPtr, labelsClusPtr, nlab); + } else { + LOG(WARNING) << "Splitting a huge cluster ! ChipID: " << chipID; + + colSpan %= o2::itsmft::ClusterPattern::MaxColSpan; + if (colSpan == 0) + colSpan = o2::itsmft::ClusterPattern::MaxColSpan; + + rowSpan %= o2::itsmft::ClusterPattern::MaxRowSpan; + if (rowSpan == 0) + rowSpan = o2::itsmft::ClusterPattern::MaxRowSpan; + + do { + uint16_t r = rowMin, rsp = rowSpan; + + do { + streamCluster(r, rsp, colMin, colSpan, npix, chipID, + compClusPtr, patternsPtr, labelsClusPtr, nlab); + r += rsp; + rsp = o2::itsmft::ClusterPattern::MaxRowSpan; + } while (r < rowMax); + + colMin += colSpan; + colSpan = o2::itsmft::ClusterPattern::MaxColSpan; + } while (colMin < colMax); } + } +} - if (labelsClusPTr) { // MC labels were requested - auto cnt = compClusPtr->size(); - for (int i = nlab; i--;) { - labelsClusPTr->addElement(cnt, labelsBuff[i]); - } +void Clusterer::ClustererThread::streamCluster(uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, int npix, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab) +{ + if (labelsClusPtr) { // MC labels were requested + auto cnt = compClusPtr->size(); + for (int i = nlab; i--;) { + labelsClusPtr->addElement(cnt, labelsBuff[i]); } + } - // add to compact clusters, which must be always filled - unsigned char patt[ClusterPattern::MaxPatternBytes] = {0}; // RSTODO FIX pattern filling - for (int i = 0; i < npix; i++) { - const auto pix = pixArrBuff[i]; - unsigned short ir = pix.getRowDirect() - rowMin, ic = pix.getCol() - colMin; - if (ir < rowSpanW && ic < colSpanW) { - int nbits = ir * colSpanW + ic; - patt[nbits >> 3] |= (0x1 << (7 - (nbits % 8))); - } + // add to compact clusters, which must be always filled + unsigned char patt[ClusterPattern::MaxPatternBytes] = {0}; // RSTODO FIX pattern filling + for (int i = 0; i < npix; i++) { + const auto pix = pixArrBuff[i]; + unsigned short ir = pix.getRowDirect() - rowMin, ic = pix.getCol() - colMin; + if (ir < rowSpanW && ic < colSpanW) { + int nbits = ir * colSpanW + ic; + patt[nbits >> 3] |= (0x1 << (7 - (nbits % 8))); } - uint16_t pattID = (parent->mPattIdConverter.size() == 0) ? CompCluster::InvalidPatternID : parent->mPattIdConverter.findGroupID(rowSpanW, colSpanW, patt); - if (pattID == CompCluster::InvalidPatternID || parent->mPattIdConverter.isGroup(pattID)) { - float xCOG = 0., zCOG = 0.; - ClusterPattern::getCOG(rowSpanW, colSpanW, patt, xCOG, zCOG); - rowMin += round(xCOG); - colMin += round(zCOG); - if (patternsPtr) { - patternsPtr->emplace_back((unsigned char)rowSpanW); - patternsPtr->emplace_back((unsigned char)colSpanW); - int nBytes = rowSpanW * colSpanW / 8; - if (((rowSpanW * colSpanW) % 8) != 0) - nBytes++; - patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + nBytes); - } + } + uint16_t pattID = (parent->mPattIdConverter.size() == 0) ? CompCluster::InvalidPatternID : parent->mPattIdConverter.findGroupID(rowSpanW, colSpanW, patt); + if (pattID == CompCluster::InvalidPatternID || parent->mPattIdConverter.isGroup(pattID)) { + float xCOG = 0., zCOG = 0.; + ClusterPattern::getCOG(rowSpanW, colSpanW, patt, xCOG, zCOG); + rowMin += round(xCOG); + colMin += round(zCOG); + if (patternsPtr) { + patternsPtr->emplace_back((unsigned char)rowSpanW); + patternsPtr->emplace_back((unsigned char)colSpanW); + int nBytes = rowSpanW * colSpanW / 8; + if (((rowSpanW * colSpanW) % 8) != 0) + nBytes++; + patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + nBytes); } - compClusPtr->emplace_back(rowMin, colMin, pattID, curChipData->getChipID()); } + compClusPtr->emplace_back(rowMin, colMin, pattID, chipID); } //__________________________________________________ void Clusterer::ClustererThread::finishChipSingleHitFast(uint32_t hit, ChipPixelData* curChipData, CompClusCont* compClusPtr, - PatternCont* patternsPtr, const MCTruth* labelsDigPtr, MCTruth* labelsClusPTr) + PatternCont* patternsPtr, const MCTruth* labelsDigPtr, MCTruth* labelsClusPtr) { auto clustersCount = compClusPtr->size(); auto pix = curChipData->getData()[hit]; uint16_t row = pix.getRowDirect(), col = pix.getCol(); - if (labelsClusPTr) { // MC labels were requested + if (labelsClusPtr) { // MC labels were requested int nlab = 0; fetchMCLabels(curChipData->getStartID() + hit, labelsDigPtr, nlab); auto cnt = compClusPtr->size(); for (int i = nlab; i--;) { - labelsClusPTr->addElement(cnt, labelsBuff[i]); + labelsClusPtr->addElement(cnt, labelsBuff[i]); } } From 96fa087920a4ef735a73bb00e518249ff706b3dc Mon Sep 17 00:00:00 2001 From: Iouri Belikov Date: Wed, 8 Jul 2020 13:44:37 +0200 Subject: [PATCH 0060/1751] Using a vector instead of an array --- .../include/ITSMFTReconstruction/Clusterer.h | 4 +-- .../common/reconstruction/src/Clusterer.cxx | 36 +++++++++---------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h index 6f1ef5b7f8550..83ceb07643c9a 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h @@ -95,7 +95,7 @@ class Clusterer uint16_t currCol = 0xffff; ///< Column being processed bool noLeftCol = true; ///< flag that there is no column on the left to check std::array labelsBuff; //! temporary buffer for building cluster labels - std::array pixArrBuff; //! temporary buffer for pattern calc. + std::vector pixArrBuff; //! temporary buffer for pattern calc. // /// temporary storage for the thread output CompClusCont compClusters; @@ -130,7 +130,7 @@ class Clusterer } void streamCluster(uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, - int npix, uint16_t chipID, + uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab); diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index 44c487c6a5091..ab3b2f96d4704 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -210,19 +210,18 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus } uint16_t rowMax = 0, rowMin = 65535; uint16_t colMax = 0, colMin = 65535; - int nlab = 0, npix = 0; + int nlab = 0; int next = preClusterHeads[i1]; + pixArrBuff.clear(); while (next >= 0) { const auto& pixEntry = pixels[next]; const auto pix = pixData[pixEntry.second]; - if (npix < pixArrBuff.size()) { - pixArrBuff[npix++] = pix; // needed for cluster topology - adjustBoundingBox(pix.getRowDirect(), pix.getCol(), rowMin, rowMax, colMin, colMax); - if (labelsClusPtr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second - fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab); - } - next = pixEntry.first; + pixArrBuff.push_back(pix); // needed for cluster topology + adjustBoundingBox(pix.getRowDirect(), pix.getCol(), rowMin, rowMax, colMin, colMax); + if (labelsClusPtr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second + fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab); } + next = pixEntry.first; } preClusterIndices[i1] = -1; for (int i2 = i1 + 1; i2 < preClusterHeads.size(); ++i2) { @@ -233,14 +232,12 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus while (next >= 0) { const auto& pixEntry = pixels[next]; const auto pix = pixData[pixEntry.second]; // PixelData - if (npix < pixArrBuff.size()) { - pixArrBuff[npix++] = pix; // needed for cluster topology - adjustBoundingBox(pix.getRowDirect(), pix.getCol(), rowMin, rowMax, colMin, colMax); - if (labelsClusPtr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second - fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab); - } - next = pixEntry.first; + pixArrBuff.push_back(pix); // needed for cluster topology + adjustBoundingBox(pix.getRowDirect(), pix.getCol(), rowMin, rowMax, colMin, colMax); + if (labelsClusPtr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second + fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab); } + next = pixEntry.first; } preClusterIndices[i2] = -1; } @@ -250,7 +247,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus uint16_t rowSpan = (rowMax - rowMin + 1); if (colSpan <= o2::itsmft::ClusterPattern::MaxColSpan && rowSpan <= o2::itsmft::ClusterPattern::MaxRowSpan) { - streamCluster(rowMin, rowSpan, colMin, colSpan, npix, chipID, + streamCluster(rowMin, rowSpan, colMin, colSpan, chipID, compClusPtr, patternsPtr, labelsClusPtr, nlab); } else { LOG(WARNING) << "Splitting a huge cluster ! ChipID: " << chipID; @@ -267,7 +264,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus uint16_t r = rowMin, rsp = rowSpan; do { - streamCluster(r, rsp, colMin, colSpan, npix, chipID, + streamCluster(r, rsp, colMin, colSpan, chipID, compClusPtr, patternsPtr, labelsClusPtr, nlab); r += rsp; rsp = o2::itsmft::ClusterPattern::MaxRowSpan; @@ -280,7 +277,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus } } -void Clusterer::ClustererThread::streamCluster(uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, int npix, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab) +void Clusterer::ClustererThread::streamCluster(uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab) { if (labelsClusPtr) { // MC labels were requested auto cnt = compClusPtr->size(); @@ -291,8 +288,7 @@ void Clusterer::ClustererThread::streamCluster(uint16_t rowMin, uint16_t rowSpan // add to compact clusters, which must be always filled unsigned char patt[ClusterPattern::MaxPatternBytes] = {0}; // RSTODO FIX pattern filling - for (int i = 0; i < npix; i++) { - const auto pix = pixArrBuff[i]; + for (const auto &pix : pixArrBuff) { unsigned short ir = pix.getRowDirect() - rowMin, ic = pix.getCol() - colMin; if (ir < rowSpanW && ic < colSpanW) { int nbits = ir * colSpanW + ic; From de42954390b750bacc1a6ac0a647e9c3300d6fe0 Mon Sep 17 00:00:00 2001 From: Iouri Belikov Date: Wed, 8 Jul 2020 17:52:58 +0200 Subject: [PATCH 0061/1751] Fixes in the streaming of pieces of huge clusters --- .../include/ITSMFTReconstruction/Clusterer.h | 2 +- .../common/reconstruction/src/Clusterer.cxx | 33 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h index 83ceb07643c9a..4982de1b5aebd 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h @@ -129,7 +129,7 @@ class Clusterer curr[row] = lastIndex; // store index of the new precluster in the current column buffer } - void streamCluster(uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, + void streamCluster(const std::vector& pixbuf, uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab); diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index ab3b2f96d4704..0b4406d7f17dd 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -232,7 +232,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus while (next >= 0) { const auto& pixEntry = pixels[next]; const auto pix = pixData[pixEntry.second]; // PixelData - pixArrBuff.push_back(pix); // needed for cluster topology + pixArrBuff.push_back(pix); // needed for cluster topology adjustBoundingBox(pix.getRowDirect(), pix.getCol(), rowMin, rowMax, colMin, colMax); if (labelsClusPtr) { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab); @@ -247,7 +247,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus uint16_t rowSpan = (rowMax - rowMin + 1); if (colSpan <= o2::itsmft::ClusterPattern::MaxColSpan && rowSpan <= o2::itsmft::ClusterPattern::MaxRowSpan) { - streamCluster(rowMin, rowSpan, colMin, colSpan, chipID, + streamCluster(pixArrBuff, rowMin, rowSpan, colMin, colSpan, chipID, compClusPtr, patternsPtr, labelsClusPtr, nlab); } else { LOG(WARNING) << "Splitting a huge cluster ! ChipID: " << chipID; @@ -264,8 +264,23 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus uint16_t r = rowMin, rsp = rowSpan; do { - streamCluster(r, rsp, colMin, colSpan, chipID, - compClusPtr, patternsPtr, labelsClusPtr, nlab); + // Select a subset of pixels fitting the reduced bounding box + std::vector pixbuf; + for (const auto& pix : pixArrBuff) { + unsigned short ir = pix.getRowDirect() - rowMin, ic = pix.getCol() - colMin; + if (ir < 0) + continue; + if (ic < 0) + continue; + if (ir < rsp && ic < colSpan) { + pixbuf.push_back(pix); + } + } + // Stream a piece of cluster only if the reduced bounding box is not empty + if (!pixbuf.empty()) { + streamCluster(pixbuf, r, rsp, colMin, colSpan, chipID, + compClusPtr, patternsPtr, labelsClusPtr, nlab); + } r += rsp; rsp = o2::itsmft::ClusterPattern::MaxRowSpan; } while (r < rowMax); @@ -277,7 +292,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus } } -void Clusterer::ClustererThread::streamCluster(uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab) +void Clusterer::ClustererThread::streamCluster(const std::vector& pixbuf, uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab) { if (labelsClusPtr) { // MC labels were requested auto cnt = compClusPtr->size(); @@ -288,12 +303,10 @@ void Clusterer::ClustererThread::streamCluster(uint16_t rowMin, uint16_t rowSpan // add to compact clusters, which must be always filled unsigned char patt[ClusterPattern::MaxPatternBytes] = {0}; // RSTODO FIX pattern filling - for (const auto &pix : pixArrBuff) { + for (const auto& pix : pixbuf) { unsigned short ir = pix.getRowDirect() - rowMin, ic = pix.getCol() - colMin; - if (ir < rowSpanW && ic < colSpanW) { - int nbits = ir * colSpanW + ic; - patt[nbits >> 3] |= (0x1 << (7 - (nbits % 8))); - } + int nbits = ir * colSpanW + ic; + patt[nbits >> 3] |= (0x1 << (7 - (nbits % 8))); } uint16_t pattID = (parent->mPattIdConverter.size() == 0) ? CompCluster::InvalidPatternID : parent->mPattIdConverter.findGroupID(rowSpanW, colSpanW, patt); if (pattID == CompCluster::InvalidPatternID || parent->mPattIdConverter.isGroup(pattID)) { From 3e31b31bdcf9c796bf771a35c6495bdd711eae70 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 9 Jul 2020 17:18:36 +0200 Subject: [PATCH 0062/1751] Use int counter to allow > 0xffff hits/chip in AlpideDecoder --- .../reconstruction/include/ITSMFTReconstruction/AlpideCoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h index 1ce80e2c1ec43..bae591a99444d 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h @@ -347,7 +347,7 @@ class AlpideCoder // ===================================================================== // // cluster map used for the ENCODING only - std::vector mFirstInRow; //! entry of 1st pixel of each non-empty row in the mPix2Encode + std::vector mFirstInRow; //! entry of 1st pixel of each non-empty row in the mPix2Encode std::vector mPix2Encode; //! pool of links: fired pixel + index of the next one in the row // ClassDefNV(AlpideCoder, 1); From b7e4371cd7d5e7d920b2b2e03a8ecf56ede89471 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 9 Jul 2020 17:19:10 +0200 Subject: [PATCH 0063/1751] fixes for large clusters treatment --- Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index 0b4406d7f17dd..584bdd011428e 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -266,13 +266,10 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus do { // Select a subset of pixels fitting the reduced bounding box std::vector pixbuf; + auto colMax = colMin + colSpan, rowMax = r + rsp; for (const auto& pix : pixArrBuff) { - unsigned short ir = pix.getRowDirect() - rowMin, ic = pix.getCol() - colMin; - if (ir < 0) - continue; - if (ic < 0) - continue; - if (ir < rsp && ic < colSpan) { + if (pix.getRowDirect() >= r && pix.getRowDirect() < rowMax && + pix.getCol() >= colMin && pix.getCol() < colMax) { pixbuf.push_back(pix); } } From b5ea3518bd8838c7d512ab959dfed5b2b5d9c5c2 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 9 Jul 2020 21:42:00 +0200 Subject: [PATCH 0064/1751] Ensure QED interacton orbit does not exceed hadronic one --- Steer/DigitizerWorkflow/src/SimReaderSpec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx b/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx index 05a85d5424793..1ba8811c23703 100644 --- a/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx +++ b/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx @@ -160,10 +160,10 @@ DataProcessorSpec getSimReaderSpec(SubspecRange range, const std::vector qedinteractionrecords; o2::InteractionTimeRecord t; LOG(INFO) << "GENERATING COL TIMES"; - do { - t = qedInteractionSampler.generateCollisionTime(); + t = qedInteractionSampler.generateCollisionTime(); + while ((t = qedInteractionSampler.generateCollisionTime()) < last) { qedinteractionrecords.push_back(t); - } while (t < last); + } LOG(INFO) << "DONE GENERATING COL TIMES"; // get digitization context and add QED stuff From 63fd13ef39f29dd69c24a8a83c757b27dbc9c7e9 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 9 Jul 2020 21:42:34 +0200 Subject: [PATCH 0065/1751] Ensure sampling starts exactly from FirstIR --- Steer/include/Steer/InteractionSampler.h | 2 +- Steer/src/InteractionSampler.cxx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Steer/include/Steer/InteractionSampler.h b/Steer/include/Steer/InteractionSampler.h index deffa584251be..f4ebf6727b283 100644 --- a/Steer/include/Steer/InteractionSampler.h +++ b/Steer/include/Steer/InteractionSampler.h @@ -78,7 +78,7 @@ class InteractionSampler o2::BunchFilling mBCFilling; ///< patter of active BCs std::vector mTimeInBC; ///< interaction times within single BC std::vector mInteractingBCs; // vector of interacting BCs - size_t mCurrBCIdx = 0; ///< counter for current interacting bunch + int mCurrBCIdx = 0; ///< counter for current interacting bunch static constexpr float DefIntRate = 50e3; ///< default interaction rate diff --git a/Steer/src/InteractionSampler.cxx b/Steer/src/InteractionSampler.cxx index 53184678892df..b9238d1801320 100644 --- a/Steer/src/InteractionSampler.cxx +++ b/Steer/src/InteractionSampler.cxx @@ -74,7 +74,8 @@ void InteractionSampler::init() while (mCurrBCIdx < mInteractingBCs.size() && mInteractingBCs[mCurrBCIdx] < mIR.bc) { mCurrBCIdx++; } - mCurrBCIdx = mCurrBCIdx == 0 ? mInteractingBCs.size() : mCurrBCIdx--; + // set the "current BC" right in front of the 1st BC to generate. There will be a jump by at least 1 during generation + mCurrBCIdx--; } //_________________________________________________ From d0e2568da4227593e95824b7dc22931227e71803 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Thu, 9 Jul 2020 20:54:51 +0200 Subject: [PATCH 0066/1751] [EMCAL-658] Get glob cell ID from col/row in EMCAL Add function getting the abs. cell ID and the cell indices from the global row and col in the EMCAL/ DCAL space. --- .../EMCAL/base/include/EMCALBase/Geometry.h | 18 +++++++++ Detectors/EMCAL/base/src/Geometry.cxx | 40 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h index 79ed70438ee3b..a7c0b64012519 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h @@ -348,6 +348,24 @@ class Geometry /// \return Row number in global numbering scheme int GlobalRow(int cellID) const; + /// \brief Get the absolute cell ID from global position in the EMCAL + /// \param row Global row ID + /// \param col Global col ID + /// \return absolute cell ID + int GetCellAbsIDFromGlobalRowCol(int row, int col) const; + + /// \brief Get the posision (row, col) of a global row-col position + /// \param row Global row ID + /// \param col Global col ID + /// \return Position in supermodule: [0 - supermodule ID, 1 - row in supermodule - col in supermodule] + std::tuple GetPositionInSupermoduleFromGlobalRowCol(int col, int row) const; + + /// \brief Get the cell indices from global position in the EMCAL + /// \param row Global row ID + /// \param col Global col ID + /// \return Cell indices [0 - supermodule, 1 - module, 2 - phi in module, 3 - eta in module] + std::tuple GetCellIndexFromGlobalRowCol(int row, int col) const; + /// \brief Given a global eta/phi point check if it belongs to a supermodule covered region. /// \param eta pseudorapidity location /// \param phi azimutal location diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index cf35978498437..79c2d36e7ec66 100644 --- a/Detectors/EMCAL/base/src/Geometry.cxx +++ b/Detectors/EMCAL/base/src/Geometry.cxx @@ -776,6 +776,46 @@ std::tuple Geometry::GlobalRowColFromIndex(int cellID) const return std::make_tuple(row, col); } +std::tuple Geometry::GetPositionInSupermoduleFromGlobalRowCol(int row, int col) const +{ + int side = col > GetNEta() / 2 ? 1 : 0, + colSM = col % (GetNEta() / 2); + int sector = 0, + rowSM = row; + for (int isec = 0; isec < GetNPhiSuperModule(); isec++) { + auto smtype = GetSMType(isec * 2); + auto nphism = (smtype == EMCAL_THIRD || smtype == DCAL_EXT) ? GetNPhi() / 3 : GetNPhi(); + if (rowSM < nphism) { + sector = isec; + break; + } + rowSM -= nphism; + } + int supermodule = sector * 2 + side; + if (supermodule == 13 || supermodule == 15 || supermodule == 17) { + // DCal odd SMs need shift of the col. index as global col index includes PHOS hole + col += 16; + } + return std::make_tuple(supermodule, rowSM, colSM); +} + +int Geometry::GetCellAbsIDFromGlobalRowCol(int row, int col) const +{ + auto [supermodule, rowSM, colSM] = GetPositionInSupermoduleFromGlobalRowCol(row, col); + return GetAbsCellIdFromCellIndexes(supermodule, rowSM, colSM); +} + +std::tuple Geometry::GetCellIndexFromGlobalRowCol(int row, int col) const +{ + auto [supermodule, rowSM, colSM] = GetPositionInSupermoduleFromGlobalRowCol(row, col); + auto indexmod = GetModuleIndexesFromCellIndexesInSModule(supermodule, rowSM, colSM); + + Int_t colInModule = colSM % mNETAdiv, + rowInMOdule = rowSM % mNPHIdiv; + colInModule = mNETAdiv - 1 - colInModule; + return std::make_tuple(supermodule, std::get<2>(indexmod), rowInMOdule, colInModule); +} + int Geometry::GlobalCol(int cellID) const { return std::get<1>(GlobalRowColFromIndex(cellID)); From a2116409da237e3a1f3f8a5fa0a5d47fecab014d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 10 Jul 2020 11:11:01 +0200 Subject: [PATCH 0067/1751] DPL: introduce forking hooks (#3963) There is now three new hooks: * Before forking. * After forking on the parent path. * After forking on the child path. This will allow having services which exploit Copy-On-Write when we get rid of the execvp. We also use these hooks to set the number of available threads for libuv. --- .../Core/include/Framework/CommonServices.h | 7 +- .../Core/include/Framework/ServiceSpec.h | 26 +++++++ Framework/Core/src/CommonMessageBackends.cxx | 12 ++++ Framework/Core/src/CommonServices.cxx | 72 ++++++++++++++++++- Framework/Core/src/runDataProcessing.cxx | 38 +++++++--- 5 files changed, 143 insertions(+), 12 deletions(-) diff --git a/Framework/Core/include/Framework/CommonServices.h b/Framework/Core/include/Framework/CommonServices.h index f4aedfe6828c0..c22535d565130 100644 --- a/Framework/Core/include/Framework/CommonServices.h +++ b/Framework/Core/include/Framework/CommonServices.h @@ -16,6 +16,10 @@ namespace o2::framework { +struct ThreadPool { + int poolSize; +}; + /// A few ServiceSpecs for services we know about and that / are needed by /// everyone. struct CommonServices { @@ -55,8 +59,9 @@ struct CommonServices { static ServiceSpec timesliceIndex(); static ServiceSpec dataRelayer(); static ServiceSpec tracingSpec(); + static ServiceSpec threadPool(int numWorkers); - static std::vector defaultServices(); + static std::vector defaultServices(int numWorkers = 0); static std::vector requiredServices(); }; diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index 2a7029a0a03bd..b95a60e8fc99d 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -14,6 +14,8 @@ #include #include +#include + namespace fair::mq { struct ProgOptions; @@ -51,6 +53,19 @@ using ServiceProcessingCallback = std::function /// A callback which is executed before the end of stream loop. using ServiceEOSCallback = std::function; +/// Callback executed before the forking of a given device in the driver +/// Notice the forking can happen multiple times. It's responsibility of +/// the service to track how many times it happens and act accordingly. +using ServicePreFork = std::function; + +/// Callback executed after forking a given device in the driver, +/// but before doing exec / starting the device. +using ServicePostForkChild = std::function; + +/// Callback executed after forking a given device in the driver, +/// but before doing exec / starting the device. +using ServicePostForkParent = std::function; + /// The kind of service we are asking for enum struct ServiceKind { /// A Service which is not thread safe, therefore all accesses to it must be mutexed. @@ -82,6 +97,17 @@ struct ServiceSpec { ServiceEOSCallback preEOS = nullptr; /// Callback executed after the end of stream callback of the user happended ServiceEOSCallback postEOS = nullptr; + /// Callback executed before the forking of a given device in the driver + /// Notice the forking can happen multiple times. It's responsibility of + /// the service to track how many times it happens and act accordingly. + ServicePreFork preFork = nullptr; + /// Callback executed after forking a given device in the driver, + /// but before doing exec / starting the device. + ServicePostForkChild postForkChild = nullptr; + /// Callback executed after forking a given device in the driver, + /// but before doing exec / starting the device. + ServicePostForkParent postForkParent = nullptr; + /// Kind of service being specified. ServiceKind kind; }; diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index b4870e5993f68..b5b4a354a712b 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -83,6 +83,9 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() CommonMessageBackendsHelpers::sendCallback(), CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -115,6 +118,9 @@ o2::framework::ServiceSpec CommonMessageBackends::fairMQBackendSpec() CommonMessageBackendsHelpers::sendCallback(), CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -127,6 +133,9 @@ o2::framework::ServiceSpec CommonMessageBackends::stringBackendSpec() CommonMessageBackendsHelpers::sendCallback(), CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -139,6 +148,9 @@ o2::framework::ServiceSpec CommonMessageBackends::rawBufferBackendSpec() CommonMessageBackendsHelpers::sendCallback(), CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index b925677063a01..eebdf7d8ee973 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -27,6 +27,8 @@ #include +#include + using AliceO2::InfoLogger::InfoLogger; using AliceO2::InfoLogger::InfoLoggerContext; using o2::configuration::ConfigurationFactory; @@ -48,6 +50,9 @@ o2::framework::ServiceSpec CommonServices::monitoringSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -60,6 +65,9 @@ o2::framework::ServiceSpec CommonServices::infologgerContextSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -140,6 +148,9 @@ o2::framework::ServiceSpec CommonServices::infologgerSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -160,6 +171,9 @@ o2::framework::ServiceSpec CommonServices::configurationSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -176,6 +190,9 @@ o2::framework::ServiceSpec CommonServices::controlSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -189,6 +206,9 @@ o2::framework::ServiceSpec CommonServices::rootFileSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -206,6 +226,9 @@ o2::framework::ServiceSpec CommonServices::parallelSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -219,6 +242,9 @@ o2::framework::ServiceSpec CommonServices::timesliceIndex() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -232,6 +258,9 @@ o2::framework::ServiceSpec CommonServices::callbacksSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -252,6 +281,9 @@ o2::framework::ServiceSpec CommonServices::dataRelayer() nullptr, nullptr, nullptr, + nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -279,12 +311,44 @@ o2::framework::ServiceSpec CommonServices::tracingSpec() }, nullptr, nullptr, + nullptr, + nullptr, + nullptr, + ServiceKind::Serial}; +} + +// FIXME: allow configuring the default number of threads per device +// This should probably be done by overriding the preFork +// callback and using the boost program options there to +// get the default number of threads. +o2::framework::ServiceSpec CommonServices::threadPool(int numWorkers) +{ + return ServiceSpec{ + "threadpool", + [](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { + return ServiceHandle{TypeIdHelpers::uniqueId(), new ThreadPool()}; + }, + [numWorkers](InitContext&, void* service) -> void* { + ThreadPool* t = reinterpret_cast(service); + t->poolSize = numWorkers; + return service; + }, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + [numWorkers](ServiceRegistry& service) -> void { + auto numWorkersS = std::to_string(numWorkers); + setenv("UV_THREADPOOL_SIZE", numWorkersS.c_str(), 0); + }, + nullptr, ServiceKind::Serial}; } -std::vector CommonServices::defaultServices() +std::vector CommonServices::defaultServices(int numThreads) { - return { + std::vector specs{ timesliceIndex(), monitoringSpec(), infologgerContextSpec(), @@ -299,6 +363,10 @@ std::vector CommonServices::defaultServices() CommonMessageBackends::arrowBackendSpec(), CommonMessageBackends::stringBackendSpec(), CommonMessageBackends::rawBufferBackendSpec()}; + if (numThreads) { + specs.push_back(threadPool(numThreads)); + } + return specs; } } // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 2d6c07abd29f4..d6355a38af226 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -360,6 +360,8 @@ void spawnDevice(std::string const& forwardedStdin, DeviceControl& control, DeviceExecution& execution, std::vector& deviceInfos, + ServiceRegistry& serviceRegistry, + boost::program_options::variables_map& varmap, uv_loop_t* loop, std::vector handles) { @@ -376,6 +378,11 @@ void spawnDevice(std::string const& forwardedStdin, // Not how the first port is actually used to broadcast clients. driverInfo.tracyPort++; + for (auto& service : spec.services) { + if (service.preFork != nullptr) { + service.preFork(serviceRegistry, varmap); + } + } // If we have a framework id, it means we have already been respawned // and that we are in a child. If not, we need to fork and re-exec, adding // the framework-id as one of the options. @@ -402,12 +409,22 @@ void spawnDevice(std::string const& forwardedStdin, dup2(childstderr[1], STDERR_FILENO); auto portS = std::to_string(driverInfo.tracyPort); setenv("TRACY_PORT", portS.c_str(), 1); + for (auto& service : spec.services) { + if (service.postForkChild != nullptr) { + service.postForkChild(serviceRegistry); + } + } execvp(execution.args[0], execution.args.data()); } - // This is the parent. We close the write end of // the child pipe and and keep track of the fd so // that we can later select on it. + for (auto& service : spec.services) { + if (service.postForkParent != nullptr) { + service.postForkParent(serviceRegistry); + } + } + struct sigaction sa_handle_int; sa_handle_int.sa_handler = handle_sigint; sigemptyset(&sa_handle_int.sa_mask); @@ -633,8 +650,7 @@ bool processSigChild(DeviceInfos& infos) return hasError; } - -int doChild(int argc, char** argv, const o2::framework::DeviceSpec& spec, TerminationPolicy errorPolicy, +int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::framework::DeviceSpec& spec, TerminationPolicy errorPolicy, uv_loop_t* loop) { fair::Logger::SetConsoleColor(false); @@ -655,10 +671,6 @@ int doChild(int argc, char** argv, const o2::framework::DeviceSpec& spec, Termin r.fConfig.AddToCmdLineOptions(optsDesc, true); }); - // We initialise this in the driver, because different drivers might have - // different versions of the service - ServiceRegistry serviceRegistry; - // This is to control lifetime. All these services get destroyed // when the runner is done. std::unique_ptr simpleRawDeviceService; @@ -757,6 +769,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, DriverControl& driverControl, DriverInfo& driverInfo, std::vector& metricsInfos, + boost::program_options::variables_map& varmap, std::string frameworkId) { DeviceSpecs deviceSpecs; @@ -813,6 +826,10 @@ int runStateMachine(DataProcessorSpecs const& workflow, uv_timer_t force_step_timer; uv_timer_init(loop, &force_step_timer); + // We initialise this in the driver, because different drivers might have + // different versions of the service + ServiceRegistry serviceRegistry; + while (true) { // If control forced some transition on us, we push it to the queue. if (driverControl.forcedTransitions.empty() == false) { @@ -931,7 +948,9 @@ int runStateMachine(DataProcessorSpecs const& workflow, } for (auto& spec : deviceSpecs) { if (spec.id == frameworkId) { - return doChild(driverInfo.argc, driverInfo.argv, spec, driverInfo.errorPolicy, loop); + return doChild(driverInfo.argc, driverInfo.argv, + serviceRegistry, spec, + driverInfo.errorPolicy, loop); } } { @@ -991,7 +1010,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, spawnDevice(forwardedStdin.str(), deviceSpecs[di], driverInfo, controls[di], deviceExecutions[di], infos, - loop, pollHandles); + serviceRegistry, varmap, loop, pollHandles); } } assert(infos.empty() == false); @@ -1657,6 +1676,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, driverControl, driverInfo, gDeviceMetricsInfos, + varmap, frameworkId); } From d2a029372373a36d0740a57ce16a521705882ac7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 10 Jul 2020 16:23:41 +0200 Subject: [PATCH 0068/1751] DPL: make service resource monitoring play well with new services (#3966) --- Framework/Core/src/runDataProcessing.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index d6355a38af226..d897a56968976 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -690,9 +690,6 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f serviceRegistry.registerService(simpleRawDeviceService.get()); serviceRegistry.registerService(&spec); - if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(spec.resourceMonitoringInterval)) { - serviceRegistry.get().enableProcessMonitoring(spec.resourceMonitoringInterval); - } // The decltype stuff is to be able to compile with both new and old // FairMQ API (one which uses a shared_ptr, the other one a unique_ptr. decltype(r.fDevice) device; @@ -710,6 +707,9 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f serviceRegistry.registerService(handle.hash, handle.instance); dynamic_cast(r.fDevice.get())->bindService(service, handle.instance); } + if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(spec.resourceMonitoringInterval)) { + serviceRegistry.get().enableProcessMonitoring(spec.resourceMonitoringInterval); + } }; runner.AddHook(afterConfigParsingCallback); From ad446f292f669d942f07ec7b23fb68a5b400f07a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 10 Jul 2020 16:35:52 +0200 Subject: [PATCH 0069/1751] Update sim_challenge.sh Increasing size of shared memory segment. Hotfix for the weekend run. Otherwise we can't finish TPC digitization for 100PbPb. --- prodtests/sim_challenge.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 1b990a457378b..65a288563ae2a 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -196,7 +196,7 @@ fi if [ "$dodigi" == "1" ]; then echo "Running digitization for $intRate kHz interaction rate" intRate=$((1000*(intRate))); - taskwrapper digi.log o2-sim-digitizer-workflow $gloOpt --interactionRate $intRate $tpcLanes + taskwrapper digi.log o2-sim-digitizer-workflow $gloOpt --shm-segment-size 10000000000 --interactionRate $intRate $tpcLanes echo "Return status of digitization: $?" # existing checks #root -b -q O2/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C+ From 644127c81b7870a7603e114a15f10399a266bd79 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sat, 11 Jul 2020 08:29:38 +0200 Subject: [PATCH 0070/1751] DPL: Option to globally disable IPC (shared memory) in a workflow (#3968) This let's the user decide to disable IPC/shm backend optimization, which might be sometimes needed: a) for testing purposes and benchmarks b) when there is not enough shared memory on a system c) on AFS where IPC does not work well --- Framework/Core/src/DeviceSpecHelpers.cxx | 34 ++++++++++++++---------- Framework/Core/src/DeviceSpecHelpers.h | 4 ++- Framework/Core/src/runDataProcessing.cxx | 2 ++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 5831c672d2944..112bcbf132a59 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -653,6 +653,7 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf std::vector& devices, ResourceManager& resourceManager, std::string const& uniqueWorkflowId, + bool optimizeTopology, unsigned short resourcesMonitoringInterval) { @@ -749,23 +750,28 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf // Optimize the topology when two devices are // running on the same node. - for (auto& connection : connections) { - auto& device1 = devices[findDeviceIndex(connection.consumer, connection.timeIndex)]; - auto& device2 = devices[findDeviceIndex(connection.producer, connection.producerTimeIndex)]; - // No need to do anything if they are not on the same host - if (device1.resource.hostname != device2.resource.hostname) { - continue; - } - for (auto& input : device1.inputChannels) { - for (auto& output : device2.outputChannels) { - if (input.hostname == output.hostname && input.port == output.port) { - input.protocol = ChannelProtocol::IPC; - output.protocol = ChannelProtocol::IPC; - input.hostname += uniqueWorkflowId; - output.hostname += uniqueWorkflowId; + if (optimizeTopology) { + LOG(INFO) << "Optimizing topology for IPC communication"; + for (auto& connection : connections) { + auto& device1 = devices[findDeviceIndex(connection.consumer, connection.timeIndex)]; + auto& device2 = devices[findDeviceIndex(connection.producer, connection.producerTimeIndex)]; + // No need to do anything if they are not on the same host + if (device1.resource.hostname != device2.resource.hostname) { + continue; + } + for (auto& input : device1.inputChannels) { + for (auto& output : device2.outputChannels) { + if (input.hostname == output.hostname && input.port == output.port) { + input.protocol = ChannelProtocol::IPC; + output.protocol = ChannelProtocol::IPC; + input.hostname += uniqueWorkflowId; + output.hostname += uniqueWorkflowId; + } } } } + } else { + LOG(INFO) << "Not optimizing topology for IPC communication"; } } diff --git a/Framework/Core/src/DeviceSpecHelpers.h b/Framework/Core/src/DeviceSpecHelpers.h index b9a92d2f173a1..a37c70471e12f 100644 --- a/Framework/Core/src/DeviceSpecHelpers.h +++ b/Framework/Core/src/DeviceSpecHelpers.h @@ -49,6 +49,7 @@ struct DeviceSpecHelpers { std::vector& devices, ResourceManager& resourceManager, std::string const& uniqueWorkflowId, + bool optimizeTopology = false, unsigned short resourcesMonitoringInterval = 0); static void dataProcessorSpecs2DeviceSpecs( @@ -58,11 +59,12 @@ struct DeviceSpecHelpers { std::vector& devices, ResourceManager& resourceManager, std::string const& uniqueWorkflowId, + bool optimizeTopology = false, unsigned short resourcesMonitoringInterval = 0) { std::vector dispatchPolicies = DispatchPolicy::createDefaultPolicies(); dataProcessorSpecs2DeviceSpecs(workflow, channelPolicies, completionPolicies, - dispatchPolicies, devices, resourceManager, uniqueWorkflowId, resourcesMonitoringInterval); + dispatchPolicies, devices, resourceManager, uniqueWorkflowId, optimizeTopology, resourcesMonitoringInterval); } /// Helper to provide the channel configuration string for an input channel diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index d897a56968976..26a1bebe02067 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -930,6 +930,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, deviceSpecs, *resourceManager, driverInfo.uniqueWorkflowId, + !varmap["no-IPC"].as(), driverInfo.resourcesMonitoringInterval); // This should expand nodes so that we can build a consistent DAG. @@ -1448,6 +1449,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, ("dump-workflow,dump", bpo::value()->zero_tokens()->default_value(false), "dump workflow as JSON") // // ("dump-workflow-file", bpo::value()->default_value("-"), "file to which do the dump") // // ("run", bpo::value()->zero_tokens()->default_value(false), "run workflow merged so far") // // + ("no-IPC", bpo::value()->zero_tokens()->default_value(false), "disable IPC topology optimization") // // ("o2-control,o2", bpo::value()->zero_tokens()->default_value(false), "create O2 Control configuration") // ("resources-monitoring", bpo::value()->default_value(0), "enable cpu/memory monitoring for provided interval in seconds"); // // some of the options must be forwarded by default to the device From b38c7331b3e7ee3d925a0b0862e4d8db8f19064b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 11 Jul 2020 08:44:11 +0200 Subject: [PATCH 0071/1751] DPL: fix locks macros when Tracy not available (#3970) --- Framework/Foundation/include/Framework/Tracing.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Framework/Foundation/include/Framework/Tracing.h b/Framework/Foundation/include/Framework/Tracing.h index 3fa311c7a70d1..e1ec3d57c52a2 100644 --- a/Framework/Foundation/include/Framework/Tracing.h +++ b/Framework/Foundation/include/Framework/Tracing.h @@ -38,6 +38,8 @@ #define TracyAppInfo(...) \ while (false) { \ } +#define TracyLockableN(T, V, N) T V +#define LockableBase(T) T #endif #endif // O2_FRAMEWORK_TRACING_H_ From 8af7175c9d8ca50b9e110b66d4cd831e4af8bd22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sat, 11 Jul 2020 20:07:14 +0200 Subject: [PATCH 0072/1751] Add possibility to remove old CCDB objects (#3964) - Other minor improvements --- Analysis/Core/src/InsertNewRunToTimestamp.cxx | 4 ++ .../Scripts/insert_Run2_run_to_timestamps.py | 40 +++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Analysis/Core/src/InsertNewRunToTimestamp.cxx b/Analysis/Core/src/InsertNewRunToTimestamp.cxx index 7a061c8abecc6..3428592ea3821 100644 --- a/Analysis/Core/src/InsertNewRunToTimestamp.cxx +++ b/Analysis/Core/src/InsertNewRunToTimestamp.cxx @@ -32,6 +32,7 @@ bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv "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."); @@ -84,6 +85,9 @@ int main(int argc, char* argv[]) } 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()); diff --git a/Analysis/Scripts/insert_Run2_run_to_timestamps.py b/Analysis/Scripts/insert_Run2_run_to_timestamps.py index 198104f0b1745..c7bcab2d1c739 100755 --- a/Analysis/Scripts/insert_Run2_run_to_timestamps.py +++ b/Analysis/Scripts/insert_Run2_run_to_timestamps.py @@ -71,12 +71,16 @@ def __eq__(self, other): return self.run == other.run -def main(input_file_name, extra_args, input_in_seconds=0, verbose=0): +def main(input_file_name, extra_args, + input_in_seconds=False, delete_previous=True, verbose=False, + url="http://ccdb-test.cern.ch:8080", path="Analysis/Core/RunToTimestamp"): """ 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: @@ -84,7 +88,9 @@ def main(input_file_name, extra_args, input_in_seconds=0, verbose=0): run_list = [] for line_no, i in enumerate(infile): i = i.strip() - if verbose == 2: + if len(i) <= 1: + continue + if verbose >= 2: print(f"Line number {line_no}: {i}") i = i.split() run = i[1] @@ -105,19 +111,43 @@ def main(input_file_name, extra_args, input_in_seconds=0, verbose=0): 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}" + cmd += f" --url {url}" + cmd += f" --path {path}" + if delete_previous: + cmd += f" --delete_previous 1" cmd += f" {extra_args}" - cmd += " -p Analysis/Core/RunToTimestamp" if i == run_list[-1]: # Printing the status of the converter as a last step cmd += " -v 1" if verbose: print(cmd) - subprocess.run(cmd.split()) + 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__": @@ -130,6 +160,8 @@ def main(input_file_name, extra_args, input_in_seconds=0, verbose=0): 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() From 9bd557601a27874cbca8fb8d64ccbf07cf080324 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 11 Jul 2020 21:32:02 +0200 Subject: [PATCH 0073/1751] DPL: extract helper functions (#3973) --- Framework/Core/src/DataProcessingDevice.cxx | 58 ++++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 27e76c9b4b197..d5243a58e64c7 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -669,6 +669,38 @@ bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info return true; } +namespace +{ +auto calculateInputRecordLatency(InputRecord const& record, uint64_t currentTime) -> DataProcessingStats::InputLatency +{ + DataProcessingStats::InputLatency result{static_cast(-1), 0}; + + for (auto& item : record) { + auto* header = o2::header::get(item.header); + if (header == nullptr) { + continue; + } + int partLatency = currentTime - header->creation; + result.minLatency = std::min(result.minLatency, partLatency); + result.maxLatency = std::max(result.maxLatency, partLatency); + } + return result; +}; + +auto calculateTotalInputRecordSize(InputRecord const& record) -> int +{ + size_t totalInputSize = 0; + for (auto& item : record) { + auto* header = o2::header::get(item.header); + if (header == nullptr) { + continue; + } + totalInputSize += header->payloadSize; + } + return totalInputSize; +}; +} // namespace + bool DataProcessingDevice::tryDispatchComputation(std::vector& completed) { ZoneScopedN("DataProcessingDevice::tryDispatchComputation"); @@ -869,32 +901,6 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector DataProcessingStats::InputLatency { - DataProcessingStats::InputLatency result{static_cast(-1), 0}; - - for (auto& item : record) { - auto* header = o2::header::get(item.header); - if (header == nullptr) { - continue; - } - int partLatency = currentTime - header->creation; - result.minLatency = std::min(result.minLatency, partLatency); - result.maxLatency = std::max(result.maxLatency, partLatency); - } - return result; - }; - - auto calculateTotalInputRecordSize = [](InputRecord const& record) -> int { - size_t totalInputSize = 0; - for (auto& item : record) { - auto* header = o2::header::get(item.header); - if (header == nullptr) { - continue; - } - totalInputSize += header->payloadSize; - } - return totalInputSize; - }; auto switchState = [& control = mServiceRegistry.get(), &state = mState.streaming](StreamingState newState) { From 1b9e39b2041f8f53d3baeb7ace8dd0f5550071b1 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 10 Jul 2020 22:17:14 +0200 Subject: [PATCH 0074/1751] HBFUtils getter for 1st IR of TF from arbitrary IR within TF Also, limit TF and HBF IDs to uint32_t. --- Detectors/Raw/include/DetectorsRaw/HBFUtils.h | 7 +++++-- Detectors/Raw/src/HBFUtils.cxx | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Detectors/Raw/include/DetectorsRaw/HBFUtils.h b/Detectors/Raw/include/DetectorsRaw/HBFUtils.h index a1ca2fa2e5aa0..6bfc6c097509d 100644 --- a/Detectors/Raw/include/DetectorsRaw/HBFUtils.h +++ b/Detectors/Raw/include/DetectorsRaw/HBFUtils.h @@ -54,10 +54,10 @@ struct HBFUtils : public o2::conf::ConfigurableParamHelper { IR getIRTF(uint32_t tf) const { return getIRHBF(tf * nHBFPerTF); } ///< get HBF ID corresponding to this IR - int64_t getHBF(const IR& rec) const; + uint32_t getHBF(const IR& rec) const; ///< get TF ID corresponding to this IR - int64_t getTF(const IR& rec) const { return getHBF(rec) / nHBFPerTF; } + uint32_t getTF(const IR& rec) const { return getHBF(rec) / nHBFPerTF; } ///< get TF and HB (within TF) for this IR std::pair getTFandHBinTF(const IR& rec) const @@ -66,6 +66,9 @@ struct HBFUtils : public o2::conf::ConfigurableParamHelper { return std::pair(hbf / nHBFPerTF, hbf % nHBFPerTF); } + ///< get 1st IR of the TF corresponding to provided interaction record + IR getFirstIRofTF(const IR& rec) const { return getIRTF(getTF(rec)); } + ///< get TF and HB (abs) for this IR std::pair getTFandHB(const IR& rec) const { diff --git a/Detectors/Raw/src/HBFUtils.cxx b/Detectors/Raw/src/HBFUtils.cxx index d9c5fc008bcf3..e9f8978451570 100644 --- a/Detectors/Raw/src/HBFUtils.cxx +++ b/Detectors/Raw/src/HBFUtils.cxx @@ -20,7 +20,7 @@ using namespace o2::raw; O2ParamImpl(o2::raw::HBFUtils); //_________________________________________________ -int64_t HBFUtils::getHBF(const IR& rec) const +uint32_t HBFUtils::getHBF(const IR& rec) const { ///< get HBF ID corresponding to this IR auto diff = rec.differenceInBC(getFirstIR()); From d2fd6022a9d51f73e0526b358949a973a76236df Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 10 Jul 2020 22:20:42 +0200 Subject: [PATCH 0075/1751] Use DataHeader.firstTForbit in ITS/TPC matcher (+hack) As the framework at the moment does not propagate the firstTForbit, we actually extract the 1st orbit using HBFUtil. --- .../include/GlobalTracking/MatchTPCITS.h | 2 +- .../src/TPCITSMatchingSpec.cxx | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index e60f0d2e037fd..0eabf19c2b8a6 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -533,7 +533,7 @@ class MatchTPCITS bool mFieldON = true; ///< flag for field ON/OFF bool mMCTruthON = false; ///< flag availability of MC truth - o2::InteractionRecord mStartIR; ///< IR corresponding to the start of the TF + o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF ///========== Parameters to be set externally, e.g. from CCDB ==================== const Params* mParams = nullptr; diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index 1a88857858b89..d1ae7eb3a433d 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -33,6 +33,10 @@ #include "ITStracking/IOUtils.h" #include "DetectorsCommonDataFormats/NameConf.h" #include "DataFormatsParameters/GRPObject.h" +#include "Headers/DataHeader.h" + +// RSTODO to remove once the framework will start propagating the header.firstTForbit +#include "DetectorsRaw/HBFUtils.h" using namespace o2::framework; using MCLabelContainer = o2::dataformats::MCTruthContainer; @@ -241,6 +245,14 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) mMatching.setFITInfoInp(fitInfo); } + const auto* dh = o2::header::get(pc.inputs().get("trackITSROF").header); + mMatching.setStartIR({0, dh->firstTForbit}); + + //RSTODO: below is a hack, to remove once the framework will start propagating the header.firstTForbit + if (tracksITSROF.size()) { + mMatching.setStartIR(o2::raw::HBFUtils::Instance().getFirstIRofTF(tracksITSROF[0].getBCData())); + } + mMatching.run(); pc.outputs().snapshot(Output{"GLO", "TPCITS", 0, Lifetime::Timeframe}, mMatching.getMatchedTracks()); From 519b646a2efc9c4a0e5850bed2fc40056473d40f Mon Sep 17 00:00:00 2001 From: Kavaldrin <37471854+Kavaldrin@users.noreply.github.com> Date: Sat, 11 Jul 2020 23:47:04 +0200 Subject: [PATCH 0076/1751] Resources monitoring: fix incorrect check for num of available metrics (#3975) Co-authored-by: Kavaldrin --- Framework/Core/src/ResourcesMonitoringHelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/ResourcesMonitoringHelper.h b/Framework/Core/src/ResourcesMonitoringHelper.h index 5b784be195a3d..b0fae70b5318e 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.h +++ b/Framework/Core/src/ResourcesMonitoringHelper.h @@ -51,7 +51,7 @@ boost::property_tree::ptree ResourcesMonitoringHelper::fillNodeWithValue(const D const T& metricsStorage, size_t labelIndex, size_t storageIndex) { - unsigned int loopRange = std::min(deviceMetrics.metrics[labelIndex].filledMetrics, metricsStorage.size()); + unsigned int loopRange = std::min(deviceMetrics.metrics[labelIndex].filledMetrics, metricsStorage[storageIndex].size()); boost::property_tree::ptree metricNode; for (unsigned int idx = 0; idx < loopRange; ++idx) { From 650eafb6fab69753000123a9ded8b25ab0fdd4b6 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 12 Jul 2020 00:34:39 +0200 Subject: [PATCH 0077/1751] DPL: move TracyClient include at the top (#3974) Doing so avoid issues with including Tracy.hpp in the .h (to debug yet to come mutexes). --- Framework/Core/src/DataProcessingDevice.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index d5243a58e64c7..a381ebfed3c25 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -7,6 +7,10 @@ // 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. +#ifdef DPL_ENABLE_TRACING +#define TRACY_ENABLE +#include +#endif #include "Framework/DataProcessingDevice.h" #include "Framework/ChannelMatching.h" #include "Framework/ControlService.h" @@ -32,10 +36,6 @@ #include "ScopedExit.h" -#ifdef DPL_ENABLE_TRACING -#define TRACY_ENABLE -#include -#endif #include #include From c6e7ac2b17c757e76d03fa28ac057d9ca7112451 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 12 Jul 2020 02:10:40 +0200 Subject: [PATCH 0078/1751] DPL: remove unneeded field for backoff factor (#3977) --- Framework/Core/include/Framework/DataProcessingDevice.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index 42de40d501aca..bfe8e3ab641d2 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -87,7 +87,6 @@ class DataProcessingDevice : public FairMQDevice uint64_t mLastMetricFlushedTimestamp = 0; /// The timestamp of the last time we actually flushed metrics uint64_t mBeginIterationTimestamp = 0; /// The timestamp of when the current ConditionalRun was started DataProcessingStats mStats; /// Stats about the actual data processing. - int mCurrentBackoff = 0; /// The current exponential backoff value. std::vector mPendingRegionInfos; /// A list of the region infos not yet notified. enum TerminationPolicy mErrorPolicy = TerminationPolicy::WAIT; /// What to do when an error arises bool mWasActive = false; /// Whether or not the device was active at last iteration. From 8ba3d7ae2248e14adf74e59f849d85c7dfbf4594 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 12 Jul 2020 09:27:37 +0200 Subject: [PATCH 0079/1751] DPL: use a proper context for socket polling (#3976) --- Framework/Core/src/DataProcessingDevice.cxx | 25 ++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index a381ebfed3c25..81c02d44e5409 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -123,12 +123,21 @@ DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegist } } +// Context for polling +struct PollerContext { + char const* name; + uv_loop_t* loop; + DataProcessingDevice* device; + int fd; +}; + void on_socket_polled(uv_poll_t* poller, int status, int events) { + PollerContext* context = (PollerContext*)poller->data; switch (events) { case UV_READABLE: { ZoneScopedN("socket readable event"); - LOG(debug) << "socket polled UV_READABLE: " << (char*)poller->data; + LOG(debug) << "socket polled UV_READABLE: " << context->name; } break; case UV_WRITABLE: { ZoneScopedN("socket writeable"); @@ -293,7 +302,12 @@ void DataProcessingDevice::InitTask() } LOG(debug) << "Polling socket for " << x.second[0].GetName(); // FIXME: leak - poller->data = strdup(x.first.c_str()); + PollerContext* pCtx = (PollerContext*)malloc(sizeof(PollerContext)); + pCtx->name = strdup(x.first.c_str()); + pCtx->loop = mState.loop; + pCtx->device = this; + pCtx->fd = zmq_fd; + poller->data = pCtx; uv_poll_init(mState.loop, poller, zmq_fd); uv_poll_start(poller, UV_READABLE | UV_DISCONNECT, &on_socket_polled); mState.activeInputPollers.push_back(poller); @@ -320,7 +334,12 @@ void DataProcessingDevice::InitTask() } LOG(debug) << "Polling socket for " << x.second[0].GetName(); // FIXME: leak - poller->data = strdup(x.first.c_str()); + PollerContext* pCtx = (PollerContext*)malloc(sizeof(PollerContext)); + pCtx->name = strdup(x.first.c_str()); + pCtx->loop = mState.loop; + pCtx->device = this; + pCtx->fd = zmq_fd; + poller->data = pCtx; uv_poll_init(mState.loop, poller, zmq_fd); uv_poll_start(poller, UV_WRITABLE, &on_socket_polled); mState.activeOutputPollers.push_back(poller); From 659652578db692a45d249edbbb5e061cb2b1e1f0 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 12 Jul 2020 22:20:45 +0200 Subject: [PATCH 0080/1751] GPU: Fix broken optimization (obviosly not always power of 2...) --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index cadc3ca115fe2..20ea6ed55edca 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -461,7 +461,7 @@ GPUd() void GPUTPCGMMerger::UnpackSliceGlobal(int nBlocks, int nThreads, int iBl } else if (itr > nLocalTracks) { sliceTr = sliceTr->GetNextTrack(); } - int localId = TrackIds[(sliceTr->LocalTrackId() >> 24) * mNMaxSingleSliceTracks | (sliceTr->LocalTrackId() & 0xFFFFFF)]; + int localId = TrackIds[(sliceTr->LocalTrackId() >> 24) * mNMaxSingleSliceTracks + (sliceTr->LocalTrackId() & 0xFFFFFF)]; if (localId == -1) { continue; } @@ -484,7 +484,7 @@ GPUd() void GPUTPCGMMerger::UnpackResetIds(int nBlocks, int nThreads, int iBlock const GPUTPCTracker& trk = GetConstantMem()->tpcTrackers[iSlice]; unsigned int nLocalTracks = Param().rec.mergerReadFromTrackerDirectly ? trk.CommonMemory()->nLocalTracks : mkSlices[iSlice]->NLocalTracks(); for (unsigned int i = iBlock * nThreads + iThread; i < nLocalTracks; i += nBlocks * nThreads) { - TrackIds[iSlice * mNMaxSingleSliceTracks | i] = -1; + TrackIds[iSlice * mNMaxSingleSliceTracks + i] = -1; } } @@ -530,7 +530,7 @@ GPUd() void GPUTPCGMMerger::RefitSliceTracks(int nBlocks, int nThreads, int iBlo track.SetGlobalTrackId(0, -1); track.SetGlobalTrackId(1, -1); unsigned int myTrack = CAMath::AtomicAdd(&mMemory->nUnpackedTracks, 1u); - TrackIds[iSlice * mNMaxSingleSliceTracks | sliceTr->LocalTrackId()] = myTrack; + TrackIds[iSlice * mNMaxSingleSliceTracks + sliceTr->LocalTrackId()] = myTrack; mSliceTrackInfos[myTrack] = track; } if (!Param().rec.mergerReadFromTrackerDirectly) { From 4bf888053fc2acc4107d332ff5ecc115f3abd33c Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Mon, 6 Jul 2020 12:29:22 +0200 Subject: [PATCH 0081/1751] TPCClusterFinder: Apply inlining and loop unrolling in more places. --- .../TPCClusterFinder/GPUTPCCFDeconvolution.cxx | 4 ++-- .../TPCClusterFinder/GPUTPCCFDeconvolution.h | 4 ++-- .../TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx | 11 +++++++---- .../TPCClusterFinder/GPUTPCCFNoiseSuppression.h | 8 ++++---- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx index 95dde7bc6f430..a68e37e6d8d31 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx @@ -114,7 +114,7 @@ GPUdii() void GPUTPCCFDeconvolution::countPeaksImpl(int nBlocks, int nThreads, i chargeMap[pos] = p; } -GPUd() char GPUTPCCFDeconvolution::countPeaksScratchpadInner( +GPUdi() char GPUTPCCFDeconvolution::countPeaksScratchpadInner( ushort ll, const uchar* isPeak, uchar* aboveThreshold) @@ -130,7 +130,7 @@ GPUd() char GPUTPCCFDeconvolution::countPeaksScratchpadInner( return peaks; } -GPUd() char GPUTPCCFDeconvolution::countPeaksScratchpadOuter( +GPUdi() char GPUTPCCFDeconvolution::countPeaksScratchpadOuter( ushort ll, uchar aboveThreshold, const uchar* isPeak) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h index 4a8c88dd56600..53fd0b0273369 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h @@ -55,8 +55,8 @@ class GPUTPCCFDeconvolution : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUd() char countPeaksScratchpadInner(ushort, const uchar*, uchar*); - static GPUd() char countPeaksScratchpadOuter(ushort, uchar, const uchar*); + static GPUdi() char countPeaksScratchpadInner(ushort, const uchar*, uchar*); + static GPUdi() char countPeaksScratchpadOuter(ushort, uchar, const uchar*); }; } // namespace gpu diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx index ff3b0c2ee9e9b..137556be76751 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx @@ -91,7 +91,7 @@ GPUd() void GPUTPCCFNoiseSuppression::updatePeaksImpl(int nBlocks, int nThreads, // So we can just set the bit and avoid rereading the charge } -GPUd() void GPUTPCCFNoiseSuppression::checkForMinima( +GPUdi() void GPUTPCCFNoiseSuppression::checkForMinima( float q, float epsilon, PackedCharge other, @@ -108,7 +108,7 @@ GPUd() void GPUTPCCFNoiseSuppression::checkForMinima( *bigger |= (lq << pos); } -GPUd() void GPUTPCCFNoiseSuppression::findMinimaScratchPad( +GPUdi() void GPUTPCCFNoiseSuppression::findMinimaScratchPad( const PackedCharge* buf, const ushort ll, const int N, @@ -118,6 +118,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaScratchPad( ulong* minimas, ulong* bigger) { + GPUCA_UNROLL(U(), U()) for (int i = 0; i < N; i++, pos++) { PackedCharge other = buf[N * ll + i]; @@ -125,13 +126,14 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaScratchPad( } } -GPUd() void GPUTPCCFNoiseSuppression::findPeaksScratchPad( +GPUdi() void GPUTPCCFNoiseSuppression::findPeaksScratchPad( const uchar* buf, const ushort ll, const int N, int pos, ulong* peaks) { + GPUCA_UNROLL(U(), U()) for (int i = 0; i < N; i++, pos++) { ulong p = CfUtils::isPeak(buf[N * ll + i]); @@ -139,12 +141,13 @@ GPUd() void GPUTPCCFNoiseSuppression::findPeaksScratchPad( } } -GPUd() bool GPUTPCCFNoiseSuppression::keepPeak( +GPUdi() bool GPUTPCCFNoiseSuppression::keepPeak( ulong minima, ulong peaks) { bool keepMe = true; + GPUCA_UNROLL(U(), U()) for (int i = 0; i < NOISE_SUPPRESSION_NEIGHBOR_NUM; i++) { bool otherPeak = (peaks & (ulong(1) << i)); bool minimaBetween = (minima & CfConsts::NoiseSuppressionMinima[i]); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h index ac1d0a1b9ff12..274218c5749fc 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h @@ -63,13 +63,13 @@ class GPUTPCCFNoiseSuppression : public GPUKernelTemplate static GPUd() void updatePeaksImpl(int, int, int, int, const ChargePos*, const uchar*, const uint, Array2D&); - static GPUd() void checkForMinima(float, float, PackedCharge, int, ulong*, ulong*); + static GPUdi() void checkForMinima(float, float, PackedCharge, int, ulong*, ulong*); - static GPUd() void findMinimaScratchPad(const PackedCharge*, const ushort, const int, int, const float, const float, ulong*, ulong*); + static GPUdi() void findMinimaScratchPad(const PackedCharge*, const ushort, const int, int, const float, const float, ulong*, ulong*); - static GPUd() void findPeaksScratchPad(const uchar*, const ushort, const int, int, ulong*); + static GPUdi() void findPeaksScratchPad(const uchar*, const ushort, const int, int, ulong*); - static GPUd() bool keepPeak(ulong, ulong); + static GPUdi() bool keepPeak(ulong, ulong); static GPUd() void findMinimaAndPeaksScratchpad(const Array2D&, const Array2D&, float, const ChargePos&, ChargePos*, PackedCharge*, ulong*, ulong*, ulong*); }; From e7f5bb0b2bb320922b188ddf0366baf08c1da73c Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Wed, 8 Jul 2020 12:45:55 +0200 Subject: [PATCH 0082/1751] TPCClusterFinder: Simplify function names. --- .../TPCClusterFinder/GPUTPCCFClusterizer.cxx | 14 ++++++------ .../TPCClusterFinder/GPUTPCCFClusterizer.h | 6 ++--- .../GPUTPCCFDeconvolution.cxx | 20 ++++++++--------- .../TPCClusterFinder/GPUTPCCFDeconvolution.h | 7 +++--- .../GPUTPCCFNoiseSuppression.cxx | 22 +++++++++---------- .../GPUTPCCFNoiseSuppression.h | 6 ++--- .../TPCClusterFinder/GPUTPCCFPeakFinder.cxx | 4 ++-- .../TPCClusterFinder/GPUTPCCFPeakFinder.h | 6 ++--- 8 files changed, 43 insertions(+), 42 deletions(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx index 10f3bc1ed43a7..31ff57058a77a 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx @@ -56,7 +56,7 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads ClusterAccumulator pc; CPU_ONLY(labelAcc->collect(pos, charge)); - buildClusterScratchPad( + buildCluster( chargeMap, pos, smem.posBcast, @@ -94,7 +94,7 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads CPU_ONLY(labelAcc->commit(pos.row(), rowIndex, maxClusterPerRow)); } -GPUdii() void GPUTPCCFClusterizer::updateClusterScratchpadInner( +GPUdii() void GPUTPCCFClusterizer::updateClusterInner( ushort lid, ushort N, const PackedCharge* buf, @@ -124,7 +124,7 @@ GPUdii() void GPUTPCCFClusterizer::updateClusterScratchpadInner( GPUbarrier(); } -GPUdii() void GPUTPCCFClusterizer::updateClusterScratchpadOuter( +GPUdii() void GPUTPCCFClusterizer::updateClusterOuter( ushort lid, ushort N, ushort M, @@ -148,7 +148,7 @@ GPUdii() void GPUTPCCFClusterizer::updateClusterScratchpadOuter( } } -GPUdii() void GPUTPCCFClusterizer::buildClusterScratchPad( +GPUdii() void GPUTPCCFClusterizer::buildCluster( const Array2D& chargeMap, ChargePos pos, ChargePos* posBcast, @@ -172,7 +172,7 @@ GPUdii() void GPUTPCCFClusterizer::buildClusterScratchPad( CfConsts::InnerNeighbors, posBcast, buf); - updateClusterScratchpadInner( + updateClusterInner( ll, 8, buf, @@ -200,7 +200,7 @@ GPUdii() void GPUTPCCFClusterizer::buildClusterScratchPad( buf); if (inGroup1) { - updateClusterScratchpadOuter( + updateClusterOuter( llhalf, 16, 16, @@ -224,7 +224,7 @@ GPUdii() void GPUTPCCFClusterizer::buildClusterScratchPad( innerAboveThreshold + wgSizeHalf, buf); if (!inGroup1) { - updateClusterScratchpadOuter( + updateClusterOuter( llhalf, 16, 16, diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h index 94db2c61fa80a..5add50ee1a904 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h @@ -64,11 +64,11 @@ class GPUTPCCFClusterizer : public GPUKernelTemplate static GPUd() void computeClustersImpl(int, int, int, int, const CfFragment&, GPUSharedMemory&, const Array2D&, const ChargePos*, MCLabelAccumulator*, uint, uint, uint*, tpc::ClusterNative*); private: - static GPUd() void updateClusterScratchpadInner(ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*, uchar*); + static GPUd() void updateClusterInner(ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*, uchar*); - static GPUd() void updateClusterScratchpadOuter(ushort, ushort, ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*); + static GPUd() void updateClusterOuter(ushort, ushort, ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*); - static GPUd() void buildClusterScratchPad(const Array2D&, ChargePos, ChargePos*, PackedCharge*, uchar*, ClusterAccumulator*, MCLabelAccumulator*); + static GPUd() void buildCluster(const Array2D&, ChargePos, ChargePos*, PackedCharge*, uchar*, ClusterAccumulator*, MCLabelAccumulator*); static GPUd() uint sortIntoBuckets(const tpc::ClusterNative&, uint, uint, uint*, tpc::ClusterNative*); }; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx index a68e37e6d8d31..dcbc92d3248d6 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx @@ -25,14 +25,14 @@ GPUdii() void GPUTPCCFDeconvolution::Thread<0>(int nBlocks, int nThreads, int iB { Array2D chargeMap(reinterpret_cast(clusterer.mPchargeMap)); Array2D isPeakMap(clusterer.mPpeakMap); - GPUTPCCFDeconvolution::countPeaksImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, isPeakMap, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions); + GPUTPCCFDeconvolution::deconvolutionImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, isPeakMap, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions); } -GPUdii() void GPUTPCCFDeconvolution::countPeaksImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, - const Array2D& peakMap, - Array2D& chargeMap, - const ChargePos* positions, - const uint digitnum) +GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, + const Array2D& peakMap, + Array2D& chargeMap, + const ChargePos* positions, + const uint digitnum) { SizeT idx = get_global_id(0); @@ -69,7 +69,7 @@ GPUdii() void GPUTPCCFDeconvolution::countPeaksImpl(int nBlocks, int nThreads, i uchar aboveThreshold = 0; if (partId < in3x3) { - peakCount = countPeaksScratchpadInner(partId, smem.buf, &aboveThreshold); + peakCount = countPeaksInner(partId, smem.buf, &aboveThreshold); } ushort in5x5 = 0; @@ -94,7 +94,7 @@ GPUdii() void GPUTPCCFDeconvolution::countPeaksImpl(int nBlocks, int nThreads, i smem.buf); if (partId < in5x5) { - peakCount = countPeaksScratchpadOuter(partId, aboveThreshold, smem.buf); + peakCount = countPeaksOuter(partId, aboveThreshold, smem.buf); peakCount *= -1; } @@ -114,7 +114,7 @@ GPUdii() void GPUTPCCFDeconvolution::countPeaksImpl(int nBlocks, int nThreads, i chargeMap[pos] = p; } -GPUdi() char GPUTPCCFDeconvolution::countPeaksScratchpadInner( +GPUdi() char GPUTPCCFDeconvolution::countPeaksInner( ushort ll, const uchar* isPeak, uchar* aboveThreshold) @@ -130,7 +130,7 @@ GPUdi() char GPUTPCCFDeconvolution::countPeaksScratchpadInner( return peaks; } -GPUdi() char GPUTPCCFDeconvolution::countPeaksScratchpadOuter( +GPUdi() char GPUTPCCFDeconvolution::countPeaksOuter( ushort ll, uchar aboveThreshold, const uchar* isPeak) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h index 53fd0b0273369..bc95cddba526e 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h @@ -36,7 +36,6 @@ class GPUTPCCFDeconvolution : public GPUKernelTemplate uchar buf[SCRATCH_PAD_WORK_GROUP_SIZE * SCRATCH_PAD_COUNT_N]; }; - static GPUd() void countPeaksImpl(int, int, int, int, GPUSharedMemory&, const Array2D&, Array2D&, const ChargePos*, const uint); #ifdef HAVE_O2HEADERS typedef GPUTPCClusterFinder processorType; @@ -55,8 +54,10 @@ class GPUTPCCFDeconvolution : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUdi() char countPeaksScratchpadInner(ushort, const uchar*, uchar*); - static GPUdi() char countPeaksScratchpadOuter(ushort, uchar, const uchar*); + static GPUd() void deconvolutionImpl(int, int, int, int, GPUSharedMemory&, const Array2D&, Array2D&, const ChargePos*, const uint); + + static GPUdi() char countPeaksInner(ushort, const uchar*, uchar*); + static GPUdi() char countPeaksOuter(ushort, uchar, const uchar*); }; } // namespace gpu diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx index 137556be76751..41ed6a79e1e7c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx @@ -48,7 +48,7 @@ GPUdii() void GPUTPCCFNoiseSuppression::noiseSuppressionImpl(int nBlocks, int nT Charge charge = chargeMap[pos].unpack(); ulong minimas, bigger, peaksAround; - findMinimaAndPeaksScratchpad( + findMinimaAndPeaks( chargeMap, peakMap, charge, @@ -108,7 +108,7 @@ GPUdi() void GPUTPCCFNoiseSuppression::checkForMinima( *bigger |= (lq << pos); } -GPUdi() void GPUTPCCFNoiseSuppression::findMinimaScratchPad( +GPUdi() void GPUTPCCFNoiseSuppression::findMinima( const PackedCharge* buf, const ushort ll, const int N, @@ -126,7 +126,7 @@ GPUdi() void GPUTPCCFNoiseSuppression::findMinimaScratchPad( } } -GPUdi() void GPUTPCCFNoiseSuppression::findPeaksScratchPad( +GPUdi() void GPUTPCCFNoiseSuppression::findPeaks( const uchar* buf, const ushort ll, const int N, @@ -158,7 +158,7 @@ GPUdi() bool GPUTPCCFNoiseSuppression::keepPeak( return keepMe; } -GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( +GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( const Array2D& chargeMap, const Array2D& peakMap, float q, @@ -198,7 +198,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( posBcast, buf); - findMinimaScratchPad( + findMinima( buf, ll, 2, @@ -220,7 +220,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( buf); if (inGroup1) { - findMinimaScratchPad( + findMinima( buf, llhalf, 16, @@ -243,7 +243,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( buf); if (inGroup1) { - findMinimaScratchPad( + findMinima( buf, llhalf, 16, @@ -267,7 +267,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( buf); if (!inGroup1) { - findMinimaScratchPad( + findMinima( buf, llhalf, 16, @@ -290,7 +290,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( buf); if (!inGroup1) { - findMinimaScratchPad( + findMinima( buf, llhalf, 16, @@ -319,7 +319,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( posBcast, bufp); - findPeaksScratchPad( + findPeaks( bufp, ll, 16, @@ -337,7 +337,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaksScratchpad( posBcast, bufp); - findPeaksScratchPad( + findPeaks( bufp, ll, 16, diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h index 274218c5749fc..028363f007b07 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h @@ -65,13 +65,13 @@ class GPUTPCCFNoiseSuppression : public GPUKernelTemplate static GPUdi() void checkForMinima(float, float, PackedCharge, int, ulong*, ulong*); - static GPUdi() void findMinimaScratchPad(const PackedCharge*, const ushort, const int, int, const float, const float, ulong*, ulong*); + static GPUdi() void findMinima(const PackedCharge*, const ushort, const int, int, const float, const float, ulong*, ulong*); - static GPUdi() void findPeaksScratchPad(const uchar*, const ushort, const int, int, ulong*); + static GPUdi() void findPeaks(const uchar*, const ushort, const int, int, ulong*); static GPUdi() bool keepPeak(ulong, ulong); - static GPUd() void findMinimaAndPeaksScratchpad(const Array2D&, const Array2D&, float, const ChargePos&, ChargePos*, PackedCharge*, ulong*, ulong*, ulong*); + static GPUd() void findMinimaAndPeaks(const Array2D&, const Array2D&, float, const ChargePos&, ChargePos*, PackedCharge*, ulong*, ulong*, ulong*); }; } // namespace gpu diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx index d6484147c502f..328e901576d41 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx @@ -28,7 +28,7 @@ GPUdii() void GPUTPCCFPeakFinder::Thread<0>(int nBlocks, int nThreads, int iBloc findPeaksImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions, clusterer.mPisPeak, isPeakMap); } -GPUdii() bool GPUTPCCFPeakFinder::isPeakScratchPad( +GPUdii() bool GPUTPCCFPeakFinder::isPeak( GPUSharedMemory& smem, Charge q, const ChargePos& pos, @@ -103,7 +103,7 @@ GPUd() void GPUTPCCFPeakFinder::findPeaksImpl(int nBlocks, int nThreads, int iBl Charge charge = pos.valid() ? chargeMap[pos].unpack() : Charge(0); uchar peak; - peak = isPeakScratchPad(smem, charge, pos, SCRATCH_PAD_SEARCH_N, chargeMap, smem.posBcast, smem.buf); + peak = isPeak(smem, charge, pos, SCRATCH_PAD_SEARCH_N, chargeMap, smem.posBcast, smem.buf); // Exit early if dummy. See comment above. bool iamDummy = (idx >= digitnum); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h index 8fcded952f924..646e8c221ed69 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h @@ -37,8 +37,6 @@ class GPUTPCCFPeakFinder : public GPUKernelTemplate PackedCharge buf[SCRATCH_PAD_WORK_GROUP_SIZE * SCRATCH_PAD_SEARCH_N]; }; - static GPUd() void findPeaksImpl(int, int, int, int, GPUSharedMemory&, const Array2D&, const ChargePos*, tpccf::SizeT, uchar*, Array2D&); - #ifdef HAVE_O2HEADERS typedef GPUTPCClusterFinder processorType; GPUhdi() static processorType* Processor(GPUConstantMem& processors) @@ -56,7 +54,9 @@ class GPUTPCCFPeakFinder : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUd() bool isPeakScratchPad(GPUSharedMemory&, tpccf::Charge, const ChargePos&, ushort, const Array2D&, ChargePos*, PackedCharge*); + static GPUd() void findPeaksImpl(int, int, int, int, GPUSharedMemory&, const Array2D&, const ChargePos*, tpccf::SizeT, uchar*, Array2D&); + + static GPUd() bool isPeak(GPUSharedMemory&, tpccf::Charge, const ChargePos&, ushort, const Array2D&, ChargePos*, PackedCharge*); }; } // namespace gpu From 58012a54d37c1e7fcec5b1285e13e6f6351f82d3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 13 Jul 2020 10:13:17 +0200 Subject: [PATCH 0083/1751] DPL: refactor stats accumulation (#3979) --- Framework/Core/src/DataProcessingDevice.cxx | 41 +++++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 81c02d44e5409..a701f47aa8ae7 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -931,6 +931,28 @@ bool DataProcessingDevice::tryDispatchComputation(std::vectorrelayerState.resize(std::max(cacheId + 1, stats->relayerState.size()), 0); + stats->relayerState[cacheId] = state; + } + uint64_t tEnd = uv_hrtime(); + stats->lastElapsedTimeMs = tEnd - tStart; + stats->lastTotalProcessedSize = calculateTotalInputRecordSize(record); + stats->lastLatency = calculateInputRecordLatency(record, tStart); + }; + + auto preUpdateStats = [stats = &mStats](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { + for (size_t ai = 0; ai != record.size(); ai++) { + auto cacheId = action.slot.index * record.size() + ai; + auto state = record.isValid(ai) ? 2 : 0; + stats->relayerState.resize(std::max(cacheId + 1, stats->relayerState.size()), 0); + stats->relayerState[cacheId] = state; + } + }; + for (auto action : getReadyActions()) { if (action.op == CompletionPolicy::CompletionOp::Wait) { continue; @@ -951,13 +973,9 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector Date: Sun, 12 Jul 2020 22:36:28 +0200 Subject: [PATCH 0084/1751] GPU: Update lastRow/Slice only when needed --- GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 995c32e7d41a8..4b2eea14dc9e0 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -116,8 +116,6 @@ GPUdii() void GPUTPCCompressionKernels::ThreadnStoredAttachedClusters, nClustersStored); From f15389a1d3c1277afce6a30acdd0e4423da2880d Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 13 Jul 2020 09:29:41 +0200 Subject: [PATCH 0085/1751] TPC: Fix reading of TPC raw pages with interim empty pages --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 1801bf7485a1c..60504a15d0a66 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -518,6 +518,8 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector Date: Mon, 13 Jul 2020 15:28:55 +0200 Subject: [PATCH 0086/1751] [EMCAL-655] Porting of the fast gamma2 raw fitter (#3585) --- .../include/DataFormatsEMCAL/Constants.h | 4 +- Detectors/EMCAL/reconstruction/CMakeLists.txt | 2 + .../EMCALReconstruction/CaloRawFitter.h | 1 - .../EMCALReconstruction/CaloRawFitterGamma2.h | 78 ++++++++ .../reconstruction/macros/RawFitterTESTs.C | 4 +- .../src/CaloRawFitterGamma2.cxx | 174 ++++++++++++++++++ .../EMCALWorkflow/RawToCellConverterSpec.h | 3 +- .../workflow/src/RawToCellConverterSpec.cxx | 1 + 8 files changed, 262 insertions(+), 5 deletions(-) create mode 100755 Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h create mode 100755 Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h index 1666568bd2dc0..9bae3c01c08d7 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h @@ -101,8 +101,8 @@ constexpr Int_t EMCAL_MAXTIMEBINS = 15; ///< Maximum number of time bins fo enum FitAlgorithm { Standard = 0, ///< Standard raw fitter - NeuralNet = 1, ///< Neural net raw fitter - FastFit = 2, ///< Fast raw fitter (Martin) + Gamma2 = 1, ///< Gamma2 raw fitter + NeuralNet = 2, ///< Neural net raw fitter NONE = 3 }; diff --git a/Detectors/EMCAL/reconstruction/CMakeLists.txt b/Detectors/EMCAL/reconstruction/CMakeLists.txt index eb94d2bdef60f..c52c191fdae11 100644 --- a/Detectors/EMCAL/reconstruction/CMakeLists.txt +++ b/Detectors/EMCAL/reconstruction/CMakeLists.txt @@ -21,6 +21,7 @@ o2_add_library(EMCALReconstruction src/CaloFitResults.cxx src/CaloRawFitter.cxx src/CaloRawFitterStandard.cxx + src/CaloRawFitterGamma2.cxx src/ClusterizerParameters.cxx src/Clusterizer.cxx src/ClusterizerTask.cxx @@ -43,6 +44,7 @@ o2_target_root_dictionary( include/EMCALReconstruction/CaloFitResults.h include/EMCALReconstruction/CaloRawFitter.h include/EMCALReconstruction/CaloRawFitterStandard.h + include/EMCALReconstruction/CaloRawFitterGamma2.h include/EMCALReconstruction/ClusterizerParameters.h include/EMCALReconstruction/Clusterizer.h include/EMCALReconstruction/ClusterizerTask.h diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h index d1ee85cd52e1e..e01806428a522 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h @@ -54,7 +54,6 @@ class CaloRawFitter /// \return pedestal, /// \return first time bin, /// \return last time bin, - /// \return ampitude cut std::tuple preFitEvaluateSamples(const std::vector& bunchvector, std::optional altrocfg1, std::optional altrocfg2, int acut); diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h new file mode 100755 index 0000000000000..e6a31d953d182 --- /dev/null +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h @@ -0,0 +1,78 @@ +// 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 __CALORAWFITTERGAMMA2_H__ +#define __CALORAWFITTERGAMMA2_H__ + +#include +#include +#include +#include +#include "EMCALReconstruction/CaloFitResults.h" +#include "DataFormatsEMCAL/Constants.h" +#include "EMCALReconstruction/Bunch.h" +#include "EMCALReconstruction/CaloRawFitter.h" + +namespace o2 +{ + +namespace emcal +{ + +/// \class CaloRawFitterGamma2 +/// \brief Raw data fitting: Gamma-2 function +/// \ingroup EMCALreconstruction +/// \author Martin Poghosyan , ORNL. +/// \since May 13th, 2020 +/// +/// Evaluation of amplitude and peak position using gamma-2 function. +/// Derivatives calculated analytically. +/// Newton's method used for solving the set of non-linear equations. +/// Ported from class AliCaloRawAnalyzerGamma2 from AliRoot + +class CaloRawFitterGamma2 : public CaloRawFitter +{ + + public: + /// \brief Constructor + CaloRawFitterGamma2(); + + /// \brief Destructor + ~CaloRawFitterGamma2() = default; + + void setNiterationsMax(int n) { mNiterationsMax = n; } + int getNiterations() { return mNiter; } + int getNiterationsMax() { return mNiterationsMax; } + + /// \brief Evaluation Amplitude and TOF + /// return Container with the fit results (amp, time, chi2, ...) + virtual CaloFitResults evaluate(const std::vector& bunchvector, + std::optional altrocfg1, + std::optional altrocfg2); + + private: + int mNiter = 0; ///< number of iteraions + int mNiterationsMax = 15; ///< max number of iteraions + + /// \brief Fits the raw signal time distribution + /// \return chi2, fit status. + std::tuple doFit_1peak(int firstTimeBin, int nSamples, float& ampl, float& time); + + /// \brief Fits the raw signal time distribution + /// \return the fit parameters: amplitude, time. + std::tuple doParabolaFit(int x) const; + + ClassDefNV(CaloRawFitterGamma2, 1); +}; // End of CaloRawFitterGamma2 + +} // namespace emcal + +} // namespace o2 +#endif diff --git a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C index 9eef11f2edd04..25695221d817b 100644 --- a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C +++ b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C @@ -19,6 +19,7 @@ #include "EMCALReconstruction/Bunch.h" #include "EMCALReconstruction/CaloRawFitterStandard.h" #include "EMCALReconstruction/AltroDecoder.h" +#include "EMCALReconstruction/CaloRawFitterGamma2.h" //#include "EMCALReconstruction/RawHeaderStream.h" #endif @@ -40,7 +41,8 @@ void RawFitterTESTs() o2::emcal::RawReaderFile rawreader(inputDir + "emcal.raw"); // define the standard raw fitter - o2::emcal::CaloRawFitterStandard RawFitter; + //o2::emcal::CaloRawFitterStandard RawFitter; + o2::emcal::CaloRawFitterGamma2 RawFitter; RawFitter.setAmpCut(NoiseThreshold); RawFitter.setL1Phase(0.); diff --git a/Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx b/Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx new file mode 100755 index 0000000000000..c587f461bd1a5 --- /dev/null +++ b/Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx @@ -0,0 +1,174 @@ +// 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 CaloRawFitterGamma2.cxx +/// \author Martin Poghosyan (Martin.Poghosyan@cern.ch) + +#include "FairLogger.h" +#include + +// ROOT sytem +#include "TMath.h" + +#include "EMCALReconstruction/Bunch.h" +#include "EMCALReconstruction/CaloFitResults.h" +#include "DataFormatsEMCAL/Constants.h" + +#include "EMCALReconstruction/CaloRawFitterGamma2.h" + +using namespace o2::emcal; + +CaloRawFitterGamma2::CaloRawFitterGamma2() : CaloRawFitter("Chi Square ( Gamma2 )", "Gamma2") +{ + mAlgo = FitAlgorithm::Gamma2; +} + +CaloFitResults CaloRawFitterGamma2::evaluate(const std::vector& bunchlist, + std::optional altrocfg1, std::optional altrocfg2) +{ + float time = 0; + float amp = 0; + float chi2 = 0; + int ndf = 0; + bool fitDone = false; + + auto [nsamples, bunchIndex, ampEstimate, + maxADC, timeEstimate, pedEstimate, first, last] = preFitEvaluateSamples(bunchlist, altrocfg1, altrocfg2, mAmpCut); + + if (ampEstimate >= mAmpCut) { + time = timeEstimate; + int timebinOffset = bunchlist.at(bunchIndex).getStartTime() - (bunchlist.at(bunchIndex).getBunchLength() - 1); + amp = ampEstimate; + + if (nsamples > 2 && maxADC < constants::OVERFLOWCUT) { + std::tie(amp, time) = doParabolaFit(timeEstimate - 1); + mNiter = 0; + std::tie(chi2, fitDone) = doFit_1peak(first, nsamples, amp, time); + + if (!fitDone) { + amp = ampEstimate; + time = timeEstimate; + chi2 = 1.e9; + } + + time += timebinOffset; + timeEstimate += timebinOffset; + ndf = nsamples - 2; + } + } + + if (fitDone) { + float ampAsymm = (amp - ampEstimate) / (amp + ampEstimate); + float timeDiff = time - timeEstimate; + + if ((TMath::Abs(ampAsymm) > 0.1) || (TMath::Abs(timeDiff) > 2)) { + amp = ampEstimate; + time = timeEstimate; + fitDone = false; + } + } + if (amp >= mAmpCut) { + if (!fitDone) { + std::default_random_engine generator; + std::uniform_real_distribution distribution(0.0, 1.0); + amp += (0.5 - distribution(generator)); + } + time = time * constants::EMCAL_TIMESAMPLE; + time -= mL1Phase; + + return CaloFitResults(maxADC, pedEstimate, mAlgo, amp, time, (int)time, chi2, ndf); + } + return CaloFitResults(-1, -1); +} + +std::tuple CaloRawFitterGamma2::doFit_1peak(int firstTimeBin, int nSamples, float& ampl, float& time) +{ + + float chi2(0.); + + // fit using gamma-2 function (ORDER =2 assumed) + if (nSamples < 3) + return std::make_tuple(chi2, false); + if (mNiter > mNiterationsMax) + return std::make_tuple(chi2, false); + + double D, dA, dt; + double c11 = 0; + double c12 = 0; + double c21 = 0; + double c22 = 0; + double d1 = 0; + double d2 = 0; + + mNiter++; + + for (int itbin = 0; itbin < nSamples; itbin++) { + + double ti = (itbin - time) / constants::TAU; + if ((ti + 1) < 0) + continue; + + double g_1i = (ti + 1) * TMath::Exp(-2 * ti); + double g_i = (ti + 1) * g_1i; + double gp_i = 2 * (g_i - g_1i); + double q1_i = (2 * ti + 1) * TMath::Exp(-2 * ti); + double q2_i = g_1i * g_1i * (4 * ti + 1); + c11 += (getReversed(itbin) - ampl * 2 * g_i) * gp_i; + c12 += g_i * g_i; + c21 += getReversed(itbin) * q1_i - ampl * q2_i; + c22 += g_i * g_1i; + double delta = ampl * g_i - getReversed(itbin); + d1 += delta * g_i; + d2 += delta * g_1i; + chi2 += (delta * delta); + } + + D = c11 * c22 - c12 * c21; + + if (TMath::Abs(D) < DBL_EPSILON) + return std::make_tuple(chi2, false); + + dt = (d1 * c22 - d2 * c12) / D * constants::TAU; + dA = (d1 * c21 - d2 * c11) / D; + + time += dt; + ampl += dA; + + bool res = true; + + if (TMath::Abs(dA) > 1 || TMath::Abs(dt) > 0.01) + std::tie(chi2, res) = doFit_1peak(firstTimeBin, nSamples, ampl, time); + + return std::make_tuple(chi2, res); +} + +std::tuple CaloRawFitterGamma2::doParabolaFit(int maxTimeBin) const +{ + float amp(0.), time(0.); + + // The equation of parabola is "y = a*x^2 + b*x + c" + // We have to find "a", "b", and "c" + + double a = (getReversed(maxTimeBin + 2) + getReversed(maxTimeBin) - 2. * getReversed(maxTimeBin + 1)) / 2.; + + if (TMath::Abs(a) < 1.e09) { + amp = getReversed(maxTimeBin + 1); + time = maxTimeBin + 1; + return std::make_tuple(amp, time); + } + + double b = getReversed(maxTimeBin + 1) - getReversed(maxTimeBin) - a * (2. * maxTimeBin + 1); + double c = getReversed(maxTimeBin) - b * maxTimeBin - a * maxTimeBin * maxTimeBin; + + time = -b / 2. / a; + amp = a * time * time + b * time + c; + + return std::make_tuple(amp, time); +} diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h index d6a2064acc8a3..06fbeffa3eb88 100644 --- a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h @@ -17,6 +17,7 @@ #include "EMCALBase/Mapper.h" #include "DataFormatsEMCAL/TriggerRecord.h" #include "EMCALReconstruction/CaloRawFitterStandard.h" +#include "EMCALReconstruction/CaloRawFitterGamma2.h" namespace o2 { @@ -62,7 +63,7 @@ class RawToCellConverterSpec : public framework::Task int mNoiseThreshold = 0; o2::emcal::Geometry* mGeometry = nullptr; ///! mMapper = nullptr; ///! mOutputCells; ///< Container with output cells std::vector mOutputTriggerRecords; ///< Container with output cells }; diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index 8c79ec49b4d15..ab15eb00b48bf 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -20,6 +20,7 @@ #include "EMCALReconstruction/CaloFitResults.h" #include "EMCALReconstruction/Bunch.h" #include "EMCALReconstruction/CaloRawFitterStandard.h" +#include "EMCALReconstruction/CaloRawFitterGamma2.h" #include "EMCALReconstruction/AltroDecoder.h" #include "CommonDataFormat/InteractionRecord.h" From 7cfca8c3697fefd5a1c950399aa9954db5fc6078 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 13 Jul 2020 10:37:13 +0200 Subject: [PATCH 0087/1751] RawReader will throw if input file path/specs are wrong --- Detectors/Raw/src/RawFileReader.cxx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index b8278cdaa98d1..4d225398f5a93 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -575,15 +575,16 @@ bool RawFileReader::addFile(const std::string& sname, o2::header::DataOrigin ori LOG(ERROR) << "Cannot add new files after initialization"; return false; } + bool ok = true; + mFileBuffers.push_back(std::make_unique(mBufferSize)); auto inFile = fopen(sname.c_str(), "rb"); - setvbuf(inFile, mFileBuffers.back().get(), _IOFBF, mBufferSize); - - bool ok = true; if (!inFile) { LOG(ERROR) << "Failed to open input file " << sname; - ok = false; + return false; } + setvbuf(inFile, mFileBuffers.back().get(), _IOFBF, mBufferSize); + if (origin == o2h::gDataOriginInvalid) { LOG(ERROR) << "Invalid data origin " << origin.as() << " for file " << sname; ok = false; @@ -594,8 +595,8 @@ bool RawFileReader::addFile(const std::string& sname, o2::header::DataOrigin ori } if (!ok) { fclose(inFile); + return false; } - mFileNames.push_back(sname); mFiles.push_back(inFile); mDataSpecs.emplace_back(origin, desc, t); @@ -722,7 +723,9 @@ void RawFileReader::loadFromInputsMap(const RawFileReader::InputsMap& inp) continue; } for (const auto& fnm : files) { // specific file names - addFile(fnm, std::get<0>(ordesc), std::get<1>(ordesc), std::get<2>(ordesc)); + if (!addFile(fnm, std::get<0>(ordesc), std::get<1>(ordesc), std::get<2>(ordesc))) { + throw std::runtime_error("wrong raw data file path or origin/description"); + } } } } From c3c7e930f92e0c375a8b104e0a046c8c927db09c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 13 Jul 2020 17:00:28 +0200 Subject: [PATCH 0088/1751] DPL: remove spurious printouts during topology creation (#3984) Otherwise breaks workflow merging --- Framework/Core/src/DeviceSpecHelpers.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 112bcbf132a59..7d1846c6f6fcd 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -751,7 +751,6 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf // Optimize the topology when two devices are // running on the same node. if (optimizeTopology) { - LOG(INFO) << "Optimizing topology for IPC communication"; for (auto& connection : connections) { auto& device1 = devices[findDeviceIndex(connection.consumer, connection.timeIndex)]; auto& device2 = devices[findDeviceIndex(connection.producer, connection.producerTimeIndex)]; @@ -770,8 +769,6 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf } } } - } else { - LOG(INFO) << "Not optimizing topology for IPC communication"; } } From dee4c46cdd85ac9b4ca738089c878638bedf6c42 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 13 Jul 2020 23:12:41 +0200 Subject: [PATCH 0089/1751] DPL: progress towards multithreading support (#3983) The actual data processing is now somewhat reentrant, as it's performed by static functions which act on a DataProcessingContext object. This will allow in the future to have different contexes for different threads making sure that each context either points to a thread safe component, or to a per thread copy. --- .../include/Framework/DataProcessingDevice.h | 66 +++- Framework/Core/src/DataProcessingDevice.cxx | 321 +++++++++++------- 2 files changed, 256 insertions(+), 131 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index bfe8e3ab641d2..fab35aec3bb73 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -22,6 +22,7 @@ #include "Framework/ForwardRoute.h" #include "Framework/TimingInfo.h" #include "Framework/TerminationPolicy.h" +#include "Framework/Tracing.h" #include #include @@ -34,6 +35,58 @@ namespace o2::framework struct InputChannelInfo; struct DeviceState; +/// Context associated to a given DataProcessor. +/// For the time being everything points to +/// members of the DataProcessingDevice and +/// we make sure that things are serialised by +/// locking a global lock. We can then have per +/// thread instances for what makes sense to have +/// per thread and relax the locks. +class DataProcessingDevice; + +struct DataProcessorContext { + // These are specific of a given context and therefore + // not shared by threads. + bool* wasActive = nullptr; + + // These are pointers to the one owned by the DataProcessingDevice + // but they are fully reentrant / thread safe and therefore can + // be accessed without a lock. + + // FIXME: move stuff here from the list below... ;-) + + // These are pointers to the one owned by the DataProcessingDevice + // and therefore require actual locking + DataProcessingDevice* device = nullptr; + DeviceSpec const* spec = nullptr; + DeviceState* state = nullptr; + + DataRelayer* relayer = nullptr; + DataProcessingStats* stats = nullptr; + ServiceRegistry* registry = nullptr; + uint64_t* lastSlowMetricSentTimestamp = nullptr; /// The timestamp of the last time we sent slow metrics + uint64_t* lastMetricFlushedTimestamp = nullptr; /// The timestamp of the last time we actually flushed metrics + uint64_t* beginIterationTimestamp = nullptr; /// The timestamp of when the current ConditionalRun was started + std::vector* completed = nullptr; + std::vector* expirationHandlers = nullptr; + TimingInfo* timingInfo = nullptr; + DataAllocator* allocator = nullptr; + AlgorithmSpec::ProcessCallback* statefulProcess = nullptr; + AlgorithmSpec::ProcessCallback* statelessProcess = nullptr; + AlgorithmSpec::ErrorCallback* error = nullptr; + /// Callbacks for services to be executed before every process method invokation + std::vector* preProcessingHandles = nullptr; + /// Callbacks for services to be executed after every process method invokation + std::vector* postProcessingHandles = nullptr; + /// Callbacks for services to be executed before every EOS user callback invokation + std::vector* preEOSHandles = nullptr; + /// Callbacks for services to be executed after every EOS user callback invokation + std::vector* postEOSHandles = nullptr; + /// Callback for the error handling + std::function* errorHandling = nullptr; + int* errorCount = nullptr; +}; + /// A device actually carrying out all the DPL /// Data Processing needs. class DataProcessingDevice : public FairMQDevice @@ -50,17 +103,22 @@ class DataProcessingDevice : public FairMQDevice void SetErrorPolicy(enum TerminationPolicy policy) { mErrorPolicy = policy; } void bindService(ServiceSpec const& spec, void* service); + // Processing functions are now renetrant + static void doRun(DataProcessorContext& context); + static void handleData(DataProcessorContext& context, FairMQParts&, InputChannelInfo&); + static bool tryDispatchComputation(DataProcessorContext& context, std::vector& completed); + std::vector mDataProcessorContexes; + protected: - bool doRun(); - bool handleData(FairMQParts&, InputChannelInfo&); - bool tryDispatchComputation(std::vector& completed); void error(const char* msg); + void fillContext(DataProcessorContext& context); private: /// The specification used to create the initial state of this device DeviceSpec const& mSpec; /// The current internal state of this device. DeviceState& mState; + AlgorithmSpec::InitCallback mInit; AlgorithmSpec::ProcessCallback mStatefulProcess; AlgorithmSpec::ProcessCallback mStatelessProcess; @@ -71,7 +129,9 @@ class DataProcessingDevice : public FairMQDevice TimingInfo mTimingInfo; DataAllocator mAllocator; DataRelayer* mRelayer = nullptr; + /// Expiration handler std::vector mExpirationHandlers; + /// Completed actions std::vector mCompleted; /// Callbacks for services to be executed before every process method invokation std::vector mPreProcessingHandles; diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index a701f47aa8ae7..671246ebf25f0 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -123,6 +123,24 @@ DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegist } } +// Callback to execute the processing. Notice how the data is +// is a vector of DataProcessorContext so that we can index the correct +// one with the thread id. For the moment we simply use the first one. +void run_callback(uv_work_t* handle) +{ + ZoneScopedN("run_callback"); + std::vector* contexes = (std::vector*)handle->data; + DataProcessorContext& context = contexes->at(0); + DataProcessingDevice::doRun(context); + // FrameMark; +} + +// Once the processing in a thread is done, this is executed on the main thread. +void run_completion(uv_work_t* handle, int status) +{ + ZoneScopedN("run_completion"); +} + // Context for polling struct PollerContext { char const* name; @@ -354,10 +372,51 @@ void DataProcessingDevice::InitTask() uv_timer_start(timer, idle_timer, 2000, 2000); mState.activeTimers.push_back(timer); } + // Whenever we InitTask, we consider as if the previous iteration // was successful, so that even if there is no timer or receiving // channel, we can still start an enumeration. mWasActive = true; + + // We should be ready to run here. Therefore we copy all the + // required parts in the DataProcessorContext. Eventually we should + // do so on a per thread basis, with fine grained locks. + mDataProcessorContexes.resize(1); + this->fillContext(mDataProcessorContexes.at(0)); +} + +void DataProcessingDevice::fillContext(DataProcessorContext& context) +{ + context.wasActive = &mWasActive; + + context.device = this; + context.spec = &mSpec; + context.state = &mState; + + context.relayer = mRelayer; + context.stats = &mStats; + context.registry = &mServiceRegistry; + context.lastSlowMetricSentTimestamp = &mLastSlowMetricSentTimestamp; /// The timestamp of the last time we sent slow metrics + context.lastMetricFlushedTimestamp = &mLastMetricFlushedTimestamp; /// The timestamp of the last time we actually flushed metrics + context.beginIterationTimestamp = &mBeginIterationTimestamp; /// The timestamp of when the current ConditionalRun was started + context.completed = &mCompleted; + context.expirationHandlers = &mExpirationHandlers; + context.timingInfo = &mTimingInfo; + context.allocator = &mAllocator; + context.statefulProcess = &mStatefulProcess; + context.statelessProcess = &mStatelessProcess; + context.error = &mError; + /// Callbacks for services to be executed before every process method invokation + context.preProcessingHandles = &mPreProcessingHandles; + /// Callbacks for services to be executed after every process method invokation + context.postProcessingHandles = &mPostProcessingHandles; + /// Callbacks for services to be executed before every EOS user callback invokation + context.preEOSHandles = &mPreEOSHandles; + /// Callbacks for services to be executed after every EOS user callback invokation + context.postEOSHandles = &mPostEOSHandles; + /// Callback for the error handling + context.errorHandling = &mErrorHandling; + context.errorCount = &mErrorCount; } void DataProcessingDevice::PreRun() @@ -377,31 +436,47 @@ bool DataProcessingDevice::ConditionalRun() // enumeration. if (mState.loop) { ZoneScopedN("uv idle"); + TracyPlot("past activity", (int64_t)mWasActive); uv_run(mState.loop, mWasActive ? UV_RUN_NOWAIT : UV_RUN_ONCE); } - auto result = DataProcessingDevice::doRun(); + + // Notify on the main thread the new region callbacks, making sure + // no callback is issued if there is something still processing. + if (mPendingRegionInfos.empty() == false) { + std::vector toBeNotified; + toBeNotified.swap(mPendingRegionInfos); // avoid any MT issue. + for (auto const& info : toBeNotified) { + mServiceRegistry.get()(CallbackService::Id::RegionInfoCallback, info); + } + } + // Synchronous execution of the callbacks. This will be moved in the + // moved in the on_socket_polled once we have threading in place. + uv_work_t handle; + handle.data = &mDataProcessorContexes; + run_callback(&handle); + run_completion(&handle, 0); FrameMark; - return result; + return true; } /// We drive the state loop ourself so that we will be able to support /// non-data triggers like those which are time based. -bool DataProcessingDevice::doRun() +void DataProcessingDevice::doRun(DataProcessorContext& context) { ZoneScopedN("doRun"); /// This will send metrics for the relayer at regular intervals of /// 5 seconds, in order to avoid overloading the system. - auto sendRelayerMetrics = [relayerStats = mRelayer->getStats(), - &stats = mStats, - &lastSent = mLastSlowMetricSentTimestamp, - ¤tTime = mBeginIterationTimestamp, - ®istry = mServiceRegistry]() + auto sendRelayerMetrics = [relayerStats = context.relayer->getStats(), + &stats = context.stats, + &lastSent = context.lastSlowMetricSentTimestamp, + ¤tTime = context.beginIterationTimestamp, + ®istry = context.registry]() -> void { if (currentTime - lastSent < 5000) { return; } ZoneScopedN("send metrics"); - auto& monitoring = registry.get(); + auto& monitoring = registry->get(); O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::SEND, 0, 0, O2_SIGNPOST_BLUE); @@ -410,20 +485,20 @@ bool DataProcessingDevice::doRun() monitoring.send(Metric{(int)relayerStats.droppedIncomingMessages, "dropped_incoming_messages"}.addTag(Key::Subsystem, Value::DPL)); monitoring.send(Metric{(int)relayerStats.relayedMessages, "relayed_messages"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)stats.pendingInputs, "inputs/relayed/pending"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)stats.incomplete, "inputs/relayed/incomplete"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)stats.inputParts, "inputs/relayed/total"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats.lastElapsedTimeMs, "elapsed_time_ms"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats.lastTotalProcessedSize, "processed_input_size_byte"} + monitoring.send(Metric{(int)stats->pendingInputs, "inputs/relayed/pending"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(int)stats->incomplete, "inputs/relayed/incomplete"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(int)stats->inputParts, "inputs/relayed/total"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{stats->lastElapsedTimeMs, "elapsed_time_ms"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{stats->lastTotalProcessedSize, "processed_input_size_byte"} .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(stats.lastTotalProcessedSize / (stats.lastElapsedTimeMs ? stats.lastElapsedTimeMs : 1) / 1000), + monitoring.send(Metric{(stats->lastTotalProcessedSize / (stats->lastElapsedTimeMs ? stats->lastElapsedTimeMs : 1) / 1000), "processing_rate_mb_s"} .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats.lastLatency.minLatency, "min_input_latency_ms"} + monitoring.send(Metric{stats->lastLatency.minLatency, "min_input_latency_ms"} .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats.lastLatency.maxLatency, "max_input_latency_ms"} + monitoring.send(Metric{stats->lastLatency.maxLatency, "max_input_latency_ms"} .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(stats.lastTotalProcessedSize / (stats.lastLatency.maxLatency ? stats.lastLatency.maxLatency : 1) / 1000), "input_rate_mb_s"} + monitoring.send(Metric{(stats->lastTotalProcessedSize / (stats->lastLatency.maxLatency ? stats->lastLatency.maxLatency : 1) / 1000), "input_rate_mb_s"} .addTag(Key::Subsystem, Value::DPL)); lastSent = currentTime; @@ -431,24 +506,24 @@ bool DataProcessingDevice::doRun() }; /// This will flush metrics only once every second. - auto flushMetrics = [& stats = mStats, - &relayer = mRelayer, - &lastFlushed = mLastMetricFlushedTimestamp, - ¤tTime = mBeginIterationTimestamp, - ®istry = mServiceRegistry]() + auto flushMetrics = [& stats = context.stats, + &relayer = context.relayer, + &lastFlushed = *context.lastMetricFlushedTimestamp, + ¤tTime = *context.beginIterationTimestamp, + ®istry = context.registry]() -> void { if (currentTime - lastFlushed < 1000) { return; } ZoneScopedN("flush metrics"); - auto& monitoring = registry.get(); + auto& monitoring = registry->get(); O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); // Send all the relevant metrics for the relayer to update the GUI // FIXME: do a delta with the previous version if too many metrics are still // sent... - for (size_t si = 0; si < stats.relayerState.size(); ++si) { - auto state = stats.relayerState[si]; + for (size_t si = 0; si < stats->relayerState.size(); ++si) { + auto state = stats->relayerState[si]; monitoring.send({state, "data_relayer/" + std::to_string(si)}); } relayer->sendContextState(); @@ -457,26 +532,19 @@ bool DataProcessingDevice::doRun() O2_SIGNPOST_END(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); }; - auto switchState = [& registry = mServiceRegistry, - &state = mState.streaming](StreamingState newState) { + auto switchState = [& registry = context.registry, + &state = context.state->streaming](StreamingState newState) { LOG(debug) << "New state " << (int)newState << " old state " << (int)state; state = newState; - registry.get().notifyStreamingState(state); + registry->get().notifyStreamingState(state); }; - mBeginIterationTimestamp = uv_hrtime() / 1000000; + *context.beginIterationTimestamp = uv_hrtime() / 1000000; - if (mPendingRegionInfos.empty() == false) { - std::vector toBeNotified; - toBeNotified.swap(mPendingRegionInfos); // avoid any MT issue. - for (auto const& info : toBeNotified) { - mServiceRegistry.get()(CallbackService::Id::RegionInfoCallback, info); - } - } - mWasActive = false; + *context.wasActive = false; { ZoneScopedN("CallbackService::Id::ClockTick"); - mServiceRegistry.get()(CallbackService::Id::ClockTick); + context.registry->get()(CallbackService::Id::ClockTick); } // Whether or not we had something to do. @@ -484,13 +552,13 @@ bool DataProcessingDevice::doRun() // expect to receive an EndOfStream signal. Thus we do not wait for these // to be completed. In the case of data source devices, as they do not have // real data input channels, they have to signal EndOfStream themselves. - bool allDone = std::any_of(mState.inputChannelInfos.begin(), mState.inputChannelInfos.end(), [](const auto& info) { + bool allDone = std::any_of(context.state->inputChannelInfos.begin(), context.state->inputChannelInfos.end(), [](const auto& info) { return info.state != InputChannelState::Pull; }); // Whether or not all the channels are completed - for (size_t ci = 0; ci < mSpec.inputChannels.size(); ++ci) { - auto& channel = mSpec.inputChannels[ci]; - auto& info = mState.inputChannelInfos[ci]; + for (size_t ci = 0; ci < context.spec->inputChannels.size(); ++ci) { + auto& channel = context.spec->inputChannels[ci]; + auto& info = context.state->inputChannelInfos[ci]; if (info.state != InputChannelState::Completed && info.state != InputChannelState::Pull) { allDone = false; @@ -499,28 +567,28 @@ bool DataProcessingDevice::doRun() continue; } FairMQParts parts; - auto result = this->Receive(parts, channel.name, 0, 0); + auto result = context.device->Receive(parts, channel.name, 0, 0); if (result > 0) { // Receiving data counts as activity now, so that // We can make sure we process all the pending // messages without hanging on the uv_run. - mWasActive = true; - this->handleData(parts, info); - mCompleted.clear(); - mCompleted.reserve(16); - mWasActive |= this->tryDispatchComputation(mCompleted); + *context.wasActive = true; + DataProcessingDevice::handleData(context, parts, info); + context.completed->clear(); + context.completed->reserve(16); + *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); } } sendRelayerMetrics(); flushMetrics(); - if (mWasActive == false) { - mServiceRegistry.get()(CallbackService::Id::Idle); + if (*context.wasActive == false) { + context.registry->get()(CallbackService::Id::Idle); } - auto activity = mRelayer->processDanglingInputs(mExpirationHandlers, mServiceRegistry); - mWasActive |= activity.expiredSlots > 0; + auto activity = context.relayer->processDanglingInputs(*context.expirationHandlers, *context.registry); + *context.wasActive |= activity.expiredSlots > 0; - mCompleted.clear(); - mWasActive |= this->tryDispatchComputation(mCompleted); + context.completed->clear(); + *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); sendRelayerMetrics(); flushMetrics(); @@ -529,39 +597,39 @@ bool DataProcessingDevice::doRun() // callback and return false. Notice that what happens next is actually // dependent on the callback, not something which is controlled by the // framework itself. - if (allDone == true && mState.streaming == StreamingState::Streaming) { + if (allDone == true && context.state->streaming == StreamingState::Streaming) { switchState(StreamingState::EndOfStreaming); - mWasActive = true; + *context.wasActive = true; } - if (mState.streaming == StreamingState::EndOfStreaming) { + if (context.state->streaming == StreamingState::EndOfStreaming) { // We keep processing data until we are Idle. // FIXME: not sure this is the correct way to drain the queues, but // I guess we will see. - while (this->tryDispatchComputation(mCompleted)) { - mRelayer->processDanglingInputs(mExpirationHandlers, mServiceRegistry); + while (DataProcessingDevice::tryDispatchComputation(context, *context.completed)) { + context.relayer->processDanglingInputs(*context.expirationHandlers, *context.registry); } sendRelayerMetrics(); flushMetrics(); - EndOfStreamContext eosContext{mServiceRegistry, mAllocator}; - for (auto& eosHandle : mPreEOSHandles) { + EndOfStreamContext eosContext{*context.registry, *context.allocator}; + for (auto& eosHandle : *context.preEOSHandles) { eosHandle.callback(eosContext, eosHandle.service); } - mServiceRegistry.get()(CallbackService::Id::EndOfStream, eosContext); - for (auto& eosHandle : mPostEOSHandles) { + context.registry->get()(CallbackService::Id::EndOfStream, eosContext); + for (auto& eosHandle : *context.postEOSHandles) { eosHandle.callback(eosContext, eosHandle.service); } - for (auto& channel : mSpec.outputChannels) { - DataProcessingHelpers::sendEndOfStream(*this, channel); + for (auto& channel : context.spec->outputChannels) { + DataProcessingHelpers::sendEndOfStream(*context.device, channel); } // This is needed because the transport is deleted before the device. - mRelayer->clear(); + context.relayer->clear(); switchState(StreamingState::Idle); - mWasActive = true; - return true; + *context.wasActive = true; + return; } - return true; + return; } void DataProcessingDevice::ResetTask() @@ -573,15 +641,15 @@ void DataProcessingDevice::ResetTask() /// is divided in two parts. In the first one we define a set of lambdas /// which describe what is actually going to happen, hiding all the state /// boilerplate which the user does not need to care about at top level. -bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info) +void DataProcessingDevice::handleData(DataProcessorContext& context, FairMQParts& parts, InputChannelInfo& info) { ZoneScopedN("DataProcessingDevice::handleData"); - assert(mSpec.inputChannels.empty() == false); + assert(context.spec->inputChannels.empty() == false); assert(parts.Size() > 0); // Initial part. Let's hide all the unnecessary and have // simple lambdas for each of the steps I am planning to have. - assert(!mSpec.inputs.empty()); + assert(!context.spec->inputs.empty()); // These duplicate references are created so that each function // does not need to know about the whole class state, but I can @@ -601,8 +669,8 @@ bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info // and we do a few stats. We bind parts as a lambda captured variable, rather // than an input, because we do not want the outer loop actually be exposed // to the implementation details of the messaging layer. - auto getInputTypes = [& stats = mStats, &parts, &info]() -> std::optional> { - stats.inputParts = parts.Size(); + auto getInputTypes = [& stats = context.stats, &parts, &info]() -> std::optional> { + stats->inputParts = parts.Size(); TracyPlot("messages received", (int64_t)parts.Size()); if (parts.Size() % 2) { @@ -642,11 +710,12 @@ bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info return results; }; - auto reportError = [& device = *this](const char* message) { - device.error(message); + auto reportError = [& registry = *context.registry, &context](const char* message) { + context.errorCount++; + registry.get().send(Metric{*context.errorCount, "errors"}.addTag(Key::Subsystem, Value::DPL)); }; - auto handleValidMessages = [&parts, &relayer = *mRelayer, &reportError](std::vector const& types) { + auto handleValidMessages = [&parts, &relayer = *context.relayer, &reportError](std::vector const& types) { // We relay execution to make sure we have a complete set of parts // available. for (size_t pi = 0; pi < (parts.Size() / 2); ++pi) { @@ -682,10 +751,10 @@ bool DataProcessingDevice::handleData(FairMQParts& parts, InputChannelInfo& info auto inputTypes = getInputTypes(); if (bool(inputTypes) == false) { reportError("Parts should come in couples. Dropping it."); - return true; + return; } handleValidMessages(*inputTypes); - return true; + return; } namespace @@ -720,7 +789,7 @@ auto calculateTotalInputRecordSize(InputRecord const& record) -> int }; } // namespace -bool DataProcessingDevice::tryDispatchComputation(std::vector& completed) +bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, std::vector& completed) { ZoneScopedN("DataProcessingDevice::tryDispatchComputation"); // This is the actual hidden state for the outer loop. In case we decide we @@ -729,19 +798,6 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector currentSetOfInputs; - auto& allocator = mAllocator; - auto& device = *this; - auto& errorCallback = mError; - auto& errorCount = mErrorCount; - auto& forwards = mSpec.forwards; - auto& inputsSchema = mSpec.inputs; - auto& relayer = *mRelayer; - auto& serviceRegistry = mServiceRegistry; - auto& statefulProcess = mStatefulProcess; - auto& statelessProcess = mStatelessProcess; - auto& timingInfo = mTimingInfo; - auto& timesliceIndex = mServiceRegistry.get(); - // These duplicate references are created so that each function // does not need to know about the whole class state, but I can // fine grain control what is exposed at each state. @@ -751,16 +807,18 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); }); - auto reportError = [&device](const char* message) { - device.error(message); + auto reportError = [& registry = *context.registry, &context](const char* message) { + context.errorCount++; + registry.get().send(Metric{*context.errorCount, "errors"}.addTag(Key::Subsystem, Value::DPL)); }; // For the moment we have a simple "immediately dispatch" policy for stuff // in the cache. This could be controlled from the outside e.g. by waiting // for a few sets of inputs to arrive before we actually dispatch the // computation, however this can be defined at a later stage. - auto canDispatchSomeComputation = [&completed, &relayer]() -> bool { - relayer.getReadyToProcess(completed); + auto canDispatchSomeComputation = [&completed, + &relayer = context.relayer]() -> bool { + relayer->getReadyToProcess(completed); return completed.empty() == false; }; @@ -768,17 +826,21 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector std::vector { - stats.pendingInputs = (int)relayer.getParallelTimeslices() - completed.size(); - stats.incomplete = completed.empty() ? 1 : 0; + auto getReadyActions = [& relayer = context.relayer, + &completed, + &stats = context.stats]() -> std::vector { + stats->pendingInputs = (int)relayer->getParallelTimeslices() - completed.size(); + stats->incomplete = completed.empty() ? 1 : 0; return completed; }; // This is needed to convert from a pair of pointers to an actual DataRef // and to make sure the ownership is moved from the cache in the relayer to // the execution. - auto fillInputs = [&relayer, &inputsSchema, ¤tSetOfInputs](TimesliceSlot slot) -> InputRecord { - currentSetOfInputs = std::move(relayer.getInputsForTimeslice(slot)); + auto fillInputs = [& relayer = context.relayer, + &spec = context.spec, + ¤tSetOfInputs](TimesliceSlot slot) -> InputRecord { + currentSetOfInputs = std::move(relayer->getInputsForTimeslice(slot)); auto getter = [¤tSetOfInputs](size_t i, size_t partindex) -> DataRef { if (currentSetOfInputs[i].size() > partindex) { return DataRef{nullptr, @@ -791,16 +853,17 @@ bool DataProcessingDevice::tryDispatchComputation(std::vectorinputs, std::move(span)}; }; // I need a preparation step which gets the current timeslice id and // propagates it to the various contextes (i.e. the actual entities which // create messages) because the messages need to have the timeslice id into // it. - auto prepareAllocatorForCurrentTimeSlice = [&timingInfo, &relayer, ×liceIndex](TimesliceSlot i) { + auto prepareAllocatorForCurrentTimeSlice = [& timingInfo = context.timingInfo, + ×liceIndex = context.registry->get()](TimesliceSlot i) { auto timeslice = timesliceIndex.getTimesliceForSlot(i); - timingInfo.timeslice = timeslice.value; + timingInfo->timeslice = timeslice.value; }; // When processing them, timers will have to be cleaned up @@ -848,7 +911,9 @@ bool DataProcessingDevice::tryDispatchComputation(std::vectorforwards) { if (DataSpecUtils::match(forward.matcher, dh->dataOrigin, dh->dataDescription, dh->subSpecification) == false || (dph->startTime % forward.maxTimeslices) != forward.timeslice) { continue; } @@ -916,13 +981,12 @@ bool DataProcessingDevice::tryDispatchComputation(std::vector(channelParts.At(0)->GetData())); // in DPL we are using subchannel 0 only - device.Send(channelParts, channelName, 0); + device->Send(channelParts, channelName, 0); } }; - - auto switchState = [& control = mServiceRegistry.get(), - &state = mState.streaming](StreamingState newState) { + auto switchState = [& control = context.registry->get(), + &state = context.state->streaming](StreamingState newState) { state = newState; control.notifyStreamingState(state); }; @@ -931,7 +995,7 @@ bool DataProcessingDevice::tryDispatchComputation(std::vectorlastLatency = calculateInputRecordLatency(record, tStart); }; - auto preUpdateStats = [stats = &mStats](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { + auto preUpdateStats = [& stats = context.stats](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { for (size_t ai = 0; ai != record.size(); ai++) { auto cacheId = action.slot.index * record.size() + ai; auto state = record.isValid(ai) ? 2 : 0; @@ -960,15 +1024,15 @@ bool DataProcessingDevice::tryDispatchComputation(std::vectorforwards.empty() == false) { forwardInputs(action.slot, record); continue; } @@ -977,33 +1041,34 @@ bool DataProcessingDevice::tryDispatchComputation(std::vectorquitRequested == false) { - if (statefulProcess) { + if (*context.statefulProcess) { ZoneScopedN("statefull process"); - statefulProcess(processContext); + (*context.statefulProcess)(processContext); } - if (statelessProcess) { + if (*context.statelessProcess) { ZoneScopedN("stateless process"); - statelessProcess(processContext); + (*context.statelessProcess)(processContext); } { ZoneScopedN("service post processing"); - for (auto& handle : mPostProcessingHandles) { + for (auto& handle : *context.postProcessingHandles) { handle.callback(processContext, handle.service); } } } } catch (std::exception& e) { ZoneScopedN("error handling"); - mErrorHandling(e, record); + (*context.errorHandling)(e, record); } + postUpdateStats(action, record, tStart); // We forward inputs only when we consume them. If we simply Process them, // we keep them for next message arriving. if (action.op == CompletionPolicy::CompletionOp::Consume) { - if (forwards.empty() == false) { + if (context.spec->forwards.empty() == false) { forwardInputs(action.slot, record); } #ifdef TRACY_ENABLE @@ -1014,9 +1079,9 @@ bool DataProcessingDevice::tryDispatchComputation(std::vectorstreaming == StreamingState::EndOfStreaming) { + for (auto& channel : context.spec->outputChannels) { + DataProcessingHelpers::sendEndOfStream(*context.device, channel); } switchState(StreamingState::Idle); } From 7587cb12b5d52ff22d12b26426e3126b98110012 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 13 Jul 2020 17:05:37 +0200 Subject: [PATCH 0090/1751] DPL: correctly initialise thread pool service --- Framework/Core/src/CommonServices.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index eebdf7d8ee973..5fdb4d359056d 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -325,8 +325,10 @@ o2::framework::ServiceSpec CommonServices::threadPool(int numWorkers) { return ServiceSpec{ "threadpool", - [](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { - return ServiceHandle{TypeIdHelpers::uniqueId(), new ThreadPool()}; + [numWorkers](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { + ThreadPool* pool = new ThreadPool(); + pool->poolSize = numWorkers; + return ServiceHandle{TypeIdHelpers::uniqueId(), pool}; }, [numWorkers](InitContext&, void* service) -> void* { ThreadPool* t = reinterpret_cast(service); From dfb7fd4aff824d55459e0d1e3d38fa9f65e62f7a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 13 Jul 2020 23:11:05 +0200 Subject: [PATCH 0091/1751] DPL: move DataProcessingStats to be a DPL Service --- .../Core/include/Framework/CommonServices.h | 1 + .../Core/include/Framework/DanglingContext.h | 33 +++++ .../include/Framework/DataProcessingDevice.h | 12 +- .../include/Framework/DataProcessingStats.h | 4 + .../Core/include/Framework/ServiceSpec.h | 13 ++ Framework/Core/src/CommonMessageBackends.cxx | 8 ++ Framework/Core/src/CommonServices.cxx | 131 ++++++++++++++++++ Framework/Core/src/DataProcessingDevice.cxx | 128 +++++------------ 8 files changed, 232 insertions(+), 98 deletions(-) create mode 100644 Framework/Core/include/Framework/DanglingContext.h diff --git a/Framework/Core/include/Framework/CommonServices.h b/Framework/Core/include/Framework/CommonServices.h index c22535d565130..402de7ae1d266 100644 --- a/Framework/Core/include/Framework/CommonServices.h +++ b/Framework/Core/include/Framework/CommonServices.h @@ -60,6 +60,7 @@ struct CommonServices { static ServiceSpec dataRelayer(); static ServiceSpec tracingSpec(); static ServiceSpec threadPool(int numWorkers); + static ServiceSpec dataProcessingStats(); static std::vector defaultServices(int numWorkers = 0); static std::vector requiredServices(); diff --git a/Framework/Core/include/Framework/DanglingContext.h b/Framework/Core/include/Framework/DanglingContext.h new file mode 100644 index 0000000000000..7b02baeb40aa5 --- /dev/null +++ b/Framework/Core/include/Framework/DanglingContext.h @@ -0,0 +1,33 @@ +// 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_DANGLINGCONTEXT_H_ +#define O2_FRAMEWORK_DANGLINGCONTEXT_H_ + +#include "Framework/ServiceRegistry.h" + +namespace o2::framework +{ + +class DanglingContext +{ + public: + DanglingContext(ServiceRegistry& services) + : mServices(services) + { + } + + ServiceRegistry& services() { return mServices; } + + ServiceRegistry& mServices; +}; + +} // namespace o2::framework + +#endif // O2_FRAMEWORK_DANGLINGCONTEXT_H_ diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index fab35aec3bb73..1dffddf8fe7c8 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -62,11 +62,7 @@ struct DataProcessorContext { DeviceState* state = nullptr; DataRelayer* relayer = nullptr; - DataProcessingStats* stats = nullptr; ServiceRegistry* registry = nullptr; - uint64_t* lastSlowMetricSentTimestamp = nullptr; /// The timestamp of the last time we sent slow metrics - uint64_t* lastMetricFlushedTimestamp = nullptr; /// The timestamp of the last time we actually flushed metrics - uint64_t* beginIterationTimestamp = nullptr; /// The timestamp of when the current ConditionalRun was started std::vector* completed = nullptr; std::vector* expirationHandlers = nullptr; TimingInfo* timingInfo = nullptr; @@ -78,6 +74,10 @@ struct DataProcessorContext { std::vector* preProcessingHandles = nullptr; /// Callbacks for services to be executed after every process method invokation std::vector* postProcessingHandles = nullptr; + /// Callbacks for services to be executed before every dangling check + std::vector* preDanglingHandles = nullptr; + /// Callbacks for services to be executed after every dangling check + std::vector* postDanglingHandles = nullptr; /// Callbacks for services to be executed before every EOS user callback invokation std::vector* preEOSHandles = nullptr; /// Callbacks for services to be executed after every EOS user callback invokation @@ -137,6 +137,10 @@ class DataProcessingDevice : public FairMQDevice std::vector mPreProcessingHandles; /// Callbacks for services to be executed after every process method invokation std::vector mPostProcessingHandles; + /// Callbacks for services to be executed before every dangling check + std::vector mPreDanglingHandles; + /// Callbacks for services to be executed after every dangling check + std::vector mPostDanglingHandles; /// Callbacks for services to be executed before every EOS user callback invokation std::vector mPreEOSHandles; /// Callbacks for services to be executed after every EOS user callback invokation diff --git a/Framework/Core/include/Framework/DataProcessingStats.h b/Framework/Core/include/Framework/DataProcessingStats.h index d809a80547b73..958df21d7df9b 100644 --- a/Framework/Core/include/Framework/DataProcessingStats.h +++ b/Framework/Core/include/Framework/DataProcessingStats.h @@ -30,6 +30,10 @@ struct DataProcessingStats { int inputParts = 0; int lastElapsedTimeMs = 0; int lastTotalProcessedSize = 0; + + uint64_t lastSlowMetricSentTimestamp = 0; /// The timestamp of the last time we sent slow metrics + uint64_t lastMetricFlushedTimestamp = 0; /// The timestamp of the last time we actually flushed metrics + uint64_t beginIterationTimestamp = 0; /// The timestamp of when the current ConditionalRun was started InputLatency lastLatency = {}; std::vector relayerState; }; diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index b95a60e8fc99d..2a78bab53969c 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -30,6 +30,7 @@ struct ServiceRegistry; struct DeviceState; struct ProcessingContext; struct EndOfStreamContext; +class DanglingContext; /// Handle to the service hash must be calculated /// using TypeIdHelper::uniqueId() so that @@ -50,6 +51,9 @@ using ServiceConfigureCallback = std::function; /// A callback which is executed before each processing loop. using ServiceProcessingCallback = std::function; +/// A callback which is executed before each dangling input loop +using ServiceDanglingCallback = std::function; + /// A callback which is executed before the end of stream loop. using ServiceEOSCallback = std::function; @@ -93,6 +97,10 @@ struct ServiceSpec { ServiceProcessingCallback preProcessing = nullptr; /// Callback executed once actual processing happened. ServiceProcessingCallback postProcessing = nullptr; + /// Callback executed before the dangling inputs loop + ServiceDanglingCallback preDangling = nullptr; + /// Callback executed after the dangling inputs loop + ServiceDanglingCallback postDangling = nullptr; /// Callback executed before the end of stream callback of the user happended ServiceEOSCallback preEOS = nullptr; /// Callback executed after the end of stream callback of the user happended @@ -122,6 +130,11 @@ struct ServiceProcessingHandle { void* service; }; +struct ServiceDanglingHandle { + ServiceDanglingCallback callback; + void* service; +}; + struct ServiceEOSHandle { ServiceEOSCallback callback; void* service; diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index b5b4a354a712b..1729042b9ad6c 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -81,6 +81,8 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() CommonServices::noConfiguration(), CommonMessageBackendsHelpers::clearContext(), CommonMessageBackendsHelpers::sendCallback(), + nullptr, + nullptr, CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), nullptr, @@ -116,6 +118,8 @@ o2::framework::ServiceSpec CommonMessageBackends::fairMQBackendSpec() CommonServices::noConfiguration(), CommonMessageBackendsHelpers::clearContext(), CommonMessageBackendsHelpers::sendCallback(), + nullptr, + nullptr, CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), nullptr, @@ -131,6 +135,8 @@ o2::framework::ServiceSpec CommonMessageBackends::stringBackendSpec() CommonServices::noConfiguration(), CommonMessageBackendsHelpers::clearContext(), CommonMessageBackendsHelpers::sendCallback(), + nullptr, + nullptr, CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), nullptr, @@ -146,6 +152,8 @@ o2::framework::ServiceSpec CommonMessageBackends::rawBufferBackendSpec() CommonServices::noConfiguration(), CommonMessageBackendsHelpers::clearContext(), CommonMessageBackendsHelpers::sendCallback(), + nullptr, + nullptr, CommonMessageBackendsHelpers::clearContextEOS(), CommonMessageBackendsHelpers::sendCallbackEOS(), nullptr, diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 5fdb4d359056d..f10691b9379ca 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -17,12 +17,17 @@ #include "Framework/LocalRootFileService.h" #include "Framework/DataRelayer.h" #include "Framework/Signpost.h" +#include "Framework/DataProcessingStats.h" #include "Framework/CommonMessageBackends.h" +#include "Framework/DanglingContext.h" +#include "Framework/EndOfStreamContext.h" +#include "Framework/Tracing.h" #include "../src/DataProcessingStatus.h" #include #include #include +#include #include #include @@ -35,6 +40,9 @@ using o2::configuration::ConfigurationFactory; using o2::configuration::ConfigurationInterface; using o2::monitoring::Monitoring; using o2::monitoring::MonitoringFactory; +using Metric = o2::monitoring::Metric; +using Key = o2::monitoring::tags::Key; +using Value = o2::monitoring::tags::Value; namespace o2::framework { @@ -53,6 +61,8 @@ o2::framework::ServiceSpec CommonServices::monitoringSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -68,6 +78,8 @@ o2::framework::ServiceSpec CommonServices::infologgerContextSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -151,6 +163,8 @@ o2::framework::ServiceSpec CommonServices::infologgerSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -174,6 +188,8 @@ o2::framework::ServiceSpec CommonServices::configurationSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -193,6 +209,8 @@ o2::framework::ServiceSpec CommonServices::controlSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -209,6 +227,8 @@ o2::framework::ServiceSpec CommonServices::rootFileSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -229,6 +249,8 @@ o2::framework::ServiceSpec CommonServices::parallelSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -245,6 +267,8 @@ o2::framework::ServiceSpec CommonServices::timesliceIndex() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -261,6 +285,8 @@ o2::framework::ServiceSpec CommonServices::callbacksSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -284,6 +310,8 @@ o2::framework::ServiceSpec CommonServices::dataRelayer() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -314,6 +342,8 @@ o2::framework::ServiceSpec CommonServices::tracingSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -340,6 +370,8 @@ o2::framework::ServiceSpec CommonServices::threadPool(int numWorkers) nullptr, nullptr, nullptr, + nullptr, + nullptr, [numWorkers](ServiceRegistry& service) -> void { auto numWorkersS = std::to_string(numWorkers); setenv("UV_THREADPOOL_SIZE", numWorkersS.c_str(), 0); @@ -348,6 +380,104 @@ o2::framework::ServiceSpec CommonServices::threadPool(int numWorkers) ServiceKind::Serial}; } +namespace +{ +/// This will send metrics for the relayer at regular intervals of +/// 5 seconds, in order to avoid overloading the system. +auto sendRelayerMetrics(ServiceRegistry& registry, DataProcessingStats& stats) -> void +{ + if (stats.beginIterationTimestamp - stats.lastSlowMetricSentTimestamp < 5000) { + return; + } + ZoneScopedN("send metrics"); + auto& relayerStats = registry.get().getStats(); + auto& monitoring = registry.get(); + + O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::SEND, 0, 0, O2_SIGNPOST_BLUE); + + monitoring.send(Metric{(int)relayerStats.malformedInputs, "malformed_inputs"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(int)relayerStats.droppedComputations, "dropped_computations"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(int)relayerStats.droppedIncomingMessages, "dropped_incoming_messages"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(int)relayerStats.relayedMessages, "relayed_messages"}.addTag(Key::Subsystem, Value::DPL)); + + monitoring.send(Metric{(int)stats.pendingInputs, "inputs/relayed/pending"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(int)stats.incomplete, "inputs/relayed/incomplete"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(int)stats.inputParts, "inputs/relayed/total"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{stats.lastElapsedTimeMs, "elapsed_time_ms"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{stats.lastTotalProcessedSize, "processed_input_size_byte"} + .addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(stats.lastTotalProcessedSize / (stats.lastElapsedTimeMs ? stats.lastElapsedTimeMs : 1) / 1000), + "processing_rate_mb_s"} + .addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{stats.lastLatency.minLatency, "min_input_latency_ms"} + .addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{stats.lastLatency.maxLatency, "max_input_latency_ms"} + .addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(stats.lastTotalProcessedSize / (stats.lastLatency.maxLatency ? stats.lastLatency.maxLatency : 1) / 1000), "input_rate_mb_s"} + .addTag(Key::Subsystem, Value::DPL)); + + stats.lastSlowMetricSentTimestamp = stats.beginIterationTimestamp; + O2_SIGNPOST_END(MonitoringStatus::ID, MonitoringStatus::SEND, 0, 0, O2_SIGNPOST_BLUE); +}; + +/// This will flush metrics only once every second. +auto flushMetrics(ServiceRegistry& registry, DataProcessingStats& stats) -> void +{ + if (stats.beginIterationTimestamp - stats.lastMetricFlushedTimestamp < 1000) { + return; + } + ZoneScopedN("flush metrics"); + auto& monitoring = registry.get(); + auto& relayer = registry.get(); + + O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); + // Send all the relevant metrics for the relayer to update the GUI + // FIXME: do a delta with the previous version if too many metrics are still + // sent... + for (size_t si = 0; si < stats.relayerState.size(); ++si) { + auto state = stats.relayerState[si]; + monitoring.send({state, "data_relayer/" + std::to_string(si)}); + } + relayer.sendContextState(); + monitoring.flushBuffer(); + stats.lastMetricFlushedTimestamp = stats.beginIterationTimestamp; + O2_SIGNPOST_END(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); +}; +} // namespace + +o2::framework::ServiceSpec CommonServices::dataProcessingStats() +{ + return ServiceSpec{ + "data-processing-stats", + [](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { + DataProcessingStats* stats = new DataProcessingStats(); + return ServiceHandle{TypeIdHelpers::uniqueId(), stats}; + }, + noConfiguration(), + nullptr, + nullptr, + [](DanglingContext& context, void* service) { + DataProcessingStats* stats = (DataProcessingStats*)service; + sendRelayerMetrics(context.services(), *stats); + flushMetrics(context.services(), *stats); + }, + [](DanglingContext& context, void* service) { + DataProcessingStats* stats = (DataProcessingStats*)service; + sendRelayerMetrics(context.services(), *stats); + flushMetrics(context.services(), *stats); + }, + [](EndOfStreamContext& context, void* service) { + DataProcessingStats* stats = (DataProcessingStats*)service; + sendRelayerMetrics(context.services(), *stats); + flushMetrics(context.services(), *stats); + }, + nullptr, + nullptr, + nullptr, + nullptr, + ServiceKind::Serial}; +} + std::vector CommonServices::defaultServices(int numThreads) { std::vector specs{ @@ -361,6 +491,7 @@ std::vector CommonServices::defaultServices(int numThreads) parallelSpec(), callbacksSpec(), dataRelayer(), + dataProcessingStats(), CommonMessageBackends::fairMQBackendSpec(), CommonMessageBackends::arrowBackendSpec(), CommonMessageBackends::stringBackendSpec(), diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 671246ebf25f0..d432941d26d8c 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -20,6 +20,7 @@ #include "Framework/DeviceState.h" #include "Framework/DispatchPolicy.h" #include "Framework/DispatchControl.h" +#include "Framework/DanglingContext.h" #include "Framework/EndOfStreamContext.h" #include "Framework/FairOptionsRetriever.h" #include "ConfigurationOptionsRetriever.h" @@ -394,11 +395,7 @@ void DataProcessingDevice::fillContext(DataProcessorContext& context) context.state = &mState; context.relayer = mRelayer; - context.stats = &mStats; context.registry = &mServiceRegistry; - context.lastSlowMetricSentTimestamp = &mLastSlowMetricSentTimestamp; /// The timestamp of the last time we sent slow metrics - context.lastMetricFlushedTimestamp = &mLastMetricFlushedTimestamp; /// The timestamp of the last time we actually flushed metrics - context.beginIterationTimestamp = &mBeginIterationTimestamp; /// The timestamp of when the current ConditionalRun was started context.completed = &mCompleted; context.expirationHandlers = &mExpirationHandlers; context.timingInfo = &mTimingInfo; @@ -410,6 +407,10 @@ void DataProcessingDevice::fillContext(DataProcessorContext& context) context.preProcessingHandles = &mPreProcessingHandles; /// Callbacks for services to be executed after every process method invokation context.postProcessingHandles = &mPostProcessingHandles; + /// Callbacks for services to be executed before every process method invokation + context.preDanglingHandles = &mPreDanglingHandles; + /// Callbacks for services to be executed after every process method invokation + context.postDanglingHandles = &mPostDanglingHandles; /// Callbacks for services to be executed before every EOS user callback invokation context.preEOSHandles = &mPreEOSHandles; /// Callbacks for services to be executed after every EOS user callback invokation @@ -464,82 +465,13 @@ bool DataProcessingDevice::ConditionalRun() void DataProcessingDevice::doRun(DataProcessorContext& context) { ZoneScopedN("doRun"); - /// This will send metrics for the relayer at regular intervals of - /// 5 seconds, in order to avoid overloading the system. - auto sendRelayerMetrics = [relayerStats = context.relayer->getStats(), - &stats = context.stats, - &lastSent = context.lastSlowMetricSentTimestamp, - ¤tTime = context.beginIterationTimestamp, - ®istry = context.registry]() - -> void { - if (currentTime - lastSent < 5000) { - return; - } - ZoneScopedN("send metrics"); - auto& monitoring = registry->get(); - - O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::SEND, 0, 0, O2_SIGNPOST_BLUE); - - monitoring.send(Metric{(int)relayerStats.malformedInputs, "malformed_inputs"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)relayerStats.droppedComputations, "dropped_computations"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)relayerStats.droppedIncomingMessages, "dropped_incoming_messages"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)relayerStats.relayedMessages, "relayed_messages"}.addTag(Key::Subsystem, Value::DPL)); - - monitoring.send(Metric{(int)stats->pendingInputs, "inputs/relayed/pending"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)stats->incomplete, "inputs/relayed/incomplete"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(int)stats->inputParts, "inputs/relayed/total"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats->lastElapsedTimeMs, "elapsed_time_ms"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats->lastTotalProcessedSize, "processed_input_size_byte"} - .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(stats->lastTotalProcessedSize / (stats->lastElapsedTimeMs ? stats->lastElapsedTimeMs : 1) / 1000), - "processing_rate_mb_s"} - .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats->lastLatency.minLatency, "min_input_latency_ms"} - .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{stats->lastLatency.maxLatency, "max_input_latency_ms"} - .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(stats->lastTotalProcessedSize / (stats->lastLatency.maxLatency ? stats->lastLatency.maxLatency : 1) / 1000), "input_rate_mb_s"} - .addTag(Key::Subsystem, Value::DPL)); - - lastSent = currentTime; - O2_SIGNPOST_END(MonitoringStatus::ID, MonitoringStatus::SEND, 0, 0, O2_SIGNPOST_BLUE); - }; - - /// This will flush metrics only once every second. - auto flushMetrics = [& stats = context.stats, - &relayer = context.relayer, - &lastFlushed = *context.lastMetricFlushedTimestamp, - ¤tTime = *context.beginIterationTimestamp, - ®istry = context.registry]() - -> void { - if (currentTime - lastFlushed < 1000) { - return; - } - ZoneScopedN("flush metrics"); - auto& monitoring = registry->get(); - - O2_SIGNPOST_START(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); - // Send all the relevant metrics for the relayer to update the GUI - // FIXME: do a delta with the previous version if too many metrics are still - // sent... - for (size_t si = 0; si < stats->relayerState.size(); ++si) { - auto state = stats->relayerState[si]; - monitoring.send({state, "data_relayer/" + std::to_string(si)}); - } - relayer->sendContextState(); - monitoring.flushBuffer(); - lastFlushed = currentTime; - O2_SIGNPOST_END(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); - }; - auto switchState = [& registry = context.registry, &state = context.state->streaming](StreamingState newState) { LOG(debug) << "New state " << (int)newState << " old state " << (int)state; state = newState; registry->get().notifyStreamingState(state); }; - - *context.beginIterationTimestamp = uv_hrtime() / 1000000; + context.registry->get().beginIterationTimestamp = uv_hrtime() / 1000000; *context.wasActive = false; { @@ -579,8 +511,10 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); } } - sendRelayerMetrics(); - flushMetrics(); + DanglingContext danglingContext{*context.registry}; + for (auto preDanglingHandle : *context.preDanglingHandles) { + preDanglingHandle.callback(danglingContext, preDanglingHandle.service); + } if (*context.wasActive == false) { context.registry->get()(CallbackService::Id::Idle); } @@ -590,8 +524,9 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) context.completed->clear(); *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); - sendRelayerMetrics(); - flushMetrics(); + for (auto postDanglingHandle : *context.postDanglingHandles) { + postDanglingHandle.callback(danglingContext, postDanglingHandle.service); + } // If we got notified that all the sources are done, we call the EndOfStream // callback and return false. Notice that what happens next is actually @@ -609,8 +544,6 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) while (DataProcessingDevice::tryDispatchComputation(context, *context.completed)) { context.relayer->processDanglingInputs(*context.expirationHandlers, *context.registry); } - sendRelayerMetrics(); - flushMetrics(); EndOfStreamContext eosContext{*context.registry, *context.allocator}; for (auto& eosHandle : *context.preEOSHandles) { eosHandle.callback(eosContext, eosHandle.service); @@ -669,8 +602,9 @@ void DataProcessingDevice::handleData(DataProcessorContext& context, FairMQParts // and we do a few stats. We bind parts as a lambda captured variable, rather // than an input, because we do not want the outer loop actually be exposed // to the implementation details of the messaging layer. - auto getInputTypes = [& stats = context.stats, &parts, &info]() -> std::optional> { - stats->inputParts = parts.Size(); + auto getInputTypes = [& stats = context.registry->get(), + &parts, &info]() -> std::optional> { + stats.inputParts = parts.Size(); TracyPlot("messages received", (int64_t)parts.Size()); if (parts.Size() % 2) { @@ -828,9 +762,9 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, // on. auto getReadyActions = [& relayer = context.relayer, &completed, - &stats = context.stats]() -> std::vector { - stats->pendingInputs = (int)relayer->getParallelTimeslices() - completed.size(); - stats->incomplete = completed.empty() ? 1 : 0; + &stats = context.registry->get()]() -> std::vector { + stats.pendingInputs = (int)relayer->getParallelTimeslices() - completed.size(); + stats.incomplete = completed.empty() ? 1 : 0; return completed; }; @@ -995,25 +929,25 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, return false; } - auto postUpdateStats = [& stats = context.stats](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { + auto postUpdateStats = [& stats = context.registry->get()](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { for (size_t ai = 0; ai != record.size(); ai++) { auto cacheId = action.slot.index * record.size() + ai; auto state = record.isValid(ai) ? 3 : 0; - stats->relayerState.resize(std::max(cacheId + 1, stats->relayerState.size()), 0); - stats->relayerState[cacheId] = state; + stats.relayerState.resize(std::max(cacheId + 1, stats.relayerState.size()), 0); + stats.relayerState[cacheId] = state; } uint64_t tEnd = uv_hrtime(); - stats->lastElapsedTimeMs = tEnd - tStart; - stats->lastTotalProcessedSize = calculateTotalInputRecordSize(record); - stats->lastLatency = calculateInputRecordLatency(record, tStart); + stats.lastElapsedTimeMs = tEnd - tStart; + stats.lastTotalProcessedSize = calculateTotalInputRecordSize(record); + stats.lastLatency = calculateInputRecordLatency(record, tStart); }; - auto preUpdateStats = [& stats = context.stats](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { + auto preUpdateStats = [& stats = context.registry->get()](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { for (size_t ai = 0; ai != record.size(); ai++) { auto cacheId = action.slot.index * record.size() + ai; auto state = record.isValid(ai) ? 2 : 0; - stats->relayerState.resize(std::max(cacheId + 1, stats->relayerState.size()), 0); - stats->relayerState[cacheId] = state; + stats.relayerState.resize(std::max(cacheId + 1, stats.relayerState.size()), 0); + stats.relayerState[cacheId] = state; } }; @@ -1104,6 +1038,12 @@ void DataProcessingDevice::bindService(ServiceSpec const& spec, void* service) if (spec.postProcessing) { mPostProcessingHandles.push_back(ServiceProcessingHandle{spec.postProcessing, service}); } + if (spec.preDangling) { + mPreDanglingHandles.push_back(ServiceDanglingHandle{spec.preDangling, service}); + } + if (spec.postDangling) { + mPostDanglingHandles.push_back(ServiceDanglingHandle{spec.postDangling, service}); + } if (spec.preEOS) { mPreEOSHandles.push_back(ServiceEOSHandle{spec.preEOS, service}); } From a5a3a26604e0cbed1155fc03e27f6e3bff0baff2 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen Date: Tue, 14 Jul 2020 13:27:53 +0300 Subject: [PATCH 0092/1751] TriggerAliases class and CCDB access via timestamps (#3967) * Added TriggerAliases class and modified CCDB access * CCDB access via timestamps and fixes in timestamp * Changed default ccdb path for RunToTimestamp converter * Adjusted timestamp task to latest changes in the converter --- Analysis/Core/CMakeLists.txt | 2 + .../Core/include/Analysis/TriggerAliases.h | 49 ++++++++++++ Analysis/Core/src/AnalysisCoreLinkDef.h | 1 + Analysis/Core/src/InsertNewRunToTimestamp.cxx | 2 +- Analysis/Core/src/TriggerAliases.cxx | 22 +++++ .../include/Analysis/EventSelection.h | 18 +---- Analysis/Tasks/CMakeLists.txt | 18 ++--- Analysis/Tasks/centralityTable.cxx | 34 ++++---- Analysis/Tasks/eventSelection.cxx | 80 ++++--------------- Analysis/Tasks/multiplicityQa.cxx | 6 +- Analysis/Tasks/timestamp.cxx | 8 +- 11 files changed, 124 insertions(+), 116 deletions(-) create mode 100644 Analysis/Core/include/Analysis/TriggerAliases.h create mode 100644 Analysis/Core/src/TriggerAliases.cxx diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index 019a72741a5a9..eb98c02979235 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -15,6 +15,7 @@ o2_add_library(AnalysisCore src/VarManager.cxx src/HistogramManager.cxx src/RunToTimestamp.cxx + src/TriggerAliases.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel) o2_target_root_dictionary(AnalysisCore @@ -24,6 +25,7 @@ o2_target_root_dictionary(AnalysisCore include/Analysis/VarManager.h include/Analysis/HistogramManager.h include/Analysis/RunToTimestamp.h + include/Analysis/TriggerAliases.h include/Analysis/MC.h LINKDEF src/AnalysisCoreLinkDef.h) diff --git a/Analysis/Core/include/Analysis/TriggerAliases.h b/Analysis/Core/include/Analysis/TriggerAliases.h new file mode 100644 index 0000000000000..9a7e9e9cbd35f --- /dev/null +++ b/Analysis/Core/include/Analysis/TriggerAliases.h @@ -0,0 +1,49 @@ +// 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 TriggerAliases_H +#define TriggerAliases_H + +#include +#include +#include +#include + +enum triggerAliases { + kINT7 = 0, + kEMC7, + kINT7inMUON, + kMuonSingleLowPt7, + kMuonUnlikeLowPt7, + kMuonLikeLowPt7, + kCUP8, + kCUP9, + kMUP10, + kMUP11, + kNaliases +}; + +class TriggerAliases +{ + public: + TriggerAliases() = default; + ~TriggerAliases() = default; + void AddAlias(int aliasId, std::string classNames) { mAliases[aliasId] = classNames; } + void AddClassIdToAlias(int aliasId, int classId) { mAliasToClassIds[aliasId].push_back(classId); } + const std::map>& GetAliasToClassIdsMap() const { return mAliasToClassIds; } + void Print(); + + private: + std::map mAliases; + std::map> mAliasToClassIds; + ClassDefNV(TriggerAliases, 1) +}; + +#endif diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index 01b17ab1e703d..db54444db5438 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -21,6 +21,7 @@ #pragma link C++ class RunToTimestamp+; #pragma link C++ class CorrelationContainer+; #pragma link C++ class TrackSelection+; +#pragma link C++ class TriggerAliases+; #pragma link C++ class VarManager + ; #pragma link C++ class HistogramManager + ; diff --git a/Analysis/Core/src/InsertNewRunToTimestamp.cxx b/Analysis/Core/src/InsertNewRunToTimestamp.cxx index 3428592ea3821..c2036cac1f72b 100644 --- a/Analysis/Core/src/InsertNewRunToTimestamp.cxx +++ b/Analysis/Core/src/InsertNewRunToTimestamp.cxx @@ -27,7 +27,7 @@ bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv 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("Test/RunToTimestamp"), "Path to the object in the CCDB repository")( + "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")( diff --git a/Analysis/Core/src/TriggerAliases.cxx b/Analysis/Core/src/TriggerAliases.cxx new file mode 100644 index 0000000000000..d5b69e9bc9a0a --- /dev/null +++ b/Analysis/Core/src/TriggerAliases.cxx @@ -0,0 +1,22 @@ +// 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 "Analysis/TriggerAliases.h" + +void TriggerAliases::Print() +{ + for (auto& al : GetAliasToClassIdsMap()) { + printf("%d", al.first); + for (auto& classIndex : al.second) { + printf(" %d", classIndex); + } + printf("\n"); + } +} diff --git a/Analysis/DataModel/include/Analysis/EventSelection.h b/Analysis/DataModel/include/Analysis/EventSelection.h index 9ff2951e4f17a..aacb72c017688 100644 --- a/Analysis/DataModel/include/Analysis/EventSelection.h +++ b/Analysis/DataModel/include/Analysis/EventSelection.h @@ -11,28 +11,14 @@ #define O2_ANALYSIS_EVENTSELECTION_H_ #include "Framework/AnalysisDataModel.h" - -// TODO read nAliases from the alias map? -#define nAliases 10 -enum triggerAliases { - kINT7 = 0, - kEMC7, - kINT7inMUON, - kMuonSingleLowPt7, - kMuonUnlikeLowPt7, - kMuonLikeLowPt7, - kCUP8, - kCUP9, - kMUP10, - kMUP11 -}; +#include "Analysis/TriggerAliases.h" namespace o2::aod { namespace evsel { // TODO bool arrays are not supported? Storing in int32 for the moment -DECLARE_SOA_COLUMN(Alias, alias, int32_t[nAliases]); +DECLARE_SOA_COLUMN(Alias, alias, int32_t[kNaliases]); DECLARE_SOA_COLUMN(BBV0A, bbV0A, bool); // beam-beam time in V0A DECLARE_SOA_COLUMN(BBV0C, bbV0C, bool); // beam-beam time in V0C DECLARE_SOA_COLUMN(BGV0A, bgV0A, bool); // beam-gas time in V0A diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index e4d4e4462bb6c..c9387198f4e59 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -35,12 +35,12 @@ o2_add_dpl_workflow(vertexing-hf o2_add_dpl_workflow(hftrackindexskimscreator SOURCES hftrackindexskimscreator.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) o2_add_dpl_workflow(hfcandidatecreator2prong SOURCES hfcandidatecreator2prong.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) o2_add_dpl_workflow(taskdzero @@ -73,37 +73,37 @@ o2_add_dpl_workflow(upc-an o2_add_dpl_workflow(event-selection SOURCES eventSelection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::CCDB + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB COMPONENT_NAME Analysis) o2_add_dpl_workflow(event-selection-qa SOURCES eventSelectionQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) o2_add_dpl_workflow(multiplicity-table SOURCES multiplicityTable.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) o2_add_dpl_workflow(multiplicity-qa SOURCES multiplicityQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) o2_add_dpl_workflow(centrality-table SOURCES centralityTable.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::CCDB + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB COMPONENT_NAME Analysis) o2_add_dpl_workflow(centrality-qa SOURCES centralityQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) o2_add_dpl_workflow(invmass-an SOURCES invMassAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) o2_add_dpl_workflow(table-maker diff --git a/Analysis/Tasks/centralityTable.cxx b/Analysis/Tasks/centralityTable.cxx index dfb0435cd03cd..ec7a43c514499 100644 --- a/Analysis/Tasks/centralityTable.cxx +++ b/Analysis/Tasks/centralityTable.cxx @@ -12,39 +12,33 @@ #include "Framework/AnalysisDataModel.h" #include "Analysis/Multiplicity.h" #include "Analysis/Centrality.h" -#include "CCDB/CcdbApi.h" -#include "TFile.h" +#include #include "TH1F.h" -#include -using std::map; -using std::string; using namespace o2; using namespace o2::framework; struct CentralityTableTask { Produces cent; - TH1F* hCumMultV0M; + Service ccdb; void init(InitContext&) { - // TODO read run number from configurables - int run = 244918; - - // read hMultV0M from ccdb - o2::ccdb::CcdbApi ccdb; - map metadata; - ccdb.init("http://ccdb-test.cern.ch:8080"); - TH1F* hMultV0M = ccdb.retrieveFromTFileAny("Multiplicity/MultV0M", metadata, run); - - // TODO produce cumulative histos in the post processing macro - hCumMultV0M = (TH1F*)hMultV0M->GetCumulative(false); - hCumMultV0M->Scale(100. / hCumMultV0M->GetMaximum()); + ccdb->setURL("http://ccdb-test.cern.ch:8080"); + ccdb->setCachingEnabled(true); + ccdb->setValidityCheckingEnabled(); } - void process(aod::Mult const& mult) + void process(soa::Join::iterator const& collision, aod::Timestamps& timestamps, aod::BCs const& bcs) { - float centV0M = hCumMultV0M->GetBinContent(hCumMultV0M->FindFixBin(mult.multV0M())); + auto ts = timestamps.iteratorAt(collision.bcId()); + LOGF(debug, "timestamp=%llu", ts.timestamp()); + TH1F* hCumMultV0M = ccdb->getForTimeStamp("Multiplicity/CumMultV0M", ts.timestamp()); + if (!hCumMultV0M) { + LOGF(fatal, "V0M centrality calibration is not available in CCDB for run=%d at timestamp=%llu", collision.bc().runNumber(), ts.timestamp()); + } + float centV0M = hCumMultV0M->GetBinContent(hCumMultV0M->FindFixBin(collision.multV0M())); + LOGF(debug, "centV0M=%.0f", centV0M); // fill centrality columns cent(centV0M); diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index 89fabe9b625ae..a10b432bf7ddb 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -11,14 +11,10 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Analysis/EventSelection.h" -#include "CCDB/CcdbApi.h" -#include "TFile.h" -#include "TTree.h" +#include "Analysis/TriggerAliases.h" +#include #include -using std::map; -using std::string; - using namespace o2; using namespace o2::framework; @@ -58,9 +54,7 @@ struct EvSelParameters { struct EventSelectionTask { Produces evsel; - map* pClassNameToIndexMap; - map mAliases; - map> mAliasToClassIds; + Service ccdb; EvSelParameters par; aod::Run2V0 getVZero(aod::BC const& bc, aod::Run2V0s const& vzeros) @@ -90,74 +84,32 @@ struct EventSelectionTask { return dummy; } - // TODO create aliases elsewhere (like BrowseAndFill macro) - void createAliases() - { - mAliases[kINT7] = "CINT7-B-NOPF-CENT,CINT7-B-NOPF-CENTNOTRD"; - mAliases[kEMC7] = "CEMC7-B-NOPF-CENTNOPMD,CDMC7-B-NOPF-CENTNOPMD"; - mAliases[kINT7inMUON] = "CINT7-B-NOPF-MUFAST"; - mAliases[kMuonSingleLowPt7] = "CMSL7-B-NOPF-MUFAST"; - mAliases[kMuonUnlikeLowPt7] = "CMUL7-B-NOPF-MUFAST"; - mAliases[kMuonLikeLowPt7] = "CMLL7-B-NOPF-MUFAST"; - mAliases[kCUP8] = "CCUP8-B-NOPF-CENTNOTRD"; - mAliases[kCUP9] = "CCUP9-B-NOPF-CENTNOTRD"; - mAliases[kMUP10] = "CMUP10-B-NOPF-MUFAST"; - mAliases[kMUP11] = "CMUP11-B-NOPF-MUFAST"; - } - void init(InitContext&) { - // TODO read run number from configurables - int run = 244918; - - // read ClassNameToIndexMap from ccdb - o2::ccdb::CcdbApi ccdb; - map metadata; - ccdb.init("http://ccdb-test.cern.ch:8080"); - pClassNameToIndexMap = ccdb.retrieveFromTFileAny>("Trigger/ClassNameToIndexMap", metadata, run); - - LOGF(debug, "List of trigger classes"); - for (auto& cl : *pClassNameToIndexMap) { - LOGF(debug, "class %02d %s", cl.second, cl.first); - } - - // TODO read aliases from CCDB - createAliases(); - - LOGF(debug, "Fill map of alias-to-class-indices"); - for (auto& al : mAliases) { - LOGF(debug, "alias classes: %s", al.second.data()); - TObjArray* tokens = TString(al.second).Tokenize(","); - for (int iClasses = 0; iClasses < tokens->GetEntriesFast(); iClasses++) { - string className = tokens->At(iClasses)->GetName(); - int index = (*pClassNameToIndexMap)[className] - 1; - if (index < 0 || index > 63) - continue; - mAliasToClassIds[al.first].push_back(index); - } - delete tokens; - } - - // TODO Fill EvSelParameters with configurable cuts from CCDB + ccdb->setURL("http://ccdb-test.cern.ch:8080"); + ccdb->setCachingEnabled(true); + ccdb->setValidityCheckingEnabled(); } - void process(aod::Collision const& collision, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs const& fdds) + void process(aod::Collision const& collision, aod::BCs const& bcs, aod::Timestamps& timestamps, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs const& fdds) { - LOGF(debug, "Starting new event"); - // CTP info + auto ts = timestamps.iteratorAt(collision.bcId()); + LOGF(debug, "timestamp=%llu", ts.timestamp()); + TriggerAliases* aliases = ccdb->getForTimeStamp("Trigger/TriggerAliases", ts.timestamp()); + if (!aliases) { + LOGF(fatal, "Trigger aliases are not available in CCDB for run=%d at timestamp=%llu", collision.bc().runNumber(), ts.timestamp()); + } uint64_t triggerMask = collision.bc().triggerMask(); LOGF(debug, "triggerMask=%llu", triggerMask); + // fill fired aliases - int32_t alias[nAliases] = {0}; - for (auto& al : mAliasToClassIds) { + int32_t alias[kNaliases] = {0}; + for (auto& al : aliases->GetAliasToClassIdsMap()) { for (auto& classIndex : al.second) { alias[al.first] |= (triggerMask & (1ull << classIndex)) > 0; } } - // for (int i=0;i<64;i++) printf("%i",(triggerMask & (1ull << i)) > 0); printf("\n"); - // for (int i=0;i hMultV0M{TH1F("hMultV0M", "", 40000, 0., 40000.)}; - OutputObj hMultZNA{TH1F("hMultZNA", "", 500, 0., 200000.)}; - OutputObj hMultZNC{TH1F("hMultZNC", "", 500, 0., 200000.)}; + OutputObj hMultV0M{TH1F("hMultV0M", "", 50000, 0., 50000.)}; + OutputObj hMultZNA{TH1F("hMultZNA", "", 600, 0., 240000.)}; + OutputObj hMultZNC{TH1F("hMultZNC", "", 600, 0., 240000.)}; void process(soa::Join::iterator const& col) { diff --git a/Analysis/Tasks/timestamp.cxx b/Analysis/Tasks/timestamp.cxx index 75b9242f3af99..52856b3e34248 100644 --- a/Analysis/Tasks/timestamp.cxx +++ b/Analysis/Tasks/timestamp.cxx @@ -29,7 +29,7 @@ struct TimestampTask { Produces ts_table; RunToTimestamp* converter = nullptr; Service ccdb; - Configurable path{"ccdb-path", "Test/RunToTimestamp", "path to the ccdb object"}; + Configurable path{"ccdb-path", "Analysis/Core/RunToTimestamp", "path to the ccdb object"}; Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; void init(o2::framework::InitContext&) @@ -46,9 +46,11 @@ struct TimestampTask { void process(aod::BC const& bc) { long timestamp = converter->getTimestamp(bc.runNumber()); - InteractionRecord current(bc.globalBC(), 0); + uint16_t currentBC = bc.globalBC() % o2::constants::lhc::LHCMaxBunches; + uint32_t currentOrbit = bc.globalBC() / o2::constants::lhc::LHCMaxBunches; + InteractionRecord current(currentBC, currentOrbit); InteractionRecord initial = o2::raw::HBFUtils::Instance().getFirstIR(); - timestamp += 1000000 * (current - initial).bc2ns(); + timestamp += (current - initial).bc2ns() / 1000000; ts_table(timestamp); } }; From af3661a7caa911ee071dec147a8439d1aed12286 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene Date: Tue, 14 Jul 2020 12:29:04 +0200 Subject: [PATCH 0093/1751] First commit of the analysis cut classes; several other fixes and improvements (#3969) * first commit for the invariant mass task * Initial commit for test base classes for Event, Track and Analysis objects * Added a task which produces trees of ReducedEvent objects * first commit for an example skimmed data table maker and reader * Added histogram and variable manager classes * Tables in ReducedInfoTables redefined using the existing columns in the central data model. Removed dependency on the VarManager for the HistogramManager * VarManager and HistogramManager classes updated. tableReader task now contains nearly complete examples on how to define all supported types of histograms * AnalysisCut and AnalysisCompositeCut classes added; other small improvements --- Analysis/Core/CMakeLists.txt | 4 + .../include/Analysis/AnalysisCompositeCut.h | 47 ++++++ Analysis/Core/include/Analysis/AnalysisCut.h | 124 ++++++++++++++ .../Core/include/Analysis/HistogramManager.h | 20 ++- Analysis/Core/include/Analysis/VarManager.h | 33 +++- Analysis/Core/src/AnalysisCompositeCut.cxx | 56 +++++++ Analysis/Core/src/AnalysisCoreLinkDef.h | 2 + Analysis/Core/src/AnalysisCut.cxx | 100 +++++++++++ Analysis/Core/src/HistogramManager.cxx | 11 +- Analysis/Core/src/VarManager.cxx | 37 +++- .../include/Analysis/ReducedInfoTables.h | 11 +- Analysis/Tasks/tableMaker.cxx | 19 ++- Analysis/Tasks/tableReader.cxx | 158 ++++++++++++------ 13 files changed, 529 insertions(+), 93 deletions(-) create mode 100644 Analysis/Core/include/Analysis/AnalysisCompositeCut.h create mode 100644 Analysis/Core/include/Analysis/AnalysisCut.h create mode 100644 Analysis/Core/src/AnalysisCompositeCut.cxx create mode 100644 Analysis/Core/src/AnalysisCut.cxx diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index eb98c02979235..8aeae80d51b5d 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -14,6 +14,8 @@ o2_add_library(AnalysisCore src/TrackSelection.cxx src/VarManager.cxx src/HistogramManager.cxx + src/AnalysisCut.cxx + src/AnalysisCompositeCut.cxx src/RunToTimestamp.cxx src/TriggerAliases.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel) @@ -24,6 +26,8 @@ o2_target_root_dictionary(AnalysisCore include/Analysis/TrackSelection.h include/Analysis/VarManager.h include/Analysis/HistogramManager.h + include/Analysis/AnalysisCut.h + include/Analysis/AnalysisCompositeCut.h include/Analysis/RunToTimestamp.h include/Analysis/TriggerAliases.h include/Analysis/MC.h diff --git a/Analysis/Core/include/Analysis/AnalysisCompositeCut.h b/Analysis/Core/include/Analysis/AnalysisCompositeCut.h new file mode 100644 index 0000000000000..59ff82a2ccb5f --- /dev/null +++ b/Analysis/Core/include/Analysis/AnalysisCompositeCut.h @@ -0,0 +1,47 @@ +// 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 +// +// Cut class manipulating groups of cuts +// + +#ifndef AnalysisCompositeCut_H +#define AnalysisCompositeCut_H + +#include "Analysis/AnalysisCut.h" +#include + +//_________________________________________________________________________ +class AnalysisCompositeCut : public AnalysisCut +{ + public: + AnalysisCompositeCut(bool useAND = kTRUE); + AnalysisCompositeCut(const char* name, const char* title, bool useAND = kTRUE); + ~AnalysisCompositeCut() override; + + void AddCut(AnalysisCut* cut) { fCutList.push_back(*cut); }; + + bool GetUseAND() const { return fOptionUseAND; } + int GetNCuts() const { return fCutList.size(); } + + bool IsSelected(float* values) override; + + protected: + bool fOptionUseAND; // true (default): apply AND on all cuts; false: use OR + std::vector fCutList; // list of cuts + + AnalysisCompositeCut(const AnalysisCompositeCut& c); + AnalysisCompositeCut& operator=(const AnalysisCompositeCut& c); + + ClassDef(AnalysisCompositeCut, 1); +}; + +#endif diff --git a/Analysis/Core/include/Analysis/AnalysisCut.h b/Analysis/Core/include/Analysis/AnalysisCut.h new file mode 100644 index 0000000000000..7b5ce3f781a54 --- /dev/null +++ b/Analysis/Core/include/Analysis/AnalysisCut.h @@ -0,0 +1,124 @@ +// 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 +// +// Class for analysis cuts applied on the variables defined in the VarManager +// + +#ifndef AnalysisCut_H +#define AnalysisCut_H + +#include +#include + +using std::vector; + +//_________________________________________________________________________ +class AnalysisCut : public TNamed +{ + public: + AnalysisCut(); + AnalysisCut(const char* name, const char* title); + AnalysisCut(const AnalysisCut& c); + AnalysisCut& operator=(const AnalysisCut& c); + ~AnalysisCut() override; + + // NOTE: Apply a selection on variable "var" to be in the range [cutLow,cutHigh] or outside this range if "exclude" is set to true + // NOTE: If a dependent variable is specified, then the selection is applied only if the dependent variable is in the range [depCutLow,depCutHigh] + // NOTE: or outside if "depCutExclude" is true + template + void AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude = false, + int dependentVar = -1, float depCutLow = 0., float depCutHigh = 0., bool depCutExclude = false, + int dependentVar2 = -1, float depCut2Low = 0., float depCut2High = 0., bool depCut2Exclude = false); + + // TODO: implement also IsSelected() functions which take as argument the object to be selected + // But this would require to have access to the VarManager for extracting variables + virtual bool IsSelected(float* values); + + static vector fgUsedVars; //! vector of used variables + + struct CutContainer { + short fVar; // variable to be cut upon + float fLow; // lower limit for the var + float fHigh; // upper limit for the var + bool fExclude; // if true, use the selection range for exclusion + + short fDepVar; // first (optional) variable on which the cut depends + float fDepLow; // lower limit for the first dependent var + float fDepHigh; // upper limit for the first dependent var + bool fDepExclude; // if true, then use the dependent variable range as exclusion + + short fDepVar2; // second (optional) variable on which the cut depends + float fDep2Low; // lower limit for the second dependent var + float fDep2High; // upper limit for the second dependent var + bool fDep2Exclude; // if true, then use the dependent variable range as exclusion + + TF1* fFuncLow; // function for the lower limit cut + TF1* fFuncHigh; // function for the upper limit cut + }; + + protected: + vector fCuts; + + ClassDef(AnalysisCut, 1); +}; + +//____________________________________________________________________________ +template +void AnalysisCut::AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude, + int dependentVar, float depCutLow, float depCutHigh, bool depCutExclude, + int dependentVar2, float depCut2Low, float depCut2High, bool depCut2Exclude) +{ + // + // Add a cut + // + CutContainer cut = {}; + + if constexpr (std::is_same_v) { + if (dependentVar < 0) + return; + cut.fFuncLow = cutLow; + cut.fLow = -9999.0; + } else { + cut.fFuncLow = nullptr; + cut.fLow = cutLow; + } + if constexpr (std::is_same_v) { + if (dependentVar < 0) + return; + cut.fFuncHigh = cutHigh; + cut.fHigh = -9999.0; + } else { + cut.fFuncHigh = nullptr; + cut.fHigh = cutHigh; + } + cut.fVar = var; + cut.fExclude = exclude; + fgUsedVars.push_back(var); + + cut.fDepVar = dependentVar; + cut.fDepLow = depCutLow; + cut.fDepHigh = depCutHigh; + cut.fDepExclude = depCutExclude; + if (dependentVar != -1) + fgUsedVars.push_back(dependentVar); + + cut.fDepVar2 = dependentVar2; + cut.fDep2Low = depCut2Low; + cut.fDep2High = depCut2High; + cut.fDep2Exclude = depCut2Exclude; + if (dependentVar2 != -1) + fgUsedVars.push_back(dependentVar2); + + fCuts.push_back(cut); +} + +#endif diff --git a/Analysis/Core/include/Analysis/HistogramManager.h b/Analysis/Core/include/Analysis/HistogramManager.h index 968abc21d42fd..dd916d870be34 100644 --- a/Analysis/Core/include/Analysis/HistogramManager.h +++ b/Analysis/Core/include/Analysis/HistogramManager.h @@ -10,6 +10,8 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // +// Class to define and fill histograms +// #ifndef HistogramManager_H #define HistogramManager_H @@ -47,22 +49,37 @@ class HistogramManager : public TNamed fMainList = list; } + // Create a new histogram class void AddHistClass(const char* histClass); + // Create a new histogram in the class with name and title + // The type of histogram is deduced from the parameters specified by the user + // The binning for at least one dimension needs to be specified, namely: nXbins, xmin, xmax, varX which will result in a TH1F histogram + // If the value for a variable is left as -1 then that is considered to not be used + // Up to 3 dimensional histograms can be defined with this function + // If isProfile = true, the last specified variable is the one being averaged + // For the case of TProfile3D, the user must use the varT to specify the averaged variable + // If specified, varW will be used as weight in the TH1::Fill() functions. + // If specified, the xLabels, yLabels, zLabels will be used to set the labels of the x,y,z axes, respectively. + // The axis titles will be set by default, if those were specified (e.g. taken from a Variable Manager) + // Otherwise these can be specified in the title string by separating them with semi-colons ";" void AddHistogram(const char* histClass, const char* name, const char* title, bool isProfile, int nXbins, double xmin, double xmax, int varX, int nYbins = 0, double ymin = 0, double ymax = 0, int varY = -1, int nZbins = 0, double zmin = 0, double zmax = 0, int varZ = -1, const char* xLabels = "", const char* yLabels = "", const char* zLabels = "", int varT = -1, int varW = -1); + // Similar to the above function, with the difference that the user can specify non-equidistant binning void AddHistogram(const char* histClass, const char* name, const char* title, bool isProfile, int nXbins, double* xbins, int varX, int nYbins = 0, double* ybins = nullptr, int varY = -1, int nZbins = 0, double* zbins = nullptr, int varZ = -1, const char* xLabels = "", const char* yLabels = "", const char* zLabels = "", int varT = -1, int varW = -1); + // Create a THn histogram (either THnF or THnSparse) with equidistant binning void AddHistogram(const char* histClass, const char* name, const char* title, int nDimensions, int* vars, int* nBins, double* xmin, double* xmax, TString* axLabels = nullptr, int varW = -1, bool useSparse = kFALSE); + // Create a THn histogram (either THnF or THnSparse) with non-equidistant binning void AddHistogram(const char* histClass, const char* name, const char* title, int nDimensions, int* vars, TArrayD* binLimits, TString* axLabels = nullptr, int varW = -1, bool useSparse = kFALSE); @@ -80,7 +97,8 @@ class HistogramManager : public TNamed private: THashList* fMainList; // master histogram list - int fNVars; // number of variables handled (tipically fromt he Variable Manager) + int fNVars; // number of variables handled (tipically from the Variable Manager) + bool* fUsedVars; //! flags of used variables std::map<std::string, std::list<std::vector<int>>> fVariablesMap; //! map holding identifiers for all variables needed by histograms diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 24996e60e1ebe..68d9994c71b22 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -10,6 +10,8 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // +// Class to handle analysis variables +// #ifndef VarManager_H #define VarManager_H @@ -20,8 +22,9 @@ #include <vector> #include <map> + //using namespace o2::aod; -using std::vector; +//using std::vector; //_________________________________________________________________________ class VarManager : public TObject @@ -40,7 +43,7 @@ class VarManager : public TObject kL3Polarity, kNRunWiseVariables, - // Event wise variables + // Event wise variables // Daria: imedjat ai ziua mja kTimeStamp, kBC, kInstLumi, @@ -64,6 +67,7 @@ class VarManager : public TObject kPt, kEta, kPhi, + kP, kRap, kMass, kCharge, @@ -103,25 +107,37 @@ class VarManager : public TObject static TString fgVariableUnits[kNVars]; // variable units static void SetDefaultVarNames(); - static void SetUseVariable(Variables var) + static void SetUseVariable(int var) { - fgUsedVars[var] = kTRUE; + if (var >= 0 && var < kNVars) + fgUsedVars[var] = kTRUE; SetVariableDependencies(); } static void SetUseVars(const bool* usedVars) { for (int i = 0; i < kNVars; ++i) { if (usedVars[i]) - fgUsedVars[i] = kTRUE; // overwrite only the variables that are being used since there are more channels to modify the used variables array, independently + fgUsedVars[i] = true; // overwrite only the variables that are being used since there are more channels to modify the used variables array, independently } SetVariableDependencies(); } - static bool GetUsedVar(Variables var) { return fgUsedVars[var]; } + static void SetUseVars(const std::vector<int> usedVars) + { + for (auto& var : usedVars) + fgUsedVars[var] = true; + } + static bool GetUsedVar(int var) + { + if (var >= 0 && var < kNVars) + return fgUsedVars[var]; + return false; + } static void SetRunNumbers(int n, int* runs); - static void FillEvent(vector<float> event, float* values = nullptr); - static void FillTrack(vector<float> track, float* values = nullptr); + static void FillEvent(std::vector<float> event, float* values = nullptr); + static void FillTrack(std::vector<float> track, float* values = nullptr); + //static void FillTrack(ReducedTrack track, float* values = nullptr); public: VarManager(); @@ -141,4 +157,5 @@ class VarManager : public TObject ClassDef(VarManager, 1) }; + #endif diff --git a/Analysis/Core/src/AnalysisCompositeCut.cxx b/Analysis/Core/src/AnalysisCompositeCut.cxx new file mode 100644 index 0000000000000..de8a5e61813ff --- /dev/null +++ b/Analysis/Core/src/AnalysisCompositeCut.cxx @@ -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. + +#include "Analysis/AnalysisCompositeCut.h" + +ClassImp(AnalysisCompositeCut) + + //____________________________________________________________________________ + AnalysisCompositeCut::AnalysisCompositeCut(bool useAND) : AnalysisCut(), + fOptionUseAND(useAND), + fCutList() +{ + // + // default constructor + // +} + +//____________________________________________________________________________ +AnalysisCompositeCut::AnalysisCompositeCut(const char* name, const char* title, bool useAND) : AnalysisCut(name, title), + fOptionUseAND(useAND), + fCutList() +{ + // + // named constructor + // +} + +//____________________________________________________________________________ +AnalysisCompositeCut::~AnalysisCompositeCut() = default; + +//____________________________________________________________________________ +bool AnalysisCompositeCut::IsSelected(float* values) +{ + // + // apply cuts + // + std::vector<AnalysisCut>::iterator it = fCutList.begin(); + for (std::vector<AnalysisCut>::iterator it = fCutList.begin(); it < fCutList.end(); ++it) { + if (fOptionUseAND && !(*it).IsSelected(values)) + return kFALSE; + if (!fOptionUseAND && (*it).IsSelected(values)) + return kTRUE; + } + + if (fOptionUseAND) + return kTRUE; + else + return kFALSE; +} diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index db54444db5438..b122ef91d96c8 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -25,3 +25,5 @@ #pragma link C++ class VarManager + ; #pragma link C++ class HistogramManager + ; +#pragma link C++ class AnalysisCut + ; +#pragma link C++ class AnalysisCompositeCut + ; diff --git a/Analysis/Core/src/AnalysisCut.cxx b/Analysis/Core/src/AnalysisCut.cxx new file mode 100644 index 0000000000000..02289075cfa20 --- /dev/null +++ b/Analysis/Core/src/AnalysisCut.cxx @@ -0,0 +1,100 @@ +// 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 "Analysis/AnalysisCut.h" + +#include <iostream> +using std::cout; +using std::endl; + +ClassImp(AnalysisCut); + +vector<int> AnalysisCut::fgUsedVars = {}; + +//____________________________________________________________________________ +AnalysisCut::AnalysisCut() : TNamed(), + fCuts() +{ + // + // default constructor + // +} + +//____________________________________________________________________________ +AnalysisCut::AnalysisCut(const char* name, const char* title) : TNamed(name, title), + fCuts() +{ + // + // named constructor + // +} + +//____________________________________________________________________________ +AnalysisCut::AnalysisCut(const AnalysisCut& c) = default; + +//____________________________________________________________________________ +AnalysisCut& AnalysisCut::operator=(const AnalysisCut& c) +{ + // + // assignment + // + if (this != &c) { + TNamed::operator=(c); + fCuts = c.fCuts; + } + return (*this); +} + +//____________________________________________________________________________ +AnalysisCut::~AnalysisCut() = default; + +//____________________________________________________________________________ +bool AnalysisCut::IsSelected(float* values) +{ + // + // apply the configured cuts + // + // iterate over cuts + for (std::vector<CutContainer>::iterator it = fCuts.begin(); it != fCuts.end(); ++it) { + // check whether a dependent variables were enabled and if they are in the requested range + if ((*it).fDepVar != -1) { + bool inRange = (values[(*it).fDepVar] > (*it).fDepLow && values[(*it).fDepVar] <= (*it).fDepHigh); + if (!inRange && !((*it).fDepExclude)) + continue; + if (inRange && (*it).fDepExclude) + continue; + } + if ((*it).fDepVar2 != -1) { + bool inRange = (values[(*it).fDepVar2] > (*it).fDep2Low && values[(*it).fDepVar2] <= (*it).fDep2High); + if (!inRange && !((*it).fDep2Exclude)) + continue; + if (inRange && (*it).fDep2Exclude) + continue; + } + // obtain the low and high cut values (either directly as a value or from a function) + float cutLow, cutHigh; + if ((*it).fFuncLow) + cutLow = ((*it).fFuncLow)->Eval(values[(*it).fDepVar]); + else + cutLow = ((*it).fLow); + if ((*it).fFuncHigh) + cutHigh = ((*it).fFuncHigh)->Eval(values[(*it).fDepVar]); + else + cutHigh = ((*it).fHigh); + // apply the cut and return the decision + bool inRange = (values[(*it).fVar] >= cutLow && values[(*it).fVar] <= cutHigh); + if (!inRange && !((*it).fExclude)) + return false; + if (inRange && ((*it).fExclude)) + return false; + } + + return true; +} diff --git a/Analysis/Core/src/HistogramManager.cxx b/Analysis/Core/src/HistogramManager.cxx index 68581d005942a..a0315fd34e23c 100644 --- a/Analysis/Core/src/HistogramManager.cxx +++ b/Analysis/Core/src/HistogramManager.cxx @@ -487,6 +487,7 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co cout << "size of array :: " << varList.size() << endl; fVariablesMap[histClass] = varList; + unsigned long int nbins = 1; THnBase* h = nullptr; if (useSparse) h = new THnSparseF(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nDimensions, nBins, xmin, xmax); @@ -495,11 +496,9 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co h->Sumw2(); // configure the THn histogram and count the allocated bins - unsigned long int bins = 1; for (int idim = 0; idim < nDimensions; ++idim) { - bins *= (nBins[idim] + 2); + nbins *= (nBins[idim] + 2); TAxis* axis = h->GetAxis(idim); - if (fVariableNames[vars[idim]][0]) axis->SetTitle(Form("%s %s", fVariableNames[vars[idim]].Data(), (fVariableUnits[vars[idim]][0] ? Form("(%s)", fVariableUnits[vars[idim]].Data()) : ""))); @@ -507,13 +506,15 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co axis->SetTitle(arr->At(1 + idim)->GetName()); if (axLabels && !axLabels[idim].IsNull()) MakeAxisLabels(axis, axLabels[idim].Data()); + fUsedVars[vars[idim]] = kTRUE; } if (useSparse) hList->Add((THnSparseF*)h); else hList->Add((THnF*)h); - fBinsAllocated += bins; + + fBinsAllocated += nbins; } //_________________________________________________________________ @@ -657,8 +658,6 @@ void HistogramManager::FillHistClass(const char* className, Float_t* values) varT = varIter->at(6); } - // TODO: check that all needed variables are marked for usage in fUsedVars, otherwise throw and error - if (!isTHn) { switch (dimension) { case 1: diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index fea8b82695e55..2ede176901463 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -10,9 +10,11 @@ #include "Analysis/VarManager.h" -ClassImp(VarManager) +#include <TMath.h> - TString VarManager::fgVariableNames[VarManager::kNVars] = {""}; +ClassImp(VarManager); + +TString VarManager::fgVariableNames[VarManager::kNVars] = {""}; TString VarManager::fgVariableUnits[VarManager::kNVars] = {""}; bool VarManager::fgUsedVars[VarManager::kNVars] = {kFALSE}; float VarManager::fgValues[VarManager::kNVars] = {0.0}; @@ -34,8 +36,12 @@ VarManager::~VarManager() = default; void VarManager::SetVariableDependencies() { // - // Set as used those variables on which other variables calculation depends + // Set as used variables on which other variables calculation depends // + if (fgUsedVars[kP]) { + fgUsedVars[kPt] = kTRUE; + fgUsedVars[kEta] = kTRUE; + } } //__________________________________________________________________ @@ -59,14 +65,16 @@ void VarManager::SetRunNumbers(int n, int* runs) } //__________________________________________________________________ -void VarManager::FillEvent(vector<float> event, float* values) +void VarManager::FillEvent(std::vector<float> event, float* values) { //TODO: the Fill function should take as argument an aod::ReducedEvent iterator, this is just a temporary fix if (!values) values = fgValues; + values[kRunNo] = event[0]; - values[kRunId] = (fgRunMap.size() > 0 ? fgRunMap[int(values[kRunNo])] : 0); + if (fgUsedVars[kRunId]) + values[kRunId] = (fgRunMap.size() > 0 ? fgRunMap[int(values[kRunNo])] : 0); values[kVtxX] = event[1]; values[kVtxY] = event[2]; values[kVtxZ] = event[3]; @@ -88,7 +96,7 @@ void VarManager::FillEvent(vector<float> event, float* values) } //__________________________________________________________________ -void VarManager::FillTrack(vector<float> track, float* values) +void VarManager::FillTrack(std::vector<float> track, float* values) { if (!values) @@ -98,6 +106,8 @@ void VarManager::FillTrack(vector<float> track, float* values) values[kEta] = track[1]; values[kPhi] = track[2]; values[kCharge] = track[3]; + if (fgUsedVars[kP]) + values[kP] = values[kPt] * TMath::CosH(values[kEta]); /*values[kPt] = track.pt(); values[kEta] = track.eta(); values[kPhi] = track.phi(); @@ -117,6 +127,19 @@ void VarManager::FillTrack(vector<float> track, float* values) //values[kTrackLength] = track.barrelLength(); } +/* +//__________________________________________________________________ +void VarManager::FillTrack(ReducedTrack track, float* values) +{ + if (!values) + values = fgValues; + + values[kPt] = track.pt(); + values[kEta] = track.eta(); + values[kPhi] = track.phi(); + values[kCharge] = track.charge(); +}*/ + //__________________________________________________________________ void VarManager::SetDefaultVarNames() { @@ -178,6 +201,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kCentVZERO] = "%"; fgVariableNames[kPt] = "p_{T}"; fgVariableUnits[kPt] = "GeV/c"; + fgVariableNames[kP] = "p"; + fgVariableUnits[kP] = "GeV/c"; fgVariableNames[kEta] = "#eta"; fgVariableUnits[kEta] = ""; fgVariableNames[kPhi] = "#varphi"; diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 685026f8e1c4a..bf374414da3ad 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -19,19 +19,14 @@ #include "MathUtils/Utils.h" #include <cmath> -namespace o2 +namespace o2::aod { -namespace aod -{ - namespace reducedevent { // basic event information DECLARE_SOA_COLUMN(Tag, tag, uint64_t); -// TODO: implement additional separate tables for other types of information, e.g. multiplicity estimators, VZERO-TZERO/FIT, ZDC, etc. - } // namespace reducedevent DECLARE_SOA_TABLE(ReducedEvents, "AOD", "REDUCEDEVENT", o2::soa::Index<>, @@ -108,8 +103,6 @@ using ReducedTrackBarrel = ReducedTracksBarrel::iterator; using ReducedTrackBarrelCov = ReducedTracksBarrelCov::iterator; using ReducedTrackMuon = ReducedTracksMuon::iterator; -} // namespace aod - -} // namespace o2 +} // namespace o2::aod #endif // O2_Analysis_ReducedInfoTables_H_ diff --git a/Analysis/Tasks/tableMaker.cxx b/Analysis/Tasks/tableMaker.cxx index 6cd008e70ca89..5bf673ebdcc76 100644 --- a/Analysis/Tasks/tableMaker.cxx +++ b/Analysis/Tasks/tableMaker.cxx @@ -27,17 +27,18 @@ using std::endl; using namespace o2; using namespace o2::framework; -using namespace o2::framework::expressions; +//using namespace o2::framework::expressions; +using namespace o2::aod; struct TableMaker { - Produces<aod::ReducedEvents> event; - Produces<aod::ReducedEventsExtended> eventExtended; - Produces<aod::ReducedEventsVtxCov> eventVtxCov; - Produces<aod::ReducedTracks> trackBasic; - Produces<aod::ReducedTracksBarrel> trackBarrel; - Produces<aod::ReducedTracksBarrelCov> trackBarrelCov; - //Produces<aod::ReducedTracksMuon> trackMuon; + Produces<ReducedEvents> event; + Produces<ReducedEventsExtended> eventExtended; + Produces<ReducedEventsVtxCov> eventVtxCov; + Produces<ReducedTracks> trackBasic; + Produces<ReducedTracksBarrel> trackBarrel; + Produces<ReducedTracksBarrelCov> trackBarrelCov; + //Produces<dq::ReducedTracksMuon> trackMuon; OutputObj<TH1F> vtxZ{TH1F("vtxZ", "vtx Z", 200, -20.0, 20.0)}; OutputObj<TH1F> vtxX{TH1F("vtxX", "vtx X", 2000, -1.0, 1.0)}; @@ -84,7 +85,7 @@ struct TableMaker { } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<TableMaker>("table-maker")}; diff --git a/Analysis/Tasks/tableReader.cxx b/Analysis/Tasks/tableReader.cxx index 24d4f8fe2453e..e878dcd26a8af 100644 --- a/Analysis/Tasks/tableReader.cxx +++ b/Analysis/Tasks/tableReader.cxx @@ -16,9 +16,12 @@ #include "Analysis/ReducedInfoTables.h" #include "Analysis/VarManager.h" #include "Analysis/HistogramManager.h" +#include "Analysis/AnalysisCut.h" +#include "Analysis/AnalysisCompositeCut.h" #include <TH1F.h> #include <TMath.h> #include <THashList.h> +#include <TString.h> #include <iostream> #include <vector> @@ -28,61 +31,14 @@ using std::vector; using namespace o2; using namespace o2::framework; -using namespace o2::framework::expressions; +//using namespace o2::framework::expressions; +using namespace o2::aod; struct TableReader { OutputObj<HistogramManager> fHistMan{"output"}; - - void DefineHistograms() - { - 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); - - fHistMan->AddHistClass("Event"); - fHistMan->AddHistogram("Event", "VtxZ", "Vtx Z", kFALSE, 60, -15.0, 15.0, VarManager::kVtxZ); // TH1F histogram - fHistMan->AddHistogram("Event", "VtxZ_Run", "Vtx Z", kTRUE, - 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("Event", "VtxX_VtxY", "Vtx X vs Vtx Y", kFALSE, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY); // TH2F histogram - fHistMan->AddHistogram("Event", "VtxX_VtxY_VtxZ", "vtx x - y - z", kFALSE, 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("Event", "NContrib_vs_VtxZ_prof", "Vtx Z vs ncontrib", kTRUE, 30, -15.0, 15.0, VarManager::kVtxZ, 10, -1., 1., VarManager::kVtxNcontrib); // TProfile histogram - fHistMan->AddHistogram("Event", "VtxZ_vs_VtxX_VtxY_prof", "Vtx Z vs (x,y)", kTRUE, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 10, -1., 1., VarManager::kVtxZ); // TProfile2D histogram - fHistMan->AddHistogram("Event", "Ncontrib_vs_VtxZ_VtxX_VtxY_prof", "n-contrib vs (x,y,z)", kTRUE, - 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("Event", "VtxX_VtxY_nonEqualBinning", "Vtx X vs Vtx Y", kFALSE, 9, vtxXbinLims, VarManager::kVtxX, 6, vtxYbinLims, VarManager::kVtxY); // TH2F histogram with custom non-equal binning - - fHistMan->AddHistogram("Event", "VtxZ_weights", "Vtx Z", kFALSE, - 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("Event", "vtxHisto", "n contrib vs (x,y,z)", 4, vars, binLimits); - - //fHistMan.AddHistogram("Event", "CentVZERO", "CentVZERO", kFALSE, 100, 0.0, 100.0, VarManager::kCentVZERO); // TH1F histogram - //fHistMan.AddHistogram("Event", "CentVZERO_VtxZ_prof", "CentVZERO vs vtxZ", kTRUE, 60, -15.0, 15.0, VarManager::kVtxZ, - // 10, 0.0, 0.0, VarManager::kCentVZERO); // TProfile with <CentVZERO> vs vtxZ - - fHistMan->AddHistClass("Track"); - fHistMan->AddHistogram("Track", "Pt", "p_{T} distribution", kFALSE, 200, 0.0, 20.0, VarManager::kPt); // TH1F histogram - //fHistMan.AddHistogram("Track", "TPCdedx_pIN", "TPC dE/dx vs pIN", kFALSE, 100, 0.0, 20.0, VarManager::kPin, - // 200, 0.0, 200., VarManager::kTPCsignal); // TH2F histogram - } + AnalysisCompositeCut* fEventCut; + AnalysisCompositeCut* fTrackCut; void init(o2::framework::InitContext&) { @@ -92,8 +48,35 @@ struct TableReader { fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); - DefineHistograms(); // define all histograms + DefineHistograms("Event_BeforeCuts;Event_AfterCuts;Track_BeforeCuts;Track_AfterCuts"); // 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); + + fTrackCut = new AnalysisCompositeCut(true); // true: use AND + AnalysisCut* cut1 = new AnalysisCut(); + cut1->AddCut(VarManager::kPt, 2.0, 4.0); + AnalysisCut* cut2 = new AnalysisCut(); + cut2->AddCut(VarManager::kPt, 0.5, 3.0); + fTrackCut->AddCut(cut1); + fTrackCut->AddCut(cut2); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } //void process(soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator event, @@ -107,14 +90,81 @@ struct TableReader { std::vector<float> eventInfo = {(float)event.runNumber(), event.posX(), event.posY(), event.posZ(), (float)event.numContrib()}; VarManager::FillEvent(eventInfo); // extract event information and place it in the fgValues array - fHistMan->FillHistClass("Event", VarManager::fgValues); // automatically fill all the histograms in the class 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); for (auto& track : tracks) { std::vector<float> trackInfo = {track.pt(), track.eta(), track.phi(), (float)track.charge()}; VarManager::FillTrack(trackInfo); - fHistMan->FillHistClass("Track", VarManager::fgValues); + fHistMan->FillHistClass("Track_BeforeCuts", VarManager::fgValues); + if (!fTrackCut->IsSelected(VarManager::fgValues)) + continue; + fHistMan->FillHistClass("Track_AfterCuts", VarManager::fgValues); } } + + void DefineHistograms(TString histClasses) + { + 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); + + 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, 100, -1.0, 1.0, VarManager::kEta); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "Phi_Eta", "#phi vs #eta distribution", false, 40, -1.0, 1.0, VarManager::kEta, 200, -6.3, 6.3, VarManager::kPhi); // TH2F histogram + //fHistMan.AddHistogram("Track", "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 100, 0.0, 20.0, VarManager::kPin, + // 200, 0.0, 200., VarManager::kTPCsignal); // TH2F histogram + } + } // end loop over histogram classes + } }; WorkflowSpec defineDataProcessing(ConfigContext const&) From 8e764d15c6cdb5f71debb51dacc642bd1b15c562 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 13 Jul 2020 19:29:33 +0200 Subject: [PATCH 0094/1751] SymbolStatistics::mIterator allowed to take negative values Building SymbolStatistics for signed data implies iterator spanning from mMin<0 to mMax>0, change mIterator mMin and mMax to int64_t from int and size_t respectively --- Utilities/rANS/include/rANS/SymbolStatistics.h | 16 ++++++++-------- Utilities/rANS/src/SymbolStatistics.cxx | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Utilities/rANS/include/rANS/SymbolStatistics.h b/Utilities/rANS/include/rANS/SymbolStatistics.h index c37bef0a18664..613cfba0d2809 100644 --- a/Utilities/rANS/include/rANS/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/SymbolStatistics.h @@ -39,7 +39,7 @@ class SymbolStatistics class Iterator { public: - Iterator(size_t index, const SymbolStatistics& stats); + Iterator(int64_t index, const SymbolStatistics& stats); using difference_type = int64_t; using value_type = std::pair<uint32_t, uint32_t>; @@ -54,7 +54,7 @@ class SymbolStatistics bool operator!=(const Iterator& other) const; private: - size_t mIndex; + int64_t mIndex; const SymbolStatistics& mStats; }; @@ -63,7 +63,7 @@ class SymbolStatistics SymbolStatistics(const IT begin, const IT end, size_t range = 0); template <typename IT> - SymbolStatistics(const IT begin, const IT end, size_t min, size_t max, size_t messageLength); + SymbolStatistics(const IT begin, const IT end, int64_t min, int64_t max, size_t messageLength); void rescaleToNBits(size_t bits); @@ -75,7 +75,7 @@ class SymbolStatistics size_t getMessageLength() const; - std::pair<uint32_t, uint32_t> operator[](size_t index) const; + std::pair<uint32_t, uint32_t> operator[](int64_t index) const; SymbolStatistics::Iterator begin() const; SymbolStatistics::Iterator end() const; @@ -88,8 +88,8 @@ class SymbolStatistics template <typename IT> void buildFrequencyTable(const IT begin, const IT end, size_t range); - int mMin; - int mMax; + int64_t mMin; + int64_t mMax; size_t mNUsedAlphabetSymbols; size_t mMessageLength; @@ -171,7 +171,7 @@ SymbolStatistics::SymbolStatistics(const IT begin, const IT end, size_t range) : } template <typename IT> -SymbolStatistics::SymbolStatistics(const IT begin, const IT end, size_t min, size_t max, size_t messageLength) : mMin(min), mMax(max), mNUsedAlphabetSymbols(0), mMessageLength(messageLength), mFrequencyTable(begin, end), mCumulativeFrequencyTable() +SymbolStatistics::SymbolStatistics(const IT begin, const IT end, int64_t min, int64_t max, size_t messageLength) : mMin(min), mMax(max), mNUsedAlphabetSymbols(0), mMessageLength(messageLength), mFrequencyTable(begin, end), mCumulativeFrequencyTable() { LOG(trace) << "start loading external symbol statistics"; for (auto i : mFrequencyTable) { @@ -193,7 +193,7 @@ void SymbolStatistics::buildFrequencyTable(const IT begin, const IT end, // find min_ and max_ const auto minmax = std::minmax_element(begin, end); - if (range > 0) { + if (range > 0) { // FIXME: providing the range will work only for data [0 : (1 << range) - 1] mMin = 0; mMax = (1 << range) - 1; diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx index 397c4ed89024f..29f5264913148 100644 --- a/Utilities/rANS/src/SymbolStatistics.cxx +++ b/Utilities/rANS/src/SymbolStatistics.cxx @@ -127,7 +127,7 @@ size_t SymbolStatistics::getMessageLength() const return mMessageLength; } -std::pair<uint32_t, uint32_t> SymbolStatistics::operator[](size_t index) const +std::pair<uint32_t, uint32_t> SymbolStatistics::operator[](int64_t index) const { assert(index - mMin < mFrequencyTable.size()); @@ -161,7 +161,7 @@ SymbolStatistics::Iterator SymbolStatistics::end() const } } -SymbolStatistics::Iterator::Iterator(size_t index, +SymbolStatistics::Iterator::Iterator(int64_t index, const SymbolStatistics& stats) : mIndex(index), mStats(stats) {} From 0fe68146451260507ecd88a0ef3c85abaa9114b8 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 11 Jul 2020 17:27:41 +0200 Subject: [PATCH 0095/1751] Fix TOF digit fields to allow multiple TF processing Since the TOF digit stores as BC the absolute bunch count from orbit 0, with int32 it will overflow after ~100 s. Change it uint64_t. Also fix the orbit/bc to uint32_t / uint16_t resp. --- Detectors/TOF/base/include/TOFBase/Digit.h | 22 +++---- Detectors/TOF/base/include/TOFBase/Strip.h | 2 +- .../TOF/base/include/TOFBase/WindowFiller.h | 4 +- Detectors/TOF/base/src/Digit.cxx | 2 +- Detectors/TOF/base/src/Strip.cxx | 2 +- Detectors/TOF/base/src/WindowFiller.cxx | 2 +- .../include/TOFReconstruction/Decoder.h | 15 ++++- Detectors/TOF/reconstruction/src/Decoder.cxx | 62 ++++++++----------- Detectors/TOF/reconstruction/src/Encoder.cxx | 2 +- .../TOFWorkflow/CompressedDecodingTask.h | 2 +- 10 files changed, 57 insertions(+), 58 deletions(-) diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index 0802800f34735..dd22ac9548f31 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -30,11 +30,11 @@ class Digit public: Digit() = default; - Digit(Int_t channel, Int_t tdc, Int_t tot, Int_t bc, Int_t label = -1, Int_t triggerorbit = 0, Int_t triggerbunch = 0); + Digit(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t label = -1, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); ~Digit() = default; /// Get global ordering key made of - static ULong64_t getOrderingKey(Int_t channel, Int_t bc, Int_t /*tdc*/) + static ULong64_t getOrderingKey(Int_t channel, uint64_t bc, Int_t /*tdc*/) { return ((static_cast<ULong64_t>(bc) << 18) + channel); // channel in the least significant bits; then shift by 18 bits (which cover the total number of channels) to write the BC number } @@ -48,8 +48,8 @@ class Digit uint16_t getTOT() const { return mTOT; } void setTOT(uint16_t tot) { mTOT = tot; } - Int_t getBC() const { return mBC; } - void setBC(Int_t bc) { mBC = bc; } + uint64_t getBC() const { return mBC; } + void setBC(uint64_t bc) { mBC = bc; } Int_t getLabel() const { return mLabel; } void setLabel(Int_t label) { mLabel = label; } @@ -78,10 +78,10 @@ class Digit void setIsProblematic(bool flag) { mIsProblematic = flag; } bool isProblematic() const { return mIsProblematic; } - void setTriggerOrbit(int value) { mTriggerOrbit = value; } - int getTriggerOrbit() const { return mTriggerOrbit; } - void setTriggerBunch(int value) { mTriggerBunch = value; } - int getTriggerBunch() const { return mTriggerBunch; } + void setTriggerOrbit(uint32_t value) { mTriggerOrbit = value; } + uint32_t getTriggerOrbit() const { return mTriggerOrbit; } + void setTriggerBunch(uint16_t value) { mTriggerBunch = value; } + uint16_t getTriggerBunch() const { return mTriggerBunch; } private: friend class boost::serialization::access; @@ -90,15 +90,15 @@ class Digit Int_t mChannel; ///< TOF channel index uint16_t mTDC; ///< TDC bin number uint16_t mTOT; ///< TOT bin number - Int_t mBC; ///< Bunch Crossing + uint64_t mBC; ///< Bunch Crossing // RS: since it is used as absolute bunch counter from orbit 0, it has to be 64 bits Int_t mLabel; ///< Index of the corresponding entry in the MC label array Int_t mElectronIndex; //!/< index in electronic format - uint16_t mTriggerOrbit = 0; //!< orbit id of trigger event + uint32_t mTriggerOrbit = 0; //!< orbit id of trigger event // RS: orbit must be 32bits long uint16_t mTriggerBunch = 0; //!< bunch id of trigger event Bool_t mIsUsedInCluster; //!/< flag to declare that the digit was used to build a cluster Bool_t mIsProblematic = false; //!< flag to tell whether the channel of the digit was problemati; not persistent; default = ok - ClassDefNV(Digit, 2); + ClassDefNV(Digit, 3); }; std::ostream& operator<<(std::ostream& stream, const Digit& dig); diff --git a/Detectors/TOF/base/include/TOFBase/Strip.h b/Detectors/TOF/base/include/TOFBase/Strip.h index 015ed765e029e..e4df3fa9fe4ef 100644 --- a/Detectors/TOF/base/include/TOFBase/Strip.h +++ b/Detectors/TOF/base/include/TOFBase/Strip.h @@ -79,7 +79,7 @@ class Strip /// reset points container o2::tof::Digit* findDigit(ULong64_t key); - Int_t addDigit(Int_t channel, Int_t tdc, Int_t tot, Int_t bc, Int_t lbl = 0, int triggerorbit = 0, int triggerbunch = 0); // returns the MC label + Int_t addDigit(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t lbl = 0, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); // returns the MC label void fillOutputContainer(std::vector<o2::tof::Digit>& digits); diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index f84ee5023f22b..a4d0604dee0e3 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -78,13 +78,13 @@ class WindowFiller // arrays with digit and MCLabels out of the current readout windows (stored to fill future readout window) std::vector<Digit> mFutureDigits; - void fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t triggerorbit = 0, Int_t triggerbunch = 0); + void fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); // void fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID); void checkIfReuseFutureDigits(); void checkIfReuseFutureDigitsRO(); - void insertDigitInFuture(Int_t channel, Int_t tdc, Int_t tot, Int_t bc, Int_t label = 0, Int_t triggerorbit = 0, Int_t triggerbunch = 0) + void insertDigitInFuture(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t label = 0, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0) { mFutureDigits.emplace_back(channel, tdc, tot, bc, label, triggerorbit, triggerbunch); mFutureToBeSorted = true; diff --git a/Detectors/TOF/base/src/Digit.cxx b/Detectors/TOF/base/src/Digit.cxx index 93910bcb70efc..9d2503287cd50 100644 --- a/Detectors/TOF/base/src/Digit.cxx +++ b/Detectors/TOF/base/src/Digit.cxx @@ -16,7 +16,7 @@ using namespace o2::tof; ClassImp(o2::tof::Digit); -Digit::Digit(Int_t channel, Int_t tdc, Int_t tot, Int_t bc, Int_t label, Int_t triggerorbit, Int_t triggerbunch) +Digit::Digit(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t label, uint32_t triggerorbit, uint16_t triggerbunch) : mChannel(channel), mTDC(tdc), mTOT(tot), mBC(bc), mLabel(label), mTriggerOrbit(triggerorbit), mTriggerBunch(triggerbunch), mIsUsedInCluster(kFALSE) { } diff --git a/Detectors/TOF/base/src/Strip.cxx b/Detectors/TOF/base/src/Strip.cxx index 43b428c4af0d1..35efb304ecd89 100644 --- a/Detectors/TOF/base/src/Strip.cxx +++ b/Detectors/TOF/base/src/Strip.cxx @@ -33,7 +33,7 @@ Strip::Strip(Int_t index) { } //_______________________________________________________________________ -Int_t Strip::addDigit(Int_t channel, Int_t tdc, Int_t tot, Int_t bc, Int_t lbl, Int_t triggerorbit, Int_t triggerbunch) +Int_t Strip::addDigit(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t lbl, uint32_t triggerorbit, uint16_t triggerbunch) { // return the MC label. We pass it also as argument, but it can change in diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index 15502720bba83..bf8b6833a5dbf 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -100,7 +100,7 @@ void WindowFiller::reset() mFirstBunch = 0; } //______________________________________________________________________ -void WindowFiller::fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t triggerorbit, Int_t triggerbunch) +void WindowFiller::fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit, uint16_t triggerbunch) { (*strips)[istrip].addDigit(channel, tdc, tot, nbc, 0, triggerorbit, triggerbunch); } diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h index eeee1b4838304..8c2738d07d328 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h @@ -44,8 +44,8 @@ class Decoder : public WindowFiller bool open(std::string name); bool decode(); - void readTRM(int icru, int icrate, int orbit, int bunchid); - void InsertDigit(int icrate, int itrm, int itdc, int ichain, int channel, int orbit, int bunchid, int time_ext, int tdc, int tot); + void readTRM(int icru, int icrate, uint32_t orbit, uint16_t bunchid); + void InsertDigit(int icrate, int itrm, int itdc, int ichain, int channel, uint32_t orbit, uint16_t bunchid, int time_ext, int tdc, int tot); void FillWindows(); void clear(); @@ -58,7 +58,16 @@ class Decoder : public WindowFiller void printCrateTrailerInfo(int icru) const; void printHitInfo(int icru) const; - static void fromRawHit2Digit(int icrate, int itrm, int itdc, int ichain, int channel, int orbit, int bunchid, int tdc, int tot, std::array<int, 6>& digitInfo); // convert raw info in digit info (channel, tdc, tot, bc), tdc = packetHit.time + (frameHeader.frameID << 13) + struct DigitInfo { + uint64_t bcAbs; + int channel; + int tdc; + int tot; + uint32_t orbit; + uint16_t bc; + }; + + static void fromRawHit2Digit(int icrate, int itrm, int itdc, int ichain, int channel, uint32_t orbit, uint16_t bunchid, int tdc, int tot, DigitInfo& dinfo); // convert raw info in digit info (channel, tdc, tot, bc), tdc = packetHit.time + (frameHeader.frameID << 13) char* nextPage(void* current, int shift = 8192); diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index 57ae82ae5d384..35dd470550f35 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -112,32 +112,31 @@ void Decoder::clear() reset(); } -void Decoder::InsertDigit(int icrate, int itrm, int itdc, int ichain, int channel, int orbit, int bunchid, int time_ext, int tdc, int tot) +void Decoder::InsertDigit(int icrate, int itrm, int itdc, int ichain, int channel, uint32_t orbit, uint16_t bunchid, int time_ext, int tdc, int tot) { - std::array<int, 6> digitInfo; + DigitInfo digitInfo; fromRawHit2Digit(icrate, itrm, itdc, ichain, channel, orbit, bunchid, time_ext + tdc, tot, digitInfo); mHitDecoded++; - int isnext = digitInfo[3] * Geo::BC_IN_WINDOW_INV; + uint64_t isnext = digitInfo.bcAbs * Geo::BC_IN_WINDOW_INV; - if (isnext >= MAXWINDOWS) { // accumulate all digits which are not in the first windows - - insertDigitInFuture(digitInfo[0], digitInfo[1], digitInfo[2], digitInfo[3], 0, digitInfo[4], digitInfo[5]); + if (isnext >= uint64_t(MAXWINDOWS)) { // accumulate all digits which are not in the first windows + insertDigitInFuture(digitInfo.channel, digitInfo.tdc, digitInfo.tot, digitInfo.bcAbs, 0, digitInfo.orbit, digitInfo.bc); } else { std::vector<Strip>* cstrip = mStripsCurrent; // first window - if (isnext) + if (isnext) { cstrip = mStripsNext[isnext - 1]; // next window - - UInt_t istrip = digitInfo[0] / Geo::NPADS; + } + UInt_t istrip = digitInfo.channel / Geo::NPADS; // add digit - fillDigitsInStrip(cstrip, digitInfo[0], digitInfo[1], digitInfo[2], digitInfo[3], istrip); + fillDigitsInStrip(cstrip, digitInfo.channel, digitInfo.tdc, digitInfo.tot, digitInfo.bcAbs, istrip); } } -void Decoder::readTRM(int icru, int icrate, int orbit, int bunchid) +void Decoder::readTRM(int icru, int icrate, uint32_t orbit, uint16_t bunchid) { if (orbit < mFirstOrbit || (orbit == mFirstOrbit && bunchid < mFirstBunch)) { @@ -145,8 +144,9 @@ void Decoder::readTRM(int icru, int icrate, int orbit, int bunchid) mFirstBunch = bunchid; } - if (mVerbose) + if (mVerbose) { printTRMInfo(icru); + } int nhits = mUnion[icru]->frameHeader.numberOfHits; int time_ext = mUnion[icru]->frameHeader.frameID << 13; int itrm = mUnion[icru]->frameHeader.trmID; @@ -157,37 +157,31 @@ void Decoder::readTRM(int icru, int icrate, int orbit, int bunchid) mUnion[icru]++; mIntegratedBytes[icru] += 4; - // read hits - Int_t channel, echannel; - Int_t tdc; - Int_t tot; - Int_t bc; - Int_t time; - - std::array<int, 6> digitInfo; + DigitInfo digitInfo; for (int i = 0; i < nhits; i++) { - fromRawHit2Digit(icrate, itrm, mUnion[icru]->packedHit.tdcID, mUnion[icru]->packedHit.chain, mUnion[icru]->packedHit.channel, orbit, bunchid, time_ext + mUnion[icru]->packedHit.time, mUnion[icru]->packedHit.tot, digitInfo); + fromRawHit2Digit(icrate, itrm, mUnion[icru]->packedHit.tdcID, mUnion[icru]->packedHit.chain, mUnion[icru]->packedHit.channel, orbit, bunchid, + time_ext + mUnion[icru]->packedHit.time, mUnion[icru]->packedHit.tot, digitInfo); mHitDecoded++; if (mVerbose) printHitInfo(icru); - int isnext = digitInfo[3] * Geo::BC_IN_WINDOW_INV; + uint64_t isnext = digitInfo.bcAbs * Geo::BC_IN_WINDOW_INV; if (isnext >= MAXWINDOWS) { // accumulate all digits which are not in the first windows - insertDigitInFuture(digitInfo[0], digitInfo[1], digitInfo[2], digitInfo[3], 0, digitInfo[4], digitInfo[5]); + insertDigitInFuture(digitInfo.channel, digitInfo.tdc, digitInfo.tot, digitInfo.bcAbs, 0, digitInfo.orbit, digitInfo.bc); } else { std::vector<Strip>* cstrip = mStripsCurrent; // first window if (isnext) cstrip = mStripsNext[isnext - 1]; // next window - UInt_t istrip = digitInfo[0] / Geo::NPADS; + UInt_t istrip = digitInfo.channel / Geo::NPADS; // add digit - fillDigitsInStrip(cstrip, digitInfo[0], digitInfo[1], digitInfo[2], digitInfo[3], istrip); + fillDigitsInStrip(cstrip, digitInfo.channel, digitInfo.tdc, digitInfo.tot, digitInfo.bcAbs, istrip); } mUnion[icru]++; @@ -195,21 +189,17 @@ void Decoder::readTRM(int icru, int icrate, int orbit, int bunchid) } } -void Decoder::fromRawHit2Digit(int icrate, int itrm, int itdc, int ichain, int channel, int orbit, int bunchid, int tdc, int tot, std::array<int, 6>& digitInfo) +void Decoder::fromRawHit2Digit(int icrate, int itrm, int itdc, int ichain, int channel, uint32_t orbit, uint16_t bunchid, int tdc, int tot, Decoder::DigitInfo& dinfo) { // convert raw info in digit info (channel, tdc, tot, bc) // tdc = packetHit.time + (frameHeader.frameID << 13) int echannel = Geo::getECHFromIndexes(icrate, itrm, ichain, itdc, channel); - digitInfo[0] = Geo::getCHFromECH(echannel); - digitInfo[2] = tot; - - digitInfo[3] = int(orbit * o2::tof::Geo::BC_IN_ORBIT); - digitInfo[3] += bunchid; - digitInfo[3] += tdc / 1024; - digitInfo[1] = tdc % 1024; - - digitInfo[4] = orbit; - digitInfo[5] = bunchid; + dinfo.channel = Geo::getCHFromECH(echannel); + dinfo.tot = tot; + dinfo.bcAbs = uint64_t(orbit) * o2::tof::Geo::BC_IN_ORBIT + bunchid + tdc / 1024; + dinfo.tdc = tdc % 1024; + dinfo.orbit = orbit; + dinfo.bc = bunchid; } char* Decoder::nextPage(void* current, int shift) diff --git a/Detectors/TOF/reconstruction/src/Encoder.cxx b/Detectors/TOF/reconstruction/src/Encoder.cxx index 1747315a36ef3..483f0a0ff24f8 100644 --- a/Detectors/TOF/reconstruction/src/Encoder.cxx +++ b/Detectors/TOF/reconstruction/src/Encoder.cxx @@ -179,7 +179,7 @@ void Encoder::encodeTRM(const std::vector<Digit>& summary, Int_t icrate, Int_t i if (hittimeTDC < 0) { LOG(ERROR) << "Negative hit encoded " << hittimeTDC << ", something went wrong in filling readout window"; - printf("%d %d %d\n", summary[istart].getBC(), mEventCounter * Geo::BC_IN_WINDOW, summary[istart].getTDC()); + printf("%llu %d %d\n", (unsigned long long)summary[istart].getBC(), mEventCounter * Geo::BC_IN_WINDOW, summary[istart].getTDC()); } // leading time mUnion[icrate]->trmDataHit.time = hittimeTDC; diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h index 92e3a7c6c66cf..85dc44202c6c8 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h @@ -55,7 +55,7 @@ class CompressedDecodingTask : public DecoderBase, public Task int mNCrateOpenTF = 0; int mNCrateCloseTF = 0; bool mHasToBePosted = false; - int mInitOrbit = 0; + uint32_t mInitOrbit = 0; TStopwatch mTimer; }; From a678ce74c94ff75344d8d0f114ff86edb1c5ac87 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 11 Jul 2020 17:40:32 +0200 Subject: [PATCH 0096/1751] Do not send ROMode for GRPUpdated from CompressedDecodingTask --- Detectors/TOF/workflow/src/CompressedDecodingTask.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 41451891fa9fd..dd86f89e880ab 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -67,8 +67,8 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) static o2::parameters::GRPObject::ROMode roMode = o2::parameters::GRPObject::CONTINUOUS; - LOG(INFO) << "TOF: Sending ROMode= " << roMode << " to GRPUpdater"; - pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ROMode", 0, Lifetime::Timeframe}, roMode); + setFirstTFOrbit(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, mInitOrbit); + setFirstTFOrbit(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, mInitOrbit); mDecoder.clear(); @@ -150,7 +150,6 @@ DataProcessorSpec getCompressedDecodingSpec(const std::string& inputDesc) std::vector<OutputSpec> outputs; outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe); - outputs.emplace_back(o2::header::gDataOriginTOF, "ROMode", 0, Lifetime::Timeframe); return DataProcessorSpec{ "tof-compressed-decoder", From 16744f0a0ae3cdfc2fd57986a15a800ee16e6415 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 11 Jul 2020 17:41:52 +0200 Subject: [PATCH 0097/1751] Ensure TOF matching uses TF 1st orbit for time reference --- .../TOF/base/include/TOFBase/WindowFiller.h | 5 +++-- Detectors/TOF/base/src/WindowFiller.cxx | 7 ++++--- .../include/TOFReconstruction/Clusterer.h | 5 +++++ .../TOF/reconstruction/src/Clusterer.cxx | 11 +++++++--- Detectors/TOF/reconstruction/src/Decoder.cxx | 10 +++++----- .../workflow/src/CompressedDecodingTask.cxx | 20 +++++++++++++++++-- .../TOF/workflow/src/TOFClusterizerSpec.cxx | 16 ++++++++++++++- 7 files changed, 58 insertions(+), 16 deletions(-) diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index a4d0604dee0e3..dacecadc26340 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -50,11 +50,12 @@ class WindowFiller void resizeVectorFutureDigit(int size) { mFutureDigits.resize(size); } + void setFirstIR(const o2::InteractionRecord& ir) { mFirstIR = ir; } + protected: // info TOF timewindow Int_t mReadoutWindowCurrent = 0; - Int_t mFirstOrbit = 0; - Int_t mFirstBunch = 0; + InteractionRecord mFirstIR{0, 0}; // reference IR (1st IR of the timeframe) InteractionTimeRecord mEventTime; bool mContinuous = true; diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index bf8b6833a5dbf..2f7cb1b5de648 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -96,9 +96,10 @@ void WindowFiller::reset() mDigitsPerTimeFrame.clear(); mReadoutWindowData.clear(); - mFirstOrbit = 0; - mFirstBunch = 0; + mFirstIR.bc = 0; + mFirstIR.orbit = 0; } + //______________________________________________________________________ void WindowFiller::fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit, uint16_t triggerbunch) { @@ -258,7 +259,7 @@ void WindowFiller::checkIfReuseFutureDigitsRO() // the same but using readout in for (std::vector<Digit>::reverse_iterator digit = mFutureDigits.rbegin(); digit != mFutureDigits.rend(); ++digit) { - int row = (digit->getTriggerOrbit() - mFirstOrbit) * Geo::BC_IN_ORBIT + (digit->getTriggerBunch() - mFirstBunch) + 100; // N bunch id of the trigger from timeframe start + 100 bunches + int row = (digit->getTriggerOrbit() - mFirstIR.orbit) * Geo::BC_IN_ORBIT + (digit->getTriggerBunch() - mFirstIR.bc) + 100; // N bunch id of the trigger from timeframe start + 100 bunches row *= Geo::BC_IN_WINDOW_INV; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h index 5c0903247eb1e..7c0d68e92cf72 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h @@ -52,6 +52,9 @@ class Clusterer Printf("mCalibApi = %p", mCalibApi); } + void setFirstOrbit(uint32_t orb); + uint32_t getFirstOrbit() const { return mFirstOrbit; } + private: void calibrateStrip(); void processStrip(std::vector<Cluster>& clusters, MCLabelContainer const* digitMCTruth); @@ -66,6 +69,8 @@ class Clusterer void addContributingDigit(Digit* dig); void buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth); CalibApi* mCalibApi = nullptr; //! calib api to handle the TOF calibration + uint32_t mFirstOrbit = 0; //! 1st orbit of the TF + uint64_t mBCOffset = 0; //! 1st orbit of the TF converted to BCs }; } // namespace tof diff --git a/Detectors/TOF/reconstruction/src/Clusterer.cxx b/Detectors/TOF/reconstruction/src/Clusterer.cxx index 4d4bc96ed5c5d..7601a9fcb4291 100644 --- a/Detectors/TOF/reconstruction/src/Clusterer.cxx +++ b/Detectors/TOF/reconstruction/src/Clusterer.cxx @@ -40,9 +40,6 @@ void Clusterer::process(DataReader& reader, std::vector<Cluster>& clusters, MCLa LOG(DEBUG) << "We had " << totNumDigits << " digits in this event"; timerProcess.Stop(); - printf("Timing:\n"); - printf("Clusterer::process: "); - timerProcess.Print(); } //__________________________________________________ @@ -53,6 +50,7 @@ void Clusterer::calibrateStrip() for (int idig = 0; idig < mStripData.digits.size(); idig++) { // LOG(DEBUG) << "Checking digit " << idig; Digit* dig = &mStripData.digits[idig]; + dig->setBC(dig->getBC() - mBCOffset); // RS Don't use raw BC, always start from the beginning of the TF double calib = mCalibApi->getTimeCalibration(dig->getChannel(), dig->getTOT() * Geo::TOTBIN_NS); //printf("channel %d) isProblematic = %d, fractionUnderPeak = %f\n",dig->getChannel(),mCalibApi->isProblematic(dig->getChannel()),mCalibApi->getFractionUnderPeak(dig->getChannel())); // toberem dig->setIsProblematic(mCalibApi->isProblematic(dig->getChannel())); @@ -258,3 +256,10 @@ void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth) return; } + +//_____________________________________________________________________ +void Clusterer::setFirstOrbit(uint32_t orb) +{ + mFirstOrbit = orb; + mBCOffset = orb * o2::constants::lhc::LHCMaxBunches; +} diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index 35dd470550f35..dd1ac880e1de7 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -139,9 +139,9 @@ void Decoder::InsertDigit(int icrate, int itrm, int itdc, int ichain, int channe void Decoder::readTRM(int icru, int icrate, uint32_t orbit, uint16_t bunchid) { - if (orbit < mFirstOrbit || (orbit == mFirstOrbit && bunchid < mFirstBunch)) { - mFirstOrbit = orbit; - mFirstBunch = bunchid; + if (orbit < mFirstIR.orbit || (orbit == mFirstIR.orbit && bunchid < mFirstIR.bc)) { + mFirstIR.orbit = orbit; + mFirstIR.bc = bunchid; } if (mVerbose) { @@ -213,8 +213,8 @@ char* Decoder::nextPage(void* current, int shift) bool Decoder::decode() // return a vector of digits in a TOF readout window { mReadoutWindowCurrent = 0; - mFirstOrbit = 0; - mFirstBunch = 0; + mFirstIR.orbit = 0; + mFirstIR.bc = 0; #ifdef VERBOSE if (mVerbose) diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index dd86f89e880ab..50524829b61e5 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -17,6 +17,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "CommonUtils/StringUtils.h" #include "Headers/RAWDataHeader.h" #include "DataFormatsTOF/CompressedDataFormat.h" #include "DetectorsRaw/HBFUtils.h" @@ -65,7 +66,14 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, *alldigits); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, *row); - static o2::parameters::GRPObject::ROMode roMode = o2::parameters::GRPObject::CONTINUOUS; + // RS this is a hack to be removed once we have correct propagation of the firstTForbit by the framework + auto setFirstTFOrbit = [&](const Output& spec, uint32_t orb) { + auto* hd = pc.outputs().findMessageHeader(spec); + if (!hd) { + throw std::runtime_error(o2::utils::concat_string("failed to find output message header for ", spec.origin.str, "/", spec.description.str, "/", std::to_string(spec.subSpec))); + } + hd->firstTForbit = orb; + }; setFirstTFOrbit(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, mInitOrbit); setFirstTFOrbit(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, mInitOrbit); @@ -84,6 +92,14 @@ void CompressedDecodingTask::run(ProcessingContext& pc) LOG(INFO) << "CompressedDecoding run"; mTimer.Start(false); + if (pc.inputs().getNofParts(0)) { + //RS set the 1st orbit of the TF from the O2 header, relying on rdhHandler is not good (in fact, the RDH might be eliminated in the derived data) + const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().getByPos(0).header); + mInitOrbit = dh->firstTForbit; + } + + mDecoder.setFirstIR({0, mInitOrbit}); + /** loop over inputs routes **/ for (auto iit = pc.inputs().begin(), iend = pc.inputs().end(); iit != iend; ++iit) { if (!iit.isValid()) @@ -131,7 +147,7 @@ void CompressedDecodingTask::rdhHandler(const o2::header::RAWDataHeader* rdh) // rdh open if ((RDHUtils::getPageCounter(rdhr) == 0) && (RDHUtils::getTriggerType(rdhr) & o2::trigger::TF)) { mNCrateOpenTF++; - mInitOrbit = RDHUtils::getHeartBeatOrbit(rdhr); + mInitOrbit = RDHUtils::getHeartBeatOrbit(rdhr); // RSTODO this may be eliminated once the framework will start to propagated the dh.firstTForbit // printf("New TF open RDH %d\n", int(rdh->feeId)); } }; diff --git a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx index 61b3796ab1174..c1d6b5bc28415 100644 --- a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx @@ -28,6 +28,9 @@ #include <memory> // for make_shared, make_unique, unique_ptr #include <vector> +// RSTODO to remove once the framework will start propagating the header.firstTForbit +#include "DetectorsRaw/HBFUtils.h" + using namespace o2::framework; namespace o2 @@ -59,6 +62,17 @@ class TOFDPLClustererTask auto digits = pc.inputs().get<gsl::span<o2::tof::Digit>>("tofdigits"); auto row = pc.inputs().get<std::vector<o2::tof::ReadoutWindowData>*>("readoutwin"); + auto header = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("tofdigits").header); + mClusterer.setFirstOrbit(header->firstTForbit); + + //RSTODO: below is a hack, to remove once the framework will start propagating the header.firstTForbit + //Here I extract the orbit/BC from the abs.BC, since the triggerer orbit/bunch are not set. Then why they are needed? + if (digits.size()) { + auto bcabs = digits[0].getBC(); + auto ir0 = o2::raw::HBFUtils::Instance().getFirstIRofTF({uint16_t(bcabs % Geo::BC_IN_ORBIT), uint32_t(bcabs / Geo::BC_IN_ORBIT)}); + mClusterer.setFirstOrbit(ir0.orbit); + } + auto labelvector = std::make_shared<std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>>(); if (mUseMC) { auto digitlabels = pc.inputs().get<std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>*>("tofdigitlabels"); @@ -101,7 +115,7 @@ class TOFDPLClustererTask mClustersArray.clear(); for (int i = 0; i < row->size(); i++) { - printf("# TOF readout window for clusterization = %d/%lu (N digits = %d)\n", i, row->size(), row->at(i).size()); + //printf("# TOF readout window for clusterization = %d/%lu (N digits = %d)\n", i, row->size(), row->at(i).size()); auto digitsRO = row->at(i).getBunchChannelData(digits); mReader.setDigitArray(&digitsRO); From 24d84fc73a737e4ccce26e29fedd45aead890ded Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 15 Jul 2020 00:11:22 +0200 Subject: [PATCH 0098/1751] DPL Analysis: permit extending Joined tables (#3988) --- Analysis/Tutorials/src/filters.cxx | 19 +++++- Framework/Core/include/Framework/ASoA.h | 64 +++++++++---------- .../Core/include/Framework/AnalysisTask.h | 44 +++++++++---- .../Core/include/Framework/Expressions.h | 5 ++ 4 files changed, 87 insertions(+), 45 deletions(-) diff --git a/Analysis/Tutorials/src/filters.cxx b/Analysis/Tutorials/src/filters.cxx index fb7762708a1e7..e9f19d4c44396 100644 --- a/Analysis/Tutorials/src/filters.cxx +++ b/Analysis/Tutorials/src/filters.cxx @@ -18,9 +18,15 @@ namespace etaphi DECLARE_SOA_COLUMN(NPhi, nphi, float); DECLARE_SOA_EXPRESSION_COLUMN(CosPhi, cosphi, float, ncos(aod::etaphi::nphi)); } // namespace etaphi +namespace track +{ +DECLARE_SOA_EXPRESSION_COLUMN(SPt, spt, float, nabs(aod::track::sigma1Pt / aod::track::signed1Pt)); +} DECLARE_SOA_TABLE(TPhi, "AOD", "TPHI", etaphi::NPhi); DECLARE_SOA_EXTENDED_TABLE_USER(EPhi, TPhi, "EPHI", aod::etaphi::CosPhi); +using etracks = soa::Join<aod::Tracks, aod::TracksCov>; +DECLARE_SOA_EXTENDED_TABLE_USER(MTracks, etracks, "MTRACK", aod::track::SPt); } // namespace o2::aod using namespace o2; @@ -43,6 +49,7 @@ struct ATask { struct BTask { Spawns<aod::EPhi> ephi; + Spawns<aod::MTracks> mtrk; float fPI = static_cast<float>(M_PI); float ptlow = 0.5f; @@ -76,10 +83,20 @@ struct CTask { } }; +struct DTask { + void process(aod::Collision const&, aod::MTracks const& tracks) + { + for (auto& track : tracks) { + LOGF(INFO, "%.3f == %.3f", track.spt(), std::abs(track.sigma1Pt() / track.signed1Pt())); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<ATask>("produce-normalizedphi"), adaptAnalysisTask<BTask>("consume-normalizedphi"), - adaptAnalysisTask<CTask>("consume-spawned")}; + adaptAnalysisTask<CTask>("consume-spawned-ephi"), + adaptAnalysisTask<DTask>("consume-spawned-mtracks")}; } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 604bc73f7cc28..aaeda27c68492 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1232,26 +1232,27 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); #define DECLARE_SOA_TABLE(_Name_, _Origin_, _Description_, ...) \ DECLARE_SOA_TABLE_FULL(_Name_, #_Name_, _Origin_, _Description_, __VA_ARGS__); -#define DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, _Origin_, _Description_, ...) \ - using _Name_ = o2::soa::JoinBase<_Table_, o2::soa::Table<__VA_ARGS__>>; \ - \ - struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ - using table_t = _Name_; \ - using base_table_t = _Table_; \ - using expression_pack_t = framework::pack<__VA_ARGS__>; \ - static constexpr char const* mLabel = #_Name_; \ - static constexpr char const mOrigin[4] = _Origin_; \ - static constexpr char const mDescription[16] = _Description_; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_> { \ - using metadata = _Name_##Metadata; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_::unfiltered_iterator> { \ - using metadata = _Name_##Metadata; \ +#define DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, _Origin_, _Description_, ...) \ + using _Name_ = o2::soa::JoinBase<typename _Table_::table_t, o2::soa::Table<__VA_ARGS__>>; \ + \ + struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ + using table_t = _Name_; \ + using base_table_t = _Table_; \ + using expression_pack_t = framework::pack<__VA_ARGS__>; \ + using originals = soa::originals_pack_t<_Table_>; \ + static constexpr char const* mLabel = #_Name_; \ + static constexpr char const mOrigin[4] = _Origin_; \ + static constexpr char const mDescription[16] = _Description_; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_> { \ + using metadata = _Name_##Metadata; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_::unfiltered_iterator> { \ + using metadata = _Name_##Metadata; \ }; #define DECLARE_SOA_EXTENDED_TABLE(_Name_, _Table_, _Description_, ...) \ @@ -1456,43 +1457,40 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) arrow::TableBatchReader reader(*atable); std::shared_ptr<arrow::RecordBatch> batch; arrow::ArrayVector v; - std::vector<arrow::ArrayVector> chunks(sizeof...(C)); + std::array<arrow::ArrayVector, sizeof...(C)> chunks; auto projectors = framework::expressions::createProjectors(columns, atable->schema()); while (true) { auto s = reader.ReadNext(&batch); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot read batches from table {}", s.ToString())); + throw std::runtime_error(fmt::format("Cannot read batches from table: {}", s.ToString())); } if (batch == nullptr) { break; } s = projectors->Evaluate(*batch, arrow::default_memory_pool(), &v); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot apply projector {}", s.ToString())); + throw std::runtime_error(fmt::format("Cannot apply projector: {}", s.ToString())); } for (auto i = 0u; i < sizeof...(C); ++i) { chunks[i].emplace_back(v.at(i)); } } - std::vector<std::shared_ptr<arrow::ChunkedArray>> arrays(sizeof...(C)); + std::array<std::shared_ptr<arrow::ChunkedArray>, sizeof...(C)> arrays; for (auto i = 0u; i < sizeof...(C); ++i) { arrays[i] = std::make_shared<arrow::ChunkedArray>(chunks[i]); } auto extra_schema = o2::soa::createSchemaFromColumns(columns); - std::vector<std::shared_ptr<arrow::Field>> new_fields; - std::vector<std::shared_ptr<arrow::ChunkedArray>> new_columns; - auto original_columns = atable->columns(); auto original_fields = atable->schema()->fields(); - std::copy(original_fields.begin(), original_fields.end(), std::back_inserter(new_fields)); - std::copy(original_columns.begin(), original_columns.end(), std::back_inserter(new_columns)); - for (auto i = 0u; i < framework::pack_size(columns); ++i) { - new_columns.push_back(arrays[i]); + auto original_columns = atable->columns(); + std::vector<std::shared_ptr<arrow::Field>> new_fields(original_fields); + std::vector<std::shared_ptr<arrow::ChunkedArray>> new_columns(original_columns); + for (auto i = 0u; i < sizeof...(C); ++i) { new_fields.emplace_back(extra_schema->field(i)); + new_columns.push_back(arrays[i]); } - auto new_schema = std::make_shared<arrow::Schema>(new_fields); - return arrow::Table::Make(new_schema, new_columns); + return arrow::Table::Make(std::make_shared<arrow::Schema>(new_fields), new_columns); } } // namespace o2::soa diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index cd3056424216c..1e59d43e5ea51 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -147,26 +147,33 @@ struct Produces<soa::Table<C...>> : WritingCursor<typename soa::FilterPersistent template <typename T> struct Spawns { using metadata = typename aod::MetadataTrait<T>::metadata; - using base_table_t = typename metadata::base_table_t; using expression_pack_t = typename metadata::expression_pack_t; - using base_metadata = typename aod::MetadataTrait<base_table_t>::metadata; + using originals = typename metadata::originals; constexpr expression_pack_t pack() { return expression_pack_t{}; } + template <typename O> InputSpec const base_spec() { + using o_metadata = typename aod::MetadataTrait<O>::metadata; return InputSpec{ - base_metadata::tableLabel(), - header::DataOrigin{base_metadata::origin()}, - header::DataDescription{base_metadata::description()}}; + o_metadata::tableLabel(), + header::DataOrigin{o_metadata::origin()}, + header::DataDescription{o_metadata::description()}}; } - constexpr const char* base_label() + template <typename... Os> + std::vector<InputSpec> const base_specs_impl(framework::pack<Os...>) { - return base_metadata::tableLabel(); + return {base_spec<Os>()...}; + } + + std::vector<InputSpec> const base_specs() + { + return base_specs_impl(originals{}); } OutputSpec const spec() const @@ -948,7 +955,8 @@ struct OutputManager<Spawns<T>> { static bool prepare(ProcessingContext& pc, Spawns<T>& what) { - auto original_table = pc.inputs().get<TableConsumer>(what.base_label())->asArrowTable(); + using metadata = typename std::decay_t<decltype(what)>::metadata; + auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(typename metadata::originals{}, pc)); what.table = std::make_shared<T>(o2::soa::spawner(what.pack(), original_table.get())); return true; } @@ -964,6 +972,18 @@ struct OutputManager<Spawns<T>> { eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); return true; } + + template <typename... Os> + static std::vector<std::shared_ptr<arrow::Table>> extractOriginals(framework::pack<Os...>, ProcessingContext& pc) + { + return {extractOriginal<Os>(pc)...}; + } + + template <typename O> + static auto extractOriginal(ProcessingContext& pc) + { + return pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable(); + } }; template <typename T> @@ -1057,9 +1077,11 @@ template <typename TABLE> struct SpawnManager<Spawns<TABLE>> { static bool requestInputs(std::vector<InputSpec>& inputs, Spawns<TABLE>& spawns) { - auto base_spec = spawns.base_spec(); - if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { - inputs.emplace_back(base_spec); + auto base_specs = spawns.base_specs(); + for (auto& base_spec : base_specs) { + if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { + inputs.emplace_back(base_spec); + } } return true; } diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index c5c5cfb972fb6..28badac8f4c77 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -249,6 +249,11 @@ inline Node operator/(Node left, BindingNode right) return Node{OpNode{BasicOp::Division}, std::move(left), right}; } +inline Node operator/(BindingNode left, BindingNode right) +{ + return Node{OpNode{BasicOp::Division}, left, right}; +} + inline Node operator+(Node left, Node right) { return Node{OpNode{BasicOp::Addition}, std::move(left), std::move(right)}; From 8af6750e2321b429abb572d67943d6b37f4e7955 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 15 Jul 2020 07:58:28 +0200 Subject: [PATCH 0099/1751] DPL: use Tracy rather than custom tracing code (#3991) --- Framework/Core/src/CommonServices.cxx | 2 -- Framework/Core/src/DataProcessingDevice.cxx | 25 ++------------------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index f10691b9379ca..4553e242f04e8 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -329,12 +329,10 @@ o2::framework::ServiceSpec CommonServices::tracingSpec() noConfiguration(), [](ProcessingContext&, void* service) { TracingInfrastructure* t = reinterpret_cast<TracingInfrastructure*>(service); - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_USER_CALLBACK); t->processingCount += 1; }, [](ProcessingContext&, void* service) { TracingInfrastructure* t = reinterpret_cast<TracingInfrastructure*>(service); - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); t->processingCount += 1; }, nullptr, diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index d432941d26d8c..ae578e887eb0e 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -94,23 +94,20 @@ DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegist mServiceRegistry{registry}, mErrorCount{0} { - StateMonitoring<DataProcessingStatus>::start(); - /// FIXME: move erro handling to a service? if (mError != nullptr) { mErrorHandling = [& errorCallback = mError, &serviceRegistry = mServiceRegistry](std::exception& e, InputRecord& record) { - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_ERROR_CALLBACK); + ZoneScopedN("Error handling"); LOG(ERROR) << "Exception caught: " << e.what() << std::endl; serviceRegistry.get<Monitoring>().send({1, "error"}); ErrorContext errorContext{record, serviceRegistry, e}; errorCallback(errorContext); - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); }; } else { mErrorHandling = [& errorPolicy = mErrorPolicy, &serviceRegistry = mServiceRegistry](std::exception& e, InputRecord& record) { - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_ERROR_CALLBACK); + ZoneScopedN("Error handling"); LOG(ERROR) << "Exception caught: " << e.what() << std::endl; serviceRegistry.get<Monitoring>().send({1, "error"}); switch (errorPolicy) { @@ -119,7 +116,6 @@ DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegist default: break; } - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); }; } } @@ -584,14 +580,6 @@ void DataProcessingDevice::handleData(DataProcessorContext& context, FairMQParts // simple lambdas for each of the steps I am planning to have. assert(!context.spec->inputs.empty()); - // These duplicate references are created so that each function - // does not need to know about the whole class state, but I can - // fine grain control what is exposed at each state. - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); - auto metricFlusher = make_scope_guard([]() noexcept { - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); - }); - enum struct InputType { Invalid, Data, @@ -732,15 +720,6 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, // should work just fine. std::vector<MessageSet> currentSetOfInputs; - // These duplicate references are created so that each function - // does not need to know about the whole class state, but I can - // fine grain control what is exposed at each state. - // FIXME: I should use a different id for this state. - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); - auto metricFlusher = make_scope_guard([]() noexcept -> void { - StateMonitoring<DataProcessingStatus>::moveTo(DataProcessingStatus::IN_DPL_OVERHEAD); - }); - auto reportError = [& registry = *context.registry, &context](const char* message) { context.errorCount++; registry.get<Monitoring>().send(Metric{*context.errorCount, "errors"}.addTag(Key::Subsystem, Value::DPL)); From 221d3de3318dc6d9ef6cee4e0b454ca67b2cecc1 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Thu, 9 Jul 2020 21:53:47 -0300 Subject: [PATCH 0100/1751] Cleanup TrackExtrap, improve seed, optimal default parameter --- .../include/MFTTracking/MFTTrackingParam.h | 2 +- .../ITSMFT/MFT/tracking/src/TrackExtrap.cxx | 241 ++++++++++-------- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 8 +- 3 files changed, 138 insertions(+), 113 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h index 6ac8d87a8a885..9b5e635bbf4fa 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h @@ -39,7 +39,7 @@ enum MFTTrackModel { struct MFTTrackingParam : public o2::conf::ConfigurableParamHelper<MFTTrackingParam> { Int_t seed = MFTTrackingSeed::DH; Int_t trackmodel = MFTTrackModel::Helix; - double sigmaboost = 1e0; + double sigmaboost = 1e3; double seedH_k = 1.0; double MFTRadLenghts = 0.041; // MFT average material budget within acceptance bool verbose = false; diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx index eb6d5e8e285da..3ec7d37c35265 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx @@ -43,16 +43,16 @@ void TrackExtrap::linearExtrapToZ(TrackParamMFT* trackParam, double zEnd) } // Compute track parameters - double dZ = (zEnd - trackParam->getZ()); - double x0 = trackParam->getX(); - double y0 = trackParam->getY(); - double phi0 = trackParam->getPhi(); + auto dZ = (zEnd - trackParam->getZ()); + auto x0 = trackParam->getX(); + auto y0 = trackParam->getY(); + auto phi0 = trackParam->getPhi(); double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); - double invtanl0 = 1.0 / trackParam->getTanl(); - double n = dZ * invtanl0; - double x = x0 + n * cosphi0; - double y = y0 + n * sinphi0; + auto invtanl0 = 1.0 / trackParam->getTanl(); + auto n = dZ * invtanl0; + auto x = x0 + n * cosphi0; + auto y = y0 + n * sinphi0; trackParam->setX(x); trackParam->setY(y); trackParam->setZ(zEnd); @@ -65,20 +65,23 @@ void TrackExtrap::linearExtrapToZCov(TrackParamMFT* trackParam, double zEnd, boo /// On return, results from the extrapolation are updated in trackParam. // Calculate the jacobian related to the track parameters extrapolated to "zEnd" - double dZ = (zEnd - trackParam->getZ()); - double phi0 = trackParam->getPhi(); - double tanl0 = trackParam->getTanl(); - double invtanl0 = 1.0 / tanl0; - // double invqpt0 = trackParam->getInvQPt(); + auto dZ = (zEnd - trackParam->getZ()); + auto x0 = trackParam->getX(); + auto y0 = trackParam->getY(); + auto phi0 = trackParam->getPhi(); + auto tanl0 = trackParam->getTanl(); + auto invtanl0 = 1.0 / tanl0; double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); - // double k = TMath::Abs(o2::constants::math::B2C * getBz()); - double n = dZ * invtanl0; - double m = n * invtanl0; - // double theta = -invqpt0 * dZ * k * invtanl0; - // auto Hz = getSignBz(); + auto n = dZ * invtanl0; + auto m = n * invtanl0; - linearExtrapToZ(trackParam, zEnd); + // Extrapolate track parameters to "zEnd" + auto x = x0 + n * cosphi0; + auto y = y0 + n * sinphi0; + trackParam->setX(x); + trackParam->setY(y); + trackParam->setZ(zEnd); // Calculate Jacobian TMatrixD jacob(5, 5); @@ -110,24 +113,21 @@ void TrackExtrap::quadraticExtrapToZ(TrackParamMFT* trackParam, double zEnd) } // Compute track parameters - double dZ = (zEnd - trackParam->getZ()); - double x0 = trackParam->getX(); - double y0 = trackParam->getY(); - double phi0 = trackParam->getPhi(); + auto dZ = (zEnd - trackParam->getZ()); + auto x0 = trackParam->getX(); + auto y0 = trackParam->getY(); + auto phi0 = trackParam->getPhi(); double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); - double invtanl0 = 1.0 / trackParam->getTanl(); - double invqpt0 = trackParam->getInvQPt(); + auto invtanl0 = 1.0 / trackParam->getTanl(); + auto invqpt0 = trackParam->getInvQPt(); auto Hz = getSignBz(); - double k = TMath::Abs(o2::constants::math::B2C * getBz()); - double n = dZ * invtanl0; - double theta = -invqpt0 * dZ * k * invtanl0; - double deltax = n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; - double deltay = n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; - - double x = x0 + deltax; - double y = y0 + deltay; - double phi = phi0 + Hz * theta; + auto k = TMath::Abs(o2::constants::math::B2C * getBz()); + auto n = dZ * invtanl0; + auto theta = -invqpt0 * dZ * k * invtanl0; + auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; + auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; + auto phi = phi0 + Hz * theta; trackParam->setX(x); trackParam->setY(y); @@ -136,62 +136,37 @@ void TrackExtrap::quadraticExtrapToZ(TrackParamMFT* trackParam, double zEnd) } //__________________________________________________________________________ -void TrackExtrap::helixExtrapToZ(TrackParamMFT* trackParam, double zEnd) +void TrackExtrap::quadraticExtrapToZCov(TrackParamMFT* trackParam, double zEnd, bool updatePropagator) { - /// Track parameters extrapolated to the plane at "zEnd" considering a helix - /// On return, results from the extrapolation are updated in trackParam. + // Extrapolate track parameters and covariances matrix to "zEnd" if (trackParam->getZ() == zEnd) { return; // nothing to be done if same z } // Compute track parameters - double dZ = (zEnd - trackParam->getZ()); - double x0 = trackParam->getX(); - double y0 = trackParam->getY(); - double px0 = trackParam->getPx(); - double py0 = trackParam->getPy(); - double invtanl0 = 1.0 / trackParam->getTanl(); - double invqpt0 = trackParam->getInvQPt(); - auto q = trackParam->getCharge(); + auto dZ = (zEnd - trackParam->getZ()); + auto x0 = trackParam->getX(); + auto y0 = trackParam->getY(); + auto phi0 = trackParam->getPhi(); + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto invtanl0 = 1.0 / trackParam->getTanl(); + auto invqpt0 = trackParam->getInvQPt(); auto Hz = getSignBz(); - double k = TMath::Abs(o2::constants::math::B2C * getBz()); - auto invk = 1.0 / k; - double theta = -invqpt0 * dZ * k * invtanl0; - double costheta, sintheta; - o2::utils::sincos(theta, sintheta, costheta); - double deltax = Hz * py0 * invk * (1.0 - costheta) - px0 * q * invk * sintheta; - double deltay = -Hz * px0 * invk * (1.0 - costheta) - py0 * q * invk * sintheta; - - double x = x0 + deltax; - double y = y0 + deltay; - double phi = trackParam->getPhi() + Hz * theta; + auto k = TMath::Abs(o2::constants::math::B2C * getBz()); + auto n = dZ * invtanl0; + auto m = n * invtanl0; + auto theta = -invqpt0 * dZ * k * invtanl0; + // Extrapolate track parameters to "zEnd" + auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; + auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; + auto phi = phi0 + Hz * theta; trackParam->setX(x); trackParam->setY(y); trackParam->setZ(zEnd); trackParam->setPhi(phi); -} - -//__________________________________________________________________________ -void TrackExtrap::quadraticExtrapToZCov(TrackParamMFT* trackParam, double zEnd, bool updatePropagator) -{ - - // Calculate the jacobian related to the track parameters extrapolated to "zEnd" - double dZ = (zEnd - trackParam->getZ()); - double phi0 = trackParam->getPhi(); - double tanl0 = trackParam->getTanl(); - double invtanl0 = 1.0 / tanl0; - double invqpt0 = trackParam->getInvQPt(); - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - double k = TMath::Abs(o2::constants::math::B2C * getBz()); - double n = dZ * invtanl0; - double m = n * invtanl0; - double theta = -invqpt0 * dZ * k * invtanl0; - auto Hz = getSignBz(); - - quadraticExtrapToZ(trackParam, zEnd); // Calculate Jacobian TMatrixD jacob(5, 5); @@ -216,22 +191,68 @@ void TrackExtrap::quadraticExtrapToZCov(TrackParamMFT* trackParam, double zEnd, } } +//__________________________________________________________________________ +void TrackExtrap::helixExtrapToZ(TrackParamMFT* trackParam, double zEnd) +{ + /// Track parameters extrapolated to the plane at "zEnd" considering a helix + /// On return, results from the extrapolation are updated in trackParam. + + if (trackParam->getZ() == zEnd) { + return; // nothing to be done if same z + } + + // Compute track parameters + auto dZ = (zEnd - trackParam->getZ()); + auto x0 = trackParam->getX(); + auto y0 = trackParam->getY(); + auto phi0 = trackParam->getPhi(); + auto tanl0 = trackParam->getTanl(); + auto invtanl0 = 1.0 / tanl0; + auto invqpt0 = trackParam->getInvQPt(); + auto qpt0 = 1.0 / invqpt0; + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto k = TMath::Abs(o2::constants::math::B2C * getBz()); + auto invk = 1.0 / k; + auto theta = -invqpt0 * dZ * k * invtanl0; + double costheta, sintheta; + o2::utils::sincos(theta, sintheta, costheta); + auto Hz = getSignBz(); + auto Y = sinphi0 * qpt0 * invk; + auto X = cosphi0 * qpt0 * invk; + auto YC = Y * costheta; + auto YS = Y * sintheta; + auto XC = X * costheta; + auto XS = X * sintheta; + + // Extrapolate track parameters to "zEnd" + auto x = x0 + Hz * (Y - YC) - XS; + auto y = y0 + Hz * (-X + XC) - YS; + auto phi = phi0 + Hz * theta; + trackParam->setX(x); + trackParam->setY(y); + trackParam->setZ(zEnd); + trackParam->setPhi(phi); +} + //__________________________________________________________________________ void TrackExtrap::helixExtrapToZCov(TrackParamMFT* trackParam, double zEnd, bool updatePropagator) { - // Calculate the jacobian related to the track parameters extrapolated to "zEnd" - double dZ = (zEnd - trackParam->getZ()); - double phi0 = trackParam->getPhi(); - double tanl0 = trackParam->getTanl(); - double invtanl0 = 1.0 / tanl0; - double invqpt0 = trackParam->getInvQPt(); + // Extrapolate track parameters and covariances matrix to "zEnd" + auto dZ = (zEnd - trackParam->getZ()); + auto x0 = trackParam->getX(); + auto y0 = trackParam->getY(); + auto phi0 = trackParam->getPhi(); + auto tanl0 = trackParam->getTanl(); + auto invtanl0 = 1.0 / tanl0; + auto invqpt0 = trackParam->getInvQPt(); auto qpt0 = 1.0 / invqpt0; double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); - double k = TMath::Abs(o2::constants::math::B2C * getBz()); - double invk = 1.0 / k; - double theta = -invqpt0 * dZ * k * invtanl0; + auto k = TMath::Abs(o2::constants::math::B2C * getBz()); + auto invk = 1.0 / k; + auto theta = -invqpt0 * dZ * k * invtanl0; double costheta, sintheta; o2::utils::sincos(theta, sintheta, costheta); auto Hz = getSignBz(); @@ -250,11 +271,17 @@ void TrackExtrap::helixExtrapToZCov(TrackParamMFT* trackParam, double zEnd, bool auto T = qpt0 * costheta; auto U = qpt0 * sintheta; auto V = qpt0; - double n = dZ * invtanl0; - double m = n * invtanl0; + auto n = dZ * invtanl0; + auto m = n * invtanl0; // Extrapolate track parameters to "zEnd" - helixExtrapToZ(trackParam, zEnd); + auto x = x0 + Hz * (Y - YC) - XS; + auto y = y0 + Hz * (-X + XC) - YS; + auto phi = phi0 + Hz * theta; + trackParam->setX(x); + trackParam->setY(y); + trackParam->setZ(zEnd); + trackParam->setPhi(phi); // Calculate Jacobian TMatrixD jacob(5, 5); @@ -334,20 +361,20 @@ void TrackExtrap::addMCSEffect(TrackParamMFT* trackParam, double dZ, double x0) /// All scattering evaluated happens at the position of the first cluster bool debug = false; - double phi0 = trackParam->getPhi(); - double tanl0 = trackParam->getTanl(); - double invtanl0 = 1.0 / tanl0; - double invqpt0 = trackParam->getInvQPt(); - double p = trackParam->getP(); + auto phi0 = trackParam->getPhi(); + auto tanl0 = trackParam->getTanl(); + auto invtanl0 = 1.0 / tanl0; + auto invqpt0 = trackParam->getInvQPt(); + auto p = trackParam->getP(); double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); - double csclambda = TMath::Abs(TMath::Sqrt(1 + tanl0 * tanl0) * invtanl0); - double pathLengthOverX0 = x0 * csclambda; + auto csclambda = TMath::Abs(TMath::Sqrt(1 + tanl0 * tanl0) * invtanl0); + auto pathLengthOverX0 = x0 * csclambda; // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory - double sigmathetasq = 0.0136 * invqpt0 * (1 + 0.038 * TMath::Log(pathLengthOverX0)); + auto sigmathetasq = 0.0136 * invqpt0 * (1 + 0.038 * TMath::Log(pathLengthOverX0)); sigmathetasq *= sigmathetasq * pathLengthOverX0; // Get covariance matrix @@ -358,14 +385,14 @@ void TrackExtrap::addMCSEffect(TrackParamMFT* trackParam, double dZ, double x0) } if (dZ > 0) { - double A = tanl0 * tanl0 + 1; - double B = dZ * cosphi0 * invtanl0; - double C = dZ * sinphi0 * invtanl0; - double D = A * B * invtanl0; - double E = -A * C * invtanl0; - double F = -C - D; - double G = B + E; - double H = -invqpt0 * tanl0; + auto A = tanl0 * tanl0 + 1; + auto B = dZ * cosphi0 * invtanl0; + auto C = dZ * sinphi0 * invtanl0; + auto D = A * B * invtanl0; + auto E = -A * C * invtanl0; + auto F = -C - D; + auto G = B + E; + auto H = -invqpt0 * tanl0; newParamCov(0, 0) += sigmathetasq * F * F; @@ -408,8 +435,8 @@ void TrackExtrap::addMCSEffect(TrackParamMFT* trackParam, double dZ, double x0) newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; } else { - double A = tanl0 * tanl0 + 1; - double H = -invqpt0 * tanl0; + auto A = tanl0 * tanl0 + 1; + auto H = -invqpt0 * tanl0; newParamCov(2, 2) += sigmathetasq; diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 418cf3f8232cd..5025d1eb31fea 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -183,24 +183,22 @@ void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) std::cout << " Init track with Seed D.\n"; break; } - if (mftTrackingParam.verbose) { auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; std::cout << "Track Model: " << model << std::endl; - std::cout << "initTrack Cluster X = " << x0 << " Y = " << y0 << " Z = " << z0 << std::endl; - std::cout << " seed Phi, Tanl, InvQpt = " << param.getPhi() << " " << param.getTanl() << " " << param.getInvQPt() << std::endl; + std::cout << " initTrack: X = " << cl.getX() << " Y = " << cl.getY() << " Z = " << cl.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; } // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) TMatrixD lastParamCov(5, 5); lastParamCov.Zero(); - lastParamCov(0, 0) = sigmaboost * sigmax0sq; // <X,X> + lastParamCov(0, 0) = sigmax0sq; // <X,X> lastParamCov(0, 1) = 0; // <Y,X> lastParamCov(0, 2) = sigmaboost * -sigmax0sq * y0 * invr0sq; // <PHI,X> lastParamCov(0, 3) = sigmaboost * -z0 * sigmax0sq * x0 * invr0cu; // <TANL,X> lastParamCov(0, 4) = sigmaboost * -x0 * sigmax0sq * invr0cu; // <INVQPT,X> - lastParamCov(1, 1) = sigmaboost * sigmay0sq; // <Y,Y> + lastParamCov(1, 1) = sigmay0sq; // <Y,Y> lastParamCov(1, 2) = sigmaboost * sigmay0sq * x0 * invr0sq; // <PHI,Y> lastParamCov(1, 3) = sigmaboost * -z0 * sigmay0sq * y0 * invr0cu; // <TANL,Y> lastParamCov(1, 4) = sigmaboost * y0 * sigmay0sq * invr0cu; //1e-2; // <INVQPT,Y> From 74c9291246bd46a9d24f7e525a392c5d288ec15b Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Sat, 11 Jul 2020 14:47:50 -0300 Subject: [PATCH 0101/1751] Enabling Smoother; Store MFT Track parameters anc covariances at last cluster --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 23 +++++++++++++++++++ .../Detectors/ITSMFT/MFT/src/TrackMFT.cxx | 13 +++++++++++ .../MFT/workflow/src/TrackFitterSpec.cxx | 8 +++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index 9ce67d44855d8..64fe847f32164 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -106,6 +106,7 @@ class TrackMFT /// return track parameters const SMatrix5& getParameters() const { return mParameters; } + /// set track parameters void setParameters(const SMatrix5& parameters) { mParameters = parameters; } @@ -159,6 +160,24 @@ class TrackMFT // Extrapolate this track to void extrapHelixToZ(double zEnd, double Field); + // Parameters and Covariances on last track clusters + const SMatrix5& getParametersLast() const { return mParametersLast; } + void setParametersLast(const SMatrix5& parameters) { mParametersLast = parameters; } // Last cluster + const SMatrix55& getCovariancesLast() const; + void setCovariancesLast(const SMatrix55& covariances); + + Double_t getZLast() const { return mZLast; } + void setZLast(Double_t z) { mZLast = z; } + Double_t getXLast() const { return mParametersLast(0); } + Double_t getYLast() const { return mParametersLast(1); } + Double_t getPhiLast() const { return mParametersLast(2); } + Double_t getTanlLast() const { return mParametersLast(3); } + Double_t getInvQPtLast() const { return mParametersLast(4); } + Double_t getPtLast() const { return TMath::Abs(1.f / mParametersLast(4)); } + Double_t getInvPtLast() const { return TMath::Abs(mParametersLast(4)); } + Double_t getPLast() const { return getPtLast() * TMath::Sqrt(1. + getTanlLast() * getTanlLast()); } // return total momentum last cluster + Double_t getEtaLast() const { return -TMath::Log(TMath::Tan((TMath::PiOver2() - TMath::ATan(getTanlLast())) / 2)); } // return total momentum + private: std::uint32_t mROFrame = 0; ///< RO Frame Int_t mNPoints{0}; // Number of clusters @@ -167,6 +186,7 @@ class TrackMFT ClusRefs mClusRef; ///< references on clusters Double_t mZ = 0.; ///< Z coordinate (cm) + Double_t mZLast = 0.; ///< Z coordinate (cm) of Last cluster /// Track parameters ordered as follow: <pre> /// X = X coordinate (cm) @@ -175,6 +195,7 @@ class TrackMFT /// TANL = tangent of \lambda (dip angle) /// INVQPT = Inverse transverse momentum (GeV/c ** -1) times charge (assumed forward motion) </pre> SMatrix5 mParameters; ///< \brief Track parameters + SMatrix5 mParametersLast; ///< \brief Track parameters at last cluster /// Covariance matrix of track parameters, ordered as follows: <pre> /// <X,X> <Y,X> <PHI,X> <TANL,X> <INVQPT,X> @@ -183,6 +204,8 @@ class TrackMFT /// <X,TANL> <Y,TANL> <PHI,TANL> <TANL,TANL> <INVQPT,TANL> /// <X,INVQPT> <Y,INVQPT> <PHI,INVQPT> <TANL,INVQPT> <INVQPT,INVQPT> </pre> SMatrix55 mCovariances; ///< \brief Covariance matrix of track parameters + SMatrix55 mCovariancesLast; ///< \brief Covariance matrix of track parameters at last cluster + Double_t mTrackChi2 = 0.; ///< Chi2 of the track when the associated cluster was attached // Results from quadratic regression of clusters X,Y positions diff --git a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx index 9661919be665f..ef9219b5fafa6 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx +++ b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx @@ -54,6 +54,19 @@ void TrackMFT::setCovariances(const SMatrix55& covariances) mCovariances = covariances; } +//__________________________________________________________________________ +const SMatrix55& TrackMFT::getCovariancesLast() const +{ + /// Return the covariance matrix for last cluster + return mCovariancesLast; +} + +//__________________________________________________________________________ +void TrackMFT::setCovariancesLast(const SMatrix55& covariances) +{ + mCovariancesLast = covariances; +} + //_________________________________________________________________________________________________ void TrackMFT::extrapHelixToZ(double zEnd, double Field) { diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx index ca4046a33dca9..0a840be5fbb77 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx @@ -48,6 +48,7 @@ void TrackFitterTask::init(InitContext& ic) /// Prepare the track extrapolation tools LOG(INFO) << "initializing track fitter"; mTrackFitter = std::make_unique<o2::mft::TrackFitter>(); + mTrackFitter->smoothTracks(true); auto filename = ic.options().get<std::string>("grp-file"); const auto grp = o2::parameters::GRPObject::loadFrom(filename.c_str()); @@ -87,14 +88,14 @@ void TrackFitterTask::run(ProcessingContext& pc) for (const auto& track : tracksLTF) { auto& temptrack = fittertracks.at(nTracksLTF + nFailedTracksLTF); convertTrack(track, temptrack, clusters); - mTrackFitter->fit(temptrack, false) ? nTracksLTF++ : nFailedTracksLTF++; + mTrackFitter->fit(temptrack, true, true) ? nTracksLTF++ : nFailedTracksLTF++; } // end fit LTF tracks // Fit CA tracks for (const auto& track : tracksCA) { auto& temptrack = fittertracks.at(nTracksLTF + nFailedTracksLTF + nTracksCA + nFailedTracksCA); convertTrack(track, temptrack, clusters); - mTrackFitter->fit(temptrack, false) ? nTracksCA++ : nFailedTracksCA++; + mTrackFitter->fit(temptrack, true, true) ? nTracksCA++ : nFailedTracksCA++; } // end fit CA tracks auto& finalMFTtracks = pc.outputs().make<std::vector<o2::mft::TrackMFT>>(Output{"MFT", "TRACKS", 0, Lifetime::Timeframe}); @@ -106,8 +107,11 @@ void TrackFitterTask::run(ProcessingContext& pc) if (!track.isRemovable()) { auto& temptrack = finalMFTtracks.at(nTotalTracks); temptrack.setZ(track.first().getZ()); + temptrack.setZLast(track.rbegin()->getZ()); temptrack.setParameters(TtoSMatrix5(track.first().getParameters())); + temptrack.setParametersLast(TtoSMatrix5(track.rbegin()->getParameters())); temptrack.setCovariances(TtoSMatrixSym55(track.first().getCovariances())); + temptrack.setCovariancesLast(TtoSMatrixSym55(track.rbegin()->getCovariances())); temptrack.setTrackChi2(track.first().getTrackChi2()); temptrack.setMCCompLabels(track.getMCCompLabels(), track.getNPoints()); temptrack.setInvQPtQuadtratic(track.getInvQPtQuadtratic()); From d741ae2f7b7682f87d79f745a27efea5528e872a Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Mon, 13 Jul 2020 14:16:24 -0300 Subject: [PATCH 0102/1751] Register track finding method on fitted MFTTracks --- .../Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h | 6 ++++++ .../MFT/tracking/include/MFTTracking/FitterTrackMFT.h | 6 ++++++ Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx | 2 +- Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx | 3 ++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index 64fe847f32164..fc3be31299ca7 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -47,6 +47,11 @@ class TrackMFT ~TrackMFT() = default; + // Track finding method + void setCA(Bool_t method) { mIsCA = method; } + const Bool_t isCA() const { return mIsCA; } + const Bool_t isLTF() const { return !mIsCA; } + /// return Z coordinate (cm) Double_t getZ() const { return mZ; } /// set Z coordinate (cm) @@ -182,6 +187,7 @@ class TrackMFT std::uint32_t mROFrame = 0; ///< RO Frame Int_t mNPoints{0}; // Number of clusters std::array<MCCompLabel, 10> mMCCompLabels; // constants::mft::LayersNumber = 10 + Bool_t mIsCA = false; // Track finding method CA vs. LTF ClusRefs mClusRef; ///< references on clusters diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h index d3a05bb70e637..d0e32b02e7f8f 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h @@ -104,6 +104,11 @@ class FitterTrackMFT const Int_t getNPoints() const { return mNPoints; } + // Track finding method + void setCA(Bool_t method) { mIsCA = method; } + const Bool_t isCA() const { return mIsCA; } + const Bool_t isLTF() const { return !mIsCA; } + // Charge and momentum from quadratic regression of clusters X,Y positions void setInvQPtQuadtratic(Double_t invqpt) { mInvQPtQuadtratic = invqpt; } const Double_t getInvQPtQuadtratic() const { return mInvQPtQuadtratic; } // Inverse charged pt @@ -121,6 +126,7 @@ class FitterTrackMFT bool mRemovable = false; ///< flag telling if this track should be deleted Int_t mNPoints{0}; // Number of clusters std::array<MCCompLabel, 10> mMCCompLabels; // constants::mft::LayersNumber = 10 + Bool_t mIsCA = false; // Track finding method CA vs. LTF // Results from quadratic regression of clusters X,Y positions // Chi2 of the quadratic regression used to estimate track pT and charge diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 5025d1eb31fea..a3d086d7a726d 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -186,7 +186,7 @@ void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) if (mftTrackingParam.verbose) { auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; std::cout << "Track Model: " << model << std::endl; - std::cout << " initTrack: X = " << cl.getX() << " Y = " << cl.getY() << " Z = " << cl.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; + std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; } // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx index 0a840be5fbb77..0c33a61ca22d5 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx @@ -95,6 +95,7 @@ void TrackFitterTask::run(ProcessingContext& pc) for (const auto& track : tracksCA) { auto& temptrack = fittertracks.at(nTracksLTF + nFailedTracksLTF + nTracksCA + nFailedTracksCA); convertTrack(track, temptrack, clusters); + temptrack.setCA(true); mTrackFitter->fit(temptrack, true, true) ? nTracksCA++ : nFailedTracksCA++; } // end fit CA tracks @@ -116,7 +117,7 @@ void TrackFitterTask::run(ProcessingContext& pc) temptrack.setMCCompLabels(track.getMCCompLabels(), track.getNPoints()); temptrack.setInvQPtQuadtratic(track.getInvQPtQuadtratic()); temptrack.setChi2QPtQuadtratic(track.getChi2QPtQuadtratic()); - //finalMFTtracks.back().printMCCompLabels(); + temptrack.setCA(track.isCA()); nTotalTracks++; } } From 3d5affd84348d1833e4df99bc8bf537edc1e61ad Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 13 Jul 2020 02:11:07 +0200 Subject: [PATCH 0103/1751] Add FT0 CTF reading and writing * Rename and move FT0-related workflows/specs from FIT/workflow to FIT/FT0/workflow * Add separate FT0 digits reader workflow * CTF class for FT0, encoder/decoder and reader/writer --- DataFormats/Detectors/FIT/FT0/CMakeLists.txt | 4 +- .../FIT/FT0/include/DataFormatsFT0/CTF.h | 81 ++++++++ .../FIT/FT0/include/DataFormatsFT0/Digit.h | 32 ++-- DataFormats/Detectors/FIT/FT0/src/CTF.cxx | 34 ++++ .../FIT/FT0/src/DataFormatsFT0LinkDef.h | 5 + Detectors/CTF/workflow/CMakeLists.txt | 1 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 + Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 11 ++ .../CTF/workflow/src/ctf-reader-workflow.cxx | 14 +- .../CTF/workflow/src/ctf-writer-workflow.cxx | 3 - Detectors/FIT/CMakeLists.txt | 1 - Detectors/FIT/FT0/CMakeLists.txt | 1 + .../FIT/FT0/reconstruction/CMakeLists.txt | 4 + .../include/FT0Reconstruction/CTFCoder.h | 174 ++++++++++++++++++ .../FIT/FT0/reconstruction/src/CTFCoder.cxx | 97 ++++++++++ .../src/FT0ReconstructionLinkDef.h | 1 + Detectors/FIT/FT0/workflow/CMakeLists.txt | 43 +++++ .../include/FT0Workflow/DigitReaderSpec.h | 45 +++++ .../include/FT0Workflow/EntropyDecoderSpec.h | 44 +++++ .../include/FT0Workflow/EntropyEncoderSpec.h | 44 +++++ .../include/FT0Workflow/RecPointReaderSpec.h} | 4 +- .../include/FT0Workflow/RecPointWriterSpec.h} | 5 +- .../include/FT0Workflow}/RecoWorkflow.h | 0 .../include/FT0Workflow/ReconstructionSpec.h} | 10 +- .../FIT/FT0/workflow/src/DigitReaderSpec.cxx | 91 +++++++++ .../FT0/workflow/src/EntropyDecoderSpec.cxx | 72 ++++++++ .../FT0/workflow/src/EntropyEncoderSpec.cxx | 71 +++++++ .../workflow/src/RecPointReaderSpec.cxx} | 6 +- .../workflow/src/RecPointWriterSpec.cxx} | 6 +- .../{ => FT0}/workflow/src/RecoWorkflow.cxx | 14 +- .../workflow/src/ReconstructionSpec.cxx} | 16 +- .../workflow/src/digits-reader-workflow.cxx | 45 +++++ .../workflow/src/entropy-encoder-workflow.cxx | 39 ++++ .../workflow/src/ft0-reco-workflow.cxx} | 2 +- Detectors/FIT/workflow/CMakeLists.txt | 25 --- .../include/FITWorkflow/FT0DigitReaderSpec.h | 62 ------- .../FIT/workflow/src/FT0DigitReaderSpec.cxx | 109 ----------- .../GlobalTrackingWorkflow/CMakeLists.txt | 2 +- .../src/MatchTPCITSWorkflow.cxx | 4 +- .../tofworkflow/CMakeLists.txt | 2 +- .../tofworkflow/src/tof-reco-workflow.cxx | 4 +- 41 files changed, 976 insertions(+), 260 deletions(-) create mode 100644 DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h create mode 100644 DataFormats/Detectors/FIT/FT0/src/CTF.cxx create mode 100644 Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h create mode 100644 Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx create mode 100644 Detectors/FIT/FT0/workflow/CMakeLists.txt create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/DigitReaderSpec.h create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h rename Detectors/FIT/{workflow/include/FITWorkflow/FT0RecPointReaderSpec.h => FT0/workflow/include/FT0Workflow/RecPointReaderSpec.h} (93%) rename Detectors/FIT/{workflow/include/FITWorkflow/FT0RecPointWriterSpec.h => FT0/workflow/include/FT0Workflow/RecPointWriterSpec.h} (87%) rename Detectors/FIT/{workflow/include/FITWorkflow => FT0/workflow/include/FT0Workflow}/RecoWorkflow.h (100%) rename Detectors/FIT/{workflow/include/FITWorkflow/FT0ReconstructorSpec.h => FT0/workflow/include/FT0Workflow/ReconstructionSpec.h} (83%) create mode 100644 Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx create mode 100644 Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx rename Detectors/FIT/{workflow/src/FT0RecPointReaderSpec.cxx => FT0/workflow/src/RecPointReaderSpec.cxx} (95%) rename Detectors/FIT/{workflow/src/FT0RecPointWriterSpec.cxx => FT0/workflow/src/RecPointWriterSpec.cxx} (93%) rename Detectors/FIT/{ => FT0}/workflow/src/RecoWorkflow.cxx (68%) rename Detectors/FIT/{workflow/src/FT0ReconstructorSpec.cxx => FT0/workflow/src/ReconstructionSpec.cxx} (87%) create mode 100644 Detectors/FIT/FT0/workflow/src/digits-reader-workflow.cxx create mode 100644 Detectors/FIT/FT0/workflow/src/entropy-encoder-workflow.cxx rename Detectors/FIT/{workflow/src/fit-reco-workflow.cxx => FT0/workflow/src/ft0-reco-workflow.cxx} (98%) delete mode 100644 Detectors/FIT/workflow/CMakeLists.txt delete mode 100644 Detectors/FIT/workflow/include/FITWorkflow/FT0DigitReaderSpec.h delete mode 100644 Detectors/FIT/workflow/src/FT0DigitReaderSpec.cxx diff --git a/DataFormats/Detectors/FIT/FT0/CMakeLists.txt b/DataFormats/Detectors/FIT/FT0/CMakeLists.txt index 05db031ba9ae6..787af014d4242 100644 --- a/DataFormats/Detectors/FIT/FT0/CMakeLists.txt +++ b/DataFormats/Detectors/FIT/FT0/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library(DataFormatsFT0 SOURCES src/ChannelData.cxx SOURCES src/RecPoints.cxx SOURCES src/RawEventData.cxx + src/CTF.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::SimulationDataFormat O2::FT0Base ) @@ -26,4 +27,5 @@ o2_target_root_dictionary(DataFormatsFT0 include/DataFormatsFT0/MCLabel.h include/DataFormatsFT0/HitType.h include/DataFormatsFT0/RawEventData.h - include/DataFormatsFT0/LookUpTable.h ) + include/DataFormatsFT0/LookUpTable.h + include/DataFormatsFT0/CTF.h) diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h new file mode 100644 index 0000000000000..6df5bc3dddaf6 --- /dev/null +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h @@ -0,0 +1,81 @@ +// 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 CTF.h +/// \author ruben.shahoyan@cern.ch +/// \brief Definitions for FT0 CTF data + +#ifndef O2_FT0_CTF_H +#define O2_FT0_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" + +namespace o2 +{ +namespace ft0 +{ + +/// Header for a single CTF +struct CTFHeader { + uint32_t nTriggers = 0; /// number of truggers in TF + uint32_t firstOrbit = 0; /// 1st orbit of TF + uint16_t firstBC = 0; /// 1st BC of TF + + ClassDefNV(CTFHeader, 1); +}; + +/// Intermediate, compressed but not yet entropy-encoded digits +struct CompressedDigits { + + CTFHeader header; + + // trigger data + std::vector<uint8_t> trigger; // trigger bits + std::vector<uint16_t> bcInc; // increment in BC if the same orbit, otherwise abs bc + std::vector<uint32_t> orbitInc; // increment in orbit + std::vector<uint8_t> nChan; // number of fired channels + + // channel data + std::vector<uint8_t> idChan; // channels ID: 1st on absolute, then increment + std::vector<int16_t> cfdTime; // CFD time + std::vector<uint32_t> qtcAmpl; // Amplitude + std::vector<uint8_t> qtc; // QTC + + CompressedDigits() = default; + + void clear(); + + ClassDefNV(CompressedDigits, 1); +}; + +/// wrapper for the Entropy-encoded clusters of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 8, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { + BLC_trigger, // trigger bits + BLC_bcInc, // increment in BC + BLC_orbitInc, // increment in orbit + BLC_nChan, // number of fired channels + BLC_idChan, // channels ID: 1st on absolute, then increment + BLC_qtc, // QTC + BLC_cfdTime, // CFD time + BLC_qtcAmpl + }; // Amplitude + + ClassDefNV(CTF, 1); +}; + +} // namespace ft0 +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h index 2ca2098a4ad5e..74f5c6ed596bb 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h @@ -36,13 +36,13 @@ struct Triggers { bitVertex, bitCen, bitSCen }; - uint8_t triggersignals; // T0 trigger signals - int8_t nChanA; // number of faired channels A side - int8_t nChanC; // number of faired channels A side - int32_t amplA; // sum amplitude A side - int32_t amplC; // sum amplitude C side - int16_t timeA; // average time A side - int16_t timeC; // average time C side + uint8_t triggersignals = 0; // T0 trigger signals + int8_t nChanA = 0; // number of fired channels A side + int8_t nChanC = 0; // number of fired channels A side + int32_t amplA = -1000; // sum amplitude A side + int32_t amplC = -1000; // sum amplitude C side + int16_t timeA = -1000; // average time A side + int16_t timeC = -1000; // average time C side Triggers() = default; Triggers(uint8_t signals, int8_t chanA, int8_t chanC, int32_t aamplA, int32_t aamplC, int16_t atimeA, int16_t atimeC) { @@ -54,11 +54,11 @@ struct Triggers { timeA = atimeA; timeC = atimeC; } - bool getOrA() { return (triggersignals & (1 << bitA)) != 0; } - bool getOrC() { return (triggersignals & (1 << bitC)) != 0; } - bool getVertex() { return (triggersignals & (1 << bitVertex)) != 0; } - bool getCen() { return (triggersignals & (1 << bitCen)) != 0; } - bool getSCen() { return (triggersignals & (1 << bitSCen)) != 0; } + bool getOrA() const { return (triggersignals & (1 << bitA)) != 0; } + bool getOrC() const { return (triggersignals & (1 << bitC)) != 0; } + bool getVertex() const { return (triggersignals & (1 << bitVertex)) != 0; } + bool getCen() const { return (triggersignals & (1 << bitCen)) != 0; } + bool getSCen() const { return (triggersignals & (1 << bitSCen)) != 0; } void setTriggers(Bool_t isA, Bool_t isC, Bool_t isVrtx, Bool_t isCnt, Bool_t isSCnt, int8_t chanA, int8_t chanC, int32_t aamplA, int32_t aamplC, int16_t atimeA, int16_t atimeC) @@ -74,13 +74,11 @@ struct Triggers { void cleanTriggers() { triggersignals = 0; - nChanA = nChanC = -1; + nChanA = nChanC = 0; amplA = amplC = -1000; timeA = timeC = -1000; } - Triggers getTriggers(); - ClassDefNV(Triggers, 1); }; @@ -90,7 +88,7 @@ struct Digit { o2::InteractionRecord mIntRecord; // Interaction record (orbit, bc) int mEventID; Digit() = default; - Digit(int first, int ne, o2::InteractionRecord iRec, Triggers chTrig, int event) + Digit(int first, int ne, const o2::InteractionRecord& iRec, const Triggers& chTrig, int event) { ref.setFirstEntry(first); ref.setEntries(ne); @@ -100,7 +98,7 @@ struct Digit { } uint32_t getOrbit() const { return mIntRecord.orbit; } uint16_t getBC() const { return mIntRecord.bc; } - Triggers getTriggers() { return mTriggers; } + Triggers getTriggers() const { return mTriggers; } int getEventID() const { return mEventID; } o2::InteractionRecord getIntRecord() { return mIntRecord; }; gsl::span<const ChannelData> getBunchChannelData(const gsl::span<const ChannelData> tfdata) const; diff --git a/DataFormats/Detectors/FIT/FT0/src/CTF.cxx b/DataFormats/Detectors/FIT/FT0/src/CTF.cxx new file mode 100644 index 0000000000000..6e6d214c6e943 --- /dev/null +++ b/DataFormats/Detectors/FIT/FT0/src/CTF.cxx @@ -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. + +#include <stdexcept> +#include <cstring> +#include "Framework/Logger.h" +#include "DataFormatsFT0/CTF.h" + +using namespace o2::ft0; + +///________________________________ +void CompressedDigits::clear() +{ + trigger.clear(); + bcInc.clear(); + orbitInc.clear(); + nChan.clear(); + + idChan.clear(); + qtc.clear(); + cfdTime.clear(); + qtcAmpl.clear(); + + header.nTriggers = 0; + header.firstOrbit = 0; + header.firstBC = 0; +} diff --git a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h index 682cc73aa12ee..b3a0badf1fecd 100644 --- a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h +++ b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h @@ -39,4 +39,9 @@ #pragma link C++ class o2::ft0::EventData + ; #pragma link C++ class o2::ft0::Topo + ; +#pragma link C++ class o2::ft0::CTFHeader + ; +#pragma link C++ class o2::ft0::CompressedDigits + ; +#pragma link C++ class o2::ft0::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::ft0::CTFHeader, 8, uint32_t> + ; + #endif diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index 285437837236f..9202a1cfffb55 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -18,6 +18,7 @@ o2_add_library(CTFWorkflow O2::DataFormatsParameters O2::ITSMFTWorkflow O2::TPCWorkflow + O2::FT0Workflow O2::Algorithm O2::CommonUtils) diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 3f51c63322e67..1a524c5418621 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -25,6 +25,7 @@ #include "DetectorsCommonDataFormats/CTFHeader.h" #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" +#include "DataFormatsFT0/CTF.h" #include "Algorithm/RangeTokenizer.h" using namespace o2::framework; @@ -125,6 +126,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::FT0; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::ft0::CTF)); + o2::ft0::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + mTimer.Stop(); LOG(INFO) << "Read CTF " << inputFile << " in " << mTimer.CpuTime() - cput << " s"; diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index eb2100e1f6cf3..8178884e49c4a 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -25,6 +25,7 @@ #include "DetectorsCommonDataFormats/NameConf.h" #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" +#include "DataFormatsFT0/CTF.h" using namespace o2::framework; @@ -95,6 +96,16 @@ void CTFWriterSpec::run(ProcessingContext& pc) header.detectors.set(det); } + det = DetID::FT0; + if (isPresent(det) && pc.inputs().isValid(det.getName())) { + auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); + const auto ctfImage = o2::ft0::CTF::getImage(ctfBuffer.data()); + LOG(INFO) << "CTF for " << det.getName(); + ctfImage.print(); + ctfImage.appendToTree(ctfTree, det.getName()); + header.detectors.set(det); + } + appendToTree(ctfTree, "CTFHeader", header); ctfTree.SetEntries(1); diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index 997a1d94f568d..2a1993a5c2ff9 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -22,6 +22,7 @@ // Specific detectors specs #include "ITSMFTWorkflow/EntropyDecoderSpec.h" #include "TPCWorkflow/EntropyDecoderSpec.h" +#include "FT0Workflow/EntropyDecoderSpec.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -44,7 +45,9 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { DetID::mask_t dets; - std::string inpNames = configcontext.options().get<std::string>("ctf-input"); + WorkflowSpec specs; + + std::string inpNames; if (!configcontext.helpOnCommandLine()) { dets.set(); // by default read all auto mskOnly = DetID::getMask(configcontext.options().get<std::string>("onlyDet")); @@ -54,11 +57,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } else { dets ^= mskSkip; } - } else if (inpNames.empty()) { - throw std::runtime_error("--ctf-input <file,...> is not provided"); + if ((inpNames = configcontext.options().get<std::string>("ctf-input")).empty()) { + throw std::runtime_error("--ctf-input <file,...> is not provided"); + } } - WorkflowSpec specs; specs.push_back(o2::ctf::getCTFReaderSpec(dets, inpNames)); // add decodors for all allowed detectors. if (dets[DetID::ITS]) { @@ -70,6 +73,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets[DetID::TPC]) { specs.push_back(o2::tpc::getEntropyDecoderSpec()); } + if (dets[DetID::FT0]) { + specs.push_back(o2::ft0::getEntropyDecoderSpec()); + } return std::move(specs); } diff --git a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx index b77dbfb4bf63b..e35a3d7d83446 100644 --- a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx @@ -19,9 +19,6 @@ #include "DataFormatsParameters/GRPObject.h" #include "DetectorsCommonDataFormats/DetID.h" -// Specific detectors specs -#include "ITSMFTWorkflow/EntropyEncoderSpec.h" - using namespace o2::framework; using DetID = o2::detectors::DetID; diff --git a/Detectors/FIT/CMakeLists.txt b/Detectors/FIT/CMakeLists.txt index c93aa1ccab557..16976f8e705bc 100644 --- a/Detectors/FIT/CMakeLists.txt +++ b/Detectors/FIT/CMakeLists.txt @@ -12,5 +12,4 @@ add_subdirectory(FT0) add_subdirectory(common) add_subdirectory(FV0) add_subdirectory(FDD) -add_subdirectory(workflow) add_subdirectory(macros) diff --git a/Detectors/FIT/FT0/CMakeLists.txt b/Detectors/FIT/FT0/CMakeLists.txt index a885f0a3f20d9..0fffd09372ef7 100644 --- a/Detectors/FIT/FT0/CMakeLists.txt +++ b/Detectors/FIT/FT0/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(base) add_subdirectory(reconstruction) add_subdirectory(simulation) +add_subdirectory(workflow) diff --git a/Detectors/FIT/FT0/reconstruction/CMakeLists.txt b/Detectors/FIT/FT0/reconstruction/CMakeLists.txt index dcb09b461e0fe..2a640cbde7df6 100644 --- a/Detectors/FIT/FT0/reconstruction/CMakeLists.txt +++ b/Detectors/FIT/FT0/reconstruction/CMakeLists.txt @@ -11,15 +11,19 @@ o2_add_library(FT0Reconstruction SOURCES src/CollisionTimeRecoTask.cxx SOURCES src/ReadRaw.cxx + src/CTFCoder.cxx PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::Framework O2::FT0Base O2::DataFormatsFT0 O2::DetectorsRaw + O2::CommonDataFormat + O2::rANS O2::Headers) o2_target_root_dictionary( FT0Reconstruction HEADERS include/FT0Reconstruction/CollisionTimeRecoTask.h HEADERS include/FT0Reconstruction/ReadRaw.h + include/FT0Reconstruction/CTFCoder.h ) diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h new file mode 100644 index 0000000000000..5c1970c34638f --- /dev/null +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -0,0 +1,174 @@ +// 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 CTFCoder.h +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of FT0 digits data + +#ifndef O2_FT0_CTFCODER_H +#define O2_FT0_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include "FT0Base/Geometry.h" +#include "DataFormatsFT0/CTF.h" +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "rANS/rans.h" + +class TTree; + +namespace o2 +{ +namespace ft0 +{ + +class CTFCoder +{ + public: + /// entropy-encode digits to buffer with CTF + template <typename VEC> + static void encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); + + /// entropy decode clusters from buffer with CTF + template <typename VDIG, typename VCHAN> + static void decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec); + + private: + /// compres digits clusters to CompressedDigits + static void compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); + + /// decompress CompressedDigits to digits + template <typename VDIG, typename VCHAN> + static void decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec); + + static void appendToTree(TTree& tree, CTF& ec); + static void readFromTree(TTree& tree, int entry, std::vector<Digit>& digitVec, std::vector<ChannelData>& channelVec); + + ClassDefNV(CTFCoder, 1); +}; + +/// entropy-encode clusters to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, // BLC_trigger + MD::EENCODE, // BLC_bcInc + MD::EENCODE, // BLC_orbitInc + MD::EENCODE, // BLC_nChan + MD::EENCODE, // BLC_idChan + MD::EENCODE, // BLC_qtc + MD::EENCODE, // BLC_cfdTime + MD::EENCODE // BLC_qtcAmpl + }; + CompressedDigits cd; + compress(cd, digitVec, channelVec); + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(cd.header); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODE CTF::get(buff.data())->encode + // clang-format off + ENCODE(cd.trigger, CTF::BLC_trigger, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_trigger], &buff); + ENCODE(cd.bcInc, CTF::BLC_bcInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_bcInc], &buff); + ENCODE(cd.orbitInc, CTF::BLC_orbitInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_orbitInc], &buff); + ENCODE(cd.nChan, CTF::BLC_nChan, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_nChan], &buff); + ENCODE(cd.idChan , CTF::BLC_idChan, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_idChan], &buff); + ENCODE(cd.qtc , CTF::BLC_qtc, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_qtc], &buff); + ENCODE(cd.cfdTime, CTF::BLC_cfdTime, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_cfdTime], &buff); + ENCODE(cd.qtcAmpl, CTF::BLC_qtcAmpl, o2::rans::ProbabilityBits25Bit, optField[CTF::BLC_qtcAmpl], &buff); + // clang-format on +} + +/// decode entropy-encoded clusters to standard compact clusters +template <typename VDIG, typename VCHAN> +void CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec) +{ + CompressedDigits cd; + cd.header = ec.getHeader(); + // clang-format off + ec.decode(cd.trigger, CTF::BLC_trigger); + ec.decode(cd.bcInc, CTF::BLC_bcInc); + ec.decode(cd.orbitInc, CTF::BLC_orbitInc); + ec.decode(cd.nChan, CTF::BLC_nChan); + ec.decode(cd.idChan , CTF::BLC_idChan); + ec.decode(cd.qtc , CTF::BLC_qtc); + ec.decode(cd.cfdTime, CTF::BLC_cfdTime); + ec.decode(cd.qtcAmpl, CTF::BLC_qtcAmpl); + // clang-format on + // + decompress(cd, digitVec, channelVec); +} + +/// decompress compressed digits to standard digits +template <typename VDIG, typename VCHAN> +void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec) +{ + digitVec.clear(); + channelVec.clear(); + digitVec.reserve(cd.header.nTriggers); + channelVec.reserve(cd.idChan.size()); + + uint32_t firstEntry = 0, clCount = 0, chipCount = 0; + o2::InteractionRecord ir(cd.header.firstBC, cd.header.firstOrbit); + + for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) { + // restore ROFRecord + if (cd.orbitInc[idig]) { // non-0 increment => new orbit + ir.bc = cd.bcInc[idig]; // bcInc has absolute meaning + ir.orbit += cd.orbitInc[idig]; + } else { + ir.bc += cd.bcInc[idig]; + } + Triggers trig; + trig.triggersignals = cd.trigger[idig]; + + firstEntry = channelVec.size(); + uint8_t chID = 0; + int amplA = 0, amplC = 0, timeA = 0, timeC = 0; + for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { + auto icc = channelVec.size(); + const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtc[icc]); + // + // rebuild digit + if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side + trig.nChanA++; + amplA += chan.QTCAmpl; + timeA += chan.CFDTime; + } else { + trig.nChanC++; + amplC += chan.QTCAmpl; + timeC += chan.CFDTime; + } + } + if (trig.nChanA) { + trig.timeA = timeA / trig.nChanA; + trig.amplA = amplA; + } + if (trig.nChanC) { + trig.timeC = timeC / trig.nChanC; + trig.amplC = amplC; + } + digitVec.emplace_back(firstEntry, cd.nChan[idig], ir, trig, idig); + } +} + +} // namespace ft0 +} // namespace o2 + +#endif // O2_FT0_CTFCODER_H diff --git a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx new file mode 100644 index 0000000000000..2140a80cb9d0e --- /dev/null +++ b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.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. + +/// \file CTFCoder.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of FT0 digits data + +#include "FT0Reconstruction/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::ft0; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) +{ + ec.appendToTree(tree, o2::detectors::DetID::getName(o2::detectors::DetID::FT0)); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, + std::vector<Digit>& digitVec, std::vector<ChannelData>& channelVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, o2::detectors::DetID::getName(o2::detectors::DetID::FT0), entry); + decode(ec, digitVec, channelVec); +} + +///________________________________ +void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec) +{ + // convert digits/channel to their compressed version + cd.clear(); + if (!digitVec.size()) { + return; + } + const auto& dig0 = digitVec[0]; + cd.header.nTriggers = digitVec.size(); + cd.header.firstOrbit = dig0.getOrbit(); + cd.header.firstBC = dig0.getBC(); + + cd.trigger.resize(cd.header.nTriggers); + cd.bcInc.resize(cd.header.nTriggers); + cd.orbitInc.resize(cd.header.nTriggers); + cd.nChan.resize(cd.header.nTriggers); + + cd.idChan.resize(channelVec.size()); + cd.qtc.resize(channelVec.size()); + cd.cfdTime.resize(channelVec.size()); + cd.qtcAmpl.resize(channelVec.size()); + + uint16_t prevBC = cd.header.firstBC; + uint32_t prevOrbit = cd.header.firstOrbit; + uint32_t ccount = 0; + for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) { + const auto& digit = digitVec[idig]; + const auto chanels = digit.getBunchChannelData(channelVec); // we assume the channels are sorted + + // fill trigger info + cd.trigger[idig] = digit.getTriggers().triggersignals; + if (prevOrbit == digit.getOrbit()) { + cd.bcInc[idig] = digit.getBC() - prevBC; + cd.orbitInc[idig] = 0; + } else { + cd.bcInc[idig] = digit.getBC(); + cd.orbitInc[idig] = digit.getOrbit() - prevOrbit; + } + prevBC = digit.getBC(); + prevOrbit = digit.getOrbit(); + // fill channels info + cd.nChan[idig] = chanels.size(); + if (!cd.nChan[idig]) { + LOG(ERROR) << "Digits with no channels"; + continue; + } + uint8_t prevChan = 0; + for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { + assert(prevChan <= chanels[ic].ChId); + cd.idChan[ccount] = chanels[ic].ChId - prevChan; + cd.qtc[ccount] = chanels[ic].ChainQTC; + cd.cfdTime[ccount] = chanels[ic].CFDTime; + cd.qtcAmpl[ccount] = chanels[ic].QTCAmpl; + prevChan = chanels[ic].ChId; + ccount++; + } + } +} diff --git a/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h b/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h index 24b5e237b0cad..0296660c18f1d 100644 --- a/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h +++ b/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h @@ -16,5 +16,6 @@ #pragma link C++ class o2::ft0::CollisionTimeRecoTask + ; #pragma link C++ class o2::ft0::ReadRaw + ; +#pragma link C++ class o2::ft0::CTFCoder + ; #endif diff --git a/Detectors/FIT/FT0/workflow/CMakeLists.txt b/Detectors/FIT/FT0/workflow/CMakeLists.txt new file mode 100644 index 0000000000000..03363c8da6187 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/CMakeLists.txt @@ -0,0 +1,43 @@ +# 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_library(FT0Workflow + SOURCES src/RecoWorkflow.cxx + src/ReconstructionSpec.cxx + src/RecPointWriterSpec.cxx + src/RecPointReaderSpec.cxx + src/EntropyEncoderSpec.cxx + src/EntropyDecoderSpec.cxx + src/DigitReaderSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DataFormatsFT0 + O2::FT0Reconstruction + O2::DetectorsCommonDataFormats + O2::DPLUtils) + +o2_add_executable(reco-workflow + SOURCES src/ft0-reco-workflow.cxx + COMPONENT_NAME ft0 + PUBLIC_LINK_LIBRARIES O2::FT0Workflow + TARGETVARNAME fitrecoexe) + +o2_add_executable(entropy-encoder-workflow + SOURCES src/entropy-encoder-workflow.cxx + COMPONENT_NAME ft0 + PUBLIC_LINK_LIBRARIES O2::FT0Workflow) + +o2_add_executable(digits-reader-workflow + SOURCES src/digits-reader-workflow.cxx + COMPONENT_NAME ft0 + PUBLIC_LINK_LIBRARIES O2::FT0Workflow) + +if(NOT APPLE) + set_property(TARGET ${fitrecoexe} PROPERTY LINK_WHAT_YOU_USE ON) +endif() diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/DigitReaderSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/DigitReaderSpec.h new file mode 100644 index 0000000000000..3b0c2f2cab1c8 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/DigitReaderSpec.h @@ -0,0 +1,45 @@ +// 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_FT0_DIGITREADERSPEC_H +#define O2_FT0_DIGITREADERSPEC_H + +#include "TFile.h" +#include "TTree.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" + +namespace o2 +{ +namespace ft0 +{ + +class DigitReader : public framework::Task +{ + public: + DigitReader(bool useMC) : mUseMC(useMC) {} + ~DigitReader() override = default; + void init(framework::InitContext& ic) final; + void run(framework::ProcessingContext& pc) final; + + private: + bool mUseMC = true; + std::unique_ptr<TTree> mTree; + std::unique_ptr<TFile> mFile; +}; + +/// create a processor spec +/// read simulated FT0 digits from a root file +framework::DataProcessorSpec getDigitReaderSpec(bool useMC); + +} // end namespace ft0 +} // end namespace o2 + +#endif // O2_FT0_DIGITREADERSPEC_H diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..360e8b1f4cdfa --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h @@ -0,0 +1,44 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to FT0 digit/channels strean + +#ifndef O2_FT0_ENTROPYDECODER_SPEC +#define O2_FT0_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace ft0 +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace ft0 +} // namespace o2 + +#endif diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..498724b7ebcc8 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h @@ -0,0 +1,44 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert clusters streams to CTF (EncodedBlocks) + +#ifndef O2_FT0_ENTROPYENCODER_SPEC +#define O2_FT0_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace ft0 +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace ft0 +} // namespace o2 + +#endif diff --git a/Detectors/FIT/workflow/include/FITWorkflow/FT0RecPointReaderSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RecPointReaderSpec.h similarity index 93% rename from Detectors/FIT/workflow/include/FITWorkflow/FT0RecPointReaderSpec.h rename to Detectors/FIT/FT0/workflow/include/FT0Workflow/RecPointReaderSpec.h index c03c1fc072385..c16b3234a0541 100644 --- a/Detectors/FIT/workflow/include/FITWorkflow/FT0RecPointReaderSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RecPointReaderSpec.h @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// @file FT0RecPointReaderSpec.h +/// @file RecPointReaderSpec.h #ifndef O2_FT0_RECPOINTREADER #define O2_FT0_RECPOINTREADER @@ -54,7 +54,7 @@ class RecPointReader : public Task /// create a processor spec /// read simulated ITS digits from a root file -framework::DataProcessorSpec getFT0RecPointReaderSpec(bool useMC); +framework::DataProcessorSpec getRecPointReaderSpec(bool useMC); } // namespace ft0 } // namespace o2 diff --git a/Detectors/FIT/workflow/include/FITWorkflow/FT0RecPointWriterSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RecPointWriterSpec.h similarity index 87% rename from Detectors/FIT/workflow/include/FITWorkflow/FT0RecPointWriterSpec.h rename to Detectors/FIT/FT0/workflow/include/FT0Workflow/RecPointWriterSpec.h index c49a9e6d26565..a4a4609cb2045 100644 --- a/Detectors/FIT/workflow/include/FITWorkflow/FT0RecPointWriterSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RecPointWriterSpec.h @@ -8,12 +8,11 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// @file FT0RecPointWriterSpec.h +/// @file RecPointWriterSpec.h #ifndef O2_FT0RECPOINTWRITER_H #define O2_FT0RECPOINTWRITER_H - #include "Framework/DataProcessorSpec.h" using namespace o2::framework; @@ -24,7 +23,7 @@ namespace ft0 { /// create a processor spec -framework::DataProcessorSpec getFT0RecPointWriterSpec(bool useMC); +framework::DataProcessorSpec getRecPointWriterSpec(bool useMC); } // namespace ft0 } // namespace o2 diff --git a/Detectors/FIT/workflow/include/FITWorkflow/RecoWorkflow.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RecoWorkflow.h similarity index 100% rename from Detectors/FIT/workflow/include/FITWorkflow/RecoWorkflow.h rename to Detectors/FIT/FT0/workflow/include/FT0Workflow/RecoWorkflow.h diff --git a/Detectors/FIT/workflow/include/FITWorkflow/FT0ReconstructorSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/ReconstructionSpec.h similarity index 83% rename from Detectors/FIT/workflow/include/FITWorkflow/FT0ReconstructorSpec.h rename to Detectors/FIT/FT0/workflow/include/FT0Workflow/ReconstructionSpec.h index 31108e52b1a89..e3e6b3da7c62f 100644 --- a/Detectors/FIT/workflow/include/FITWorkflow/FT0ReconstructorSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/ReconstructionSpec.h @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// @file FT0ReconstructorSpec.h +/// @file ReconstructionSpec.h #ifndef O2_FT0RECONSTRUCTORDPL_H #define O2_FT0RECONSTRUCTORDPL_H @@ -25,11 +25,11 @@ namespace o2 namespace ft0 { -class FT0ReconstructorDPL : public Task +class ReconstructionDPL : public Task { public: - FT0ReconstructorDPL(bool useMC) : mUseMC(useMC) {} - ~FT0ReconstructorDPL() override = default; + ReconstructionDPL(bool useMC) : mUseMC(useMC) {} + ~ReconstructionDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -43,7 +43,7 @@ class FT0ReconstructorDPL : public Task }; /// create a processor spec -framework::DataProcessorSpec getFT0ReconstructorSpec(bool useMC = true); +framework::DataProcessorSpec getReconstructionSpec(bool useMC = true); } // namespace ft0 } // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx b/Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx new file mode 100644 index 0000000000000..b1f99a2b598e4 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx @@ -0,0 +1,91 @@ +// 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 DigitReaderSpec.cxx + +#include <vector> + +#include "TTree.h" + +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "FT0Workflow/DigitReaderSpec.h" +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" +#include "DataFormatsFT0/MCLabel.h" +#include "SimulationDataFormat/MCTruthContainer.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +void DigitReader::init(InitContext& ic) +{ + auto filename = ic.options().get<std::string>("ft0-digit-infile"); + mFile = std::make_unique<TFile>(filename.c_str(), "OLD"); + if (!mFile->IsOpen()) { + LOG(ERROR) << "Cannot open the " << filename.c_str() << " file !"; + throw std::runtime_error("cannot open input digits file"); + } + mTree.reset((TTree*)mFile->Get("o2sim")); + if (!mTree) { + LOG(ERROR) << "Did not find o2sim tree in " << filename.c_str(); + throw std::runtime_error("Did not fine o2sim file in FT0 digits tree"); + } +} + +void DigitReader::run(ProcessingContext& pc) +{ + + std::vector<o2::ft0::Digit> digits, *pdigits = &digits; + std::vector<o2::ft0::ChannelData> channels, *pchannels = &channels; + mTree->SetBranchAddress("FT0DIGITSBC", &pdigits); + mTree->SetBranchAddress("FT0DIGITSCH", &pchannels); + + o2::dataformats::MCTruthContainer<o2::ft0::MCLabel> labels, *plabels = &labels; + if (mUseMC) { + mTree->SetBranchAddress("FT0DIGITSMCTR", &plabels); + } + mTree->GetEntry(0); + + LOG(INFO) << "FT0DigitReader pushed " << channels.size() << " channels in " << digits.size() << " digits"; + + pc.outputs().snapshot(Output{"FT0", "DIGITSBC", 0, Lifetime::Timeframe}, digits); + pc.outputs().snapshot(Output{"FT0", "DIGITSCH", 0, Lifetime::Timeframe}, channels); + if (mUseMC) { + pc.outputs().snapshot(Output{"FT0", "DIGITSMCTR", 0, Lifetime::Timeframe}, labels); + } + pc.services().get<ControlService>().endOfStream(); + pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); +} + +DataProcessorSpec getDigitReaderSpec(bool useMC) +{ + std::vector<OutputSpec> outputs; + outputs.emplace_back("FT0", "DIGITSBC", 0, Lifetime::Timeframe); + outputs.emplace_back("FT0", "DIGITSCH", 0, Lifetime::Timeframe); + if (useMC) { + outputs.emplace_back("FT0", "DIGITSMCTR", 0, Lifetime::Timeframe); + } + + return DataProcessorSpec{ + "ft0-digit-reader", + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask<DigitReader>(useMC)}, + Options{ + {"ft0-digit-infile", VariantType::String, "ft0digits.root", {"Name of the input file"}}}}; +} + +} // namespace ft0 +} // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx b/Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..612485d6df9af --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,72 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "FT0Reconstruction/CTFCoder.h" +#include "FT0Workflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& digits = pc.outputs().make<std::vector<o2::ft0::Digit>>(OutputRef{"digits"}); + auto& channels = pc.outputs().make<std::vector<o2::ft0::ChannelData>>(OutputRef{"channels"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::ft0::CTF::getImage(buff.data()); + CTFCoder::decode(ctfImage, digits, channels); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << channels.size() << " FT0 channels in " << digits.size() << " digits in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "FT0 Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"digits"}, "FT0", "DIGITSBC", 0, Lifetime::Timeframe}, + OutputSpec{{"channels"}, "FT0", "DIGITSCH", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "ft0-entropy-decoder", + Inputs{InputSpec{"ctf", "FT0", "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{}}; +} + +} // namespace ft0 +} // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx b/Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..549cdf5277845 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,71 @@ +// 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 EntropyEncoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "FT0Reconstruction/CTFCoder.h" +#include "FT0Workflow/EntropyEncoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto digits = pc.inputs().get<gsl::span<o2::ft0::Digit>>("digits"); + auto channels = pc.inputs().get<gsl::span<o2::ft0::ChannelData>>("channels"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"FT0", "CTFDATA", 0, Lifetime::Timeframe}); + CTFCoder::encode(buffer, digits, channels); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + // eeb->print(); + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for FT0 in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "FT0 Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("digits", "FT0", "DIGITSBC", 0, Lifetime::Timeframe); + inputs.emplace_back("channels", "FT0", "DIGITSCH", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "ft0-entropy-encoder", + inputs, + Outputs{{"FT0", "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{}}; +} + +} // namespace ft0 +} // namespace o2 diff --git a/Detectors/FIT/workflow/src/FT0RecPointReaderSpec.cxx b/Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx similarity index 95% rename from Detectors/FIT/workflow/src/FT0RecPointReaderSpec.cxx rename to Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx index 5fbf40021a00a..328447acfbd47 100644 --- a/Detectors/FIT/workflow/src/FT0RecPointReaderSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// @file FT0RecPointReaderSpec.cxx +/// @file RecPointReaderSpec.cxx #include <vector> @@ -16,7 +16,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" -#include "FITWorkflow/FT0RecPointReaderSpec.h" +#include "FT0Workflow/RecPointReaderSpec.h" using namespace o2::framework; using namespace o2::ft0; @@ -72,7 +72,7 @@ void RecPointReader::connectTree(const std::string& filename) LOG(INFO) << "Loaded FT0 RecPoints tree from " << filename << " with " << mTree->GetEntries() << " entries"; } -DataProcessorSpec getFT0RecPointReaderSpec(bool useMC) +DataProcessorSpec getRecPointReaderSpec(bool useMC) { std::vector<OutputSpec> outputSpec; outputSpec.emplace_back(o2::header::gDataOriginFT0, "RECPOINTS", 0, Lifetime::Timeframe); diff --git a/Detectors/FIT/workflow/src/FT0RecPointWriterSpec.cxx b/Detectors/FIT/FT0/workflow/src/RecPointWriterSpec.cxx similarity index 93% rename from Detectors/FIT/workflow/src/FT0RecPointWriterSpec.cxx rename to Detectors/FIT/FT0/workflow/src/RecPointWriterSpec.cxx index a50671d2f0115..cfae8f06c1b44 100644 --- a/Detectors/FIT/workflow/src/FT0RecPointWriterSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/RecPointWriterSpec.cxx @@ -8,11 +8,11 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// @file FT0RecPointWriterSpec.cxx +/// @file RecPointWriterSpec.cxx #include <vector> -#include "FITWorkflow/FT0RecPointWriterSpec.h" +#include "FT0Workflow/RecPointWriterSpec.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" #include "DataFormatsFT0/RecPoints.h" @@ -25,7 +25,7 @@ namespace ft0 template <typename T> using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; -DataProcessorSpec getFT0RecPointWriterSpec(bool useMC) +DataProcessorSpec getRecPointWriterSpec(bool useMC) { using RecPointsType = std::vector<o2::ft0::RecPoints>; using ChanDataType = std::vector<o2::ft0::ChannelDataFloat>; diff --git a/Detectors/FIT/workflow/src/RecoWorkflow.cxx b/Detectors/FIT/FT0/workflow/src/RecoWorkflow.cxx similarity index 68% rename from Detectors/FIT/workflow/src/RecoWorkflow.cxx rename to Detectors/FIT/FT0/workflow/src/RecoWorkflow.cxx index 024533ab3f5fa..e3bddfefb69c9 100644 --- a/Detectors/FIT/workflow/src/RecoWorkflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/RecoWorkflow.cxx @@ -10,11 +10,11 @@ /// @file RecoWorkflow.cxx -#include "FITWorkflow/RecoWorkflow.h" +#include "FT0Workflow/RecoWorkflow.h" -#include "FITWorkflow/FT0DigitReaderSpec.h" -#include "FITWorkflow/FT0RecPointWriterSpec.h" -#include "FITWorkflow/FT0ReconstructorSpec.h" +#include "FT0Workflow/DigitReaderSpec.h" +#include "FT0Workflow/RecPointWriterSpec.h" +#include "FT0Workflow/ReconstructionSpec.h" namespace o2 { @@ -25,11 +25,11 @@ framework::WorkflowSpec getRecoWorkflow(bool useMC, bool disableRootInp, bool di { framework::WorkflowSpec specs; if (!disableRootInp) { - specs.emplace_back(o2::ft0::getFT0DigitReaderSpec(useMC)); + specs.emplace_back(o2::ft0::getDigitReaderSpec(useMC)); } - specs.emplace_back(o2::ft0::getFT0ReconstructorSpec(useMC)); + specs.emplace_back(o2::ft0::getReconstructionSpec(useMC)); if (!disableRootOut) { - specs.emplace_back(o2::ft0::getFT0RecPointWriterSpec(useMC)); + specs.emplace_back(o2::ft0::getRecPointWriterSpec(useMC)); } return specs; } diff --git a/Detectors/FIT/workflow/src/FT0ReconstructorSpec.cxx b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx similarity index 87% rename from Detectors/FIT/workflow/src/FT0ReconstructorSpec.cxx rename to Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx index 92e3a94db4f14..a38147e1f446b 100644 --- a/Detectors/FIT/workflow/src/FT0ReconstructorSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx @@ -8,12 +8,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// @file FT0ReconstructorSpec.cxx +/// @file ReconstructionSpec.cxx #include <vector> #include "SimulationDataFormat/MCTruthContainer.h" #include "Framework/ControlService.h" -#include "FITWorkflow/FT0ReconstructorSpec.h" +#include "FT0Workflow/ReconstructionSpec.h" #include "DataFormatsFT0/Digit.h" #include "DataFormatsFT0/ChannelData.h" #include "DataFormatsFT0/MCLabel.h" @@ -25,12 +25,12 @@ namespace o2 namespace ft0 { -void FT0ReconstructorDPL::init(InitContext& ic) +void ReconstructionDPL::init(InitContext& ic) { - LOG(INFO) << "FT0ReconstructorDPL::init"; + LOG(INFO) << "ReconstructionDPL::init"; } -void FT0ReconstructorDPL::run(ProcessingContext& pc) +void ReconstructionDPL::run(ProcessingContext& pc) { if (mFinished) { return; @@ -67,14 +67,14 @@ void FT0ReconstructorDPL::run(ProcessingContext& pc) pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); } -DataProcessorSpec getFT0ReconstructorSpec(bool useMC) +DataProcessorSpec getReconstructionSpec(bool useMC) { std::vector<InputSpec> inputSpec; std::vector<OutputSpec> outputSpec; inputSpec.emplace_back("digits", o2::header::gDataOriginFT0, "DIGITSBC", 0, Lifetime::Timeframe); inputSpec.emplace_back("digch", o2::header::gDataOriginFT0, "DIGITSCH", 0, Lifetime::Timeframe); if (useMC) { - LOG(INFO) << "Currently FT0Reconstructor does not consume and provide MC truth"; + LOG(INFO) << "Currently Reconstruction does not consume and provide MC truth"; inputSpec.emplace_back("labels", o2::header::gDataOriginFT0, "DIGITSMCTR", 0, Lifetime::Timeframe); } outputSpec.emplace_back(o2::header::gDataOriginFT0, "RECPOINTS", 0, Lifetime::Timeframe); @@ -84,7 +84,7 @@ DataProcessorSpec getFT0ReconstructorSpec(bool useMC) "ft0-reconstructor", inputSpec, outputSpec, - AlgorithmSpec{adaptFromTask<FT0ReconstructorDPL>(useMC)}, + AlgorithmSpec{adaptFromTask<ReconstructionDPL>(useMC)}, Options{}}; } diff --git a/Detectors/FIT/FT0/workflow/src/digits-reader-workflow.cxx b/Detectors/FIT/FT0/workflow/src/digits-reader-workflow.cxx new file mode 100644 index 0000000000000..09e2f407e512b --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/digits-reader-workflow.cxx @@ -0,0 +1,45 @@ +// 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 digits-reader-workflow.cxx +/// \brief Implementation of FT0 digits reader +/// +/// \author ruben.shahoyan@cern.ch + +#include "Framework/CallbackService.h" +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Task.h" +#include "FT0Workflow/DigitReaderSpec.h" +#include "CommonUtils/ConfigurableParam.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<o2::framework::ConfigParamSpec> options{ + {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}}; + std::string keyvaluehelp("Semicolon separated key=value strings"); + options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(const ConfigContext& ctx) +{ + WorkflowSpec specs; + + DataProcessorSpec producer = o2::ft0::getDigitReaderSpec(ctx.options().get<bool>("disable-mc")); + specs.push_back(producer); + return specs; +} diff --git a/Detectors/FIT/FT0/workflow/src/entropy-encoder-workflow.cxx b/Detectors/FIT/FT0/workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..e4a094904a820 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/entropy-encoder-workflow.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. + +#include "FT0Workflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::ft0::getEntropyEncoderSpec()); + return wf; +} diff --git a/Detectors/FIT/workflow/src/fit-reco-workflow.cxx b/Detectors/FIT/FT0/workflow/src/ft0-reco-workflow.cxx similarity index 98% rename from Detectors/FIT/workflow/src/fit-reco-workflow.cxx rename to Detectors/FIT/FT0/workflow/src/ft0-reco-workflow.cxx index 8c992576cdc6e..9cfe9732aaa21 100644 --- a/Detectors/FIT/workflow/src/fit-reco-workflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/ft0-reco-workflow.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "FITWorkflow/RecoWorkflow.h" +#include "FT0Workflow/RecoWorkflow.h" #include "CommonUtils/ConfigurableParam.h" using namespace o2::framework; diff --git a/Detectors/FIT/workflow/CMakeLists.txt b/Detectors/FIT/workflow/CMakeLists.txt deleted file mode 100644 index 6e147c4cf6bd9..0000000000000 --- a/Detectors/FIT/workflow/CMakeLists.txt +++ /dev/null @@ -1,25 +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. - -o2_add_library(FITWorkflow - SOURCES src/RecoWorkflow.cxx src/FT0DigitReaderSpec.cxx - src/FT0ReconstructorSpec.cxx src/FT0RecPointWriterSpec.cxx - src/FT0RecPointReaderSpec.cxx - PUBLIC_LINK_LIBRARIES O2::FT0Reconstruction O2::Framework O2::DPLUtils) - -o2_add_executable(reco-workflow - COMPONENT_NAME fit - SOURCES src/fit-reco-workflow.cxx - PUBLIC_LINK_LIBRARIES O2::FITWorkflow - TARGETVARNAME fitrecoexe) - -if(NOT APPLE) - set_property(TARGET ${fitrecoexe} PROPERTY LINK_WHAT_YOU_USE ON) -endif() diff --git a/Detectors/FIT/workflow/include/FITWorkflow/FT0DigitReaderSpec.h b/Detectors/FIT/workflow/include/FITWorkflow/FT0DigitReaderSpec.h deleted file mode 100644 index 1e2127a9bd738..0000000000000 --- a/Detectors/FIT/workflow/include/FITWorkflow/FT0DigitReaderSpec.h +++ /dev/null @@ -1,62 +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. - -/// @file FT0DigitReaderSpec.h - -#ifndef O2_FT0_DIGITREADER -#define O2_FT0_DIGITREADER - -#include "TFile.h" - -#include "Framework/DataProcessorSpec.h" -#include "Framework/Task.h" -#include "DataFormatsFT0/Digit.h" -#include "DataFormatsFT0/MCLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" - -using namespace o2::framework; - -namespace o2 -{ -namespace ft0 -{ - -class DigitReader : public Task -{ - public: - DigitReader(bool useMC = true); - ~DigitReader() override = default; - void init(InitContext& ic) final; - void run(ProcessingContext& pc) final; - - private: - bool mFinished = false; - bool mUseMC = true; // use MC truth - o2::header::DataOrigin mOrigin = o2::header::gDataOriginFT0; - - std::vector<o2::ft0::Digit>* mDigitsBC = nullptr; - std::vector<o2::ft0::ChannelData>* mDigitsCH = nullptr; - o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>* mMCTruth = nullptr; - - std::string mInputFileName = ""; - std::string mDigitTreeName = "o2sim"; - std::string mDigitBranchName = "FT0DigitBC"; - std::string mDigitChBranchName = "FT0DigitCH"; - std::string mDigitMCTruthBranchName = "FT0DIGITSMCTR"; -}; - -/// create a processor spec -/// read simulated ITS digits from a root file -framework::DataProcessorSpec getFT0DigitReaderSpec(bool useMC); - -} // namespace ft0 -} // namespace o2 - -#endif /* O2_FT0_DIGITREADER */ diff --git a/Detectors/FIT/workflow/src/FT0DigitReaderSpec.cxx b/Detectors/FIT/workflow/src/FT0DigitReaderSpec.cxx deleted file mode 100644 index ad1f56aedf129..0000000000000 --- a/Detectors/FIT/workflow/src/FT0DigitReaderSpec.cxx +++ /dev/null @@ -1,109 +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. - -/// @file FT0DigitReaderSpec.cxx - -#include <vector> - -#include "TTree.h" - -#include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" -#include "FITWorkflow/FT0DigitReaderSpec.h" - -using namespace o2::framework; -using namespace o2::ft0; - -namespace o2 -{ -namespace ft0 -{ - -DigitReader::DigitReader(bool useMC) -{ - mUseMC = useMC; -} - -void DigitReader::init(InitContext& ic) -{ - mInputFileName = ic.options().get<std::string>("ft0-digits-infile"); -} - -void DigitReader::run(ProcessingContext& pc) -{ - if (mFinished) { - return; - } - - { // load data from files - TFile digFile(mInputFileName.c_str(), "read"); - if (digFile.IsZombie()) { - LOG(FATAL) << "Failed to open FT0 digits file " << mInputFileName; - } - LOG(INFO) << " file read " << mInputFileName; - TTree* digTree = (TTree*)digFile.Get(mDigitTreeName.c_str()); - // digTree->Print(); - if (!digTree) { - LOG(FATAL) << "Failed to load FT0 digits tree " << mDigitTreeName << " from " << mInputFileName; - } - if (!digTree) { - LOG(FATAL) << "Failed to load FT0 digits tree " << mDigitTreeName << " from " << mInputFileName; - } - LOG(INFO) << "Loaded FT0 digits tree " << mDigitTreeName << " from " << mInputFileName; - - digTree->SetBranchAddress("FT0DIGITSBC", &mDigitsBC); - digTree->SetBranchAddress("FT0DIGITSCH", &mDigitsCH); - - if (mUseMC) { - if (digTree->GetBranch(mDigitMCTruthBranchName.c_str())) { - digTree->SetBranchAddress(mDigitMCTruthBranchName.c_str(), &mMCTruth); - LOG(INFO) << "Will use MC-truth from " << mDigitMCTruthBranchName; - } else { - LOG(INFO) << "MC-truth is missing"; - mUseMC = false; - } - } - - digTree->GetEntry(0); - delete digTree; - digFile.Close(); - } - - pc.outputs().snapshot(Output{mOrigin, "DIGITSBC", 0, Lifetime::Timeframe}, *mDigitsBC); - pc.outputs().snapshot(Output{mOrigin, "DIGITSCH", 0, Lifetime::Timeframe}, *mDigitsCH); - if (mUseMC) { - pc.outputs().snapshot(Output{mOrigin, "DIGITSMCTR", 0, Lifetime::Timeframe}, *mMCTruth); - } - - mFinished = true; - pc.services().get<ControlService>().endOfStream(); - pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); -} - -DataProcessorSpec getFT0DigitReaderSpec(bool useMC) -{ - std::vector<OutputSpec> outputSpec; - outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSBC", 0, Lifetime::Timeframe); - outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSCH", 0, Lifetime::Timeframe); - if (useMC) { - outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSMCTR", 0, Lifetime::Timeframe); - } - - return DataProcessorSpec{ - "ft0-digit-reader", - Inputs{}, - outputSpec, - AlgorithmSpec{adaptFromTask<DigitReader>()}, - Options{ - {"ft0-digits-infile", VariantType::String, "ft0digits.root", {"Name of the input file"}}}}; -} - -} // namespace ft0 -} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index 729d108fec904..fb975f6d7711a 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -13,7 +13,7 @@ o2_add_library(GlobalTrackingWorkflow SOURCES src/TrackWriterTPCITSSpec.cxx src/TPCITSMatchingSpec.cxx src/MatchTPCITSWorkflow.cxx src/TrackTPCITSReaderSpec.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTracking O2::ITStracking O2::ITSWorkflow - O2::TPCWorkflow O2::FITWorkflow + O2::TPCWorkflow O2::FT0Workflow O2::ITSMFTWorkflow) o2_add_executable(match-workflow diff --git a/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx b/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx index efc72a1ba758e..15a41178d841e 100644 --- a/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx @@ -14,7 +14,7 @@ #include "ITSWorkflow/TrackReaderSpec.h" #include "TPCWorkflow/TrackReaderSpec.h" #include "TPCWorkflow/PublisherSpec.h" -#include "FITWorkflow/FT0RecPointReaderSpec.h" +#include "FT0Workflow/RecPointReaderSpec.h" #include "GlobalTrackingWorkflow/TPCITSMatchingSpec.h" #include "GlobalTrackingWorkflow/MatchTPCITSWorkflow.h" #include "GlobalTrackingWorkflow/TrackWriterTPCITSSpec.h" @@ -54,7 +54,7 @@ framework::WorkflowSpec getMatchTPCITSWorkflow(bool useMC, bool disableRootInp, useMC)); if (o2::globaltracking::MatchITSTPCParams::Instance().runAfterBurner) { - specs.emplace_back(o2::ft0::getFT0RecPointReaderSpec(useMC)); + specs.emplace_back(o2::ft0::getRecPointReaderSpec(useMC)); } } specs.emplace_back(o2::globaltracking::getTPCITSMatchingSpec(useMC, tpcClusLanes)); diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt index 0e2aed78c0327..bba7096226851 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt @@ -15,7 +15,7 @@ o2_add_library(TOFWorkflow src/TOFMatchedReaderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction O2::GlobalTracking O2::GlobalTrackingWorkflow O2::TOFWorkflowUtils - O2::TOFCalibration O2::DataFormatsFT0 O2::FT0Reconstruction O2::FITWorkflow) + O2::TOFCalibration O2::DataFormatsFT0 O2::FT0Reconstruction O2::FT0Workflow) o2_add_executable(reco-workflow COMPONENT_NAME tof diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 40f11833d8b0d..0f731e193361f 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -36,7 +36,7 @@ #include "DataFormatsParameters/GRPObject.h" // FIT -#include "FITWorkflow/FT0RecPointReaderSpec.h" +#include "FT0Workflow/RecPointReaderSpec.h" #include <string> #include <stdexcept> @@ -181,7 +181,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } if (useFIT) { - specs.emplace_back(o2::ft0::getFT0RecPointReaderSpec(useMC)); + specs.emplace_back(o2::ft0::getRecPointReaderSpec(useMC)); } if (writematching || writecalib) { From 43dcc0a68310c9b4d01de44982e901104402ea42 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 13 Jul 2020 15:20:19 +0200 Subject: [PATCH 0104/1751] Add test for TF0 CTF encoding/decoding --- Detectors/CTF/CMakeLists.txt | 8 ++ Detectors/CTF/test/test_ctf_io_ft0.cxx | 138 +++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 Detectors/CTF/test/test_ctf_io_ft0.cxx diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index 4e1bd6ee7b22c..3e0f269c6430a 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -25,3 +25,11 @@ o2_add_test(tpc SOURCES test/test_ctf_io_tpc.cxx COMPONENT_NAME ctf LABELS ctf) + +o2_add_test(ft0 + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::FT0Reconstruction + O2::DataFormatsFT0 + SOURCES test/test_ctf_io_ft0.cxx + COMPONENT_NAME ctf + LABELS ctf) diff --git a/Detectors/CTF/test/test_ctf_io_ft0.cxx b/Detectors/CTF/test/test_ctf_io_ft0.cxx new file mode 100644 index 0000000000000..709e9712be989 --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_ft0.cxx @@ -0,0 +1,138 @@ +// 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. + +#define BOOST_TEST_MODULE Test FT0CTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DataFormatsTPC/CompressedClusters.h" +#include "DataFormatsTPC/CTF.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "FT0Reconstruction/CTFCoder.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <cstring> + +using namespace o2::ft0; + +BOOST_AUTO_TEST_CASE(CTFTest) +{ + std::vector<Digit> digits; + std::vector<ChannelData> channels; + + TStopwatch sw; + sw.Start(); + o2::InteractionRecord ir(0, 0); + + constexpr int MAXChan = 4 * (Geometry::NCellsA + Geometry::NCellsC); + for (int idig = 0; idig < 1000; idig++) { + ir += 1 + gRandom->Integer(200); + uint8_t ich = gRandom->Poisson(10); + auto start = channels.size(); + int32_t tMeanA = 0, tMeanC = 0; + uint32_t ampTotA = 0, ampTotC = 0; + Triggers trig; + trig.triggersignals = gRandom->Integer(128); + while (ich < MAXChan) { + int16_t t = -2048 + gRandom->Integer(2048 * 2); + uint16_t q = gRandom->Integer(4096); + uint8_t chain = gRandom->Rndm() > 0.5 ? 0 : 1; + channels.emplace_back(ich, t, q, chain); + if (ich < 4 * uint8_t(Geometry::NCellsA)) { + trig.nChanA++; + ampTotA += q; + tMeanA += t; + } else { + trig.nChanC++; + ampTotC += q; + tMeanC += t; + } + ich += 1 + gRandom->Poisson(10); + } + if (trig.nChanA) { + trig.timeA = tMeanA / trig.nChanA; + trig.amplA = ampTotA; + } + if (trig.nChanC) { + trig.timeC = tMeanC / trig.nChanC; + trig.amplC = ampTotC; + } + auto end = channels.size(); + digits.emplace_back(start, end - start, ir, trig, idig); + } + + LOG(INFO) << "Generated " << channels.size() << " channels in " << digits.size() << " digits " << sw.CpuTime() << " s"; + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + CTFCoder::encode(vec, digits, channels); // compress + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + TFile flOut("test_ctf_ft0.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + auto* ctfImage = o2::ft0::CTF::get(vec.data()); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "FT0"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + { + sw.Start(); + TFile flIn("test_ctf_ft0.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + o2::ft0::CTF::readFromTree(vec, *(tree.get()), "FT0"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<Digit> digitsD; + std::vector<ChannelData> channelsD; + + sw.Start(); + const auto ctfImage = o2::ft0::CTF::getImage(vec.data()); + CTFCoder::decode(ctfImage, digitsD, channelsD); // decompress + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + BOOST_CHECK(digitsD.size() == digits.size()); + BOOST_CHECK(channelsD.size() == channels.size()); + + for (int i = digits.size(); i--;) { + const auto& dor = digits[i]; + const auto& ddc = digitsD[i]; + BOOST_CHECK(dor.mIntRecord == ddc.mIntRecord); + BOOST_CHECK(dor.mTriggers.nChanA == ddc.mTriggers.nChanA); + BOOST_CHECK(dor.mTriggers.nChanC == ddc.mTriggers.nChanC); + BOOST_CHECK(dor.mTriggers.amplA == ddc.mTriggers.amplA); + BOOST_CHECK(dor.mTriggers.amplC == ddc.mTriggers.amplC); + BOOST_CHECK(dor.mTriggers.timeA == ddc.mTriggers.timeA); + BOOST_CHECK(dor.mTriggers.timeC == ddc.mTriggers.timeC); + BOOST_CHECK(dor.mTriggers.triggersignals == ddc.mTriggers.triggersignals); + } + for (int i = channels.size(); i--;) { + const auto& cor = channels[i]; + const auto& cdc = channelsD[i]; + BOOST_CHECK(cor.ChId == cdc.ChId); + BOOST_CHECK(cor.ChainQTC == cdc.ChainQTC); + BOOST_CHECK(cor.CFDTime == cdc.CFDTime); + BOOST_CHECK(cor.QTCAmpl == cdc.QTCAmpl); + } +} From 3d93521b954d4ed81628998c0edd8ed754e23f91 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 13 Jul 2020 23:33:58 +0200 Subject: [PATCH 0105/1751] GPU: Fix sanitizer warning --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 6 +++--- GPU/GPUTracking/Merger/GPUTPCGMMerger.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 20ea6ed55edca..24112c107d489 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -1200,7 +1200,7 @@ GPUd() void GPUTPCGMMerger::ResolveMergeSlices(GPUResolveSharedMemory& smem, int } } -GPUd() void GPUTPCGMMerger::MergeCEFill(const GPUTPCGMSliceTrack* track, const GPUTPCGMMergedTrackHit& cls, const GPUTPCGMMergedTrackHitXYZ& clsXYZ, int itr) +GPUd() void GPUTPCGMMerger::MergeCEFill(const GPUTPCGMSliceTrack* track, const GPUTPCGMMergedTrackHit& cls, const GPUTPCGMMergedTrackHitXYZ* clsXYZ, int itr) { if (Param().rec.NonConsecutiveIDs) { return; @@ -1214,7 +1214,7 @@ GPUd() void GPUTPCGMMerger::MergeCEFill(const GPUTPCGMSliceTrack* track, const G float z = 0; if (Param().earlyTpcTransform) { - z = clsXYZ.z; + z = clsXYZ->z; } else { float x, y; auto& cln = mConstantMem->ioPtrs.clustersNative->clustersLinear[cls.num]; @@ -1699,7 +1699,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int i auto& cls = mConstantMem->ioPtrs.clustersNative->clustersLinear; CEside = cls[cl[0].num].getTime() < cls[cl[nHits - 1].num].getTime(); } - MergeCEFill(trackParts[CEside ? lastTrackIndex : firstTrackIndex], cl[CEside ? (nHits - 1) : 0], clXYZ[CEside ? (nHits - 1) : 0], iOutputTrack); + MergeCEFill(trackParts[CEside ? lastTrackIndex : firstTrackIndex], cl[CEside ? (nHits - 1) : 0], &clXYZ[CEside ? (nHits - 1) : 0], iOutputTrack); } } // itr } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h index 539ff4275ca3a..7015ddf5e2b44 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h @@ -169,7 +169,7 @@ class GPUTPCGMMerger : public GPUProcessor template <int I> GPUd() void MergeBorderTracks(int nBlocks, int nThreads, int iBlock, int iThread, int iSlice1, GPUTPCGMBorderTrack* B1, int N1, int iSlice2, GPUTPCGMBorderTrack* B2, int N2, int mergeMode = 0); - GPUd() void MergeCEFill(const GPUTPCGMSliceTrack* track, const GPUTPCGMMergedTrackHit& cls, const GPUTPCGMMergedTrackHitXYZ& clsXYZ, int itr); + GPUd() void MergeCEFill(const GPUTPCGMSliceTrack* track, const GPUTPCGMMergedTrackHit& cls, const GPUTPCGMMergedTrackHitXYZ* clsXYZ, int itr); void CheckMergedTracks(); #ifndef GPUCA_GPUCODE From 3b9d60dd30c8910ea2bc458b4709cb38ffe39d84 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 13 Jul 2020 23:55:54 +0200 Subject: [PATCH 0106/1751] GPU: Fix typo --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 60504a15d0a66..2438f3e048dfd 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -193,7 +193,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int int len = std::min(optLen - 11, 1023); memcpy(matBudFileName, optPtr + 11, len); matBudFileName[len] = 0; - } else if (optLen > 8 && strncmp(optPtr, "gpuNum=", 7) == 0) { + } else if (optLen > 7 && strncmp(optPtr, "gpuNum=", 7) == 0) { sscanf(optPtr + 7, "%d", &gpuDevice); printf("Using GPU device %d\n", gpuDevice); } else if (optLen > 8 && strncmp(optPtr, "gpuMemorySize=", 14) == 0) { From 9b5330834b14c3e7301dd06cfcee1939e147ed0e Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Fri, 10 Jul 2020 13:49:42 +0200 Subject: [PATCH 0107/1751] MFT: application of physics cuts and flags --- Detectors/Base/src/MaterialManager.cxx | 4 +- Detectors/ITSMFT/MFT/base/src/Barrel.cxx | 8 +- .../ITSMFT/MFT/base/src/HeatExchanger.cxx | 20 +-- .../ITSMFT/MFT/simulation/data/simcuts.dat | 62 ++++++++ .../include/MFTSimulation/Detector.h | 33 ----- .../ITSMFT/MFT/simulation/src/Detector.cxx | 132 +++++++++++------- 6 files changed, 158 insertions(+), 101 deletions(-) diff --git a/Detectors/Base/src/MaterialManager.cxx b/Detectors/Base/src/MaterialManager.cxx index 76ad1ddb0229a..2b184635f0574 100644 --- a/Detectors/Base/src/MaterialManager.cxx +++ b/Detectors/Base/src/MaterialManager.cxx @@ -405,14 +405,14 @@ void MaterialManager::loadCutsAndProcessesFromFile(const char* modname, const ch // apply cuts via material manager interface for (int i = 0; i < NCUTS; ++i) { if (cut[i] >= 0.) { - SpecialCut(modname, itmed, cutnames[i], cut[i]); + SpecialCut(detName, itmed, cutnames[i], cut[i]); } } // apply process flags for (int i = 0; i < NFLAGS - 1; ++i) { if (flag[i] >= 0) { - SpecialProcess(modname, itmed, procnames[i], flag[i]); + SpecialProcess(detName, itmed, procnames[i], flag[i]); } } } // end loop over lines diff --git a/Detectors/ITSMFT/MFT/base/src/Barrel.cxx b/Detectors/ITSMFT/MFT/base/src/Barrel.cxx index 39840d06535a3..c1b4ba90865c5 100644 --- a/Detectors/ITSMFT/MFT/base/src/Barrel.cxx +++ b/Detectors/ITSMFT/MFT/base/src/Barrel.cxx @@ -38,13 +38,13 @@ TGeoVolumeAssembly* Barrel::createBarrel() // TGeoMedium* kMeAl = gGeoManager->GetMedium("MFT_Alu$"); TGeoMedium* mCu = gGeoManager->GetMedium("MFT_Cu$"); - TGeoMedium* mCarbon = gGeoManager->GetMedium("MFT_CarbonFiberM46J"); - TGeoMedium* mRohacell = gGeoManager->GetMedium("MFT_Rohacell"); + TGeoMedium* mCarbon = gGeoManager->GetMedium("MFT_CarbonFiberM46J$"); + TGeoMedium* mRohacell = gGeoManager->GetMedium("MFT_Rohacell$"); TGeoMedium* mKapton = gGeoManager->GetMedium("MFT_Kapton$"); TGeoMedium* mWater = gGeoManager->GetMedium("MFT_Water$"); TGeoMedium* mAir = gGeoManager->GetMedium("MFT_Air$"); - TGeoMedium* mPolypropylene = gGeoManager->GetMedium("MFT_Polypropylene"); - TGeoMedium* mPolyurethane = gGeoManager->GetMedium("MFT_Polyurethane"); + TGeoMedium* mPolypropylene = gGeoManager->GetMedium("MFT_Polypropylene$"); + TGeoMedium* mPolyurethane = gGeoManager->GetMedium("MFT_Polyurethane$"); // define shape of joints TGeoVolume* BarrelJoint0 = gGeoManager->MakeTubs( "Barrel_joint0", kMeAl, 49.600, 49.85, 1.05, 207.2660445, 332.7339555); diff --git a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx index 2d2d123c51154..29cde9a5e04df 100644 --- a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx @@ -893,8 +893,8 @@ void HeatExchanger::createHalfDisk0(Int_t half) mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); - mRohacell = gGeoManager->GetMedium("MFT_Rohacell"); - mPipe = gGeoManager->GetMedium("MFT_Polyimide"); + mRohacell = gGeoManager->GetMedium("MFT_Rohacell$"); + mPipe = gGeoManager->GetMedium("MFT_Polyimide$"); mPeek = gGeoManager->GetMedium("MFT_PEEK$"); auto* cooling = new TGeoVolumeAssembly(Form("cooling_D0_H%d", half)); @@ -1426,8 +1426,8 @@ void HeatExchanger::createHalfDisk1(Int_t half) mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); - mRohacell = gGeoManager->GetMedium("MFT_Rohacell"); - mPipe = gGeoManager->GetMedium("MFT_Polyimide"); + mRohacell = gGeoManager->GetMedium("MFT_Rohacell$"); + mPipe = gGeoManager->GetMedium("MFT_Polyimide$"); mPeek = gGeoManager->GetMedium("MFT_PEEK$"); auto* cooling = new TGeoVolumeAssembly(Form("cooling_D1_H%d", half)); @@ -1969,8 +1969,8 @@ void HeatExchanger::createHalfDisk2(Int_t half) mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); - mRohacell = gGeoManager->GetMedium("MFT_Rohacell"); - mPipe = gGeoManager->GetMedium("MFT_Polyimide"); + mRohacell = gGeoManager->GetMedium("MFT_Rohacell$"); + mPipe = gGeoManager->GetMedium("MFT_Polyimide$"); mPeek = gGeoManager->GetMedium("MFT_PEEK$"); auto* cooling = new TGeoVolumeAssembly(Form("cooling_D2_H%d", half)); @@ -2618,8 +2618,8 @@ void HeatExchanger::createHalfDisk3(Int_t half) mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); - mRohacell = gGeoManager->GetMedium("MFT_Rohacell"); - mPipe = gGeoManager->GetMedium("MFT_Polyimide"); + mRohacell = gGeoManager->GetMedium("MFT_Rohacell$"); + mPipe = gGeoManager->GetMedium("MFT_Polyimide$"); mPeek = gGeoManager->GetMedium("MFT_PEEK$"); auto* cooling = new TGeoVolumeAssembly(Form("cooling_D3_H%d", half)); @@ -3160,8 +3160,8 @@ void HeatExchanger::createHalfDisk4(Int_t half) mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); - mRohacell = gGeoManager->GetMedium("MFT_Rohacell"); - mPipe = gGeoManager->GetMedium("MFT_Polyimide"); + mRohacell = gGeoManager->GetMedium("MFT_Rohacell$"); + mPipe = gGeoManager->GetMedium("MFT_Polyimide$"); mPeek = gGeoManager->GetMedium("MFT_PEEK$"); auto* cooling = new TGeoVolumeAssembly(Form("cooling_D4_H%d", half)); diff --git a/Detectors/ITSMFT/MFT/simulation/data/simcuts.dat b/Detectors/ITSMFT/MFT/simulation/data/simcuts.dat index e69de29bb2d1d..23e72e91d1dca 100644 --- a/Detectors/ITSMFT/MFT/simulation/data/simcuts.dat +++ b/Detectors/ITSMFT/MFT/simulation/data/simcuts.dat @@ -0,0 +1,62 @@ +* MFT +* === +* +* Med GAM ELEC NHAD CHAD MUON EBREM MUHAB EDEL MUDEL MUPA ANNI BREM COMP DCAY DRAY HADR LOSS MULS PAIR PHOT RAYL STRA +* "Air" +MFT 0 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Vacuum" +MFT 1 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Si" +MFT 2 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Readout" +MFT 3 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Support" +MFT 4 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Carbon" +MFT 5 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Be" +MFT 6 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Alu" +MFT 7 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Water" +MFT 8 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "SiO2" +MFT 9 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Inox" +MFT 10 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Kapton" +MFT 11 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Epoxy" +MFT 12 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "SE4445" +MFT 13 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "CarbonFiber" +MFT 14 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Rohacell" +MFT 15 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Polyimide" +MFT 16 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "PEEK" +MFT 17 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "FR4" +MFT 18 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Cu" +MFT 19 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "X7Rcapacitors" +MFT 20 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "X7Rweld" +MFT 21 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "CarbonFleece" +MFT 22 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "CarbonFiberM46J" +MFT 23 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Polypropylene" +MFT 24 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "Polyurethane" +MFT 25 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "ALPIDE_METALSTACK" +ALPIDE 0 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "ALPIDE_AIR" +ALPIDE 1 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* "ALPIDE_SI" +ALPIDE 2 3.e-5 3.e-5 3.e-5 3.e-5 1.e-3 3.e-5 3.e-5 3.e-5 3.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 diff --git a/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h b/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h index 8d0a015fbaeb9..8986b68c3f6a9 100644 --- a/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h +++ b/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h @@ -90,39 +90,6 @@ class Detector : public o2::base::DetImpl<Detector> /// Creating materials for the detector void createMaterials(); - - enum EMedia { - Zero, - Air, - Vacuum, - Si, - Readout, - Support, - Carbon, - Be, - Alu, - Water, - SiO2, - Inox, - Kapton, - Epoxy, - CarbonFiber, - CarbonEpoxy, - Rohacell, - Polyimide, - PEEK, - FR4, - Cu, - X7R, - X7Rw, - CarbonFleece, - SE4445, - CarbonFiberM46J, - Polypropylene, - Polyurethane - - }; // media IDs used in CreateMaterials - void setDensitySupportOverSi(Double_t density) { if (density > 1e-6) diff --git a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx index f79f11f21a1fb..1d4e1c33f8035 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx @@ -353,24 +353,31 @@ void Detector::createMaterials() LOG(DEBUG) << "Detector::createMaterials >>>>> fieldType " << fieldType << " maxField " << maxField; - o2::base::Detector::Mixture(++matId, "Air$", aAir, zAir, dAir, nAir, wAir); - o2::base::Detector::Medium(Air, "Air$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin); + matId = 0; // starting value - o2::base::Detector::Mixture(++matId, "Vacuum$", aAir, zAir, dAirVacuum, nAir, wAir); - o2::base::Detector::Medium(Vacuum, "Vacuum$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Air$", aAir, zAir, dAir, nAir, wAir); + o2::base::Detector::Medium(matId, "Air$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Material(++matId, "Si$", aSi, zSi, dSi, radSi, absSi); - o2::base::Detector::Medium(Si, "Si$", matId, sens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, + o2::base::Detector::Mixture(matId, "Vacuum$", aAir, zAir, dAirVacuum, nAir, wAir); + o2::base::Detector::Medium(matId, "Vacuum$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; + + o2::base::Detector::Material(matId, "Si$", aSi, zSi, dSi, radSi, absSi); + o2::base::Detector::Medium(matId, "Si$", matId, sens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + matId++; - o2::base::Detector::Material(++matId, "Readout$", aSi, zSi, dSi, radSi, absSi); - o2::base::Detector::Medium(Readout, "Readout$", matId, unsens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, + o2::base::Detector::Material(matId, "Readout$", aSi, zSi, dSi, radSi, absSi); + o2::base::Detector::Medium(matId, "Readout$", matId, unsens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + matId++; - o2::base::Detector::Material(++matId, "Support$", aSi, zSi, dSi * mDensitySupportOverSi, + o2::base::Detector::Material(matId, "Support$", aSi, zSi, dSi * mDensitySupportOverSi, radSi / mDensitySupportOverSi, absSi / mDensitySupportOverSi); - o2::base::Detector::Medium(Support, "Support$", matId, unsens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, + o2::base::Detector::Medium(matId, "Support$", matId, unsens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + matId++; Double_t maxBending = 0; // Max Angle Double_t maxStepSize = 0.001; // Max step size @@ -388,76 +395,97 @@ void Detector::createMaterials() maxStepSize = .01; precision = .003; minStepSize = .003; - o2::base::Detector::Material(++matId, "Carbon$", aCarb, zCarb, dCarb, radCarb, absCarb); - o2::base::Detector::Medium(Carbon, "Carbon$", matId, 0, fieldType, maxField, maxBending, maxStepSize, maxEnergyLoss, + o2::base::Detector::Material(matId, "Carbon$", aCarb, zCarb, dCarb, radCarb, absCarb); + o2::base::Detector::Medium(matId, "Carbon$", matId, 0, fieldType, maxField, maxBending, maxStepSize, maxEnergyLoss, precision, minStepSize); + matId++; - o2::base::Detector::Material(++matId, "Be$", aBe, zBe, dBe, radBe, absBe); - o2::base::Detector::Medium(Be, "Be$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Material(matId, "Be$", aBe, zBe, dBe, radBe, absBe); + o2::base::Detector::Medium(matId, "Be$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Material(++matId, "Alu$", aAlu, zAlu, dAlu, radAlu, absAlu); - o2::base::Detector::Medium(Alu, "Alu$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Material(matId, "Alu$", aAlu, zAlu, dAlu, radAlu, absAlu); + o2::base::Detector::Medium(matId, "Alu$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Water$", aWater, zWater, dWater, nWater, wWater); - o2::base::Detector::Medium(Water, "Water$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Water$", aWater, zWater, dWater, nWater, wWater); + o2::base::Detector::Medium(matId, "Water$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "SiO2$", aSiO2, zSiO2, dSiO2, nSiO2, wSiO2); - o2::base::Detector::Medium(SiO2, "SiO2$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "SiO2$", aSiO2, zSiO2, dSiO2, nSiO2, wSiO2); + o2::base::Detector::Medium(matId, "SiO2$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Inox$", aInox, zInox, dInox, nInox, wInox); - o2::base::Detector::Medium(Inox, "Inox$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Inox$", aInox, zInox, dInox, nInox, wInox); + o2::base::Detector::Medium(matId, "Inox$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Kapton$", aKapton, zKapton, dKapton, 4, wKapton); - o2::base::Detector::Medium(Kapton, "Kapton$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Kapton$", aKapton, zKapton, dKapton, 4, wKapton); + o2::base::Detector::Medium(matId, "Kapton$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Epoxy$", aEpoxy, zEpoxy, dEpoxy, -3, wEpoxy); - o2::base::Detector::Medium(Epoxy, "Epoxy$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Epoxy$", aEpoxy, zEpoxy, dEpoxy, -3, wEpoxy); + o2::base::Detector::Medium(matId, "Epoxy$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "SE4445$", aSE4445, zSE4445, dSE4445, -5, wSE4445); - o2::base::Detector::Medium(SE4445, "SE4445$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "SE4445$", aSE4445, zSE4445, dSE4445, -5, wSE4445); + o2::base::Detector::Medium(matId, "SE4445$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "CarbonFiber$", aCM55J, zCM55J, dCM55J, 4, wCM55J); - o2::base::Detector::Medium(CarbonEpoxy, "CarbonFiber$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, + o2::base::Detector::Mixture(matId, "CarbonFiber$", aCM55J, zCM55J, dCM55J, 4, wCM55J); + o2::base::Detector::Medium(matId, "CarbonFiber$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Rohacell", aRohacell, zRohacell, dRohacell, nRohacell, wRohacell); - o2::base::Detector::Medium(Rohacell, "Rohacell", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Rohacell$", aRohacell, zRohacell, dRohacell, nRohacell, wRohacell); + o2::base::Detector::Medium(matId, "Rohacell$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Polyimide", aPolyimide, zPolyimide, dPolyimide, nPolyimide, wPolyimide); - o2::base::Detector::Medium(Polyimide, "Polyimide", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, + o2::base::Detector::Mixture(matId, "Polyimide$", aPolyimide, zPolyimide, dPolyimide, nPolyimide, wPolyimide); + o2::base::Detector::Medium(matId, "Polyimide$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "PEEK$", aPEEK, zPEEK, dPEEK, nPEEK, wPEEK); - o2::base::Detector::Medium(PEEK, "PEEK$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "PEEK$", aPEEK, zPEEK, dPEEK, nPEEK, wPEEK); + o2::base::Detector::Medium(matId, "PEEK$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "FR4$", aFR4, zFR4, dFR4, nFR4, wFR4); - o2::base::Detector::Medium(FR4, "FR4$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "FR4$", aFR4, zFR4, dFR4, nFR4, wFR4); + o2::base::Detector::Medium(matId, "FR4$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Material(++matId, "Cu$", aCu, zCu, dCu, radCu, absCu); - o2::base::Detector::Medium(Cu, "Cu$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Material(matId, "Cu$", aCu, zCu, dCu, radCu, absCu); + o2::base::Detector::Medium(matId, "Cu$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "X7Rcapacitors$", aX7R, zX7R, dX7R, 6, wX7R); - o2::base::Detector::Medium(X7R, "X7Rcapacitors$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, + o2::base::Detector::Mixture(matId, "X7Rcapacitors$", aX7R, zX7R, dX7R, 6, wX7R); + o2::base::Detector::Medium(matId, "X7Rcapacitors$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "X7Rweld$", aX7Rweld, zX7Rweld, dX7Rweld, 2, wX7Rweld); - o2::base::Detector::Medium(X7Rw, "X7Rweld$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "X7Rweld$", aX7Rweld, zX7Rweld, dX7Rweld, 2, wX7Rweld); + o2::base::Detector::Medium(matId, "X7Rweld$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; // Carbon fleece from AliITSSUv2.cxx - o2::base::Detector::Material(++matId, "CarbonFleece$", 12.0107, 6, 0.4, radCarb, absCarb); // 999,999); why 999??? - o2::base::Detector::Medium(CarbonFleece, "CarbonFleece$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, + o2::base::Detector::Material(matId, "CarbonFleece$", 12.0107, 6, 0.4, radCarb, absCarb); // 999,999); why 999??? + o2::base::Detector::Medium(matId, "CarbonFleece$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; //Barrel Materials - o2::base::Detector::Mixture(++matId, "CarbonFiberM46J", aCM46J, zCM46J, dCM46J, nCM46J, wCM46J); - o2::base::Detector::Medium(CarbonFiberM46J, "CarbonFiberM46J", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "CarbonFiberM46J$", aCM46J, zCM46J, dCM46J, nCM46J, wCM46J); + o2::base::Detector::Medium(matId, "CarbonFiberM46J$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Polypropylene", aPolyppln, zPolyppln, dPolyppln, nPolyppln, wPolyppln); - o2::base::Detector::Medium(Polypropylene, "Polypropylene", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Polypropylene$", aPolyppln, zPolyppln, dPolyppln, nPolyppln, wPolyppln); + o2::base::Detector::Medium(matId, "Polypropylene$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; - o2::base::Detector::Mixture(++matId, "Polyurethane", aPolyurthn, zPolyurthn, dPolyurthn, nPolyurthn, wPolyurthn); - o2::base::Detector::Medium(Polyurethane, "Polyurethane", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + o2::base::Detector::Mixture(matId, "Polyurethane$", aPolyurthn, zPolyurthn, dPolyurthn, nPolyurthn, wPolyurthn); + o2::base::Detector::Medium(matId, "Polyurethane$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin); + matId++; LOG(DEBUG) << "Detector::createMaterials -----> matId = " << matId; } From 5ae1e30c257ceef4eff9d3c98b1dd46f2f364a5f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 15 Jul 2020 19:14:08 +0200 Subject: [PATCH 0108/1751] If requested QED is absent, throw an exception --- DataFormats/simulation/src/DigitizationContext.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/simulation/src/DigitizationContext.cxx b/DataFormats/simulation/src/DigitizationContext.cxx index abb7f9ed519f3..fdd35354909b0 100644 --- a/DataFormats/simulation/src/DigitizationContext.cxx +++ b/DataFormats/simulation/src/DigitizationContext.cxx @@ -212,7 +212,7 @@ void DigitizationContext::fillQED(std::string_view QEDprefix, std::vector<o2::In auto t = (TTree*)f.Get("o2sim"); if (!t) { LOG(ERROR) << "No QED kinematics found"; - return; + throw std::runtime_error("No QED kinematics found"); } auto numberQEDevents = t->GetEntries(); int eventID = 0; From 92cc2231cbdd48f7460fff4c21c569e9ca63fc1c Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Thu, 16 Jul 2020 14:11:38 +0200 Subject: [PATCH 0109/1751] bug fix in AODReaderHelpers.cxx (#4000) --- Framework/Core/src/AODReaderHelpers.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index c8771181e6ea4..3fa0189a89f8c 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -198,7 +198,9 @@ void checkAndEnableAlien(std::string const& filename) TGrid::Connect("alien://"); } if (filename.rfind("@", 0) == 0) { - std::ifstream filenames(filename); + std::string strippedFilename = filename; + strippedFilename.erase(0, 1); + std::ifstream filenames(strippedFilename); for (std::string line; std::getline(filenames, line);) { if (line.rfind("alien://", 0) == 0) { LOG(debug) << "AliEn file requested. Enabling support."; From d3d7f1ed2543afcd14bd689c87c1b2471c699bf4 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen <evgeny.kryshen@cern.ch> Date: Thu, 16 Jul 2020 16:02:59 +0300 Subject: [PATCH 0110/1751] Read SOR orbit counters from CCDB (#3996) --- Analysis/Tasks/timestamp.cxx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Analysis/Tasks/timestamp.cxx b/Analysis/Tasks/timestamp.cxx index 52856b3e34248..496baa443bc1a 100644 --- a/Analysis/Tasks/timestamp.cxx +++ b/Analysis/Tasks/timestamp.cxx @@ -20,7 +20,7 @@ #include <CCDB/BasicCCDBManager.h> #include "CommonDataFormat/InteractionRecord.h" #include "DetectorsRaw/HBFUtils.h" - +#include <map> using namespace o2::framework; using namespace o2::header; using namespace o2; @@ -28,6 +28,7 @@ using namespace o2; struct TimestampTask { Produces<aod::Timestamps> ts_table; RunToTimestamp* converter = nullptr; + std::map<int, int>* mapStartOrbit = nullptr; Service<o2::ccdb::BasicCCDBManager> ccdb; Configurable<std::string> path{"ccdb-path", "Analysis/Core/RunToTimestamp", "path to the ccdb object"}; Configurable<long> timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; @@ -41,6 +42,10 @@ struct TimestampTask { } else { LOGF(fatal, "Cannot find run-number to timestamp converter in path '%s'.", path.value.data()); } + mapStartOrbit = ccdb->get<std::map<int, int>>("Trigger/StartOrbit"); + if (!mapStartOrbit) { + LOGF(fatal, "Cannot find map of SOR orbits in CCDB in path Trigger/StartOrbit"); + } } void process(aod::BC const& bc) @@ -48,8 +53,10 @@ struct TimestampTask { long timestamp = converter->getTimestamp(bc.runNumber()); uint16_t currentBC = bc.globalBC() % o2::constants::lhc::LHCMaxBunches; uint32_t currentOrbit = bc.globalBC() / o2::constants::lhc::LHCMaxBunches; + uint16_t initialBC = 0; // exact bc number not relevant due to ms precision of timestamps + uint32_t initialOrbit = mapStartOrbit->at(bc.runNumber()); InteractionRecord current(currentBC, currentOrbit); - InteractionRecord initial = o2::raw::HBFUtils::Instance().getFirstIR(); + InteractionRecord initial(initialBC, initialOrbit); timestamp += (current - initial).bc2ns() / 1000000; ts_table(timestamp); } From c6d6cee8053f498b2a514f891a5f4ed6a6e03116 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 16 Jul 2020 13:02:08 +0200 Subject: [PATCH 0111/1751] RawPixelDecoder allows user-defined DataOrigin (for QC) --- .../include/ITSMFTReconstruction/RawPixelDecoder.h | 5 +++++ .../ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 1ed100134198c..457a5839ddcc6 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -20,6 +20,7 @@ #include "ITSMFTReconstruction/ChipMappingMFT.h" #include "DetectorsRaw/HBFUtils.h" #include "Headers/RAWDataHeader.h" +#include "Headers/DataHeader.h" #include "CommonDataFormat/InteractionRecord.h" #include "ITSMFTReconstruction/GBTLink.h" #include "ITSMFTReconstruction/RUDecodeData.h" @@ -64,6 +65,9 @@ class RawPixelDecoder : public PixelReader const RUDecodeData* getRUDecode(int ruSW) const { return mRUEntry[ruSW] < 0 ? nullptr : &mRUDecodeVec[mRUEntry[ruSW]]; } + auto getUserDataOrigin() const { return mUserDataOrigin; } + void setUserDataOrigin(header::DataOrigin orig) { mUserDataOrigin = orig; } + void setNThreads(int n); int getNThreads() const { return mNThreads; } @@ -100,6 +104,7 @@ class RawPixelDecoder : public PixelReader std::vector<RUDecodeData> mRUDecodeVec; // set of active RUs std::array<int, Mapping::getNRUs()> mRUEntry; // entry of the RU with given SW ID in the mRUDecodeVec std::string mSelfName; // self name + header::DataOrigin mUserDataOrigin = o2::header::gDataOriginInvalid; // alternative user-provided data origin to pick uint16_t mCurRUDecodeID = NORUDECODED; // index of currently processed RUDecode container int mLastReadChipID = -1; // chip ID returned by previous getNextChipData call, used for ordering checks Mapping mMAP; // chip mapping diff --git a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx index 1ecb790a1db81..5d88c8ae54ea1 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx @@ -152,7 +152,8 @@ void RawPixelDecoder<Mapping>::setupLinks(InputRecord& inputs) { mCurRUDecodeID = NORUDECODED; auto nLinks = mGBTLinks.size(); - std::vector<InputSpec> filter{InputSpec{"filter", ConcreteDataTypeMatcher{mMAP.getOrigin(), "RAWDATA"}, Lifetime::Timeframe}}; + auto origin = (mUserDataOrigin == o2::header::gDataOriginInvalid) ? mMAP.getOrigin() : mUserDataOrigin; + std::vector<InputSpec> filter{InputSpec{"filter", ConcreteDataTypeMatcher{origin, "RAWDATA"}, Lifetime::Timeframe}}; DPLRawParser parser(inputs, filter); uint32_t currSSpec = 0xffffffff; // dummy starting subspec int linksAdded = 0; From d9a86247ab49bed0195b30767fcfe113e42abbbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Thu, 16 Jul 2020 19:21:25 +0200 Subject: [PATCH 0112/1751] Simplify reconstruction of decay candidates. (#4001) * Add function getTrackParCov. * Unify and generalise calculations of 4-momentum kinematics. Use double precision. --- .../DataModel/include/Analysis/RecoDecay.h | 98 ++++++++---- .../include/Analysis/trackUtilities.h | 32 ++++ Analysis/Tasks/hfcandidatecreator2prong.cxx | 51 +++---- Analysis/Tasks/hftrackindexskimscreator.cxx | 139 +++++++----------- 4 files changed, 168 insertions(+), 152 deletions(-) create mode 100644 Analysis/DataModel/include/Analysis/trackUtilities.h diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index d619b515b122f..613bf44849666 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -10,75 +10,109 @@ #ifndef O2_ANALYSIS_RECODECAY_H_ #define O2_ANALYSIS_RECODECAY_H_ -float energy(float px, float py, float pz, float mass) +double energy(double px, double py, double pz, double mass) { - float en_ = sqrtf(mass * mass + px * px + py * py + pz * pz); + double en_ = sqrt(mass * mass + px * px + py * py + pz * pz); return en_; }; -float invmass2prongs2(float px0, float py0, float pz0, float mass0, - float px1, float py1, float pz1, float mass1) +double invmass2prongs2(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1) { - float energy0_ = energy(px0, py0, pz0, mass0); - float energy1_ = energy(px1, py1, pz1, mass1); - float energytot = energy0_ + energy1_; + double energy0_ = energy(px0, py0, pz0, mass0); + double energy1_ = energy(px1, py1, pz1, mass1); + double energytot = energy0_ + energy1_; - float psum2 = (px0 + px1) * (px0 + px1) + - (py0 + py1) * (py0 + py1) + - (pz0 + pz1) * (pz0 + pz1); + double psum2 = (px0 + px1) * (px0 + px1) + + (py0 + py1) * (py0 + py1) + + (pz0 + pz1) * (pz0 + pz1); return energytot * energytot - psum2; }; -float invmass3prongs2(float px0, float py0, float pz0, float mass0, - float px1, float py1, float pz1, float mass1, - float px2, float py2, float pz2, float mass2) +double invmass3prongs2(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1, + double px2, double py2, double pz2, double mass2) { - float energy0_ = energy(px0, py0, pz0, mass0); - float energy1_ = energy(px1, py1, pz1, mass1); - float energy2_ = energy(px2, py2, pz2, mass2); - float energytot = energy0_ + energy1_ + energy2_; - - float psum2 = (px0 + px1 + px2) * (px0 + px1 + px2) + - (py0 + py1 + py2) * (py0 + py1 + py2) + - (pz0 + pz1 + pz2) * (pz0 + pz1 + pz2); + double energy0_ = energy(px0, py0, pz0, mass0); + double energy1_ = energy(px1, py1, pz1, mass1); + double energy2_ = energy(px2, py2, pz2, mass2); + double energytot = energy0_ + energy1_ + energy2_; + + double psum2 = (px0 + px1 + px2) * (px0 + px1 + px2) + + (py0 + py1 + py2) * (py0 + py1 + py2) + + (pz0 + pz1 + pz2) * (pz0 + pz1 + pz2); return energytot * energytot - psum2; }; -float invmass2prongs(float px0, float py0, float pz0, float mass0, - float px1, float py1, float pz1, float mass1) +double invmass2prongs(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1) { return sqrt(invmass2prongs2(px0, py0, pz0, mass0, px1, py1, pz1, mass1)); }; -float invmass3prongs(float px0, float py0, float pz0, float mass0, - float px1, float py1, float pz1, float mass1, - float px2, float py2, float pz2, float mass2) +double invmass3prongs(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1, + double px2, double py2, double pz2, double mass2) { return sqrt(invmass3prongs2(px0, py0, pz0, mass0, px1, py1, pz1, mass1, px2, py2, pz2, mass2)); }; -float ptcand2prong(float px0, float py0, float px1, float py1) +double ptcand2prong(double px0, double py0, double px1, double py1) { return sqrt((px0 + px1) * (px0 + px1) + (py0 + py1) * (py0 + py1)); }; -float pttrack(float px, float py) +double pttrack(double px, double py) { return sqrt(px * px + py * py); }; -float declength(float xdecay, float ydecay, float zdecay, float xvtx, float yvtx, float zvtx) +double declength(double xdecay, double ydecay, double zdecay, double xvtx, double yvtx, double zvtx) { - return sqrtf((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx) + (zdecay - zvtx) * (zdecay - zvtx)); + return sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx) + (zdecay - zvtx) * (zdecay - zvtx)); }; -float declengthxy(float xdecay, float ydecay, float xvtx, float yvtx) +double declengthxy(double xdecay, double ydecay, double xvtx, double yvtx) { - return sqrtf((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx)); + return sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx)); }; +/// Add a track object to a list. +/// \param list vector of track objects +/// \param momentum 3-momentum components (x, y, z) +/// \param temporal mass or energy (depends on the vector type) +template <typename T, typename U, typename V> +void addTrack(std::vector<T>& list, U momentum_x, U momentum_y, U momentum_z, V temporal) +{ + T track(momentum_x, momentum_y, momentum_z, temporal); + list.push_back(track); +} + +/// Add a track object to a list. +/// \param list vector of track objects +/// \param momentum array of 3-momentum components (x, y, z) +/// \param temporal mass or energy (depends on the vector type) +template <typename T, typename U, typename V> +void addTrack(std::vector<T>& list, const std::array<U, 3>& momentum, V temporal) +{ + addTrack(list, momentum[0], momentum[1], momentum[2], temporal); +} + +/// Sum up track objects in a list. +/// \param list vector of track objects +/// \return Return the sum of the vector elements. +template <typename T> +T sumOfTracks(const std::vector<T>& list) +{ + T sum; + for (const auto& track : list) { + sum += track; + } + return sum; +} + #endif // O2_ANALYSIS_RECODECAY_H_ diff --git a/Analysis/DataModel/include/Analysis/trackUtilities.h b/Analysis/DataModel/include/Analysis/trackUtilities.h new file mode 100644 index 0000000000000..47dcdacc24300 --- /dev/null +++ b/Analysis/DataModel/include/Analysis/trackUtilities.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. + +/// \file Utilities for manipulating track parameters +/// +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + +#ifndef O2_ANALYSIS_TRACKUTILITIES_H_ +#define O2_ANALYSIS_TRACKUTILITIES_H_ + +template <typename T> +auto getTrackParCov(T track) +{ + std::array<float, 5> arraypar = {track.y(), track.z(), track.snp(), + track.tgl(), track.signed1Pt()}; + std::array<float, 15> covpar = {track.cYY(), track.cZY(), track.cZZ(), + track.cSnpY(), track.cSnpZ(), + track.cSnpSnp(), track.cTglY(), track.cTglZ(), + track.cTglSnp(), track.cTglTgl(), + track.c1PtY(), track.c1PtZ(), track.c1PtSnp(), + track.c1PtTgl(), track.c1Pt21Pt2()}; + return o2::track::TrackParCov(track.x(), track.alpha(), std::move(arraypar), std::move(covpar)); +} + +#endif // O2_ANALYSIS_TRACKUTILITIES_H_ diff --git a/Analysis/Tasks/hfcandidatecreator2prong.cxx b/Analysis/Tasks/hfcandidatecreator2prong.cxx index 1ec0575169b9a..b593f8f944472 100644 --- a/Analysis/Tasks/hfcandidatecreator2prong.cxx +++ b/Analysis/Tasks/hfcandidatecreator2prong.cxx @@ -15,9 +15,11 @@ #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" #include <TFile.h> #include <TH1F.h> +#include <Math/Vector4D.h> #include <cmath> #include <array> #include <cstdlib> @@ -26,6 +28,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +using namespace ROOT::Math; struct HFCandidateCreator2Prong { Produces<aod::HfCandProng2> hfcandprong2; @@ -56,30 +59,13 @@ struct HFCandidateCreator2Prong { df.setMinParamChange(d_minparamchange); df.setMinRelChi2Change(d_minrelchi2change); - for (auto& hfpr2 : hftrackindexprong2s) { - float x_p1 = hfpr2.index0().x(); - float alpha_p1 = hfpr2.index0().alpha(); - std::array<float, 5> arraypar_p1 = {hfpr2.index0().y(), hfpr2.index0().z(), hfpr2.index0().snp(), - hfpr2.index0().tgl(), hfpr2.index0().signed1Pt()}; - std::array<float, 15> covpar_p1 = {hfpr2.index0().cYY(), hfpr2.index0().cZY(), hfpr2.index0().cZZ(), - hfpr2.index0().cSnpY(), hfpr2.index0().cSnpZ(), - hfpr2.index0().cSnpSnp(), hfpr2.index0().cTglY(), hfpr2.index0().cTglZ(), - hfpr2.index0().cTglSnp(), hfpr2.index0().cTglTgl(), - hfpr2.index0().c1PtY(), hfpr2.index0().c1PtZ(), hfpr2.index0().c1PtSnp(), - hfpr2.index0().c1PtTgl(), hfpr2.index0().c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar_p1(x_p1, alpha_p1, arraypar_p1, covpar_p1); + std::vector<PxPyPzMVector> listTracks; + double masspion = 0.140; + double masskaon = 0.494; - float x_n1 = hfpr2.index1().x(); - float alpha_n1 = hfpr2.index1().alpha(); - std::array<float, 5> arraypar_n1 = {hfpr2.index1().y(), hfpr2.index1().z(), hfpr2.index1().snp(), - hfpr2.index1().tgl(), hfpr2.index1().signed1Pt()}; - std::array<float, 15> covpar_n1 = {hfpr2.index1().cYY(), hfpr2.index1().cZY(), hfpr2.index1().cZZ(), - hfpr2.index1().cSnpY(), hfpr2.index1().cSnpZ(), - hfpr2.index1().cSnpSnp(), hfpr2.index1().cTglY(), hfpr2.index1().cTglZ(), - hfpr2.index1().cTglSnp(), hfpr2.index1().cTglTgl(), - hfpr2.index1().c1PtY(), hfpr2.index1().c1PtZ(), hfpr2.index1().c1PtSnp(), - hfpr2.index1().c1PtTgl(), hfpr2.index1().c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar_n1(x_n1, alpha_n1, arraypar_n1, covpar_n1); + for (auto& hfpr2 : hftrackindexprong2s) { + auto trackparvar_p1 = getTrackParCov(hfpr2.index0()); + auto trackparvar_n1 = getTrackParCov(hfpr2.index1()); df.setUseAbsDCA(true); int nCand = df.process(trackparvar_p1, trackparvar_n1); if (nCand == 0) @@ -89,16 +75,15 @@ struct HFCandidateCreator2Prong { std::array<float, 3> pvec1; df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); - float masspion = 0.140; - float masskaon = 0.494; - float mass_ = sqrt(invmass2prongs2(pvec0[0], pvec0[1], - pvec0[2], masspion, - pvec1[0], pvec1[1], - pvec1[2], masskaon)); - float masssw_ = sqrt(invmass2prongs2(pvec0[0], pvec0[1], - pvec0[2], masskaon, - pvec1[0], pvec1[1], - pvec1[2], masspion)); + + addTrack(listTracks, pvec0, masspion); + addTrack(listTracks, pvec1, masskaon); + double mass_ = (sumOfTracks(listTracks)).M(); + listTracks[0].SetM(masskaon); + listTracks[1].SetM(masspion); + double masssw_ = (sumOfTracks(listTracks)).M(); + listTracks.clear(); + hfcandprong2(collision.posX(), collision.posY(), collision.posZ(), pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], vtx[0], vtx[1], vtx[2], mass_, masssw_); diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index c7208ee46ef86..f465ff1fbdba0 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -15,9 +15,11 @@ #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" #include <TFile.h> #include <TH1F.h> +#include <Math/Vector4D.h> #include <cmath> #include <array> #include <cstdlib> @@ -26,6 +28,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +using namespace ROOT::Math; namespace o2::aod { @@ -67,17 +70,7 @@ struct SelectTracks { if (!isselected_0) status = 0; array<float, 2> dca; - float x0_ = track_0.x(); - float alpha0_ = track_0.alpha(); - std::array<float, 5> arraypar0 = {track_0.y(), track_0.z(), track_0.snp(), - track_0.tgl(), track_0.signed1Pt()}; - std::array<float, 15> covpar0 = {track_0.cYY(), track_0.cZY(), track_0.cZZ(), - track_0.cSnpY(), track_0.cSnpZ(), - track_0.cSnpSnp(), track_0.cTglY(), track_0.cTglZ(), - track_0.cTglSnp(), track_0.cTglTgl(), - track_0.c1PtY(), track_0.c1PtZ(), track_0.c1PtSnp(), - track_0.c1PtTgl(), track_0.c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar0(x0_, alpha0_, arraypar0, covpar0); + auto trackparvar0 = getTrackParCov(track_0); trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca); if (abs(dca[0]) < dcatoprimxymin) status = 0; @@ -93,8 +86,9 @@ struct SelectTracks { }; struct HFTrackIndexSkimsCreator { - float masspion = 0.140; - float masskaon = 0.494; + std::vector<PxPyPzMVector> listTracks; + double masspion = 0.140; + double masskaon = 0.494; OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; Produces<aod::HfTrackIndexProng2> hftrackindexprong2; @@ -150,32 +144,12 @@ struct HFTrackIndexSkimsCreator { auto& track_p1 = *i_p1; if (track_p1.signed1Pt() < 0) continue; - float x_p1 = track_p1.x(); - float alpha_p1 = track_p1.alpha(); - std::array<float, 5> arraypar_p1 = {track_p1.y(), track_p1.z(), track_p1.snp(), - track_p1.tgl(), track_p1.signed1Pt()}; - std::array<float, 15> covpar_p1 = {track_p1.cYY(), track_p1.cZY(), track_p1.cZZ(), - track_p1.cSnpY(), track_p1.cSnpZ(), - track_p1.cSnpSnp(), track_p1.cTglY(), track_p1.cTglZ(), - track_p1.cTglSnp(), track_p1.cTglTgl(), - track_p1.c1PtY(), track_p1.c1PtZ(), track_p1.c1PtSnp(), - track_p1.c1PtTgl(), track_p1.c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar_p1(x_p1, alpha_p1, arraypar_p1, covpar_p1); + auto trackparvar_p1 = getTrackParCov(track_p1); for (auto i_n1 = tracks.begin(); i_n1 != tracks.end(); ++i_n1) { auto& track_n1 = *i_n1; if (track_n1.signed1Pt() > 0) continue; - float x_n1 = track_n1.x(); - float alpha_n1 = track_n1.alpha(); - std::array<float, 5> arraypar_n1 = {track_n1.y(), track_n1.z(), track_n1.snp(), - track_n1.tgl(), track_n1.signed1Pt()}; - std::array<float, 15> covpar_n1 = {track_n1.cYY(), track_n1.cZY(), track_n1.cZZ(), - track_n1.cSnpY(), track_n1.cSnpZ(), - track_n1.cSnpSnp(), track_n1.cTglY(), track_n1.cTglZ(), - track_n1.cTglSnp(), track_n1.cTglTgl(), - track_n1.c1PtY(), track_n1.c1PtZ(), track_n1.c1PtSnp(), - track_n1.c1PtTgl(), track_n1.c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar_n1(x_n1, alpha_n1, arraypar_n1, covpar_n1); + auto trackparvar_n1 = getTrackParCov(track_n1); df.setUseAbsDCA(true); int nCand = df.process(trackparvar_p1, trackparvar_n1); if (nCand == 0) @@ -185,14 +159,15 @@ struct HFTrackIndexSkimsCreator { std::array<float, 3> pvec1; df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); - float mass_ = sqrt(invmass2prongs2(pvec0[0], pvec0[1], - pvec0[2], masspion, - pvec1[0], pvec1[1], - pvec1[2], masskaon)); - float masssw_ = sqrt(invmass2prongs2(pvec0[0], pvec0[1], - pvec0[2], masskaon, - pvec1[0], pvec1[1], - pvec1[2], masspion)); + + addTrack(listTracks, pvec0, masspion); + addTrack(listTracks, pvec1, masskaon); + double mass_ = (sumOfTracks(listTracks)).M(); + listTracks[0].SetM(masskaon); + listTracks[1].SetM(masspion); + double masssw_ = (sumOfTracks(listTracks)).M(); + listTracks.clear(); + if (b_dovalplots == true) { hmass2->Fill(mass_); hmass2->Fill(masssw_); @@ -206,24 +181,18 @@ struct HFTrackIndexSkimsCreator { auto& track_p2 = *i_p2; if (track_p2.signed1Pt() < 0) continue; - float x_p2 = track_p2.x(); - float alpha_p2 = track_p2.alpha(); - double mass3prong2 = invmass3prongs2(track_p1.px(), track_p1.py(), track_p1.pz(), masspion, - track_n1.px(), track_n1.py(), track_n1.pz(), masskaon, - track_p2.px(), track_p2.py(), track_p2.pz(), masspion); - if (mass3prong2 < d_minmassDp * d_minmassDp || mass3prong2 > d_maxmassDp * d_maxmassDp) + + addTrack(listTracks, track_p1.px(), track_p1.py(), track_p1.pz(), masspion); + addTrack(listTracks, track_n1.px(), track_n1.py(), track_n1.pz(), masskaon); + addTrack(listTracks, track_p2.px(), track_p2.py(), track_p2.pz(), masspion); + double mass3prong = (sumOfTracks(listTracks)).M(); + listTracks.clear(); + + if (mass3prong < d_minmassDp || mass3prong > d_maxmassDp) continue; if (b_dovalplots == true) - hmass3->Fill(sqrt(mass3prong2)); - std::array<float, 5> arraypar_p2 = {track_p2.y(), track_p2.z(), track_p2.snp(), - track_p2.tgl(), track_p2.signed1Pt()}; - std::array<float, 15> covpar_p2 = {track_p2.cYY(), track_p2.cZY(), track_p2.cZZ(), - track_p2.cSnpY(), track_p2.cSnpZ(), - track_p2.cSnpSnp(), track_p2.cTglY(), track_p2.cTglZ(), - track_p2.cTglSnp(), track_p2.cTglTgl(), - track_p2.c1PtY(), track_p2.c1PtZ(), track_p2.c1PtSnp(), - track_p2.c1PtTgl(), track_p2.c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar_p2(x_p2, alpha_p2, arraypar_p2, covpar_p2); + hmass3->Fill(mass3prong); + auto trackparvar_p2 = getTrackParCov(track_p2); df3.setUseAbsDCA(true); int nCand3 = df3.process(trackparvar_p1, trackparvar_n1, trackparvar_p2); if (nCand3 == 0) @@ -235,12 +204,13 @@ struct HFTrackIndexSkimsCreator { df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); df.getTrack(2).getPxPyPzGlo(pvec2); - float mass_ = sqrt(invmass3prongs2(pvec0[0], pvec0[1], - pvec0[2], masspion, - pvec1[0], pvec1[1], - pvec1[2], masskaon, - pvec2[0], pvec2[1], - pvec2[2], masspion)); + + addTrack(listTracks, pvec0, masspion); + addTrack(listTracks, pvec1, masskaon); + addTrack(listTracks, pvec2, masspion); + double mass_ = (sumOfTracks(listTracks)).M(); + listTracks.clear(); + if (b_dovalplots == true) { hmass3->Fill(mass_); } @@ -254,23 +224,17 @@ struct HFTrackIndexSkimsCreator { auto& track_n2 = *i_n2; if (track_n2.signed1Pt() > 0) continue; - float x_n2 = track_n2.x(); - float alpha_n2 = track_n2.alpha(); - double mass3prong2 = invmass3prongs2(track_n1.px(), track_n1.py(), track_n1.pz(), masspion, - track_p1.px(), track_p1.py(), track_p1.pz(), masskaon, - track_n2.px(), track_n2.py(), track_n2.pz(), masspion); - if (mass3prong2 < d_minmassDp * d_minmassDp || mass3prong2 > d_maxmassDp * d_maxmassDp) + + addTrack(listTracks, track_n1.px(), track_n1.py(), track_n1.pz(), masspion); + addTrack(listTracks, track_p1.px(), track_p1.py(), track_p1.pz(), masskaon); + addTrack(listTracks, track_n2.px(), track_n2.py(), track_n2.pz(), masspion); + double mass3prong = (sumOfTracks(listTracks)).M(); + listTracks.clear(); + + if (mass3prong < d_minmassDp || mass3prong > d_maxmassDp) continue; - hmass3->Fill(sqrt(mass3prong2)); - std::array<float, 5> arraypar_n2 = {track_n2.y(), track_n2.z(), track_n2.snp(), - track_n2.tgl(), track_n2.signed1Pt()}; - std::array<float, 15> covpar_n2 = {track_n2.cYY(), track_n2.cZY(), track_n2.cZZ(), - track_n2.cSnpY(), track_n2.cSnpZ(), - track_n2.cSnpSnp(), track_n2.cTglY(), track_n2.cTglZ(), - track_n2.cTglSnp(), track_n2.cTglTgl(), - track_n2.c1PtY(), track_n2.c1PtZ(), track_n2.c1PtSnp(), - track_n2.c1PtTgl(), track_n2.c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar_n2(x_n2, alpha_n2, arraypar_n2, covpar_n2); + hmass3->Fill(mass3prong); + auto trackparvar_n2 = getTrackParCov(track_n2); df3.setUseAbsDCA(true); int nCand3 = df3.process(trackparvar_n1, trackparvar_p1, trackparvar_n2); if (nCand3 == 0) @@ -282,12 +246,13 @@ struct HFTrackIndexSkimsCreator { df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); df.getTrack(2).getPxPyPzGlo(pvec2); - float mass_ = sqrt(invmass3prongs2(pvec0[0], pvec0[1], - pvec0[2], masspion, - pvec1[0], pvec1[1], - pvec1[2], masskaon, - pvec2[0], pvec2[1], - pvec2[2], masspion)); + + addTrack(listTracks, pvec0, masspion); + addTrack(listTracks, pvec1, masskaon); + addTrack(listTracks, pvec2, masspion); + double mass_ = (sumOfTracks(listTracks)).M(); + listTracks.clear(); + if (b_dovalplots == true) { hmass3->Fill(mass_); } From 6d54e0e4ca03330fef185dd0ef04bb13bff0587f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Thu, 16 Jul 2020 19:21:46 +0200 Subject: [PATCH 0113/1751] Renamed setters for CCDB manager and remove TNamed inheritance (#3997) * Rename setter for Caching/ValidityChecking - Add few lines to CCDB README * Remove TNamed inheritance * Remove default url and path for converter * move uint -> unsigned int --- .../Core/include/Analysis/RunToTimestamp.h | 19 +++++++++---------- Analysis/Core/src/InsertNewRunToTimestamp.cxx | 6 +++--- Analysis/Core/src/RunToTimestamp.cxx | 11 ++++++----- .../Scripts/insert_Run2_run_to_timestamps.py | 5 +---- Analysis/Tasks/centralityTable.cxx | 4 ++-- Analysis/Tasks/eventSelection.cxx | 4 ++-- Analysis/Tutorials/src/ccdbaccess.cxx | 2 +- CCDB/README.md | 7 ++++++- CCDB/include/CCDB/BasicCCDBManager.h | 6 +++--- CCDB/test/testBasicCCDBManager.cxx | 4 ++-- 10 files changed, 35 insertions(+), 33 deletions(-) diff --git a/Analysis/Core/include/Analysis/RunToTimestamp.h b/Analysis/Core/include/Analysis/RunToTimestamp.h index d721b43b7f32d..6dabf861e267e 100644 --- a/Analysis/Core/include/Analysis/RunToTimestamp.h +++ b/Analysis/Core/include/Analysis/RunToTimestamp.h @@ -17,33 +17,32 @@ #define RunToTimestamp_H #include <map> -#include <FairLogger.h> -#include "TNamed.h" +#include <Rtypes.h> -class RunToTimestamp : public TNamed +class RunToTimestamp { public: RunToTimestamp() = default; - ~RunToTimestamp() final = default; + ~RunToTimestamp() = default; /// Checks if the converter has a particular run - bool Has(uint runNumber) const { return mMap.count(runNumber); } + bool Has(unsigned int runNumber) const { return mMap.count(runNumber); } /// Inserts a new run with a timestamp in the converter database - bool insert(uint runNumber, long timestamp); + bool insert(unsigned int runNumber, long timestamp); /// Updates an already present run number with a new timestamp - bool update(uint runNumber, long timestamp); + bool update(unsigned int runNumber, long timestamp); /// Gets the timestamp of a run - long getTimestamp(uint runNumber) const; + long getTimestamp(unsigned int runNumber) const; /// Prints the content of the converter void print() const; private: - std::map<uint, long> mMap; - ClassDef(RunToTimestamp, 1) // converter class between run number and timestamp + std::map<unsigned int, long> mMap; + ClassDefNV(RunToTimestamp, 1) // converter class between run number and timestamp }; #endif diff --git a/Analysis/Core/src/InsertNewRunToTimestamp.cxx b/Analysis/Core/src/InsertNewRunToTimestamp.cxx index c2036cac1f72b..ae00495e2d14a 100644 --- a/Analysis/Core/src/InsertNewRunToTimestamp.cxx +++ b/Analysis/Core/src/InsertNewRunToTimestamp.cxx @@ -25,7 +25,7 @@ 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<uint>()->required(), "Run number to use")( + "run,r", bpo::value<unsigned int>()->required(), "Run number to use")( "timestamp,t", bpo::value<long>()->required(), "Timestamp to use equivalent to the run number")( "path,p", bpo::value<std::string>()->default_value("Analysis/Core/RunToTimestamp"), "Path to the object in the CCDB repository")( "url,u", bpo::value<std::string>()->default_value("http://ccdb-test.cern.ch:8080"), "URL of the CCDB database")( @@ -90,9 +90,9 @@ int main(int argc, char* argv[]) } if (vm["update"].as<int>()) - converter->update(vm["run"].as<uint>(), vm["timestamp"].as<long>()); + converter->update(vm["run"].as<unsigned int>(), vm["timestamp"].as<long>()); else - converter->insert(vm["run"].as<uint>(), vm["timestamp"].as<long>()); + converter->insert(vm["run"].as<unsigned int>(), vm["timestamp"].as<long>()); if (vm["verbose"].as<int>()) converter->print(); diff --git a/Analysis/Core/src/RunToTimestamp.cxx b/Analysis/Core/src/RunToTimestamp.cxx index 6b9a21f51468b..dffff7b63c04d 100644 --- a/Analysis/Core/src/RunToTimestamp.cxx +++ b/Analysis/Core/src/RunToTimestamp.cxx @@ -14,13 +14,14 @@ // Author: Nicolo' Jacazio on 2020-06-22 #include "Analysis/RunToTimestamp.h" +#include <FairLogger.h> ClassImp(RunToTimestamp); -bool RunToTimestamp::insert(uint runNumber, long timestamp) +bool RunToTimestamp::insert(unsigned int runNumber, long timestamp) { - std::pair<std::map<uint, long>::iterator, bool> check; - check = mMap.insert(std::pair<uint, long>(runNumber, timestamp)); + std::pair<std::map<unsigned int, long>::iterator, bool> check; + check = mMap.insert(std::pair<unsigned int, long>(runNumber, timestamp)); if (!check.second) { LOG(FATAL) << "Run number " << runNumber << " already existed with a timestamp of " << check.first->second; return false; @@ -29,7 +30,7 @@ bool RunToTimestamp::insert(uint runNumber, long timestamp) return true; } -bool RunToTimestamp::update(uint runNumber, long timestamp) +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"; @@ -39,7 +40,7 @@ bool RunToTimestamp::update(uint runNumber, long timestamp) return true; } -long RunToTimestamp::getTimestamp(uint runNumber) const +long RunToTimestamp::getTimestamp(unsigned int runNumber) const { if (!Has(runNumber)) { LOG(ERROR) << "Run to Timestamp converter does not have run " << runNumber; diff --git a/Analysis/Scripts/insert_Run2_run_to_timestamps.py b/Analysis/Scripts/insert_Run2_run_to_timestamps.py index c7bcab2d1c739..227f047635a75 100755 --- a/Analysis/Scripts/insert_Run2_run_to_timestamps.py +++ b/Analysis/Scripts/insert_Run2_run_to_timestamps.py @@ -72,8 +72,7 @@ def __eq__(self, other): def main(input_file_name, extra_args, - input_in_seconds=False, delete_previous=True, verbose=False, - url="http://ccdb-test.cern.ch:8080", path="Analysis/Core/RunToTimestamp"): + 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. @@ -119,8 +118,6 @@ def main(input_file_name, extra_args, cmd = "o2-analysiscore-makerun2timestamp" cmd += f" --run {i.run}" cmd += f" --timestamp {i.start}" - cmd += f" --url {url}" - cmd += f" --path {path}" if delete_previous: cmd += f" --delete_previous 1" cmd += f" {extra_args}" diff --git a/Analysis/Tasks/centralityTable.cxx b/Analysis/Tasks/centralityTable.cxx index ec7a43c514499..ffa4337255db5 100644 --- a/Analysis/Tasks/centralityTable.cxx +++ b/Analysis/Tasks/centralityTable.cxx @@ -25,8 +25,8 @@ struct CentralityTableTask { void init(InitContext&) { ccdb->setURL("http://ccdb-test.cern.ch:8080"); - ccdb->setCachingEnabled(true); - ccdb->setValidityCheckingEnabled(); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); } void process(soa::Join<aod::Collisions, aod::Mults>::iterator const& collision, aod::Timestamps& timestamps, aod::BCs const& bcs) diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index a10b432bf7ddb..b48adecd40b24 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -87,8 +87,8 @@ struct EventSelectionTask { void init(InitContext&) { ccdb->setURL("http://ccdb-test.cern.ch:8080"); - ccdb->setCachingEnabled(true); - ccdb->setValidityCheckingEnabled(); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); } void process(aod::Collision const& collision, aod::BCs const& bcs, aod::Timestamps& timestamps, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs const& fdds) diff --git a/Analysis/Tutorials/src/ccdbaccess.cxx b/Analysis/Tutorials/src/ccdbaccess.cxx index c697236bf2ec2..5c9036542f3fc 100644 --- a/Analysis/Tutorials/src/ccdbaccess.cxx +++ b/Analysis/Tutorials/src/ccdbaccess.cxx @@ -36,7 +36,7 @@ struct TimestampUserTask { // Set CCDB url ccdb->setURL(url.value); // Enabling object caching - ccdb->setCachingEnabled(true); + ccdb->setCaching(true); // Not later than now objects ccdb->setCreatedNotAfter(nolaterthan.value); } diff --git a/CCDB/README.md b/CCDB/README.md index 97796f6bd8429..adcc993c950f1 100644 --- a/CCDB/README.md +++ b/CCDB/README.md @@ -92,9 +92,14 @@ unless the validity range of the cached object does not match to requested times In case user wants to enforce a fresh copy loading, the cache for particular CCDB path can be cleaned by invoking `mgr.clear(<path>)`. One can also reset whole cache using `mgr.clear()`. -Uncached mode can be imposed by invoking `mgr.setCachingEnabled(false)`, in which case every query will retrieve a new copy of object from the server and +Uncached mode can be imposed by invoking `mgr.setCaching(false)`, in which case every query will retrieve a new copy of object from the server and the user should take care himself of deleting retrieved objects to avoid memory leaks. +Upper and lower limits on the object creation time can be set by `mgr.setCreatedNotAfter(upper_limit_timestamp)` and `mgr.setCreatedNotBefore(lower_limit_timestamp)`, it specifies the fields "If-Not-After" and "If-Not-Before" when retrieving an object from CCDB. +This feature is useful to avoid using newer objects if the CCDB is updated in parallel to the task execution. + +In cached mode, the manager can check that local objects are still valid by requiring `mgr.setLocalObjectValidityChecking(true)`, in this case a CCDB query is performed only if the cached object is no longer valid. + ## Future ideas / todo: - [ ] offer improved error handling / exceptions diff --git a/CCDB/include/CCDB/BasicCCDBManager.h b/CCDB/include/CCDB/BasicCCDBManager.h index 215fb4558283b..b34cce62fc93a 100644 --- a/CCDB/include/CCDB/BasicCCDBManager.h +++ b/CCDB/include/CCDB/BasicCCDBManager.h @@ -87,7 +87,7 @@ class BasicCCDBManager bool isCachingEnabled() const { return mCachingEnabled; } /// disable or enable caching - void setCachingEnabled(bool v) + void setCaching(bool v) { mCachingEnabled = v; if (!v) { @@ -96,10 +96,10 @@ class BasicCCDBManager } /// check if checks of object validity before CCDB query is enabled - bool isValidityCheckingEnabled() const { return mCheckObjValidityEnabled; } + bool isLocalObjectValidityCheckingEnabled() const { return mCheckObjValidityEnabled; } /// set the flag to check object validity before CCDB query - void setValidityCheckingEnabled(bool v = true) { mCheckObjValidityEnabled = v; } + void setLocalObjectValidityChecking(bool v = true) { mCheckObjValidityEnabled = v; } /// set the object upper validity limit void setCreatedNotAfter(long v) { mCreatedNotAfter = v; } diff --git a/CCDB/test/testBasicCCDBManager.cxx b/CCDB/test/testBasicCCDBManager.cxx index 956a3da911643..3a49d56172c7f 100644 --- a/CCDB/test/testBasicCCDBManager.cxx +++ b/CCDB/test/testBasicCCDBManager.cxx @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(TestBasicCCDBManager) auto& cdb = o2::ccdb::BasicCCDBManager::instance(); cdb.setURL(uri); cdb.setTimestamp((start + stop) / 2); - cdb.setCachingEnabled(true); + cdb.setCaching(true); auto* objA = cdb.get<std::string>(pathA); // will be loaded from scratch and fill the cache LOG(INFO) << "1st reading of A: " << *objA; @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE(TestBasicCCDBManager) cdb.resetCreatedNotBefore(); // resetting upper validity limit // disable cache at all (will also clean it) - cdb.setCachingEnabled(false); + cdb.setCaching(false); objA = cdb.get<std::string>(pathA); // will be loaded from scratch, w/o filling the cache LOG(INFO) << "Reading A after disabling the cache: " << *objA; BOOST_CHECK(objA && (*objA) == ccdbObjO); // make sure correct object is loaded From 40e219add710b3de773541e095a0241cc3fa116a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 17 Jul 2020 15:26:36 +0200 Subject: [PATCH 0114/1751] Introduce a Github Action to force cleanup of build status of a PR (#4004) Can be triggered by hand from the Actions web page. --- .github/workflows/clean-test.yml | 66 ++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/clean-test.yml diff --git a/.github/workflows/clean-test.yml b/.github/workflows/clean-test.yml new file mode 100644 index 0000000000000..f50d62f142043 --- /dev/null +++ b/.github/workflows/clean-test.yml @@ -0,0 +1,66 @@ +name: Clean PR checks +on: + workflow_dispatch: + inputs: + pr: + description: PR to be cleaned + required: true + checks: + description: Checks to be cleaned + required: true + default: 'build/O2/o2,build/O2/gpu,build/AliceO2/O2/o2/macOS,build/o2checkcode/o2' + owner: + description: Organization + required: true + default: 'AliceO2Group' + repo: + description: Repository + required: true + default: 'AliceO2' + +jobs: + cleanup_pr_checks: + runs-on: ubuntu-latest + steps: + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + - name: Install ali-bot + run: | + sudo apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev + python -m pip install --upgrade pip + pip install git+https://github.com/alisw/ali-bot@master + - uses: octokit/graphql-action@v2.x + id: get_last_commit_for_pr + with: + query: | + { + repository(owner: "${{ github.event.inputs.owner }}", name: "${{ github.event.inputs.repo }}") { + url + pullRequest(number:${{ github.event.inputs.pr }}) { + commits(last: 1) { + nodes { + commit { + oid + } + } + } + } + } + } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Cleanup tests + run: |- + set -x + cat <<\EOF > results.json + ${{ steps.get_last_commit_for_pr.outputs.data }} + EOF + COMMIT=$(jq -r '.repository.pullRequest.commits.nodes[].commit.oid' results.json) + echo $COMMIT + for check in `echo ${{ github.event.inputs.checks }} | tr , \\n`; do + set-github-status -c ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }}@$COMMIT -s $check/pending + done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 28575998531862b97a6c24d9d39dde1876406f65 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 17 Jul 2020 15:29:54 +0200 Subject: [PATCH 0115/1751] Correctly escape \n --- .github/workflows/clean-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clean-test.yml b/.github/workflows/clean-test.yml index f50d62f142043..69b73d51ab3d5 100644 --- a/.github/workflows/clean-test.yml +++ b/.github/workflows/clean-test.yml @@ -59,7 +59,7 @@ jobs: EOF COMMIT=$(jq -r '.repository.pullRequest.commits.nodes[].commit.oid' results.json) echo $COMMIT - for check in `echo ${{ github.event.inputs.checks }} | tr , \\n`; do + for check in `echo ${{ github.event.inputs.checks }} | tr , \\\\n`; do set-github-status -c ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }}@$COMMIT -s $check/pending done env: From 4b6e337f02d61736fb4e46846f065ccf4f99c27e Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Thu, 16 Jul 2020 17:11:26 +0200 Subject: [PATCH 0116/1751] [EMCAL-658] Fix calculation of pos. in sm from global pos - Fix calculation of SM ID (GetEta and GetPhi returning number of modules, not towers) - Fix column shift of the DCAL odd supermodules - Add exception for invalid row-col position, either with row/col outside the valid area or within the PHOS hole - Throw InvalidCellIDException for cell index outside range --- Detectors/EMCAL/base/CMakeLists.txt | 4 +++ .../EMCAL/base/include/EMCALBase/Geometry.h | 16 +++++++++ .../base/include/EMCALBase/GeometryBase.h | 34 ++++++++++++++++++ Detectors/EMCAL/base/src/Geometry.cxx | 24 ++++++++++--- .../base/test/testGeometryRowColIndexing.C | 36 +++++++++++++++++++ 5 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 Detectors/EMCAL/base/test/testGeometryRowColIndexing.C diff --git a/Detectors/EMCAL/base/CMakeLists.txt b/Detectors/EMCAL/base/CMakeLists.txt index 62b399719b9ed..b86b579230afb 100644 --- a/Detectors/EMCAL/base/CMakeLists.txt +++ b/Detectors/EMCAL/base/CMakeLists.txt @@ -36,3 +36,7 @@ o2_add_test(Mapper COMPONENT_NAME emcal LABELS emcal ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage) + +o2_add_test_root_macro(test/testGeometryRowColIndexing.C + PUBLIC_LINK_LIBRARIES O2::EMCALBase + LABELS emcal) \ No newline at end of file diff --git a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h index a7c0b64012519..9e21cc9422265 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h @@ -186,9 +186,19 @@ class Geometry Float_t GetDCALStandardPhiMax() const { return mDCALStandardPhiMax; } Int_t GetNECLayers() const { return mNECLayers; } Float_t GetDCALInnerExtandedEta() const { return mDCALInnerExtandedEta; } + + /// \brief Get the number of modules in supermodule in z- (beam) direction + /// \return Number of modules Int_t GetNZ() const { return mNZ; } + + /// \brief Get the number of modules in supermodule in #eta direction + /// \return Number of modules Int_t GetNEta() const { return mNZ; } + + /// \brief Get the number of modules in supermodule in #phi direction + /// \return Number of modules Int_t GetNPhi() const { return mNPhi; } + Float_t GetECPbRadThick() const { return mECPbRadThickness; } Float_t GetECScintThick() const { return mECScintThick; } Float_t GetSampling() const { return mSampling; } @@ -336,34 +346,40 @@ class Geometry /// \brief get (Column,Row) pair of cell in global numbering scheme /// \param cellID Absolute cell ID /// \return tuple with position in global numbering scheme (0 - row, 1 - column) + /// \throw InvalidCellIDException std::tuple<int, int> GlobalRowColFromIndex(int cellID) const; /// \brief Get column number of cell in global numbering scheme /// \param cellID Absolute cell ID /// \return Column number in global numbering scheme + /// \throw InvalidCellIDException int GlobalCol(int cellID) const; /// \brief Get row number of cell in global numbering scheme /// \param cellID Absolute cell ID /// \return Row number in global numbering scheme + /// \throw InvalidCellIDException int GlobalRow(int cellID) const; /// \brief Get the absolute cell ID from global position in the EMCAL /// \param row Global row ID /// \param col Global col ID /// \return absolute cell ID + /// \throw RowColException int GetCellAbsIDFromGlobalRowCol(int row, int col) const; /// \brief Get the posision (row, col) of a global row-col position /// \param row Global row ID /// \param col Global col ID /// \return Position in supermodule: [0 - supermodule ID, 1 - row in supermodule - col in supermodule] + /// \throw RowColException std::tuple<int, int, int> GetPositionInSupermoduleFromGlobalRowCol(int col, int row) const; /// \brief Get the cell indices from global position in the EMCAL /// \param row Global row ID /// \param col Global col ID /// \return Cell indices [0 - supermodule, 1 - module, 2 - phi in module, 3 - eta in module] + /// \throw RowColException std::tuple<int, int, int, int> GetCellIndexFromGlobalRowCol(int row, int col) const; /// \brief Given a global eta/phi point check if it belongs to a supermodule covered region. diff --git a/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h b/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h index 2e84ae6e7641d..3af58c7f8ab1c 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h +++ b/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h @@ -189,6 +189,40 @@ class SupermoduleIndexException : public std::exception std::string mMessage; ///< Error message }; +/// \class RowColException +/// \brief Handling error for invalid positions in row-column space +/// \ingroup EMCALBase +class RowColException : public std::exception +{ + public: + /// \brief Constructor, initializing the exception with invalid row-column position + /// \param row Row ID of the position + /// \param col Column ID of the position + RowColException(int row, int col) : mRow(row), mCol(col), mMessage("") + { + mMessage = "Invalid position: row " + std::to_string(mRow) + ", col " + std::to_string(mCol); + } + + /// \brief Destructor + ~RowColException() noexcept final = default; + + /// \brief Get row of the position raising the exception + /// \return Row ID + int getRow() const noexcept { return mRow; } + + /// \brief Get column of the position raising the exception + /// \brief Column ID + int getCol() const noexcept { return mCol; } + + /// \brief Access tp error message of the exception + /// \return Error message + const char* what() const noexcept final { return mMessage.data(); } + + private: + int mRow, mCol; + std::string mMessage; +}; + } // namespace emcal } // namespace o2 diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index 79c2d36e7ec66..d3f3476a6a082 100644 --- a/Detectors/EMCAL/base/src/Geometry.cxx +++ b/Detectors/EMCAL/base/src/Geometry.cxx @@ -756,6 +756,8 @@ Int_t Geometry::GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t iet std::tuple<int, int> Geometry::GlobalRowColFromIndex(int cellID) const { + if (cellID >= GetNCells()) + throw InvalidCellIDException(cellID); auto [supermodule, module, phiInModule, etaInModule] = GetCellIndex(cellID); auto [row, col] = GetCellPhiEtaIndexInSModule(supermodule, module, phiInModule, etaInModule); // add offsets (row / col per supermodule) @@ -778,23 +780,35 @@ std::tuple<int, int> Geometry::GlobalRowColFromIndex(int cellID) const std::tuple<int, int, int> Geometry::GetPositionInSupermoduleFromGlobalRowCol(int row, int col) const { - int side = col > GetNEta() / 2 ? 1 : 0, - colSM = col % (GetNEta() / 2); - int sector = 0, + if (col < 0 || col >= 4 * GetNEta()) + throw RowColException(row, col); + int side = col < GetNEta() * 2 ? 0 : 1, + colSM = col % (GetNEta() * 2); + int sector = -1, rowSM = row; for (int isec = 0; isec < GetNPhiSuperModule(); isec++) { auto smtype = GetSMType(isec * 2); - auto nphism = (smtype == EMCAL_THIRD || smtype == DCAL_EXT) ? GetNPhi() / 3 : GetNPhi(); + auto nphism = GetNPhi() * 2; + if (smtype == EMCAL_THIRD || smtype == DCAL_EXT) + nphism /= 3; if (rowSM < nphism) { sector = isec; break; } rowSM -= nphism; } + if (sector < 0) + throw RowColException(row, col); int supermodule = sector * 2 + side; if (supermodule == 13 || supermodule == 15 || supermodule == 17) { // DCal odd SMs need shift of the col. index as global col index includes PHOS hole - col += 16; + colSM -= 16; + if (colSM < 0) + throw RowColException(row, col); // Position inside PHOS hole specified + } + if (supermodule == 12 || supermodule == 14 || supermodule == 16) { + if (colSM > 32) + throw RowColException(row, col); // Position inside PHOS hole specified } return std::make_tuple(supermodule, rowSM, colSM); } diff --git a/Detectors/EMCAL/base/test/testGeometryRowColIndexing.C b/Detectors/EMCAL/base/test/testGeometryRowColIndexing.C new file mode 100644 index 0000000000000..9006dcdf43277 --- /dev/null +++ b/Detectors/EMCAL/base/test/testGeometryRowColIndexing.C @@ -0,0 +1,36 @@ +// 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 + +void testGeometryRowColIndexing() +{ + auto geo = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); + TH1* habsid = new TH1D("hAbsID", "Cell abs ID", 20001, -0.5, 20000.5); + TH1* hsmod = new TH1D("hsmod", "Supermodule ID", 21, -0.5, 20.5); + for (int icol = 0; icol < 96; icol++) { + for (int irow = 0; irow < 208; irow++) { + // exclude PHOS hole + if (icol >= 32 && icol < 64 && irow >= 128 && irow < 200) + continue; + int absID = geo->GetCellAbsIDFromGlobalRowCol(irow, icol); + habsid->Fill(absID); + auto [smod, mod, iphi, ieta] = geo->GetCellIndexFromGlobalRowCol(irow, icol); + hsmod->Fill(smod); + std::cout << "Col " << icol << ", row " << irow << ": ID " << absID << ", sm " << smod << ", module " << mod << ", iphi " << iphi << ", ieta " << ieta << std::endl; + } + } + auto plot = new TCanvas("geotest", "Geometry test", 1200, 700); + plot->Divide(2, 1); + plot->cd(1); + habsid->Draw(); + plot->cd(2); + hsmod->Draw(); + plot->cd(); + plot->Update(); +} \ No newline at end of file From 7e26d857db9b36ad832deac6439481b77e3cad36 Mon Sep 17 00:00:00 2001 From: Ivana Hrivnacova <Ivana.Hrivnacova@cern.ch> Date: Fri, 17 Jul 2020 15:03:26 +0200 Subject: [PATCH 0117/1751] Update g4config.in with added tuning for killing looping particles (Geant4 VMC v5-0-p5 or development version is required.) --- Detectors/gconfig/g4config.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Detectors/gconfig/g4config.in b/Detectors/gconfig/g4config.in index 28ffdb67fdfb2..e36d1056884dd 100644 --- a/Detectors/gconfig/g4config.in +++ b/Detectors/gconfig/g4config.in @@ -6,6 +6,7 @@ /mcVerbose/opGeometryManager 1 /mcTracking/loopVerbose 1 /mcVerbose/composedPhysicsList 2 +/mcVerbose/runAction 2 # For looping thresholds control #/tracking/verbose 1 #//control/cout/ignoreThreadsExcept 0 @@ -47,6 +48,11 @@ /mcMagField/setMaximumEpsilonStep 1.0e-05 /mcMagField/printParameters +# Change default parameters for killing looping particles +# +/mcPhysics/useHighLooperThresholds +/mcRun/setLooperThresholdImportantEnergy 100. MeV + # Define media with the INCLXX physics list; here basically in all ITS media #/mcVerbose/biasingConfigurationManager 3 /mcPhysics/biasing/setModel inclxx From b2b0910583cad186f1025d6ffca5a76d576a9dd7 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Tue, 14 Jul 2020 15:08:20 +0200 Subject: [PATCH 0118/1751] An example of use of AMPT from AliRoot --- doc/DetectorSimulation.md | 1 + run/SimExamples/AliRoot_AMPT/README.md | 21 ++++ .../AliRoot_AMPT/aliroot_ampt.macro | 103 ++++++++++++++++++ run/SimExamples/AliRoot_AMPT/run.sh | 13 +++ run/SimExamples/README.md | 1 + 5 files changed, 139 insertions(+) create mode 100644 run/SimExamples/AliRoot_AMPT/README.md create mode 100644 run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro create mode 100755 run/SimExamples/AliRoot_AMPT/run.sh diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index 4ed2e4df2d5f8..7aec8594c2530 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -451,6 +451,7 @@ Other helpful resources are the scripts used for regression testing in [prodtest | Example | Short Description | | --------------------- | -------------------------------------------------------------------------------------- | | [AliRoot_Hijing](../run/SimExamples/AliRoot_Hijing) | Example showing how to use Hijing from AliRoot for event generation | +| [AliRoot_AMPT](../run/SimExamples/AliRoot_AMPT) | Example showing how to use AMPT from AliRoot for event generation | | [Adaptive_Pythia8](../run/SimExamples/Adaptive_Pythia8) | Complex example showing **generator configuration for embedding** that cat adapt the response based on the background event | | [Signal_ImpactB](../run/SimExamples/Signal_ImpactB) | Example showing **generator configuration for embedding** that cat adapt to the impact parameter of the background event | | [HepMC_STARlight](../run/SimExamples/HepMC_STARlight) | Simple example showing **generator configuration** that runs a standalone `STARlight` generation that couples to the `o2` via a `HepMC` file | diff --git a/run/SimExamples/AliRoot_AMPT/README.md b/run/SimExamples/AliRoot_AMPT/README.md new file mode 100644 index 0000000000000..bab945e21c0ac --- /dev/null +++ b/run/SimExamples/AliRoot_AMPT/README.md @@ -0,0 +1,21 @@ +<!-- doxy +\page refrunSimExamplesAliRoot_AMPT Example AliRoot_AMPT +/doxy --> + +This is a complex simulation example showing how to run event simulation using the AMPT event generator interface from AliRoot. +A wrapper class AliRoot_AMPT is defined to keep the AliGenAmpt instance and configure it. +It also provides methods to set a random event plane before event generation and to update the event header. +The overall setup is steered by the function `ampt(double energy = 5020., double bMin = 0., double bMax = 20.)` defined in the macro `aliroot_ampt.macro`. + +The macro file is specified via the argument of `--extGenFile` whereas the specific function call to retrieven the configuration is specified via the argument of `--extGenFunc`. + +# IMPORTANT +To run this example you need to load an AliRoot package compatible with the O2. +for more details, https://alice.its.cern.ch/jira/browse/AOGM-246 + +AliRoot needs to be loaded **after** O2 in the following sense: +`alienv enter O2/latest,AliRoot/latest` +The other order may show unresolved symbol problems. + +# WARNING +The physics output of this simulation is not fully tested and validated. diff --git a/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro b/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro new file mode 100644 index 0000000000000..1a26f68cd3410 --- /dev/null +++ b/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro @@ -0,0 +1,103 @@ +// configures a AliGenAmpt class from AliRoot +// usage: o2sim -g extgen --extGenFile aliroot_ampt.macro +// options: --extGenFunc aliroot_ampt(5020., 0., 20.) + +/// \author R+Preghenella - October 2018 + +R__LOAD_LIBRARY(libAMPT) +R__LOAD_LIBRARY(libTAmpt) + +class AliRoot_AMPT : public o2::eventgen::GeneratorTGenerator +{ + +public: + + AliRoot_AMPT() { + + // instance and configure AMPT + AliGenAmpt *genHi = new AliGenAmpt(-1); + genHi->SetEnergyCMS(5020.); + genHi->SetReferenceFrame("CMS"); + genHi->SetProjectile("A", 208, 82); + genHi->SetTarget("A", 208, 82); + genHi->SetIsoft(1); //1: defaul - 4: string melting + genHi->SetStringFrag(0.5, 0.9); //Lund string frgmentation parameters + genHi->SetPtHardMin(3); + genHi->SetImpactParameterRange(0., 20.); + + // Xmu = 3.2 fm^-1 and as = 0.33 ==> sigma_{partonic} = 1.5mb + // Ntmax = 150 + // v_2{2} = 0.102105 +/- 0.000266894 + // v_2{4} = 0.0829477 +/- 0.00106158 + + genHi->SetNtMax(150); // NTMAX: number of timesteps (D=150) + genHi->SetXmu(3.2264); // parton screening mass in fm^(-1) (D=3.2264d0) + + genHi->SetJetQuenching(0); // enable jet quenching + genHi->SetShadowing(1); // enable shadowing + // genHi->SetDecaysOff(1); // neutral pion and heavy particle decays switched off + genHi->SetSpectators(0); // track spectators + //Boost into LHC lab frame + genHi->SetBoostLHC(1); + // genHi->Init(); + genHi->SetRandomReactionPlane(kTRUE); + + + // save pointers to objects + mGenAMPT = genHi; + }; + + ~AliRoot_AMPT() { + delete mGenAMPT; + } + + bool Init() { + + // initialize AMPT + mGenAMPT->Init(); + + // configure TGenerator interface + setMomentumUnit(1.); // [GeV/c] + setEnergyUnit(1.); // [GeV/c] + setPositionUnit(0.1); // [cm] + setTimeUnit(3.3356410e-12); // [s] + setTGenerator(mGenAMPT->GetMC()); + + // initialise TGenerator interface + return o2::eventgen::GeneratorTGenerator::Init(); + } + + bool generateEvent() { + // set a random event plane + auto theAMPT = (TAmpt *)mGenAMPT->GetMC(); + TRandom *r = AliAmptRndm::GetAmptRandom(); + theAMPT->SetReactionPlaneAngle(TMath::TwoPi()*r->Rndm()); + + // generate the event + return o2::eventgen::GeneratorTGenerator::generateEvent(); + } + + void updateHeader(FairMCEventHeader* eventHeader) { + auto theAMPT = (TAmpt *)mGenAMPT->GetMC(); + auto impactB = theAMPT->GetHINT1(19); + auto evPlane = theAMPT->GetReactionPlaneAngle(); + eventHeader->SetB(impactB); + eventHeader->SetRotX(0.); + eventHeader->SetRotY(0.); + eventHeader->SetRotZ(evPlane); + std::cout << " Updated the event header: impactB = " << impactB << ", evPlane = " << evPlane << std::endl; + }; + + AliGenAmpt *mGenAMPT = nullptr; +}; + + +FairGenerator* +ampt(double energy = 5020., double bMin = 0., double bMax = 20., int isoft = 1) +{ + auto gen = new AliRoot_AMPT(); + gen->mGenAMPT->SetEnergyCMS(energy); + gen->mGenAMPT->SetImpactParameterRange(bMin, bMax); + gen->mGenAMPT->SetIsoft(isoft); + return gen; +} diff --git a/run/SimExamples/AliRoot_AMPT/run.sh b/run/SimExamples/AliRoot_AMPT/run.sh new file mode 100755 index 0000000000000..4665cac4af1b3 --- /dev/null +++ b/run/SimExamples/AliRoot_AMPT/run.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# +# Please, refer to the README.md for more information +# + +set -x + +NEV=5 +ENERGY=5020. +BMIN=15. +BMAX=20. +o2-sim -j 20 -n ${NEV} -g extgen -m PIPE ITS TPC -o sim \ + --extGenFile "aliroot_ampt.macro" --extGenFunc "ampt(${ENERGY}, ${BMIN}, ${BMAX})" diff --git a/run/SimExamples/README.md b/run/SimExamples/README.md index 8802f6e6411b7..ed77f8b00f2cf 100644 --- a/run/SimExamples/README.md +++ b/run/SimExamples/README.md @@ -9,6 +9,7 @@ * \subpage refrunSimExamplesTrigger_ImpactB_Pythia8 * \subpage refrunSimExamplesAdaptive_Pythia8 * \subpage refrunSimExamplesAliRoot_Hijing +* \subpage refrunSimExamplesAliRoot_AMPT * \subpage refrunSimExamplesHepMC_STARlight * \subpage refrunSimExamplesJet_Embedding_Pythia8 * \subpage refrunSimExamplesStepMonitoringSimple1 From 82836bbfb9322fca3e1b16f456038d35fc8c3e2c Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Sat, 18 Jul 2020 08:51:52 +0200 Subject: [PATCH 0119/1751] Small arrangements for more flexibility + selectFromAncestor util function (#4008) --- .../include/Generators/GeneratorPythia8.h | 16 +++++- Generators/src/GeneratorPythia8.cxx | 52 ++++++++++++++++--- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/Generators/include/Generators/GeneratorPythia8.h b/Generators/include/Generators/GeneratorPythia8.h index 9332d193bdd66..c743c931aefc9 100644 --- a/Generators/include/Generators/GeneratorPythia8.h +++ b/Generators/include/Generators/GeneratorPythia8.h @@ -42,6 +42,14 @@ class GeneratorPythia8 : public Generator void setConfig(std::string val) { mConfig = val; }; void setHooksFileName(std::string val) { mHooksFileName = val; }; void setHooksFuncName(std::string val) { mHooksFuncName = val; }; + void setUserHooks(Pythia8::UserHooks* hooks) + { +#if PYTHIA_VERSION_INTEGER < 8300 + mPythia.setUserHooksPtr(hooks); +#else + mPythia.setUserHooksPtr(std::shared_ptr<Pythia8::UserHooks>(hooks)); +#endif + } /** methods **/ bool readString(std::string val) { return mPythia.readString(val, true); }; @@ -55,11 +63,17 @@ class GeneratorPythia8 : public Generator /** methods to override **/ Bool_t generateEvent() override; - Bool_t importParticles() override; + Bool_t importParticles() override { return importParticles(mPythia.event); }; /** methods that can be overridded **/ void updateHeader(FairMCEventHeader* eventHeader) override; + /** internal methods **/ + Bool_t importParticles(Pythia8::Event& event); + + /** utilities **/ + void selectFromAncestor(int ancestor, Pythia8::Event& inputEvent, Pythia8::Event& outputEvent); + /** Pythia8 **/ Pythia8::Pythia mPythia; //! diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 578b09a0839f5..47b608ea9733b 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -68,11 +68,7 @@ Bool_t GeneratorPythia8::Init() LOG(FATAL) << "Failed to init \'Pythia8\': problem with user hooks configuration "; return false; } -#if PYTHIA_VERSION_INTEGER < 8300 - mPythia.setUserHooksPtr(hooks); -#else - mPythia.setUserHooksPtr(std::shared_ptr<Pythia8::UserHooks>(hooks)); -#endif + setUserHooks(hooks); } #if PYTHIA_VERSION_INTEGER < 8300 @@ -144,15 +140,15 @@ Bool_t /*****************************************************************/ Bool_t - GeneratorPythia8::importParticles() + GeneratorPythia8::importParticles(Pythia8::Event& event) { /** import particles **/ /* loop over particles */ // auto weight = mPythia.info.weight(); // TBD: use weights - auto nParticles = mPythia.event.size(); + auto nParticles = event.size(); for (Int_t iparticle = 0; iparticle < nParticles; iparticle++) { // first particle is system - auto particle = mPythia.event[iparticle]; + auto particle = event[iparticle]; auto pdg = particle.id(); auto st = particle.statusHepMC(); auto px = particle.px(); @@ -191,6 +187,46 @@ void GeneratorPythia8::updateHeader(FairMCEventHeader* eventHeader) eventHeader->SetB(hiinfo->b()); } +/*****************************************************************/ + +void GeneratorPythia8::selectFromAncestor(int ancestor, Pythia8::Event& inputEvent, Pythia8::Event& outputEvent) +{ + + /** select from ancestor + fills the output event with all particles related to + an ancestor of the input event **/ + + // recursive selection via lambda function + std::set<int> selected; + std::function<void(int)> select; + select = [&](int i) { + selected.insert(i); + auto dl = inputEvent[i].daughterList(); + for (auto j : dl) + select(j); + }; + select(ancestor); + + // map selected particle index to output index + std::map<int, int> indexMap; + int index = outputEvent.size(); + for (auto i : selected) + indexMap[i] = index++; + + // adjust mother/daughter indices and append to output event + for (auto i : selected) { + auto p = mPythia.event[i]; + auto m1 = indexMap[p.mother1()]; + auto m2 = indexMap[p.mother2()]; + auto d1 = indexMap[p.daughter1()]; + auto d2 = indexMap[p.daughter2()]; + p.mothers(m1, m2); + p.daughters(d1, d2); + + outputEvent.append(p); + } +} + /*****************************************************************/ /*****************************************************************/ From 20ca1284f6dc4b078522a12a67c63f86d6228224 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Sat, 18 Jul 2020 10:00:29 +0200 Subject: [PATCH 0120/1751] Accept missing Data[Input,Output]Director in json file (#4005) --- Framework/Core/src/DataInputDirector.cxx | 4 ++-- Framework/Core/src/DataOutputDirector.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 8c96e70171510..1a1f2efc64c89 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -207,8 +207,8 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) itemName = "InputDirector"; const Value& didirItem = (*jsonDoc)[itemName]; if (!didirItem.IsObject()) { - LOGP(ERROR, "Check the JSON document! Couldn't find an \"{}\" object!", itemName); - return false; + LOGP(INFO, "No \"{}\" object found in the JSON document!", itemName); + return true; } // now read various items diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index 576e897815683..61d1cfa07d5eb 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -265,7 +265,7 @@ std::tuple<std::string, std::string, int> DataOutputDirector::readJsonDocument(D itemName = "OutputDirector"; const Value& dodirItem = (*jsonDocument)[itemName]; if (!dodirItem.IsObject()) { - LOGP(ERROR, "Check the JSON document! Couldn't find an \"{}\" object!", itemName); + LOGP(INFO, "No \"{}\" object found in the JSON document!", itemName); return memptyanswer; } From f1c7d4741dc911827ec3ea8d2bdec9689c3e1558 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 17 Jul 2020 10:52:49 +0200 Subject: [PATCH 0121/1751] GPU: Fix TODO and implement proper atomic min/max for floats --- GPU/Common/GPUCommonMath.h | 28 +++++++++++++++++++ .../SliceTracker/GPUTPCSliceData.cxx | 25 +++++++++-------- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 73fbe5cb9dac0..866a1dd501f7c 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -473,6 +473,34 @@ GPUdi() void GPUCommonMath::AtomicMinInt(S* addr, T val) #endif // GPUCA_GPUCODE } +#if defined(__CUDACC__) || defined(__HIPCC__) +#define GPUCA_HAVE_ATOMIC_MINMAX_FLOAT +template <> +GPUdii() void GPUCommonMath::AtomicMaxInt(GPUglobalref() GPUgeneric() GPUAtomic(float) * addr, float val) +{ + if (val == -0.f) { + val = 0.f; + } + if (val >= 0) { + AtomicMaxInt((GPUAtomic(int)*)addr, __float_as_int(val)); + } else { + AtomicMinInt((GPUAtomic(unsigned int)*)addr, __float_as_uint(val)); + } +} +template <> +GPUdii() void GPUCommonMath::AtomicMinInt(GPUglobalref() GPUgeneric() GPUAtomic(float) * addr, float val) +{ + if (val == -0.f) { + val = 0.f; + } + if (val >= 0) { + AtomicMinInt((GPUAtomic(int)*)addr, __float_as_int(val)); + } else { + AtomicMaxInt((GPUAtomic(unsigned int)*)addr, __float_as_uint(val)); + } +} +#endif + #undef CHOICE #if !defined(__OPENCL__) || defined(__OPENCLCPP__) diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx index 3daa92c3d6217..e00ada516132e 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx @@ -225,9 +225,9 @@ GPUd() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int i GPUTPCRow& row = mRows[rowIndex]; if (iThread == 0) { - tmpMinMax[0] = -yMin; + tmpMinMax[0] = yMin; tmpMinMax[1] = yMax; - tmpMinMax[2] = -zMin; + tmpMinMax[2] = zMin; tmpMinMax[3] = zMax; row.mFirstHitInBinOffset = CAMath::nextMultipleOf<GPUCA_ROWALIGNMENT / sizeof(calink)>(GetGridSize(RowOffset, rowIndex) + rowIndex * GPUCA_ROWALIGNMENT / sizeof(int)); } @@ -279,30 +279,33 @@ GPUd() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int i row.mHitNumberOffset = CAMath::nextMultipleOf<GPUCA_ROWALIGNMENT / sizeof(calink)>(RowOffset + rowIndex * GPUCA_ROWALIGNMENT / sizeof(calink)); } - /* CAMath::AtomicMaxShared(&tmpMinMax[0], -yMin); // Atomic max not supported for float +#ifdef GPUCA_HAVE_ATOMIC_MINMAX_FLOAT + CAMath::AtomicMinShared(&tmpMinMax[0], yMin); CAMath::AtomicMaxShared(&tmpMinMax[1], yMax); - CAMath::AtomicMaxShared(&tmpMinMax[2], -zMin); - CAMath::AtomicMaxShared(&tmpMinMax[3], zMax); */ - for (int i = 0; i < nThreads; i++) { // Todo: Implement a better version of this stupid atomic max replacement + CAMath::AtomicMinShared(&tmpMinMax[2], zMin); + CAMath::AtomicMaxShared(&tmpMinMax[3], zMax); +#else + for (int i = 0; i < nThreads; i++) { GPUbarrier(); if (iThread == i) { - if (tmpMinMax[0] < -yMin) { - tmpMinMax[0] = -yMin; + if (tmpMinMax[0] > yMin) { + tmpMinMax[0] = yMin; } if (tmpMinMax[1] < yMax) { tmpMinMax[1] = yMax; } - if (tmpMinMax[2] < -zMin) { - tmpMinMax[2] = -zMin; + if (tmpMinMax[2] > zMin) { + tmpMinMax[2] = zMin; } if (tmpMinMax[3] < zMax) { tmpMinMax[3] = zMax; } } } +#endif GPUbarrier(); if (iThread == 0) { - CreateGrid(mem, &row, -tmpMinMax[0], tmpMinMax[1], -tmpMinMax[2], tmpMinMax[3]); + CreateGrid(mem, &row, tmpMinMax[0], tmpMinMax[1], tmpMinMax[2], tmpMinMax[3]); } GPUbarrier(); const GPUTPCGrid& grid = row.mGrid; From 7b10debe991f630f11f7919f50108553d8da49b3 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 19 Jul 2020 00:04:45 +0200 Subject: [PATCH 0122/1751] GPU: Fix TODO: Move synchronization to latest possible point --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index f33a6ef1bf5f7..b3d0d88ec7b8e 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1436,7 +1436,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() mRec->PushNonPersistentMemory(); for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { SetupGPUProcessor(&processors()->tpcTrackers[iSlice], true); // Now we allocate - mRec->ResetRegisteredMemoryPointers(&processors()->tpcTrackers[iSlice]); // TODO: The above call breaks the GPU ptrs to already allocated memory. This fixes them. Should actually be cleaner up at the source. + mRec->ResetRegisteredMemoryPointers(&processors()->tpcTrackers[iSlice]); // TODO: The above call breaks the GPU ptrs to already allocated memory. This fixes them. Should actually be cleaned up at the source. processors()->tpcTrackers[iSlice].SetupCommonMemory(); } @@ -1771,7 +1771,6 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() TransferMemoryResourcesToHost(RecoStep::TPCSliceTracking, &processors()->tpcTrackers[i], -1, true); } } - SynchronizeGPU(); // Todo: why needed? processing small data fails otherwise if (GetDeviceProcessingSettings().debugLevel >= 2) { GPUInfo("TPC Slice Tracker finished"); } @@ -1861,7 +1860,6 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) bool doGPUall = doGPU && GetDeviceProcessingSettings().fullMergerOnGPU; GPUReconstruction::krnlDeviceType deviceType = doGPUall ? GPUReconstruction::krnlDeviceType::Auto : GPUReconstruction::krnlDeviceType::CPU; unsigned int numBlocks = (!mRec->IsGPU() || doGPUall) ? BlockCount() : 1; - GPUTPCGMMerger& Merger = processors()->tpcMerger; GPUTPCGMMerger& MergerShadow = doGPU ? processorsShadow()->tpcMerger : Merger; GPUTPCGMMerger& MergerShadowAll = doGPUall ? processorsShadow()->tpcMerger : Merger; @@ -1870,6 +1868,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) } const auto& threadContext = GetThreadContext(); + SynchronizeGPU(); // Need to know the full number of slice tracks SetupGPUProcessor(&Merger, true); AllocateRegisteredMemory(Merger.MemoryResOutput(), mOutputTPCTracks); From 6492ee09660e281ead3ddcb90e254347f16a16f3 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 18 Jul 2020 03:38:06 +0200 Subject: [PATCH 0123/1751] MatchTPCITS: fix in ITS match registration --- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 6abd5627a7a89..8cf34c580d73c 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -911,7 +911,7 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2) } else { // max number of candidates reached, will overwrite the last one nextMatchRec.chi2 = chi2; suppressMatchRecordITS(nextMatchRec.partnerID, iTPC); // flag as disabled the overriden ITS match - registerMatchRecordITS(iITS, tTPC.matchID, chi2); // register TPC track entry in the ITS records + registerMatchRecordITS(iITS, iTPC, chi2); // register TPC track entry in the ITS records nextMatchRec.partnerID = iITS; // reuse the record of suppressed ITS match to store better one return true; } @@ -930,7 +930,7 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2) topID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC.size(); // register to his parent } // nextID==-1 will mean that the while loop run over all candidates->the new one is the worst (goes to the end) - registerMatchRecordITS(iITS, tTPC.matchID, chi2); // register TPC track in the ITS records + registerMatchRecordITS(iITS, iTPC, chi2); // register TPC track in the ITS records mMatchRecordsTPC.emplace_back(iITS, chi2, nextID); // create new record with empty reference on next match // make sure that after addition the number of candidates don't exceed allowed number count++; @@ -957,7 +957,7 @@ void MatchTPCITS::registerMatchRecordITS(int iITS, int iTPC, float chi2) ///< register TPC match in ITS tracks match records, ordering then in chi2 auto& tITS = mITSWork[iITS]; int idnew = mMatchRecordsITS.size(); - mMatchRecordsITS.emplace_back(iTPC, chi2); // associate iTPC with this record + auto& newRecord = mMatchRecordsITS.emplace_back(iTPC, chi2); // associate iTPC with this record if (tITS.matchID < 0) { tITS.matchID = idnew; return; @@ -965,8 +965,6 @@ void MatchTPCITS::registerMatchRecordITS(int iITS, int iTPC, float chi2) // there are other matches for this ITS track, insert the new record preserving chi2 order // navigate till last record or the one with worse chi2 int topID = MinusOne, nextRecord = tITS.matchID; - mMatchRecordsITS.emplace_back(iTPC, chi2); // associate iTPC with this record - auto& newRecord = mMatchRecordsITS.back(); do { auto& recITS = mMatchRecordsITS[nextRecord]; if (chi2 < recITS.chi2) { // insert before this one @@ -1065,12 +1063,12 @@ void MatchTPCITS::printCandidatesTPC() const for (int i = 0; i < ntpc; i++) { const auto& tTPC = mTPCWork[i]; int nm = getNMatchRecordsTPC(tTPC); - printf("*** trackTPC#%6d %6d : Ncand = %d\n", i, tTPC.sourceID, nm); + printf("*** trackTPC#%6d %6d : Ncand = %d Best = %d\n", i, tTPC.sourceID, nm, tTPC.matchID); int count = 0, recID = tTPC.matchID; while (recID > MinusOne) { const auto& rcTPC = mMatchRecordsTPC[recID]; const auto& tITS = mITSWork[rcTPC.partnerID]; - printf(" * cand %2d : ITS track %6d Chi2: %.2f\n", count, tITS.sourceID, rcTPC.chi2); + printf(" * cand %2d : ITS track %6d(src:%6d) Chi2: %.2f\n", count, rcTPC.partnerID, tITS.sourceID, rcTPC.chi2); count++; recID = rcTPC.nextRecID; } @@ -1086,12 +1084,12 @@ void MatchTPCITS::printCandidatesITS() const for (int i = 0; i < nits; i++) { const auto& tITS = mITSWork[i]; - printf("*** trackITS#%6d %6d : Ncand = %d\n", i, tITS.sourceID, getNMatchRecordsITS(tITS)); + printf("*** trackITS#%6d %6d : Ncand = %d Best = %d\n", i, tITS.sourceID, getNMatchRecordsITS(tITS), tITS.matchID); int count = 0, recID = tITS.matchID; while (recID > MinusOne) { const auto& rcITS = mMatchRecordsITS[recID]; const auto& tTPC = mTPCWork[rcITS.partnerID]; - printf(" * cand %2d : TPC track %6d Chi2: %.2f\n", count, tTPC.sourceID, rcITS.chi2); + printf(" * cand %2d : TPC track %6d(src:%6d) Chi2: %.2f\n", count, rcITS.partnerID, tTPC.sourceID, rcITS.chi2); count++; recID = rcITS.nextRecID; } @@ -1460,7 +1458,6 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) ///< refit in inward direction the pair of TPC and ITS tracks const float maxStep = 2.f; // max propagation step (TODO: tune) - const auto& tTPC = mTPCWork[iTPC]; if (isDisabledTPC(tTPC)) { return false; // no match From 853c3af9de9ddbe91ff9231d29f4a3f137ba7cc9 Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Thu, 16 Jul 2020 15:30:18 +0200 Subject: [PATCH 0124/1751] fix in tof decoding to recover first readout window --- Detectors/TOF/base/src/WindowFiller.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index 2f7cb1b5de648..418e6fd445bc2 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -157,6 +157,8 @@ void WindowFiller::flushOutputContainer(std::vector<Digit>& digits) printf("Future digits = %lu\n", mFutureDigits.size()); + checkIfReuseFutureDigitsRO(); + if (!mContinuous) fillOutputContainer(digits); else { From 32c386018d85e001e5441acefa8b70c6fc24e54e Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Fri, 17 Jul 2020 17:15:04 +0200 Subject: [PATCH 0125/1751] tof decoder: fix to have digits TF with the right number of readout windows (for proper comparison with sim) --- .../workflow/src/CompressedDecodingTask.cxx | 16 +++++++ macro/compareTOFDigits.C | 44 ++++++++++++++++--- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 50524829b61e5..a7fe6653ec172 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -52,10 +52,26 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) mHasToBePosted = false; mDecoder.FillWindows(); + int nwindowperTF = o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * 3; + // send output message std::vector<o2::tof::Digit>* alldigits = mDecoder.getDigitPerTimeFrame(); std::vector<o2::tof::ReadoutWindowData>* row = mDecoder.getReadoutWindowData(); + ReadoutWindowData* last = nullptr; + if (row->size()) + last = &(row->at(row->size() - 1)); + int lastval = last->first() + last->size(); + + while (row->size() < nwindowperTF) { + // complete timeframe with empty readout windows + row->emplace_back(lastval, 0); + } + while (row->size() > nwindowperTF) { + // remove extra readout windows after a check they are empty + row->pop_back(); + } + int n_tof_window = row->size(); int n_orbits = n_tof_window / 3; int digit_size = alldigits->size(); diff --git a/macro/compareTOFDigits.C b/macro/compareTOFDigits.C index f944a3d54a6a6..b9b450f2f86a8 100644 --- a/macro/compareTOFDigits.C +++ b/macro/compareTOFDigits.C @@ -47,10 +47,28 @@ bool compareTOFDigits(std::string inpName1 = "tofdigitsOr.root", std::string inp int nro1 = row1.size(); int nro2 = row2.size(); + for (int ii = 1; ii < t2->GetEntries(); ii++) { + t2->GetEvent(ii); + nro2 += row2.size(); + } + + int row2lastSize = row2.size(); + while (row1[nro1 - 1].size() == 0 && nro1 > 0) nro1--; - while (row2[nro2 - 1].size() == 0 && nro2 > 0) + while (row2[row2lastSize - 1].size() == 0 && row2lastSize > 0) { + row2lastSize--; nro2--; + } + + if (row2lastSize == 0) { + t2->GetEvent(t2->GetEntries() - 2); + row2lastSize = row2.size(); + while (row2[row2lastSize - 1].size() == 0 && row2lastSize > 0) { + row2lastSize--; + nro2--; + } + } if (nro1 != nro2) { printf("N readout windows different!!!! %d != %d \n", nro1, nro2); @@ -60,15 +78,29 @@ bool compareTOFDigits(std::string inpName1 = "tofdigitsOr.root", std::string inp printf("N readout windows = %d\n", nro1); - for (int i = 0; i < nro1; i++) { - if (row1[i].size() != row2[i].size()) { - printf("Readout window %d) different number of digits in this window!!!! %d != %d \n", i, int(row1[i].size()), int(row2[i].size())); + int offset = 0; + t2->GetEvent(0); + int nro2c = row2.size(); + int next = 1; + + for (int k = 0; k < nro1; k++) { + if (k >= nro2c) { + offset = nro2c; + t2->GetEvent(next); + nro2c += row2.size(); + next++; + } + int i = k; + int i2 = i - offset; + + if (row1[i].size() != row2[i2].size()) { + printf("Readout window %d) different number of digits in this window!!!! %d != %d \n", i, int(row1[i].size()), int(row2[i2].size())); status = false; return status; } auto digitsRO1 = row1.at(i).getBunchChannelData(digits1); - auto digitsRO2 = row2.at(i).getBunchChannelData(digits2); + auto digitsRO2 = row2.at(i2).getBunchChannelData(digits2); for (int j = 0; j < row1[i].size(); j++) { bool digitstatus = true; @@ -83,7 +115,7 @@ bool compareTOFDigits(std::string inpName1 = "tofdigitsOr.root", std::string inp } if (digitsRO1[j].getBC() != digitsRO2[j].getBC()) { - printf("RO %d - Digit %d/%d) Different BCs %d != %d \n", i, j, row1[i].size(), digitsRO1[j].getBC(), digitsRO2[j].getBC()); + printf("RO %d - Digit %d/%d) Different BCs %lu != %lu \n", i, j, row1[i].size(), digitsRO1[j].getBC(), digitsRO2[j].getBC()); digitstatus = false; } From ed580f749b47515878878eeb02afc96e19993153 Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Wed, 15 Jul 2020 15:14:08 +0300 Subject: [PATCH 0126/1751] fix small bugs --- .../FIT/FT0/simulation/src/Digitizer.cxx | 27 ++++++++++--------- .../FIT/FT0/simulation/src/Digits2Raw.cxx | 18 ++++++++----- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx index 106eff553174e..3c3a96513ff59 100644 --- a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx @@ -204,8 +204,9 @@ void Digitizer::storeBC(BCCache& bc, auto channel_begin = channel_end; channel_end = std::find_if(channel_begin, particles.end(), [ipmt](BCCache::particle const& p) { return p.hit_ch != ipmt; }); - if (channel_end - channel_begin < mParameters.mAmp_trsh) + if (channel_end - channel_begin < mParameters.mAmp_trsh) { continue; + } channel_times.resize(channel_end - channel_begin); std::transform(channel_begin, channel_end, channel_times.begin(), [](BCCache::particle const& p) { return p.hit_time; }); int chain = (std::rand() % 2) ? 1 : 0; @@ -223,15 +224,16 @@ void Digitizer::storeBC(BCCache& bc, float amp = is_time_in_signal_gate ? mParameters.mV_2_Nchannels * charge : 0; if (amp > 4095) amp = 4095; - LOG(INFO) << mEventID << " bc " << firstBCinDeque.bc << ", ipmt " << ipmt << ", smeared_time " << smeared_time << " nStored " << nStored; + LOG(DEBUG) << mEventID << " bc " << firstBCinDeque.bc << " orbit " << firstBCinDeque.orbit << ", ipmt " << ipmt << ", smeared_time " << smeared_time << " nStored " << nStored; digitsCh.emplace_back(ipmt, smeared_time, int(amp), chain); nStored++; // fill triggers Bool_t is_A_side = (ipmt <= 4 * mParameters.nCellsA); - if (smeared_time > mParameters.mTime_trg_gate || smeared_time < -mParameters.mTime_trg_gate) + if (!is_time_in_signal_gate) { continue; + } if (is_A_side) { n_hit_A++; @@ -256,20 +258,21 @@ void Digitizer::storeBC(BCCache& bc, uint16_t timeC = is_C ? mean_time_C / n_hit_C : 0; // average time C side Triggers triggers; - triggers.setTriggers(is_A, is_C, isVertex, is_Central, is_SemiCentral, int8_t(n_hit_A), int8_t(n_hit_C), - amplA, amplC, timeA, timeC); - - digitsBC.emplace_back(first, nStored, firstBCinDeque, triggers, mEventID - 1); - size_t const nBC = digitsBC.size(); - for (auto const& lbl : bc.labels) - labels.addElement(nBC - 1, lbl); - + if (nStored > 0) { + triggers.setTriggers(is_A, is_C, isVertex, is_Central, is_SemiCentral, int8_t(n_hit_A), int8_t(n_hit_C), + amplA, amplC, timeA, timeC); + + digitsBC.emplace_back(first, nStored, firstBCinDeque, triggers, mEventID - 1); + size_t const nBC = digitsBC.size(); + for (auto const& lbl : bc.labels) + labels.addElement(nBC - 1, lbl); + } // Debug output ------------------------------------------------------------- LOG(INFO) << "Event ID: " << mEventID << ", bc " << firstBCinDeque.bc << ", N hit " << bc.hits.size(); LOG(INFO) << "N hit A: " << int(triggers.nChanA) << " N hit C: " << int(triggers.nChanC) << " summ ampl A: " << int(triggers.amplA) << " summ ampl C: " << int(triggers.amplC) << " mean time A: " << triggers.timeA - << " mean time C: " << triggers.timeC; + << " mean time C: " << triggers.timeC << " nStored " << nStored; LOG(INFO) << "IS A " << triggers.getOrA() << " IsC " << triggers.getOrC() << " vertex " << triggers.getVertex() << " is Central " << triggers.getCen() << " is SemiCentral " << triggers.getSCen(); } diff --git a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx index fa7040e94c7cc..a14caf506b2ab 100644 --- a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx @@ -113,6 +113,7 @@ void Digits2Raw::readDigits(const std::string& outDir, const std::string& fileDi for (int ibc = 0; ibc < nbc; ibc++) { auto& bcd = digitsBC[ibc]; intRecord = bcd.getIntRecord(); + bcd.printStream(std::cout); auto channels = bcd.getBunchChannelData(digitsCh); if (!channels.empty()) convertDigits(bcd, channels, lut, intRecord); @@ -135,9 +136,9 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, if (nlink != oldlink) { if (oldlink >= 0) { uint nGBTWords = uint((nchannels + 1) / 2); - LOG(DEBUG) << " oldlink " << oldlink << " nGBTWords " << nGBTWords; - if ((nchannels % 2) == 1) + if ((nchannels % 2) == 1) { mRawEventData.mEventData[nchannels] = {}; + } mRawEventData.mEventHeader.nGBTWords = nGBTWords; auto data = mRawEventData.to_vector(false); mLinkID = uint32_t(oldlink); @@ -147,7 +148,6 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, oldlink = nlink; mRawEventData.mEventHeader = makeGBTHeader(nlink, intRecord); nchannels = 0; - // LOG(INFO) << " switch to new link " << nlink; } auto& newData = mRawEventData.mEventData[nchannels]; bool isAside = (pmchannels[ich].ChId < 96); @@ -165,7 +165,7 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, int chain = std::rand() % 2; newData.numberADC = chain ? 1 : 0; newData.channelID = lut.getMCP(pmchannels[ich].ChId); - // LOG(INFO) << "packed GBT " << nlink << " channelID " << (int)newData.channelID << " charge " << newData.charge << " time " << newData.time << " chain " << int(newData.numberADC) << " size " << sizeof(newData); + LOG(DEBUG) << "packed GBT " << nlink << " channelID " << (int)newData.channelID << " charge " << newData.charge << " time " << newData.time << " chain " << int(newData.numberADC) << " channel dig " << (int)pmchannels[ich].ChId; nchannels++; } // fill mEventData[nchannels] with 0s to flag that this is a dummy data @@ -173,7 +173,11 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, if ((nchannels % 2) == 1) mRawEventData.mEventData[nchannels] = {}; mRawEventData.mEventHeader.nGBTWords = nGBTWords; - LOG(DEBUG) << " last " << oldlink; + auto data = mRawEventData.to_vector(false); + mLinkID = uint32_t(oldlink); + mFeeID = uint64_t(oldlink); + mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, intRecord, data); + //TCM mRawEventData.mEventHeader = makeGBTHeader(LinkTCM, intRecord); //TCM mRawEventData.mEventHeader.nGBTWords = 1; @@ -213,10 +217,10 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, << " ver " << tcmdata.vertex << " A " << tcmdata.orA << " C " << tcmdata.orC << " size " << sizeof(tcmdata); } - auto data = mRawEventData.to_vector(1); + auto datatcm = mRawEventData.to_vector(1); mLinkID = uint32_t(LinkTCM); mFeeID = uint64_t(LinkTCM); - mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, intRecord, data); + mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, intRecord, datatcm); } //_____________________________________________________________________________________ From 0ab44710b7afee79652d784d0c3f3a7f5718b2ae Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Sat, 18 Jul 2020 12:38:41 +0300 Subject: [PATCH 0127/1751] remove unused digitization parameter --- .../simulation/include/FT0Simulation/DigitizationParameters.h | 3 +-- Detectors/FIT/FT0/simulation/src/Digitizer.cxx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Detectors/FIT/FT0/simulation/include/FT0Simulation/DigitizationParameters.h b/Detectors/FIT/FT0/simulation/include/FT0Simulation/DigitizationParameters.h index 48debbc36b2f3..1552631a2bb80 100644 --- a/Detectors/FIT/FT0/simulation/include/FT0Simulation/DigitizationParameters.h +++ b/Detectors/FIT/FT0/simulation/include/FT0Simulation/DigitizationParameters.h @@ -29,12 +29,11 @@ struct DigitizationParameters { float mAmpRecordLow = -4; // integrate charge from float mAmpRecordUp = 15; // to [ns] - int mTime_trg_gate = 189; //2500/13; (+-2ns) #channels + int mTime_trg_gate = 192; // #channels // int mTime_trg_gate = 2000; //2000/13; (+-2ns) #channels no limits float mTimeDiffAC = (Geometry::ZdetA - Geometry::ZdetC) * TMath::C(); float C_side_cable_cmps = 2.86; //ns float A_side_cable_cmps = 11.110; //ns - int mSignalWidth = 189; //+-2500.ps/13.2ps #channels int mtrg_central_trh = 600.; // channels int mtrg_semicentral_trh = 300.; // channels diff --git a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx index 3c3a96513ff59..164367179c3b7 100644 --- a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx @@ -348,7 +348,7 @@ void Digitizer::printParameters() const { LOG(INFO) << " Run Digitzation with parametrs: \n" << " CFD amplitude threshold \n " << mParameters.mCFD_trsh << " CFD signal gate in ps \n" - << mParameters.mSignalWidth << "shift to have signal around zero after CFD trancformation \n" + << mParameters.mTime_trg_gate << "shift to have signal around zero after CFD trancformation \n" << mParameters.mCfdShift << "CFD distance between 0.3 of max amplitude to max \n" << mParameters.mCFDShiftPos << "MIP -> mV " << mParameters.mMip_in_V << " Pe in MIP \n" << mParameters.mPe_in_mip << "noise level " << mParameters.mNoiseVar << " noise frequency \n" From 1dc26c5499add2e2fcadc8e71cd44ee1568963bc Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Sun, 19 Jul 2020 23:22:42 +0200 Subject: [PATCH 0128/1751] DPL Analysis: Allow for nested filtering and partitioning on filtered (#3998) * Added unions and intersections of filtered * Nicer iterator for partitions --- Analysis/Tutorials/src/partitions.cxx | 9 +- Framework/Core/include/Framework/ASoA.h | 217 +++++++++++++++--- .../Core/include/Framework/AnalysisTask.h | 35 ++- Framework/Core/test/test_ASoA.cxx | 126 ++++++++++ Framework/Core/test/test_AnalysisTask.cxx | 65 ++++++ 5 files changed, 411 insertions(+), 41 deletions(-) diff --git a/Analysis/Tutorials/src/partitions.cxx b/Analysis/Tutorials/src/partitions.cxx index 50806e953095f..05455f3d46f26 100644 --- a/Analysis/Tutorials/src/partitions.cxx +++ b/Analysis/Tutorials/src/partitions.cxx @@ -32,15 +32,12 @@ struct ATask { float philow = 1.0f; float phiup = 2.0f; - Partition<soa::Filtered<aod::Tracks>> leftPhiP = aod::track::phiraw < philow; - Partition<soa::Filtered<aod::Tracks>> midPhiP = aod::track::phiraw >= philow && aod::track::phiraw < phiup; - Partition<soa::Filtered<aod::Tracks>> rightPhiP = aod::track::phiraw >= phiup; + Partition<soa::Filtered<aod::Tracks>> leftPhi = aod::track::phiraw < philow; + Partition<soa::Filtered<aod::Tracks>> midPhi = aod::track::phiraw >= philow && aod::track::phiraw < phiup; + Partition<soa::Filtered<aod::Tracks>> rightPhi = aod::track::phiraw >= phiup; void process(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& tracks) { - auto& leftPhi = leftPhiP.getPartition(); - auto& midPhi = midPhiP.getPartition(); - auto& rightPhi = rightPhiP.getPartition(); LOGF(INFO, "Collision: %d [N = %d] [left phis = %d] [mid phis = %d] [right phis = %d]", collision.globalIndex(), tracks.size(), leftPhi.size(), midPhi.size(), rightPhi.size()); diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index aaeda27c68492..cdf271a5f42b4 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1324,7 +1324,7 @@ template <typename T> using is_soa_concat_t = typename framework::is_specialization<T, soa::Concat>; template <typename T> -class Filtered : public T +class FilteredPolicy : public T { public: using originals = originals_pack_t<T>; @@ -1336,45 +1336,30 @@ class Filtered : public T { return typename table_t::template RowViewFiltered<P, Os...>{}; } - using iterator = decltype(make_it<Filtered<T>>(originals{})); + using iterator = decltype(make_it<FilteredPolicy<T>>(originals{})); using const_iterator = iterator; - Filtered(std::vector<std::shared_ptr<arrow::Table>>&& tables, SelectionVector&& selection, uint64_t offset = 0) + FilteredPolicy(std::vector<std::shared_ptr<arrow::Table>>&& tables, SelectionVector&& selection, uint64_t offset = 0) : T{std::move(tables), offset}, - mSelectedRows{std::forward<SelectionVector>(selection)}, - mFilteredEnd{mSelectedRows.size()} + mSelectedRows{std::forward<SelectionVector>(selection)} { - if (tableSize() == 0) { - mFilteredBegin = mFilteredEnd; - } else { - mFilteredBegin = table_t::filtered_begin(mSelectedRows); - } + resetRanges(); } - Filtered(std::vector<std::shared_ptr<arrow::Table>>&& tables, framework::expressions::Selection selection, uint64_t offset = 0) + FilteredPolicy(std::vector<std::shared_ptr<arrow::Table>>&& tables, framework::expressions::Selection selection, uint64_t offset = 0) : T{std::move(tables), offset}, - mSelectedRows{copySelection(selection)}, - mFilteredEnd{mSelectedRows.size()} + mSelectedRows{copySelection(selection)} { - if (tableSize() == 0) { - mFilteredBegin = mFilteredEnd; - } else { - mFilteredBegin = table_t::filtered_begin(mSelectedRows); - } + resetRanges(); } - Filtered(std::vector<std::shared_ptr<arrow::Table>>&& tables, gandiva::NodePtr const& tree, uint64_t offset = 0) + FilteredPolicy(std::vector<std::shared_ptr<arrow::Table>>&& tables, gandiva::NodePtr const& tree, uint64_t offset = 0) : T{std::move(tables), offset}, mSelectedRows{copySelection(framework::expressions::createSelection(this->asArrowTable(), framework::expressions::createFilter(this->asArrowTable()->schema(), - framework::expressions::makeCondition(tree))))}, - mFilteredEnd{mSelectedRows.size()} + framework::expressions::makeCondition(tree))))} { - if (tableSize() == 0) { - mFilteredBegin = mFilteredEnd; - } else { - mFilteredBegin = table_t::filtered_begin(mSelectedRows); - } + resetRanges(); } iterator begin() @@ -1384,7 +1369,7 @@ class Filtered : public T RowViewSentinel end() { - return RowViewSentinel{mFilteredEnd}; + return RowViewSentinel{*mFilteredEnd}; } const_iterator begin() const @@ -1394,7 +1379,7 @@ class Filtered : public T RowViewSentinel end() const { - return RowViewSentinel{mFilteredEnd}; + return RowViewSentinel{*mFilteredEnd}; } iterator iteratorAt(uint64_t i) @@ -1435,10 +1420,184 @@ class Filtered : public T mFilteredBegin.bindExternalIndices(current...); } + protected: + void sumWithSelection(SelectionVector const& selection) + { + SelectionVector rowsUnion; + std::set_union(mSelectedRows.begin(), mSelectedRows.end(), selection.begin(), selection.end(), std::back_inserter(rowsUnion)); + mSelectedRows = rowsUnion; + resetRanges(); + } + + void intersectWithSelection(SelectionVector const& selection) + { + SelectionVector intersection; + std::set_intersection(mSelectedRows.begin(), mSelectedRows.end(), selection.begin(), selection.end(), std::back_inserter(intersection)); + mSelectedRows = intersection; + resetRanges(); + } + private: + void resetRanges() + { + mFilteredEnd.reset(new RowViewSentinel{mSelectedRows.size()}); + if (tableSize() == 0) { + mFilteredBegin = *mFilteredEnd; + } else { + mFilteredBegin = table_t::filtered_begin(mSelectedRows); + } + } + SelectionVector mSelectedRows; iterator mFilteredBegin; - RowViewSentinel mFilteredEnd; + std::shared_ptr<RowViewSentinel> mFilteredEnd; +}; + +template <typename T> +class Filtered : public FilteredPolicy<T> +{ + public: + Filtered(std::vector<std::shared_ptr<arrow::Table>>&& tables, SelectionVector&& selection, uint64_t offset = 0) + : FilteredPolicy<T>(std::move(tables), std::forward<SelectionVector>(selection), offset) {} + + Filtered(std::vector<std::shared_ptr<arrow::Table>>&& tables, framework::expressions::Selection selection, uint64_t offset = 0) + : FilteredPolicy<T>(std::move(tables), selection, offset) {} + + Filtered(std::vector<std::shared_ptr<arrow::Table>>&& tables, gandiva::NodePtr const& tree, uint64_t offset = 0) + : FilteredPolicy<T>(std::move(tables), tree, offset) {} + + Filtered<T> operator+(SelectionVector const& selection) + { + Filtered<T> copy(*this); + copy.sumWithSelection(selection); + return copy; + } + + Filtered<T> operator+(Filtered<T> const& other) + { + return operator+(other.getSelectedRows()); + } + + Filtered<T> operator+=(SelectionVector const& selection) + { + this->sumWithSelection(selection); + return *this; + } + + Filtered<T> operator+=(Filtered<T> const& other) + { + return operator+=(other.getSelectedRows()); + } + + Filtered<T> operator*(SelectionVector const& selection) + { + Filtered<T> copy(*this); + copy.intersectWithSelection(selection); + return copy; + } + + Filtered<T> operator*(Filtered<T> const& other) + { + return operator*(other.getSelectedRows()); + } + + Filtered<T> operator*=(SelectionVector const& selection) + { + this->intersectWithSelection(selection); + return *this; + } + + Filtered<T> operator*=(Filtered<T> const& other) + { + return operator*=(other.getSelectedRows()); + } +}; + +template <typename T> +class Filtered<Filtered<T>> : public FilteredPolicy<typename T::table_t> +{ + public: + using table_t = typename FilteredPolicy<typename T::table_t>::table_t; + + Filtered(std::vector<Filtered<T>>&& tables, SelectionVector&& selection, uint64_t offset = 0) + : FilteredPolicy<typename T::table_t>(std::move(extractTablesFromFiltered(std::move(tables))), std::forward<SelectionVector>(selection), offset) + { + for (auto& table : tables) { + *this *= table; + } + } + + Filtered(std::vector<Filtered<T>>&& tables, framework::expressions::Selection selection, uint64_t offset = 0) + : FilteredPolicy<typename T::table_t>(std::move(extractTablesFromFiltered(std::move(tables))), selection, offset) + { + for (auto& table : tables) { + *this *= table; + } + } + + Filtered(std::vector<Filtered<T>>&& tables, gandiva::NodePtr const& tree, uint64_t offset = 0) + : FilteredPolicy<typename T::table_t>(std::move(extractTablesFromFiltered(std::move(tables))), tree, offset) + { + for (auto& table : tables) { + *this *= table; + } + } + + Filtered<Filtered<T>> operator+(SelectionVector const& selection) + { + Filtered<Filtered<T>> copy(*this); + copy.sumWithSelection(selection); + return copy; + } + + Filtered<Filtered<T>> operator+(Filtered<T> const& other) + { + return operator+(other.getSelectedRows()); + } + + Filtered<Filtered<T>> operator+=(SelectionVector const& selection) + { + this->sumWithSelection(selection); + return *this; + } + + Filtered<Filtered<T>> operator+=(Filtered<T> const& other) + { + return operator+=(other.getSelectedRows()); + } + + Filtered<Filtered<T>> operator*(SelectionVector const& selection) + { + Filtered<Filtered<T>> copy(*this); + copy.intersectionWithSelection(selection); + return copy; + } + + Filtered<Filtered<T>> operator*(Filtered<T> const& other) + { + return operator*(other.getSelectedRows()); + } + + Filtered<Filtered<T>> operator*=(SelectionVector const& selection) + { + this->intersectWithSelection(selection); + return *this; + } + + Filtered<Filtered<T>> operator*=(Filtered<T> const& other) + { + return operator*=(other.getSelectedRows()); + } + + private: + std::vector<std::shared_ptr<arrow::Table>> extractTablesFromFiltered(std::vector<Filtered<T>>&& tables) + { + std::vector<std::shared_ptr<arrow::Table>> outTables; + for (auto& table : tables) { + outTables.push_back(table.asArrowTable()); + } + return outTables; + } }; template <typename T> diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 1e59d43e5ea51..8b0d360c8db2e 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -327,7 +327,7 @@ struct Partition { Partition(expressions::Node&& node) { auto filter = expressions::Filter(std::move(node)); - auto schema = o2::soa::createSchemaFromColumns(typename T::table_t::persistent_columns_t{}); + auto schema = o2::soa::createSchemaFromColumns(typename T::persistent_columns_t{}); expressions::Operations ops = createOperations(filter); if (isSchemaCompatible(schema, ops)) { mTree = createExpressionTree(ops, schema); @@ -338,7 +338,11 @@ struct Partition { void setTable(const T& table) { - mFiltered.reset(new o2::soa::Filtered<typename T::table_t>{{table.asArrowTable()}, mTree}); + if constexpr (soa::is_soa_filtered_t<std::decay_t<T>>::value) { + mFiltered.reset(new o2::soa::Filtered<T>{{table}, mTree}); + } else { + mFiltered.reset(new o2::soa::Filtered<T>{{table.asArrowTable()}, mTree}); + } } template <typename... Ts> @@ -357,13 +361,32 @@ struct Partition { } } - o2::soa::Filtered<typename T::table_t>& getPartition() + gandiva::NodePtr mTree; + std::unique_ptr<o2::soa::Filtered<T>> mFiltered; + + using filtered_iterator = typename o2::soa::Filtered<T>::iterator; + using filtered_const_iterator = typename o2::soa::Filtered<T>::const_iterator; + inline filtered_iterator begin() { - return *mFiltered; + return mFiltered->begin(); + } + inline o2::soa::RowViewSentinel end() + { + return mFiltered->end(); + } + inline filtered_const_iterator begin() const + { + return mFiltered->begin(); + } + inline o2::soa::RowViewSentinel end() const + { + return mFiltered->end(); } - gandiva::NodePtr mTree; - std::unique_ptr<o2::soa::Filtered<typename T::table_t>> mFiltered; + int64_t size() const + { + return mFiltered->size(); + } }; template <typename ANY> diff --git a/Framework/Core/test/test_ASoA.cxx b/Framework/Core/test/test_ASoA.cxx index cc57e5f47cf52..b276f86c95552 100644 --- a/Framework/Core/test/test_ASoA.cxx +++ b/Framework/Core/test/test_ASoA.cxx @@ -496,3 +496,129 @@ BOOST_AUTO_TEST_CASE(TestSchemaCreation) BOOST_CHECK_EQUAL(schema->field(0)->name(), "x"); BOOST_CHECK_EQUAL(schema->field(1)->name(), "y"); } + +BOOST_AUTO_TEST_CASE(TestFilteredOperators) +{ + TableBuilder builderA; + auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"}); + rowWriterA(0, 0, 8); + rowWriterA(0, 1, 9); + rowWriterA(0, 2, 10); + rowWriterA(0, 3, 11); + rowWriterA(0, 4, 12); + rowWriterA(0, 5, 13); + rowWriterA(0, 6, 14); + rowWriterA(0, 7, 15); + auto tableA = builderA.finalize(); + BOOST_REQUIRE_EQUAL(tableA->num_rows(), 8); + + using TestA = o2::soa::Table<o2::soa::Index<>, test::X, test::Y>; + using FilteredTest = Filtered<TestA>; + using NestedFilteredTest = Filtered<Filtered<TestA>>; + using namespace o2::framework; + + expressions::Filter f1 = test::x < 4; + expressions::Filter f2 = test::y > 13; + + TestA testA{tableA}; + FilteredTest filtered1{{testA.asArrowTable()}, expressions::createSelection(testA.asArrowTable(), f1)}; + BOOST_CHECK_EQUAL(4, filtered1.size()); + BOOST_CHECK(filtered1.begin() != filtered1.end()); + + FilteredTest filtered2{{testA.asArrowTable()}, expressions::createSelection(testA.asArrowTable(), f2)}; + BOOST_CHECK_EQUAL(2, filtered2.size()); + BOOST_CHECK(filtered2.begin() != filtered2.end()); + + FilteredTest filteredUnion = filtered1 + filtered2; + BOOST_CHECK_EQUAL(6, filteredUnion.size()); + + std::vector<std::tuple<int32_t, int32_t>> expectedUnion{ + {0, 8}, {1, 9}, {2, 10}, {3, 11}, {6, 14}, {7, 15}}; + auto i = 0; + for (auto& f : filteredUnion) { + BOOST_CHECK_EQUAL(std::get<0>(expectedUnion[i]), f.x()); + BOOST_CHECK_EQUAL(std::get<1>(expectedUnion[i]), f.y()); + BOOST_CHECK_EQUAL(std::get<0>(expectedUnion[i]), f.index()); + i++; + } + BOOST_CHECK_EQUAL(i, 6); + + FilteredTest filteredIntersection = filtered1 * filtered2; + BOOST_CHECK_EQUAL(0, filteredIntersection.size()); + + i = 0; + for (auto& f : filteredIntersection) { + i++; + } + BOOST_CHECK_EQUAL(i, 0); + + expressions::Filter f3 = test::x < 3; + FilteredTest filtered3{{testA.asArrowTable()}, expressions::createSelection(testA.asArrowTable(), f3)}; + BOOST_CHECK_EQUAL(3, filtered3.size()); + BOOST_CHECK(filtered3.begin() != filtered3.end()); + + FilteredTest unionIntersection = (filtered1 + filtered2) * filtered3; + BOOST_CHECK_EQUAL(3, unionIntersection.size()); + + i = 0; + for (auto& f : unionIntersection) { + BOOST_CHECK_EQUAL(i, f.x()); + BOOST_CHECK_EQUAL(i + 8, f.y()); + BOOST_CHECK_EQUAL(i, f.index()); + i++; + } + BOOST_CHECK_EQUAL(i, 3); +} + +BOOST_AUTO_TEST_CASE(TestNestedFiltering) +{ + TableBuilder builderA; + auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"}); + rowWriterA(0, 0, 8); + rowWriterA(0, 1, 9); + rowWriterA(0, 2, 10); + rowWriterA(0, 3, 11); + rowWriterA(0, 4, 12); + rowWriterA(0, 5, 13); + rowWriterA(0, 6, 14); + rowWriterA(0, 7, 15); + auto tableA = builderA.finalize(); + BOOST_REQUIRE_EQUAL(tableA->num_rows(), 8); + + using TestA = o2::soa::Table<o2::soa::Index<>, test::X, test::Y>; + using FilteredTest = Filtered<TestA>; + using NestedFilteredTest = Filtered<Filtered<TestA>>; + using TripleNestedFilteredTest = Filtered<Filtered<Filtered<TestA>>>; + using namespace o2::framework; + + expressions::Filter f1 = test::x < 4; + expressions::Filter f2 = test::y > 9; + expressions::Filter f3 = test::x < 3; + + TestA testA{tableA}; + FilteredTest filtered{{testA.asArrowTable()}, expressions::createSelection(testA.asArrowTable(), f1)}; + BOOST_CHECK_EQUAL(4, filtered.size()); + BOOST_CHECK(filtered.begin() != filtered.end()); + + NestedFilteredTest nestedFiltered{{filtered}, expressions::createSelection(filtered.asArrowTable(), f2)}; + BOOST_CHECK_EQUAL(2, nestedFiltered.size()); + auto i = 0; + for (auto& f : nestedFiltered) { + BOOST_CHECK_EQUAL(i + 2, f.x()); + BOOST_CHECK_EQUAL(i + 10, f.y()); + BOOST_CHECK_EQUAL(i + 2, f.index()); + i++; + } + BOOST_CHECK_EQUAL(i, 2); + + TripleNestedFilteredTest tripleFiltered{{nestedFiltered}, expressions::createSelection(nestedFiltered.asArrowTable(), f3)}; + BOOST_CHECK_EQUAL(1, tripleFiltered.size()); + i = 0; + for (auto& f : tripleFiltered) { + BOOST_CHECK_EQUAL(i + 2, f.x()); + BOOST_CHECK_EQUAL(i + 10, f.y()); + BOOST_CHECK_EQUAL(i + 2, f.index()); + i++; + } + BOOST_CHECK_EQUAL(i, 1); +} diff --git a/Framework/Core/test/test_AnalysisTask.cxx b/Framework/Core/test/test_AnalysisTask.cxx index 0de0a33381cab..a9ac25d2ced52 100644 --- a/Framework/Core/test/test_AnalysisTask.cxx +++ b/Framework/Core/test/test_AnalysisTask.cxx @@ -189,3 +189,68 @@ BOOST_AUTO_TEST_CASE(AdaptorCompilation) auto task10 = adaptAnalysisTask<JTask>("test10"); } + +BOOST_AUTO_TEST_CASE(TestPartitionIteration) +{ + TableBuilder builderA; + auto rowWriterA = builderA.persist<float, float>({"fX", "fY"}); + rowWriterA(0, 0.0f, 8.0f); + rowWriterA(0, 1.0f, 9.0f); + rowWriterA(0, 2.0f, 10.0f); + rowWriterA(0, 3.0f, 11.0f); + rowWriterA(0, 4.0f, 12.0f); + rowWriterA(0, 5.0f, 13.0f); + rowWriterA(0, 6.0f, 14.0f); + rowWriterA(0, 7.0f, 15.0f); + auto tableA = builderA.finalize(); + BOOST_REQUIRE_EQUAL(tableA->num_rows(), 8); + + using TestA = o2::soa::Table<o2::soa::Index<>, aod::test::X, aod::test::Y>; + using FilteredTest = o2::soa::Filtered<TestA>; + using PartitionTest = Partition<TestA>; + using PartitionFilteredTest = Partition<o2::soa::Filtered<TestA>>; + using PartitionNestedFilteredTest = Partition<o2::soa::Filtered<o2::soa::Filtered<TestA>>>; + using namespace o2::framework; + + TestA testA{tableA}; + + PartitionTest p1 = aod::test::x < 4.0f; + p1.setTable(testA); + BOOST_CHECK_EQUAL(4, p1.size()); + BOOST_CHECK(p1.begin() != p1.end()); + auto i = 0; + for (auto& p : p1) { + BOOST_CHECK_EQUAL(i, p.x()); + BOOST_CHECK_EQUAL(i + 8, p.y()); + BOOST_CHECK_EQUAL(i, p.index()); + i++; + } + BOOST_CHECK_EQUAL(i, 4); + + expressions::Filter f1 = aod::test::x < 4.0f; + FilteredTest filtered{{testA.asArrowTable()}, expressions::createSelection(testA.asArrowTable(), f1)}; + PartitionFilteredTest p2 = aod::test::y > 9.0f; + p2.setTable(filtered); + + BOOST_CHECK_EQUAL(2, p2.size()); + i = 0; + for (auto& p : p2) { + BOOST_CHECK_EQUAL(i + 2, p.x()); + BOOST_CHECK_EQUAL(i + 10, p.y()); + BOOST_CHECK_EQUAL(i + 2, p.index()); + i++; + } + BOOST_CHECK_EQUAL(i, 2); + + PartitionNestedFilteredTest p3 = aod::test::x < 3.0f; + p3.setTable(*(p2.mFiltered)); + BOOST_CHECK_EQUAL(1, p3.size()); + i = 0; + for (auto& p : p3) { + BOOST_CHECK_EQUAL(i + 2, p.x()); + BOOST_CHECK_EQUAL(i + 10, p.y()); + BOOST_CHECK_EQUAL(i + 2, p.index()); + i++; + } + BOOST_CHECK_EQUAL(i, 1); +} From a4b0899087402a0c879dd8bf47b86aeb757ea242 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Sun, 19 Jul 2020 23:26:20 +0200 Subject: [PATCH 0129/1751] DPL Analysis: Correctly handle branches with type l (ULong64_t) (#4010) --- Framework/Core/include/Framework/TableTreeHelpers.h | 2 +- Framework/Core/src/TableTreeHelpers.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/TableTreeHelpers.h b/Framework/Core/include/Framework/TableTreeHelpers.h index f229b3e289fe2..2be51630f6a5a 100644 --- a/Framework/Core/include/Framework/TableTreeHelpers.h +++ b/Framework/Core/include/Framework/TableTreeHelpers.h @@ -138,7 +138,7 @@ class ColumnIterator TTreeReaderValue<uint8_t>* mReaderValue_ub = nullptr; TTreeReaderValue<uint16_t>* mReaderValue_us = nullptr; TTreeReaderValue<uint32_t>* mReaderValue_ui = nullptr; - TTreeReaderValue<uint64_t>* mReaderValue_ul = nullptr; + TTreeReaderValue<ULong64_t>* mReaderValue_ul = nullptr; TTreeReaderValue<int8_t>* mReaderValue_b = nullptr; TTreeReaderValue<int16_t>* mReaderValue_s = nullptr; TTreeReaderValue<int32_t>* mReaderValue_i = nullptr; diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 4d569ba422323..c79c50d1e57de 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -429,7 +429,7 @@ ColumnIterator::ColumnIterator(TTreeReader* reader, const char* colname) MAKE_FIELD_AND_BUILDER(uint32_t, 1, mTableBuilder_ui); break; case EDataType::kULong64_t: - mReaderValue_ul = new TTreeReaderValue<uint64_t>(*reader, mColumnName); + mReaderValue_ul = new TTreeReaderValue<ULong64_t>(*reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint64_t, 1, mTableBuilder_ul); break; case EDataType::kChar_t: From cd1043b1463d23a2c27893949b377222a1aef562 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 19 Jul 2020 23:40:44 +0200 Subject: [PATCH 0130/1751] DPL: proxy all parts when sending them to a non DPL device (#3937) --- .../Core/src/ExternalFairMQDeviceProxy.cxx | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx index cd76cdd6c391d..78e79844db913 100644 --- a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx +++ b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx @@ -420,18 +420,8 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, return adaptStateless([](RawDeviceService& rds, InputRecord& inputs) { std::unordered_map<std::string, FairMQParts> outputs; auto& device = *rds.device(); - for (auto& input : inputs) { - // TODO: we need to make a copy of the messages, maybe we can implement functionality in - // the RawDeviceService to forward messages, but this also needs to take into account that - // other consumers might exist - size_t headerMsgSize = o2::header::Stack::headerStackSize(reinterpret_cast<o2::byte const*>(input.header)); - auto* dh = o2::header::get<DataHeader*>(input.header); - if (!dh) { - std::stringstream errorMessage; - errorMessage << "no data header in " << *input.spec; - throw std::runtime_error(errorMessage.str()); - } - size_t payloadMsgSize = dh->payloadSize; + for (size_t ii = 0; ii != inputs.size(); ++ii) { + auto first = inputs.getByPos(ii, 0); // we could probably do something like this but we do not know when the message is going to be sent // and if DPL is still owning a valid copy. //auto headerMessage = device.NewMessageFor(input.spec->binding, input.header, headerMsgSize, [](void*, void*) {}); @@ -439,12 +429,27 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, // Note: DPL is only setting up one instance of a channel while FairMQ allows to have an // array of channels, the index is 0 in the call constexpr auto index = 0; - auto headerMessage = device.NewMessageFor(input.spec->binding, index, headerMsgSize); - memcpy(headerMessage->GetData(), input.header, headerMsgSize); - auto payloadMessage = device.NewMessageFor(input.spec->binding, index, payloadMsgSize); - memcpy(payloadMessage->GetData(), input.payload, payloadMsgSize); - outputs[input.spec->binding].AddPart(std::move(headerMessage)); - outputs[input.spec->binding].AddPart(std::move(payloadMessage)); + for (size_t pi = 0; pi < inputs.getNofParts(ii); ++pi) { + auto part = inputs.getByPos(ii, pi); + // TODO: we need to make a copy of the messages, maybe we can implement functionality in + // the RawDeviceService to forward messages, but this also needs to take into account that + // other consumers might exist + size_t headerMsgSize = o2::header::Stack::headerStackSize(reinterpret_cast<o2::byte const*>(first.header)); + auto* dh = o2::header::get<DataHeader*>(first.header); + if (!dh) { + std::stringstream errorMessage; + errorMessage << "no data header in " << *first.spec; + throw std::runtime_error(errorMessage.str()); + } + size_t payloadMsgSize = dh->payloadSize; + + auto headerMessage = device.NewMessageFor(first.spec->binding, index, headerMsgSize); + memcpy(headerMessage->GetData(), part.header, headerMsgSize); + auto payloadMessage = device.NewMessageFor(first.spec->binding, index, payloadMsgSize); + memcpy(payloadMessage->GetData(), part.payload, payloadMsgSize); + outputs[first.spec->binding].AddPart(std::move(headerMessage)); + outputs[first.spec->binding].AddPart(std::move(payloadMessage)); + } } for (auto& [channelName, channelParts] : outputs) { if (channelParts.Size() == 0) { From 5bbc6f7679a8f8e4b3ef6f247768e358b222ff08 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 19 Jul 2020 23:42:24 +0200 Subject: [PATCH 0131/1751] DPL: split data receiving and actual processing (#3990) --- .../include/Framework/DataProcessingDevice.h | 2 ++ Framework/Core/src/DataProcessingDevice.cxx | 28 +++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index 1dffddf8fe7c8..05db79ce32af2 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -48,6 +48,7 @@ struct DataProcessorContext { // These are specific of a given context and therefore // not shared by threads. bool* wasActive = nullptr; + bool allDone = false; // These are pointers to the one owned by the DataProcessingDevice // but they are fully reentrant / thread safe and therefore can @@ -105,6 +106,7 @@ class DataProcessingDevice : public FairMQDevice // Processing functions are now renetrant static void doRun(DataProcessorContext& context); + static void doPrepare(DataProcessorContext& context); static void handleData(DataProcessorContext& context, FairMQParts&, InputChannelInfo&); static bool tryDispatchComputation(DataProcessorContext& context, std::vector<DataRelayer::RecordAction>& completed); std::vector<DataProcessorContext> mDataProcessorContexes; diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index ae578e887eb0e..3c3008469b6cd 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -128,6 +128,7 @@ void run_callback(uv_work_t* handle) ZoneScopedN("run_callback"); std::vector<DataProcessorContext>* contexes = (std::vector<DataProcessorContext>*)handle->data; DataProcessorContext& context = contexes->at(0); + DataProcessingDevice::doPrepare(context); DataProcessingDevice::doRun(context); // FrameMark; } @@ -458,9 +459,9 @@ bool DataProcessingDevice::ConditionalRun() /// We drive the state loop ourself so that we will be able to support /// non-data triggers like those which are time based. -void DataProcessingDevice::doRun(DataProcessorContext& context) +void DataProcessingDevice::doPrepare(DataProcessorContext& context) { - ZoneScopedN("doRun"); + ZoneScopedN("DataProcessingDevice::doPrepare"); auto switchState = [& registry = context.registry, &state = context.state->streaming](StreamingState newState) { LOG(debug) << "New state " << (int)newState << " old state " << (int)state; @@ -480,7 +481,7 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) // expect to receive an EndOfStream signal. Thus we do not wait for these // to be completed. In the case of data source devices, as they do not have // real data input channels, they have to signal EndOfStream themselves. - bool allDone = std::any_of(context.state->inputChannelInfos.begin(), context.state->inputChannelInfos.end(), [](const auto& info) { + context.allDone = std::any_of(context.state->inputChannelInfos.begin(), context.state->inputChannelInfos.end(), [](const auto& info) { return info.state != InputChannelState::Pull; }); // Whether or not all the channels are completed @@ -489,7 +490,7 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) auto& info = context.state->inputChannelInfos[ci]; if (info.state != InputChannelState::Completed && info.state != InputChannelState::Pull) { - allDone = false; + context.allDone = false; } if (info.state != InputChannelState::Running) { continue; @@ -502,11 +503,22 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) // messages without hanging on the uv_run. *context.wasActive = true; DataProcessingDevice::handleData(context, parts, info); - context.completed->clear(); - context.completed->reserve(16); - *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); } } +} + +void DataProcessingDevice::doRun(DataProcessorContext& context) +{ + auto switchState = [& registry = context.registry, + &state = context.state->streaming](StreamingState newState) { + LOG(debug) << "New state " << (int)newState << " old state " << (int)state; + state = newState; + registry->get<ControlService>().notifyStreamingState(state); + }; + + context.completed->clear(); + context.completed->reserve(16); + *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); DanglingContext danglingContext{*context.registry}; for (auto preDanglingHandle : *context.preDanglingHandles) { preDanglingHandle.callback(danglingContext, preDanglingHandle.service); @@ -528,7 +540,7 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) // callback and return false. Notice that what happens next is actually // dependent on the callback, not something which is controlled by the // framework itself. - if (allDone == true && context.state->streaming == StreamingState::Streaming) { + if (context.allDone == true && context.state->streaming == StreamingState::Streaming) { switchState(StreamingState::EndOfStreaming); *context.wasActive = true; } From 5127399bb8bae3a0db93d061caa90ef3abc37794 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 20 Jul 2020 09:19:29 +0200 Subject: [PATCH 0132/1751] DPL: cleanup usage of context.state->streaming (#4013) --- Framework/Core/src/DataProcessingDevice.cxx | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 3c3008469b6cd..cb2d9951363b3 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -462,12 +462,6 @@ bool DataProcessingDevice::ConditionalRun() void DataProcessingDevice::doPrepare(DataProcessorContext& context) { ZoneScopedN("DataProcessingDevice::doPrepare"); - auto switchState = [& registry = context.registry, - &state = context.state->streaming](StreamingState newState) { - LOG(debug) << "New state " << (int)newState << " old state " << (int)state; - state = newState; - registry->get<ControlService>().notifyStreamingState(state); - }; context.registry->get<DataProcessingStats>().beginIterationTimestamp = uv_hrtime() / 1000000; *context.wasActive = false; @@ -510,10 +504,10 @@ void DataProcessingDevice::doPrepare(DataProcessorContext& context) void DataProcessingDevice::doRun(DataProcessorContext& context) { auto switchState = [& registry = context.registry, - &state = context.state->streaming](StreamingState newState) { - LOG(debug) << "New state " << (int)newState << " old state " << (int)state; - state = newState; - registry->get<ControlService>().notifyStreamingState(state); + &state = context.state](StreamingState newState) { + LOG(debug) << "New state " << (int)newState << " old state " << (int)state->streaming; + state->streaming = newState; + registry->get<ControlService>().notifyStreamingState(state->streaming); }; context.completed->clear(); @@ -911,9 +905,9 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, }; auto switchState = [& control = context.registry->get<ControlService>(), - &state = context.state->streaming](StreamingState newState) { - state = newState; - control.notifyStreamingState(state); + &state = context.state](StreamingState newState) { + state->streaming = newState; + control.notifyStreamingState(state->streaming); }; if (canDispatchSomeComputation() == false) { From 39395606c67b4f300afb1082840111a51e0b7135 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 20 Jul 2020 09:57:46 +0200 Subject: [PATCH 0133/1751] Fix typos in copyright notices for codechecker --- Detectors/CPV/simulation/src/Detector.cxx | 1 - Detectors/MUON/MCH/Tracking/src/TrackParam.cxx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Detectors/CPV/simulation/src/Detector.cxx b/Detectors/CPV/simulation/src/Detector.cxx index b68d112205a52..faf57590b8eb8 100644 --- a/Detectors/CPV/simulation/src/Detector.cxx +++ b/Detectors/CPV/simulation/src/Detector.cxx @@ -1,4 +1,3 @@ - // 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". diff --git a/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx b/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx index f7c88c0774ad8..3c3c389a1973e 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx @@ -1,4 +1,4 @@ -#// Copyright CERN and copyright holders of ALICE O2. This software is +// 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". // From 4886f1e606b457572735283af9d287059e60297b Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 21 Jul 2020 11:14:11 +0200 Subject: [PATCH 0134/1751] Dont use default qed/hadronic xsection User must provide explicitly the x-sections ratio value --- Steer/DigitizerWorkflow/src/SimReaderSpec.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx b/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx index 1ba8811c23703..2cad46653185e 100644 --- a/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx +++ b/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx @@ -125,6 +125,7 @@ DataProcessorSpec getSimReaderSpec(SubspecRange range, const std::vector<std::st } mgr.getInteractionSampler().init(); + mgr.getInteractionSampler().print(); // doing a random event selection/subsampling? mgr.setRandomEventSequence(ctx.options().get<int>("randomsample") > 0); @@ -151,12 +152,16 @@ DataProcessorSpec getSimReaderSpec(SubspecRange range, const std::vector<std::st last.bc = o2::constants::lhc::LHCMaxBunches; const float ratio = ctx.options().get<float>("qed-x-section-ratio"); + if (ratio <= 0.) { + throw std::runtime_error("no meaningful qed-x-section-ratio was provided"); + } const float hadronicrate = ctx.options().get<float>("interactionRate"); const float qedrate = ratio * hadronicrate; LOG(INFO) << "QED RATE " << qedrate; qedInteractionSampler.setInteractionRate(qedrate); qedInteractionSampler.setFirstIR(first); qedInteractionSampler.init(); + qedInteractionSampler.print(); std::vector<o2::InteractionTimeRecord> qedinteractionrecords; o2::InteractionTimeRecord t; LOG(INFO) << "GENERATING COL TIMES"; @@ -202,7 +207,7 @@ DataProcessorSpec getSimReaderSpec(SubspecRange range, const std::vector<std::st {"firstOrbit", VariantType::Int, 1, {"First orbit in interaction sampling"}}, {"bcPatternFile", VariantType::String, "", {"Interacting BC pattern file (e.g. from CreateBCPattern.C)"}}, {"simPrefixQED", VariantType::String, "", {"Sim (QED) input prefix (example: path/o2qed). The prefix allows to find files like path/o2qed_Kine.root etc."}}, - {"qed-x-section-ratio", VariantType::Float, 10000.0f, {"Ratio of cross sections QED/hadronic events. Determines QED interaction rate from hadronic interaction rate."}}, + {"qed-x-section-ratio", VariantType::Float, -1.f, {"Ratio of cross sections QED/hadronic events. Determines QED interaction rate from hadronic interaction rate."}}, {"outcontext", VariantType::String, "collisioncontext.root", {"Output file for collision context"}}, {"incontext", VariantType::String, "", {"Take collision context from this file"}}, {"ncollisions,n", From 23e7c91e3bf9b9ea46e569a449fb099fbe4a4b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 21 Jul 2020 21:34:21 +0200 Subject: [PATCH 0135/1751] Get particle masses from the PDG database. (#4022) Fix indentation in CMakeLists.txt. --- Analysis/Tasks/CMakeLists.txt | 130 ++++++++++---------- Analysis/Tasks/hfcandidatecreator2prong.cxx | 6 +- Analysis/Tasks/hftrackindexskimscreator.cxx | 6 +- 3 files changed, 73 insertions(+), 69 deletions(-) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index c9387198f4e59..bd707ba595a6b 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -9,44 +9,44 @@ # submit itself to any jurisdiction. o2_add_dpl_workflow(trackselection - SOURCES trackselection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES trackselection.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) o2_add_dpl_workflow(correlations - SOURCES correlations.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES correlations.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore + COMPONENT_NAME Analysis) o2_add_dpl_workflow(correlations-collection - SOURCES correlationsCollection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES correlationsCollection.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore + COMPONENT_NAME Analysis) o2_add_dpl_workflow(correlations-mixed - SOURCES correlationsMixed.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES correlationsMixed.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore + COMPONENT_NAME Analysis) o2_add_dpl_workflow(vertexing-hf - SOURCES vertexerhf.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing - COMPONENT_NAME Analysis) + SOURCES vertexerhf.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing + COMPONENT_NAME Analysis) o2_add_dpl_workflow(hftrackindexskimscreator - SOURCES hftrackindexskimscreator.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing - COMPONENT_NAME Analysis) + SOURCES hftrackindexskimscreator.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG + COMPONENT_NAME Analysis) o2_add_dpl_workflow(hfcandidatecreator2prong - SOURCES hfcandidatecreator2prong.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing - COMPONENT_NAME Analysis) + SOURCES hfcandidatecreator2prong.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG + COMPONENT_NAME Analysis) o2_add_dpl_workflow(taskdzero - SOURCES taskdzero.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing - COMPONENT_NAME Analysis) + SOURCES taskdzero.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing + COMPONENT_NAME Analysis) o2_add_dpl_workflow(spectra-tof SOURCES spectraTOF.cxx @@ -54,67 +54,67 @@ o2_add_dpl_workflow(spectra-tof COMPONENT_NAME Analysis) o2_add_dpl_workflow(validation - SOURCES validation.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase - COMPONENT_NAME Analysis) + SOURCES validation.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase + COMPONENT_NAME Analysis) if(FastJet_FOUND) o2_add_dpl_workflow(jetfinder - SOURCES jetfinder.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel - FastJet::FastJet - COMPONENT_NAME Analysis) + SOURCES jetfinder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + FastJet::FastJet + COMPONENT_NAME Analysis) endif() o2_add_dpl_workflow(upc-an - SOURCES upcAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) + SOURCES upcAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) o2_add_dpl_workflow(event-selection - SOURCES eventSelection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB - COMPONENT_NAME Analysis) + SOURCES eventSelection.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB + COMPONENT_NAME Analysis) o2_add_dpl_workflow(event-selection-qa - SOURCES eventSelectionQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) + SOURCES eventSelectionQa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) o2_add_dpl_workflow(multiplicity-table - SOURCES multiplicityTable.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) + SOURCES multiplicityTable.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) o2_add_dpl_workflow(multiplicity-qa - SOURCES multiplicityQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - + SOURCES multiplicityQa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(centrality-table - SOURCES centralityTable.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB - COMPONENT_NAME Analysis) + SOURCES centralityTable.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB + COMPONENT_NAME Analysis) o2_add_dpl_workflow(centrality-qa - SOURCES centralityQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - + SOURCES centralityQa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(invmass-an - SOURCES invMassAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - + SOURCES invMassAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(table-maker - SOURCES tableMaker.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore - COMPONENT_NAME Analysis) - + SOURCES tableMaker.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(table-reader - SOURCES tableReader.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES tableReader.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) o2_add_dpl_workflow(timestamp SOURCES timestamp.cxx diff --git a/Analysis/Tasks/hfcandidatecreator2prong.cxx b/Analysis/Tasks/hfcandidatecreator2prong.cxx index b593f8f944472..baa528f675c77 100644 --- a/Analysis/Tasks/hfcandidatecreator2prong.cxx +++ b/Analysis/Tasks/hfcandidatecreator2prong.cxx @@ -20,6 +20,8 @@ #include <TFile.h> #include <TH1F.h> #include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> #include <cmath> #include <array> #include <cstdlib> @@ -60,8 +62,8 @@ struct HFCandidateCreator2Prong { df.setMinRelChi2Change(d_minrelchi2change); std::vector<PxPyPzMVector> listTracks; - double masspion = 0.140; - double masskaon = 0.494; + double masspion = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + double masskaon = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); for (auto& hfpr2 : hftrackindexprong2s) { auto trackparvar_p1 = getTrackParCov(hfpr2.index0()); diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index f465ff1fbdba0..80d55aee3474f 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -20,6 +20,8 @@ #include <TFile.h> #include <TH1F.h> #include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> #include <cmath> #include <array> #include <cstdlib> @@ -87,8 +89,8 @@ struct SelectTracks { struct HFTrackIndexSkimsCreator { std::vector<PxPyPzMVector> listTracks; - double masspion = 0.140; - double masskaon = 0.494; + double masspion = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + double masskaon = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; Produces<aod::HfTrackIndexProng2> hftrackindexprong2; From e08ec663d9f993be246d208e3dade7f6b9b8c1f0 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 21 Jul 2020 21:35:11 +0200 Subject: [PATCH 0136/1751] DPL: pass --shm-mlock-segment to FairMQ (#4018) --- Framework/Core/src/DeviceSpecHelpers.cxx | 2 ++ Framework/Core/test/test_FrameworkDataFlowToDDS.cxx | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 7d1846c6f6fcd..3fbbeca68b09e 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -908,6 +908,7 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, realOdesc.add_options()("child-driver", bpo::value<std::string>()); realOdesc.add_options()("rate", bpo::value<std::string>()); realOdesc.add_options()("shm-segment-size", bpo::value<std::string>()); + realOdesc.add_options()("shm-mlock-segment", bpo::value<std::string>()); realOdesc.add_options()("shm-monitor", bpo::value<std::string>()); realOdesc.add_options()("session", bpo::value<std::string>()); filterArgsFct(expansions.we_wordc, expansions.we_wordv, realOdesc); @@ -1016,6 +1017,7 @@ boost::program_options::options_description DeviceSpecHelpers::getForwardedDevic ("rate", bpo::value<std::string>(), "rate for a data source device (Hz)") // ("shm-monitor", bpo::value<std::string>(), "whether to use the shared memory monitor") // ("shm-segment-size", bpo::value<std::string>(), "size of the shared memory segment in bytes") // + ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // ("session", bpo::value<std::string>(), "unique label for the shared memory session") // ("configuration,cfg", bpo::value<std::string>(), "configuration connection string") // ("monitoring-backend", bpo::value<std::string>(), "monitoring connection string") // diff --git a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx index 8861b0df3101b..908856fca1805 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx @@ -97,16 +97,16 @@ BOOST_AUTO_TEST_CASE(TestDDS) dumpDeviceSpec2DDS(ss, devices, executions); BOOST_CHECK_EQUAL(ss.str(), R"EXPECTED(<topology name="o2-dataflow"> <decltask name="A"> - <exe reachable="true">foo --id A --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id A --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="B"> - <exe reachable="true">foo --id B --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id B --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="C"> - <exe reachable="true">foo --id C --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id C --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="D"> - <exe reachable="true">foo --id D --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id D --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <declcollection name="DPL"> <tasks> From fbcb566bfa970d147e846ea5b3ba57bfd6b09b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Tue, 21 Jul 2020 21:35:41 +0200 Subject: [PATCH 0137/1751] Add PID in hf vertexing (#4021) --- Analysis/Tasks/hftrackindexskimscreator.cxx | 34 +++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index 80d55aee3474f..d67d3fc601d46 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -15,6 +15,7 @@ #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" +#include "PID/PIDResponse.h" #include "Analysis/trackUtilities.h" #include <TFile.h> @@ -34,18 +35,25 @@ using namespace ROOT::Math; namespace o2::aod { -namespace seltrack +namespace hfseltrack { +enum Select { + IsTrackSel = BIT(0), + IsPion = BIT(1), + IsKaon = BIT(2), + IsProton = BIT(3) +}; + 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 hfseltrack +DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", hfseltrack::IsSel, hfseltrack::DCAPrim0, + hfseltrack::DCAPrim1); } // namespace o2::aod struct SelectTracks { - Produces<aod::SelTrack> seltrack; + Produces<aod::SelTrack> hfseltrack; Configurable<double> ptmintrack{"ptmintrack", -1, "ptmin single track"}; Configurable<double> dcatoprimxymin{"dcatoprimxymin", 0, "dca xy to prim vtx min"}; Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min number of tpc cls >="}; @@ -56,7 +64,7 @@ struct SelectTracks { OutputObj<TH1F> hdcatoprimxy_cuts{TH1F("hdcatoprimxy_cuts", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; void process(aod::Collision const& collision, - soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) + soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::pidRespTOF> const& tracks) { Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); for (auto it0 = tracks.begin(); it0 != tracks.end(); ++it0) { @@ -76,13 +84,21 @@ struct SelectTracks { trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca); if (abs(dca[0]) < dcatoprimxymin) status = 0; + if (status) { + if (TMath::Abs(track_0.nSigmaPi()) < 3) + status |= BIT(o2::aod::hfseltrack::IsPion); + if (TMath::Abs(track_0.nSigmaKa()) < 3) + status |= BIT(o2::aod::hfseltrack::IsKaon); + if (TMath::Abs(track_0.nSigmaPr()) < 3) + status |= BIT(o2::aod::hfseltrack::IsProton); + } if (b_dovalplots == true) { - if (status == 1) { + if (status) { hpt_cuts->Fill(track_0.pt()); hdcatoprimxy_cuts->Fill(dca[0]); } } - seltrack(status, dca[0], dca[1]); + hfseltrack(status, dca[0], dca[1]); } } }; @@ -110,7 +126,7 @@ struct HFTrackIndexSkimsCreator { Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min mass dplus presel"}; Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - Filter seltrack = (aod::seltrack::issel == 1); + Filter hfseltrack = (aod::hfseltrack::issel == 1); void process(aod::Collision const& collision, aod::BCs const& bcs, From b55c9e5c61751612d6eed42b88c4e02d17a5aa5d Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Tue, 21 Jul 2020 21:36:08 +0200 Subject: [PATCH 0138/1751] Nitpick: added using for clearer code (#4015) --- Analysis/Tutorials/src/partitions.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Analysis/Tutorials/src/partitions.cxx b/Analysis/Tutorials/src/partitions.cxx index 05455f3d46f26..ca56c4c4209d7 100644 --- a/Analysis/Tutorials/src/partitions.cxx +++ b/Analysis/Tutorials/src/partitions.cxx @@ -32,11 +32,14 @@ struct ATask { float philow = 1.0f; float phiup = 2.0f; - Partition<soa::Filtered<aod::Tracks>> leftPhi = aod::track::phiraw < philow; - Partition<soa::Filtered<aod::Tracks>> midPhi = aod::track::phiraw >= philow && aod::track::phiraw < phiup; - Partition<soa::Filtered<aod::Tracks>> rightPhi = aod::track::phiraw >= phiup; - void process(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& tracks) + using myTracks = soa::Filtered<aod::Tracks>; + + Partition<myTracks> leftPhi = aod::track::phiraw < philow; + Partition<myTracks> midPhi = aod::track::phiraw >= philow && aod::track::phiraw < phiup; + Partition<myTracks> rightPhi = aod::track::phiraw >= phiup; + + void process(aod::Collision const& collision, myTracks const& tracks) { LOGF(INFO, "Collision: %d [N = %d] [left phis = %d] [mid phis = %d] [right phis = %d]", collision.globalIndex(), tracks.size(), leftPhi.size(), midPhi.size(), rightPhi.size()); From 562b47b3b9254d94df2a98f3045c6cc1c0c8f01b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 21 Jul 2020 21:53:27 +0200 Subject: [PATCH 0139/1751] CODEOWNERS: Make @ginnocen owner of AliceO2/Analysis/Tasks/hf* --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 5d6caaf8fd90e..6bed50671ba2b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -13,6 +13,7 @@ /Algorithm @matthiasrichter /Analysis @jgrosseo +/Analysis/Tasks/hf* @ginnocen /CCDB @costing @Barthelemy @sawenzel @AliceO2Group/framework-admins From 500bd4acbff59a247429a9a524cb9c208ac2ff3e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 21 Jul 2020 21:59:29 +0200 Subject: [PATCH 0140/1751] Revert "Add PID in hf vertexing (#4021)" (#4024) This reverts commit fbcb566bfa970d147e846ea5b3ba57bfd6b09b77. --- Analysis/Tasks/hftrackindexskimscreator.cxx | 34 ++++++--------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index d67d3fc601d46..80d55aee3474f 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -15,7 +15,6 @@ #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" -#include "PID/PIDResponse.h" #include "Analysis/trackUtilities.h" #include <TFile.h> @@ -35,25 +34,18 @@ using namespace ROOT::Math; namespace o2::aod { -namespace hfseltrack +namespace seltrack { -enum Select { - IsTrackSel = BIT(0), - IsPion = BIT(1), - IsKaon = BIT(2), - IsProton = BIT(3) -}; - DECLARE_SOA_COLUMN(IsSel, issel, int); DECLARE_SOA_COLUMN(DCAPrim0, dcaprim0, float); DECLARE_SOA_COLUMN(DCAPrim1, dcaprim1, float); -} // namespace hfseltrack -DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", hfseltrack::IsSel, hfseltrack::DCAPrim0, - hfseltrack::DCAPrim1); +} // namespace seltrack +DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", seltrack::IsSel, seltrack::DCAPrim0, + seltrack::DCAPrim1); } // namespace o2::aod struct SelectTracks { - Produces<aod::SelTrack> hfseltrack; + Produces<aod::SelTrack> seltrack; Configurable<double> ptmintrack{"ptmintrack", -1, "ptmin single track"}; Configurable<double> dcatoprimxymin{"dcatoprimxymin", 0, "dca xy to prim vtx min"}; Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min number of tpc cls >="}; @@ -64,7 +56,7 @@ struct SelectTracks { OutputObj<TH1F> hdcatoprimxy_cuts{TH1F("hdcatoprimxy_cuts", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; void process(aod::Collision const& collision, - soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::pidRespTOF> const& tracks) + soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) { Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); for (auto it0 = tracks.begin(); it0 != tracks.end(); ++it0) { @@ -84,21 +76,13 @@ struct SelectTracks { trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca); if (abs(dca[0]) < dcatoprimxymin) status = 0; - if (status) { - if (TMath::Abs(track_0.nSigmaPi()) < 3) - status |= BIT(o2::aod::hfseltrack::IsPion); - if (TMath::Abs(track_0.nSigmaKa()) < 3) - status |= BIT(o2::aod::hfseltrack::IsKaon); - if (TMath::Abs(track_0.nSigmaPr()) < 3) - status |= BIT(o2::aod::hfseltrack::IsProton); - } if (b_dovalplots == true) { - if (status) { + if (status == 1) { hpt_cuts->Fill(track_0.pt()); hdcatoprimxy_cuts->Fill(dca[0]); } } - hfseltrack(status, dca[0], dca[1]); + seltrack(status, dca[0], dca[1]); } } }; @@ -126,7 +110,7 @@ struct HFTrackIndexSkimsCreator { Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min mass dplus presel"}; Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - Filter hfseltrack = (aod::hfseltrack::issel == 1); + Filter seltrack = (aod::seltrack::issel == 1); void process(aod::Collision const& collision, aod::BCs const& bcs, From 638ccb02fa8787b486f658ba5bdae4a9bd739b41 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 22 Jul 2020 09:35:22 +0200 Subject: [PATCH 0141/1751] DPL: pass environment to children via --environment (#4025) --- .../Core/include/Framework/DeviceExecution.h | 2 + Framework/Core/src/DeviceSpecHelpers.cxx | 53 +++++++++++++------ Framework/Core/src/runDataProcessing.cxx | 3 ++ 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceExecution.h b/Framework/Core/include/Framework/DeviceExecution.h index 0dae0252c4319..8e3b57b6bc291 100644 --- a/Framework/Core/include/Framework/DeviceExecution.h +++ b/Framework/Core/include/Framework/DeviceExecution.h @@ -23,6 +23,8 @@ namespace framework struct DeviceExecution { /// The options passed to a given device std::vector<char*> args; + /// The environment to be passed to a given device + std::vector<char*> environ; }; } // namespace framework diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 3fbbeca68b09e..79d4bdf2898c3 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -800,6 +800,18 @@ void DeviceSpecHelpers::reworkShmSegmentSize(std::vector<DataProcessorInfo>& inf } } +namespace +{ +template <class Container> +void split(const std::string& str, Container& cont) +{ + std::istringstream iss(str); + std::copy(std::istream_iterator<std::string>(iss), + std::istream_iterator<std::string>(), + std::back_inserter(cont)); +} +} // namespace + void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, std::vector<DataProcessorInfo> const& processorInfos, std::vector<DeviceSpec> const& deviceSpecs, @@ -860,6 +872,7 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, "--shm-monitor", "false", "--log-color", "false", "--color", "false"}; + std::vector<std::string> tmpEnv; if (defaultStopped) { tmpArgs.push_back("-s"); } @@ -891,6 +904,10 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, bpo::variables_map varmap; bpo::store(parsed_options, varmap); + if (varmap.count("environment")) { + auto environment = varmap["environment"].as<std::string>(); + split(environment, tmpEnv); + } // options can be grouped per processor spec, the group is entered by // the option created from the actual processor spec name @@ -907,6 +924,7 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, realOdesc.add_options()("severity", bpo::value<std::string>()); realOdesc.add_options()("child-driver", bpo::value<std::string>()); realOdesc.add_options()("rate", bpo::value<std::string>()); + realOdesc.add_options()("environment", bpo::value<std::string>()); realOdesc.add_options()("shm-segment-size", bpo::value<std::string>()); realOdesc.add_options()("shm-mlock-segment", bpo::value<std::string>()); realOdesc.add_options()("shm-monitor", bpo::value<std::string>()); @@ -990,6 +1008,10 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, // execvp wants a NULL terminated list. execution.args.push_back(nullptr); + for (auto& env : tmpEnv) { + execution.environ.emplace_back(strdup(env.c_str())); + } + // FIXME: this should probably be reflected in the GUI std::ostringstream str; for (size_t ai = 0; ai < execution.args.size() - 1; ai++) { @@ -1009,21 +1031,22 @@ boost::program_options::options_description DeviceSpecHelpers::getForwardedDevic // - rate is an option of FairMQ device for ConditionalRun // - child-driver is not a FairMQ device option but used per device to start to process bpo::options_description forwardedDeviceOptions; - forwardedDeviceOptions.add_options() // - ("severity", bpo::value<std::string>()->default_value("info"), "severity level of the log") // - ("plugin,P", bpo::value<std::string>(), "FairMQ plugin list") // - ("plugin-search-path,S", bpo::value<std::string>(), "FairMQ plugins search path") // - ("control-port", bpo::value<std::string>(), "Utility port to be used by O2 Control") // - ("rate", bpo::value<std::string>(), "rate for a data source device (Hz)") // - ("shm-monitor", bpo::value<std::string>(), "whether to use the shared memory monitor") // - ("shm-segment-size", bpo::value<std::string>(), "size of the shared memory segment in bytes") // - ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // - ("session", bpo::value<std::string>(), "unique label for the shared memory session") // - ("configuration,cfg", bpo::value<std::string>(), "configuration connection string") // - ("monitoring-backend", bpo::value<std::string>(), "monitoring connection string") // - ("infologger-mode", bpo::value<std::string>(), "INFOLOGGER_MODE override") // - ("infologger-severity", bpo::value<std::string>(), "minimun FairLogger severity which goes to info logger") // - ("child-driver", bpo::value<std::string>(), "external driver to start childs with (e.g. valgrind)"); // + forwardedDeviceOptions.add_options() // + ("severity", bpo::value<std::string>()->default_value("info"), "severity level of the log") // + ("plugin,P", bpo::value<std::string>(), "FairMQ plugin list") // + ("plugin-search-path,S", bpo::value<std::string>(), "FairMQ plugins search path") // + ("control-port", bpo::value<std::string>(), "Utility port to be used by O2 Control") // + ("rate", bpo::value<std::string>(), "rate for a data source device (Hz)") // + ("shm-monitor", bpo::value<std::string>(), "whether to use the shared memory monitor") // + ("shm-segment-size", bpo::value<std::string>(), "size of the shared memory segment in bytes") // + ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // + ("environment", bpo::value<std::string>(), "comma separated list of environment variables to set for the device") // + ("session", bpo::value<std::string>(), "unique label for the shared memory session") // + ("configuration,cfg", bpo::value<std::string>(), "configuration connection string") // + ("monitoring-backend", bpo::value<std::string>(), "monitoring connection string") // + ("infologger-mode", bpo::value<std::string>(), "INFOLOGGER_MODE override") // + ("infologger-severity", bpo::value<std::string>(), "minimun FairLogger severity which goes to info logger") // + ("child-driver", bpo::value<std::string>(), "external driver to start childs with (e.g. valgrind)"); // return forwardedDeviceOptions; } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 26a1bebe02067..00bd0341e2b4a 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -414,6 +414,9 @@ void spawnDevice(std::string const& forwardedStdin, service.postForkChild(serviceRegistry); } } + for (auto& env : execution.environ) { + putenv(env); + } execvp(execution.args[0], execution.args.data()); } // This is the parent. We close the write end of From 71e86f5c4e777df2b5ad02ca791bc0029741ff2d Mon Sep 17 00:00:00 2001 From: frmanso <manso@clermont.in2p3.fr> Date: Wed, 22 Jul 2020 16:27:31 +0200 Subject: [PATCH 0142/1751] New Power Supply Unit (#4016) Co-authored-by: Manso <manso@clraliceport15.in2p3.fr> --- .../MFT/base/include/MFTBase/HalfDetector.h | 3 - .../ITSMFT/MFT/base/src/GeometryBuilder.cxx | 14 +- .../ITSMFT/MFT/base/src/HalfDetector.cxx | 15 +- .../ITSMFT/MFT/base/src/PowerSupplyUnit.cxx | 1672 +++++++++++------ 4 files changed, 1090 insertions(+), 614 deletions(-) diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfDetector.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfDetector.h index 1c6a5ddf8d3a4..8797d4b2e797b 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfDetector.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfDetector.h @@ -18,7 +18,6 @@ #include "TNamed.h" #include "TGeoVolume.h" -#include "MFTBase/PowerSupplyUnit.h" namespace o2 { @@ -51,8 +50,6 @@ class HalfDetector : public TNamed private: HalfSegmentation* mSegmentation; ///< \brief Pointer to the half-MFT segmentation - PowerSupplyUnit* mPSU; - void createHalfDisks(); ClassDefOverride(HalfDetector, 1); diff --git a/Detectors/ITSMFT/MFT/base/src/GeometryBuilder.cxx b/Detectors/ITSMFT/MFT/base/src/GeometryBuilder.cxx index 7185b5a7790d8..7608c734e6a69 100644 --- a/Detectors/ITSMFT/MFT/base/src/GeometryBuilder.cxx +++ b/Detectors/ITSMFT/MFT/base/src/GeometryBuilder.cxx @@ -22,6 +22,7 @@ #include "MFTBase/Barrel.h" #include "MFTBase/PatchPanel.h" #include "MFTBase/MFTBaseParam.h" +#include "MFTBase/PowerSupplyUnit.h" #include "TGeoVolume.h" #include "TGeoManager.h" @@ -60,7 +61,18 @@ void GeometryBuilder::buildGeometry() delete halfMFT; } - /// \todo Add the service, Barrel, etc Those objects will probably be defined into the COMMON ITSMFT area. + // Add the service, Barrel, etc + if (!mftBaseParam.minimal && mftBaseParam.buildPSU) { + auto* mPSU = new PowerSupplyUnit(); + TGeoVolumeAssembly* mHalfPSU = mPSU->create(); + TGeoTranslation* t_PSU = new TGeoTranslation("t_PSU", 0, 0.0, -72.6); + t_PSU->RegisterYourself(); + auto* r_PSU = new TGeoRotation("rotation_PSU", 0.0, 0.0, 180.0); + auto* p_PSU = new TGeoCombiTrans(*t_PSU, *r_PSU); + volMFT->AddNode(mHalfPSU, 1, t_PSU); + volMFT->AddNode(mHalfPSU, 2, p_PSU); + } + if (!mftBaseParam.minimal && mftBaseParam.buildCone) { auto* halfCone = new HalfCone(); TGeoVolumeAssembly* halfCone1 = halfCone->createHalfCone(0); diff --git a/Detectors/ITSMFT/MFT/base/src/HalfDetector.cxx b/Detectors/ITSMFT/MFT/base/src/HalfDetector.cxx index 51f6b102166dc..b3a133dbae734 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfDetector.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfDetector.cxx @@ -21,7 +21,7 @@ #include "MFTBase/HalfDisk.h" #include "MFTBase/Geometry.h" #include "MFTBase/HalfDetector.h" -#include "MFTBase/PowerSupplyUnit.h" +//#include "MFTBase/PowerSupplyUnit.h" #include "MFTBase/MFTBaseParam.h" using namespace o2::mft; @@ -31,12 +31,12 @@ ClassImp(o2::mft::HalfDetector); /// \brief Default constructor //_____________________________________________________________________________ -HalfDetector::HalfDetector() : TNamed(), mHalfVolume(nullptr), mSegmentation(nullptr), mPSU(nullptr) {} +HalfDetector::HalfDetector() : TNamed(), mHalfVolume(nullptr), mSegmentation(nullptr) {} /// \brief Constructor //_____________________________________________________________________________ -HalfDetector::HalfDetector(HalfSegmentation* seg) : TNamed(), mHalfVolume(nullptr), mSegmentation(seg), mPSU(nullptr) +HalfDetector::HalfDetector(HalfSegmentation* seg) : TNamed(), mHalfVolume(nullptr), mSegmentation(seg) { Geometry* mftGeom = Geometry::instance(); @@ -49,7 +49,7 @@ HalfDetector::HalfDetector(HalfSegmentation* seg) : TNamed(), mHalfVolume(nullpt mHalfVolume = new TGeoVolumeAssembly(GetName()); - mPSU = new PowerSupplyUnit(); + //mPSU = new PowerSupplyUnit(); createHalfDisks(); } @@ -72,11 +72,4 @@ void HalfDetector::createHalfDisks() mHalfVolume->AddNode(halfDisk->getVolume(), halfDiskId, halfDiskSeg->getTransformation()); delete halfDisk; } - - if (!mftBaseParam.minimal && mftBaseParam.buildPSU) { - TGeoVolumeAssembly* mHalfPSU = mPSU->create(); - TGeoTranslation* tHalfPSU = new TGeoTranslation("tHalfPSU", 0, 0.4, -72.6 + 46.0); - tHalfPSU->RegisterYourself(); - mHalfVolume->AddNode(mHalfPSU, 0, tHalfPSU); - } } diff --git a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx index 1d8192d85ca94..ce227260a32d9 100644 --- a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx +++ b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx @@ -9,8 +9,8 @@ // or submit itself to any jurisdiction. /// \file PowerSupplyUnit.cxx -/// \brief Class building the MFT heat exchanger -/// \author P. Demongodin, Raphael Tieulent <raphael.tieulent@cern.ch> +/// \brief Class building the MFT Power Supply Unit +/// \author Satoshi Yano #include "TMath.h" #include "TGeoManager.h" @@ -20,6 +20,7 @@ #include "TGeoCone.h" #include "TGeoBoolNode.h" #include "TGeoBBox.h" +#include "TGeoSphere.h" #include "TGeoVolume.h" #include "FairLogger.h" #include "MFTBase/Constants.h" @@ -40,703 +41,1176 @@ PowerSupplyUnit::PowerSupplyUnit() TGeoVolumeAssembly* PowerSupplyUnit::create() { - //fm auto* mPowerSupplyUnit = new TGeoVolumeAssembly(); - - new TGeoBBox("dummy", 0, 0, 0); + //TGeoManager *gManager = new TGeoManager(); TGeoMedium* kMedPeek = gGeoManager->GetMedium("MFT_PEEK$"); TGeoMedium* kMed_Water = gGeoManager->GetMedium("MFT_Water$"); TGeoMedium* kMedAlu = gGeoManager->GetMedium("MFT_Alu$"); - TGeoMedium* kMedCu = gGeoManager->GetMedium("MFT_Cu$"); TGeoVolumeAssembly* mHalfPSU = new TGeoVolumeAssembly("PSU"); + Double_t delta_thickness = 0.2; + + Double_t water_pipe_main_position_radius = (18.62 + 18.18) / 2.; + + Double_t block_widest_angle = 126.07; + Double_t block_radius = (19.5 + 17.7) / 2.; + Double_t block_angle_index[] = {126.08, 114.03, 101.91, 89.96, 77.88, 66.06, 54.16, 42.06, 30, 17.99, 6.07}; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //Middle peek part + //Middle Spacer //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Double_t middle_board_thickness = 0.8; - Double_t middle_board_max_radius1 = 26.432; - Double_t middle_board_min_radius1 = 17.0; - Double_t middleBox_sub_angle2 = 112.26 * TMath::Pi() / 180.; - Double_t middleBox_sub_width1 = 20.8; - - Double_t middleBox_sub_height1 = middle_board_max_radius1 * (1 - sqrt(1 - pow(middleBox_sub_width1 / 2. / middle_board_max_radius1, 2))); - - Double_t middleBox_sub_width2 = 2 * middle_board_max_radius1; - Double_t middleBox_sub_height2 = 2 * middle_board_min_radius1 * TMath::Cos(middleBox_sub_angle2 / 2); - - new TGeoTubeSeg("middleTubeSeg1", middle_board_min_radius1, middle_board_max_radius1, middle_board_thickness / 2, 180, 0); - new TGeoBBox("middleBox_sub1", middleBox_sub_width1 / 2, middleBox_sub_height1 / 2, middle_board_thickness); - new TGeoBBox("middleBox_sub2", middleBox_sub_width2 / 2, middleBox_sub_height2 / 2, middle_board_thickness); - - auto* tmiddleBox_sub1 = new TGeoTranslation("tmiddleBox_sub1", 0, -(middle_board_max_radius1 - middleBox_sub_height1 / 2), 0); - auto* tmiddleBox_sub2 = new TGeoTranslation("tmiddleBox_sub2", 0., 0., 0.); - tmiddleBox_sub1->RegisterYourself(); - tmiddleBox_sub2->RegisterYourself(); - - Double_t middleBox_edge_width1 = 11.4; - Double_t middleBox_edge_height1 = 4.996; - - Double_t middleBox_edge_sub_width1 = 1.8 + 0.5 * 2; - Double_t middleBox_edge_sub_height1 = 6.025 + 0.5 * 2; + std::string name_middle_spacer_main_cover = ""; + + //main + Double_t middle_spacer_main_thickness = 0.50; + Double_t middle_spacer_main_min_radius1 = 17.0; + Double_t middle_spacer_main_max_radius1 = 21.7; + Double_t middle_spacer_main_sub_rectangle_top_height = 5 + 2.787; + Double_t middle_spacer_main_sub_rectangle_top_width = middle_spacer_main_max_radius1 * 2; + + TGeoTubeSeg* middle_spacer_main_arc = new TGeoTubeSeg("middle_spacer_main_arc", middle_spacer_main_min_radius1, middle_spacer_main_max_radius1, middle_spacer_main_thickness / 2, 180, 0); + TGeoBBox* middle_spacer_main_sub_rectangle_top = new TGeoBBox("middle_spacer_main_sub_rectangle_top", middle_spacer_main_sub_rectangle_top_width / 2., middle_spacer_main_sub_rectangle_top_height / 2., middle_spacer_main_thickness / 2. + delta_thickness); + TGeoTranslation* trans_middle_spacer_main_sub_rectangle_top = new TGeoTranslation("trans_middle_spacer_main_sub_rectangle_top", 0, -middle_spacer_main_sub_rectangle_top_height / 2, 0); + trans_middle_spacer_main_sub_rectangle_top->RegisterYourself(); + + Double_t middle_spacer_main_add_rectangle_side_height = 4.5 + 1.5; + Double_t middle_spacer_main_add_rectangle_side_width = 9.0; + TGeoBBox* middle_spacer_main_add_rectangle_side = new TGeoBBox("middle_spacer_main_add_rectangle_side", middle_spacer_main_add_rectangle_side_width / 2., middle_spacer_main_add_rectangle_side_height / 2., middle_spacer_main_thickness / 2.); + TGeoTranslation* trans_middle_spacer_main_add_rectangle_side_left = new TGeoTranslation("trans_middle_spacer_main_add_rectangle_side_left", 28.4 / 2. + middle_spacer_main_add_rectangle_side_width / 2., -5 - middle_spacer_main_add_rectangle_side_height / 2., 0); + TGeoTranslation* trans_middle_spacer_main_add_rectangle_side_right = new TGeoTranslation("trans_middle_spacer_main_add_rectangle_side_right", -(28.4 / 2. + middle_spacer_main_add_rectangle_side_width / 2.), -5 - middle_spacer_main_add_rectangle_side_height / 2., 0); + trans_middle_spacer_main_add_rectangle_side_left->RegisterYourself(); + trans_middle_spacer_main_add_rectangle_side_right->RegisterYourself(); + + Double_t middle_spacer_main_add_rectangle_side_small_thickness = 1.18; + Double_t middle_spacer_main_add_rectangle_side_small_height = 1.5; + Double_t middle_spacer_main_add_rectangle_side_small_width = 2.4; + TGeoBBox* middle_spacer_main_add_rectangle_side_small = new TGeoBBox("middle_spacer_main_add_rectangle_side_small", middle_spacer_main_add_rectangle_side_small_width / 2., middle_spacer_main_add_rectangle_side_small_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2.); + TGeoTranslation* trans_middle_spacer_main_add_rectangle_side_small_left = new TGeoTranslation("trans_middle_spacer_main_add_rectangle_side_small_left", 28.4 / 2. + middle_spacer_main_add_rectangle_side_width + middle_spacer_main_add_rectangle_side_small_width / 2, -5 - middle_spacer_main_add_rectangle_side_small_height / 2., 0); + TGeoTranslation* trans_middle_spacer_main_add_rectangle_side_small_right = new TGeoTranslation("trans_middle_spacer_main_add_rectangle_side_small_right", -(28.4 / 2. + middle_spacer_main_add_rectangle_side_width + middle_spacer_main_add_rectangle_side_small_width / 2), -5 - middle_spacer_main_add_rectangle_side_small_height / 2., 0); + trans_middle_spacer_main_add_rectangle_side_small_left->RegisterYourself(); + trans_middle_spacer_main_add_rectangle_side_small_right->RegisterYourself(); + + TGeoCompositeShape* middle_spacer_main = new TGeoCompositeShape("middle_spacer_main", + "middle_spacer_main_arc - middle_spacer_main_sub_rectangle_top:trans_middle_spacer_main_sub_rectangle_top" + " + middle_spacer_main_add_rectangle_side:trans_middle_spacer_main_add_rectangle_side_left + middle_spacer_main_add_rectangle_side:trans_middle_spacer_main_add_rectangle_side_right" + " + middle_spacer_main_add_rectangle_side_small:trans_middle_spacer_main_add_rectangle_side_small_left + middle_spacer_main_add_rectangle_side_small:trans_middle_spacer_main_add_rectangle_side_small_right"); + + //Cover + + Double_t middle_spacer_cover_thickness = 0.15; + Double_t middle_spacer_cover_arc_max_radius = 19.5; + Double_t middle_spacer_cover_arc_min_radius = 17.0; + TGeoTubeSeg* middle_spacer_cover_arc = new TGeoTubeSeg("middle_spacer_cover_arc", middle_spacer_cover_arc_min_radius, middle_spacer_cover_arc_max_radius, middle_spacer_cover_thickness / 2, 180, 0); + TGeoTranslation* trans_middle_spacer_cover_arc = new TGeoTranslation("trans_middle_spacer_cover_arc", 0, 0, middle_spacer_main_thickness / 2 + middle_spacer_cover_thickness / 2); + trans_middle_spacer_cover_arc->RegisterYourself(); + + Double_t middle_spacer_cover_sub_rectangle_top_height = 5.0 + 1.5 + 1.9; + Double_t middle_spacer_cover_sub_rectangle_top_width = middle_spacer_cover_arc_max_radius * 2; + TGeoBBox* middle_spacer_cover_sub_rectangle_top = new TGeoBBox("middle_spacer_cover_sub_rectangle_top", middle_spacer_cover_sub_rectangle_top_width / 2., middle_spacer_cover_sub_rectangle_top_height, middle_spacer_cover_thickness / 2. + delta_thickness); + TGeoTranslation* trans_middle_spacer_cover_sub_rectangle_top = new TGeoTranslation("trans_middle_spacer_cover_sub_rectangle_top", 0, 0, middle_spacer_main_thickness / 2 + middle_spacer_cover_thickness / 2); + trans_middle_spacer_cover_sub_rectangle_top->RegisterYourself(); + + Double_t middle_spacer_cover_rectangle_side1_height = 1.9; + Double_t middle_spacer_cover_rectangle_side1_width_left = 4.2; //rahgh + Double_t middle_spacer_cover_rectangle_side1_width_right = 8.8; //rahgh + TGeoBBox* middle_spacer_cover_rectangle_side1_left = new TGeoBBox("middle_spacer_cover_rectangle_side1_left", middle_spacer_cover_rectangle_side1_width_left / 2., middle_spacer_cover_rectangle_side1_height / 2., middle_spacer_cover_thickness / 2.); + TGeoBBox* middle_spacer_cover_rectangle_side1_right = new TGeoBBox("middle_spacer_cover_rectangle_side1_right", middle_spacer_cover_rectangle_side1_width_right / 2., middle_spacer_cover_rectangle_side1_height / 2., middle_spacer_cover_thickness / 2.); + TGeoTranslation* trans_middle_spacer_cover_rectangle_side1_left = new TGeoTranslation("trans_middle_spacer_cover_rectangle_side1_left", 28.4 / 2 + middle_spacer_cover_rectangle_side1_width_left / 2, -5 - 1.5 - 1.9 + middle_spacer_cover_rectangle_side1_height / 2, middle_spacer_main_thickness / 2 + middle_spacer_cover_thickness / 2); + TGeoTranslation* trans_middle_spacer_cover_rectangle_side1_right = new TGeoTranslation("trans_middle_spacer_cover_rectangle_side1_right", -(28.4 / 2 + middle_spacer_cover_rectangle_side1_width_right / 2), -5 - 1.5 - 1.9 + middle_spacer_cover_rectangle_side1_height / 2, middle_spacer_main_thickness / 2 + middle_spacer_cover_thickness / 2); + trans_middle_spacer_cover_rectangle_side1_left->RegisterYourself(); + trans_middle_spacer_cover_rectangle_side1_right->RegisterYourself(); + + Double_t middle_spacer_cover_rectangle_side2_height = 1.5; + Double_t middle_spacer_cover_rectangle_side2_width = 2.0; //rahgh + TGeoBBox* middle_spacer_cover_rectangle_side2 = new TGeoBBox("middle_spacer_cover_rectangle_side2", middle_spacer_cover_rectangle_side2_width / 2., middle_spacer_cover_rectangle_side2_height / 2., middle_spacer_cover_thickness / 2.); + TGeoTranslation* trans_middle_spacer_cover_rectangle_side2_left = new TGeoTranslation("trans_middle_spacer_cover_rectangle_side2_left", 28.4 / 2 + middle_spacer_cover_rectangle_side2_width / 2, -5 - 1.5 - 2.787 + middle_spacer_cover_rectangle_side2_height / 2, middle_spacer_main_thickness / 2 + middle_spacer_cover_thickness / 2); + TGeoTranslation* trans_middle_spacer_cover_rectangle_side2_right = new TGeoTranslation("trans_middle_spacer_cover_rectangle_side2_right", -(28.4 / 2 + middle_spacer_cover_rectangle_side2_width / 2), -5 - 1.5 - 2.787 + middle_spacer_cover_rectangle_side2_height / 2, middle_spacer_main_thickness / 2 + middle_spacer_cover_thickness / 2); + trans_middle_spacer_cover_rectangle_side2_left->RegisterYourself(); + trans_middle_spacer_cover_rectangle_side2_right->RegisterYourself(); + + Double_t middle_spacer_cover_rectangle_side3_height = 1.9; + Double_t middle_spacer_cover_rectangle_side3_width = 2.1; //rahgh + TGeoBBox* middle_spacer_cover_rectangle_side3 = new TGeoBBox("middle_spacer_cover_rectangle_side3", middle_spacer_cover_rectangle_side3_width / 2., middle_spacer_cover_rectangle_side3_height / 2., middle_spacer_cover_thickness / 2.); + TGeoTranslation* trans_middle_spacer_cover_rectangle_side3 = new TGeoTranslation("trans_middle_spacer_cover_rectangle_side3", 28.4 / 2 + 8.8 - middle_spacer_cover_rectangle_side3_width / 2, -5 - 1.5 - middle_spacer_cover_rectangle_side3_height / 2, middle_spacer_main_thickness / 2 + middle_spacer_cover_thickness / 2); + trans_middle_spacer_cover_rectangle_side3->RegisterYourself(); + + name_middle_spacer_main_cover += + " middle_spacer_cover_arc:trans_middle_spacer_cover_arc - middle_spacer_cover_sub_rectangle_top:trans_middle_spacer_cover_sub_rectangle_top" + " + middle_spacer_cover_rectangle_side1_left:trans_middle_spacer_cover_rectangle_side1_left + middle_spacer_cover_rectangle_side1_right:trans_middle_spacer_cover_rectangle_side1_right" + " + middle_spacer_cover_rectangle_side2:trans_middle_spacer_cover_rectangle_side2_left + middle_spacer_cover_rectangle_side2:trans_middle_spacer_cover_rectangle_side2_right" + " + middle_spacer_cover_rectangle_side3:trans_middle_spacer_cover_rectangle_side3"; + + Double_t middle_spacer_cover_block_thickness = 0.19; + Double_t middle_spacer_cover_block_height = 1.0; + Double_t middle_spacer_cover_block_width = 1.0; + Double_t middle_spacer_cover_block_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + middle_spacer_cover_block_thickness / 2.; + + TGeoBBox* middle_spacer_cover_block = new TGeoBBox("middle_spacer_cover_block", middle_spacer_cover_block_width / 2, middle_spacer_cover_block_height / 2, middle_spacer_cover_block_thickness / 2); + + TGeoCompositeShape* rotated_middle_spacer_cover_block[24]; + for (Int_t iB = 0; iB < 11; ++iB) { + + Double_t block_angle = (180. - block_angle_index[iB]) / 2. * TMath::Pi() / 180.; + + TGeoRotation* rotate_electric_board_sub_box_left = new TGeoRotation(Form("rotate_middle_spacer_cover_block_No%d", iB * 2), 180 - block_angle * 180. / TMath::Pi(), 0, 0); + TGeoRotation* rotate_electric_board_sub_box_right = new TGeoRotation(Form("rotate_middle_spacer_cover_block_No%d", iB * 2 + 1), block_angle * 180. / TMath::Pi(), 0, 0); + rotate_electric_board_sub_box_left->RegisterYourself(); + rotate_electric_board_sub_box_right->RegisterYourself(); + + Double_t cent_block_left[] = {block_radius * TMath::Cos(block_angle), -block_radius * TMath::Sin(block_angle), middle_spacer_cover_block_position_z}; + Double_t cent_block_right[] = {block_radius * TMath::Cos(TMath::Pi() - block_angle), -block_radius * TMath::Sin(TMath::Pi() - block_angle), middle_spacer_cover_block_position_z}; + + TGeoCombiTrans* combtrans_electric_board_sub_box_left = new TGeoCombiTrans(Form("combtrans_spacer_cover_block_No%d", 2 * iB), cent_block_left[0], cent_block_left[1], cent_block_left[2], rotate_electric_board_sub_box_left); + TGeoCombiTrans* combtrans_electric_board_sub_box_right = new TGeoCombiTrans(Form("combtrans_spacer_cover_block_No%d", 2 * iB + 1), cent_block_right[0], cent_block_right[1], cent_block_right[2], rotate_electric_board_sub_box_right); + combtrans_electric_board_sub_box_left->RegisterYourself(); + combtrans_electric_board_sub_box_right->RegisterYourself(); + + name_middle_spacer_main_cover += Form("+middle_spacer_cover_block:combtrans_spacer_cover_block_No%d", 2 * iB); + name_middle_spacer_main_cover += Form("+middle_spacer_cover_block:combtrans_spacer_cover_block_No%d", 2 * iB + 1); + } - Double_t middleBox_edge_sub_width2 = 1.1; - Double_t middleBox_edge_sub_height2 = 1.0; + TGeoTranslation* trans_spacer_cover_block_left = new TGeoTranslation("trans_spacer_cover_block_left", 22.259 - middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, middle_spacer_cover_block_position_z); + trans_spacer_cover_block_left->RegisterYourself(); + name_middle_spacer_main_cover += "+middle_spacer_cover_block:trans_spacer_cover_block_left"; - Double_t middleBox_edge_sub_height3 = 1.3; + TGeoTranslation* trans_spacer_cover_block_right = new TGeoTranslation("trans_spacer_cover_block_right", -22.247 + middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, middle_spacer_cover_block_position_z); + trans_spacer_cover_block_right->RegisterYourself(); + name_middle_spacer_main_cover += "+middle_spacer_cover_block:trans_spacer_cover_block_right"; - new TGeoBBox("middleBox_edge1", middleBox_edge_width1 / 2, middleBox_edge_height1 / 2, middle_board_thickness / 2); - new TGeoBBox("middleBox_edge_sub1", middleBox_edge_sub_width1 / 2, middleBox_edge_sub_height1 / 2, middle_board_thickness); - new TGeoBBox("middleBox_edge_sub2", middleBox_edge_sub_width2 / 2, middleBox_edge_sub_height2 / 2, middle_board_thickness); - - auto* tmiddleBox_edge_right1 = new TGeoTranslation("tmiddleBox_edge_right1", - middle_board_min_radius1 * TMath::Sin(middleBox_sub_angle2 / 2) + middleBox_edge_width1 / 2, - -(middle_board_min_radius1 * TMath::Cos(middleBox_sub_angle2 / 2) - middleBox_edge_height1 / 2), 0); - auto* tmiddleBox_edge_sub_right1 = new TGeoTranslation("tmiddleBox_edge_sub_right1", - middle_board_min_radius1 * TMath::Sin(middleBox_sub_angle2 / 2) + middleBox_edge_width1 - middleBox_edge_sub_width1 / 2, - -middle_board_min_radius1 * TMath::Cos(middleBox_sub_angle2 / 2) + middleBox_edge_height1 - middleBox_edge_sub_height2 - middleBox_edge_sub_height3 - middleBox_edge_sub_height1 / 2, - 0); - auto* tmiddleBox_edge_sub_right2 = new TGeoTranslation("tmiddleBox_edge_sub_right2", - middle_board_min_radius1 * TMath::Sin(middleBox_sub_angle2 / 2) + middleBox_edge_width1 - middleBox_edge_sub_width2 / 2, - -(middle_board_min_radius1 * TMath::Cos(middleBox_sub_angle2 / 2) - middleBox_edge_height1 / 2) + middleBox_edge_height1 / 2 - middleBox_edge_sub_height2 / 2, - 0); - - auto* tmiddleBox_edge_left1 = new TGeoTranslation("tmiddleBox_edge_left1", - -(middle_board_min_radius1 * TMath::Sin(middleBox_sub_angle2 / 2) + middleBox_edge_width1 / 2), - -(middle_board_min_radius1 * TMath::Cos(middleBox_sub_angle2 / 2) - middleBox_edge_height1 / 2), 0); - auto* tmiddleBox_edge_sub_left1 = new TGeoTranslation("tmiddleBox_edge_sub_left1", - -(middle_board_min_radius1 * TMath::Sin(middleBox_sub_angle2 / 2) + middleBox_edge_width1 - middleBox_edge_sub_width1 / 2), - -middle_board_min_radius1 * TMath::Cos(middleBox_sub_angle2 / 2) + middleBox_edge_height1 - middleBox_edge_sub_height2 - middleBox_edge_sub_height3 - middleBox_edge_sub_height1 / 2, - 0); - auto* tmiddleBox_edge_sub_left2 = new TGeoTranslation("tmiddleBox_edge_sub_left2", - -(middle_board_min_radius1 * TMath::Sin(middleBox_sub_angle2 / 2) + middleBox_edge_width1 - middleBox_edge_sub_width2 / 2), - -(middle_board_min_radius1 * TMath::Cos(middleBox_sub_angle2 / 2) - middleBox_edge_height1 / 2) + middleBox_edge_height1 / 2 - middleBox_edge_sub_height2 / 2, - 0); - - tmiddleBox_edge_right1->RegisterYourself(); - tmiddleBox_edge_sub_right1->RegisterYourself(); - tmiddleBox_edge_sub_right2->RegisterYourself(); - - tmiddleBox_edge_left1->RegisterYourself(); - tmiddleBox_edge_sub_left1->RegisterYourself(); - tmiddleBox_edge_sub_left2->RegisterYourself(); - - Double_t middleBox_side_lack_radius1 = 25.0; - Double_t middleBox_side_lack_height1 = 0.937 + 0.5; - Double_t middleBox_side_lack_angle1 = 24.75 + (2 * 0.5 * 360) / (2 * TMath::Pi() * middleBox_side_lack_radius1); - - Double_t middleBox_side_lack_position_angle_min_right1 = 270 - middleBox_side_lack_angle1 - 9.83 - TMath::ASin(middleBox_sub_width1 / 2 / middle_board_max_radius1) * 180 / TMath::Pi(); - Double_t middleBox_side_lack_position_angle_max_right1 = 270 - 9.83 - TMath::ASin(middleBox_sub_width1 / 2 / middle_board_max_radius1) * 180 / TMath::Pi(); - - new TGeoTubeSeg("middleBox_side_lack_right1", middleBox_side_lack_radius1, middle_board_max_radius1, middle_board_thickness, middleBox_side_lack_position_angle_min_right1, middleBox_side_lack_position_angle_max_right1); - - Double_t middleBox_side_lack_position_angle_min_left1 = 360 - middleBox_side_lack_angle1 - 9.83 - TMath::ASin(middleBox_sub_width1 / 2 / middle_board_max_radius1) * 180 / TMath::Pi(); - Double_t middleBox_side_lack_position_angle_max_left1 = 360 - 9.83 - TMath::ASin(middleBox_sub_width1 / 2 / middle_board_max_radius1) * 180 / TMath::Pi(); - - new TGeoTubeSeg("middleBox_side_lack_left1", middleBox_side_lack_radius1, middle_board_max_radius1, middle_board_thickness, middleBox_side_lack_position_angle_min_left1, middleBox_side_lack_position_angle_max_left1); + TGeoCompositeShape* middle_spacer_cover = new TGeoCompositeShape("middle_spacer_cover", name_middle_spacer_main_cover.c_str()); - new TGeoCompositeShape("middle_board_shape", - "middleTubeSeg1" - "-middleBox_sub1:tmiddleBox_sub1" - "-middleBox_sub2:tmiddleBox_sub2" - "+middleBox_edge1:tmiddleBox_edge_right1 - middleBox_edge_sub1:tmiddleBox_edge_sub_right1 - middleBox_edge_sub2:tmiddleBox_edge_sub_right2" - "+middleBox_edge1:tmiddleBox_edge_left1 - middleBox_edge_sub1:tmiddleBox_edge_sub_left1 - middleBox_edge_sub2:tmiddleBox_edge_sub_left2" - "-middleBox_side_lack_right1 - middleBox_side_lack_left1"); - - Double_t pipe_sub_radius1 = 0.2; - Double_t center_pipe_sub_torus_radius1 = 18.7 - pipe_sub_radius1; - Double_t center_pipe_sub_torus_angle1 = 114.84; - - new TGeoTorus("middleCenterWaterPipeTorus_sub1", center_pipe_sub_torus_radius1, pipe_sub_radius1, pipe_sub_radius1, 0, center_pipe_sub_torus_angle1); - auto* rmiddleCenterWaterPipeTorus_sub1 = new TGeoRotation("rmiddleCenterWaterPipeTorus_sub1", -(180 - 0.5 * (180 - center_pipe_sub_torus_angle1)), 0, 0); - rmiddleCenterWaterPipeTorus_sub1->RegisterYourself(); - - Double_t side_pipe_sub_torus_radius1 = 1.2 - pipe_sub_radius1; - Double_t side_pipe_sub_torus_angle1 = 57.42; - - new TGeoTorus("middleSideWaterPipeTorus_sub1", side_pipe_sub_torus_radius1, pipe_sub_radius1, pipe_sub_radius1, 0, side_pipe_sub_torus_angle1); - - auto* rmiddleSideWaterPipeTorus_sub_right1 = new TGeoRotation("rmiddleSideWaterPipeTorus_sub_right1", 90, 0, 0); - auto* rmiddleSideWaterPipeTorus_sub_left1 = new TGeoRotation("rmiddleSideWaterPipeTorus_sub_left1", 90 - side_pipe_sub_torus_angle1, 0, 0); - rmiddleSideWaterPipeTorus_sub_right1->RegisterYourself(); - rmiddleSideWaterPipeTorus_sub_left1->RegisterYourself(); - - new TGeoCompositeShape("rotated_middleSideWaterPipeTorus_sub_right1", - "dummy + middleSideWaterPipeTorus_sub1:rmiddleSideWaterPipeTorus_sub_right1"); - new TGeoCompositeShape("rotated_middleSideWaterPipeTorus_sub_left1", - "dummy + middleSideWaterPipeTorus_sub1:rmiddleSideWaterPipeTorus_sub_left1"); - - auto* tmiddleSideWaterPipeTorus_sub_right1 = new TGeoTranslation("tmiddleSideWaterPipeTorus_sub_right1", - center_pipe_sub_torus_radius1 * TMath::Sin(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180.) + side_pipe_sub_torus_radius1 * TMath::Sin(side_pipe_sub_torus_angle1 * TMath::Pi() / 180.), - -center_pipe_sub_torus_radius1 * TMath::Cos(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180.) - side_pipe_sub_torus_radius1 * TMath::Cos(side_pipe_sub_torus_angle1 * TMath::Pi() / 180.), 0); - tmiddleSideWaterPipeTorus_sub_right1->RegisterYourself(); - - auto* tmiddleSideWaterPipeTorus_sub_left1 = new TGeoTranslation("tmiddleSideWaterPipeTorus_sub_left1", - -(center_pipe_sub_torus_radius1 * TMath::Sin(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180.) + side_pipe_sub_torus_radius1 * TMath::Sin(side_pipe_sub_torus_angle1 * TMath::Pi() / 180.)), - -center_pipe_sub_torus_radius1 * TMath::Cos(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180.) - side_pipe_sub_torus_radius1 * TMath::Cos(side_pipe_sub_torus_angle1 * TMath::Pi() / 180.), 0); - tmiddleSideWaterPipeTorus_sub_left1->RegisterYourself(); - - Double_t side_pipe_sub_tube_length1 = 6.568; - - new TGeoTube("middleSideWaterPipeTube_sub1", 0, pipe_sub_radius1, side_pipe_sub_tube_length1 / 2); - - auto* rmiddleSideWaterPipeTube_sub1 = new TGeoRotation("rmiddleSideWaterPipeTube_sub1", 90, 90, 0); - rmiddleSideWaterPipeTube_sub1->RegisterYourself(); - - new TGeoCompositeShape("rotated_middleSideWaterPipeTube_sub1", "dummy+middleSideWaterPipeTube_sub1:rmiddleSideWaterPipeTube_sub1"); - - TGeoTranslation* tmiddleSideWaterPipeTube_sub_right1 = new TGeoTranslation("tmiddleSideWaterPipeTube_sub_right1", - center_pipe_sub_torus_radius1 * TMath::Sin(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_sub_torus_radius1 * TMath::Sin(side_pipe_sub_torus_angle1 * TMath::Pi() / 180) + side_pipe_sub_tube_length1 / 2, - -center_pipe_sub_torus_radius1 * TMath::Cos(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_sub_torus_radius1 * (1 - TMath::Sin((90 - side_pipe_sub_torus_angle1) * TMath::Pi() / 180)), - 0); - TGeoTranslation* tmiddleSideWaterPipeTube_sub_left1 = new TGeoTranslation("tmiddleSideWaterPipeTube_sub_left1", - -(center_pipe_sub_torus_radius1 * TMath::Sin(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_sub_torus_radius1 * TMath::Sin(side_pipe_sub_torus_angle1 * TMath::Pi() / 180) + side_pipe_sub_tube_length1 / 2), - -center_pipe_sub_torus_radius1 * TMath::Cos(center_pipe_sub_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_sub_torus_radius1 * (1 - TMath::Sin((90 - side_pipe_sub_torus_angle1) * TMath::Pi() / 180)), - 0); - tmiddleSideWaterPipeTube_sub_right1->RegisterYourself(); - tmiddleSideWaterPipeTube_sub_left1->RegisterYourself(); - - new TGeoCompositeShape("middleWaterPipeTorus_sub_shape", - "dummy + middleCenterWaterPipeTorus_sub1:rmiddleCenterWaterPipeTorus_sub1" - "+rotated_middleSideWaterPipeTorus_sub_right1:tmiddleSideWaterPipeTorus_sub_right1" - "+rotated_middleSideWaterPipeTube_sub1:tmiddleSideWaterPipeTube_sub_right1" - "+rotated_middleSideWaterPipeTorus_sub_left1:tmiddleSideWaterPipeTorus_sub_left1" - "+rotated_middleSideWaterPipeTube_sub1:tmiddleSideWaterPipeTube_sub_left1"); - - TGeoTranslation* tmiddleWaterPipeTorus_sub_shape1 = new TGeoTranslation("tmiddleWaterPipeTorus_sub_shape1", 0, 0, middle_board_thickness / 2); - TGeoTranslation* tmiddleWaterPipeTorus_sub_shape2 = new TGeoTranslation("tmiddleWaterPipeTorus_sub_shape2", 0, 0, -middle_board_thickness / 2); - tmiddleWaterPipeTorus_sub_shape1->RegisterYourself(); - tmiddleWaterPipeTorus_sub_shape2->RegisterYourself(); - - TGeoCompositeShape* middle_board_pipeSubtracted_shape = new TGeoCompositeShape("middle_board_pipeSubtracted_shape", - "middle_board_shape-middleWaterPipeTorus_sub_shape:tmiddleWaterPipeTorus_sub_shape1" - "-middleWaterPipeTorus_sub_shape:tmiddleWaterPipeTorus_sub_shape2"); + TGeoRotation* rotate_middle_spacer_cover_back = new TGeoRotation("rotate_middle_spacer_cover_back", 180, 180, 0); + rotate_middle_spacer_cover_back->RegisterYourself(); - TGeoVolume* middle_peek_board = new TGeoVolume("middle_peek_board", middle_board_pipeSubtracted_shape, kMedPeek); - - mHalfPSU->AddNode(middle_peek_board, 0, nullptr); + TGeoCompositeShape* middle_spacer_cover_bothside = new TGeoCompositeShape("middle_spacer_cover_bothside", "middle_spacer_cover + middle_spacer_cover:rotate_middle_spacer_cover_back"); - /////////////////////////////////////////////////////////////////////////////////////////////////////////// - //water pipe part - /////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Water pipe hole - Double_t pipe_min_radius1 = 0.075; - Double_t pipe_max_radius1 = 0.100; - Double_t center_pipe_torus_radius1 = 18.5; - Double_t center_pipe_torus_angle1 = 114.84; + Double_t water_pipe_inner_radius = 0.3 / 2.; + Double_t water_pipe_outer_radius = 0.4 / 2.; - new TGeoTorus("middleCenterWaterPipeTorus1", center_pipe_torus_radius1, pipe_min_radius1, pipe_max_radius1, 0, center_pipe_torus_angle1); - - auto* rmiddleCenterWaterPipeTorus1 = new TGeoRotation("rmiddleCenterWaterPipeTorus1", -(180 - 0.5 * (180 - center_pipe_torus_angle1)), 0, 0); - rmiddleCenterWaterPipeTorus1->RegisterYourself(); - - Double_t side_pipe_torus_radius1 = 1.0; - Double_t side_pipe_torus_angle1 = 57.42; - - new TGeoTorus("middleSideWaterPipeTorus1", side_pipe_torus_radius1, pipe_min_radius1, pipe_max_radius1, 0, side_pipe_torus_angle1); - - auto* rmiddleSideWaterPipeTorus_right1 = new TGeoRotation("rmiddleSideWaterPipeTorus_right1", 90, 0, 0); - auto* rmiddleSideWaterPipeTorus_left1 = new TGeoRotation("rmiddleSideWaterPipeTorus_left1", 90 - side_pipe_torus_angle1, 0, 0); - rmiddleSideWaterPipeTorus_right1->RegisterYourself(); - rmiddleSideWaterPipeTorus_left1->RegisterYourself(); - - new TGeoCompositeShape("rotated_middleSideWaterPipeTorus_right1", - "dummy + middleSideWaterPipeTorus1:rmiddleSideWaterPipeTorus_right1"); - new TGeoCompositeShape("rotated_middleSideWaterPipeTorus_left1", - "dummy + middleSideWaterPipeTorus1:rmiddleSideWaterPipeTorus_left1"); - - auto* tmiddleSideWaterPipeTorus_right1 = new TGeoTranslation("tmiddleSideWaterPipeTorus_right1", - center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180.), - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) - side_pipe_torus_radius1 * TMath::Cos(side_pipe_torus_angle1 * TMath::Pi() / 180.), 0); - auto* tmiddleSideWaterPipeTorus_left1 = new TGeoTranslation("tmiddleSideWaterPipeTorus_left1", - -(center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180.)), - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) - side_pipe_torus_radius1 * TMath::Cos(side_pipe_torus_angle1 * TMath::Pi() / 180.), 0); - tmiddleSideWaterPipeTorus_right1->RegisterYourself(); - tmiddleSideWaterPipeTorus_left1->RegisterYourself(); - - Double_t side_pipe_tube_length1 = 6.868; - - new TGeoTube("middleSideWaterPipeTube1", pipe_min_radius1, pipe_max_radius1, side_pipe_tube_length1 / 2); - auto* rmiddleSideWaterPipeTube1 = new TGeoRotation("rmiddleSideWaterPipeTube1", 90, 90, 0); - rmiddleSideWaterPipeTube1->RegisterYourself(); - - new TGeoCompositeShape("rotated_middleSideWaterPipeTube1", "dummy+middleSideWaterPipeTube1:rmiddleSideWaterPipeTube1"); - - TGeoTranslation* tmiddleSideWaterPipeTube_right1 = new TGeoTranslation("tmiddleSideWaterPipeTube_right1", - center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180) + side_pipe_tube_length1 / 2, - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * (1 - TMath::Sin((90 - side_pipe_torus_angle1) * TMath::Pi() / 180)), - 0); - TGeoTranslation* tmiddleSideWaterPipeTube_left1 = new TGeoTranslation("tmiddleSideWaterPipeTube_left1", - -(center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180) + side_pipe_tube_length1 / 2), - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * (1 - TMath::Sin((90 - side_pipe_torus_angle1) * TMath::Pi() / 180)), - 0); - tmiddleSideWaterPipeTube_right1->RegisterYourself(); - tmiddleSideWaterPipeTube_left1->RegisterYourself(); - - new TGeoCompositeShape("water_pipe_shape", - "middleCenterWaterPipeTorus1:rmiddleCenterWaterPipeTorus1" - " + rotated_middleSideWaterPipeTorus_right1:tmiddleSideWaterPipeTorus_right1 + rotated_middleSideWaterPipeTorus_left1:tmiddleSideWaterPipeTorus_left1" - " + rotated_middleSideWaterPipeTube1:tmiddleSideWaterPipeTube_right1 + rotated_middleSideWaterPipeTube1:tmiddleSideWaterPipeTube_left1"); - - TGeoTranslation* tmiddleWaterPipeTorus_shape1 = new TGeoTranslation("tmiddleWaterPipeTorus_shape1", 0, 0, middle_board_thickness / 2 - pipe_max_radius1); - TGeoTranslation* tmiddleWaterPipeTorus_shape2 = new TGeoTranslation("tmiddleWaterPipeTorus_shape2", 0, 0, -middle_board_thickness / 2 + pipe_max_radius1); - tmiddleWaterPipeTorus_shape1->RegisterYourself(); - tmiddleWaterPipeTorus_shape2->RegisterYourself(); - - TGeoCompositeShape* water_pipe_2side_shape = new TGeoCompositeShape("water_pipe_2side_shape", "water_pipe_shape:tmiddleWaterPipeTorus_shape1+water_pipe_shape:tmiddleWaterPipeTorus_shape2"); - - TGeoVolume* water_pipe = new TGeoVolume("water_pipe", water_pipe_2side_shape, kMedAlu); - water_pipe->SetLineColor(kGray); + Double_t water_pipe_main_angle = 126.19; - mHalfPSU->AddNode(water_pipe, 1, nullptr); + Double_t water_pipe_side_position_radius = (1.8 + 1.4) / 2; + Double_t water_pipe_side_angle = 63.1; - /////////////////////////////////////////////////////////////////////////////////////////////////////////// - //water in the pipe part - /////////////////////////////////////////////////////////////////////////////////////////////////////////// + Double_t water_pipe_straight_tube_side1_length = 2.865 / 2.; + Double_t water_pipe_straight_tube_side2_length = 8.950 / 2; - new TGeoTorus("middleCenterWaterTorus1", center_pipe_torus_radius1, 0, pipe_min_radius1, 0, center_pipe_torus_angle1); - auto* rmiddleCenterWaterTorus1 = new TGeoRotation("rmiddleCenterWaterTorus1", -(180 - 0.5 * (180 - center_pipe_torus_angle1)), 0, 0); - rmiddleCenterWaterTorus1->RegisterYourself(); + TGeoTorus* middle_spacer_sub_water_pipe_main_torus = new TGeoTorus("middle_spacer_sub_water_pipe_main_torus", water_pipe_main_position_radius, 0., water_pipe_outer_radius, 180 + (180 - water_pipe_main_angle) / 2., water_pipe_main_angle); - new TGeoTorus("middleSideWaterTorus1", side_pipe_torus_radius1, 0, pipe_min_radius1, 0, side_pipe_torus_angle1); + TGeoTorus* middle_spacer_sub_water_pipe_side_torus_left1 = new TGeoTorus("middle_spacer_sub_water_pipe_side_torus_left1", water_pipe_side_position_radius, 0., water_pipe_outer_radius, 90, water_pipe_side_angle); + TGeoTorus* middle_spacer_sub_water_pipe_side_torus_right1 = new TGeoTorus("middle_spacer_sub_water_pipe_side_torus_right1", water_pipe_side_position_radius, 0., water_pipe_outer_radius, 90 - water_pipe_side_angle, water_pipe_side_angle); - auto* rmiddleSideWaterTorus_right1 = new TGeoRotation("rmiddleSideWaterTorus_right1", 90, 0, 0); - auto* rmiddleSideWaterTorus_left1 = new TGeoRotation("rmiddleSideWaterTorus_left1", 90 - side_pipe_torus_angle1, 0, 0); - rmiddleSideWaterTorus_right1->RegisterYourself(); - rmiddleSideWaterTorus_left1->RegisterYourself(); + TGeoTranslation* trans_middle_spacer_sub_water_pipe_side_torus_left1 = new TGeoTranslation("trans_middle_spacer_sub_water_pipe_side_torus_left1", (water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.), -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.), 0); + TGeoTranslation* trans_middle_spacer_sub_water_pipe_side_torus_right1 = new TGeoTranslation("trans_middle_spacer_sub_water_pipe_side_torus_right1", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.), -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.), 0); + trans_middle_spacer_sub_water_pipe_side_torus_left1->RegisterYourself(); + trans_middle_spacer_sub_water_pipe_side_torus_right1->RegisterYourself(); - new TGeoCompositeShape("rotated_middleSideWaterTorus_right1", "dummy + middleSideWaterTorus1:rmiddleSideWaterTorus_right1"); - new TGeoCompositeShape("rotated_middleSideWaterTorus_left1", "dummy + middleSideWaterTorus1:rmiddleSideWaterTorus_left1"); + TGeoTubeSeg* middle_spacer_sub_water_pipe_straight_tube_side1 = new TGeoTubeSeg("middle_spacer_sub_water_pipe_straight_tube_side1", 0., water_pipe_outer_radius, water_pipe_straight_tube_side1_length, 0, 360); + TGeoRotation* rotate_middle_spacer_sub_water_pipe_straight_tube_side1 = new TGeoRotation("rotate_middle_spacer_sub_water_pipe_straight_tube_side1", 90, 90, 0); + rotate_middle_spacer_sub_water_pipe_straight_tube_side1->RegisterYourself(); - auto* tmiddleSideWaterTorus_right1 = new TGeoTranslation("tmiddleSideWaterTorus_right1", - center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180.), - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) - side_pipe_torus_radius1 * TMath::Cos(side_pipe_torus_angle1 * TMath::Pi() / 180.), 0); - auto* tmiddleSideWaterTorus_left1 = new TGeoTranslation("tmiddleSideWaterTorus_left1", - -(center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180.)), - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180.) - side_pipe_torus_radius1 * TMath::Cos(side_pipe_torus_angle1 * TMath::Pi() / 180.), 0); - tmiddleSideWaterTorus_right1->RegisterYourself(); - tmiddleSideWaterTorus_left1->RegisterYourself(); + TGeoCombiTrans* combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_left = new TGeoCombiTrans("combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_left", (water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius, 0, rotate_middle_spacer_sub_water_pipe_straight_tube_side1); + TGeoCombiTrans* combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_right = new TGeoCombiTrans("combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_right", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius, 0, rotate_middle_spacer_sub_water_pipe_straight_tube_side1); + combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_left->RegisterYourself(); + combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_right->RegisterYourself(); - new TGeoTube("middleSideWaterTube1", 0, pipe_min_radius1, side_pipe_tube_length1 / 2); + TGeoTorus* middle_spacer_sub_water_pipe_side_torus_left2 = new TGeoTorus("middle_spacer_sub_water_pipe_side_torus_left2", water_pipe_side_position_radius, 0., water_pipe_outer_radius, 0, 90); + TGeoTorus* middle_spacer_sub_water_pipe_side_torus_right2 = new TGeoTorus("middle_spacer_sub_water_pipe_side_torus_right2", water_pipe_side_position_radius, 0., water_pipe_outer_radius, 90, 90); - auto* rmiddleSideWaterTube1 = new TGeoRotation("rmiddleSideWaterTube1", 90, 90, 0); - rmiddleSideWaterTube1->RegisterYourself(); + TGeoTranslation* trans_middle_spacer_sub_water_pipe_side_torus_left2 = new TGeoTranslation("trans_middle_spacer_sub_water_pipe_side_torus_left2", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius, 0); + TGeoTranslation* trans_middle_spacer_sub_water_pipe_side_torus_right2 = new TGeoTranslation("trans_middle_spacer_sub_water_pipe_side_torus_right2", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius, 0); + trans_middle_spacer_sub_water_pipe_side_torus_left2->RegisterYourself(); + trans_middle_spacer_sub_water_pipe_side_torus_right2->RegisterYourself(); - new TGeoCompositeShape("rotated_middleSideWaterTube1", "dummy+middleSideWaterTube1:rmiddleSideWaterTube1"); + TGeoTubeSeg* middle_spacer_sub_water_pipe_straight_tube_side2 = new TGeoTubeSeg("middle_spacer_sub_water_pipe_straight_tube_side2", 0., water_pipe_outer_radius, water_pipe_straight_tube_side2_length, 0, 360); - TGeoTranslation* tmiddleSideWaterTube_right1 = new TGeoTranslation("tmiddleSideWaterTube_right1", - center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180) + side_pipe_tube_length1 / 2, - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * (1 - TMath::Sin((90 - side_pipe_torus_angle1) * TMath::Pi() / 180)), - 0); - TGeoTranslation* tmiddleSideWaterTube_left1 = new TGeoTranslation("tmiddleSideWaterTube_left1", - -(center_pipe_torus_radius1 * TMath::Sin(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * TMath::Sin(side_pipe_torus_angle1 * TMath::Pi() / 180) + side_pipe_tube_length1 / 2), - -center_pipe_torus_radius1 * TMath::Cos(center_pipe_torus_angle1 / 2 * TMath::Pi() / 180) + side_pipe_torus_radius1 * (1 - TMath::Sin((90 - side_pipe_torus_angle1) * TMath::Pi() / 180)), - 0); - tmiddleSideWaterTube_right1->RegisterYourself(); - tmiddleSideWaterTube_left1->RegisterYourself(); + TGeoRotation* rotate_middle_spacer_sub_water_pipe_straight_tube_side2 = new TGeoRotation("rotate_middle_spacer_sub_water_pipe_straight_tube_side2", 0, 90, 0); + rotate_middle_spacer_sub_water_pipe_straight_tube_side2->RegisterYourself(); - new TGeoCompositeShape("water_shape", - "middleCenterWaterTorus1:rmiddleCenterWaterTorus1" - " + rotated_middleSideWaterTorus_right1:tmiddleSideWaterTorus_right1 + rotated_middleSideWaterTorus_left1:tmiddleSideWaterTorus_left1" - " + rotated_middleSideWaterTube1:tmiddleSideWaterTube_right1 + rotated_middleSideWaterTube1:tmiddleSideWaterTube_left1"); + TGeoCombiTrans* combtrans_middle_spacer_sub_water_pipe_straight_tube_side_left2 = new TGeoCombiTrans("combtrans_middle_spacer_sub_water_pipe_straight_tube_side_left2", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2 + water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius - water_pipe_straight_tube_side2_length, 0, rotate_middle_spacer_sub_water_pipe_straight_tube_side2); - TGeoTranslation* tmiddleWaterTorus_shape1 = new TGeoTranslation("tmiddleWaterTorus_shape1", 0, 0, middle_board_thickness / 2 - pipe_max_radius1); - TGeoTranslation* tmiddleWaterTorus_shape2 = new TGeoTranslation("tmiddleWaterTorus_shape2", 0, 0, -middle_board_thickness / 2 + pipe_max_radius1); - tmiddleWaterTorus_shape1->RegisterYourself(); - tmiddleWaterTorus_shape2->RegisterYourself(); + TGeoCombiTrans* combtrans_middle_spacer_sub_water_pipe_straight_tube_side_right2 = new TGeoCombiTrans("combtrans_middle_spacer_sub_water_pipe_straight_tube_side_right2", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2 - water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius - water_pipe_straight_tube_side2_length, 0, rotate_middle_spacer_sub_water_pipe_straight_tube_side2); - TGeoCompositeShape* water_2side_shape = new TGeoCompositeShape("water_2side_shape", "water_shape:tmiddleWaterTorus_shape1+water_shape:tmiddleWaterTorus_shape2"); + combtrans_middle_spacer_sub_water_pipe_straight_tube_side_left2->RegisterYourself(); + combtrans_middle_spacer_sub_water_pipe_straight_tube_side_right2->RegisterYourself(); - TGeoVolume* water = new TGeoVolume("water", water_2side_shape, kMed_Water); - water->SetLineColor(kBlue); - mHalfPSU->AddNode(water, 1, nullptr); + TGeoCompositeShape* middle_spacer_shape = new TGeoCompositeShape("middle_spacer_shape", + "middle_spacer_main + middle_spacer_cover_bothside" + " - middle_spacer_sub_water_pipe_main_torus - middle_spacer_sub_water_pipe_side_torus_left1:trans_middle_spacer_sub_water_pipe_side_torus_left1 - middle_spacer_sub_water_pipe_side_torus_right1:trans_middle_spacer_sub_water_pipe_side_torus_right1" + " - middle_spacer_sub_water_pipe_straight_tube_side1:combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_left - middle_spacer_sub_water_pipe_straight_tube_side1:combtrans_rotated_middle_spacer_sub_water_pipe_straight_tube_side1_right" + " - middle_spacer_sub_water_pipe_side_torus_left2:trans_middle_spacer_sub_water_pipe_side_torus_left2 - middle_spacer_sub_water_pipe_side_torus_right2:trans_middle_spacer_sub_water_pipe_side_torus_right2" + " - middle_spacer_sub_water_pipe_straight_tube_side2:combtrans_middle_spacer_sub_water_pipe_straight_tube_side_left2 - middle_spacer_sub_water_pipe_straight_tube_side2:combtrans_middle_spacer_sub_water_pipe_straight_tube_side_right2"); + + TGeoVolume* middle_spacer = new TGeoVolume("middle_spacer", middle_spacer_shape, kMedAlu); + middle_spacer->SetLineColor(kTeal - 4); + mHalfPSU->AddNode(middle_spacer, 0, nullptr); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Electoric board + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Double_t electric_board_thickness = 0.171; + Double_t electric_board_max_radius1 = 26.706; + Double_t electric_board_min_radius1 = 17.0; + Double_t electric_board_sub_rectangle_middle_height = 5 + 4.347; + Double_t electric_board_sub_rectangle_middle_width = electric_board_max_radius1 * 2; + Double_t electric_board_sub_rectangle_bottom_height = 10.00; //laugh + Double_t electric_board_sub_rectangle_bottom_width = 20.80; + Double_t electric_board_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness / 2; + + TGeoTubeSeg* electric_board_main = new TGeoTubeSeg("electric_board_main", electric_board_min_radius1, electric_board_max_radius1, electric_board_thickness / 2, 180, 0); + TGeoTranslation* trans_electric_board_main = new TGeoTranslation("trans_electric_board_main", 0, 0, electric_board_position_z); + trans_electric_board_main->RegisterYourself(); + + TGeoBBox* electric_board_sub_rectangle_middle = new TGeoBBox("electric_board_sub_rectangle_middle", electric_board_sub_rectangle_middle_width / 2., electric_board_sub_rectangle_middle_height / 2., electric_board_thickness / 2. + delta_thickness); + TGeoBBox* electric_board_sub_rectangle_bottom = new TGeoBBox("electric_board_sub_rectangle_bottom", electric_board_sub_rectangle_bottom_width / 2., electric_board_sub_rectangle_bottom_height / 2., electric_board_thickness / 2. + delta_thickness); + + TGeoTranslation* trans_electric_board_sub_rectangle_middle = new TGeoTranslation("trans_electric_board_sub_rectangle_middle", 0, -electric_board_sub_rectangle_middle_height / 2., electric_board_position_z); + TGeoTranslation* trans_electric_board_sub_rectangle_bottom = new TGeoTranslation("trans_electric_board_sub_rectangle_bottom", 0, -(24.6 + electric_board_sub_rectangle_bottom_height / 2.), electric_board_position_z); + trans_electric_board_sub_rectangle_middle->RegisterYourself(); + trans_electric_board_sub_rectangle_bottom->RegisterYourself(); + + Double_t electric_board_add_rectangle_side_height = 4.347; + Double_t electric_board_add_rectangle_side_width = 8.800; + + TGeoBBox* electric_board_add_rectangle_side = new TGeoBBox("electric_board_add_rectangle_side", electric_board_add_rectangle_side_width / 2., electric_board_add_rectangle_side_height / 2., electric_board_thickness / 2.); + TGeoTranslation* trans_electric_board_add_rectangle_side_left = new TGeoTranslation("trans_electric_board_add_rectangle_side_left", 28.4 / 2. + electric_board_add_rectangle_side_width / 2., -5.0 - electric_board_add_rectangle_side_height / 2., electric_board_position_z); + TGeoTranslation* trans_electric_board_add_rectangle_side_right = new TGeoTranslation("trans_electric_board_add_rectangle_side_right", -(28.4 / 2. + electric_board_add_rectangle_side_width / 2.), -5.0 - electric_board_add_rectangle_side_height / 2., electric_board_position_z); + trans_electric_board_add_rectangle_side_left->RegisterYourself(); + trans_electric_board_add_rectangle_side_right->RegisterYourself(); + + Double_t electric_board_sub_rectangle_side_width = 10.; //raugh + Double_t electric_board_sub_rectangle_side_height = 8.576; + + TGeoBBox* electric_board_sub_rectangle_side = new TGeoBBox("electric_board_sub_rectangle_side", electric_board_sub_rectangle_side_width / 2., electric_board_sub_rectangle_side_height / 2., electric_board_thickness / 2. + delta_thickness); + TGeoTranslation* trans_electric_board_sub_rectangle_side_left = new TGeoTranslation("trans_electric_board_sub_rectangle_side_left", 28.4 / 2 + 8.8 + electric_board_sub_rectangle_side_width / 2., -5.0 - electric_board_sub_rectangle_side_height / 2., electric_board_position_z); + TGeoTranslation* trans_electric_board_sub_rectangle_side_right = new TGeoTranslation("trans_electric_board_sub_rectangle_side_right", -(28.4 / 2 + 8.8 + electric_board_sub_rectangle_side_width / 2.), -5.0 - electric_board_sub_rectangle_side_height / 2., electric_board_position_z); + trans_electric_board_sub_rectangle_side_left->RegisterYourself(); + trans_electric_board_sub_rectangle_side_right->RegisterYourself(); + + Double_t electric_board_sub_box_height = 1.1; + Double_t electric_board_sub_box_width = 1.1; + + TGeoBBox* electric_board_sub_box = new TGeoBBox("electric_board_sub_box", electric_board_sub_box_width / 2, electric_board_sub_box_height / 2, electric_board_thickness / 2 + delta_thickness); + + TGeoCompositeShape* rotated_electric_board_sub_box[24]; + + std::string name_electric_board_shape = + "electric_board_main:trans_electric_board_main - electric_board_sub_rectangle_middle:trans_electric_board_sub_rectangle_middle - electric_board_sub_rectangle_bottom:trans_electric_board_sub_rectangle_bottom" + " + electric_board_add_rectangle_side:trans_electric_board_add_rectangle_side_left + electric_board_add_rectangle_side:trans_electric_board_add_rectangle_side_right" + " - electric_board_sub_rectangle_side:trans_electric_board_sub_rectangle_side_left - electric_board_sub_rectangle_side:trans_electric_board_sub_rectangle_side_right"; + + for (Int_t iB = 0; iB < 11; ++iB) { + + Double_t block_angle = (180. - block_angle_index[iB]) / 2. * TMath::Pi() / 180.; + + TGeoRotation* rotate_electric_board_sub_box_left = new TGeoRotation(Form("rotate_electric_board_sub_box_No%d", iB * 2), 180 - block_angle * 180. / TMath::Pi(), 0, 0); + TGeoRotation* rotate_electric_board_sub_box_right = new TGeoRotation(Form("rotate_electric_board_sub_box_No%d", iB * 2 + 1), block_angle * 180. / TMath::Pi(), 0, 0); + rotate_electric_board_sub_box_left->RegisterYourself(); + rotate_electric_board_sub_box_right->RegisterYourself(); + + Double_t cent_block_left[] = {block_radius * TMath::Cos(block_angle), -block_radius * TMath::Sin(block_angle), electric_board_position_z}; + Double_t cent_block_right[] = {block_radius * TMath::Cos(TMath::Pi() - block_angle), -block_radius * TMath::Sin(TMath::Pi() - block_angle), electric_board_position_z}; + + TGeoCombiTrans* combtrans_electric_board_sub_box_left = new TGeoCombiTrans(Form("combtrans_electric_board_sub_box_No%d", 2 * iB), cent_block_left[0], cent_block_left[1], cent_block_left[2], rotate_electric_board_sub_box_left); + TGeoCombiTrans* combtrans_electric_board_sub_box_right = new TGeoCombiTrans(Form("combtrans_electric_board_sub_box_No%d", 2 * iB + 1), cent_block_right[0], cent_block_right[1], cent_block_right[2], rotate_electric_board_sub_box_right); + combtrans_electric_board_sub_box_left->RegisterYourself(); + combtrans_electric_board_sub_box_right->RegisterYourself(); + + name_electric_board_shape += Form("-electric_board_sub_box:combtrans_electric_board_sub_box_No%d", 2 * iB); + name_electric_board_shape += Form("-electric_board_sub_box:combtrans_electric_board_sub_box_No%d", 2 * iB + 1); + } + + TGeoTranslation* trans_electric_board_sub_box_left = new TGeoTranslation("trans_electric_board_sub_box_left", 22.259 - electric_board_sub_box_width / 2, -8.305 + electric_board_sub_box_height / 2, electric_board_position_z); + trans_electric_board_sub_box_left->RegisterYourself(); + name_electric_board_shape += "-electric_board_sub_box:trans_electric_board_sub_box_left"; + + TGeoTranslation* trans_electric_board_sub_box_right = new TGeoTranslation("trans_electric_board_sub_box_right", -22.247 + electric_board_sub_box_width / 2, -8.305 + electric_board_sub_box_height / 2, electric_board_position_z); + trans_electric_board_sub_box_right->RegisterYourself(); + name_electric_board_shape += "-electric_board_sub_box:trans_electric_board_sub_box_right"; + + TGeoCompositeShape* electric_board_shape = new TGeoCompositeShape("electric_board_shape", name_electric_board_shape.c_str()); - /////////////////////////////////////////////////////////////////////////////////////////////////////////// - //PSU surface - /////////////////////////////////////////////////////////////////////////////////////////////////////////// - - Double_t surface_board_thickness = 0.16; - Double_t surface_board_max_radius1 = 26.432; - Double_t surface_board_min_radius1 = 17.0; - Double_t surfaceBox_sub_angle2 = 113.29 * TMath::Pi() / 180.; - Double_t surfaceBox_sub_width1 = 20.8; + TGeoRotation* trans_electric_board_front = new TGeoRotation("trans_electric_board_front", 0, 0, 0); + TGeoRotation* trans_electric_board_back = new TGeoRotation("trans_electric_board_back", 180, 180, 0); + + TGeoVolume* electric_board = new TGeoVolume("electric_board", electric_board_shape, kMedPeek); + electric_board->SetLineColor(kGreen + 2); + mHalfPSU->AddNode(electric_board, 0, trans_electric_board_front); + mHalfPSU->AddNode(electric_board, 0, trans_electric_board_back); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Water pipe + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Double_t surfaceBox_sub_height1 = surface_board_max_radius1 * (1 - sqrt(1 - pow(surfaceBox_sub_width1 / 2. / surface_board_max_radius1, 2))); + TGeoTorus* water_pipe_main_torus = new TGeoTorus("water_pipe_main_torus", water_pipe_main_position_radius, water_pipe_inner_radius, water_pipe_outer_radius, 180 + (180 - water_pipe_main_angle) / 2., water_pipe_main_angle); - Double_t surfaceBox_sub_width2 = 2 * surface_board_max_radius1; - Double_t surfaceBox_sub_height2 = 2 * surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2); - - new TGeoTubeSeg("surfaceTubeSeg1", surface_board_min_radius1, surface_board_max_radius1, surface_board_thickness / 2, 180, 0); - new TGeoBBox("surfaceBox_sub1", surfaceBox_sub_width1 / 2, surfaceBox_sub_height1 / 2, surface_board_thickness); - new TGeoBBox("surfaceBox_sub2", surfaceBox_sub_width2 / 2, surfaceBox_sub_height2 / 2, surface_board_thickness); + TGeoTorus* water_pipe_side_torus_left1 = new TGeoTorus("water_pipe_side_torus_left1", water_pipe_side_position_radius, water_pipe_inner_radius, water_pipe_outer_radius, 90, water_pipe_side_angle); + TGeoTorus* water_pipe_side_torus_right1 = new TGeoTorus("water_pipe_side_torus_right1", water_pipe_side_position_radius, water_pipe_inner_radius, water_pipe_outer_radius, 90 - water_pipe_side_angle, water_pipe_side_angle); - auto* tsurfaceBox_sub1 = new TGeoTranslation("tsurfaceBox_sub1", 0, -(surface_board_max_radius1 - surfaceBox_sub_height1 / 2), 0); - auto* tsurfaceBox_sub2 = new TGeoTranslation("tsurfaceBox_sub2", 0., 0., 0.); - tsurfaceBox_sub1->RegisterYourself(); - tsurfaceBox_sub2->RegisterYourself(); + TGeoTranslation* trans_water_pipe_side_torus_left1 = new TGeoTranslation("trans_water_pipe_side_torus_left1", (water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.), -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.), 0); + TGeoTranslation* trans_water_pipe_side_torus_right1 = new TGeoTranslation("trans_water_pipe_side_torus_right1", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.), -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.), 0); + trans_water_pipe_side_torus_left1->RegisterYourself(); + trans_water_pipe_side_torus_right1->RegisterYourself(); - Double_t surfaceBox_edge_width1 = 8.8; - Double_t surfaceBox_edge_height1 = 4.347; + TGeoTubeSeg* water_pipe_straight_tube_side1 = new TGeoTubeSeg("water_pipe_straight_tube_side1", water_pipe_inner_radius, water_pipe_outer_radius, water_pipe_straight_tube_side1_length, 0, 360); - Double_t surfaceBox_edge_sub_width1 = 5.; - Double_t surfaceBox_edge_sub_height1 = 8.025; + TGeoRotation* rotate_water_pipe_straight_tube_side1 = new TGeoRotation("rotate_water_pipe_straight_tube_side1", 90, 90, 0); + rotate_water_pipe_straight_tube_side1->RegisterYourself(); - new TGeoBBox("surfaceBox_edge1", surfaceBox_edge_width1 / 2, surfaceBox_edge_height1 / 2, surface_board_thickness / 2); - new TGeoBBox("surfaceBox_sub_edge1", surfaceBox_edge_sub_width1 / 2, surfaceBox_edge_sub_height1 / 2, surface_board_thickness); + TGeoCombiTrans* combtrans_rotated_water_pipe_straight_tube_side1_left = new TGeoCombiTrans("combtrans_rotated_water_pipe_straight_tube_side1_left", (water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius, 0, rotate_water_pipe_straight_tube_side1); + TGeoCombiTrans* combtrans_rotated_water_pipe_straight_tube_side1_right = new TGeoCombiTrans("combtrans_rotated_water_pipe_straight_tube_side1_right", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius, 0, rotate_water_pipe_straight_tube_side1); + combtrans_rotated_water_pipe_straight_tube_side1_left->RegisterYourself(); + combtrans_rotated_water_pipe_straight_tube_side1_right->RegisterYourself(); - auto* tsurfaceBox_edge_right1 = new TGeoTranslation("tsurfaceBox_edge_right1", - surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 / 2, - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 / 2, 0); - auto* tsurfaceBox_edge_sub_right1 = new TGeoTranslation("tsurfaceBox_edge_sub_right1", - surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 + surfaceBox_edge_sub_width1 / 2, - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 - surfaceBox_edge_sub_height1 / 2, 0); - auto* tsurfaceBox_edge_left1 = new TGeoTranslation("tsurfaceBox_edge_left1", - -(surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 / 2), - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 / 2, 0); - auto* tsurfaceBox_edge_sub_left1 = new TGeoTranslation("tsurfaceBox_edge_sub_left1", - -(surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 + surfaceBox_edge_sub_width1 / 2), - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 - surfaceBox_edge_sub_height1 / 2, 0); + TGeoTorus* water_pipe_side_torus_left2 = new TGeoTorus("water_pipe_side_torus_left2", water_pipe_side_position_radius, water_pipe_inner_radius, water_pipe_outer_radius, 0, 90); + TGeoTorus* water_pipe_side_torus_right2 = new TGeoTorus("water_pipe_side_torus_right2", water_pipe_side_position_radius, water_pipe_inner_radius, water_pipe_outer_radius, 90, 90); + TGeoTranslation* trans_water_pipe_side_torus_left2 = new TGeoTranslation("trans_water_pipe_side_torus_left2", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius, 0); + TGeoTranslation* trans_water_pipe_side_torus_right2 = new TGeoTranslation("trans_water_pipe_side_torus_right2", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius, 0); + trans_water_pipe_side_torus_left2->RegisterYourself(); + trans_water_pipe_side_torus_right2->RegisterYourself(); - tsurfaceBox_edge_right1->RegisterYourself(); - tsurfaceBox_edge_sub_right1->RegisterYourself(); + TGeoTubeSeg* water_pipe_straight_tube_side2 = new TGeoTubeSeg("water_pipe_straight_tube_side2", water_pipe_inner_radius, water_pipe_outer_radius, water_pipe_straight_tube_side2_length, 0, 360); + TGeoRotation* rotate_water_pipe_straight_tube_side2 = new TGeoRotation("rotate_water_pipe_straight_tube_side2", 0, 90, 0); - tsurfaceBox_edge_left1->RegisterYourself(); - tsurfaceBox_edge_sub_left1->RegisterYourself(); + rotate_water_pipe_straight_tube_side2->RegisterYourself(); - Double_t surfaceBox_center_sub_min_radius1 = 18.0; - Double_t surfaceBox_center_sub_max_radius1 = 19.0; - Double_t surfaceBox_center_sub_max_angle1 = 130; + TGeoCombiTrans* combtrans_water_pipe_straight_tube_side_left2 = new TGeoCombiTrans("combtrans_water_pipe_straight_tube_side_left2", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2 + water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius - water_pipe_straight_tube_side2_length, 0, rotate_water_pipe_straight_tube_side2); - new TGeoTubeSeg("surfaceCenterTubeSeg_sub1", surfaceBox_center_sub_min_radius1, surfaceBox_center_sub_max_radius1, middle_board_thickness, - 180 + (180 - surfaceBox_center_sub_max_angle1) / 2, 180 + (180 - surfaceBox_center_sub_max_angle1) / 2 + surfaceBox_center_sub_max_angle1); + TGeoCombiTrans* combtrans_water_pipe_straight_tube_side_right2 = new TGeoCombiTrans("combtrans_water_pipe_straight_tube_side_right2", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2 - water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius - water_pipe_straight_tube_side2_length, 0, rotate_water_pipe_straight_tube_side2); - Double_t surfaceBox_edge_sub_width2 = 1.; - Double_t surfaceBox_edge_sub_height2 = 1.; - Double_t surfaceBox_edge_sub_refposi_x = 0.76; - Double_t surfaceBox_edge_sub_refposi_y = 4.004; + combtrans_water_pipe_straight_tube_side_left2->RegisterYourself(); + combtrans_water_pipe_straight_tube_side_right2->RegisterYourself(); - new TGeoBBox("surfaceBox_square_sub2", surfaceBox_edge_sub_width2 / 2, surfaceBox_edge_sub_height2 / 2, surface_board_thickness); - auto* tsurfaceBox_square_sub_right2 = new TGeoTranslation("tsurfaceBox_square_sub_right2", - surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 - surfaceBox_edge_sub_refposi_x - surfaceBox_edge_sub_width2 / 2, - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 - surfaceBox_edge_sub_refposi_y - surfaceBox_edge_sub_height2 / 2, 0); - auto* tsurfaceBox_square_sub_left2 = new TGeoTranslation("tsurfaceBox_square_sub_left2", - -(surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 - surfaceBox_edge_sub_refposi_x - surfaceBox_edge_sub_width2 / 2), - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 - surfaceBox_edge_sub_refposi_y - surfaceBox_edge_sub_height2 / 2, 0); - tsurfaceBox_square_sub_right2->RegisterYourself(); - tsurfaceBox_square_sub_left2->RegisterYourself(); + TGeoCompositeShape* water_pipe_shape = new TGeoCompositeShape("water_pipe_shape", + "water_pipe_main_torus + water_pipe_side_torus_left1:trans_water_pipe_side_torus_left1 + water_pipe_side_torus_right1:trans_water_pipe_side_torus_right1" + " + water_pipe_straight_tube_side1:combtrans_rotated_water_pipe_straight_tube_side1_left + water_pipe_straight_tube_side1:combtrans_rotated_water_pipe_straight_tube_side1_right" + " + water_pipe_side_torus_left2:trans_water_pipe_side_torus_left2 + water_pipe_side_torus_right2:trans_water_pipe_side_torus_right2" + " + water_pipe_straight_tube_side2:combtrans_water_pipe_straight_tube_side_left2 + water_pipe_straight_tube_side2:combtrans_water_pipe_straight_tube_side_right2"); - new TGeoCompositeShape("surface_board_shape", - "surfaceTubeSeg1 - surfaceBox_sub1:tsurfaceBox_sub1 - surfaceBox_sub2:tsurfaceBox_sub2" - "+surfaceBox_edge1:tsurfaceBox_edge_right1 - surfaceBox_sub_edge1:tsurfaceBox_edge_sub_right1" - "+surfaceBox_edge1:tsurfaceBox_edge_left1 - surfaceBox_sub_edge1:tsurfaceBox_edge_sub_left1" - "-surfaceCenterTubeSeg_sub1 - surfaceBox_square_sub2:tsurfaceBox_square_sub_right2" - "-surfaceCenterTubeSeg_sub1 - surfaceBox_square_sub2:tsurfaceBox_square_sub_left2"); + TGeoVolume* water_pipe = new TGeoVolume("water_pipe", water_pipe_shape, kMedAlu); + water_pipe->SetLineColor(kGray); + mHalfPSU->AddNode(water_pipe, 1, nullptr); - auto* tsurface_board_shape1 = new TGeoTranslation("tsurface_board_shape1", 0, 0, middle_board_thickness / 2 + surface_board_thickness / 2); - auto* tsurface_board_shape2 = new TGeoTranslation("tsurface_board_shape2", 0, 0, -(middle_board_thickness / 2 + surface_board_thickness / 2)); - tsurface_board_shape1->RegisterYourself(); - tsurface_board_shape2->RegisterYourself(); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Water + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TGeoCompositeShape* surface_board_2side_shape = new TGeoCompositeShape("surface_board_2side_shape", "surface_board_shape:tsurface_board_shape1 + surface_board_shape:tsurface_board_shape2"); + TGeoTorus* water_main_torus = new TGeoTorus("water_main_torus", water_pipe_main_position_radius, 0, water_pipe_inner_radius, 180 + (180 - water_pipe_main_angle) / 2., water_pipe_main_angle); - TGeoVolume* surface_board = new TGeoVolume("surface_board", surface_board_2side_shape, kMedPeek); - surface_board->SetLineColor(kGreen + 3); + TGeoTorus* water_side_torus_left1 = new TGeoTorus("water_side_torus_left1", water_pipe_side_position_radius, 0, water_pipe_inner_radius, 90, water_pipe_side_angle); + TGeoTorus* water_side_torus_right1 = new TGeoTorus("water_side_torus_right1", water_pipe_side_position_radius, 0, water_pipe_inner_radius, 90 - water_pipe_side_angle, water_pipe_side_angle); - mHalfPSU->AddNode(surface_board, 1, nullptr); + TGeoTranslation* trans_water_side_torus_left1 = new TGeoTranslation("trans_water_side_torus_left1", (water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.), -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.), 0); + TGeoTranslation* trans_water_side_torus_right1 = new TGeoTranslation("trans_water_side_torus_right1", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.), -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.), 0); + trans_water_side_torus_left1->RegisterYourself(); + trans_water_side_torus_right1->RegisterYourself(); - /////////////////////////////////////////////////////////////////////////////////////////////////////////// - //PSU DCDC - /////////////////////////////////////////////////////////////////////////////////////////////////////////// + TGeoTubeSeg* water_straight_tube_side1 = new TGeoTubeSeg("water_straight_tube_side1", 0, water_pipe_inner_radius, water_pipe_straight_tube_side1_length, 0, 360); + TGeoRotation* rotate_water_straight_tube_side1 = new TGeoRotation("rotate_water_straight_tube_side1", 90, 90, 0); + rotate_water_straight_tube_side1->RegisterYourself(); - Int_t nDCDC = 22; + TGeoCombiTrans* combtrans_rotated_water_straight_tube_side1_left = new TGeoCombiTrans("combtrans_rotated_water_straight_tube_side1_left", (water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius, 0, rotate_water_straight_tube_side1); + TGeoCombiTrans* combtrans_rotated_water_straight_tube_side1_right = new TGeoCombiTrans("combtrans_rotated_water_straight_tube_side1_right", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius, 0, rotate_water_straight_tube_side1); + combtrans_rotated_water_straight_tube_side1_left->RegisterYourself(); + combtrans_rotated_water_straight_tube_side1_right->RegisterYourself(); - Double_t DCDC_main_width1 = 1.4; - Double_t DCDC_main_height1 = 1.85; - Double_t DCDC_main_thickness1 = 0.8; + TGeoTorus* water_side_torus_left2 = new TGeoTorus("water_side_torus_left2", water_pipe_side_position_radius, 0, water_pipe_inner_radius, 0, 90); + TGeoTorus* water_side_torus_right2 = new TGeoTorus("water_side_torus_right2", water_pipe_side_position_radius, 0, water_pipe_inner_radius, 90, 90); + TGeoTranslation* trans_water_side_torus_left2 = new TGeoTranslation("trans_water_side_torus_left2", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius, 0); + TGeoTranslation* trans_water_side_torus_right2 = new TGeoTranslation("trans_water_side_torus_right2", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius, 0); + trans_water_side_torus_left2->RegisterYourself(); + trans_water_side_torus_right2->RegisterYourself(); - new TGeoBBox("DCDC_main_shape1", DCDC_main_width1 / 2, DCDC_main_height1 / 2, DCDC_main_thickness1 / 2); - - Double_t DCDC_width2 = 1.694; - Double_t DCDC_height2 = 4.348; - Double_t DCDC_thickness2 = 0.04; + TGeoTubeSeg* water_straight_tube_side2 = new TGeoTubeSeg("water_straight_tube_side2", 0, water_pipe_inner_radius, water_pipe_straight_tube_side2_length, 0, 360); + TGeoRotation* rotate_water_straight_tube_side2 = new TGeoRotation("rotate_water_straight_tube_side2", 0, 90, 0); + rotate_water_straight_tube_side2->RegisterYourself(); - new TGeoBBox("DCDC_shape2", DCDC_width2 / 2, DCDC_height2 / 2, DCDC_thickness2 / 2); + TGeoCombiTrans* combtrans_water_straight_tube_side_left2 = new TGeoCombiTrans("combtrans_water_straight_tube_side_left2", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2 + water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius - water_pipe_straight_tube_side2_length, 0, rotate_water_straight_tube_side2); - Double_t DCDC_sub_edge_thickness1 = 0.02; - Double_t DCDC_sub_width1 = DCDC_main_width1 - DCDC_sub_edge_thickness1 * 2; - Double_t DCDC_sub_height1 = DCDC_main_height1 - DCDC_sub_edge_thickness1 * 2; - Double_t DCDC_sub_thickness1 = DCDC_main_thickness1; - - new TGeoBBox("DCDC_sub_shape1", DCDC_sub_width1 / 2, DCDC_sub_height1 / 2, DCDC_sub_thickness1 / 2); - - TGeoTranslation* tDCDC_sub_shape1 = new TGeoTranslation("tDCDC_sub_shape1", 0, 0, DCDC_sub_edge_thickness1); - tDCDC_sub_shape1->RegisterYourself(); - - new TGeoCompositeShape("DCDC_shape1", "DCDC_main_shape1 - DCDC_sub_shape1:tDCDC_sub_shape1"); + TGeoCombiTrans* combtrans_water_straight_tube_side_right2 = new TGeoCombiTrans("combtrans_water_straight_tube_side_right2", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2 - water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_side_position_radius - water_pipe_side_position_radius - water_pipe_straight_tube_side2_length, 0, rotate_water_straight_tube_side2); - Double_t full_angle = 126; - Double_t one_angle = 126. / (nDCDC - 1); - Double_t start_DCDC_angle = 180 + (180 - full_angle) / 2; + combtrans_water_straight_tube_side_left2->RegisterYourself(); + combtrans_water_straight_tube_side_right2->RegisterYourself(); - Double_t position_radius = 18.5; - - TGeoRotation* rDCDC_shape1[22]; - TGeoTranslation* tDCDC_shape1[22]; - TGeoCompositeShape* rotated_DCDC_shape1[22]; - - TGeoRotation* rDCDC_shape2[22]; - TGeoTranslation* tDCDC_shape2[22]; - TGeoCompositeShape* rotated_DCDC_shape2[22]; - - TString string_all_DCDC_shape1 = ""; - TString string_all_DCDC_shape2 = ""; + TGeoCompositeShape* water_shape = new TGeoCompositeShape("water_shape", + "water_main_torus + water_side_torus_left1:trans_water_side_torus_left1 + water_side_torus_right1:trans_water_side_torus_right1" + " + water_straight_tube_side1:combtrans_rotated_water_straight_tube_side1_left + water_straight_tube_side1:combtrans_rotated_water_straight_tube_side1_right" + " + water_side_torus_left2:trans_water_side_torus_left2 + water_side_torus_right2:trans_water_side_torus_right2" + " + water_straight_tube_side2:combtrans_water_straight_tube_side_left2 + water_straight_tube_side2:combtrans_water_straight_tube_side_right2"); - for (Int_t iDCDC = 0; iDCDC < nDCDC; ++iDCDC) { - rDCDC_shape1[iDCDC] = new TGeoRotation(Form("rDCDC_shape1_angle%d", iDCDC + 1), full_angle / 2 - one_angle * iDCDC, 0, 0); - rDCDC_shape2[iDCDC] = new TGeoRotation(Form("rDCDC_shape2_angle%d", iDCDC + 1), full_angle / 2 - one_angle * iDCDC, 0, 0); - rDCDC_shape1[iDCDC]->RegisterYourself(); - rDCDC_shape2[iDCDC]->RegisterYourself(); + TGeoVolume* water = new TGeoVolume("water", water_shape, kMed_Water); + water->SetLineColor(kBlue); + mHalfPSU->AddNode(water, 1, nullptr); - rotated_DCDC_shape1[iDCDC] = new TGeoCompositeShape(Form("rotated_DCDC_shape1_angle%d", iDCDC + 1), Form("dummy+DCDC_shape1:rDCDC_shape1_angle%d", iDCDC + 1)); - rotated_DCDC_shape2[iDCDC] = new TGeoCompositeShape(Form("rotated_DCDC_shape2_angle%d", iDCDC + 1), Form("dummy+DCDC_shape2:rDCDC_shape2_angle%d", iDCDC + 1)); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //DCDC cobverter + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - tDCDC_shape1[iDCDC] = new TGeoTranslation(Form("tDCDC_shape1_pos%d", iDCDC + 1), - -position_radius * TMath::Cos((start_DCDC_angle + one_angle * iDCDC) * TMath::Pi() / 180.), - position_radius * TMath::Sin((start_DCDC_angle + one_angle * iDCDC) * TMath::Pi() / 180.), 0); - tDCDC_shape2[iDCDC] = new TGeoTranslation(Form("tDCDC_shape2_pos%d", iDCDC + 1), - -(position_radius + DCDC_height2 / 5) * TMath::Cos((start_DCDC_angle + one_angle * iDCDC) * TMath::Pi() / 180.), - (position_radius + DCDC_height2 / 5) * TMath::Sin((start_DCDC_angle + one_angle * iDCDC) * TMath::Pi() / 180.), 0); - tDCDC_shape1[iDCDC]->RegisterYourself(); - tDCDC_shape2[iDCDC]->RegisterYourself(); + //Sheet1 - if (iDCDC + 1 == nDCDC) { - string_all_DCDC_shape1 += Form("rotated_DCDC_shape1_angle%d:tDCDC_shape1_pos%d", iDCDC + 1, iDCDC + 1); - string_all_DCDC_shape2 += Form("rotated_DCDC_shape2_angle%d:tDCDC_shape2_pos%d", iDCDC + 1, iDCDC + 1); + Double_t DCDC_sheet1_thickness = 0.040; + Double_t DCDC_sheet1_height = 1.694; + Double_t DCDC_sheet1_width = 4.348; + Double_t DCDC_sheet1_radius = (block_radius + DCDC_sheet1_width / 2. - 0.673 - 1.85 + 1.85 / 2.); + + Double_t DCDC_sheet1_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + middle_spacer_cover_block_thickness + DCDC_sheet1_thickness / 2; + //Double_t DCDC_sheet1_position_z = electric_board_position_z + electric_board_thickness/2. + DCDC_sheet1_thickness/2.; + + TGeoBBox* DCDC_sheet1_box = new TGeoBBox("DCDC_sheet1_box", DCDC_sheet1_width / 2., DCDC_sheet1_height / 2., DCDC_sheet1_thickness / 2.); + + TGeoCompositeShape* rotated_DCDC_sheet1_box[24]; + + std::string name_DCDC_sheet1_box = ""; + + for (Int_t iB = 0; iB < 11; ++iB) { + + Double_t block_angle = (180. - block_angle_index[iB]) / 2. * TMath::Pi() / 180.; + + TGeoRotation* rotate_DCDC_sheet1_box_left = new TGeoRotation(Form("rotate_DCDC_sheet1_box_No%d", iB * 2), 180 - block_angle * 180. / TMath::Pi(), 0, 0); + TGeoRotation* rotate_DCDC_sheet1_box_right = new TGeoRotation(Form("rotate_DCDC_sheet1_box_No%d", iB * 2 + 1), block_angle * 180. / TMath::Pi(), 0, 0); + rotate_DCDC_sheet1_box_left->RegisterYourself(); + rotate_DCDC_sheet1_box_right->RegisterYourself(); + + Double_t cent_block_left[] = {DCDC_sheet1_radius * TMath::Cos(block_angle), -DCDC_sheet1_radius * TMath::Sin(block_angle), DCDC_sheet1_position_z}; + Double_t cent_block_right[] = {DCDC_sheet1_radius * TMath::Cos(TMath::Pi() - block_angle), -DCDC_sheet1_radius * TMath::Sin(TMath::Pi() - block_angle), DCDC_sheet1_position_z}; + + TGeoCombiTrans* combtrans_DCDC_sheet1_box_left = new TGeoCombiTrans(Form("combtrans_DCDC_sheet1_box_No%d", 2 * iB), cent_block_left[0], cent_block_left[1], cent_block_left[2], rotate_DCDC_sheet1_box_left); + TGeoCombiTrans* combtrans_DCDC_sheet1_box_right = new TGeoCombiTrans(Form("combtrans_DCDC_sheet1_box_No%d", 2 * iB + 1), cent_block_right[0], cent_block_right[1], cent_block_right[2], rotate_DCDC_sheet1_box_right); + combtrans_DCDC_sheet1_box_left->RegisterYourself(); + combtrans_DCDC_sheet1_box_right->RegisterYourself(); + + if (iB == 0) { + name_DCDC_sheet1_box += Form("DCDC_sheet1_box:combtrans_DCDC_sheet1_box_No%d", 2 * iB); } else { - string_all_DCDC_shape1 += Form("rotated_DCDC_shape1_angle%d:tDCDC_shape1_pos%d+", iDCDC + 1, iDCDC + 1); - string_all_DCDC_shape2 += Form("rotated_DCDC_shape2_angle%d:tDCDC_shape2_pos%d+", iDCDC + 1, iDCDC + 1); + name_DCDC_sheet1_box += Form("+DCDC_sheet1_box:combtrans_DCDC_sheet1_box_No%d", 2 * iB); } + + name_DCDC_sheet1_box += Form("+DCDC_sheet1_box:combtrans_DCDC_sheet1_box_No%d", 2 * iB + 1); } - string_all_DCDC_shape1 += "+ DCDC_shape1:tsurfaceBox_square_sub_right2 + DCDC_shape1:tsurfaceBox_square_sub_left2"; + TGeoBBox* DCDC_sheet1_box_side = new TGeoBBox("DCDC_sheet1_box_side", DCDC_sheet1_height / 2., DCDC_sheet1_width / 2., DCDC_sheet1_thickness / 2.); - auto* tDCDC_shape_side_right2 = new TGeoTranslation("tDCDC_shape_side_right2", - surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 - surfaceBox_edge_sub_refposi_x - surfaceBox_edge_sub_width2 / 2, - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 - surfaceBox_edge_sub_refposi_y - surfaceBox_edge_sub_height2 / 2 + DCDC_height2 / 5., - 0); + TGeoTranslation* trans_DCDC_sheet1_box_left = new TGeoTranslation("trans_DCDC_sheet1_box_left", 22.259 - middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2 - 0.576, DCDC_sheet1_position_z); + trans_DCDC_sheet1_box_left->RegisterYourself(); + name_DCDC_sheet1_box += "+DCDC_sheet1_box_side:trans_DCDC_sheet1_box_left"; - auto* tDCDC_shape_side_left2 = new TGeoTranslation("tDCDC_shape_side_left2", - -(surface_board_min_radius1 * TMath::Sin(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_width1 - surfaceBox_edge_sub_refposi_x - surfaceBox_edge_sub_width2 / 2), - -surface_board_min_radius1 * TMath::Cos(surfaceBox_sub_angle2 / 2) + surfaceBox_edge_height1 - surfaceBox_edge_sub_refposi_y - surfaceBox_edge_sub_height2 / 2 + DCDC_height2 / 5., - 0); - tDCDC_shape_side_right2->RegisterYourself(); - tDCDC_shape_side_left2->RegisterYourself(); + TGeoTranslation* trans_DCDC_sheet1_box_right = new TGeoTranslation("trans_DCDC_sheet1_box_right", -22.247 + middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2 - 0.576, DCDC_sheet1_position_z); + trans_DCDC_sheet1_box_right->RegisterYourself(); + name_DCDC_sheet1_box += "+DCDC_sheet1_box_side:trans_DCDC_sheet1_box_right"; - string_all_DCDC_shape2 += "+ DCDC_shape2:tDCDC_shape_side_right2 + DCDC_shape2:tDCDC_shape_side_left2"; + TGeoCompositeShape* DCDC_sheet1_shape = new TGeoCompositeShape("DCDC_sheet1_shape", name_DCDC_sheet1_box.c_str()); - new TGeoCompositeShape("all_DCDC_shape1", string_all_DCDC_shape1); + TGeoVolume* DCDC_sheet1 = new TGeoVolume("DCDC_sheet1", DCDC_sheet1_shape, kMedPeek); + DCDC_sheet1->SetLineColor(kGreen); - TGeoRotation* rall_DCDC_shape1 = new TGeoRotation("rall_DCDC_shape1", 0, 180, 180); - rall_DCDC_shape1->RegisterYourself(); + TGeoRotation* trans_DCDC_sheet1_front = new TGeoRotation("trans_DCDC_sheet1_front", 0, 0, 0); + TGeoRotation* trans_DCDC_sheet1_back = new TGeoRotation("trans_DCDC_sheet1_back", 180, 180, 0); - new TGeoCompositeShape("all_DCDC_shape_opposit", "dummy+all_DCDC_shape1:rall_DCDC_shape1"); + mHalfPSU->AddNode(DCDC_sheet1, 0, trans_DCDC_sheet1_front); + mHalfPSU->AddNode(DCDC_sheet1, 0, trans_DCDC_sheet1_back); - new TGeoCompositeShape("all_DCDC_base_shape", string_all_DCDC_shape2); + //Cover box - auto* tall_DCDC_shape_shape1 = new TGeoTranslation("tall_DCDC_shape_shape1", 0, 0, middle_board_thickness / 2 + surface_board_thickness + DCDC_thickness2 + DCDC_main_thickness1 / 2); - auto* tall_DCDC_shape_shape2 = new TGeoTranslation("tall_DCDC_shape_shape2", 0, 0, -(middle_board_thickness / 2 + surface_board_thickness + DCDC_thickness2 + DCDC_main_thickness1 / 2)); - tall_DCDC_shape_shape1->RegisterYourself(); - tall_DCDC_shape_shape2->RegisterYourself(); + Double_t DCDC_cover_thickness = 0.800; + Double_t DCDC_cover_outer_height = 1.400; + Double_t DCDC_cover_outer_width = 1.85; + Double_t DCDC_cover_depth = 0.05; + Double_t DCDC_cover_inner_width = DCDC_cover_outer_width - 2 * DCDC_cover_depth; + Double_t DCDC_cover_inner_height = DCDC_cover_outer_height - 2 * DCDC_cover_depth; - auto* tall_DCDC_base_shape_shape1 = new TGeoTranslation("tall_DCDC_base_shape_shape1", 0, 0, middle_board_thickness / 2 + surface_board_thickness + DCDC_thickness2 / 2); - auto* tall_DCDC_base_shape_shape2 = new TGeoTranslation("tall_DCDC_base_shape_shape2", 0, 0, -(middle_board_thickness / 2 + surface_board_thickness + DCDC_thickness2 / 2)); - tall_DCDC_base_shape_shape1->RegisterYourself(); - tall_DCDC_base_shape_shape2->RegisterYourself(); + Double_t DCDC_cover_position_z = DCDC_sheet1_position_z + DCDC_sheet1_thickness / 2. + DCDC_cover_thickness / 2.; - TGeoCompositeShape* two_side_all_DCDC_shape = new TGeoCompositeShape("two_side_all_DCDC_shape", "all_DCDC_shape_opposit:tall_DCDC_shape_shape1 + all_DCDC_shape1:tall_DCDC_shape_shape2"); + TGeoBBox* DCDC_cover_outer_box = new TGeoBBox("DCDC_cover_outer_box", DCDC_cover_outer_width / 2., DCDC_cover_outer_height / 2., DCDC_cover_thickness / 2.); + TGeoBBox* DCDC_cover_innner_box = new TGeoBBox("DCDC_cover_inner_box", DCDC_cover_inner_width / 2., DCDC_cover_inner_height / 2., DCDC_cover_thickness / 2.); - TGeoCompositeShape* two_side_all_DCDC_base_shape = new TGeoCompositeShape("two_side_all_DCDC_base_shape", - "all_DCDC_base_shape:tall_DCDC_base_shape_shape1 + all_DCDC_base_shape:tall_DCDC_base_shape_shape2"); + TGeoCompositeShape* rotated_DCDC_cover_outer_box[23]; + TGeoCompositeShape* rotated_DCDC_cover_inner_box[23]; - TGeoVolume* DCDC1 = new TGeoVolume("DCDC1", two_side_all_DCDC_shape, kMedAlu); - DCDC1->SetLineColor(kGray); + std::string name_DCDC_cover_box = ""; - TGeoVolume* DCDC2 = new TGeoVolume("DCDC2", two_side_all_DCDC_base_shape, kMedAlu); - DCDC2->SetLineColor(kSpring); + for (Int_t iB = 0; iB < 11; ++iB) { - mHalfPSU->AddNode(DCDC1, 1, nullptr); - mHalfPSU->AddNode(DCDC2, 1, nullptr); + Double_t block_angle = (180. - block_angle_index[iB]) / 2. * TMath::Pi() / 180.; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // DC-DC coil part - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TGeoRotation* rotate_DCDC_cover_box_left = new TGeoRotation(Form("rotate_DCDC_cover_box_No%d", iB * 2), 180 - block_angle * 180. / TMath::Pi(), 0, 0); + TGeoRotation* rotate_DCDC_cover_box_right = new TGeoRotation(Form("rotate_DCDC_cover_box_No%d", iB * 2 + 1), block_angle * 180. / TMath::Pi(), 0, 0); + rotate_DCDC_cover_box_left->RegisterYourself(); + rotate_DCDC_cover_box_right->RegisterYourself(); - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Very detaild coil shape part - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Double_t cent_block_left[] = {block_radius * TMath::Cos(block_angle), -block_radius * TMath::Sin(block_angle), DCDC_cover_position_z}; + Double_t cent_block_right[] = {block_radius * TMath::Cos(TMath::Pi() - block_angle), -block_radius * TMath::Sin(TMath::Pi() - block_angle), DCDC_cover_position_z}; + + TGeoCombiTrans* combtrans_DCDC_cover_outer_box_left = new TGeoCombiTrans(Form("combtrans_DCDC_cover_outer_box_No%d", 2 * iB), cent_block_left[0], cent_block_left[1], cent_block_left[2], rotate_DCDC_cover_box_left); + TGeoCombiTrans* combtrans_DCDC_cover_outer_box_right = new TGeoCombiTrans(Form("combtrans_DCDC_cover_outer_box_No%d", 2 * iB + 1), cent_block_right[0], cent_block_right[1], cent_block_right[2], rotate_DCDC_cover_box_right); + combtrans_DCDC_cover_outer_box_left->RegisterYourself(); + combtrans_DCDC_cover_outer_box_right->RegisterYourself(); + + TGeoCombiTrans* combtrans_DCDC_cover_inner_box_left = new TGeoCombiTrans(Form("combtrans_DCDC_cover_inner_box_No%d", 2 * iB), cent_block_left[0], cent_block_left[1], cent_block_left[2] - 2 * DCDC_cover_depth, rotate_DCDC_cover_box_left); + TGeoCombiTrans* combtrans_DCDC_cover_inner_box_right = new TGeoCombiTrans(Form("combtrans_DCDC_cover_inner_box_No%d", 2 * iB + 1), cent_block_right[0], cent_block_right[1], cent_block_right[2] - 2 * DCDC_cover_depth, rotate_DCDC_cover_box_right); + combtrans_DCDC_cover_inner_box_left->RegisterYourself(); + combtrans_DCDC_cover_inner_box_right->RegisterYourself(); - Double_t DCDC_coil_radius1 = 0.1; - Double_t DCDC_coil_min_radius1 = 0; - Double_t DCDC_coil_max_radius1 = DCDC_coil_radius1 - 0.075; - Double_t DCDC_coil_straight_gap = DCDC_coil_radius1 / 20.; - Double_t DCDC_coil_torus_part_radius = 2. / 5. * DCDC_width2 / 2.; - - new TGeoTorus("DCDC_coil_main_shape", DCDC_coil_radius1, 0, DCDC_coil_max_radius1, 0, 360); - - TGeoTranslation* tDCDC_coil_straight[9]; - tDCDC_coil_straight[0] = new TGeoTranslation("tDCDC_coil_straight_No0", 0, 0, 0); - tDCDC_coil_straight[1] = new TGeoTranslation("tDCDC_coil_straight_No1", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * 1); - tDCDC_coil_straight[2] = new TGeoTranslation("tDCDC_coil_straight_No2", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * 2); - tDCDC_coil_straight[3] = new TGeoTranslation("tDCDC_coil_straight_No3", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * 3); - tDCDC_coil_straight[4] = new TGeoTranslation("tDCDC_coil_straight_No4", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * 4); - tDCDC_coil_straight[5] = new TGeoTranslation("tDCDC_coil_straight_No5", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * -1); - tDCDC_coil_straight[6] = new TGeoTranslation("tDCDC_coil_straight_No6", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * -2); - tDCDC_coil_straight[7] = new TGeoTranslation("tDCDC_coil_straight_No7", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * -3); - tDCDC_coil_straight[8] = new TGeoTranslation("tDCDC_coil_straight_No8", 0, 0, (DCDC_coil_max_radius1 * 2 + DCDC_coil_straight_gap) * -4); - - for (Int_t i = 0; i < 9; ++i) - tDCDC_coil_straight[i]->RegisterYourself(); - - new TGeoCompositeShape("DCDC_coil_straight_shape1", - "DCDC_coil_main_shape:tDCDC_coil_straight_No0" - "+ DCDC_coil_main_shape:tDCDC_coil_straight_No1 + DCDC_coil_main_shape:tDCDC_coil_straight_No2" - "+ DCDC_coil_main_shape:tDCDC_coil_straight_No3 + DCDC_coil_main_shape:tDCDC_coil_straight_No4" - "+ DCDC_coil_main_shape:tDCDC_coil_straight_No5 + DCDC_coil_main_shape:tDCDC_coil_straight_No6" - "+ DCDC_coil_main_shape:tDCDC_coil_straight_No7 + DCDC_coil_main_shape:tDCDC_coil_straight_No8"); - TGeoRotation* rDCDC_coil_torus[7]; - Double_t DCDC_coil_torus_part_angle[] = {15, 30, 60, 90, 120, 150, 165}; - - TGeoCompositeShape* rotated_DCDC_coil_main_shape[7]; - for (Int_t i = 0; i < 7; ++i) { - rDCDC_coil_torus[i] = new TGeoRotation(Form("rDCDC_coil_torus_No%d", i), -90, DCDC_coil_torus_part_angle[i], 0); - rDCDC_coil_torus[i]->RegisterYourself(); - rotated_DCDC_coil_main_shape[i] = new TGeoCompositeShape(Form("rotated_DCDC_coil_main_shape_No%d", i), Form("dummy + DCDC_coil_main_shape:rDCDC_coil_torus_No%d", i)); + if (iB == 0) + name_DCDC_cover_box += Form("DCDC_cover_outer_box:combtrans_DCDC_cover_outer_box_No%d - DCDC_cover_inner_box:combtrans_DCDC_cover_inner_box_No%d", 2 * iB, 2 * iB); + else + name_DCDC_cover_box += Form("+DCDC_cover_outer_box:combtrans_DCDC_cover_outer_box_No%d - DCDC_cover_inner_box:combtrans_DCDC_cover_inner_box_No%d", 2 * iB, 2 * iB); + name_DCDC_cover_box += Form("+DCDC_cover_outer_box:combtrans_DCDC_cover_outer_box_No%d - DCDC_cover_inner_box:combtrans_DCDC_cover_inner_box_No%d", 2 * iB + 1, 2 * iB + 1); } - TGeoTranslation* trotated_DCDC_coil_main_shape[7]; + TGeoBBox* DCDC_cover_outer_box_side = new TGeoBBox("DCDC_cover_outer_box_side", DCDC_cover_outer_height / 2., DCDC_cover_outer_width / 2., DCDC_cover_thickness / 2.); + TGeoBBox* DCDC_cover_innner_box_side = new TGeoBBox("DCDC_cover_inner_box_side", DCDC_cover_inner_height / 2., DCDC_cover_inner_width / 2., DCDC_cover_thickness / 2.); - for (Int_t i = 0; i < 7; ++i) { - trotated_DCDC_coil_main_shape[i] = new TGeoTranslation(Form("trotated_DCDC_coil_main_shape_No%d", i), - DCDC_coil_torus_part_radius * TMath::Cos(DCDC_coil_torus_part_angle[i] * TMath::Pi() / 180.), - 0, - DCDC_coil_torus_part_radius * TMath::Sin(DCDC_coil_torus_part_angle[i] * TMath::Pi() / 180.)); - trotated_DCDC_coil_main_shape[i]->RegisterYourself(); + TGeoTranslation* trans_DCDC_cover_outer_box_left = new TGeoTranslation("trans_DCDC_cover_outer_box_left", 22.259 - middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, DCDC_cover_position_z); + TGeoTranslation* trans_DCDC_cover_inner_box_left = new TGeoTranslation("trans_DCDC_cover_inner_box_left", 22.259 - middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, DCDC_cover_position_z - 2 * DCDC_cover_depth); + trans_DCDC_cover_outer_box_left->RegisterYourself(); + trans_DCDC_cover_inner_box_left->RegisterYourself(); + name_DCDC_cover_box += "+DCDC_cover_outer_box_side:trans_DCDC_cover_outer_box_left - DCDC_cover_inner_box_side:trans_DCDC_cover_inner_box_left"; + + TGeoTranslation* trans_DCDC_cover_outer_box_right = new TGeoTranslation("trans_DCDC_cover_outer_box_right", -22.247 + middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, DCDC_cover_position_z); + TGeoTranslation* trans_DCDC_cover_inner_box_right = new TGeoTranslation("trans_DCDC_cover_inner_box_right", -22.247 + middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, DCDC_cover_position_z - 2 * DCDC_cover_depth); + trans_DCDC_cover_outer_box_right->RegisterYourself(); + trans_DCDC_cover_inner_box_right->RegisterYourself(); + name_DCDC_cover_box += "+DCDC_cover_outer_box_side:trans_DCDC_cover_outer_box_right - DCDC_cover_inner_box_side:trans_DCDC_cover_inner_box_right"; + + TGeoCompositeShape* DCDC_cover_shape = new TGeoCompositeShape("DCDC_cover_shape", name_DCDC_cover_box.c_str()); + TGeoVolume* DCDC_cover = new TGeoVolume("DCDC_cover", DCDC_cover_shape, kMedAlu); + DCDC_cover->SetLineColor(kGray); + + TGeoRotation* trans_DCDC_cover_front = new TGeoRotation("trans_DCDC_cover_front", 0, 0, 0); + TGeoRotation* trans_DCDC_cover_back = new TGeoRotation("trans_DCDC_cover_back", 180, 180, 0); + + mHalfPSU->AddNode(DCDC_cover, 0, trans_DCDC_cover_front); + mHalfPSU->AddNode(DCDC_cover, 0, trans_DCDC_cover_back); + + //DCDC converter connector + + Double_t DCDC_connector_thickness = 0.225; + Double_t DCDC_connector_height = 1.44; + Double_t DCDC_connector_width = 0.305; + Double_t DCDC_connector_radius = (block_radius + DCDC_sheet1_width / 2. - 0.673 - 1.85 + 1.85 / 2. + DCDC_sheet1_width / 2 - 0.55 - 0.305 + 0.305 / 2.); + Double_t DCDC_connector_position_z = DCDC_sheet1_position_z + DCDC_sheet1_thickness / 2. + DCDC_connector_thickness / 2; + + TGeoBBox* DCDC_connector_box = new TGeoBBox("DCDC_connector_box", DCDC_connector_width / 2., DCDC_connector_height / 2., DCDC_connector_thickness / 2.); + + TGeoCompositeShape* rotated_DCDC_connector_box[23]; + + std::string name_DCDC_connector_box = ""; + + for (Int_t iB = 0; iB < 11; ++iB) { + + Double_t block_angle = (180. - block_angle_index[iB]) / 2. * TMath::Pi() / 180.; + + TGeoRotation* rotate_DCDC_connector_box_left = new TGeoRotation(Form("rotate_DCDC_connector_box_No%d", iB * 2), 180 - block_angle * 180. / TMath::Pi(), 0, 0); + TGeoRotation* rotate_DCDC_connector_box_right = new TGeoRotation(Form("rotate_DCDC_connector_box_No%d", iB * 2 + 1), block_angle * 180. / TMath::Pi(), 0, 0); + rotate_DCDC_connector_box_left->RegisterYourself(); + rotate_DCDC_connector_box_right->RegisterYourself(); + Double_t cent_block_left[] = {DCDC_connector_radius * TMath::Cos(block_angle), -DCDC_connector_radius * TMath::Sin(block_angle), DCDC_connector_position_z}; + Double_t cent_block_right[] = {DCDC_connector_radius * TMath::Cos(TMath::Pi() - block_angle), -DCDC_connector_radius * TMath::Sin(TMath::Pi() - block_angle), DCDC_connector_position_z}; + + TGeoCombiTrans* combtrans_DCDC_connector_box_left = new TGeoCombiTrans(Form("combtrans_DCDC_connector_box_No%d", 2 * iB), cent_block_left[0], cent_block_left[1], cent_block_left[2], rotate_DCDC_connector_box_left); + TGeoCombiTrans* combtrans_DCDC_connector_box_right = new TGeoCombiTrans(Form("combtrans_DCDC_connector_box_No%d", 2 * iB + 1), cent_block_right[0], cent_block_right[1], cent_block_right[2], rotate_DCDC_connector_box_right); + combtrans_DCDC_connector_box_left->RegisterYourself(); + combtrans_DCDC_connector_box_right->RegisterYourself(); + + if (iB == 0) + name_DCDC_connector_box += Form("DCDC_connector_box:combtrans_DCDC_connector_box_No%d", 2 * iB); + else + name_DCDC_connector_box += Form("+DCDC_connector_box:combtrans_DCDC_connector_box_No%d", 2 * iB); + name_DCDC_connector_box += Form("+DCDC_connector_box:combtrans_DCDC_connector_box_No%d", 2 * iB + 1); } - new TGeoCompositeShape("DCDC_coil_torus_shape1", - "rotated_DCDC_coil_main_shape_No0:trotated_DCDC_coil_main_shape_No0" - "+ rotated_DCDC_coil_main_shape_No1:trotated_DCDC_coil_main_shape_No1" - "+ rotated_DCDC_coil_main_shape_No2:trotated_DCDC_coil_main_shape_No2" - "+ rotated_DCDC_coil_main_shape_No3:trotated_DCDC_coil_main_shape_No3" - "+ rotated_DCDC_coil_main_shape_No4:trotated_DCDC_coil_main_shape_No4" - "+ rotated_DCDC_coil_main_shape_No5:trotated_DCDC_coil_main_shape_No5" - "+ rotated_DCDC_coil_main_shape_No6:trotated_DCDC_coil_main_shape_No6"); - - TGeoTranslation* tDCDC_coil_straight_shape1[2]; - tDCDC_coil_straight_shape1[0] = new TGeoTranslation("tDCDC_coil_straight_shape1_right", DCDC_coil_torus_part_radius, 0, 0); - tDCDC_coil_straight_shape1[1] = new TGeoTranslation("tDCDC_coil_straight_shape1_left", -DCDC_coil_torus_part_radius, 0, 0); - tDCDC_coil_straight_shape1[0]->RegisterYourself(); - tDCDC_coil_straight_shape1[1]->RegisterYourself(); - - TGeoRotation* rDCDC_coil_torus_shape1[2]; - rDCDC_coil_torus_shape1[0] = new TGeoRotation("rDCDC_coil_torus_shape1_top", 0, 0, 0); - rDCDC_coil_torus_shape1[1] = new TGeoRotation("rDCDC_coil_torus_shape1_bottom", 0, 180, 0); - rDCDC_coil_torus_shape1[0]->RegisterYourself(); - rDCDC_coil_torus_shape1[1]->RegisterYourself(); - - TGeoCompositeShape* rotated_DCDC_coil_torus_shape1[2]; - rotated_DCDC_coil_torus_shape1[0] = new TGeoCompositeShape("rotated_DCDC_coil_torus_shape1_top", "dummy+DCDC_coil_torus_shape1:rDCDC_coil_torus_shape1_top"); - rotated_DCDC_coil_torus_shape1[1] = new TGeoCompositeShape("rotated_DCDC_coil_torus_shape1_bottom", "dummy+DCDC_coil_torus_shape1:rDCDC_coil_torus_shape1_bottom"); - - TGeoTranslation* trotated_DCDC_coil_torus_shape1[2]; - trotated_DCDC_coil_torus_shape1[0] = new TGeoTranslation("trotated_DCDC_coil_torus_shape1_top", 0, 0, (DCDC_coil_max_radius1 + DCDC_coil_straight_gap / 4.) * 9); - trotated_DCDC_coil_torus_shape1[1] = new TGeoTranslation("trotated_DCDC_coil_torus_shape1_bottom", 0, 0, -(DCDC_coil_max_radius1 + DCDC_coil_straight_gap / 4.) * 9); - trotated_DCDC_coil_torus_shape1[0]->RegisterYourself(); - trotated_DCDC_coil_torus_shape1[1]->RegisterYourself(); - /* - TGeoCompositeShape *DCDC_coil_shape1 = new TGeoCompositeShape("DCDC_coil_shape1", - "DCDC_coil_straight_shape1:tDCDC_coil_straight_shape1_right + DCDC_coil_straight_shape1:tDCDC_coil_straight_shape1_left" - "+rotated_DCDC_coil_torus_shape1_top:trotated_DCDC_coil_torus_shape1_top" - "+rotated_DCDC_coil_torus_shape1_bottom:trotated_DCDC_coil_torus_shape1_bottom"); - */ + TGeoBBox* DCDC_connector_box_side = new TGeoBBox("DCDC_connector_box_side", DCDC_connector_height / 2., DCDC_connector_width / 2., DCDC_connector_thickness / 2.); + + TGeoTranslation* trans_DCDC_connector_box_left = new TGeoTranslation("trans_DCDC_connector_box_left", 22.259 - middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2 - 2.019, DCDC_connector_position_z); + trans_DCDC_connector_box_left->RegisterYourself(); + name_DCDC_connector_box += "+DCDC_connector_box_side:trans_DCDC_connector_box_left"; + + TGeoTranslation* trans_DCDC_connector_box_right = new TGeoTranslation("trans_DCDC_connector_box_right", -22.247 + middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2 - 2.019, DCDC_connector_position_z); + trans_DCDC_connector_box_right->RegisterYourself(); + name_DCDC_connector_box += "+DCDC_connector_box_side:trans_DCDC_connector_box_right"; + + TGeoCompositeShape* DCDC_connector_shape = new TGeoCompositeShape("DCDC_connector_shape", name_DCDC_connector_box.c_str()); + + TGeoVolume* DCDC_connector = new TGeoVolume("DCDC_connector", DCDC_connector_shape, kMedPeek); + DCDC_connector->SetLineColor(kGray + 2); + + TGeoRotation* trans_DCDC_connector_front = new TGeoRotation("trans_DCDC_connector_front", 0, 0, 0); + TGeoRotation* trans_DCDC_connector_back = new TGeoRotation("trans_DCDC_connector_back", 180, 180, 0); + + mHalfPSU->AddNode(DCDC_connector, 0, trans_DCDC_connector_front); + mHalfPSU->AddNode(DCDC_connector, 0, trans_DCDC_connector_back); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Mezzanine + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + //prop + + Double_t mezzanine_prop_main_length = 1.615; + Double_t mezzanine_prop_main_radius = 0.476 / 2.; + Double_t mezzanine_prop_small_length = 0.16; + Double_t mezzanine_prop_small_radius = 0.3 / 2.; + Double_t mezzanine_prop_lid_radius = 0.57 / 2.; + + Double_t mezzanine_prop_main_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length / 2; + Double_t mezzanine_prop_small_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length + mezzanine_prop_small_length / 2.; + Double_t mezzanine_prop_lid_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length + mezzanine_prop_small_length; + + TGeoTubeSeg* mezzanine_prop_main_tube = new TGeoTubeSeg("mezzanine_prop_main_tube", 0, mezzanine_prop_main_radius, mezzanine_prop_main_length / 2., 0, 360); + TGeoTubeSeg* mezzanine_prop_small_tube = new TGeoTubeSeg("mezzanine_prop_small_tube", 0, mezzanine_prop_small_radius, mezzanine_prop_small_length / 2., 0, 360); + TGeoSphere* mezzanine_prop_lid_sphere = new TGeoSphere("mezzanine_prop_lid_sphere", 0, mezzanine_prop_lid_radius, 0, 90, 0, 360); + TGeoTranslation* trans_mezzanine_prop_main_tube = new TGeoTranslation("trans_mezzanine_prop_main_tube", 0, 0, mezzanine_prop_main_position_z); + TGeoTranslation* trans_mezzanine_prop_small_tube = new TGeoTranslation("trans_mezzanine_prop_small_tube", 0, 0, mezzanine_prop_small_position_z); + TGeoTranslation* trans_mezzanine_prop_lid_sphere = new TGeoTranslation("trans_mezzanine_prop_lid_sphere", 0, 0, mezzanine_prop_lid_position_z); + trans_mezzanine_prop_main_tube->RegisterYourself(); + trans_mezzanine_prop_small_tube->RegisterYourself(); + trans_mezzanine_prop_lid_sphere->RegisterYourself(); + + TGeoCompositeShape* mazzanine_prop_shape = new TGeoCompositeShape("mazzanine_prop_shape", "mezzanine_prop_main_tube:trans_mezzanine_prop_main_tube + mezzanine_prop_small_tube:trans_mezzanine_prop_small_tube + mezzanine_prop_lid_sphere:trans_mezzanine_prop_lid_sphere"); + TGeoTranslation* trans_mezzanine_prop_left = new TGeoTranslation("trans_mezzanine_prop_left", +8, -21.5, 0); + TGeoTranslation* trans_mezzanine_prop_right = new TGeoTranslation("trans_mezzanine_prop_right", -8, -21.5, 0); + trans_mezzanine_prop_left->RegisterYourself(); + trans_mezzanine_prop_right->RegisterYourself(); + TGeoCompositeShape* mazzanine_prop_shape_bothside = new TGeoCompositeShape("mazzanine_prop_shape_bothside", "mazzanine_prop_shape:trans_mezzanine_prop_left+mazzanine_prop_shape:trans_mezzanine_prop_right"); + + TGeoVolume* mazzanine_prop = new TGeoVolume("mazzanine_prop", mazzanine_prop_shape_bothside, kMedAlu); + mazzanine_prop->SetLineColor(kAzure - 3); + + TGeoRotation* trans_mazzanine_prop_front = new TGeoRotation("trans_mazzanine_prop_front", 0, 0, 0); + TGeoRotation* trans_mazzanine_prop_back = new TGeoRotation("trans_mazzanine_prop_back", 180, 180, 0); + + mHalfPSU->AddNode(mazzanine_prop, 0, trans_mazzanine_prop_front); + mHalfPSU->AddNode(mazzanine_prop, 0, trans_mazzanine_prop_back); + + //main + + Double_t mezzanine_main_thickness = mezzanine_prop_small_length; + Double_t mezzanine_main_width = 20.7; + Double_t mezzanine_main_height = 9.5; + Double_t mezzanine_main_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length + mezzanine_main_thickness / 2.; + + TGeoBBox* mezzanine_main_box = new TGeoBBox("mezzanine_main_box", mezzanine_main_width / 2., mezzanine_main_height / 2., mezzanine_main_thickness / 2.); + TGeoTubeSeg* mezzanine_main_sub_arc = new TGeoTubeSeg("mezzanine_main_sub_arc", 0, electric_board_min_radius1, mezzanine_main_thickness / 2 + delta_thickness, 180, 0); + TGeoTubeSeg* mezzanine_main_sub_hole = new TGeoTubeSeg("mezzanine_main_sub_hole", 0, mezzanine_prop_small_radius, mezzanine_main_thickness / 2 + delta_thickness, 0, 360); + + TGeoTranslation* trans_mezzanine_main_box = new TGeoTranslation("trans_mezzanine_main_box", 0, -15.1 - mezzanine_main_height / 2., mezzanine_main_position_z); + TGeoTranslation* trans_mezzanine_main_sub_arc = new TGeoTranslation("trans_mezzanine_main_sub_arc", 0, 0, mezzanine_main_position_z); + TGeoTranslation* trans_mezzanine_main_sub_hole_left = new TGeoTranslation("trans_mezzanine_main_sub_hole_left", +8, -21.5, mezzanine_main_position_z); + TGeoTranslation* trans_mezzanine_main_sub_hole_right = new TGeoTranslation("trans_mezzanine_main_sub_hole_right", +8, -21.5, mezzanine_main_position_z); + trans_mezzanine_main_box->RegisterYourself(); + trans_mezzanine_main_sub_arc->RegisterYourself(); + trans_mezzanine_main_sub_hole_right->RegisterYourself(); + trans_mezzanine_main_sub_hole_left->RegisterYourself(); + + TGeoCompositeShape* mezzanine_shape = new TGeoCompositeShape("mezzanine_shape", "mezzanine_main_box:trans_mezzanine_main_box - mezzanine_main_sub_arc:trans_mezzanine_main_sub_arc - mezzanine_main_sub_hole:trans_mezzanine_main_sub_hole_left - mezzanine_main_sub_hole:trans_mezzanine_main_sub_hole_right"); + TGeoVolume* mezzanine = new TGeoVolume("mezzanine", mezzanine_shape, kMedPeek); + mezzanine->SetLineColor(kGreen + 2); + + TGeoRotation* trans_mezzanine_front = new TGeoRotation("trans_mazzanine_front", 0, 0, 0); + TGeoRotation* trans_mazzanine_back = new TGeoRotation("trans_mazzanine_back", 180, 180, 0); + + mHalfPSU->AddNode(mezzanine, 0, trans_mezzanine_front); + mHalfPSU->AddNode(mezzanine, 0, trans_mazzanine_back); + + //connector + + Double_t mezzanine_connector_base_box_thickness = 1.186; + Double_t mezzanine_connector_base_box_width = 6.778; + Double_t mezzanine_connector_base_box_height = 1.595; + Double_t mezzanine_connector_base_box_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_connector_base_box_thickness / 2; + + Double_t mezzanine_connector_base_sub_box_thickness = mezzanine_connector_base_box_thickness - 0.307; + Double_t mezzanine_connector_base_sub_box_width = 6.778; + Double_t mezzanine_connector_base_sub_box_height = 1.468; + + TGeoBBox* mezzanine_connector_base_box = new TGeoBBox("mezzanine_connector_base", mezzanine_connector_base_box_width / 2., mezzanine_connector_base_box_height / 2., mezzanine_connector_base_box_thickness / 2.); + TGeoBBox* mezzanine_connector_base_sub_box = new TGeoBBox("mezzanine_connector_base_sub_box", mezzanine_connector_base_sub_box_width / 2. + delta_thickness, mezzanine_connector_base_sub_box_height / 2., mezzanine_connector_base_sub_box_thickness / 2.); + + TGeoTranslation* trans_mezzanine_connector_base_box = new TGeoTranslation("trans_mezzanine_connector_base_box", 0, -22.421 - mezzanine_connector_base_box_height / 2.0, mezzanine_connector_base_box_position_z); + TGeoTranslation* trans_mezzanine_connector_base_sub_box = new TGeoTranslation("trans_mezzanine_connector_base_sub_box", 0, -22.421 - mezzanine_connector_base_box_height / 2.0, mezzanine_connector_base_box_position_z + (mezzanine_connector_base_box_thickness - mezzanine_connector_base_sub_box_thickness) / 2.); + trans_mezzanine_connector_base_box->RegisterYourself(); + trans_mezzanine_connector_base_sub_box->RegisterYourself(); + + TGeoCompositeShape* mezzanine_connector_base_shape = new TGeoCompositeShape("mezzanine_connector_base_shape", "mezzanine_connector_base:trans_mezzanine_connector_base_box - mezzanine_connector_base_sub_box:trans_mezzanine_connector_base_sub_box"); + TGeoVolume* mezzanine_connector_base = new TGeoVolume("mezzanine_connector_base", mezzanine_connector_base_shape, kMedPeek); + mezzanine_connector_base->SetLineColor(kOrange + 7); + + TGeoRotation* trans_mezzanine_connector_base_front = new TGeoRotation("trans_mezzanine_connector_base_front", 0, 0, 0); + TGeoRotation* trans_mezzanine_connector_base_back = new TGeoRotation("trans_mezzanine_connector_base_back", 180, 180, 0); + mHalfPSU->AddNode(mezzanine_connector_base, 0, trans_mezzanine_connector_base_front); + mHalfPSU->AddNode(mezzanine_connector_base, 0, trans_mezzanine_connector_base_back); + + Double_t mezzanine_connector_lid_bottom_box_thickness = 0.112; + Double_t mezzanine_connector_lid_bottom_box_width = 6.778; + Double_t mezzanine_connector_lid_bottom_box_height = 1.468; + Double_t mezzanine_connector_lid_bottom_box_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + 0.967 + mezzanine_connector_lid_bottom_box_thickness / 2.; + + TGeoBBox* mezzanine_connector_lid_bottom_box = new TGeoBBox("mezzanine_connector_lid_bottom_box", mezzanine_connector_lid_bottom_box_width / 2., mezzanine_connector_lid_bottom_box_height / 2., mezzanine_connector_lid_bottom_box_thickness / 2.); + TGeoVolume* mezzanine_connector_lid_bottom = new TGeoVolume("mezzanine_connector_lid_bottom", mezzanine_connector_lid_bottom_box, kMedPeek); + mezzanine_connector_lid_bottom->SetLineColor(kGray + 2); + + TGeoTranslation* trans_mezzanine_connector_lid_bottom_front = new TGeoTranslation("trans_mezzanine_connector_lid_bottom_front", 0, 0 - 22.421 - mezzanine_connector_base_box_height / 2., mezzanine_connector_lid_bottom_box_position_z); + TGeoTranslation* trans_mezzanine_connector_lid_bottom_back = new TGeoTranslation("trans_mezzanine_connector_lid_bottom_back", 0, 0 - 22.421 - mezzanine_connector_base_box_height / 2., -mezzanine_connector_lid_bottom_box_position_z); + mHalfPSU->AddNode(mezzanine_connector_lid_bottom, 0, trans_mezzanine_connector_lid_bottom_front); + mHalfPSU->AddNode(mezzanine_connector_lid_bottom, 0, trans_mezzanine_connector_lid_bottom_back); + + Double_t mezzanine_connector_lid_top_box_thickness = mezzanine_main_position_z - mezzanine_main_thickness / 2 - mezzanine_connector_lid_bottom_box_position_z - mezzanine_connector_lid_bottom_box_thickness / 2.; + Double_t mezzanine_connector_lid_top_box_width = 6.660; + Double_t mezzanine_connector_lid_top_box_height = 1.328; + Double_t mezzanine_connector_lid_top_box_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + 0.967 + mezzanine_connector_lid_bottom_box_thickness + mezzanine_connector_lid_top_box_thickness / 2.; + TGeoBBox* mezzanine_connector_lid_top_box = new TGeoBBox("mezzanine_connector_lid_top_box", mezzanine_connector_lid_top_box_width / 2., mezzanine_connector_lid_top_box_height / 2., mezzanine_connector_lid_top_box_thickness / 2.); + TGeoVolume* mezzanine_connector_lid_top = new TGeoVolume("mezzanine_connector_lid_top", mezzanine_connector_lid_top_box, kMedPeek); + mezzanine_connector_lid_top->SetLineColor(kGray + 2); + + TGeoTranslation* trans_mezzanine_connector_lid_top_front = new TGeoTranslation("trans_mezzanine_connector_lid_top_front", 0, 0 - 22.421 - mezzanine_connector_base_box_height / 2., mezzanine_connector_lid_top_box_position_z); + TGeoTranslation* trans_mezzanine_connector_lid_top_back = new TGeoTranslation("trans_mezzanine_connector_lid_top_back", 0, 0 - 22.421 - mezzanine_connector_base_box_height / 2., -mezzanine_connector_lid_top_box_position_z); + mHalfPSU->AddNode(mezzanine_connector_lid_top, 0, trans_mezzanine_connector_lid_top_front); + mHalfPSU->AddNode(mezzanine_connector_lid_top, 0, trans_mezzanine_connector_lid_top_back); + + //DCDC converter on mezzanine + + Double_t spacer_sheet1_mezzanine_box_thickness = 0.086; + Double_t spacer_sheet1_mezzanine_box_width = 1.397; + Double_t spacer_sheet1_mezzanine_box_height = 0.343; + Double_t spacer_sheet1_mezzanine_box_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length - spacer_sheet1_mezzanine_box_thickness / 2.; + Double_t gap_sheet1_on_mezzanine = 0.1; + + TGeoBBox* spacer_sheet1_mezzanine_box = new TGeoBBox("spacer_sheet1_mezzanine_box", spacer_sheet1_mezzanine_box_width / 2., spacer_sheet1_mezzanine_box_height / 2., spacer_sheet1_mezzanine_box_thickness / 2.); + TGeoTranslation* trans_spacer_sheet1_mezzanine_box_front[5]; + trans_spacer_sheet1_mezzanine_box_front[0] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_front_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_front[1] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_front_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_front[2] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_front_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_front[3] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_front_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_front[4] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_front_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), spacer_sheet1_mezzanine_box_position_z); + TGeoTranslation* trans_spacer_sheet1_mezzanine_box_back[5]; + trans_spacer_sheet1_mezzanine_box_back[0] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_back_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_back[1] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_back_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_back[2] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_back_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_back[3] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_back_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -spacer_sheet1_mezzanine_box_position_z); + trans_spacer_sheet1_mezzanine_box_back[4] = new TGeoTranslation("trans_spacer_sheet1_mezzanine_box_back_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -spacer_sheet1_mezzanine_box_position_z); + + TGeoVolume* spacer_sheet1_mezzanine = new TGeoVolume("spacer_sheet1_mezzanine", spacer_sheet1_mezzanine_box, kMedPeek); + spacer_sheet1_mezzanine->SetLineColor(kGray + 2); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_front[0]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_front[1]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_front[2]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_front[3]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_front[4]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_back[0]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_back[1]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_back[2]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_back[3]); + mHalfPSU->AddNode(spacer_sheet1_mezzanine, 0, trans_spacer_sheet1_mezzanine_box_back[4]); + + Double_t sheet1_on_mezzanine_box_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length - spacer_sheet1_mezzanine_box_thickness - DCDC_sheet1_thickness / 2.; + + TGeoTranslation* trans_sheet1_on_mezzanine_box_front[5]; + trans_sheet1_on_mezzanine_box_front[0] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_front_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_front[1] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_front_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_front[2] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_front_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_front[3] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_front_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_front[4] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_front_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), sheet1_on_mezzanine_box_position_z); + TGeoTranslation* trans_sheet1_on_mezzanine_box_back[5]; + trans_sheet1_on_mezzanine_box_back[0] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_back_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), -sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_back[1] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_back_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), -sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_back[2] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_back_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), -sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_back[3] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_back_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), -sheet1_on_mezzanine_box_position_z); + trans_sheet1_on_mezzanine_box_back[4] = new TGeoTranslation("trans_sheet1_on_mezzanine_box_back_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_sheet1_width / 2.), -sheet1_on_mezzanine_box_position_z); + + TGeoVolume* sheet1_on_mezzanine = new TGeoVolume("sheet1_on_mezzanine", DCDC_sheet1_box_side, kMedPeek); + sheet1_on_mezzanine->SetLineColor(kGreen); + + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_front[0]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_front[1]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_front[2]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_front[3]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_front[4]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_back[0]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_back[1]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_back[2]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_back[3]); + mHalfPSU->AddNode(sheet1_on_mezzanine, 0, trans_sheet1_on_mezzanine_box_back[4]); + + Double_t DCDC_connector_on_mezzanine_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length - spacer_sheet1_mezzanine_box_thickness - DCDC_sheet1_thickness - DCDC_connector_thickness / 2.; + + TGeoVolume* DCDC_connector_on_mezzanine = new TGeoVolume("DCDC_connector_on_mezzanine", DCDC_connector_box_side, kMedPeek); + DCDC_connector_on_mezzanine->SetLineColor(kGray + 2); + TGeoTranslation* trans_DCDC_connector_on_mezzanine_front[5]; + trans_DCDC_connector_on_mezzanine_front[0] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_front_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_front[1] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_front_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_front[2] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_front_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_front[3] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_front_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_front[4] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_front_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), DCDC_connector_on_mezzanine_position_z); + TGeoTranslation* trans_DCDC_connector_on_mezzanine_back[5]; + trans_DCDC_connector_on_mezzanine_back[0] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_back_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_back[1] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_back_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_back[2] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_back_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_back[3] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_back_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -DCDC_connector_on_mezzanine_position_z); + trans_DCDC_connector_on_mezzanine_back[4] = new TGeoTranslation("trans_DCDC_connector_on_mezzanine_back_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (spacer_sheet1_mezzanine_box_width / 2. + 0.531), -DCDC_connector_on_mezzanine_position_z); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_front[0]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_front[1]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_front[2]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_front[3]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_front[4]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_back[0]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_back[1]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_back[2]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_back[3]); + mHalfPSU->AddNode(DCDC_connector_on_mezzanine, 0, trans_DCDC_connector_on_mezzanine_back[4]); + + Double_t DCDC_cover_on_mezzanine_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length - spacer_sheet1_mezzanine_box_thickness - DCDC_sheet1_thickness - DCDC_cover_thickness / 2.; + + TGeoTranslation* trans_DCDC_cover_innner_box_back = new TGeoTranslation("trans_DCDC_cover_innner_box_back", 0, 0, -2 * DCDC_cover_depth); + TGeoTranslation* trans_DCDC_cover_innner_box_front = new TGeoTranslation("trans_DCDC_cover_innner_box_front", 0, 0, +2 * DCDC_cover_depth); + trans_DCDC_cover_innner_box_back->RegisterYourself(); + trans_DCDC_cover_innner_box_front->RegisterYourself(); + + TGeoRotation* rotate_DCDC_cover_on_mezzanine_shape = new TGeoRotation("rotate_DCDC_cover_on_mezzanine_shape", 0, 180, 180); + rotate_DCDC_cover_on_mezzanine_shape->RegisterYourself(); + + TGeoCompositeShape* DCDC_cover_on_mezzanine_shape_back = new TGeoCompositeShape("DCDC_cover_on_mezzanine_shape_back", "DCDC_cover_outer_box_side - DCDC_cover_inner_box_side:trans_DCDC_cover_innner_box_back"); + TGeoCompositeShape* DCDC_cover_on_mezzanine_shape_front = new TGeoCompositeShape("DCDC_cover_on_mezzanine_shape_front", "DCDC_cover_outer_box_side - DCDC_cover_inner_box_side:trans_DCDC_cover_innner_box_front"); + + TGeoVolume* DCDC_cover_on_mezzanine_front = new TGeoVolume("DCDC_cover_on_mezzanine_front", DCDC_cover_on_mezzanine_shape_front, kMedPeek); + TGeoVolume* DCDC_cover_on_mezzanine_back = new TGeoVolume("DCDC_cover_on_mezzanine_back", DCDC_cover_on_mezzanine_shape_back, kMedPeek); + DCDC_cover_on_mezzanine_front->SetLineColor(kGray); + DCDC_cover_on_mezzanine_back->SetLineColor(kGray); + + TGeoTranslation* trans_DCDC_cover_on_mezzanine_front[5]; + trans_DCDC_cover_on_mezzanine_front[0] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_front_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_front[1] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_front_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_front[2] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_front_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_front[3] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_front_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_front[4] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_front_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), DCDC_cover_on_mezzanine_position_z); + TGeoTranslation* trans_DCDC_cover_on_mezzanine_back[5]; + trans_DCDC_cover_on_mezzanine_back[0] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_back_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_back[1] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_back_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_back[2] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_back_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_back[3] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_back_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -DCDC_cover_on_mezzanine_position_z); + trans_DCDC_cover_on_mezzanine_back[4] = new TGeoTranslation("trans_DCDC_cover_on_mezzanine_back_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -DCDC_cover_on_mezzanine_position_z); + + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_front, 0, trans_DCDC_cover_on_mezzanine_front[0]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_front, 0, trans_DCDC_cover_on_mezzanine_front[1]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_front, 0, trans_DCDC_cover_on_mezzanine_front[2]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_front, 0, trans_DCDC_cover_on_mezzanine_front[3]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_front, 0, trans_DCDC_cover_on_mezzanine_front[4]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_back, 0, trans_DCDC_cover_on_mezzanine_back[0]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_back, 0, trans_DCDC_cover_on_mezzanine_back[1]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_back, 0, trans_DCDC_cover_on_mezzanine_back[2]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_back, 0, trans_DCDC_cover_on_mezzanine_back[3]); + mHalfPSU->AddNode(DCDC_cover_on_mezzanine_back, 0, trans_DCDC_cover_on_mezzanine_back[4]); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Connector + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Double_t main_connector1_thickness = 0.752; + Double_t main_connector1_width = 2.350; + Double_t main_connector1_height = 0.160; + TGeoBBox* connector1_box = new TGeoBBox("connector1_box", main_connector1_width / 2., main_connector1_height / 2., main_connector1_thickness / 2.); + + Double_t main_connector2_thickness = 0.564; + Double_t main_connector2_width = 2.086; + Double_t main_connector2_height = 0.499; + TGeoBBox* connector2_box = new TGeoBBox("connector2_box", main_connector2_width / 2., main_connector2_height / 2., main_connector2_thickness / 2.); + + Double_t main_connector3_thickness = 0.742; + Double_t main_connector3_width = 2.567; + Double_t main_connector3_height = 0.579; + TGeoBBox* connector3_box = new TGeoBBox("connector3_box", main_connector3_width / 2., main_connector3_height / 2., main_connector3_thickness / 2.); + + TGeoVolume* main_connector1 = new TGeoVolume("main_connector1", connector1_box, kMedPeek); + main_connector1->SetLineColor(kGray + 2); + TGeoVolume* main_connector2 = new TGeoVolume("main_connector2", connector2_box, kMedPeek); + main_connector2->SetLineColor(kGray + 2); + TGeoVolume* main_connector3 = new TGeoVolume("main_connector3", connector3_box, kMedPeek); + main_connector3->SetLineColor(kGray + 2); + + TGeoTranslation* trans_main_connector1_front[10]; + trans_main_connector1_front[0] = new TGeoTranslation("trans_main_connector1_front_No0", 14.462 + main_connector2_width / 2., -4.276 - main_connector1_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector1_front[1] = new TGeoTranslation("trans_main_connector1_front_No1", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1, -4.276 - main_connector1_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector1_front[2] = new TGeoTranslation("trans_main_connector1_front_No2", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2, -4.276 - main_connector1_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector1_front[3] = new TGeoTranslation("trans_main_connector1_front_No3", -(14.462 + main_connector2_width / 2.), -4.276 - main_connector1_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector1_front[4] = new TGeoTranslation("trans_main_connector1_front_No4", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1), -4.276 - main_connector1_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector1_front[5] = new TGeoTranslation("trans_main_connector1_front_No5", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2), -4.276 - main_connector1_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + TGeoTranslation* trans_main_connector1_back[10]; + trans_main_connector1_back[0] = new TGeoTranslation("trans_main_connector1_back_No0", 14.462 + main_connector2_width / 2., -4.276 - main_connector1_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector1_back[1] = new TGeoTranslation("trans_main_connector1_back_No1", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1, -4.276 - main_connector1_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector1_back[2] = new TGeoTranslation("trans_main_connector1_back_No2", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2, -4.276 - main_connector1_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector1_back[3] = new TGeoTranslation("trans_main_connector1_back_No3", -(14.462 + main_connector2_width / 2.), -4.276 - main_connector1_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector1_back[4] = new TGeoTranslation("trans_main_connector1_back_No4", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1), -4.276 - main_connector1_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector1_back[5] = new TGeoTranslation("trans_main_connector1_back_No5", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2), -4.276 - main_connector1_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + + TGeoTranslation* trans_main_connector2_front[10]; + trans_main_connector2_front[0] = new TGeoTranslation("trans_main_connector2_front_No0", 14.462 + main_connector2_width / 2., -4.276 - main_connector1_height - main_connector2_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector2_front[1] = new TGeoTranslation("trans_main_connector2_front_No1", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1, -4.276 - main_connector1_height - main_connector2_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector2_front[2] = new TGeoTranslation("trans_main_connector2_front_No2", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2, -4.276 - main_connector1_height - main_connector2_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector2_front[3] = new TGeoTranslation("trans_main_connector2_front_No3", -(14.462 + main_connector2_width / 2.), -4.276 - main_connector1_height - main_connector2_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector2_front[4] = new TGeoTranslation("trans_main_connector2_front_No4", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1), -4.276 - main_connector1_height - main_connector2_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + trans_main_connector2_front[5] = new TGeoTranslation("trans_main_connector2_front_No5", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2), -4.276 - main_connector1_height - main_connector2_height / 2., middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2); + TGeoTranslation* trans_main_connector2_back[10]; + trans_main_connector2_back[0] = new TGeoTranslation("trans_main_connector2_back_No0", 14.462 + main_connector2_width / 2., -4.276 - main_connector1_height - main_connector2_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector2_back[1] = new TGeoTranslation("trans_main_connector2_back_No1", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1, -4.276 - main_connector1_height - main_connector2_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector2_back[2] = new TGeoTranslation("trans_main_connector2_back_No2", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2, -4.276 - main_connector1_height - main_connector2_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector2_back[3] = new TGeoTranslation("trans_main_connector2_back_No3", -(14.462 + main_connector2_width / 2.), -4.276 - main_connector1_height - main_connector2_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector2_back[4] = new TGeoTranslation("trans_main_connector2_back_No4", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1), -4.276 - main_connector1_height - main_connector2_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + trans_main_connector2_back[5] = new TGeoTranslation("trans_main_connector2_back_No5", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2), -4.276 - main_connector1_height - main_connector2_height / 2., -(middle_spacer_main_add_rectangle_side_small_thickness / 2. + main_connector3_thickness / 2)); + + TGeoTranslation* trans_main_connector3_front[10]; + trans_main_connector3_front[0] = new TGeoTranslation("trans_main_connector3_front_No0", 14.462 + main_connector2_width / 2., -4.436 - main_connector2_height - main_connector3_height / 2., electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2); + trans_main_connector3_front[1] = new TGeoTranslation("trans_main_connector3_front_No1", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1, -4.436 - main_connector2_height - main_connector3_height / 2., electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2); + trans_main_connector3_front[2] = new TGeoTranslation("trans_main_connector3_front_No2", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2, -4.436 - main_connector2_height - main_connector3_height / 2., electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2); + trans_main_connector3_front[3] = new TGeoTranslation("trans_main_connector3_front_No3", -(14.462 + main_connector2_width / 2.), -4.436 - main_connector2_height - main_connector3_height / 2., electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2); + trans_main_connector3_front[4] = new TGeoTranslation("trans_main_connector3_front_No4", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1), -4.436 - main_connector2_height - main_connector3_height / 2., electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2); + trans_main_connector3_front[5] = new TGeoTranslation("trans_main_connector3_front_No5", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2), -4.436 - main_connector2_height - main_connector3_height / 2., electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2); + TGeoTranslation* trans_main_connector3_back[10]; + trans_main_connector3_back[0] = new TGeoTranslation("trans_main_connector3_back_No0", 14.462 + main_connector2_width / 2., -4.436 - main_connector2_height - main_connector3_height / 2., -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2)); + trans_main_connector3_back[1] = new TGeoTranslation("trans_main_connector3_back_No1", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1, -4.436 - main_connector2_height - main_connector3_height / 2., -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2)); + trans_main_connector3_back[2] = new TGeoTranslation("trans_main_connector3_back_No2", 14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2, -4.436 - main_connector2_height - main_connector3_height / 2., -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2)); + trans_main_connector3_back[3] = new TGeoTranslation("trans_main_connector3_back_No3", -(14.462 + main_connector2_width / 2.), -4.436 - main_connector2_height - main_connector3_height / 2., -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2)); + trans_main_connector3_back[4] = new TGeoTranslation("trans_main_connector3_back_No4", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 1), -4.436 - main_connector2_height - main_connector3_height / 2., -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2)); + trans_main_connector3_back[5] = new TGeoTranslation("trans_main_connector3_back_No5", -(14.462 + main_connector2_width / 2. + (0.766 + main_connector2_width) * 2), -4.436 - main_connector2_height - main_connector3_height / 2., -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2)); + + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_front[0]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_front[1]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_front[2]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_front[3]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_front[4]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_front[5]); + + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_front[0]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_front[1]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_front[2]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_front[3]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_front[4]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_front[5]); + + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_front[0]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_front[1]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_front[2]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_front[3]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_front[4]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_front[5]); + + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_back[0]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_back[1]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_back[2]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_back[3]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_back[4]); + mHalfPSU->AddNode(main_connector1, 0, trans_main_connector1_back[5]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_back[0]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_back[1]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_back[2]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_back[3]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_back[4]); + mHalfPSU->AddNode(main_connector2, 0, trans_main_connector2_back[5]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_back[0]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_back[1]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_back[2]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_back[3]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_back[4]); + mHalfPSU->AddNode(main_connector3, 0, trans_main_connector3_back[5]); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Rough coil shape part //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // - new TGeoTorus("DCDC_rough_coil_torus_shape", DCDC_coil_torus_part_radius, DCDC_coil_radius1 - DCDC_coil_max_radius1, - DCDC_coil_radius1 + DCDC_coil_max_radius1, 0, 180); - new TGeoTube("DCDC_rough_coil_straight_shape", DCDC_coil_radius1 - DCDC_coil_max_radius1, DCDC_coil_radius1 + DCDC_coil_max_radius1, - DCDC_coil_max_radius1 * 9 + DCDC_coil_straight_gap * 4); - - TGeoRotation* rDCDC_rough_coil_torus_shape1 = new TGeoRotation("rDCDC_rough_coil_torus_shape1", 0, 90, 0); - TGeoRotation* rDCDC_rough_coil_torus_shape2 = new TGeoRotation("rDCDC_rough_coil_torus_shape2", 0, -90, 0); - rDCDC_rough_coil_torus_shape1->RegisterYourself(); - rDCDC_rough_coil_torus_shape2->RegisterYourself(); - - new TGeoCompositeShape("rotated_DCDC_rough_coil_torus_shape1", "dummy+DCDC_rough_coil_torus_shape:rDCDC_rough_coil_torus_shape1"); - new TGeoCompositeShape("rotated_DCDC_rough_coil_torus_shape2", "dummy+DCDC_rough_coil_torus_shape:rDCDC_rough_coil_torus_shape2"); - - TGeoTranslation* tDCDC_rough_coil_straight_shape1 = new TGeoTranslation("tDCDC_rough_coil_straight_shape1", DCDC_coil_torus_part_radius, 0, 0); - TGeoTranslation* tDCDC_rough_coil_straight_shape2 = new TGeoTranslation("tDCDC_rough_coil_straight_shape2", -DCDC_coil_torus_part_radius, 0, 0); - tDCDC_rough_coil_straight_shape1->RegisterYourself(); - tDCDC_rough_coil_straight_shape2->RegisterYourself(); - TGeoTranslation* tDCDC_rough_coil_torus_shape1 = new TGeoTranslation("tDCDC_rough_coil_torus_shape1", 0, 0, DCDC_coil_max_radius1 * 9 + DCDC_coil_straight_gap * 4); - TGeoTranslation* tDCDC_rough_coil_torus_shape2 = new TGeoTranslation("tDCDC_rough_coil_torus_shape2", 0, 0, -(DCDC_coil_max_radius1 * 9 + DCDC_coil_straight_gap * 4)); - tDCDC_rough_coil_torus_shape1->RegisterYourself(); - tDCDC_rough_coil_torus_shape2->RegisterYourself(); - - new TGeoCompositeShape("DCDC_coil_shape1", - "DCDC_rough_coil_straight_shape:tDCDC_rough_coil_straight_shape1+" - "DCDC_rough_coil_straight_shape:tDCDC_rough_coil_straight_shape2+" - "rotated_DCDC_rough_coil_torus_shape1:tDCDC_rough_coil_torus_shape1+" - "rotated_DCDC_rough_coil_torus_shape2:tDCDC_rough_coil_torus_shape2"); - TGeoRotation* rDCDC_coil_shape1[nDCDC]; - TGeoTranslation* tDCDC_coil_shape1[nDCDC]; - TGeoCompositeShape* rotated_DCDC_coil_shape1[nDCDC]; - TString string_all_DCDC_coil_shape1 = ""; - - for (Int_t iDCDC = 0; iDCDC < nDCDC; ++iDCDC) { - rDCDC_coil_shape1[iDCDC] = new TGeoRotation(Form("rDCDC_coil_shape1_angle%d", iDCDC + 1), full_angle / 2 - one_angle * iDCDC, 90, 0); - rDCDC_coil_shape1[iDCDC]->RegisterYourself(); - - rotated_DCDC_coil_shape1[iDCDC] = new TGeoCompositeShape(Form("rotated_DCDC_coil_shape1_angle%d", iDCDC + 1), Form("dummy+DCDC_coil_shape1:rDCDC_coil_shape1_angle%d", iDCDC + 1)); - - tDCDC_shape1[iDCDC] = new TGeoTranslation(Form("tDCDC_coil_shape1_pos%d", iDCDC + 1), - -position_radius * TMath::Cos((start_DCDC_angle + one_angle * iDCDC) * TMath::Pi() / 180.), - position_radius * TMath::Sin((start_DCDC_angle + one_angle * iDCDC) * TMath::Pi() / 180.), 0); - tDCDC_shape1[iDCDC]->RegisterYourself(); - - if (iDCDC + 1 == nDCDC) { - string_all_DCDC_coil_shape1 += Form("rotated_DCDC_coil_shape1_angle%d:tDCDC_shape1_pos%d", iDCDC + 1, iDCDC + 1); - } else { - string_all_DCDC_coil_shape1 += Form("rotated_DCDC_coil_shape1_angle%d:tDCDC_shape1_pos%d+", iDCDC + 1, iDCDC + 1); - } + + Double_t coil_torus_inner_radius1 = TMath::Min(DCDC_cover_inner_width, DCDC_cover_inner_height) / 10.0; + Double_t coil_torus_outer_radius1 = TMath::Min(DCDC_cover_inner_width, DCDC_cover_inner_height) / 8.0; + Double_t coil_radius1 = TMath::Min(DCDC_cover_inner_width, DCDC_cover_inner_height) / 3.0 - coil_torus_outer_radius1; + Double_t coil_position_z = DCDC_sheet1_position_z + DCDC_sheet1_thickness / 2. + coil_torus_outer_radius1; + + TGeoTorus* coil_torus = new TGeoTorus("coil_torus", coil_radius1, coil_torus_inner_radius1, coil_torus_outer_radius1, 0, 360); + + std::string name_coil = ""; + + TGeoCompositeShape* rotated_coil_torus[23]; + + for (Int_t iB = 0; iB < 11; ++iB) { + + Double_t block_angle = (180. - block_angle_index[iB]) / 2. * TMath::Pi() / 180.; + + TGeoRotation* rotate_coil_torus_left = new TGeoRotation(Form("rotate_coil_torus_No%d", iB * 2), 180 - block_angle * 180. / TMath::Pi(), 0, 0); + TGeoRotation* rotate_coil_torus_right = new TGeoRotation(Form("rotate_coil_torus_No%d", iB * 2 + 1), block_angle * 180. / TMath::Pi(), 0, 0); + rotate_coil_torus_left->RegisterYourself(); + rotate_coil_torus_right->RegisterYourself(); + + Double_t cent_block_left[] = {block_radius * TMath::Cos(block_angle), -block_radius * TMath::Sin(block_angle), coil_position_z}; + Double_t cent_block_right[] = {block_radius * TMath::Cos(TMath::Pi() - block_angle), -block_radius * TMath::Sin(TMath::Pi() - block_angle), coil_position_z}; + + TGeoCombiTrans* combtrans_coil_torus_left = new TGeoCombiTrans(Form("combtrans_coil_torus_No%d", 2 * iB), cent_block_left[0], cent_block_left[1], cent_block_left[2], rotate_coil_torus_left); + TGeoCombiTrans* combtrans_coil_torus_right = new TGeoCombiTrans(Form("combtrans_coil_torus_No%d", 2 * iB + 1), cent_block_right[0], cent_block_right[1], cent_block_right[2], rotate_coil_torus_right); + combtrans_coil_torus_left->RegisterYourself(); + combtrans_coil_torus_right->RegisterYourself(); + + if (iB == 0) + name_coil += Form("coil_torus:combtrans_coil_torus_No%d", 2 * iB); + else + name_coil += Form("+coil_torus:combtrans_coil_torus_No%d", 2 * iB); + name_coil += Form("+coil_torus:combtrans_coil_torus_No%d", 2 * iB + 1); } - TGeoRotation* rDCDC_side_coil_shape1 = new TGeoRotation("rDCDC_side_coil_shape1", 0, 90, 0); - rDCDC_side_coil_shape1->RegisterYourself(); - new TGeoCompositeShape("rotated_DCDC_side_coil_shape", "dummy+DCDC_coil_shape1:rDCDC_side_coil_shape1"); + TGeoTorus* coil_torus_side = new TGeoTorus("coil_torus_side", coil_radius1, coil_torus_inner_radius1, coil_torus_outer_radius1, 0, 360); + + TGeoTranslation* trans_coil_torus_side_left = new TGeoTranslation("trans_coil_torus_side_left", 22.259 - middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, coil_position_z); + trans_coil_torus_side_left->RegisterYourself(); + name_coil += "+coil_torus_side:trans_coil_torus_side_left"; + + TGeoTranslation* trans_coil_torus_side_right = new TGeoTranslation("trans_coil_torus_side_right", -22.247 + middle_spacer_cover_block_width / 2, -8.305 + middle_spacer_cover_block_height / 2, coil_position_z); + trans_coil_torus_side_right->RegisterYourself(); + name_coil += "+coil_torus_side:trans_coil_torus_side_right"; + + TGeoCompositeShape* coil_shape = new TGeoCompositeShape("coil_shape", name_coil.c_str()); + + TGeoVolume* coil = new TGeoVolume("coil", coil_shape, kMedAlu); + coil->SetLineColor(kYellow); + + TGeoRotation* trans_coil_front = new TGeoRotation("trans_coil_front", 0, 0, 0); + TGeoRotation* trans_coil_back = new TGeoRotation("trans_coil_back", 180, 180, 0); + + mHalfPSU->AddNode(coil, 0, trans_coil_front); + mHalfPSU->AddNode(coil, 0, trans_coil_back); + + //On Mazzenine + + Double_t coil_on_mezzanine_position_z = middle_spacer_main_thickness / 2. + middle_spacer_cover_thickness + electric_board_thickness + mezzanine_prop_main_length - spacer_sheet1_mezzanine_box_thickness - DCDC_sheet1_thickness - coil_torus_outer_radius1; + + TGeoTranslation* trans_coil_on_mezzanine_front[5]; + trans_coil_on_mezzanine_front[0] = new TGeoTranslation("trans_coil_on_mezzanine_front_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_front[1] = new TGeoTranslation("trans_coil_on_mezzanine_front_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_front[2] = new TGeoTranslation("trans_coil_on_mezzanine_front_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_front[3] = new TGeoTranslation("trans_coil_on_mezzanine_front_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_front[4] = new TGeoTranslation("trans_coil_on_mezzanine_front_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), coil_on_mezzanine_position_z); + TGeoTranslation* trans_coil_on_mezzanine_back[5]; + trans_coil_on_mezzanine_back[0] = new TGeoTranslation("trans_coil_on_mezzanine_back_No0", +2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_back[1] = new TGeoTranslation("trans_coil_on_mezzanine_back_No1", +1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_back[2] = new TGeoTranslation("trans_coil_on_mezzanine_back_No2", 0 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_back[3] = new TGeoTranslation("trans_coil_on_mezzanine_back_No3", -1 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -coil_on_mezzanine_position_z); + trans_coil_on_mezzanine_back[4] = new TGeoTranslation("trans_coil_on_mezzanine_back_No4", -2 * (DCDC_sheet1_height + gap_sheet1_on_mezzanine), -17.952 - (DCDC_cover_outer_width / 2. + 1.825), -coil_on_mezzanine_position_z); + + TGeoVolume* coil_on_mezzanine = new TGeoVolume("coil_on_mezzanine", coil_torus, kMedAlu); + coil_on_mezzanine->SetLineColor(kYellow); + + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_front[0]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_front[1]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_front[2]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_front[3]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_front[4]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_back[0]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_back[1]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_back[2]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_back[3]); + mHalfPSU->AddNode(coil_on_mezzanine, 0, trans_coil_on_mezzanine_back[4]); + + //small connector borrom + + Double_t main_connector_angle1 = 52 * TMath::Pi() / 180.; + Double_t main_connector_angle2 = 45 * TMath::Pi() / 180.; + + //front + + //left + + TGeoRotation* rotate_main_connector_box_angle1_left = new TGeoRotation("rotate_main_connector_box_angle1_left", 0, 0, 90 - main_connector_angle1 * 180 / TMath::Pi()); + TGeoRotation* rotate_main_connector_box_angle2_left = new TGeoRotation("rotate_main_connector_box_angle2_left", 0, 0, 90 - main_connector_angle2 * 180 / TMath::Pi()); + TGeoRotation* rotate_main_connector_box_angle1_right = new TGeoRotation("rotate_main_connector_box_angle1_right", 0, 0, -90 + main_connector_angle1 * 180 / TMath::Pi()); + TGeoRotation* rotate_main_connector_box_angle2_right = new TGeoRotation("rotate_main_connector_box_angle2_right", 0, 0, -90 + main_connector_angle2 * 180 / TMath::Pi()); + rotate_main_connector_box_angle1_left->RegisterYourself(); + rotate_main_connector_box_angle2_left->RegisterYourself(); + rotate_main_connector_box_angle1_right->RegisterYourself(); + rotate_main_connector_box_angle2_right->RegisterYourself(); + + TGeoTranslation* trans_connector1_box = new TGeoTranslation("trans_connector1_box", 0, -main_connector3_height / 2. - main_connector2_height - main_connector1_height / 2., 0); + TGeoTranslation* trans_connector2_box = new TGeoTranslation("trans_connector2_box", 0, -main_connector3_height / 2. - main_connector2_height / 2., 0); + TGeoTranslation* trans_connector3_box = new TGeoTranslation("trans_connector3_box", 0, 0, 0); + trans_connector1_box->RegisterYourself(); + trans_connector2_box->RegisterYourself(); + trans_connector3_box->RegisterYourself(); + + TGeoCompositeShape* comp_connector_box = new TGeoCompositeShape("comp_connector_box", "connector1_box:trans_connector1_box+connector2_box:trans_connector2_box+connector3_box:trans_connector3_box"); + + TGeoVolume* connector = new TGeoVolume("connector", comp_connector_box, kMedPeek); + connector->SetLineColor(kGray + 2); + + TGeoCombiTrans* trans_connector1_front = new TGeoCombiTrans("trans_connector1_front", +(17.064 + 15.397) / 2., -(21.795 + 19.758) / 2, electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2, rotate_main_connector_box_angle1_left); + TGeoCombiTrans* trans_connector2_front = new TGeoCombiTrans("trans_connector2_front", +(19.345 + 17.941) / 2, -(19.757 + 17.531) / 2, electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2, rotate_main_connector_box_angle2_left); + TGeoCombiTrans* trans_connector3_front = new TGeoCombiTrans("trans_connector1_front", -(17.064 + 15.397) / 2., -(21.795 + 19.758) / 2, electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2, rotate_main_connector_box_angle1_right); + TGeoCombiTrans* trans_connector4_front = new TGeoCombiTrans("trans_connector2_front", -(19.345 + 17.941) / 2, -(19.757 + 17.531) / 2, electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2, rotate_main_connector_box_angle2_right); + + mHalfPSU->AddNode(connector, 0, trans_connector1_front); + mHalfPSU->AddNode(connector, 0, trans_connector2_front); + mHalfPSU->AddNode(connector, 0, trans_connector3_front); + mHalfPSU->AddNode(connector, 0, trans_connector4_front); - string_all_DCDC_coil_shape1 += "+rotated_DCDC_side_coil_shape:tsurfaceBox_square_sub_right2 + rotated_DCDC_side_coil_shape:tsurfaceBox_square_sub_left2"; + TGeoCombiTrans* trans_connector1_back = new TGeoCombiTrans("trans_connector1_back", +(17.064 + 15.397) / 2., -(21.795 + 19.758) / 2, -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2), rotate_main_connector_box_angle1_left); + TGeoCombiTrans* trans_connector2_back = new TGeoCombiTrans("trans_connector2_back", +(19.345 + 17.941) / 2, -(19.757 + 17.531) / 2, -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2), rotate_main_connector_box_angle2_left); + TGeoCombiTrans* trans_connector3_back = new TGeoCombiTrans("trans_connector1_back", -(17.064 + 15.397) / 2., -(21.795 + 19.758) / 2, -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2), rotate_main_connector_box_angle1_right); + TGeoCombiTrans* trans_connector4_back = new TGeoCombiTrans("trans_connector2_back", -(19.345 + 17.941) / 2, -(19.757 + 17.531) / 2, -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2), rotate_main_connector_box_angle2_right); - new TGeoCompositeShape("all_DCDC_coil_shape1", string_all_DCDC_coil_shape1); + mHalfPSU->AddNode(connector, 0, trans_connector1_back); + mHalfPSU->AddNode(connector, 0, trans_connector2_back); + mHalfPSU->AddNode(connector, 0, trans_connector3_back); + mHalfPSU->AddNode(connector, 0, trans_connector4_back); - auto* tall_DCDC_coil_shape1 = new TGeoTranslation("tall_DCDC_coil_shape1", 0, 0, middle_board_thickness / 2 + surface_board_thickness + DCDC_thickness2 + DCDC_coil_radius1); - auto* tall_DCDC_coil_shape2 = new TGeoTranslation("tall_DCDC_coil_shape2", 0, 0, -(middle_board_thickness / 2 + surface_board_thickness + DCDC_thickness2 + DCDC_coil_radius1)); - tall_DCDC_coil_shape1->RegisterYourself(); - tall_DCDC_coil_shape2->RegisterYourself(); + //large connector bottom + + Double_t main_large_connector_bottom_angle1 = 36 * TMath::Pi() / 180.; - TGeoCompositeShape* two_side_all_DCDC_coil_shape1 = new TGeoCompositeShape("two_side_all_DCDC_coil_shape1", - "all_DCDC_coil_shape1:tall_DCDC_coil_shape1+" - "all_DCDC_coil_shape1:tall_DCDC_coil_shape2"); - TGeoVolume* DCDC_coil1 = new TGeoVolume("DCDC_coil1", two_side_all_DCDC_coil_shape1, kMedCu); + Double_t main_large_connector1_thickness = 0.752; + Double_t main_large_connector1_width = 3.95; + Double_t main_large_connector1_height = 0.16; - mHalfPSU->AddNode(DCDC_coil1, 1, nullptr); - //TGeoTranslation* tHalfPSU = new TGeoTranslation("tHalfPSU",0, -4.2 - (middleBox_sub_height1/2-surfaceBox_edge_height1/2), -72.6 + 46.0); - //TGeoTranslation* tHalfPSU = new TGeoTranslation("tHalfPSU",0,0, -72.6 + 46.0); - //tHalfPSU->RegisterYourself(); - //mHalfVolume->AddNode(mHalfPSU,0,tHalfPSU); + Double_t main_large_connector2_thickness = 0.56; + Double_t main_large_connector2_width = 3.95; + Double_t main_large_connector2_height = 0.536; + + Double_t main_large_connector3_thickness = 0.626; + Double_t main_large_connector3_width = 4.167; + Double_t main_large_connector3_height = 0.579; + + TGeoBBox* large_connector_bottom1_box = new TGeoBBox("large_connector1_box", main_large_connector1_width / 2., main_large_connector1_height / 2., main_large_connector1_thickness / 2.); + TGeoBBox* large_connector_bottom2_box = new TGeoBBox("large_connector2_box", main_large_connector2_width / 2., main_large_connector2_height / 2., main_large_connector2_thickness / 2.); + TGeoBBox* large_connector_bottom3_box = new TGeoBBox("large_connector3_box", main_large_connector3_width / 2., main_large_connector3_height / 2., main_large_connector3_thickness / 2.); + + TGeoTranslation* trans_large_connector1_box = new TGeoTranslation("trans_large_connector1_box", 0, -main_large_connector3_height / 2. - main_large_connector2_height - main_large_connector1_height / 2., 0); + TGeoTranslation* trans_large_connector2_box = new TGeoTranslation("trans_large_connector2_box", 0, -main_large_connector3_height / 2. - main_large_connector2_height / 2., 0); + TGeoTranslation* trans_large_connector3_box = new TGeoTranslation("trans_large_connector3_box", 0, 0, 0); + trans_large_connector1_box->RegisterYourself(); + trans_large_connector2_box->RegisterYourself(); + trans_large_connector3_box->RegisterYourself(); + + TGeoCompositeShape* comp_large_connector_box = new TGeoCompositeShape("comp_large_connector_box", "large_connector1_box:trans_large_connector1_box+large_connector2_box:trans_large_connector2_box+large_connector3_box:trans_large_connector3_box"); + + TGeoRotation* rotate_large_connector_bottom_box_front = new TGeoRotation("rotate_large_connector_bottom_box_front", 0, 0, -(90 - main_large_connector_bottom_angle1 * 180 / TMath::Pi())); + TGeoRotation* rotate_large_connector_bottom_box_back = new TGeoRotation("rotate_large_connector_bottom_box_back", 0, 0, (90 - main_large_connector_bottom_angle1 * 180 / TMath::Pi())); + rotate_large_connector_bottom_box_front->RegisterYourself(); + rotate_large_connector_bottom_box_back->RegisterYourself(); + + TGeoCombiTrans* combtrans_rotated_large_connector_front = new TGeoCombiTrans("combtrans_rotated_large_connector_front", -(22.268 + 20.287) / 2, (-17.315 - 13.603) / 2, +(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2), rotate_large_connector_bottom_box_front); + TGeoCombiTrans* combtrans_rotated_large_connector_back = new TGeoCombiTrans("combtrans_rotated_large_connector_back", +(22.268 + 20.287) / 2, (-17.315 - 13.603) / 2, -(electric_board_position_z + electric_board_thickness / 2 + main_connector3_thickness / 2), rotate_large_connector_bottom_box_back); + + TGeoVolume* large_connector = new TGeoVolume("large_connector", comp_large_connector_box, kMedPeek); + large_connector->SetLineColor(kGray + 2); + + mHalfPSU->AddNode(large_connector, 0, combtrans_rotated_large_connector_front); + mHalfPSU->AddNode(large_connector, 0, combtrans_rotated_large_connector_back); return mHalfPSU; } From 6e351e34a4cef4ae350de413d826f64cf2826e95 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 22 Jul 2020 16:33:15 +0200 Subject: [PATCH 0143/1751] DPL driver: allow {timeslice0} and {timeslice1} in --environment (#4026) When passing environment to a pipelined process, one can use `{timeslice0}` (0 based index) or `{timeslice1}` (1 based) which will be substituted with the actual timeslice of the given dataprocessor. --- Framework/Core/src/runDataProcessing.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 00bd0341e2b4a..0b7743272dfff 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -415,7 +415,11 @@ void spawnDevice(std::string const& forwardedStdin, } } for (auto& env : execution.environ) { - putenv(env); + char* formatted = strdup(fmt::format(env, + fmt::arg("timeslice0", spec.inputTimesliceId), + fmt::arg("timeslice1", spec.inputTimesliceId + 1)) + .c_str()); + putenv(formatted); } execvp(execution.args[0], execution.args.data()); } From 8c6ff964b2a3ec5a9e88496617f2e6266ca5e6c8 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 19 Jul 2020 14:36:01 +0200 Subject: [PATCH 0144/1751] GPU: Add some options of future PRs before rework of configuration framework --- GPU/GPUTracking/Base/GPUSettings.cxx | 1 + GPU/GPUTracking/Base/GPUSettings.h | 1 + GPU/GPUTracking/Standalone/qconfigoptions.h | 1 + GPU/GPUTracking/Standalone/standalone.cxx | 1 + 4 files changed, 4 insertions(+) diff --git a/GPU/GPUTracking/Base/GPUSettings.cxx b/GPU/GPUTracking/Base/GPUSettings.cxx index 5b3cabcd1c482..7aa1f4f3f977d 100644 --- a/GPU/GPUTracking/Base/GPUSettings.cxx +++ b/GPU/GPUTracking/Base/GPUSettings.cxx @@ -104,6 +104,7 @@ void GPUSettingsDeviceProcessing::SetDefaults() nTPCClustererLanes = 3; registerStandaloneInputMemory = false; tpcCompressionGatherMode = -1; + tpcCompressionGatherModeKernel = -1; mergerSortTracks = -1; runMC = false; memoryScalingFactor = 1.f; diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index 2b637a9eed481..92c16d2129714 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -165,6 +165,7 @@ struct GPUSettingsDeviceProcessing { bool deviceTimers; // Use device timers instead of host-based timers bool registerStandaloneInputMemory; // Automatically register memory for the GPU which is used as input for the standalone benchmark int tpcCompressionGatherMode; // Modes: 0 = gather by DMA, 1 = DMA + gather on host, 2 = gather by kernel + int tpcCompressionGatherModeKernel; // Kernels: 0 = unbuffered, 1 = buffer in shm (4 byte chunks), 2 = buffer in shm (8 byte chunks), 3 = buffer in shm (16 byte chunks) char mergerSortTracks; // Sort track indices for GPU track fit bool runMC; // Process MC labels float memoryScalingFactor; // Factor to apply to all memory scalers diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index 494ac73c11e04..c5123bf096a85 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -97,6 +97,7 @@ AddOption(mergerSortTracks, int, -1, "mergerSortTracks", 0, "Sort track indizes AddOption(recoSteps, int, -1, "recoSteps", 0, "Bitmask for RecoSteps") AddOption(recoStepsGPU, int, -1, "recoStepsGPU", 0, "Bitmask for RecoSteps") AddOption(tpcCompressionGatherMode, int, -1, "tpcCompressionGatherMode", 0, "TPC Compressed Clusters Gather Mode") +AddOption(tpcCompressionGatherModeKernel, int, -1, "tpcCompressionGatherModeKernel", 0, "TPC Compressed Clusters Gather Mode Kernel") AddOption(runMC, bool, false, "runMC", 0, "Process MC labels") AddOption(ompKernels, bool, false, "ompKernels", 0, "Parallelize with OMP inside kernels instead of over slices") AddOption(doublePipeline, bool, false, "doublePipeline", 0, "Double pipeline mode") diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 10d985c8215f5..bb960ad00f340 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -423,6 +423,7 @@ int SetupReconstruction() } devProc.mergerSortTracks = configStandalone.configProc.mergerSortTracks; devProc.tpcCompressionGatherMode = configStandalone.configProc.tpcCompressionGatherMode; + devProc.tpcCompressionGatherModeKernel = configStandalone.configProc.tpcCompressionGatherModeKernel; steps.steps = GPUDataTypes::RecoStep::AllRecoSteps; if (configStandalone.configRec.runTRD != -1) { From 485d3054fd97f804f35151101feb72490bc49d2b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 15 Jul 2020 18:11:52 +0200 Subject: [PATCH 0145/1751] GPU: Add additional debug information on number of registers / shared memory used by kernels --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index eae5b0f82c556..06ca876ccdfb9 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -656,16 +656,19 @@ int GPUReconstructionCUDABackend::unregisterMemoryForGPU(const void* ptr) void GPUReconstructionCUDABackend::PrintKernelOccupancies() { int maxBlocks, threads, suggestedBlocks; + cudaFuncAttributes attr; GPUFailedMsg(cuCtxPushCurrent(mInternals->CudaContext)); #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) \ GPUFailedMsg(cudaOccupancyMaxPotentialBlockSize(&suggestedBlocks, &threads, GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)))); \ GPUFailedMsg(cudaOccupancyMaxActiveBlocksPerMultiprocessor(&maxBlocks, GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)), threads, 0)); \ - GPUInfo("Kernel: %50s Block size: %4d, Maximum active blocks: %3d, Suggested blocks: %3d", GPUCA_M_STR(GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class))), threads, maxBlocks, suggestedBlocks); + GPUFailedMsg(cudaFuncGetAttributes(&attr, GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)))); \ + GPUInfo("Kernel: %50s Block size: %4d, Maximum active blocks: %3d, Suggested blocks: %3d, Regs: %3d, smem: %3d", GPUCA_M_STR(GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class))), threads, maxBlocks, suggestedBlocks, attr.numRegs, (int)attr.sharedSizeBytes); #define GPUCA_KRNL_LOAD_multi(x_class, x_attributes, x_arguments, x_forward) \ GPUFailedMsg(cudaOccupancyMaxPotentialBlockSize(&suggestedBlocks, &threads, GPUCA_M_CAT3(krnl_, GPUCA_M_KRNL_NAME(x_class), _multi))); \ GPUFailedMsg(cudaOccupancyMaxActiveBlocksPerMultiprocessor(&maxBlocks, GPUCA_M_CAT3(krnl_, GPUCA_M_KRNL_NAME(x_class), _multi), threads, 0)); \ - GPUInfo("Kernel: %50s Block size: %4d, Maximum active blocks: %3d, Suggested blocks: %3d", GPUCA_M_STR(GPUCA_M_CAT3(krnl_, GPUCA_M_KRNL_NAME(x_class), _multi)), threads, maxBlocks, suggestedBlocks); + GPUFailedMsg(cudaFuncGetAttributes(&attr, GPUCA_M_CAT3(krnl_, GPUCA_M_KRNL_NAME(x_class), _multi))); \ + GPUInfo("Kernel: %50s Block size: %4d, Maximum active blocks: %3d, Suggested blocks: %3d, Regs: %3d, smem: %3d", GPUCA_M_STR(GPUCA_M_CAT3(krnl_, GPUCA_M_KRNL_NAME(x_class), _multi)), threads, maxBlocks, suggestedBlocks, attr.numRegs, (int)attr.sharedSizeBytes); #include "GPUReconstructionKernels.h" #undef GPUCA_KRNL #undef GPUCA_KRNL_LOAD_single From 8bb550027bbb059bfcb674e8d7acc632ddce76c6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 15 Jul 2020 19:12:03 +0200 Subject: [PATCH 0146/1751] GPU: Use plain variable name for parameter parsing by default, and optname only optionaly --- .../Base/GPUReconstructionTimeframe.cxx | 4 +- GPU/GPUTracking/Standalone/qconfigoptions.h | 242 +++++++++--------- GPU/GPUTracking/Standalone/standalone.cxx | 14 +- GPU/GPUTracking/Standalone/utils/qconfig.cxx | 8 +- GPU/GPUTracking/Standalone/utils/qconfig.h | 43 ++-- 5 files changed, 159 insertions(+), 152 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx index bda4478a41bbd..46ba6bce5bc7b 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx @@ -214,7 +214,7 @@ void GPUReconstructionTimeframe::MergeShiftedEvents() int GPUReconstructionTimeframe::LoadCreateTimeFrame(int iEvent) { - if (config.nTotalInTFEvents && mNTotalCollisions >= config.nTotalInTFEvents) { + if (config.nTotalEventsInTF && mNTotalCollisions >= config.nTotalEventsInTF) { return (2); } @@ -229,7 +229,7 @@ int GPUReconstructionTimeframe::LoadCreateTimeFrame(int iEvent) for (int iTrain = 0; iTrain < config.bunchTrainCount && nBunch < lastBunch; iTrain++) { int nCollisionsInTrain = 0; for (int iBunch = 0; iBunch < config.bunchCount && nBunch < lastBunch; iBunch++) { - const bool inTF = nBunch >= 0 && nBunch < lastTFBunch && (config.nTotalInTFEvents == 0 || nCollisions < mNTotalCollisions + config.nTotalInTFEvents); + const bool inTF = nBunch >= 0 && nBunch < lastTFBunch && (config.nTotalEventsInTF == 0 || nCollisions < mNTotalCollisions + config.nTotalEventsInTF); if (mcMin == -1 && inTF) { mcMin = mChain->mIOPtrs.nMCInfosTPC; } diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index c5123bf096a85..c265ce9b47c18 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -13,176 +13,176 @@ // clang-format off BeginSubConfig(structConfigGL, configGL, configStandalone, "GL", 'g', "OpenGL display settings") -AddOption(clustersOnly, bool, false, "clustersOnly", 0, "Visualize clusters only") +AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") AddHelp("help", 'h') EndConfig() BeginSubConfig(structConfigTF, configTF, configStandalone, "TF", 't', "Timeframe settings") -AddOption(nMerge, int, 0, "merge", 0, "Merge n events in a timeframe", min(0)) -AddOption(averageDistance, float, 50., "mergeDist", 0, "Average distance in cm of events merged into timeframe", min(0.f)) -AddOption(randomizeDistance, bool, true, "mergeRand", 0, "Randomize distance around average distance of merged events") -AddOption(shiftFirstEvent, bool, true, "mergeFirst", 0, "Also shift the first event in z when merging events to a timeframe") -AddOption(bunchSim, int, 0, "simBunches", 0, "Simulate correct bunch interactions instead of placing only the average number of events. A value [n] > 1 sets TFlen for [n] collisions in average. (Incompatible to TFmerge)") -AddOption(bunchCount, int, 12, "bunchCount", 0, "Number of bunches per train") -AddOption(bunchSpacing, int, 50, "bunchSpacing", 0, "Spacing between benches in ns") -AddOption(bunchTrainCount, int, 48, "bunchTrainCount", 0, "Number of bunch trains") -AddOption(abortGapTime, int, (3000), "abortGap", 0, "Length of abort gap in ns") -AddOption(interactionRate, int, 50000, "rate", 0, "Instantaneous interaction rate") -AddOption(timeFrameLen, long long int, (1000000000 / 44), "len", 'l', "Timeframe len in ns") -AddOption(noBorder, bool, false, "noBorder", 0, "Do not simulate border effects (partial events)") -AddOption(noEventRepeat, int, 0, "noEventRepeat", 0, "0: Place random events, 1: Place events in timeframe one after another, 2: Place random events but do not repat", def(1)) -AddOption(nTotalInTFEvents, int, 0, "nTotal", 0, "Total number of collisions to be placed in the interior of all time frames (excluding borders)") -AddOption(eventStride, int, 0, "eventStride", 0, "Do not select random event, but walk over array of events in stride steps") -AddOption(overlayRaw, bool, false, "overlayRaw", 0, "Overlay raw TPC data instead of spatial clusters") +AddOption(nMerge, int, 0, "", 0, "Merge n events in a timeframe", min(0)) +AddOption(averageDistance, float, 50., "", 0, "Average distance in cm of events merged into timeframe", min(0.f)) +AddOption(randomizeDistance, bool, true, "", 0, "Randomize distance around average distance of merged events") +AddOption(shiftFirstEvent, bool, true, "", 0, "Also shift the first event in z when merging events to a timeframe") +AddOption(bunchSim, int, 0, "", 0, "Simulate correct bunch interactions instead of placing only the average number of events. A value [n] > 1 sets TFlen for [n] collisions in average. (Incompatible to TFmerge)") +AddOption(bunchCount, int, 12, "", 0, "Number of bunches per train") +AddOption(bunchSpacing, int, 50, "", 0, "Spacing between benches in ns") +AddOption(bunchTrainCount, int, 48, "", 0, "Number of bunch trains") +AddOption(abortGapTime, int, (3000), "", 0, "Length of abort gap in ns") +AddOption(interactionRate, int, 50000, "", 0, "Instantaneous interaction rate") +AddOption(timeFrameLen, long long int, (1000000000 / 44), "", 'l', "Timeframe len in ns") +AddOption(noBorder, bool, false, "", 0, "Do not simulate border effects (partial events)") +AddOption(noEventRepeat, int, 0, "", 0, "0: Place random events, 1: Place events in timeframe one after another, 2: Place random events but do not repat", def(1)) +AddOption(nTotalEventsInTF, int, 0, "", 0, "Total number of collisions to be placed in the interior of all time frames (excluding borders)") +AddOption(eventStride, int, 0, "", 0, "Do not select random event, but walk over array of events in stride steps") +AddOption(overlayRaw, bool, false, "", 0, "Overlay raw TPC data instead of spatial clusters") AddHelp("help", 'h') EndConfig() BeginSubConfig(structConfigQA, configQA, configStandalone, "QA", 'q', "QA settings") -AddOptionVec(compareInputs, const char*, "input", 0, "Read histogram from these input files and include them in the output plots") -AddOptionVec(compareInputNames, const char*, "inputName", 0, "Legend entries for data from comparison histogram files") -AddOption(name, const char*, nullptr, "name", 0, "Legend entry for new data from current processing") -AddOption(output, const char*, nullptr, "histOut", 0, "Store histograms in output root file", def("histograms.root")) -AddOption(inputHistogramsOnly, bool, false, "only", 0, "Do not run tracking, but just create PDFs from input root files") -AddOption(strict, bool, true, "strict", 0, "Strict QA mode: Only consider resolution of tracks where the fit ended within 5 cm of the reference, and remove outliers.") -AddOption(qpt, float, 10.f, "qpt", 0, "Set cut for Q/Pt", def(2.f)) -AddOption(recThreshold, float, 0.9f, "recThreshold", 0, "Compute the efficiency including impure tracks with fake contamination") -AddOption(csvDump, bool, false, "csvDump", 0, "Dump all clusters and Pt information into csv file") -AddOption(maxResX, float, 1e6f, "maxResX", 0, "Maxmimum X (~radius) for reconstructed track position to take into accound for resolution QA in cm") -AddOption(resPrimaries, int, 0, "resPrimaries", 0, "0: Resolution for all tracks, 1: only for primary tracks, 2: only for non-primaries", def(1)) -AddOption(nativeFitResolutions, bool, false, "nativeFitResolutions", 0, "Create resolution histograms in the native fit units (sin(phi), tan(lambda), Q/Pt)") -AddOption(filterCharge, int, 0, "filterCharge", 0, "Filter for positive (+1) or negative (-1) charge") -AddOption(filterPID, int, -1, "filterPID", 0, "Filter for Particle Type (0 Electron, 1 Muon, 2 Pion, 3 Kaon, 4 Proton)") -AddOption(writeMCLabels, bool, false, "writeLabels", 0, "Store mc labels to file for later matching") -AddOptionVec(matchMCLabels, const char*, "matchLabels", 0, "Read labels from files and match them, only process tracks where labels differ") -AddOption(matchDisplayMinPt, float, 0, "matchDisplayMinPt", 0, "Minimum Pt of a matched track to be displayed") -AddOption(writeRootFiles, bool, false, "root", 0, "Create ROOT canvas files") -AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAonly") +AddOptionVec(compareInputs, const char*, "QAinput", 0, "Read histogram from these input files and include them in the output plots") +AddOptionVec(compareInputNames, const char*, "QAinputName", 0, "Legend entries for data from comparison histogram files") +AddOption(name, const char*, nullptr, "", 0, "Legend entry for new data from current processing") +AddOption(output, const char*, nullptr, "", 0, "Store histograms in output root file", def("histograms.root")) +AddOption(inputHistogramsOnly, bool, false, "", 0, "Do not run tracking, but just create PDFs from input root files") +AddOption(strict, bool, true, "", 0, "Strict QA mode: Only consider resolution of tracks where the fit ended within 5 cm of the reference, and remove outliers.") +AddOption(qpt, float, 10.f, "", 0, "Set cut for Q/Pt", def(2.f)) +AddOption(recThreshold, float, 0.9f, "", 0, "Compute the efficiency including impure tracks with fake contamination") +AddOption(csvDump, bool, false, "", 0, "Dump all clusters and Pt information into csv file") +AddOption(maxResX, float, 1e6f, "", 0, "Maxmimum X (~radius) for reconstructed track position to take into accound for resolution QA in cm") +AddOption(resPrimaries, int, 0, "", 0, "0: Resolution for all tracks, 1: only for primary tracks, 2: only for non-primaries", def(1)) +AddOption(nativeFitResolutions, bool, false, "", 0, "Create resolution histograms in the native fit units (sin(phi), tan(lambda), Q/Pt)") +AddOption(filterCharge, int, 0, "", 0, "Filter for positive (+1) or negative (-1) charge") +AddOption(filterPID, int, -1, "", 0, "Filter for Particle Type (0 Electron, 1 Muon, 2 Pion, 3 Kaon, 4 Proton)") +AddOption(writeMCLabels, bool, false, "", 0, "Store mc labels to file for later matching") +AddOptionVec(matchMCLabels, const char*, "", 0, "Read labels from files and match them, only process tracks where labels differ") +AddOption(matchDisplayMinPt, float, 0, "", 0, "Minimum Pt of a matched track to be displayed") +AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") +AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") AddHelp("help", 'h') EndConfig() BeginSubConfig(structConfigEG, configEG, configStandalone, "EG", 0, "Event generator settings") -AddOption(numberOfTracks, int, 1, "numberOfTracks", 0, "Number of tracks per generated event") +AddOption(numberOfTracks, int, 1, "", 0, "Number of tracks per generated event") AddHelp("help", 'h') EndConfig() BeginSubConfig(structConfigRec, configRec, configStandalone, "REC", 0, "Reconstruction settings") -AddOption(globalTracking, bool, true, "globalTracking", 0, "Enable global tracking") -AddOption(runTRD, int, -1, "trd", 0, "Enable TRD processing") -AddOption(rundEdx, int, 1, "dEdx", 0, "Enable dEdx processing") -AddOption(runCompression, int, 1, "compression", 0, "Enable TPC Compression") -AddOption(runTransformation, int, 1, "transformation", 0, "Enable TPC Transformation") -AddOption(disableRefitAttachment, int, 0, "refitAttachmentMask", 0, "Mask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") -AddOption(tpcReject, int, -1, "tpcReject", 0, "Enable rejection of TPC clusters for compression (-1 = default, 0 = no, 1 = strategy A, 2 = strategy B)") -AddOption(tpcRejectThreshold, float, 0.f, "tpcRejectThreshold", 0, "Pt threshold to reject clusters of TPC tracks") -AddOption(tpcCompression, int, 7, "tpcCompression", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") -AddOption(tpcCompressionSort, int, 0, "tpcCompressionSort", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") -AddOption(ForceEarlyTPCTransform, int, -1, "ForceEarlyTPCTransform", 0, "Force early TPC transformation also for continuous data (-1 = auto)") -AddOption(fwdTPCDigitsAsClusters, bool, false, "forwardTPCdigits", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") -AddOption(dropLoopers, bool, false, "dropLoopers", 0, "Drop looping tracks starting from second loop") -AddOption(mergerCovSource, int, -1, "mergerCovSource", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following") -AddOption(mergerInterpolateErrors, int, -1, "mergerInterpolateErrors", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") -AddOption(fitInProjections, int, -1, "fitInProjections", 0, "Fit in projection, -1 to enable for all but passes but the first one") -AddOption(fitPropagateBzOnly, int, -1, "fitPropagateBzOnly", 0, "Propagate using Bz only for n passes") -AddOption(retryRefit, int, -1, "retryRefit", 0, "Retry refit when fit fails") -AddOption(loopInterpolationInExtraPass, int, -1, "loopPass", 0, "Perform loop interpolation in an extra pass") -AddOption(mergerReadFromTrackerDirectly, bool, true, "mergerReadFromTrackerDirectly", 0, "Forward data directly from tracker to merger on GPU") +AddOption(globalTracking, bool, true, "", 0, "Enable global tracking") +AddOption(runTRD, int, -1, "", 0, "Enable TRD processing") +AddOption(rundEdx, int, 1, "", 0, "Enable dEdx processing") +AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") +AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") +AddOption(disableRefitAttachment, int, 0, "", 0, "Mask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") +AddOption(tpcReject, int, -1, "", 0, "Enable rejection of TPC clusters for compression (-1 = default, 0 = no, 1 = strategy A, 2 = strategy B)") +AddOption(tpcRejectThreshold, float, 0.f, "", 0, "Pt threshold to reject clusters of TPC tracks") +AddOption(tpcCompression, int, 7, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") +AddOption(tpcCompressionSort, int, 0, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") +AddOption(ForceEarlyTPCTransform, int, -1, "", 0, "Force early TPC transformation also for continuous data (-1 = auto)") +AddOption(fwdTPCDigitsAsClusters, bool, false, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") +AddOption(dropLoopers, bool, false, "", 0, "Drop looping tracks starting from second loop") +AddOption(mergerCovSource, int, -1, "", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following") +AddOption(mergerInterpolateErrors, int, -1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") +AddOption(fitInProjections, int, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") +AddOption(fitPropagateBzOnly, int, -1, "", 0, "Propagate using Bz only for n passes") +AddOption(retryRefit, int, -1, "", 0, "Retry refit when fit fails") +AddOption(loopInterpolationInExtraPass, int, -1, "", 0, "Perform loop interpolation in an extra pass") +AddOption(mergerReadFromTrackerDirectly, bool, true, "", 0, "Forward data directly from tracker to merger on GPU") AddHelp("help", 'h') EndConfig() BeginSubConfig(structConfigProc, configProc, configStandalone, "PROC", 0, "Processing settings") -AddOption(nStreams, int, -1, "nStreams", 0, "Number of GPU streams / command queues") -AddOption(constructorPipeline, int, -1, "constructorPipeline", 0, "Run tracklet constructor in pipeline") -AddOption(selectorPipeline, int, -1, "selectorPipeline", 0, "Run tracklet selector in pipeline") -AddOption(mergerSortTracks, int, -1, "mergerSortTracks", 0, "Sort track indizes for GPU track fit") -AddOption(recoSteps, int, -1, "recoSteps", 0, "Bitmask for RecoSteps") -AddOption(recoStepsGPU, int, -1, "recoStepsGPU", 0, "Bitmask for RecoSteps") -AddOption(tpcCompressionGatherMode, int, -1, "tpcCompressionGatherMode", 0, "TPC Compressed Clusters Gather Mode") -AddOption(tpcCompressionGatherModeKernel, int, -1, "tpcCompressionGatherModeKernel", 0, "TPC Compressed Clusters Gather Mode Kernel") -AddOption(runMC, bool, false, "runMC", 0, "Process MC labels") -AddOption(ompKernels, bool, false, "ompKernels", 0, "Parallelize with OMP inside kernels instead of over slices") -AddOption(doublePipeline, bool, false, "doublePipeline", 0, "Double pipeline mode") -AddOption(prefetchTPCpageScan, int, 0, "prefetchTPCpageScan", 0, "Prefetch Data for TPC page scan in CPU cache") +AddOption(nStreams, int, -1, "", 0, "Number of GPU streams / command queues") +AddOption(constructorPipeline, int, -1, "", 0, "Run tracklet constructor in pipeline") +AddOption(selectorPipeline, int, -1, "", 0, "Run tracklet selector in pipeline") +AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fit") +AddOption(recoSteps, int, -1, "", 0, "Bitmask for RecoSteps") +AddOption(recoStepsGPU, int, -1, "", 0, "Bitmask for RecoSteps") +AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode") +AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") +AddOption(runMC, bool, false, "", 0, "Process MC labels") +AddOption(ompKernels, bool, false, "", 0, "Parallelize with OMP inside kernels instead of over slices") +AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") +AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") AddHelp("help", 'h') EndConfig() BeginConfig(structConfigStandalone, configStandalone) #if defined(CUDA_ENABLED) || defined(OPENCL1_ENABLED) || defined(HIP_ENABLED) -AddOption(runGPU, bool, true, "gpu", 'g', "Use GPU for processing", message("GPU processing: %s")) +AddOption(runGPU, bool, true, "", 'g', "Use GPU for processing", message("GPU processing: %s")) #else -AddOption(runGPU, bool, false, "gpu", 'g', "Use GPU for processing", message("GPU processing: %s")) +AddOption(runGPU, bool, false, "", 'g', "Use GPU for processing", message("GPU processing: %s")) #endif -AddOptionSet(runGPU, bool, false, "cpu", 'c', "Use CPU for processing", message("CPU enabled")) +AddOptionSet(runGPU, bool, false, "", 'c', "Use CPU for processing", message("CPU enabled")) #if defined(CUDA_ENABLED) -AddOption(gpuType, const char*, "CUDA", "gpuType", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +AddOption(gpuType, const char*, "CUDA", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") #elif defined(OPENCL2_ENABLED) -AddOption(gpuType, const char*, "OCL2", "gpuType", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +AddOption(gpuType, const char*, "OCL2", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") #elif defined(OPENCL1_ENABLED) -AddOption(gpuType, const char*, "OCL", "gpuType", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +AddOption(gpuType, const char*, "OCL", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") #elif defined(HIP_ENABLED) -AddOption(gpuType, const char*, "HIP", "gpuType", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +AddOption(gpuType, const char*, "HIP", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") #else -AddOption(gpuType, const char*, "", "gpuType", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +AddOption(gpuType, const char*, "", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") #endif -AddOption(runGPUforce, bool, true, "gpuForce", 0, "Force usage of the specified GPU device type, no CPU fallback") -AddOption(gpuInitMutex, bool, false, "gpuInitMutex", 0, "Use mutex to synchronize initialization of multiple GPU instances") -AddOption(oclGPUonly, bool, false, "oclGPUonly", 0, "Allow only GPU as OpenCL device") -AddOption(helperThreads, int, 1, "helperThreads", 0, "Number of CPU helper threads for CPU processing") -AddOption(noprompt, bool, true, "prompt", 0, "Do prompt for keypress before exiting", def(false)) -AddOption(continueOnError, bool, false, "continue", 0, "Continue processing after an error") +AddOption(runGPUforce, bool, true, "", 0, "Force usage of the specified GPU device type, no CPU fallback") +AddOption(gpuInitMutex, bool, false, "", 0, "Use mutex to synchronize initialization of multiple GPU instances") +AddOption(oclGPUonly, bool, false, "", 0, "Allow only GPU as OpenCL device") +AddOption(helperThreads, int, 1, "", 0, "Number of CPU helper threads for CPU processing") +AddOption(noprompt, bool, true, "", 0, "Do prompt for keypress before exiting") +AddOption(continueOnError, bool, false, "", 0, "Continue processing after an error") AddOption(DebugLevel, int, 0, "debug", 'd', "Set debug level") AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Set alloc debug level") -AddOption(DeviceTiming, bool, true, "deviceTiming", 0, "Use device timers instead of host-based time measurement") -AddOption(seed, int, -1, "seed", 0, "Set srand seed (-1: random)") -AddOption(cleardebugout, bool, false, "clearDebugFile", 0, "Clear debug output file when processing next event") -AddOption(cudaDevice, int, -1, "gpuDevice", 0, "Set GPU device to use (-1: automatic)") -AddOption(StartEvent, int, 0, "s", 's', "First event to process", min(0)) -AddOption(NEvents, int, -1, "n", 'n', "Number of events to process (-1; all)", min(0)) -AddOption(merger, int, 1, "runMerger", 0, "Run track merging / refit", min(0), max(1)) +AddOption(DeviceTiming, bool, true, "", 0, "Use device timers instead of host-based time measurement") +AddOption(seed, int, -1, "", 0, "Set srand seed (-1: random)") +AddOption(cleardebugout, bool, false, "", 0, "Clear debug output file when processing next event") +AddOption(deviceNum, int, -1, "", 0, "Set GPU device to use (-1: automatic)") +AddOption(StartEvent, int, 0, "", 's', "First event to process", min(0)) +AddOption(NEvents, int, -1, "", 'n', "Number of events to process (-1; all)", min(0)) +AddOption(merger, int, 1, "", 0, "Run track merging / refit", min(0), max(1)) AddOption(runs, int, 1, "runs", 'r', "Number of iterations to perform (repeat each event)", min(0)) AddOption(runs2, int, 1, "runsExternal", 0, "Number of iterations to perform (repeat full processing)", min(1)) -AddOption(runsInit, int, 1, "runsInit", 0, "Number of initial iterations excluded from average", min(0)) +AddOption(runsInit, int, 1, "", 0, "Number of initial iterations excluded from average", min(0)) AddOption(EventsDir, const char*, "pp", "events", 'e', "Directory with events to process", message("Reading events from Directory events/%s")) AddOption(OMPThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %d OMP threads")) AddOption(eventDisplay, int, 0, "display", 'd', "Show standalone event display", def(1)) //1: default display (Windows / X11), 2: glut, 3: glfw -AddOption(qa, bool, false, "qa", 'q', "Enable tracking QA", message("Running QA: %s")) -AddOption(eventGenerator, bool, false, "eventGenerator", 0, "Run event generator") -AddOption(nways, int, 3, "NWays", 0, "Use n-way track-fit", min(1)) +AddOption(qa, bool, false, "", 'q', "Enable tracking QA", message("Running QA: %s")) +AddOption(eventGenerator, bool, false, "", 0, "Run event generator") +AddOption(nways, int, 3, "", 0, "Use n-way track-fit", min(1)) AddOptionSet(nways, int, 3, "3Way", 0, "Use 3-way track-fit") AddOptionSet(nways, int, 1, "1Way", 0, "Use 3-way track-fit") -AddOption(nwaysouter, bool, false, "OuterParam", 0, "Create OuterParam") -AddOption(dzdr, float, 2.5f, "DzDr", 0, "Use dZ/dR search window instead of vertex window") -AddOption(cont, bool, false, "continuous", 0, "Process continuous timeframe data") +AddOption(nwaysouter, bool, false, "", 0, "Create OuterParam") +AddOption(dzdr, float, 2.5f, "", 0, "Use dZ/dR search window instead of vertex window") +AddOption(cont, bool, false, "", 0, "Process continuous timeframe data") AddOption(forceMemorySize, unsigned long long int, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ull)) AddOption(forceHostMemorySize, unsigned long long int, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ull)) -AddOption(memoryScalingFactor, float, 1.f, "memoryScalingFactor", 0, "Factor to apply to all memory scalers") +AddOption(memoryScalingFactor, float, 1.f, "", 0, "Factor to apply to all memory scalers") AddOption(outputcontrolmem, unsigned long long int, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ull), message("Using %lld bytes as output memory")) AddOption(inputcontrolmem, unsigned long long int, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ull), message("Using %lld bytes as input memory")) -AddOption(registerInputMemory, bool, false, "registerInputMemory", 0, "Automatically register input memory buffers for the GPU") -AddOption(affinity, int, -1, "cpuAffinity", 0, "Pin CPU affinity to this CPU core", min(-1)) -AddOption(fifo, bool, false, "fifoScheduler", 0, "Use FIFO realtime scheduler", message("Setting FIFO scheduler: %s")) -AddOption(fpe, bool, true, "fpe", 0, "Trap on floating point exceptions") -AddOption(flushDenormals, bool, true, "flushDenormals", 0, "Enable FTZ and DAZ (Flush all denormals to zero)") -AddOption(solenoidBz, float, -1e6f, "solenoidBz", 0, "Field strength of solenoid Bz in kGaus") -AddOption(constBz, bool, false, "constBz", 0, "Force constand Bz") -AddOption(overrideMaxTimebin, bool, false, "overrideMaxTimebin", 0, "Override max time bin setting for continuous data with max time bin in time frame") -AddOption(encodeZS, int, -1, "encodeZS", 0, "Zero-Suppress TPC data", def(1)) -AddOption(zsFilter, int, -1, "zsFilter", 0, "Apply Zero-Suppression when loading digits and remove those below threshold", def(1)) -AddOption(zsThreshold, float, 2.0f, "zsThreshold", 0, "Zero-Suppression threshold") -AddOption(zs12bit, bool, true, "zs12bit", 0, "Perform 12 bit zero-suppression encoding / filter") -AddOption(dumpEvents, bool, false, "dumpEvents", 0, "Dump events (after transformation such as encodeZS") -AddOption(stripDumpedEvents, bool, false, "stripDumpedEvents", 0, "Remove redundant inputs (e.g. digits and ZS) before dumping") -AddOption(referenceX, float, 500.f, "referenceX", 0, "Reference X position to transport track to after fit") -AddOption(rejectMode, char, 5, "rejectMode", 0, "Merger Reject Mode") -AddOption(allocationStrategy, int, 0, "allocationStrategy", 0, "Memory Allocation Stragegy (0 = auto, 1 = individual allocations, 2 = single global allocation)") -AddOption(printSettings, bool, false, "printSettings", 0, "Print all settings") -AddOption(compressionStat, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") -AddOption(memoryStat, bool, false, "memoryStat", 0, "Print memory statistics") +AddOption(registerInputMemory, bool, false, "", 0, "Automatically register input memory buffers for the GPU") +AddOption(cpuAffinity, int, -1, "", 0, "Pin CPU affinity to this CPU core", min(-1)) +AddOption(fifoScheduler, bool, false, "", 0, "Use FIFO realtime scheduler", message("Setting FIFO scheduler: %s")) +AddOption(fpe, bool, true, "", 0, "Trap on floating point exceptions") +AddOption(flushDenormals, bool, true, "", 0, "Enable FTZ and DAZ (Flush all denormals to zero)") +AddOption(solenoidBz, float, -1e6f, "", 0, "Field strength of solenoid Bz in kGaus") +AddOption(constBz, bool, false, "", 0, "Force constand Bz") +AddOption(overrideMaxTimebin, bool, false, "", 0, "Override max time bin setting for continuous data with max time bin in time frame") +AddOption(encodeZS, int, -1, "", 0, "Zero-Suppress TPC data", def(1)) +AddOption(zsFilter, int, -1, "", 0, "Apply Zero-Suppression when loading digits and remove those below threshold", def(1)) +AddOption(zsThreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") +AddOption(zs12bit, bool, true, "", 0, "Perform 12 bit zero-suppression encoding / filter") +AddOption(dumpEvents, bool, false, "", 0, "Dump events (after transformation such as encodeZS") +AddOption(stripDumpedEvents, bool, false, "", 0, "Remove redundant inputs (e.g. digits and ZS) before dumping") +AddOption(referenceX, float, 500.f, "", 0, "Reference X position to transport track to after fit") +AddOption(rejectMode, char, 5, "", 0, "Merger Reject Mode") +AddOption(allocationStrategy, int, 0, "", 0, "Memory Allocation Stragegy (0 = auto, 1 = individual allocations, 2 = single global allocation)") +AddOption(printSettings, bool, false, "", 0, "Print all settings") +AddOption(compressionStat, bool, false, "", 0, "Run statistics and verification for cluster compression") +AddOption(memoryStat, bool, false, "", 0, "Print memory statistics") AddOption(testSyncAsync, bool, false, "syncAsync", 0, "Test first synchronous and then asynchronous processing") AddOption(testSync, bool, false, "sync", 0, "Test settings for synchronous phase") AddOption(timeFrameTime, bool, false, "tfTime", 0, "Print some debug information about time frame processing time") -AddOption(controlProfiler, bool, false, "controlProfiler", 0, "Issues GPU profiler stop and start commands to profile only the relevant processing part") -AddOption(alternateBorderSort, int, -1, "alternateBorderSort", 0, "Alternative implementation for sorting of border tracks") -AddOption(preloadEvents, bool, false, "preloadEvents", 0, "Preload events into host memory before start processing") +AddOption(controlProfiler, bool, false, "", 0, "Issues GPU profiler stop and start commands to profile only the relevant processing part") +AddOption(alternateBorderSort, int, -1, "", 0, "Alternative implementation for sorting of border tracks") +AddOption(preloadEvents, bool, false, "", 0, "Preload events into host memory before start processing") AddHelp("help", 'h') AddHelpAll("helpall", 'H') AddSubConfig(structConfigTF, configTF) diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index bb960ad00f340..e7f67fb5385d1 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -120,18 +120,18 @@ int ReadConfiguration(int argc, char** argv) #ifndef _WIN32 setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, ""); - if (configStandalone.affinity != -1) { + if (configStandalone.cpuAffinity != -1) { cpu_set_t mask; CPU_ZERO(&mask); - CPU_SET(configStandalone.affinity, &mask); + CPU_SET(configStandalone.cpuAffinity, &mask); - printf("Setting affinitiy to restrict on CPU core %d\n", configStandalone.affinity); + printf("Setting affinitiy to restrict on CPU core %d\n", configStandalone.cpuAffinity); if (0 != sched_setaffinity(0, sizeof(mask), &mask)) { printf("Error setting CPU affinity\n"); return 1; } } - if (configStandalone.fifo) { + if (configStandalone.fifoScheduler) { printf("Setting FIFO scheduler\n"); sched_param param; sched_getparam(0, ¶m); @@ -149,11 +149,11 @@ int ReadConfiguration(int argc, char** argv) } #else - if (configStandalone.affinity != -1) { + if (configStandalone.cpuAffinity != -1) { printf("Affinity setting not supported on Windows\n"); return 1; } - if (configStandalone.fifo) { + if (configStandalone.fifoScheduler) { printf("FIFO Scheduler setting not supported on Windows\n"); return 1; } @@ -357,7 +357,7 @@ int SetupReconstruction() if (configStandalone.OMPThreads != -1) { devProc.nThreads = configStandalone.OMPThreads; } - devProc.deviceNum = configStandalone.cudaDevice; + devProc.deviceNum = configStandalone.deviceNum; devProc.forceMemoryPoolSize = (configStandalone.forceMemorySize == 1 && configStandalone.eventDisplay) ? 2 : configStandalone.forceMemorySize; devProc.forceHostMemoryPoolSize = configStandalone.forceHostMemorySize; devProc.debugLevel = configStandalone.DebugLevel; diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index 32552fc61a569..6219e48a3d3b5 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -258,7 +258,13 @@ struct qConfigType { argBuffer[argBufferPos++] = preoptshort == 0 ? '-' : preoptshort; argBuffer[argBufferPos++] = optnameshort; } - std::cout << "\t" << name << ": " << argBuffer << (optnameshort == 0 ? "" : arguments) << "--" << preopt << optname << (optnameshort == 0 ? arguments : ", ") << "type: " << type; + std::cout << "\t" << name << ": " << argBuffer << (optnameshort == 0 ? "" : arguments) << "--"; + if (optname[0] == 0) { + std::cout << preopt << name; + } else { + std::cout << optname; + } + std::cout << (optnameshort == 0 ? arguments : ", ") << "type: " << type; if (optionType == 0) { std::cout << ", default: " << def; } diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index e53bc50226fbd..5f13fa94d5050 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -20,12 +20,13 @@ #ifdef QCONFIG_PARSE -#define QCONFIG_COMPARE(optname, optnameshort) \ - (thisoption[0] == '-' && ((preoptshort == 0 && thisoption[1] == optnameshort && thisoption[2] == 0) || (thisoption[1] == '-' && strlen(preopt) == 0 && strcmp(&thisoption[2], optname) == 0) || \ - (preoptshort != 0 && thisoption[1] == preoptshort && thisoption[2] == optnameshort && thisoption[3] == 0) || (thisoption[1] == '-' && strlen(preopt) && strncmp(&thisoption[2], preopt, strlen(preopt)) == 0 && strcmp(&thisoption[2 + strlen(preopt)], optname) == 0))) +#define QCONFIG_COMPARE(name, optname, optnameshort) \ + (thisoption[0] == '-' && ((thisoption[1] == '-' && optname[0] != 0 && strcmp(&thisoption[2], optname) == 0) || \ + (preoptshort == 0 && thisoption[1] == optnameshort && thisoption[2] == 0) || (thisoption[1] == '-' && strlen(preopt) == 0 && strcmp(&thisoption[2], name) == 0) || \ + (preoptshort != 0 && thisoption[1] == preoptshort && thisoption[2] == optnameshort && thisoption[3] == 0) || (thisoption[1] == '-' && strlen(preopt) && strncmp(&thisoption[2], preopt, strlen(preopt)) == 0 && strcmp(&thisoption[2 + strlen(preopt)], name) == 0))) #define AddOption(name, type, default, optname, optnameshort, ...) \ - else if (QCONFIG_COMPARE(optname, optnameshort)) \ + else if (QCONFIG_COMPARE(#name, optname, optnameshort)) \ { \ int retVal = qConfigType<type>::qAddOption(tmp.name, i, argv, argc, default, __VA_ARGS__); \ if (retVal) { \ @@ -34,7 +35,7 @@ } #define AddOptionSet(name, type, value, optname, optnameshort, ...) \ - else if (QCONFIG_COMPARE(optname, optnameshort)) \ + else if (QCONFIG_COMPARE(optname, "", optnameshort)) \ { \ int retVal = qConfigType<type>::qAddOption(tmp.name, i, nullptr, 0, value, __VA_ARGS__, set(value)); \ if (retVal) { \ @@ -43,7 +44,7 @@ } #define AddOptionVec(name, type, optname, optnameshort, ...) \ - else if (QCONFIG_COMPARE(optname, optnameshort)) \ + else if (QCONFIG_COMPARE(#name, optname, optnameshort)) \ { \ int retVal = qConfigType<type>::qAddOptionVec(tmp.name, i, argv, argc, __VA_ARGS__); \ if (retVal) { \ @@ -52,7 +53,7 @@ } #define AddOptionArray(name, type, count, default, optname, optnameshort, ...) \ - else if (QCONFIG_COMPARE(optname, optnameshort)) \ + else if (QCONFIG_COMPARE(#name, optname, optnameshort)) \ { \ int retVal = qConfigType<type>::qAddOptionArray(tmp.name, count, i, argv, argc, __VA_ARGS__); \ if (retVal) { \ @@ -89,24 +90,24 @@ } \ } -#define AddHelp(cmd, cmdshort) \ - else if (QCONFIG_COMPARE(cmd, cmdshort)) \ - { \ - const char* arg = getArg(i, argv, argc); \ - qConfigHelp(arg ? arg : preopt); \ - return (qcrHelp); \ +#define AddHelp(cmd, cmdshort) \ + else if (QCONFIG_COMPARE(cmd, "", cmdshort)) \ + { \ + const char* arg = getArg(i, argv, argc); \ + qConfigHelp(arg ? arg : preopt); \ + return (qcrHelp); \ } -#define AddHelpAll(cmd, cmdshort) \ - else if (QCONFIG_COMPARE(cmd, cmdshort)) \ - { \ - const char* arg = getArg(i, argv, argc); \ - qConfigHelp(arg ? arg : "", true); \ - return (qcrHelp); \ +#define AddHelpAll(cmd, cmdshort) \ + else if (QCONFIG_COMPARE(cmd, "", cmdshort)) \ + { \ + const char* arg = getArg(i, argv, argc); \ + qConfigHelp(arg ? arg : "", true); \ + return (qcrHelp); \ } #define AddCommand(cmd, cmdshort, command, help) \ - else if (QCONFIG_COMPARE(cmd, cmdshort)) \ + else if (QCONFIG_COMPARE(cmd, "", cmdshort)) \ { \ if (command) { \ return (qcrCmd); \ @@ -114,7 +115,7 @@ } #define AddShortcut(cmd, cmdshort, forward, help, ...) \ - else if (QCONFIG_COMPARE(cmd, cmdshort)) \ + else if (QCONFIG_COMPARE(cmd, "", cmdshort)) \ { \ const char* options[] = {"", __VA_ARGS__, nullptr}; \ const int nOptions = sizeof(options) / sizeof(options[0]) - 1; \ From 2c164d3f9903db42e228acf1f33f8ab0dbda2923 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 16 Jul 2020 13:20:22 +0200 Subject: [PATCH 0147/1751] GPU: Move standalone config structures in o2::gpu namespace --- GPU/GPUTracking/Standalone/qconfigoptions.h | 13 ++++++++- GPU/GPUTracking/Standalone/utils/qconfig.h | 32 +++++++++++++++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index c265ce9b47c18..622f83226d695 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -12,7 +12,15 @@ /// \author David Rohr // clang-format off -BeginSubConfig(structConfigGL, configGL, configStandalone, "GL", 'g', "OpenGL display settings") + +#ifdef QCONFIG_INSTANCE +using namespace GPUCA_NAMESPACE::gpu; +#endif +BeginNamespace(GPUCA_NAMESPACE) +BeginNamespace(gpu) + +// Settings concerning the event display +BeginSubConfig(GPUSettingsDisplay, configGL, configStandalone, "GL", 'g', "OpenGL display settings") AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") AddHelp("help", 'h') EndConfig() @@ -192,4 +200,7 @@ AddSubConfig(structConfigGL, configGL) AddSubConfig(structConfigRec, configRec) AddSubConfig(structConfigProc, configProc) EndConfig() + +EndNamespace() // gpu +EndNamespace() // GPUCA_NAMESPACE // clang-format on diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index 5f13fa94d5050..47dcaabb97aea 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -185,7 +185,12 @@ name& tmp = parent.instance; #define EndConfig() } +// End QCONFIG_PRINT #elif defined(QCONFIG_INSTANCE) +#define BeginNamespace(name) \ + namespace name \ + { +#define EndNamespace() } #define AddOption(name, type, default, optname, optnameshort, help, ...) name(default), #define AddVariable(name, type, default) name(default), #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) @@ -224,11 +229,20 @@ enum qConfigRetVal { qcrOK = 0, qcrArrayOverflow = 8 }; } -#else -#ifdef QCONFIG_HEADER_GUARD -#define QCONFIG_HEADER_GUARD_NO_INCLUDE -#else -#define QCONFIG_HEADER_GUARD +#if defined(QCONFIG_EXTERNS) +#define BeginNamespace(name) \ + namespace name \ + { +#define EndNamespace() } +#define AddOption(name, type, default, optname, optnameshort, help, ...) +#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) +#define AddOptionVec(name, type, optname, optnameshort, help, ...) +#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) +#define AddSubConfig(name, instance) +#define BeginConfig(name, instance) extern "C" name instance; +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) +#define EndConfig() +#undef QCONFIG_EXTERNS #if defined(QCONFIG_CPP11_INIT) && !defined(QCONFIG_GPU) #define AddOption(name, type, default, optname, optnameshort, help, ...) type name = default; @@ -245,6 +259,11 @@ enum qConfigRetVal { qcrOK = 0, } \ ; #else +#define BeginNamespace(name) \ + namespace name \ + { +#define EndNamespace() } +#define AddCustomCPP(...) __VA_ARGS__ #define AddOption(name, type, default, optname, optnameshort, help, ...) type name; #define AddVariable(name, type, default) type name; #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) @@ -322,6 +341,9 @@ struct qConfigDummy { #undef AddHelpText #undef AddCommand #undef AddShortcut +#undef BeginNamespace +#undef EndNamespace +#undef AddCustomCPP #ifdef QCONFIG_COMPARE #undef QCONFIG_COMPARE #endif From 40623f3eab29b2e03eb0d0eff91c4f601c5fe32a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 16 Jul 2020 13:21:57 +0200 Subject: [PATCH 0148/1751] GPU: Merge the two GPU settings implementations we had --- .../reconstruction/test/testGPUCATracking.cxx | 2 +- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 4 +- GPU/Common/GPUDefConstantsAndSettings.h | 4 +- GPU/GPUTracking/Base/GPUParam.cxx | 2 +- GPU/GPUTracking/Base/GPUReconstruction.cxx | 20 +- GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 2 +- .../Base/GPUReconstructionConvert.cxx | 4 +- .../Base/GPUReconstructionConvert.h | 2 +- GPU/GPUTracking/Base/GPUSettings.cxx | 94 +-------- GPU/GPUTracking/Base/GPUSettings.h | 131 ++---------- GPU/GPUTracking/Base/opencl/CMakeLists.txt | 1 + GPU/GPUTracking/Global/GPUChainTracking.cxx | 6 +- GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx | 4 +- .../SliceTracker/GPUTPCTracker.cxx | 2 +- .../Standalone/display/GPUDisplay.cxx | 8 +- .../Standalone/display/GPUDisplay.h | 2 +- .../Standalone/display/GPUDisplayConfig.h | 3 +- GPU/GPUTracking/Standalone/qa/GPUQA.h | 2 +- GPU/GPUTracking/Standalone/qa/GPUQAConfig.h | 3 +- GPU/GPUTracking/Standalone/qa/genEvents.cxx | 4 + GPU/GPUTracking/Standalone/qconfigoptions.h | 196 +++++++++++------- GPU/GPUTracking/Standalone/standalone.cxx | 160 ++++---------- GPU/GPUTracking/Standalone/utils/qconfig.cxx | 22 +- GPU/GPUTracking/Standalone/utils/qconfig.h | 45 ++-- .../TRDTracking/GPUTRDTrackerKernels.cxx | 2 +- 25 files changed, 270 insertions(+), 455 deletions(-) diff --git a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx index adf52848f9357..c1eef94639e54 100644 --- a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx @@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(CATracking_test1) config.configProcessing.deviceType = GPUDataTypes::DeviceType::CPU; config.configProcessing.forceDeviceType = true; - config.configDeviceProcessing.nThreads = 4; //4 threads if we run on the CPU, 1 = default, 0 = auto-detect + config.configDeviceProcessing.ompThreads = 4; //4 threads if we run on the CPU, 1 = default, 0 = auto-detect config.configDeviceProcessing.runQA = false; //Run QA after tracking config.configDeviceProcessing.eventDisplay = nullptr; //Ptr to event display backend, for running standalone OpenGL event display //config.configDeviceProcessing.eventDisplay = new GPUDisplayBackendGlfw; diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 2438f3e048dfd..a4a793a458fdb 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -238,7 +238,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int LOG(INFO) << "GPU device number selected from pipeline id: " << myId << " / " << idMax; } config.configDeviceProcessing.deviceNum = gpuDevice; - config.configDeviceProcessing.nThreads = nThreads; + config.configDeviceProcessing.ompThreads = nThreads; config.configDeviceProcessing.runQA = qa; // Run QA after tracking config.configDeviceProcessing.runMC = specconfig.processMC; // Propagate MC labels config.configDeviceProcessing.eventDisplay = display; // Ptr to event display backend, for running standalone OpenGL event display @@ -262,7 +262,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int config.configReconstruction.tpcRejectionMode = tpcRejectionMode; // Implement TPC Strategy A config.configReconstruction.tpcRejectQPt = 1.f / 0.05f; // Reject clusters of tracks < 50 MeV config.configReconstruction.tpcCompressionModes = GPUSettings::CompressionFull; // Activate all compression steps - config.configReconstruction.tpcCompressionSortOrder = GPUSettings::SortPad; // Sort order for differences compression + config.configReconstruction.tpcCompressionSortOrder = GPUSettings::SortTime; // Sort order for differences compression config.configReconstruction.tpcSigBitsCharge = 4; // Number of significant bits in TPC cluster chargs config.configReconstruction.tpcSigBitsWidth = 3; // Number of significant bits in TPC cluster width diff --git a/GPU/Common/GPUDefConstantsAndSettings.h b/GPU/Common/GPUDefConstantsAndSettings.h index fc6833b402364..0d7b9b004508c 100644 --- a/GPU/Common/GPUDefConstantsAndSettings.h +++ b/GPU/Common/GPUDefConstantsAndSettings.h @@ -19,9 +19,7 @@ // clang-format off -#ifndef GPUDEF_H - #error Please include GPUDef.h -#endif +#include "GPUCommonDef.h" #if !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) && !defined(GPUCA_O2_LIB) && !defined(GPUCA_O2_INTERFACE) #error You are using the CA GPU tracking without defining the build type (O2/AliRoot/Standalone). If you are running an O2 ROOT macro, please include GPUO2Interface.h first! diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 4edfc7f402622..3a5087674b0aa 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -32,7 +32,7 @@ void GPUParam::SetDefaults(float solenoidBz) { memset((void*)this, 0, sizeof(*this)); new (&tpcGeometry) GPUTPCGeometry; - rec.SetDefaults(); + new (&rec) GPUSettingsRec; // clang-format off float const kParamS0Par[2][3][6] = diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index aff7bbee78381..114243f14c846 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -88,8 +88,8 @@ GPUReconstruction::GPUReconstruction(const GPUSettingsProcessing& cfg) : mHostCo mMaster = cfg.master; cfg.master->mSlaves.emplace_back(this); } - mDeviceProcessingSettings.SetDefaults(); - mEventSettings.SetDefaults(); + new (&mDeviceProcessingSettings) GPUSettingsDeviceProcessing; + new (&mEventSettings) GPUSettingsEvent; param().SetDefaults(&mEventSettings); mMemoryScalers.reset(new GPUMemorySizeScalers); for (unsigned int i = 0; i < NSLICES; i++) { @@ -252,15 +252,15 @@ int GPUReconstruction::InitPhaseBeforeDevice() mMemoryScalers->factor = mDeviceProcessingSettings.memoryScalingFactor; #ifdef WITH_OPENMP - if (mDeviceProcessingSettings.nThreads <= 0) { - mDeviceProcessingSettings.nThreads = omp_get_max_threads(); + if (mDeviceProcessingSettings.ompThreads <= 0) { + mDeviceProcessingSettings.ompThreads = omp_get_max_threads(); } else { - omp_set_num_threads(mDeviceProcessingSettings.nThreads); + omp_set_num_threads(mDeviceProcessingSettings.ompThreads); } #else - mDeviceProcessingSettings.nThreads = 1; + mDeviceProcessingSettings.ompThreads = 1; #endif - mMaxThreads = std::max(mMaxThreads, mDeviceProcessingSettings.nThreads); + mMaxThreads = std::max(mMaxThreads, mDeviceProcessingSettings.ompThreads); if (IsGPU()) { mNStreams = std::max(mDeviceProcessingSettings.nStreams, 3); } @@ -905,7 +905,7 @@ int GPUReconstruction::ReadSettings(const char* dir) std::string f; f = dir; f += "settings.dump"; - mEventSettings.SetDefaults(); + new (&mEventSettings) GPUSettingsEvent; if (ReadStructFromFile(f.c_str(), &mEventSettings)) { return 1; } @@ -919,7 +919,7 @@ int GPUReconstruction::ReadSettings(const char* dir) void GPUReconstruction::SetSettings(float solenoidBz) { GPUSettingsEvent ev; - ev.SetDefaults(); + new (&ev) GPUSettingsEvent; ev.solenoidBz = solenoidBz; SetSettings(&ev, nullptr, nullptr); } @@ -960,7 +960,7 @@ std::unique_ptr<GPUReconstruction::GPUThreadContext> GPUReconstruction::GetThrea GPUReconstruction* GPUReconstruction::CreateInstance(DeviceType type, bool forceType, GPUReconstruction* master) { GPUSettingsProcessing cfg; - cfg.SetDefaults(); + new (&cfg) GPUSettingsProcessing; cfg.deviceType = type; cfg.forceDeviceType = forceType; cfg.master = master; diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index f00c7112cd9fe..55e84ff7a9f9e 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -72,7 +72,7 @@ int GPUReconstructionCPUBackend::runKernelBackend(krnlSetup& _xyz, const Args&.. unsigned int num = y.num == 0 || y.num == -1 ? 1 : y.num; for (unsigned int k = 0; k < num; k++) { if (mDeviceProcessingSettings.ompKernels) { - GPUCA_OPENMP(parallel for num_threads(mDeviceProcessingSettings.nThreads)) + GPUCA_OPENMP(parallel for num_threads(mDeviceProcessingSettings.ompThreads)) for (unsigned int iB = 0; iB < x.nBlocks; iB++) { typename T::GPUSharedMemory smem; T::template Thread<I>(x.nBlocks, 1, iB, 0, smem, T::Processor(*mHostConstantMem)[y.start + k], args...); diff --git a/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx b/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx index 53a9da0231a83..9cb9c13061f8e 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx @@ -566,7 +566,7 @@ void GPUReconstructionConvert::RunZSEncoderCreateMeta(const unsigned long long i } } -void GPUReconstructionConvert::RunZSFilter(std::unique_ptr<o2::tpc::Digit[]>* buffers, const o2::tpc::Digit* const* ptrs, size_t* nsb, const size_t* ns, const GPUParam& param, bool zs12bit) +void GPUReconstructionConvert::RunZSFilter(std::unique_ptr<o2::tpc::Digit[]>* buffers, const o2::tpc::Digit* const* ptrs, size_t* nsb, const size_t* ns, const GPUParam& param, bool zs12bit, float threshold) { #ifdef HAVE_O2HEADERS for (unsigned int i = 0; i < NSLICES; i++) { @@ -577,7 +577,7 @@ void GPUReconstructionConvert::RunZSFilter(std::unique_ptr<o2::tpc::Digit[]>* bu const unsigned int decodeBits = zs12bit ? TPCZSHDR::TPC_ZS_NBITS_V2 : TPCZSHDR::TPC_ZS_NBITS_V1; const float decodeBitsFactor = (1 << (decodeBits - 10)); for (unsigned int k = 0; k < ns[i]; k++) { - if (buffers[i][k].getChargeFloat() >= param.rec.tpcZSthreshold) { + if (buffers[i][k].getChargeFloat() >= threshold) { if (k > j) { buffers[i][j] = buffers[i][k]; } diff --git a/GPU/GPUTracking/Base/GPUReconstructionConvert.h b/GPU/GPUTracking/Base/GPUReconstructionConvert.h index 81ad8c235fe3c..56799c160da23 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionConvert.h +++ b/GPU/GPUTracking/Base/GPUReconstructionConvert.h @@ -53,7 +53,7 @@ class GPUReconstructionConvert template <class T, class S> static void RunZSEncoder(const S& in, std::unique_ptr<unsigned long long int[]>* outBuffer, unsigned int* outSizes, o2::raw::RawFileWriter* raw, const o2::InteractionRecord* ir, const GPUParam& param, bool zs12bit, bool verify, float threshold = 0.f, bool padding = true); static void RunZSEncoderCreateMeta(const unsigned long long int* buffer, const unsigned int* sizes, void** ptrs, GPUTrackingInOutZS* out); - static void RunZSFilter(std::unique_ptr<o2::tpc::Digit[]>* buffers, const o2::tpc::Digit* const* ptrs, size_t* nsb, const size_t* ns, const GPUParam& param, bool zs12bit); + static void RunZSFilter(std::unique_ptr<o2::tpc::Digit[]>* buffers, const o2::tpc::Digit* const* ptrs, size_t* nsb, const size_t* ns, const GPUParam& param, bool zs12bit, float threshold); static int GetMaxTimeBin(const o2::tpc::ClusterNativeAccess& native); static int GetMaxTimeBin(const GPUTrackingInOutDigits& digits); static int GetMaxTimeBin(const GPUTrackingInOutZS& zspages); diff --git a/GPU/GPUTracking/Base/GPUSettings.cxx b/GPU/GPUTracking/Base/GPUSettings.cxx index 7aa1f4f3f977d..4ec538dd843ac 100644 --- a/GPU/GPUTracking/Base/GPUSettings.cxx +++ b/GPU/GPUTracking/Base/GPUSettings.cxx @@ -18,46 +18,14 @@ using namespace GPUCA_NAMESPACE::gpu; -void GPUSettingsRec::SetDefaults() +GPUSettingsProcessing::GPUSettingsProcessing() { - HitPickUpFactor = 2.; - NeighboursSearchArea = 3.f; - ClusterError2CorrectionY = 1.f; - ClusterError2CorrectionZ = 1.f; - MinNTrackClusters = -1; - MaxTrackQPt = 1.f / GPUCA_MIN_TRACK_PT_DEFAULT; - NWays = 3; - NWaysOuter = false; - RejectMode = 5; - GlobalTracking = true; - SearchWindowDZDR = 0.f; - TrackReferenceX = 1000.f; - NonConsecutiveIDs = false; - ForceEarlyTPCTransform = -1; - DisableRefitAttachment = 0; - dEdxTruncLow = 2; - dEdxTruncHigh = 77; - tpcRejectionMode = GPUSettings::RejectionStrategyA; - tpcRejectQPt = 1.f / 0.05f; - tpcCompressionModes = GPUSettings::CompressionFull; - tpcCompressionSortOrder = GPUSettings::SortPad; - tpcSigBitsCharge = 4; - tpcSigBitsWidth = 3; - tpcZSthreshold = 2; - fwdTPCDigitsAsClusters = 0; - bz0Pt = 60; - dropLoopers = false; - mergerCovSource = 2; - mergerInterpolateErrors = 1; - fitInProjections = -1; - fitPropagateBzOnly = -1; - retryRefit = 1; - loopInterpolationInExtraPass = -1; - mergerReadFromTrackerDirectly = 1; - useMatLUT = false; + deviceType = GPUDataTypes::DeviceType::CPU; + forceDeviceType = true; + master = nullptr; } -void GPUSettingsEvent::SetDefaults() +GPUSettingsEvent::GPUSettingsEvent() { solenoidBz = -5.00668; constBz = 0; @@ -65,55 +33,3 @@ void GPUSettingsEvent::SetDefaults() continuousMaxTimeBin = 0; needsClusterer = 0; } - -void GPUSettingsProcessing::SetDefaults() -{ - deviceType = GPUDataTypes::DeviceType::CPU; - forceDeviceType = true; - master = nullptr; -} - -void GPUSettingsDeviceProcessing::SetDefaults() -{ - nThreads = 1; - ompKernels = false; - deviceNum = -1; - platformNum = -1; - globalInitMutex = false; - gpuDeviceOnly = false; - nDeviceHelperThreads = 2; - debugLevel = -1; - allocDebugLevel = 0; - deviceTimers = true; - debugMask = -1; - comparableDebutOutput = true; - resetTimers = 1; - eventDisplay = nullptr; - runQA = false; - runCompressionStatistics = false; - stuckProtection = 0; - memoryAllocationStrategy = 0; - keepAllMemory = false; - keepDisplayMemory = false; - nStreams = 8; - trackletConstructorInPipeline = -1; - trackletSelectorInPipeline = -1; - trackletSelectorSlices = -1; - forceMemoryPoolSize = 0; - forceHostMemoryPoolSize = 0; - nTPCClustererLanes = 3; - registerStandaloneInputMemory = false; - tpcCompressionGatherMode = -1; - tpcCompressionGatherModeKernel = -1; - mergerSortTracks = -1; - runMC = false; - memoryScalingFactor = 1.f; - disableMemoryReuse = false; - fullMergerOnGPU = true; - alternateBorderSort = -1; - delayedOutput = true; - tpccfGatherKernel = true; - prefetchTPCpageScan = false; - doublePipeline = false; - doublePipelineClusterizer = true; -} diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index 92c16d2129714..717ded018b168 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -14,7 +14,10 @@ #ifndef GPUSETTINGS_H #define GPUSETTINGS_H -#include "GPUCommonMath.h" +#include "GPUCommonDef.h" +#ifndef __OPENCL__ +#include <vector> +#endif namespace GPUCA_NAMESPACE { @@ -44,66 +47,10 @@ class GPUSettings #endif }; -// Settings concerning the reconstruction -struct GPUSettingsRec { -#ifndef GPUCA_GPUCODE - GPUSettingsRec() - { - SetDefaults(); - } - void SetDefaults(); - void SetMinTrackPt(float v) { MaxTrackQPt = CAMath::Abs(v) > 0.001 ? 1. / CAMath::Abs(v) : 1. / 0.001; } -#endif - - // There must be no bool in here, use char, as sizeof(bool) is compiler dependent and fails on GPUs!!!!!! - float HitPickUpFactor; // multiplier for the chi2 window for hit pick up procedure - float NeighboursSearchArea; // area in cm for the search of neighbours - float ClusterError2CorrectionY; // correction for the squared cluster error during tracking - float ClusterError2CorrectionZ; // correction for the squared cluster error during tracking - int MinNTrackClusters; //* required min number of clusters on the track - float MaxTrackQPt; //* required max Q/Pt (==min Pt) of tracks - char NWays; // Do N fit passes in final fit of merger - char NWaysOuter; // Store outer param - char RejectMode; // 0: no limit on rejection or missed hits, >0: break after n rejected hits, <0: reject at max -n hits - char GlobalTracking; // Enable Global Tracking (prolong tracks to adjacent sectors to find short segments) - float SearchWindowDZDR; // Use DZDR window for seeding instead of vertex window - float TrackReferenceX; // Transport all tracks to this X after tracking (disabled if > 500) - char NonConsecutiveIDs; // Non-consecutive cluster IDs as in HLT, disables features that need access to slice data in TPC merger - char ForceEarlyTPCTransform; // Force early TPC transformation also for continuous data (-1 = auto) - unsigned char DisableRefitAttachment; // Bitmask to disable cluster attachment steps in refit: 1: attachment, 2: propagation, 4: loop following, 8: mirroring - unsigned char dEdxTruncLow; // Low truncation threshold, fraction of 128 - unsigned char dEdxTruncHigh; // High truncation threshold, fraction of 128 - unsigned char tpcRejectionMode; // 0: do not reject clusters, 1: do reject identified junk, 2: reject everything but good tracks - float tpcRejectQPt; // Reject tracks below this Pt - unsigned char tpcCompressionModes; // Enabled steps of TPC compression as flags: 1=truncate charge/width LSB, 2=differences, 4=track-model - unsigned char tpcCompressionSortOrder; // Sort order for clusters storred as differences (0 = time, 1 = pad, 2 = Z-curve-time-pad, 3 = Z-curve-pad-time) - unsigned char tpcSigBitsCharge; // Number of significant bits for TPC cluster charge in compression mode 1 - unsigned char tpcSigBitsWidth; // Number of significant bits for TPC cluster width in compression mode 1 - unsigned char tpcZSthreshold; // TPC Zero Suppression Threshold (for loading digits / forwarging digits as clusters) - unsigned char fwdTPCDigitsAsClusters; // Simply forward TPC digits as clusters - unsigned char bz0Pt; // Nominal Pt to set when bz = 0 (in 10 MeV) - unsigned char dropLoopers; // Drop all clusters after starting from the second loop from tracks - unsigned char mergerCovSource; // 0 = simpleFilterErrors, 1 = use from track following - unsigned char mergerInterpolateErrors; // Use interpolation for cluster rejection based on chi-2 instead of extrapolation - char fitInProjections; // -1 for automatic - char fitPropagateBzOnly; // Use only Bz for the propagation during the fit in the first n passes, -1 = NWays -1 - char retryRefit; // Retry refit with larger cluster errors when fit fails - char loopInterpolationInExtraPass; // Perform the loop interpolation in an extra pass - char mergerReadFromTrackerDirectly; // Make the TPC merger read the output directly from the tracker class - char useMatLUT; // Use material lookup table for TPC refit -}; - // Settings describing the events / time frames struct GPUSettingsEvent { -#ifndef GPUCA_GPUCODE - GPUSettingsEvent() - { - SetDefaults(); - } - void SetDefaults(); -#endif - - // All new members must be sizeof(int)/sizeof(float) for alignment reasons! + // All new members must be sizeof(int) resp. sizeof(float) for alignment reasons! + GPUSettingsEvent(); float solenoidBz; // solenoid field strength int constBz; // for test-MC events with constant Bz int homemadeEvents; // Toy-MC events @@ -113,72 +60,18 @@ struct GPUSettingsEvent { // Settings defining the setup of the GPUReconstruction processing (basically selecting the device / class instance) struct GPUSettingsProcessing { -#ifndef GPUCA_GPUCODE - GPUSettingsProcessing() - { - SetDefaults(); - } - void SetDefaults(); -#endif - + GPUSettingsProcessing(); unsigned int deviceType; // Device type, shall use GPUDataTypes::DEVICE_TYPE constants, e.g. CPU / CUDA char forceDeviceType; // Fail if device initialization fails, otherwise falls back to CPU GPUReconstruction* master; // GPUReconstruction master object }; -// Settings steering the processing once the device was selected -struct GPUSettingsDeviceProcessing { -#ifndef GPUCA_GPUCODE - GPUSettingsDeviceProcessing() - { - SetDefaults(); - } - void SetDefaults(); -#endif - - int nThreads; // Numnber of threads on CPU, 0 = auto-detect - bool ompKernels; // OMP Parallelization inside kernels - int deviceNum; // Device number to use, in case the backend provides multiple devices (-1 = auto-select) - int platformNum; // Platform to use, in case the backend provides multiple platforms (-1 = auto-select) - bool globalInitMutex; // Global mutex to synchronize initialization over multiple instances - bool gpuDeviceOnly; // Use only GPU as device (i.e. no CPU for OpenCL) - int nDeviceHelperThreads; // Additional CPU helper-threads for CPU parts of processing with accelerator - int debugLevel; // Level of debug output (-1 = silent) - int allocDebugLevel; // Some debug output for memory allocations (without messing with normal debug level) - int debugMask; // Mask for debug output dumps to file - bool comparableDebutOutput; // Make CPU and GPU debug output comparable (sort / skip concurrent parts) - int resetTimers; // Reset timers every event - GPUDisplayBackend* eventDisplay; // Run event display after processing, ptr to backend - bool runQA; // Run QA after processing - bool runCompressionStatistics; // Run statistics and verification for cluster compression - int stuckProtection; // Timeout in us, When AMD GPU is stuck, just continue processing and skip tracking, do not crash or stall the chain - int memoryAllocationStrategy; // 0 = auto, 1 = new/delete per resource (default for CPU), 2 = big chunk single allocation (default for device) - bool keepAllMemory; // Allocate all memory on both device and host, and do not reuse - bool keepDisplayMemory; // Like keepAllMemory, but only for memory required for event display - int nStreams; // Number of parallel GPU streams - char trackletConstructorInPipeline; // Run tracklet constructor in pileline like the preceeding tasks instead of as one big block - char trackletSelectorInPipeline; // Run tracklet selector in pipeline, requres also tracklet constructor in pipeline - char trackletSelectorSlices; // Number of slices to processes in parallel at max - size_t forceMemoryPoolSize; // Override size of memory pool to be allocated on GPU / Host (set =1 to force allocating all device memory, if supported) - size_t forceHostMemoryPoolSize; // Override size of host memory pool, overriding forceMemoryPoolSize on the host - int nTPCClustererLanes; // Number of TPC clusterers that can run in parallel - bool deviceTimers; // Use device timers instead of host-based timers - bool registerStandaloneInputMemory; // Automatically register memory for the GPU which is used as input for the standalone benchmark - int tpcCompressionGatherMode; // Modes: 0 = gather by DMA, 1 = DMA + gather on host, 2 = gather by kernel - int tpcCompressionGatherModeKernel; // Kernels: 0 = unbuffered, 1 = buffer in shm (4 byte chunks), 2 = buffer in shm (8 byte chunks), 3 = buffer in shm (16 byte chunks) - char mergerSortTracks; // Sort track indices for GPU track fit - bool runMC; // Process MC labels - float memoryScalingFactor; // Factor to apply to all memory scalers - bool disableMemoryReuse; // Disable memory reusage (for debugging only) - bool fullMergerOnGPU; // Perform full TPC track merging on GPU instead of only refit - char alternateBorderSort; // Alternative scheduling for sorting of border tracks - bool delayedOutput; // Delay output to be parallel to track fit - bool tpccfGatherKernel; // Use a kernel instead of the DMA engine to gather the clusters - char prefetchTPCpageScan; // Prefetch headers during TPC page scan - bool doublePipeline; // Use a double-pipeline driven by 2 threads - bool doublePipelineClusterizer; // Include the input data of the clusterizer in the double-pipeline -}; } // namespace gpu } // namespace GPUCA_NAMESPACE +#if !defined(__OPENCL__) || defined(__OPENCLCPP__) +#define QCONFIG_CPP11_INIT +#endif +#include "utils/qconfig.h" + #endif diff --git a/GPU/GPUTracking/Base/opencl/CMakeLists.txt b/GPU/GPUTracking/Base/opencl/CMakeLists.txt index 781cf2643b3b9..85cfa1577f15f 100644 --- a/GPU/GPUTracking/Base/opencl/CMakeLists.txt +++ b/GPU/GPUTracking/Base/opencl/CMakeLists.txt @@ -57,6 +57,7 @@ add_custom_command( -I${GPUDIR}/Global -I${GPUDIR}/SliceTracker -I${GPUDIR}/TRDTracking + -I${GPUDIR}/Standalone -DGPUCA_GPULIBRARY=OCL1 -x clc++ MAIN_DEPENDENCY ${CL_SRC} diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index b3d0d88ec7b8e..6c38a8dc546c1 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -737,7 +737,7 @@ void GPUChainTracking::ConvertZSEncoder(bool zs12bit) void GPUChainTracking::ConvertZSFilter(bool zs12bit) { - GPUReconstructionConvert::RunZSFilter(mIOMem.tpcDigits, mIOPtrs.tpcPackedDigits->tpcDigits, mIOMem.digitMap->nTPCDigits, mIOPtrs.tpcPackedDigits->nTPCDigits, param(), zs12bit); + GPUReconstructionConvert::RunZSFilter(mIOMem.tpcDigits, mIOPtrs.tpcPackedDigits->tpcDigits, mIOMem.digitMap->nTPCDigits, mIOPtrs.tpcPackedDigits->nTPCDigits, param(), zs12bit, param().rec.tpcZSthreshold); } void GPUChainTracking::LoadClusterErrors() { param().LoadClusterErrors(); } @@ -1478,7 +1478,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() int streamMap[NSLICES]; bool error = false; - GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().ompThreads)) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { GPUTPCTracker& trk = processors()->tpcTrackers[iSlice]; GPUTPCTracker& trkShadow = doGPU ? processorsShadow()->tpcTrackers[iSlice] : trk; @@ -1735,7 +1735,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } } else { mSliceSelectorReady = NSLICES; - GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().ompThreads)) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { if (param().rec.GlobalTracking) { GlobalTracking(iSlice, 0); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx index 1fe68b7b95fa5..88ef9c094174a 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx @@ -23,7 +23,7 @@ template <> GPUdii() void GPUTPCGMMergerTrackFit::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, int mode) { const int iEnd = mode == -1 ? merger.Memory()->nRetryRefit : merger.NOutputTracks(); - GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().ompThreads)) for (int ii = get_global_id(0); ii < iEnd; ii += get_global_size(0)) { const int i = mode == -1 ? merger.RetryRefitIds()[ii] : mode ? merger.TrackOrderProcess()[ii] : ii; GPUTPCGMTrackParam::RefitTrack(merger.OutputTracks()[i], i, &merger, mode == -1); @@ -33,7 +33,7 @@ GPUdii() void GPUTPCGMMergerTrackFit::Thread<0>(int nBlocks, int nThreads, int i template <> GPUdii() void GPUTPCGMMergerFollowLoopers::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger) { - GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().ompThreads)) for (unsigned int i = get_global_id(0); i < merger.Memory()->nLoopData; i += get_global_size(0)) { GPUTPCGMTrackParam::RefitLoop(&merger, i); } diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx index 74754beb788fa..0dfaa88012a23 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx @@ -106,7 +106,7 @@ void* GPUTPCTracker::SetPointersCommon(void* mem) void GPUTPCTracker::RegisterMemoryAllocation() { AllocateAndInitializeLate(); - bool reuseCondition = !mRec->GetDeviceProcessingSettings().keepDisplayMemory && mRec->GetDeviceProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetDeviceProcessingSettings().nThreads == 1); + bool reuseCondition = !mRec->GetDeviceProcessingSettings().keepDisplayMemory && mRec->GetDeviceProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetDeviceProcessingSettings().ompThreads == 1); GPUMemoryReuse reLinks{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerDataLinks, (unsigned short)(mISlice % mRec->GetDeviceProcessingSettings().nStreams)}; mMemoryResLinks = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataLinks, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCSliceLinks", reLinks); mMemoryResSliceScratch = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK | GPUMemoryResource::MEMORY_CUSTOM, "TPCSliceScratch"); diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 66d139964fe81..b7850ad3b00cb 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -630,7 +630,7 @@ int GPUDisplay::InitGL_internal() setQuality(); ReSizeGLScene(GPUDisplayBackend::INIT_WIDTH, GPUDisplayBackend::INIT_HEIGHT, true); #ifdef WITH_OPENMP - int maxThreads = mChain->GetDeviceProcessingSettings().nThreads > 1 ? mChain->GetDeviceProcessingSettings().nThreads : 1; + int maxThreads = mChain->GetDeviceProcessingSettings().ompThreads > 1 ? mChain->GetDeviceProcessingSettings().ompThreads : 1; omp_set_num_threads(maxThreads); #else int maxThreads = 1; @@ -1164,7 +1164,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) mMaxClusterZ = 0; bool error = false; - GPUCA_OPENMP(parallel for num_threads(mChain->GetDeviceProcessingSettings().nThreads) reduction(max : mMaxClusterZ)) + GPUCA_OPENMP(parallel for num_threads(mChain->GetDeviceProcessingSettings().ompThreads) reduction(max : mMaxClusterZ)) for (int iSlice = 0; iSlice < NSLICES; iSlice++) { if (error) { continue; @@ -1219,7 +1219,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) return (1); } - GPUCA_OPENMP(parallel for num_threads(mChain->GetDeviceProcessingSettings().nThreads) reduction(max : mMaxClusterZ)) + GPUCA_OPENMP(parallel for num_threads(mChain->GetDeviceProcessingSettings().ompThreads) reduction(max : mMaxClusterZ)) for (int i = 0; i < mCurrentSpacePointsTRD; i++) { const auto& sp = trdTracker().SpacePoints()[i]; int iSec = mChain->GetTRDGeometry()->GetSector(trdTracker().Tracklets()[i].GetDetector()); @@ -1551,7 +1551,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) mGlDLFinal[iSlice].resize(mNCollissions); } } - GPUCA_OPENMP(parallel num_threads(mChain->GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel num_threads(mChain->GetDeviceProcessingSettings().ompThreads)) { #ifdef WITH_OPENMP int numThread = omp_get_thread_num(); diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.h b/GPU/GPUTracking/Standalone/display/GPUDisplay.h index 3ec116569ad3e..44ada1c12abbf 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.h @@ -57,7 +57,7 @@ class GPUDisplay ~GPUDisplay() = default; GPUDisplay(const GPUDisplay&) = delete; - typedef structConfigGL configDisplay; + typedef GPUDisplayConfig configDisplay; int StartDisplay() { return 1; } void ShowNextEvent() {} diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h b/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h index 11586934c89a5..edd5e146056ff 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h @@ -25,7 +25,8 @@ namespace GPUCA_NAMESPACE { namespace gpu { -typedef structConfigGL GPUDisplayConfig; +typedef GPUSettingsDisplay GPUDisplayConfig; +extern GPUSettingsStandalone configStandalone; } } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 459288fd6d5b5..a18a17d0bce49 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -41,7 +41,7 @@ class GPUQA GPUQA(GPUChainTracking* rec) {} ~GPUQA() = default; - typedef structConfigQA configQA; + typedef GPUQAConfig configQA; int InitQA() { return 1; } void RunQA(bool matchOnly = false) {} diff --git a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h b/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h index 25084fa3acbcc..e7db99c592a8b 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h @@ -25,7 +25,8 @@ namespace GPUCA_NAMESPACE { namespace gpu { -typedef structConfigQA GPUQAConfig; +typedef GPUSettingsQA GPUQAConfig; +extern GPUSettingsStandalone configStandalone; } } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/qa/genEvents.cxx b/GPU/GPUTracking/Standalone/qa/genEvents.cxx index d22238a33aa33..9594d79f1b4f9 100644 --- a/GPU/GPUTracking/Standalone/qa/genEvents.cxx +++ b/GPU/GPUTracking/Standalone/qa/genEvents.cxx @@ -41,6 +41,10 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace std; +namespace GPUCA_NAMESPACE::gpu +{ +extern GPUSettingsStandalone configStandalone; +} int genEvents::GetSlice(double GlobalPhi) { diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index 622f83226d695..2f710e5f1fd20 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -11,6 +11,9 @@ /// \file qconfigoptions.h /// \author David Rohr +#include "GPUDefConstantsAndSettings.h" +#include "GPUSettings.h" + // clang-format off #ifdef QCONFIG_INSTANCE @@ -19,24 +22,114 @@ using namespace GPUCA_NAMESPACE::gpu; BeginNamespace(GPUCA_NAMESPACE) BeginNamespace(gpu) +// Settings concerning the reconstruction +// There must be no bool in here, use char, as sizeof(bool) is compiler dependent and fails on GPUs!!!!!! +BeginSubConfig(GPUSettingsRec, configRec, configStandalone, "REC", 0, "Reconstruction settings") +AddOption(tpcRejectQPt, float, 1.f / 0.05f, "", 0, "QPt threshold to reject clusters of TPC tracks (Inverse Pt!!!)") +AddOption(HitPickUpFactor, float, 2., "", 0, "multiplier for the chi2 window for hit pick up procedure") +AddOption(NeighboursSearchArea, float, 3., "", 0, "area in cm for the search of neighbours") +AddOption(ClusterError2CorrectionY, float, 1., "", 0, "correction for the squared cluster error during tracking") +AddOption(ClusterError2CorrectionZ, float, 1., "", 0, "correction for the squared cluster error during tracking") +AddOption(MinNTrackClusters, int, -1, "", 0, "required min number of clusters on the track") +AddOption(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required max Q/Pt (==min Pt) of tracks") +AddOption(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") +AddOption(TrackReferenceX, float, 1000, "", 0, "Transport all tracks to this X after tracking (disabled if > 500)") +AddOption(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") +AddOption(NWays, char, 3, "", 0, "Do N fit passes in final fit of merger") +AddOption(NWaysOuter, char, 0, "", 0, "Store outer param") +AddOption(RejectMode, char, 5, "", 0, "0: no limit on rejection or missed hits, >0: break after n rejected hits, <0: reject at max -n hits") +AddOption(NonConsecutiveIDs, char, false, "", 0, "Non-consecutive cluster IDs as in HLT, disables features that need access to slice data in TPC merger") +AddOption(dEdxTruncLow, unsigned char, 2, "", 0, "Low truncation threshold, fraction of 128") +AddOption(dEdxTruncHigh, unsigned char, 77, "", 0, "High truncation threshold, fraction of 128") +AddOption(GlobalTracking, char, 1, "", 0, "Enable Global Tracking (prolong tracks to adjacent sectors to find short segments)") +AddOption(DisableRefitAttachment, unsigned char, 0, "", 0, "Bitmask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") +AddOption(tpcRejectionMode, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression (0 = no, 1 = strategy A, 2 = strategy B)") +AddOption(tpcCompressionModes, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") +AddOption(tpcCompressionSortOrder, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") +AddOption(tpcSigBitsCharge, unsigned char, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") +AddOption(tpcSigBitsWidth, unsigned char, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") +AddOption(ForceEarlyTPCTransform, char, -1, "", 0, "Force early TPC transformation also for continuous data (-1 = auto)") +AddOption(fwdTPCDigitsAsClusters, unsigned char, 0, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") +AddOption(bz0Pt, unsigned char, 60, "", 0, "Nominal Pt to set when bz = 0 (in 10 MeV)") +AddOption(dropLoopers, unsigned char, 0, "", 0, "Drop looping tracks starting from second loop") +AddOption(mergerCovSource, unsigned char, 2, "", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following, 2 = refit") +AddOption(mergerInterpolateErrors, unsigned char, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") +AddOption(fitInProjections, char, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") +AddOption(fitPropagateBzOnly, char, -1, "", 0, "Propagate using Bz only for n passes") +AddOption(retryRefit, char, 1, "", 0, "Retry refit when fit fails") +AddOption(loopInterpolationInExtraPass, char, -1, "", 0, "Perform loop interpolation in an extra pass") +AddOption(mergerReadFromTrackerDirectly, char, 1, "", 0, "Forward data directly from tracker to merger on GPU") +AddOption(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") +AddCustomCPP(void SetMinTrackPt(float v) { MaxTrackQPt = v > 0.001 ? (1. / v) : (1. / 0.001); }) +AddHelp("help", 'h') +EndConfig() + +// Settings steering the processing once the device was selected +BeginSubConfig(GPUSettingsDeviceProcessing, configProc, configStandalone, "PROC", 0, "Processing settings") +AddOption(platformNum, int, -1, "", 0, "Platform to use, in case the backend provides multiple platforms (-1 = auto-select)") +AddOption(gpuDeviceOnly, bool, false, "", 0, "Use only GPU as device (i.e. no CPU for OpenCL)") +AddOption(debugMask, int, -1, "", 0, "Mask for debug output dumps to file") +AddOption(comparableDebutOutput, bool, true, "", 0, "Make CPU and GPU debug output comparable (sort / skip concurrent parts)") +AddOption(resetTimers, int, 1, "", 0, "Reset timers every event") +AddOption(stuckProtection, int, 0, "", 0, "Timeout in us, When AMD GPU is stuck, just continue processing and skip tracking, do not crash or stall the chain") +AddOption(keepAllMemory, bool, false, "", 0, "Allocate all memory on both device and host, and do not reuse") +AddOption(keepDisplayMemory, bool, false, "", 0, "Like keepAllMemory, but only for memory required for event display") +AddOption(trackletSelectorSlices, char, -1, "", 0, "Number of slices to processes in parallel at max") +AddOption(nTPCClustererLanes, int, 3, "", 0, "Number of TPC clusterers that can run in parallel") +AddOption(disableMemoryReuse, bool, false, "", 0, "Disable memory reusage (for debugging only)") +AddOption(fullMergerOnGPU, bool, true, "", 0, "Perform full TPC track merging on GPU instead of only refit") +AddOption(delayedOutput, bool, true, "", 0, "Delay output to be parallel to track fit") +AddOption(tpccfGatherKernel, bool, true, "", 0, "Use a kernel instead of the DMA engine to gather the clusters") +AddOption(doublePipelineClusterizer, bool, true, "", 0, "Include the input data of the clusterizer in the double-pipeline") +AddOption(deviceNum, int, -1, "gpuDevice", 0, "Set GPU device to use (-1: automatic)") +AddOption(globalInitMutex, bool, false, "", 0, "Use global mutex to synchronize initialization of multiple GPU instances") +AddOption(ompThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %d OMP threads")) +AddOption(nDeviceHelperThreads, int, 1, "", 0, "Number of CPU helper threads for CPU processing") +AddOption(nStreams, int, 8, "", 0, "Number of GPU streams / command queues") +AddOption(trackletConstructorInPipeline, int, -1, "", 0, "Run tracklet constructor in the pipeline") +AddOption(trackletSelectorInPipeline, int, -1, "", 0, "Run tracklet selector in the pipeline") +AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fit") +AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode") +AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") +AddOption(runMC, bool, false, "", 0, "Process MC labels") +AddOption(ompKernels, bool, false, "", 0, "Parallelize with OMP inside kernels instead of over slices") +AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") +AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") +AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") +AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") +AddOption(runQA, bool, false, "qa", 'q', "Enable tracking QA", message("Running QA: %s")) +AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") +AddOption(forceMemoryPoolSize, unsigned long, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ul)) +AddOption(forceHostMemoryPoolSize, unsigned long, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ul)) +AddOption(memoryAllocationStrategy, int, 0, "", 0, "Memory Allocation Stragegy (0 = auto, 1 = individual allocations, 2 = single global allocation)") +AddOption(deviceTimers, bool, true, "", 0, "Use device timers instead of host-based time measurement") +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") +AddVariable(eventDisplay, GPUCA_NAMESPACE::gpu::GPUDisplayBackend*, nullptr) +AddHelp("help", 'h') +EndConfig() + +#ifndef GPUCA_GPUCODE_DEVICE // Settings concerning the event display BeginSubConfig(GPUSettingsDisplay, configGL, configStandalone, "GL", 'g', "OpenGL display settings") AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") AddHelp("help", 'h') EndConfig() -BeginSubConfig(structConfigTF, configTF, configStandalone, "TF", 't', "Timeframe settings") +// Settings concerning the standlone timeframe from run 2 events assembly tool +BeginSubConfig(GPUSettingsTF, configTF, configStandalone, "TF", 't', "Timeframe settings") AddOption(nMerge, int, 0, "", 0, "Merge n events in a timeframe", min(0)) AddOption(averageDistance, float, 50., "", 0, "Average distance in cm of events merged into timeframe", min(0.f)) AddOption(randomizeDistance, bool, true, "", 0, "Randomize distance around average distance of merged events") AddOption(shiftFirstEvent, bool, true, "", 0, "Also shift the first event in z when merging events to a timeframe") AddOption(bunchSim, int, 0, "", 0, "Simulate correct bunch interactions instead of placing only the average number of events. A value [n] > 1 sets TFlen for [n] collisions in average. (Incompatible to TFmerge)") -AddOption(bunchCount, int, 12, "", 0, "Number of bunches per train") +AddOption(bunchCount, int, 12, "", 0, "Number of bunches per trainsort") AddOption(bunchSpacing, int, 50, "", 0, "Spacing between benches in ns") AddOption(bunchTrainCount, int, 48, "", 0, "Number of bunch trains") AddOption(abortGapTime, int, (3000), "", 0, "Length of abort gap in ns") AddOption(interactionRate, int, 50000, "", 0, "Instantaneous interaction rate") -AddOption(timeFrameLen, long long int, (1000000000 / 44), "", 'l', "Timeframe len in ns") +AddOption(timeFrameLen, long, (1000000000 / 44), "", 'l', "Timeframe len in ns") AddOption(noBorder, bool, false, "", 0, "Do not simulate border effects (partial events)") AddOption(noEventRepeat, int, 0, "", 0, "0: Place random events, 1: Place events in timeframe one after another, 2: Place random events but do not repat", def(1)) AddOption(nTotalEventsInTF, int, 0, "", 0, "Total number of collisions to be placed in the interior of all time frames (excluding borders)") @@ -45,7 +138,8 @@ AddOption(overlayRaw, bool, false, "", 0, "Overlay raw TPC data instead of spati AddHelp("help", 'h') EndConfig() -BeginSubConfig(structConfigQA, configQA, configStandalone, "QA", 'q', "QA settings") +// Settings concerning the standalone QA +BeginSubConfig(GPUSettingsQA, configQA, configStandalone, "QA", 'q', "QA settings") AddOptionVec(compareInputs, const char*, "QAinput", 0, "Read histogram from these input files and include them in the output plots") AddOptionVec(compareInputNames, const char*, "QAinputName", 0, "Legend entries for data from comparison histogram files") AddOption(name, const char*, nullptr, "", 0, "Legend entry for new data from current processing") @@ -68,52 +162,14 @@ AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinp AddHelp("help", 'h') EndConfig() -BeginSubConfig(structConfigEG, configEG, configStandalone, "EG", 0, "Event generator settings") +// Settings concerning standalone toy event generator +BeginSubConfig(GPUSettingsEG, configEG, configStandalone, "EG", 0, "Event generator settings") AddOption(numberOfTracks, int, 1, "", 0, "Number of tracks per generated event") AddHelp("help", 'h') EndConfig() -BeginSubConfig(structConfigRec, configRec, configStandalone, "REC", 0, "Reconstruction settings") -AddOption(globalTracking, bool, true, "", 0, "Enable global tracking") -AddOption(runTRD, int, -1, "", 0, "Enable TRD processing") -AddOption(rundEdx, int, 1, "", 0, "Enable dEdx processing") -AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") -AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") -AddOption(disableRefitAttachment, int, 0, "", 0, "Mask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") -AddOption(tpcReject, int, -1, "", 0, "Enable rejection of TPC clusters for compression (-1 = default, 0 = no, 1 = strategy A, 2 = strategy B)") -AddOption(tpcRejectThreshold, float, 0.f, "", 0, "Pt threshold to reject clusters of TPC tracks") -AddOption(tpcCompression, int, 7, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") -AddOption(tpcCompressionSort, int, 0, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") -AddOption(ForceEarlyTPCTransform, int, -1, "", 0, "Force early TPC transformation also for continuous data (-1 = auto)") -AddOption(fwdTPCDigitsAsClusters, bool, false, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") -AddOption(dropLoopers, bool, false, "", 0, "Drop looping tracks starting from second loop") -AddOption(mergerCovSource, int, -1, "", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following") -AddOption(mergerInterpolateErrors, int, -1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") -AddOption(fitInProjections, int, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") -AddOption(fitPropagateBzOnly, int, -1, "", 0, "Propagate using Bz only for n passes") -AddOption(retryRefit, int, -1, "", 0, "Retry refit when fit fails") -AddOption(loopInterpolationInExtraPass, int, -1, "", 0, "Perform loop interpolation in an extra pass") -AddOption(mergerReadFromTrackerDirectly, bool, true, "", 0, "Forward data directly from tracker to merger on GPU") -AddHelp("help", 'h') -EndConfig() - -BeginSubConfig(structConfigProc, configProc, configStandalone, "PROC", 0, "Processing settings") -AddOption(nStreams, int, -1, "", 0, "Number of GPU streams / command queues") -AddOption(constructorPipeline, int, -1, "", 0, "Run tracklet constructor in pipeline") -AddOption(selectorPipeline, int, -1, "", 0, "Run tracklet selector in pipeline") -AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fit") -AddOption(recoSteps, int, -1, "", 0, "Bitmask for RecoSteps") -AddOption(recoStepsGPU, int, -1, "", 0, "Bitmask for RecoSteps") -AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode") -AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") -AddOption(runMC, bool, false, "", 0, "Process MC labels") -AddOption(ompKernels, bool, false, "", 0, "Parallelize with OMP inside kernels instead of over slices") -AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") -AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") -AddHelp("help", 'h') -EndConfig() - -BeginConfig(structConfigStandalone, configStandalone) +// Settings for the standalone benchmark +BeginConfig(GPUSettingsStandalone, configStandalone) #if defined(CUDA_ENABLED) || defined(OPENCL1_ENABLED) || defined(HIP_ENABLED) AddOption(runGPU, bool, true, "", 'g', "Use GPU for processing", message("GPU processing: %s")) #else @@ -132,40 +188,22 @@ AddOption(gpuType, const char*, "HIP", "", 0, "GPU type (CUDA / HIP / OCL / OCL2 AddOption(gpuType, const char*, "", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") #endif AddOption(runGPUforce, bool, true, "", 0, "Force usage of the specified GPU device type, no CPU fallback") -AddOption(gpuInitMutex, bool, false, "", 0, "Use mutex to synchronize initialization of multiple GPU instances") -AddOption(oclGPUonly, bool, false, "", 0, "Allow only GPU as OpenCL device") -AddOption(helperThreads, int, 1, "", 0, "Number of CPU helper threads for CPU processing") AddOption(noprompt, bool, true, "", 0, "Do prompt for keypress before exiting") AddOption(continueOnError, bool, false, "", 0, "Continue processing after an error") -AddOption(DebugLevel, int, 0, "debug", 'd', "Set debug level") -AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Set alloc debug level") -AddOption(DeviceTiming, bool, true, "", 0, "Use device timers instead of host-based time measurement") AddOption(seed, int, -1, "", 0, "Set srand seed (-1: random)") AddOption(cleardebugout, bool, false, "", 0, "Clear debug output file when processing next event") -AddOption(deviceNum, int, -1, "", 0, "Set GPU device to use (-1: automatic)") AddOption(StartEvent, int, 0, "", 's', "First event to process", min(0)) AddOption(NEvents, int, -1, "", 'n', "Number of events to process (-1; all)", min(0)) -AddOption(merger, int, 1, "", 0, "Run track merging / refit", min(0), max(1)) AddOption(runs, int, 1, "runs", 'r', "Number of iterations to perform (repeat each event)", min(0)) AddOption(runs2, int, 1, "runsExternal", 0, "Number of iterations to perform (repeat full processing)", min(1)) AddOption(runsInit, int, 1, "", 0, "Number of initial iterations excluded from average", min(0)) AddOption(EventsDir, const char*, "pp", "events", 'e', "Directory with events to process", message("Reading events from Directory events/%s")) -AddOption(OMPThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %d OMP threads")) AddOption(eventDisplay, int, 0, "display", 'd', "Show standalone event display", def(1)) //1: default display (Windows / X11), 2: glut, 3: glfw -AddOption(qa, bool, false, "", 'q', "Enable tracking QA", message("Running QA: %s")) AddOption(eventGenerator, bool, false, "", 0, "Run event generator") -AddOption(nways, int, 3, "", 0, "Use n-way track-fit", min(1)) -AddOptionSet(nways, int, 3, "3Way", 0, "Use 3-way track-fit") -AddOptionSet(nways, int, 1, "1Way", 0, "Use 3-way track-fit") AddOption(nwaysouter, bool, false, "", 0, "Create OuterParam") -AddOption(dzdr, float, 2.5f, "", 0, "Use dZ/dR search window instead of vertex window") AddOption(cont, bool, false, "", 0, "Process continuous timeframe data") -AddOption(forceMemorySize, unsigned long long int, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ull)) -AddOption(forceHostMemorySize, unsigned long long int, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ull)) -AddOption(memoryScalingFactor, float, 1.f, "", 0, "Factor to apply to all memory scalers") -AddOption(outputcontrolmem, unsigned long long int, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ull), message("Using %lld bytes as output memory")) -AddOption(inputcontrolmem, unsigned long long int, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ull), message("Using %lld bytes as input memory")) -AddOption(registerInputMemory, bool, false, "", 0, "Automatically register input memory buffers for the GPU") +AddOption(outputcontrolmem, unsigned long, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ul), message("Using %lld bytes as output memory")) +AddOption(inputcontrolmem, unsigned long, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ul), message("Using %lld bytes as input memory")) AddOption(cpuAffinity, int, -1, "", 0, "Pin CPU affinity to this CPU core", min(-1)) AddOption(fifoScheduler, bool, false, "", 0, "Use FIFO realtime scheduler", message("Setting FIFO scheduler: %s")) AddOption(fpe, bool, true, "", 0, "Trap on floating point exceptions") @@ -175,31 +213,33 @@ AddOption(constBz, bool, false, "", 0, "Force constand Bz") AddOption(overrideMaxTimebin, bool, false, "", 0, "Override max time bin setting for continuous data with max time bin in time frame") AddOption(encodeZS, int, -1, "", 0, "Zero-Suppress TPC data", def(1)) AddOption(zsFilter, int, -1, "", 0, "Apply Zero-Suppression when loading digits and remove those below threshold", def(1)) -AddOption(zsThreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") AddOption(zs12bit, bool, true, "", 0, "Perform 12 bit zero-suppression encoding / filter") AddOption(dumpEvents, bool, false, "", 0, "Dump events (after transformation such as encodeZS") AddOption(stripDumpedEvents, bool, false, "", 0, "Remove redundant inputs (e.g. digits and ZS) before dumping") -AddOption(referenceX, float, 500.f, "", 0, "Reference X position to transport track to after fit") -AddOption(rejectMode, char, 5, "", 0, "Merger Reject Mode") -AddOption(allocationStrategy, int, 0, "", 0, "Memory Allocation Stragegy (0 = auto, 1 = individual allocations, 2 = single global allocation)") AddOption(printSettings, bool, false, "", 0, "Print all settings") -AddOption(compressionStat, bool, false, "", 0, "Run statistics and verification for cluster compression") AddOption(memoryStat, bool, false, "", 0, "Print memory statistics") AddOption(testSyncAsync, bool, false, "syncAsync", 0, "Test first synchronous and then asynchronous processing") AddOption(testSync, bool, false, "sync", 0, "Test settings for synchronous phase") AddOption(timeFrameTime, bool, false, "tfTime", 0, "Print some debug information about time frame processing time") AddOption(controlProfiler, bool, false, "", 0, "Issues GPU profiler stop and start commands to profile only the relevant processing part") -AddOption(alternateBorderSort, int, -1, "", 0, "Alternative implementation for sorting of border tracks") AddOption(preloadEvents, bool, false, "", 0, "Preload events into host memory before start processing") +AddOption(recoSteps, int, -1, "", 0, "Bitmask for RecoSteps") +AddOption(recoStepsGPU, int, -1, "", 0, "Bitmask for RecoSteps") +AddOption(runMerger, int, 1, "", 0, "Run track merging / refit", min(0), max(1)) +AddOption(runTRD, int, -1, "", 0, "Enable TRD processing") +AddOption(rundEdx, int, 1, "", 0, "Enable dEdx processing") +AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") +AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") AddHelp("help", 'h') AddHelpAll("helpall", 'H') -AddSubConfig(structConfigTF, configTF) -AddSubConfig(structConfigQA, configQA) -AddSubConfig(structConfigEG, configEG) -AddSubConfig(structConfigGL, configGL) -AddSubConfig(structConfigRec, configRec) -AddSubConfig(structConfigProc, configProc) +AddSubConfig(GPUSettingsTF, configTF) +AddSubConfig(GPUSettingsQA, configQA) +AddSubConfig(GPUSettingsEG, configEG) +AddSubConfig(GPUSettingsDisplay, configGL) +AddSubConfig(GPUSettingsRec, configRec) +AddSubConfig(GPUSettingsDeviceProcessing, configProc) EndConfig() +#endif // !GPUCA_GPUCODE_DEVICE EndNamespace() // gpu EndNamespace() // GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index e7f67fb5385d1..33bc49d967410 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -116,7 +116,9 @@ int ReadConfiguration(int argc, char** argv) if (configStandalone.printSettings) { qConfigPrint(); } - + if (configStandalone.configProc.debugLevel < 0) { + configStandalone.configProc.debugLevel = 0; + } #ifndef _WIN32 setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, ""); @@ -163,19 +165,19 @@ int ReadConfiguration(int argc, char** argv) } #endif #ifndef HAVE_O2HEADERS - configStandalone.configRec.runTRD = configStandalone.configRec.rundEdx = configStandalone.configRec.runCompression = configStandalone.configRec.runTransformation = configStandalone.testSyncAsync = configStandalone.testSync = 0; + configStandalone.configRec.runTRD = configStandalone.rundEdx = configStandalone.configRec.runCompression = configStandalone.runTransformation = configStandalone.testSyncAsync = configStandalone.testSync = 0; configStandalone.configRec.ForceEarlyTPCTransform = 1; #endif #ifndef GPUCA_TPC_GEOMETRY_O2 configStandalone.configRec.mergerReadFromTrackerDirectly = 0; #endif #ifndef GPUCA_BUILD_QA - if (configStandalone.qa || configStandalone.eventGenerator) { + if (configStandalone.configProc.runQA || configStandalone.eventGenerator) { printf("QA not enabled in build\n"); return 1; } #endif - if (configStandalone.qa) { + if (configStandalone.configProc.runQA) { if (getenv("LC_NUMERIC")) { printf("Please unset the LC_NUMERIC env variable, otherwise ROOT will not be able to fit correctly\n"); // BUG: ROOT Problem return 1; @@ -217,27 +219,27 @@ int ReadConfiguration(int argc, char** argv) return 1; } if (configStandalone.configQA.inputHistogramsOnly) { - configStandalone.configRec.rundEdx = false; + configStandalone.rundEdx = false; } if (configStandalone.eventDisplay) { configStandalone.noprompt = 1; } - if (configStandalone.DebugLevel >= 4 && !configStandalone.configProc.ompKernels) { - configStandalone.OMPThreads = 1; + if (configStandalone.configProc.debugLevel >= 4 && !configStandalone.configProc.ompKernels) { + configStandalone.configProc.ompThreads = 1; } #ifdef WITH_OPENMP - if (configStandalone.OMPThreads != -1) { - omp_set_num_threads(configStandalone.OMPThreads); + if (configStandalone.configProc.ompThreads != -1) { + omp_set_num_threads(configStandalone.configProc.ompThreads); } else { - configStandalone.OMPThreads = omp_get_max_threads(); + configStandalone.configProc.ompThreads = omp_get_max_threads(); } - if (configStandalone.OMPThreads != omp_get_max_threads()) { + if (configStandalone.configProc.ompThreads != omp_get_max_threads()) { printf("Cannot set number of OMP threads!\n"); return 1; } #else - configStandalone.OMPThreads = 1; + configStandalone.configProc.ompThreads = 1; #endif if (configStandalone.outputcontrolmem) { bool forceEmptyMemory = getenv("LD_PRELOAD") && strstr(getenv("LD_PRELOAD"), "valgrind") != nullptr; @@ -289,6 +291,8 @@ int SetupReconstruction() GPUSettingsEvent ev = rec->GetEventSettings(); GPUSettingsRec recSet; GPUSettingsDeviceProcessing devProc; + memcpy((void*)&recSet, (void*)&configStandalone.configRec, sizeof(GPUSettingsRec)); + memcpy((void*)&devProc, (void*)&configStandalone.configProc, sizeof(GPUSettingsDeviceProcessing)); GPURecoStepConfiguration steps; if (configStandalone.eventGenerator) { @@ -322,55 +326,7 @@ int SetupReconstruction() printf("Standalone Test Framework for CA Tracker - Using GPU\n"); } - recSet.SetMinTrackPt(GPUCA_MIN_TRACK_PT_DEFAULT); - recSet.NWays = configStandalone.nways; - recSet.NWaysOuter = configStandalone.nwaysouter; - recSet.RejectMode = configStandalone.rejectMode; - recSet.SearchWindowDZDR = configStandalone.dzdr; - recSet.GlobalTracking = configStandalone.configRec.globalTracking; - recSet.DisableRefitAttachment = configStandalone.configRec.disableRefitAttachment; - recSet.ForceEarlyTPCTransform = configStandalone.configRec.ForceEarlyTPCTransform; - recSet.fwdTPCDigitsAsClusters = configStandalone.configRec.fwdTPCDigitsAsClusters; - recSet.dropLoopers = configStandalone.configRec.dropLoopers; - if (configStandalone.configRec.mergerCovSource != -1) { - recSet.mergerCovSource = configStandalone.configRec.mergerCovSource; - } - if (configStandalone.configRec.mergerInterpolateErrors != -1) { - recSet.mergerInterpolateErrors = configStandalone.configRec.mergerInterpolateErrors; - } - if (configStandalone.referenceX < 500.) { - recSet.TrackReferenceX = configStandalone.referenceX; - } - recSet.tpcZSthreshold = configStandalone.zsThreshold; - if (configStandalone.configRec.fitInProjections != -1) { - recSet.fitInProjections = configStandalone.configRec.fitInProjections; - } - if (configStandalone.configRec.fitPropagateBzOnly != -1) { - recSet.fitPropagateBzOnly = configStandalone.configRec.fitPropagateBzOnly; - } - if (configStandalone.configRec.retryRefit != -1) { - recSet.retryRefit = configStandalone.configRec.retryRefit; - } - recSet.loopInterpolationInExtraPass = configStandalone.configRec.loopInterpolationInExtraPass; - recSet.mergerReadFromTrackerDirectly = configStandalone.configRec.mergerReadFromTrackerDirectly; - - if (configStandalone.OMPThreads != -1) { - devProc.nThreads = configStandalone.OMPThreads; - } - devProc.deviceNum = configStandalone.deviceNum; - devProc.forceMemoryPoolSize = (configStandalone.forceMemorySize == 1 && configStandalone.eventDisplay) ? 2 : configStandalone.forceMemorySize; - devProc.forceHostMemoryPoolSize = configStandalone.forceHostMemorySize; - devProc.debugLevel = configStandalone.DebugLevel; - devProc.allocDebugLevel = configStandalone.allocDebugLevel; - devProc.deviceTimers = configStandalone.DeviceTiming; - devProc.runQA = configStandalone.qa; - devProc.runMC = configStandalone.configProc.runMC; - devProc.ompKernels = configStandalone.configProc.ompKernels; - devProc.runCompressionStatistics = configStandalone.compressionStat; - devProc.memoryScalingFactor = configStandalone.memoryScalingFactor; - devProc.alternateBorderSort = configStandalone.alternateBorderSort; - devProc.doublePipeline = configStandalone.configProc.doublePipeline; - devProc.prefetchTPCpageScan = configStandalone.configProc.prefetchTPCpageScan; + configStandalone.configProc.forceMemoryPoolSize = (configStandalone.configProc.forceMemoryPoolSize == 1 && configStandalone.eventDisplay) ? 2 : configStandalone.configProc.forceMemoryPoolSize; if (configStandalone.eventDisplay) { #ifdef GPUCA_BUILD_EVENT_DISPLAY #ifdef _WIN32 @@ -398,49 +354,23 @@ int SetupReconstruction() #endif devProc.eventDisplay = eventDisplay.get(); } - devProc.nDeviceHelperThreads = configStandalone.helperThreads; - devProc.globalInitMutex = configStandalone.gpuInitMutex; - devProc.gpuDeviceOnly = configStandalone.oclGPUonly; - devProc.memoryAllocationStrategy = configStandalone.allocationStrategy; - devProc.registerStandaloneInputMemory = configStandalone.registerInputMemory; - if (configStandalone.configRec.tpcReject != -1) { - recSet.tpcRejectionMode = configStandalone.configRec.tpcReject; - } - if (configStandalone.configRec.tpcRejectThreshold != 0.f) { - recSet.tpcRejectQPt = 1.f / configStandalone.configRec.tpcRejectThreshold; - } - recSet.tpcCompressionModes = configStandalone.configRec.tpcCompression; - recSet.tpcCompressionSortOrder = configStandalone.configRec.tpcCompressionSort; - - if (configStandalone.configProc.nStreams >= 0) { - devProc.nStreams = configStandalone.configProc.nStreams; - } - if (configStandalone.configProc.constructorPipeline >= 0) { - devProc.trackletConstructorInPipeline = configStandalone.configProc.constructorPipeline; - } - if (configStandalone.configProc.selectorPipeline >= 0) { - devProc.trackletSelectorInPipeline = configStandalone.configProc.selectorPipeline; - } - devProc.mergerSortTracks = configStandalone.configProc.mergerSortTracks; - devProc.tpcCompressionGatherMode = configStandalone.configProc.tpcCompressionGatherMode; - devProc.tpcCompressionGatherModeKernel = configStandalone.configProc.tpcCompressionGatherModeKernel; steps.steps = GPUDataTypes::RecoStep::AllRecoSteps; - if (configStandalone.configRec.runTRD != -1) { - steps.steps.setBits(GPUDataTypes::RecoStep::TRDTracking, configStandalone.configRec.runTRD > 0); + if (configStandalone.runTRD != -1) { + steps.steps.setBits(GPUDataTypes::RecoStep::TRDTracking, configStandalone.runTRD > 0); } else if (chainTracking->GetTRDGeometry() == nullptr) { steps.steps.setBits(GPUDataTypes::RecoStep::TRDTracking, false); } - if (configStandalone.configRec.rundEdx != -1) { - steps.steps.setBits(GPUDataTypes::RecoStep::TPCdEdx, configStandalone.configRec.rundEdx > 0); + if (configStandalone.rundEdx != -1) { + steps.steps.setBits(GPUDataTypes::RecoStep::TPCdEdx, configStandalone.rundEdx > 0); } - if (configStandalone.configRec.runCompression != -1) { - steps.steps.setBits(GPUDataTypes::RecoStep::TPCCompression, configStandalone.configRec.runCompression > 0); + if (configStandalone.runCompression != -1) { + steps.steps.setBits(GPUDataTypes::RecoStep::TPCCompression, configStandalone.runCompression > 0); } - if (configStandalone.configRec.runTransformation != -1) { - steps.steps.setBits(GPUDataTypes::RecoStep::TPCConversion, configStandalone.configRec.runTransformation > 0); + if (configStandalone.runTransformation != -1) { + steps.steps.setBits(GPUDataTypes::RecoStep::TPCConversion, configStandalone.runTransformation > 0); } - if (!configStandalone.merger) { + if (!configStandalone.runMerger) { steps.steps.setBits(GPUDataTypes::RecoStep::TPCMerging, false); steps.steps.setBits(GPUDataTypes::RecoStep::TRDTracking, false); steps.steps.setBits(GPUDataTypes::RecoStep::TPCdEdx, false); @@ -457,11 +387,11 @@ int SetupReconstruction() steps.steps.setBits(GPUDataTypes::RecoStep::TPCClusterFinding, false); } - if (configStandalone.configProc.recoSteps >= 0) { - steps.steps &= configStandalone.configProc.recoSteps; + if (configStandalone.recoSteps >= 0) { + steps.steps &= configStandalone.recoSteps; } - if (configStandalone.configProc.recoStepsGPU >= 0) { - steps.stepsGPUMask &= configStandalone.configProc.recoStepsGPU; + if (configStandalone.recoStepsGPU >= 0) { + steps.stepsGPUMask &= configStandalone.recoStepsGPU; } steps.outputs.clear(); @@ -529,7 +459,7 @@ int SetupReconstruction() return 1; } } - if (configStandalone.DebugLevel >= 4) { + if (configStandalone.configProc.debugLevel >= 4) { rec->PrintKernelOccupancies(); } return (0); @@ -546,8 +476,8 @@ int ReadEvent(int n) if (r) { return r; } - if (chainTracking->mIOPtrs.clustersNative && (configStandalone.configTF.bunchSim || configStandalone.configTF.nMerge || !configStandalone.configRec.runTransformation)) { - if (configStandalone.DebugLevel >= 2) { + if (chainTracking->mIOPtrs.clustersNative && (configStandalone.configTF.bunchSim || configStandalone.configTF.nMerge || !configStandalone.runTransformation)) { + if (configStandalone.configProc.debugLevel >= 2) { printf("Converting Native to Legacy ClusterData for overlaying - WARNING: No raw clusters produced - Compression etc will not run!!!\n"); } chainTracking->ConvertNativeToClusterDataLegacy(); @@ -584,12 +514,12 @@ int LoadEvent(int iEvent, int x) chainTracking->ConvertZSEncoder(configStandalone.zs12bit); } } - if (!configStandalone.configRec.runTransformation) { + if (!configStandalone.runTransformation) { chainTracking->mIOPtrs.clustersNative = nullptr; } else { for (int i = 0; i < chainTracking->NSLICES; i++) { if (chainTracking->mIOPtrs.rawClusters[i]) { - if (configStandalone.DebugLevel >= 2) { + if (configStandalone.configProc.debugLevel >= 2) { printf("Converting Legacy Raw Cluster to Native\n"); } chainTracking->ConvertRun2RawToNative(); @@ -689,7 +619,7 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, OutputStat(chainTrackingUse, iRun == 0 ? nTracksTotal : nullptr, iRun == 0 ? nClustersTotal : nullptr); if (configStandalone.memoryStat) { recUse->PrintMemoryStatistics(); - } else if (configStandalone.DebugLevel >= 2) { + } else if (configStandalone.configProc.debugLevel >= 2) { recUse->PrintMemoryOverview(); } } @@ -776,17 +706,17 @@ int main(int argc, char** argv) printf("Error initializing GPUReconstruction\n"); return 1; } - rec->SetDebugLevelTmp(configStandalone.DebugLevel); + rec->SetDebugLevelTmp(configStandalone.configProc.debugLevel); chainTracking = rec->AddChain<GPUChainTracking>(); if (configStandalone.testSyncAsync) { - if (configStandalone.DebugLevel >= 3) { - recAsync->SetDebugLevelTmp(configStandalone.DebugLevel); + if (configStandalone.configProc.debugLevel >= 3) { + recAsync->SetDebugLevelTmp(configStandalone.configProc.debugLevel); } chainTrackingAsync = recAsync->AddChain<GPUChainTracking>(); } if (configStandalone.configProc.doublePipeline) { - if (configStandalone.DebugLevel >= 3) { - recPipeline->SetDebugLevelTmp(configStandalone.DebugLevel); + if (configStandalone.configProc.debugLevel >= 3) { + recPipeline->SetDebugLevelTmp(configStandalone.configProc.debugLevel); } chainTrackingPipeline = recPipeline->AddChain<GPUChainTracking>(); } @@ -943,15 +873,15 @@ int main(int argc, char** argv) double nClusters = chainTracking->GetTPCMerger().NMaxClusters(); if (nClusters > 0) { double nClsPerTF = 550000. * 1138.3; - double timePerTF = (configStandalone.configProc.doublePipeline ? pipelineWalltime : ((configStandalone.DebugLevel ? rec->GetStatKernelTime() : rec->GetStatWallTime()) / 1000000.)) * nClsPerTF / nClusters; + double timePerTF = (configStandalone.configProc.doublePipeline ? pipelineWalltime : ((configStandalone.configProc.debugLevel ? rec->GetStatKernelTime() : rec->GetStatWallTime()) / 1000000.)) * nClsPerTF / nClusters; double nGPUsReq = timePerTF / 0.02277; char stat[1024]; snprintf(stat, 1024, "Sync phase: %.2f sec per 256 orbit TF, %.1f GPUs required", timePerTF, nGPUsReq); if (configStandalone.testSyncAsync) { - timePerTF = (configStandalone.DebugLevel ? recAsync->GetStatKernelTime() : recAsync->GetStatWallTime()) / 1000000. * nClsPerTF / nClusters; + timePerTF = (configStandalone.configProc.debugLevel ? recAsync->GetStatKernelTime() : recAsync->GetStatWallTime()) / 1000000. * nClsPerTF / nClusters; snprintf(stat + strlen(stat), 1024 - strlen(stat), " - Async phase: %f sec per TF", timePerTF); } - printf("%s (Measured %s time - Extrapolated from %d clusters to %d)\n", stat, configStandalone.DebugLevel ? "kernel" : "wall", (int)nClusters, (int)nClsPerTF); + printf("%s (Measured %s time - Extrapolated from %d clusters to %d)\n", stat, configStandalone.configProc.debugLevel ? "kernel" : "wall", (int)nClusters, (int)nClsPerTF); } } @@ -970,7 +900,7 @@ int main(int argc, char** argv) } #ifndef _WIN32 - if (configStandalone.qa && configStandalone.fpe) { + if (configStandalone.configProc.runQA && configStandalone.fpe) { fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); } #endif diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index 6219e48a3d3b5..71f2c07f4e8ef 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -19,6 +19,7 @@ #include <functional> #include <iostream> #include <tuple> +#include <vector> #include "qconfig.h" // Create config instances @@ -345,6 +346,15 @@ inline int qAddOptionType<char>(qConfigSettings<char>& settings, char& ref, int& settings.doDefault); } template <> +inline int qAddOptionType<unsigned char>(qConfigSettings<unsigned char>& settings, unsigned char& ref, int& i, const char** argv, const int argc, unsigned char /*def*/) +{ + return qAddOptionGeneric<unsigned char>( + settings, ref, i, argv, argc, settings.set, [](const char* a) -> unsigned char { + return atoi(a); + }, + settings.doDefault); +} +template <> inline int qAddOptionType<int>(qConfigSettings<int>& settings, int& ref, int& i, const char** argv, const int argc, int /*def*/) { return qAddOptionGeneric<int>( @@ -363,19 +373,19 @@ inline int qAddOptionType<unsigned int>(qConfigSettings<unsigned int>& settings, settings.doDefault); } template <> -inline int qAddOptionType<long long int>(qConfigSettings<long long int>& settings, long long int& ref, int& i, const char** argv, const int argc, long long int /*def*/) +inline int qAddOptionType<long>(qConfigSettings<long>& settings, long& ref, int& i, const char** argv, const int argc, long /*def*/) { - return qAddOptionGeneric<long long int>( - settings, ref, i, argv, argc, settings.set, [](const char* a) -> long long int { + return qAddOptionGeneric<long>( + settings, ref, i, argv, argc, settings.set, [](const char* a) -> long { return strtoll(a, nullptr, 0); }, settings.doDefault); } template <> -inline int qAddOptionType<unsigned long long int>(qConfigSettings<unsigned long long int>& settings, unsigned long long int& ref, int& i, const char** argv, const int argc, unsigned long long int /*def*/) +inline int qAddOptionType<unsigned long>(qConfigSettings<unsigned long>& settings, unsigned long& ref, int& i, const char** argv, const int argc, unsigned long /*def*/) { - return qAddOptionGeneric<unsigned long long int>( - settings, ref, i, argv, argc, settings.set, [](const char* a) -> unsigned long long int { + return qAddOptionGeneric<unsigned long>( + settings, ref, i, argv, argc, settings.set, [](const char* a) -> unsigned long { return strtoull(a, nullptr, 0); }, settings.doDefault); diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index 47dcaabb97aea..fbd48373eac77 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -11,7 +11,7 @@ /// \file qconfig.h /// \author David Rohr -#include <vector> +#ifndef QCONFIG_HEADER_GUARD_NO_INCLUDE #define AddArrayDefaults(...) \ { \ @@ -124,6 +124,7 @@ goto repeat; \ } +// End QCONFIG_PARSE #elif defined(QCONFIG_HELP) #define AddOption(name, type, default, optname, optnameshort, ...) qConfigType<type>::qConfigHelpOption(qon_mxstr(name), qon_mxstr(type), qon_mxstr(default), optname, optnameshort, preopt, preoptshort, 0, __VA_ARGS__); #define AddOptionSet(name, type, value, optname, optnameshort, ...) qConfigType<type>::qConfigHelpOption(qon_mxstr(name), qon_mxstr(type), qon_mxstr(value), optname, optnameshort, preopt, preoptshort, 1, __VA_ARGS__); @@ -153,6 +154,7 @@ #define AddShortcut(cmd, cmdshort, forward, help, ...) qConfigType<void*>::qConfigHelpOption("shortcut", "shortcut", nullptr, cmd, cmdshort, preopt, preoptshort, 4, help); #define AddHelpText(text) printf("\n " text ":\n"); +// End QCONFIG_HELP #elif defined(QCONFIG_PRINT) #define AddOption(name, type, default, optname, optnameshort, ...) std::cout << "\t" << qon_mxstr(name) << ": " << tmp.name << "\n"; #define AddVariable(name, type, default) std::cout << "\t" << qon_mxstr(name) << ": " << tmp.name << "\n"; @@ -204,16 +206,16 @@ #define EndConfig() \ _qConfigDummy() {} -#elif defined(QCONFIG_EXTERNS) -#define AddOption(name, type, default, optname, optnameshort, help, ...) -#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) -#define AddOptionVec(name, type, optname, optnameshort, help, ...) -#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) -#define AddSubConfig(name, instance) -#define BeginConfig(name, instance) extern "C" name instance; -#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) -#define EndConfig() +// End QCONFIG_INSTANCE +#else // Define structures +#ifdef QCONFIG_HEADER_GUARD +#define QCONFIG_HEADER_GUARD_NO_INCLUDE +#ifdef QCONFIG_EXTERNS #undef QCONFIG_EXTERNS +#endif +#else +#define QCONFIG_HEADER_GUARD + extern int qConfigParse(int argc, const char** argv, const char* filename = nullptr); extern void qConfigPrint(); namespace qConfig @@ -244,7 +246,13 @@ enum qConfigRetVal { qcrOK = 0, #define EndConfig() #undef QCONFIG_EXTERNS -#if defined(QCONFIG_CPP11_INIT) && !defined(QCONFIG_GPU) +// End QCONFIG_EXTERNS +#elif defined(QCONFIG_CPP11_INIT) && !defined(QCONFIG_GPU) +#define BeginNamespace(name) \ + namespace name \ + { +#define EndNamespace() } +#define AddCustomCPP(...) __VA_ARGS__ #define AddOption(name, type, default, optname, optnameshort, help, ...) type name = default; #define AddVariable(name, type, default) type name = default; #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) @@ -321,10 +329,18 @@ struct qConfigDummy { #ifndef AddHelpText #define AddHelpText(text) #endif +#ifndef BeginNamespace +#define BeginNamespace(name) +#endif +#ifndef EndNamespace +#define EndNamespace() +#endif +#ifndef AddCustomCPP +#define AddCustomCPP(...) +#endif #ifndef QCONFIG_HEADER_GUARD_NO_INCLUDE #include "qconfigoptions.h" -#endif #undef AddOption #undef AddVariable @@ -351,3 +367,8 @@ struct qConfigDummy { #ifdef QCONFIG_EXTERNS #include "qconfig.h" #endif +#else +#undef QCONFIG_HEADER_GUARD_NO_INCLUDE +#endif + +#endif // QCONFIG_HEADER_GUARD_NO_INCLUDE diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx index c13e91238f5bd..7b5e948a99356 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx @@ -23,7 +23,7 @@ using namespace GPUCA_NAMESPACE::gpu; template <> GPUdii() void GPUTRDTrackerKernels::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) { - GPUCA_OPENMP(parallel for if(!processors.trdTracker.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(processors.trdTracker.GetRec().GetDeviceProcessingSettings().nThreads)) + GPUCA_OPENMP(parallel for if(!processors.trdTracker.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(processors.trdTracker.GetRec().GetDeviceProcessingSettings().ompThreads)) for (int i = get_global_id(0); i < processors.trdTracker.NTracks(); i += get_global_size(0)) { processors.trdTracker.DoTrackingThread(i, get_global_id(0)); } From d41f49568eb8d4963120c251414d0850238bc830 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 18 Jul 2020 23:32:57 +0200 Subject: [PATCH 0149/1751] GPU: Remove global extern instance of standalone config --- GPU/GPUTracking/Standalone/utils/qconfig.h | 25 +--------------------- 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index fbd48373eac77..8f65c6200a640 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -210,9 +210,6 @@ #else // Define structures #ifdef QCONFIG_HEADER_GUARD #define QCONFIG_HEADER_GUARD_NO_INCLUDE -#ifdef QCONFIG_EXTERNS -#undef QCONFIG_EXTERNS -#endif #else #define QCONFIG_HEADER_GUARD @@ -231,23 +228,7 @@ enum qConfigRetVal { qcrOK = 0, qcrArrayOverflow = 8 }; } -#if defined(QCONFIG_EXTERNS) -#define BeginNamespace(name) \ - namespace name \ - { -#define EndNamespace() } -#define AddOption(name, type, default, optname, optnameshort, help, ...) -#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) -#define AddOptionVec(name, type, optname, optnameshort, help, ...) -#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) -#define AddSubConfig(name, instance) -#define BeginConfig(name, instance) extern "C" name instance; -#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) -#define EndConfig() -#undef QCONFIG_EXTERNS - -// End QCONFIG_EXTERNS -#elif defined(QCONFIG_CPP11_INIT) && !defined(QCONFIG_GPU) +#if defined(QCONFIG_CPP11_INIT) && !defined(QCONFIG_GPU) #define BeginNamespace(name) \ namespace name \ { @@ -305,7 +286,6 @@ struct qConfigDummy { struct qConfigDummy { qConfigDummy() {} }; -#define QCONFIG_EXTERNS #endif #endif #endif @@ -364,9 +344,6 @@ struct qConfigDummy { #undef QCONFIG_COMPARE #endif -#ifdef QCONFIG_EXTERNS -#include "qconfig.h" -#endif #else #undef QCONFIG_HEADER_GUARD_NO_INCLUDE #endif From 58fa3509120bf075d28fbf440f982c3b9855d66d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 18 Jul 2020 23:43:43 +0200 Subject: [PATCH 0150/1751] GPU: Remove non C++11 style config option initializers --- GPU/GPUTracking/Base/GPUSettings.h | 4 +- .../Standalone/display/GPUDisplayConfig.h | 3 - GPU/GPUTracking/Standalone/qa/GPUQAConfig.h | 3 - GPU/GPUTracking/Standalone/utils/qconfig.h | 69 +++++-------------- 4 files changed, 18 insertions(+), 61 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index 717ded018b168..b582fa622d8e1 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -69,8 +69,8 @@ struct GPUSettingsProcessing { } // namespace gpu } // namespace GPUCA_NAMESPACE -#if !defined(__OPENCL__) || defined(__OPENCLCPP__) -#define QCONFIG_CPP11_INIT +#ifdef GPUCA_GPUCODE_DEVICE +#define QCONFIG_GPU #endif #include "utils/qconfig.h" diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h b/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h index edd5e146056ff..6cfe4fde927c4 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h @@ -16,9 +16,6 @@ #include "GPUCommonDef.h" -#if !defined(GPUCA_STANDALONE) -#define QCONFIG_CPP11_INIT -#endif #include "utils/qconfig.h" namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h b/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h index e7db99c592a8b..3d7d67d71493d 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h @@ -16,9 +16,6 @@ #include "GPUCommonDef.h" -#if !defined(GPUCA_STANDALONE) -#define QCONFIG_CPP11_INIT -#endif #include "utils/qconfig.h" namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index 8f65c6200a640..2dbca296a43a6 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -193,18 +193,15 @@ namespace name \ { #define EndNamespace() } -#define AddOption(name, type, default, optname, optnameshort, help, ...) name(default), -#define AddVariable(name, type, default) name(default), +#define AddOption(name, type, default, optname, optnameshort, help, ...) +#define AddVariable(name, type, default) #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) -#define AddOptionVec(name, type, optname, optnameshort, help, ...) name(), -#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) name default, -#define AddSubConfig(name, instance) instance(), -#define BeginConfig(name, instance) \ - name instance; \ - name::name() : -#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) name::name() : -#define EndConfig() \ - _qConfigDummy() {} +#define AddOptionVec(name, type, optname, optnameshort, help, ...) +#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) +#define AddSubConfig(name, instance) +#define BeginConfig(name, instance) name instance; +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) +#define EndConfig() // End QCONFIG_INSTANCE #else // Define structures @@ -228,66 +225,32 @@ enum qConfigRetVal { qcrOK = 0, qcrArrayOverflow = 8 }; } -#if defined(QCONFIG_CPP11_INIT) && !defined(QCONFIG_GPU) #define BeginNamespace(name) \ namespace name \ { #define EndNamespace() } #define AddCustomCPP(...) __VA_ARGS__ +#if !defined(QCONFIG_GPU) #define AddOption(name, type, default, optname, optnameshort, help, ...) type name = default; #define AddVariable(name, type, default) type name = default; -#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) -#define AddSubConfig(name, instance) name instance; #define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) type name[count] = {default}; #define AddOptionVec(name, type, optname, optnameshort, help, ...) std::vector<type> name; -#define BeginConfig(name, instance) \ - struct name { -#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ - struct name { -#define EndConfig() \ - } \ - ; #else -#define BeginNamespace(name) \ - namespace name \ - { -#define EndNamespace() } -#define AddCustomCPP(...) __VA_ARGS__ #define AddOption(name, type, default, optname, optnameshort, help, ...) type name; #define AddVariable(name, type, default) type name; -#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) -#define AddSubConfig(name, instance) name instance; #define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) type name[count]; -#define EndConfig() \ - qConfigDummy _qConfigDummy; \ - } \ - ; -#ifdef QCONFIG_GPU #define AddOptionVec(name, type, optname, optnameshort, help, ...) void* name[sizeof(std::vector<type>) / sizeof(void*)]; +#endif +#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) +#define AddSubConfig(name, instance) name instance; #define BeginConfig(name, instance) \ struct name { #define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ struct name { -struct qConfigDummy { -}; -#else -#define AddOptionVec(name, type, optname, optnameshort, help, ...) std::vector<type> name; -#define BeginConfig(name, instance) \ - struct name { \ - name(); \ - name(const name& s); \ - name& operator=(const name& s); -#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ - struct name { \ - name(); \ - name(const name& s); \ - name& operator=(const name& s); -; -struct qConfigDummy { - qConfigDummy() {} -}; -#endif -#endif +#define EndConfig() \ + } \ + ; + #endif #endif From 360d738ca7c54fb1dc9cddcd9b6f2943b29da1bc Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 19 Jul 2020 01:18:33 +0200 Subject: [PATCH 0151/1751] GPU: Separate config structure for standalone and for O2 --- GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx | 4 ++++ GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 6 ++++++ GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h | 1 - GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 6 ++++++ GPU/GPUTracking/Standalone/qa/GPUQAConfig.h | 1 - GPU/GPUTracking/Standalone/qconfigoptions.h | 10 ++++++++++ GPU/GPUTracking/Standalone/standalone.cxx | 5 +++++ 7 files changed, 31 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx index 46ba6bce5bc7b..430a6a9d2ea13 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx @@ -31,6 +31,10 @@ using namespace GPUCA_NAMESPACE::gpu; +namespace GPUCA_NAMESPACE::gpu +{ +extern GPUSettingsStandalone configStandalone; +} static auto& config = configStandalone.configTF; GPUReconstructionTimeframe::GPUReconstructionTimeframe(GPUChainTracking* chain, int (*read)(int), int nEvents) : mChain(chain), mReadEvent(read), mNEventsInDirectory(nEvents), mDisUniReal(0., 1.), mRndGen1(configStandalone.seed), mRndGen2(mDisUniInt(mRndGen1)) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index b7850ad3b00cb..2992b055826fa 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -78,6 +78,12 @@ using namespace GPUCA_NAMESPACE::gpu; #define GET_CID(slice, i) (tracker.Param().earlyTpcTransform ? tracker.ClusterData()[i].id : (tracker.GetConstantMem()->ioPtrs.clustersNative->clusterOffset[slice][0] + i)) +#ifdef GPUCA_STANDALONE +namespace GPUCA_NAMESPACE::gpu +{ +extern GPUSettingsStandalone configStandalone; +} +#endif static const GPUDisplay::configDisplay& GPUDisplay_GetConfig(GPUChainTracking* rec) { #if !defined(GPUCA_STANDALONE) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h b/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h index 6cfe4fde927c4..b4d44813e490c 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h @@ -23,7 +23,6 @@ namespace GPUCA_NAMESPACE namespace gpu { typedef GPUSettingsDisplay GPUDisplayConfig; -extern GPUSettingsStandalone configStandalone; } } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index fc0e9bbf2a536..434254d8f3473 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -136,6 +136,12 @@ using namespace GPUCA_NAMESPACE::gpu; CHECK_CLUSTER_STATE_CHK_NOCOUNT() //Fill state variables, do not increase counters // clang-format on +#ifdef GPUCA_STANDALONE +namespace GPUCA_NAMESPACE::gpu +{ +extern GPUSettingsStandalone configStandalone; +} +#endif static const GPUQA::configQA& GPUQA_GetConfig(GPUChainTracking* rec) { #if !defined(GPUCA_STANDALONE) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h b/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h index 3d7d67d71493d..97d9ba5622945 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h @@ -23,7 +23,6 @@ namespace GPUCA_NAMESPACE namespace gpu { typedef GPUSettingsQA GPUQAConfig; -extern GPUSettingsStandalone configStandalone; } } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index 2f710e5f1fd20..cc5a783bbed7b 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -162,6 +162,7 @@ AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinp AddHelp("help", 'h') EndConfig() +#ifdef GPUCA_STANDALONE // Settings concerning standalone toy event generator BeginSubConfig(GPUSettingsEG, configEG, configStandalone, "EG", 0, "Event generator settings") AddOption(numberOfTracks, int, 1, "", 0, "Number of tracks per generated event") @@ -239,6 +240,15 @@ AddSubConfig(GPUSettingsDisplay, configGL) AddSubConfig(GPUSettingsRec, configRec) AddSubConfig(GPUSettingsDeviceProcessing, configProc) EndConfig() +#elif defined(GPUCA_O2_LIB) // GPUCA_STANDALONE +BeginSubConfig(GPUSettingsO2, configGPUO2, configStandalone, "O2", 0, "O2 workflow settings") +AddOption(solenoidBz, float, -5.00668, "", 0, "solenoid field strength") +AddOption(constBz, bool, false, "", 0, "force constant Bz for tests") +AddOption(continuousMaxTimeBin, int, 0, "", 0, "maximum time bin of continuous data, 0 for triggered events, -1 for default of 23ms") +AddOption(deviceType, const char*, "CPU", "", 0, "Device type, CPU | CUDA | HIP | OCL1 | OCL2") +AddOption(forceDeviceType, bool, true, "", 0, "force device type, otherwise allows fall-back to CPU") +EndConfig() +#endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE EndNamespace() // gpu diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 33bc49d967410..5f0ec03d5a894 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -75,6 +75,11 @@ using namespace GPUCA_NAMESPACE::gpu; //#define BROKEN_EVENTS +namespace GPUCA_NAMESPACE::gpu +{ +extern GPUSettingsStandalone configStandalone; +} + GPUReconstruction *rec, *recAsync, *recPipeline; GPUChainTracking *chainTracking, *chainTrackingAsync, *chainTrackingPipeline; #ifdef HAVE_O2HEADERS From e1e808a59e0be0960f7a65d3ee2e695d6cc21041 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 19 Jul 2020 10:51:35 +0200 Subject: [PATCH 0152/1751] GPU: Rename some settings (clearer and shorter names) --- .../reconstruction/test/testGPUCATracking.cxx | 12 +- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 24 +- GPU/GPUTracking/Base/GPUParam.cxx | 4 +- GPU/GPUTracking/Base/GPUParam.h | 4 +- GPU/GPUTracking/Base/GPUProcessor.cxx | 2 +- GPU/GPUTracking/Base/GPUReconstruction.cxx | 150 +++++----- GPU/GPUTracking/Base/GPUReconstruction.h | 40 +-- GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 30 +- GPU/GPUTracking/Base/GPUReconstructionCPU.h | 24 +- .../Base/GPUReconstructionDeviceBase.cxx | 38 +-- .../Base/GPUReconstructionDeviceBase.h | 2 +- .../Base/GPUReconstructionIncludes.h | 36 +-- GPU/GPUTracking/Base/GPUSettings.cxx | 2 +- GPU/GPUTracking/Base/GPUSettings.h | 4 +- .../Base/cuda/GPUReconstructionCUDA.cu | 54 ++-- .../Base/cuda/GPUReconstructionCUDA.h | 6 +- .../Base/hip/GPUReconstructionHIP.h | 6 +- .../Base/hip/GPUReconstructionHIP.hip.cxx | 48 +-- .../opencl-common/GPUReconstructionOCL.cxx | 60 ++-- .../Base/opencl-common/GPUReconstructionOCL.h | 6 +- .../GPUReconstructionOCLInternals.h | 4 +- .../Base/opencl/GPUReconstructionOCL1.cxx | 6 +- .../Base/opencl/GPUReconstructionOCL1.h | 6 +- .../Base/opencl2/GPUReconstructionOCL2.cxx | 8 +- .../Base/opencl2/GPUReconstructionOCL2.h | 6 +- .../DataCompression/GPUTPCCompression.cxx | 8 +- GPU/GPUTracking/Global/GPUChain.h | 14 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 278 +++++++++--------- GPU/GPUTracking/Interface/GPUO2Interface.cxx | 6 +- .../Interface/GPUO2InterfaceConfiguration.h | 5 +- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 16 +- GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx | 4 +- .../Merger/GPUTPCGlobalMergerComponent.cxx | 2 +- .../SliceTracker/GPUTPCTracker.cxx | 18 +- .../SliceTracker/GPUTPCTrackerComponent.cxx | 2 +- .../SliceTracker/GPUTPCTrackerDump.cxx | 6 +- .../Standalone/display/GPUDisplay.cxx | 8 +- GPU/GPUTracking/Standalone/qconfigoptions.h | 4 +- GPU/GPUTracking/Standalone/standalone.cxx | 6 +- .../TPCClusterFinder/GPUTPCClusterFinder.cxx | 4 +- .../TRDTracking/GPUTRDTrackerComponent.cxx | 2 +- .../TRDTracking/GPUTRDTrackerKernels.cxx | 2 +- .../TRDTracking/macros/run_trd_tracker.C | 2 +- 43 files changed, 485 insertions(+), 484 deletions(-) diff --git a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx index c1eef94639e54..8b7037120aecf 100644 --- a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx @@ -51,13 +51,13 @@ BOOST_AUTO_TEST_CASE(CATracking_test1) bool continuous = false; //time frame data v.s. triggered events GPUO2InterfaceConfiguration config; - config.configProcessing.deviceType = GPUDataTypes::DeviceType::CPU; - config.configProcessing.forceDeviceType = true; + config.configDeviceBackend.deviceType = GPUDataTypes::DeviceType::CPU; + config.configDeviceBackend.forceDeviceType = true; - config.configDeviceProcessing.ompThreads = 4; //4 threads if we run on the CPU, 1 = default, 0 = auto-detect - config.configDeviceProcessing.runQA = false; //Run QA after tracking - config.configDeviceProcessing.eventDisplay = nullptr; //Ptr to event display backend, for running standalone OpenGL event display - //config.configDeviceProcessing.eventDisplay = new GPUDisplayBackendGlfw; + config.configProcessing.ompThreads = 4; //4 threads if we run on the CPU, 1 = default, 0 = auto-detect + config.configProcessing.runQA = false; //Run QA after tracking + config.configProcessing.eventDisplay = nullptr; //Ptr to event display backend, for running standalone OpenGL event display + //config.configProcessing.eventDisplay = new GPUDisplayBackendGlfw; config.configEvent.solenoidBz = solenoidBz; config.configEvent.continuousMaxTimeBin = continuous ? GPUSettings::TPC_MAX_TF_TIME_BIN : 0; //Number of timebins in timeframe if continuous, 0 otherwise diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index a4a793a458fdb..10407716c7f93 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -225,11 +225,11 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int processAttributes->suppressOutput = (dump == 2); GPUO2InterfaceConfiguration config; if (useGPU) { - config.configProcessing.deviceType = GPUDataTypes::GetDeviceType(gpuType); + config.configDeviceBackend.deviceType = GPUDataTypes::GetDeviceType(gpuType); } else { - config.configProcessing.deviceType = GPUDataTypes::DeviceType::CPU; + config.configDeviceBackend.deviceType = GPUDataTypes::DeviceType::CPU; } - config.configProcessing.forceDeviceType = true; // If we request a GPU, we force that it is available - no CPU fallback + config.configDeviceBackend.forceDeviceType = true; // If we request a GPU, we force that it is available - no CPU fallback if (gpuDevice == -2) { int myId = ic.services().get<const o2::framework::DeviceSpec>().inputTimesliceId; @@ -237,16 +237,16 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int gpuDevice = myId; LOG(INFO) << "GPU device number selected from pipeline id: " << myId << " / " << idMax; } - config.configDeviceProcessing.deviceNum = gpuDevice; - config.configDeviceProcessing.ompThreads = nThreads; - config.configDeviceProcessing.runQA = qa; // Run QA after tracking - config.configDeviceProcessing.runMC = specconfig.processMC; // Propagate MC labels - config.configDeviceProcessing.eventDisplay = display; // Ptr to event display backend, for running standalone OpenGL event display - config.configDeviceProcessing.debugLevel = debugLevel; // Debug verbosity - config.configDeviceProcessing.forceMemoryPoolSize = memoryPoolSize; // GPU / Host Memory pool size, default = 1 = auto-detect - config.configDeviceProcessing.forceHostMemoryPoolSize = hostMemoryPoolSize; // Same for host, overrides the avove value for the host if set + config.configProcessing.deviceNum = gpuDevice; + config.configProcessing.ompThreads = nThreads; + config.configProcessing.runQA = qa; // Run QA after tracking + config.configProcessing.runMC = specconfig.processMC; // Propagate MC labels + config.configProcessing.eventDisplay = display; // Ptr to event display backend, for running standalone OpenGL event display + config.configProcessing.debugLevel = debugLevel; // Debug verbosity + config.configProcessing.forceMemoryPoolSize = memoryPoolSize; // GPU / Host Memory pool size, default = 1 = auto-detect + config.configProcessing.forceHostMemoryPoolSize = hostMemoryPoolSize; // Same for host, overrides the avove value for the host if set if (memoryPoolSize || hostMemoryPoolSize) { - config.configDeviceProcessing.memoryAllocationStrategy = 2; + config.configProcessing.memoryAllocationStrategy = 2; } config.configEvent.solenoidBz = solenoidBz; diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 3a5087674b0aa..066392f0e7794 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -120,7 +120,7 @@ void GPUParam::SetDefaults(float solenoidBz) GPUTPCGMPolynomialFieldManager::GetPolynomialField(BzkG, polynomialField); } -void GPUParam::UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsDeviceProcessing* p) +void GPUParam::UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsProcessing* p) { if (e) { AssumeConstantBz = e->constBz; @@ -141,7 +141,7 @@ void GPUParam::UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsD earlyTpcTransform = rec.ForceEarlyTPCTransform == -1 ? (!ContinuousTracking) : rec.ForceEarlyTPCTransform; } -void GPUParam::SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r, const GPUSettingsDeviceProcessing* p, const GPURecoStepConfiguration* w) +void GPUParam::SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r, const GPUSettingsProcessing* p, const GPURecoStepConfiguration* w) { SetDefaults(e->solenoidBz); if (w) { diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index f76f109a8869b..0cc23fdb70f1c 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -63,8 +63,8 @@ struct GPUParam { #ifndef GPUCA_GPUCODE void SetDefaults(float solenoidBz); - void SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r = nullptr, const GPUSettingsDeviceProcessing* p = nullptr, const GPURecoStepConfiguration* w = nullptr); - void UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsDeviceProcessing* p = nullptr); + void SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r = nullptr, const GPUSettingsProcessing* p = nullptr, const GPURecoStepConfiguration* w = nullptr); + void UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsProcessing* p = nullptr); void LoadClusterErrors(bool Print = 0); #endif diff --git a/GPU/GPUTracking/Base/GPUProcessor.cxx b/GPU/GPUTracking/Base/GPUProcessor.cxx index fe3b27ae646f0..c6408f1d04530 100644 --- a/GPU/GPUTracking/Base/GPUProcessor.cxx +++ b/GPU/GPUTracking/Base/GPUProcessor.cxx @@ -21,7 +21,7 @@ GPUProcessor::GPUProcessor() : mRec(nullptr), mGPUProcessorType(PROCESSOR_TYPE_C GPUProcessor::~GPUProcessor() { - if (mRec && mRec->GetDeviceProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (mRec && mRec->GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { Clear(); } } diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 114243f14c846..b3da6adc0e504 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -76,10 +76,10 @@ constexpr GPUReconstruction::GeometryType GPUReconstruction::geometryType; static long long int ptrDiff(void* a, void* b) { return (long long int)((char*)a - (char*)b); } -GPUReconstruction::GPUReconstruction(const GPUSettingsProcessing& cfg) : mHostConstantMem(new GPUConstantMem), mProcessingSettings(cfg) +GPUReconstruction::GPUReconstruction(const GPUSettingsDeviceBackend& cfg) : mHostConstantMem(new GPUConstantMem), mDeviceBackendSettings(cfg) { if (cfg.master) { - if (cfg.master->mProcessingSettings.deviceType != cfg.deviceType) { + if (cfg.master->mDeviceBackendSettings.deviceType != cfg.deviceType) { throw std::invalid_argument("device type of master and slave GPUReconstruction does not match"); } if (cfg.master->mMaster) { @@ -88,7 +88,7 @@ GPUReconstruction::GPUReconstruction(const GPUSettingsProcessing& cfg) : mHostCo mMaster = cfg.master; cfg.master->mSlaves.emplace_back(this); } - new (&mDeviceProcessingSettings) GPUSettingsDeviceProcessing; + new (&mProcessingSettings) GPUSettingsProcessing; new (&mEventSettings) GPUSettingsEvent; param().SetDefaults(&mEventSettings); mMemoryScalers.reset(new GPUMemorySizeScalers); @@ -193,84 +193,84 @@ int GPUReconstruction::InitPhaseBeforeDevice() mRecoStepsGPU.set((unsigned char)0); } - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_AUTO) { - mDeviceProcessingSettings.memoryAllocationStrategy = IsGPU() ? GPUMemoryResource::ALLOCATION_GLOBAL : GPUMemoryResource::ALLOCATION_INDIVIDUAL; + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_AUTO) { + mProcessingSettings.memoryAllocationStrategy = IsGPU() ? GPUMemoryResource::ALLOCATION_GLOBAL : GPUMemoryResource::ALLOCATION_INDIVIDUAL; } - if (mDeviceProcessingSettings.debugLevel >= 4) { - mDeviceProcessingSettings.keepAllMemory = true; + if (mProcessingSettings.debugLevel >= 4) { + mProcessingSettings.keepAllMemory = true; } - if (mDeviceProcessingSettings.debugLevel >= 5 && mDeviceProcessingSettings.allocDebugLevel < 2) { - mDeviceProcessingSettings.allocDebugLevel = 2; + if (mProcessingSettings.debugLevel >= 5 && mProcessingSettings.allocDebugLevel < 2) { + mProcessingSettings.allocDebugLevel = 2; } - if (mDeviceProcessingSettings.eventDisplay || mDeviceProcessingSettings.keepAllMemory) { - mDeviceProcessingSettings.keepDisplayMemory = true; + if (mProcessingSettings.eventDisplay || mProcessingSettings.keepAllMemory) { + mProcessingSettings.keepDisplayMemory = true; } - if (mDeviceProcessingSettings.debugLevel < 6) { - mDeviceProcessingSettings.debugMask = 0; + if (mProcessingSettings.debugLevel < 6) { + mProcessingSettings.debugMask = 0; } - if (mDeviceProcessingSettings.debugLevel < 1) { - mDeviceProcessingSettings.deviceTimers = false; + if (mProcessingSettings.debugLevel < 1) { + mProcessingSettings.deviceTimers = false; } - if (mDeviceProcessingSettings.debugLevel >= 6 && mDeviceProcessingSettings.comparableDebutOutput) { - mDeviceProcessingSettings.nTPCClustererLanes = 1; - if (mDeviceProcessingSettings.trackletConstructorInPipeline < 0) { - mDeviceProcessingSettings.trackletConstructorInPipeline = 1; + if (mProcessingSettings.debugLevel >= 6 && mProcessingSettings.comparableDebutOutput) { + mProcessingSettings.nTPCClustererLanes = 1; + if (mProcessingSettings.trackletConstructorInPipeline < 0) { + mProcessingSettings.trackletConstructorInPipeline = 1; } - if (mDeviceProcessingSettings.trackletSelectorInPipeline < 0) { - mDeviceProcessingSettings.trackletSelectorInPipeline = 1; + if (mProcessingSettings.trackletSelectorInPipeline < 0) { + mProcessingSettings.trackletSelectorInPipeline = 1; } - if (mDeviceProcessingSettings.trackletSelectorSlices < 0) { - mDeviceProcessingSettings.trackletSelectorSlices = 1; + if (mProcessingSettings.trackletSelectorSlices < 0) { + mProcessingSettings.trackletSelectorSlices = 1; } } - if (mDeviceProcessingSettings.tpcCompressionGatherMode < 0) { - mDeviceProcessingSettings.tpcCompressionGatherMode = (mRecoStepsGPU & GPUDataTypes::RecoStep::TPCCompression) ? 2 : 0; + if (mProcessingSettings.tpcCompressionGatherMode < 0) { + mProcessingSettings.tpcCompressionGatherMode = (mRecoStepsGPU & GPUDataTypes::RecoStep::TPCCompression) ? 2 : 0; } if (!(mRecoStepsGPU & GPUDataTypes::RecoStep::TPCMerging)) { - mDeviceProcessingSettings.mergerSortTracks = false; + mProcessingSettings.mergerSortTracks = false; } if (!IsGPU()) { - mDeviceProcessingSettings.nDeviceHelperThreads = 0; + mProcessingSettings.nDeviceHelperThreads = 0; } if (param().rec.NonConsecutiveIDs) { param().rec.DisableRefitAttachment = 0xFF; } if (!(mRecoStepsGPU & RecoStep::TPCMerging) || !param().rec.mergerReadFromTrackerDirectly) { - mDeviceProcessingSettings.fullMergerOnGPU = false; + mProcessingSettings.fullMergerOnGPU = false; } - if (mDeviceProcessingSettings.debugLevel || !mDeviceProcessingSettings.fullMergerOnGPU) { - mDeviceProcessingSettings.delayedOutput = false; + if (mProcessingSettings.debugLevel || !mProcessingSettings.fullMergerOnGPU) { + mProcessingSettings.delayedOutput = false; } UpdateSettings(); GPUCA_GPUReconstructionUpdateDefailts(); - if (!mDeviceProcessingSettings.trackletConstructorInPipeline) { - mDeviceProcessingSettings.trackletSelectorInPipeline = false; + if (!mProcessingSettings.trackletConstructorInPipeline) { + mProcessingSettings.trackletSelectorInPipeline = false; } - mMemoryScalers->factor = mDeviceProcessingSettings.memoryScalingFactor; + mMemoryScalers->factor = mProcessingSettings.memoryScalingFactor; #ifdef WITH_OPENMP - if (mDeviceProcessingSettings.ompThreads <= 0) { - mDeviceProcessingSettings.ompThreads = omp_get_max_threads(); + if (mProcessingSettings.ompThreads <= 0) { + mProcessingSettings.ompThreads = omp_get_max_threads(); } else { - omp_set_num_threads(mDeviceProcessingSettings.ompThreads); + omp_set_num_threads(mProcessingSettings.ompThreads); } #else - mDeviceProcessingSettings.ompThreads = 1; + mProcessingSettings.ompThreads = 1; #endif - mMaxThreads = std::max(mMaxThreads, mDeviceProcessingSettings.ompThreads); + mMaxThreads = std::max(mMaxThreads, mProcessingSettings.ompThreads); if (IsGPU()) { - mNStreams = std::max(mDeviceProcessingSettings.nStreams, 3); + mNStreams = std::max(mProcessingSettings.nStreams, 3); } - if (mDeviceProcessingSettings.doublePipeline && (mChains.size() != 1 || mChains[0]->SupportsDoublePipeline() == false || !IsGPU() || mDeviceProcessingSettings.memoryAllocationStrategy != GPUMemoryResource::ALLOCATION_GLOBAL)) { + if (mProcessingSettings.doublePipeline && (mChains.size() != 1 || mChains[0]->SupportsDoublePipeline() == false || !IsGPU() || mProcessingSettings.memoryAllocationStrategy != GPUMemoryResource::ALLOCATION_GLOBAL)) { GPUError("Must use double pipeline mode only with exactly one chain that must support it"); return 1; } - if (mMaster == nullptr && mDeviceProcessingSettings.doublePipeline) { + if (mMaster == nullptr && mProcessingSettings.doublePipeline) { mPipelineContext.reset(new GPUReconstructionPipelineContext); } @@ -282,13 +282,13 @@ int GPUReconstruction::InitPhaseBeforeDevice() mDeviceMemorySize += memGpu; mHostMemorySize += memHost; } - if (mDeviceProcessingSettings.forceMemoryPoolSize && mDeviceProcessingSettings.forceMemoryPoolSize <= 2 && CanQueryMaxMemory()) { - mDeviceMemorySize = mDeviceProcessingSettings.forceMemoryPoolSize; - } else if (mDeviceProcessingSettings.forceMemoryPoolSize > 2) { - mDeviceMemorySize = mHostMemorySize = mDeviceProcessingSettings.forceMemoryPoolSize; + if (mProcessingSettings.forceMemoryPoolSize && mProcessingSettings.forceMemoryPoolSize <= 2 && CanQueryMaxMemory()) { + mDeviceMemorySize = mProcessingSettings.forceMemoryPoolSize; + } else if (mProcessingSettings.forceMemoryPoolSize > 2) { + mDeviceMemorySize = mHostMemorySize = mProcessingSettings.forceMemoryPoolSize; } - if (mDeviceProcessingSettings.forceHostMemoryPoolSize) { - mHostMemorySize = mDeviceProcessingSettings.forceHostMemoryPoolSize; + if (mProcessingSettings.forceHostMemoryPoolSize) { + mHostMemorySize = mProcessingSettings.forceHostMemoryPoolSize; } for (unsigned int i = 0; i < mProcessors.size(); i++) { @@ -355,7 +355,7 @@ int GPUReconstruction::Exit() mChains.clear(); // Make sure we destroy a possible ITS GPU tracker before we call the destructors mHostConstantMem.reset(); // Reset these explicitly before the destruction of other members unloads the library - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { for (unsigned int i = 0; i < mMemoryResources.size(); i++) { if (mMemoryResources[i].mReuse >= 0) { continue; @@ -392,7 +392,7 @@ void GPUReconstruction::ComputeReuseMax(GPUProcessor* proc) size_t GPUReconstruction::AllocateRegisteredMemory(GPUProcessor* proc, bool resetCustom) { - if (mDeviceProcessingSettings.debugLevel >= 5) { + if (mProcessingSettings.debugLevel >= 5) { GPUInfo("Allocating memory %p", (void*)proc); } size_t total = 0; @@ -405,7 +405,7 @@ size_t GPUReconstruction::AllocateRegisteredMemory(GPUProcessor* proc, bool rese } } } - if (mDeviceProcessingSettings.debugLevel >= 5) { + if (mProcessingSettings.debugLevel >= 5) { GPUInfo("Allocating memory done"); } return total; @@ -413,7 +413,7 @@ size_t GPUReconstruction::AllocateRegisteredMemory(GPUProcessor* proc, bool rese size_t GPUReconstruction::AllocateRegisteredPermanentMemory() { - if (mDeviceProcessingSettings.debugLevel >= 5) { + if (mProcessingSettings.debugLevel >= 5) { GPUInfo("Allocating Permanent Memory"); } int total = 0; @@ -424,7 +424,7 @@ size_t GPUReconstruction::AllocateRegisteredPermanentMemory() } mHostMemoryPermanent = mHostMemoryPool; mDeviceMemoryPermanent = mDeviceMemoryPool; - if (mDeviceProcessingSettings.debugLevel >= 5) { + if (mProcessingSettings.debugLevel >= 5) { GPUInfo("Permanent Memory Done"); } return total; @@ -443,7 +443,7 @@ size_t GPUReconstruction::AllocateRegisteredMemoryHelper(GPUMemoryResource* res, GPUError("Insufficient reuse memory %lu < %lu (%s)", mMemoryResources[res->mReuse].mSize, retVal, res->mName); throw std::bad_alloc(); } - if (mDeviceProcessingSettings.allocDebugLevel >= 2) { + if (mProcessingSettings.allocDebugLevel >= 2) { std::cout << "Reused " << res->mName << ": " << retVal << "\n"; } return retVal; @@ -477,7 +477,7 @@ size_t GPUReconstruction::AllocateRegisteredMemoryHelper(GPUMemoryResource* res, std::cout << "Memory pool size exceeded (" << res->mName << ": " << (memorypoolend ? (memorysize + ((char*)memorypool - (char*)memorypoolend)) : (char*)memorypool - (char*)memorybase) << " < " << memorysize << "\n"; throw std::bad_alloc(); } - if (mDeviceProcessingSettings.allocDebugLevel >= 2) { + if (mProcessingSettings.allocDebugLevel >= 2) { std::cout << "Allocated " << res->mName << ": " << retVal << " - available: " << (memorypoolend ? ((char*)memorypoolend - (char*)memorypool) : (memorysize - ((char*)memorypool - (char*)memorybase))) << "\n"; } return retVal; @@ -485,7 +485,7 @@ size_t GPUReconstruction::AllocateRegisteredMemoryHelper(GPUMemoryResource* res, void GPUReconstruction::AllocateRegisteredMemoryInternal(GPUMemoryResource* res, GPUOutputControl* control, GPUReconstruction* recPool) { - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL && (control == nullptr || control->OutputType == GPUOutputControl::AllocateInternal)) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL && (control == nullptr || control->OutputType == GPUOutputControl::AllocateInternal)) { if (!(res->mType & GPUMemoryResource::MEMORY_EXTERNAL)) { if (res->mPtrDevice && res->mReuse < 0) { operator delete(res->mPtrDevice GPUCA_OPERATOR_NEW_ALIGNMENT); @@ -502,7 +502,7 @@ void GPUReconstruction::AllocateRegisteredMemoryInternal(GPUMemoryResource* res, } res->mPtr = GPUProcessor::alignPointer<GPUCA_BUFFER_ALIGNMENT>(res->mPtrDevice); res->SetPointers(res->mPtr); - if (mDeviceProcessingSettings.allocDebugLevel >= 2) { + if (mProcessingSettings.allocDebugLevel >= 2) { std::cout << (res->mReuse >= 0 ? "Reused " : "Allocated ") << res->mName << ": " << res->mSize << "\n"; } } @@ -514,7 +514,7 @@ void GPUReconstruction::AllocateRegisteredMemoryInternal(GPUMemoryResource* res, if (IsGPU() && res->mOverrideSize < GPUCA_BUFFER_ALIGNMENT) { res->mOverrideSize = GPUCA_BUFFER_ALIGNMENT; } - if ((!IsGPU() || (res->mType & GPUMemoryResource::MEMORY_HOST) || mDeviceProcessingSettings.keepDisplayMemory) && !(res->mType & GPUMemoryResource::MEMORY_EXTERNAL)) { // keepAllMemory --> keepDisplayMemory + if ((!IsGPU() || (res->mType & GPUMemoryResource::MEMORY_HOST) || mProcessingSettings.keepDisplayMemory) && !(res->mType & GPUMemoryResource::MEMORY_EXTERNAL)) { // keepAllMemory --> keepDisplayMemory if (control && control->OutputType == GPUOutputControl::UseExternalBuffer) { if (control->OutputAllocator) { res->mSize = std::max((size_t)res->SetPointers((void*)1) - 1, res->mOverrideSize); @@ -567,7 +567,7 @@ void* GPUReconstruction::AllocateUnmanagedMemory(size_t size, int type) if (type != GPUMemoryResource::MEMORY_HOST && (!IsGPU() || type != GPUMemoryResource::MEMORY_GPU)) { throw std::bad_alloc(); } - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { mUnmanagedChunks.emplace_back(new char[size + GPUCA_BUFFER_ALIGNMENT]); return GPUProcessor::alignPointer<GPUCA_BUFFER_ALIGNMENT>(mUnmanagedChunks.back().get()); } else { @@ -637,10 +637,10 @@ void GPUReconstruction::FreeRegisteredMemory(GPUProcessor* proc, bool freeCustom void GPUReconstruction::FreeRegisteredMemory(short ires) { GPUMemoryResource* res = &mMemoryResources[ires]; - if (mDeviceProcessingSettings.allocDebugLevel >= 2 && (res->mPtr || res->mPtrDevice)) { + if (mProcessingSettings.allocDebugLevel >= 2 && (res->mPtr || res->mPtrDevice)) { std::cout << "Freeing " << res->mName << ": size " << res->mSize << " (reused " << res->mReuse << ")\n"; } - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL && res->mReuse < 0) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL && res->mReuse < 0) { operator delete(res->mPtrDevice GPUCA_OPERATOR_NEW_ALIGNMENT); } res->mPtr = nullptr; @@ -662,10 +662,10 @@ void GPUReconstruction::PushNonPersistentMemory() void GPUReconstruction::PopNonPersistentMemory(RecoStep step) { - if (mDeviceProcessingSettings.debugLevel >= 3 || mDeviceProcessingSettings.allocDebugLevel) { + if (mProcessingSettings.debugLevel >= 3 || mProcessingSettings.allocDebugLevel) { printf("Allocated memory after %30s: %'13lld (non temporary %'13lld, blocked %'13lld)\n", GPUDataTypes::RECO_STEP_NAMES[getRecoStepNum(step, true)], ptrDiff(mDeviceMemoryPool, mDeviceMemoryBase) + ptrDiff((char*)mDeviceMemoryBase + mDeviceMemorySize, mDeviceMemoryPoolEnd), ptrDiff(mDeviceMemoryPool, mDeviceMemoryBase), mDeviceMemoryPoolBlocked == nullptr ? 0ll : ptrDiff((char*)mDeviceMemoryBase + mDeviceMemorySize, mDeviceMemoryPoolBlocked)); } - if (mDeviceProcessingSettings.keepDisplayMemory || mDeviceProcessingSettings.disableMemoryReuse) { + if (mProcessingSettings.keepDisplayMemory || mProcessingSettings.disableMemoryReuse) { return; } mHostMemoryPoolEnd = mNonPersistentMemoryStack.back().first; @@ -727,7 +727,7 @@ void GPUReconstruction::PrintMemoryMax() void GPUReconstruction::PrintMemoryOverview() { - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { printf("Memory Allocation: Host %'lld / %'lld (Permanent %'lld), Device %'lld / %'lld, (Permanent %'lld) %d chunks\n", ptrDiff(mHostMemoryPool, mHostMemoryBase) + ptrDiff((char*)mHostMemoryBase + mHostMemorySize, mHostMemoryPoolEnd), (long long int)mHostMemorySize, ptrDiff(mHostMemoryPermanent, mHostMemoryBase), ptrDiff(mDeviceMemoryPool, mDeviceMemoryBase) + ptrDiff((char*)mDeviceMemoryBase + mDeviceMemorySize, mDeviceMemoryPoolEnd), (long long int)mDeviceMemorySize, ptrDiff(mDeviceMemoryPermanent, mDeviceMemoryBase), (int)mMemoryResources.size()); @@ -782,10 +782,10 @@ int GPUReconstruction::getGeneralStepNum(GeneralStep step, bool validCheck) { re void GPUReconstruction::RunPipelineWorker() { - if (!mInitialized || !mDeviceProcessingSettings.doublePipeline || mMaster != nullptr || !mSlaves.size()) { + if (!mInitialized || !mProcessingSettings.doublePipeline || mMaster != nullptr || !mSlaves.size()) { throw std::invalid_argument("Cannot start double pipeline mode"); } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("Pipeline worker started"); } bool terminate = false; @@ -809,7 +809,7 @@ void GPUReconstruction::RunPipelineWorker() q->done = true; q->c.notify_one(); } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("Pipeline worker ended"); } } @@ -892,7 +892,7 @@ void GPUReconstruction::DumpSettings(const char* dir) } } -void GPUReconstruction::UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsDeviceProcessing* p) +void GPUReconstruction::UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsProcessing* p) { param().UpdateEventSettings(e, p); if (mInitialized) { @@ -924,7 +924,7 @@ void GPUReconstruction::SetSettings(float solenoidBz) SetSettings(&ev, nullptr, nullptr); } -void GPUReconstruction::SetSettings(const GPUSettingsEvent* settings, const GPUSettingsRec* rec, const GPUSettingsDeviceProcessing* proc, const GPURecoStepConfiguration* workflow) +void GPUReconstruction::SetSettings(const GPUSettingsEvent* settings, const GPUSettingsRec* rec, const GPUSettingsProcessing* proc, const GPURecoStepConfiguration* workflow) { if (mInitialized) { GPUError("Cannot update settings while initialized"); @@ -932,7 +932,7 @@ void GPUReconstruction::SetSettings(const GPUSettingsEvent* settings, const GPUS } mEventSettings = *settings; if (proc) { - mDeviceProcessingSettings = *proc; + mProcessingSettings = *proc; } if (workflow) { mRecoSteps = workflow->steps; @@ -959,15 +959,15 @@ std::unique_ptr<GPUReconstruction::GPUThreadContext> GPUReconstruction::GetThrea GPUReconstruction* GPUReconstruction::CreateInstance(DeviceType type, bool forceType, GPUReconstruction* master) { - GPUSettingsProcessing cfg; - new (&cfg) GPUSettingsProcessing; + GPUSettingsDeviceBackend cfg; + new (&cfg) GPUSettingsDeviceBackend; cfg.deviceType = type; cfg.forceDeviceType = forceType; cfg.master = master; return CreateInstance(cfg); } -GPUReconstruction* GPUReconstruction::CreateInstance(const GPUSettingsProcessing& cfg) +GPUReconstruction* GPUReconstruction::CreateInstance(const GPUSettingsDeviceBackend& cfg) { GPUReconstruction* retVal = nullptr; unsigned int type = cfg.deviceType; @@ -999,7 +999,7 @@ GPUReconstruction* GPUReconstruction::CreateInstance(const GPUSettingsProcessing GPUError("Error: Could not load GPUReconstruction for specified device: %s (%u)", DEVICE_TYPE_NAMES[type], type); } else { GPUError("Could not load GPUReconstruction for device type %s (%u), falling back to CPU version", DEVICE_TYPE_NAMES[type], type); - GPUSettingsProcessing cfg2 = cfg; + GPUSettingsDeviceBackend cfg2 = cfg; cfg2.deviceType = DeviceType::CPU; retVal = CreateInstance(cfg2); } @@ -1106,7 +1106,7 @@ int GPUReconstruction::LibraryLoader::LoadLibrary() return 0; } -GPUReconstruction* GPUReconstruction::LibraryLoader::GetPtr(const GPUSettingsProcessing& cfg) +GPUReconstruction* GPUReconstruction::LibraryLoader::GetPtr(const GPUSettingsDeviceBackend& cfg) { if (LoadLibrary()) { return nullptr; @@ -1114,7 +1114,7 @@ GPUReconstruction* GPUReconstruction::LibraryLoader::GetPtr(const GPUSettingsPro if (mGPUEntry == nullptr) { return nullptr; } - GPUReconstruction* (*tmp)(const GPUSettingsProcessing& cfg) = (GPUReconstruction * (*)(const GPUSettingsProcessing& cfg)) mGPUEntry; + GPUReconstruction* (*tmp)(const GPUSettingsDeviceBackend& cfg) = (GPUReconstruction * (*)(const GPUSettingsDeviceBackend& cfg)) mGPUEntry; return tmp(cfg); } diff --git a/GPU/GPUTracking/Base/GPUReconstruction.h b/GPU/GPUTracking/Base/GPUReconstruction.h index bff0aa230ad24..2aa74e9dbf0b3 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.h +++ b/GPU/GPUTracking/Base/GPUReconstruction.h @@ -105,7 +105,7 @@ class GPUReconstruction static unsigned int getNIOTypeMultiplicity(InOutPointerType type) { return (type == CLUSTER_DATA || type == SLICE_OUT_TRACK || type == SLICE_OUT_CLUSTER || type == RAW_CLUSTERS || type == TPC_DIGIT) ? NSLICES : 1; } // Functionality to create an instance of GPUReconstruction for the desired device - static GPUReconstruction* CreateInstance(const GPUSettingsProcessing& cfg); + static GPUReconstruction* CreateInstance(const GPUSettingsDeviceBackend& cfg); static GPUReconstruction* CreateInstance(DeviceType type = DeviceType::CPU, bool forceType = true, GPUReconstruction* master = nullptr); static GPUReconstruction* CreateInstance(int type, bool forceType, GPUReconstruction* master = nullptr) { return CreateInstance((DeviceType)type, forceType, master); } static GPUReconstruction* CreateInstance(const char* type, bool forceType, GPUReconstruction* master = nullptr); @@ -217,19 +217,19 @@ class GPUReconstruction bool slavesExist() { return mSlaves.size() || mMaster; } // Getters / setters for parameters - DeviceType GetDeviceType() const { return (DeviceType)mProcessingSettings.deviceType; } + DeviceType GetDeviceType() const { return (DeviceType)mDeviceBackendSettings.deviceType; } bool IsGPU() const { return GetDeviceType() != DeviceType::INVALID_DEVICE && GetDeviceType() != DeviceType::CPU; } const GPUParam& GetParam() const { return mHostConstantMem->param; } const GPUConstantMem& GetConstantMem() const { return *mHostConstantMem; } const GPUSettingsEvent& GetEventSettings() const { return mEventSettings; } - const GPUSettingsProcessing& GetProcessingSettings() { return mProcessingSettings; } - const GPUSettingsDeviceProcessing& GetDeviceProcessingSettings() const { return mDeviceProcessingSettings; } + const GPUSettingsDeviceBackend& GetDeviceBackendSettings() { return mDeviceBackendSettings; } + const GPUSettingsProcessing& GetProcessingSettings() const { return mProcessingSettings; } bool IsInitialized() const { return mInitialized; } void SetSettings(float solenoidBz); - void SetSettings(const GPUSettingsEvent* settings, const GPUSettingsRec* rec = nullptr, const GPUSettingsDeviceProcessing* proc = nullptr, const GPURecoStepConfiguration* workflow = nullptr); - void SetResetTimers(bool reset) { mDeviceProcessingSettings.resetTimers = reset; } // May update also after Init() - void SetDebugLevelTmp(int level) { mDeviceProcessingSettings.debugLevel = level; } // Temporarily, before calling SetSettings() - void UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsDeviceProcessing* p = nullptr); + void SetSettings(const GPUSettingsEvent* settings, const GPUSettingsRec* rec = nullptr, const GPUSettingsProcessing* proc = nullptr, const GPURecoStepConfiguration* workflow = nullptr); + void SetResetTimers(bool reset) { mProcessingSettings.resetTimers = reset; } // May update also after Init() + void SetDebugLevelTmp(int level) { mProcessingSettings.debugLevel = level; } // Temporarily, before calling SetSettings() + void UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsProcessing* p = nullptr); void SetOutputControl(const GPUOutputControl& v) { mOutputControl = v; } void SetOutputControl(void* ptr, size_t size); void SetInputControl(void* ptr, size_t size); @@ -260,7 +260,7 @@ class GPUReconstruction protected: void AllocateRegisteredMemoryInternal(GPUMemoryResource* res, GPUOutputControl* control, GPUReconstruction* recPool); - GPUReconstruction(const GPUSettingsProcessing& cfg); // Constructor + GPUReconstruction(const GPUSettingsDeviceBackend& cfg); // Constructor int InitPhaseBeforeDevice(); virtual void UpdateSettings() {} virtual int InitDevice() = 0; @@ -319,8 +319,8 @@ class GPUReconstruction // Settings GPUSettingsEvent mEventSettings; // Event Parameters - GPUSettingsProcessing mProcessingSettings; // Processing Parameters (at constructor level) - GPUSettingsDeviceProcessing mDeviceProcessingSettings; // Processing Parameters (at init level) + GPUSettingsDeviceBackend mDeviceBackendSettings; // Processing Parameters (at constructor level) + GPUSettingsProcessing mProcessingSettings; // Processing Parameters (at init level) GPUOutputControl mOutputControl; // Controls the output of the individual components GPUOutputControl mInputControl; // Prefefined input memory location for reading standalone dumps std::unique_ptr<GPUMemorySizeScalers> mMemoryScalers; // Scalers how much memory will be needed @@ -397,7 +397,7 @@ class GPUReconstruction LibraryLoader(const char* lib, const char* func); int LoadLibrary(); int CloseLibrary(); - GPUReconstruction* GetPtr(const GPUSettingsProcessing& cfg); + GPUReconstruction* GetPtr(const GPUSettingsDeviceBackend& cfg); const char* mLibName; const char* mFuncName; @@ -406,7 +406,7 @@ class GPUReconstruction }; static std::shared_ptr<LibraryLoader> sLibCUDA, sLibHIP, sLibOCL, sLibOCL2; - static GPUReconstruction* GPUReconstruction_Create_CPU(const GPUSettingsProcessing& cfg); + static GPUReconstruction* GPUReconstruction_Create_CPU(const GPUSettingsDeviceBackend& cfg); }; template <class T> @@ -426,7 +426,7 @@ inline T* GPUReconstruction::AllocateIOMemoryHelper(size_t n, const T*& ptr, std } else { u.reset(new T[n]); retVal = u.get(); - if (mDeviceProcessingSettings.registerStandaloneInputMemory) { + if (mProcessingSettings.registerStandaloneInputMemory) { if (registerMemoryForGPU(u.get(), n * sizeof(T))) { GPUError("Error registering memory for GPU: %p - %lld bytes\n", (void*)u.get(), (long long int)(n * sizeof(T))); throw std::bad_alloc(); @@ -448,7 +448,7 @@ template <class T> inline short GPUReconstruction::RegisterMemoryAllocation(T* proc, void* (T::*setPtr)(void*), int type, const char* name, const GPUMemoryReuse& re) { if (!(type & (GPUMemoryResource::MEMORY_HOST | GPUMemoryResource::MEMORY_GPU))) { - if ((type & GPUMemoryResource::MEMORY_SCRATCH) && !mDeviceProcessingSettings.keepDisplayMemory) { // keepAllMemory --> keepDisplayMemory + if ((type & GPUMemoryResource::MEMORY_SCRATCH) && !mProcessingSettings.keepDisplayMemory) { // keepAllMemory --> keepDisplayMemory type |= (proc->mGPUProcessorType == GPUProcessor::PROCESSOR_TYPE_CPU ? GPUMemoryResource::MEMORY_HOST : GPUMemoryResource::MEMORY_GPU); } else { type |= GPUMemoryResource::MEMORY_HOST | GPUMemoryResource::MEMORY_GPU; @@ -462,7 +462,7 @@ inline short GPUReconstruction::RegisterMemoryAllocation(T* proc, void* (T::*set throw std::bad_alloc(); } unsigned short retVal = mMemoryResources.size() - 1; - if (re.type != GPUMemoryReuse::NONE && !mDeviceProcessingSettings.disableMemoryReuse) { + if (re.type != GPUMemoryReuse::NONE && !mProcessingSettings.disableMemoryReuse) { const auto& it = mMemoryReuse1to1.find(re.id); if (it == mMemoryReuse1to1.end()) { mMemoryReuse1to1[re.id] = {proc, retVal}; @@ -548,7 +548,7 @@ inline size_t GPUReconstruction::ReadData(FILE* fp, const T** entries, S* num, s numTotal += num[i]; } (void)r; - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Read %lld %s", (long long int)numTotal, IOTYPENAMES[type]); } return numTotal; @@ -588,7 +588,7 @@ inline std::unique_ptr<T> GPUReconstruction::ReadFlatObjectFromFile(const char* r = fread((void*)retVal.get(), 1, size[0], fp); r = fread(buf, 1, size[1], fp); fclose(fp); - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Read %lld bytes from %s", (long long int)r, file); } retVal->clearInternalBufferPtr(); @@ -627,7 +627,7 @@ inline std::unique_ptr<T> GPUReconstruction::ReadStructFromFile(const char* file std::unique_ptr<T> newObj(new T); r = fread(newObj.get(), 1, size, fp); fclose(fp); - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Read %lld bytes from %s", (long long int)r, file); } return newObj; @@ -648,7 +648,7 @@ inline int GPUReconstruction::ReadStructFromFile(const char* file, T* obj) } r = fread(obj, 1, size, fp); fclose(fp); - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Read %lld bytes from %s", (long long int)r, file); } return 0; diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index 55e84ff7a9f9e..98712cb7b417d 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -51,7 +51,7 @@ using namespace GPUCA_NAMESPACE::gpu; constexpr GPUReconstructionCPU::krnlRunRange GPUReconstructionCPU::krnlRunRangeNone; constexpr GPUReconstructionCPU::krnlEvent GPUReconstructionCPU::krnlEventNone; -GPUReconstruction* GPUReconstruction::GPUReconstruction_Create_CPU(const GPUSettingsProcessing& cfg) { return new GPUReconstructionCPU(cfg); } +GPUReconstruction* GPUReconstruction::GPUReconstruction_Create_CPU(const GPUSettingsDeviceBackend& cfg) { return new GPUReconstructionCPU(cfg); } GPUReconstructionCPU::~GPUReconstructionCPU() { @@ -71,8 +71,8 @@ int GPUReconstructionCPUBackend::runKernelBackend(krnlSetup& _xyz, const Args&.. } unsigned int num = y.num == 0 || y.num == -1 ? 1 : y.num; for (unsigned int k = 0; k < num; k++) { - if (mDeviceProcessingSettings.ompKernels) { - GPUCA_OPENMP(parallel for num_threads(mDeviceProcessingSettings.ompThreads)) + if (mProcessingSettings.ompKernels) { + GPUCA_OPENMP(parallel for num_threads(mProcessingSettings.ompThreads)) for (unsigned int iB = 0; iB < x.nBlocks; iB++) { typename T::GPUSharedMemory smem; T::template Thread<I>(x.nBlocks, 1, iB, 0, smem, T::Processor(*mHostConstantMem)[y.start + k], args...); @@ -125,7 +125,7 @@ size_t GPUReconstructionCPU::TransferMemoryResourcesHelper(GPUProcessor* proc, i if (!(res.mType & GPUMemoryResource::MEMORY_GPU) || (res.mType & GPUMemoryResource::MEMORY_CUSTOM_TRANSFER)) { continue; } - if (!mDeviceProcessingSettings.keepAllMemory && !all && (res.mType & exc) && !(res.mType & inc)) { + if (!mProcessingSettings.keepAllMemory && !all && (res.mType & exc) && !(res.mType & inc)) { continue; } if (toGPU) { @@ -151,7 +151,7 @@ int GPUReconstructionCPU::GetThread() int GPUReconstructionCPU::InitDevice() { - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { if (mDeviceMemorySize > mHostMemorySize) { mHostMemorySize = mDeviceMemorySize; } @@ -161,7 +161,7 @@ int GPUReconstructionCPU::InitDevice() mHostMemoryPermanent = mHostMemoryBase; ClearAllocatedMemory(); } - if (mDeviceProcessingSettings.ompKernels) { + if (mProcessingSettings.ompKernels) { mBlockCount = getOMPMaxThreads(); } mThreadId = GetThread(); @@ -170,7 +170,7 @@ int GPUReconstructionCPU::InitDevice() int GPUReconstructionCPU::ExitDevice() { - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { if (mMaster == nullptr) { operator delete(mHostMemoryBase); } @@ -186,13 +186,13 @@ int GPUReconstructionCPU::RunChains() mNEventsProcessed++; timerTotal.Start(); - if (mDeviceProcessingSettings.doublePipeline) { + if (mProcessingSettings.doublePipeline) { if (EnqueuePipeline()) { return 1; } } else { if (mThreadId != GetThread()) { - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Thread changed, migrating context, Previous Thread: %d, New Thread: %d", mThreadId, GetThread()); } mThreadId = GetThread(); @@ -210,7 +210,7 @@ int GPUReconstructionCPU::RunChains() timerTotal.Stop(); mStatWallTime = (timerTotal.GetElapsedTime() * 1000000. / mStatNEvents); - if (GetDeviceProcessingSettings().debugLevel >= 1) { + if (GetProcessingSettings().debugLevel >= 1) { double kernelTotal = 0; std::vector<double> kernelStepTimes(GPUDataTypes::N_RECO_STEPS); @@ -222,7 +222,7 @@ int GPUReconstructionCPU::RunChains() for (int j = 0; j < mTimers[i]->num; j++) { HighResTimer& timer = mTimers[i]->timer[j]; time += timer.GetElapsedTime(); - if (mDeviceProcessingSettings.resetTimers) { + if (mProcessingSettings.resetTimers) { timer.Reset(); } } @@ -239,7 +239,7 @@ int GPUReconstructionCPU::RunChains() snprintf(bandwidth, 256, " (%6.3f GB/s - %'14lu bytes)", mTimers[i]->memSize / time * 1e-9, (unsigned long)(mTimers[i]->memSize / mStatNEvents)); } printf("Execution Time: Task (%c %8ux): %50s Time: %'10d us%s\n", type, mTimers[i]->count, mTimers[i]->name.c_str(), (int)(time * 1000000 / mStatNEvents), bandwidth); - if (mDeviceProcessingSettings.resetTimers) { + if (mProcessingSettings.resetTimers) { mTimers[i]->count = 0; mTimers[i]->memSize = 0; } @@ -256,7 +256,7 @@ int GPUReconstructionCPU::RunChains() printf("Execution Time: Step (D %8ux): %11s %38s Time: %'10d us (%6.3f GB/s - %'14lu bytes - %'14lu per call)\n", mTimersRecoSteps[i].countToHost, "DMA to Host", GPUDataTypes::RECO_STEP_NAMES[i], (int)(mTimersRecoSteps[i].timerToHost.GetElapsedTime() * 1000000 / mStatNEvents), mTimersRecoSteps[i].bytesToHost / mTimersRecoSteps[i].timerToHost.GetElapsedTime() * 1e-9, mTimersRecoSteps[i].bytesToHost / mStatNEvents, mTimersRecoSteps[i].bytesToHost / mTimersRecoSteps[i].countToHost); } - if (mDeviceProcessingSettings.resetTimers) { + if (mProcessingSettings.resetTimers) { mTimersRecoSteps[i].bytesToGPU = mTimersRecoSteps[i].bytesToHost = 0; mTimersRecoSteps[i].timerToGPU.Reset(); mTimersRecoSteps[i].timerToHost.Reset(); @@ -273,10 +273,10 @@ int GPUReconstructionCPU::RunChains() mStatKernelTime = kernelTotal * 1000000 / mStatNEvents; printf("Execution Time: Total : %50s Time: %'10d us\n", "Total Kernel", (int)mStatKernelTime); printf("Execution Time: Total : %50s Time: %'10d us\n", "Total Wall", (int)mStatWallTime); - } else if (GetDeviceProcessingSettings().debugLevel >= 0) { + } else if (GetProcessingSettings().debugLevel >= 0) { printf("Total Wall Time: %'d us\n", (int)mStatWallTime); } - if (mDeviceProcessingSettings.resetTimers) { + if (mProcessingSettings.resetTimers) { mStatNEvents = 0; timerTotal.Reset(); } diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.h b/GPU/GPUTracking/Base/GPUReconstructionCPU.h index 940d50385fc84..adc8594d46fe3 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.h +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.h @@ -51,7 +51,7 @@ class GPUReconstructionCPUBackend : public GPUReconstruction ~GPUReconstructionCPUBackend() override = default; protected: - GPUReconstructionCPUBackend(const GPUSettingsProcessing& cfg) : GPUReconstruction(cfg) {} + GPUReconstructionCPUBackend(const GPUSettingsDeviceBackend& cfg) : GPUReconstruction(cfg) {} template <class T, int I = 0, typename... Args> int runKernelBackend(krnlSetup& _xyz, const Args&... args); template <class T, int I> @@ -66,7 +66,7 @@ class GPUReconstructionKernels : public T template <class X, int Y = 0> using classArgument = GPUReconstruction::classArgument<X, Y>; virtual ~GPUReconstructionKernels() = default; // NOLINT: BUG: Do not declare override in template class! AMD hcc will not create the destructor otherwise. - GPUReconstructionKernels(const GPUSettingsProcessing& cfg) : T(cfg) {} + GPUReconstructionKernels(const GPUSettingsDeviceBackend& cfg) : T(cfg) {} protected: #define GPUCA_KRNL(x_class, attributes, x_arguments, x_forward) \ @@ -92,7 +92,7 @@ class GPUReconstructionKernels<GPUReconstructionCPUBackend> : public GPUReconstr template <class X, int Y = 0> using classArgument = GPUReconstruction::classArgument<X, Y>; virtual ~GPUReconstructionKernels() = default; // NOLINT: Do not declare override in template class! AMD hcc will not create the destructor otherwise. - GPUReconstructionKernels(const GPUSettingsProcessing& cfg) : GPUReconstructionCPUBackend(cfg) {} + GPUReconstructionKernels(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionCPUBackend(cfg) {} protected: #define GPUCA_KRNL(x_class, x_attributes, x_arguments, x_forward) \ @@ -105,7 +105,7 @@ class GPUReconstructionKernels<GPUReconstructionCPUBackend> : public GPUReconstr class GPUReconstructionCPU : public GPUReconstructionKernels<GPUReconstructionCPUBackend> { - friend GPUReconstruction* GPUReconstruction::GPUReconstruction_Create_CPU(const GPUSettingsProcessing& cfg); + friend GPUReconstruction* GPUReconstruction::GPUReconstruction_Create_CPU(const GPUSettingsDeviceBackend& cfg); friend class GPUChain; public: @@ -154,7 +154,7 @@ class GPUReconstructionCPU : public GPUReconstructionKernels<GPUReconstructionCP short mMemoryResProcessors = -1; }; - GPUReconstructionCPU(const GPUSettingsProcessing& cfg) : GPUReconstructionKernels(cfg) {} + GPUReconstructionCPU(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionKernels(cfg) {} virtual void SynchronizeStream(int stream) {} virtual void SynchronizeEvents(deviceEvent* evList, int nEvents = 1) {} @@ -267,15 +267,15 @@ inline int GPUReconstructionCPU::runKernel(const krnlExec& x, const krnlRunRange if (nThreads > GPUCA_MAX_THREADS) { throw std::runtime_error("GPUCA_MAX_THREADS exceeded"); } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("Running kernel %s (Stream %d, Range %d/%d, Grid %d/%d) on %s", GetKernelName<S, I>(), x.stream, y.start, y.num, nBlocks, nThreads, cpuFallback == 2 ? "CPU (forced)" : cpuFallback ? "CPU (fallback)" : mDeviceName.c_str()); } if (nThreads == 0 || nBlocks == 0) { return 0; } - if (mDeviceProcessingSettings.debugLevel >= 0) { + if (mProcessingSettings.debugLevel >= 0) { t = &getKernelTimer<S, I, J>(myStep, !IsGPU() || cpuFallback ? getOMPThreadNum() : x.stream); - if (!mDeviceProcessingSettings.deviceTimers || !IsGPU() || cpuFallback) { + if (!mProcessingSettings.deviceTimers || !IsGPU() || cpuFallback) { t->Start(); } } @@ -289,18 +289,18 @@ inline int GPUReconstructionCPU::runKernel(const krnlExec& x, const krnlRunRange return 1; } } - if (mDeviceProcessingSettings.debugLevel >= 0) { + if (mProcessingSettings.debugLevel >= 0) { if (GPUDebug(GetKernelName<S, I>(), x.stream)) { throw std::runtime_error("kernel failure"); } if (t) { - if (!mDeviceProcessingSettings.deviceTimers || !IsGPU() || cpuFallback) { + if (!mProcessingSettings.deviceTimers || !IsGPU() || cpuFallback) { t->Stop(); } else { t->AddTime(setup.t); } } - if (mDeviceProcessingSettings.debugLevel >= 1 && CheckErrorCodes()) { + if (mProcessingSettings.debugLevel >= 1 && CheckErrorCodes()) { throw std::runtime_error("kernel error code"); } } @@ -346,7 +346,7 @@ HighResTimer& GPUReconstructionCPU::getTimer(const char* name, int num) static int id = getNextTimerId(); timerMeta* timer = getTimerById(id); if (timer == nullptr) { - int max = std::max({getOMPMaxThreads(), mDeviceProcessingSettings.nDeviceHelperThreads + 1, mDeviceProcessingSettings.nStreams}); + int max = std::max({getOMPMaxThreads(), mProcessingSettings.nDeviceHelperThreads + 1, mProcessingSettings.nStreams}); timer = insertTimer(id, name, J, max, 1, RecoStep::NoRecoStep); } if (num == -1) { diff --git a/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.cxx b/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.cxx index 6b8bc57037e46..9b71edde5659c 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.cxx @@ -32,7 +32,7 @@ class GPUTPCRow; #define SemLockName "AliceHLTTPCGPUTrackerInitLockSem" -GPUReconstructionDeviceBase::GPUReconstructionDeviceBase(const GPUSettingsProcessing& cfg, size_t sizeCheck) : GPUReconstructionCPU(cfg) +GPUReconstructionDeviceBase::GPUReconstructionDeviceBase(const GPUSettingsDeviceBackend& cfg, size_t sizeCheck) : GPUReconstructionCPU(cfg) { if (sizeCheck != sizeof(GPUReconstructionDeviceBase)) { GPUFatal("Mismatch of C++ object size between GPU compilers!"); @@ -55,7 +55,7 @@ void* GPUReconstructionDeviceBase::helperWrapper_static(void* arg) void* GPUReconstructionDeviceBase::helperWrapper(GPUReconstructionHelpers::helperParam* par) { - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("\tHelper thread %d starting", par->num); } @@ -66,8 +66,8 @@ void* GPUReconstructionDeviceBase::helperWrapper(GPUReconstructionHelpers::helpe par->mutex[0].lock(); while (par->terminate == false) { - for (int i = par->num + 1; i < par->count; i += mDeviceProcessingSettings.nDeviceHelperThreads + 1) { - // if (mDeviceProcessingSettings.debugLevel >= 3) GPUInfo("\tHelper Thread %d Running, Slice %d+%d, Phase %d", par->num, i, par->phase); + for (int i = par->num + 1; i < par->count; i += mProcessingSettings.nDeviceHelperThreads + 1) { + // if (mProcessingSettings.debugLevel >= 3) GPUInfo("\tHelper Thread %d Running, Slice %d+%d, Phase %d", par->num, i, par->phase); if ((par->functionCls->*par->function)(i, par->num + 1, par)) { par->error = 1; } @@ -75,12 +75,12 @@ void* GPUReconstructionDeviceBase::helperWrapper(GPUReconstructionHelpers::helpe break; } par->done = i + 1; - // if (mDeviceProcessingSettings.debugLevel >= 3) GPUInfo("\tHelper Thread %d Finished, Slice %d+%d, Phase %d", par->num, i, par->phase); + // if (mProcessingSettings.debugLevel >= 3) GPUInfo("\tHelper Thread %d Finished, Slice %d+%d, Phase %d", par->num, i, par->phase); } ResetThisHelperThread(par); par->mutex[0].lock(); } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("\tHelper thread %d terminating", par->num); } par->mutex[1].unlock(); @@ -145,11 +145,11 @@ void GPUReconstructionDeviceBase::ReleaseGlobalLock(void* sem) void GPUReconstructionDeviceBase::ResetHelperThreads(int helpers) { - GPUImportant("Error occurred, GPU tracker helper threads will be reset (Number of threads %d (%d))", mDeviceProcessingSettings.nDeviceHelperThreads, mNSlaveThreads); + GPUImportant("Error occurred, GPU tracker helper threads will be reset (Number of threads %d (%d))", mProcessingSettings.nDeviceHelperThreads, mNSlaveThreads); SynchronizeGPU(); - for (int i = 0; i < mDeviceProcessingSettings.nDeviceHelperThreads; i++) { + for (int i = 0; i < mProcessingSettings.nDeviceHelperThreads; i++) { mHelperParams[i].reset = true; - if (helpers || i >= mDeviceProcessingSettings.nDeviceHelperThreads) { + if (helpers || i >= mProcessingSettings.nDeviceHelperThreads) { pthread_mutex_lock(&((pthread_mutex_t*)mHelperParams[i].mutex)[1]); } } @@ -158,7 +158,7 @@ void GPUReconstructionDeviceBase::ResetHelperThreads(int helpers) int GPUReconstructionDeviceBase::StartHelperThreads() { - int nThreads = mDeviceProcessingSettings.nDeviceHelperThreads; + int nThreads = mProcessingSettings.nDeviceHelperThreads; if (nThreads) { mHelperParams = new GPUReconstructionHelpers::helperParam[nThreads]; if (mHelperParams == nullptr) { @@ -206,14 +206,14 @@ int GPUReconstructionDeviceBase::StopHelperThreads() void GPUReconstructionDeviceBase::WaitForHelperThreads() { - for (int i = 0; i < mDeviceProcessingSettings.nDeviceHelperThreads; i++) { + for (int i = 0; i < mProcessingSettings.nDeviceHelperThreads; i++) { pthread_mutex_lock(&((pthread_mutex_t*)mHelperParams[i].mutex)[1]); } } void GPUReconstructionDeviceBase::RunHelperThreads(int (GPUReconstructionHelpers::helperDelegateBase::*function)(int i, int t, GPUReconstructionHelpers::helperParam* p), GPUReconstructionHelpers::helperDelegateBase* functionCls, int count) { - for (int i = 0; i < mDeviceProcessingSettings.nDeviceHelperThreads; i++) { + for (int i = 0; i < mProcessingSettings.nDeviceHelperThreads; i++) { mHelperParams[i].done = 0; mHelperParams[i].error = 0; mHelperParams[i].function = function; @@ -230,22 +230,22 @@ int GPUReconstructionDeviceBase::InitDevice() // CPU_SET(0, &mask); // sched_setaffinity(0, sizeof(mask), &mask); - if (mDeviceProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { GPUError("Individual memory allocation strategy unsupported for device\n"); return (1); } - if (mDeviceProcessingSettings.nStreams > GPUCA_MAX_STREAMS) { - GPUError("Too many straems requested %d > %d\n", mDeviceProcessingSettings.nStreams, GPUCA_MAX_STREAMS); + if (mProcessingSettings.nStreams > GPUCA_MAX_STREAMS) { + GPUError("Too many straems requested %d > %d\n", mProcessingSettings.nStreams, GPUCA_MAX_STREAMS); return (1); } mThreadId = GetThread(); void* semLock = nullptr; - if (mDeviceProcessingSettings.globalInitMutex && GetGlobalLock(semLock)) { + if (mProcessingSettings.globalInitMutex && GetGlobalLock(semLock)) { return (1); } - if (mDeviceProcessingSettings.deviceTimers) { + if (mProcessingSettings.deviceTimers) { AddGPUEvents(mDebugEvents); } @@ -255,7 +255,7 @@ int GPUReconstructionDeviceBase::InitDevice() return (1); } - if (mDeviceProcessingSettings.globalInitMutex) { + if (mProcessingSettings.globalInitMutex) { ReleaseGlobalLock(semLock); } @@ -271,7 +271,7 @@ int GPUReconstructionDeviceBase::InitDevice() return (1); } - if (mMaster == nullptr || mDeviceProcessingSettings.debugLevel >= 2) { + if (mMaster == nullptr || mProcessingSettings.debugLevel >= 2) { GPUInfo("GPU Tracker initialization successfull"); // Verbosity reduced because GPU backend will print GPUImportant message! } diff --git a/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.h b/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.h index cb3a2bc1d95d2..7e81e7b59151a 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.h +++ b/GPU/GPUTracking/Base/GPUReconstructionDeviceBase.h @@ -35,7 +35,7 @@ class GPUReconstructionDeviceBase : public GPUReconstructionCPU const GPUParam* DeviceParam() const { return &mDeviceConstantMem->param; } protected: - GPUReconstructionDeviceBase(const GPUSettingsProcessing& cfg, size_t sizeCheck); + GPUReconstructionDeviceBase(const GPUSettingsDeviceBackend& cfg, size_t sizeCheck); int InitDevice() override; virtual int InitDevice_Runtime() = 0; diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h index c7f409cb45453..6c2af2842bc68 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h @@ -43,24 +43,24 @@ #define RANDOM_ERROR //#define RANDOM_ERROR || rand() % 500 == 1 -#define GPUCA_GPUReconstructionUpdateDefailts() \ - if (mDeviceProcessingSettings.trackletConstructorInPipeline < 0) { \ - mDeviceProcessingSettings.trackletConstructorInPipeline = GPUCA_CONSTRUCTOR_IN_PIPELINE; \ - } \ - if (mDeviceProcessingSettings.trackletSelectorInPipeline < 0) { \ - mDeviceProcessingSettings.trackletSelectorInPipeline = GPUCA_SELECTOR_IN_PIPELINE; \ - } \ - if (mDeviceProcessingSettings.trackletSelectorSlices < 0) { \ - mDeviceProcessingSettings.trackletSelectorSlices = GPUCA_TRACKLET_SELECTOR_SLICE_COUNT; \ - } \ - if (mDeviceProcessingSettings.alternateBorderSort < 0) { \ - mDeviceProcessingSettings.alternateBorderSort = GPUCA_ALTERNATE_BORDER_SORT; \ - } \ - if (mDeviceProcessingSettings.mergerSortTracks < 0) { \ - mDeviceProcessingSettings.mergerSortTracks = GPUCA_SORT_BEFORE_FIT; \ - } \ - if (param().rec.loopInterpolationInExtraPass < 0) { \ - param().rec.loopInterpolationInExtraPass = GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION; \ +#define GPUCA_GPUReconstructionUpdateDefailts() \ + if (mProcessingSettings.trackletConstructorInPipeline < 0) { \ + mProcessingSettings.trackletConstructorInPipeline = GPUCA_CONSTRUCTOR_IN_PIPELINE; \ + } \ + if (mProcessingSettings.trackletSelectorInPipeline < 0) { \ + mProcessingSettings.trackletSelectorInPipeline = GPUCA_SELECTOR_IN_PIPELINE; \ + } \ + if (mProcessingSettings.trackletSelectorSlices < 0) { \ + mProcessingSettings.trackletSelectorSlices = GPUCA_TRACKLET_SELECTOR_SLICE_COUNT; \ + } \ + if (mProcessingSettings.alternateBorderSort < 0) { \ + mProcessingSettings.alternateBorderSort = GPUCA_ALTERNATE_BORDER_SORT; \ + } \ + if (mProcessingSettings.mergerSortTracks < 0) { \ + mProcessingSettings.mergerSortTracks = GPUCA_SORT_BEFORE_FIT; \ + } \ + if (param().rec.loopInterpolationInExtraPass < 0) { \ + param().rec.loopInterpolationInExtraPass = GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION; \ } #endif diff --git a/GPU/GPUTracking/Base/GPUSettings.cxx b/GPU/GPUTracking/Base/GPUSettings.cxx index 4ec538dd843ac..f7156a1fad96d 100644 --- a/GPU/GPUTracking/Base/GPUSettings.cxx +++ b/GPU/GPUTracking/Base/GPUSettings.cxx @@ -18,7 +18,7 @@ using namespace GPUCA_NAMESPACE::gpu; -GPUSettingsProcessing::GPUSettingsProcessing() +GPUSettingsDeviceBackend::GPUSettingsDeviceBackend() { deviceType = GPUDataTypes::DeviceType::CPU; forceDeviceType = true; diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index b582fa622d8e1..a99dd343a5e9d 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -59,8 +59,8 @@ struct GPUSettingsEvent { }; // Settings defining the setup of the GPUReconstruction processing (basically selecting the device / class instance) -struct GPUSettingsProcessing { - GPUSettingsProcessing(); +struct GPUSettingsDeviceBackend { + GPUSettingsDeviceBackend(); unsigned int deviceType; // Device type, shall use GPUDataTypes::DEVICE_TYPE constants, e.g. CPU / CUDA char forceDeviceType; // Fail if device initialization fails, otherwise falls back to CPU GPUReconstruction* master; // GPUReconstruction master object diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 06ca876ccdfb9..0a7a122adc1ea 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -142,14 +142,14 @@ GPUg() void runKernelCUDA(GPUCA_CONSMEM_PTR int iSlice_internal, Args... args) template <> void GPUReconstructionCUDABackend::runKernelBackendInternal<GPUMemClean16, 0>(krnlSetup& _xyz, void* const& ptr, unsigned long const& size) { - GPUDebugTiming timer(mDeviceProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); + GPUDebugTiming timer(mProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); GPUFailedMsg(cudaMemsetAsync(ptr, 0, size, mInternals->Streams[_xyz.x.stream])); } template <class T, int I, typename... Args> void GPUReconstructionCUDABackend::runKernelBackendInternal(krnlSetup& _xyz, const Args&... args) { - GPUDebugTiming timer(mDeviceProcessingSettings.deviceTimers, (void**)mDebugEvents, mInternals->Streams, _xyz); + GPUDebugTiming timer(mProcessingSettings.deviceTimers, (void**)mDebugEvents, mInternals->Streams, _xyz); backendInternal<T, I>::runKernelBackendMacro(_xyz, this, args...); } @@ -171,12 +171,12 @@ int GPUReconstructionCUDABackend::runKernelBackend(krnlSetup& _xyz, const Args&. return 0; } -GPUReconstructionCUDABackend::GPUReconstructionCUDABackend(const GPUSettingsProcessing& cfg) : GPUReconstructionDeviceBase(cfg, sizeof(GPUReconstructionDeviceBase)) +GPUReconstructionCUDABackend::GPUReconstructionCUDABackend(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionDeviceBase(cfg, sizeof(GPUReconstructionDeviceBase)) { if (mMaster == nullptr) { mInternals = new GPUReconstructionCUDAInternals; } - mProcessingSettings.deviceType = DeviceType::CUDA; + mDeviceBackendSettings.deviceType = DeviceType::CUDA; } GPUReconstructionCUDABackend::~GPUReconstructionCUDABackend() @@ -187,7 +187,7 @@ GPUReconstructionCUDABackend::~GPUReconstructionCUDABackend() } } -GPUReconstruction* GPUReconstruction_Create_CUDA(const GPUSettingsProcessing& cfg) { return new GPUReconstructionCUDA(cfg); } +GPUReconstruction* GPUReconstruction_Create_CUDA(const GPUSettingsDeviceBackend& cfg) { return new GPUReconstructionCUDA(cfg); } void GPUReconstructionCUDABackend::GetITSTraits(std::unique_ptr<o2::its::TrackerTraits>* trackerTraits, std::unique_ptr<o2::its::VertexerTraits>* vertexerTraits) { @@ -218,7 +218,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUError("Error getting CUDA Device Count"); return (1); } - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Available CUDA devices:"); } const int reqVerMaj = 2; @@ -227,7 +227,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() std::vector<size_t> devMemory(count, 0); bool contextCreated = false; for (int i = 0; i < count; i++) { - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Examining device %d", i); } size_t free, total; @@ -237,14 +237,14 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() return (1); } if (GPUFailedMsgI(cuCtxCreate(&mInternals->CudaContext, 0, tmpDevice))) { - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUWarning("Couldn't create context for device %d. Skipping it.", i); } continue; } contextCreated = true; if (GPUFailedMsgI(cuMemGetInfo(&free, &total))) { - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUWarning("Error obtaining CUDA memory info about device %d! Skipping it.", i); } GPUFailedMsg(cuCtxDestroy(mInternals->CudaContext)); @@ -254,13 +254,13 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUFailedMsg(cuCtxDestroy(mInternals->CudaContext)); contextCreated = false; } - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Obtained current memory usage for device %d", i); } if (GPUFailedMsgI(cudaGetDeviceProperties(&cudaDeviceProp, i))) { continue; } - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Obtained device properties for device %d", i); } int deviceOK = true; @@ -274,7 +274,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() } deviceSpeed = (double)cudaDeviceProp.multiProcessorCount * (double)cudaDeviceProp.clockRate * (double)cudaDeviceProp.warpSize * (double)free * (double)cudaDeviceProp.major * (double)cudaDeviceProp.major; - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUImportant("Device %s%2d: %s (Rev: %d.%d - Mem Avail %lld / %lld)%s %s", deviceOK ? " " : "[", i, cudaDeviceProp.name, cudaDeviceProp.major, cudaDeviceProp.minor, (long long int)free, (long long int)cudaDeviceProp.totalGlobalMem, deviceOK ? " " : " ]", deviceOK ? "" : deviceFailure); } if (!deviceOK) { @@ -286,7 +286,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() bestDevice = i; bestDeviceSpeed = deviceSpeed; } else { - if (mDeviceProcessingSettings.debugLevel >= 2 && mDeviceProcessingSettings.deviceNum < 0) { + if (mProcessingSettings.debugLevel >= 2 && mProcessingSettings.deviceNum < 0) { GPUInfo("Skipping: Speed %f < %f\n", deviceSpeed, bestDeviceSpeed); } } @@ -297,15 +297,15 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUWarning("No %sCUDA Device available, aborting CUDA Initialisation", count ? "appropriate " : ""); GPUImportant("Requiring Revision %d.%d, Mem: %lld", reqVerMaj, reqVerMin, (long long int)std::max(mDeviceMemorySize, REQUIRE_MIN_MEMORY)); noDevice = true; - } else if (mDeviceProcessingSettings.deviceNum > -1) { - if (mDeviceProcessingSettings.deviceNum >= (signed)count) { - GPUError("Requested device ID %d does not exist", mDeviceProcessingSettings.deviceNum); + } else if (mProcessingSettings.deviceNum > -1) { + if (mProcessingSettings.deviceNum >= (signed)count) { + GPUError("Requested device ID %d does not exist", mProcessingSettings.deviceNum); noDevice = true; - } else if (!devicesOK[mDeviceProcessingSettings.deviceNum]) { - GPUError("Unsupported device requested (%d)", mDeviceProcessingSettings.deviceNum); + } else if (!devicesOK[mProcessingSettings.deviceNum]) { + GPUError("Unsupported device requested (%d)", mProcessingSettings.deviceNum); noDevice = true; } else { - bestDevice = mDeviceProcessingSettings.deviceNum; + bestDevice = mProcessingSettings.deviceNum; } } if (noDevice) { @@ -318,7 +318,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUFailedMsgI(cudaGetDeviceProperties(&cudaDeviceProp, mDeviceId)); - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Using CUDA Device %s with Properties:", cudaDeviceProp.name); GPUInfo("\ttotalGlobalMem = %lld", (unsigned long long int)cudaDeviceProp.totalGlobalMem); GPUInfo("\tsharedMemPerBlock = %lld", (unsigned long long int)cudaDeviceProp.sharedMemPerBlock); @@ -393,7 +393,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUFailedMsgI(cudaDeviceReset()); return (1); } - if (mDeviceProcessingSettings.debugLevel >= 1) { + if (mProcessingSettings.debugLevel >= 1) { GPUInfo("Memory ptrs: GPU (%lld bytes): %p - Host (%lld bytes): %p", (long long int)mDeviceMemorySize, mDeviceMemoryBase, (long long int)mHostMemorySize, mHostMemoryBase); memset(mHostMemoryBase, 0xDD, mHostMemorySize); if (GPUFailedMsgI(cudaMemset(mDeviceMemoryBase, 0xDD, mDeviceMemorySize))) { @@ -442,7 +442,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUFailedMsgI(cuCtxPushCurrent(mInternals->CudaContext)); } - if (mDeviceProcessingSettings.debugLevel >= 1) { + if (mProcessingSettings.debugLevel >= 1) { } for (unsigned int i = 0; i < mEvents.size(); i++) { cudaEvent_t* events = (cudaEvent_t*)mEvents[i].data(); @@ -505,7 +505,7 @@ int GPUReconstructionCUDABackend::ExitDevice_Runtime() size_t GPUReconstructionCUDABackend::GPUMemCpy(void* dst, const void* src, size_t size, int stream, int toGPU, deviceEvent* ev, deviceEvent* evList, int nEvents) { - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { stream = -1; } if (stream == -1) { @@ -529,12 +529,12 @@ size_t GPUReconstructionCUDABackend::GPUMemCpy(void* dst, const void* src, size_ size_t GPUReconstructionCUDABackend::TransferMemoryInternal(GPUMemoryResource* res, int stream, deviceEvent* ev, deviceEvent* evList, int nEvents, bool toGPU, const void* src, void* dst) { if (!(res->Type() & GPUMemoryResource::MEMORY_GPU)) { - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Skipped transfer of non-GPU memory resource: %s", res->Name()); } return 0; } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("Copying to %s: %s - %lld bytes", toGPU ? "GPU" : "Host", res->Name(), (long long int)res->Size()); } return GPUMemCpy(dst, src, res->Size(), stream, toGPU, ev, evList, nEvents); @@ -618,14 +618,14 @@ int GPUReconstructionCUDABackend::GPUDebug(const char* state, int stream) GPUError("Cuda Error %s while running kernel (%s) (Stream %d)", cudaGetErrorString(cuErr), state, stream); return (1); } - if (mDeviceProcessingSettings.debugLevel == 0) { + if (mProcessingSettings.debugLevel == 0) { return (0); } if (GPUFailedMsgI(cudaDeviceSynchronize())) { GPUError("CUDA Error while synchronizing (%s) (Stream %d)", state, stream); return (1); } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("GPU Sync Done"); } return (0); diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h index 1ef0adb8af580..5997a88d8c224 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h @@ -17,9 +17,9 @@ #include "GPUReconstructionDeviceBase.h" #ifdef _WIN32 -extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_CUDA(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_CUDA(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #else -extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_CUDA(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_CUDA(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #endif namespace GPUCA_NAMESPACE @@ -34,7 +34,7 @@ class GPUReconstructionCUDABackend : public GPUReconstructionDeviceBase ~GPUReconstructionCUDABackend() override; protected: - GPUReconstructionCUDABackend(const GPUSettingsProcessing& cfg); + GPUReconstructionCUDABackend(const GPUSettingsDeviceBackend& cfg); int InitDevice_Runtime() override; int ExitDevice_Runtime() override; diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.h b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.h index eb118a38b35c4..9f36d0db0fb78 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.h +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.h @@ -17,9 +17,9 @@ #include "GPUReconstructionDeviceBase.h" #ifdef _WIN32 -extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_HIP(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_HIP(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #else -extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_HIP(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_HIP(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #endif namespace GPUCA_NAMESPACE @@ -34,7 +34,7 @@ class GPUReconstructionHIPBackend : public GPUReconstructionDeviceBase ~GPUReconstructionHIPBackend() override; protected: - GPUReconstructionHIPBackend(const GPUSettingsProcessing& cfg); + GPUReconstructionHIPBackend(const GPUSettingsDeviceBackend& cfg); int InitDevice_Runtime() override; int ExitDevice_Runtime() override; diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index 0e57f80cb587b..9517f41f90486 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -148,14 +148,14 @@ GPUg() void runKernelHIP(GPUCA_CONSMEM_PTR int iSlice_internal, Args... args) template <> void GPUReconstructionHIPBackend::runKernelBackendInternal<GPUMemClean16, 0>(krnlSetup& _xyz, void* const& ptr, unsigned long const& size) { - GPUDebugTiming timer(mDeviceProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); + GPUDebugTiming timer(mProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); GPUFailedMsg(hipMemsetAsync(ptr, 0, size, mInternals->Streams[_xyz.x.stream])); } template <class T, int I, typename... Args> void GPUReconstructionHIPBackend::runKernelBackendInternal(krnlSetup& _xyz, const Args&... args) { - if (mDeviceProcessingSettings.deviceTimers) { + if (mProcessingSettings.deviceTimers) { #ifdef __CUDACC__ GPUFailedMsg(hipEventRecord((hipEvent_t)mDebugEvents->DebugStart, mInternals->Streams[x.stream])); #endif @@ -190,12 +190,12 @@ int GPUReconstructionHIPBackend::runKernelBackend(krnlSetup& _xyz, const Args&.. return 0; } -GPUReconstructionHIPBackend::GPUReconstructionHIPBackend(const GPUSettingsProcessing& cfg) : GPUReconstructionDeviceBase(cfg, sizeof(GPUReconstructionDeviceBase)) +GPUReconstructionHIPBackend::GPUReconstructionHIPBackend(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionDeviceBase(cfg, sizeof(GPUReconstructionDeviceBase)) { if (mMaster == nullptr) { mInternals = new GPUReconstructionHIPInternals; } - mProcessingSettings.deviceType = DeviceType::HIP; + mDeviceBackendSettings.deviceType = DeviceType::HIP; } GPUReconstructionHIPBackend::~GPUReconstructionHIPBackend() @@ -206,7 +206,7 @@ GPUReconstructionHIPBackend::~GPUReconstructionHIPBackend() } } -GPUReconstruction* GPUReconstruction_Create_HIP(const GPUSettingsProcessing& cfg) { return new GPUReconstructionHIP(cfg); } +GPUReconstruction* GPUReconstruction_Create_HIP(const GPUSettingsDeviceBackend& cfg) { return new GPUReconstructionHIP(cfg); } void GPUReconstructionHIPBackend::GetITSTraits(std::unique_ptr<o2::its::TrackerTraits>* trackerTraits, std::unique_ptr<o2::its::VertexerTraits>* vertexerTraits) { @@ -233,28 +233,28 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() GPUError("Error getting HIP Device Count"); return (1); } - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Available HIP devices:"); } std::vector<bool> devicesOK(count, false); for (int i = 0; i < count; i++) { - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Examining device %d", i); } - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Obtained current memory usage for device %d", i); } if (GPUFailedMsgI(hipGetDeviceProperties(&hipDeviceProp, i))) { continue; } - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Obtained device properties for device %d", i); } int deviceOK = true; const char* deviceFailure = ""; deviceSpeed = (double)hipDeviceProp.multiProcessorCount * (double)hipDeviceProp.clockRate * (double)hipDeviceProp.warpSize * (double)hipDeviceProp.major * (double)hipDeviceProp.major; - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUImportant("Device %s%2d: %s (Rev: %d.%d - Mem %lld)%s %s", deviceOK ? " " : "[", i, hipDeviceProp.name, hipDeviceProp.major, hipDeviceProp.minor, (long long int)hipDeviceProp.totalGlobalMem, deviceOK ? " " : " ]", deviceOK ? "" : deviceFailure); } if (!deviceOK) { @@ -265,7 +265,7 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() bestDevice = i; bestDeviceSpeed = deviceSpeed; } else { - if (mDeviceProcessingSettings.debugLevel >= 2 && mDeviceProcessingSettings.deviceNum < 0) { + if (mProcessingSettings.debugLevel >= 2 && mProcessingSettings.deviceNum < 0) { GPUInfo("Skipping: Speed %f < %f\n", deviceSpeed, bestDeviceSpeed); } } @@ -275,15 +275,15 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() return (1); } - if (mDeviceProcessingSettings.deviceNum > -1) { - if (mDeviceProcessingSettings.deviceNum >= (signed)count) { - GPUWarning("Requested device ID %d does not exist", mDeviceProcessingSettings.deviceNum); + if (mProcessingSettings.deviceNum > -1) { + if (mProcessingSettings.deviceNum >= (signed)count) { + GPUWarning("Requested device ID %d does not exist", mProcessingSettings.deviceNum); return (1); - } else if (!devicesOK[mDeviceProcessingSettings.deviceNum]) { - GPUWarning("Unsupported device requested (%d)", mDeviceProcessingSettings.deviceNum); + } else if (!devicesOK[mProcessingSettings.deviceNum]) { + GPUWarning("Unsupported device requested (%d)", mProcessingSettings.deviceNum); return (1); } else { - bestDevice = mDeviceProcessingSettings.deviceNum; + bestDevice = mProcessingSettings.deviceNum; } } mDeviceId = bestDevice; @@ -291,7 +291,7 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() GPUFailedMsgI(hipGetDeviceProperties(&hipDeviceProp, mDeviceId)); hipDeviceProp.totalConstMem = 65536; // TODO: Remove workaround, fixes incorrectly reported HIP constant memory - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Using HIP Device %s with Properties:", hipDeviceProp.name); GPUInfo("\ttotalGlobalMem = %lld", (unsigned long long int)hipDeviceProp.totalGlobalMem); GPUInfo("\tsharedMemPerBlock = %lld", (unsigned long long int)hipDeviceProp.sharedMemPerBlock); @@ -347,7 +347,7 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() GPUFailedMsgI(hipDeviceReset()); return (1); } - if (mDeviceProcessingSettings.debugLevel >= 1) { + if (mProcessingSettings.debugLevel >= 1) { GPUInfo("Memory ptrs: GPU (%lld bytes): %p - Host (%lld bytes): %p", (long long int)mDeviceMemorySize, mDeviceMemoryBase, (long long int)mHostMemorySize, mHostMemoryBase); memset(mHostMemoryBase, 0, mHostMemorySize); if (GPUFailedMsgI(hipMemset(mDeviceMemoryBase, 0xDD, mDeviceMemorySize))) { @@ -447,7 +447,7 @@ int GPUReconstructionHIPBackend::ExitDevice_Runtime() size_t GPUReconstructionHIPBackend::GPUMemCpy(void* dst, const void* src, size_t size, int stream, int toGPU, deviceEvent* ev, deviceEvent* evList, int nEvents) { - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { stream = -1; } if (stream == -1) { @@ -471,12 +471,12 @@ size_t GPUReconstructionHIPBackend::GPUMemCpy(void* dst, const void* src, size_t size_t GPUReconstructionHIPBackend::TransferMemoryInternal(GPUMemoryResource* res, int stream, deviceEvent* ev, deviceEvent* evList, int nEvents, bool toGPU, const void* src, void* dst) { if (!(res->Type() & GPUMemoryResource::MEMORY_GPU)) { - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Skipped transfer of non-GPU memory resource: %s", res->Name()); } return 0; } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("Copying to %s: %s - %lld bytes", toGPU ? "GPU" : "Host", res->Name(), (long long int)res->Size()); } return GPUMemCpy(dst, src, res->Size(), stream, toGPU, ev, evList, nEvents); @@ -549,14 +549,14 @@ int GPUReconstructionHIPBackend::GPUDebug(const char* state, int stream) GPUError("HIP Error %s while running kernel (%s) (Stream %d)", hipGetErrorString(cuErr), state, stream); return (1); } - if (mDeviceProcessingSettings.debugLevel == 0) { + if (mProcessingSettings.debugLevel == 0) { return (0); } if (GPUFailedMsgI(hipDeviceSynchronize())) { GPUError("HIP Error while synchronizing (%s) (Stream %d)", state, stream); return (1); } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("GPU Sync Done"); } return (0); diff --git a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx index 2f3136190921f..15970c59f7163 100644 --- a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx +++ b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx @@ -36,12 +36,12 @@ using namespace GPUCA_NAMESPACE::gpu; #include "GPUReconstructionKernels.h" #undef GPUCA_KRNL -GPUReconstructionOCL::GPUReconstructionOCL(const GPUSettingsProcessing& cfg) : GPUReconstructionDeviceBase(cfg, sizeof(GPUReconstructionDeviceBase)) +GPUReconstructionOCL::GPUReconstructionOCL(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionDeviceBase(cfg, sizeof(GPUReconstructionDeviceBase)) { if (mMaster == nullptr) { mInternals = new GPUReconstructionOCLInternals; } - mProcessingSettings.deviceType = DeviceType::OCL; + mDeviceBackendSettings.deviceType = DeviceType::OCL; } GPUReconstructionOCL::~GPUReconstructionOCL() @@ -68,7 +68,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() if (num_platforms == 0) { quit("No OpenCL Platform found"); } - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("%d OpenCL Platforms found", num_platforms); } @@ -79,11 +79,11 @@ int GPUReconstructionOCL::InitDevice_Runtime() } bool found = false; - if (mDeviceProcessingSettings.platformNum >= 0) { - if (mDeviceProcessingSettings.platformNum >= (int)num_platforms) { + if (mProcessingSettings.platformNum >= 0) { + if (mProcessingSettings.platformNum >= (int)num_platforms) { quit("Invalid platform specified"); } - mInternals->platform = mInternals->platforms[mDeviceProcessingSettings.platformNum]; + mInternals->platform = mInternals->platforms[mProcessingSettings.platformNum]; found = true; } else { for (unsigned int i_platform = 0; i_platform < num_platforms; i_platform++) { @@ -92,7 +92,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() clGetPlatformInfo(mInternals->platforms[i_platform], CL_PLATFORM_VERSION, sizeof(platform_version), platform_version, nullptr); clGetPlatformInfo(mInternals->platforms[i_platform], CL_PLATFORM_NAME, sizeof(platform_name), platform_name, nullptr); clGetPlatformInfo(mInternals->platforms[i_platform], CL_PLATFORM_VENDOR, sizeof(platform_vendor), platform_vendor, nullptr); - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Available Platform %d: (%s %s) %s %s", i_platform, platform_profile, platform_version, platform_vendor, platform_name); } if (CheckPlatform(i_platform)) { @@ -121,12 +121,12 @@ int GPUReconstructionOCL::InitDevice_Runtime() cl_device_type device_type; cl_uint freq, shaders; - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Available OPENCL devices:"); } std::vector<bool> devicesOK(count, false); for (unsigned int i = 0; i < count; i++) { - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("Examining device %d", i); } cl_uint nbits; @@ -141,7 +141,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() clGetDeviceInfo(mInternals->devices[i], CL_DEVICE_ENDIAN_LITTLE, sizeof(endian), &endian, nullptr); int deviceOK = true; const char* deviceFailure = ""; - if (mDeviceProcessingSettings.gpuDeviceOnly && ((device_type & CL_DEVICE_TYPE_CPU) || !(device_type & CL_DEVICE_TYPE_GPU))) { + if (mProcessingSettings.gpuDeviceOnly && ((device_type & CL_DEVICE_TYPE_CPU) || !(device_type & CL_DEVICE_TYPE_GPU))) { deviceOK = false; deviceFailure = "No GPU device"; } @@ -155,7 +155,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() } double bestDeviceSpeed = -1, deviceSpeed = (double)freq * (double)shaders; - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUImportant("Device %s%2d: %s %s (Frequency %d, Shaders %d, %d bit) (Speed Value: %lld)%s %s", deviceOK ? " " : "[", i, device_vendor, device_name, (int)freq, (int)shaders, (int)nbits, (long long int)deviceSpeed, deviceOK ? " " : " ]", deviceOK ? "" : deviceFailure); } if (!deviceOK) { @@ -166,7 +166,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() bestDevice = i; bestDeviceSpeed = deviceSpeed; } else { - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Skipping: Speed %f < %f", deviceSpeed, bestDeviceSpeed); } } @@ -175,13 +175,13 @@ int GPUReconstructionOCL::InitDevice_Runtime() quit("No %sOPENCL Device available, aborting OPENCL Initialisation", count ? "appropriate " : ""); } - if (mDeviceProcessingSettings.deviceNum > -1) { - if (mDeviceProcessingSettings.deviceNum >= (signed)count) { - quit("Requested device ID %d does not exist", mDeviceProcessingSettings.deviceNum); - } else if (!devicesOK[mDeviceProcessingSettings.deviceNum]) { - quit("Unsupported device requested (%d)", mDeviceProcessingSettings.deviceNum); + if (mProcessingSettings.deviceNum > -1) { + if (mProcessingSettings.deviceNum >= (signed)count) { + quit("Requested device ID %d does not exist", mProcessingSettings.deviceNum); + } else if (!devicesOK[mProcessingSettings.deviceNum]) { + quit("Unsupported device requested (%d)", mProcessingSettings.deviceNum); } else { - bestDevice = mDeviceProcessingSettings.deviceNum; + bestDevice = mProcessingSettings.deviceNum; } } mInternals->device = mInternals->devices[bestDevice]; @@ -200,7 +200,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() clGetDeviceInfo(mInternals->device, CL_DEVICE_VERSION, sizeof(deviceVersion) - 1, deviceVersion, nullptr); clGetDeviceInfo(mInternals->device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(maxWorkGroup), &maxWorkGroup, nullptr); clGetDeviceInfo(mInternals->device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(maxWorkItems), maxWorkItems, nullptr); - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Using OpenCL device %d: %s %s with properties:", bestDevice, device_vendor, device_name); GPUInfo("\tVersion = %s", deviceVersion); GPUInfo("\tFrequency = %d", (int)freq); @@ -233,7 +233,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() return 1; } - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("OpenCL program and kernels loaded successfully"); } @@ -253,7 +253,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() for (int i = 0; i < mNStreams; i++) { #ifdef CL_VERSION_2_0 cl_queue_properties prop = 0; - if (mDeviceProcessingSettings.deviceTimers) { + if (mProcessingSettings.deviceTimers) { prop |= CL_QUEUE_PROFILING_ENABLE; } mInternals->command_queue[i] = clCreateCommandQueueWithProperties(mInternals->context, mInternals->device, &prop, &ocl_error); @@ -300,7 +300,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() quit("Error obtaining device memory ptr"); } - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Mapping hostmemory"); } mHostMemoryBase = clEnqueueMapBuffer(mInternals->command_queue[0], mInternals->mem_host, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, mHostMemorySize, 0, nullptr, nullptr, &ocl_error); @@ -311,7 +311,7 @@ int GPUReconstructionOCL::InitDevice_Runtime() mDeviceMemoryBase = ((void**)mHostMemoryBase)[0]; mDeviceConstantMem = (GPUConstantMem*)((void**)mHostMemoryBase)[1]; - if (mDeviceProcessingSettings.debugLevel >= 1) { + if (mProcessingSettings.debugLevel >= 1) { GPUInfo("Memory ptrs: GPU (%lld bytes): %p - Host (%lld bytes): %p", (long long int)mDeviceMemorySize, mDeviceMemoryBase, (long long int)mHostMemorySize, mHostMemoryBase); memset(mHostMemoryBase, 0xDD, mHostMemorySize); } @@ -368,7 +368,7 @@ size_t GPUReconstructionOCL::GPUMemCpy(void* dst, const void* src, size_t size, if (evList == nullptr) { nEvents = 0; } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { stream = -1; } if (stream == -1) { @@ -387,12 +387,12 @@ size_t GPUReconstructionOCL::GPUMemCpy(void* dst, const void* src, size_t size, size_t GPUReconstructionOCL::TransferMemoryInternal(GPUMemoryResource* res, int stream, deviceEvent* ev, deviceEvent* evList, int nEvents, bool toGPU, const void* src, void* dst) { if (!(res->Type() & GPUMemoryResource::MEMORY_GPU)) { - if (mDeviceProcessingSettings.debugLevel >= 4) { + if (mProcessingSettings.debugLevel >= 4) { GPUInfo("Skipped transfer of non-GPU memory resource: %s", res->Name()); } return 0; } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("Copying to %s: %s - %lld bytes", toGPU ? "GPU" : "Host", res->Name(), (long long int)res->Size()); } return GPUMemCpy(dst, src, res->Size(), stream, toGPU, ev, evList, nEvents); @@ -413,9 +413,9 @@ void GPUReconstructionOCL::RecordMarker(deviceEvent* ev, int stream) { GPUFailed int GPUReconstructionOCL::DoStuckProtection(int stream, void* event) { - if (mDeviceProcessingSettings.stuckProtection) { + if (mProcessingSettings.stuckProtection) { cl_int tmp = 0; - for (int i = 0; i <= mDeviceProcessingSettings.stuckProtection / 50; i++) { + for (int i = 0; i <= mProcessingSettings.stuckProtection / 50; i++) { usleep(50); clGetEventInfo(*(cl_event*)event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(tmp), &tmp, nullptr); if (tmp == CL_COMPLETE) { @@ -465,7 +465,7 @@ bool GPUReconstructionOCL::IsEventDone(deviceEvent* evList, int nEvents) int GPUReconstructionOCL::GPUDebug(const char* state, int stream) { // Wait for OPENCL-Kernel to finish and check for OPENCL errors afterwards, in case of debugmode - if (mDeviceProcessingSettings.debugLevel == 0) { + if (mProcessingSettings.debugLevel == 0) { return (0); } for (int i = 0; i < mNStreams; i++) { @@ -473,7 +473,7 @@ int GPUReconstructionOCL::GPUDebug(const char* state, int stream) GPUError("OpenCL Error while synchronizing (%s) (Stream %d/%d)", state, stream, i); } } - if (mDeviceProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3) { GPUInfo("GPU Sync Done"); } return (0); diff --git a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.h b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.h index 1a80dd3772e22..46e50e8547357 100644 --- a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.h +++ b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.h @@ -17,9 +17,9 @@ #include "GPUReconstructionDeviceBase.h" #ifdef _WIN32 -extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCLconst GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCLconst GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #else -extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #endif namespace GPUCA_NAMESPACE::gpu @@ -30,7 +30,7 @@ class GPUReconstructionOCL : public GPUReconstructionDeviceBase { public: ~GPUReconstructionOCL() override; - GPUReconstructionOCL(const GPUSettingsProcessing& cfg); + GPUReconstructionOCL(const GPUSettingsDeviceBackend& cfg); protected: int InitDevice_Runtime() override; diff --git a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h index 5078b3bcbb5a5..1f411324d6b05 100644 --- a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h +++ b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h @@ -201,14 +201,14 @@ int GPUReconstructionOCL::runKernelBackendCommon(krnlSetup& _xyz, K& k, const Ar cl_event ev; cl_event* evr; bool tmpEvent = false; - if (z.ev == nullptr && mDeviceProcessingSettings.deviceTimers) { + if (z.ev == nullptr && mProcessingSettings.deviceTimers) { evr = &ev; tmpEvent = true; } else { evr = (cl_event*)z.ev; } int retVal = clExecuteKernelA(mInternals->command_queue[x.stream], k, x.nThreads, x.nThreads * x.nBlocks, evr, (cl_event*)z.evList, z.nEvents); - if (mDeviceProcessingSettings.deviceTimers) { + if (mProcessingSettings.deviceTimers) { cl_ulong time_start, time_end; GPUFailedMsg(clWaitForEvents(1, evr)); GPUFailedMsg(clGetEventProfilingInfo(*evr, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, nullptr)); diff --git a/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.cxx b/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.cxx index db8d72fb5391e..051bdcfeeb7da 100644 --- a/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.cxx +++ b/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.cxx @@ -28,9 +28,9 @@ using namespace GPUCA_NAMESPACE::gpu; #include "../makefiles/opencl_obtain_program.h" extern "C" char _makefile_opencl_program_Base_opencl_common_GPUReconstructionOCL_cl[]; -GPUReconstruction* GPUReconstruction_Create_OCL(const GPUSettingsProcessing& cfg) { return new GPUReconstructionOCL1(cfg); } +GPUReconstruction* GPUReconstruction_Create_OCL(const GPUSettingsDeviceBackend& cfg) { return new GPUReconstructionOCL1(cfg); } -GPUReconstructionOCL1Backend::GPUReconstructionOCL1Backend(const GPUSettingsProcessing& cfg) : GPUReconstructionOCL(cfg) +GPUReconstructionOCL1Backend::GPUReconstructionOCL1Backend(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionOCL(cfg) { } @@ -91,7 +91,7 @@ bool GPUReconstructionOCL1Backend::CheckPlatform(unsigned int i) float ver = 0; sscanf(platform_version, "OpenCL 2.0 AMD-APP (%f)", &ver); if (ver < 2000.f) { - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("AMD APP OpenCL Platform found"); } return true; diff --git a/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.h b/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.h index d143f51dfecff..28131147f8463 100644 --- a/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.h +++ b/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL1.h @@ -17,9 +17,9 @@ #include "GPUReconstructionOCL.h" #ifdef _WIN32 -extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #else -extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #endif namespace GPUCA_NAMESPACE::gpu @@ -32,7 +32,7 @@ class GPUReconstructionOCL1Backend : public GPUReconstructionOCL ~GPUReconstructionOCL1Backend() override = default; protected: - GPUReconstructionOCL1Backend(const GPUSettingsProcessing& cfg); + GPUReconstructionOCL1Backend(const GPUSettingsDeviceBackend& cfg); template <class T, int I = 0, typename... Args> int runKernelBackend(krnlSetup& _xyz, const Args&... args); diff --git a/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.cxx b/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.cxx index c46a6beeaa18b..700dfd9e3942a 100644 --- a/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.cxx +++ b/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.cxx @@ -36,9 +36,9 @@ extern "C" unsigned int _makefile_opencl_program_Base_opencl_GPUReconstructionOC extern "C" char _makefile_opencl_program_Base_opencl_GPUReconstructionOCL2_cl_src[]; extern "C" unsigned int _makefile_opencl_program_Base_opencl_GPUReconstructionOCL2_cl_src_size; -GPUReconstruction* GPUReconstruction_Create_OCL2(const GPUSettingsProcessing& cfg) { return new GPUReconstructionOCL2(cfg); } +GPUReconstruction* GPUReconstruction_Create_OCL2(const GPUSettingsDeviceBackend& cfg) { return new GPUReconstructionOCL2(cfg); } -GPUReconstructionOCL2Backend::GPUReconstructionOCL2Backend(const GPUSettingsProcessing& cfg) : GPUReconstructionOCL(cfg) +GPUReconstructionOCL2Backend::GPUReconstructionOCL2Backend(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionOCL(cfg) { } @@ -134,7 +134,7 @@ bool GPUReconstructionOCL2Backend::CheckPlatform(unsigned int i) float ver1 = 0; sscanf(platform_version, "OpenCL %f", &ver1); if (ver1 >= 2.2f) { - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("OpenCL 2.2 capable platform found"); } return true; @@ -147,7 +147,7 @@ bool GPUReconstructionOCL2Backend::CheckPlatform(unsigned int i) sscanf(pos, "(%f)", &ver2); } if ((ver1 >= 2.f && ver2 >= 2000.f) || ver1 >= 2.1f) { - if (mDeviceProcessingSettings.debugLevel >= 2) { + if (mProcessingSettings.debugLevel >= 2) { GPUInfo("AMD ROCm OpenCL Platform found"); } return true; diff --git a/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.h b/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.h index 859e76adeef53..dbaa05f290d6e 100644 --- a/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.h +++ b/GPU/GPUTracking/Base/opencl2/GPUReconstructionOCL2.h @@ -17,9 +17,9 @@ #include "GPUReconstructionOCL.h" #ifdef _WIN32 -extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL2(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" __declspec(dllexport) GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL2(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #else -extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL2(const GPUCA_NAMESPACE::gpu::GPUSettingsProcessing& cfg); +extern "C" GPUCA_NAMESPACE::gpu::GPUReconstruction* GPUReconstruction_Create_OCL2(const GPUCA_NAMESPACE::gpu::GPUSettingsDeviceBackend& cfg); #endif namespace GPUCA_NAMESPACE::gpu @@ -32,7 +32,7 @@ class GPUReconstructionOCL2Backend : public GPUReconstructionOCL ~GPUReconstructionOCL2Backend() override = default; protected: - GPUReconstructionOCL2Backend(const GPUSettingsProcessing& cfg); + GPUReconstructionOCL2Backend(const GPUSettingsDeviceBackend& cfg); template <class T, int I = 0, typename... Args> int runKernelBackend(krnlSetup& _xyz, const Args&... args); diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx index cf96cf8f15c28..99c1557cccbb6 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx @@ -29,10 +29,10 @@ void* GPUTPCCompression::SetPointersOutputHost(void* mem) void* GPUTPCCompression::SetPointersScratch(void* mem) { computePointerWithAlignment(mem, mClusterStatus, mMaxClusters); - if (mRec->GetDeviceProcessingSettings().tpcCompressionGatherMode == 2) { + if (mRec->GetProcessingSettings().tpcCompressionGatherMode == 2) { computePointerWithAlignment(mem, mAttachedClusterFirstIndex, mMaxTracks); } - if (mRec->GetDeviceProcessingSettings().tpcCompressionGatherMode != 1) { + if (mRec->GetProcessingSettings().tpcCompressionGatherMode != 1) { SetPointersCompressedClusters(mem, mPtrs, mMaxTrackClusters, mMaxTracks, mMaxClusters, false); } return mem; @@ -41,7 +41,7 @@ void* GPUTPCCompression::SetPointersScratch(void* mem) void* GPUTPCCompression::SetPointersOutput(void* mem) { computePointerWithAlignment(mem, mAttachedClusterFirstIndex, mMaxTrackClusters); - if (mRec->GetDeviceProcessingSettings().tpcCompressionGatherMode == 1) { + if (mRec->GetProcessingSettings().tpcCompressionGatherMode == 1) { SetPointersCompressedClusters(mem, mPtrs, mMaxTrackClusters, mMaxTracks, mMaxClusters, false); } return mem; @@ -94,7 +94,7 @@ void GPUTPCCompression::RegisterMemoryAllocation() { AllocateAndInitializeLate(); mMemoryResOutputHost = mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersOutputHost, GPUMemoryResource::MEMORY_OUTPUT_FLAG | GPUMemoryResource::MEMORY_HOST | GPUMemoryResource::MEMORY_CUSTOM, "TPCCompressionOutputHost"); - if (mRec->GetDeviceProcessingSettings().tpcCompressionGatherMode != 2) { + if (mRec->GetProcessingSettings().tpcCompressionGatherMode != 2) { mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersOutput, GPUMemoryResource::MEMORY_OUTPUT | GPUMemoryResource::MEMORY_STACK, "TPCCompressionOutput"); } mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCCompressionScratch"); diff --git a/GPU/GPUTracking/Global/GPUChain.h b/GPU/GPUTracking/Global/GPUChain.h index ba01a99603903..a1483cd3a09bb 100644 --- a/GPU/GPUTracking/Global/GPUChain.h +++ b/GPU/GPUTracking/Global/GPUChain.h @@ -57,8 +57,8 @@ class GPUChain const GPUParam& GetParam() const { return mRec->mHostConstantMem->param; } const GPUSettingsEvent& GetEventSettings() const { return mRec->mEventSettings; } + const GPUSettingsDeviceBackend& GetDeviceBackendSettings() const { return mRec->mDeviceBackendSettings; } const GPUSettingsProcessing& GetProcessingSettings() const { return mRec->mProcessingSettings; } - const GPUSettingsDeviceProcessing& GetDeviceProcessingSettings() const { return mRec->mDeviceProcessingSettings; } GPUReconstruction* rec() { return mRec; } const GPUReconstruction* rec() const { return mRec; } @@ -79,7 +79,7 @@ class GPUChain inline GPUConstantMem* processorsDevice() { return mRec->mDeviceConstantMem; } inline GPUParam& param() { return mRec->param(); } inline const GPUConstantMem* processors() const { return mRec->processors(); } - inline GPUSettingsDeviceProcessing& DeviceProcessingSettings() { return mRec->mDeviceProcessingSettings; } + inline GPUSettingsProcessing& ProcessingSettings() { return mRec->mProcessingSettings; } inline void SynchronizeStream(int stream) { mRec->SynchronizeStream(stream); } inline void SynchronizeEvents(deviceEvent* evList, int nEvents = 1) { mRec->SynchronizeEvents(evList, nEvents); } template <class T> @@ -246,7 +246,7 @@ inline void GPUChain::timeCpy(RecoStep step, int toGPU, S T::*func, Args... args } HighResTimer* timer = nullptr; size_t* bytes = nullptr; - if (mRec->mDeviceProcessingSettings.debugLevel >= 1 && toGPU >= 0) { // Todo: time special cases toGPU < 0 + if (mRec->mProcessingSettings.debugLevel >= 1 && toGPU >= 0) { // Todo: time special cases toGPU < 0 int id = mRec->getRecoStepNum(step, false); if (id != -1) { auto& tmp = mRec->mTimersRecoSteps[id]; @@ -267,11 +267,11 @@ inline void GPUChain::timeCpy(RecoStep step, int toGPU, S T::*func, Args... args template <class T, class S, typename... Args> bool GPUChain::DoDebugAndDump(GPUChain::RecoStep step, int mask, bool transfer, T& processor, S T::*func, Args&&... args) { - if (GetDeviceProcessingSettings().keepAllMemory) { + if (GetProcessingSettings().keepAllMemory) { if (transfer) { TransferMemoryResourcesToHost(step, &processor, -1, true); } - if (GetDeviceProcessingSettings().debugLevel >= 6 && (mask == 0 || (GetDeviceProcessingSettings().debugMask & mask))) { + if (GetProcessingSettings().debugLevel >= 6 && (mask == 0 || (GetProcessingSettings().debugMask & mask))) { (processor.*func)(args...); return true; } @@ -283,11 +283,11 @@ template <class T, class S, typename... Args> int GPUChain::runRecoStep(RecoStep step, S T::*func, Args... args) { if (GetRecoSteps().isSet(step)) { - if (GetDeviceProcessingSettings().debugLevel >= 1) { + if (GetProcessingSettings().debugLevel >= 1) { mRec->getRecoStepTimer(step).Start(); } int retVal = (reinterpret_cast<T*>(this)->*func)(args...); - if (GetDeviceProcessingSettings().debugLevel >= 1) { + if (GetProcessingSettings().debugLevel >= 1) { mRec->getRecoStepTimer(step).Stop(); } return retVal; diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 6c38a8dc546c1..defb82bb5b11e 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -270,7 +270,7 @@ bool GPUChainTracking::ValidateSettings() GPUError("incompatible settings for non consecutive ids"); return false; } - if (!param().rec.mergerReadFromTrackerDirectly && GetDeviceProcessingSettings().ompKernels) { + if (!param().rec.mergerReadFromTrackerDirectly && GetProcessingSettings().ompKernels) { GPUError("OMP Kernels require mergerReadFromTrackerDirectly"); return false; } @@ -278,11 +278,11 @@ bool GPUChainTracking::ValidateSettings() GPUError("configure max time bin exceeds 256 orbits"); return false; } - if (mRec->IsGPU() && std::max(GetDeviceProcessingSettings().nTPCClustererLanes + 1, GetDeviceProcessingSettings().nTPCClustererLanes * 2) + (GetDeviceProcessingSettings().doublePipeline ? 1 : 0) > mRec->NStreams()) { + if (mRec->IsGPU() && std::max(GetProcessingSettings().nTPCClustererLanes + 1, GetProcessingSettings().nTPCClustererLanes * 2) + (GetProcessingSettings().doublePipeline ? 1 : 0) > mRec->NStreams()) { GPUError("NStreams must be > nTPCClustererLanes"); return false; } - if (GetDeviceProcessingSettings().doublePipeline) { + if (GetProcessingSettings().doublePipeline) { if (!GetRecoStepsOutputs().isOnlySet(GPUDataTypes::InOutType::TPCMergedTracks, GPUDataTypes::InOutType::TPCCompressedClusters, GPUDataTypes::InOutType::TPCClusters)) { GPUError("Invalid outputs for double pipeline mode 0x%x", (unsigned int)GetRecoStepsOutputs()); return false; @@ -291,7 +291,7 @@ bool GPUChainTracking::ValidateSettings() GPUError("Must use external output for double pipeline mode"); return false; } - if (DeviceProcessingSettings().tpcCompressionGatherMode == 1) { + if (ProcessingSettings().tpcCompressionGatherMode == 1) { GPUError("Double pipeline incompatible to compression mode 1"); return false; } @@ -306,7 +306,7 @@ bool GPUChainTracking::ValidateSettings() int GPUChainTracking::Init() { const auto& threadContext = GetThreadContext(); - if (GetDeviceProcessingSettings().debugLevel >= 1) { + if (GetProcessingSettings().debugLevel >= 1) { printf("Enabled Reconstruction Steps: 0x%x (on GPU: 0x%x)", (int)GetRecoSteps().get(), (int)GetRecoStepsGPU().get()); for (unsigned int i = 0; i < sizeof(GPUDataTypes::RECO_STEP_NAMES) / sizeof(GPUDataTypes::RECO_STEP_NAMES[0]); i++) { if (GetRecoSteps().isSet(1u << i)) { @@ -336,11 +336,11 @@ int GPUChainTracking::Init() return 1; } - if (GPUQA::QAAvailable() && (GetDeviceProcessingSettings().runQA || GetDeviceProcessingSettings().eventDisplay)) { + if (GPUQA::QAAvailable() && (GetProcessingSettings().runQA || GetProcessingSettings().eventDisplay)) { mQA.reset(new GPUQA(this)); } - if (GetDeviceProcessingSettings().eventDisplay) { - mEventDisplay.reset(new GPUDisplay(GetDeviceProcessingSettings().eventDisplay, this, mQA.get())); + if (GetProcessingSettings().eventDisplay) { + mEventDisplay.reset(new GPUDisplay(GetProcessingSettings().eventDisplay, this, mQA.get())); } processors()->errorCodes.setMemory(mInputsHost->mErrorCodes); @@ -381,7 +381,7 @@ int GPUChainTracking::Init() TransferMemoryResourceLinkToGPU(RecoStep::NoRecoStep, mInputsHost->mResourceErrorCodes); } - if (GetDeviceProcessingSettings().debugLevel >= 6) { + if (GetProcessingSettings().debugLevel >= 6) { mDebugFile->open(mRec->IsGPU() ? "GPU.out" : "CPU.out"); } @@ -445,7 +445,7 @@ std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCo } #ifndef GPUCA_NO_VC - if (GetDeviceProcessingSettings().prefetchTPCpageScan >= 3 && j < GPUTrackingInOutZS::NENDPOINTS - 1) { + if (GetProcessingSettings().prefetchTPCpageScan >= 3 && j < GPUTrackingInOutZS::NENDPOINTS - 1) { for (unsigned int k = 0; k < mIOPtrs.tpcZS->slice[iSlice].count[j + 1]; k++) { for (unsigned int l = 0; l < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j + 1][k]; l++) { Vc::Common::prefetchMid(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j + 1][k]) + l * TPCZSHDR::TPC_ZS_PAGE_SIZE); @@ -467,7 +467,7 @@ std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCo return {0, 0}; } #ifndef GPUCA_NO_VC - if (GetDeviceProcessingSettings().prefetchTPCpageScan >= 2 && l + 1 < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]) { + if (GetProcessingSettings().prefetchTPCpageScan >= 2 && l + 1 < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]) { Vc::Common::prefetchForOneRead(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + (l + 1) * TPCZSHDR::TPC_ZS_PAGE_SIZE); Vc::Common::prefetchForOneRead(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + (l + 1) * TPCZSHDR::TPC_ZS_PAGE_SIZE + sizeof(RAWDataHeaderGPU)); } @@ -564,10 +564,10 @@ int GPUChainTracking::ForceInitQA() int GPUChainTracking::Finalize() { - if (GetDeviceProcessingSettings().runQA && mQA->IsInitialized()) { + if (GetProcessingSettings().runQA && mQA->IsInitialized()) { mQA->DrawQAHistograms(); } - if (GetDeviceProcessingSettings().debugLevel >= 6) { + if (GetProcessingSettings().debugLevel >= 6) { mDebugFile->close(); } if (mCompressionStatistics) { @@ -651,7 +651,7 @@ int GPUChainTracking::ConvertNativeToClusterData() } } if (!param().earlyTpcTransform) { - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Early transform inactive, skipping TPC Early transformation kernel, transformed on the fly during slice data creation / refit"); } return 0; @@ -684,7 +684,7 @@ void GPUChainTracking::ConvertNativeToClusterDataLegacy() GPUReconstructionConvert::ConvertNativeToClusterData(mIOMem.clusterNativeAccess.get(), mIOMem.clusterData, mIOPtrs.nClusterData, processors()->calibObjects.fastTransform, param().continuousMaxTimeBin); for (unsigned int i = 0; i < NSLICES; i++) { mIOPtrs.clusterData[i] = mIOMem.clusterData[i].get(); - if (GetDeviceProcessingSettings().registerStandaloneInputMemory) { + if (GetProcessingSettings().registerStandaloneInputMemory) { if (mRec->registerMemoryForGPU(mIOMem.clusterData[i].get(), mIOPtrs.nClusterData[i] * sizeof(*mIOPtrs.clusterData[i]))) { throw std::runtime_error("Error registering memory for GPU"); } @@ -706,7 +706,7 @@ void GPUChainTracking::ConvertRun2RawToNative() mIOMem.clusterData[i].reset(nullptr); } mIOPtrs.clustersNative = mIOMem.clusterNativeAccess.get(); - if (GetDeviceProcessingSettings().registerStandaloneInputMemory) { + if (GetProcessingSettings().registerStandaloneInputMemory) { if (mRec->registerMemoryForGPU(mIOMem.clustersNative.get(), mIOMem.clusterNativeAccess->nClustersTotal * sizeof(*mIOMem.clusterNativeAccess->clustersLinear))) { throw std::runtime_error("Error registering memory for GPU"); } @@ -721,7 +721,7 @@ void GPUChainTracking::ConvertZSEncoder(bool zs12bit) GPUReconstructionConvert::RunZSEncoder<o2::tpc::Digit>(*mIOPtrs.tpcPackedDigits, &mIOMem.tpcZSpages, &mIOMem.tpcZSmeta2->n[0][0], nullptr, nullptr, param(), zs12bit, true); GPUReconstructionConvert::RunZSEncoderCreateMeta(mIOMem.tpcZSpages.get(), &mIOMem.tpcZSmeta2->n[0][0], &mIOMem.tpcZSmeta2->ptr[0][0], mIOMem.tpcZSmeta.get()); mIOPtrs.tpcZS = mIOMem.tpcZSmeta.get(); - if (GetDeviceProcessingSettings().registerStandaloneInputMemory) { + if (GetProcessingSettings().registerStandaloneInputMemory) { for (unsigned int i = 0; i < NSLICES; i++) { for (unsigned int j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { for (unsigned int k = 0; k < mIOPtrs.tpcZS->slice[i].count[j]; k++) { @@ -768,11 +768,11 @@ void GPUChainTracking::SetTRDGeometry(std::unique_ptr<o2::trd::TRDGeometryFlat>& int GPUChainTracking::ReadEvent(unsigned int iSlice, int threadId) { - if (GetDeviceProcessingSettings().debugLevel >= 5) { + if (GetProcessingSettings().debugLevel >= 5) { GPUInfo("Running ReadEvent for slice %d on thread %d\n", iSlice, threadId); } runKernel<GPUTPCCreateSliceData>({GetGridAuto(0, GPUReconstruction::krnlDeviceType::CPU)}, {iSlice}); - if (GetDeviceProcessingSettings().debugLevel >= 5) { + if (GetProcessingSettings().debugLevel >= 5) { GPUInfo("Finished ReadEvent for slice %d on thread %d\n", iSlice, threadId); } return (0); @@ -780,20 +780,20 @@ int GPUChainTracking::ReadEvent(unsigned int iSlice, int threadId) void GPUChainTracking::WriteOutput(int iSlice, int threadId) { - if (GetDeviceProcessingSettings().debugLevel >= 5) { + if (GetProcessingSettings().debugLevel >= 5) { GPUInfo("Running WriteOutput for slice %d on thread %d\n", iSlice, threadId); } - if (GetDeviceProcessingSettings().nDeviceHelperThreads) { + if (GetProcessingSettings().nDeviceHelperThreads) { while (mLockAtomic.test_and_set(std::memory_order_acquire)) { ; } } processors()->tpcTrackers[iSlice].WriteOutputPrepare(); - if (GetDeviceProcessingSettings().nDeviceHelperThreads) { + if (GetProcessingSettings().nDeviceHelperThreads) { mLockAtomic.clear(); } processors()->tpcTrackers[iSlice].WriteOutput(); - if (GetDeviceProcessingSettings().debugLevel >= 5) { + if (GetProcessingSettings().debugLevel >= 5) { GPUInfo("Finished WriteOutput for slice %d on thread %d\n", iSlice, threadId); } } @@ -843,20 +843,20 @@ int GPUChainTracking::ForwardTPCDigits() int GPUChainTracking::GlobalTracking(unsigned int iSlice, int threadId, bool synchronizeOutput) { - if (GetDeviceProcessingSettings().debugLevel >= 5) { + if (GetProcessingSettings().debugLevel >= 5) { GPUInfo("GPU Tracker running Global Tracking for slice %u on thread %d\n", iSlice, threadId); } - GPUReconstruction::krnlDeviceType deviceType = GetDeviceProcessingSettings().fullMergerOnGPU ? GPUReconstruction::krnlDeviceType::Auto : GPUReconstruction::krnlDeviceType::CPU; + GPUReconstruction::krnlDeviceType deviceType = GetProcessingSettings().fullMergerOnGPU ? GPUReconstruction::krnlDeviceType::Auto : GPUReconstruction::krnlDeviceType::CPU; runKernel<GPUTPCGlobalTracking>(GetGridBlk(256, iSlice % mRec->NStreams(), deviceType), {iSlice}); - if (GetDeviceProcessingSettings().fullMergerOnGPU) { + if (GetProcessingSettings().fullMergerOnGPU) { TransferMemoryResourceLinkToHost(RecoStep::TPCSliceTracking, processors()->tpcTrackers[iSlice].MemoryResCommon(), iSlice % mRec->NStreams()); } if (synchronizeOutput) { SynchronizeStream(iSlice % mRec->NStreams()); } - if (GetDeviceProcessingSettings().debugLevel >= 5) { + if (GetProcessingSettings().debugLevel >= 5) { GPUInfo("GPU Tracker finished Global Tracking for slice %u on thread %d\n", iSlice, threadId); } return (0); @@ -984,7 +984,7 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) return 1; } #ifndef GPUCA_NO_VC - if (GetDeviceProcessingSettings().prefetchTPCpageScan >= 1 && iSlice < NSLICES - 1) { + if (GetProcessingSettings().prefetchTPCpageScan >= 1 && iSlice < NSLICES - 1) { for (unsigned int j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { for (unsigned int k = 0; k < mIOPtrs.tpcZS->slice[iSlice].count[j]; k++) { for (unsigned int l = 0; l < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]; l++) { @@ -1005,7 +1005,7 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) if (mRec->IsGPU()) { processorsShadow()->tpcClusterer[iSlice].SetNMaxDigits(processors()->tpcClusterer[iSlice].mPmemory->counters.nDigits, mCFContext->nPagesFragmentMax, nDigitsFragment[iSlice]); } - if (mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { + if (mPipelineNotifyCtx && GetProcessingSettings().doublePipelineClusterizer) { mPipelineNotifyCtx->rec->AllocateRegisteredForeignMemory(processors()->tpcClusterer[iSlice].mZSOffsetId, mRec); mPipelineNotifyCtx->rec->AllocateRegisteredForeignMemory(processors()->tpcClusterer[iSlice].mZSId, mRec); } else { @@ -1026,13 +1026,13 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) GPUInfo("Event has %lld TPC Digits", (long long int)mRec->MemoryScalers()->nTPCdigits); } mCFContext->fragmentFirst = CfFragment{std::max<int>(mCFContext->tpcMaxTimeBin + 1, TPC_MAX_FRAGMENT_LEN), TPC_MAX_FRAGMENT_LEN}; - for (int iSlice = 0; iSlice < GetDeviceProcessingSettings().nTPCClustererLanes && iSlice < NSLICES; iSlice++) { + for (int iSlice = 0; iSlice < GetProcessingSettings().nTPCClustererLanes && iSlice < NSLICES; iSlice++) { if (mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice]) { - mCFContext->nextPos[iSlice] = RunTPCClusterizer_transferZS(iSlice, mCFContext->fragmentFirst, GetDeviceProcessingSettings().nTPCClustererLanes + iSlice); + mCFContext->nextPos[iSlice] = RunTPCClusterizer_transferZS(iSlice, mCFContext->fragmentFirst, GetProcessingSettings().nTPCClustererLanes + iSlice); } } - if (mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { + if (mPipelineNotifyCtx && GetProcessingSettings().doublePipelineClusterizer) { for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { mCFContext->ptrSave[iSlice].zsOffsetHost = processors()->tpcClusterer[iSlice].mPzsOffsets; mCFContext->ptrSave[iSlice].zsOffsetDevice = processorsShadow()->tpcClusterer[iSlice].mPzsOffsets; @@ -1052,7 +1052,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) mRec->PushNonPersistentMemory(); const auto& threadContext = GetThreadContext(); bool doGPU = GetRecoStepsGPU() & RecoStep::TPCClusterFinding; - if (RunTPCClusterizer_prepare(mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer)) { + if (RunTPCClusterizer_prepare(mPipelineNotifyCtx && GetProcessingSettings().doublePipelineClusterizer)) { return 1; } @@ -1063,7 +1063,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { SetupGPUProcessor(&processors()->tpcClusterer[iSlice], true); // Now we allocate } - if (mPipelineNotifyCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { + if (mPipelineNotifyCtx && GetProcessingSettings().doublePipelineClusterizer) { RunTPCClusterizer_prepare(true); // Restore some pointers, allocated by the other pipeline, and set to 0 by SetupGPUProcessor (since not allocated in this pipeline) } @@ -1079,7 +1079,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) ClusterNativeAccess* tmpNative = mClusterNativeAccess.get(); // setup MC Labels - bool propagateMCLabels = !doGPU && GetDeviceProcessingSettings().runMC && processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC != nullptr; + bool propagateMCLabels = !doGPU && GetProcessingSettings().runMC && processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC != nullptr; auto* digitsMC = propagateMCLabels ? processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC : nullptr; @@ -1099,20 +1099,20 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (buildNativeGPU) { AllocateRegisteredMemory(mInputsHost->mResourceClusterNativeBuffer); } - if (buildNativeHost && !(buildNativeGPU && GetDeviceProcessingSettings().delayedOutput)) { + if (buildNativeHost && !(buildNativeGPU && GetProcessingSettings().delayedOutput)) { AllocateRegisteredMemory(mInputsHost->mResourceClusterNativeOutput, mOutputClustersNative); } char transferRunning[NSLICES] = {0}; unsigned int outputQueueStart = mOutputQueue.size(); - for (unsigned int iSliceBase = 0; iSliceBase < NSLICES; iSliceBase += GetDeviceProcessingSettings().nTPCClustererLanes) { - std::vector<bool> laneHasData(GetDeviceProcessingSettings().nTPCClustererLanes, false); + for (unsigned int iSliceBase = 0; iSliceBase < NSLICES; iSliceBase += GetProcessingSettings().nTPCClustererLanes) { + std::vector<bool> laneHasData(GetProcessingSettings().nTPCClustererLanes, false); for (CfFragment fragment = mCFContext->fragmentFirst; !fragment.isEnd(); fragment = fragment.next()) { - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Processing time bins [%d, %d)", fragment.start, fragment.last()); } - for (int lane = 0; lane < GetDeviceProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { + for (int lane = 0; lane < GetProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { if (fragment.index != 0) { SynchronizeStream(lane); // Don't overwrite charge map from previous iteration until cluster computation is finished } @@ -1156,7 +1156,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice]) { TransferMemoryResourceLinkToGPU(RecoStep::TPCClusterFinding, mInputsHost->mResourceZS, lane); - SynchronizeStream(GetDeviceProcessingSettings().nTPCClustererLanes + lane); + SynchronizeStream(GetProcessingSettings().nTPCClustererLanes + lane); } SynchronizeStream(mRec->NStreams() - 1); // Wait for copying to constant memory @@ -1176,18 +1176,18 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); } } - for (int lane = 0; lane < GetDeviceProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { + for (int lane = 0; lane < GetProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { unsigned int iSlice = iSliceBase + lane; SynchronizeStream(lane); if (mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice]) { CfFragment f = fragment.next(); int nextSlice = iSlice; if (f.isEnd()) { - nextSlice += GetDeviceProcessingSettings().nTPCClustererLanes; + nextSlice += GetProcessingSettings().nTPCClustererLanes; f = mCFContext->fragmentFirst; } if (nextSlice < NSLICES && mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice]) { - mCFContext->nextPos[nextSlice] = RunTPCClusterizer_transferZS(nextSlice, f, GetDeviceProcessingSettings().nTPCClustererLanes + lane); + mCFContext->nextPos[nextSlice] = RunTPCClusterizer_transferZS(nextSlice, f, GetProcessingSettings().nTPCClustererLanes + lane); } } GPUTPCClusterFinder& clusterer = processors()->tpcClusterer[iSlice]; @@ -1215,7 +1215,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpPeaksCompacted, *mDebugFile); } - for (int lane = 0; lane < GetDeviceProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { + for (int lane = 0; lane < GetProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { unsigned int iSlice = iSliceBase + lane; GPUTPCClusterFinder& clusterer = processors()->tpcClusterer[iSlice]; GPUTPCClusterFinder& clustererShadow = doGPU ? processorsShadow()->tpcClusterer[iSlice] : clusterer; @@ -1231,7 +1231,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaksCompacted, *mDebugFile); } - for (int lane = 0; lane < GetDeviceProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { + for (int lane = 0; lane < GetProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { unsigned int iSlice = iSliceBase + lane; GPUTPCClusterFinder& clusterer = processors()->tpcClusterer[iSlice]; GPUTPCClusterFinder& clustererShadow = doGPU ? processorsShadow()->tpcClusterer[iSlice] : clusterer; @@ -1250,7 +1250,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); runKernel<GPUTPCCFClusterizer>(GetGrid(clusterer.mPmemory->counters.nClusters, lane), {iSlice}, {}); - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Lane %d: Found clusters: digits %u peaks %u clusters %u", lane, (int)clusterer.mPmemory->counters.nPositions, (int)clusterer.mPmemory->counters.nPeaks, (int)clusterer.mPmemory->counters.nClusters); } TransferMemoryResourcesToHost(RecoStep::TPCClusterFinding, &clusterer, lane); @@ -1262,7 +1262,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } size_t nClsFirst = nClsTotal; bool anyLaneHasData = false; - for (int lane = 0; lane < GetDeviceProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { + for (int lane = 0; lane < GetProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { unsigned int iSlice = iSliceBase + lane; std::fill(&tmpNative->nClusters[iSlice][0], &tmpNative->nClusters[iSlice][0] + tpc::Constants::MAXGLOBALPADROW, 0); SynchronizeStream(lane); @@ -1270,12 +1270,12 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) GPUTPCClusterFinder& clustererShadow = doGPU ? processorsShadow()->tpcClusterer[iSlice] : clusterer; if (laneHasData[lane]) { anyLaneHasData = true; - if (buildNativeGPU && GetDeviceProcessingSettings().tpccfGatherKernel) { + if (buildNativeGPU && GetProcessingSettings().tpccfGatherKernel) { runKernel<GPUTPCCFGather>(GetGridBlk(GPUCA_ROW_COUNT, mRec->NStreams() - 1), {iSlice}, {}, &mInputsShadow->mPclusterNativeBuffer[nClsTotal]); } for (unsigned int j = 0; j < GPUCA_ROW_COUNT; j++) { if (buildNativeGPU) { - if (!GetDeviceProcessingSettings().tpccfGatherKernel) { + if (!GetProcessingSettings().tpccfGatherKernel) { GPUMemCpyAlways(RecoStep::TPCClusterFinding, (void*)&mInputsShadow->mPclusterNativeBuffer[nClsTotal], (const void*)&clustererShadow.mPclusterByRow[j * clusterer.mNMaxClusterPerRow], sizeof(mIOPtrs.clustersNative->clustersLinear[0]) * clusterer.mPclusterInRow[j], mRec->NStreams() - 1, -2); } } else if (buildNativeHost) { @@ -1305,14 +1305,14 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } } if (buildNativeHost && buildNativeGPU && anyLaneHasData) { - if (GetDeviceProcessingSettings().delayedOutput) { + if (GetProcessingSettings().delayedOutput) { mOutputQueue.emplace_back(outputQueueEntry{(void*)((char*)&mInputsHost->mPclusterNativeOutput[nClsFirst] - (char*)&mInputsHost->mPclusterNativeOutput[0]), &mInputsShadow->mPclusterNativeBuffer[nClsFirst], (nClsTotal - nClsFirst) * sizeof(mInputsHost->mPclusterNativeOutput[nClsFirst]), RecoStep::TPCClusterFinding}); } else { GPUMemCpy(RecoStep::TPCClusterFinding, (void*)&mInputsHost->mPclusterNativeOutput[nClsFirst], (void*)&mInputsShadow->mPclusterNativeBuffer[nClsFirst], (nClsTotal - nClsFirst) * sizeof(mInputsHost->mPclusterNativeOutput[nClsFirst]), mRec->NStreams() - 1, false); } } } - for (int i = 0; i < GetDeviceProcessingSettings().nTPCClustererLanes; i++) { + for (int i = 0; i < GetProcessingSettings().nTPCClustererLanes; i++) { if (transferRunning[i]) { ReleaseEvent(&mEvents->stream[i]); } @@ -1324,7 +1324,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) mcLabels.setFrom(mcLinearLabels.header, mcLinearLabels.data); - if (buildNativeHost && buildNativeGPU && GetDeviceProcessingSettings().delayedOutput) { + if (buildNativeHost && buildNativeGPU && GetProcessingSettings().delayedOutput) { mInputsHost->mNClusterNative = mInputsShadow->mNClusterNative = nClsTotal; AllocateRegisteredMemory(mInputsHost->mResourceClusterNativeOutput, mOutputClustersNative); for (unsigned int i = outputQueueStart; i < mOutputQueue.size(); i++) { @@ -1357,7 +1357,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (synchronizeOutput) { SynchronizeStream(mRec->NStreams() - 1); } - if (buildNativeHost && GetDeviceProcessingSettings().debugLevel >= 4) { + if (buildNativeHost && GetProcessingSettings().debugLevel >= 4) { for (unsigned int i = 0; i < NSLICES; i++) { for (unsigned int j = 0; j < GPUCA_ROW_COUNT; j++) { std::sort(&mInputsHost->mPclusterNativeOutput[tmpNative->clusterOffset[i][j]], &mInputsHost->mPclusterNativeOutput[tmpNative->clusterOffset[i][j] + tmpNative->nClusters[i][j]]); @@ -1396,7 +1396,7 @@ int GPUChainTracking::RunTPCTrackingSlices() int GPUChainTracking::RunTPCTrackingSlices_internal() { - if (GetDeviceProcessingSettings().debugLevel >= 2) { + if (GetProcessingSettings().debugLevel >= 2) { GPUInfo("Running TPC Slice Tracker"); } bool doGPU = GetRecoStepsGPU() & RecoStep::TPCSliceTracking; @@ -1457,7 +1457,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } // Copy Tracker Object to GPU Memory - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Copying Tracker objects to GPU"); } if (PrepareProfile()) { @@ -1478,44 +1478,44 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() int streamMap[NSLICES]; bool error = false; - GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel for if(!(doGPU || GetProcessingSettings().ompKernels)) num_threads(GetProcessingSettings().ompThreads)) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { GPUTPCTracker& trk = processors()->tpcTrackers[iSlice]; GPUTPCTracker& trkShadow = doGPU ? processorsShadow()->tpcTrackers[iSlice] : trk; int useStream = (iSlice % mRec->NStreams()); - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Creating Slice Data (Slice %d)", iSlice); } if (doSliceDataOnGPU) { TransferMemoryResourcesToGPU(RecoStep::TPCSliceTracking, &trk, useStream); runKernel<GPUTPCCreateSliceData>(GetGridBlk(GPUCA_ROW_COUNT, useStream), {iSlice}, {nullptr, streamInit[useStream] ? nullptr : &mEvents->init}); streamInit[useStream] = true; - } else if (!doGPU || iSlice % (GetDeviceProcessingSettings().nDeviceHelperThreads + 1) == 0) { + } else if (!doGPU || iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) == 0) { if (ReadEvent(iSlice, 0)) { GPUError("Error reading event"); error = 1; continue; } } else { - if (GetDeviceProcessingSettings().debugLevel >= 3) { - GPUInfo("Waiting for helper thread %d", iSlice % (GetDeviceProcessingSettings().nDeviceHelperThreads + 1) - 1); + if (GetProcessingSettings().debugLevel >= 3) { + GPUInfo("Waiting for helper thread %d", iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) - 1); } - while (HelperDone(iSlice % (GetDeviceProcessingSettings().nDeviceHelperThreads + 1) - 1) < (int)iSlice) { + while (HelperDone(iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) - 1) < (int)iSlice) { ; } - if (HelperError(iSlice % (GetDeviceProcessingSettings().nDeviceHelperThreads + 1) - 1)) { + if (HelperError(iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) - 1)) { error = 1; continue; } } - if (!doGPU && trk.CheckEmptySlice() && GetDeviceProcessingSettings().debugLevel == 0) { + if (!doGPU && trk.CheckEmptySlice() && GetProcessingSettings().debugLevel == 0) { continue; } - if (GetDeviceProcessingSettings().debugLevel >= 6) { + if (GetProcessingSettings().debugLevel >= 6) { *mDebugFile << "\n\nReconstruction: Slice " << iSlice << "/" << NSLICES << std::endl; - if (GetDeviceProcessingSettings().debugMask & 1) { + if (GetProcessingSettings().debugMask & 1) { if (doSliceDataOnGPU) { TransferMemoryResourcesToHost(RecoStep::TPCSliceTracking, &trk, -1, true); } @@ -1524,10 +1524,10 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } // Initialize temporary memory where needed - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Copying Slice Data to GPU and initializing temporary memory"); } - if (GetDeviceProcessingSettings().keepAllMemory && !doSliceDataOnGPU) { + if (GetProcessingSettings().keepAllMemory && !doSliceDataOnGPU) { memset((void*)trk.Data().HitWeights(), 0, trkShadow.Data().NumberOfHitsPlusAlign() * sizeof(*trkShadow.Data().HitWeights())); } else { runKernel<GPUMemClean16>(GetGridAutoStep(useStream, RecoStep::TPCSliceTracking), krnlRunRangeNone, {}, trkShadow.Data().HitWeights(), trkShadow.Data().NumberOfHitsPlusAlign() * sizeof(*trkShadow.Data().HitWeights())); @@ -1544,10 +1544,10 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() runKernel<GPUTPCNeighboursFinder>(GetGridBlk(GPUCA_ROW_COUNT, useStream), {iSlice}, {nullptr, streamInit[useStream] ? nullptr : &mEvents->init}); streamInit[useStream] = true; - if (GetDeviceProcessingSettings().keepDisplayMemory) { + if (GetProcessingSettings().keepDisplayMemory) { TransferMemoryResourcesToHost(RecoStep::TPCSliceTracking, &trk, -1, true); memcpy(trk.LinkTmpMemory(), mRec->Res(trk.MemoryResLinks()).Ptr(), mRec->Res(trk.MemoryResLinks()).Size()); - if (GetDeviceProcessingSettings().debugMask & 2) { + if (GetProcessingSettings().debugMask & 2) { trk.DumpLinks(*mDebugFile); } } @@ -1563,26 +1563,26 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() #endif DoDebugAndDump(RecoStep::TPCSliceTracking, 32, trk, &GPUTPCTracker::DumpStartHits, *mDebugFile); - if (GetDeviceProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { trk.UpdateMaxData(); AllocateRegisteredMemory(trk.MemoryResTracklets()); AllocateRegisteredMemory(trk.MemoryResOutput()); } - if (!(doGPU || GetDeviceProcessingSettings().debugLevel >= 1) || GetDeviceProcessingSettings().trackletConstructorInPipeline) { + if (!(doGPU || GetProcessingSettings().debugLevel >= 1) || GetProcessingSettings().trackletConstructorInPipeline) { runKernel<GPUTPCTrackletConstructor>(GetGridAuto(useStream), {iSlice}); DoDebugAndDump(RecoStep::TPCSliceTracking, 128, trk, &GPUTPCTracker::DumpTrackletHits, *mDebugFile); - if (GetDeviceProcessingSettings().debugMask & 256 && !GetDeviceProcessingSettings().comparableDebutOutput) { + if (GetProcessingSettings().debugMask & 256 && !GetProcessingSettings().comparableDebutOutput) { trk.DumpHitWeights(*mDebugFile); } } - if (!(doGPU || GetDeviceProcessingSettings().debugLevel >= 1) || GetDeviceProcessingSettings().trackletSelectorInPipeline) { + if (!(doGPU || GetProcessingSettings().debugLevel >= 1) || GetProcessingSettings().trackletSelectorInPipeline) { runKernel<GPUTPCTrackletSelector>(GetGridAuto(useStream), {iSlice}); runKernel<GPUTPCGlobalTrackingCopyNumbers>({1, -ThreadCount(), useStream}, {iSlice}, {}, 1); TransferMemoryResourceLinkToHost(RecoStep::TPCSliceTracking, trk.MemoryResCommon(), useStream, &mEvents->slice[iSlice]); streamMap[iSlice] = useStream; - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Slice %u, Number of tracks: %d", iSlice, *trk.NTracks()); } DoDebugAndDump(RecoStep::TPCSliceTracking, 512, trk, &GPUTPCTracker::DumpTrackHits, *mDebugFile); @@ -1592,14 +1592,14 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() return (3); } - if (doGPU || GetDeviceProcessingSettings().debugLevel >= 1) { + if (doGPU || GetProcessingSettings().debugLevel >= 1) { ReleaseEvent(&mEvents->init); if (!doSliceDataOnGPU) { WaitForHelperThreads(); } - if (!GetDeviceProcessingSettings().trackletSelectorInPipeline) { - if (GetDeviceProcessingSettings().trackletConstructorInPipeline) { + if (!GetProcessingSettings().trackletSelectorInPipeline) { + if (GetProcessingSettings().trackletConstructorInPipeline) { SynchronizeGPU(); } else { for (int i = 0; i < mRec->NStreams(); i++) { @@ -1613,7 +1613,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() ReleaseEvent(&mEvents->single); } - if (GetDeviceProcessingSettings().debugLevel >= 4) { + if (GetProcessingSettings().debugLevel >= 4) { for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { DoDebugAndDump(RecoStep::TPCSliceTracking, 128, processors()->tpcTrackers[iSlice], &GPUTPCTracker::DumpTrackletHits, *mDebugFile); } @@ -1622,7 +1622,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() int runSlices = 0; int useStream = 0; for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice += runSlices) { - if (runSlices < GetDeviceProcessingSettings().trackletSelectorSlices) { + if (runSlices < GetProcessingSettings().trackletSelectorSlices) { runSlices++; } runSlices = CAMath::Min<int>(runSlices, NSLICES - iSlice); @@ -1630,7 +1630,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() runSlices = getKernelProperties<GPUTPCTrackletSelector>().minBlocks * BlockCount(); } - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Running TPC Tracklet selector (Stream %d, Slice %d to %d)", useStream, iSlice, iSlice + runSlices); } runKernel<GPUTPCTrackletSelector>(GetGridAuto(useStream), {iSlice, runSlices}); @@ -1658,7 +1658,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() unsigned int tmpSlice = 0; for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Transfering Tracks from GPU to Host"); } @@ -1675,15 +1675,15 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() tmpSlice++; } - if (GetDeviceProcessingSettings().keepAllMemory) { + if (GetProcessingSettings().keepAllMemory) { TransferMemoryResourcesToHost(RecoStep::TPCSliceTracking, &processors()->tpcTrackers[iSlice], -1, true); - if (!GetDeviceProcessingSettings().trackletConstructorInPipeline) { - if (GetDeviceProcessingSettings().debugMask & 256 && !GetDeviceProcessingSettings().comparableDebutOutput) { + if (!GetProcessingSettings().trackletConstructorInPipeline) { + if (GetProcessingSettings().debugMask & 256 && !GetProcessingSettings().comparableDebutOutput) { processors()->tpcTrackers[iSlice].DumpHitWeights(*mDebugFile); } } - if (!GetDeviceProcessingSettings().trackletSelectorInPipeline) { - if (GetDeviceProcessingSettings().debugMask & 512) { + if (!GetProcessingSettings().trackletSelectorInPipeline) { + if (GetProcessingSettings().debugMask & 512) { processors()->tpcTrackers[iSlice].DumpTrackHits(*mDebugFile); } } @@ -1692,17 +1692,17 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() if (transferRunning[iSlice]) { SynchronizeEvents(&mEvents->slice[iSlice]); } - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Tracks Transfered: %d / %d", *processors()->tpcTrackers[iSlice].NTracks(), *processors()->tpcTrackers[iSlice].NTrackHits()); } - if (GetDeviceProcessingSettings().debugLevel >= 3) { - GPUInfo("Data ready for slice %d, helper thread %d", iSlice, iSlice % (GetDeviceProcessingSettings().nDeviceHelperThreads + 1)); + if (GetProcessingSettings().debugLevel >= 3) { + GPUInfo("Data ready for slice %d, helper thread %d", iSlice, iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1)); } mSliceSelectorReady = iSlice; if (param().rec.GlobalTracking) { - for (unsigned int tmpSlice2a = 0; tmpSlice2a <= iSlice; tmpSlice2a += GetDeviceProcessingSettings().nDeviceHelperThreads + 1) { + for (unsigned int tmpSlice2a = 0; tmpSlice2a <= iSlice; tmpSlice2a += GetProcessingSettings().nDeviceHelperThreads + 1) { unsigned int tmpSlice2 = GPUTPCGlobalTracking::GlobalTrackingSliceOrder(tmpSlice2a); unsigned int sliceLeft = (tmpSlice2 + (NSLICES / 2 - 1)) % (NSLICES / 2); unsigned int sliceRight = (tmpSlice2 + 1) % (NSLICES / 2); @@ -1718,7 +1718,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } } } else { - if (iSlice % (GetDeviceProcessingSettings().nDeviceHelperThreads + 1) == 0) { + if (iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) == 0) { WriteOutput(iSlice, 0); } } @@ -1730,12 +1730,12 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() ReleaseEvent(&mEvents->slice[iSlice]); } if (!(GetRecoStepsOutputs() & GPUDataTypes::InOutType::TPCSectorTracks) && param().rec.GlobalTracking) { - GlobalTracking(iSlice, 0, !GetDeviceProcessingSettings().fullMergerOnGPU); + GlobalTracking(iSlice, 0, !GetProcessingSettings().fullMergerOnGPU); } } } else { mSliceSelectorReady = NSLICES; - GPUCA_OPENMP(parallel for if(!(doGPU || GetDeviceProcessingSettings().ompKernels)) num_threads(GetDeviceProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel for if(!(doGPU || GetProcessingSettings().ompKernels)) num_threads(GetProcessingSettings().ompThreads)) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { if (param().rec.GlobalTracking) { GlobalTracking(iSlice, 0); @@ -1746,14 +1746,14 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } } - if (param().rec.GlobalTracking && GetDeviceProcessingSettings().debugLevel >= 3) { + if (param().rec.GlobalTracking && GetProcessingSettings().debugLevel >= 3) { for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { GPUInfo("Slice %d - Tracks: Local %d Global %d - Hits: Local %d Global %d", iSlice, processors()->tpcTrackers[iSlice].CommonMemory()->nLocalTracks, processors()->tpcTrackers[iSlice].CommonMemory()->nTracks, processors()->tpcTrackers[iSlice].CommonMemory()->nLocalTrackHits, processors()->tpcTrackers[iSlice].CommonMemory()->nTrackHits); } } - if (GetDeviceProcessingSettings().debugMask & 1024 && !GetDeviceProcessingSettings().comparableDebutOutput) { + if (GetProcessingSettings().debugMask & 1024 && !GetProcessingSettings().comparableDebutOutput) { for (unsigned int i = 0; i < NSLICES; i++) { processors()->tpcTrackers[i].DumpOutput(*mDebugFile); } @@ -1767,11 +1767,11 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() mIOPtrs.sliceTracks[i] = processors()->tpcTrackers[i].Tracks(); mIOPtrs.nSliceClusters[i] = *processors()->tpcTrackers[i].NTrackHits(); mIOPtrs.sliceClusters[i] = processors()->tpcTrackers[i].TrackHits(); - if (GetDeviceProcessingSettings().keepDisplayMemory && !GetDeviceProcessingSettings().keepAllMemory) { + if (GetProcessingSettings().keepDisplayMemory && !GetProcessingSettings().keepAllMemory) { TransferMemoryResourcesToHost(RecoStep::TPCSliceTracking, &processors()->tpcTrackers[i], -1, true); } } - if (GetDeviceProcessingSettings().debugLevel >= 2) { + if (GetProcessingSettings().debugLevel >= 2) { GPUInfo("TPC Slice Tracker finished"); } mRec->PopNonPersistentMemory(RecoStep::TPCSliceTracking); @@ -1781,8 +1781,8 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() void GPUChainTracking::RunTPCTrackingMerger_MergeBorderTracks(char withinSlice, char mergeMode, GPUReconstruction::krnlDeviceType deviceType) { unsigned int n = withinSlice == -1 ? NSLICES / 2 : NSLICES; - bool doGPUall = GetRecoStepsGPU() & RecoStep::TPCMerging && GetDeviceProcessingSettings().fullMergerOnGPU; - if (GetDeviceProcessingSettings().alternateBorderSort && (!mRec->IsGPU() || doGPUall)) { + bool doGPUall = GetRecoStepsGPU() & RecoStep::TPCMerging && GetProcessingSettings().fullMergerOnGPU; + if (GetProcessingSettings().alternateBorderSort && (!mRec->IsGPU() || doGPUall)) { GPUTPCGMMerger& Merger = processors()->tpcMerger; GPUTPCGMMerger& MergerShadow = doGPUall ? processorsShadow()->tpcMerger : Merger; TransferMemoryResourceLinkToHost(RecoStep::TPCMerging, Merger.MemoryResMemory(), 0, &mEvents->init); @@ -1840,7 +1840,7 @@ void GPUChainTracking::RunTPCTrackingMerger_Resolve(char useOrigTrackParam, char int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) { - if (GetDeviceProcessingSettings().debugLevel >= 6 && GetDeviceProcessingSettings().comparableDebutOutput && param().rec.mergerReadFromTrackerDirectly) { + if (GetProcessingSettings().debugLevel >= 6 && GetProcessingSettings().comparableDebutOutput && param().rec.mergerReadFromTrackerDirectly) { for (unsigned int i = 0; i < NSLICES; i++) { GPUTPCTracker& trk = processors()->tpcTrackers[i]; TransferMemoryResourcesToHost(RecoStep::NoRecoStep, &trk); @@ -1857,13 +1857,13 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) } mRec->PushNonPersistentMemory(); bool doGPU = GetRecoStepsGPU() & RecoStep::TPCMerging; - bool doGPUall = doGPU && GetDeviceProcessingSettings().fullMergerOnGPU; + bool doGPUall = doGPU && GetProcessingSettings().fullMergerOnGPU; GPUReconstruction::krnlDeviceType deviceType = doGPUall ? GPUReconstruction::krnlDeviceType::Auto : GPUReconstruction::krnlDeviceType::CPU; unsigned int numBlocks = (!mRec->IsGPU() || doGPUall) ? BlockCount() : 1; GPUTPCGMMerger& Merger = processors()->tpcMerger; GPUTPCGMMerger& MergerShadow = doGPU ? processorsShadow()->tpcMerger : Merger; GPUTPCGMMerger& MergerShadowAll = doGPUall ? processorsShadow()->tpcMerger : Merger; - if (GetDeviceProcessingSettings().debugLevel >= 2) { + if (GetProcessingSettings().debugLevel >= 2) { GPUInfo("Running TPC Merger"); } const auto& threadContext = GetThreadContext(); @@ -1933,7 +1933,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) waitForTransfer = 1; } - if (GetDeviceProcessingSettings().mergerSortTracks) { + if (GetProcessingSettings().mergerSortTracks) { runKernel<GPUTPCGMMergerSortTracksPrepare>(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); CondWaitEvent(waitForTransfer, &mEvents->single); runKernel<GPUTPCGMMergerSortTracks>(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); @@ -1965,14 +1965,14 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) TransferMemoryResourcesToGPU(RecoStep::TPCMerging, &Merger, 0); } - if (GetDeviceProcessingSettings().delayedOutput) { + if (GetProcessingSettings().delayedOutput) { for (unsigned int i = 0; i < mOutputQueue.size(); i++) { GPUMemCpy(mOutputQueue[i].step, mOutputQueue[i].dst, mOutputQueue[i].src, mOutputQueue[i].size, mRec->NStreams() - 2, false); } mOutputQueue.clear(); } - runKernel<GPUTPCGMMergerTrackFit>(GetGridBlk(Merger.NOutputTracks(), 0), krnlRunRangeNone, krnlEventNone, GetDeviceProcessingSettings().mergerSortTracks ? 1 : 0); + runKernel<GPUTPCGMMergerTrackFit>(GetGridBlk(Merger.NOutputTracks(), 0), krnlRunRangeNone, krnlEventNone, GetProcessingSettings().mergerSortTracks ? 1 : 0); if (param().rec.retryRefit == 1) { runKernel<GPUTPCGMMergerTrackFit>(GetGridAuto(0), krnlRunRangeNone, krnlEventNone, -1); } @@ -1994,7 +1994,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) if (doGPUall) { RecordMarker(&mEvents->single, 0); - if (!GetDeviceProcessingSettings().fullMergerOnGPU) { + if (!GetProcessingSettings().fullMergerOnGPU) { TransferMemoryResourceLinkToHost(RecoStep::TPCMerging, Merger.MemoryResOutput(), mRec->NStreams() - 2, nullptr, &mEvents->single); } else { GPUMemCpy(RecoStep::TPCMerging, Merger.OutputTracks(), MergerShadowAll.OutputTracks(), Merger.NOutputTracks() * sizeof(*Merger.OutputTracks()), mRec->NStreams() - 2, 0, nullptr, &mEvents->single); @@ -2011,7 +2011,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) } else { TransferMemoryResourcesToGPU(RecoStep::TPCMerging, &Merger, 0); } - if (GetDeviceProcessingSettings().keepDisplayMemory && !GetDeviceProcessingSettings().keepAllMemory) { + if (GetProcessingSettings().keepDisplayMemory && !GetProcessingSettings().keepAllMemory) { TransferMemoryResourcesToHost(RecoStep::TPCMerging, &Merger, -1, true); } mRec->ReturnVolatileDeviceMemory(); @@ -2022,7 +2022,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) mIOPtrs.nMergedTrackHits = Merger.NOutputTrackClusters(); mIOPtrs.mergedTrackHitAttachment = Merger.ClusterAttachment(); - if (GetDeviceProcessingSettings().debugLevel >= 2) { + if (GetProcessingSettings().debugLevel >= 2) { GPUInfo("TPC Merger Finished (output clusters %d / input clusters %d)", Merger.NOutputTrackClusters(), Merger.NClusters()); } mRec->PopNonPersistentMemory(RecoStep::TPCMerging); @@ -2038,7 +2038,7 @@ int GPUChainTracking::RunTPCCompression() GPUTPCCompression& Compressor = processors()->tpcCompressor; GPUTPCCompression& CompressorShadow = doGPU ? processorsShadow()->tpcCompressor : Compressor; const auto& threadContext = GetThreadContext(); - if (mPipelineFinalizationCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { + if (mPipelineFinalizationCtx && GetProcessingSettings().doublePipelineClusterizer) { RecordMarker(&mEvents->single, 0); } Compressor.mNMaxClusterSliceRow = 0; @@ -2058,7 +2058,7 @@ int GPUChainTracking::RunTPCCompression() runKernel<GPUTPCCompressionKernels, GPUTPCCompressionKernels::step0attached>(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); runKernel<GPUTPCCompressionKernels, GPUTPCCompressionKernels::step1unattached>(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); TransferMemoryResourcesToHost(myStep, &Compressor, 0); - if (mPipelineFinalizationCtx && GetDeviceProcessingSettings().doublePipelineClusterizer) { + if (mPipelineFinalizationCtx && GetProcessingSettings().doublePipelineClusterizer) { SynchronizeEvents(&mEvents->single); ReleaseEvent(&mEvents->single); ((GPUChainTracking*)GetNextChainInQueue())->RunTPCClusterizer_prepare(false); @@ -2078,12 +2078,12 @@ int GPUChainTracking::RunTPCCompression() const o2::tpc::CompressedClustersPtrs* P = nullptr; HighResTimer* gatherTimer = nullptr; int outputStream = 0; - if (DeviceProcessingSettings().doublePipeline) { + if (ProcessingSettings().doublePipeline) { SynchronizeStream(mRec->NStreams() - 2); // Synchronize output copies running in parallel from memory that might be released, only the following async copy from stacked memory is safe after the chain finishes. outputStream = mRec->NStreams() - 2; } - if (DeviceProcessingSettings().tpcCompressionGatherMode == 2) { + if (ProcessingSettings().tpcCompressionGatherMode == 2) { void* devicePtr = mRec->getGPUPointer(Compressor.mOutputFlat); if (devicePtr != Compressor.mOutputFlat) { CompressedClustersPtrs& ptrs = *Compressor.mOutput; // We need to update the ptrs with the gpu-mapped version of the host address space @@ -2097,9 +2097,9 @@ int GPUChainTracking::RunTPCCompression() getKernelTimer<GPUTPCCompressionKernels, GPUTPCCompressionKernels::step2gather>(RecoStep::TPCCompression, 0, outputSize); } else { char direction = 0; - if (DeviceProcessingSettings().tpcCompressionGatherMode == 0) { + if (ProcessingSettings().tpcCompressionGatherMode == 0) { P = &CompressorShadow.mPtrs; - } else if (DeviceProcessingSettings().tpcCompressionGatherMode == 1) { + } else if (ProcessingSettings().tpcCompressionGatherMode == 1) { P = &Compressor.mPtrs; direction = -1; gatherTimer = &getTimer<GPUTPCCompressionKernels>("GPUTPCCompression_GatherOnCPU", 0); @@ -2142,7 +2142,7 @@ int GPUChainTracking::RunTPCCompression() GPUMemCpyAlways(myStep, O->timeA, P->timeA, O->nTracks * sizeof(O->timeA[0]), outputStream, direction); GPUMemCpyAlways(myStep, O->padA, P->padA, O->nTracks * sizeof(O->padA[0]), outputStream, direction); } - if (DeviceProcessingSettings().tpcCompressionGatherMode == 1) { + if (ProcessingSettings().tpcCompressionGatherMode == 1) { gatherTimer->Stop(); } mIOPtrs.tpcCompressedClusters = Compressor.mOutputFlat; @@ -2262,7 +2262,7 @@ int GPUChainTracking::DoTRDGPUTracking() TransferMemoryResourcesToHost(RecoStep::TRDTracking, &Tracker, 0); SynchronizeStream(0); - if (GetDeviceProcessingSettings().debugLevel >= 2) { + if (GetProcessingSettings().debugLevel >= 2) { GPUInfo("GPU TRD tracker Finished"); } #endif @@ -2272,16 +2272,16 @@ int GPUChainTracking::DoTRDGPUTracking() int GPUChainTracking::RunChain() { const auto threadContext = GetThreadContext(); - if (GetDeviceProcessingSettings().runCompressionStatistics && mCompressionStatistics == nullptr) { + if (GetProcessingSettings().runCompressionStatistics && mCompressionStatistics == nullptr) { mCompressionStatistics.reset(new GPUTPCClusterStatistics); } - const bool needQA = GPUQA::QAAvailable() && (GetDeviceProcessingSettings().runQA || (GetDeviceProcessingSettings().eventDisplay && mIOPtrs.nMCInfosTPC)); + const bool needQA = GPUQA::QAAvailable() && (GetProcessingSettings().runQA || (GetProcessingSettings().eventDisplay && mIOPtrs.nMCInfosTPC)); if (needQA && mQA->IsInitialized() == false) { if (mQA->InitQA()) { return 1; } } - if (GetDeviceProcessingSettings().debugLevel >= 6) { + if (GetProcessingSettings().debugLevel >= 6) { *mDebugFile << "\n\nProcessing event " << mRec->getNEventsProcessed() << std::endl; } if (mRec->slavesExist() && mRec->IsGPU()) { @@ -2334,10 +2334,10 @@ int GPUChainTracking::RunChain() mRec->PopNonPersistentMemory(RecoStep::TPCSliceTracking); // Release 1st stack level, TPC slice data not needed after merger if (mIOPtrs.clustersNative) { - if (GetDeviceProcessingSettings().doublePipeline) { + if (GetProcessingSettings().doublePipeline) { GPUChainTracking* foreignChain = (GPUChainTracking*)GetNextChainInQueue(); if (foreignChain && foreignChain->mIOPtrs.tpcZS) { - if (GetDeviceProcessingSettings().debugLevel >= 3) { + if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Preempting tpcZS input of foreign chain"); } mPipelineFinalizationCtx.reset(new GPUChainTrackingFinalContext); @@ -2354,7 +2354,7 @@ int GPUChainTracking::RunChain() return 1; } - if (!GetDeviceProcessingSettings().doublePipeline) { // Synchronize with output copies running asynchronously + if (!GetProcessingSettings().doublePipeline) { // Synchronize with output copies running asynchronously SynchronizeStream(mRec->NStreams() - 2); } @@ -2362,26 +2362,26 @@ int GPUChainTracking::RunChain() return 1; } - return GetDeviceProcessingSettings().doublePipeline ? 0 : RunChainFinalize(); + return GetProcessingSettings().doublePipeline ? 0 : RunChainFinalize(); } int GPUChainTracking::RunChainFinalize() { #ifdef HAVE_O2HEADERS - if (mIOPtrs.clustersNative && (GetRecoSteps() & RecoStep::TPCCompression) && GetDeviceProcessingSettings().runCompressionStatistics) { + if (mIOPtrs.clustersNative && (GetRecoSteps() & RecoStep::TPCCompression) && GetProcessingSettings().runCompressionStatistics) { CompressedClusters c = *mIOPtrs.tpcCompressedClusters; mCompressionStatistics->RunStatistics(mIOPtrs.clustersNative, &c, param()); } #endif - const bool needQA = GPUQA::QAAvailable() && (GetDeviceProcessingSettings().runQA || (GetDeviceProcessingSettings().eventDisplay && mIOPtrs.nMCInfosTPC)); + const bool needQA = GPUQA::QAAvailable() && (GetProcessingSettings().runQA || (GetProcessingSettings().eventDisplay && mIOPtrs.nMCInfosTPC)); if (needQA) { mRec->getGeneralStepTimer(GeneralStep::QA).Start(); - mQA->RunQA(!GetDeviceProcessingSettings().runQA); + mQA->RunQA(!GetProcessingSettings().runQA); mRec->getGeneralStepTimer(GeneralStep::QA).Stop(); } - if (GetDeviceProcessingSettings().eventDisplay) { + if (GetProcessingSettings().eventDisplay) { if (!mDisplayRunning) { if (mEventDisplay->StartDisplay()) { return (1); @@ -2391,7 +2391,7 @@ int GPUChainTracking::RunChainFinalize() mEventDisplay->ShowNextEvent(); } - if (GetDeviceProcessingSettings().eventDisplay->EnableSendKey()) { + if (GetProcessingSettings().eventDisplay->EnableSendKey()) { while (kbhit()) { getch(); } @@ -2401,27 +2401,27 @@ int GPUChainTracking::RunChainFinalize() int iKey; do { Sleep(10); - if (GetDeviceProcessingSettings().eventDisplay->EnableSendKey()) { + if (GetProcessingSettings().eventDisplay->EnableSendKey()) { iKey = kbhit() ? getch() : 0; if (iKey == 'q') { - GetDeviceProcessingSettings().eventDisplay->mDisplayControl = 2; + GetProcessingSettings().eventDisplay->mDisplayControl = 2; } else if (iKey == 'n') { break; } else if (iKey) { - while (GetDeviceProcessingSettings().eventDisplay->mSendKey != 0) { + while (GetProcessingSettings().eventDisplay->mSendKey != 0) { Sleep(1); } - GetDeviceProcessingSettings().eventDisplay->mSendKey = iKey; + GetProcessingSettings().eventDisplay->mSendKey = iKey; } } - } while (GetDeviceProcessingSettings().eventDisplay->mDisplayControl == 0); - if (GetDeviceProcessingSettings().eventDisplay->mDisplayControl == 2) { + } while (GetProcessingSettings().eventDisplay->mDisplayControl == 0); + if (GetProcessingSettings().eventDisplay->mDisplayControl == 2) { mDisplayRunning = false; - GetDeviceProcessingSettings().eventDisplay->DisplayExit(); - DeviceProcessingSettings().eventDisplay = nullptr; + GetProcessingSettings().eventDisplay->DisplayExit(); + ProcessingSettings().eventDisplay = nullptr; return (2); } - GetDeviceProcessingSettings().eventDisplay->mDisplayControl = 0; + GetProcessingSettings().eventDisplay->mDisplayControl = 0; GPUInfo("Loading next event"); mEventDisplay->WaitForNextEvent(); @@ -2483,7 +2483,7 @@ int GPUChainTracking::CheckErrorCodes() for (int i = 0; i < 1 + mRec->IsGPU(); i++) { if (i) { const auto& threadContext = GetThreadContext(); - if (GetDeviceProcessingSettings().doublePipeline) { + if (GetProcessingSettings().doublePipeline) { TransferMemoryResourceLinkToHost(RecoStep::NoRecoStep, mInputsHost->mResourceErrorCodes, 0); SynchronizeStream(0); } else { diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 879d8b83e1442..629c2de0fd830 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -39,7 +39,7 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) } mConfig.reset(new GPUO2InterfaceConfiguration(config)); mContinuous = mConfig->configEvent.continuousMaxTimeBin != 0; - mRec.reset(GPUReconstruction::CreateInstance(mConfig->configProcessing)); + mRec.reset(GPUReconstruction::CreateInstance(mConfig->configDeviceBackend)); if (mRec == nullptr) { GPUError("Error obtaining instance of GPUReconstruction"); return 1; @@ -50,7 +50,7 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) if (mConfig->configWorkflow.inputs.isSet(GPUDataTypes::InOutType::TPCRaw)) { mConfig->configEvent.needsClusterer = 1; } - mRec->SetSettings(&mConfig->configEvent, &mConfig->configReconstruction, &mConfig->configDeviceProcessing, &mConfig->configWorkflow); + mRec->SetSettings(&mConfig->configEvent, &mConfig->configReconstruction, &mConfig->configProcessing, &mConfig->configWorkflow); mChain->SetTPCFastTransform(mConfig->configCalib.fastTransform); mChain->SetdEdxSplines(mConfig->configCalib.dEdxSplines); mChain->SetMatLUT(mConfig->configCalib.matLUT); @@ -67,7 +67,7 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) if (mRec->Init()) { return (1); } - if (!mRec->IsGPU() && mConfig->configDeviceProcessing.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (!mRec->IsGPU() && mConfig->configProcessing.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { mRec->MemoryScalers()->factor *= 2; } mInitialized = true; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index f4646c2c1b9b3..a1017f8ee86fb 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -74,14 +74,15 @@ struct GPUO2InterfaceConfiguration { struct GPUInterfaceSettings { int dumpEvents = 0; bool outputToExternalBuffers = false; - // These constants affect GPU memory allocation and do not limit the CPU processing + // These constants affect GPU memory allocation only and do not limit the CPU processing + unsigned long maxTPCZS = 4096ul * 1024 * 1024; unsigned int maxTPCHits = 1024 * 1024 * 1024; unsigned int maxTRDTracklets = 128 * 1024; unsigned int maxITSTracks = 96 * 1024; }; + GPUSettingsDeviceBackend configDeviceBackend; GPUSettingsProcessing configProcessing; - GPUSettingsDeviceProcessing configDeviceProcessing; GPUSettingsEvent configEvent; GPUSettingsRec configReconstruction; GPUDisplayConfig configDisplay; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 24112c107d489..72b1088445755 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -252,7 +252,7 @@ void* GPUTPCGMMerger::SetPointersRefitScratch(void* mem) { computePointerWithAlignment(mem, mRetryRefitIds, mNMaxTracks); computePointerWithAlignment(mem, mLoopData, mNMaxTracks); - if (mRec->GetDeviceProcessingSettings().fullMergerOnGPU) { + if (mRec->GetProcessingSettings().fullMergerOnGPU) { mem = SetPointersRefitScratch2(mem); } return mem; @@ -261,7 +261,7 @@ void* GPUTPCGMMerger::SetPointersRefitScratch(void* mem) void* GPUTPCGMMerger::SetPointersRefitScratch2(void* mem) { computePointerWithAlignment(mem, mTrackOrderAttach, mNMaxTracks); - if (mRec->GetDeviceProcessingSettings().mergerSortTracks) { + if (mRec->GetProcessingSettings().mergerSortTracks) { computePointerWithAlignment(mem, mTrackOrderProcess, mNMaxTracks); } return mem; @@ -275,7 +275,7 @@ void* GPUTPCGMMerger::SetPointersOutput(void* mem) computePointerWithAlignment(mem, mClustersXYZ, mNMaxOutputTrackClusters); } computePointerWithAlignment(mem, mClusterAttachment, mNMaxClusters); - if (!mRec->GetDeviceProcessingSettings().fullMergerOnGPU) { + if (!mRec->GetProcessingSettings().fullMergerOnGPU) { mem = SetPointersRefitScratch2(mem); } @@ -285,9 +285,9 @@ void* GPUTPCGMMerger::SetPointersOutput(void* mem) void GPUTPCGMMerger::RegisterMemoryAllocation() { AllocateAndInitializeLate(); - mRec->RegisterMemoryAllocation(this, &GPUTPCGMMerger::SetPointersMerger, (mRec->GetDeviceProcessingSettings().fullMergerOnGPU ? 0 : GPUMemoryResource::MEMORY_HOST) | GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCMerger"); + mRec->RegisterMemoryAllocation(this, &GPUTPCGMMerger::SetPointersMerger, (mRec->GetProcessingSettings().fullMergerOnGPU ? 0 : GPUMemoryResource::MEMORY_HOST) | GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCMerger"); mRec->RegisterMemoryAllocation(this, &GPUTPCGMMerger::SetPointersRefitScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCMergerRefitScratch"); - mMemoryResOutput = mRec->RegisterMemoryAllocation(this, &GPUTPCGMMerger::SetPointersOutput, (mRec->GetDeviceProcessingSettings().fullMergerOnGPU ? GPUMemoryResource::MEMORY_OUTPUT : GPUMemoryResource::MEMORY_INOUT) | GPUMemoryResource::MEMORY_CUSTOM, "TPCMergerOutput"); + mMemoryResOutput = mRec->RegisterMemoryAllocation(this, &GPUTPCGMMerger::SetPointersOutput, (mRec->GetProcessingSettings().fullMergerOnGPU ? GPUMemoryResource::MEMORY_OUTPUT : GPUMemoryResource::MEMORY_INOUT) | GPUMemoryResource::MEMORY_CUSTOM, "TPCMergerOutput"); mMemoryResMemory = mRec->RegisterMemoryAllocation(this, &GPUTPCGMMerger::SetPointersMemory, GPUMemoryResource::MEMORY_PERMANENT, "TPCMergerMemory"); } @@ -708,7 +708,7 @@ struct MergeBorderTracks_compMin { template <> void GPUCA_KRNL_BACKEND_CLASS::runKernelBackendInternal<GPUTPCGMMergerMergeBorders, 3>(krnlSetup& _xyz, GPUTPCGMBorderRange* const& range, int const& N, int const& cmpMax) { - GPUDebugTiming timer(mDeviceProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); + GPUDebugTiming timer(mProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); thrust::device_ptr<GPUTPCGMBorderRange> p(range); ThrustVolatileAsyncAllocator alloc(this); if (cmpMax) { @@ -1740,7 +1740,7 @@ struct GPUTPCGMMergerSortTracks_comp { template <> void GPUCA_KRNL_BACKEND_CLASS::runKernelBackendInternal<GPUTPCGMMergerSortTracks, 0>(krnlSetup& _xyz) { - GPUDebugTiming timer(mDeviceProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); + GPUDebugTiming timer(mProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); thrust::device_ptr<unsigned int> trackSort((unsigned int*)mProcessorsShadow->tpcMerger.TrackOrderProcess()); ThrustVolatileAsyncAllocator alloc(this); thrust::sort(GPUCA_THRUST_NAMESPACE::par(alloc).on(mInternals->Streams[_xyz.x.stream]), trackSort, trackSort + processors()->tpcMerger.NOutputTracks(), GPUTPCGMMergerSortTracks_comp(mProcessorsShadow->tpcMerger.OutputTracks())); @@ -1760,7 +1760,7 @@ struct GPUTPCGMMergerSortTracksQPt_comp { template <> void GPUCA_KRNL_BACKEND_CLASS::runKernelBackendInternal<GPUTPCGMMergerSortTracksQPt, 0>(krnlSetup& _xyz) { - GPUDebugTiming timer(mDeviceProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); + GPUDebugTiming timer(mProcessingSettings.debugLevel, nullptr, mInternals->Streams, _xyz, this); thrust::device_ptr<unsigned int> trackSort((unsigned int*)mProcessorsShadow->tpcMerger.TmpMem()); ThrustVolatileAsyncAllocator alloc(this); thrust::sort(GPUCA_THRUST_NAMESPACE::par(alloc).on(mInternals->Streams[_xyz.x.stream]), trackSort, trackSort + processors()->tpcMerger.NOutputTracks(), GPUTPCGMMergerSortTracksQPt_comp(mProcessorsShadow->tpcMerger.OutputTracks())); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx index 88ef9c094174a..70a3f0f8a4a12 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx @@ -23,7 +23,7 @@ template <> GPUdii() void GPUTPCGMMergerTrackFit::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, int mode) { const int iEnd = mode == -1 ? merger.Memory()->nRetryRefit : merger.NOutputTracks(); - GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel for if(!merger.GetRec().GetProcessingSettings().ompKernels) num_threads(merger.GetRec().GetProcessingSettings().ompThreads)) for (int ii = get_global_id(0); ii < iEnd; ii += get_global_size(0)) { const int i = mode == -1 ? merger.RetryRefitIds()[ii] : mode ? merger.TrackOrderProcess()[ii] : ii; GPUTPCGMTrackParam::RefitTrack(merger.OutputTracks()[i], i, &merger, mode == -1); @@ -33,7 +33,7 @@ GPUdii() void GPUTPCGMMergerTrackFit::Thread<0>(int nBlocks, int nThreads, int i template <> GPUdii() void GPUTPCGMMergerFollowLoopers::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger) { - GPUCA_OPENMP(parallel for if(!merger.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(merger.GetRec().GetDeviceProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel for if(!merger.GetRec().GetProcessingSettings().ompKernels) num_threads(merger.GetRec().GetProcessingSettings().ompThreads)) for (unsigned int i = get_global_id(0); i < merger.Memory()->nLoopData; i += get_global_size(0)) { GPUTPCGMTrackParam::RefitLoop(&merger, i); } diff --git a/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx b/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx index c9ecc673658b9..8b5af42c399dd 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx @@ -292,7 +292,7 @@ int GPUTPCGlobalMergerComponent::Configure(const char* cdbEntry, const char* cha GPUSettingsEvent ev; GPUSettingsRec rec; - GPUSettingsDeviceProcessing devProc; + GPUSettingsProcessing devProc; ev.solenoidBz = fSolenoidBz; if (fClusterErrorCorrectionY > 1.e-4) { rec.ClusterError2CorrectionY = fClusterErrorCorrectionY * fClusterErrorCorrectionY; diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx index 0dfaa88012a23..87de160778a69 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx @@ -78,7 +78,7 @@ void* GPUTPCTracker::SetPointersDataRows(void* mem) { return mData.SetPointersRo void* GPUTPCTracker::SetPointersScratch(void* mem) { computePointerWithAlignment(mem, mTrackletStartHits, mNMaxStartHits); - if (mRec->GetDeviceProcessingSettings().memoryAllocationStrategy != GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (mRec->GetProcessingSettings().memoryAllocationStrategy != GPUMemoryResource::ALLOCATION_INDIVIDUAL) { mem = SetPointersTracklets(mem); } if (mRec->IsGPU()) { @@ -90,7 +90,7 @@ void* GPUTPCTracker::SetPointersScratch(void* mem) void* GPUTPCTracker::SetPointersScratchHost(void* mem) { - if (mRec->GetDeviceProcessingSettings().keepDisplayMemory) { + if (mRec->GetProcessingSettings().keepDisplayMemory) { computePointerWithAlignment(mem, mLinkTmpMemory, mRec->Res(mMemoryResLinks).Size()); } mem = mData.SetPointersClusterIds(mem, mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCMerging); @@ -106,21 +106,21 @@ void* GPUTPCTracker::SetPointersCommon(void* mem) void GPUTPCTracker::RegisterMemoryAllocation() { AllocateAndInitializeLate(); - bool reuseCondition = !mRec->GetDeviceProcessingSettings().keepDisplayMemory && mRec->GetDeviceProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetDeviceProcessingSettings().ompThreads == 1); - GPUMemoryReuse reLinks{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerDataLinks, (unsigned short)(mISlice % mRec->GetDeviceProcessingSettings().nStreams)}; + bool reuseCondition = !mRec->GetProcessingSettings().keepDisplayMemory && mRec->GetProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetProcessingSettings().ompThreads == 1); + GPUMemoryReuse reLinks{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerDataLinks, (unsigned short)(mISlice % mRec->GetProcessingSettings().nStreams)}; mMemoryResLinks = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataLinks, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCSliceLinks", reLinks); mMemoryResSliceScratch = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK | GPUMemoryResource::MEMORY_CUSTOM, "TPCSliceScratch"); mMemoryResSliceInput = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataInput, GPUMemoryResource::MEMORY_INPUT | GPUMemoryResource::MEMORY_STACK | GPUMemoryResource::MEMORY_CUSTOM, "TPCSliceInput"); - GPUMemoryReuse reWeights{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerDataWeights, (unsigned short)(mISlice % mRec->GetDeviceProcessingSettings().nStreams)}; + GPUMemoryReuse reWeights{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerDataWeights, (unsigned short)(mISlice % mRec->GetProcessingSettings().nStreams)}; mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataWeights, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCSliceWeights", reWeights); - GPUMemoryReuse reScratch{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerScratch, (unsigned short)(mISlice % mRec->GetDeviceProcessingSettings().nStreams)}; + GPUMemoryReuse reScratch{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerScratch, (unsigned short)(mISlice % mRec->GetProcessingSettings().nStreams)}; mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCTrackerScratch", reScratch); mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersScratchHost, GPUMemoryResource::MEMORY_SCRATCH_HOST, "TPCTrackerHost"); mMemoryResCommon = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersCommon, GPUMemoryResource::MEMORY_PERMANENT, "TPCTrackerCommon"); mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataRows, GPUMemoryResource::MEMORY_PERMANENT, "TPCSliceRows"); - unsigned int type = mRec->GetDeviceProcessingSettings().fullMergerOnGPU ? GPUMemoryResource::MEMORY_SCRATCH : GPUMemoryResource::MEMORY_OUTPUT; - if (mRec->GetDeviceProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { // For individual scheme, we allocate tracklets separately, and change the type for the following allocations to custom + unsigned int type = mRec->GetProcessingSettings().fullMergerOnGPU ? GPUMemoryResource::MEMORY_SCRATCH : GPUMemoryResource::MEMORY_OUTPUT; + if (mRec->GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { // For individual scheme, we allocate tracklets separately, and change the type for the following allocations to custom type |= GPUMemoryResource::MEMORY_CUSTOM; mMemoryResTracklets = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersTracklets, type, "TPCTrackerTracklets"); } @@ -143,7 +143,7 @@ GPUhd() void* GPUTPCTracker::SetPointersOutput(void* mem) void GPUTPCTracker::SetMaxData(const GPUTrackingInOutPointers& io) { - if (mRec->GetDeviceProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + if (mRec->GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { mNMaxStartHits = mData.NumberOfHits(); } else { mNMaxStartHits = mRec->MemoryScalers()->NTPCStartHits(mData.NumberOfHits()); diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx index 9fa63b304fddd..a436d1bd971e3 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx @@ -370,7 +370,7 @@ int GPUTPCTrackerComponent::ConfigureSlices() // Initialize the tracker slices GPUSettingsRec rec; GPUSettingsEvent ev; - GPUSettingsDeviceProcessing devProc; + GPUSettingsProcessing devProc; ev.solenoidBz = fSolenoidBz; ev.continuousMaxTimeBin = 0; // triggered events diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx index e0466f685eef3..7f113aa94ca04 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx @@ -114,7 +114,7 @@ void GPUTPCTracker::DumpStartHits(std::ostream& out) { // sort start hits and dump to file out << "Start Hits: (Slice" << mISlice << ") (" << *NStartHits() << ")" << std::endl; - if (mRec->GetDeviceProcessingSettings().comparableDebutOutput) { + if (mRec->GetProcessingSettings().comparableDebutOutput) { qsort(TrackletStartHits(), *NStartHits(), sizeof(GPUTPCHitId), StarthitSortComparison); } for (unsigned int i = 0; i < *NStartHits(); i++) { @@ -137,7 +137,7 @@ void GPUTPCTracker::DumpTrackHits(std::ostream& out) for (int i = 0; i < Tracks()[j].NHits(); i++) { out << TrackHits()[Tracks()[j].FirstHitID() + i].RowIndex() << "-" << TrackHits()[Tracks()[j].FirstHitID() + i].HitIndex() << ", "; } - if (!mRec->GetDeviceProcessingSettings().comparableDebutOutput) { + if (!mRec->GetProcessingSettings().comparableDebutOutput) { out << "(Track: " << j << ")"; } out << std::endl; @@ -157,7 +157,7 @@ void GPUTPCTracker::DumpTrackletHits(std::ostream& out) out << "Tracklets: (Slice" << mISlice << ") (" << nTracklets << ")" << std::endl; std::vector<int> Ids(nTracklets); std::iota(Ids.begin(), Ids.end(), 0); - if (mRec->GetDeviceProcessingSettings().comparableDebutOutput) { + if (mRec->GetProcessingSettings().comparableDebutOutput) { std::sort(Ids.begin(), Ids.end(), [this](const int& a, const int& b) { if (this->Tracklets()[a].FirstRow() == this->Tracklets()[b].FirstRow()) { return this->Tracklets()[a].Param().Y() > this->Tracklets()[b].Param().Y(); diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 2992b055826fa..9a08a84f05a85 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -636,7 +636,7 @@ int GPUDisplay::InitGL_internal() setQuality(); ReSizeGLScene(GPUDisplayBackend::INIT_WIDTH, GPUDisplayBackend::INIT_HEIGHT, true); #ifdef WITH_OPENMP - int maxThreads = mChain->GetDeviceProcessingSettings().ompThreads > 1 ? mChain->GetDeviceProcessingSettings().ompThreads : 1; + int maxThreads = mChain->GetProcessingSettings().ompThreads > 1 ? mChain->GetProcessingSettings().ompThreads : 1; omp_set_num_threads(maxThreads); #else int maxThreads = 1; @@ -1170,7 +1170,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) mMaxClusterZ = 0; bool error = false; - GPUCA_OPENMP(parallel for num_threads(mChain->GetDeviceProcessingSettings().ompThreads) reduction(max : mMaxClusterZ)) + GPUCA_OPENMP(parallel for num_threads(mChain->GetProcessingSettings().ompThreads) reduction(max : mMaxClusterZ)) for (int iSlice = 0; iSlice < NSLICES; iSlice++) { if (error) { continue; @@ -1225,7 +1225,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) return (1); } - GPUCA_OPENMP(parallel for num_threads(mChain->GetDeviceProcessingSettings().ompThreads) reduction(max : mMaxClusterZ)) + GPUCA_OPENMP(parallel for num_threads(mChain->GetProcessingSettings().ompThreads) reduction(max : mMaxClusterZ)) for (int i = 0; i < mCurrentSpacePointsTRD; i++) { const auto& sp = trdTracker().SpacePoints()[i]; int iSec = mChain->GetTRDGeometry()->GetSector(trdTracker().Tracklets()[i].GetDetector()); @@ -1557,7 +1557,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) mGlDLFinal[iSlice].resize(mNCollissions); } } - GPUCA_OPENMP(parallel num_threads(mChain->GetDeviceProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel num_threads(mChain->GetProcessingSettings().ompThreads)) { #ifdef WITH_OPENMP int numThread = omp_get_thread_num(); diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index cc5a783bbed7b..4ea8035c646c4 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -65,7 +65,7 @@ AddHelp("help", 'h') EndConfig() // Settings steering the processing once the device was selected -BeginSubConfig(GPUSettingsDeviceProcessing, configProc, configStandalone, "PROC", 0, "Processing settings") +BeginSubConfig(GPUSettingsProcessing, configProc, configStandalone, "PROC", 0, "Processing settings") AddOption(platformNum, int, -1, "", 0, "Platform to use, in case the backend provides multiple platforms (-1 = auto-select)") AddOption(gpuDeviceOnly, bool, false, "", 0, "Use only GPU as device (i.e. no CPU for OpenCL)") AddOption(debugMask, int, -1, "", 0, "Mask for debug output dumps to file") @@ -238,7 +238,7 @@ AddSubConfig(GPUSettingsQA, configQA) AddSubConfig(GPUSettingsEG, configEG) AddSubConfig(GPUSettingsDisplay, configGL) AddSubConfig(GPUSettingsRec, configRec) -AddSubConfig(GPUSettingsDeviceProcessing, configProc) +AddSubConfig(GPUSettingsProcessing, configProc) EndConfig() #elif defined(GPUCA_O2_LIB) // GPUCA_STANDALONE BeginSubConfig(GPUSettingsO2, configGPUO2, configStandalone, "O2", 0, "O2 workflow settings") diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 5f0ec03d5a894..69a223ba800ee 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -295,9 +295,9 @@ int SetupReconstruction() GPUSettingsEvent ev = rec->GetEventSettings(); GPUSettingsRec recSet; - GPUSettingsDeviceProcessing devProc; + GPUSettingsProcessing devProc; memcpy((void*)&recSet, (void*)&configStandalone.configRec, sizeof(GPUSettingsRec)); - memcpy((void*)&devProc, (void*)&configStandalone.configProc, sizeof(GPUSettingsDeviceProcessing)); + memcpy((void*)&devProc, (void*)&configStandalone.configProc, sizeof(GPUSettingsProcessing)); GPURecoStepConfiguration steps; if (configStandalone.eventGenerator) { @@ -900,7 +900,7 @@ int main(int argc, char** argv) } breakrun: - if (rec->GetDeviceProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { + if (rec->GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_GLOBAL) { rec->PrintMemoryMax(); } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx index d05fd115b4850..6de2623d70614 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx @@ -89,10 +89,10 @@ void GPUTPCClusterFinder::RegisterMemoryAllocation() { AllocateAndInitializeLate(); mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersInput, GPUMemoryResource::MEMORY_INPUT | GPUMemoryResource::MEMORY_GPU | GPUMemoryResource::MEMORY_STACK, "TPCClustererInput"); - mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCClustererScratch", GPUMemoryReuse{GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::ClustererScratch, (unsigned short)(mISlice % mRec->GetDeviceProcessingSettings().nTPCClustererLanes)}); + mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCClustererScratch", GPUMemoryReuse{GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::ClustererScratch, (unsigned short)(mISlice % mRec->GetProcessingSettings().nTPCClustererLanes)}); mMemoryId = mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersMemory, GPUMemoryResource::MEMORY_PERMANENT, "TPCClustererMemory"); mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersOutput, GPUMemoryResource::MEMORY_OUTPUT | GPUMemoryResource::MEMORY_STACK, "TPCClustererOutput"); - mZSId = mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersZS, GPUMemoryResource::MEMORY_CUSTOM | GPUMemoryResource::MEMORY_CUSTOM_TRANSFER | GPUMemoryResource::MEMORY_GPU | GPUMemoryResource::MEMORY_STACK, "TPCClustererZSData", GPUMemoryReuse{GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::ClustererZS, (unsigned short)(mISlice % mRec->GetDeviceProcessingSettings().nTPCClustererLanes)}); + mZSId = mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersZS, GPUMemoryResource::MEMORY_CUSTOM | GPUMemoryResource::MEMORY_CUSTOM_TRANSFER | GPUMemoryResource::MEMORY_GPU | GPUMemoryResource::MEMORY_STACK, "TPCClustererZSData", GPUMemoryReuse{GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::ClustererZS, (unsigned short)(mISlice % mRec->GetProcessingSettings().nTPCClustererLanes)}); mZSOffsetId = mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersZSOffset, GPUMemoryResource::MEMORY_CUSTOM | GPUMemoryResource::MEMORY_CUSTOM_TRANSFER | GPUMemoryResource::MEMORY_INPUT | GPUMemoryResource::MEMORY_STACK, "TPCClustererZSOffsets"); } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx index 2b1003cf7a678..0eaa192f37778 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx @@ -185,7 +185,7 @@ int GPUTRDTrackerComponent::DoInit(int argc, const char** argv) GPUSettingsEvent cfgEvent; cfgEvent.solenoidBz = GetBz(); GPUSettingsRec cfgRec; - GPUSettingsDeviceProcessing cfgDeviceProcessing; + GPUSettingsProcessing cfgDeviceProcessing; GPURecoStepConfiguration cfgRecoStep; cfgRecoStep.steps = GPUDataTypes::RecoStep::NoRecoStep; cfgRecoStep.inputs.clear(); diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx index 7b5e948a99356..296407ed2af00 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerKernels.cxx @@ -23,7 +23,7 @@ using namespace GPUCA_NAMESPACE::gpu; template <> GPUdii() void GPUTRDTrackerKernels::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) { - GPUCA_OPENMP(parallel for if(!processors.trdTracker.GetRec().GetDeviceProcessingSettings().ompKernels) num_threads(processors.trdTracker.GetRec().GetDeviceProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel for if(!processors.trdTracker.GetRec().GetProcessingSettings().ompKernels) num_threads(processors.trdTracker.GetRec().GetProcessingSettings().ompThreads)) for (int i = get_global_id(0); i < processors.trdTracker.NTracks(); i += get_global_size(0)) { processors.trdTracker.DoTrackingThread(i, get_global_id(0)); } diff --git a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C index a7413e4894325..c7fc292457c82 100644 --- a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C +++ b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C @@ -42,7 +42,7 @@ void run_trd_tracker(std::string path = "./", //-------- init GPU reconstruction --------// GPUSettingsEvent cfgEvent; // defaults should be ok GPUSettingsRec cfgRec; // don't care for now, NWaysOuter is set in here for instance - GPUSettingsDeviceProcessing cfgDeviceProcessing; // also keep defaults here, or adjust debug level + GPUSettingsProcessing cfgDeviceProcessing; // also keep defaults here, or adjust debug level cfgDeviceProcessing.debugLevel = 10; GPURecoStepConfiguration cfgRecoStep; cfgRecoStep.steps = GPUDataTypes::RecoStep::NoRecoStep; From 336df45ab49043b7812d92b72adb23bcf53613e5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 19 Jul 2020 14:21:06 +0200 Subject: [PATCH 0153/1751] Add some useful information to warnings --- Common/Utils/src/ConfigurableParamHelper.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Common/Utils/src/ConfigurableParamHelper.cxx b/Common/Utils/src/ConfigurableParamHelper.cxx index 5fcba03b305e5..838b44cc8115c 100644 --- a/Common/Utils/src/ConfigurableParamHelper.cxx +++ b/Common/Utils/src/ConfigurableParamHelper.cxx @@ -83,18 +83,18 @@ void loopOverMembers(TClass* cl, void* obj, } if (dm->IsaPointer()) { - LOG(WARNING) << "Pointer types not supported in ConfigurableParams"; + LOG(WARNING) << "Pointer types not supported in ConfigurableParams: " << dm->GetFullTypeName() << " " << dm->GetName(); continue; } if (!dm->IsBasic() && !isValidComplex()) { - LOG(WARNING) << "Generic complex types not supported in ConfigurableParams"; + LOG(WARNING) << "Generic complex types not supported in ConfigurableParams: " << dm->GetFullTypeName() << " " << dm->GetName(); continue; } const auto dim = dm->GetArrayDim(); // we support very simple vectored data in 1D for now if (dim > 1) { - LOG(WARNING) << "We support at most 1 dimensional arrays in ConfigurableParams"; + LOG(WARNING) << "We support at most 1 dimensional arrays in ConfigurableParams: " << dm->GetFullTypeName() << " " << dm->GetName(); continue; } From f09760f2e67ba76fa331454077a61ba136441a90 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 19 Jul 2020 11:36:20 +0200 Subject: [PATCH 0154/1751] GPU: Use ConfigurableParam to configure GPU Tracking workflow --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 191 +++--------------- GPU/GPUTracking/Base/GPUReconstruction.cxx | 3 + .../Base/GPUReconstructionTimeframe.cxx | 2 +- GPU/GPUTracking/Base/GPUSettings.h | 1 + GPU/GPUTracking/CMakeLists.txt | 4 +- GPU/GPUTracking/GPUTrackingLinkDef_O2.h | 5 + .../GPUO2InterfaceConfigurableParam.cxx | 100 +++++++++ .../GPUO2InterfaceConfigurableParam.h | 75 +++++++ .../Interface/GPUO2InterfaceConfiguration.h | 3 + .../Standalone/display/GPUDisplay.cxx | 2 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 10 +- GPU/GPUTracking/Standalone/qa/genEvents.cxx | 2 +- GPU/GPUTracking/Standalone/qconfigoptions.h | 88 ++++---- GPU/GPUTracking/Standalone/standalone.cxx | 146 ++++++------- GPU/GPUTracking/Standalone/utils/qconfig.cxx | 10 + GPU/GPUTracking/Standalone/utils/qconfig.h | 2 +- 16 files changed, 352 insertions(+), 292 deletions(-) create mode 100644 GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx create mode 100644 GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 10407716c7f93..fa8eb8a1d124c 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -95,178 +95,37 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int auto processAttributes = std::make_shared<ProcessAttributes>(); auto initFunction = [processAttributes, specconfig](InitContext& ic) { - auto options = ic.options().get<std::string>("tracker-options"); { auto& parser = processAttributes->parser; auto& tracker = processAttributes->tracker; parser = std::make_unique<ClusterGroupParser>(); tracker = std::make_unique<GPUCATracking>(); - // Prepare initialization of CATracker - we parse the deprecated option string here, - // and create the proper configuration objects for compatibility. - // This should go away eventually. - - // Default Settings - float solenoidBz = 5.00668; // B-field - float refX = 83.; // transport tracks to this x after tracking, >500 for disabling - bool continuous = false; // time frame data v.s. triggered events - int nThreads = 1; // number of threads if we run on the CPU, 1 = default, 0 = auto-detect - bool useGPU = false; // use a GPU for processing, if false uses GPU - int debugLevel = 0; // Enable additional debug output - int dump = 0; // create memory dump of processed events for standalone runs, 2 to dump only and skip processing - char gpuType[1024] = "CUDA"; // Type of GPU device, if useGPU is set to true - int gpuDevice = -1; // Select GPU device id (-1 = auto-detect fastest, -2 = use pipeline-slice) - GPUDisplayBackend* display = nullptr; // Ptr to display backend (enables event display) - bool qa = false; // Run the QA after tracking - bool readTransformationFromFile = false; // Read the TPC transformation from the file - bool allocateOutputOnTheFly = true; // Provide a callback to allocate output buffer on the fly instead of preallocating - char tpcTransformationFileName[1024] = ""; // A file with the TPC transformation - char matBudFileName[1024] = ""; // Material budget file name - char dEdxSplinesFile[1024] = ""; // File containing dEdx splines - int tpcRejectionMode = GPUSettings::RejectionStrategyA; - size_t memoryPoolSize = 1; - size_t hostMemoryPoolSize = 0; + // Create configuration object and fill settings + GPUO2InterfaceConfiguration config; const auto grp = o2::parameters::GRPObject::loadFrom("o2sim_grp.root"); if (grp) { - solenoidBz *= grp->getL3Current() / 30000.; - continuous = grp->isDetContinuousReadOut(o2::detectors::DetID::TPC); - LOG(INFO) << "Initializing run paramerers from GRP bz=" << solenoidBz << " cont=" << continuous; + config.configEvent.solenoidBz *= grp->getL3Current() / 30000.; + config.configEvent.continuousMaxTimeBin = grp->isDetContinuousReadOut(o2::detectors::DetID::TPC) ? -1 : 0; // Number of timebins in timeframe if continuous, 0 otherwise + LOG(INFO) << "Initializing run paramerers from GRP bz=" << config.configEvent.solenoidBz << " cont=" << grp->isDetContinuousReadOut(o2::detectors::DetID::TPC); } else { throw std::runtime_error("Failed to initialize run parameters from GRP"); } - - // Parse the config string - const char* opt = options.c_str(); - if (opt && *opt) { - printf("Received options %s\n", opt); - const char* optPtr = opt; - while (optPtr && *optPtr) { - while (*optPtr == ' ') { - optPtr++; - } - const char* nextPtr = strstr(optPtr, " "); - const int optLen = nextPtr ? nextPtr - optPtr : strlen(optPtr); - if (strncmp(optPtr, "cont", optLen) == 0) { - continuous = true; - printf("Continuous tracking mode enabled\n"); - } else if (strncmp(optPtr, "dump", optLen) == 0) { - dump = 1; - printf("Dumping of input events enabled\n"); - } else if (strncmp(optPtr, "dumponly", optLen) == 0) { - dump = 2; - printf("Dumping of input events enabled, processing disabled\n"); - } else if (strncmp(optPtr, "display", optLen) == 0) { -#ifdef GPUCA_BUILD_EVENT_DISPLAY - processAttributes->displayBackend.reset(new GPUDisplayBackendGlfw); - display = processAttributes->displayBackend.get(); - printf("Event display enabled\n"); -#else - printf("Standalone Event Display not enabled at build time!\n"); -#endif - } else if (strncmp(optPtr, "qa", optLen) == 0) { - qa = true; - printf("Enabling TPC Standalone QA\n"); - } else if (optLen > 3 && strncmp(optPtr, "bz=", 3) == 0) { - sscanf(optPtr + 3, "%f", &solenoidBz); - printf("Using solenoid field %f\n", solenoidBz); - } else if (optLen > 5 && strncmp(optPtr, "refX=", 5) == 0) { - sscanf(optPtr + 5, "%f", &refX); - printf("Propagating to reference X %f\n", refX); - } else if (optLen > 5 && strncmp(optPtr, "debug=", 6) == 0) { - sscanf(optPtr + 6, "%d", &debugLevel); - printf("Debug level set to %d\n", debugLevel); - } else if (optLen > 8 && strncmp(optPtr, "threads=", 8) == 0) { - sscanf(optPtr + 8, "%d", &nThreads); - printf("Using %d threads\n", nThreads); - } else if (optLen > 21 && strncmp(optPtr, "tpcRejectionStrategy=", 21) == 0) { - sscanf(optPtr + 21, "%d", &tpcRejectionMode); - tpcRejectionMode = tpcRejectionMode == 0 ? GPUSettings::RejectionNone : tpcRejectionMode == 1 ? GPUSettings::RejectionStrategyA : GPUSettings::RejectionStrategyB; - printf("TPC Rejection Mode: %d\n", tpcRejectionMode); - } else if (optLen > 8 && strncmp(optPtr, "gpuType=", 8) == 0) { - int len = std::min(optLen - 8, 1023); - memcpy(gpuType, optPtr + 8, len); - gpuType[len] = 0; - useGPU = true; - printf("Using GPU Type %s\n", gpuType); - } else if (optLen > 8 && strncmp(optPtr, "matBudFile=", 8) == 0) { - int len = std::min(optLen - 11, 1023); - memcpy(matBudFileName, optPtr + 11, len); - matBudFileName[len] = 0; - } else if (optLen > 7 && strncmp(optPtr, "gpuNum=", 7) == 0) { - sscanf(optPtr + 7, "%d", &gpuDevice); - printf("Using GPU device %d\n", gpuDevice); - } else if (optLen > 8 && strncmp(optPtr, "gpuMemorySize=", 14) == 0) { - sscanf(optPtr + 14, "%llu", (unsigned long long int*)&memoryPoolSize); - printf("GPU memory pool size set to %llu\n", (unsigned long long int)memoryPoolSize); - } else if (optLen > 8 && strncmp(optPtr, "hostMemorySize=", 15) == 0) { - sscanf(optPtr + 15, "%llu", (unsigned long long int*)&hostMemoryPoolSize); - printf("Host memory pool size set to %llu\n", (unsigned long long int)hostMemoryPoolSize); - } else if (optLen > 8 && strncmp(optPtr, "dEdxFile=", 9) == 0) { - int len = std::min(optLen - 9, 1023); - memcpy(dEdxSplinesFile, optPtr + 9, len); - dEdxSplinesFile[len] = 0; - } else if (optLen > 15 && strncmp(optPtr, "transformation=", 15) == 0) { - int len = std::min(optLen - 15, 1023); - memcpy(tpcTransformationFileName, optPtr + 15, len); - tpcTransformationFileName[len] = 0; - readTransformationFromFile = true; - printf("Read TPC transformation from the file \"%s\"\n", tpcTransformationFileName); - } else { - printf("Unknown option: %s\n", optPtr); - throw std::invalid_argument("Unknown config string option"); - } - optPtr = nextPtr; - } + const GPUSettingsO2& confParam = config.ReadConfigurableParam(); + processAttributes->allocateOutputOnTheFly = confParam.allocateOutputOnTheFly; + processAttributes->suppressOutput = (confParam.dump == 2); + if (config.configEvent.continuousMaxTimeBin == -1) { + config.configEvent.continuousMaxTimeBin = (o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * o2::constants::lhc::LHCMaxBunches + 2 * Constants::LHCBCPERTIMEBIN - 2) / Constants::LHCBCPERTIMEBIN; } - - // Create configuration object and fill settings - processAttributes->allocateOutputOnTheFly = allocateOutputOnTheFly; - processAttributes->suppressOutput = (dump == 2); - GPUO2InterfaceConfiguration config; - if (useGPU) { - config.configDeviceBackend.deviceType = GPUDataTypes::GetDeviceType(gpuType); - } else { - config.configDeviceBackend.deviceType = GPUDataTypes::DeviceType::CPU; - } - config.configDeviceBackend.forceDeviceType = true; // If we request a GPU, we force that it is available - no CPU fallback - - if (gpuDevice == -2) { + if (config.configProcessing.deviceNum == -2) { int myId = ic.services().get<const o2::framework::DeviceSpec>().inputTimesliceId; int idMax = ic.services().get<const o2::framework::DeviceSpec>().maxInputTimeslices; - gpuDevice = myId; + config.configProcessing.deviceNum = myId; LOG(INFO) << "GPU device number selected from pipeline id: " << myId << " / " << idMax; } - config.configProcessing.deviceNum = gpuDevice; - config.configProcessing.ompThreads = nThreads; - config.configProcessing.runQA = qa; // Run QA after tracking - config.configProcessing.runMC = specconfig.processMC; // Propagate MC labels - config.configProcessing.eventDisplay = display; // Ptr to event display backend, for running standalone OpenGL event display - config.configProcessing.debugLevel = debugLevel; // Debug verbosity - config.configProcessing.forceMemoryPoolSize = memoryPoolSize; // GPU / Host Memory pool size, default = 1 = auto-detect - config.configProcessing.forceHostMemoryPoolSize = hostMemoryPoolSize; // Same for host, overrides the avove value for the host if set - if (memoryPoolSize || hostMemoryPoolSize) { - config.configProcessing.memoryAllocationStrategy = 2; - } - - config.configEvent.solenoidBz = solenoidBz; - int maxContTimeBin = (o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * o2::constants::lhc::LHCMaxBunches + 2 * Constants::LHCBCPERTIMEBIN - 2) / Constants::LHCBCPERTIMEBIN; - config.configEvent.continuousMaxTimeBin = continuous ? maxContTimeBin : 0; // Number of timebins in timeframe if continuous, 0 otherwise - - config.configReconstruction.NWays = 3; // Should always be 3! - config.configReconstruction.NWaysOuter = true; // Will create outer param for TRD - config.configReconstruction.SearchWindowDZDR = 2.5f; // Should always be 2.5 for looper-finding and/or continuous tracking - config.configReconstruction.TrackReferenceX = refX; - - // Settings for TPC Compression: - config.configReconstruction.tpcRejectionMode = tpcRejectionMode; // Implement TPC Strategy A - config.configReconstruction.tpcRejectQPt = 1.f / 0.05f; // Reject clusters of tracks < 50 MeV - config.configReconstruction.tpcCompressionModes = GPUSettings::CompressionFull; // Activate all compression steps - config.configReconstruction.tpcCompressionSortOrder = GPUSettings::SortTime; // Sort order for differences compression - config.configReconstruction.tpcSigBitsCharge = 4; // Number of significant bits in TPC cluster chargs - config.configReconstruction.tpcSigBitsWidth = 3; // Number of significant bits in TPC cluster width - - config.configInterface.dumpEvents = dump; + config.configProcessing.runMC = specconfig.processMC; + config.configReconstruction.NWaysOuter = true; config.configInterface.outputToExternalBuffers = true; // Configure the "GPU workflow" i.e. which steps we run on the GPU (or CPU) with this instance of GPUCATracking @@ -294,9 +153,9 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } // Create and forward data objects for TPC transformation, material LUT, ... - if (readTransformationFromFile) { + if (confParam.transformationFile.size()) { processAttributes->fastTransform = nullptr; - config.configCalib.fastTransform = TPCFastTransform::loadFromFile(tpcTransformationFileName); + config.configCalib.fastTransform = TPCFastTransform::loadFromFile(confParam.transformationFile.c_str()); } else { processAttributes->fastTransform = std::move(TPCFastTransformHelperO2::instance()->create(0)); config.configCalib.fastTransform = processAttributes->fastTransform.get(); @@ -304,14 +163,15 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int if (config.configCalib.fastTransform == nullptr) { throw std::invalid_argument("GPUCATracking: initialization of the TPC transformation failed"); } - if (strlen(matBudFileName)) { - config.configCalib.matLUT = o2::base::MatLayerCylSet::loadFromFile(matBudFileName, "MatBud"); + if (confParam.matLUTFile.size()) { + config.configCalib.matLUT = o2::base::MatLayerCylSet::loadFromFile(confParam.matLUTFile.c_str(), "MatBud"); } - processAttributes->dEdxSplines.reset(new TPCdEdxCalibrationSplines); - if (strlen(dEdxSplinesFile)) { - TFile dEdxFile(dEdxSplinesFile); - processAttributes->dEdxSplines->setSplinesFromFile(dEdxFile); + if (confParam.dEdxFile.size()) { + processAttributes->dEdxSplines.reset(new TPCdEdxCalibrationSplines(confParam.dEdxFile.c_str())); + } else { + processAttributes->dEdxSplines.reset(new TPCdEdxCalibrationSplines); } + config.configCalib.dEdxSplines = processAttributes->dEdxSplines.get(); // Sample code what needs to be done for the TRD Geometry, when we extend this to TRD tracking. @@ -877,10 +737,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int return DataProcessorSpec{"tpc-tracker", // process id {createInputSpecs()}, {createOutputSpecs()}, - AlgorithmSpec(initFunction), - Options{ - {"tracker-options", VariantType::String, "", {"Option string passed to tracker"}}, - }}; + AlgorithmSpec(initFunction)}; } } // namespace tpc diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index b3da6adc0e504..1eb32726c6588 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -193,6 +193,9 @@ int GPUReconstruction::InitPhaseBeforeDevice() mRecoStepsGPU.set((unsigned char)0); } + if (mProcessingSettings.forceMemoryPoolSize || mProcessingSettings.forceHostMemoryPoolSize) { + mProcessingSettings.memoryAllocationStrategy = GPUMemoryResource::ALLOCATION_GLOBAL; + } if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_AUTO) { mProcessingSettings.memoryAllocationStrategy = IsGPU() ? GPUMemoryResource::ALLOCATION_GLOBAL : GPUMemoryResource::ALLOCATION_INDIVIDUAL; } diff --git a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx index 430a6a9d2ea13..a7cd332069943 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.cxx @@ -35,7 +35,7 @@ namespace GPUCA_NAMESPACE::gpu { extern GPUSettingsStandalone configStandalone; } -static auto& config = configStandalone.configTF; +static auto& config = configStandalone.TF; GPUReconstructionTimeframe::GPUReconstructionTimeframe(GPUChainTracking* chain, int (*read)(int), int nEvents) : mChain(chain), mReadEvent(read), mNEventsInDirectory(nEvents), mDisUniReal(0., 1.), mRndGen1(configStandalone.seed), mRndGen2(mDisUniInt(mRndGen1)) { diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index a99dd343a5e9d..6bb8b9b95e94e 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -17,6 +17,7 @@ #include "GPUCommonDef.h" #ifndef __OPENCL__ #include <vector> +#include <string> #endif namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 54c39c206bd50..7ef4be1f8abb9 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -133,8 +133,8 @@ set(HDRS_INSTALL # Sources only for O2 if(ALIGPU_BUILD_TYPE STREQUAL "O2") - set(SRCS ${SRCS} Interface/GPUO2Interface.cxx) - set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h dEdx/TPCdEdxCalibrationSplines.h) + set(SRCS ${SRCS} Interface/GPUO2Interface.cxx Interface/GPUO2InterfaceConfigurableParam.cxx) + set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h Interface/GPUO2InterfaceConfigurableParam.h dEdx/TPCdEdxCalibrationSplines.h) endif() # Sources for O2 and for Standalone if requested in config file diff --git a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h index df36878f8dee3..bcd8d5fdb0936 100644 --- a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h +++ b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h @@ -19,5 +19,10 @@ #pragma link C++ class o2::gpu::GPUTPCO2Interface + ; #pragma link C++ class o2::gpu::TPCdEdxCalibrationSplines + ; +#pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsO2 + ; +#pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsRec + ; +#pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsProcessing + ; +#pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsDisplay + ; +#pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsQA + ; #endif diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx new file mode 100644 index 0000000000000..8b401c2688e3f --- /dev/null +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx @@ -0,0 +1,100 @@ +// 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 GPUO2InterfaceConfigurableParam.cxx +/// \author David Rohr + +#include "GPUO2InterfaceConfigurableParam.h" +#include "GPUO2InterfaceConfiguration.h" +#include "GPUDataTypes.h" + +using namespace o2::gpu; +#define BeginNamespace(name) +#define EndNamespace() +#define AddOption(name, type, default, optname, optnameshort, help, ...) +#define AddVariable(name, type, default) +#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) +#define AddOptionVec(name, type, optname, optnameshort, help, ...) +#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) +#define AddSubConfig(name, instance) +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) O2ParamImpl(GPUCA_M_CAT(GPUConfigurableParam, name)) +#define EndConfig() +#define AddCustomCPP(...) +#define AddHelp(...) +#define AddShortcut(...) +#include "qconfigoptions.h" +#undef BeginNamespace +#undef EndNamespace +#undef AddOption +#undef AddVariable +#undef AddOptionSet +#undef AddOptionVec +#undef AddOptionArray +#undef AddSubConfig +#undef BeginSubConfig +#undef EndConfig +#undef AddCustomCPP +#undef AddHelp +#undef AddShortcut + +GPUSettingsO2 GPUO2InterfaceConfiguration::ReadConfigurableParam() +{ +#define BeginNamespace(name) +#define EndNamespace() +#define AddOption(name, type, default, optname, optnameshort, help, ...) dst.name = src.name; +#define AddVariable(name, type, default) +#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) +#define AddOptionVec(name, type, optname, optnameshort, help, ...) +#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) \ + for (int i = 0; i < count; i++) { \ + dst.name[i] = src.name[i]; \ + } +#define AddSubConfig(name, instance) +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ + name instance; \ + { \ + auto& src = GPUCA_M_CAT(GPUConfigurableParam, name)::Instance(); \ + name& dst = instance; +#define EndConfig() } +#define AddCustomCPP(...) +#define AddHelp(...) +#define AddShortcut(...) +#include "qconfigoptions.h" +#undef BeginNamespace +#undef EndNamespace +#undef AddOption +#undef AddVariable +#undef AddOptionSet +#undef AddOptionVec +#undef AddOptionArray +#undef AddSubConfig +#undef BeginSubConfig +#undef EndConfig +#undef AddCustomCPP +#undef AddHelp +#undef AddShortcut + + configProcessing = proc; + configReconstruction = rec; + configDisplay = GL; + configQA = QA; + if (global.continuousMaxTimeBin) { + configEvent.continuousMaxTimeBin = global.continuousMaxTimeBin; + } + if (global.solenoidBz > -1000.f) { + configEvent.solenoidBz = global.solenoidBz; + } + if (global.constBz) { + configEvent.constBz = global.constBz; + } + configDeviceBackend.deviceType = GPUDataTypes::GetDeviceType(global.deviceType.c_str()); + configDeviceBackend.forceDeviceType = global.forceDeviceType; + return global; +} diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h new file mode 100644 index 0000000000000..89d42533d641f --- /dev/null +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h @@ -0,0 +1,75 @@ +// 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 GPUO2InterfaceConfigurableParam.h +/// \author David Rohr + +// This file auto-generates a ConfigurableParam object from the GPU parameter macros. +// Set via: +// --configKeyValues "GPU_global.[x]=[y]" : for global GPU run configurations, like solenoidBz, gpuType, configuration object files. +// --configKeyValues "GPU_rec.[x]=[y]" : for GPU reconstruction related settings used on the GPU, like pt threshold for track rejection. +// --configKeyValues "GPU_proc.[x]=[y]" : for processing options steering GPU reconstruction like GPU device ID, debug output level, number of CPU threads. +// Check qconfigoptions.h for all options + +#ifndef GPUO2INTERFACECONFIGURABLEPARAM_H +#define GPUO2INTERFACECONFIGURABLEPARAM_H + +// Some defines denoting that we are compiling for O2 +#ifndef HAVE_O2HEADERS +#define HAVE_O2HEADERS +#endif +#ifndef GPUCA_TPC_GEOMETRY_O2 +#define GPUCA_TPC_GEOMETRY_O2 +#endif +#ifndef GPUCA_O2_INTERFACE +#define GPUCA_O2_INTERFACE +#endif + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" +#include "GPUSettings.h" +#include "GPUDefMacros.h" +#include <vector> + +#define BeginNamespace(name) \ + namespace name \ + { +#define EndNamespace() } +#define AddOption(name, type, default, optname, optnameshort, help, ...) type name = default; +#define AddVariable(name, type, default) +#define AddOptionSet(name, type, value, optname, optnameshort, help, ...) +#define AddOptionVec(name, type, optname, optnameshort, help, ...) +#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) type name[count] = {default}; +#define AddSubConfig(name, instance) +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ + struct GPUCA_M_CAT(GPUConfigurableParam, name) : public o2::conf::ConfigurableParamHelper<GPUCA_M_CAT(GPUConfigurableParam, name)> { \ + O2ParamDef(GPUCA_M_CAT(GPUConfigurableParam, name), GPUCA_M_STR(GPUCA_M_CAT(GPU_, instance))) public: +#define EndConfig() \ + } \ + ; +#define AddCustomCPP(...) __VA_ARGS__ +#define AddHelp(...) +#define AddShortcut(...) +#include "qconfigoptions.h" +#undef BeginNamespace +#undef EndNamespace +#undef AddOption +#undef AddVariable +#undef AddOptionSet +#undef AddOptionVec +#undef AddOptionArray +#undef AddSubConfig +#undef BeginSubConfig +#undef EndConfig +#undef AddCustomCPP +#undef AddHelp +#undef AddShortcut + +#endif diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index a1017f8ee86fb..24c1f2459b00f 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -46,6 +46,7 @@ class Digit; namespace gpu { class TPCFastTransform; +struct GPUSettingsO2; // This defines an output region. Ptr points to a memory buffer, which should have a proper alignment. // Since DPL does not respect the alignment of data types, we do not impose anything specic but just use a char data type, but it should be >= 64 bytes ideally. @@ -90,6 +91,8 @@ struct GPUO2InterfaceConfiguration { GPUInterfaceSettings configInterface; GPURecoStepConfiguration configWorkflow; GPUCalibObjects configCalib; + + GPUSettingsO2 ReadConfigurableParam(); }; // Structure with pointers to actual data for input and output diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 9a08a84f05a85..194667acb1cf8 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -95,7 +95,7 @@ static const GPUDisplay::configDisplay& GPUDisplay_GetConfig(GPUChainTracking* r } #else - return configStandalone.configGL; + return configStandalone.GL; #endif } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 434254d8f3473..f094928f3327d 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -153,7 +153,7 @@ static const GPUQA::configQA& GPUQA_GetConfig(GPUChainTracking* rec) } #else - return configStandalone.configQA; + return configStandalone.QA; #endif } @@ -1477,9 +1477,9 @@ GPUCA_OPENMP(parallel for) void GPUQA::GetName(char* fname, int k) { const int nNewInput = mConfig.inputHistogramsOnly ? 0 : 1; - if (k || mConfig.inputHistogramsOnly || mConfig.name) { + if (k || mConfig.inputHistogramsOnly || mConfig.name.size()) { if (!(mConfig.inputHistogramsOnly || k)) { - snprintf(fname, 1024, "%s - ", mConfig.name); + snprintf(fname, 1024, "%s - ", mConfig.name.c_str()); } else if (mConfig.compareInputNames.size() > (unsigned)(k - nNewInput)) { snprintf(fname, 1024, "%s - ", mConfig.compareInputNames[k - nNewInput]); } else { @@ -1522,8 +1522,8 @@ int GPUQA::DrawQAHistograms() tin[i] = new TFile(mConfig.compareInputs[i]); } TFile* tout = nullptr; - if (mConfig.output) { - tout = new TFile(mConfig.output, "RECREATE"); + if (mConfig.output.size()) { + tout = new TFile(mConfig.output.c_str(), "RECREATE"); } float legendSpacingString = 0.025; diff --git a/GPU/GPUTracking/Standalone/qa/genEvents.cxx b/GPU/GPUTracking/Standalone/qa/genEvents.cxx index 9594d79f1b4f9..914adcef3a8e8 100644 --- a/GPU/GPUTracking/Standalone/qa/genEvents.cxx +++ b/GPU/GPUTracking/Standalone/qa/genEvents.cxx @@ -157,7 +157,7 @@ int genEvents::GenerateEvent(const GPUParam& param, char* filename) gRandom->SetSeed(configStandalone.seed); } - int nTracks = configStandalone.configEG.numberOfTracks; // Number of MC tracks, must be at least as large as the largest fMCID assigned above + int nTracks = configStandalone.EG.numberOfTracks; // Number of MC tracks, must be at least as large as the largest fMCID assigned above cout << "NTracks " << nTracks << endl; std::vector<GPUTPCMCInfo> mcInfo(nTracks); memset(mcInfo.data(), 0, nTracks * sizeof(mcInfo[0])); diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index 4ea8035c646c4..e73de9f960279 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -24,7 +24,7 @@ BeginNamespace(gpu) // Settings concerning the reconstruction // There must be no bool in here, use char, as sizeof(bool) is compiler dependent and fails on GPUs!!!!!! -BeginSubConfig(GPUSettingsRec, configRec, configStandalone, "REC", 0, "Reconstruction settings") +BeginSubConfig(GPUSettingsRec, rec, configStandalone, "REC", 0, "Reconstruction settings") AddOption(tpcRejectQPt, float, 1.f / 0.05f, "", 0, "QPt threshold to reject clusters of TPC tracks (Inverse Pt!!!)") AddOption(HitPickUpFactor, float, 2., "", 0, "multiplier for the chi2 window for hit pick up procedure") AddOption(NeighboursSearchArea, float, 3., "", 0, "area in cm for the search of neighbours") @@ -65,7 +65,7 @@ AddHelp("help", 'h') EndConfig() // Settings steering the processing once the device was selected -BeginSubConfig(GPUSettingsProcessing, configProc, configStandalone, "PROC", 0, "Processing settings") +BeginSubConfig(GPUSettingsProcessing, proc, configStandalone, "PROC", 0, "Processing settings") AddOption(platformNum, int, -1, "", 0, "Platform to use, in case the backend provides multiple platforms (-1 = auto-select)") AddOption(gpuDeviceOnly, bool, false, "", 0, "Use only GPU as device (i.e. no CPU for OpenCL)") AddOption(debugMask, int, -1, "", 0, "Mask for debug output dumps to file") @@ -81,7 +81,7 @@ AddOption(fullMergerOnGPU, bool, true, "", 0, "Perform full TPC track merging on AddOption(delayedOutput, bool, true, "", 0, "Delay output to be parallel to track fit") AddOption(tpccfGatherKernel, bool, true, "", 0, "Use a kernel instead of the DMA engine to gather the clusters") AddOption(doublePipelineClusterizer, bool, true, "", 0, "Include the input data of the clusterizer in the double-pipeline") -AddOption(deviceNum, int, -1, "gpuDevice", 0, "Set GPU device to use (-1: automatic)") +AddOption(deviceNum, int, -1, "gpuDevice", 0, "Set GPU device to use (-1: automatic, -2: for round-robin usage in timeslice-pipeline)") AddOption(globalInitMutex, bool, false, "", 0, "Use global mutex to synchronize initialization of multiple GPU instances") AddOption(ompThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %d OMP threads")) AddOption(nDeviceHelperThreads, int, 1, "", 0, "Number of CPU helper threads for CPU processing") @@ -112,38 +112,17 @@ EndConfig() #ifndef GPUCA_GPUCODE_DEVICE // Settings concerning the event display -BeginSubConfig(GPUSettingsDisplay, configGL, configStandalone, "GL", 'g', "OpenGL display settings") +BeginSubConfig(GPUSettingsDisplay, GL, configStandalone, "GL", 'g', "OpenGL display settings") AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") AddHelp("help", 'h') EndConfig() -// Settings concerning the standlone timeframe from run 2 events assembly tool -BeginSubConfig(GPUSettingsTF, configTF, configStandalone, "TF", 't', "Timeframe settings") -AddOption(nMerge, int, 0, "", 0, "Merge n events in a timeframe", min(0)) -AddOption(averageDistance, float, 50., "", 0, "Average distance in cm of events merged into timeframe", min(0.f)) -AddOption(randomizeDistance, bool, true, "", 0, "Randomize distance around average distance of merged events") -AddOption(shiftFirstEvent, bool, true, "", 0, "Also shift the first event in z when merging events to a timeframe") -AddOption(bunchSim, int, 0, "", 0, "Simulate correct bunch interactions instead of placing only the average number of events. A value [n] > 1 sets TFlen for [n] collisions in average. (Incompatible to TFmerge)") -AddOption(bunchCount, int, 12, "", 0, "Number of bunches per trainsort") -AddOption(bunchSpacing, int, 50, "", 0, "Spacing between benches in ns") -AddOption(bunchTrainCount, int, 48, "", 0, "Number of bunch trains") -AddOption(abortGapTime, int, (3000), "", 0, "Length of abort gap in ns") -AddOption(interactionRate, int, 50000, "", 0, "Instantaneous interaction rate") -AddOption(timeFrameLen, long, (1000000000 / 44), "", 'l', "Timeframe len in ns") -AddOption(noBorder, bool, false, "", 0, "Do not simulate border effects (partial events)") -AddOption(noEventRepeat, int, 0, "", 0, "0: Place random events, 1: Place events in timeframe one after another, 2: Place random events but do not repat", def(1)) -AddOption(nTotalEventsInTF, int, 0, "", 0, "Total number of collisions to be placed in the interior of all time frames (excluding borders)") -AddOption(eventStride, int, 0, "", 0, "Do not select random event, but walk over array of events in stride steps") -AddOption(overlayRaw, bool, false, "", 0, "Overlay raw TPC data instead of spatial clusters") -AddHelp("help", 'h') -EndConfig() - // Settings concerning the standalone QA -BeginSubConfig(GPUSettingsQA, configQA, configStandalone, "QA", 'q', "QA settings") +BeginSubConfig(GPUSettingsQA, QA, configStandalone, "QA", 'q', "QA settings") AddOptionVec(compareInputs, const char*, "QAinput", 0, "Read histogram from these input files and include them in the output plots") AddOptionVec(compareInputNames, const char*, "QAinputName", 0, "Legend entries for data from comparison histogram files") -AddOption(name, const char*, nullptr, "", 0, "Legend entry for new data from current processing") -AddOption(output, const char*, nullptr, "", 0, "Store histograms in output root file", def("histograms.root")) +AddOption(name, std::string, "", "", 0, "Legend entry for new data from current processing") +AddOption(output, std::string, "", "", 0, "Store histograms in output root file", def(std::string("histograms.root"))) AddOption(inputHistogramsOnly, bool, false, "", 0, "Do not run tracking, but just create PDFs from input root files") AddOption(strict, bool, true, "", 0, "Strict QA mode: Only consider resolution of tracks where the fit ended within 5 cm of the reference, and remove outliers.") AddOption(qpt, float, 10.f, "", 0, "Set cut for Q/Pt", def(2.f)) @@ -163,15 +142,36 @@ AddHelp("help", 'h') EndConfig() #ifdef GPUCA_STANDALONE +// Settings concerning the standlone timeframe from run 2 events assembly tool +BeginSubConfig(GPUSettingsTF, TF, configStandalone, "TF", 't', "Timeframe settings") +AddOption(nMerge, int, 0, "", 0, "Merge n events in a timeframe", min(0)) +AddOption(averageDistance, float, 50., "", 0, "Average distance in cm of events merged into timeframe", min(0.f)) +AddOption(randomizeDistance, bool, true, "", 0, "Randomize distance around average distance of merged events") +AddOption(shiftFirstEvent, bool, true, "", 0, "Also shift the first event in z when merging events to a timeframe") +AddOption(bunchSim, int, 0, "", 0, "Simulate correct bunch interactions instead of placing only the average number of events. A value [n] > 1 sets TFlen for [n] collisions in average. (Incompatible to TFmerge)") +AddOption(bunchCount, int, 12, "", 0, "Number of bunches per trainsort") +AddOption(bunchSpacing, int, 50, "", 0, "Spacing between benches in ns") +AddOption(bunchTrainCount, int, 48, "", 0, "Number of bunch trains") +AddOption(abortGapTime, int, (3000), "", 0, "Length of abort gap in ns") +AddOption(interactionRate, int, 50000, "", 0, "Instantaneous interaction rate") +AddOption(timeFrameLen, long, (1000000000 / 44), "", 'l', "Timeframe len in ns") +AddOption(noBorder, bool, false, "", 0, "Do not simulate border effects (partial events)") +AddOption(noEventRepeat, int, 0, "", 0, "0: Place random events, 1: Place events in timeframe one after another, 2: Place random events but do not repat", def(1)) +AddOption(nTotalEventsInTF, int, 0, "", 0, "Total number of collisions to be placed in the interior of all time frames (excluding borders)") +AddOption(eventStride, int, 0, "", 0, "Do not select random event, but walk over array of events in stride steps") +AddOption(overlayRaw, bool, false, "", 0, "Overlay raw TPC data instead of spatial clusters") +AddHelp("help", 'h') +EndConfig() + // Settings concerning standalone toy event generator -BeginSubConfig(GPUSettingsEG, configEG, configStandalone, "EG", 0, "Event generator settings") +BeginSubConfig(GPUSettingsEG, EG, configStandalone, "EG", 0, "Event generator settings") AddOption(numberOfTracks, int, 1, "", 0, "Number of tracks per generated event") AddHelp("help", 'h') EndConfig() // Settings for the standalone benchmark BeginConfig(GPUSettingsStandalone, configStandalone) -#if defined(CUDA_ENABLED) || defined(OPENCL1_ENABLED) || defined(HIP_ENABLED) +#if defined(CUDA_ENABLED) || defined(OPENCL1_ENABLED) || defined(OPENCL2_ENABLED) || defined(HIP_ENABLED) AddOption(runGPU, bool, true, "", 'g', "Use GPU for processing", message("GPU processing: %s")) #else AddOption(runGPU, bool, false, "", 'g', "Use GPU for processing", message("GPU processing: %s")) @@ -201,7 +201,7 @@ AddOption(runsInit, int, 1, "", 0, "Number of initial iterations excluded from a AddOption(EventsDir, const char*, "pp", "events", 'e', "Directory with events to process", message("Reading events from Directory events/%s")) AddOption(eventDisplay, int, 0, "display", 'd', "Show standalone event display", def(1)) //1: default display (Windows / X11), 2: glut, 3: glfw AddOption(eventGenerator, bool, false, "", 0, "Run event generator") -AddOption(nwaysouter, bool, false, "", 0, "Create OuterParam") +AddOption(nways7, bool, false, "", 0, "Create OuterParam") AddOption(cont, bool, false, "", 0, "Process continuous timeframe data") AddOption(outputcontrolmem, unsigned long, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ul), message("Using %lld bytes as output memory")) AddOption(inputcontrolmem, unsigned long, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ul), message("Using %lld bytes as input memory")) @@ -233,20 +233,26 @@ AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") AddHelp("help", 'h') AddHelpAll("helpall", 'H') -AddSubConfig(GPUSettingsTF, configTF) -AddSubConfig(GPUSettingsQA, configQA) -AddSubConfig(GPUSettingsEG, configEG) -AddSubConfig(GPUSettingsDisplay, configGL) -AddSubConfig(GPUSettingsRec, configRec) -AddSubConfig(GPUSettingsProcessing, configProc) +AddSubConfig(GPUSettingsTF, TF) +AddSubConfig(GPUSettingsQA, QA) +AddSubConfig(GPUSettingsEG, EG) +AddSubConfig(GPUSettingsDisplay, GL) +AddSubConfig(GPUSettingsRec, rec) +AddSubConfig(GPUSettingsProcessing, proc) EndConfig() -#elif defined(GPUCA_O2_LIB) // GPUCA_STANDALONE -BeginSubConfig(GPUSettingsO2, configGPUO2, configStandalone, "O2", 0, "O2 workflow settings") -AddOption(solenoidBz, float, -5.00668, "", 0, "solenoid field strength") +#elif defined(GPUCA_O2_LIB) || defined(GPUCA_O2_INTERFACE) // GPUCA_STANDALONE +BeginSubConfig(GPUSettingsO2, global, configStandalone, "O2", 0, "O2 workflow settings") +AddOption(solenoidBz, float, -1000.f, "", 0, "solenoid field strength") AddOption(constBz, bool, false, "", 0, "force constant Bz for tests") AddOption(continuousMaxTimeBin, int, 0, "", 0, "maximum time bin of continuous data, 0 for triggered events, -1 for default of 23ms") -AddOption(deviceType, const char*, "CPU", "", 0, "Device type, CPU | CUDA | HIP | OCL1 | OCL2") +AddOption(deviceType, std::string, "CPU", "", 0, "Device type, CPU | CUDA | HIP | OCL1 | OCL2") AddOption(forceDeviceType, bool, true, "", 0, "force device type, otherwise allows fall-back to CPU") +AddOption(dump, int, 0, "", 0, "Dump events for standalone benchmark: 1 = dump events, 2 = dump events and skip processing in workflow") +AddOption(runDisplay, bool, false, "", 0, "Run event visualization after processing") +AddOption(dEdxFile, std::string, "", "", 0, "File name of dEdx Splines file") +AddOption(transformationFile, std::string, "", "", 0, "File name of TPC fast transformation map") +AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") +AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") EndConfig() #endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 69a223ba800ee..20a93aa288b52 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -121,8 +121,8 @@ int ReadConfiguration(int argc, char** argv) if (configStandalone.printSettings) { qConfigPrint(); } - if (configStandalone.configProc.debugLevel < 0) { - configStandalone.configProc.debugLevel = 0; + if (configStandalone.proc.debugLevel < 0) { + configStandalone.proc.debugLevel = 0; } #ifndef _WIN32 setlocale(LC_ALL, ""); @@ -170,19 +170,19 @@ int ReadConfiguration(int argc, char** argv) } #endif #ifndef HAVE_O2HEADERS - configStandalone.configRec.runTRD = configStandalone.rundEdx = configStandalone.configRec.runCompression = configStandalone.runTransformation = configStandalone.testSyncAsync = configStandalone.testSync = 0; - configStandalone.configRec.ForceEarlyTPCTransform = 1; + configStandalone.runTRD = configStandalone.rundEdx = configStandalone.runCompression = configStandalone.runTransformation = configStandalone.testSyncAsync = configStandalone.testSync = 0; + configStandalone.rec.ForceEarlyTPCTransform = 1; #endif #ifndef GPUCA_TPC_GEOMETRY_O2 - configStandalone.configRec.mergerReadFromTrackerDirectly = 0; + configStandalone.rec.mergerReadFromTrackerDirectly = 0; #endif #ifndef GPUCA_BUILD_QA - if (configStandalone.configProc.runQA || configStandalone.eventGenerator) { + if (configStandalone.proc.runQA || configStandalone.eventGenerator) { printf("QA not enabled in build\n"); return 1; } #endif - if (configStandalone.configProc.runQA) { + if (configStandalone.proc.runQA) { if (getenv("LC_NUMERIC")) { printf("Please unset the LC_NUMERIC env variable, otherwise ROOT will not be able to fit correctly\n"); // BUG: ROOT Problem return 1; @@ -194,57 +194,57 @@ int ReadConfiguration(int argc, char** argv) return 1; } #endif - if (configStandalone.configProc.doublePipeline && configStandalone.testSyncAsync) { + if (configStandalone.proc.doublePipeline && configStandalone.testSyncAsync) { printf("Cannot run asynchronous processing with double pipeline\n"); return 1; } - if (configStandalone.configProc.doublePipeline && (configStandalone.runs < 4 || !configStandalone.outputcontrolmem)) { + if (configStandalone.proc.doublePipeline && (configStandalone.runs < 4 || !configStandalone.outputcontrolmem)) { printf("Double pipeline mode needs at least 3 runs per event and external output\n"); return 1; } - if (configStandalone.configTF.bunchSim && configStandalone.configTF.nMerge) { + if (configStandalone.TF.bunchSim && configStandalone.TF.nMerge) { printf("Cannot run --MERGE and --SIMBUNCHES togeterh\n"); return 1; } - if (configStandalone.configTF.bunchSim > 1) { - configStandalone.configTF.timeFrameLen = 1.e9 * configStandalone.configTF.bunchSim / configStandalone.configTF.interactionRate; + if (configStandalone.TF.bunchSim > 1) { + configStandalone.TF.timeFrameLen = 1.e9 * configStandalone.TF.bunchSim / configStandalone.TF.interactionRate; } - if (configStandalone.configTF.nMerge) { - double len = configStandalone.configTF.nMerge - 1; - if (configStandalone.configTF.randomizeDistance) { + if (configStandalone.TF.nMerge) { + double len = configStandalone.TF.nMerge - 1; + if (configStandalone.TF.randomizeDistance) { len += 0.5; } - if (configStandalone.configTF.shiftFirstEvent) { + if (configStandalone.TF.shiftFirstEvent) { len += 0.5; } - configStandalone.configTF.timeFrameLen = (len * configStandalone.configTF.averageDistance / GPUReconstructionTimeframe::TPCZ + 1) * GPUReconstructionTimeframe::DRIFT_TIME; + configStandalone.TF.timeFrameLen = (len * configStandalone.TF.averageDistance / GPUReconstructionTimeframe::TPCZ + 1) * GPUReconstructionTimeframe::DRIFT_TIME; } - if (configStandalone.configQA.inputHistogramsOnly && configStandalone.configQA.compareInputs.size() == 0) { + if (configStandalone.QA.inputHistogramsOnly && configStandalone.QA.compareInputs.size() == 0) { printf("Can only produce QA pdf output when input files are specified!\n"); return 1; } - if (configStandalone.configQA.inputHistogramsOnly) { + if (configStandalone.QA.inputHistogramsOnly) { configStandalone.rundEdx = false; } if (configStandalone.eventDisplay) { configStandalone.noprompt = 1; } - if (configStandalone.configProc.debugLevel >= 4 && !configStandalone.configProc.ompKernels) { - configStandalone.configProc.ompThreads = 1; + if (configStandalone.proc.debugLevel >= 4 && !configStandalone.proc.ompKernels) { + configStandalone.proc.ompThreads = 1; } #ifdef WITH_OPENMP - if (configStandalone.configProc.ompThreads != -1) { - omp_set_num_threads(configStandalone.configProc.ompThreads); + if (configStandalone.proc.ompThreads != -1) { + omp_set_num_threads(configStandalone.proc.ompThreads); } else { - configStandalone.configProc.ompThreads = omp_get_max_threads(); + configStandalone.proc.ompThreads = omp_get_max_threads(); } - if (configStandalone.configProc.ompThreads != omp_get_max_threads()) { + if (configStandalone.proc.ompThreads != omp_get_max_threads()) { printf("Cannot set number of OMP threads!\n"); return 1; } #else - configStandalone.configProc.ompThreads = 1; + configStandalone.proc.ompThreads = 1; #endif if (configStandalone.outputcontrolmem) { bool forceEmptyMemory = getenv("LD_PRELOAD") && strstr(getenv("LD_PRELOAD"), "valgrind") != nullptr; @@ -253,7 +253,7 @@ int ReadConfiguration(int argc, char** argv) printf("Valgrind detected, emptying GPU output memory to avoid false positive undefined reads"); memset(outputmemory.get(), 0, configStandalone.outputcontrolmem); } - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { outputmemoryPipeline.reset(new char[configStandalone.outputcontrolmem]); if (forceEmptyMemory) { memset(outputmemoryPipeline.get(), 0, configStandalone.outputcontrolmem); @@ -288,7 +288,7 @@ int SetupReconstruction() if (configStandalone.testSyncAsync) { recAsync->ReadSettings(filename); } - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { recPipeline->ReadSettings(filename); } } @@ -296,8 +296,8 @@ int SetupReconstruction() GPUSettingsEvent ev = rec->GetEventSettings(); GPUSettingsRec recSet; GPUSettingsProcessing devProc; - memcpy((void*)&recSet, (void*)&configStandalone.configRec, sizeof(GPUSettingsRec)); - memcpy((void*)&devProc, (void*)&configStandalone.configProc, sizeof(GPUSettingsProcessing)); + memcpy((void*)&recSet, (void*)&configStandalone.rec, sizeof(GPUSettingsRec)); + memcpy((void*)&devProc, (void*)&configStandalone.proc, sizeof(GPUSettingsProcessing)); GPURecoStepConfiguration steps; if (configStandalone.eventGenerator) { @@ -309,7 +309,7 @@ int SetupReconstruction() if (configStandalone.constBz) { ev.constBz = true; } - if (configStandalone.configTF.nMerge || configStandalone.configTF.bunchSim) { + if (configStandalone.TF.nMerge || configStandalone.TF.bunchSim) { if (ev.continuousMaxTimeBin) { printf("ERROR: requested to overlay continuous data - not supported\n"); return 1; @@ -319,7 +319,7 @@ int SetupReconstruction() configStandalone.cont = true; } if (chainTracking->GetTPCTransform()) { - ev.continuousMaxTimeBin = configStandalone.configTF.timeFrameLen * ((double)GPUReconstructionTimeframe::TPCZ / (double)GPUReconstructionTimeframe::DRIFT_TIME) / chainTracking->GetTPCTransform()->getVDrift(); + ev.continuousMaxTimeBin = configStandalone.TF.timeFrameLen * ((double)GPUReconstructionTimeframe::TPCZ / (double)GPUReconstructionTimeframe::DRIFT_TIME) / chainTracking->GetTPCTransform()->getVDrift(); } } if (configStandalone.cont && ev.continuousMaxTimeBin == 0) { @@ -331,7 +331,7 @@ int SetupReconstruction() printf("Standalone Test Framework for CA Tracker - Using GPU\n"); } - configStandalone.configProc.forceMemoryPoolSize = (configStandalone.configProc.forceMemoryPoolSize == 1 && configStandalone.eventDisplay) ? 2 : configStandalone.configProc.forceMemoryPoolSize; + configStandalone.proc.forceMemoryPoolSize = (configStandalone.proc.forceMemoryPoolSize == 1 && configStandalone.eventDisplay) ? 2 : configStandalone.proc.forceMemoryPoolSize; if (configStandalone.eventDisplay) { #ifdef GPUCA_BUILD_EVENT_DISPLAY #ifdef _WIN32 @@ -381,7 +381,7 @@ int SetupReconstruction() steps.steps.setBits(GPUDataTypes::RecoStep::TPCdEdx, false); steps.steps.setBits(GPUDataTypes::RecoStep::TPCCompression, false); } - if (configStandalone.configTF.bunchSim || configStandalone.configTF.nMerge) { + if (configStandalone.TF.bunchSim || configStandalone.TF.nMerge) { steps.steps.setBits(GPUDataTypes::RecoStep::TRDTracking, false); } steps.inputs.set(GPUDataTypes::InOutType::TPCClusters, GPUDataTypes::InOutType::TRDTracklets); @@ -417,7 +417,7 @@ int SetupReconstruction() } } rec->SetSettings(&ev, &recSet, &devProc, &steps); - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { recPipeline->SetSettings(&ev, &recSet, &devProc, &steps); } if (configStandalone.testSyncAsync) { @@ -443,7 +443,7 @@ int SetupReconstruction() if (configStandalone.outputcontrolmem) { rec->SetOutputControl(outputmemory.get(), configStandalone.outputcontrolmem); - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { recPipeline->SetOutputControl(outputmemoryPipeline.get(), configStandalone.outputcontrolmem); } } @@ -453,7 +453,7 @@ int SetupReconstruction() return 1; } if (configStandalone.outputcontrolmem && rec->IsGPU()) { - if (rec->registerMemoryForGPU(outputmemory.get(), configStandalone.outputcontrolmem) || (configStandalone.configProc.doublePipeline && recPipeline->registerMemoryForGPU(outputmemoryPipeline.get(), configStandalone.outputcontrolmem))) { + if (rec->registerMemoryForGPU(outputmemory.get(), configStandalone.outputcontrolmem) || (configStandalone.proc.doublePipeline && recPipeline->registerMemoryForGPU(outputmemoryPipeline.get(), configStandalone.outputcontrolmem))) { printf("ERROR registering memory for the GPU!!!\n"); return 1; } @@ -464,7 +464,7 @@ int SetupReconstruction() return 1; } } - if (configStandalone.configProc.debugLevel >= 4) { + if (configStandalone.proc.debugLevel >= 4) { rec->PrintKernelOccupancies(); } return (0); @@ -481,8 +481,8 @@ int ReadEvent(int n) if (r) { return r; } - if (chainTracking->mIOPtrs.clustersNative && (configStandalone.configTF.bunchSim || configStandalone.configTF.nMerge || !configStandalone.runTransformation)) { - if (configStandalone.configProc.debugLevel >= 2) { + if (chainTracking->mIOPtrs.clustersNative && (configStandalone.TF.bunchSim || configStandalone.TF.nMerge || !configStandalone.runTransformation)) { + if (configStandalone.proc.debugLevel >= 2) { printf("Converting Native to Legacy ClusterData for overlaying - WARNING: No raw clusters produced - Compression etc will not run!!!\n"); } chainTracking->ConvertNativeToClusterDataLegacy(); @@ -492,11 +492,11 @@ int ReadEvent(int n) int LoadEvent(int iEvent, int x) { - if (configStandalone.configTF.bunchSim) { + if (configStandalone.TF.bunchSim) { if (tf->LoadCreateTimeFrame(iEvent)) { return 1; } - } else if (configStandalone.configTF.nMerge) { + } else if (configStandalone.TF.nMerge) { if (tf->LoadMergedEvents(iEvent)) { return 1; } @@ -524,7 +524,7 @@ int LoadEvent(int iEvent, int x) } else { for (int i = 0; i < chainTracking->NSLICES; i++) { if (chainTracking->mIOPtrs.rawClusters[i]) { - if (configStandalone.configProc.debugLevel >= 2) { + if (configStandalone.proc.debugLevel >= 2) { printf("Converting Legacy Raw Cluster to Native\n"); } chainTracking->ConvertRun2RawToNative(); @@ -559,7 +559,7 @@ void OutputStat(GPUChainTracking* t, long long int* nTracksTotal = nullptr, long nAttachedClustersFitted += t->mIOPtrs.mergedTracks[k].NClustersFitted(); } } - unsigned int nCls = configStandalone.configProc.doublePipeline ? t->mIOPtrs.clustersNative->nClustersTotal : t->GetTPCMerger().NMaxClusters(); + unsigned int nCls = configStandalone.proc.doublePipeline ? t->mIOPtrs.clustersNative->nClustersTotal : t->GetTPCMerger().NMaxClusters(); for (unsigned int k = 0; k < nCls; k++) { int attach = t->mIOPtrs.mergedTrackHitAttachment[k]; if (attach & GPUTPCGMMergerTypes::attachFlagMask) { @@ -599,10 +599,10 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, if (configStandalone.testSyncAsync) { printf("Running synchronous phase\n"); } - const GPUTrackingInOutPointers& ioPtrs = ioPtrEvents[!configStandalone.preloadEvents ? 0 : configStandalone.configProc.doublePipeline ? (iteration % ioPtrEvents.size()) : (iEvent - configStandalone.StartEvent)]; + const GPUTrackingInOutPointers& ioPtrs = ioPtrEvents[!configStandalone.preloadEvents ? 0 : configStandalone.proc.doublePipeline ? (iteration % ioPtrEvents.size()) : (iEvent - configStandalone.StartEvent)]; chainTrackingUse->mIOPtrs = ioPtrs; - if (iteration == (configStandalone.configProc.doublePipeline ? 2 : (configStandalone.runs - 1))) { - if (configStandalone.configProc.doublePipeline) { + if (iteration == (configStandalone.proc.doublePipeline ? 2 : (configStandalone.runs - 1))) { + if (configStandalone.proc.doublePipeline) { timerPipeline->Start(); } if (configStandalone.controlProfiler) { @@ -612,7 +612,7 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, int tmpRetVal = recUse->RunChains(); int iterationEnd = nIterationEnd.fetch_add(1); if (iterationEnd == configStandalone.runs - 1) { - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { timerPipeline->Stop(); } if (configStandalone.controlProfiler) { @@ -624,7 +624,7 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, OutputStat(chainTrackingUse, iRun == 0 ? nTracksTotal : nullptr, iRun == 0 ? nClustersTotal : nullptr); if (configStandalone.memoryStat) { recUse->PrintMemoryStatistics(); - } else if (configStandalone.configProc.debugLevel >= 2) { + } else if (configStandalone.proc.debugLevel >= 2) { recUse->PrintMemoryOverview(); } } @@ -664,7 +664,7 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, recAsync->ClearAllocatedMemory(); } #endif - if (!configStandalone.configProc.doublePipeline) { + if (!configStandalone.proc.doublePipeline) { recUse->ClearAllocatedMemory(); } @@ -680,7 +680,7 @@ int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, } iRun++; } - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { recUse->ClearAllocatedMemory(); } nIteration.store(runs); @@ -703,7 +703,7 @@ int main(int argc, char** argv) recUniqueAsync.reset(GPUReconstruction::CreateInstance(configStandalone.runGPU ? configStandalone.gpuType : GPUReconstruction::DEVICE_TYPE_NAMES[GPUReconstruction::DeviceType::CPU], configStandalone.runGPUforce, rec)); recAsync = recUniqueAsync.get(); } - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { recUniquePipeline.reset(GPUReconstruction::CreateInstance(configStandalone.runGPU ? configStandalone.gpuType : GPUReconstruction::DEVICE_TYPE_NAMES[GPUReconstruction::DeviceType::CPU], configStandalone.runGPUforce, rec)); recPipeline = recUniquePipeline.get(); } @@ -711,22 +711,22 @@ int main(int argc, char** argv) printf("Error initializing GPUReconstruction\n"); return 1; } - rec->SetDebugLevelTmp(configStandalone.configProc.debugLevel); + rec->SetDebugLevelTmp(configStandalone.proc.debugLevel); chainTracking = rec->AddChain<GPUChainTracking>(); if (configStandalone.testSyncAsync) { - if (configStandalone.configProc.debugLevel >= 3) { - recAsync->SetDebugLevelTmp(configStandalone.configProc.debugLevel); + if (configStandalone.proc.debugLevel >= 3) { + recAsync->SetDebugLevelTmp(configStandalone.proc.debugLevel); } chainTrackingAsync = recAsync->AddChain<GPUChainTracking>(); } - if (configStandalone.configProc.doublePipeline) { - if (configStandalone.configProc.debugLevel >= 3) { - recPipeline->SetDebugLevelTmp(configStandalone.configProc.debugLevel); + if (configStandalone.proc.doublePipeline) { + if (configStandalone.proc.debugLevel >= 3) { + recPipeline->SetDebugLevelTmp(configStandalone.proc.debugLevel); } chainTrackingPipeline = recPipeline->AddChain<GPUChainTracking>(); } #ifdef HAVE_O2HEADERS - if (!configStandalone.configProc.doublePipeline) { + if (!configStandalone.proc.doublePipeline) { chainITS = rec->AddChain<GPUChainITS>(0); if (configStandalone.testSyncAsync) { chainITSAsync = recAsync->AddChain<GPUChainITS>(0); @@ -739,7 +739,7 @@ int main(int argc, char** argv) } std::unique_ptr<std::thread> pipelineThread; - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { pipelineThread.reset(new std::thread([]() { rec->RunPipelineWorker(); })); } @@ -764,7 +764,7 @@ int main(int argc, char** argv) in.close(); } - if (configStandalone.configTF.bunchSim || configStandalone.configTF.nMerge) { + if (configStandalone.TF.bunchSim || configStandalone.TF.nMerge) { tf.reset(new GPUReconstructionTimeframe(chainTracking, ReadEvent, nEventsInDirectory)); } @@ -774,7 +774,7 @@ int main(int argc, char** argv) } int nEvents = configStandalone.NEvents; - if (configStandalone.configTF.bunchSim) { + if (configStandalone.TF.bunchSim) { nEvents = configStandalone.NEvents > 0 ? configStandalone.NEvents : 1; } else { if (nEvents == -1 || nEvents > nEventsInDirectory) { @@ -783,8 +783,8 @@ int main(int argc, char** argv) } nEvents = nEventsInDirectory; } - if (configStandalone.configTF.nMerge > 1) { - nEvents /= configStandalone.configTF.nMerge; + if (configStandalone.TF.nMerge > 1) { + nEvents /= configStandalone.TF.nMerge; } } @@ -802,7 +802,7 @@ int main(int argc, char** argv) } for (int iRunOuter = 0; iRunOuter < configStandalone.runs2; iRunOuter++) { - if (configStandalone.configQA.inputHistogramsOnly) { + if (configStandalone.QA.inputHistogramsOnly) { chainTracking->ForceInitQA(); break; } @@ -855,7 +855,7 @@ int main(int argc, char** argv) nIteration.store(0); nIterationEnd.store(0); double pipelineWalltime = 1.; - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { HighResTimer timerPipeline; if (RunBenchmark(rec, chainTracking, 1, iEvent, &nTracksTotal, &nClustersTotal) || RunBenchmark(recPipeline, chainTrackingPipeline, 2, iEvent, &nTracksTotal, &nClustersTotal)) { goto breakrun; @@ -878,19 +878,19 @@ int main(int argc, char** argv) double nClusters = chainTracking->GetTPCMerger().NMaxClusters(); if (nClusters > 0) { double nClsPerTF = 550000. * 1138.3; - double timePerTF = (configStandalone.configProc.doublePipeline ? pipelineWalltime : ((configStandalone.configProc.debugLevel ? rec->GetStatKernelTime() : rec->GetStatWallTime()) / 1000000.)) * nClsPerTF / nClusters; + double timePerTF = (configStandalone.proc.doublePipeline ? pipelineWalltime : ((configStandalone.proc.debugLevel ? rec->GetStatKernelTime() : rec->GetStatWallTime()) / 1000000.)) * nClsPerTF / nClusters; double nGPUsReq = timePerTF / 0.02277; char stat[1024]; snprintf(stat, 1024, "Sync phase: %.2f sec per 256 orbit TF, %.1f GPUs required", timePerTF, nGPUsReq); if (configStandalone.testSyncAsync) { - timePerTF = (configStandalone.configProc.debugLevel ? recAsync->GetStatKernelTime() : recAsync->GetStatWallTime()) / 1000000. * nClsPerTF / nClusters; + timePerTF = (configStandalone.proc.debugLevel ? recAsync->GetStatKernelTime() : recAsync->GetStatWallTime()) / 1000000. * nClsPerTF / nClusters; snprintf(stat + strlen(stat), 1024 - strlen(stat), " - Async phase: %f sec per TF", timePerTF); } - printf("%s (Measured %s time - Extrapolated from %d clusters to %d)\n", stat, configStandalone.configProc.debugLevel ? "kernel" : "wall", (int)nClusters, (int)nClsPerTF); + printf("%s (Measured %s time - Extrapolated from %d clusters to %d)\n", stat, configStandalone.proc.debugLevel ? "kernel" : "wall", (int)nClusters, (int)nClsPerTF); } } - if (configStandalone.preloadEvents && configStandalone.configProc.doublePipeline) { + if (configStandalone.preloadEvents && configStandalone.proc.doublePipeline) { break; } } @@ -905,19 +905,19 @@ int main(int argc, char** argv) } #ifndef _WIN32 - if (configStandalone.configProc.runQA && configStandalone.fpe) { + if (configStandalone.proc.runQA && configStandalone.fpe) { fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); } #endif - if (configStandalone.configProc.doublePipeline) { + if (configStandalone.proc.doublePipeline) { rec->TerminatePipelineWorker(); pipelineThread->join(); } rec->Finalize(); if (configStandalone.outputcontrolmem && rec->IsGPU()) { - if (rec->unregisterMemoryForGPU(outputmemory.get()) || (configStandalone.configProc.doublePipeline && recPipeline->unregisterMemoryForGPU(outputmemoryPipeline.get()))) { + if (rec->unregisterMemoryForGPU(outputmemory.get()) || (configStandalone.proc.doublePipeline && recPipeline->unregisterMemoryForGPU(outputmemoryPipeline.get()))) { printf("Error unregistering memory\n"); } } diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index 71f2c07f4e8ef..ffa94f45bd53c 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -20,6 +20,7 @@ #include <iostream> #include <tuple> #include <vector> +#include <string> #include "qconfig.h" // Create config instances @@ -417,6 +418,15 @@ inline int qAddOptionType<const char*>(qConfigSettings<const char*>& settings, c }, settings.doDefault); } +template <> +inline int qAddOptionType<std::string>(qConfigSettings<std::string>& settings, std::string& ref, int& i, const char** argv, const int argc, std::string /*def*/) +{ + return qAddOptionGeneric<std::string>( + settings, ref, i, argv, argc, settings.set, [](const char* a) -> std::string { + return a; + }, + settings.doDefault); +} // Checks and messages for additional settings template <typename T> diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index 2dbca296a43a6..688ea042eae4e 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -254,6 +254,7 @@ enum qConfigRetVal { qcrOK = 0, #endif #endif +#ifndef QCONFIG_HEADER_GUARD_NO_INCLUDE #ifndef AddHelp #define AddHelp(cmd, cmdshort) #endif @@ -282,7 +283,6 @@ enum qConfigRetVal { qcrOK = 0, #define AddCustomCPP(...) #endif -#ifndef QCONFIG_HEADER_GUARD_NO_INCLUDE #include "qconfigoptions.h" #undef AddOption From b9dafa09b76c3468985c2b6fda6b214b9c0df2e3 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 19 Jul 2020 14:47:40 +0200 Subject: [PATCH 0155/1751] GPU: Give file with list of GPU settings a more reasonable name --- GPU/GPUTracking/Base/GPUSettings.h | 1 + GPU/GPUTracking/Base/GPUSettingsList.h | 269 ++++++++++++++++++ GPU/GPUTracking/CMakeLists.txt | 6 +- .../GPUO2InterfaceConfigurableParam.cxx | 4 +- .../GPUO2InterfaceConfigurableParam.h | 4 +- GPU/GPUTracking/Standalone/qconfigoptions.h | 250 +--------------- 6 files changed, 277 insertions(+), 257 deletions(-) create mode 100644 GPU/GPUTracking/Base/GPUSettingsList.h diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index 6bb8b9b95e94e..b7fa6225ba4c2 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -73,6 +73,7 @@ struct GPUSettingsDeviceBackend { #ifdef GPUCA_GPUCODE_DEVICE #define QCONFIG_GPU #endif +// See GPUSettingsList.h for a list of all available settings of GPU Reconstruction #include "utils/qconfig.h" #endif diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h new file mode 100644 index 0000000000000..f26f60297f1f6 --- /dev/null +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -0,0 +1,269 @@ +// 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 GPUSettingsList.h +/// \author David Rohr + +// This file contains macros to generate all settings for the GPU Reconstruction. +// Macros are used in the following places: +// Create ConfigurableParam object for workflow. +// Configure standalone benchmark. +// Create plain-C struct for GPU code. +// Create static constexpr with default values for GPU run time compilation + +#include "GPUDefConstantsAndSettings.h" +#include "GPUSettings.h" + +// clang-format off + +#ifdef QCONFIG_INSTANCE +using namespace GPUCA_NAMESPACE::gpu; +#endif +BeginNamespace(GPUCA_NAMESPACE) +BeginNamespace(gpu) + +// Settings concerning the reconstruction +// There must be no bool in here, use char, as sizeof(bool) is compiler dependent and fails on GPUs!!!!!! +BeginSubConfig(GPUSettingsRec, rec, configStandalone, "REC", 0, "Reconstruction settings") +AddOption(tpcRejectQPt, float, 1.f / 0.05f, "", 0, "QPt threshold to reject clusters of TPC tracks (Inverse Pt!!!)") +AddOption(HitPickUpFactor, float, 2., "", 0, "multiplier for the chi2 window for hit pick up procedure") +AddOption(NeighboursSearchArea, float, 3., "", 0, "area in cm for the search of neighbours") +AddOption(ClusterError2CorrectionY, float, 1., "", 0, "correction for the squared cluster error during tracking") +AddOption(ClusterError2CorrectionZ, float, 1., "", 0, "correction for the squared cluster error during tracking") +AddOption(MinNTrackClusters, int, -1, "", 0, "required min number of clusters on the track") +AddOption(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required max Q/Pt (==min Pt) of tracks") +AddOption(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") +AddOption(TrackReferenceX, float, 1000, "", 0, "Transport all tracks to this X after tracking (disabled if > 500)") +AddOption(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") +AddOption(NWays, char, 3, "", 0, "Do N fit passes in final fit of merger") +AddOption(NWaysOuter, char, 0, "", 0, "Store outer param") +AddOption(RejectMode, char, 5, "", 0, "0: no limit on rejection or missed hits, >0: break after n rejected hits, <0: reject at max -n hits") +AddOption(NonConsecutiveIDs, char, false, "", 0, "Non-consecutive cluster IDs as in HLT, disables features that need access to slice data in TPC merger") +AddOption(dEdxTruncLow, unsigned char, 2, "", 0, "Low truncation threshold, fraction of 128") +AddOption(dEdxTruncHigh, unsigned char, 77, "", 0, "High truncation threshold, fraction of 128") +AddOption(GlobalTracking, char, 1, "", 0, "Enable Global Tracking (prolong tracks to adjacent sectors to find short segments)") +AddOption(DisableRefitAttachment, unsigned char, 0, "", 0, "Bitmask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") +AddOption(tpcRejectionMode, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression (0 = no, 1 = strategy A, 2 = strategy B)") +AddOption(tpcCompressionModes, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") +AddOption(tpcCompressionSortOrder, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") +AddOption(tpcSigBitsCharge, unsigned char, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") +AddOption(tpcSigBitsWidth, unsigned char, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") +AddOption(ForceEarlyTPCTransform, char, -1, "", 0, "Force early TPC transformation also for continuous data (-1 = auto)") +AddOption(fwdTPCDigitsAsClusters, unsigned char, 0, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") +AddOption(bz0Pt, unsigned char, 60, "", 0, "Nominal Pt to set when bz = 0 (in 10 MeV)") +AddOption(dropLoopers, unsigned char, 0, "", 0, "Drop looping tracks starting from second loop") +AddOption(mergerCovSource, unsigned char, 2, "", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following, 2 = refit") +AddOption(mergerInterpolateErrors, unsigned char, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") +AddOption(fitInProjections, char, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") +AddOption(fitPropagateBzOnly, char, -1, "", 0, "Propagate using Bz only for n passes") +AddOption(retryRefit, char, 1, "", 0, "Retry refit when fit fails") +AddOption(loopInterpolationInExtraPass, char, -1, "", 0, "Perform loop interpolation in an extra pass") +AddOption(mergerReadFromTrackerDirectly, char, 1, "", 0, "Forward data directly from tracker to merger on GPU") +AddOption(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") +AddCustomCPP(void SetMinTrackPt(float v) { MaxTrackQPt = v > 0.001 ? (1. / v) : (1. / 0.001); }) +AddHelp("help", 'h') +EndConfig() + +// Settings steering the processing once the device was selected +BeginSubConfig(GPUSettingsProcessing, proc, configStandalone, "PROC", 0, "Processing settings") +AddOption(platformNum, int, -1, "", 0, "Platform to use, in case the backend provides multiple platforms (-1 = auto-select)") +AddOption(gpuDeviceOnly, bool, false, "", 0, "Use only GPU as device (i.e. no CPU for OpenCL)") +AddOption(debugMask, int, -1, "", 0, "Mask for debug output dumps to file") +AddOption(comparableDebutOutput, bool, true, "", 0, "Make CPU and GPU debug output comparable (sort / skip concurrent parts)") +AddOption(resetTimers, int, 1, "", 0, "Reset timers every event") +AddOption(stuckProtection, int, 0, "", 0, "Timeout in us, When AMD GPU is stuck, just continue processing and skip tracking, do not crash or stall the chain") +AddOption(keepAllMemory, bool, false, "", 0, "Allocate all memory on both device and host, and do not reuse") +AddOption(keepDisplayMemory, bool, false, "", 0, "Like keepAllMemory, but only for memory required for event display") +AddOption(trackletSelectorSlices, char, -1, "", 0, "Number of slices to processes in parallel at max") +AddOption(nTPCClustererLanes, int, 3, "", 0, "Number of TPC clusterers that can run in parallel") +AddOption(disableMemoryReuse, bool, false, "", 0, "Disable memory reusage (for debugging only)") +AddOption(fullMergerOnGPU, bool, true, "", 0, "Perform full TPC track merging on GPU instead of only refit") +AddOption(delayedOutput, bool, true, "", 0, "Delay output to be parallel to track fit") +AddOption(tpccfGatherKernel, bool, true, "", 0, "Use a kernel instead of the DMA engine to gather the clusters") +AddOption(doublePipelineClusterizer, bool, true, "", 0, "Include the input data of the clusterizer in the double-pipeline") +AddOption(deviceNum, int, -1, "gpuDevice", 0, "Set GPU device to use (-1: automatic, -2: for round-robin usage in timeslice-pipeline)") +AddOption(globalInitMutex, bool, false, "", 0, "Use global mutex to synchronize initialization of multiple GPU instances") +AddOption(ompThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %d OMP threads")) +AddOption(nDeviceHelperThreads, int, 1, "", 0, "Number of CPU helper threads for CPU processing") +AddOption(nStreams, int, 8, "", 0, "Number of GPU streams / command queues") +AddOption(trackletConstructorInPipeline, int, -1, "", 0, "Run tracklet constructor in the pipeline") +AddOption(trackletSelectorInPipeline, int, -1, "", 0, "Run tracklet selector in the pipeline") +AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fit") +AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode") +AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") +AddOption(runMC, bool, false, "", 0, "Process MC labels") +AddOption(ompKernels, bool, false, "", 0, "Parallelize with OMP inside kernels instead of over slices") +AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") +AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") +AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") +AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") +AddOption(runQA, bool, false, "qa", 'q', "Enable tracking QA", message("Running QA: %s")) +AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") +AddOption(forceMemoryPoolSize, unsigned long, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ul)) +AddOption(forceHostMemoryPoolSize, unsigned long, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ul)) +AddOption(memoryAllocationStrategy, int, 0, "", 0, "Memory Allocation Stragegy (0 = auto, 1 = individual allocations, 2 = single global allocation)") +AddOption(deviceTimers, bool, true, "", 0, "Use device timers instead of host-based time measurement") +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") +AddVariable(eventDisplay, GPUCA_NAMESPACE::gpu::GPUDisplayBackend*, nullptr) +AddHelp("help", 'h') +EndConfig() + +#ifndef GPUCA_GPUCODE_DEVICE +// Settings concerning the event display +BeginSubConfig(GPUSettingsDisplay, GL, configStandalone, "GL", 'g', "OpenGL display settings") +AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") +AddHelp("help", 'h') +EndConfig() + +// Settings concerning the standalone QA +BeginSubConfig(GPUSettingsQA, QA, configStandalone, "QA", 'q', "QA settings") +AddOptionVec(compareInputs, const char*, "QAinput", 0, "Read histogram from these input files and include them in the output plots") +AddOptionVec(compareInputNames, const char*, "QAinputName", 0, "Legend entries for data from comparison histogram files") +AddOption(name, std::string, "", "", 0, "Legend entry for new data from current processing") +AddOption(output, std::string, "", "", 0, "Store histograms in output root file", def(std::string("histograms.root"))) +AddOption(inputHistogramsOnly, bool, false, "", 0, "Do not run tracking, but just create PDFs from input root files") +AddOption(strict, bool, true, "", 0, "Strict QA mode: Only consider resolution of tracks where the fit ended within 5 cm of the reference, and remove outliers.") +AddOption(qpt, float, 10.f, "", 0, "Set cut for Q/Pt", def(2.f)) +AddOption(recThreshold, float, 0.9f, "", 0, "Compute the efficiency including impure tracks with fake contamination") +AddOption(csvDump, bool, false, "", 0, "Dump all clusters and Pt information into csv file") +AddOption(maxResX, float, 1e6f, "", 0, "Maxmimum X (~radius) for reconstructed track position to take into accound for resolution QA in cm") +AddOption(resPrimaries, int, 0, "", 0, "0: Resolution for all tracks, 1: only for primary tracks, 2: only for non-primaries", def(1)) +AddOption(nativeFitResolutions, bool, false, "", 0, "Create resolution histograms in the native fit units (sin(phi), tan(lambda), Q/Pt)") +AddOption(filterCharge, int, 0, "", 0, "Filter for positive (+1) or negative (-1) charge") +AddOption(filterPID, int, -1, "", 0, "Filter for Particle Type (0 Electron, 1 Muon, 2 Pion, 3 Kaon, 4 Proton)") +AddOption(writeMCLabels, bool, false, "", 0, "Store mc labels to file for later matching") +AddOptionVec(matchMCLabels, const char*, "", 0, "Read labels from files and match them, only process tracks where labels differ") +AddOption(matchDisplayMinPt, float, 0, "", 0, "Minimum Pt of a matched track to be displayed") +AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") +AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") +AddHelp("help", 'h') +EndConfig() + +#ifdef GPUCA_STANDALONE +// Settings concerning the standlone timeframe from run 2 events assembly tool +BeginSubConfig(GPUSettingsTF, TF, configStandalone, "TF", 't', "Timeframe settings") +AddOption(nMerge, int, 0, "", 0, "Merge n events in a timeframe", min(0)) +AddOption(averageDistance, float, 50., "", 0, "Average distance in cm of events merged into timeframe", min(0.f)) +AddOption(randomizeDistance, bool, true, "", 0, "Randomize distance around average distance of merged events") +AddOption(shiftFirstEvent, bool, true, "", 0, "Also shift the first event in z when merging events to a timeframe") +AddOption(bunchSim, int, 0, "", 0, "Simulate correct bunch interactions instead of placing only the average number of events. A value [n] > 1 sets TFlen for [n] collisions in average. (Incompatible to TFmerge)") +AddOption(bunchCount, int, 12, "", 0, "Number of bunches per trainsort") +AddOption(bunchSpacing, int, 50, "", 0, "Spacing between benches in ns") +AddOption(bunchTrainCount, int, 48, "", 0, "Number of bunch trains") +AddOption(abortGapTime, int, (3000), "", 0, "Length of abort gap in ns") +AddOption(interactionRate, int, 50000, "", 0, "Instantaneous interaction rate") +AddOption(timeFrameLen, long, (1000000000 / 44), "", 'l', "Timeframe len in ns") +AddOption(noBorder, bool, false, "", 0, "Do not simulate border effects (partial events)") +AddOption(noEventRepeat, int, 0, "", 0, "0: Place random events, 1: Place events in timeframe one after another, 2: Place random events but do not repat", def(1)) +AddOption(nTotalEventsInTF, int, 0, "", 0, "Total number of collisions to be placed in the interior of all time frames (excluding borders)") +AddOption(eventStride, int, 0, "", 0, "Do not select random event, but walk over array of events in stride steps") +AddOption(overlayRaw, bool, false, "", 0, "Overlay raw TPC data instead of spatial clusters") +AddHelp("help", 'h') +EndConfig() + +// Settings concerning standalone toy event generator +BeginSubConfig(GPUSettingsEG, EG, configStandalone, "EG", 0, "Event generator settings") +AddOption(numberOfTracks, int, 1, "", 0, "Number of tracks per generated event") +AddHelp("help", 'h') +EndConfig() + +// Settings for the standalone benchmark +BeginConfig(GPUSettingsStandalone, configStandalone) +#if defined(CUDA_ENABLED) || defined(OPENCL1_ENABLED) || defined(OPENCL2_ENABLED) || defined(HIP_ENABLED) +AddOption(runGPU, bool, true, "", 'g', "Use GPU for processing", message("GPU processing: %s")) +#else +AddOption(runGPU, bool, false, "", 'g', "Use GPU for processing", message("GPU processing: %s")) +#endif +AddOptionSet(runGPU, bool, false, "", 'c', "Use CPU for processing", message("CPU enabled")) +#if defined(CUDA_ENABLED) +AddOption(gpuType, const char*, "CUDA", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +#elif defined(OPENCL2_ENABLED) +AddOption(gpuType, const char*, "OCL2", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +#elif defined(OPENCL1_ENABLED) +AddOption(gpuType, const char*, "OCL", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +#elif defined(HIP_ENABLED) +AddOption(gpuType, const char*, "HIP", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +#else +AddOption(gpuType, const char*, "", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") +#endif +AddOption(runGPUforce, bool, true, "", 0, "Force usage of the specified GPU device type, no CPU fallback") +AddOption(noprompt, bool, true, "", 0, "Do prompt for keypress before exiting") +AddOption(continueOnError, bool, false, "", 0, "Continue processing after an error") +AddOption(seed, int, -1, "", 0, "Set srand seed (-1: random)") +AddOption(cleardebugout, bool, false, "", 0, "Clear debug output file when processing next event") +AddOption(StartEvent, int, 0, "", 's', "First event to process", min(0)) +AddOption(NEvents, int, -1, "", 'n', "Number of events to process (-1; all)", min(0)) +AddOption(runs, int, 1, "runs", 'r', "Number of iterations to perform (repeat each event)", min(0)) +AddOption(runs2, int, 1, "runsExternal", 0, "Number of iterations to perform (repeat full processing)", min(1)) +AddOption(runsInit, int, 1, "", 0, "Number of initial iterations excluded from average", min(0)) +AddOption(EventsDir, const char*, "pp", "events", 'e', "Directory with events to process", message("Reading events from Directory events/%s")) +AddOption(eventDisplay, int, 0, "display", 'd', "Show standalone event display", def(1)) //1: default display (Windows / X11), 2: glut, 3: glfw +AddOption(eventGenerator, bool, false, "", 0, "Run event generator") +AddOption(nways7, bool, false, "", 0, "Create OuterParam") +AddOption(cont, bool, false, "", 0, "Process continuous timeframe data") +AddOption(outputcontrolmem, unsigned long, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ul), message("Using %lld bytes as output memory")) +AddOption(inputcontrolmem, unsigned long, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ul), message("Using %lld bytes as input memory")) +AddOption(cpuAffinity, int, -1, "", 0, "Pin CPU affinity to this CPU core", min(-1)) +AddOption(fifoScheduler, bool, false, "", 0, "Use FIFO realtime scheduler", message("Setting FIFO scheduler: %s")) +AddOption(fpe, bool, true, "", 0, "Trap on floating point exceptions") +AddOption(flushDenormals, bool, true, "", 0, "Enable FTZ and DAZ (Flush all denormals to zero)") +AddOption(solenoidBz, float, -1e6f, "", 0, "Field strength of solenoid Bz in kGaus") +AddOption(constBz, bool, false, "", 0, "Force constand Bz") +AddOption(overrideMaxTimebin, bool, false, "", 0, "Override max time bin setting for continuous data with max time bin in time frame") +AddOption(encodeZS, int, -1, "", 0, "Zero-Suppress TPC data", def(1)) +AddOption(zsFilter, int, -1, "", 0, "Apply Zero-Suppression when loading digits and remove those below threshold", def(1)) +AddOption(zs12bit, bool, true, "", 0, "Perform 12 bit zero-suppression encoding / filter") +AddOption(dumpEvents, bool, false, "", 0, "Dump events (after transformation such as encodeZS") +AddOption(stripDumpedEvents, bool, false, "", 0, "Remove redundant inputs (e.g. digits and ZS) before dumping") +AddOption(printSettings, bool, false, "", 0, "Print all settings") +AddOption(memoryStat, bool, false, "", 0, "Print memory statistics") +AddOption(testSyncAsync, bool, false, "syncAsync", 0, "Test first synchronous and then asynchronous processing") +AddOption(testSync, bool, false, "sync", 0, "Test settings for synchronous phase") +AddOption(timeFrameTime, bool, false, "tfTime", 0, "Print some debug information about time frame processing time") +AddOption(controlProfiler, bool, false, "", 0, "Issues GPU profiler stop and start commands to profile only the relevant processing part") +AddOption(preloadEvents, bool, false, "", 0, "Preload events into host memory before start processing") +AddOption(recoSteps, int, -1, "", 0, "Bitmask for RecoSteps") +AddOption(recoStepsGPU, int, -1, "", 0, "Bitmask for RecoSteps") +AddOption(runMerger, int, 1, "", 0, "Run track merging / refit", min(0), max(1)) +AddOption(runTRD, int, -1, "", 0, "Enable TRD processing") +AddOption(rundEdx, int, 1, "", 0, "Enable dEdx processing") +AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") +AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") +AddHelp("help", 'h') +AddHelpAll("helpall", 'H') +AddSubConfig(GPUSettingsTF, TF) +AddSubConfig(GPUSettingsQA, QA) +AddSubConfig(GPUSettingsEG, EG) +AddSubConfig(GPUSettingsDisplay, GL) +AddSubConfig(GPUSettingsRec, rec) +AddSubConfig(GPUSettingsProcessing, proc) +EndConfig() +#elif defined(GPUCA_O2_LIB) || defined(GPUCA_O2_INTERFACE) // GPUCA_STANDALONE +BeginSubConfig(GPUSettingsO2, global, configStandalone, "O2", 0, "O2 workflow settings") +AddOption(solenoidBz, float, -1000.f, "", 0, "solenoid field strength") +AddOption(constBz, bool, false, "", 0, "force constant Bz for tests") +AddOption(continuousMaxTimeBin, int, 0, "", 0, "maximum time bin of continuous data, 0 for triggered events, -1 for default of 23ms") +AddOption(deviceType, std::string, "CPU", "", 0, "Device type, CPU | CUDA | HIP | OCL1 | OCL2") +AddOption(forceDeviceType, bool, true, "", 0, "force device type, otherwise allows fall-back to CPU") +AddOption(dump, int, 0, "", 0, "Dump events for standalone benchmark: 1 = dump events, 2 = dump events and skip processing in workflow") +AddOption(runDisplay, bool, false, "", 0, "Run event visualization after processing") +AddOption(dEdxFile, std::string, "", "", 0, "File name of dEdx Splines file") +AddOption(transformationFile, std::string, "", "", 0, "File name of TPC fast transformation map") +AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") +AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") +EndConfig() +#endif // GPUCA_O2_LIB +#endif // !GPUCA_GPUCODE_DEVICE + +EndNamespace() // gpu +EndNamespace() // GPUCA_NAMESPACE + // clang-format on diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 7ef4be1f8abb9..f6300053a017d 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -129,6 +129,8 @@ set(HDRS_INSTALL Base/GPUParam.inc Merger/GPUTPCGMMergerTypes.h Global/GPUErrorCodes.h + Standalone/qconfigoptions.h + Base/GPUSettingsList.h ) # Sources only for O2 @@ -229,10 +231,6 @@ else() set(HDRS_INSTALL ${HDRS_INSTALL} Standalone/qa/GPUQA.h) endif() -if(GPUCA_EVENT_DISPLAY OR GPUCA_QA) - set(HDRS_INSTALL ${HDRS_INSTALL} Standalone/qconfigoptions.h) -endif() - # Update HDR variables with files derrived from SRC variables string(REPLACE ".cxx" ".h" HDRS_CINT_ALIROOT "${SRCS}") string(REPLACE ".cxx" ".h" HDRS_TMP "${SRCS_NO_CINT}") diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx index 8b401c2688e3f..7e63fc0403d3d 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx @@ -29,7 +29,7 @@ using namespace o2::gpu; #define AddCustomCPP(...) #define AddHelp(...) #define AddShortcut(...) -#include "qconfigoptions.h" +#include "GPUSettingsList.h" #undef BeginNamespace #undef EndNamespace #undef AddOption @@ -66,7 +66,7 @@ GPUSettingsO2 GPUO2InterfaceConfiguration::ReadConfigurableParam() #define AddCustomCPP(...) #define AddHelp(...) #define AddShortcut(...) -#include "qconfigoptions.h" +#include "GPUSettingsList.h" #undef BeginNamespace #undef EndNamespace #undef AddOption diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h index 89d42533d641f..90e472fb1a6e3 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h @@ -16,7 +16,7 @@ // --configKeyValues "GPU_global.[x]=[y]" : for global GPU run configurations, like solenoidBz, gpuType, configuration object files. // --configKeyValues "GPU_rec.[x]=[y]" : for GPU reconstruction related settings used on the GPU, like pt threshold for track rejection. // --configKeyValues "GPU_proc.[x]=[y]" : for processing options steering GPU reconstruction like GPU device ID, debug output level, number of CPU threads. -// Check qconfigoptions.h for all options +// Check GPUSettingsList.h for all options #ifndef GPUO2INTERFACECONFIGURABLEPARAM_H #define GPUO2INTERFACECONFIGURABLEPARAM_H @@ -57,7 +57,7 @@ #define AddCustomCPP(...) __VA_ARGS__ #define AddHelp(...) #define AddShortcut(...) -#include "qconfigoptions.h" +#include "GPUSettingsList.h" #undef BeginNamespace #undef EndNamespace #undef AddOption diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index e73de9f960279..42486f7bc75d2 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -11,252 +11,4 @@ /// \file qconfigoptions.h /// \author David Rohr -#include "GPUDefConstantsAndSettings.h" -#include "GPUSettings.h" - -// clang-format off - -#ifdef QCONFIG_INSTANCE -using namespace GPUCA_NAMESPACE::gpu; -#endif -BeginNamespace(GPUCA_NAMESPACE) -BeginNamespace(gpu) - -// Settings concerning the reconstruction -// There must be no bool in here, use char, as sizeof(bool) is compiler dependent and fails on GPUs!!!!!! -BeginSubConfig(GPUSettingsRec, rec, configStandalone, "REC", 0, "Reconstruction settings") -AddOption(tpcRejectQPt, float, 1.f / 0.05f, "", 0, "QPt threshold to reject clusters of TPC tracks (Inverse Pt!!!)") -AddOption(HitPickUpFactor, float, 2., "", 0, "multiplier for the chi2 window for hit pick up procedure") -AddOption(NeighboursSearchArea, float, 3., "", 0, "area in cm for the search of neighbours") -AddOption(ClusterError2CorrectionY, float, 1., "", 0, "correction for the squared cluster error during tracking") -AddOption(ClusterError2CorrectionZ, float, 1., "", 0, "correction for the squared cluster error during tracking") -AddOption(MinNTrackClusters, int, -1, "", 0, "required min number of clusters on the track") -AddOption(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required max Q/Pt (==min Pt) of tracks") -AddOption(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") -AddOption(TrackReferenceX, float, 1000, "", 0, "Transport all tracks to this X after tracking (disabled if > 500)") -AddOption(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") -AddOption(NWays, char, 3, "", 0, "Do N fit passes in final fit of merger") -AddOption(NWaysOuter, char, 0, "", 0, "Store outer param") -AddOption(RejectMode, char, 5, "", 0, "0: no limit on rejection or missed hits, >0: break after n rejected hits, <0: reject at max -n hits") -AddOption(NonConsecutiveIDs, char, false, "", 0, "Non-consecutive cluster IDs as in HLT, disables features that need access to slice data in TPC merger") -AddOption(dEdxTruncLow, unsigned char, 2, "", 0, "Low truncation threshold, fraction of 128") -AddOption(dEdxTruncHigh, unsigned char, 77, "", 0, "High truncation threshold, fraction of 128") -AddOption(GlobalTracking, char, 1, "", 0, "Enable Global Tracking (prolong tracks to adjacent sectors to find short segments)") -AddOption(DisableRefitAttachment, unsigned char, 0, "", 0, "Bitmask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") -AddOption(tpcRejectionMode, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression (0 = no, 1 = strategy A, 2 = strategy B)") -AddOption(tpcCompressionModes, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") -AddOption(tpcCompressionSortOrder, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") -AddOption(tpcSigBitsCharge, unsigned char, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") -AddOption(tpcSigBitsWidth, unsigned char, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") -AddOption(ForceEarlyTPCTransform, char, -1, "", 0, "Force early TPC transformation also for continuous data (-1 = auto)") -AddOption(fwdTPCDigitsAsClusters, unsigned char, 0, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") -AddOption(bz0Pt, unsigned char, 60, "", 0, "Nominal Pt to set when bz = 0 (in 10 MeV)") -AddOption(dropLoopers, unsigned char, 0, "", 0, "Drop looping tracks starting from second loop") -AddOption(mergerCovSource, unsigned char, 2, "", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following, 2 = refit") -AddOption(mergerInterpolateErrors, unsigned char, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") -AddOption(fitInProjections, char, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") -AddOption(fitPropagateBzOnly, char, -1, "", 0, "Propagate using Bz only for n passes") -AddOption(retryRefit, char, 1, "", 0, "Retry refit when fit fails") -AddOption(loopInterpolationInExtraPass, char, -1, "", 0, "Perform loop interpolation in an extra pass") -AddOption(mergerReadFromTrackerDirectly, char, 1, "", 0, "Forward data directly from tracker to merger on GPU") -AddOption(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") -AddCustomCPP(void SetMinTrackPt(float v) { MaxTrackQPt = v > 0.001 ? (1. / v) : (1. / 0.001); }) -AddHelp("help", 'h') -EndConfig() - -// Settings steering the processing once the device was selected -BeginSubConfig(GPUSettingsProcessing, proc, configStandalone, "PROC", 0, "Processing settings") -AddOption(platformNum, int, -1, "", 0, "Platform to use, in case the backend provides multiple platforms (-1 = auto-select)") -AddOption(gpuDeviceOnly, bool, false, "", 0, "Use only GPU as device (i.e. no CPU for OpenCL)") -AddOption(debugMask, int, -1, "", 0, "Mask for debug output dumps to file") -AddOption(comparableDebutOutput, bool, true, "", 0, "Make CPU and GPU debug output comparable (sort / skip concurrent parts)") -AddOption(resetTimers, int, 1, "", 0, "Reset timers every event") -AddOption(stuckProtection, int, 0, "", 0, "Timeout in us, When AMD GPU is stuck, just continue processing and skip tracking, do not crash or stall the chain") -AddOption(keepAllMemory, bool, false, "", 0, "Allocate all memory on both device and host, and do not reuse") -AddOption(keepDisplayMemory, bool, false, "", 0, "Like keepAllMemory, but only for memory required for event display") -AddOption(trackletSelectorSlices, char, -1, "", 0, "Number of slices to processes in parallel at max") -AddOption(nTPCClustererLanes, int, 3, "", 0, "Number of TPC clusterers that can run in parallel") -AddOption(disableMemoryReuse, bool, false, "", 0, "Disable memory reusage (for debugging only)") -AddOption(fullMergerOnGPU, bool, true, "", 0, "Perform full TPC track merging on GPU instead of only refit") -AddOption(delayedOutput, bool, true, "", 0, "Delay output to be parallel to track fit") -AddOption(tpccfGatherKernel, bool, true, "", 0, "Use a kernel instead of the DMA engine to gather the clusters") -AddOption(doublePipelineClusterizer, bool, true, "", 0, "Include the input data of the clusterizer in the double-pipeline") -AddOption(deviceNum, int, -1, "gpuDevice", 0, "Set GPU device to use (-1: automatic, -2: for round-robin usage in timeslice-pipeline)") -AddOption(globalInitMutex, bool, false, "", 0, "Use global mutex to synchronize initialization of multiple GPU instances") -AddOption(ompThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %d OMP threads")) -AddOption(nDeviceHelperThreads, int, 1, "", 0, "Number of CPU helper threads for CPU processing") -AddOption(nStreams, int, 8, "", 0, "Number of GPU streams / command queues") -AddOption(trackletConstructorInPipeline, int, -1, "", 0, "Run tracklet constructor in the pipeline") -AddOption(trackletSelectorInPipeline, int, -1, "", 0, "Run tracklet selector in the pipeline") -AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fit") -AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode") -AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") -AddOption(runMC, bool, false, "", 0, "Process MC labels") -AddOption(ompKernels, bool, false, "", 0, "Parallelize with OMP inside kernels instead of over slices") -AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") -AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") -AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") -AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") -AddOption(runQA, bool, false, "qa", 'q', "Enable tracking QA", message("Running QA: %s")) -AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") -AddOption(forceMemoryPoolSize, unsigned long, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ul)) -AddOption(forceHostMemoryPoolSize, unsigned long, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ul)) -AddOption(memoryAllocationStrategy, int, 0, "", 0, "Memory Allocation Stragegy (0 = auto, 1 = individual allocations, 2 = single global allocation)") -AddOption(deviceTimers, bool, true, "", 0, "Use device timers instead of host-based time measurement") -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") -AddVariable(eventDisplay, GPUCA_NAMESPACE::gpu::GPUDisplayBackend*, nullptr) -AddHelp("help", 'h') -EndConfig() - -#ifndef GPUCA_GPUCODE_DEVICE -// Settings concerning the event display -BeginSubConfig(GPUSettingsDisplay, GL, configStandalone, "GL", 'g', "OpenGL display settings") -AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") -AddHelp("help", 'h') -EndConfig() - -// Settings concerning the standalone QA -BeginSubConfig(GPUSettingsQA, QA, configStandalone, "QA", 'q', "QA settings") -AddOptionVec(compareInputs, const char*, "QAinput", 0, "Read histogram from these input files and include them in the output plots") -AddOptionVec(compareInputNames, const char*, "QAinputName", 0, "Legend entries for data from comparison histogram files") -AddOption(name, std::string, "", "", 0, "Legend entry for new data from current processing") -AddOption(output, std::string, "", "", 0, "Store histograms in output root file", def(std::string("histograms.root"))) -AddOption(inputHistogramsOnly, bool, false, "", 0, "Do not run tracking, but just create PDFs from input root files") -AddOption(strict, bool, true, "", 0, "Strict QA mode: Only consider resolution of tracks where the fit ended within 5 cm of the reference, and remove outliers.") -AddOption(qpt, float, 10.f, "", 0, "Set cut for Q/Pt", def(2.f)) -AddOption(recThreshold, float, 0.9f, "", 0, "Compute the efficiency including impure tracks with fake contamination") -AddOption(csvDump, bool, false, "", 0, "Dump all clusters and Pt information into csv file") -AddOption(maxResX, float, 1e6f, "", 0, "Maxmimum X (~radius) for reconstructed track position to take into accound for resolution QA in cm") -AddOption(resPrimaries, int, 0, "", 0, "0: Resolution for all tracks, 1: only for primary tracks, 2: only for non-primaries", def(1)) -AddOption(nativeFitResolutions, bool, false, "", 0, "Create resolution histograms in the native fit units (sin(phi), tan(lambda), Q/Pt)") -AddOption(filterCharge, int, 0, "", 0, "Filter for positive (+1) or negative (-1) charge") -AddOption(filterPID, int, -1, "", 0, "Filter for Particle Type (0 Electron, 1 Muon, 2 Pion, 3 Kaon, 4 Proton)") -AddOption(writeMCLabels, bool, false, "", 0, "Store mc labels to file for later matching") -AddOptionVec(matchMCLabels, const char*, "", 0, "Read labels from files and match them, only process tracks where labels differ") -AddOption(matchDisplayMinPt, float, 0, "", 0, "Minimum Pt of a matched track to be displayed") -AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") -AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") -AddHelp("help", 'h') -EndConfig() - -#ifdef GPUCA_STANDALONE -// Settings concerning the standlone timeframe from run 2 events assembly tool -BeginSubConfig(GPUSettingsTF, TF, configStandalone, "TF", 't', "Timeframe settings") -AddOption(nMerge, int, 0, "", 0, "Merge n events in a timeframe", min(0)) -AddOption(averageDistance, float, 50., "", 0, "Average distance in cm of events merged into timeframe", min(0.f)) -AddOption(randomizeDistance, bool, true, "", 0, "Randomize distance around average distance of merged events") -AddOption(shiftFirstEvent, bool, true, "", 0, "Also shift the first event in z when merging events to a timeframe") -AddOption(bunchSim, int, 0, "", 0, "Simulate correct bunch interactions instead of placing only the average number of events. A value [n] > 1 sets TFlen for [n] collisions in average. (Incompatible to TFmerge)") -AddOption(bunchCount, int, 12, "", 0, "Number of bunches per trainsort") -AddOption(bunchSpacing, int, 50, "", 0, "Spacing between benches in ns") -AddOption(bunchTrainCount, int, 48, "", 0, "Number of bunch trains") -AddOption(abortGapTime, int, (3000), "", 0, "Length of abort gap in ns") -AddOption(interactionRate, int, 50000, "", 0, "Instantaneous interaction rate") -AddOption(timeFrameLen, long, (1000000000 / 44), "", 'l', "Timeframe len in ns") -AddOption(noBorder, bool, false, "", 0, "Do not simulate border effects (partial events)") -AddOption(noEventRepeat, int, 0, "", 0, "0: Place random events, 1: Place events in timeframe one after another, 2: Place random events but do not repat", def(1)) -AddOption(nTotalEventsInTF, int, 0, "", 0, "Total number of collisions to be placed in the interior of all time frames (excluding borders)") -AddOption(eventStride, int, 0, "", 0, "Do not select random event, but walk over array of events in stride steps") -AddOption(overlayRaw, bool, false, "", 0, "Overlay raw TPC data instead of spatial clusters") -AddHelp("help", 'h') -EndConfig() - -// Settings concerning standalone toy event generator -BeginSubConfig(GPUSettingsEG, EG, configStandalone, "EG", 0, "Event generator settings") -AddOption(numberOfTracks, int, 1, "", 0, "Number of tracks per generated event") -AddHelp("help", 'h') -EndConfig() - -// Settings for the standalone benchmark -BeginConfig(GPUSettingsStandalone, configStandalone) -#if defined(CUDA_ENABLED) || defined(OPENCL1_ENABLED) || defined(OPENCL2_ENABLED) || defined(HIP_ENABLED) -AddOption(runGPU, bool, true, "", 'g', "Use GPU for processing", message("GPU processing: %s")) -#else -AddOption(runGPU, bool, false, "", 'g', "Use GPU for processing", message("GPU processing: %s")) -#endif -AddOptionSet(runGPU, bool, false, "", 'c', "Use CPU for processing", message("CPU enabled")) -#if defined(CUDA_ENABLED) -AddOption(gpuType, const char*, "CUDA", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") -#elif defined(OPENCL2_ENABLED) -AddOption(gpuType, const char*, "OCL2", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") -#elif defined(OPENCL1_ENABLED) -AddOption(gpuType, const char*, "OCL", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") -#elif defined(HIP_ENABLED) -AddOption(gpuType, const char*, "HIP", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") -#else -AddOption(gpuType, const char*, "", "", 0, "GPU type (CUDA / HIP / OCL / OCL2)") -#endif -AddOption(runGPUforce, bool, true, "", 0, "Force usage of the specified GPU device type, no CPU fallback") -AddOption(noprompt, bool, true, "", 0, "Do prompt for keypress before exiting") -AddOption(continueOnError, bool, false, "", 0, "Continue processing after an error") -AddOption(seed, int, -1, "", 0, "Set srand seed (-1: random)") -AddOption(cleardebugout, bool, false, "", 0, "Clear debug output file when processing next event") -AddOption(StartEvent, int, 0, "", 's', "First event to process", min(0)) -AddOption(NEvents, int, -1, "", 'n', "Number of events to process (-1; all)", min(0)) -AddOption(runs, int, 1, "runs", 'r', "Number of iterations to perform (repeat each event)", min(0)) -AddOption(runs2, int, 1, "runsExternal", 0, "Number of iterations to perform (repeat full processing)", min(1)) -AddOption(runsInit, int, 1, "", 0, "Number of initial iterations excluded from average", min(0)) -AddOption(EventsDir, const char*, "pp", "events", 'e', "Directory with events to process", message("Reading events from Directory events/%s")) -AddOption(eventDisplay, int, 0, "display", 'd', "Show standalone event display", def(1)) //1: default display (Windows / X11), 2: glut, 3: glfw -AddOption(eventGenerator, bool, false, "", 0, "Run event generator") -AddOption(nways7, bool, false, "", 0, "Create OuterParam") -AddOption(cont, bool, false, "", 0, "Process continuous timeframe data") -AddOption(outputcontrolmem, unsigned long, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ul), message("Using %lld bytes as output memory")) -AddOption(inputcontrolmem, unsigned long, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ul), message("Using %lld bytes as input memory")) -AddOption(cpuAffinity, int, -1, "", 0, "Pin CPU affinity to this CPU core", min(-1)) -AddOption(fifoScheduler, bool, false, "", 0, "Use FIFO realtime scheduler", message("Setting FIFO scheduler: %s")) -AddOption(fpe, bool, true, "", 0, "Trap on floating point exceptions") -AddOption(flushDenormals, bool, true, "", 0, "Enable FTZ and DAZ (Flush all denormals to zero)") -AddOption(solenoidBz, float, -1e6f, "", 0, "Field strength of solenoid Bz in kGaus") -AddOption(constBz, bool, false, "", 0, "Force constand Bz") -AddOption(overrideMaxTimebin, bool, false, "", 0, "Override max time bin setting for continuous data with max time bin in time frame") -AddOption(encodeZS, int, -1, "", 0, "Zero-Suppress TPC data", def(1)) -AddOption(zsFilter, int, -1, "", 0, "Apply Zero-Suppression when loading digits and remove those below threshold", def(1)) -AddOption(zs12bit, bool, true, "", 0, "Perform 12 bit zero-suppression encoding / filter") -AddOption(dumpEvents, bool, false, "", 0, "Dump events (after transformation such as encodeZS") -AddOption(stripDumpedEvents, bool, false, "", 0, "Remove redundant inputs (e.g. digits and ZS) before dumping") -AddOption(printSettings, bool, false, "", 0, "Print all settings") -AddOption(memoryStat, bool, false, "", 0, "Print memory statistics") -AddOption(testSyncAsync, bool, false, "syncAsync", 0, "Test first synchronous and then asynchronous processing") -AddOption(testSync, bool, false, "sync", 0, "Test settings for synchronous phase") -AddOption(timeFrameTime, bool, false, "tfTime", 0, "Print some debug information about time frame processing time") -AddOption(controlProfiler, bool, false, "", 0, "Issues GPU profiler stop and start commands to profile only the relevant processing part") -AddOption(preloadEvents, bool, false, "", 0, "Preload events into host memory before start processing") -AddOption(recoSteps, int, -1, "", 0, "Bitmask for RecoSteps") -AddOption(recoStepsGPU, int, -1, "", 0, "Bitmask for RecoSteps") -AddOption(runMerger, int, 1, "", 0, "Run track merging / refit", min(0), max(1)) -AddOption(runTRD, int, -1, "", 0, "Enable TRD processing") -AddOption(rundEdx, int, 1, "", 0, "Enable dEdx processing") -AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") -AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") -AddHelp("help", 'h') -AddHelpAll("helpall", 'H') -AddSubConfig(GPUSettingsTF, TF) -AddSubConfig(GPUSettingsQA, QA) -AddSubConfig(GPUSettingsEG, EG) -AddSubConfig(GPUSettingsDisplay, GL) -AddSubConfig(GPUSettingsRec, rec) -AddSubConfig(GPUSettingsProcessing, proc) -EndConfig() -#elif defined(GPUCA_O2_LIB) || defined(GPUCA_O2_INTERFACE) // GPUCA_STANDALONE -BeginSubConfig(GPUSettingsO2, global, configStandalone, "O2", 0, "O2 workflow settings") -AddOption(solenoidBz, float, -1000.f, "", 0, "solenoid field strength") -AddOption(constBz, bool, false, "", 0, "force constant Bz for tests") -AddOption(continuousMaxTimeBin, int, 0, "", 0, "maximum time bin of continuous data, 0 for triggered events, -1 for default of 23ms") -AddOption(deviceType, std::string, "CPU", "", 0, "Device type, CPU | CUDA | HIP | OCL1 | OCL2") -AddOption(forceDeviceType, bool, true, "", 0, "force device type, otherwise allows fall-back to CPU") -AddOption(dump, int, 0, "", 0, "Dump events for standalone benchmark: 1 = dump events, 2 = dump events and skip processing in workflow") -AddOption(runDisplay, bool, false, "", 0, "Run event visualization after processing") -AddOption(dEdxFile, std::string, "", "", 0, "File name of dEdx Splines file") -AddOption(transformationFile, std::string, "", "", 0, "File name of TPC fast transformation map") -AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") -AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") -EndConfig() -#endif // GPUCA_O2_LIB -#endif // !GPUCA_GPUCODE_DEVICE - -EndNamespace() // gpu -EndNamespace() // GPUCA_NAMESPACE - // clang-format on +#include "GPUSettingsList.h" From 9884a2116926f0e28891fa1b50d97945b2e499c2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 20 Jul 2020 22:38:45 +0200 Subject: [PATCH 0156/1751] GPU: Remove redundant setting of number of OpenMP threads --- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 10 ++-------- GPU/GPUTracking/Standalone/standalone.cxx | 13 ------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 194667acb1cf8..310986b318915 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -635,14 +635,8 @@ int GPUDisplay::InitGL_internal() setDepthBuffer(); setQuality(); ReSizeGLScene(GPUDisplayBackend::INIT_WIDTH, GPUDisplayBackend::INIT_HEIGHT, true); -#ifdef WITH_OPENMP - int maxThreads = mChain->GetProcessingSettings().ompThreads > 1 ? mChain->GetProcessingSettings().ompThreads : 1; - omp_set_num_threads(maxThreads); -#else - int maxThreads = 1; -#endif - mThreadBuffers.resize(maxThreads); - mThreadTracks.resize(maxThreads); + mThreadBuffers.resize(mChain->GetProcessingSettings().ompThreads); + mThreadTracks.resize(mChain->GetProcessingSettings().ompThreads); #ifdef GPUCA_DISPLAY_OPENGL_CORE CHKERR(mVertexShader = glCreateShader(GL_VERTEX_SHADER)); CHKERR(glShaderSource(mVertexShader, 1, &GPUDisplayShaders::vertexShader, NULL)); diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 20a93aa288b52..77e016cfa6a9d 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -233,19 +233,6 @@ int ReadConfiguration(int argc, char** argv) configStandalone.proc.ompThreads = 1; } -#ifdef WITH_OPENMP - if (configStandalone.proc.ompThreads != -1) { - omp_set_num_threads(configStandalone.proc.ompThreads); - } else { - configStandalone.proc.ompThreads = omp_get_max_threads(); - } - if (configStandalone.proc.ompThreads != omp_get_max_threads()) { - printf("Cannot set number of OMP threads!\n"); - return 1; - } -#else - configStandalone.proc.ompThreads = 1; -#endif if (configStandalone.outputcontrolmem) { bool forceEmptyMemory = getenv("LD_PRELOAD") && strstr(getenv("LD_PRELOAD"), "valgrind") != nullptr; outputmemory.reset(new char[configStandalone.outputcontrolmem]); From e308f51de8ca624935375c63d752b70ecf70f59f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 23 Jul 2020 15:25:00 +0200 Subject: [PATCH 0157/1751] DPL: allow specifying a post fork command This allows specifying a command to be executed after a given children has forked. For example it can be used to invoke numactl on the child pid and set it's numa parameters. A number of templated argument can be specified to customize the command based on the child process and parents properties. E.g.: {timeslice0} : the parallel processing timeslice (0 based index) {timeslice1} : the parallel processing timeslice (1 based index) {pid}: the pid of the child {id}: the id of the child {name}: the data processor name of the parent {rank0}: the rank of data parallel computation {maxRank0}: the max rank of the data parallel computation --- Framework/Core/src/DeviceSpecHelpers.cxx | 2 ++ Framework/Core/src/runDataProcessing.cxx | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 79d4bdf2898c3..a2f586a2a6c5d 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -925,6 +925,7 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, realOdesc.add_options()("child-driver", bpo::value<std::string>()); realOdesc.add_options()("rate", bpo::value<std::string>()); realOdesc.add_options()("environment", bpo::value<std::string>()); + realOdesc.add_options()("post-fork-command", bpo::value<std::string>()); realOdesc.add_options()("shm-segment-size", bpo::value<std::string>()); realOdesc.add_options()("shm-mlock-segment", bpo::value<std::string>()); realOdesc.add_options()("shm-monitor", bpo::value<std::string>()); @@ -1041,6 +1042,7 @@ boost::program_options::options_description DeviceSpecHelpers::getForwardedDevic ("shm-segment-size", bpo::value<std::string>(), "size of the shared memory segment in bytes") // ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // ("environment", bpo::value<std::string>(), "comma separated list of environment variables to set for the device") // + ("post-fork-command", bpo::value<std::string>(), "post fork command to execute (e.g. numactl {pid}") // ("session", bpo::value<std::string>(), "unique label for the shared memory session") // ("configuration,cfg", bpo::value<std::string>(), "configuration connection string") // ("monitoring-backend", bpo::value<std::string>(), "monitoring connection string") // diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 0b7743272dfff..841798eb47b22 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -423,6 +423,23 @@ void spawnDevice(std::string const& forwardedStdin, } execvp(execution.args[0], execution.args.data()); } + if (varmap.count("post-fork-command")) { + auto templateCmd = varmap["post-fork-command"]; + auto cmd = fmt::format(templateCmd.as<std::string>(), + fmt::arg("pid", id), + fmt::arg("id", spec.id), + fmt::arg("name", spec.name), + fmt::arg("timeslice0", spec.inputTimesliceId), + fmt::arg("timeslice1", spec.inputTimesliceId + 1), + fmt::arg("rank0", spec.rank), + fmt::arg("maxRank0", spec.nSlots) + ); + int err = system(cmd.c_str()); + if (err) { + LOG(error) << "Post fork command `" << cmd << "` returned with status " << err; + } + LOG(debug) << "Successfully executed `" << cmd; + } // This is the parent. We close the write end of // the child pipe and and keep track of the fd so // that we can later select on it. From e2a8bb260e1832d332516af424bfd540642601c6 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 23 Jul 2020 15:43:24 +0200 Subject: [PATCH 0158/1751] DPL: add support for current CPU / NODE to post-fork-command This adds: {cpu}: parent process cpu at some point after the fork {node}: parent process numa node at some point after the fork to the templated arguments understood by --post-fork-command --- Framework/Core/src/runDataProcessing.cxx | 33 +++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 841798eb47b22..4afad32ab9749 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -106,6 +106,25 @@ #include <sys/un.h> #include <sys/wait.h> #include <unistd.h> +#if __has_include(<linux/getcpu.h>) +#include <linux/getcpu.h> +#elif __has_include(<cpuid.h>) +#include <cpuid.h> +#define CPUID(INFO, LEAF, SUBLEAF) __cpuid_count(LEAF, SUBLEAF, INFO[0], INFO[1], INFO[2], INFO[3]) +#define GETCPU(CPU) \ + { \ + uint32_t CPUInfo[4]; \ + CPUID(CPUInfo, 1, 0); \ + /* CPUInfo[1] is EBX, bits 24-31 are APIC ID */ \ + if ((CPUInfo[3] & (1 << 9)) == 0) { \ + CPU = -1; /* no APIC on chip */ \ + } else { \ + CPU = (unsigned)CPUInfo[1] >> 24; \ + } \ + if (CPU < 0) \ + CPU = 0; \ + } +#endif using namespace o2::monitoring; using namespace o2::configuration; @@ -424,16 +443,24 @@ void spawnDevice(std::string const& forwardedStdin, execvp(execution.args[0], execution.args.data()); } if (varmap.count("post-fork-command")) { + unsigned cpu = -1; + unsigned node = -1; +#if __has_include(<linux/getcpu.h>) + getcpu(&cpu, &node, nullptr); +#elif __has_include(<cpuid.h>) + GETCPU(cpu); +#endif auto templateCmd = varmap["post-fork-command"]; - auto cmd = fmt::format(templateCmd.as<std::string>(), + auto cmd = fmt::format(templateCmd.as<std::string>(), fmt::arg("pid", id), fmt::arg("id", spec.id), + fmt::arg("cpu", cpu), + fmt::arg("node", node), fmt::arg("name", spec.name), fmt::arg("timeslice0", spec.inputTimesliceId), fmt::arg("timeslice1", spec.inputTimesliceId + 1), fmt::arg("rank0", spec.rank), - fmt::arg("maxRank0", spec.nSlots) - ); + fmt::arg("maxRank0", spec.nSlots)); int err = system(cmd.c_str()); if (err) { LOG(error) << "Post fork command `" << cmd << "` returned with status " << err; From b312da122a738187363b18d118f45b325c944d21 Mon Sep 17 00:00:00 2001 From: nburmaso <nazar.burmasov@cern.ch> Date: Fri, 24 Jul 2020 09:12:48 +0300 Subject: [PATCH 0159/1751] Fixed track selection bug --- Analysis/Tasks/upcAnalysis.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Analysis/Tasks/upcAnalysis.cxx b/Analysis/Tasks/upcAnalysis.cxx index 54b728d5784c2..36514fa770ac9 100644 --- a/Analysis/Tasks/upcAnalysis.cxx +++ b/Analysis/Tasks/upcAnalysis.cxx @@ -41,13 +41,13 @@ struct UPCAnalysis { // TODO: // Add trigger class check // if (!col.alias()[kCUP9]) - // return; + // return; std::vector<soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection>::iterator> selTracks; for (auto track : tracks) { if (!track.isGlobalTrack()) continue; selTracks.push_back(track); - if (selTracks.size() == 2) + if (selTracks.size() > 2) break; } if (selTracks.size() != 2) From 3e72d7e8c65a96c0447adc20aa6e7cd13861b9ba Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Tue, 19 May 2020 16:56:11 +0200 Subject: [PATCH 0160/1751] moved headers around to the orders they appear in raw data --- DataFormats/Detectors/TRD/CMakeLists.txt | 6 +- .../TRD/include/DataFormatsTRD/RawData.h | 435 ++++++++++++++++++ .../TRD/include/DataFormatsTRD/Tracklet64.h | 137 ++++++ .../Detectors/TRD/src/DataFormatsTRDLinkDef.h | 5 + DataFormats/Detectors/TRD/src/RawData.cxx | 22 + DataFormats/Detectors/TRD/src/Tracklet64.cxx | 22 + Detectors/TRD/base/CMakeLists.txt | 7 + Detectors/TRD/base/test/testRawData.cxx | 98 ++++ .../include/TRDSimulation/Tracklets2Raw.h | 54 +++ .../TRD/simulation/src/TrapSimulator.cxx | 33 +- 10 files changed, 806 insertions(+), 13 deletions(-) create mode 100644 DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h create mode 100644 DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h create mode 100644 DataFormats/Detectors/TRD/src/RawData.cxx create mode 100644 DataFormats/Detectors/TRD/src/Tracklet64.cxx create mode 100644 Detectors/TRD/base/test/testRawData.cxx create mode 100644 Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h diff --git a/DataFormats/Detectors/TRD/CMakeLists.txt b/DataFormats/Detectors/TRD/CMakeLists.txt index ea053219e7630..9d104bd3a7635 100644 --- a/DataFormats/Detectors/TRD/CMakeLists.txt +++ b/DataFormats/Detectors/TRD/CMakeLists.txt @@ -10,10 +10,14 @@ o2_add_library(DataFormatsTRD SOURCES src/TriggerRecord.cxx + src/RawData.cxx + src/Tracklet64.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::SimulationDataFormat ) o2_target_root_dictionary(DataFormatsTRD - HEADERS include/DataFormatsTRD/TriggerRecord.h) + HEADERS include/DataFormatsTRD/TriggerRecord.h + include/DataFormatsTRD/RawData.h + include/DataFormatsTRD/Tracklet64.h) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h new file mode 100644 index 0000000000000..25ca0eab61a13 --- /dev/null +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -0,0 +1,435 @@ +// 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_TRD_RAWDATA_H +#define ALICEO2_TRD_RAWDATA_H + +#include <iosfwd> +#include <iostream> +#include <iomanip> +#include <fstream> +#include "fairlogger/Logger.h" +/// \class TRDRDH +/// \brief Header for TRD raw data header +// this is the header added by the CRU + +namespace o2{ +namespace trd{ + +struct HalfCRUHeader +{ +/* Half cru header +64 bits is too wide, hence reduce to 32 to make it readable. + + |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| + ------------------------------------------------------------------------------------------------- +Word 0 | link 0 errorflags | link 0 datasize | link 1 errorflags | + ------------------------------------------------------------------------------------------------- +Word 0 | link 0 data size | link 2 error flags | link 2 datasize upper| + ------------------------------------------------------------------------------------------------- +Word 1 | link 2 datasize lower | link 3 errorflags | link 3 datasize | + ------------------------------------------------------------------------------------------------- +Word 1 | link 4 errorflags | link 4 datasize | link 5 errorflags | + ------------------------------------------------------------------------------------------------- +Word 2 | link 5 data size | link 6 error flags | link 6 datasize upper| + ------------------------------------------------------------------------------------------------- +Word 2 | link 6 datasize lower | link 7 errorflags | link 7 datasize | + ------------------------------------------------------------------------------------------------- +Word 3 | reserved | + ------------------------------------------------------------------------------------------------- +Word 3 | header version | bunch crossing | stop bit | event type | + ------------------------------------------------------------------------------------------------- +Word 4 | reserved | + ------------------------------------------------------------------------------------------------- +Word 4 | reserved | + ------------------------------------------------------------------------------------------------- +Word 5 | reserved | link 8 error flags | + ------------------------------------------------------------------------------------------------- +Word 5 | link 8 data size | link 9 error flags | link 9 datasize upper| + ------------------------------------------------------------------------------------------------- +Word 6 | link 9 datasize lower | link 10 errorflags | link 10 datasize | + ------------------------------------------------------------------------------------------------- +Word 6 | link 11 errorflags | link 11 datasize | link 12 errorflags | + ------------------------------------------------------------------------------------------------- +Word 7 | link 12 data size | link 13 error flags | link 13 datasize upper| + ------------------------------------------------------------------------------------------------- +Word 7 |link 13 datasize lower | link 14 errorflags | link 14 datasize | + ------------------------------------------------------------------------------------------------- + +alternate candidate : + |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| + ------------------------------------------------------------------------------------------------- +Word 0 | header version | bunch crossing | stop bit | event type | + ------------------------------------------------------------------------------------------------- +Word 0 | reserved | + ------------------------------------------------------------------------------------------------- +Word 1 | link 0 errorflags | link 1 errorflags | link2 error flags | link 3 error flags | + ------------------------------------------------------------------------------------------------- +Word 1 | link 4 error flags | link 5 error flags | link 6 error flags | link 7 error flags | + ------------------------------------------------------------------------------------------------- +Word 2 | link 0 datasize | link 1 datasize | + ------------------------------------------------------------------------------------------------- +Word 2 | link 2 datasize | link 3 datasize | + ------------------------------------------------------------------------------------------------- +Word 3 | link 4 data size | link 5 datasize | + ------------------------------------------------------------------------------------------------- +Word 3 | link 6 datasize | link 7 datasize | + ------------------------------------------------------------------------------------------------- +Word 4 | reserved | + ------------------------------------------------------------------------------------------------- +Word 4 | reserved | + ------------------------------------------------------------------------------------------------- +Word 5 | reserved | link 8 error flags | + ------------------------------------------------------------------------------------------------- +Word 5 | link 9 errorflags | link 10 errorflags | link11 error flags | link 12 error flags | + ------------------------------------------------------------------------------------------------- +Word 6 | link 13 error flags | link 14 error flags | link 8 datasize | + ------------------------------------------------------------------------------------------------- +Word 6 | link 9 datasize | link 10 datasize | + ------------------------------------------------------------------------------------------------- +Word 7 | link 11 datasize | link 12 datasize | + ------------------------------------------------------------------------------------------------- +Word 7 | link 13 datasize | link 14 datasize | + -------------------------------------------------------------------------------------------------- +*/ + + union{ + uint64_t word02[3]; + struct{ + uint64_t errorflags : 8; + uint64_t size : 16; + }__attribute__((__packed__)) linksA[8]; + }; + union{ + uint64_t word3=0x0; + //first word * + // uint64_t: 0x0000000000000000 + // | - | || + // | | | |- 0..7 Event type + // | | | -- 8..11 Stop bit + // | | ------ 12..23 bunch crossing id + // | -------- 24..31 TRD Header version + // --------------- 32..63 reserveda + struct{ + uint64_t reserveda :32; // + uint64_t HeaderVersion : 8; // TRD Header Version + uint64_t BunchCrossing :12; // bunch crossing + uint64_t StopBit : 4; // 8 .. 11 stop bit 0x1 if TRD packet is last data packet of trigger, else 0x0 TODO why 4 bits if only using 1? + uint64_t EventType : 8; // bit 0..7 event type of the data. Trigger bits from TTC-PON message, distinguish physics from calibration events. + }__attribute__((__packed__)); + }; + union{ + uint64_t word4=0x0; + struct{ + uint64_t reservedb; + }__attribute__((__packed__)); + }; + union{ + uint64_t word57[3]; + struct{ + uint64_t errorflags : 8; + uint64_t size : 16; + }__attribute__((__packed__)) linksB[8]; // although this is 8 dont use index 0 as its part of reserved. + }; +}; + +/// \structure HalfChamberHeader +/// \brief Header for each half chamber +// Coming before all other tracklet data, a single tracklet word as a header for its half chamber + +struct HalfChamberHeader +{ + union{ + // 10987654321098765432109876543210 + // uint32_t: 00000000000000000000000000000000 + // cccccccccccccccc iiiiiiiiiii + // ffff| y| + // | | |------ 0-10 half chamber id + // | | ------------- 11 always 0x1 + // | ----------------------------- 12-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 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 format : 4; + // 0 baseline PID 3 time slices, 7 bit each + // 1 DO NOT USE ! reserved for tracklet end marker disambiguation + // 14 Tracklet test-pattern mode + // 15 Reserved for testing + }__attribute__((__packed__)); + }; +}; + +/// \structure MCMRawDataHeader +/// \brief Header for MCM tracklet data outuput +// This constitutes the "4x32" bits of information from a single MCM, MCMRawDataHeader and 1-3 TrapRawTracklet. +struct MCMRawDataHeader +{ + //first word * + // 10987654321098765432109876543210 + // uint32_t: 00000000000000000000000000000000 + // 1zzzz pppppppp pppppppp 1 + // || yy| pppppppp | ccc-- 0..1 check bits + // || | | | ------------ 2-9 pid for tracklet 3 second part + // || | | --------------------- 10-17 pid for tracklet 2 second part + // || | ---------------------------- 18-25 pid for tracklet 1 second part + // || ------------------------------ 26-27 coly + // |---------------------------------- 28-31 padrow + //TODO need to check endianness, I have a vague memory the trap chip has different endianness to x86. + union{ + uint32_t word; + struct{ + uint32_t oneb : 1; // + uint32_t pid0:8 ; // 3 parts of pid for each tracklet + uint32_t pid1:8 ; // 3 parts of pid for each tracklet + uint32_t pid2:8 ; // 3 parts of pid for each tracklet + uint32_t col : 2; // 2 bits for position in pad direction. + uint32_t padrow : 4; // padrow,z coordinate for chip. + uint32_t onea : 1; // + }__attribute__((__packed__)); + }; + +}; + +// \structure TrapRawTracklet. +// \brief Raw Data of a tracklet, part is how ever in the MCM Header hence both are grouped together in the same file + + struct TrapRawTracklet{ // This is a bad name as part of the tracklet data is in the MCMHeader. + union{ + uint32_t word; + struct{ + uint8_t checkbit : 1; // The size of the data for this link + uint16_t pid : 15 ; // Particle Identity + uint16_t slope : 6 ; // Deflection angle of tracklet + uint16_t pos : 10 ; // Position of tracklet, signed 10 bits, granularity 0.02 pad widths, -10.22 to +10.22, relative to centre of pad 10 + }__attribute__((__packed__)); + }; + }; + + + +/* +std::vector<uint32_t> getPID(char *rawdata, int tracklet) +{ + // extract the 2 parts of the pid and return the combined PID + // rawdata starts with the mcmheader + uint32_t pid = 1;//(rawdata.pid[tracklet]<<15) + rawdata.pid[]; TODO figure out a better way that is not *undefined* c++ to progress to following 32bit words after MCMRawDataHeader. + //TODO come back here, marker to come back. + std::vector<uint32_t> pids; + MCMRawDataHeader mcmheader; + TrapRawTracklet trackletdata; + //memcpy(&mcmheader,&rawdata[0],sizeof(mcmheader)); + std::copy(rawdata.begin(), rawdata.begin()+sizeof(mcmheader),(char*)&mcmheader); + for(int tracklet=0;tracklet<3;tracklet++){ + memcpy(&trackletdata,&rawdata[0]+sizeof(mcmheader)+tracklet*sizeof(trackletdata),sizeof(TrapRawTracklet)); + uint32_t headpid=0; + switch(tracklet){ + case 0 : headpid=mcmheader.pid0;break; + case 1 : headpid=mcmheader.pid1;break; + case 2 : headpid=mcmheader.pid2;break; + } + pids[tracklet] = (headpid<<15) + trackletdata.pid; + } + // memcpy(rawdata,) + return pids; +} + +uint32_t getPadRow(const char *rawdata) +{ + MCMRawDataHeader mcmheader; + memcpy(&mcmheader, rawdata,sizeof(MCMRawDataHeader)); + return mcmheader.padrow; + +} +uint32_t getCol(const char* rawdata) +{ + MCMRawDataHeader mcmheader; + memcpy(&mcmheader, rawdata,sizeof(MCMRawDataHeader)); + return mcmheader.col; + +} +int16_t getPos(const char* rawdata, int tracklet) +{ + // extract y from the tracklet word, raw data points to the mcmheader of this data. + //rawdata points to the MCMRawDataHeader + TrapRawTracklet trackletdata; + MCMRawDataHeader mcmrawdataheader; + memcpy(&mcmrawdataheader,rawdata,sizeof(MCMRawDataHeader)); + memcpy(&trackletdata,rawdata+sizeof(MCMRawDataHeader)); + return trackletdata.pos; + return 1; +} +uint32_t getSlope(const *rawdata, int tracklet) +{ + // extract dy or slope from the tracklet word, raw data points to the mcmheader of this data. + TrapRawTracklet trackletdata; + memcpy(&trackletdata,&rawdata[0]+sizeof(MCMRawDataHeader)+tracklet*sizeof(trackletdata),sizeof(TrapRawTracklet)); + return trackletdata.slope; +} +due to the interplay of MCMRawDataHeader and TrapRawTracklet come back to this. TODO +*/ + + +uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data=true) +{ + //TODO this needs some more ellaborate testing. I got the packing to work so for now, + // its a question of unpacking info in line 88 and 89. + uint32_t info=0; + if(link>14) return 0xffffffff; + + char *words; + if(link<8) words = (char*)&cruhead.word02[0]; + if(link<15) words= (char*)&cruhead.word57[0]; + uint32_t byteoffset=link*3; // each link [size+erroflags] is 24 bits, so 3 bytes. + if(data) info = ((words[byteoffset+1] )<< 8 )+ (words[byteoffset+2]); + else info=words[byteoffset]; + + return info; +} + +uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link) +{ + uint32_t errorflags=0; + if(link<8){ + //dealing with word0-2 + errorflags= cruhead.linksA[link].errorflags; + } + else { + if(link<16){ + errorflags=cruhead.linksB[link-8+1].errorflags; // link 0 [actually 9] is in fact the end part of reserved. + + } + else std::cout << "error link=" << link << " not in range 0-14" << std::endl; + } + return errorflags; +} + +uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link) +{ + //return number 32 byte blocks for the link 3x64bit ints. + uint32_t size=0; + if(link<8){ + size= (cruhead.linksA[link].size); + } + else { + if(link<16){ // link 0 is part of reserved + size=cruhead.linksB[link-8+1].size; + + } + else std::cout << "error link=" << link << " not in range 0-14" << std::endl; + } + return size; +} + +uint32_t getlinkerrorflags(const HalfCRUHeader& cruheader, std::array<uint32_t,15>& linkerrorflags ) +{ + for(uint32_t link=0;link<15;link++){ + linkerrorflags[link] = getlinkerrorflag(cruheader,link); + } + return 0; +} +uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t,15>& linksizes ) +{ + for(uint32_t link=0;link<15;link++){ + linksizes[link] = getlinkdatasize(cruheader,link); + } + return 0; +} + +/* + * Printing methods to dump and display the various structures above in pretty format or hexdump + */ + +std::ostream& operator<<(std::ostream& stream, const HalfChamberHeader halfchamberheader) +{ + stream << "HalfChamberHeader : " << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const TrapRawTracklet& tracklet) +{ + // make a pretty output of the tracklet. + stream << "TrapRawTracklet: pos=" << tracklet.pos << "::slope=" << tracklet.slope <<"::pid="<< tracklet.pid <<"::checkbit=" << tracklet.checkbit << std::endl; + return stream; +} +void printTrapRawTracklet(o2::trd::TrapRawTracklet& tracklet) +{ + LOGF(INFO,"TrapRawTracklet: "); +} + +void printMCMHeader(o2::trd::MCMRawDataHeader& mcmhead) +{ + LOGF(INFO,"MCMRawHeader: 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d",mcmhead.onea,mcmhead.padrow,mcmhead.col,mcmhead.pid2,mcmhead.pid1,mcmhead.pid0,mcmhead.oneb); +} + +std::ostream& operator<<(std::ostream& stream, const MCMRawDataHeader& mcmhead) +{ + // make a pretty output of the mcm header. + // stream << "MCMRawHeader:" << mcmhead.checkbits << "::" << (mcmhead.pid&0xfff000000) << ":"<< (mcmhead.pid&0xfff000) << ":"<< (mcmhead.pid&0xfff) << std::endl; + stream << "MCMRawHeader:" << mcmhead.onea<<"::"<< mcmhead.pid2 << ":"<< mcmhead.pid1 << ":"<< mcmhead.pid0 << "::"<<mcmhead.oneb<< std::endl; + return stream; +} + + +void printHalfChamber(o2::trd::HalfChamberHeader& halfchamber) +{ + LOGF(INFO,"HCID : %d MCLK: %d Format: %d Always1:%d",halfchamber.HCID,halfchamber.MCLK,halfchamber.format, halfchamber.one); +} + +void dumpHalfChamber(o2::trd::HalfChamberHeader& halfchamber) +{ + LOGF(INFO,"HalfChamber : 0x%08x",halfchamber.word); +} + +void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) +{ + std::array<uint32_t,15> sizes; + std::array<uint32_t,15> errorflags; + getlinkdatasizes(halfcru,sizes); + getlinkerrorflags(halfcru,errorflags); + LOGF(INFO, "V:%d BC:%d SB:%d EType:%d",halfcru.HeaderVersion,halfcru.BunchCrossing,halfcru.StopBit,halfcru.EventType); + for(int i=0;i<15;i++) LOGF(INFO,"Link %d size: %ul eflag: 0x%02x",i,sizes[i],errorflags[i]); +} + +void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) +{ + std::array<uint32_t,16> raw{}; + memcpy(&raw[0],&halfcru,sizeof(halfcru)); + for(int i=0;i<4;i++){ + int index=4*i; + LOGF(INFO,"[1/2CRUHeader %d] 0x%08x 0x%08x 0x%08x 0x%08x",i,raw[index+3],raw[index+2],raw[index+1],raw[index+0]); + } +} + + +std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) // make a pretty output of the header. +{ + stream << std::hex; + stream << "EventType : " << halfcru.EventType << std::endl; + stream << "StopBit : " << halfcru.StopBit << std::endl; + stream << "BunchCrossing : " << halfcru.BunchCrossing << std::endl; + stream << "HeaderVersion : " << halfcru.HeaderVersion << std::endl; + stream << "link sizes : "; + for(int link=0;link<15;link++)stream << link<<":"<<std::hex << std::setw(4) << getlinkdatasize(halfcru,link) <<","; + stream << std::endl; + stream << "link errorflags : "; + for(int link=0;link<15;link++)stream << link<<":"<<std::hex << std::setw(2) << getlinkerrorflag(halfcru,link) <<","; + stream << std::endl; + stream << "0x" << halfcru.word02[0] << " 0x" << halfcru.word02[1] << " 0x" << halfcru.word02[2] << " 0x" << halfcru.word3 << " 0x" << halfcru.word4 << " 0x" << halfcru.word57[0] << " 0x" << halfcru.word57[1] << " 0x" << halfcru.word57[2]<< std:: endl; + return stream; +} + +} // namespace trd +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h new file mode 100644 index 0000000000000..370f5c33ef11e --- /dev/null +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -0,0 +1,137 @@ +// 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 "TRDBase/TRDGeometryBase.h" +//#include "DetectorsCommonDataFormats/DetMatrixCache.h" +//#include "DetectorsCommonDataFormats/DetID.h" + +#ifndef O2_TRD_TRACKLET64_H +#define O2_TRD_TRACKLET64_H + +//////////////////////////////////////////////////////////////////////////// +// // +// TRD Raw tracklet // +// class for TRD tracklets // +// loosely based on the old TrackletMCM // +// It still returns the old TrackletWord of run2, rebuilt on calling. // +// Authors // +// Sean Murray (murrays@cern.ch) // +// +//////////////////////////////////////////////////////////////////////////// +#include <vector> +#include <array> +#include <memory> // for std::unique_ptr +#include "Rtypes.h" // for ClassDef +#include "fairlogger/Logger.h" + +namespace o2 +{ +namespace trd +{ +/* |63|62|61|60|59|58|57|56|55|54|53|52|51|50|49|48|47|46|45|44|43|42|41|40|39|38|37|36|35|34|33|32| + ------------------------------------------------------------------------------------------------- +Word 0 | Format | HCID | padrow | col | position | + ------------------------------------------------------------------------------------------------- + |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| + ------------------------------------------------------------------------------------------------- +Word 0 | slope | Q0 | Q1 | Q2 | + ------------------------------------------------------------------------------------------------- +*/ +class Tracklet64 +{ +// bit masks for the above raw data; +static constexpr uint64_t formatmask= 0xf000000000000000; //0-1079 +static constexpr uint64_t hcidmask = 0x0ffe000000000000; //0-1079 +static constexpr uint64_t padrowmask= 0x0001e00000000000; //0-3; +static constexpr uint64_t colmask = 0x0000180000000000; +static constexpr uint64_t posmask = 0x000007ff00000000; +static constexpr uint64_t slopemask = 0x00000000ff000000; +static constexpr uint64_t Q0mask = 0x0000000000ff0000; +static constexpr uint64_t Q1mask = 0x000000000000ff00; +static constexpr uint64_t Q2mask = 0x00000000000000ff; +static constexpr uint64_t PIDmask = 0x0000000000ffffff; +//bit shifts for the above raw data +static constexpr uint64_t formatbs =60; +static constexpr uint64_t hcidbs =49; +static constexpr uint64_t padrowbs =45; +static constexpr uint64_t colbs =43; +static constexpr uint64_t posbs=32; +static constexpr uint64_t slopebs =24; +static constexpr uint64_t PIDbs = 0; +static constexpr uint64_t Q0bs=16; +static constexpr uint64_t Q1bs=8; +static constexpr uint64_t Q2bs=0; + public: + Tracklet64()=default; + Tracklet64(uint64_t trackletword) { mtrackletWord=trackletword;} + Tracklet64(const Tracklet64& rhs); + Tracklet64(uint64_t format,uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, + uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0){ + mtrackletWord=((format << formatbs)&formatmask) + ((hcid << hcidbs)&hcidmask) + + ((padrow << padrowbs)&padrowmask) + ((col<<colbs)&colmask) + ((position<<posbs)&posmask) + + ((slope<<slopebs)&slopemask) + ((Q2<<Q2bs)&Q2mask) + ((Q1<<Q1bs)&Q1mask) + ((Q0<<Q0bs)&Q0mask); + } + ~Tracklet64() = default; + + Tracklet64& operator=(const Tracklet64& o) { return *this; } + + //TODO convert to the actual number regarding compliments. + // ----- Getters for contents of tracklet word ----- + uint64_t getHCID() const{ return ((mtrackletWord&hcidmask)>>hcidbs);}; // no units + uint64_t getPadRow() const { return ((mtrackletWord&padrowmask)>>padrowbs);}; // in units of ?? + uint64_t getPosition() const{ return ((mtrackletWord&posmask)>>posbs);}; // in units of 0.02 pads [10bits] .. -10.22 to 10.22 + uint64_t getSlope() const{ return ((mtrackletWord&slopemask)>>slopebs);}; // in units of -127 .. 127 + uint64_t getPID() const{ return ((mtrackletWord&PIDmask));}; // in units of counts all 3 together + uint64_t getQ0() const{ return ((mtrackletWord&Q0mask)>>Q0bs);}; // in units of counts all 3 together + uint64_t getQ1() const{ return ((mtrackletWord&Q1mask)>>Q1bs);}; // in units of counts all 3 together + uint64_t getQ2() const{ return ((mtrackletWord&Q2mask)>>Q2bs);}; // in units of counts all 3 together + + uint64_t buildTrackletWord(uint64_t format,uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0){ + mtrackletWord=((format << formatbs)&formatmask) + ((hcid << hcidbs)&hcidmask) + ((padrow << padrowbs)&padrowmask) + ((col<<colbs)&colmask) + ((position<<posbs)&posmask) + ((slope<<slopebs)&slopemask) + ((Q2<<Q2bs)&Q2mask) + ((Q1<<Q1bs)&Q1mask) + ((Q0<<Q0bs)&Q0mask); + return 0; + } + uint64_t setTrackletWord(uint64_t trackletword) { + mtrackletWord=trackletword; + return 0; + } + // ----- Getters for tracklet information ----- + // TODO figure out how to get MCM and ROB from hcid, chipindex and row. + int getMCM() const { return 1; } + int getROB() const { return 1; } + + // ----- Getters for offline corresponding values ----- + int getDetector() const { return getHCID() / 2; } + + uint64_t getTrackletWord() const{ return mtrackletWord;}; + uint32_t getTrackletWord32() const; + +// void setDetector(int id) { uint64_t hcid= 2* id; uint64_t side=1;mtrackletWord = hcid << hcidbs + ; } + // void setHCId(int id) { mHCId = id; } + // TODO row and mcm to chipindex and z mapping. + uint64_t setQ0(int charge) { mtrackletWord |= ((charge<<Q0bs) & Q0mask); return mtrackletWord;} + uint64_t setQ1(int charge) { mtrackletWord |= ((charge<<Q1bs) & Q1mask); return mtrackletWord;} + uint64_t setQ2(int charge) { mtrackletWord |= ((charge<<Q2bs) & Q2mask); return mtrackletWord;} + void setPID(uint64_t pid) { mtrackletWord |= ((((uint64_t)pid)<<PIDbs) & PIDmask); } // set the entire pid area of the trackletword, all the 3 Q's + void setPosition(uint64_t position) { mtrackletWord |= ((((uint64_t)position)<<posbs) & posmask);} + void setSlope(uint64_t slope) { mtrackletWord |= ((((uint64_t)slope)<<slopebs) & slopemask);} + + + protected: + uint64_t mtrackletWord; // the 64 bit word holding all the tracklet information for run3. + private: + // Tracklet& operator=(const Tracklet &rhs); // not implemented + ClassDefNV(Tracklet64, 1); +}; + +//using Tracklet = RawTracklet64; + +} //namespace trd +} //namespace o2 +#endif diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index 30b2926d3845b..049ed4189ba8a 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -15,6 +15,11 @@ #pragma link off all functions; #pragma link C++ class o2::trd::TriggerRecord + ; +#pragma link C++ struct o2::trd::HalfCRUHeader + ; +#pragma link C++ struct o2::trd::HalfChamberHeader + ; +#pragma link C++ struct o2::trd::MCMRawDataHeader + ; +#pragma link C++ struct o2::trd::TrapRawTracklet + ; +#pragma link C++ class o2::trd::Tracklet64 + ; #pragma link C++ class std::vector < o2::trd::TriggerRecord > +; #endif diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx new file mode 100644 index 0000000000000..0490e7c0aa22e --- /dev/null +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -0,0 +1,22 @@ +// 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 <iostream> +//#include "DataFormatsTRD/RawData.h" + +namespace o2 +{ + +namespace trd +{ + + +} // namespace trd +} // namespace o2 diff --git a/DataFormats/Detectors/TRD/src/Tracklet64.cxx b/DataFormats/Detectors/TRD/src/Tracklet64.cxx new file mode 100644 index 0000000000000..f30bedf94c995 --- /dev/null +++ b/DataFormats/Detectors/TRD/src/Tracklet64.cxx @@ -0,0 +1,22 @@ +// 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 <iostream> +//#include "DataFormatsTRD/Tracklet64.h" + +namespace o2 +{ + +namespace trd +{ + + +} // namespace trd +} // namespace o2 diff --git a/Detectors/TRD/base/CMakeLists.txt b/Detectors/TRD/base/CMakeLists.txt index bb97e82247ef9..a82cf6475a6eb 100644 --- a/Detectors/TRD/base/CMakeLists.txt +++ b/Detectors/TRD/base/CMakeLists.txt @@ -78,3 +78,10 @@ o2_add_test(Geometry ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage LABELS trd ) +o2_add_test(RawData + COMPONENT_NAME trd + PUBLIC_LINK_LIBRARIES O2::TRDBase O2::DataFormatsTRD + SOURCES test/testRawData.cxx + ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage + LABELS trd + ) diff --git a/Detectors/TRD/base/test/testRawData.cxx b/Detectors/TRD/base/test/testRawData.cxx new file mode 100644 index 0000000000000..dbcf855905cb4 --- /dev/null +++ b/Detectors/TRD/base/test/testRawData.cxx @@ -0,0 +1,98 @@ +// 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 testTRDDataFormats.cxx +/// \brief This task tests the data format structs +/// \author Sean Murray, murrays@cern.ch + +#define BOOST_TEST_MODULE Test TRD_RawDataHeader +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include <cstdlib> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/Tracklet64.h" + +namespace o2 +{ +namespace trd +{ + +/// \brief Test the data header struct sizes +// +/// check the bit manipulations +BOOST_AUTO_TEST_CASE(TRDRawDataHeaderSizes) +{ + //check the sizes of header structs due to packing + BOOST_CHECK_EQUAL(sizeof(o2::trd::TrapRawTracklet),4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfChamberHeader),4); BOOST_CHECK_EQUAL(sizeof(o2::trd::MCMRawDataHeader),4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfCRUHeader),64); +} + + +BOOST_AUTO_TEST_CASE(TRDRawDataHeaderInternals) +{ + o2::trd::TrapRawTracklet tracklet; + o2::trd::HalfChamberHeader halfchamberheader; + o2::trd::HalfCRUHeader halfcruheader; + halfcruheader.word02[0] = 0x102; + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags,2); + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size,1); + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags,o2::trd::getlinkerrorflag(halfcruheader,0)); + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size,o2::trd::getlinkdatasize(halfcruheader,0)); +//ab is size + halfcruheader.word02[2] = 0xffffaa0000000000; + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size,0xffff); + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags,0xaa); + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags,o2::trd::getlinkerrorflag(halfcruheader,7)); + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size,o2::trd::getlinkdatasize(halfcruheader,7)); + halfcruheader.word3 = (0x222LL)<<40; //bc is at 0x000ffff000000000 + BOOST_CHECK_EQUAL(halfcruheader.BunchCrossing,0x222); + halfcruheader.word3 = 0x7700000000; //headerversion is at 0x00ff0000000 + BOOST_CHECK_EQUAL(halfcruheader.HeaderVersion,119); + halfcruheader.word57[0] = 0x345869faba; + halfcruheader.word57[2] = 0xaaade1277; + + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags,0xba); + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size,0x69fa); + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags,o2::trd::getlinkerrorflag(halfcruheader,8)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size,o2::trd::getlinkdatasize(halfcruheader,8)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags,0x58); + BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size,0x34); +//ab is size + BOOST_CHECK_EQUAL(halfcruheader.linksB[5].size,0x1277); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size,0xaaa); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags,0xde); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags,o2::trd::getlinkerrorflag(halfcruheader,14)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size,o2::trd::getlinkdatasize(halfcruheader,14)); + //now test the boundary crossing of the int64_t + halfcruheader.word02[0]= (uint64_t)0x1000000000000000; + halfcruheader.word02[1]= (uint64_t)0xa00b000c000d0ebf; + BOOST_CHECK_EQUAL(halfcruheader.linksA[2].size,0xbf10); // check a size that spans a 64bit word. + o2::trd::MCMRawDataHeader mcmrawdataheader; + mcmrawdataheader.word=0xa0000000; + BOOST_CHECK_EQUAL(mcmrawdataheader.padrow,10); + mcmrawdataheader.word=0x0c000000; + BOOST_CHECK_EQUAL(mcmrawdataheader.col,3); + mcmrawdataheader.word=0x03fc0000; + BOOST_CHECK_EQUAL(mcmrawdataheader.pid2,0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 + mcmrawdataheader.word=0x03fc; + BOOST_CHECK_EQUAL(mcmrawdataheader.pid0,0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 + //check tracklet + tracklet.word=0xffc00000; + BOOST_CHECK_EQUAL((uint32_t)tracklet.pos,0x3ff); + +} +} // namespace trd +} // namespace o2 diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h b/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h new file mode 100644 index 0000000000000..3da7db0359149 --- /dev/null +++ b/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h @@ -0,0 +1,54 @@ +// 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 Tracklet2Raw.h +// /// \brief converts tracklets raw stream to raw data format +// // murrays@cern.ch +// +// +#ifndef ALICEO2_TRD_TRACKLETS2RAW_H +#define ALICEO2_TRD_TRACKLETS2RAW_H + + +#include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/TrackletRawData.h" + +namespace o2 +{ +namespace trd +{ + +class Tracklets2Raw +{ + + static constexpr int NChannels; + static constexpr int NLinksPerCRU=30; + static constexpr int NCRU=36; + + public: + Tracklets2Raw() = default; + Tracklets2Raw(const std::string& outDir, const std::string& fileRawTrackletsName); + void readTracklets(const std::string& outDir, const std::string& fileRawTrackletsName); + + void converTracklets(o2::trd::TrackletRaw rawTracklets, gsl::span<2::trd::TriggerRecord const & mTriggerRecord); + + + private: + const o2::raw::HBFUtils& mSampler = o2::raw::HBFUtils::Instance(); + o2::raw::RawFileWriter mWriter("TRD"); + bool mOutputPerLink = true; + uint32_t mLinkId =0; + uint32_t mCRUId = 0; + uint32_t mEndPointId = 0; + uint32_t mFeeId =0; +}; +} // end trd namespace +} // end o2 namespace +#endif diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index cf24778285715..38ef569246b0a 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -886,17 +886,6 @@ int TrapSimulator::getCol(int adc) return col; } -int TrapSimulator::packData(std::vector<uint32_t>& buf) -{ - // - //given the, up to 3 tracklets, pack them according to the define data format. - // - //TODO this is left blank so that the dataformats etc. can come in a seperate PR - //to keep different work seperate. - LOG(fatal) << "Called packData of TrapSimualtor ... why? I am going to die, till next pr."; - return 1; -} - int TrapSimulator::produceRawStream(std::vector<uint32_t>& buf, unsigned int iEv) const { // @@ -1004,8 +993,28 @@ int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) // A MCM Header followed by at most 3 tracklet words. // Although a little confusingly some of the tracklet data is in the header. - numberWordsWritten = packData(buf); +// numberWordsWritten = packData(buf); + // + //given the, up to 3 tracklets, pack them according to the define data format. + // + // produce a MCM Header, then the 1 to 3 tracklet words. +// + std::array<uint32_t,3> pid; +// std::array<TrackletRawDataHeader,3> tracklet; +// MCMRawDataHeader mcmheader; +// TrackletRawDataHeader tracklet[3]; // at most 3 tracklets +// mcmheader.checkbits=0x3; +// mcmheader.y=; +// mcmheader z=; +/* for(auto track mTrackletArray) + { + tracklet[].checkbit=0x1; + tracklet[].pid=0x1; + tracklet[].dy=0x1; + tracklet[].y=0x1; + mcmheader.pid[]=0x1; // part of the tracklet pid is stored in the chip header. +*/ return numberWordsWritten; } From 496c1ccc7aea4de0b687cdceb023ee24d5c0fad4 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 23 Jul 2020 14:59:43 +0200 Subject: [PATCH 0161/1751] clang formatting --- .../TRD/include/DataFormatsTRD/RawData.h | 387 +++++++++--------- .../TRD/include/DataFormatsTRD/Tracklet64.h | 125 +++--- .../Detectors/TRD/src/DataFormatsTRDLinkDef.h | 2 +- DataFormats/Detectors/TRD/src/RawData.cxx | 1 - DataFormats/Detectors/TRD/src/Tracklet64.cxx | 1 - Detectors/TRD/base/test/testRawData.cxx | 83 ++-- .../include/TRDSimulation/Tracklets2Raw.h | 44 +- .../TRD/simulation/src/TrapSimulator.cxx | 20 +- 8 files changed, 336 insertions(+), 327 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h index 25ca0eab61a13..c89491086a7c4 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -17,15 +17,16 @@ #include <fstream> #include "fairlogger/Logger.h" /// \class TRDRDH -/// \brief Header for TRD raw data header +/// \brief Header for TRD raw data header // this is the header added by the CRU -namespace o2{ -namespace trd{ - -struct HalfCRUHeader +namespace o2 +{ +namespace trd { -/* Half cru header + +struct HalfCRUHeader { + /* Half cru header 64 bits is too wide, hence reduce to 32 to make it readable. |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| @@ -100,123 +101,118 @@ Word 7 | link 13 datasize | link 14 dat -------------------------------------------------------------------------------------------------- */ - union{ + union { uint64_t word02[3]; - struct{ - uint64_t errorflags : 8; - uint64_t size : 16; - }__attribute__((__packed__)) linksA[8]; - }; - union{ - uint64_t word3=0x0; - //first word * + struct { + uint64_t errorflags : 8; + uint64_t size : 16; + } __attribute__((__packed__)) linksA[8]; + }; + union { + uint64_t word3 = 0x0; + //first word * // uint64_t: 0x0000000000000000 // | - | || - // | | | |- 0..7 Event type + // | | | |- 0..7 Event type // | | | -- 8..11 Stop bit - // | | ------ 12..23 bunch crossing id - // | -------- 24..31 TRD Header version + // | | ------ 12..23 bunch crossing id + // | -------- 24..31 TRD Header version // --------------- 32..63 reserveda - struct{ - uint64_t reserveda :32; // - uint64_t HeaderVersion : 8; // TRD Header Version - uint64_t BunchCrossing :12; // bunch crossing - uint64_t StopBit : 4; // 8 .. 11 stop bit 0x1 if TRD packet is last data packet of trigger, else 0x0 TODO why 4 bits if only using 1? - uint64_t EventType : 8; // bit 0..7 event type of the data. Trigger bits from TTC-PON message, distinguish physics from calibration events. - }__attribute__((__packed__)); - }; - union{ - uint64_t word4=0x0; - struct{ - uint64_t reservedb; - }__attribute__((__packed__)); - }; - union{ - uint64_t word57[3]; - struct{ - uint64_t errorflags : 8; - uint64_t size : 16; - }__attribute__((__packed__)) linksB[8]; // although this is 8 dont use index 0 as its part of reserved. - }; + struct { + uint64_t reserveda : 32; // + uint64_t HeaderVersion : 8; // TRD Header Version + uint64_t BunchCrossing : 12; // bunch crossing + uint64_t StopBit : 4; // 8 .. 11 stop bit 0x1 if TRD packet is last data packet of trigger, else 0x0 TODO why 4 bits if only using 1? + uint64_t EventType : 8; // bit 0..7 event type of the data. Trigger bits from TTC-PON message, distinguish physics from calibration events. + } __attribute__((__packed__)); + }; + union { + uint64_t word4 = 0x0; + struct { + uint64_t reservedb; + } __attribute__((__packed__)); + }; + union { + uint64_t word57[3]; + struct { + uint64_t errorflags : 8; + uint64_t size : 16; + } __attribute__((__packed__)) linksB[8]; // although this is 8 dont use index 0 as its part of reserved. + }; }; /// \structure HalfChamberHeader /// \brief Header for each half chamber // Coming before all other tracklet data, a single tracklet word as a header for its half chamber -struct HalfChamberHeader -{ - union{ - // 10987654321098765432109876543210 - // uint32_t: 00000000000000000000000000000000 - // cccccccccccccccc iiiiiiiiiii - // ffff| y| - // | | |------ 0-10 half chamber id - // | | ------------- 11 always 0x1 - // | ----------------------------- 12-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 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 format : 4; - // 0 baseline PID 3 time slices, 7 bit each - // 1 DO NOT USE ! reserved for tracklet end marker disambiguation - // 14 Tracklet test-pattern mode - // 15 Reserved for testing - }__attribute__((__packed__)); - }; +struct HalfChamberHeader { + union { + // 10987654321098765432109876543210 + // uint32_t: 00000000000000000000000000000000 + // cccccccccccccccc iiiiiiiiiii + // ffff| y| + // | | |------ 0-10 half chamber id + // | | ------------- 11 always 0x1 + // | ----------------------------- 12-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 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 format : 4; + // 0 baseline PID 3 time slices, 7 bit each + // 1 DO NOT USE ! reserved for tracklet end marker disambiguation + // 14 Tracklet test-pattern mode + // 15 Reserved for testing + } __attribute__((__packed__)); + }; }; /// \structure MCMRawDataHeader /// \brief Header for MCM tracklet data outuput // This constitutes the "4x32" bits of information from a single MCM, MCMRawDataHeader and 1-3 TrapRawTracklet. -struct MCMRawDataHeader -{ - //first word * - // 10987654321098765432109876543210 - // uint32_t: 00000000000000000000000000000000 - // 1zzzz pppppppp pppppppp 1 - // || yy| pppppppp | ccc-- 0..1 check bits - // || | | | ------------ 2-9 pid for tracklet 3 second part - // || | | --------------------- 10-17 pid for tracklet 2 second part - // || | ---------------------------- 18-25 pid for tracklet 1 second part - // || ------------------------------ 26-27 coly - // |---------------------------------- 28-31 padrow - //TODO need to check endianness, I have a vague memory the trap chip has different endianness to x86. - union{ - uint32_t word; - struct{ - uint32_t oneb : 1; // - uint32_t pid0:8 ; // 3 parts of pid for each tracklet - uint32_t pid1:8 ; // 3 parts of pid for each tracklet - uint32_t pid2:8 ; // 3 parts of pid for each tracklet - uint32_t col : 2; // 2 bits for position in pad direction. - uint32_t padrow : 4; // padrow,z coordinate for chip. - uint32_t onea : 1; // - }__attribute__((__packed__)); - }; - +struct MCMRawDataHeader { + //first word * + // 10987654321098765432109876543210 + // uint32_t: 00000000000000000000000000000000 + // 1zzzz pppppppp pppppppp 1 + // || yy| pppppppp | ccc-- 0..1 check bits + // || | | | ------------ 2-9 pid for tracklet 3 second part + // || | | --------------------- 10-17 pid for tracklet 2 second part + // || | ---------------------------- 18-25 pid for tracklet 1 second part + // || ------------------------------ 26-27 coly + // |---------------------------------- 28-31 padrow + //TODO need to check endianness, I have a vague memory the trap chip has different endianness to x86. + union { + uint32_t word; + struct { + uint32_t oneb : 1; // + uint32_t pid0 : 8; // 3 parts of pid for each tracklet + uint32_t pid1 : 8; // 3 parts of pid for each tracklet + uint32_t pid2 : 8; // 3 parts of pid for each tracklet + uint32_t col : 2; // 2 bits for position in pad direction. + uint32_t padrow : 4; // padrow,z coordinate for chip. + uint32_t onea : 1; // + } __attribute__((__packed__)); + }; }; // \structure TrapRawTracklet. // \brief Raw Data of a tracklet, part is how ever in the MCM Header hence both are grouped together in the same file - struct TrapRawTracklet{ // This is a bad name as part of the tracklet data is in the MCMHeader. - union{ - uint32_t word; - struct{ - uint8_t checkbit : 1; // The size of the data for this link - uint16_t pid : 15 ; // Particle Identity - uint16_t slope : 6 ; // Deflection angle of tracklet - uint16_t pos : 10 ; // Position of tracklet, signed 10 bits, granularity 0.02 pad widths, -10.22 to +10.22, relative to centre of pad 10 - }__attribute__((__packed__)); - }; - }; - - +struct TrapRawTracklet { // This is a bad name as part of the tracklet data is in the MCMHeader. + union { + uint32_t word; + struct { + uint8_t checkbit : 1; // The size of the data for this link + uint16_t pid : 15; // Particle Identity + uint16_t slope : 6; // Deflection angle of tracklet + uint16_t pos : 10; // Position of tracklet, signed 10 bits, granularity 0.02 pad widths, -10.22 to +10.22, relative to centre of pad 10 + } __attribute__((__packed__)); + }; +}; /* std::vector<uint32_t> getPID(char *rawdata, int tracklet) @@ -279,71 +275,73 @@ uint32_t getSlope(const *rawdata, int tracklet) due to the interplay of MCMRawDataHeader and TrapRawTracklet come back to this. TODO */ - -uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data=true) +uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data = true) { - //TODO this needs some more ellaborate testing. I got the packing to work so for now, - // its a question of unpacking info in line 88 and 89. - uint32_t info=0; - if(link>14) return 0xffffffff; - - char *words; - if(link<8) words = (char*)&cruhead.word02[0]; - if(link<15) words= (char*)&cruhead.word57[0]; - uint32_t byteoffset=link*3; // each link [size+erroflags] is 24 bits, so 3 bytes. - if(data) info = ((words[byteoffset+1] )<< 8 )+ (words[byteoffset+2]); - else info=words[byteoffset]; - - return info; + //TODO this needs some more ellaborate testing. I got the packing to work so for now, + // its a question of unpacking info in line 88 and 89. + uint32_t info = 0; + if (link > 14) + return 0xffffffff; + + char* words; + if (link < 8) + words = (char*)&cruhead.word02[0]; + if (link < 15) + words = (char*)&cruhead.word57[0]; + uint32_t byteoffset = link * 3; // each link [size+erroflags] is 24 bits, so 3 bytes. + if (data) + info = ((words[byteoffset + 1]) << 8) + (words[byteoffset + 2]); + else + info = words[byteoffset]; + + return info; } uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link) { - uint32_t errorflags=0; - if(link<8){ - //dealing with word0-2 - errorflags= cruhead.linksA[link].errorflags; - } - else { - if(link<16){ - errorflags=cruhead.linksB[link-8+1].errorflags; // link 0 [actually 9] is in fact the end part of reserved. - - } - else std::cout << "error link=" << link << " not in range 0-14" << std::endl; - } - return errorflags; + uint32_t errorflags = 0; + if (link < 8) { + //dealing with word0-2 + errorflags = cruhead.linksA[link].errorflags; + } else { + if (link < 16) { + errorflags = cruhead.linksB[link - 8 + 1].errorflags; // link 0 [actually 9] is in fact the end part of reserved. + + } else + std::cout << "error link=" << link << " not in range 0-14" << std::endl; + } + return errorflags; } uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link) { - //return number 32 byte blocks for the link 3x64bit ints. - uint32_t size=0; - if(link<8){ - size= (cruhead.linksA[link].size); - } - else { - if(link<16){ // link 0 is part of reserved - size=cruhead.linksB[link-8+1].size; - - } - else std::cout << "error link=" << link << " not in range 0-14" << std::endl; - } - return size; + //return number 32 byte blocks for the link 3x64bit ints. + uint32_t size = 0; + if (link < 8) { + size = (cruhead.linksA[link].size); + } else { + if (link < 16) { // link 0 is part of reserved + size = cruhead.linksB[link - 8 + 1].size; + + } else + std::cout << "error link=" << link << " not in range 0-14" << std::endl; + } + return size; } -uint32_t getlinkerrorflags(const HalfCRUHeader& cruheader, std::array<uint32_t,15>& linkerrorflags ) +uint32_t getlinkerrorflags(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linkerrorflags) { - for(uint32_t link=0;link<15;link++){ - linkerrorflags[link] = getlinkerrorflag(cruheader,link); - } - return 0; + for (uint32_t link = 0; link < 15; link++) { + linkerrorflags[link] = getlinkerrorflag(cruheader, link); + } + return 0; } -uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t,15>& linksizes ) +uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linksizes) { - for(uint32_t link=0;link<15;link++){ - linksizes[link] = getlinkdatasize(cruheader,link); - } - return 0; + for (uint32_t link = 0; link < 15; link++) { + linksizes[link] = getlinkdatasize(cruheader, link); + } + return 0; } /* @@ -352,81 +350,82 @@ uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t,15 std::ostream& operator<<(std::ostream& stream, const HalfChamberHeader halfchamberheader) { - stream << "HalfChamberHeader : " << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; - return stream; + stream << "HalfChamberHeader : " << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; + return stream; } std::ostream& operator<<(std::ostream& stream, const TrapRawTracklet& tracklet) { - // make a pretty output of the tracklet. - stream << "TrapRawTracklet: pos=" << tracklet.pos << "::slope=" << tracklet.slope <<"::pid="<< tracklet.pid <<"::checkbit=" << tracklet.checkbit << std::endl; - return stream; + // make a pretty output of the tracklet. + stream << "TrapRawTracklet: pos=" << tracklet.pos << "::slope=" << tracklet.slope << "::pid=" << tracklet.pid << "::checkbit=" << tracklet.checkbit << std::endl; + return stream; } void printTrapRawTracklet(o2::trd::TrapRawTracklet& tracklet) { - LOGF(INFO,"TrapRawTracklet: "); + LOGF(INFO, "TrapRawTracklet: "); } void printMCMHeader(o2::trd::MCMRawDataHeader& mcmhead) { - LOGF(INFO,"MCMRawHeader: 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d",mcmhead.onea,mcmhead.padrow,mcmhead.col,mcmhead.pid2,mcmhead.pid1,mcmhead.pid0,mcmhead.oneb); + LOGF(INFO, "MCMRawHeader: 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d", mcmhead.onea, mcmhead.padrow, mcmhead.col, mcmhead.pid2, mcmhead.pid1, mcmhead.pid0, mcmhead.oneb); } -std::ostream& operator<<(std::ostream& stream, const MCMRawDataHeader& mcmhead) +std::ostream& operator<<(std::ostream& stream, const MCMRawDataHeader& mcmhead) { - // make a pretty output of the mcm header. - // stream << "MCMRawHeader:" << mcmhead.checkbits << "::" << (mcmhead.pid&0xfff000000) << ":"<< (mcmhead.pid&0xfff000) << ":"<< (mcmhead.pid&0xfff) << std::endl; - stream << "MCMRawHeader:" << mcmhead.onea<<"::"<< mcmhead.pid2 << ":"<< mcmhead.pid1 << ":"<< mcmhead.pid0 << "::"<<mcmhead.oneb<< std::endl; - return stream; + // make a pretty output of the mcm header. + // stream << "MCMRawHeader:" << mcmhead.checkbits << "::" << (mcmhead.pid&0xfff000000) << ":"<< (mcmhead.pid&0xfff000) << ":"<< (mcmhead.pid&0xfff) << std::endl; + stream << "MCMRawHeader:" << mcmhead.onea << "::" << mcmhead.pid2 << ":" << mcmhead.pid1 << ":" << mcmhead.pid0 << "::" << mcmhead.oneb << std::endl; + return stream; } - void printHalfChamber(o2::trd::HalfChamberHeader& halfchamber) { - LOGF(INFO,"HCID : %d MCLK: %d Format: %d Always1:%d",halfchamber.HCID,halfchamber.MCLK,halfchamber.format, halfchamber.one); + LOGF(INFO, "HCID : %d MCLK: %d Format: %d Always1:%d", halfchamber.HCID, halfchamber.MCLK, halfchamber.format, halfchamber.one); } void dumpHalfChamber(o2::trd::HalfChamberHeader& halfchamber) { - LOGF(INFO,"HalfChamber : 0x%08x",halfchamber.word); + LOGF(INFO, "HalfChamber : 0x%08x", halfchamber.word); } void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) { - std::array<uint32_t,15> sizes; - std::array<uint32_t,15> errorflags; - getlinkdatasizes(halfcru,sizes); - getlinkerrorflags(halfcru,errorflags); - LOGF(INFO, "V:%d BC:%d SB:%d EType:%d",halfcru.HeaderVersion,halfcru.BunchCrossing,halfcru.StopBit,halfcru.EventType); - for(int i=0;i<15;i++) LOGF(INFO,"Link %d size: %ul eflag: 0x%02x",i,sizes[i],errorflags[i]); + std::array<uint32_t, 15> sizes; + std::array<uint32_t, 15> errorflags; + getlinkdatasizes(halfcru, sizes); + getlinkerrorflags(halfcru, errorflags); + LOGF(INFO, "V:%d BC:%d SB:%d EType:%d", halfcru.HeaderVersion, halfcru.BunchCrossing, halfcru.StopBit, halfcru.EventType); + for (int i = 0; i < 15; i++) + LOGF(INFO, "Link %d size: %ul eflag: 0x%02x", i, sizes[i], errorflags[i]); } void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) { - std::array<uint32_t,16> raw{}; - memcpy(&raw[0],&halfcru,sizeof(halfcru)); - for(int i=0;i<4;i++){ - int index=4*i; - LOGF(INFO,"[1/2CRUHeader %d] 0x%08x 0x%08x 0x%08x 0x%08x",i,raw[index+3],raw[index+2],raw[index+1],raw[index+0]); - } + std::array<uint32_t, 16> raw{}; + memcpy(&raw[0], &halfcru, sizeof(halfcru)); + for (int i = 0; i < 4; i++) { + int index = 4 * i; + LOGF(INFO, "[1/2CRUHeader %d] 0x%08x 0x%08x 0x%08x 0x%08x", i, raw[index + 3], raw[index + 2], raw[index + 1], raw[index + 0]); + } } - std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) // make a pretty output of the header. { - stream << std::hex; - stream << "EventType : " << halfcru.EventType << std::endl; - stream << "StopBit : " << halfcru.StopBit << std::endl; - stream << "BunchCrossing : " << halfcru.BunchCrossing << std::endl; - stream << "HeaderVersion : " << halfcru.HeaderVersion << std::endl; - stream << "link sizes : "; - for(int link=0;link<15;link++)stream << link<<":"<<std::hex << std::setw(4) << getlinkdatasize(halfcru,link) <<","; - stream << std::endl; - stream << "link errorflags : "; - for(int link=0;link<15;link++)stream << link<<":"<<std::hex << std::setw(2) << getlinkerrorflag(halfcru,link) <<","; - stream << std::endl; - stream << "0x" << halfcru.word02[0] << " 0x" << halfcru.word02[1] << " 0x" << halfcru.word02[2] << " 0x" << halfcru.word3 << " 0x" << halfcru.word4 << " 0x" << halfcru.word57[0] << " 0x" << halfcru.word57[1] << " 0x" << halfcru.word57[2]<< std:: endl; - return stream; + stream << std::hex; + stream << "EventType : " << halfcru.EventType << std::endl; + stream << "StopBit : " << halfcru.StopBit << std::endl; + stream << "BunchCrossing : " << halfcru.BunchCrossing << std::endl; + stream << "HeaderVersion : " << halfcru.HeaderVersion << std::endl; + stream << "link sizes : "; + for (int link = 0; link < 15; link++) + stream << link << ":" << std::hex << std::setw(4) << getlinkdatasize(halfcru, link) << ","; + stream << std::endl; + stream << "link errorflags : "; + for (int link = 0; link < 15; link++) + stream << link << ":" << std::hex << std::setw(2) << getlinkerrorflag(halfcru, link) << ","; + stream << std::endl; + stream << "0x" << halfcru.word02[0] << " 0x" << halfcru.word02[1] << " 0x" << halfcru.word02[2] << " 0x" << halfcru.word3 << " 0x" << halfcru.word4 << " 0x" << halfcru.word57[0] << " 0x" << halfcru.word57[1] << " 0x" << halfcru.word57[2] << std::endl; + return stream; } } // namespace trd diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index 370f5c33ef11e..5c42a1b97f1b0 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -46,37 +46,39 @@ Word 0 | slope | Q0 | Q1 */ class Tracklet64 { -// bit masks for the above raw data; -static constexpr uint64_t formatmask= 0xf000000000000000; //0-1079 -static constexpr uint64_t hcidmask = 0x0ffe000000000000; //0-1079 -static constexpr uint64_t padrowmask= 0x0001e00000000000; //0-3; -static constexpr uint64_t colmask = 0x0000180000000000; -static constexpr uint64_t posmask = 0x000007ff00000000; -static constexpr uint64_t slopemask = 0x00000000ff000000; -static constexpr uint64_t Q0mask = 0x0000000000ff0000; -static constexpr uint64_t Q1mask = 0x000000000000ff00; -static constexpr uint64_t Q2mask = 0x00000000000000ff; -static constexpr uint64_t PIDmask = 0x0000000000ffffff; -//bit shifts for the above raw data -static constexpr uint64_t formatbs =60; -static constexpr uint64_t hcidbs =49; -static constexpr uint64_t padrowbs =45; -static constexpr uint64_t colbs =43; -static constexpr uint64_t posbs=32; -static constexpr uint64_t slopebs =24; -static constexpr uint64_t PIDbs = 0; -static constexpr uint64_t Q0bs=16; -static constexpr uint64_t Q1bs=8; -static constexpr uint64_t Q2bs=0; + // bit masks for the above raw data; + static constexpr uint64_t formatmask = 0xf000000000000000; //0-1079 + static constexpr uint64_t hcidmask = 0x0ffe000000000000; //0-1079 + static constexpr uint64_t padrowmask = 0x0001e00000000000; //0-3; + static constexpr uint64_t colmask = 0x0000180000000000; + static constexpr uint64_t posmask = 0x000007ff00000000; + static constexpr uint64_t slopemask = 0x00000000ff000000; + static constexpr uint64_t Q0mask = 0x0000000000ff0000; + static constexpr uint64_t Q1mask = 0x000000000000ff00; + static constexpr uint64_t Q2mask = 0x00000000000000ff; + static constexpr uint64_t PIDmask = 0x0000000000ffffff; + //bit shifts for the above raw data + static constexpr uint64_t formatbs = 60; + static constexpr uint64_t hcidbs = 49; + static constexpr uint64_t padrowbs = 45; + static constexpr uint64_t colbs = 43; + static constexpr uint64_t posbs = 32; + static constexpr uint64_t slopebs = 24; + static constexpr uint64_t PIDbs = 0; + static constexpr uint64_t Q0bs = 16; + static constexpr uint64_t Q1bs = 8; + static constexpr uint64_t Q2bs = 0; + public: - Tracklet64()=default; - Tracklet64(uint64_t trackletword) { mtrackletWord=trackletword;} + Tracklet64() = default; + Tracklet64(uint64_t trackletword) { mtrackletWord = trackletword; } Tracklet64(const Tracklet64& rhs); - Tracklet64(uint64_t format,uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, - uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0){ - mtrackletWord=((format << formatbs)&formatmask) + ((hcid << hcidbs)&hcidmask) + - ((padrow << padrowbs)&padrowmask) + ((col<<colbs)&colmask) + ((position<<posbs)&posmask) + - ((slope<<slopebs)&slopemask) + ((Q2<<Q2bs)&Q2mask) + ((Q1<<Q1bs)&Q1mask) + ((Q0<<Q0bs)&Q0mask); + Tracklet64(uint64_t format, uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, + uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0) + { + mtrackletWord = ((format << formatbs) & formatmask) + ((hcid << hcidbs) & hcidmask) + + ((padrow << padrowbs) & padrowmask) + ((col << colbs) & colmask) + ((position << posbs) & posmask) + + ((slope << slopebs) & slopemask) + ((Q2 << Q2bs) & Q2mask) + ((Q1 << Q1bs) & Q1mask) + ((Q0 << Q0bs) & Q0mask); } ~Tracklet64() = default; @@ -84,22 +86,24 @@ static constexpr uint64_t Q2bs=0; //TODO convert to the actual number regarding compliments. // ----- Getters for contents of tracklet word ----- - uint64_t getHCID() const{ return ((mtrackletWord&hcidmask)>>hcidbs);}; // no units - uint64_t getPadRow() const { return ((mtrackletWord&padrowmask)>>padrowbs);}; // in units of ?? - uint64_t getPosition() const{ return ((mtrackletWord&posmask)>>posbs);}; // in units of 0.02 pads [10bits] .. -10.22 to 10.22 - uint64_t getSlope() const{ return ((mtrackletWord&slopemask)>>slopebs);}; // in units of -127 .. 127 - uint64_t getPID() const{ return ((mtrackletWord&PIDmask));}; // in units of counts all 3 together - uint64_t getQ0() const{ return ((mtrackletWord&Q0mask)>>Q0bs);}; // in units of counts all 3 together - uint64_t getQ1() const{ return ((mtrackletWord&Q1mask)>>Q1bs);}; // in units of counts all 3 together - uint64_t getQ2() const{ return ((mtrackletWord&Q2mask)>>Q2bs);}; // in units of counts all 3 together + uint64_t getHCID() const { return ((mtrackletWord & hcidmask) >> hcidbs); }; // no units + uint64_t getPadRow() const { return ((mtrackletWord & padrowmask) >> padrowbs); }; // in units of ?? + uint64_t getPosition() const { return ((mtrackletWord & posmask) >> posbs); }; // in units of 0.02 pads [10bits] .. -10.22 to 10.22 + uint64_t getSlope() const { return ((mtrackletWord & slopemask) >> slopebs); }; // in units of -127 .. 127 + uint64_t getPID() const { return ((mtrackletWord & PIDmask)); }; // in units of counts all 3 together + uint64_t getQ0() const { return ((mtrackletWord & Q0mask) >> Q0bs); }; // in units of counts all 3 together + uint64_t getQ1() const { return ((mtrackletWord & Q1mask) >> Q1bs); }; // in units of counts all 3 together + uint64_t getQ2() const { return ((mtrackletWord & Q2mask) >> Q2bs); }; // in units of counts all 3 together - uint64_t buildTrackletWord(uint64_t format,uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0){ - mtrackletWord=((format << formatbs)&formatmask) + ((hcid << hcidbs)&hcidmask) + ((padrow << padrowbs)&padrowmask) + ((col<<colbs)&colmask) + ((position<<posbs)&posmask) + ((slope<<slopebs)&slopemask) + ((Q2<<Q2bs)&Q2mask) + ((Q1<<Q1bs)&Q1mask) + ((Q0<<Q0bs)&Q0mask); - return 0; + uint64_t buildTrackletWord(uint64_t format, uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0) + { + mtrackletWord = ((format << formatbs) & formatmask) + ((hcid << hcidbs) & hcidmask) + ((padrow << padrowbs) & padrowmask) + ((col << colbs) & colmask) + ((position << posbs) & posmask) + ((slope << slopebs) & slopemask) + ((Q2 << Q2bs) & Q2mask) + ((Q1 << Q1bs) & Q1mask) + ((Q0 << Q0bs) & Q0mask); + return 0; } - uint64_t setTrackletWord(uint64_t trackletword) { - mtrackletWord=trackletword; - return 0; + uint64_t setTrackletWord(uint64_t trackletword) + { + mtrackletWord = trackletword; + return 0; } // ----- Getters for tracklet information ----- // TODO figure out how to get MCM and ROB from hcid, chipindex and row. @@ -109,23 +113,34 @@ static constexpr uint64_t Q2bs=0; // ----- Getters for offline corresponding values ----- int getDetector() const { return getHCID() / 2; } - uint64_t getTrackletWord() const{ return mtrackletWord;}; + uint64_t getTrackletWord() const { return mtrackletWord; }; uint32_t getTrackletWord32() const; -// void setDetector(int id) { uint64_t hcid= 2* id; uint64_t side=1;mtrackletWord = hcid << hcidbs + ; } + // void setDetector(int id) { uint64_t hcid= 2* id; uint64_t side=1;mtrackletWord = hcid << hcidbs + ; } // void setHCId(int id) { mHCId = id; } // TODO row and mcm to chipindex and z mapping. - uint64_t setQ0(int charge) { mtrackletWord |= ((charge<<Q0bs) & Q0mask); return mtrackletWord;} - uint64_t setQ1(int charge) { mtrackletWord |= ((charge<<Q1bs) & Q1mask); return mtrackletWord;} - uint64_t setQ2(int charge) { mtrackletWord |= ((charge<<Q2bs) & Q2mask); return mtrackletWord;} - void setPID(uint64_t pid) { mtrackletWord |= ((((uint64_t)pid)<<PIDbs) & PIDmask); } // set the entire pid area of the trackletword, all the 3 Q's - void setPosition(uint64_t position) { mtrackletWord |= ((((uint64_t)position)<<posbs) & posmask);} - void setSlope(uint64_t slope) { mtrackletWord |= ((((uint64_t)slope)<<slopebs) & slopemask);} - + uint64_t setQ0(int charge) + { + mtrackletWord |= ((charge << Q0bs) & Q0mask); + return mtrackletWord; + } + uint64_t setQ1(int charge) + { + mtrackletWord |= ((charge << Q1bs) & Q1mask); + return mtrackletWord; + } + uint64_t setQ2(int charge) + { + mtrackletWord |= ((charge << Q2bs) & Q2mask); + return mtrackletWord; + } + void setPID(uint64_t pid) { mtrackletWord |= ((((uint64_t)pid) << PIDbs) & PIDmask); } // set the entire pid area of the trackletword, all the 3 Q's + void setPosition(uint64_t position) { mtrackletWord |= ((((uint64_t)position) << posbs) & posmask); } + void setSlope(uint64_t slope) { mtrackletWord |= ((((uint64_t)slope) << slopebs) & slopemask); } - protected: - uint64_t mtrackletWord; // the 64 bit word holding all the tracklet information for run3. - private: + protected: + uint64_t mtrackletWord; // the 64 bit word holding all the tracklet information for run3. + private: // Tracklet& operator=(const Tracklet &rhs); // not implemented ClassDefNV(Tracklet64, 1); }; diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index 049ed4189ba8a..8f1e489320984 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -19,7 +19,7 @@ #pragma link C++ struct o2::trd::HalfChamberHeader + ; #pragma link C++ struct o2::trd::MCMRawDataHeader + ; #pragma link C++ struct o2::trd::TrapRawTracklet + ; -#pragma link C++ class o2::trd::Tracklet64 + ; +#pragma link C++ class o2::trd::Tracklet64 + ; #pragma link C++ class std::vector < o2::trd::TriggerRecord > +; #endif diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index 0490e7c0aa22e..cd4b925b891eb 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -17,6 +17,5 @@ namespace o2 namespace trd { - } // namespace trd } // namespace o2 diff --git a/DataFormats/Detectors/TRD/src/Tracklet64.cxx b/DataFormats/Detectors/TRD/src/Tracklet64.cxx index f30bedf94c995..32cd53a6f862a 100644 --- a/DataFormats/Detectors/TRD/src/Tracklet64.cxx +++ b/DataFormats/Detectors/TRD/src/Tracklet64.cxx @@ -17,6 +17,5 @@ namespace o2 namespace trd { - } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/test/testRawData.cxx b/Detectors/TRD/base/test/testRawData.cxx index dbcf855905cb4..7a4dac88bec25 100644 --- a/Detectors/TRD/base/test/testRawData.cxx +++ b/Detectors/TRD/base/test/testRawData.cxx @@ -35,64 +35,63 @@ namespace trd BOOST_AUTO_TEST_CASE(TRDRawDataHeaderSizes) { //check the sizes of header structs due to packing - BOOST_CHECK_EQUAL(sizeof(o2::trd::TrapRawTracklet),4); - BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfChamberHeader),4); BOOST_CHECK_EQUAL(sizeof(o2::trd::MCMRawDataHeader),4); - BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfCRUHeader),64); + BOOST_CHECK_EQUAL(sizeof(o2::trd::TrapRawTracklet), 4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfChamberHeader), 4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::MCMRawDataHeader), 4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfCRUHeader), 64); } - BOOST_AUTO_TEST_CASE(TRDRawDataHeaderInternals) { o2::trd::TrapRawTracklet tracklet; o2::trd::HalfChamberHeader halfchamberheader; o2::trd::HalfCRUHeader halfcruheader; halfcruheader.word02[0] = 0x102; - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags,2); - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size,1); - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags,o2::trd::getlinkerrorflag(halfcruheader,0)); - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size,o2::trd::getlinkdatasize(halfcruheader,0)); -//ab is size + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags, 2); + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size, 1); + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 0)); + BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size, o2::trd::getlinkdatasize(halfcruheader, 0)); + //ab is size halfcruheader.word02[2] = 0xffffaa0000000000; - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size,0xffff); - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags,0xaa); - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags,o2::trd::getlinkerrorflag(halfcruheader,7)); - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size,o2::trd::getlinkdatasize(halfcruheader,7)); - halfcruheader.word3 = (0x222LL)<<40; //bc is at 0x000ffff000000000 - BOOST_CHECK_EQUAL(halfcruheader.BunchCrossing,0x222); + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size, 0xffff); + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags, 0xaa); + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 7)); + BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size, o2::trd::getlinkdatasize(halfcruheader, 7)); + halfcruheader.word3 = (0x222LL) << 40; //bc is at 0x000ffff000000000 + BOOST_CHECK_EQUAL(halfcruheader.BunchCrossing, 0x222); halfcruheader.word3 = 0x7700000000; //headerversion is at 0x00ff0000000 - BOOST_CHECK_EQUAL(halfcruheader.HeaderVersion,119); + BOOST_CHECK_EQUAL(halfcruheader.HeaderVersion, 119); halfcruheader.word57[0] = 0x345869faba; halfcruheader.word57[2] = 0xaaade1277; - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags,0xba); - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size,0x69fa); - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags,o2::trd::getlinkerrorflag(halfcruheader,8)); - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size,o2::trd::getlinkdatasize(halfcruheader,8)); - BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags,0x58); - BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size,0x34); -//ab is size - BOOST_CHECK_EQUAL(halfcruheader.linksB[5].size,0x1277); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size,0xaaa); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags,0xde); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags,o2::trd::getlinkerrorflag(halfcruheader,14)); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size,o2::trd::getlinkdatasize(halfcruheader,14)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags, 0xba); + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size, 0x69fa); + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 8)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size, o2::trd::getlinkdatasize(halfcruheader, 8)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags, 0x58); + BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size, 0x34); + //ab is size + BOOST_CHECK_EQUAL(halfcruheader.linksB[5].size, 0x1277); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size, 0xaaa); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags, 0xde); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 14)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size, o2::trd::getlinkdatasize(halfcruheader, 14)); //now test the boundary crossing of the int64_t - halfcruheader.word02[0]= (uint64_t)0x1000000000000000; - halfcruheader.word02[1]= (uint64_t)0xa00b000c000d0ebf; - BOOST_CHECK_EQUAL(halfcruheader.linksA[2].size,0xbf10); // check a size that spans a 64bit word. + halfcruheader.word02[0] = (uint64_t)0x1000000000000000; + halfcruheader.word02[1] = (uint64_t)0xa00b000c000d0ebf; + BOOST_CHECK_EQUAL(halfcruheader.linksA[2].size, 0xbf10); // check a size that spans a 64bit word. o2::trd::MCMRawDataHeader mcmrawdataheader; - mcmrawdataheader.word=0xa0000000; - BOOST_CHECK_EQUAL(mcmrawdataheader.padrow,10); - mcmrawdataheader.word=0x0c000000; - BOOST_CHECK_EQUAL(mcmrawdataheader.col,3); - mcmrawdataheader.word=0x03fc0000; - BOOST_CHECK_EQUAL(mcmrawdataheader.pid2,0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 - mcmrawdataheader.word=0x03fc; - BOOST_CHECK_EQUAL(mcmrawdataheader.pid0,0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 + mcmrawdataheader.word = 0xa0000000; + BOOST_CHECK_EQUAL(mcmrawdataheader.padrow, 10); + mcmrawdataheader.word = 0x0c000000; + BOOST_CHECK_EQUAL(mcmrawdataheader.col, 3); + mcmrawdataheader.word = 0x03fc0000; + BOOST_CHECK_EQUAL(mcmrawdataheader.pid2, 0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 + mcmrawdataheader.word = 0x03fc; + BOOST_CHECK_EQUAL(mcmrawdataheader.pid0, 0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 //check tracklet - tracklet.word=0xffc00000; - BOOST_CHECK_EQUAL((uint32_t)tracklet.pos,0x3ff); - + tracklet.word = 0xffc00000; + BOOST_CHECK_EQUAL((uint32_t)tracklet.pos, 0x3ff); } } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h b/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h index 3da7db0359149..fd970e1c5cbb3 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h @@ -16,7 +16,6 @@ #ifndef ALICEO2_TRD_TRACKLETS2RAW_H #define ALICEO2_TRD_TRACKLETS2RAW_H - #include "DataFormatsTRD/TriggerRecord.h" #include "DataFormatsTRD/TrackletRawData.h" @@ -28,27 +27,26 @@ namespace trd class Tracklets2Raw { - static constexpr int NChannels; - static constexpr int NLinksPerCRU=30; - static constexpr int NCRU=36; - - public: - Tracklets2Raw() = default; - Tracklets2Raw(const std::string& outDir, const std::string& fileRawTrackletsName); - void readTracklets(const std::string& outDir, const std::string& fileRawTrackletsName); - - void converTracklets(o2::trd::TrackletRaw rawTracklets, gsl::span<2::trd::TriggerRecord const & mTriggerRecord); - - - private: - const o2::raw::HBFUtils& mSampler = o2::raw::HBFUtils::Instance(); - o2::raw::RawFileWriter mWriter("TRD"); - bool mOutputPerLink = true; - uint32_t mLinkId =0; - uint32_t mCRUId = 0; - uint32_t mEndPointId = 0; - uint32_t mFeeId =0; + static constexpr int NChannels; + static constexpr int NLinksPerCRU = 30; + static constexpr int NCRU = 36; + + public: + Tracklets2Raw() = default; + Tracklets2Raw(const std::string& outDir, const std::string& fileRawTrackletsName); + void readTracklets(const std::string& outDir, const std::string& fileRawTrackletsName); + + void converTracklets(o2::trd::TrackletRaw rawTracklets, gsl::span < 2 ::trd::TriggerRecord const& mTriggerRecord); + + private: + const o2::raw::HBFUtils& mSampler = o2::raw::HBFUtils::Instance(); + o2::raw::RawFileWriter mWriter("TRD"); + bool mOutputPerLink = true; + uint32_t mLinkId = 0; + uint32_t mCRUId = 0; + uint32_t mEndPointId = 0; + uint32_t mFeeId = 0; }; -} // end trd namespace -} // end o2 namespace +} // namespace trd +} // namespace o2 #endif diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 38ef569246b0a..8e8ad2ccd55af 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -993,20 +993,20 @@ int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) // A MCM Header followed by at most 3 tracklet words. // Although a little confusingly some of the tracklet data is in the header. -// numberWordsWritten = packData(buf); + // numberWordsWritten = packData(buf); // //given the, up to 3 tracklets, pack them according to the define data format. // // produce a MCM Header, then the 1 to 3 tracklet words. -// - std::array<uint32_t,3> pid; -// std::array<TrackletRawDataHeader,3> tracklet; -// MCMRawDataHeader mcmheader; -// TrackletRawDataHeader tracklet[3]; // at most 3 tracklets -// mcmheader.checkbits=0x3; -// mcmheader.y=; -// mcmheader z=; -/* for(auto track mTrackletArray) + // + std::array<uint32_t, 3> pid; + // std::array<TrackletRawDataHeader,3> tracklet; + // MCMRawDataHeader mcmheader; + // TrackletRawDataHeader tracklet[3]; // at most 3 tracklets + // mcmheader.checkbits=0x3; + // mcmheader.y=; + // mcmheader z=; + /* for(auto track mTrackletArray) { tracklet[].checkbit=0x1; tracklet[].pid=0x1; From c598b8a080131cf07243ce7aacf6e7285a0908ab Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 23 Jul 2020 15:09:38 +0200 Subject: [PATCH 0162/1751] remove changes to trapsimulator --- .../TRD/simulation/src/TrapSimulator.cxx | 42 +++++++------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 8e8ad2ccd55af..e356989df5227 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -886,6 +886,18 @@ int TrapSimulator::getCol(int adc) return col; } +int TrapSimulator::packData(std::vector<uint32_t>& buf) +{ + + // + //given the, up to 3 tracklets, pack them according to the define data format. + // + //TODO this is left blank so that the dataformats etc. can come in a seperate PR + //to keep different work seperate. + LOG(fatal) << "Called packData of TrapSimualtor ... why? I am going to die, till next pr."; + return 1; +} + int TrapSimulator::produceRawStream(std::vector<uint32_t>& buf, unsigned int iEv) const { // @@ -988,33 +1000,9 @@ int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) return 0; int numberWordsWritten = 0; // Number of written words - - // Produce tracklet data. - // A MCM Header followed by at most 3 tracklet words. - // Although a little confusingly some of the tracklet data is in the header. - - // numberWordsWritten = packData(buf); - // - //given the, up to 3 tracklets, pack them according to the define data format. - // - // produce a MCM Header, then the 1 to 3 tracklet words. - // - std::array<uint32_t, 3> pid; - // std::array<TrackletRawDataHeader,3> tracklet; - // MCMRawDataHeader mcmheader; - // TrackletRawDataHeader tracklet[3]; // at most 3 tracklets - // mcmheader.checkbits=0x3; - // mcmheader.y=; - // mcmheader z=; - /* for(auto track mTrackletArray) - { - tracklet[].checkbit=0x1; - tracklet[].pid=0x1; - tracklet[].dy=0x1; - tracklet[].y=0x1; - mcmheader.pid[]=0x1; // part of the tracklet pid is stored in the chip header. - -*/ + + numberWordsWritten = packData(buf); + return numberWordsWritten; } From dadab8bdfc3d3ef1b04b2e32b6a985e0d557b012 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 23 Jul 2020 15:11:39 +0200 Subject: [PATCH 0163/1751] remove changes to trapsimulator, whitespace --- Detectors/TRD/simulation/src/TrapSimulator.cxx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index e356989df5227..5e0bd602271ef 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -886,9 +886,8 @@ int TrapSimulator::getCol(int adc) return col; } -int TrapSimulator::packData(std::vector<uint32_t>& buf) -{ - +int TrapSimulator::packData(std::vector<uint32_t>& buf) +{ // //given the, up to 3 tracklets, pack them according to the define data format. // @@ -897,7 +896,7 @@ int TrapSimulator::packData(std::vector<uint32_t>& buf) LOG(fatal) << "Called packData of TrapSimualtor ... why? I am going to die, till next pr."; return 1; } - + int TrapSimulator::produceRawStream(std::vector<uint32_t>& buf, unsigned int iEv) const { // @@ -1000,9 +999,9 @@ int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) return 0; int numberWordsWritten = 0; // Number of written words - + numberWordsWritten = packData(buf); - + return numberWordsWritten; } From df97e0b48f6e796714846a645e70d9b97158a58c Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 23 Jul 2020 15:18:24 +0200 Subject: [PATCH 0164/1751] remove changes to trapsimulator, whitespace, and some other stuff --- Detectors/TRD/simulation/src/TrapSimulator.cxx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 5e0bd602271ef..1b13eaa2f2b16 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -889,12 +889,12 @@ int TrapSimulator::getCol(int adc) int TrapSimulator::packData(std::vector<uint32_t>& buf) { // - //given the, up to 3 tracklets, pack them according to the define data format. - // - //TODO this is left blank so that the dataformats etc. can come in a seperate PR + //given the, up to 3 tracklets, pack them according to the define data format. + // + //TODO this is left blank so that the dataformats etc. can come in a seperate PR //to keep different work seperate. - LOG(fatal) << "Called packData of TrapSimualtor ... why? I am going to die, till next pr."; - return 1; + LOG(fatal) << "Called packData of TrapSimualtor ... why? I am going to die, till next pr."; + return 1; } int TrapSimulator::produceRawStream(std::vector<uint32_t>& buf, unsigned int iEv) const @@ -1000,6 +1000,10 @@ int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) int numberWordsWritten = 0; // Number of written words + // Produce tracklet data. + // A MCM Header followed by at most 3 tracklet words. + // Although a little confusingly some of the tracklet data is in the header. + numberWordsWritten = packData(buf); return numberWordsWritten; From 8a2496c96d5b1e76186b4aeb44960a82bbdd651b Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 23 Jul 2020 15:19:15 +0200 Subject: [PATCH 0165/1751] remove changes to trapsimulator, whitespace, and some other stuff and more --- Detectors/TRD/simulation/src/TrapSimulator.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 1b13eaa2f2b16..cf24778285715 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -892,7 +892,7 @@ int TrapSimulator::packData(std::vector<uint32_t>& buf) //given the, up to 3 tracklets, pack them according to the define data format. // //TODO this is left blank so that the dataformats etc. can come in a seperate PR - //to keep different work seperate. + //to keep different work seperate. LOG(fatal) << "Called packData of TrapSimualtor ... why? I am going to die, till next pr."; return 1; } @@ -1000,8 +1000,8 @@ int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) int numberWordsWritten = 0; // Number of written words - // Produce tracklet data. - // A MCM Header followed by at most 3 tracklet words. + // Produce tracklet data. + // A MCM Header followed by at most 3 tracklet words. // Although a little confusingly some of the tracklet data is in the header. numberWordsWritten = packData(buf); From 11ec877053e72809b6283fef2cb44c58d78f13e8 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 23 Jul 2020 15:21:04 +0200 Subject: [PATCH 0166/1751] remove tracklets2raw, its for a subsequent PR --- .../include/TRDSimulation/Tracklets2Raw.h | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h b/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h deleted file mode 100644 index fd970e1c5cbb3..0000000000000 --- a/Detectors/TRD/simulation/include/TRDSimulation/Tracklets2Raw.h +++ /dev/null @@ -1,52 +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. -// -// /// \file Tracklet2Raw.h -// /// \brief converts tracklets raw stream to raw data format -// // murrays@cern.ch -// -// -#ifndef ALICEO2_TRD_TRACKLETS2RAW_H -#define ALICEO2_TRD_TRACKLETS2RAW_H - -#include "DataFormatsTRD/TriggerRecord.h" -#include "DataFormatsTRD/TrackletRawData.h" - -namespace o2 -{ -namespace trd -{ - -class Tracklets2Raw -{ - - static constexpr int NChannels; - static constexpr int NLinksPerCRU = 30; - static constexpr int NCRU = 36; - - public: - Tracklets2Raw() = default; - Tracklets2Raw(const std::string& outDir, const std::string& fileRawTrackletsName); - void readTracklets(const std::string& outDir, const std::string& fileRawTrackletsName); - - void converTracklets(o2::trd::TrackletRaw rawTracklets, gsl::span < 2 ::trd::TriggerRecord const& mTriggerRecord); - - private: - const o2::raw::HBFUtils& mSampler = o2::raw::HBFUtils::Instance(); - o2::raw::RawFileWriter mWriter("TRD"); - bool mOutputPerLink = true; - uint32_t mLinkId = 0; - uint32_t mCRUId = 0; - uint32_t mEndPointId = 0; - uint32_t mFeeId = 0; -}; -} // namespace trd -} // namespace o2 -#endif From fb0c07df373da35b44ba44ac387595007d9a1c0e Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 23 Jul 2020 23:42:27 +0200 Subject: [PATCH 0167/1751] fix tests --- .../TRD/include/DataFormatsTRD/RawData.h | 15 +++++++------ .../TRD/include/DataFormatsTRD/Tracklet64.h | 14 ++++++------ Detectors/TRD/base/test/testRawData.cxx | 22 +++++++++---------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h index c89491086a7c4..786d6ded2024f 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -177,13 +177,14 @@ struct MCMRawDataHeader { //first word * // 10987654321098765432109876543210 // uint32_t: 00000000000000000000000000000000 - // 1zzzz pppppppp pppppppp 1 - // || yy| pppppppp | ccc-- 0..1 check bits - // || | | | ------------ 2-9 pid for tracklet 3 second part - // || | | --------------------- 10-17 pid for tracklet 2 second part - // || | ---------------------------- 18-25 pid for tracklet 1 second part - // || ------------------------------ 26-27 coly - // |---------------------------------- 28-31 padrow + // 1zzzz pppppppp pppppppp1 + // || yy| pppppppp | |--- 0 1 check bits + // || | | | ----------- 1-8 pid for tracklet 3 second part + // || | | -------------------- 9-16 pid for tracklet 2 second part + // || | ---------------------------- 17-24 pid for tracklet 1 second part + // || ------------------------------ 25-26 coly + // |---------------------------------- 27-30 padrow + // ----------------------------------- 31 1 //TODO need to check endianness, I have a vague memory the trap chip has different endianness to x86. union { uint32_t word; diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index 5c42a1b97f1b0..3de850f520191 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -47,9 +47,9 @@ Word 0 | slope | Q0 | Q1 class Tracklet64 { // bit masks for the above raw data; - static constexpr uint64_t formatmask = 0xf000000000000000; //0-1079 - static constexpr uint64_t hcidmask = 0x0ffe000000000000; //0-1079 - static constexpr uint64_t padrowmask = 0x0001e00000000000; //0-3; + static constexpr uint64_t formatmask = 0xf000000000000000; + static constexpr uint64_t hcidmask = 0x0ffe000000000000; + static constexpr uint64_t padrowmask = 0x0001e00000000000; static constexpr uint64_t colmask = 0x0000180000000000; static constexpr uint64_t posmask = 0x000007ff00000000; static constexpr uint64_t slopemask = 0x00000000ff000000; @@ -86,8 +86,8 @@ class Tracklet64 //TODO convert to the actual number regarding compliments. // ----- Getters for contents of tracklet word ----- - uint64_t getHCID() const { return ((mtrackletWord & hcidmask) >> hcidbs); }; // no units - uint64_t getPadRow() const { return ((mtrackletWord & padrowmask) >> padrowbs); }; // in units of ?? + uint64_t getHCID() const { return ((mtrackletWord & hcidmask) >> hcidbs); }; // no units 0..1077 + uint64_t getPadRow() const { return ((mtrackletWord & padrowmask) >> padrowbs); }; // in units of uint64_t getPosition() const { return ((mtrackletWord & posmask) >> posbs); }; // in units of 0.02 pads [10bits] .. -10.22 to 10.22 uint64_t getSlope() const { return ((mtrackletWord & slopemask) >> slopebs); }; // in units of -127 .. 127 uint64_t getPID() const { return ((mtrackletWord & PIDmask)); }; // in units of counts all 3 together @@ -106,7 +106,7 @@ class Tracklet64 return 0; } // ----- Getters for tracklet information ----- - // TODO figure out how to get MCM and ROB from hcid, chipindex and row. + // TODO figure out how to get MCM and ROB from hcid, col and padrow. int getMCM() const { return 1; } int getROB() const { return 1; } @@ -118,7 +118,7 @@ class Tracklet64 // void setDetector(int id) { uint64_t hcid= 2* id; uint64_t side=1;mtrackletWord = hcid << hcidbs + ; } // void setHCId(int id) { mHCId = id; } - // TODO row and mcm to chipindex and z mapping. + // TODO row and mcm to col and padrow mapping. uint64_t setQ0(int charge) { mtrackletWord |= ((charge << Q0bs) & Q0mask); diff --git a/Detectors/TRD/base/test/testRawData.cxx b/Detectors/TRD/base/test/testRawData.cxx index 7a4dac88bec25..8d938edaba30a 100644 --- a/Detectors/TRD/base/test/testRawData.cxx +++ b/Detectors/TRD/base/test/testRawData.cxx @@ -63,31 +63,29 @@ BOOST_AUTO_TEST_CASE(TRDRawDataHeaderInternals) BOOST_CHECK_EQUAL(halfcruheader.HeaderVersion, 119); halfcruheader.word57[0] = 0x345869faba; halfcruheader.word57[2] = 0xaaade1277; - - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags, 0xba); - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size, 0x69fa); - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 8)); - BOOST_CHECK_EQUAL(halfcruheader.linksB[0].size, o2::trd::getlinkdatasize(halfcruheader, 8)); +//linkb[0] zero is undefined. BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags, 0x58); BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size, 0x34); + BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 8)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size, o2::trd::getlinkdatasize(halfcruheader, 8)); //ab is size BOOST_CHECK_EQUAL(halfcruheader.linksB[5].size, 0x1277); BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size, 0xaaa); BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags, 0xde); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 14)); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size, o2::trd::getlinkdatasize(halfcruheader, 14)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 13)); + BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size, o2::trd::getlinkdatasize(halfcruheader, 13)); //now test the boundary crossing of the int64_t halfcruheader.word02[0] = (uint64_t)0x1000000000000000; halfcruheader.word02[1] = (uint64_t)0xa00b000c000d0ebf; BOOST_CHECK_EQUAL(halfcruheader.linksA[2].size, 0xbf10); // check a size that spans a 64bit word. o2::trd::MCMRawDataHeader mcmrawdataheader; - mcmrawdataheader.word = 0xa0000000; - BOOST_CHECK_EQUAL(mcmrawdataheader.padrow, 10); - mcmrawdataheader.word = 0x0c000000; + mcmrawdataheader.word = 0x78000000; + BOOST_CHECK_EQUAL(mcmrawdataheader.padrow, 15); + mcmrawdataheader.word = 0x06000000; BOOST_CHECK_EQUAL(mcmrawdataheader.col, 3); - mcmrawdataheader.word = 0x03fc0000; + mcmrawdataheader.word = 0x01fe0000; BOOST_CHECK_EQUAL(mcmrawdataheader.pid2, 0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 - mcmrawdataheader.word = 0x03fc; + mcmrawdataheader.word = 0x01fe; BOOST_CHECK_EQUAL(mcmrawdataheader.pid0, 0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 //check tracklet tracklet.word = 0xffc00000; From d76536df60f436a5a38c3c28e3fee724770d3a03 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Fri, 24 Jul 2020 00:07:15 +0200 Subject: [PATCH 0168/1751] refactor tracklet constructor to use the internal build method --- DataFormats/Detectors/TRD/CMakeLists.txt | 1 + .../TRD/include/DataFormatsTRD/Tracklet64.h | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/DataFormats/Detectors/TRD/CMakeLists.txt b/DataFormats/Detectors/TRD/CMakeLists.txt index 9d104bd3a7635..ea85f21d17999 100644 --- a/DataFormats/Detectors/TRD/CMakeLists.txt +++ b/DataFormats/Detectors/TRD/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library(DataFormatsTRD src/Tracklet64.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::SimulationDataFormat + O2::TRDBase ) o2_target_root_dictionary(DataFormatsTRD diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index 3de850f520191..a2b1cbc557f7f 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -30,6 +30,7 @@ #include <memory> // for std::unique_ptr #include "Rtypes.h" // for ClassDef #include "fairlogger/Logger.h" +#include "TRDBase/FeeParam.h" namespace o2 { @@ -76,9 +77,7 @@ class Tracklet64 Tracklet64(uint64_t format, uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0) { - mtrackletWord = ((format << formatbs) & formatmask) + ((hcid << hcidbs) & hcidmask) + - ((padrow << padrowbs) & padrowmask) + ((col << colbs) & colmask) + ((position << posbs) & posmask) + - ((slope << slopebs) & slopemask) + ((Q2 << Q2bs) & Q2mask) + ((Q1 << Q1bs) & Q1mask) + ((Q0 << Q0bs) & Q0mask); + buildTrackletWord(format,hcid, padrow, col, position, slope, Q2, Q1, Q0); } ~Tracklet64() = default; @@ -88,6 +87,7 @@ class Tracklet64 // ----- Getters for contents of tracklet word ----- uint64_t getHCID() const { return ((mtrackletWord & hcidmask) >> hcidbs); }; // no units 0..1077 uint64_t getPadRow() const { return ((mtrackletWord & padrowmask) >> padrowbs); }; // in units of + uint64_t getColumn() const { return ((mtrackletWord & colmask) >> colbs); }; // in units of uint64_t getPosition() const { return ((mtrackletWord & posmask) >> posbs); }; // in units of 0.02 pads [10bits] .. -10.22 to 10.22 uint64_t getSlope() const { return ((mtrackletWord & slopemask) >> slopebs); }; // in units of -127 .. 127 uint64_t getPID() const { return ((mtrackletWord & PIDmask)); }; // in units of counts all 3 together @@ -107,8 +107,14 @@ class Tracklet64 } // ----- Getters for tracklet information ----- // TODO figure out how to get MCM and ROB from hcid, col and padrow. - int getMCM() const { return 1; } - int getROB() const { return 1; } + int getMCM() const { + return (getColumn() % (FeeParam::mgkNcol / 2)) / FeeParam::mgkNcolMcm + FeeParam::mgkNmcmRobInCol * (getPadRow() % FeeParam::mgkNmcmRobInRow); + } + int getROB() const { + int side=getColumn()/(FeeParam::mgkNcol/2); + return (int)((int)getPadRow() / (int)FeeParam::mgkNmcmRobInRow) * 2 + side; + } + // ----- Getters for offline corresponding values ----- int getDetector() const { return getHCID() / 2; } From f5f4c7ded93eb8023f176c70ff9e85a5f84c6dcf Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Fri, 24 Jul 2020 00:10:44 +0200 Subject: [PATCH 0169/1751] keep travis happy --- .../Detectors/TRD/include/DataFormatsTRD/Tracklet64.h | 11 ++++++----- Detectors/TRD/base/test/testRawData.cxx | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index a2b1cbc557f7f..250f8f8fc3ab7 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -48,9 +48,9 @@ Word 0 | slope | Q0 | Q1 class Tracklet64 { // bit masks for the above raw data; - static constexpr uint64_t formatmask = 0xf000000000000000; - static constexpr uint64_t hcidmask = 0x0ffe000000000000; - static constexpr uint64_t padrowmask = 0x0001e00000000000; + static constexpr uint64_t formatmask = 0xf000000000000000; + static constexpr uint64_t hcidmask = 0x0ffe000000000000; + static constexpr uint64_t padrowmask = 0x0001e00000000000; static constexpr uint64_t colmask = 0x0000180000000000; static constexpr uint64_t posmask = 0x000007ff00000000; static constexpr uint64_t slopemask = 0x00000000ff000000; @@ -79,6 +79,7 @@ class Tracklet64 { buildTrackletWord(format,hcid, padrow, col, position, slope, Q2, Q1, Q0); } + ~Tracklet64() = default; Tracklet64& operator=(const Tracklet64& o) { return *this; } @@ -86,8 +87,8 @@ class Tracklet64 //TODO convert to the actual number regarding compliments. // ----- Getters for contents of tracklet word ----- uint64_t getHCID() const { return ((mtrackletWord & hcidmask) >> hcidbs); }; // no units 0..1077 - uint64_t getPadRow() const { return ((mtrackletWord & padrowmask) >> padrowbs); }; // in units of - uint64_t getColumn() const { return ((mtrackletWord & colmask) >> colbs); }; // in units of + uint64_t getPadRow() const { return ((mtrackletWord & padrowmask) >> padrowbs); }; // in units of + uint64_t getColumn() const { return ((mtrackletWord & colmask) >> colbs); }; // in units of uint64_t getPosition() const { return ((mtrackletWord & posmask) >> posbs); }; // in units of 0.02 pads [10bits] .. -10.22 to 10.22 uint64_t getSlope() const { return ((mtrackletWord & slopemask) >> slopebs); }; // in units of -127 .. 127 uint64_t getPID() const { return ((mtrackletWord & PIDmask)); }; // in units of counts all 3 together diff --git a/Detectors/TRD/base/test/testRawData.cxx b/Detectors/TRD/base/test/testRawData.cxx index 8d938edaba30a..480612f4f2080 100644 --- a/Detectors/TRD/base/test/testRawData.cxx +++ b/Detectors/TRD/base/test/testRawData.cxx @@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(TRDRawDataHeaderInternals) BOOST_CHECK_EQUAL(halfcruheader.HeaderVersion, 119); halfcruheader.word57[0] = 0x345869faba; halfcruheader.word57[2] = 0xaaade1277; -//linkb[0] zero is undefined. + //linkb[0] zero is undefined. BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags, 0x58); BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size, 0x34); BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 8)); From 0e1210cd8ce7684effc223c7a59140f0a709ec78 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Fri, 24 Jul 2020 00:19:22 +0200 Subject: [PATCH 0170/1751] clang errors --- .../TRD/include/DataFormatsTRD/Tracklet64.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index 250f8f8fc3ab7..5123504d8852b 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -77,7 +77,7 @@ class Tracklet64 Tracklet64(uint64_t format, uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0) { - buildTrackletWord(format,hcid, padrow, col, position, slope, Q2, Q1, Q0); + buildTrackletWord(format, hcid, padrow, col, position, slope, Q2, Q1, Q0); } ~Tracklet64() = default; @@ -88,7 +88,7 @@ class Tracklet64 // ----- Getters for contents of tracklet word ----- uint64_t getHCID() const { return ((mtrackletWord & hcidmask) >> hcidbs); }; // no units 0..1077 uint64_t getPadRow() const { return ((mtrackletWord & padrowmask) >> padrowbs); }; // in units of - uint64_t getColumn() const { return ((mtrackletWord & colmask) >> colbs); }; // in units of + uint64_t getColumn() const { return ((mtrackletWord & colmask) >> colbs); }; // in units of uint64_t getPosition() const { return ((mtrackletWord & posmask) >> posbs); }; // in units of 0.02 pads [10bits] .. -10.22 to 10.22 uint64_t getSlope() const { return ((mtrackletWord & slopemask) >> slopebs); }; // in units of -127 .. 127 uint64_t getPID() const { return ((mtrackletWord & PIDmask)); }; // in units of counts all 3 together @@ -108,15 +108,16 @@ class Tracklet64 } // ----- Getters for tracklet information ----- // TODO figure out how to get MCM and ROB from hcid, col and padrow. - int getMCM() const { - return (getColumn() % (FeeParam::mgkNcol / 2)) / FeeParam::mgkNcolMcm + FeeParam::mgkNmcmRobInCol * (getPadRow() % FeeParam::mgkNmcmRobInRow); + int getMCM() const + { + return (getColumn() % (FeeParam::mgkNcol / 2)) / FeeParam::mgkNcolMcm + FeeParam::mgkNmcmRobInCol * (getPadRow() % FeeParam::mgkNmcmRobInRow); } - int getROB() const { - int side=getColumn()/(FeeParam::mgkNcol/2); - return (int)((int)getPadRow() / (int)FeeParam::mgkNmcmRobInRow) * 2 + side; + int getROB() const + { + int side = getColumn() / (FeeParam::mgkNcol / 2); + return (int)((int)getPadRow() / (int)FeeParam::mgkNmcmRobInRow) * 2 + side; } - // ----- Getters for offline corresponding values ----- int getDetector() const { return getHCID() / 2; } From 7d445cf2a3395a3e742d9282589ff603054488c1 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 24 Jul 2020 10:01:54 +0200 Subject: [PATCH 0171/1751] Fix memory leak in TPC workflow --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 57 ++++++++++---------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index fa8eb8a1d124c..fa0a1278ed6a6 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -541,8 +541,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } // a byte size resizable vector object, the DataAllocator returns reference to internal object // initialize optional pointer to the vector object - using ClusterOutputChunkType = std::decay_t<decltype(pc.outputs().make<std::vector<char>>(Output{"", "", 0}))>; - ClusterOutputChunkType* clusterOutput = nullptr; + using O2CharVectorOutputType = std::decay_t<decltype(pc.outputs().make<std::vector<char>>(Output{"", "", 0}))>; TPCSectorHeader clusterOutputSectorHeader{0}; if (processAttributes->clusterOutputIds.size() > 0) { if (activeSectors == 0) { @@ -556,37 +555,38 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int clusterOutputSectorHeader.sectorBits = activeSectors; // subspecs [0, NSectors - 1] are used to identify sector data, we use NSectors // to indicate the full TPC - o2::header::DataHeader::SubSpecificationType subspec = NSectors; clusterOutputSectorHeader.activeSectors = activeSectors; - clusterOutput = &pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}); } GPUInterfaceOutputs outputRegions; // TODO: For output to preallocated buffer, just allocated some large buffer for now. // This should be estimated correctly, but it is not the default for now, so it doesn't matter much. size_t bufferSize = 256ul * 1024 * 1024; - auto* bufferCompressedClusters = !processAttributes->allocateOutputOnTheFly && specconfig.outputCompClustersFlat ? &pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, bufferSize) : nullptr; - if (processAttributes->allocateOutputOnTheFly && specconfig.outputCompClustersFlat) { - outputRegions.compressedClusters.allocator = [&bufferCompressedClusters, &pc](size_t size) -> void* {bufferCompressedClusters = &pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, size); return bufferCompressedClusters->data(); }; - } else if (specconfig.outputCompClustersFlat) { - outputRegions.compressedClusters.ptr = bufferCompressedClusters->data(); - outputRegions.compressedClusters.size = bufferCompressedClusters->size(); - } - if (clusterOutput != nullptr) { + std::optional<std::reference_wrapper<O2CharVectorOutputType>> clusterOutput = std::nullopt, bufferCompressedClusters = std::nullopt, bufferTPCTracks = std::nullopt; + if (specconfig.outputCompClustersFlat) { + if (processAttributes->allocateOutputOnTheFly) { + outputRegions.compressedClusters.allocator = [&bufferCompressedClusters, &pc](size_t size) -> void* {bufferCompressedClusters.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, size)); return bufferCompressedClusters->get().data(); }; + } else { + bufferCompressedClusters.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, bufferSize)); + outputRegions.compressedClusters.ptr = bufferCompressedClusters->get().data(); + outputRegions.compressedClusters.size = bufferCompressedClusters->get().size(); + } + } + if (processAttributes->clusterOutputIds.size() > 0) { if (processAttributes->allocateOutputOnTheFly) { - outputRegions.clustersNative.allocator = [&clusterOutput, &pc](size_t size) -> void* {clusterOutput->resize(size + sizeof(ClusterCountIndex)); return (char*)clusterOutput->data() + sizeof(ClusterCountIndex); }; + outputRegions.clustersNative.allocator = [&clusterOutput, &pc, clusterOutputSectorHeader](size_t size) -> void* {clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, size + sizeof(ClusterCountIndex))); return (char*)clusterOutput->get().data() + sizeof(ClusterCountIndex); }; } else { - clusterOutput->resize(bufferSize); - outputRegions.clustersNative.ptr = (char*)clusterOutput->data() + sizeof(ClusterCountIndex); - outputRegions.clustersNative.size = clusterOutput->size() * sizeof(*clusterOutput->data()) - sizeof(ClusterCountIndex); + clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, bufferSize)); + outputRegions.clustersNative.ptr = (char*)clusterOutput->get().data() + sizeof(ClusterCountIndex); + outputRegions.clustersNative.size = clusterOutput->get().size() * sizeof(*clusterOutput->get().data()) - sizeof(ClusterCountIndex); } } - auto* bufferTPCTracks = !processAttributes->allocateOutputOnTheFly ? &pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, bufferSize) : nullptr; if (processAttributes->allocateOutputOnTheFly) { - outputRegions.tpcTracks.allocator = [&bufferTPCTracks, &pc](size_t size) -> void* {bufferTPCTracks = &pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, size); return bufferTPCTracks->data(); }; + outputRegions.tpcTracks.allocator = [&bufferTPCTracks, &pc](size_t size) -> void* {bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, size)); return bufferTPCTracks->get().data(); }; } else { - outputRegions.tpcTracks.ptr = bufferTPCTracks->data(); - outputRegions.tpcTracks.size = bufferTPCTracks->size(); + bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, bufferSize)); + outputRegions.tpcTracks.ptr = bufferTPCTracks->get().data(); + outputRegions.tpcTracks.size = bufferTPCTracks->get().size(); } int retVal = tracker->runTracking(&ptrs, &outputRegions); @@ -609,8 +609,10 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int if (ptrs.compressedClusters != nullptr) { if (specconfig.outputCompClustersFlat) { - bufferCompressedClusters->resize(outputRegions.compressedClusters.size); - if ((void*)ptrs.compressedClusters != (void*)bufferCompressedClusters->data()) { + if (!processAttributes->allocateOutputOnTheFly) { + bufferCompressedClusters->get().resize(outputRegions.compressedClusters.size); + } + if ((void*)ptrs.compressedClusters != (void*)bufferCompressedClusters->get().data()) { throw std::runtime_error("compressed cluster output ptrs out of sync"); // sanity check } } @@ -628,17 +630,18 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } // previously, clusters have been published individually for the enabled sectors // clusters are now published as one block, subspec is NSectors - if (clusterOutput != nullptr) { - clusterOutput->resize(sizeof(ClusterCountIndex) + outputRegions.clustersNative.size); - if ((void*)ptrs.clusters->clustersLinear != (void*)((char*)clusterOutput->data() + sizeof(ClusterCountIndex))) { + if (clusterOutput) { + if (!processAttributes->allocateOutputOnTheFly) { + clusterOutput->get().resize(sizeof(ClusterCountIndex) + outputRegions.clustersNative.size); + } + if ((void*)ptrs.clusters->clustersLinear != (void*)((char*)clusterOutput->get().data() + sizeof(ClusterCountIndex))) { throw std::runtime_error("cluster native output ptrs out of sync"); // sanity check } o2::header::DataHeader::SubSpecificationType subspec = NSectors; // doing a copy for now, in the future the tracker uses the output buffer directly - auto& target = *clusterOutput; ClusterNativeAccess const& accessIndex = *ptrs.clusters; - ClusterCountIndex* outIndex = reinterpret_cast<ClusterCountIndex*>(target.data()); + ClusterCountIndex* outIndex = reinterpret_cast<ClusterCountIndex*>(clusterOutput->get().data()); static_assert(sizeof(ClusterCountIndex) == sizeof(accessIndex.nClusters)); memcpy(outIndex, &accessIndex.nClusters[0][0], sizeof(ClusterCountIndex)); if (specconfig.processMC && accessIndex.clustersMCTruth) { From ad0c1116fe6795bdc00db24e3c5e4d0381d44245 Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Sat, 18 Jul 2020 11:58:02 +0300 Subject: [PATCH 0172/1751] read raw data and convert to digits --- .../FT0/include/DataFormatsFT0/LookUpTable.h | 15 +- .../FT0/include/DataFormatsFT0/RawEventData.h | 158 ++++++- Detectors/FIT/FT0/CMakeLists.txt | 1 + Detectors/FIT/FT0/raw/CMakeLists.txt | 17 + .../FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h | 430 ++++++++++++++++++ .../FT0/raw/include/FT0Raw/DataBlockReader.h | 132 ++++++ .../FT0/raw/include/FT0Raw/DigitBlockFT0.h | 135 ++++++ Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx | 16 + Detectors/FIT/FT0/raw/src/DataBlockReader.cxx | 15 + Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx | 17 + Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h | 24 + Detectors/FIT/FT0/workflow/CMakeLists.txt | 12 +- .../FT0Workflow/FT0DataProcessDPLSpec.h | 60 +++ .../FT0Workflow/FT0DataReaderDPLSpec.h | 63 +++ .../include/FT0Workflow/FT0Workflow.h | 25 + .../workflow/src/FT0DataProcessDPLSpec.cxx | 50 ++ .../FT0/workflow/src/FT0DataReaderDPLSpec.cxx | 80 ++++ .../FIT/FT0/workflow/src/FT0Workflow.cxx | 33 ++ .../FIT/FT0/workflow/src/RecoWorkflow.cxx | 2 + .../FIT/FT0/workflow/src/ft0-flp-workflow.cxx | 47 ++ 20 files changed, 1307 insertions(+), 25 deletions(-) create mode 100644 Detectors/FIT/FT0/raw/CMakeLists.txt create mode 100644 Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h create mode 100644 Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h create mode 100644 Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h create mode 100644 Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx create mode 100644 Detectors/FIT/FT0/raw/src/DataBlockReader.cxx create mode 100644 Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx create mode 100644 Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataProcessDPLSpec.h create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h create mode 100644 Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx create mode 100644 Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx create mode 100644 Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx create mode 100644 Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h index b139213474be5..caa1e6cac5526 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h @@ -48,13 +48,15 @@ class LookUpTable /// Default constructor. /// It must be kept public for root persistency purposes, /// but should never be called by the outside world - LookUpTable() = default; + //LookUpTable() = default; + explicit LookUpTable(std::vector<Topo> const& topoVector) : mTopoVector(topoVector), mInvTopo(topoVector.size()) { for (size_t channel = 0; channel < mTopoVector.size(); ++channel) mInvTopo.at(getIdx(mTopoVector[channel].mPM, mTopoVector[channel].mMCP)) = channel; } + ~LookUpTable() = default; void printFullMap() const { @@ -72,6 +74,17 @@ class LookUpTable int getLink(int channel) const { return mTopoVector[channel].mPM; } int getMCP(int channel) const { return mTopoVector[channel].mMCP; } + static o2::ft0::LookUpTable linear() + { + std::vector<o2::ft0::Topo> lut_data(NUMBER_OF_MCPs * NUMBER_OF_PMs); + for (int link = 0; link < NUMBER_OF_PMs; ++link) { + for (int mcp = 0; mcp < NUMBER_OF_MCPs; ++mcp) { + lut_data[link * NUMBER_OF_MCPs + mcp] = o2::ft0::Topo{link, mcp}; + } + } + return o2::ft0::LookUpTable{lut_data}; + } + private: std::vector<Topo> mTopoVector; std::vector<int> mInvTopo; diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h index 4ebe0341e5779..32216663c537f 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h @@ -21,6 +21,7 @@ #include <CommonDataFormat/InteractionRecord.h> #include <Framework/Logger.h> #include <iostream> +#include <utility> #include <cstring> #include "Rtypes.h" namespace o2 @@ -30,25 +31,51 @@ namespace ft0 constexpr int Nchannels_FT0 = 208; constexpr int Nchannels_PM = 12; constexpr int NPMs = 19; +constexpr size_t sizeWord = 16; struct EventHeader { - static constexpr int PayloadSize = 16; + static constexpr size_t PayloadSize = 16; //should be equal to 10 + static constexpr size_t PayloadPerGBTword = 16; //should be equal to 10 + static constexpr int MinNelements = 1; + static constexpr int MaxNelements = 1; union { uint64_t word[2] = {}; struct { uint64_t bc : 12; uint64_t orbit : 32; - uint64_t reservedField1 : 20; + uint64_t phase : 3; + uint64_t errorPhase : 1; + uint64_t reservedField1 : 16; uint64_t reservedField2 : 8; uint64_t nGBTWords : 4; uint64_t startDescriptor : 4; uint64_t reservedField3 : 48; }; }; + InteractionRecord getIntRec() { return InteractionRecord{(uint16_t)bc, (uint32_t)orbit}; } + + void print() + { + + std::cout << std::hex; + std::cout << "################EventHeader###############" << std::endl; + std::cout << "startDescriptor: " << startDescriptor << std::endl; + std::cout << "nGBTWords: " << nGBTWords << std::endl; + std::cout << "BC: " << bc << std::endl; + std::cout << "Orbit: " << orbit << std::endl; + std::cout << "##########################################" << std::endl; + + std::cout << std::dec; + } }; struct EventData { + static constexpr size_t PayloadSize = 5; + static constexpr size_t PayloadPerGBTword = 10; + static constexpr int MinNelements = 1; + static constexpr int MaxNelements = 12; + union { - uint64_t word = {0}; + uint64_t word = {0}; //should be struct { int64_t time : 12; int64_t charge : 13; @@ -65,31 +92,116 @@ struct EventData { channelID : 4; }; }; - uint64_t word_zeros = 0x0; - static const size_t PayloadSizeSecondWord = 11; - static const size_t PayloadSizeFirstWord = 5; + void print() + { + + std::cout << std::hex; + std::cout << "###############EventData(PM)##############" << std::endl; + std::cout << "------------Channel " << channelID << "------------" << std::endl; + std::cout << "Charge: " << charge << std::endl; + std::cout << "Time: " << time << std::endl; + std::cout << "1TimeLostEvent: " << is1TimeLostEvent << std::endl; + std::cout << "2TimeLostEvent: " << is2TimeLostEvent << std::endl; + std::cout << "ADCinGate: " << isADCinGate << std::endl; + std::cout << "AmpHigh: " << isAmpHigh << std::endl; + std::cout << "DoubleEvent: " << isDoubleEvent << std::endl; + std::cout << "EventInTVDC: " << isEventInTVDC << std::endl; + std::cout << "TimeInfoLate: " << isTimeInfoLate << std::endl; + std::cout << "TimeInfoLost: " << isTimeInfoLost << std::endl; + std::cout << "numberADC: " << numberADC << std::endl; + std::cout << "##########################################" << std::endl; + + std::cout << std::dec; + } + uint64_t word_zeros = 0x0; //to remove + static const size_t PayloadSizeSecondWord = 11; //to remove + static const size_t PayloadSizeFirstWord = 5; //to remove }; struct TCMdata { - static constexpr int PayloadSize = 16; + static constexpr size_t PayloadSize = 16; //should be equal to 10 + static constexpr size_t PayloadPerGBTword = 16; //should be equal to 10 + static constexpr int MinNelements = 1; + static constexpr int MaxNelements = 1; + uint64_t orC : 1, // 0 bit (0 byte) + orA : 1, //1 bit + sCen : 1, //2 bit + cen : 1, //3 bit + vertex : 1, //4 bit + reservedField1 : 3, //5 bit + nChanA : 7, //8 bit(1 byte) + reservedField2 : 1, //15 bit + nChanC : 7, //16 bit(2 byte) + reservedField3 : 1; // 23 bit + int64_t amplA : 17, //24 bit (3 byte) + reservedField4 : 1, //41 bit + amplC : 17, //42 bit. + reservedField5 : 1, //59 bit. + //in standard case(without __atribute__((packed)) macros, or packing by using union) + //here will be empty 4 bits, end next field("timeA") will start from 64 bit. + timeA : 9, //60 bit + reservedField6 : 1, //69 bit + timeC : 9, //70 bit + reservedField7 : 1, //79 bit + reservedField8 : 48; //80 bit + + void print() + { + std::cout << std::hex; + std::cout << "################TCMdata###################" << std::endl; + std::cout << "orC: " << orC << std::endl; + std::cout << "orA: " << orA << std::endl; + std::cout << "sCen: " << sCen << std::endl; + std::cout << "cen: " << cen << std::endl; + std::cout << "vertex: " << vertex << std::endl; + std::cout << "nChanA: " << nChanA << std::endl; + std::cout << "nChanC: " << nChanC << std::endl; + std::cout << "amplA: " << amplA << std::endl; + std::cout << "amplC: " << amplC << std::endl; + std::cout << "timeA: " << timeA << std::endl; + std::cout << "timeC: " << timeC << std::endl; + std::cout << "##########################################" << std::endl; + + std::cout << std::dec; + } + + //temporary, this method should be in Triggers struct + void pushTrgData(Triggers& trg) + { + trg.triggersignals = ((bool)orA << Triggers::bitA) | + ((bool)orC << Triggers::bitC) | + ((bool)vertex << Triggers::bitVertex) | + ((bool)cen << Triggers::bitCen) | + ((bool)sCen << Triggers::bitSCen); + trg.nChanA = (int8_t)nChanA; + trg.nChanC = (int8_t)nChanC; + trg.amplA = (int32_t)amplA; + trg.amplC = (int32_t)amplC; + trg.timeA = (int16_t)timeA; + trg.timeC = (int16_t)timeC; + } +} __attribute__((__packed__)); + +struct TCMdataExtended { + static constexpr size_t PayloadSize = 4; + static constexpr size_t PayloadPerGBTword = 10; + static constexpr int MinNelements = 1; + static constexpr int MaxNelements = 20; union { - uint64_t word[2] = {0}; - struct { - uint64_t orC : 1, - orA : 1, - sCen : 1, - cen : 1, - vertex : 1, - nChanA : 7, - nChanC : 7; - int64_t amplA : 18, - amplC : 18, - reservedField1 : 1, //56B, PayloadSize1stWord 6 - timeA : 9, - timeC : 9, - reservedField2 : 46; - }; + uint32_t word[1] = {}; + uint32_t triggerWord; }; + + void print() + { + + std::cout << std::hex; + std::cout << "############TCMdataExtended###############" << std::endl; + std::cout << "triggerWord: " << triggerWord << std::endl; + std::cout << "##########################################" << std::endl; + + std::cout << std::dec; + } }; class RawEventData diff --git a/Detectors/FIT/FT0/CMakeLists.txt b/Detectors/FIT/FT0/CMakeLists.txt index 0fffd09372ef7..ba81588e3beb4 100644 --- a/Detectors/FIT/FT0/CMakeLists.txt +++ b/Detectors/FIT/FT0/CMakeLists.txt @@ -9,6 +9,7 @@ # submit itself to any jurisdiction. add_subdirectory(base) +add_subdirectory(raw) add_subdirectory(reconstruction) add_subdirectory(simulation) add_subdirectory(workflow) diff --git a/Detectors/FIT/FT0/raw/CMakeLists.txt b/Detectors/FIT/FT0/raw/CMakeLists.txt new file mode 100644 index 0000000000000..8c0f3cbdf0767 --- /dev/null +++ b/Detectors/FIT/FT0/raw/CMakeLists.txt @@ -0,0 +1,17 @@ +#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_library(FT0Raw + SOURCES src/DataBlockRaw.cxx src/DigitBlockFT0.cxx src/DataBlockReader.cxx + PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::DataFormatsFT0) + +o2_target_root_dictionary(FT0Raw + HEADERS include/FT0Raw/DataBlockRaw.h include/FT0Raw/DigitBlockFT0.h include/FT0Raw/DataBlockReader.h + LINKDEF src/FT0RawLinkDef.h) diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h new file mode 100644 index 0000000000000..5935e5e61785a --- /dev/null +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h @@ -0,0 +1,430 @@ +// 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 DataBlockRaw.h class for RAW data format data blocks +// +// Artur.Furs +// afurs@cern.ch +//DataBlockWrapper - wrapper for raw data structures +//There should be three static fields in raw data structs, which defines its "signature": +// payloadSize - actual payload size per one raw data struct element (can be larger than GBTword size!) +// payloadPerGBTword - maximum payload per one GBT word +// MaxNelements - maximum number of elements per data block(for header it should be equal to 1) +// +//Also it requares several methods: +// print() - for printing raw data structs +// getIntRec() - for InteractionRecord extraction, should be in Header struct + +//DataBlockBase - base class for making composition of raw data structures, uses CRTP(static polyporphism) +//usage: +// class DataBlockOfYourModule: public DataBlockBase< DataBlockOfYourModule, RawHeaderStruct, RawDataStruct ...> +// define "deserialization" method with deserialization logic for current DataBlock +// define "sanityCheck" method for checking if the DataBlock is correct +//Warning! Classes should be simple, without refs and pointers! +//TODO: +// need to use references on the DataBlock fileds, with fast access +// traites for classes and structs +// + +#ifndef ALICEO2_FIT_DATABLOCKRAW_H_ +#define ALICEO2_FIT_DATABLOCKRAW_H_ +#include <iostream> +#include <vector> +#include <Rtypes.h> +#include "CommonDataFormat/InteractionRecord.h" +#include <DataFormatsFT0/RawEventData.h> +#include <gsl/span> +#include <boost/mpl/inherit.hpp> +#include <boost/mpl/vector.hpp> + +#include <vector> +#include <tuple> +#include <array> +#include <iostream> +#include <cassert> + +namespace o2 +{ +namespace ft0 +{ +using RawHeaderPM = o2::ft0::EventHeader; +using RawDataPM = o2::ft0::EventData; +using RawHeaderTCM = o2::ft0::EventHeader; +using RawDataTCM = o2::ft0::TCMdata; +using RawHeaderTCMext = o2::ft0::EventHeader; +using RawDataTCMext = o2::ft0::TCMdataExtended; + +using namespace std; + +template <typename T> +struct DataBlockWrapper { + DataBlockWrapper() = default; + DataBlockWrapper(const DataBlockWrapper& other) = default; + DataBlockWrapper(DataBlockWrapper&& other) = default; + // virtual ~DataBlockWrapper() = default; + + std::vector<uint8_t> serialize(int nWords) + { + std::vector<uint8_t> vecBytes(sizeWord * nWords); + uint8_t* srcAddress = (uint8_t*)mData; + if (nWords == 0) + return std::move(vecBytes); + gsl::span<uint8_t> serializedBytes(vecBytes); + size_t countBytes = 0; + int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords - 1]); + for (int iStep = 0; iStep < nSteps; iStep++) { + memcpy(serializedBytes.data() + std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]), srcAddress + std::get<kDESTBYTEPOS>(sByteLookupTable[iStep]), std::get<kNBYTES>(sByteLookupTable[iStep])); + countBytes += std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]); + } + return std::move(vecBytes); + } + + void deserialize(const gsl::span<const uint8_t> inputBytes, int nWords, size_t& srcPos) + { + mNelements = 0; + mNwords = 0; + if (nWords == 0 || nWords > MaxNwords || inputBytes.size() - srcPos < nWords * sizeWord) { + //in case of bad fields responsible for deserialization logic, byte position will be pushed to the end of binary sequence + srcPos = inputBytes.size(); + return; + } + uint8_t* destAddress = (uint8_t*)mData; + size_t countBytes = 0; + int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords - 1]); + mNwords = nWords; + mNelements = std::get<kNELEMENTS>(sReadingLookupTable[nWords - 1]); + for (int iStep = 0; iStep < nSteps; iStep++) { + memcpy(destAddress + std::get<kDESTBYTEPOS>(sByteLookupTable[iStep]), inputBytes.data() + std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]) + srcPos, std::get<kNBYTES>(sByteLookupTable[iStep])); + countBytes += std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]); + } + srcPos += mNwords * sizeWord; + } + + static constexpr int MaxNwords = T::PayloadSize * T::MaxNelements / T::PayloadPerGBTword + (T::PayloadSize * T::MaxNelements % T::PayloadPerGBTword > 0); //calculating max GBT words per block + static constexpr int MaxNbytes = sizeWord * MaxNwords; + + //get number of byte reading steps + static constexpr size_t getNsteps() + { + int count = 0; + size_t payloadFull = T::MaxNelements * T::PayloadSize; + size_t payloadInWord = T::PayloadPerGBTword; + size_t payloadPerElem = T::PayloadSize; + while (payloadFull > 0) { + if (payloadPerElem < payloadInWord) { + count++; + payloadFull -= payloadPerElem; + payloadInWord -= payloadPerElem; + payloadPerElem = 0; + } else { + count++; + payloadFull -= payloadInWord; + payloadPerElem -= payloadInWord; + payloadInWord = 0; + } + if (payloadInWord == 0) + payloadInWord = T::PayloadPerGBTword; + if (payloadPerElem == 0) + payloadPerElem = T::PayloadSize; + } + return count; + } + //enumerator for tuple access: + //[Index] is index of step to read bytes + //kNBYTES - number of bytes to read from source and to write into destination + //kSRCBYTEPOS - Byte position in the source(binary raw data sequence) + //kDESTBYTEPOS - Byte position to write at destionation(memory allocation of T-element array) + //kELEMENTINDEX - element index at current step + //kWORDINDEX - word index at current step + // + enum AccessByteLUT { kNBYTES, + kSRCBYTEPOS, + kDESTBYTEPOS, + kELEMENTINDEX, + kWORDINDEX }; + static constexpr std::array<std::tuple<size_t, size_t, size_t, int, int>, getNsteps()> GetByteLookupTable() + { + std::array<std::tuple<size_t, size_t, size_t, int, int>, getNsteps()> seqBytes{}; + int count = 0; + int countElement = 0; + int countWord = 0; + size_t destBytePosPerElem = 0; + size_t srcBytePos = 0; + size_t payloadFull = T::MaxNelements * T::PayloadSize; + + size_t bytesInWord = sizeWord; + size_t payloadInWord = T::PayloadPerGBTword; + + size_t payloadPerElem = T::PayloadSize; + + uint64_t indexElem = 0; + uint64_t indexLastElem = T::MaxNelements - 1; + + while (payloadFull > 0) { + if (payloadPerElem < payloadInWord) { //new element + std::get<kNBYTES>(seqBytes[count]) = payloadPerElem; + std::get<kSRCBYTEPOS>(seqBytes[count]) = srcBytePos; + std::get<kDESTBYTEPOS>(seqBytes[count]) = destBytePosPerElem; + std::get<kELEMENTINDEX>(seqBytes[count]) = countElement; + std::get<kWORDINDEX>(seqBytes[count]) = countWord; + srcBytePos += payloadPerElem; + count++; + payloadFull -= payloadPerElem; + payloadInWord -= payloadPerElem; + bytesInWord -= payloadPerElem; + payloadPerElem = 0; + + } else { + std::get<kNBYTES>(seqBytes[count]) = payloadInWord; + std::get<kSRCBYTEPOS>(seqBytes[count]) = srcBytePos; + std::get<kDESTBYTEPOS>(seqBytes[count]) = destBytePosPerElem; + std::get<kELEMENTINDEX>(seqBytes[count]) = countElement; + std::get<kWORDINDEX>(seqBytes[count]) = countWord; + srcBytePos += bytesInWord; + count++; + destBytePosPerElem += payloadInWord; + + payloadFull -= payloadInWord; + payloadPerElem -= payloadInWord; + payloadInWord = 0; + bytesInWord = 0; + } + + if (payloadInWord == 0) + payloadInWord = T::PayloadPerGBTword; + if (payloadPerElem == 0) { + payloadPerElem = T::PayloadSize; + countElement++; + destBytePosPerElem = countElement * sizeof(T); + } + if (bytesInWord == 0) { + bytesInWord = sizeWord; + countWord++; + } + } + return seqBytes; + } + static constexpr std::array<std::tuple<size_t, size_t, size_t, int, int>, getNsteps()> sByteLookupTable = GetByteLookupTable(); + + //enumerator for tuple access: + //[Index] is word index position, i.e. "Index+1" number of words will be deserialized + //kNELEMENTS - number of T elements will be fully deserialized in "Index+1" words + //kNSTEPS - number of steps for reading "Index+1" words + //kISPARTED - if one T-element is parted at current word,i.e. current word contains partially deserialized T element at the end of the word + enum AccessReadingLUT { kNELEMENTS, + kNSTEPS, + kISPARTED }; + static constexpr std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords> GetReadingLookupTable() + { + std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords> readingScheme{}; + size_t payloadPerElem = T::PayloadSize; + int countWord = 0; + for (int iStep = 0; iStep < getNsteps(); iStep++) { + if (countWord < std::get<kWORDINDEX>((GetByteLookupTable())[iStep])) { //new word + std::get<kNSTEPS>(readingScheme[countWord]) = iStep; + std::get<kNELEMENTS>(readingScheme[countWord]) = std::get<kELEMENTINDEX>((GetByteLookupTable())[iStep]); + if (payloadPerElem > 0) { + std::get<kISPARTED>(readingScheme[countWord]) = true; + } else { + std::get<kISPARTED>(readingScheme[countWord]) = false; + } + countWord++; + } + if (payloadPerElem == 0) + payloadPerElem = T::PayloadSize; + payloadPerElem -= std::get<kNBYTES>((GetByteLookupTable())[iStep]); + } + //Last step checking + std::get<kNSTEPS>(readingScheme[countWord]) = getNsteps(); + if (payloadPerElem > 0) { + std::get<kISPARTED>(readingScheme[countWord]) = true; + std::get<kNELEMENTS>(readingScheme[countWord]) = std::get<kELEMENTINDEX>((GetByteLookupTable())[getNsteps() - 1]); + } else { + std::get<kISPARTED>(readingScheme[countWord]) = false; + std::get<kNELEMENTS>(readingScheme[countWord]) = std::get<kELEMENTINDEX>((GetByteLookupTable())[getNsteps() - 1]) + 1; + } + return readingScheme; + } + static constexpr std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords> sReadingLookupTable = GetReadingLookupTable(); + // + //Printing LookupTables + static void printLUT() + { + cout << endl + << "-------------------------------------------" << endl; + std::cout << "kNELEMENTS|kNSTEPS|kISPARTED" << std::endl; + for (int i = 0; i < MaxNwords; i++) { + std::cout << std::endl + << std::get<kNELEMENTS>(sReadingLookupTable[i]) << "|" + << std::get<kNSTEPS>(sReadingLookupTable[i]) << "|" + << std::get<kISPARTED>(sReadingLookupTable[i]) << endl; + } + cout << endl + << "-------------------------------------------" << endl; + std::cout << "kELEMENTINDEX|kWORDINDEX|kNBYTES|kSRCBYTEPOS|kDESTBYTEPOS" << std::endl; + for (int i = 0; i < getNsteps(); i++) { + cout << endl + << std::get<kELEMENTINDEX>(sByteLookupTable[i]) << "|" + << std::get<kWORDINDEX>(sByteLookupTable[i]) << "|" + << std::get<kNBYTES>(sByteLookupTable[i]) << "|" + << std::get<kSRCBYTEPOS>(sByteLookupTable[i]) << "|" + << std::get<kDESTBYTEPOS>(sByteLookupTable[i]) << endl; + } + } + void print() + { + assert(mNelements <= T::MaxNelements); + for (int i = 0; i < mNelements; i++) { + std::cout << "\nPringting element number: " << i << std::endl; + mData[i].print(); + } + } + T mData[T::MaxNelements]; + unsigned int mNelements; //number of deserialized elements; + unsigned int mNwords; //number of deserialized GBT words; +}; + +//CRTP(static polymorphism) + Composition over multiple inheritance(Header + multiple data structures) +template <class DataBlock, class Header, class... DataStructures> +class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataBlockWrapper<DataStructures>...>::type +{ + typedef boost::mpl::vector<DataStructures...> DataBlockTypes; + typedef DataBlockBase<DataBlock, Header, DataStructures...> TemplateHeader; + typedef typename boost::mpl::inherit<DataBlockWrapper<Header>, DataBlockWrapper<DataStructures>...>::type DataBlockDerivedBase; + + public: + DataBlockBase() = default; + DataBlockBase(const DataBlockBase& other) = default; + + virtual ~DataBlockBase() = default; + + static void printLUT() + { + DataBlockWrapper<Header>::printLUT(); + (static_cast<void>(DataBlockWrapper<DataStructures>::printLUT()), ...); + } + + void print() + { + LOG(INFO) << "HEADER"; + DataBlockWrapper<Header>::print(); + LOG(INFO) << "DATA"; + (static_cast<void>(DataBlockWrapper<DataStructures>::print()), ...); + } + + InteractionRecord getInteractionRecord() + { + return DataBlockWrapper<Header>::mData[0].getIntRec(); + } + // + //use this for block decoding + void decodeBlock(gsl::span<const uint8_t> payload, size_t srcPos) + { + mSize = 0; + size_t bytePos = srcPos; + static_cast<DataBlock*>(this)->deserialize(payload, bytePos); + mSize = bytePos - srcPos; + //checking sanity and updating + update(); + } + + bool isCorrect() { return mIsCorrect; } + + void update() + { + mIsCorrect = true; + isNonZeroBlockSizes(mIsCorrect, DataBlockWrapper<Header>::mNelements); // checking sub-block(header) size + (isNonZeroBlockSizes(mIsCorrect, DataBlockWrapper<DataStructures>::mNelements), ...); // checking sub-block sizes + static_cast<DataBlock*>(this)->sanityCheck(mIsCorrect); + } + + size_t mSize; //deserialized size + bool mIsCorrect; + + protected: + //check if there are sub blocks with zero number of elements + void isNonZeroBlockSizes(bool& flag, unsigned int nElements) { flag &= (bool)nElements; } + //void updateSize(size_t blockSize) { mSize += blockSize; } +}; + +//FT0 DATA BLOCK DEFINITIONS + +//standard data block from PM +class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> +{ + public: + DataBlockPM() = default; + DataBlockPM(const DataBlockPM& other) = default; + virtual ~DataBlockPM() = default; + void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) + { + DataBlockWrapper<RawHeaderPM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderPM>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataPM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderPM>::mData[0].nGBTWords, srcByteShift); + } + //Custom sanity checking for current deserialized block + // put here code for raw data checking + void sanityCheck(bool& flag) + { + if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) + DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling + //TODO + } + // + ClassDefNV(DataBlockPM, 1); +}; +//standard data block from TCM +class DataBlockTCM : public DataBlockBase<DataBlockTCM, RawHeaderTCM, RawDataTCM> +{ + public: + DataBlockTCM() = default; + DataBlockTCM(const DataBlockTCM& other) = default; + virtual ~DataBlockTCM() = default; + void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) + { + DataBlockWrapper<RawHeaderTCM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCM>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataTCM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCM>::mData[0].nGBTWords, srcByteShift); + } + //Custom sanity checking for current deserialized block + // put here code for raw data checking + void sanityCheck(bool& flag) + { + + } //TODO + // + ClassDefNV(DataBlockTCM, 1); +}; + +//extended TCM mode, 1 TCMdata + 8 TCMdataExtendedstructs +class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, RawDataTCM, RawDataTCMext> +{ + public: + DataBlockTCMext() = default; + DataBlockTCMext(const DataBlockTCMext& other) = default; + virtual ~DataBlockTCMext() = default; + void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) + { + DataBlockWrapper<RawHeaderTCMext>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCMext>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataTCM>::deserialize(srcBytes, DataBlockWrapper<RawDataTCM>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataTCMext>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCMext>::mData[0].nGBTWords - DataBlockWrapper<RawDataTCM>::MaxNwords, srcByteShift); + } + + //Custom sanity checking for current deserialized block + // put here code for raw data checking + void sanityCheck(bool& flag) + { + + } //TODO + // + ClassDefNV(DataBlockTCMext, 1); +}; + +} // namespace ft0 +} // namespace o2 +#endif diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h new file mode 100644 index 0000000000000..5c5ca481f761f --- /dev/null +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h @@ -0,0 +1,132 @@ +// 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 DataBlockReader.h class for RAW data reading +// +// Artur.Furs +// afurs@cern.ch +// +//Main purpuse is to decode FT0 data blocks and push them to DigitBlockFT0 for proccess +//TODO: +// in place contruction, change push_back to emplace_back in DataBlockReader +// move semantic for DataBlocks + +#ifndef ALICEO2_FIT_DATABLOCKREADER_H_ +#define ALICEO2_FIT_DATABLOCKREADER_H_ +#include <iostream> +#include <vector> +#include <Rtypes.h> +#include "FT0Raw/DataBlockRaw.h" +#include "FT0Raw/DigitBlockFT0.h" +#include <boost/mpl/inherit.hpp> +#include <boost/mpl/vector.hpp> + +#include <CommonDataFormat/InteractionRecord.h> +#include "Headers/RAWDataHeader.h" +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" + +#include <gsl/span> +namespace o2 +{ +namespace ft0 +{ + +template <class DataBlockType> +class DataBlockReader +{ + public: + DataBlockReader() = default; + // ~DataBlockReader() = default; + typedef DataBlockType DataBlock; + size_t decodeBlocks(const gsl::span<const uint8_t> binaryPayload, std::vector<DataBlockType>& vecDataBlocks) + { + size_t srcPos = 0; + while (srcPos < binaryPayload.size()) { //checking element + DataBlockType dataBlock; + dataBlock.decodeBlock(binaryPayload, srcPos); + srcPos += dataBlock.mSize; + if (dataBlock.isCorrect()) + vecDataBlocks.push_back(dataBlock); + } + return srcPos; + } +}; + +//Composition over multiple inheritance(multiple data block reader) +template <class DigitBlockType, class... DataBlockTypes> +class RawReaderBase : public boost::mpl::inherit<DataBlockReader<DataBlockTypes>...>::type +{ + public: + typedef boost::mpl::vector<DataBlockTypes...> DataBlockVectorTypes; + typedef boost::mpl::vector<DataBlockReader<DataBlockTypes>...> ReaderTypes; + RawReaderBase() = default; + ~RawReaderBase() = default; + + std::map<InteractionRecord, DigitBlockType> mMapDigits; + template <class DataBlockType> + void pushDataBlock(gsl::span<const uint8_t> payload, int linkID) + { + std::vector<DataBlockType> vecDataBlocks; + auto srcPos = DataBlockReader<DataBlockType>::decodeBlocks(payload, vecDataBlocks); + for (auto& dataBlock : vecDataBlocks) { + auto intRec = dataBlock.getInteractionRecord(); + auto [digitIter, isNew] = mMapDigits.try_emplace(intRec, intRec); + digitIter->second.template proccess<DataBlockType>(dataBlock, linkID); + } + } +}; + +// Raw reader for FT0 +template <bool IsExtendedMode = false> +class RawReaderFT0 : public RawReaderBase<DigitBlockFT0, DataBlockPM, typename std::conditional<IsExtendedMode, DataBlockTCMext, DataBlockTCM>::type> +{ + public: + typedef typename std::conditional<IsExtendedMode, DataBlockTCMext, DataBlockTCM>::type DataBlockTCMtype; + typedef RawReaderBase<DigitBlockFT0, DataBlockPM, DataBlockTCMtype> RawReaderBaseType; + + RawReaderFT0() {} + ~RawReaderFT0() = default; + //deserialize payload to raw data blocks and proccesss them to digits + void proccess(int linkID, gsl::span<const uint8_t> payload) + { + if (0 <= linkID && linkID < 18) { + //PM data proccessing + RawReaderBaseType::template pushDataBlock<DataBlockPM>(payload, linkID); + } else if (linkID == 18) { + //TCM data proccessing + RawReaderBaseType::template pushDataBlock<DataBlockTCMtype>(payload, linkID); + } else { + //put here code in case of bad rdh.linkID value + LOG(INFO) << "WARNING! WRONG LINK ID!"; + return; + } + + // + } + //pop digits + int popDigits(std::vector<Digit>& vecDigit, std::vector<ChannelData>& vecChannelData) + { + int digitCounter = RawReaderBaseType::mMapDigits.size(); + for (auto& digit : (RawReaderBaseType::mMapDigits)) { + digit.second.popData(vecDigit, vecChannelData); + //digitCounter++; + } + (RawReaderBaseType::mMapDigits).clear(); + return digitCounter; + } + + ClassDefNV(RawReaderFT0, 1); +}; + +} // namespace ft0 +} // namespace o2 + +#endif diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h new file mode 100644 index 0000000000000..a109d46ab6c14 --- /dev/null +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h @@ -0,0 +1,135 @@ +// 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 DigitBlockFT0.h class for proccessing RAW data into Digits +// +// Artur.Furs +// afurs@cern.ch +// TODO: +// traites for DataBlocks +// check if the EventID filling is correct + +#ifndef ALICEO2_FIT_DIGITBLOCKFT0_H_ +#define ALICEO2_FIT_DIGITBLOCKFT0_H_ +#include <iostream> +#include <vector> +#include <algorithm> +#include <Rtypes.h> +#include "FT0Raw/DataBlockRaw.h" +#include <CommonDataFormat/InteractionRecord.h> +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" +#include "DataFormatsFT0/LookUpTable.h" + +#include <boost/mpl/vector.hpp> +#include <boost/mpl/contains.hpp> + +#include <gsl/span> +namespace o2 +{ +namespace ft0 +{ + +class DigitBlockFT0 +{ + //Mandatory to fill! Just add class type into corresponding template header. + typedef boost::mpl::vector<DataBlockPM, DataBlockTCM, DataBlockTCMext> ProccessBlockTypes; + //typedef boost::mpl::vector<DataBlockTCM,DataBlockTCMext> TrgInfoTypes; + // + public: + DigitBlockFT0(o2::InteractionRecord intRec) { mDigit.mIntRecord = intRec; } + DigitBlockFT0() = default; + DigitBlockFT0(const DigitBlockFT0& other) = default; + //~DigitBlockFT0() = default; + + Digit mDigit; + std::vector<ChannelData> mVecChannelData; + static o2::ft0::LookUpTable sLookupTable; + static int sEventID; + template <class DataBlockType> + //,typename enable_if<boost::mpl::contains<ProccessBlockTypes,DataBlockType>::type::value>::type > //TODO traits + void proccess(DataBlockType& dataBlock, int linkID) + { + if constexpr (std::is_same<DataBlockType, DataBlockPM>::value) { //Filling data from PM + for (int iEventData = 0; iEventData < dataBlock.DataBlockWrapper<RawDataPM>::mNelements; iEventData++) { + mVecChannelData.emplace_back(int(sLookupTable.getChannel(linkID, dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].channelID)), + int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].time), + int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].charge), + int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].numberADC)); + } + } else if constexpr (std::is_same<DataBlockType, DataBlockTCM>::value) { //Filling data from TCM (normal/extended mode) + dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].pushTrgData(mDigit.mTriggers); + } + + else if constexpr (std::is_same<DataBlockType, DataBlockTCMext>::value) { //Filling data from TCM, extended mode. Same proccess as for normal mode, for now. + dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].pushTrgData(mDigit.mTriggers); + } + } + void popData(std::vector<Digit>& vecDigits, std::vector<ChannelData>& vecChannelData) + { + //last digit filling + mDigit.ref.set(vecChannelData.size(), mVecChannelData.size()); + mDigit.mEventID = sEventID; + // + vecDigits.push_back(std::move(mDigit)); + std::move(mVecChannelData.begin(), mVecChannelData.end(), std::back_inserter(vecChannelData)); + mVecChannelData.clear(); + + sEventID++; //Increasing static eventID. After each poping of the data, it will increase + } + void print() + { + std::cout << "\n______________DIGIT DATA____________"; + std::cout << std::hex; + std::cout << "\nBC: " << mDigit.mIntRecord.bc << "| ORBIT: " << mDigit.mIntRecord.orbit; + std::cout << "\nRef first: " << mDigit.ref.getFirstEntry() << "| Ref entries: " << mDigit.ref.getEntries(); + std::cout << "\nmTrigger: " << static_cast<uint16_t>(mDigit.mTriggers.triggersignals); + std::cout << "\nnChanA: " << static_cast<uint16_t>(mDigit.mTriggers.nChanA) << " | nChanC: " << static_cast<uint16_t>(mDigit.mTriggers.nChanC); + std::cout << "\namplA: " << mDigit.mTriggers.amplA << " | amplC: " << mDigit.mTriggers.amplC; + std::cout << "\ntimeA: " << mDigit.mTriggers.timeA << " | timeC: " << mDigit.mTriggers.timeC; + + std::cout << "\n______________CHANNEL DATA____________\n"; + std::cout << "\nN channel: " << mVecChannelData.size(); + for (const auto& chData : mVecChannelData) { + std::cout << "\nChId: " << static_cast<uint16_t>(chData.ChId) << " | ChainQTC:" << static_cast<uint16_t>(chData.ChainQTC) << " | CFDTime: " << chData.CFDTime << " | QTCAmpl: " << chData.QTCAmpl; + } + std::cout << std::dec; + std::cout << "\n"; + LOG(INFO) << "______________________________________"; + } + + static void print(std::vector<Digit>& vecDigit, std::vector<ChannelData>& vecChannelData) + { + for (const auto& digit : vecDigit) { + std::cout << "\n______________DIGIT DATA____________"; + std::cout << std::hex; + std::cout << "\nBC: " << digit.mIntRecord.bc << "| ORBIT: " << digit.mIntRecord.orbit << " | EventID: " << digit.mEventID; + std::cout << "\nRef first: " << digit.ref.getFirstEntry() << "| Ref entries: " << digit.ref.getEntries(); + std::cout << "\nmTrigger: " << static_cast<uint16_t>(digit.mTriggers.triggersignals); + std::cout << "\nnChanA: " << static_cast<uint16_t>(digit.mTriggers.nChanA) << " | nChanC: " << static_cast<uint16_t>(digit.mTriggers.nChanC); + std::cout << "\namplA: " << digit.mTriggers.amplA << " | amplC: " << digit.mTriggers.amplC; + std::cout << "\ntimeA: " << digit.mTriggers.timeA << " | timeC: " << digit.mTriggers.timeC; + + std::cout << "\n______________CHANNEL DATA____________\n"; + for (int iChData = digit.ref.getFirstEntry(); iChData < digit.ref.getFirstEntry() + digit.ref.getEntries(); iChData++) { + + std::cout << "\nChId: " << static_cast<uint16_t>(vecChannelData[iChData].ChId) << " | ChainQTC:" << static_cast<uint16_t>(vecChannelData[iChData].ChainQTC) + << " | CFDTime: " << vecChannelData[iChData].CFDTime << " | QTCAmpl: " << vecChannelData[iChData].QTCAmpl; + } + std::cout << std::dec; + std::cout << "\n______________________________________\n"; + } + } + ClassDefNV(DigitBlockFT0, 1); +}; + +} // namespace ft0 +} // namespace o2 +#endif diff --git a/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx b/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx new file mode 100644 index 0000000000000..eb4bc06850245 --- /dev/null +++ b/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx @@ -0,0 +1,16 @@ +// 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 "FT0Raw/DataBlockRaw.h" +using namespace o2::ft0; + +ClassImp(DataBlockPM); +ClassImp(DataBlockTCM); +ClassImp(DataBlockTCMext); diff --git a/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx b/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx new file mode 100644 index 0000000000000..6a869f7f3ec6b --- /dev/null +++ b/Detectors/FIT/FT0/raw/src/DataBlockReader.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 "FT0Raw/DataBlockReader.h" +using namespace o2::ft0; + +ClassImp(RawReaderFT0<true>); +ClassImp(RawReaderFT0<false>); diff --git a/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx new file mode 100644 index 0000000000000..ab36f0a1a613e --- /dev/null +++ b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx @@ -0,0 +1,17 @@ +// 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 "FT0Raw/DigitBlockFT0.h" +using namespace o2::ft0; + +ClassImp(DigitBlockFT0); + +int DigitBlockFT0::sEventID = 0; +o2::ft0::LookUpTable DigitBlockFT0::sLookupTable = o2::ft0::LookUpTable::linear(); diff --git a/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h b/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h new file mode 100644 index 0000000000000..c01219fcc0901 --- /dev/null +++ b/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h @@ -0,0 +1,24 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::ft0::DataBlockPM + ; +#pragma link C++ class o2::ft0::DataBlockTCM + ; +#pragma link C++ class o2::ft0::DataBlockTCMext + ; +#pragma link C++ class o2::ft0::DigitBlockFT0 + ; +#pragma link C++ class o2::ft0::RawReaderFT0 < true> + ; +#pragma link C++ class o2::ft0::RawReaderFT0 < false> + ; + +#endif diff --git a/Detectors/FIT/FT0/workflow/CMakeLists.txt b/Detectors/FIT/FT0/workflow/CMakeLists.txt index 03363c8da6187..993e4d3aeec66 100644 --- a/Detectors/FIT/FT0/workflow/CMakeLists.txt +++ b/Detectors/FIT/FT0/workflow/CMakeLists.txt @@ -16,11 +16,15 @@ o2_add_library(FT0Workflow src/EntropyEncoderSpec.cxx src/EntropyDecoderSpec.cxx src/DigitReaderSpec.cxx + src/FT0Workflow.cxx + src/FT0DataProcessDPLSpec.cxx + src/FT0DataReaderDPLSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsFT0 O2::FT0Reconstruction O2::DetectorsCommonDataFormats - O2::DPLUtils) + O2::DPLUtils + O2::FT0Raw) o2_add_executable(reco-workflow SOURCES src/ft0-reco-workflow.cxx @@ -38,6 +42,12 @@ o2_add_executable(digits-reader-workflow COMPONENT_NAME ft0 PUBLIC_LINK_LIBRARIES O2::FT0Workflow) +o2_add_executable(flp-dpl-workflow + COMPONENT_NAME ft0 + SOURCES src/ft0-flp-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::FT0Workflow + TARGETVARNAME ft0flpexe) + if(NOT APPLE) set_property(TARGET ${fitrecoexe} PROPERTY LINK_WHAT_YOU_USE ON) endif() diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataProcessDPLSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataProcessDPLSpec.h new file mode 100644 index 0000000000000..0f79510037f09 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataProcessDPLSpec.h @@ -0,0 +1,60 @@ +// 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 FT0DataProcessDPLSpec.h + +#ifndef O2_FT0DATAPROCESSDPLSPEC_H +#define O2_FT0DATAPROCESSDPLSPEC_H + +#include "Framework/CallbackService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/Lifetime.h" +#include "Framework/Output.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/SerializationMethods.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" + +#include "FT0Raw/DigitBlockFT0.h" +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" + +#include <iostream> +#include <vector> +#include <gsl/span> + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +class FT0DataProcessDPLSpec : public Task +{ + public: + FT0DataProcessDPLSpec(bool dumpEventBlocks) : mDumpEventBlocks(dumpEventBlocks) {} + ~FT0DataProcessDPLSpec() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + + private: + bool mDumpEventBlocks; + + o2::header::DataOrigin mOrigin = o2::header::gDataOriginFT0; +}; + +framework::DataProcessorSpec getFT0DataProcessDPLSpec(bool dumpProcessor); + +} // namespace ft0 +} // namespace o2 + +#endif /* O2_FT0DATAPROCESSDPL_H */ diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h new file mode 100644 index 0000000000000..cf6b7f0d4079d --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h @@ -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. + +/// @file FT0DataReaderDPLSpec.h + +#ifndef O2_FT0DATAREADERDPLSPEC_H +#define O2_FT0DATAREADERDPLSPEC_H + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "Framework/CallbackService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/Lifetime.h" +#include "Framework/Output.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/SerializationMethods.h" +#include "DPLUtils/DPLRawParser.h" +#include "FT0Raw/DataBlockReader.h" +#include "FT0Raw/DigitBlockFT0.h" + +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" +#include <iostream> +#include <vector> +#include <gsl/span> +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ +template <bool IsExtendedMode> +class FT0DataReaderDPLSpec : public Task +{ + public: + FT0DataReaderDPLSpec(bool dumpEventBlocks, bool isExtendedMode) : mIsExtendedMode(isExtendedMode), mDumpEventBlocks(dumpEventBlocks) {} + ~FT0DataReaderDPLSpec() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + + private: + bool mDumpEventBlocks; + bool mIsExtendedMode; + std::vector<Digit> mVecDigits; + std::vector<ChannelData> mVecChannelData; + RawReaderFT0<IsExtendedMode> mRawReaderFT0; + o2::header::DataOrigin mOrigin = o2::header::gDataOriginFT0; +}; +framework::AlgorithmSpec getAlgorithmSpec(bool dumpReader, bool isExtendedMode); +framework::DataProcessorSpec getFT0DataReaderDPLSpec(bool dumpReader, bool isExtendedMode); + +} // namespace ft0 +} // namespace o2 + +#endif /* O2_FT0DATAREADERDPL_H */ diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h new file mode 100644 index 0000000000000..5e833c0103cfc --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h @@ -0,0 +1,25 @@ +// 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_FIT_FT0WORKFLOW_H +#define O2_FIT_FT0WORKFLOW_H + +/// @file FT0Workflow.h + +#include "Framework/WorkflowSpec.h" + +namespace o2 +{ +namespace fit +{ +framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, bool dumpProcessor, bool dumpReader); +} // namespace fit +} // namespace o2 +#endif diff --git a/Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx new file mode 100644 index 0000000000000..7fe7de20506b9 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx @@ -0,0 +1,50 @@ +// 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 FT0DataProcessDPLSpec.cxx + +#include "FT0Workflow/FT0DataProcessDPLSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ +using namespace std; +void FT0DataProcessDPLSpec::init(InitContext& ic) +{ +} + +void FT0DataProcessDPLSpec::run(ProcessingContext& pc) +{ + LOG(INFO) << "FT0DataProcessDPLSpec running..."; + auto vecDigits = pc.inputs().get<std::vector<Digit>>("digits"); + auto vecChannelData = pc.inputs().get<std::vector<ChannelData>>("digch"); + if (mDumpEventBlocks) + DigitBlockFT0::print(vecDigits, vecChannelData); +} + +DataProcessorSpec getFT0DataProcessDPLSpec(bool dumpProcessor) +{ + std::vector<InputSpec> inputSpec; + inputSpec.emplace_back("digits", o2::header::gDataOriginFT0, "DIGITSBC", 0, Lifetime::Timeframe); + inputSpec.emplace_back("digch", o2::header::gDataOriginFT0, "DIGITSCH", 0, Lifetime::Timeframe); + LOG(INFO) << "DataProcessorSpec getFT0DataProcessDPLSpec"; + return DataProcessorSpec{ + "ft0-dataprocess-dpl-flp", + inputSpec, + Outputs{}, + AlgorithmSpec{adaptFromTask<FT0DataProcessDPLSpec>(dumpProcessor)}, + Options{}}; +} + +} // namespace ft0 +} // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx new file mode 100644 index 0000000000000..13d75de77dbb6 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx @@ -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. + +/// @file FT0DataReaderDPLSpec.cxx + +#include "FT0Workflow/FT0DataReaderDPLSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ +using namespace std; +template <bool IsExtendedMode> +void FT0DataReaderDPLSpec<IsExtendedMode>::init(InitContext& ic) + +{ +} +template <bool IsExtendedMode> +void FT0DataReaderDPLSpec<IsExtendedMode>::run(ProcessingContext& pc) + +{ + DPLRawParser parser(pc.inputs()); + mVecDigits.clear(); + mVecChannelData.clear(); + LOG(INFO) << "FT0DataReaderDPLSpec"; + uint64_t count = 0; + for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { + //Proccessing each page + count++; + //auto rdhPtr = it.get_if<o2::header::RAWDataHeader>(); //PROBLEM! + //auto rdhPtr = it.get_if<o2::header::RAWDataHeaderV4>(); + auto rdhPtr = it.get_if<o2::header::RAWDataHeaderV6>(); + + gsl::span<const uint8_t> payload(it.data(), it.size()); + mRawReaderFT0.proccess(rdhPtr->linkID, payload); + } + + mRawReaderFT0.popDigits(mVecDigits, mVecChannelData); + LOG(INFO) << "Number of Digits: " << mVecDigits.size(); + LOG(INFO) << "Number of ChannelData: " << mVecChannelData.size(); + if (mDumpEventBlocks) + DigitBlockFT0::print(mVecDigits, mVecChannelData); + pc.outputs().snapshot(Output{o2::header::gDataOriginFT0, "DIGITSBC", 0, Lifetime::Timeframe}, mVecDigits); + pc.outputs().snapshot(Output{o2::header::gDataOriginFT0, "DIGITSCH", 0, Lifetime::Timeframe}, mVecChannelData); +} +AlgorithmSpec getAlgorithmSpec(bool dumpReader, bool isExtendedMode) +{ + if (isExtendedMode) { + LOG(INFO) << "TCM mode: extended, additional TCM data blocks(TCMdataExtended) will be in payload from TCM!"; + return adaptFromTask<FT0DataReaderDPLSpec<true>>(dumpReader, isExtendedMode); + } + LOG(INFO) << "TCM mode: normal, only TCMdata will be in payload from TCM."; + return adaptFromTask<FT0DataReaderDPLSpec<false>>(dumpReader, isExtendedMode); +} + +DataProcessorSpec getFT0DataReaderDPLSpec(bool dumpReader, bool isExtendedMode) +{ + std::vector<OutputSpec> outputSpec; + outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSBC", 0, Lifetime::Timeframe); + outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSCH", 0, Lifetime::Timeframe); + LOG(INFO) << "DataProcessorSpec getFT0DataReaderDPLSpec"; + return DataProcessorSpec{ + "ft0-datareader-dpl-flp", + o2::framework::select("TF:FT0/RAWDATA"), + outputSpec, + getAlgorithmSpec(dumpReader, isExtendedMode), + Options{}}; +} + +} // namespace ft0 +} // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx new file mode 100644 index 0000000000000..8bc57045e8822 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx @@ -0,0 +1,33 @@ +// 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 FT0Workflow.cxx + +#include "FT0Workflow/FT0Workflow.h" +#include "FT0Workflow/FT0DataReaderDPLSpec.h" +#include "FT0Workflow/FT0DataProcessDPLSpec.h" + +namespace o2 +{ +namespace fit +{ + +framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, bool dumpProcessor, bool dumpReader) +{ + LOG(INFO) << "framework::WorkflowSpec getFT0Workflow"; + framework::WorkflowSpec specs; + specs.emplace_back(o2::ft0::getFT0DataReaderDPLSpec(dumpReader, isExtendedMode)); + if (useProcess) + specs.emplace_back(o2::ft0::getFT0DataProcessDPLSpec(dumpProcessor)); + return specs; +} + +} // namespace fit +} // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/RecoWorkflow.cxx b/Detectors/FIT/FT0/workflow/src/RecoWorkflow.cxx index e3bddfefb69c9..af33a654e941e 100644 --- a/Detectors/FIT/FT0/workflow/src/RecoWorkflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/RecoWorkflow.cxx @@ -15,6 +15,7 @@ #include "FT0Workflow/DigitReaderSpec.h" #include "FT0Workflow/RecPointWriterSpec.h" #include "FT0Workflow/ReconstructionSpec.h" +#include "FT0Workflow/FT0DataReaderDPLSpec.h" namespace o2 { @@ -27,6 +28,7 @@ framework::WorkflowSpec getRecoWorkflow(bool useMC, bool disableRootInp, bool di if (!disableRootInp) { specs.emplace_back(o2::ft0::getDigitReaderSpec(useMC)); } + specs.emplace_back(o2::ft0::getReconstructionSpec(useMC)); if (!disableRootOut) { specs.emplace_back(o2::ft0::getRecPointWriterSpec(useMC)); diff --git a/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx b/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx new file mode 100644 index 0000000000000..4a4f1d73b333a --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx @@ -0,0 +1,47 @@ +// 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 "FT0Workflow/FT0Workflow.h" +#include "CommonUtils/ConfigurableParam.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + workflowOptions.push_back(ConfigParamSpec{ + "tcm-extended-mode", o2::framework::VariantType::Bool, false, {"in case of extended TCM mode (1 header + 1 TCMdata + 8 TCMdataExtended)"}}); + + workflowOptions.push_back(ConfigParamSpec{ + "use-process", o2::framework::VariantType::Bool, false, {"enable processor for data taking/dumping"}}); + workflowOptions.push_back(ConfigParamSpec{ + "dump-blocks-process", o2::framework::VariantType::Bool, false, {"enable dumping of event blocks at processor side"}}); + workflowOptions.push_back(ConfigParamSpec{ + "dump-blocks-reader", o2::framework::VariantType::Bool, false, {"enable dumping of event blocks at reader side"}}); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + LOG(INFO) << "WorkflowSpec defineDataProcessing"; + auto useProcessor = configcontext.options().get<bool>("use-process"); + auto dumpProcessor = configcontext.options().get<bool>("dump-blocks-process"); + auto dumpReader = configcontext.options().get<bool>("dump-blocks-reader"); + auto isExtendedMode = configcontext.options().get<bool>("tcm-extended-mode"); + + LOG(INFO) << "WorkflowSpec FLPWorkflow"; + return std::move(o2::fit::getFT0Workflow(isExtendedMode, useProcessor, dumpProcessor, dumpReader)); +} From 874096821b97fe94b0df6030691a710cabc157b4 Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Sat, 18 Jul 2020 14:29:58 +0300 Subject: [PATCH 0173/1751] remove default virtual destructor --- Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h | 1 - Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h | 1 - Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h | 1 - 3 files changed, 3 deletions(-) diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h index 5935e5e61785a..b84b965fae574 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h @@ -68,7 +68,6 @@ struct DataBlockWrapper { DataBlockWrapper() = default; DataBlockWrapper(const DataBlockWrapper& other) = default; DataBlockWrapper(DataBlockWrapper&& other) = default; - // virtual ~DataBlockWrapper() = default; std::vector<uint8_t> serialize(int nWords) { diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h index 5c5ca481f761f..6c9ddc283aaa5 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h @@ -44,7 +44,6 @@ class DataBlockReader { public: DataBlockReader() = default; - // ~DataBlockReader() = default; typedef DataBlockType DataBlock; size_t decodeBlocks(const gsl::span<const uint8_t> binaryPayload, std::vector<DataBlockType>& vecDataBlocks) { diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h index a109d46ab6c14..0250c2a10a303 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h @@ -47,7 +47,6 @@ class DigitBlockFT0 DigitBlockFT0(o2::InteractionRecord intRec) { mDigit.mIntRecord = intRec; } DigitBlockFT0() = default; DigitBlockFT0(const DigitBlockFT0& other) = default; - //~DigitBlockFT0() = default; Digit mDigit; std::vector<ChannelData> mVecChannelData; From 7c63d75ca74418a836cb9273ff87f4e1122aaf9f Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Thu, 23 Jul 2020 11:06:08 +0300 Subject: [PATCH 0174/1751] some fixes --- .../FT0/include/DataFormatsFT0/ChannelData.h | 21 ++++- .../FIT/FT0/include/DataFormatsFT0/Digit.h | 23 ++--- .../FT0/include/DataFormatsFT0/LookUpTable.h | 25 +++-- .../FT0/include/DataFormatsFT0/RawEventData.h | 88 ++++++++--------- .../Detectors/FIT/FT0/src/RawEventData.cxx | 94 +------------------ Detectors/FIT/FT0/raw/CMakeLists.txt | 4 - .../FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h | 48 ++++------ .../FT0/raw/include/FT0Raw/DataBlockReader.h | 10 +- .../FT0/raw/include/FT0Raw/DigitBlockFT0.h | 12 +-- Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx | 4 - Detectors/FIT/FT0/raw/src/DataBlockReader.cxx | 3 - Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx | 2 - .../FIT/FT0/simulation/src/Digitizer.cxx | 4 +- .../FIT/FT0/simulation/src/Digits2Raw.cxx | 30 ++---- .../FT0/workflow/src/FT0DataReaderDPLSpec.cxx | 5 +- 15 files changed, 125 insertions(+), 248 deletions(-) diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/ChannelData.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/ChannelData.h index 6c6422871febd..d42bad4cfef8e 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/ChannelData.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/ChannelData.h @@ -27,6 +27,15 @@ struct ChannelData { uint8_t ChainQTC = 0xff; //QTC chain int16_t CFDTime = -1000; //time in #CFD channels, 0 at the LHC clk center int16_t QTCAmpl = -1000; // Amplitude #channels + enum EEventDataBit { kNumberADC, + kIsDoubleEvent, + kIsTimeInfoNOTvalid, + kIsCFDinADCgate, + kIsTimeInfoLate, + kIsAmpHigh, + kIsEventInTVDC, + kIsTimeInfoLost + }; ChannelData() = default; ChannelData(uint8_t iPmt, int time, int charge, uint8_t chainQTC) @@ -36,10 +45,18 @@ struct ChannelData { QTCAmpl = charge; ChainQTC = chainQTC; } - + void setFlag(uint8_t flag) + { + ChainQTC = flag; + } + void setFlag(EEventDataBit bitFlag, bool value) + { + ChainQTC |= (value << bitFlag); + } + bool getFlag(EEventDataBit bitFlag) const { return bool(ChainQTC << bitFlag); } void print() const; - ClassDefNV(ChannelData, 1); + ClassDefNV(ChannelData, 2); }; } // namespace ft0 } // namespace o2 diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h index 74f5c6ed596bb..68bd05ffae8bc 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h @@ -85,8 +85,12 @@ struct Triggers { struct Digit { o2::dataformats::RangeReference<int, int> ref; Triggers mTriggers; // pattern of triggers in this BC + uint8_t mEventStatus; //Status of event from FT0, such as Pileup , etc o2::InteractionRecord mIntRecord; // Interaction record (orbit, bc) int mEventID; + enum EEventStatus { + kPileup + }; Digit() = default; Digit(int first, int ne, const o2::InteractionRecord& iRec, const Triggers& chTrig, int event) { @@ -102,24 +106,13 @@ struct Digit { int getEventID() const { return mEventID; } o2::InteractionRecord getIntRecord() { return mIntRecord; }; gsl::span<const ChannelData> getBunchChannelData(const gsl::span<const ChannelData> tfdata) const; - enum { bit1TimeLostEvent, - bit2TimeLostEvent, - bitADCinGate, - bitTimeInfoLate, - bitAmpHigh, - bitEventInTVDC, - bitTimeInfoLost }; - // T0 channel flags - uint8_t flags; - void setFlags(bool is1TimeLostEvent, bool is2TimeLostEvent, bool isADCinGate, bool isTimeInfoLate, bool isAmpHigh, bool isEventInTVDC, bool isTimeInfoLost) - { - flags = (is1TimeLostEvent << bit1TimeLostEvent) | (is2TimeLostEvent << bit2TimeLostEvent) | (isADCinGate << bitADCinGate) | (isTimeInfoLate << bitTimeInfoLate) | (isAmpHigh << bitAmpHigh) | (isEventInTVDC << bitEventInTVDC) | (isTimeInfoLost << bitTimeInfoLost); - }; void printStream(std::ostream& stream) const; void setTriggers(Triggers trig) { mTriggers = trig; }; - - ClassDefNV(Digit, 3); + void setEventStatus(uint8_t stat) { mEventStatus = stat; }; + void setStatusFlag(EEventStatus bit, bool value) { mEventStatus |= (value << bit); }; + bool getStatusFlag(EEventStatus bit) const { return bool(mEventStatus << bit); } + ClassDefNV(Digit, 4); }; } // namespace ft0 } // namespace o2 diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h index caa1e6cac5526..ae3a516a83c2a 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h @@ -8,10 +8,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -//file RawEventData.h class for RAW data format +// file RawEventData.h class for RAW data format // Alla.Maevskaya // simple look-up table just to feed digits 2 raw procedure. -//Will be really set after module/electronics connections +// Will be really set after module/electronics connections // #ifndef ALICEO2_FT0_LOOKUPTABLE_H_ #define ALICEO2_FT0_LOOKUPTABLE_H_ @@ -48,22 +48,25 @@ class LookUpTable /// Default constructor. /// It must be kept public for root persistency purposes, /// but should never be called by the outside world - //LookUpTable() = default; + // LookUpTable() = default; explicit LookUpTable(std::vector<Topo> const& topoVector) : mTopoVector(topoVector), mInvTopo(topoVector.size()) { for (size_t channel = 0; channel < mTopoVector.size(); ++channel) - mInvTopo.at(getIdx(mTopoVector[channel].mPM, mTopoVector[channel].mMCP)) = channel; + mInvTopo.at(getIdx(mTopoVector[channel].mPM, mTopoVector[channel].mMCP)) = + channel; } ~LookUpTable() = default; void printFullMap() const { for (size_t channel = 0; channel < mTopoVector.size(); ++channel) - std::cout << channel << "\t : PM \t" << mTopoVector[channel].mPM << " MCP \t" << mTopoVector[channel].mMCP << std::endl; + std::cout << channel << "\t : PM \t" << mTopoVector[channel].mPM + << " MCP \t" << mTopoVector[channel].mMCP << std::endl; for (size_t idx = 0; idx < mInvTopo.size(); ++idx) - std::cout << "PM \t" << getLinkFromIdx(mInvTopo[idx]) << " MCP \t" << getMCPFromIdx(mInvTopo[idx]) << std::endl; + std::cout << "PM \t" << getLinkFromIdx(mInvTopo[idx]) << " MCP \t" + << getMCPFromIdx(mInvTopo[idx]) << std::endl; } int getChannel(int link, int mcp) const @@ -94,14 +97,8 @@ class LookUpTable assert(mcp < NUMBER_OF_MCPs); return link * NUMBER_OF_MCPs + mcp; } - static int getLinkFromIdx(int idx) - { - return idx / NUMBER_OF_MCPs; - } - static int getMCPFromIdx(int idx) - { - return idx % NUMBER_OF_MCPs; - } + static int getLinkFromIdx(int idx) { return idx / NUMBER_OF_MCPs; } + static int getMCPFromIdx(int idx) { return idx % NUMBER_OF_MCPs; } ClassDefNV(LookUpTable, 1); }; diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h index 32216663c537f..cdf49bad76003 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h @@ -16,6 +16,8 @@ #define ALICEO2_FIT_RAWEVENTDATA_H_ #include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" + #include "Headers/RAWDataHeader.h" #include "DataFormatsFT0/LookUpTable.h" #include <CommonDataFormat/InteractionRecord.h> @@ -52,11 +54,10 @@ struct EventHeader { uint64_t reservedField3 : 48; }; }; - InteractionRecord getIntRec() { return InteractionRecord{(uint16_t)bc, (uint32_t)orbit}; } + InteractionRecord getIntRec() const { return InteractionRecord{(uint16_t)bc, (uint32_t)orbit}; } - void print() + void print() const { - std::cout << std::hex; std::cout << "################EventHeader###############" << std::endl; std::cout << "startDescriptor: " << startDescriptor << std::endl; @@ -64,55 +65,74 @@ struct EventHeader { std::cout << "BC: " << bc << std::endl; std::cout << "Orbit: " << orbit << std::endl; std::cout << "##########################################" << std::endl; - std::cout << std::dec; } }; struct EventData { static constexpr size_t PayloadSize = 5; static constexpr size_t PayloadPerGBTword = 10; - static constexpr int MinNelements = 1; + static constexpr int MinNelements = 1; //additional static field static constexpr int MaxNelements = 12; + // + static constexpr int BitFlagPos = 25; // position of first bit flag(numberADC) union { - uint64_t word = {0}; //should be + uint64_t word = {0}; struct { int64_t time : 12; int64_t charge : 13; - uint64_t numberADC : 1, + uint64_t numberADC : 1, //25 bit isDoubleEvent : 1, - is1TimeLostEvent : 1, - is2TimeLostEvent : 1, - isADCinGate : 1, + isTimeInfoNOTvalid : 1, + isCFDinADCgate : 1, isTimeInfoLate : 1, isAmpHigh : 1, isEventInTVDC : 1, isTimeInfoLost : 1, - reservedField : 2, + reservedField : 3, channelID : 4; }; }; - void print() + void generateFlags() + { + numberADC = std::rand() % 2; + isDoubleEvent = 0; + isTimeInfoNOTvalid = 0; + isCFDinADCgate = 1; + isTimeInfoLate = 0; + isAmpHigh = 0; + isEventInTVDC = 1; + isTimeInfoLost = 0; + } + uint8_t getFlagWord() const + { + return uint8_t(word >> BitFlagPos); + } + void print() const { - std::cout << std::hex; std::cout << "###############EventData(PM)##############" << std::endl; std::cout << "------------Channel " << channelID << "------------" << std::endl; std::cout << "Charge: " << charge << std::endl; std::cout << "Time: " << time << std::endl; - std::cout << "1TimeLostEvent: " << is1TimeLostEvent << std::endl; - std::cout << "2TimeLostEvent: " << is2TimeLostEvent << std::endl; - std::cout << "ADCinGate: " << isADCinGate << std::endl; - std::cout << "AmpHigh: " << isAmpHigh << std::endl; - std::cout << "DoubleEvent: " << isDoubleEvent << std::endl; - std::cout << "EventInTVDC: " << isEventInTVDC << std::endl; - std::cout << "TimeInfoLate: " << isTimeInfoLate << std::endl; - std::cout << "TimeInfoLost: " << isTimeInfoLost << std::endl; std::cout << "numberADC: " << numberADC << std::endl; + std::cout << "isDoubleEvent: " << isDoubleEvent << std::endl; + std::cout << "isTimeInfoNOTvalid: " << isTimeInfoNOTvalid << std::endl; + std::cout << "isCFDinADCgate: " << isCFDinADCgate << std::endl; + std::cout << "isTimeInfoLate: " << isTimeInfoLate << std::endl; + std::cout << "isAmpHigh: " << isAmpHigh << std::endl; + std::cout << "isEventInTVDC: " << isEventInTVDC << std::endl; + std::cout << "isTimeInfoLost: " << isTimeInfoLost << std::endl; std::cout << "##########################################" << std::endl; - std::cout << std::dec; } + + //temporary, this method should be in ChannelData struct, TODO + void fillChannelData(ChannelData& channelData) const + { + channelData.ChainQTC = getFlagWord(); + } + uint64_t word_zeros = 0x0; //to remove static const size_t PayloadSizeSecondWord = 11; //to remove static const size_t PayloadSizeFirstWord = 5; //to remove @@ -145,7 +165,7 @@ struct TCMdata { reservedField7 : 1, //79 bit reservedField8 : 48; //80 bit - void print() + void print() const { std::cout << std::hex; std::cout << "################TCMdata###################" << std::endl; @@ -165,8 +185,8 @@ struct TCMdata { std::cout << std::dec; } - //temporary, this method should be in Triggers struct - void pushTrgData(Triggers& trg) + //temporary, this method should be in Triggers struct, TODO + void fillTrigger(Triggers& trg) { trg.triggersignals = ((bool)orA << Triggers::bitA) | ((bool)orC << Triggers::bitC) | @@ -208,23 +228,7 @@ class RawEventData { public: RawEventData() = default; - void generateHeader(int nChannels); - void generateData(); - void generateRandomHeader(int nChannels); - void generateRandomData(); - void generateRandomEvent(int nChannels); - EventHeader* getEventHeaderPtr() { return &mEventHeader; } - EventData* getEventDataPtr() { return mEventData; } void print(); - enum EEventDataBit { kNumberADC, - kIsDoubleEvent, - kIs1TimeLostEvent, - kIs2TimeLostEvent, - kIsADCinGate, - kIsTimeInfoLate, - kIsAmpHigh, - kIsEventInTVDC, - kIsTimeInfoLost }; const static int gStartDescriptor = 0x0000000f; int size() const @@ -281,7 +285,7 @@ class RawEventData TCMdata mTCMdata; bool mIsPadded = true; ///////////////////////////////////////////////// - ClassDefNV(RawEventData, 1); + ClassDefNV(RawEventData, 2); }; std::ostream& operator<<(std::ostream& stream, const RawEventData& data); diff --git a/DataFormats/Detectors/FIT/FT0/src/RawEventData.cxx b/DataFormats/Detectors/FIT/FT0/src/RawEventData.cxx index 835a51e3993cc..1ee3d9f348a03 100644 --- a/DataFormats/Detectors/FIT/FT0/src/RawEventData.cxx +++ b/DataFormats/Detectors/FIT/FT0/src/RawEventData.cxx @@ -15,96 +15,4 @@ using namespace o2::ft0; -using namespace std; - -ClassImp(RawEventData); - -void RawEventData::generateData() -{ - for (int iCh = 0; iCh < mEventHeader.nGBTWords * 2; iCh++) { - mEventData[iCh].channelID = iCh; - mEventData[iCh].charge = 1000; - mEventData[iCh].time = 500; - mEventData[iCh].is1TimeLostEvent = 1; - mEventData[iCh].is2TimeLostEvent = 1; - mEventData[iCh].isADCinGate = 1; - mEventData[iCh].isAmpHigh = 1; - mEventData[iCh].isDoubleEvent = 1; - mEventData[iCh].isEventInTVDC = 1; - mEventData[iCh].isTimeInfoLate = 1; - mEventData[iCh].isTimeInfoLost = 1; - mEventData[iCh].numberADC = 1; - } -} - -void RawEventData::generateHeader(int nChannels) -{ - mEventHeader.startDescriptor = 15; - mEventHeader.nGBTWords = (nChannels + 1) / 2; - mEventHeader.reservedField1 = 0; - mEventHeader.reservedField2 = 0; - mEventHeader.bc = 200; - mEventHeader.orbit = 100; -} - -void RawEventData::generateRandomHeader(int nChannels) -{ - mEventHeader.startDescriptor = 0x0000000f; - if (nChannels > 0 && nChannels < 13) - mEventHeader.nGBTWords = (nChannels + 1) / 2; - else - mEventHeader.nGBTWords = 1; - mEventHeader.bc = std::rand() % 2000; // 1999-max bc - mEventHeader.orbit = std::rand() % 100; -} - -void RawEventData::generateRandomData() -{ - for (int iCh = 0; iCh < mEventHeader.nGBTWords * 2; iCh++) { - mEventData[iCh].channelID = std::rand() % 208 + 1; - mEventData[iCh].charge = std::rand() % 1000; - mEventData[iCh].time = std::rand() % 500; - mEventData[iCh].is1TimeLostEvent = std::rand() % 2; - mEventData[iCh].is2TimeLostEvent = std::rand() % 2; - mEventData[iCh].isADCinGate = std::rand() % 2; - mEventData[iCh].isAmpHigh = std::rand() % 2; - mEventData[iCh].isDoubleEvent = std::rand() % 2; - mEventData[iCh].isEventInTVDC = std::rand() % 2; - mEventData[iCh].isTimeInfoLate = std::rand() % 2; - mEventData[iCh].isTimeInfoLost = std::rand() % 2; - mEventData[iCh].numberADC = std::rand() % 2; - } -} - -void RawEventData::generateRandomEvent(int nChannels) -{ - generateRandomHeader(nChannels); - generateRandomData(); -} - -void RawEventData::print() -{ - std::cout << "==================Raw event data==================" << endl; - std::cout << "##################Header##################" << endl; - std::cout << "startDescriptor: " << mEventHeader.startDescriptor << endl; - std::cout << "Nchannels: " << mEventHeader.nGBTWords * 2 << endl; - std::cout << "BC: " << mEventHeader.bc << endl; - std::cout << "Orbit: " << mEventHeader.orbit << endl; - std::cout << "##########################################" << endl; - std::cout << "###################DATA###################" << endl; - for (int iCh = 0; iCh < mEventHeader.nGBTWords * 2; iCh++) { - std::cout << "------------Channel " << mEventData[iCh].channelID << "------------" << endl; - std::cout << "Charge: " << mEventData[iCh].charge << endl; - std::cout << "Time: " << mEventData[iCh].time << endl; - std::cout << "1TimeLostEvent: " << mEventData[iCh].is1TimeLostEvent << endl; - std::cout << "2TimeLostEvent: " << mEventData[iCh].is2TimeLostEvent << endl; - std::cout << "ADCinGate: " << mEventData[iCh].isADCinGate << endl; - std::cout << "AmpHigh: " << mEventData[iCh].isAmpHigh << endl; - std::cout << "DoubleEvent: " << mEventData[iCh].isDoubleEvent << endl; - std::cout << "EventInTVDC: " << mEventData[iCh].isEventInTVDC << endl; - std::cout << "TimeInfoLate: " << mEventData[iCh].isTimeInfoLate << endl; - std::cout << "TimeInfoLost: " << mEventData[iCh].isTimeInfoLost << endl; - std::cout << "numberADC: " << mEventData[iCh].numberADC << endl; - } - std::cout << "##########################################" << endl; -} +ClassImp(RawEventData); \ No newline at end of file diff --git a/Detectors/FIT/FT0/raw/CMakeLists.txt b/Detectors/FIT/FT0/raw/CMakeLists.txt index 8c0f3cbdf0767..80a09489805ee 100644 --- a/Detectors/FIT/FT0/raw/CMakeLists.txt +++ b/Detectors/FIT/FT0/raw/CMakeLists.txt @@ -11,7 +11,3 @@ o2_add_library(FT0Raw SOURCES src/DataBlockRaw.cxx src/DigitBlockFT0.cxx src/DataBlockReader.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::DataFormatsFT0) - -o2_target_root_dictionary(FT0Raw - HEADERS include/FT0Raw/DataBlockRaw.h include/FT0Raw/DigitBlockFT0.h include/FT0Raw/DataBlockReader.h - LINKDEF src/FT0RawLinkDef.h) diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h index b84b965fae574..bfbac3c37520b 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h @@ -66,14 +66,13 @@ using namespace std; template <typename T> struct DataBlockWrapper { DataBlockWrapper() = default; - DataBlockWrapper(const DataBlockWrapper& other) = default; - DataBlockWrapper(DataBlockWrapper&& other) = default; + DataBlockWrapper(const DataBlockWrapper&) = default; std::vector<uint8_t> serialize(int nWords) { std::vector<uint8_t> vecBytes(sizeWord * nWords); uint8_t* srcAddress = (uint8_t*)mData; - if (nWords == 0) + if (nWords == 0 || nWords > MaxNwords) return std::move(vecBytes); gsl::span<uint8_t> serializedBytes(vecBytes); size_t countBytes = 0; @@ -277,7 +276,7 @@ struct DataBlockWrapper { << std::get<kDESTBYTEPOS>(sByteLookupTable[i]) << endl; } } - void print() + void print() const { assert(mNelements <= T::MaxNelements); for (int i = 0; i < mNelements; i++) { @@ -287,7 +286,7 @@ struct DataBlockWrapper { } T mData[T::MaxNelements]; unsigned int mNelements; //number of deserialized elements; - unsigned int mNwords; //number of deserialized GBT words; + unsigned int mNwords; //number of deserialized GBT words; //can be excluded }; //CRTP(static polymorphism) + Composition over multiple inheritance(Header + multiple data structures) @@ -300,9 +299,7 @@ class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataB public: DataBlockBase() = default; - DataBlockBase(const DataBlockBase& other) = default; - - virtual ~DataBlockBase() = default; + DataBlockBase(const DataBlockBase&) = default; static void printLUT() { @@ -310,7 +307,7 @@ class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataB (static_cast<void>(DataBlockWrapper<DataStructures>::printLUT()), ...); } - void print() + void print() const { LOG(INFO) << "HEADER"; DataBlockWrapper<Header>::print(); @@ -318,7 +315,7 @@ class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataB (static_cast<void>(DataBlockWrapper<DataStructures>::print()), ...); } - InteractionRecord getInteractionRecord() + InteractionRecord getInteractionRecord() const { return DataBlockWrapper<Header>::mData[0].getIntRec(); } @@ -334,7 +331,7 @@ class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataB update(); } - bool isCorrect() { return mIsCorrect; } + bool isCorrect() const { return mIsCorrect; } void update() { @@ -360,8 +357,7 @@ class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> { public: DataBlockPM() = default; - DataBlockPM(const DataBlockPM& other) = default; - virtual ~DataBlockPM() = default; + DataBlockPM(const DataBlockPM&) = default; void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) { DataBlockWrapper<RawHeaderPM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderPM>::MaxNwords, srcByteShift); @@ -373,18 +369,16 @@ class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> { if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling - //TODO + //TODO, Descriptor checking, Channel range } - // - ClassDefNV(DataBlockPM, 1); }; + //standard data block from TCM class DataBlockTCM : public DataBlockBase<DataBlockTCM, RawHeaderTCM, RawDataTCM> { public: DataBlockTCM() = default; - DataBlockTCM(const DataBlockTCM& other) = default; - virtual ~DataBlockTCM() = default; + DataBlockTCM(const DataBlockTCM&) = default; void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) { DataBlockWrapper<RawHeaderTCM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCM>::MaxNwords, srcByteShift); @@ -394,10 +388,8 @@ class DataBlockTCM : public DataBlockBase<DataBlockTCM, RawHeaderTCM, RawDataTCM // put here code for raw data checking void sanityCheck(bool& flag) { - - } //TODO - // - ClassDefNV(DataBlockTCM, 1); + //TODO, Descriptor checking, Channel range + } }; //extended TCM mode, 1 TCMdata + 8 TCMdataExtendedstructs @@ -405,8 +397,8 @@ class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, R { public: DataBlockTCMext() = default; - DataBlockTCMext(const DataBlockTCMext& other) = default; - virtual ~DataBlockTCMext() = default; + DataBlockTCMext(const DataBlockTCMext&) = default; + //virtual ~DataBlockTCMext() = default; void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) { DataBlockWrapper<RawHeaderTCMext>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCMext>::MaxNwords, srcByteShift); @@ -418,12 +410,10 @@ class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, R // put here code for raw data checking void sanityCheck(bool& flag) { - - } //TODO - // - ClassDefNV(DataBlockTCMext, 1); + //TODO, Descriptor checking, Channel range + } }; } // namespace ft0 } // namespace o2 -#endif +#endif \ No newline at end of file diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h index 6c9ddc283aaa5..80527589b9e0b 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h @@ -44,6 +44,7 @@ class DataBlockReader { public: DataBlockReader() = default; + ~DataBlockReader() = default; typedef DataBlockType DataBlock; size_t decodeBlocks(const gsl::span<const uint8_t> binaryPayload, std::vector<DataBlockType>& vecDataBlocks) { @@ -53,7 +54,7 @@ class DataBlockReader dataBlock.decodeBlock(binaryPayload, srcPos); srcPos += dataBlock.mSize; if (dataBlock.isCorrect()) - vecDataBlocks.push_back(dataBlock); + vecDataBlocks.push_back(dataBlock); //change to in-place construction? TODO } return srcPos; } @@ -91,7 +92,7 @@ class RawReaderFT0 : public RawReaderBase<DigitBlockFT0, DataBlockPM, typename s typedef typename std::conditional<IsExtendedMode, DataBlockTCMext, DataBlockTCM>::type DataBlockTCMtype; typedef RawReaderBase<DigitBlockFT0, DataBlockPM, DataBlockTCMtype> RawReaderBaseType; - RawReaderFT0() {} + RawReaderFT0() = default; ~RawReaderFT0() = default; //deserialize payload to raw data blocks and proccesss them to digits void proccess(int linkID, gsl::span<const uint8_t> payload) @@ -116,16 +117,13 @@ class RawReaderFT0 : public RawReaderBase<DigitBlockFT0, DataBlockPM, typename s int digitCounter = RawReaderBaseType::mMapDigits.size(); for (auto& digit : (RawReaderBaseType::mMapDigits)) { digit.second.popData(vecDigit, vecChannelData); - //digitCounter++; } (RawReaderBaseType::mMapDigits).clear(); return digitCounter; } - - ClassDefNV(RawReaderFT0, 1); }; } // namespace ft0 } // namespace o2 -#endif +#endif \ No newline at end of file diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h index 0250c2a10a303..6913499d0014d 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h @@ -47,6 +47,7 @@ class DigitBlockFT0 DigitBlockFT0(o2::InteractionRecord intRec) { mDigit.mIntRecord = intRec; } DigitBlockFT0() = default; DigitBlockFT0(const DigitBlockFT0& other) = default; + ~DigitBlockFT0() = default; Digit mDigit; std::vector<ChannelData> mVecChannelData; @@ -58,17 +59,17 @@ class DigitBlockFT0 { if constexpr (std::is_same<DataBlockType, DataBlockPM>::value) { //Filling data from PM for (int iEventData = 0; iEventData < dataBlock.DataBlockWrapper<RawDataPM>::mNelements; iEventData++) { - mVecChannelData.emplace_back(int(sLookupTable.getChannel(linkID, dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].channelID)), + mVecChannelData.emplace_back(uint8_t(sLookupTable.getChannel(linkID, dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].channelID)), int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].time), int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].charge), - int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].numberADC)); + dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].getFlagWord()); } } else if constexpr (std::is_same<DataBlockType, DataBlockTCM>::value) { //Filling data from TCM (normal/extended mode) - dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].pushTrgData(mDigit.mTriggers); + dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].fillTrigger(mDigit.mTriggers); } else if constexpr (std::is_same<DataBlockType, DataBlockTCMext>::value) { //Filling data from TCM, extended mode. Same proccess as for normal mode, for now. - dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].pushTrgData(mDigit.mTriggers); + dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].fillTrigger(mDigit.mTriggers); } } void popData(std::vector<Digit>& vecDigits, std::vector<ChannelData>& vecChannelData) @@ -83,7 +84,7 @@ class DigitBlockFT0 sEventID++; //Increasing static eventID. After each poping of the data, it will increase } - void print() + void print() const { std::cout << "\n______________DIGIT DATA____________"; std::cout << std::hex; @@ -126,7 +127,6 @@ class DigitBlockFT0 std::cout << "\n______________________________________\n"; } } - ClassDefNV(DigitBlockFT0, 1); }; } // namespace ft0 diff --git a/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx b/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx index eb4bc06850245..7eec38be58b3e 100644 --- a/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx +++ b/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx @@ -10,7 +10,3 @@ #include "FT0Raw/DataBlockRaw.h" using namespace o2::ft0; - -ClassImp(DataBlockPM); -ClassImp(DataBlockTCM); -ClassImp(DataBlockTCMext); diff --git a/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx b/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx index 6a869f7f3ec6b..15b2c9a0beef3 100644 --- a/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx +++ b/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx @@ -10,6 +10,3 @@ #include "FT0Raw/DataBlockReader.h" using namespace o2::ft0; - -ClassImp(RawReaderFT0<true>); -ClassImp(RawReaderFT0<false>); diff --git a/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx index ab36f0a1a613e..b232b80e84de7 100644 --- a/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx +++ b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx @@ -11,7 +11,5 @@ #include "FT0Raw/DigitBlockFT0.h" using namespace o2::ft0; -ClassImp(DigitBlockFT0); - int DigitBlockFT0::sEventID = 0; o2::ft0::LookUpTable DigitBlockFT0::sLookupTable = o2::ft0::LookUpTable::linear(); diff --git a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx index 164367179c3b7..56ac6da062909 100644 --- a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx @@ -252,8 +252,8 @@ void Digitizer::storeBC(BCCache& bc, is_SemiCentral = summ_ampl_A + summ_ampl_C >= mParameters.mtrg_semicentral_trh; vertex_time = (mean_time_A - mean_time_C) * 0.5; isVertex = is_A && is_C && (vertex_time > -mParameters.mTime_trg_gate && vertex_time < mParameters.mTime_trg_gate); - uint32_t amplA = is_A ? summ_ampl_A : 0; // sum amplitude A side - uint32_t amplC = is_C ? summ_ampl_C : 0; // sum amplitude C side + uint32_t amplA = is_A ? summ_ampl_A * 0.125 : 0; // sum amplitude A side / 8 (hardware) + uint32_t amplC = is_C ? summ_ampl_C * 0.125 : 0; // sum amplitude C side / 8 (hardware) uint16_t timeA = is_A ? mean_time_A / n_hit_A : 0; // average time A side uint16_t timeC = is_C ? mean_time_C / n_hit_C : 0; // average time C side diff --git a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx index a14caf506b2ab..57be45a072939 100644 --- a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx @@ -113,7 +113,6 @@ void Digits2Raw::readDigits(const std::string& outDir, const std::string& fileDi for (int ibc = 0; ibc < nbc; ibc++) { auto& bcd = digitsBC[ibc]; intRecord = bcd.getIntRecord(); - bcd.printStream(std::cout); auto channels = bcd.getBunchChannelData(digitsCh); if (!channels.empty()) convertDigits(bcd, channels, lut, intRecord); @@ -136,9 +135,9 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, if (nlink != oldlink) { if (oldlink >= 0) { uint nGBTWords = uint((nchannels + 1) / 2); - if ((nchannels % 2) == 1) { + LOG(DEBUG) << " oldlink " << oldlink << " nGBTWords " << nGBTWords; + if ((nchannels % 2) == 1) mRawEventData.mEventData[nchannels] = {}; - } mRawEventData.mEventHeader.nGBTWords = nGBTWords; auto data = mRawEventData.to_vector(false); mLinkID = uint32_t(oldlink); @@ -148,24 +147,15 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, oldlink = nlink; mRawEventData.mEventHeader = makeGBTHeader(nlink, intRecord); nchannels = 0; + // LOG(INFO) << " switch to new link " << nlink; } auto& newData = mRawEventData.mEventData[nchannels]; bool isAside = (pmchannels[ich].ChId < 96); newData.charge = pmchannels[ich].QTCAmpl; - newData.time = pmchannels[ich].CFDTime; - newData.is1TimeLostEvent = 0; - newData.is2TimeLostEvent = 0; - newData.isADCinGate = 1; - newData.isAmpHigh = 0; - newData.isDoubleEvent = 0; - newData.isEventInTVDC = 1; - newData.isTimeInfoLate = 0; - newData.isTimeInfoLost = 0; - int chain = std::rand() % 2; - newData.numberADC = chain ? 1 : 0; + newData.generateFlags(); newData.channelID = lut.getMCP(pmchannels[ich].ChId); - LOG(DEBUG) << "packed GBT " << nlink << " channelID " << (int)newData.channelID << " charge " << newData.charge << " time " << newData.time << " chain " << int(newData.numberADC) << " channel dig " << (int)pmchannels[ich].ChId; + // LOG(INFO) << "packed GBT " << nlink << " channelID " << (int)newData.channelID << " charge " << newData.charge << " time " << newData.time << " chain " << int(newData.numberADC) << " size " << sizeof(newData); nchannels++; } // fill mEventData[nchannels] with 0s to flag that this is a dummy data @@ -173,11 +163,7 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, if ((nchannels % 2) == 1) mRawEventData.mEventData[nchannels] = {}; mRawEventData.mEventHeader.nGBTWords = nGBTWords; - auto data = mRawEventData.to_vector(false); - mLinkID = uint32_t(oldlink); - mFeeID = uint64_t(oldlink); - mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, intRecord, data); - + LOG(DEBUG) << " last " << oldlink; //TCM mRawEventData.mEventHeader = makeGBTHeader(LinkTCM, intRecord); //TCM mRawEventData.mEventHeader.nGBTWords = 1; @@ -217,10 +203,10 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, << " ver " << tcmdata.vertex << " A " << tcmdata.orA << " C " << tcmdata.orC << " size " << sizeof(tcmdata); } - auto datatcm = mRawEventData.to_vector(1); + auto data = mRawEventData.to_vector(1); mLinkID = uint32_t(LinkTCM); mFeeID = uint64_t(LinkTCM); - mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, intRecord, datatcm); + mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, intRecord, data); } //_____________________________________________________________________________________ diff --git a/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx index 13d75de77dbb6..2e338ce41b20e 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx @@ -36,10 +36,7 @@ void FT0DataReaderDPLSpec<IsExtendedMode>::run(ProcessingContext& pc) for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { //Proccessing each page count++; - //auto rdhPtr = it.get_if<o2::header::RAWDataHeader>(); //PROBLEM! - //auto rdhPtr = it.get_if<o2::header::RAWDataHeaderV4>(); - auto rdhPtr = it.get_if<o2::header::RAWDataHeaderV6>(); - + auto rdhPtr = it.get_if<o2::header::RAWDataHeader>(); gsl::span<const uint8_t> payload(it.data(), it.size()); mRawReaderFT0.proccess(rdhPtr->linkID, payload); } From f806423237efe2dcb6f82034c4fec1963b58c2cf Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 24 Jul 2020 15:39:18 +0200 Subject: [PATCH 0175/1751] DPL: improve logic for default shm-segment-size Use 90% of the soft limit for VSIZE, unless otherwise specified or unless unlimited. --- Framework/Core/src/DeviceSpecHelpers.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index a2f586a2a6c5d..9924241e7c563 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -36,6 +36,9 @@ #include <uv.h> #include <iostream> +#include <sys/time.h> +#include <sys/resource.h> + namespace bpo = boost::program_options; using namespace o2::framework; @@ -791,6 +794,14 @@ void DeviceSpecHelpers::reworkShmSegmentSize(std::vector<DataProcessorInfo>& inf } info.cmdLineArgs.erase(it, it + 2); } + /// If no segment size is set, make it 90% of the VSIZE. + if (segmentSize == 0) { + struct rlimit limits; + getrlimit(RLIMIT_AS, &limits); + if (limits.rlim_cur != RLIM_INFINITY) { + segmentSize = (limits.rlim_cur / 100) * 90; + } + } if (segmentSize == 0) { segmentSize = 2000000000LL; } From 6bbc694c00a7c661b9f46a46dd00c3f83c7b9247 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Fri, 24 Jul 2020 19:22:39 +0200 Subject: [PATCH 0176/1751] Several changes in the DQ skimming and analysis tools (#4028) * Initial commit for test base classes for Event, Track and Analysis objects * Added a task which produces trees of ReducedEvent objects * Added histogram and variable manager classes * Tables in ReducedInfoTables redefined using the existing columns in the central data model. Removed dependency on the VarManager for the HistogramManager * VarManager and HistogramManager classes updated. * Small changes to the Histogram and Variable managers. First commit of the analysis cut classes * AnalysisCut and AnalysisCompositeCut classes added; other small improvements * Update in the DQ skimmed data model (muon tables); added templated Fill() functions in the VarManager; trigger aliases included in the event table; --- Analysis/Core/include/Analysis/VarManager.h | 209 ++++++++++++++++-- Analysis/Core/src/VarManager.cxx | 112 +++------- .../include/Analysis/ReducedInfoTables.h | 52 +++-- Analysis/Tasks/tableMaker.cxx | 98 ++++++-- Analysis/Tasks/tableReader.cxx | 131 +++++++++-- 5 files changed, 458 insertions(+), 144 deletions(-) diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 68d9994c71b22..0f5a0a81b805f 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -16,19 +16,34 @@ #ifndef VarManager_H #define VarManager_H -//#include "Analysis/ReducedInfoTables.h" #include <TObject.h> #include <TString.h> #include <vector> #include <map> +#include <cmath> -//using namespace o2::aod; -//using std::vector; +// TODO: create an array holding these constants for all needed particles or check for a place where these are already defined +static const float fgkElectronMass = 0.000511; // GeV //_________________________________________________________________________ class VarManager : public TObject { + public: + enum ObjTypes { + BC = BIT(0), + Collision = BIT(1), + ReducedEvent = BIT(2), + ReducedEventExtended = BIT(3), + ReducedEventVtxCov = BIT(4), + Track = BIT(0), + TrackCov = BIT(1), + TrackExtra = BIT(2), + ReducedTrack = BIT(3), + ReducedTrackBarrel = BIT(4), + ReducedTrackBarrelCov = BIT(5), + ReducedTrackMuon = BIT(6) + }; public: enum Variables { @@ -36,18 +51,11 @@ class VarManager : public TObject // Run wise variables kRunNo = 0, kRunId, - kRunTimeStart, - kRunTimeStop, - kLHCFillNumber, - kDipolePolarity, - kL3Polarity, kNRunWiseVariables, // Event wise variables // Daria: imedjat ai ziua mja - kTimeStamp, + kCollisionTime, kBC, - kInstLumi, - kEventType, kIsPhysicsSelection, kVtxX, kVtxY, @@ -68,6 +76,9 @@ class VarManager : public TObject kEta, kPhi, kP, + kPx, + kPy, + kPz, kRap, kMass, kCharge, @@ -84,9 +95,22 @@ class VarManager : public TObject kTRDsignal, kTOFsignal, kTrackLength, + kTrackCYY, + kTrackCZZ, + kTrackCSnpSnp, + kTrackCTglTgl, + kTrackC1Pt21Pt2, kNBarrelTrackVariables, // Muon track variables + kMuonInvBendingMomentum, + kMuonThetaX, + kMuonThetaY, + kMuonZMu, + kMuonBendingCoor, + kMuonNonBendingCoor, + kMuonChi2, + kMuonChi2MatchTrigger, kNMuonTrackVariables, // Pair variables @@ -135,9 +159,12 @@ class VarManager : public TObject static void SetRunNumbers(int n, int* runs); - static void FillEvent(std::vector<float> event, float* values = nullptr); - static void FillTrack(std::vector<float> track, float* values = nullptr); - //static void FillTrack(ReducedTrack track, float* values = nullptr); + template <uint32_t fillMap, typename T> + static void FillEvent(T const& event, float* values = nullptr); + template <uint32_t fillMap, typename T> + static void FillTrack(T const& track, float* values = nullptr); + template <typename T> + static void FillPair(T const& t1, T const& t2, float* values = nullptr); public: VarManager(); @@ -152,10 +179,164 @@ class VarManager : public TObject static std::map<int, int> fgRunMap; // map of runs to be used in histogram axes + static void FillEventDerived(float* values = nullptr); + static void FillTrackDerived(float* values = nullptr); + VarManager& operator=(const VarManager& c); VarManager(const VarManager& c); ClassDef(VarManager, 1) }; +template <uint32_t fillMap, typename T> +void VarManager::FillEvent(T const& event, float* values) +{ + if (!values) + values = fgValues; + + if constexpr ((fillMap & BC) > 0) { + values[kRunNo] = event.bc().runNumber(); // accessed via Collisions table + values[kBC] = event.bc().globalBC(); + } + + if constexpr ((fillMap & Collision) > 0) { + values[kVtxX] = event.posX(); + values[kVtxY] = event.posY(); + values[kVtxZ] = event.posZ(); + values[kVtxNcontrib] = event.numContrib(); + values[kCollisionTime] = event.collisionTime(); + values[kVtxCovXX] = event.covXX(); + values[kVtxCovXY] = event.covXY(); + values[kVtxCovXZ] = event.covXZ(); + values[kVtxCovYY] = event.covYY(); + values[kVtxCovYZ] = event.covYZ(); + values[kVtxCovZZ] = event.covZZ(); + values[kVtxChi2] = event.chi2(); + } + + // TODO: need to add EvSels and Cents tables, etc. in case of the central data model + + if constexpr ((fillMap & ReducedEvent) > 0) { + values[kRunNo] = event.runNumber(); + values[kVtxX] = event.posX(); + values[kVtxY] = event.posY(); + values[kVtxZ] = event.posZ(); + values[kVtxNcontrib] = event.numContrib(); + } + + if constexpr ((fillMap & ReducedEventExtended) > 0) { + values[kBC] = event.globalBC(); + values[kCentVZERO] = event.centV0M(); + } + + if constexpr ((fillMap & ReducedEventVtxCov) > 0) { + values[kVtxCovXX] = event.covXX(); + values[kVtxCovXY] = event.covXY(); + values[kVtxCovXZ] = event.covXZ(); + values[kVtxCovYY] = event.covYY(); + values[kVtxCovYZ] = event.covYZ(); + values[kVtxCovZZ] = event.covZZ(); + values[kVtxChi2] = event.chi2(); + } + + FillEventDerived(values); +} + +template <uint32_t fillMap, typename T> +void VarManager::FillTrack(T const& track, float* values) +{ + if (!values) + values = fgValues; + + if constexpr ((fillMap & Track) > 0) { + values[kPt] = track.pt(); + values[kEta] = track.eta(); + values[kPhi] = track.phi(); + values[kCharge] = track.charge(); + } + + if constexpr ((fillMap & TrackExtra) > 0) { + values[kPin] = track.tpcInnerParam(); + if (fgUsedVars[kITSncls]) + values[kITSncls] = track.itsNCls(); // dynamic column + values[kITSchi2] = track.itsChi2NCl(); + values[kTPCncls] = track.tpcNClsFound(); + values[kTPCchi2] = track.tpcChi2NCl(); + values[kTPCsignal] = track.tpcSignal(); + values[kTRDsignal] = track.trdSignal(); + values[kTOFsignal] = track.tofSignal(); + values[kTrackLength] = track.length(); + } + + if constexpr ((fillMap & TrackCov) > 0) { + values[kTrackCYY] = track.cYY(); + values[kTrackCZZ] = track.cZZ(); + values[kTrackCSnpSnp] = track.cSnpSnp(); + values[kTrackCTglTgl] = track.cTglTgl(); + values[kTrackC1Pt21Pt2] = track.c1Pt21Pt2(); + } + + if constexpr ((fillMap & ReducedTrack) > 0) { + values[kPt] = track.pt(); + if (fgUsedVars[kPx]) + values[kPx] = track.px(); + if (fgUsedVars[kPy]) + values[kPy] = track.py(); + if (fgUsedVars[kPz]) + values[kPz] = track.pz(); + values[kEta] = track.eta(); + values[kPhi] = track.phi(); + values[kCharge] = track.charge(); + } + + if constexpr ((fillMap & ReducedTrackBarrel) > 0) { + values[kPin] = track.tpcInnerParam(); + if (fgUsedVars[kITSncls]) { // TODO: add the central data model dynamic column to the reduced table + values[kITSncls] = 0.0; + for (int i = 0; i < 6; ++i) + values[kITSncls] += ((track.itsClusterMap() & (1 << i)) ? 1 : 0); + } + values[kITSchi2] = track.itsChi2NCl(); + values[kTPCncls] = track.tpcNClsFound(); + values[kTPCchi2] = track.tpcChi2NCl(); + values[kTPCsignal] = track.tpcSignal(); + values[kTRDsignal] = track.trdSignal(); + values[kTOFsignal] = track.tofSignal(); + values[kTrackLength] = track.length(); + } + + if constexpr ((fillMap & ReducedTrackBarrelCov) > 0) { + values[kTrackCYY] = track.cYY(); + values[kTrackCZZ] = track.cZZ(); + values[kTrackCSnpSnp] = track.cSnpSnp(); + values[kTrackCTglTgl] = track.cTglTgl(); + values[kTrackC1Pt21Pt2] = track.c1Pt21Pt2(); + } + + if constexpr ((fillMap & ReducedTrackMuon) > 0) { + values[kMuonInvBendingMomentum] = track.inverseBendingMomentum(); + values[kMuonThetaX] = track.thetaX(); + values[kMuonThetaY] = track.thetaY(); + values[kMuonZMu] = track.zMu(); + values[kMuonBendingCoor] = track.bendingCoor(); + values[kMuonNonBendingCoor] = track.nonBendingCoor(); + values[kMuonChi2] = track.chi2(); + values[kMuonChi2MatchTrigger] = track.chi2MatchTrigger(); + } + + FillTrackDerived(values); +} + +template <typename T> +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()); +} + #endif diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 2ede176901463..c8091956a3b53 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -65,81 +65,25 @@ void VarManager::SetRunNumbers(int n, int* runs) } //__________________________________________________________________ -void VarManager::FillEvent(std::vector<float> event, float* values) +void VarManager::FillEventDerived(float* values) { - - //TODO: the Fill function should take as argument an aod::ReducedEvent iterator, this is just a temporary fix - if (!values) - values = fgValues; - - values[kRunNo] = event[0]; + // + // Fill event-wise derived quantities (these are all quantities which can be computed just based on the values already filled in the FillEvent() function) + // if (fgUsedVars[kRunId]) values[kRunId] = (fgRunMap.size() > 0 ? fgRunMap[int(values[kRunNo])] : 0); - values[kVtxX] = event[1]; - values[kVtxY] = event[2]; - values[kVtxZ] = event[3]; - values[kVtxNcontrib] = event[4]; - /*values[kRunNo] = event.runNumber(); - values[kVtxX] = event.posX(); - values[kVtxY] = event.posY(); - values[kVtxZ] = event.posZ(); - values[kVtxNcontrib] = event.numContrib();*/ - //values[kVtxChi2] = event.chi2(); - //values[kBC] = event.bc(); - //values[kCentVZERO] = event.centVZERO(); - //values[kVtxCovXX] = event.covXX(); - //values[kVtxCovXY] = event.covXY(); - //values[kVtxCovXZ] = event.covXZ(); - //values[kVtxCovYY] = event.covYY(); - //values[kVtxCovYZ] = event.covYZ(); - //values[kVtxCovZZ] = event.covZZ(); } //__________________________________________________________________ -void VarManager::FillTrack(std::vector<float> track, float* values) +void VarManager::FillTrackDerived(float* values) { - - if (!values) - values = fgValues; - - values[kPt] = track[0]; - values[kEta] = track[1]; - values[kPhi] = track[2]; - values[kCharge] = track[3]; + // + // Fill track-wise derived quantities (these are all quantities which can be computed just based on the values already filled in the FillTrack() function) + // if (fgUsedVars[kP]) values[kP] = values[kPt] * TMath::CosH(values[kEta]); - /*values[kPt] = track.pt(); - values[kEta] = track.eta(); - values[kPhi] = track.phi(); - values[kCharge] = track.charge();*/ - //values[kPin] = track.tpcInnerParam(); - //if(fgUsedVars[kITSncls]) { - // values[kITSncls] = 0.0; - // for(int i=0; i<6; ++i) - // values[kITSncls] += ((track.itsClusterMap() & (1<<i)) ? 1 : 0); - //} - //values[kITSchi2] = track.itsChi2NCl(); - //values[kTPCncls] = track.tpcNCls(); - //values[kTPCchi2] = track.tpcChi2NCl(); - //values[kTPCsignal] = track.tpcSignal(); - //values[kTRDsignal] = track.trdSignal(); - //values[kTOFsignal] = track.tofSignal(); - //values[kTrackLength] = track.barrelLength(); } -/* -//__________________________________________________________________ -void VarManager::FillTrack(ReducedTrack track, float* values) -{ - if (!values) - values = fgValues; - - values[kPt] = track.pt(); - values[kEta] = track.eta(); - values[kPhi] = track.phi(); - values[kCharge] = track.charge(); -}*/ - //__________________________________________________________________ void VarManager::SetDefaultVarNames() { @@ -155,24 +99,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kRunNo] = ""; fgVariableNames[kRunId] = "Run number"; fgVariableUnits[kRunId] = ""; - fgVariableNames[kRunTimeStart] = "Run start time"; - fgVariableUnits[kRunTimeStart] = ""; - fgVariableNames[kRunTimeStop] = "Run stop time"; - fgVariableUnits[kRunTimeStop] = ""; - fgVariableNames[kLHCFillNumber] = "LHC fill number"; - fgVariableUnits[kLHCFillNumber] = ""; - fgVariableNames[kDipolePolarity] = "Dipole polarity"; - fgVariableUnits[kDipolePolarity] = ""; - fgVariableNames[kL3Polarity] = "L3 polarity"; - fgVariableUnits[kL3Polarity] = ""; - fgVariableNames[kTimeStamp] = "Time stamp"; - fgVariableUnits[kTimeStamp] = ""; + fgVariableNames[kCollisionTime] = "collision time"; + fgVariableUnits[kCollisionTime] = ""; fgVariableNames[kBC] = "Bunch crossing"; fgVariableUnits[kBC] = ""; - fgVariableNames[kInstLumi] = "Instantaneous luminosity"; - fgVariableUnits[kInstLumi] = "Hz/mb"; - fgVariableNames[kEventType] = "Event type"; - fgVariableUnits[kEventType] = ""; fgVariableNames[kIsPhysicsSelection] = "Physics selection"; fgVariableUnits[kIsPhysicsSelection] = ""; fgVariableNames[kVtxX] = "Vtx X "; @@ -203,6 +133,12 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kPt] = "GeV/c"; fgVariableNames[kP] = "p"; fgVariableUnits[kP] = "GeV/c"; + fgVariableNames[kPx] = "p_{x}"; + fgVariableUnits[kPy] = "GeV/c"; + fgVariableNames[kPy] = "p_{y}"; + fgVariableUnits[kPz] = "GeV/c"; + fgVariableNames[kPz] = "p_{z}"; + fgVariableUnits[kPx] = "GeV/c"; fgVariableNames[kEta] = "#eta"; fgVariableUnits[kEta] = ""; fgVariableNames[kPhi] = "#varphi"; @@ -233,6 +169,22 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kTOFsignal] = ""; fgVariableNames[kTrackLength] = "track length"; fgVariableUnits[kTrackLength] = "cm"; + fgVariableNames[kMuonInvBendingMomentum] = "Inverse bending mom."; + fgVariableUnits[kMuonInvBendingMomentum] = "1/(GeV/c)"; + fgVariableNames[kMuonThetaX] = "theta X"; + fgVariableUnits[kMuonThetaX] = ""; + fgVariableNames[kMuonThetaY] = "theta Y"; + fgVariableUnits[kMuonThetaY] = ""; + fgVariableNames[kMuonZMu] = "ZMu"; + fgVariableUnits[kMuonZMu] = ""; + fgVariableNames[kMuonBendingCoor] = "bending coor."; + fgVariableUnits[kMuonBendingCoor] = ""; + fgVariableNames[kMuonNonBendingCoor] = "non-bending coor."; + fgVariableUnits[kMuonNonBendingCoor] = ""; + fgVariableNames[kMuonChi2] = "#chi 2"; + fgVariableUnits[kMuonChi2] = ""; + fgVariableNames[kMuonChi2MatchTrigger] = "#chi 2 trigger match"; + fgVariableUnits[kMuonChi2MatchTrigger] = ""; fgVariableNames[kCandidateId] = ""; fgVariableUnits[kCandidateId] = ""; fgVariableNames[kPairType] = "Pair type"; diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index bf374414da3ad..403e605529701 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -14,6 +14,7 @@ #ifndef O2_Analysis_ReducedInfoTables_H_ #define O2_Analysis_ReducedInfoTables_H_ +#include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Analysis/Centrality.h" #include "MathUtils/Utils.h" @@ -26,6 +27,7 @@ namespace reducedevent // basic event information DECLARE_SOA_COLUMN(Tag, tag, uint64_t); +DECLARE_SOA_COLUMN(TriggerAlias, triggerAlias, uint32_t); } // namespace reducedevent @@ -34,7 +36,7 @@ DECLARE_SOA_TABLE(ReducedEvents, "AOD", "REDUCEDEVENT", o2::soa::Index<>, collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib); DECLARE_SOA_TABLE(ReducedEventsExtended, "AOD", "REEXTENDED", - bc::GlobalBC, bc::TriggerMask, collision::CollisionTime, cent::CentV0M); + bc::GlobalBC, bc::TriggerMask, reducedevent::TriggerAlias, cent::CentV0M); DECLARE_SOA_TABLE(ReducedEventsVtxCov, "AOD", "REVTXCOV", collision::CovXX, collision::CovXY, collision::CovXZ, @@ -57,14 +59,10 @@ 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_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return abs(pt) * cos(phi); }); -DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return abs(pt) * sin(phi); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return abs(pt) * sinh(eta); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pmom, pmom, [](float pt, float eta) -> float { return abs(pt) * cosh(eta); }); - -// MUON tracks extra information -DECLARE_SOA_COLUMN(MuonChi2, muonChi2, float); -DECLARE_SOA_COLUMN(MuonChi2MatchTrigger, muonChi2MatchTrigger, float); +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 reducedtrack @@ -93,16 +91,42 @@ DECLARE_SOA_TABLE(ReducedTracksBarrelCov, "AOD", "RTBARRELCOV", track::CYY, track::CZZ, track::CSnpSnp, track::CTglTgl, track::C1Pt21Pt2); -// TODO: change names of these columns in the AnalysisDataModel to identify the members as muon quantities -DECLARE_SOA_TABLE(ReducedTracksMuon, "AOD", "RTMUON", - reducedtrack::MuonChi2, reducedtrack::MuonChi2MatchTrigger); +// muon quantities +namespace reducedmuon +{ +DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); +DECLARE_SOA_COLUMN(FilteringFlags, filteringFlags, uint64_t); +// the (pt,eta,phi,charge) will be computed in the skimming task +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_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 reducedmuon + +DECLARE_SOA_TABLE(ReducedMuons, "AOD", "RTMUON", + o2::soa::Index<>, reducedmuon::ReducedEventId, reducedmuon::FilteringFlags, + reducedmuon::Pt, reducedmuon::Eta, reducedmuon::Phi, reducedmuon::Charge, + reducedmuon::Px<reducedmuon::Pt, reducedmuon::Phi>, + reducedmuon::Py<reducedmuon::Pt, reducedmuon::Phi>, + reducedmuon::Pz<reducedmuon::Pt, reducedmuon::Eta>, + reducedmuon::Pmom<reducedmuon::Pt, reducedmuon::Eta>); + +DECLARE_SOA_TABLE(ReducedMuonsExtended, "AOD", "RTMUONEXTENDED", + muon::InverseBendingMomentum, + muon::ThetaX, muon::ThetaY, muon::ZMu, + muon::BendingCoor, muon::NonBendingCoor, + muon::Chi2, muon::Chi2MatchTrigger); // iterators using ReducedTrack = ReducedTracks::iterator; using ReducedTrackBarrel = ReducedTracksBarrel::iterator; using ReducedTrackBarrelCov = ReducedTracksBarrelCov::iterator; -using ReducedTrackMuon = ReducedTracksMuon::iterator; - +using ReducedMuon = ReducedMuons::iterator; +using ReducedMuonExtended = ReducedMuonsExtended::iterator; } // namespace o2::aod #endif // O2_Analysis_ReducedInfoTables_H_ diff --git a/Analysis/Tasks/tableMaker.cxx b/Analysis/Tasks/tableMaker.cxx index 5bf673ebdcc76..09aa452ee7acf 100644 --- a/Analysis/Tasks/tableMaker.cxx +++ b/Analysis/Tasks/tableMaker.cxx @@ -17,7 +17,10 @@ #include "Analysis/Multiplicity.h" #include "Analysis/EventSelection.h" #include "Analysis/Centrality.h" +#include "Analysis/TriggerAliases.h" #include "Analysis/ReducedInfoTables.h" +#include "Analysis/VarManager.h" +#include "Analysis/HistogramManager.h" #include <TH1F.h> #include <TMath.h> #include <iostream> @@ -38,36 +41,56 @@ struct TableMaker { Produces<ReducedTracks> trackBasic; Produces<ReducedTracksBarrel> trackBarrel; Produces<ReducedTracksBarrelCov> trackBarrelCov; - //Produces<dq::ReducedTracksMuon> trackMuon; + Produces<ReducedMuons> muonBasic; + Produces<ReducedMuonsExtended> muonExtended; - OutputObj<TH1F> vtxZ{TH1F("vtxZ", "vtx Z", 200, -20.0, 20.0)}; - OutputObj<TH1F> vtxX{TH1F("vtxX", "vtx X", 2000, -1.0, 1.0)}; - OutputObj<TH1F> vtxY{TH1F("vtxY", "vtx Y", 2000, -1.0, 1.0)}; + OutputObj<HistogramManager> fHistMan{"output"}; + + // 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::BC | VarManager::ObjTypes::Collision; + constexpr static uint32_t fgTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackCov; 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("Event;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill } - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, /*aod::Muons const& tracksMuon,*/ aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov> const& tracksBarrel) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov> const& tracksBarrel) { uint64_t tag = 0; - if (collision.sel7()) - tag |= (uint64_t(1) << 0); + uint32_t triggerAliases = 0; + for (int i = 0; i < kNaliases; i++) + if (collision.alias()[i] > 0) + triggerAliases |= (uint32_t(1) << i); - vtxZ->Fill(collision.posZ()); - vtxX->Fill(collision.posX()); - vtxY->Fill(collision.posY()); + VarManager::ResetValues(); + VarManager::FillEvent<fgEventFillMap>(collision); // extract event information and place it in the fgValues array + fHistMan->FillHistClass("Event", VarManager::fgValues); // automatically fill all the histograms in the class Event event(tag, collision.bc().runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib()); - eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), collision.collisionTime(), collision.centV0M()); + eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), triggerAliases, collision.centV0M()); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + uint64_t trackFilteringTag = 0; for (auto& track : tracksBarrel) { if (track.pt() < 1.0) continue; - trackBasic(collision, track.globalIndex(), uint64_t(0), track.pt(), track.eta(), track.phi(), track.charge()); + trackBasic(collision, track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), @@ -77,11 +100,54 @@ struct TableMaker { trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); } - /*for (auto& muon : tracksMuon) { + for (auto& muon : tracksMuon) { // TODO: add proper information for muon tracks - trackBasic(collision, 0, muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), short(0), short(0), uint64_t(1)); - trackMuon(muon.chi2(), muon.chi2MatchTrigger()); - }*/ + if (muon.bc() != collision.bc()) + continue; + trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track + //TODO: the calculation of the muon momentum vector should be done in the central data model + float xSlope = tan(muon.thetaX()); + float ySlope = tan(muon.thetaY()); + float pz = -sqrt(1.0 + ySlope * ySlope) / abs(muon.inverseBendingMomentum()); + float pt = abs(pz) * sqrt(xSlope * xSlope + ySlope * ySlope); + float phi = atan2(ySlope, xSlope); + phi = (phi >= 0.0 ? phi : phi + TMath::TwoPi()); + float eta = acos(pz / sqrt(pt * pt + pz * pz)); + eta = tan(0.5 * eta); + if (eta > 0.0) + eta = -log(eta); + muonBasic(collision, trackFilteringTag, pt, eta, phi, (muon.inverseBendingMomentum() > 0.0 ? short(1) : short(-1))); + muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); + } + } + + void DefineHistograms(TString histClasses) + { + 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 + } + } // end loop over histogram classes } }; diff --git a/Analysis/Tasks/tableReader.cxx b/Analysis/Tasks/tableReader.cxx index e878dcd26a8af..805920c0a0663 100644 --- a/Analysis/Tasks/tableReader.cxx +++ b/Analysis/Tasks/tableReader.cxx @@ -24,6 +24,7 @@ #include <TString.h> #include <iostream> #include <vector> +#include <typeinfo> using std::cout; using std::endl; @@ -39,6 +40,19 @@ struct TableReader { OutputObj<HistogramManager> 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; + constexpr static uint32_t fgMuonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackMuon; void init(o2::framework::InitContext&) { @@ -48,7 +62,7 @@ struct TableReader { fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); - DefineHistograms("Event_BeforeCuts;Event_AfterCuts;Track_BeforeCuts;Track_AfterCuts"); // define all histograms + DefineHistograms("Event_BeforeCuts;Event_AfterCuts;TrackBarrel_BeforeCuts;TrackBarrel_AfterCuts;TrackMuon_BeforeCuts;TrackMuon_AfterCuts;PairsBarrel;PairsMuon;"); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill DefineCuts(); @@ -63,47 +77,95 @@ struct TableReader { 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, cutLow, 0.335, false, VarManager::kVtxX, 0.067, 0.070); - varCut->AddCut(VarManager::kVtxY, 0.0, 0.335); + //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, 2.0, 4.0); + cut1->AddCut(VarManager::kPt, 1.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); AnalysisCut* cut2 = new AnalysisCut(); cut2->AddCut(VarManager::kPt, 0.5, 3.0); fTrackCut->AddCut(cut1); - fTrackCut->AddCut(cut2); + //fTrackCut->AddCut(cut2); + + fMuonCut = new AnalysisCompositeCut(true); + AnalysisCut kineMuonCut; + kineMuonCut.AddCut(VarManager::kPt, 1.5, 10.0); + fMuonCut->AddCut(&kineMuonCut); VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - //void process(soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator event, - // soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel> tracks) - void process(aod::ReducedEvents::iterator event, aod::ReducedTracks tracks) + void process(soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator event, + soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov> const& tracks, + soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended> 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 VarManager::ResetValues(); - std::vector<float> eventInfo = {(float)event.runNumber(), event.posX(), event.posY(), event.posZ(), (float)event.numContrib()}; - VarManager::FillEvent(eventInfo); // extract event information and place it in the fgValues array - + VarManager::FillEvent<fgEventFillMap>(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); + // 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<std::decay_t<decltype(tracks)>::iterator> selectedTracksPos; + std::vector<std::decay_t<decltype(tracks)>::iterator> selectedTracksNeg; for (auto& track : tracks) { - std::vector<float> trackInfo = {track.pt(), track.eta(), track.phi(), (float)track.charge()}; - VarManager::FillTrack(trackInfo); - fHistMan->FillHistClass("Track_BeforeCuts", VarManager::fgValues); + + VarManager::ResetValues(VarManager::kNEventWiseVariables, VarManager::kNMuonTrackVariables); + + VarManager::FillTrack<fgTrackFillMap>(track); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); if (!fTrackCut->IsSelected(VarManager::fgValues)) continue; - fHistMan->FillHistClass("Track_AfterCuts", VarManager::fgValues); + 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 + for (auto& tpos : selectedTracksPos) { + for (auto& tneg : selectedTracksNeg) { + VarManager::FillPair(tpos, tneg); + fHistMan->FillHistClass("PairsBarrel", VarManager::fgValues); + } + } + + // loop over muon tracks + std::vector<std::decay_t<decltype(muons)>::iterator> selectedMuonsPos; + std::vector<std::decay_t<decltype(muons)>::iterator> selectedMuonsNeg; + for (auto& muon : muons) { + VarManager::FillTrack<fgMuonFillMap>(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); + } + + // same event pairing for muons + for (auto& tpos : selectedMuonsNeg) { + for (auto& tneg : selectedMuonsPos) { + VarManager::FillPair(tpos, tneg); + fHistMan->FillHistClass("PairsMuon", VarManager::fgValues); + } } } @@ -152,16 +214,45 @@ struct TableReader { 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 + 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, 100, -1.0, 1.0, VarManager::kEta); // TH1F histogram - fHistMan->AddHistogram(classStr.Data(), "Phi_Eta", "#phi vs #eta distribution", false, 40, -1.0, 1.0, VarManager::kEta, 200, -6.3, 6.3, VarManager::kPhi); // TH2F histogram - //fHistMan.AddHistogram("Track", "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 100, 0.0, 20.0, VarManager::kPin, - // 200, 0.0, 200., VarManager::kTPCsignal); // TH2F 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, 200, 0.0, 20.0, VarManager::kPz); + + if (classStr.Contains("Barrel")) { + fHistMan->AddHistogram(classStr.Data(), "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 100, 0.0, 20.0, VarManager::kPin, + 200, 0.0, 200., VarManager::kTPCsignal); // 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); } } // end loop over histogram classes } From b287ca0ce9a5e9618c8b90fbe2b89e8576089daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Sat, 25 Jul 2020 17:40:17 +0200 Subject: [PATCH 0177/1751] Fix typos. (#4030) --- Analysis/Tasks/hftrackindexskimscreator.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index 80d55aee3474f..7d5269b18cc48 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -203,9 +203,9 @@ struct HFTrackIndexSkimsCreator { std::array<float, 3> pvec0; std::array<float, 3> pvec1; std::array<float, 3> pvec2; - df.getTrack(0).getPxPyPzGlo(pvec0); - df.getTrack(1).getPxPyPzGlo(pvec1); - df.getTrack(2).getPxPyPzGlo(pvec2); + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); addTrack(listTracks, pvec0, masspion); addTrack(listTracks, pvec1, masskaon); @@ -219,7 +219,7 @@ struct HFTrackIndexSkimsCreator { hftrackindexprong3(track_p1.collisionId(), track_p1.globalIndex(), track_n1.globalIndex(), - track_p1.globalIndex(), 2); + track_p2.globalIndex(), 2); } //second loop on negative tracks for (auto i_n2 = i_n1 + 1; i_n2 != tracks.end(); ++i_n2) { @@ -245,9 +245,9 @@ struct HFTrackIndexSkimsCreator { std::array<float, 3> pvec0; std::array<float, 3> pvec1; std::array<float, 3> pvec2; - df.getTrack(0).getPxPyPzGlo(pvec0); - df.getTrack(1).getPxPyPzGlo(pvec1); - df.getTrack(2).getPxPyPzGlo(pvec2); + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); addTrack(listTracks, pvec0, masspion); addTrack(listTracks, pvec1, masskaon); @@ -261,7 +261,7 @@ struct HFTrackIndexSkimsCreator { hftrackindexprong3(track_n1.collisionId(), track_n1.globalIndex(), track_p1.globalIndex(), - track_n1.globalIndex(), 2.); + track_n2.globalIndex(), 2); } } } From 9d77fe21750f350e717f89968f1140106fdca0e6 Mon Sep 17 00:00:00 2001 From: "Parada, Jorge" <Jorge.Parada@amd.com> Date: Fri, 24 Jul 2020 12:51:21 +0200 Subject: [PATCH 0178/1751] GPU: Tune parameters for AMD Vega --- GPU/Common/GPUDefGPUParameters.h | 17 +++++++++-------- .../SliceTracker/GPUTPCTrackletSelector.cxx | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 17e76172eaaff..f029480c1f4a5 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -30,7 +30,7 @@ #if defined(GPUCA_GPUTYPE_VEGA) #define GPUCA_WARP_SIZE 64 #define GPUCA_THREAD_COUNT 256 - #define GPUCA_LB_GPUTPCCreateSliceData 256 + #define GPUCA_LB_GPUTPCCreateSliceData 128 #define GPUCA_LB_GPUTPCStartHitsSorter 1024, 2 #define GPUCA_LB_GPUTPCStartHitsFinder 1024 #define GPUCA_LB_GPUTPCTrackletConstructor 512, 1 @@ -57,7 +57,7 @@ #define GPUCA_LB_GPUTPCGMMergerMergeBorders_step2 256 #define GPUCA_LB_GPUTPCGMMergerMergeCE 256 #define GPUCA_LB_GPUTPCGMMergerLinkGlobalTracks 256 - #define GPUCA_LB_GPUTPCGMMergerCollect 256 + #define GPUCA_LB_GPUTPCGMMergerCollect 512 #define GPUCA_LB_GPUTPCGMMergerSortTracks 256 #define GPUCA_LB_GPUTPCGMMergerSortTracksQPt 256 #define GPUCA_LB_GPUTPCGMMergerSortTracksPrepare 256 @@ -72,12 +72,13 @@ #define GPUCA_LB_GPUTPCCompressionKernels_step2gather 128 #define GPUCA_LB_CLUSTER_FINDER 512 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 5 - #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 6 - #define GPUCA_CONSTRUCTOR_IN_PIPELINE 0 - #define GPUCA_SELECTOR_IN_PIPELINE 0 - #define GPUCA_ALTERNATE_BORDER_SORT 0 - #define GPUCA_SORT_BEFORE_FIT 0 - #define GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION 0 + #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 20 + #define GPUCA_CONSTRUCTOR_IN_PIPELINE 1 + #define GPUCA_SELECTOR_IN_PIPELINE 1 + #define GPUCA_ALTERNATE_BORDER_SORT 1 + #define GPUCA_SORT_BEFORE_FIT 1 + #define GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION 1 + #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_NO_ATOMIC_PRECHECK 1 #elif defined(GPUCA_GPUTYPE_TURING) #define GPUCA_WARP_SIZE 32 diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx index 00b999c821bdb..2c49c33c3f129 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx @@ -58,6 +58,7 @@ GPUdii() void GPUTPCTrackletSelector::Thread<0>(int nBlocks, int nThreads, int i int nHits = 0; const int minHits = tracker.Param().rec.MinNTrackClusters == -1 ? GPUCA_TRACKLET_SELECTOR_MIN_HITS(tracklet.Param().QPt()) : tracker.Param().rec.MinNTrackClusters; + GPUCA_UNROLL(, U(1)) for (irow = firstRow; irow <= lastRow && lastRow - irow + nHits >= minHits; irow++) { gap++; calink ih = tracker.TrackletRowHits()[tracklet.FirstHit() + (irow - firstRow)]; From e013f3efaf4da891a904216247734ff05c9dc8f7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 24 Jul 2020 13:00:47 +0200 Subject: [PATCH 0179/1751] GPU: Add macro to apply different inline attributes depending on architecture, and apply some tuning for AMD --- GPU/Common/GPUCommonDefAPI.h | 7 +++++++ GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 1 + GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 1 + GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 6 +++--- GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx | 4 ++-- 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/GPU/Common/GPUCommonDefAPI.h b/GPU/Common/GPUCommonDefAPI.h index bbfffa4d5a314..2a4a9f249f615 100644 --- a/GPU/Common/GPUCommonDefAPI.h +++ b/GPU/Common/GPUCommonDefAPI.h @@ -172,6 +172,13 @@ #define GPUAtomic(type) type #endif +#ifndef GPUdic // Takes different parameter for inlining: 0 = never, 1 = always, 2 = compiler-decision +#define GPUdic(...) GPUd() +#endif +#define GPUCA_GPUdic_select_0() GPUdni() +#define GPUCA_GPUdic_select_1() GPUdii() +#define GPUCA_GPUdic_select_2() GPUd() + #ifdef GPUCA_CONSTANT_AS_ARGUMENT #undef GPUconstant #define GPUconstant() diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 0a7a122adc1ea..d514d753c54b3 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -13,6 +13,7 @@ #define GPUCA_GPUTYPE_TURING #define GPUCA_UNROLL(CUDA, HIP) GPUCA_M_UNROLL_##CUDA +#define GPUdic(CUDA, HIP) GPUCA_GPUdic_select_##CUDA() #include <cuda.h> #include <cuda_profiler_api.h> diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index 9517f41f90486..fe911960742d9 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -13,6 +13,7 @@ #define GPUCA_GPUTYPE_VEGA #define GPUCA_UNROLL(CUDA, HIP) GPUCA_M_UNROLL_##HIP +#define GPUdic(CUDA, HIP) GPUCA_GPUdic_select_##HIP() #include <hip/hip_runtime.h> #ifdef __CUDACC__ diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index 1cec87e24e0c9..cbf6050271cb8 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -1064,7 +1064,7 @@ GPUd() o2::base::MatBudget GPUTPCGMPropagator::getMatBudget(const float* p1, con #endif } -GPUdni() void GPUTPCGMPropagator::UpdateMaterial(const GPUTPCGMPhysicalTrackModel& GPUrestrict() t0e) +GPUdic(0, 1) void GPUTPCGMPropagator::UpdateMaterial(const GPUTPCGMPhysicalTrackModel& GPUrestrict() t0e) { #ifdef HAVE_O2HEADERS float xyz1[3] = {getGlobalX(mT0.GetX(), mT0.GetY()), getGlobalY(mT0.GetX(), mT0.GetY()), mT0.GetZ()}; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index b61c55d0eed52..b9b3482a317d3 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -566,7 +566,7 @@ GPUd() bool GPUTPCGMTrackParam::FollowCircleChk(float lrFactor, float toY, float (up ? (-mP[0] * lrFactor > toX || (right ^ (mP[2] > 0))) : (-mP[0] * lrFactor < toX || (right ^ (mP[2] < 0)))); // don't overshoot in X } -GPUdni() void GPUTPCGMTrackParam::StoreAttachMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toY, float toX, int toSlice, int toRow, bool inFlyDirection, float alpha) +GPUdic(0, 1) void GPUTPCGMTrackParam::StoreAttachMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toY, float toX, int toSlice, int toRow, bool inFlyDirection, float alpha) { unsigned int nLoopData = CAMath::AtomicAdd(&Merger->Memory()->nLoopData, 1u); if (nLoopData >= Merger->NMaxTracks()) { @@ -590,7 +590,7 @@ GPUdni() void GPUTPCGMTrackParam::StoreAttachMirror(const GPUTPCGMMerger* GPUres Merger->LoopData()[nLoopData] = data; } -GPUd() void GPUTPCGMTrackParam::RefitLoop(const GPUTPCGMMerger* GPUrestrict() Merger, int loopIdx) +GPUdii() void GPUTPCGMTrackParam::RefitLoop(const GPUTPCGMMerger* GPUrestrict() Merger, int loopIdx) { GPUTPCGMPropagator prop; prop.SetMaterialTPC(); @@ -612,7 +612,7 @@ GPUd() void GPUTPCGMTrackParam::RefitLoop(const GPUTPCGMMerger* GPUrestrict() Me } template <int I> -GPUdni() int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestrict() Merger, GPUTPCGMPropagator& GPUrestrict() prop, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toX, float toY, int toSlice, int toRow, bool inFlyDirection, bool phase2) +GPUdic(0, 1) int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestrict() Merger, GPUTPCGMPropagator& GPUrestrict() prop, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toX, float toY, int toSlice, int toRow, bool inFlyDirection, bool phase2) { if (Merger->Param().rec.DisableRefitAttachment & 4) { return 1; diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx index 865925d2181b1..d29e041f122de 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx @@ -107,7 +107,7 @@ GPUd() void GPUTPCTrackletConstructor::StoreTracklet(int /*nBlocks*/, int /*nThr } MEM_CLASS_PRE2_TEMPLATE(class T) -GPUd() void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int /*nThreads*/, int /*iBlock*/, int /*iThread*/, GPUsharedref() T& GPUrestrict() s, GPUTPCThreadMemory& GPUrestrict() r, GPUconstantref() MEM_GLOBAL(GPUTPCTracker) & GPUrestrict() tracker, MEM_LG2(GPUTPCTrackParam) & GPUrestrict() tParam, int iRow, calink& rowHit) +GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int /*nThreads*/, int /*iBlock*/, int /*iThread*/, GPUsharedref() T& GPUrestrict() s, GPUTPCThreadMemory& GPUrestrict() r, GPUconstantref() MEM_GLOBAL(GPUTPCTracker) & GPUrestrict() tracker, MEM_LG2(GPUTPCTrackParam) & GPUrestrict() tParam, int iRow, calink& rowHit) { // reconstruction of tracklets, tracklets update step CA_MAKE_SHARED_REF(GPUTPCRow, row, tracker.Row(iRow), s.mRows[iRow]); @@ -353,7 +353,7 @@ GPUd() void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int /*nTh } } -GPUd() void GPUTPCTrackletConstructor::DoTracklet(GPUconstantref() MEM_GLOBAL(GPUTPCTracker) & GPUrestrict() tracker, GPUsharedref() GPUTPCTrackletConstructor::MEM_LOCAL(GPUSharedMemory) & GPUrestrict() s, GPUTPCThreadMemory& GPUrestrict() r) +GPUdic(2, 1) void GPUTPCTrackletConstructor::DoTracklet(GPUconstantref() MEM_GLOBAL(GPUTPCTracker) & GPUrestrict() tracker, GPUsharedref() GPUTPCTrackletConstructor::MEM_LOCAL(GPUSharedMemory) & GPUrestrict() s, GPUTPCThreadMemory& GPUrestrict() r) { int iRow = 0, iRowEnd = GPUCA_ROW_COUNT; MEM_PLAIN(GPUTPCTrackParam) From 4e17ef966b3dfe8e780282571e698bd8d3d923b7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 24 Jul 2020 21:48:52 +0200 Subject: [PATCH 0180/1751] GPU: Fix help message of standalone benchmark, use default constructor and don't pass 0, which can fail --- GPU/GPUTracking/Base/GPUSettingsList.h | 6 +++--- GPU/GPUTracking/Standalone/utils/qconfig.cxx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index f26f60297f1f6..76e74572cf6e9 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -240,12 +240,12 @@ AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") AddHelp("help", 'h') AddHelpAll("helpall", 'H') +AddSubConfig(GPUSettingsRec, rec) +AddSubConfig(GPUSettingsProcessing, proc) AddSubConfig(GPUSettingsTF, TF) AddSubConfig(GPUSettingsQA, QA) -AddSubConfig(GPUSettingsEG, EG) AddSubConfig(GPUSettingsDisplay, GL) -AddSubConfig(GPUSettingsRec, rec) -AddSubConfig(GPUSettingsProcessing, proc) +AddSubConfig(GPUSettingsEG, EG) EndConfig() #elif defined(GPUCA_O2_LIB) || defined(GPUCA_O2_INTERFACE) // GPUCA_STANDALONE BeginSubConfig(GPUSettingsO2, global, configStandalone, "O2", 0, "O2 workflow settings") diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index ffa94f45bd53c..79dd8cffbe68b 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -73,9 +73,9 @@ static inline const char* getOptName(const char** argv, int i) template <typename T> struct qConfigSettings { - qConfigSettings() : checkMin(false), checkMax(false), doSet(false), doDefault(false), min(0), max(0), set(0), message(nullptr), allowEmpty(false){}; + qConfigSettings() : checkMin(false), checkMax(false), doSet(false), doDefault(false), min(), max(), set(), message(nullptr), allowEmpty(false){}; template <typename S> - qConfigSettings(const qConfigSettings<S> v) : checkMin(false), checkMax(false), doSet(false), doDefault(false), min(0), max(0), set(0), message(v.message), allowEmpty(v.allowEmpty){}; + qConfigSettings(const qConfigSettings<S> v) : checkMin(false), checkMax(false), doSet(false), doDefault(false), min(), max(), set(), message(v.message), allowEmpty(v.allowEmpty){}; bool checkMin, checkMax; bool doSet, doDefault; T min, max; From 58815babbe853d33349c8b658486711fc1441823 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 24 Jul 2020 22:46:29 +0200 Subject: [PATCH 0181/1751] GPU: Fix typo --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index defb82bb5b11e..86f5b0e042635 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1972,7 +1972,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) mOutputQueue.clear(); } - runKernel<GPUTPCGMMergerTrackFit>(GetGridBlk(Merger.NOutputTracks(), 0), krnlRunRangeNone, krnlEventNone, GetProcessingSettings().mergerSortTracks ? 1 : 0); + runKernel<GPUTPCGMMergerTrackFit>(GetGrid(Merger.NOutputTracks(), 0), krnlRunRangeNone, krnlEventNone, GetProcessingSettings().mergerSortTracks ? 1 : 0); if (param().rec.retryRefit == 1) { runKernel<GPUTPCGMMergerTrackFit>(GetGridAuto(0), krnlRunRangeNone, krnlEventNone, -1); } From 515ff74f36a48456a2bde21fe052905f1c151e37 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 25 Jul 2020 19:46:59 +0200 Subject: [PATCH 0182/1751] GPU: Solve performance problem with AMD compiler --- GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx index e00ada516132e..7e2a54fabf624 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx @@ -154,7 +154,7 @@ GPUdi() static void UpdateMinMaxYZ(float& yMin, float& yMax, float& zMin, float& } } -GPUd() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int iBlock, int iThread, GPUconstantref() const MEM_CONSTANT(GPUConstantMem) * GPUrestrict() mem, int iSlice, float* tmpMinMax) +GPUdii() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int iBlock, int iThread, GPUconstantref() const MEM_CONSTANT(GPUConstantMem) * GPUrestrict() mem, int iSlice, float* tmpMinMax) { #ifdef GPUCA_GPUCODE constexpr bool EarlyTransformWithoutClusterNative = false; From 52d7ddb10dcb57de1fd12c053122be6a7a6cc8a9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 25 Jul 2020 22:49:13 +0200 Subject: [PATCH 0183/1751] GPU: Use non-spinning waits to reduce HIP runtime CPU load --- GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index fe911960742d9..fb883e432df21 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -330,6 +330,10 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() GPUError("Could not set HIP Device!"); return (1); } + if (GPUFailedMsgI(hipSetDeviceFlags(hipDeviceScheduleBlockingSync))) { + GPUError("Could not set HIP Device!"); + return (1); + } /*if (GPUFailedMsgI(hipDeviceSetLimit(hipLimitStackSize, GPUCA_GPU_STACK_SIZE))) { @@ -398,7 +402,7 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() for (unsigned int i = 0; i < mEvents.size(); i++) { hipEvent_t* events = (hipEvent_t*)mEvents[i].data(); for (unsigned int j = 0; j < mEvents[i].size(); j++) { - if (GPUFailedMsgI(hipEventCreate(&events[j]))) { + if (GPUFailedMsgI(hipEventCreateWithFlags(&events[j], hipEventBlockingSync))) { GPUError("Error creating event"); GPUFailedMsgI(hipDeviceReset()); return 1; From 1ba2c91c851d65a710094789c2eabcc570471789 Mon Sep 17 00:00:00 2001 From: iouribelikov <iouri.belikov@cern.ch> Date: Mon, 27 Jul 2020 15:27:22 +0200 Subject: [PATCH 0184/1751] Using noise maps inside the ITSMFT raw data decoder (#4027) * Introducing a noise map to the AlpideCoder (thanks to Zhaozhong Shi) * A macro generating noise maps out of digits (thanks to Zhaozhong Shi) * Setting the software chipID outside the AlpideCoder * Command-line option for the name of noise map file * A macro generating noise maps out of clusters * Check end-of-cable-data when calculating the software chip id * Hiding the current noise map implementation behind a dedicated class * Improving the noise map class. Passing the noise map object to the AlpideCoder via a pointer. * The topology dictionary is actually not needed for the 1pix-cluster noise calibration * The number of chips in a noise map becomes a parameter --- .../Detectors/ITSMFT/common/CMakeLists.txt | 2 + .../include/DataFormatsITSMFT/NoiseMap.h | 95 +++++++++++++++++++ .../common/src/ITSMFTDataFormatsLinkDef.h | 1 + .../Detectors/ITSMFT/common/src/NoiseMap.cxx | 16 ++++ Detectors/ITSMFT/ITS/macros/CMakeLists.txt | 1 + .../ITSMFT/ITS/macros/Calib/CMakeLists.txt | 20 ++++ .../macros/Calib/MakeNoiseMapFromClusters.C | 81 ++++++++++++++++ .../ITS/macros/Calib/MakeNoiseMapFromDigits.C | 38 ++++++++ .../ITSMFTReconstruction/AlpideCoder.h | 42 ++++++-- .../ITSMFTReconstruction/RUDecodeData.h | 12 ++- .../common/reconstruction/src/AlpideCoder.cxx | 4 + .../include/ITSMFTWorkflow/STFDecoderSpec.h | 7 +- .../common/workflow/src/STFDecoderSpec.cxx | 23 +++-- .../workflow/src/stf-decoder-workflow.cxx | 6 +- 14 files changed, 329 insertions(+), 19 deletions(-) create mode 100644 DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h create mode 100644 DataFormats/Detectors/ITSMFT/common/src/NoiseMap.cxx create mode 100644 Detectors/ITSMFT/ITS/macros/Calib/CMakeLists.txt create mode 100644 Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C create mode 100644 Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromDigits.C diff --git a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt index 712dedda2b3ae..01cd0301c980d 100644 --- a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt +++ b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt @@ -11,6 +11,7 @@ o2_add_library(DataFormatsITSMFT SOURCES src/ROFRecord.cxx src/Digit.cxx + src/NoiseMap.cxx src/Cluster.cxx src/CompCluster.cxx src/ClusterPattern.cxx @@ -24,6 +25,7 @@ o2_add_library(DataFormatsITSMFT o2_target_root_dictionary(DataFormatsITSMFT HEADERS include/DataFormatsITSMFT/ROFRecord.h include/DataFormatsITSMFT/Digit.h + include/DataFormatsITSMFT/NoiseMap.h include/DataFormatsITSMFT/Cluster.h include/DataFormatsITSMFT/CompCluster.h include/DataFormatsITSMFT/ClusterPattern.h diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h new file mode 100644 index 0000000000000..af685a0bf3423 --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h @@ -0,0 +1,95 @@ +// 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 NoiseMap.h +/// \brief Definition of the ITSMFT NoiseMap +#ifndef ALICEO2_ITSMFT_NOISEMAP_H +#define ALICEO2_ITSMFT_NOISEMAP_H + +#include "Rtypes.h" // for Double_t, ULong_t, etc +#include <iostream> +#include <climits> +#include <vector> +#include <map> + +namespace o2 +{ + +namespace itsmft +{ +/// \class NoiseMap +/// \brief NoiseMap class for the ITS and MFT +/// + +class NoiseMap +{ + + public: + /// Constructor, initializing values for position, charge and readout frame + NoiseMap(std::vector<std::map<int, int>>& noise) { mNoisyPixels.swap(noise); } + + /// Constructor + NoiseMap() = default; + /// Constructor + NoiseMap(int nchips) + { + mNoisyPixels.assign(nchips, std::map<int, int>()); + } + /// Destructor + ~NoiseMap() = default; + + /// Get the noise level for this pixels + float getNoiseLevel(int chip, int row, int col) const + { + if (chip > mNoisyPixels.size()) + return 0; + auto key = row * 1024 + col; + const auto keyIt = mNoisyPixels[chip].find(key); + if (keyIt != mNoisyPixels[chip].end()) + return keyIt->second; + return 0; + } + + void increaseNoiseCount(int chip, int row, int col) + { + if (chip > mNoisyPixels.size()) + return; + auto key = row * 1024 + col; + mNoisyPixels[chip][key]++; + } + + int dumpAboveThreshold(int t = 3) const + { + int n = 0; + auto chipID = mNoisyPixels.size(); + while (chipID--) { + const auto& map = mNoisyPixels[chipID]; + for (const auto& pair : map) { + if (pair.second <= t) + continue; + n++; + auto key = pair.first; + auto row = key / 1024; + auto col = key % 1024; + std::cout << "chip, row, col, noise: " << chipID << ' ' << row << ' ' << col << ' ' << pair.second << '\n'; + } + } + return n; + } + + private: + std::vector<std::map<int, int>> mNoisyPixels; ///< Internal noise map representation + + ClassDefNV(NoiseMap, 1); +}; +} // namespace itsmft +} // namespace o2 + +#endif /* ALICEO2_ITSMFT_NOISEMAP_H */ diff --git a/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h b/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h index 38853604b2d43..93d32c016b985 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h +++ b/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h @@ -15,6 +15,7 @@ #pragma link off all functions; #pragma link C++ class o2::itsmft::Digit + ; +#pragma link C++ class o2::itsmft::NoiseMap + ; #pragma link C++ class std::vector < o2::itsmft::Digit> + ; #pragma link C++ class o2::itsmft::ROFRecord + ; diff --git a/DataFormats/Detectors/ITSMFT/common/src/NoiseMap.cxx b/DataFormats/Detectors/ITSMFT/common/src/NoiseMap.cxx new file mode 100644 index 0000000000000..a1c95abb6e37a --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/src/NoiseMap.cxx @@ -0,0 +1,16 @@ +// 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 NoiseMap.cxx +/// \brief Implementation of the ITSMFT NoiseMap + +#include "DataFormatsITSMFT/NoiseMap.h" + +ClassImp(o2::itsmft::NoiseMap); diff --git a/Detectors/ITSMFT/ITS/macros/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/CMakeLists.txt index b88d9a3a43c4e..433d0e3e352e0 100644 --- a/Detectors/ITSMFT/ITS/macros/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/macros/CMakeLists.txt @@ -10,3 +10,4 @@ add_subdirectory(EVE) add_subdirectory(test) +add_subdirectory(Calib) diff --git a/Detectors/ITSMFT/ITS/macros/Calib/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/Calib/CMakeLists.txt new file mode 100644 index 0000000000000..ef2e78517ace7 --- /dev/null +++ b/Detectors/ITSMFT/ITS/macros/Calib/CMakeLists.txt @@ -0,0 +1,20 @@ +# 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_test_root_macro(MakeNoiseMapFromDigits.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsITSMFT + O2::ITSMFTBase + O2::ITSBase) + +o2_add_test_root_macro(MakeNoiseMapFromClusters.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsITSMFT + O2::ITSMFTBase + O2::ITSBase) + diff --git a/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C new file mode 100644 index 0000000000000..cc5b7967fcbf8 --- /dev/null +++ b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C @@ -0,0 +1,81 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include <iostream> +#include <vector> +#include <string> + +#include <TFile.h> +#include <TTree.h> + +#include "DataFormatsITSMFT/ClusterPattern.h" +#include "DataFormatsITSMFT/CompCluster.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "DataFormatsITSMFT/NoiseMap.h" + +#endif + +void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string output = "noise.root", int threshold = 3) +{ + TFile in(input.data()); + if (!in.IsOpen()) { + std::cerr << "Can not open the input file " << input << '\n'; + return; + } + auto clusTree = (TTree*)in.Get("o2sim"); + if (!clusTree) { + std::cerr << "Can not get cluster tree\n"; + return; + } + + // Clusters + std::vector<o2::itsmft::CompClusterExt>* clusters = nullptr; + clusTree->SetBranchAddress("ITSClusterComp", &clusters); + + // Pixel patterns + std::vector<unsigned char>* patternsPtr = nullptr; + auto pattBranch = clusTree->GetBranch("ITSClusterPatt"); + if (pattBranch) { + pattBranch->SetAddress(&patternsPtr); + } + + //RO frames + std::vector<o2::itsmft::ROFRecord>* rofVec = nullptr; + clusTree->SetBranchAddress("ITSClustersROF", &rofVec); + + o2::itsmft::NoiseMap noiseMap(24120); + + int n1pix = 0; + auto nevents = clusTree->GetEntries(); + for (int n = 0; n < nevents; n++) { + clusTree->GetEntry(n); + auto pattIt = patternsPtr->cbegin(); + for (const auto& rof : *rofVec) { + auto clustersInFrame = rof.getROFData(*clusters); + for (const auto& c : clustersInFrame) { + if (c.getPatternID() != o2::itsmft::CompCluster::InvalidPatternID) + continue; + o2::itsmft::ClusterPattern patt(pattIt); + if (patt.getRowSpan() != 1) + continue; + if (patt.getColumnSpan() != 1) + continue; + auto id = c.getSensorID(); + auto row = c.getRow(); + auto col = c.getCol(); + noiseMap.increaseNoiseCount(id, row, col); + n1pix++; + } + } + } + + int ncalib = noiseMap.dumpAboveThreshold(threshold); + std::cout << "Threshold: " << threshold << " number of pixels: " << ncalib << '\n'; + std::cout << "Number of 1-pixel clusters: " << n1pix << '\n'; + + TFile out(output.data(), "new"); + if (!out.IsOpen()) { + std::cerr << "Can not open the output file " << output << '\n'; + return; + } + out.WriteObject(&noiseMap, "Noise"); + out.Close(); +} diff --git a/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromDigits.C b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromDigits.C new file mode 100644 index 0000000000000..3ee33831ebc39 --- /dev/null +++ b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromDigits.C @@ -0,0 +1,38 @@ +#include <TFile.h> +#include <TTree.h> +#include <iostream> +#include "DataFormatsITSMFT/ROFRecord.h" +#include "DataFormatsITSMFT/Digit.h" +#include "DataFormatsITSMFT/NoiseMap.h" + +void MakeNoiseMapFromDigits(std::string digifile = "itsdigits.root", int hitCut = 3) +{ + // Digits + TFile* file1 = TFile::Open(digifile.data()); + TTree* digTree = (TTree*)file1->Get("o2sim"); + std::vector<o2::itsmft::Digit>* digArr = nullptr; + digTree->SetBranchAddress("ITSDigit", &digArr); + + o2::itsmft::NoiseMap noiseMap(24120); + + int nevD = digTree->GetEntries(), nd = 0; + for (int iev = 0; iev < nevD; iev++) { + digTree->GetEvent(iev); + for (const auto& d : *digArr) { + nd++; + auto id = d.getChipIndex(); + auto row = d.getRow(); + auto col = d.getColumn(); + noiseMap.increaseNoiseCount(id, row, col); + } + } + + TFile* fout = new TFile("ITSnoise.root", "new"); + fout->cd(); + fout->WriteObject(&noiseMap, "Noise"); + fout->Close(); + + int nPixelCalib = noiseMap.dumpAboveThreshold(hitCut); + std::cout << "Noise threshold = " << hitCut << " Noisy pixels = " << nPixelCalib << '\n'; + std::cout << "Total Digits Processed = " << nd << '\n'; +} diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h index bae591a99444d..824393966a625 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h @@ -20,8 +20,10 @@ #include <FairLogger.h> #include <iostream> #include "PayLoadCont.h" +#include <map> #include "ITSMFTReconstruction/PixelData.h" +#include "DataFormatsITSMFT/NoiseMap.h" /// \file AlpideCoder.h /// \brief class for the ALPIDE data decoding/encoding @@ -103,6 +105,9 @@ class AlpideCoder static bool isEmptyChip(uint8_t b) { return (b & CHIPEMPTY) == CHIPEMPTY; } + static void setNoisyPixels(const NoiseMap* noise) { mNoisyPixels = noise; } + static void setNoiseThreshold(int t) { mNoiseThreshold = t; } + /// decode alpide data for the next non-empty chip from the buffer template <class T> static int decodeChip(ChipPixelData& chipData, T& buffer) @@ -127,7 +132,7 @@ class AlpideCoder uint8_t dataCM = dataC & (~MaskChipID); // if ((expectInp & ExpectChipEmpty) && dataCM == CHIPEMPTY) { // empty chip was expected - chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module + //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module if (!buffer.next(timestamp)) { return unexpectedEOF("CHIP_EMPTY:Timestamp"); } @@ -136,7 +141,7 @@ class AlpideCoder } if ((expectInp & ExpectChipHeader) && dataCM == CHIPHEADER) { // chip header was expected - chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module + //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module if (!buffer.next(timestamp)) { return unexpectedEOF("CHIP_HEADER"); } @@ -158,7 +163,7 @@ class AlpideCoder if (nRightCHits) { colDPrev++; for (int ihr = 0; ihr < nRightCHits; ihr++) { - chipData.getData().emplace_back(rightColHits[ihr], colDPrev); + addHit(chipData, rightColHits[ihr], colDPrev); } } break; @@ -186,7 +191,7 @@ class AlpideCoder if (colD != colDPrev) { colDPrev++; for (int ihr = 0; ihr < nRightCHits; ihr++) { - chipData.getData().emplace_back(rightColHits[ihr], colDPrev); + addHit(chipData, rightColHits[ihr], colDPrev); } colDPrev = colD; nRightCHits = 0; // reset the buffer @@ -200,7 +205,7 @@ class AlpideCoder if (rightC) { rightColHits[nRightCHits++] = row; // col = colD+1 } else { - chipData.getData().emplace_back(row, colD); // col = colD, left column hits are added directly to the container + addHit(chipData, row, colD); // col = colD, left column hits are added directly to the container } if ((dataS & (~MaskDColID)) == DATALONG) { // multiple hits ? @@ -216,7 +221,7 @@ class AlpideCoder if (rightC) { // same as above rightColHits[nRightCHits++] = rowE; } else { - chipData.getData().emplace_back(rowE, colD + rightC); // left column hits are added directly to the container + addHit(chipData, rowE, colD + rightC); // left column hits are added directly to the container } } } @@ -264,8 +269,27 @@ class AlpideCoder void print() const; void reset(); // + template <class T> + static int getChipID(T& buffer) + { + uint8_t id = 0; + return (buffer.current(id) && isChipHeaderOrEmpty(id)) ? (id & AlpideCoder::MaskChipID) : -1; + } private: + /// Output a non-noisy fired pixel + static void addHit(ChipPixelData& chipData, short row, short col) + { + if (mNoisyPixels) { + auto chipID = chipData.getChipID(); + if (mNoisyPixels->getNoiseLevel(chipID, row, col) > mNoiseThreshold) { + return; + } + } + + chipData.getData().emplace_back(row, col); + } + ///< add pixed to compressed matrix, the data must be provided sorted in row/col, no check is done void addPixel(short row, short col) { @@ -346,11 +370,15 @@ class AlpideCoder // ===================================================================== // + + static const NoiseMap* mNoisyPixels; + static int mNoiseThreshold; + // cluster map used for the ENCODING only std::vector<int> mFirstInRow; //! entry of 1st pixel of each non-empty row in the mPix2Encode std::vector<PixLink> mPix2Encode; //! pool of links: fired pixel + index of the next one in the row // - ClassDefNV(AlpideCoder, 1); + ClassDefNV(AlpideCoder, 2); }; } // namespace itsmft diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h index 00391e9294ec8..0a43f63cc9617 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h @@ -73,14 +73,24 @@ int RUDecodeData::decodeROF(const Mapping& mp) continue; } int nhits = 0; + int cid = AlpideCoder::getChipID(cableData[icab]); + if (cid < 0) { + continue; + } + chipData->setChipID(mp.getGlobalChipID(cid, cableHWID[icab], *ruInfo)); while ((nhits = AlpideCoder::decodeChip(*chipData, cableData[icab]))) { // we register only chips with hits or errors flags set if (nhits > 0) { // convert HW chip id within the module to absolute chip id - chipData->setChipID(mp.getGlobalChipID(chipData->getChipID(), cableHWID[icab], *ruInfo)); + //chipData->setChipID(mp.getGlobalChipID(chipData->getChipID(), cableHWID[icab], *ruInfo)); setROFInfo(chipData, cableLinkPtr[icab]); ntot += nhits; if (++nChipsFired < chipsData.size()) { // fetch next free chip chipData = &chipsData[nChipsFired]; + cid = AlpideCoder::getChipID(cableData[icab]); + if (cid < 0) { + continue; + } + chipData->setChipID(mp.getGlobalChipID(cid, cableHWID[icab], *ruInfo)); } else { break; // last chip decoded } diff --git a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx index 4bedd22889528..05376a1298ae4 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx @@ -13,9 +13,13 @@ #include "ITSMFTReconstruction/AlpideCoder.h" #include <TClass.h> +#include <TFile.h> using namespace o2::itsmft; +const NoiseMap* AlpideCoder::mNoisyPixels = nullptr; +int AlpideCoder::mNoiseThreshold = 3; + //_____________________________________ void AlpideCoder::print() const { diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h index 166eecd60da12..66567aa47a32c 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h @@ -37,7 +37,7 @@ template <class Mapping> class STFDecoder : public Task { public: - STFDecoder(bool clusters = true, bool pattern = true, bool digits = false, std::string_view dict = ""); + STFDecoder(bool clusters = true, bool pattern = true, bool digits = false, std::string_view dict = "", std::string_view noise = ""); ~STFDecoder() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -53,6 +53,7 @@ class STFDecoder : public Task size_t mTFCounter = 0; std::string mSelfName; std::string mDictName; + std::string mNoiseName; std::unique_ptr<RawPixelDecoder<Mapping>> mDecoder; std::unique_ptr<Clusterer> mClusterer; }; @@ -61,8 +62,8 @@ using STFDecoderITS = STFDecoder<ChipMappingITS>; using STFDecoderMFT = STFDecoder<ChipMappingMFT>; /// create a processor spec -o2::framework::DataProcessorSpec getSTFDecoderITSSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict); -o2::framework::DataProcessorSpec getSTFDecoderMFTSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict); +o2::framework::DataProcessorSpec getSTFDecoderITSSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict, const std::string& noise); +o2::framework::DataProcessorSpec getSTFDecoderMFTSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict, const std::string& noise); } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index e9b53db160b6d..224a0ada3a283 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -40,8 +40,8 @@ using namespace o2::framework; ///_______________________________________ template <class Mapping> -STFDecoder<Mapping>::STFDecoder(bool doClusters, bool doPatterns, bool doDigits, std::string_view dict) - : mDoClusters(doClusters), mDoPatterns(doPatterns), mDoDigits(doDigits), mDictName(dict) +STFDecoder<Mapping>::STFDecoder(bool doClusters, bool doPatterns, bool doDigits, std::string_view dict, std::string_view noise) + : mDoClusters(doClusters), mDoPatterns(doPatterns), mDoDigits(doDigits), mDictName(dict), mNoiseName(noise) { mSelfName = o2::utils::concat_string(Mapping::getName(), "STFDecoder"); mTimer.Stop(); @@ -60,6 +60,17 @@ void STFDecoder<Mapping>::init(InitContext& ic) mDecoder->setNThreads(mNThreads); mDecoder->setFormat(ic.options().get<bool>("old-format") ? GBTLink::OldFormat : GBTLink::NewFormat); mDecoder->setVerbosity(ic.options().get<int>("decoder-verbosity")); + + std::string noiseFile = o2::base::NameConf::getDictionaryFileName(detID, mNoiseName, ".root"); + if (o2::base::NameConf::pathExists(noiseFile)) { + TFile* f = TFile::Open(noiseFile.data(), "old"); + auto pnoise = (NoiseMap*)f->Get("Noise"); + AlpideCoder::setNoisyPixels(pnoise); + LOG(INFO) << mSelfName << " loading noise map file: " << noiseFile; + } else { + LOG(INFO) << mSelfName << " Noise file " << noiseFile << " is absent, " << Mapping::getName() << " running without noise suppression"; + } + if (mDoClusters) { mClusterer = std::make_unique<Clusterer>(); mClusterer->setNChips(Mapping::getNChips()); @@ -149,7 +160,7 @@ void STFDecoder<Mapping>::endOfStream(EndOfStreamContext& ec) } } -DataProcessorSpec getSTFDecoderITSSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict) +DataProcessorSpec getSTFDecoderITSSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict, const std::string& noise) { std::vector<OutputSpec> outputs; auto orig = o2::header::gDataOriginITS; @@ -168,14 +179,14 @@ DataProcessorSpec getSTFDecoderITSSpec(bool doClusters, bool doPatterns, bool do "its-stf-decoder", Inputs{{"stf", ConcreteDataTypeMatcher{orig, "RAWDATA"}, Lifetime::Timeframe}}, outputs, - AlgorithmSpec{adaptFromTask<STFDecoder<ChipMappingITS>>(doClusters, doPatterns, doDigits, dict)}, + AlgorithmSpec{adaptFromTask<STFDecoder<ChipMappingITS>>(doClusters, doPatterns, doDigits, dict, noise)}, Options{ {"nthreads", VariantType::Int, 1, {"Number of decoding/clustering threads"}}, {"old-format", VariantType::Bool, false, {"Use old format (1 trigger per CRU page)"}}, {"decoder-verbosity", VariantType::Int, 0, {"Verbosity level (-1: silent, 0: errors, 1: headers, 2: data)"}}}}; } -DataProcessorSpec getSTFDecoderMFTSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict) +DataProcessorSpec getSTFDecoderMFTSpec(bool doClusters, bool doPatterns, bool doDigits, const std::string& dict, const std::string& noise) { std::vector<OutputSpec> outputs; auto orig = o2::header::gDataOriginMFT; @@ -196,7 +207,7 @@ DataProcessorSpec getSTFDecoderMFTSpec(bool doClusters, bool doPatterns, bool do "mft-stf-decoder", Inputs{{"stf", ConcreteDataTypeMatcher{orig, "RAWDATA"}, Lifetime::Timeframe}}, outputs, - AlgorithmSpec{adaptFromTask<STFDecoder<ChipMappingMFT>>(doClusters, doPatterns, doDigits, dict)}, + AlgorithmSpec{adaptFromTask<STFDecoder<ChipMappingMFT>>(doClusters, doPatterns, doDigits, dict, noise)}, Options{ {"nthreads", VariantType::Int, 1, {"Number of decoding/clustering threads"}}, {"old-format", VariantType::Bool, false, {"Use old format (1 trigger per CRU page)"}}, diff --git a/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx index 839faa6d8fbe8..cb9c73c25d44b 100644 --- a/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx @@ -26,6 +26,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) ConfigParamSpec{"no-cluster-patterns", VariantType::Bool, false, {"do not produce clusters patterns (def: produce)"}}, ConfigParamSpec{"digits", VariantType::Bool, false, {"produce digits (def: skip)"}}, ConfigParamSpec{"dict-file", VariantType::String, "", {"name of the cluster-topology dictionary file"}}, + ConfigParamSpec{"noise-file", VariantType::String, "", {"name of the noise map file"}}, ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; std::swap(workflowOptions, options); @@ -42,14 +43,15 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) auto doPatterns = doClusters && !cfgc.options().get<bool>("no-cluster-patterns"); auto doDigits = cfgc.options().get<bool>("digits"); auto dict = cfgc.options().get<std::string>("dict-file"); + auto noise = cfgc.options().get<std::string>("noise-file"); // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); if (cfgc.options().get<bool>("mft")) { - wf.emplace_back(o2::itsmft::getSTFDecoderMFTSpec(doClusters, doPatterns, doDigits, dict)); + wf.emplace_back(o2::itsmft::getSTFDecoderMFTSpec(doClusters, doPatterns, doDigits, dict, noise)); } else { - wf.emplace_back(o2::itsmft::getSTFDecoderITSSpec(doClusters, doPatterns, doDigits, dict)); + wf.emplace_back(o2::itsmft::getSTFDecoderITSSpec(doClusters, doPatterns, doDigits, dict, noise)); } return wf; } From 4e0df044b926f99abe2d0f5b4bce10bb94c0d861 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 27 Jul 2020 23:59:15 +0200 Subject: [PATCH 0185/1751] DPL: use different logic to allocate shm-segment-size (#4046) --- Framework/Core/src/DeviceSpecHelpers.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 9924241e7c563..3062f4467b1b6 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -794,12 +794,12 @@ void DeviceSpecHelpers::reworkShmSegmentSize(std::vector<DataProcessorInfo>& inf } info.cmdLineArgs.erase(it, it + 2); } - /// If no segment size is set, make it 90% of the VSIZE. + /// If no segment size is set, make it max VSIZE - 1GB or 90% max VSIZE. if (segmentSize == 0) { struct rlimit limits; getrlimit(RLIMIT_AS, &limits); if (limits.rlim_cur != RLIM_INFINITY) { - segmentSize = (limits.rlim_cur / 100) * 90; + segmentSize = std::min(limits.rlim_cur - 1000000000LL, (limits.rlim_cur * 90LL) / 100LL); } } if (segmentSize == 0) { From 0edd93c4bebbfc53031dc1c44911e76a573bec80 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 28 Jul 2020 10:23:12 +0200 Subject: [PATCH 0186/1751] DPL: open ipc socket in a tmp directory (#4043) This has better chances to succeed (e.g. no AFS) and will avoid polluting the pwd. --- Framework/Core/CMakeLists.txt | 7 +++++++ Framework/Core/src/ChannelSpecHelpers.cxx | 23 +++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 5433d6af42da2..11b27a2a53938 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -19,6 +19,12 @@ if (TARGET AliceO2::DebugGUI) set(DEBUGGUI_TARGET AliceO2::DebugGUI) endif() +# Given GCC 7.3 does not provide std::filesystem we use Boost instead +# Drop this once we move to GCC 8.2+ +if (NOT __APPLE__) + set(BOOST_FILESYSTEM Boost::filesystem) +endif() + o2_add_library(Framework SOURCES src/AODReaderHelpers.cxx src/ASoA.cxx @@ -129,6 +135,7 @@ o2_add_library(Framework ROOT::ROOTDataFrame O2::FrameworkLogger Boost::serialization + ${BOOST_FILESYSTEM} arrow::gandiva_shared LibUV::LibUV ) diff --git a/Framework/Core/src/ChannelSpecHelpers.cxx b/Framework/Core/src/ChannelSpecHelpers.cxx index 374260335f6a9..5500692dd83bd 100644 --- a/Framework/Core/src/ChannelSpecHelpers.cxx +++ b/Framework/Core/src/ChannelSpecHelpers.cxx @@ -12,6 +12,25 @@ #include <ostream> #include <cassert> #include <stdexcept> +#if __has_include(<filesystem>) +#include <filesystem> +namespace fs = std::filesystem; +#elif __has_include(<boost/filesystem.hpp>) +#include <boost/filesystem.hpp> +namespace fs = boost::filesystem; +#endif + +namespace +{ +std::string getTmpFolder() +{ + std::string tmppath = fs::temp_directory_path().native(); + while (tmppath.back() == '/') { + tmppath.pop_back(); + } + return tmppath; +} +} // namespace namespace o2::framework { @@ -48,7 +67,7 @@ std::string ChannelSpecHelpers::channelUrl(OutputChannelSpec const& channel) { switch (channel.protocol) { case ChannelProtocol::IPC: - return fmt::format("ipc://{}_{},transport=shmem", channel.hostname, channel.port); + return fmt::format("ipc://{}/{}_{},transport=shmem", getTmpFolder(), channel.hostname, channel.port); default: return channel.method == ChannelMethod::Bind ? fmt::format("tcp://*:{}", channel.port) : fmt::format("tcp://{}:{}", channel.hostname, channel.port); @@ -59,7 +78,7 @@ std::string ChannelSpecHelpers::channelUrl(InputChannelSpec const& channel) { switch (channel.protocol) { case ChannelProtocol::IPC: - return fmt::format("ipc://{}_{},transport=shmem", channel.hostname, channel.port); + return fmt::format("ipc://{}/{}_{},transport=shmem", getTmpFolder(), channel.hostname, channel.port); default: return channel.method == ChannelMethod::Bind ? fmt::format("tcp://*:{}", channel.port) : fmt::format("tcp://{}:{}", channel.hostname, channel.port); From 597d753c1de57b2ff2337a55e6a279317d705609 Mon Sep 17 00:00:00 2001 From: dstocco <dstocco@users.noreply.github.com> Date: Tue, 28 Jul 2020 10:30:26 +0200 Subject: [PATCH 0187/1751] Fix serach path for libUV (#3933) --- dependencies/FindLibUV.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dependencies/FindLibUV.cmake b/dependencies/FindLibUV.cmake index f284c6e563710..4f193a6f2a5da 100644 --- a/dependencies/FindLibUV.cmake +++ b/dependencies/FindLibUV.cmake @@ -50,11 +50,13 @@ They may be set by end users to point at libuv components. #----------------------------------------------------------------------------- find_library(LibUV_LIBRARY NAMES uv libuv + PATHS $ENV{LIBUV_ROOT}/lib ) mark_as_advanced(LibUV_LIBRARY) find_path(LibUV_INCLUDE_DIR NAMES uv.h + PATHS $ENV{LIBUV_ROOT}/include ) mark_as_advanced(LibUV_INCLUDE_DIR) From 6a231575ed5d0908db27e95893bbbe80c96e45ec Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 16 Jul 2020 16:22:47 +0200 Subject: [PATCH 0188/1751] DPL: make ServiceRegistry thread safe and aware the ServiceRegistry has now knowledge of the fact that the services inside have different behavior depending on their thread safety. In particular there are three kind of services: * ServiceKind::Serial unique instance, which will have to be locked. * ServiceKind::Global unique instance, renetrant and thread safe. * ServiceKind::Stream multiple instances, one per thread. For the time being this only translates in returning the same pointer for Serial / Global services. In a near future the function will return a smart pointer which will provide functionalities for locking / unlocking access to the service itself. --- Framework/Core/CMakeLists.txt | 1 + .../Core/include/Framework/CommonServices.h | 4 +- .../Core/include/Framework/ServiceHandle.h | 44 +++++ .../Core/include/Framework/ServiceRegistry.h | 152 +++++++++++++----- .../Core/include/Framework/ServiceSpec.h | 19 +-- Framework/Core/src/ServiceRegistry.cxx | 63 ++++++++ Framework/Core/src/runDataProcessing.cxx | 2 +- Framework/Core/test/test_Services.cxx | 84 ++++++++++ 8 files changed, 308 insertions(+), 61 deletions(-) create mode 100644 Framework/Core/include/Framework/ServiceHandle.h create mode 100644 Framework/Core/src/ServiceRegistry.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 11b27a2a53938..886ab90b797fd 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -98,6 +98,7 @@ o2_add_library(Framework src/RCombinedDS.cxx src/ReadoutAdapter.cxx src/ResourcesMonitoringHelper.cxx + src/ServiceRegistry.cxx src/SimpleResourceManager.cxx src/StreamOperators.cxx src/TMessageSerializer.cxx diff --git a/Framework/Core/include/Framework/CommonServices.h b/Framework/Core/include/Framework/CommonServices.h index 402de7ae1d266..6c26583efedd8 100644 --- a/Framework/Core/include/Framework/CommonServices.h +++ b/Framework/Core/include/Framework/CommonServices.h @@ -29,7 +29,7 @@ struct CommonServices { static ServiceInit simpleServiceInit() { return [](ServiceRegistry&, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { - return ServiceHandle{TypeIdHelpers::uniqueId<I>(), new T}; + return ServiceHandle{TypeIdHelpers::uniqueId<I>(), new T, ServiceKind::Serial, typeid(T).name()}; }; } @@ -38,7 +38,7 @@ struct CommonServices { static ServiceInit singletonServiceInit() { return [](ServiceRegistry&, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { - return ServiceHandle{TypeIdHelpers::uniqueId<I>(), T::instance()}; + return ServiceHandle{TypeIdHelpers::uniqueId<I>(), T::instance(), ServiceKind::Serial, typeid(T).name()}; }; } diff --git a/Framework/Core/include/Framework/ServiceHandle.h b/Framework/Core/include/Framework/ServiceHandle.h new file mode 100644 index 0000000000000..3f3759bd1e9ca --- /dev/null +++ b/Framework/Core/include/Framework/ServiceHandle.h @@ -0,0 +1,44 @@ +// 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_SERVICEHANDLE_H_ +#define O2_FRAMEWORK_SERVICEHANDLE_H_ + +#include <string> + +namespace o2::framework +{ + +/// The kind of service we are asking for +enum struct ServiceKind { + /// A Service which is not thread safe, therefore all accesses to it must be mutexed. + Serial, + /// A Service which is thread safe and therefore can be used by many threads the same time without risk + Global, + /// A Service which is specific to a given thread in a thread pool + Stream +}; + +/// Handle to the service hash must be calculated +/// using TypeIdHelper::uniqueId<BaseClass>() so that +/// we can retrieve the service by its baseclass. +struct ServiceHandle { + /// Unique hash associated to the type of service. + unsigned int hash; + /// Type erased pointer to a service + void* instance; + /// Kind of service + ServiceKind kind; + /// Mnemonic name to use for the service. + std::string name = "unknown"; +}; + +} // namespace o2::framework + +#endif // O2_FRAMEWORK_SERVICEHANDLE_H_ diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index 0700eace7f96c..fae6303f4706b 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -10,6 +10,7 @@ #ifndef O2_FRAMEWORK_SERVICEREGISTRY_H_ #define O2_FRAMEWORK_SERVICEREGISTRY_H_ +#include "Framework/ServiceHandle.h" #include "Framework/CompilerBuiltins.h" #include "Framework/TypeIdHelpers.h" @@ -21,14 +22,18 @@ #include <type_traits> #include <typeinfo> #include <stdexcept> +#include <thread> +#include <atomic> namespace o2::framework { -/// Service registry to hold generic, singleton like, interfaces and retrieve -/// them by type. -class ServiceRegistry -{ +struct ServiceMeta { + ServiceKind kind = ServiceKind::Serial; + uint64_t threadId = 0; +}; + +struct ServiceRegistryBase { /// The maximum distance a entry can be from the optimal slot. constexpr static int MAX_DISTANCE = 8; /// The number of slots in the hashmap. @@ -38,29 +43,103 @@ class ServiceRegistry public: using hash_type = decltype(TypeIdHelpers::uniqueId<void>()); + ServiceRegistryBase(); + + ServiceRegistryBase(ServiceRegistryBase const& other) + { + mServicesKey = other.mServicesKey; + mServicesValue = other.mServicesValue; + mServicesMeta = other.mServicesMeta; + for (size_t i = 0; i < other.mServicesBooked.size(); ++i) { + this->mServicesBooked[i] = other.mServicesBooked[i].load(); + } + } - ServiceRegistry() + ServiceRegistryBase& operator=(ServiceRegistryBase const& other) { - mServicesKey.fill(0L); - mServicesValue.fill(nullptr); + mServicesKey = other.mServicesKey; + mServicesValue = other.mServicesValue; + mServicesMeta = other.mServicesMeta; + for (size_t i = 0; i < other.mServicesBooked.size(); ++i) { + this->mServicesBooked[i] = other.mServicesBooked[i].load(); + } + return *this; } /// Type erased service registration. @a typeHash is the /// hash used to identify the service, @a service is /// a type erased pointer to the service itself. - void registerService(hash_type typeHash, void* service) + /// This method is supposed to be thread safe + void registerService(hash_type typeHash, void* service, ServiceKind kind, uint64_t threadId, char const* name = nullptr) const; + + // Lookup a given @a typeHash for a given @a threadId at + // a unique (per typeHash) location. There might + // be other typeHash which sit in the same place, but + // the if statement will rule them out. As long as + // only one thread writes in a given i + id location + // as guaranteed by the atomic, mServicesKey[i + id] will + // either be 0 or the final value. + // This method should NEVER register a new service, event when requested. + int getPos(uint32_t typeHash, uint64_t threadId) const { - hash_type id = typeHash & MAX_SERVICES_MASK; + auto id = typeHash & MAX_SERVICES_MASK; + auto threadHashId = (typeHash ^ threadId) & MAX_SERVICES_MASK; + std::atomic_thread_fence(std::memory_order_acquire); for (uint8_t i = 0; i < MAX_DISTANCE; ++i) { - if (mServicesValue[i + id] == nullptr) { - mServicesKey[i + id] = typeHash; - mServicesValue[i + id] = service; - return; + if (mServicesKey[i + threadHashId] == typeHash) { + return i + threadHashId; } } - O2_BUILTIN_UNREACHABLE(); + return -1; } + // Basic, untemplated API. This will require explicitly + // providing the @a typeHash for the Service type, + // there @a threadId of the thread asking the service + // and the @a kind of service. This + // method might trigger the registering of a new service + // if the service is not a stream service and the global + // zero service is available. + // Use this API only if you know what you are doing. + void* get(uint32_t typeHash, uint64_t threadId, ServiceKind kind, char const* name = nullptr) const + { + // Look for the service. If found, return it. + // Notice how due to threading issues, we might + // find it with getPos, but the value can still + // be nullptr. + auto pos = getPos(typeHash, threadId); + if (pos != -1) { + void* ptr = mServicesValue[pos]; + if (ptr) { + return ptr; + } + } + // We are looking up a service which is not of + // stream kind and was not looked up by this thread + // before. + if (threadId != 0) { + int pos = getPos(typeHash, 0); + if (pos != -1 && kind != ServiceKind::Stream) { + registerService(typeHash, mServicesValue[pos], kind, threadId, name); + } + return mServicesValue[pos]; + } + // If we are here it means we never registered a + // service for the 0 thread (i.e. the main thread). + return nullptr; + } + + mutable std::array<uint32_t, MAX_SERVICES + MAX_DISTANCE> mServicesKey; + mutable std::array<void*, MAX_SERVICES + MAX_DISTANCE> mServicesValue; + mutable std::array<ServiceMeta, MAX_SERVICES + MAX_DISTANCE> mServicesMeta; + mutable std::array<std::atomic<bool>, MAX_SERVICES + MAX_DISTANCE> mServicesBooked; +}; + +/// Service registry to hold generic, singleton like, interfaces and retrieve +/// them by type. +class ServiceRegistry : ServiceRegistryBase +{ + public: // Register a service for the given interface T // with actual implementation C, i.e. C is derived from T. // Only one instance of type C can be registered per type T. @@ -68,7 +147,7 @@ class ServiceRegistry // of the service still belongs to whatever created it, and is // not passed to the registry. It's therefore responsibility of // the creator of the service to properly dispose it. - template <class I, class C> + template <class I, class C, enum ServiceKind K = ServiceKind::Serial> void registerService(C* service) { // This only works for concrete implementations of the type T. @@ -77,10 +156,12 @@ class ServiceRegistry static_assert(std::is_base_of<I, C>::value == true, "Registered service is not derived from declared interface"); constexpr hash_type typeHash = TypeIdHelpers::uniqueId<I>(); - registerService(typeHash, reinterpret_cast<void*>(service)); + auto tid = std::this_thread::get_id(); + std::hash<std::thread::id> hasher; + ServiceRegistryBase::registerService(typeHash, reinterpret_cast<void*>(service), K, hasher(tid), typeid(C).name()); } - template <class I, class C> + template <class I, class C, enum ServiceKind K = ServiceKind::Serial> void registerService(C const* service) { // This only works for concrete implementations of the type T. @@ -90,14 +171,9 @@ class ServiceRegistry "Registered service is not derived from declared interface"); constexpr auto typeHash = TypeIdHelpers::uniqueId<I const>(); constexpr auto id = typeHash & MAX_SERVICES_MASK; - for (uint8_t i = 0; i < MAX_DISTANCE; ++i) { - if (mServicesValue[i + id] == nullptr) { - mServicesKey[i + id] = typeHash; - mServicesValue[i + id] = (void*)(service); - return; - } - } - O2_BUILTIN_UNREACHABLE(); + auto tid = std::this_thread::get_id(); + std::hash<std::thread::id> hasher; + ServiceRegistryBase::registerService(typeHash, reinterpret_cast<void*>(const_cast<C*>(service)), K, hasher(tid), typeid(C).name()); } /// Check if service of type T is currently active. @@ -105,8 +181,10 @@ class ServiceRegistry std::enable_if_t<std::is_const_v<T> == false, bool> active() const { constexpr auto typeHash = TypeIdHelpers::uniqueId<T>(); - auto ptr = get(typeHash); - return ptr != nullptr; + auto tid = std::this_thread::get_id(); + std::hash<std::thread::id> hasher; + auto result = ServiceRegistryBase::getPos(typeHash, hasher(tid)) != -1; + return result; } /// Get a service for the given interface T. The returned reference exposed to @@ -116,7 +194,9 @@ class ServiceRegistry T& get() const { constexpr auto typeHash = TypeIdHelpers::uniqueId<T>(); - auto ptr = get(typeHash); + auto tid = std::this_thread::get_id(); + std::hash<std::thread::id> hasher; + auto ptr = ServiceRegistryBase::get(typeHash, hasher(tid), ServiceKind::Serial, typeid(T).name()); if (O2_BUILTIN_LIKELY(ptr != nullptr)) { if constexpr (std::is_const_v<T>) { return *reinterpret_cast<T const*>(ptr); @@ -129,20 +209,12 @@ class ServiceRegistry ". Make sure you use const / non-const correctly."); } - void* get(uint32_t typeHash) const + void registerService(ServiceHandle& handle) { - auto id = typeHash & MAX_SERVICES_MASK; - for (uint8_t i = 0; i < MAX_DISTANCE; ++i) { - if (mServicesKey[i + id] == typeHash) { - return mServicesValue[i + id]; - } - } - return nullptr; + auto tid = std::this_thread::get_id(); + std::hash<std::thread::id> hasher; + ServiceRegistryBase::registerService(handle.hash, handle.instance, handle.kind, hasher(tid), handle.name.c_str()); } - - private: - std::array<uint32_t, MAX_SERVICES + MAX_DISTANCE> mServicesKey; - std::array<void*, MAX_SERVICES + MAX_DISTANCE> mServicesValue; }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index 2a78bab53969c..14b323c622433 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -10,6 +10,7 @@ #ifndef O2_FRAMEWORK_SERVICESPEC_H_ #define O2_FRAMEWORK_SERVICESPEC_H_ +#include "Framework/ServiceHandle.h" #include <functional> #include <string> #include <vector> @@ -32,14 +33,6 @@ struct ProcessingContext; struct EndOfStreamContext; class DanglingContext; -/// Handle to the service hash must be calculated -/// using TypeIdHelper::uniqueId<BaseClass>() so that -/// we can retrieve the service by its baseclass. -struct ServiceHandle { - uint32_t hash; - void* instance; -}; - /// A callback to create a given Service. using ServiceInit = std::function<ServiceHandle(ServiceRegistry&, DeviceState&, fair::mq::ProgOptions&)>; @@ -70,16 +63,6 @@ using ServicePostForkChild = std::function<void(ServiceRegistry&)>; /// but before doing exec / starting the device. using ServicePostForkParent = std::function<void(ServiceRegistry&)>; -/// The kind of service we are asking for -enum struct ServiceKind { - /// A Service which is not thread safe, therefore all accesses to it must be mutexed. - Serial, - /// A Service which is thread safe and therefore can be used by many threads the same time without risk - Global, - /// A Service which is specific to a given thread in a thread pool - Stream -}; - /// A specification for a Service. /// A Service is a utility class which does not perform /// data processing itself, but it can be used by the data processor diff --git a/Framework/Core/src/ServiceRegistry.cxx b/Framework/Core/src/ServiceRegistry.cxx new file mode 100644 index 0000000000000..e79e4f75d97e3 --- /dev/null +++ b/Framework/Core/src/ServiceRegistry.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/ServiceRegistry.h" +#include "Framework/Tracing.h" +#include "Framework/Logger.h" +#include <iostream> + +namespace o2::framework +{ + +ServiceRegistryBase::ServiceRegistryBase() +{ + mServicesKey.fill(0L); + mServicesValue.fill(nullptr); + for (size_t i = 0; i < mServicesBooked.size(); ++i) { + mServicesBooked[i] = false; + } +} + +/// Type erased service registration. @a typeHash is the +/// hash used to identify the service, @a service is +/// a type erased pointer to the service itself. +/// This method is supposed to be thread safe +void ServiceRegistryBase::registerService(hash_type typeHash, void* service, ServiceKind kind, uint64_t threadId, const char* name) const +{ + hash_type id = typeHash & MAX_SERVICES_MASK; + hash_type threadHashId = (typeHash ^ threadId) & MAX_SERVICES_MASK; + // If kind is not stream, there is only one copy of our service. + // So we look if it is already registered and reused it if it is. + // If not, we register it as thread id 0 and as the passed one. + if (kind != ServiceKind::Stream && threadId != 0) { + void* oldService = this->get(typeHash, 0, kind); + if (oldService == nullptr) { + registerService(typeHash, service, kind, 0); + } else { + service = oldService; + } + } + for (uint8_t i = 0; i < MAX_DISTANCE; ++i) { + // If the service slot was not taken, take it atomically + bool expected = false; + if (mServicesBooked[i + threadHashId].compare_exchange_strong(expected, true, + std::memory_order_seq_cst)) { + mServicesValue[i + threadHashId] = service; + mServicesMeta[i + threadHashId] = ServiceMeta{kind, threadId}; + mServicesKey[i + threadHashId] = typeHash; + std::atomic_thread_fence(std::memory_order_release); + return; + } + } + throw std::runtime_error(std::string("Unable to find a spot in the registry for service ") + + std::to_string(typeHash) + + ". Make sure you use const / non-const correctly."); +} + +} // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 4afad32ab9749..5c483559c226f 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -755,7 +755,7 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f for (auto& service : spec.services) { LOG(info) << "Initialising service " << service.name; auto handle = service.init(serviceRegistry, *deviceState.get(), r.fConfig); - serviceRegistry.registerService(handle.hash, handle.instance); + serviceRegistry.registerService(handle); dynamic_cast<DataProcessingDevice*>(r.fDevice.get())->bindService(service, handle.instance); } if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(spec.resourceMonitoringInterval)) { diff --git a/Framework/Core/test/test_Services.cxx b/Framework/Core/test/test_Services.cxx index 419464a4cba44..e3b003cce013f 100644 --- a/Framework/Core/test/test_Services.cxx +++ b/Framework/Core/test/test_Services.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Framework/ServiceHandle.h" #include "Framework/ServiceRegistry.h" #include "Framework/CallbackService.h" #include <boost/test/unit_test.hpp> @@ -77,3 +78,86 @@ BOOST_AUTO_TEST_CASE(TestCallbackService) registry.get<CallbackService>()(CallbackService::Id::Stop); BOOST_CHECK(cbCalled); } + +struct DummyService { + int threadId; +}; + +BOOST_AUTO_TEST_CASE(TestSerialServices) +{ + using namespace o2::framework; + ServiceRegistryBase registry; + + DummyService t0{0}; + /// We register it pretending to be on thread 0 + registry.registerService(TypeIdHelpers::uniqueId<DummyService>(), &t0, ServiceKind::Serial, 0); + + auto tt0 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 0, ServiceKind::Serial)); + auto tt1 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 1, ServiceKind::Serial)); + auto tt2 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 2, ServiceKind::Serial)); + BOOST_CHECK_EQUAL(tt0->threadId, 0); + BOOST_CHECK_EQUAL(tt1->threadId, 0); + BOOST_CHECK_EQUAL(tt2->threadId, 0); +} + +BOOST_AUTO_TEST_CASE(TestGlobalServices) +{ + using namespace o2::framework; + ServiceRegistryBase registry; + + DummyService t0{0}; + /// We register it pretending to be on thread 0 + registry.registerService(TypeIdHelpers::uniqueId<DummyService>(), &t0, ServiceKind::Global, 0); + + auto tt0 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 0, ServiceKind::Serial)); + auto tt1 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 1, ServiceKind::Serial)); + auto tt2 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 2, ServiceKind::Serial)); + BOOST_CHECK_EQUAL(tt0->threadId, 0); + BOOST_CHECK_EQUAL(tt1->threadId, 0); + BOOST_CHECK_EQUAL(tt2->threadId, 0); +} + +BOOST_AUTO_TEST_CASE(TestGlobalServices02) +{ + using namespace o2::framework; + ServiceRegistryBase registry; + + DummyService t0{1}; + /// We register it pretending to be on thread 0 + registry.registerService(TypeIdHelpers::uniqueId<DummyService>(), &t0, ServiceKind::Global, 1); + + auto tt0 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 0, ServiceKind::Global)); + auto tt1 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 1, ServiceKind::Global)); + auto tt2 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 2, ServiceKind::Global)); + BOOST_CHECK_EQUAL(tt0->threadId, 1); + BOOST_CHECK_EQUAL(tt1->threadId, 1); + BOOST_CHECK_EQUAL(tt2->threadId, 1); +} + +BOOST_AUTO_TEST_CASE(TestStreamServices) +{ + using namespace o2::framework; + ServiceRegistryBase registry; + + DummyService t0{0}; + DummyService t1{1}; + DummyService t2{2}; + /// We register it pretending to be on thread 0 + registry.registerService(TypeIdHelpers::uniqueId<DummyService>(), &t0, ServiceKind::Stream, 0); + registry.registerService(TypeIdHelpers::uniqueId<DummyService>(), &t1, ServiceKind::Stream, 1); + registry.registerService(TypeIdHelpers::uniqueId<DummyService>(), &t2, ServiceKind::Stream, 2); + + auto tt0 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 0, ServiceKind::Stream)); + auto tt1 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 1, ServiceKind::Stream)); + auto tt2 = reinterpret_cast<DummyService*>(registry.get(TypeIdHelpers::uniqueId<DummyService>(), 2, ServiceKind::Stream)); + BOOST_CHECK_EQUAL(tt0->threadId, 0); + BOOST_CHECK_EQUAL(tt1->threadId, 1); + BOOST_CHECK_EQUAL(tt2->threadId, 2); +} + +BOOST_AUTO_TEST_CASE(TestServiceRegistryCtor) +{ + using namespace o2::framework; + ServiceRegistry registry; + registry = ServiceRegistry(); +} From af4d84fba3cf7f9a728395dcbcac5a2fdc22f719 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 24 Jul 2020 01:06:22 +0200 Subject: [PATCH 0189/1751] DPL: make sure ServiceRegistry::registerService is type erased --- .../Core/include/Framework/ServiceRegistry.h | 13 ++-- .../Framework/ServiceRegistryHelpers.h | 67 +++++++++++++++++++ Framework/Core/src/runDataProcessing.cxx | 4 +- Framework/Core/test/test_Services.cxx | 8 +-- 4 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 Framework/Core/include/Framework/ServiceRegistryHelpers.h diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index fae6303f4706b..2198ecf7a6417 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -11,6 +11,7 @@ #define O2_FRAMEWORK_SERVICEREGISTRY_H_ #include "Framework/ServiceHandle.h" +#include "Framework/ServiceRegistryHelpers.h" #include "Framework/CompilerBuiltins.h" #include "Framework/TypeIdHelpers.h" @@ -140,13 +141,7 @@ struct ServiceRegistryBase { class ServiceRegistry : ServiceRegistryBase { public: - // Register a service for the given interface T - // with actual implementation C, i.e. C is derived from T. - // Only one instance of type C can be registered per type T. - // The fact we use a bare pointer indicates that the ownership - // of the service still belongs to whatever created it, and is - // not passed to the registry. It's therefore responsibility of - // the creator of the service to properly dispose it. + /// @deprecated old API to be substituted with the ServiceHandle one template <class I, class C, enum ServiceKind K = ServiceKind::Serial> void registerService(C* service) { @@ -161,6 +156,7 @@ class ServiceRegistry : ServiceRegistryBase ServiceRegistryBase::registerService(typeHash, reinterpret_cast<void*>(service), K, hasher(tid), typeid(C).name()); } + /// @deprecated old API to be substituted with the ServiceHandle one template <class I, class C, enum ServiceKind K = ServiceKind::Serial> void registerService(C const* service) { @@ -209,7 +205,8 @@ class ServiceRegistry : ServiceRegistryBase ". Make sure you use const / non-const correctly."); } - void registerService(ServiceHandle& handle) + /// Register a service given an handle + void registerService(ServiceHandle handle) { auto tid = std::this_thread::get_id(); std::hash<std::thread::id> hasher; diff --git a/Framework/Core/include/Framework/ServiceRegistryHelpers.h b/Framework/Core/include/Framework/ServiceRegistryHelpers.h new file mode 100644 index 0000000000000..86781a79c5ece --- /dev/null +++ b/Framework/Core/include/Framework/ServiceRegistryHelpers.h @@ -0,0 +1,67 @@ +// 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_SERVICEREGISTRYHELPERS_H_ +#define O2_FRAMEWORK_SERVICEREGISTRYHELPERS_H_ + +#include "Framework/ServiceHandle.h" +#include "Framework/TypeIdHelpers.h" + +#include <algorithm> +#include <array> +#include <exception> +#include <functional> +#include <string> +#include <type_traits> +#include <typeinfo> +#include <stdexcept> +#include <thread> + +namespace o2::framework +{ + +/// Helpers for ServiceRegistry manipulations +struct ServiceRegistryHelpers { + public: + // Create an handle for a service for the given interface T + // with actual implementation C, i.e. C is derived from T. + // Only one instance of type C can be registered per type T. + // The fact we use a bare pointer indicates that the ownership + // of the service still belongs to whatever created it, and is + // not passed to the registry. It's therefore responsibility of + // the creator of the service to properly dispose it. + template <class I, class C, enum ServiceKind K = ServiceKind::Serial> + static auto handleForService(C* service) -> ServiceHandle + { + // This only works for concrete implementations of the type T. + // We need type elision as we do not want to know all the services in + // advance + static_assert(std::is_base_of<I, C>::value == true, + "Registered service is not derived from declared interface"); + constexpr auto typeHash = TypeIdHelpers::uniqueId<I>(); + return ServiceHandle{typeHash, reinterpret_cast<void*>(service), K, typeid(C).name()}; + } + + /// Same as above, but for const instances + template <class I, class C, enum ServiceKind K = ServiceKind::Serial> + static auto handleForService(C const* service) -> ServiceHandle + { + // This only works for concrete implementations of the type T. + // We need type elision as we do not want to know all the services in + // advance + static_assert(std::is_base_of<I, C>::value == true, + "Registered service is not derived from declared interface"); + constexpr auto typeHash = TypeIdHelpers::uniqueId<I const>(); + return ServiceHandle{typeHash, reinterpret_cast<void*>(const_cast<C*>(service)), K, typeid(C).name()}; + } +}; + +} // namespace o2::framework + +#endif // O2_FRAMEWORK_SERVICEREGISTRYHELPERS_H_ diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 5c483559c226f..e53505ba3a96f 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -738,8 +738,8 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f simpleRawDeviceService = std::make_unique<SimpleRawDeviceService>(nullptr, spec); - serviceRegistry.registerService<RawDeviceService>(simpleRawDeviceService.get()); - serviceRegistry.registerService<DeviceSpec>(&spec); + serviceRegistry.registerService(ServiceRegistryHelpers::handleForService<RawDeviceService>(simpleRawDeviceService.get())); + serviceRegistry.registerService(ServiceRegistryHelpers::handleForService<DeviceSpec>(&spec)); // The decltype stuff is to be able to compile with both new and old // FairMQ API (one which uses a shared_ptr, the other one a unique_ptr. diff --git a/Framework/Core/test/test_Services.cxx b/Framework/Core/test/test_Services.cxx index e3b003cce013f..498a58f5227d6 100644 --- a/Framework/Core/test/test_Services.cxx +++ b/Framework/Core/test/test_Services.cxx @@ -49,9 +49,9 @@ BOOST_AUTO_TEST_CASE(TestServiceRegistry) ConcreteA serviceA; ConcreteB serviceB; ConcreteC const serviceC; - registry.registerService<InterfaceA>(&serviceA); - registry.registerService<InterfaceB>(&serviceB); - registry.registerService<InterfaceC>(&serviceC); + registry.registerService(ServiceRegistryHelpers::handleForService<InterfaceA>(&serviceA)); + registry.registerService(ServiceRegistryHelpers::handleForService<InterfaceB>(&serviceB)); + registry.registerService(ServiceRegistryHelpers::handleForService<InterfaceC>(&serviceC)); BOOST_CHECK(registry.get<InterfaceA>().method() == true); BOOST_CHECK(registry.get<InterfaceB>().method() == false); BOOST_CHECK(registry.get<InterfaceC const>().method() == false); @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(TestCallbackService) using namespace o2::framework; ServiceRegistry registry; auto service = std::make_unique<CallbackService>(); - registry.registerService<CallbackService>(service.get()); + registry.registerService(ServiceRegistryHelpers::handleForService<CallbackService>(service.get())); // the callback simply sets the captured variable to indicated that it was called bool cbCalled = false; From 091e30251b3b431cf338d6e7e057ffbb2f77bc7b Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan <shahor02@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:45:02 +0200 Subject: [PATCH 0190/1751] add to RawPixelDecoder a public getter for links, their number (#4048) Co-authored-by: shahoian <ruben.shahoyan@cern.ch> --- .../include/ITSMFTReconstruction/RawPixelDecoder.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 457a5839ddcc6..537f1337fee98 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -64,6 +64,8 @@ class RawPixelDecoder : public PixelReader int fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs); const RUDecodeData* getRUDecode(int ruSW) const { return mRUEntry[ruSW] < 0 ? nullptr : &mRUDecodeVec[mRUEntry[ruSW]]; } + const GBTLink* getGBTLink(int i) const { return i < 0 ? nullptr : &mGBTLinks[i]; } + int getNLinks() const { return mGBTLinks.size(); } auto getUserDataOrigin() const { return mUserDataOrigin; } void setUserDataOrigin(header::DataOrigin orig) { mUserDataOrigin = orig; } @@ -93,7 +95,6 @@ class RawPixelDecoder : public PixelReader int getRUEntrySW(int ruSW) const { return mRUEntry[ruSW]; } RUDecodeData* getRUDecode(int ruSW) { return &mRUDecodeVec[mRUEntry[ruSW]]; } GBTLink* getGBTLink(int i) { return i < 0 ? nullptr : &mGBTLinks[i]; } - const GBTLink* getGBTLink(int i) const { return i < 0 ? nullptr : &mGBTLinks[i]; } RUDecodeData& getCreateRUDecode(int ruSW); static constexpr uint16_t NORUDECODED = 0xffff; // this must be > than max N RUs From 1961fcf899271492c5bd6c5e3f8d26e8b2246f31 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 29 Jul 2020 09:50:21 +0200 Subject: [PATCH 0191/1751] DPL Analysis: allow grouping on filtered iterator --- Analysis/Tutorials/src/filters.cxx | 6 +++-- Framework/Core/include/Framework/ASoA.h | 5 ++++ .../Core/include/Framework/AnalysisTask.h | 24 ++++++++++++------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Analysis/Tutorials/src/filters.cxx b/Analysis/Tutorials/src/filters.cxx index e9f19d4c44396..ddb31fbb9bf33 100644 --- a/Analysis/Tutorials/src/filters.cxx +++ b/Analysis/Tutorials/src/filters.cxx @@ -65,9 +65,11 @@ struct BTask { float phiup = 2.0f; Filter phifilter = (aod::etaphi::nphi < phiup) && (aod::etaphi::nphi > philow); - void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TPhi>> const& tracks) + Filter posZfilter = nabs(aod::collision::posZ) < 10.0f; + + void process(soa::Filtered<aod::Collisions>::iterator const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TPhi>> const& tracks) { - LOGF(INFO, "Collision: %d [N = %d]", collision.globalIndex(), tracks.size()); + LOGF(INFO, "Collision: %d [N = %d], -10 < %.3f < 10", collision.globalIndex(), tracks.size(), collision.posZ()); for (auto& track : tracks) { LOGF(INFO, "id = %d; eta: %.3f < %.3f < %.3f; phi: %.3f < %.3f < %.3f; pt: %.3f < %.3f < %.3f", track.collisionId(), etalow, track.eta(), etaup, philow, track.nphi(), phiup, ptlow, track.pt(), ptup); } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index cdf271a5f42b4..9c975eb391988 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -925,6 +925,11 @@ class Table return mTable->num_rows(); } + int64_t tableSize() const + { + return size(); + } + /// Bind the columns which refer to other tables /// to the associated tables. template <typename... TA> diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 8b0d360c8db2e..a3c224b42d27b 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -608,6 +608,9 @@ struct AnalysisDataProcessorBuilder { mGroupingElement{gt.begin()}, position{0} { + if constexpr (soa::is_soa_filtered_t<std::decay_t<G>>::value) { + groupSelection = >.getSelectedRows(); + } auto indexColumnName = getLabelFromType(); arrow::compute::FunctionContext ctx; /// prepare slices and offsets for all associated tables that have index @@ -625,7 +628,7 @@ struct AnalysisDataProcessorBuilder { if (result.ok() == false) { throw std::runtime_error("Cannot split collection"); } - if (groups[index].size() != gt.size()) { + if (groups[index].size() != gt.tableSize()) { throw std::runtime_error("Splitting collection resulted in different group number than there is rows in the grouping table."); }; } @@ -711,24 +714,28 @@ struct AnalysisDataProcessorBuilder { { constexpr auto index = framework::has_type_at<A1>(associated_pack_t{}); if (hasIndexTo<G>(typename std::decay_t<A1>::persistent_columns_t{})) { + auto pos = position; + if constexpr (soa::is_soa_filtered_t<std::decay_t<G>>::value) { + pos = groupSelection[position]; + } if constexpr (soa::is_soa_filtered_t<std::decay_t<A1>>::value) { - auto groupedElementsTable = arrow::util::get<std::shared_ptr<arrow::Table>>(((groups[index])[position]).value); + auto groupedElementsTable = arrow::util::get<std::shared_ptr<arrow::Table>>(((groups[index])[pos]).value); // for each grouping element we need to slice the selection vector - auto start_iterator = std::lower_bound(starts[index], selections[index]->end(), (offsets[index])[position]); - auto stop_iterator = std::lower_bound(start_iterator, selections[index]->end(), (offsets[index])[position + 1]); + auto start_iterator = std::lower_bound(starts[index], selections[index]->end(), (offsets[index])[pos]); + auto stop_iterator = std::lower_bound(start_iterator, selections[index]->end(), (offsets[index])[pos + 1]); starts[index] = stop_iterator; soa::SelectionVector slicedSelection{start_iterator, stop_iterator}; std::transform(slicedSelection.begin(), slicedSelection.end(), slicedSelection.begin(), [&](int64_t idx) { - return idx - static_cast<int64_t>((offsets[index])[position]); + return idx - static_cast<int64_t>((offsets[index])[pos]); }); - std::decay_t<A1> typedTable{{groupedElementsTable}, std::move(slicedSelection), (offsets[index])[position]}; + std::decay_t<A1> typedTable{{groupedElementsTable}, std::move(slicedSelection), (offsets[index])[pos]}; return typedTable; } else { - auto groupedElementsTable = arrow::util::get<std::shared_ptr<arrow::Table>>(((groups[index])[position]).value); - std::decay_t<A1> typedTable{{groupedElementsTable}, (offsets[index])[position]}; + auto groupedElementsTable = arrow::util::get<std::shared_ptr<arrow::Table>>(((groups[index])[pos]).value); + std::decay_t<A1> typedTable{{groupedElementsTable}, (offsets[index])[pos]}; return typedTable; } } else { @@ -740,6 +747,7 @@ struct AnalysisDataProcessorBuilder { std::tuple<A...>* mAt; typename grouping_t::iterator mGroupingElement; uint64_t position = 0; + soa::SelectionVector* groupSelection = nullptr; std::array<std::vector<arrow::compute::Datum>, sizeof...(A)> groups; std::array<std::vector<uint64_t>, sizeof...(A)> offsets; From 9bcc364f2a433a7246b2d0808454564aea292921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Wed, 29 Jul 2020 14:49:58 +0200 Subject: [PATCH 0192/1751] Add a proto PID response for TPC signals (#4036) --- Analysis/DataModel/CMakeLists.txt | 3 +- Analysis/DataModel/include/PID/PIDResponse.h | 68 +++++++++++- Analysis/DataModel/include/PID/PIDTPC.h | 105 ++++++++++++++++++ Analysis/DataModel/include/PID/ParamBase.h | 71 ++++++++++++ Analysis/DataModel/src/PIDTPC.cxx | 39 +++++++ Analysis/Tasks/CMakeLists.txt | 5 + Analysis/Tasks/spectraTPC.cxx | 78 +++++++++++++ .../include/TPCSimulation/Detector.h | 2 +- 8 files changed, 367 insertions(+), 4 deletions(-) create mode 100644 Analysis/DataModel/include/PID/PIDTPC.h create mode 100644 Analysis/DataModel/include/PID/ParamBase.h create mode 100644 Analysis/DataModel/src/PIDTPC.cxx create mode 100644 Analysis/Tasks/spectraTPC.cxx diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index fa2097783e236..9a37c144b8b91 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -11,8 +11,9 @@ o2_add_library(AnalysisDataModel SOURCES src/dummy.cxx src/PIDTOF.cxx + src/PIDTPC.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src - PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats + PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats O2::TPCSimulation ) o2_add_executable(dump-aod-data-model diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/PID/PIDResponse.h index c207a5cc1eeeb..dfaf5a02962f3 100644 --- a/Analysis/DataModel/include/PID/PIDResponse.h +++ b/Analysis/DataModel/include/PID/PIDResponse.h @@ -23,8 +23,9 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "ReconstructionDataFormats/Track.h" -#include "PID/PIDTOF.h" #include "ReconstructionDataFormats/PID.h" +#include "PID/PIDTOF.h" +#include "PID/PIDTPC.h" namespace o2::aod { @@ -87,6 +88,34 @@ DECLARE_SOA_TABLE(pidRespTOF, "AOD", "pidRespTOF", ExpSigmaEl, ExpSigmaMu, ExpSigmaPi, ExpSigmaKa, ExpSigmaPr, ExpSigmaDe, ExpSigmaTr, ExpSigmaHe, ExpSigmaAl, NSigmaEl, NSigmaMu, NSigmaPi, NSigmaKa, NSigmaPr, NSigmaDe, NSigmaTr, NSigmaHe, NSigmaAl); +namespace pidTPC +{ +// Expected signals +DECLARE_SOA_COLUMN(ExpSignalEl, expSignalEl, float); +DECLARE_SOA_COLUMN(ExpSignalMu, expSignalMu, float); +DECLARE_SOA_COLUMN(ExpSignalPi, expSignalPi, float); +DECLARE_SOA_COLUMN(ExpSignalKa, expSignalKa, float); +DECLARE_SOA_COLUMN(ExpSignalPr, expSignalPr, float); +DECLARE_SOA_COLUMN(ExpSignalDe, expSignalDe, float); +DECLARE_SOA_COLUMN(ExpSignalTr, expSignalTr, float); +DECLARE_SOA_COLUMN(ExpSignalHe, expSignalHe, float); +DECLARE_SOA_COLUMN(ExpSignalAl, expSignalAl, float); +// NSigma +DECLARE_SOA_COLUMN(NSigmaEl, nSigmaEl, float); +DECLARE_SOA_COLUMN(NSigmaMu, nSigmaMu, float); +DECLARE_SOA_COLUMN(NSigmaPi, nSigmaPi, float); +DECLARE_SOA_COLUMN(NSigmaKa, nSigmaKa, float); +DECLARE_SOA_COLUMN(NSigmaPr, nSigmaPr, float); +DECLARE_SOA_COLUMN(NSigmaDe, nSigmaDe, float); +DECLARE_SOA_COLUMN(NSigmaTr, nSigmaTr, float); +DECLARE_SOA_COLUMN(NSigmaHe, nSigmaHe, float); +DECLARE_SOA_COLUMN(NSigmaAl, nSigmaAl, float); +} // namespace pidTPC + +DECLARE_SOA_TABLE(pidRespTPC, "AOD", "pidRespTPC", + pidTPC::ExpSignalEl, pidTPC::ExpSignalMu, pidTPC::ExpSignalPi, pidTPC::ExpSignalKa, pidTPC::ExpSignalPr, pidTPC::ExpSignalDe, pidTPC::ExpSignalTr, pidTPC::ExpSignalHe, pidTPC::ExpSignalAl, + pidTPC::NSigmaEl, pidTPC::NSigmaMu, pidTPC::NSigmaPi, pidTPC::NSigmaKa, pidTPC::NSigmaPr, pidTPC::NSigmaDe, pidTPC::NSigmaTr, pidTPC::NSigmaHe, pidTPC::NSigmaAl); + } // namespace o2::aod using namespace o2; @@ -108,7 +137,7 @@ struct pidTOFTask { evt.SetEvTimeMask(0, collision.collisionTimeMask()); tof::Response resp = tof::Response(); resp.SetEventTime(evt); - for (auto i : tracks) { + for (auto const& i : tracks) { resp.UpdateTrack(i.p(), i.tofExpMom() / tof::Response::kCSPEED, i.length(), i.tofSignal()); tofpidbeta(resp.GetBeta(), resp.GetBetaExpectedSigma(), @@ -147,4 +176,39 @@ struct pidTOFTask { } }; +struct pidTPCTask { + Produces<aod::pidRespTPC> tpcpid; + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) + { + tpc::Response resp = tpc::Response(); + float bbparams[5] = {0.0320981, 19.9768, 2.52666e-16, 2.72123, 6.08092}; + resp.mParam.mBetheBloch.mParameters.Set(bbparams); + float resoparams[2] = {0.07, 0.0}; + resp.mParam.mRelResolution.mParameters.Set(resoparams); + for (auto const& i : tracks) { + resp.UpdateTrack(i.p(), i.tpcSignal(), i.tpcNClsShared()); + tpcpid( + resp.GetExpectedSignal(PID::Electron), + resp.GetExpectedSignal(PID::Muon), + resp.GetExpectedSignal(PID::Pion), + resp.GetExpectedSignal(PID::Kaon), + resp.GetExpectedSignal(PID::Proton), + resp.GetExpectedSignal(PID::Deuteron), + resp.GetExpectedSignal(PID::Triton), + resp.GetExpectedSignal(PID::Helium3), + resp.GetExpectedSignal(PID::Alpha), + resp.GetNumberOfSigmas(PID::Electron), + resp.GetNumberOfSigmas(PID::Muon), + resp.GetNumberOfSigmas(PID::Pion), + resp.GetNumberOfSigmas(PID::Kaon), + resp.GetNumberOfSigmas(PID::Proton), + resp.GetNumberOfSigmas(PID::Deuteron), + resp.GetNumberOfSigmas(PID::Triton), + resp.GetNumberOfSigmas(PID::Helium3), + resp.GetNumberOfSigmas(PID::Alpha)); + } + } +}; + #endif // O2_FRAMEWORK_PIDRESPONSE_H_ diff --git a/Analysis/DataModel/include/PID/PIDTPC.h b/Analysis/DataModel/include/PID/PIDTPC.h new file mode 100644 index 0000000000000..87cde9af0aa19 --- /dev/null +++ b/Analysis/DataModel/include/PID/PIDTPC.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 PIDTPC.h +/// \author Nicolo' Jacazio +/// \since 2020-07-24 +/// \brief Handler for the TPC PID response +/// + +#ifndef O2_FRAMEWORK_PIDTPC_H_ +#define O2_FRAMEWORK_PIDTPC_H_ + +// ROOT includes +#include "Rtypes.h" +#include "TMath.h" + +// O2 includes +#include "Framework/Logger.h" +#include "ReconstructionDataFormats/PID.h" +#include "PID/ParamBase.h" + +namespace o2::pid::tpc +{ + +float BetheBlochF(float x, const std::array<float, 5> p); +float RelResolutionF(float x, const std::array<float, 2> p); + +/// \brief Class to handle the parametrization of the detector response +class Param +{ + public: + Param() = default; + ~Param() = default; + + /// Getter for the expected signal + /// Calculates the expected PID signal as the function of + /// the information stored in the track and the given parameters, + /// for the specified particle type + float GetExpectedSignal(float mom, float mass, float charge) const; + + /// Getter for the charge factor BB goes with z^2, however in reality it is slightly larger (calibration, threshold effects, ...) + float GetChargeFactor(float charge) const { return TMath::Power(charge, 2.3); } + + /// Getter for the expected resolution. + /// Returns the expected sigma of the PID signal. + /// If the operation is not possible, return a negative value. + float GetExpectedSigma(float npoints, float tpcsignal) const; + + /// Bethe-Bloch function normalised to 1 at the minimum + Parametrization<float, 5, BetheBlochF> mBetheBloch = Parametrization<float, 5, BetheBlochF>(); + + /// Parametrization of the resolution + Parametrization<float, 2, RelResolutionF> mRelResolution = Parametrization<float, 2, RelResolutionF>(); + + float mMIP = 50.f; // dEdx for MIP + private: +}; + +/// \brief Class to handle the the TPC detector response +class Response +{ + public: + Response() = default; + ~Response() = default; + + /// Updater for the TPC response to setup the track parameters + /// i.e. sets the track of interest + void UpdateTrack(float mom, float tpcsignal, float tpcpoints) + { + mMomentum = mom; + mTPCSignal = tpcsignal; + mTPCPoints = tpcpoints; + }; + + // Expected resolution + /// Gets the expected resolution of the measurement + float GetExpectedSigma(o2::track::PID::ID id) const { return mParam.GetExpectedSigma(mTPCSignal, mTPCPoints); } + + // Expected signal + /// Gets the expected signal of the measurement + float GetExpectedSignal(o2::track::PID::ID id) const { return mParam.GetExpectedSignal(mMomentum, o2::track::PID::getMass(id), o2::track::PID::getCharge(id)); } + + // Nsigma + float GetNumberOfSigmas(o2::track::PID::ID id) const { return (mTPCSignal - GetExpectedSignal(id)) / GetExpectedSigma(id); } + + Param mParam; /// Parametrization of the TPC signal + private: + // Event of interest information + // Track of interest information + float mMomentum; /// Momentum + float mTPCSignal; /// TPC signal + float mTPCPoints; /// Number of TPC points for TPC signal +}; + +} // namespace o2::pid::tpc + +#endif // O2_FRAMEWORK_PIDTPC_H_ diff --git a/Analysis/DataModel/include/PID/ParamBase.h b/Analysis/DataModel/include/PID/ParamBase.h new file mode 100644 index 0000000000000..52275a3b85d7a --- /dev/null +++ b/Analysis/DataModel/include/PID/ParamBase.h @@ -0,0 +1,71 @@ +// 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 ParamBase.h +/// \author Nicolo' Jacazio +/// +/// Set of utilities to handle the parametrization of the PID response for each detector +/// These are the basic storage elements to be kept in the CCDB +/// + +#ifndef O2_FRAMEWORK_PARAMBASE_H_ +#define O2_FRAMEWORK_PARAMBASE_H_ + +// ROOT includes +#include "Rtypes.h" + +namespace o2::pid +{ + +/// \brief Class to handle the parameters of a given detector response +template <typename T, unsigned int size> +class Parameters +{ + public: + Parameters() = default; + ~Parameters() = default; + + /// Setter for parametrization parameters + void Set(unsigned int param_index, T value) { param_index < size ? mPar[param_index] = value : 0.f; } + /// Setter for parametrization parameters + void Set(T const value[size]) + { + for (unsigned int i = 0; i < size; i++) + Set(i, value[i]); + } + /// Getter for parametrization parameters + T Get(unsigned int param_index) const { return param_index < size ? mPar[param_index] : -999.f; } + /// Getter for parametrization parameters + std::array<T, size> Get() const { return mPar; } + + private: + /// parameters + std::array<T, size> mPar; +}; + +/// \brief Class to handle the parameters and the parametrization of a given detector response +template <typename T, unsigned int size, T (*functional_form)(T, const std::array<T, size>)> +class Parametrization +{ + public: + Parametrization() = default; + ~Parametrization() = default; + + /// Getter for parametrization values + T GetValue(T x) const { return functional_form(x, mParameters.Get()); } + + /// Parameters of the parametrization + Parameters<T, size> mParameters = Parameters<T, size>(); +}; + +} // namespace o2::pid + +#endif // O2_FRAMEWORK_PARAMBASE_H_ diff --git a/Analysis/DataModel/src/PIDTPC.cxx b/Analysis/DataModel/src/PIDTPC.cxx new file mode 100644 index 0000000000000..31b8bd3ed5b5a --- /dev/null +++ b/Analysis/DataModel/src/PIDTPC.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. + +#include "PID/PIDTPC.h" +#include "TPCSimulation/Detector.h" + +namespace o2::pid::tpc +{ + +float BetheBlochF(float betagamma, const std::array<float, 5> p) +{ + // Parameters of the ALEPH Bethe-Bloch formula + return o2::tpc::Detector::BetheBlochAleph(betagamma, p[0], p[1], p[2], p[3], p[4]); +} + +float RelResolutionF(float npoints, const std::array<float, 2> p) +{ + // relative dEdx resolution rel sigma = fRes0*sqrt(1+fResN2/npoint) + return p[0] * (npoints > 0 ? sqrt(1. + p[1] / npoints) : 1.f); +} + +float Param::GetExpectedSignal(float mom, float mass, float charge) const +{ + return mBetheBloch.GetValue(mom / mass) * mMIP * GetChargeFactor(charge); +} + +float Param::GetExpectedSigma(float npoints, float tpcsignal) const +{ + return tpcsignal * mRelResolution.GetValue(npoints); +} + +} // namespace o2::pid::tpc diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index bd707ba595a6b..4b7a54b554d4c 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -53,6 +53,11 @@ o2_add_dpl_workflow(spectra-tof PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) +o2_add_dpl_workflow(spectra-tpc + SOURCES spectraTPC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(validation SOURCES validation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase diff --git a/Analysis/Tasks/spectraTPC.cxx b/Analysis/Tasks/spectraTPC.cxx new file mode 100644 index 0000000000000..67412053a98bb --- /dev/null +++ b/Analysis/Tasks/spectraTPC.cxx @@ -0,0 +1,78 @@ +// 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 includes +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" + +// ROOT includes +#include <TH1F.h> + +#define DOTH1F(OBJ, ...) \ + OutputObj<TH1F> OBJ{TH1F(#OBJ, __VA_ARGS__)}; +#define DOTH2F(OBJ, ...) \ + OutputObj<TH2F> OBJ{TH2F(#OBJ, __VA_ARGS__)}; + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct TPCPIDQATask { + // TPC NSigma + DOTH2F(htpcsignal, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", 100, 0, 5, 100, 0, 1000); + DOTH2F(hexpEl, ";#it{p} (GeV/#it{c});TPC exoected signal e;Tracks", 100, 0, 5, 100, 0, 1000); + DOTH2F(hexpDe, ";#it{p} (GeV/#it{c});TPC exoected signal d;Tracks", 100, 0, 5, 100, 0, 1000); + DOTH2F(hnsigmaEl, ";#it{p} (GeV/#it{c});TPC N_{sigma e};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaMu, ";#it{p} (GeV/#it{c});TPC N_{sigma #mu};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaPi, ";#it{p} (GeV/#it{c});TPC N_{sigma #pi};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaKa, ";#it{p} (GeV/#it{c});TPC N_{sigma K};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaPr, ";#it{p} (GeV/#it{c});TPC N_{sigma p};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaDe, ";#it{p} (GeV/#it{c});TPC N_{sigma d};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaTr, ";#it{p} (GeV/#it{c});TPC N_{sigma t};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaHe, ";#it{p} (GeV/#it{c});TPC N_{sigma ^{3}He};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaAl, ";#it{p} (GeV/#it{c});TPC N_{sigma #alpha};Tracks", 100, 0, 5, 100, -10, 10); + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) + { + for (auto const& i : tracks) { + // Track selection + const UChar_t clustermap = i.itsClusterMap(); + bool issel = (i.tpcNClsFindable() > 70); + issel = issel && (i.flags() & 0x4); + issel = issel && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); + if (!issel) + continue; + // + htpcsignal->Fill(i.p(), i.tpcSignal()); + hexpEl->Fill(i.p(), i.expSignalEl()); + hexpDe->Fill(i.p(), i.expSignalDe()); + hnsigmaEl->Fill(i.p(), i.nSigmaEl()); + hnsigmaMu->Fill(i.p(), i.nSigmaMu()); + hnsigmaPi->Fill(i.p(), i.nSigmaPi()); + hnsigmaKa->Fill(i.p(), i.nSigmaKa()); + hnsigmaPr->Fill(i.p(), i.nSigmaPr()); + hnsigmaDe->Fill(i.p(), i.nSigmaDe()); + hnsigmaTr->Fill(i.p(), i.nSigmaTr()); + hnsigmaHe->Fill(i.p(), i.nSigmaHe()); + hnsigmaAl->Fill(i.p(), i.nSigmaAl()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<pidTPCTask>("pidTPC-task"), + adaptAnalysisTask<TPCPIDQATask>("TPCpidqa-task")}; +} diff --git a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h index a18880c9a5ff0..ca94e58779bde 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h @@ -114,7 +114,7 @@ class Detector : public o2::base::DetImpl<Detector> /// @param kp* Parameters for the ALICE TPC /// @return Bethe-Bloch value in MIP units template <typename T> - T BetheBlochAleph(T bg, T kp1, T kp2, T kp3, T kp4, T kp5); + static T BetheBlochAleph(T bg, T kp1, T kp2, T kp3, T kp4, T kp5); /// Copied from AliRoot - should go to someplace else /// Function to generate random numbers according to Gamma function From d398e1360cfe78676597cf34aa1ee3be1b93dacb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 29 Jul 2020 15:20:39 +0200 Subject: [PATCH 0193/1751] EncodedBlocks::getData returns 0 if registry and payload are not set --- .../Common/include/DetectorsCommonDataFormats/EncodedBlocks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 3474a5954adf6..692e092359bfb 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -128,7 +128,7 @@ struct Block { int nStored = 0; // total payload: data + dictionary length W* payload = nullptr; //[nStored]; - W* getData() { return payload ? (payload + nDict) : (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())); } + W* getData() { return payload ? (payload + nDict) : (registry ? (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())) : nullptr); } W* getDict() { return nDict ? payload : nullptr; } const W* getData() const { return payload ? (payload + nDict) : nullptr; } const W* getDict() const { return nDict ? payload : nullptr; } From b10b0520eb38f78634b4975852d8f32e6fceaa18 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 23:29:23 +0200 Subject: [PATCH 0194/1751] Add missing includes for Root 6.22 (#4055) --- .../TPC/calibration/SpacePoints/src/TrackInterpolation.cxx | 1 + EventVisualisation/Detectors/src/DataReaderVSD.cxx | 1 + Framework/Core/test/test_SimpleWildcard.cxx | 1 + Framework/Core/test/test_SimpleWildcard02.cxx | 1 + Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx | 1 + Framework/TestWorkflows/src/test_o2RootMessageWorkflow.cxx | 2 +- Steer/include/Steer/O2RunSim.h | 1 + Utilities/Mergers/test/test_Algorithm.cxx | 1 + 8 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index 3f95bafcb01bd..1956fdbfdc446 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -19,6 +19,7 @@ #include "DataFormatsTPC/TrackTPC.h" #include <fairlogger/Logger.h> +#include <set> using namespace o2::tpc; diff --git a/EventVisualisation/Detectors/src/DataReaderVSD.cxx b/EventVisualisation/Detectors/src/DataReaderVSD.cxx index 74e2f507991ea..ae940a02445b0 100644 --- a/EventVisualisation/Detectors/src/DataReaderVSD.cxx +++ b/EventVisualisation/Detectors/src/DataReaderVSD.cxx @@ -20,6 +20,7 @@ #include <TPRegexp.h> #include <TEveTrackPropagator.h> #include <TEveEventManager.h> +#include <TKey.h> namespace o2 { diff --git a/Framework/Core/test/test_SimpleWildcard.cxx b/Framework/Core/test/test_SimpleWildcard.cxx index c5647b35454a4..a5101e8f87478 100644 --- a/Framework/Core/test/test_SimpleWildcard.cxx +++ b/Framework/Core/test/test_SimpleWildcard.cxx @@ -17,6 +17,7 @@ #include <algorithm> #include <memory> #include <unordered_map> +#include <TObjString.h> using namespace o2::framework; diff --git a/Framework/Core/test/test_SimpleWildcard02.cxx b/Framework/Core/test/test_SimpleWildcard02.cxx index 17d890a78df45..bd4acbc48b08f 100644 --- a/Framework/Core/test/test_SimpleWildcard02.cxx +++ b/Framework/Core/test/test_SimpleWildcard02.cxx @@ -17,6 +17,7 @@ #include <algorithm> #include <memory> #include <unordered_map> +#include <TObjString.h> using namespace o2::framework; diff --git a/Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx b/Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx index 7c7e6656a242d..17b49d7c084b7 100644 --- a/Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx +++ b/Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx @@ -29,6 +29,7 @@ void customize(std::vector<ChannelConfigurationPolicy>& policies) #include "Framework/DataSamplingHeader.h" #include "Framework/Logger.h" #include <TClonesArray.h> +#include <TObjString.h> #include <TH1F.h> #include <TString.h> diff --git a/Framework/TestWorkflows/src/test_o2RootMessageWorkflow.cxx b/Framework/TestWorkflows/src/test_o2RootMessageWorkflow.cxx index 538fc3c39066e..3068e320196ca 100644 --- a/Framework/TestWorkflows/src/test_o2RootMessageWorkflow.cxx +++ b/Framework/TestWorkflows/src/test_o2RootMessageWorkflow.cxx @@ -20,7 +20,7 @@ #include <TClonesArray.h> #include <TH1F.h> #include <TString.h> - +#include <TObjString.h> #include <chrono> using namespace o2::framework; diff --git a/Steer/include/Steer/O2RunSim.h b/Steer/include/Steer/O2RunSim.h index 709d54461e62d..90ea8df528542 100644 --- a/Steer/include/Steer/O2RunSim.h +++ b/Steer/include/Steer/O2RunSim.h @@ -36,6 +36,7 @@ #include "FairTask.h" // for FairTask #include "FairTrajFilter.h" // for FairTrajFilter #include "TRandom.h" +#include <TObjString.h> #include <Steer/O2MCApplication.h> namespace o2 diff --git a/Utilities/Mergers/test/test_Algorithm.cxx b/Utilities/Mergers/test/test_Algorithm.cxx index a87414f5963c5..0082b4e381efb 100644 --- a/Utilities/Mergers/test/test_Algorithm.cxx +++ b/Utilities/Mergers/test/test_Algorithm.cxx @@ -24,6 +24,7 @@ #include "Mergers/CustomMergeableObject.h" #include <TObjArray.h> +#include <TObjString.h> #include <TH1.h> #include <TH2.h> #include <TH3.h> From d825b46e32439070c57e2a5c9f5bae4a86416ea2 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 29 Jul 2020 23:43:56 +0200 Subject: [PATCH 0195/1751] DPL Analysis: fix for integer comparison in expressions (#4050) --- Analysis/Tutorials/src/filters.cxx | 3 ++- Framework/Core/include/Framework/DataTypes.h | 2 ++ Framework/Core/src/Expressions.cxx | 12 ++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Analysis/Tutorials/src/filters.cxx b/Analysis/Tutorials/src/filters.cxx index ddb31fbb9bf33..fe33f3df1834f 100644 --- a/Analysis/Tutorials/src/filters.cxx +++ b/Analysis/Tutorials/src/filters.cxx @@ -86,7 +86,8 @@ struct CTask { }; struct DTask { - void process(aod::Collision const&, aod::MTracks const& tracks) + Filter notTracklet = aod::track::trackType != 3; // only works with literal now + void process(aod::Collision const&, soa::Filtered<aod::MTracks> const& tracks) { for (auto& track : tracks) { LOGF(INFO, "%.3f == %.3f", track.spt(), std::abs(track.sigma1Pt() / track.signed1Pt())); diff --git a/Framework/Core/include/Framework/DataTypes.h b/Framework/Core/include/Framework/DataTypes.h index fe56d1d2a5dd7..12abe74a7cce7 100644 --- a/Framework/Core/include/Framework/DataTypes.h +++ b/Framework/Core/include/Framework/DataTypes.h @@ -10,6 +10,8 @@ #ifndef O2_FRAMEWORK_DATATYPES_H_ #define O2_FRAMEWORK_DATATYPES_H_ +#include <cstdint> + namespace o2::aod::track { enum TrackTypeEnum : uint8_t { diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 5e6457ea7e22b..38b753875ddd6 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -425,6 +425,16 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, return node; }; + auto insertEqualizeUpcastNode = [&](gandiva::NodePtr node1, gandiva::NodePtr node2, atype::type t1, atype::type t2) { + if (t2 > t1) { + auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t2), {node1}, concreteArrowType(t2)); + node1 = upcast; + } else { + auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t1), {node2}, concreteArrowType(t1)); + node2 = upcast; + } + }; + switch (it->op) { case BasicOp::LogicalOr: tree = gandiva::TreeExprBuilder::MakeOr({leftNode, rightNode}); @@ -437,6 +447,8 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, if (it->type != atype::BOOL) { leftNode = insertUpcastNode(leftNode, it->left.type); rightNode = insertUpcastNode(rightNode, it->right.type); + } else if (it->op == BasicOp::Equal || it->op == BasicOp::NotEqual) { + insertEqualizeUpcastNode(leftNode, rightNode, it->left.type, it->right.type); } tree = gandiva::TreeExprBuilder::MakeFunction(binaryOperationsMap[it->op], {leftNode, rightNode}, concreteArrowType(it->type)); } else { From 3a4b547fdc80ebd4bf0189236326c3d48cad3057 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 21:59:59 +0200 Subject: [PATCH 0196/1751] GPU: Fix incorrect number of blocks for TPC track merging on CPU with OMP without ompKernels --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 86f5b0e042635..660288bbe9fd1 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1972,7 +1972,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) mOutputQueue.clear(); } - runKernel<GPUTPCGMMergerTrackFit>(GetGrid(Merger.NOutputTracks(), 0), krnlRunRangeNone, krnlEventNone, GetProcessingSettings().mergerSortTracks ? 1 : 0); + runKernel<GPUTPCGMMergerTrackFit>(doGPU ? GetGrid(Merger.NOutputTracks(), 0) : GetGridAuto(0), krnlRunRangeNone, krnlEventNone, GetProcessingSettings().mergerSortTracks ? 1 : 0); if (param().rec.retryRefit == 1) { runKernel<GPUTPCGMMergerTrackFit>(GetGridAuto(0), krnlRunRangeNone, krnlEventNone, -1); } From 936f5b31309bc4d7585b80b831689cfa115951aa Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 21:43:13 +0200 Subject: [PATCH 0197/1751] TPC Workflow: Bugfix: Don't make assumptions how bz has been initialized when updating from GRP --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index fa0a1278ed6a6..f8f6487c82f57 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -106,7 +106,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int GPUO2InterfaceConfiguration config; const auto grp = o2::parameters::GRPObject::loadFrom("o2sim_grp.root"); if (grp) { - config.configEvent.solenoidBz *= grp->getL3Current() / 30000.; + config.configEvent.solenoidBz = 5.00668f * grp->getL3Current() / 30000.; config.configEvent.continuousMaxTimeBin = grp->isDetContinuousReadOut(o2::detectors::DetID::TPC) ? -1 : 0; // Number of timebins in timeframe if continuous, 0 otherwise LOG(INFO) << "Initializing run paramerers from GRP bz=" << config.configEvent.solenoidBz << " cont=" << grp->isDetContinuousReadOut(o2::detectors::DetID::TPC); } else { From 3f29263964f36526f1b84d384dc3de128c460d7d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 21:47:52 +0200 Subject: [PATCH 0198/1751] TPC Workflow: Fix missing default value for track reference X --- GPU/GPUTracking/Base/GPUSettingsList.h | 2 +- GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 76e74572cf6e9..c4db90282ab12 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -40,7 +40,7 @@ AddOption(ClusterError2CorrectionZ, float, 1., "", 0, "correction for the square AddOption(MinNTrackClusters, int, -1, "", 0, "required min number of clusters on the track") AddOption(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required max Q/Pt (==min Pt) of tracks") AddOption(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") -AddOption(TrackReferenceX, float, 1000, "", 0, "Transport all tracks to this X after tracking (disabled if > 500)") +AddOption(TrackReferenceX, float, 1000.f, "", 0, "Transport all tracks to this X after tracking (disabled if > 500, auto = 1000)") AddOption(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") AddOption(NWays, char, 3, "", 0, "Do N fit passes in final fit of merger") AddOption(NWaysOuter, char, 0, "", 0, "Store outer param") diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx index 7e63fc0403d3d..d7ee19f625da9 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx @@ -94,6 +94,9 @@ GPUSettingsO2 GPUO2InterfaceConfiguration::ReadConfigurableParam() if (global.constBz) { configEvent.constBz = global.constBz; } + if (configReconstruction.TrackReferenceX == 1000.f) { + configReconstruction.TrackReferenceX = 83.f; + } configDeviceBackend.deviceType = GPUDataTypes::GetDeviceType(global.deviceType.c_str()); configDeviceBackend.forceDeviceType = global.forceDeviceType; return global; From 52b18e89d05c5a47cd127ea638e54e04c406226e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 22:10:29 +0200 Subject: [PATCH 0199/1751] TPC Workflow: Add option to disable dEdx/matLut in synchronous processing --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 9 +++++++-- GPU/GPUTracking/Base/GPUSettingsList.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index f8f6487c82f57..d8db59f44398f 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -132,8 +132,13 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int config.configWorkflow.steps.set(GPUDataTypes::RecoStep::TPCConversion, GPUDataTypes::RecoStep::TPCSliceTracking, GPUDataTypes::RecoStep::TPCMerging, - GPUDataTypes::RecoStep::TPCCompression, - GPUDataTypes::RecoStep::TPCdEdx); + GPUDataTypes::RecoStep::TPCCompression); + + config.configWorkflow.steps.setBits(GPUDataTypes::RecoStep::TPCdEdx, !confParam.synchronousProcessing); + if (confParam.synchronousProcessing) { + config.configReconstruction.useMatLUT = false; + } + // Alternative steps: TRDTracking | ITSTracking config.configWorkflow.inputs.set(GPUDataTypes::InOutType::TPCClusters); // Alternative inputs: GPUDataTypes::InOutType::TRDTracklets diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index c4db90282ab12..c26f50ffd7c72 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -260,6 +260,7 @@ AddOption(dEdxFile, std::string, "", "", 0, "File name of dEdx Splines file") AddOption(transformationFile, std::string, "", "", 0, "File name of TPC fast transformation map") AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") +AddOption(synchronousProcessing, bool, false, "", 0, "Apply performance shortcuts for synchronous processing, disable unneeded steps") EndConfig() #endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE From 0aa0fcc7fbe32f8a1ddf4506a7da30229bbead09 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 23:21:11 +0200 Subject: [PATCH 0200/1751] TPC Workflow: Add option to define buffer size in case buffers are not allocated on the fly --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 11 +++++------ GPU/GPUTracking/Base/GPUSettingsList.h | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index d8db59f44398f..826ff85c6c24f 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -90,6 +90,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int std::vector<int> clusterOutputIds; bool readyToQuit = false; bool allocateOutputOnTheFly = false; + unsigned long outputBufferSize = 0; bool suppressOutput = false; }; @@ -114,6 +115,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } const GPUSettingsO2& confParam = config.ReadConfigurableParam(); processAttributes->allocateOutputOnTheFly = confParam.allocateOutputOnTheFly; + processAttributes->outputBufferSize = confParam.outputBufferSize; processAttributes->suppressOutput = (confParam.dump == 2); if (config.configEvent.continuousMaxTimeBin == -1) { config.configEvent.continuousMaxTimeBin = (o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * o2::constants::lhc::LHCMaxBunches + 2 * Constants::LHCBCPERTIMEBIN - 2) / Constants::LHCBCPERTIMEBIN; @@ -564,15 +566,12 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } GPUInterfaceOutputs outputRegions; - // TODO: For output to preallocated buffer, just allocated some large buffer for now. - // This should be estimated correctly, but it is not the default for now, so it doesn't matter much. - size_t bufferSize = 256ul * 1024 * 1024; std::optional<std::reference_wrapper<O2CharVectorOutputType>> clusterOutput = std::nullopt, bufferCompressedClusters = std::nullopt, bufferTPCTracks = std::nullopt; if (specconfig.outputCompClustersFlat) { if (processAttributes->allocateOutputOnTheFly) { outputRegions.compressedClusters.allocator = [&bufferCompressedClusters, &pc](size_t size) -> void* {bufferCompressedClusters.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, size)); return bufferCompressedClusters->get().data(); }; } else { - bufferCompressedClusters.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, bufferSize)); + bufferCompressedClusters.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, processAttributes->outputBufferSize)); outputRegions.compressedClusters.ptr = bufferCompressedClusters->get().data(); outputRegions.compressedClusters.size = bufferCompressedClusters->get().size(); } @@ -581,7 +580,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int if (processAttributes->allocateOutputOnTheFly) { outputRegions.clustersNative.allocator = [&clusterOutput, &pc, clusterOutputSectorHeader](size_t size) -> void* {clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, size + sizeof(ClusterCountIndex))); return (char*)clusterOutput->get().data() + sizeof(ClusterCountIndex); }; } else { - clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, bufferSize)); + clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, processAttributes->outputBufferSize)); outputRegions.clustersNative.ptr = (char*)clusterOutput->get().data() + sizeof(ClusterCountIndex); outputRegions.clustersNative.size = clusterOutput->get().size() * sizeof(*clusterOutput->get().data()) - sizeof(ClusterCountIndex); } @@ -589,7 +588,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int if (processAttributes->allocateOutputOnTheFly) { outputRegions.tpcTracks.allocator = [&bufferTPCTracks, &pc](size_t size) -> void* {bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, size)); return bufferTPCTracks->get().data(); }; } else { - bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, bufferSize)); + bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, processAttributes->outputBufferSize)); outputRegions.tpcTracks.ptr = bufferTPCTracks->get().data(); outputRegions.tpcTracks.size = bufferTPCTracks->get().size(); } diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index c26f50ffd7c72..7700386bb2e38 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -260,6 +260,7 @@ AddOption(dEdxFile, std::string, "", "", 0, "File name of dEdx Splines file") AddOption(transformationFile, std::string, "", "", 0, "File name of TPC fast transformation map") AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") +AddOption(outputBufferSize, unsigned long, 200000000ul, "", 0, "Size of the output buffers to be allocated") AddOption(synchronousProcessing, bool, false, "", 0, "Apply performance shortcuts for synchronous processing, disable unneeded steps") EndConfig() #endif // GPUCA_O2_LIB From c25d073e2d106ccc4a5b4d6a661cc466159aebfb Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 23:21:48 +0200 Subject: [PATCH 0201/1751] GPU: Add missing OpenCL version target definition --- .../Base/opencl-common/GPUReconstructionOCLInternals.h | 1 + .../Standalone/makefiles/makefile_opencl_compiler.cxx | 1 + 2 files changed, 2 insertions(+) diff --git a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h index 1f411324d6b05..ae3291bebb0a4 100644 --- a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h +++ b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h @@ -16,6 +16,7 @@ #ifndef GPUTPCGPUTRACKEROPENCLINTERNALS_H #define GPUTPCGPUTRACKEROPENCLINTERNALS_H +#define CL_TARGET_OPENCL_VERSION 220 #include <CL/opencl.h> #include <CL/cl_ext.h> #include <vector> diff --git a/GPU/GPUTracking/Standalone/makefiles/makefile_opencl_compiler.cxx b/GPU/GPUTracking/Standalone/makefiles/makefile_opencl_compiler.cxx index c4178a0523745..58918fe988539 100644 --- a/GPU/GPUTracking/Standalone/makefiles/makefile_opencl_compiler.cxx +++ b/GPU/GPUTracking/Standalone/makefiles/makefile_opencl_compiler.cxx @@ -11,6 +11,7 @@ /// \file makefile_opencl_compiler.cxx /// \author David Rohr +#define CL_TARGET_OPENCL_VERSION 220 #define _CRT_SECURE_NO_WARNINGS #include "CL/opencl.h" #include <cstdlib> From 8bf04115aeb84e52c06f9d86038a63d934869fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Thu, 30 Jul 2020 08:45:41 +0200 Subject: [PATCH 0202/1751] RecoDecay: version for analysis challenge (#4054) * Replace vector calculations back with explicit helper functions. * Get particle masses outside process(). * Rename mass variables. * Simplify bool value conditions. * Fix filling of 3-prong mass histogram. --- .../DataModel/include/Analysis/RecoDecay.h | 50 ++--------- Analysis/Tasks/hfcandidatecreator2prong.cxx | 27 +++--- Analysis/Tasks/hftrackindexskimscreator.cxx | 90 ++++++++++--------- 3 files changed, 68 insertions(+), 99 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index 613bf44849666..ebda753431603 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -14,7 +14,7 @@ double energy(double px, double py, double pz, double mass) { double en_ = sqrt(mass * mass + px * px + py * py + pz * pz); return en_; -}; +} double invmass2prongs2(double px0, double py0, double pz0, double mass0, double px1, double py1, double pz1, double mass1) @@ -28,7 +28,7 @@ double invmass2prongs2(double px0, double py0, double pz0, double mass0, (py0 + py1) * (py0 + py1) + (pz0 + pz1) * (pz0 + pz1); return energytot * energytot - psum2; -}; +} double invmass3prongs2(double px0, double py0, double pz0, double mass0, double px1, double py1, double pz1, double mass1, @@ -43,14 +43,14 @@ double invmass3prongs2(double px0, double py0, double pz0, double mass0, (py0 + py1 + py2) * (py0 + py1 + py2) + (pz0 + pz1 + pz2) * (pz0 + pz1 + pz2); return energytot * energytot - psum2; -}; +} double invmass2prongs(double px0, double py0, double pz0, double mass0, double px1, double py1, double pz1, double mass1) { return sqrt(invmass2prongs2(px0, py0, pz0, mass0, px1, py1, pz1, mass1)); -}; +} double invmass3prongs(double px0, double py0, double pz0, double mass0, double px1, double py1, double pz1, double mass1, @@ -59,60 +59,26 @@ double invmass3prongs(double px0, double py0, double pz0, double mass0, return sqrt(invmass3prongs2(px0, py0, pz0, mass0, px1, py1, pz1, mass1, px2, py2, pz2, mass2)); -}; +} double ptcand2prong(double px0, double py0, double px1, double py1) { return sqrt((px0 + px1) * (px0 + px1) + (py0 + py1) * (py0 + py1)); -}; +} double pttrack(double px, double py) { return sqrt(px * px + py * py); -}; +} double declength(double xdecay, double ydecay, double zdecay, double xvtx, double yvtx, double zvtx) { return sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx) + (zdecay - zvtx) * (zdecay - zvtx)); -}; +} double declengthxy(double xdecay, double ydecay, double xvtx, double yvtx) { return sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx)); -}; - -/// Add a track object to a list. -/// \param list vector of track objects -/// \param momentum 3-momentum components (x, y, z) -/// \param temporal mass or energy (depends on the vector type) -template <typename T, typename U, typename V> -void addTrack(std::vector<T>& list, U momentum_x, U momentum_y, U momentum_z, V temporal) -{ - T track(momentum_x, momentum_y, momentum_z, temporal); - list.push_back(track); -} - -/// Add a track object to a list. -/// \param list vector of track objects -/// \param momentum array of 3-momentum components (x, y, z) -/// \param temporal mass or energy (depends on the vector type) -template <typename T, typename U, typename V> -void addTrack(std::vector<T>& list, const std::array<U, 3>& momentum, V temporal) -{ - addTrack(list, momentum[0], momentum[1], momentum[2], temporal); -} - -/// Sum up track objects in a list. -/// \param list vector of track objects -/// \return Return the sum of the vector elements. -template <typename T> -T sumOfTracks(const std::vector<T>& list) -{ - T sum; - for (const auto& track : list) { - sum += track; - } - return sum; } #endif // O2_ANALYSIS_RECODECAY_H_ diff --git a/Analysis/Tasks/hfcandidatecreator2prong.cxx b/Analysis/Tasks/hfcandidatecreator2prong.cxx index baa528f675c77..a9c1e29f7c62a 100644 --- a/Analysis/Tasks/hfcandidatecreator2prong.cxx +++ b/Analysis/Tasks/hfcandidatecreator2prong.cxx @@ -49,6 +49,9 @@ struct HFCandidateCreator2Prong { "stop iterations if largest change of any X is smaller than this"}; Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; + double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + double massK = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); + void process(aod::Collision const& collision, aod::HfTrackIndexProng2 const& hftrackindexprong2s, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) @@ -61,9 +64,8 @@ struct HFCandidateCreator2Prong { df.setMinParamChange(d_minparamchange); df.setMinRelChi2Change(d_minrelchi2change); - std::vector<PxPyPzMVector> listTracks; - double masspion = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); - double masskaon = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); + double mass2PiK{0}; + double mass2KPi{0}; for (auto& hfpr2 : hftrackindexprong2s) { auto trackparvar_p1 = getTrackParCov(hfpr2.index0()); @@ -78,23 +80,22 @@ struct HFCandidateCreator2Prong { df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); - addTrack(listTracks, pvec0, masspion); - addTrack(listTracks, pvec1, masskaon); - double mass_ = (sumOfTracks(listTracks)).M(); - listTracks[0].SetM(masskaon); - listTracks[1].SetM(masspion); - double masssw_ = (sumOfTracks(listTracks)).M(); - listTracks.clear(); + mass2PiK = invmass2prongs( + pvec0[0], pvec0[1], pvec0[2], massPi, + pvec1[0], pvec1[1], pvec1[2], massK); + mass2KPi = invmass2prongs( + pvec0[0], pvec0[1], pvec0[2], massK, + pvec1[0], pvec1[1], pvec1[2], massPi); hfcandprong2(collision.posX(), collision.posY(), collision.posZ(), pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], - vtx[0], vtx[1], vtx[2], mass_, masssw_); + vtx[0], vtx[1], vtx[2], mass2PiK, mass2KPi); if (b_dovalplots == true) { hvtx_x_out->Fill(vtx[0]); hvtx_y_out->Fill(vtx[1]); hvtx_z_out->Fill(vtx[2]); - hmass2->Fill(mass_); - hmass2->Fill(masssw_); + hmass2->Fill(mass2PiK); + hmass2->Fill(mass2KPi); } } } diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index 7d5269b18cc48..0f4fb14f28741 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -62,7 +62,7 @@ struct SelectTracks { for (auto it0 = tracks.begin(); it0 != tracks.end(); ++it0) { auto& track_0 = *it0; int status = 1; - if (b_dovalplots == true) + if (b_dovalplots) hpt_nocuts->Fill(track_0.pt()); if (track_0.pt() < ptmintrack) status = 0; @@ -76,7 +76,7 @@ struct SelectTracks { trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca); if (abs(dca[0]) < dcatoprimxymin) status = 0; - if (b_dovalplots == true) { + if (b_dovalplots) { if (status == 1) { hpt_cuts->Fill(track_0.pt()); hdcatoprimxy_cuts->Fill(dca[0]); @@ -88,9 +88,6 @@ struct SelectTracks { }; struct HFTrackIndexSkimsCreator { - std::vector<PxPyPzMVector> listTracks; - double masspion = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); - double masskaon = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; Produces<aod::HfTrackIndexProng2> hftrackindexprong2; @@ -111,6 +108,8 @@ struct HFTrackIndexSkimsCreator { Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; Filter seltrack = (aod::seltrack::issel == 1); + double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + double massK = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); void process(aod::Collision const& collision, aod::BCs const& bcs, @@ -142,6 +141,11 @@ struct HFTrackIndexSkimsCreator { df3.setMinParamChange(d_minparamchange); df3.setMinRelChi2Change(d_minrelchi2change); + double mass2PiK{0}; + double mass2KPi{0}; + double mass3PiKPiPlus{0}; + double mass3PiKPiMinus{0}; + for (auto i_p1 = tracks.begin(); i_p1 != tracks.end(); ++i_p1) { auto& track_p1 = *i_p1; if (track_p1.signed1Pt() < 0) @@ -162,21 +166,22 @@ struct HFTrackIndexSkimsCreator { df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); - addTrack(listTracks, pvec0, masspion); - addTrack(listTracks, pvec1, masskaon); - double mass_ = (sumOfTracks(listTracks)).M(); - listTracks[0].SetM(masskaon); - listTracks[1].SetM(masspion); - double masssw_ = (sumOfTracks(listTracks)).M(); - listTracks.clear(); + mass2PiK = invmass2prongs( + pvec0[0], pvec0[1], pvec0[2], massPi, + pvec1[0], pvec1[1], pvec1[2], massK); + mass2KPi = invmass2prongs( + pvec0[0], pvec0[1], pvec0[2], massK, + pvec1[0], pvec1[1], pvec1[2], massPi); - if (b_dovalplots == true) { - hmass2->Fill(mass_); - hmass2->Fill(masssw_); + if (b_dovalplots) { + hmass2->Fill(mass2PiK); + hmass2->Fill(mass2KPi); } + hftrackindexprong2(track_p1.collisionId(), track_p1.globalIndex(), track_n1.globalIndex(), 1); + if (do3prong == 1) { //second loop on positive tracks for (auto i_p2 = i_p1 + 1; i_p2 != tracks.end(); ++i_p2) { @@ -184,16 +189,14 @@ struct HFTrackIndexSkimsCreator { if (track_p2.signed1Pt() < 0) continue; - addTrack(listTracks, track_p1.px(), track_p1.py(), track_p1.pz(), masspion); - addTrack(listTracks, track_n1.px(), track_n1.py(), track_n1.pz(), masskaon); - addTrack(listTracks, track_p2.px(), track_p2.py(), track_p2.pz(), masspion); - double mass3prong = (sumOfTracks(listTracks)).M(); - listTracks.clear(); + mass3PiKPiPlus = invmass3prongs( + track_p1.px(), track_p1.py(), track_p1.pz(), massPi, + track_n1.px(), track_n1.py(), track_n1.pz(), massK, + track_p2.px(), track_p2.py(), track_p2.pz(), massPi); - if (mass3prong < d_minmassDp || mass3prong > d_maxmassDp) + if (mass3PiKPiPlus < d_minmassDp || mass3PiKPiPlus > d_maxmassDp) continue; - if (b_dovalplots == true) - hmass3->Fill(mass3prong); + auto trackparvar_p2 = getTrackParCov(track_p2); df3.setUseAbsDCA(true); int nCand3 = df3.process(trackparvar_p1, trackparvar_n1, trackparvar_p2); @@ -207,15 +210,15 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); - addTrack(listTracks, pvec0, masspion); - addTrack(listTracks, pvec1, masskaon); - addTrack(listTracks, pvec2, masspion); - double mass_ = (sumOfTracks(listTracks)).M(); - listTracks.clear(); + mass3PiKPiPlus = invmass3prongs( + pvec0[0], pvec0[1], pvec0[2], massPi, + pvec1[0], pvec1[1], pvec1[2], massK, + pvec2[0], pvec2[1], pvec2[2], massPi); - if (b_dovalplots == true) { - hmass3->Fill(mass_); + if (b_dovalplots) { + hmass3->Fill(mass3PiKPiPlus); } + hftrackindexprong3(track_p1.collisionId(), track_p1.globalIndex(), track_n1.globalIndex(), @@ -227,15 +230,14 @@ struct HFTrackIndexSkimsCreator { if (track_n2.signed1Pt() > 0) continue; - addTrack(listTracks, track_n1.px(), track_n1.py(), track_n1.pz(), masspion); - addTrack(listTracks, track_p1.px(), track_p1.py(), track_p1.pz(), masskaon); - addTrack(listTracks, track_n2.px(), track_n2.py(), track_n2.pz(), masspion); - double mass3prong = (sumOfTracks(listTracks)).M(); - listTracks.clear(); + mass3PiKPiMinus = invmass3prongs( + track_n1.px(), track_n1.py(), track_n1.pz(), massPi, + track_p1.px(), track_p1.py(), track_p1.pz(), massK, + track_n2.px(), track_n2.py(), track_n2.pz(), massPi); - if (mass3prong < d_minmassDp || mass3prong > d_maxmassDp) + if (mass3PiKPiMinus < d_minmassDp || mass3PiKPiMinus > d_maxmassDp) continue; - hmass3->Fill(mass3prong); + auto trackparvar_n2 = getTrackParCov(track_n2); df3.setUseAbsDCA(true); int nCand3 = df3.process(trackparvar_n1, trackparvar_p1, trackparvar_n2); @@ -249,15 +251,15 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); - addTrack(listTracks, pvec0, masspion); - addTrack(listTracks, pvec1, masskaon); - addTrack(listTracks, pvec2, masspion); - double mass_ = (sumOfTracks(listTracks)).M(); - listTracks.clear(); + mass3PiKPiMinus = invmass3prongs( + pvec0[0], pvec0[1], pvec0[2], massPi, + pvec1[0], pvec1[1], pvec1[2], massK, + pvec2[0], pvec2[1], pvec2[2], massPi); - if (b_dovalplots == true) { - hmass3->Fill(mass_); + if (b_dovalplots) { + hmass3->Fill(mass3PiKPiMinus); } + hftrackindexprong3(track_n1.collisionId(), track_n1.globalIndex(), track_p1.globalIndex(), From a862f21fdf991f6f36e545f72fa48983c0c30660 Mon Sep 17 00:00:00 2001 From: Matteo Concas <mconcas@cern.ch> Date: Thu, 23 Jul 2020 15:15:10 +0200 Subject: [PATCH 0203/1751] Fix ITS3 simulation --- .../Common/include/DetectorsCommonDataFormats/SimTraits.h | 2 +- Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx | 2 +- Detectors/Upgrades/IT3/simulation/src/Detector.cxx | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h index 8ae6399a7a065..f2a3d3be7d7c0 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h @@ -89,7 +89,7 @@ class SimTraits /*ACO*/ VS{ "ACOHit" } #ifdef ENABLE_UPGRADES , - /*IT3*/ VS{ "ITS3Hit" } + /*IT3*/ VS{ "IT3Hit" } #endif }; // clang-format on diff --git a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx index a873385bbc7ec..d73e809e8f1be 100644 --- a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx @@ -285,7 +285,7 @@ TGeoHMatrix* GeometryTGeo::extractMatrixSensor(int index) const int wrID = mLayerToWrapper[lay]; - TString path = Form("/cave_1/%s_2/", GeometryTGeo::getITSVolPattern()); + TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getITSVolPattern()); if (wrID >= 0) { path += Form("%s%d_1/", getITSWrapVolPattern(), wrID); diff --git a/Detectors/Upgrades/IT3/simulation/src/Detector.cxx b/Detectors/Upgrades/IT3/simulation/src/Detector.cxx index 674a52efd1ed6..40b262c1b17fb 100644 --- a/Detectors/Upgrades/IT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/IT3/simulation/src/Detector.cxx @@ -919,14 +919,14 @@ void Detector::constructDetectorGeometry() // Create the geometry and insert it in the mother volume ITSV TGeoManager* geoManager = gGeoManager; - TGeoVolume* vALIC = geoManager->GetVolume("cave"); + TGeoVolume* vALIC = geoManager->GetVolume("barrel"); if (!vALIC) { LOG(FATAL) << "Could not find the top volume"; } new TGeoVolumeAssembly(GeometryTGeo::getITSVolPattern()); TGeoVolume* vITSV = geoManager->GetVolume(GeometryTGeo::getITSVolPattern()); - vALIC->AddNode(vITSV, 2, nullptr); // Copy number is 2 to cheat AliGeoManager::CheckSymNamesLUT + vALIC->AddNode(vITSV, 2, new TGeoTranslation(0, 30., 0)); // Copy number is 2 to cheat AliGeoManager::CheckSymNamesLUT const Int_t kLength = 100; Char_t vstrng[kLength] = "xxxRS"; //? @@ -1200,7 +1200,7 @@ void Detector::addAlignableVolumes() const return; } - TString path = Form("/cave_1/%s_2", GeometryTGeo::getITSVolPattern()); + TString path = Form("/cave_1/barrel_1/%s_2", GeometryTGeo::getITSVolPattern()); TString sname = GeometryTGeo::composeSymNameITS3(); LOG(DEBUG) << sname << " <-> " << path; From 7ea7cf529efb4425bea4260fd86c3330c8898f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Thu, 30 Jul 2020 14:16:46 +0200 Subject: [PATCH 0204/1751] HF Analysis: add documentation comments. (#4064) --- Analysis/Tasks/hfcandidatecreator2prong.cxx | 2 ++ Analysis/Tasks/hftrackindexskimscreator.cxx | 14 +++++++++++--- Analysis/Tasks/taskdzero.cxx | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Analysis/Tasks/hfcandidatecreator2prong.cxx b/Analysis/Tasks/hfcandidatecreator2prong.cxx index a9c1e29f7c62a..984a4512ae130 100644 --- a/Analysis/Tasks/hfcandidatecreator2prong.cxx +++ b/Analysis/Tasks/hfcandidatecreator2prong.cxx @@ -32,6 +32,7 @@ using namespace o2::framework::expressions; using std::array; using namespace ROOT::Math; +/// Reconstruction of heavy-flavour 2-prong decay candidates struct HFCandidateCreator2Prong { Produces<aod::HfCandProng2> hfcandprong2; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; @@ -67,6 +68,7 @@ struct HFCandidateCreator2Prong { double mass2PiK{0}; double mass2KPi{0}; + // loop over 2-prong secondary vertices for (auto& hfpr2 : hftrackindexprong2s) { auto trackparvar_p1 = getTrackParCov(hfpr2.index0()); auto trackparvar_n1 = getTrackParCov(hfpr2.index1()); diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index 0f4fb14f28741..5c30c55c8f1a6 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -44,6 +44,7 @@ DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", seltrack::IsSel, seltrack::DCAPri seltrack::DCAPrim1); } // namespace o2::aod +/// Track selection struct SelectTracks { Produces<aod::SelTrack> seltrack; Configurable<double> ptmintrack{"ptmintrack", -1, "ptmin single track"}; @@ -61,7 +62,7 @@ struct SelectTracks { Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); for (auto it0 = tracks.begin(); it0 != tracks.end(); ++it0) { auto& track_0 = *it0; - int status = 1; + int status = 1; // selection flag if (b_dovalplots) hpt_nocuts->Fill(track_0.pt()); if (track_0.pt() < ptmintrack) @@ -87,6 +88,7 @@ struct SelectTracks { } }; +/// Pre-selection of 2-prong and 3-prong secondary vertices struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; @@ -146,16 +148,21 @@ struct HFTrackIndexSkimsCreator { double mass3PiKPiPlus{0}; double mass3PiKPiMinus{0}; + // first loop over positive tracks for (auto i_p1 = tracks.begin(); i_p1 != tracks.end(); ++i_p1) { auto& track_p1 = *i_p1; if (track_p1.signed1Pt() < 0) continue; auto trackparvar_p1 = getTrackParCov(track_p1); + + // first loop over negative tracks for (auto i_n1 = tracks.begin(); i_n1 != tracks.end(); ++i_n1) { auto& track_n1 = *i_n1; if (track_n1.signed1Pt() > 0) continue; auto trackparvar_n1 = getTrackParCov(track_n1); + + // reconstruct the 2-prong secondary vertex df.setUseAbsDCA(true); int nCand = df.process(trackparvar_p1, trackparvar_n1); if (nCand == 0) @@ -182,8 +189,9 @@ struct HFTrackIndexSkimsCreator { track_p1.globalIndex(), track_n1.globalIndex(), 1); + // 3-prong vertex reconstruction if (do3prong == 1) { - //second loop on positive tracks + // second loop over positive tracks for (auto i_p2 = i_p1 + 1; i_p2 != tracks.end(); ++i_p2) { auto& track_p2 = *i_p2; if (track_p2.signed1Pt() < 0) @@ -224,7 +232,7 @@ struct HFTrackIndexSkimsCreator { track_n1.globalIndex(), track_p2.globalIndex(), 2); } - //second loop on negative tracks + // second loop over negative tracks for (auto i_n2 = i_n1 + 1; i_n2 != tracks.end(); ++i_n2) { auto& track_n2 = *i_n2; if (track_n2.signed1Pt() > 0) diff --git a/Analysis/Tasks/taskdzero.cxx b/Analysis/Tasks/taskdzero.cxx index a968774413d05..9bc98f51d530c 100644 --- a/Analysis/Tasks/taskdzero.cxx +++ b/Analysis/Tasks/taskdzero.cxx @@ -26,6 +26,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +/// D0 analysis task struct TaskDzero { OutputObj<TH1F> hmass{TH1F("hmass", "2-track inv mass", 500, 0, 5.0)}; OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0, 10.0)}; From fecb080448a8f27c40d6242828d26b7a396cbd0a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 30 Jul 2020 16:09:19 +0200 Subject: [PATCH 0205/1751] DPL: move Service callback responsibility to ServiceRegistry (#4061) Since the ServiceRegistry is needed to manage the lifetime of services, in particular in a multithreaded environment, this moves the responsibility of managing / invoking the ServiceSpec associated callback (including the one which actually creates the service, possibly on a per thread basis) to the service registry. --- .../include/Framework/DataProcessingDevice.h | 27 +----- .../Core/include/Framework/ServiceRegistry.h | 75 ++++++++++++----- Framework/Core/src/DataProcessingDevice.cxx | 61 ++------------ Framework/Core/src/ServiceRegistry.cxx | 83 ++++++++++++++++++- Framework/Core/src/runDataProcessing.cxx | 6 +- Framework/Core/test/test_Services.cxx | 8 +- 6 files changed, 150 insertions(+), 110 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index 05db79ce32af2..84cd9f31b9077 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -71,19 +71,7 @@ struct DataProcessorContext { AlgorithmSpec::ProcessCallback* statefulProcess = nullptr; AlgorithmSpec::ProcessCallback* statelessProcess = nullptr; AlgorithmSpec::ErrorCallback* error = nullptr; - /// Callbacks for services to be executed before every process method invokation - std::vector<ServiceProcessingHandle>* preProcessingHandles = nullptr; - /// Callbacks for services to be executed after every process method invokation - std::vector<ServiceProcessingHandle>* postProcessingHandles = nullptr; - /// Callbacks for services to be executed before every dangling check - std::vector<ServiceDanglingHandle>* preDanglingHandles = nullptr; - /// Callbacks for services to be executed after every dangling check - std::vector<ServiceDanglingHandle>* postDanglingHandles = nullptr; - /// Callbacks for services to be executed before every EOS user callback invokation - std::vector<ServiceEOSHandle>* preEOSHandles = nullptr; - /// Callbacks for services to be executed after every EOS user callback invokation - std::vector<ServiceEOSHandle>* postEOSHandles = nullptr; - /// Callback for the error handling + std::function<void(std::exception& e, InputRecord& record)>* errorHandling = nullptr; int* errorCount = nullptr; }; @@ -102,7 +90,6 @@ class DataProcessingDevice : public FairMQDevice void ResetTask() final; bool ConditionalRun() final; void SetErrorPolicy(enum TerminationPolicy policy) { mErrorPolicy = policy; } - void bindService(ServiceSpec const& spec, void* service); // Processing functions are now renetrant static void doRun(DataProcessorContext& context); @@ -135,18 +122,6 @@ class DataProcessingDevice : public FairMQDevice std::vector<ExpirationHandler> mExpirationHandlers; /// Completed actions std::vector<DataRelayer::RecordAction> mCompleted; - /// Callbacks for services to be executed before every process method invokation - std::vector<ServiceProcessingHandle> mPreProcessingHandles; - /// Callbacks for services to be executed after every process method invokation - std::vector<ServiceProcessingHandle> mPostProcessingHandles; - /// Callbacks for services to be executed before every dangling check - std::vector<ServiceDanglingHandle> mPreDanglingHandles; - /// Callbacks for services to be executed after every dangling check - std::vector<ServiceDanglingHandle> mPostDanglingHandles; - /// Callbacks for services to be executed before every EOS user callback invokation - std::vector<ServiceEOSHandle> mPreEOSHandles; - /// Callbacks for services to be executed after every EOS user callback invokation - std::vector<ServiceEOSHandle> mPostEOSHandles; int mErrorCount; uint64_t mLastSlowMetricSentTimestamp = 0; /// The timestamp of the last time we sent slow metrics diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index 2198ecf7a6417..488155ea1acd9 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -11,6 +11,7 @@ #define O2_FRAMEWORK_SERVICEREGISTRY_H_ #include "Framework/ServiceHandle.h" +#include "Framework/ServiceSpec.h" #include "Framework/ServiceRegistryHelpers.h" #include "Framework/CompilerBuiltins.h" #include "Framework/TypeIdHelpers.h" @@ -34,19 +35,31 @@ struct ServiceMeta { uint64_t threadId = 0; }; -struct ServiceRegistryBase { +struct ServiceRegistry { /// The maximum distance a entry can be from the optimal slot. constexpr static int MAX_DISTANCE = 8; /// The number of slots in the hashmap. constexpr static int MAX_SERVICES = 256; /// The mask to use to calculate the initial slot id. constexpr static int MAX_SERVICES_MASK = MAX_SERVICES - 1; + /// Callbacks for services to be executed before every process method invokation + std::vector<ServiceProcessingHandle> mPreProcessingHandles; + /// Callbacks for services to be executed after every process method invokation + std::vector<ServiceProcessingHandle> mPostProcessingHandles; + /// Callbacks for services to be executed before every dangling check + std::vector<ServiceDanglingHandle> mPreDanglingHandles; + /// Callbacks for services to be executed after every dangling check + std::vector<ServiceDanglingHandle> mPostDanglingHandles; + /// Callbacks for services to be executed before every EOS user callback invokation + std::vector<ServiceEOSHandle> mPreEOSHandles; + /// Callbacks for services to be executed after every EOS user callback invokation + std::vector<ServiceEOSHandle> mPostEOSHandles; public: using hash_type = decltype(TypeIdHelpers::uniqueId<void>()); - ServiceRegistryBase(); + ServiceRegistry(); - ServiceRegistryBase(ServiceRegistryBase const& other) + ServiceRegistry(ServiceRegistry const& other) { mServicesKey = other.mServicesKey; mServicesValue = other.mServicesValue; @@ -56,7 +69,7 @@ struct ServiceRegistryBase { } } - ServiceRegistryBase& operator=(ServiceRegistryBase const& other) + ServiceRegistry& operator=(ServiceRegistry const& other) { mServicesKey = other.mServicesKey; mServicesValue = other.mServicesValue; @@ -67,6 +80,29 @@ struct ServiceRegistryBase { return *this; } + /// Invoke callbacks to be executed before every process method invokation + void preProcessingCallbacks(ProcessingContext&); + /// Invoke callbacks to be executed after every process method invokation + void postProcessingCallbacks(ProcessingContext&); + /// Invoke callbacks to be executed before every dangling check + void preDanglingCallbacks(DanglingContext&); + /// Invoke callbacks to be executed after every dangling check + void postDanglingCallbacks(DanglingContext&); + /// Invoke callbacks to be executed before every EOS user callback invokation + void preEOSCallbacks(EndOfStreamContext&); + /// Invoke callbacks to be executed after every EOS user callback invokation + void postEOSCallbacks(EndOfStreamContext&); + /// Declare a service by its ServiceSpec. If of type Global + /// / Serial it will be immediately registered for tid 0, + /// so that subsequent gets will ultimately use it. + /// If it is of kind "Stream" we will create the Service only + /// when requested by a given thread. This function is not + /// thread safe. + void declareService(ServiceSpec const& spec, DeviceState& state, fair::mq::ProgOptions& options); + + /// Bind the callbacks of a service spec to a given service. + void bindService(ServiceSpec const& spec, void* service); + /// Type erased service registration. @a typeHash is the /// hash used to identify the service, @a service is /// a type erased pointer to the service itself. @@ -130,17 +166,20 @@ struct ServiceRegistryBase { return nullptr; } + /// Register a service given an handle + void registerService(ServiceHandle handle) + { + auto tid = std::this_thread::get_id(); + std::hash<std::thread::id> hasher; + ServiceRegistry::registerService(handle.hash, handle.instance, handle.kind, hasher(tid), handle.name.c_str()); + } + + mutable std::vector<ServiceSpec> mSpecs; mutable std::array<uint32_t, MAX_SERVICES + MAX_DISTANCE> mServicesKey; mutable std::array<void*, MAX_SERVICES + MAX_DISTANCE> mServicesValue; mutable std::array<ServiceMeta, MAX_SERVICES + MAX_DISTANCE> mServicesMeta; mutable std::array<std::atomic<bool>, MAX_SERVICES + MAX_DISTANCE> mServicesBooked; -}; -/// Service registry to hold generic, singleton like, interfaces and retrieve -/// them by type. -class ServiceRegistry : ServiceRegistryBase -{ - public: /// @deprecated old API to be substituted with the ServiceHandle one template <class I, class C, enum ServiceKind K = ServiceKind::Serial> void registerService(C* service) @@ -153,7 +192,7 @@ class ServiceRegistry : ServiceRegistryBase constexpr hash_type typeHash = TypeIdHelpers::uniqueId<I>(); auto tid = std::this_thread::get_id(); std::hash<std::thread::id> hasher; - ServiceRegistryBase::registerService(typeHash, reinterpret_cast<void*>(service), K, hasher(tid), typeid(C).name()); + ServiceRegistry::registerService(typeHash, reinterpret_cast<void*>(service), K, hasher(tid), typeid(C).name()); } /// @deprecated old API to be substituted with the ServiceHandle one @@ -169,7 +208,7 @@ class ServiceRegistry : ServiceRegistryBase constexpr auto id = typeHash & MAX_SERVICES_MASK; auto tid = std::this_thread::get_id(); std::hash<std::thread::id> hasher; - ServiceRegistryBase::registerService(typeHash, reinterpret_cast<void*>(const_cast<C*>(service)), K, hasher(tid), typeid(C).name()); + this->registerService(typeHash, reinterpret_cast<void*>(const_cast<C*>(service)), K, hasher(tid), typeid(C).name()); } /// Check if service of type T is currently active. @@ -179,7 +218,7 @@ class ServiceRegistry : ServiceRegistryBase constexpr auto typeHash = TypeIdHelpers::uniqueId<T>(); auto tid = std::this_thread::get_id(); std::hash<std::thread::id> hasher; - auto result = ServiceRegistryBase::getPos(typeHash, hasher(tid)) != -1; + auto result = this->getPos(typeHash, hasher(tid)) != -1; return result; } @@ -192,7 +231,7 @@ class ServiceRegistry : ServiceRegistryBase constexpr auto typeHash = TypeIdHelpers::uniqueId<T>(); auto tid = std::this_thread::get_id(); std::hash<std::thread::id> hasher; - auto ptr = ServiceRegistryBase::get(typeHash, hasher(tid), ServiceKind::Serial, typeid(T).name()); + auto ptr = this->get(typeHash, hasher(tid), ServiceKind::Serial, typeid(T).name()); if (O2_BUILTIN_LIKELY(ptr != nullptr)) { if constexpr (std::is_const_v<T>) { return *reinterpret_cast<T const*>(ptr); @@ -204,14 +243,6 @@ class ServiceRegistry : ServiceRegistryBase typeid(T).name() + ". Make sure you use const / non-const correctly."); } - - /// Register a service given an handle - void registerService(ServiceHandle handle) - { - auto tid = std::this_thread::get_id(); - std::hash<std::thread::id> hasher; - ServiceRegistryBase::registerService(handle.hash, handle.instance, handle.kind, hasher(tid), handle.name.c_str()); - } }; } // namespace o2::framework diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index cb2d9951363b3..b62d3bd86f8a2 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -400,18 +400,6 @@ void DataProcessingDevice::fillContext(DataProcessorContext& context) context.statefulProcess = &mStatefulProcess; context.statelessProcess = &mStatelessProcess; context.error = &mError; - /// Callbacks for services to be executed before every process method invokation - context.preProcessingHandles = &mPreProcessingHandles; - /// Callbacks for services to be executed after every process method invokation - context.postProcessingHandles = &mPostProcessingHandles; - /// Callbacks for services to be executed before every process method invokation - context.preDanglingHandles = &mPreDanglingHandles; - /// Callbacks for services to be executed after every process method invokation - context.postDanglingHandles = &mPostDanglingHandles; - /// Callbacks for services to be executed before every EOS user callback invokation - context.preEOSHandles = &mPreEOSHandles; - /// Callbacks for services to be executed after every EOS user callback invokation - context.postEOSHandles = &mPostEOSHandles; /// Callback for the error handling context.errorHandling = &mErrorHandling; context.errorCount = &mErrorCount; @@ -514,9 +502,8 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) context.completed->reserve(16); *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); DanglingContext danglingContext{*context.registry}; - for (auto preDanglingHandle : *context.preDanglingHandles) { - preDanglingHandle.callback(danglingContext, preDanglingHandle.service); - } + + context.registry->preDanglingCallbacks(danglingContext); if (*context.wasActive == false) { context.registry->get<CallbackService>()(CallbackService::Id::Idle); } @@ -526,9 +513,7 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) context.completed->clear(); *context.wasActive |= DataProcessingDevice::tryDispatchComputation(context, *context.completed); - for (auto postDanglingHandle : *context.postDanglingHandles) { - postDanglingHandle.callback(danglingContext, postDanglingHandle.service); - } + context.registry->postDanglingCallbacks(danglingContext); // If we got notified that all the sources are done, we call the EndOfStream // callback and return false. Notice that what happens next is actually @@ -547,13 +532,11 @@ void DataProcessingDevice::doRun(DataProcessorContext& context) context.relayer->processDanglingInputs(*context.expirationHandlers, *context.registry); } EndOfStreamContext eosContext{*context.registry, *context.allocator}; - for (auto& eosHandle : *context.preEOSHandles) { - eosHandle.callback(eosContext, eosHandle.service); - } + + context.registry->preEOSCallbacks(eosContext); context.registry->get<CallbackService>()(CallbackService::Id::EndOfStream, eosContext); - for (auto& eosHandle : *context.postEOSHandles) { - eosHandle.callback(eosContext, eosHandle.service); - } + context.registry->postEOSCallbacks(eosContext); + for (auto& channel : context.spec->outputChannels) { DataProcessingHelpers::sendEndOfStream(*context.device, channel); } @@ -946,9 +929,7 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, ProcessingContext processContext{record, *context.registry, *context.allocator}; { ZoneScopedN("service pre processing"); - for (auto& handle : *context.preProcessingHandles) { - handle.callback(processContext, handle.service); - } + context.registry->preProcessingCallbacks(processContext); } if (action.op == CompletionPolicy::CompletionOp::Discard) { if (context.spec->forwards.empty() == false) { @@ -973,9 +954,7 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, { ZoneScopedN("service post processing"); - for (auto& handle : *context.postProcessingHandles) { - handle.callback(processContext, handle.service); - } + context.registry->postProcessingCallbacks(processContext); } } } catch (std::exception& e) { @@ -1015,26 +994,4 @@ void DataProcessingDevice::error(const char* msg) mServiceRegistry.get<Monitoring>().send(Metric{mErrorCount, "errors"}.addTag(Key::Subsystem, Value::DPL)); } -void DataProcessingDevice::bindService(ServiceSpec const& spec, void* service) -{ - if (spec.preProcessing) { - mPreProcessingHandles.push_back(ServiceProcessingHandle{spec.preProcessing, service}); - } - if (spec.postProcessing) { - mPostProcessingHandles.push_back(ServiceProcessingHandle{spec.postProcessing, service}); - } - if (spec.preDangling) { - mPreDanglingHandles.push_back(ServiceDanglingHandle{spec.preDangling, service}); - } - if (spec.postDangling) { - mPostDanglingHandles.push_back(ServiceDanglingHandle{spec.postDangling, service}); - } - if (spec.preEOS) { - mPreEOSHandles.push_back(ServiceEOSHandle{spec.preEOS, service}); - } - if (spec.postEOS) { - mPostEOSHandles.push_back(ServiceEOSHandle{spec.postEOS, service}); - } -} - } // namespace o2::framework diff --git a/Framework/Core/src/ServiceRegistry.cxx b/Framework/Core/src/ServiceRegistry.cxx index e79e4f75d97e3..7efcad9fb29ea 100644 --- a/Framework/Core/src/ServiceRegistry.cxx +++ b/Framework/Core/src/ServiceRegistry.cxx @@ -15,7 +15,7 @@ namespace o2::framework { -ServiceRegistryBase::ServiceRegistryBase() +ServiceRegistry::ServiceRegistry() { mServicesKey.fill(0L); mServicesValue.fill(nullptr); @@ -28,7 +28,7 @@ ServiceRegistryBase::ServiceRegistryBase() /// hash used to identify the service, @a service is /// a type erased pointer to the service itself. /// This method is supposed to be thread safe -void ServiceRegistryBase::registerService(hash_type typeHash, void* service, ServiceKind kind, uint64_t threadId, const char* name) const +void ServiceRegistry::registerService(hash_type typeHash, void* service, ServiceKind kind, uint64_t threadId, const char* name) const { hash_type id = typeHash & MAX_SERVICES_MASK; hash_type threadHashId = (typeHash ^ threadId) & MAX_SERVICES_MASK; @@ -60,4 +60,83 @@ void ServiceRegistryBase::registerService(hash_type typeHash, void* service, Ser ". Make sure you use const / non-const correctly."); } +void ServiceRegistry::declareService(ServiceSpec const& spec, DeviceState& state, fair::mq::ProgOptions& options) +{ + mSpecs.push_back(spec); + // Services which are not stream must have a single instance created upfront. + if (spec.kind != ServiceKind::Stream) { + ServiceHandle handle = spec.init(*this, state, options); + this->registerService(handle.hash, handle.instance, handle.kind, 0, handle.name.c_str()); + this->bindService(spec, handle.instance); + } +} + +void ServiceRegistry::bindService(ServiceSpec const& spec, void* service) +{ + if (spec.preProcessing) { + mPreProcessingHandles.push_back(ServiceProcessingHandle{spec.preProcessing, service}); + } + if (spec.postProcessing) { + mPostProcessingHandles.push_back(ServiceProcessingHandle{spec.postProcessing, service}); + } + if (spec.preDangling) { + mPreDanglingHandles.push_back(ServiceDanglingHandle{spec.preDangling, service}); + } + if (spec.postDangling) { + mPostDanglingHandles.push_back(ServiceDanglingHandle{spec.postDangling, service}); + } + if (spec.preEOS) { + mPreEOSHandles.push_back(ServiceEOSHandle{spec.preEOS, service}); + } + if (spec.postEOS) { + mPostEOSHandles.push_back(ServiceEOSHandle{spec.postEOS, service}); + } +} + +/// Invoke callbacks to be executed before every process method invokation +void ServiceRegistry::preProcessingCallbacks(ProcessingContext& processContext) +{ + for (auto& handle : mPreProcessingHandles) { + handle.callback(processContext, handle.service); + } +} +/// Invoke callbacks to be executed after every process method invokation +void ServiceRegistry::postProcessingCallbacks(ProcessingContext& processContext) +{ + for (auto& handle : mPostProcessingHandles) { + handle.callback(processContext, handle.service); + } +} +/// Invoke callbacks to be executed before every dangling check +void ServiceRegistry::preDanglingCallbacks(DanglingContext& danglingContext) +{ + for (auto preDanglingHandle : mPreDanglingHandles) { + preDanglingHandle.callback(danglingContext, preDanglingHandle.service); + } +} + +/// Invoke callbacks to be executed after every dangling check +void ServiceRegistry::postDanglingCallbacks(DanglingContext& danglingContext) +{ + for (auto postDanglingHandle : mPostDanglingHandles) { + postDanglingHandle.callback(danglingContext, postDanglingHandle.service); + } +} + +/// Invoke callbacks to be executed before every EOS user callback invokation +void ServiceRegistry::preEOSCallbacks(EndOfStreamContext& eosContext) +{ + for (auto& eosHandle : mPreEOSHandles) { + eosHandle.callback(eosContext, eosHandle.service); + } +} + +/// Invoke callbacks to be executed after every EOS user callback invokation +void ServiceRegistry::postEOSCallbacks(EndOfStreamContext& eosContext) +{ + for (auto& eosHandle : mPostEOSHandles) { + eosHandle.callback(eosContext, eosHandle.service); + } +} + } // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index e53505ba3a96f..542150a659414 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -753,10 +753,8 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f /// Create all the requested services and initialise them for (auto& service : spec.services) { - LOG(info) << "Initialising service " << service.name; - auto handle = service.init(serviceRegistry, *deviceState.get(), r.fConfig); - serviceRegistry.registerService(handle); - dynamic_cast<DataProcessingDevice*>(r.fDevice.get())->bindService(service, handle.instance); + LOG(info) << "Declaring service " << service.name; + serviceRegistry.declareService(service, *deviceState.get(), r.fConfig); } if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(spec.resourceMonitoringInterval)) { serviceRegistry.get<Monitoring>().enableProcessMonitoring(spec.resourceMonitoringInterval); diff --git a/Framework/Core/test/test_Services.cxx b/Framework/Core/test/test_Services.cxx index 498a58f5227d6..d3392df309eeb 100644 --- a/Framework/Core/test/test_Services.cxx +++ b/Framework/Core/test/test_Services.cxx @@ -86,7 +86,7 @@ struct DummyService { BOOST_AUTO_TEST_CASE(TestSerialServices) { using namespace o2::framework; - ServiceRegistryBase registry; + ServiceRegistry registry; DummyService t0{0}; /// We register it pretending to be on thread 0 @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(TestSerialServices) BOOST_AUTO_TEST_CASE(TestGlobalServices) { using namespace o2::framework; - ServiceRegistryBase registry; + ServiceRegistry registry; DummyService t0{0}; /// We register it pretending to be on thread 0 @@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(TestGlobalServices) BOOST_AUTO_TEST_CASE(TestGlobalServices02) { using namespace o2::framework; - ServiceRegistryBase registry; + ServiceRegistry registry; DummyService t0{1}; /// We register it pretending to be on thread 0 @@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(TestGlobalServices02) BOOST_AUTO_TEST_CASE(TestStreamServices) { using namespace o2::framework; - ServiceRegistryBase registry; + ServiceRegistry registry; DummyService t0{0}; DummyService t1{1}; From 07679f73966fd88cf96ce45da3115510f1c96864 Mon Sep 17 00:00:00 2001 From: Peter Hristov <pzhristov@users.noreply.github.com> Date: Thu, 30 Jul 2020 20:33:27 +0200 Subject: [PATCH 0206/1751] Replace the mother and daughter arrays by separate columns. (#4065) Introduce impact parameter in gthe MC collision. Co-authored-by: hristov <Peter.Hristov@cern.ch> --- Analysis/Core/include/Analysis/MC.h | 22 +++++++++---------- Analysis/Tutorials/src/mcHistograms.cxx | 2 +- .../include/Framework/AnalysisDataModel.h | 12 ++++++---- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Analysis/Core/include/Analysis/MC.h b/Analysis/Core/include/Analysis/MC.h index 913188baeccd2..19895d10c1e3b 100644 --- a/Analysis/Core/include/Analysis/MC.h +++ b/Analysis/Core/include/Analysis/MC.h @@ -87,17 +87,17 @@ bool isPhysicalPrimary(TMCParticles& mcParticles, TMCParticle const& particle) if (particle.producedByGenerator()) { // Solution for K0L decayed by Pythia6 // -> - if (particle.mother()[0] != -1) { - auto mother = mcParticles.iteratorAt(particle.mother()[0]); + if (particle.mother0() != -1) { + auto mother = mcParticles.iteratorAt(particle.mother0()); if (std::abs(mother.pdgCode()) == 130) return false; } // <- // check for direct photon in parton shower // -> - if (pdg == 22 && particle.daughter()[0] != -1) { - LOGF(debug, "D %d", particle.daughter()[0]); - auto daughter = mcParticles.iteratorAt(particle.daughter()[0]); + if (pdg == 22 && particle.daughter0() != -1) { + LOGF(debug, "D %d", particle.daughter0()); + auto daughter = mcParticles.iteratorAt(particle.daughter0()); if (daughter.pdgCode() == 22) return false; } @@ -107,8 +107,8 @@ bool isPhysicalPrimary(TMCParticles& mcParticles, TMCParticle const& particle) // Particle produced during transport - LOGF(debug, "M0 %d %d", particle.producedByGenerator(), particle.mother()[0]); - auto mother = mcParticles.iteratorAt(particle.mother()[0]); + LOGF(debug, "M0 %d %d", particle.producedByGenerator(), particle.mother0()); + auto mother = mcParticles.iteratorAt(particle.mother0()); int mpdg = std::abs(mother.pdgCode()); // Check for Sigma0 @@ -132,10 +132,10 @@ bool isPhysicalPrimary(TMCParticles& mcParticles, TMCParticle const& particle) // To be sure that heavy flavor has not been produced in a secondary interaction // Loop back to the generated mother - LOGF(debug, "M0 %d %d", mother.producedByGenerator(), mother.mother()[0]); - while (mother.mother()[0] != -1 && !mother.producedByGenerator()) { - mother = mcParticles.iteratorAt(mother.mother()[0]); - LOGF(debug, "M+ %d %d", mother.producedByGenerator(), mother.mother()[0]); + LOGF(debug, "M0 %d %d", mother.producedByGenerator(), mother.mother0()); + while (mother.mother0() != -1 && !mother.producedByGenerator()) { + mother = mcParticles.iteratorAt(mother.mother0()); + LOGF(debug, "M+ %d %d", mother.producedByGenerator(), mother.mother0()); mpdg = std::abs(mother.pdgCode()); mfl = int(mpdg / std::pow(10, int(std::log10(mpdg)))); } diff --git a/Analysis/Tutorials/src/mcHistograms.cxx b/Analysis/Tutorials/src/mcHistograms.cxx index 49debb6ff7054..b9901d5a86d27 100644 --- a/Analysis/Tutorials/src/mcHistograms.cxx +++ b/Analysis/Tutorials/src/mcHistograms.cxx @@ -39,7 +39,7 @@ struct BTask { { //LOGF(info, "MC. vtx-z = %f", mcCollision.posZ()); LOGF(info, "First: %d | Length: %d", mcParticles.begin().index(), mcParticles.size()); - LOGF(info, "Particles mother: %d", (mcParticles.begin() + 1000).mother()[0]); + LOGF(info, "Particles mother: %d", (mcParticles.begin() + 1000).mother0()); for (auto& mcParticle : mcParticles) { if (MC::isPhysicalPrimary(mcParticles, mcParticle)) { phiH->Fill(mcParticle.phi()); diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 684d62446c95a..8684076c10411 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -459,11 +459,13 @@ DECLARE_SOA_COLUMN(PosY, posY, float); DECLARE_SOA_COLUMN(PosZ, posZ, float); DECLARE_SOA_COLUMN(T, t, float); DECLARE_SOA_COLUMN(Weight, weight, float); +DECLARE_SOA_COLUMN(ImpactParameter, impactParameter, float); } // namespace mccollision DECLARE_SOA_TABLE(McCollisions, "AOD", "MCCOLLISION", o2::soa::Index<>, mccollision::BCId, mccollision::GeneratorsID, - mccollision::PosX, mccollision::PosY, mccollision::PosZ, mccollision::T, mccollision::Weight); + mccollision::PosX, mccollision::PosY, mccollision::PosZ, mccollision::T, mccollision::Weight, + mccollision::ImpactParameter); using McCollision = McCollisions::iterator; namespace mcparticle @@ -472,8 +474,10 @@ DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); DECLARE_SOA_COLUMN(StatusCode, statusCode, int); DECLARE_SOA_COLUMN(Flags, flags, uint8_t); -DECLARE_SOA_COLUMN(Mother, mother, int[2]); // TODO needs INDEX pending NULL columns -DECLARE_SOA_COLUMN(Daughter, daughter, int[2]); // TODO needs INDEX pending NULL columns +DECLARE_SOA_COLUMN(Mother0, mother0, int); +DECLARE_SOA_COLUMN(Mother1, mother1, int); +DECLARE_SOA_COLUMN(Daughter0, daughter0, int); +DECLARE_SOA_COLUMN(Daughter1, daughter1, int); DECLARE_SOA_COLUMN(Weight, weight, float); DECLARE_SOA_COLUMN(Px, px, float); DECLARE_SOA_COLUMN(Py, py, float); @@ -492,7 +496,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(ProducedByGenerator, producedByGenerator, [](uint8_t DECLARE_SOA_TABLE(McParticles, "AOD", "MCPARTICLE", o2::soa::Index<>, mcparticle::McCollisionId, mcparticle::PdgCode, mcparticle::StatusCode, mcparticle::Flags, - mcparticle::Mother, mcparticle::Daughter, mcparticle::Weight, + mcparticle::Mother0, mcparticle::Mother1, mcparticle::Daughter0, mcparticle::Daughter1, mcparticle::Weight, mcparticle::Px, mcparticle::Py, mcparticle::Pz, mcparticle::E, mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, mcparticle::Phi<mcparticle::Px, mcparticle::Py>, From e8ad1302cc4297ae66a6441dbca7ddc1516e14d2 Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Mon, 27 Jul 2020 12:40:00 +0200 Subject: [PATCH 0207/1751] add tof ctf format --- DataFormats/Detectors/TOF/CMakeLists.txt | 2 + .../TOF/include/DataFormatsTOF/CTF.h | 97 +++++++ DataFormats/Detectors/TOF/src/CTF.cxx | 30 ++ .../Detectors/TOF/src/DataFormatsTOFLinkDef.h | 5 + Detectors/TOF/base/include/TOFBase/Digit.h | 23 +- Detectors/TOF/base/src/WindowFiller.cxx | 3 + Detectors/TOF/reconstruction/CMakeLists.txt | 7 +- .../include/TOFReconstruction/CTFCoder.h | 62 ++++ Detectors/TOF/reconstruction/src/CTFCoder.cxx | 269 ++++++++++++++++++ Detectors/TOF/simulation/src/Digitizer.cxx | 3 + 10 files changed, 499 insertions(+), 2 deletions(-) create mode 100644 DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h create mode 100644 DataFormats/Detectors/TOF/src/CTF.cxx create mode 100644 Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h create mode 100644 Detectors/TOF/reconstruction/src/CTFCoder.cxx diff --git a/DataFormats/Detectors/TOF/CMakeLists.txt b/DataFormats/Detectors/TOF/CMakeLists.txt index d991fecf5ba91..d92bfabaaed6a 100644 --- a/DataFormats/Detectors/TOF/CMakeLists.txt +++ b/DataFormats/Detectors/TOF/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library(DataFormatsTOF src/CalibInfoTOF.cxx src/CalibLHCphaseTOF.cxx src/CalibTimeSlewingParamTOF.cxx + src/CTF.cxx PUBLIC_LINK_LIBRARIES O2::ReconstructionDataFormats Boost::serialization) @@ -25,4 +26,5 @@ o2_target_root_dictionary(DataFormatsTOF include/DataFormatsTOF/CalibTimeSlewingParamTOF.h include/DataFormatsTOF/RawDataFormat.h include/DataFormatsTOF/CompressedDataFormat.h + include/DataFormatsTOF/CTF.h ) diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h new file mode 100644 index 0000000000000..113fc24b76e07 --- /dev/null +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h @@ -0,0 +1,97 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file CTF.h +/// \author fnoferin@cern.ch +/// \brief Definitions for TOF CTF data + +#ifndef O2_TOF_CTF_H +#define O2_TOF_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" + +namespace o2 +{ +namespace tof +{ + +class ROFRecord; +class CompClusterExt; + +/// Header for a single CTF +struct CTFHeader { + uint32_t nROFs = 0; /// number of ROFrame in TF + uint32_t nDigits = 0; /// number of digits in TF + uint32_t nPatternBytes = 0; /// number of bytes for explict patterns + uint32_t firstOrbit = 0; /// 1st orbit of TF + uint16_t firstBC = 0; /// 1st BC of TF + + ClassDefNV(CTFHeader, 1); +}; + +/// Compressed but not yet entropy-encoded infos +struct CompressedInfos { + + CTFHeader header; + + /* + ROF = 1/3 orbit = 1188 BC + 1 TF = 128 * 3 = 364 ROF + TIMEFRAME = 2^8 TDC + 1 BC = 2^10 TDC = 4 TIMEFRAME + ROF = 4752 TIMEFRAME < 2^13 TIMEFRAME + + timeFrame = deltaBC/64; + timeTDC = (deltaBC%64)*1024+ dig.getTDC(); + */ + + // ROF header data + std::vector<uint16_t> bcIncROF; /// increment of ROF BC wrt BC of previous ROF + std::vector<uint32_t> orbitIncROF; /// increment of ROF orbit wrt orbit of previous ROF + std::vector<uint32_t> ndigROF; /// number of digits in ROF + + // Hit data + std::vector<uint16_t> timeFrameInc; /// time increment with respect of previous digit in TimeFrame units + std::vector<uint16_t> timeTDCInc; /// time increment with respect of previous digit in TDC channel (about 24.4 ps) within timeframe + std::vector<uint16_t> stripID; /// increment of stripID wrt that of prev. strip + std::vector<uint8_t> chanInStrip; /// channel in strip 0-95 (ordered in time) + std::vector<uint16_t> tot; /// Time-Over-Threshold in TOF channel (about 48.8 ps) + std::vector<uint16_t> pattMap; /// explict patterns container + + CompressedInfos() = default; + + void clear(); + + ClassDefNV(CompressedInfos, 1); +}; + +/// wrapper for the Entropy-encoded clusters of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 10, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { BLCbcIncROF, + BLCorbitIncROF, + BLCndigROF, + BLCtimeFrameInc, + BLCtimeTDCInc, + BLCstripID, + BLCchanInStrip, + BLCtot, + BLCpattMap }; + + ClassDefNV(CTF, 1); +}; + +} // namespace tof +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/TOF/src/CTF.cxx b/DataFormats/Detectors/TOF/src/CTF.cxx new file mode 100644 index 0000000000000..d09858058a918 --- /dev/null +++ b/DataFormats/Detectors/TOF/src/CTF.cxx @@ -0,0 +1,30 @@ +// 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 <stdexcept> +#include <cstring> +#include "Framework/Logger.h" +#include "DataFormatsTOF/CTF.h" + +using namespace o2::tof; + +///________________________________ +void CompressedInfos::clear() +{ + bcIncROF.clear(); + orbitIncROF.clear(); + ndigROF.clear(); + timeFrameInc.clear(); + timeTDCInc.clear(); + stripID.clear(); + chanInStrip.clear(); + tot.clear(); + pattMap.clear(); +} diff --git a/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h b/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h index 001dcd3dce855..12964816922cf 100644 --- a/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h +++ b/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h @@ -25,4 +25,9 @@ #pragma link C++ class std::vector < o2::dataformats::CalibInfoTOFshort> + ; #pragma link C++ class std::vector < o2::dataformats::CalibInfoTOF> + ; +#pragma link C++ class o2::tof::CTFHeader + ; +#pragma link C++ class o2::tof::CompressedInfos + ; +#pragma link C++ class o2::tof::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::tof::CTFHeader, 10, uint32_t> + ; + #endif diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index dd22ac9548f31..9701079002345 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -15,6 +15,7 @@ #include "Rtypes.h" #include "TOFBase/Geo.h" #include "CommonDataFormat/RangeReference.h" +#include "CommonDataFormat/InteractionRecord.h" #include <gsl/span> #include <boost/serialization/base_object.hpp> // for base_object @@ -107,6 +108,23 @@ struct ReadoutWindowData { // 1st entry and number of entries in the full vector of digits // for given trigger (or BC or RO frame) o2::dataformats::RangeReference<int, int> ref; + InteractionRecord mFirstIR{0, 0}; + + const InteractionRecord& getBCData() const { return mFirstIR; } + + void setBCData(int orbit, int bc) + { + mFirstIR.orbit = orbit; + mFirstIR.bc = bc; + } + void setBCData(InteractionRecord& src) + { + mFirstIR.orbit = src.orbit; + mFirstIR.bc = src.bc; + } + void SetBC(int bc) { mFirstIR.bc = bc; } + void SetOrbit(int orbit) { mFirstIR.orbit = orbit; } + gsl::span<const Digit> getBunchChannelData(const gsl::span<const Digit> tfdata) const { // extract the span of channel data for this readout window from the whole TF data @@ -123,7 +141,10 @@ struct ReadoutWindowData { int first() const { return ref.getFirstEntry(); } int size() const { return ref.getEntries(); } - ClassDefNV(ReadoutWindowData, 1); + void setFirstEntry(int first) { ref.setFirstEntry(first); } + void setNEntries(int ne) { ref.setEntries(ne); } + + ClassDefNV(ReadoutWindowData, 2); }; } // namespace tof diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index 418e6fd445bc2..9daeabf8368f5 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -121,6 +121,9 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) int first = mDigitsPerTimeFrame.size(); int ne = digits.size(); ReadoutWindowData info(first, ne); + int orbit_shift = mReadoutWindowData.size() / 3; + int bc_shift = (mReadoutWindowData.size() % 3) * Geo::BC_IN_WINDOW; + info.setBCData(mFirstIR.orbit + orbit_shift, mFirstIR.bc + bc_shift); if (digits.size()) mDigitsPerTimeFrame.insert(mDigitsPerTimeFrame.end(), digits.begin(), digits.end()); mReadoutWindowData.push_back(info); diff --git a/Detectors/TOF/reconstruction/CMakeLists.txt b/Detectors/TOF/reconstruction/CMakeLists.txt index 3bdd192d96c42..0be712150f14b 100644 --- a/Detectors/TOF/reconstruction/CMakeLists.txt +++ b/Detectors/TOF/reconstruction/CMakeLists.txt @@ -13,8 +13,12 @@ o2_add_library(TOFReconstruction src/ClustererTask.cxx src/Encoder.cxx src/DecoderBase.cxx src/Decoder.cxx + src/CTFCoder.cxx PUBLIC_LINK_LIBRARIES O2::TOFBase O2::DataFormatsTOF O2::SimulationDataFormat + O2::CommonDataFormat + O2::DataFormatsTOF + O2::rANS O2::TOFCalibration O2::DetectorsRaw) o2_target_root_dictionary(TOFReconstruction @@ -23,4 +27,5 @@ o2_target_root_dictionary(TOFReconstruction include/TOFReconstruction/ClustererTask.h include/TOFReconstruction/Encoder.h include/TOFReconstruction/DecoderBase.h - include/TOFReconstruction/Decoder.h) + include/TOFReconstruction/Decoder.h + include/TOFReconstruction/CTFCoder.h) diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h new file mode 100644 index 0000000000000..86e84e4601e36 --- /dev/null +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -0,0 +1,62 @@ +// 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 CTFCoder.h +/// \author fnoferin@cern.ch +/// \brief class for entropy encoding/decoding of TOF compressed infos data + +#ifndef O2_TOF_CTFCODER_H +#define O2_TOF_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include "DataFormatsTOF/CTF.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "rANS/rans.h" +#include "TOFBase/Digit.h" + +class TTree; + +namespace o2 +{ +namespace tof +{ + +class CTFCoder +{ + public: + /// entropy-encode clusters to buffer with CTF + template <typename VEC> + static void encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const unsigned char>& pattVec); + + /// entropy decode clusters from buffer with CTF + template <typename VROF, typename VDIG, typename VPAT> + static void decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); + + private: + /// compres compact clusters to CompressedInfos + static void compress(CompressedInfos& cc, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const unsigned char>& pattVec); + + /// decompress CompressedInfos to compact clusters + template <typename VROF, typename VDIG, typename VPAT> + static void decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); + + static void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); + static void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<unsigned char>& pattVec); + + protected: + ClassDefNV(CTFCoder, 1); +}; + +} // namespace tof +} // namespace o2 + +#endif // O2_TOF_CTFCODER_H diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx new file mode 100644 index 0000000000000..e889b3d148a1c --- /dev/null +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -0,0 +1,269 @@ +// 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 CTFCoder.cxx +/// \author fnoferin@cern.ch +/// \brief class for entropy encoding/decoding of TOF compressed digits data + +#include "TOFReconstruction/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::tof; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec) +{ + ec.appendToTree(tree, id.getName()); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, o2::detectors::DetID id, + std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<unsigned char>& pattVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, id.getName(), entry); + decode(ec, rofRecVec, cdigVec, pattVec); +} + +///________________________________ +void CTFCoder::compress(CompressedInfos& cc, + const gsl::span<const ReadoutWindowData>& rofRecVec, + const gsl::span<const Digit>& cdigVec, + const gsl::span<const unsigned char>& pattVec) +{ + // store in the header the orbit of 1st ROF + cc.clear(); + if (!rofRecVec.size()) { + return; + } + const auto& rofRec0 = rofRecVec[0]; + int nrof = rofRecVec.size(); + + cc.header.nROFs = nrof; + cc.header.firstOrbit = rofRec0.getBCData().orbit; + cc.header.firstBC = rofRec0.getBCData().bc; + cc.header.nPatternBytes = pattVec.size(); + cc.header.nDigits = cdigVec.size(); + + cc.bcIncROF.resize(cc.header.nROFs); + cc.orbitIncROF.resize(cc.header.nROFs); + cc.ndigROF.resize(cc.header.nROFs); + // + cc.timeFrameInc.resize(cc.header.nDigits); + cc.timeTDCInc.resize(cc.header.nDigits); + cc.stripID.resize(cc.header.nDigits); + cc.chanInStrip.resize(cc.header.nDigits); + cc.tot.resize(cc.header.nDigits); + cc.pattMap.resize(cc.header.nPatternBytes); + + uint16_t prevBC = cc.header.firstBC; + uint32_t prevOrbit = cc.header.firstOrbit; + + std::vector<Digit> digCopy; + + for (uint32_t irof = 0; irof < rofRecVec.size(); irof++) { + const auto& rofRec = rofRecVec[irof]; + + const auto& intRec = rofRec.getBCData(); + int rofInBC = intRec.toLong(); + // define interaction record + if (intRec.orbit == prevOrbit) { + cc.orbitIncROF[irof] = 0; + cc.bcIncROF[irof] = intRec.bc - prevBC; // store increment of BC if in the same orbit + } else { + cc.orbitIncROF[irof] = intRec.orbit - prevOrbit; + cc.bcIncROF[irof] = intRec.bc; // otherwise, store absolute bc + prevOrbit = intRec.orbit; + } + prevBC = intRec.bc; + auto ndig = rofRec.size(); + cc.ndigROF[irof] = ndig; + + if (!ndig) { // no hits data for this ROF --> not fill + continue; + } + + int idig = rofRec.first(), idigMax = idig + ndig; + + // make a copy of digits + digCopy.clear(); + for (; idig < idigMax; idig++) { + digCopy.emplace_back(cdigVec[idig]); + } + + // sort digits according to time (ascending order) + std::sort(digCopy.begin(), digCopy.end(), + [](o2::tof::Digit a, o2::tof::Digit b) { + if (a.getBC() == b.getBC()) + return a.getTDC() < b.getTDC(); + else + return a.getBC() < b.getBC(); + }); + + int timeframe = 0; + int tdc = 0; + idig = 0; + for (; idig < ndig; idig++) { + const auto& dig = digCopy[idig]; + int deltaBC = dig.getBC() - rofInBC; + int ctimeframe = deltaBC / 64; + int cTDC = (deltaBC % 64) * 1024 + dig.getTDC(); + if (ctimeframe == timeframe) { + cc.timeFrameInc[idig] = 0; + cc.timeTDCInc[idig] = cTDC - tdc; + } else { + cc.timeFrameInc[idig] = ctimeframe - timeframe; + cc.timeTDCInc[idig] = cTDC; + timeframe = ctimeframe; + } + tdc = cTDC; + + int chan = dig.getChannel(); + cc.stripID[idig] = chan / Geo::NPADS; + cc.chanInStrip[idig] = chan % Geo::NPADS; + cc.tot[idig] = dig.getTOT(); + } + } + // store explicit patters as they are + memcpy(cc.pattMap.data(), pattVec.data(), cc.header.nPatternBytes); // RSTODO: do we need this? +} +///___________________________________________________________________________________ +/// entropy-encode digits to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const unsigned char>& pattVec) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, //BLCbcIncROF + MD::EENCODE, //BLCorbitIncROF + MD::EENCODE, //BLCndigROF + MD::EENCODE, //BLCtimeFrameInc + MD::EENCODE, //BLCtimeTDCInc + MD::EENCODE, //BLCstripID + MD::EENCODE, //BLCchanInStrip + MD::EENCODE, //BLCtot + MD::EENCODE, //BLCpattMap + }; + CompressedInfos cc; + compress(cc, rofRecVec, cdigVec, pattVec); + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(cc.header); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODE CTF::get(buff.data())->encode + // clang-format off + ENCODE(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCbcIncROF], &buff); + ENCODE(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCorbitIncROF], &buff); + ENCODE(cc.ndigROF, CTF::BLCndigROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCndigROF], &buff); + ENCODE(cc.timeFrameInc, CTF::BLCtimeFrameInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeFrameInc], &buff); + ENCODE(cc.timeTDCInc, CTF::BLCtimeTDCInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeTDCInc], &buff); + ENCODE(cc.stripID, CTF::BLCstripID, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCstripID], &buff); + ENCODE(cc.chanInStrip, CTF::BLCchanInStrip, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCchanInStrip], &buff); + ENCODE(cc.tot, CTF::BLCtot, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtot], &buff); + ENCODE(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpattMap], &buff); + // clang-format on +} +///___________________________________________________________________________________ +/// decode entropy-encoded digits to standard compact digits +template <typename VROF, typename VDIG, typename VPAT> +void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec) +{ + CompressedInfos cc; + cc.header = ec.getHeader(); + // clang-format off + ec.decode(cc.bcIncROF, CTF::BLCbcIncROF); + ec.decode(cc.orbitIncROF, CTF::BLCorbitIncROF); + ec.decode(cc.ndigROF, CTF::BLCndigROF); + + ec.decode(cc.timeFrameInc, CTF::BLCtimeFrameInc); + ec.decode(cc.timeTDCInc, CTF::BLCtimeTDCInc); + ec.decode(cc.stripID, CTF::BLCstripID); + ec.decode(cc.chanInStrip, CTF::BLCchanInStrip); + ec.decode(cc.tot, CTF::BLCtot); + ec.decode(cc.pattMap, CTF::BLCpattMap); + // clang-format on + // + decompress(cc, rofRecVec, cdigVec, pattVec); +} +///___________________________________________________________________________________ +/// decompress compressed infos to standard compact digits +template <typename VROF, typename VDIG, typename VPAT> +void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec) +{ + rofRecVec.resize(cc.header.nROFs); + cdigVec.resize(cc.header.nDigits); + pattVec.resize(cc.header.nPatternBytes); + + o2::InteractionRecord prevIR(cc.header.firstBC, cc.header.firstOrbit); + uint32_t firstEntry = 0, digCount = 0, stripCount = 0; + for (uint32_t irof = 0; irof < cc.header.nROFs; irof++) { + // restore ROFRecord + auto& rofRec = rofRecVec[irof]; + if (cc.orbitIncROF[irof]) { // new orbit + prevIR.bc = cc.bcIncROF[irof]; // bcInc has absolute meaning + prevIR.orbit += cc.orbitIncROF[irof]; + } else { + prevIR.bc += cc.bcIncROF[irof]; + } + rofRec.setBCData(prevIR); + rofRec.setFirstEntry(firstEntry); + rofRec.setNEntries(cc.ndigROF[irof]); + firstEntry += cc.ndigROF[irof]; + + // restore hit data + uint ctimeframe = 0; + uint ctdc = 0; + + int firstDig = digCount; + + for (uint32_t idig = 0; idig < cc.ndigROF[irof]; idig++) { + auto& digit = cdigVec[digCount]; + if (cc.timeFrameInc[digCount]) { // new time frame + ctdc = cc.timeTDCInc[digCount]; + ctimeframe += cc.timeFrameInc[digCount]; + } else { + ctdc += cc.timeTDCInc[digCount]; + } + + digit.setBC(uint32_t(ctimeframe) * 64 + ctdc / 1024); + digit.setTDC(ctdc % 1024); + digit.setTOT(cc.tot[digCount]); + digit.setChannel(uint32_t(cc.stripID[digCount]) * 96 + cc.chanInStrip[digCount]); + + digCount++; + } + + // sort digits according to strip number within the ROF + if (digCount > firstDig) { + std::partial_sort(cdigVec.begin() + firstDig, cdigVec.begin() + digCount - 1, cdigVec.end(), + [](o2::tof::Digit a, o2::tof::Digit b) { + int str1 = a.getChannel() / 1600; + int str2 = b.getChannel() / 1600; + return (str1 <= str2); + }); + } + } + // explicit patterns + memcpy(pattVec.data(), cc.pattMap.data(), cc.header.nPatternBytes); // RSTODO use swap? + assert(digCount == cc.header.nDigits); + + if (digCount != cc.header.nDigits) { + LOG(ERROR) << "expected " << cc.header.nDigits << " but counted " << digCount << " in ROFRecords"; + throw std::runtime_error("mismatch between expected and counter number of digits"); + } +} diff --git a/Detectors/TOF/simulation/src/Digitizer.cxx b/Detectors/TOF/simulation/src/Digitizer.cxx index 46eded78bd297..14ce608fecf98 100644 --- a/Detectors/TOF/simulation/src/Digitizer.cxx +++ b/Detectors/TOF/simulation/src/Digitizer.cxx @@ -784,6 +784,9 @@ void Digitizer::fillOutputContainer(std::vector<Digit>& digits) int first = mDigitsPerTimeFrame.size(); int ne = digits.size(); ReadoutWindowData info(first, ne); + int orbit_shift = mReadoutWindowData.size() / 3; + int bc_shift = (mReadoutWindowData.size() % 3) * Geo::BC_IN_WINDOW; + info.setBCData(mFirstIR.orbit + orbit_shift, mFirstIR.bc + bc_shift); mDigitsPerTimeFrame.insert(mDigitsPerTimeFrame.end(), digits.begin(), digits.end()); mReadoutWindowData.push_back(info); } From 7bc8edba4832ab7fba2506bb2475795c42799fc7 Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Tue, 28 Jul 2020 12:22:43 +0200 Subject: [PATCH 0208/1751] add tof entropy-encoder spec --- .../TOF/include/DataFormatsTOF/CTF.h | 4 +- DataFormats/Detectors/TOF/src/CTF.cxx | 1 + .../tofworkflow/src/tof-reco-workflow.cxx | 13 +- Detectors/TOF/base/include/TOFBase/Digit.h | 9 +- Detectors/TOF/reconstruction/CMakeLists.txt | 2 +- .../include/TOFReconstruction/CTFCoder.h | 142 +++++++++++++++++- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 135 +---------------- .../src/TOFReconstructionLinkDef.h | 1 + Detectors/TOF/workflow/CMakeLists.txt | 4 +- .../include/TOFWorkflow/EntropyEncoderSpec.h | 45 ++++++ .../TOF/workflow/src/EntropyEncoderSpec.cxx | 74 +++++++++ .../src/TOFDigitizerSpec.cxx | 6 + 12 files changed, 295 insertions(+), 141 deletions(-) create mode 100644 Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h create mode 100644 Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h index 113fc24b76e07..7f6b981ee88cb 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h @@ -58,6 +58,7 @@ struct CompressedInfos { std::vector<uint16_t> bcIncROF; /// increment of ROF BC wrt BC of previous ROF std::vector<uint32_t> orbitIncROF; /// increment of ROF orbit wrt orbit of previous ROF std::vector<uint32_t> ndigROF; /// number of digits in ROF + std::vector<uint32_t> ndiaROF; /// number of diagnostic/pattern words in ROF // Hit data std::vector<uint16_t> timeFrameInc; /// time increment with respect of previous digit in TimeFrame units @@ -65,7 +66,7 @@ struct CompressedInfos { std::vector<uint16_t> stripID; /// increment of stripID wrt that of prev. strip std::vector<uint8_t> chanInStrip; /// channel in strip 0-95 (ordered in time) std::vector<uint16_t> tot; /// Time-Over-Threshold in TOF channel (about 48.8 ps) - std::vector<uint16_t> pattMap; /// explict patterns container + std::vector<uint32_t> pattMap; /// explict patterns container CompressedInfos() = default; @@ -81,6 +82,7 @@ struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 10, uint32_t> { enum Slots { BLCbcIncROF, BLCorbitIncROF, BLCndigROF, + BLCndiaROF, BLCtimeFrameInc, BLCtimeTDCInc, BLCstripID, diff --git a/DataFormats/Detectors/TOF/src/CTF.cxx b/DataFormats/Detectors/TOF/src/CTF.cxx index d09858058a918..ce3559df1b3d6 100644 --- a/DataFormats/Detectors/TOF/src/CTF.cxx +++ b/DataFormats/Detectors/TOF/src/CTF.cxx @@ -21,6 +21,7 @@ void CompressedInfos::clear() bcIncROF.clear(); orbitIncROF.clear(); ndigROF.clear(); + ndiaROF.clear(); timeFrameInc.clear(); timeTDCInc.clear(); stripID.clear(); diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 0f731e193361f..a71dc10c012c3 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -24,6 +24,7 @@ #include "TOFWorkflow/TOFCalibWriterSpec.h" #include "TOFWorkflow/TOFRawWriterSpec.h" #include "TOFWorkflow/CompressedDecodingTask.h" +#include "TOFWorkflow/EntropyEncoderSpec.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigParamSpec.h" #include "TOFWorkflow/RecoWorkflowSpec.h" @@ -46,8 +47,8 @@ // including Framework/runDataProcessing void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { - workflowOptions.push_back(ConfigParamSpec{"input-type", o2::framework::VariantType::String, "digits", {"digits, raw, clusters, TBI"}}); - workflowOptions.push_back(ConfigParamSpec{"output-type", o2::framework::VariantType::String, "clusters,matching-info,calib-info", {"digits,clusters, matching-info, calib-info, TBI"}}); + workflowOptions.push_back(ConfigParamSpec{"input-type", o2::framework::VariantType::String, "digits", {"digits, raw, clusters, ctf"}}); + workflowOptions.push_back(ConfigParamSpec{"output-type", o2::framework::VariantType::String, "clusters,matching-info,calib-info", {"digits, clusters, matching-info, calib-info, raw, ctf"}}); workflowOptions.push_back(ConfigParamSpec{"disable-mc", o2::framework::VariantType::Bool, false, {"disable sending of MC information, TBI"}}); workflowOptions.push_back(ConfigParamSpec{"tof-sectors", o2::framework::VariantType::String, "0-17", {"TOF sector range, e.g. 5-7,8,9 ,TBI"}}); workflowOptions.push_back(ConfigParamSpec{"tof-lanes", o2::framework::VariantType::Int, 1, {"number of parallel lanes up to the matcher, TBI"}}); @@ -104,6 +105,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) bool writecalib = 0; bool writedigit = 0; bool writeraw = 0; + bool writectf = 0; if (outputType.rfind("clusters") < outputType.size()) writecluster = 1; @@ -115,6 +117,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) writedigit = 1; if (outputType.rfind("raw") < outputType.size()) writeraw = 1; + if (outputType.rfind("ctf") < outputType.size()) + writectf = 1; bool dgtinput = 0; if (inputType == "digits") { @@ -201,6 +205,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) specs.emplace_back(o2::tof::getTOFCalibWriterSpec()); } } + if (writectf) { + LOG(INFO) << "Insert TOF CTF encoder"; + specs.emplace_back(o2::tof::getEntropyEncoderSpec()); + } + LOG(INFO) << "Number of active devices = " << specs.size(); return std::move(specs); diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index 9701079002345..70b43d9db884e 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -108,6 +108,7 @@ struct ReadoutWindowData { // 1st entry and number of entries in the full vector of digits // for given trigger (or BC or RO frame) o2::dataformats::RangeReference<int, int> ref; + o2::dataformats::RangeReference<int, int> refDiagnostic; InteractionRecord mFirstIR{0, 0}; const InteractionRecord& getBCData() const { return mFirstIR; } @@ -136,15 +137,21 @@ struct ReadoutWindowData { { ref.setFirstEntry(first); ref.setEntries(ne); + refDiagnostic.setFirstEntry(0); + refDiagnostic.setEntries(0); } int first() const { return ref.getFirstEntry(); } int size() const { return ref.getEntries(); } + int firstDia() const { return refDiagnostic.getFirstEntry(); } + int sizeDia() const { return refDiagnostic.getEntries(); } void setFirstEntry(int first) { ref.setFirstEntry(first); } void setNEntries(int ne) { ref.setEntries(ne); } + void setFirstEntryDia(int first) { refDiagnostic.setFirstEntry(first); } + void setNEntriesDia(int ne) { refDiagnostic.setEntries(ne); } - ClassDefNV(ReadoutWindowData, 2); + ClassDefNV(ReadoutWindowData, 3); }; } // namespace tof diff --git a/Detectors/TOF/reconstruction/CMakeLists.txt b/Detectors/TOF/reconstruction/CMakeLists.txt index 0be712150f14b..d577164f5202e 100644 --- a/Detectors/TOF/reconstruction/CMakeLists.txt +++ b/Detectors/TOF/reconstruction/CMakeLists.txt @@ -18,7 +18,7 @@ o2_add_library(TOFReconstruction O2::SimulationDataFormat O2::CommonDataFormat O2::DataFormatsTOF - O2::rANS + O2::rANS O2::DPLUtils O2::TOFCalibration O2::DetectorsRaw) o2_target_root_dictionary(TOFReconstruction diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index 86e84e4601e36..26607797f8e6b 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -35,7 +35,7 @@ class CTFCoder public: /// entropy-encode clusters to buffer with CTF template <typename VEC> - static void encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const unsigned char>& pattVec); + static void encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec); /// entropy decode clusters from buffer with CTF template <typename VROF, typename VDIG, typename VPAT> @@ -43,19 +43,155 @@ class CTFCoder private: /// compres compact clusters to CompressedInfos - static void compress(CompressedInfos& cc, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const unsigned char>& pattVec); + static void compress(CompressedInfos& cc, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec); /// decompress CompressedInfos to compact clusters template <typename VROF, typename VDIG, typename VPAT> static void decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); static void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); - static void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<unsigned char>& pattVec); + static void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec); protected: ClassDefNV(CTFCoder, 1); }; +///___________________________________________________________________________________ +/// entropy-encode digits to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, //BLCbcIncROF + MD::EENCODE, //BLCorbitIncROF + MD::EENCODE, //BLCndigROF + MD::EENCODE, //BLCndiaROF + MD::EENCODE, //BLCtimeFrameInc + MD::EENCODE, //BLCtimeTDCInc + MD::EENCODE, //BLCstripID + MD::EENCODE, //BLCchanInStrip + MD::EENCODE, //BLCtot + MD::EENCODE, //BLCpattMap + }; + CompressedInfos cc; + compress(cc, rofRecVec, cdigVec, pattVec); + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(cc.header); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODE CTF::get(buff.data())->encode + // clang-format off + ENCODE(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCbcIncROF], &buff); + ENCODE(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCorbitIncROF], &buff); + ENCODE(cc.ndigROF, CTF::BLCndigROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCndigROF], &buff); + ENCODE(cc.ndiaROF, CTF::BLCndiaROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCndiaROF], &buff); + ENCODE(cc.timeFrameInc, CTF::BLCtimeFrameInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeFrameInc], &buff); + ENCODE(cc.timeTDCInc, CTF::BLCtimeTDCInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeTDCInc], &buff); + ENCODE(cc.stripID, CTF::BLCstripID, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCstripID], &buff); + ENCODE(cc.chanInStrip, CTF::BLCchanInStrip, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCchanInStrip], &buff); + ENCODE(cc.tot, CTF::BLCtot, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtot], &buff); + ENCODE(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpattMap], &buff); + // clang-format on +} +///___________________________________________________________________________________ +/// decode entropy-encoded digits to standard compact digits +template <typename VROF, typename VDIG, typename VPAT> +void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec) +{ + CompressedInfos cc; + cc.header = ec.getHeader(); + // clang-format off + ec.decode(cc.bcIncROF, CTF::BLCbcIncROF); + ec.decode(cc.orbitIncROF, CTF::BLCorbitIncROF); + ec.decode(cc.ndigROF, CTF::BLCndigROF); + ec.decode(cc.ndiaROF, CTF::BLCndiaROF); + + ec.decode(cc.timeFrameInc, CTF::BLCtimeFrameInc); + ec.decode(cc.timeTDCInc, CTF::BLCtimeTDCInc); + ec.decode(cc.stripID, CTF::BLCstripID); + ec.decode(cc.chanInStrip, CTF::BLCchanInStrip); + ec.decode(cc.tot, CTF::BLCtot); + ec.decode(cc.pattMap, CTF::BLCpattMap); + // clang-format on + // + decompress(cc, rofRecVec, cdigVec, pattVec); +} +///___________________________________________________________________________________ +/// decompress compressed infos to standard compact digits +template <typename VROF, typename VDIG, typename VPAT> +void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec) +{ + rofRecVec.resize(cc.header.nROFs); + cdigVec.resize(cc.header.nDigits); + pattVec.resize(cc.header.nPatternBytes); + + o2::InteractionRecord prevIR(cc.header.firstBC, cc.header.firstOrbit); + uint32_t firstEntry = 0, digCount = 0, stripCount = 0, ndiagnostic = 0; + for (uint32_t irof = 0; irof < cc.header.nROFs; irof++) { + // restore ROFRecord + auto& rofRec = rofRecVec[irof]; + if (cc.orbitIncROF[irof]) { // new orbit + prevIR.bc = cc.bcIncROF[irof]; // bcInc has absolute meaning + prevIR.orbit += cc.orbitIncROF[irof]; + } else { + prevIR.bc += cc.bcIncROF[irof]; + } + rofRec.setBCData(prevIR); + rofRec.setFirstEntry(firstEntry); + rofRec.setNEntries(cc.ndigROF[irof]); + rofRec.setFirstEntryDia(ndiagnostic); + rofRec.setNEntriesDia(cc.ndiaROF[irof]); + firstEntry += cc.ndigROF[irof]; + ndiagnostic += cc.ndiaROF[irof]; + + // restore hit data + uint ctimeframe = 0; + uint ctdc = 0; + + int firstDig = digCount; + + for (uint32_t idig = 0; idig < cc.ndigROF[irof]; idig++) { + auto& digit = cdigVec[digCount]; + if (cc.timeFrameInc[digCount]) { // new time frame + ctdc = cc.timeTDCInc[digCount]; + ctimeframe += cc.timeFrameInc[digCount]; + } else { + ctdc += cc.timeTDCInc[digCount]; + } + + digit.setBC(uint32_t(ctimeframe) * 64 + ctdc / 1024); + digit.setTDC(ctdc % 1024); + digit.setTOT(cc.tot[digCount]); + digit.setChannel(uint32_t(cc.stripID[digCount]) * 96 + cc.chanInStrip[digCount]); + + digCount++; + } + + // sort digits according to strip number within the ROF + if (digCount > firstDig) { + std::partial_sort(cdigVec.begin() + firstDig, cdigVec.begin() + digCount - 1, cdigVec.end(), + [](o2::tof::Digit a, o2::tof::Digit b) { + int str1 = a.getChannel() / 1600; + int str2 = b.getChannel() / 1600; + return (str1 <= str2); + }); + } + } + // explicit patterns + memcpy(pattVec.data(), cc.pattMap.data(), cc.header.nPatternBytes); // RSTODO use swap? + assert(digCount == cc.header.nDigits); + + if (digCount != cc.header.nDigits) { + LOG(ERROR) << "expected " << cc.header.nDigits << " but counted " << digCount << " in ROFRecords"; + throw std::runtime_error("mismatch between expected and counter number of digits"); + } +} + } // namespace tof } // namespace o2 diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index e889b3d148a1c..ee77af33e7958 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -28,7 +28,7 @@ void CTFCoder::appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec) ///___________________________________________________________________________________ // extract and decode data from the tree void CTFCoder::readFromTree(TTree& tree, int entry, o2::detectors::DetID id, - std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<unsigned char>& pattVec) + std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec) { assert(entry >= 0 && entry < tree.GetEntries()); CTF ec; @@ -40,7 +40,7 @@ void CTFCoder::readFromTree(TTree& tree, int entry, o2::detectors::DetID id, void CTFCoder::compress(CompressedInfos& cc, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, - const gsl::span<const unsigned char>& pattVec) + const gsl::span<const uint32_t>& pattVec) { // store in the header the orbit of 1st ROF cc.clear(); @@ -59,6 +59,7 @@ void CTFCoder::compress(CompressedInfos& cc, cc.bcIncROF.resize(cc.header.nROFs); cc.orbitIncROF.resize(cc.header.nROFs); cc.ndigROF.resize(cc.header.nROFs); + cc.ndiaROF.resize(cc.header.nROFs); // cc.timeFrameInc.resize(cc.header.nDigits); cc.timeTDCInc.resize(cc.header.nDigits); @@ -89,6 +90,7 @@ void CTFCoder::compress(CompressedInfos& cc, prevBC = intRec.bc; auto ndig = rofRec.size(); cc.ndigROF[irof] = ndig; + cc.ndiaROF[irof] = rofRec.sizeDia(); if (!ndig) { // no hits data for this ROF --> not fill continue; @@ -138,132 +140,3 @@ void CTFCoder::compress(CompressedInfos& cc, // store explicit patters as they are memcpy(cc.pattMap.data(), pattVec.data(), cc.header.nPatternBytes); // RSTODO: do we need this? } -///___________________________________________________________________________________ -/// entropy-encode digits to buffer with CTF -template <typename VEC> -void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const unsigned char>& pattVec) -{ - using MD = o2::ctf::Metadata::OptStore; - // what to do which each field: see o2::ctd::Metadata explanation - constexpr MD optField[CTF::getNBlocks()] = { - MD::EENCODE, //BLCbcIncROF - MD::EENCODE, //BLCorbitIncROF - MD::EENCODE, //BLCndigROF - MD::EENCODE, //BLCtimeFrameInc - MD::EENCODE, //BLCtimeTDCInc - MD::EENCODE, //BLCstripID - MD::EENCODE, //BLCchanInStrip - MD::EENCODE, //BLCtot - MD::EENCODE, //BLCpattMap - }; - CompressedInfos cc; - compress(cc, rofRecVec, cdigVec, pattVec); - auto ec = CTF::create(buff); - using ECB = CTF::base; - - ec->setHeader(cc.header); - ec->getANSHeader().majorVersion = 0; - ec->getANSHeader().minorVersion = 1; - // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec -#define ENCODE CTF::get(buff.data())->encode - // clang-format off - ENCODE(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCbcIncROF], &buff); - ENCODE(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCorbitIncROF], &buff); - ENCODE(cc.ndigROF, CTF::BLCndigROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCndigROF], &buff); - ENCODE(cc.timeFrameInc, CTF::BLCtimeFrameInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeFrameInc], &buff); - ENCODE(cc.timeTDCInc, CTF::BLCtimeTDCInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeTDCInc], &buff); - ENCODE(cc.stripID, CTF::BLCstripID, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCstripID], &buff); - ENCODE(cc.chanInStrip, CTF::BLCchanInStrip, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCchanInStrip], &buff); - ENCODE(cc.tot, CTF::BLCtot, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtot], &buff); - ENCODE(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpattMap], &buff); - // clang-format on -} -///___________________________________________________________________________________ -/// decode entropy-encoded digits to standard compact digits -template <typename VROF, typename VDIG, typename VPAT> -void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec) -{ - CompressedInfos cc; - cc.header = ec.getHeader(); - // clang-format off - ec.decode(cc.bcIncROF, CTF::BLCbcIncROF); - ec.decode(cc.orbitIncROF, CTF::BLCorbitIncROF); - ec.decode(cc.ndigROF, CTF::BLCndigROF); - - ec.decode(cc.timeFrameInc, CTF::BLCtimeFrameInc); - ec.decode(cc.timeTDCInc, CTF::BLCtimeTDCInc); - ec.decode(cc.stripID, CTF::BLCstripID); - ec.decode(cc.chanInStrip, CTF::BLCchanInStrip); - ec.decode(cc.tot, CTF::BLCtot); - ec.decode(cc.pattMap, CTF::BLCpattMap); - // clang-format on - // - decompress(cc, rofRecVec, cdigVec, pattVec); -} -///___________________________________________________________________________________ -/// decompress compressed infos to standard compact digits -template <typename VROF, typename VDIG, typename VPAT> -void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec) -{ - rofRecVec.resize(cc.header.nROFs); - cdigVec.resize(cc.header.nDigits); - pattVec.resize(cc.header.nPatternBytes); - - o2::InteractionRecord prevIR(cc.header.firstBC, cc.header.firstOrbit); - uint32_t firstEntry = 0, digCount = 0, stripCount = 0; - for (uint32_t irof = 0; irof < cc.header.nROFs; irof++) { - // restore ROFRecord - auto& rofRec = rofRecVec[irof]; - if (cc.orbitIncROF[irof]) { // new orbit - prevIR.bc = cc.bcIncROF[irof]; // bcInc has absolute meaning - prevIR.orbit += cc.orbitIncROF[irof]; - } else { - prevIR.bc += cc.bcIncROF[irof]; - } - rofRec.setBCData(prevIR); - rofRec.setFirstEntry(firstEntry); - rofRec.setNEntries(cc.ndigROF[irof]); - firstEntry += cc.ndigROF[irof]; - - // restore hit data - uint ctimeframe = 0; - uint ctdc = 0; - - int firstDig = digCount; - - for (uint32_t idig = 0; idig < cc.ndigROF[irof]; idig++) { - auto& digit = cdigVec[digCount]; - if (cc.timeFrameInc[digCount]) { // new time frame - ctdc = cc.timeTDCInc[digCount]; - ctimeframe += cc.timeFrameInc[digCount]; - } else { - ctdc += cc.timeTDCInc[digCount]; - } - - digit.setBC(uint32_t(ctimeframe) * 64 + ctdc / 1024); - digit.setTDC(ctdc % 1024); - digit.setTOT(cc.tot[digCount]); - digit.setChannel(uint32_t(cc.stripID[digCount]) * 96 + cc.chanInStrip[digCount]); - - digCount++; - } - - // sort digits according to strip number within the ROF - if (digCount > firstDig) { - std::partial_sort(cdigVec.begin() + firstDig, cdigVec.begin() + digCount - 1, cdigVec.end(), - [](o2::tof::Digit a, o2::tof::Digit b) { - int str1 = a.getChannel() / 1600; - int str2 = b.getChannel() / 1600; - return (str1 <= str2); - }); - } - } - // explicit patterns - memcpy(pattVec.data(), cc.pattMap.data(), cc.header.nPatternBytes); // RSTODO use swap? - assert(digCount == cc.header.nDigits); - - if (digCount != cc.header.nDigits) { - LOG(ERROR) << "expected " << cc.header.nDigits << " but counted " << digCount << " in ROFRecords"; - throw std::runtime_error("mismatch between expected and counter number of digits"); - } -} diff --git a/Detectors/TOF/reconstruction/src/TOFReconstructionLinkDef.h b/Detectors/TOF/reconstruction/src/TOFReconstructionLinkDef.h index e996ffbdd4b9d..a8cd7a6c2c067 100644 --- a/Detectors/TOF/reconstruction/src/TOFReconstructionLinkDef.h +++ b/Detectors/TOF/reconstruction/src/TOFReconstructionLinkDef.h @@ -20,5 +20,6 @@ #pragma link C++ class o2::tof::ClustererTask + ; #pragma link C++ class o2::tof::raw::Encoder + ; #pragma link C++ class o2::tof::compressed::Decoder + ; +#pragma link C++ class o2::tof::CTFCoder + ; #endif diff --git a/Detectors/TOF/workflow/CMakeLists.txt b/Detectors/TOF/workflow/CMakeLists.txt index 94d4cfcc7a34e..369d09342f875 100644 --- a/Detectors/TOF/workflow/CMakeLists.txt +++ b/Detectors/TOF/workflow/CMakeLists.txt @@ -17,5 +17,5 @@ o2_add_library(TOFWorkflowUtils src/TOFRawWriterSpec.cxx src/CompressedDecodingTask.cxx src/CompressedInspectorTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::TOFBase O2::DataFormatsTOF - O2::TOFReconstruction) + src/EntropyEncoderSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction) diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..11d50e09e10fd --- /dev/null +++ b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h @@ -0,0 +1,45 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert clusters streams to CTF (EncodedBlocks) + +#ifndef O2_TOF_ENTROPYENCODER_SPEC +#define O2_TOF_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "Headers/DataHeader.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace tof +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace tof +} // namespace o2 + +#endif diff --git a/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..a2b7ce68d86f3 --- /dev/null +++ b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,74 @@ +// 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 EntropyEncoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "TOFBase/Digit.h" +#include "TOFReconstruction/CTFCoder.h" +#include "TOFWorkflow/EntropyEncoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto compDigits = pc.inputs().get<gsl::span<Digit>>("compClusters"); + auto pspan = pc.inputs().get<gsl::span<uint32_t>>("patterns"); + auto rofs = pc.inputs().get<gsl::span<ReadoutWindowData>>("ROframes"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{o2::header::gDataOriginTOF, "CTFDATA", 0, Lifetime::Timeframe}); + CTFCoder::encode(buffer, rofs, compDigits, pspan); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + // eeb->print(); + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for TOF in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "%s Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots TOF", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("compDigits", o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe); + inputs.emplace_back("patterns", o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); + inputs.emplace_back("ROframes", o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "tof-entropy-encoder", + inputs, + Outputs{{o2::header::gDataOriginTOF, "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{}}; +} + +} // namespace tof +} // namespace o2 diff --git a/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx index e2df6005a7f38..75be3e028db3b 100644 --- a/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx @@ -163,6 +163,11 @@ class TOFDPLDigitizerTask : public o2::base::BaseDPLDigitizer pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITSMCTR", 0, Lifetime::Timeframe}, *mcLabVecOfVec); } pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, *readoutwindow); + + // send empty pattern from digitizer (it may change in future) + static std::vector<uint32_t> patterns; + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, patterns); + LOG(INFO) << "TOF: Sending ROMode= " << roMode << " to GRPUpdater"; pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ROMode", 0, Lifetime::Timeframe}, roMode); @@ -199,6 +204,7 @@ DataProcessorSpec getTOFDigitizerSpec(int channel, bool useCCDB, bool mctruth) std::vector<OutputSpec> outputs; outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); if (mctruth) { outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITSMCTR", 0, Lifetime::Timeframe); } From f17f0be0d6c1415aca0b00975edb8fe54d6fc16f Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Wed, 29 Jul 2020 12:15:14 +0200 Subject: [PATCH 0209/1751] add Entropy(De/En)coder specs --- Detectors/CTF/workflow/CMakeLists.txt | 1 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 ++ Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 13 ++++ .../tofworkflow/src/tof-reco-workflow.cxx | 17 +++-- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 2 + Detectors/TOF/workflow/CMakeLists.txt | 7 ++ .../include/TOFWorkflow/DigitReaderSpec.h | 2 + .../include/TOFWorkflow/EntropyDecoderSpec.h | 44 +++++++++++ .../TOF/workflow/src/DigitReaderSpec.cxx | 15 +++- .../TOF/workflow/src/EntropyDecoderSpec.cxx | 74 +++++++++++++++++++ .../TOF/workflow/src/EntropyEncoderSpec.cxx | 5 +- .../TOF/workflow/src/TOFDigitWriterSpec.cxx | 9 +++ .../workflow/src/entropy-encoder-workflow.cxx | 39 ++++++++++ 13 files changed, 224 insertions(+), 12 deletions(-) create mode 100644 Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h create mode 100644 Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/TOF/workflow/src/entropy-encoder-workflow.cxx diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index 9202a1cfffb55..ece52e2fc9270 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -15,6 +15,7 @@ o2_add_library(CTFWorkflow O2::DetectorsCommonDataFormats O2::DataFormatsITSMFT O2::DataFormatsTPC + O2::DataFormatsTOF O2::DataFormatsParameters O2::ITSMFTWorkflow O2::TPCWorkflow diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 1a524c5418621..2b26bbf251859 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -26,6 +26,7 @@ #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" #include "DataFormatsFT0/CTF.h" +#include "DataFormatsTOF/CTF.h" #include "Algorithm/RangeTokenizer.h" using namespace o2::framework; @@ -133,6 +134,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::TOF; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::tof::CTF)); + o2::tof::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + mTimer.Stop(); LOG(INFO) << "Read CTF " << inputFile << " in " << mTimer.CpuTime() - cput << " s"; diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 8178884e49c4a..aa2b6586a4948 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -26,6 +26,7 @@ #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" #include "DataFormatsFT0/CTF.h" +#include "DataFormatsTOF/CTF.h" using namespace o2::framework; @@ -106,6 +107,16 @@ void CTFWriterSpec::run(ProcessingContext& pc) header.detectors.set(det); } + det = DetID::TOF; + if (isPresent(det) && pc.inputs().isValid(det.getName())) { + auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); + const auto ctfImage = o2::tof::CTF::getImage(ctfBuffer.data()); + LOG(INFO) << "CTF for " << det.getName(); + ctfImage.print(); + ctfImage.appendToTree(ctfTree, det.getName()); + header.detectors.set(det); + } + appendToTree(ctfTree, "CTFHeader", header); ctfTree.SetEntries(1); @@ -125,9 +136,11 @@ void CTFWriterSpec::endOfStream(EndOfStreamContext& ec) DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run) { std::vector<InputSpec> inputs; + LOG(INFO) << "Det list:"; for (auto id = DetID::First; id <= DetID::Last; id++) { if (dets[id]) { inputs.emplace_back(DetID::getName(id), DetID::getDataOrigin(id), "CTFDATA", 0, Lifetime::Timeframe); + LOG(INFO) << "Det " << DetID::getName(id) << " added"; } } return DataProcessorSpec{ diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index a71dc10c012c3..181a293401b4b 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -25,6 +25,7 @@ #include "TOFWorkflow/TOFRawWriterSpec.h" #include "TOFWorkflow/CompressedDecodingTask.h" #include "TOFWorkflow/EntropyEncoderSpec.h" +#include "TOFWorkflow/EntropyDecoderSpec.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigParamSpec.h" #include "TOFWorkflow/RecoWorkflowSpec.h" @@ -121,16 +122,17 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) writectf = 1; bool dgtinput = 0; + bool clusterinput = 0; + bool rawinput = 0; + bool ctfinput = 0; if (inputType == "digits") { dgtinput = 1; - } - bool clusterinput = 0; - if (inputType == "clusters") { + } else if (inputType == "clusters") { clusterinput = 1; - } - bool rawinput = 0; - if (inputType == "raw") { + } else if (inputType == "raw") { rawinput = 1; + } else if (inputType == "ctf") { + ctfinput = 1; } auto useMC = !cfgc.options().get<bool>("disable-mc"); @@ -173,6 +175,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) LOG(INFO) << "Insert TOF Digit Writer"; specs.emplace_back(o2::tof::getTOFDigitWriterSpec(0)); } + } else if (ctfinput) { + LOG(INFO) << "Insert TOF CTF decoder"; + specs.emplace_back(o2::tof::getEntropyDecoderSpec()); } if (!clusterinput && writecluster) { diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index ee77af33e7958..ae033a3219018 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -50,6 +50,8 @@ void CTFCoder::compress(CompressedInfos& cc, const auto& rofRec0 = rofRecVec[0]; int nrof = rofRecVec.size(); + printf("TOF compress %d ReadoutWindow with %ld digits\n", nrof, cdigVec.size()); + cc.header.nROFs = nrof; cc.header.firstOrbit = rofRec0.getBCData().orbit; cc.header.firstBC = rofRec0.getBCData().bc; diff --git a/Detectors/TOF/workflow/CMakeLists.txt b/Detectors/TOF/workflow/CMakeLists.txt index 369d09342f875..1cda6cfabe976 100644 --- a/Detectors/TOF/workflow/CMakeLists.txt +++ b/Detectors/TOF/workflow/CMakeLists.txt @@ -18,4 +18,11 @@ o2_add_library(TOFWorkflowUtils src/CompressedDecodingTask.cxx src/CompressedInspectorTask.cxx src/EntropyEncoderSpec.cxx + src/EntropyDecoderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction) + +o2_add_executable(entropy-encoder-workflow + SOURCES src/entropy-encoder-workflow.cxx + COMPONENT_NAME tof + PUBLIC_LINK_LIBRARIES O2::TOFWorkflow) + diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/DigitReaderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflow/DigitReaderSpec.h index 79fbd2f450452..e4e3acca37947 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/DigitReaderSpec.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/DigitReaderSpec.h @@ -38,11 +38,13 @@ class DigitReader : public Task private: int mState = 0; + int mCurrentEntry = 0; bool mUseMC = true; std::unique_ptr<TFile> mFile = nullptr; std::vector<o2::tof::Digit> mDigits, *mPdigits = &mDigits; std::vector<o2::tof::ReadoutWindowData> mRow, *mProw = &mRow; std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>> mLabels, *mPlabels = &mLabels; + std::vector<uint32_t> mPatterns, *mPpatterns = &mPatterns; }; /// create a processor spec diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..a654b3aa938b0 --- /dev/null +++ b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h @@ -0,0 +1,44 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to FT0 digit/channels strean + +#ifndef O2_TOF_ENTROPYDECODER_SPEC +#define O2_TOF_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace tof +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace tof +} // namespace o2 + +#endif diff --git a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx index c2a3bfb3a9d94..39c1872d39af4 100644 --- a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx @@ -51,16 +51,18 @@ void DigitReader::run(ProcessingContext& pc) if (treeDig) { treeDig->SetBranchAddress("TOFDigit", &mPdigits); treeDig->SetBranchAddress("TOFReadoutWindow", &mProw); + treeDig->SetBranchAddress("TOFPatterns", &mPpatterns); if (mUseMC) { treeDig->SetBranchAddress("TOFDigitMCTruth", &mPlabels); } - treeDig->GetEntry(0); + treeDig->GetEntry(mCurrentEntry); // add digits loaded in the output snapshot pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, mDigits); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, mRow); + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, mPatterns); if (mUseMC) pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITSMCTR", 0, Lifetime::Timeframe}, mLabels); @@ -73,9 +75,13 @@ void DigitReader::run(ProcessingContext& pc) return; } - mState = 2; - //pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); - pc.services().get<ControlService>().endOfStream(); + mCurrentEntry++; + + if (mCurrentEntry >= treeDig->GetEntries()) { + mState = 2; + //pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); + pc.services().get<ControlService>().endOfStream(); + } } DataProcessorSpec getDigitReaderSpec(bool useMC) @@ -86,6 +92,7 @@ DataProcessorSpec getDigitReaderSpec(bool useMC) if (useMC) { outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITSMCTR", 0, Lifetime::Timeframe); } + outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "ROMode", 0, Lifetime::Timeframe); return DataProcessorSpec{ diff --git a/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..21c52fea23f17 --- /dev/null +++ b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,74 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "TOFReconstruction/CTFCoder.h" +#include "TOFWorkflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& digits = pc.outputs().make<std::vector<Digit>>(OutputRef{"digits"}); + auto& row = pc.outputs().make<std::vector<ReadoutWindowData>>(OutputRef{"row"}); + auto& patterns = pc.outputs().make<std::vector<uint32_t>>(OutputRef{"patterns"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::tof::CTF::getImage(buff.data()); + CTFCoder::decode(ctfImage, row, digits, patterns); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << digits.size() << " digits in " << row.size() << " ROF in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "TOF Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"digits"}, o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, + OutputSpec{{"row"}, o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, + OutputSpec{{"patterns"}, o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "tof-entropy-decoder", + Inputs{InputSpec{"ctf", o2::header::gDataOriginTOF, "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{}}; +} + +} // namespace tof +} // namespace o2 diff --git a/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx index a2b7ce68d86f3..3b80f3432219c 100644 --- a/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx @@ -35,7 +35,7 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); mTimer.Start(false); - auto compDigits = pc.inputs().get<gsl::span<Digit>>("compClusters"); + auto compDigits = pc.inputs().get<gsl::span<Digit>>("compDigits"); auto pspan = pc.inputs().get<gsl::span<uint32_t>>("patterns"); auto rofs = pc.inputs().get<gsl::span<ReadoutWindowData>>("ROframes"); @@ -47,11 +47,12 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) // eeb->print(); mTimer.Stop(); LOG(INFO) << "Created encoded data of size " << eeb->size() << " for TOF in " << mTimer.CpuTime() - cput << " s"; + // pc.services().get<ControlService>().endOfStream(); } void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) { - LOGF(INFO, "%s Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots TOF", + LOGF(INFO, "TOF Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } diff --git a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx index efc394950385e..bd4d664bf7c5f 100644 --- a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx @@ -26,6 +26,7 @@ template <typename T> using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; using OutputType = std::vector<o2::tof::Digit>; using ReadoutWinType = std::vector<o2::tof::ReadoutWindowData>; +using PatternType = std::vector<uint32_t>; using LabelsType = std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>; using namespace o2::header; @@ -52,6 +53,9 @@ DataProcessorSpec getTOFDigitWriterSpec(bool useMC) auto loggerROW = [nCalls](ReadoutWinType const& row) { LOG(INFO) << "RECEIVED READOUT WINDOWS " << row.size(); }; + auto loggerPatterns = [nCalls](PatternType const& patterns) { + LOG(INFO) << "RECEIVED PATTERNS " << patterns.size(); + }; return MakeRootTreeWriterSpec("TOFDigitWriter", "tofdigits.root", "o2sim", @@ -68,6 +72,11 @@ DataProcessorSpec getTOFDigitWriterSpec(bool useMC) "rowindow-branch-name", 1, loggerROW}, + BranchDefinition<PatternType>{InputSpec{"patterns", gDataOriginTOF, "PATTERNS", 0}, + "TOFPatterns", + "patterns-branch-name", + 1, + loggerPatterns}, BranchDefinition<LabelsType>{InputSpec{"labels", gDataOriginTOF, "DIGITSMCTR", 0}, "TOFDigitMCTruth", (useMC ? 1 : 0), // one branch if mc labels enabled diff --git a/Detectors/TOF/workflow/src/entropy-encoder-workflow.cxx b/Detectors/TOF/workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..acf2045d728e8 --- /dev/null +++ b/Detectors/TOF/workflow/src/entropy-encoder-workflow.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. + +#include "TOFWorkflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::tof::getEntropyEncoderSpec()); + return wf; +} From 54883bcae38a1fb95c17ca74f6b264ae444ef05b Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Thu, 30 Jul 2020 09:17:10 +0200 Subject: [PATCH 0210/1751] fix for reading from ctf --- .../tofworkflow/src/tof-reco-workflow.cxx | 6 ++++ Detectors/TOF/base/include/TOFBase/Digit.h | 4 +++ .../include/TOFReconstruction/CTFCoder.h | 35 ++++++++++++++----- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 11 +++--- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 181a293401b4b..9e7dc66a2d20a 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -178,6 +178,12 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } else if (ctfinput) { LOG(INFO) << "Insert TOF CTF decoder"; specs.emplace_back(o2::tof::getEntropyDecoderSpec()); + + if (writedigit && !disableRootOutput) { + // add TOF digit writer without mc labels + LOG(INFO) << "Insert TOF Digit Writer"; + specs.emplace_back(o2::tof::getTOFDigitWriterSpec(0)); + } } if (!clusterinput && writecluster) { diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index 70b43d9db884e..0e66989d4360d 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -39,6 +39,10 @@ class Digit { return ((static_cast<ULong64_t>(bc) << 18) + channel); // channel in the least significant bits; then shift by 18 bits (which cover the total number of channels) to write the BC number } + ULong64_t getOrderingKey() + { + return getOrderingKey(mChannel, mBC, mTDC); + } Int_t getChannel() const { return mChannel; } void setChannel(Int_t channel) { mChannel = channel; } diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index 26607797f8e6b..e024064d713d7 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -129,6 +129,7 @@ void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdig rofRecVec.resize(cc.header.nROFs); cdigVec.resize(cc.header.nDigits); pattVec.resize(cc.header.nPatternBytes); + std::vector<Digit> digCopy; o2::InteractionRecord prevIR(cc.header.firstBC, cc.header.firstOrbit); uint32_t firstEntry = 0, digCount = 0, stripCount = 0, ndiagnostic = 0; @@ -149,22 +150,30 @@ void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdig firstEntry += cc.ndigROF[irof]; ndiagnostic += cc.ndiaROF[irof]; + if (!cc.ndigROF[irof]) + continue; + // restore hit data uint ctimeframe = 0; uint ctdc = 0; int firstDig = digCount; + int BCrow = prevIR.orbit * Geo::BC_IN_ORBIT + prevIR.bc; + + digCopy.resize(cc.ndigROF[irof]); for (uint32_t idig = 0; idig < cc.ndigROF[irof]; idig++) { - auto& digit = cdigVec[digCount]; + auto& digit = digCopy[idig]; //cdigVec[digCount]; + printf("%d) TF=%d, TDC=%d, STRIP=%d, CH=%d\n", idig, cc.timeFrameInc[digCount], cc.timeTDCInc[digCount], cc.stripID[digCount], cc.chanInStrip[digCount]); if (cc.timeFrameInc[digCount]) { // new time frame ctdc = cc.timeTDCInc[digCount]; ctimeframe += cc.timeFrameInc[digCount]; } else { ctdc += cc.timeTDCInc[digCount]; } + printf("BC=%d, TDC=%d, TOT=%d, CH=%d \n", uint32_t(ctimeframe) * 64 + ctdc / 1024 + BCrow, ctdc % 1024, cc.tot[digCount], uint32_t(cc.stripID[digCount]) * 96 + cc.chanInStrip[digCount]); - digit.setBC(uint32_t(ctimeframe) * 64 + ctdc / 1024); + digit.setBC(uint32_t(ctimeframe) * 64 + ctdc / 1024 + BCrow); digit.setTDC(ctdc % 1024); digit.setTOT(cc.tot[digCount]); digit.setChannel(uint32_t(cc.stripID[digCount]) * 96 + cc.chanInStrip[digCount]); @@ -173,14 +182,22 @@ void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdig } // sort digits according to strip number within the ROF - if (digCount > firstDig) { - std::partial_sort(cdigVec.begin() + firstDig, cdigVec.begin() + digCount - 1, cdigVec.end(), - [](o2::tof::Digit a, o2::tof::Digit b) { - int str1 = a.getChannel() / 1600; - int str2 = b.getChannel() / 1600; - return (str1 <= str2); - }); + std::sort(digCopy.begin(), digCopy.end(), + [](o2::tof::Digit a, o2::tof::Digit b) { + int str1 = a.getChannel() / Geo::NPADS; + int str2 = b.getChannel() / Geo::NPADS; + if (str1 == str2) { + return (a.getOrderingKey() < b.getOrderingKey()); + } + return (str1 < str2); + }); + + // fill digits, once sorted, of rof in digit vector + for (uint32_t idig = 0; idig < digCopy.size(); idig++) { + cdigVec[firstDig + idig] = digCopy[idig]; } + + digCopy.clear(); } // explicit patterns memcpy(pattVec.data(), cc.pattMap.data(), cc.header.nPatternBytes); // RSTODO use swap? diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index ae033a3219018..6092941a3b685 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -98,7 +98,8 @@ void CTFCoder::compress(CompressedInfos& cc, continue; } - int idig = rofRec.first(), idigMax = idig + ndig; + int idigMin = rofRec.first(), idigMax = idigMin + ndig; + int idig = idigMin; // make a copy of digits digCopy.clear(); @@ -117,9 +118,9 @@ void CTFCoder::compress(CompressedInfos& cc, int timeframe = 0; int tdc = 0; - idig = 0; - for (; idig < ndig; idig++) { - const auto& dig = digCopy[idig]; + idig = idigMin; + for (; idig < idigMax; idig++) { + const auto& dig = digCopy[idig - idigMin]; int deltaBC = dig.getBC() - rofInBC; int ctimeframe = deltaBC / 64; int cTDC = (deltaBC % 64) * 1024 + dig.getTDC(); @@ -137,6 +138,8 @@ void CTFCoder::compress(CompressedInfos& cc, cc.stripID[idig] = chan / Geo::NPADS; cc.chanInStrip[idig] = chan % Geo::NPADS; cc.tot[idig] = dig.getTOT(); + printf("%d) TOFBC = %d, deltaBC = %d, TDC = %d, CH=%d\n", irof, rofInBC, deltaBC, cTDC, chan); + printf("%d) TF=%d, TDC=%d, STRIP=%d, CH=%d, TOT=%d\n", idig, cc.timeFrameInc[idig], cc.timeTDCInc[idig], cc.stripID[idig], cc.chanInStrip[idig], cc.tot[idig]); } } // store explicit patters as they are From 03dea76bf1e79e8e7e639e50691ae9d395e3180b Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 30 Jul 2020 19:26:54 +0200 Subject: [PATCH 0211/1751] Functionality of run_buildTopoDict_its was transferred to CheckTopologies.C suppress to avoid maintaining duplicated code --- .../ITSMFT/ITS/macros/test/CMakeLists.txt | 9 - .../ITS/macros/test/run_buildTopoDict_its.C | 216 ------------------ 2 files changed, 225 deletions(-) delete mode 100644 Detectors/ITSMFT/ITS/macros/test/run_buildTopoDict_its.C diff --git a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt index 05f4171cbe5a5..656dbe4574438 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt @@ -72,15 +72,6 @@ o2_add_test_root_macro(DisplayTrack.C # O2::ITSMFTReconstruction # LABELS its) -o2_add_test_root_macro(run_buildTopoDict_its.C - PUBLIC_LINK_LIBRARIES O2::MathUtils - O2::ITSBase - O2::ITSMFTReconstruction - O2::DataFormatsITSMFT - O2::ITSMFTSimulation - O2::SimulationDataFormat - LABELS its) - o2_add_test_root_macro(run_digi2rawVarPage_its.C PUBLIC_LINK_LIBRARIES O2::ITSMFTReconstruction O2::DataFormatsITSMFT diff --git a/Detectors/ITSMFT/ITS/macros/test/run_buildTopoDict_its.C b/Detectors/ITSMFT/ITS/macros/test/run_buildTopoDict_its.C deleted file mode 100644 index 1bd3a9eda500b..0000000000000 --- a/Detectors/ITSMFT/ITS/macros/test/run_buildTopoDict_its.C +++ /dev/null @@ -1,216 +0,0 @@ -/// \file run_buildTopoDict_its -/// Macros to generate dictionary of topologies. - -#if !defined(__CLING__) || defined(__ROOTCLING__) -#include <TAxis.h> -#include <TCanvas.h> -#include <TFile.h> -#include <TH1F.h> -#include <TH2F.h> -#include <TNtuple.h> -#include <TString.h> -#include <TStyle.h> -#include <TTree.h> -#include <TStopwatch.h> -#include <TSystem.h> -#include <fstream> -#include <string> - -#include "MathUtils/Utils.h" -#include "ITSBase/GeometryTGeo.h" -#include "ITSMFTReconstruction/BuildTopologyDictionary.h" -#include "DataFormatsITSMFT/CompCluster.h" -#include "DataFormatsITSMFT/ClusterTopology.h" -#include "DataFormatsITSMFT/ROFRecord.h" -#include "ITSMFTSimulation/Hit.h" -#include "MathUtils/Cartesian3D.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" -#include <unordered_map> -#include "DetectorsCommonDataFormats/NameConf.h" -#endif - -/// Build dictionary of topologies from the root file with compact clusters -/// If the hitfile is non-empty, the mean bias between the cluster COG -/// and mean MC hit position is calculated - -void run_buildTopoDict_its(std::string clusfile = "o2clus_its.root", - std::string hitfile = "o2sim_HitsITS.root", - std::string inputGeom = "") -{ - const int QEDSourceID = 99; // Clusters from this MC source correspond to QED electrons - - using namespace o2::base; - using namespace o2::its; - - using o2::itsmft::BuildTopologyDictionary; - using o2::itsmft::ClusterTopology; - using o2::itsmft::CompClusterExt; - using o2::itsmft::Hit; - using ROFRec = o2::itsmft::ROFRecord; - using MC2ROF = o2::itsmft::MC2ROFRecord; - using HitVec = std::vector<Hit>; - using MC2HITS_map = std::unordered_map<uint64_t, int>; // maps (track_ID<<16 + chip_ID) to entry in the hit vector - - std::vector<HitVec*> hitVecPool; - std::vector<MC2HITS_map> mc2hitVec; - - TStopwatch sw; - sw.Start(); - - // Geometry - o2::base::GeometryManager::loadGeometry(inputGeom); - auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); // request cached transforms - - // Hits if requested - TFile* fileH = nullptr; - TTree* hitTree = nullptr; - - if (!hitfile.empty() && !gSystem->AccessPathName(hitfile.c_str())) { - fileH = TFile::Open(hitfile.data()); - hitTree = (TTree*)fileH->Get("o2sim"); - mc2hitVec.resize(hitTree->GetEntries()); - hitVecPool.resize(hitTree->GetEntries(), nullptr); - } - - // Clusters - TFile* fileCl = TFile::Open(clusfile.data()); - TTree* clusTree = (TTree*)fileCl->Get("o2sim"); - std::vector<CompClusterExt>* clusArr = nullptr; - clusTree->SetBranchAddress("ITSClusterComp", &clusArr); - std::vector<unsigned char>* patternsPtr = nullptr; - auto pattBranch = clusTree->GetBranch("ITSClusterPatt"); - if (pattBranch) { - pattBranch->SetAddress(&patternsPtr); - } - - // ROFrecords - std::vector<ROFRec> rofRecVec, *rofRecVecP = &rofRecVec; - clusTree->SetBranchAddress("ITSClustersROF", &rofRecVecP); - - // Cluster MC labels - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clusLabArr = nullptr; - std::vector<MC2ROF> mc2rofVec, *mc2rofVecP = &mc2rofVec; - if (hitTree && clusTree->GetBranch("ITSClusterMCTruth")) { - clusTree->SetBranchAddress("ITSClusterMCTruth", &clusLabArr); - clusTree->SetBranchAddress("ITSClustersMC2ROF", &mc2rofVecP); - } - clusTree->GetEntry(0); - - BuildTopologyDictionary dict; - - int nROFRec = (int)rofRecVec.size(); - std::vector<int> mcEvMin(nROFRec, hitTree->GetEntries()), mcEvMax(nROFRec, -1); - - if (clusLabArr) { // >> build min and max MC events used by each ROF - for (int imc = mc2rofVec.size(); imc--;) { - const auto& mc2rof = mc2rofVec[imc]; - if (mc2rof.rofRecordID < 0) { - continue; // this MC event did not contribute to any ROF - } - for (int irfd = mc2rof.maxROF - mc2rof.minROF + 1; irfd--;) { - int irof = mc2rof.rofRecordID + irfd; - if (mcEvMin[irof] > imc) { - mcEvMin[irof] = imc; - } - if (mcEvMax[irof] < imc) { - mcEvMax[irof] = imc; - } - } - } - } // << build min and max MC events used by each ROF - - auto pattIdx = patternsPtr->cbegin(); - for (int irof = 0; irof < nROFRec; irof++) { - const auto& rofRec = rofRecVec[irof]; - - rofRec.print(); - - if (clusLabArr) { // >> read and map MC events contributing to this ROF - for (int im = mcEvMin[irof]; im <= mcEvMax[irof]; im++) { - if (!hitVecPool[im]) { - hitTree->SetBranchAddress("ITSHit", &hitVecPool[im]); - hitTree->GetEntry(im); - auto& mc2hit = mc2hitVec[im]; - const auto* hitArray = hitVecPool[im]; - for (int ih = hitArray->size(); ih--;) { - const auto& hit = (*hitArray)[ih]; - uint64_t key = (uint64_t(hit.GetTrackID()) << 32) + hit.GetDetectorID(); - mc2hit.emplace(key, ih); - } - } - } - } // << cache MC events contributing to this ROF - - for (int icl = 0; icl < rofRec.getNEntries(); icl++) { - int clEntry = rofRec.getFirstEntry() + icl; // entry of icl-th cluster of this ROF in the vector of clusters - // do we read MC data? - - const auto& cluster = (*clusArr)[clEntry]; - - ClusterTopology topology; - o2::itsmft::ClusterPattern pattern(pattIdx); - topology.setPattern(pattern); - // - // do we need to account for the bias of cluster COG wrt MC hit center? - float dX = BuildTopologyDictionary::IgnoreVal, dZ = BuildTopologyDictionary::IgnoreVal; - if (clusLabArr) { - const auto& lab = (clusLabArr->getLabels(clEntry))[0]; // we neglect effect of cluster contributed by multiple hits - auto srcID = lab.getSourceID(); - if (!lab.isNoise() && srcID != QEDSourceID) { // use MC truth info only for non-QED and non-noise clusters - auto trID = lab.getTrackID(); - const auto& mc2hit = mc2hitVec[lab.getEventID()]; - const auto* hitArray = hitVecPool[lab.getEventID()]; - int chipID = cluster.getSensorID(); - uint64_t key = (uint64_t(trID) << 32) + chipID; - auto hitEntry = mc2hit.find(key); - if (hitEntry != mc2hit.end()) { - const auto& hit = (*hitArray)[hitEntry->second]; - auto locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local - auto locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); - locH.SetXYZ(0.5 * (locH.X() + locHsta.X()), 0.5 * (locH.Y() + locHsta.Y()), 0.5 * (locH.Z() + locHsta.Z())); - const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern); - dX = locH.X() - locC.X(); - dZ = locH.Z() - locC.Z(); - } else { - printf("Failed to find MC hit entry for Tr:%d chipID:%d\n", trID, chipID); - } - } - } - dict.accountTopology(topology, dX, dZ); - } - // clean MC cache for events which are not needed anymore - int irfNext = irof; - while ((++irfNext < nROFRec) && mcEvMax[irfNext] < 0) { - } // find next ROF having MC contribution - int limMC = irfNext == nROFRec ? hitVecPool.size() : mcEvMin[irfNext]; // can clean events up to this - for (int imc = mcEvMin[irof]; imc < limMC; imc++) { - delete hitVecPool[imc]; - hitVecPool[imc] = nullptr; - mc2hitVec[imc].clear(); - } - } - - dict.setThreshold(0.0001); - dict.groupRareTopologies(); - - auto dID = o2::detectors::DetID::ITS; - dict.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "", ".bin")); - dict.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "", ".txt")); - dict.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "", ".root")); - - TFile histogramOutput("dict_histograms.root", "recreate"); - TCanvas* cComplete = new TCanvas("cComplete", "Distribution of all the topologies"); - cComplete->cd(); - cComplete->SetLogy(); - TH1F* hComplete = nullptr; - o2::itsmft::TopologyDictionary::getTopologyDistribution(dict.getDictionary(), hComplete, "hComplete"); - hComplete->SetDirectory(0); - hComplete->Draw("hist"); - cComplete->Print("dictHisto.pdf"); - cComplete->Write(); - sw.Stop(); - sw.Print(); -} From 650c483cf2db671006685532afb98ee4373b58a2 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 30 Jul 2020 19:32:02 +0200 Subject: [PATCH 0212/1751] Make CheckTopologies to work with QED-embedded MC + fix The new way of adding QED leads to MC2ROF vector mapping global event id (including copious QED events) to ROF, while the Hits file provided as MC truth belongs to hadronic events (sourceID=0). Therefore, we have to provide the DigitizationContext and remap global interaction ID to that of hadronic events. --- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 66 ++++++++++++++----- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index 4318ed1155f7d..e51b082aec6dd 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -27,12 +27,14 @@ #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "DetectorsCommonDataFormats/NameConf.h" +#include "SimulationDataFormat/DigitizationContext.h" #include "Framework/Logger.h" #include <unordered_map> #endif void CheckTopologies(std::string clusfile = "o2clus_its.root", std::string hitfile = "o2sim_HitsITS.root", + std::string collContextfile = "collisioncontext.root", std::string inputGeom = "") { const int QEDSourceID = 99; // Clusters from this MC source correspond to QED electrons @@ -49,10 +51,10 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", using MC2ROF = o2::itsmft::MC2ROFRecord; using HitVec = std::vector<Hit>; using MC2HITS_map = std::unordered_map<uint64_t, int>; // maps (track_ID<<16 + chip_ID) to entry in the hit vector - + std::unordered_map<int, int> hadronicMCMap; // mapping from MC event entry to hadronic event ID std::vector<HitVec*> hitVecPool; std::vector<MC2HITS_map> mc2hitVec; - + const o2::steer::DigitizationContext* digContext = nullptr; TStopwatch sw; sw.Start(); @@ -66,11 +68,34 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", TFile* fileH = nullptr; TTree* hitTree = nullptr; - if (!hitfile.empty() && !gSystem->AccessPathName(hitfile.c_str())) { + if (!hitfile.empty() && !collContextfile.empty() && !gSystem->AccessPathName(hitfile.c_str()) && !gSystem->AccessPathName(collContextfile.c_str())) { fileH = TFile::Open(hitfile.data()); hitTree = (TTree*)fileH->Get("o2sim"); mc2hitVec.resize(hitTree->GetEntries()); hitVecPool.resize(hitTree->GetEntries(), nullptr); + digContext = o2::steer::DigitizationContext::loadFromFile(collContextfile); + + auto& intGlo = digContext->getEventParts(digContext->isQEDProvided()); + int hadrID = -1, nGlo = intGlo.size(), nHadro = 0; + for (int iglo = 0; iglo < nGlo; iglo++) { + const auto& parts = intGlo[iglo]; + bool found = false; + for (auto& part : parts) { + if (part.sourceID == 0) { // we use underlying background + hadronicMCMap[iglo] = part.entryID; + found = true; + nHadro++; + break; + } + } + if (!found) { + hadronicMCMap[iglo] = -1; + } + } + if (nHadro < hitTree->GetEntries()) { + LOG(FATAL) << "N=" << nHadro << " hadronic events < " + << " N=" << hitTree->GetEntries() << " Hit enties."; + } } // Clusters @@ -103,21 +128,27 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", BuildTopologyDictionary noiseDictionary; int nROFRec = (int)rofRecVec.size(); - std::vector<int> mcEvMin(nROFRec, hitTree->GetEntries()), mcEvMax(nROFRec, -1); + std::vector<int> mcEvMin, mcEvMax; if (clusLabArr) { // >> build min and max MC events used by each ROF + mcEvMin.resize(nROFRec, hitTree->GetEntries()); + mcEvMax.resize(nROFRec, -1); for (int imc = mc2rofVec.size(); imc--;) { + int hadrID = hadronicMCMap[imc]; + if (hadrID < 0) { + continue; + } const auto& mc2rof = mc2rofVec[imc]; if (mc2rof.rofRecordID < 0) { continue; // this MC event did not contribute to any ROF } for (int irfd = mc2rof.maxROF - mc2rof.minROF + 1; irfd--;) { int irof = mc2rof.rofRecordID + irfd; - if (mcEvMin[irof] > imc) { - mcEvMin[irof] = imc; + if (mcEvMin[irof] > hadrID) { + mcEvMin[irof] = hadrID; } - if (mcEvMax[irof] < imc) { - mcEvMax[irof] = imc; + if (mcEvMax[irof] < hadrID) { + mcEvMax[irof] = hadrID; } } } @@ -152,6 +183,7 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", const auto& cluster = (*clusArr)[clEntry]; if (cluster.getPatternID() != CompCluster::InvalidPatternID) { + LOG(WARNING) << "Encountered patternID = " << cluster.getPatternID() << " != " << CompCluster::InvalidPatternID; LOG(WARNING) << "Clusters have already been generated with a dictionary! Quitting"; return; } @@ -181,6 +213,7 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", dZ = locH.Z() - locC.Z(); } else { printf("Failed to find MC hit entry for Tr:%d chipID:%d\n", trID, chipID); + lab.print(); } signalDictionary.accountTopology(topology, dX, dZ); } else { @@ -190,17 +223,16 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", completeDictionary.accountTopology(topology, dX, dZ); } // clean MC cache for events which are not needed anymore - int irfNext = irof; - while ((++irfNext < nROFRec) && mcEvMax[irfNext] < 0) { - } // find next ROF having MC contribution - int limMC = irfNext == nROFRec ? hitVecPool.size() : mcEvMin[irfNext]; // can clean events up to this - for (int imc = mcEvMin[irof]; imc < limMC; imc++) { - delete hitVecPool[imc]; - hitVecPool[imc] = nullptr; - mc2hitVec[imc].clear(); + if (clusLabArr) { + int irfNext = irof; + int limMC = irfNext == nROFRec ? hitVecPool.size() : mcEvMin[irfNext]; // can clean events up to this + for (int imc = mcEvMin[irof]; imc < limMC; imc++) { + delete hitVecPool[imc]; + hitVecPool[imc] = nullptr; + mc2hitVec[imc].clear(); + } } } - auto dID = o2::detectors::DetID::ITS; completeDictionary.setThreshold(0.0001); From 0a017aca14bd07f91c8bdc4d1648e1e07766821d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 31 Jul 2020 00:35:55 +0200 Subject: [PATCH 0213/1751] DPL: align to 64 bit C-array messages (#4068) --- Framework/Core/src/MessageContext.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/MessageContext.cxx b/Framework/Core/src/MessageContext.cxx index 83945066848ae..039fbbb590849 100644 --- a/Framework/Core/src/MessageContext.cxx +++ b/Framework/Core/src/MessageContext.cxx @@ -19,7 +19,7 @@ namespace framework FairMQMessagePtr MessageContext::createMessage(const std::string& channel, int index, size_t size) { - return proxy().getDevice()->NewMessageFor(channel, 0, size); + return proxy().getDevice()->NewMessageFor(channel, 0, size, fair::mq::Alignment{64}); } FairMQMessagePtr MessageContext::createMessage(const std::string& channel, int index, void* data, size_t size, fairmq_free_fn* ffn, void* hint) From f652055f2fa3e714991ea1ef46d7a8880579c02a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 1 Aug 2020 07:59:09 +0200 Subject: [PATCH 0214/1751] DPL: Always use boost::filesystem (#4066) * Always use boost * Update CMakeLists.txt --- Framework/Core/CMakeLists.txt | 4 ++-- Framework/Core/src/ChannelSpecHelpers.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 886ab90b797fd..d34953c8f9bf2 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -21,9 +21,9 @@ endif() # Given GCC 7.3 does not provide std::filesystem we use Boost instead # Drop this once we move to GCC 8.2+ -if (NOT __APPLE__) +# if (NOT __APPLE__) set(BOOST_FILESYSTEM Boost::filesystem) -endif() +# endif() o2_add_library(Framework SOURCES src/AODReaderHelpers.cxx diff --git a/Framework/Core/src/ChannelSpecHelpers.cxx b/Framework/Core/src/ChannelSpecHelpers.cxx index 5500692dd83bd..87b7ff45c0c1c 100644 --- a/Framework/Core/src/ChannelSpecHelpers.cxx +++ b/Framework/Core/src/ChannelSpecHelpers.cxx @@ -12,7 +12,7 @@ #include <ostream> #include <cassert> #include <stdexcept> -#if __has_include(<filesystem>) +#if 0 #include <filesystem> namespace fs = std::filesystem; #elif __has_include(<boost/filesystem.hpp>) From ac6585b18adc81af008c0b88a0ed3e374c4cf12b Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan <shahor02@users.noreply.github.com> Date: Sat, 1 Aug 2020 13:17:03 +0200 Subject: [PATCH 0215/1751] o2-raw-file-reader-workflow --cache-data will cache data at 1st reading (#4071) Then, with --loop option following iterations will avoid disk IO Co-authored-by: shahoian <ruben.shahoyan@cern.ch> --- Detectors/Raw/README.md | 5 +- .../Raw/include/DetectorsRaw/RawFileReader.h | 16 +++- Detectors/Raw/src/RawFileReader.cxx | 74 ++++++++++++------- Detectors/Raw/src/RawFileReaderWorkflow.cxx | 17 +++-- Detectors/Raw/src/RawFileReaderWorkflow.h | 2 +- Detectors/Raw/src/rawfile-reader-workflow.cxx | 4 +- 6 files changed, 78 insertions(+), 40 deletions(-) diff --git a/Detectors/Raw/README.md b/Detectors/Raw/README.md index 6b94e1f94cc43..e35c82c4158ce 100644 --- a/Detectors/Raw/README.md +++ b/Detectors/Raw/README.md @@ -305,6 +305,8 @@ o2-raw-file-reader-workflow --super-page-size arg (=1048576) super-page size for FMQ parts definition --part-per-hbf FMQ parts per superpage (default) of HBF --raw-channel-config arg optional raw FMQ channel for non-DPL output + --cache-data cache data at 1st reading, may require excessive memory!!! + --configKeyValues arg semicolon separated key=value strings # to suppress various error checks / reporting @@ -323,7 +325,8 @@ The workflow takes an input from the configuration file (as described in `RawFil with the `OutputSpec`s indicated in the configuration file (or defaults). Each link data gets `SubSpecification` according to DataDistribution scheme. -If `--loop` argument is provided, data will be re-played in loop. The delay (in seconds) can be added between sensding of consecutive TFs to avoid pile-up of TFs. +If `--loop` argument is provided, data will be re-played in loop. The delay (in seconds) can be added between sensding of consecutive TFs to avoid pile-up of TFs. By default at each iteration the data will be again read from the disk. +Using `--cache-data` option one can force caching the data to memory during the 1st reading, this avoiding disk I/O for following iterations, but this option should be used with care as it will eventually create a memory copy of all TFs to read. At every invocation of the device `processing` callback a full TimeFrame for every link will be added as a multi-part `FairMQ` message and relayed by the relevant channel. By default each part will be a single CRU super-page of the link. This behaviour can be changed by providing `part-per-hbf` option, in which case each HBF will be added as a separate HBF. diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index e2a1e3e6d6a58..7754ac7cf7661 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -97,6 +97,13 @@ class RawFileReader using InputsMap = std::map<OrigDescCard, std::vector<std::string>>; //===================================================================================== + + // reference on blocks making single message part + struct PartStat { + int size; // total size + int nBlocks; // number of consecutive LinkBlock objects + }; + // info on the smallest block of data to be read when fetching the HBF struct LinkBlock { enum { StartTF = 0x1, @@ -109,6 +116,7 @@ class RawFileReader IR ir = 0; //! ir starting the block uint16_t fileID = 0; //! file id where the block is located uint8_t flags = 0; //! different flags + std::unique_ptr<char[]> dataCache; //! optional cache for fast access LinkBlock() = default; LinkBlock(int fid, size_t offs) : offset(offs), fileID(fid) {} void setFlag(uint8_t fl, bool v = true) @@ -155,12 +163,12 @@ class RawFileReader size_t getLargestTF() const; size_t getNextHBFSize() const; size_t getNextTFSize() const; - size_t getNextTFSuperPagesStat(std::vector<size_t>& parts) const; + size_t getNextTFSuperPagesStat(std::vector<PartStat>& parts) const; int getNHBFinTF() const; size_t readNextHBF(char* buff); size_t readNextTF(char* buff); - size_t readNextSuperPage(char* buff); + size_t readNextSuperPage(char* buff, const PartStat* pstat = nullptr); size_t skipNextHBF(); size_t skipNextTF(); @@ -220,6 +228,9 @@ class RawFileReader uint32_t getOrbitMin() const { return mOrbitMin; } uint32_t getOrbitMax() const { return mOrbitMax; } + bool getCacheData() const { return mCacheData; } + void setCacheData(bool v) { mCacheData = v; } + o2::header::DataOrigin getDefaultDataOrigin() const { return mDefDataOrigin; } o2::header::DataDescription getDefaultDataSpecification() const { return mDefDataDescription; } ReadoutCardType getDefaultReadoutCardType() const { return mDefCardType; } @@ -261,6 +272,7 @@ class RawFileReader int mCurrentFileID = 0; //! current file being processed long int mPosInFile = 0; //! current position in the file bool mMultiLinkFile = false; //! was > than 1 link seen in the file? + bool mCacheData = false; //! cache data to block after 1st scan (may require excessive memory, use with care) uint32_t mCheckErrors = 0; //! mask for errors to check int mVerbosity = 0; diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index 4d225398f5a93..669c4a1fa6e6c 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -72,26 +72,28 @@ void RawFileReader::LinkData::print(bool verbose, const std::string& pref) const } //____________________________________________ -size_t RawFileReader::LinkData::getNextTFSuperPagesStat(std::vector<size_t>& parts) const +size_t RawFileReader::LinkData::getNextTFSuperPagesStat(std::vector<RawFileReader::PartStat>& parts) const { // get stat. of superpages for this link in this TF. We treat as a start of a superpage the discontinuity in the link data, new TF // or continuous data exceeding a threshold (e.g. 1MB) - size_t sz = 0; + int sz = 0; int nSP = 0; - int ibl = nextBlock2Read, nbl = blocks.size(); + int ibl = nextBlock2Read, nbl = blocks.size(), nblPart = 0; parts.clear(); while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { if (ibl > nextBlock2Read && (blocks[ibl].testFlag(LinkBlock::StartSP) || (sz + blocks[ibl].size) > reader->mNominalSPageSize || (blocks[ibl - 1].offset + blocks[ibl - 1].size) < blocks[ibl].offset)) { // new superpage - parts.push_back(sz); + parts.emplace_back(RawFileReader::PartStat{sz, nblPart}); sz = 0; + nblPart = 0; } sz += blocks[ibl].size; + nblPart++; ibl++; } if (sz) { - parts.push_back(sz); + parts.emplace_back(RawFileReader::PartStat{sz, nblPart}); } return parts.size(); } @@ -118,16 +120,23 @@ size_t RawFileReader::LinkData::readNextHBF(char* buff) int ibl = nextBlock2Read, nbl = blocks.size(); bool error = false; while (ibl < nbl) { - const auto& blc = blocks[ibl]; + auto& blc = blocks[ibl]; if (blc.ir != blocks[nextBlock2Read].ir) { break; } ibl++; - auto fl = reader->mFiles[blc.fileID]; - if (fseek(fl, blc.offset, SEEK_SET) || fread(buff + sz, 1, blc.size, fl) != blc.size) { - LOGF(ERROR, "Failed to read for the %s a bloc:", describe()); - blc.print(); - error = true; + if (blc.dataCache) { + memcpy(buff + sz, blc.dataCache.get(), blc.size); + } else { + auto fl = reader->mFiles[blc.fileID]; + if (fseek(fl, blc.offset, SEEK_SET) || fread(buff + sz, 1, blc.size, fl) != blc.size) { + LOGF(ERROR, "Failed to read for the %s a bloc:", describe()); + blc.print(); + error = true; + } else if (reader->mCacheData) { // need to fill the cache at 1st reading + blc.dataCache = std::make_unique<char[]>(blc.size); + memcpy(blc.dataCache.get(), buff + sz, blc.size); // will be used at next reading + } } sz += blc.size; } @@ -226,31 +235,42 @@ int RawFileReader::LinkData::getNHBFinTF() const } //____________________________________________ -size_t RawFileReader::LinkData::readNextSuperPage(char* buff) +size_t RawFileReader::LinkData::readNextSuperPage(char* buff, const RawFileReader::PartStat* pstat) { // read data of the next complete HB, buffer of getNextHBFSize() must be allocated in advance size_t sz = 0; int ibl = nextBlock2Read, nbl = blocks.size(); auto tfID = blocks[nextBlock2Read].tfID; bool error = false; - - while (ibl < nbl) { - const auto& blc = blocks[ibl]; - if (ibl > nextBlock2Read && (blc.tfID != blocks[nextBlock2Read].tfID || - blc.testFlag(LinkBlock::StartSP) || - (sz + blc.size) > reader->mNominalSPageSize || - blocks[ibl - 1].offset + blocks[ibl - 1].size < blc.offset)) { // new superpage or TF - break; + if (pstat) { // info is provided, use it derictly + sz = pstat->size; + ibl += pstat->nBlocks; + } else { // need to calculate blocks to read + while (ibl < nbl) { + auto& blc = blocks[ibl]; + if (ibl > nextBlock2Read && (blc.tfID != blocks[nextBlock2Read].tfID || + blc.testFlag(LinkBlock::StartSP) || + (sz + blc.size) > reader->mNominalSPageSize || + blocks[ibl - 1].offset + blocks[ibl - 1].size < blc.offset)) { // new superpage or TF + break; + } + ibl++; + sz += blc.size; } - ibl++; - sz += blc.size; } if (sz) { - auto fl = reader->mFiles[blocks[nextBlock2Read].fileID]; - if (fseek(fl, blocks[nextBlock2Read].offset, SEEK_SET) || fread(buff, 1, sz, fl) != sz) { - LOGF(ERROR, "Failed to read for the %s a bloc:", describe()); - blocks[nextBlock2Read].print(); - error = true; + if (reader->mCacheData && blocks[nextBlock2Read].dataCache) { + memcpy(buff, blocks[nextBlock2Read].dataCache.get(), sz); + } else { + auto fl = reader->mFiles[blocks[nextBlock2Read].fileID]; + if (fseek(fl, blocks[nextBlock2Read].offset, SEEK_SET) || fread(buff, 1, sz, fl) != sz) { + LOGF(ERROR, "Failed to read for the %s a bloc:", describe()); + blocks[nextBlock2Read].print(); + error = true; + } else if (reader->mCacheData) { // cache after 1st reading + blocks[nextBlock2Read].dataCache = std::make_unique<char[]>(sz); + memcpy(blocks[nextBlock2Read].dataCache.get(), buff, sz); + } } } nextBlock2Read = ibl; diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index b1aba7550ee52..779628a8d34cf 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -46,7 +46,7 @@ class RawReaderSpecs : public o2f::Task { public: explicit RawReaderSpecs(const std::string& config, int loop = 1, uint32_t delay_us = 0, - uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, + uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, bool cache = false, size_t spSize = 1024L * 1024L, size_t buffSize = 5 * 1024UL, const std::string& rawChannelName = "") : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mPartPerSP(partPerSP), mReader(std::make_unique<o2::raw::RawFileReader>(config, 0, buffSize)), mRawChannelName(rawChannelName) @@ -54,6 +54,7 @@ class RawReaderSpecs : public o2f::Task mReader->setCheckErrors(errmap); mReader->setMaxTFToRead(maxTF); mReader->setNominalSPageSize(spSize); + mReader->setCacheData(cache); LOG(INFO) << "Will preprocess files with buffer size of " << buffSize << " bytes"; LOG(INFO) << "Number of loops over whole data requested: " << mLoop; for (int i = NTimers; i--;) { @@ -134,7 +135,7 @@ class RawReaderSpecs : public o2f::Task for (int il = 0; il < nlinks; il++) { mReader->getLink(il).rewindToTF(tfID); } - std::vector<size_t> partsSP; + std::vector<RawFileReader::PartStat> partsSP; const auto& hbfU = HBFUtils::Instance(); // read next time frame @@ -157,12 +158,12 @@ class RawReaderSpecs : public o2f::Task while (hdrTmpl.splitPayloadIndex < hdrTmpl.splitPayloadParts) { - tfSize += hdrTmpl.payloadSize = mPartPerSP ? partsSP[hdrTmpl.splitPayloadIndex] : link.getNextHBFSize(); + tfSize += hdrTmpl.payloadSize = mPartPerSP ? partsSP[hdrTmpl.splitPayloadIndex].size : link.getNextHBFSize(); auto fmqFactory = device->GetChannel(link.fairMQChannel, 0).Transport(); auto hdMessage = fmqFactory->CreateMessage(hstackSize, fair::mq::Alignment{64}); auto plMessage = fmqFactory->CreateMessage(hdrTmpl.payloadSize, fair::mq::Alignment{64}); mTimer[TimerIO].Start(false); - auto bread = mPartPerSP ? link.readNextSuperPage(reinterpret_cast<char*>(plMessage->GetData())) : link.readNextHBF(reinterpret_cast<char*>(plMessage->GetData())); + auto bread = mPartPerSP ? link.readNextSuperPage(reinterpret_cast<char*>(plMessage->GetData()), &partsSP[hdrTmpl.splitPayloadIndex]) : link.readNextHBF(reinterpret_cast<char*>(plMessage->GetData())); if (bread != hdrTmpl.payloadSize) { LOG(ERROR) << "Link " << il << " read " << bread << " bytes instead of " << hdrTmpl.payloadSize << " expected in TF=" << mTFCounter << " part=" << hdrTmpl.splitPayloadIndex; @@ -245,7 +246,7 @@ class RawReaderSpecs : public o2f::Task }; o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t delay_us, uint32_t errmap, - uint32_t minTF, uint32_t maxTF, bool partPerSP, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) + uint32_t minTF, uint32_t maxTF, bool partPerSP, bool cache, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) { // check which inputs are present in files to read o2f::DataProcessorSpec spec; @@ -276,15 +277,15 @@ o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t dela LOG(INFO) << "Will send output to non-DPL channel " << rawChannelConfig; } - spec.algorithm = o2f::adaptFromTask<RawReaderSpecs>(config, loop, delay_us, errmap, minTF, maxTF, partPerSP, spSize, buffSize, rawChannelName); + spec.algorithm = o2f::adaptFromTask<RawReaderSpecs>(config, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, spSize, buffSize, rawChannelName); return spec; } o2f::WorkflowSpec o2::raw::getRawFileReaderWorkflow(std::string inifile, int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, - bool partPerSP, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) + bool partPerSP, bool cache, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) { o2f::WorkflowSpec specs; - specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, spSize, buffSize, rawChannelConfig)); + specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, spSize, buffSize, rawChannelConfig)); return specs; } diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.h b/Detectors/Raw/src/RawFileReaderWorkflow.h index bbe3a808512d5..731921eb46a5d 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.h +++ b/Detectors/Raw/src/RawFileReaderWorkflow.h @@ -22,7 +22,7 @@ namespace raw { framework::WorkflowSpec getRawFileReaderWorkflow(std::string inifile, int loop = 1, uint32_t delay_us = 0, uint32_t errMap = 0xffffffff, - uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, + uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, bool cache = false, size_t spSize = 1024L * 1024L, size_t bufferSize = 1024L * 1024L, const std::string& rawChannelConfig = ""); diff --git a/Detectors/Raw/src/rawfile-reader-workflow.cxx b/Detectors/Raw/src/rawfile-reader-workflow.cxx index 8d56b8e3aca4d..5a752cfd07fd9 100644 --- a/Detectors/Raw/src/rawfile-reader-workflow.cxx +++ b/Detectors/Raw/src/rawfile-reader-workflow.cxx @@ -32,6 +32,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) options.push_back(ConfigParamSpec{"super-page-size", VariantType::Int64, 1024L * 1024L, {"super-page size for FMQ parts definition"}}); options.push_back(ConfigParamSpec{"part-per-hbf", VariantType::Bool, false, {"FMQ parts per superpage (default) of HBF"}}); options.push_back(ConfigParamSpec{"raw-channel-config", VariantType::String, "", {"optional raw FMQ channel for non-DPL output"}}); + options.push_back(ConfigParamSpec{"cache-data", VariantType::Bool, false, {"cache data at 1st reading, may require excessive memory!!!"}}); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}); // options for error-check suppression @@ -55,6 +56,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) uint64_t buffSize = uint64_t(configcontext.options().get<int64_t>("buffer-size")); uint64_t spSize = uint64_t(configcontext.options().get<int64_t>("super-page-size")); bool partPerSP = !configcontext.options().get<bool>("part-per-hbf"); + bool cache = configcontext.options().get<bool>("cache-data"); std::string rawChannelConfig = configcontext.options().get<std::string>("raw-channel-config"); uint32_t errmap = 0; for (int i = RawFileReader::NErrorsDefined; i--;) { @@ -67,5 +69,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); uint32_t delay_us = uint32_t(1e6 * configcontext.options().get<float>("delay")); // delay in microseconds - return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, spSize, buffSize, rawChannelConfig)); + return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, spSize, buffSize, rawChannelConfig)); } From 6ad0a877c447e976e60c84ff741a0ae18426589d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 1 Aug 2020 17:35:44 +0200 Subject: [PATCH 0216/1751] GPU: Fix after configuration change, dumpEvent setting was lost --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 826ff85c6c24f..ea8be026291d7 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -117,6 +117,8 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int processAttributes->allocateOutputOnTheFly = confParam.allocateOutputOnTheFly; processAttributes->outputBufferSize = confParam.outputBufferSize; processAttributes->suppressOutput = (confParam.dump == 2); + config.configInterface.dumpEvents = confParam.dump; + if (config.configEvent.continuousMaxTimeBin == -1) { config.configEvent.continuousMaxTimeBin = (o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * o2::constants::lhc::LHCMaxBunches + 2 * Constants::LHCBCPERTIMEBIN - 2) / Constants::LHCBCPERTIMEBIN; } From 3e81126c4bf2a02f118221a191b4113e75d7540b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 1 Aug 2020 17:36:07 +0200 Subject: [PATCH 0217/1751] GPU: Do not force a memory pool size if there is no pool --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 1eb32726c6588..cd69a746cf5d2 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -193,12 +193,15 @@ int GPUReconstruction::InitPhaseBeforeDevice() mRecoStepsGPU.set((unsigned char)0); } - if (mProcessingSettings.forceMemoryPoolSize || mProcessingSettings.forceHostMemoryPoolSize) { + if (mProcessingSettings.forceMemoryPoolSize >= 1024 || mProcessingSettings.forceHostMemoryPoolSize >= 1024) { mProcessingSettings.memoryAllocationStrategy = GPUMemoryResource::ALLOCATION_GLOBAL; } if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_AUTO) { mProcessingSettings.memoryAllocationStrategy = IsGPU() ? GPUMemoryResource::ALLOCATION_GLOBAL : GPUMemoryResource::ALLOCATION_INDIVIDUAL; } + if (mProcessingSettings.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { + mProcessingSettings.forceMemoryPoolSize = mProcessingSettings.forceHostMemoryPoolSize = 0; + } if (mProcessingSettings.debugLevel >= 4) { mProcessingSettings.keepAllMemory = true; } From 3856a00a4402ca155c6acafac5ed079922205961 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 30 Jul 2020 10:24:28 +0200 Subject: [PATCH 0218/1751] GPU: Set ompKernels=true by default in GPUReconstruction on CPU --- GPU/GPUTracking/Base/GPUSettingsList.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 7700386bb2e38..91623d7863bde 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -99,7 +99,7 @@ AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fi AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode") AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") AddOption(runMC, bool, false, "", 0, "Process MC labels") -AddOption(ompKernels, bool, false, "", 0, "Parallelize with OMP inside kernels instead of over slices") +AddOption(ompKernels, bool, true, "", 0, "Parallelize with OMP inside kernels instead of over slices") AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") From 9bc030e890162e2cdc7e796d3d512f1637de4bdb Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 1 Aug 2020 17:54:29 +0200 Subject: [PATCH 0219/1751] DPL: Add timeslice4 placeholder --- Framework/Core/src/runDataProcessing.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 542150a659414..8974b8b5250af 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -436,7 +436,8 @@ void spawnDevice(std::string const& forwardedStdin, for (auto& env : execution.environ) { char* formatted = strdup(fmt::format(env, fmt::arg("timeslice0", spec.inputTimesliceId), - fmt::arg("timeslice1", spec.inputTimesliceId + 1)) + fmt::arg("timeslice1", spec.inputTimesliceId + 1), + fmt::arg("timeslice4", spec.inputTimesliceId + 4)) .c_str()); putenv(formatted); } From e80aa7fdcdbd72e73ba56fd06a4f76d11bc79cdd Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 1 Aug 2020 18:00:12 +0200 Subject: [PATCH 0220/1751] TPC: Parallelize track output in TPC workflow with OpenMP as long as we still have this stupid copying --- Detectors/TPC/reconstruction/CMakeLists.txt | 8 ++++++++ .../TPC/reconstruction/src/GPUCATracking.cxx | 18 ++++++++++++------ GPU/GPUTracking/CMakeLists.txt | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Detectors/TPC/reconstruction/CMakeLists.txt b/Detectors/TPC/reconstruction/CMakeLists.txt index 05469cde4aac4..c07c02f16e0d3 100644 --- a/Detectors/TPC/reconstruction/CMakeLists.txt +++ b/Detectors/TPC/reconstruction/CMakeLists.txt @@ -9,6 +9,7 @@ # submit itself to any jurisdiction. o2_add_library(TPCReconstruction + TARGETVARNAME targetName SOURCES src/AdcClockMonitor.cxx src/ClustererTask.cxx src/GBTFrame.cxx @@ -132,3 +133,10 @@ o2_add_test_root_macro(macro/findKrBoxCluster.C # target which is built after reconstruction # o2_add_test_root_macro(macro/testTracks.C PUBLIC_LINK_LIBRARIES # ReconstructionDataFormats O2::TPCBase O2::DataFormatsTPC O2::TPCSimulation) + +if(OpenMP_CXX_FOUND) + message(STATUS "GPU: Using OpenMP: ${OpenMP_CXX_SPEC_DATE}") + # Must be private, depending libraries might be compiled by compiler not understanding -fopenmp + target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) + target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) +endif() diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 814d84cb23732..83d1170dad14f 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -34,6 +34,9 @@ #include "GPUTPCGMMergedTrackHit.h" #include "GPUHostDataTypes.h" +#include <atomic> +#include <omp.h> + using namespace o2::gpu; using namespace o2::tpc; using namespace o2; @@ -41,7 +44,7 @@ using namespace o2::dataformats; using MCLabelContainer = MCTruthContainer<MCCompLabel>; -GPUCATracking::GPUCATracking() : mTrackingCAO2Interface() {} +GPUCATracking::GPUCATracking() = default; GPUCATracking::~GPUCATracking() { deinitialize(); } int GPUCATracking::initialize(const GPUO2InterfaceConfiguration& config) @@ -150,11 +153,15 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* mNTracksASide = tmp; } nTracks = tmp; - outputTracks->resize(nTracks); outClusRefs->resize(clBuff); - clBuff = 0; + std::atomic_int clusterOffsetCounter; + clusterOffsetCounter.store(0); + +#ifdef WITH_OPENMP +#pragma omp parallel for num_threads(4) +#endif for (int iTmp = 0; iTmp < nTracks; iTmp++) { auto& oTrack = (*outputTracks)[iTmp]; const int i = trackSort[iTmp].first; @@ -225,12 +232,12 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* nOutCl++; } } + clBuff = clusterOffsetCounter.fetch_add(nOutCl + (nOutCl + 1) / 2); oTrack.setClusterRef(clBuff, nOutCl); // register the references uint32_t* clIndArr = &(*outClusRefs)[clBuff]; // cluster indices start here uint8_t* sectorIndexArr = reinterpret_cast<uint8_t*>(clIndArr + nOutCl); uint8_t* rowIndexArr = sectorIndexArr + nOutCl; - clBuff += nOutCl + (nOutCl + 1) / 2; std::vector<std::pair<MCCompLabel, unsigned int>> labels; nOutCl = 0; for (int j = 0; j < tracks[i].NClusters(); j++) { @@ -282,9 +289,8 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* outputTracksMCTruth->addElement(iTmp, bestLabel); } } - int lastSector = trackClusters[tracks[i].FirstClusterRef() + tracks[i].NClusters() - 1].slice; } - outClusRefs->resize(clBuff); // remove overhead + outClusRefs->resize(clusterOffsetCounter.load()); // remove overhead if (data->o2Digits || data->tpcZS || data->compressedClusters) { data->clusters = ptrs.clustersNative; } diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index f6300053a017d..bba284aa634b9 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -416,8 +416,8 @@ endif() if(OpenMP_CXX_FOUND) message(STATUS "GPU: Using OpenMP: ${OpenMP_CXX_SPEC_DATE}") - target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) # Must be private, depending libraries might be compiled by compiler not understanding -fopenmp + target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) endif() From 9ea562e2bdeb46a86c91825f7daa83cac3c2a1e2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 1 Aug 2020 18:16:34 +0200 Subject: [PATCH 0221/1751] TPC: Don't allocate these buffers as std::vector to avoid zeroing the memory via the constructor --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 24 +++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index ea8be026291d7..e52c196ccd563 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -569,29 +569,31 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int GPUInterfaceOutputs outputRegions; std::optional<std::reference_wrapper<O2CharVectorOutputType>> clusterOutput = std::nullopt, bufferCompressedClusters = std::nullopt, bufferTPCTracks = std::nullopt; + char *clusterOutputChar = nullptr, *bufferCompressedClustersChar = nullptr, *bufferTPCTracksChar = nullptr; if (specconfig.outputCompClustersFlat) { if (processAttributes->allocateOutputOnTheFly) { - outputRegions.compressedClusters.allocator = [&bufferCompressedClusters, &pc](size_t size) -> void* {bufferCompressedClusters.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, size)); return bufferCompressedClusters->get().data(); }; + outputRegions.compressedClusters.allocator = [&bufferCompressedClustersChar, &pc](size_t size) -> void* {bufferCompressedClustersChar = pc.outputs().make<char>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, size).data(); return bufferCompressedClustersChar; }; } else { bufferCompressedClusters.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "COMPCLUSTERSFLAT", 0}, processAttributes->outputBufferSize)); - outputRegions.compressedClusters.ptr = bufferCompressedClusters->get().data(); + outputRegions.compressedClusters.ptr = bufferCompressedClustersChar = bufferCompressedClusters->get().data(); outputRegions.compressedClusters.size = bufferCompressedClusters->get().size(); } } if (processAttributes->clusterOutputIds.size() > 0) { if (processAttributes->allocateOutputOnTheFly) { - outputRegions.clustersNative.allocator = [&clusterOutput, &pc, clusterOutputSectorHeader](size_t size) -> void* {clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, size + sizeof(ClusterCountIndex))); return (char*)clusterOutput->get().data() + sizeof(ClusterCountIndex); }; + outputRegions.clustersNative.allocator = [&clusterOutputChar, &pc, clusterOutputSectorHeader](size_t size) -> void* {clusterOutputChar = pc.outputs().make<char>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, size + sizeof(ClusterCountIndex)).data(); return clusterOutputChar + sizeof(ClusterCountIndex); }; } else { clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, processAttributes->outputBufferSize)); - outputRegions.clustersNative.ptr = (char*)clusterOutput->get().data() + sizeof(ClusterCountIndex); - outputRegions.clustersNative.size = clusterOutput->get().size() * sizeof(*clusterOutput->get().data()) - sizeof(ClusterCountIndex); + clusterOutputChar = clusterOutput->get().data(); + outputRegions.clustersNative.ptr = clusterOutputChar + sizeof(ClusterCountIndex); + outputRegions.clustersNative.size = clusterOutput->get().size() - sizeof(ClusterCountIndex); } } if (processAttributes->allocateOutputOnTheFly) { - outputRegions.tpcTracks.allocator = [&bufferTPCTracks, &pc](size_t size) -> void* {bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, size)); return bufferTPCTracks->get().data(); }; + outputRegions.tpcTracks.allocator = [&bufferTPCTracksChar, &pc](size_t size) -> void* {bufferTPCTracksChar = pc.outputs().make<char>(Output{gDataOriginTPC, "TRACKSGPU", 0}, size).data(); return bufferTPCTracksChar; }; } else { bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, processAttributes->outputBufferSize)); - outputRegions.tpcTracks.ptr = bufferTPCTracks->get().data(); + outputRegions.tpcTracks.ptr = bufferTPCTracksChar = bufferTPCTracks->get().data(); outputRegions.tpcTracks.size = bufferTPCTracks->get().size(); } @@ -618,7 +620,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int if (!processAttributes->allocateOutputOnTheFly) { bufferCompressedClusters->get().resize(outputRegions.compressedClusters.size); } - if ((void*)ptrs.compressedClusters != (void*)bufferCompressedClusters->get().data()) { + if ((void*)ptrs.compressedClusters != (void*)bufferCompressedClustersChar) { throw std::runtime_error("compressed cluster output ptrs out of sync"); // sanity check } } @@ -636,18 +638,18 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } // previously, clusters have been published individually for the enabled sectors // clusters are now published as one block, subspec is NSectors - if (clusterOutput) { + if (processAttributes->clusterOutputIds.size() > 0) { if (!processAttributes->allocateOutputOnTheFly) { clusterOutput->get().resize(sizeof(ClusterCountIndex) + outputRegions.clustersNative.size); } - if ((void*)ptrs.clusters->clustersLinear != (void*)((char*)clusterOutput->get().data() + sizeof(ClusterCountIndex))) { + if ((void*)ptrs.clusters->clustersLinear != (void*)(clusterOutputChar + sizeof(ClusterCountIndex))) { throw std::runtime_error("cluster native output ptrs out of sync"); // sanity check } o2::header::DataHeader::SubSpecificationType subspec = NSectors; // doing a copy for now, in the future the tracker uses the output buffer directly ClusterNativeAccess const& accessIndex = *ptrs.clusters; - ClusterCountIndex* outIndex = reinterpret_cast<ClusterCountIndex*>(clusterOutput->get().data()); + ClusterCountIndex* outIndex = reinterpret_cast<ClusterCountIndex*>(clusterOutputChar); static_assert(sizeof(ClusterCountIndex) == sizeof(accessIndex.nClusters)); memcpy(outIndex, &accessIndex.nClusters[0][0], sizeof(ClusterCountIndex)); if (specconfig.processMC && accessIndex.clustersMCTruth) { From 8b90475047761ace17c8e4fb20edca1b27ea3e74 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 2 Aug 2020 09:29:34 +0200 Subject: [PATCH 0222/1751] GPU: Disable OMP for TPC track output if MC labels are present since the container is not thread safe --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 83d1170dad14f..f7eca85185a19 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -160,7 +160,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* clusterOffsetCounter.store(0); #ifdef WITH_OPENMP -#pragma omp parallel for num_threads(4) +#pragma omp parallel for if(!outputTracksMCTruth) num_threads(4) #endif for (int iTmp = 0; iTmp < nTracks; iTmp++) { auto& oTrack = (*outputTracks)[iTmp]; From f2c6dbab2f895417a1d79961411496403e733e1a Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Thu, 23 Jul 2020 21:43:47 +0300 Subject: [PATCH 0223/1751] tune CTF --- .../FIT/FT0/include/DataFormatsFT0/CTF.h | 12 +++--- DataFormats/Detectors/FIT/FT0/src/CTF.cxx | 3 +- Detectors/CTF/test/test_ctf_io_ft0.cxx | 29 +++++++++------ .../FIT/FT0/base/include/FT0Base/Geometry.h | 2 +- .../include/FT0Reconstruction/CTFCoder.h | 37 +++++++++++-------- .../FIT/FT0/reconstruction/src/CTFCoder.cxx | 4 +- 6 files changed, 52 insertions(+), 35 deletions(-) diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h index 6df5bc3dddaf6..1989a8f2df02c 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h @@ -43,12 +43,13 @@ struct CompressedDigits { std::vector<uint16_t> bcInc; // increment in BC if the same orbit, otherwise abs bc std::vector<uint32_t> orbitInc; // increment in orbit std::vector<uint8_t> nChan; // number of fired channels + // std::vector<uint8_t> eventFlags; // special flags about event conditions: pile-up, not use for collision time, not use for event plane, etc. // channel data std::vector<uint8_t> idChan; // channels ID: 1st on absolute, then increment std::vector<int16_t> cfdTime; // CFD time - std::vector<uint32_t> qtcAmpl; // Amplitude - std::vector<uint8_t> qtc; // QTC + std::vector<int16_t> qtcAmpl; // Amplitude + std::vector<uint8_t> qtcChain; // QTC chain CompressedDigits() = default; @@ -66,11 +67,12 @@ struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 8, uint32_t> { BLC_bcInc, // increment in BC BLC_orbitInc, // increment in orbit BLC_nChan, // number of fired channels + // BLC_flags, // flags special flags about event conditions: pile-up, not use for collision time, not use for event plane, etc. BLC_idChan, // channels ID: 1st on absolute, then increment - BLC_qtc, // QTC + BLC_qtcChain, // ADC chain BLC_cfdTime, // CFD time - BLC_qtcAmpl - }; // Amplitude + BLC_qtcAmpl // amplitude + }; ClassDefNV(CTF, 1); }; diff --git a/DataFormats/Detectors/FIT/FT0/src/CTF.cxx b/DataFormats/Detectors/FIT/FT0/src/CTF.cxx index 6e6d214c6e943..8298be41f5b84 100644 --- a/DataFormats/Detectors/FIT/FT0/src/CTF.cxx +++ b/DataFormats/Detectors/FIT/FT0/src/CTF.cxx @@ -22,9 +22,10 @@ void CompressedDigits::clear() bcInc.clear(); orbitInc.clear(); nChan.clear(); + // eventFlags.clear(); idChan.clear(); - qtc.clear(); + qtcChain.clear(); cfdTime.clear(); qtcAmpl.clear(); diff --git a/Detectors/CTF/test/test_ctf_io_ft0.cxx b/Detectors/CTF/test/test_ctf_io_ft0.cxx index 709e9712be989..e9cddf0abe8f8 100644 --- a/Detectors/CTF/test/test_ctf_io_ft0.cxx +++ b/Detectors/CTF/test/test_ctf_io_ft0.cxx @@ -33,13 +33,14 @@ BOOST_AUTO_TEST_CASE(CTFTest) sw.Start(); o2::InteractionRecord ir(0, 0); + int mTime_trg_gate = 192; // #channels constexpr int MAXChan = 4 * (Geometry::NCellsA + Geometry::NCellsC); for (int idig = 0; idig < 1000; idig++) { ir += 1 + gRandom->Integer(200); uint8_t ich = gRandom->Poisson(10); auto start = channels.size(); int32_t tMeanA = 0, tMeanC = 0; - uint32_t ampTotA = 0, ampTotC = 0; + int32_t ampTotA = 0, ampTotC = 0; Triggers trig; trig.triggersignals = gRandom->Integer(128); while (ich < MAXChan) { @@ -47,24 +48,26 @@ BOOST_AUTO_TEST_CASE(CTFTest) uint16_t q = gRandom->Integer(4096); uint8_t chain = gRandom->Rndm() > 0.5 ? 0 : 1; channels.emplace_back(ich, t, q, chain); - if (ich < 4 * uint8_t(Geometry::NCellsA)) { - trig.nChanA++; - ampTotA += q; - tMeanA += t; - } else { - trig.nChanC++; - ampTotC += q; - tMeanC += t; + if (std::abs(t) < Geometry::mTime_trg_gate) { + if (ich < 4 * uint8_t(Geometry::NCellsA)) { + trig.nChanA++; + ampTotA += q; + tMeanA += t; + } else { + trig.nChanC++; + ampTotC += q; + tMeanC += t; + } } ich += 1 + gRandom->Poisson(10); } if (trig.nChanA) { trig.timeA = tMeanA / trig.nChanA; - trig.amplA = ampTotA; + trig.amplA = ampTotA * 0.125; } if (trig.nChanC) { trig.timeC = tMeanC / trig.nChanC; - trig.amplC = ampTotC; + trig.amplC = ampTotC * 0.125; // sum/8 } auto end = channels.size(); digits.emplace_back(start, end - start, ir, trig, idig); @@ -114,10 +117,14 @@ BOOST_AUTO_TEST_CASE(CTFTest) BOOST_CHECK(digitsD.size() == digits.size()); BOOST_CHECK(channelsD.size() == channels.size()); + LOG(INFO) << " BOOST_CHECK digitsD.size() " << digitsD.size() << " digits.size() " << digits.size() << " BOOST_CHECK(channelsD.size() " << channelsD.size() << " channels.size()) " << channels.size(); for (int i = digits.size(); i--;) { const auto& dor = digits[i]; const auto& ddc = digitsD[i]; + LOG(INFO) << " dor " << dor.mTriggers.nChanA << " " << dor.mTriggers.nChanC << " " << dor.mTriggers.amplA << " " << dor.mTriggers.amplC; + LOG(INFO) << " ddc " << ddc.mTriggers.nChanA << " " << ddc.mTriggers.nChanC << " " << ddc.mTriggers.amplA << " " << ddc.mTriggers.amplC; + BOOST_CHECK(dor.mIntRecord == ddc.mIntRecord); BOOST_CHECK(dor.mTriggers.nChanA == ddc.mTriggers.nChanA); BOOST_CHECK(dor.mTriggers.nChanC == ddc.mTriggers.nChanC); diff --git a/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h b/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h index fc6eae1755528..9d405806424e6 100644 --- a/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h +++ b/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h @@ -43,7 +43,7 @@ class Geometry static constexpr float ChannelWidth = 13.02; // channel width in ps static constexpr float MV_2_Nchannels = 2.2857143; //amplitude channel 7 mV ->16channels static constexpr float MV_2_NchannelsInverse = 0.437499997; //inverse amplitude channel 7 mV ->16channels - /// + static constexpr int mTime_trg_gate = 192; // #channels private: TVector3 mMCP[52]; diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index 5c1970c34638f..88746ec85cda8 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -68,8 +68,9 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g MD::EENCODE, // BLC_bcInc MD::EENCODE, // BLC_orbitInc MD::EENCODE, // BLC_nChan + // MD::EENCODE, // BLC_flags MD::EENCODE, // BLC_idChan - MD::EENCODE, // BLC_qtc + MD::EENCODE, // BLC_qtcChain MD::EENCODE, // BLC_cfdTime MD::EENCODE // BLC_qtcAmpl }; @@ -88,8 +89,9 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g ENCODE(cd.bcInc, CTF::BLC_bcInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_bcInc], &buff); ENCODE(cd.orbitInc, CTF::BLC_orbitInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_orbitInc], &buff); ENCODE(cd.nChan, CTF::BLC_nChan, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_nChan], &buff); + // ENCODE(cd.eventFlags, CTF::BLC_flags, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_flags], &buff); ENCODE(cd.idChan , CTF::BLC_idChan, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_idChan], &buff); - ENCODE(cd.qtc , CTF::BLC_qtc, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_qtc], &buff); + ENCODE(cd.qtcChain, CTF::BLC_qtcChain, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_qtcChain], &buff); ENCODE(cd.cfdTime, CTF::BLC_cfdTime, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_cfdTime], &buff); ENCODE(cd.qtcAmpl, CTF::BLC_qtcAmpl, o2::rans::ProbabilityBits25Bit, optField[CTF::BLC_qtcAmpl], &buff); // clang-format on @@ -106,8 +108,9 @@ void CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec) ec.decode(cd.bcInc, CTF::BLC_bcInc); ec.decode(cd.orbitInc, CTF::BLC_orbitInc); ec.decode(cd.nChan, CTF::BLC_nChan); - ec.decode(cd.idChan , CTF::BLC_idChan); - ec.decode(cd.qtc , CTF::BLC_qtc); + // ec.decode(cd.eventFlags, CTF::BLC_flags); + ec.decode(cd.idChan, CTF::BLC_idChan); + ec.decode(cd.qtcChain, CTF::BLC_qtcChain); ec.decode(cd.cfdTime, CTF::BLC_cfdTime); ec.decode(cd.qtcAmpl, CTF::BLC_qtcAmpl); // clang-format on @@ -141,28 +144,32 @@ void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& cha firstEntry = channelVec.size(); uint8_t chID = 0; int amplA = 0, amplC = 0, timeA = 0, timeC = 0; + // int mTime_trg_gate = 192; // #channels for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { auto icc = channelVec.size(); - const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtc[icc]); + const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtcChain[icc]); // // rebuild digit - if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side - trig.nChanA++; - amplA += chan.QTCAmpl; - timeA += chan.CFDTime; - } else { - trig.nChanC++; - amplC += chan.QTCAmpl; - timeC += chan.CFDTime; + if (std::abs(chan.CFDTime) < Geometry::mTime_trg_gate) { + if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side + amplA += chan.QTCAmpl; + timeA += chan.CFDTime; + trig.nChanA++; + + } else { + amplC += chan.QTCAmpl; + timeC += chan.CFDTime; + trig.nChanC++; + } } } if (trig.nChanA) { trig.timeA = timeA / trig.nChanA; - trig.amplA = amplA; + trig.amplA = amplA / 8; } if (trig.nChanC) { trig.timeC = timeC / trig.nChanC; - trig.amplC = amplC; + trig.amplC = amplC / 8; } digitVec.emplace_back(firstEntry, cd.nChan[idig], ir, trig, idig); } diff --git a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx index 2140a80cb9d0e..70036155daa3b 100644 --- a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx @@ -55,7 +55,7 @@ void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digi cd.nChan.resize(cd.header.nTriggers); cd.idChan.resize(channelVec.size()); - cd.qtc.resize(channelVec.size()); + cd.qtcChain.resize(channelVec.size()); cd.cfdTime.resize(channelVec.size()); cd.qtcAmpl.resize(channelVec.size()); @@ -87,7 +87,7 @@ void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digi for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { assert(prevChan <= chanels[ic].ChId); cd.idChan[ccount] = chanels[ic].ChId - prevChan; - cd.qtc[ccount] = chanels[ic].ChainQTC; + cd.qtcChain[ccount] = chanels[ic].ChainQTC; cd.cfdTime[ccount] = chanels[ic].CFDTime; cd.qtcAmpl[ccount] = chanels[ic].QTCAmpl; prevChan = chanels[ic].ChId; From 8b84a136f3b84b877cac3a469dacdf9b3a445e30 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 1 Aug 2020 17:58:03 +0200 Subject: [PATCH 0224/1751] speed-up rANS cumulated frequency algorithm --- .../rANS/include/rANS/SymbolStatistics.h | 3 +- Utilities/rANS/src/SymbolStatistics.cxx | 73 ++++++++++--------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/Utilities/rANS/include/rANS/SymbolStatistics.h b/Utilities/rANS/include/rANS/SymbolStatistics.h index 613cfba0d2809..11f4dc5993748 100644 --- a/Utilities/rANS/include/rANS/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/SymbolStatistics.h @@ -84,7 +84,7 @@ class SymbolStatistics private: void buildCumulativeFrequencyTable(); - + auto getCumulativeFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } template <typename IT> void buildFrequencyTable(const IT begin, const IT end, size_t range); @@ -92,7 +92,6 @@ class SymbolStatistics int64_t mMax; size_t mNUsedAlphabetSymbols; size_t mMessageLength; - std::vector<uint32_t> mFrequencyTable; std::vector<uint32_t> mCumulativeFrequencyTable; }; diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx index 29f5264913148..15b59e85554c0 100644 --- a/Utilities/rANS/src/SymbolStatistics.cxx +++ b/Utilities/rANS/src/SymbolStatistics.cxx @@ -38,45 +38,50 @@ void SymbolStatistics::rescaleToNBits(size_t bits) assert(newCumulatedFrequency >= mFrequencyTable.size()); size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); + std::vector<uint32_t> sortIdx; + sortIdx.reserve(mNUsedAlphabetSymbols); // resample distribution based on cumulative frequencies_ - for (size_t i = 1; i <= mFrequencyTable.size(); i++) - mCumulativeFrequencyTable[i] = - (static_cast<uint64_t>(newCumulatedFrequency) * - mCumulativeFrequencyTable[i]) / - cumulatedFrequencies; + for (size_t i = 0; i < mFrequencyTable.size();) { + if (mFrequencyTable[i]) { + sortIdx.push_back(i); // we will sort only those memorize only those entries which can be used + } + i++; + mCumulativeFrequencyTable[i] = (static_cast<uint64_t>(newCumulatedFrequency) * mCumulativeFrequencyTable[i]) / cumulatedFrequencies; + } + + std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getCumulativeFrequency(i) < this->getCumulativeFrequency(j); }); + size_t nonZeroStart = 0; + while (getCumulativeFrequency(sortIdx[nonZeroStart]) == 0) { // find elements whose frequency was rounded to 0 + nonZeroStart++; + } + size_t aboveOne = nonZeroStart; + while (getCumulativeFrequency(sortIdx[aboveOne]) == 1 && aboveOne < mNUsedAlphabetSymbols) { // // find elements whose frequency >1 + aboveOne++; + } + assert(nonZeroStart < mNUsedAlphabetSymbols && aboveOne < mNUsedAlphabetSymbols); // if we nuked any non-0 frequency symbol to 0, we need to steal // the range to make the frequency nonzero from elsewhere. // - // this is not at all optimal, i'm just doing the first thing that comes to - // mind. - for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i] && - mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]) { - // symbol i was set to zero freq - - // find best symbol to steal frequency from (try to steal from low-freq - // ones) - std::pair<size_t, size_t> stealFromEntry{mFrequencyTable.size(), ~0u}; - for (size_t j = 0; j < mFrequencyTable.size(); j++) { - uint32_t frequency = - mCumulativeFrequencyTable[j + 1] - mCumulativeFrequencyTable[j]; - if (frequency > 1 && frequency < stealFromEntry.second) { - stealFromEntry.second = frequency; - stealFromEntry.first = j; - } + for (int i = 0; i < nonZeroStart; i++) { + auto iZero = sortIdx[i]; + // steal from smallest frequency>1 element + while (getCumulativeFrequency(sortIdx[aboveOne]) < 2 && aboveOne < mNUsedAlphabetSymbols) { // in case the frequency became 1, use next element + aboveOne++; + } + assert(aboveOne < mNUsedAlphabetSymbols); + auto iSteal = sortIdx[aboveOne]; + + // and steal from it! + if (iSteal < iZero) { + for (size_t j = iSteal + 1; j <= iZero; j++) { + mCumulativeFrequencyTable[j]--; } - assert(stealFromEntry.first != mFrequencyTable.size()); - - // and steal from it! - if (stealFromEntry.first < i) { - for (size_t j = stealFromEntry.first + 1; j <= i; j++) - mCumulativeFrequencyTable[j]--; - } else { - assert(stealFromEntry.first > i); - for (size_t j = i + 1; j <= stealFromEntry.first; j++) - mCumulativeFrequencyTable[j]++; + } else { + assert(iSteal > iZero); + for (size_t j = iZero + 1; j <= iSteal; j++) { + mCumulativeFrequencyTable[j]++; } } } @@ -84,6 +89,7 @@ void SymbolStatistics::rescaleToNBits(size_t bits) // calculate updated freqs and make sure we didn't screw anything up assert(mCumulativeFrequencyTable.front() == 0 && mCumulativeFrequencyTable.back() == newCumulatedFrequency); + for (size_t i = 0; i < mFrequencyTable.size(); i++) { if (mFrequencyTable[i] == 0) assert(mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]); @@ -91,8 +97,7 @@ void SymbolStatistics::rescaleToNBits(size_t bits) assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); // calc updated freq - mFrequencyTable[i] = - mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; + mFrequencyTable[i] = getCumulativeFrequency(i); } // for(int i = 0; i<static_cast<int>(freqs.getNumSymbols()); i++){ // std::cout << i << ": " << i + min_ << " " << freqs[i] << " " << From 93bf6f152e87b5c6447612cc3cfe2fb704e71438 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 2 Aug 2020 00:08:47 +0200 Subject: [PATCH 0225/1751] Simplify and speedup rANS cumulated frequency algorithm --- .../rANS/include/rANS/SymbolStatistics.h | 2 +- Utilities/rANS/src/SymbolStatistics.cxx | 55 +++++++------------ 2 files changed, 20 insertions(+), 37 deletions(-) diff --git a/Utilities/rANS/include/rANS/SymbolStatistics.h b/Utilities/rANS/include/rANS/SymbolStatistics.h index 11f4dc5993748..3d643be6d64e9 100644 --- a/Utilities/rANS/include/rANS/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/SymbolStatistics.h @@ -84,7 +84,7 @@ class SymbolStatistics private: void buildCumulativeFrequencyTable(); - auto getCumulativeFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } + auto getFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } template <typename IT> void buildFrequencyTable(const IT begin, const IT end, size_t range); diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx index 15b59e85554c0..97c2a4e92f061 100644 --- a/Utilities/rANS/src/SymbolStatistics.cxx +++ b/Utilities/rANS/src/SymbolStatistics.cxx @@ -38,53 +38,36 @@ void SymbolStatistics::rescaleToNBits(size_t bits) assert(newCumulatedFrequency >= mFrequencyTable.size()); size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); + std::vector<uint32_t> sortIdx; sortIdx.reserve(mNUsedAlphabetSymbols); // resample distribution based on cumulative frequencies_ - for (size_t i = 0; i < mFrequencyTable.size();) { + for (size_t i = 0; i < mFrequencyTable.size(); i++) { if (mFrequencyTable[i]) { sortIdx.push_back(i); // we will sort only those memorize only those entries which can be used } - i++; - mCumulativeFrequencyTable[i] = (static_cast<uint64_t>(newCumulatedFrequency) * mCumulativeFrequencyTable[i]) / cumulatedFrequencies; } - std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getCumulativeFrequency(i) < this->getCumulativeFrequency(j); }); - size_t nonZeroStart = 0; - while (getCumulativeFrequency(sortIdx[nonZeroStart]) == 0) { // find elements whose frequency was rounded to 0 - nonZeroStart++; - } - size_t aboveOne = nonZeroStart; - while (getCumulativeFrequency(sortIdx[aboveOne]) == 1 && aboveOne < mNUsedAlphabetSymbols) { // // find elements whose frequency >1 - aboveOne++; - } - assert(nonZeroStart < mNUsedAlphabetSymbols && aboveOne < mNUsedAlphabetSymbols); - - // if we nuked any non-0 frequency symbol to 0, we need to steal - // the range to make the frequency nonzero from elsewhere. - // - for (int i = 0; i < nonZeroStart; i++) { - auto iZero = sortIdx[i]; - // steal from smallest frequency>1 element - while (getCumulativeFrequency(sortIdx[aboveOne]) < 2 && aboveOne < mNUsedAlphabetSymbols) { // in case the frequency became 1, use next element - aboveOne++; + std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getFrequency(i) < this->getFrequency(j); }); + size_t need_shift = 0; + for (size_t i = 0; i < sortIdx.size(); i++) { + if (static_cast<uint64_t>(getFrequency(sortIdx[i])) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies >= 1) { + break; } - assert(aboveOne < mNUsedAlphabetSymbols); - auto iSteal = sortIdx[aboveOne]; - - // and steal from it! - if (iSteal < iZero) { - for (size_t j = iSteal + 1; j <= iZero; j++) { - mCumulativeFrequencyTable[j]--; - } - } else { - assert(iSteal > iZero); - for (size_t j = iZero + 1; j <= iSteal; j++) { - mCumulativeFrequencyTable[j]++; - } + need_shift++; + } + + size_t shift = 0; + auto beforeUpdate = mCumulativeFrequencyTable[0]; + for (size_t i = 0; i < mFrequencyTable.size(); i++) { + if (mFrequencyTable[i] && static_cast<uint64_t>(mCumulativeFrequencyTable[i + 1] - beforeUpdate) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies < 1) { + shift++; } + beforeUpdate = mCumulativeFrequencyTable[i + 1]; + mCumulativeFrequencyTable[i + 1] = (static_cast<uint64_t>(newCumulatedFrequency - need_shift) * mCumulativeFrequencyTable[i + 1]) / cumulatedFrequencies + shift; } + assert(shift == need_shift); // calculate updated freqs and make sure we didn't screw anything up assert(mCumulativeFrequencyTable.front() == 0 && @@ -97,7 +80,7 @@ void SymbolStatistics::rescaleToNBits(size_t bits) assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); // calc updated freq - mFrequencyTable[i] = getCumulativeFrequency(i); + mFrequencyTable[i] = getFrequency(i); } // for(int i = 0; i<static_cast<int>(freqs.getNumSymbols()); i++){ // std::cout << i << ": " << i + min_ << " " << freqs[i] << " " << From 6e09776470e62d3afdb1d5ec97edf98a83ecfbed Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 2 Aug 2020 15:05:44 +0200 Subject: [PATCH 0226/1751] GPU: Increase required CUDA min memory margin to avoid failus in CUDA backend with memory auto-detection --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index d514d753c54b3..86a35195018cd 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -46,7 +46,7 @@ static constexpr size_t REQUIRE_MIN_MEMORY = 1024u * 1024 * 1024; static constexpr size_t REQUIRE_MEMORY_RESERVED = 512u * 1024 * 1024; -static constexpr size_t REQUIRE_FREE_MEMORY_RESERVED = 1280u * 1024 * 1024; +static constexpr size_t REQUIRE_FREE_MEMORY_RESERVED = 2048u * 1024 * 1024; using namespace GPUCA_NAMESPACE::gpu; From c4974968429c67472d53101ccbe978b98769d6fe Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 2 Aug 2020 15:33:06 +0200 Subject: [PATCH 0227/1751] GPU: Fix todo - use zOffset in track model compression --- .../DataCompression/GPUTPCCompressionKernels.cxx | 8 +++++--- .../DataCompression/TPCClusterDecompressor.cxx | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 4b2eea14dc9e0..5d01bd41fa213 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -43,6 +43,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at CompressedClustersPtrs& GPUrestrict() c = compressor.mPtrs; unsigned int lastRow = 0, lastSlice = 0; // BUG: These should be unsigned char, but then CUDA breaks GPUTPCCompressionTrackModel track; + float zOffset = 0; for (int k = trk.NClusters() - 1; k >= 0; k--) { const GPUTPCGMMergedTrackHit& GPUrestrict() hit = merger.Clusters()[trk.FirstClusterRef() + k]; if (hit.state & GPUTPCGMMergedTrackHit::flagReject) { @@ -84,7 +85,8 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at int cidx = trk.FirstClusterRef() + nClustersStored++; if (nClustersStored == 1) { unsigned char qpt = fabs(trk.GetParam().GetQPt()) < 20.f ? (trk.GetParam().GetQPt() * (127.f / 20.f) + 127.5f) : (trk.GetParam().GetQPt() > 0 ? 254 : 0); - track.Init(x, y, z, param.SliceParam[hit.slice].Alpha, qpt, param); // TODO: Compression track model must respect Z offset! + zOffset = z; + track.Init(x, y, z - zOffset, param.SliceParam[hit.slice].Alpha, qpt, param); myTrack = CAMath::AtomicAdd(&compressor.mMemory->nStoredTracks, 1u); compressor.mAttachedClusterFirstIndex[myTrack] = trk.FirstClusterRef(); @@ -112,7 +114,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at c.sliceLegDiffA[cidx] = (hit.leg == lastLeg ? 0 : compressor.NSLICES) + slice; float pad = CAMath::Max(0.f, CAMath::Min((float)param.tpcGeometry.NPads(GPUCA_ROW_COUNT - 1), param.tpcGeometry.LinearY2Pad(hit.slice, hit.row, track.Y()))); c.padResA[cidx] = orgCl.padPacked - orgCl.packPad(pad); - float time = CAMath::Max(0.f, param.tpcGeometry.LinearZ2Time(hit.slice, track.Z())); + float time = CAMath::Max(0.f, param.tpcGeometry.LinearZ2Time(hit.slice, track.Z() + zOffset)); c.timeResA[cidx] = (orgCl.getTimePacked() - orgCl.packTime(time)) & 0xFFFFFF; lastLeg = hit.leg; } @@ -129,7 +131,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at c.sigmaPadA[cidx] = sigmapad; c.sigmaTimeA[cidx] = sigmatime; c.flagsA[cidx] = orgCl.getFlags(); - if (k && track.Filter(y, z, hit.row)) { + if (k && track.Filter(y, z - zOffset, hit.row)) { break; } lastRow = hit.row; diff --git a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx index fa55bbe7f0988..51df22a39a175 100644 --- a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx +++ b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx @@ -38,6 +38,7 @@ int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompres { std::vector<ClusterNative> clusters[NSLICES][GPUCA_ROW_COUNT]; unsigned int offset = 0; + float zOffset = 0; for (unsigned int i = 0; i < clustersCompressed->nTracks; i++) { unsigned int slice = clustersCompressed->sliceA[i]; unsigned int row = clustersCompressed->rowA[i]; @@ -75,7 +76,7 @@ int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompres if (timeTmp & 800000) { timeTmp |= 0xFF000000; } - time = timeTmp + ClusterNative::packTime(CAMath::Max(0.f, param.tpcGeometry.LinearZ2Time(slice, track.Z()))); + time = timeTmp + ClusterNative::packTime(CAMath::Max(0.f, param.tpcGeometry.LinearZ2Time(slice, track.Z() + zOffset))); float tmpPad = CAMath::Max(0.f, CAMath::Min((float)param.tpcGeometry.NPads(GPUCA_ROW_COUNT - 1), param.tpcGeometry.LinearY2Pad(slice, row, track.Y()))); pad = clustersCompressed->padResA[offset - i - 1] + ClusterNative::packPad(tmpPad); } else { @@ -87,9 +88,10 @@ int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompres float y = param.tpcGeometry.LinearPad2Y(slice, row, clusterVector.back().getPad()); float z = param.tpcGeometry.LinearTime2Z(slice, clusterVector.back().getTime()); if (j == 0) { - track.Init(param.tpcGeometry.Row2X(row), y, z, param.SliceParam[slice].Alpha, clustersCompressed->qPtA[i], param); + zOffset = z; + track.Init(param.tpcGeometry.Row2X(row), y, z - zOffset, param.SliceParam[slice].Alpha, clustersCompressed->qPtA[i], param); } - if (j + 1 < clustersCompressed->nTrackClusters[i] && track.Filter(y, z, row)) { + if (j + 1 < clustersCompressed->nTrackClusters[i] && track.Filter(y, z - zOffset, row)) { offset += clustersCompressed->nTrackClusters[i] - j; break; } From aa4a137cd1bc1168d6a5d0641327879bb4d3bd0b Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 3 Aug 2020 03:48:22 +0200 Subject: [PATCH 0228/1751] fix data splitting for in some marginal cases --- .../common/simulation/src/MC2RawEncoder.cxx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx b/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx index b85c57166f54c..cb61faa5fc3cc 100644 --- a/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx +++ b/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx @@ -287,16 +287,19 @@ int MC2RawEncoder<Mapping>::carryOverMethod(const header::RDHAny* rdh, const gsl // make sure ptr and end of the suggested block are within the payload assert(offs >= 0 && size_t(offs + maxSize) <= data.size()); - if ((maxSize <= TotServiceSize)) { // we cannot split trigger+header - return 0; // suggest moving the whole payload to the new CRU page - } - // this is where we would usually split: account for the trailer to add int actualSize = maxSize - sizeof(GBTDataTrailer); - char* trailPtr = &data[data.size() - sizeof(GBTDataTrailer)]; // pointer on the payload trailer - if (ptr + actualSize >= trailPtr) { // we need to split at least 1 GBT word before the trailer - actualSize = trailPtr - ptr - GBTPaddedWordLength; + + if ((maxSize <= TotServiceSize)) { // we cannot split trigger+header + actualSize = 0; // suggest moving the whole payload to the new CRU page + if (offs == 0) { // just carry over everything, trigger+header was not yet written + return actualSize; + } + } else { + if (ptr + actualSize >= trailPtr) { // we need to split at least 1 GBT word before the trailer + actualSize = trailPtr - ptr - GBTPaddedWordLength; + } } // copy the GBTTrigger and GBTHeader from the head of the payload header.resize(TrigHeadSize); From b5b538995078db577663801c0bce9b55be64410b Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 3 Aug 2020 03:49:02 +0200 Subject: [PATCH 0229/1751] ITS feeID to per-link raw data file names --- Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx b/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx index e1fe768bf41b5..4514ba3e2c4c7 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx @@ -273,7 +273,8 @@ void setupLinks(o2::itsmft::MC2RawEncoder<MAP>& m2r, std::string_view outDir, st outFileLink = o2::utils::concat_string(outDir, "/", outPrefix, "_cru", std::to_string(cruID), ".raw"); } else if (fileFor == "link") { outFileLink = o2::utils::concat_string(outDir, "/", outPrefix, "_cru", std::to_string(cruID), - "_link", std::to_string(linkID), "_ep", std::to_string(link->endPointID), ".raw"); + "_link", std::to_string(linkID), "_ep", std::to_string(link->endPointID), + "_feeid", std::to_string(link->feeID), ".raw"); } else { throw std::runtime_error("invalid option provided for file grouping"); } From 6b2d798a76ad48c18b9eb948be1cfee9f7800cf4 Mon Sep 17 00:00:00 2001 From: Ivana Hrivnacova <Ivana.Hrivnacova@cern.ch> Date: Wed, 29 Jul 2020 15:27:33 +0200 Subject: [PATCH 0230/1751] Fix in Generators CMake: Replaced install(FILES ..) with o2_data_file(..) macro; this avoids o2sim_G3/4 ctest failures due to missing generators directory in the 'stage' directory in build. --- Generators/CMakeLists.txt | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index fc33264049b34..f8651bb079625 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -139,20 +139,6 @@ o2_add_test_root_macro(share/egconfig/pythia8_userhooks_charm.C LABELS generators) endif() -install(FILES share/external/extgen.C share/external/pythia6.C - share/external/tgenerator.C share/external/QEDLoader.C share/external/QEDepem.C - share/external/trigger_multiplicity.C - share/external/trigger_mpi.C - DESTINATION share/Generators/external/) - -install(FILES share/egconfig/pythia8_inel.cfg - share/egconfig/pythia8_hf.cfg - share/egconfig/pythia8_hi.cfg - share/egconfig/pythia8_userhooks_charm.C - DESTINATION share/Generators/egconfig/) - -install(FILES share/pythia8/decays/base.cfg - share/pythia8/decays/bjpsidimuon.cfg - DESTINATION share/Generators/pythia8/decays/) - - +o2_data_file(COPY share/external DESTINATION Generators) +o2_data_file(COPY share/egconfig DESTINATION Generators) +o2_data_file(COPY share/pythia8 DESTINATION Generators) From 299c914043d8427280c4543eb5cc9a13a734f406 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Tue, 28 Jul 2020 08:20:35 +0200 Subject: [PATCH 0231/1751] Flag to allow use of compressed decoder in CONET mode --- .../reconstruction/include/TOFReconstruction/DecoderBase.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h index a03744814cdc2..bef010acc2cd7 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h @@ -41,6 +41,10 @@ class DecoderBaseT inline bool run() { rewind(); + if (mDecoderCONET) { + mDecoderPointerMax = reinterpret_cast<const uint32_t*>(mDecoderBuffer + mDecoderBufferSize); + return processDRM(); + } while (!processHBF()) ; return false; @@ -54,6 +58,7 @@ class DecoderBaseT void setDecoderVerbose(bool val) { mDecoderVerbose = val; }; void setDecoderBuffer(const char* val) { mDecoderBuffer = val; }; void setDecoderBufferSize(long val) { mDecoderBufferSize = val; }; + void setDecoderCONET(bool val) { mDecoderCONET = val; }; private: /** handlers **/ @@ -88,6 +93,7 @@ class DecoderBaseT bool mDecoderVerbose = false; bool mDecoderError = false; bool mDecoderFatal = false; + bool mDecoderCONET = false; char mDecoderSaveBuffer[1048576]; uint32_t mDecoderSaveBufferDataSize = 0; uint32_t mDecoderSaveBufferDataLeft = 0; From 748fc64ae4e34c830840100c2e1d77e652a86aa4 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Sat, 25 Jul 2020 16:46:40 +0200 Subject: [PATCH 0232/1751] fix trapsimulator output for raw, add 64 bit tracklets, add linkrecord. --- DataFormats/Detectors/TRD/CMakeLists.txt | 17 +- .../TRD/include/DataFormatsTRD/LinkRecord.h | 62 +++++ .../TRD/include/DataFormatsTRD/RawData.h | 230 ++++-------------- .../TRD/include/DataFormatsTRD/Tracklet64.h | 76 +++--- .../Detectors/TRD/src/DataFormatsTRDLinkDef.h | 8 +- DataFormats/Detectors/TRD/src/LinkRecord.cxx | 32 +++ DataFormats/Detectors/TRD/src/RawData.cxx | 164 ++++++++++++- DataFormats/Detectors/TRD/src/Tracklet64.cxx | 17 +- Detectors/TRD/base/CMakeLists.txt | 1 + Detectors/TRD/base/test/testRawData.cxx | 12 +- Detectors/TRD/macros/ParseTrapRawOutput.C | 64 +++++ Detectors/TRD/simulation/CMakeLists.txt | 3 +- .../include/TRDSimulation/TrapSimulator.h | 20 +- .../TRD/simulation/src/TrapSimulator.cxx | 185 ++++++++++---- Detectors/TRD/workflow/CMakeLists.txt | 1 + .../TRDWorkflow/TRDTrapRawWriterSpec.h | 40 +++ .../TRDWorkflow/TRDTrapSimulatorSpec.h | 19 +- .../workflow/src/TRDTrackletWriterSpec.cxx | 4 +- .../TRD/workflow/src/TRDTrapRawWriterSpec.cxx | 51 ++++ .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 148 +++++++---- .../workflow/src/TRDTrapSimulatorWorkFlow.cxx | 5 +- .../TRD/workflow/src/TRDWorkflowLinkDef.h | 2 +- cmake/O2RootMacroExclusionList.cmake | 1 + 23 files changed, 824 insertions(+), 338 deletions(-) create mode 100644 DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h create mode 100644 DataFormats/Detectors/TRD/src/LinkRecord.cxx create mode 100644 Detectors/TRD/macros/ParseTrapRawOutput.C create mode 100644 Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapRawWriterSpec.h create mode 100644 Detectors/TRD/workflow/src/TRDTrapRawWriterSpec.cxx diff --git a/DataFormats/Detectors/TRD/CMakeLists.txt b/DataFormats/Detectors/TRD/CMakeLists.txt index ea85f21d17999..4554b4df53635 100644 --- a/DataFormats/Detectors/TRD/CMakeLists.txt +++ b/DataFormats/Detectors/TRD/CMakeLists.txt @@ -10,15 +10,14 @@ o2_add_library(DataFormatsTRD SOURCES src/TriggerRecord.cxx - src/RawData.cxx + src/LinkRecord.cxx src/Tracklet64.cxx - PUBLIC_LINK_LIBRARIES O2::CommonDataFormat - O2::SimulationDataFormat - O2::TRDBase - ) + src/RawData.cxx + PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::SimulationDataFormat) -o2_target_root_dictionary(DataFormatsTRD - HEADERS include/DataFormatsTRD/TriggerRecord.h - include/DataFormatsTRD/RawData.h - include/DataFormatsTRD/Tracklet64.h) + o2_target_root_dictionary(DataFormatsTRD + HEADERS include/DataFormatsTRD/TriggerRecord.h + include/DataFormatsTRD/LinkRecord.h + include/DataFormatsTRD/Tracklet64.h + include/DataFormatsTRD/RawData.h) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h new file mode 100644 index 0000000000000..f0bf477278351 --- /dev/null +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h @@ -0,0 +1,62 @@ +// 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_TRD_LINKRECORD_H +#define ALICEO2_TRD_LINKRECORD_H + +#include <iosfwd> +#include "Rtypes.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "CommonDataFormat/RangeReference.h" +#include "DataFormatsTRD/RawData.h" + +namespace o2 +{ + +namespace trd +{ + +/// \class LinkRecord +/// \brief Header for data corresponding to the indexing of the links in the raw data output +/// adapted from DataFormatsTRD/TriggerRecord +class LinkRecord +{ + using DataRange = o2::dataformats::RangeReference<int>; + + public: + LinkRecord() = default; + LinkRecord(const uint32_t hcid, int firstentry, int nentries) : mLinkId(hcid), mDataRange(firstentry, nentries) {} + ~LinkRecord() = default; + + void setLinkId(const uint32_t linkid) { mLinkId = linkid; } + 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; } + int getNumberOfObjects() const { return mDataRange.getEntries(); } + int getFirstEntry() const { return mDataRange.getFirstEntry(); } + + void printStream(std::ostream& stream) const; + + private: + uint32_t mLinkId; /// The link ID for this set of data, hcid as well + DataRange mDataRange; /// Index of the triggering event (event index and first entry in the container) + + ClassDefNV(LinkRecord, 1); +}; + +std::ostream& operator<<(std::ostream& stream, const LinkRecord& trg); + +} // namespace trd + +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h index 786d6ded2024f..5b4b3ac336e54 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -11,11 +11,8 @@ #ifndef ALICEO2_TRD_RAWDATA_H #define ALICEO2_TRD_RAWDATA_H -#include <iosfwd> -#include <iostream> -#include <iomanip> -#include <fstream> #include "fairlogger/Logger.h" + /// \class TRDRDH /// \brief Header for TRD raw data header // this is the header added by the CRU @@ -141,11 +138,11 @@ Word 7 | link 13 datasize | link 14 dat }; }; -/// \structure HalfChamberHeader +/// \structure TrackletHCHeader /// \brief Header for each half chamber // Coming before all other tracklet data, a single tracklet word as a header for its half chamber -struct HalfChamberHeader { +struct TrackletHCHeader { union { // 10987654321098765432109876543210 // uint32_t: 00000000000000000000000000000000 @@ -170,10 +167,10 @@ struct HalfChamberHeader { }; }; -/// \structure MCMRawDataHeader +/// \structure TrackletMCMHeader /// \brief Header for MCM tracklet data outuput -// This constitutes the "4x32" bits of information from a single MCM, MCMRawDataHeader and 1-3 TrapRawTracklet. -struct MCMRawDataHeader { +// This constitutes the "4x32" bits of information from a single MCM, TrackletMCMHeader and 1-3 TrackletMCMData. +struct TrackletMCMHeader { //first word * // 10987654321098765432109876543210 // uint32_t: 00000000000000000000000000000000 @@ -190,9 +187,9 @@ struct MCMRawDataHeader { uint32_t word; struct { uint32_t oneb : 1; // - uint32_t pid0 : 8; // 3 parts of pid for each tracklet - uint32_t pid1 : 8; // 3 parts of pid for each tracklet - uint32_t pid2 : 8; // 3 parts of pid for each tracklet + uint32_t pid0 : 8; // part of pid for tracklet 0 + uint32_t pid1 : 8; // part of pid for tracklet 1 + uint32_t pid2 : 8; // part of pid for tracklet 2 uint32_t col : 2; // 2 bits for position in pad direction. uint32_t padrow : 4; // padrow,z coordinate for chip. uint32_t onea : 1; // @@ -200,16 +197,16 @@ struct MCMRawDataHeader { }; }; -// \structure TrapRawTracklet. +// \structure TrackletMCMData. // \brief Raw Data of a tracklet, part is how ever in the MCM Header hence both are grouped together in the same file -struct TrapRawTracklet { // This is a bad name as part of the tracklet data is in the MCMHeader. +struct TrackletMCMData { // This is a bad name as part of the tracklet data is in the MCMHeader. union { uint32_t word; struct { - uint8_t checkbit : 1; // The size of the data for this link - uint16_t pid : 15; // Particle Identity + uint8_t checkbit : 1; // uint16_t slope : 6; // Deflection angle of tracklet + uint16_t pid : 15; // Particle Identity uint16_t pos : 10; // Position of tracklet, signed 10 bits, granularity 0.02 pad widths, -10.22 to +10.22, relative to centre of pad 10 } __attribute__((__packed__)); }; @@ -220,15 +217,15 @@ std::vector<uint32_t> getPID(char *rawdata, int tracklet) { // extract the 2 parts of the pid and return the combined PID // rawdata starts with the mcmheader - uint32_t pid = 1;//(rawdata.pid[tracklet]<<15) + rawdata.pid[]; TODO figure out a better way that is not *undefined* c++ to progress to following 32bit words after MCMRawDataHeader. + uint32_t pid = 1;//(rawdata.pid[tracklet]<<15) + rawdata.pid[]; TODO figure out a better way that is not *undefined* c++ to progress to following 32bit words after TrackletMCMHeader. //TODO come back here, marker to come back. std::vector<uint32_t> pids; - MCMRawDataHeader mcmheader; - TrapRawTracklet trackletdata; + TrackletMCMHeader mcmheader; + TrackletMCMData trackletdata; //memcpy(&mcmheader,&rawdata[0],sizeof(mcmheader)); std::copy(rawdata.begin(), rawdata.begin()+sizeof(mcmheader),(char*)&mcmheader); for(int tracklet=0;tracklet<3;tracklet++){ - memcpy(&trackletdata,&rawdata[0]+sizeof(mcmheader)+tracklet*sizeof(trackletdata),sizeof(TrapRawTracklet)); + memcpy(&trackletdata,&rawdata[0]+sizeof(mcmheader)+tracklet*sizeof(trackletdata),sizeof(TrackletMCMData)); uint32_t headpid=0; switch(tracklet){ case 0 : headpid=mcmheader.pid0;break; @@ -243,193 +240,54 @@ std::vector<uint32_t> getPID(char *rawdata, int tracklet) uint32_t getPadRow(const char *rawdata) { - MCMRawDataHeader mcmheader; - memcpy(&mcmheader, rawdata,sizeof(MCMRawDataHeader)); + TrackletMCMHeader mcmheader; + memcpy(&mcmheader, rawdata,sizeof(TrackletMCMHeader)); return mcmheader.padrow; } uint32_t getCol(const char* rawdata) { - MCMRawDataHeader mcmheader; - memcpy(&mcmheader, rawdata,sizeof(MCMRawDataHeader)); + TrackletMCMHeader mcmheader; + memcpy(&mcmheader, rawdata,sizeof(TrackletMCMHeader)); return mcmheader.col; } int16_t getPos(const char* rawdata, int tracklet) { // extract y from the tracklet word, raw data points to the mcmheader of this data. - //rawdata points to the MCMRawDataHeader - TrapRawTracklet trackletdata; - MCMRawDataHeader mcmrawdataheader; - memcpy(&mcmrawdataheader,rawdata,sizeof(MCMRawDataHeader)); - memcpy(&trackletdata,rawdata+sizeof(MCMRawDataHeader)); + //rawdata points to the TrackletMCMHeader + TrackletMCMData trackletdata; + TrackletMCMHeader mcmrawdataheader; + memcpy(&mcmrawdataheader,rawdata,sizeof(TrackletMCMHeader)); + memcpy(&trackletdata,rawdata+sizeof(TrackletMCMHeader)); return trackletdata.pos; return 1; } uint32_t getSlope(const *rawdata, int tracklet) { // extract dy or slope from the tracklet word, raw data points to the mcmheader of this data. - TrapRawTracklet trackletdata; - memcpy(&trackletdata,&rawdata[0]+sizeof(MCMRawDataHeader)+tracklet*sizeof(trackletdata),sizeof(TrapRawTracklet)); + TrackletMCMData trackletdata; + memcpy(&trackletdata,&rawdata[0]+sizeof(TrackletMCMHeader)+tracklet*sizeof(trackletdata),sizeof(TrackletMCMData)); return trackletdata.slope; } -due to the interplay of MCMRawDataHeader and TrapRawTracklet come back to this. TODO +due to the interplay of TrackletMCMHeader and TrackletMCMData come back to this. TODO */ -uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data = true) -{ - //TODO this needs some more ellaborate testing. I got the packing to work so for now, - // its a question of unpacking info in line 88 and 89. - uint32_t info = 0; - if (link > 14) - return 0xffffffff; - - char* words; - if (link < 8) - words = (char*)&cruhead.word02[0]; - if (link < 15) - words = (char*)&cruhead.word57[0]; - uint32_t byteoffset = link * 3; // each link [size+erroflags] is 24 bits, so 3 bytes. - if (data) - info = ((words[byteoffset + 1]) << 8) + (words[byteoffset + 2]); - else - info = words[byteoffset]; - - return info; -} - -uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link) -{ - uint32_t errorflags = 0; - if (link < 8) { - //dealing with word0-2 - errorflags = cruhead.linksA[link].errorflags; - } else { - if (link < 16) { - errorflags = cruhead.linksB[link - 8 + 1].errorflags; // link 0 [actually 9] is in fact the end part of reserved. - - } else - std::cout << "error link=" << link << " not in range 0-14" << std::endl; - } - return errorflags; -} - -uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link) -{ - //return number 32 byte blocks for the link 3x64bit ints. - uint32_t size = 0; - if (link < 8) { - size = (cruhead.linksA[link].size); - } else { - if (link < 16) { // link 0 is part of reserved - size = cruhead.linksB[link - 8 + 1].size; - - } else - std::cout << "error link=" << link << " not in range 0-14" << std::endl; - } - return size; -} - -uint32_t getlinkerrorflags(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linkerrorflags) -{ - for (uint32_t link = 0; link < 15; link++) { - linkerrorflags[link] = getlinkerrorflag(cruheader, link); - } - return 0; +uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data); +uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link); +uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link); +uint32_t getlinkerrorflags(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linkerrorflags); +uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linksizes); +std::ostream& operator<<(std::ostream& stream, const TrackletHCHeader halfchamberheader); +std::ostream& operator<<(std::ostream& stream, const TrackletMCMData& tracklet); +void printTrackletMCMData(o2::trd::TrackletMCMData& tracklet); +void printTrackletMCMHeader(o2::trd::TrackletMCMHeader& mcmhead); +std::ostream& operator<<(std::ostream& stream, const TrackletMCMHeader& mcmhead); +void printHalfChamber(o2::trd::TrackletHCHeader& halfchamber); +void dumpHalfChamber(o2::trd::TrackletHCHeader& halfchamber); +void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru); +void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru); +std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru); } -uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linksizes) -{ - for (uint32_t link = 0; link < 15; link++) { - linksizes[link] = getlinkdatasize(cruheader, link); - } - return 0; -} - -/* - * Printing methods to dump and display the various structures above in pretty format or hexdump - */ - -std::ostream& operator<<(std::ostream& stream, const HalfChamberHeader halfchamberheader) -{ - stream << "HalfChamberHeader : " << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; - return stream; -} - -std::ostream& operator<<(std::ostream& stream, const TrapRawTracklet& tracklet) -{ - // make a pretty output of the tracklet. - stream << "TrapRawTracklet: pos=" << tracklet.pos << "::slope=" << tracklet.slope << "::pid=" << tracklet.pid << "::checkbit=" << tracklet.checkbit << std::endl; - return stream; } -void printTrapRawTracklet(o2::trd::TrapRawTracklet& tracklet) -{ - LOGF(INFO, "TrapRawTracklet: "); -} - -void printMCMHeader(o2::trd::MCMRawDataHeader& mcmhead) -{ - LOGF(INFO, "MCMRawHeader: 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d", mcmhead.onea, mcmhead.padrow, mcmhead.col, mcmhead.pid2, mcmhead.pid1, mcmhead.pid0, mcmhead.oneb); -} - -std::ostream& operator<<(std::ostream& stream, const MCMRawDataHeader& mcmhead) -{ - // make a pretty output of the mcm header. - // stream << "MCMRawHeader:" << mcmhead.checkbits << "::" << (mcmhead.pid&0xfff000000) << ":"<< (mcmhead.pid&0xfff000) << ":"<< (mcmhead.pid&0xfff) << std::endl; - stream << "MCMRawHeader:" << mcmhead.onea << "::" << mcmhead.pid2 << ":" << mcmhead.pid1 << ":" << mcmhead.pid0 << "::" << mcmhead.oneb << std::endl; - return stream; -} - -void printHalfChamber(o2::trd::HalfChamberHeader& halfchamber) -{ - LOGF(INFO, "HCID : %d MCLK: %d Format: %d Always1:%d", halfchamber.HCID, halfchamber.MCLK, halfchamber.format, halfchamber.one); -} - -void dumpHalfChamber(o2::trd::HalfChamberHeader& halfchamber) -{ - LOGF(INFO, "HalfChamber : 0x%08x", halfchamber.word); -} - -void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) -{ - std::array<uint32_t, 15> sizes; - std::array<uint32_t, 15> errorflags; - getlinkdatasizes(halfcru, sizes); - getlinkerrorflags(halfcru, errorflags); - LOGF(INFO, "V:%d BC:%d SB:%d EType:%d", halfcru.HeaderVersion, halfcru.BunchCrossing, halfcru.StopBit, halfcru.EventType); - for (int i = 0; i < 15; i++) - LOGF(INFO, "Link %d size: %ul eflag: 0x%02x", i, sizes[i], errorflags[i]); -} - -void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) -{ - std::array<uint32_t, 16> raw{}; - memcpy(&raw[0], &halfcru, sizeof(halfcru)); - for (int i = 0; i < 4; i++) { - int index = 4 * i; - LOGF(INFO, "[1/2CRUHeader %d] 0x%08x 0x%08x 0x%08x 0x%08x", i, raw[index + 3], raw[index + 2], raw[index + 1], raw[index + 0]); - } -} - -std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) // make a pretty output of the header. -{ - stream << std::hex; - stream << "EventType : " << halfcru.EventType << std::endl; - stream << "StopBit : " << halfcru.StopBit << std::endl; - stream << "BunchCrossing : " << halfcru.BunchCrossing << std::endl; - stream << "HeaderVersion : " << halfcru.HeaderVersion << std::endl; - stream << "link sizes : "; - for (int link = 0; link < 15; link++) - stream << link << ":" << std::hex << std::setw(4) << getlinkdatasize(halfcru, link) << ","; - stream << std::endl; - stream << "link errorflags : "; - for (int link = 0; link < 15; link++) - stream << link << ":" << std::hex << std::setw(2) << getlinkerrorflag(halfcru, link) << ","; - stream << std::endl; - stream << "0x" << halfcru.word02[0] << " 0x" << halfcru.word02[1] << " 0x" << halfcru.word02[2] << " 0x" << halfcru.word3 << " 0x" << halfcru.word4 << " 0x" << halfcru.word57[0] << " 0x" << halfcru.word57[1] << " 0x" << halfcru.word57[2] << std::endl; - return stream; -} - -} // namespace trd -} // namespace o2 - #endif diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index 5123504d8852b..7550c081ea166 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -30,7 +30,6 @@ #include <memory> // for std::unique_ptr #include "Rtypes.h" // for ClassDef #include "fairlogger/Logger.h" -#include "TRDBase/FeeParam.h" namespace o2 { @@ -42,46 +41,23 @@ Word 0 | Format | HCID | padrow | col | ------------------------------------------------------------------------------------------------- |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| ------------------------------------------------------------------------------------------------- -Word 0 | slope | Q0 | Q1 | Q2 | +Word 0 | slope | Q2 | Q1 | Q0 | ------------------------------------------------------------------------------------------------- */ class Tracklet64 { - // bit masks for the above raw data; - static constexpr uint64_t formatmask = 0xf000000000000000; - static constexpr uint64_t hcidmask = 0x0ffe000000000000; - static constexpr uint64_t padrowmask = 0x0001e00000000000; - static constexpr uint64_t colmask = 0x0000180000000000; - static constexpr uint64_t posmask = 0x000007ff00000000; - static constexpr uint64_t slopemask = 0x00000000ff000000; - static constexpr uint64_t Q0mask = 0x0000000000ff0000; - static constexpr uint64_t Q1mask = 0x000000000000ff00; - static constexpr uint64_t Q2mask = 0x00000000000000ff; - static constexpr uint64_t PIDmask = 0x0000000000ffffff; - //bit shifts for the above raw data - static constexpr uint64_t formatbs = 60; - static constexpr uint64_t hcidbs = 49; - static constexpr uint64_t padrowbs = 45; - static constexpr uint64_t colbs = 43; - static constexpr uint64_t posbs = 32; - static constexpr uint64_t slopebs = 24; - static constexpr uint64_t PIDbs = 0; - static constexpr uint64_t Q0bs = 16; - static constexpr uint64_t Q1bs = 8; - static constexpr uint64_t Q2bs = 0; public: Tracklet64() = default; Tracklet64(uint64_t trackletword) { mtrackletWord = trackletword; } - Tracklet64(const Tracklet64& rhs); + Tracklet64(const Tracklet64& rhs) { mtrackletWord = rhs.getTrackletWord(); }; Tracklet64(uint64_t format, uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, - uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0) + uint64_t slope, uint64_t Q0, uint64_t Q1, uint64_t Q2) { - buildTrackletWord(format, hcid, padrow, col, position, slope, Q2, Q1, Q0); + buildTrackletWord(format, hcid, padrow, col, position, slope, Q0, Q1, Q2); } ~Tracklet64() = default; - Tracklet64& operator=(const Tracklet64& o) { return *this; } //TODO convert to the actual number regarding compliments. @@ -106,16 +82,26 @@ class Tracklet64 mtrackletWord = trackletword; return 0; } + static const int mgkNmcmRob = 16; // Number of MCMs per ROB + static const int mgkNmcmRobInRow = 4; // Number of MCMs per ROB in row dir. + static const int mgkNmcmRobInCol = 4; // Number of MCMs per ROB in col dir. + static const int mgkNrobC0 = 6; // Number of ROBs per C0 chamber + static const int mgkNrobC1 = 8; // Number of ROBs per C1 chamber + static const int mgkNadcMcm = 21; // Number of ADC channels per MCM + static const int mgkNcol = 144; // Number of pads per padplane row + static const int mgkNcolMcm = 18; // Number of pads per MCM + static const int mgkNrowC0 = 12; // Number of Rows per C0 chamber + static const int mgkNrowC1 = 16; // Number of Rows per C1 chamber + // ----- Getters for tracklet information ----- - // TODO figure out how to get MCM and ROB from hcid, col and padrow. int getMCM() const { - return (getColumn() % (FeeParam::mgkNcol / 2)) / FeeParam::mgkNcolMcm + FeeParam::mgkNmcmRobInCol * (getPadRow() % FeeParam::mgkNmcmRobInRow); + return (getColumn() % (72)) / 18 + 4 * (getPadRow() % 4); } int getROB() const { - int side = getColumn() / (FeeParam::mgkNcol / 2); - return (int)((int)getPadRow() / (int)FeeParam::mgkNmcmRobInRow) * 2 + side; + int side = getColumn() / 72; + return (int)((int)getPadRow() / 8 + side); } // ----- Getters for offline corresponding values ----- @@ -145,6 +131,30 @@ class Tracklet64 void setPID(uint64_t pid) { mtrackletWord |= ((((uint64_t)pid) << PIDbs) & PIDmask); } // set the entire pid area of the trackletword, all the 3 Q's void setPosition(uint64_t position) { mtrackletWord |= ((((uint64_t)position) << posbs) & posmask); } void setSlope(uint64_t slope) { mtrackletWord |= ((((uint64_t)slope) << slopebs) & slopemask); } + void printStream(std::ostream& stream) const; + + // bit masks for the above raw data; + static constexpr uint64_t formatmask = 0xf000000000000000; + static constexpr uint64_t hcidmask = 0x0ffe000000000000; + static constexpr uint64_t padrowmask = 0x0001e00000000000; + static constexpr uint64_t colmask = 0x0000180000000000; + static constexpr uint64_t posmask = 0x000007ff00000000; + static constexpr uint64_t slopemask = 0x00000000ff000000; + static constexpr uint64_t Q2mask = 0x0000000000ff0000; + static constexpr uint64_t Q1mask = 0x000000000000ff00; + static constexpr uint64_t Q0mask = 0x00000000000000ff; + static constexpr uint64_t PIDmask = 0x0000000000ffffff; + //bit shifts for the above raw data + static constexpr uint64_t formatbs = 60; + static constexpr uint64_t hcidbs = 49; + static constexpr uint64_t padrowbs = 45; + static constexpr uint64_t colbs = 43; + static constexpr uint64_t posbs = 32; + static constexpr uint64_t slopebs = 24; + static constexpr uint64_t PIDbs = 0; + static constexpr uint64_t Q2bs = 16; + static constexpr uint64_t Q1bs = 8; + static constexpr uint64_t Q0bs = 0; protected: uint64_t mtrackletWord; // the 64 bit word holding all the tracklet information for run3. @@ -153,7 +163,7 @@ class Tracklet64 ClassDefNV(Tracklet64, 1); }; -//using Tracklet = RawTracklet64; +std::ostream& operator<<(std::ostream& stream, const Tracklet64& trg); } //namespace trd } //namespace o2 diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index 8f1e489320984..f4e87501d4f9f 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -15,11 +15,13 @@ #pragma link off all functions; #pragma link C++ class o2::trd::TriggerRecord + ; +#pragma link C++ class o2::trd::LinkRecord + ; #pragma link C++ struct o2::trd::HalfCRUHeader + ; -#pragma link C++ struct o2::trd::HalfChamberHeader + ; -#pragma link C++ struct o2::trd::MCMRawDataHeader + ; -#pragma link C++ struct o2::trd::TrapRawTracklet + ; +#pragma link C++ struct o2::trd::TrackletHCHeader + ; +#pragma link C++ struct o2::trd::TrackletMCMHeader + ; +#pragma link C++ struct o2::trd::TrackletMCMData + ; #pragma link C++ class o2::trd::Tracklet64 + ; #pragma link C++ class std::vector < o2::trd::TriggerRecord > +; +#pragma link C++ class std::vector < o2::trd::LinkRecord > +; #endif diff --git a/DataFormats/Detectors/TRD/src/LinkRecord.cxx b/DataFormats/Detectors/TRD/src/LinkRecord.cxx new file mode 100644 index 0000000000000..bafdbcf73d15d --- /dev/null +++ b/DataFormats/Detectors/TRD/src/LinkRecord.cxx @@ -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. + +#include <iostream> +#include "DataFormatsTRD/LinkRecord.h" + +namespace o2 +{ + +namespace trd +{ + +void LinkRecord::printStream(std::ostream& stream) const +{ + stream << "Data for link 0x" << std::hex << mLinkId << std::dec << ", starting from entry " << getFirstEntry() << " with " << getNumberOfObjects() << " objects"; +} + +std::ostream& operator<<(std::ostream& stream, const LinkRecord& trg) +{ + trg.printStream(stream); + return stream; +} + +} // namespace trd +} // namespace o2 diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index cd4b925b891eb..51d3b3c6ef0e6 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -8,8 +8,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include <iomanip> #include <iostream> -//#include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/RawData.h" namespace o2 { @@ -17,5 +18,166 @@ namespace o2 namespace trd { +uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data = true) +{ + // cruhead is the incoming header to pass + // link is the link you are requesting information on, 0-14 + // + uint32_t info = 0; + if (link > 14) + return 0xffffffff; + + char* words; + if (link < 8) + words = (char*)&cruhead.word02[0]; + if (link < 15) + words = (char*)&cruhead.word57[0]; + uint32_t byteoffset = link * 3; // each link [size+erroflags] is 24 bits, so 3 bytes. + if (data) + info = ((words[byteoffset + 1]) << 8) + (words[byteoffset + 2]); + else + info = words[byteoffset]; + + return info; +} + +uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link) +{ + // link is the link you are requesting information on, 0-14 + uint32_t errorflags = 0; + if (link < 8) { + //dealing with word0-2 + errorflags = cruhead.linksA[link].errorflags; + } else { + if (link < 16) { + errorflags = cruhead.linksB[link - 8 + 1].errorflags; // link 0 [actually 9] is in fact the end part of reserved. + + } else + std::cout << "error link=" << link << " not in range 0-14" << std::endl; + } + return errorflags; +} + +uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link) +{ + // link is the link you are requesting information on, 0-14 + //return number 32 byte blocks for the link 3x64bit ints. + uint32_t size = 0; + if (link < 8) { + size = (cruhead.linksA[link].size); + } else { + if (link < 16) { // link 0 is part of reserved + size = cruhead.linksB[link - 8 + 1].size; + + } else + std::cout << "error link=" << link << " not in range 0-14" << std::endl; + } + return size; +} + +uint32_t getlinkerrorflags(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linkerrorflags) +{ + // retrieve all the link error flags for this half cru + for (uint32_t link = 0; link < 15; link++) { + linkerrorflags[link] = getlinkerrorflag(cruheader, link); + } + return 0; +} +uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t, 15>& linksizes) +{ + // retrieve all the link sizes for this half cru + for (uint32_t link = 0; link < 15; link++) { + linksizes[link] = getlinkdatasize(cruheader, link); + } + return 0; +} + +// +// Printing methods to dump and display the various structures above in pretty format or hexdump +// printNameOfStruct(const NameOfStruct& nameofstruct); +// dumpNameOfStruct(const NameOfStruct& nameofstruct); +// std::ostrea& operator<<(std::ostream& stream, const NameOfStruct& nameofstruct); +// + +std::ostream& operator<<(std::ostream& stream, const TrackletHCHeader halfchamberheader) +{ + stream << "TrackletHCHeader : Raw:0x" << std::hex << halfchamberheader.word << " " << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const TrackletMCMData& tracklet) +{ + // make a pretty output of the tracklet. + stream << "TrackletMCMData: Raw:0x" << std::hex << tracklet.word << " pos=" << tracklet.pos << "::slope=" << tracklet.slope << "::pid=" << tracklet.pid << "::checkbit=" << tracklet.checkbit << std::endl; + return stream; +} +void printTrackletMCMData(o2::trd::TrackletMCMData& tracklet) +{ + LOGF(INFO, "TrackletMCMData: Raw:0x%08x pos:%d slope:%d pid:0x%08x checkbit:0x%02x", tracklet.word, tracklet.pos, tracklet.slope, tracklet.pid, tracklet.checkbit); +} + +void printTrackletMCMHeader(o2::trd::TrackletMCMHeader& mcmhead) +{ + LOGF(INFO, "MCMRawHeader: Raw:0x%08x 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d", mcmhead.word, mcmhead.onea, mcmhead.padrow, mcmhead.col, mcmhead.pid2, mcmhead.pid1, mcmhead.pid0, mcmhead.oneb); +} + +std::ostream& operator<<(std::ostream& stream, const TrackletMCMHeader& mcmhead) +{ + // make a pretty output of the mcm header. + // stream << "MCMRawHeader:" << mcmhead.checkbits << "::" << (mcmhead.pid&0xfff000000) << ":"<< (mcmhead.pid&0xfff000) << ":"<< (mcmhead.pid&0xfff) << std::endl; + stream << "MCMRawHeader: Raw:0x" << std::hex << mcmhead.word << " " << mcmhead.onea << "::" << mcmhead.pid2 << ":" << mcmhead.pid1 << ":" << mcmhead.pid0 << "::" << mcmhead.oneb << std::endl; + return stream; +} + +void printHalfChamber(o2::trd::TrackletHCHeader& 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); +} + +void dumpHalfChamber(o2::trd::TrackletHCHeader& halfchamber) +{ + LOGF(INFO, "HalfChamber : 0x%08x", halfchamber.word); +} + +void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) +{ + std::array<uint32_t, 15> sizes; + std::array<uint32_t, 15> errorflags; + getlinkdatasizes(halfcru, sizes); + getlinkerrorflags(halfcru, errorflags); + LOGF(INFO, "V:%d BC:%d SB:%d EType:%d", halfcru.HeaderVersion, halfcru.BunchCrossing, halfcru.StopBit, halfcru.EventType); + for (int i = 0; i < 15; i++) + LOGF(INFO, "Link %d size: %ul eflag: 0x%02x", i, sizes[i], errorflags[i]); +} + +void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) +{ + std::array<uint32_t, 16> raw{}; + memcpy(&raw[0], &halfcru, sizeof(halfcru)); + for (int i = 0; i < 4; i++) { + int index = 4 * i; + LOGF(INFO, "[1/2CRUHeader %d] 0x%08x 0x%08x 0x%08x 0x%08x", i, raw[index + 3], raw[index + 2], raw[index + 1], raw[index + 0]); + } +} + +std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) // make a pretty output of the header. +{ + stream << std::hex; + stream << "EventType : " << halfcru.EventType << std::endl; + stream << "StopBit : " << halfcru.StopBit << std::endl; + stream << "BunchCrossing : " << halfcru.BunchCrossing << std::endl; + stream << "HeaderVersion : " << halfcru.HeaderVersion << std::endl; + stream << "link sizes : "; + for (int link = 0; link < 15; link++) + stream << link << ":" << std::hex << std::setw(4) << getlinkdatasize(halfcru, link) << ","; + stream << std::endl; + stream << "link errorflags : "; + for (int link = 0; link < 15; link++) + stream << link << ":" << std::hex << std::setw(2) << getlinkerrorflag(halfcru, link) << ","; + stream << std::endl; + stream << "0x" << halfcru.word02[0] << " 0x" << halfcru.word02[1] << " 0x" << halfcru.word02[2] << " 0x" << halfcru.word3 << " 0x" << halfcru.word4 << " 0x" << halfcru.word57[0] << " 0x" << halfcru.word57[1] << " 0x" << halfcru.word57[2] << std::endl; + return stream; +} + } // namespace trd } // namespace o2 diff --git a/DataFormats/Detectors/TRD/src/Tracklet64.cxx b/DataFormats/Detectors/TRD/src/Tracklet64.cxx index 32cd53a6f862a..63151ddc56546 100644 --- a/DataFormats/Detectors/TRD/src/Tracklet64.cxx +++ b/DataFormats/Detectors/TRD/src/Tracklet64.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. #include <iostream> -//#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/Tracklet64.h" namespace o2 { @@ -17,5 +17,20 @@ namespace o2 namespace trd { +void Tracklet64::printStream(std::ostream& stream) const +{ + stream << "Tracklet64 : 0x" << std::hex << getTrackletWord(); + stream << "\t hcid : " << getHCID() << " row:" << getPadRow() << " col:" << getColumn() + << " Position:" << getPosition() << " slope:" << getSlope() + << " PID:0x" << getPID() + << " Q0:" << getQ0() << " Q1:" << getQ1() << " Q2:" << getQ2(); +} + +std::ostream& operator<<(std::ostream& stream, const Tracklet64& trg) +{ + trg.printStream(stream); + return stream; +} + } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/CMakeLists.txt b/Detectors/TRD/base/CMakeLists.txt index a82cf6475a6eb..54c50ed5cba1e 100644 --- a/Detectors/TRD/base/CMakeLists.txt +++ b/Detectors/TRD/base/CMakeLists.txt @@ -36,6 +36,7 @@ o2_add_library(TRDBase O2::DetectorsBase ROOT::Physics O2::SimulationDataFormat + O2::DataFormatsTRD O2::CCDB) o2_target_root_dictionary(TRDBase diff --git a/Detectors/TRD/base/test/testRawData.cxx b/Detectors/TRD/base/test/testRawData.cxx index 480612f4f2080..5c39367cdaac4 100644 --- a/Detectors/TRD/base/test/testRawData.cxx +++ b/Detectors/TRD/base/test/testRawData.cxx @@ -35,16 +35,16 @@ namespace trd BOOST_AUTO_TEST_CASE(TRDRawDataHeaderSizes) { //check the sizes of header structs due to packing - BOOST_CHECK_EQUAL(sizeof(o2::trd::TrapRawTracklet), 4); - BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfChamberHeader), 4); - BOOST_CHECK_EQUAL(sizeof(o2::trd::MCMRawDataHeader), 4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::TrackletMCMData), 4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::TrackletHCHeader), 4); + BOOST_CHECK_EQUAL(sizeof(o2::trd::TrackletMCMHeader), 4); BOOST_CHECK_EQUAL(sizeof(o2::trd::HalfCRUHeader), 64); } BOOST_AUTO_TEST_CASE(TRDRawDataHeaderInternals) { - o2::trd::TrapRawTracklet tracklet; - o2::trd::HalfChamberHeader halfchamberheader; + o2::trd::TrackletMCMData tracklet; + o2::trd::TrackletHCHeader halfchamberheader; o2::trd::HalfCRUHeader halfcruheader; halfcruheader.word02[0] = 0x102; BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags, 2); @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(TRDRawDataHeaderInternals) halfcruheader.word02[0] = (uint64_t)0x1000000000000000; halfcruheader.word02[1] = (uint64_t)0xa00b000c000d0ebf; BOOST_CHECK_EQUAL(halfcruheader.linksA[2].size, 0xbf10); // check a size that spans a 64bit word. - o2::trd::MCMRawDataHeader mcmrawdataheader; + o2::trd::TrackletMCMHeader mcmrawdataheader; mcmrawdataheader.word = 0x78000000; BOOST_CHECK_EQUAL(mcmrawdataheader.padrow, 15); mcmrawdataheader.word = 0x06000000; diff --git a/Detectors/TRD/macros/ParseTrapRawOutput.C b/Detectors/TRD/macros/ParseTrapRawOutput.C new file mode 100644 index 0000000000000..c1d212463b5ce --- /dev/null +++ b/Detectors/TRD/macros/ParseTrapRawOutput.C @@ -0,0 +1,64 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include <TChain.h> +#include <TFile.h> +#include <TH1F.h> +#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/LinkData.h" +#include <memory> +#endif + +//Parse the trackletraw output of a trap simulation +//Display on the screen and indent for half chamber, mcmheader and mcmtracklet. +//Create a raw dump as well of the incoming data. + +using namespace o2::trd; + +void ParseTrapRawOutput(std::string path = "./", std::string inputTracklets = "trdtrapraw.root") +{ + TChain trdtrapraw("o2sim"); + trdtrapraw.AddFile((path + inputTracklets).c_str()); + + std::vector<o2::trd::LinkRecord> links; + std::vector<o2::trd::LinkRecord>* linksptr = &links; + + std::vector<uint32_t> trapraw; + std::vector<uint32_t>* traprawptr = &trapraw; + trdtrapraw.SetBranchAddress("TrapRaw", &traprawptr); + trdtrapraw.SetBranchAddress("TrapLinkRecord", &linksptr); + trdtrapraw.GetEntry(0); + + ofstream outfile("rawdata", std::ios::out | std::ofstream::binary); + outfile.write((char*)(&trapraw[0]), sizeof(trapraw[0]) * trapraw.size()); + outfile.close(); + uint64_t mcmheadcount = 0; + uint64_t halfchamberheadcount = 0; + uint64_t traprawtrackletount = 0; + //at each linkrecord data we should have a halfchamberheader; + // with in the range specified by the linkrecord we have a structure of : + // mcmheader, traprawtracklet[1-3], mcmheader, traprawtracklet[1-3], etc. etc. + for (auto& link : links) { + o2::trd::TrackletHCHeader halfchamber; + halfchamber.word = link.getLinkId(); + std::cout << "in link with HCID of " << halfchamber; + for (int i = link.getFirstEntry(); i < link.getFirstEntry() + link.getNumberOfObjects(); i++) { + //read TrackletMCMHeader + //read 1 to 3 TrackletMCMDatas + if (((trapraw[i]) & 0x1) == 1 && (trapraw[i] & 0x80000000) != 0) { + TrackletMCMHeader mcm; + mcm.word = trapraw[i]; + std::cout << "\t\t" << mcm; + mcmheadcount++; + } else if (((trapraw[i]) & 0x1) == 0) { + //tracklet word + // + TrackletMCMData tracklet; + tracklet.word = trapraw[i]; + std::cout << "\t\t\t\tTracklet : 0x" << std::hex << tracklet.word << std::dec << std::endl; + traprawtrackletount++; + } else + std::cout << "most sig bit is not binary ?? 0x" << std::hex << trapraw[i] << std::dec << std::endl; + } + } + std::cout << "counts " << halfchamberheadcount << "::" << mcmheadcount << "::" << traprawtrackletount << std::endl; +} diff --git a/Detectors/TRD/simulation/CMakeLists.txt b/Detectors/TRD/simulation/CMakeLists.txt index 08ebaa02c5424..b1107bbc1e9d1 100644 --- a/Detectors/TRD/simulation/CMakeLists.txt +++ b/Detectors/TRD/simulation/CMakeLists.txt @@ -20,7 +20,7 @@ o2_add_library(TRDSimulation src/TrapConfig.cxx src/TrapConfigHandler.cxx src/TrapSimulator.cxx - PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::SimulationDataFormat O2::TRDBase) + PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::SimulationDataFormat O2::TRDBase O2::DataFormatsTRD O2::DetectorsRaw) o2_target_root_dictionary(TRDSimulation HEADERS include/TRDSimulation/Detector.h @@ -37,3 +37,4 @@ if (OpenMP_CXX_FOUND) endif() o2_data_file(COPY data DESTINATION Detectors/TRD/simulation) + diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h index 7d9fa7153d534..7dde07da45ff3 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h @@ -21,15 +21,19 @@ #include <iostream> #include <ostream> #include <fstream> +#include <gsl/span> #include "TRDBase/Tracklet.h" #include "TRDBase/FeeParam.h" #include "TRDBase/Digit.h" +#include "TRDBase/Tracklet.h" #include "TRDSimulation/Digitizer.h" #include "TRDSimulation/TrapConfigHandler.h" //TODO I think i can dump this. #include "TRDSimulation/TrapConfig.h" #include "TRDBase/MCLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +//#include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/Tracklet64.h" class TH2F; @@ -82,6 +86,8 @@ class TrapSimulator for (auto& tmplabel : mADCLabels) tmplabel.clear(); // clear MC Labels sent in from the digits coming in. mTrackletLabels.clear(); // clear the stored labels. + mTrackletArray.clear(); + mTrackletArray64.clear(); }; // void setData(int iadc, const std::vector<int>& adc); // set ADC data with array void setData(int iadc, const ArrayADC& adc, std::vector<o2::MCCompLabel>& labels); // set ADC data with array @@ -117,9 +123,9 @@ class TrapSimulator std::string getTrklBranchName() const { return mTrklBranchName; } void setTrklBranchName(std::string name) { mTrklBranchName = name; } - int packData(std::vector<uint32_t>& buf); - int produceRawStream(std::vector<uint32_t>& buf, unsigned int iEv = 0) const; // Produce raw data stream - Real data format - int produceTrackletStream(std::vector<uint32_t>& buf); // produce the tracklet stream for this MCM + int packData(std::vector<uint32_t>& rawdata, uint32_t offset); + int getRawStream(std::vector<uint32_t>& buf, uint32_t offset, unsigned int iEv = 0) const; // Produce raw data stream - Real data format + int getTrackletStream(std::vector<uint32_t>& buf, uint32_t offset); // produce the tracklet stream for this MCM // different stages of processing in the TRAP void filter(); // Apply digital filters for existing data (according to configuration) @@ -195,9 +201,9 @@ class TrapSimulator static const int mgkDmemAddrTimeOffset = 0xc3fe; // DMEM address of time offset t0 static const int mgkDmemAddrYcorr = 0xc3ff; // DMEM address of y correction (mis-alignment) static const int mgkMaxTracklets = 4; // maximum number of tracklet-words submitted per MCM (one per CPU) - //std::array<TrackletMCM> getTrackletArray() const { return mTrackletArray; } std::vector<Tracklet>& getTrackletArray() { return mTrackletArray; } - void getTracklets(std::vector<Tracklet>& TrackletStore); // place the trapsim tracklets nto the incoming vector + std::vector<Tracklet64>& getTrackletArray64() { return mTrackletArray64; } + void getTracklet64s(std::vector<Tracklet64>& TrackletStore); // place the trapsim 64 bit tracklets nto the incoming vector o2::dataformats::MCTruthContainer<o2::MCCompLabel>& getTrackletLabels() { return mTrackletLabels; } bool checkInitialized() const; // Check whether the class is initialized @@ -259,6 +265,7 @@ class TrapSimulator int mNhits; // number of hits unsigned int mQ0; // charge accumulated in first window unsigned int mQ1; // charge accumulated in second window + unsigned int mQ2; // charge accumulated in some other windows TODO find or write the documentation for window3 unsigned int mSumX; // sum x int mSumY; // sum y unsigned int mSumX2; // sum x**2 @@ -269,6 +276,7 @@ class TrapSimulator mNhits = 0; mQ0 = 0; mQ1 = 0; + mQ2 = 0; //TODO should this go here as its calculated differeintly in softwaren not hardware like the other 2? mSumX = 0; mSumY = 0; mSumX2 = 0; @@ -294,6 +302,7 @@ class TrapSimulator std::array<std::vector<o2::MCCompLabel>, FeeParam::mgkNadcMcm> mADCLabels{}; // MC Labels sent in from the digits coming in. std::vector<unsigned int> mMCMT; // tracklet word for one mcm/trap-chip std::vector<Tracklet> mTrackletArray; // Array of TRDtrackletMCM which contains MC information in addition to the tracklet word + std::vector<Tracklet64> mTrackletArray64; // Array of TRDtrackletMCM which contains MC information in addition to the tracklet word o2::dataformats::MCTruthContainer<o2::MCCompLabel> mTrackletLabels; std::vector<int> mZSMap; // Zero suppression map (1 dimensional projection) @@ -341,6 +350,7 @@ class TrapSimulator static bool mgStoreClusters; // whether to store all clusters in the tracklets bool mDataIsSet = false; Calibrations* mCalib; + static constexpr bool debugheaders = false; }; std::ostream& operator<<(std::ostream& os, const TrapSimulator& mcm); diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index cf24778285715..4fb06cf5c78e4 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -35,6 +35,8 @@ #include "TRDSimulation/Digitizer.h" #include <SimulationDataFormat/MCCompLabel.h> #include <SimulationDataFormat/MCTruthContainer.h> +#include <DataFormatsTRD/RawData.h> +#include <DataFormatsTRD/Tracklet64.h> #include <iostream> #include <iomanip> @@ -240,9 +242,8 @@ std::ostream& o2::trd::operator<<(std::ostream& os, const TrapSimulator& mcm) else if (os.iword(TrapSimulator::mgkFormatIndex) == 2) { int bufSize = 300; std::vector<uint32_t> buf; - buf.resize(bufSize); - - int bufLength = mcm.produceRawStream(buf); + buf.reserve(bufSize); + int bufLength = mcm.getRawStream(buf, 0); for (int i = 0; i < bufLength; i++) std::cout << "0x" << std::hex << buf[i] << std::dec << std::endl; @@ -654,7 +655,7 @@ void TrapSimulator::print(int choice) const if ((choice & PRINTFOUND) != 0) { LOG(info) << "Found Tracklets:"; for (int iTrkl = 0; iTrkl < mTrackletArray.size(); iTrkl++) { - LOG(info) << "tracklet " << iTrkl << ": 0x" << hex << std::setw(8) << mTrackletArray[iTrkl].getTrackletWord(); + LOG(info) << "tracklet " << iTrkl << ": 0x" << hex << std::setw(16) << mTrackletArray[iTrkl].getTrackletWord(); } } } @@ -886,18 +887,95 @@ int TrapSimulator::getCol(int adc) return col; } -int TrapSimulator::packData(std::vector<uint32_t>& buf) +//TODO figure why I could not get span to work here +int TrapSimulator::packData(std::vector<uint32_t>& rawdata, uint32_t offset) { + // return # of 32 bit words. // //given the, up to 3 tracklets, pack them according to the define data format. // + // std::cout << "span size in packData is : " << rawdata.size() << std::endl; //TODO this is left blank so that the dataformats etc. can come in a seperate PR //to keep different work seperate. - LOG(fatal) << "Called packData of TrapSimualtor ... why? I am going to die, till next pr."; - return 1; + uint32_t wordswritten = 0; // count the 32 bit words written; + // std::cout << &raw[offset] << std::endl; + // std::cout << raw.data() << std::endl;; + TrackletMCMHeader mcmhead; + int trackletcount = 0; + // TrackletMCMHeader mcmhead; + offset++; + std::array<TrackletMCMData, 3> tracklets{}; + mcmhead.oneb = 1; + mcmhead.onea = 1; + mcmhead.padrow = ((mRobPos >> 1) << 2) | (mMcmPos >> 2); + int mcmcol = mMcmPos % FeeParam::mgkNmcmRobInCol + (mRobPos % 2) * FeeParam::mgkNmcmRobInCol; + int padcol = mcmcol * FeeParam::mgkNcolMcm + FeeParam::mgkNcolMcm + 1; + mcmhead.col = 1; //TODO check this, cant call FeeParam due to virtual function + LOG(debug) << "packing data with trackletarry64 size of : " << mTrackletArray64.size(); + for (int i = 0; i < 3; i++) { + if (i < mTrackletArray64.size()) { // we have a tracklet + LOG(debug) << "we have a tracklet at i=" << i << " with trackletword 0x" << mTrackletArray64[i].getTrackletWord(); + switch (i) { + case 0: + mcmhead.pid0 = ((mTrackletArray64[0].getQ2()) << 2) + ((mTrackletArray64[0].getQ1()) >> 5); + break; // all of Q2 and upper 2 bits of Q1. + case 1: + mcmhead.pid1 = ((mTrackletArray64[1].getQ2()) << 2) + ((mTrackletArray64[1].getQ1()) >> 5); + break; // all of Q2 and upper 2 bits of Q1. + case 2: + mcmhead.pid2 = ((mTrackletArray64[2].getQ2()) << 2) + ((mTrackletArray64[2].getQ1()) >> 5); + break; // all of Q2 and upper 2 bits of Q1. + } + tracklets[i].checkbit = 1; + uint32_t tmppid = mTrackletArray64[i].getPID() & 0x3fff; + LOG(debug) << "tracklet i " << i << " has pid of 0x" << std::hex << mTrackletArray64[i].getPID() << " and we are going to put in 0x" << std::hex << tmppid; + LOG(debug) << mTrackletArray64[i]; + tracklets[i].pid = mTrackletArray64[i].getPID() & 0x3fff; // the bottom 12 bits of the pid + tracklets[i].slope = mTrackletArray64[i].getSlope(); + tracklets[i].pos = mTrackletArray64[i].getPosition(); + tracklets[i].checkbit = 0; + trackletcount++; + } else { // else we dont have a tracklet so mark it off in the header. + switch (i) { + case 1: + mcmhead.pid1 = 0xff; + LOG(debug) << "setting mcmhead pid1 to 0xff with tracklet array size of " << mTrackletArray64[i]; + break; // set the pid to ff to signify not there + case 2: + mcmhead.pid2 = 0xff; + break; // set the pid to maximal to signify not there (6bits). + } + } + } + // raw.push_back((uint32_t)mcmhead) + LOG(debug) << "pushing back mcm head of 0x" << std::hex << mcmhead.word << " with trackletcount of : " << std::dec << trackletcount << ":-:" << wordswritten; + rawdata.push_back(mcmhead.word); //memcpy(&rawdata[wordswritten++], &mcmhead, sizeof(mcmhead)); + wordswritten++; + for (int i = 0; i < trackletcount; i++) { + LOG(debug) << "pushing back mcmtrackletword of 0x" << std::hex << tracklets[i].word; + rawdata.push_back(tracklets[i].word); //memcpy(&rawdata[wordswritten++], &tracklets[i], sizeof(TrackletMCMData)); + wordswritten++; + } + + //display the headers written + if (debugheaders) { + LOG(info) << ">>>>> START DEBUG OUTPUT OF packData trackletcount:-:wordcount" << trackletcount << ":-:" << wordswritten; + o2::trd::printTrackletMCMHeader(mcmhead); + o2::trd::printTrackletMCMData(tracklets[0]); + if (trackletcount > 1) + o2::trd::printTrackletMCMData(tracklets[1]); + if (trackletcount > 2) + o2::trd::printTrackletMCMData(tracklets[2]); + LOG(info) << "<<<<< END DEBUG OUTPUT OF packData"; + } + //must produce between 2 and 4 words ... 1 and 3 tracklets. + // assert(wordswritten<5); + // assert(wordswritten>1); + LOG(debug) << "now to leave pack data after passing asserts with wordswritten = " << wordswritten; + return wordswritten; // in units of 32 bits. } -int TrapSimulator::produceRawStream(std::vector<uint32_t>& buf, unsigned int iEv) const +int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, unsigned int iEv) const { // // Produce raw data stream from this MCM and put in buf @@ -986,7 +1064,7 @@ int TrapSimulator::produceRawStream(std::vector<uint32_t>& buf, unsigned int iEv return numberWordsWritten; } -int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) +int TrapSimulator::getTrackletStream(std::vector<uint32_t>& buf, uint32_t offset) { // // Produce tracklet raw data stream from this MCM and put in buf @@ -1003,8 +1081,9 @@ int TrapSimulator::produceTrackletStream(std::vector<uint32_t>& buf) // Produce tracklet data. // A MCM Header followed by at most 3 tracklet words. // Although a little confusingly some of the tracklet data is in the header. - - numberWordsWritten = packData(buf); + if (mTrackletArray64.size() != 0) { // meaningless if there are no tracklets + numberWordsWritten = packData(buf, offset); + } return numberWordsWritten; } @@ -1136,14 +1215,14 @@ unsigned short TrapSimulator::filterGainNextSample(int adc, unsigned short value unsigned short mga = mTrapConfig->getTrapReg(TrapConfig::TrapReg_t(TrapConfig::kFGA0 + adc), mDetector, mRobPos, mMcmPos); // 40; unsigned short mgta = mTrapConfig->getTrapReg(TrapConfig::kFGTA, mDetector, mRobPos, mMcmPos); // 20; unsigned short mgtb = mTrapConfig->getTrapReg(TrapConfig::kFGTB, mDetector, mRobPos, mMcmPos); // 2060; - // mgf=256; - // mga=8; - // mgta=20; - // mgtb=2060; + // mgf=256; + // mga=8; + // mgta=20; + // mgtb=2060; unsigned int mgfExtended = 0x700 + mgf; // The corr factor which is finally applied has to be extended by 0x700 (hex) or 0.875 (dec) - // because fgf=0 correspons to 0.875 and fgf=511 correspons to 1.125 - 2^(-11) - // (see TRAP User Manual for details) + // because fgf=0 correspons to 0.875 and fgf=511 correspons to 1.125 - 2^(-11) + // (see TRAP User Manual for details) //if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " with adc = " << adc << " value = " << value << " Trapconfig values :" << mgby <<":"<<mgf<<":"<<mga<<":"<<mgta<<":"<<mgtb << ":"<< mgfExtended; unsigned int corr; // corrected value @@ -1392,6 +1471,13 @@ void TrapSimulator::addHitToFitreg(int adc, unsigned short timebin, unsigned sho mFitReg[adc].mQ1 += qtot; } + if ((timebin > mTrapConfig->getTrapReg(TrapConfig::kTPQE1, mDetector, mRobPos, mMcmPos)) && + (timebin > mTrapConfig->getTrapReg(TrapConfig::kTPQE0, mDetector, mRobPos, mMcmPos)) && + (timebin < mNTimeBin)) { + mFitReg[adc].mQ2 += qtot; + // TODO I am not sure what happens with Q2, for now just assume its the rest of the time windows after Q0 and Q1 and before the end of the time bins. + } + if ((timebin >= mTrapConfig->getTrapReg(TrapConfig::kTPFS, mDetector, mRobPos, mMcmPos)) && (timebin < mTrapConfig->getTrapReg(TrapConfig::kTPFE, mDetector, mRobPos, mMcmPos))) { mFitReg[adc].mSumX += timebin; @@ -1504,14 +1590,14 @@ void TrapSimulator::calcFitreg() // The accumulated charge is with the pedestal!!! qtotTemp = adcLeft + adcCentral + adcRight; /* if ((qtotTemp > 130)) { - LOG(info) << "testtree " - << "qtot=" << qtotTemp - << " qleft=" << adcLeft - << " qcent=" << adcCentral - << " qright=" << adcRight - << " for " << mDetector <<":"<<mRobPos<<":"<<mMcmPos << ":adcleft:"<<adcch<<":t"<<timebin; - } -*/ + LOG(info) << "testtree " + << "qtot=" << qtotTemp + << " qleft=" << adcLeft + << " qcent=" << adcCentral + << " qright=" << adcRight + << " for " << mDetector <<":"<<mRobPos<<":"<<mMcmPos << ":adcleft:"<<adcch<<":t"<<timebin; + } + */ if ((hitQual) && (qtotTemp >= mTrapConfig->getTrapReg(TrapConfig::kTPHT, mDetector, mRobPos, mMcmPos)) && (adcLeft <= adcCentral) && @@ -1607,9 +1693,9 @@ void TrapSimulator::calcFitreg() // subtract the pedestal TPFP, clipping instead of wrapping int regTPFP = mTrapConfig->getTrapReg(TrapConfig::kTPFP, mDetector, mRobPos, mMcmPos); //TODO put this together with the others as members of trapsim, which is initiliased by det,rob,mcm. - // LOG(info) << "Hit found, time=" << timebin << ", adcch=" << adcch << "/" << adcch + 1 << "/" - // << adcch + 2 << ", adc values=" << adcLeft << "/" << adcCentral << "/" - // << adcRight << ", regTPFP=" << regTPFP << ", TPHT=" << mTrapConfig->getTrapReg(TrapConfig::kTPHT, mDetector, mRobPos, mMcmPos); + // LOG(info) << "Hit found, time=" << timebin << ", adcch=" << adcch << "/" << adcch + 1 << "/" + // << adcch + 2 << ", adc values=" << adcLeft << "/" << adcCentral << "/" + // << adcRight << ", regTPFP=" << regTPFP << ", TPHT=" << mTrapConfig->getTrapReg(TrapConfig::kTPHT, mDetector, mRobPos, mMcmPos); if (adcLeft < regTPFP) adcLeft = 0; else @@ -1636,23 +1722,23 @@ void TrapSimulator::calcFitreg() if (adcLeft > adcRight) ypos = -ypos; /* TODO this is left in here as a ref for what was done with labels, its stored externally now figure something out. -*/ + */ // add the hit to the fitregister // int a=qTotal[adcch] >> mgkAddDigits; // LOG(info) << "calling addHitToFitreg with :" << adcch << " :: " << timebin << " :: " << hex << qTotal[adcch] << dec << " :: shifted bits :" << 2 << " :: " << ypos; // addHitToFitreg(adcch, timebin, qTotal[adcch] >> 2, ypos); LOG(debug) << __func__ << "ADDING HIT FOR in adclabels : " << mADCLabels[adcch].size() << " with adcch of " << adcch << " qtot : " << qTotal[adcch] << " timebin :" << timebin; addHitToFitreg(adcch, timebin, qTotal[adcch] >> mgkAddDigits, ypos); //, mADCLabels[adcch]); - // LOG(debug) << __FILE__ << ":" << __LINE__ << " :: added hit to fit re "; + // LOG(debug) << __FILE__ << ":" << __LINE__ << " :: added hit to fit re "; } } } /* - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { - if (mFitReg[iAdc].mNhits != 0) { - LOG(debug) << "fitreg[" << iAdc << "]: nHits = " << mFitReg[iAdc].mNhits << "]: sumX = " << mFitReg[iAdc].mSumX << ", sumY = " << mFitReg[iAdc].mSumY << ", sumX2 = " << mFitReg[iAdc].mSumX2 << ", sumY2 = " << mFitReg[iAdc].mSumY2 << ", sumXY = " << mFitReg[iAdc].mSumXY; - } - }*/ + for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { + if (mFitReg[iAdc].mNhits != 0) { + LOG(debug) << "fitreg[" << iAdc << "]: nHits = " << mFitReg[iAdc].mNhits << "]: sumX = " << mFitReg[iAdc].mSumX << ", sumY = " << mFitReg[iAdc].mSumY << ", sumX2 = " << mFitReg[iAdc].mSumX2 << ", sumY2 = " << mFitReg[iAdc].mSumY2 << ", sumXY = " << mFitReg[iAdc].mSumXY; + } + }*/ //print(PRINTRAW); LOG(debug) << "LEAVING : " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " :: " << getDetector() << ":" << getRobPos() << ":" << getMcmPos() << " and mNHits : " << mNHits; } @@ -1718,9 +1804,9 @@ void TrapSimulator::trackletSelection() mFitPtr[i] = trackletCandch[i]; // pointer to the left channel with tracklet for CPU[i] for (i = ntracks; i < 4; i++) // CPUs without tracklets mFitPtr[i] = 31; // pointer to the left channel with tracklet for CPU[i] = 31 (invalid) - // LOG(info) << "-------------------------------------------- found " << ntracks << " tracklet candidates"; - // for (i = 0; i < 4; i++) - // LOG(info) << "fitPtr[" << i << "]: " << mFitPtr[i]; + // LOG(info) << "-------------------------------------------- found " << ntracks << " tracklet candidates"; + // for (i = 0; i < 4; i++) + // LOG(info) << "fitPtr[" << i << "]: " << mFitPtr[i]; // reject multiple tracklets if (FeeParam::instance()->getRejectMultipleTracklets()) { @@ -1762,7 +1848,7 @@ void TrapSimulator::fitTracklet() // parameters in fitred.asm (fit program) int rndAdd = 0; int decPlaces = 5; // must be larger than 1 or change the following code - // if (decPlaces > 1) + // if (decPlaces > 1) rndAdd = (1 << (decPlaces - 1)) + 1; // else if (decPlaces == 1) // rndAdd = 1; @@ -1790,7 +1876,7 @@ void TrapSimulator::fitTracklet() // local variables for calculation long mult, temp, denom; //??? - unsigned int q0, q1, pid; // charges in the two windows and total charge + unsigned int q0, q1, q2 = 23, pid; // charges in the two windows and total charge float rawpid, rawz, rawy, rawslope, rawoffset; float rawslope4trackletword, rawoffset4trackletword; unsigned short nHits; // number of hits @@ -1949,6 +2035,8 @@ void TrapSimulator::fitTracklet() mHits[iHit].mTimebin < mTrapConfig->getTrapReg(TrapConfig::kTPQE1, mDetector, mRobPos, mMcmPos)) { nHits1++; } + //TODO nHits2 ???? to correspond to Q2 ??? + // LOG(debug) << "setting bit pattern for chanel : " << mHits[iHit].mChannel << " of hit : " << iHit << std::hex << " bitp before : " << adchitbp << std::dec; adchitbp |= (1 << mHits[iHit].mChannel); LOG(debug) << "after setting bit pattern for chanel : " << mHits[iHit].mChannel << " of hit : " << iHit << std::hex << " bitp after : " << adchitbp << std::dec; @@ -1976,8 +2064,15 @@ void TrapSimulator::fitTracklet() LOG(debug) << "TrapSim Trackletarray size is : " << mTrackletArray.size() << " :: adding a track at " << mMCMT[cpu] << ":" << mDetector * 2 + mRobPos % 2 << ":" << mRobPos << ":" << mMcmPos << " LABELS size: " << localTrackletLabels.size(); mTrackletArray.emplace_back(mDetector * 2 + mRobPos % 2, mRobPos, mMcmPos, rawpid, rawslope, rawoffset, rawslope4trackletword, rawoffset4trackletword); + uint32_t format = 0; + uint32_t hcid = mDetector * 2 + mRobPos % 2; + uint32_t padrow = ((mRobPos >> 1) << 2) | (mMcmPos >> 2); + uint32_t col = 0; + uint32_t position = rawoffset; + //uint32_t s + mTrackletArray64.emplace_back(format, hcid, padrow, col, position, slope, q2, q1, q0); int newtrackposition = mTrackletArray.size() - 1; - // mTrackletArray[newtrackposition].setLabel(mcLabel); + //mTrackletArray[newtrackposition].setLabel(mcLabel); mTrackletArray[newtrackposition].setNHits(fit0->mNhits + fit1->mNhits); mTrackletArray[newtrackposition].setNHits0(nHits0); mTrackletArray[newtrackposition].setNHits1(nHits1); @@ -2044,11 +2139,11 @@ void TrapSimulator::tracklet() fitTracklet(); } -void TrapSimulator::getTracklets(std::vector<Tracklet>& TrackletStore) +void TrapSimulator::getTracklet64s(std::vector<Tracklet64>& TrackletStore) { // simply returns the found tracklets for the O2 dpl to then do its thing. // - TrackletStore.insert(std::end(TrackletStore), std::begin(mTrackletArray), std::end(mTrackletArray)); + TrackletStore.insert(std::end(TrackletStore), std::begin(mTrackletArray64), std::end(mTrackletArray64)); //std::copy(mTrackletArray.begin(),mTrackletArray.end(),std::back_inserter(TrackletStore)); } @@ -2056,7 +2151,7 @@ void TrapSimulator::getTracklets(std::vector<Tracklet>& TrackletStore) // PID section // // Memory area for the LUT: 0xC100 to 0xC3FF -// +// ??? TODO Q2 ??? Aso do we still need this function? We are sending back the charge sumations now. // The addresses for the parameters (the order is optimized for maximum calculation speed in the MCMs): // 0xC028: cor1 // 0xC029: nBins(sF) @@ -2105,7 +2200,7 @@ int TrapSimulator::getPID(int q0, int q1) addrQ0 = (((addrQ0 * q0) >> 16) >> 16); // because addrQ0 = (q0 * corrQ0) >> 32; does not work for unknown reasons if (addrQ0 >= nBinsQ0) { // check for overflow - // LOG(debug3) << "Overflow in q0: " << addrQ0 << "/4 is bigger then " << nBinsQ0; + // LOG(debug3) << "Overflow in q0: " << addrQ0 << "/4 is bigger then " << nBinsQ0; addrQ0 = nBinsQ0 - 1; } diff --git a/Detectors/TRD/workflow/CMakeLists.txt b/Detectors/TRD/workflow/CMakeLists.txt index 078158c38810c..99be830a2f288 100644 --- a/Detectors/TRD/workflow/CMakeLists.txt +++ b/Detectors/TRD/workflow/CMakeLists.txt @@ -16,6 +16,7 @@ o2_add_library(TRDWorkflow src/TRDDigitWriterSpec.cxx src/TRDDigitReaderSpec.cxx src/TRDTrackletWriterSpec.cxx + src/TRDTrapRawWriterSpec.cxx src/TRDTrapSimulatorSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::Steer O2::Algorithm O2::DataFormatsTRD O2::TRDSimulation O2::DetectorsBase O2::SimulationDataFormat O2::TRDBase) diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapRawWriterSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapRawWriterSpec.h new file mode 100644 index 0000000000000..82189f7affe7f --- /dev/null +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapRawWriterSpec.h @@ -0,0 +1,40 @@ +// 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_TRDTRAPSIMULATORRAWWRITER_H +#define O2_TRDTRAPSIMULATORRAWWRITER_H + +#include <fstream> +#include <iostream> + +// This is the raw data that is output by the trap trap chip. +// mcmheader word followed by 1 or more traprawtracklet words. +// and a halfchamber header at the beginning of a half chamber. +// halfchamber header + mcmheader uniquely identifies the chip producing the data. + +namespace o2 +{ +namespace framework +{ +struct DataProcessorSpec; +} +} // namespace o2 + +namespace o2 +{ +namespace trd +{ + +o2::framework::DataProcessorSpec getTRDTrapRawWriterSpec(); + +} // end namespace trd +} // end namespace o2 + +#endif // O2_TRDTRAPSIMULATORRAWWRITER_H diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h index dec702aa3d185..a69092e7c64bb 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h @@ -18,9 +18,11 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "TRDBase/FeeParam.h" -#include "TRDBase/Tracklet.h" #include "TRDSimulation/TrapSimulator.h" #include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/LinkRecord.h" +#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/RawData.h" #include "TRDSimulation/TrapConfig.h" #include "CCDB/BasicCCDBManager.h" @@ -39,7 +41,12 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task void init(o2::framework::InitContext& ic) override; void run(o2::framework::ProcessingContext& pc) override; - void fixTriggerRecords(std::vector<o2::trd::TriggerRecord>& trigRecord); + + protected: + void fixTriggerRecords(std::vector<o2::trd::TriggerRecord>& trigRecord); // should be temporary. + void setTriggerRecord(std::vector<o2::trd::TriggerRecord>& triggerrecord, uint32_t currentrecord, uint64_t recordsize); + void setTrapSimulatorData(int adc, std::vector<o2::trd::Digit>& digits, int digitposition); + // TODO LABELS, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* labels) private: std::array<TrapSimulator, 8> mTrapSimulator; //the 8 trap simulators for a given padrow. @@ -58,13 +65,14 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task bool mEnableOnlineGainCorrection{false}; bool mEnableTrapConfigDump{false}; bool mFixTriggerRecords{false}; // shift the trigger record due to its being corrupt on coming in. - std::vector<Tracklet> mTracklets; // store of found tracklets + std::vector<Tracklet64> mTracklets; // store of found tracklets std::string mTrapConfigName; // the name of the config to be used. std::string mTrapConfigBaseName = "TRD_test/TrapConfig/"; std::unique_ptr<CalOnlineGainTables> mGainTable; //this will probably not be used in run3. std::string mOnlineGainTableName; std::unique_ptr<Calibrations> mCalib; // store the calibrations connection to CCDB. Used primarily for the gaintables in line above. + std::vector<o2::trd::LinkRecord> mLinkRecords; //arrays to keep some stats during processing std::array<unsigned int, 8> mTrapUsedCounter{0}; std::array<unsigned int, 8> mTrapUsedFrequency{0}; @@ -77,9 +85,14 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task std::chrono::duration<double> mTrackletTime{0}; ///< full timer std::chrono::duration<double> mSortingTime{0}; ///< full timer + uint64_t mTotalRawWordsWritten = 0; // words written for the raw format of 4x32bits, where 4 can be 2 to 4 depending on # of tracklets in the block. + int32_t mOldHalfChamberID = 0; + bool mNewTrackletHCHeaderHasBeenWritten{false}; + TrackletHCHeader mTrackletHCHeader; // the current half chamber header, that will be written if a first tracklet is found for this halfchamber. TrapConfig* getTrapConfig(); void loadTrapConfig(); void setOnlineGainTables(); + uint32_t getHalfChamberID(uint32_t detector, uint32_t rob) { return detector * 2 + rob % 2; }; }; o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec(); diff --git a/Detectors/TRD/workflow/src/TRDTrackletWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDTrackletWriterSpec.cxx index 709402e5c463a..ee8d4ff93ef7b 100644 --- a/Detectors/TRD/workflow/src/TRDTrackletWriterSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrackletWriterSpec.cxx @@ -18,8 +18,8 @@ #include "TRDBase/Digit.h" #include <SimulationDataFormat/MCTruthContainer.h> #include "TRDBase/MCLabel.h" -#include "TRDBase/Tracklet.h" #include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/Tracklet64.h" #include <fstream> #include <iostream> @@ -52,7 +52,7 @@ o2::framework::DataProcessorSpec getTRDTrackletWriterSpec() "trdtracklets.root", "o2sim", 1, - BranchDefinition<std::vector<o2::trd::Tracklet>>{InputSpec{"tracklets", "TRD", "TRACKLETS"}, "Tracklet"}, + BranchDefinition<std::vector<o2::trd::Tracklet64>>{InputSpec{"tracklets", "TRD", "TRACKLETS"}, "Tracklet"}, //BranchDefinition<o2::dataformats::MCTruthContainer<o2::trd::MCLabel>>{InputSpec{"trklabels", "TRD", "TRKLABELS"}, "TRKLabels"}, BranchDefinition<std::vector<o2::trd::TriggerRecord>>{InputSpec{"tracklettrigs", "TRD", "TRKTRGRD"}, "TrackTrg"})(); }; diff --git a/Detectors/TRD/workflow/src/TRDTrapRawWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapRawWriterSpec.cxx new file mode 100644 index 0000000000000..e05161a9bcec9 --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDTrapRawWriterSpec.cxx @@ -0,0 +1,51 @@ +// 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_TRDTRAPSIMULATORTRAPRAWWRITER_H +#define O2_TRDTRAPSIMULATORTRAPRAWWRITER_H + +#include "Framework/DataProcessorSpec.h" +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "Framework/InputSpec.h" +#include "TRDWorkflow/TRDTrapRawWriterSpec.h" +#include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/LinkRecord.h" + +#include <fstream> +#include <iostream> + +using namespace o2::framework; + +namespace o2 +{ +namespace trd +{ + +template <typename T> +using BranchDefinition = framework::MakeRootTreeWriterSpec::BranchDefinition<T>; + +o2::framework::DataProcessorSpec getTRDTrapRawWriterSpec() +{ + // using InputSpec = framework::InputSpec; + using MakeRootTreeWriterSpec = framework::MakeRootTreeWriterSpec; + return MakeRootTreeWriterSpec("TRDTrkltRawWrt", + "trdtrapraw.root", + "o2sim", + 1, + BranchDefinition<std::vector<uint32_t>>{InputSpec{"trapraw", "TRD", "RAWDATA"}, "TrapRaw"}, + BranchDefinition<std::vector<o2::trd::LinkRecord>>{InputSpec{"traplinks", "TRD", "RAWLNKRD"}, "TrapLinkRecord"}, + BranchDefinition<std::vector<o2::trd::TriggerRecord>>{InputSpec{"traprawtrigrec", "TRD", "RAWTRGRD"}, "RawTriggerRecord"})(); +}; + +} // end namespace trd +} // end namespace o2 + +#endif // O2_TRDTRAPSIMULATORTRACKLETWRITER_H diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 1e4876f90f600..10773f8d9f28e 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -20,6 +20,8 @@ #include <cmath> #include <unistd.h> // for getppid #include <chrono> +#include <gsl/span> + #include "TChain.h" #include "Framework/ConfigParamRegistry.h" @@ -46,6 +48,9 @@ #include "TRDBase/Calibrations.h" #include "TRDSimulation/TrapSimulator.h" #include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/LinkRecord.h" +#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/RawData.h" //#ifdef WITH_OPENMP //#include <omp.h> @@ -116,7 +121,7 @@ TrapConfig* TRDDPLTrapSimulatorTask::getTrapConfig() // try to load the requested configuration loadTrapConfig(); //calib. - LOG(debug) << "using TRAPconfig :" << mTrapConfig->getConfigName().c_str() << "." << mTrapConfig->getConfigVersion().c_str(); + LOG(info) << "using TRAPconfig :" << mTrapConfig->getConfigName().c_str() << "." << mTrapConfig->getConfigVersion().c_str(); // we still have to load the gain tables // if the gain filter is active @@ -168,7 +173,7 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() { // try to load the specified configuration from the CCDB - LOG(debug) << "looking for TRAPconfig " << mTrapConfigName; + LOG(info) << "looking for TRAPconfig " << mTrapConfigName; auto& ccdbmgr = o2::ccdb::BasicCCDBManager::instance(); ccdbmgr.setTimestamp(297595); @@ -179,7 +184,6 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() //failed to find or open or connect or something to get the trapconfig from the ccdb. //first check the directory listing. LOG(warn) << " failed to get trapconfig from ccdb with name : " << mTrapConfigName; - LOG(info) << "Retrieving trapconfig failed"; } else { //TODO figure out how to get the debug level from logger and only do this for debug option to --severity debug (or what ever the command actualy is) if (mEnableTrapConfigDump) @@ -302,6 +306,19 @@ bool digitindexcompare(unsigned int A, unsigned int B, const std::vector<o2::trd return 0; } +void TRDDPLTrapSimulatorTask::setTriggerRecord(std::vector<o2::trd::TriggerRecord>& triggerrecord, uint32_t currentrecord, uint64_t recordsize) +{ + // so increment the tracklet trigger records and fill accordingly for the now completed prior triggerrecord. + uint64_t triggerrecordstart = 0; + if (currentrecord == 0) { // for not the first one we can simply look back to the previous one to get the start. + triggerrecordstart = 0; + triggerrecord[currentrecord].setDataRange(triggerrecordstart, recordsize); + } else { + triggerrecordstart = triggerrecord[currentrecord - 1].getFirstEntry() + triggerrecord[currentrecord - 1].getNumberOfObjects(); + triggerrecord[currentrecord].setDataRange(triggerrecordstart, recordsize - triggerrecordstart); + } +} + void TRDDPLTrapSimulatorTask::fixTriggerRecords(std::vector<o2::trd::TriggerRecord>& trigRecord) { // Trigger records are coming with an extra one at the end, and the first one blank and the last 2 having the same bunch crossing information. @@ -332,14 +349,11 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // mNumThreads = std::min(maxthreads, 8); // LOG(INFO) << "TRD: Trapping with " << mNumThreads << " threads "; //#endif - //TODO need to change to gsl::span. // get inputs for the TrapSimulator // the digits are going to be sorted, we therefore need a copy of the vector rather than an object created // directly on the input data, the output vector however is created directly inside the message // memory thus avoiding copy by snapshot - // TODO: rather than sorting the digits, an index can be sorted and the read-only input data accessed - // via the sorted index auto inputDigits = pc.inputs().get<gsl::span<o2::trd::Digit>>("digitinput"); std::vector<o2::trd::Digit> msgDigits(inputDigits.begin(), inputDigits.end()); // auto digits pc.outputs().make<std::vector<o2::trd::Digit>>(Output{"TRD", "TRKDIGITS", 0, Lifetime::Timeframe}, msgDigits.begin(), msgDigits.end()); @@ -351,7 +365,10 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // the returned object is read-only as it refers directly to the underlying raw input data // need to make a copy because the object might be changed in fixTriggerRecords auto inputTriggerRecords = pc.inputs().get<gsl::span<o2::trd::TriggerRecord>>("triggerrecords"); + // trigger records to index the 64bit tracklets.yy std::vector<o2::trd::TriggerRecord> triggerRecords(inputTriggerRecords.begin(), inputTriggerRecords.end()); + // trigger records to index the "raw" data + uint64_t currentTriggerRecord = 0; for (auto& trig : triggerRecords) { @@ -362,6 +379,9 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) fixTriggerRecords(triggerRecords); std::vector<o2::trd::TriggerRecord> trackletTriggerRecords = triggerRecords; // copy over the whole thing but we only really want the bunch crossing info. + std::vector<o2::trd::TriggerRecord> rawTriggerRecords = triggerRecords; // as we have the option of having tracklets and/or raw data, we need both triggerrecords. + // of course we dont *actually* need it we could simply walk through all the raw data header to header. + mLinkRecords.reserve(1077 * triggerRecords.size()); // worse case scenario is all links for all events. TODO get 1077 from somewhere. //TODO these must be created directly in the output as done at the top of this run method std::vector<unsigned int> msgDigitsIndex; @@ -370,15 +390,18 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) LOG(debug) << "Read in msgDigits with size of : " << msgDigits.size() << " labels contain : " << digitMCLabels->getNElements() << " with and index size of : " << digitMCLabels->getIndexedSize(); if (digitMCLabels->getIndexedSize() != msgDigits.size()) { - LOG(debug) << "Read in msgDigits with size of : " << msgDigits.size() << " labels contain : " << digitMCLabels->getNElements() << " with and index size of : " << digitMCLabels->getIndexedSize(); - LOG(warn) << "Digits and Labels coming into TrapSimulator are of differing sizes, labels will be jibberish. "; + LOG(warn) << "Digits and Labels coming into TrapSimulator are of differing sizes, labels will be jibberish. " << digitMCLabels->getIndexedSize() << "!=" << msgDigits.size(); } //set up structures to hold the returning tracklets. - std::vector<Tracklet> trapTracklets; //vector to store the retrieved tracklets from an trapsim object - std::vector<Tracklet> trapTrackletsAccum; + std::vector<Tracklet64> trapTracklets; //vector to store the retrieved tracklets from an trapsim object + std::vector<Tracklet64> trapTrackletsAccum; + std::vector<uint32_t> rawdata; + trapTracklets.reserve(30); trapTrackletsAccum.reserve(msgDigits.size() / 3); msgDigitsIndex.reserve(msgDigits.size()); + // worse case scenario is header and single tracklet word, hence 2, for higher tracklet count the factors reduces relative to tracklet count. Remember 3 digits per tracklet. + rawdata.reserve(msgDigits.size() * 2); int count = 0; //make msgDigitsIndex a simple vector of ascending numbers mapping trivially into the msgDigits vector. @@ -391,7 +414,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) //sort the digits array std::stable_sort(msgDigits.begin(), msgDigits.end(), msgDigitSortComparator); mSortingTime = std::chrono::high_resolution_clock::now() - sortstart; - LOG(info) << "TRD Digit Sorting took " << mSortingTime.count(); + LOG(debug) << "TRD Digit Sorting took " << mSortingTime.count(); // sort from triggerRecords.getFirstEntry() to triggerRecords.getFirstEntry()+triggerRecords.getNumberOfObjects(); //check the incoming triggerrecords: for (auto& trig : triggerRecords) { @@ -401,6 +424,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) LOG(debug) << "Trigger Tracklet Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); } //accounting variables for various things. + //TODO make them class members, i dont want to fiddle right now though. int olddetector = -1; int oldrow = -1; int oldpad = -1; @@ -409,11 +433,15 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) int oldsize = 0; double trackletrate; unsigned long oldtrackletcount = 0; + mTotalRawWordsWritten = 0; // words written for the raw format of 4x32bits, where 4 can be 2 to 4 depending on # of tracklets in the block. + mOldHalfChamberID = 0; + mNewTrackletHCHeaderHasBeenWritten = false; // now to loop over the incoming digits. auto digitloopstart = std::chrono::high_resolution_clock::now(); uint64_t digitcounter = 0; - for (auto digititerator = msgDigits.begin(); digititerator != msgDigits.end() /* && loopindex<300*/; ++digititerator) { + LOG(debug4) << "now for digit loop "; + for (auto digititerator = msgDigits.begin(); digititerator != msgDigits.end() /* && std::distance(msgDigits.begin(),digititerator)<7*/; ++digititerator) { //in here we have an entire padrow which corresponds to 8 TRAPs. //while on a single padrow, populate data structures in the 8 trapsimulator. //on change of padrow @@ -425,37 +453,46 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) int rob = mFeeParam->getROBfromPad(row, pad); int mcm = mFeeParam->getMCMfromPad(row, pad); LOG(debug3) << "calculated rob and mcm at top of loop with detector:row:pad:rob:mcm" << detector << ":" << row << ":" << pad << ":" << rob << ":" << mcm; + LOG(debug) << "digit time : " << digittime; if (digititerator == msgDigits.begin()) { // first time in loop oldrow = row; olddetector = detector; } - + //Are we on a new half chamber ? + if (mOldHalfChamberID != getHalfChamberID(detector, rob)) { + // hcid= detector*2 + robpos%2; + // new half chamber so add the header to the raw data stream. + mTrackletHCHeader.HCID = getHalfChamberID(detector, rob); + mTrackletHCHeader.one = 1; + mTrackletHCHeader.MCLK = currentTriggerRecord * 42; // 42 because its the universally true answer, this is fake in anycase, so long as its always bigger than the previous one and increasing. + mTrackletHCHeader.format = 4; + mOldHalfChamberID = getHalfChamberID(detector, rob); + // now we have a problem. We must only write the halfchamberheader if a tracklet is written i.e. if the digits for this half chamber actually produce 1 or more tracklets! + mNewTrackletHCHeaderHasBeenWritten = false; + } //figure out which trigger record from digits we are on if (digitcounter >= triggerRecords[currentTriggerRecord].getFirstEntry() + triggerRecords[currentTriggerRecord].getNumberOfObjects()) { //trigger record changed. - // so increment the tracklet trigger records and fill accordingly for the now completed prior triggerrecord. - uint64_t triggerrecordstart = 0; - if (currentTriggerRecord == 0) { // for not the first one we can simply look back to the previous one to get the start. - triggerrecordstart = 0; - trackletTriggerRecords[currentTriggerRecord].setDataRange(triggerrecordstart, trapTrackletsAccum.size()); - } else { - triggerrecordstart = trackletTriggerRecords[currentTriggerRecord - 1].getFirstEntry() + trackletTriggerRecords[currentTriggerRecord - 1].getNumberOfObjects(); - trackletTriggerRecords[currentTriggerRecord].setDataRange(triggerrecordstart, trapTrackletsAccum.size() - triggerrecordstart); - } - currentTriggerRecord++; //move to next trigger record. + //Now we know the ranges so populate the triggerrecord related to the previously block of data. + setTriggerRecord(trackletTriggerRecords, currentTriggerRecord, trapTrackletsAccum.size()); + setTriggerRecord(rawTriggerRecords, currentTriggerRecord, mTotalRawWordsWritten); + currentTriggerRecord++; + LOG(debug) << "changing trigger records : " << currentTriggerRecord; } if (olddetector != detector || oldrow != row) { // we have gone over the pad row. //TODO ??? do we need to check for change of time as well? //all data is inside the 8 relavent trapsimulators + LOG(debug) << "digit count in change padrow if statement is : " << std::distance(msgDigits.begin(), digititerator); int preivousrob = mFeeParam->getROBfromPad(oldrow, oldpad); // //fireup Trapsim. auto traploopstart = std::chrono::high_resolution_clock::now(); unsigned long numberofusedtraps = 0; for (int trapcounter = 0; trapcounter < 8; trapcounter++) { unsigned int isinit = mTrapSimulator[trapcounter].checkInitialized(); - // LOG(debug3) << "Start of trap : " << trapcounter; + LOG(debug) << "Start of trap : " << trapcounter; if (mTrapSimulator[trapcounter].isDataSet()) { //firedtraps + LOG(debug3) << "DataSet on : " << trapcounter; //this one has been filled with data for the now previous pad row. auto trapsimtimerstart = std::chrono::high_resolution_clock::now(); mTrapUsedCounter[trapcounter]++; @@ -463,9 +500,26 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) mTrapSimulator[trapcounter].filter(); mTrapSimulator[trapcounter].tracklet(); - trapTracklets = mTrapSimulator[trapcounter].getTrackletArray(); //TODO remove the copy and send the Accumulated array into the Trapsimulator + trapTracklets = mTrapSimulator[trapcounter].getTrackletArray64(); //TODO remove the copy and send the Accumulated array into the Trapsimulator auto trapLabels = mTrapSimulator[trapcounter].getTrackletLabels(); - + if (!mNewTrackletHCHeaderHasBeenWritten && trapTracklets.size() != 0) { // take account of the case where we have data in the trapchip adc but no tracklets + //we have a tracklet for said half chamber, but the halfchamber ID has not been written yet + // .. fix the previous linkrecord to note its end of range. + if (mLinkRecords.size() == 0) { // special case for the first entry into the linkrecords vector. + mLinkRecords.emplace_back(mTrackletHCHeader.word, 0, -1); + } else { + mLinkRecords.back().setNumberOfObjects(mTotalRawWordsWritten - mLinkRecords.back().getFirstEntry()); // current number of words written - the start of this index record. + //..... so write the new one thing + + mLinkRecords.emplace_back(mTrackletHCHeader.word, mTotalRawWordsWritten, -1); // set the number of elements to -1 for an error condition + } + //mTotalRawWordsWritten++; //no longer writing to raw stream + mNewTrackletHCHeaderHasBeenWritten = true; + LOG(debug) << mTrackletHCHeader; + } + LOG(debug) << "getting trackletsteram for trapcounter = " << trapcounter; + auto wordswritten = mTrapSimulator[trapcounter].getTrackletStream(rawdata, mTotalRawWordsWritten); // view of data from current marker and only 5 words long (can only have 4 words at most in the trackletstream for 1 MCM) + mTotalRawWordsWritten += wordswritten; LOG(debug) << "Tracklets accumulated before addition of new ones :" << trapTrackletsAccum.size() << " :: about to add " << trapTracklets.size() << " count tracklets, labels coming in index of: " << trapLabels.getIndexedSize() << " and elements of : " @@ -476,7 +530,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) mTrapSimAccumulatedTime += std::chrono::high_resolution_clock::now() - trapsimtimerstart; if (mShowTrackletStats > 0) { if (trapTrackletsAccum.size() - oldsize > mShowTrackletStats) { - LOG(debug) << "TrapSim Accumulated tracklets: " << trapTrackletsAccum.size() << " :: " << trapTracklets.size(); + LOG(info) << "TrapSim Accumulated tracklets: " << trapTrackletsAccum.size() << " :: " << trapTracklets.size(); oldsize = trapTrackletsAccum.size(); } } @@ -502,6 +556,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) } // LOG(info) << "Finishe MCM : : " << trapcounter; } //end of loop over trap chips + //timing info mTrapLoopTime += std::chrono::high_resolution_clock::now() - traploopstart; mTrapUsedFrequency[numberofusedtraps]++; @@ -527,12 +582,11 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) int trapindex = pad / 18; //check trap is initialised. if (!mTrapSimulator[trapindex].isDataSet()) { - // LOG(debug) << "Initialising trapsimulator for triplet (" << detector << "," << rob << "," - // << mcm << ") as its not initialized and we need to send it some adc data."; + LOG(debug) << "Initialising trapsimulator for triplet (" << detector << "," << rob << "," + << mcm << ") as its not initialized and we need to send it some adc data."; mTrapSimulator[trapindex].init(mTrapConfig, detector, rob, mcm); } - int adc = 0; - adc = 20 - (pad % 18) - 1; + int adc = 20 - (pad % 18) - 1; std::vector<o2::MCCompLabel> tmplabels; auto digitslabels = digitMCLabels->getLabels(digitcounter); for (auto& tmplabel : digitslabels) { @@ -564,29 +618,37 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // now finalise auto triggerrecordstart = trackletTriggerRecords[currentTriggerRecord - 1].getFirstEntry() + trackletTriggerRecords[currentTriggerRecord - 1].getNumberOfObjects(); trackletTriggerRecords[currentTriggerRecord].setDataRange(triggerrecordstart, trapTrackletsAccum.size() - triggerrecordstart); + mLinkRecords.back().setNumberOfObjects(mTotalRawWordsWritten - mLinkRecords.back().getFirstEntry()); // set the final link entry LOG(info) << "Trap simulator found " << trapTrackletsAccum.size() << " tracklets from " << msgDigits.size() << " Digits and " << trackletMCLabels.getIndexedSize() << " associated MC Label indexes and " << trackletMCLabels.getNElements() << " associated MC Labels"; if (mShowTrackletStats > 0) { mDigitLoopTime = std::chrono::high_resolution_clock::now() - digitloopstart; - LOG(info) << "Trap Simulator done \\o/ "; + LOG(info) << "Trap Simulator done "; #ifdef TRDTIMESORT - LOG(info) << "Sorting took " << mSortingTime.count(); + LOG(info) << "Sorting took " << mSortingTime.count() << "s"; #endif - LOG(info) << "Digit loop took : " << mDigitLoopTime.count(); - LOG(info) << "Trapsim took : " << mTrapSimAccumulatedTime.count(); - LOG(info) << "Traploop took : " << mTrapLoopTime.count(); + LOG(info) << "Digit loop took : " << mDigitLoopTime.count() << "s"; + LOG(info) << "Trapsim took : " << mTrapSimAccumulatedTime.count() << "s"; + LOG(info) << "Traploop took : " << mTrapLoopTime.count() << "s"; for (auto trapcount : mTrapUsedFrequency) { LOG(info) << "# traps fired Traploop are : " << trapcount; } for (auto trapcount : mTrapUsedCounter) { LOG(info) << "each trap position fired : " << trapcount; } + LOG(info) << "Raw data words written = " << mTotalRawWordsWritten << " with a vector size = " << rawdata.size(); + LOG(info) << "Raw data words written = " << mTotalRawWordsWritten << " with a vector size = " << rawdata.size(); } + LOG(debug) << "END OF RUN ............."; pc.outputs().snapshot(Output{"TRD", "TRACKLETS", 0, Lifetime::Timeframe}, trapTrackletsAccum); pc.outputs().snapshot(Output{"TRD", "TRKTRGRD", 0, Lifetime::Timeframe}, trackletTriggerRecords); /*pc.outputs().snapshot(Output{"TRD", "TRKLABELS", 0, Lifetime::Timeframe}, trackletMCLabels); */ // LOG(info) << "digit MCLabels is of type : " << type_id_with_cvr<decltype(digitMCLabels)>().pretty_name(); - LOG(info) << "exiting the trap sim run method "; + pc.outputs().snapshot(Output{"TRD", "RAWDATA", 0, Lifetime::Timeframe}, rawdata); + pc.outputs().snapshot(Output{"TRD", "RAWTRGRD", 0, Lifetime::Timeframe}, rawTriggerRecords); + pc.outputs().snapshot(Output{"TRD", "RAWLNKRD", 0, Lifetime::Timeframe}, mLinkRecords); + + LOG(debug) << "exiting the trap sim run method "; pc.services().get<ControlService>().endOfStream(); pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); } @@ -595,11 +657,14 @@ o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec() { return DataProcessorSpec{"TRAP", Inputs{InputSpec{"digitinput", "TRD", "DIGITS", 0}, InputSpec{"triggerrecords", "TRD", "TRGRDIG", 0}, InputSpec{"labelinput", "TRD", "LABELS", 0}}, - Outputs{OutputSpec{"TRD", "TRACKLETS", 0, Lifetime::Timeframe}, - OutputSpec{"TRD", "TRKTRGRD", 0, Lifetime::Timeframe} + Outputs{OutputSpec{"TRD", "TRACKLETS", 0, Lifetime::Timeframe}, // this is the 64 tracklet words + OutputSpec{"TRD", "TRKTRGRD", 0, Lifetime::Timeframe}, /*OutputSpec{"TRD", "TRKDIGITS", 0, Lifetime::Timeframe},*/ - /*OutputSpec{"TRD", "TRKLABELS", 0, Lifetime::Timeframe},*/ - /*OutputSpec{"TRD", "RAWDATA", 0, Lifetime::Timeframe}*/}, + OutputSpec{"TRD", "TRKLABELS", 0, Lifetime::Timeframe}, + /*OutputSpec{"TRD", "TRAPRAWDUMP", 0, Lifetime::Timeframe},*/ + OutputSpec{"TRD", "RAWTRGRD", 0, Lifetime::Timeframe}, // offsets for each event in the rawdata + OutputSpec{"TRD", "RAWLNKRD", 0, Lifetime::Timeframe}, // offsets for each link/halfchamberheader in the rawdata, halfchamberheader sitting in here. + OutputSpec{"TRD", "RAWDATA", 0, Lifetime::Timeframe}}, // this is the mcmheader,traprawtracklet, repeat in varying quantities. AlgorithmSpec{adaptFromTask<TRDDPLTrapSimulatorTask>()}, Options{ {"show-trd-trackletstats", VariantType::Int, 25000, {"Display the accumulated size and capacity at number of track intervals"}}, @@ -612,6 +677,7 @@ o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec() {"trd-onlinegaintable", VariantType::String, "Krypton_2015-02", {"Online gain table to be use, names found in CCDB, obviously trd-onlinegaincorrection must be set as well."}}, {"trd-debugrejectedtracklets", VariantType::Bool, false, {"Output all MCM where tracklets were not identified"}}, {"trd-dumptrapconfig", VariantType::Bool, false, {"Dump the trapconfig at loading"}}, + {"trd-dataformat", VariantType::Int, 1, {"Raw dataformat 1. 4x32bit words 2. 1 with triggerrecords."}}, {"trd-runnum", VariantType::Int, 297595, {"Run number to use to anchor simulation to, defaults to 297595"}}}}; }; diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorWorkFlow.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorWorkFlow.cxx index 84d0516ecaea5..7ee787c381be3 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorWorkFlow.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorWorkFlow.cxx @@ -20,6 +20,7 @@ // for TRD #include "TRDWorkflow/TRDTrapSimulatorSpec.h" #include "TRDWorkflow/TRDTrackletWriterSpec.h" +#include "TRDWorkflow/TRDTrapRawWriterSpec.h" #include "TRDWorkflow/TRDDigitReaderSpec.h" #include "DataFormatsParameters/GRPObject.h" @@ -85,5 +86,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // connect the TRD digitization o2::trd::getTRDTrapSimulatorSpec(), // connect the TRD digit writer - o2::trd::getTRDTrackletWriterSpec()}; + o2::trd::getTRDTrackletWriterSpec(), + // connect the TRD digit writer + o2::trd::getTRDTrapRawWriterSpec()}; } diff --git a/Detectors/TRD/workflow/src/TRDWorkflowLinkDef.h b/Detectors/TRD/workflow/src/TRDWorkflowLinkDef.h index 51b41d4d5fa62..e109530d22899 100644 --- a/Detectors/TRD/workflow/src/TRDWorkflowLinkDef.h +++ b/Detectors/TRD/workflow/src/TRDWorkflowLinkDef.h @@ -15,6 +15,6 @@ #pragma link off all functions; //#pragma link C++ class o2::trd::TRDDPLDigitizerTask + ; - +#pragma link C++ class gsl::span < uint32_t > +; #endif diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 5b0fb440a072e..4130e4f4a564a 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -28,6 +28,7 @@ list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Detectors/TRD/base/macros/Readocdb.C Detectors/TRD/base/macros/PrintTrapConfig.C Detectors/TRD/base/macros/ConvertRun2DigitsAndTracklets.C + Detectors/TRD/macros/ParseTrapRawOutput.C Detectors/EMCAL/calib/macros/ReadTestBadChannelMap_CCDBApi.C GPU/GPUTracking/Merger/macros/checkPropagation.C # Needs AliRoot AliExternalTrackParam GPU/GPUTracking/Merger/macros/fitPolynomialFieldIts.C # Needs AliRoot AliMagF From 3232790562a72eb263fd622be99ea43c39f8d3da Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 3 Aug 2020 22:04:37 +0200 Subject: [PATCH 0233/1751] DPL Analysis: functions to perform index building (#4076) * Minor fix: remove unused function arguments * DPL Analysis: functions to perform index building * Add missing constexpr * Fix for older gcc * missing decay_t * avoid copying iterators * simplify search algorithm * stop searches if one of the tables ended * remove redundant condition --- Framework/Core/CMakeLists.txt | 1 + Framework/Core/include/Framework/ASoA.h | 30 ++++- .../Core/include/Framework/AnalysisTask.h | 7 +- .../Core/include/Framework/TableBuilder.h | 107 ++++++++++++++++- Framework/Core/test/test_IndexBuilder.cxx | 112 ++++++++++++++++++ 5 files changed, 251 insertions(+), 6 deletions(-) create mode 100644 Framework/Core/test/test_IndexBuilder.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index d34953c8f9bf2..52b765447b2d1 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -178,6 +178,7 @@ foreach(t Graphviz GroupSlicer HistogramRegistry + IndexBuilder InfoLogger InputRecord InputRecordWalker diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 9c975eb391988..ee2cd61704ad6 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -600,7 +600,7 @@ struct RowViewCore : public IP, C... { using persistent_columns_t = framework::selected_pack<is_persistent_t, C...>; using dynamic_columns_t = framework::selected_pack<is_dynamic_t, C...>; using index_columns_t = framework::selected_pack<is_index_t, C...>; - constexpr inline static bool has_index_v = !std::is_same_v<index_columns_t, framework::pack<>>; + constexpr inline static bool has_index_v = framework::pack_size(index_columns_t{}) > 0; using external_index_columns_t = framework::selected_pack<is_external_index_t, C...>; RowViewCore(arrow::ChunkedArray* columnData[sizeof...(C)], IP&& policy) @@ -786,6 +786,14 @@ class Table template <typename IP, typename Parent, typename... T> struct RowViewBase : public RowViewCore<IP, C...> { + /// Helper function to extract bound indices + template <typename... Is> + static constexpr auto extractBindings(framework::pack<Is...>) + { + return framework::pack<typename Is::binding_t...>{}; + } + using external_index_columns_t = framework::selected_pack<is_external_index_t, C...>; + using bindings_pack_t = decltype(extractBindings(external_index_columns_t{})); using parent_t = Parent; using originals = originals_pack_t<T...>; @@ -819,6 +827,22 @@ class Table return *this; } + void matchTo(RowViewBase const& other) + { + this->mRowIndex = other.mRowIndex; + } + + template <typename TI> + auto getId() const + { + if constexpr (framework::has_type_v<std::decay_t<TI>, bindings_pack_t>) { + constexpr auto idx = framework::has_type_at<std::decay_t<TI>>(bindings_pack_t{}); + return framework::pack_element_t<idx, external_index_columns_t>::getId(); + } else { + return static_cast<int32_t>(-1); + } + } + using RowViewCore<IP, C...>::operator++; /// Allow incrementing by more than one the iterator @@ -1116,6 +1140,10 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); _Name_##Id() = default; \ _Name_##Id(_Name_##Id const& other) = default; \ _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ \ type _Getter_##Id() const \ { \ diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index a3c224b42d27b..e22899871fd6b 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -185,6 +185,7 @@ struct Spawns { { return OutputRef{metadata::tableLabel(), 0}; } + T* operator->() { return table.get(); @@ -392,17 +393,17 @@ struct Partition { template <typename ANY> struct PartitionManager { template <typename... T2s> - static void setPartition(ANY&, T2s&... tables) + static void setPartition(ANY&, T2s&...) { } template <typename... Ts> - static void bindExternalIndices(ANY&, Ts*... tables) + static void bindExternalIndices(ANY&, Ts*...) { } template <typename... Ts> - static void getBoundToExternalIndices(ANY& partition, Ts&... tables) + static void getBoundToExternalIndices(ANY&, Ts&...) { } }; diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index b705f08704e99..c6c65508e120d 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -581,14 +581,14 @@ class TableBuilder /// template argument T is a o2::soa::Table which contains only the /// persistent columns. template <typename T, size_t... Is> - auto cursorHelper(std::index_sequence<Is...> s) + auto cursorHelper(std::index_sequence<Is...>) { std::vector<std::string> columnNames{pack_element_t<Is, typename T::columns>::columnLabel()...}; return this->template persist<typename pack_element_t<Is, typename T::columns>::type...>(columnNames); } template <typename T, typename E, size_t... Is> - auto cursorHelper(std::index_sequence<Is...> s) + auto cursorHelper(std::index_sequence<Is...>) { std::vector<std::string> columnNames{pack_element_t<Is, typename T::columns>::columnLabel()...}; return this->template persist<E>(columnNames); @@ -601,6 +601,109 @@ class TableBuilder std::vector<std::shared_ptr<arrow::Array>> mArrays; }; +/// Helper to get a tuple tail +template <typename Head, typename... Tail> +std::tuple<Tail...> tuple_tail(std::tuple<Head, Tail...>& t) +{ + return apply([](auto const&, auto&... tail) { return std::tie(tail...); }, t); +} + +/// Helpers to get type pack from tuple +template <typename... T> +constexpr auto pack_from_tuple(std::tuple<T...> const&) +{ + return framework::pack<T...>{}; +} + +/// Binary search for an index column +template <typename Key, typename T> +void lowerBound(int32_t value, T& start) +{ + static_assert(soa::is_soa_iterator_t<T>::value, "Argument needs to be a Table::iterator"); + int step; + auto count = start.mMaxRow - start.globalIndex(); + + while (count > 0) { + step = count / 2; + start.moveByIndex(step); + if (start.template getId<Key>() < value) { + count -= step + 1; + } else { + start.moveByIndex(-step); + count = step; + } + } +} + +template <typename... T> +using iterator_tuple_t = std::tuple<typename T::iterator...>; + +/// Generic builder for in index table +template <typename... Cs, typename Key, typename T1, typename... T> +auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) +{ + static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); + using tables_t = framework::pack<T...>; + using first_t = T1; + auto tail = tuple_tail(tables); + TableBuilder builder; + auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); + + std::array<int32_t, sizeof...(T)> values; + iterator_tuple_t<std::decay_t<T>...> begins = std::apply( + [](auto&&... x) { + return std::make_tuple(x.begin()...); + }, + tail); + + using rest_it_t = decltype(pack_from_tuple(begins)); + + auto first = std::get<first_t>(tables); + for (auto& row : first) { + auto idx = -1; + if constexpr (std::is_same_v<std::decay_t<Key>, std::decay_t<T1>>) { + idx = row.globalIndex(); + } else { + row.template getId<Key>(); + } + auto setValue = [&](auto& x) -> bool { + using type = std::decay_t<decltype(x)>; + constexpr auto position = framework::has_type_at<type>(rest_it_t{}); + + lowerBound<Key>(idx, x); + if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { + return false; + } else if (x.template getId<Key>() != idx) { + return false; + } else { + values[position] = x.globalIndex(); + ++x; + return true; + } + }; + + if (std::apply( + [](auto&... x) { + return ((x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) && ...); + }, + begins)) { + break; + } + + auto result = std::apply( + [&](auto&... x) { + std::array<bool, sizeof...(T)> results{setValue(x)...}; + return (results[framework::has_type_at<std::decay_t<decltype(x)>>(rest_it_t{})] && ...); + }, + begins); + + if (result) { + cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); + } + } + return builder.finalize(); +} + } // namespace framework } // namespace o2 #endif // FRAMEWORK_TABLEBUILDER_H diff --git a/Framework/Core/test/test_IndexBuilder.cxx b/Framework/Core/test/test_IndexBuilder.cxx new file mode 100644 index 0000000000000..59ec528f80ee0 --- /dev/null +++ b/Framework/Core/test/test_IndexBuilder.cxx @@ -0,0 +1,112 @@ +// 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. + +#define BOOST_TEST_MODULE Test Framework IndexBuilder +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include "Framework/AnalysisDataModel.h" +#include "Framework/TableBuilder.h" +#include <boost/test/unit_test.hpp> + +using namespace o2::framework; +using namespace arrow; +using namespace o2::soa; + +DECLARE_SOA_STORE(); +namespace coords +{ +DECLARE_SOA_COLUMN_FULL(X, x, float, "x"); +DECLARE_SOA_COLUMN_FULL(Y, y, float, "y"); +DECLARE_SOA_COLUMN_FULL(Z, z, float, "z"); +} // namespace coords +DECLARE_SOA_TABLE(Points, "TST", "POINTS", Index<>, coords::X, coords::Y, coords::Z); + +namespace extra_1 +{ +DECLARE_SOA_INDEX_COLUMN(Point, point); +DECLARE_SOA_COLUMN_FULL(D, d, float, "d"); +} // namespace extra_1 +DECLARE_SOA_TABLE(Distances, "TST", "DISTANCES", Index<>, extra_1::PointId, extra_1::D); + +namespace extra_2 +{ +DECLARE_SOA_INDEX_COLUMN(Point, point); +DECLARE_SOA_COLUMN_FULL(IsTrue, istrue, bool, "istrue"); +} // namespace extra_2 +DECLARE_SOA_TABLE(Flags, "TST", "Flags", Index<>, extra_2::PointId, extra_2::IsTrue); + +namespace extra_3 +{ +DECLARE_SOA_INDEX_COLUMN(Point, point); +DECLARE_SOA_COLUMN_FULL(Category, category, int32_t, "category"); +} // namespace extra_3 +DECLARE_SOA_TABLE(Categorys, "TST", "Categories", Index<>, extra_3::PointId, extra_3::Category); + +namespace indices +{ +DECLARE_SOA_INDEX_COLUMN(Point, point); +DECLARE_SOA_INDEX_COLUMN(Distance, distance); +DECLARE_SOA_INDEX_COLUMN(Flag, flag); +DECLARE_SOA_INDEX_COLUMN(Category, category); +} // namespace indices + +DECLARE_SOA_TABLE(IDXs, "TST", "Index", Index<>, indices::PointId, indices::DistanceId, indices::FlagId, indices::CategoryId); + +BOOST_AUTO_TEST_CASE(TestIndexBuilder) +{ + TableBuilder b1; + auto w1 = b1.cursor<Points>(); + TableBuilder b2; + auto w2 = b2.cursor<Distances>(); + TableBuilder b3; + auto w3 = b3.cursor<Flags>(); + TableBuilder b4; + auto w4 = b4.cursor<Categorys>(); + + for (auto i = 0; i < 10; ++i) { + w1(0, i * 2., i * 3., i * 4.); + } + + std::array<int, 7> d = {0, 1, 2, 4, 7, 8, 9}; + std::array<int, 5> f = {0, 1, 2, 5, 8}; + std::array<int, 7> c = {0, 1, 2, 3, 5, 7, 8}; + + for (auto i : d) { + w2(0, i, i * 10.); + } + + for (auto i : f) { + w3(0, i, static_cast<bool>(i % 2)); + } + + for (auto i : c) { + w4(0, i, i + 2); + } + + auto t1 = b1.finalize(); + Points st1{t1}; + auto t2 = b2.finalize(); + Distances st2{t2}; + auto t3 = b3.finalize(); + Flags st3{t3}; + auto t4 = b4.finalize(); + Categorys st4{t4}; + + auto t5 = indexBuilder(typename IDXs::persistent_columns_t{}, st1, std::tie(st1, st2, st3, st4)); + BOOST_REQUIRE_EQUAL(t5->num_rows(), 4); + IDXs idxt{t5}; + idxt.bindExternalIndices(&st1, &st2, &st3, &st4); + for (auto& row : idxt) { + BOOST_REQUIRE(row.distance().pointId() == row.pointId()); + BOOST_REQUIRE(row.flag().pointId() == row.pointId()); + BOOST_REQUIRE(row.category().pointId() == row.pointId()); + } +} From cc8d52cc23a4196bbce67308994aaaa848e2e726 Mon Sep 17 00:00:00 2001 From: frmanso <manso@clermont.in2p3.fr> Date: Tue, 4 Aug 2020 10:27:30 +0200 Subject: [PATCH 0234/1751] MFT: Remove dummy box to solve illegal case in geometry (#4053) * Remove dummy box to solve illegal case in geometry * Creation by default of the disk PCB supports --- .../MFT/base/include/MFTBase/MFTBaseParam.h | 2 +- .../ITSMFT/MFT/base/src/HeatExchanger.cxx | 52 +++++++------------ 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/MFTBaseParam.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/MFTBaseParam.h index 16ed9d3a4d5fb..bd981afebdfcd 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/MFTBaseParam.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/MFTBaseParam.h @@ -34,7 +34,7 @@ struct MFTBaseParam : public o2::conf::ConfigurableParamHelper<MFTBaseParam> { bool buildCone = true; bool buildBarrel = true; bool buildPatchPanel = true; - bool buildPCBSupports = false; + bool buildPCBSupports = true; bool buildPCBs = true; bool buildPSU = true; diff --git a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx index 29cde9a5e04df..18e3877e16e78 100644 --- a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx @@ -237,15 +237,6 @@ void HeatExchanger::createManifold(Int_t disk) lengthTop2 = cornerRadiusTop[disk]; Double_t lengthMiddle1[5]; - /* - lengthMiddle1[0] = 6.71; - lengthMiddle1[1] = 6.71; - lengthMiddle1[2] = 6.71; - //lengthMiddle1[3] = 9.20; - //lengthMiddle1[4] = 9.20; - lengthMiddle1[3] = 6.71; - lengthMiddle1[4] = 6.71; - */ lengthMiddle1[0] = mSupportYDimensions[0][0]; lengthMiddle1[1] = mSupportYDimensions[1][0]; lengthMiddle1[2] = mSupportYDimensions[2][0]; @@ -256,8 +247,6 @@ void HeatExchanger::createManifold(Int_t disk) Double_t lengthBottom1; lengthBottom1 = lengthMiddle1[disk]; - auto* dummy = new TGeoBBox("dummy", 0, 0, 0); - auto* Top1 = new TGeoBBox(Form("Top1MF%d", disk), lengthTop1[disk] / 2, widthTop1[disk] / 2, thicknessTop[disk] / 2); auto* Top2 = new TGeoBBox(Form("Top2MF%d", disk), lengthTop2 / 2, widthTop2 / 2, thicknessTop[disk] / 2); auto* Top3 = new TGeoTube(Form("Top3MF%d", disk), 0, cornerRadiusTop[disk], thicknessTop[disk] / 2); @@ -328,8 +317,6 @@ void HeatExchanger::createManifold(Int_t disk) lengthBulge[0] = 0.395; lengthBulge[1] = 0.395; lengthBulge[2] = 0.395; - //lengthBulge[3] = 0.400; - //lengthBulge[4] = 0.400; lengthBulge[3] = 0.395; lengthBulge[4] = 0.395; @@ -478,8 +465,6 @@ void HeatExchanger::createManifold(Int_t disk) lengthStep1[0] = 5.61; lengthStep1[1] = 5.61; lengthStep1[2] = 5.61; - //lengthStep1[3] = 7.90; - //lengthStep1[4] = 7.90; lengthStep1[3] = 5.61; lengthStep1[4] = 5.61; Double_t widthStep1[5]; @@ -532,12 +517,14 @@ void HeatExchanger::createManifold(Int_t disk) TGeoRotation* rcoverBodyStep = new TGeoRotation(Form("rcoverBodyStep4MF%d", disk), 45, 0, 0); rcoverBodyStep->RegisterYourself(); - TGeoCompositeShape* coverBodyStep4rotated = new TGeoCompositeShape(Form("coverBodyStep4rotatedMF%d", disk), Form("dummy + coverBodyStep4MF%d:rcoverBodyStep4MF%d", disk, disk)); + TGeoCombiTrans* combtcoverBodyStep[4]; + combtcoverBodyStep[3] = new TGeoCombiTrans(Form("combtcoverBodyStep4MF%d", disk), -(lengthStep1[disk] - lengthStep2) / 2, -widthStep1[disk] / 2, 0., rcoverBodyStep); + combtcoverBodyStep[3]->RegisterYourself(); for (Int_t i = 0; i < 4; ++i) tcoverBodyStep[i]->RegisterYourself(); - TGeoCompositeShape* shapeStep = new TGeoCompositeShape(Form("shapeStepMF%d", disk), Form("coverBodyStep1MF%d:tcoverBodyStep1MF%d + coverBodyStep2MF%d:tcoverBodyStep2MF%d + coverBodyStep3MF%d:tcoverBodyStep3MF%d + coverBodyStep4rotatedMF%d:tcoverBodyStep4MF%d", disk, disk, disk, disk, disk, disk, disk, disk)); + TGeoCompositeShape* shapeStep = new TGeoCompositeShape(Form("shapeStepMF%d", disk), Form("coverBodyStep1MF%d:tcoverBodyStep1MF%d + coverBodyStep2MF%d:tcoverBodyStep2MF%d + coverBodyStep3MF%d:tcoverBodyStep3MF%d + coverBodyStep4MF%d:combtcoverBodyStep4MF%d", disk, disk, disk, disk, disk, disk, disk, disk)); TGeoTranslation* tcoverStep = new TGeoTranslation(Form("tcoverStepMF%d", disk), -(lengthMiddle1[disk] / 2 - (lengthStep1[disk] / 2 - lengthStep2 / 2)), (widthBody / 2 - widthStep1[disk] / 2), -(thicknessBody[disk] / 2 - thicknessStep1[disk] / 2)); @@ -572,12 +559,13 @@ void HeatExchanger::createManifold(Int_t disk) TGeoRotation* rcoverBodyBulgeSub = new TGeoRotation(Form("rcoverBodyBulgeSubMF%d", disk), 0, 90, 45); rcoverBodyBulgeSub->RegisterYourself(); - TGeoCompositeShape* coverBodyBulgeSubrotated = new TGeoCompositeShape(Form("coverBodyBulgeSubrotatedMF%d", disk), Form("dummy + coverBodyBulgeSubMF%d:rcoverBodyBulgeSubMF%d", disk, disk)); - TGeoTranslation* tcoverBodyBulgeSub = new TGeoTranslation(Form("tcoverBodyBulgeSubMF%d", disk), -lengthBulge[disk] / 2, 0, 0); tcoverBodyBulgeSub->RegisterYourself(); - TGeoCompositeShape* shapeBulge = new TGeoCompositeShape(Form("shapeBulgeMF%d", disk), Form("coverBodyBulgeMF%d - coverBodyBulgeSubrotatedMF%d:tcoverBodyBulgeSubMF%d", disk, disk, disk)); + TGeoCombiTrans* combtcoverBodyBulgeSub = new TGeoCombiTrans(Form("combtcoverBodyBulgeSubMF%d", disk), -lengthBulge[disk] / 2, 0, 0, rcoverBodyBulgeSub); + combtcoverBodyBulgeSub->RegisterYourself(); + + TGeoCompositeShape* shapeBulge = new TGeoCompositeShape(Form("shapeBulgeMF%d", disk), Form("coverBodyBulgeMF%d - coverBodyBulgeSubMF%d:combtcoverBodyBulgeSubMF%d", disk, disk, disk)); TGeoTranslation* tcoverBulge = new TGeoTranslation(Form("tcoverBulgeMF%d", disk), -(lengthMiddle1[disk] / 2 + lengthBulge[disk] / 2), -(widthBody / 2 - widthBulge[disk] / 2), 0); tcoverBulge->RegisterYourself(); @@ -604,15 +592,17 @@ void HeatExchanger::createManifold(Int_t disk) TGeoRotation* rshapeManifold2 = new TGeoRotation(Form("rshapeManifold2MF%d", disk), 0, 180, 0); rshapeManifold2->RegisterYourself(); - TGeoCompositeShape* shapeManifold2rotated = new TGeoCompositeShape(Form("shapeManifold2rotatedMF%d", disk), Form("dummy + shapeManifold2MF%d:rshapeManifold2MF%d", disk, disk)); - TGeoTranslation* tshapeManifold1 = new TGeoTranslation(Form("tshapeManifold1MF%d", disk), 0, 0, -((thicknessBody[disk] + thicknessMiddle[disk] + thicknessBottom[disk]) / 2 - (thicknessTop[disk] + thicknessMiddle[disk] + thicknessBottom[disk]) / 2)); tshapeManifold1->RegisterYourself(); + TGeoTranslation* tshapeManifold2 = new TGeoTranslation(Form("tshapeManifold2MF%d", disk), 0, 0, (thicknessBody[disk] + thicknessMiddle[disk] + thicknessBottom[disk]) / 2 - thicknessBody[disk] / 2); tshapeManifold2->RegisterYourself(); - TGeoCompositeShape* shapeManifold = new TGeoCompositeShape("shapeManifold", Form("shapeManifold1MF%d:tshapeManifold1MF%d + shapeManifold2rotatedMF%d:tshapeManifold2MF%d", disk, disk, disk, disk)); + TGeoCombiTrans* combtshapeManifold2 = new TGeoCombiTrans(Form("combtshapeManifold2MF%d", disk), 0, 0, (thicknessBody[disk] + thicknessMiddle[disk] + thicknessBottom[disk]) / 2 - thicknessBody[disk] / 2, rshapeManifold2); + combtshapeManifold2->RegisterYourself(); + + TGeoCompositeShape* shapeManifold = new TGeoCompositeShape("shapeManifold", Form("shapeManifold1MF%d:tshapeManifold1MF%d + shapeManifold2MF%d:combtshapeManifold2MF%d", disk, disk, disk, disk)); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Manifold3 @@ -660,8 +650,6 @@ void HeatExchanger::createManifold(Int_t disk) TGeoTranslation* tPlug5sub = new TGeoTranslation(Form("tPlug5subMF%d", disk), 0, outerRadiusPlug5 * TMath::Cos(anglesubPlug5) + outerRadiusPlug5 * (1 - TMath::Cos(anglesubPlug5)) / 2, 0.); tPlug5sub->RegisterYourself(); - TGeoCompositeShape* disPlug5sub = new TGeoCompositeShape(Form("disPlug5subMF%d", disk), Form("dummy + plug5subMF%d:tPlug5subMF%d", disk, disk)); - TGeoRotation* rPlug5sub[nSidePlug5]; TString namePlug5 = Form("plug5mainMF%d", disk); @@ -669,7 +657,9 @@ void HeatExchanger::createManifold(Int_t disk) for (Int_t index = 0; index < nSidePlug5; ++index) { rPlug5sub[index] = new TGeoRotation(Form("rPlug5sub%dMF%d", index, disk), index * 60, 0, 0); rPlug5sub[index]->RegisterYourself(); - namePlug5 += Form(" - disPlug5subMF%d:rPlug5sub%dMF%d", disk, index, disk); + TGeoCombiTrans* combtPlug5sub = new TGeoCombiTrans(Form("combtPlug5subMF%d", disk), 0, outerRadiusPlug5 * TMath::Cos(anglesubPlug5) + outerRadiusPlug5 * (1 - TMath::Cos(anglesubPlug5)) / 2, 0., rPlug5sub[index]); + combtPlug5sub->RegisterYourself(); + namePlug5 += Form(" - plug5subMF%d:combtPlug5subMF%d", disk, disk); } TGeoCompositeShape* plug5 = new TGeoCompositeShape(Form("plug5MF%d", disk), namePlug5); @@ -730,8 +720,6 @@ void HeatExchanger::createManifold(Int_t disk) TGeoTranslation* tPlug12sub = new TGeoTranslation(Form("tPlug12subMF%d", disk), 0, outerRadiusPlug12 * TMath::Cos(anglesubPlug12) + outerRadiusPlug12 * (1 - TMath::Cos(anglesubPlug12)) / 2, 0.); tPlug12sub->RegisterYourself(); - TGeoCompositeShape* disPlug12sub = new TGeoCompositeShape(Form("disPlug12subMF%d", disk), Form("dummy + plug12subMF%d:tPlug12subMF%d", disk, disk)); - TGeoRotation* rPlug12sub[nSidePlug12]; TString namePlug12 = Form("plug12mainMF%d", disk); @@ -739,7 +727,9 @@ void HeatExchanger::createManifold(Int_t disk) for (Int_t index = 0; index < nSidePlug12; ++index) { rPlug12sub[index] = new TGeoRotation(Form("rPlug12sub%dMF%d", index, disk), index * 60, 0, 0); rPlug12sub[index]->RegisterYourself(); - namePlug12 += Form(" - disPlug12subMF%d:rPlug12sub%dMF%d", disk, index, disk); + TGeoCombiTrans* combtPlug12sub = new TGeoCombiTrans(Form("combtPlug12subMF%d", disk), 0, outerRadiusPlug12 * TMath::Cos(anglesubPlug12) + outerRadiusPlug12 * (1 - TMath::Cos(anglesubPlug12)) / 2, 0., rPlug12sub[index]); + combtPlug12sub->RegisterYourself(); + namePlug12 += Form(" - plug12subMF%d:combtPlug12subMF%d", disk, disk); } TGeoCompositeShape* plug12 = new TGeoCompositeShape(Form("plug12MF%d", disk), namePlug12); @@ -848,7 +838,6 @@ void HeatExchanger::createManifold(Int_t disk) mHalfDisk->AddNode(MFplug01, 1, transformationplug1); transformationwater1 = - //new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + mfZ / 2 + fShift + (thicknessTotMF/2 - watherThickness[disk]/2) - (thicknessBody[disk] - thicknessTop[disk] - watherThickness[disk]),mfY / 2 + deltay, mZPlan[disk], rotation1); new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + 0.1 + thicknessTotMF / 2 + (thicknessTotMF / 2 - watherThickness[disk] / 2) - (thicknessBody[disk] - thicknessTop[disk] - watherThickness[disk]), mHalfDiskGap + mSupportYDimensions[disk][0] / 2, mZPlan[disk], rotation1); mHalfDisk->AddNode(MFwater01, 1, transformationwater1); @@ -859,20 +848,17 @@ void HeatExchanger::createManifold(Int_t disk) TGeoRotation* rotation2 = new TGeoRotation(Form("rotation2MF%d", disk), 90, 90., 0.); transformation2 = - //new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + mfZ / 2 + fShift, -mfY / 2 - deltay, mZPlan[disk], rotation2); new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + 0.1 + thicknessTotMF / 2, -mHalfDiskGap - mSupportYDimensions[disk][0] / 2, mZPlan[disk], rotation2); mHalfDisk->AddNode(MF02, 1, transformation2); TGeoRotation* rotationplug2 = new TGeoRotation(Form("rotationplug1MF%d", disk), -90, 90., 90.); transformationplug2 = - //new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + mfZ / 2 + fShift + thicknessTotMF/2 + refposPlug - (thicknessPlug8 + thicknessPlug9 + thicknessPlug10 + thicknessPlug11),-mfY / 2 - deltay + ((lengthBody)/2 - holeOffset[3]), mZPlan[disk], rotationplug2); new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + 0.1 + thicknessTotMF / 2 + thicknessTotMF / 2 + refposPlug - (thicknessPlug8 + thicknessPlug9 + thicknessPlug10 + thicknessPlug11), -mHalfDiskGap - mSupportYDimensions[disk][0] / 2 + ((lengthBody) / 2 - holeOffset[3]), mZPlan[disk], rotationplug2); mHalfDisk->AddNode(MFplug02, 1, transformationplug2); transformationwater2 = - //new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + mfZ / 2 + fShift + ((thicknessTotMF/2 - watherThickness[disk]/2) - (thicknessBody[disk] - thicknessTop[disk] - watherThickness[disk])),-mfY / 2 - deltay, mZPlan[disk], rotation2); new TGeoCombiTrans(mSupportXDimensions[disk][0] / 2 + 0.1 + thicknessTotMF / 2 + ((thicknessTotMF / 2 - watherThickness[disk] / 2) - (thicknessBody[disk] - thicknessTop[disk] - watherThickness[disk])), -mHalfDiskGap - mSupportYDimensions[disk][0] / 2, mZPlan[disk], rotation2); mHalfDisk->AddNode(MFwater02, 1, transformationwater2); From abc408d15cd596e9af571d268d2047d1af0322f7 Mon Sep 17 00:00:00 2001 From: Piotr Konopka <piotr.jan.konopka@cern.ch> Date: Mon, 3 Aug 2020 14:41:47 +0200 Subject: [PATCH 0235/1751] [QC-378] Data Sampling: Support multiple parts in Dispatcher --- Framework/Core/src/Dispatcher.cxx | 50 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Framework/Core/src/Dispatcher.cxx b/Framework/Core/src/Dispatcher.cxx index e364a0fa73412..2f1246ab7a621 100644 --- a/Framework/Core/src/Dispatcher.cxx +++ b/Framework/Core/src/Dispatcher.cxx @@ -21,6 +21,7 @@ #include "Framework/DataSpecUtils.h" #include "Framework/Logger.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/InputRecordWalker.h" #include <Monitoring/Monitoring.h> #include <Configuration/ConfigurationInterface.h> @@ -76,31 +77,30 @@ void Dispatcher::init(InitContext& ctx) void Dispatcher::run(ProcessingContext& ctx) { - for (const auto& input : ctx.inputs()) { - if (input.header != nullptr && input.spec != nullptr) { - const auto* inputHeader = header::get<header::DataHeader*>(input.header); - ConcreteDataMatcher inputMatcher{inputHeader->dataOrigin, inputHeader->dataDescription, inputHeader->subSpecification}; - - for (auto& policy : mPolicies) { - // todo: consider getting the outputSpec in match to improve performance - // todo: consider matching (and deciding) in completion policy to save some time - - if (policy->match(inputMatcher) && policy->decide(input)) { - // We copy every header which is not DataHeader or DataProcessingHeader, - // so that custom data-dependent headers are passed forward, - // and we add a DataSamplingHeader. - header::Stack headerStack{ - std::move(extractAdditionalHeaders(input.header)), - std::move(prepareDataSamplingHeader(*policy.get(), ctx.services().get<const DeviceSpec>()))}; - - if (!policy->getFairMQOutputChannel().empty()) { - sendFairMQ(ctx.services().get<RawDeviceService>().device(), input, policy->getFairMQOutputChannelName(), - std::move(headerStack)); - } else { - Output output = policy->prepareOutput(inputMatcher, input.spec->lifetime); - output.metaHeader = std::move(header::Stack{std::move(output.metaHeader), std::move(headerStack)}); - send(ctx.outputs(), input, std::move(output)); - } + for (const auto& input : InputRecordWalker(ctx.inputs())) { + + const auto* inputHeader = header::get<header::DataHeader*>(input.header); + ConcreteDataMatcher inputMatcher{inputHeader->dataOrigin, inputHeader->dataDescription, inputHeader->subSpecification}; + + for (auto& policy : mPolicies) { + // todo: consider getting the outputSpec in match to improve performance + // todo: consider matching (and deciding) in completion policy to save some time + + if (policy->match(inputMatcher) && policy->decide(input)) { + // We copy every header which is not DataHeader or DataProcessingHeader, + // so that custom data-dependent headers are passed forward, + // and we add a DataSamplingHeader. + header::Stack headerStack{ + std::move(extractAdditionalHeaders(input.header)), + std::move(prepareDataSamplingHeader(*policy.get(), ctx.services().get<const DeviceSpec>()))}; + + if (!policy->getFairMQOutputChannel().empty()) { + sendFairMQ(ctx.services().get<RawDeviceService>().device(), input, policy->getFairMQOutputChannelName(), + std::move(headerStack)); + } else { + Output output = policy->prepareOutput(inputMatcher, input.spec->lifetime); + output.metaHeader = std::move(header::Stack{std::move(output.metaHeader), std::move(headerStack)}); + send(ctx.outputs(), input, std::move(output)); } } } From 6c5936bee8835af9822d339f621245cc66761218 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 17 Apr 2020 11:34:36 +0200 Subject: [PATCH 0236/1751] Use non-owning pointer for objects, fix alias --- .../include/TPCCalibration/CalibTreeDump.h | 15 +++++++++------ .../TPC/calibration/src/CalibTreeDump.cxx | 19 ++++++++++++++++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibTreeDump.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibTreeDump.h index b8dbfdf362369..6bb611bf40ebb 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibTreeDump.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibTreeDump.h @@ -53,28 +53,31 @@ class CalibTreeDump /// Add CalDet object template <typename T> - void add(const CalDet<T>& calDet) + void add(CalDet<T>* calDet) { - mCalDetObjects.push_back(calDet); + mCalDetObjects.emplace_back(calDet); } //void add(const CalDet<DataTypes>& calDet) { mCalDetObjects.push_back(calDet); } /// Add CalArray objects template <typename T> - void add(const CalArray<T>& calArray) + void add(CalArray<T>* calArray) { - mCalArrayObjects.push_back(calArray); + mCalArrayObjects.emplace_back(calArray); } /// Set adding of FEE mapping to the tree void setAddFEEInfo(bool add = true) { mAddFEEInfo = add; } + /// Add CalPad objects from a file + void addCalPads(const std::string_view file, const std::string_view calPadNames); + /// Dump the registered calibration data to file void dumpToFile(const std::string filename = "CalibTree.root"); private: - std::vector<DataTypes> mCalDetObjects{}; ///< array of CalDet objects - std::vector<DataTypes> mCalArrayObjects{}; ///< array of CalArray objects + std::vector<DataTypes*> mCalDetObjects{}; ///< array of CalDet objects + std::vector<DataTypes*> mCalArrayObjects{}; ///< array of CalArray objects bool mAddFEEInfo{false}; ///< add front end electronics mappings std::vector<float> mTraceLengthIROC; ///< trace lengths IROC std::vector<float> mTraceLengthOROC; ///< trace lengths OROC diff --git a/Detectors/TPC/calibration/src/CalibTreeDump.cxx b/Detectors/TPC/calibration/src/CalibTreeDump.cxx index b9154baf7bbdd..60cd738ca7a3e 100644 --- a/Detectors/TPC/calibration/src/CalibTreeDump.cxx +++ b/Detectors/TPC/calibration/src/CalibTreeDump.cxx @@ -25,6 +25,7 @@ #include "TPCBase/CalDet.h" #include "TPCBase/CRU.h" #include "TPCBase/Mapper.h" +#include "TPCBase/Utils.h" #include "TPCBase/Sector.h" #include "TPCCalibration/CalibTreeDump.h" @@ -33,6 +34,14 @@ using o2::math_utils::math_base::median; using namespace o2::tpc; +void CalibTreeDump::addCalPads(const std::string_view file, const std::string_view calPadNames) +{ + auto calPads = utils::readCalPads(file, calPadNames); + for (auto calPad : calPads) { + add(calPad); + } +} + //______________________________________________________________________________ void CalibTreeDump::dumpToFile(const std::string filename) { @@ -195,8 +204,12 @@ void CalibTreeDump::addCalDetObjects(TTree* tree) { int iter = 0; - for (auto& calDet : mCalDetObjects) { + for (auto pcalDet : mCalDetObjects) { // ===| branch names |=== + if (!pcalDet) { + continue; + } + auto& calDet = *pcalDet; std::string name = calDet.getName(); if (name == "PadCalibrationObject" || name.size() == 0) { @@ -318,8 +331,8 @@ void CalibTreeDump::setDefaultAliases(TTree* tree) tree->SetAlias("OROC2", "partition == 3"); tree->SetAlias("OROC3", "partition == 4"); - tree->SetAlias("A_Side", "sector < 36"); - tree->SetAlias("C_Side", "sector >= 36"); + tree->SetAlias("A_Side", "sector < 18"); + tree->SetAlias("C_Side", "sector >= 18"); if (mAddFEEInfo) { tree->SetAlias("fecID", "fecInSector + sector * 91"); From 8d0b992346003af5e246f607f90eab75f8a995a1 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 17 Apr 2020 11:35:07 +0200 Subject: [PATCH 0237/1751] better visualization --- Detectors/TPC/base/src/Painter.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/base/src/Painter.cxx b/Detectors/TPC/base/src/Painter.cxx index ede2f413556d3..7a4d2ed8e42a3 100644 --- a/Detectors/TPC/base/src/Painter.cxx +++ b/Detectors/TPC/base/src/Painter.cxx @@ -172,7 +172,7 @@ TH2* painter::getHistogram2D(const CalArray<T>& calArray) const PadSubset padSubset = calArray.getPadSubset(); // ===| maximum number of rows and pads |===================================== const int nrows = mapper.getNumberOfPadRows(padSubset, position); - const int npads = mapper.getNumberOfPadsInRow(padSubset, position, nrows - 1); + const int npads = mapper.getNumberOfPadsInRow(padSubset, position, nrows - 1) + 6; // ===| create histogram |==================================================== const auto title = calArray.getName().c_str(); From 1349db14097470e238e23766a5829c464a657109 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 17 Apr 2020 11:36:11 +0200 Subject: [PATCH 0238/1751] extend mapping functions --- Detectors/TPC/base/include/TPCBase/FECInfo.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Detectors/TPC/base/include/TPCBase/FECInfo.h b/Detectors/TPC/base/include/TPCBase/FECInfo.h index b975a49d72c72..72af837b31ca1 100644 --- a/Detectors/TPC/base/include/TPCBase/FECInfo.h +++ b/Detectors/TPC/base/include/TPCBase/FECInfo.h @@ -21,6 +21,11 @@ namespace tpc class FECInfo { public: + static constexpr int ChannelsPerSAMPA = 32; + static constexpr int SAMPAsPerFEC = 5; + static constexpr int ChannelsPerFEC = ChannelsPerSAMPA * SAMPAsPerFEC; + static constexpr int FECsPerSector = 91; + FECInfo() = default; FECInfo(unsigned char index, //unsigned char connector, @@ -33,7 +38,7 @@ class FECInfo unsigned char getIndex() const { return mIndex; } //const unsigned char getConnector() const { return mConnector; } // -> can be calculated from mSampaChannel and mSampaChip - //const unsigned char getChannel() const { return mChannel; } // -> can be calculated from mSampaChannel and mSampaChip + unsigned char getFECChannel() const { return mSampaChip * ChannelsPerSAMPA + mSampaChannel; } // -> can be calculated from mSampaChannel and mSampaChip unsigned char getSampaChip() const { return mSampaChip; } unsigned char getSampaChannel() const { return mSampaChannel; } @@ -58,6 +63,12 @@ class FECInfo static constexpr int sampaOnFEC(const int globalSAMPAId) { return (globalSAMPAId >> 5) & 7; } static constexpr int channelOnSAMPA(const int globalSAMPAId) { return globalSAMPAId & 31; } + /// calculate the sampa number from the channel number on the FEC (0-159) + static constexpr int sampaFromFECChannel(const int fecChannel) { return fecChannel / ChannelsPerSAMPA; } + + /// calculate the sampa channel number from the channel number on the FEC (0-159) + static constexpr int channelFromFECChannel(const int fecChannel) { return fecChannel % ChannelsPerSAMPA; } + static void sampaInfo(const int globalSAMPAId, int& fecInSector, int& sampaOnFEC, int& channelOnSAMPA) { fecInSector = (globalSAMPAId >> 8); From 0ae99bb94faaaa526245457dbd0124d40ac3b8d8 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 17 Apr 2020 11:37:33 +0200 Subject: [PATCH 0239/1751] add function to easily read several CalPad objectes from file --- Detectors/TPC/base/include/TPCBase/Utils.h | 11 ++++---- Detectors/TPC/base/src/Utils.cxx | 32 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/Utils.h b/Detectors/TPC/base/include/TPCBase/Utils.h index d3ff0d5e1e1fd..6da9672bf1de5 100644 --- a/Detectors/TPC/base/include/TPCBase/Utils.h +++ b/Detectors/TPC/base/include/TPCBase/Utils.h @@ -19,6 +19,8 @@ #include <vector> #include <string_view> +#include "TPCBase/CalDet.h" + class TObjArray; class TCanvas; class TH1; @@ -28,12 +30,6 @@ namespace o2 namespace tpc { -template <class T> -class CalDet; - -template <class T> -class CalArray; - /// \namespace utils /// \brief Common utility functions /// @@ -49,7 +45,10 @@ const std::vector<std::string> tokenize(const std::string_view input, const std: TH1* getBinInfoXY(int& binx, int& biny, float& bincx, float& bincy); void addFECInfo(); void saveCanvases(TObjArray& arr, std::string_view outDir, std::string_view types = "png,pdf", std::string_view rootFileName = ""); +void saveCanvases(std::vector<TCanvas*> canvases, std::string_view outDir, std::string_view types = "png,pdf", std::string_view rootFileName = ""); void saveCanvas(TCanvas& c, std::string_view outDir, std::string_view types); +std::vector<CalPad*> readCalPads(const std::string_view fileName, const std::vector<std::string>& calPadNames); +std::vector<CalPad*> readCalPads(const std::string_view fileName, const std::string_view calPadNames); } // namespace utils } // namespace tpc diff --git a/Detectors/TPC/base/src/Utils.cxx b/Detectors/TPC/base/src/Utils.cxx index 4a2401c3eace2..90fd39311fdf2 100644 --- a/Detectors/TPC/base/src/Utils.cxx +++ b/Detectors/TPC/base/src/Utils.cxx @@ -122,6 +122,16 @@ void utils::saveCanvases(TObjArray& arr, std::string_view outDir, std::string_vi } } +void utils::saveCanvases(std::vector<TCanvas*> canvases, std::string_view outDir, std::string_view types, std::string_view rootFileName) +{ + TObjArray arr; + for (auto c : canvases) { + arr.Add(c); + } + + saveCanvases(arr, outDir, types, rootFileName); +} + void utils::saveCanvas(TCanvas& c, std::string_view outDir, std::string_view types) { const auto typesVec = tokenize(types, ","); @@ -129,3 +139,25 @@ void utils::saveCanvas(TCanvas& c, std::string_view outDir, std::string_view typ c.SaveAs(fmt::format("{}/{}.{}", outDir, c.GetName(), type).data()); } } + +std::vector<CalPad*> utils::readCalPads(const std::string_view fileName, const std::vector<std::string>& calPadNames) +{ + std::vector<CalPad*> calPads(calPadNames.size()); + + std::unique_ptr<TFile> file(TFile::Open(fileName.data())); + if (!file || !file->IsOpen() || file->IsZombie()) { + return calPads; + } + + for (size_t iCalPad = 0; iCalPad < calPadNames.size(); ++iCalPad) { + file->GetObject(calPadNames[iCalPad].data(), calPads[iCalPad]); + } + + return calPads; +} + +std::vector<CalPad*> utils::readCalPads(const std::string_view fileName, const std::string_view calPadNames) +{ + auto calPadNamesVec = tokenize(calPadNames, ","); + return readCalPads(fileName, calPadNamesVec); +} From 4ca0ad06daa66c646884664996f8172a333c23e2 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Mon, 4 May 2020 20:44:34 +0200 Subject: [PATCH 0240/1751] WIP: Add support for Link-based ZS --- .../include/TPCReconstruction/RawReaderCRU.h | 28 +++++++++++++------ .../TPC/reconstruction/src/RawReaderCRU.cxx | 11 +++++++- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h index 7ee3436a35816..497c347ea34b9 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h @@ -58,16 +58,21 @@ enum DebugLevel : uint8_t { /// data type enum class DataType : uint8_t { - TryToDetect = 0, ///< try to auto detect the mode - Continuous = 1, ///< continuous data taking - HBScaling = 2, ///< heart beat sclaing mode - Triggered = 3 ///< triggered data + Continuous = 1, ///< continuous data taking + HBScaling = 2, ///< heart beat sclaing mode + Triggered = 3, ///< triggered data }; /// file type enum class ReaderType : uint8_t { - FLPData = 0, ///< single files from FLP as 8k pages with RAWDataHeader - EPNData = 1 ///< STF builder data merged on EPN + FLP = 0, ///< single files from FLP as 8k pages with RAWDataHeader + EPN = 1, ///< STF builder data merged on EPN +}; + +/// data type +enum class RAWDataType : uint8_t { + GBT = 0, ///< GBT encoded raw data + LinkZS = 1, ///< Link based zero suppression }; using RDH = o2::header::RAWDataHeader; @@ -919,7 +924,12 @@ class RawReaderCRUManager void setDebugLevel(uint32_t debugLevel) { mDebugLevel = debugLevel; } /// set data type - void setDataType(DataType dataType) { mDataType = dataType; } + void setDataType(DataType dataType, RAWDataType rawType) + { + mDataType = dataType; + mRawDataType = rawType; + mDetectDataType = false; + } /// get data type DataType getDataType() const { return mDataType; } @@ -937,7 +947,9 @@ class RawReaderCRUManager std::vector<std::unique_ptr<RawReaderCRU>> mRawReadersCRU{}; ///< cru type raw readers RawReaderCRUEventSync mEventSync{}; ///< event synchronisation uint32_t mDebugLevel{0}; ///< debug level - DataType mDataType{DataType::TryToDetect}; ///< data type + DataType mDataType{DataType::Continuous}; ///< data type + RAWDataType mRawDataType{RAWDataType::GBT}; ///< raw data type + bool mDetectDataType{true}; ///< try to detect data types bool mIsInitialized{false}; ///< if init was called already ADCDataCallback mADCDataCallback{nullptr}; ///< callback function for filling the ADC data diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index e08eb1b868414..27473511b6631 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -227,10 +227,18 @@ int RawReaderCRU::scanFile() // triggerType == 0x10 in the firt packet // if (mManager) { - if (mManager->mDataType == DataType::TryToDetect) { + if (mManager->mDetectDataType) { const uint64_t triggerTypeForTriggeredData = 0x10; const uint64_t triggerType = RDHUtils::getTriggerType(rdh); const uint64_t pageCnt = RDHUtils::getPageCounter(rdh); + const uint64_t linkID = RDHUtils::getLinkID(rdh); + + if (pageCnt == 0) { + if (linkID == 15) { + mManager->mRawDataType = RAWDataType::LinkZS; + mManager->mDetectDataType = false; + } + } if (pageCnt == 1) { if (triggerType == triggerTypeForTriggeredData) { @@ -240,6 +248,7 @@ int RawReaderCRU::scanFile() mManager->mDataType = DataType::HBScaling; O2INFO("Detected HB scaling"); } + mManager->mDetectDataType = false; } } } From 51a62b08723d864babf653cec8b451e70d59dd8b Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 15 May 2020 14:54:29 +0200 Subject: [PATCH 0241/1751] fix format definition, fix data offset, better getters --- .../DataFormatsTPC/ZeroSuppressionLinkBased.h | 64 ++++++++++++++----- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppressionLinkBased.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppressionLinkBased.h index c6275f0a4da49..0f14e9a6b74af 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppressionLinkBased.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppressionLinkBased.h @@ -29,6 +29,8 @@ static constexpr uint32_t DataWordSizeBytes = DataWordSizeBits / 8; ///< size of /// header definition of the zero suppressed link based data format struct Header { + static constexpr uint32_t MagicWord = 0xFC000000; + union { uint64_t word0 = 0; ///< lower 64 bits struct { /// @@ -41,15 +43,17 @@ struct Header { struct { /// uint64_t bitMaskHigh : 16; ///< higher bits of the 80 bit bitmask uint32_t bunchCrossing : 12; ///< bunch crossing number - uint32_t numWordsPayload : 8; ///< number of 128bit words with 12bit ADC values - uint64_t zero : 28; ///< not used + uint32_t numWordsPayload : 4; ///< number of 128bit words with 12bit ADC values + uint32_t magicWord : 32; ///< not used }; }; - std::bitset<80> getChannelBits() + std::bitset<80> getChannelBits() const { return std::bitset<80>((std::bitset<80>(bitMaskHigh) << 64) | std::bitset<80>(bitMaskLow)); } + + bool hasCorrectMagicWord() const { return magicWord == MagicWord; } }; /// empty header for @@ -66,11 +70,12 @@ struct Header { /// 2 x ((6 x 10 bit) + 4 bit padding) template <uint32_t DataBitSizeT = 12, uint32_t SignificantBitsT = 2> struct Data { - static constexpr uint32_t ChannelsPerHalfWord = DataWordSizeBits / DataBitSizeT / 2; ///< number of ADC values in one 128b word - static constexpr uint32_t DataBitSize = DataBitSizeT; ///< number of bits of the data representation - static constexpr uint32_t SignificantBits = SignificantBitsT; ///< number of bits used for floating point precision - static constexpr uint64_t BitMask = ((uint64_t(1) << DataBitSize) - 1); ///< mask for bits - static constexpr float FloatConversion = 1.f / float(1 << SignificantBits); ///< conversion factor from integer representation to float + static constexpr uint32_t ChannelsPerWord = DataWordSizeBits / DataBitSizeT; ///< number of ADC values in one 128b word + static constexpr uint32_t ChannelsPerHalfWord = ChannelsPerWord / 2; ///< number of ADC values in one 64b word + static constexpr uint32_t DataBitSize = DataBitSizeT; ///< number of bits of the data representation + static constexpr uint32_t SignificantBits = SignificantBitsT; ///< number of bits used for floating point precision + static constexpr uint64_t BitMask = ((uint64_t(1) << DataBitSize) - 1); ///< mask for bits + static constexpr float FloatConversion = 1.f / float(1 << SignificantBits); ///< conversion factor from integer representation to float uint64_t adcValues[2]{}; ///< 128bit ADC values (max. 10x12bit) @@ -94,7 +99,7 @@ struct Data { } /// get ADC value of channel at position 'pos' (0-9) - uint32_t getADCValue(uint32_t pos) + uint32_t getADCValue(uint32_t pos) const { const uint32_t word = pos / ChannelsPerHalfWord; const uint32_t posInWord = pos % ChannelsPerHalfWord; @@ -103,7 +108,7 @@ struct Data { } /// get ADC value in float - float getADCValueFloat(uint32_t pos) + float getADCValueFloat(uint32_t pos) const { return float(getADCValue(pos)) * FloatConversion; } @@ -124,14 +129,34 @@ struct ContainerT<DataBitSizeT, SignificantBitsT, true> { Header header; ///< header data Data<DataBitSizeT, SignificantBitsT> data[0]; ///< 128 bit words with 12bit ADC values - uint32_t dataWords() { return header.numWordsPayload + 1; } + /// bunch crossing number + uint32_t getBunchCrossing() const { return header.bunchCrossing; } + + /// number of data words without the header + uint32_t getDataWords() const { return header.numWordsPayload; } + + /// number of data words including the header + uint32_t getTotalWords() const { return header.numWordsPayload + 1; } + + /// channel bitmask + std::bitset<80> getChannelBits() const { return header.getChannelBits(); } }; template <uint32_t DataBitSizeT, uint32_t SignificantBitsT> struct ContainerT<DataBitSizeT, SignificantBitsT, false> { Data<DataBitSizeT, SignificantBitsT> data[0]; ///< 128 bit words with 12bit ADC values - uint32_t dataWords() { return 7; } + /// bunch crossing number + uint32_t getBunchCrossing() const { return 0; } + + /// number of data words without the header + uint32_t getDataWords() const { return 7; } + + /// number of data words including the header, which is not present in case of 10bit decoded data format + uint32_t getTotalWords() const { return 7; } + + /// channel bitmask + std::bitset<80> getChannelBits() const { return std::bitset<80>().set(); } }; /// Container for decoded data, either zero suppressed or pure raw data @@ -158,16 +183,25 @@ struct Container { /// reset all ADC values void reset() { - for (int i = 0; i < cont.dataWords(); ++i) { + for (int i = 0; i < cont.getDataWords(); ++i) { cont.data[i].reset(); } } + uint32_t getBunchCrossing() const { return cont.getBunchCrossing(); } + uint32_t getDataWords() const { return cont.getDataWords(); } + uint32_t getTotalWords() const { return cont.getTotalWords(); } + std::bitset<80> getChannelBits() const { return cont.getChannelBits(); } + + /// total size in bytes + size_t getTotalSizeBytes() const { return getTotalWords() * DataWordSizeBytes; } + /// get position of next container. Validity check to be done outside! - Container* next() + Container* next() const { - return (Container*)(this + cont.dataWords() * DataWordSizeBytes); + return (Container*)((const char*)this + getTotalWords() * DataWordSizeBytes); } + }; // namespace zerosupp_link_based using ContainerZS = Container<>; From c44194509ba123de8ecb834b45f8c5dd5371f38b Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 15 May 2020 14:56:24 +0200 Subject: [PATCH 0242/1751] add mapping of raw FEC channel to SAMPA and channel on SAMPA * required for link-based zero suppression * the raw data channel (0-79) on a half-FEC needs proper mapping from the cru and channel number to SAMPA chip and channel on SAMPA to extract row and pad --- Detectors/TPC/base/include/TPCBase/Mapper.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Detectors/TPC/base/include/TPCBase/Mapper.h b/Detectors/TPC/base/include/TPCBase/Mapper.h index a51b041d7f1db..f7905e0d32982 100644 --- a/Detectors/TPC/base/include/TPCBase/Mapper.h +++ b/Detectors/TPC/base/include/TPCBase/Mapper.h @@ -254,6 +254,21 @@ class Mapper return pos; } + /// sampa on FEC and channel on SAMPA from the cru and the raw FEC channel (0-79) in the half FEC + /// this is required for the link-based zero suppression + static constexpr void getSampaAndChannelOnFEC(const int cruID, const size_t rawFECChannel, int& sampaOnFEC, int& channelOnSAMPA) + { + constexpr int sampaMapping[10] = {0, 0, 1, 1, 2, 3, 3, 4, 4, 2}; + constexpr int channelOffset[10] = {0, 16, 0, 16, 0, 0, 16, 0, 16, 16}; + + const int regionIter = cruID % 2; + const int istreamm = ((rawFECChannel % 10) / 2); + const int partitionStream = istreamm + regionIter * 5; + sampaOnFEC = sampaMapping[partitionStream]; + const int channel = (rawFECChannel % 2) + 2 * (rawFECChannel / 10); + channelOnSAMPA = channel + channelOffset[partitionStream]; + } + const PadCentre& padCentre(const int partition, const int fecInPartition, const int sampaOnFEC, const int channelOnSAMPA) const { From 5df79e8a5f17bdc66f8918e5c761478ed407d716 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 15 May 2020 16:23:05 +0200 Subject: [PATCH 0243/1751] move function to public for external usage --- .../include/TPCCalibration/DigitDump.h | 18 ++++++++++++------ Detectors/TPC/calibration/src/DigitDump.cxx | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/DigitDump.h b/Detectors/TPC/calibration/include/TPCCalibration/DigitDump.h index a2a22b2c84d13..284e0f50c9119 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/DigitDump.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/DigitDump.h @@ -125,6 +125,18 @@ class DigitDump : public CalibRawBase /// return digits for specific sector std::vector<Digit>& getDigits(int sector) { return mDigits[sector]; } + /// directly add a digit + void addDigit(const CRU& cru, const float signal, const int rowInSector, const int padInRow, const int timeBin) + { + mDigits[cru.sector()].emplace_back(cru, signal, rowInSector, padInRow, timeBin); + } + + /// initialize + void initInputOutput(); + + /// End event function + void endEvent() final; + private: std::unique_ptr<CalPad> mPedestal{}; ///< CalDet object with pedestal information std::unique_ptr<CalPad> mNoise{}; ///< CalDet object with noise @@ -152,12 +164,6 @@ class DigitDump : public CalibRawBase /// load noise and pedestal void loadNoiseAndPedestal(); - /// initialize - void initInputOutput(); - - /// End event function - void endEvent() final; - /// dummy reset void resetEvent() final {} }; diff --git a/Detectors/TPC/calibration/src/DigitDump.cxx b/Detectors/TPC/calibration/src/DigitDump.cxx index 85dd0a1f239c5..1797f6352f2f8 100644 --- a/Detectors/TPC/calibration/src/DigitDump.cxx +++ b/Detectors/TPC/calibration/src/DigitDump.cxx @@ -89,7 +89,7 @@ Int_t DigitDump::updateCRU(const CRU& cru, const Int_t row, const Int_t pad, //printf("updateCRU: %d, %d (%d, %d), %d, %d, %f, %f\n", int(cru), row, globalRow, sectorRow, pad, timeBin, signal, pedestal); // fill digits - mDigits[cru.sector()].emplace_back(cru, signalCorr, globalRow, pad, timeBin); + addDigit(cru, signalCorr, globalRow, pad, timeBin); return 0; } From 9d988cad000bbe508e9175d79b78fd71ca8ecc7a Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Wed, 20 May 2020 14:55:39 +0200 Subject: [PATCH 0244/1751] Fix escaping of literal {} --- Detectors/TPC/base/src/Utils.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/base/src/Utils.cxx b/Detectors/TPC/base/src/Utils.cxx index 90fd39311fdf2..f41d31972f69e 100644 --- a/Detectors/TPC/base/src/Utils.cxx +++ b/Detectors/TPC/base/src/Utils.cxx @@ -12,6 +12,7 @@ #include <regex> #include <string> #include <fmt/format.h> +#include <fmt/printf.h> #include "TObject.h" #include "TObjArray.h" @@ -101,10 +102,13 @@ void utils::addFECInfo() const auto& fecInfo = mapper.getFECInfo(PadROCPos(roc, row, pad)); - std::string title("#splitline{#lower[.1]{#scale[.5]{"); - title += (roc / 18 % 2 == 0) ? "A" : "C"; - title += fmt::format("{:02d} ({:02d}) row: {:02d}, pad: {:03d}, globalpad: {:05d} (in roc)}}}{#scale[.5]{FEC: {:02d}, Chip: {:02d}, Chn: {:02d}, Value: {:.3f}}}", - roc % 18, roc, row, pad, channel, fecInfo.getIndex(), fecInfo.getSampaChip(), fecInfo.getSampaChannel(), binValue); + const std::string title = fmt::format( + "#splitline{{#lower[.1]{{#scale[.5]{{" + "{}{:02d} ({:02d}) row: {:02d}, pad: {:03d}, globalpad: {:05d} (in roc)" + "}}}}}}{{#scale[.5]{{FEC: " + "{:02d}, Chip: {:02d}, Chn: {:02d}, Value: {:.3f}" + "}}}}", + (roc / 18 % 2 == 0) ? "A" : "C", roc % 18, roc, row, pad, channel, fecInfo.getIndex(), fecInfo.getSampaChip(), fecInfo.getSampaChannel(), binValue); h->SetTitle(title.data()); } From a1413834cd3b92f0e7e93aebf3bb14aed5d62cc8 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Wed, 20 May 2020 14:56:45 +0200 Subject: [PATCH 0245/1751] Add options for pedestal offset and only dumping links with data --- .../calibration/macro/preparePedestalFiles.C | 24 ++++++++++++++----- .../calibration/macro/preparePedestalFiles.sh | 18 +++++++++----- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Detectors/TPC/calibration/macro/preparePedestalFiles.C b/Detectors/TPC/calibration/macro/preparePedestalFiles.C index d5ace146b26f8..91d2e8a13e962 100644 --- a/Detectors/TPC/calibration/macro/preparePedestalFiles.C +++ b/Detectors/TPC/calibration/macro/preparePedestalFiles.C @@ -14,6 +14,7 @@ #include <fstream> #include <iostream> #include <tuple> +#include <numeric> #include "TFile.h" #include "TROOT.h" @@ -45,7 +46,7 @@ struct LinkInfo { using ValueArray = std::array<uint32_t, 80>; using DataMap = std::map<LinkInfo, ValueArray>; -void writeValues(const std::string_view fileName, const DataMap& map); +void writeValues(const std::string_view fileName, const DataMap& map, bool onlyFilled = false); int getHWChannel(int sampa, int channel, int regionIter); /// convert float to integer with fixed precision and max number of digits @@ -72,7 +73,7 @@ constexpr float fixedSizeToFloat(uint32_t value) return float(value) * FloatConversion; } -void preparePedestalFiles(const std::string_view pedestalFileName, const TString outputDir = "./", float sigmaNoise = 3, float minADC = 2, float pedestalOffset = 0) +void preparePedestalFiles(const std::string_view pedestalFileName, const TString outputDir = "./", float sigmaNoise = 3, float minADC = 2, float pedestalOffset = 0, bool onlyFilled = false) { static constexpr float FloatConversion = 1.f / float(1 << 2); @@ -126,13 +127,19 @@ void preparePedestalFiles(const std::string_view pedestalFileName, const TString const int globalLinkID = (fecInPartition % fecOffset) + dataWrapperID * 12; float pedestal = rocPedestal.getValue(ipad); + if ((pedestal > 0) && (pedestalOffset > pedestal)) { + printf("ROC: %2zu, pad: %3zu -- pedestal offset %.2f larger than the pedestal value %.2f. Pedestal and noise will be set to 0\n", iroc, ipad, pedestalOffset, pedestal); + } else { + pedestal -= pedestalOffset; + } + float noise = std::abs(rocNoise.getValue(ipad)); // it seems with the new fitting procedure, the noise can also be negative, since in gaus sigma is quadratic if ((pedestal < 0) || (pedestal > 1023) || (noise < 0) || (noise > 1023)) { printf("Bad pedestal or noise value in ROC %2zu, CRU %3d, fec in CRU: %2d, SAMPA: %d, channel: %2d, pedestal: %.4f, noise %.4f, setting both to 0\n", iroc, cruID, fecInPartition, sampa, sampaChannel, pedestal, noise); pedestal = 0; noise = 0; } - const float threshold = std::max(sigmaNoise * noise, minADC); + const float threshold = (noise > 0) ? std::max(sigmaNoise * noise, minADC) : 0; const int hwChannel = getHWChannel(sampa, sampaChannel, region % 2); // for debugging @@ -149,8 +156,8 @@ void preparePedestalFiles(const std::string_view pedestalFileName, const TString } } - writeValues((outputDir + "/pedestal_values.txt").Data(), pedestalValues); - writeValues((outputDir + "/threshold_values.txt").Data(), thresholdlValues); + writeValues((outputDir + "/pedestal_values.txt").Data(), pedestalValues, onlyFilled); + writeValues((outputDir + "/threshold_values.txt").Data(), thresholdlValues, onlyFilled); } /// return the hardware channel number as mapped in the CRU @@ -167,11 +174,16 @@ int getHWChannel(int sampa, int channel, int regionIter) /// write values of map to fileName /// -void writeValues(const std::string_view fileName, const DataMap& map) +void writeValues(const std::string_view fileName, const DataMap& map, bool onlyFilled) { std::ofstream str(fileName.data(), std::ofstream::out); for (const auto& [linkInfo, data] : map) { + if (onlyFilled) { + if (!std::accumulate(data.begin(), data.end(), uint32_t(0))) { + continue; + } + } std::string values; for (const auto& val : data) { if (values.size()) { diff --git a/Detectors/TPC/calibration/macro/preparePedestalFiles.sh b/Detectors/TPC/calibration/macro/preparePedestalFiles.sh index d5ea493b26cf7..64e086b803e35 100755 --- a/Detectors/TPC/calibration/macro/preparePedestalFiles.sh +++ b/Detectors/TPC/calibration/macro/preparePedestalFiles.sh @@ -8,10 +8,12 @@ required arguments -i, --inputFile= : input file name optional arguments: --o, --outputDir= : set output directory for (default: ./) --m, --minADC= : minimal ADC value accepted for threshold (default: 2) --s, --sigmaNoise= : number of sigmas for the threshold (default: 3) --h, --help : show this help message" +-o, --outputDir= : set output directory for (default: ./) +-m, --minADC= : minimal ADC value accepted for threshold (default: 2) +-s, --sigmaNoise= : number of sigmas for the threshold (default: 3) +-p, --pedestalOffset= : pedestal offset value +-f, --onlyFilled : only write links which have data +-h, --help : show this help message" echo "$usage" } @@ -30,9 +32,11 @@ fileInfo= outputDir="./" minADC=2 sigmaNoise=3 +pedestalOffset=0 +onlyFilled=0 # ===| parse command line options |============================================= -OPTIONS=$(getopt -l "inputFile:,outputDir:,minADC:,sigmaNoise:,help" -o "i:o:t:m:s:h" -n "preparePedestalFiles.sh" -- "$@") +OPTIONS=$(getopt -l "inputFile:,outputDir:,minADC:,sigmaNoise:,pedestalOffset:,onlyFilled,help" -o "i:o:t:m:s:p:fh" -n "preparePedestalFiles.sh" -- "$@") if [ $? != 0 ] ; then usageAndExit @@ -47,6 +51,8 @@ while true; do -o|--outputDir) outputDir=$2; shift 2;; -m|--minADC) minADC=$2; shift 2;; -s|--sigmaNoise) sigmaNoise=$2; shift 2;; + -p|--pedestalOffset) pedestalOffset=$2; shift 2;; + -f|--onlyFilled) onlyFilled=1; shift;; -h|--help) usageAndExit;; *) echo "Internal error!" ; exit 1 ;; esac @@ -58,6 +64,6 @@ if [[ -z "$inputFile" ]]; then fi # ===| command building and execution |========================================= -cmd="root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/preparePedestalFiles.C+g'(\"$inputFile\",\"$outputDir\", $sigmaNoise, $minADC)'" +cmd="root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/preparePedestalFiles.C+g'(\"$inputFile\",\"$outputDir\", $sigmaNoise, $minADC, $pedestalOffset, $onlyFilled)'" echo "running: $cmd" eval $cmd From 28d06f8041ebebde3c6284557e0277eb699f0ceb Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Wed, 20 May 2020 14:57:43 +0200 Subject: [PATCH 0246/1751] update help for statistics type --- Detectors/TPC/calibration/macro/runPedestal.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/calibration/macro/runPedestal.sh b/Detectors/TPC/calibration/macro/runPedestal.sh index e7d645fb23774..2903beb4ea840 100755 --- a/Detectors/TPC/calibration/macro/runPedestal.sh +++ b/Detectors/TPC/calibration/macro/runPedestal.sh @@ -18,7 +18,7 @@ usage() { echo " -n, --nevents= : number of events to process (default: 1000)" echo " -m, --adcMin= : minimal ADC values accepted (default: 0)" echo " -x, --adcMax= : maximal ADC values accepted (default: 1100)" - echo " -s, --statType= : statistics type - 0: Gaus fit (default), 1: Mean and StdDev" + echo " -s, --statType= : statistics type - 0: Gaus fit (default), 1: Gaus fit fast, 2: Mean and StdDev" echo " -v, --verbosity= : set verbosity level for raw reader" echo " -d, --debugLevel= : set debug level for raw reader" echo " -w, --writeDebug : write debug output histograms" From 3d6db1b12eee853a2e562cb534de287fe87a51bf Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Wed, 20 May 2020 21:19:54 +0200 Subject: [PATCH 0247/1751] possibility to use pulser for CE analysis --- .../include/TPCCalibration/CalibPulser.h | 3 +++ Detectors/TPC/calibration/macro/drawPulser.C | 24 +++++++++++++++---- Detectors/TPC/calibration/macro/runPulser.C | 6 ++++- Detectors/TPC/calibration/macro/runPulser.sh | 8 +++++-- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h index 4ea939dafbf97..d1cb18fe4d679 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h @@ -119,6 +119,9 @@ class CalibPulser : public CalibRawBase mXmaxQtot = max; } + /// set minimum Qtot signal for the signal + void setMinQtot(int minQtot) { mMinimumQtot = minQtot; } + /// Analyse the buffered pulser information void analyse(); diff --git a/Detectors/TPC/calibration/macro/drawPulser.C b/Detectors/TPC/calibration/macro/drawPulser.C index d499010138a3d..331719c3fac09 100644 --- a/Detectors/TPC/calibration/macro/drawPulser.C +++ b/Detectors/TPC/calibration/macro/drawPulser.C @@ -25,7 +25,7 @@ /// Open pedestalFile and retrieve noise and pedestal values /// Draw then in separate canvases and add an executable to be able to add /// FEC information to the title -TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir = "") +TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir = "", int type = 0) { if ((mode != 0) && (mode != 1)) { return 0x0; @@ -47,9 +47,25 @@ TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir // mode 1 handling if (mode == 1) { - auto arrT0 = painter::makeSummaryCanvases(*calT0, 100, 238.f, 240.f); - auto arrWidth = painter::makeSummaryCanvases(*calWidth, 100, 0.38f, 0.57f); - auto arrQtot = painter::makeSummaryCanvases(*calQtot, 100, 20.f, 280.f); + float tMin = 238.f; + float tMax = 240.f; + float wMin = 0.38f; + float wMax = 0.57f; + float qMin = 20.f; + float qMax = 280.f; + + if (type == 1) { + tMin = 455.f; + tMax = 465.f; + wMin = 0.6; + wMax = 0.8; + qMin = 2.f; + qMax = 180.f; + } + + auto arrT0 = painter::makeSummaryCanvases(*calT0, 100, tMin, tMax); + auto arrWidth = painter::makeSummaryCanvases(*calWidth, 100, wMin, wMax); + auto arrQtot = painter::makeSummaryCanvases(*calQtot, 100, qMin, qMax); for (auto c : arrT0) { arrCanvases->Add(c); diff --git a/Detectors/TPC/calibration/macro/runPulser.C b/Detectors/TPC/calibration/macro/runPulser.C index b59d03eb02f99..f3da112096f4c 100644 --- a/Detectors/TPC/calibration/macro/runPulser.C +++ b/Detectors/TPC/calibration/macro/runPulser.C @@ -21,7 +21,7 @@ void runPulser(std::vector<std::string_view> fileInfos, TString outputFileName = Int_t adcMin = 0, Int_t adcMax = 1100, Int_t firstTimeBin = 0, Int_t lastTimeBin = 500, TString pedestalAndNoiseFile = "", - uint32_t verbosity = 0, uint32_t debugLevel = 0) + uint32_t verbosity = 0, uint32_t debugLevel = 0, int type = 0) { using namespace o2::tpc; // ===| set up calibration class |============================================ @@ -29,6 +29,10 @@ void runPulser(std::vector<std::string_view> fileInfos, TString outputFileName = calib.setADCRange(adcMin, adcMax); calib.setTimeBinRange(firstTimeBin, lastTimeBin); calib.setDebugLevel(); + if (type == 1) { + calib.setQtotBinning(150,2,302); + calib.setMinQtot(4); + } //calib.setDebugLevel(debugLevel); // ===| load pedestal if requested |========================================== diff --git a/Detectors/TPC/calibration/macro/runPulser.sh b/Detectors/TPC/calibration/macro/runPulser.sh index 2fe16884a81c6..3a6e637008059 100755 --- a/Detectors/TPC/calibration/macro/runPulser.sh +++ b/Detectors/TPC/calibration/macro/runPulser.sh @@ -21,6 +21,7 @@ usage() { echo " -p, --pedestalFile= : pedestal and noise file" echo " -v, --verbosity= : set verbosity level for raw reader" echo " -d, --debugLevel= : set debug level for raw reader" + echo " -t, --type= : run type (pulser: 0, laser: 1)" echo " -h, --help : show this help message" } @@ -45,8 +46,10 @@ debugLevel=0 adcMin=0 adcMax=1100 +dataType=0 + # ===| parse command line options |============================================= -OPTIONS=$(getopt -l "fileInfo:,outputFile:,firstTimeBin:,lastTimeBin:,nevents:,adcMin:,adcMax:,pedestalFile:,verbosity:,debugLevel:,help" -o "i:o:f:l:n:m:x:p:v:d:h" -n "runPulser.sh" -- "$@") +OPTIONS=$(getopt -l "fileInfo:,outputFile:,firstTimeBin:,lastTimeBin:,nevents:,adcMin:,adcMax:,pedestalFile:,verbosity:,debugLevel:,type:,help" -o "i:o:f:l:n:m:x:p:v:d:t:h" -n "runPulser.sh" -- "$@") if [ $? != 0 ] ; then usageAndExit @@ -67,6 +70,7 @@ while true; do -p|--pedestalFile) pedestalFile=$2; shift 2;; -v|--verbosity) verbosity=$2; shift 2;; -d|--debugLevel) debugLevel=$2; shift 2;; + -t|--type) dataType=$2; shift 2;; -h|--help) usageAndExit;; *) echo "Internal error!" ; exit 1 ;; esac @@ -89,6 +93,6 @@ fi fileInfo=$(echo $fileInfo | sed "s|^|{\"|;s|,|:$lastTimeBin\",\"|g;s|$|\"}|") # ===| command building and execution |========================================= -cmd="root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPulser.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, \"$pedestalFile\", $verbosity, $debugLevel)'" +cmd="root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPulser.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, \"$pedestalFile\", $verbosity, $debugLevel, $dataType)'" echo "running: $cmd" eval $cmd From 6b0ba4a4c918917d21835090770cb3ad4e14bdec Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Mon, 25 May 2020 13:11:29 +0200 Subject: [PATCH 0248/1751] improve file handling --- .../include/TPCReconstruction/RawReaderCRU.h | 2 + .../TPC/reconstruction/src/RawReaderCRU.cxx | 50 +++++++++++-------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h index 497c347ea34b9..c20017bf7f346 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h @@ -712,6 +712,8 @@ class RawReaderCRU std::map<PadPos, std::vector<uint16_t>> mADCdata; ///< decoded ADC data RawReaderCRUManager* mManager{nullptr}; ///< event synchronization information + std::ifstream mFileHandle; ///< file handle for input file + /// collect raw GBT data void collectGBTData(std::vector<o2::byte>& data); diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index 27473511b6631..aae19e5179e1d 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -190,10 +190,12 @@ int RawReaderCRU::scanFile() //const uint64_t RDH_HEADERWORD0 = 0x00004003; const uint64_t RDH_HEADERWORD0 = 0x00004000 + RDHUtils::getVersion<o2::header::RAWDataHeader>(); - std::ifstream file; - file.open(mInputFileName, std::ifstream::binary); - if (!file.good()) - throw std::runtime_error("Unable to open or access file " + mInputFileName); + std::ifstream& file = mFileHandle; + if (!file.is_open()) { + file.open(mInputFileName, std::ifstream::binary); + if (!file.good()) + throw std::runtime_error("Unable to open or access file " + mInputFileName); + } // get length of file in bytes file.seekg(0, file.end); @@ -371,10 +373,12 @@ int RawReaderCRU::scanFile() void RawReaderCRU::findSyncPositions() { - std::ifstream file; - file.open(mInputFileName, std::ifstream::binary); - if (!file.good()) - throw std::runtime_error("Unable to open or access file " + mInputFileName); + std::ifstream& file = mFileHandle; + if (!file.is_open()) { + file.open(mInputFileName, std::ifstream::binary); + if (!file.good()) + throw std::runtime_error("Unable to open or access file " + mInputFileName); + } // loop over the MaxNumberOfLinks potential links in the data // only if data from the link is present and selected @@ -431,10 +435,12 @@ void RawReaderCRU::findSyncPositions() int RawReaderCRU::processPacket(GBTFrame& gFrame, uint32_t startPos, uint32_t size, ADCRawData& rawData) { // open the data file - std::ifstream file; - file.open(mInputFileName, std::ifstream::binary); - if (!file.good()) - throw std::runtime_error("Unable to open or access file " + mInputFileName); + std::ifstream& file = mFileHandle; + if (!file.is_open()) { + file.open(mInputFileName, std::ifstream::binary); + if (!file.good()) + throw std::runtime_error("Unable to open or access file " + mInputFileName); + } // jump to the start position of the packet file.seekg(startPos, file.beg); @@ -674,10 +680,12 @@ void RawReaderCRU::collectGBTData(std::vector<o2::byte>& data) const auto& mapper = Mapper::instance(); const auto& linkInfoArray = mManager->mEventSync.getLinkInfoArrayForEvent(mEventNumber, mCRU); - std::ifstream file; - file.open(mInputFileName, std::ios::binary); - if (!file.good()) - throw std::runtime_error("Unable to open or access file " + mInputFileName); + std::ifstream& file = mFileHandle; + if (!file.is_open()) { + file.open(mInputFileName, std::ios::binary); + if (!file.good()) + throw std::runtime_error("Unable to open or access file " + mInputFileName); + } size_t presentDataPosition = 0; @@ -777,10 +785,12 @@ void RawReaderCRU::copyEvents(const std::vector<uint32_t>& eventNumbers, std::st std::ofstream outputFile(outputFileName, std::ios_base::binary | mode); // open the input file - std::ifstream file; - file.open(mInputFileName, std::ifstream::binary); - if (!file.good()) { - throw std::runtime_error("Unable to open or access file " + mInputFileName); + std::ifstream& file = mFileHandle; + if (!file.is_open()) { + file.open(mInputFileName, std::ifstream::binary); + if (!file.good()) { + throw std::runtime_error("Unable to open or access file " + mInputFileName); + } } // data buffer. Maximum size is 8k From 8bb72ec285e29b1f0822702c4ceebb48a1b58407 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Mon, 25 May 2020 13:24:29 +0200 Subject: [PATCH 0249/1751] add possibility to merge CalPad objects from different files --- Detectors/TPC/base/include/TPCBase/Utils.h | 9 ++++ Detectors/TPC/base/src/Utils.cxx | 50 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/Detectors/TPC/base/include/TPCBase/Utils.h b/Detectors/TPC/base/include/TPCBase/Utils.h index 6da9672bf1de5..83feaa959eff6 100644 --- a/Detectors/TPC/base/include/TPCBase/Utils.h +++ b/Detectors/TPC/base/include/TPCBase/Utils.h @@ -50,6 +50,15 @@ void saveCanvas(TCanvas& c, std::string_view outDir, std::string_view types); std::vector<CalPad*> readCalPads(const std::string_view fileName, const std::vector<std::string>& calPadNames); std::vector<CalPad*> readCalPads(const std::string_view fileName, const std::string_view calPadNames); +/// Merge cal pad objects from different files +/// +/// Requires that all objects have the same name in the differnet files. +/// Objects are simply added. +/// \param outputFileName name of the output file +/// \param inputFileNames input file names. Perforams file system 'ls' in case the string includes '.root'. Otherwise it assumes a text input file with line by line file names. +/// \param calPadNames comma separated list of names of the CalPad objects as stored in the file. +void mergeCalPads(std::string_view outputFileName, std::string_view inputFileNames, std::string_view calPadNames); + } // namespace utils } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/base/src/Utils.cxx b/Detectors/TPC/base/src/Utils.cxx index f41d31972f69e..ee6c672289993 100644 --- a/Detectors/TPC/base/src/Utils.cxx +++ b/Detectors/TPC/base/src/Utils.cxx @@ -14,6 +14,7 @@ #include <fmt/format.h> #include <fmt/printf.h> +#include "TSystem.h" #include "TObject.h" #include "TObjArray.h" #include "TCanvas.h" @@ -165,3 +166,52 @@ std::vector<CalPad*> utils::readCalPads(const std::string_view fileName, const s auto calPadNamesVec = tokenize(calPadNames, ","); return readCalPads(fileName, calPadNamesVec); } + +/// macro to merge cal pad objects from different files +/// +/// requires that all objects have the same name in the differnet files. +/// Objects are simply added. +/// \param outputFileName name of the output file +/// \param inputFileNames input file names. Perforams file system 'ls' in case the string includes '.root'. Otherwise it assumes a text input file with line by line file names. +/// \param calPadNames comma separated list of names of the CalPad objects as stored in the file. +void utils::mergeCalPads(std::string_view outputFileName, std::string_view inputFileNames, std::string_view calPadNames) +{ + using namespace o2::tpc; + + auto calPadNamesVec = utils::tokenize(calPadNames, ","); + + std::string_view cmd = "ls"; + if (inputFileNames.rfind(".root") == std::string_view::npos) { + cmd = "cat"; + } + auto files = gSystem->GetFromPipe(TString::Format("%s %s", cmd.data(), inputFileNames.data())); + std::unique_ptr<TObjArray> arrFiles(files.Tokenize("\n")); + + std::vector<CalPad*> mergedCalPads; + + for (auto ofile : *arrFiles) { + auto calPads = utils::readCalPads(ofile->GetName(), calPadNamesVec); + if (!calPads.size()) { + continue; + } + if (!mergedCalPads.size()) { + mergedCalPads = calPads; + } else { + for (size_t iCalPad = 0; iCalPad<calPads.size(); ++iCalPad) { + auto calPadName = calPadNamesVec[iCalPad]; + auto calPadMerged = mergedCalPads[iCalPad]; + calPadMerged->setName(calPadName); + auto calPadToMerge = calPads[iCalPad]; + + *calPadMerged += *calPadToMerge; + + delete calPadToMerge; + } + } + } + + std::unique_ptr<TFile> outFile(TFile::Open(outputFileName.data(), "recreate")); + for (auto calPad : mergedCalPads) { + outFile->WriteObject(calPad, calPad->getName().data()); + } +} From f43b87e24b32e08b4a83f84c3fd049df63ef410f Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Mon, 25 May 2020 13:41:32 +0200 Subject: [PATCH 0250/1751] Several fixes and improvements in calib classes * Add auto detection of time bin with maximum number of entries. Allow to add a range around this time bin to limit analysis to it. Improves CE analysis. * Add possibility to cut on the minum Qmax value * Better default settings for CE analysis fix CalibPulser.h --- .../include/TPCCalibration/CalibPulser.h | 49 ++++++++---- .../include/TPCCalibration/CalibPulserParam.h | 33 +++++---- .../include/TPCCalibration/CalibRawBase.h | 1 + Detectors/TPC/calibration/macro/drawPulser.C | 4 +- .../TPC/calibration/macro/runPedestal.sh | 7 +- Detectors/TPC/calibration/macro/runPulser.C | 4 +- Detectors/TPC/calibration/src/CalibPulser.cxx | 74 ++++++++++++++++--- 7 files changed, 124 insertions(+), 48 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h index d1cb18fe4d679..4928604b3b490 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibPulser.h @@ -119,8 +119,14 @@ class CalibPulser : public CalibRawBase mXmaxQtot = max; } - /// set minimum Qtot signal for the signal - void setMinQtot(int minQtot) { mMinimumQtot = minQtot; } + /// set minimum Qtot for the signal + void setMinQtot(float minQtot) { mMinimumQtot = minQtot; } + + /// set minimum Qmax for the signal + void setMinQmax(float minQmax) { mMinimumQmax = minQmax; } + + /// set time bin range around the one with the maximum number of entries + void setMaxTimeBinRange(int max) { mMaxTimeBinRange = max; } /// Analyse the buffered pulser information void analyse(); @@ -158,23 +164,27 @@ class CalibPulser : public CalibRawBase float mXminWidth; ///< xmin of width reference histogram float mXmaxWidth; ///< xmax of width reference histogram - int mFirstTimeBin; ///< first time bin used in analysis - int mLastTimeBin; ///< first time bin used in analysis - int mADCMin; ///< minimum adc value - int mADCMax; ///< maximum adc value - int mNumberOfADCs; ///< number of adc values (mADCMax-mADCMin+1) - int mPeakIntMinus; ///< lower bound from maximum for the peak integration, mean and std dev. calc - int mPeakIntPlus; ///< upper bound from maximum for the peak integration, mean and std dev. calc - int mMinimumQtot; ///< minimal Qtot accepted as pulser signal - CalPad mT0; ///< CalDet object with pulser time information - CalPad mWidth; ///< CalDet object with pulser pulse width information - CalPad mQtot; ///< CalDet object with pulser Qtot information + int mFirstTimeBin; ///< first time bin used in analysis + int mLastTimeBin; ///< first time bin used in analysis + int mADCMin; ///< minimum adc value + int mADCMax; ///< maximum adc value + int mNumberOfADCs; ///< number of adc values (mADCMax-mADCMin+1) + int mPeakIntMinus; ///< lower bound from maximum for the peak integration, mean and std dev. calc + int mPeakIntPlus; ///< upper bound from maximum for the peak integration, mean and std dev. calc + float mMinimumQtot; ///< minimal Qtot accepted as pulser signal + float mMinimumQmax; ///< minimal Qtot accepted as pulser signal + int mMaxTimeBinRange; ///< number of time bins around the one with the maximum number of entries arouch which to analyse + CalPad mT0; ///< CalDet object with pulser time information + CalPad mWidth; ///< CalDet object with pulser pulse width information + CalPad mQtot; ///< CalDet object with pulser Qtot information const CalPad* mPedestal; //!< Pedestal calibration object const CalPad* mNoise; //!< Noise calibration object std::map<PadROCPos, VectorType> mPulserData; //!< ADC data to calculate pulser information + std::array<std::vector<size_t>, ROC::MaxROC> mTimeBinEntries{}; //!< entries per time bin per ROC + PtrVectorType mT0Histograms; //!< T0 histogramgs per ROC and pad PtrVectorType mWidthHistograms; //!< Width histogramgs per ROC and pad PtrVectorType mQtotHistograms; //!< Qtot histogramgs per ROC and pad @@ -184,6 +194,14 @@ class CalibPulser : public CalibRawBase float mT0{0.f}; float mWidth{0.f}; float mQtot{0.f}; + + bool isValid() const { return (mT0 > 0.f) || (mWidth > 0.f) || (mQtot > 0.f); } + }; + + /// element pair + struct ElemPair { + size_t first{0}; + size_t last{0}; }; /// create or return a histogram for a specific ROC @@ -217,7 +235,10 @@ class CalibPulser : public CalibRawBase /// process the adc values of one pad /// extract the T0, width, qmax and qtot /// \param adcData vector with ADC values per pad - PulserData processPadData(const PadROCPos& padROCPos, const VectorType& adcData); + PulserData processPadData(const PadROCPos& padROCPos, const VectorType& adcData, const ElemPair& range); + + /// maximum time bin entries per ROC + std::array<ElemPair, ROC::MaxROC> getTimeRangeROCs(); /// dummy reset void resetEvent() final {} diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibPulserParam.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibPulserParam.h index a928650565188..8aac9fedd51a4 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibPulserParam.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibPulserParam.h @@ -24,22 +24,23 @@ namespace tpc { struct CalibPulserParam : public o2::conf::ConfigurableParamHelper<CalibPulserParam> { - int NbinsT0{200}; ///< Number of bins for T0 reference histogram - float XminT0{-2}; ///< xmin of T0 reference histogram - float XmaxT0{2}; ///< xmax of T0 reference histogram - int NbinsQtot{200}; ///< Number of bins for Qtot reference histogram - float XminQtot{50}; ///< xmin of Qtot reference histogram - float XmaxQtot{700}; ///< xmax of Qtot reference histogram - int NbinsWidth{100}; ///< Number of bins for width reference histogram - float XminWidth{0.1}; ///< xmin of width reference histogram - float XmaxWidth{5.1}; ///< xmax of width reference histogram - int FirstTimeBin{10}; ///< first time bin used in analysis - int LastTimeBin{490}; ///< first time bin used in analysis - int ADCMin{5}; ///< minimum adc value - int ADCMax{1023}; ///< maximum adc value - int PeakIntMinus{2}; ///< lower bound from maximum for the peak integration, mean and std dev. calc - int PeakIntPlus{2}; ///< upper bound from maximum for the peak integration, mean and std dev. calc - int MinimumQtot{20}; ///< minimal Qtot accepted as pulser signal + int NbinsT0{200}; ///< Number of bins for T0 reference histogram + float XminT0{-2}; ///< xmin of T0 reference histogram + float XmaxT0{2}; ///< xmax of T0 reference histogram + int NbinsQtot{200}; ///< Number of bins for Qtot reference histogram + float XminQtot{50}; ///< xmin of Qtot reference histogram + float XmaxQtot{700}; ///< xmax of Qtot reference histogram + int NbinsWidth{100}; ///< Number of bins for width reference histogram + float XminWidth{0.1}; ///< xmin of width reference histogram + float XmaxWidth{5.1}; ///< xmax of width reference histogram + int FirstTimeBin{10}; ///< first time bin used in analysis + int LastTimeBin{490}; ///< first time bin used in analysis + int ADCMin{5}; ///< minimum adc value + int ADCMax{1023}; ///< maximum adc value + int PeakIntMinus{2}; ///< lower bound from maximum for the peak integration, mean and std dev. calc + int PeakIntPlus{2}; ///< upper bound from maximum for the peak integration, mean and std dev. calc + float MinimumQtot{20}; ///< minimal Qtot accepted as pulser signal + float MinimumQmax{10}; ///< minimal Qmax accepted as pulser signal O2ParamDef(CalibPulserParam, "TPCCalibPulser"); }; diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h index 8436ee14bbbc3..a9ed98f4dbf40 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h @@ -636,6 +636,7 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventDigitTree(int event } endEvent(); + endReader(); ++mNevents; LOG(INFO) << "Present event number : " << mPresentEventNumber; diff --git a/Detectors/TPC/calibration/macro/drawPulser.C b/Detectors/TPC/calibration/macro/drawPulser.C index 331719c3fac09..e1bb4d13d1860 100644 --- a/Detectors/TPC/calibration/macro/drawPulser.C +++ b/Detectors/TPC/calibration/macro/drawPulser.C @@ -55,8 +55,8 @@ TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir float qMax = 280.f; if (type == 1) { - tMin = 455.f; - tMax = 465.f; + tMin = 425.f; + tMax = 485.f; wMin = 0.6; wMax = 0.8; qMin = 2.f; diff --git a/Detectors/TPC/calibration/macro/runPedestal.sh b/Detectors/TPC/calibration/macro/runPedestal.sh index 2903beb4ea840..bb246245d4ade 100755 --- a/Detectors/TPC/calibration/macro/runPedestal.sh +++ b/Detectors/TPC/calibration/macro/runPedestal.sh @@ -93,8 +93,9 @@ fi fileInfo=$(echo $fileInfo | sed "s|^|{\"|;s|,|:$lastTimeBin\",\"|g;s|$|\"}|") # ===| command building and execution |========================================= -cmd="root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPedestal.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, $statisticsType, $verbosity, $debugLevel, 0, $writeDebug)'" -#cmd="perf record -g -o perf.log root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPedestal.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, $statisticsType, $verbosity, $debugLevel)'" -#cmd="valgrind --tool=callgrind --dump-instr=yes --dump-instr=yes root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPedestal.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, $statisticsType, $verbosity, $debugLevel)'" +cmd="" +#cmd="valgrind --tool=callgrind --dump-instr=yes --dump-instr=yes" +#cmd="perf record -g -o perf.log" +cmd="$cmd root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPedestal.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, $statisticsType, $verbosity, $debugLevel, 0, $writeDebug)'" echo "running: $cmd" eval $cmd diff --git a/Detectors/TPC/calibration/macro/runPulser.C b/Detectors/TPC/calibration/macro/runPulser.C index f3da112096f4c..48e9d1cf3cf95 100644 --- a/Detectors/TPC/calibration/macro/runPulser.C +++ b/Detectors/TPC/calibration/macro/runPulser.C @@ -31,7 +31,9 @@ void runPulser(std::vector<std::string_view> fileInfos, TString outputFileName = calib.setDebugLevel(); if (type == 1) { calib.setQtotBinning(150,2,302); - calib.setMinQtot(4); + calib.setMinQtot(8); + calib.setMinQmax(6); + calib.setMaxTimeBinRange(6); } //calib.setDebugLevel(debugLevel); diff --git a/Detectors/TPC/calibration/src/CalibPulser.cxx b/Detectors/TPC/calibration/src/CalibPulser.cxx index cb53738591a97..0ad6fc07a0d79 100644 --- a/Detectors/TPC/calibration/src/CalibPulser.cxx +++ b/Detectors/TPC/calibration/src/CalibPulser.cxx @@ -45,9 +45,11 @@ CalibPulser::CalibPulser(PadSubset padSubset) mPeakIntMinus{2}, mPeakIntPlus{2}, mMinimumQtot{20}, - mT0{"PulserT0"}, - mWidth{"PulserWidth"}, - mQtot{"PulserQtot"}, + mMinimumQmax{10}, + mMaxTimeBinRange{5}, + mT0{"T0"}, + mWidth{"Width"}, + mQtot{"Qtot"}, mPedestal{nullptr}, mNoise{nullptr}, mPulserData{}, @@ -87,6 +89,7 @@ void CalibPulser::init() mPeakIntMinus = param.PeakIntMinus; mPeakIntPlus = param.PeakIntPlus; mMinimumQtot = param.MinimumQtot; + mMinimumQmax = param.MinimumQmax; } //______________________________________________________________________________ @@ -118,6 +121,14 @@ Int_t CalibPulser::updateROC(const Int_t roc, const Int_t row, const Int_t pad, adcData[timeBin - mFirstTimeBin] = signal; //printf("%2d, %3d, %3d, %3d: %.2f\n", roc, row, pad, timeBin, signal); + + // ---| entries per time bin |--- + auto& timeBinEntries = mTimeBinEntries[roc]; + if (!timeBinEntries.size()) { + timeBinEntries.resize(mLastTimeBin - mFirstTimeBin + 1); + } + ++timeBinEntries[timeBin - mFirstTimeBin]; + return 1; } @@ -125,26 +136,36 @@ Int_t CalibPulser::updateROC(const Int_t roc, const Int_t row, const Int_t pad, void CalibPulser::endReader() { // loop over all signals of all pads filled for the present raw reader - for (auto& keyValue : mPulserData) { - const auto& padROCPos = keyValue.first; - const auto& adcData = keyValue.second; + //for (auto& keyValue : mPulserData) { + //const auto& padROCPos = keyValue.first; + //const auto& adcData = keyValue.second; + // + auto timeRangeROCs = getTimeRangeROCs(); + + for (const auto& [padROCPos, adcData] : mPulserData) { const auto currentChannel = mMapper.getPadNumberInROC(padROCPos); //std::cout << (int)padROCPos.getROC().getRoc() << ", " << padROCPos.getRow() << ", " << padROCPos.getPad() << std::endl; //for (auto& val: adcData) std::cout << val << ", "; //std::cout << std::endl; - const auto data = processPadData(padROCPos, adcData); + const auto& elemPair = timeRangeROCs[int(padROCPos.getROC())]; + const auto data = processPadData(padROCPos, adcData, elemPair); //std::cout << data.mT0+mFirstTimeBin << " : " << data.mQtot << " : " << data.mWidth << "\n"; // fill histograms - getHistoT0(padROCPos.getROC(), true)->Fill(data.mT0 + mFirstTimeBin, currentChannel); - getHistoQtot(padROCPos.getROC(), true)->Fill(data.mQtot, currentChannel); - getHistoSigma(padROCPos.getROC(), true)->Fill(data.mWidth, currentChannel); + if (data.isValid()) { + getHistoT0(padROCPos.getROC(), true)->Fill(data.mT0 + mFirstTimeBin, currentChannel); + getHistoQtot(padROCPos.getROC(), true)->Fill(data.mQtot, currentChannel); + getHistoSigma(padROCPos.getROC(), true)->Fill(data.mWidth, currentChannel); + } } // reset the adc data to free space mPulserData.clear(); + for (auto& v : mTimeBinEntries) { + std::fill(v.begin(), v.end(), 0); + } } //______________________________________________________________________________ @@ -166,13 +187,21 @@ TH2S* CalibPulser::getHistogram(ROC roc, CalibPulser::PtrVectorType& rocVector, } //______________________________________________________________________________ -CalibPulser::PulserData CalibPulser::processPadData(const PadROCPos& padROCPos, const CalibPulser::VectorType& adcData) +CalibPulser::PulserData CalibPulser::processPadData(const PadROCPos& padROCPos, const CalibPulser::VectorType& adcData, const CalibPulser::ElemPair& range) { // data to return PulserData data; + // find time bin with maximum number of entreis + const auto vectorSize = adcData.size(); - const auto maxElement = std::max_element(std::begin(adcData), std::end(adcData)); + //const auto maxElement = std::max_element(std::begin(adcData), std::end(adcData)); + const auto maxElement = std::max_element(std::begin(adcData) + range.first, std::begin(adcData) + range.last); + + if (*maxElement < mMinimumQmax) { + return data; + } + const auto maxPosition = std::distance(std::begin(adcData), maxElement); double weightedSum = 0.; @@ -200,10 +229,31 @@ CalibPulser::PulserData CalibPulser::processPadData(const PadROCPos& padROCPos, return data; } +//______________________________________________________________________________ +std::array<CalibPulser::ElemPair, ROC::MaxROC> CalibPulser::getTimeRangeROCs() +{ + std::array<ElemPair, ROC::MaxROC> maxTimeBin; + + for (size_t iROC = 0; iROC < mTimeBinEntries.size(); ++iROC) { + const auto& timeBinEntries = mTimeBinEntries[iROC]; + const auto size = timeBinEntries.size(); + const auto maxElement = std::max_element(std::begin(timeBinEntries), std::end(timeBinEntries)); + const auto maxPosition = std::distance(std::begin(timeBinEntries), maxElement); + + maxTimeBin[iROC].first = (maxPosition > mMaxTimeBinRange) ? maxPosition - mMaxTimeBinRange : 0; + maxTimeBin[iROC].last = std::min(size_t(maxPosition + mMaxTimeBinRange), size - 1); + } + + return maxTimeBin; +} + //______________________________________________________________________________ void CalibPulser::resetData() { mPulserData.clear(); + for (auto& v : mTimeBinEntries) { + std::fill(v.begin(), v.end(), 0); + } std::vector<PtrVectorType*> v{&mT0Histograms, &mWidthHistograms, &mQtotHistograms}; for (auto histArray : v) { From edf17938b2645d1cb1b9d78553f20ec9ae8a09b4 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 11 Jun 2020 15:53:25 +0200 Subject: [PATCH 0251/1751] add function to easily build a chain --- Detectors/TPC/base/include/TPCBase/Utils.h | 11 +++++++ Detectors/TPC/base/src/Utils.cxx | 34 ++++++++++++++++------ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/Utils.h b/Detectors/TPC/base/include/TPCBase/Utils.h index 83feaa959eff6..d2bc09914f25f 100644 --- a/Detectors/TPC/base/include/TPCBase/Utils.h +++ b/Detectors/TPC/base/include/TPCBase/Utils.h @@ -24,6 +24,7 @@ class TObjArray; class TCanvas; class TH1; +class TChain; namespace o2 { @@ -59,6 +60,16 @@ std::vector<CalPad*> readCalPads(const std::string_view fileName, const std::str /// \param calPadNames comma separated list of names of the CalPad objects as stored in the file. void mergeCalPads(std::string_view outputFileName, std::string_view inputFileNames, std::string_view calPadNames); +/// Build a chain interpreting a command line argument +/// +/// Comman line argument can e.g. be +/// ls *.root +/// cat fileWithRootFiles.txt +/// \param command command to run +/// \param treeName name of the tree in the chain +/// \param treeTitle title of the tree +TChain* buildChain(std::string_view command, std::string_view treeName, std::string_view treeTitle); + } // namespace utils } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/base/src/Utils.cxx b/Detectors/TPC/base/src/Utils.cxx index ee6c672289993..29cc54afbabf4 100644 --- a/Detectors/TPC/base/src/Utils.cxx +++ b/Detectors/TPC/base/src/Utils.cxx @@ -20,7 +20,9 @@ #include "TCanvas.h" #include "TH1.h" #include "TFile.h" +#include "TChain.h" +#include "Framework/Logger.h" #include "TPCBase/Mapper.h" #include "TPCBase/Utils.h" @@ -167,13 +169,7 @@ std::vector<CalPad*> utils::readCalPads(const std::string_view fileName, const s return readCalPads(fileName, calPadNamesVec); } -/// macro to merge cal pad objects from different files -/// -/// requires that all objects have the same name in the differnet files. -/// Objects are simply added. -/// \param outputFileName name of the output file -/// \param inputFileNames input file names. Perforams file system 'ls' in case the string includes '.root'. Otherwise it assumes a text input file with line by line file names. -/// \param calPadNames comma separated list of names of the CalPad objects as stored in the file. +//______________________________________________________________________________ void utils::mergeCalPads(std::string_view outputFileName, std::string_view inputFileNames, std::string_view calPadNames) { using namespace o2::tpc; @@ -186,7 +182,7 @@ void utils::mergeCalPads(std::string_view outputFileName, std::string_view input } auto files = gSystem->GetFromPipe(TString::Format("%s %s", cmd.data(), inputFileNames.data())); std::unique_ptr<TObjArray> arrFiles(files.Tokenize("\n")); - + std::vector<CalPad*> mergedCalPads; for (auto ofile : *arrFiles) { @@ -197,7 +193,7 @@ void utils::mergeCalPads(std::string_view outputFileName, std::string_view input if (!mergedCalPads.size()) { mergedCalPads = calPads; } else { - for (size_t iCalPad = 0; iCalPad<calPads.size(); ++iCalPad) { + for (size_t iCalPad = 0; iCalPad < calPads.size(); ++iCalPad) { auto calPadName = calPadNamesVec[iCalPad]; auto calPadMerged = mergedCalPads[iCalPad]; calPadMerged->setName(calPadName); @@ -215,3 +211,23 @@ void utils::mergeCalPads(std::string_view outputFileName, std::string_view input outFile->WriteObject(calPad, calPad->getName().data()); } } + +//______________________________________________________________________________ +TChain* utils::buildChain(std::string_view command, std::string_view treeName, std::string_view treeTitle) +{ + const TString files = gSystem->GetFromPipe(command.data()); + std::unique_ptr<TObjArray> arrFiles(files.Tokenize("\n")); + if (!arrFiles->GetEntriesFast()) { + LOGP(error, "command '{}' did not return results", command); + return nullptr; + } + + auto c = new TChain(treeName.data(), treeTitle.data()); + for (const auto o : *arrFiles) { + LOGP(info, "Adding file '{}'", o->GetName()); + c->AddFile(o->GetName()); + } + + return c; +} + From bdb34ab873e7a201d0b42b3746f528a74317ae1a Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 11 Jun 2020 15:55:41 +0200 Subject: [PATCH 0252/1751] add aliases --- Detectors/TPC/calibration/src/CalibTreeDump.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Detectors/TPC/calibration/src/CalibTreeDump.cxx b/Detectors/TPC/calibration/src/CalibTreeDump.cxx index 60cd738ca7a3e..79b4266b49e11 100644 --- a/Detectors/TPC/calibration/src/CalibTreeDump.cxx +++ b/Detectors/TPC/calibration/src/CalibTreeDump.cxx @@ -325,6 +325,10 @@ void CalibTreeDump::setDefaultAliases(TTree* tree) tree->SetAlias("region", "cruInSector"); tree->SetAlias("partition", "int(cruInSector / 2)"); + tree->SetAlias("padWidth", "(region == 0) * 0.416 + (region == 1) * 0.42 + (region == 2) * 0.42 + (region == 3) * 0.436 + (region == 4) * 0.6 + (region == 5) * 0.6 + (region == 6) * 0.608 + (region == 7) * 0.588 + (region == 8) * 0.604 + (region == 9) * 0.607"); + tree->SetAlias("padHeight", "0.75 + (region>3)*0.25 + (region>5)*0.2 + (region>7)*0.3"); + tree->SetAlias("padArea", "padHeight * padWidth"); + tree->SetAlias("IROC", "roc < 36"); tree->SetAlias("OROC", "roc >= 36"); tree->SetAlias("OROC1", "partition == 2"); From 147ac7564efe91b4edef393446e8a4f857cc014e Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 11 Jun 2020 15:56:39 +0200 Subject: [PATCH 0253/1751] upate qtot binning --- Detectors/TPC/calibration/macro/runPulser.C | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/TPC/calibration/macro/runPulser.C b/Detectors/TPC/calibration/macro/runPulser.C index 48e9d1cf3cf95..d1b8b4898a701 100644 --- a/Detectors/TPC/calibration/macro/runPulser.C +++ b/Detectors/TPC/calibration/macro/runPulser.C @@ -29,8 +29,9 @@ void runPulser(std::vector<std::string_view> fileInfos, TString outputFileName = calib.setADCRange(adcMin, adcMax); calib.setTimeBinRange(firstTimeBin, lastTimeBin); calib.setDebugLevel(); + calib.setQtotBinning(140, 22, 302); if (type == 1) { - calib.setQtotBinning(150,2,302); + calib.setQtotBinning(150, 2, 302); calib.setMinQtot(8); calib.setMinQmax(6); calib.setMaxTimeBinRange(6); From cf256e4d750df769b7842912b614e02ae0c9cec2 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 11 Jun 2020 16:05:38 +0200 Subject: [PATCH 0254/1751] add possibility to normalize qTot to pad area --- Detectors/TPC/calibration/macro/drawPulser.C | 44 ++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/calibration/macro/drawPulser.C b/Detectors/TPC/calibration/macro/drawPulser.C index e1bb4d13d1860..f4f1d28a87964 100644 --- a/Detectors/TPC/calibration/macro/drawPulser.C +++ b/Detectors/TPC/calibration/macro/drawPulser.C @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #if !defined(__CLING__) || defined(__ROOTCLING__) +#include <array> #include "TROOT.h" #include "TMath.h" #include "TH2.h" @@ -16,21 +17,25 @@ #include "TPCBase/CalDet.h" #include "TPCBase/Painter.h" #include "TPCBase/Utils.h" +#include "TPCBase/Mapper.h" #include "TPad.h" #include "TCanvas.h" #include "TH1F.h" #include "TString.h" +#include "TStyle.h" #endif /// Open pedestalFile and retrieve noise and pedestal values /// Draw then in separate canvases and add an executable to be able to add /// FEC information to the title -TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir = "", int type = 0) +TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir = "", int type = 0, bool normalizeQtot = true) { if ((mode != 0) && (mode != 1)) { return 0x0; } + gStyle->SetNumberContours(100); + TObjArray* arrCanvases = new TObjArray; arrCanvases->SetName("Pulser"); @@ -45,6 +50,35 @@ TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir f.GetObject("Width", calWidth); f.GetObject("Qtot", calQtot); + if (normalizeQtot) { + // normalize Qtot to pad area + const auto& mapper = o2::tpc::Mapper::instance(); + std::array<float, 152> mapRowPadArea; + { + int iregion = 0; + auto padRegion = &mapper.getPadRegionInfo(iregion); + for (size_t i = 0; i < mapRowPadArea.size(); ++i) { + if (i >= padRegion->getGlobalRowOffset() + padRegion->getNumberOfPadRows()) { + padRegion = &mapper.getPadRegionInfo(++iregion); + } + mapRowPadArea[i] = padRegion->getPadWidth() * padRegion->getPadHeight(); + //printf("row: %3i, region: %i, size: %.2f\n", i, iregion, mapRowPadArea[i]); + } + } + + auto& calArraysQtot = calQtot->getData(); + for (size_t iROC = 0; iROC < calArraysQtot.size(); ++iROC) { + auto& calArray = calArraysQtot[iROC]; + auto& qTotROC = calArray.getData(); + int offset = iROC < 36 ? 0 : mapper.getPadsInIROC(); + for (size_t iPad = 0; iPad < qTotROC.size(); ++iPad) { + const auto& padPos = mapper.padPos(iPad + offset); + auto& val = qTotROC[iPad]; + val /= mapRowPadArea[padPos.getRow()]; + } + } + } + // mode 1 handling if (mode == 1) { float tMin = 238.f; @@ -53,14 +87,18 @@ TObjArray* drawPulser(TString pulserFile, int mode = 0, std::string_view outDir float wMax = 0.57f; float qMin = 20.f; float qMax = 280.f; + if (normalizeQtot) { + qMin = 100.f; + qMax = 350.f; + } if (type == 1) { tMin = 425.f; tMax = 485.f; wMin = 0.6; wMax = 0.8; - qMin = 2.f; - qMax = 180.f; + qMin = 5.f; + qMax = 500.f; } auto arrT0 = painter::makeSummaryCanvases(*calT0, 100, tMin, tMax); From 169e1a31462d9d72934c1714497567c3dbb16bb0 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Mon, 22 Jun 2020 19:59:10 +0200 Subject: [PATCH 0255/1751] possibility to set first and last time bin for HWClfinder --- .../include/TPCReconstruction/HwClusterer.h | 4 +- .../TPCReconstruction/HwClustererParam.h | 2 + .../reconstruction/macro/runRecoFromDigits.sh | 10 ++++- .../TPC/reconstruction/src/HwClusterer.cxx | 40 +++++++++++++------ 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h index b52030da6d50a..58d9c80b82942 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h @@ -189,7 +189,9 @@ class HwClusterer : public Clusterer short mCurrentMcContainerInBuffer; ///< Bit field, where to find the current MC container in buffer short mSplittingMode; ///< Cluster splitting mode, 0 no splitting, 1 for minimum contributes half to both, 2 for miminum corresponds to left/older cluster int mClusterSector; ///< Sector to be processed - int mLastTimebin; ///< Last time bin of previous event + int mPreviousTimebin; ///< Last time bin of previous event + int mFirstTimebin; ///< First time bin to process + int mLastTimebin; ///< Last time bin to process unsigned mLastHB; ///< Last HB bin of previous event unsigned mPeakChargeThreshold; ///< Charge threshold for the central peak in ADC counts unsigned mContributionChargeThreshold; ///< Charge threshold for the contributing pads in ADC counts diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClustererParam.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClustererParam.h index ef1316ce5f982..5a48f31ee4a1b 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClustererParam.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClustererParam.h @@ -26,6 +26,8 @@ namespace tpc struct HwClustererParam : public o2::conf::ConfigurableParamHelper<HwClustererParam> { unsigned peakChargeThreshold = 2; ///< Charge threshold for the central peak in ADC counts unsigned contributionChargeThreshold = 0; ///< Charge threshold for the contributing pads in ADC counts + unsigned firstTimeBin = 0; ///< First time bin to process + unsigned lastTimeBin = 200000; ///< Last time bin to process short splittingMode = 0; ///< cluster splitting mode, 0 no splitting, 1 for minimum contributes half to both, 2 for miminum corresponds to left/older cluster, bool isContinuousReadout = true; ///< Switch for continuous readout bool rejectSinglePadClusters = false; ///< Switch to reject single pad clusters, sigmaPad2Pre == 0 diff --git a/Detectors/TPC/reconstruction/macro/runRecoFromDigits.sh b/Detectors/TPC/reconstruction/macro/runRecoFromDigits.sh index 4ad3028f7ae17..273e6fa4d8923 100755 --- a/Detectors/TPC/reconstruction/macro/runRecoFromDigits.sh +++ b/Detectors/TPC/reconstruction/macro/runRecoFromDigits.sh @@ -6,6 +6,8 @@ usage() { echo echo "optional arguments:" echo " -i, --inputFile= : set output file name (default: '$inputFile')" + echo " -f, --fistTimeBin= : first time bin for cluster finder" + echo " -l, --lastTimeBin= : last time bin for cluster finder" echo " -o, --outputType= : set output type to be writte (default: '$outputType')" echo " -q, --qMaxThreshold= : set qMax threshold for clusterization (default: '$qMaxThreshold')" echo " -h, --help : show this help message" @@ -24,9 +26,11 @@ usageAndExit() { inputFile=tpcdigits.root outputType=clusters,tracks qMaxThreshold=4 +firstTimeBin=0 +lastTimeBin=500 # ===| parse command line options |============================================= -OPTIONS=$(getopt -l "inputFile:,outputType:,qMaxThreshold:,help" -o "i:o:q:h" -n "runRecoFromDigits.sh" -- "$@") +OPTIONS=$(getopt -l "inputFile:,firstTimeBin:,lastTimeBin:,outputType:,qMaxThreshold:,help" -o "i:f:l:o:q:h" -n "runRecoFromDigits.sh" -- "$@") if [ $? != 0 ] ; then usageAndExit @@ -38,6 +42,8 @@ while true; do case "$1" in --) shift; break;; -i|--inputFile) inputFile=$2; shift 2;; + -f|--firstTimeBin) firstTimeBin=$2; shift 2;; + -l|--lastTimeBin) lastTimeBin=$2; shift 2;; -o|--outputType) outputType=$2; shift 2;; -q|--qMaxThreshold) qMaxThreshold=$2; shift 2;; -h|--help) usageAndExit;; @@ -48,6 +54,6 @@ done # ===| check for required arguments |=========================================== # ===| command building and execution |========================================= -cmd="o2-tpc-reco-workflow -b --infile $inputFile --disable-mc --configKeyValues 'TPCHwClusterer.peakChargeThreshold=$qMaxThreshold;TPCHwClusterer.isContinuousReadout=0' --output-type $outputType" +cmd="o2-tpc-reco-workflow -b --infile $inputFile --disable-mc --configKeyValues 'TPCHwClusterer.peakChargeThreshold=$qMaxThreshold;TPCHwClusterer.isContinuousReadout=0;TPCHwClusterer.firstTimeBin=$firstTimeBin;TPCHwClusterer.lastTimeBin=$lastTimeBin' --output-type $outputType" echo $cmd eval $cmd diff --git a/Detectors/TPC/reconstruction/src/HwClusterer.cxx b/Detectors/TPC/reconstruction/src/HwClusterer.cxx index 7563493069368..de41dcc290eba 100644 --- a/Detectors/TPC/reconstruction/src/HwClusterer.cxx +++ b/Detectors/TPC/reconstruction/src/HwClusterer.cxx @@ -35,7 +35,9 @@ HwClusterer::HwClusterer( mCurrentMcContainerInBuffer(0), mSplittingMode(0), mClusterSector(sectorid), - mLastTimebin(-1), + mPreviousTimebin(-1), + mFirstTimebin(0), + mLastTimebin(200000), mLastHB(0), mPeakChargeThreshold(2), mContributionChargeThreshold(0), @@ -117,6 +119,8 @@ void HwClusterer::init() mPeakChargeThreshold = param.peakChargeThreshold; mContributionChargeThreshold = param.contributionChargeThreshold; + mFirstTimebin = param.firstTimeBin; + mLastTimebin = param.lastTimeBin; mSplittingMode = param.splittingMode; mIsContinuousReadout = param.isContinuousReadout; mRejectSinglePadClusters = param.rejectSinglePadClusters; @@ -158,14 +162,22 @@ void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, MCLabel * already done. */ - if (digit.getTimeStamp() != mLastTimebin) { + const auto timeBin = digit.getTimeStamp(); + + if (timeBin < mFirstTimebin) { + continue; + } else if (timeBin > mLastTimebin) { + break; + } + + if (timeBin != mPreviousTimebin) { /* * If the timebin changes, it could change by more then just 1 (not every * timebin has digits). Since the tmp storage covers mTimebinsInBuffer, * at most mTimebinsInBuffer new timebins need to be prepared and checked * for clusters. */ - for (int i = mLastTimebin; (i < digit.getTimeStamp()) && (i - mLastTimebin < mTimebinsInBuffer); ++i) { + for (int i = mPreviousTimebin; (i < timeBin) && (i - mPreviousTimebin < mTimebinsInBuffer); ++i) { /* * If the HB of the cluster which will be found in a few lines, NOT the @@ -190,7 +202,7 @@ void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, MCLabel * doens't matter. * * If mTimebinsInBuffer would be 5 and i 5 is the new digit timebin (4 - * would be mLastTimebin), then 0 is the oldest one timebin and will to + * would be mPreviousTimebin), then 0 is the oldest one timebin and will to * be replaced by the new arriving one. The cluster which could be * found, would then range from timebin 0 to 4 and has its center at * timebin 2. Threrefore we are looking in (i - 2) for clusters and @@ -216,36 +228,38 @@ void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, MCLabel // the original pointer could already point to the next container. if (mcDigitTruth) { if (mCurrentMcContainerInBuffer == 0) { - mMCtruth[mapTimeInRange(digit.getTimeStamp())] = std::make_shared<MCLabelContainer const>(*mcDigitTruth); + mMCtruth[mapTimeInRange(timeBin)] = std::make_shared<MCLabelContainer const>(*mcDigitTruth); } else { - mMCtruth[mapTimeInRange(digit.getTimeStamp())] = std::shared_ptr<MCLabelContainer const>(mMCtruth[getFirstSetBitOfField()]); + mMCtruth[mapTimeInRange(timeBin)] = std::shared_ptr<MCLabelContainer const>(mMCtruth[getFirstSetBitOfField()]); } - mCurrentMcContainerInBuffer |= (0x1 << (mapTimeInRange(digit.getTimeStamp()))); + mCurrentMcContainerInBuffer |= (0x1 << (mapTimeInRange(timeBin))); } } /* * add current digit to storage */ - index = mapTimeInRange(digit.getTimeStamp()) * mPadsPerRowSet[mGlobalRowToRowSet[digit.getRow()]] + (digit.getPad() + 2); + const auto row = digit.getRow(); + const auto pad = digit.getPad(); + index = mapTimeInRange(timeBin) * mPadsPerRowSet[mGlobalRowToRowSet[row]] + (pad + 2); // offset of digit pad because of 2 empty pads on both sides float charge = digit.getChargeFloat(); // TODO: fill noise here as well if necessary if (mPedestalObject) { - charge -= mPedestalObject->getValue(CRU(digit.getCRU()), digit.getRow(), digit.getPad()); + charge -= mPedestalObject->getValue(CRU(digit.getCRU()), row, pad); } /* * charge could be smaller than 0 due to pedestal subtraction, if so set it to zero * noise thresholds for zero suppression could also be done here ... */ - mDataBuffer[mGlobalRowToRowSet[digit.getRow()]][index][mGlobalRowToVcIndex[digit.getRow()]] = + mDataBuffer[mGlobalRowToRowSet[row]][index][mGlobalRowToVcIndex[row]] = charge < 0 ? 0 : ((charge < float(0x3FFF) / (1 << 4)) ? (charge * (1 << 4)) : 0x3FFF); - mIndexBuffer[mGlobalRowToRowSet[digit.getRow()]][index][mGlobalRowToVcIndex[digit.getRow()]] = digitIndex++; + mIndexBuffer[mGlobalRowToRowSet[row]][index][mGlobalRowToVcIndex[row]] = digitIndex++; - mLastTimebin = digit.getTimeStamp(); + mPreviousTimebin = timeBin; } if (!mIsContinuousReadout) { @@ -810,7 +824,7 @@ void HwClusterer::finishFrame(bool clear) { unsigned HB; // Search in last remaining timebins for clusters - for (int i = mLastTimebin; i - mLastTimebin < mTimebinsInBuffer; ++i) { + for (int i = mPreviousTimebin; i - mPreviousTimebin < mTimebinsInBuffer; ++i) { HB = i < 3 ? 0 : (i - 3) / 447; // integer division on purpose if (HB != mLastHB) { writeOutputWithTimeOffset(mLastHB * 447); From 947a0662bfd5eb0ae13883bd007b0697ddc744f8 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 31 Jul 2020 14:38:52 +0200 Subject: [PATCH 0256/1751] possibility to display a time bin range also fix offset calculation in the binning --- .../TPC/monitor/macro/RunSimpleEventDisplay.C | 6 +++--- Detectors/TPC/monitor/macro/startMonitor | 14 ++++++++++---- Detectors/TPC/monitor/src/SimpleEventDisplay.cxx | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C b/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C index 1a3bf2e49e3bb..7d203bae30596 100644 --- a/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C +++ b/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C @@ -337,7 +337,7 @@ void DrawPadSignal(TString type) //mRawReader->Reset(); TH1D* h2 = mEvDisp.makePadSignals(roc, row, pad); if (h2) { - h2->GetXaxis()->SetRangeUser(0, mEvDisp.getNumberOfProcessedTimeBins() + 5); + //h2->GetXaxis()->SetRangeUser(0, mEvDisp.getNumberOfProcessedTimeBins() + 5); h2->Draw(); h2->SetStats(0); @@ -601,7 +601,7 @@ void CallEventNumber() } //__________________________________________________________________________ -void RunSimpleEventDisplay(TString fileInfo, TString pedestalFile = "", Int_t nTimeBinsPerCall = 500, uint32_t verbosity = 0, uint32_t debugLevel = 0, int selectedSector = 0, bool showSides = 0) +void RunSimpleEventDisplay(TString fileInfo, TString pedestalFile = "", Int_t firstTimeBin = 0, Int_t lastTimeBin = 500, Int_t nTimeBinsPerCall = 500, uint32_t verbosity = 0, uint32_t debugLevel = 0, int selectedSector = 0, bool showSides = 0) { FairLogger* logger = FairLogger::GetLogger(); logger->SetLogVerbosityLevel("LOW"); @@ -623,7 +623,7 @@ void RunSimpleEventDisplay(TString fileInfo, TString pedestalFile = "", Int_t nT mEvDisp.setSelectedSector(mSelectedSector); mEvDisp.setLastSelSector(mSelectedSector); mEvDisp.setTimeBinsPerCall(nTimeBinsPerCall); - mEvDisp.setTimeBinRange(0, nTimeBinsPerCall); + mEvDisp.setTimeBinRange(firstTimeBin, lastTimeBin); InitGUI(); // while (mRawReader->NextEvent() && mRawReader->GetEventFromTag()==0) Next(); diff --git a/Detectors/TPC/monitor/macro/startMonitor b/Detectors/TPC/monitor/macro/startMonitor index c8f93fa684195..2ed32d5aa6fdc 100755 --- a/Detectors/TPC/monitor/macro/startMonitor +++ b/Detectors/TPC/monitor/macro/startMonitor @@ -13,7 +13,9 @@ usage() { echo echo "optional arguments:" echo " -p, --pedestalFile= : pedestal file" - echo " -t, --timeBins= : number of time bins to process (default: 1000)" + echo " -f, --fistTimeBin= : first time bin for pulser search" + echo " -l, --lastTimeBin= : last time bin for pulser search" + echo " -t, --timeBins= : number of time bins to process (default: $timeBins)" echo " -v, --verbosity= : set verbosity level" echo " -d, --debugLevel= : set debug level" echo " -s, --sector= : select specific sector (default 0)" @@ -33,14 +35,16 @@ usageAndExit() { # ===| default variable values |================================================ fileInfo= pedestalFile= -timeBins=1000 +firstTimeBin=0 +lastTimeBin=512 +timeBins=512 verbosity=0 debugLevel=0 selectedSector=0 showOverview=0 # ===| parse command line options |============================================= -OPTIONS=$(getopt -l "fileInfo:,pedestalFile:,timeBins:,verbosity:,debugLevel:,sector:,overview,help" -o "i:p:t:v:d:s:oh" -n "startMonitor" -- "$@") +OPTIONS=$(getopt -l "fileInfo:,pedestalFile:,firstTimeBin:,lastTimeBin:,timeBins:,verbosity:,debugLevel:,sector:,overview,help" -o "i:p:f:l:t:v:d:s:oh" -n "startMonitor" -- "$@") if [ $? != 0 ] ; then usageAndExit @@ -53,6 +57,8 @@ while true; do --) shift; break;; -i|--fileInfo) fileInfo=$2; shift 2;; -p|--pedestalFile) pedestalFile=$2; shift 2;; + -f|--firstTimeBin) firstTimeBin=$2; shift 2;; + -l|--lastTimeBin) lastTimeBin=$2; shift 2;; -t|--timeBins) timeBins=$2; shift 2;; -v|--verbosity) verbosity=$2; shift 2;; -d|--debugLevel) debugLevel=$2; shift 2;; @@ -79,6 +85,6 @@ fi # ===| command building and execution |========================================= #cmd="valgrind --log-file=valgrind.log root.exe -l $O2_SRC/Detectors/TPC/reconstruction/macro/addInclude.C $O2_SRC/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C+g'(\"$fileInfo\",\"$pedestalFile\",$timeBins,$verbosity,$debugLevel,$selectedSector,$showOverview)'" -cmd="root.exe -l $O2_SRC/Detectors/TPC/reconstruction/macro/addInclude.C $O2_SRC/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C+g'(\"$fileInfo\",\"$pedestalFile\",$timeBins,$verbosity,$debugLevel,$selectedSector,$showOverview)'" +cmd="root.exe -l $O2_SRC/Detectors/TPC/reconstruction/macro/addInclude.C $O2_SRC/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C+g'(\"$fileInfo\", \"$pedestalFile\", $firstTimeBin, $lastTimeBin, $timeBins, $verbosity, $debugLevel, $selectedSector, $showOverview)'" echo "running: $cmd" eval $cmd diff --git a/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx b/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx index 8347edf8e02f2..77f02a12b537b 100644 --- a/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx +++ b/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx @@ -135,7 +135,7 @@ Int_t SimpleEventDisplay::updateROC(const Int_t roc, //fill signals for current pad if (mCurrentROC % 36 == mSelectedSector % 36) { const Int_t nbins = mLastTimeBin - mFirstTimeBin; - const Int_t offset = (nbins + 2) * (iChannel + 1) + timeBin + 1; + const Int_t offset = (nbins + 2) * (iChannel + 1) + (timeBin - mFirstTimeBin) + 1; if ((UInt_t)roc < mTPCmapper.getNumberOfIROCs()) { mHSigIROC->GetArray()[offset] = corrSignal; From be40bcb2281612c110c529b866bcc90e578d8a69 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 31 Jul 2020 15:18:35 +0200 Subject: [PATCH 0257/1751] make independent of RDH version --- Detectors/TPC/reconstruction/CMakeLists.txt | 3 ++- Detectors/TPC/reconstruction/src/RawReaderCRU.cxx | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/reconstruction/CMakeLists.txt b/Detectors/TPC/reconstruction/CMakeLists.txt index c07c02f16e0d3..e7456f146032a 100644 --- a/Detectors/TPC/reconstruction/CMakeLists.txt +++ b/Detectors/TPC/reconstruction/CMakeLists.txt @@ -28,7 +28,8 @@ o2_add_library(TPCReconstruction src/TPCFastTransformHelperO2.cxx src/CTFCoder.cxx PUBLIC_LINK_LIBRARIES FairRoot::Base O2::SimulationDataFormat - O2::TPCBase O2::GPUTracking) + O2::TPCBase O2::GPUTracking + O2::DetectorsRaw) o2_target_root_dictionary( TPCReconstruction diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index aae19e5179e1d..b60ffee7c4353 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -188,7 +188,7 @@ int RawReaderCRU::scanFile() // std::vector<PacketDescriptor> mPacketDescriptorMap; //const uint64_t RDH_HEADERWORD0 = 0x1ea04003; //const uint64_t RDH_HEADERWORD0 = 0x00004003; - const uint64_t RDH_HEADERWORD0 = 0x00004000 + RDHUtils::getVersion<o2::header::RAWDataHeader>(); + const uint64_t RDH_HEADERWORD0 = 0x00004000; // + RDHUtils::getVersion<o2::header::RAWDataHeader>(); std::ifstream& file = mFileHandle; if (!file.is_open()) { @@ -287,7 +287,7 @@ int RawReaderCRU::scanFile() // * create the packet descriptor // * set the mLinkPresent flag // - if ((rdh.word0 & 0x0000FFFF) == RDH_HEADERWORD0) { + if ((rdh.word0 & 0x0000FFF0) == RDH_HEADERWORD0) { // non 0 stop bit means data with payload if (RDHUtils::getStop(rdh) == 0) { mPacketDescriptorMaps[globalLinkID].emplace_back(currentPos, mCRU, linkID, dataWrapperID, memorySize, packetSize); From 1e45350fa280f29dd1cb6b7eb0b6ff4d4b8fdc33 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 31 Jul 2020 15:19:08 +0200 Subject: [PATCH 0258/1751] add operator+ and - --- Detectors/TPC/base/include/TPCBase/CalDet.h | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Detectors/TPC/base/include/TPCBase/CalDet.h b/Detectors/TPC/base/include/TPCBase/CalDet.h index 6e4511d0839c1..bfc68b5eb5855 100644 --- a/Detectors/TPC/base/include/TPCBase/CalDet.h +++ b/Detectors/TPC/base/include/TPCBase/CalDet.h @@ -41,6 +41,8 @@ class CalDet public: CalDet() = default; + CalDet(CalDet const&) = default; + CalDet& operator=(CalDet const&) = default; ~CalDet() = default; CalDet(PadSubset padSusbset) : mName{"PadCalibrationObject"}, mData{}, mPadSubset{padSusbset} { initData(); } @@ -82,6 +84,12 @@ class CalDet const CalDet& operator*=(const T& val); const CalDet& operator/=(const T& val); + template <class U> + friend CalDet<U> operator+(const CalDet<U>&, const CalDet<U>&); + + template <class U> + friend CalDet<U> operator-(const CalDet<U>&, const CalDet<U>&); + private: std::string mName; ///< name of the object std::vector<CalType> mData; ///< internal CalArrays @@ -282,6 +290,23 @@ inline const CalDet<T>& CalDet<T>::operator/=(const T& val) return *this; } +//______________________________________________________________________________ +template <class T> +CalDet<T> operator+(const CalDet<T>& c1, const CalDet<T>& c2) +{ + CalDet<T> ret(c1); + ret += c2; + return ret; +} + +//______________________________________________________________________________ +template <class T> +CalDet<T> operator-(const CalDet<T>& c1, const CalDet<T>& c2) +{ + CalDet<T> ret(c1); + ret -= c2; + return ret; +} // ===| Full detector initialisation |========================================== template <class T> void CalDet<T>::initData() From 26ea055645126fb41249c55d6eb276f89c60d903 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 31 Jul 2020 15:20:28 +0200 Subject: [PATCH 0259/1751] add missing const --- Detectors/TPC/base/src/Utils.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Detectors/TPC/base/src/Utils.cxx b/Detectors/TPC/base/src/Utils.cxx index 29cc54afbabf4..afffced098dcd 100644 --- a/Detectors/TPC/base/src/Utils.cxx +++ b/Detectors/TPC/base/src/Utils.cxx @@ -174,7 +174,7 @@ void utils::mergeCalPads(std::string_view outputFileName, std::string_view input { using namespace o2::tpc; - auto calPadNamesVec = utils::tokenize(calPadNames, ","); + const auto calPadNamesVec = utils::tokenize(calPadNames, ","); std::string_view cmd = "ls"; if (inputFileNames.rfind(".root") == std::string_view::npos) { @@ -230,4 +230,3 @@ TChain* utils::buildChain(std::string_view command, std::string_view treeName, s return c; } - From b49b52a0089e6b624492ded122f1a671df6f8f7a Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 31 Jul 2020 15:21:16 +0200 Subject: [PATCH 0260/1751] extend calibration data drawing functionality --- Detectors/TPC/base/include/TPCBase/Painter.h | 27 ++++++ Detectors/TPC/base/src/Painter.cxx | 95 ++++++++++++++------ 2 files changed, 96 insertions(+), 26 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/Painter.h b/Detectors/TPC/base/include/TPCBase/Painter.h index 41b1b87f224f1..bab3d989180ee 100644 --- a/Detectors/TPC/base/include/TPCBase/Painter.h +++ b/Detectors/TPC/base/include/TPCBase/Painter.h @@ -57,6 +57,19 @@ TCanvas* draw(const CalDet<T>& calDet, int nbins1D = 300, float xMin1D = 0, floa template <class T> TCanvas* draw(const CalArray<T>& calArray); +/// fill existing 2D histogram for CalDet object +/// \param h2D histogram to fill +/// \param CalDet object with data +/// \param side side which to get the histogram for +template <class T> +void fillHistogram2D(TH2& h2D, const CalDet<T>& calDet, Side side); + +/// fill existing 2D histogram for CalArray object +/// \param h2D histogram to fill +/// \param CalArray object with data +template <class T> +void fillHistogram2D(TH2& h2D, const CalArray<T>& calArray); + /// get 2D histogram for CalDet object /// \param CalDet object with data /// \param side side which to get the histogram for @@ -84,6 +97,20 @@ TH2* getHistogram2D(const CalArray<T>& calArray); template <class T> std::vector<TCanvas*> makeSummaryCanvases(const CalDet<T>& calDet, int nbins1D = 300, float xMin1D = 0, float xMax1D = 0, bool onlyFilled = true); +/// Create summary canvases for a CalDet object +/// +/// 1 Canvas with 2D and 1D distributions for each side +/// 1 Canvas with 2D distributions for all ROCs +/// 1 Canvas with 1D distributions for all ROCs +/// \param CalDet object to draw +/// \param nbins1D number of bins used for the 1D projections +/// \param xMin1D minimum value for 1D distribution (xMin = 0 and xMax = 0 for auto scaling) +/// \param xMax1D maximum value for 1D distribution (xMin = 0 and xMax = 0 for auto scaling) +/// \param fileName input file name +/// \param calPadNames comma separated list of names of the CalPad objects as stored in the file. +/// \return TCanvas containing CalDet content +std::vector<TCanvas*> makeSummaryCanvases(const std::string_view fileName, const std::string_view calPadNames, int nbins1D = 300, float xMin1D = 0, float xMax1D = 0, bool onlyFilled = true); + } // namespace painter } // namespace tpc diff --git a/Detectors/TPC/base/src/Painter.cxx b/Detectors/TPC/base/src/Painter.cxx index 7a4d2ed8e42a3..934e6d29165ef 100644 --- a/Detectors/TPC/base/src/Painter.cxx +++ b/Detectors/TPC/base/src/Painter.cxx @@ -24,6 +24,7 @@ #include "TPCBase/CalDet.h" #include "TPCBase/CalArray.h" #include "TPCBase/Painter.h" +#include "TPCBase/Utils.h" using namespace o2::tpc; @@ -129,34 +130,66 @@ TCanvas* painter::draw(const CalArray<T>& calArray) //______________________________________________________________________________ template <class T> -TH2* painter::getHistogram2D(const CalDet<T>& calDet, Side side) +void painter::fillHistogram2D(TH2& h2D, const CalDet<T>& calDet, Side side) { static const Mapper& mapper = Mapper::instance(); - const auto title = calDet.getName().c_str(); - std::string name = calDet.getName(); - std::replace(name.begin(), name.end(), ' ', '_'); - const char side_name = (side == Side::A) ? 'A' : 'C'; - - auto h2D = new TH2F(Form("h_%cside_2D_%s", side_name, name.c_str()), - Form("%s (%c-Side);x (cm);y (cm)", title, side_name), - 300, -300, 300, 300, -300, 300); - for (ROC roc; !roc.looped(); ++roc) { - if (roc.side() != side) + if (roc.side() != side) { continue; + } + const int nrows = mapper.getNumberOfRowsROC(roc); for (int irow = 0; irow < nrows; ++irow) { const int npads = mapper.getNumberOfPadsInRowROC(roc, irow); for (int ipad = 0; ipad < npads; ++ipad) { const auto val = calDet.getValue(roc, irow, ipad); const GlobalPosition2D pos = mapper.getPadCentre(PadROCPos(roc, irow, ipad)); - const int bin = h2D->FindBin(pos.X(), pos.Y()); - if (!h2D->GetBinContent(bin)) - h2D->SetBinContent(bin, val); + const int bin = h2D.FindBin(pos.X(), pos.Y()); + if (!h2D.GetBinContent(bin)) { + h2D.SetBinContent(bin, val); + } } } } +} + +//______________________________________________________________________________ +template <class T> +void painter::fillHistogram2D(TH2& h2D, const CalArray<T>& calArray) +{ + static const Mapper& mapper = Mapper::instance(); + + const size_t position = calArray.getPadSubsetNumber(); + const PadSubset padSubset = calArray.getPadSubset(); + const int nrows = mapper.getNumberOfPadRows(padSubset, position); + + // ===| fill hist |=========================================================== + for (int irow = 0; irow < nrows; ++irow) { + const int padsInRow = mapper.getNumberOfPadsInRow(padSubset, position, irow); + for (int ipad = 0; ipad < padsInRow; ++ipad) { + const GlobalPadNumber pad = mapper.getPadNumber(padSubset, position, irow, ipad); + const auto val = calArray.getValue(pad); + const int cpad = ipad - padsInRow / 2; + h2D.Fill(irow, cpad, val); + } + } +} + +//______________________________________________________________________________ +template <class T> +TH2* painter::getHistogram2D(const CalDet<T>& calDet, Side side) +{ + const auto title = calDet.getName().c_str(); + std::string name = calDet.getName(); + std::replace(name.begin(), name.end(), ' ', '_'); + const char side_name = (side == Side::A) ? 'A' : 'C'; + + auto h2D = new TH2F(Form("h_%cside_2D_%s", side_name, name.c_str()), + Form("%s (%c-Side);x (cm);y (cm)", title, side_name), + 300, -300, 300, 300, -300, 300); + + fillHistogram2D(*h2D, calDet, side); return h2D; } @@ -168,8 +201,8 @@ TH2* painter::getHistogram2D(const CalArray<T>& calArray) static const Mapper& mapper = Mapper::instance(); const size_t position = calArray.getPadSubsetNumber(); - const PadSubset padSubset = calArray.getPadSubset(); + // ===| maximum number of rows and pads |===================================== const int nrows = mapper.getNumberOfPadRows(padSubset, position); const int npads = mapper.getNumberOfPadsInRow(padSubset, position, nrows - 1) + 6; @@ -183,17 +216,8 @@ TH2* painter::getHistogram2D(const CalArray<T>& calArray) nrows, 0., nrows, npads, -npads / 2, npads / 2); - // ===| fill hist |=========================================================== - for (int irow = 0; irow < nrows; ++irow) { - const int padsInRow = mapper.getNumberOfPadsInRow(padSubset, position, irow); - for (int ipad = 0; ipad < padsInRow; ++ipad) { - const GlobalPadNumber pad = mapper.getPadNumber(padSubset, position, irow, ipad); - const auto val = calArray.getValue(pad); - const int cpad = ipad - padsInRow / 2; - hist->Fill(irow, cpad, val); - //printf("%d %d: %f\n", irow, cpad, (double)val); - } - } + fillHistogram2D(*hist, calArray); + return hist; } @@ -280,6 +304,25 @@ std::vector<TCanvas*> painter::makeSummaryCanvases(const CalDet<T>& calDet, int return vecCanvases; } +//============================================================================== +std::vector<TCanvas*> painter::makeSummaryCanvases(const std::string_view fileName, const std::string_view calPadNames, int nbins1D, float xMin1D, float xMax1D, bool onlyFilled) +{ + using namespace o2::tpc; + + const auto calPads = utils::readCalPads(fileName, calPadNames); + + std::vector<TCanvas*> vecCanvases; + + for (const auto calPad : calPads) { + auto canvases = makeSummaryCanvases(*calPad, nbins1D, xMin1D, xMax1D, onlyFilled); + for (auto c : canvases) { + vecCanvases.emplace_back(c); + } + } + + return vecCanvases; +} + // ===| explicit instantiations |=============================================== // this is required to force the compiler to create instances with the types // we usually would like to deal with From 37179171502f8667012a485a6fdd59865251c46d Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 4 Aug 2020 09:28:54 +0200 Subject: [PATCH 0261/1751] Avoid printf and use LOG(DEBUG) instead --- .../tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx | 2 +- .../TPC/calibration/SpacePoints/src/TrackInterpolation.cxx | 4 ++-- Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx index 314ccf03b0ae8..11d6c64c14fdd 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx @@ -162,7 +162,7 @@ void TPCInterpolationDPL::run(ProcessingContext& pc) // not yet implemented } - printf("TPC Interpolation Workflow initialized. Start processing...\n"); + LOG(INFO) << "TPC Interpolation Workflow initialized. Start processing..."; mInterpolation.process(); diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index 1956fdbfdc446..cc69d9cb61b56 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -123,12 +123,12 @@ bool TrackInterpolation::trackPassesQualityCuts(const o2::dataformats::TrackTPCI // track has a match in TRD or TOF if (trkTPC.getNClusterReferences() < param::MinTPCNCls || trkITS.getNumberOfClusters() < param::MinITSNCls) { - printf("TPC clusters (%i), ITS clusters(%i)\n", trkTPC.getNClusterReferences(), trkITS.getNumberOfClusters()); + LOG(DEBUG) << "TPC clusters (" << trkTPC.getNClusterReferences() << "), ITS clusters(" << trkITS.getNumberOfClusters() << ")"; return false; } if (trkTPC.getChi2() / trkTPC.getNClusterReferences() > param::MaxTPCChi2 || trkITS.getChi2() / trkITS.getNumberOfClusters() > param::MaxITSChi2) { - printf("TPC reduced chi2 (%.2f), ITS reduced chi2 (%.2f)\n", trkTPC.getChi2() / trkTPC.getNClusterReferences(), trkITS.getChi2() / trkITS.getNumberOfClusters()); + LOG(DEBUG) << "TPC reduced chi2 (" << trkTPC.getChi2() / trkTPC.getNClusterReferences() << "), ITS reduced chi2 (" << trkITS.getChi2() / trkITS.getNumberOfClusters() << ")"; return false; } } else { diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx index dc610f2a9efe7..160340066159f 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx @@ -510,8 +510,8 @@ void TrackResiduals::buildLocalResidualTreesFromRun2Data() fillLocalResidualsTrees(); } - printf("Rejected due to Nclusters(%i), HelixFit(%i), qpt(%i), validation(%i)\n", nRejCl, nRejHelix, nRejQpt, nRejValidation); - printf("validation failed %i times because of fraction of rej. cls and %i times because of rms and %i rest\n", counterTrkValidation[1], counterTrkValidation[2], counterTrkValidation[0]); + //printf("Rejected due to Nclusters(%i), HelixFit(%i), qpt(%i), validation(%i)\n", nRejCl, nRejHelix, nRejQpt, nRejValidation); + //printf("validation failed %i times because of fraction of rej. cls and %i times because of rms and %i rest\n", counterTrkValidation[1], counterTrkValidation[2], counterTrkValidation[0]); LOG(info) << "Accepted " << nTracksSelected << " tracks. With outliers it would be " << nTracksSelectedWithOutliers; dumpTracks(debugOutliers); writeLocalResidualTreesToFile(); From 7f0e56dd748537bbdf16af88a9211ea047e6f715 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Mon, 3 Aug 2020 23:55:14 +0200 Subject: [PATCH 0262/1751] changing printf to LOG more changes changing format clang --- Detectors/GlobalTracking/src/MatchTOF.cxx | 26 ++++++++--------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index fff40892e56ff..0afa155d8f395 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -57,9 +57,7 @@ void MatchTOF::run() prepareTOFClusters(); mTimerTot.Stop(); - printf("Timing:\n"); - printf("prepareTOFCluster: "); - mTimerTot.Print(); + LOGF(INFO, "Timing prepareTOFCluster: Cpu: %.3e s Real: %.3e s in %d slots", mTimerTot.CpuTime(), mTimerTot.RealTime(), mTimerTot.Counter() - 1); mTimerTot.Start(); if (mIsworkflowON) { @@ -71,9 +69,7 @@ void MatchTOF::run() prepareTracks(); mTimerTot.Stop(); - printf("Timing:\n"); - printf("prepare tracks: "); - mTimerTot.Print(); + LOGF(INFO, "Timing prepare tracks: Cpu: %.3e s Real: %.3e s in %d slots", mTimerTot.CpuTime(), mTimerTot.RealTime(), mTimerTot.Counter() - 1); mTimerTot.Start(); for (int sec = o2::constants::math::NSectors; sec--;) { @@ -99,9 +95,7 @@ void MatchTOF::run() prepareTracks(); mTimerTot.Stop(); - printf("Timing:\n"); - printf("prepare tracks: "); - mTimerTot.Print(); + LOGF(INFO, "Timing prepare tracks: Cpu: %.3e s Real: %.3e s in %d slots", mTimerTot.CpuTime(), mTimerTot.RealTime(), mTimerTot.Counter() - 1); mTimerTot.Start(); /* Uncomment for local debug @@ -146,9 +140,7 @@ void MatchTOF::run() mWFInputAttached = false; mTimerTot.Stop(); - printf("Timing:\n"); - printf("Do Matching: "); - mTimerTot.Print(); + LOGF(INFO, "Timing Do Matching: Cpu: %.3e s Real: %.3e s in %d slots", mTimerTot.CpuTime(), mTimerTot.RealTime(), mTimerTot.Counter() - 1); } //______________________________________________ @@ -255,7 +247,7 @@ void MatchTOF::printCandidatesTOF() const void MatchTOF::attachInputTrees() { ///< attaching the input tree - printf("attachInputTrees\n"); + LOG(DEBUG) << "attachInputTrees"; if (!mInputTreeTracks) { LOG(FATAL) << "Input tree with tracks is not set"; } @@ -339,7 +331,7 @@ bool MatchTOF::prepareTracks() auto o2field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); float bzField = o2field->solenoidField(); // magnetic field in kGauss - Printf("\n\nWe have %d tracks to try to match to TOF", mNumOfTracks); + LOG(DEBUG) << "\n\nWe have %d tracks to try to match to TOF: " << mNumOfTracks; int nNotPropagatedToTOF = 0; for (int it = 0; it < mNumOfTracks; it++) { const o2::dataformats::TrackTPCITS& trcOrig = mTracksArrayInp[it]; // TODO: check if we cannot directly use the o2::track::TrackParCov class instead of o2::dataformats::TrackTPCITS, and then avoid the casting below; this is the track at the vertex @@ -515,9 +507,9 @@ bool MatchTOF::loadTracksNextChunk() //______________________________________________ bool MatchTOF::loadTOFClustersNextChunk() { - printf("Loat clusters next chunck\n"); + LOG(DEBUG) << "Loat clusters next chunck"; ///< load next chunk of clusters to be matched to TOF - printf("Loading TOF clusters: number of entries in tree = %lld\n", mTreeTOFClusters->GetEntries()); + LOG(DEBUG) << "Loading TOF clusters: number of entries in tree = " << mTreeTOFClusters->GetEntries(); while (++mCurrTOFClustersTreeEntry < mTreeTOFClusters->GetEntries()) { mTreeTOFClusters->GetEntry(mCurrTOFClustersTreeEntry); mTOFClustersArrayInp = gsl::span<const Cluster>{*mTOFClustersArrayInpVect}; @@ -874,7 +866,7 @@ void MatchTOF::selectBestMatches() { ///< define the track-TOFcluster pair per sector - printf("Number of pair matched = %lu\n", mMatchedTracksPairs.size()); + LOG(INFO) << "Number of pair matched = " << mMatchedTracksPairs.size(); // first, we sort according to the chi2 std::sort(mMatchedTracksPairs.begin(), mMatchedTracksPairs.end(), [this](o2::dataformats::MatchInfoTOF& a, o2::dataformats::MatchInfoTOF& b) { return (a.getChi2() < b.getChi2()); }); From 205e7ed796aff1d085c0737d4a4d72556d96929e Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 4 Aug 2020 18:45:24 +0200 Subject: [PATCH 0263/1751] DPL Analysis: working fix for TrackType filter (#4090) --- Analysis/Tutorials/src/filters.cxx | 2 +- Framework/Core/include/Framework/Expressions.h | 2 +- Framework/Core/src/Expressions.cxx | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Analysis/Tutorials/src/filters.cxx b/Analysis/Tutorials/src/filters.cxx index fe33f3df1834f..122b5c290826e 100644 --- a/Analysis/Tutorials/src/filters.cxx +++ b/Analysis/Tutorials/src/filters.cxx @@ -86,7 +86,7 @@ struct CTask { }; struct DTask { - Filter notTracklet = aod::track::trackType != 3; // only works with literal now + Filter notTracklet = aod::track::trackType != static_cast<uint8_t>(aod::track::TrackTypeEnum::Run2Tracklet); void process(aod::Collision const&, soa::Filtered<aod::MTracks> const& tracks) { for (auto& track : tracks) { diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index 28badac8f4c77..0c66726f59376 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -51,7 +51,7 @@ struct LiteralStorage { using stored_pack = framework::pack<T...>; }; -using LiteralValue = LiteralStorage<int, bool, float, double>; +using LiteralValue = LiteralStorage<int, bool, float, double, uint8_t>; template <typename T> constexpr auto selectArrowType() diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 38b753875ddd6..6869b2fcad3a3 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -392,6 +392,8 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, return gandiva::TreeExprBuilder::MakeLiteral(std::get<float>(content)); if (content.index() == 3) return gandiva::TreeExprBuilder::MakeLiteral(std::get<double>(content)); + if (content.index() == 4) + return gandiva::TreeExprBuilder::MakeLiteral(std::get<uint8_t>(content)); throw std::runtime_error("Malformed LiteralNode"); } @@ -425,11 +427,11 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, return node; }; - auto insertEqualizeUpcastNode = [&](gandiva::NodePtr node1, gandiva::NodePtr node2, atype::type t1, atype::type t2) { + auto insertEqualizeUpcastNode = [&](gandiva::NodePtr& node1, gandiva::NodePtr& node2, atype::type t1, atype::type t2) { if (t2 > t1) { auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t2), {node1}, concreteArrowType(t2)); node1 = upcast; - } else { + } else if (t1 > t2) { auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t1), {node2}, concreteArrowType(t1)); node2 = upcast; } From ec0fde995e88f89dec7b512d4f92c524e145d5f1 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 4 Aug 2020 15:28:31 +0200 Subject: [PATCH 0264/1751] ConfigurableParam: fix bug when using arrays of strings --- Common/Utils/src/ConfigurableParamHelper.cxx | 27 ++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Common/Utils/src/ConfigurableParamHelper.cxx b/Common/Utils/src/ConfigurableParamHelper.cxx index 838b44cc8115c..f8fe1d16f570a 100644 --- a/Common/Utils/src/ConfigurableParamHelper.cxx +++ b/Common/Utils/src/ConfigurableParamHelper.cxx @@ -118,6 +118,24 @@ std::string getName(const TDataMember* dm, int index, int size) return namestream.str(); } +// ---------------------------------------------------------------------- +size_t getSizeOfUnderlyingType(const TDataMember& dm) +{ + auto dt = dm.GetDataType(); + if (dt) { + // if basic built-in type supported by ROOT + return dt->Size(); + } else { + // for now only catch std::string as other supported type + auto tname = dm.GetFullTypeName(); + if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { + return sizeof(std::string); + } + LOG(ERROR) << "ENCOUNTERED AN UNSUPPORTED TYPE " << tname << "IN A CONFIGURABLE PARAMETER"; + } + return 0; +} + // ---------------------------------------------------------------------- const char* asString(TDataMember const& dm, char* pointer) @@ -165,8 +183,7 @@ std::vector<ParamDataMember>* _ParamHelper::getDataMembersImpl(std::string const std::vector<ParamDataMember>* members = new std::vector<ParamDataMember>; auto toDataMember = [&members, obj, mainkey, provmap](const TDataMember* dm, int index, int size) { - auto dt = dm->GetDataType(); - auto TS = dt ? dt->Size() : 0; + auto TS = getSizeOfUnderlyingType(*dm); char* pointer = ((char*)obj) + dm->GetOffset() + index * TS; const std::string name = getName(dm, index, size); const char* value = asString(*dm, pointer); @@ -259,7 +276,7 @@ void _ParamHelper::fillKeyValuesImpl(std::string const& mainkey, TClass* cl, voi auto fillMap = [obj, &mainkey, &localtree, &keytostoragemap, &enumRegistry](const TDataMember* dm, int index, int size) { const auto name = getName(dm, index, size); auto dt = dm->GetDataType(); - auto TS = dt ? dt->Size() : 0; + auto TS = getSizeOfUnderlyingType(*dm); char* pointer = ((char*)obj) + dm->GetOffset() + index * TS; localtree.put(name, asString(*dm, pointer)); @@ -318,7 +335,7 @@ void _ParamHelper::assignmentImpl(std::string const& mainkey, TClass* cl, void* auto assignifchanged = [to, from, &mainkey, provmap](const TDataMember* dm, int index, int size) { const auto name = getName(dm, index, size); auto dt = dm->GetDataType(); - auto TS = dt ? dt->Size() : 0; + auto TS = getSizeOfUnderlyingType(*dm); char* pointerto = ((char*)to) + dm->GetOffset() + index * TS; char* pointerfrom = ((char*)from) + dm->GetOffset() + index * TS; @@ -351,7 +368,7 @@ void _ParamHelper::assignmentImpl(std::string const& mainkey, TClass* cl, void* if (!isMemblockDifferent(pointerto, pointerfrom, TS)) { updateProv(); // actually copy - std::memcpy(pointerto, pointerfrom, dt->Size()); + std::memcpy(pointerto, pointerfrom, getSizeOfUnderlyingType(*dm)); } }; loopOverMembers(cl, to, assignifchanged); From 098986c18c00e6afab48c5819b4c6f96b9dabfe3 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 4 Aug 2020 13:31:29 +0200 Subject: [PATCH 0265/1751] o2sim: create ipc socket files in tmp dir --- run/o2simtopology.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/run/o2simtopology.json b/run/o2simtopology.json index cfe8cd8234b43..8f65580a95b7b 100644 --- a/run/o2simtopology.json +++ b/run/o2simtopology.json @@ -10,7 +10,7 @@ { "type":"req", "method":"connect", - "address":"ipc://primary-get_25005", + "address":"ipc:///tmp/primary-get_25005", "sndBufSize":"100000", "rcvBufSize":"100000", "rateLogging":"0" @@ -23,7 +23,7 @@ { "type":"push", "method":"connect", - "address":"ipc://hitmerger-simdata_25009", + "address":"ipc:///tmp/hitmerger-simdata_25009", "sndBufSize":1000, "rcvBufSize":1000, "rateLogging":0 @@ -41,7 +41,7 @@ { "type":"rep", "method":"bind", - "address":"ipc://primary-get_25005", + "address":"ipc:///tmp/primary-get_25005", "sndBufSize":100000, "rcvBufSize":100000, "rateLogging":0 @@ -59,7 +59,7 @@ { "type":"req", "method":"connect", - "address":"ipc://primary-get_25005", + "address":"ipc:///tmp/primary-get_25005", "sndBufSize":"1000", "rcvBufSize":"1000", "rateLogging":"0" @@ -72,7 +72,7 @@ { "type":"pull", "method":"bind", - "address":"ipc://hitmerger-simdata_25009", + "address":"ipc:///tmp/hitmerger-simdata_25009", "sndBufSize":1000, "rcvBufSize":1000, "rateLogging":0 From ec211d42c99f57cbde55f2e0973236c12b8637c0 Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Tue, 4 Aug 2020 13:28:13 +0300 Subject: [PATCH 0266/1751] fix write last channel --- Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx index 57be45a072939..6986a709b1bca 100644 --- a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx @@ -155,7 +155,7 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, newData.time = pmchannels[ich].CFDTime; newData.generateFlags(); newData.channelID = lut.getMCP(pmchannels[ich].ChId); - // LOG(INFO) << "packed GBT " << nlink << " channelID " << (int)newData.channelID << " charge " << newData.charge << " time " << newData.time << " chain " << int(newData.numberADC) << " size " << sizeof(newData); + LOG(DEBUG) << "packed GBT " << nlink << " channelID " << (int)newData.channelID << " charge " << newData.charge << " time " << newData.time << " chain " << int(newData.numberADC) << " size " << sizeof(newData); nchannels++; } // fill mEventData[nchannels] with 0s to flag that this is a dummy data @@ -163,6 +163,10 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, if ((nchannels % 2) == 1) mRawEventData.mEventData[nchannels] = {}; mRawEventData.mEventHeader.nGBTWords = nGBTWords; + auto datalast = mRawEventData.to_vector(false); + mLinkID = uint32_t(oldlink); + mFeeID = uint64_t(oldlink); + mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, intRecord, datalast); LOG(DEBUG) << " last " << oldlink; //TCM mRawEventData.mEventHeader = makeGBTHeader(LinkTCM, intRecord); //TCM From 10eae369bd16ec178c7c590d94cc6fc4d672f5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Wed, 5 Aug 2020 15:08:01 +0200 Subject: [PATCH 0267/1751] Add detector prefix for expected values (#4088) --- Analysis/DataModel/include/PID/PIDResponse.h | 121 +++++++++++-------- Analysis/Tasks/spectraTOF.cxx | 26 ++-- Analysis/Tasks/spectraTPC.cxx | 22 ++-- 3 files changed, 95 insertions(+), 74 deletions(-) diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/PID/PIDResponse.h index dfaf5a02962f3..8227b05a0cfc7 100644 --- a/Analysis/DataModel/include/PID/PIDResponse.h +++ b/Analysis/DataModel/include/PID/PIDResponse.h @@ -45,35 +45,35 @@ DECLARE_SOA_DYNAMIC_COLUMN(DiffBetaEl, diffbetael, [](float beta, float expbetae namespace pidTOF { // Expected times -DECLARE_SOA_COLUMN(ExpTimeEl, expTimeEl, float); -DECLARE_SOA_COLUMN(ExpTimeMu, expTimeMu, float); -DECLARE_SOA_COLUMN(ExpTimePi, expTimePi, float); -DECLARE_SOA_COLUMN(ExpTimeKa, expTimeKa, float); -DECLARE_SOA_COLUMN(ExpTimePr, expTimePr, float); -DECLARE_SOA_COLUMN(ExpTimeDe, expTimeDe, float); -DECLARE_SOA_COLUMN(ExpTimeTr, expTimeTr, float); -DECLARE_SOA_COLUMN(ExpTimeHe, expTimeHe, float); -DECLARE_SOA_COLUMN(ExpTimeAl, expTimeAl, float); +DECLARE_SOA_COLUMN(TOFExpSignalEl, tofExpSignalEl, float); +DECLARE_SOA_COLUMN(TOFExpSignalMu, tofExpSignalMu, float); +DECLARE_SOA_COLUMN(TOFExpSignalPi, tofExpSignalPi, float); +DECLARE_SOA_COLUMN(TOFExpSignalKa, tofExpSignalKa, float); +DECLARE_SOA_COLUMN(TOFExpSignalPr, tofExpSignalPr, float); +DECLARE_SOA_COLUMN(TOFExpSignalDe, tofExpSignalDe, float); +DECLARE_SOA_COLUMN(TOFExpSignalTr, tofExpSignalTr, float); +DECLARE_SOA_COLUMN(TOFExpSignalHe, tofExpSignalHe, float); +DECLARE_SOA_COLUMN(TOFExpSignalAl, tofExpSignalAl, float); // Expected sigma -DECLARE_SOA_COLUMN(ExpSigmaEl, expSigmaEl, float); -DECLARE_SOA_COLUMN(ExpSigmaMu, expSigmaMu, float); -DECLARE_SOA_COLUMN(ExpSigmaPi, expSigmaPi, float); -DECLARE_SOA_COLUMN(ExpSigmaKa, expSigmaKa, float); -DECLARE_SOA_COLUMN(ExpSigmaPr, expSigmaPr, float); -DECLARE_SOA_COLUMN(ExpSigmaDe, expSigmaDe, float); -DECLARE_SOA_COLUMN(ExpSigmaTr, expSigmaTr, float); -DECLARE_SOA_COLUMN(ExpSigmaHe, expSigmaHe, float); -DECLARE_SOA_COLUMN(ExpSigmaAl, expSigmaAl, float); +DECLARE_SOA_COLUMN(TOFExpSigmaEl, tofExpSigmaEl, float); +DECLARE_SOA_COLUMN(TOFExpSigmaMu, tofExpSigmaMu, float); +DECLARE_SOA_COLUMN(TOFExpSigmaPi, tofExpSigmaPi, float); +DECLARE_SOA_COLUMN(TOFExpSigmaKa, tofExpSigmaKa, float); +DECLARE_SOA_COLUMN(TOFExpSigmaPr, tofExpSigmaPr, float); +DECLARE_SOA_COLUMN(TOFExpSigmaDe, tofExpSigmaDe, float); +DECLARE_SOA_COLUMN(TOFExpSigmaTr, tofExpSigmaTr, float); +DECLARE_SOA_COLUMN(TOFExpSigmaHe, tofExpSigmaHe, float); +DECLARE_SOA_COLUMN(TOFExpSigmaAl, tofExpSigmaAl, float); // NSigma -DECLARE_SOA_COLUMN(NSigmaEl, nSigmaEl, float); -DECLARE_SOA_COLUMN(NSigmaMu, nSigmaMu, float); -DECLARE_SOA_COLUMN(NSigmaPi, nSigmaPi, float); -DECLARE_SOA_COLUMN(NSigmaKa, nSigmaKa, float); -DECLARE_SOA_COLUMN(NSigmaPr, nSigmaPr, float); -DECLARE_SOA_COLUMN(NSigmaDe, nSigmaDe, float); -DECLARE_SOA_COLUMN(NSigmaTr, nSigmaTr, float); -DECLARE_SOA_COLUMN(NSigmaHe, nSigmaHe, float); -DECLARE_SOA_COLUMN(NSigmaAl, nSigmaAl, float); +DECLARE_SOA_COLUMN(TOFNSigmaEl, tofNSigmaEl, float); +DECLARE_SOA_COLUMN(TOFNSigmaMu, tofNSigmaMu, float); +DECLARE_SOA_COLUMN(TOFNSigmaPi, tofNSigmaPi, float); +DECLARE_SOA_COLUMN(TOFNSigmaKa, tofNSigmaKa, float); +DECLARE_SOA_COLUMN(TOFNSigmaPr, tofNSigmaPr, float); +DECLARE_SOA_COLUMN(TOFNSigmaDe, tofNSigmaDe, float); +DECLARE_SOA_COLUMN(TOFNSigmaTr, tofNSigmaTr, float); +DECLARE_SOA_COLUMN(TOFNSigmaHe, tofNSigmaHe, float); +DECLARE_SOA_COLUMN(TOFNSigmaAl, tofNSigmaAl, float); } // namespace pidTOF using namespace pidTOFbeta; @@ -84,37 +84,49 @@ DECLARE_SOA_TABLE(pidRespTOFbeta, "AOD", "pidRespTOFbeta", DiffBetaEl<Beta, ExpBetaEl>); using namespace pidTOF; DECLARE_SOA_TABLE(pidRespTOF, "AOD", "pidRespTOF", - ExpTimeEl, ExpTimeMu, ExpTimePi, ExpTimeKa, ExpTimePr, ExpTimeDe, ExpTimeTr, ExpTimeHe, ExpTimeAl, - ExpSigmaEl, ExpSigmaMu, ExpSigmaPi, ExpSigmaKa, ExpSigmaPr, ExpSigmaDe, ExpSigmaTr, ExpSigmaHe, ExpSigmaAl, - NSigmaEl, NSigmaMu, NSigmaPi, NSigmaKa, NSigmaPr, NSigmaDe, NSigmaTr, NSigmaHe, NSigmaAl); + TOFExpSignalEl, TOFExpSignalMu, TOFExpSignalPi, TOFExpSignalKa, TOFExpSignalPr, TOFExpSignalDe, TOFExpSignalTr, TOFExpSignalHe, TOFExpSignalAl, + TOFExpSigmaEl, TOFExpSigmaMu, TOFExpSigmaPi, TOFExpSigmaKa, TOFExpSigmaPr, TOFExpSigmaDe, TOFExpSigmaTr, TOFExpSigmaHe, TOFExpSigmaAl, + TOFNSigmaEl, TOFNSigmaMu, TOFNSigmaPi, TOFNSigmaKa, TOFNSigmaPr, TOFNSigmaDe, TOFNSigmaTr, TOFNSigmaHe, TOFNSigmaAl); namespace pidTPC { // Expected signals -DECLARE_SOA_COLUMN(ExpSignalEl, expSignalEl, float); -DECLARE_SOA_COLUMN(ExpSignalMu, expSignalMu, float); -DECLARE_SOA_COLUMN(ExpSignalPi, expSignalPi, float); -DECLARE_SOA_COLUMN(ExpSignalKa, expSignalKa, float); -DECLARE_SOA_COLUMN(ExpSignalPr, expSignalPr, float); -DECLARE_SOA_COLUMN(ExpSignalDe, expSignalDe, float); -DECLARE_SOA_COLUMN(ExpSignalTr, expSignalTr, float); -DECLARE_SOA_COLUMN(ExpSignalHe, expSignalHe, float); -DECLARE_SOA_COLUMN(ExpSignalAl, expSignalAl, float); +DECLARE_SOA_COLUMN(TPCExpSignalEl, tpcExpSignalEl, float); +DECLARE_SOA_COLUMN(TPCExpSignalMu, tpcExpSignalMu, float); +DECLARE_SOA_COLUMN(TPCExpSignalPi, tpcExpSignalPi, float); +DECLARE_SOA_COLUMN(TPCExpSignalKa, tpcExpSignalKa, float); +DECLARE_SOA_COLUMN(TPCExpSignalPr, tpcExpSignalPr, float); +DECLARE_SOA_COLUMN(TPCExpSignalDe, tpcExpSignalDe, float); +DECLARE_SOA_COLUMN(TPCExpSignalTr, tpcExpSignalTr, float); +DECLARE_SOA_COLUMN(TPCExpSignalHe, tpcExpSignalHe, float); +DECLARE_SOA_COLUMN(TPCExpSignalAl, tpcExpSignalAl, float); +// Expected sigma +DECLARE_SOA_COLUMN(TPCExpSigmaEl, tpcExpSigmaEl, float); +DECLARE_SOA_COLUMN(TPCExpSigmaMu, tpcExpSigmaMu, float); +DECLARE_SOA_COLUMN(TPCExpSigmaPi, tpcExpSigmaPi, float); +DECLARE_SOA_COLUMN(TPCExpSigmaKa, tpcExpSigmaKa, float); +DECLARE_SOA_COLUMN(TPCExpSigmaPr, tpcExpSigmaPr, float); +DECLARE_SOA_COLUMN(TPCExpSigmaDe, tpcExpSigmaDe, float); +DECLARE_SOA_COLUMN(TPCExpSigmaTr, tpcExpSigmaTr, float); +DECLARE_SOA_COLUMN(TPCExpSigmaHe, tpcExpSigmaHe, float); +DECLARE_SOA_COLUMN(TPCExpSigmaAl, tpcExpSigmaAl, float); // NSigma -DECLARE_SOA_COLUMN(NSigmaEl, nSigmaEl, float); -DECLARE_SOA_COLUMN(NSigmaMu, nSigmaMu, float); -DECLARE_SOA_COLUMN(NSigmaPi, nSigmaPi, float); -DECLARE_SOA_COLUMN(NSigmaKa, nSigmaKa, float); -DECLARE_SOA_COLUMN(NSigmaPr, nSigmaPr, float); -DECLARE_SOA_COLUMN(NSigmaDe, nSigmaDe, float); -DECLARE_SOA_COLUMN(NSigmaTr, nSigmaTr, float); -DECLARE_SOA_COLUMN(NSigmaHe, nSigmaHe, float); -DECLARE_SOA_COLUMN(NSigmaAl, nSigmaAl, float); +DECLARE_SOA_COLUMN(TPCNSigmaEl, tpcNSigmaEl, float); +DECLARE_SOA_COLUMN(TPCNSigmaMu, tpcNSigmaMu, float); +DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNSigmaPi, float); +DECLARE_SOA_COLUMN(TPCNSigmaKa, tpcNSigmaKa, float); +DECLARE_SOA_COLUMN(TPCNSigmaPr, tpcNSigmaPr, float); +DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNSigmaDe, float); +DECLARE_SOA_COLUMN(TPCNSigmaTr, tpcNSigmaTr, float); +DECLARE_SOA_COLUMN(TPCNSigmaHe, tpcNSigmaHe, float); +DECLARE_SOA_COLUMN(TPCNSigmaAl, tpcNSigmaAl, float); } // namespace pidTPC +using namespace pidTPC; DECLARE_SOA_TABLE(pidRespTPC, "AOD", "pidRespTPC", - pidTPC::ExpSignalEl, pidTPC::ExpSignalMu, pidTPC::ExpSignalPi, pidTPC::ExpSignalKa, pidTPC::ExpSignalPr, pidTPC::ExpSignalDe, pidTPC::ExpSignalTr, pidTPC::ExpSignalHe, pidTPC::ExpSignalAl, - pidTPC::NSigmaEl, pidTPC::NSigmaMu, pidTPC::NSigmaPi, pidTPC::NSigmaKa, pidTPC::NSigmaPr, pidTPC::NSigmaDe, pidTPC::NSigmaTr, pidTPC::NSigmaHe, pidTPC::NSigmaAl); + TPCExpSignalEl, TPCExpSignalMu, TPCExpSignalPi, TPCExpSignalKa, TPCExpSignalPr, TPCExpSignalDe, TPCExpSignalTr, TPCExpSignalHe, TPCExpSignalAl, + TPCExpSigmaEl, TPCExpSigmaMu, TPCExpSigmaPi, TPCExpSigmaKa, TPCExpSigmaPr, TPCExpSigmaDe, TPCExpSigmaTr, TPCExpSigmaHe, TPCExpSigmaAl, + TPCNSigmaEl, TPCNSigmaMu, TPCNSigmaPi, TPCNSigmaKa, TPCNSigmaPr, TPCNSigmaDe, TPCNSigmaTr, TPCNSigmaHe, TPCNSigmaAl); } // namespace o2::aod @@ -198,6 +210,15 @@ struct pidTPCTask { resp.GetExpectedSignal(PID::Triton), resp.GetExpectedSignal(PID::Helium3), resp.GetExpectedSignal(PID::Alpha), + resp.GetExpectedSigma(PID::Electron), + resp.GetExpectedSigma(PID::Muon), + resp.GetExpectedSigma(PID::Pion), + resp.GetExpectedSigma(PID::Kaon), + resp.GetExpectedSigma(PID::Proton), + resp.GetExpectedSigma(PID::Deuteron), + resp.GetExpectedSigma(PID::Triton), + resp.GetExpectedSigma(PID::Helium3), + resp.GetExpectedSigma(PID::Alpha), resp.GetNumberOfSigmas(PID::Electron), resp.GetNumberOfSigmas(PID::Muon), resp.GetNumberOfSigmas(PID::Pion), diff --git a/Analysis/Tasks/spectraTOF.cxx b/Analysis/Tasks/spectraTOF.cxx index 0ceab235380c5..fe3b8740c1b7d 100644 --- a/Analysis/Tasks/spectraTOF.cxx +++ b/Analysis/Tasks/spectraTOF.cxx @@ -74,17 +74,17 @@ struct TOFPIDQATask { hevtime_NoCut->Fill(collision.collisionTime() / 1000); // hevtime_NoCut->Fill(collision.collisionTime0() / 1000); // - htimediffEl_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimeEl()); - htimediffMu_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimeMu()); - htimediffPi_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimePi()); - htimediffKa_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimeKa()); - htimediffPr_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.expTimePr()); + htimediffEl_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalEl()); + htimediffMu_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalMu()); + htimediffPi_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalPi()); + htimediffKa_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalKa()); + htimediffPr_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalPr()); // - hnsigmaEl_NoCut->Fill(i.p(), i.nSigmaEl()); - hnsigmaMu_NoCut->Fill(i.p(), i.nSigmaMu()); - hnsigmaPi_NoCut->Fill(i.p(), i.nSigmaPi()); - hnsigmaKa_NoCut->Fill(i.p(), i.nSigmaKa()); - hnsigmaPr_NoCut->Fill(i.p(), i.nSigmaPr()); + hnsigmaEl_NoCut->Fill(i.p(), i.tofNSigmaEl()); + hnsigmaMu_NoCut->Fill(i.p(), i.tofNSigmaMu()); + hnsigmaPi_NoCut->Fill(i.p(), i.tofNSigmaPi()); + hnsigmaKa_NoCut->Fill(i.p(), i.tofNSigmaKa()); + hnsigmaPr_NoCut->Fill(i.p(), i.tofNSigmaPr()); // Beta hp_beta->Fill(i.p(), i.beta()); } @@ -121,13 +121,13 @@ struct SpectraTask { issel = issel && (i.flags() & 0x80000000); //kTIME if (!issel) continue; - if (TMath::Abs(i.nSigmaPi()) < 3) { + if (TMath::Abs(i.tofNSigmaPi()) < 3) { hp_El->Fill(i.p()); hpt_El->Fill(i.pt()); - } else if (TMath::Abs(i.nSigmaKa()) < 3) { + } else if (TMath::Abs(i.tofNSigmaKa()) < 3) { hp_Ka->Fill(i.p()); hpt_Ka->Fill(i.pt()); - } else if (TMath::Abs(i.nSigmaPr()) < 3) { + } else if (TMath::Abs(i.tofNSigmaPr()) < 3) { hp_Pr->Fill(i.p()); hpt_Pr->Fill(i.pt()); } diff --git a/Analysis/Tasks/spectraTPC.cxx b/Analysis/Tasks/spectraTPC.cxx index 67412053a98bb..6b22011eb4a5b 100644 --- a/Analysis/Tasks/spectraTPC.cxx +++ b/Analysis/Tasks/spectraTPC.cxx @@ -55,17 +55,17 @@ struct TPCPIDQATask { continue; // htpcsignal->Fill(i.p(), i.tpcSignal()); - hexpEl->Fill(i.p(), i.expSignalEl()); - hexpDe->Fill(i.p(), i.expSignalDe()); - hnsigmaEl->Fill(i.p(), i.nSigmaEl()); - hnsigmaMu->Fill(i.p(), i.nSigmaMu()); - hnsigmaPi->Fill(i.p(), i.nSigmaPi()); - hnsigmaKa->Fill(i.p(), i.nSigmaKa()); - hnsigmaPr->Fill(i.p(), i.nSigmaPr()); - hnsigmaDe->Fill(i.p(), i.nSigmaDe()); - hnsigmaTr->Fill(i.p(), i.nSigmaTr()); - hnsigmaHe->Fill(i.p(), i.nSigmaHe()); - hnsigmaAl->Fill(i.p(), i.nSigmaAl()); + hexpEl->Fill(i.p(), i.tpcExpSignalEl()); + hexpDe->Fill(i.p(), i.tpcExpSignalDe()); + hnsigmaEl->Fill(i.p(), i.tpcNSigmaEl()); + hnsigmaMu->Fill(i.p(), i.tpcNSigmaMu()); + hnsigmaPi->Fill(i.p(), i.tpcNSigmaPi()); + hnsigmaKa->Fill(i.p(), i.tpcNSigmaKa()); + hnsigmaPr->Fill(i.p(), i.tpcNSigmaPr()); + hnsigmaDe->Fill(i.p(), i.tpcNSigmaDe()); + hnsigmaTr->Fill(i.p(), i.tpcNSigmaTr()); + hnsigmaHe->Fill(i.p(), i.tpcNSigmaHe()); + hnsigmaAl->Fill(i.p(), i.tpcNSigmaAl()); } } }; From 743c16cb09ee67103f6f55d18f6e80ef2e6accbf Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 5 Aug 2020 08:30:55 +0200 Subject: [PATCH 0268/1751] GPU: Don't log to stdout --- GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index 98712cb7b417d..db4dd2bd42a14 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -274,7 +274,7 @@ int GPUReconstructionCPU::RunChains() printf("Execution Time: Total : %50s Time: %'10d us\n", "Total Kernel", (int)mStatKernelTime); printf("Execution Time: Total : %50s Time: %'10d us\n", "Total Wall", (int)mStatWallTime); } else if (GetProcessingSettings().debugLevel >= 0) { - printf("Total Wall Time: %'d us\n", (int)mStatWallTime); + GPUInfo("Total Wall Time: %d us", (int)mStatWallTime); } if (mProcessingSettings.resetTimers) { mStatNEvents = 0; From f5823eb339b1c1b8acd95e519b388e365dac9d62 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Mon, 22 Jun 2020 22:15:50 +0200 Subject: [PATCH 0269/1751] [rANS] convenience functionalities and bugfixes * enoder/decoder for binary data and benchmarks * Better reporting for Encoder/decoder * bugfixes --- Utilities/rANS/CMakeLists.txt | 20 +++ Utilities/rANS/include/rANS/Decoder.h | 4 +- Utilities/rANS/include/rANS/Encoder.h | 14 +- .../rANS/include/rANS/SymbolStatistics.h | 2 - Utilities/rANS/include/rANS/helper.h | 6 + Utilities/rANS/run/bin-encode-decode.cxx | 152 ++++++++++++++++++ 6 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 Utilities/rANS/run/bin-encode-decode.cxx diff --git a/Utilities/rANS/CMakeLists.txt b/Utilities/rANS/CMakeLists.txt index b627df2b74f69..3f0dd0305d0e8 100644 --- a/Utilities/rANS/CMakeLists.txt +++ b/Utilities/rANS/CMakeLists.txt @@ -18,3 +18,23 @@ o2_add_test(EncodeDecode PUBLIC_LINK_LIBRARIES O2::rANS COMPONENT_NAME rANS LABELS utils) + + +o2_add_executable(rans-encode-decode-8 + TARGETVARNAME targetName + SOURCES run/bin-encode-decode.cxx + PUBLIC_LINK_LIBRARIES O2::rANS Boost::program_options) +target_compile_definitions(${targetName} PRIVATE -DSOURCE_T=uint8_t) + + +o2_add_executable(rans-encode-decode-16 + TARGETVARNAME targetName + SOURCES run/bin-encode-decode.cxx + PUBLIC_LINK_LIBRARIES O2::rANS Boost::program_options) +target_compile_definitions(${targetName} PRIVATE -DSOURCE_T=uint16_t) + +o2_add_executable(rans-encode-decode-32 + TARGETVARNAME targetName + SOURCES run/bin-encode-decode.cxx + PUBLIC_LINK_LIBRARIES O2::rANS Boost::program_options) +target_compile_definitions(${targetName} PRIVATE -DSOURCE_T=uint32_t) \ No newline at end of file diff --git a/Utilities/rANS/include/rANS/Decoder.h b/Utilities/rANS/include/rANS/Decoder.h index b4e2e920c5628..175a099291d2a 100644 --- a/Utilities/rANS/include/rANS/Decoder.h +++ b/Utilities/rANS/include/rANS/Decoder.h @@ -137,7 +137,9 @@ void Decoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, inputIter = rans0.decAdvanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); } t.stop(); - LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + LOG(debug1) << "Decoder::" << __func__ << " {ProcessedBytes: " << numSymbols * sizeof(source_T) << "," + << " inclusiveTimeMS: " << t.getDurationMS() << "," + << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (numSymbols * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; LOG(trace) << "done decoding"; } diff --git a/Utilities/rANS/include/rANS/Encoder.h b/Utilities/rANS/include/rANS/Encoder.h index 063890ac9552e..0fd0b13102df0 100644 --- a/Utilities/rANS/include/rANS/Encoder.h +++ b/Utilities/rANS/include/rANS/Encoder.h @@ -18,6 +18,7 @@ #include <memory> #include <algorithm> +#include <iomanip> #include <fairlogger/Logger.h> #include <stdexcept> @@ -164,17 +165,24 @@ const stream_IT Encoder<coder_T, stream_T, source_T>::Encoder::process( } t.stop(); - LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + LOG(debug1) << "Encoder::" << __func__ << " {ProcessedBytes: " << inputBufferSize * sizeof(source_T) << "," + << " inclusiveTimeMS: " << t.getDurationMS() << "," + << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (inputBufferSize * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; // advanced diagnostics for debug builds #if !defined(NDEBUG) + + const auto inputBufferSizeB = inputBufferSize * sizeof(source_T); + const auto outputBufferSizeB = std::distance(outputBegin, outputIter) * sizeof(stream_T); + LOG(debug2) << "EncoderProperties: {" << "sourceTypeB: " << sizeof(source_T) << ", " << "streamTypeB: " << sizeof(stream_T) << ", " << "coderTypeB: " << sizeof(coder_T) << ", " << "probabilityBits: " << mProbabilityBits << ", " - << "inputBufferSizeB: " << inputBufferSize * sizeof(source_T) << ", " - << "outputBufferSizeB: " << std::distance(outputBegin, outputIter) * sizeof(stream_T) << "}"; + << "inputBufferSizeB: " << inputBufferSizeB << ", " + << "outputBufferSizeB: " << outputBufferSizeB << ", " + << "compressionFactor: " << std::fixed << std::setprecision(2) << static_cast<double>(inputBufferSizeB) / static_cast<double>(outputBufferSizeB) << "}"; #endif LOG(trace) << "done encoding"; diff --git a/Utilities/rANS/include/rANS/SymbolStatistics.h b/Utilities/rANS/include/rANS/SymbolStatistics.h index 3d643be6d64e9..1337d08a80d91 100644 --- a/Utilities/rANS/include/rANS/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/SymbolStatistics.h @@ -96,8 +96,6 @@ class SymbolStatistics std::vector<uint32_t> mCumulativeFrequencyTable; }; -std::ostream& operator<<(std::ostream& strm, const SymbolStatistics& a); - template <typename IT> SymbolStatistics::SymbolStatistics(const IT begin, const IT end, size_t range) : mMin(0), mMax(0), mNUsedAlphabetSymbols(0), mMessageLength(0), mFrequencyTable(), mCumulativeFrequencyTable() { diff --git a/Utilities/rANS/include/rANS/helper.h b/Utilities/rANS/include/rANS/helper.h index 72146eec943cf..5b7d8ce18fd6b 100644 --- a/Utilities/rANS/include/rANS/helper.h +++ b/Utilities/rANS/include/rANS/helper.h @@ -59,6 +59,12 @@ class RANSTimer return duration.count(); } + double getDurationS() + { + std::chrono::duration<double, std::ratio<1>> duration = mStop - mStart; + return duration.count(); + } + private: std::chrono::time_point<std::chrono::high_resolution_clock> mStart; std::chrono::time_point<std::chrono::high_resolution_clock> mStop; diff --git a/Utilities/rANS/run/bin-encode-decode.cxx b/Utilities/rANS/run/bin-encode-decode.cxx new file mode 100644 index 0000000000000..5c4e4ec8fed05 --- /dev/null +++ b/Utilities/rANS/run/bin-encode-decode.cxx @@ -0,0 +1,152 @@ +// 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 bin-encode-decode.cpp +/// @author Michael Lettrich +/// @since 2020-06-22 +/// @brief benchmark encode/decode using rans on binary data. + +#include "rANS/rans.h" + +#include <boost/program_options.hpp> + +#include <fairlogger/Logger.h> + +namespace bpo = boost::program_options; + +#ifndef SOURCE_T +#define SOURCE_T uint8_t +#endif + +using source_t = SOURCE_T; +using coder_t = uint64_t; +using stream_t = uint32_t; +static const uint REPETITIONS = 5; +static const uint PROB_BITS = 18; +using Rans = o2::rans::Coder<coder_t, stream_t>; + +template <typename T> +void readFile(const std::string& filename, std::vector<T>* tokens) +{ + std::ifstream is(filename, std::ios_base::binary | std::ios_base::in); + if (is) { + // get length of file: + is.seekg(0, is.end); + size_t length = is.tellg(); + is.seekg(0, is.beg); + + // reserve size of tokens + if (!tokens) { + throw std::runtime_error("Cannot read file into nonexistent vector"); + } + + if (length % sizeof(T)) { + throw std::runtime_error("Filesize is not a multiple of datatype."); + } + // size the vector appropriately + size_t num_elems = length / sizeof(T); + tokens->resize(num_elems); + + // read data as a block: + is.read(reinterpret_cast<char*>(tokens->data()), length); + is.close(); + } +} + +int main(int argc, char* argv[]) +{ + + bpo::options_description options("Allowed options"); + // clang-format off + options.add_options() + ("help,h", "print usage message") + ("file,f",bpo::value<std::string>(), "file to compress") + ("samples,s",bpo::value<uint32_t>(), "how often to run benchmark") + ("bits,b",bpo::value<uint32_t>()->default_value(20), "resample dictionary to N Bits") + ("range,r",bpo::value<uint32_t>()->default_value(0), "range of the source data") + ("log_severity,l",bpo::value<std::string>(), "severity of FairLogger"); + // clang-format on + + bpo::variables_map vm; + bpo::store(bpo::parse_command_line(argc, argv, options), vm); + bpo::notify(vm); + + if (vm.count("help")) { + std::cout << options << "\n"; + return 0; + } + + const std::string filename = [&]() { + if (vm.count("file")) { + return vm["file"].as<std::string>(); + } else { + LOG(error) << "missing path to input file"; + exit(1); + } + }(); + + const uint32_t probabilityBits = [&]() { + if (vm.count("bits")) { + return vm["bits"].as<uint32_t>(); + } else { + return PROB_BITS; + } + }(); + + const uint32_t symbolRangeBits = [&]() { + if (vm.count("range")) { + return vm["range"].as<uint32_t>(); + } else { + return static_cast<uint32_t>(0); + } + }(); + + const uint32_t repetitions = [&]() { + if (vm.count("samples")) { + return vm["samples"].as<uint32_t>(); + } else { + return REPETITIONS; + } + }(); + + if (vm.count("log_severity")) { + fair::Logger::SetConsoleSeverity(vm["log_severity"].as<std::string>().c_str()); + } + for (size_t i = 0; i < repetitions; i++) { + LOG(info) << "repetion: " << i; + std::vector<source_t> tokens; + readFile(filename, &tokens); + + std::unique_ptr<o2::rans::SymbolStatistics> stats = [&]() { + auto stats = std::make_unique<o2::rans::SymbolStatistics>(std::begin(tokens), std::end(tokens)); + stats->rescaleToNBits(probabilityBits); + return std::move(stats); + }(); + + std::vector<stream_t> encoderBuffer(256 << 20, 0); + const auto encodedMessageEnd = [&]() { + const o2::rans::Encoder64<source_t> encoder{*stats, probabilityBits}; + return encoder.process(encoderBuffer.begin(), encoderBuffer.end(), std::begin(tokens), std::end(tokens)); + }(); + + std::vector<source_t> decoderBuffer(tokens.size()); + [&]() { + o2::rans::Decoder64<source_t> decoder{*stats, probabilityBits}; + decoder.process(decoderBuffer.begin(), encodedMessageEnd, stats->getMessageLength()); + }(); + + if (std::memcmp(tokens.data(), decoderBuffer.data(), + tokens.size() * sizeof(source_t))) { + LOG(error) << "Decoder failed tests"; + } else { + LOG(info) << "Decoder passed tests"; + } + } +} From c5e51ed5ab639f98c97dd25b195671c15f5172e8 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Tue, 23 Jun 2020 17:36:38 +0200 Subject: [PATCH 0270/1751] [rANS] Incompressible Symbols and Deduplication * refactor and only expose external API to users * refactor symbol statistics and introduce control symbol for incompressible data * refactor Coder class and split into Encoder/Decoder classes * implement coder/decoder for rare symbols * implement coder/decoder for deduplication --- .../EncodedBlocks.h | 6 +- Utilities/rANS/CMakeLists.txt | 6 +- Utilities/rANS/include/rANS/Coder.h | 377 ------------------ Utilities/rANS/include/rANS/Decoder.h | 67 ++-- Utilities/rANS/include/rANS/DedupDecoder.h | 104 +++++ Utilities/rANS/include/rANS/DedupEncoder.h | 161 ++++++++ Utilities/rANS/include/rANS/Encoder.h | 48 ++- Utilities/rANS/include/rANS/LiteralDecoder.h | 108 +++++ Utilities/rANS/include/rANS/LiteralEncoder.h | 150 +++++++ .../rANS/include/rANS/SymbolStatistics.h | 337 +++++++++++++--- Utilities/rANS/include/rANS/SymbolTable.h | 69 ---- .../rANS/include/rANS/internal/Decoder.h | 165 ++++++++ .../rANS/{ => internal}/DecoderSymbol.h | 10 +- .../rANS/include/rANS/internal/Encoder.h | 195 +++++++++ .../rANS/{ => internal}/EncoderSymbol.h | 12 +- .../{ => internal}/ReverseSymbolLookupTable.h | 38 +- .../rANS/include/rANS/internal/SymbolTable.h | 104 +++++ .../rANS/include/rANS/{ => internal}/helper.h | 21 +- Utilities/rANS/include/rANS/rans.h | 23 +- Utilities/rANS/run/bin-encode-decode.cxx | 5 +- Utilities/rANS/test/test_ransEncodeDecode.cxx | 101 ++++- 21 files changed, 1479 insertions(+), 628 deletions(-) delete mode 100644 Utilities/rANS/include/rANS/Coder.h create mode 100644 Utilities/rANS/include/rANS/DedupDecoder.h create mode 100644 Utilities/rANS/include/rANS/DedupEncoder.h create mode 100644 Utilities/rANS/include/rANS/LiteralDecoder.h create mode 100644 Utilities/rANS/include/rANS/LiteralEncoder.h delete mode 100644 Utilities/rANS/include/rANS/SymbolTable.h create mode 100644 Utilities/rANS/include/rANS/internal/Decoder.h rename Utilities/rANS/include/rANS/{ => internal}/DecoderSymbol.h (88%) create mode 100644 Utilities/rANS/include/rANS/internal/Encoder.h rename Utilities/rANS/include/rANS/{ => internal}/EncoderSymbol.h (95%) rename Utilities/rANS/include/rANS/{ => internal}/ReverseSymbolLookupTable.h (59%) create mode 100644 Utilities/rANS/include/rANS/internal/SymbolTable.h rename Utilities/rANS/include/rANS/{ => internal}/helper.h (73%) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 692e092359bfb..def38fc60cf78 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -621,7 +621,7 @@ void EncodedBlocks<H, N, W>::decode(D* dest, // destination pointer if (block.getNData()) { if (md.opt == Metadata::OptStore::EENCODE) { assert(block.getNDict()); // at the moment we expect to have dictionary - o2::rans::SymbolStatistics stats(block.getDict(), block.getDict() + block.getNDict(), md.min, md.max, md.messageLength); + o2::rans::SymbolStatistics<D> stats(block.getDict(), block.getDict() + block.getNDict(), md.min, md.max, md.messageLength); o2::rans::Decoder64<D> decoder(stats, md.probabilityBits); decoder.process(dest, block.getData() + block.getNData(), md.messageLength); } else { // data was stored as is @@ -656,7 +656,7 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source return; } static_assert(std::is_same<W, stream_t>()); - std::unique_ptr<rans::SymbolStatistics> stats = nullptr; + std::unique_ptr<rans::SymbolStatistics<S>> stats = nullptr; Metadata md; auto* bl = &mBlocks[slot]; @@ -680,7 +680,7 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source // case 3: message where entropy coding should be applied if (opt == Metadata::OptStore::EENCODE) { // build symbol statistics - stats = std::make_unique<rans::SymbolStatistics>(srcBegin, srcEnd); + stats = std::make_unique<rans::SymbolStatistics<S>>(srcBegin, srcEnd); stats->rescaleToNBits(probabilityBits); const o2::rans::Encoder64<S> encoder{*stats, probabilityBits}; const int dictSize = stats->getFrequencyTable().size(); diff --git a/Utilities/rANS/CMakeLists.txt b/Utilities/rANS/CMakeLists.txt index 3f0dd0305d0e8..a732fe678480c 100644 --- a/Utilities/rANS/CMakeLists.txt +++ b/Utilities/rANS/CMakeLists.txt @@ -8,9 +8,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_library(rANS - SOURCES src/SymbolStatistics.cxx - PUBLIC_LINK_LIBRARIES FairLogger::FairLogger) +o2_add_header_only_library(rANS + INTERFACE_LINK_LIBRARIES FairLogger::FairLogger) o2_add_test(EncodeDecode NAME EncodeDecode @@ -19,7 +18,6 @@ o2_add_test(EncodeDecode COMPONENT_NAME rANS LABELS utils) - o2_add_executable(rans-encode-decode-8 TARGETVARNAME targetName SOURCES run/bin-encode-decode.cxx diff --git a/Utilities/rANS/include/rANS/Coder.h b/Utilities/rANS/include/rANS/Coder.h deleted file mode 100644 index 388b90f9b50f9..0000000000000 --- a/Utilities/rANS/include/rANS/Coder.h +++ /dev/null @@ -1,377 +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. - -/// @file Coder.h -/// @author Michael Lettrich -/// @since 2019-05-10 -/// @brief Stateless class for coding and decoding symbols using rANS - -#ifndef RANS_CODER_H -#define RANS_CODER_H - -#include <vector> -#include <cstdint> -#include <cassert> -#include <type_traits> - -#include "DecoderSymbol.h" -#include "EncoderSymbol.h" -#include "helper.h" - -namespace o2 -{ -namespace rans -{ -__extension__ typedef unsigned __int128 uint128; - -// READ ME FIRST: -// -// This is designed like a typical arithmetic coder API, but there's three -// twists you absolutely should be aware of before you start hacking: -// -// 1. You need to encode data in *reverse* - last symbol first. rANS works -// like a stack: last in, first out. -// 2. Likewise, the encoder outputs bytes *in reverse* - that is, you give -// it a pointer to the *end* of your buffer (exclusive), and it will -// slowly move towards the beginning as more bytes are emitted. -// 3. Unlike basically any other entropy coder implementation you might -// have used, you can interleave data from multiple independent rANS -// encoders into the same bytestream without any extra signaling; -// you can also just write some bytes by yourself in the middle if -// you want to. This is in addition to the usual arithmetic encoder -// property of being able to switch models on the fly. Writing raw -// bytes can be useful when you have some data that you know is -// incompressible, and is cheaper than going through the rANS encode -// function. Using multiple rANS coders on the same byte stream wastes -// a few bytes compared to using just one, but execution of two -// independent encoders can happen in parallel on superscalar and -// Out-of-Order CPUs, so this can be *much* faster in tight decoding -// loops. -// -// This is why all the rANS functions take the write pointer as an -// argument instead of just storing it in some context struct. - -// -------------------------------------------------------------------------- -template <typename State_T, typename Stream_T> -class Coder -{ - // the Coder works either with a 64Bit state and 32 bit streaming or - //a 32 Bit state and 8 Bit streaming We need to make sure it gets initialized with - //the right template arguments at compile time. - static_assert((sizeof(State_T) == sizeof(uint32_t) && sizeof(Stream_T) == sizeof(uint8_t)) || - (sizeof(State_T) == sizeof(uint64_t) && sizeof(Stream_T) == sizeof(uint32_t)), - "Coder can either be 32Bit with 8 Bit stream type or 64 Bit Type with 32 Bit stream type"); - - public: - Coder(); - - // Initializes the encoder - void encInit(); - - // Encodes a single symbol with range start "start" and frequency "freq". - // All frequencies are assumed to sum to "1 << scale_bits", and the - // resulting bytes get written to ptr (which is updated). - // - // NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from - // beginning to end! Likewise, the output bytestream is written *backwards*: - // ptr starts pointing at the end of the output buffer and keeps decrementing. - template <typename Stream_IT> - Stream_IT encPut(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits); - - // Flushes the rANS encoder. - template <typename Stream_IT> - Stream_IT encFlush(Stream_IT iter); - - // Initializes a rANS decoder. - // Unlike the encoder, the decoder works forwards as you'd expect. - template <typename Stream_IT> - Stream_IT decInit(Stream_IT iter); - - // Returns the current cumulative frequency (map it to a symbol yourself!) - uint32_t decGet(uint32_t scale_bits); - - // Advances in the bit stream by "popping" a single symbol with range start - // "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits", - // and the resulting bytes get written to ptr (which is updated). - template <typename Stream_IT> - Stream_IT decAdvance(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits); - - // Encodes a given symbol. This is faster than straight RansEnc since we can do - // multiplications instead of a divide. - // - // See Rans32EncSymbolInit for a description of how this works. - template <typename Stream_IT> - Stream_IT encPutSymbol(Stream_IT iter, const EncoderSymbol<State_T>& sym, uint32_t scale_bits); - - // Equivalent to Rans32DecAdvance that takes a symbol. - template <typename Stream_IT> - Stream_IT decAdvanceSymbol(Stream_IT iter, const DecoderSymbol& sym, uint32_t scale_bits); - - // Advances in the bit stream by "popping" a single symbol with range start - // "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits". - // No renormalization or output happens. - void decAdvanceStep(uint32_t start, uint32_t freq, uint32_t scale_bits); - - // Equivalent to Rans32DecAdvanceStep that takes a symbol. - void decAdvanceSymbolStep(const DecoderSymbol& sym, uint32_t scale_bits); - - // Renormalize. - template <typename Stream_IT> - Stream_IT decRenorm(Stream_IT iter); - - private: - State_T mState; - - // Renormalize the encoder. - template <typename Stream_IT> - std::tuple<State_T, Stream_IT> encRenorm(State_T x, Stream_IT iter, uint32_t freq, uint32_t scale_bits); - - // Renormalize. - template <typename Stream_IT> - std::tuple<State_T, Stream_IT> decRenorm(State_T x, Stream_IT iter); - - // L ('l' in the paper) is the lower bound of our normalization interval. - // Between this and our byte-aligned emission, we use 31 (not 32!) bits. - // This is done intentionally because exact reciprocals for 31-bit uints - // fit in 32-bit uints: this permits some optimizations during encoding. - inline static constexpr State_T LOWER_BOUND = needs64Bit<State_T>() ? (1u << 31) : (1u << 23); // lower bound of our normalization interval - - inline static constexpr State_T STREAM_BITS = sizeof(Stream_T) * 8; // lower bound of our normalization interval -}; - -template <typename State_T, typename Stream_T> -Coder<State_T, Stream_T>::Coder() : mState(){}; - -template <typename State_T, typename Stream_T> -void Coder<State_T, Stream_T>::encInit() -{ - mState = LOWER_BOUND; -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -Stream_IT Coder<State_T, Stream_T>::encPut(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - // renormalize - Stream_IT streamPos; - State_T x; - std::tie(x, streamPos) = encRenorm(mState, iter, freq, scale_bits); - - // x = C(s,x) - mState = ((x / freq) << scale_bits) + (x % freq) + start; - return streamPos; -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -Stream_IT Coder<State_T, Stream_T>::encFlush(Stream_IT iter) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - Stream_IT streamPos = iter; - - if constexpr (needs64Bit<State_T>()) { - ++streamPos; - *streamPos = static_cast<Stream_T>(mState >> 32); - ++streamPos; - *streamPos = static_cast<Stream_T>(mState >> 0); - assert(std::distance(iter, streamPos) == 2); - } else { - ++streamPos; - *streamPos = static_cast<Stream_T>(mState >> 24); - ++streamPos; - *streamPos = static_cast<Stream_T>(mState >> 16); - ++streamPos; - *streamPos = static_cast<Stream_T>(mState >> 8); - ++streamPos; - *streamPos = static_cast<Stream_T>(mState >> 0); - assert(std::distance(iter, streamPos) == 4); - } - - mState = 0; - return streamPos; -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -Stream_IT Coder<State_T, Stream_T>::decInit(Stream_IT iter) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - State_T x = 0; - Stream_IT streamPos = iter; - - if constexpr (needs64Bit<State_T>()) { - x = static_cast<State_T>(*streamPos) << 0; - --streamPos; - x |= static_cast<State_T>(*streamPos) << 32; - --streamPos; - assert(std::distance(streamPos, iter) == 2); - } else { - x = static_cast<State_T>(*streamPos) << 0; - --streamPos; - x |= static_cast<State_T>(*streamPos) << 8; - --streamPos; - x |= static_cast<State_T>(*streamPos) << 16; - --streamPos; - x |= static_cast<State_T>(*streamPos) << 24; - --streamPos; - assert(std::distance(streamPos, iter) == 4); - } - - mState = x; - return streamPos; -}; - -template <typename State_T, typename Stream_T> -uint32_t Coder<State_T, Stream_T>::decGet(uint32_t scale_bits) -{ - return mState & ((1u << scale_bits) - 1); -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -Stream_IT Coder<State_T, Stream_T>::decAdvance(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - State_T mask = (1ull << scale_bits) - 1; - - // s, x = D(x) - State_T x = mState; - x = freq * (x >> scale_bits) + (x & mask) - start; - - // renormalize - Stream_IT streamPos; - std::tie(mState, streamPos) = this->decRenorm(x, iter); - return streamPos; -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -Stream_IT Coder<State_T, Stream_T>::encPutSymbol(Stream_IT iter, const EncoderSymbol<State_T>& sym, uint32_t scale_bits) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - assert(sym.freq != 0); // can't encode symbol with freq=0 - - // renormalize - Stream_IT streamPos; - State_T x; - std::tie(x, streamPos) = encRenorm(mState, iter, sym.freq, scale_bits); - - // x = C(s,x) - State_T q; - - if constexpr (needs64Bit<State_T>()) { - // This code needs support for 64-bit long multiplies with 128-bit result - // (or more precisely, the top 64 bits of a 128-bit result). - q = static_cast<State_T>((static_cast<uint128>(x) * sym.rcp_freq) >> 64); - } else { - q = static_cast<State_T>((static_cast<uint64_t>(x) * sym.rcp_freq) >> 32); - } - q = q >> sym.rcp_shift; - - mState = x + sym.bias + q * sym.cmpl_freq; - return streamPos; -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -Stream_IT Coder<State_T, Stream_T>::decAdvanceSymbol(Stream_IT iter, const DecoderSymbol& sym, uint32_t scale_bits) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - return decAdvance(iter, sym.start, sym.freq, scale_bits); -}; - -template <typename State_T, typename Stream_T> -void Coder<State_T, Stream_T>::decAdvanceStep(uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - State_T mask = (1u << scale_bits) - 1; - - // s, x = D(x) - State_T x = mState; - mState = freq * (x >> scale_bits) + (x & mask) - start; -}; - -template <typename State_T, typename Stream_T> -void Coder<State_T, Stream_T>::decAdvanceSymbolStep(const DecoderSymbol& sym, uint32_t scale_bits) -{ - decAdvanceStep(sym.start, sym.freq, scale_bits); -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -Stream_IT Coder<State_T, Stream_T>::decRenorm(Stream_IT iter) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - Stream_IT streamPos; - std::tie(mState, streamPos) = this->decRenorm(mState, iter); - return streamPos; -} - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -inline std::tuple<State_T, Stream_IT> Coder<State_T, Stream_T>::encRenorm(State_T x, Stream_IT iter, uint32_t freq, uint32_t scale_bits) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - Stream_IT streamPos = iter; - - State_T x_max = ((LOWER_BOUND >> scale_bits) << STREAM_BITS) * freq; // this turns into a shift. - if (x >= x_max) { - if constexpr (needs64Bit<State_T>()) { - ++streamPos; - *streamPos = static_cast<Stream_T>(x); - x >>= STREAM_BITS; - assert(x < x_max); - } else { - do { - ++streamPos; - *streamPos = static_cast<Stream_T>(x & 0xff); - x >>= STREAM_BITS; - } while (x >= x_max); - } - } - return std::make_tuple(x, streamPos); -}; - -template <typename State_T, typename Stream_T> -template <typename Stream_IT> -inline std::tuple<State_T, Stream_IT> Coder<State_T, Stream_T>::decRenorm(State_T x, Stream_IT iter) -{ - static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); - - Stream_IT streamPos = iter; - - // renormalize - if (x < LOWER_BOUND) { - if constexpr (needs64Bit<State_T>()) { - x = (x << STREAM_BITS) | *streamPos; - --streamPos; - assert(x >= LOWER_BOUND); - } else { - - do { - x = (x << STREAM_BITS) | *streamPos; - --streamPos; - } while (x < LOWER_BOUND); - } - } - return std::make_tuple(x, streamPos); -} - -} // namespace rans -} // namespace o2 - -#endif /* RANS_CODER_H */ diff --git a/Utilities/rANS/include/rANS/Decoder.h b/Utilities/rANS/include/rANS/Decoder.h index 175a099291d2a..3655bbf0ed84a 100644 --- a/Utilities/rANS/include/rANS/Decoder.h +++ b/Utilities/rANS/include/rANS/Decoder.h @@ -16,29 +16,32 @@ #ifndef RANS_DECODER_H #define RANS_DECODER_H +#include "internal/Decoder.h" + #include <cstddef> #include <type_traits> #include <iostream> #include <fairlogger/Logger.h> -#include "SymbolTable.h" -#include "DecoderSymbol.h" -#include "ReverseSymbolLookupTable.h" -#include "Coder.h" +#include "internal/DecoderSymbol.h" +#include "internal/ReverseSymbolLookupTable.h" +#include "internal/SymbolTable.h" +#include "internal/Decoder.h" namespace o2 { namespace rans { + template <typename coder_T, typename stream_T, typename source_T> class Decoder { - private: - using decoderSymbol_t = SymbolTable<DecoderSymbol>; - using reverseSymbolLookupTable_t = ReverseSymbolLookupTable<source_T>; - using ransDecoder = Coder<coder_T, stream_T>; + protected: + using decoderSymbol_t = internal::SymbolTable<internal::DecoderSymbol, source_T>; + using reverseSymbolLookupTable_t = internal::ReverseSymbolLookupTable<source_T>; + using ransDecoder = internal::Decoder<coder_T, stream_T>; public: Decoder(const Decoder& d); @@ -46,16 +49,16 @@ class Decoder Decoder<coder_T, stream_T, source_T>& operator=(const Decoder& d); Decoder<coder_T, stream_T, source_T>& operator=(Decoder&& d) = default; ~Decoder() = default; - Decoder(const SymbolStatistics& stats, size_t probabilityBits); + Decoder(const SymbolStatistics<source_T>& stats, size_t probabilityBits); template <typename stream_IT, typename source_IT> - void process(const source_IT outputBegin, const stream_IT inputEnd, size_t numSymbols) const; + void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength) const; using coder_t = coder_T; using stream_t = stream_T; using source_t = source_T; - private: + protected: std::unique_ptr<decoderSymbol_t> mSymbolTable; std::unique_ptr<reverseSymbolLookupTable_t> mReverseLUT; size_t mProbabilityBits; @@ -78,8 +81,9 @@ Decoder<coder_T, stream_T, source_T>& Decoder<coder_T, stream_T, source_T>::oper } template <typename coder_T, typename stream_T, typename source_T> -Decoder<coder_T, stream_T, source_T>::Decoder(const SymbolStatistics& stats, size_t probabilityBits) : mSymbolTable(nullptr), mReverseLUT(nullptr), mProbabilityBits(probabilityBits) +Decoder<coder_T, stream_T, source_T>::Decoder(const SymbolStatistics<source_T>& stats, size_t probabilityBits) : mSymbolTable(nullptr), mReverseLUT(nullptr), mProbabilityBits(probabilityBits) { + using namespace internal; RANSTimer t; t.start(); mSymbolTable = std::make_unique<decoderSymbol_t>(stats, probabilityBits); @@ -93,53 +97,50 @@ Decoder<coder_T, stream_T, source_T>::Decoder(const SymbolStatistics& stats, siz template <typename coder_T, typename stream_T, typename source_T> template <typename stream_IT, typename source_IT> -void Decoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, const stream_IT inputEnd, size_t numSymbols) const +void Decoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength) const { + using namespace internal; LOG(trace) << "start decoding"; RANSTimer t; t.start(); static_assert(std::is_same<typename std::iterator_traits<source_IT>::value_type, source_T>::value); static_assert(std::is_same<typename std::iterator_traits<stream_IT>::value_type, stream_T>::value); - if (numSymbols == 0) { + if (messageLength == 0) { LOG(warning) << "Empty message passed to decoder, skipping decode process"; return; } - ransDecoder rans0, rans1; stream_IT inputIter = inputEnd; source_IT it = outputBegin; // make Iter point to the last last element --inputIter; - inputIter = rans0.decInit(inputIter); - inputIter = rans1.decInit(inputIter); + ransDecoder rans0, rans1; + inputIter = rans0.init(inputIter); + inputIter = rans1.init(inputIter); - for (size_t i = 0; i < (numSymbols & ~1); i += 2) { - const stream_T s0 = - (*mReverseLUT)[rans0.decGet(mProbabilityBits)]; - const stream_T s1 = - (*mReverseLUT)[rans1.decGet(mProbabilityBits)]; + for (size_t i = 0; i < (messageLength & ~1); i += 2) { + const stream_T s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; + const stream_T s1 = (*mReverseLUT)[rans1.get(mProbabilityBits)]; *it++ = s0; *it++ = s1; - rans0.decAdvanceSymbolStep((*mSymbolTable)[s0], mProbabilityBits); - rans1.decAdvanceSymbolStep((*mSymbolTable)[s1], mProbabilityBits); - inputIter = rans0.decRenorm(inputIter); - inputIter = rans1.decRenorm(inputIter); + inputIter = rans0.advanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); + inputIter = rans1.advanceSymbol(inputIter, (*mSymbolTable)[s1], mProbabilityBits); } - // last byte, if number of bytes was odd - if (numSymbols & 1) { - const stream_T s0 = - (*mReverseLUT)[rans0.decGet(mProbabilityBits)]; + // last byte, if message length was odd + if (messageLength & 1) { + const stream_T s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; *it = s0; - inputIter = rans0.decAdvanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); + inputIter = rans0.advanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); } t.stop(); - LOG(debug1) << "Decoder::" << __func__ << " {ProcessedBytes: " << numSymbols * sizeof(source_T) << "," + LOG(debug1) << "Decoder::" << __func__ << " { DecodedSymbols: " << messageLength << "," + << "processedBytes: " << messageLength * sizeof(source_T) << "," << " inclusiveTimeMS: " << t.getDurationMS() << "," - << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (numSymbols * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; + << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (messageLength * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; LOG(trace) << "done decoding"; } diff --git a/Utilities/rANS/include/rANS/DedupDecoder.h b/Utilities/rANS/include/rANS/DedupDecoder.h new file mode 100644 index 0000000000000..8a9c1e9c94405 --- /dev/null +++ b/Utilities/rANS/include/rANS/DedupDecoder.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. + +/// @file Decoder.h +/// @author Michael Lettrich +/// @since 2020-04-06 +/// @brief Decoder - decode a rANS encoded state back into source symbols + +#ifndef RANS_DEDUPDECODER_H +#define RANS_DEDUPDECODER_H + +#include "Decoder.h" + +#include <cstddef> +#include <type_traits> +#include <iostream> +#include <string> + +#include <fairlogger/Logger.h> + +#include "internal/DecoderSymbol.h" +#include "internal/ReverseSymbolLookupTable.h" +#include "internal/SymbolTable.h" +#include "internal/Decoder.h" + +namespace o2 +{ +namespace rans +{ + +template <typename coder_T, typename stream_T, typename source_T> +class DedupDecoder : public Decoder<coder_T, stream_T, source_T> +{ + //inherit constructors; + using Decoder<coder_T, stream_T, source_T>::Decoder; + + public: + using duplicatesMap_t = std::map<uint32_t, uint32_t>; + + template <typename stream_IT, typename source_IT> + void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, duplicatesMap_t& duplicates) const; +}; + +template <typename coder_T, typename stream_T, typename source_T> +template <typename stream_IT, typename source_IT> +void DedupDecoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, duplicatesMap_t& duplicates) const +{ + using namespace internal; + using ransDecoder = internal::Decoder<coder_T, stream_T>; + LOG(trace) << "start decoding"; + RANSTimer t; + t.start(); + static_assert(std::is_same<typename std::iterator_traits<source_IT>::value_type, source_T>::value); + static_assert(std::is_same<typename std::iterator_traits<stream_IT>::value_type, stream_T>::value); + + if (messageLength == 0) { + LOG(warning) << "Empty message passed to decoder, skipping decode process"; + return; + } + + stream_IT inputIter = inputEnd; + source_IT it = outputBegin; + + // make Iter point to the last last element + --inputIter; + + ransDecoder rans; + inputIter = rans.init(inputIter); + + for (size_t i = 0; i < (messageLength); i++) { + const stream_T s = (*this->mReverseLUT)[rans.get(this->mProbabilityBits)]; + + // deduplication + auto duplicatesIter = duplicates.find(i); + if (duplicatesIter != duplicates.end()) { + LOG(trace) << "pos[" << i << "]: restoring " << duplicatesIter->second << " duplicates of symbol " << (char)s; + for (int d = 0; d < duplicatesIter->second; d++) { + *it++ = s; + i++; + } + } + *it++ = s; + inputIter = rans.advanceSymbol(inputIter, (*this->mSymbolTable)[s], this->mProbabilityBits); + } + + t.stop(); + LOG(debug1) << "Decoder::" << __func__ << " { DecodedSymbols: " << messageLength << "," + << "processedBytes: " << messageLength * sizeof(source_T) << "," + << " inclusiveTimeMS: " << t.getDurationMS() << "," + << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (messageLength * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; + + LOG(trace) << "done decoding"; +} +} // namespace rans +} // namespace o2 + +#endif /* RANS_DEDUPDECODER_H */ diff --git a/Utilities/rANS/include/rANS/DedupEncoder.h b/Utilities/rANS/include/rANS/DedupEncoder.h new file mode 100644 index 0000000000000..3a4efaf2d9f74 --- /dev/null +++ b/Utilities/rANS/include/rANS/DedupEncoder.h @@ -0,0 +1,161 @@ +// 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 Encoder.h +/// @author Michael Lettrich +/// @since 2020-04-06 +/// @brief Encoder - code symbol into a rANS encoded state + +#ifndef INCLUDE_RANS_DEDUPENCODER_H_ +#define INCLUDE_RANS_DEDUPENCODER_H_ + +#include "Encoder.h" + +#include <memory> +#include <algorithm> +#include <iomanip> +#include <map> +#include <cstdint> +#include <string> + +#include <fairlogger/Logger.h> +#include <stdexcept> + +#include "internal/EncoderSymbol.h" +#include "internal/helper.h" +#include "internal/SymbolTable.h" + +namespace o2 +{ +namespace rans +{ + +template <typename coder_T, typename stream_T, typename source_T> +class DedupEncoder : public Encoder<coder_T, stream_T, source_T> +{ + //inherit constructors; + using Encoder<coder_T, stream_T, source_T>::Encoder; + + public: + using duplicatesMap_t = std::map<uint32_t, uint32_t>; + + template <typename stream_IT, typename source_IT> + const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd, + const source_IT inputBegin, source_IT inputEnd, duplicatesMap_t& duplicates) const; +}; + +template <typename coder_T, typename stream_T, typename source_T> +template <typename stream_IT, typename source_IT> +const stream_IT DedupEncoder<coder_T, stream_T, source_T>::process(const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd, duplicatesMap_t& duplicates) const +{ + using namespace internal; + using ransCoder = internal::Encoder<coder_T, stream_T>; + LOG(trace) << "start encoding"; + RANSTimer t; + t.start(); + + static_assert(std::is_same<typename std::iterator_traits<source_IT>::value_type, source_T>::value); + static_assert(std::is_same<typename std::iterator_traits<stream_IT>::value_type, stream_T>::value); + + if (inputBegin == inputEnd) { + LOG(warning) << "passed empty message to encoder, skip encoding"; + return outputEnd; + } + + if (outputBegin == outputEnd) { + const std::string errorMessage("Unallocated encode buffer passed to encoder. Aborting"); + LOG(error) << errorMessage; + throw std::runtime_error(errorMessage); + } + + ransCoder rans; + + stream_IT outputIter = outputBegin; + source_IT inputIT = inputEnd; + + const auto inputBufferSize = std::distance(inputBegin, inputEnd); + + auto encode = [&inputBegin, &duplicates, this](source_IT symbolIter, stream_IT outputIter, ransCoder& coder) { + const source_T symbol = *symbolIter; + const auto& encoderSymbol = (*this->mSymbolTable)[symbol]; + + // dedup step: + auto dedupIT = symbolIter; + //advance on source by one. + --dedupIT; + size_t numDuplicates = 0; + + // find out how many duplicates we have + while (*dedupIT == symbol) { + --dedupIT; + ++numDuplicates; + } + + // if we have a duplicate treat it. + if (numDuplicates > 0) { + LOG(trace) << "pos[" << std::distance(inputBegin, symbolIter) - 1 << "]: found " << numDuplicates << " duplicates of symbol " << (char)symbol; + duplicates.emplace(std::distance(inputBegin, symbolIter) - 1, numDuplicates); + } + + return std::tuple(++dedupIT, coder.putSymbol(outputIter, encoderSymbol, this->mProbabilityBits)); + }; + + while (inputIT > inputBegin) { // NB: working in reverse! + std::tie(inputIT, outputIter) = encode(--inputIT, outputIter, rans); + assert(outputIter < outputEnd); + } + outputIter = rans.flush(outputIter); + // first iterator past the range so that sizes, distances and iterators work correctly. + ++outputIter; + + assert(!(outputIter > outputEnd)); + + // deal with overflow + if (outputIter > outputEnd) { + const std::string exceptionText = [&]() { + std::stringstream ss; + ss << __func__ << " detected overflow in encode buffer: allocated:" << std::distance(outputBegin, outputEnd) << ", used:" << std::distance(outputBegin, outputIter); + return ss.str(); + }(); + + LOG(error) << exceptionText; + throw std::runtime_error(exceptionText); + } + + t.stop(); + LOG(debug1) << "Encoder::" << __func__ << " {ProcessedBytes: " << inputBufferSize * sizeof(source_T) << "," + << " inclusiveTimeMS: " << t.getDurationMS() << "," + << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (inputBufferSize * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; + +// advanced diagnostics for debug builds +#if !defined(NDEBUG) + + const auto inputBufferSizeB = inputBufferSize * sizeof(source_T); + const auto outputBufferSizeB = std::distance(outputBegin, outputIter) * sizeof(stream_T); + + LOG(debug2) << "EncoderProperties: {" + << "sourceTypeB: " << sizeof(source_T) << ", " + << "streamTypeB: " << sizeof(stream_T) << ", " + << "coderTypeB: " << sizeof(coder_T) << ", " + << "probabilityBits: " << this->mProbabilityBits << ", " + << "inputBufferSizeB: " << inputBufferSizeB << ", " + << "outputBufferSizeB: " << outputBufferSizeB << ", " + << "compressionFactor: " << std::fixed << std::setprecision(2) << static_cast<double>(inputBufferSizeB) / static_cast<double>(outputBufferSizeB) << "}"; +#endif + + LOG(trace) << "done encoding"; + + return outputIter; +}; + +} // namespace rans +} // namespace o2 + +#endif /* INCLUDE_RANS_DEDUPENCODER_H_ */ diff --git a/Utilities/rANS/include/rANS/Encoder.h b/Utilities/rANS/include/rANS/Encoder.h index 0fd0b13102df0..943683eab40dc 100644 --- a/Utilities/rANS/include/rANS/Encoder.h +++ b/Utilities/rANS/include/rANS/Encoder.h @@ -16,6 +16,8 @@ #ifndef RANS_ENCODER_H #define RANS_ENCODER_H +#include "internal/Encoder.h" + #include <memory> #include <algorithm> #include <iomanip> @@ -23,20 +25,20 @@ #include <fairlogger/Logger.h> #include <stdexcept> -#include "SymbolTable.h" -#include "EncoderSymbol.h" -#include "Coder.h" -#include "helper.h" +#include "internal/EncoderSymbol.h" +#include "internal/helper.h" +#include "internal/SymbolTable.h" namespace o2 { namespace rans { + template <typename coder_T, typename stream_T, typename source_T> class Encoder { - private: - using encoderSymbolTable_t = SymbolTable<EncoderSymbol<coder_T>>; + protected: + using encoderSymbolTable_t = internal::SymbolTable<internal::EncoderSymbol<coder_T>, source_T>; public: Encoder() = delete; @@ -48,7 +50,7 @@ class Encoder Encoder(const encoderSymbolTable_t& e, size_t probabilityBits); Encoder(encoderSymbolTable_t&& e, size_t probabilityBits); - Encoder(const SymbolStatistics& stats, size_t probabilityBits); + Encoder(const SymbolStatistics<source_T>& stats, size_t probabilityBits); template <typename stream_IT, typename source_IT> const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd, @@ -58,11 +60,11 @@ class Encoder using stream_t = stream_T; using source_t = source_T; - private: + protected: std::unique_ptr<encoderSymbolTable_t> mSymbolTable; size_t mProbabilityBits; - using ransCoder = Coder<coder_T, stream_T>; + using ransCoder = internal::Encoder<coder_T, stream_T>; }; template <typename coder_T, typename stream_T, typename source_T> @@ -89,9 +91,10 @@ template <typename coder_T, typename stream_T, typename source_T> Encoder<coder_T, stream_T, source_T>::Encoder(encoderSymbolTable_t&& e, size_t probabilityBits) : mSymbolTable(std::move(e.mSymbolTable)), mProbabilityBits(probabilityBits){}; template <typename coder_T, typename stream_T, typename source_T> -Encoder<coder_T, stream_T, source_T>::Encoder(const SymbolStatistics& stats, +Encoder<coder_T, stream_T, source_T>::Encoder(const SymbolStatistics<source_T>& stats, size_t probabilityBits) : mSymbolTable(nullptr), mProbabilityBits(probabilityBits) { + using namespace internal; RANSTimer t; t.start(); mSymbolTable = std::make_unique<encoderSymbolTable_t>(stats, probabilityBits); @@ -101,9 +104,9 @@ Encoder<coder_T, stream_T, source_T>::Encoder(const SymbolStatistics& stats, template <typename coder_T, typename stream_T, typename source_T> template <typename stream_IT, typename source_IT> -const stream_IT Encoder<coder_T, stream_T, source_T>::Encoder::process( - const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd) const +const stream_IT Encoder<coder_T, stream_T, source_T>::Encoder::process(const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd) const { + using namespace internal; LOG(trace) << "start encoding"; RANSTimer t; t.start(); @@ -123,30 +126,31 @@ const stream_IT Encoder<coder_T, stream_T, source_T>::Encoder::process( } ransCoder rans0, rans1; - rans0.encInit(); - rans1.encInit(); stream_IT outputIter = outputBegin; source_IT inputIT = inputEnd; const auto inputBufferSize = std::distance(inputBegin, inputEnd); + auto encode = [this](source_IT symbolIter, stream_IT outputIter, ransCoder& coder) { + const source_T symbol = *symbolIter; + const auto& encoderSymbol = (*this->mSymbolTable)[symbol]; + return std::tuple(symbolIter, coder.putSymbol(outputIter, encoderSymbol, this->mProbabilityBits)); + }; + // odd number of bytes? if (inputBufferSize & 1) { - const coder_T s = *(--inputIT); - outputIter = rans0.encPutSymbol(outputIter, (*mSymbolTable)[s], mProbabilityBits); + std::tie(inputIT, outputIter) = encode(--inputIT, outputIter, rans0); assert(outputIter < outputEnd); } while (inputIT > inputBegin) { // NB: working in reverse! - const coder_T s1 = *(--inputIT); - const coder_T s0 = *(--inputIT); - outputIter = rans1.encPutSymbol(outputIter, (*mSymbolTable)[s1], mProbabilityBits); - outputIter = rans0.encPutSymbol(outputIter, (*mSymbolTable)[s0], mProbabilityBits); + std::tie(inputIT, outputIter) = encode(--inputIT, outputIter, rans1); + std::tie(inputIT, outputIter) = encode(--inputIT, outputIter, rans0); assert(outputIter < outputEnd); } - outputIter = rans1.encFlush(outputIter); - outputIter = rans0.encFlush(outputIter); + outputIter = rans1.flush(outputIter); + outputIter = rans0.flush(outputIter); // first iterator past the range so that sizes, distances and iterators work correctly. ++outputIter; diff --git a/Utilities/rANS/include/rANS/LiteralDecoder.h b/Utilities/rANS/include/rANS/LiteralDecoder.h new file mode 100644 index 0000000000000..ef42c27442dd9 --- /dev/null +++ b/Utilities/rANS/include/rANS/LiteralDecoder.h @@ -0,0 +1,108 @@ +// 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 Decoder.h +/// @author Michael Lettrich +/// @since 2020-04-06 +/// @brief Decoder - decode a rANS encoded state back into source symbols + +#ifndef RANS_LITERALDECODER_H +#define RANS_LITERALDECODER_H + +#include "Decoder.h" + +#include <cstddef> +#include <type_traits> +#include <iostream> +#include <string> + +#include <fairlogger/Logger.h> + +#include "internal/DecoderSymbol.h" +#include "internal/ReverseSymbolLookupTable.h" +#include "internal/SymbolTable.h" +#include "internal/Decoder.h" + +namespace o2 +{ +namespace rans +{ + +template <typename coder_T, typename stream_T, typename source_T> +class LiteralDecoder : public Decoder<coder_T, stream_T, source_T> +{ + //inherit constructors; + using Decoder<coder_T, stream_T, source_T>::Decoder; + + public: + template <typename stream_IT, typename source_IT> + void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, std::vector<source_T>& literals) const; +}; + +template <typename coder_T, typename stream_T, typename source_T> +template <typename stream_IT, typename source_IT> +void LiteralDecoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, std::vector<source_T>& literals) const +{ + using namespace internal; + using ransDecoder = internal::Decoder<coder_T, stream_T>; + LOG(trace) << "start decoding"; + RANSTimer t; + t.start(); + static_assert(std::is_same<typename std::iterator_traits<source_IT>::value_type, source_T>::value); + static_assert(std::is_same<typename std::iterator_traits<stream_IT>::value_type, stream_T>::value); + + if (messageLength == 0) { + LOG(warning) << "Empty message passed to decoder, skipping decode process"; + return; + } + + stream_IT inputIter = inputEnd; + source_IT it = outputBegin; + + auto decode = [&, this](ransDecoder& decoder) { + auto cumul = decoder.get(this->mProbabilityBits); + const uint32_t streamSymbol = (*this->mReverseLUT)[cumul]; + source_T symbol = streamSymbol; + if (this->mSymbolTable->isLiteralSymbol(streamSymbol)) { + symbol = literals.back(); + literals.pop_back(); + } + + return std::make_tuple(symbol, decoder.advanceSymbol(inputIter, (*this->mSymbolTable)[streamSymbol], this->mProbabilityBits)); + }; + + // make Iter point to the last last element + --inputIter; + + ransDecoder rans0, rans1; + inputIter = rans0.init(inputIter); + inputIter = rans1.init(inputIter); + + for (size_t i = 0; i < (messageLength & ~1); i += 2) { + std::tie(*it++, inputIter) = decode(rans0); + std::tie(*it++, inputIter) = decode(rans1); + } + + // last byte, if message length was odd + if (messageLength & 1) { + std::tie(*it++, inputIter) = decode(rans0); + } + t.stop(); + LOG(debug1) << "Decoder::" << __func__ << " { DecodedSymbols: " << messageLength << "," + << "processedBytes: " << messageLength * sizeof(source_T) << "," + << " inclusiveTimeMS: " << t.getDurationMS() << "," + << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (messageLength * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; + + LOG(trace) << "done decoding"; +} +} // namespace rans +} // namespace o2 + +#endif /* RANS_LITERALDECODER_H */ diff --git a/Utilities/rANS/include/rANS/LiteralEncoder.h b/Utilities/rANS/include/rANS/LiteralEncoder.h new file mode 100644 index 0000000000000..13d4abf265bcd --- /dev/null +++ b/Utilities/rANS/include/rANS/LiteralEncoder.h @@ -0,0 +1,150 @@ +// 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 Encoder.h +/// @author Michael Lettrich +/// @since 2020-04-06 +/// @brief Encoder - code symbol into a rANS encoded state + +#ifndef RANS_LITERAL_ENCODER_H +#define RANS_LITERAL_ENCODER_H + +#include "Encoder.h" + +#include <memory> +#include <algorithm> +#include <iomanip> + +#include <fairlogger/Logger.h> +#include <stdexcept> + +#include "internal/EncoderSymbol.h" +#include "internal/helper.h" +#include "internal/SymbolTable.h" + +namespace o2 +{ +namespace rans +{ + +template <typename coder_T, typename stream_T, typename source_T> +class LiteralEncoder : public Encoder<coder_T, stream_T, source_T> +{ + //inherit constructors; + using Encoder<coder_T, stream_T, source_T>::Encoder; + + public: + template <typename stream_IT, typename source_IT> + const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd, + const source_IT inputBegin, source_IT inputEnd, std::vector<source_T>& literals) const; +}; + +template <typename coder_T, typename stream_T, typename source_T> +template <typename stream_IT, typename source_IT> +const stream_IT LiteralEncoder<coder_T, stream_T, source_T>::process(const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd, std::vector<source_T>& literals) const +{ + using namespace internal; + using ransCoder = internal::Encoder<coder_T, stream_T>; + LOG(trace) << "start encoding"; + RANSTimer t; + t.start(); + + static_assert(std::is_same<typename std::iterator_traits<source_IT>::value_type, source_T>::value); + static_assert(std::is_same<typename std::iterator_traits<stream_IT>::value_type, stream_T>::value); + + if (inputBegin == inputEnd) { + LOG(warning) << "passed empty message to encoder, skip encoding"; + return outputEnd; + } + + if (outputBegin == outputEnd) { + const std::string errorMessage("Unallocated encode buffer passed to encoder. Aborting"); + LOG(error) << errorMessage; + throw std::runtime_error(errorMessage); + } + + ransCoder rans0, rans1; + + stream_IT outputIter = outputBegin; + source_IT inputIT = inputEnd; + + const auto inputBufferSize = std::distance(inputBegin, inputEnd); + + auto encode = [&literals, this](source_IT symbolIter, stream_IT outputIter, ransCoder& coder) { + const source_T symbol = *symbolIter; + const auto& encoderSymbol = (*this->mSymbolTable)[symbol]; + if (encoderSymbol.freq != 0) { + return std::tuple(symbolIter, coder.putSymbol(outputIter, encoderSymbol, this->mProbabilityBits)); + } else { + literals.push_back(symbol); + return std::tuple(symbolIter, coder.putSymbol(outputIter, this->mSymbolTable->getLiteralSymbol(), this->mProbabilityBits)); + } + }; + + // odd number of bytes? + if (inputBufferSize & 1) { + std::tie(inputIT, outputIter) = encode(--inputIT, outputIter, rans0); + assert(outputIter < outputEnd); + } + + while (inputIT > inputBegin) { // NB: working in reverse! + std::tie(inputIT, outputIter) = encode(--inputIT, outputIter, rans1); + std::tie(inputIT, outputIter) = encode(--inputIT, outputIter, rans0); + assert(outputIter < outputEnd); + } + outputIter = rans1.flush(outputIter); + outputIter = rans0.flush(outputIter); + // first iterator past the range so that sizes, distances and iterators work correctly. + ++outputIter; + + assert(!(outputIter > outputEnd)); + + // deal with overflow + if (outputIter > outputEnd) { + const std::string exceptionText = [&]() { + std::stringstream ss; + ss << __func__ << " detected overflow in encode buffer: allocated:" << std::distance(outputBegin, outputEnd) << ", used:" << std::distance(outputBegin, outputIter); + return ss.str(); + }(); + + LOG(error) << exceptionText; + throw std::runtime_error(exceptionText); + } + + t.stop(); + LOG(debug1) << "Encoder::" << __func__ << " {ProcessedBytes: " << inputBufferSize * sizeof(source_T) << "," + << " inclusiveTimeMS: " << t.getDurationMS() << "," + << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (inputBufferSize * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; + +// advanced diagnostics for debug builds +#if !defined(NDEBUG) + + const auto inputBufferSizeB = inputBufferSize * sizeof(source_T); + const auto outputBufferSizeB = std::distance(outputBegin, outputIter) * sizeof(stream_T); + + LOG(debug2) << "EncoderProperties: {" + << "sourceTypeB: " << sizeof(source_T) << ", " + << "streamTypeB: " << sizeof(stream_T) << ", " + << "coderTypeB: " << sizeof(coder_T) << ", " + << "probabilityBits: " << this->mProbabilityBits << ", " + << "inputBufferSizeB: " << inputBufferSizeB << ", " + << "outputBufferSizeB: " << outputBufferSizeB << ", " + << "compressionFactor: " << std::fixed << std::setprecision(2) << static_cast<double>(inputBufferSizeB) / static_cast<double>(outputBufferSizeB) << "}"; +#endif + + LOG(trace) << "done encoding"; + + return outputIter; +}; + +} // namespace rans +} // namespace o2 + +#endif /* RANS_LITERAL_ENCODER_H */ diff --git a/Utilities/rANS/include/rANS/SymbolStatistics.h b/Utilities/rANS/include/rANS/SymbolStatistics.h index 1337d08a80d91..12d4c8bf7221d 100644 --- a/Utilities/rANS/include/rANS/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/SymbolStatistics.h @@ -23,59 +23,65 @@ #include <vector> #include <cmath> #include <iterator> +#include <type_traits> #include <fairlogger/Logger.h> -#include "helper.h" +#include "internal/helper.h" namespace o2 { namespace rans { +template <typename Source_T> class SymbolStatistics { + static_assert(std::is_integral<Source_T>() && sizeof(Source_T) <= sizeof(uint32_t), "Source symbols restricted to integer types"); + public: class Iterator { public: - Iterator(int64_t index, const SymbolStatistics& stats); + Iterator(size_t index, const SymbolStatistics& stats); using difference_type = int64_t; - using value_type = std::pair<uint32_t, uint32_t>; - using pointer = const std::pair<uint32_t, uint32_t>*; - using reference = const std::pair<uint32_t, uint32_t>&; + using value_type = std::tuple<uint32_t, uint32_t>; + using pointer = const std::tuple<uint32_t, uint32_t>*; + using reference = const std::tuple<uint32_t, uint32_t>&; using iterator_category = std::random_access_iterator_tag; const Iterator& operator++(); + difference_type operator-(const Iterator& other) const; + value_type operator*() const; bool operator!=(const Iterator& other) const; private: - int64_t mIndex; - const SymbolStatistics& mStats; + size_t mIndex; + const SymbolStatistics<Source_T>& mStats; }; public: template <typename IT> - SymbolStatistics(const IT begin, const IT end, size_t range = 0); + SymbolStatistics(const IT begin, const IT end, Source_T min = 0, Source_T max = 0); template <typename IT> - SymbolStatistics(const IT begin, const IT end, int64_t min, int64_t max, size_t messageLength); + SymbolStatistics(const IT begin, const IT end, int32_t min, int32_t max, size_t messageLength); void rescaleToNBits(size_t bits); - int getMinSymbol() const; - int getMaxSymbol() const; + int32_t getMinSymbol() const; + int32_t getMaxSymbol() const; size_t getAlphabetSize() const; size_t getAlphabetRangeBits() const; size_t getNUsedAlphabetSymbols() const; size_t getMessageLength() const; - std::pair<uint32_t, uint32_t> operator[](int64_t index) const; + std::tuple<uint32_t, uint32_t> operator[](size_t index) const; SymbolStatistics::Iterator begin() const; SymbolStatistics::Iterator end() const; @@ -86,19 +92,22 @@ class SymbolStatistics void buildCumulativeFrequencyTable(); auto getFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } template <typename IT> - void buildFrequencyTable(const IT begin, const IT end, size_t range); + void buildFrequencyTable(const IT begin, const IT end); - int64_t mMin; - int64_t mMax; - size_t mNUsedAlphabetSymbols; + int32_t mMin; + int32_t mMax; size_t mMessageLength; std::vector<uint32_t> mFrequencyTable; std::vector<uint32_t> mCumulativeFrequencyTable; + + static constexpr size_t MAX_RANGE = 26; }; +template <typename Source_T> template <typename IT> -SymbolStatistics::SymbolStatistics(const IT begin, const IT end, size_t range) : mMin(0), mMax(0), mNUsedAlphabetSymbols(0), mMessageLength(0), mFrequencyTable(), mCumulativeFrequencyTable() +SymbolStatistics<Source_T>::SymbolStatistics(const IT begin, const IT end, Source_T min, Source_T max) : mMin(min), mMax(max), mMessageLength(0), mFrequencyTable(), mCumulativeFrequencyTable() { + using namespace internal; LOG(trace) << "start building symbol statistics"; RANSTimer t; t.start(); @@ -107,17 +116,31 @@ SymbolStatistics::SymbolStatistics(const IT begin, const IT end, size_t range) : return; } - buildFrequencyTable(begin, end, range); + //find size + if (mMin == 0 && mMax == 0) { + LOG(trace) << "finding minmax"; + const auto& [minIter, maxIter] = std::minmax_element(begin, end); + mMin = *minIter; + mMax = *maxIter; + LOG(trace) << "min: " << mMin << ", max: " << mMax; + } - for (auto i : mFrequencyTable) { - if (i > 0) { - mNUsedAlphabetSymbols++; - } + // range check + if (max - min > 1 << (MAX_RANGE - 1)) { + const std::string errmsg = [&]() { + std::stringstream ss; + ss << "Range of source message " << getAlphabetRangeBits() << "Bits surpasses maximal allowed range of " << MAX_RANGE << "Bits."; + return ss.str(); + }(); + LOG(error) << errmsg; + throw std::runtime_error(errmsg); } + buildFrequencyTable(begin, end); + buildCumulativeFrequencyTable(); - mMessageLength = mCumulativeFrequencyTable.back(); + mMessageLength = std::distance(begin, end); assert(mFrequencyTable.size() > 0); assert(mCumulativeFrequencyTable.size() > 1); @@ -129,15 +152,6 @@ SymbolStatistics::SymbolStatistics(const IT begin, const IT end, size_t range) : // advanced diagnostics in debug builds #if !defined(NDEBUG) [&]() { - const uint messageRange = [&]() -> uint { - if (range > 0) { - return range; - } else if (mMax - mMin == 0) { - return 1; - } else { - return std::ceil(std::log2(mMax - mMin)); - } }(); - double entropy = 0; for (auto frequency : mFrequencyTable) { if (frequency > 0) { @@ -146,75 +160,266 @@ SymbolStatistics::SymbolStatistics(const IT begin, const IT end, size_t range) : } } + size_t nUsedAlphabetSymbols = 0; + for (auto symbolCount : mFrequencyTable) { + if (symbolCount > 0) { + ++nUsedAlphabetSymbols; + } + } + const auto minmax = std::minmax_element(begin, end); + LOG(debug2) << "messageProperties: {" - << "numSymbols: " << mMessageLength << ", " - << "alphabetRange: " << messageRange << ", " - << "alphabetSize: " << mNUsedAlphabetSymbols << ", " - << "minSymbol: " << mMin << ", " - << "maxSymbol: " << mMax << ", " + << "messageLength: " << mMessageLength << ", " + << "alphabetRange: " << getAlphabetRangeBits() << ", " + << "alphabetSize: " << nUsedAlphabetSymbols << ", " + << "minSymbol: " << *minmax.first << ", " + << "maxSymbol: " << *minmax.second << ", " << "entropy: " << entropy << ", " << "bufferSizeB: " << mMessageLength * sizeof(typename std::iterator_traits<IT>::value_type) << ", " - << "actualSizeB: " << static_cast<int>(mMessageLength * messageRange / 8) << ", " + << "actualSizeB: " << static_cast<int>(mMessageLength * getAlphabetRangeBits() / 8) << ", " << "entropyMessageB: " << static_cast<int>(std::ceil(entropy * mMessageLength / 8)) << "}"; LOG(debug2) << "SymbolStatistics: {" << "entries: " << mFrequencyTable.size() << ", " - << "frequencyTableSizeB: " << mFrequencyTable.size() * sizeof(std::decay_t<decltype(mFrequencyTable)>::value_type) << ", " - << "CumulativeFrequencyTableSizeB: " << mCumulativeFrequencyTable.size() * sizeof(std::decay_t<decltype(mCumulativeFrequencyTable)>::value_type) << "}"; + << "frequencyTableSizeB: " << mFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mFrequencyTable)>::value_type) << ", " + << "CumulativeFrequencyTableSizeB: " << mCumulativeFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mCumulativeFrequencyTable)>::value_type) << "}"; }(); #endif LOG(trace) << "done building symbol statistics"; } +template <typename Source_T> template <typename IT> -SymbolStatistics::SymbolStatistics(const IT begin, const IT end, int64_t min, int64_t max, size_t messageLength) : mMin(min), mMax(max), mNUsedAlphabetSymbols(0), mMessageLength(messageLength), mFrequencyTable(begin, end), mCumulativeFrequencyTable() +SymbolStatistics<Source_T>::SymbolStatistics(const IT begin, const IT end, int32_t min, int32_t max, size_t messageLength) : mMin(min), mMax(max), mMessageLength(messageLength), mFrequencyTable(begin, end), mCumulativeFrequencyTable() { LOG(trace) << "start loading external symbol statistics"; - for (auto i : mFrequencyTable) { - if (i > 0) { - mNUsedAlphabetSymbols++; - } - } buildCumulativeFrequencyTable(); + LOG(debug2) << "SymbolStatistics: {" + << "messageLength: " << mMessageLength << ", " + << "entries: " << mFrequencyTable.size() << ", " + << "frequencyTableSizeB: " << mFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mFrequencyTable)>::value_type) << ", " + << "CumulativeFrequencyTableSizeB: " << mCumulativeFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mCumulativeFrequencyTable)>::value_type) << "}"; + LOG(trace) << "done loading external symbol statistics"; } +template <typename Source_T> template <typename IT> -void SymbolStatistics::buildFrequencyTable(const IT begin, const IT end, - size_t range) +void SymbolStatistics<Source_T>::buildFrequencyTable(const IT begin, const IT end) { + using namespace internal; LOG(trace) << "start building frequency table"; - // find min_ and max_ - const auto minmax = std::minmax_element(begin, end); - if (range > 0) { // FIXME: providing the range will work only for data [0 : (1 << range) - 1] - mMin = 0; - mMax = (1 << range) - 1; + ++mMax; + const size_t size = mMax - mMin; + LOG(trace) << "size: " << size; + assert(size > 0); + mFrequencyTable.resize(size + 1, 0); + + for (IT it = begin; it != end; it++) { + const auto value = *it - mMin; + assert(value >= 0); + assert(value < size); + mFrequencyTable[value]++; + } + mFrequencyTable.back() = 1; + + LOG(trace) << "done building frequency table"; +} +template <typename Source_T> +void SymbolStatistics<Source_T>::rescaleToNBits(size_t bits) +{ + using namespace internal; + LOG(trace) << "start rescaling frequency table"; + RANSTimer t; + t.start(); + + if (mFrequencyTable.empty()) { + LOG(warning) << "rescaling Frequency Table for empty message"; + return; + } - // do checks - if (static_cast<unsigned int>(mMin) > *minmax.first) { - throw std::runtime_error("min of data too small for specified range"); + const size_t newCumulatedFrequency = bitsToRange(bits); + assert(newCumulatedFrequency > this->getNUsedAlphabetSymbols()); + + size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); + + // resample distribution based on cumulative frequencies_ + for (size_t i = 1; i <= mFrequencyTable.size(); i++) + mCumulativeFrequencyTable[i] = + (static_cast<uint64_t>(newCumulatedFrequency) * + mCumulativeFrequencyTable[i]) / + cumulatedFrequencies; + + // if we nuked any non-0 frequency symbol to 0, we need to steal + // the range to make the frequency nonzero from elsewhere. + // + // this is not at all optimal, i'm just doing the first thing that comes to + // mind. + for (size_t i = 0; i < mFrequencyTable.size(); i++) { + if (mFrequencyTable[i] && + mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]) { + // symbol i was set to zero freq + + // find best symbol to steal frequency from (try to steal from low-freq + // ones) + std::pair<size_t, size_t> stealFromEntry{mFrequencyTable.size(), ~0u}; + for (size_t j = 0; j < mFrequencyTable.size(); j++) { + uint32_t frequency = + mCumulativeFrequencyTable[j + 1] - mCumulativeFrequencyTable[j]; + if (frequency > 1 && frequency < stealFromEntry.second) { + stealFromEntry.second = frequency; + stealFromEntry.first = j; + } + } + assert(stealFromEntry.first != mFrequencyTable.size()); + + // and steal from it! + if (stealFromEntry.first < i) { + for (size_t j = stealFromEntry.first + 1; j <= i; j++) + mCumulativeFrequencyTable[j]--; + } else { + assert(stealFromEntry.first > i); + for (size_t j = i + 1; j <= stealFromEntry.first; j++) + mCumulativeFrequencyTable[j]++; + } } + } - if (static_cast<unsigned int>(mMax) < *minmax.second) { - throw std::runtime_error("max of data too big for specified range"); + // calculate updated freqs and make sure we didn't screw anything up + assert(mCumulativeFrequencyTable.front() == 0 && + mCumulativeFrequencyTable.back() == newCumulatedFrequency); + for (size_t i = 0; i < mFrequencyTable.size(); i++) { + if (mFrequencyTable[i] == 0) + assert(mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]); + else + assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); + + // calc updated freq + mFrequencyTable[i] = + mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; + } + // for(int i = 0; i<static_cast<int>(freqs.getNumSymbols()); i++){ + // std::cout << i << ": " << i + min_ << " " << freqs[i] << " " << + // cummulatedFrequencies_[i] << std::endl; + // } + // std::cout << cummulatedFrequencies_.back() << std::endl; + + t.stop(); + LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + + LOG(trace) << "done rescaling frequency table"; +} + +template <typename Source_T> +int32_t SymbolStatistics<Source_T>::getMinSymbol() const +{ + return mMin; +} + +template <typename Source_T> +int32_t SymbolStatistics<Source_T>::getMaxSymbol() const +{ + return mMax; +} + +template <typename Source_T> +size_t SymbolStatistics<Source_T>::getAlphabetSize() const +{ + return mFrequencyTable.size(); +} +template <typename Source_T> +size_t SymbolStatistics<Source_T>::getAlphabetRangeBits() const +{ + return std::ceil(std::log2(mMax - mMin)); +} +template <typename Source_T> +size_t SymbolStatistics<Source_T>::getNUsedAlphabetSymbols() const +{ + size_t nUsedAlphabetSymbols = 0; + for (auto symbolCount : mFrequencyTable) { + if (symbolCount > 0) { + ++nUsedAlphabetSymbols; } - } else { - mMin = *minmax.first; - mMax = *minmax.second; } - assert(mMax >= mMin); + return nUsedAlphabetSymbols; +} - mFrequencyTable.resize(std::abs(mMax - mMin) + 1, 0); +template <typename Source_T> +size_t SymbolStatistics<Source_T>::getMessageLength() const +{ + return mMessageLength; +} +template <typename Source_T> +std::tuple<uint32_t, uint32_t> SymbolStatistics<Source_T>::operator[](size_t index) const +{ + // assert(index - mMin < mFrequencyTable.size()); - for (IT it = begin; it != end; it++) { - mFrequencyTable[*it - mMin]++; + return {mFrequencyTable[index], mCumulativeFrequencyTable[index]}; +} +template <typename Source_T> +void SymbolStatistics<Source_T>::buildCumulativeFrequencyTable() +{ + LOG(trace) << "start building cumulative frequency table"; + + mCumulativeFrequencyTable.resize(mFrequencyTable.size() + 1); + mCumulativeFrequencyTable[0] = 0; + std::partial_sum(mFrequencyTable.begin(), mFrequencyTable.end(), + mCumulativeFrequencyTable.begin() + 1); + + LOG(trace) << "done building cumulative frequency table"; +} + +template <typename Source_T> +typename SymbolStatistics<Source_T>::Iterator SymbolStatistics<Source_T>::begin() const +{ + return SymbolStatistics::Iterator(0, *this); +} + +template <typename Source_T> +typename SymbolStatistics<Source_T>::Iterator SymbolStatistics<Source_T>::end() const +{ + if (mFrequencyTable.empty()) { + return this->begin(); // begin == end for empty stats; + } else { + return SymbolStatistics::Iterator(mFrequencyTable.size(), *this); } - LOG(trace) << "done building frequency table"; } + +template <typename Source_T> +SymbolStatistics<Source_T>::Iterator::Iterator(size_t index, const SymbolStatistics<Source_T>& stats) : mIndex(index), mStats(stats) +{ +} + +template <typename Source_T> +const typename SymbolStatistics<Source_T>::Iterator& SymbolStatistics<Source_T>::Iterator::operator++() +{ + ++mIndex; + assert(mIndex <= mStats.getMaxSymbol() + 1); + return *this; +} + +template <typename Source_T> +typename SymbolStatistics<Source_T>::Iterator::difference_type SymbolStatistics<Source_T>::Iterator::operator-(const Iterator& other) const +{ + return mIndex - other.mIndex; +} + +template <typename Source_T> +typename SymbolStatistics<Source_T>::Iterator::value_type SymbolStatistics<Source_T>::Iterator::operator*() const +{ + return std::move(mStats[mIndex]); +} + +template <typename Source_T> +bool SymbolStatistics<Source_T>::Iterator::operator!=(const Iterator& other) const +{ + return this->mIndex != other.mIndex; +} + } // namespace rans } // namespace o2 diff --git a/Utilities/rANS/include/rANS/SymbolTable.h b/Utilities/rANS/include/rANS/SymbolTable.h deleted file mode 100644 index 0c421cfce97f2..0000000000000 --- a/Utilities/rANS/include/rANS/SymbolTable.h +++ /dev/null @@ -1,69 +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. - -/// @file SymbolTable.h -/// @author Michael Lettrich -/// @since 2019-06-21 -/// @brief Container for information needed to encode/decode a symbol of the alphabet - -#ifndef RANS_SYMBOLTABLE_H -#define RANS_SYMBOLTABLE_H - -#include <vector> -#include <cstdint> - -#include <fairlogger/Logger.h> - -#include "SymbolStatistics.h" - -namespace o2 -{ -namespace rans -{ - -template <typename T> -class SymbolTable -{ - public: - SymbolTable(const SymbolStatistics& symbolStats, uint64_t probabiltyBits) : mMin(symbolStats.getMinSymbol()) - { - LOG(trace) << "start building symbol table"; - mSymbolTable.reserve(symbolStats.getAlphabetSize()); - - for (const auto& entry : symbolStats) { - mSymbolTable.emplace_back(entry.second, entry.first, probabiltyBits); - } - -// advanced diagnostics for debug builds -#if !defined(NDEBUG) - LOG(debug2) << "SymbolTableProperties: {" - << "entries:" << mSymbolTable.size() << ", " - << "sizeB: " << mSymbolTable.size() * sizeof(T) << "}"; -#endif - - LOG(trace) << "done building symbol table"; - } - - const T& operator[](int index) const - { - auto idx = index - mMin; - assert(idx >= 0); - assert(idx < mSymbolTable.size()); - return mSymbolTable[idx]; - } - - private: - int mMin; - std::vector<T> mSymbolTable; -}; -} // namespace rans -} // namespace o2 - -#endif /* RANS_SYMBOLTABLE_H */ diff --git a/Utilities/rANS/include/rANS/internal/Decoder.h b/Utilities/rANS/include/rANS/internal/Decoder.h new file mode 100644 index 0000000000000..d983a1f91a34d --- /dev/null +++ b/Utilities/rANS/include/rANS/internal/Decoder.h @@ -0,0 +1,165 @@ +// 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 Decoder.h +/// @author Michael Lettrich +/// @since 2019-05-10 +/// @brief lass for decoding symbols using rANS + +#ifndef RANS_INTERNAL_DECODER_H_ +#define RANS_INTERNAL_DECODER_H_ + +#include <vector> +#include <cstdint> +#include <cassert> +#include <tuple> +#include <type_traits> + +#include "DecoderSymbol.h" +#include "EncoderSymbol.h" +#include "helper.h" + +namespace o2 +{ +namespace rans +{ +namespace internal +{ +__extension__ typedef unsigned __int128 uint128; + +template <typename State_T, typename Stream_T> +class Decoder +{ + // the Coder works either with a 64Bit state and 32 bit streaming or + //a 32 Bit state and 8 Bit streaming We need to make sure it gets initialized with + //the right template arguments at compile time. + static_assert((sizeof(State_T) == sizeof(uint32_t) && sizeof(Stream_T) == sizeof(uint8_t)) || + (sizeof(State_T) == sizeof(uint64_t) && sizeof(Stream_T) == sizeof(uint32_t)), + "Coder can either be 32Bit with 8 Bit stream type or 64 Bit Type with 32 Bit stream type"); + + public: + Decoder(); + + // Initializes a rANS decoder. + // Unlike the encoder, the decoder works forwards as you'd expect. + template <typename Stream_IT> + Stream_IT init(Stream_IT iter); + + // Returns the current cumulative frequency (map it to a symbol yourself!) + uint32_t get(uint32_t scale_bits); + + // Equivalent to Rans32DecAdvance that takes a symbol. + template <typename Stream_IT> + Stream_IT advanceSymbol(Stream_IT iter, const DecoderSymbol& sym, uint32_t scale_bits); + + private: + State_T mState; + + // Renormalize. + template <typename Stream_IT> + std::tuple<State_T, Stream_IT> renorm(State_T x, Stream_IT iter); + + // L ('l' in the paper) is the lower bound of our normalization interval. + // Between this and our byte-aligned emission, we use 31 (not 32!) bits. + // This is done intentionally because exact reciprocals for 31-bit uints + // fit in 32-bit uints: this permits some optimizations during encoding. + inline static constexpr State_T LOWER_BOUND = needs64Bit<State_T>() ? (1u << 31) : (1u << 23); // lower bound of our normalization interval + + inline static constexpr State_T STREAM_BITS = sizeof(Stream_T) * 8; // lower bound of our normalization interval +}; + +template <typename State_T, typename Stream_T> +Decoder<State_T, Stream_T>::Decoder() : mState(0){}; + +template <typename State_T, typename Stream_T> +template <typename Stream_IT> +Stream_IT Decoder<State_T, Stream_T>::init(Stream_IT iter) +{ + static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); + + State_T x = 0; + Stream_IT streamPos = iter; + + if constexpr (needs64Bit<State_T>()) { + x = static_cast<State_T>(*streamPos) << 0; + --streamPos; + x |= static_cast<State_T>(*streamPos) << 32; + --streamPos; + assert(std::distance(streamPos, iter) == 2); + } else { + x = static_cast<State_T>(*streamPos) << 0; + --streamPos; + x |= static_cast<State_T>(*streamPos) << 8; + --streamPos; + x |= static_cast<State_T>(*streamPos) << 16; + --streamPos; + x |= static_cast<State_T>(*streamPos) << 24; + --streamPos; + assert(std::distance(streamPos, iter) == 4); + } + + mState = x; + return streamPos; +}; + +template <typename State_T, typename Stream_T> +uint32_t Decoder<State_T, Stream_T>::get(uint32_t scale_bits) +{ + return mState & ((1u << scale_bits) - 1); +}; + +template <typename State_T, typename Stream_T> +template <typename Stream_IT> +Stream_IT Decoder<State_T, Stream_T>::advanceSymbol(Stream_IT iter, const DecoderSymbol& sym, uint32_t scale_bits) +{ + static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); + + State_T mask = (1ull << scale_bits) - 1; + + // s, x = D(x) + State_T x = mState; + x = sym.freq * (x >> scale_bits) + (x & mask) - sym.start; + + // renormalize + Stream_IT streamPos; + std::tie(mState, streamPos) = this->renorm(x, iter); + return streamPos; +}; + +template <typename State_T, typename Stream_T> +template <typename Stream_IT> +inline std::tuple<State_T, Stream_IT> Decoder<State_T, Stream_T>::renorm(State_T x, Stream_IT iter) +{ + static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); + + Stream_IT streamPos = iter; + + // renormalize + if (x < LOWER_BOUND) { + if constexpr (needs64Bit<State_T>()) { + x = (x << STREAM_BITS) | *streamPos; + --streamPos; + assert(x >= LOWER_BOUND); + } else { + + do { + x = (x << STREAM_BITS) | *streamPos; + --streamPos; + } while (x < LOWER_BOUND); + } + } + return std::make_tuple(x, streamPos); +} + +} // namespace internal +} // namespace rans +} // namespace o2 + +#endif /* RANS_INTERNAL_DECODER_H_ */ diff --git a/Utilities/rANS/include/rANS/DecoderSymbol.h b/Utilities/rANS/include/rANS/internal/DecoderSymbol.h similarity index 88% rename from Utilities/rANS/include/rANS/DecoderSymbol.h rename to Utilities/rANS/include/rANS/internal/DecoderSymbol.h index d022b3f8bdadf..b35a690fd8b3b 100644 --- a/Utilities/rANS/include/rANS/DecoderSymbol.h +++ b/Utilities/rANS/include/rANS/internal/DecoderSymbol.h @@ -13,8 +13,8 @@ /// @since 2019-05-21 /// @brief Structure containing all relevant information for decoding a rANS encoded symbol -#ifndef RANS_DECODERSYMBOL_H -#define RANS_DECODERSYMBOL_H +#ifndef RANS_INTERNAL_DECODERSYMBOL_H +#define RANS_INTERNAL_DECODERSYMBOL_H #include <cstdint> @@ -22,6 +22,8 @@ namespace o2 { namespace rans { +namespace internal +{ // Decoder symbols are straightforward. struct DecoderSymbol { @@ -37,8 +39,8 @@ struct DecoderSymbol { uint32_t start; // Start of range. uint32_t freq; // Symbol frequency. }; - +} // namespace internal } // namespace rans } // namespace o2 -#endif /* RANS_DECODERSYMBOL_H */ +#endif /* RANS_INTERNAL_DECODERSYMBOL_H */ diff --git a/Utilities/rANS/include/rANS/internal/Encoder.h b/Utilities/rANS/include/rANS/internal/Encoder.h new file mode 100644 index 0000000000000..c3e9c9fb04b89 --- /dev/null +++ b/Utilities/rANS/include/rANS/internal/Encoder.h @@ -0,0 +1,195 @@ +// 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 Encoder.h +/// @author Michael Lettrich +/// @since 2019-05-10 +/// @brief class for encoding symbols using rANS + +#ifndef RANS_INTERNAL_ENCODER_H +#define RANS_INTERNAL_ENCODER_H + +#include <vector> +#include <cstdint> +#include <cassert> +#include <type_traits> +#include <tuple> + +#include "DecoderSymbol.h" +#include "EncoderSymbol.h" +#include "helper.h" + +namespace o2 +{ +namespace rans +{ +namespace internal +{ + +template <typename State_T, typename Stream_T> +class Encoder +{ + __extension__ typedef unsigned __int128 uint128; + + // the Coder works either with a 64Bit state and 32 bit streaming or + //a 32 Bit state and 8 Bit streaming We need to make sure it gets initialized with + //the right template arguments at compile time. + static_assert((sizeof(State_T) == sizeof(uint32_t) && sizeof(Stream_T) == sizeof(uint8_t)) || + (sizeof(State_T) == sizeof(uint64_t) && sizeof(Stream_T) == sizeof(uint32_t)), + "Coder can either be 32Bit with 8 Bit stream type or 64 Bit Type with 32 Bit stream type"); + + public: + Encoder(); + + // Encodes a single symbol with range start "start" and frequency "freq". + // All frequencies are assumed to sum to "1 << scale_bits", and the + // resulting bytes get written to ptr (which is updated). + // + // NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from + // beginning to end! Likewise, the output bytestream is written *backwards*: + // ptr starts pointing at the end of the output buffer and keeps decrementing. + template <typename Stream_IT> + Stream_IT put(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits); + + // Flushes the rANS encoder. + template <typename Stream_IT> + Stream_IT flush(Stream_IT iter); + + // Encodes a given symbol. This is faster than straight RansEnc since we can do + // multiplications instead of a divide. + // + // See Rans32EncSymbolInit for a description of how this works. + template <typename Stream_IT> + Stream_IT putSymbol(Stream_IT iter, const EncoderSymbol<State_T>& sym, uint32_t scale_bits); + + private: + State_T mState; + + // Renormalize the encoder. + template <typename Stream_IT> + std::tuple<State_T, Stream_IT> renorm(State_T x, Stream_IT iter, uint32_t freq, uint32_t scale_bits); + + // L ('l' in the paper) is the lower bound of our normalization interval. + // Between this and our byte-aligned emission, we use 31 (not 32!) bits. + // This is done intentionally because exact reciprocals for 31-bit uints + // fit in 32-bit uints: this permits some optimizations during encoding. + inline static constexpr State_T LOWER_BOUND = needs64Bit<State_T>() ? (1u << 31) : (1u << 23); // lower bound of our normalization interval + + inline static constexpr State_T STREAM_BITS = sizeof(Stream_T) * 8; // lower bound of our normalization interval +}; + +template <typename State_T, typename Stream_T> +Encoder<State_T, Stream_T>::Encoder() : mState(LOWER_BOUND){}; + +template <typename State_T, typename Stream_T> +template <typename Stream_IT> +Stream_IT Encoder<State_T, Stream_T>::put(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); + // renormalize + Stream_IT streamPos; + State_T x; + std::tie(x, streamPos) = renorm(mState, iter, freq, scale_bits); + + // x = C(s,x) + mState = ((x / freq) << scale_bits) + (x % freq) + start; + return streamPos; +}; + +template <typename State_T, typename Stream_T> +template <typename Stream_IT> +Stream_IT Encoder<State_T, Stream_T>::flush(Stream_IT iter) +{ + static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); + + Stream_IT streamPos = iter; + + if constexpr (needs64Bit<State_T>()) { + ++streamPos; + *streamPos = static_cast<Stream_T>(mState >> 32); + ++streamPos; + *streamPos = static_cast<Stream_T>(mState >> 0); + assert(std::distance(iter, streamPos) == 2); + } else { + ++streamPos; + *streamPos = static_cast<Stream_T>(mState >> 24); + ++streamPos; + *streamPos = static_cast<Stream_T>(mState >> 16); + ++streamPos; + *streamPos = static_cast<Stream_T>(mState >> 8); + ++streamPos; + *streamPos = static_cast<Stream_T>(mState >> 0); + assert(std::distance(iter, streamPos) == 4); + } + + mState = 0; + return streamPos; +}; + +template <typename State_T, typename Stream_T> +template <typename Stream_IT> +Stream_IT Encoder<State_T, Stream_T>::putSymbol(Stream_IT iter, const EncoderSymbol<State_T>& sym, uint32_t scale_bits) +{ + static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); + + assert(sym.freq != 0); // can't encode symbol with freq=0 + + // renormalize + Stream_IT streamPos; + State_T x; + std::tie(x, streamPos) = renorm(mState, iter, sym.freq, scale_bits); + + // x = C(s,x) + State_T q = 0; + + if constexpr (needs64Bit<State_T>()) { + // This code needs support for 64-bit long multiplies with 128-bit result + // (or more precisely, the top 64 bits of a 128-bit result). + q = static_cast<State_T>((static_cast<uint128>(x) * sym.rcp_freq) >> 64); + } else { + q = static_cast<State_T>((static_cast<uint64_t>(x) * sym.rcp_freq) >> 32); + } + q = q >> sym.rcp_shift; + + mState = x + sym.bias + q * sym.cmpl_freq; + return streamPos; +}; + +template <typename State_T, typename Stream_T> +template <typename Stream_IT> +inline std::tuple<State_T, Stream_IT> Encoder<State_T, Stream_T>::renorm(State_T x, Stream_IT iter, uint32_t freq, uint32_t scale_bits) +{ + static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value); + + Stream_IT streamPos = iter; + + State_T x_max = ((LOWER_BOUND >> scale_bits) << STREAM_BITS) * freq; // this turns into a shift. + if (x >= x_max) { + if constexpr (needs64Bit<State_T>()) { + ++streamPos; + *streamPos = static_cast<Stream_T>(x); + x >>= STREAM_BITS; + assert(x < x_max); + } else { + do { + ++streamPos; + *streamPos = static_cast<Stream_T>(x & 0xff); + x >>= STREAM_BITS; + } while (x >= x_max); + } + } + return std::make_tuple(x, streamPos); +}; + +} // namespace internal +} // namespace rans +} // namespace o2 + +#endif /* RANS_INTERNAL_ENCODER_H */ diff --git a/Utilities/rANS/include/rANS/EncoderSymbol.h b/Utilities/rANS/include/rANS/internal/EncoderSymbol.h similarity index 95% rename from Utilities/rANS/include/rANS/EncoderSymbol.h rename to Utilities/rANS/include/rANS/internal/EncoderSymbol.h index 8499a8afbd95f..b15ecb8105bf9 100644 --- a/Utilities/rANS/include/rANS/EncoderSymbol.h +++ b/Utilities/rANS/include/rANS/internal/EncoderSymbol.h @@ -13,19 +13,20 @@ /// @since 2019-05-21 /// @brief Structure containing all relevant information to encode a symbol. -#ifndef RANS_ENCODERSYMBOL_H -#define RANS_ENCODERSYMBOL_H +#ifndef RANS_INTERNAL_ENCODERSYMBOL_H +#define RANS_INTERNAL_ENCODERSYMBOL_H #include <cstdint> #include <cassert> -#include "helper.h" +#include "../internal/helper.h" namespace o2 { namespace rans { - +namespace internal +{ // Encoder symbol description // This (admittedly odd) selection of parameters was chosen to make // RansEncPutSymbol as cheap as possible. @@ -125,7 +126,8 @@ struct EncoderSymbol { uint32_t rcp_shift; // Reciprocal shift }; +} // namespace internal } //namespace rans } //namespace o2 -#endif /* RANS_ENCODERSYMBOL_H */ +#endif /* RANS_INTERNAL_ENCODERSYMBOL_H */ diff --git a/Utilities/rANS/include/rANS/ReverseSymbolLookupTable.h b/Utilities/rANS/include/rANS/internal/ReverseSymbolLookupTable.h similarity index 59% rename from Utilities/rANS/include/rANS/ReverseSymbolLookupTable.h rename to Utilities/rANS/include/rANS/internal/ReverseSymbolLookupTable.h index ec6d306009830..70deb2ff7b23d 100644 --- a/Utilities/rANS/include/rANS/ReverseSymbolLookupTable.h +++ b/Utilities/rANS/include/rANS/internal/ReverseSymbolLookupTable.h @@ -13,26 +13,28 @@ /// @since 2020-04-06 /// @brief Maps CDF back to source symbol - needed for the decoder -#ifndef RANS_REVERSESYMBOLLOOKUPTABLE_H -#define RANS_REVERSESYMBOLLOOKUPTABLE_H +#ifndef RANS_INTERNAL_REVERSESYMBOLLOOKUPTABLE_H +#define RANS_INTERNAL_REVERSESYMBOLLOOKUPTABLE_H #include <vector> #include <type_traits> #include <fairlogger/Logger.h> -#include "SymbolStatistics.h" -#include "helper.h" +#include "../internal/helper.h" +#include "rANS/SymbolStatistics.h" namespace o2 { namespace rans { -template <typename source_t> +namespace internal +{ +template <typename Source_T> class ReverseSymbolLookupTable { public: ReverseSymbolLookupTable(size_t probabilityBits, - const SymbolStatistics& stats) : mLut() + const SymbolStatistics<Source_T>& stats) : mLut() { LOG(trace) << "start building reverse symbol lookup table"; @@ -43,14 +45,23 @@ class ReverseSymbolLookupTable mLut.resize(bitsToRange(probabilityBits)); // go over all symbols - for (int symbol = stats.getMinSymbol(); symbol <= stats.getMaxSymbol(); - symbol++) { - for (uint32_t cumulative = stats[symbol].second; - cumulative < stats[symbol].second + stats[symbol].first; cumulative++) { + for (auto symbolIT = std::begin(stats); symbolIT != std::end(stats); ++symbolIT) { + auto symbol = stats.getMinSymbol() + std::distance(std::begin(stats), symbolIT); + const auto [symFrequency, symCumulated] = *symbolIT; + for (auto cumulative = symCumulated; + cumulative < symCumulated + symFrequency; cumulative++) { mLut[cumulative] = symbol; } } +// for (int symbol = stats.getMinSymbol(); symbol <= stats.getMaxSymbol(); +// symbol++) { +// for (uint32_t cumulative = stats[symbol].second; +// cumulative < stats[symbol].second + stats[symbol].first; cumulative++) { +// mLut[cumulative] = symbol; +// } +// } + // advanced diagnostics for debug builds #if !defined(NDEBUG) LOG(debug2) << "reverseSymbolLookupTableProperties: {" @@ -61,16 +72,17 @@ class ReverseSymbolLookupTable LOG(trace) << "done building reverse symbol lookup table"; }; - inline source_t operator[](size_t cummulative) const + inline int32_t operator[](size_t cummulative) const { return mLut[cummulative]; }; private: - std::vector<source_t> mLut; + std::vector<int32_t> mLut; }; +} // namespace internal } // namespace rans } // namespace o2 -#endif /* RANS_REVERSESYMBOLLOOKUPTABLE_H */ +#endif /* RANS_INTERNAL_REVERSESYMBOLLOOKUPTABLE_H */ diff --git a/Utilities/rANS/include/rANS/internal/SymbolTable.h b/Utilities/rANS/include/rANS/internal/SymbolTable.h new file mode 100644 index 0000000000000..922da16caf1d5 --- /dev/null +++ b/Utilities/rANS/include/rANS/internal/SymbolTable.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. + +/// @file SymbolTable.h +/// @author Michael Lettrich +/// @since 2019-06-21 +/// @brief Container for information needed to encode/decode a symbol of the alphabet + +#ifndef RANS_INTERNAL_SYMBOLTABLE_H +#define RANS_INTERNAL_SYMBOLTABLE_H + +#include <vector> +#include <cstdint> + +#include <fairlogger/Logger.h> + +#include "rANS/SymbolStatistics.h" + +namespace o2 +{ +namespace rans +{ +namespace internal +{ + +template <typename T, typename Source_T> +class SymbolTable +{ + + public: + SymbolTable(const SymbolStatistics<Source_T>& symbolStats, size_t probabiltyBits); + + const T& operator[](Source_T index) const; + + const T& getLiteralSymbol() const; + + bool isLiteralSymbol(Source_T index) const; + + private: + int mMin; + std::vector<T*> mIndex; + std::vector<T> mSymbols; +}; + +template <typename T, typename Source_T> +SymbolTable<T, Source_T>::SymbolTable(const SymbolStatistics<Source_T>& symbolStats, uint64_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mIndex(), mSymbols() +{ + LOG(trace) << "start building symbol table"; + + mIndex.reserve(symbolStats.getAlphabetSize()); + mSymbols.reserve(symbolStats.getAlphabetSize()); + + for (const auto& entry : symbolStats) { + const auto [symFrequency, symCumulated] = entry; + mSymbols.emplace_back(symCumulated, symFrequency, probabiltyBits); + mIndex.emplace_back(&mSymbols.back()); + } + +// advanced diagnostics for debug builds +#if !defined(NDEBUG) + LOG(debug2) << "SymbolTableProperties: {" + << "entries:" << mSymbols.size() << ", " + << "sizeB: " << mSymbols.size() * sizeof(T) + mIndex.size() * sizeof(T*) << "}"; +#endif + + LOG(trace) << "done building symbol table"; +} + +template <typename T, typename Source_T> +inline const T& SymbolTable<T, Source_T>::operator[](Source_T index) const +{ + const auto idx = index - mMin; + assert(idx >= 0); + assert(idx < mSymbols.size()); + return *(mIndex[idx]); +} + +template <typename T, typename Source_T> +inline bool SymbolTable<T, Source_T>::isLiteralSymbol(Source_T index) const +{ + const auto idx = index - mMin; + assert(idx >= 0); + assert(idx < mSymbols.size()); + return idx == mSymbols.size() - 1; +} + +template <typename T, typename Source_T> +inline const T& SymbolTable<T, Source_T>::getLiteralSymbol() const +{ + return mSymbols.back(); +} + +} // namespace internal +} // namespace rans +} // namespace o2 + +#endif /* RANS_INTERNAL_SYMBOLTABLE_H */ diff --git a/Utilities/rANS/include/rANS/helper.h b/Utilities/rANS/include/rANS/internal/helper.h similarity index 73% rename from Utilities/rANS/include/rANS/helper.h rename to Utilities/rANS/include/rANS/internal/helper.h index 5b7d8ce18fd6b..b8c5c46283d43 100644 --- a/Utilities/rANS/include/rANS/helper.h +++ b/Utilities/rANS/include/rANS/internal/helper.h @@ -13,8 +13,8 @@ /// @since 2019-05-21 /// @brief various helper functions -#ifndef RANS_HELPER_H -#define RANS_HELPER_H +#ifndef RANS_INTERNAL_HELPER_H +#define RANS_INTERNAL_HELPER_H #include <cstddef> #include <cmath> @@ -24,6 +24,8 @@ namespace o2 { namespace rans { +namespace internal +{ template <typename T> inline constexpr bool needs64Bit() @@ -36,18 +38,6 @@ inline constexpr size_t bitsToRange(size_t bits) return 1 << bits; } -inline size_t calculateMaxBufferSize(size_t num, size_t rangeBits, size_t sizeofStreamT) -{ - // RS: w/o safety margin the o2-test-ctf-io produces an overflow in the Encoder::process - constexpr size_t SaferyMargin = 16; - return std::ceil(1.20 * (num * rangeBits * 1.0) / (sizeofStreamT * 8.0)) + SaferyMargin; -} - -//rans default values -constexpr size_t ProbabilityBits8Bit = 10; -constexpr size_t ProbabilityBits16Bit = 22; -constexpr size_t ProbabilityBits25Bit = 25; - class RANSTimer { public: @@ -70,7 +60,8 @@ class RANSTimer std::chrono::time_point<std::chrono::high_resolution_clock> mStop; }; +} // namespace internal } // namespace rans } // namespace o2 -#endif /* RANS_HELPER_H */ +#endif /* RANS_INTERNAL_HELPER_H */ diff --git a/Utilities/rANS/include/rANS/rans.h b/Utilities/rANS/include/rANS/rans.h index 9650389ecdd65..9f99575bbab93 100644 --- a/Utilities/rANS/include/rANS/rans.h +++ b/Utilities/rANS/include/rANS/rans.h @@ -16,9 +16,14 @@ #ifndef RANS_RANS_H #define RANS_RANS_H -#include "rANS/SymbolStatistics.h" -#include "rANS/Encoder.h" -#include "rANS/Decoder.h" +#include "SymbolStatistics.h" +#include "Encoder.h" +#include "Decoder.h" +#include "DedupEncoder.h" +#include "DedupDecoder.h" +#include "LiteralEncoder.h" +#include "LiteralDecoder.h" +#include "internal/helper.h" namespace o2 { @@ -34,6 +39,18 @@ using Decoder32 = Decoder<uint32_t, uint8_t, source_T>; template <typename source_T> using Decoder64 = Decoder<uint64_t, uint32_t, source_T>; +//rans default values +constexpr size_t ProbabilityBits8Bit = 10; +constexpr size_t ProbabilityBits16Bit = 22; +constexpr size_t ProbabilityBits25Bit = 25; + +inline size_t calculateMaxBufferSize(size_t num, size_t rangeBits, size_t sizeofStreamT) +{ + // RS: w/o safety margin the o2-test-ctf-io produces an overflow in the Encoder::process + constexpr size_t SaferyMargin = 16; + return std::ceil(1.20 * (num * rangeBits * 1.0) / (sizeofStreamT * 8.0)) + SaferyMargin; +} + } // namespace rans } // namespace o2 diff --git a/Utilities/rANS/run/bin-encode-decode.cxx b/Utilities/rANS/run/bin-encode-decode.cxx index 5c4e4ec8fed05..82c2a810a92b5 100644 --- a/Utilities/rANS/run/bin-encode-decode.cxx +++ b/Utilities/rANS/run/bin-encode-decode.cxx @@ -30,7 +30,6 @@ using coder_t = uint64_t; using stream_t = uint32_t; static const uint REPETITIONS = 5; static const uint PROB_BITS = 18; -using Rans = o2::rans::Coder<coder_t, stream_t>; template <typename T> void readFile(const std::string& filename, std::vector<T>* tokens) @@ -124,8 +123,8 @@ int main(int argc, char* argv[]) std::vector<source_t> tokens; readFile(filename, &tokens); - std::unique_ptr<o2::rans::SymbolStatistics> stats = [&]() { - auto stats = std::make_unique<o2::rans::SymbolStatistics>(std::begin(tokens), std::end(tokens)); + std::unique_ptr<o2::rans::SymbolStatistics<source_t>> stats = [&]() { + auto stats = std::make_unique<o2::rans::SymbolStatistics<source_t>>(std::begin(tokens), std::end(tokens), symbolRangeBits); stats->rescaleToNBits(probabilityBits); return std::move(stats); }(); diff --git a/Utilities/rANS/test/test_ransEncodeDecode.cxx b/Utilities/rANS/test/test_ransEncodeDecode.cxx index d8b2fb4e4051f..50e00d6861568 100644 --- a/Utilities/rANS/test/test_ransEncodeDecode.cxx +++ b/Utilities/rANS/test/test_ransEncodeDecode.cxx @@ -37,6 +37,10 @@ struct Fixture { using encoder_t = o2::rans::Encoder<coder_t, stream_t, source_t>; using decoder_t = o2::rans::Decoder<coder_t, stream_t, source_t>; + using literalEncoder_t = o2::rans::LiteralEncoder<coder_t, stream_t, source_t>; + using literalDecoder_t = o2::rans::LiteralDecoder<coder_t, stream_t, source_t>; + using dedupEncoder_t = o2::rans::DedupEncoder<coder_t, stream_t, source_t>; + using dedupDecoder_t = o2::rans::DedupDecoder<coder_t, stream_t, source_t>; //TUNIG parameters // how many bits do we resample the symbol statistics to? @@ -55,16 +59,16 @@ struct Fixture { template <typename CODER_T, typename STREAM_T, uint P> struct FixtureFull : public Fixture<CODER_T, STREAM_T, P> { const std::string source = R"(Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium - doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis - et quasi architecto beatae vitae dicta sunt, explicabo. nemo enim ipsam voluptatem, - quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores - eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, - quia dolor sit, amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora - incidunt, ut labore et dolore magnam aliquam quaerat voluptatem. ut enim ad minima veniam, - quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea - commodi consequatur? quis autem vel eum iure reprehenderit, qui in ea voluptate velit - esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, - quo voluptas nulla pariatur?)"; +doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis +et quasi architecto beatae vitae dicta sunt, explicabo. nemo enim ipsam voluptatem, +quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores +eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, +quia dolor sit, amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora +incidunt, ut labore et dolore magnam aliquam quaerat voluptatem. ut enim ad minima veniam, +quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea +commodi consequatur? quis autem vel eum iure reprehenderit, qui in ea voluptate velit +esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, +quo voluptas nulla pariatur?)"; }; typedef boost::mpl::vector<Fixture<uint32_t, uint8_t, 14>, Fixture<uint64_t, uint32_t, 18>, FixtureFull<uint32_t, uint8_t, 14>, FixtureFull<uint64_t, uint32_t, 18>> Fixtures; @@ -73,7 +77,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode, T, Fixtures, T) { // iterate over the message and create PDF and CDF for each symbol in the message - o2::rans::SymbolStatistics stats{std::begin(T::source), std::end(T::source)}; + o2::rans::SymbolStatistics<typename T::source_t> stats{std::begin(T::source), std::end(T::source)}; // For performance reason the distributions must be rescaled to be a power of two. stats.rescaleToNBits(T::probabilityBits); @@ -101,3 +105,78 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode, T, Fixtures, T) BOOST_REQUIRE(std::memcmp(&(*T::source.begin()), decoderBuffer.data(), decoderBuffer.size() * sizeof(typename T::source_t)) == 0); } + +typedef boost::mpl::vector<FixtureFull<uint32_t, uint8_t, 14>, FixtureFull<uint64_t, uint32_t, 14>> LiteralFixtures; + +BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_literals, T, LiteralFixtures, T) +{ + // iterate over the message and create PDF and CDF for each symbol in the message + o2::rans::SymbolStatistics<typename T::source_t> stats{std::begin(T::source), std::end(T::source)}; + // For performance reason the distributions must be rescaled to be a power of two. + stats.rescaleToNBits(T::probabilityBits); + + std::string adaptedSource = "\\"; + adaptedSource.append(T::source); + adaptedSource.append("&%=/*!"); + + // buffer to write the rANS coded message into + std::vector<typename T::stream_t> encoderBuffer(1 << 20, 0); + //create a stateful encoder object that builds an encoding table from the given symbol statistics + const typename T::literalEncoder_t encoder{stats, T::probabilityBits}; + // encoder rANS encodes symbols from SOURCE array to encoder Buffer. Since coder and decoder + // are mathematical inverse functions on the ANS state, they operate as a stack - + // i.e. the decoder outputs the message in reverse order of the encoder. + // By convention the encoder runs backwards over the input so that the decoder can return + // the data in the expected order. The encoder will start from encoderBuffer.begin() + // and return an iterator one element past the last entry written. + // This means the encodeded message ranges from encoderBuffer.begin() to encodedMessageEnd -1, with (encodedMessageEnd -encoderBuffer.begin()) entries written. + std::vector<typename T::source_t> literals; + auto encodedMessageEnd = encoder.process(encoderBuffer.begin(), encoderBuffer.end(), std::begin(adaptedSource), std::end(adaptedSource), literals); + + // The decoded message will go into the decoder buffer which will have as many symbols as the original message + std::vector<typename T::source_t> decoderBuffer(std::distance(std::begin(adaptedSource), std::end(adaptedSource)), 0); + // create a stateful decoder object that build a decoding table from the given symbol statistics + const typename T::literalDecoder_t decoder{stats, T::probabilityBits}; + // the decoder unwinds the rANS state in the encoder buffer starting at ransBegin and decodes it into the decode buffer; + decoder.process(decoderBuffer.begin(), encodedMessageEnd, std::distance(std::begin(adaptedSource), std::end(adaptedSource)), literals); + + //the decodeBuffer and the source message have to be identical afterwards. + BOOST_REQUIRE(std::memcmp(&(*adaptedSource.begin()), decoderBuffer.data(), + decoderBuffer.size() * sizeof(typename T::source_t)) == 0); +} + +typedef boost::mpl::vector<FixtureFull<uint32_t, uint8_t, 14>, FixtureFull<uint64_t, uint32_t, 14>> DedupFixtures; + +BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_dedup, T, DedupFixtures, T) +{ + + // iterate over the message and create PDF and CDF for each symbol in the message + o2::rans::SymbolStatistics<typename T::source_t> stats{std::begin(T::source), std::end(T::source)}; + // For performance reason the distributions must be rescaled to be a power of two. + stats.rescaleToNBits(T::probabilityBits); + + // buffer to write the rANS coded message into + std::vector<typename T::stream_t> encoderBuffer(1 << 20, 0); + //create a stateful encoder object that builds an encoding table from the given symbol statistics + const typename T::dedupEncoder_t encoder{stats, T::probabilityBits}; + // encoder rANS encodes symbols from SOURCE array to encoder Buffer. Since coder and decoder + // are mathematical inverse functions on the ANS state, they operate as a stack - + // i.e. the decoder outputs the message in reverse order of the encoder. + // By convention the encoder runs backwards over the input so that the decoder can return + // the data in the expected order. The encoder will start from encoderBuffer.begin() + // and return an iterator one element past the last entry written. + // This means the encodeded message ranges from encoderBuffer.begin() to encodedMessageEnd -1, with (encodedMessageEnd -encoderBuffer.begin()) entries written. + std::map<uint32_t, uint32_t> duplicates; + auto encodedMessageEnd = encoder.process(encoderBuffer.begin(), encoderBuffer.end(), std::begin(T::source), std::end(T::source), duplicates); + + // The decoded message will go into the decoder buffer which will have as many symbols as the original message + std::vector<typename T::source_t> decoderBuffer(std::distance(std::begin(T::source), std::end(T::source)), 0); + // create a stateful decoder object that build a decoding table from the given symbol statistics + const typename T::dedupDecoder_t decoder{stats, T::probabilityBits}; + // the decoder unwinds the rANS state in the encoder buffer starting at ransBegin and decodes it into the decode buffer; + decoder.process(decoderBuffer.begin(), encodedMessageEnd, stats.getMessageLength(), duplicates); + + //the decodeBuffer and the source message have to be identical afterwards. + BOOST_REQUIRE(std::memcmp(&(*T::source.begin()), decoderBuffer.data(), + decoderBuffer.size() * sizeof(typename T::source_t)) == 0); +} From be8178b9a5fe483ec7e71d4e28da21e3a1f1378a Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Fri, 17 Jul 2020 17:37:20 +0200 Subject: [PATCH 0271/1751] [rANS] static dictionaries for EncodedBlocks * Allow EncodedBlocks to use static dictionaries by using the rans::LiteralEncoder that handles incompressible symbols * Extend Blocks datastructure handle literal symbols --- .../EncodedBlocks.h | 176 +++++++++++++----- .../rANS/include/rANS/SymbolStatistics.h | 103 +++++----- Utilities/rANS/include/rANS/rans.h | 20 ++ Utilities/rANS/src/SymbolStatistics.cxx | 174 ----------------- 4 files changed, 195 insertions(+), 278 deletions(-) delete mode 100644 Utilities/rANS/src/SymbolStatistics.cxx diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index def38fc60cf78..1d7c8f6b21850 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -68,6 +68,7 @@ struct Metadata { NODATA // no data was provided }; size_t messageLength = 0; + size_t nLiterals = 0; uint8_t coderType = 0; uint8_t streamSize = 0; uint8_t probabilityBits = 0; @@ -76,15 +77,19 @@ struct Metadata { int32_t max = 0; int nDictWords = 0; int nDataWords = 0; + int nLiteralWords = 0; void clear() { min = max = 0; messageLength = 0; + nLiterals = 0; coderType = 0; streamSize = 0; probabilityBits = 0; - nDataWords = nDictWords = 0; + nDictWords = 0; + nDataWords = 0; + nLiteralWords = 0; } ClassDefNV(Metadata, 1); }; @@ -125,15 +130,51 @@ struct Block { Registry* registry = nullptr; //! non-persistent info for in-memory ops int nDict = 0; // dictionary length (if any) - int nStored = 0; // total payload: data + dictionary length + int nData = 0; // length of data + int nLiterals = 0; // length of literals vector (if any) + int nStored = 0; // total length W* payload = nullptr; //[nStored]; - W* getData() { return payload ? (payload + nDict) : (registry ? (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())) : nullptr); } - W* getDict() { return nDict ? payload : nullptr; } - const W* getData() const { return payload ? (payload + nDict) : nullptr; } - const W* getDict() const { return nDict ? payload : nullptr; } - int getNData() const { return nStored - nDict; } - int getNDict() const { return nDict; } + inline W* getDict() { return payload ? payload : (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())); }; + inline W* getData() { return payload ? (payload + nDict) : (registry ? (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())) : nullptr); }; + W* getLiterals() + { + if (payload) { + return payload + nDict + nData; + } + if (registry) { + payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); + return payload + nDict + nData; + } + return nullptr; + }; + + inline const W* getDict() const { return nDict ? payload : nullptr; }; + inline const W* getData() const { return payload ? (payload + nDict) : nullptr; }; + inline const W* getLiterals() const { return nLiterals ? payload + nDict + nData : nullptr; }; + + inline void setNDict(int _ndict) + { + nDict = _ndict; + nStored += nDict; + } + + inline void setNData(int _ndata) + { + nData = _ndata; + nStored += nData; + } + + inline void setNLiterals(int _nliterals) + { + nLiterals = _nliterals; + nStored += nLiterals; + } + + inline int getNDict() const { return nDict; } + inline int getNData() const { return nData; } + inline int getNLiterals() const { return nLiterals; } + inline int getNStored() const { return nStored; } ~Block() { @@ -145,78 +186,98 @@ struct Block { /// clear itself void clear() { - nDict = nStored = 0; + nDict = 0; + nData = 0; + nLiterals = 0; + nStored = 0; payload = nullptr; } /// estimate free size needed to add new block - static size_t estimateSize(int _ndict, int _ndata) + static size_t estimateSize(int _ndict, int _ndata, int _nliterals) { - return alignSize((_ndict + _ndata) * sizeof(W)); + return alignSize((_ndict + _ndata + _nliterals) * sizeof(W)); } // store a dictionary in an empty block void storeDict(int _ndict, const W* _dict) { - if (nDict || nStored) { + if (getNStored() > 0) { throw std::runtime_error("trying to write in occupied block"); } - size_t sz = estimateSize(_ndict, 0); + size_t sz = estimateSize(_ndict, 0, 0); assert(registry); // this method is valid only for flat version, which has a registry assert(sz <= registry->getFreeSize()); assert((_ndict > 0) == (_dict != nullptr)); - nDict = nStored = _ndict; + setNDict(_ndict); if (nDict) { - auto ptr = payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); - memcpy(ptr, _dict, _ndict * sizeof(W)); - ptr += _ndict; + memcpy(getDict(), _dict, _ndict * sizeof(W)); } }; // store a dictionary to a block which can either be empty or contain a dict. void storeData(int _ndata, const W* _data) { - if (nStored > nDict) { + if (getNStored() > getNDict()) { throw std::runtime_error("trying to write in occupied block"); } - size_t sz = estimateSize(0, _ndata); + size_t sz = estimateSize(0, _ndata, 0); assert(registry); // this method is valid only for flat version, which has a registry assert(sz <= registry->getFreeSize()); assert((_ndata > 0) == (_data != nullptr)); - nStored = nDict + _ndata; - if (_ndata) { - auto ptr = payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); - ptr += nDict; - memcpy(ptr, _data, _ndata * sizeof(W)); + setNData(_ndata); + if (nData) { + memcpy(getData(), _data, _ndata * sizeof(W)); + } + } + + // store a dictionary to a block which can either be empty or contain a dict. + void storeLiterals(int _nliterals, const W* _literals) + { + if (getNStored() > getNDict() + getNData()) { + throw std::runtime_error("trying to write in occupied block"); + } + + size_t sz = estimateSize(0, 0, _nliterals); + assert(registry); // this method is valid only for flat version, which has a registry + assert(sz <= registry->getFreeSize()); + // assert((_nliterals > 0) == (_literals != nullptr)); + setNLiterals(_nliterals); + if (nLiterals) { + memcpy(getLiterals(), _literals, _nliterals * sizeof(W)); } } // resize block and free up unused buffer space. void endBlock() { - size_t sz = estimateSize(nStored, 0); + size_t sz = estimateSize(getNStored(), 0, 0); registry->shrinkFreeBlock(sz); } /// store binary blob data (buffer filled from head to tail) - void store(int _ndict, int _ndata, const W* _dict, const W* _data) + void store(int _ndict, int _ndata, int _nliterals, const W* _dict, const W* _data, const W* _literals) { - size_t sz = estimateSize(_ndict, _ndata); + size_t sz = estimateSize(_ndict, _ndata, _nliterals); assert(registry); // this method is valid only for flat version, which has a registry assert(sz <= registry->getFreeSize()); assert((_ndict > 0) == (_dict != nullptr)); assert((_ndata > 0) == (_data != nullptr)); - nStored = _ndict + _ndata; - nDict = _ndict; - if (nStored) { - auto ptr = payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); - if (_dict) { - memcpy(ptr, _dict, _ndict * sizeof(W)); - ptr += _ndict; + // assert(_literals == _data + _nliterals); + setNDict(_ndict); + setNData(_ndata); + setNLiterals(_nliterals); + if (getNStored()) { + payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); + if (getNDict()) { + memcpy(getDict(), _dict, _ndict * sizeof(W)); + } + if (getNData()) { + memcpy(getData(), _data, _ndata * sizeof(W)); } - if (_data) { - memcpy(ptr, _data, _ndata * sizeof(W)); + if (getNLiterals()) { + memcpy(getLiterals(), _literals, _nliterals * sizeof(W)); } } registry->shrinkFreeBlock(sz); @@ -269,7 +330,7 @@ class EncodedBlocks static auto create(VD& v); /// estimate free size needed to add new block - static size_t estimateBlockSize(int _ndict, int _ndata) { return Block<W>::estimateSize(_ndict, _ndata); } + static size_t estimateBlockSize(int _ndict, int _ndata, int _nliterals) { return Block<W>::estimateSize(_ndict, _ndata, _nliterals); } /// check if empty and valid bool empty() const { return (mRegistry.offsFreeStart == alignSize(sizeof(*this))) && (mRegistry.size >= mRegistry.offsFreeStart); } @@ -394,7 +455,7 @@ void EncodedBlocks<H, N, W>::readFromTree(VD& vec, TTree& tree, const std::strin for (int i = 0; i < N; i++) { Block<W> bl; readTreeBranch(tree, o2::utils::concat_string(name, "_block.", std::to_string(i), "."), bl); - tmp->mBlocks[i].store(bl.getNDict(), bl.getNData(), bl.getDict(), bl.getData()); + tmp->mBlocks[i].store(bl.getNDict(), bl.getNData(), bl.getNLiterals(), bl.getDict(), bl.getData(), bl.getLiterals()); } } @@ -482,7 +543,7 @@ size_t EncodedBlocks<H, N, W>::estimateSizeFromMetadata() const { size_t sz = alignSize(sizeof(*this)); for (int i = 0; i < N; i++) { - sz += alignSize((mMetadata[i].nDictWords + mMetadata[i].nDataWords) * sizeof(W)); + sz += alignSize((mMetadata[i].nDictWords + mMetadata[i].nDataWords + mMetadata[i].nLiteralWords) * sizeof(W)); } return sz; } @@ -622,8 +683,14 @@ void EncodedBlocks<H, N, W>::decode(D* dest, // destination pointer if (md.opt == Metadata::OptStore::EENCODE) { assert(block.getNDict()); // at the moment we expect to have dictionary o2::rans::SymbolStatistics<D> stats(block.getDict(), block.getDict() + block.getNDict(), md.min, md.max, md.messageLength); - o2::rans::Decoder64<D> decoder(stats, md.probabilityBits); - decoder.process(dest, block.getData() + block.getNData(), md.messageLength); + + // load incompressible symbols if they existed + std::vector<D> literals; + if (md.nLiterals) { + literals = std::vector<D>{reinterpret_cast<const D*>(block.getLiterals()), reinterpret_cast<const D*>(block.getLiterals()) + md.nLiterals}; + } + o2::rans::LiteralDecoder64<D> decoder(stats, md.probabilityBits); + decoder.process(dest, block.getData() + block.getNData(), md.messageLength, literals); } else { // data was stored as is std::memcpy(dest, block.payload, md.messageLength * sizeof(D)); } @@ -652,7 +719,7 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source // case 1: empty source message if (srcBegin == srcEnd) { - mMetadata[slot] = Metadata{0, sizeof(uint64_t), sizeof(stream_t), probabilityBits, Metadata::OptStore::NODATA, 0, 0, 0, 0}; + mMetadata[slot] = Metadata{0, 0, sizeof(uint64_t), sizeof(stream_t), probabilityBits, Metadata::OptStore::NODATA, 0, 0, 0, 0, 0}; return; } static_assert(std::is_same<W, stream_t>()); @@ -664,7 +731,7 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source // resize underlying buffer of block if necessary and update all pointers. auto expandStorage = [&](int dictElems, int encodeBufferElems) { - auto szNeed = estimateBlockSize(dictElems, encodeBufferElems); // size in bytes!!! + auto szNeed = estimateBlockSize(dictElems, encodeBufferElems, 0); // size in bytes!!! if (szNeed >= getFreeSize()) { LOG(INFO) << "Slot " << slot << ": free size: " << getFreeSize() << ", need " << szNeed; if (buffer) { @@ -682,7 +749,7 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source // build symbol statistics stats = std::make_unique<rans::SymbolStatistics<S>>(srcBegin, srcEnd); stats->rescaleToNBits(probabilityBits); - const o2::rans::Encoder64<S> encoder{*stats, probabilityBits}; + const o2::rans::LiteralEncoder64<S> encoder{*stats, probabilityBits}; const int dictSize = stats->getFrequencyTable().size(); // estimate size of encode buffer @@ -693,13 +760,22 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source expandStorage(dictSize, dataSize); //store dictionary first bl->storeDict(dictSize, stats->getFrequencyTable().data()); + // vector of incompressible literal symbols + std::vector<S> literals; // directly encode source message into block buffer. - const auto encodedMessageEnd = encoder.process(bl->getData(), bl->getData() + dataSize, srcBegin, srcEnd); + const auto encodedMessageEnd = encoder.process(bl->getData(), bl->getData() + dataSize, srcBegin, srcEnd, literals); dataSize = encodedMessageEnd - bl->getData(); // update the size claimed by encode message directly inside the block - bl->nStored = bl->nDict + dataSize; - *meta = Metadata{stats->getMessageLength(), sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, - stats->getMinSymbol(), stats->getMaxSymbol(), dictSize, dataSize}; + bl->setNData(dataSize); + // store incompressible symbols if any + + int literalSize = 0; + if (literals.size()) { + literalSize = (literals.size() * sizeof(S)) / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); + bl->storeLiterals(literalSize, reinterpret_cast<const stream_t*>(literals.data())); + } + *meta = Metadata{stats->getMessageLength(), literals.size(), sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, + stats->getMinSymbol(), stats->getMaxSymbol(), dictSize, dataSize, literalSize}; } else { // store original data w/o EEncoding const size_t messageLength = (srcEnd - srcBegin); @@ -707,8 +783,8 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source const int dataSize = szb / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); // no dictionary needed expandStorage(0, dataSize); - *meta = Metadata{messageLength, sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, - 0, 0, 0, dataSize}; + *meta = Metadata{messageLength, 0, sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, + 0, 0, 0, dataSize, 0}; bl->storeData(meta->nDataWords, reinterpret_cast<const W*>(srcBegin)); } // resize block if necessary diff --git a/Utilities/rANS/include/rANS/SymbolStatistics.h b/Utilities/rANS/include/rANS/SymbolStatistics.h index 12d4c8bf7221d..0e33a09699629 100644 --- a/Utilities/rANS/include/rANS/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/SymbolStatistics.h @@ -65,11 +65,11 @@ class SymbolStatistics }; public: - template <typename IT> - SymbolStatistics(const IT begin, const IT end, Source_T min = 0, Source_T max = 0); + template <typename Source_IT> + SymbolStatistics(const Source_IT begin, const Source_IT end, Source_T min = 0, Source_T max = 0); - template <typename IT> - SymbolStatistics(const IT begin, const IT end, int32_t min, int32_t max, size_t messageLength); + template <typename Source_IT> + SymbolStatistics(const Source_IT begin, const Source_IT end, int32_t min, int32_t max, size_t messageLength); void rescaleToNBits(size_t bits); @@ -91,8 +91,9 @@ class SymbolStatistics private: void buildCumulativeFrequencyTable(); auto getFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } - template <typename IT> - void buildFrequencyTable(const IT begin, const IT end); + + template <typename Source_IT> + void buildFrequencyTable(const Source_IT begin, const Source_IT end); int32_t mMin; int32_t mMax; @@ -104,9 +105,11 @@ class SymbolStatistics }; template <typename Source_T> -template <typename IT> -SymbolStatistics<Source_T>::SymbolStatistics(const IT begin, const IT end, Source_T min, Source_T max) : mMin(min), mMax(max), mMessageLength(0), mFrequencyTable(), mCumulativeFrequencyTable() +template <typename Source_IT> +SymbolStatistics<Source_T>::SymbolStatistics(const Source_IT begin, const Source_IT end, Source_T min, Source_T max) : mMin(min), mMax(max), mMessageLength(0), mFrequencyTable(), mCumulativeFrequencyTable() { + static_assert(std::is_same<typename std::remove_const<typename std::iterator_traits<Source_IT>::value_type>::type, Source_T>::value); + using namespace internal; LOG(trace) << "start building symbol statistics"; RANSTimer t; @@ -175,7 +178,7 @@ SymbolStatistics<Source_T>::SymbolStatistics(const IT begin, const IT end, Sourc << "minSymbol: " << *minmax.first << ", " << "maxSymbol: " << *minmax.second << ", " << "entropy: " << entropy << ", " - << "bufferSizeB: " << mMessageLength * sizeof(typename std::iterator_traits<IT>::value_type) << ", " + << "bufferSizeB: " << mMessageLength * sizeof(typename std::iterator_traits<Source_IT>::value_type) << ", " << "actualSizeB: " << static_cast<int>(mMessageLength * getAlphabetRangeBits() / 8) << ", " << "entropyMessageB: " << static_cast<int>(std::ceil(entropy * mMessageLength / 8)) << "}"; @@ -190,9 +193,11 @@ SymbolStatistics<Source_T>::SymbolStatistics(const IT begin, const IT end, Sourc } template <typename Source_T> -template <typename IT> -SymbolStatistics<Source_T>::SymbolStatistics(const IT begin, const IT end, int32_t min, int32_t max, size_t messageLength) : mMin(min), mMax(max), mMessageLength(messageLength), mFrequencyTable(begin, end), mCumulativeFrequencyTable() +template <typename Source_IT> +SymbolStatistics<Source_T>::SymbolStatistics(const Source_IT begin, const Source_IT end, int32_t min, int32_t max, size_t messageLength) : mMin(min), mMax(max), mMessageLength(messageLength), mFrequencyTable(begin, end), mCumulativeFrequencyTable() { + static_assert(std::is_same<typename std::remove_const<typename std::iterator_traits<Source_IT>::value_type>::type, uint32_t>::value); + LOG(trace) << "start loading external symbol statistics"; buildCumulativeFrequencyTable(); @@ -207,9 +212,11 @@ SymbolStatistics<Source_T>::SymbolStatistics(const IT begin, const IT end, int32 } template <typename Source_T> -template <typename IT> -void SymbolStatistics<Source_T>::buildFrequencyTable(const IT begin, const IT end) +template <typename Source_IT> +void SymbolStatistics<Source_T>::buildFrequencyTable(const Source_IT begin, const Source_IT end) { + static_assert(std::is_same<typename std::remove_const<typename std::iterator_traits<Source_IT>::value_type>::type, Source_T>::value); + using namespace internal; LOG(trace) << "start building frequency table"; @@ -219,7 +226,7 @@ void SymbolStatistics<Source_T>::buildFrequencyTable(const IT begin, const IT en assert(size > 0); mFrequencyTable.resize(size + 1, 0); - for (IT it = begin; it != end; it++) { + for (Source_IT it = begin; it != end; it++) { const auto value = *it - mMin; assert(value >= 0); assert(value < size); @@ -243,55 +250,44 @@ void SymbolStatistics<Source_T>::rescaleToNBits(size_t bits) } const size_t newCumulatedFrequency = bitsToRange(bits); - assert(newCumulatedFrequency > this->getNUsedAlphabetSymbols()); + assert(newCumulatedFrequency >= mFrequencyTable.size()); size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); + std::vector<uint32_t> sortIdx; + sortIdx.reserve(getNUsedAlphabetSymbols()); + // resample distribution based on cumulative frequencies_ - for (size_t i = 1; i <= mFrequencyTable.size(); i++) - mCumulativeFrequencyTable[i] = - (static_cast<uint64_t>(newCumulatedFrequency) * - mCumulativeFrequencyTable[i]) / - cumulatedFrequencies; - - // if we nuked any non-0 frequency symbol to 0, we need to steal - // the range to make the frequency nonzero from elsewhere. - // - // this is not at all optimal, i'm just doing the first thing that comes to - // mind. for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i] && - mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]) { - // symbol i was set to zero freq - - // find best symbol to steal frequency from (try to steal from low-freq - // ones) - std::pair<size_t, size_t> stealFromEntry{mFrequencyTable.size(), ~0u}; - for (size_t j = 0; j < mFrequencyTable.size(); j++) { - uint32_t frequency = - mCumulativeFrequencyTable[j + 1] - mCumulativeFrequencyTable[j]; - if (frequency > 1 && frequency < stealFromEntry.second) { - stealFromEntry.second = frequency; - stealFromEntry.first = j; - } - } - assert(stealFromEntry.first != mFrequencyTable.size()); - - // and steal from it! - if (stealFromEntry.first < i) { - for (size_t j = stealFromEntry.first + 1; j <= i; j++) - mCumulativeFrequencyTable[j]--; - } else { - assert(stealFromEntry.first > i); - for (size_t j = i + 1; j <= stealFromEntry.first; j++) - mCumulativeFrequencyTable[j]++; - } + if (mFrequencyTable[i]) { + sortIdx.push_back(i); // we will sort only those memorize only those entries which can be used } } + std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getFrequency(i) < this->getFrequency(j); }); + size_t need_shift = 0; + for (size_t i = 0; i < sortIdx.size(); i++) { + if (static_cast<uint64_t>(getFrequency(sortIdx[i])) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies >= 1) { + break; + } + need_shift++; + } + + size_t shift = 0; + auto beforeUpdate = mCumulativeFrequencyTable[0]; + for (size_t i = 0; i < mFrequencyTable.size(); i++) { + if (mFrequencyTable[i] && static_cast<uint64_t>(mCumulativeFrequencyTable[i + 1] - beforeUpdate) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies < 1) { + shift++; + } + beforeUpdate = mCumulativeFrequencyTable[i + 1]; + mCumulativeFrequencyTable[i + 1] = (static_cast<uint64_t>(newCumulatedFrequency - need_shift) * mCumulativeFrequencyTable[i + 1]) / cumulatedFrequencies + shift; + } + assert(shift == need_shift); + // calculate updated freqs and make sure we didn't screw anything up assert(mCumulativeFrequencyTable.front() == 0 && mCumulativeFrequencyTable.back() == newCumulatedFrequency); + for (size_t i = 0; i < mFrequencyTable.size(); i++) { if (mFrequencyTable[i] == 0) assert(mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]); @@ -299,8 +295,7 @@ void SymbolStatistics<Source_T>::rescaleToNBits(size_t bits) assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); // calc updated freq - mFrequencyTable[i] = - mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; + mFrequencyTable[i] = getFrequency(i); } // for(int i = 0; i<static_cast<int>(freqs.getNumSymbols()); i++){ // std::cout << i << ": " << i + min_ << " " << freqs[i] << " " << diff --git a/Utilities/rANS/include/rANS/rans.h b/Utilities/rANS/include/rANS/rans.h index 9f99575bbab93..acb293a7ca972 100644 --- a/Utilities/rANS/include/rANS/rans.h +++ b/Utilities/rANS/include/rANS/rans.h @@ -39,6 +39,26 @@ using Decoder32 = Decoder<uint32_t, uint8_t, source_T>; template <typename source_T> using Decoder64 = Decoder<uint64_t, uint32_t, source_T>; +template <typename source_T> +using LiteralEncoder32 = LiteralEncoder<uint32_t, uint8_t, source_T>; +template <typename source_T> +using LiteralEncoder64 = LiteralEncoder<uint64_t, uint32_t, source_T>; + +template <typename source_T> +using LiteralDecoder32 = LiteralDecoder<uint32_t, uint8_t, source_T>; +template <typename source_T> +using LiteralDecoder64 = LiteralDecoder<uint64_t, uint32_t, source_T>; + +template <typename source_T> +using DedupEncoder32 = DedupEncoder<uint32_t, uint8_t, source_T>; +template <typename source_T> +using DedupEncoder64 = DedupEncoder<uint64_t, uint32_t, source_T>; + +template <typename source_T> +using DedupDecoder32 = DedupDecoder<uint32_t, uint8_t, source_T>; +template <typename source_T> +using DedupDecoder64 = DedupDecoder<uint64_t, uint32_t, source_T>; + //rans default values constexpr size_t ProbabilityBits8Bit = 10; constexpr size_t ProbabilityBits16Bit = 22; diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx deleted file mode 100644 index 97c2a4e92f061..0000000000000 --- a/Utilities/rANS/src/SymbolStatistics.cxx +++ /dev/null @@ -1,174 +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. - -/// @file SymbolStatistics.cpp -/// @author Michael Lettrich -/// @since 2019-05-08 -/// @brief Structure to depict the distribution of symbols in the source message. - -#include <cmath> - -#include "rANS/SymbolStatistics.h" -#include "rANS/helper.h" - -namespace o2 -{ -namespace rans -{ - -void SymbolStatistics::rescaleToNBits(size_t bits) -{ - LOG(trace) << "start rescaling frequency table"; - RANSTimer t; - t.start(); - - if (mFrequencyTable.empty()) { - LOG(warning) << "rescaling Frequency Table for empty message"; - return; - } - - const size_t newCumulatedFrequency = bitsToRange(bits); - assert(newCumulatedFrequency >= mFrequencyTable.size()); - - size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); - - std::vector<uint32_t> sortIdx; - sortIdx.reserve(mNUsedAlphabetSymbols); - - // resample distribution based on cumulative frequencies_ - for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i]) { - sortIdx.push_back(i); // we will sort only those memorize only those entries which can be used - } - } - - std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getFrequency(i) < this->getFrequency(j); }); - size_t need_shift = 0; - for (size_t i = 0; i < sortIdx.size(); i++) { - if (static_cast<uint64_t>(getFrequency(sortIdx[i])) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies >= 1) { - break; - } - need_shift++; - } - - size_t shift = 0; - auto beforeUpdate = mCumulativeFrequencyTable[0]; - for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i] && static_cast<uint64_t>(mCumulativeFrequencyTable[i + 1] - beforeUpdate) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies < 1) { - shift++; - } - beforeUpdate = mCumulativeFrequencyTable[i + 1]; - mCumulativeFrequencyTable[i + 1] = (static_cast<uint64_t>(newCumulatedFrequency - need_shift) * mCumulativeFrequencyTable[i + 1]) / cumulatedFrequencies + shift; - } - assert(shift == need_shift); - - // calculate updated freqs and make sure we didn't screw anything up - assert(mCumulativeFrequencyTable.front() == 0 && - mCumulativeFrequencyTable.back() == newCumulatedFrequency); - - for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i] == 0) - assert(mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]); - else - assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); - - // calc updated freq - mFrequencyTable[i] = getFrequency(i); - } - // for(int i = 0; i<static_cast<int>(freqs.getNumSymbols()); i++){ - // std::cout << i << ": " << i + min_ << " " << freqs[i] << " " << - // cummulatedFrequencies_[i] << std::endl; - // } - // std::cout << cummulatedFrequencies_.back() << std::endl; - - t.stop(); - LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); - - LOG(trace) << "done rescaling frequency table"; -} - -int SymbolStatistics::getMinSymbol() const { return mMin; } - -int SymbolStatistics::getMaxSymbol() const { return mMax; } - -size_t SymbolStatistics::getAlphabetSize() const { return mFrequencyTable.size(); } - -size_t SymbolStatistics::getAlphabetRangeBits() const -{ - return std::max(std::ceil(std::log2(mMax - mMin)), 1.0); -} - -size_t SymbolStatistics::getNUsedAlphabetSymbols() const -{ - return mNUsedAlphabetSymbols; -} - -size_t SymbolStatistics::getMessageLength() const -{ - return mMessageLength; -} - -std::pair<uint32_t, uint32_t> SymbolStatistics::operator[](int64_t index) const -{ - assert(index - mMin < mFrequencyTable.size()); - - return std::make_pair(mFrequencyTable[index - mMin], - mCumulativeFrequencyTable[index - mMin]); -} - -void SymbolStatistics::buildCumulativeFrequencyTable() -{ - LOG(trace) << "start building cumulative frequency table"; - - mCumulativeFrequencyTable.resize(mFrequencyTable.size() + 1); - mCumulativeFrequencyTable[0] = 0; - std::partial_sum(mFrequencyTable.begin(), mFrequencyTable.end(), - mCumulativeFrequencyTable.begin() + 1); - - LOG(trace) << "done building cumulative frequency table"; -} - -SymbolStatistics::Iterator SymbolStatistics::begin() const -{ - return SymbolStatistics::Iterator(this->getMinSymbol(), *this); -} - -SymbolStatistics::Iterator SymbolStatistics::end() const -{ - if (mFrequencyTable.empty()) { - return this->begin(); // begin == end for empty stats; - } else { - return SymbolStatistics::Iterator(this->getMaxSymbol() + 1, *this); - } -} - -SymbolStatistics::Iterator::Iterator(int64_t index, - const SymbolStatistics& stats) - : mIndex(index), mStats(stats) {} - -const SymbolStatistics::Iterator& SymbolStatistics::Iterator::operator++() -{ - ++mIndex; - assert(mIndex <= mStats.getMaxSymbol() + 1); - return *this; -} - -std::pair<uint32_t, uint32_t> SymbolStatistics::Iterator::operator*() const -{ - return std::move(mStats[mIndex]); -} - -bool SymbolStatistics::Iterator::operator!=(const Iterator& other) const -{ - return this->mIndex != other.mIndex; -} - -} // namespace rans -} // namespace o2 From 25448d46337c53fa25bb843fd6d8615b7a183949 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Fri, 24 Jul 2020 12:28:30 +0200 Subject: [PATCH 0272/1751] [rANS] Factor out creation of frequency tables * SymbolStatistics are no longer in user code * FrequencyTable as the new interface for users * allows adding arbitray amounts of new samples * additivity of different frequency tables * Creates static or dynamic FrequencyTables and pass to Encoder/Decoder to assemble SymbolStatistics and SymbolTables internaly. --- .../EncodedBlocks.h | 37 +- Utilities/rANS/CMakeLists.txt | 14 +- Utilities/rANS/include/rANS/Decoder.h | 24 +- Utilities/rANS/include/rANS/DedupDecoder.h | 2 +- Utilities/rANS/include/rANS/Encoder.h | 10 +- Utilities/rANS/include/rANS/FrequencyTable.h | 255 +++++++++++ Utilities/rANS/include/rANS/LiteralDecoder.h | 2 +- .../rANS/include/rANS/SymbolStatistics.h | 421 ------------------ .../include/rANS/internal/EncoderSymbol.h | 2 +- .../rANS/internal/ReverseSymbolLookupTable.h | 10 +- .../include/rANS/internal/SymbolStatistics.h | 222 +++++++++ .../rANS/include/rANS/internal/SymbolTable.h | 30 +- Utilities/rANS/include/rANS/rans.h | 9 +- Utilities/rANS/run/bin-encode-decode.cxx | 13 +- Utilities/rANS/src/FrequencyTable.cxx | 99 ++++ Utilities/rANS/src/SymbolStatistics.cxx | 128 ++++++ Utilities/rANS/test/test_ransEncodeDecode.cxx | 34 +- .../rANS/test/test_ransFrequencyTable.cxx | 80 ++++ 18 files changed, 885 insertions(+), 507 deletions(-) create mode 100644 Utilities/rANS/include/rANS/FrequencyTable.h delete mode 100644 Utilities/rANS/include/rANS/SymbolStatistics.h create mode 100644 Utilities/rANS/include/rANS/internal/SymbolStatistics.h create mode 100644 Utilities/rANS/src/FrequencyTable.cxx create mode 100644 Utilities/rANS/src/SymbolStatistics.cxx create mode 100644 Utilities/rANS/test/test_ransFrequencyTable.cxx diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 1d7c8f6b21850..ceefb8a6c5587 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -135,6 +135,10 @@ struct Block { int nStored = 0; // total length W* payload = nullptr; //[nStored]; + inline const W* getDict() const { return nDict ? payload : nullptr; }; + inline const W* getData() const { return payload ? (payload + nDict) : nullptr; }; + inline const W* getLiterals() const { return nLiterals ? (payload + nDict + nData) : nullptr; }; + inline W* getDict() { return payload ? payload : (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())); }; inline W* getData() { return payload ? (payload + nDict) : (registry ? (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())) : nullptr); }; W* getLiterals() @@ -149,10 +153,6 @@ struct Block { return nullptr; }; - inline const W* getDict() const { return nDict ? payload : nullptr; }; - inline const W* getData() const { return payload ? (payload + nDict) : nullptr; }; - inline const W* getLiterals() const { return nLiterals ? payload + nDict + nData : nullptr; }; - inline void setNDict(int _ndict) { nDict = _ndict; @@ -682,14 +682,15 @@ void EncodedBlocks<H, N, W>::decode(D* dest, // destination pointer if (block.getNData()) { if (md.opt == Metadata::OptStore::EENCODE) { assert(block.getNDict()); // at the moment we expect to have dictionary - o2::rans::SymbolStatistics<D> stats(block.getDict(), block.getDict() + block.getNDict(), md.min, md.max, md.messageLength); + o2::rans::FrequencyTable frequencies; + frequencies.addFrequencies(block.getDict(), block.getDict() + block.getNDict(), md.min, md.max); // load incompressible symbols if they existed std::vector<D> literals; if (md.nLiterals) { literals = std::vector<D>{reinterpret_cast<const D*>(block.getLiterals()), reinterpret_cast<const D*>(block.getLiterals()) + md.nLiterals}; } - o2::rans::LiteralDecoder64<D> decoder(stats, md.probabilityBits); + o2::rans::LiteralDecoder64<D> decoder(frequencies, md.probabilityBits); decoder.process(dest, block.getData() + block.getNData(), md.messageLength, literals); } else { // data was stored as is std::memcpy(dest, block.payload, md.messageLength * sizeof(D)); @@ -712,18 +713,19 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source mRegistry.nFilledBlocks++; using stream_t = typename o2::rans::Encoder64<S>::stream_t; + const size_t messageLength = std::distance(srcBegin, srcEnd); // cover three cases: // * empty source message: no entropy coding // * source message to pass through without any entropy coding // * source message where entropy coding should be applied // case 1: empty source message - if (srcBegin == srcEnd) { + if (messageLength == 0) { mMetadata[slot] = Metadata{0, 0, sizeof(uint64_t), sizeof(stream_t), probabilityBits, Metadata::OptStore::NODATA, 0, 0, 0, 0, 0}; return; } static_assert(std::is_same<W, stream_t>()); - std::unique_ptr<rans::SymbolStatistics<S>> stats = nullptr; + std::unique_ptr<rans::FrequencyTable> frequencies = nullptr; Metadata md; auto* bl = &mBlocks[slot]; @@ -747,19 +749,19 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source // case 3: message where entropy coding should be applied if (opt == Metadata::OptStore::EENCODE) { // build symbol statistics - stats = std::make_unique<rans::SymbolStatistics<S>>(srcBegin, srcEnd); - stats->rescaleToNBits(probabilityBits); - const o2::rans::LiteralEncoder64<S> encoder{*stats, probabilityBits}; - const int dictSize = stats->getFrequencyTable().size(); + frequencies = std::make_unique<rans::FrequencyTable>(); + frequencies->addSamples(srcBegin, srcEnd); + const o2::rans::LiteralEncoder64<S> encoder{*frequencies, probabilityBits}; + const int dictSize = frequencies->size(); // estimate size of encode buffer - int dataSize = rans::calculateMaxBufferSize(stats->getMessageLength(), - stats->getAlphabetRangeBits(), + int dataSize = rans::calculateMaxBufferSize(messageLength, + frequencies->getAlphabetRangeBits(), sizeof(S)); // preliminary expansion of storage based on dict size + estimated size of encode buffer expandStorage(dictSize, dataSize); //store dictionary first - bl->storeDict(dictSize, stats->getFrequencyTable().data()); + bl->storeDict(dictSize, frequencies->data()); // vector of incompressible literal symbols std::vector<S> literals; // directly encode source message into block buffer. @@ -774,11 +776,10 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source literalSize = (literals.size() * sizeof(S)) / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); bl->storeLiterals(literalSize, reinterpret_cast<const stream_t*>(literals.data())); } - *meta = Metadata{stats->getMessageLength(), literals.size(), sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, - stats->getMinSymbol(), stats->getMaxSymbol(), dictSize, dataSize, literalSize}; + *meta = Metadata{messageLength, literals.size(), sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, + frequencies->getMinSymbol(), frequencies->getMaxSymbol(), dictSize, dataSize, literalSize}; } else { // store original data w/o EEncoding - const size_t messageLength = (srcEnd - srcBegin); const size_t szb = messageLength * sizeof(S); const int dataSize = szb / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); // no dictionary needed diff --git a/Utilities/rANS/CMakeLists.txt b/Utilities/rANS/CMakeLists.txt index a732fe678480c..46e86f0cf3767 100644 --- a/Utilities/rANS/CMakeLists.txt +++ b/Utilities/rANS/CMakeLists.txt @@ -8,8 +8,10 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_header_only_library(rANS - INTERFACE_LINK_LIBRARIES FairLogger::FairLogger) +o2_add_library(rANS + SOURCES src/SymbolStatistics.cxx + src/FrequencyTable.cxx + PUBLIC_LINK_LIBRARIES FairLogger::FairLogger) o2_add_test(EncodeDecode NAME EncodeDecode @@ -18,13 +20,19 @@ o2_add_test(EncodeDecode COMPONENT_NAME rANS LABELS utils) +o2_add_test(FrequencyTable + NAME FrequencyTable + SOURCES test/test_ransFrequencyTable.cxx + PUBLIC_LINK_LIBRARIES O2::rANS + COMPONENT_NAME rANS + LABELS utils) + o2_add_executable(rans-encode-decode-8 TARGETVARNAME targetName SOURCES run/bin-encode-decode.cxx PUBLIC_LINK_LIBRARIES O2::rANS Boost::program_options) target_compile_definitions(${targetName} PRIVATE -DSOURCE_T=uint8_t) - o2_add_executable(rans-encode-decode-16 TARGETVARNAME targetName SOURCES run/bin-encode-decode.cxx diff --git a/Utilities/rANS/include/rANS/Decoder.h b/Utilities/rANS/include/rANS/Decoder.h index 3655bbf0ed84a..d3220e4f955f1 100644 --- a/Utilities/rANS/include/rANS/Decoder.h +++ b/Utilities/rANS/include/rANS/Decoder.h @@ -21,13 +21,16 @@ #include <cstddef> #include <type_traits> #include <iostream> +#include <memory> #include <fairlogger/Logger.h> +#include "FrequencyTable.h" #include "internal/DecoderSymbol.h" #include "internal/ReverseSymbolLookupTable.h" #include "internal/SymbolTable.h" #include "internal/Decoder.h" +#include "internal/SymbolStatistics.h" namespace o2 { @@ -39,8 +42,8 @@ class Decoder { protected: - using decoderSymbol_t = internal::SymbolTable<internal::DecoderSymbol, source_T>; - using reverseSymbolLookupTable_t = internal::ReverseSymbolLookupTable<source_T>; + using decoderSymbol_t = internal::SymbolTable<internal::DecoderSymbol>; + using reverseSymbolLookupTable_t = internal::ReverseSymbolLookupTable; using ransDecoder = internal::Decoder<coder_T, stream_T>; public: @@ -49,7 +52,7 @@ class Decoder Decoder<coder_T, stream_T, source_T>& operator=(const Decoder& d); Decoder<coder_T, stream_T, source_T>& operator=(Decoder&& d) = default; ~Decoder() = default; - Decoder(const SymbolStatistics<source_T>& stats, size_t probabilityBits); + Decoder(const FrequencyTable& stats, size_t probabilityBits); template <typename stream_IT, typename source_IT> void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength) const; @@ -81,16 +84,19 @@ Decoder<coder_T, stream_T, source_T>& Decoder<coder_T, stream_T, source_T>::oper } template <typename coder_T, typename stream_T, typename source_T> -Decoder<coder_T, stream_T, source_T>::Decoder(const SymbolStatistics<source_T>& stats, size_t probabilityBits) : mSymbolTable(nullptr), mReverseLUT(nullptr), mProbabilityBits(probabilityBits) +Decoder<coder_T, stream_T, source_T>::Decoder(const FrequencyTable& frequencies, size_t probabilityBits) : mSymbolTable(nullptr), mReverseLUT(nullptr), mProbabilityBits(probabilityBits) { using namespace internal; + + SymbolStatistics stats(frequencies, mProbabilityBits); + RANSTimer t; t.start(); - mSymbolTable = std::make_unique<decoderSymbol_t>(stats, probabilityBits); + mSymbolTable = std::make_unique<decoderSymbol_t>(stats, mProbabilityBits); t.stop(); LOG(debug1) << "Decoder SymbolTable inclusive time (ms): " << t.getDurationMS(); t.start(); - mReverseLUT = std::make_unique<reverseSymbolLookupTable_t>(probabilityBits, stats); + mReverseLUT = std::make_unique<reverseSymbolLookupTable_t>(mProbabilityBits, stats); t.stop(); LOG(debug1) << "ReverseSymbolLookupTable inclusive time (ms): " << t.getDurationMS(); }; @@ -122,8 +128,8 @@ void Decoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, inputIter = rans1.init(inputIter); for (size_t i = 0; i < (messageLength & ~1); i += 2) { - const stream_T s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; - const stream_T s1 = (*mReverseLUT)[rans1.get(mProbabilityBits)]; + const int64_t s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; + const int64_t s1 = (*mReverseLUT)[rans1.get(mProbabilityBits)]; *it++ = s0; *it++ = s1; inputIter = rans0.advanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); @@ -132,7 +138,7 @@ void Decoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, // last byte, if message length was odd if (messageLength & 1) { - const stream_T s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; + const int64_t s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; *it = s0; inputIter = rans0.advanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); } diff --git a/Utilities/rANS/include/rANS/DedupDecoder.h b/Utilities/rANS/include/rANS/DedupDecoder.h index 8a9c1e9c94405..b9c3538b95dcf 100644 --- a/Utilities/rANS/include/rANS/DedupDecoder.h +++ b/Utilities/rANS/include/rANS/DedupDecoder.h @@ -75,7 +75,7 @@ void DedupDecoder<coder_T, stream_T, source_T>::process(const source_IT outputBe inputIter = rans.init(inputIter); for (size_t i = 0; i < (messageLength); i++) { - const stream_T s = (*this->mReverseLUT)[rans.get(this->mProbabilityBits)]; + const auto s = (*this->mReverseLUT)[rans.get(this->mProbabilityBits)]; // deduplication auto duplicatesIter = duplicates.find(i); diff --git a/Utilities/rANS/include/rANS/Encoder.h b/Utilities/rANS/include/rANS/Encoder.h index 943683eab40dc..3ce5aa8bc5f80 100644 --- a/Utilities/rANS/include/rANS/Encoder.h +++ b/Utilities/rANS/include/rANS/Encoder.h @@ -28,6 +28,7 @@ #include "internal/EncoderSymbol.h" #include "internal/helper.h" #include "internal/SymbolTable.h" +#include "FrequencyTable.h" namespace o2 { @@ -38,7 +39,7 @@ template <typename coder_T, typename stream_T, typename source_T> class Encoder { protected: - using encoderSymbolTable_t = internal::SymbolTable<internal::EncoderSymbol<coder_T>, source_T>; + using encoderSymbolTable_t = internal::SymbolTable<internal::EncoderSymbol<coder_T>>; public: Encoder() = delete; @@ -50,7 +51,7 @@ class Encoder Encoder(const encoderSymbolTable_t& e, size_t probabilityBits); Encoder(encoderSymbolTable_t&& e, size_t probabilityBits); - Encoder(const SymbolStatistics<source_T>& stats, size_t probabilityBits); + Encoder(const FrequencyTable& frequencies, size_t probabilityBits); template <typename stream_IT, typename source_IT> const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd, @@ -91,10 +92,13 @@ template <typename coder_T, typename stream_T, typename source_T> Encoder<coder_T, stream_T, source_T>::Encoder(encoderSymbolTable_t&& e, size_t probabilityBits) : mSymbolTable(std::move(e.mSymbolTable)), mProbabilityBits(probabilityBits){}; template <typename coder_T, typename stream_T, typename source_T> -Encoder<coder_T, stream_T, source_T>::Encoder(const SymbolStatistics<source_T>& stats, +Encoder<coder_T, stream_T, source_T>::Encoder(const FrequencyTable& frequencies, size_t probabilityBits) : mSymbolTable(nullptr), mProbabilityBits(probabilityBits) { using namespace internal; + + SymbolStatistics stats(frequencies, mProbabilityBits); + RANSTimer t; t.start(); mSymbolTable = std::make_unique<encoderSymbolTable_t>(stats, probabilityBits); diff --git a/Utilities/rANS/include/rANS/FrequencyTable.h b/Utilities/rANS/include/rANS/FrequencyTable.h new file mode 100644 index 0000000000000..b9f357851dd3e --- /dev/null +++ b/Utilities/rANS/include/rANS/FrequencyTable.h @@ -0,0 +1,255 @@ +// 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 FrequencyTable.h +/// @author Michael Lettrich +/// @since 2019-05-08 +/// @brief Histogram to depict frequencies of source symbols for rANS compression. + +#ifndef INCLUDE_RANS_FREQUENCYTABLE_H_ +#define INCLUDE_RANS_FREQUENCYTABLE_H_ + +#include <algorithm> +#include <cassert> +#include <cmath> +#include <iostream> +#include <iterator> +#include <numeric> +#include <type_traits> +#include <vector> + +#include <fairlogger/Logger.h> + +#include "internal/helper.h" + +namespace o2 +{ +namespace rans +{ +class FrequencyTable; + +std::ostream& operator<<(std::ostream& out, const FrequencyTable& fTable); + +class FrequencyTable +{ + public: + using value_t = int32_t; + + FrequencyTable() : mMin(0), mMax(0), mNumSamples(0), mFrequencyTable(){}; + + FrequencyTable(value_t min, value_t max) : mMin(0), mMax(0), mNumSamples(0), mFrequencyTable(mMax - mMin + 1, 0) + { + assert(mMax >= mMin); + } + + FrequencyTable(size_t range) : FrequencyTable(0, internal::bitsToRange(range) - 1) { assert(range >= 1); }; + + template <typename Source_IT> + void addSamples(Source_IT begin, Source_IT end, value_t min = 0, value_t max = 0); + + template <typename Freq_IT> + void addFrequencies(Freq_IT begin, Freq_IT end, value_t min, value_t max); + + value_t operator[](value_t index) const; + + size_t size() const; + + const uint32_t* data() const; + + const uint32_t* cbegin() const; + + const uint32_t* cend() const; + + uint32_t* begin(); + + uint32_t* end(); + + const uint32_t* begin() const; + + const uint32_t* end() const; + + FrequencyTable& operator+(FrequencyTable& other); + + value_t getMinSymbol() const; + value_t getMaxSymbol() const; + + size_t getAlphabetRangeBits() const; + + size_t getNumSamples() const; + + size_t getUsedAlphabetSize() const; + + private: + void resizeFrequencyTable(value_t min, value_t max); + + value_t mMin; + value_t mMax; + size_t mNumSamples; + std::vector<uint32_t> mFrequencyTable; +}; + +template <typename Source_IT> +void FrequencyTable::addSamples(Source_IT begin, Source_IT end, value_t min, value_t max) +{ + static_assert(std::is_integral<typename std::iterator_traits<Source_IT>::value_type>::value); + + LOG(trace) << "start adding samples"; + internal::RANSTimer t; + t.start(); + + if (begin == end) { + LOG(warning) << "Passed empty message to " << __func__; + return; + } + + if (min != max && (!max && !min)) { + resizeFrequencyTable(min, max); + } else { + const auto& [minIter, maxIter] = std::minmax_element(begin, end); + resizeFrequencyTable(*minIter, *maxIter); + } + + for (auto it = begin; it != end; it++) { + assert((*it - mMin) < mFrequencyTable.size()); + mFrequencyTable[*it - mMin]++; + } + mNumSamples = std::distance(begin, end); + + t.stop(); + LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + +#if !defined(NDEBUG) + LOG(debug2) << *this; +#endif + LOG(trace) << "done adding samples"; +} + +template <typename Freq_IT> +void FrequencyTable::addFrequencies(Freq_IT begin, Freq_IT end, value_t min, value_t max) +{ + static_assert(std::is_integral<typename std::iterator_traits<Freq_IT>::value_type>::value); + + LOG(trace) << "start adding frequencies"; + internal::RANSTimer t; + t.start(); + + if (begin == end) { + LOG(warning) << "Passed empty FrequencyTable to " << __func__; + return; + } + + // ensure correct size of frequency table and grow it if necessary + resizeFrequencyTable(min, max); + + // either 0 or offset from array start. + const size_t offset = std::abs(mMin - min); + + // ftableA[i] += fTableB[i+offset] + std::transform(begin, end, + mFrequencyTable.begin() + offset, + mFrequencyTable.begin() + offset, + [this](typename std::iterator_traits<Freq_IT>::value_type first, uint32_t second) { + mNumSamples += first; + return first + second; }); + + t.stop(); + LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + +#if !defined(NDEBUG) + LOG(debug2) << *this; +#endif + + LOG(trace) << "done adding frequencies"; +} + +inline typename FrequencyTable::value_t FrequencyTable::operator[](value_t index) const +{ + const value_t idx = index - mMin; + assert(idx >= 0); + assert(idx < mFrequencyTable.size()); + return mFrequencyTable[index]; +} + +inline size_t FrequencyTable::size() const +{ + return mFrequencyTable.size(); +} + +inline const uint32_t* FrequencyTable::data() const +{ + return mFrequencyTable.data(); +} + +inline const uint32_t* FrequencyTable::cbegin() const +{ + return mFrequencyTable.data(); +} + +inline const uint32_t* FrequencyTable::cend() const +{ + return mFrequencyTable.data() + mFrequencyTable.size(); +} + +inline uint32_t* FrequencyTable::begin() +{ + return const_cast<uint32_t*>(static_cast<const FrequencyTable*>(this)->begin()); +} + +inline uint32_t* FrequencyTable::end() +{ + return const_cast<uint32_t*>(static_cast<const FrequencyTable*>(this)->end()); +} + +inline const uint32_t* FrequencyTable::begin() const +{ + return cbegin(); +} + +inline const uint32_t* FrequencyTable::end() const +{ + return cend(); +} + +inline FrequencyTable& FrequencyTable::operator+(FrequencyTable& other) +{ + addFrequencies(std::begin(other), std::end(other), other.getMinSymbol(), other.getMaxSymbol()); + return *this; +} + +inline typename FrequencyTable::value_t FrequencyTable::getMinSymbol() const +{ + return mMin; +} + +inline typename FrequencyTable::value_t FrequencyTable::getMaxSymbol() const +{ + return mMax; +} + +inline size_t FrequencyTable::getAlphabetRangeBits() const +{ + if (mMax - mMin > 0) { + return std::ceil(std::log2(mMax - mMin)); + } else if (mMax - mMin == 0) { + return 1; + } else { + return 0; + } +} + +inline size_t FrequencyTable::getNumSamples() const +{ + return mNumSamples; +} + +} // namespace rans +} // namespace o2 + +#endif /* INCLUDE_RANS_FREQUENCYTABLE_H_ */ diff --git a/Utilities/rANS/include/rANS/LiteralDecoder.h b/Utilities/rANS/include/rANS/LiteralDecoder.h index ef42c27442dd9..e87382b4a27a8 100644 --- a/Utilities/rANS/include/rANS/LiteralDecoder.h +++ b/Utilities/rANS/include/rANS/LiteralDecoder.h @@ -68,7 +68,7 @@ void LiteralDecoder<coder_T, stream_T, source_T>::process(const source_IT output auto decode = [&, this](ransDecoder& decoder) { auto cumul = decoder.get(this->mProbabilityBits); - const uint32_t streamSymbol = (*this->mReverseLUT)[cumul]; + const auto streamSymbol = (*this->mReverseLUT)[cumul]; source_T symbol = streamSymbol; if (this->mSymbolTable->isLiteralSymbol(streamSymbol)) { symbol = literals.back(); diff --git a/Utilities/rANS/include/rANS/SymbolStatistics.h b/Utilities/rANS/include/rANS/SymbolStatistics.h deleted file mode 100644 index 0e33a09699629..0000000000000 --- a/Utilities/rANS/include/rANS/SymbolStatistics.h +++ /dev/null @@ -1,421 +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. - -/// @file SymbolStatistics.h -/// @author Michael Lettrich -/// @since 2019-05-08 -/// @brief Structure to depict the distribution of symbols in the source message. - -#ifndef RANS_SYMBOLSTATISTICS_H -#define RANS_SYMBOLSTATISTICS_H - -#include <algorithm> -#include <cassert> -#include <iostream> -#include <numeric> -#include <vector> -#include <cmath> -#include <iterator> -#include <type_traits> - -#include <fairlogger/Logger.h> - -#include "internal/helper.h" - -namespace o2 -{ -namespace rans -{ - -template <typename Source_T> -class SymbolStatistics -{ - static_assert(std::is_integral<Source_T>() && sizeof(Source_T) <= sizeof(uint32_t), "Source symbols restricted to integer types"); - - public: - class Iterator - { - public: - Iterator(size_t index, const SymbolStatistics& stats); - - using difference_type = int64_t; - using value_type = std::tuple<uint32_t, uint32_t>; - using pointer = const std::tuple<uint32_t, uint32_t>*; - using reference = const std::tuple<uint32_t, uint32_t>&; - using iterator_category = std::random_access_iterator_tag; - - const Iterator& operator++(); - - difference_type operator-(const Iterator& other) const; - - value_type operator*() const; - - bool operator!=(const Iterator& other) const; - - private: - size_t mIndex; - const SymbolStatistics<Source_T>& mStats; - }; - - public: - template <typename Source_IT> - SymbolStatistics(const Source_IT begin, const Source_IT end, Source_T min = 0, Source_T max = 0); - - template <typename Source_IT> - SymbolStatistics(const Source_IT begin, const Source_IT end, int32_t min, int32_t max, size_t messageLength); - - void rescaleToNBits(size_t bits); - - int32_t getMinSymbol() const; - int32_t getMaxSymbol() const; - size_t getAlphabetSize() const; - size_t getAlphabetRangeBits() const; - size_t getNUsedAlphabetSymbols() const; - - size_t getMessageLength() const; - - std::tuple<uint32_t, uint32_t> operator[](size_t index) const; - - SymbolStatistics::Iterator begin() const; - SymbolStatistics::Iterator end() const; - - const auto& getFrequencyTable() const { return mFrequencyTable; } - - private: - void buildCumulativeFrequencyTable(); - auto getFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } - - template <typename Source_IT> - void buildFrequencyTable(const Source_IT begin, const Source_IT end); - - int32_t mMin; - int32_t mMax; - size_t mMessageLength; - std::vector<uint32_t> mFrequencyTable; - std::vector<uint32_t> mCumulativeFrequencyTable; - - static constexpr size_t MAX_RANGE = 26; -}; - -template <typename Source_T> -template <typename Source_IT> -SymbolStatistics<Source_T>::SymbolStatistics(const Source_IT begin, const Source_IT end, Source_T min, Source_T max) : mMin(min), mMax(max), mMessageLength(0), mFrequencyTable(), mCumulativeFrequencyTable() -{ - static_assert(std::is_same<typename std::remove_const<typename std::iterator_traits<Source_IT>::value_type>::type, Source_T>::value); - - using namespace internal; - LOG(trace) << "start building symbol statistics"; - RANSTimer t; - t.start(); - if (begin == end) { - LOG(warning) << "Passed empty message to " << __func__; - return; - } - - //find size - if (mMin == 0 && mMax == 0) { - LOG(trace) << "finding minmax"; - const auto& [minIter, maxIter] = std::minmax_element(begin, end); - mMin = *minIter; - mMax = *maxIter; - LOG(trace) << "min: " << mMin << ", max: " << mMax; - } - - // range check - if (max - min > 1 << (MAX_RANGE - 1)) { - const std::string errmsg = [&]() { - std::stringstream ss; - ss << "Range of source message " << getAlphabetRangeBits() << "Bits surpasses maximal allowed range of " << MAX_RANGE << "Bits."; - return ss.str(); - }(); - LOG(error) << errmsg; - throw std::runtime_error(errmsg); - } - - buildFrequencyTable(begin, end); - - buildCumulativeFrequencyTable(); - - mMessageLength = std::distance(begin, end); - - assert(mFrequencyTable.size() > 0); - assert(mCumulativeFrequencyTable.size() > 1); - assert(mCumulativeFrequencyTable.size() - mFrequencyTable.size() == 1); - - t.stop(); - LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); - -// advanced diagnostics in debug builds -#if !defined(NDEBUG) - [&]() { - double entropy = 0; - for (auto frequency : mFrequencyTable) { - if (frequency > 0) { - const double p = (frequency * 1.0) / mMessageLength; - entropy -= p * std::log2(p); - } - } - - size_t nUsedAlphabetSymbols = 0; - for (auto symbolCount : mFrequencyTable) { - if (symbolCount > 0) { - ++nUsedAlphabetSymbols; - } - } - const auto minmax = std::minmax_element(begin, end); - - LOG(debug2) << "messageProperties: {" - << "messageLength: " << mMessageLength << ", " - << "alphabetRange: " << getAlphabetRangeBits() << ", " - << "alphabetSize: " << nUsedAlphabetSymbols << ", " - << "minSymbol: " << *minmax.first << ", " - << "maxSymbol: " << *minmax.second << ", " - << "entropy: " << entropy << ", " - << "bufferSizeB: " << mMessageLength * sizeof(typename std::iterator_traits<Source_IT>::value_type) << ", " - << "actualSizeB: " << static_cast<int>(mMessageLength * getAlphabetRangeBits() / 8) << ", " - << "entropyMessageB: " << static_cast<int>(std::ceil(entropy * mMessageLength / 8)) << "}"; - - LOG(debug2) << "SymbolStatistics: {" - << "entries: " << mFrequencyTable.size() << ", " - << "frequencyTableSizeB: " << mFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mFrequencyTable)>::value_type) << ", " - << "CumulativeFrequencyTableSizeB: " << mCumulativeFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mCumulativeFrequencyTable)>::value_type) << "}"; - }(); -#endif - - LOG(trace) << "done building symbol statistics"; -} - -template <typename Source_T> -template <typename Source_IT> -SymbolStatistics<Source_T>::SymbolStatistics(const Source_IT begin, const Source_IT end, int32_t min, int32_t max, size_t messageLength) : mMin(min), mMax(max), mMessageLength(messageLength), mFrequencyTable(begin, end), mCumulativeFrequencyTable() -{ - static_assert(std::is_same<typename std::remove_const<typename std::iterator_traits<Source_IT>::value_type>::type, uint32_t>::value); - - LOG(trace) << "start loading external symbol statistics"; - - buildCumulativeFrequencyTable(); - - LOG(debug2) << "SymbolStatistics: {" - << "messageLength: " << mMessageLength << ", " - << "entries: " << mFrequencyTable.size() << ", " - << "frequencyTableSizeB: " << mFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mFrequencyTable)>::value_type) << ", " - << "CumulativeFrequencyTableSizeB: " << mCumulativeFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mCumulativeFrequencyTable)>::value_type) << "}"; - - LOG(trace) << "done loading external symbol statistics"; -} - -template <typename Source_T> -template <typename Source_IT> -void SymbolStatistics<Source_T>::buildFrequencyTable(const Source_IT begin, const Source_IT end) -{ - static_assert(std::is_same<typename std::remove_const<typename std::iterator_traits<Source_IT>::value_type>::type, Source_T>::value); - - using namespace internal; - LOG(trace) << "start building frequency table"; - - ++mMax; - const size_t size = mMax - mMin; - LOG(trace) << "size: " << size; - assert(size > 0); - mFrequencyTable.resize(size + 1, 0); - - for (Source_IT it = begin; it != end; it++) { - const auto value = *it - mMin; - assert(value >= 0); - assert(value < size); - mFrequencyTable[value]++; - } - mFrequencyTable.back() = 1; - - LOG(trace) << "done building frequency table"; -} -template <typename Source_T> -void SymbolStatistics<Source_T>::rescaleToNBits(size_t bits) -{ - using namespace internal; - LOG(trace) << "start rescaling frequency table"; - RANSTimer t; - t.start(); - - if (mFrequencyTable.empty()) { - LOG(warning) << "rescaling Frequency Table for empty message"; - return; - } - - const size_t newCumulatedFrequency = bitsToRange(bits); - assert(newCumulatedFrequency >= mFrequencyTable.size()); - - size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); - - std::vector<uint32_t> sortIdx; - sortIdx.reserve(getNUsedAlphabetSymbols()); - - // resample distribution based on cumulative frequencies_ - for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i]) { - sortIdx.push_back(i); // we will sort only those memorize only those entries which can be used - } - } - - std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getFrequency(i) < this->getFrequency(j); }); - size_t need_shift = 0; - for (size_t i = 0; i < sortIdx.size(); i++) { - if (static_cast<uint64_t>(getFrequency(sortIdx[i])) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies >= 1) { - break; - } - need_shift++; - } - - size_t shift = 0; - auto beforeUpdate = mCumulativeFrequencyTable[0]; - for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i] && static_cast<uint64_t>(mCumulativeFrequencyTable[i + 1] - beforeUpdate) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies < 1) { - shift++; - } - beforeUpdate = mCumulativeFrequencyTable[i + 1]; - mCumulativeFrequencyTable[i + 1] = (static_cast<uint64_t>(newCumulatedFrequency - need_shift) * mCumulativeFrequencyTable[i + 1]) / cumulatedFrequencies + shift; - } - assert(shift == need_shift); - - // calculate updated freqs and make sure we didn't screw anything up - assert(mCumulativeFrequencyTable.front() == 0 && - mCumulativeFrequencyTable.back() == newCumulatedFrequency); - - for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i] == 0) - assert(mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]); - else - assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); - - // calc updated freq - mFrequencyTable[i] = getFrequency(i); - } - // for(int i = 0; i<static_cast<int>(freqs.getNumSymbols()); i++){ - // std::cout << i << ": " << i + min_ << " " << freqs[i] << " " << - // cummulatedFrequencies_[i] << std::endl; - // } - // std::cout << cummulatedFrequencies_.back() << std::endl; - - t.stop(); - LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); - - LOG(trace) << "done rescaling frequency table"; -} - -template <typename Source_T> -int32_t SymbolStatistics<Source_T>::getMinSymbol() const -{ - return mMin; -} - -template <typename Source_T> -int32_t SymbolStatistics<Source_T>::getMaxSymbol() const -{ - return mMax; -} - -template <typename Source_T> -size_t SymbolStatistics<Source_T>::getAlphabetSize() const -{ - return mFrequencyTable.size(); -} -template <typename Source_T> -size_t SymbolStatistics<Source_T>::getAlphabetRangeBits() const -{ - return std::ceil(std::log2(mMax - mMin)); -} -template <typename Source_T> -size_t SymbolStatistics<Source_T>::getNUsedAlphabetSymbols() const -{ - size_t nUsedAlphabetSymbols = 0; - for (auto symbolCount : mFrequencyTable) { - if (symbolCount > 0) { - ++nUsedAlphabetSymbols; - } - } - return nUsedAlphabetSymbols; -} - -template <typename Source_T> -size_t SymbolStatistics<Source_T>::getMessageLength() const -{ - return mMessageLength; -} -template <typename Source_T> -std::tuple<uint32_t, uint32_t> SymbolStatistics<Source_T>::operator[](size_t index) const -{ - // assert(index - mMin < mFrequencyTable.size()); - - return {mFrequencyTable[index], mCumulativeFrequencyTable[index]}; -} -template <typename Source_T> -void SymbolStatistics<Source_T>::buildCumulativeFrequencyTable() -{ - LOG(trace) << "start building cumulative frequency table"; - - mCumulativeFrequencyTable.resize(mFrequencyTable.size() + 1); - mCumulativeFrequencyTable[0] = 0; - std::partial_sum(mFrequencyTable.begin(), mFrequencyTable.end(), - mCumulativeFrequencyTable.begin() + 1); - - LOG(trace) << "done building cumulative frequency table"; -} - -template <typename Source_T> -typename SymbolStatistics<Source_T>::Iterator SymbolStatistics<Source_T>::begin() const -{ - return SymbolStatistics::Iterator(0, *this); -} - -template <typename Source_T> -typename SymbolStatistics<Source_T>::Iterator SymbolStatistics<Source_T>::end() const -{ - if (mFrequencyTable.empty()) { - return this->begin(); // begin == end for empty stats; - } else { - return SymbolStatistics::Iterator(mFrequencyTable.size(), *this); - } -} - -template <typename Source_T> -SymbolStatistics<Source_T>::Iterator::Iterator(size_t index, const SymbolStatistics<Source_T>& stats) : mIndex(index), mStats(stats) -{ -} - -template <typename Source_T> -const typename SymbolStatistics<Source_T>::Iterator& SymbolStatistics<Source_T>::Iterator::operator++() -{ - ++mIndex; - assert(mIndex <= mStats.getMaxSymbol() + 1); - return *this; -} - -template <typename Source_T> -typename SymbolStatistics<Source_T>::Iterator::difference_type SymbolStatistics<Source_T>::Iterator::operator-(const Iterator& other) const -{ - return mIndex - other.mIndex; -} - -template <typename Source_T> -typename SymbolStatistics<Source_T>::Iterator::value_type SymbolStatistics<Source_T>::Iterator::operator*() const -{ - return std::move(mStats[mIndex]); -} - -template <typename Source_T> -bool SymbolStatistics<Source_T>::Iterator::operator!=(const Iterator& other) const -{ - return this->mIndex != other.mIndex; -} - -} // namespace rans -} // namespace o2 - -#endif /* RANS_SYMBOLSTATISTICS_H */ diff --git a/Utilities/rANS/include/rANS/internal/EncoderSymbol.h b/Utilities/rANS/include/rANS/internal/EncoderSymbol.h index b15ecb8105bf9..133a97f10bae5 100644 --- a/Utilities/rANS/include/rANS/internal/EncoderSymbol.h +++ b/Utilities/rANS/include/rANS/internal/EncoderSymbol.h @@ -19,7 +19,7 @@ #include <cstdint> #include <cassert> -#include "../internal/helper.h" +#include "helper.h" namespace o2 { diff --git a/Utilities/rANS/include/rANS/internal/ReverseSymbolLookupTable.h b/Utilities/rANS/include/rANS/internal/ReverseSymbolLookupTable.h index 70deb2ff7b23d..7b10a3a6d5fc3 100644 --- a/Utilities/rANS/include/rANS/internal/ReverseSymbolLookupTable.h +++ b/Utilities/rANS/include/rANS/internal/ReverseSymbolLookupTable.h @@ -20,8 +20,8 @@ #include <type_traits> #include <fairlogger/Logger.h> -#include "../internal/helper.h" -#include "rANS/SymbolStatistics.h" +#include "helper.h" +#include "SymbolStatistics.h" namespace o2 { @@ -29,16 +29,16 @@ namespace rans { namespace internal { -template <typename Source_T> + class ReverseSymbolLookupTable { public: ReverseSymbolLookupTable(size_t probabilityBits, - const SymbolStatistics<Source_T>& stats) : mLut() + const SymbolStatistics& stats) : mLut() { LOG(trace) << "start building reverse symbol lookup table"; - if (stats.getAlphabetSize() == 0) { + if (stats.size() == 1) { LOG(warning) << "SymbolStatistics of empty message passed to " << __func__; return; } diff --git a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h new file mode 100644 index 0000000000000..4717bebdf4c5b --- /dev/null +++ b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h @@ -0,0 +1,222 @@ +// 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 SymbolStatistics.h +/// @author Michael Lettrich +/// @since 2019-05-08 +/// @brief Structure to depict the distribution of symbols in the source message. + +#ifndef RANS_SYMBOLSTATISTICS_H +#define RANS_SYMBOLSTATISTICS_H + +#include <algorithm> +#include <cassert> +#include <iostream> +#include <numeric> +#include <vector> +#include <cmath> +#include <iterator> +#include <type_traits> + +#include <fairlogger/Logger.h> + +#include "helper.h" +#include "rANS/FrequencyTable.h" + +namespace o2 +{ +namespace rans +{ +namespace internal +{ + +class SymbolStatistics +{ + + public: + class Iterator + { + public: + Iterator(size_t index, const SymbolStatistics& stats) : mIndex(index), mStats(stats){}; + + using difference_type = int64_t; + using value_type = std::tuple<uint32_t, uint32_t>; + using pointer = const std::tuple<uint32_t, uint32_t>*; + using reference = const std::tuple<uint32_t, uint32_t>&; + using iterator_category = std::random_access_iterator_tag; + + const Iterator& operator++(); + + difference_type operator-(const Iterator& other) const; + + value_type operator*() const; + + bool operator!=(const Iterator& other) const; + + private: + size_t mIndex; + const SymbolStatistics& mStats; + }; + + public: + SymbolStatistics(const FrequencyTable& frequencyTable, size_t scaleBits); + + template <typename Source_IT> + SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits); + + auto getFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } + + std::tuple<uint32_t, uint32_t> operator[](int64_t index) const; + std::tuple<uint32_t, uint32_t> at(size_t pos) const; + + Iterator begin() const; + Iterator end() const; + + size_t size() const; + + int64_t getMinSymbol() const; + int64_t getMaxSymbol() const; + + private: + void buildCumulativeFrequencyTable(); + + void rescale(); + + size_t getNUsedAlphabetSymbols() const; + + int64_t mMin; + int64_t mMax; + size_t mScaleBits; + + std::vector<uint32_t> mFrequencyTable; + std::vector<uint32_t> mCumulativeFrequencyTable; + + static constexpr size_t MAX_RANGE = 26; +}; + +template <typename Source_IT> +SymbolStatistics::SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits) : mMin(min), mMax(max), mScaleBits(scaleBits), mFrequencyTable(), mCumulativeFrequencyTable() +{ + + using namespace internal; + LOG(trace) << "start building symbol statistics"; + RANSTimer t; + t.start(); + + if (begin == end) { + LOG(warning) << "Passed empty message to " << __func__; + return; + } + + assert(mScaleBits > 0); + + //additional bit for incompressible symbol + mFrequencyTable.reserve(std::distance(begin, end) + 1); + + mFrequencyTable.insert(mFrequencyTable.begin(), begin, end); + //incompressible symbol + mFrequencyTable.push_back(1); + + // range check + if (mMax - mMin > 1 << (MAX_RANGE - 1)) { + const std::string errmsg = [&]() { + std::stringstream ss; + ss << "Range of source message " << std::ceil(std::log2(mMax - mMin)) << "Bits surpasses maximal allowed range of " << MAX_RANGE << "Bits."; + return ss.str(); + }(); + LOG(error) << errmsg; + throw std::runtime_error(errmsg); + } + + buildCumulativeFrequencyTable(); + rescale(); + + assert(mFrequencyTable.size() > 1); + assert(mCumulativeFrequencyTable.size() > 2); + assert(mCumulativeFrequencyTable.size() - mFrequencyTable.size() == 1); + + t.stop(); + LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + +// advanced diagnostics in debug builds +#if !defined(NDEBUG) + LOG(debug2) << "SymbolStatistics: {" + << "entries: " << mFrequencyTable.size() << ", " + << "frequencyTableSizeB: " << mFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mFrequencyTable)>::value_type) << ", " + << "CumulativeFrequencyTableSizeB: " << mCumulativeFrequencyTable.size() * sizeof(typename std::decay_t<decltype(mCumulativeFrequencyTable)>::value_type) << "}"; +#endif + + LOG(trace) << "done building symbol statistics"; +} + +inline int64_t SymbolStatistics::getMinSymbol() const +{ + return mMin; +} + +inline int64_t SymbolStatistics::getMaxSymbol() const +{ + return mMax; +} + +inline size_t SymbolStatistics::size() const +{ + return mFrequencyTable.size(); +} + +inline std::tuple<uint32_t, uint32_t> SymbolStatistics::operator[](int64_t index) const +{ + assert(index - mMin < mFrequencyTable.size()); + return {mFrequencyTable[index], mCumulativeFrequencyTable[index]}; +} + +inline std::tuple<uint32_t, uint32_t> SymbolStatistics::at(size_t pos) const +{ + assert(pos < mFrequencyTable.size()); + return {mFrequencyTable[pos], mCumulativeFrequencyTable[pos]}; +} + +inline SymbolStatistics::Iterator SymbolStatistics::begin() const +{ + return SymbolStatistics::Iterator(0, *this); +} + +inline SymbolStatistics::Iterator SymbolStatistics::end() const +{ + return SymbolStatistics::Iterator(mFrequencyTable.size(), *this); +} + +inline const SymbolStatistics::Iterator& SymbolStatistics::Iterator::operator++() +{ + ++mIndex; + assert(mIndex <= mStats.mFrequencyTable.size()); + return *this; +} + +inline SymbolStatistics::Iterator::difference_type SymbolStatistics::Iterator::operator-(const Iterator& other) const +{ + return mIndex - other.mIndex; +} + +inline typename SymbolStatistics::Iterator::value_type SymbolStatistics::Iterator::operator*() const +{ + return std::move(mStats.at(mIndex)); +} + +inline bool SymbolStatistics::Iterator::operator!=(const Iterator& other) const +{ + return this->mIndex != other.mIndex; +} + +} // namespace internal +} // namespace rans +} // namespace o2 + +#endif /* RANS_SYMBOLSTATISTICS_H */ diff --git a/Utilities/rANS/include/rANS/internal/SymbolTable.h b/Utilities/rANS/include/rANS/internal/SymbolTable.h index 922da16caf1d5..91ea8e9c4c0d9 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolTable.h +++ b/Utilities/rANS/include/rANS/internal/SymbolTable.h @@ -21,7 +21,7 @@ #include <fairlogger/Logger.h> -#include "rANS/SymbolStatistics.h" +#include "SymbolStatistics.h" namespace o2 { @@ -30,18 +30,18 @@ namespace rans namespace internal { -template <typename T, typename Source_T> +template <typename T> class SymbolTable { public: - SymbolTable(const SymbolStatistics<Source_T>& symbolStats, size_t probabiltyBits); + SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits); - const T& operator[](Source_T index) const; + const T& operator[](int64_t index) const; const T& getLiteralSymbol() const; - bool isLiteralSymbol(Source_T index) const; + bool isLiteralSymbol(int64_t index) const; private: int mMin; @@ -49,13 +49,13 @@ class SymbolTable std::vector<T> mSymbols; }; -template <typename T, typename Source_T> -SymbolTable<T, Source_T>::SymbolTable(const SymbolStatistics<Source_T>& symbolStats, uint64_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mIndex(), mSymbols() +template <typename T> +SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mIndex(), mSymbols() { LOG(trace) << "start building symbol table"; - mIndex.reserve(symbolStats.getAlphabetSize()); - mSymbols.reserve(symbolStats.getAlphabetSize()); + mIndex.reserve(symbolStats.size()); + mSymbols.reserve(symbolStats.size()); for (const auto& entry : symbolStats) { const auto [symFrequency, symCumulated] = entry; @@ -73,8 +73,8 @@ SymbolTable<T, Source_T>::SymbolTable(const SymbolStatistics<Source_T>& symbolSt LOG(trace) << "done building symbol table"; } -template <typename T, typename Source_T> -inline const T& SymbolTable<T, Source_T>::operator[](Source_T index) const +template <typename T> +inline const T& SymbolTable<T>::operator[](int64_t index) const { const auto idx = index - mMin; assert(idx >= 0); @@ -82,8 +82,8 @@ inline const T& SymbolTable<T, Source_T>::operator[](Source_T index) const return *(mIndex[idx]); } -template <typename T, typename Source_T> -inline bool SymbolTable<T, Source_T>::isLiteralSymbol(Source_T index) const +template <typename T> +inline bool SymbolTable<T>::isLiteralSymbol(int64_t index) const { const auto idx = index - mMin; assert(idx >= 0); @@ -91,8 +91,8 @@ inline bool SymbolTable<T, Source_T>::isLiteralSymbol(Source_T index) const return idx == mSymbols.size() - 1; } -template <typename T, typename Source_T> -inline const T& SymbolTable<T, Source_T>::getLiteralSymbol() const +template <typename T> +inline const T& SymbolTable<T>::getLiteralSymbol() const { return mSymbols.back(); } diff --git a/Utilities/rANS/include/rANS/rans.h b/Utilities/rANS/include/rANS/rans.h index acb293a7ca972..be2fd50b8fd42 100644 --- a/Utilities/rANS/include/rANS/rans.h +++ b/Utilities/rANS/include/rANS/rans.h @@ -16,7 +16,7 @@ #ifndef RANS_RANS_H #define RANS_RANS_H -#include "SymbolStatistics.h" +#include "FrequencyTable.h" #include "Encoder.h" #include "Decoder.h" #include "DedupEncoder.h" @@ -66,9 +66,10 @@ constexpr size_t ProbabilityBits25Bit = 25; inline size_t calculateMaxBufferSize(size_t num, size_t rangeBits, size_t sizeofStreamT) { - // RS: w/o safety margin the o2-test-ctf-io produces an overflow in the Encoder::process - constexpr size_t SaferyMargin = 16; - return std::ceil(1.20 * (num * rangeBits * 1.0) / (sizeofStreamT * 8.0)) + SaferyMargin; + // // RS: w/o safety margin the o2-test-ctf-io produces an overflow in the Encoder::process + // constexpr size_t SaferyMargin = 16; + // return std::ceil(1.20 * (num * rangeBits * 1.0) / (sizeofStreamT * 8.0)) + SaferyMargin; + return num * sizeofStreamT; } } // namespace rans diff --git a/Utilities/rANS/run/bin-encode-decode.cxx b/Utilities/rANS/run/bin-encode-decode.cxx index 82c2a810a92b5..d11416b6f9f31 100644 --- a/Utilities/rANS/run/bin-encode-decode.cxx +++ b/Utilities/rANS/run/bin-encode-decode.cxx @@ -123,22 +123,19 @@ int main(int argc, char* argv[]) std::vector<source_t> tokens; readFile(filename, &tokens); - std::unique_ptr<o2::rans::SymbolStatistics<source_t>> stats = [&]() { - auto stats = std::make_unique<o2::rans::SymbolStatistics<source_t>>(std::begin(tokens), std::end(tokens), symbolRangeBits); - stats->rescaleToNBits(probabilityBits); - return std::move(stats); - }(); + o2::rans::FrequencyTable frequencies; + frequencies.addSamples(std::begin(tokens), std::end(tokens)); std::vector<stream_t> encoderBuffer(256 << 20, 0); const auto encodedMessageEnd = [&]() { - const o2::rans::Encoder64<source_t> encoder{*stats, probabilityBits}; + const o2::rans::Encoder64<source_t> encoder{frequencies, probabilityBits}; return encoder.process(encoderBuffer.begin(), encoderBuffer.end(), std::begin(tokens), std::end(tokens)); }(); std::vector<source_t> decoderBuffer(tokens.size()); [&]() { - o2::rans::Decoder64<source_t> decoder{*stats, probabilityBits}; - decoder.process(decoderBuffer.begin(), encodedMessageEnd, stats->getMessageLength()); + o2::rans::Decoder64<source_t> decoder{frequencies, probabilityBits}; + decoder.process(decoderBuffer.begin(), encodedMessageEnd, std::distance(std::begin(tokens), std::end(tokens))); }(); if (std::memcmp(tokens.data(), decoderBuffer.data(), diff --git a/Utilities/rANS/src/FrequencyTable.cxx b/Utilities/rANS/src/FrequencyTable.cxx new file mode 100644 index 0000000000000..50d638941f373 --- /dev/null +++ b/Utilities/rANS/src/FrequencyTable.cxx @@ -0,0 +1,99 @@ +// 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 FrequencyTable.cxx +/// @author Michael Lettrich +/// @since Aug 1, 2020 +/// @brief Implementation of a frequency table for rANS symbole (i.e. a histogram) + +#include "rANS/FrequencyTable.h" + +namespace o2 +{ +namespace rans +{ + +void FrequencyTable::resizeFrequencyTable(value_t min, value_t max) +{ + LOG(trace) << "start resizing frequency table"; + internal::RANSTimer t; + t.start(); + // calculate new dimensions + const value_t newMin = std::min(mMin, min); + const value_t newMax = std::max(mMax, max); + const size_t newSize = newMax - newMin + 1; + + // empty - init; + if (mMin == 0 && mMax == 0) { + mFrequencyTable.resize(newSize, 0); + } + + // if the new size is bigger than the old one we need to resize the frequency table + if ((newSize) > mFrequencyTable.size()) { + const size_t offset = newMin < mMin ? std::abs(min - mMin) : 0; + std::vector<uint32_t> tmpFrequencyTable; + tmpFrequencyTable.reserve(newSize); + // insert initial offset if applicable + tmpFrequencyTable.insert(std::begin(tmpFrequencyTable), offset, 0); + // append current frequency table + tmpFrequencyTable.insert(std::end(tmpFrequencyTable), mFrequencyTable.begin(), mFrequencyTable.end()); + //fill tail with zeroes if applicable + const size_t tail = newMax > mMax ? std::abs(max - mMax) : 0; + tmpFrequencyTable.insert(std::end(tmpFrequencyTable), tail, 0); + + mFrequencyTable = std::move(tmpFrequencyTable); + } + + assert(mFrequencyTable.size() == newSize); + mMin = newMin; + mMax = newMax; + + t.stop(); + LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + LOG(trace) << "done resizing frequency table"; +} + +size_t FrequencyTable::getUsedAlphabetSize() const +{ + size_t nUsedAlphabetSymbols = 0; + + for (auto freq : *this) { + if (freq > 0) { + nUsedAlphabetSymbols++; + } + } + return nUsedAlphabetSymbols; +} + +std::ostream& operator<<(std::ostream& out, const FrequencyTable& fTable) +{ + double entropy = 0; + for (auto frequency : fTable) { + if (frequency > 0) { + const double p = (frequency * 1.0) / fTable.getNumSamples(); + entropy -= p * std::log2(p); + } + } + + out << "FrequencyTable: {" + << "numSymbols: " << fTable.getNumSamples() << ", " + << "alphabetRange: " << fTable.getAlphabetRangeBits() << ", " + << "alphabetSize: " << fTable.getUsedAlphabetSize() << ", " + << "minSymbol: " << fTable.getMinSymbol() << ", " + << "maxSymbol: " << fTable.getMaxSymbol() << ", " + << "sizeFrequencyTableB: " << fTable.size() << ", " + << "sizeFrequencyTableB: " << fTable.size() * sizeof(typename o2::rans::FrequencyTable::value_t) << ", " + << "entropy: " << entropy << "}"; + + return out; +} + +} //namespace rans +} // namespace o2 diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx new file mode 100644 index 0000000000000..ab8feddbaf4d0 --- /dev/null +++ b/Utilities/rANS/src/SymbolStatistics.cxx @@ -0,0 +1,128 @@ +// 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 SymbolStatistics.cpp +/// @author Michael Lettrich +/// @since 2019-05-08 +/// @brief Structure to depict the distribution of symbols in the source message. + +#include <cmath> + +#include "rANS/internal/SymbolStatistics.h" +#include "rANS/internal/helper.h" + +namespace o2 +{ +namespace rans +{ +namespace internal +{ + +SymbolStatistics::SymbolStatistics(const FrequencyTable& frequencyTable, size_t scaleBits) : SymbolStatistics(frequencyTable.begin(), frequencyTable.end(), frequencyTable.getMinSymbol(), frequencyTable.getMaxSymbol(), scaleBits){}; + +void SymbolStatistics::rescale() +{ + + using namespace internal; + LOG(trace) << "start rescaling frequency table"; + RANSTimer t; + t.start(); + + if (mFrequencyTable.empty()) { + LOG(warning) << "rescaling Frequency Table for empty message"; + return; + } + + const size_t newCumulatedFrequency = bitsToRange(mScaleBits); + assert(newCumulatedFrequency >= mFrequencyTable.size()); + + size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); + + std::vector<uint32_t> sortIdx; + sortIdx.reserve(getNUsedAlphabetSymbols()); + + // resample distribution based on cumulative frequencies_ + for (size_t i = 0; i < mFrequencyTable.size(); i++) { + if (mFrequencyTable[i]) { + sortIdx.push_back(i); // we will sort only those memorize only those entries which can be used + } + } + + std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getFrequency(i) < this->getFrequency(j); }); + size_t need_shift = 0; + for (size_t i = 0; i < sortIdx.size(); i++) { + if (static_cast<uint64_t>(getFrequency(sortIdx[i])) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies >= 1) { + break; + } + need_shift++; + } + + size_t shift = 0; + auto beforeUpdate = mCumulativeFrequencyTable[0]; + for (size_t i = 0; i < mFrequencyTable.size(); i++) { + if (mFrequencyTable[i] && static_cast<uint64_t>(mCumulativeFrequencyTable[i + 1] - beforeUpdate) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies < 1) { + shift++; + } + beforeUpdate = mCumulativeFrequencyTable[i + 1]; + mCumulativeFrequencyTable[i + 1] = (static_cast<uint64_t>(newCumulatedFrequency - need_shift) * mCumulativeFrequencyTable[i + 1]) / cumulatedFrequencies + shift; + } + assert(shift == need_shift); + + // calculate updated freqs and make sure we didn't screw anything up + assert(mCumulativeFrequencyTable.front() == 0 && + mCumulativeFrequencyTable.back() == newCumulatedFrequency); + + for (size_t i = 0; i < mFrequencyTable.size(); i++) { + if (mFrequencyTable[i] == 0) + assert(mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]); + else + assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); + + // calc updated freq + mFrequencyTable[i] = getFrequency(i); + } + // for(int i = 0; i<static_cast<int>(freqs.getNumSymbols()); i++){ + // std::cout << i << ": " << i + min_ << " " << freqs[i] << " " << + // cummulatedFrequencies_[i] << std::endl; + // } + // std::cout << cummulatedFrequencies_.back() << std::endl; + + t.stop(); + LOG(debug1) << __func__ << " inclusive time (ms): " << t.getDurationMS(); + + LOG(trace) << "done rescaling frequency table"; +} + +size_t SymbolStatistics::getNUsedAlphabetSymbols() const +{ + size_t nUsedAlphabetSymbols = 0; + for (auto symbolCount : mFrequencyTable) { + if (symbolCount > 0) { + ++nUsedAlphabetSymbols; + } + } + return nUsedAlphabetSymbols; +} + +void SymbolStatistics::buildCumulativeFrequencyTable() +{ + LOG(trace) << "start building cumulative frequency table"; + + mCumulativeFrequencyTable.resize(mFrequencyTable.size() + 1); + mCumulativeFrequencyTable[0] = 0; + std::partial_sum(mFrequencyTable.begin(), mFrequencyTable.end(), + mCumulativeFrequencyTable.begin() + 1); + + LOG(trace) << "done building cumulative frequency table"; +} + +} // namespace internal +} // namespace rans +} // namespace o2 diff --git a/Utilities/rANS/test/test_ransEncodeDecode.cxx b/Utilities/rANS/test/test_ransEncodeDecode.cxx index 50e00d6861568..500be5f5d3e1b 100644 --- a/Utilities/rANS/test/test_ransEncodeDecode.cxx +++ b/Utilities/rANS/test/test_ransEncodeDecode.cxx @@ -53,7 +53,7 @@ struct Fixture { // 25Bits for 25Bit alphabets const uint probabilityBits = P; - const std::string source = ""; + const std::string source; }; template <typename CODER_T, typename STREAM_T, uint P> @@ -77,14 +77,13 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode, T, Fixtures, T) { // iterate over the message and create PDF and CDF for each symbol in the message - o2::rans::SymbolStatistics<typename T::source_t> stats{std::begin(T::source), std::end(T::source)}; - // For performance reason the distributions must be rescaled to be a power of two. - stats.rescaleToNBits(T::probabilityBits); + o2::rans::FrequencyTable frequencies; + frequencies.addSamples(std::begin(T::source), std::end(T::source)); // buffer to write the rANS coded message into std::vector<typename T::stream_t> encoderBuffer(1 << 20, 0); //create a stateful encoder object that builds an encoding table from the given symbol statistics - const typename T::encoder_t encoder{stats, T::probabilityBits}; + const typename T::encoder_t encoder{frequencies, T::probabilityBits}; // encoder rANS encodes symbols from SOURCE array to encoder Buffer. Since coder and decoder // are mathematical inverse functions on the ANS state, they operate as a stack - // i.e. the decoder outputs the message in reverse order of the encoder. @@ -97,9 +96,9 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode, T, Fixtures, T) // The decoded message will go into the decoder buffer which will have as many symbols as the original message std::vector<typename T::source_t> decoderBuffer(std::distance(std::begin(T::source), std::end(T::source)), 0); // create a stateful decoder object that build a decoding table from the given symbol statistics - const typename T::decoder_t decoder{stats, T::probabilityBits}; + const typename T::decoder_t decoder{frequencies, T::probabilityBits}; // the decoder unwinds the rANS state in the encoder buffer starting at ransBegin and decodes it into the decode buffer; - decoder.process(decoderBuffer.begin(), encodedMessageEnd, stats.getMessageLength()); + decoder.process(decoderBuffer.begin(), encodedMessageEnd, std::distance(std::begin(T::source), std::end(T::source))); //the decodeBuffer and the source message have to be identical afterwards. BOOST_REQUIRE(std::memcmp(&(*T::source.begin()), decoderBuffer.data(), @@ -110,10 +109,10 @@ typedef boost::mpl::vector<FixtureFull<uint32_t, uint8_t, 14>, FixtureFull<uint6 BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_literals, T, LiteralFixtures, T) { + // iterate over the message and create PDF and CDF for each symbol in the message - o2::rans::SymbolStatistics<typename T::source_t> stats{std::begin(T::source), std::end(T::source)}; - // For performance reason the distributions must be rescaled to be a power of two. - stats.rescaleToNBits(T::probabilityBits); + o2::rans::FrequencyTable frequencies; + frequencies.addSamples(std::begin(T::source), std::end(T::source)); std::string adaptedSource = "\\"; adaptedSource.append(T::source); @@ -122,7 +121,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_literals, T, LiteralFixtures, // buffer to write the rANS coded message into std::vector<typename T::stream_t> encoderBuffer(1 << 20, 0); //create a stateful encoder object that builds an encoding table from the given symbol statistics - const typename T::literalEncoder_t encoder{stats, T::probabilityBits}; + const typename T::literalEncoder_t encoder{frequencies, T::probabilityBits}; // encoder rANS encodes symbols from SOURCE array to encoder Buffer. Since coder and decoder // are mathematical inverse functions on the ANS state, they operate as a stack - // i.e. the decoder outputs the message in reverse order of the encoder. @@ -136,7 +135,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_literals, T, LiteralFixtures, // The decoded message will go into the decoder buffer which will have as many symbols as the original message std::vector<typename T::source_t> decoderBuffer(std::distance(std::begin(adaptedSource), std::end(adaptedSource)), 0); // create a stateful decoder object that build a decoding table from the given symbol statistics - const typename T::literalDecoder_t decoder{stats, T::probabilityBits}; + const typename T::literalDecoder_t decoder{frequencies, T::probabilityBits}; // the decoder unwinds the rANS state in the encoder buffer starting at ransBegin and decodes it into the decode buffer; decoder.process(decoderBuffer.begin(), encodedMessageEnd, std::distance(std::begin(adaptedSource), std::end(adaptedSource)), literals); @@ -151,14 +150,13 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_dedup, T, DedupFixtures, T) { // iterate over the message and create PDF and CDF for each symbol in the message - o2::rans::SymbolStatistics<typename T::source_t> stats{std::begin(T::source), std::end(T::source)}; - // For performance reason the distributions must be rescaled to be a power of two. - stats.rescaleToNBits(T::probabilityBits); + o2::rans::FrequencyTable frequencies; + frequencies.addSamples(std::begin(T::source), std::end(T::source)); // buffer to write the rANS coded message into std::vector<typename T::stream_t> encoderBuffer(1 << 20, 0); //create a stateful encoder object that builds an encoding table from the given symbol statistics - const typename T::dedupEncoder_t encoder{stats, T::probabilityBits}; + const typename T::dedupEncoder_t encoder{frequencies, T::probabilityBits}; // encoder rANS encodes symbols from SOURCE array to encoder Buffer. Since coder and decoder // are mathematical inverse functions on the ANS state, they operate as a stack - // i.e. the decoder outputs the message in reverse order of the encoder. @@ -172,9 +170,9 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_dedup, T, DedupFixtures, T) // The decoded message will go into the decoder buffer which will have as many symbols as the original message std::vector<typename T::source_t> decoderBuffer(std::distance(std::begin(T::source), std::end(T::source)), 0); // create a stateful decoder object that build a decoding table from the given symbol statistics - const typename T::dedupDecoder_t decoder{stats, T::probabilityBits}; + const typename T::dedupDecoder_t decoder{frequencies, T::probabilityBits}; // the decoder unwinds the rANS state in the encoder buffer starting at ransBegin and decodes it into the decode buffer; - decoder.process(decoderBuffer.begin(), encodedMessageEnd, stats.getMessageLength(), duplicates); + decoder.process(decoderBuffer.begin(), encodedMessageEnd, std::distance(std::begin(T::source), std::end(T::source)), duplicates); //the decodeBuffer and the source message have to be identical afterwards. BOOST_REQUIRE(std::memcmp(&(*T::source.begin()), decoderBuffer.data(), diff --git a/Utilities/rANS/test/test_ransFrequencyTable.cxx b/Utilities/rANS/test/test_ransFrequencyTable.cxx new file mode 100644 index 0000000000000..b67d40584201d --- /dev/null +++ b/Utilities/rANS/test/test_ransFrequencyTable.cxx @@ -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. + +/// @file test_ransFrequencyTable.cxx +/// @author Michael Lettrich +/// @since Aug 1, 2020 +/// @brief + +#define BOOST_TEST_MODULE Utility test +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> + +#include "rANS/rans.h" + +BOOST_AUTO_TEST_CASE(test_addSamples) +{ + std::vector<int> A{5, 5, 6, 6, 8, 8, 8, 8, 8, -1, -5, 2, 7, 3}; + std::vector<uint32_t> histA{1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 2, 2, 1, 5}; + + o2::rans::FrequencyTable fA; + fA.addSamples(std::begin(A), std::end(A)); + + BOOST_CHECK_EQUAL(fA.getMinSymbol(), -5); + BOOST_CHECK_EQUAL(fA.getMaxSymbol(), 8); + BOOST_CHECK_EQUAL(fA.size(), histA.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(fA), std::end(fA), std::begin(histA), std::end(histA)); + + std::vector<int> B{10, -10}; + fA.addSamples(std::begin(B), std::end(B)); + + BOOST_CHECK_EQUAL(fA.getMinSymbol(), -10); + BOOST_CHECK_EQUAL(fA.getMaxSymbol(), 10); + + std::vector<uint32_t> histAandB{1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 2, 2, 1, 5, 0, 1}; + BOOST_CHECK_EQUAL(fA.size(), histAandB.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(fA), std::end(fA), std::begin(histAandB), std::end(histAandB)); +} + +BOOST_AUTO_TEST_CASE(test_addFrequencies) +{ + std::vector<int> A{5, 5, 6, 6, 8, 8, 8, 8, 8, -1, -5, 2, 7, 3}; + std::vector<uint32_t> histA{1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 2, 2, 1, 5}; + + o2::rans::FrequencyTable ftmp; + ftmp.addSamples(std::begin(A), std::end(A)); + + o2::rans::FrequencyTable fA; + fA.addFrequencies(std::begin(ftmp), std::end(ftmp), ftmp.getMinSymbol(), ftmp.getMaxSymbol()); + + BOOST_CHECK_EQUAL(fA.getMinSymbol(), -5); + BOOST_CHECK_EQUAL(fA.getMaxSymbol(), 8); + BOOST_CHECK_EQUAL(fA.size(), histA.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(fA), std::end(fA), std::begin(histA), std::end(histA)); + + std::vector<int> B{10, 8, -10}; + o2::rans::FrequencyTable fB; + fB.addSamples(std::begin(B), std::end(B)); + + fA = fA + fB; + + BOOST_CHECK_EQUAL(fA.getMinSymbol(), -10); + BOOST_CHECK_EQUAL(fA.getMaxSymbol(), 10); + + std::vector<uint32_t> histAandB{1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 2, 2, 1, 6, 0, 1}; + BOOST_CHECK_EQUAL(fA.size(), histAandB.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(fA), std::end(fA), std::begin(histAandB), std::end(histAandB)); +} From f5086f8462c5729e8150d2551d0d1648e7bc3fb3 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Mon, 3 Aug 2020 20:35:32 +0200 Subject: [PATCH 0273/1751] [rANS] adapt rescaling in FrequencyTable --- Utilities/rANS/include/rANS/internal/SymbolStatistics.h | 2 -- Utilities/rANS/src/SymbolStatistics.cxx | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h index 4717bebdf4c5b..e648a649f1e1f 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h @@ -71,8 +71,6 @@ class SymbolStatistics template <typename Source_IT> SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits); - auto getFrequency(size_t i) const { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; } - std::tuple<uint32_t, uint32_t> operator[](int64_t index) const; std::tuple<uint32_t, uint32_t> at(size_t pos) const; diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx index ab8feddbaf4d0..5e41593654b12 100644 --- a/Utilities/rANS/src/SymbolStatistics.cxx +++ b/Utilities/rANS/src/SymbolStatistics.cxx @@ -30,6 +30,8 @@ SymbolStatistics::SymbolStatistics(const FrequencyTable& frequencyTable, size_t void SymbolStatistics::rescale() { + auto getFrequency = [this](size_t i) { return mCumulativeFrequencyTable[i + 1] - mCumulativeFrequencyTable[i]; }; + using namespace internal; LOG(trace) << "start rescaling frequency table"; RANSTimer t; @@ -55,7 +57,7 @@ void SymbolStatistics::rescale() } } - std::sort(sortIdx.begin(), sortIdx.end(), [this](uint32_t i, uint32_t j) { return this->getFrequency(i) < this->getFrequency(j); }); + std::sort(sortIdx.begin(), sortIdx.end(), [&](uint32_t i, uint32_t j) { return getFrequency(i) < getFrequency(j); }); size_t need_shift = 0; for (size_t i = 0; i < sortIdx.size(); i++) { if (static_cast<uint64_t>(getFrequency(sortIdx[i])) * (newCumulatedFrequency - need_shift) / cumulatedFrequencies >= 1) { From c20166e3d540ee627533aaec36fdebbc815a0f0a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 5 Aug 2020 15:44:17 +0200 Subject: [PATCH 0274/1751] GPU: Fix race condition between TrackletSelector and GlobalTracking --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 47 ++++++++++++------- .../SliceTracker/GPUTPCGlobalTracking.cxx | 10 ++++ .../SliceTracker/GPUTPCGlobalTracking.h | 1 + 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 660288bbe9fd1..b0ad632acc79d 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1704,12 +1704,8 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() if (param().rec.GlobalTracking) { for (unsigned int tmpSlice2a = 0; tmpSlice2a <= iSlice; tmpSlice2a += GetProcessingSettings().nDeviceHelperThreads + 1) { unsigned int tmpSlice2 = GPUTPCGlobalTracking::GlobalTrackingSliceOrder(tmpSlice2a); - unsigned int sliceLeft = (tmpSlice2 + (NSLICES / 2 - 1)) % (NSLICES / 2); - unsigned int sliceRight = (tmpSlice2 + 1) % (NSLICES / 2); - if (tmpSlice2 >= (int)NSLICES / 2) { - sliceLeft += NSLICES / 2; - sliceRight += NSLICES / 2; - } + unsigned int sliceLeft, sliceRight; + GPUTPCGlobalTracking::GlobalTrackingSliceLeftRight(tmpSlice2, sliceLeft, sliceRight); if (tmpSlice2 <= iSlice && sliceLeft <= iSlice && sliceRight <= iSlice && mWriteOutputDone[tmpSlice2] == 0) { GlobalTracking(tmpSlice2, 0); @@ -1725,13 +1721,34 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } WaitForHelperThreads(); } + if (!(GetRecoStepsOutputs() & GPUDataTypes::InOutType::TPCSectorTracks) && param().rec.GlobalTracking) { + std::vector<bool> blocking(NSLICES * mRec->NStreams()); + for (int i = 0; i < NSLICES; i++) { + for (int j = 0; j < mRec->NStreams(); j++) { + blocking[i * mRec->NStreams() + j] = i % mRec->NStreams() == j; + } + } + for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { + unsigned int tmpSlice = GPUTPCGlobalTracking::GlobalTrackingSliceOrder(iSlice); + if (!((GetRecoStepsOutputs() & GPUDataTypes::InOutType::TPCSectorTracks) || (doGPU && !(GetRecoStepsGPU() & RecoStep::TPCMerging)))) { + unsigned int sliceLeft, sliceRight; + GPUTPCGlobalTracking::GlobalTrackingSliceLeftRight(tmpSlice, sliceLeft, sliceRight); + if (!blocking[tmpSlice * mRec->NStreams() + sliceLeft] % mRec->NStreams()) { + StreamWaitForEvents(tmpSlice % mRec->NStreams(), &mEvents->slice[sliceLeft]); + blocking[tmpSlice * mRec->NStreams() + sliceLeft % mRec->NStreams()] = true; + } + if (!blocking[tmpSlice * mRec->NStreams() + sliceRight] % mRec->NStreams()) { + StreamWaitForEvents(tmpSlice % mRec->NStreams(), &mEvents->slice[sliceRight]); + blocking[tmpSlice * mRec->NStreams() + sliceRight % mRec->NStreams()] = true; + } + } + GlobalTracking(tmpSlice, 0, !GetProcessingSettings().fullMergerOnGPU); + } + } for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { if (transferRunning[iSlice]) { ReleaseEvent(&mEvents->slice[iSlice]); } - if (!(GetRecoStepsOutputs() & GPUDataTypes::InOutType::TPCSectorTracks) && param().rec.GlobalTracking) { - GlobalTracking(iSlice, 0, !GetProcessingSettings().fullMergerOnGPU); - } } } else { mSliceSelectorReady = NSLICES; @@ -2451,15 +2468,11 @@ int GPUChainTracking::HelperReadEvent(int iSlice, int threadId, GPUReconstructio int GPUChainTracking::HelperOutput(int iSlice, int threadId, GPUReconstructionHelpers::helperParam* par) { if (param().rec.GlobalTracking) { - int tmpSlice = GPUTPCGlobalTracking::GlobalTrackingSliceOrder(iSlice); - int sliceLeft = (tmpSlice + (NSLICES / 2 - 1)) % (NSLICES / 2); - int sliceRight = (tmpSlice + 1) % (NSLICES / 2); - if (tmpSlice >= (int)NSLICES / 2) { - sliceLeft += NSLICES / 2; - sliceRight += NSLICES / 2; - } + unsigned int tmpSlice = GPUTPCGlobalTracking::GlobalTrackingSliceOrder(iSlice); + unsigned int sliceLeft, sliceRight; + GPUTPCGlobalTracking::GlobalTrackingSliceLeftRight(tmpSlice, sliceLeft, sliceRight); - while (mSliceSelectorReady < tmpSlice || mSliceSelectorReady < sliceLeft || mSliceSelectorReady < sliceRight) { + while (mSliceSelectorReady < (int)tmpSlice || mSliceSelectorReady < (int)sliceLeft || mSliceSelectorReady < (int)sliceRight) { if (par->reset) { return 1; } diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx index 84f9e062e2555..8c4cecc096de7 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx @@ -191,6 +191,16 @@ GPUd() int GPUTPCGlobalTracking::GlobalTrackingSliceOrder(int iSlice) } return iSlice; } + +GPUd() void GPUTPCGlobalTracking::GlobalTrackingSliceLeftRight(unsigned int iSlice, unsigned int& left, unsigned int& right) +{ + left = (iSlice + (GPUDataTypes::NSLICES / 2 - 1)) % (GPUDataTypes::NSLICES / 2); + right = (iSlice + 1) % (GPUDataTypes::NSLICES / 2); + if (iSlice >= (int)GPUDataTypes::NSLICES / 2) { + left += GPUDataTypes::NSLICES / 2; + right += GPUDataTypes::NSLICES / 2; + } +} #endif // !__OPENCL__ || __OPENCLCPP__ template <> diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.h b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.h index 836db229d7ce5..d981be3ba5423 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.h +++ b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.h @@ -42,6 +42,7 @@ class GPUTPCGlobalTracking : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() MEM_LOCAL(GPUSharedMemory) & smem, processorType& tracker); GPUd() static int GlobalTrackingSliceOrder(int iSlice); + GPUd() static void GlobalTrackingSliceLeftRight(unsigned int iSlice, unsigned int& left, unsigned int& right); private: GPUd() static int PerformGlobalTrackingRun(GPUTPCTracker& tracker, GPUsharedref() MEM_LOCAL(GPUSharedMemory) & GPUrestrict() smem, const GPUTPCTracker& sliceSource, int iTrack, int rowIndex, float angle, int direction); From f6664d72281df8481d959f36dbf36abe736b53e2 Mon Sep 17 00:00:00 2001 From: Thomas Klemenz <thomas.klemenz@tum.de> Date: Tue, 16 Jun 2020 12:16:49 +0200 Subject: [PATCH 0275/1751] added CalPadWrapper to enable publishing of CalPad to QCG --- Detectors/TPC/qc/CMakeLists.txt | 3 +- .../TPC/qc/include/TPCQC/CalPadWrapper.h | 61 +++++++++++++++++++ Detectors/TPC/qc/include/TPCQC/Clusters.h | 7 +++ Detectors/TPC/qc/src/TPCQCLinkDef.h | 1 + 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 Detectors/TPC/qc/include/TPCQC/CalPadWrapper.h diff --git a/Detectors/TPC/qc/CMakeLists.txt b/Detectors/TPC/qc/CMakeLists.txt index 28cd9b510cb84..2f60bf0bcfe8b 100644 --- a/Detectors/TPC/qc/CMakeLists.txt +++ b/Detectors/TPC/qc/CMakeLists.txt @@ -23,7 +23,8 @@ o2_target_root_dictionary(TPCQC include/TPCQC/Helpers.h include/TPCQC/TrackCuts.h include/TPCQC/Clusters.h - include/TPCQC/Tracks.h) + include/TPCQC/Tracks.h + include/TPCQC/CalPadWrapper.h) o2_add_test(PID COMPONENT_NAME tpc diff --git a/Detectors/TPC/qc/include/TPCQC/CalPadWrapper.h b/Detectors/TPC/qc/include/TPCQC/CalPadWrapper.h new file mode 100644 index 0000000000000..77afbc8909b4b --- /dev/null +++ b/Detectors/TPC/qc/include/TPCQC/CalPadWrapper.h @@ -0,0 +1,61 @@ +// 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_CalPadWrapper_H +#define O2_CalPadWrapper_H + +#include <TClass.h> +#include <TObject.h> + +#include "TPCBase/CalDet.h" + +namespace o2 +{ +namespace tpc +{ +namespace qc +{ +/// Temporary solution until objects not inheriting from TObject can be handled in QualityControl +/// A wrapper class to easily promote CalDet<float> objects to a TObject +/// does not take ownership of wrapped object and should not be used +/// in tight loops since construction expensive +class CalPadWrapper : public TObject +{ + public: + CalPadWrapper(o2::tpc::CalDet<float>* obj) : mObj(obj), TObject() + { + } + + CalPadWrapper() = default; + + void setObj(o2::tpc::CalDet<float>* obj) + { + mObj = obj; + } + + o2::tpc::CalDet<float>* getObj() + { + return mObj; + } + + virtual const char* GetName() const override { return mObj ? mObj->getName().data() : "unset"; } + + virtual ~CalPadWrapper() override = default; + + private: + o2::tpc::CalDet<float>* mObj{}; ///< wrapped CalDet<float> (aka CalPad) + + ClassDefOverride(CalPadWrapper, 1); +}; +} // namespace qc +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/qc/include/TPCQC/Clusters.h b/Detectors/TPC/qc/include/TPCQC/Clusters.h index 9944124c7b61f..9d4668f490887 100644 --- a/Detectors/TPC/qc/include/TPCQC/Clusters.h +++ b/Detectors/TPC/qc/include/TPCQC/Clusters.h @@ -54,6 +54,13 @@ class Clusters const CalPad& getSigmaPad() const { return mSigmaPad; } const CalPad& getTimeBin() const { return mTimeBin; } + CalPad& getNClusters() { return mNClusters; } + CalPad& getQMax() { return mQMax; } + CalPad& getQTot() { return mQTot; } + CalPad& getSigmaTime() { return mSigmaTime; } + CalPad& getSigmaPad() { return mSigmaPad; } + CalPad& getTimeBin() { return mTimeBin; } + private: CalPad mNClusters{"N_Clusters"}; CalPad mQMax{"Q_Max"}; diff --git a/Detectors/TPC/qc/src/TPCQCLinkDef.h b/Detectors/TPC/qc/src/TPCQCLinkDef.h index 565d9a7a385aa..99cce76f3c5c5 100644 --- a/Detectors/TPC/qc/src/TPCQCLinkDef.h +++ b/Detectors/TPC/qc/src/TPCQCLinkDef.h @@ -18,6 +18,7 @@ #pragma link C++ class o2::tpc::qc::TrackCuts+; #pragma link C++ class o2::tpc::qc::Clusters+; #pragma link C++ class o2::tpc::qc::Tracks+; +#pragma link C++ class o2::tpc::qc::CalPadWrapper+; #pragma link C++ function o2::tpc::qc::helpers::makeLogBinning+; #pragma link C++ function o2::tpc::qc::helpers::setStyleHistogram1D+; #pragma link C++ function o2::tpc::qc::helpers::setStyleHistogram2D+; From 500c14c7c43f6f6460b46d65c9e7eafa7c2d3511 Mon Sep 17 00:00:00 2001 From: Thomas Klemenz <thomas.klemenz@tum.de> Date: Tue, 23 Jun 2020 15:50:45 +0200 Subject: [PATCH 0276/1751] prevent division by 0 in CalArray /= operator --- Detectors/TPC/base/include/TPCBase/CalArray.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/CalArray.h b/Detectors/TPC/base/include/TPCBase/CalArray.h index 1536162b57b12..839df16c2b4e5 100644 --- a/Detectors/TPC/base/include/TPCBase/CalArray.h +++ b/Detectors/TPC/base/include/TPCBase/CalArray.h @@ -229,7 +229,7 @@ template <class T> inline const CalArray<T>& CalArray<T>::operator*=(const CalArray<T>& other) { if (!((mPadSubset == other.mPadSubset) && (mPadSubsetNumber == other.mPadSubsetNumber))) { - LOG(ERROR) << "pad subste type of the objects it not compatible"; + LOG(ERROR) << "pad subset type of the objects it not compatible"; return *this; } for (size_t i = 0; i < mData.size(); ++i) { @@ -243,11 +243,16 @@ template <class T> inline const CalArray<T>& CalArray<T>::operator/=(const CalArray<T>& other) { if (!((mPadSubset == other.mPadSubset) && (mPadSubsetNumber == other.mPadSubsetNumber))) { - LOG(ERROR) << "pad subste type of the objects it not compatible"; + LOG(ERROR) << "pad subset type of the objects it not compatible"; return *this; } for (size_t i = 0; i < mData.size(); ++i) { - mData[i] /= other.getValue(i); + if (other.getValue(i) != 0) { + mData[i] /= other.getValue(i); + } else { + mData[i] = 0; + LOG(ERROR) << "Division by 0 detected! Value was set to 0."; + } } return *this; } From ae2a58fdfaf65dae35f408c1ad3e9ee5c74fbe3c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 5 Aug 2020 21:47:07 +0200 Subject: [PATCH 0277/1751] Use random seeding in digitization (interaction records) So far, the same interaction records were produced for each digitization invocation. This commit forces random start seeding as a quick fix. --- Steer/DigitizerWorkflow/src/SimReaderSpec.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx b/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx index 2cad46653185e..ad8922be63902 100644 --- a/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx +++ b/Steer/DigitizerWorkflow/src/SimReaderSpec.cxx @@ -85,6 +85,10 @@ DataProcessorSpec getSimReaderSpec(SubspecRange range, const std::vector<std::st // initialize fundamental objects auto& mgr = steer::HitProcessingManager::instance(); + // init gRandom to random start + // TODO: offer option to set seed + gRandom->SetSeed(0); + if (simprefixes.size() == 0) { LOG(ERROR) << "No simulation prefix available"; } else { From 0057a62b0264f11eab30e626527251a86b2838ae Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Thu, 6 Aug 2020 15:05:22 +0200 Subject: [PATCH 0278/1751] TOF CalibInfo reader in (#4087) * TOF CalibInfo reader in * cleanup of printf --- .../tofworkflow/CMakeLists.txt | 6 ++ .../include/TOFWorkflow/CalibInfoReaderSpec.h | 55 ++++++++++++ .../tofworkflow/src/CalibInfoReaderSpec.cxx | 88 +++++++++++++++++++ .../tofworkflow/src/tof-calibinfo-reader.cxx | 82 +++++++++++++++++ Detectors/TOF/base/src/WindowFiller.cxx | 5 -- .../include/TOFReconstruction/Clusterer.h | 1 - Detectors/TOF/reconstruction/src/Decoder.cxx | 1 - Detectors/TOF/simulation/src/Digitizer.cxx | 7 +- 8 files changed, 236 insertions(+), 9 deletions(-) create mode 100644 Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt index bba7096226851..5e52105e0ff0f 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt @@ -13,6 +13,7 @@ o2_add_library(TOFWorkflow src/TOFMatchedWriterSpec.cxx src/TOFCalibWriterSpec.cxx src/TOFMatchedReaderSpec.cxx + src/CalibInfoReaderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction O2::GlobalTracking O2::GlobalTrackingWorkflow O2::TOFWorkflowUtils O2::TOFCalibration O2::DataFormatsFT0 O2::FT0Reconstruction O2::FT0Workflow) @@ -21,3 +22,8 @@ o2_add_executable(reco-workflow COMPONENT_NAME tof SOURCES src/tof-reco-workflow.cxx PUBLIC_LINK_LIBRARIES O2::TOFWorkflow) + +o2_add_executable(calib-reader + COMPONENT_NAME tof + SOURCES src/tof-calibinfo-reader.cxx + PUBLIC_LINK_LIBRARIES O2::TOFWorkflow) diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h new file mode 100644 index 0000000000000..b0c8f2562ce36 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h @@ -0,0 +1,55 @@ +// 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 CalibInfoReaderSpec.h + +#ifndef O2_TOF_CALIBINFOREADER +#define O2_TOF_CALIBINFOREADER + +#include "TFile.h" + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "DataFormatsTOF/CalibInfoTOF.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +class CalibInfoReader : public Task +{ + public: + CalibInfoReader(int instance, int ninstances, const char* filename) : mInstance(instance), mNinstances(ninstances), mFileName(filename) {} + ~CalibInfoReader() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + + private: + int mState = 0; + int mInstance; + int mNinstances; + const char* mFileName = nullptr; + FILE* mFile = nullptr; + int mCurrentEntry = 0; + int mGlobalEntry = 0; + std::vector<o2::dataformats::CalibInfoTOF> mVect, *mPvect = &mVect; +}; + +/// create a processor spec +/// read simulated TOF digits from a root file +framework::DataProcessorSpec getCalibInfoReaderSpec(int instance, int ninstances, const char* filename); + +} // namespace tof +} // namespace o2 + +#endif /* O2_TOF_CALIBINFOREADER */ diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx new file mode 100644 index 0000000000000..30881cab806fc --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx @@ -0,0 +1,88 @@ +// 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 DigitReaderSpec.cxx + +#include <vector> + +#include "TChain.h" +#include "TTree.h" + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "TOFWorkflow/CalibInfoReaderSpec.h" + +using namespace o2::framework; +using namespace o2::tof; + +namespace o2 +{ +namespace tof +{ + +void CalibInfoReader::init(InitContext& ic) +{ + LOG(INFO) << "Init CalibInfo reader!"; + mFile = fopen(mFileName, "r"); + if (!mFile) { + LOG(ERROR) << "Cannot open the " << mFileName << " file !"; + mState = 0; + return; + } + mState = 1; +} + +void CalibInfoReader::run(ProcessingContext& pc) +{ + if (mState != 1) { + return; + } + + char filename[100]; + int ientry = 0; + while (fscanf(mFile, "%s", filename) == 1) { + TFile* fin = TFile::Open(filename); + TTree* tin = (TTree*)fin->Get("calibTOF"); + tin->SetBranchAddress("TOFCalibInfo", &mPvect); + for (int i = 0; i < tin->GetEntries(); i += mNinstances) { + if ((ientry % mNinstances) == mInstance) { + tin->GetEvent(i); + LOG(INFO) << "Send " << mVect.size() << " calib infos"; + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CALIBINFOS", 0, Lifetime::Timeframe}, mVect); + } + ientry++; + } + } + + mState = 2; + pc.services().get<ControlService>().endOfStream(); + return; +} + +DataProcessorSpec getCalibInfoReaderSpec(int instance, int ninstances, const char* filename) +{ + std::vector<OutputSpec> outputs; + outputs.emplace_back(o2::header::gDataOriginTOF, "CALIBINFOS", 0, Lifetime::Timeframe); + + const char* nameSpec; + if (ninstances == 1) + nameSpec = "tof-calibinfo-reader"; + else + nameSpec = Form("tof-calibinfo-reader-%d", instance); + + return DataProcessorSpec{ + nameSpec, + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask<CalibInfoReader>(instance, ninstances, filename)}, + Options{/* for the moment no options */}}; +} +} // namespace tof +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx new file mode 100644 index 0000000000000..586573be21b2a --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx @@ -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 tof-reco-workflow.cxx +/// @author Francesco Noferini +/// @since 2019-05-22 +/// @brief Basic DPL workflow for TOF reconstruction starting from digits + +#include "DetectorsBase/Propagator.h" +#include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" +#include "TOFWorkflow/CalibInfoReaderSpec.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/ConfigParamSpec.h" +#include "TOFWorkflow/RecoWorkflowSpec.h" +#include "Algorithm/RangeTokenizer.h" +#include "FairLogger.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" + +#include <string> +#include <stdexcept> +#include <unordered_map> + +// add workflow options, note that customization needs to be declared before +// including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{"collection-infile", o2::framework::VariantType::String, "list-calibfile", {"Name of the collection input file"}}); + workflowOptions.push_back(ConfigParamSpec{"ninstances", o2::framework::VariantType::Int, 1, {"Number of reader instances"}}); + workflowOptions.push_back(ConfigParamSpec{"configKeyValues", o2::framework::VariantType::String, "", {"Semicolon separated key=value strings ..."}}); +} + +#include "Framework/runDataProcessing.h" // the main driver + +using namespace o2::framework; + +/// The workflow executable for the stand alone TOF reconstruction workflow +/// The basic workflow for TOF reconstruction is defined in RecoWorkflow.cxx +/// and contains the following default processors +/// - digit reader +/// - clusterer +/// - cluster raw decoder +/// - track-TOF matcher +/// +/// The default workflow can be customized by specifying input and output types +/// e.g. digits, raw, clusters. +/// +/// MC info is processed by default, disabled by using command line option `--disable-mc` +/// +/// This function hooks up the the workflow specifications into the DPL driver. +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec specs; + + if (!cfgc.helpOnCommandLine()) { + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + } + + int ninstances = cfgc.options().get<int>("ninstances"); + auto listname = cfgc.options().get<std::string>("collection-infile"); + + char* stringTBP = new char[listname.size()]; + sprintf(stringTBP, "%s", listname.c_str()); + + // the lane configuration defines the subspecification ids to be distributed among the lanes. + // auto tofSectors = o2::RangeTokenizer::tokenize<int>(cfgc.options().get<std::string>("tof-sectors")); + // std::vector<int> laneConfiguration = tofSectors; + + for (int i = 0; i < ninstances; i++) + specs.emplace_back(o2::tof::getCalibInfoReaderSpec(i, ninstances, stringTBP)); + + LOG(INFO) << "Number of active devices = " << specs.size(); + + return std::move(specs); +} diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index 9daeabf8368f5..ff357c69caeaa 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -149,17 +149,12 @@ void WindowFiller::flushOutputContainer(std::vector<Digit>& digits) { // flush all residual buffered data // TO be implemented - printf("flushOutputContainer\n"); for (Int_t i = 0; i < MAXWINDOWS; i++) { int n = 0; for (int j = 0; j < mStrips[i].size(); j++) n += ((mStrips[i])[j]).getNumberOfDigits(); - - printf("ro #%d: digits = %d\n", i, n); } - printf("Future digits = %lu\n", mFutureDigits.size()); - checkIfReuseFutureDigitsRO(); if (!mContinuous) diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h index 7c0d68e92cf72..11dad2d0dfa19 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h @@ -49,7 +49,6 @@ class Clusterer void setCalibApi(CalibApi* calibApi) { mCalibApi = calibApi; - Printf("mCalibApi = %p", mCalibApi); } void setFirstOrbit(uint32_t orb); diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index dd1ac880e1de7..11fed56cee81b 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -305,7 +305,6 @@ void Decoder::FillWindows() { std::vector<Digit> digTemp; flushOutputContainer(digTemp); - printf("hit decoded = %d (digits not filled = %lu)\n", mHitDecoded, mFutureDigits.size()); } void Decoder::printCrateInfo(int icru) const diff --git a/Detectors/TOF/simulation/src/Digitizer.cxx b/Detectors/TOF/simulation/src/Digitizer.cxx index 14ce608fecf98..a778f27b6d4c5 100644 --- a/Detectors/TOF/simulation/src/Digitizer.cxx +++ b/Detectors/TOF/simulation/src/Digitizer.cxx @@ -245,7 +245,11 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, time = getDigitTimeSmeared(time, x, z, charge); // add time smearing charge *= getFractionOfCharge(x, z); - Float_t tot = 12; // time-over-threshold + + // tot tuned to reproduce 0.8% of orphans tot(=0) + Float_t tot = gRandom->Gaus(12., 1.5); // time-over-threshold + if (tot < 8.4) + tot = 0; Float_t xborder = Geo::XPAD * 0.5 - TMath::Abs(x); Float_t zborder = Geo::ZPAD * 0.5 - TMath::Abs(z); @@ -826,7 +830,6 @@ void Digitizer::fillOutputContainer(std::vector<Digit>& digits) void Digitizer::flushOutputContainer(std::vector<Digit>& digits) { // flush all residual buffered data // TO be implemented - printf("flushOutputContainer\n"); if (!mContinuous) fillOutputContainer(digits); else { From 6e3234dba46689f667b2ee785deb68ab88da4ac8 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 6 Aug 2020 10:49:49 +0200 Subject: [PATCH 0279/1751] TPC workflow: avoid leak in callback registry and ensure cleanup of processAttributes --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index e52c196ccd563..536aab8a8cf98 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -200,7 +200,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } auto& callbacks = ic.services().get<CallbackService>(); - callbacks.set(CallbackService::Id::RegionInfoCallback, [processAttributes](FairMQRegionInfo const& info) { + callbacks.set(CallbackService::Id::RegionInfoCallback, [&processAttributes](FairMQRegionInfo const& info) { if (info.size) { auto& tracker = processAttributes->tracker; if (tracker->registerMemoryForGPU(info.ptr, info.size)) { From bd9d79e3c167296c65f5c3e392bd47a1dd119120 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 6 Aug 2020 10:49:59 +0200 Subject: [PATCH 0280/1751] GPU: Minor fixes --- Detectors/TPC/workflow/src/tpc-reco-workflow.cxx | 4 ++-- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index 3f2635ea5a0f0..fb8ce7de652fd 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -49,7 +49,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) {"tpc-sectors", VariantType::String, "0-35", {"TPC sector range, e.g. 5-7,8,9"}}, {"tpc-lanes", VariantType::Int, 1, {"number of parallel lanes up to the tracker"}}, {"dispatching-mode", VariantType::String, "prompt", {"determines when to dispatch: prompt, complete"}}, - {"tpc-zs", VariantType::Bool, false, {"use TPC zero suppression, true/false"}}, + {"tpc-zs-on-the-fly", VariantType::Bool, false, {"use TPC zero suppression on the fly, true/false"}}, {"zs-threshold", VariantType::Float, 2.0f, {"zero suppression threshold"}}, {"zs-10bit", VariantType::Bool, false, {"use 10 bit ADCs for TPC zero suppression, true/false, default/false = 12 bit ADC"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings (e.g.: 'TPCHwClusterer.peakChargeThreshold=4;...')"}}, @@ -146,7 +146,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) inputType, // cfgc.options().get<std::string>("output-type"), // cfgc.options().get<bool>("ca-clusterer"), // - cfgc.options().get<bool>("tpc-zs"), // + cfgc.options().get<bool>("tpc-zs-on-the-fly"), // cfgc.options().get<bool>("zs-10bit"), // cfgc.options().get<float>("zs-threshold") // ); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index f094928f3327d..1f99d2305fe9d 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -424,8 +424,7 @@ int GPUQA::InitQA() std::vector<o2::MCTrack>* tracksX; std::vector<o2::TrackReference>* trackRefsX; if (treeSim == nullptr) { - GPUError("Error reading o2sim tree"); - exit(1); + throw std::runtime_error("Error reading o2sim tree"); } treeSim->SetBranchAddress("MCTrack", &tracksX); treeSim->SetBranchAddress("TrackRefs", &trackRefsX); From 689e34a08b4bf2b89ed0067d9a5c9f511e6c8d44 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 6 Aug 2020 16:53:57 +0200 Subject: [PATCH 0281/1751] Use the random seed from gRandom as default for Pythia8 --- Generators/src/GeneratorFactory.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index d532ff0022896..bb225f2fed689 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -34,6 +34,8 @@ #include <Generators/TriggerParticleParam.h> #include "Generators/ConfigurationMacroHelper.h" +#include "TRandom.h" + namespace o2 { namespace eventgen @@ -68,6 +70,10 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair gen->setConfig(param.config); gen->setHooksFileName(param.hooksFileName); gen->setHooksFuncName(param.hooksFuncName); + auto seed = (gRandom->GetSeed() % 900000000); + LOG(INFO) << "Using random seed from gRandom % 900000000: " << seed; + gen->readString("Random:setSeed on"); + gen->readString("Random:seed " + std::to_string(seed)); return gen; }; #endif From 4b3119eac203271405a609447a52e6826091b81c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 6 Aug 2020 16:59:49 +0200 Subject: [PATCH 0282/1751] o2sim: Better init parameters in event server --- run/O2PrimaryServerDevice.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/run/O2PrimaryServerDevice.h b/run/O2PrimaryServerDevice.h index 0b5178f7512eb..7e1c34326e1c4 100644 --- a/run/O2PrimaryServerDevice.h +++ b/run/O2PrimaryServerDevice.h @@ -60,7 +60,6 @@ class O2PrimaryServerDevice : public FairMQDevice TStopwatch timer; timer.Start(); auto& conf = o2::conf::SimConfig::Instance(); - o2::conf::ConfigurableParam::updateFromString(conf.getKeyValueString()); o2::eventgen::GeneratorFactory::setPrimaryGenerator(conf, &mPrimGen); mPrimGen.SetEvent(&mEventHeader); @@ -96,6 +95,11 @@ class O2PrimaryServerDevice : public FairMQDevice for (auto& keyvalue : vm) { LOG(INFO) << "///// " << keyvalue.first << " " << keyvalue.second.value().type().name(); } + // update the parameters from an INI/JSON file, if given (overrides code-based version) + o2::conf::ConfigurableParam::updateFromFile(conf.getConfigFile()); + // update the parameters from stuff given at command line (overrides file-based version) + o2::conf::ConfigurableParam::updateFromString(conf.getKeyValueString()); + // MC ENGINE LOG(INFO) << "ENGINE SET TO " << vm["mcEngine"].as<std::string>(); // CHUNK SIZE From 98fad32eba32f00102d2da6f2b3ce20cadd2e28f Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 6 Aug 2020 17:55:31 +0200 Subject: [PATCH 0283/1751] ConfParam: Use numeric interpretation for char/unsigned char So far, for char parameters, assignment from string used generic boost::lexical_cast. This cast however, interpreted that right hand side as a character literal rather than an integer number. We now specialize the assignment code and always interpret the right hand side as a number. --- Common/Utils/src/ConfigurableParam.cxx | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Common/Utils/src/ConfigurableParam.cxx b/Common/Utils/src/ConfigurableParam.cxx index 0f8580360f688..73d32880ac5f0 100644 --- a/Common/Utils/src/ConfigurableParam.cxx +++ b/Common/Utils/src/ConfigurableParam.cxx @@ -20,6 +20,7 @@ #include <boost/lexical_cast.hpp> #include <algorithm> #include <array> +#include <limits> #ifdef NDEBUG #undef NDEBUG #endif @@ -747,6 +748,38 @@ bool ConvertAndCopy<std::string>(std::string const& valuestring, void* targetadd } return false; } +// special version for char and unsigned char since we are interested in the numeric +// meaning of char as an 8-bit integer (boost lexical cast is assigning the string as a character i// nterpretation +template <> +bool ConvertAndCopy<char>(std::string const& valuestring, void* targetaddr) +{ + int intvalue = boost::lexical_cast<int>(valuestring); + if (intvalue > std::numeric_limits<char>::max() || intvalue < std::numeric_limits<char>::min()) { + LOG(ERROR) << "Cannot assign " << valuestring << " to a char variable"; + return false; + } + char addr = intvalue; + if (isMemblockDifferent<char>(targetaddr, (void*)&addr)) { + std::memcpy(targetaddr, (void*)&addr, sizeof(char)); + return true; + } + return false; +} +template <> +bool ConvertAndCopy<unsigned char>(std::string const& valuestring, void* targetaddr) +{ + unsigned int intvalue = boost::lexical_cast<int>(valuestring); + if (intvalue > std::numeric_limits<unsigned char>::max() || intvalue < std::numeric_limits<unsigned char>::min()) { + LOG(ERROR) << "Cannot assign " << valuestring << " to an unsigned char variable"; + return false; + } + unsigned char addr = intvalue; + if (isMemblockDifferent<unsigned char>(targetaddr, (void*)&addr)) { + std::memcpy(targetaddr, (void*)&addr, sizeof(unsigned char)); + return true; + } + return false; +} bool ConfigurableParam::updateThroughStorageMapWithConversion(std::string const& key, std::string const& valuestring) { From e372cb2092e92e4f3da43e4a2e6d55fc5ae22de6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 7 Aug 2020 09:22:27 +0200 Subject: [PATCH 0284/1751] Reduce verbosity --- Detectors/Base/src/GeometryManager.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/Base/src/GeometryManager.cxx b/Detectors/Base/src/GeometryManager.cxx index cb3b6537c4498..646b70cacec6e 100644 --- a/Detectors/Base/src/GeometryManager.cxx +++ b/Detectors/Base/src/GeometryManager.cxx @@ -322,7 +322,7 @@ GeometryManager::MatBudgetExt GeometryManager::meanMaterialBudgetExt(float x0, f // This means navigation has problems on one boundary // Try to cross by making a small step const double* curPos = gGeoManager->GetCurrentPoint(); - LOG(ERROR) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')'; + LOG(warning) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')'; budTotal.normalize(stepTot); budTotal.nCross = -1; // flag failed navigation return MatBudgetExt(budTotal); @@ -414,7 +414,7 @@ o2::base::MatBudget GeometryManager::meanMaterialBudget(float x0, float y0, floa // This means navigation has problems on one boundary // Try to cross by making a small step const double* curPos = gGeoManager->GetCurrentPoint(); - LOG(ERROR) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')'; + LOG(warning) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')'; budTotal.meanRho /= stepTot; budTotal.length = stepTot; return o2::base::MatBudget(budTotal); From 48b944645bb7c8accc31996e024c3a2985ad08c0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 7 Aug 2020 09:30:52 +0200 Subject: [PATCH 0285/1751] Fix logging to stdout --- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 8cf34c580d73c..593291f0c2436 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -251,7 +251,7 @@ void MatchTPCITS::run() ProcInfo_t procInfoStart, procInfoStop; gSystem->GetProcInfo(&procInfoStart); constexpr uint64_t kMB = 1024 * 1024; - printf("Memory (GB) at entrance: RSS: %.3f VMem: %.3f\n", float(procInfoStart.fMemResident) / kMB, float(procInfoStart.fMemVirtual) / kMB); + LOGF(info, "Memory (GB) at entrance: RSS: %.3f VMem: %.3f\n", float(procInfoStart.fMemResident) / kMB, float(procInfoStart.fMemVirtual) / kMB); mTimer[SWTot].Start(false); From a3eb2d1ee83416f8ad5f5c5f08d3298ed289a318 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 7 Aug 2020 09:22:55 +0200 Subject: [PATCH 0286/1751] DPL: Make sure forceful exit message is printed only once --- Framework/Core/src/runDataProcessing.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 8974b8b5250af..2407e0c528cc2 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1128,7 +1128,11 @@ int runStateMachine(DataProcessorSpecs const& workflow, // I allow queueing of more sigchld only when // I process the previous call if (forceful_exit == true) { - LOG(INFO) << "Forceful exit requested."; + static bool forcefulExitMessage = true; + if (forcefulExitMessage) { + LOG(INFO) << "Forceful exit requested."; + forcefulExitMessage = false; + } killChildren(infos, SIGCONT); killChildren(infos, SIGKILL); } From 2cc9d09994542944c6a9ffa8fe83cf47020b8d3f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 6 Aug 2020 17:38:52 +0200 Subject: [PATCH 0287/1751] DPL: Forward some more FairMQ SHM command line arguments --- Framework/Core/src/DeviceSpecHelpers.cxx | 4 ++++ Framework/Core/test/test_FrameworkDataFlowToDDS.cxx | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 3062f4467b1b6..3d9d98319d2ff 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -939,6 +939,8 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, realOdesc.add_options()("post-fork-command", bpo::value<std::string>()); realOdesc.add_options()("shm-segment-size", bpo::value<std::string>()); realOdesc.add_options()("shm-mlock-segment", bpo::value<std::string>()); + realOdesc.add_options()("shm-zero-segment", bpo::value<std::string>()); + realOdesc.add_options()("shm-throw-bad-alloc", bpo::value<std::string>()); realOdesc.add_options()("shm-monitor", bpo::value<std::string>()); realOdesc.add_options()("session", bpo::value<std::string>()); filterArgsFct(expansions.we_wordc, expansions.we_wordv, realOdesc); @@ -1052,6 +1054,8 @@ boost::program_options::options_description DeviceSpecHelpers::getForwardedDevic ("shm-monitor", bpo::value<std::string>(), "whether to use the shared memory monitor") // ("shm-segment-size", bpo::value<std::string>(), "size of the shared memory segment in bytes") // ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // + ("shm-zero-segment", bpo::value<std::string>()->default_value("false"), "zero shared memory segment") // + ("shm-throw-bad-alloc", bpo::value<std::string>()->default_value("true"), "throw if insufficient shm memory") // ("environment", bpo::value<std::string>(), "comma separated list of environment variables to set for the device") // ("post-fork-command", bpo::value<std::string>(), "post fork command to execute (e.g. numactl {pid}") // ("session", bpo::value<std::string>(), "unique label for the shared memory session") // diff --git a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx index 908856fca1805..784adf5533015 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx @@ -97,16 +97,16 @@ BOOST_AUTO_TEST_CASE(TestDDS) dumpDeviceSpec2DDS(ss, devices, executions); BOOST_CHECK_EQUAL(ss.str(), R"EXPECTED(<topology name="o2-dataflow"> <decltask name="A"> - <exe reachable="true">foo --id A --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id A --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="B"> - <exe reachable="true">foo --id B --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id B --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="C"> - <exe reachable="true">foo --id C --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id C --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="D"> - <exe reachable="true">foo --id D --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id D --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <declcollection name="DPL"> <tasks> From b29679119b7bc7eda65796fe50499cb8732d99a2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 7 Aug 2020 14:51:43 +0200 Subject: [PATCH 0288/1751] Reset TPC Track interpolation output before processing --- Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index cc69d9cb61b56..d017015a4cfb9 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -49,6 +49,7 @@ void TrackInterpolation::process() LOG(error) << "Initialization not yet done. Aborting..."; return; } + reset(); #ifdef TPC_RUN2 // processing will not work if the run 2 geometry is defined in the parameter class SpacePointsCalibParam.h From 46283c64e6f06a4f91e5a100893691a12048adea Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Sat, 18 Jul 2020 23:15:54 +0000 Subject: [PATCH 0289/1751] Use basecluster on MFT cluster --- .../ReconstructionDataFormats/TrackFwd.h | 423 ++++++++++++++++++ .../tracking/include/MFTTracking/Cluster.h | 15 +- .../tracking/include/MFTTracking/TrackCA.h | 2 + .../include/MFTTracking/TrackParamMFT.h | 1 - .../tracking/include/MFTTracking/Tracker.h | 66 +-- Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx | 10 +- .../MFT/tracking/src/FitterTrackMFT.cxx | 10 +- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 1 - .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 32 +- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 30 +- 10 files changed, 505 insertions(+), 85 deletions(-) create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h new file mode 100644 index 0000000000000..4668aaf5d9e15 --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -0,0 +1,423 @@ +// 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 Track.h +/// \brief Base track model for the Barrel, params only, w/o covariance +/// \author ruben.shahoyan@cern.ch + +#ifndef ALICEO2_BASE_TRACKFWD +#define ALICEO2_BASE_TRACKFWD + + +namespace o2 +{ +template <typename T> +class BaseCluster; + +namespace dataformats +{ +class VertexBase; +class DCA; +} // namespace dataformats + +namespace track +{ +// aliases for track elements +enum ParLabels : int { kY, + kZ, + kSnp, + kTgl, + kQ2Pt }; +enum CovLabels : int { + kSigY2, + kSigZY, + kSigZ2, + kSigSnpY, + kSigSnpZ, + kSigSnp2, + kSigTglY, + kSigTglZ, + kSigTglSnp, + kSigTgl2, + kSigQ2PtY, + kSigQ2PtZ, + kSigQ2PtSnp, + kSigQ2PtTgl, + kSigQ2Pt2 +}; + +enum DirType : int { DirInward = -1, + DirAuto = 0, + DirOutward = 1 }; + +constexpr int kNParams = 5, kCovMatSize = 15, kLabCovMatSize = 21; + +constexpr float kCY2max = 100 * 100, // SigmaY<=100cm + kCZ2max = 100 * 100, // SigmaZ<=100cm + kCSnp2max = 1 * 1, // SigmaSin<=1 + kCTgl2max = 1 * 1, // SigmaTan<=1 + kC1Pt2max = 100 * 100, // Sigma1/Pt<=100 1/GeV + kMostProbablePt = 0.6, // Most Probable Pt (GeV), for running with Bz=0 + kCalcdEdxAuto = -999.f; // value indicating request for dedx calculation + +// access to covariance matrix by row and column +constexpr int CovarMap[kNParams][kNParams] = {{0, 1, 3, 6, 10}, + {1, 2, 4, 7, 11}, + {3, 4, 5, 8, 12}, + {6, 7, 8, 9, 13}, + {10, 11, 12, 13, 14}}; + +// access to covariance matrix diagonal elements +constexpr int DiagMap[kNParams] = {0, 2, 5, 9, 14}; + +constexpr float HugeF = o2::constants::math::VeryBig; + +// helper function +float BetheBlochSolid(float bg, float rho = 2.33f, float kp1 = 0.20f, float kp2 = 3.00f, float meanI = 173e-9f, + float meanZA = 0.49848f); +void g3helx3(float qfield, float step, std::array<float, 7>& vect); + +class TrackPar +{ // track parameterization, kinematics only. + public: + TrackPar() = default; + TrackPar(float x, float alpha, const std::array<float, kNParams>& par); + TrackPar(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, int sign, bool sectorAlpha = true); + TrackPar(const TrackPar&) = default; + TrackPar& operator=(const TrackPar& src) = default; + ~TrackPar() = default; + + const float* getParams() const { return mP; } + float getParam(int i) const { return mP[i]; } + float getX() const { return mX; } + float getAlpha() const { return mAlpha; } + float getY() const { return mP[kY]; } + float getZ() const { return mP[kZ]; } + float getSnp() const { return mP[kSnp]; } + float getTgl() const { return mP[kTgl]; } + float getQ2Pt() const { return mP[kQ2Pt]; } + + /// calculate cos^2 and cos of track direction in rphi-tracking + float getCsp2() const + { + float csp2 = (1. - mP[kSnp]) * (1. + mP[kSnp]); + return csp2 > o2::constants::math::Almost0 ? csp2 : o2::constants::math::Almost0; + } + float getCsp() const { return sqrtf(getCsp2()); } + + void setX(float v) { mX = v; } + void setParam(float v, int i) { mP[i] = v; } + void setAlpha(float v) { mAlpha = v; } + void setY(float v) { mP[kY] = v; } + void setZ(float v) { mP[kZ] = v; } + void setSnp(float v) { mP[kSnp] = v; } + void setTgl(float v) { mP[kTgl] = v; } + void setQ2Pt(float v) { mP[kQ2Pt] = v; } + + // derived getters + bool getXatLabR(float r, float& x, float bz, DirType dir = DirAuto) const; + void getCircleParamsLoc(float bz, o2::utils::CircleXY& circle) const; + void getCircleParams(float bz, o2::utils::CircleXY& circle, float& sna, float& csa) const; + void getLineParams(o2::utils::IntervalXY& line, float& sna, float& csa) const; + float getCurvature(float b) const { return mP[kQ2Pt] * b * o2::constants::math::B2C; } + float getSign() const { return mP[kQ2Pt] > 0 ? 1.f : -1.f; } + float getPhi() const; + float getPhiPos() const; + + float getP2Inv() const; + float getP2() const; + float getPInv() const; + float getP() const; + float getPt() const; + + float getTheta() const { return constants::math::PIHalf - std::atan(mP[3]); } + float getEta() const { return -std::log(std::tan(0.5 * getTheta())); } + Point3D<float> getXYZGlo() const; + void getXYZGlo(std::array<float, 3>& xyz) const; + bool getPxPyPzGlo(std::array<float, 3>& pxyz) const; + bool getPosDirGlo(std::array<float, 9>& posdirp) const; + + // methods for track params estimate at other point + bool getYZAt(float xk, float b, float& y, float& z) const; + float getZAt(float xk, float b) const; + float getYAt(float xk, float b) const; + Point3D<float> getXYZGloAt(float xk, float b, bool& ok) const; + + // parameters manipulation + bool correctForELoss(float xrho, float mass, bool anglecorr = false, float dedx = kCalcdEdxAuto); + bool rotateParam(float alpha); + bool propagateParamTo(float xk, float b); + bool propagateParamTo(float xk, const std::array<float, 3>& b); + + bool propagateParamToDCA(const Point3D<float>& vtx, float b, std::array<float, 2>* dca = nullptr, float maxD = 999.f); + + void invertParam(); + +#ifndef GPUCA_ALIGPUCODE + void printParam() const; + std::string asString() const; +#endif + + protected: + void updateParam(float delta, int i) { mP[i] += delta; } + void updateParams(const float delta[kNParams]) + { + for (int i = kNParams; i--;) { + mP[i] += delta[i]; + } + } + // derived getters + + private: + // + 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 + + ClassDefNV(TrackPar, 1); +}; + +class TrackParCov : public TrackPar +{ // track+error parameterization + using MatrixDSym5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepSym<double, kNParams>>; + using MatrixD5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepStd<double, kNParams, kNParams>>; + + public: + TrackParCov() : TrackPar{} {} + TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, const std::array<float, kCovMatSize>& cov); + TrackParCov(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, + const std::array<float, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); + TrackParCov(const TrackParCov& src) = default; + TrackParCov& operator=(const TrackParCov& src) = default; + ~TrackParCov() = default; + + const float* getCov() const { return mC; } + float getSigmaY2() const { return mC[kSigY2]; } + float getSigmaZY() const { return mC[kSigZY]; } + float getSigmaZ2() const { return mC[kSigZ2]; } + float getSigmaSnpY() const { return mC[kSigSnpY]; } + float getSigmaSnpZ() const { return mC[kSigSnpZ]; } + float getSigmaSnp2() const { return mC[kSigSnp2]; } + float getSigmaTglY() const { return mC[kSigTglY]; } + float getSigmaTglZ() const { return mC[kSigTglZ]; } + float getSigmaTglSnp() const { return mC[kSigTglSnp]; } + float getSigmaTgl2() const { return mC[kSigTgl2]; } + float getSigma1PtY() const { return mC[kSigQ2PtY]; } + float getSigma1PtZ() const { return mC[kSigQ2PtZ]; } + float getSigma1PtSnp() const { return mC[kSigQ2PtSnp]; } + float getSigma1PtTgl() const { return mC[kSigQ2PtTgl]; } + float getSigma1Pt2() const { return mC[kSigQ2Pt2]; } + float getCovarElem(int i, int j) const { return mC[CovarMap[i][j]]; } + float getDiagError2(int i) const { return mC[DiagMap[i]]; } + +#ifndef GPUCA_ALIGPUCODE + void print() const; + std::string asString() const; +#endif + + // parameters + covmat manipulation + bool rotate(float alpha); + bool propagateTo(float xk, float b); + bool propagateTo(float xk, const std::array<float, 3>& b); + bool propagateToDCA(const o2::dataformats::VertexBase& vtx, float b, o2::dataformats::DCA* dca = nullptr, float maxD = 999.f); + void invert(); + + float getPredictedChi2(const std::array<float, 2>& p, const std::array<float, 3>& cov) const; + + template <typename T> + float getPredictedChi2(const BaseCluster<T>& p) const + { + const std::array<float, 2> pyz = {p.getY(), p.getZ()}; + const std::array<float, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; + return getPredictedChi2(pyz, cov); + } + + float getPredictedChi2(const TrackParCov& rhs) const; + + void buildCombinedCovMatrix(const TrackParCov& rhs, MatrixDSym5& cov) const; + float getPredictedChi2(const TrackParCov& rhs, MatrixDSym5& covToSet) const; + bool update(const TrackParCov& rhs, const MatrixDSym5& covInv); + + bool update(const std::array<float, 2>& p, const std::array<float, 3>& cov); + + template <typename T> + bool update(const BaseCluster<T>& p) + { + const std::array<float, 2> pyz = {p.getY(), p.getZ()}; + const std::array<float, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; + return update(pyz, cov); + } + + bool update(const TrackParCov& rhs); + + bool correctForMaterial(float x2x0, float xrho, float mass, bool anglecorr = false, float dedx = kCalcdEdxAuto); + + void resetCovariance(float s2 = 0); + void checkCovariance(); + void setCov(float v, int i) { mC[i] = v; } + + protected: + void updateCov(const float delta[kCovMatSize]) + { + for (int i = kCovMatSize; i--;) + mC[i] += delta[i]; + } + + protected: + float mC[kCovMatSize] = {0.f}; // 15 covariance matrix elements + + ClassDefNV(TrackParCov, 1); +}; + +//____________________________________________________________ +inline TrackPar::TrackPar(float x, float alpha, const std::array<float, kNParams>& par) : mX{x}, mAlpha{alpha} +{ + // explicit constructor + std::copy(par.begin(), par.end(), mP); +} + +//_______________________________________________________ +inline void TrackPar::getLineParams(o2::utils::IntervalXY& ln, float& sna, float& csa) const +{ + // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } + o2::utils::sincos(getAlpha(), sna, csa); + o2::utils::rotateZ(getX(), getY(), ln.xP, ln.yP, sna, csa); // reference point in global frame + float snp = getSnp(), csp = sqrtf((1.f - snp) * (1.f + snp)); + ln.dxP = csp * csa - snp * sna; + ln.dyP = snp * csa + csp * sna; +} + +//_______________________________________________________ +inline void TrackPar::getCircleParams(float bz, o2::utils::CircleXY& c, float& sna, float& csa) const +{ + // get circle params in loc and lab frame, for straight line just set to global coordinates + getCircleParamsLoc(bz, c); + o2::utils::sincos(getAlpha(), sna, csa); + o2::utils::rotateZ(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame +} + +//_______________________________________________________ +inline void TrackPar::getCircleParamsLoc(float bz, o2::utils::CircleXY& c) const +{ + // get circle params in track local frame, for straight line just set to local coordinates + c.rC = getCurvature(bz); + if (std::abs(c.rC) > o2::constants::math::Almost0) { + c.rC = 1.f / getCurvature(bz); + float sn = getSnp(), cs = sqrtf((1. - sn) * (1. + sn)); + c.xC = getX() - sn * c.rC; // center in tracking + c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!! + c.rC = fabs(c.rC); + } else { + c.rC = 0.f; // signal straight line + c.xC = getX(); + c.yC = getY(); + } +} + +//_______________________________________________________ +inline void TrackPar::getXYZGlo(std::array<float, 3>& xyz) const +{ + // track coordinates in lab frame + xyz[0] = getX(); + xyz[1] = getY(); + xyz[2] = getZ(); + utils::RotateZ(xyz, getAlpha()); +} + +//_______________________________________________________ +inline float TrackPar::getPhi() const +{ + // track pt direction phi (in 0:2pi range) + float phi = asinf(getSnp()) + getAlpha(); + utils::BringTo02Pi(phi); + return phi; +} + +#ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden +//_______________________________________________________ +inline Point3D<float> TrackPar::getXYZGlo() const +{ + return Rotation2D(getAlpha())(Point3D<float>(getX(), getY(), getZ())); +} + +//_______________________________________________________ +inline Point3D<float> TrackPar::getXYZGloAt(float xk, float b, bool& ok) const +{ + //---------------------------------------------------------------- + // estimate global X,Y,Z in global frame at given X + //---------------------------------------------------------------- + float y = 0.f, z = 0.f; + ok = getYZAt(xk, b, y, z); + return ok ? Rotation2D(getAlpha())(Point3D<float>(xk, y, z)) : Point3D<float>(); +} +#endif + +//_______________________________________________________ +inline float TrackPar::getPhiPos() const +{ + // angle of track position (in -pi:pi range) + float phi = atan2f(getY(), getX()) + getAlpha(); + utils::BringTo02Pi(phi); + return phi; +} + +//____________________________________________________________ +inline float TrackPar::getP2Inv() const +{ + // return the inverted track momentum^2 + return getQ2Pt() * getQ2Pt() / (1.f + getTgl() * getTgl()); +} + +//____________________________________________________________ +inline float TrackPar::getPInv() const +{ + // return the inverted track momentum^2 + return fabs(getQ2Pt()) / sqrtf(1.f + getTgl() * getTgl()); +} + +//____________________________________________________________ +inline float TrackPar::getP2() const +{ + // return the track momentum^2 + auto p2inv = getP2Inv(); + return (p2inv > o2::constants::math::Almost0) ? 1. / p2inv : o2::constants::math::VeryBig; +} + +//____________________________________________________________ +inline float TrackPar::getP() const +{ + // return the track momentum + float pInv = getPInv(); + return (pInv > o2::constants::math::Almost0) ? 1. / pInv : o2::constants::math::VeryBig; +} + +//____________________________________________________________ +inline float TrackPar::getPt() const +{ + // return the track transverse momentum + float ptI = fabs(getQ2Pt()); + return (ptI > o2::constants::math::Almost0) ? 1.f / ptI : o2::constants::math::VeryBig; +} + +//============================================================ + +//____________________________________________________________ +inline TrackParCov::TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, + const std::array<float, kCovMatSize>& cov) + : TrackPar{x, alpha, par} +{ + // explicit constructor + std::copy(cov.begin(), cov.end(), mC); +} + +} // namespace track +} // namespace o2 + +#endif diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index 63bdaada3f836..a0c2d57fff211 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -16,9 +16,8 @@ #define O2_MFT_CLUSTER_H_ #include <array> - +#include "ReconstructionDataFormats/BaseCluster.h" #include "MFTTracking/IndexTableUtils.h" - #include "GPUCommonDef.h" namespace o2 @@ -26,11 +25,9 @@ namespace o2 namespace mft { -struct Cluster final { +struct Cluster : public o2::BaseCluster<float> { Cluster(const Float_t x, const Float_t y, const Float_t z, const Float_t phi, const Float_t r, const Int_t idx, const Int_t bin) - : xCoordinate{x}, - yCoordinate{y}, - zCoordinate{z}, + : BaseCluster(1 ,x, y, z), phiCoordinate{phi}, rCoordinate{r}, clusterId{idx}, @@ -38,9 +35,9 @@ struct Cluster final { Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t index); Cluster(const Int_t layerIndex, const Cluster& other); - Float_t xCoordinate; - Float_t yCoordinate; - Float_t zCoordinate; + //Float_t xCoordinate; + //Float_t yCoordinate; + //Float_t zCoordinate; Float_t phiCoordinate; Float_t rCoordinate; Int_t clusterId; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index e5295e831239e..c42fe5a0b3493 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -167,6 +167,8 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; } + LOG(INFO) << "MFT TrackLTF setPoint mNPoints = " << mNPoints << std::endl; + } } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h index 64c63a6076a81..7e41df9563a2b 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h @@ -19,7 +19,6 @@ #include <TMatrixD.h> #include <TMath.h> -#include "MFTBase/Constants.h" #include "MFTTracking/Cluster.h" namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 189b8ec2b79c5..d92bde4e7654c 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -108,13 +108,13 @@ inline const Float_t Tracker::getDistanceToSeed(const Cluster& cluster1, const C // the seed is between "cluster1" and "cluster2" and cuts the plane // of the "cluster" at a distance dR from it Float_t dxSeed, dySeed, dzSeed, dz, dR, xSeed, ySeed; - dxSeed = cluster2.xCoordinate - cluster1.xCoordinate; - dySeed = cluster2.yCoordinate - cluster1.yCoordinate; - dzSeed = cluster2.zCoordinate - cluster1.zCoordinate; - dz = cluster.zCoordinate - cluster1.zCoordinate; - xSeed = cluster1.xCoordinate + dxSeed * dz / dzSeed; - ySeed = cluster1.yCoordinate + dySeed * dz / dzSeed; - dR = std::sqrt((cluster.xCoordinate - xSeed) * (cluster.xCoordinate - xSeed) + (cluster.yCoordinate - ySeed) * (cluster.yCoordinate - ySeed)); + dxSeed = cluster2.getX() - cluster1.getX(); + dySeed = cluster2.getY() - cluster1.getY(); + dzSeed = cluster2.getZ() - cluster1.getZ(); + dz = cluster.getZ() - cluster1.getZ(); + xSeed = cluster1.getX() + dxSeed * dz / dzSeed; + ySeed = cluster1.getY() + dySeed * dz / dzSeed; + dR = std::sqrt((cluster.getX() - xSeed) * (cluster.getX() - xSeed) + (cluster.getY() - ySeed) * (cluster.getY() - ySeed)); return dR; } @@ -122,8 +122,8 @@ inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t l { Float_t dz, x_proj, y_proj, r_proj, phi_proj; dz = constants::mft::LayerZCoordinate()[layer] - constants::mft::LayerZCoordinate()[layer1]; - x_proj = cluster1.xCoordinate + dz * cluster1.xCoordinate * constants::mft::InverseLayerZCoordinate()[layer1]; - y_proj = cluster1.yCoordinate + dz * cluster1.yCoordinate * constants::mft::InverseLayerZCoordinate()[layer1]; + x_proj = cluster1.getX() + dz * cluster1.getX() * constants::mft::InverseLayerZCoordinate()[layer1]; + y_proj = cluster1.getY() + dz * cluster1.getY() * constants::mft::InverseLayerZCoordinate()[layer1]; auto clsPoint2D = Point2D<Float_t>(x_proj, y_proj); r_proj = clsPoint2D.R(); phi_proj = clsPoint2D.Phi(); @@ -170,21 +170,21 @@ inline const Float_t Tracker::getCellDeviation(const ROframe& event, const Cell& auto cluster21 = event.getClustersInLayer(cell2layer1)[cell2cls1]; auto cluster22 = event.getClustersInLayer(cell2layer2)[cell2cls2]; - Float_t cell1x1 = cluster11.xCoordinate; - Float_t cell1y1 = cluster11.yCoordinate; - Float_t cell1z1 = cluster11.zCoordinate; + Float_t cell1x1 = cluster11.getX(); + Float_t cell1y1 = cluster11.getY(); + Float_t cell1z1 = cluster11.getZ(); - Float_t cell1x2 = cluster12.xCoordinate; - Float_t cell1y2 = cluster12.yCoordinate; - Float_t cell1z2 = cluster12.zCoordinate; + Float_t cell1x2 = cluster12.getX(); + Float_t cell1y2 = cluster12.getY(); + Float_t cell1z2 = cluster12.getZ(); - Float_t cell2x1 = cluster21.xCoordinate; - Float_t cell2y1 = cluster21.yCoordinate; - Float_t cell2z1 = cluster21.zCoordinate; + Float_t cell2x1 = cluster21.getX(); + Float_t cell2y1 = cluster21.getY(); + Float_t cell2z1 = cluster21.getZ(); - Float_t cell2x2 = cluster22.xCoordinate; - Float_t cell2y2 = cluster22.yCoordinate; - Float_t cell2z2 = cluster22.zCoordinate; + Float_t cell2x2 = cluster22.getX(); + Float_t cell2y2 = cluster22.getY(); + Float_t cell2z2 = cluster22.getZ(); Float_t cell1dx = cell1x2 - cell1x1; Float_t cell1dy = cell1y2 - cell1y1; @@ -221,21 +221,21 @@ inline const Bool_t Tracker::getCellsConnect(const ROframe& event, const Cell& c auto cluster21 = event.getClustersInLayer(cell2layer1)[cell2cls1]; auto cluster22 = event.getClustersInLayer(cell2layer2)[cell2cls2]; - Float_t cell1x1 = cluster11.xCoordinate; - Float_t cell1y1 = cluster11.yCoordinate; - //Float_t cell1z1 = cluster11.zCoordinate; + Float_t cell1x1 = cluster11.getX(); + Float_t cell1y1 = cluster11.getY(); + //Float_t cell1z1 = cluster11.getZ(); - Float_t cell1x2 = cluster12.xCoordinate; - Float_t cell1y2 = cluster12.yCoordinate; - //Float_t cell1z2 = cluster12.zCoordinate; + Float_t cell1x2 = cluster12.getX(); + Float_t cell1y2 = cluster12.getY(); + //Float_t cell1z2 = cluster12.getZ(); - Float_t cell2x1 = cluster21.xCoordinate; - Float_t cell2y1 = cluster21.yCoordinate; - //Float_t cell2z1 = cluster21.zCoordinate; + Float_t cell2x1 = cluster21.getX(); + Float_t cell2y1 = cluster21.getY(); + //Float_t cell2z1 = cluster21.getZ(); - Float_t cell2x2 = cluster22.xCoordinate; - Float_t cell2y2 = cluster22.yCoordinate; - //Float_t cell2z2 = cluster22.zCoordinate; + Float_t cell2x2 = cluster22.getX(); + Float_t cell2y2 = cluster22.getY(); + //Float_t cell2z2 = cluster22.getZ(); Float_t cell1dx = cell1x2 - cell1x1; Float_t cell1dy = cell1y2 - cell1y1; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx index 244e7ea521f9f..6517f51489c88 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx @@ -23,9 +23,7 @@ namespace mft { Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t index) - : xCoordinate{x}, - yCoordinate{y}, - zCoordinate{z}, + : BaseCluster(1 , x, y, z), phiCoordinate{0.}, rCoordinate{0.}, clusterId{index}, @@ -38,16 +36,14 @@ Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t } Cluster::Cluster(const Int_t layerIndex, const Cluster& other) - : xCoordinate{other.xCoordinate}, - yCoordinate{other.yCoordinate}, - zCoordinate{other.zCoordinate}, + : BaseCluster(1 , other.getXYZ()), phiCoordinate{0.}, rCoordinate{0.}, clusterId{other.clusterId}, indexTableBin{index_table_utils::getBinIndex(index_table_utils::getRBinIndex(layerIndex, rCoordinate), index_table_utils::getPhiBinIndex(phiCoordinate))} { - auto clsPoint2D = Point2D<Float_t>(other.xCoordinate, other.yCoordinate); + auto clsPoint2D = Point2D<Float_t>(other.getX(), other.getY()); rCoordinate = clsPoint2D.R(); phiCoordinate = clsPoint2D.Phi(); o2::utils::BringTo02PiGen(phiCoordinate); diff --git a/Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx b/Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx index 47a83a4a17814..943325433547e 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx @@ -51,7 +51,7 @@ TrackParamMFT& FitterTrackMFT::createParamAtCluster(const Cluster& cluster) // find the iterator before which the new element will be constructed auto itParam = mParamAtClusters.begin(); for (; itParam != mParamAtClusters.end(); ++itParam) { - if (cluster.zCoordinate >= itParam->getZ()) { + if (cluster.getZ() >= itParam->getZ()) { break; } } @@ -59,9 +59,9 @@ TrackParamMFT& FitterTrackMFT::createParamAtCluster(const Cluster& cluster) // add the new track parameters mParamAtClusters.emplace(itParam); --itParam; - itParam->setX(cluster.xCoordinate); - itParam->setY(cluster.yCoordinate); - itParam->setZ(cluster.zCoordinate); + itParam->setX(cluster.getX()); + itParam->setY(cluster.getY()); + itParam->setZ(cluster.getZ()); itParam->setClusterPtr(&cluster); mNPoints++; return *itParam; @@ -83,7 +83,7 @@ void FitterTrackMFT::addParamAtCluster(const TrackParamMFT& param) // find the iterator before which the new element will be constructed auto itParam = mParamAtClusters.begin(); for (; itParam != mParamAtClusters.end(); ++itParam) { - if (cluster->zCoordinate >= itParam->getZ()) { + if (cluster->getZ() >= itParam->getZ()) { break; } } diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index 68dd0dd85bf82..cc3c2f932ddc7 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -45,7 +45,6 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g auto clusters_in_frame = rof.getROFData(clusters); for (auto& c : clusters_in_frame) { int layer = geom->getLayer(c.getSensorID()); - auto pattID = c.getPatternID(); Point3D<float> locXYZ; float sigmaY2 = ioutils::DefClusError2Row, sigmaZ2 = ioutils::DefClusError2Col, sigmaYZ = 0; //Dummy COG errors (about half pixel size) diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index a3d086d7a726d..17e3e84a51855 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -138,9 +138,9 @@ void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) auto& mftTrackingParam = MFTTrackingParam::Instance(); // compute the track parameters at the last cluster - double x0 = cl.xCoordinate; - double y0 = cl.yCoordinate; - double z0 = cl.zCoordinate; + double x0 = cl.getX(); + double y0 = cl.getY(); + double z0 = cl.getZ(); double pt = TMath::Sqrt(x0 * x0 + y0 * y0); double pz = z0; double phi0 = TMath::ATan2(y0, x0); @@ -240,12 +240,12 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& auto& mftTrackingParam = MFTTrackingParam::Instance(); - if (cl.zCoordinate <= startingParam.getZ()) { + if (cl.getZ() <= startingParam.getZ()) { LOG(INFO) << "AddCluster ERROR: The new cluster must be upstream! Bug on TrackFinder. "; return false; } if (mftTrackingParam.verbose) - std::cout << "addCluster: X = " << cl.xCoordinate << " Y = " << cl.yCoordinate << " Z = " << cl.zCoordinate << std::endl; + std::cout << "addCluster: X = " << cl.getX() << " Y = " << cl.getY() << " Z = " << cl.getZ() << std::endl; // copy the current parameters into the new ones param.setParameters(startingParam.getParameters()); param.setZ(startingParam.getZ()); @@ -256,13 +256,13 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& using o2::mft::constants::LayerZPosition; int startingLayerID, newLayerID; - double dZ = TMath::Abs(cl.zCoordinate - startingParam.getZ()); + double dZ = TMath::Abs(cl.getZ() - startingParam.getZ()); //LayerID of each cluster from ZPosition // TODO: Use ChipMapping for (auto layer = 10; layer--;) if (startingParam.getZ() < LayerZPosition[layer] + .3 & startingParam.getZ() > LayerZPosition[layer] - .3) startingLayerID = layer; for (auto layer = 10; layer--;) - if (cl.zCoordinate<LayerZPosition[layer] + .3 & cl.zCoordinate> LayerZPosition[layer] - .3) + if (cl.getZ()<LayerZPosition[layer] + .3 & cl.getZ()> LayerZPosition[layer] - .3) newLayerID = layer; // Number of disks crossed by this tracklet int NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; @@ -271,7 +271,7 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& if (mftTrackingParam.verbose) { std::cout << "startingLayerID = " << startingLayerID << " ; " << "newLayerID = " << newLayerID << " ; "; - std::cout << "cl.zCoordinate = " << cl.zCoordinate << " ; "; + std::cout << "cl.getZ() = " << cl.getZ() << " ; "; std::cout << "startingParam.getZ() = " << startingParam.getZ() << " ; "; std::cout << "NDisksMS = " << NDisksMS << std::endl; } @@ -289,7 +289,7 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& std::cout << " BeforeExtrap: X = " << param.getX() << " Y = " << param.getY() << " Z = " << param.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; // extrapolate to the z position of the new cluster - mTrackExtrap.extrapToZCov(¶m, cl.zCoordinate, mSmooth); + mTrackExtrap.extrapToZCov(¶m, cl.getZ(), mSmooth); if (mftTrackingParam.verbose) std::cout << " AfterExtrap: X = " << param.getX() << " Y = " << param.getY() << " Z = " << param.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; @@ -304,7 +304,7 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& param.setClusterPtr(&cl); if (runKalmanFilter(param)) { if (mftTrackingParam.verbose) { - std::cout << " New Cluster: X = " << cl.xCoordinate << " Y = " << cl.yCoordinate << " Z = " << cl.zCoordinate << std::endl; + std::cout << " New Cluster: X = " << cl.getX() << " Y = " << cl.getY() << " Z = " << cl.getZ() << std::endl; std::cout << " AfterKalman: X = " << param.getX() << " Y = " << param.getY() << " Z = " << param.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; std::cout << std::endl; // Outputs track covariance matrix: @@ -366,8 +366,8 @@ bool TrackFitter::runKalmanFilter(TrackParamMFT& trackParam) const Cluster* cluster = trackParam.getClusterPtr(); TMatrixD clusterParam(5, 1); clusterParam.Zero(); - clusterParam(0, 0) = cluster->xCoordinate; - clusterParam(1, 0) = cluster->yCoordinate; + clusterParam(0, 0) = cluster->getX(); + clusterParam(1, 0) = cluster->getY(); // compute the actual parameter weight (W) TMatrixD paramWeight(trackParam.getCovariances()); @@ -458,8 +458,8 @@ bool TrackFitter::runSmoother(const TrackParamMFT& previousParam, TrackParamMFT& const Cluster* cluster = param.getClusterPtr(); TMatrixD smoothResidual(2, 1); smoothResidual.Zero(); - smoothResidual(0, 0) = cluster->xCoordinate - smoothParameters(0, 0); - smoothResidual(1, 0) = cluster->yCoordinate - smoothParameters(1, 0); + smoothResidual(0, 0) = cluster->getX() - smoothParameters(0, 0); + smoothResidual(1, 0) = cluster->getY() - smoothParameters(1, 0); // compute weight of smoothed residual: W(k n) = (clusterCov - C(k n))^-1 TMatrixD smoothResidualWeight(2, 2); @@ -503,8 +503,8 @@ Double_t invQPtFromParabola(const FitterTrackMFT& track, Double_t bFieldZ, Doubl Double_t* y = new Double_t[nPoints]; int n = 0; for (auto trackparam = track.begin(); trackparam != track.end(); trackparam++) { - auto x_0 = trackparam->getClusterPtr()->xCoordinate - x_m; - auto y_0 = trackparam->getClusterPtr()->yCoordinate - y_m; + auto x_0 = trackparam->getClusterPtr()->getX() - x_m; + auto y_0 = trackparam->getClusterPtr()->getY() - y_m; x[n] = x_0 * costheta - y_0 * sintheta; y[n] = x_0 * sintheta + y_0 * costheta; //std::cout << " adding rotated point to fit at z = " << trackparam->getClusterPtr()->getZ() << " (" << x[n] << "," << y[n] << ") "<< std::endl; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index 593b96763d1d4..5fa74ff4c9c77 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -169,7 +169,7 @@ void Tracker::findTracksLTF(ROframe& event) // add the first seed-point mcCompLabel = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentTrackLTF().setPoint(cluster1.xCoordinate, cluster1.yCoordinate, cluster1.zCoordinate, layer1, clsLayer1, mcCompLabel, newPoint); + event.getCurrentTrackLTF().setPoint(cluster1.getX(), cluster1.getY(), cluster1.getZ(), layer1, clsLayer1, mcCompLabel, newPoint); for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { @@ -209,7 +209,7 @@ void Tracker::findTracksLTF(ROframe& event) hasDisk[layer / 2] = kTRUE; mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); - event.getCurrentTrackLTF().setPoint(cluster.xCoordinate, cluster.yCoordinate, cluster.zCoordinate, layer, clsLayer, mcCompLabel, newPoint); + event.getCurrentTrackLTF().setPoint(cluster.getX(), cluster.getY(), cluster.getZ(), layer, clsLayer, mcCompLabel, newPoint); } // end clusters bin intermediate layer } // end intermediate layers } // end binPhi @@ -218,10 +218,11 @@ void Tracker::findTracksLTF(ROframe& event) // add the second seed-point mcCompLabel = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentTrackLTF().setPoint(cluster2.xCoordinate, cluster2.yCoordinate, cluster2.zCoordinate, layer2, clsLayer2, mcCompLabel, newPoint); + event.getCurrentTrackLTF().setPoint(cluster2.getX(), cluster2.getY(), cluster2.getZ(), layer2, clsLayer2, mcCompLabel, newPoint); // keep only tracks fulfilling the minimum length condition if (event.getCurrentTrackLTF().getNPoints() < constants::mft::MinTrackPoints) { + LOG(INFO) << "removing Current TrackLTF as nPointDisks = " << event.getCurrentTrackLTF().getNPoints() << std::endl; event.removeCurrentTrackLTF(); continue; } @@ -232,8 +233,11 @@ void Tracker::findTracksLTF(ROframe& event) } if (nPointDisks < constants::mft::MinTrackPoints) { event.removeCurrentTrackLTF(); + LOG(INFO) << "removing Current TrackLTF as nPointDisks = " << nPointDisks << std::endl; continue; } + LOG(INFO) << "Current TrackLTF as nPointDisks = " << nPointDisks << std::endl; + // mark the used clusters //Int_t lay, layMin = 10, layMax = -1; for (Int_t point = 0; point < event.getCurrentTrackLTF().getNPoints(); ++point) { @@ -330,7 +334,7 @@ void Tracker::findTracksCA(ROframe& event) // add the 1st/2nd road points mcCompLabel = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentRoad().setPoint(cluster1.xCoordinate, cluster1.yCoordinate, cluster1.zCoordinate, layer1, clsLayer1, mcCompLabel, newPoint); + event.getCurrentRoad().setPoint(cluster1.getX(), cluster1.getY(), cluster1.getZ(), layer1, clsLayer1, mcCompLabel, newPoint); for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { @@ -367,7 +371,7 @@ void Tracker::findTracksCA(ROframe& event) hasDisk[layer / 2] = kTRUE; mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentRoad().setPoint(cluster.xCoordinate, cluster.yCoordinate, cluster.zCoordinate, layer, clsLayer, mcCompLabel, newPoint); + event.getCurrentRoad().setPoint(cluster.getX(), cluster.getY(), cluster.getZ(), layer, clsLayer, mcCompLabel, newPoint); } // end clusters bin intermediate layer } // end intermediate layers @@ -377,7 +381,7 @@ void Tracker::findTracksCA(ROframe& event) // add the second seed-point mcCompLabel = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentRoad().setPoint(cluster2.xCoordinate, cluster2.yCoordinate, cluster2.zCoordinate, layer2, clsLayer2, mcCompLabel, newPoint); + event.getCurrentRoad().setPoint(cluster2.getX(), cluster2.getY(), cluster2.getZ(), layer2, clsLayer2, mcCompLabel, newPoint); // keep only roads fulfilling the minimum length condition if (event.getCurrentRoad().getNPoints() < constants::mft::MinTrackPoints) { @@ -677,9 +681,9 @@ const Float_t Tracker::getCellChisquare(ROframe& event, const Cell& cell) const z[point] = trackCA.getZCoordinates()[point]; err[point] = constants::mft::Resolution; // FIXME } - x[point] = cluster2.xCoordinate; - y[point] = cluster2.yCoordinate; - z[point] = cluster2.zCoordinate; + x[point] = cluster2.getX(); + y[point] = cluster2.getY(); + z[point] = cluster2.getZ(); err[point] = constants::mft::Resolution; // FIXME // linear regression in the plane z:x @@ -714,8 +718,8 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce if (trackCA.getNPoints() > 0) { const Float_t xLast = trackCA.getXCoordinates()[trackCA.getNPoints() - 1]; const Float_t yLast = trackCA.getYCoordinates()[trackCA.getNPoints() - 1]; - Float_t dx = xLast - cluster2.xCoordinate; - Float_t dy = yLast - cluster2.yCoordinate; + Float_t dx = xLast - cluster2.getX(); + Float_t dy = yLast - cluster2.getY(); Float_t dr = std::sqrt(dx * dx + dy * dy); if (dr > constants::mft::Resolution) { return kFALSE; @@ -729,11 +733,11 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce if (trackCA.getNPoints() == 0) { newPoint = kTRUE; - trackCA.setPoint(cluster2.xCoordinate, cluster2.yCoordinate, cluster2.zCoordinate, layer2, cls2Id, mcCompLabel2, newPoint); + trackCA.setPoint(cluster2.getX(), cluster2.getY(), cluster2.getZ(), layer2, cls2Id, mcCompLabel2, newPoint); } newPoint = kTRUE; - trackCA.setPoint(cluster1.xCoordinate, cluster1.yCoordinate, cluster1.zCoordinate, layer1, cls1Id, mcCompLabel1, newPoint); + trackCA.setPoint(cluster1.getX(), cluster1.getY(), cluster1.getZ(), layer1, cls1Id, mcCompLabel1, newPoint); trackCA.addCell(layer1, cellId); From 1eaeba1eaf831c51189f7a685e0ab2bdeb0c2525 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Sun, 19 Jul 2020 02:26:08 -0300 Subject: [PATCH 0290/1751] TrackParCovFwd: Base Class for MFTTrack --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 95 +--- .../Detectors/ITSMFT/MFT/src/TrackMFT.cxx | 63 --- DataFormats/Reconstruction/CMakeLists.txt | 2 + .../ReconstructionDataFormats/TrackFwd.h | 494 +++++------------- .../src/ReconstructionDataFormatsLinkDef.h | 2 + DataFormats/Reconstruction/src/TrackFwd.cxx | 432 +++++++++++++++ .../tracking/include/MFTTracking/Cluster.h | 3 - .../tracking/include/MFTTracking/TrackCA.h | 11 +- .../include/MFTTracking/TrackParamMFT.h | 2 - .../ITSMFT/MFT/tracking/src/TrackParamMFT.cxx | 59 --- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 3 - 11 files changed, 571 insertions(+), 595 deletions(-) create mode 100644 DataFormats/Reconstruction/src/TrackFwd.cxx diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index fc3be31299ca7..e4bee98c281fd 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -22,6 +22,8 @@ #include "CommonDataFormat/RangeReference.h" #include "SimulationDataFormat/MCCompLabel.h" +#include "ReconstructionDataFormats/TrackFwd.h" + namespace o2 { @@ -33,7 +35,7 @@ class Cluster; namespace mft { -class TrackMFT +class TrackMFT : public o2::track::TrackParCovFwd { using Cluster = o2::itsmft::Cluster; using ClusRefs = o2::dataformats::RangeRefComp<4>; @@ -43,8 +45,6 @@ class TrackMFT public: TrackMFT() = default; TrackMFT(const TrackMFT& t) = default; - TrackMFT(const Double_t Z, const SMatrix5 parameters, const SMatrix55 covariances, const Double_t chi2); - ~TrackMFT() = default; // Track finding method @@ -52,32 +52,6 @@ class TrackMFT const Bool_t isCA() const { return mIsCA; } const Bool_t isLTF() const { return !mIsCA; } - /// return Z coordinate (cm) - Double_t getZ() const { return mZ; } - /// set Z coordinate (cm) - void setZ(Double_t z) { mZ = z; } - Double_t getX() const { return mParameters(0); } - void setX(Double_t x) { mParameters(0) = x; } - Double_t getSigmaX() const { return mCovariances(0, 0); } - - Double_t getY() const { return mParameters(1); } - void setY(Double_t y) { mParameters(1) = y; } - Double_t getSigmaY() const { return mCovariances(1, 1); } - - void setPhi(Double_t phi) { mParameters(2) = phi; } - Double_t getPhi() const { return mParameters(2); } - Double_t getSigmaPhi() const { return mCovariances(2, 2); } - - void setTanl(Double_t tanl) { mParameters(3) = tanl; } - Double_t getTanl() const { return mParameters(3); } - Double_t getSigmaTanl() const { return mCovariances(3, 3); } - - void setInvQPt(Double_t invqpt) { mParameters(4) = invqpt; } - Double_t getInvQPt() const { return mParameters(4); } // return Inverse charged pt - Double_t getPt() const { return TMath::Abs(1.f / mParameters(4)); } - Double_t getInvPt() const { return TMath::Abs(mParameters(4)); } - Double_t getSigmaInvQPt() const { return mCovariances(4, 4); } - // Charge and momentum from quadratic regression of clusters X,Y positions void setInvQPtQuadtratic(Double_t invqpt) { mInvQPtQuadtratic = invqpt; } const Double_t getInvQPtQuadtratic() const { return mInvQPtQuadtratic; } // Inverse charged pt @@ -86,42 +60,7 @@ class TrackMFT void setChi2QPtQuadtratic(Double_t chi2) { mQuadraticFitChi2 = chi2; } const Double_t getChi2QPtQuadtratic() const { return mQuadraticFitChi2; } - Double_t getPx() const { return TMath::Cos(getPhi()) * getPt(); } // return px - Double_t getInvPx() const { return 1. / getPx(); } // return invpx - - Double_t getPy() const { return TMath::Sin(getPhi()) * getPt(); } // return py - Double_t getInvPy() const { return 1. / getPx(); } // return invpy - - Double_t getPz() const { return getTanl() * getPt(); } // return pz - Double_t getInvPz() const { return 1. / getPz(); } // return invpz - Double_t getP() const { return getPt() * TMath::Sqrt(1. + getTanl() * getTanl()); } // return total momentum - Double_t getInverseMomentum() const { return 1.f / getP(); } - - Double_t getEta() const { return -TMath::Log(TMath::Tan((TMath::PiOver2() - TMath::ATan(getTanl())) / 2)); } // return total momentum - - /// return the charge (assumed forward motion) - Double_t getCharge() const { return TMath::Sign(1., mParameters(4)); } - /// set the charge (assumed forward motion) - void setCharge(Double_t charge) - { - if (charge * mParameters(4) < 0.) - mParameters(4) *= -1.; - } - - /// return track parameters - const SMatrix5& getParameters() const { return mParameters; } - - /// set track parameters - void setParameters(const SMatrix5& parameters) { mParameters = parameters; } - - const SMatrix55& getCovariances() const; - void setCovariances(const SMatrix55& covariances); - - /// return the chi2 of the track when the associated cluster was attached - Double_t getTrackChi2() const { return mTrackChi2; } - /// set the chi2 of the track when the associated cluster was attached - void setTrackChi2(Double_t chi2) { mTrackChi2 = chi2; } // Other functions int getNumberOfClusters() const { return mClusRef.getEntries(); } @@ -162,9 +101,6 @@ class TrackMFT void print() const; void printMCCompLabels() const; - // Extrapolate this track to - void extrapHelixToZ(double zEnd, double Field); - // Parameters and Covariances on last track clusters const SMatrix5& getParametersLast() const { return mParametersLast; } void setParametersLast(const SMatrix5& parameters) { mParametersLast = parameters; } // Last cluster @@ -191,28 +127,11 @@ class TrackMFT ClusRefs mClusRef; ///< references on clusters - Double_t mZ = 0.; ///< Z coordinate (cm) Double_t mZLast = 0.; ///< Z coordinate (cm) of Last cluster - /// Track parameters ordered as follow: <pre> - /// X = X coordinate (cm) - /// Y = Y coordinate (cm) - /// PHI = azimutal angle - /// TANL = tangent of \lambda (dip angle) - /// INVQPT = Inverse transverse momentum (GeV/c ** -1) times charge (assumed forward motion) </pre> - SMatrix5 mParameters; ///< \brief Track parameters SMatrix5 mParametersLast; ///< \brief Track parameters at last cluster - - /// Covariance matrix of track parameters, ordered as follows: <pre> - /// <X,X> <Y,X> <PHI,X> <TANL,X> <INVQPT,X> - /// <X,Y> <Y,Y> <PHI,Y> <TANL,Y> <INVQPT,Y> - /// <X,PHI> <Y,PHI> <PHI,PHI> <TANL,PHI> <INVQPT,PHI> - /// <X,TANL> <Y,TANL> <PHI,TANL> <TANL,TANL> <INVQPT,TANL> - /// <X,INVQPT> <Y,INVQPT> <PHI,INVQPT> <TANL,INVQPT> <INVQPT,INVQPT> </pre> - SMatrix55 mCovariances; ///< \brief Covariance matrix of track parameters SMatrix55 mCovariancesLast; ///< \brief Covariance matrix of track parameters at last cluster - Double_t mTrackChi2 = 0.; ///< Chi2 of the track when the associated cluster was attached // Results from quadratic regression of clusters X,Y positions // Chi2 of the quadratic regression used to estimate track pT and charge @@ -252,14 +171,6 @@ class TrackMFTExt : public TrackMFT ClassDefNV(TrackMFTExt, 1); }; } // namespace mft -namespace framework -{ -template <typename T> -struct is_messageable; -template <> -struct is_messageable<o2::mft::TrackMFT> : std::true_type { -}; -} // namespace framework } // namespace o2 #endif diff --git a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx index ef9219b5fafa6..d8175db88b6a4 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx +++ b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx @@ -32,34 +32,7 @@ namespace mft using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; -//__________________________________________________________________________ -TrackMFT::TrackMFT(const Double_t z, const SMatrix5 parameters, const SMatrix55 covariances, const Double_t chi2) -{ - mZ = z; - mParameters = parameters; - mCovariances = covariances; - mTrackChi2 = chi2; -} - -//__________________________________________________________________________ -const SMatrix55& TrackMFT::getCovariances() const -{ - /// Return the covariance matrix - return mCovariances; -} - -//__________________________________________________________________________ -void TrackMFT::setCovariances(const SMatrix55& covariances) -{ - mCovariances = covariances; -} -//__________________________________________________________________________ -const SMatrix55& TrackMFT::getCovariancesLast() const -{ - /// Return the covariance matrix for last cluster - return mCovariancesLast; -} //__________________________________________________________________________ void TrackMFT::setCovariancesLast(const SMatrix55& covariances) @@ -67,42 +40,6 @@ void TrackMFT::setCovariancesLast(const SMatrix55& covariances) mCovariancesLast = covariances; } -//_________________________________________________________________________________________________ -void TrackMFT::extrapHelixToZ(double zEnd, double Field) -{ - /// Track extrapolated to the plane at "zEnd" considering a helix - - if (getZ() == zEnd) { - return; // nothing to be done if same z - } - - // Extrapolate track parameters - double dZ = (zEnd - getZ()); // Propagate in meters - double tanl0 = getTanl(); - double invtanl0 = 1.0 / tanl0; - double px0 = getPx(); - double py0 = getPy(); - double invqpt0 = getInvQPt(); - auto q = getCharge(); - auto Hz = std::copysign(1.0, Field); - double k = TMath::Abs(o2::constants::math::B2C * Field); - auto invk = 1.0 / k; - double theta = -invqpt0 * dZ * k * invtanl0; - double costheta, sintheta; - o2::utils::sincos(theta, sintheta, costheta); - - double deltax = Hz * py0 * invk * (1.0 - costheta) - px0 * q * invk * sintheta; - double deltay = -Hz * px0 * invk * (1.0 - costheta) - py0 * q * invk * sintheta; - double x = getX() + deltax; - double y = getY() + deltay; - double deltaphi = +dZ * k * invqpt0 * invtanl0; - double phi = getPhi() + theta; - setX(x); - setY(y); - setZ(zEnd); - setPhi(phi); -} - //__________________________________________________________________________ void TrackMFT::print() const { diff --git a/DataFormats/Reconstruction/CMakeLists.txt b/DataFormats/Reconstruction/CMakeLists.txt index 0cd8cad59eb9a..a1bd82619d9f0 100644 --- a/DataFormats/Reconstruction/CMakeLists.txt +++ b/DataFormats/Reconstruction/CMakeLists.txt @@ -10,6 +10,7 @@ o2_add_library(ReconstructionDataFormats SOURCES src/Track.cxx + src/TrackFwd.cxx src/BaseCluster.cxx src/TrackTPCITS.cxx src/Vertex.cxx @@ -24,6 +25,7 @@ o2_add_library(ReconstructionDataFormats o2_target_root_dictionary( ReconstructionDataFormats HEADERS include/ReconstructionDataFormats/Track.h + include/ReconstructionDataFormats/TrackFwd.h include/ReconstructionDataFormats/BaseCluster.h include/ReconstructionDataFormats/TrackTPCITS.h include/ReconstructionDataFormats/Vertex.h diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index 4668aaf5d9e15..ab89e32263868 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -8,414 +8,164 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file Track.h -/// \brief Base track model for the Barrel, params only, w/o covariance -/// \author ruben.shahoyan@cern.ch +/// \file TrackFwd.h +/// \brief Base forward track model, params only, w/o covariance +/// +/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS + #ifndef ALICEO2_BASE_TRACKFWD #define ALICEO2_BASE_TRACKFWD +#include <TMath.h> +#include "Math/SMatrix.h" +#include "MathUtils/Utils.h" +//#include <Framework/Logger.h> namespace o2 { -template <typename T> -class BaseCluster; - -namespace dataformats -{ -class VertexBase; -class DCA; -} // namespace dataformats - namespace track { -// aliases for track elements -enum ParLabels : int { kY, - kZ, - kSnp, - kTgl, - kQ2Pt }; -enum CovLabels : int { - kSigY2, - kSigZY, - kSigZ2, - kSigSnpY, - kSigSnpZ, - kSigSnp2, - kSigTglY, - kSigTglZ, - kSigTglSnp, - kSigTgl2, - kSigQ2PtY, - kSigQ2PtZ, - kSigQ2PtSnp, - kSigQ2PtTgl, - kSigQ2Pt2 -}; -enum DirType : int { DirInward = -1, - DirAuto = 0, - DirOutward = 1 }; - -constexpr int kNParams = 5, kCovMatSize = 15, kLabCovMatSize = 21; - -constexpr float kCY2max = 100 * 100, // SigmaY<=100cm - kCZ2max = 100 * 100, // SigmaZ<=100cm - kCSnp2max = 1 * 1, // SigmaSin<=1 - kCTgl2max = 1 * 1, // SigmaTan<=1 - kC1Pt2max = 100 * 100, // Sigma1/Pt<=100 1/GeV - kMostProbablePt = 0.6, // Most Probable Pt (GeV), for running with Bz=0 - kCalcdEdxAuto = -999.f; // value indicating request for dedx calculation - -// access to covariance matrix by row and column -constexpr int CovarMap[kNParams][kNParams] = {{0, 1, 3, 6, 10}, - {1, 2, 4, 7, 11}, - {3, 4, 5, 8, 12}, - {6, 7, 8, 9, 13}, - {10, 11, 12, 13, 14}}; - -// access to covariance matrix diagonal elements -constexpr int DiagMap[kNParams] = {0, 2, 5, 9, 14}; - -constexpr float HugeF = o2::constants::math::VeryBig; - -// helper function -float BetheBlochSolid(float bg, float rho = 2.33f, float kp1 = 0.20f, float kp2 = 3.00f, float meanI = 173e-9f, - float meanZA = 0.49848f); -void g3helx3(float qfield, float step, std::array<float, 7>& vect); - -class TrackPar -{ // track parameterization, kinematics only. - public: - TrackPar() = default; - TrackPar(float x, float alpha, const std::array<float, kNParams>& par); - TrackPar(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, int sign, bool sectorAlpha = true); - TrackPar(const TrackPar&) = default; - TrackPar& operator=(const TrackPar& src) = default; - ~TrackPar() = default; - - const float* getParams() const { return mP; } - float getParam(int i) const { return mP[i]; } - float getX() const { return mX; } - float getAlpha() const { return mAlpha; } - float getY() const { return mP[kY]; } - float getZ() const { return mP[kZ]; } - float getSnp() const { return mP[kSnp]; } - float getTgl() const { return mP[kTgl]; } - float getQ2Pt() const { return mP[kQ2Pt]; } - - /// calculate cos^2 and cos of track direction in rphi-tracking - float getCsp2() const - { - float csp2 = (1. - mP[kSnp]) * (1. + mP[kSnp]); - return csp2 > o2::constants::math::Almost0 ? csp2 : o2::constants::math::Almost0; - } - float getCsp() const { return sqrtf(getCsp2()); } - - void setX(float v) { mX = v; } - void setParam(float v, int i) { mP[i] = v; } - void setAlpha(float v) { mAlpha = v; } - void setY(float v) { mP[kY] = v; } - void setZ(float v) { mP[kZ] = v; } - void setSnp(float v) { mP[kSnp] = v; } - void setTgl(float v) { mP[kTgl] = v; } - void setQ2Pt(float v) { mP[kQ2Pt] = v; } - - // derived getters - bool getXatLabR(float r, float& x, float bz, DirType dir = DirAuto) const; - void getCircleParamsLoc(float bz, o2::utils::CircleXY& circle) const; - void getCircleParams(float bz, o2::utils::CircleXY& circle, float& sna, float& csa) const; - void getLineParams(o2::utils::IntervalXY& line, float& sna, float& csa) const; - float getCurvature(float b) const { return mP[kQ2Pt] * b * o2::constants::math::B2C; } - float getSign() const { return mP[kQ2Pt] > 0 ? 1.f : -1.f; } - float getPhi() const; - float getPhiPos() const; - - float getP2Inv() const; - float getP2() const; - float getPInv() const; - float getP() const; - float getPt() const; - - float getTheta() const { return constants::math::PIHalf - std::atan(mP[3]); } - float getEta() const { return -std::log(std::tan(0.5 * getTheta())); } - Point3D<float> getXYZGlo() const; - void getXYZGlo(std::array<float, 3>& xyz) const; - bool getPxPyPzGlo(std::array<float, 3>& pxyz) const; - bool getPosDirGlo(std::array<float, 9>& posdirp) const; - - // methods for track params estimate at other point - bool getYZAt(float xk, float b, float& y, float& z) const; - float getZAt(float xk, float b) const; - float getYAt(float xk, float b) const; - Point3D<float> getXYZGloAt(float xk, float b, bool& ok) const; - - // parameters manipulation - bool correctForELoss(float xrho, float mass, bool anglecorr = false, float dedx = kCalcdEdxAuto); - bool rotateParam(float alpha); - bool propagateParamTo(float xk, float b); - bool propagateParamTo(float xk, const std::array<float, 3>& b); - - bool propagateParamToDCA(const Point3D<float>& vtx, float b, std::array<float, 2>* dca = nullptr, float maxD = 999.f); - - void invertParam(); - -#ifndef GPUCA_ALIGPUCODE - void printParam() const; - std::string asString() const; -#endif +//using Cluster = o2::BaseCluster<Float_t>; +using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; +using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; - protected: - void updateParam(float delta, int i) { mP[i] += delta; } - void updateParams(const float delta[kNParams]) - { - for (int i = kNParams; i--;) { - mP[i] += delta[i]; - } - } - // derived getters - - private: - // - 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 - - ClassDefNV(TrackPar, 1); -}; +class TrackParFwd +{ // Forward track parameterization, kinematics only. +public: + TrackParFwd() = default; + ~TrackParFwd() = default; -class TrackParCov : public TrackPar -{ // track+error parameterization - using MatrixDSym5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepSym<double, kNParams>>; - using MatrixD5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepStd<double, kNParams, kNParams>>; - - public: - TrackParCov() : TrackPar{} {} - TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, const std::array<float, kCovMatSize>& cov); - TrackParCov(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, - const std::array<float, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); - TrackParCov(const TrackParCov& src) = default; - TrackParCov& operator=(const TrackParCov& src) = default; - ~TrackParCov() = default; - - const float* getCov() const { return mC; } - float getSigmaY2() const { return mC[kSigY2]; } - float getSigmaZY() const { return mC[kSigZY]; } - float getSigmaZ2() const { return mC[kSigZ2]; } - float getSigmaSnpY() const { return mC[kSigSnpY]; } - float getSigmaSnpZ() const { return mC[kSigSnpZ]; } - float getSigmaSnp2() const { return mC[kSigSnp2]; } - float getSigmaTglY() const { return mC[kSigTglY]; } - float getSigmaTglZ() const { return mC[kSigTglZ]; } - float getSigmaTglSnp() const { return mC[kSigTglSnp]; } - float getSigmaTgl2() const { return mC[kSigTgl2]; } - float getSigma1PtY() const { return mC[kSigQ2PtY]; } - float getSigma1PtZ() const { return mC[kSigQ2PtZ]; } - float getSigma1PtSnp() const { return mC[kSigQ2PtSnp]; } - float getSigma1PtTgl() const { return mC[kSigQ2PtTgl]; } - float getSigma1Pt2() const { return mC[kSigQ2Pt2]; } - float getCovarElem(int i, int j) const { return mC[CovarMap[i][j]]; } - float getDiagError2(int i) const { return mC[DiagMap[i]]; } - -#ifndef GPUCA_ALIGPUCODE - void print() const; - std::string asString() const; -#endif + TrackParFwd(const TrackParFwd& tp) = default; + TrackParFwd& operator=(const TrackParFwd& tp) = default; + TrackParFwd(TrackParFwd&&) = delete; + TrackParFwd& operator=(TrackParFwd&&) = delete; + + /// return Z coordinate (cm) + Double_t getZ() const { return mZ; } + /// set Z coordinate (cm) + void setZ(Double_t z) { mZ = z; } + Double_t getX() const { return mParameters(0); } + void setX(Double_t x) { mParameters(0) = x; } - // parameters + covmat manipulation - bool rotate(float alpha); - bool propagateTo(float xk, float b); - bool propagateTo(float xk, const std::array<float, 3>& b); - bool propagateToDCA(const o2::dataformats::VertexBase& vtx, float b, o2::dataformats::DCA* dca = nullptr, float maxD = 999.f); - void invert(); + Double_t getY() const { return mParameters(1); } + void setY(Double_t y) { mParameters(1) = y; } - float getPredictedChi2(const std::array<float, 2>& p, const std::array<float, 3>& cov) const; + void setPhi(Double_t phi) { mParameters(2) = phi; } + Double_t getPhi() const { return mParameters(2); } - template <typename T> - float getPredictedChi2(const BaseCluster<T>& p) const - { - const std::array<float, 2> pyz = {p.getY(), p.getZ()}; - const std::array<float, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; - return getPredictedChi2(pyz, cov); - } + void setTanl(Double_t tanl) { mParameters(3) = tanl; } + Double_t getTanl() const { return mParameters(3); } - float getPredictedChi2(const TrackParCov& rhs) const; + void setInvQPt(Double_t invqpt) { mParameters(4) = invqpt; } + Double_t getInvQPt() const { return mParameters(4); } // return Inverse charged pt + Double_t getPt() const { return TMath::Abs(1.f / mParameters(4)); } + Double_t getInvPt() const { return TMath::Abs(mParameters(4)); } - void buildCombinedCovMatrix(const TrackParCov& rhs, MatrixDSym5& cov) const; - float getPredictedChi2(const TrackParCov& rhs, MatrixDSym5& covToSet) const; - bool update(const TrackParCov& rhs, const MatrixDSym5& covInv); + Double_t getPx() const { return TMath::Cos(getPhi()) * getPt(); } // return px + Double_t getInvPx() const { return 1. / getPx(); } // return invpx - bool update(const std::array<float, 2>& p, const std::array<float, 3>& cov); + Double_t getPy() const { return TMath::Sin(getPhi()) * getPt(); } // return py + Double_t getInvPy() const { return 1. / getPx(); } // return invpy - template <typename T> - bool update(const BaseCluster<T>& p) - { - const std::array<float, 2> pyz = {p.getY(), p.getZ()}; - const std::array<float, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; - return update(pyz, cov); - } + Double_t getPz() const { return getTanl() * getPt(); } // return pz + Double_t getInvPz() const { return 1. / getPz(); } // return invpz - bool update(const TrackParCov& rhs); + Double_t getP() const { return getPt() * TMath::Sqrt(1. + getTanl() * getTanl()); } // return total momentum + Double_t getInverseMomentum() const { return 1.f / getP(); } - bool correctForMaterial(float x2x0, float xrho, float mass, bool anglecorr = false, float dedx = kCalcdEdxAuto); + Double_t getEta() const { return -TMath::Log(TMath::Tan((TMath::PiOver2() - TMath::ATan(getTanl())) / 2)); } // return total momentum - void resetCovariance(float s2 = 0); - void checkCovariance(); - void setCov(float v, int i) { mC[i] = v; } + /// return the charge (assumed forward motion) + Double_t getCharge() const { return TMath::Sign(1., mParameters(4)); } + /// set the charge (assumed forward motion) + void setCharge(Double_t charge) + { + if (charge * mParameters(4) < 0.) + mParameters(4) *= -1.; + } - protected: - void updateCov(const float delta[kCovMatSize]) - { - for (int i = kCovMatSize; i--;) - mC[i] += delta[i]; - } + /// return track parameters + const SMatrix5& getParameters() const { return mParameters; } + /// set track parameters + void setParameters(const SMatrix5& parameters) { mParameters = parameters; } + /// add track parameters + void addParameters(const SMatrix5& parameters) { mParameters += parameters; } - protected: - float mC[kCovMatSize] = {0.f}; // 15 covariance matrix elements + /// get pointer to associated cluster + //const Cluster* getClusterPtr() const { return mClusterPtr; } + /// set pointer to associated cluster + //void setClusterPtr(const Cluster* cluster) { mClusterPtr = cluster; } + + + /// return the chi2 of the track when the associated cluster was attached + Double_t getTrackChi2() const { return mTrackChi2; } + /// set the chi2 of the track when the associated cluster was attached + void setTrackChi2(Double_t chi2) { mTrackChi2 = chi2; } + + void linearExtrapToZ(double zEnd); + void quadraticExtrapToZ(double zEnd, double zField); + void helixExtrapToZ(double zEnd, double zField); + +private: + Double_t mZ = 0.; ///< Z coordinate (cm) + + /// Track parameters ordered as follow: <pre> + /// X = X coordinate (cm) + /// Y = Y coordinate (cm) + /// PHI = azimutal angle + /// TANL = tangent of \lambda (dip angle) + /// INVQPT = Inverse transverse momentum (GeV/c ** -1) times charge (assumed forward motion) </pre> + SMatrix5 mParameters{}; ///< \brief Track parameters + //const Cluster* mClusterPtr = nullptr; ///< Pointer to the associated cluster if any + Double_t mTrackChi2 = 0.; ///< Chi2 of the track when the associated cluster was attached + + ClassDefNV(TrackParFwd, 1); - ClassDefNV(TrackParCov, 1); }; -//____________________________________________________________ -inline TrackPar::TrackPar(float x, float alpha, const std::array<float, kNParams>& par) : mX{x}, mAlpha{alpha} -{ - // explicit constructor - std::copy(par.begin(), par.end(), mP); -} +class TrackParCovFwd : public TrackParFwd +{ // Forward track+error parameterization + public: + using TrackParFwd::TrackParFwd; // inherit base constructors -//_______________________________________________________ -inline void TrackPar::getLineParams(o2::utils::IntervalXY& ln, float& sna, float& csa) const -{ - // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } - o2::utils::sincos(getAlpha(), sna, csa); - o2::utils::rotateZ(getX(), getY(), ln.xP, ln.yP, sna, csa); // reference point in global frame - float snp = getSnp(), csp = sqrtf((1.f - snp) * (1.f + snp)); - ln.dxP = csp * csa - snp * sna; - ln.dyP = snp * csa + csp * sna; -} - -//_______________________________________________________ -inline void TrackPar::getCircleParams(float bz, o2::utils::CircleXY& c, float& sna, float& csa) const -{ - // get circle params in loc and lab frame, for straight line just set to global coordinates - getCircleParamsLoc(bz, c); - o2::utils::sincos(getAlpha(), sna, csa); - o2::utils::rotateZ(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame -} - -//_______________________________________________________ -inline void TrackPar::getCircleParamsLoc(float bz, o2::utils::CircleXY& c) const -{ - // get circle params in track local frame, for straight line just set to local coordinates - c.rC = getCurvature(bz); - if (std::abs(c.rC) > o2::constants::math::Almost0) { - c.rC = 1.f / getCurvature(bz); - float sn = getSnp(), cs = sqrtf((1. - sn) * (1. + sn)); - c.xC = getX() - sn * c.rC; // center in tracking - c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!! - c.rC = fabs(c.rC); - } else { - c.rC = 0.f; // signal straight line - c.xC = getX(); - c.yC = getY(); - } -} - -//_______________________________________________________ -inline void TrackPar::getXYZGlo(std::array<float, 3>& xyz) const -{ - // track coordinates in lab frame - xyz[0] = getX(); - xyz[1] = getY(); - xyz[2] = getZ(); - utils::RotateZ(xyz, getAlpha()); -} - -//_______________________________________________________ -inline float TrackPar::getPhi() const -{ - // track pt direction phi (in 0:2pi range) - float phi = asinf(getSnp()) + getAlpha(); - utils::BringTo02Pi(phi); - return phi; -} - -#ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden -//_______________________________________________________ -inline Point3D<float> TrackPar::getXYZGlo() const -{ - return Rotation2D(getAlpha())(Point3D<float>(getX(), getY(), getZ())); -} + TrackParCovFwd() = default; + ~TrackParCovFwd() = default; -//_______________________________________________________ -inline Point3D<float> TrackPar::getXYZGloAt(float xk, float b, bool& ok) const -{ - //---------------------------------------------------------------- - // estimate global X,Y,Z in global frame at given X - //---------------------------------------------------------------- - float y = 0.f, z = 0.f; - ok = getYZAt(xk, b, y, z); - return ok ? Rotation2D(getAlpha())(Point3D<float>(xk, y, z)) : Point3D<float>(); -} -#endif -//_______________________________________________________ -inline float TrackPar::getPhiPos() const -{ - // angle of track position (in -pi:pi range) - float phi = atan2f(getY(), getX()) + getAlpha(); - utils::BringTo02Pi(phi); - return phi; -} - -//____________________________________________________________ -inline float TrackPar::getP2Inv() const -{ - // return the inverted track momentum^2 - return getQ2Pt() * getQ2Pt() / (1.f + getTgl() * getTgl()); -} + TrackParCovFwd(const TrackParCovFwd& tpf) = default; + TrackParCovFwd& operator=(const TrackParCovFwd& tpf) = default; + TrackParCovFwd(const Double_t z, const SMatrix5 parameters, const SMatrix55 covariances, const Double_t chi2); -//____________________________________________________________ -inline float TrackPar::getPInv() const -{ - // return the inverted track momentum^2 - return fabs(getQ2Pt()) / sqrtf(1.f + getTgl() * getTgl()); -} -//____________________________________________________________ -inline float TrackPar::getP2() const -{ - // return the track momentum^2 - auto p2inv = getP2Inv(); - return (p2inv > o2::constants::math::Almost0) ? 1. / p2inv : o2::constants::math::VeryBig; -} + const SMatrix55& getCovariances() const; + void setCovariances(const SMatrix55& covariances); + void deleteCovariances(); -//____________________________________________________________ -inline float TrackPar::getP() const -{ - // return the track momentum - float pInv = getPInv(); - return (pInv > o2::constants::math::Almost0) ? 1. / pInv : o2::constants::math::VeryBig; -} + Double_t getSigmaX() const { return mCovariances(0, 0); } + Double_t getSigmaY() const { return mCovariances(1, 1); } + Double_t getSigmaPhi() const { return mCovariances(2, 2); } + Double_t getSigmaTanl() const { return mCovariances(3, 3); } + Double_t getSigmaInvQPt() const { return mCovariances(4, 4); } -//____________________________________________________________ -inline float TrackPar::getPt() const -{ - // return the track transverse momentum - float ptI = fabs(getQ2Pt()); - return (ptI > o2::constants::math::Almost0) ? 1.f / ptI : o2::constants::math::VeryBig; -} + void linearExtrapToZCov(double zEnd); + void quadraticExtrapToZCov(double zEnd, double zField); + void helixExtrapToZCov(double zEnd, double zField); + void addMCSEffect(double dZ, double x0, double zField); -//============================================================ +private: -//____________________________________________________________ -inline TrackParCov::TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, - const std::array<float, kCovMatSize>& cov) - : TrackPar{x, alpha, par} -{ - // explicit constructor - std::copy(cov.begin(), cov.end(), mC); -} + /// Covariance matrix of track parameters, ordered as follows: <pre> + /// <X,X> <Y,X> <PHI,X> <TANL,X> <INVQPT,X> + /// <X,Y> <Y,Y> <PHI,Y> <TANL,Y> <INVQPT,Y> + /// <X,PHI> <Y,PHI> <PHI,PHI> <TANL,PHI> <INVQPT,PHI> + /// <X,TANL> <Y,TANL> <PHI,TANL> <TANL,TANL> <INVQPT,TANL> + /// <X,INVQPT> <Y,INVQPT> <PHI,INVQPT> <TANL,INVQPT> <INVQPT,INVQPT> </pre> + SMatrix55 mCovariances{}; ///< \brief Covariance matrix of track parameters + ClassDefNV(TrackParCovFwd, 1); + +}; } // namespace track } // namespace o2 diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index e8c481cddf741..b617c8913a0e9 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -16,6 +16,8 @@ #pragma link C++ class o2::track::TrackPar + ; #pragma link C++ class o2::track::TrackParCov + ; +#pragma link C++ class o2::track::TrackParFwd + ; +#pragma link C++ class o2::track::TrackParCovFwd + ; #pragma link C++ class o2::track::PID + ; #pragma link C++ class o2::track::TrackLTIntegral + ; diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx new file mode 100644 index 0000000000000..9fc10792f974e --- /dev/null +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -0,0 +1,432 @@ +// 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 "ReconstructionDataFormats/TrackFwd.h" +#include "Math/MatrixFunctions.h" + + +namespace o2 +{ +namespace track +{ +using namespace std; + +//_________________________________________________________________________ +TrackParCovFwd::TrackParCovFwd(const Double_t z, const SMatrix5 parameters, const SMatrix55 covariances, const Double_t chi2) +{ + setZ(z); + setParameters(parameters); + setCovariances(covariances); + setTrackChi2(chi2); +} + +//__________________________________________________________________________ +const SMatrix55& TrackParCovFwd::getCovariances() const +{ + /// Return the covariance matrix (create it before if needed) + return mCovariances; +} + +//__________________________________________________________________________ +void TrackParCovFwd::setCovariances(const SMatrix55& covariances) +{ + /// Set the covariance matrix + mCovariances = covariances; +} + + +//__________________________________________________________________________ +void TrackParCovFwd::deleteCovariances() +{ + /// Delete the covariance matrix + mCovariances = SMatrix55(); +} + +/* //_________________________________________________________________________ +TrackParCovFwd& TrackParCovFwd::operator=(const TrackParCovFwd& tp) +{ + /// Assignment operator + if (this == &tp) + return *this; + + TrackParFwd::operator=(tp); + mCovariances = tp.mCovariances; + return *this; +} +*/ + + + +/* +//_________________________________________________________________________ +TrackParCovFwd::TrackParCovFwd(const TrackParCovFwd& tp) + : TrackParFwd(tp) +{ + /// Copy constructor + mCovariances = tp.mCovariances; +} +*/ + + +//__________________________________________________________________________ +void TrackParFwd::linearExtrapToZ(double zEnd) +{ + /// Track linearly extrapolated to the plane at "zEnd". + + if (getZ() == zEnd) { + return; // nothing to be done if same z + } + + // Compute track parameters + auto dZ = (zEnd - getZ()); + auto x0 = getX(); + auto y0 = getY(); + auto phi0 = getPhi(); + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto invtanl0 = 1.0 / getTanl(); + auto n = dZ * invtanl0; + auto x = x0 + n * cosphi0; + auto y = y0 + n * sinphi0; + setX(x); + setY(y); + setZ(zEnd); +} + +//__________________________________________________________________________ +void TrackParCovFwd::linearExtrapToZCov(double zEnd) +{ + /// Track parameters and their covariances linearly extrapolated to the plane at "zEnd". + /// On return, results from the extrapolation are updated in trackParam. + + // Calculate the jacobian related to the track parameters extrapolated to "zEnd" + auto dZ = (zEnd - getZ()); + auto x0 = getX(); + auto y0 = getY(); + auto phi0 = getPhi(); + auto tanl0 = getTanl(); + auto invtanl0 = 1.0 / tanl0; + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto n = dZ * invtanl0; + auto m = n * invtanl0; + + // Extrapolate track parameters to "zEnd" + auto x = x0 + n * cosphi0; + auto y = y0 + n * sinphi0; + setX(x); + setY(y); + setZ(zEnd); + + // Calculate Jacobian + SMatrix55 jacob = ROOT::Math::SMatrixIdentity(); + jacob(0, 2) = -n * sinphi0; + jacob(0, 3) = -m * cosphi0; + jacob(1, 2) = n * cosphi0; + jacob(1, 3) = -m * sinphi0; + + // Extrapolate track parameter covariances to "zEnd" + setCovariances(ROOT::Math::Similarity(jacob,mCovariances)); +} + +//__________________________________________________________________________ +void TrackParFwd::quadraticExtrapToZ(double zEnd, double zField) +{ + /// Track parameters extrapolated to the plane at "zEnd" considering a helix + /// On return, results from the extrapolation are updated in trackParam. + + if (getZ() == zEnd) { + return; // nothing to be done if same z + } + + // Compute track parameters + auto dZ = (zEnd - getZ()); + auto x0 = getX(); + auto y0 = getY(); + auto phi0 = getPhi(); + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto invtanl0 = 1.0 / getTanl(); + auto invqpt0 = getInvQPt(); + auto Hz = std::copysign(1, zField); + auto k = TMath::Abs(o2::constants::math::B2C * zField); + auto n = dZ * invtanl0; + auto theta = -invqpt0 * dZ * k * invtanl0; + auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; + auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; + auto phi = phi0 + Hz * theta; + + setX(x); + setY(y); + setZ(zEnd); + setPhi(phi); +} + +//__________________________________________________________________________ +void TrackParCovFwd::quadraticExtrapToZCov(double zEnd, double zField) +{ + + // Extrapolate track parameters and covariances matrix to "zEnd" + if (getZ() == zEnd) { + return; // nothing to be done if same z + } + + // Compute track parameters + auto dZ = (zEnd - getZ()); + auto x0 = getX(); + auto y0 = getY(); + auto phi0 = getPhi(); + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto invtanl0 = 1.0 / getTanl(); + auto invqpt0 = getInvQPt(); + auto Hz = std::copysign(1, zField); + auto k = TMath::Abs(o2::constants::math::B2C * zField); + auto n = dZ * invtanl0; + auto m = n * invtanl0; + auto theta = -invqpt0 * dZ * k * invtanl0; + + // Extrapolate track parameters to "zEnd" + auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; + auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; + auto phi = phi0 + Hz * theta; + setX(x); + setY(y); + setZ(zEnd); + setPhi(phi); + + // Calculate Jacobian + SMatrix55 jacob = ROOT::Math::SMatrixIdentity(); + jacob(0, 2) = -n * theta * 0.5 * Hz * cosphi0 - n * sinphi0; + jacob(0, 3) = Hz * m * theta * sinphi0 - m * cosphi0; + jacob(0, 4) = k * m * 0.5 * Hz * dZ * sinphi0; + jacob(1, 2) = -n * theta * 0.5 * Hz * sinphi0 + n * cosphi0; + jacob(1, 3) = -Hz * m * theta * cosphi0 - m * sinphi0; + jacob(1, 4) = -k * m * 0.5 * Hz * dZ * cosphi0; + jacob(2, 3) = -Hz * theta * invtanl0; + jacob(2, 4) = -Hz * k * n; + + // Extrapolate track parameter covariances to "zEnd" + setCovariances(ROOT::Math::Similarity(jacob,mCovariances)); + +} + +//__________________________________________________________________________ +void TrackParFwd::helixExtrapToZ(double zEnd, double zField) +{ + /// Track parameters extrapolated to the plane at "zEnd" considering a helix + /// On return, results from the extrapolation are updated in trackParam. + + if (getZ() == zEnd) { + return; // nothing to be done if same z + } + + // Compute track parameters + auto dZ = (zEnd - getZ()); + auto x0 = getX(); + auto y0 = getY(); + auto phi0 = getPhi(); + auto tanl0 = getTanl(); + auto invtanl0 = 1.0 / tanl0; + auto invqpt0 = getInvQPt(); + auto qpt0 = 1.0 / invqpt0; + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto k = TMath::Abs(o2::constants::math::B2C * zField); + auto invk = 1.0 / k; + auto theta = -invqpt0 * dZ * k * invtanl0; + double costheta, sintheta; + o2::utils::sincos(theta, sintheta, costheta); + auto Hz = std::copysign(1, zField); + auto Y = sinphi0 * qpt0 * invk; + auto X = cosphi0 * qpt0 * invk; + auto YC = Y * costheta; + auto YS = Y * sintheta; + auto XC = X * costheta; + auto XS = X * sintheta; + + // Extrapolate track parameters to "zEnd" + auto x = x0 + Hz * (Y - YC) - XS; + auto y = y0 + Hz * (-X + XC) - YS; + auto phi = phi0 + Hz * theta; + setX(x); + setY(y); + setZ(zEnd); + setPhi(phi); +} + +//__________________________________________________________________________ +void TrackParCovFwd::helixExtrapToZCov(double zEnd, double zField) +{ + + // Extrapolate track parameters and covariances matrix to "zEnd" + auto dZ = (zEnd - getZ()); + auto x0 = getX(); + auto y0 = getY(); + auto phi0 = getPhi(); + auto tanl0 = getTanl(); + auto invtanl0 = 1.0 / tanl0; + auto invqpt0 = getInvQPt(); + auto qpt0 = 1.0 / invqpt0; + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + auto k = TMath::Abs(o2::constants::math::B2C * zField); + auto invk = 1.0 / k; + auto theta = -invqpt0 * dZ * k * invtanl0; + double costheta, sintheta; + o2::utils::sincos(theta, sintheta, costheta); + auto Hz = std::copysign(1, zField); + auto L = qpt0 * qpt0 * invk; + auto N = dZ * invtanl0 * qpt0; + auto O = sintheta * cosphi0; + auto P = sinphi0 * costheta; + auto R = sinphi0 * sintheta; + auto S = cosphi0 * costheta; + auto Y = sinphi0 * qpt0 * invk; + auto X = cosphi0 * qpt0 * invk; + auto YC = Y * costheta; + auto YS = Y * sintheta; + auto XC = X * costheta; + auto XS = X * sintheta; + auto T = qpt0 * costheta; + auto U = qpt0 * sintheta; + auto V = qpt0; + auto n = dZ * invtanl0; + auto m = n * invtanl0; + + // Extrapolate track parameters to "zEnd" + auto x = x0 + Hz * (Y - YC) - XS; + auto y = y0 + Hz * (-X + XC) - YS; + auto phi = phi0 + Hz * theta; + setX(x); + setY(y); + setZ(zEnd); + setPhi(phi); + + // Calculate Jacobian + SMatrix55 jacob = ROOT::Math::SMatrixIdentity(); + jacob(0, 2) = Hz * X - Hz * XC + YS; + jacob(0, 3) = Hz * R * m - S * m; + jacob(0, 4) = -Hz * N * R + Hz * T * Y - Hz * V * Y + N * S + U * X; + jacob(1, 2) = Hz * Y - Hz * YC - XS; + jacob(1, 3) = -Hz * O * m - P * m; + jacob(1, 4) = Hz * N * O - Hz * T * X + Hz * V * X + N * P + U * Y; + jacob(2, 3) = -Hz * theta * invtanl0; + jacob(2, 4) = -Hz * k * n; + + // Extrapolate track parameter covariances to "zEnd" + setCovariances(ROOT::Math::Similarity(jacob,mCovariances)); + +} + +//__________________________________________________________________________ +void TrackParCovFwd::addMCSEffect(double dZ, double x0, double zField) +{ + /// Add to the track parameter covariances the effects of multiple Coulomb scattering + /// through a material of thickness "abs(dZ)" and of radiation length "x0" + /// assuming linear propagation and using the small angle approximation. + /// All scattering evaluated happens at the position of the first cluster + + auto phi0 = getPhi(); + auto tanl0 = getTanl(); + auto invtanl0 = 1.0 / tanl0; + auto invqpt0 = getInvQPt(); + auto p = getP(); + + double cosphi0, sinphi0; + o2::utils::sincos(phi0, sinphi0, cosphi0); + + auto csclambda = TMath::Abs(TMath::Sqrt(1 + tanl0 * tanl0) * invtanl0); + auto pathLengthOverX0 = x0 * csclambda; + + // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory + auto sigmathetasq = 0.0136 * invqpt0 * (1 + 0.038 * TMath::Log(pathLengthOverX0)); + sigmathetasq *= sigmathetasq * pathLengthOverX0; + + // Get covariance matrix + SMatrix55 newParamCov(getCovariances()); + + if (dZ > 0) { + auto A = tanl0 * tanl0 + 1; + auto B = dZ * cosphi0 * invtanl0; + auto C = dZ * sinphi0 * invtanl0; + auto D = A * B * invtanl0; + auto E = -A * C * invtanl0; + auto F = -C - D; + auto G = B + E; + auto H = -invqpt0 * tanl0; + + newParamCov(0, 0) += sigmathetasq * F * F; + + newParamCov(0, 1) += sigmathetasq * F * G; + newParamCov(1, 0) += sigmathetasq * F * G; + + newParamCov(1, 1) += sigmathetasq * G * G; + + newParamCov(2, 0) += sigmathetasq * F; + newParamCov(0, 2) += sigmathetasq * F; + + newParamCov(2, 1) += sigmathetasq * G; + newParamCov(1, 2) += sigmathetasq * G; + + newParamCov(2, 2) += sigmathetasq; + + newParamCov(3, 0) += sigmathetasq * A * F; + newParamCov(0, 3) += sigmathetasq * A * F; + + newParamCov(3, 1) += sigmathetasq * A * G; + newParamCov(1, 3) += sigmathetasq * A * G; + + newParamCov(3, 2) += sigmathetasq * A; + newParamCov(2, 3) += sigmathetasq * A; + + newParamCov(3, 3) += sigmathetasq * A * A; + + newParamCov(4, 0) += sigmathetasq * F * H; + newParamCov(0, 4) += sigmathetasq * F * H; + + newParamCov(4, 1) += sigmathetasq * G * H; + newParamCov(1, 4) += sigmathetasq * G * H; + + newParamCov(4, 2) += sigmathetasq * H; + newParamCov(2, 4) += sigmathetasq * H; + + newParamCov(4, 3) += sigmathetasq * A * H; + newParamCov(3, 4) += sigmathetasq * A * H; + + newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; + } else { + + auto A = tanl0 * tanl0 + 1; + auto H = -invqpt0 * tanl0; + + newParamCov(2, 2) += sigmathetasq; + + newParamCov(3, 2) += sigmathetasq * A; + newParamCov(2, 3) += sigmathetasq * A; + + newParamCov(3, 3) += sigmathetasq * A * A; + + newParamCov(4, 2) += sigmathetasq * H; + newParamCov(2, 4) += sigmathetasq * H; + + newParamCov(4, 3) += sigmathetasq * A * H; + newParamCov(3, 4) += sigmathetasq * A * H; + + newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; + } + + + // Set new covariances + setCovariances(newParamCov); +} + +} // namespace track +} // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index a0c2d57fff211..f42e86fd870bd 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -35,9 +35,6 @@ struct Cluster : public o2::BaseCluster<float> { Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t index); Cluster(const Int_t layerIndex, const Cluster& other); - //Float_t xCoordinate; - //Float_t yCoordinate; - //Float_t zCoordinate; Float_t phiCoordinate; Float_t rCoordinate; Int_t clusterId; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index c42fe5a0b3493..20537e2dad905 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -16,6 +16,7 @@ #define O2_MFT_TRACKCA_H_ #include <array> +#include "DataFormatsMFT/TrackMFT.h" #include "SimulationDataFormat/MCCompLabel.h" #include "MFTTracking/Constants.h" #include <fairlogger/Logger.h> @@ -25,7 +26,7 @@ namespace o2 namespace mft { -class TrackCA final +class TrackCA : public TrackMFT { public: TrackCA() = default; @@ -172,5 +173,13 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z } } // namespace mft +namespace framework +{ +template <typename T> +struct is_messageable; +template <> +struct is_messageable<o2::mft::TrackCA> : std::true_type { +}; +} // namespace framework } // namespace o2 #endif /* O2_MFT_TRACKCA_H_ */ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h index 7e41df9563a2b..3bc63486d8773 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h @@ -132,8 +132,6 @@ class TrackParamMFT /// set the local chi2 of the associated cluster with respect to the track void setLocalChi2(Double_t chi2) { mLocalChi2 = chi2; } - Bool_t isCompatibleTrackParamMFT(const TrackParamMFT& TrackParamMFT, Double_t sigma2Cut, Double_t& normChi2) const; - void print() const; void clear(); diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx index 06f058c389d10..6442dc42fb885 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx @@ -298,65 +298,6 @@ void TrackParamMFT::setSmoothCovariances(const TMatrixD& smoothCovariances) } } -//__________________________________________________________________________ -Bool_t TrackParamMFT::isCompatibleTrackParamMFT(const TrackParamMFT& TrackParamMFT, Double_t sigma2Cut, Double_t& chi2) const -{ - /// Return kTRUE if the two set of track parameters are compatible within sigma2Cut - /// Set chi2 to the compatible chi2 value - /// Note that parameter covariances must exist for at least one set of parameters - /// Note also that if parameters are not given at the same Z, results will be meaningless - - // reset chi2 value - chi2 = 0.; - - // ckeck covariance matrices - if (!mCovariances && !TrackParamMFT.mCovariances) { - LOG(ERROR) << "Covariance matrix must exist for at least one set of parameters"; - return kFALSE; - } - - Double_t maxChi2 = 5. * sigma2Cut * sigma2Cut; // 5 degrees of freedom - - // check Z parameters - if (mZ != TrackParamMFT.mZ) { - LOG(WARN) << "Parameters are given at different Z position (" << mZ << " : " << TrackParamMFT.mZ - << "): results are meaningless"; - } - - // compute the parameter residuals - TMatrixD deltaParam(mParameters, TMatrixD::kMinus, TrackParamMFT.mParameters); - - // build the error matrix - TMatrixD weight(5, 5); - if (mCovariances) { - weight += *mCovariances; - } - if (TrackParamMFT.mCovariances) { - weight += *(TrackParamMFT.mCovariances); - } - - // invert the error matrix to get the parameter weights if possible - if (weight.Determinant() == 0) { - LOG(ERROR) << "Cannot compute the compatibility chi2"; - return kFALSE; - } - weight.Invert(); - - // compute the compatibility chi2 - TMatrixD tmp(deltaParam, TMatrixD::kTransposeMult, weight); - TMatrixD mChi2(tmp, TMatrixD::kMult, deltaParam); - - // set chi2 value - chi2 = mChi2(0, 0); - - // check compatibility - if (chi2 > maxChi2) { - return kFALSE; - } - - return kTRUE; -} - //__________________________________________________________________________ void TrackParamMFT::print() const { diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index 5fa74ff4c9c77..e31f54d027e01 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -222,7 +222,6 @@ void Tracker::findTracksLTF(ROframe& event) // keep only tracks fulfilling the minimum length condition if (event.getCurrentTrackLTF().getNPoints() < constants::mft::MinTrackPoints) { - LOG(INFO) << "removing Current TrackLTF as nPointDisks = " << event.getCurrentTrackLTF().getNPoints() << std::endl; event.removeCurrentTrackLTF(); continue; } @@ -233,10 +232,8 @@ void Tracker::findTracksLTF(ROframe& event) } if (nPointDisks < constants::mft::MinTrackPoints) { event.removeCurrentTrackLTF(); - LOG(INFO) << "removing Current TrackLTF as nPointDisks = " << nPointDisks << std::endl; continue; } - LOG(INFO) << "Current TrackLTF as nPointDisks = " << nPointDisks << std::endl; // mark the used clusters //Int_t lay, layMin = 10, layMax = -1; From 1bce686ded9d56516710c402c30b495a8a5d3855 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Mon, 20 Jul 2020 22:36:14 -0300 Subject: [PATCH 0291/1751] Light version of TrackFitter --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 17 +- .../Detectors/ITSMFT/MFT/src/TrackMFT.cxx | 8 - .../ReconstructionDataFormats/TrackFwd.h | 189 ++++--- DataFormats/Reconstruction/src/TrackFwd.cxx | 16 +- Detectors/ITSMFT/MFT/tracking/CMakeLists.txt | 2 + .../tracking/include/MFTTracking/Cluster.h | 2 +- .../tracking/include/MFTTracking/TrackCA.h | 106 ++-- .../include/MFTTracking/TrackFitter2.h | 84 ++++ .../tracking/include/MFTTracking/Tracker.h | 6 +- Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx | 4 +- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 7 +- .../ITSMFT/MFT/tracking/src/TrackFitter2.cxx | 468 ++++++++++++++++++ Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 28 +- .../ITSMFT/MFT/workflow/src/RecoWorkflow.cxx | 2 +- .../MFT/workflow/src/TrackWriterSpec.cxx | 6 +- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 42 +- 16 files changed, 766 insertions(+), 221 deletions(-) create mode 100644 Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h create mode 100644 Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index e4bee98c281fd..044916e678ebf 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -24,20 +24,13 @@ #include "SimulationDataFormat/MCCompLabel.h" #include "ReconstructionDataFormats/TrackFwd.h" - namespace o2 { -namespace itsmft -{ -class Cluster; -} - namespace mft { class TrackMFT : public o2::track::TrackParCovFwd { - using Cluster = o2::itsmft::Cluster; using ClusRefs = o2::dataformats::RangeRefComp<4>; using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; @@ -48,7 +41,7 @@ class TrackMFT : public o2::track::TrackParCovFwd ~TrackMFT() = default; // Track finding method - void setCA(Bool_t method) { mIsCA = method; } + void setCA(Bool_t method = true) { mIsCA = method; } const Bool_t isCA() const { return mIsCA; } const Bool_t isLTF() const { return !mIsCA; } @@ -60,8 +53,6 @@ class TrackMFT : public o2::track::TrackParCovFwd void setChi2QPtQuadtratic(Double_t chi2) { mQuadraticFitChi2 = chi2; } const Double_t getChi2QPtQuadtratic() const { return mQuadraticFitChi2; } - - // Other functions int getNumberOfClusters() const { return mClusRef.getEntries(); } int getFirstClusterEntry() const { return mClusRef.getFirstEntry(); } @@ -149,10 +140,10 @@ class TrackMFTExt : public TrackMFT static constexpr int MaxClusters = 10; using TrackMFT::TrackMFT; // inherit base constructors - void setClusterIndex(int l, int i) + void setClusterIndex(int l, int i, int ncl) { - int ncl = getNumberOfClusters(); - mIndex[ncl++] = (l << 28) + i; + //int ncl = getNumberOfClusters(); + mIndex[ncl] = (l << 28) + i; getClusterRefs().setEntries(ncl); } diff --git a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx index d8175db88b6a4..9815fc55148db 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx +++ b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx @@ -17,12 +17,6 @@ #include "CommonConstants/MathConstants.h" #include "Framework/Logger.h" #include "MathUtils/Utils.h" -#include <TMath.h> -#include "DataFormatsITSMFT/Cluster.h" - -using namespace o2::mft; -using namespace o2::itsmft; -using namespace o2::constants::math; namespace o2 { @@ -32,8 +26,6 @@ namespace mft using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; - - //__________________________________________________________________________ void TrackMFT::setCovariancesLast(const SMatrix55& covariances) { diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index ab89e32263868..624629902c5b4 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -13,7 +13,6 @@ /// /// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - #ifndef ALICEO2_BASE_TRACKFWD #define ALICEO2_BASE_TRACKFWD @@ -33,112 +32,108 @@ using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; class TrackParFwd { // Forward track parameterization, kinematics only. -public: - TrackParFwd() = default; - ~TrackParFwd() = default; - - TrackParFwd(const TrackParFwd& tp) = default; - TrackParFwd& operator=(const TrackParFwd& tp) = default; - TrackParFwd(TrackParFwd&&) = delete; - TrackParFwd& operator=(TrackParFwd&&) = delete; - - /// return Z coordinate (cm) - Double_t getZ() const { return mZ; } - /// set Z coordinate (cm) - void setZ(Double_t z) { mZ = z; } - Double_t getX() const { return mParameters(0); } - void setX(Double_t x) { mParameters(0) = x; } - - Double_t getY() const { return mParameters(1); } - void setY(Double_t y) { mParameters(1) = y; } - - void setPhi(Double_t phi) { mParameters(2) = phi; } - Double_t getPhi() const { return mParameters(2); } - - void setTanl(Double_t tanl) { mParameters(3) = tanl; } - Double_t getTanl() const { return mParameters(3); } - - void setInvQPt(Double_t invqpt) { mParameters(4) = invqpt; } - Double_t getInvQPt() const { return mParameters(4); } // return Inverse charged pt - Double_t getPt() const { return TMath::Abs(1.f / mParameters(4)); } - Double_t getInvPt() const { return TMath::Abs(mParameters(4)); } - - Double_t getPx() const { return TMath::Cos(getPhi()) * getPt(); } // return px - Double_t getInvPx() const { return 1. / getPx(); } // return invpx - - Double_t getPy() const { return TMath::Sin(getPhi()) * getPt(); } // return py - Double_t getInvPy() const { return 1. / getPx(); } // return invpy - - Double_t getPz() const { return getTanl() * getPt(); } // return pz - Double_t getInvPz() const { return 1. / getPz(); } // return invpz - - Double_t getP() const { return getPt() * TMath::Sqrt(1. + getTanl() * getTanl()); } // return total momentum - Double_t getInverseMomentum() const { return 1.f / getP(); } - - Double_t getEta() const { return -TMath::Log(TMath::Tan((TMath::PiOver2() - TMath::ATan(getTanl())) / 2)); } // return total momentum - - /// return the charge (assumed forward motion) - Double_t getCharge() const { return TMath::Sign(1., mParameters(4)); } - /// set the charge (assumed forward motion) - void setCharge(Double_t charge) - { - if (charge * mParameters(4) < 0.) - mParameters(4) *= -1.; - } - - /// return track parameters - const SMatrix5& getParameters() const { return mParameters; } - /// set track parameters - void setParameters(const SMatrix5& parameters) { mParameters = parameters; } - /// add track parameters - void addParameters(const SMatrix5& parameters) { mParameters += parameters; } - - /// get pointer to associated cluster - //const Cluster* getClusterPtr() const { return mClusterPtr; } - /// set pointer to associated cluster - //void setClusterPtr(const Cluster* cluster) { mClusterPtr = cluster; } - - - /// return the chi2 of the track when the associated cluster was attached - Double_t getTrackChi2() const { return mTrackChi2; } - /// set the chi2 of the track when the associated cluster was attached - void setTrackChi2(Double_t chi2) { mTrackChi2 = chi2; } - - void linearExtrapToZ(double zEnd); - void quadraticExtrapToZ(double zEnd, double zField); - void helixExtrapToZ(double zEnd, double zField); - -private: - Double_t mZ = 0.; ///< Z coordinate (cm) - - /// Track parameters ordered as follow: <pre> - /// X = X coordinate (cm) - /// Y = Y coordinate (cm) - /// PHI = azimutal angle - /// TANL = tangent of \lambda (dip angle) - /// INVQPT = Inverse transverse momentum (GeV/c ** -1) times charge (assumed forward motion) </pre> - SMatrix5 mParameters{}; ///< \brief Track parameters - //const Cluster* mClusterPtr = nullptr; ///< Pointer to the associated cluster if any - Double_t mTrackChi2 = 0.; ///< Chi2 of the track when the associated cluster was attached - - ClassDefNV(TrackParFwd, 1); - + public: + TrackParFwd() = default; + ~TrackParFwd() = default; + + TrackParFwd(const TrackParFwd& tp) = default; + TrackParFwd& operator=(const TrackParFwd& tp) = default; + TrackParFwd(TrackParFwd&&) = delete; + TrackParFwd& operator=(TrackParFwd&&) = delete; + + /// return Z coordinate (cm) + Double_t getZ() const { return mZ; } + /// set Z coordinate (cm) + void setZ(Double_t z) { mZ = z; } + Double_t getX() const { return mParameters(0); } + void setX(Double_t x) { mParameters(0) = x; } + + Double_t getY() const { return mParameters(1); } + void setY(Double_t y) { mParameters(1) = y; } + + void setPhi(Double_t phi) { mParameters(2) = phi; } + Double_t getPhi() const { return mParameters(2); } + + void setTanl(Double_t tanl) { mParameters(3) = tanl; } + Double_t getTanl() const { return mParameters(3); } + + void setInvQPt(Double_t invqpt) { mParameters(4) = invqpt; } + Double_t getInvQPt() const { return mParameters(4); } // return Inverse charged pt + Double_t getPt() const { return TMath::Abs(1.f / mParameters(4)); } + Double_t getInvPt() const { return TMath::Abs(mParameters(4)); } + + Double_t getPx() const { return TMath::Cos(getPhi()) * getPt(); } // return px + Double_t getInvPx() const { return 1. / getPx(); } // return invpx + + Double_t getPy() const { return TMath::Sin(getPhi()) * getPt(); } // return py + Double_t getInvPy() const { return 1. / getPx(); } // return invpy + + Double_t getPz() const { return getTanl() * getPt(); } // return pz + Double_t getInvPz() const { return 1. / getPz(); } // return invpz + + Double_t getP() const { return getPt() * TMath::Sqrt(1. + getTanl() * getTanl()); } // return total momentum + Double_t getInverseMomentum() const { return 1.f / getP(); } + + Double_t getEta() const { return -TMath::Log(TMath::Tan((TMath::PiOver2() - TMath::ATan(getTanl())) / 2)); } // return total momentum + + /// return the charge (assumed forward motion) + Double_t getCharge() const { return TMath::Sign(1., mParameters(4)); } + /// set the charge (assumed forward motion) + void setCharge(Double_t charge) + { + if (charge * mParameters(4) < 0.) + mParameters(4) *= -1.; + } + + /// return track parameters + const SMatrix5& getParameters() const { return mParameters; } + /// set track parameters + void setParameters(const SMatrix5& parameters) { mParameters = parameters; } + /// add track parameters + void addParameters(const SMatrix5& parameters) { mParameters += parameters; } + + /// get pointer to associated cluster + //const Cluster* getClusterPtr() const { return mClusterPtr; } + /// set pointer to associated cluster + //void setClusterPtr(const Cluster* cluster) { mClusterPtr = cluster; } + + /// return the chi2 of the track when the associated cluster was attached + Double_t getTrackChi2() const { return mTrackChi2; } + /// set the chi2 of the track when the associated cluster was attached + void setTrackChi2(Double_t chi2) { mTrackChi2 = chi2; } + + void linearExtrapToZ(double zEnd); + void quadraticExtrapToZ(double zEnd, double zField); + void helixExtrapToZ(double zEnd, double zField); + + private: + Double_t mZ = 0.; ///< Z coordinate (cm) + + /// Track parameters ordered as follow: <pre> + /// X = X coordinate (cm) + /// Y = Y coordinate (cm) + /// PHI = azimutal angle + /// TANL = tangent of \lambda (dip angle) + /// INVQPT = Inverse transverse momentum (GeV/c ** -1) times charge (assumed forward motion) </pre> + SMatrix5 mParameters{}; ///< \brief Track parameters + //const Cluster* mClusterPtr = nullptr; ///< Pointer to the associated cluster if any + Double_t mTrackChi2 = 0.; ///< Chi2 of the track when the associated cluster was attached + + ClassDefNV(TrackParFwd, 1); }; class TrackParCovFwd : public TrackParFwd { // Forward track+error parameterization - public: + public: using TrackParFwd::TrackParFwd; // inherit base constructors TrackParCovFwd() = default; ~TrackParCovFwd() = default; - TrackParCovFwd(const TrackParCovFwd& tpf) = default; TrackParCovFwd& operator=(const TrackParCovFwd& tpf) = default; TrackParCovFwd(const Double_t z, const SMatrix5 parameters, const SMatrix55 covariances, const Double_t chi2); - const SMatrix55& getCovariances() const; void setCovariances(const SMatrix55& covariances); void deleteCovariances(); @@ -154,17 +149,15 @@ class TrackParCovFwd : public TrackParFwd void helixExtrapToZCov(double zEnd, double zField); void addMCSEffect(double dZ, double x0, double zField); -private: - + private: /// Covariance matrix of track parameters, ordered as follows: <pre> /// <X,X> <Y,X> <PHI,X> <TANL,X> <INVQPT,X> /// <X,Y> <Y,Y> <PHI,Y> <TANL,Y> <INVQPT,Y> /// <X,PHI> <Y,PHI> <PHI,PHI> <TANL,PHI> <INVQPT,PHI> /// <X,TANL> <Y,TANL> <PHI,TANL> <TANL,TANL> <INVQPT,TANL> /// <X,INVQPT> <Y,INVQPT> <PHI,INVQPT> <TANL,INVQPT> <INVQPT,INVQPT> </pre> - SMatrix55 mCovariances{}; ///< \brief Covariance matrix of track parameters + SMatrix55 mCovariances{}; ///< \brief Covariance matrix of track parameters ClassDefNV(TrackParCovFwd, 1); - }; } // namespace track diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 9fc10792f974e..dad57552b6846 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -11,7 +11,6 @@ #include "ReconstructionDataFormats/TrackFwd.h" #include "Math/MatrixFunctions.h" - namespace o2 { namespace track @@ -38,10 +37,9 @@ const SMatrix55& TrackParCovFwd::getCovariances() const void TrackParCovFwd::setCovariances(const SMatrix55& covariances) { /// Set the covariance matrix - mCovariances = covariances; + mCovariances = covariances; } - //__________________________________________________________________________ void TrackParCovFwd::deleteCovariances() { @@ -62,8 +60,6 @@ TrackParCovFwd& TrackParCovFwd::operator=(const TrackParCovFwd& tp) } */ - - /* //_________________________________________________________________________ TrackParCovFwd::TrackParCovFwd(const TrackParCovFwd& tp) @@ -74,7 +70,6 @@ TrackParCovFwd::TrackParCovFwd(const TrackParCovFwd& tp) } */ - //__________________________________________________________________________ void TrackParFwd::linearExtrapToZ(double zEnd) { @@ -133,7 +128,7 @@ void TrackParCovFwd::linearExtrapToZCov(double zEnd) jacob(1, 3) = -m * sinphi0; // Extrapolate track parameter covariances to "zEnd" - setCovariances(ROOT::Math::Similarity(jacob,mCovariances)); + setCovariances(ROOT::Math::Similarity(jacob, mCovariances)); } //__________________________________________________________________________ @@ -214,8 +209,7 @@ void TrackParCovFwd::quadraticExtrapToZCov(double zEnd, double zField) jacob(2, 4) = -Hz * k * n; // Extrapolate track parameter covariances to "zEnd" - setCovariances(ROOT::Math::Similarity(jacob,mCovariances)); - + setCovariances(ROOT::Math::Similarity(jacob, mCovariances)); } //__________________________________________________________________________ @@ -322,8 +316,7 @@ void TrackParCovFwd::helixExtrapToZCov(double zEnd, double zField) jacob(2, 4) = -Hz * k * n; // Extrapolate track parameter covariances to "zEnd" - setCovariances(ROOT::Math::Similarity(jacob,mCovariances)); - + setCovariances(ROOT::Math::Similarity(jacob, mCovariances)); } //__________________________________________________________________________ @@ -423,7 +416,6 @@ void TrackParCovFwd::addMCSEffect(double dZ, double x0, double zField) newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; } - // Set new covariances setCovariances(newParamCov); } diff --git a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt index 118ab44c59117..abdd6f764be2b 100644 --- a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt @@ -16,6 +16,7 @@ o2_add_library(MFTTracking src/Cluster.cxx src/IOUtils.cxx src/TrackFitter.cxx + src/TrackFitter2.cxx src/FitterTrackMFT.cxx src/TrackExtrap.cxx src/MFTTrackingParam.cxx @@ -30,6 +31,7 @@ o2_target_root_dictionary(MFTTracking HEADERS include/MFTTracking/TrackCA.h HEADERS include/MFTTracking/TrackFitter.h HEADERS include/MFTTracking/TrackExtrap.h + HEADERS include/MFTTracking/TrackFitter2.h HEADERS include/MFTTracking/FitterTrackMFT.h HEADERS include/MFTTracking/TrackParamMFT.h HEADERS include/MFTTracking/MFTTrackingParam.h diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index f42e86fd870bd..6cb7394159bd7 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -27,7 +27,7 @@ namespace mft struct Cluster : public o2::BaseCluster<float> { Cluster(const Float_t x, const Float_t y, const Float_t z, const Float_t phi, const Float_t r, const Int_t idx, const Int_t bin) - : BaseCluster(1 ,x, y, z), + : BaseCluster(1, x, y, z), phiCoordinate{phi}, rCoordinate{r}, clusterId{idx}, diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index 20537e2dad905..a873274f16e5f 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -26,7 +26,31 @@ namespace o2 namespace mft { -class TrackCA : public TrackMFT +class TrackLTF : public TrackMFTExt +{ + public: + const Int_t getNPoints() const { return mNPoints; } + const std::array<Float_t, constants::mft::LayersNumber>& getXCoordinates() const { return mX; } + const std::array<Float_t, constants::mft::LayersNumber>& getYCoordinates() const { return mY; } + const std::array<Float_t, constants::mft::LayersNumber>& getZCoordinates() const { return mZ; } + const std::array<Int_t, constants::mft::LayersNumber>& getLayers() const { return mLayer; } + const std::array<Int_t, constants::mft::LayersNumber>& getClustersId() const { return mClusterId; } + const std::array<MCCompLabel, constants::mft::LayersNumber>& getMCCompLabels() const { return mMCCompLabels; } + void setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); + + protected: + Int_t mNPoints{0}; + + private: + std::array<Float_t, constants::mft::LayersNumber> mX = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; + std::array<Float_t, constants::mft::LayersNumber> mY = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; + std::array<Float_t, constants::mft::LayersNumber> mZ = {-120., -120., -120., -120., -120., -120., -120., -120., -120., -120.}; + std::array<Int_t, constants::mft::LayersNumber> mLayer; + std::array<Int_t, constants::mft::LayersNumber> mClusterId; + std::array<MCCompLabel, constants::mft::LayersNumber> mMCCompLabels; +}; + +class TrackCA : public TrackLTF { public: TrackCA() = default; @@ -36,36 +60,23 @@ class TrackCA : public TrackMFT const Int_t getNCells() const; void setRoadId(const Int_t rid) { mRoadId = rid; } const Int_t getRoadId() const; - void setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); - const Int_t getNPoints() const { return mNPoints; } void setChiSquareZX(const Float_t chisq) { mChiSquareZX = chisq; } void setChiSquareZY(const Float_t chisq) { mChiSquareZY = chisq; } const Float_t getChiSquareZX() const { return mChiSquareZX; } const Float_t getChiSquareZY() const { return mChiSquareZY; } - const std::array<Float_t, constants::mft::LayersNumber>& getXCoordinates() const { return mX; } - const std::array<Float_t, constants::mft::LayersNumber>& getYCoordinates() const { return mY; } - const std::array<Float_t, constants::mft::LayersNumber>& getZCoordinates() const { return mZ; } - const std::array<Int_t, constants::mft::LayersNumber>& getLayers() const { return mLayer; } - const std::array<Int_t, constants::mft::LayersNumber>& getClustersId() const { return mClusterId; } + const std::array<Int_t, constants::mft::LayersNumber>& getCellsLayer() const { return mCellLayer; } const std::array<Int_t, constants::mft::LayersNumber>& getCellsId() const { return mCellId; } - const std::array<MCCompLabel, constants::mft::LayersNumber>& getMCCompLabels() const { return mMCCompLabels; } private: - Int_t mNPoints{0}; Int_t mNCells{0}; Int_t mRoadId{-1}; Float_t mChiSquareZX{0.}; Float_t mChiSquareZY{0.}; - std::array<Float_t, constants::mft::LayersNumber> mX = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; - std::array<Float_t, constants::mft::LayersNumber> mY = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; - std::array<Float_t, constants::mft::LayersNumber> mZ = {-120., -120., -120., -120., -120., -120., -120., -120., -120., -120.}; - std::array<Int_t, constants::mft::LayersNumber> mLayer; - std::array<Int_t, constants::mft::LayersNumber> mClusterId; + std::array<Int_t, constants::mft::LayersNumber> mCellLayer; std::array<Int_t, constants::mft::LayersNumber> mCellId; - std::array<MCCompLabel, constants::mft::LayersNumber> mMCCompLabels; - ClassDefNV(TrackCA, 1); + ClassDefNV(TrackCA, 2); }; inline void TrackCA::addCell(const Int_t layer, const Int_t cellId) @@ -97,55 +108,6 @@ inline const Int_t TrackCA::getRoadId() const return mRoadId; } -inline void TrackCA::setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint) -{ - if (newPoint) { - if (mNPoints == constants::mft::LayersNumber) { - LOG(WARN) << "MFT TrackLTF Overflow"; - return; - } - mX[mNPoints] = x; - mY[mNPoints] = y; - mZ[mNPoints] = z; - mLayer[mNPoints] = layer; - mClusterId[mNPoints] = clusterId; - mMCCompLabels[mNPoints] = label; - mNPoints++; - } else { - mX[mNPoints] = x; - mY[mNPoints] = y; - mZ[mNPoints] = z; - mLayer[mNPoints] = layer; - mClusterId[mNPoints] = clusterId; - mMCCompLabels[mNPoints] = label; - } -} - -class TrackLTF final -{ - public: - TrackLTF() = default; - ~TrackLTF() = default; - void setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); - const Int_t getNPoints() const { return mNPoints; } - const std::array<Float_t, constants::mft::LayersNumber>& getXCoordinates() const { return mX; } - const std::array<Float_t, constants::mft::LayersNumber>& getYCoordinates() const { return mY; } - const std::array<Float_t, constants::mft::LayersNumber>& getZCoordinates() const { return mZ; } - const std::array<Int_t, constants::mft::LayersNumber>& getLayers() const { return mLayer; } - const std::array<Int_t, constants::mft::LayersNumber>& getClustersId() const { return mClusterId; } - const std::array<MCCompLabel, constants::mft::LayersNumber>& getMCCompLabels() const { return mMCCompLabels; } - - private: - Int_t mNPoints = 0; - std::array<Float_t, constants::mft::LayersNumber> mX = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; - std::array<Float_t, constants::mft::LayersNumber> mY = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; - std::array<Float_t, constants::mft::LayersNumber> mZ = {-120., -120., -120., -120., -120., -120., -120., -120., -120., -120.}; - std::array<Int_t, constants::mft::LayersNumber> mLayer; - std::array<Int_t, constants::mft::LayersNumber> mClusterId; - std::array<MCCompLabel, constants::mft::LayersNumber> mMCCompLabels; - ClassDefNV(TrackLTF, 1); -}; - inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint) { if (newPoint) { @@ -159,6 +121,9 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z mLayer[mNPoints] = layer; mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; + //std::cout << "setClusterIndex(layer, clusterId) = " << layer << " , " << clusterId << " newpoint" << std::endl; + setClusterIndex(layer, clusterId, mNPoints); + mNPoints++; } else { mX[mNPoints] = x; @@ -167,9 +132,9 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z mLayer[mNPoints] = layer; mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; + //std::cout << "setClusterIndex(layer, clusterId) = " << layer << " , " << clusterId << std::endl; + setClusterIndex(layer, clusterId, mNPoints); } - LOG(INFO) << "MFT TrackLTF setPoint mNPoints = " << mNPoints << std::endl; - } } // namespace mft @@ -180,6 +145,11 @@ struct is_messageable; template <> struct is_messageable<o2::mft::TrackCA> : std::true_type { }; +template <typename T> +struct is_messageable; +template <> +struct is_messageable<o2::mft::TrackLTF> : std::true_type { +}; } // namespace framework } // namespace o2 #endif /* O2_MFT_TRACKCA_H_ */ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h new file mode 100644 index 0000000000000..ed8344d394da5 --- /dev/null +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h @@ -0,0 +1,84 @@ +// 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 TrackFitter.h +/// \brief Definition of a class to fit a track to a set of clusters +/// +/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS + +#ifndef ALICEO2_MFT_TRACKFITTER2_H_ +#define ALICEO2_MFT_TRACKFITTER2_H_ + +#include "MFTTracking/Cluster.h" +#include "MFTTracking/TrackCA.h" +#include "MFTTracking/FitterTrackMFT.h" +#include "MFTTracking/TrackParamMFT.h" +#include "MFTTracking/TrackExtrap.h" +#include "MFTTracking/MFTTrackingParam.h" +#include "DataFormatsMFT/TrackMFT.h" + +#include <TLinearFitter.h> +#include <list> + +namespace o2 +{ +namespace mft +{ + +/// Class to fit a track to a set of clusters +class TrackFitter2 +{ + + using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; + using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; + + public: + TrackFitter2() = default; + ~TrackFitter2() = default; + + TrackFitter2(const TrackFitter2&) = delete; + TrackFitter2& operator=(const TrackFitter2&) = delete; + TrackFitter2(TrackFitter2&&) = delete; + TrackFitter2& operator=(TrackFitter2&&) = delete; + + void setBz(float bZ); + + bool fit(TrackLTF& track); + + bool fit(FitterTrackMFT& track, std::list<TrackParamMFT>::reverse_iterator* itStartingParam = nullptr); + + bool runKalmanFilter(TrackLTF& track, int cluster); + + /// Return the maximum chi2 above which the track can be considered as abnormal + static constexpr double getMaxChi2() { return SMaxChi2; } + + private: + bool initTrack(TrackLTF& track); + bool addCluster(TrackLTF& track, int cluster); + + Float_t mBZField; // kiloGauss. + static constexpr double SMaxChi2 = 2.e10; ///< maximum chi2 above which the track can be considered as abnormal + /// default layer thickness in X0 for reconstruction //FIXME: set values for the MFT + static constexpr double SLayerThicknessInX0[10] = {0.065, 0.065, 0.075, 0.075, 0.035, + 0.035, 0.035, 0.035, 0.035, 0.035}; + + bool mFieldON = true; + o2::mft::TrackExtrap mTrackExtrap; +}; + +// Functions to estimate momentum and charge from track curvature +Double_t invQPtFromParabola2(const FitterTrackMFT& track, double bFieldZ, Double_t& chi2); +Double_t invQPtFromParabola2(const TrackLTF& track, double bFieldZ, Double_t& chi2); +Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2); + +} // namespace mft +} // namespace o2 + +#endif // ALICEO2_MFT_TrackFitter2_H_ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index d92bde4e7654c..3a460d4d48006 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -16,7 +16,7 @@ #define O2_MFT_TRACKER_H_ #include "MFTTracking/ROframe.h" -#include "MFTTracking/TrackFitter.h" +#include "MFTTracking/TrackFitter2.h" #include "MFTTracking/Cluster.h" #include "MathUtils/Utils.h" @@ -24,6 +24,7 @@ #include "DataFormatsMFT/TrackMFT.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "DataFormatsParameters/GRPObject.h" namespace o2 { @@ -64,6 +65,9 @@ class Tracker void runBackwardInRoad(ROframe&); void updateCellStatusInRoad(Road&); + bool fitTracks(ROframe&); + std::unique_ptr<o2::mft::TrackFitter2> mTrackFitter = nullptr; + const Int_t isDiskFace(Int_t layer) const; const Float_t getDistanceToSeed(const Cluster&, const Cluster&, const Cluster&) const; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx index 6517f51489c88..004d7522232b8 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx @@ -23,7 +23,7 @@ namespace mft { Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t index) - : BaseCluster(1 , x, y, z), + : BaseCluster(1, x, y, z), phiCoordinate{0.}, rCoordinate{0.}, clusterId{index}, @@ -36,7 +36,7 @@ Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t } Cluster::Cluster(const Int_t layerIndex, const Cluster& other) - : BaseCluster(1 , other.getXYZ()), + : BaseCluster(1, other.getXYZ()), phiCoordinate{0.}, rCoordinate{0.}, clusterId{other.clusterId}, diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 17e3e84a51855..380b2bb3d47d7 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -262,7 +262,7 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& if (startingParam.getZ() < LayerZPosition[layer] + .3 & startingParam.getZ() > LayerZPosition[layer] - .3) startingLayerID = layer; for (auto layer = 10; layer--;) - if (cl.getZ()<LayerZPosition[layer] + .3 & cl.getZ()> LayerZPosition[layer] - .3) + if (cl.getZ() < LayerZPosition[layer] + .3 & cl.getZ() > LayerZPosition[layer] - .3) newLayerID = layer; // Number of disks crossed by this tracklet int NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; @@ -492,7 +492,7 @@ Double_t invQPtFromParabola(const FitterTrackMFT& track, Double_t bFieldZ, Doubl auto theta = -TMath::ATan2(deltay, deltax); auto costheta = TMath::Cos(theta), sintheta = TMath::Sin(theta); - bool verbose = false; + bool verbose = true; if (verbose) { std::cout << "First and last cluster X,Y => " << track.first().getX() << " , " << track.first().getY() << " / " << track.rbegin()->getX() << " , " << track.rbegin()->getY() << std::endl; std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) " << std::endl; @@ -507,7 +507,8 @@ Double_t invQPtFromParabola(const FitterTrackMFT& track, Double_t bFieldZ, Doubl auto y_0 = trackparam->getClusterPtr()->getY() - y_m; x[n] = x_0 * costheta - y_0 * sintheta; y[n] = x_0 * sintheta + y_0 * costheta; - //std::cout << " adding rotated point to fit at z = " << trackparam->getClusterPtr()->getZ() << " (" << x[n] << "," << y[n] << ") "<< std::endl; + if (verbose) + std::cout << " adding rotated point to fit at z = " << trackparam->getClusterPtr()->getZ() << " (" << x[n] << "," << y[n] << ") " << std::endl; n++; } diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx new file mode 100644 index 0000000000000..eb38cb1b70153 --- /dev/null +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx @@ -0,0 +1,468 @@ +// 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 TrackFitter.cxx +/// \brief Implementation of a class to fit a track to a set of clusters +/// +/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS + +#include "MFTBase/Constants.h" +#include "MFTTracking/TrackFitter2.h" +#include "MFTTracking/TrackCA.h" +#include "MFTTracking/TrackExtrap.h" +#include "MFTTracking/Cluster.h" +#include "DataFormatsMFT/TrackMFT.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "ITSMFTReconstruction/ChipMappingMFT.h" +#include <stdexcept> +#include <TMath.h> +#include <TMatrixD.h> +#include <TF1.h> +#include <TF2.h> +#include "CommonConstants/MathConstants.h" +#include "MathUtils/MathBase.h" +#include "MathUtils/Utils.h" + +using o2::math_utils::math_base::fitGaus; + +namespace o2 +{ +namespace mft +{ + +//_________________________________________________________________________________________________ +void TrackFitter2::setBz(float bZ) +{ + auto& mftTrackingParam = MFTTrackingParam::Instance(); + + /// Set the magnetic field for the MFT + mBZField = bZ; + mTrackExtrap.setBz(bZ); + + if (mftTrackingParam.verbose) { + LOG(INFO) << "Setting Fitter field = " << bZ; + } +} + +//_________________________________________________________________________________________________ +bool TrackFitter2::fit(TrackLTF& track) +{ + + /// Fit a track to its attached clusters + /// Fit the entire track or only the part upstream itStartingParam + /// Returns false in case of failure + + auto& mftTrackingParam = MFTTrackingParam::Instance(); + auto nClusters = track.getNPoints(); + + if (mftTrackingParam.verbose) { + std::cout << "\n ***************************** Start Fitting new track ***************************** \n"; + std::cout << "N Clusters = " << nClusters << std::endl; + } + + initTrack(track); + + if (mftTrackingParam.verbose) { + std::cout << "Seed covariances: \n"; + track.getCovariances().Print(std::cout); + std::cout << std::endl; + } + + // recusively add the upstream clusters and update the track parameters + nClusters--; + while (nClusters-- > 0) { + if (!addCluster(track, nClusters)) { + return false; + } + } + + if (mftTrackingParam.verbose) { + // std::cout << "Track covariances:"; + // trac->getCovariances().Print(); + std::cout << "Track Chi2 = " << track.getTrackChi2() << std::endl; + std::cout << " ***************************** Done fitting *****************************\n"; + } + + return true; +} + +//_________________________________________________________________________________________________ +bool TrackFitter2::initTrack(TrackLTF& track) +{ + // initialize the starting track parameters and cluster + double chi2invqptquad; + double invpqtquad; + auto nPoints = track.getNPoints(); + invpqtquad = invQPtFromParabola2(track, mBZField, chi2invqptquad); + track.setInvQPtQuadtratic(invpqtquad); + track.setChi2QPtQuadtratic(chi2invqptquad); + track.setInvQPt(invpqtquad); + + /// Compute the initial track parameters at the z position of the last cluster (cl) + /// The covariance matrix is computed such that the last cluster is the only constraint + /// (by assigning an infinite dispersion to the other cluster) + /// These parameters are the seed for the Kalman filter + + auto& mftTrackingParam = MFTTrackingParam::Instance(); + + // compute the track parameters at the last cluster + double x0 = track.getXCoordinates()[nPoints - 1]; + double y0 = track.getYCoordinates()[nPoints - 1]; + double z0 = track.getZCoordinates()[nPoints - 1]; + double pt = TMath::Sqrt(x0 * x0 + y0 * y0); + double pz = z0; + double phi0 = TMath::ATan2(y0, x0); + double tanl = pz / pt; + double r0sq = x0 * x0 + y0 * y0; + double r0cu = r0sq * TMath::Sqrt(r0sq); + double invr0sq = 1.0 / r0sq; + double invr0cu = 1.0 / r0cu; + double sigmax0sq = 5e-4; + double sigmay0sq = 5.43e-4; + double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond + double sigmaboost = mftTrackingParam.sigmaboost; // Boost q/pt seed covariances + double seedH_k = mftTrackingParam.seedH_k; // SeedH constant + + track.setX(x0); + track.setY(y0); + track.setZ(z0); + track.setPhi(phi0); + track.setTanl(tanl); + + // Configure the track seed + switch (mftTrackingParam.seed) { + case AB: + if (mftTrackingParam.verbose) + std::cout << " Init track with Seed A / B; sigmaboost = " << sigmaboost << ".\n"; + track.setInvQPt(1.0 / pt); // Seeds A & B + break; + case CE: + if (mftTrackingParam.verbose) + std::cout << " Init track with Seed C / E; sigmaboost = " << sigmaboost << ".\n"; + track.setInvQPt(std::copysign(1.0, track.getInvQPt()) / pt); // Seeds C & E + break; + case DH: + if (mftTrackingParam.verbose) + std::cout << " Init track with Seed H; (k = " << seedH_k << "); sigmaboost = " << sigmaboost << ".\n"; + track.setInvQPt(track.getInvQPt() / seedH_k); // SeedH + break; + default: + if (mftTrackingParam.verbose) + std::cout << " Init track with Seed D.\n"; + break; + } + if (mftTrackingParam.verbose) { + auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; + std::cout << "Track Model: " << model << std::endl; + std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + } + + // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) + SMatrix55 lastParamCov; + //lastParamCov.Zero(); + lastParamCov(0, 0) = sigmax0sq; // <X,X> + lastParamCov(0, 1) = 0; // <Y,X> + lastParamCov(0, 2) = sigmaboost * -sigmax0sq * y0 * invr0sq; // <PHI,X> + lastParamCov(0, 3) = sigmaboost * -z0 * sigmax0sq * x0 * invr0cu; // <TANL,X> + lastParamCov(0, 4) = sigmaboost * -x0 * sigmax0sq * invr0cu; // <INVQPT,X> + + lastParamCov(1, 1) = sigmay0sq; // <Y,Y> + lastParamCov(1, 2) = sigmaboost * sigmay0sq * x0 * invr0sq; // <PHI,Y> + lastParamCov(1, 3) = sigmaboost * -z0 * sigmay0sq * y0 * invr0cu; // <TANL,Y> + lastParamCov(1, 4) = sigmaboost * y0 * sigmay0sq * invr0cu; //1e-2; // <INVQPT,Y> + + lastParamCov(2, 2) = sigmaboost * (sigmax0sq * y0 * y0 + sigmay0sq * x0 * x0) * invr0sq * invr0sq; // <PHI,PHI> + lastParamCov(2, 3) = sigmaboost * z0 * x0 * y0 * (sigmax0sq - sigmay0sq) * invr0sq * invr0cu; // <TANL,PHI> + lastParamCov(2, 4) = sigmaboost * y0 * x0 * invr0cu * invr0sq * (sigmax0sq - sigmay0sq); // <INVQPT,PHI> + + lastParamCov(3, 3) = sigmaboost * z0 * z0 * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0) * invr0cu * invr0cu + sigmaDeltaZsq * invr0sq; // <TANL,TANL> + lastParamCov(3, 4) = sigmaboost * z0 * invr0cu * invr0cu * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0); // <INVQPT,TANL> + + lastParamCov(4, 4) = sigmaboost * sigmaboost * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0) * invr0cu * invr0cu; // <INVQPT,INVQPT> + + lastParamCov(1, 0) = lastParamCov(0, 1); // + lastParamCov(2, 0) = lastParamCov(0, 2); // + lastParamCov(2, 1) = lastParamCov(1, 2); // + lastParamCov(3, 0) = lastParamCov(0, 3); // + lastParamCov(3, 1) = lastParamCov(1, 3); // + lastParamCov(3, 2) = lastParamCov(2, 3); // + lastParamCov(4, 0) = lastParamCov(0, 4); // + lastParamCov(4, 1) = lastParamCov(1, 4); // + lastParamCov(4, 2) = lastParamCov(2, 4); // + lastParamCov(4, 3) = lastParamCov(3, 4); // + + track.setCovariances(lastParamCov); + track.setTrackChi2(0.); + + return true; +} + +bool TrackFitter2::addCluster(TrackLTF& track, int cluster) +{ + /// Extrapolate the starting track parameters to the z position of the new cluster + /// accounting for MCS dispersion in the current layer and the other(s) crossed + /// Recompute the parameters adding the cluster constraint with the Kalman filter + /// Returns false in case of failure + + auto& mftTrackingParam = MFTTrackingParam::Instance(); + const auto& clx = track.getXCoordinates()[cluster]; + const auto& cly = track.getYCoordinates()[cluster]; + const auto& clz = track.getZCoordinates()[cluster]; + + if (track.getZ() >= clz) { + LOG(INFO) << "AddCluster ERROR: The new cluster must be upstream! Bug on TrackFinder. "; + LOG(INFO) << "track.getZ() = " << track.getZ() << " ; newClusterZ = " << clz; + + return false; + } + if (mftTrackingParam.verbose) + std::cout << "addCluster: X = " << clx << " Y = " << cly << " Z = " << clz << " nCluster = " << cluster << std::endl; + + // add MCS effects for the new cluster + using o2::mft::constants::LayerZPosition; + int startingLayerID, newLayerID; + + double dZ = TMath::Abs(clz - track.getZ()); + //LayerID of each cluster from ZPosition // TODO: Use ChipMapping + for (auto layer = 10; layer--;) + if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3) + startingLayerID = layer; + for (auto layer = 10; layer--;) + if (clz<LayerZPosition[layer] + .3 & clz> LayerZPosition[layer] - .3) + newLayerID = layer; + // Number of disks crossed by this tracklet + int NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; + + double MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0; + if (mftTrackingParam.verbose) { + std::cout << "startingLayerID = " << startingLayerID << " ; " + << "newLayerID = " << newLayerID << " ; "; + std::cout << "cl.getZ() = " << clz << " ; "; + std::cout << "startingParam.getZ() = " << track.getZ() << " ; "; + std::cout << "NDisksMS = " << NDisksMS << std::endl; + } + /* + // Add MCS effects + if ((NDisksMS * MFTDiskThicknessInX0) != 0) + mTrackExtrap.addMCSEffect(¶m, -1, NDisksMS * MFTDiskThicknessInX0); +*/ + + if (mftTrackingParam.verbose) + std::cout << " BeforeExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + + // extrapolate to the z position of the new cluster + track.helixExtrapToZCov(clz, mBZField); + + if (mftTrackingParam.verbose) + std::cout << " AfterExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + + // recompute the parameters + + if (runKalmanFilter(track, cluster)) { + if (mftTrackingParam.verbose) { + std::cout << " New Cluster: X = " << clx << " Y = " << cly << " Z = " << clz << std::endl; + std::cout << " AfterKalman: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + std::cout << std::endl; + // Outputs track covariance matrix: + // param.getCovariances().Print(); + } + return true; + } + return false; +} + +//_________________________________________________________________________________________________ +bool TrackFitter2::runKalmanFilter(TrackLTF& track, int cluster) +{ + /// Compute the new track parameters including the attached cluster with the Kalman filter + /// The current parameters are supposed to have been extrapolated to the cluster z position + /// Retruns false in case of failure + + // get propagated track parameters (p) + auto param = track.getParameters(); + + // get new cluster parameters (m) + SMatrix5 clusterParam; + clusterParam(0) = track.getXCoordinates()[cluster]; + clusterParam(1) = track.getYCoordinates()[cluster]; + + // compute the actual parameter weight (W) + SMatrix55 paramWeight(track.getCovariances()); + if (!(paramWeight.Invert())) { + LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; + return false; + } + + // compute the new cluster weight (U) + SMatrix55 clusterWeight; + clusterWeight(0, 0) = 1. / 5e-4; // FIXME + clusterWeight(1, 1) = 1. / 5.43e-4; + + // compute the new parameters covariance matrix ((W+U)^-1) + SMatrix55 newParamCov(paramWeight + clusterWeight); + if (!newParamCov.Invert()) { + LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; + return false; + } + track.setCovariances(newParamCov); + + // compute the new parameters: (p' = ((W+U)^-1)U(m-p) + p) + // Parameters increment: p' - p = ((W+U)^-1)U(m-p) + SMatrix5 predict_residuals(clusterParam - param); // m-p -> residuals of prediction + SMatrix5 tmp(clusterWeight * predict_residuals); // U(m-p) + SMatrix5 newParamDelta(newParamCov * tmp); // ((W+U)^-1)U(m-p) + SMatrix5 newParam = newParamDelta + param; // ((W+U)^-1)U(m-p) + p + track.setParameters(newParam); + + // compute the additional addChi2 = ((p'-p)^t)W(p'-p) + ((p'-m)^t)U(p'-m) + SMatrix5 tmp2(clusterParam - newParam); // (m-p) + auto addChi2Track(ROOT::Math::Similarity(newParamDelta, paramWeight) + ROOT::Math::Similarity(tmp2, clusterWeight)); + track.setTrackChi2(track.getTrackChi2() + addChi2Track); + + return true; +} + +//__________________________________________________________________________ +Double_t invQPtFromParabola2(const FitterTrackMFT& track, Double_t bFieldZ, Double_t& chi2) +{ + //rotate track to stabilize quadratic fitting + auto deltax = track.rbegin()->getX() - track.first().getX(); + auto deltay = track.rbegin()->getY() - track.first().getY(); + auto x_m = (track.rbegin()->getX() + track.first().getX()) / 2; + auto y_m = (track.rbegin()->getY() + track.first().getY()) / 2; + auto theta = -TMath::ATan2(deltay, deltax); + auto costheta = TMath::Cos(theta), sintheta = TMath::Sin(theta); + + bool verbose = false; + if (verbose) { + std::cout << "First and last cluster X,Y => " << track.first().getX() << " , " << track.first().getY() << " / " << track.rbegin()->getX() << " , " << track.rbegin()->getY() << std::endl; + std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) " << std::endl; + } + + auto nPoints = track.getNClusters(); + Double_t* x = new Double_t[nPoints]; + Double_t* y = new Double_t[nPoints]; + int n = 0; + for (auto trackparam = track.begin(); trackparam != track.end(); trackparam++) { + auto x_0 = trackparam->getClusterPtr()->getX() - x_m; + auto y_0 = trackparam->getClusterPtr()->getY() - y_m; + x[n] = x_0 * costheta - y_0 * sintheta; + y[n] = x_0 * sintheta + y_0 * costheta; + n++; + } + + Double_t q0, q1, q2; + chi2 = QuadraticRegression2(nPoints, x, y, q0, q1, q2); + Double_t radiusParabola = 0.5 / q2; + auto invqpt_parabola = q2 / (o2::constants::math::B2C * bFieldZ * 0.5); // radiusParabola; // radius = 0.5/q2 + + if (verbose) { + std::cout << "--------------------------------------------" << std::endl; + std::cout << " Fit QuadraticRegression: " << std::endl; + std::cout << " Fit Parameters [0] = " << q0 << " [1] = " << q1 << " [2] = " << q2 << std::endl; + std::cout << " Radius from QuadraticRegression = " << 0.5 / q2 << std::endl; + std::cout << " Seed qpt = " << 1.0 / invqpt_parabola << std::endl; + std::cout << "--------------------------------------------" << std::endl; + } + + return invqpt_parabola; +} + +//__________________________________________________________________________ +Double_t invQPtFromParabola2(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) +{ + auto nPoints = track.getNPoints(); + + const std::array<Float_t, constants::mft::LayersNumber>& xPositons = track.getXCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& yPositons = track.getYCoordinates(); + + //rotate track to stabilize quadratic fitting + auto deltax = xPositons[0] - xPositons[nPoints - 1]; + auto deltay = yPositons[0] - yPositons[nPoints - 1]; + + auto x_m = (xPositons[nPoints - 1] + xPositons[0]) / 2; + auto y_m = (yPositons[nPoints - 1] + yPositons[0]) / 2; + auto theta = -TMath::ATan2(deltay, deltax); + auto costheta = TMath::Cos(theta), sintheta = TMath::Sin(theta); + + bool verbose = true; + if (verbose) { + std::cout << "First and last cluster X,Y => " << xPositons[0] << " , " << yPositons[0] << " / " << xPositons[nPoints - 1] << " , " << yPositons[nPoints - 1] << std::endl; + std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) ; nPoints = " << nPoints << std::endl; + } + + Double_t* x = new Double_t[nPoints]; + Double_t* y = new Double_t[nPoints]; + for (auto n = 0; n < nPoints; n++) { + auto x_0 = xPositons[n] - x_m; + auto y_0 = yPositons[n] - y_m; + x[n] = x_0 * costheta - y_0 * sintheta; + y[n] = x_0 * sintheta + y_0 * costheta; + if (verbose) + std::cout << " adding rotated point to fit at z = " << track.getZCoordinates()[n] << " (" << x[n] << "," << y[n] << ") " << std::endl; + } + + Double_t q0, q1, q2; + chi2 = QuadraticRegression2(nPoints, x, y, q0, q1, q2); + Double_t radiusParabola = 0.5 / q2; + auto invqpt_parabola = q2 / (o2::constants::math::B2C * bFieldZ * 0.5); // radiusParabola; // radius = 0.5/q2 + + if (verbose) { + std::cout << "--------------------------------------------" << std::endl; + std::cout << " Fit QuadraticRegression: " << std::endl; + std::cout << " Fit Parameters [0] = " << q0 << " [1] = " << q1 << " [2] = " << q2 << std::endl; + std::cout << " Radius from QuadraticRegression = " << 0.5 / q2 << std::endl; + std::cout << " Seed qpt = " << 1.0 / invqpt_parabola << std::endl; + std::cout << "--------------------------------------------" << std::endl; + } + + return invqpt_parabola; +} + +//__________________________________________________________________________ +Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2) +{ + /// Perform a Quadratic Regression + /// Assume same error on all clusters = 1 + /// Return ~ Chi2 + + TMatrixD y(nVal, 1); + TMatrixD x(nVal, 3); + TMatrixD xtrans(3, nVal); + + for (int i = 0; i < nVal; i++) { + y(i, 0) = yVal[i]; + x(i, 0) = 1.; + x(i, 1) = xVal[i]; + x(i, 2) = xVal[i] * xVal[i]; + xtrans(0, i) = 1.; + xtrans(1, i) = xVal[i]; + xtrans(2, i) = xVal[i] * xVal[i]; + } + TMatrixD tmp(xtrans, TMatrixD::kMult, x); + tmp.Invert(); + + TMatrixD tmp2(xtrans, TMatrixD::kMult, y); + TMatrixD b(tmp, TMatrixD::kMult, tmp2); + + p0 = b(0, 0); + p1 = b(1, 0); + p2 = b(2, 0); + + // chi2 = (y-xb)^t . W . (y-xb) + TMatrixD tmp3(x, TMatrixD::kMult, b); + TMatrixD tmp4(y, TMatrixD::kMinus, tmp3); + TMatrixD chi2(tmp4, TMatrixD::kTransposeMult, tmp4); + + return chi2(0, 0); +} + +} // namespace mft +} // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index e31f54d027e01..62149efdb781a 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -15,10 +15,9 @@ #include "MFTTracking/Cluster.h" #include "MFTTracking/Cell.h" #include "MFTTracking/TrackCA.h" -#include "MFTTracking/TrackFitter.h" #include "DataFormatsMFT/TrackMFT.h" - #include "ReconstructionDataFormats/Track.h" + #include "Framework/Logger.h" namespace o2 @@ -26,13 +25,21 @@ namespace o2 namespace mft { -Tracker::Tracker(bool useMC) : mUseMC{useMC} {} +Tracker::Tracker(bool useMC) : mUseMC{useMC} +{ + + /// Prepare the track extrapolation tools + LOG(INFO) << "initializing track fitter"; + mTrackFitter = std::make_unique<o2::mft::TrackFitter2>(); + mTrackFitter->setBz(mBz); +} void Tracker::clustersToTracks(ROframe& event, std::ostream& timeBenchmarkOutputStream) { mTracks.clear(); mTrackLabels.clear(); findTracks(event); + fitTracks(event); } void Tracker::findTracks(ROframe& event) @@ -243,7 +250,6 @@ void Tracker::findTracksLTF(ROframe& event) //layMin = (lay < layMin) ? lay : layMin; //layMax = (lay > layMax) ? lay : layMax; } - } // end seed clusters bin layer2 } // end binPhi } // end binR @@ -532,6 +538,7 @@ void Tracker::runBackwardInRoad(ROframe& event) // start a track CA event.addTrackCA(); event.getCurrentTrackCA().setRoadId(road.getRoadId()); + event.getCurrentTrackCA().setCA(); if (addCellToCurrentTrackCA(layer, icell, event)) { road.setCellUsed(layer, icell, kTRUE); } @@ -646,7 +653,6 @@ void Tracker::runBackwardInRoad(ROframe& event) event.markUsedCluster(cellC.getFirstLayerId(), cellC.getFirstClusterIndex()); event.markUsedCluster(cellC.getSecondLayerId(), cellC.getSecondClusterIndex()); } - } // end loop cells } // end loop start layer } @@ -843,5 +849,17 @@ const Bool_t Tracker::LinearRegression(Int_t npoints, Float_t* x, Float_t* y, Fl return kTRUE; } +bool Tracker::fitTracks(ROframe& event) +{ + for (auto& track : event.getTracksLTF()) { + mTrackFitter->fit(track); + } + for (auto& track : event.getTracksCA()) { + mTrackFitter->fit(track); + } + + return true; +} + } // namespace mft } // namespace o2 diff --git a/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx index 7e3e4832d8645..30df4930ca8c6 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx @@ -43,7 +43,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, bool upstreamDigits, bool upstre specs.emplace_back(o2::mft::getClusterWriterSpec(useMC)); } specs.emplace_back(o2::mft::getTrackerSpec(useMC)); - specs.emplace_back(o2::mft::getTrackFitterSpec(useMC)); + //specs.emplace_back(o2::mft::getTrackFitterSpec(useMC)); if (!disableRootOutput) { specs.emplace_back(o2::mft::getTrackWriterSpec(useMC)); } diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx index 69e0fae8717d9..acc5991001ab6 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx @@ -37,7 +37,7 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) // Spectators for logging // this is only to restore the original behavior auto tracksSize = std::make_shared<int>(0); - auto tracksSizeGetter = [tracksSize](std::vector<o2::mft::TrackMFT> const& tracks) { + auto tracksSizeGetter = [tracksSize](std::vector<o2::mft::TrackLTF> const& tracks) { *tracksSize = tracks.size(); }; auto logger = [tracksSize](std::vector<o2::itsmft::ROFRecord> const& rofs) { @@ -46,13 +46,15 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) return MakeRootTreeWriterSpec("mft-track-writer", "mfttracks.root", MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree with MFT tracks"}, - BranchDefinition<std::vector<o2::mft::TrackMFT>>{InputSpec{"tracks", "MFT", "TRACKS", 0}, + BranchDefinition<std::vector<o2::mft::TrackLTF>>{InputSpec{"tracks", "MFT", "TRACKS", 0}, "MFTTrack", tracksSizeGetter}, BranchDefinition<std::vector<o2::mft::TrackLTF>>{InputSpec{"tracksltf", "MFT", "TRACKSLTF", 0}, "MFTTrackLTF"}, BranchDefinition<std::vector<o2::mft::TrackCA>>{InputSpec{"tracksca", "MFT", "TRACKSCA", 0}, "MFTTrackCA"}, + BranchDefinition<std::vector<int>>{InputSpec{"trackClIdx", "MFT", "TRACKCLSID", 0}, + "MFTTrackClusIdx"}, BranchDefinition<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>{InputSpec{"labels", "MFT", "TRACKSMCTR", 0}, "MFTTrackMCTruth", (useMC ? 1 : 0), // one branch if mc labels enabled diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index b3df99bf9a45f..582b1022c15c6 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -56,8 +56,8 @@ void TrackerDPL::init(InitContext& ic) o2::TransformType::T2G)); mTracker = std::make_unique<o2::mft::Tracker>(mUseMC); - double origD[3] = {0., 0., 0.}; - mTracker->setBz(field->getBz(origD)); + double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT + mTracker->setBz(field->getBz(centerMFT)); } else { throw std::runtime_error(o2::utils::concat_string("Cannot retrieve GRP from the ", filename)); } @@ -97,14 +97,14 @@ void TrackerDPL::run(ProcessingContext& pc) } //std::vector<o2::mft::TrackMFTExt> tracks; - std::vector<int> allClusIdx; + auto& allClusIdx = pc.outputs().make<std::vector<int>>(Output{"MFT", "TRACKCLSID", 0, Lifetime::Timeframe}); o2::dataformats::MCTruthContainer<o2::MCCompLabel> trackLabels; - std::vector<o2::mft::TrackMFT> allTracks; o2::dataformats::MCTruthContainer<o2::MCCompLabel> allTrackLabels; std::vector<o2::mft::TrackLTF> tracksLTF; auto& allTracksLTF = pc.outputs().make<std::vector<o2::mft::TrackLTF>>(Output{"MFT", "TRACKSLTF", 0, Lifetime::Timeframe}); std::vector<o2::mft::TrackCA> tracksCA; auto& allTracksCA = pc.outputs().make<std::vector<o2::mft::TrackCA>>(Output{"MFT", "TRACKSCA", 0, Lifetime::Timeframe}); + auto& allTracksMFT = pc.outputs().make<std::vector<o2::mft::TrackLTF>>(Output{"MFT", "TRACKS", 0, Lifetime::Timeframe}); std::uint32_t roFrame = 0; o2::mft::ROframe event(0); @@ -126,9 +126,10 @@ void TrackerDPL::run(ProcessingContext& pc) gsl::span<const unsigned char>::iterator pattIt = patterns.begin(); if (continuous) { - for (const auto& rof : rofs) { + for (auto& rof : rofs) { int nclUsed = ioutils::loadROFrameData(rof, event, compClusters, pattIt, mDict, labels); if (nclUsed) { + /* event.setROFrameId(roFrame); event.initialise(); LOG(INFO) << "ROframe: " << roFrame << ", clusters loaded : " << nclUsed; @@ -139,18 +140,42 @@ void TrackerDPL::run(ProcessingContext& pc) LOG(INFO) << "Found tracks LTF: " << tracksLTF.size(); LOG(INFO) << "Found tracks CA: " << tracksCA.size(); trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. - int first = allTracks.size(); + int first = allTracksMFT.size(); int shiftIdx = -rof.getFirstEntry(); rofs[roFrame].setFirstEntry(first); std::copy(tracksLTF.begin(), tracksLTF.end(), std::back_inserter(allTracksLTF)); std::copy(tracksCA.begin(), tracksCA.end(), std::back_inserter(allTracksCA)); allTrackLabels.mergeAtBack(trackLabels); + */ + + + event.setROFrameId(roFrame); + event.initialise(); + LOG(INFO) << "ROframe: " << roFrame << ", clusters loaded : " << nclUsed; + mTracker->setROFrame(roFrame); + mTracker->clustersToTracks(event); + tracksLTF.swap(event.getTracksLTF()); + tracksCA.swap(event.getTracksCA()); + LOG(INFO) << "Found tracks LTF: " << tracksLTF.size(); + LOG(INFO) << "Found tracks CA: " << tracksCA.size(); + trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. + int first = allTracksMFT.size(); + int number = tracksLTF.size() + tracksCA.size(); + int shiftIdx = -rof.getFirstEntry(); + rof.setFirstEntry(first); + rofs[roFrame].setFirstEntry(first); + rof.setNEntries(number); + copyTracks(tracksLTF, allTracksMFT, allClusIdx, shiftIdx); + copyTracks(tracksCA, allTracksMFT, allClusIdx, shiftIdx); + std::copy(tracksLTF.begin(), tracksLTF.end(), std::back_inserter(allTracksLTF)); + std::copy(tracksCA.begin(), tracksCA.end(), std::back_inserter(allTracksCA)); + allTrackLabels.mergeAtBack(trackLabels); } roFrame++; } } - //LOG(INFO) << "MFTTracker pushed " << allTracks.size() << " tracks"; + LOG(INFO) << "MFTTracker pushed " << allTracksMFT.size() << " tracks"; LOG(INFO) << "MFTTracker pushed " << allTracksLTF.size() << " tracks LTF"; LOG(INFO) << "MFTTracker pushed " << allTracksCA.size() << " tracks CA"; if (mUseMC) { @@ -167,9 +192,12 @@ DataProcessorSpec getTrackerSpec(bool useMC) inputs.emplace_back("ROframes", "MFT", "CLUSTERSROF", 0, Lifetime::Timeframe); std::vector<OutputSpec> outputs; + outputs.emplace_back("MFT", "TRACKS", 0, Lifetime::Timeframe); outputs.emplace_back("MFT", "TRACKSLTF", 0, Lifetime::Timeframe); outputs.emplace_back("MFT", "TRACKSCA", 0, Lifetime::Timeframe); outputs.emplace_back("MFT", "TRACKSROF", 0, Lifetime::Timeframe); + outputs.emplace_back("MFT", "TRACKCLSID", 0, Lifetime::Timeframe); + if (useMC) { inputs.emplace_back("labels", "MFT", "CLUSTERSMCTR", 0, Lifetime::Timeframe); From ee7535c431e2d445c7675d8e049def7d4b93bac0 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Sat, 25 Jul 2020 18:07:35 +0000 Subject: [PATCH 0292/1751] MFT track fitting incorporated into tracker workflow New track fitting profits from Kalman filter methods incorporated to TrackParCovFwd. TrackParCovFwd emulates some functionality of the central barrel track class (TrackParCovFwd). --- .../ReconstructionDataFormats/TrackFwd.h | 13 +- DataFormats/Reconstruction/src/TrackFwd.cxx | 2 +- Detectors/ITSMFT/MFT/tracking/CMakeLists.txt | 4 - .../tracking/include/MFTTracking/TrackCA.h | 41 +- .../include/MFTTracking/TrackFitter.h | 40 +- .../include/MFTTracking/TrackFitter2.h | 84 --- .../tracking/include/MFTTracking/Tracker.h | 4 +- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 525 +++++++++--------- .../ITSMFT/MFT/tracking/src/TrackFitter2.cxx | 468 ---------------- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 4 +- Detectors/ITSMFT/MFT/workflow/CMakeLists.txt | 2 - .../include/MFTWorkflow/TrackFitterSpec.h | 58 -- .../ITSMFT/MFT/workflow/src/RecoWorkflow.cxx | 2 - .../MFT/workflow/src/TrackFitterSpec.cxx | 203 ------- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 21 - 15 files changed, 323 insertions(+), 1148 deletions(-) delete mode 100644 Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h delete mode 100644 Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx delete mode 100644 Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackFitterSpec.h delete mode 100644 Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index 624629902c5b4..3ed90b8bc9c44 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -19,14 +19,12 @@ #include <TMath.h> #include "Math/SMatrix.h" #include "MathUtils/Utils.h" -//#include <Framework/Logger.h> namespace o2 { namespace track { -//using Cluster = o2::BaseCluster<Float_t>; using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; @@ -92,16 +90,12 @@ class TrackParFwd /// add track parameters void addParameters(const SMatrix5& parameters) { mParameters += parameters; } - /// get pointer to associated cluster - //const Cluster* getClusterPtr() const { return mClusterPtr; } - /// set pointer to associated cluster - //void setClusterPtr(const Cluster* cluster) { mClusterPtr = cluster; } - /// return the chi2 of the track when the associated cluster was attached Double_t getTrackChi2() const { return mTrackChi2; } /// set the chi2 of the track when the associated cluster was attached void setTrackChi2(Double_t chi2) { mTrackChi2 = chi2; } + // Track propagation void linearExtrapToZ(double zEnd); void quadraticExtrapToZ(double zEnd, double zField); void helixExtrapToZ(double zEnd, double zField); @@ -115,8 +109,7 @@ class TrackParFwd /// PHI = azimutal angle /// TANL = tangent of \lambda (dip angle) /// INVQPT = Inverse transverse momentum (GeV/c ** -1) times charge (assumed forward motion) </pre> - SMatrix5 mParameters{}; ///< \brief Track parameters - //const Cluster* mClusterPtr = nullptr; ///< Pointer to the associated cluster if any + SMatrix5 mParameters{}; ///< \brief Track parameters Double_t mTrackChi2 = 0.; ///< Chi2 of the track when the associated cluster was attached ClassDefNV(TrackParFwd, 1); @@ -147,7 +140,7 @@ class TrackParCovFwd : public TrackParFwd void linearExtrapToZCov(double zEnd); void quadraticExtrapToZCov(double zEnd, double zField); void helixExtrapToZCov(double zEnd, double zField); - void addMCSEffect(double dZ, double x0, double zField); + void addMCSEffect(double dZ, double x0); private: /// Covariance matrix of track parameters, ordered as follows: <pre> diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index dad57552b6846..6195fde4395dc 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -320,7 +320,7 @@ void TrackParCovFwd::helixExtrapToZCov(double zEnd, double zField) } //__________________________________________________________________________ -void TrackParCovFwd::addMCSEffect(double dZ, double x0, double zField) +void TrackParCovFwd::addMCSEffect(double dZ, double x0) { /// Add to the track parameter covariances the effects of multiple Coulomb scattering /// through a material of thickness "abs(dZ)" and of radiation length "x0" diff --git a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt index abdd6f764be2b..a58aa71464962 100644 --- a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt @@ -16,9 +16,7 @@ o2_add_library(MFTTracking src/Cluster.cxx src/IOUtils.cxx src/TrackFitter.cxx - src/TrackFitter2.cxx src/FitterTrackMFT.cxx - src/TrackExtrap.cxx src/MFTTrackingParam.cxx PUBLIC_LINK_LIBRARIES O2::CommonConstants O2::DataFormatsITSMFT @@ -30,8 +28,6 @@ o2_add_library(MFTTracking o2_target_root_dictionary(MFTTracking HEADERS include/MFTTracking/TrackCA.h HEADERS include/MFTTracking/TrackFitter.h - HEADERS include/MFTTracking/TrackExtrap.h - HEADERS include/MFTTracking/TrackFitter2.h HEADERS include/MFTTracking/FitterTrackMFT.h HEADERS include/MFTTracking/TrackParamMFT.h HEADERS include/MFTTracking/MFTTrackingParam.h diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index a873274f16e5f..5d7f35d14f716 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -37,6 +37,7 @@ class TrackLTF : public TrackMFTExt const std::array<Int_t, constants::mft::LayersNumber>& getClustersId() const { return mClusterId; } const std::array<MCCompLabel, constants::mft::LayersNumber>& getMCCompLabels() const { return mMCCompLabels; } void setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); + void sort(); protected: Int_t mNPoints{0}; @@ -121,7 +122,6 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z mLayer[mNPoints] = layer; mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; - //std::cout << "setClusterIndex(layer, clusterId) = " << layer << " , " << clusterId << " newpoint" << std::endl; setClusterIndex(layer, clusterId, mNPoints); mNPoints++; @@ -132,11 +132,48 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z mLayer[mNPoints] = layer; mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; - //std::cout << "setClusterIndex(layer, clusterId) = " << layer << " , " << clusterId << std::endl; setClusterIndex(layer, clusterId, mNPoints); } } +inline void TrackLTF::sort() +{ + // Orders elements along z position + + struct ClusterData { + Float_t x; + Float_t y; + Float_t z; + Float_t layer; + Float_t clusterId; + Float_t label; + }; + + std::vector<ClusterData> points; + for (Int_t point = 0; point < getNPoints(); ++point) { + auto& somepoint = points.emplace_back(); + somepoint.x = mX[point]; + somepoint.y = mY[point]; + somepoint.z = mZ[point]; + somepoint.layer = mLayer[point]; + somepoint.clusterId = mClusterId[point]; + somepoint.label = mMCCompLabels[point]; + } + + std::sort(points.begin(), points.end(), [](ClusterData a, ClusterData b) { return a.z > b.z; }); + + // after sorting + for (Int_t point = 0; point < getNPoints(); ++point) { + // auto& somepoint = points.emplace_back(); + mX[point] = points[point].x; + mY[point] = points[point].y; + mZ[point] = points[point].z; + mLayer[point] = points[point].layer; + mClusterId[point] = points[point].clusterId; + mMCCompLabels[point] = points[point].label; + } +} + } // namespace mft namespace framework { diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h index 68702029abd2c..956cccd8dbd80 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h @@ -13,17 +13,15 @@ /// /// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS -#ifndef ALICEO2_MFT_TRACKFITTER_H_ -#define ALICEO2_MFT_TRACKFITTER_H_ +#ifndef ALICEO2_MFT_TrackFitter_H_ +#define ALICEO2_MFT_TrackFitter_H_ #include "MFTTracking/Cluster.h" #include "MFTTracking/TrackCA.h" -#include "MFTTracking/FitterTrackMFT.h" #include "MFTTracking/TrackParamMFT.h" -#include "MFTTracking/TrackExtrap.h" +//#include "MFTTracking/TrackExtrap.h" #include "MFTTracking/MFTTrackingParam.h" #include "DataFormatsMFT/TrackMFT.h" - #include <TLinearFitter.h> #include <list> @@ -35,6 +33,10 @@ namespace mft /// Class to fit a track to a set of clusters class TrackFitter { + + using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; + using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; + public: TrackFitter() = default; ~TrackFitter() = default; @@ -46,40 +48,34 @@ class TrackFitter void setBz(float bZ); - /// Enable/disable the smoother (and the saving of related parameters) - void smoothTracks(bool smooth) { mSmooth = smooth; } - /// Return the smoother enable/disable flag - bool isSmootherEnabled() { return mSmooth; } + bool fit(TrackLTF& track); - bool fit(FitterTrackMFT& track, bool smooth = true, bool finalize = true, - std::list<TrackParamMFT>::reverse_iterator* itStartingParam = nullptr); - - bool runKalmanFilter(TrackParamMFT& trackParam); + bool runKalmanFilter(TrackLTF& track, int cluster); /// Return the maximum chi2 above which the track can be considered as abnormal static constexpr double getMaxChi2() { return SMaxChi2; } private: - void initTrack(const Cluster& cl, TrackParamMFT& param); - bool addCluster(const TrackParamMFT& startingParam, const Cluster& cl, TrackParamMFT& param); - bool smoothTrack(FitterTrackMFT& track, bool finalize); - bool runSmoother(const TrackParamMFT& previousParam, TrackParamMFT& param); + bool initTrack(TrackLTF& track); + bool addCluster(TrackLTF& track, int cluster); + Float_t mBZField; // kiloGauss. static constexpr double SMaxChi2 = 2.e10; ///< maximum chi2 above which the track can be considered as abnormal /// default layer thickness in X0 for reconstruction //FIXME: set values for the MFT static constexpr double SLayerThicknessInX0[10] = {0.065, 0.065, 0.075, 0.075, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035}; - bool mSmooth = false; ///< switch ON/OFF the smoother bool mFieldON = true; - o2::mft::TrackExtrap mTrackExtrap; + //o2::mft::TrackExtrap mTrackExtrap; }; // Functions to estimate momentum and charge from track curvature -Double_t invQPtFromParabola(const FitterTrackMFT& track, double bFieldZ, Double_t& chi2); -Double_t QuadraticRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2); +Double_t invQPtFromParabola2(const TrackLTF& track, double bFieldZ, Double_t& chi2); +Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2); +Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2); +Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yErr, Double_t& a, Double_t& ae, Double_t& b, Double_t& be); } // namespace mft } // namespace o2 -#endif // ALICEO2_MFT_TRACKFITTER_H_ +#endif // ALICEO2_MFT_TrackFitter_H_ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h deleted file mode 100644 index ed8344d394da5..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter2.h +++ /dev/null @@ -1,84 +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. - -/// \file TrackFitter.h -/// \brief Definition of a class to fit a track to a set of clusters -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#ifndef ALICEO2_MFT_TRACKFITTER2_H_ -#define ALICEO2_MFT_TRACKFITTER2_H_ - -#include "MFTTracking/Cluster.h" -#include "MFTTracking/TrackCA.h" -#include "MFTTracking/FitterTrackMFT.h" -#include "MFTTracking/TrackParamMFT.h" -#include "MFTTracking/TrackExtrap.h" -#include "MFTTracking/MFTTrackingParam.h" -#include "DataFormatsMFT/TrackMFT.h" - -#include <TLinearFitter.h> -#include <list> - -namespace o2 -{ -namespace mft -{ - -/// Class to fit a track to a set of clusters -class TrackFitter2 -{ - - using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; - using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; - - public: - TrackFitter2() = default; - ~TrackFitter2() = default; - - TrackFitter2(const TrackFitter2&) = delete; - TrackFitter2& operator=(const TrackFitter2&) = delete; - TrackFitter2(TrackFitter2&&) = delete; - TrackFitter2& operator=(TrackFitter2&&) = delete; - - void setBz(float bZ); - - bool fit(TrackLTF& track); - - bool fit(FitterTrackMFT& track, std::list<TrackParamMFT>::reverse_iterator* itStartingParam = nullptr); - - bool runKalmanFilter(TrackLTF& track, int cluster); - - /// Return the maximum chi2 above which the track can be considered as abnormal - static constexpr double getMaxChi2() { return SMaxChi2; } - - private: - bool initTrack(TrackLTF& track); - bool addCluster(TrackLTF& track, int cluster); - - Float_t mBZField; // kiloGauss. - static constexpr double SMaxChi2 = 2.e10; ///< maximum chi2 above which the track can be considered as abnormal - /// default layer thickness in X0 for reconstruction //FIXME: set values for the MFT - static constexpr double SLayerThicknessInX0[10] = {0.065, 0.065, 0.075, 0.075, 0.035, - 0.035, 0.035, 0.035, 0.035, 0.035}; - - bool mFieldON = true; - o2::mft::TrackExtrap mTrackExtrap; -}; - -// Functions to estimate momentum and charge from track curvature -Double_t invQPtFromParabola2(const FitterTrackMFT& track, double bFieldZ, Double_t& chi2); -Double_t invQPtFromParabola2(const TrackLTF& track, double bFieldZ, Double_t& chi2); -Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2); - -} // namespace mft -} // namespace o2 - -#endif // ALICEO2_MFT_TrackFitter2_H_ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 3a460d4d48006..4ad05d364c78c 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -16,7 +16,7 @@ #define O2_MFT_TRACKER_H_ #include "MFTTracking/ROframe.h" -#include "MFTTracking/TrackFitter2.h" +#include "MFTTracking/TrackFitter.h" #include "MFTTracking/Cluster.h" #include "MathUtils/Utils.h" @@ -66,7 +66,7 @@ class Tracker void updateCellStatusInRoad(Road&); bool fitTracks(ROframe&); - std::unique_ptr<o2::mft::TrackFitter2> mTrackFitter = nullptr; + std::unique_ptr<o2::mft::TrackFitter> mTrackFitter = nullptr; const Int_t isDiskFace(Int_t layer) const; diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 380b2bb3d47d7..56b2bfd5f6686 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -44,7 +44,7 @@ void TrackFitter::setBz(float bZ) /// Set the magnetic field for the MFT mBZField = bZ; - mTrackExtrap.setBz(bZ); + //mTrackExtrap.setBz(bZ); if (mftTrackingParam.verbose) { LOG(INFO) << "Setting Fitter field = " << bZ; @@ -52,83 +52,58 @@ void TrackFitter::setBz(float bZ) } //_________________________________________________________________________________________________ -bool TrackFitter::fit(FitterTrackMFT& track, bool smooth, bool finalize, - std::list<TrackParamMFT>::reverse_iterator* itStartingParam) +bool TrackFitter::fit(TrackLTF& track) { + /// Fit a track to its attached clusters - /// Smooth the track if requested and the smoother enabled - /// If finalize = true: copy the smoothed parameters, if any, into the regular ones /// Fit the entire track or only the part upstream itStartingParam /// Returns false in case of failure auto& mftTrackingParam = MFTTrackingParam::Instance(); + auto nClusters = track.getNPoints(); if (mftTrackingParam.verbose) { std::cout << "\n ***************************** Start Fitting new track ***************************** \n"; - std::cout << "N Clusters = " << track.getNPoints() << std::endl; + std::cout << "N Clusters = " << nClusters << std::endl; } - // initialize the starting track parameters and cluster - double chi2invqptquad; - double invpqtquad; - - auto itParam(track.rbegin()); - if (itStartingParam != nullptr) { - // use the ones pointed to by itStartingParam - if (*itStartingParam == track.rend()) { - LOG(INFO) << "MFT Fit ERROR: invalid track starting parameters"; - track.removable(); - return false; - } - itParam = *itStartingParam; - } else { - // or start from the last cluster and compute the track parameters from its position - // and the one of the first previous cluster found on a different layer - auto itPreviousParam(itParam); - ++itPreviousParam; - invpqtquad = invQPtFromParabola(track, mBZField, chi2invqptquad); - track.setInvQPtQuadtratic(invpqtquad); - track.setChi2QPtQuadtratic(chi2invqptquad); - (*itParam).setInvQPt(track.getInvQPtQuadtratic()); // Initial momentum estimate - initTrack(*itParam->getClusterPtr(), *itParam); - } + initTrack(track); if (mftTrackingParam.verbose) { - std::cout << "Seed covariances:"; - itParam->getCovariances().Print(); + std::cout << "Seed covariances: \n"; + track.getCovariances().Print(std::cout); + std::cout << std::endl; } // recusively add the upstream clusters and update the track parameters - TrackParamMFT* startingParam = &*itParam; - while (++itParam != track.rend()) { - if (!addCluster(*startingParam, *itParam->getClusterPtr(), *itParam)) { - track.removable(); + nClusters--; + while (nClusters-- > 0) { + if (!addCluster(track, nClusters)) { return false; } - startingParam = &*itParam; } - itParam--; if (mftTrackingParam.verbose) { - std::cout << "Track covariances:"; - itParam->getCovariances().Print(); - std::cout << "Track Chi2 = " << itParam->getTrackChi2() << std::endl; + // std::cout << "Track covariances:"; + // trac->getCovariances().Print(); + std::cout << "Track Chi2 = " << track.getTrackChi2() << std::endl; std::cout << " ***************************** Done fitting *****************************\n"; } - // smooth the track if requested and the smoother enabled - if (smooth && mSmooth) { - if (!smoothTrack(track, finalize)) { - track.removable(); - return false; - } - } return true; } //_________________________________________________________________________________________________ -void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) +bool TrackFitter::initTrack(TrackLTF& track) { + // initialize the starting track parameters and cluster + double chi2invqptquad; + double invpqtquad; + auto nPoints = track.getNPoints(); + invpqtquad = invQPtFromFCF(track, mBZField, chi2invqptquad); + track.setInvQPtQuadtratic(invpqtquad); + track.setChi2QPtQuadtratic(chi2invqptquad); + track.setInvQPt(invpqtquad); /// Compute the initial track parameters at the z position of the last cluster (cl) /// The covariance matrix is computed such that the last cluster is the only constraint @@ -138,9 +113,9 @@ void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) auto& mftTrackingParam = MFTTrackingParam::Instance(); // compute the track parameters at the last cluster - double x0 = cl.getX(); - double y0 = cl.getY(); - double z0 = cl.getZ(); + double x0 = track.getXCoordinates()[nPoints - 1]; + double y0 = track.getYCoordinates()[nPoints - 1]; + double z0 = track.getZCoordinates()[nPoints - 1]; double pt = TMath::Sqrt(x0 * x0 + y0 * y0); double pz = z0; double phi0 = TMath::ATan2(y0, x0); @@ -149,34 +124,34 @@ void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) double r0cu = r0sq * TMath::Sqrt(r0sq); double invr0sq = 1.0 / r0sq; double invr0cu = 1.0 / r0cu; - double sigmax0sq = cl.sigmaX2; - double sigmay0sq = cl.sigmaY2; - double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond + double sigmax0sq = 5e-4; + double sigmay0sq = 5.43e-4; + double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond double sigmaboost = mftTrackingParam.sigmaboost; // Boost q/pt seed covariances double seedH_k = mftTrackingParam.seedH_k; // SeedH constant - param.setX(x0); - param.setY(y0); - param.setZ(z0); - param.setPhi(phi0); - param.setTanl(tanl); + track.setX(x0); + track.setY(y0); + track.setZ(z0); + track.setPhi(phi0); + track.setTanl(tanl); // Configure the track seed switch (mftTrackingParam.seed) { case AB: if (mftTrackingParam.verbose) std::cout << " Init track with Seed A / B; sigmaboost = " << sigmaboost << ".\n"; - param.setInvQPt(1.0 / pt); // Seeds A & B + track.setInvQPt(1.0 / pt); // Seeds A & B break; case CE: if (mftTrackingParam.verbose) std::cout << " Init track with Seed C / E; sigmaboost = " << sigmaboost << ".\n"; - param.setInvQPt(std::copysign(1.0, param.getInvQPt()) / pt); // Seeds C & E + track.setInvQPt(std::copysign(1.0, track.getInvQPt()) / pt); // Seeds C & E break; case DH: if (mftTrackingParam.verbose) std::cout << " Init track with Seed H; (k = " << seedH_k << "); sigmaboost = " << sigmaboost << ".\n"; - param.setInvQPt(param.getInvQPt() / seedH_k); // SeedH + track.setInvQPt(track.getInvQPt() / seedH_k); // SeedH break; default: if (mftTrackingParam.verbose) @@ -186,14 +161,14 @@ void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) if (mftTrackingParam.verbose) { auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; std::cout << "Track Model: " << model << std::endl; - std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; + std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; } // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) - TMatrixD lastParamCov(5, 5); - lastParamCov.Zero(); - lastParamCov(0, 0) = sigmax0sq; // <X,X> - lastParamCov(0, 1) = 0; // <Y,X> + SMatrix55 lastParamCov; + //lastParamCov.Zero(); + lastParamCov(0, 0) = sigmax0sq; // <X,X> + lastParamCov(0, 1) = 0; // <Y,X> lastParamCov(0, 2) = sigmaboost * -sigmax0sq * y0 * invr0sq; // <PHI,X> lastParamCov(0, 3) = sigmaboost * -z0 * sigmax0sq * x0 * invr0cu; // <TANL,X> lastParamCov(0, 4) = sigmaboost * -x0 * sigmax0sq * invr0cu; // <INVQPT,X> @@ -223,15 +198,13 @@ void TrackFitter::initTrack(const Cluster& cl, TrackParamMFT& param) lastParamCov(4, 2) = lastParamCov(2, 4); // lastParamCov(4, 3) = lastParamCov(3, 4); // - param.setCovariances(lastParamCov); + track.setCovariances(lastParamCov); + track.setTrackChi2(0.); - // set other parameters - param.setClusterPtr(&cl); - param.setTrackChi2(0.); + return true; } -//_________________________________________________________________________________________________ -bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& cl, TrackParamMFT& param) +bool TrackFitter::addCluster(TrackLTF& track, int cluster) { /// Extrapolate the starting track parameters to the z position of the new cluster /// accounting for MCS dispersion in the current layer and the other(s) crossed @@ -239,30 +212,30 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& /// Returns false in case of failure auto& mftTrackingParam = MFTTrackingParam::Instance(); + const auto& clx = track.getXCoordinates()[cluster]; + const auto& cly = track.getYCoordinates()[cluster]; + const auto& clz = track.getZCoordinates()[cluster]; - if (cl.getZ() <= startingParam.getZ()) { - LOG(INFO) << "AddCluster ERROR: The new cluster must be upstream! Bug on TrackFinder. "; - return false; + if (track.getZ() >= clz) { + LOG(INFO) << "AddCluster ERROR: The new cluster must be upstream! Bug on TrackFinder. " << (track.isCA() ? " CATrack" : "LTFTrack"); + LOG(INFO) << "track.getZ() = " << track.getZ() << " ; newClusterZ = " << clz; + + //return false; } if (mftTrackingParam.verbose) - std::cout << "addCluster: X = " << cl.getX() << " Y = " << cl.getY() << " Z = " << cl.getZ() << std::endl; - // copy the current parameters into the new ones - param.setParameters(startingParam.getParameters()); - param.setZ(startingParam.getZ()); - param.setCovariances(startingParam.getCovariances()); - param.setTrackChi2(startingParam.getTrackChi2()); + std::cout << "addCluster: X = " << clx << " Y = " << cly << " Z = " << clz << " nCluster = " << cluster << std::endl; // add MCS effects for the new cluster using o2::mft::constants::LayerZPosition; int startingLayerID, newLayerID; - double dZ = TMath::Abs(cl.getZ() - startingParam.getZ()); + double dZ = TMath::Abs(clz - track.getZ()); //LayerID of each cluster from ZPosition // TODO: Use ChipMapping for (auto layer = 10; layer--;) - if (startingParam.getZ() < LayerZPosition[layer] + .3 & startingParam.getZ() > LayerZPosition[layer] - .3) + if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3) startingLayerID = layer; for (auto layer = 10; layer--;) - if (cl.getZ() < LayerZPosition[layer] + .3 & cl.getZ() > LayerZPosition[layer] - .3) + if (clz<LayerZPosition[layer] + .3 & clz> LayerZPosition[layer] - .3) newLayerID = layer; // Number of disks crossed by this tracklet int NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; @@ -271,249 +244,122 @@ bool TrackFitter::addCluster(const TrackParamMFT& startingParam, const Cluster& if (mftTrackingParam.verbose) { std::cout << "startingLayerID = " << startingLayerID << " ; " << "newLayerID = " << newLayerID << " ; "; - std::cout << "cl.getZ() = " << cl.getZ() << " ; "; - std::cout << "startingParam.getZ() = " << startingParam.getZ() << " ; "; + std::cout << "cl.getZ() = " << clz << " ; "; + std::cout << "startingParam.getZ() = " << track.getZ() << " ; "; std::cout << "NDisksMS = " << NDisksMS << std::endl; } - // Add MCS effects if ((NDisksMS * MFTDiskThicknessInX0) != 0) - mTrackExtrap.addMCSEffect(¶m, -1, NDisksMS * MFTDiskThicknessInX0); - - // reset propagator for smoother - if (mSmooth) { - param.resetPropagator(); - } + track.addMCSEffect(-1, NDisksMS * MFTDiskThicknessInX0); if (mftTrackingParam.verbose) - std::cout << " BeforeExtrap: X = " << param.getX() << " Y = " << param.getY() << " Z = " << param.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; + std::cout << " BeforeExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; // extrapolate to the z position of the new cluster - mTrackExtrap.extrapToZCov(¶m, cl.getZ(), mSmooth); - + track.helixExtrapToZCov(clz, mBZField); if (mftTrackingParam.verbose) - std::cout << " AfterExtrap: X = " << param.getX() << " Y = " << param.getY() << " Z = " << param.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; - - // save extrapolated parameters and covariances for smoother - if (mSmooth) { - param.setExtrapParameters(param.getParameters()); - param.setExtrapCovariances(param.getCovariances()); - } + std::cout << " AfterExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; // recompute the parameters - param.setClusterPtr(&cl); - if (runKalmanFilter(param)) { + if (runKalmanFilter(track, cluster)) { if (mftTrackingParam.verbose) { - std::cout << " New Cluster: X = " << cl.getX() << " Y = " << cl.getY() << " Z = " << cl.getZ() << std::endl; - std::cout << " AfterKalman: X = " << param.getX() << " Y = " << param.getY() << " Z = " << param.getZ() << " Tgl = " << param.getTanl() << " Phi = " << param.getPhi() << " pz = " << param.getPz() << " qpt = " << 1.0 / param.getInvQPt() << std::endl; + std::cout << " New Cluster: X = " << clx << " Y = " << cly << " Z = " << clz << std::endl; + std::cout << " AfterKalman: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; std::cout << std::endl; // Outputs track covariance matrix: // param.getCovariances().Print(); } return true; - } else - return false; -} - -//_________________________________________________________________________________________________ -bool TrackFitter::smoothTrack(FitterTrackMFT& track, bool finalize) -{ - /// Recompute the track parameters at each cluster using the Smoother - /// Smoothed parameters are stored in dedicated data members - /// If finalize, they are copied in the regular parameters in case of success - /// Returns false in case of failure - - auto itCurrentParam(track.begin()); - auto itPreviousParam(itCurrentParam); - ++itCurrentParam; - - // smoothed parameters and covariances at first cluster = filtered parameters and covariances - itPreviousParam->setSmoothParameters(itPreviousParam->getParameters()); - itPreviousParam->setSmoothCovariances(itPreviousParam->getCovariances()); - - // local chi2 at first cluster = last additional chi2 provided by Kalman - itPreviousParam->setLocalChi2(itPreviousParam->getTrackChi2() - itCurrentParam->getTrackChi2()); - - // recursively smooth the next parameters and covariances - do { - if (!runSmoother(*itPreviousParam, *itCurrentParam)) { - return false; - } - ++itPreviousParam; - } while (++itCurrentParam != track.end()); - - // update the regular parameters and covariances if requested - if (finalize) { - for (auto& param : track) { - param.setParameters(param.getSmoothParameters()); - param.setCovariances(param.getSmoothCovariances()); - } } - return true; + return false; } //_________________________________________________________________________________________________ -bool TrackFitter::runKalmanFilter(TrackParamMFT& trackParam) +bool TrackFitter::runKalmanFilter(TrackLTF& track, int cluster) { /// Compute the new track parameters including the attached cluster with the Kalman filter /// The current parameters are supposed to have been extrapolated to the cluster z position /// Retruns false in case of failure - // get actual track parameters (p) - TMatrixD param(trackParam.getParameters()); + // get propagated track parameters (p) + auto param = track.getParameters(); // get new cluster parameters (m) - const Cluster* cluster = trackParam.getClusterPtr(); - TMatrixD clusterParam(5, 1); - clusterParam.Zero(); - clusterParam(0, 0) = cluster->getX(); - clusterParam(1, 0) = cluster->getY(); + SMatrix5 clusterParam; + clusterParam(0) = track.getXCoordinates()[cluster]; + clusterParam(1) = track.getYCoordinates()[cluster]; // compute the actual parameter weight (W) - TMatrixD paramWeight(trackParam.getCovariances()); - if (paramWeight.Determinant() != 0) { - paramWeight.Invert(); - } else { + SMatrix55 paramWeight(track.getCovariances()); + if (!(paramWeight.Invert())) { LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; return false; } // compute the new cluster weight (U) - TMatrixD clusterWeight(5, 5); - clusterWeight.Zero(); - clusterWeight(0, 0) = 1. / cluster->sigmaX2; // 1. / cluster->getEx2(); - clusterWeight(1, 1) = 1. / cluster->sigmaY2; // 1. / cluster->getEy2(); + SMatrix55 clusterWeight; + clusterWeight(0, 0) = 1. / 5e-4; // FIXME + clusterWeight(1, 1) = 1. / 5.43e-4; // compute the new parameters covariance matrix ((W+U)^-1) - TMatrixD newParamCov(paramWeight, TMatrixD::kPlus, clusterWeight); - if (newParamCov.Determinant() != 0) { - newParamCov.Invert(); - } else { + SMatrix55 newParamCov(paramWeight + clusterWeight); + if (!newParamCov.Invert()) { LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; return false; } - trackParam.setCovariances(newParamCov); - - // compute the new parameters (p' = ((W+U)^-1)U(m-p) + p) - TMatrixD tmp(clusterParam, TMatrixD::kMinus, param); // m-p - TMatrixD tmp2(clusterWeight, TMatrixD::kMult, tmp); // U(m-p) - TMatrixD newParam(newParamCov, TMatrixD::kMult, tmp2); // ((W+U)^-1)U(m-p) - newParam += param; // ((W+U)^-1)U(m-p) + p - trackParam.setParameters(newParam); - - // compute the additional chi2 (= ((p'-p)^-1)W(p'-p) + ((p'-m)^-1)U(p'-m)) - tmp = newParam; // p' - tmp -= param; // (p'-p) - TMatrixD tmp3(paramWeight, TMatrixD::kMult, tmp); // W(p'-p) - TMatrixD addChi2Track(tmp, TMatrixD::kTransposeMult, tmp3); // ((p'-p)^-1)W(p'-p) - tmp = newParam; // p' - tmp -= clusterParam; // (p'-m) - TMatrixD tmp4(clusterWeight, TMatrixD::kMult, tmp); // U(p'-m) - addChi2Track += TMatrixD(tmp, TMatrixD::kTransposeMult, tmp4); // ((p'-p)^-1)W(p'-p) + ((p'-m)^-1)U(p'-m) - trackParam.setTrackChi2(trackParam.getTrackChi2() + addChi2Track(0, 0)); + track.setCovariances(newParamCov); - return true; -} - -//_________________________________________________________________________________________________ -bool TrackFitter::runSmoother(const TrackParamMFT& previousParam, TrackParamMFT& param) -{ - /// Recompute the track parameters starting from the previous ones - /// Returns false in case of failure + // compute the new parameters: (p' = ((W+U)^-1)U(m-p) + p) + // Parameters increment: p' - p = ((W+U)^-1)U(m-p) + SMatrix5 predict_residuals(clusterParam - param); // m-p -> residuals of prediction + SMatrix5 tmp(clusterWeight * predict_residuals); // U(m-p) + SMatrix5 newParamDelta(newParamCov * tmp); // ((W+U)^-1)U(m-p) + SMatrix5 newParam = newParamDelta + param; // ((W+U)^-1)U(m-p) + p + track.setParameters(newParam); - // get variables - const TMatrixD& extrapParameters = previousParam.getExtrapParameters(); // X(k+1 k) - const TMatrixD& filteredParameters = param.getParameters(); // X(k k) - const TMatrixD& previousSmoothParameters = previousParam.getSmoothParameters(); // X(k+1 n) - const TMatrixD& propagator = previousParam.getPropagator(); // F(k) - const TMatrixD& extrapCovariances = previousParam.getExtrapCovariances(); // C(k+1 k) - const TMatrixD& filteredCovariances = param.getCovariances(); // C(k k) - const TMatrixD& previousSmoothCovariances = previousParam.getSmoothCovariances(); // C(k+1 n) - - // compute smoother gain: A(k) = C(kk) * F(k)^t * (C(k+1 k))^-1 - TMatrixD extrapWeight(extrapCovariances); - if (extrapWeight.Determinant() != 0) { - extrapWeight.Invert(); // (C(k+1 k))^-1 - } else { - LOG(INFO) << "Smoother ERROR: Determinant = 0"; - return false; - } - TMatrixD smootherGain(filteredCovariances, TMatrixD::kMultTranspose, propagator); // C(kk) * F(k)^t - smootherGain *= extrapWeight; // C(kk) * F(k)^t * (C(k+1 k))^-1 - - // compute smoothed parameters: X(k n) = X(k k) + A(k) * (X(k+1 n) - X(k+1 k)) - TMatrixD tmpParam(previousSmoothParameters, TMatrixD::kMinus, extrapParameters); // X(k+1 n) - X(k+1 k) - TMatrixD smoothParameters(smootherGain, TMatrixD::kMult, tmpParam); // A(k) * (X(k+1 n) - X(k+1 k)) - smoothParameters += filteredParameters; // X(k k) + A(k) * (X(k+1 n) - X(k+1 k)) - param.setSmoothParameters(smoothParameters); - - // compute smoothed covariances: C(k n) = C(k k) + A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t - TMatrixD tmpCov(previousSmoothCovariances, TMatrixD::kMinus, extrapCovariances); // C(k+1 n) - C(k+1 k) - TMatrixD tmpCov2(tmpCov, TMatrixD::kMultTranspose, smootherGain); // (C(k+1 n) - C(k+1 k)) * (A(k))^t - TMatrixD smoothCovariances(smootherGain, TMatrixD::kMult, tmpCov2); // A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t - smoothCovariances += filteredCovariances; // C(k k) + A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t - param.setSmoothCovariances(smoothCovariances); - - // compute smoothed residual: r(k n) = cluster - X(k n) - const Cluster* cluster = param.getClusterPtr(); - TMatrixD smoothResidual(2, 1); - smoothResidual.Zero(); - smoothResidual(0, 0) = cluster->getX() - smoothParameters(0, 0); - smoothResidual(1, 0) = cluster->getY() - smoothParameters(1, 0); - - // compute weight of smoothed residual: W(k n) = (clusterCov - C(k n))^-1 - TMatrixD smoothResidualWeight(2, 2); - smoothResidualWeight(0, 0) = cluster->sigmaX2 - smoothCovariances(0, 0); // cluster->getEx2() - smoothCovariances(0, 0); - smoothResidualWeight(0, 1) = -smoothCovariances(0, 2); - smoothResidualWeight(1, 0) = -smoothCovariances(2, 0); - smoothResidualWeight(1, 1) = cluster->sigmaY2 - smoothCovariances(2, 2); // cluster->getEy2() - smoothCovariances(2, 2); - if (smoothResidualWeight.Determinant() != 0) { - smoothResidualWeight.Invert(); - } else { - LOG(INFO) << "Smoother ERROR: Determinant = 0"; - return false; - } + // compute the additional addChi2 = ((p'-p)^t)W(p'-p) + ((p'-m)^t)U(p'-m) + SMatrix5 tmp2(clusterParam - newParam); // (m-p) + auto addChi2Track(ROOT::Math::Similarity(newParamDelta, paramWeight) + ROOT::Math::Similarity(tmp2, clusterWeight)); + track.setTrackChi2(track.getTrackChi2() + addChi2Track); - // compute local chi2 = (r(k n))^t * W(k n) * r(k n) - TMatrixD tmpChi2(smoothResidual, TMatrixD::kTransposeMult, smoothResidualWeight); // (r(k n))^t * W(k n) - TMatrixD localChi2(tmpChi2, TMatrixD::kMult, smoothResidual); // (r(k n))^t * W(k n) * r(k n) - param.setLocalChi2(localChi2(0, 0)); return true; } //__________________________________________________________________________ -Double_t invQPtFromParabola(const FitterTrackMFT& track, Double_t bFieldZ, Double_t& chi2) +Double_t invQPtFromParabola2(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) { + auto nPoints = track.getNPoints(); + + const std::array<Float_t, constants::mft::LayersNumber>& xPositons = track.getXCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& yPositons = track.getYCoordinates(); + //rotate track to stabilize quadratic fitting - auto deltax = track.rbegin()->getX() - track.first().getX(); - auto deltay = track.rbegin()->getY() - track.first().getY(); - auto x_m = (track.rbegin()->getX() + track.first().getX()) / 2; - auto y_m = (track.rbegin()->getY() + track.first().getY()) / 2; + auto deltax = xPositons[0] - xPositons[nPoints - 1]; + auto deltay = yPositons[0] - yPositons[nPoints - 1]; + //auto x_m = (xPositons[nPoints - 1] + xPositons[0]) / 2; + //auto y_m = (yPositons[nPoints - 1] + yPositons[0]) / 2; auto theta = -TMath::ATan2(deltay, deltax); auto costheta = TMath::Cos(theta), sintheta = TMath::Sin(theta); - bool verbose = true; + bool verbose = false; if (verbose) { - std::cout << "First and last cluster X,Y => " << track.first().getX() << " , " << track.first().getY() << " / " << track.rbegin()->getX() << " , " << track.rbegin()->getY() << std::endl; - std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) " << std::endl; + std::cout << "First and last cluster X,Y => " << xPositons[0] << " , " << yPositons[0] << " / " << xPositons[nPoints - 1] << " , " << yPositons[nPoints - 1] << std::endl; + std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) ; nPoints = " << nPoints << std::endl; } - auto nPoints = track.getNClusters(); Double_t* x = new Double_t[nPoints]; Double_t* y = new Double_t[nPoints]; - int n = 0; - for (auto trackparam = track.begin(); trackparam != track.end(); trackparam++) { - auto x_0 = trackparam->getClusterPtr()->getX() - x_m; - auto y_0 = trackparam->getClusterPtr()->getY() - y_m; + for (auto n = 0; n < nPoints; n++) { + auto x_0 = xPositons[n]; // - x_m; + auto y_0 = yPositons[n]; // - y_m; x[n] = x_0 * costheta - y_0 * sintheta; y[n] = x_0 * sintheta + y_0 * costheta; if (verbose) - std::cout << " adding rotated point to fit at z = " << trackparam->getClusterPtr()->getZ() << " (" << x[n] << "," << y[n] << ") " << std::endl; - n++; + std::cout << " adding rotated point to fit at z = " << track.getZCoordinates()[n] << " (" << x[n] << "," << y[n] << ") " << std::endl; } Double_t q0, q1, q2; - chi2 = QuadraticRegression(nPoints, x, y, q0, q1, q2); + chi2 = QuadraticRegression2(nPoints, x, y, q0, q1, q2); Double_t radiusParabola = 0.5 / q2; auto invqpt_parabola = q2 / (o2::constants::math::B2C * bFieldZ * 0.5); // radiusParabola; // radius = 0.5/q2 @@ -530,7 +376,7 @@ Double_t invQPtFromParabola(const FitterTrackMFT& track, Double_t bFieldZ, Doubl } //__________________________________________________________________________ -Double_t QuadraticRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2) +Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2) { /// Perform a Quadratic Regression /// Assume same error on all clusters = 1 @@ -567,5 +413,150 @@ Double_t QuadraticRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_ return chi2(0, 0); } +Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) +{ + + const std::array<Float_t, constants::mft::LayersNumber>& xPositons = track.getXCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& yPositons = track.getYCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& zPositons = track.getZCoordinates(); + + // Fast Circle Fit (Hansroul, Jeremie, Savard, 1987) + auto nPoints = track.getNPoints(); + Double_t* xVal = new Double_t[nPoints]; + Double_t* yVal = new Double_t[nPoints]; + Double_t* zVal = new Double_t[nPoints]; + Double_t* xErr = new Double_t[nPoints]; + Double_t* yErr = new Double_t[nPoints]; + Double_t* uVal = new Double_t[nPoints - 1]; + Double_t* vVal = new Double_t[nPoints - 1]; + Double_t* vErr = new Double_t[nPoints - 1]; + Double_t a, ae, b, be, x2, y2, invx2y2, rx, ry, r; + + for (auto np = 0; np < nPoints; np++) { + //printf("BV track %d %f %f %f \n", np, trackparam->getClusterPtr()->getX(), trackparam->getClusterPtr()->getY(), trackparam->getClusterPtr()->getZ()); + xErr[np] = 5e-4; // FIXME + yErr[np] = 5e-4; // FIXME + if (np > 0) { + xVal[np] = xPositons[np] - xVal[0]; + yVal[np] = yPositons[np] - yVal[0]; + xErr[np] *= std::sqrt(2.); + yErr[np] *= std::sqrt(2.); + } else { + xVal[np] = 0.; + yVal[np] = 0.; + } + zVal[np] = zPositons[np]; + } + for (int i = 0; i < (nPoints - 1); i++) { + x2 = xVal[i + 1] * xVal[i + 1]; + y2 = yVal[i + 1] * yVal[i + 1]; + invx2y2 = 1. / (x2 + y2); + uVal[i] = xVal[i + 1] * invx2y2; + vVal[i] = yVal[i + 1] * invx2y2; + vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2)) * invx2y2 * invx2y2; + } + + Double_t invqpt_fcf; + Int_t qfcf; + chi2 = 0.; + if (LinearRegression((nPoints - 1), uVal, vVal, yErr, a, ae, b, be)) { + // v = a * u + b + // circle passing through (0,0): + // (x - rx)^2 + (y - ry)^2 = r^2 + // ---> a = - rx / ry; + // ---> b = 1 / (2 * ry) + ry = 1. / (2. * b); + rx = -a * ry; + r = std::sqrt(rx * rx + ry * ry); + + // pt ---> + Double_t invpt = 1. / (o2::constants::math::B2C * bFieldZ * r); + + // sign(q) ---> + // rotate around the first point (0,0) to bring the last point + // on the x axis (y = 0) and check the y sign of the rotated + // center of the circle + Double_t x = xVal[nPoints - 1], y = yVal[nPoints - 1], z = zVal[nPoints - 1]; + Double_t slope = TMath::ATan2(y, x); + Double_t cosSlope = TMath::Cos(slope); + Double_t sinSlope = TMath::Sin(slope); + Double_t rxRot = rx * cosSlope + ry * sinSlope; + Double_t ryRot = rx * sinSlope - ry * cosSlope; + qfcf = (ryRot < 0.) ? -1 : +1; + //printf("BV r-quad %f , r-fcf %f q-fcf %f \n", 0.5 / q2, r, qfcf); + + //Double_t xRot = x * cosSlope + y * sinSlope; + //printf("BV check %f %f \n", xRot, 2.0 * rxRot); + + Double_t alpha = 2.0 * std::abs(TMath::ATan2(rxRot, ryRot)); + Double_t x0 = xVal[0], y0 = yVal[0], z0 = zVal[0]; + Double_t dxyz2 = (x - x0) * (x - x0) + (y - y0) * (y - y0) + (z - z0) * (z - z0); + Double_t cst = 1000.; + Double_t c_alpha = cst * alpha; + Double_t p, pt, pz; + pt = 1. / invpt; + p = std::sqrt(dxyz2) / c_alpha; + pz = std::sqrt(p * p - pt * pt); + // tanl = pz / pt; + invqpt_fcf = qfcf * invpt; + } else { // the linear regression failed... + printf("BV LinearRegression failed!\n"); + invqpt_fcf = 1. / 100.; + } + + return invqpt_fcf; +} + +//__________________________________________________________________________ +Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yErr, Double_t& a, Double_t& ae, Double_t& b, Double_t& be) +{ + // linear regression y = a * x + b + + Double_t S1, SXY, SX, SY, SXX, SsXY, SsXX, SsYY, Xm, Ym, s, delta, difx; + Double_t invYErr2; + + S1 = SXY = SX = SY = SXX = 0.0; + SsXX = SsYY = SsXY = Xm = Ym = 0.; + difx = 0.; + for (Int_t i = 0; i < nVal; i++) { + //printf("BV LinFit %d %f %f %f \n", i, xVal[i], yVal[i], yErr[i]); + invYErr2 = 1. / (yErr[i] * yErr[i]); + S1 += invYErr2; + SXY += xVal[i] * yVal[i] * invYErr2; + SX += xVal[i] * invYErr2; + SY += yVal[i] * invYErr2; + SXX += xVal[i] * xVal[i] * invYErr2; + if (i > 0) + difx += TMath::Abs(xVal[i] - xVal[i - 1]); + Xm += xVal[i]; + Ym += yVal[i]; + SsXX += xVal[i] * xVal[i]; + SsYY += yVal[i] * yVal[i]; + SsXY += xVal[i] * yVal[i]; + } + delta = SXX * S1 - SX * SX; + if (delta == 0.) { + return kFALSE; + } + a = (SXY * S1 - SX * SY) / delta; + b = (SY * SXX - SX * SXY) / delta; + + Ym /= (Double_t)nVal; + Xm /= (Double_t)nVal; + SsYY -= (Double_t)nVal * (Ym * Ym); + SsXX -= (Double_t)nVal * (Xm * Xm); + SsXY -= (Double_t)nVal * (Ym * Xm); + Double_t eps = 1.E-24; + if ((nVal > 2) && (TMath::Abs(difx) > eps) && ((SsYY - (SsXY * SsXY) / SsXX) > 0.)) { + s = TMath::Sqrt((SsYY - (SsXY * SsXY) / SsXX) / (nVal - 2)); + be = s * TMath::Sqrt(1. / (Double_t)nVal + (Xm * Xm) / SsXX); + ae = s / TMath::Sqrt(SsXX); + } else { + be = 0.; + ae = 0.; + } + return kTRUE; +} + } // namespace mft } // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx deleted file mode 100644 index eb38cb1b70153..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter2.cxx +++ /dev/null @@ -1,468 +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. - -/// \file TrackFitter.cxx -/// \brief Implementation of a class to fit a track to a set of clusters -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#include "MFTBase/Constants.h" -#include "MFTTracking/TrackFitter2.h" -#include "MFTTracking/TrackCA.h" -#include "MFTTracking/TrackExtrap.h" -#include "MFTTracking/Cluster.h" -#include "DataFormatsMFT/TrackMFT.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "ITSMFTReconstruction/ChipMappingMFT.h" -#include <stdexcept> -#include <TMath.h> -#include <TMatrixD.h> -#include <TF1.h> -#include <TF2.h> -#include "CommonConstants/MathConstants.h" -#include "MathUtils/MathBase.h" -#include "MathUtils/Utils.h" - -using o2::math_utils::math_base::fitGaus; - -namespace o2 -{ -namespace mft -{ - -//_________________________________________________________________________________________________ -void TrackFitter2::setBz(float bZ) -{ - auto& mftTrackingParam = MFTTrackingParam::Instance(); - - /// Set the magnetic field for the MFT - mBZField = bZ; - mTrackExtrap.setBz(bZ); - - if (mftTrackingParam.verbose) { - LOG(INFO) << "Setting Fitter field = " << bZ; - } -} - -//_________________________________________________________________________________________________ -bool TrackFitter2::fit(TrackLTF& track) -{ - - /// Fit a track to its attached clusters - /// Fit the entire track or only the part upstream itStartingParam - /// Returns false in case of failure - - auto& mftTrackingParam = MFTTrackingParam::Instance(); - auto nClusters = track.getNPoints(); - - if (mftTrackingParam.verbose) { - std::cout << "\n ***************************** Start Fitting new track ***************************** \n"; - std::cout << "N Clusters = " << nClusters << std::endl; - } - - initTrack(track); - - if (mftTrackingParam.verbose) { - std::cout << "Seed covariances: \n"; - track.getCovariances().Print(std::cout); - std::cout << std::endl; - } - - // recusively add the upstream clusters and update the track parameters - nClusters--; - while (nClusters-- > 0) { - if (!addCluster(track, nClusters)) { - return false; - } - } - - if (mftTrackingParam.verbose) { - // std::cout << "Track covariances:"; - // trac->getCovariances().Print(); - std::cout << "Track Chi2 = " << track.getTrackChi2() << std::endl; - std::cout << " ***************************** Done fitting *****************************\n"; - } - - return true; -} - -//_________________________________________________________________________________________________ -bool TrackFitter2::initTrack(TrackLTF& track) -{ - // initialize the starting track parameters and cluster - double chi2invqptquad; - double invpqtquad; - auto nPoints = track.getNPoints(); - invpqtquad = invQPtFromParabola2(track, mBZField, chi2invqptquad); - track.setInvQPtQuadtratic(invpqtquad); - track.setChi2QPtQuadtratic(chi2invqptquad); - track.setInvQPt(invpqtquad); - - /// Compute the initial track parameters at the z position of the last cluster (cl) - /// The covariance matrix is computed such that the last cluster is the only constraint - /// (by assigning an infinite dispersion to the other cluster) - /// These parameters are the seed for the Kalman filter - - auto& mftTrackingParam = MFTTrackingParam::Instance(); - - // compute the track parameters at the last cluster - double x0 = track.getXCoordinates()[nPoints - 1]; - double y0 = track.getYCoordinates()[nPoints - 1]; - double z0 = track.getZCoordinates()[nPoints - 1]; - double pt = TMath::Sqrt(x0 * x0 + y0 * y0); - double pz = z0; - double phi0 = TMath::ATan2(y0, x0); - double tanl = pz / pt; - double r0sq = x0 * x0 + y0 * y0; - double r0cu = r0sq * TMath::Sqrt(r0sq); - double invr0sq = 1.0 / r0sq; - double invr0cu = 1.0 / r0cu; - double sigmax0sq = 5e-4; - double sigmay0sq = 5.43e-4; - double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond - double sigmaboost = mftTrackingParam.sigmaboost; // Boost q/pt seed covariances - double seedH_k = mftTrackingParam.seedH_k; // SeedH constant - - track.setX(x0); - track.setY(y0); - track.setZ(z0); - track.setPhi(phi0); - track.setTanl(tanl); - - // Configure the track seed - switch (mftTrackingParam.seed) { - case AB: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed A / B; sigmaboost = " << sigmaboost << ".\n"; - track.setInvQPt(1.0 / pt); // Seeds A & B - break; - case CE: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed C / E; sigmaboost = " << sigmaboost << ".\n"; - track.setInvQPt(std::copysign(1.0, track.getInvQPt()) / pt); // Seeds C & E - break; - case DH: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed H; (k = " << seedH_k << "); sigmaboost = " << sigmaboost << ".\n"; - track.setInvQPt(track.getInvQPt() / seedH_k); // SeedH - break; - default: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed D.\n"; - break; - } - if (mftTrackingParam.verbose) { - auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; - std::cout << "Track Model: " << model << std::endl; - std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; - } - - // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) - SMatrix55 lastParamCov; - //lastParamCov.Zero(); - lastParamCov(0, 0) = sigmax0sq; // <X,X> - lastParamCov(0, 1) = 0; // <Y,X> - lastParamCov(0, 2) = sigmaboost * -sigmax0sq * y0 * invr0sq; // <PHI,X> - lastParamCov(0, 3) = sigmaboost * -z0 * sigmax0sq * x0 * invr0cu; // <TANL,X> - lastParamCov(0, 4) = sigmaboost * -x0 * sigmax0sq * invr0cu; // <INVQPT,X> - - lastParamCov(1, 1) = sigmay0sq; // <Y,Y> - lastParamCov(1, 2) = sigmaboost * sigmay0sq * x0 * invr0sq; // <PHI,Y> - lastParamCov(1, 3) = sigmaboost * -z0 * sigmay0sq * y0 * invr0cu; // <TANL,Y> - lastParamCov(1, 4) = sigmaboost * y0 * sigmay0sq * invr0cu; //1e-2; // <INVQPT,Y> - - lastParamCov(2, 2) = sigmaboost * (sigmax0sq * y0 * y0 + sigmay0sq * x0 * x0) * invr0sq * invr0sq; // <PHI,PHI> - lastParamCov(2, 3) = sigmaboost * z0 * x0 * y0 * (sigmax0sq - sigmay0sq) * invr0sq * invr0cu; // <TANL,PHI> - lastParamCov(2, 4) = sigmaboost * y0 * x0 * invr0cu * invr0sq * (sigmax0sq - sigmay0sq); // <INVQPT,PHI> - - lastParamCov(3, 3) = sigmaboost * z0 * z0 * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0) * invr0cu * invr0cu + sigmaDeltaZsq * invr0sq; // <TANL,TANL> - lastParamCov(3, 4) = sigmaboost * z0 * invr0cu * invr0cu * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0); // <INVQPT,TANL> - - lastParamCov(4, 4) = sigmaboost * sigmaboost * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0) * invr0cu * invr0cu; // <INVQPT,INVQPT> - - lastParamCov(1, 0) = lastParamCov(0, 1); // - lastParamCov(2, 0) = lastParamCov(0, 2); // - lastParamCov(2, 1) = lastParamCov(1, 2); // - lastParamCov(3, 0) = lastParamCov(0, 3); // - lastParamCov(3, 1) = lastParamCov(1, 3); // - lastParamCov(3, 2) = lastParamCov(2, 3); // - lastParamCov(4, 0) = lastParamCov(0, 4); // - lastParamCov(4, 1) = lastParamCov(1, 4); // - lastParamCov(4, 2) = lastParamCov(2, 4); // - lastParamCov(4, 3) = lastParamCov(3, 4); // - - track.setCovariances(lastParamCov); - track.setTrackChi2(0.); - - return true; -} - -bool TrackFitter2::addCluster(TrackLTF& track, int cluster) -{ - /// Extrapolate the starting track parameters to the z position of the new cluster - /// accounting for MCS dispersion in the current layer and the other(s) crossed - /// Recompute the parameters adding the cluster constraint with the Kalman filter - /// Returns false in case of failure - - auto& mftTrackingParam = MFTTrackingParam::Instance(); - const auto& clx = track.getXCoordinates()[cluster]; - const auto& cly = track.getYCoordinates()[cluster]; - const auto& clz = track.getZCoordinates()[cluster]; - - if (track.getZ() >= clz) { - LOG(INFO) << "AddCluster ERROR: The new cluster must be upstream! Bug on TrackFinder. "; - LOG(INFO) << "track.getZ() = " << track.getZ() << " ; newClusterZ = " << clz; - - return false; - } - if (mftTrackingParam.verbose) - std::cout << "addCluster: X = " << clx << " Y = " << cly << " Z = " << clz << " nCluster = " << cluster << std::endl; - - // add MCS effects for the new cluster - using o2::mft::constants::LayerZPosition; - int startingLayerID, newLayerID; - - double dZ = TMath::Abs(clz - track.getZ()); - //LayerID of each cluster from ZPosition // TODO: Use ChipMapping - for (auto layer = 10; layer--;) - if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3) - startingLayerID = layer; - for (auto layer = 10; layer--;) - if (clz<LayerZPosition[layer] + .3 & clz> LayerZPosition[layer] - .3) - newLayerID = layer; - // Number of disks crossed by this tracklet - int NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; - - double MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0; - if (mftTrackingParam.verbose) { - std::cout << "startingLayerID = " << startingLayerID << " ; " - << "newLayerID = " << newLayerID << " ; "; - std::cout << "cl.getZ() = " << clz << " ; "; - std::cout << "startingParam.getZ() = " << track.getZ() << " ; "; - std::cout << "NDisksMS = " << NDisksMS << std::endl; - } - /* - // Add MCS effects - if ((NDisksMS * MFTDiskThicknessInX0) != 0) - mTrackExtrap.addMCSEffect(¶m, -1, NDisksMS * MFTDiskThicknessInX0); -*/ - - if (mftTrackingParam.verbose) - std::cout << " BeforeExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; - - // extrapolate to the z position of the new cluster - track.helixExtrapToZCov(clz, mBZField); - - if (mftTrackingParam.verbose) - std::cout << " AfterExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; - - // recompute the parameters - - if (runKalmanFilter(track, cluster)) { - if (mftTrackingParam.verbose) { - std::cout << " New Cluster: X = " << clx << " Y = " << cly << " Z = " << clz << std::endl; - std::cout << " AfterKalman: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; - std::cout << std::endl; - // Outputs track covariance matrix: - // param.getCovariances().Print(); - } - return true; - } - return false; -} - -//_________________________________________________________________________________________________ -bool TrackFitter2::runKalmanFilter(TrackLTF& track, int cluster) -{ - /// Compute the new track parameters including the attached cluster with the Kalman filter - /// The current parameters are supposed to have been extrapolated to the cluster z position - /// Retruns false in case of failure - - // get propagated track parameters (p) - auto param = track.getParameters(); - - // get new cluster parameters (m) - SMatrix5 clusterParam; - clusterParam(0) = track.getXCoordinates()[cluster]; - clusterParam(1) = track.getYCoordinates()[cluster]; - - // compute the actual parameter weight (W) - SMatrix55 paramWeight(track.getCovariances()); - if (!(paramWeight.Invert())) { - LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; - return false; - } - - // compute the new cluster weight (U) - SMatrix55 clusterWeight; - clusterWeight(0, 0) = 1. / 5e-4; // FIXME - clusterWeight(1, 1) = 1. / 5.43e-4; - - // compute the new parameters covariance matrix ((W+U)^-1) - SMatrix55 newParamCov(paramWeight + clusterWeight); - if (!newParamCov.Invert()) { - LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; - return false; - } - track.setCovariances(newParamCov); - - // compute the new parameters: (p' = ((W+U)^-1)U(m-p) + p) - // Parameters increment: p' - p = ((W+U)^-1)U(m-p) - SMatrix5 predict_residuals(clusterParam - param); // m-p -> residuals of prediction - SMatrix5 tmp(clusterWeight * predict_residuals); // U(m-p) - SMatrix5 newParamDelta(newParamCov * tmp); // ((W+U)^-1)U(m-p) - SMatrix5 newParam = newParamDelta + param; // ((W+U)^-1)U(m-p) + p - track.setParameters(newParam); - - // compute the additional addChi2 = ((p'-p)^t)W(p'-p) + ((p'-m)^t)U(p'-m) - SMatrix5 tmp2(clusterParam - newParam); // (m-p) - auto addChi2Track(ROOT::Math::Similarity(newParamDelta, paramWeight) + ROOT::Math::Similarity(tmp2, clusterWeight)); - track.setTrackChi2(track.getTrackChi2() + addChi2Track); - - return true; -} - -//__________________________________________________________________________ -Double_t invQPtFromParabola2(const FitterTrackMFT& track, Double_t bFieldZ, Double_t& chi2) -{ - //rotate track to stabilize quadratic fitting - auto deltax = track.rbegin()->getX() - track.first().getX(); - auto deltay = track.rbegin()->getY() - track.first().getY(); - auto x_m = (track.rbegin()->getX() + track.first().getX()) / 2; - auto y_m = (track.rbegin()->getY() + track.first().getY()) / 2; - auto theta = -TMath::ATan2(deltay, deltax); - auto costheta = TMath::Cos(theta), sintheta = TMath::Sin(theta); - - bool verbose = false; - if (verbose) { - std::cout << "First and last cluster X,Y => " << track.first().getX() << " , " << track.first().getY() << " / " << track.rbegin()->getX() << " , " << track.rbegin()->getY() << std::endl; - std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) " << std::endl; - } - - auto nPoints = track.getNClusters(); - Double_t* x = new Double_t[nPoints]; - Double_t* y = new Double_t[nPoints]; - int n = 0; - for (auto trackparam = track.begin(); trackparam != track.end(); trackparam++) { - auto x_0 = trackparam->getClusterPtr()->getX() - x_m; - auto y_0 = trackparam->getClusterPtr()->getY() - y_m; - x[n] = x_0 * costheta - y_0 * sintheta; - y[n] = x_0 * sintheta + y_0 * costheta; - n++; - } - - Double_t q0, q1, q2; - chi2 = QuadraticRegression2(nPoints, x, y, q0, q1, q2); - Double_t radiusParabola = 0.5 / q2; - auto invqpt_parabola = q2 / (o2::constants::math::B2C * bFieldZ * 0.5); // radiusParabola; // radius = 0.5/q2 - - if (verbose) { - std::cout << "--------------------------------------------" << std::endl; - std::cout << " Fit QuadraticRegression: " << std::endl; - std::cout << " Fit Parameters [0] = " << q0 << " [1] = " << q1 << " [2] = " << q2 << std::endl; - std::cout << " Radius from QuadraticRegression = " << 0.5 / q2 << std::endl; - std::cout << " Seed qpt = " << 1.0 / invqpt_parabola << std::endl; - std::cout << "--------------------------------------------" << std::endl; - } - - return invqpt_parabola; -} - -//__________________________________________________________________________ -Double_t invQPtFromParabola2(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) -{ - auto nPoints = track.getNPoints(); - - const std::array<Float_t, constants::mft::LayersNumber>& xPositons = track.getXCoordinates(); - const std::array<Float_t, constants::mft::LayersNumber>& yPositons = track.getYCoordinates(); - - //rotate track to stabilize quadratic fitting - auto deltax = xPositons[0] - xPositons[nPoints - 1]; - auto deltay = yPositons[0] - yPositons[nPoints - 1]; - - auto x_m = (xPositons[nPoints - 1] + xPositons[0]) / 2; - auto y_m = (yPositons[nPoints - 1] + yPositons[0]) / 2; - auto theta = -TMath::ATan2(deltay, deltax); - auto costheta = TMath::Cos(theta), sintheta = TMath::Sin(theta); - - bool verbose = true; - if (verbose) { - std::cout << "First and last cluster X,Y => " << xPositons[0] << " , " << yPositons[0] << " / " << xPositons[nPoints - 1] << " , " << yPositons[nPoints - 1] << std::endl; - std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) ; nPoints = " << nPoints << std::endl; - } - - Double_t* x = new Double_t[nPoints]; - Double_t* y = new Double_t[nPoints]; - for (auto n = 0; n < nPoints; n++) { - auto x_0 = xPositons[n] - x_m; - auto y_0 = yPositons[n] - y_m; - x[n] = x_0 * costheta - y_0 * sintheta; - y[n] = x_0 * sintheta + y_0 * costheta; - if (verbose) - std::cout << " adding rotated point to fit at z = " << track.getZCoordinates()[n] << " (" << x[n] << "," << y[n] << ") " << std::endl; - } - - Double_t q0, q1, q2; - chi2 = QuadraticRegression2(nPoints, x, y, q0, q1, q2); - Double_t radiusParabola = 0.5 / q2; - auto invqpt_parabola = q2 / (o2::constants::math::B2C * bFieldZ * 0.5); // radiusParabola; // radius = 0.5/q2 - - if (verbose) { - std::cout << "--------------------------------------------" << std::endl; - std::cout << " Fit QuadraticRegression: " << std::endl; - std::cout << " Fit Parameters [0] = " << q0 << " [1] = " << q1 << " [2] = " << q2 << std::endl; - std::cout << " Radius from QuadraticRegression = " << 0.5 / q2 << std::endl; - std::cout << " Seed qpt = " << 1.0 / invqpt_parabola << std::endl; - std::cout << "--------------------------------------------" << std::endl; - } - - return invqpt_parabola; -} - -//__________________________________________________________________________ -Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2) -{ - /// Perform a Quadratic Regression - /// Assume same error on all clusters = 1 - /// Return ~ Chi2 - - TMatrixD y(nVal, 1); - TMatrixD x(nVal, 3); - TMatrixD xtrans(3, nVal); - - for (int i = 0; i < nVal; i++) { - y(i, 0) = yVal[i]; - x(i, 0) = 1.; - x(i, 1) = xVal[i]; - x(i, 2) = xVal[i] * xVal[i]; - xtrans(0, i) = 1.; - xtrans(1, i) = xVal[i]; - xtrans(2, i) = xVal[i] * xVal[i]; - } - TMatrixD tmp(xtrans, TMatrixD::kMult, x); - tmp.Invert(); - - TMatrixD tmp2(xtrans, TMatrixD::kMult, y); - TMatrixD b(tmp, TMatrixD::kMult, tmp2); - - p0 = b(0, 0); - p1 = b(1, 0); - p2 = b(2, 0); - - // chi2 = (y-xb)^t . W . (y-xb) - TMatrixD tmp3(x, TMatrixD::kMult, b); - TMatrixD tmp4(y, TMatrixD::kMinus, tmp3); - TMatrixD chi2(tmp4, TMatrixD::kTransposeMult, tmp4); - - return chi2(0, 0); -} - -} // namespace mft -} // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index 62149efdb781a..ff0caae2aed09 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -30,7 +30,7 @@ Tracker::Tracker(bool useMC) : mUseMC{useMC} /// Prepare the track extrapolation tools LOG(INFO) << "initializing track fitter"; - mTrackFitter = std::make_unique<o2::mft::TrackFitter2>(); + mTrackFitter = std::make_unique<o2::mft::TrackFitter>(); mTrackFitter->setBz(mBz); } @@ -370,7 +370,6 @@ void Tracker::findTracksCA(ROframe& event) if (dR >= dRcut) { continue; } - hasDisk[layer / 2] = kTRUE; mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); newPoint = kTRUE; @@ -855,6 +854,7 @@ bool Tracker::fitTracks(ROframe& event) mTrackFitter->fit(track); } for (auto& track : event.getTracksCA()) { + track.sort(); mTrackFitter->fit(track); } diff --git a/Detectors/ITSMFT/MFT/workflow/CMakeLists.txt b/Detectors/ITSMFT/MFT/workflow/CMakeLists.txt index b5691a014497a..ebfe2f71cebdc 100644 --- a/Detectors/ITSMFT/MFT/workflow/CMakeLists.txt +++ b/Detectors/ITSMFT/MFT/workflow/CMakeLists.txt @@ -16,7 +16,6 @@ o2_add_library(MFTWorkflow src/ClusterWriterSpec.cxx src/ClusterReaderSpec.cxx src/TrackerSpec.cxx - src/TrackFitterSpec.cxx src/TrackWriterSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::SimConfig @@ -29,4 +28,3 @@ o2_add_executable(reco-workflow SOURCES src/mft-reco-workflow.cxx COMPONENT_NAME mft PUBLIC_LINK_LIBRARIES O2::MFTWorkflow) - diff --git a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackFitterSpec.h b/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackFitterSpec.h deleted file mode 100644 index 198a36e700cf4..0000000000000 --- a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackFitterSpec.h +++ /dev/null @@ -1,58 +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. - -/// \file TrackFitterSpec.h -/// \brief Definition of a data processor to read, refit and send tracks with attached clusters -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#ifndef ALICEO2_MFT_TRACKFITTERSPEC_H_ -#define ALICEO2_MFT_TRACKFITTERSPEC_H_ - -#include "MFTTracking/TrackFitter.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/Task.h" - -namespace o2 -{ -namespace mft -{ - -using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; -using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; - -class TrackFitterTask : public o2::framework::Task -{ - public: - TrackFitterTask(bool useMC) : mUseMC(useMC) {} - ~TrackFitterTask() override = default; - void init(o2::framework::InitContext& ic) final; - void run(o2::framework::ProcessingContext& pc) final; - - private: - int mState = 0; - bool mUseMC = true; - std::unique_ptr<o2::parameters::GRPObject> mGRP = nullptr; - std::unique_ptr<o2::mft::TrackFitter> mTrackFitter = nullptr; -}; - -template <typename T, typename O, typename C> -void convertTrack(const T& inTrack, O& outTrack, C& clusters); - -SMatrix55 TtoSMatrixSym55(TMatrixD inMatrix); -SMatrix5 TtoSMatrix5(TMatrixD inMatrix); - -o2::framework::DataProcessorSpec getTrackFitterSpec(bool useMC); - -} // end namespace mft -} // end namespace o2 - -#endif // ALICEO2_MFT_TRACKFITTERSPEC_H_ diff --git a/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx index 30df4930ca8c6..055820074eb96 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx @@ -18,7 +18,6 @@ #include "MFTWorkflow/ClusterWriterSpec.h" #include "MFTWorkflow/ClusterReaderSpec.h" #include "MFTWorkflow/TrackerSpec.h" -#include "MFTWorkflow/TrackFitterSpec.h" #include "MFTWorkflow/TrackWriterSpec.h" namespace o2 @@ -43,7 +42,6 @@ framework::WorkflowSpec getWorkflow(bool useMC, bool upstreamDigits, bool upstre specs.emplace_back(o2::mft::getClusterWriterSpec(useMC)); } specs.emplace_back(o2::mft::getTrackerSpec(useMC)); - //specs.emplace_back(o2::mft::getTrackFitterSpec(useMC)); if (!disableRootOutput) { specs.emplace_back(o2::mft::getTrackWriterSpec(useMC)); } diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx deleted file mode 100644 index 0c33a61ca22d5..0000000000000 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackFitterSpec.cxx +++ /dev/null @@ -1,203 +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. - -/// \file TrackFitterSpec.cxx -/// \brief Implementation of a data processor to read, refit and send tracks with attached clusters -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#include "MFTWorkflow/TrackFitterSpec.h" -#include "Field/MagneticField.h" -#include "TGeoGlobalMagField.h" -#include "DetectorsBase/Propagator.h" - -#include <stdexcept> -#include <list> - -#include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/Lifetime.h" -#include "Framework/Output.h" -#include "Framework/Task.h" - -#include "MFTTracking/TrackParamMFT.h" -#include "MFTTracking/TrackCA.h" -#include "MFTTracking/FitterTrackMFT.h" -#include "MFTTracking/TrackFitter.h" -#include "MFTTracking/TrackExtrap.h" -#include "MFTTracking/Cluster.h" - -using namespace std; -using namespace o2::framework; - -namespace o2 -{ -namespace mft -{ - -void TrackFitterTask::init(InitContext& ic) -{ - /// Prepare the track extrapolation tools - LOG(INFO) << "initializing track fitter"; - mTrackFitter = std::make_unique<o2::mft::TrackFitter>(); - mTrackFitter->smoothTracks(true); - - auto filename = ic.options().get<std::string>("grp-file"); - const auto grp = o2::parameters::GRPObject::loadFrom(filename.c_str()); - if (grp) { - mGRP.reset(grp); - o2::base::Propagator::initFieldFromGRP(grp); - auto field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); - - double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT - mTrackFitter->setBz(field->getBz(centerMFT)); - - } else { - LOG(ERROR) << "Cannot retrieve GRP from the " << filename.c_str() << " file !"; - mState = 0; - } - mState = 1; -} - -//_________________________________________________________________________________________________ -void TrackFitterTask::run(ProcessingContext& pc) -{ - - if (mState != 1) - return; - - auto tracksLTF = pc.inputs().get<gsl::span<o2::mft::TrackLTF>>("tracksltf"); - auto tracksCA = pc.inputs().get<gsl::span<o2::mft::TrackCA>>("tracksca"); - - int nTracksCA = 0; - int nFailedTracksCA = 0; - int nTracksLTF = 0; - int nFailedTracksLTF = 0; - std::vector<o2::mft::FitterTrackMFT> fittertracks(tracksLTF.size() + tracksCA.size()); - std::list<Cluster> clusters; - - // Fit LTF tracks - for (const auto& track : tracksLTF) { - auto& temptrack = fittertracks.at(nTracksLTF + nFailedTracksLTF); - convertTrack(track, temptrack, clusters); - mTrackFitter->fit(temptrack, true, true) ? nTracksLTF++ : nFailedTracksLTF++; - } // end fit LTF tracks - - // Fit CA tracks - for (const auto& track : tracksCA) { - auto& temptrack = fittertracks.at(nTracksLTF + nFailedTracksLTF + nTracksCA + nFailedTracksCA); - convertTrack(track, temptrack, clusters); - temptrack.setCA(true); - mTrackFitter->fit(temptrack, true, true) ? nTracksCA++ : nFailedTracksCA++; - } // end fit CA tracks - - auto& finalMFTtracks = pc.outputs().make<std::vector<o2::mft::TrackMFT>>(Output{"MFT", "TRACKS", 0, Lifetime::Timeframe}); - finalMFTtracks.resize(nTracksLTF + nTracksCA); - - auto nTotalTracks = 0; - // Convert fitter tracks to the final Standalone MFT Track - for (const auto& track : fittertracks) { - if (!track.isRemovable()) { - auto& temptrack = finalMFTtracks.at(nTotalTracks); - temptrack.setZ(track.first().getZ()); - temptrack.setZLast(track.rbegin()->getZ()); - temptrack.setParameters(TtoSMatrix5(track.first().getParameters())); - temptrack.setParametersLast(TtoSMatrix5(track.rbegin()->getParameters())); - temptrack.setCovariances(TtoSMatrixSym55(track.first().getCovariances())); - temptrack.setCovariancesLast(TtoSMatrixSym55(track.rbegin()->getCovariances())); - temptrack.setTrackChi2(track.first().getTrackChi2()); - temptrack.setMCCompLabels(track.getMCCompLabels(), track.getNPoints()); - temptrack.setInvQPtQuadtratic(track.getInvQPtQuadtratic()); - temptrack.setChi2QPtQuadtratic(track.getChi2QPtQuadtratic()); - temptrack.setCA(track.isCA()); - nTotalTracks++; - } - } - - LOG(INFO) << "MFTFitter loaded " << tracksLTF.size() << " LTF tracks"; - LOG(INFO) << "MFTFitter loaded " << tracksCA.size() << " CA tracks"; - LOG(INFO) << "MFTFitter pushed " << fittertracks.size() << " tracks"; - LOG(INFO) << "MFTFitter dropped " << nFailedTracksLTF << " LTF tracks"; - LOG(INFO) << "MFTFitter dropped " << nFailedTracksCA << " CA tracks"; - - mState = 2; - pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); -} - -//_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getTrackFitterSpec(bool useMC) -{ - std::vector<InputSpec> inputs; - inputs.emplace_back("tracksltf", "MFT", "TRACKSLTF", 0, Lifetime::Timeframe); - inputs.emplace_back("tracksca", "MFT", "TRACKSCA", 0, Lifetime::Timeframe); - - std::vector<OutputSpec> outputs; - outputs.emplace_back("MFT", "TRACKS", 0, Lifetime::Timeframe); - - return DataProcessorSpec{ - "mft-track-fitter", - inputs, - outputs, - AlgorithmSpec{adaptFromTask<TrackFitterTask>(useMC)}, - Options{ - {"grp-file", VariantType::String, "o2sim_grp.root", {"Name of the output file"}}, - }}; -} - -//_________________________________________________________________________________________________ -template <typename T, typename O, typename C> -void convertTrack(const T& inTrack, O& outTrack, C& clusters) -{ - //auto fittedTrack = FitterTrackMFT(); - //TMatrixD covariances(5,5); - auto xpos = inTrack.getXCoordinates(); - auto ypos = inTrack.getYCoordinates(); - auto zpos = inTrack.getZCoordinates(); - auto clusterIDs = inTrack.getClustersId(); - auto nClusters = inTrack.getNPoints(); - static int ntrack = 0; - - // Add clusters to Tracker's cluster vector & set fittedTrack cluster range. - // TODO: get rid of this cluster vector - for (auto cls = 0; cls < nClusters; cls++) { - Cluster& tempcluster = clusters.emplace_back(xpos[cls], ypos[cls], zpos[cls], clusterIDs[cls]); - tempcluster.sigmaY2 = 5.43e-4; // FIXME: Use clusters errors once available - tempcluster.sigmaX2 = 5.0e-4; - outTrack.createParamAtCluster(tempcluster); - } - outTrack.setMCCompLabels(inTrack.getMCCompLabels(), nClusters); -} - -//_________________________________________________________________________________________________ -SMatrix55 TtoSMatrixSym55(TMatrixD inMatrix) -{ - // TMatrix to sym SMatrix - SMatrix55 outMatrix; - for (auto i = 5; i--;) { - outMatrix(i, i) = inMatrix(i, i); - for (auto j = i; j--;) { - outMatrix(i, j) = inMatrix(i, j); - } - } - return outMatrix; -} - -//_________________________________________________________________________________________________ -SMatrix5 TtoSMatrix5(TMatrixD inMatrix) -{ - SMatrix5 outMatrix; - for (auto i = 0; i < 5; i++) - outMatrix(i) = inMatrix(i, 0); - return outMatrix; -} - -} // namespace mft -} // namespace o2 diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 582b1022c15c6..1a48945f08327 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -129,26 +129,6 @@ void TrackerDPL::run(ProcessingContext& pc) for (auto& rof : rofs) { int nclUsed = ioutils::loadROFrameData(rof, event, compClusters, pattIt, mDict, labels); if (nclUsed) { - /* - event.setROFrameId(roFrame); - event.initialise(); - LOG(INFO) << "ROframe: " << roFrame << ", clusters loaded : " << nclUsed; - mTracker->setROFrame(roFrame); - mTracker->clustersToTracks(event); - tracksLTF.swap(event.getTracksLTF()); - tracksCA.swap(event.getTracksCA()); - LOG(INFO) << "Found tracks LTF: " << tracksLTF.size(); - LOG(INFO) << "Found tracks CA: " << tracksCA.size(); - trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. - int first = allTracksMFT.size(); - int shiftIdx = -rof.getFirstEntry(); - rofs[roFrame].setFirstEntry(first); - std::copy(tracksLTF.begin(), tracksLTF.end(), std::back_inserter(allTracksLTF)); - std::copy(tracksCA.begin(), tracksCA.end(), std::back_inserter(allTracksCA)); - allTrackLabels.mergeAtBack(trackLabels); - */ - - event.setROFrameId(roFrame); event.initialise(); LOG(INFO) << "ROframe: " << roFrame << ", clusters loaded : " << nclUsed; @@ -198,7 +178,6 @@ DataProcessorSpec getTrackerSpec(bool useMC) outputs.emplace_back("MFT", "TRACKSROF", 0, Lifetime::Timeframe); outputs.emplace_back("MFT", "TRACKCLSID", 0, Lifetime::Timeframe); - if (useMC) { inputs.emplace_back("labels", "MFT", "CLUSTERSMCTR", 0, Lifetime::Timeframe); inputs.emplace_back("MC2ROframes", "MFT", "CLUSTERSMC2ROF", 0, Lifetime::Timeframe); From ab32a95cb536213ffb41ffb71439e100f78e9ef7 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Sat, 25 Jul 2020 18:55:40 +0000 Subject: [PATCH 0293/1751] Removing obsolete files --- Detectors/ITSMFT/MFT/tracking/CMakeLists.txt | 4 - .../include/MFTTracking/FitterTrackMFT.h | 141 ------ .../include/MFTTracking/TrackExtrap.h | 68 --- .../include/MFTTracking/TrackFitter.h | 2 - .../include/MFTTracking/TrackParamMFT.h | 179 ------- .../MFT/tracking/src/FitterTrackMFT.cxx | 137 ----- .../MFT/tracking/src/MFTTrackingLinkDef.h | 1 - .../ITSMFT/MFT/tracking/src/TrackExtrap.cxx | 468 ------------------ .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 1 - .../ITSMFT/MFT/tracking/src/TrackParamMFT.cxx | 315 ------------ 10 files changed, 1316 deletions(-) delete mode 100644 Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h delete mode 100644 Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackExtrap.h delete mode 100644 Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h delete mode 100644 Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx delete mode 100644 Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx delete mode 100644 Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx diff --git a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt index a58aa71464962..1ec7e28dc5ce2 100644 --- a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt @@ -11,12 +11,10 @@ o2_add_library(MFTTracking TARGETVARNAME targetName SOURCES src/Tracker.cxx - src/TrackParamMFT.cxx src/ROframe.cxx src/Cluster.cxx src/IOUtils.cxx src/TrackFitter.cxx - src/FitterTrackMFT.cxx src/MFTTrackingParam.cxx PUBLIC_LINK_LIBRARIES O2::CommonConstants O2::DataFormatsITSMFT @@ -28,7 +26,5 @@ o2_add_library(MFTTracking o2_target_root_dictionary(MFTTracking HEADERS include/MFTTracking/TrackCA.h HEADERS include/MFTTracking/TrackFitter.h - HEADERS include/MFTTracking/FitterTrackMFT.h - HEADERS include/MFTTracking/TrackParamMFT.h HEADERS include/MFTTracking/MFTTrackingParam.h LINKDEF src/MFTTrackingLinkDef.h) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h deleted file mode 100644 index d0e32b02e7f8f..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/FitterTrackMFT.h +++ /dev/null @@ -1,141 +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. - -/// \file FitterTrackMFT.h -/// \brief Definition of the MFT track for internal use by the fitter -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#ifndef ALICEO2_MFT_FITTERTRACK_H_ -#define ALICEO2_MFT_FITTERTRACK_H_ - -#include <list> -#include <memory> - -#include "MFTTracking/Cluster.h" -#include "MFTTracking/TrackParamMFT.h" -#include "SimulationDataFormat/MCCompLabel.h" - -namespace o2 -{ -namespace mft -{ - -/// track for internal use byt the MFT Track Fitter -class FitterTrackMFT -{ - public: - FitterTrackMFT() = default; - ~FitterTrackMFT() = default; - - FitterTrackMFT(const FitterTrackMFT& track); - FitterTrackMFT& operator=(const FitterTrackMFT& track) = delete; - //FitterTrackMFT(FitterTrackMFT&&) = delete; - FitterTrackMFT& operator=(FitterTrackMFT&&) = delete; - - /// Return a reference to the track parameters at vertex - const TrackParamMFT& getParamAtVertex() const { return mParamAtVertex; } - - /// Return the number of attached clusters - const int getNClusters() const { return mParamAtClusters.size(); } - - // Set and Get MCCompLabels - const std::array<MCCompLabel, 10>& getMCCompLabels() const { return mMCCompLabels; } // constants::mft::LayersNumber = 10 - void setMCCompLabels(const std::array<MCCompLabel, 10>& labels, int nPoints) - { - mMCCompLabels = labels; - mNPoints = nPoints; - } - - /// Return a reference to the track parameters at first cluster - const TrackParamMFT& first() const { return mParamAtClusters.front(); } - /// Return a reference to the track parameters at last cluster - const TrackParamMFT& last() const { return mParamAtClusters.back(); } - - /// Return an iterator to the track parameters at clusters (point to the first one) - auto begin() { return mParamAtClusters.begin(); } - auto begin() const { return mParamAtClusters.begin(); } - /// Return an iterator passing the track parameters at last cluster - auto end() { return mParamAtClusters.end(); } - auto end() const { return mParamAtClusters.end(); } - /// Return a reverse iterator to the track parameters at clusters (point to the last one) - auto rbegin() { return mParamAtClusters.rbegin(); } - auto rbegin() const { return mParamAtClusters.rbegin(); } - /// Return a reverse iterator passing the track parameters at first cluster - auto rend() { return mParamAtClusters.rend(); } - auto rend() const { return mParamAtClusters.rend(); } - - TrackParamMFT& createParamAtCluster(const Cluster& cluster); - void addParamAtCluster(const TrackParamMFT& param); - /// Remove the given track parameters from the internal list and return an iterator to the parameters that follow - auto removeParamAtCluster(std::list<TrackParamMFT>::iterator& itParam) { return mParamAtClusters.erase(itParam); } - - bool isBetter(const FitterTrackMFT& track) const; - - void tagRemovableClusters(uint8_t requestedStationMask); - - void setCurrentParam(const TrackParamMFT& param, int chamber); - TrackParamMFT& getCurrentParam(); - /// get a reference to the current chamber on which the current parameters are given - const int& getCurrentChamber() const { return mCurrentLayer; } - /// check whether the current track parameters exist - bool hasCurrentParam() const { return mCurrentParam ? true : false; } - /// check if the current parameters are valid - bool areCurrentParamValid() const { return (mCurrentLayer > -1); } - /// invalidate the current parameters - void invalidateCurrentParam() { mCurrentLayer = -1; } - - /// set the flag telling if this track shares cluster(s) with another - void connected(bool connected = true) { mConnected = connected; } - /// return the flag telling if this track shares cluster(s) with another - bool isConnected() const { return mConnected; } - - /// set the flag telling if this track should be deleted - void removable(bool removable = true) { mRemovable = removable; } - /// return the flag telling if this track should be deleted - bool isRemovable() const { return mRemovable; } - - const Int_t getNPoints() const { return mNPoints; } - - // Track finding method - void setCA(Bool_t method) { mIsCA = method; } - const Bool_t isCA() const { return mIsCA; } - const Bool_t isLTF() const { return !mIsCA; } - - // Charge and momentum from quadratic regression of clusters X,Y positions - void setInvQPtQuadtratic(Double_t invqpt) { mInvQPtQuadtratic = invqpt; } - const Double_t getInvQPtQuadtratic() const { return mInvQPtQuadtratic; } // Inverse charged pt - const Double_t getPtQuadtratic() const { return TMath::Abs(1.f / getInvQPtQuadtratic()); } - const Double_t getChargeQuadratic() const { return TMath::Sign(1., getInvQPtQuadtratic()); } - void setChi2QPtQuadtratic(Double_t chi2) { mQuadraticFitChi2 = chi2; } - const Double_t getChi2QPtQuadtratic() const { return mQuadraticFitChi2; } - - private: - TrackParamMFT mParamAtVertex{}; ///< track parameters at vertex - std::list<TrackParamMFT> mParamAtClusters{}; ///< list of track parameters at each cluster - std::unique_ptr<TrackParamMFT> mCurrentParam{}; ///< current track parameters used during tracking - int mCurrentLayer = -1; ///< current chamber on which the current parameters are given - bool mConnected = false; ///< flag telling if this track shares cluster(s) with another - bool mRemovable = false; ///< flag telling if this track should be deleted - Int_t mNPoints{0}; // Number of clusters - std::array<MCCompLabel, 10> mMCCompLabels; // constants::mft::LayersNumber = 10 - Bool_t mIsCA = false; // Track finding method CA vs. LTF - - // Results from quadratic regression of clusters X,Y positions - // Chi2 of the quadratic regression used to estimate track pT and charge - Double_t mQuadraticFitChi2 = 0.; - // inversed charged momentum from quadratic regression - Double_t mInvQPtQuadtratic; -}; - -} // namespace mft -} // namespace o2 - -#endif // ALICEO2_MFT_FITTERTRACK_H_ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackExtrap.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackExtrap.h deleted file mode 100644 index 59b3f74ad2de8..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackExtrap.h +++ /dev/null @@ -1,68 +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. - -/// \file TrackExtrap.h -/// \brief Definition of tools for track extrapolation -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#ifndef ALICEO2_MFT_TRACKEXTRAP_H_ -#define ALICEO2_MFT_TRACKEXTRAP_H_ - -#include <cstddef> - -#include <TMatrixD.h> -#include "MFTTracking/MFTTrackingParam.h" - -namespace o2 -{ -namespace mft -{ - -class TrackParamMFT; - -/// Class holding tools for track extrapolation -class TrackExtrap -{ - public: - // static class - TrackExtrap() = default; - ~TrackExtrap() = default; - - TrackExtrap(const TrackExtrap&) = delete; - TrackExtrap& operator=(const TrackExtrap&) = delete; - TrackExtrap(TrackExtrap&&) = delete; - TrackExtrap& operator=(TrackExtrap&&) = delete; - - void setBz(float bZ) { mBZField = bZ; } /// Set the magnetic field for the MFT - const float getBz() const { return mBZField; } - const int getSignBz() const { return std::copysign(1, mBZField); } - /// Return true if the field is switched ON - const bool isFieldON() { return mIsFieldON; } - - bool extrapToZ(TrackParamMFT* TrackParamMFT, double zEnd, bool isFieldON = true); - void extrapToZCov(TrackParamMFT* TrackParamMFT, double zEnd, bool updatePropagator = false, bool isFieldON = true); - void linearExtrapToZ(TrackParamMFT* TrackParamMFT, double zEnd); - void linearExtrapToZCov(TrackParamMFT* TrackParamMFT, double zEnd, bool updatePropagator); - void quadraticExtrapToZ(TrackParamMFT* TrackParamMFT, double zEnd); - void quadraticExtrapToZCov(TrackParamMFT* TrackParamMFT, double zEnd, bool updatePropagator); - void helixExtrapToZ(TrackParamMFT* TrackParamMFT, double zEnd); - void helixExtrapToZCov(TrackParamMFT* TrackParamMFT, double zEnd, bool updatePropagator); - void addMCSEffect(TrackParamMFT* TrackParamMFT, double dZ, double x0); - - private: - Float_t mBZField; // kiloGauss. - bool mIsFieldON = false; ///< true if the field is switched ON -}; - -} // namespace mft -} // namespace o2 - -#endif // ALICEO2_MFT_TRACKEXTRAP_H_ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h index 956cccd8dbd80..5b6a9ba3027ad 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h @@ -18,8 +18,6 @@ #include "MFTTracking/Cluster.h" #include "MFTTracking/TrackCA.h" -#include "MFTTracking/TrackParamMFT.h" -//#include "MFTTracking/TrackExtrap.h" #include "MFTTracking/MFTTrackingParam.h" #include "DataFormatsMFT/TrackMFT.h" #include <TLinearFitter.h> diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h deleted file mode 100644 index 3bc63486d8773..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackParamMFT.h +++ /dev/null @@ -1,179 +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. - -/// \file TrackParamMFT.h -/// \brief Definition of the MFT track parameters for internal use -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#ifndef ALICEO2_MFT_TRACKPARAMMFT_H_ -#define ALICEO2_MFT_TRACKPARAMMFT_H_ - -#include <TMatrixD.h> -#include <TMath.h> - -#include "MFTTracking/Cluster.h" - -namespace o2 -{ -namespace mft -{ - - -/// track parameters for internal use -class TrackParamMFT -{ - public: - TrackParamMFT() = default; - ~TrackParamMFT() = default; - - TrackParamMFT(const TrackParamMFT& tp); - TrackParamMFT& operator=(const TrackParamMFT& tp); - TrackParamMFT(TrackParamMFT&&) = delete; - TrackParamMFT& operator=(TrackParamMFT&&) = delete; - - /// return Z coordinate (cm) - Double_t getZ() const { return mZ; } - /// set Z coordinate (cm) - void setZ(Double_t z) { mZ = z; } - Double_t getX() const { return mParameters(0, 0); } - void setX(Double_t x) { mParameters(0, 0) = x; } - - Double_t getY() const { return mParameters(1, 0); } - void setY(Double_t y) { mParameters(1, 0) = y; } - - void setPhi(Double_t phi) { mParameters(2, 0) = phi; } - Double_t getPhi() const { return mParameters(2, 0); } - - void setTanl(Double_t tanl) { mParameters(3, 0) = tanl; } - Double_t getTanl() const { return mParameters(3, 0); } - - void setInvQPt(Double_t invqpt) { mParameters(4, 0) = invqpt; } - Double_t getInvQPt() const { return mParameters(4, 0); } // return Inverse charged pt - Double_t getPt() const { return TMath::Abs(1.f / mParameters(4, 0)); } - Double_t getInvPt() const { return TMath::Abs(mParameters(4, 0)); } - - Double_t getPx() const { return TMath::Cos(getPhi()) * getPt(); } // return px - Double_t getInvPx() const { return 1. / getPx(); } // return invpx - - Double_t getPy() const { return TMath::Sin(getPhi()) * getPt(); } // return py - Double_t getInvPy() const { return 1. / getPx(); } // return invpy - - Double_t getPz() const { return getTanl() * getPt(); } // return pz - Double_t getInvPz() const { return 1. / getPz(); } // return invpz - - Double_t getP() const { return getPt() * TMath::Sqrt(1. + getTanl() * getTanl()); } // return total momentum - Double_t getInverseMomentum() const { return 1.f / getP(); } - - /// return the charge (assumed forward motion) - Double_t getCharge() const { return TMath::Sign(1., mParameters(4, 0)); } - /// set the charge (assumed forward motion) - void setCharge(Double_t charge) - { - if (charge * mParameters(4, 0) < 0.) - mParameters(4, 0) *= -1.; - } - - /// return track parameters - const TMatrixD& getParameters() const { return mParameters; } - /// set track parameters - void setParameters(const TMatrixD& parameters) { mParameters = parameters; } - /// add track parameters - void addParameters(const TMatrixD& parameters) { mParameters += parameters; } - - /// return kTRUE if the covariance matrix exist, kFALSE if not - Bool_t hasCovariances() const { return (mCovariances) ? kTRUE : kFALSE; } - - const TMatrixD& getCovariances() const; - void setCovariances(const TMatrixD& covariances); - void setCovariances(const Double_t matrix[5][5]); - void setVariances(const Double_t matrix[5][5]); - void deleteCovariances(); - - const TMatrixD& getPropagator() const; - void resetPropagator(); - void updatePropagator(const TMatrixD& propagator); - - const TMatrixD& getExtrapParameters() const; - void setExtrapParameters(const TMatrixD& parameters); - - const TMatrixD& getExtrapCovariances() const; - void setExtrapCovariances(const TMatrixD& covariances); - - const TMatrixD& getSmoothParameters() const; - void setSmoothParameters(const TMatrixD& parameters); - - const TMatrixD& getSmoothCovariances() const; - void setSmoothCovariances(const TMatrixD& covariances); - - /// get pointer to associated cluster - const Cluster* getClusterPtr() const { return mClusterPtr; } - /// set pointer to associated cluster - void setClusterPtr(const Cluster* cluster) { mClusterPtr = cluster; } - - /// return true if the associated cluster can be removed from the track it belongs to - Bool_t isRemovable() const { return mRemovable; } - /// set the flag telling whether the associated cluster can be removed from the track it belongs to or not - void setRemovable(Bool_t removable) { mRemovable = removable; } - - /// return the chi2 of the track when the associated cluster was attached - Double_t getTrackChi2() const { return mTrackChi2; } - /// set the chi2 of the track when the associated cluster was attached - void setTrackChi2(Double_t chi2) { mTrackChi2 = chi2; } - /// return the local chi2 of the associated cluster with respect to the track - Double_t getLocalChi2() const { return mLocalChi2; } - /// set the local chi2 of the associated cluster with respect to the track - void setLocalChi2(Double_t chi2) { mLocalChi2 = chi2; } - - void print() const; - - void clear(); - - private: - Double_t mZ = 0.; ///< Z coordinate (cm) - - /// Track parameters ordered as follow: <pre> - /// X = X coordinate (cm) - /// Y = Y coordinate (cm) - /// PHI = azimutal angle - /// TANL = tangent of \lambda (dip angle) - /// INVQPT = Inverse transverse momentum (GeV/c ** -1) times charge (assumed forward motion) </pre> - TMatrixD mParameters{5, 1}; ///< \brief Track parameters - - /// Covariance matrix of track parameters, ordered as follows: <pre> - /// <X,X> <Y,X> <PHI,X> <TANL,X> <INVQPT,X> - /// <X,Y> <Y,Y> <PHI,Y> <TANL,Y> <INVQPT,Y> - /// <X,PHI> <Y,PHI> <PHI,PHI> <TANL,PHI> <INVQPT,PHI> - /// <X,TANL> <Y,TANL> <PHI,TANL> <TANL,TANL> <INVQPT,TANL> - /// <X,INVQPT> <Y,INVQPT> <PHI,INVQPT> <TANL,INVQPT> <INVQPT,INVQPT> </pre> - mutable std::unique_ptr<TMatrixD> mCovariances{}; ///< \brief Covariance matrix of track parameters - - /// Jacobian used to extrapolate the track parameters and covariances to the actual z position - mutable std::unique_ptr<TMatrixD> mPropagator{}; - /// Track parameters extrapolated to the actual z position (not filtered by Kalman) - mutable std::unique_ptr<TMatrixD> mExtrapParameters{}; - /// Covariance matrix extrapolated to the actual z position (not filtered by Kalman) - mutable std::unique_ptr<TMatrixD> mExtrapCovariances{}; - - mutable std::unique_ptr<TMatrixD> mSmoothParameters{}; ///< Track parameters obtained using smoother - mutable std::unique_ptr<TMatrixD> mSmoothCovariances{}; ///< Covariance matrix obtained using smoother - - const Cluster* mClusterPtr = nullptr; ///< Pointer to the associated cluster if any - - Bool_t mRemovable = false; ///< kTRUE if the associated cluster can be removed from the track it belongs to - - Double_t mTrackChi2 = 0.; ///< Chi2 of the track when the associated cluster was attached - Double_t mLocalChi2 = 0.; ///< Local chi2 of the associated cluster with respect to the track -}; - -} // namespace mft -} // namespace o2 - -#endif // ALICEO2_MFT_TRACKPARAMMFT_H_ diff --git a/Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx b/Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx deleted file mode 100644 index 943325433547e..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/src/FitterTrackMFT.cxx +++ /dev/null @@ -1,137 +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. - -/// \file FitterTrackMFT.cxx -/// \brief Implementation of the MFT track for internal use -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#include "MFTTracking/FitterTrackMFT.h" - -#include <iostream> - -#include <FairMQLogger.h> - -namespace o2 -{ -namespace mft -{ - -using namespace std; - -//__________________________________________________________________________ -FitterTrackMFT::FitterTrackMFT(const FitterTrackMFT& track) - : mParamAtVertex(track.mParamAtVertex), - mParamAtClusters(track.mParamAtClusters), - mCurrentParam(nullptr), - mCurrentLayer(-1), - mConnected(track.mConnected), - mRemovable(track.mRemovable), - mMCCompLabels(track.mMCCompLabels), - mNPoints(track.mNPoints) - -{ -} - -//__________________________________________________________________________ -TrackParamMFT& FitterTrackMFT::createParamAtCluster(const Cluster& cluster) -{ - /// Create the object to hold the track parameters at the given cluster - /// Only the z position of the track is set to the cluster z position - /// Keep the internal list of track parameters at clusters sorted in z - /// Return a reference to the newly created parameters - - // find the iterator before which the new element will be constructed - auto itParam = mParamAtClusters.begin(); - for (; itParam != mParamAtClusters.end(); ++itParam) { - if (cluster.getZ() >= itParam->getZ()) { - break; - } - } - - // add the new track parameters - mParamAtClusters.emplace(itParam); - --itParam; - itParam->setX(cluster.getX()); - itParam->setY(cluster.getY()); - itParam->setZ(cluster.getZ()); - itParam->setClusterPtr(&cluster); - mNPoints++; - return *itParam; -} - -//__________________________________________________________________________ -void FitterTrackMFT::addParamAtCluster(const TrackParamMFT& param) -{ - /// Add a copy of the given track parameters in the internal list - /// The parameters must be associated with a cluster - /// Keep the internal list of track parameters sorted in clusters z - - const Cluster* cluster = param.getClusterPtr(); - if (cluster == nullptr) { - LOG(ERROR) << "The TrackParamMFT must be associated with a cluster --> not added"; - return; - } - - // find the iterator before which the new element will be constructed - auto itParam = mParamAtClusters.begin(); - for (; itParam != mParamAtClusters.end(); ++itParam) { - if (cluster->getZ() >= itParam->getZ()) { - break; - } - } - - // add the new track parameters - mParamAtClusters.emplace(itParam, param); -} - -//__________________________________________________________________________ -bool FitterTrackMFT::isBetter(const FitterTrackMFT& track) const -{ - /// Return true if this track is better than the one given as parameter - /// It is better if it has more clusters or a better chi2 in case of equality - int nCl1 = this->getNClusters(); - int nCl2 = track.getNClusters(); - return ((nCl1 > nCl2) || ((nCl1 == nCl2) && (this->first().getTrackChi2() < track.first().getTrackChi2()))); -} - -//__________________________________________________________________________ -void FitterTrackMFT::tagRemovableClusters(uint8_t requestedStationMask) -{ - /// Identify clusters that can be removed from the track, - /// with the only requirements to have at least 1 cluster per requested station - /// and at least 2 chambers over 4 in stations 4 & 5 that contain cluster(s) -} - -//__________________________________________________________________________ -void FitterTrackMFT::setCurrentParam(const TrackParamMFT& param, int chamber) -{ - /// set the current track parameters and the associated chamber - if (mCurrentParam) { - *mCurrentParam = param; - } else { - mCurrentParam = std::make_unique<TrackParamMFT>(param); - } - mCurrentParam->setClusterPtr(nullptr); - mCurrentLayer = chamber; -} - -//__________________________________________________________________________ -TrackParamMFT& FitterTrackMFT::getCurrentParam() -{ - /// get a reference to the current track parameters. Create dummy parameters if needed - if (!mCurrentParam) { - mCurrentParam = std::make_unique<TrackParamMFT>(); - } - return *mCurrentParam; -} - -} // namespace mft -} // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h b/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h index ff17bbc9ef49b..f5f83773097fb 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h +++ b/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h @@ -15,7 +15,6 @@ #pragma link off all functions; #pragma link C++ class o2::mft::TrackLTF + ; #pragma link C++ class o2::mft::TrackCA + ; -#pragma link C++ class o2::mft::TrackParamMFT + ; #pragma link C++ class std::vector < o2::mft::TrackLTF> + ; #pragma link C++ class std::vector < o2::mft::TrackCA> + ; #pragma link C++ class o2::mft::MFTTrackingParam + ; diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx deleted file mode 100644 index 3ec7d37c35265..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackExtrap.cxx +++ /dev/null @@ -1,468 +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. - -/// \file TrackExtrap.cxx -/// \brief Implementation of tools for track extrapolation -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#include "MFTTracking/TrackExtrap.h" -#include "MFTTracking/TrackParamMFT.h" - -#include "CommonConstants/MathConstants.h" -#include "MathUtils/Utils.h" -#include <TGeoGlobalMagField.h> -#include <TGeoManager.h> -#include <TGeoMaterial.h> -#include <TGeoNode.h> -#include <TGeoShape.h> -#include <TMath.h> - -#include <FairMQLogger.h> - -namespace o2 -{ -namespace mft -{ - -//__________________________________________________________________________ -void TrackExtrap::linearExtrapToZ(TrackParamMFT* trackParam, double zEnd) -{ - /// Track parameters linearly extrapolated to the plane at "zEnd". - /// On return, results from the extrapolation are updated in trackParam. - - if (trackParam->getZ() == zEnd) { - return; // nothing to be done if same z - } - - // Compute track parameters - auto dZ = (zEnd - trackParam->getZ()); - auto x0 = trackParam->getX(); - auto y0 = trackParam->getY(); - auto phi0 = trackParam->getPhi(); - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - auto invtanl0 = 1.0 / trackParam->getTanl(); - auto n = dZ * invtanl0; - auto x = x0 + n * cosphi0; - auto y = y0 + n * sinphi0; - trackParam->setX(x); - trackParam->setY(y); - trackParam->setZ(zEnd); -} - -//__________________________________________________________________________ -void TrackExtrap::linearExtrapToZCov(TrackParamMFT* trackParam, double zEnd, bool updatePropagator) -{ - /// Track parameters and their covariances linearly extrapolated to the plane at "zEnd". - /// On return, results from the extrapolation are updated in trackParam. - - // Calculate the jacobian related to the track parameters extrapolated to "zEnd" - auto dZ = (zEnd - trackParam->getZ()); - auto x0 = trackParam->getX(); - auto y0 = trackParam->getY(); - auto phi0 = trackParam->getPhi(); - auto tanl0 = trackParam->getTanl(); - auto invtanl0 = 1.0 / tanl0; - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - auto n = dZ * invtanl0; - auto m = n * invtanl0; - - // Extrapolate track parameters to "zEnd" - auto x = x0 + n * cosphi0; - auto y = y0 + n * sinphi0; - trackParam->setX(x); - trackParam->setY(y); - trackParam->setZ(zEnd); - - // Calculate Jacobian - TMatrixD jacob(5, 5); - jacob.UnitMatrix(); - jacob(0, 2) = -n * sinphi0; - jacob(0, 3) = -m * cosphi0; - jacob(1, 2) = n * cosphi0; - jacob(1, 3) = -m * sinphi0; - - // Extrapolate track parameter covariances to "zEnd" - TMatrixD tmp(trackParam->getCovariances(), TMatrixD::kMultTranspose, jacob); - TMatrixD tmp2(jacob, TMatrixD::kMult, tmp); - trackParam->setCovariances(tmp2); - - // Update the propagator if required - if (updatePropagator) { - trackParam->updatePropagator(jacob); - } -} - -//__________________________________________________________________________ -void TrackExtrap::quadraticExtrapToZ(TrackParamMFT* trackParam, double zEnd) -{ - /// Track parameters extrapolated to the plane at "zEnd" considering a helix - /// On return, results from the extrapolation are updated in trackParam. - - if (trackParam->getZ() == zEnd) { - return; // nothing to be done if same z - } - - // Compute track parameters - auto dZ = (zEnd - trackParam->getZ()); - auto x0 = trackParam->getX(); - auto y0 = trackParam->getY(); - auto phi0 = trackParam->getPhi(); - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - auto invtanl0 = 1.0 / trackParam->getTanl(); - auto invqpt0 = trackParam->getInvQPt(); - auto Hz = getSignBz(); - auto k = TMath::Abs(o2::constants::math::B2C * getBz()); - auto n = dZ * invtanl0; - auto theta = -invqpt0 * dZ * k * invtanl0; - auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; - auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; - auto phi = phi0 + Hz * theta; - - trackParam->setX(x); - trackParam->setY(y); - trackParam->setZ(zEnd); - trackParam->setPhi(phi); -} - -//__________________________________________________________________________ -void TrackExtrap::quadraticExtrapToZCov(TrackParamMFT* trackParam, double zEnd, bool updatePropagator) -{ - - // Extrapolate track parameters and covariances matrix to "zEnd" - if (trackParam->getZ() == zEnd) { - return; // nothing to be done if same z - } - - // Compute track parameters - auto dZ = (zEnd - trackParam->getZ()); - auto x0 = trackParam->getX(); - auto y0 = trackParam->getY(); - auto phi0 = trackParam->getPhi(); - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - auto invtanl0 = 1.0 / trackParam->getTanl(); - auto invqpt0 = trackParam->getInvQPt(); - auto Hz = getSignBz(); - auto k = TMath::Abs(o2::constants::math::B2C * getBz()); - auto n = dZ * invtanl0; - auto m = n * invtanl0; - auto theta = -invqpt0 * dZ * k * invtanl0; - - // Extrapolate track parameters to "zEnd" - auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; - auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; - auto phi = phi0 + Hz * theta; - trackParam->setX(x); - trackParam->setY(y); - trackParam->setZ(zEnd); - trackParam->setPhi(phi); - - // Calculate Jacobian - TMatrixD jacob(5, 5); - jacob.UnitMatrix(); - jacob(0, 2) = -n * theta * 0.5 * Hz * cosphi0 - n * sinphi0; - jacob(0, 3) = Hz * m * theta * sinphi0 - m * cosphi0; - jacob(0, 4) = k * m * 0.5 * Hz * dZ * sinphi0; - jacob(1, 2) = -n * theta * 0.5 * Hz * sinphi0 + n * cosphi0; - jacob(1, 3) = -Hz * m * theta * cosphi0 - m * sinphi0; - jacob(1, 4) = -k * m * 0.5 * Hz * dZ * cosphi0; - jacob(2, 3) = -Hz * theta * invtanl0; - jacob(2, 4) = -Hz * k * n; - - // Extrapolate track parameter covariances to "zEnd" - TMatrixD tmp(trackParam->getCovariances(), TMatrixD::kMultTranspose, jacob); - TMatrixD tmp2(jacob, TMatrixD::kMult, tmp); - trackParam->setCovariances(tmp2); - - // Update the propagator if required - if (updatePropagator) { - trackParam->updatePropagator(jacob); - } -} - -//__________________________________________________________________________ -void TrackExtrap::helixExtrapToZ(TrackParamMFT* trackParam, double zEnd) -{ - /// Track parameters extrapolated to the plane at "zEnd" considering a helix - /// On return, results from the extrapolation are updated in trackParam. - - if (trackParam->getZ() == zEnd) { - return; // nothing to be done if same z - } - - // Compute track parameters - auto dZ = (zEnd - trackParam->getZ()); - auto x0 = trackParam->getX(); - auto y0 = trackParam->getY(); - auto phi0 = trackParam->getPhi(); - auto tanl0 = trackParam->getTanl(); - auto invtanl0 = 1.0 / tanl0; - auto invqpt0 = trackParam->getInvQPt(); - auto qpt0 = 1.0 / invqpt0; - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - auto k = TMath::Abs(o2::constants::math::B2C * getBz()); - auto invk = 1.0 / k; - auto theta = -invqpt0 * dZ * k * invtanl0; - double costheta, sintheta; - o2::utils::sincos(theta, sintheta, costheta); - auto Hz = getSignBz(); - auto Y = sinphi0 * qpt0 * invk; - auto X = cosphi0 * qpt0 * invk; - auto YC = Y * costheta; - auto YS = Y * sintheta; - auto XC = X * costheta; - auto XS = X * sintheta; - - // Extrapolate track parameters to "zEnd" - auto x = x0 + Hz * (Y - YC) - XS; - auto y = y0 + Hz * (-X + XC) - YS; - auto phi = phi0 + Hz * theta; - trackParam->setX(x); - trackParam->setY(y); - trackParam->setZ(zEnd); - trackParam->setPhi(phi); -} - -//__________________________________________________________________________ -void TrackExtrap::helixExtrapToZCov(TrackParamMFT* trackParam, double zEnd, bool updatePropagator) -{ - - // Extrapolate track parameters and covariances matrix to "zEnd" - auto dZ = (zEnd - trackParam->getZ()); - auto x0 = trackParam->getX(); - auto y0 = trackParam->getY(); - auto phi0 = trackParam->getPhi(); - auto tanl0 = trackParam->getTanl(); - auto invtanl0 = 1.0 / tanl0; - auto invqpt0 = trackParam->getInvQPt(); - auto qpt0 = 1.0 / invqpt0; - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - auto k = TMath::Abs(o2::constants::math::B2C * getBz()); - auto invk = 1.0 / k; - auto theta = -invqpt0 * dZ * k * invtanl0; - double costheta, sintheta; - o2::utils::sincos(theta, sintheta, costheta); - auto Hz = getSignBz(); - auto L = qpt0 * qpt0 * invk; - auto N = dZ * invtanl0 * qpt0; - auto O = sintheta * cosphi0; - auto P = sinphi0 * costheta; - auto R = sinphi0 * sintheta; - auto S = cosphi0 * costheta; - auto Y = sinphi0 * qpt0 * invk; - auto X = cosphi0 * qpt0 * invk; - auto YC = Y * costheta; - auto YS = Y * sintheta; - auto XC = X * costheta; - auto XS = X * sintheta; - auto T = qpt0 * costheta; - auto U = qpt0 * sintheta; - auto V = qpt0; - auto n = dZ * invtanl0; - auto m = n * invtanl0; - - // Extrapolate track parameters to "zEnd" - auto x = x0 + Hz * (Y - YC) - XS; - auto y = y0 + Hz * (-X + XC) - YS; - auto phi = phi0 + Hz * theta; - trackParam->setX(x); - trackParam->setY(y); - trackParam->setZ(zEnd); - trackParam->setPhi(phi); - - // Calculate Jacobian - TMatrixD jacob(5, 5); - jacob.UnitMatrix(); - jacob(0, 2) = Hz * X - Hz * XC + YS; - jacob(0, 3) = Hz * R * m - S * m; - jacob(0, 4) = -Hz * N * R + Hz * T * Y - Hz * V * Y + N * S + U * X; - jacob(1, 2) = Hz * Y - Hz * YC - XS; - jacob(1, 3) = -Hz * O * m - P * m; - jacob(1, 4) = Hz * N * O - Hz * T * X + Hz * V * X + N * P + U * Y; - jacob(2, 3) = -Hz * theta * invtanl0; - jacob(2, 4) = -Hz * k * n; - - // Extrapolate track parameter covariances to "zEnd" - TMatrixD tmp(trackParam->getCovariances(), TMatrixD::kMultTranspose, jacob); - TMatrixD tmp2(jacob, TMatrixD::kMult, tmp); - trackParam->setCovariances(tmp2); - - // Update the propagator if required - if (updatePropagator) { - trackParam->updatePropagator(jacob); - } -} - -//__________________________________________________________________________ -bool TrackExtrap::extrapToZ(TrackParamMFT* trackParam, double zEnd, bool isFieldON) -{ - /// Interface to track parameter extrapolation to the plane at "Z". - /// On return, the track parameters resulting from the extrapolation are updated in trackParam. - if (!isFieldON) { - linearExtrapToZ(trackParam, zEnd); - return true; - } else { - - quadraticExtrapToZ(trackParam, zEnd); - return true; - } -} - -//__________________________________________________________________________ -void TrackExtrap::extrapToZCov(TrackParamMFT* trackParam, double zEnd, bool updatePropagator, bool isFieldON) -{ - /// Track parameters and their covariances extrapolated to the plane at "zEnd". - /// On return, results from the extrapolation are updated in trackParam. - - auto& mftTrackingParam = MFTTrackingParam::Instance(); - - if (!isFieldON) { // linear extrapolation if no magnetic field - linearExtrapToZCov(trackParam, zEnd, updatePropagator); - return; - } else { - // Extrapolate track parameters to "zEnd" - - switch (mftTrackingParam.trackmodel) { - case Helix: - helixExtrapToZCov(trackParam, zEnd, updatePropagator); - return; - break; - case Quadratic: - quadraticExtrapToZCov(trackParam, zEnd, updatePropagator); - return; - break; - case Linear: - linearExtrapToZCov(trackParam, zEnd, updatePropagator); - return; - break; - } - } -} - -//__________________________________________________________________________ -void TrackExtrap::addMCSEffect(TrackParamMFT* trackParam, double dZ, double x0) -{ - /// Add to the track parameter covariances the effects of multiple Coulomb scattering - /// through a material of thickness "abs(dZ)" and of radiation length "x0" - /// assuming linear propagation and using the small angle approximation. - /// All scattering evaluated happens at the position of the first cluster - - bool debug = false; - auto phi0 = trackParam->getPhi(); - auto tanl0 = trackParam->getTanl(); - auto invtanl0 = 1.0 / tanl0; - auto invqpt0 = trackParam->getInvQPt(); - auto p = trackParam->getP(); - - double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); - - auto csclambda = TMath::Abs(TMath::Sqrt(1 + tanl0 * tanl0) * invtanl0); - auto pathLengthOverX0 = x0 * csclambda; - - // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory - auto sigmathetasq = 0.0136 * invqpt0 * (1 + 0.038 * TMath::Log(pathLengthOverX0)); - sigmathetasq *= sigmathetasq * pathLengthOverX0; - - // Get covariance matrix - TMatrixD newParamCov(trackParam->getCovariances()); - if (debug) { - std::cout << "Track covariances before MCS:"; - newParamCov.Print(); - } - - if (dZ > 0) { - auto A = tanl0 * tanl0 + 1; - auto B = dZ * cosphi0 * invtanl0; - auto C = dZ * sinphi0 * invtanl0; - auto D = A * B * invtanl0; - auto E = -A * C * invtanl0; - auto F = -C - D; - auto G = B + E; - auto H = -invqpt0 * tanl0; - - newParamCov(0, 0) += sigmathetasq * F * F; - - newParamCov(0, 1) += sigmathetasq * F * G; - newParamCov(1, 0) += sigmathetasq * F * G; - - newParamCov(1, 1) += sigmathetasq * G * G; - - newParamCov(2, 0) += sigmathetasq * F; - newParamCov(0, 2) += sigmathetasq * F; - - newParamCov(2, 1) += sigmathetasq * G; - newParamCov(1, 2) += sigmathetasq * G; - - newParamCov(2, 2) += sigmathetasq; - - newParamCov(3, 0) += sigmathetasq * A * F; - newParamCov(0, 3) += sigmathetasq * A * F; - - newParamCov(3, 1) += sigmathetasq * A * G; - newParamCov(1, 3) += sigmathetasq * A * G; - - newParamCov(3, 2) += sigmathetasq * A; - newParamCov(2, 3) += sigmathetasq * A; - - newParamCov(3, 3) += sigmathetasq * A * A; - - newParamCov(4, 0) += sigmathetasq * F * H; - newParamCov(0, 4) += sigmathetasq * F * H; - - newParamCov(4, 1) += sigmathetasq * G * H; - newParamCov(1, 4) += sigmathetasq * G * H; - - newParamCov(4, 2) += sigmathetasq * H; - newParamCov(2, 4) += sigmathetasq * H; - - newParamCov(4, 3) += sigmathetasq * A * H; - newParamCov(3, 4) += sigmathetasq * A * H; - - newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; - } else { - - auto A = tanl0 * tanl0 + 1; - auto H = -invqpt0 * tanl0; - - newParamCov(2, 2) += sigmathetasq; - - newParamCov(3, 2) += sigmathetasq * A; - newParamCov(2, 3) += sigmathetasq * A; - - newParamCov(3, 3) += sigmathetasq * A * A; - - newParamCov(4, 2) += sigmathetasq * H; - newParamCov(2, 4) += sigmathetasq * H; - - newParamCov(4, 3) += sigmathetasq * A * H; - newParamCov(3, 4) += sigmathetasq * A * H; - - newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; - } - - if (debug) { - std::cout << "Track covariances after MCS:"; - newParamCov.Print(); - std::cout << " **********************************************************\n"; - } - - // Set new covariances - trackParam->setCovariances(newParamCov); -} - -} // namespace mft -} // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 56b2bfd5f6686..588d8d8c50a4d 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -16,7 +16,6 @@ #include "MFTBase/Constants.h" #include "MFTTracking/TrackFitter.h" #include "MFTTracking/TrackCA.h" -#include "MFTTracking/TrackExtrap.h" #include "MFTTracking/Cluster.h" #include "DataFormatsMFT/TrackMFT.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx deleted file mode 100644 index 6442dc42fb885..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackParamMFT.cxx +++ /dev/null @@ -1,315 +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. - -/// \file TrackParamMFT.cxx -/// \brief Implementation of the MFT track parameters for internal use -/// -/// \author Philippe Pillot, Subatech; adapted by Rafael Pezzi, UFRGS - -#include "MFTTracking/TrackParamMFT.h" - -#include <iomanip> -#include <iostream> - -#include <TMath.h> - -#include <FairMQLogger.h> - -namespace o2 -{ -namespace mft -{ - -using namespace std; - -//_________________________________________________________________________ -TrackParamMFT::TrackParamMFT(const TrackParamMFT& tp) - : mZ(tp.mZ), - mParameters(tp.mParameters), - mClusterPtr(tp.mClusterPtr), - mRemovable(tp.mRemovable), - mTrackChi2(tp.mTrackChi2), - mLocalChi2(tp.mLocalChi2) -{ - /// Copy constructor - if (tp.mCovariances) - mCovariances = std::make_unique<TMatrixD>(*(tp.mCovariances)); - if (tp.mPropagator) - mPropagator = std::make_unique<TMatrixD>(*(tp.mPropagator)); - if (tp.mExtrapParameters) - mExtrapParameters = std::make_unique<TMatrixD>(*(tp.mExtrapParameters)); - if (tp.mExtrapCovariances) - mExtrapCovariances = std::make_unique<TMatrixD>(*(tp.mExtrapCovariances)); - if (tp.mSmoothParameters) - mSmoothParameters = std::make_unique<TMatrixD>(*(tp.mSmoothParameters)); - if (tp.mSmoothCovariances) - mSmoothCovariances = std::make_unique<TMatrixD>(*(tp.mSmoothCovariances)); -} - -//_________________________________________________________________________ -TrackParamMFT& TrackParamMFT::operator=(const TrackParamMFT& tp) -{ - /// Assignment operator - if (this == &tp) - return *this; - - mZ = tp.mZ; - - mParameters = tp.mParameters; - - if (tp.mCovariances) { - if (mCovariances) - *mCovariances = *(tp.mCovariances); - else - mCovariances = std::make_unique<TMatrixD>(*(tp.mCovariances)); - } else - mCovariances.reset(); - - if (tp.mPropagator) { - if (mPropagator) - *mPropagator = *(tp.mPropagator); - else - mPropagator = std::make_unique<TMatrixD>(*(tp.mPropagator)); - } else - mPropagator.reset(); - - if (tp.mExtrapParameters) { - if (mExtrapParameters) - *mExtrapParameters = *(tp.mExtrapParameters); - else - mExtrapParameters = std::make_unique<TMatrixD>(*(tp.mExtrapParameters)); - } else - mExtrapParameters.reset(); - - if (tp.mExtrapCovariances) { - if (mExtrapCovariances) - *mExtrapCovariances = *(tp.mExtrapCovariances); - else - mExtrapCovariances = std::make_unique<TMatrixD>(*(tp.mExtrapCovariances)); - } else - mExtrapCovariances.reset(); - - if (tp.mSmoothParameters) { - if (mSmoothParameters) - *mSmoothParameters = *(tp.mSmoothParameters); - else - mSmoothParameters = std::make_unique<TMatrixD>(*(tp.mSmoothParameters)); - } else - mSmoothParameters.reset(); - - if (tp.mSmoothCovariances) { - if (mSmoothCovariances) - *mSmoothCovariances = *(tp.mSmoothCovariances); - else - mSmoothCovariances = std::make_unique<TMatrixD>(*(tp.mSmoothCovariances)); - } else - mSmoothCovariances.reset(); - - mClusterPtr = tp.mClusterPtr; - - mRemovable = tp.mRemovable; - - mTrackChi2 = tp.mTrackChi2; - mLocalChi2 = tp.mLocalChi2; - - return *this; -} - -//__________________________________________________________________________ -void TrackParamMFT::clear() -{ - /// clear memory - deleteCovariances(); - mPropagator.reset(); - mExtrapParameters.reset(); - mExtrapCovariances.reset(); - mSmoothParameters.reset(); - mSmoothCovariances.reset(); -} - -//__________________________________________________________________________ -const TMatrixD& TrackParamMFT::getCovariances() const -{ - /// Return the covariance matrix (create it before if needed) - if (!mCovariances) { - mCovariances = std::make_unique<TMatrixD>(5, 5); - mCovariances->Zero(); - } - return *mCovariances; -} - -//__________________________________________________________________________ -void TrackParamMFT::setCovariances(const TMatrixD& covariances) -{ - /// Set the covariance matrix - if (mCovariances) - *mCovariances = covariances; - else - mCovariances = std::make_unique<TMatrixD>(covariances); -} - -//__________________________________________________________________________ -void TrackParamMFT::setCovariances(const Double_t matrix[5][5]) -{ - /// Set the covariance matrix - if (mCovariances) - mCovariances->SetMatrixArray(&(matrix[0][0])); - else - mCovariances = std::make_unique<TMatrixD>(5, 5, &(matrix[0][0])); -} - -//__________________________________________________________________________ -void TrackParamMFT::setVariances(const Double_t matrix[5][5]) -{ - /// Set the diagonal terms of the covariance matrix (variances) - if (!mCovariances) - mCovariances = std::make_unique<TMatrixD>(5, 5); - mCovariances->Zero(); - for (Int_t i = 0; i < 5; i++) - (*mCovariances)(i, i) = matrix[i][i]; -} - -//__________________________________________________________________________ -void TrackParamMFT::deleteCovariances() -{ - /// Delete the covariance matrix - mCovariances.reset(); -} - -//__________________________________________________________________________ -const TMatrixD& TrackParamMFT::getPropagator() const -{ - /// Return the propagator (create it before if needed) - if (!mPropagator) { - mPropagator = std::make_unique<TMatrixD>(5, 5); - mPropagator->UnitMatrix(); - } - return *mPropagator; -} - -//__________________________________________________________________________ -void TrackParamMFT::resetPropagator() -{ - /// Reset the propagator - if (mPropagator) - mPropagator->UnitMatrix(); -} - -//__________________________________________________________________________ -void TrackParamMFT::updatePropagator(const TMatrixD& propagator) -{ - /// Update the propagator - if (mPropagator) - *mPropagator = TMatrixD(propagator, TMatrixD::kMult, *mPropagator); - else - mPropagator = std::make_unique<TMatrixD>(propagator); -} - -//__________________________________________________________________________ -const TMatrixD& TrackParamMFT::getExtrapParameters() const -{ - /// Return extrapolated parameters (create it before if needed) - if (!mExtrapParameters) { - mExtrapParameters = std::make_unique<TMatrixD>(5, 1); - mExtrapParameters->Zero(); - } - return *mExtrapParameters; -} - -//__________________________________________________________________________ -void TrackParamMFT::setExtrapParameters(const TMatrixD& extrapParameters) -{ - /// Set extrapolated parameters - if (mExtrapParameters) - *mExtrapParameters = extrapParameters; - else - mExtrapParameters = std::make_unique<TMatrixD>(extrapParameters); -} - -//__________________________________________________________________________ -const TMatrixD& TrackParamMFT::getExtrapCovariances() const -{ - /// Return the extrapolated covariance matrix (create it before if needed) - if (!mExtrapCovariances) { - mExtrapCovariances = std::make_unique<TMatrixD>(5, 5); - mExtrapCovariances->Zero(); - } - return *mExtrapCovariances; -} - -//__________________________________________________________________________ -void TrackParamMFT::setExtrapCovariances(const TMatrixD& extrapCovariances) -{ - /// Set the extrapolated covariance matrix - if (mExtrapCovariances) - *mExtrapCovariances = extrapCovariances; - else - mExtrapCovariances = std::make_unique<TMatrixD>(extrapCovariances); -} - -//__________________________________________________________________________ -const TMatrixD& TrackParamMFT::getSmoothParameters() const -{ - /// Return the smoothed parameters (create it before if needed) - if (!mSmoothParameters) { - mSmoothParameters = std::make_unique<TMatrixD>(5, 1); - mSmoothParameters->Zero(); - } - return *mSmoothParameters; -} - -//__________________________________________________________________________ -void TrackParamMFT::setSmoothParameters(const TMatrixD& smoothParameters) -{ - /// Set the smoothed parameters - if (mSmoothParameters) { - *mSmoothParameters = smoothParameters; - } else { - mSmoothParameters = std::make_unique<TMatrixD>(smoothParameters); - } -} - -//__________________________________________________________________________ -const TMatrixD& TrackParamMFT::getSmoothCovariances() const -{ - /// Return the smoothed covariance matrix (create it before if needed) - if (!mSmoothCovariances) { - mSmoothCovariances = std::make_unique<TMatrixD>(5, 5); - mSmoothCovariances->Zero(); - } - return *mSmoothCovariances; -} - -//__________________________________________________________________________ -void TrackParamMFT::setSmoothCovariances(const TMatrixD& smoothCovariances) -{ - /// Set the smoothed covariance matrix - if (mSmoothCovariances) { - *mSmoothCovariances = smoothCovariances; - } else { - mSmoothCovariances = std::make_unique<TMatrixD>(smoothCovariances); - } -} - -//__________________________________________________________________________ -void TrackParamMFT::print() const -{ - /// Printing TrackParamMFT informations - LOG(INFO) << "TrackParamMFT: p =" << setw(5) << setprecision(3) << getP() - << " Tanl = " << setw(5) << setprecision(3) << getTanl() - << " phi = " << setw(5) << setprecision(3) << getPhi() - << " pz = " << setw(5) << setprecision(3) << getPz() - << " pt = " << setw(5) << setprecision(3) << getPt() - << " charge = " << setw(5) << setprecision(3) << getCharge() - << " chi2 = " << setw(5) << setprecision(3) << getTrackChi2() << endl; -} - -} // namespace mft -} // namespace o2 From 85e2c4a1cae80d6cb645f83eb0befca1b960b556 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Mon, 27 Jul 2020 14:17:58 +0000 Subject: [PATCH 0294/1751] Several fixes on forward tracking * Fix MCS Effects on TrackParCovFwd * Proper use of ROOT::Math::MatRepSym * Enabling MFT track fitter both directions * OutParameters fitted and stored on MFT Tracks * Track propagation methods: naming consistent with TrackPar (propagation instead of extrapolation) * Optimizations: removing unecessary local variables, trivial methods moved inline... --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 29 +---- .../Detectors/ITSMFT/MFT/src/TrackMFT.cxx | 6 - .../ReconstructionDataFormats/TrackFwd.h | 39 +++--- DataFormats/Reconstruction/src/TrackFwd.cxx | 121 +++++------------- .../tracking/include/MFTTracking/TrackCA.h | 14 +- .../include/MFTTracking/TrackFitter.h | 5 +- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 93 ++++++++------ Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 7 +- 8 files changed, 128 insertions(+), 186 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index 044916e678ebf..f87532f573a45 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -92,23 +92,8 @@ class TrackMFT : public o2::track::TrackParCovFwd void print() const; void printMCCompLabels() const; - // Parameters and Covariances on last track clusters - const SMatrix5& getParametersLast() const { return mParametersLast; } - void setParametersLast(const SMatrix5& parameters) { mParametersLast = parameters; } // Last cluster - const SMatrix55& getCovariancesLast() const; - void setCovariancesLast(const SMatrix55& covariances); - - Double_t getZLast() const { return mZLast; } - void setZLast(Double_t z) { mZLast = z; } - Double_t getXLast() const { return mParametersLast(0); } - Double_t getYLast() const { return mParametersLast(1); } - Double_t getPhiLast() const { return mParametersLast(2); } - Double_t getTanlLast() const { return mParametersLast(3); } - Double_t getInvQPtLast() const { return mParametersLast(4); } - Double_t getPtLast() const { return TMath::Abs(1.f / mParametersLast(4)); } - Double_t getInvPtLast() const { return TMath::Abs(mParametersLast(4)); } - Double_t getPLast() const { return getPtLast() * TMath::Sqrt(1. + getTanlLast() * getTanlLast()); } // return total momentum last cluster - Double_t getEtaLast() const { return -TMath::Log(TMath::Tan((TMath::PiOver2() - TMath::ATan(getTanlLast())) / 2)); } // return total momentum + const o2::track::TrackParCovFwd& GetOutParam() const { return mOutParameters; } + void SetOutParam(const o2::track::TrackParCovFwd parcov) { mOutParameters = parcov; } private: std::uint32_t mROFrame = 0; ///< RO Frame @@ -118,11 +103,8 @@ class TrackMFT : public o2::track::TrackParCovFwd ClusRefs mClusRef; ///< references on clusters - Double_t mZLast = 0.; ///< Z coordinate (cm) of Last cluster - - SMatrix5 mParametersLast; ///< \brief Track parameters at last cluster - SMatrix55 mCovariancesLast; ///< \brief Covariance matrix of track parameters at last cluster - + // Outward parameters for MCH matching + o2::track::TrackParCovFwd mOutParameters; // Results from quadratic regression of clusters X,Y positions // Chi2 of the quadratic regression used to estimate track pT and charge @@ -137,6 +119,9 @@ class TrackMFTExt : public TrackMFT { ///< heavy version of TrackMFT, with clusters embedded public: + TrackMFTExt() = default; + TrackMFTExt(const TrackMFTExt& t) = default; + ~TrackMFTExt() = default; static constexpr int MaxClusters = 10; using TrackMFT::TrackMFT; // inherit base constructors diff --git a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx index 9815fc55148db..b8315153d8e0b 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx +++ b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx @@ -26,12 +26,6 @@ namespace mft using SMatrix55 = ROOT::Math::SMatrix<double, 5, 5, ROOT::Math::MatRepSym<double, 5>>; using SMatrix5 = ROOT::Math::SVector<Double_t, 5>; -//__________________________________________________________________________ -void TrackMFT::setCovariancesLast(const SMatrix55& covariances) -{ - mCovariancesLast = covariances; -} - //__________________________________________________________________________ void TrackMFT::print() const { diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index 3ed90b8bc9c44..2ae69b75e63d7 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -95,12 +95,12 @@ class TrackParFwd /// set the chi2 of the track when the associated cluster was attached void setTrackChi2(Double_t chi2) { mTrackChi2 = chi2; } - // Track propagation - void linearExtrapToZ(double zEnd); - void quadraticExtrapToZ(double zEnd, double zField); - void helixExtrapToZ(double zEnd, double zField); + // Track parameter propagation + void propagateParamToZlinear(double zEnd); + void propagateParamToZquadratic(double zEnd, double zField); + void propagateParamToZhelix(double zEnd, double zField); - private: + protected: Double_t mZ = 0.; ///< Z coordinate (cm) /// Track parameters ordered as follow: <pre> @@ -122,25 +122,26 @@ class TrackParCovFwd : public TrackParFwd TrackParCovFwd() = default; ~TrackParCovFwd() = default; - - TrackParCovFwd(const TrackParCovFwd& tpf) = default; TrackParCovFwd& operator=(const TrackParCovFwd& tpf) = default; TrackParCovFwd(const Double_t z, const SMatrix5 parameters, const SMatrix55 covariances, const Double_t chi2); - const SMatrix55& getCovariances() const; - void setCovariances(const SMatrix55& covariances); - void deleteCovariances(); + const SMatrix55& getCovariances() const { return mCovariances; } + void setCovariances(const SMatrix55& covariances) { mCovariances = covariances; } + void deleteCovariances() { mCovariances = SMatrix55(); } + + Double_t getSigma2X() const { return mCovariances(0, 0); } + Double_t getSigma2Y() const { return mCovariances(1, 1); } + Double_t getSigma2Phi() const { return mCovariances(2, 2); } + Double_t getSigma2Tanl() const { return mCovariances(3, 3); } + Double_t getSigma2InvQPt() const { return mCovariances(4, 4); } - Double_t getSigmaX() const { return mCovariances(0, 0); } - Double_t getSigmaY() const { return mCovariances(1, 1); } - Double_t getSigmaPhi() const { return mCovariances(2, 2); } - Double_t getSigmaTanl() const { return mCovariances(3, 3); } - Double_t getSigmaInvQPt() const { return mCovariances(4, 4); } + // Propagate parameters and covariances matrix + void propagateToZlinear(double zEnd); + void propagateToZquadratic(double zEnd, double zField); + void propagateToZhelix(double zEnd, double zField); - void linearExtrapToZCov(double zEnd); - void quadraticExtrapToZCov(double zEnd, double zField); - void helixExtrapToZCov(double zEnd, double zField); - void addMCSEffect(double dZ, double x0); + // Add Multiple Coulomb Scattering effects + void addMCSEffect(double dZ, double x2X0); private: /// Covariance matrix of track parameters, ordered as follows: <pre> diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 6195fde4395dc..7e19da02e3d09 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -27,53 +27,9 @@ TrackParCovFwd::TrackParCovFwd(const Double_t z, const SMatrix5 parameters, cons } //__________________________________________________________________________ -const SMatrix55& TrackParCovFwd::getCovariances() const +void TrackParFwd::propagateParamToZlinear(double zEnd) { - /// Return the covariance matrix (create it before if needed) - return mCovariances; -} - -//__________________________________________________________________________ -void TrackParCovFwd::setCovariances(const SMatrix55& covariances) -{ - /// Set the covariance matrix - mCovariances = covariances; -} - -//__________________________________________________________________________ -void TrackParCovFwd::deleteCovariances() -{ - /// Delete the covariance matrix - mCovariances = SMatrix55(); -} - -/* //_________________________________________________________________________ -TrackParCovFwd& TrackParCovFwd::operator=(const TrackParCovFwd& tp) -{ - /// Assignment operator - if (this == &tp) - return *this; - - TrackParFwd::operator=(tp); - mCovariances = tp.mCovariances; - return *this; -} -*/ - -/* -//_________________________________________________________________________ -TrackParCovFwd::TrackParCovFwd(const TrackParCovFwd& tp) - : TrackParFwd(tp) -{ - /// Copy constructor - mCovariances = tp.mCovariances; -} -*/ - -//__________________________________________________________________________ -void TrackParFwd::linearExtrapToZ(double zEnd) -{ - /// Track linearly extrapolated to the plane at "zEnd". + // Track parameters linearly extrapolated to the plane at "zEnd". if (getZ() == zEnd) { return; // nothing to be done if same z @@ -96,10 +52,9 @@ void TrackParFwd::linearExtrapToZ(double zEnd) } //__________________________________________________________________________ -void TrackParCovFwd::linearExtrapToZCov(double zEnd) +void TrackParCovFwd::propagateToZlinear(double zEnd) { - /// Track parameters and their covariances linearly extrapolated to the plane at "zEnd". - /// On return, results from the extrapolation are updated in trackParam. + // Track parameters and their covariances linearly extrapolated to the plane at "zEnd". // Calculate the jacobian related to the track parameters extrapolated to "zEnd" auto dZ = (zEnd - getZ()); @@ -114,10 +69,8 @@ void TrackParCovFwd::linearExtrapToZCov(double zEnd) auto m = n * invtanl0; // Extrapolate track parameters to "zEnd" - auto x = x0 + n * cosphi0; - auto y = y0 + n * sinphi0; - setX(x); - setY(y); + mParameters(0) += n * cosphi0; + mParameters(1) += n * sinphi0; setZ(zEnd); // Calculate Jacobian @@ -132,10 +85,9 @@ void TrackParCovFwd::linearExtrapToZCov(double zEnd) } //__________________________________________________________________________ -void TrackParFwd::quadraticExtrapToZ(double zEnd, double zField) +void TrackParFwd::propagateParamToZquadratic(double zEnd, double zField) { - /// Track parameters extrapolated to the plane at "zEnd" considering a helix - /// On return, results from the extrapolation are updated in trackParam. + // Track parameters extrapolated to the plane at "zEnd" considering a helix if (getZ() == zEnd) { return; // nothing to be done if same z @@ -143,8 +95,6 @@ void TrackParFwd::quadraticExtrapToZ(double zEnd, double zField) // Compute track parameters auto dZ = (zEnd - getZ()); - auto x0 = getX(); - auto y0 = getY(); auto phi0 = getPhi(); double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); @@ -154,21 +104,19 @@ void TrackParFwd::quadraticExtrapToZ(double zEnd, double zField) auto k = TMath::Abs(o2::constants::math::B2C * zField); auto n = dZ * invtanl0; auto theta = -invqpt0 * dZ * k * invtanl0; - auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; - auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; - auto phi = phi0 + Hz * theta; - setX(x); - setY(y); + mParameters(0) += n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; + mParameters(1) += n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; + mParameters(2) += Hz * theta; setZ(zEnd); - setPhi(phi); } //__________________________________________________________________________ -void TrackParCovFwd::quadraticExtrapToZCov(double zEnd, double zField) +void TrackParCovFwd::propagateToZquadratic(double zEnd, double zField) { - // Extrapolate track parameters and covariances matrix to "zEnd" + // using quadratic track model + if (getZ() == zEnd) { return; // nothing to be done if same z } @@ -213,10 +161,10 @@ void TrackParCovFwd::quadraticExtrapToZCov(double zEnd, double zField) } //__________________________________________________________________________ -void TrackParFwd::helixExtrapToZ(double zEnd, double zField) +void TrackParFwd::propagateParamToZhelix(double zEnd, double zField) { - /// Track parameters extrapolated to the plane at "zEnd" considering a helix - /// On return, results from the extrapolation are updated in trackParam. + // Track parameters extrapolated to the plane at "zEnd" + // using helix track model if (getZ() == zEnd) { return; // nothing to be done if same z @@ -257,10 +205,11 @@ void TrackParFwd::helixExtrapToZ(double zEnd, double zField) } //__________________________________________________________________________ -void TrackParCovFwd::helixExtrapToZCov(double zEnd, double zField) +void TrackParCovFwd::propagateToZhelix(double zEnd, double zField) { - // Extrapolate track parameters and covariances matrix to "zEnd" + // using helix track model + auto dZ = (zEnd - getZ()); auto x0 = getX(); auto y0 = getY(); @@ -320,27 +269,28 @@ void TrackParCovFwd::helixExtrapToZCov(double zEnd, double zField) } //__________________________________________________________________________ -void TrackParCovFwd::addMCSEffect(double dZ, double x0) +void TrackParCovFwd::addMCSEffect(double dZ, double x_over_X0) { - /// Add to the track parameter covariances the effects of multiple Coulomb scattering - /// through a material of thickness "abs(dZ)" and of radiation length "x0" - /// assuming linear propagation and using the small angle approximation. - /// All scattering evaluated happens at the position of the first cluster + /// Add multiple Coulomb scattering effects to the track parameter covariances. + /// * if (dZ > 0): MCS effects are evaluated with a linear propagation model. + /// * if (dZ <= 0): only angular MCS effects are evaluated as if dZ = 0. + /// * x_over_X0 is the fraction of the radiation lenght (x/X0). + /// * No energy loss correction. + /// * All scattering evaluated at the position of the first cluster. auto phi0 = getPhi(); auto tanl0 = getTanl(); auto invtanl0 = 1.0 / tanl0; auto invqpt0 = getInvQPt(); - auto p = getP(); double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); auto csclambda = TMath::Abs(TMath::Sqrt(1 + tanl0 * tanl0) * invtanl0); - auto pathLengthOverX0 = x0 * csclambda; + auto pathLengthOverX0 = x_over_X0 * csclambda; // // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory - auto sigmathetasq = 0.0136 * invqpt0 * (1 + 0.038 * TMath::Log(pathLengthOverX0)); + auto sigmathetasq = 0.0136 * getInverseMomentum() * (1 + 0.038 * TMath::Log(pathLengthOverX0)); sigmathetasq *= sigmathetasq * pathLengthOverX0; // Get covariance matrix @@ -359,40 +309,30 @@ void TrackParCovFwd::addMCSEffect(double dZ, double x0) newParamCov(0, 0) += sigmathetasq * F * F; newParamCov(0, 1) += sigmathetasq * F * G; - newParamCov(1, 0) += sigmathetasq * F * G; newParamCov(1, 1) += sigmathetasq * G * G; newParamCov(2, 0) += sigmathetasq * F; - newParamCov(0, 2) += sigmathetasq * F; newParamCov(2, 1) += sigmathetasq * G; - newParamCov(1, 2) += sigmathetasq * G; newParamCov(2, 2) += sigmathetasq; newParamCov(3, 0) += sigmathetasq * A * F; - newParamCov(0, 3) += sigmathetasq * A * F; newParamCov(3, 1) += sigmathetasq * A * G; - newParamCov(1, 3) += sigmathetasq * A * G; newParamCov(3, 2) += sigmathetasq * A; - newParamCov(2, 3) += sigmathetasq * A; newParamCov(3, 3) += sigmathetasq * A * A; newParamCov(4, 0) += sigmathetasq * F * H; - newParamCov(0, 4) += sigmathetasq * F * H; newParamCov(4, 1) += sigmathetasq * G * H; - newParamCov(1, 4) += sigmathetasq * G * H; newParamCov(4, 2) += sigmathetasq * H; - newParamCov(2, 4) += sigmathetasq * H; newParamCov(4, 3) += sigmathetasq * A * H; - newParamCov(3, 4) += sigmathetasq * A * H; newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; } else { @@ -403,15 +343,12 @@ void TrackParCovFwd::addMCSEffect(double dZ, double x0) newParamCov(2, 2) += sigmathetasq; newParamCov(3, 2) += sigmathetasq * A; - newParamCov(2, 3) += sigmathetasq * A; newParamCov(3, 3) += sigmathetasq * A * A; newParamCov(4, 2) += sigmathetasq * H; - newParamCov(2, 4) += sigmathetasq * H; newParamCov(4, 3) += sigmathetasq * A * H; - newParamCov(3, 4) += sigmathetasq * A * H; newParamCov(4, 4) += sigmathetasq * tanl0 * tanl0 * invqpt0 * invqpt0; } diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index 5d7f35d14f716..558c7e06982b7 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -29,6 +29,9 @@ namespace mft class TrackLTF : public TrackMFTExt { public: + TrackLTF() = default; + TrackLTF(const TrackLTF& t) = default; + ~TrackLTF() = default; const Int_t getNPoints() const { return mNPoints; } const std::array<Float_t, constants::mft::LayersNumber>& getXCoordinates() const { return mX; } const std::array<Float_t, constants::mft::LayersNumber>& getYCoordinates() const { return mY; } @@ -55,6 +58,7 @@ class TrackCA : public TrackLTF { public: TrackCA() = default; + TrackCA(const TrackCA& t) = default; ~TrackCA() = default; void addCell(const Int_t, const Int_t); void removeLastCell(Int_t&, Int_t&); @@ -139,14 +143,13 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z inline void TrackLTF::sort() { // Orders elements along z position - struct ClusterData { Float_t x; Float_t y; Float_t z; - Float_t layer; - Float_t clusterId; - Float_t label; + Int_t layer; + Int_t clusterId; + Int_t label; }; std::vector<ClusterData> points; @@ -162,9 +165,8 @@ inline void TrackLTF::sort() std::sort(points.begin(), points.end(), [](ClusterData a, ClusterData b) { return a.z > b.z; }); - // after sorting + // Storing sorted cluster data for (Int_t point = 0; point < getNPoints(); ++point) { - // auto& somepoint = points.emplace_back(); mX[point] = points[point].x; mY[point] = points[point].y; mZ[point] = points[point].z; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h index 5b6a9ba3027ad..b41ed70bc512a 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h @@ -46,7 +46,8 @@ class TrackFitter void setBz(float bZ); - bool fit(TrackLTF& track); + bool initTrack(TrackLTF& track, bool outward = false); + bool fit(TrackLTF& track, bool outward = false); bool runKalmanFilter(TrackLTF& track, int cluster); @@ -54,7 +55,6 @@ class TrackFitter static constexpr double getMaxChi2() { return SMaxChi2; } private: - bool initTrack(TrackLTF& track); bool addCluster(TrackLTF& track, int cluster); Float_t mBZField; // kiloGauss. @@ -64,7 +64,6 @@ class TrackFitter 0.035, 0.035, 0.035, 0.035, 0.035}; bool mFieldON = true; - //o2::mft::TrackExtrap mTrackExtrap; }; // Functions to estimate momentum and charge from track curvature diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 588d8d8c50a4d..47c8569a4a113 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -43,7 +43,6 @@ void TrackFitter::setBz(float bZ) /// Set the magnetic field for the MFT mBZField = bZ; - //mTrackExtrap.setBz(bZ); if (mftTrackingParam.verbose) { LOG(INFO) << "Setting Fitter field = " << bZ; @@ -51,7 +50,7 @@ void TrackFitter::setBz(float bZ) } //_________________________________________________________________________________________________ -bool TrackFitter::fit(TrackLTF& track) +bool TrackFitter::fit(TrackLTF& track, bool outward) { /// Fit a track to its attached clusters @@ -66,7 +65,6 @@ bool TrackFitter::fit(TrackLTF& track) std::cout << "N Clusters = " << nClusters << std::endl; } - initTrack(track); if (mftTrackingParam.verbose) { std::cout << "Seed covariances: \n"; @@ -74,14 +72,23 @@ bool TrackFitter::fit(TrackLTF& track) std::cout << std::endl; } - // recusively add the upstream clusters and update the track parameters - nClusters--; - while (nClusters-- > 0) { - if (!addCluster(track, nClusters)) { - return false; + // recursively add clusters and update the track parameters + if (!outward) { // Inward + nClusters--; + while (nClusters-- > 0) { + if (!addCluster(track, nClusters)) { + return false; + } + } + } else { // Outward for MCH matching + int ncl = 1; + while (ncl < nClusters) { + if (!addCluster(track, ncl)) { + return false; + } + ncl++; } } - if (mftTrackingParam.verbose) { // std::cout << "Track covariances:"; // trac->getCovariances().Print(); @@ -93,7 +100,7 @@ bool TrackFitter::fit(TrackLTF& track) } //_________________________________________________________________________________________________ -bool TrackFitter::initTrack(TrackLTF& track) +bool TrackFitter::initTrack(TrackLTF& track, bool outward) { // initialize the starting track parameters and cluster double chi2invqptquad; @@ -104,17 +111,23 @@ bool TrackFitter::initTrack(TrackLTF& track) track.setChi2QPtQuadtratic(chi2invqptquad); track.setInvQPt(invpqtquad); - /// Compute the initial track parameters at the z position of the last cluster (cl) + /// Compute the initial track parameters /// The covariance matrix is computed such that the last cluster is the only constraint /// (by assigning an infinite dispersion to the other cluster) /// These parameters are the seed for the Kalman filter auto& mftTrackingParam = MFTTrackingParam::Instance(); - // compute the track parameters at the last cluster - double x0 = track.getXCoordinates()[nPoints - 1]; - double y0 = track.getYCoordinates()[nPoints - 1]; - double z0 = track.getZCoordinates()[nPoints - 1]; + // compute track parameters + int where; // First or last cluster? + if (outward) + where = 0; + else + where = nPoints - 1; + + double x0 = track.getXCoordinates()[where]; + double y0 = track.getYCoordinates()[where]; + double z0 = track.getZCoordinates()[where]; double pt = TMath::Sqrt(x0 * x0 + y0 * y0); double pz = z0; double phi0 = TMath::ATan2(y0, x0); @@ -165,7 +178,6 @@ bool TrackFitter::initTrack(TrackLTF& track) // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) SMatrix55 lastParamCov; - //lastParamCov.Zero(); lastParamCov(0, 0) = sigmax0sq; // <X,X> lastParamCov(0, 1) = 0; // <Y,X> lastParamCov(0, 2) = sigmaboost * -sigmax0sq * y0 * invr0sq; // <PHI,X> @@ -186,17 +198,6 @@ bool TrackFitter::initTrack(TrackLTF& track) lastParamCov(4, 4) = sigmaboost * sigmaboost * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0) * invr0cu * invr0cu; // <INVQPT,INVQPT> - lastParamCov(1, 0) = lastParamCov(0, 1); // - lastParamCov(2, 0) = lastParamCov(0, 2); // - lastParamCov(2, 1) = lastParamCov(1, 2); // - lastParamCov(3, 0) = lastParamCov(0, 3); // - lastParamCov(3, 1) = lastParamCov(1, 3); // - lastParamCov(3, 2) = lastParamCov(2, 3); // - lastParamCov(4, 0) = lastParamCov(0, 4); // - lastParamCov(4, 1) = lastParamCov(1, 4); // - lastParamCov(4, 2) = lastParamCov(2, 4); // - lastParamCov(4, 3) = lastParamCov(3, 4); // - track.setCovariances(lastParamCov); track.setTrackChi2(0.); @@ -205,7 +206,7 @@ bool TrackFitter::initTrack(TrackLTF& track) bool TrackFitter::addCluster(TrackLTF& track, int cluster) { - /// Extrapolate the starting track parameters to the z position of the new cluster + /// Propagate track to the z position of the new cluster /// accounting for MCS dispersion in the current layer and the other(s) crossed /// Recompute the parameters adding the cluster constraint with the Kalman filter /// Returns false in case of failure @@ -215,11 +216,10 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) const auto& cly = track.getYCoordinates()[cluster]; const auto& clz = track.getZCoordinates()[cluster]; - if (track.getZ() >= clz) { + if (track.getZ() == clz) { LOG(INFO) << "AddCluster ERROR: The new cluster must be upstream! Bug on TrackFinder. " << (track.isCA() ? " CATrack" : "LTFTrack"); - LOG(INFO) << "track.getZ() = " << track.getZ() << " ; newClusterZ = " << clz; - - //return false; + LOG(INFO) << "track.getZ() = " << track.getZ() << " ; newClusterZ = " << clz << " ==> Skipping point."; + return true; } if (mftTrackingParam.verbose) std::cout << "addCluster: X = " << clx << " Y = " << cly << " Z = " << clz << " nCluster = " << cluster << std::endl; @@ -228,7 +228,7 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) using o2::mft::constants::LayerZPosition; int startingLayerID, newLayerID; - double dZ = TMath::Abs(clz - track.getZ()); + double dZ = clz - track.getZ(); //LayerID of each cluster from ZPosition // TODO: Use ChipMapping for (auto layer = 10; layer--;) if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3) @@ -237,7 +237,11 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) if (clz<LayerZPosition[layer] + .3 & clz> LayerZPosition[layer] - .3) newLayerID = layer; // Number of disks crossed by this tracklet - int NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; + int NDisksMS; + if (clz - track.getZ() > 0) + NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; + else + NDisksMS = (startingLayerID % 2 == 0) ? (newLayerID - startingLayerID + 1) / 2 : (newLayerID - startingLayerID) / 2; double MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0; if (mftTrackingParam.verbose) { @@ -254,8 +258,23 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) if (mftTrackingParam.verbose) std::cout << " BeforeExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; - // extrapolate to the z position of the new cluster - track.helixExtrapToZCov(clz, mBZField); + // Propagate track to the z position of the new cluster + switch (mftTrackingParam.trackmodel) { + case Linear: + track.propagateToZlinear(clz); + break; + case Quadratic: + track.propagateToZquadratic(clz, mBZField); + break; + case Helix: + track.propagateToZhelix(clz, mBZField); + break; + default: + std::cout << " Invalid track model.\n"; + return false; + break; + } + if (mftTrackingParam.verbose) std::cout << " AfterExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; @@ -277,7 +296,7 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) bool TrackFitter::runKalmanFilter(TrackLTF& track, int cluster) { /// Compute the new track parameters including the attached cluster with the Kalman filter - /// The current parameters are supposed to have been extrapolated to the cluster z position + /// The current track is expected to have been propagated to the cluster z position /// Retruns false in case of failure // get propagated track parameters (p) diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index ff0caae2aed09..644e21939554c 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -28,7 +28,7 @@ namespace mft Tracker::Tracker(bool useMC) : mUseMC{useMC} { - /// Prepare the track extrapolation tools + /// Configure track propagation LOG(INFO) << "initializing track fitter"; mTrackFitter = std::make_unique<o2::mft::TrackFitter>(); mTrackFitter->setBz(mBz); @@ -851,7 +851,12 @@ const Bool_t Tracker::LinearRegression(Int_t npoints, Float_t* x, Float_t* y, Fl bool Tracker::fitTracks(ROframe& event) { for (auto& track : event.getTracksLTF()) { + TrackLTF outParam = track; + mTrackFitter->initTrack(track); mTrackFitter->fit(track); + mTrackFitter->initTrack(outParam, true); + mTrackFitter->fit(outParam, true); + track.SetOutParam(outParam); } for (auto& track : event.getTracksCA()) { track.sort(); From 102f118e63bb0d5825001e787f1d40bb378b410c Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Mon, 27 Jul 2020 19:49:13 -0300 Subject: [PATCH 0295/1751] Corrections for low momentum MFT track seed parameters --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 22 ++- .../include/MFTTracking/MFTTrackingParam.h | 1 - .../include/MFTTracking/TrackFitter.h | 2 - .../tracking/include/MFTTracking/Tracker.h | 2 +- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 166 ++++-------------- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 29 ++- 6 files changed, 75 insertions(+), 147 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index f87532f573a45..d9417556f6978 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -45,13 +45,13 @@ class TrackMFT : public o2::track::TrackParCovFwd const Bool_t isCA() const { return mIsCA; } const Bool_t isLTF() const { return !mIsCA; } - // Charge and momentum from quadratic regression of clusters X,Y positions - void setInvQPtQuadtratic(Double_t invqpt) { mInvQPtQuadtratic = invqpt; } - const Double_t getInvQPtQuadtratic() const { return mInvQPtQuadtratic; } // Inverse charged pt - const Double_t getPtQuadtratic() const { return TMath::Abs(1.f / getInvQPtQuadtratic()); } - const Double_t getChargeQuadratic() const { return TMath::Sign(1., getInvQPtQuadtratic()); } - void setChi2QPtQuadtratic(Double_t chi2) { mQuadraticFitChi2 = chi2; } - const Double_t getChi2QPtQuadtratic() const { return mQuadraticFitChi2; } + // Tracking seed charge and momentum from Fast Circle Fit of clusters X,Y positions + void setInvQPtSeed(Double_t invqpt) { mInvQPtSeed = invqpt; } + const Double_t getInvQPtSeed() const { return mInvQPtSeed; } // Inverse charged pt + const Double_t getPtSeed() const { return TMath::Abs(1.f / getInvQPtSeed()); } + const Double_t getChargeSeed() const { return TMath::Sign(1., getInvQPtSeed()); } + void setChi2QPtSeed(Double_t chi2) { mSeedinvQPtFitChi2 = chi2; } + const Double_t getChi2QPtSeed() const { return mSeedinvQPtFitChi2; } // Other functions int getNumberOfClusters() const { return mClusRef.getEntries(); } @@ -106,11 +106,9 @@ class TrackMFT : public o2::track::TrackParCovFwd // Outward parameters for MCH matching o2::track::TrackParCovFwd mOutParameters; - // Results from quadratic regression of clusters X,Y positions - // Chi2 of the quadratic regression used to estimate track pT and charge - Double_t mQuadraticFitChi2 = 0.; - // inversed charged momentum from quadratic regression - Double_t mInvQPtQuadtratic; + // Seed InveQPt and Chi2 from fitting clusters X,Y positions + Double_t mSeedinvQPtFitChi2 = 0.; + Double_t mInvQPtSeed; ClassDefNV(TrackMFT, 1); }; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h index 9b5e635bbf4fa..6735b02ca1765 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h @@ -23,7 +23,6 @@ namespace mft enum MFTTrackingSeed { AB, // - CE, DH }; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h index b41ed70bc512a..3bbcf41f9b0cc 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h @@ -67,8 +67,6 @@ class TrackFitter }; // Functions to estimate momentum and charge from track curvature -Double_t invQPtFromParabola2(const TrackLTF& track, double bFieldZ, Double_t& chi2); -Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2); Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2); Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yErr, Double_t& a, Double_t& ae, Double_t& b, Double_t& be); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 4ad05d364c78c..e18529353bc4c 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -43,7 +43,7 @@ class Tracker Tracker(const Tracker&) = delete; Tracker& operator=(const Tracker&) = delete; - void setBz(Float_t bz) { mBz = bz; } + void setBz(Float_t bz); const Float_t getBz() const { return mBz; } std::vector<TrackMFT>& getTracks(); diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 47c8569a4a113..f08ef991e0197 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -61,15 +61,9 @@ bool TrackFitter::fit(TrackLTF& track, bool outward) auto nClusters = track.getNPoints(); if (mftTrackingParam.verbose) { - std::cout << "\n ***************************** Start Fitting new track ***************************** \n"; - std::cout << "N Clusters = " << nClusters << std::endl; - } - - - if (mftTrackingParam.verbose) { - std::cout << "Seed covariances: \n"; - track.getCovariances().Print(std::cout); - std::cout << std::endl; + std::cout << "Seed covariances: \n" + << track.getCovariances() << std::endl + << std::endl; } // recursively add clusters and update the track parameters @@ -102,22 +96,32 @@ bool TrackFitter::fit(TrackLTF& track, bool outward) //_________________________________________________________________________________________________ bool TrackFitter::initTrack(TrackLTF& track, bool outward) { + + auto& mftTrackingParam = MFTTrackingParam::Instance(); + // initialize the starting track parameters and cluster double chi2invqptquad; - double invpqtquad; + double invQPtSeed; auto nPoints = track.getNPoints(); - invpqtquad = invQPtFromFCF(track, mBZField, chi2invqptquad); - track.setInvQPtQuadtratic(invpqtquad); - track.setChi2QPtQuadtratic(chi2invqptquad); - track.setInvQPt(invpqtquad); + auto k = TMath::Abs(o2::constants::math::B2C * mBZField); + auto Hz = std::copysign(1, mBZField); + //invQPtSeed = invQPtFromParabola(track, mBZField, chi2invqptquad); + invQPtSeed = invQPtFromFCF(track, mBZField, chi2invqptquad); + + if (mftTrackingParam.verbose) { + std::cout << "\n ***************************** Start Fitting new track ***************************** \n"; + std::cout << "N Clusters = " << nPoints << std::endl; + } + + track.setInvQPtSeed(invQPtSeed); + track.setChi2QPtSeed(chi2invqptquad); + track.setInvQPt(invQPtSeed); /// Compute the initial track parameters /// The covariance matrix is computed such that the last cluster is the only constraint /// (by assigning an infinite dispersion to the other cluster) /// These parameters are the seed for the Kalman filter - auto& mftTrackingParam = MFTTrackingParam::Instance(); - // compute track parameters int where; // First or last cluster? if (outward) @@ -128,10 +132,13 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) double x0 = track.getXCoordinates()[where]; double y0 = track.getYCoordinates()[where]; double z0 = track.getZCoordinates()[where]; - double pt = TMath::Sqrt(x0 * x0 + y0 * y0); - double pz = z0; - double phi0 = TMath::ATan2(y0, x0); - double tanl = pz / pt; + double deltaX = track.getXCoordinates()[nPoints - 1] - track.getXCoordinates()[0]; + double deltaY = track.getYCoordinates()[nPoints - 1] - track.getYCoordinates()[0]; + double deltaZ = track.getZCoordinates()[nPoints - 1] - track.getZCoordinates()[0]; + double deltaR = TMath::Sqrt(deltaX * deltaX + deltaY * deltaY); + double tanl = 0.5 * TMath::Sqrt(2) * (deltaZ / deltaR) * + TMath::Sqrt(TMath::Sqrt((invQPtSeed * deltaR * k) * (invQPtSeed * deltaR * k) + 1) + 1); + double phi0 = TMath::ATan2(y0, x0) + 0.5 * Hz * invQPtSeed * deltaZ * k / tanl; double r0sq = x0 * x0 + y0 * y0; double r0cu = r0sq * TMath::Sqrt(r0sq); double invr0sq = 1.0 / r0sq; @@ -152,22 +159,17 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) switch (mftTrackingParam.seed) { case AB: if (mftTrackingParam.verbose) - std::cout << " Init track with Seed A / B; sigmaboost = " << sigmaboost << ".\n"; - track.setInvQPt(1.0 / pt); // Seeds A & B - break; - case CE: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed C / E; sigmaboost = " << sigmaboost << ".\n"; - track.setInvQPt(std::copysign(1.0, track.getInvQPt()) / pt); // Seeds C & E + std::cout << " Init track with Seed A / B; sigmaboost = " << sigmaboost << (track.isCA() ? " CA Track " : " LTF Track") << std::endl; + track.setInvQPt(1.0 / TMath::Sqrt(x0 * x0 + y0 * y0)); // Seeds A & B break; case DH: if (mftTrackingParam.verbose) - std::cout << " Init track with Seed H; (k = " << seedH_k << "); sigmaboost = " << sigmaboost << ".\n"; + std::cout << " Init track with Seed H; (k = " << seedH_k << "); sigmaboost = " << sigmaboost << (track.isCA() ? " CA Track " : " LTF Track") << std::endl; track.setInvQPt(track.getInvQPt() / seedH_k); // SeedH break; default: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed D.\n"; + LOG(ERROR) << "Invalid MFT tracking seed"; + return false; break; } if (mftTrackingParam.verbose) { @@ -204,6 +206,7 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) return true; } +//_________________________________________________________________________________________________ bool TrackFitter::addCluster(TrackLTF& track, int cluster) { /// Propagate track to the z position of the new cluster @@ -343,94 +346,7 @@ bool TrackFitter::runKalmanFilter(TrackLTF& track, int cluster) return true; } -//__________________________________________________________________________ -Double_t invQPtFromParabola2(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) -{ - auto nPoints = track.getNPoints(); - - const std::array<Float_t, constants::mft::LayersNumber>& xPositons = track.getXCoordinates(); - const std::array<Float_t, constants::mft::LayersNumber>& yPositons = track.getYCoordinates(); - - //rotate track to stabilize quadratic fitting - auto deltax = xPositons[0] - xPositons[nPoints - 1]; - auto deltay = yPositons[0] - yPositons[nPoints - 1]; - //auto x_m = (xPositons[nPoints - 1] + xPositons[0]) / 2; - //auto y_m = (yPositons[nPoints - 1] + yPositons[0]) / 2; - auto theta = -TMath::ATan2(deltay, deltax); - auto costheta = TMath::Cos(theta), sintheta = TMath::Sin(theta); - - bool verbose = false; - if (verbose) { - std::cout << "First and last cluster X,Y => " << xPositons[0] << " , " << yPositons[0] << " / " << xPositons[nPoints - 1] << " , " << yPositons[nPoints - 1] << std::endl; - std::cout << " Angle to rotate: " << theta << " ( " << theta * TMath::RadToDeg() << " deg ) ; nPoints = " << nPoints << std::endl; - } - - Double_t* x = new Double_t[nPoints]; - Double_t* y = new Double_t[nPoints]; - for (auto n = 0; n < nPoints; n++) { - auto x_0 = xPositons[n]; // - x_m; - auto y_0 = yPositons[n]; // - y_m; - x[n] = x_0 * costheta - y_0 * sintheta; - y[n] = x_0 * sintheta + y_0 * costheta; - if (verbose) - std::cout << " adding rotated point to fit at z = " << track.getZCoordinates()[n] << " (" << x[n] << "," << y[n] << ") " << std::endl; - } - - Double_t q0, q1, q2; - chi2 = QuadraticRegression2(nPoints, x, y, q0, q1, q2); - Double_t radiusParabola = 0.5 / q2; - auto invqpt_parabola = q2 / (o2::constants::math::B2C * bFieldZ * 0.5); // radiusParabola; // radius = 0.5/q2 - - if (verbose) { - std::cout << "--------------------------------------------" << std::endl; - std::cout << " Fit QuadraticRegression: " << std::endl; - std::cout << " Fit Parameters [0] = " << q0 << " [1] = " << q1 << " [2] = " << q2 << std::endl; - std::cout << " Radius from QuadraticRegression = " << 0.5 / q2 << std::endl; - std::cout << " Seed qpt = " << 1.0 / invqpt_parabola << std::endl; - std::cout << "--------------------------------------------" << std::endl; - } - - return invqpt_parabola; -} - -//__________________________________________________________________________ -Double_t QuadraticRegression2(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t& p0, Double_t& p1, Double_t& p2) -{ - /// Perform a Quadratic Regression - /// Assume same error on all clusters = 1 - /// Return ~ Chi2 - - TMatrixD y(nVal, 1); - TMatrixD x(nVal, 3); - TMatrixD xtrans(3, nVal); - - for (int i = 0; i < nVal; i++) { - y(i, 0) = yVal[i]; - x(i, 0) = 1.; - x(i, 1) = xVal[i]; - x(i, 2) = xVal[i] * xVal[i]; - xtrans(0, i) = 1.; - xtrans(1, i) = xVal[i]; - xtrans(2, i) = xVal[i] * xVal[i]; - } - TMatrixD tmp(xtrans, TMatrixD::kMult, x); - tmp.Invert(); - - TMatrixD tmp2(xtrans, TMatrixD::kMult, y); - TMatrixD b(tmp, TMatrixD::kMult, tmp2); - - p0 = b(0, 0); - p1 = b(1, 0); - p2 = b(2, 0); - - // chi2 = (y-xb)^t . W . (y-xb) - TMatrixD tmp3(x, TMatrixD::kMult, b); - TMatrixD tmp4(y, TMatrixD::kMinus, tmp3); - TMatrixD chi2(tmp4, TMatrixD::kTransposeMult, tmp4); - - return chi2(0, 0); -} - +//_________________________________________________________________________________________________ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) { @@ -451,8 +367,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) Double_t a, ae, b, be, x2, y2, invx2y2, rx, ry, r; for (auto np = 0; np < nPoints; np++) { - //printf("BV track %d %f %f %f \n", np, trackparam->getClusterPtr()->getX(), trackparam->getClusterPtr()->getY(), trackparam->getClusterPtr()->getZ()); - xErr[np] = 5e-4; // FIXME + xErr[np] = 5e-4; // FIXME -> errors from clusters yErr[np] = 5e-4; // FIXME if (np > 0) { xVal[np] = xPositons[np] - xVal[0]; @@ -500,11 +415,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) Double_t sinSlope = TMath::Sin(slope); Double_t rxRot = rx * cosSlope + ry * sinSlope; Double_t ryRot = rx * sinSlope - ry * cosSlope; - qfcf = (ryRot < 0.) ? -1 : +1; - //printf("BV r-quad %f , r-fcf %f q-fcf %f \n", 0.5 / q2, r, qfcf); - - //Double_t xRot = x * cosSlope + y * sinSlope; - //printf("BV check %f %f \n", xRot, 2.0 * rxRot); + qfcf = (ryRot > 0.) ? -1 : +1; Double_t alpha = 2.0 * std::abs(TMath::ATan2(rxRot, ryRot)); Double_t x0 = xVal[0], y0 = yVal[0], z0 = zVal[0]; @@ -515,7 +426,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) pt = 1. / invpt; p = std::sqrt(dxyz2) / c_alpha; pz = std::sqrt(p * p - pt * pt); - // tanl = pz / pt; + invqpt_fcf = qfcf * invpt; } else { // the linear regression failed... printf("BV LinearRegression failed!\n"); @@ -525,7 +436,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) return invqpt_fcf; } -//__________________________________________________________________________ +////_________________________________________________________________________________________________ Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yErr, Double_t& a, Double_t& ae, Double_t& b, Double_t& be) { // linear regression y = a * x + b @@ -537,7 +448,6 @@ Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yE SsXX = SsYY = SsXY = Xm = Ym = 0.; difx = 0.; for (Int_t i = 0; i < nVal; i++) { - //printf("BV LinFit %d %f %f %f \n", i, xVal[i], yVal[i], yErr[i]); invYErr2 = 1. / (yErr[i] * yErr[i]); S1 += invYErr2; SXY += xVal[i] * yVal[i] * invYErr2; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index 644e21939554c..9d26dd958ba31 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -25,15 +25,22 @@ namespace o2 namespace mft { +//_________________________________________________________________________________________________ Tracker::Tracker(bool useMC) : mUseMC{useMC} { - /// Configure track propagation - LOG(INFO) << "initializing track fitter"; mTrackFitter = std::make_unique<o2::mft::TrackFitter>(); - mTrackFitter->setBz(mBz); } +//_________________________________________________________________________________________________ +void Tracker::setBz(Float_t bz) +{ + /// Configure track propagation + mBz = bz; + mTrackFitter->setBz(bz); +} + +//_________________________________________________________________________________________________ void Tracker::clustersToTracks(ROframe& event, std::ostream& timeBenchmarkOutputStream) { mTracks.clear(); @@ -42,6 +49,7 @@ void Tracker::clustersToTracks(ROframe& event, std::ostream& timeBenchmarkOutput fitTracks(event); } +//_________________________________________________________________________________________________ void Tracker::findTracks(ROframe& event) { //computeCells(event); @@ -49,6 +57,7 @@ void Tracker::findTracks(ROframe& event) findTracksCA(event); } +//_________________________________________________________________________________________________ void Tracker::computeCells(ROframe& event) { MCCompLabel mcCompLabel; @@ -91,6 +100,7 @@ void Tracker::computeCells(ROframe& event) } // end layers } +//_________________________________________________________________________________________________ void Tracker::findTracksLTF(ROframe& event) { // find (high momentum) tracks by the Linear Track Finder (LTF) method @@ -258,6 +268,7 @@ void Tracker::findTracksLTF(ROframe& event) } // end seeding } +//_________________________________________________________________________________________________ void Tracker::findTracksCA(ROframe& event) { // layers: 0, 1, 2, ..., 9 @@ -415,6 +426,7 @@ void Tracker::findTracksCA(ROframe& event) } // end layer1 } +//_________________________________________________________________________________________________ void Tracker::computeCellsInRoad(Road& road) { Int_t layer1, layer1min, layer1max, layer2, layer2min, layer2max; @@ -453,6 +465,7 @@ void Tracker::computeCellsInRoad(Road& road) } // end layer1 } +//_________________________________________________________________________________________________ void Tracker::runForwardInRoad(ROframe& event) { Int_t layerR, layerL, icellR, icellL; @@ -504,6 +517,7 @@ void Tracker::runForwardInRoad(ROframe& event) } // end while (step) } +//_________________________________________________________________________________________________ void Tracker::runBackwardInRoad(ROframe& event) { if (mMaxCellLevel == 1) @@ -656,6 +670,7 @@ void Tracker::runBackwardInRoad(ROframe& event) } // end loop start layer } +//_________________________________________________________________________________________________ void Tracker::updateCellStatusInRoad(Road& road) { for (Int_t layer = 0; layer < (constants::mft::LayersNumber - 1); ++layer) { @@ -666,6 +681,7 @@ void Tracker::updateCellStatusInRoad(Road& road) } } +//_________________________________________________________________________________________________ const Float_t Tracker::getCellChisquare(ROframe& event, const Cell& cell) const { // returns the new chisquare of the previous cells plus the new one @@ -705,6 +721,7 @@ const Float_t Tracker::getCellChisquare(ROframe& event, const Cell& cell) const return (chisqZX + chisqZY) / (Float_t)nDegFree; } +//_________________________________________________________________________________________________ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t cellId, ROframe& event) { TrackCA& trackCA = event.getCurrentTrackCA(); @@ -848,6 +865,7 @@ const Bool_t Tracker::LinearRegression(Int_t npoints, Float_t* x, Float_t* y, Fl return kTRUE; } +//_________________________________________________________________________________________________ bool Tracker::fitTracks(ROframe& event) { for (auto& track : event.getTracksLTF()) { @@ -860,7 +878,12 @@ bool Tracker::fitTracks(ROframe& event) } for (auto& track : event.getTracksCA()) { track.sort(); + TrackCA outParam = track; + mTrackFitter->initTrack(track); mTrackFitter->fit(track); + mTrackFitter->initTrack(outParam, true); + mTrackFitter->fit(outParam, true); + track.SetOutParam(outParam); } return true; From aaf2500262c8e694d6c750ea80f68745e54f0613 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Wed, 29 Jul 2020 21:39:35 +0000 Subject: [PATCH 0296/1751] Using MFT cluster uncertainties on tracking workflow --- .../tracking/include/MFTTracking/Cluster.h | 10 ++-- .../tracking/include/MFTTracking/ROframe.h | 60 ++++--------------- .../tracking/include/MFTTracking/TrackCA.h | 60 ++++++++++++------- .../tracking/include/MFTTracking/Tracker.h | 34 +++-------- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 8 +-- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 14 +++-- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 10 ++-- 7 files changed, 83 insertions(+), 113 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index 6cb7394159bd7..50478f827fd53 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -26,12 +26,14 @@ namespace mft { struct Cluster : public o2::BaseCluster<float> { - Cluster(const Float_t x, const Float_t y, const Float_t z, const Float_t phi, const Float_t r, const Int_t idx, const Int_t bin) - : BaseCluster(1, x, y, z), + Cluster(const Float_t x, const Float_t y, const Float_t z, const Float_t phi, const Float_t r, const Int_t idx, const Int_t bin, const Float_t sigX2, const Float_t sigY2, const Int_t sensorID) + : BaseCluster(sensorID, x, y, z), phiCoordinate{phi}, rCoordinate{r}, clusterId{idx}, - indexTableBin{bin} {}; + indexTableBin{bin}, + sigmaX2{sigX2}, + sigmaY2{sigY2} {}; Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t index); Cluster(const Int_t layerIndex, const Cluster& other); @@ -39,8 +41,8 @@ struct Cluster : public o2::BaseCluster<float> { Float_t rCoordinate; Int_t clusterId; Int_t indexTableBin; - Float_t sigmaY2; Float_t sigmaX2; + Float_t sigmaY2; }; } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h index 4b4711d45640a..e7d062eb0cfa5 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h @@ -43,19 +43,22 @@ class ROframe final { public: ROframe(Int_t ROframeId); - Int_t getROFrameId() const; + Int_t getROFrameId() const { return mROframeId; } Int_t getTotalClusters() const; void setROFrameId(const Int_t rofid) { mROframeId = rofid; } - const std::array<std::vector<Cluster>, constants::mft::LayersNumber>& getClusters() const; - const std::vector<Cluster>& getClustersInLayer(Int_t layerId) const; - const MCCompLabel& getClusterLabels(Int_t layerId, const Cluster& cl) const; - const MCCompLabel& getClusterLabels(Int_t layerId, const Int_t clId) const; - const std::map<Int_t, std::pair<Int_t, Int_t>>& getClusterBinIndexRange(Int_t layerId) const; - Int_t getClusterExternalIndex(Int_t layerId, const Int_t clId) const; + const std::array<std::vector<Cluster>, constants::mft::LayersNumber>& getClusters() const { return mClusters; } + const std::vector<Cluster>& getClustersInLayer(Int_t layerId) const { return mClusters[layerId]; } + + const MCCompLabel& getClusterLabels(Int_t layerId, const Cluster& cl) const { return mClusterLabels[layerId][cl.clusterId]; } + const MCCompLabel& getClusterLabels(Int_t layerId, const Int_t clId) const { return mClusterLabels[layerId][clId]; } + + const std::map<Int_t, std::pair<Int_t, Int_t>>& getClusterBinIndexRange(Int_t layerId) const { return mClusterBinIndexRange[layerId]; } + Int_t getClusterExternalIndex(Int_t layerId, const Int_t clId) const { return mClusterExternalIndices[layerId][clId]; } + const std::array<std::vector<Cell>, constants::mft::LayersNumber>& getCells() const; - const std::vector<Cell>& getCellsInLayer(Int_t layerId) const; + const std::vector<Cell>& getCellsInLayer(Int_t layerId) const { return mCells[layerId]; } std::vector<TrackLTF>& getTracksLTF(); TrackLTF& getCurrentTrackLTF(); void removeCurrentTrackLTF(); @@ -75,7 +78,8 @@ class ROframe final void addClusterLabelToLayer(Int_t layer, const MCCompLabel label); void addClusterExternalIndexToLayer(Int_t layer, const Int_t idx); void addClusterBinIndexRangeToLayer(Int_t layer, const std::pair<Int_t, std::pair<Int_t, Int_t>> range); - void addTrackLTF(); + void addTrackLTF() { mTracksLTF.emplace_back(); } + void addTrackCA(); void addRoad(); @@ -100,43 +104,6 @@ class ROframe final std::vector<Road> mRoads; }; -inline Int_t ROframe::getROFrameId() const { return mROframeId; } - -inline const std::array<std::vector<Cluster>, constants::mft::LayersNumber>& ROframe::getClusters() const -{ - return mClusters; -} - -inline const std::vector<Cluster>& ROframe::getClustersInLayer(Int_t layerId) const -{ - return mClusters[layerId]; -} - -inline const MCCompLabel& ROframe::getClusterLabels(Int_t layerId, const Cluster& cl) const -{ - return mClusterLabels[layerId][cl.clusterId]; -} - -inline const MCCompLabel& ROframe::getClusterLabels(Int_t layerId, const Int_t clId) const -{ - return mClusterLabels[layerId][clId]; -} - -inline Int_t ROframe::getClusterExternalIndex(Int_t layerId, const Int_t clId) const -{ - return mClusterExternalIndices[layerId][clId]; -} - -inline const std::map<Int_t, std::pair<Int_t, Int_t>>& ROframe::getClusterBinIndexRange(Int_t layerId) const -{ - return mClusterBinIndexRange[layerId]; -} - -inline const std::vector<Cell>& ROframe::getCellsInLayer(Int_t layerId) const -{ - return mCells[layerId]; -} - template <typename... T> void ROframe::addClusterToLayer(Int_t layer, T&&... values) { @@ -168,7 +135,6 @@ inline Bool_t ROframe::isClusterUsed(Int_t layer, Int_t clusterId) const inline void ROframe::markUsedCluster(Int_t layer, Int_t clusterId) { mUsedClusters[layer][clusterId] = kTRUE; } -inline void ROframe::addTrackLTF() { mTracksLTF.emplace_back(); } inline TrackLTF& ROframe::getCurrentTrackLTF() { diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index 558c7e06982b7..c079c8be618d8 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -19,6 +19,7 @@ #include "DataFormatsMFT/TrackMFT.h" #include "SimulationDataFormat/MCCompLabel.h" #include "MFTTracking/Constants.h" +#include "MFTTracking/Cluster.h" #include <fairlogger/Logger.h> namespace o2 @@ -36,10 +37,13 @@ class TrackLTF : public TrackMFTExt const std::array<Float_t, constants::mft::LayersNumber>& getXCoordinates() const { return mX; } const std::array<Float_t, constants::mft::LayersNumber>& getYCoordinates() const { return mY; } const std::array<Float_t, constants::mft::LayersNumber>& getZCoordinates() const { return mZ; } + const std::array<Float_t, constants::mft::LayersNumber>& getSigmasX2() const { return mSigmaX2; } + const std::array<Float_t, constants::mft::LayersNumber>& getSigmasY2() const { return mSigmaY2; } const std::array<Int_t, constants::mft::LayersNumber>& getLayers() const { return mLayer; } const std::array<Int_t, constants::mft::LayersNumber>& getClustersId() const { return mClusterId; } const std::array<MCCompLabel, constants::mft::LayersNumber>& getMCCompLabels() const { return mMCCompLabels; } - void setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); + void setPoint(const Cluster, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); + void sort(); protected: @@ -49,11 +53,14 @@ class TrackLTF : public TrackMFTExt std::array<Float_t, constants::mft::LayersNumber> mX = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; std::array<Float_t, constants::mft::LayersNumber> mY = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; std::array<Float_t, constants::mft::LayersNumber> mZ = {-120., -120., -120., -120., -120., -120., -120., -120., -120., -120.}; + std::array<Float_t, constants::mft::LayersNumber> mSigmaX2 = {0}; + std::array<Float_t, constants::mft::LayersNumber> mSigmaY2 = {0}; std::array<Int_t, constants::mft::LayersNumber> mLayer; std::array<Int_t, constants::mft::LayersNumber> mClusterId; std::array<MCCompLabel, constants::mft::LayersNumber> mMCCompLabels; }; +//_________________________________________________________________________________________________ class TrackCA : public TrackLTF { public: @@ -62,9 +69,9 @@ class TrackCA : public TrackLTF ~TrackCA() = default; void addCell(const Int_t, const Int_t); void removeLastCell(Int_t&, Int_t&); - const Int_t getNCells() const; + const Int_t getNCells() const { return mNCells; } void setRoadId(const Int_t rid) { mRoadId = rid; } - const Int_t getRoadId() const; + const Int_t getRoadId() const { return mRoadId; } void setChiSquareZX(const Float_t chisq) { mChiSquareZX = chisq; } void setChiSquareZY(const Float_t chisq) { mChiSquareZY = chisq; } const Float_t getChiSquareZX() const { return mChiSquareZX; } @@ -84,6 +91,7 @@ class TrackCA : public TrackLTF ClassDefNV(TrackCA, 2); }; +//_________________________________________________________________________________________________ inline void TrackCA::addCell(const Int_t layer, const Int_t cellId) { mCellLayer[mNCells] = layer; @@ -91,6 +99,7 @@ inline void TrackCA::addCell(const Int_t layer, const Int_t cellId) mNCells++; } +//_________________________________________________________________________________________________ inline void TrackCA::removeLastCell(Int_t& layer, Int_t& cellId) { layer = mCellLayer[mNCells - 1]; @@ -103,26 +112,19 @@ inline void TrackCA::removeLastCell(Int_t& layer, Int_t& cellId) mNCells--; } -inline const Int_t TrackCA::getNCells() const -{ - return mNCells; -} - -inline const Int_t TrackCA::getRoadId() const -{ - return mRoadId; -} - -inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint) +//_________________________________________________________________________________________________ +inline void TrackLTF::setPoint(const Cluster cl, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint) { if (newPoint) { if (mNPoints == constants::mft::LayersNumber) { LOG(WARN) << "MFT TrackLTF Overflow"; return; } - mX[mNPoints] = x; - mY[mNPoints] = y; - mZ[mNPoints] = z; + mX[mNPoints] = cl.getX(); + mY[mNPoints] = cl.getY(); + mZ[mNPoints] = cl.getZ(); + mSigmaX2[mNPoints] = cl.sigmaX2; + mSigmaY2[mNPoints] = cl.sigmaY2; mLayer[mNPoints] = layer; mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; @@ -130,9 +132,11 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z mNPoints++; } else { - mX[mNPoints] = x; - mY[mNPoints] = y; - mZ[mNPoints] = z; + mX[mNPoints] = cl.getX(); + mY[mNPoints] = cl.getY(); + mZ[mNPoints] = cl.getZ(); + mSigmaX2[mNPoints] = cl.sigmaX2; + mSigmaY2[mNPoints] = cl.sigmaY2; mLayer[mNPoints] = layer; mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; @@ -140,6 +144,7 @@ inline void TrackLTF::setPoint(const Float_t x, const Float_t y, const Float_t z } } +//_________________________________________________________________________________________________ inline void TrackLTF::sort() { // Orders elements along z position @@ -147,22 +152,28 @@ inline void TrackLTF::sort() Float_t x; Float_t y; Float_t z; + Float_t sigmaX2; + Float_t sigmaY2; Int_t layer; Int_t clusterId; - Int_t label; + MCCompLabel label; }; - std::vector<ClusterData> points; + + // Loading cluster data for (Int_t point = 0; point < getNPoints(); ++point) { auto& somepoint = points.emplace_back(); somepoint.x = mX[point]; somepoint.y = mY[point]; somepoint.z = mZ[point]; + somepoint.sigmaX2 = mSigmaX2[point]; + somepoint.sigmaY2 = mSigmaY2[point]; somepoint.layer = mLayer[point]; somepoint.clusterId = mClusterId[point]; somepoint.label = mMCCompLabels[point]; } + // Sorting cluster data std::sort(points.begin(), points.end(), [](ClusterData a, ClusterData b) { return a.z > b.z; }); // Storing sorted cluster data @@ -170,6 +181,8 @@ inline void TrackLTF::sort() mX[point] = points[point].x; mY[point] = points[point].y; mZ[point] = points[point].z; + mSigmaX2[point] = points[point].sigmaX2; + mSigmaY2[point] = points[point].sigmaY2; mLayer[point] = points[point].layer; mClusterId[point] = points[point].clusterId; mMCCompLabels[point] = points[point].label; @@ -177,6 +190,7 @@ inline void TrackLTF::sort() } } // namespace mft + namespace framework { template <typename T> @@ -184,11 +198,13 @@ struct is_messageable; template <> struct is_messageable<o2::mft::TrackCA> : std::true_type { }; + template <typename T> struct is_messageable; template <> struct is_messageable<o2::mft::TrackLTF> : std::true_type { }; + } // namespace framework } // namespace o2 #endif /* O2_MFT_TRACKCA_H_ */ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index e18529353bc4c..8897e6a4f0c89 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -46,9 +46,9 @@ class Tracker void setBz(Float_t bz); const Float_t getBz() const { return mBz; } - std::vector<TrackMFT>& getTracks(); - std::vector<TrackLTF>& getTracksLTF(); - o2::dataformats::MCTruthContainer<MCCompLabel>& getTrackLabels(); + std::vector<TrackMFT>& getTracks() { return mTracks; } + std::vector<TrackLTF>& getTracksLTF() { return mTracksLTF; } + o2::dataformats::MCTruthContainer<MCCompLabel>& getTrackLabels() { return mTrackLabels; } void clustersToTracks(ROframe&, std::ostream& = std::cout); @@ -68,8 +68,7 @@ class Tracker bool fitTracks(ROframe&); std::unique_ptr<o2::mft::TrackFitter> mTrackFitter = nullptr; - const Int_t isDiskFace(Int_t layer) const; - + const Int_t isDiskFace(Int_t layer) const { return (layer % 2); } const Float_t getDistanceToSeed(const Cluster&, const Cluster&, const Cluster&) const; void getRPhiProjectionBin(const Cluster&, const Int_t, const Int_t, Int_t&, Int_t&) const; Bool_t getBinClusterRange(const ROframe&, const Int_t, const Int_t, Int_t&, Int_t&) const; @@ -92,21 +91,7 @@ class Tracker bool mUseMC = false; }; -inline std::vector<TrackMFT>& Tracker::getTracks() -{ - return mTracks; -} - -inline std::vector<TrackLTF>& Tracker::getTracksLTF() -{ - return mTracksLTF; -} - -inline o2::dataformats::MCTruthContainer<MCCompLabel>& Tracker::getTrackLabels() -{ - return mTrackLabels; -} - +//_________________________________________________________________________________________________ inline const Float_t Tracker::getDistanceToSeed(const Cluster& cluster1, const Cluster& cluster2, const Cluster& cluster) const { // the seed is between "cluster1" and "cluster2" and cuts the plane @@ -122,6 +107,7 @@ inline const Float_t Tracker::getDistanceToSeed(const Cluster& cluster1, const C return dR; } +//_________________________________________________________________________________________________ inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t layer1, const Int_t layer, Int_t& binR_proj, Int_t& binPhi_proj) const { Float_t dz, x_proj, y_proj, r_proj, phi_proj; @@ -137,6 +123,7 @@ inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t l return; } +//_________________________________________________________________________________________________ inline Bool_t Tracker::getBinClusterRange(const ROframe& event, const Int_t layer, const Int_t bin, Int_t& clsMinIndex, Int_t& clsMaxIndex) const { const auto pair2 = event.getClusterBinIndexRange(layer).find(bin); @@ -150,11 +137,7 @@ inline Bool_t Tracker::getBinClusterRange(const ROframe& event, const Int_t laye return kTRUE; } -inline const Int_t Tracker::isDiskFace(Int_t layer) const -{ - return (layer % 2); -} - +//_________________________________________________________________________________________________ inline const Float_t Tracker::getCellDeviation(const ROframe& event, const Cell& cell1, const Cell& cell2) const { Int_t cell1layer1 = cell1.getFirstLayerId(); @@ -206,6 +189,7 @@ inline const Float_t Tracker::getCellDeviation(const ROframe& event, const Cell& return std::acos(cosAngle); } +//_________________________________________________________________________________________________ inline const Bool_t Tracker::getCellsConnect(const ROframe& event, const Cell& cell1, const Cell& cell2) const { Int_t cell1layer1 = cell1.getFirstLayerId(); diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index cc3c2f932ddc7..e65c6e198579d 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -47,10 +47,10 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g int layer = geom->getLayer(c.getSensorID()); auto pattID = c.getPatternID(); Point3D<float> locXYZ; - float sigmaY2 = ioutils::DefClusError2Row, sigmaZ2 = ioutils::DefClusError2Col, sigmaYZ = 0; //Dummy COG errors (about half pixel size) + float sigmaX2 = ioutils::DefClusError2Row, sigmaY2 = ioutils::DefClusError2Col; //Dummy COG errors (about half pixel size) if (pattID != itsmft::CompCluster::InvalidPatternID) { - sigmaY2 = dict.getErr2X(pattID); - sigmaZ2 = dict.getErr2Z(pattID); + sigmaX2 = dict.getErr2X(pattID); // ALPIDE local X coordinate => MFT global X coordinate (ALPIDE rows) + sigmaY2 = dict.getErr2Z(pattID); // ALPIDE local Z coordinate => MFT global Y coordinate (ALPIDE columns) if (!dict.isGroup(pattID)) { locXYZ = dict.getClusterCoordinates(c); } else { @@ -73,7 +73,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g int phiBinIndex = constants::index_table::getPhiBinIndex(phiCoord); int binIndex = constants::index_table::getBinIndex(rBinIndex, phiBinIndex); - event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), phiCoord, rCoord, event.getClustersInLayer(layer).size(), binIndex); + event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), phiCoord, rCoord, event.getClustersInLayer(layer).size(), binIndex, sigmaX2, sigmaY2, sensorID); if (mcLabels) { event.addClusterLabelToLayer(layer, *(mcLabels->getLabels(first + clusterId).begin())); } diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index f08ef991e0197..b0adaed5167a8 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -143,8 +143,8 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) double r0cu = r0sq * TMath::Sqrt(r0sq); double invr0sq = 1.0 / r0sq; double invr0cu = 1.0 / r0cu; - double sigmax0sq = 5e-4; - double sigmay0sq = 5.43e-4; + double sigmax0sq = track.getSigmasX2()[where]; + double sigmay0sq = track.getSigmasY2()[where]; double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond double sigmaboost = mftTrackingParam.sigmaboost; // Boost q/pt seed covariances double seedH_k = mftTrackingParam.seedH_k; // SeedH constant @@ -319,8 +319,8 @@ bool TrackFitter::runKalmanFilter(TrackLTF& track, int cluster) // compute the new cluster weight (U) SMatrix55 clusterWeight; - clusterWeight(0, 0) = 1. / 5e-4; // FIXME - clusterWeight(1, 1) = 1. / 5.43e-4; + clusterWeight(0, 0) = 1. / track.getSigmasX2()[cluster]; + clusterWeight(1, 1) = 1. / track.getSigmasY2()[cluster]; // compute the new parameters covariance matrix ((W+U)^-1) SMatrix55 newParamCov(paramWeight + clusterWeight); @@ -353,6 +353,8 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) const std::array<Float_t, constants::mft::LayersNumber>& xPositons = track.getXCoordinates(); const std::array<Float_t, constants::mft::LayersNumber>& yPositons = track.getYCoordinates(); const std::array<Float_t, constants::mft::LayersNumber>& zPositons = track.getZCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& SigmasX2 = track.getSigmasX2(); + const std::array<Float_t, constants::mft::LayersNumber>& SigmasY2 = track.getSigmasY2(); // Fast Circle Fit (Hansroul, Jeremie, Savard, 1987) auto nPoints = track.getNPoints(); @@ -367,8 +369,8 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) Double_t a, ae, b, be, x2, y2, invx2y2, rx, ry, r; for (auto np = 0; np < nPoints; np++) { - xErr[np] = 5e-4; // FIXME -> errors from clusters - yErr[np] = 5e-4; // FIXME + xErr[np] = SigmasX2[np]; + yErr[np] = SigmasY2[np]; if (np > 0) { xVal[np] = xPositons[np] - xVal[0]; yVal[np] = yPositons[np] - yVal[0]; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index 9d26dd958ba31..cb0e033505591 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -186,7 +186,7 @@ void Tracker::findTracksLTF(ROframe& event) // add the first seed-point mcCompLabel = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentTrackLTF().setPoint(cluster1.getX(), cluster1.getY(), cluster1.getZ(), layer1, clsLayer1, mcCompLabel, newPoint); + event.getCurrentTrackLTF().setPoint(cluster1, layer1, clsLayer1, mcCompLabel, newPoint); for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { @@ -226,7 +226,7 @@ void Tracker::findTracksLTF(ROframe& event) hasDisk[layer / 2] = kTRUE; mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); - event.getCurrentTrackLTF().setPoint(cluster.getX(), cluster.getY(), cluster.getZ(), layer, clsLayer, mcCompLabel, newPoint); + event.getCurrentTrackLTF().setPoint(cluster, layer, clsLayer, mcCompLabel, newPoint); } // end clusters bin intermediate layer } // end intermediate layers } // end binPhi @@ -235,7 +235,7 @@ void Tracker::findTracksLTF(ROframe& event) // add the second seed-point mcCompLabel = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentTrackLTF().setPoint(cluster2.getX(), cluster2.getY(), cluster2.getZ(), layer2, clsLayer2, mcCompLabel, newPoint); + event.getCurrentTrackLTF().setPoint(cluster2, layer2, clsLayer2, mcCompLabel, newPoint); // keep only tracks fulfilling the minimum length condition if (event.getCurrentTrackLTF().getNPoints() < constants::mft::MinTrackPoints) { @@ -752,11 +752,11 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce if (trackCA.getNPoints() == 0) { newPoint = kTRUE; - trackCA.setPoint(cluster2.getX(), cluster2.getY(), cluster2.getZ(), layer2, cls2Id, mcCompLabel2, newPoint); + trackCA.setPoint(cluster2, layer2, cls2Id, mcCompLabel2, newPoint); } newPoint = kTRUE; - trackCA.setPoint(cluster1.getX(), cluster1.getY(), cluster1.getZ(), layer1, cls1Id, mcCompLabel1, newPoint); + trackCA.setPoint(cluster1, layer1, cls1Id, mcCompLabel1, newPoint); trackCA.addCell(layer1, cellId); From 5241a5404a8d68dc27055c3f6f601d8dacd6c57a Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Thu, 6 Aug 2020 23:43:13 +0000 Subject: [PATCH 0297/1751] Fix MFT Tracks cluster indices --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 3 +-- .../MFT/tracking/include/MFTTracking/TrackCA.h | 10 +++++++--- .../MFT/tracking/include/MFTTracking/Tracker.h | 6 +++--- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 17 +++++++++-------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index d9417556f6978..2e633523ca5c1 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -125,8 +125,7 @@ class TrackMFTExt : public TrackMFT void setClusterIndex(int l, int i, int ncl) { - //int ncl = getNumberOfClusters(); - mIndex[ncl] = (l << 28) + i; + mIndex[ncl] = (l << 27) + i; getClusterRefs().setEntries(ncl); } diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index c079c8be618d8..4412127322c27 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -116,7 +116,12 @@ inline void TrackCA::removeLastCell(Int_t& layer, Int_t& cellId) inline void TrackLTF::setPoint(const Cluster cl, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint) { if (newPoint) { - if (mNPoints == constants::mft::LayersNumber) { + if (mNPoints > 0) + if (mZ[mNPoints - 1] == cl.getZ()) { + LOG(WARN) << "MFT TrackLTF: skipping setPoint (1 cluster per layer!)"; + return; + } + if (mNPoints >= constants::mft::LayersNumber - 1) { LOG(WARN) << "MFT TrackLTF Overflow"; return; } @@ -128,9 +133,8 @@ inline void TrackLTF::setPoint(const Cluster cl, const Int_t layer, const Int_t mLayer[mNPoints] = layer; mClusterId[mNPoints] = clusterId; mMCCompLabels[mNPoints] = label; - setClusterIndex(layer, clusterId, mNPoints); - mNPoints++; + setClusterIndex(layer, clusterId, mNPoints); } else { mX[mNPoints] = cl.getX(); mY[mNPoints] = cl.getY(); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 8897e6a4f0c89..e893ff0e04db6 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -46,7 +46,7 @@ class Tracker void setBz(Float_t bz); const Float_t getBz() const { return mBz; } - std::vector<TrackMFT>& getTracks() { return mTracks; } + std::vector<TrackMFTExt>& getTracks() { return mTracks; } std::vector<TrackLTF>& getTracksLTF() { return mTracksLTF; } o2::dataformats::MCTruthContainer<MCCompLabel>& getTrackLabels() { return mTrackLabels; } @@ -66,7 +66,6 @@ class Tracker void updateCellStatusInRoad(Road&); bool fitTracks(ROframe&); - std::unique_ptr<o2::mft::TrackFitter> mTrackFitter = nullptr; const Int_t isDiskFace(Int_t layer) const { return (layer % 2); } const Float_t getDistanceToSeed(const Cluster&, const Cluster&, const Cluster&) const; @@ -81,10 +80,11 @@ class Tracker Float_t mBz = 5.f; std::uint32_t mROFrame = 0; - std::vector<TrackMFT> mTracks; + std::vector<TrackMFTExt> mTracks; std::vector<TrackLTF> mTracksLTF; std::vector<Cluster> mClusters; o2::dataformats::MCTruthContainer<MCCompLabel> mTrackLabels; + std::unique_ptr<o2::mft::TrackFitter> mTrackFitter = nullptr; Int_t mMaxCellLevel = 0; diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 1a48945f08327..52c5e15ef807f 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -113,12 +113,15 @@ void TrackerDPL::run(ProcessingContext& pc) LOG(INFO) << "MFTTracker RO: continuous=" << continuous; // snippet to convert found tracks to final output tracks with separate cluster indices - auto copyTracks = [](auto& tracks, auto& allTracks, auto& allClusIdx, int offset = 0) { + auto copyTracks = [&event](auto& tracks, auto& allTracks, auto& allClusIdx, int offset = 0) { for (auto& trc : tracks) { trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices int ncl = trc.getNumberOfClusters(); for (int ic = 0; ic < ncl; ic++) { - allClusIdx.push_back(trc.getClusterIndex(ic) + offset); + auto layer_clID = trc.getClustersId()[ic]; + auto layer = trc.getLayers()[ic]; + auto externalClusterID = event.getClusterExternalIndex(layer, trc.getClustersId()[ic]); + allClusIdx.push_back(externalClusterID); } allTracks.emplace_back(trc); } @@ -141,14 +144,12 @@ void TrackerDPL::run(ProcessingContext& pc) trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. int first = allTracksMFT.size(); int number = tracksLTF.size() + tracksCA.size(); - int shiftIdx = -rof.getFirstEntry(); rof.setFirstEntry(first); - rofs[roFrame].setFirstEntry(first); rof.setNEntries(number); - copyTracks(tracksLTF, allTracksMFT, allClusIdx, shiftIdx); - copyTracks(tracksCA, allTracksMFT, allClusIdx, shiftIdx); - std::copy(tracksLTF.begin(), tracksLTF.end(), std::back_inserter(allTracksLTF)); - std::copy(tracksCA.begin(), tracksCA.end(), std::back_inserter(allTracksCA)); + copyTracks(tracksLTF, allTracksMFT, allClusIdx); + copyTracks(tracksCA, allTracksMFT, allClusIdx); + std::copy(tracksLTF.begin(), tracksLTF.end(), std::back_inserter(allTracksLTF)); // TODO: Get rid of allTracksLTF + std::copy(tracksCA.begin(), tracksCA.end(), std::back_inserter(allTracksCA)); // TODO: Get rid of allTracksCA allTrackLabels.mergeAtBack(trackLabels); } roFrame++; From 8c65bdc8351f7c8ea80a7fab6ffa567579e81804 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Fri, 7 Aug 2020 01:11:44 +0000 Subject: [PATCH 0298/1751] MFT Tracker Computing MCLabels --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 9 ---- .../Detectors/ITSMFT/MFT/src/TrackMFT.cxx | 6 --- .../tracking/include/MFTTracking/Tracker.h | 43 +++++++++++++++++++ .../MFT/workflow/src/TrackWriterSpec.cxx | 4 +- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 10 +++-- 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index 2e633523ca5c1..0f56eb94c391c 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -74,13 +74,6 @@ class TrackMFT : public o2::track::TrackParCovFwd mClusRef.set(firstEntry, n); } - const std::array<MCCompLabel, 10>& getMCCompLabels() const { return mMCCompLabels; } // constants::mft::LayersNumber = 10 - void setMCCompLabels(const std::array<MCCompLabel, 10>& labels, int nPoints) - { - mMCCompLabels = labels; - mNPoints = nPoints; - } - const ClusRefs& getClusterRefs() const { return mClusRef; } ClusRefs& getClusterRefs() { return mClusRef; } @@ -90,7 +83,6 @@ class TrackMFT : public o2::track::TrackParCovFwd const Int_t getNPoints() const { return mNPoints; } void print() const; - void printMCCompLabels() const; const o2::track::TrackParCovFwd& GetOutParam() const { return mOutParameters; } void SetOutParam(const o2::track::TrackParCovFwd parcov) { mOutParameters = parcov; } @@ -98,7 +90,6 @@ class TrackMFT : public o2::track::TrackParCovFwd private: std::uint32_t mROFrame = 0; ///< RO Frame Int_t mNPoints{0}; // Number of clusters - std::array<MCCompLabel, 10> mMCCompLabels; // constants::mft::LayersNumber = 10 Bool_t mIsCA = false; // Track finding method CA vs. LTF ClusRefs mClusRef; ///< references on clusters diff --git a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx index b8315153d8e0b..814329b02e3f3 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx +++ b/DataFormats/Detectors/ITSMFT/MFT/src/TrackMFT.cxx @@ -39,12 +39,6 @@ void TrackMFT::print() const << " chi2 = " << std::setw(5) << std::setprecision(3) << getTrackChi2() << std::endl; } -//__________________________________________________________________________ -void TrackMFT::printMCCompLabels() const -{ - /// Printing TrackMFT MCLabel information - LOG(INFO) << "TrackMFT with " << mNPoints << " clusters. MCLabels: " << mMCCompLabels[0] << mMCCompLabels[1] << "..."; //<< mMCCompLabels[2] << mMCCompLabels[3] << mMCCompLabels[4] << mMCCompLabels[5] << mMCCompLabels[6] << mMCCompLabels[7] << mMCCompLabels[8] << mMCCompLabels[9]; -} } // namespace mft } // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index e893ff0e04db6..ab9c04bad1361 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -52,6 +52,9 @@ class Tracker void clustersToTracks(ROframe&, std::ostream& = std::cout); + template <class T> + void computeTracksMClabels(const T&); + void setROFrame(std::uint32_t f) { mROFrame = f; } std::uint32_t getROFrame() const { return mROFrame; } @@ -243,6 +246,46 @@ inline const Bool_t Tracker::getCellsConnect(const ROframe& event, const Cell& c return kTRUE; } +//_________________________________________________________________________________________________ +template <class T> +inline void Tracker::computeTracksMClabels(const T& tracks) +{ + /// Moore's Voting Algorithm + for (auto& track : tracks) { + MCCompLabel maxOccurrencesValue{-1, -1, -1, false}; + int count{0}; + bool isFakeTrack{false}; + auto nClusters = track.getNumberOfClusters(); + for (int iCluster = 0; iCluster < nClusters; ++iCluster) { + const MCCompLabel& currentLabel = track.getMCCompLabels()[iCluster]; + if (currentLabel == maxOccurrencesValue) { + ++count; + } else { + if (count != 0) { // only in the first iteration count can be 0 at this point + --count; + } + if (count == 0) { + maxOccurrencesValue = currentLabel; + count = 1; + } + } + } + count = 0; + for (int iCluster = 0; iCluster < nClusters; ++iCluster) { + if (track.getMCCompLabels()[iCluster] == maxOccurrencesValue) + count++; + } + + auto labelratio = 1.0 * count / nClusters; + if (labelratio >= 0.8) { + } else { + isFakeTrack = true; + maxOccurrencesValue.setFakeFlag(); + } + mTrackLabels.addElement(mTrackLabels.getIndexedSize(), maxOccurrencesValue); + } +} + } // namespace mft } // namespace o2 diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx index acc5991001ab6..991bb70fe9949 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx @@ -37,7 +37,7 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) // Spectators for logging // this is only to restore the original behavior auto tracksSize = std::make_shared<int>(0); - auto tracksSizeGetter = [tracksSize](std::vector<o2::mft::TrackLTF> const& tracks) { + auto tracksSizeGetter = [tracksSize](std::vector<o2::mft::TrackMFT> const& tracks) { *tracksSize = tracks.size(); }; auto logger = [tracksSize](std::vector<o2::itsmft::ROFRecord> const& rofs) { @@ -46,7 +46,7 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) return MakeRootTreeWriterSpec("mft-track-writer", "mfttracks.root", MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree with MFT tracks"}, - BranchDefinition<std::vector<o2::mft::TrackLTF>>{InputSpec{"tracks", "MFT", "TRACKS", 0}, + BranchDefinition<std::vector<o2::mft::TrackMFT>>{InputSpec{"tracks", "MFT", "TRACKS", 0}, "MFTTrack", tracksSizeGetter}, BranchDefinition<std::vector<o2::mft::TrackLTF>>{InputSpec{"tracksltf", "MFT", "TRACKSLTF", 0}, diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 52c5e15ef807f..160f3e923fff1 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -104,7 +104,7 @@ void TrackerDPL::run(ProcessingContext& pc) auto& allTracksLTF = pc.outputs().make<std::vector<o2::mft::TrackLTF>>(Output{"MFT", "TRACKSLTF", 0, Lifetime::Timeframe}); std::vector<o2::mft::TrackCA> tracksCA; auto& allTracksCA = pc.outputs().make<std::vector<o2::mft::TrackCA>>(Output{"MFT", "TRACKSCA", 0, Lifetime::Timeframe}); - auto& allTracksMFT = pc.outputs().make<std::vector<o2::mft::TrackLTF>>(Output{"MFT", "TRACKS", 0, Lifetime::Timeframe}); + auto& allTracksMFT = pc.outputs().make<std::vector<o2::mft::TrackMFT>>(Output{"MFT", "TRACKS", 0, Lifetime::Timeframe}); std::uint32_t roFrame = 0; o2::mft::ROframe event(0); @@ -139,18 +139,22 @@ void TrackerDPL::run(ProcessingContext& pc) mTracker->clustersToTracks(event); tracksLTF.swap(event.getTracksLTF()); tracksCA.swap(event.getTracksCA()); + mTracker->computeTracksMClabels(tracksLTF); + mTracker->computeTracksMClabels(tracksCA); + trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. + allTrackLabels.mergeAtBack(trackLabels); + LOG(INFO) << "Found tracks LTF: " << tracksLTF.size(); LOG(INFO) << "Found tracks CA: " << tracksCA.size(); - trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. int first = allTracksMFT.size(); int number = tracksLTF.size() + tracksCA.size(); rof.setFirstEntry(first); rof.setNEntries(number); copyTracks(tracksLTF, allTracksMFT, allClusIdx); copyTracks(tracksCA, allTracksMFT, allClusIdx); + std::copy(tracksLTF.begin(), tracksLTF.end(), std::back_inserter(allTracksLTF)); // TODO: Get rid of allTracksLTF std::copy(tracksCA.begin(), tracksCA.end(), std::back_inserter(allTracksCA)); // TODO: Get rid of allTracksCA - allTrackLabels.mergeAtBack(trackLabels); } roFrame++; } From 332bdb84fc2214748a238e1959a358640dbd19bd Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Sat, 8 Aug 2020 15:37:55 +0000 Subject: [PATCH 0299/1751] Remove internal MFT tracker classes from reco output --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 8 +++++ Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 3 +- .../ITSMFT/MFT/workflow/src/ClustererSpec.cxx | 4 +-- .../MFT/workflow/src/TrackWriterSpec.cxx | 4 --- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 29 ++++++++++--------- 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index 0f56eb94c391c..cdf7a2160ad05 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -135,6 +135,14 @@ class TrackMFTExt : public TrackMFT ClassDefNV(TrackMFTExt, 1); }; } // namespace mft +namespace framework +{ +template <typename T> +struct is_messageable; +template <> +struct is_messageable<o2::mft::TrackMFT> : std::true_type { +}; +} // namespace framework } // namespace o2 #endif diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index e65c6e198579d..a87a1a756b43c 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -72,7 +72,8 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g int rBinIndex = constants::index_table::getRBinIndex(rCoord); int phiBinIndex = constants::index_table::getPhiBinIndex(phiCoord); int binIndex = constants::index_table::getBinIndex(rBinIndex, phiBinIndex); - + // TODO: Check consistency of sigmaX2 and sigmaY2 + // std::cout << "ClusterID = " << clusterId << " ; pattID = " << pattID << " ; sigmaX2 = " << sigmaX2 << " ; sigmaY2 = " << sigmaY2 << std::endl; event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), phiCoord, rCoord, event.getClustersInLayer(layer).size(), binIndex, sigmaX2, sigmaY2, sensorID); if (mcLabels) { event.addClusterLabelToLayer(layer, *(mcLabels->getLabels(first + clusterId).begin())); diff --git a/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx index bd428ff4ec17f..26e90db4cd58e 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx @@ -72,9 +72,9 @@ void ClustererDPL::init(InitContext& ic) std::string dictFile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::MFT, dictPath, ".bin"); if (o2::base::NameConf::pathExists(dictFile)) { mClusterer->loadDictionary(dictFile); - LOG(INFO) << "ITSClusterer running with a provided dictionary: " << dictFile; + LOG(INFO) << "MFTClusterer running with a provided dictionary: " << dictFile; } else { - LOG(INFO) << "Dictionary " << dictFile << " is absent, ITSClusterer expects cluster patterns"; + LOG(INFO) << "Dictionary " << dictFile << " is absent, MFTClusterer expects cluster patterns"; } mState = 1; mClusterer->print(); diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx index 991bb70fe9949..25ee745f2bb9d 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx @@ -49,10 +49,6 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) BranchDefinition<std::vector<o2::mft::TrackMFT>>{InputSpec{"tracks", "MFT", "TRACKS", 0}, "MFTTrack", tracksSizeGetter}, - BranchDefinition<std::vector<o2::mft::TrackLTF>>{InputSpec{"tracksltf", "MFT", "TRACKSLTF", 0}, - "MFTTrackLTF"}, - BranchDefinition<std::vector<o2::mft::TrackCA>>{InputSpec{"tracksca", "MFT", "TRACKSCA", 0}, - "MFTTrackCA"}, BranchDefinition<std::vector<int>>{InputSpec{"trackClIdx", "MFT", "TRACKCLSID", 0}, "MFTTrackClusIdx"}, BranchDefinition<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>{InputSpec{"labels", "MFT", "TRACKSMCTR", 0}, diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 160f3e923fff1..1af1434713712 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -63,7 +63,7 @@ void TrackerDPL::init(InitContext& ic) } std::string dictPath = ic.options().get<std::string>("its-dictionary-path"); - std::string dictFile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, dictPath, ".bin"); + std::string dictFile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::MFT, dictPath, ".bin"); if (o2::base::NameConf::pathExists(dictFile)) { mDict.readBinaryFile(dictFile); LOG(INFO) << "Tracker running with a provided dictionary: " << dictFile; @@ -76,6 +76,8 @@ void TrackerDPL::run(ProcessingContext& pc) { gsl::span<const unsigned char> patterns = pc.inputs().get<gsl::span<unsigned char>>("patterns"); auto compClusters = pc.inputs().get<const std::vector<o2::itsmft::CompClusterExt>>("compClusters"); + auto nTracksLTF = 0; + auto nTracksCA = 0; // code further down does assignment to the rofs and the altered object is used for output // we therefore need a copy of the vector rather than an object created directly on the input data, @@ -101,9 +103,7 @@ void TrackerDPL::run(ProcessingContext& pc) o2::dataformats::MCTruthContainer<o2::MCCompLabel> trackLabels; o2::dataformats::MCTruthContainer<o2::MCCompLabel> allTrackLabels; std::vector<o2::mft::TrackLTF> tracksLTF; - auto& allTracksLTF = pc.outputs().make<std::vector<o2::mft::TrackLTF>>(Output{"MFT", "TRACKSLTF", 0, Lifetime::Timeframe}); std::vector<o2::mft::TrackCA> tracksCA; - auto& allTracksCA = pc.outputs().make<std::vector<o2::mft::TrackCA>>(Output{"MFT", "TRACKSCA", 0, Lifetime::Timeframe}); auto& allTracksMFT = pc.outputs().make<std::vector<o2::mft::TrackMFT>>(Output{"MFT", "TRACKS", 0, Lifetime::Timeframe}); std::uint32_t roFrame = 0; @@ -139,10 +139,15 @@ void TrackerDPL::run(ProcessingContext& pc) mTracker->clustersToTracks(event); tracksLTF.swap(event.getTracksLTF()); tracksCA.swap(event.getTracksCA()); - mTracker->computeTracksMClabels(tracksLTF); - mTracker->computeTracksMClabels(tracksCA); - trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. - allTrackLabels.mergeAtBack(trackLabels); + nTracksLTF += tracksLTF.size(); + nTracksCA += tracksCA.size(); + + if (mUseMC) { + mTracker->computeTracksMClabels(tracksLTF); + mTracker->computeTracksMClabels(tracksCA); + trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. + allTrackLabels.mergeAtBack(trackLabels); + } LOG(INFO) << "Found tracks LTF: " << tracksLTF.size(); LOG(INFO) << "Found tracks CA: " << tracksCA.size(); @@ -152,17 +157,15 @@ void TrackerDPL::run(ProcessingContext& pc) rof.setNEntries(number); copyTracks(tracksLTF, allTracksMFT, allClusIdx); copyTracks(tracksCA, allTracksMFT, allClusIdx); - - std::copy(tracksLTF.begin(), tracksLTF.end(), std::back_inserter(allTracksLTF)); // TODO: Get rid of allTracksLTF - std::copy(tracksCA.begin(), tracksCA.end(), std::back_inserter(allTracksCA)); // TODO: Get rid of allTracksCA } roFrame++; } } + LOG(INFO) << "MFTTracker found " << nTracksLTF << " tracks LTF"; + LOG(INFO) << "MFTTracker found " << nTracksCA << " tracks CA"; LOG(INFO) << "MFTTracker pushed " << allTracksMFT.size() << " tracks"; - LOG(INFO) << "MFTTracker pushed " << allTracksLTF.size() << " tracks LTF"; - LOG(INFO) << "MFTTracker pushed " << allTracksCA.size() << " tracks CA"; + if (mUseMC) { pc.outputs().snapshot(Output{"MFT", "TRACKSMCTR", 0, Lifetime::Timeframe}, allTrackLabels); pc.outputs().snapshot(Output{"MFT", "TRACKSMC2ROF", 0, Lifetime::Timeframe}, mc2rofs); @@ -178,8 +181,6 @@ DataProcessorSpec getTrackerSpec(bool useMC) std::vector<OutputSpec> outputs; outputs.emplace_back("MFT", "TRACKS", 0, Lifetime::Timeframe); - outputs.emplace_back("MFT", "TRACKSLTF", 0, Lifetime::Timeframe); - outputs.emplace_back("MFT", "TRACKSCA", 0, Lifetime::Timeframe); outputs.emplace_back("MFT", "TRACKSROF", 0, Lifetime::Timeframe); outputs.emplace_back("MFT", "TRACKCLSID", 0, Lifetime::Timeframe); From b310c315235b94db80c41ac794fdbb69f1643eb0 Mon Sep 17 00:00:00 2001 From: Philip Hauer <philip.hauer@cern.ch> Date: Mon, 10 Aug 2020 07:53:49 +0200 Subject: [PATCH 0300/1751] Revised Krypton Box Cluster Finder (#4086) * Cluster Finder now takes into account that each row starts with 0. * Fixed a minor issue so that meanPad is calculated correctly. * Adjusted tree and file name in macro to match earlier versions. --- .../TPCReconstruction/KrBoxClusterFinder.h | 4 ++ .../reconstruction/macro/findKrBoxCluster.C | 71 ++++++++++--------- .../reconstruction/src/KrBoxClusterFinder.cxx | 13 +++- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h index a75765bce08de..6f8e18b135ecd 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h @@ -70,6 +70,7 @@ #include "DataFormatsTPC/Digit.h" #include "TPCReconstruction/KrCluster.h" +#include "TPCBase/Mapper.h" #include <tuple> #include <vector> @@ -123,6 +124,9 @@ class KrBoxClusterFinder static constexpr size_t MaxRows = 152; ///< Size of the map in row-direction static constexpr size_t MaxTimes = 550; ///< Size of the map in time-direction + /// Need an instance of Mapper to know position of pads + const Mapper& mMapperInstance = o2::tpc::Mapper::instance(); + KrCluster mTempCluster; ///< Used to save the cluster data /// Here the map is defined where all digits are temporarily stored diff --git a/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C b/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C index ec539c48bf7ca..23bac1ed5c25f 100644 --- a/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C +++ b/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C @@ -12,6 +12,7 @@ /// \brief This macro retrieves clusters from Krypton and X-Ray runs, input tpcdigits.root /// \author Philip Hauer <philip.hauer@cern.ch> +#if !defined(__CLING__) || defined(__ROOTCLING__) #include "TCanvas.h" #include "TFile.h" #include "TTree.h" @@ -24,8 +25,9 @@ #include <iostream> #include <tuple> #include <vector> +#endif -void findKrBoxCluster() +void findKrBoxCluster(int lastTimeBin = 1000, int run = -1, int time = -1) { // Read the digits: TFile* file = new TFile("tpcdigits.root"); @@ -34,17 +36,19 @@ void findKrBoxCluster() std::cout << "The Tree has " << nEntries << " Entries." << std::endl; // Initialize File for later writing - TFile* f = new TFile("boxClustersSectors.root", "RECREATE", "Clusters"); - TTree* T = new TTree("T", "Clusters"); + TFile* fOut = new TFile("BoxClusters.root", "RECREATE"); + TTree* tClusters = new TTree("Clusters", "Clusters"); - // Tree will be filled with a vector of clusters - std::vector<o2::tpc::KrCluster> vCluster{}; - T->Branch("cluster", &vCluster); + // Create a Branch for each sector: + std::vector<o2::tpc::KrCluster> clusters; + tClusters->Branch("cls", &clusters); + tClusters->Branch("run", &run); + tClusters->Branch("time", &time); - std::array<std::vector<o2::tpc::Digit>*, 36> DigitizedSignal; - for (int iSec = 0; iSec < DigitizedSignal.size(); ++iSec) { - DigitizedSignal[iSec] = nullptr; - tree->SetBranchAddress(Form("TPCDigit_%d", iSec), &DigitizedSignal[iSec]); + std::array<std::vector<o2::tpc::Digit>*, 36> digitizedSignal; + for (size_t iSec = 0; iSec < digitizedSignal.size(); ++iSec) { + digitizedSignal[iSec] = nullptr; + tree->SetBranchAddress(Form("TPCDigit_%zu", iSec), &digitizedSignal[iSec]); } // Now everything can get processed @@ -54,34 +58,35 @@ void findKrBoxCluster() tree->GetEntry(iEvent); // Each event consists of sectors (atm only two) for (int i = 0; i < 36; i++) { - auto sector = DigitizedSignal[i]; - if (sector->size() != 0) { - // Create ClusterFinder Object on Heap since creation on stack fails - // Probably due to too much memory consumption - o2::tpc::KrBoxClusterFinder* cluster = new o2::tpc::KrBoxClusterFinder(*sector); - std::vector<std::tuple<int, int, int>> localMaxima = cluster->findLocalMaxima(); - // Loop over cluster centers - for (const std::tuple<int, int, int>& coords : localMaxima) { - int padMax = std::get<0>(coords); - int rowMax = std::get<1>(coords); - int timeMax = std::get<2>(coords); - // Build total cluster - o2::tpc::KrCluster tempCluster = cluster->buildCluster(padMax, rowMax, timeMax); - tempCluster.sector = i; - vCluster.emplace_back(tempCluster); + auto sector = digitizedSignal[i]; + if (sector->size() == 0) { + continue; + } + // Create ClusterFinder Object on Heap since creation on stack fails + // Probably due to too much memory consumption + auto clFinder = std::make_unique<o2::tpc::KrBoxClusterFinder>(*sector); + std::vector<std::tuple<int, int, int>> localMaxima = clFinder->findLocalMaxima(); + // Loop over cluster centers + for (const std::tuple<int, int, int>& coords : localMaxima) { + int padMax = std::get<0>(coords); + int rowMax = std::get<1>(coords); + int timeMax = std::get<2>(coords); + + if (timeMax >= lastTimeBin) { + continue; } - // Clean up memory: - delete cluster; - cluster = nullptr; + // Build total cluster + o2::tpc::KrCluster tempCluster = clFinder->buildCluster(padMax, rowMax, timeMax); + tempCluster.sector = i; + clusters.emplace_back(tempCluster); } } // Fill Tree - T->Fill(); - vCluster.clear(); + tClusters->Fill(); + clusters.clear(); } // Write Tree to file - f->cd(); - T->Write(); - f->Close(); + fOut->Write(); + fOut->Close(); return; } diff --git a/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx b/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx index 8f03e702bbf81..df12de4060693 100644 --- a/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx +++ b/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx @@ -35,7 +35,14 @@ KrBoxClusterFinder::KrBoxClusterFinder(std::vector<o2::tpc::Digit>& eventSector) // Fill digits map for (const auto& digit : eventSector) { - mMapOfAllDigits[digit.getTimeStamp()][digit.getRow()][digit.getPad()] = digit.getChargeFloat(); + const int time = digit.getTimeStamp(); + const int row = digit.getRow(); + const int pad = digit.getPad(); + + const int pads = mMapperInstance.getNumberOfPadsInRowSector(row); + const int corPad = pad - (pads / 2) + (MaxPads / 2); + + mMapOfAllDigits[time][row][corPad] = digit.getChargeFloat(); } } @@ -54,6 +61,10 @@ void KrBoxClusterFinder::updateTempClusterFinal() mTempCluster.sigmaPad = std::sqrt(std::abs(mTempCluster.sigmaPad - mTempCluster.meanPad * mTempCluster.meanPad)); mTempCluster.sigmaRow = std::sqrt(std::abs(mTempCluster.sigmaRow - mTempCluster.meanRow * mTempCluster.meanRow)); mTempCluster.sigmaTime = std::sqrt(std::abs(mTempCluster.sigmaTime - mTempCluster.meanTime * mTempCluster.meanTime)); + + const int pads = mMapperInstance.getNumberOfPadsInRowSector(int(mTempCluster.meanRow)); + + mTempCluster.meanPad = mTempCluster.meanPad + (pads / 2.0) - (MaxPads / 2.0); } // Function to update the temporal cluster. From a3e598a28a831718e3dc12c793fc38aae0ab5a5e Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 10 Aug 2020 08:01:05 +0200 Subject: [PATCH 0301/1751] DPL Analysis: templates to build and propagate custom index (#4097) --- Analysis/Tutorials/CMakeLists.txt | 5 + Analysis/Tutorials/src/custom_index.cxx | 46 +++++++ Framework/Core/include/Framework/ASoA.h | 65 ++++++++- .../include/Framework/AnalysisDataModel.h | 2 +- .../Core/include/Framework/AnalysisTask.h | 127 +++++++++++++++--- .../Core/include/Framework/TableBuilder.h | 7 +- 6 files changed, 224 insertions(+), 28 deletions(-) create mode 100644 Analysis/Tutorials/src/custom_index.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index ac029f4c7427b..43c73dab44567 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -107,3 +107,8 @@ o2_add_dpl_workflow(ccdbaccess PUBLIC_LINK_LIBRARIES O2::AnalysisCore O2::CCDB O2::Framework O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) +o2_add_dpl_workflow(custom-index + SOURCES src/custom_index.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) + diff --git a/Analysis/Tutorials/src/custom_index.cxx b/Analysis/Tutorials/src/custom_index.cxx new file mode 100644 index 0000000000000..0da64f533496b --- /dev/null +++ b/Analysis/Tutorials/src/custom_index.cxx @@ -0,0 +1,46 @@ +// 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" + +namespace o2::aod +{ +namespace indices +{ +DECLARE_SOA_INDEX_COLUMN(BC, bc); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_INDEX_COLUMN(Zdc, zdc); +} // namespace indices + +DECLARE_SOA_INDEX_TABLE(Matched, BCs, "MATCHED", indices::CollisionId, indices::BCId, indices::ZdcId); + +} // namespace o2::aod + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// This is a very simple example showing how to iterate over tracks +// and create a new collection for them. +// FIXME: this should really inherit from AnalysisTask but +// we need GCC 7.4+ for that +struct ATask { + Builds<aod::Matched> matched; + void init(o2::framework::InitContext&) + { + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<ATask>("produce-index")}; +} diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index ee2cd61704ad6..82a4fdb94f2b4 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -774,6 +774,13 @@ using is_soa_table_t = typename framework::is_specialization<T, soa::Table>; template <typename T> using is_soa_table_like_t = typename framework::is_base_of_template<soa::Table, T>; +/// Helper function to extract bound indices +template <typename... Is> +static constexpr auto extractBindings(framework::pack<Is...>) +{ + return framework::pack<typename Is::binding_t...>{}; +} + /// A Table class which observes an arrow::Table and provides /// It is templated on a set of Column / DynamicColumn types. template <typename... C> @@ -786,12 +793,7 @@ class Table template <typename IP, typename Parent, typename... T> struct RowViewBase : public RowViewCore<IP, C...> { - /// Helper function to extract bound indices - template <typename... Is> - static constexpr auto extractBindings(framework::pack<Is...>) - { - return framework::pack<typename Is::binding_t...>{}; - } + using external_index_columns_t = framework::selected_pack<is_external_index_t, C...>; using bindings_pack_t = decltype(extractBindings(external_index_columns_t{})); using parent_t = Parent; @@ -838,6 +840,8 @@ class Table if constexpr (framework::has_type_v<std::decay_t<TI>, bindings_pack_t>) { constexpr auto idx = framework::has_type_at<std::decay_t<TI>>(bindings_pack_t{}); return framework::pack_element_t<idx, external_index_columns_t>::getId(); + } else if constexpr (std::is_same_v<std::decay_t<TI>, Parent>) { + return this->globalIndex(); } else { return static_cast<int32_t>(-1); } @@ -1294,6 +1298,32 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); #define DECLARE_SOA_EXTENDED_TABLE_USER(_Name_, _Table_, _Description_, ...) \ DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "AOD", _Description_, __VA_ARGS__) +#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, ...) \ + using _Name_ = o2::soa::IndexTable<_Key_, soa::Index<>, __VA_ARGS__>; \ + \ + struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ + using table_t = _Name_; \ + using Key = _Key_; \ + using index_pack_t = framework::pack<__VA_ARGS__>; \ + using originals = decltype(soa::extractBindings(index_pack_t{})); \ + static constexpr char const* mLabel = #_Name_; \ + static constexpr char const mOrigin[4] = _Origin_; \ + static constexpr char const mDescription[16] = _Description_; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_> { \ + using metadata = _Name_##Metadata; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_::unfiltered_iterator> { \ + using metadata = _Name_##Metadata; \ + }; + +#define DECLARE_SOA_INDEX_TABLE(_Name_, _Key_, _Description_, ...) \ + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, __VA_ARGS__) + namespace o2::soa { template <typename... Ts> @@ -1685,6 +1715,29 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) return arrow::Table::Make(std::make_shared<arrow::Schema>(new_fields), new_columns); } +/// Template for building an index table to access matching rows from non- +/// joinable, but compatible tables, e.g. Collisions and ZDCs. +/// First argument is the key table (BCs for the Collisions+ZDCs case), the rest +/// are index columns defined for the required tables. +/// First index will be used by process() as the grouping +template <typename Key, typename H, typename... Ts> +struct IndexTable : Table<H, Ts...> { + using table_t = Table<H, Ts...>; + using indexing_t = Key; + using first_t = H; + using rest_t = framework::pack<Ts...>; + + IndexTable(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) + : table_t{table, offset} + { + } + + IndexTable(IndexTable const&) = default; + IndexTable(IndexTable&&) = default; + IndexTable& operator=(IndexTable const&) = default; + IndexTable& operator=(IndexTable&&) = default; +}; + } // namespace o2::soa #endif // O2_FRAMEWORK_ASOA_H_ diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 8684076c10411..eadce4cf050ec 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -361,7 +361,7 @@ DECLARE_SOA_COLUMN(TimeZPA, timeZPA, float); DECLARE_SOA_COLUMN(TimeZPC, timeZPC, float); } // namespace zdc -DECLARE_SOA_TABLE(Zdcs, "AOD", "ZDC", zdc::BCId, zdc::EnergyZEM1, zdc::EnergyZEM2, +DECLARE_SOA_TABLE(Zdcs, "AOD", "ZDC", o2::soa::Index<>, zdc::BCId, zdc::EnergyZEM1, zdc::EnergyZEM2, zdc::EnergyCommonZNA, zdc::EnergyCommonZNC, zdc::EnergyCommonZPA, zdc::EnergyCommonZPC, zdc::EnergySectorZNA, zdc::EnergySectorZNC, zdc::EnergySectorZPA, zdc::EnergySectorZPC, zdc::TimeZEM1, zdc::TimeZEM2, zdc::TimeZNA, zdc::TimeZNC, zdc::TimeZPA, zdc::TimeZPC); diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index e22899871fd6b..7b32ad4a8400b 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -142,19 +142,12 @@ struct Produces<soa::Table<C...>> : WritingCursor<typename soa::FilterPersistent } }; -/// This helper class allows you to declare extended tables which should be -/// created by the task (as opposed to those pre-defined by data model) +/// Base template for table transformation declarations template <typename T> -struct Spawns { +struct TransformTable { using metadata = typename aod::MetadataTrait<T>::metadata; - using expression_pack_t = typename metadata::expression_pack_t; using originals = typename metadata::originals; - constexpr expression_pack_t pack() - { - return expression_pack_t{}; - } - template <typename O> InputSpec const base_spec() { @@ -202,6 +195,36 @@ struct Spawns { std::shared_ptr<T> table = nullptr; }; +/// This helper struct allows you to declare extended tables which should be +/// created by the task (as opposed to those pre-defined by data model) +template <typename T> +struct Spawns : TransformTable<T> { + using metadata = typename TransformTable<T>::metadata; + using originals = typename metadata::originals; + using expression_pack_t = typename metadata::expression_pack_t; + + constexpr auto pack() + { + return expression_pack_t{}; + } +}; + +/// This helper struct allows you to declare index tables to be created in a task +template <typename T> +struct Builds : TransformTable<T> { + using metadata = typename TransformTable<T>::metadata; + using originals = typename metadata::originals; + using Key = typename T::indexing_t; + using H = typename T::first_t; + using Ts = typename T::rest_t; + using index_pack_t = typename metadata::index_pack_t; + + constexpr auto pack() + { + return index_pack_t{}; + } +}; + /// This helper class allows you to declare things which will be created by a /// given analysis task. Currently wrapped objects are limited to be TNamed /// descendants. Objects will be written to a ROOT file at the end of the @@ -880,6 +903,7 @@ struct FilterManager<expressions::Filter> { } }; +/// SFINAE placeholder template <typename T> struct OutputManager { template <typename ANY> @@ -907,6 +931,7 @@ struct OutputManager { } }; +/// Produces specialization template <typename TABLE> struct OutputManager<Produces<TABLE>> { static bool appendOutput(std::vector<OutputSpec>& outputs, Produces<TABLE>& what, uint32_t) @@ -929,6 +954,7 @@ struct OutputManager<Produces<TABLE>> { } }; +/// HistogramRegistry specialization template <> struct OutputManager<HistogramRegistry> { static bool appendOutput(std::vector<OutputSpec>& outputs, HistogramRegistry& what, uint32_t) @@ -952,6 +978,7 @@ struct OutputManager<HistogramRegistry> { } }; +/// OutputObj specialization template <typename T> struct OutputManager<OutputObj<T>> { static bool appendOutput(std::vector<OutputSpec>& outputs, OutputObj<T>& what, uint32_t hash) @@ -977,6 +1004,19 @@ struct OutputManager<OutputObj<T>> { } }; +/// Spawns specializations +template <typename O> +static auto extractOriginal(ProcessingContext& pc) +{ + return pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable(); +} + +template <typename... Os> +static std::vector<std::shared_ptr<arrow::Table>> extractOriginals(framework::pack<Os...>, ProcessingContext& pc) +{ + return {extractOriginal<Os>(pc)...}; +} + template <typename T> struct OutputManager<Spawns<T>> { static bool appendOutput(std::vector<OutputSpec>& outputs, Spawns<T>& what, uint32_t) @@ -1004,17 +1044,48 @@ struct OutputManager<Spawns<T>> { eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); return true; } +}; - template <typename... Os> - static std::vector<std::shared_ptr<arrow::Table>> extractOriginals(framework::pack<Os...>, ProcessingContext& pc) +/// Builds specialization +template <typename O> +static auto extractTypedOriginal(ProcessingContext& pc) +{ + ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables + return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; +} + +template <typename... Os> +static auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +{ + return std::make_tuple(extractTypedOriginal<Os>(pc)...); +} + +template <typename T> +struct OutputManager<Builds<T>> { + static bool appendOutput(std::vector<OutputSpec>& outputs, Builds<T>& what, uint32_t) { - return {extractOriginal<Os>(pc)...}; + outputs.emplace_back(what.spec()); + return true; } - template <typename O> - static auto extractOriginal(ProcessingContext& pc) + static bool prepare(ProcessingContext& pc, Builds<T>& what) + { + using metadata = typename std::decay_t<decltype(what)>::metadata; + auto source_tables = extractOriginalsTuple(typename metadata::originals{}, pc); + what.table = std::make_shared<T>(indexBuilder(typename metadata::index_pack_t{}, extractTypedOriginal<typename metadata::Key>(pc), source_tables)); + return true; + } + + static bool finalize(ProcessingContext&, Builds<T>&) { - return pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable(); + return true; + } + + static bool postRun(EndOfStreamContext& eosc, Builds<T>& what) + { + using metadata = typename std::decay_t<decltype(what)>::metadata; + eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); + return true; } }; @@ -1119,6 +1190,26 @@ struct SpawnManager<Spawns<TABLE>> { } }; +/// Manager template for building index tables +template <typename T> +struct IndexManager { + static bool requestInputs(std::vector<InputSpec>&, T const&) { return false; }; +}; + +template <typename IDX> +struct IndexManager<Builds<IDX>> { + static bool requestInputs(std::vector<InputSpec>& inputs, Builds<IDX>& builds) + { + auto base_specs = builds.base_specs(); + for (auto& base_spec : base_specs) { + if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { + inputs.emplace_back(base_spec); + } + } + return true; + } +}; + // SFINAE test template <typename T> class has_process @@ -1205,6 +1296,12 @@ DataProcessorSpec adaptAnalysisTask(char const* name, Args&&... args) }, tupledTask); + //request base tables for indices to be built + std::apply([&inputs](auto&... x) { + return (IndexManager<std::decay_t<decltype(x)>>::requestInputs(inputs, x), ...); + }, + tupledTask); + std::apply([&outputs, &hash](auto&... x) { return (OutputManager<std::decay_t<decltype(x)>>::appendOutput(outputs, x, hash), ...); }, tupledTask); std::apply([&options, &hash](auto&... x) { return (OptionManager<std::decay_t<decltype(x)>>::appendOption(options, x), ...); }, tupledTask); diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index c6c65508e120d..0b725bbdc5bf7 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -660,12 +660,7 @@ auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> table auto first = std::get<first_t>(tables); for (auto& row : first) { - auto idx = -1; - if constexpr (std::is_same_v<std::decay_t<Key>, std::decay_t<T1>>) { - idx = row.globalIndex(); - } else { - row.template getId<Key>(); - } + auto idx = row.template getId<Key>(); auto setValue = [&](auto& x) -> bool { using type = std::decay_t<decltype(x)>; constexpr auto position = framework::has_type_at<type>(rest_it_t{}); From 10af71dd177e76e75565328c91cfb3eb11ce60f1 Mon Sep 17 00:00:00 2001 From: Matteo Concas <mconcas@cern.ch> Date: Mon, 10 Aug 2020 08:02:22 +0200 Subject: [PATCH 0302/1751] Add MC simulation for IT4 (placeholder name) (#4093) --- .../DetectorsCommonDataFormats/DetID.h | 9 +- .../DetectorsCommonDataFormats/SimTraits.h | 8 +- DataFormats/Detectors/Common/src/DetID.cxx | 1 + .../Headers/include/Headers/DataHeader.h | 1 + .../include/DetectorsBase/GeometryManager.h | 2 +- Detectors/Upgrades/PostLS4/CMakeLists.txt | 2 + Detectors/Upgrades/PostLS4/IT4/CMakeLists.txt | 13 + .../Upgrades/PostLS4/IT4/base/CMakeLists.txt | 18 + .../IT4/base/include/ITS4Base/GeometryTGeo.h | 354 ++ .../include/ITS4Base/MisalignmentParameter.h | 70 + .../PostLS4/IT4/base/src/GeometryTGeo.cxx | 742 ++++ .../PostLS4/IT4/base/src/ITS4BaseLinkDef.h | 20 + .../IT4/base/src/MisalignmentParameter.cxx | 92 + .../PostLS4/IT4/macros/CMakeLists.txt | 11 + .../PostLS4/IT4/macros/test/CMakeLists.txt | 9 + .../PostLS4/IT4/simulation/CMakeLists.txt | 25 + .../PostLS4/IT4/simulation/data/simcuts.dat | 0 .../include/ITS4Simulation/Detector.h | 382 ++ .../include/ITS4Simulation/V11Geometry.h | 458 ++ .../include/ITS4Simulation/V1Layer.h | 415 ++ .../include/ITS4Simulation/V3Layer.h | 570 +++ .../include/ITS4Simulation/V3Services.h | 184 + .../PostLS4/IT4/simulation/src/Detector.cxx | 1353 ++++++ .../simulation/src/ITS4SimulationLinkDef.h | 24 + .../IT4/simulation/src/V11Geometry.cxx | 1229 ++++++ .../PostLS4/IT4/simulation/src/V1Layer.cxx | 2762 ++++++++++++ .../PostLS4/IT4/simulation/src/V3Layer.cxx | 3840 +++++++++++++++++ .../PostLS4/IT4/simulation/src/V3Services.cxx | 2340 ++++++++++ macro/CMakeLists.txt | 1 + macro/build_geometry.C | 9 +- run/CMakeLists.txt | 1 + run/O2HitMerger.h | 5 + 32 files changed, 14943 insertions(+), 7 deletions(-) create mode 100644 Detectors/Upgrades/PostLS4/IT4/CMakeLists.txt create mode 100644 Detectors/Upgrades/PostLS4/IT4/base/CMakeLists.txt create mode 100644 Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/MisalignmentParameter.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx create mode 100644 Detectors/Upgrades/PostLS4/IT4/base/src/ITS4BaseLinkDef.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/base/src/MisalignmentParameter.cxx create mode 100644 Detectors/Upgrades/PostLS4/IT4/macros/CMakeLists.txt create mode 100644 Detectors/Upgrades/PostLS4/IT4/macros/test/CMakeLists.txt create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/CMakeLists.txt create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/data/simcuts.dat create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/Detector.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V11Geometry.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V1Layer.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Layer.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Services.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/src/V11Geometry.cxx create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/src/V1Layer.cxx create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx create mode 100644 Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h index 0d14edec5ac04..43988131d846b 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h @@ -70,7 +70,8 @@ class DetID static constexpr ID ACO = 15; #ifdef ENABLE_UPGRADES static constexpr ID IT3 = 16; - static constexpr ID Last = IT3; + static constexpr ID IT4 = 17; + static constexpr ID Last = IT4; #else static constexpr ID Last = ACO; ///< if extra detectors added, update this !!! #endif @@ -132,7 +133,7 @@ class DetID static constexpr const char* sDetNames[nDetectors + 1] = ///< defined detector names #ifdef ENABLE_UPGRADES - {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ACO", "IT3", nullptr}; + {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ACO", "IT3", "IT4", nullptr}; #else {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ACO", nullptr}; #endif @@ -144,7 +145,7 @@ class DetID utils::bit2Mask(ACO) #ifdef ENABLE_UPGRADES , - utils::bit2Mask(IT3) + utils::bit2Mask(IT3), utils::bit2Mask(IT4) #endif }; @@ -155,7 +156,7 @@ class DetID o2h::gDataOriginMID, o2h::gDataOriginZDC, o2h::gDataOriginFT0, o2h::gDataOriginFV0, o2h::gDataOriginFDD, o2h::gDataOriginACO #ifdef ENABLE_UPGRADES , - o2h::gDataOriginIT3 + o2h::gDataOriginIT3, o2h::gDataOriginIT4 #endif }; diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h index f2a3d3be7d7c0..332f8a42010be 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h @@ -89,7 +89,8 @@ class SimTraits /*ACO*/ VS{ "ACOHit" } #ifdef ENABLE_UPGRADES , - /*IT3*/ VS{ "IT3Hit" } + /*IT3*/ VS{ "IT3Hit" }, + /*IT4*/ VS{ "IT4Hit" } #endif }; // clang-format on @@ -226,6 +227,11 @@ template <> struct DetIDToHitTypes<o2::detectors::DetID::IT3> { using HitType = o2::itsmft::Hit; }; + +template <> +struct DetIDToHitTypes<o2::detectors::DetID::IT4> { + using HitType = o2::itsmft::Hit; +}; #endif } // namespace detectors diff --git a/DataFormats/Detectors/Common/src/DetID.cxx b/DataFormats/Detectors/Common/src/DetID.cxx index 6214caf5c2c0f..ac6cb80e7ba12 100644 --- a/DataFormats/Detectors/Common/src/DetID.cxx +++ b/DataFormats/Detectors/Common/src/DetID.cxx @@ -30,6 +30,7 @@ constexpr DetID::ID DetID::ITS, DetID::TPC, DetID::TRD, DetID::TOF, DetID::PHS, #ifdef ENABLE_UPGRADES constexpr DetID::ID DetID::IT3; +constexpr DetID::ID DetID::IT4; #endif constexpr int DetID::nDetectors; diff --git a/DataFormats/Headers/include/Headers/DataHeader.h b/DataFormats/Headers/include/Headers/DataHeader.h index 8e79fa2c70394..91eddadc902ba 100644 --- a/DataFormats/Headers/include/Headers/DataHeader.h +++ b/DataFormats/Headers/include/Headers/DataHeader.h @@ -634,6 +634,7 @@ constexpr o2::header::DataOrigin gDataOriginTRD{"TRD"}; constexpr o2::header::DataOrigin gDataOriginZDC{"ZDC"}; #ifdef ENABLE_UPGRADES constexpr o2::header::DataOrigin gDataOriginIT3{"IT3"}; +constexpr o2::header::DataOrigin gDataOriginIT4{"IT4"}; #endif //possible data types diff --git a/Detectors/Base/include/DetectorsBase/GeometryManager.h b/Detectors/Base/include/DetectorsBase/GeometryManager.h index 5b340f7487380..f29e795664d3d 100644 --- a/Detectors/Base/include/DetectorsBase/GeometryManager.h +++ b/Detectors/Base/include/DetectorsBase/GeometryManager.h @@ -130,7 +130,7 @@ class GeometryManager : public TObject private: /// sensitive volume identifier composed from (det_mask<<sDetOffset)|(sensid&sSensorMask) #ifdef ENABLE_UPGRADES - static constexpr UInt_t sDetOffset = 14; /// detector identifier will start from this bit + static constexpr UInt_t sDetOffset = 13; /// detector identifier will start from this bit #else static constexpr UInt_t sDetOffset = 15; /// detector identifier will start from this bit #endif diff --git a/Detectors/Upgrades/PostLS4/CMakeLists.txt b/Detectors/Upgrades/PostLS4/CMakeLists.txt index 73aa18e55d56b..031729b79c5ed 100644 --- a/Detectors/Upgrades/PostLS4/CMakeLists.txt +++ b/Detectors/Upgrades/PostLS4/CMakeLists.txt @@ -7,3 +7,5 @@ # 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. + +add_subdirectory(IT4) \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/CMakeLists.txt b/Detectors/Upgrades/PostLS4/IT4/CMakeLists.txt new file mode 100644 index 0000000000000..4d58e2495d96f --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/CMakeLists.txt @@ -0,0 +1,13 @@ +# 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. + +add_subdirectory(simulation) +add_subdirectory(base) +add_subdirectory(macros) \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/base/CMakeLists.txt b/Detectors/Upgrades/PostLS4/IT4/base/CMakeLists.txt new file mode 100644 index 0000000000000..bcf29a286d57c --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/base/CMakeLists.txt @@ -0,0 +1,18 @@ +# 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_library(ITS4Base + SOURCES src/MisalignmentParameter.cxx + src/GeometryTGeo.cxx + PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::ITSMFTBase) + +o2_target_root_dictionary(ITS4Base + HEADERS include/ITS4Base/GeometryTGeo.h + include/ITS4Base/MisalignmentParameter.h) diff --git a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h new file mode 100644 index 0000000000000..5248112ef766f --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h @@ -0,0 +1,354 @@ +// 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 GeometryTGeo.h +/// \brief Definition of the GeometryTGeo class +/// \author cvetan.cheshkov@cern.ch - 15/02/2007 +/// \author ruben.shahoyan@cern.ch - adapted to ITSupg 18/07/2012 + +#ifndef ALICEO2_ITS4_GEOMETRYTGEO_H_ +#define ALICEO2_ITS4_GEOMETRYTGEO_H_ + +#include <TGeoMatrix.h> // for TGeoHMatrix +#include <TObject.h> // for TObject +#include <array> +#include <string> +#include <vector> +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "ITSMFTBase/GeometryTGeo.h" +#include "MathUtils/Utils.h" +#include "Rtypes.h" // for Int_t, Double_t, Bool_t, UInt_t, etc + +class TGeoPNEntry; + +namespace o2 +{ +namespace its4 +{ +/// GeometryTGeo is a simple interface class to TGeoManager. It is used in the simulation +/// and reconstruction in order to query the TGeo ITS geometry. +/// RS: In order to preserve the static character of the class but make it dynamically access +/// geometry, we need to check in every method if the structures are initialized. To be converted +/// to singleton at later stage. + +class GeometryTGeo : public o2::itsmft::GeometryTGeo +{ + public: + typedef o2::Transform3D Mat3D; + using DetMatrixCache::getMatrixL2G; + using DetMatrixCache::getMatrixT2GRot; + using DetMatrixCache::getMatrixT2L; + // this method is not advised for ITS: for barrel detectors whose tracking frame is just a rotation + // it is cheaper to use T2GRot + using DetMatrixCache::getMatrixT2G; + + static GeometryTGeo* Instance() + { + // get (create if needed) a unique instance of the object + if (!sInstance) + sInstance = std::unique_ptr<GeometryTGeo>(new GeometryTGeo(true, 0)); + return sInstance.get(); + } + + // adopt the unique instance from external raw pointer (to be used only to read saved instance from file) + static void adopt(GeometryTGeo* raw); + + // constructor + // ATTENTION: this class is supposed to behave as a singleton, but to make it root-persistent + // we must define public default constructor. + // NEVER use it, it will throw exception if the class instance was already created + // Use GeometryTGeo::Instance() instead + GeometryTGeo(bool build = kFALSE, int loadTrans = 0 + /*o2::base::utils::bit2Mask(o2::TransformType::T2L, // default transformations to load + o2::TransformType::T2G, + o2::TransformType::L2G)*/ + ); + + /// Default destructor + ~GeometryTGeo() override = default; + + GeometryTGeo(const GeometryTGeo& src) = delete; + GeometryTGeo& operator=(const GeometryTGeo& geom) = delete; + + // implement filling of the matrix cache + using o2::itsmft::GeometryTGeo::fillMatrixCache; + void fillMatrixCache(int mask) override; + + // cache parameters of sensors tracking frames + void fillTrackingFramesCache(); + + /// Exract ITS parameters from TGeo + void Build(int loadTrans = 0) override; + + int getNumberOfChipRowsPerModule(int lay) const { return mNumberOfChipRowsPerModule[lay]; } + int getNumberOfChipColsPerModule(int lay) const + { + return mNumberOfChipRowsPerModule[lay] ? mNumberOfChipsPerModule[lay] / mNumberOfChipRowsPerModule[lay] : -1; + } + + int getNumberOfChipsPerModule(int lay) const { return mNumberOfChipsPerModule[lay]; } + int getNumberOfChipsPerHalfStave(int lay) const { return mNumberOfChipsPerHalfStave[lay]; } + int getNumberOfChipsPerStave(int lay) const { return mNumberOfChipsPerStave[lay]; } + int getNumberOfChipsPerLayer(int lay) const { return mNumberOfChipsPerLayer[lay]; } + int getNumberOfModules(int lay) const { return mNumberOfModules[lay]; } + int getNumberOfHalfStaves(int lay) const { return mNumberOfHalfStaves[lay]; } + int getNumberOfStaves(int lay) const { return mNumberOfStaves[lay]; } + int getNumberOfLayers() const { return mNumberOfLayers; } + int getChipIndex(int lay, int detInLay) const { return getFirstChipIndex(lay) + detInLay; } + /// This routine computes the chip index number from the layer, stave, and chip number in stave + /// \param int lay The layer number. Starting from 0. + /// \param int sta The stave number. Starting from 0 + /// \param int chipInStave The chip number in the stave. Starting from 0 + int getChipIndex(int lay, int sta, int detInSta) const; + + /// This routine computes the chip index number from the layer, stave, substave and chip number + /// in substave + /// \param int lay The layer number. Starting from 0. + /// \param int sta The stave number. Starting from 0 + /// \param int substa The substave number. Starting from 0 + /// \param int chipInSStave The chip number in the sub stave. Starting from 0 + int getChipIndex(int lay, int sta, int subSta, int detInSubSta) const; + + /// This routine computes the chip index number from the layer,stave, substave module and + /// chip number in module. + /// \param int lay The layer number. Starting from 0. + /// \param int sta The stave number. Starting from 0 + /// \param int substa The substave number. Starting from 0 + /// \param int module The module number ... + /// \param int chipInSStave The chip number in the module. Starting from 0 + int getChipIndex(int lay, int sta, int subSta, int md, int detInMod) const; + + /// This routine computes the layer, stave, substave, module and chip number + /// given the chip index number + /// \param int index The chip index number, starting from zero. + /// \param int lay The layer number. Starting from 0 + /// \param int sta The stave number. Starting from 0 + /// \param int ssta The halfstave number. Starting from 0 + /// \param int mod The module number. Starting from 0 + /// \param int chip The detector number. Starting from 0 + bool getChipId(int index, int& lay, int& sta, int& ssta, int& mod, int& chip) const; + + /// Get chip layer, from 0 + int getLayer(int index) const; + + /// Get chip stave, from 0 + int getStave(int index) const; + + /// Get chip substave id in stave, from 0 + int getHalfStave(int index) const; + + /// Get chip module id in substave, from 0 + int getModule(int index) const; + + /// Get chip number within layer, from 0 + int getChipIdInLayer(int index) const; + + /// Get chip number within stave, from 0 + int getChipIdInStave(int index) const; + + /// Get chip number within stave, from 0 + int getChipIdInHalfStave(int index) const; + + /// Get chip number within module, from 0 + int getChipIdInModule(int index) const; + + int getLastChipIndex(int lay) const { return mLastChipIndex[lay]; } + int getFirstChipIndex(int lay) const { return (lay == 0) ? 0 : mLastChipIndex[lay - 1] + 1; } + const char* getSymbolicName(int index) const + { + /// return symbolic name of sensor + return o2::base::GeometryManager::getSymbolicName(getDetID(), index); + } + + const char* getSymbolicName(int lay, int sta, int det) const + { + /// return symbolic name of sensor + return getSymbolicName(getChipIndex(lay, sta, det)); + } + + /// Get the transformation matrix for a given chip (NOT A SENSOR!!!) 'index' by quering the TGeoManager + TGeoHMatrix* getMatrix(int index) const { return o2::base::GeometryManager::getMatrix(getDetID(), index); } + TGeoHMatrix* getMatrix(int lay, int sta, int sens) const { return getMatrix(getChipIndex(lay, sta, sens)); } + bool getOriginalMatrix(int index, TGeoHMatrix& m) const + { + /// Get the original (ideal geometry) TGeo matrix for a given chip identified by 'index' + /// The method is slow, so it should be used with great care (for caching only) + return o2::base::GeometryManager::getOriginalMatrix(getDetID(), index, m); + } + + bool getOriginalMatrix(int lay, int sta, int det, TGeoHMatrix& m) const + { + /// Get the original (ideal geometry) TGeo matrix for a given chip identified by 'index' + /// The method is slow, so it should be used with great care (for caching only) + return getOriginalMatrix(getChipIndex(lay, sta, det), m); + } + + const Mat3D& getMatrixT2L(int lay, int sta, int det) const { return getMatrixT2L(getChipIndex(lay, sta, det)); } + const Mat3D& getMatrixSensor(int index) const { return getMatrixL2G(index); } + const Mat3D& getMatrixSensor(int lay, int sta, int det) + { + // get positioning matrix of the sensor, alias to getMatrixL2G + return getMatrixSensor(getChipIndex(lay, sta, det)); + } + + const Rot2D& getMatrixT2GRot(int lay, int sta, int sens) + { + /// get matrix for tracking to global frame transformation + return getMatrixT2GRot(getChipIndex(lay, sta, sens)); + } + + bool isTrackingFrameCached() const { return !mCacheRefX.empty(); } + void getSensorXAlphaRefPlane(int index, float& x, float& alpha) const + { + x = getSensorRefX(index); + alpha = getSensorRefAlpha(index); + } + + float getSensorRefX(int isn) const { return mCacheRefX[isn]; } + float getSensorRefAlpha(int isn) const { return mCacheRefAlpha[isn]; } + // Attention: these are transformations wrt sensitive volume! + void localToGlobal(int index, const double* loc, double* glob); + + void localToGlobal(int lay, int sta, int det, const double* loc, double* glob); + + void globalToLocal(int index, const double* glob, double* loc); + + void globalToLocal(int lay, int sta, int det, const double* glob, double* loc); + + void localToGlobalVector(int index, const double* loc, double* glob); + + void globalToLocalVector(int index, const double* glob, double* loc); + + void Print(Option_t* opt = "") const; + + static const char* getITSVolPattern() { return sVolumeName.c_str(); } + static const char* getITSLayerPattern() { return sLayerName.c_str(); } + static const char* getITSWrapVolPattern() { return sWrapperVolumeName.c_str(); } + static const char* getITSStavePattern() { return sStaveName.c_str(); } + static const char* getITSHalfStavePattern() { return sHalfStaveName.c_str(); } + static const char* getITSModulePattern() { return sModuleName.c_str(); } + static const char* getITSChipPattern() { return sChipName.c_str(); } + static const char* getITSSensorPattern() { return sSensorName.c_str(); } + static void setITSVolPattern(const char* nm) { sVolumeName = nm; } + static void setITSLayerPattern(const char* nm) { sLayerName = nm; } + static void setITSWrapVolPattern(const char* nm) { sWrapperVolumeName = nm; } + static void setITSStavePattern(const char* nm) { sStaveName = nm; } + static void setITSHalfStavePattern(const char* nm) { sHalfStaveName = nm; } + static void setITSModulePattern(const char* nm) { sModuleName = nm; } + static void setITSChipPattern(const char* nm) { sChipName = nm; } + static void setITSSensorPattern(const char* nm) { sSensorName = nm; } + /// sym name of the layer + static const char* composeSymNameITS4() { return o2::detectors::DetID(o2::detectors::DetID::IT3).getName(); } + /// sym name of the layer + static const char* composeSymNameLayer(int lr); + + /// Sym name of the stave at given layer + static const char* composeSymNameStave(int lr, int sta); + + /// Sym name of the stave at given layer + static const char* composeSymNameHalfStave(int lr, int sta, int ssta); + + /// Sym name of the substave at given layer/stave + static const char* composeSymNameModule(int lr, int sta, int ssta, int mod); + + /// Sym name of the chip in the given layer/stave/substave/module + static const char* composeSymNameChip(int lr, int sta, int ssta, int mod, int chip); + + protected: + /// Get the transformation matrix of the SENSOR (not necessary the same as the chip) + /// for a given chip 'index' by quering the TGeoManager + TGeoHMatrix* extractMatrixSensor(int index) const; + + // create matrix for transformation from sensor local frame to global one + TGeoHMatrix& createT2LMatrix(int isn); + + // get sensor tracking frame alpha and + void extractSensorXAlpha(int isn, float& x, float& alp); + + /// This routine computes the layer number a given the chip index + /// \param int index The chip index number, starting from zero. + /// \param int indexInLr The chip index inside a layer, starting from zero. + /// \param int lay The layer number. Starting from 0. + bool getLayer(int index, int& lay, int& index2) const; + + /// Determines the number of chips per module on the (sub)stave in the Geometry + /// Also extract the layout: span of module centers in Z and X + /// \param lay: layer number from 0 + int extractNumberOfChipsPerModule(int lay, int& nrow) const; + + /// Determines the number of layers in the Geometry + /// \param lay: layer number, starting from 0 + int extractNumberOfStaves(int lay) const; + + /// Determines the number of substaves in the stave of the layer + /// \param lay: layer number, starting from 0 + int extractNumberOfHalfStaves(int lay) const; + + /// Determines the number of modules in substave in the stave of the layer + /// \param lay: layer number, starting from 0 + /// For the setup w/o modules defined the module and the stave or the substave is the same thing + /// Legacy method, keep it just in case... + int extractNumberOfModules(int lay) const; + + /// Determines the layer detector type the Geometry and + /// returns the detector type id for the layer + /// \param lay: layer number from 0 + int extractLayerChipType(int lay) const; + + /// Determines the number of layers in the Geometry + int extractNumberOfLayers(); + + /// Extract number following the prefix in the name string + int extractVolumeCopy(const char* name, const char* prefix) const; + + TGeoPNEntry* getPNEntry(int index) const + { + /// Get a pointer to the TGeoPNEntry of a chip identified by 'index' + /// Returns NULL in case of invalid index, missing TGeoManager or invalid symbolic name + return o2::base::GeometryManager::getPNEntry(getDetID(), index); + } + + protected: + static constexpr int MAXLAYERS = 15; ///< max number of active layers + + Int_t mNumberOfLayers; ///< number of layers + std::vector<int> mNumberOfStaves; ///< number of staves/layer(layer) + std::vector<int> mNumberOfHalfStaves; ///< the number of substaves/stave(layer) + std::vector<int> mNumberOfModules; ///< number of modules/substave(layer) + std::vector<int> mNumberOfChipsPerModule; ///< number of chips per module (group of chips on substaves) + std::vector<int> mNumberOfChipRowsPerModule; ///< number of chips rows per module (relevant for OB modules) + std::vector<int> mNumberOfChipsPerHalfStave; ///< number of chips per substave + std::vector<int> mNumberOfChipsPerStave; ///< number of chips per stave + std::vector<int> mNumberOfChipsPerLayer; ///< number of chips per stave + std::vector<int> mLastChipIndex; ///< max ID of the detctor in the layer + std::array<char, MAXLAYERS> mLayerToWrapper; ///< Layer to wrapper correspondence + + std::vector<float> mCacheRefX; ///< sensors tracking plane reference X + std::vector<float> mCacheRefAlpha; ///< sensors tracking plane reference alpha + + static std::string sVolumeName; ///< Mother volume name + static std::string sLayerName; ///< Layer name + static std::string sStaveName; ///< Stave name + static std::string sHalfStaveName; ///< HalfStave name + static std::string sModuleName; ///< Module name + static std::string sChipName; ///< Chip name + static std::string sSensorName; ///< Sensor name + static std::string sWrapperVolumeName; ///< Wrapper volume name + + private: + static std::unique_ptr<o2::its4::GeometryTGeo> sInstance; ///< singletone instance + + ClassDefOverride(GeometryTGeo, 1); // ITS geometry based on TGeo +}; +} // namespace its4 +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/MisalignmentParameter.h b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/MisalignmentParameter.h new file mode 100644 index 0000000000000..3c4ea1a572c24 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/MisalignmentParameter.h @@ -0,0 +1,70 @@ +// 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 MisalignmentParameter.h +/// \brief Definition of the MisalignmentParameter class + +#ifndef ALICEO2_ITS4_MISALIGNMENTPARAMETER_H_ +#define ALICEO2_ITS4_MISALIGNMENTPARAMETER_H_ + +#include "FairParGenericSet.h" // for FairParGenericSet + +#include "Rtypes.h" // for ClassDef + +#include "TArrayD.h" // for TArrayD + +class FairParamList; + +namespace o2 +{ +namespace its4 +{ +class MisalignmentParameter : public FairParGenericSet +{ + public: + MisalignmentParameter(const char* name = "MisalignmentParameter", + const char* title = "Misalignment parameter for AliceO2ITSHitProducerIdealMisallign Parameters", + const char* context = "TestDefaultContext"); + + ~MisalignmentParameter() override; + + void Clear(); + + void putParams(FairParamList*) override; + + Bool_t getParams(FairParamList*) override; + + TArrayD getShiftX() { return mShiftX; } + TArrayD getShiftY() { return mShiftY; } + TArrayD getShiftZ() { return mShiftZ; } + TArrayD getRotX() { return mRotX; } + TArrayD getRotY() { return mRotY; } + TArrayD getRotZ() { return mRotZ; } + Int_t getNumberOfDetectors() { return mNumberOfDetectors; } + + private: + TArrayD mShiftX; ///< Array to hold the misalignment in x-direction + TArrayD mShiftY; ///< Array to hold the misalignment in y-direction + TArrayD mShiftZ; ///< Array to hold the misalignment in z-direction + TArrayD mRotX; ///< Array to hold the rotation in x-direction + TArrayD mRotY; ///< Array to hold the rotation in y-direction + TArrayD mRotZ; ///< Array to hold the rotation in z-direction + Int_t mNumberOfDetectors; ///< Total number of detectors + + MisalignmentParameter(const MisalignmentParameter&); + + MisalignmentParameter& operator=(const MisalignmentParameter&); + + ClassDefOverride(MisalignmentParameter, 1); +}; +} // namespace its4 +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx new file mode 100644 index 0000000000000..d686f3010e25d --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx @@ -0,0 +1,742 @@ +// 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 GeometryTGeo.cxx +/// \brief Implementation of the GeometryTGeo class +/// \author cvetan.cheshkov@cern.ch - 15/02/2007 +/// \author ruben.shahoyan@cern.ch - adapted to ITSupg 18/07/2012 + +// ATTENTION: In opposite to old AliITSgeomTGeo, all indices start from 0, not from 1!!! + +#include "ITS4Base/GeometryTGeo.h" +#include "DetectorsBase/GeometryManager.h" +#include "ITSMFTBase/SegmentationAlpide.h" +#include "MathUtils/Cartesian3D.h" + +#include "FairLogger.h" // for LOG + +#include <TGeoBBox.h> // for TGeoBBox +#include <TGeoManager.h> // for gGeoManager, TGeoManager +#include <TGeoPhysicalNode.h> // for TGeoPNEntry, TGeoPhysicalNode +#include <TGeoShape.h> // for TGeoShape +#include <TMath.h> // for Nint, ATan2, RadToDeg +#include <TString.h> // for TString, Form +#include "TClass.h" // for TClass +#include "TGeoMatrix.h" // for TGeoHMatrix +#include "TGeoNode.h" // for TGeoNode, TGeoNodeMatrix +#include "TGeoVolume.h" // for TGeoVolume +#include "TMathBase.h" // for Max +#include "TObjArray.h" // for TObjArray +#include "TObject.h" // for TObject + +#include <cctype> // for isdigit +#include <cstdio> // for snprintf, NULL, printf +#include <cstring> // for strstr, strlen + +using namespace TMath; +using namespace o2::its4; +using namespace o2::detectors; +using namespace o2::utils; + +using Segmentation = o2::itsmft::SegmentationAlpide; + +ClassImp(o2::its4::GeometryTGeo); + +std::unique_ptr<o2::its4::GeometryTGeo> GeometryTGeo::sInstance; + +std::string GeometryTGeo::sVolumeName = "ITSV"; ///< Mother volume name +std::string GeometryTGeo::sLayerName = "ITSULayer"; ///< Layer name +std::string GeometryTGeo::sStaveName = "ITSUStave"; ///< Stave name +std::string GeometryTGeo::sHalfStaveName = "ITSUHalfStave"; ///< HalfStave name +std::string GeometryTGeo::sModuleName = "ITSUModule"; ///< Module name +std::string GeometryTGeo::sChipName = "ITSUChip"; ///< Chip name +std::string GeometryTGeo::sSensorName = "ITSUSensor"; ///< Sensor name +std::string GeometryTGeo::sWrapperVolumeName = "ITSUWrapVol"; ///< Wrapper volume name + +//__________________________________________________________________________ +GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : o2::itsmft::GeometryTGeo(DetID::IT3) +{ + // default c-tor, if build is true, the structures will be filled and the transform matrices + // will be cached + if (sInstance) { + LOG(FATAL) << "Invalid use of public constructor: o2::its4::GeometryTGeo instance exists"; + // throw std::runtime_error("Invalid use of public constructor: o2::its4::GeometryTGeo instance exists"); + } + + for (int i = MAXLAYERS; i--;) { + mLayerToWrapper[i] = -1; + } + if (build) { + Build(loadTrans); + } +} + +//__________________________________________________________________________ +void GeometryTGeo::adopt(GeometryTGeo* raw) +{ + // adopt the unique instance from external raw pointer (to be used only to read saved instance from file) + if (sInstance) { + LOG(FATAL) << "No adoption: o2::its4::GeometryTGeo instance exists"; + } + sInstance = std::unique_ptr<o2::its4::GeometryTGeo>(raw); +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIndex(int lay, int sta, int chipInStave) const +{ + return getFirstChipIndex(lay) + mNumberOfChipsPerStave[lay] * sta + chipInStave; +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIndex(int lay, int sta, int substa, int chipInSStave) const +{ + int n = getFirstChipIndex(lay) + mNumberOfChipsPerStave[lay] * sta + chipInSStave; + if (mNumberOfHalfStaves[lay] && substa > 0) { + n += mNumberOfChipsPerHalfStave[lay] * substa; + } + return n; +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIndex(int lay, int sta, int substa, int md, int chipInMod) const +{ + int n = getFirstChipIndex(lay) + mNumberOfChipsPerStave[lay] * sta + chipInMod; + if (mNumberOfHalfStaves[lay] && substa > 0) { + n += mNumberOfChipsPerHalfStave[lay] * substa; + } + if (mNumberOfModules[lay] && md > 0) { + n += mNumberOfChipsPerModule[lay] * md; + } + return n; +} + +//__________________________________________________________________________ +bool GeometryTGeo::getLayer(int index, int& lay, int& indexInLr) const +{ + lay = getLayer(index); + indexInLr = index - getFirstChipIndex(lay); + return kTRUE; +} + +//__________________________________________________________________________ +int GeometryTGeo::getLayer(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + return lay; +} + +//__________________________________________________________________________ +int GeometryTGeo::getStave(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + index -= getFirstChipIndex(lay); + return index / mNumberOfChipsPerStave[lay]; +} + +//__________________________________________________________________________ +int GeometryTGeo::getHalfStave(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + if (mNumberOfHalfStaves[lay] < 0) { + return -1; + } + index -= getFirstChipIndex(lay); + index %= mNumberOfChipsPerStave[lay]; + return index / mNumberOfChipsPerHalfStave[lay]; +} + +//__________________________________________________________________________ +int GeometryTGeo::getModule(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + if (mNumberOfModules[lay] < 0) { + return 0; + } + index -= getFirstChipIndex(lay); + index %= mNumberOfChipsPerStave[lay]; + if (mNumberOfHalfStaves[lay]) { + index %= mNumberOfChipsPerHalfStave[lay]; + } + return index / mNumberOfChipsPerModule[lay]; +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIdInLayer(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + index -= getFirstChipIndex(lay); + return index; +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIdInStave(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + index -= getFirstChipIndex(lay); + return index % mNumberOfChipsPerStave[lay]; +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIdInHalfStave(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + index -= getFirstChipIndex(lay); + return index % mNumberOfChipsPerHalfStave[lay]; +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIdInModule(int index) const +{ + int lay = 0; + while (index > mLastChipIndex[lay]) { + lay++; + } + index -= getFirstChipIndex(lay); + return index % mNumberOfChipsPerModule[lay]; +} + +//__________________________________________________________________________ +bool GeometryTGeo::getChipId(int index, int& lay, int& sta, int& hsta, int& mod, int& chip) const +{ + lay = getLayer(index); + index -= getFirstChipIndex(lay); + sta = index / mNumberOfChipsPerStave[lay]; + index %= mNumberOfChipsPerStave[lay]; + hsta = mNumberOfHalfStaves[lay] > 0 ? index / mNumberOfChipsPerHalfStave[lay] : -1; + index %= mNumberOfChipsPerHalfStave[lay]; + mod = mNumberOfModules[lay] > 0 ? index / mNumberOfChipsPerModule[lay] : -1; + chip = index % mNumberOfChipsPerModule[lay]; + + return kTRUE; +} + +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameLayer(int lr) +{ + return Form("%s/%s%d", composeSymNameITS4(), getITSLayerPattern(), lr); +} + +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameStave(int lr, int stave) +{ + return Form("%s/%s%d", composeSymNameLayer(lr), getITSStavePattern(), stave); +} + +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameHalfStave(int lr, int stave, int substave) +{ + return substave >= 0 ? Form("%s/%s%d", composeSymNameStave(lr, stave), getITSHalfStavePattern(), substave) + : composeSymNameStave(lr, stave); +} + +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameModule(int lr, int stave, int substave, int mod) +{ + return mod >= 0 ? Form("%s/%s%d", composeSymNameHalfStave(lr, stave, substave), getITSModulePattern(), mod) + : composeSymNameHalfStave(lr, stave, substave); +} + +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameChip(int lr, int sta, int substave, int mod, int chip) +{ + return Form("%s/%s%d", composeSymNameModule(lr, sta, substave, mod), getITSChipPattern(), chip); +} + +//__________________________________________________________________________ +TGeoHMatrix* GeometryTGeo::extractMatrixSensor(int index) const +{ + // extract matrix transforming from the PHYSICAL sensor frame to global one + // Note, the if the effective sensitive layer thickness is smaller than the + // total physical sensor tickness, this matrix is biased and connot be used + // directly for transformation from sensor frame to global one. + // + // Therefore we need to add a shift + + int lay, stav, sstav, mod, chipInMod; + getChipId(index, lay, stav, sstav, mod, chipInMod); + + int wrID = mLayerToWrapper[lay]; + + TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getITSVolPattern()); + + if (wrID >= 0) { + path += Form("%s%d_1/", getITSWrapVolPattern(), wrID); + } + + path += + Form("%s%d_1/%s%d_%d/", GeometryTGeo::getITSLayerPattern(), lay, GeometryTGeo::getITSStavePattern(), lay, stav); + + if (mNumberOfHalfStaves[lay] > 0) { + path += Form("%s%d_%d/", GeometryTGeo::getITSHalfStavePattern(), lay, sstav); + } + if (mNumberOfModules[lay] > 0) { + path += Form("%s%d_%d/", GeometryTGeo::getITSModulePattern(), lay, mod); + } + path += + Form("%s%d_%d/%s%d_1", GeometryTGeo::getITSChipPattern(), lay, chipInMod, GeometryTGeo::getITSSensorPattern(), lay); + + static TGeoHMatrix matTmp; + gGeoManager->PushPath(); + + if (!gGeoManager->cd(path.Data())) { + gGeoManager->PopPath(); + LOG(ERROR) << "Error in cd-ing to " << path.Data(); + return nullptr; + } // end if !gGeoManager + + matTmp = *gGeoManager->GetCurrentMatrix(); // matrix may change after cd + // RSS + // printf("%d/%d/%d %s\n",lay,stav,detInSta,path.Data()); + // mat->Print(); + // Restore the modeler state. + gGeoManager->PopPath(); + + // account for the difference between physical sensitive layer (where charge collection is simulated) and effective sensor ticknesses + static TGeoTranslation tra(0., 0.5 * (Segmentation::SensorLayerThickness - Segmentation::SensorLayerThicknessEff), 0.); + + matTmp *= tra; + + return &matTmp; +} + +//__________________________________________________________________________ +void GeometryTGeo::Build(int loadTrans) +{ + if (isBuilt()) { + LOG(WARNING) << "Already built"; + return; // already initialized + } + + if (!gGeoManager) { + // RSTODO: in future there will be a method to load matrices from the CDB + LOG(FATAL) << "Geometry is not loaded"; + } + + mNumberOfLayers = extractNumberOfLayers(); + if (!mNumberOfLayers) { + return; + } + + mNumberOfStaves.resize(mNumberOfLayers); + mNumberOfHalfStaves.resize(mNumberOfLayers); + mNumberOfModules.resize(mNumberOfLayers); + mNumberOfChipsPerModule.resize(mNumberOfLayers); + mNumberOfChipRowsPerModule.resize(mNumberOfLayers); + mNumberOfChipsPerHalfStave.resize(mNumberOfLayers); + mNumberOfChipsPerStave.resize(mNumberOfLayers); + mNumberOfChipsPerLayer.resize(mNumberOfLayers); + mLastChipIndex.resize(mNumberOfLayers); + int numberOfChips = 0; + + for (int i = 0; i < mNumberOfLayers; i++) { + mNumberOfStaves[i] = extractNumberOfStaves(i); + mNumberOfHalfStaves[i] = extractNumberOfHalfStaves(i); + mNumberOfModules[i] = extractNumberOfModules(i); + mNumberOfChipsPerModule[i] = extractNumberOfChipsPerModule(i, mNumberOfChipRowsPerModule[i]); + mNumberOfChipsPerHalfStave[i] = mNumberOfChipsPerModule[i] * Max(1, mNumberOfModules[i]); + mNumberOfChipsPerStave[i] = mNumberOfChipsPerHalfStave[i] * Max(1, mNumberOfHalfStaves[i]); + mNumberOfChipsPerLayer[i] = mNumberOfChipsPerStave[i] * mNumberOfStaves[i]; + numberOfChips += mNumberOfChipsPerLayer[i]; + mLastChipIndex[i] = numberOfChips - 1; + } + setSize(numberOfChips); + fillTrackingFramesCache(); + // + fillMatrixCache(loadTrans); +} + +//__________________________________________________________________________ +void GeometryTGeo::fillMatrixCache(int mask) +{ + // populate matrix cache for requested transformations + // + if (mSize < 1) { + LOG(WARNING) << "The method Build was not called yet"; + Build(mask); + return; + } + + // build matrices + if ((mask & o2::utils::bit2Mask(o2::TransformType::L2G)) && !getCacheL2G().isFilled()) { + // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation + LOG(INFO) << "Loading ITS L2G matrices from TGeo"; + auto& cacheL2G = getCacheL2G(); + cacheL2G.setSize(mSize); + + for (int i = 0; i < mSize; i++) { + TGeoHMatrix* hm = extractMatrixSensor(i); + cacheL2G.setMatrix(Mat3D(*hm), i); + } + } + + if ((mask & o2::utils::bit2Mask(o2::TransformType::T2L)) && !getCacheT2L().isFilled()) { + // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation + LOG(INFO) << "Loading ITS T2L matrices from TGeo"; + auto& cacheT2L = getCacheT2L(); + cacheT2L.setSize(mSize); + for (int i = 0; i < mSize; i++) { + TGeoHMatrix& hm = createT2LMatrix(i); + cacheT2L.setMatrix(Mat3D(hm), i); + } + } + + if ((mask & o2::utils::bit2Mask(o2::TransformType::T2G)) && !getCacheT2G().isFilled()) { + LOG(WARNING) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices"; + // matrices for Tracking to Global frame transformation + LOG(INFO) << "Loading ITS T2G matrices from TGeo"; + auto& cacheT2G = getCacheT2G(); + cacheT2G.setSize(mSize); + + for (int i = 0; i < mSize; i++) { + TGeoHMatrix& mat = createT2LMatrix(i); + mat.MultiplyLeft(extractMatrixSensor(i)); + cacheT2G.setMatrix(Mat3D(mat), i); + } + } + + if ((mask & o2::utils::bit2Mask(o2::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { + // 2D rotation matrices for Tracking frame to Global rotations + LOG(INFO) << "Loading ITS T2G rotation 2D matrices"; + auto& cacheT2Gr = getCacheT2GRot(); + cacheT2Gr.setSize(mSize); + for (int i = 0; i < mSize; i++) { + cacheT2Gr.setMatrix(Rot2D(getSensorRefAlpha(i)), i); + } + } +} + +//__________________________________________________________________________ +void GeometryTGeo::fillTrackingFramesCache() +{ + // fill for every sensor its tracking frame parameteres + if (!isTrackingFrameCached()) { + // special cache for sensors tracking frame X and alpha params + mCacheRefX.resize(mSize); + mCacheRefAlpha.resize(mSize); + for (int i = 0; i < mSize; i++) { + extractSensorXAlpha(i, mCacheRefX[i], mCacheRefAlpha[i]); + } + } +} + +//__________________________________________________________________________ +int GeometryTGeo::extractNumberOfLayers() +{ + int numberOfLayers = 0; + + TGeoVolume* itsV = gGeoManager->GetVolume(getITSVolPattern()); + if (!itsV) { + LOG(FATAL) << "ITS volume " << getITSVolPattern() << " is not in the geometry"; + } + + // Loop on all ITSV nodes, count Layer volumes by checking names + // Build on the fly layer - wrapper correspondence + TObjArray* nodes = itsV->GetNodes(); + int nNodes = nodes->GetEntriesFast(); + + for (int j = 0; j < nNodes; j++) { + int lrID = -1; + TGeoNode* nd = (TGeoNode*)nodes->At(j); + const char* name = nd->GetName(); + + if (strstr(name, getITSLayerPattern())) { + numberOfLayers++; + if ((lrID = extractVolumeCopy(name, GeometryTGeo::getITSLayerPattern())) < 0) { + LOG(FATAL) << "Failed to extract layer ID from the " << name; + exit(1); + } + + mLayerToWrapper[lrID] = -1; // not wrapped + } else if (strstr(name, getITSWrapVolPattern())) { // this is a wrapper volume, may cointain layers + int wrID = -1; + if ((wrID = extractVolumeCopy(name, GeometryTGeo::getITSWrapVolPattern())) < 0) { + LOG(FATAL) << "Failed to extract wrapper ID from the " << name; + exit(1); + } + + TObjArray* nodesW = nd->GetNodes(); + int nNodesW = nodesW->GetEntriesFast(); + + for (int jw = 0; jw < nNodesW; jw++) { + TGeoNode* ndW = (TGeoNode*)nodesW->At(jw); + if (strstr(ndW->GetName(), getITSLayerPattern())) { + if ((lrID = extractVolumeCopy(ndW->GetName(), GeometryTGeo::getITSLayerPattern())) < 0) { + LOG(FATAL) << "Failed to extract layer ID from the " << name; + exit(1); + } + numberOfLayers++; + mLayerToWrapper[lrID] = wrID; + } + } + } + } + return numberOfLayers; +} + +//__________________________________________________________________________ +int GeometryTGeo::extractNumberOfStaves(int lay) const +{ + int numberOfStaves = 0; + char laynam[30]; + snprintf(laynam, 30, "%s%d", getITSLayerPattern(), lay); + TGeoVolume* volLr = gGeoManager->GetVolume(laynam); + if (!volLr) { + LOG(FATAL) << "can't find " << laynam << " volume"; + return -1; + } + + // Loop on all layer nodes, count Stave volumes by checking names + int nNodes = volLr->GetNodes()->GetEntries(); + for (int j = 0; j < nNodes; j++) { + // LOG(INFO) << "L" << lay << " " << j << " of " << nNodes << " " + // << volLr->GetNodes()->At(j)->GetName() << " " + // << getITSStavePattern() << " -> " << numberOfStaves; + if (strstr(volLr->GetNodes()->At(j)->GetName(), getITSStavePattern())) { + numberOfStaves++; + } + } + return numberOfStaves; +} + +//__________________________________________________________________________ +int GeometryTGeo::extractNumberOfHalfStaves(int lay) const +{ + if (sHalfStaveName.empty()) { + return 0; // for the setup w/o substave defined the stave and the substave is the same thing + } + int nSS = 0; + char stavnam[30]; + snprintf(stavnam, 30, "%s%d", getITSStavePattern(), lay); + TGeoVolume* volLd = gGeoManager->GetVolume(stavnam); + if (!volLd) { + LOG(FATAL) << "can't find volume " << stavnam; + } + // Loop on all stave nodes, count Chip volumes by checking names + int nNodes = volLd->GetNodes()->GetEntries(); + for (int j = 0; j < nNodes; j++) { + if (strstr(volLd->GetNodes()->At(j)->GetName(), getITSHalfStavePattern())) { + nSS++; + } + } + return nSS; +} + +//__________________________________________________________________________ +int GeometryTGeo::extractNumberOfModules(int lay) const +{ + if (sModuleName.empty()) { + return 0; + } + + char stavnam[30]; + TGeoVolume* volLd = nullptr; + + if (!sHalfStaveName.empty()) { + snprintf(stavnam, 30, "%s%d", getITSHalfStavePattern(), lay); + volLd = gGeoManager->GetVolume(stavnam); + } + if (!volLd) { // no substaves, check staves + snprintf(stavnam, 30, "%s%d", getITSStavePattern(), lay); + volLd = gGeoManager->GetVolume(stavnam); + } + if (!volLd) { + return 0; + } + + int nMod = 0; + + // Loop on all substave nodes, count module volumes by checking names + int nNodes = volLd->GetNodes()->GetEntries(); + + for (int j = 0; j < nNodes; j++) { + if (strstr(volLd->GetNodes()->At(j)->GetName(), getITSModulePattern())) { + nMod++; + } + } + return nMod; +} + +//__________________________________________________________________________ +int GeometryTGeo::extractNumberOfChipsPerModule(int lay, int& nrow) const +{ + int numberOfChips = 0; + char stavnam[30]; + TGeoVolume* volLd = nullptr; + + if (!sModuleName.empty()) { + snprintf(stavnam, 30, "%s%d", getITSModulePattern(), lay); + volLd = gGeoManager->GetVolume(stavnam); + } + if (!volLd) { // no modules on this layer, check substaves + if (!sHalfStaveName.empty()) { + snprintf(stavnam, 30, "%s%d", getITSHalfStavePattern(), lay); + volLd = gGeoManager->GetVolume(stavnam); + } + } + if (!volLd) { // no substaves on this layer, check staves + snprintf(stavnam, 30, "%s%d", getITSStavePattern(), lay); + volLd = gGeoManager->GetVolume(stavnam); + } + if (!volLd) { + LOG(FATAL) << "can't find volume containing chips on layer " << lay; + } + + // Loop on all stave nodes, count Chip volumes by checking names + int nNodes = volLd->GetNodes()->GetEntries(); + + double xmin = 1e9, xmax = -1e9, zmin = 1e9, zmax = -1e9; + double lab[3], loc[3] = {0, 0, 0}; + double dx = -1, dz = -1; + + for (int j = 0; j < nNodes; j++) { + // AliInfo(Form("L%d %d of %d %s %s -> + // %d",lay,j,nNodes,volLd->GetNodes()->At(j)->GetName(),GetITSChipPattern(),numberOfChips)); + TGeoNodeMatrix* node = (TGeoNodeMatrix*)volLd->GetNodes()->At(j); + if (!strstr(node->GetName(), getITSChipPattern())) { + continue; + } + node->LocalToMaster(loc, lab); + if (lab[0] > xmax) { + xmax = lab[0]; + } + if (lab[0] < xmin) { + xmin = lab[0]; + } + if (lab[2] > zmax) { + zmax = lab[2]; + } + if (lab[2] < zmin) { + zmin = lab[2]; + } + + numberOfChips++; + + if (dx < 0) { + TGeoShape* chShape = node->GetVolume()->GetShape(); + TGeoBBox* bbox = dynamic_cast<TGeoBBox*>(chShape); + if (!bbox) { + LOG(FATAL) << "Chip " << node->GetName() << " volume is of unprocessed shape " << chShape->IsA()->GetName(); + } else { + dx = 2 * bbox->GetDX(); + dz = 2 * bbox->GetDZ(); + } + } + } + + double spanX = xmax - xmin; + double spanZ = zmax - zmin; + nrow = TMath::Nint(spanX / dx + 1); + int ncol = TMath::Nint(spanZ / dz + 1); + if (nrow * ncol != numberOfChips) { + LOG(ERROR) << "Inconsistency between Nchips=" << numberOfChips << " and Nrow*Ncol=" << nrow << "*" << ncol << "->" + << nrow * ncol << "\n" + << "Extracted chip dimensions (x,z): " << dx << " " << dz << " Module Span: " << spanX << " " << spanZ; + } + return numberOfChips; +} + +//__________________________________________________________________________ +int GeometryTGeo::extractLayerChipType(int lay) const +{ + char stavnam[30]; + snprintf(stavnam, 30, "%s%d", getITSLayerPattern(), lay); + TGeoVolume* volLd = gGeoManager->GetVolume(stavnam); + if (!volLd) { + LOG(FATAL) << "can't find volume " << stavnam; + return -1; + } + return volLd->GetUniqueID(); +} + +//__________________________________________________________________________ +void GeometryTGeo::Print(Option_t*) const +{ + printf("NLayers:%d NChips:%d\n", mNumberOfLayers, getNumberOfChips()); + if (!isBuilt()) + return; + + for (int i = 0; i < mNumberOfLayers; i++) { + printf( + "Lr%2d\tNStav:%2d\tNChips:%2d " + "(%dx%-2d)\tNMod:%d\tNSubSt:%d\tNSt:%3d\tChip#:%5d:%-5d\tWrapVol:%d\n", + i, mNumberOfStaves[i], mNumberOfChipsPerModule[i], mNumberOfChipRowsPerModule[i], + mNumberOfChipRowsPerModule[i] ? mNumberOfChipsPerModule[i] / mNumberOfChipRowsPerModule[i] : 0, + mNumberOfModules[i], mNumberOfHalfStaves[i], mNumberOfStaves[i], getFirstChipIndex(i), getLastChipIndex(i), + mLayerToWrapper[i]); + } +} + +//__________________________________________________________________________ +void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp) +{ + // calculate r and phi of the impact of the normal on the sensor + // (i.e. phi of the tracking frame alpha and X of the sensor in this frame) + double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3]; + const TGeoHMatrix* matL2G = extractMatrixSensor(isn); + + matL2G->LocalToMaster(locA, gloA); + matL2G->LocalToMaster(locB, gloB); + double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1]; + double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy); + double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t; + x = Sqrt(xp * xp + yp * yp); + alp = ATan2(yp, xp); + BringTo02Pi(alp); +} + +//__________________________________________________________________________ +TGeoHMatrix& GeometryTGeo::createT2LMatrix(int isn) +{ + // create for sensor isn the TGeo matrix for Tracking to Local frame transformations + static TGeoHMatrix t2l; + float x = 0.f, alp = 0.f; + extractSensorXAlpha(isn, x, alp); + t2l.Clear(); + t2l.RotateZ(alp * RadToDeg()); // rotate in direction of normal to the sensor plane + const TGeoHMatrix* matL2G = extractMatrixSensor(isn); + const TGeoHMatrix& matL2Gi = matL2G->Inverse(); + t2l.MultiplyLeft(&matL2Gi); + return t2l; +} + +//__________________________________________________________________________ +int GeometryTGeo::extractVolumeCopy(const char* name, const char* prefix) const +{ + TString nms = name; + if (!nms.BeginsWith(prefix)) { + return -1; + } + nms.Remove(0, strlen(prefix)); + if (!isdigit(nms.Data()[0])) { + return -1; + } + return nms.Atoi(); +} diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/ITS4BaseLinkDef.h b/Detectors/Upgrades/PostLS4/IT4/base/src/ITS4BaseLinkDef.h new file mode 100644 index 0000000000000..ffcb6d02c92fc --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/ITS4BaseLinkDef.h @@ -0,0 +1,20 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::its4::GeometryTGeo; +#pragma link C++ class o2::its4::MisalignmentParameter + ; + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/MisalignmentParameter.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/MisalignmentParameter.cxx new file mode 100644 index 0000000000000..de5e2886c9688 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/MisalignmentParameter.cxx @@ -0,0 +1,92 @@ +// 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 MisalignmentParameter.cxx +/// \brief Implementation of the MisalignmentParameter class + +#include "ITS4Base/MisalignmentParameter.h" + +#include "FairParamList.h" + +using namespace o2::its4; + +ClassImp(o2::its4::MisalignmentParameter); + +MisalignmentParameter::MisalignmentParameter(const char* name, const char* title, const char* context) + : FairParGenericSet(name, title, context), + mShiftX(), + mShiftY(), + mShiftZ(), + mRotX(), + mRotY(), + mRotZ(), + mNumberOfDetectors(0) +{ +} + +MisalignmentParameter::~MisalignmentParameter() = default; +void MisalignmentParameter::Clear() {} +void MisalignmentParameter::putParams(FairParamList* list) +{ + if (!list) { + return; + } + + list->add("NumberOfDetectors", mNumberOfDetectors); + list->add("ShiftX", mShiftX); + list->add("ShiftY", mShiftY); + list->add("ShiftZ", mShiftZ); + list->add("RotationX", mRotX); + list->add("RotationY", mRotY); + list->add("RotationZ", mRotZ); +} + +Bool_t MisalignmentParameter::getParams(FairParamList* list) +{ + if (!list) { + return kFALSE; + } + + if (!list->fill("NumberOfDetectors", &mNumberOfDetectors)) { + return kFALSE; + } + + mShiftX.Set(mNumberOfDetectors); + if (!list->fill("ShiftX", &mShiftX)) { + return kFALSE; + } + + mShiftY.Set(mNumberOfDetectors); + if (!list->fill("ShiftY", &mShiftY)) { + return kFALSE; + } + + mShiftZ.Set(mNumberOfDetectors); + if (!list->fill("ShiftZ", &mShiftZ)) { + return kFALSE; + } + + mRotX.Set(mNumberOfDetectors); + if (!list->fill("RotationX", &mRotX)) { + return kFALSE; + } + + mRotY.Set(mNumberOfDetectors); + if (!list->fill("RotationY", &mRotY)) { + return kFALSE; + } + + mRotZ.Set(mNumberOfDetectors); + if (!list->fill("RotationZ", &mRotZ)) { + return kFALSE; + } + + return kTRUE; +} diff --git a/Detectors/Upgrades/PostLS4/IT4/macros/CMakeLists.txt b/Detectors/Upgrades/PostLS4/IT4/macros/CMakeLists.txt new file mode 100644 index 0000000000000..e2058e7d098e1 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/macros/CMakeLists.txt @@ -0,0 +1,11 @@ +# 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. + +add_subdirectory(test) \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/macros/test/CMakeLists.txt b/Detectors/Upgrades/PostLS4/IT4/macros/test/CMakeLists.txt new file mode 100644 index 0000000000000..10bb6dd71f256 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/macros/test/CMakeLists.txt @@ -0,0 +1,9 @@ +# 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. \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/CMakeLists.txt b/Detectors/Upgrades/PostLS4/IT4/simulation/CMakeLists.txt new file mode 100644 index 0000000000000..483884d69a87d --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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_library(ITS4Simulation + SOURCES src/V11Geometry.cxx src/V1Layer.cxx src/V3Layer.cxx + src/Detector.cxx src/V3Services.cxx + PUBLIC_LINK_LIBRARIES O2::ITS4Base O2::ITSMFTSimulation + ROOT::Physics) + +o2_target_root_dictionary(ITS4Simulation + HEADERS include/ITS4Simulation/Detector.h + include/ITS4Simulation/V1Layer.h + include/ITS4Simulation/V3Layer.h + include/ITS4Simulation/V11Geometry.h + include/ITS4Simulation/V3Services.h + ) + +o2_data_file(COPY data DESTINATION Detectors/ITS4/simulation) \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/data/simcuts.dat b/Detectors/Upgrades/PostLS4/IT4/simulation/data/simcuts.dat new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/Detector.h b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/Detector.h new file mode 100644 index 0000000000000..07a34c82af897 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/Detector.h @@ -0,0 +1,382 @@ +// 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 Detector.h +/// \brief Definition of the Detector class + +#ifndef ALICEO2_ITS4_DETECTOR_H_ +#define ALICEO2_ITS4_DETECTOR_H_ + +#include <vector> // for vector +#include "DetectorsBase/GeometryManager.h" // for getSensID +#include "DetectorsBase/Detector.h" // for Detector +#include "DetectorsCommonDataFormats/DetID.h" // for Detector +#include "ITSMFTSimulation/Hit.h" // for Hit +#include "Rtypes.h" // for Int_t, Double_t, Float_t, Bool_t, etc +#include "TArrayD.h" // for TArrayD +#include "TGeoManager.h" // for gGeoManager, TGeoManager (ptr only) +#include "TLorentzVector.h" // for TLorentzVector +#include "TVector3.h" // for TVector3 + +class FairVolume; +class TGeoVolume; + +class TParticle; + +class TString; + +namespace o2 +{ +namespace itsmft +{ +class Hit; +} +} // namespace o2 + +namespace o2 +{ +namespace its4 +{ +class GeometryTGeo; +} +} // namespace o2 +namespace o2 +{ +namespace its4 +{ +class V3Layer; +} +} // namespace o2 + +namespace o2 +{ +namespace its4 +{ +class V3Layer; +class V3Services; + +class Detector : public o2::base::DetImpl<Detector> +{ + public: + enum Model { + kIBModelDummy = 0, + kIBModel0 = 1, + kIBModel1 = 2, + kIBModel21 = 3, + kIBModel22 = 4, + kIBModel3 = 5, + kIBModel4 = 10, + kOBModelDummy = 6, + kOBModel0 = 7, + kOBModel1 = 8, + kOBModel2 = 9 + }; + + static constexpr Int_t sNumberLayers = 10; ///< Number of layers in ITSU + static constexpr Int_t sNumberInnerLayers = 10; ///< Number of inner layers in ITSU + static constexpr Int_t sNumberOfWrapperVolumes = 3; ///< Number of wrapper volumes + + /// Name : Detector Name + /// Active: kTRUE for active detectors (ProcessHits() will be called) + /// kFALSE for inactive detectors + Detector(Bool_t active); + + /// Special version for ITS4: add number on Inner Layers + Detector(Bool_t active, Int_t nlay); + + /// Default constructor + Detector(); + + /// Default destructor + ~Detector() override; + + /// Initialization of the detector is done here + void InitializeO2Detector() override; + + /// This method is called for each step during simulation (see FairMCApplication::Stepping()) + Bool_t ProcessHits(FairVolume* v = nullptr) override; + + /// Registers the produced collections in FAIRRootManager + void Register() override; + + /// Gets the produced collections + std::vector<o2::itsmft::Hit>* getHits(Int_t iColl) const + { + if (iColl == 0) { + return mHits; + } + return nullptr; + } + + public: + /// Has to be called after each event to reset the containers + void Reset() override; + + /// Base class to create the detector geometry + void ConstructGeometry() override; + + /// Creates the Service Barrel (as a simple cylinder) for IB and OB + /// \param innerBarrel if true, build IB service barrel, otherwise for OB + /// \param dest the mother volume holding the service barrel + /// \param mgr the gGeoManager pointer (used to get the material) + void createServiceBarrel(const Bool_t innerBarrel, TGeoVolume* dest, const TGeoManager* mgr = gGeoManager); + + /// Sets the layer parameters + /// \param nlay layer number + /// \param phi0 layer phi0 + /// \param r layer radius + /// \param nstav number of staves + /// \param nunit IB: number of chips per stave + /// \param OB: number of modules per half stave + /// \param lthick stave thickness (if omitted, defaults to 0) + /// \param dthick detector thickness (if omitted, defaults to 0) + /// \param dettypeID ?? + /// \param buildLevel (if 0, all geometry is build, used for material budget studies) + void defineLayer(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod, Double_t lthick = 0., + Double_t dthick = 0., UInt_t detType = 0, Int_t buildFlag = 0) override; + + /// Sets the layer parameters for a "turbo" layer + /// (i.e. a layer whose staves overlap in phi) + /// \param nlay layer number + /// \param phi0 phi of 1st stave + /// \param r layer radius + /// \param nstav number of staves + /// \param nunit IB: number of chips per stave + /// \param OB: number of modules per half stave + /// \param width stave width + /// \param tilt layer tilt angle (degrees) + /// \param lthick stave thickness (if omitted, defaults to 0) + /// \param dthick detector thickness (if omitted, defaults to 0) + /// \param dettypeID ?? + /// \param buildLevel (if 0, all geometry is build, used for material budget studies) + // void defineLayerTurbo(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod, Double_t width, Double_t tilt, + // Double_t lthick = 0., Double_t dthick = 0., UInt_t detType = 0, Int_t buildFlag = 0) override; + + /// Sets the layer parameters for new ITS4 geo + /// \param nlay layer number + /// \param r layer radius + /// \param zlen layer length + /// \param dthick detector thickness (if omitted, defaults to 0) + /// \param dettypeID ?? + /// \param buildLevel (if 0, all geometry is build, used for material budget studies) + void defineInnerLayerITS4(Int_t nlay, Double_t r, Double_t zlen, + Double_t dthick = 0., UInt_t detType = 0, Int_t buildFlag = 0); + + /// Gets the layer parameters + /// \param nlay layer number + /// \param phi0 phi of 1st stave + /// \param r layer radius + /// \param nstav number of staves + /// \param nmod IB: number of chips per stave + /// \param OB: number of modules per half stave + /// \param width stave width + /// \param tilt stave tilt angle + /// \param lthick stave thickness + /// \param dthick detector thickness + /// \param dettype detector type + virtual void getLayerParameters(Int_t nlay, Double_t& phi0, Double_t& r, Int_t& nladd, Int_t& nmod, Double_t& width, + Double_t& tilt, Double_t& lthick, Double_t& mthick, UInt_t& dettype) const; + + /// This method is an example of how to add your own point of type Hit to the clones array + o2::itsmft::Hit* addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos, + const TVector3& startMom, double startE, double endTime, double eLoss, + unsigned char startStatus, unsigned char endStatus); + + /// Set per wrapper volume parameters + void defineWrapperVolume(Int_t id, Double_t rmin, Double_t rmax, Double_t zspan) override; + + /// Add alignable top volumes + void addAlignableVolumes() const override; + + /// Add alignable Layer volumes + /// \param lr layer number + /// \param parent path of the parent volume + /// \param lastUID on output, UID of the last volume + void addAlignableVolumesLayer(Int_t lr, TString& parent, Int_t& lastUID) const; + + /// Add alignable Stave volumes + /// \param lr layer number + /// \param st stave number + /// \param parent path of the parent volume + /// \param lastUID on output, UID of the last volume + void addAlignableVolumesStave(Int_t lr, Int_t st, TString& parent, Int_t& lastUID) const; + + /// Add alignable HalfStave volumes + /// \param lr layer number + /// \param st stave number + /// \param hst half stave number + /// \param parent path of the parent volume + /// \param lastUID on output, UID of the last volume + void addAlignableVolumesHalfStave(Int_t lr, Int_t st, Int_t hst, TString& parent, Int_t& lastUID) const; + + /// Add alignable Module volumes + /// \param lr layer number + /// \param st stave number + /// \param hst half stave number + /// \param md module number + /// \param parent path of the parent volume + /// \param lastUID on output, UID of the last volume + void addAlignableVolumesModule(Int_t lr, Int_t st, Int_t hst, Int_t md, TString& parent, Int_t& lastUID) const; + + /// Add alignable Chip volumes + /// \param lr layer number + /// \param st stave number + /// \param hst half stave number + /// \param md module number + /// \param ch chip number + /// \param parent path of the parent volume + /// \param lastUID on output, UID of the last volume + void addAlignableVolumesChip(Int_t lr, Int_t st, Int_t hst, Int_t md, Int_t ch, TString& parent, + Int_t& lastUID) const; + + /// Return Chip Volume UID + /// \param id volume id + Int_t chipVolUID(Int_t id) const { return o2::base::GeometryManager::getSensID(o2::detectors::DetID::IT4, id); } + + void EndOfEvent() override; + + void FinishPrimary() override { ; } + virtual void finishRun() { ; } + void BeginPrimary() override { ; } + void PostTrack() override { ; } + void PreTrack() override { ; } + /// Prints out the content of this class in ASCII format + /// \param ostream *os The output stream + void Print(std::ostream* os) const; + + /// Reads in the content of this class in the format of Print + /// \param istream *is The input stream + void Read(std::istream* is); + + /// Returns the number of layers + Int_t getNumberOfLayers() const { return sNumberLayers; } + virtual void setStaveModelIB(Model model) { mStaveModelInnerBarrel = model; } + virtual void setStaveModelOB(Model model) { mStaveModelOuterBarrel = model; } + virtual Model getStaveModelIB() const { return mStaveModelInnerBarrel; } + virtual Model getStaveModelOB() const { return mStaveModelOuterBarrel; } + + void createOuterBarrel(const Bool_t ob) { mCreateOuterBarrel = ob; }; + Bool_t isCreateOuterBarrel() { return mCreateOuterBarrel; }; + + o2::its4::GeometryTGeo* mGeometryTGeo; //! access to geometry details + + protected: + Int_t* mLayerID; //! [sNumberLayers] layer identifier + TString* mLayerName; //! [sNumberLayers] layer identifier + + private: + /// this is transient data about track passing the sensor + struct TrackData { // this is transient + bool mHitStarted; //! hit creation started + unsigned char mTrkStatusStart; //! track status flag + TLorentzVector mPositionStart; //! position at entrance + TLorentzVector mMomentumStart; //! momentum + double mEnergyLoss; //! energy loss + } mTrackData; //! + + Int_t mNumberOfInnerLayers; //! number of ITS4 inner layers + Int_t mTotalNumberOfLayers; //! total number of ITS4 layers (IB+OB) + Bool_t mCreateOuterBarrel; //! true to create the Outer Barrel + + Int_t mNumberOfDetectors; + + Bool_t mModifyGeometry; + + Double_t mWrapperMinRadius[sNumberOfWrapperVolumes]; //! Min radius of wrapper volume + Double_t mWrapperMaxRadius[sNumberOfWrapperVolumes]; //! Max radius of wrapper volume + Double_t mWrapperZSpan[sNumberOfWrapperVolumes]; //! Z span of wrapper volume + Int_t* mWrapperLayerId; //! Id of wrapper layer to which layer belongs (-1 if not wrapped) + + Bool_t* mTurboLayer; //! True for "turbo" layers + Bool_t* mITS4Layer; //! True for new ITS4 layers + Double_t* mLayerPhi0; //! Vector of layer's 1st stave phi in lab + Double_t* mLayerRadii; //! Vector of layer radii + Double_t* mLayerZLen; //! Vector of layer lengths + Int_t* mStavePerLayer; //! Vector of number of staves per layer + Int_t* mUnitPerStave; //! Vector of number of "units" per stave + Double_t* mChipThickness; //! Vector of chip thicknesses + Double_t* mStaveWidth; //! Vector of stave width (only used for turbo) + Double_t* mStaveTilt; //! Vector of stave tilt (only used for turbo) + Double_t* mDetectorThickness; //! Vector of detector thicknesses + UInt_t* mChipTypeID; //! Vector of detector type id + Int_t* mBuildLevel; //! Vector of Material Budget Studies + + /// Container for hit data + std::vector<o2::itsmft::Hit>* mHits; + + /// We need this as a method to access members + void configITS(Detector* its); + + /// Creates all needed arrays + void createAllArrays(); + + /// Creates an air-filled wrapper cylindrical volume + TGeoVolume* createWrapperVolume(const Int_t nLay); + + /// Create the detector materials + virtual void createMaterials(); + + /// Construct the detector geometry + void constructDetectorGeometry(); + + /// Define the sensitive volumes of the geometry + void defineSensitiveVolumes(); + + /// Creates the Inner Barrel Services + /// \param motherVolume the TGeoVolume owing the volume structure + void createInnerBarrelServices(TGeoVolume* motherVolume); + + /// Creates the Middle Barrel Services + /// \param motherVolume the TGeoVolume owing the volume structure + void createMiddlBarrelServices(TGeoVolume* motherVolume); + + /// Creates the Outer Barrel Services + /// \param motherVolume the TGeoVolume owing the volume structure + void createOuterBarrelServices(TGeoVolume* motherVolume); + + /// Creates the Outer Barrel Supports + /// \param motherVolume the TGeoVolume owing the volume supports + void createOuterBarrelSupports(TGeoVolume* motherVolume); + + Detector(const Detector&); + + Detector& operator=(const Detector&); + + Model mStaveModelInnerBarrel; //! The stave model for the Inner Barrel + Model mStaveModelOuterBarrel; //! The stave model for the Outer Barrel + V3Layer** mGeometry; //! Geometry + V3Services* mServicesGeometry; //! Services Geometry + + template <typename Det> + friend class o2::base::DetImpl; + ClassDefOverride(Detector, 1); +}; + +// Input and output function for standard C++ input/output. +std::ostream& operator<<(std::ostream& os, Detector& source); + +std::istream& operator>>(std::istream& os, Detector& source); +} // namespace its4 +} // namespace o2 + +#ifdef USESHM +namespace o2 +{ +namespace base +{ +template <> +struct UseShm<o2::its4::Detector> { + static constexpr bool value = true; +}; +} // namespace base +} // namespace o2 +#endif + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V11Geometry.h b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V11Geometry.h new file mode 100644 index 0000000000000..e008c9bffd505 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V11Geometry.h @@ -0,0 +1,458 @@ +// 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 V11Geometry.h +/// \brief Definition of the V11Geometry class + +#ifndef ALICEO2_ITS4_V11GEOMETRY_H_ +#define ALICEO2_ITS4_V11GEOMETRY_H_ + +#include <TMath.h> // for DegToRad, Cos, Sin, Tan +#include <TObject.h> // for TObject +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, V11Geometry::Class, etc + +class TGeoArb8; // lines 11-11 +class TGeoBBox; // lines 16-16 +class TGeoConeSeg; // lines 15-15 +class TGeoPcon; // lines 12-12 +class TGeoTube; // lines 13-13 +class TGeoTubeSeg; // lines 14-14 + +namespace o2 +{ +namespace its4 +{ + +/// This class is a base class for the ITS geometry version 11. It contains common/standard +/// functions used in many places in defining the ITS geometry, version 11. Large posions of +/// the ITS geometry, version 11, should be derived from this class so as to make maximum +/// use of these common functions. This class also defines the proper conversion values such, +/// to cm and degrees, such that the most useful units, those used in the Engineering drawings, +/// can be used. +class V11Geometry : public TObject +{ + + public: + V11Geometry() : mDebug(){}; + + V11Geometry(Int_t debug) : mDebug(debug){}; + + ~V11Geometry() + override = default; + + /// Sets the debug flag for debugging output + void setDebug(Int_t level = 5) + { + mDebug = level; + } + + /// Clears the debug flag so no debugging output will be generated + void setNoDebug() + { + mDebug = 0; + } + + /// Returns the debug flag value + Bool_t getDebug(Int_t level = 1) const + { + return mDebug >= level; + } + + // Static functions + + /// Define Trig functions for use with degrees (standerd TGeo angles). + /// Sine function + Double_t sinD(Double_t deg) const + { + return TMath::Sin(deg * TMath::DegToRad()); + } + + /// Cosine function + Double_t cosD(Double_t deg) const + { + return TMath::Cos(deg * TMath::DegToRad()); + } + + /// Tangent function + Double_t tanD(Double_t deg) const + { + return TMath::Tan(deg * TMath::DegToRad()); + } + + /// Determine the intersection of two lines + /// Given the two lines, one passing by (x0,y0) with slope m and + /// the other passing by (x1,y1) with slope n, returns the coordinates + /// of the intersecting point (xi,yi) + /// \param Double_t m The slope of the first line + /// \param Double_t x0,y0 The x and y coord. of the first point + /// \param Double_t n The slope of the second line + /// \param Double_t x1,y1 The x and y coord. of the second point + /// As an output it gives the coordinates xi and yi of the intersection point + void intersectLines(Double_t m, Double_t x0, Double_t y0, Double_t n, Double_t x1, Double_t y1, Double_t& xi, + Double_t& yi) const; + + /// Determine the intersection of a line and a circle + /// Given a line passing by (x0,y0) with slope m and a circle with + /// radius rr and center (xc,yc), returns the coordinates of the + /// intersecting points (xi1,yi1) and (xi2,yi2) (xi1 > xi2) + /// \param Double_t m The slope of the line + /// \param Double_t x0,y0 The x and y coord. of the point + /// \param Double_t rr The radius of the circle + /// \param Double_t xc,yc The x and y coord. of the center of circle + /// As an output it gives the coordinates xi and yi of the intersection points + /// Returns kFALSE if the line does not intercept the circle, otherwise kTRUE + static Bool_t intersectCircle(Double_t m, Double_t x0, Double_t y0, Double_t rr, Double_t xc, Double_t yc, + Double_t& xi1, Double_t& yi1, Double_t& xi2, Double_t& yi2); + + /// Given the two points (x0,y0) and (x1,y1) and the location x, returns + /// the value y corresponding to that point x on the line defined by the + /// two points. Returns the value y corresponding to the point x on the line defined by + /// the two points (x0,y0) and (x1,y1). + /// \param Double_t x0 The first x value defining the line + /// \param Double_t y0 The first y value defining the line + /// \param Double_t x1 The second x value defining the line + /// \param Double_t y1 The second y value defining the line + /// \param Double_t x The x value for which the y value is wanted. + Double_t yFrom2Points(Double_t x0, Double_t y0, Double_t x1, Double_t y1, Double_t x) const; + + /// Given the two points (x0,y0) and (x1,y1) and the location y, returns + /// the value x corresponding to that point y on the line defined by the + /// two points. Returns the value x corresponding to the point y on the line defined by + /// the two points (x0,y0) and (x1,y1). + /// \param Double_t x0 The first x value defining the line + /// \param Double_t y0 The first y value defining the line + /// \param Double_t x1 The second x value defining the line + /// \param Double_t y1 The second y value defining the line + /// \param Double_t y The y value for which the x value is wanted. + Double_t xFrom2Points(Double_t x0, Double_t y0, Double_t x1, Double_t y1, Double_t y) const; + + /// Functions require at parts of Volume A to be already defined. + /// Returns the value of Rmax corresponding to point z alone the line + /// defined by the two points p.Rmax(i1),p-GetZ(i1) and p->GetRmax(i2), + /// p->GetZ(i2). + /// \param TGeoPcon *p The Polycone where the two points come from + /// \param Int_t i1 Point 1 + /// \param Int_t i2 Point 2 + /// \param Double_t z The value of z for which Rmax is to be found + /// \param Double_t Rmx the value corresponding to z + Double_t rMaxFrom2Points(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t z) const; + + /// Returns the value of Rmin corresponding to point z alone the line + /// defined by the two points p->GetRmin(i1),p->GetZ(i1) and + /// p->GetRmin(i2), p->GetZ(i2). + /// \param TGeoPcon *p The Polycone where the two points come from + /// \param Int_t i1 Point 1 + /// \param Int_t i2 Point 2 + /// \param Double_t z The value of z for which Rmax is to be found + /// \param Double_t Rmx the value corresponding to z + Double_t rMinFrom2Points(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t z) const; + + /// Returns the value of Rmin corresponding to point z alone the line + /// defined by the two points p->GetRmin(i1),p->GetZ(i1) and + /// p->GetRmin(i2), p->GetZ(i2). Returns the value r corresponding to z and the + /// line defined by the two points + /// \param Double_t az Array of z values + /// \param Double_t r Array of r values + /// \param Int_t i1 First Point in arrays + /// \param Int_t i2 Second Point in arrays + /// \param Double_t z Value z at which r is to be found + Double_t rFrom2Points(const Double_t* ar, const Double_t* az, Int_t i1, Int_t i2, Double_t z) const; + + /// Returns the value of Z corresponding to point R alone the line + /// defined by the two points p->GetRmin(i1),p->GetZ(i1) and + /// p->GetRmin(i2),p->GetZ(i2). Returns the value z corresponding to r min + /// and the line defined by the two points + /// \param TGeoPcon *p The Poly cone where the two points come from. + /// \param Int_t i1 First Point in arrays + /// \param Int_t i2 Second Point in arrays + /// \param Double_t r Value r min at which z is to be found + Double_t zFrom2MinPoints(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t r) const; + + /// Returns the value of Z corresponding to point R alone the line + /// defined by the two points p->GetRmax(i1),p->GetZ(i1) and + /// p->GetRmax(i2),p->GetZ(i2). Returns the value z corresponding to + /// r max and the line defined by the two points + /// \param TGeoPcon *p The Poly cone where the two points come from. + /// \param Int_t i1 First Point in arrays + /// \param Int_t i2 Second Point in arrays + /// \param Double_t r Value r max at which z is to be found + Double_t zFrom2MaxPoints(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t r) const; + + /// Returns the value of z corresponding to point R alone the line + /// defined by the two points p->GetRmax(i1),p->GetZ(i1) and + /// p->GetRmax(i2),p->GetZ(i2). Returns the value z corresponding to r + /// and the line defined by the two points + /// \param Double_t z Array of z values + /// \param Double_t ar Array of r values + /// \param Int_t i1 First Point in arrays + /// \param Int_t i2 Second Point in arrays + /// \param Double_t r Value r at which z is to be found + Double_t zFrom2Points(const Double_t* az, const Double_t* ar, Int_t i1, Int_t i2, Double_t r) const; + + /// General Outer Cone surface equation Rmax + /// Given 1 point from a TGeoPcon(z and Rmax) the angle tc returns r for + /// a given z, an offset (distnace perpendicular to line at angle tc) of + /// th may be applied. Returns the value Rmax corresponding to the line at angle th, offset by + /// th, and the point p->GetZ/Rmin[ip] at the location z. + /// \param TGeoPcon *p The poly cone where the initial point comes from + /// \param Int_t ip The index in p to get the point location + /// \param Double_t tc The angle of that part of the cone is at + /// \param Double_t z The value of z to compute Rmax from + /// \param Double_t th The perpendicular distance the parralell line is from the point ip + Double_t rMaxFromZpCone(const TGeoPcon* p, int ip, Double_t tc, Double_t z, Double_t th = 0.0) const; + + // General Cone surface equation R(z). Returns the value R correstponding to the line at + // angle th, offset by th, and the point p->GetZ/Rmax[ip] at the location z. + // \param Double_t ar The array of R values + // \param Double_t az The array of Z values + // \param Int_t ip The index in p to get the point location + // \param Double_t tc The angle of that part of the cone is at + // \param Double_t z The value of z to compute R from + // \param Double_t th The perpendicular distance the parralell line is from the point ip + Double_t rFromZpCone(const Double_t* ar, const Double_t* az, int ip, Double_t tc, Double_t z, + Double_t th = 0.0) const; + + /// General Inner Cone surface equation Rmin. + /// Given 1 point from a TGeoPcon(z and Rmin) the angle tc returns r for + /// a given z, an offset (distnace perpendicular to line at angle tc) of + /// th may be applied. Returns the value Rmin correstponding to the line at angle th, + /// offset by th, and the point p->GetZ/Rmin[ip] at the location z. + /// \param TGeoPcon *p The poly cone where the initial point comes from + /// \param Int_t ip The index in p to get the point location + /// \param Double_t tc The angle of that part of the cone is at + /// \param Double_t z The value of z to compute Rmin from + /// \param Double_t th The perpendicular distance the parralell line is from the point ip + Double_t rMinFromZpCone(const TGeoPcon* p, Int_t ip, Double_t tc, Double_t z, Double_t th = 0.0) const; + + /// General Outer cone Surface equation for z. + /// Given 1 point from a TGeoPcon(z and Rmax) the angle tc returns z for + /// a given Rmax, an offset (distnace perpendicular to line at angle tc) of + /// th may be applied. Returns thevalue Z correstponding to the line at angle th, + /// offset by th, and the point p->GetZ/Rmax[ip] at the location r. + /// \param TGeoPcon *p The poly cone where the initial point comes from + /// \param Int_t ip The index in p to get the point location + /// \param Double_t tc The angle of that part of the cone is at + /// \param Double_t r The value of Rmax to compute z from + /// \param Double_t th The perpendicular distance the parralell line is from the point ip + Double_t zFromRMaxpCone(const TGeoPcon* p, int ip, Double_t tc, Double_t r, Double_t th = 0.0) const; + + /// General Outer cone Surface equation for z. + /// Returns the value Z correstponding to the line at angle th, offeset by + /// th, and the point p->GetZ/Rmax[ip] at the locatin r. + /// \param Double_t ar The array of R values + /// \param Double_t az The array of Z values + /// \param Int_t ip The index in p to get the point location + /// \param Double_t tc The angle of that part of the cone is at + /// \param Double_t r The value of Rmax to compute z from + /// \param Double_t th The perpendicular distance the parralell line is from the point ip + Double_t zFromRMaxpCone(const Double_t* ar, const Double_t* az, Int_t ip, Double_t tc, Double_t r, + Double_t th = 0.0) const; + + /// General Inner cone Surface equation for z. + /// Given 1 point from a TGeoPcon(z and Rmin) the angle tc returns z for + /// a given Rmin, an offset (distnace perpendicular to line at angle tc) of + /// th may be applied. Returns the value Z correstponding to the line at angle th, offeset by + /// th, and the point p->GetZ/Rmin[ip] at the location r. + /// \param TGeoPcon *p The poly cone where the initial point comes from + /// \param Int_t ip The index in p to get the point location + /// \param Double_t tc The angle of that part of the cone is at + /// \param Double_t r The value of Rmin to compute z from + /// \param Double_t th The perpendicular distance the parralell line is from the point ip + Double_t zFromRMinpCone(const TGeoPcon* p, int ip, Double_t tc, Double_t r, Double_t th = 0.0) const; + + /// Given two lines defined by the points i1, i2,i3 in the TGeoPcon + /// class p that intersect at point p->GetZ(i2) return the point z,r + /// that is Cthick away in the TGeoPcon class q. If points i1=i2 + /// and max == kTRUE, then p->GetRmin(i1) and p->GetRmax(i2) are used. + /// if points i2=i3 and max=kTRUE then points p->GetRmax(i2) and + /// p->GetRmin(i3) are used. If i2=i3 and max=kFALSE, then p->GetRmin(i2) + /// and p->GetRmax(i3) are used. + /// \param TGeoPcon *p Class where points i1, i2, and i3 are taken from + /// \param Int_t i1 First point in class p + /// \param Int_t i2 Second point in class p + /// \param Int_t i3 Third point in class p + /// \param Double_t c Distance inside the outer/inner surface that the point j1 + /// is to be computed for + /// \param TGeoPcon *q Pointer to class for results to be put into. + /// \param Int_t j1 Point in class q where data is to be stored. + /// \param Bool_t ma if kTRUE, then a Rmax value is computed, else a Rmin valule is computed + /// \param TGeoPcon *q Pointer to class for results to be put into. + void insidePoint(const TGeoPcon* p, Int_t i1, Int_t i2, Int_t i3, Double_t Cthick, TGeoPcon* q, Int_t j1, + Bool_t max) const; + + /// Given two intersecting lines defined by the points (x0,y0), (x1,y1) and + /// (x1,y1), (x2,y2) {intersecting at (x1,y1)} the point (x,y) a distance + /// c away is returned such that two lines a distance c away from the + /// lines defined above intersect at (x,y). + /// \param Double_t x0 X point on the first intersecting sets of lines + /// \param Double_t y0 Y point on the first intersecting sets of lines + /// \param Double_t x1 X point on the first/second intersecting sets of lines + /// \param Double_t y1 Y point on the first/second intersecting sets of lines + /// \param Double_t x2 X point on the second intersecting sets of lines + /// \param Double_t y2 Y point on the second intersecting sets of lines + /// \param Double_t c Distance the two sets of lines are from each other + /// \param Double_t x X point for the intersecting sets of parellel lines + /// \param Double_t y Y point for the intersecting sets of parellel lines + void insidePoint(Double_t x0, Double_t y0, Double_t x1, Double_t y1, Double_t x2, Double_t y2, Double_t c, + Double_t& x, Double_t& y) const; + + /// Given an initial point z0,r0, the initial angle theta0, and the radius + /// of curvature, returns the point z1, r1 at the angle theta1. Theta + /// measured from the r axis in the clock wise direction [degrees]. + /// \param Double_t rc The radius of curvature + /// \param Double_t theta0 The starting angle (degrees) + /// \param Double_t z0 The value of z at theta0 + /// \param Double_t r0 The value of r at theta0 + /// \param Double_t theta1 The ending angle (degrees) + /// \param Double_t &z1 The value of z at theta1 + /// \param Double_t &r1 The value of r at theta1 + void radiusOfCurvature(Double_t rc, Double_t theta0, Double_t z0, Double_t r0, Double_t theta1, Double_t& z1, + Double_t& r1) const; + + // Output functions for debugging + + /// Prints out the content of the TGeoArb8 + /// \param TGeoArb8 *a + void printArb8(const TGeoArb8* a) const; + + /// Prints out the contents of the TGeoPcon + /// \param TGeoPcon *a + void printPcon(const TGeoPcon* a) const; + + /// Prints out the contents of the TGeoTube + /// \param TGeoTube *a + void printTube(const TGeoTube* a) const; + + /// Prints out the contents of the TGeoTubeSeg + /// \param TGeoTubeSeg *a + void printTubeSeg(const TGeoTubeSeg* a) const; + + /// Prints out the contents of the TGeoConeSeg + /// \param TGeoConeSeg *a + void printConeSeg(const TGeoConeSeg* a) const; + + /// Prints out the contents of the TGeoBBox + /// \param TGeoBBox *a + void printBBox(const TGeoBBox* a) const; + + /// Draws a cross sectional view of the TGeoPcon, Primarily for debugging. + /// A TCanvas should exist first. + /// \param TGeoPcon *p The TGeoPcon to be "drawn" + /// \param Int_t fillc The fill color to be used + /// \param Int_t fills The fill style to be used + /// \param Int_t linec The line color to be used + /// \param Int_t lines The line style to be used + /// \param Int_t linew The line width to be used + /// \param Int_t markc The markder color to be used + /// \param Int_t marks The markder style to be used + /// \param Float_t marksize The marker size + void drawCrossSection(const TGeoPcon* p, Int_t fillc = 7, Int_t fills = 4050, Int_t linec = 3, Int_t lines = 1, + Int_t linew = 4, Int_t markc = 2, Int_t marks = 4, Float_t marksize = 1.0) const; + + /// Computes the angles, t0 and t1 corresponding to the intersection of + /// the line, defined by {x0,y0} {x1,y1}, and the circle, defined by + /// its center {xc,yc} and radius r. If the line does not intersect the + /// line, function returns kFALSE, otherwise it returns kTRUE. If the + /// line is tangent to the circle, the angles t0 and t1 will be the same. + /// Returns kTRUE if line intersects circle or kFALSE if line does not intersect circle + /// or the line is not properly defined point {x0,y0} and {x1,y1} are the same point. + /// \param Double_t x0 X of first point defining the line + /// \param Double_t y0 Y of first point defining the line + /// \param Double_t x1 X of Second point defining the line + /// \param Double_t y1 Y of Second point defining the line + /// \param Double_t xc X of Circle center point defining the line + /// \param Double_t yc Y of Circle center point defining the line + /// \param Double_t r radius of circle + /// \param Double_t &t0 First angle where line intersects circle + /// \param Double_t &t1 Second angle where line intersects circle + Bool_t angleOfIntersectionWithLine(Double_t x0, Double_t y0, Double_t x1, Double_t y1, Double_t xc, Double_t yc, + Double_t rc, Double_t& t0, Double_t& t1) const; + + /// Function to compute the ending angle, for arc 0, and starting angle, + /// for arc 1, such that a straight line will connect them with no discontinuities. + /// Begin_Html + /* + <img src="picts/ITS/V11Geometry_AnglesForRoundedCorners.gif"> + */ + // End_Html + /// \param Double_t x0 X Coordinate of arc 0 center. + /// \param Double_t y0 Y Coordinate of arc 0 center. + /// \param Double_t r0 Radius of curvature of arc 0. For signe see figure. + /// \param Double_t x1 X Coordinate of arc 1 center. + /// \param Double_t y1 Y Coordinate of arc 1 center. + /// \param Double_t r1 Radius of curvature of arc 1. For signe see figure. + /// \param Double_t t0 Ending angle of arch 0, with respect to x axis, Degrees. + /// \param Double_t t1 Starting angle of arch 1, with respect to x axis, Degrees. + void anglesForRoundedCorners(Double_t x0, Double_t y0, Double_t r0, Double_t x1, Double_t y1, Double_t r1, + Double_t& t0, Double_t& t1) const; + + /// Define a general createMaterials function here so that if + /// any specific subdetector does not define it this null function + /// will due. This function is not declaired const so that a sub- + /// detector's version may use class variables if they wish. + /// Defined media here should correspond to the one defined in galice.cuts + /// File which is red in (AliMC*) fMCApp::Init() { ReadTransPar(); } + void createDefaultMaterials(); + + virtual void createMaterials(){}; + + /// Function to create the figure describing how the function + /// anglesForRoundedCorners works. + /// \param Double_t x0 X Coordinate of arc 0 center. + /// \param Double_t y0 Y Coordinate of arc 0 center. + /// \param Double_t r0 Radius of curvature of arc 0. For signe see figure. + /// \param Double_t x1 X Coordinate of arc 1 center. + /// \param Double_t y1 Y Coordinate of arc 1 center. + /// \param Double_t r1 Radius of curvature of arc 1. For signe see figure. + void makeFigure1(Double_t x0 = 0.0, Double_t y0 = 0.0, Double_t r0 = 2.0, Double_t x1 = -4.0, Double_t y1 = -2.0, + Double_t r1 = 1.0); + + protected: + // Units, Convert from k?? to cm,degree,GeV,seconds, + static const Double_t sMicron; ///< Convert micron to TGeom's cm. + static const Double_t sMm; ///< Convert mm to TGeom's cm. + static const Double_t sCm; ///< Convert cm to TGeom's cm. + static const Double_t sDegree; ///< Convert degrees to TGeom's degrees + static const Double_t sRadian; ///< To Radians + static const Double_t sGCm3; ///< Density in g/cm^3 + static const Double_t sKgm3; ///< Density in kg/m^3 + static const Double_t sKgdm3; ///< Density in kg/dm^3 + static const Double_t sCelsius; ///< Temperature in degrees Celcius + static const Double_t sPascal; ///< Preasure in Pascal + static const Double_t sKPascal; ///< Preasure in KPascal + static const Double_t sEV; ///< Energy in eV + static const Double_t sKEV; ///< Energy in KeV + static const Double_t sMEV; ///< Energy in MeV + static const Double_t sGEV; ///< Energy in GeV + + private: + /// Basic function used to determine the ending angle and starting angles + /// for rounded corners given the relative distance between the centers + /// of the circles and the difference/sum of their radii. Case 0. Returns the angle in Degrees + /// \param Double_t dx difference in x locations of the circle centers + /// \param Double_t dy difference in y locations of the circle centers + /// \param Double_t sdr difference or sum of the circle radii + Double_t angleForRoundedCorners0(Double_t dx, Double_t dy, Double_t sdr) const; + + /// Basic function used to determine the ending angle and starting angles + /// for rounded corners given the relative distance between the centers + /// of the circles and the difference/sum of their radii. Case 0. Returns the angle in Degrees + /// \param Double_t dx difference in x locations of the circle centers + /// \param Double_t dy difference in y locations of the circle centers + /// \param Double_t sdr difference or sum of the circle radii + Double_t angleForRoundedCorners1(Double_t dx, Double_t dy, Double_t sdr) const; + + Int_t mDebug; //! Debug flag/level + ClassDefOverride(V11Geometry, 1); // Base class for ITS v11 geometry +}; +} // namespace its4 +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V1Layer.h b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V1Layer.h new file mode 100644 index 0000000000000..33e5e46ea0856 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V1Layer.h @@ -0,0 +1,415 @@ +// 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_ITS4_UPGRADEV1LAYER_H_ +#define ALICEO2_ITS4_UPGRADEV1LAYER_H_ + +#include <TGeoManager.h> // for gGeoManager +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc +#include "ITS4Simulation/V11Geometry.h" // for V11Geometry +#include "ITS4Simulation/Detector.h" // for Detector, Detector::Model + +class TGeoArb8; + +class TGeoCombiTrans; + +class TGeoVolume; // lines 15-15 + +namespace o2 +{ +namespace its4 +{ + +/// This class defines the Geometry for the ITS using TGeo. This is a work class used +/// to study different configurations during the development of the new ITS structure +class V1Layer : public V11Geometry +{ + + public: + enum { + kStave, + kHalfStave, + kModule, + kChip, + kNHLevels + }; + + // Default constructor + V1Layer(); + + // Constructor setting debugging level + V1Layer(Int_t debug); + + // Constructor setting layer number and debugging level + V1Layer(Int_t lay, Int_t debug); + + /// Constructor setting layer number and debugging level + /// for a "turbo" layer (i.e. where staves overlap in phi) + V1Layer(Int_t lay, Bool_t turbo, Int_t debug); + + /// Copy constructor + V1Layer(const V1Layer& source); + + /// Assignment operator + V1Layer& operator=(const V1Layer& source); + + /// Default destructor + ~V1Layer() override; + + Bool_t isTurbo() const + { + return mIsTurbo; + }; + + Double_t getStaveThick() const + { + return mStaveThickness; + }; + + Double_t getStaveTilt() const + { + return mStaveTilt; + }; + + Double_t getStaveWidth() const + { + return mStaveWidth; + }; + + Double_t getSensorThick() const + { + return mSensorThickness; + }; + + Double_t getNumberOfStaves() const + { + return mNumberOfStaves; + }; + + Double_t getNumberOfChips() const + { + return mNumberOfChips; + }; + + Double_t getRadius() const + { + return mLayerRadius; + }; + + Double_t getPhi0() const + { + return mPhi0; + }; + + Double_t getZLength() const + { + return mZLength; + }; + + Int_t getChipType() const + { + return mChipTypeID; + } + + Int_t getNumberOfStavesPerParent() const + { + return mHierarchy[kStave]; + } + + Int_t getNumberOfHalfStavesPerParent() const + { + return mHierarchy[kHalfStave]; + } + + Int_t getNumberOfModulesPerParent() const + { + return mHierarchy[kModule]; + } + + Int_t getNumberOfChipsPerParent() const + { + return mHierarchy[kChip]; + } + + Detector::Model getStaveModel() const + { + return mStaveModel; + } + + void setStaveThick(Double_t t) + { + mStaveThickness = t; + }; + + /// Sets the Stave tilt angle (for turbo layers only) + /// \param t The stave tilt angle + void setStaveTilt(Double_t t); + + /// Sets the Stave width (for turbo layers only) + /// \param w The stave width + void setStaveWidth(Double_t w); + + void setSensorThick(Double_t t) + { + mSensorThickness = t; + }; + + void setNumberOfStaves(Int_t n) + { + mHierarchy[kStave] = mNumberOfStaves = n; + }; + + /// Sets the number of units in a stave: + /// for the Inner Barrel: the number of chips per stave + /// for the Outer Barrel: the number of modules per half stave + /// \param u the number of units + void setNumberOfUnits(Int_t u); + + void setRadius(Double_t r) + { + mLayerRadius = r; + }; + + void setPhi0(Double_t phi) + { + mPhi0 = phi; + } + + void setZLength(Double_t z) + { + mZLength = z; + }; + + void setChipType(Int_t tp) + { + mChipTypeID = tp; + } + + void setBuildLevel(Int_t buildLevel) + { + mBuildLevel = buildLevel; + } + + void setStaveModel(o2::its4::Detector::Model model) + { + mStaveModel = model; + } + + /// Creates the actual Layer and places inside its mother volume + /// \param motherVolume the TGeoVolume owing the volume structure + virtual void createLayer(TGeoVolume* motherVolume); + + private: + /// Creates the actual Layer and places inside its mother volume + /// A so-called "turbo" layer is a layer where staves overlap in phi + /// User can set width and tilt angle, no check is performed here + /// to avoid volume overlaps + /// \param motherVolume The TGeoVolume owing the volume structure + void createLayerTurbo(TGeoVolume* motherVolume); + + /// Computes the inner radius of the air container for the Turbo configuration + /// as the radius of either the circle tangent to the stave or the circle + /// passing for the stave's lower vertex. Returns the radius of the container + /// if >0, else flag to use the lower vertex + Double_t radiusOmTurboContainer(); + + /// Creates the actual Stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStave(const TGeoManager* mgr = gGeoManager); + + // TGeoVolume* createChip(Double_t x, Double_t z, const TGeoManager *mgr=gGeoManager); + + /// Creates the IB Module: (only the chips for the time being) + /// Returns the module as a TGeoVolume + /// \param xmod, ymod, zmod X, Y, Z module half lengths + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createModuleInnerB(Double_t x, Double_t y, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Creates the actual Chip + /// \param xchip,ychip,zchip The chip dimensions + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createChipInnerB(Double_t x, Double_t y, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Creates the OB Module: HIC + FPC + Carbon plate + /// Returns the module as a TGeoVolume + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createModuleOuterB(const TGeoManager* mgr = gGeoManager); + + /// Create the chip stave for the Inner Barrel(Here we fake the halfstave volume to have the + /// same formal geometry hierarchy as for the Outer Barrel) + /// \param xsta, ysta, zsta X, Y, Z stave half lengths + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveInnerB(Double_t x, Double_t y, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create the mechanical stave structure + /// \param xsta X length + /// \param zsta Z length + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveStructInnerB(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create a dummy stave + /// \param xsta X length + /// \param zsta Z length + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerBDummy(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager) const; + + /// Create the mechanical stave structure for Model 0 of TDR + /// \param xsta X length + /// \param zsta Z length + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerB0(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create the mechanical stave structure for Model 1 of TDR + /// \param xsta X length + /// \param zsta Z length + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerB1(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create the mechanical stave structure for Model 2.1 of TDR + /// \param xsta X length + /// \param zsta Z length + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerB21(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create the mechanical stave structure for Model 2.2 of TDR + /// \param xsta X length + /// \param zsta Z length + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerB22(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create the mechanical stave structure for Model 3 of TDR + /// \param xsta X length + /// \param zsta Z length + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerB3(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create the chip stave for the Outer Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveOuterB(const TGeoManager* mgr = gGeoManager); + + /// Create dummy stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelOuterBDummy(const TGeoManager* mgr = gGeoManager) const; + + /// Creation of the mechanical stave structure for the Outer Barrel as in v0 + /// (we fake the module and halfstave volumes to have always + /// the same formal geometry hierarchy) + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelOuterB0(const TGeoManager* mgr = gGeoManager); + + /// Create the mechanical half stave structure or the Outer Barrel as in TDR + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelOuterB1(const TGeoManager* mgr = gGeoManager); + + /// Create the space frame for the Outer Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createSpaceFrameOuterB(const TGeoManager* mgr = gGeoManager); + + /// Create dummy stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createSpaceFrameOuterBDummy(const TGeoManager* mgr = gGeoManager) const; + + /// Create the space frame for the Outer Barrel (Model 1) + /// Returns a TGeoVolume with the Space Frame of a stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createSpaceFrameOuterB1(const TGeoManager* mgr = gGeoManager); + + /// Creates the V-shaped sides of the OB space frame (from a similar method with same + /// name and function in V11GeometrySDD class by L.Gaudichet) + TGeoArb8* createStaveSide(const char* name, Double_t dz, Double_t angle, Double_t xSign, Double_t L, Double_t H, + Double_t l); + + /// Help method to create a TGeoCombiTrans matrix from a similar method with same name and + /// function in V11GeometrySDD class by L.Gaudichet) + /// Returns the TGeoCombiTrans which make a translation in y and z and a rotation in phi + /// in the global coord system. If planeSym = true, the rotation places the object + /// symetrically (with respect to the transverse plane) to its position in the + /// case planeSym = false + TGeoCombiTrans* createCombiTrans(const char* name, Double_t dy, Double_t dz, Double_t dphi, + Bool_t planeSym = kFALSE); + + /// Help method to add a translation to a TGeoCombiTrans matrix (from a similar method + /// with same name and function in V11GeometrySDD class by L.Gaudichet) + void addTranslationToCombiTrans(TGeoCombiTrans* ct, Double_t dx = 0, Double_t dy = 0, Double_t dz = 0) const; + + Int_t mLayerNumber; ///< Current layer number + Double_t mPhi0; ///< lab phi of 1st stave, in degrees!!! + Double_t mLayerRadius; ///< Inner radius of this layer + Double_t mZLength; ///< Z length of this layer + Double_t mSensorThickness; ///< Sensor thickness + Double_t mStaveThickness; ///< Stave thickness + Double_t mStaveWidth; ///< Stave width (for turbo layers only) + Double_t mStaveTilt; ///< Stave tilt angle (for turbo layers only) in degrees + Int_t mNumberOfStaves; ///< Number of staves in this layer + Int_t mNumberOfModules; ///< Number of modules per container if defined (HalfStave, Stave, whatever is + ///< container) + Int_t mNumberOfChips; ///< Number chips per container (module, HalfStave, Stave, whatever is + /// container) + Int_t mHierarchy[kNHLevels]; ///< array to query number of staves, hstaves, modules, chips per its parent volume + + UInt_t mChipTypeID; ///< detector type id + Bool_t mIsTurbo; ///< True if this layer is a "turbo" layer + Int_t mBuildLevel; ///< Used for material studies + + Detector::Model mStaveModel; ///< The stave model + + // Parameters for the geometry + + // General Parameters + static const Int_t sNumberOmInnerLayers; ///< Number of IB Layers + + static const Double_t sDefaultSensorThick; ///< Default sensor thickness + static const Double_t sDefaultStaveThick; ///< Default stave thickness + + // Inner Barrel Parameters + static const Int_t sIBChipsPerRow; ///< IB chips per row in module + static const Int_t sIBNChipRows; ///< IB chip rows in module + + // Outer Barrel Parameters + static const Int_t sOBChipsPerRow; ///< OB chips per row in module + static const Int_t sOBNChipRows; ///< OB chip rows in module + + static const Double_t sOBHalfStaveWidth; ///< OB Half Stave Width + static const Double_t sOBModuleWidth; ///< OB Module Width + static const Double_t sOBModuleGap; ///< Gap between OB modules + static const Double_t sOBChipXGap; ///< Gap between OB chips on X + static const Double_t sOBChipZGap; ///< Gap between OB chips on Z + static const Double_t sOBFlexCableAlThick; ///< Thickness of FPC Aluminum + static const Double_t sOBFlexCableKapThick; ///< Thickness of FPC Kapton + static const Double_t sOBBusCableAlThick; ///< Thickness of Bus Aluminum + static const Double_t sOBBusCableKapThick; ///< Thickness of Bus Kapton + static const Double_t sOBCarbonPlateThick; ///< OB Carbon Plate Thickness + static const Double_t sOBColdPlateThick; ///< OB Cold Plate Thickness + static const Double_t sOBGlueThick; ///< OB Glue total Thickness + static const Double_t sOBModuleZLength; ///< OB Chip Length along Z + static const Double_t sOBHalfStaveYTrans; ///< OB half staves Y transl. + static const Double_t sOBHalfStaveXOverlap; ///< OB half staves X overlap + static const Double_t sOBGraphiteFoilThick; ///< OB graphite foil thickness + static const Double_t sOBCoolTubeInnerD; ///< OB cooling inner diameter + static const Double_t sOBCoolTubeThick; ///< OB cooling tube thickness + static const Double_t sOBCoolTubeXDist; ///< OB cooling tube separation + + static const Double_t sOBSpaceFrameWidth; ///< OB Space Frame Width + static const Double_t sOBSpaceFrameTotHigh; ///< OB Total Y Height + static const Double_t sOBSFrameBeamRadius; ///< OB Space Frame Beam Radius + static const Double_t sOBSpaceFrameLa; ///< Parameters defining... + static const Double_t sOBSpaceFrameHa; ///< ...the V side shape... + static const Double_t sOBSpaceFrameLb; ///< ...of the carbon... + static const Double_t sOBSpaceFrameHb; ///< ...OB Space Frame + static const Double_t sOBSpaceFrameL; ///< OB SF + static const Double_t sOBSFBotBeamAngle; ///< OB SF bottom beam angle + static const Double_t sOBSFrameBeamSidePhi; ///< OB SF side beam angle + + ClassDefOverride(V1Layer, 0); // ITS v1 geometry +}; +} // namespace its4 +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Layer.h b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Layer.h new file mode 100644 index 0000000000000..c04160e8997ad --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Layer.h @@ -0,0 +1,570 @@ +// 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 V3Layer.h +/// \brief Definition of the V3Layer class +/// \author Mario Sitta <sitta@to.infn.it> +/// \author Chinorat Kobdaj (kobdaj@g.sut.ac.th) + +#ifndef ALICEO2_ITS4_UPGRADEV3LAYER_H_ +#define ALICEO2_ITS4_UPGRADEV3LAYER_H_ + +#include <TGeoManager.h> // for gGeoManager +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc +#include "ITS4Simulation/V11Geometry.h" // for V11Geometry +#include "ITS4Simulation/Detector.h" // for Detector, Detector::Model + +class TGeoXtru; + +class TGeoCombiTrans; + +class TGeoVolume; // lines 15-15 + +namespace o2 +{ +namespace its4 +{ + +/// This class defines the Geometry for the ITS using TGeo. This is a work class used +/// to study different configurations during the development of the new ITS structure +class V3Layer : public V11Geometry +{ + + public: + enum { kStave, + kHalfStave, + kModule, + kChip, + kNHLevels }; + + // Default constructor + V3Layer(); + + /// Constructor setting layer number and debugging level + /// for a "turbo" layer (i.e. where staves overlap in phi) + V3Layer(Int_t lay, Bool_t turbo = kFALSE, Int_t debug = 0); + + /// Copy constructor + V3Layer(const V3Layer&) = default; + + /// Assignment operator + V3Layer& operator=(const V3Layer&) = default; + + /// Default destructor + ~V3Layer() override; + + Bool_t hasGammaConversionRods() const { return mAddGammaConv; }; + + Bool_t isTurbo() const { return mIsTurbo; }; + + Bool_t isITS4() const { return mIsITS4; }; + + Double_t getChipThick() const { return mChipThickness; }; + + Double_t getStaveTilt() const { return mStaveTilt; }; + + Double_t getStaveWidth() const { return mStaveWidth; }; + + Double_t getSensorThick() const { return mSensorThickness; }; + + Double_t getNumberOfStaves() const { return mNumberOfStaves; }; + + Double_t getNumberOfChips() const { return mNumberOfChips; }; + + Double_t getRadius() const { return mLayerRadius; }; + + Double_t getPhi0() const { return mPhi0; }; + + Double_t getIBModuleZLength() const { return mIBModuleZLength; }; + + Double_t getOBModuleZLength() const { return mOBModuleZLength; }; + + Int_t getChipType() const { return mChipTypeID; } + + Int_t getNumberOfStavesPerParent() const { return mHierarchy[kStave]; } + + Int_t getNumberOfHalfStavesPerParent() const { return mHierarchy[kHalfStave]; } + + Int_t getNumberOfModulesPerParent() const { return mHierarchy[kModule]; } + + Int_t getNumberOfChipsPerParent() const { return mHierarchy[kChip]; } + + Int_t getBuildLevel() const { return mBuildLevel; } + + Int_t getNumberOfInnerlayers() const { return mNumberOfInnerLayers; }; + + Detector::Model getStaveModel() const { return mStaveModel; } + + void setChipThick(Double_t t) { mChipThickness = t; }; + + /// Gets the Gamma Conversion Rod diameter + Double_t getGammaConversionRodDiam(); + + /// Gets the Gamma Conversion Rod X position + Double_t getGammaConversionRodXPos(); + + /// Sets whether this is a new ITS4 layer + void setIsITS4(const Bool_t its4) { mIsITS4 = its4; }; + + /// Sets Module Z length (valid only for new ITS4 layer) + void setIBModuleZLength(const Double_t z) { mIBModuleZLength = z; }; + + /// Sets the Stave tilt angle (for turbo layers only) + /// \param t The stave tilt angle + void setStaveTilt(Double_t t); + + /// Sets the Stave width (for turbo layers only) + /// \param w The stave width + void setStaveWidth(Double_t w); + + void setSensorThick(Double_t t) { mSensorThickness = t; }; + + void setNumberOfStaves(Int_t n) { mHierarchy[kStave] = mNumberOfStaves = n; }; + + /// Sets the number of units in a stave: + /// for the Inner Barrel: the number of chips per stave + /// for the Outer Barrel: the number of modules per half stave + /// \param u the number of units + void setNumberOfUnits(Int_t u); + + void setRadius(Double_t r) { mLayerRadius = r; }; + + void setPhi0(Double_t phi) { mPhi0 = phi; } + + void setChipType(Int_t tp) { mChipTypeID = tp; } + + void setBuildLevel(Int_t buildLevel) { mBuildLevel = buildLevel; } + + void setStaveModel(o2::its4::Detector::Model model) { mStaveModel = model; } + + void setNumberOfInnerLayers(const Int_t n) { mNumberOfInnerLayers = n; }; + + /// Adds the Gamma Conversion Rods to the geometry + /// \param diam the diameter of each rod + /// \param xPos the X position of each rod + void addGammaConversionRods(const Double_t diam, const Double_t xPos); + + /// Creates the actual Layer and places inside its mother volume + /// \param motherVolume the TGeoVolume owing the volume structure + virtual void createLayer(TGeoVolume* motherVolume); + + private: + /// Creates the actual Layer and places inside its mother volume + /// A so-called "turbo" layer is a layer where staves overlap in phi + /// User can set width and tilt angle, no check is performed here + /// to avoid volume overlaps + /// \param motherVolume The TGeoVolume owing the volume structure + void createLayerTurbo(TGeoVolume* motherVolume); + + /// Creates a new ITS4 Layer and places inside its mother volume + /// \param motherVolume The TGeoVolume owing the volume structure + /// \param mgr The GeoManager (used only to get the proper material) + void createITS4Layer(TGeoVolume* motherVolume, const TGeoManager* mgr = gGeoManager); + + /// Computes the inner radius of the air container for the Turbo configuration + /// as the radius of either the circle tangent to the stave or the circle + /// passing for the stave's lower vertex. Returns the radius of the container + /// if >0, else flag to use the lower vertex + Double_t radiusOmTurboContainer(); + + /// Creates the actual Stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStave(const TGeoManager* mgr = gGeoManager); + + /// Creates the IB Module: (only the chips for the time being) + /// Returns the module as a TGeoVolume + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createModuleInnerB(const TGeoManager* mgr = gGeoManager); + + /// Creates the OB Module: HIC + FPC + Carbon plate + /// Returns the module as a TGeoVolume + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createModuleOuterB(const TGeoManager* mgr = gGeoManager); + + /// Creates the IB FPC Aluminum Ground layer + /// Returns the layer as a TGeoVolume + /// \param x, z X, Z layer half lengths + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createIBFPCAlGnd(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Creates the IB FPC Aluminum Anode layer + /// Returns the layer as a TGeoVolume + /// \param x, z X, Z layer half lengths + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createIBFPCAlAnode(Double_t x, Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Creates the IB FPC capacitors + /// \param modvol The IB module mother volume + /// \param zchip The chip half Z length + /// \param yzero The Y base position of capacitors + /// \param mgr The GeoManager (used only to get the proper material) + void createIBCapacitors(TGeoVolume* modvol, Double_t zchip, Double_t yzero, const TGeoManager* mgr = gGeoManager); + + /// Create the chip stave for the Inner Barrel(Here we fake the halfstave volume to have the + /// same formal geometry hierarchy as for the Outer Barrel) + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveInnerB(const TGeoManager* mgr = gGeoManager); + + /// Create the mechanical stave structure + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveStructInnerB(const TGeoManager* mgr = gGeoManager); + + /// Create a dummy stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerBDummy(const TGeoManager* mgr = gGeoManager) const; + + /// Create the mechanical stave structure for Model 4 of TDR + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelInnerB4(const TGeoManager* mgr = gGeoManager); + + /// Create the Inner Barrel End Stave connectors + /// \param mgr The GeoManager (used only to get the proper material) + void createIBConnectors(const TGeoManager* mgr = gGeoManager); + + /// Create the Inner Barrel End Stave connectors on Side A + /// \param mgr The GeoManager (used only to get the proper material) + void createIBConnectorsASide(const TGeoManager* mgr = gGeoManager); + + /// Create the Inner Barrel End Stave connectors on Side C + /// \param mgr The GeoManager (used only to get the proper material) + void createIBConnectorsCSide(const TGeoManager* mgr = gGeoManager); + + /// Creates the OB FPC Copper Ground layer + /// Returns the FPC as a TGeoVolume + /// \param z Z module half lengths + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createOBFPCCuGnd(Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Creates the OB FPC Copper Signal layer + /// Returns the FPC as a TGeoVolume + /// \param z Z module half lengths + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createOBFPCCuSig(Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Creates the OB Power and Bias Buses + /// Returns a TGeoVolume with both buses + /// \param z Z stave half lengths + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createOBPowerBiasBuses(Double_t z, const TGeoManager* mgr = gGeoManager); + + /// Create the chip stave for the Outer Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveOuterB(const TGeoManager* mgr = gGeoManager); + + /// Create dummy stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelOuterBDummy(const TGeoManager* mgr = gGeoManager) const; + + /// Create the mechanical half stave structure or the Outer Barrel as in TDR + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createStaveModelOuterB2(const TGeoManager* mgr = gGeoManager); + + /// Create the Cold Plate connectors + void createOBColdPlateConnectors(); + + /// Create the A-Side end-stave connectors for OB staves + void createOBColdPlateConnectorsASide(); + + /// Create the C-Side end-stave connectors for OB staves + void createOBColdPlateConnectorsCSide(); + + /// Create the space frame for the Outer Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createSpaceFrameOuterB(const TGeoManager* mgr = gGeoManager); + + /// Create dummy stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createSpaceFrameOuterBDummy(const TGeoManager* mgr = gGeoManager) const; + + /// Create the space frame for the Outer Barrel (Model 2) + /// Returns a TGeoVolume with the Space Frame of a stave + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createSpaceFrameOuterB2(const TGeoManager* mgr = gGeoManager); + + /// Create the space frame building blocks for the Outer Barrel + /// \param mgr The GeoManager (used only to get the proper material) + void createOBSpaceFrameObjects(const TGeoManager* mgr = gGeoManager); + + /// Create the space frame connectors for the Outer Barrel + /// \param mother the mother volume where to put the connector + /// \param ymot,zmot the Y and Z position in the mother volume + /// \param sideA true for side A, false for side C + /// \param mgr The GeoManager (used only to get the proper material) + void createOBSpaceFrameConnector(TGeoVolume* mother, const Double_t ymot, const Double_t zmot, const Bool_t sideA, const TGeoManager* mgr = gGeoManager); + + /// Creates the V-shaped sides of the OB space frame (from a similar method with same + /// name and function in V11GeometrySDD class by L.Gaudichet) + /// \param name The volume name + /// \param dz The half Z length + /// \param alpha The first rotation angle + /// \param beta The second rotation angle + /// \param L The stave length + /// \param H The stave height + /// \param top True to create the top corner, False to create the side one + TGeoXtru* createStaveSide(const char* name, Double_t dz, Double_t alpha, Double_t beta, Double_t L, Double_t H, + Bool_t top); + + /// Help method to create a TGeoCombiTrans matrix from a similar method with same name and + /// function in V11GeometrySDD class by L.Gaudichet) + /// Returns the TGeoCombiTrans which make a translation in y and z and a rotation in phi + /// in the global coord system. If planeSym = true, the rotation places the object + /// symetrically (with respect to the transverse plane) to its position in the + /// case planeSym = false + TGeoCombiTrans* createCombiTrans(const char* name, Double_t dy, Double_t dz, Double_t dphi, Bool_t planeSym = kFALSE); + + /// Help method to add a translation to a TGeoCombiTrans matrix (from a similar method + /// with same name and function in V11GeometrySDD class by L.Gaudichet) + void addTranslationToCombiTrans(TGeoCombiTrans* ct, Double_t dx = 0, Double_t dy = 0, Double_t dz = 0) const; + + Int_t mLayerNumber; ///< Current layer number + Int_t mNumberOfInnerLayers; ///< Actual number of inner layers + Double_t mPhi0; ///< lab phi of 1st stave, in degrees!!! + Double_t mLayerRadius; ///< Inner radius of this layer + Double_t mSensorThickness; ///< Sensor thickness + Double_t mChipThickness; ///< Chip thickness + Double_t mStaveWidth; ///< Stave width (for turbo layers only) + Double_t mStaveTilt; ///< Stave tilt angle (for turbo layers only) in degrees + Int_t mNumberOfStaves; ///< Number of staves in this layer + Int_t mNumberOfModules; ///< Number of modules per container if defined (HalfStave, Stave, whatever is + ///< container) + Int_t mNumberOfChips; ///< Number chips per container (module, HalfStave, Stave, whatever is + /// container) + Int_t mHierarchy[kNHLevels]; ///< array to query number of staves, hstaves, modules, chips per its parent volume + + UInt_t mChipTypeID; ///< detector type id + Bool_t mIsTurbo; ///< True if this layer is a "turbo" layer + Bool_t mIsITS4; ///< True if this layer is a new ITS4 layer + Int_t mBuildLevel; ///< Used for material studies + + Detector::Model mStaveModel; ///< The stave model + + Bool_t mAddGammaConv; ///< True to add Gamma Conversion Rods + Double_t mGammaConvDiam; ///< Gamma Conversion Rod Diameter + Double_t mGammaConvXPos; ///< Gamma Conversion Rod X Position + + // Dimensions computed during geometry build-up + Double_t mIBModuleZLength; ///< IB Module Length along Z + Double_t mOBModuleZLength; ///< OB Module Length along Z + + // Parameters for the geometry + + // General Parameters + static const Int_t sNumberOfInnerLayers; ///< Number of IB Layers + + static const Double_t sDefaultSensorThick; ///< Default sensor thickness + static const Double_t sMetalLayerThick; ///< Metal layer thickness + + // Inner Barrel Parameters + static const Int_t sIBChipsPerRow; ///< IB chips per row in module + static const Int_t sIBNChipRows; ///< IB chip rows in module + static const Double_t sIBChipZGap; ///< Gap between IB chips on Z + + static const Double_t sIBModuleZLength; ///< IB Module Length along Z + static const Double_t sIBFPCWiderXPlus; ///< FPC protrusion at X>0 + static const Double_t sIBFPCWiderXNeg; ///< FPC protrusion at X<0 + static const Double_t sIBFlexCableAlThick; ///< Thickness of FPC Aluminum + static const Double_t sIBFPCAlGNDWidth; ///< Width of total FPC Al Gnd + static const Double_t sIBFPCAlAnodeWidth1; ///< Width of FPC Al Anode + static const Double_t sIBFPCAlAnodeWidth2; ///< Width of FPC Al Anode + static const Double_t sIBFlexCableKapThick; ///< Thickness of FPC Kapton + static const Double_t sIBFlexCablePolyThick; ///< Thickness of FPC Coverlay + static const Double_t sIBFlexCapacitorXWid; ///< IB capaictor X width + static const Double_t sIBFlexCapacitorYHi; ///< IB capaictor Y height + static const Double_t sIBFlexCapacitorZLen; ///< IB capaictor Z length + static const Double_t sIBColdPlateWidth; ///< IB cold plate X width + static const Double_t sIBColdPlateZLen; ///< IB cold plate Z length + static const Double_t sIBGlueThick; ///< IB glue thickness + static const Double_t sIBCarbonFleeceThick; ///< IB carbon fleece thickness + static const Double_t sIBCarbonPaperThick; ///< IB Carbon Paper Thickness + static const Double_t sIBCarbonPaperWidth; ///< IB Carbon Paper X Width + static const Double_t sIBCarbonPaperZLen; ///< IB Carbon Paper Z Length + static const Double_t sIBK13D2UThick; ///< IB k13d2u prepreg thickness + static const Double_t sIBCoolPipeInnerD; ///< IB cooling inner diameter + static const Double_t sIBCoolPipeThick; ///< IB cooling pipe thickness + static const Double_t sIBCoolPipeXDist; ///< IB cooling pipe separation + static const Double_t sIBCoolPipeZLen; ///< IB cooling pipe length + static const Double_t sIBTopVertexWidth1; ///< IB TopVertex width + static const Double_t sIBTopVertexWidth2; ///< IB TopVertex width + static const Double_t sIBTopVertexHeight; ///< IB TopVertex height + static const Double_t sIBTopVertexAngle; ///< IB TopVertex aperture angle + static const Double_t sIBSideVertexWidth; ///< IB SideVertex width + static const Double_t sIBSideVertexHeight; ///< IB SideVertex height + static const Double_t sIBTopFilamentSide; ///< IB TopFilament side + static const Double_t sIBTopFilamentAlpha; ///< IB TopFilament angle + static const Double_t sIBTopFilamentInterZ; ///< IB TopFilament Z interdist + static const Double_t sIBEndSupportThick; ///< IB end support thickness + static const Double_t sIBEndSupportZLen; ///< IB end support length + static const Double_t sIBEndSupportXUp; ///< IB end support X up wide + static const Double_t sIBEndSupportOpenPhi; ///< IB end support opening phi + + static const Double_t sIBConnectorXWidth; ///< IB Connectors Width + static const Double_t sIBConnectorYTot; ///< IB Connectors total height + static const Double_t sIBConnectBlockZLen; ///< IB Connector Block Z length + static const Double_t sIBConnBodyYHeight; ///< IB Connector Body Y height + static const Double_t sIBConnTailYMid; ///< IB Connector Tail Y mid pt + static const Double_t sIBConnTailYShift; ///< IB Connector Tail Y shift + static const Double_t sIBConnTailZLen; ///< IB Connector Tail Z length + static const Double_t sIBConnTailOpenPhi; ///< IB Connector Tail Angle + static const Double_t sIBConnRoundHoleD; ///< IB Connector Hole diameter + static const Double_t sIBConnRoundHoleZ; ///< IB Connector Hole Z pos + static const Double_t sIBConnSquareHoleX; ///< IB Connector Hole X len + static const Double_t sIBConnSquareHoleZ; ///< IB Connector Hole Z len + static const Double_t sIBConnSquareHoleZPos; ///< IB Connector Hole Z pos + static const Double_t sIBConnInsertHoleD; ///< IB Connector Insert diam + static const Double_t sIBConnInsertHoleZPos; ///< IB Connector Insert Z pos + static const Double_t sIBConnTubeHole1D; ///< IB Connector Tube1 diam + static const Double_t sIBConnTubeHole1ZLen; ///< IB Connector Tube1 Z len + static const Double_t sIBConnTubeHole1ZLen2; ///< IB Conn Tube1 Z len 2'side + static const Double_t sIBConnTubeHole2D; ///< IB Connector Tube2 diam + static const Double_t sIBConnTubeHole3XPos; ///< IB Connector Tube3 X pos + static const Double_t sIBConnTubeHole3ZPos; ///< IB Connector Tube3 Z pos + static const Double_t sIBConnTubesXDist; ///< IB Connector Tubes X dist + static const Double_t sIBConnTubesYPos; ///< IB Connector Tubes Y pos + static const Double_t sIBConnInsertD; ///< IB Connector Insert diam + static const Double_t sIBConnInsertHeight; ///< IB Connector Insert height + static const Double_t sIBConnSideHole1D; ///< IB Conn Side 1st hole D + static const Double_t sIBConnSideHole1YPos; ///< IB Conn Side 1st hole Y pos + static const Double_t sIBConnSideHole1ZPos; ///< IB Conn Side 1st hole Z pos + static const Double_t sIBConnSideHole1XWid; ///< IB Conn Side 1st hole X wid + static const Double_t sIBConnSideHole2YPos; ///< IB Conn Side 2nd hole Y pos + static const Double_t sIBConnSideHole2ZPos; ///< IB Conn Side 2nd hole Z pos + static const Double_t sIBConnSideHole2XWid; ///< IB Conn Side 2nd hole X wid + static const Double_t sIBConnSideHole2YWid; ///< IB Conn Side 2nd hole Y wid + static const Double_t sIBConnSideHole2ZWid; ///< IB Conn Side 2nd hole Z wid + static const Double_t sIBConnectAFitExtD; ///< IB ConnectorA Fitting ext D + static const Double_t sIBConnectAFitIntD; ///< IB ConnectorA Fitting int D + static const Double_t sIBConnectAFitZLen; ///< IB ConnectorA Fitting Z len + static const Double_t sIBConnectAFitZOut; ///< IB ConnectorA Fitting Z Out + static const Double_t sIBConnPlugInnerD; ///< IB Connector Plug int diam + static const Double_t sIBConnPlugTotLen; ///< IB Connector Plug tot len + static const Double_t sIBConnPlugInnerLen; ///< IB Connector Plug int len + + static const Double_t sIBStaveHeight; ///< IB Stave Total Y Height + + // Outer Barrel Parameters + static const Int_t sOBChipsPerRow; ///< OB chips per row in module + static const Int_t sOBNChipRows; ///< OB chip rows in module + + static const Double_t sOBChipThickness; ///< Default OB chip thickness + + static const Double_t sOBHalfStaveWidth; ///< OB Half Stave Width + static const Double_t sOBModuleGap; ///< Gap between OB modules + static const Double_t sOBChipXGap; ///< Gap between OB chips on X + static const Double_t sOBChipZGap; ///< Gap between OB chips on Z + static const Double_t sOBFlexCableXWidth; ///< OB FPC X width + static const Double_t sOBFlexCableAlThick; ///< Thickness of FPC Aluminum + static const Double_t sOBFlexCableKapThick; ///< Thickness of FPC Kapton + static const Double_t sOBFPCSoldMaskThick; ///< Thickness of FPC Solder Mask + static const Double_t sOBFPCCopperThick; ///< Thickness of FPC Copper + static const Double_t sOBFPCCuAreaFracGnd; ///< Fraction of Cu on Gnd FPC + static const Double_t sOBFPCCuAreaFracSig; ///< Fraction of Cu on Sig FPC + static const Double_t sOBGlueFPCThick; ///< Thickness of Glue to FPC + static const Double_t sOBGlueColdPlThick; ///< Thickness of Glue to Cold Pl + static const Double_t sOBPowerBusXWidth; ///< OB Power Bus X width + static const Double_t sOBPowerBusAlThick; ///< OB Power Bus Al thickness + static const Double_t sOBPowerBusAlFrac; ///< Fraction of Al on OB PB + static const Double_t sOBPowerBusDielThick; ///< OB Power Bus Dielectric thick + static const Double_t sOBPowerBusKapThick; ///< OB Power Bus Kapton thick + static const Double_t sOBBiasBusXWidth; ///< OB Bias Bus X width + static const Double_t sOBBiasBusAlThick; ///< OB Bias Bus Al thickness + static const Double_t sOBBiasBusAlFrac; ///< Fraction of Al on OB BB + static const Double_t sOBBiasBusDielThick; ///< OB Bias Bus Dielectric thick + static const Double_t sOBBiasBusKapThick; ///< OB Bias Bus Kapton thick + static const Double_t sOBColdPlateXWidth; ///< OB Cold Plate X width + static const Double_t sOBColdPlateZLenML; ///< OB ML Cold Plate Z length + static const Double_t sOBColdPlateZLenOL; ///< OB OL Cold Plate Z length + static const Double_t sOBColdPlateThick; ///< OB Cold Plate Thickness + static const Double_t sOBHalfStaveYPos; ///< OB half staves Y position + static const Double_t sOBHalfStaveYTrans; ///< OB half staves Y transl. + static const Double_t sOBHalfStaveXOverlap; ///< OB half staves X overlap + static const Double_t sOBGraphiteFoilThick; ///< OB graphite foil thickness + static const Double_t sOBCarbonFleeceThick; ///< OB carbon fleece thickness + static const Double_t sOBCoolTubeInnerD; ///< OB cooling inner diameter + static const Double_t sOBCoolTubeThick; ///< OB cooling tube thickness + static const Double_t sOBCoolTubeXDist; ///< OB cooling tube separation + + static const Double_t sOBCPConnectorXWidth; ///< OB Cold Plate Connect Width + static const Double_t sOBCPConnBlockZLen; ///< OB CP Connect Block Z len + static const Double_t sOBCPConnBlockYHei; ///< OB CP Connect Block Z len + static const Double_t sOBCPConnHollowZLen; ///< OB CP Connect Block Z len + static const Double_t sOBCPConnHollowYHei; ///< OB CP Connect Block Z len + static const Double_t sOBCPConnSquareHoleX; ///< OB Conn Square Hole X len + static const Double_t sOBCPConnSquareHoleZ; ///< OB Conn Square Hole Z len + static const Double_t sOBCPConnSqrHoleZPos; ///< OB Conn Square Hole Z pos + static const Double_t sOBCPConnSqrInsertRZ; ///< OB Conn Square Insert RZpos + static const Double_t sOBCPConnRoundHoleD; ///< OB Conn Round Hole diam + static const Double_t sOBCPConnRndHoleZPos; ///< OB Conn Round Hole Z pos + static const Double_t sOBCPConnTubesXDist; ///< OB Connector Tubes X dist + static const Double_t sOBCPConnTubesYPos; ///< OB Connector Tubes Y pos + static const Double_t sOBCPConnTubeHole1D; ///< OB Connector Tube1 diam + static const Double_t sOBCPConnTubeHole1Z; ///< OB Connector Tube1 Z len + static const Double_t sOBCPConnTubeHole2D; ///< OB Connector Tube2 diam + static const Double_t sOBCPConnFitHoleD; ///< OB Connector Fit Hole diam + static const Double_t sOBCPConnTubeHole3XP; ///< OB Connector Tube3 X pos + static const Double_t sOBCPConnTubeHole3ZP; ///< OB Connector Tube3 Z pos + static const Double_t sOBCPConnInstZThick; ///< OB Connector Insert height + static const Double_t sOBCPConnInsertYHei; ///< OB Connector Insert height + static const Double_t sOBCPConnAFitExtD; ///< OB ConnectorA Fitting ext D + static const Double_t sOBCPConnAFitThick; ///< OB ConnectorA Fitting thick + static const Double_t sOBCPConnAFitZLen; ///< OB ConnectorA Fitting Z len + static const Double_t sOBCPConnAFitZIn; ///< OB ConnectorA Fitting Z ins + static const Double_t sOBCPConnPlugInnerD; ///< OB Connector Plug int diam + static const Double_t sOBCPConnPlugTotLen; ///< OB Connector Plug tot le + static const Double_t sOBCPConnPlugThick; ///< OB Connector Plug thickness + + static const Double_t sOBSpaceFrameZLen[2]; ///< OB Space Frame Length + static const Int_t sOBSpaceFrameNUnits[2]; ///< OB Number of SF Units + static const Double_t sOBSpaceFrameUnitLen; ///< OB Space Frame Unit length + static const Double_t sOBSpaceFrameWidth; ///< OB Space Frame Width + static const Double_t sOBSpaceFrameHeight; ///< OB Space Frame Height + static const Double_t sOBSpaceFrameTopVL; ///< Parameters defining... + static const Double_t sOBSpaceFrameTopVH; ///< ...the Top V shape + static const Double_t sOBSpaceFrameSideVL; ///< Parameters defining... + static const Double_t sOBSpaceFrameSideVH; ///< ...the Side V shape + static const Double_t sOBSpaceFrameVAlpha; ///< Angles of aperture... + static const Double_t sOBSpaceFrameVBeta; ///< ...of the V shapes + static const Double_t sOBSFrameBaseRibDiam; ///< OB SFrame Base Rib Diam + static const Double_t sOBSFrameBaseRibPhi; ///< OB SF base beam angle + static const Double_t sOBSFrameSideRibDiam; ///< OB SFrame Side Rib Diam + static const Double_t sOBSFrameSideRibPhi; ///< OB SF side beam angle + static const Double_t sOBSFrameULegLen; ///< OB SF U-Leg length + static const Double_t sOBSFrameULegWidth; ///< OB SF U-Leg width + static const Double_t sOBSFrameULegHeight1; ///< OB SF U-Leg height + static const Double_t sOBSFrameULegHeight2; ///< OB SF U-Leg height + static const Double_t sOBSFrameULegThick; ///< OB SF U-Leg thickness + static const Double_t sOBSFrameULegXPos; ///< OB SF U-Leg X position + static const Double_t sOBSFrameConnWidth; ///< OB SF Connector width + static const Double_t sOBSFrameConnTotLen; ///< OB SF Connector total length + static const Double_t sOBSFrameConnTotHei; ///< OB SF Connector total height + static const Double_t sOBSFrameConnTopLen; ///< OB SF Connector top length + static const Double_t sOBSFrameConnInsWide; ///< OB SF Connector insert width + static const Double_t sOBSFrameConnInsBase; ///< OB SF Connector insert base + static const Double_t sOBSFrameConnInsHei; ///< OB SF Connector insert height + static const Double_t sOBSFrameConnHoleZPos; ///< OB SF Connector holes Z pos + static const Double_t sOBSFrameConnHoleZDist; ///< OB SF Connector holes Zdist + static const Double_t sOBSFrameConnTopHoleD; ///< OB SF Connec top hole diam + static const Double_t sOBSFrConnTopHoleXDist; ///< OB SF Connec top hole Xdist + static const Double_t sOBSFrameConnAHoleWid; ///< OB SF Connect A hole width + static const Double_t sOBSFrameConnAHoleLen; ///< OB SF Connect A hole length + static const Double_t sOBSFrConnASideHoleD; ///< OB SF Conn A side hole dia + static const Double_t sOBSFrConnASideHoleL; ///< OB SF Conn A side hole len + static const Double_t sOBSFrConnASideHoleY; ///< OB SF Conn A side hole Y pos + static const Double_t sOBSFrameConnCHoleZPos; ///< OB SF Connect C hole Z pos + static const Double_t sOBSFrConnCHoleXDist; ///< OB SF Conn C top hole Xdist + static const Double_t sOBSFrConnCTopHoleD; ///< OB SF Conn C top hole dia + static const Double_t sOBSFrameConnInsHoleD; ///< OB SF Connec insert hole dia + static const Double_t sOBSFrameConnInsHoleX; ///< OB SF Connec insert hole X + + ClassDefOverride(V3Layer, 0); // ITS v3 geometry +}; +} // namespace its4 +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Services.h b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Services.h new file mode 100644 index 0000000000000..c1ba390d07c10 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Services.h @@ -0,0 +1,184 @@ +// 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 V3Services.h +/// \brief Definition of the V3Services class +/// \author Mario Sitta <sitta@to.infn.it> +/// \author Parinya Namwongsa <parinya.namwongsa@cern.ch> + +#ifndef ALICEO2_ITS4_UPGRADEV3SERVICES_H_ +#define ALICEO2_ITS4_UPGRADEV3SERVICES_H_ + +#include <TGeoManager.h> // for gGeoManager +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc +#include "ITS4Simulation/V11Geometry.h" // for V11Geometry +#include "ITS4Simulation/Detector.h" // for Detector, Detector::Model + +class TGeoXtru; + +class TGeoCombiTrans; + +class TGeoVolume; + +namespace o2 +{ +namespace its4 +{ + +/// This class defines the Geometry for the Services of the ITS Upgrade using TGeo. +class V3Services : public V11Geometry +{ + + public: + // Default constructor + V3Services(); + + /// Copy constructor + V3Services(const V3Services&) = default; + + /// Assignment operator + V3Services& operator=(const V3Services&) = default; + + /// Default destructor + ~V3Services() override; + + /// Creates the Inner Barrel End Wheels on Side A + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createIBEndWheelsSideA(const TGeoManager* mgr = gGeoManager); + + /// Creates the Inner Barrel End Wheels on Side C + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createIBEndWheelsSideC(const TGeoManager* mgr = gGeoManager); + + /// Creates the CYSS Assembly (i.e. the supporting half cylinder and cone) + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* createCYSSAssembly(const TGeoManager* mgr = gGeoManager); + + /// Creates the Middle Barrel End Wheels on Side A + /// \param mother the TGeoVolume owing the volume structure + /// \param mgr The GeoManager (used only to get the proper material) + void createMBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Middle Barrel End Wheels on Side C + /// \param mother the TGeoVolume owing the volume structure + /// \param mgr The GeoManager (used only to get the proper material) + void createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Outer Barrel End Wheels on Side A + /// \param mother the TGeoVolume owing the volume structure + /// \param mgr The GeoManager (used only to get the proper material) + void createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Outer Barrel End Wheels on Side C + /// \param mother the TGeoVolume owing the volume structure + /// \param mgr The GeoManager (used only to get the proper material) + void createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Outer Barrel Cone on Side A + /// \param mother the TGeoVolume owing the volume structure + /// \param mgr The GeoManager (used only to get the proper material) + void createOBConeSideA(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Outer Barrel Cone on Side C + /// \param mother the TGeoVolume owing the volume structure + /// \param mgr The GeoManager (used only to get the proper material) + void createOBConeSideC(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + private: + /// Creates a single Inner Barrel End Wheel on Side A + /// \param iLay the layer number + /// \param endWheel the End Wheel volume assembly + /// \param mgr The GeoManager (used only to get the proper material) + void ibEndWheelSideA(const Int_t iLay, TGeoVolume* endWheel, const TGeoManager* mgr = gGeoManager); + + /// Creates a single Inner Barrel End Wheel on Side C + /// \param iLay the layer number + /// \param endWheel the End Wheel volume assembly + /// \param mgr The GeoManager (used only to get the proper material) + void ibEndWheelSideC(const Int_t iLay, TGeoVolume* endWheel, const TGeoManager* mgr = gGeoManager); + + /// Creates the shape of a Rib on Side A + /// \param iLay the layer number + TGeoXtru* ibEndWheelARibShape(const Int_t iLay); + + /// Creates the CYSS cylinder of the Inner Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* ibCyssCylinder(const TGeoManager* mgr = gGeoManager); + + /// Creates the CYSS cone of the Inner Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* ibCyssCone(const TGeoManager* mgr = gGeoManager); + + /// Creates the CYSS Flange on Side A of the Inner Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* ibCyssFlangeSideA(const TGeoManager* mgr = gGeoManager); + + /// Creates the hollows in the CYSS Flange on Side A of the Inner Barrel + /// \param zlen the thickness of the ring where the hollows are + TString ibCreateHollowsCyssFlangeSideA(const Double_t zlen); + + /// Creates the CYSS Flange on Side C of the Inner Barrel + /// \param mgr The GeoManager (used only to get the proper material) + TGeoVolume* ibCyssFlangeSideC(const TGeoManager* mgr = gGeoManager); + + /// Creates a single Middle/Outer Barrel End Wheel on Side A + /// \param iLay the layer number + /// \param mother the volume containing the created wheel + /// \param mgr The GeoManager (used only to get the proper material) + void obEndWheelSideA(const Int_t iLay, TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates a single Middle Barrel End Wheel on Side C + /// \param iLay the layer number + /// \param mother the volume containing the created wheel + /// \param mgr The GeoManager (used only to get the proper material) + void mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates a single Outer Barrel End Wheel on Side C + /// \param iLay the layer number + /// \param mother the volume containing the created wheel + /// \param mgr The GeoManager (used only to get the proper material) + void obEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Outer Barrel Cone on Side A + /// \param mother the volume containing the created wheel + /// \param mgr The GeoManager (used only to get the proper material) + void obConeSideA(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Outer Barrel Cone on Side C + /// \param mother the volume containing the created wheel + /// \param mgr The GeoManager (used only to get the proper material) + void obConeSideC(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + /// Creates the Outer Barrel Cone Trays on Side A + /// \param mother the volume containing the created wheel + /// \param mgr The GeoManager (used only to get the proper material) + void obConeTraysSideA(TGeoVolume* mother, const TGeoManager* mgr = gGeoManager); + + // Parameters + static constexpr Int_t sNumberInnerLayers = 3; ///< Number of inner layers in ITSU + static constexpr Int_t sNumberMiddlLayers = 2; ///< Number of middle layers in ITSU + static constexpr Int_t sNumberOuterLayers = 2; ///< Number of outer layers in ITSU + + // Common parameters for IB services + static const Double_t sIBWheelACZdist; ///< IB Z distance between wheels + static const Double_t sIBCYSSFlangeCZPos; ///< IB Z position of CYSS C Flange + + // Common parameters for OB services + static const Double_t sOBWheelThickness; ///< MB/OB Wheels Thickness + static const Double_t sMBWheelsZpos; ///< MB Wheels Z position + static const Double_t sOBWheelsZpos; ///< OB Wheels Z position + static const Double_t sOBConesZpos; ///< OB Cones A & C Z position + + ClassDefOverride(V3Services, 0); // ITS v3 support geometry +}; +} // namespace its4 +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx new file mode 100644 index 0000000000000..f740ba40eab1c --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx @@ -0,0 +1,1353 @@ +// 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 Detector.cxx +/// \brief Implementation of the Detector class + +#include "ITSMFTBase/SegmentationAlpide.h" +#include "ITSMFTSimulation/Hit.h" +#include "ITS4Base/GeometryTGeo.h" +#include "ITS4Simulation/Detector.h" +#include "ITS4Simulation/V3Layer.h" +#include "ITS4Simulation/V3Services.h" + +#include "SimulationDataFormat/Stack.h" +#include "SimulationDataFormat/TrackReference.h" + +// FairRoot includes +#include "FairDetector.h" // for FairDetector +#include "FairLogger.h" // for LOG, LOG_IF +#include "FairRootManager.h" // for FairRootManager +#include "FairRun.h" // for FairRun +#include "FairRuntimeDb.h" // for FairRuntimeDb +#include "FairVolume.h" // for FairVolume +#include "FairRootManager.h" + +#include "TGeoManager.h" // for TGeoManager, gGeoManager +#include "TGeoTube.h" // for TGeoTube +#include "TGeoPcon.h" // for TGeoPcon +#include "TGeoVolume.h" // for TGeoVolume, TGeoVolumeAssembly +#include "TString.h" // for TString, operator+ +#include "TVirtualMC.h" // for gMC, TVirtualMC +#include "TVirtualMCStack.h" // for TVirtualMCStack + +#include <cstdio> // for NULL, snprintf + +class FairModule; + +class TGeoMedium; + +class TParticle; + +using std::cout; +using std::endl; + +using o2::itsmft::Hit; +using Segmentation = o2::itsmft::SegmentationAlpide; +using namespace o2::its4; + +Detector::Detector() + : o2::base::DetImpl<Detector>("IT4", kTRUE), + mTrackData(), + /* + mHitStarted(false), + mTrkStatusStart(), + mPositionStart(), + mMomentumStart(), + mEnergyLoss(), + */ + mNumberOfDetectors(-1), + mModifyGeometry(kFALSE), + mHits(o2::utils::createSimVector<o2::itsmft::Hit>()), + mStaveModelInnerBarrel(kIBModel0), + mStaveModelOuterBarrel(kOBModel0) +{ +} + +static double radii2Turbo(double rMin, double rMid, double rMax, double sensW) +{ + // compute turbo angle from radii and sensor width + return TMath::ASin((rMax * rMax - rMin * rMin) / (2 * rMid * sensW)) * TMath::RadToDeg(); +} + +// We need this as a method to access members +void Detector::configITS(Detector* its) +{ + // build ITS upgrade detector + const int kNLr = 7; + const int kNLrInner = 3; + const int kBuildLevel = 0; + const int kSensTypeID = 0; // dummy id for Alpide sensor + + const float ChipThicknessIB = 50.e-4; + const float ChipThicknessOB = 100.e-4; + + enum { kRmn, + kRmd, + kRmx, + kNModPerStave, + kPhi0, + kNStave, + kNPar }; + // Radii are from last TDR (ALICE-TDR-017.pdf Tab. 1.1, rMid is mean value) + // const double tdr5dat[kNLr][kNPar] = { + // {2.24, 2.34, 2.67, 9., 16.42, 12}, // for each inner layer: rMin,rMid,rMax,NChip/Stave, phi0, nStaves + // {3.01, 3.15, 3.46, 9., 12.18, 16}, + // {3.78, 3.93, 4.21, 9., 9.55, 20}, + // {-1, 19.6, -1, 4., 0., 24}, // for others: -, rMid, -, NMod/HStave, phi0, nStaves // 24 was 49 + // {-1, 24.55, -1, 4., 0., 30}, // 30 was 61 + // {-1, 34.39, -1, 7., 0., 42}, // 42 was 88 + // {-1, 39.34, -1, 7., 0., 48} // 48 was 100 + // }; + // const int nChipsPerModule = 7; // For OB: how many chips in a row + // const double zChipGap = 0.01; // For OB: gap in Z between chips + // const double zModuleGap = 0.01; // For OB: gap in Z between modules + + // double dzLr, rLr, phi0, turbo; + // int nStaveLr, nModPerStaveLr; + + // its->setStaveModelIB(o2::its4::Detector::kIBModel4); + its->setStaveModelOB(o2::its4::Detector::kOBModel2); + + const int kNWrapVol = 3; + const double wrpRMin[kNWrapVol] = {2.1, 19.3, 33.32}; + const double wrpRMax[kNWrapVol] = {15.4, 29.14, 46.0}; + const double wrpZSpan[kNWrapVol] = {70., 93., 163.6}; + + for (int iw = 0; iw < kNWrapVol; iw++) { + its->defineWrapperVolume(iw, wrpRMin[iw], wrpRMax[iw], wrpZSpan[iw]); + } + + // Build OB only (4 layers) + // for (int idLr = mNumberOfInnerLayers; idLr < mTotalNumberOfLayers; idLr++) { + // int im = idLr - mNumberOfInnerLayers + kNLrInner; + // rLr = tdr5dat[im][kRmd]; + // phi0 = tdr5dat[im][kPhi0]; + + // nStaveLr = TMath::Nint(tdr5dat[im][kNStave]); + // nModPerStaveLr = TMath::Nint(tdr5dat[im][kNModPerStave]); + // int nChipsPerStaveLr = nModPerStaveLr; + // its->defineLayer(idLr, phi0, rLr, nStaveLr, nModPerStaveLr, ChipThicknessOB, Segmentation::SensorLayerThickness, + // kSensTypeID, kBuildLevel); + // } + + // From Mario Sitta's hack + std::vector<std::array<double, 2>> tdr5data; + tdr5data.emplace_back(std::array<double, 2>{1.8f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{2.4f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{3.0f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{4.0f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{5.0f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{6.0f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{7.0f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{8.0f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{9.0f, 27.15}); + tdr5data.emplace_back(std::array<double, 2>{10.0f, 27.15}); + + static constexpr float SensorLayerThickness = 30.e-4; + its->setStaveModelOB(o2::its4::Detector::kOBModel2); + // its->createOuterBarrel(false); + + auto idLayer{0}; + for (auto& layerData : tdr5data) { + its->defineInnerLayerITS4(idLayer, layerData[0], layerData[1], SensorLayerThickness, 0, 0); + ++idLayer; + } + its->createOuterBarrel(false); +} + +Detector::Detector(Bool_t active) + : o2::base::DetImpl<Detector>("IT4", active), + mTrackData(), + /* + mHitStarted(false), + mTrkStatusStart(), + mPositionStart(), + mMomentumStart(), + mEnergyLoss(), + */ + mNumberOfInnerLayers(10), + mNumberOfDetectors(-1), + mModifyGeometry(kFALSE), + mHits(o2::utils::createSimVector<o2::itsmft::Hit>()), + mStaveModelInnerBarrel(kIBModel0), + mStaveModelOuterBarrel(kOBModel0) +{ + + mTotalNumberOfLayers = mNumberOfInnerLayers + (sNumberLayers - sNumberInnerLayers); + + createAllArrays(); + + for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { + mLayerName[j].Form("%s%d", GeometryTGeo::getITSSensorPattern(), j); // See V3Layer + } + + if (mTotalNumberOfLayers > 0) { // if not, we'll Fatal-ize in CreateGeometry + for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { + mITS4Layer[j] = kFALSE; + mLayerPhi0[j] = 0; + mLayerRadii[j] = 0.; + mLayerZLen[j] = 0.; + mStavePerLayer[j] = 0; + mUnitPerStave[j] = 0; + mChipThickness[j] = 0.; + mStaveWidth[j] = 0.; + mStaveTilt[j] = 0.; + mDetectorThickness[j] = 0.; + mChipTypeID[j] = 0; + mBuildLevel[j] = 0; + mGeometry[j] = nullptr; + } + } + mServicesGeometry = nullptr; + + for (int i = sNumberOfWrapperVolumes; i--;) { + mWrapperMinRadius[i] = mWrapperMaxRadius[i] = mWrapperZSpan[i] = -1; + } + + configITS(this); +} + +Detector::Detector(const Detector& rhs) + : o2::base::DetImpl<Detector>(rhs), + mTrackData(), + /* + mHitStarted(false), + mTrkStatusStart(), + mPositionStart(), + mMomentumStart(), + mEnergyLoss(), + */ + mNumberOfInnerLayers(rhs.mNumberOfInnerLayers), + mNumberOfDetectors(rhs.mNumberOfDetectors), + mModifyGeometry(rhs.mModifyGeometry), + + /// Container for data points + mHits(o2::utils::createSimVector<o2::itsmft::Hit>()), + mStaveModelInnerBarrel(rhs.mStaveModelInnerBarrel), + mStaveModelOuterBarrel(rhs.mStaveModelOuterBarrel) +{ + + for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { + mLayerName[j].Form("%s%d", GeometryTGeo::getITSSensorPattern(), j); // See V3Layer + } +} + +Detector::~Detector() +{ + + if (mHits) { + // delete mHits; + o2::utils::freeSimVector(mHits); + } +} + +Detector& Detector::operator=(const Detector& rhs) +{ + // The standard = operator + // Inputs: + // Detector &h the sourse of this copy + // Outputs: + // none. + // Return: + // A copy of the sourse hit h + + if (this == &rhs) { + return *this; + } + + // base class assignment + base::Detector::operator=(rhs); + + mNumberOfDetectors = rhs.mNumberOfDetectors; + + mModifyGeometry = rhs.mModifyGeometry; + + /// Container for data points + mHits = nullptr; + + mStaveModelInnerBarrel = rhs.mStaveModelInnerBarrel; + mStaveModelOuterBarrel = rhs.mStaveModelOuterBarrel; + + for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { + mLayerName[j].Form("%s%d", GeometryTGeo::getITSSensorPattern(), j); // See V3Layer + } + + return *this; +} + +void Detector::createAllArrays() +{ + // Create all arrays + // We have to do it here because now the number of Inner Layers is + // not fixed, so we don't know in advance how many to create: they + // cannot be anymore static arrays as in the default version + // M.S. 21 mar 2020 (13th day of Italian Coronavirus lockdown) + + mLayerID = new Int_t[mTotalNumberOfLayers]; + mLayerName = new TString[mTotalNumberOfLayers]; + + mWrapperLayerId = new Int_t[mTotalNumberOfLayers]; + mTurboLayer = new Bool_t[mTotalNumberOfLayers]; + mITS4Layer = new Bool_t[mTotalNumberOfLayers]; + + mLayerPhi0 = new Double_t[mTotalNumberOfLayers]; + mLayerRadii = new Double_t[mTotalNumberOfLayers]; + mLayerZLen = new Double_t[mTotalNumberOfLayers]; + mStavePerLayer = new Int_t[mTotalNumberOfLayers]; + mUnitPerStave = new Int_t[mTotalNumberOfLayers]; + mChipThickness = new Double_t[mTotalNumberOfLayers]; + mStaveWidth = new Double_t[mTotalNumberOfLayers]; + mStaveTilt = new Double_t[mTotalNumberOfLayers]; + mDetectorThickness = new Double_t[mTotalNumberOfLayers]; + mChipTypeID = new UInt_t[mTotalNumberOfLayers]; + mBuildLevel = new Int_t[mTotalNumberOfLayers]; + + mGeometry = new V3Layer*[mTotalNumberOfLayers]; +} + +void Detector::InitializeO2Detector() +{ + // Define the list of sensitive volumes + defineSensitiveVolumes(); + + for (int i = 0; i < mTotalNumberOfLayers; i++) { + mLayerID[i] = gMC ? TVirtualMC::GetMC()->VolId(mLayerName[i]) : 0; + } + + mGeometryTGeo = GeometryTGeo::Instance(); + // FairRuntimeDb* rtdb= FairRun::Instance()->GetRuntimeDb(); + // O2itsGeoPar* par=(O2itsGeoPar*)(rtdb->getContainer("O2itsGeoPar")); +} + +Bool_t Detector::ProcessHits(FairVolume* vol) +{ + // This method is called from the MC stepping + if (!(fMC->TrackCharge())) { + return kFALSE; + } + + Int_t lay = 0, volID = vol->getMCid(); + + // FIXME: Determine the layer number. Is this information available directly from the FairVolume? + bool notSens = false; + while ((lay < mTotalNumberOfLayers) && (notSens = (volID != mLayerID[lay]))) { + ++lay; + } + if (notSens) + return kFALSE; // RS: can this happen? This method must be called for sensors only? + + // Is it needed to keep a track reference when the outer ITS volume is encountered? + auto stack = (o2::data::Stack*)fMC->GetStack(); + if (fMC->IsTrackExiting() && (lay == 0 || lay == 6)) { + // Keep the track refs for the innermost and outermost layers only + o2::TrackReference tr(*fMC, GetDetId()); + tr.setTrackID(stack->GetCurrentTrackNumber()); + tr.setUserId(lay); + stack->addTrackReference(tr); + } + bool startHit = false, stopHit = false; + unsigned char status = 0; + if (fMC->IsTrackEntering()) { + status |= Hit::kTrackEntering; + } + if (fMC->IsTrackInside()) { + status |= Hit::kTrackInside; + } + if (fMC->IsTrackExiting()) { + status |= Hit::kTrackExiting; + } + if (fMC->IsTrackOut()) { + status |= Hit::kTrackOut; + } + if (fMC->IsTrackStop()) { + status |= Hit::kTrackStopped; + } + if (fMC->IsTrackAlive()) { + status |= Hit::kTrackAlive; + } + + // track is entering or created in the volume + if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) { + startHit = true; + } else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) { + stopHit = true; + } + + // increment energy loss at all steps except entrance + if (!startHit) + mTrackData.mEnergyLoss += fMC->Edep(); + if (!(startHit | stopHit)) + return kFALSE; // do noting + + if (startHit) { + mTrackData.mEnergyLoss = 0.; + fMC->TrackMomentum(mTrackData.mMomentumStart); + fMC->TrackPosition(mTrackData.mPositionStart); + mTrackData.mTrkStatusStart = status; + mTrackData.mHitStarted = true; + } + if (stopHit) { + TLorentzVector positionStop; + fMC->TrackPosition(positionStop); + // Retrieve the indices with the volume path + int stave(0), halfstave(0), chipinmodule(0), module; + fMC->CurrentVolOffID(1, chipinmodule); + fMC->CurrentVolOffID(2, module); + fMC->CurrentVolOffID(3, halfstave); + fMC->CurrentVolOffID(4, stave); + int chipindex = mGeometryTGeo->getChipIndex(lay, stave, halfstave, module, chipinmodule); + + Hit* p = addHit(stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(), + mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(), + mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status); + // p->SetTotalEnergy(vmc->Etot()); + + // RS: not sure this is needed + // Increment number of Detector det points in TParticle + stack->addHit(GetDetId()); + } + + return kTRUE; +} + +void Detector::createMaterials() +{ + Int_t ifield = 2; + Float_t fieldm = 10.0; + o2::base::Detector::initFieldTrackingParams(ifield, fieldm); + //////////// + + Float_t tmaxfd = 0.1; // 1.0; // Degree + Float_t stemax = 1.0; // cm + Float_t deemax = 0.1; // 30.0; // Fraction of particle's energy 0<deemax<=1 + Float_t epsil = 1.0E-4; // 1.0; // cm + Float_t stmin = 0.0; // cm "Default value used" + + Float_t tmaxfdSi = 0.1; // .10000E+01; // Degree + Float_t stemaxSi = 0.0075; // .10000E+01; // cm + Float_t deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1 + Float_t epsilSi = 1.0E-4; // .10000E+01; + Float_t stminSi = 0.0; // cm "Default value used" + + Float_t tmaxfdAir = 0.1; // .10000E+01; // Degree + Float_t stemaxAir = .10000E+01; // cm + Float_t deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1 + Float_t epsilAir = 1.0E-4; // .10000E+01; + Float_t stminAir = 0.0; // cm "Default value used" + + // AIR + Float_t aAir[4] = {12.0107, 14.0067, 15.9994, 39.948}; + Float_t zAir[4] = {6., 7., 8., 18.}; + Float_t wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827}; + Float_t dAir = 1.20479E-3; + + // Water + Float_t aWater[2] = {1.00794, 15.9994}; + Float_t zWater[2] = {1., 8.}; + Float_t wWater[2] = {0.111894, 0.888106}; + Float_t dWater = 1.0; + + // PEEK CF30 + Float_t aPEEK[3] = {12.0107, 1.00794, 15.9994}; + Float_t zPEEK[3] = {6., 1., 8.}; + Float_t wPEEK[3] = {19., 12., 3}; + Float_t dPEEK = 1.32; + + // Kapton + Float_t aKapton[4] = {1.00794, 12.0107, 14.010, 15.9994}; + Float_t zKapton[4] = {1., 6., 7., 8.}; + Float_t wKapton[4] = {0.026362, 0.69113, 0.07327, 0.209235}; + Float_t dKapton = 1.42; + + // Tungsten Carbide + Float_t aWC[2] = {183.84, 12.0107}; + Float_t zWC[2] = {74, 6}; + Float_t wWC[2] = {0.5, 0.5}; + Float_t dWC = 15.63; + + // BEOL (Metal interconnection stack in Si sensors) + Float_t aBEOL[3] = {26.982, 28.086, 15.999}; + Float_t zBEOL[3] = {13, 14, 8}; // Al, Si, O + Float_t wBEOL[3] = {0.170, 0.388, 0.442}; + Float_t dBEOL = 2.28; + + // Inox 304 + Float_t aInox304[4] = {12.0107, 51.9961, 58.6928, 55.845}; + Float_t zInox304[4] = {6., 24., 28, 26}; // C, Cr, Ni, Fe + Float_t wInox304[4] = {0.0003, 0.18, 0.10, 0}; // [3] will be computed + Float_t dInox304 = 7.85; + + // Ceramic (for IB capacitors) (BaTiO3) + Float_t aCeramic[3] = {137.327, 47.867, 15.999}; + Float_t zCeramic[3] = {56, 22, 8}; // Ba, Ti, O + Float_t wCeramic[3] = {1, 1, 3}; // Molecular composition + Float_t dCeramic = 6.02; + + // Rohacell (C9 H13 N1 O2) + Float_t aRohac[4] = {12.01, 1.01, 14.010, 16.}; + Float_t zRohac[4] = {6., 1., 7., 8.}; + Float_t wRohac[4] = {9., 13., 1., 2.}; + Float_t dRohac = 0.05; + + o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir); + o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir); + + o2::base::Detector::Mixture(2, "WATER$", aWater, zWater, dWater, 2, wWater); + o2::base::Detector::Medium(2, "WATER$", 2, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + o2::base::Detector::Material(3, "SI$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); + o2::base::Detector::Medium(3, "SI$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + + o2::base::Detector::Material(4, "BERILLIUM$", 9.01, 4., 1.848, 35.3, 36.7); // From AliPIPEv3 + o2::base::Detector::Medium(4, "BERILLIUM$", 4, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + o2::base::Detector::Material(5, "COPPER$", 0.63546E+02, 0.29000E+02, 0.89600E+01, 0.14300E+01, 0.99900E+03); + o2::base::Detector::Medium(5, "COPPER$", 5, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + // needed for STAVE , Carbon, kapton, Epoxy, flexcable + + // AliceO2::Base::Detector::Material(6,"CARBON$",12.0107,6,2.210,999,999); + o2::base::Detector::Material(6, "CARBON$", 12.0107, 6, 2.210 / 1.3, 999, 999); + o2::base::Detector::Medium(6, "CARBON$", 6, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + + o2::base::Detector::Mixture(7, "KAPTON(POLYCH2)$", aKapton, zKapton, dKapton, 4, wKapton); + o2::base::Detector::Medium(7, "KAPTON(POLYCH2)$", 7, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + // values below modified as compared to source AliITSv11 ! + + // BEOL (Metal interconnection stack in Si sensors) + o2::base::Detector::Mixture(29, "METALSTACK$", aBEOL, zBEOL, dBEOL, 3, wBEOL); + o2::base::Detector::Medium(29, "METALSTACK$", 29, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + // Glue between IB chip and FPC: density reduced to take into account + // empty spaces (160 glue spots/chip , diam. 1 spot = 1 mm) + o2::base::Detector::Material(30, "GLUE_IBFPC$", 12.011, 6, 1.05 * 0.3, 999, 999); + o2::base::Detector::Medium(30, "GLUE_IBFPC$", 30, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + // Ceramic for IB capacitors (nmat < 0 => wmat contains number of atoms) + o2::base::Detector::Mixture(31, "CERAMIC$", aCeramic, zCeramic, dCeramic, -3, wCeramic); + o2::base::Detector::Medium(31, "CERAMIC$", 31, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + // All types of carbon + // Unidirectional prepreg + o2::base::Detector::Material(8, "K13D2U2k$", 12.0107, 6, 1.643, 999, 999); + o2::base::Detector::Medium(8, "K13D2U2k$", 8, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + o2::base::Detector::Material(17, "K13D2U120$", 12.0107, 6, 1.583, 999, 999); + o2::base::Detector::Medium(17, "K13D2U120$", 17, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + // Carbon prepreg woven + o2::base::Detector::Material(18, "F6151B05M$", 12.0107, 6, 2.133, 999, 999); + o2::base::Detector::Medium(18, "F6151B05M$", 18, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + // Impregnated thread + o2::base::Detector::Material(9, "M60J3K$", 12.0107, 6, 2.21, 999, 999); + o2::base::Detector::Medium(9, "M60J3K$", 9, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + // Impregnated thread + o2::base::Detector::Material(10, "M55J6K$", 12.0107, 6, 1.63, 999, 999); + o2::base::Detector::Medium(10, "M55J6K$", 10, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + // Fabric(0/90) + o2::base::Detector::Material(11, "T300$", 12.0107, 6, 1.725, 999, 999); + o2::base::Detector::Medium(11, "T300$", 11, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + // AMEC Thermasol + o2::base::Detector::Material(12, "FGS003$", 12.0107, 6, 1.6, 999, 999); + o2::base::Detector::Medium(12, "FGS003$", 12, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + // Carbon fleece + o2::base::Detector::Material(13, "CarbonFleece$", 12.0107, 6, 0.4, 999, 999); + o2::base::Detector::Medium(13, "CarbonFleece$", 13, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, + stminSi); + // Rohacell + o2::base::Detector::Mixture(32, "ROHACELL$", aRohac, zRohac, dRohac, -4, wRohac); + o2::base::Detector::Medium(32, "ROHACELL$", 32, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + + // PEEK CF30 + o2::base::Detector::Mixture(19, "PEEKCF30$", aPEEK, zPEEK, dPEEK, -3, wPEEK); + o2::base::Detector::Medium(19, "PEEKCF30$", 19, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + + // Flex cable + Float_t aFCm[5] = {12.0107, 1.00794, 14.0067, 15.9994, 26.981538}; + Float_t zFCm[5] = {6., 1., 7., 8., 13.}; + Float_t wFCm[5] = {0.520088819984, 0.01983871336, 0.0551367996, 0.157399667056, 0.247536}; + // Float_t dFCm = 1.6087; // original + // Float_t dFCm = 2.55; // conform with STAR + Float_t dFCm = 2.595; // conform with Corrado + + o2::base::Detector::Mixture(14, "FLEXCABLE$", aFCm, zFCm, dFCm, 5, wFCm); + o2::base::Detector::Medium(14, "FLEXCABLE$", 14, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + // AliceO2::Base::Detector::Material(7,"GLUE$",0.12011E+02,0.60000E+01,0.1930E+01/2.015,999,999); + // // original + o2::base::Detector::Material(15, "GLUE$", 12.011, 6, 1.93 / 2.015, 999, 999); // conform with ATLAS, Corrado, Stefan + o2::base::Detector::Medium(15, "GLUE$", 15, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + o2::base::Detector::Material(16, "ALUMINUM$", 0.26982E+02, 0.13000E+02, 0.26989E+01, 0.89000E+01, 0.99900E+03); + o2::base::Detector::Medium(16, "ALUMINUM$", 16, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + + o2::base::Detector::Mixture(20, "TUNGCARB$", aWC, zWC, dWC, 2, wWC); + o2::base::Detector::Medium(20, "TUNGCARB$", 20, 0, ifield, fieldm, tmaxfd, stemax, deemaxSi, epsilSi, stminSi); + + wInox304[3] = 1. - wInox304[0] - wInox304[1] - wInox304[2]; + o2::base::Detector::Mixture(21, "INOX304$", aInox304, zInox304, dInox304, 4, wInox304); + o2::base::Detector::Medium(21, "INOX304$", 21, 0, ifield, fieldm, tmaxfd, stemax, deemaxSi, epsilSi, stminSi); + + // Tungsten (for gamma converter rods) + o2::base::Detector::Material(28, "TUNGSTEN$", 183.84, 74, 19.25, 999, 999); + o2::base::Detector::Medium(28, "TUNGSTEN$", 28, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); +} + +void Detector::EndOfEvent() { Reset(); } + +void Detector::Register() +{ + // This will create a branch in the output tree called Hit, setting the last + // parameter to kFALSE means that this collection will not be written to the file, + // it will exist only during the simulation + + if (FairRootManager::Instance()) { + FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE); + } +} + +void Detector::Reset() +{ + if (!o2::utils::ShmManager::Instance().isOperational()) { + mHits->clear(); + } +} + +void Detector::defineWrapperVolume(Int_t id, Double_t rmin, Double_t rmax, Double_t zspan) +{ + // set parameters of id-th wrapper volume + if (id >= sNumberOfWrapperVolumes || id < 0) { + LOG(FATAL) << "id " << id << " of wrapper volume is not in 0-" << sNumberOfWrapperVolumes - 1 << " range"; + } + + mWrapperMinRadius[id] = rmin; + mWrapperMaxRadius[id] = rmax; + mWrapperZSpan[id] = zspan; +} + +void Detector::defineLayer(Int_t nlay, double phi0, Double_t r, Int_t nstav, Int_t nunit, Double_t lthick, + Double_t dthick, UInt_t dettypeID, Int_t buildLevel) +{ + // Sets the layer parameters + // Inputs: + // nlay layer number + // phi0 layer phi0 + // r layer radius + // nstav number of staves + // nunit IB: number of chips per stave + // OB: number of modules per half stave + // lthick stave thickness (if omitted, defaults to 0) + // dthick detector thickness (if omitted, defaults to 0) + // dettypeID ?? + // buildLevel (if 0, all geometry is build, used for material budget studies) + // Outputs: + // none. + // Return: + // none. + + LOG(INFO) << "L# " << nlay << " Phi:" << phi0 << " R:" << r << " Nst:" << nstav << " Nunit:" << nunit + << " Lthick:" << lthick << " Dthick:" << dthick << " DetID:" << dettypeID << " B:" << buildLevel; + + if (nlay >= mTotalNumberOfLayers || nlay < 0) { + LOG(ERROR) << "Wrong layer number " << nlay; + return; + } + + mTurboLayer[nlay] = kFALSE; + mLayerPhi0[nlay] = phi0; + mLayerRadii[nlay] = r; + mStavePerLayer[nlay] = nstav; + mUnitPerStave[nlay] = nunit; + mChipThickness[nlay] = lthick; + mDetectorThickness[nlay] = dthick; + mChipTypeID[nlay] = dettypeID; + mBuildLevel[nlay] = buildLevel; +} + +void Detector::defineInnerLayerITS4(Int_t nlay, Double_t r, Double_t zlen, + Double_t dthick, UInt_t dettypeID, Int_t buildLevel) +{ + // Sets the layer parameters + // Inputs: + // nlay layer number + // r layer radius + // zlen layer length + // dthick detector thickness (if omitted, defaults to 0) + // dettypeID ?? + // buildLevel (if 0, all geometry is build, used for material budget studies) + // Outputs: + // none. + // Return: + // none. + + LOG(INFO) << "L# " << nlay << " with ITS4 geo R:" << r + << " Dthick:" << dthick << " DetID:" << dettypeID << " B:" << buildLevel; + + if (nlay >= mTotalNumberOfLayers || nlay < 0) { + LOG(ERROR) << "Wrong layer number " << nlay; + return; + } + + mTurboLayer[nlay] = kFALSE; + mITS4Layer[nlay] = kTRUE; + mLayerRadii[nlay] = r; + mLayerZLen[nlay] = zlen; + mDetectorThickness[nlay] = dthick; + mChipTypeID[nlay] = dettypeID; + mBuildLevel[nlay] = buildLevel; + LOG(INFO) << "Added layer: " << nlay << std::endl; +} + +void Detector::getLayerParameters(Int_t nlay, Double_t& phi0, Double_t& r, Int_t& nstav, Int_t& nmod, Double_t& width, + Double_t& tilt, Double_t& lthick, Double_t& dthick, UInt_t& dettype) const +{ + // Gets the layer parameters + // Inputs: + // nlay layer number + // Outputs: + // phi0 phi of 1st stave + // r layer radius + // nstav number of staves + // nmod IB: number of chips per stave + // OB: number of modules per half stave + // width stave width + // tilt stave tilt angle + // lthick stave thickness + // dthick detector thickness + // dettype detector type + // Return: + // none. + + if (nlay >= mTotalNumberOfLayers || nlay < 0) { + LOG(ERROR) << "Wrong layer number " << nlay; + return; + } + + phi0 = mLayerPhi0[nlay]; + r = mLayerRadii[nlay]; + nstav = mStavePerLayer[nlay]; + nmod = mUnitPerStave[nlay]; + width = mStaveWidth[nlay]; + tilt = mStaveTilt[nlay]; + lthick = mChipThickness[nlay]; + dthick = mDetectorThickness[nlay]; + dettype = mChipTypeID[nlay]; +} + +TGeoVolume* Detector::createWrapperVolume(Int_t id) +{ + // Creates an air-filled wrapper cylindrical volume + // For OB a Pcon is needed to host the support rings + // while avoiding overlaps with MFT structures and OB cones + + const Double_t suppRingAZlen = 4.; + const Double_t coneRingARmax = 33.96; + const Double_t coneRingAZlen = 5.6; + const Double_t suppRingCZlen[3] = {4.8, 4.0, 2.4}; + const Double_t suppRingsRmin[3] = {23.35, 20.05, 35.4}; + + if (mWrapperMinRadius[id] < 0 || mWrapperMaxRadius[id] < 0 || mWrapperZSpan[id] < 0) { + LOG(FATAL) << "Wrapper volume " << id << " was requested but not defined"; + } + + // Now create the actual shape and volume + TGeoShape* tube; + Double_t zlen; + switch (id) { + case 0: // IB Layer 0,1,2: simple cylinder + { + TGeoTube* wrap = new TGeoTube(mWrapperMinRadius[id], mWrapperMaxRadius[id], mWrapperZSpan[id] / 2.); + tube = (TGeoShape*)wrap; + } break; + case 1: // MB Layer 3,4: complex Pcon to avoid MFT overlaps + { + TGeoPcon* wrap = new TGeoPcon(0, 360, 6); + zlen = mWrapperZSpan[id] / 2 + suppRingCZlen[0]; + wrap->DefineSection(0, -zlen, suppRingsRmin[0], mWrapperMaxRadius[id]); + zlen = mWrapperZSpan[id] / 2 + suppRingCZlen[1]; + wrap->DefineSection(1, -zlen, suppRingsRmin[0], mWrapperMaxRadius[id]); + wrap->DefineSection(2, -zlen, suppRingsRmin[1], mWrapperMaxRadius[id]); + wrap->DefineSection(3, -mWrapperZSpan[id] / 2., suppRingsRmin[1], mWrapperMaxRadius[id]); + wrap->DefineSection(4, -mWrapperZSpan[id] / 2., mWrapperMinRadius[id], mWrapperMaxRadius[id]); + zlen = mWrapperZSpan[id] / 2 + suppRingAZlen; + wrap->DefineSection(5, zlen, mWrapperMinRadius[id], mWrapperMaxRadius[id]); + tube = (TGeoShape*)wrap; + } break; + case 2: // OB Layer 5,6: simpler Pcon to avoid OB cones overlaps + { + TGeoPcon* wrap = new TGeoPcon(0, 360, 6); + zlen = mWrapperZSpan[id] / 2; + wrap->DefineSection(0, -zlen, suppRingsRmin[2], mWrapperMaxRadius[id]); + zlen -= suppRingCZlen[2]; + wrap->DefineSection(1, -zlen, suppRingsRmin[2], mWrapperMaxRadius[id]); + wrap->DefineSection(2, -zlen, mWrapperMinRadius[id], mWrapperMaxRadius[id]); + zlen = mWrapperZSpan[id] / 2 - coneRingAZlen; + wrap->DefineSection(3, zlen, mWrapperMinRadius[id], mWrapperMaxRadius[id]); + wrap->DefineSection(4, zlen, coneRingARmax, mWrapperMaxRadius[id]); + wrap->DefineSection(5, mWrapperZSpan[id] / 2, coneRingARmax, mWrapperMaxRadius[id]); + tube = (TGeoShape*)wrap; + } break; + default: // Can never happen, keeps gcc quiet + break; + } + + TGeoMedium* medAir = gGeoManager->GetMedium("IT4_AIR$"); + + char volnam[30]; + snprintf(volnam, 29, "%s%d", GeometryTGeo::getITSWrapVolPattern(), id); + + auto* wrapper = new TGeoVolume(volnam, tube, medAir); + + return wrapper; +} + +void Detector::ConstructGeometry() +{ + // Create the detector materials + createMaterials(); + // Construct the detector geometry + constructDetectorGeometry(); +} + +void Detector::constructDetectorGeometry() +{ + // Create the geometry and insert it in the mother volume ITSV + TGeoManager* geoManager = gGeoManager; + + TGeoVolume* vALIC = geoManager->GetVolume("barrel"); + + if (!vALIC) { + LOG(FATAL) << "Could not find the top volume"; + } + new TGeoVolumeAssembly(GeometryTGeo::getITSVolPattern()); + TGeoVolume* vITSV = geoManager->GetVolume(GeometryTGeo::getITSVolPattern()); + vALIC->AddNode(vITSV, 2, new TGeoTranslation(0, 30., 0)); // Copy number is 2 to cheat AliGeoManager::CheckSymNamesLUT + + const Int_t kLength = 100; + Char_t vstrng[kLength] = "xxxRS"; //? + vITSV->SetTitle(vstrng); + + // Check that we have all needed parameters + for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { + if (mLayerRadii[j] <= 0) { + LOG(FATAL) << "Wrong layer radius for layer " << j << "(" << mLayerRadii[j] << ")"; + } + if (mStavePerLayer[j] <= 0 && !mITS4Layer[j]) { + LOG(FATAL) << "Wrong number of staves for layer " << j << "(" << mStavePerLayer[j] << ")"; + } + if (mUnitPerStave[j] <= 0 && !mITS4Layer[j]) { + LOG(FATAL) << "Wrong number of chips for layer " << j << "(" << mUnitPerStave[j] << ")"; + } + if (mChipThickness[j] < 0 && !mITS4Layer[j]) { + LOG(FATAL) << "Wrong chip thickness for layer " << j << "(" << mChipThickness[j] << ")"; + } + if (mTurboLayer[j] && mStaveWidth[j] <= 0) { + LOG(FATAL) << "Wrong stave width for layer " << j << "(" << mStaveWidth[j] << ")"; + } + if (mDetectorThickness[j] < 0) { + LOG(FATAL) << "Wrong Sensor thickness for layer " << j << "(" << mDetectorThickness[j] << ")"; + } + + if (j > 0 && // Always check IB, check OB only if present + ((j < mNumberOfInnerLayers) || mCreateOuterBarrel)) { + if (mLayerRadii[j] <= mLayerRadii[j - 1]) { + LOG(FATAL) << "Layer " << j << " radius (" << mLayerRadii[j] << ") is smaller than layer " << j - 1 + << " radius (" << mLayerRadii[j - 1] << ")"; + } + } + + if (mChipThickness[j] == 0 && !mITS4Layer[j]) { + LOG(INFO) << "Chip thickness for layer " << j << " not set, using default"; + } + } + + // Create the wrapper volumes + TGeoVolume** wrapVols = nullptr; + + if (sNumberOfWrapperVolumes && mCreateOuterBarrel) { + wrapVols = new TGeoVolume*[sNumberOfWrapperVolumes]; + for (int id = 1; id < sNumberOfWrapperVolumes; id++) { + wrapVols[id] = createWrapperVolume(id); + vITSV->AddNode(wrapVols[id], 1, nullptr); + } + } + if (!mCreateOuterBarrel) + mTotalNumberOfLayers = mNumberOfInnerLayers; + + // Now create the actual geometry + for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { + TGeoVolume* dest = vITSV; + mWrapperLayerId[j] = -1; + + if (mTurboLayer[j]) { + mGeometry[j] = new V3Layer(j, kTRUE, kFALSE); + mGeometry[j]->setStaveWidth(mStaveWidth[j]); + mGeometry[j]->setStaveTilt(mStaveTilt[j]); + } else { + mGeometry[j] = new V3Layer(j, kFALSE); + } + + mGeometry[j]->setNumberOfInnerLayers(mNumberOfInnerLayers); + + if (mITS4Layer[j]) { + mGeometry[j]->setIsITS4(kTRUE); + mGeometry[j]->setIBModuleZLength(mLayerZLen[j]); + } + + mGeometry[j]->setPhi0(mLayerPhi0[j]); + mGeometry[j]->setRadius(mLayerRadii[j]); + mGeometry[j]->setNumberOfStaves(mStavePerLayer[j]); + mGeometry[j]->setNumberOfUnits(mUnitPerStave[j]); + mGeometry[j]->setChipType(mChipTypeID[j]); + mGeometry[j]->setBuildLevel(mBuildLevel[j]); + + if (j < mNumberOfInnerLayers) { + mGeometry[j]->setStaveModel(mStaveModelInnerBarrel); + } else { + mGeometry[j]->setStaveModel(mStaveModelOuterBarrel); + } + + LOG(DEBUG1) << "mBuildLevel: " << mBuildLevel[j]; + + if (mChipThickness[j] != 0) { + mGeometry[j]->setChipThick(mChipThickness[j]); + } + if (mDetectorThickness[j] != 0) { + mGeometry[j]->setSensorThick(mDetectorThickness[j]); + } + + if (mCreateOuterBarrel && j >= mNumberOfInnerLayers) + for (int iw = 0; iw < sNumberOfWrapperVolumes; iw++) { + if (mLayerRadii[j] > mWrapperMinRadius[iw] && mLayerRadii[j] < mWrapperMaxRadius[iw]) { + LOG(DEBUG) << "Will embed layer " << j << " in wrapper volume " << iw; + + dest = wrapVols[iw]; + mWrapperLayerId[j] = iw; + break; + } + } + mGeometry[j]->createLayer(dest); + } + + // Finally create the services + mServicesGeometry = new V3Services(); + + // createInnerBarrelServices(wrapVols[0]); + // createMiddlBarrelServices(wrapVols[1]); + // createOuterBarrelServices(wrapVols[2]); + // createOuterBarrelSupports(vITSV); + + // TEMPORARY - These routines will be obsoleted once the new services are completed - TEMPORARY + // createServiceBarrel(kTRUE, wrapVols[0]); + // createServiceBarrel(kFALSE, wrapVols[2]); + delete[] wrapVols; // delete pointer only, not the volumes +} + +void Detector::createInnerBarrelServices(TGeoVolume* motherVolume) +{ + // + // Creates the Inner Barrel Service structures + // + // Input: + // motherVolume : the volume hosting the services + // + // Output: + // + // Return: + // + // Created: 15 May 2019 Mario Sitta + // (partially based on P.Namwongsa implementation in AliRoot) + // Updated: 19 Jun 2019 Mario Sitta IB Side A added + // Updated: 21 Oct 2019 Mario Sitta CYSS added + // + + // Create the End Wheels on Side A + TGeoVolume* endWheelsA = mServicesGeometry->createIBEndWheelsSideA(); + + motherVolume->AddNode(endWheelsA, 1, nullptr); + + // Create the End Wheels on Side C + TGeoVolume* endWheelsC = mServicesGeometry->createIBEndWheelsSideC(); + + motherVolume->AddNode(endWheelsC, 1, nullptr); + + // Create the CYSS Assembly (i.e. the supporting half cylinder and cone) + TGeoVolume* cyss = mServicesGeometry->createCYSSAssembly(); + + motherVolume->AddNode(cyss, 1, nullptr); +} + +void Detector::createMiddlBarrelServices(TGeoVolume* motherVolume) +{ + // + // Creates the Middle Barrel Service structures + // + // Input: + // motherVolume : the volume hosting the services + // + // Output: + // + // Return: + // + // Created: 24 Sep 2019 Mario Sitta + // + + // Create the End Wheels on Side A + mServicesGeometry->createMBEndWheelsSideA(motherVolume); + + // Create the End Wheels on Side C + mServicesGeometry->createMBEndWheelsSideC(motherVolume); +} + +void Detector::createOuterBarrelServices(TGeoVolume* motherVolume) +{ + // + // Creates the Outer Barrel Service structures + // + // Input: + // motherVolume : the volume hosting the services + // + // Output: + // + // Return: + // + // Created: 27 Sep 2019 Mario Sitta + // + + // Create the End Wheels on Side A + mServicesGeometry->createOBEndWheelsSideA(motherVolume); + + // Create the End Wheels on Side C + mServicesGeometry->createOBEndWheelsSideC(motherVolume); +} + +void Detector::createOuterBarrelSupports(TGeoVolume* motherVolume) +{ + // + // Creates the Outer Barrel Service structures + // + // Input: + // motherVolume : the volume hosting the supports + // + // Output: + // + // Return: + // + // Created: 26 Jan 2020 Mario Sitta + // + + // Create the Cone on Side A + mServicesGeometry->createOBConeSideA(motherVolume); + + // Create the Cone on Side C + mServicesGeometry->createOBConeSideC(motherVolume); +} + +// Service Barrel +void Detector::createServiceBarrel(const Bool_t innerBarrel, TGeoVolume* dest, const TGeoManager* mgr) +{ + // Creates the Service Barrel (as a simple cylinder) for IB and OB + // Inputs: + // innerBarrel : if true, build IB service barrel, otherwise for OB + // dest : the mother volume holding the service barrel + // mgr : the gGeoManager pointer (used to get the material) + // + + Double_t rminIB = 4.7; + Double_t rminOB = 43.9; + Double_t zLenOB; + Double_t cInt = 0.22; // dimensioni cilindro di supporto interno + Double_t cExt = 1.00; // dimensioni cilindro di supporto esterno + // Double_t phi1 = 180; + // Double_t phi2 = 360; + + TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + + if (innerBarrel) { + zLenOB = ((TGeoTube*)(dest->GetShape()))->GetDz(); + // TGeoTube*ibSuppSh = new TGeoTubeSeg(rminIB,rminIB+cInt,zLenOB,phi1,phi2); + auto* ibSuppSh = new TGeoTube(rminIB, rminIB + cInt, zLenOB); + auto* ibSupp = new TGeoVolume("ibSuppCyl", ibSuppSh, medCarbonFleece); + dest->AddNode(ibSupp, 1); + } else { + zLenOB = ((TGeoTube*)(dest->GetShape()))->GetDz(); + auto* obSuppSh = new TGeoTube(rminOB, rminOB + cExt, zLenOB); + auto* obSupp = new TGeoVolume("obSuppCyl", obSuppSh, medCarbonFleece); + dest->AddNode(obSupp, 1); + } + + return; +} + +void Detector::addAlignableVolumes() const +{ + // + // Creates entries for alignable volumes associating the symbolic volume + // name with the corresponding volume path. + // + // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot) + // + + LOG(INFO) << "Add ITS alignable volumes"; + + if (!gGeoManager) { + LOG(FATAL) << "TGeoManager doesn't exist !"; + return; + } + + TString path = Form("/cave_1/barrel_1/%s_2", GeometryTGeo::getITSVolPattern()); + TString sname = GeometryTGeo::composeSymNameITS4(); + + LOG(DEBUG) << sname << " <-> " << path; + + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + + Int_t lastUID = 0; + for (Int_t lr = 0; lr < mTotalNumberOfLayers; lr++) + addAlignableVolumesLayer(lr, path, lastUID); + + return; +} + +void Detector::addAlignableVolumesLayer(int lr, TString& parent, Int_t& lastUID) const +{ + // + // Add alignable volumes for a Layer and its daughters + // + // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot) + // + + TString wrpV = + mWrapperLayerId[lr] != -1 ? Form("%s%d_1", GeometryTGeo::getITSWrapVolPattern(), mWrapperLayerId[lr]) : ""; + TString path; + if (mCreateOuterBarrel && (lr >= mNumberOfInnerLayers)) { + path = Form("%s/%s/%s%d_1", parent.Data(), wrpV.Data(), GeometryTGeo::getITSLayerPattern(), lr); + } else { + path = Form("%s/%s%d_1", parent.Data(), GeometryTGeo::getITSLayerPattern(), lr); + } + TString sname = GeometryTGeo::composeSymNameLayer(lr); + + LOG(DEBUG) << "Add " << sname << " <-> " << path; + + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + + const V3Layer* lrobj = mGeometry[lr]; + Int_t nstaves = lrobj->getNumberOfStavesPerParent(); + for (int st = 0; st < nstaves; st++) + addAlignableVolumesStave(lr, st, path, lastUID); + + return; +} + +void Detector::addAlignableVolumesStave(Int_t lr, Int_t st, TString& parent, Int_t& lastUID) const +{ + // + // Add alignable volumes for a Stave and its daughters + // + // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot) + // + TString path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSStavePattern(), lr, st); + TString sname = GeometryTGeo::composeSymNameStave(lr, st); + + LOG(DEBUG) << "Add " << sname << " <-> " << path; + + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + + const V3Layer* lrobj = mGeometry[lr]; + Int_t nhstave = lrobj->getNumberOfHalfStavesPerParent(); + Int_t start = nhstave > 0 ? 0 : -1; + for (Int_t sst = start; sst < nhstave; sst++) + addAlignableVolumesHalfStave(lr, st, sst, path, lastUID); + + return; +} + +void Detector::addAlignableVolumesHalfStave(Int_t lr, Int_t st, Int_t hst, TString& parent, Int_t& lastUID) const +{ + // + // Add alignable volumes for a HalfStave (if any) and its daughters + // + // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot) + // + + TString path = parent; + if (hst >= 0) { + path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSHalfStavePattern(), lr, hst); + TString sname = GeometryTGeo::composeSymNameHalfStave(lr, st, hst); + + LOG(DEBUG) << "Add " << sname << " <-> " << path; + + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } + + const V3Layer* lrobj = mGeometry[lr]; + Int_t nmodules = lrobj->getNumberOfModulesPerParent(); + Int_t start = nmodules > 0 ? 0 : -1; + for (Int_t md = start; md < nmodules; md++) + addAlignableVolumesModule(lr, st, hst, md, path, lastUID); + + return; +} + +void Detector::addAlignableVolumesModule(Int_t lr, Int_t st, Int_t hst, Int_t md, TString& parent, Int_t& lastUID) const +{ + // + // Add alignable volumes for a Module (if any) and its daughters + // + // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot) + // + + TString path = parent; + if (md >= 0) { + path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSModulePattern(), lr, md); + TString sname = GeometryTGeo::composeSymNameModule(lr, st, hst, md); + + LOG(DEBUG) << "Add " << sname << " <-> " << path; + + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } + + const V3Layer* lrobj = mGeometry[lr]; + Int_t nchips = lrobj->getNumberOfChipsPerParent(); + for (Int_t ic = 0; ic < nchips; ic++) + addAlignableVolumesChip(lr, st, hst, md, ic, path, lastUID); + + return; +} + +void Detector::addAlignableVolumesChip(Int_t lr, Int_t st, Int_t hst, Int_t md, Int_t ch, TString& parent, + Int_t& lastUID) const +{ + // + // Add alignable volumes for a Chip + // + // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot) + // + + TString path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSChipPattern(), lr, ch); + TString sname = GeometryTGeo::composeSymNameChip(lr, st, hst, md, ch); + Int_t modUID = chipVolUID(lastUID++); + + LOG(DEBUG) << "Add " << sname << " <-> " << path; + + if (!gGeoManager->SetAlignableEntry(sname, path.Data(), modUID)) + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + + return; +} + +void Detector::defineSensitiveVolumes() +{ + TGeoManager* geoManager = gGeoManager; + TGeoVolume* v; + + TString volumeName; + + // The names of the ITS sensitive volumes have the format: ITSUSensor(0...sNumberLayers-1) + for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { + volumeName = GeometryTGeo::getITSSensorPattern() + TString::Itoa(j, 10); + v = geoManager->GetVolume(volumeName.Data()); + AddSensitiveVolume(v); + } +} + +Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos, + const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus, + unsigned char endStatus) +{ + mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus); + return &(mHits->back()); +} + +void Detector::Print(std::ostream* os) const +{ + // Standard output format for this class. + // Inputs: + // ostream *os The output stream + // Outputs: + // none. + // Return: + // none. + +#if defined __GNUC__ +#if __GNUC__ > 2 + std::ios::fmtflags fmt; +#else + Int_t fmt; +#endif +#else +#if defined __ICC || defined __ECC || defined __xlC__ + ios::fmtflags fmt; +#else + Int_t fmt; +#endif +#endif + // RS: why do we need to pring this garbage? + + // fmt = os->setf(std::ios::scientific); // set scientific floating point output + // fmt = os->setf(std::ios::hex); // set hex for mStatus only. + // fmt = os->setf(std::ios::dec); // every thing else decimel. + // *os << mModule << " "; + // *os << mEnergyDepositionStep << " " << mTof; + // *os << " " << mStartingStepX << " " << mStartingStepY << " " << mStartingStepZ; + // *os << " " << endl; + // os->flags(fmt); // reset back to old formating. + return; +} + +void Detector::Read(std::istream* is) +{ + // Standard input format for this class. + // Inputs: + // istream *is the input stream + // Outputs: + // none. + // Return: + // none. + // RS no need to read garbage + return; +} + +std::ostream& operator<<(std::ostream& os, Detector& p) +{ + // Standard output streaming function. + // Inputs: + // ostream os The output stream + // Detector p The his to be printed out + // Outputs: + // none. + // Return: + // The input stream + + p.Print(&os); + return os; +} + +std::istream& operator>>(std::istream& is, Detector& r) +{ + // Standard input streaming function. + // Inputs: + // istream is The input stream + // Detector p The Detector class to be filled from this input stream + // Outputs: + // none. + // Return: + // The input stream + + r.Read(&is); + return is; +} + +ClassImp(o2::its4::Detector); diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h b/Detectors/Upgrades/PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h new file mode 100644 index 0000000000000..b880f7208f756 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h @@ -0,0 +1,24 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::its4::V11Geometry + ; +#pragma link C++ class o2::its4::V1Layer + ; +#pragma link C++ class o2::its4::V3Layer + ; +#pragma link C++ class o2::its4::V3Services + ; +#pragma link C++ class o2::its4::Detector + ; +#pragma link C++ class o2::base::DetImpl < o2::its4::Detector> + ; + +#endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V11Geometry.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V11Geometry.cxx new file mode 100644 index 0000000000000..ce89b44ada297 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V11Geometry.cxx @@ -0,0 +1,1229 @@ +// 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 V11Geometry.cxx +/// \brief Implementation of the V11Geometry class + +#include "ITS4Simulation/V11Geometry.h" + +#include "FairLogger.h" // for LOG + +#include <TArc.h> // for TArc +#include <TArrow.h> // for TArrow +#include <TCanvas.h> // for TCanvas +#include <TGeoArb8.h> // for TGeoArb8 +#include <TGeoElement.h> // for TGeoElement +#include <TGeoMaterial.h> // for TGeoMixture, TGeoMaterial, etc +#include <TGeoPcon.h> // for TGeoPcon +#include <TGeoCone.h> // for TGeoConSeg +#include <TLine.h> // for TLine +#include <TPolyLine.h> // for TPolyLine +#include <TPolyMarker.h> // for TPolyMarker +#include <TText.h> // for TText +#include "TMath.h" // for DegToRad, Cos, Sqrt, ATan2, Sin, Tan, Pi, etc +#include "TMathBase.h" // for Max, Min, Abs +#include <TGeoTube.h> // for TGeoTubeSeg + +#include <cstdio> // for printf, snprintf +#include <Riostream.h> + +using std::cin; +using std::cout; +using std::endl; + +using namespace o2::its4; + +ClassImp(o2::its4::V11Geometry); + +const Double_t V11Geometry::sMicron = 1.0E-4; +const Double_t V11Geometry::sMm = 0.10; +const Double_t V11Geometry::sCm = 1.00; +const Double_t V11Geometry::sDegree = 1.0; +const Double_t V11Geometry::sRadian = 180. / 3.14159265358979323846; +const Double_t V11Geometry::sGCm3 = 1.0; // assume default is g/cm^3 +const Double_t V11Geometry::sKgm3 = 1.0E+3; // assume Kg/m^3 +const Double_t V11Geometry::sKgdm3 = 1.0; // assume Kg/dm^3 +const Double_t V11Geometry::sCelsius = 1.0; // Assume default is C +const Double_t V11Geometry::sPascal = 1.0E-3; // Assume kPascal +const Double_t V11Geometry::sKPascal = 1.0; // Asume kPascal +const Double_t V11Geometry::sEV = 1.0E-9; // GeV default +const Double_t V11Geometry::sKEV = 1.0e-6; // GeV default +const Double_t V11Geometry::sMEV = 1.0e-3; // GeV default +const Double_t V11Geometry::sGEV = 1.0; // GeV default + +void V11Geometry::intersectLines(Double_t m, Double_t x0, Double_t y0, Double_t n, Double_t x1, + Double_t y1, Double_t& xi, Double_t& yi) const +{ + if (TMath::Abs(m - n) < 0.000001) { + LOG(ERROR) << "Lines are parallel: m = " << m << " n = " << n; + return; + } + + xi = (y1 - n * x1 - y0 + m * x0) / (m - n); + yi = y0 + m * (xi - x0); + + return; +} + +Bool_t V11Geometry::intersectCircle(Double_t m, Double_t x0, Double_t y0, Double_t rr, Double_t xc, + Double_t yc, Double_t& xi1, Double_t& yi1, Double_t& xi2, + Double_t& yi2) +{ + Double_t p = m * x0 - y0; + Double_t q = m * m + 1; + + p = p - m * xc + yc; + + Double_t delta = m * m * p * p - q * (p * p - rr * rr); + + if (delta < 0) { + return kFALSE; + } else { + Double_t root = TMath::Sqrt(delta); + xi1 = (m * p + root) / q + xc; + xi2 = (m * p - root) / q + xc; + yi1 = m * (xi1 - x0) + y0; + yi2 = m * (xi2 - x0) + y0; + return kTRUE; + } +} + +Double_t V11Geometry::yFrom2Points(Double_t x0, Double_t y0, Double_t x1, Double_t y1, Double_t x) + const +{ + if (x0 == x1 && y0 == y1) { + printf( + "Error: V11Geometry::Yfrom2Ponts The two points are " + "the same (%e,%e) and (%e,%e)", + x0, y0, x1, y1); + return 0.0; + } // end if + if (x0 == x1) { + printf( + "Warning: V11Geometry::yFrom2Points x0=%e == x1=%e. " + "line vertical " + "returning mean y", + x0, x1); + return 0.5 * (y0 + y1); + } // end if x0==x1 + Double_t m = (y0 - y1) / (x0 - x1); + return m * (x - x0) + y0; +} + +Double_t V11Geometry::xFrom2Points(Double_t x0, Double_t y0, Double_t x1, Double_t y1, Double_t y) + const +{ + if (x0 == x1 && y0 == y1) { + printf( + "Error: V11Geometry::Yfrom2Ponts The two points are " + "the same (%e,%e) and (%e,%e)", + x0, y0, x1, y1); + return 0.0; + } // end if + if (y0 == y1) { + printf( + "Warrning: V11Geometry::yFrom2Points y0=%e == y1=%e. " + "line horizontal returning mean x", + y0, y1); + return 0.5 * (x0 + x1); + } // end if y0==y1 + Double_t m = (x0 - x1) / (y0 - y1); + return m * (y - y0) + x0; +} + +Double_t V11Geometry::rMaxFrom2Points(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t z) const +{ + Double_t d0, d1, d2, r; + + d0 = p->GetRmax(i1) - p->GetRmax(i2); // cout <<"L263: d0="<<d0<<endl; + d1 = z - p->GetZ(i2); // cout <<"L264: d1="<<d1<<endl; + d2 = p->GetZ(i1) - p->GetZ(i2); // cout <<"L265: d2="<<d2<<endl; + r = p->GetRmax(i2) + d1 * d0 / d2; // cout <<"L266: r="<<r<<endl; + return r; +} + +Double_t V11Geometry::rMinFrom2Points(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t z) const +{ + return p->GetRmin(i2) + + (p->GetRmin(i1) - p->GetRmin(i2)) * (z - p->GetZ(i2)) / (p->GetZ(i1) - p->GetZ(i2)); +} + +Double_t V11Geometry::rFrom2Points(const Double_t* p, const Double_t* az, Int_t i1, Int_t i2, + Double_t z) const +{ + return p[i2] + (p[i1] - p[i2]) * (z - az[i2]) / (az[i1] - az[i2]); +} + +Double_t V11Geometry::zFrom2MinPoints(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t r) const +{ + return p->GetZ(i2) + + (p->GetZ(i1) - p->GetZ(i2)) * (r - p->GetRmin(i2)) / (p->GetRmin(i1) - p->GetRmin(i2)); +} + +Double_t V11Geometry::zFrom2MaxPoints(const TGeoPcon* p, Int_t i1, Int_t i2, Double_t r) const +{ + return p->GetZ(i2) + + (p->GetZ(i1) - p->GetZ(i2)) * (r - p->GetRmax(i2)) / (p->GetRmax(i1) - p->GetRmax(i2)); +} + +Double_t V11Geometry::zFrom2Points(const Double_t* z, const Double_t* ar, Int_t i1, Int_t i2, + Double_t r) const +{ + return z[i2] + (z[i1] - z[i2]) * (r - ar[i2]) / (ar[i1] - ar[i2]); +} + +Double_t V11Geometry::rMaxFromZpCone(const TGeoPcon* p, int ip, Double_t tc, Double_t z, + Double_t th) const +{ + Double_t tantc = TMath::Tan(tc * TMath::DegToRad()); + Double_t costc = TMath::Cos(tc * TMath::DegToRad()); + + return -tantc * (z - p->GetZ(ip)) + p->GetRmax(ip) + th / costc; +} + +Double_t V11Geometry::rFromZpCone(const Double_t* ar, const Double_t* az, int ip, Double_t tc, + Double_t z, Double_t th) const +{ + Double_t tantc = TMath::Tan(tc * TMath::DegToRad()); + Double_t costc = TMath::Cos(tc * TMath::DegToRad()); + + return -tantc * (z - az[ip]) + ar[ip] + th / costc; +} + +Double_t V11Geometry::rMinFromZpCone(const TGeoPcon* p, Int_t ip, Double_t tc, Double_t z, + Double_t th) const +{ + Double_t tantc = TMath::Tan(tc * TMath::DegToRad()); + Double_t costc = TMath::Cos(tc * TMath::DegToRad()); + + return -tantc * (z - p->GetZ(ip)) + p->GetRmin(ip) + th / costc; +} + +Double_t V11Geometry::zFromRMaxpCone(const TGeoPcon* p, int ip, Double_t tc, Double_t r, + Double_t th) const +{ + Double_t tantc = TMath::Tan(tc * TMath::DegToRad()); + Double_t costc = TMath::Cos(tc * TMath::DegToRad()); + + return p->GetZ(ip) + (p->GetRmax(ip) + th / costc - r) / tantc; +} + +Double_t V11Geometry::zFromRMaxpCone(const Double_t* ar, const Double_t* az, int ip, Double_t tc, + Double_t r, Double_t th) const +{ + Double_t tantc = TMath::Tan(tc * TMath::DegToRad()); + Double_t costc = TMath::Cos(tc * TMath::DegToRad()); + + return az[ip] + (ar[ip] + th / costc - r) / tantc; +} + +Double_t V11Geometry::zFromRMinpCone(const TGeoPcon* p, int ip, Double_t tc, Double_t r, + Double_t th) const +{ + Double_t tantc = TMath::Tan(tc * TMath::DegToRad()); + Double_t costc = TMath::Cos(tc * TMath::DegToRad()); + + return p->GetZ(ip) + (p->GetRmin(ip) + th / costc - r) / tantc; +} + +void V11Geometry::radiusOfCurvature(Double_t rc, Double_t theta0, Double_t z0, Double_t r0, + Double_t theta1, Double_t& z1, Double_t& r1) const +{ + z1 = rc * (TMath::Sin(theta1 * TMath::DegToRad()) - TMath::Sin(theta0 * TMath::DegToRad())) + z0; + r1 = rc * (TMath::Cos(theta1 * TMath::DegToRad()) - TMath::Cos(theta0 * TMath::DegToRad())) + r0; + return; +} + +void V11Geometry::insidePoint(const TGeoPcon* p, Int_t i1, Int_t i2, Int_t i3, Double_t c, + TGeoPcon* q, Int_t j1, Bool_t max) const +{ + Double_t x0, y0, x1, y1, x2, y2, x, y; + + if (max) { + c = -c; // cout <<"L394 c="<<c<<endl; + y0 = p->GetRmax(i1); + if (i1 == i2) { + y0 = p->GetRmin(i1); // cout <<"L396 y0="<<y0<<endl; + } + y1 = p->GetRmax(i2); // cout <<"L397 y1="<<y1<<endl; + y2 = p->GetRmax(i3); // cout <<"L398 y2="<<y2<<endl; + if (i2 == i3) { + y2 = p->GetRmin(i3); // cout <<"L399 y2="<<y2<<endl; + } + } else { // min + y0 = p->GetRmin(i1); // cout <<"L401 y0="<<y0<<endl; + y1 = p->GetRmin(i2); // cout <<"L402 y1="<<y1<<endl; + y2 = p->GetRmin(i3); + + if (i2 == i3) { + y2 = p->GetRmax(i3); // cout <<"L404 y2="<<y2<<endl; + } + } // end if + x0 = p->GetZ(i1); // cout <<"L406 x0="<<x0<<endl; + x1 = p->GetZ(i2); // cout <<"L407 x1="<<x1<<endl; + x2 = p->GetZ(i3); // cout <<"L408 x2="<<x2<<endl; + + insidePoint(x0, y0, x1, y1, x2, y2, c, x, y); + q->Z(j1) = x; + + if (max) { + q->Rmax(j1) = y; + } else { + q->Rmin(j1) = y; + } + return; +} + +void V11Geometry::insidePoint(Double_t x0, Double_t y0, Double_t x1, Double_t y1, Double_t x2, + Double_t y2, Double_t c, Double_t& x, Double_t& y) const +{ + Double_t dx01, dx12, dy01, dy12, r01, r12, m; + + // printf("InsidePoint: x0=% #12.7g y0=% #12.7g x1=% #12.7g y1=% #12.7g " + // "x2=% #12.7g y2=% #12.7g c=% #12.7g ",x0,y0,x1,y2,x2,y2,c); + dx01 = x0 - x1; // cout <<"L410 dx01="<<dx01<<endl; + dx12 = x1 - x2; // cout <<"L411 dx12="<<dx12<<endl; + dy01 = y0 - y1; // cout <<"L412 dy01="<<dy01<<endl; + dy12 = y1 - y2; // cout <<"L413 dy12="<<dy12<<endl; + r01 = TMath::Sqrt(dy01 * dy01 + dx01 * dx01); // cout <<"L414 r01="<<r01<<endl; + r12 = TMath::Sqrt(dy12 * dy12 + dx12 * dx12); // cout <<"L415 r12="<<r12<<endl; + m = dx12 * dy01 - dy12 * dx01; + if (m * m < DBL_EPSILON) { // m == n + if (dy01 == 0.0) { // line are = + x = x1 + c; // cout <<"L419 x="<<x<<endl; + y = y1; // cout <<"L420 y="<<y<<endl; + // printf("dy01==0.0 x=% #12.7g y=% #12.7g\n",x,y); + return; + } else if (dx01 == 0.0) { + x = x1; + y = y1 + c; + // printf("dx01==0.0 x=% #12.7g y=% #12.7g\n",x,y); + return; + } else { // dx01!=0 and dy01 !=0. + x = x1 - 0.5 * c * r01 / dy01; // cout <<"L434 x="<<x<<endl; + y = y1 + 0.5 * c * r01 / dx01; // cout <<"L435 y="<<y<<endl; + // printf("m*m<DBL_E x=% #12.7g y=% #12.7g\n",x,y); + } // end if + return; + } + x = x1 + c * (dx12 * r01 - dx01 * r12) / m; // cout <<"L442 x="<<x<<endl; + y = y1 + c * (dy12 * r01 - dy01 * r12) / m; // cout <<"L443 y="<<y<<endl; + // printf(" x=% #12.7g y=% #12.7g\n",x,y); + // cout <<"=============================================="<<endl; + return; +} + +void V11Geometry::printArb8(const TGeoArb8* a) const +{ + if (!getDebug()) { + return; + } + printf("%s", a->GetName()); + a->InspectShape(); + return; +} + +void V11Geometry::printPcon(const TGeoPcon* a) const +{ + if (!getDebug()) { + return; + } + cout << a->GetName() << ": N=" << a->GetNz() << " Phi1=" << a->GetPhi1() + << ", Dphi=" << a->GetDphi() << endl; + cout << "i\t Z \t Rmin \t Rmax" << endl; + for (Int_t iii = 0; iii < a->GetNz(); iii++) { + cout << iii << "\t" << a->GetZ(iii) << "\t" << a->GetRmin(iii) << "\t" << a->GetRmax(iii) + << endl; + } // end for iii + return; +} + +void V11Geometry::printTube(const TGeoTube* a) const +{ + if (!getDebug()) { + return; + } + cout << a->GetName() << ": Rmin=" << a->GetRmin() << " Rmax=" << a->GetRmax() + << " Dz=" << a->GetDz() << endl; + return; +} + +void V11Geometry::printTubeSeg(const TGeoTubeSeg* a) const +{ + if (!getDebug()) { + return; + } + cout << a->GetName() << ": Phi1=" << a->GetPhi1() << " Phi2=" << a->GetPhi2() + << " Rmin=" << a->GetRmin() << " Rmax=" << a->GetRmax() << " Dz=" << a->GetDz() << endl; + return; +} + +void V11Geometry::printConeSeg(const TGeoConeSeg* a) const +{ + if (!getDebug()) { + return; + } + cout << a->GetName() << ": Phi1=" << a->GetPhi1() << " Phi2=" << a->GetPhi2() + << " Rmin1=" << a->GetRmin1() << " Rmax1=" << a->GetRmax1() << " Rmin2=" << a->GetRmin2() + << " Rmax2=" << a->GetRmax2() << " Dz=" << a->GetDz() << endl; + return; +} + +void V11Geometry::printBBox(const TGeoBBox* a) const +{ + if (!getDebug()) { + return; + } + cout << a->GetName() << ": Dx=" << a->GetDX() << " Dy=" << a->GetDY() << " Dz=" << a->GetDZ() + << endl; + return; +} + +void V11Geometry::createDefaultMaterials() +{ + Int_t i; + Double_t w; + + // Define some elements + auto* itsH = new TGeoElement("IT4_H", "Hydrogen", 1, 1.00794); + auto* itsHe = new TGeoElement("IT4_He", "Helium", 2, 4.002602); + auto* itsC = new TGeoElement("IT4_C", "Carbon", 6, 12.0107); + auto* itsN = new TGeoElement("IT4_N", "Nitrogen", 7, 14.0067); + auto* itsO = new TGeoElement("IT4_O", "Oxygen", 8, 15.994); + auto* itsF = new TGeoElement("IT4_F", "Florine", 9, 18.9984032); + auto* itsNe = new TGeoElement("IT4_Ne", "Neon", 10, 20.1797); + auto* itsMg = new TGeoElement("IT4_Mg", "Magnesium", 12, 24.3050); + auto* itsAl = new TGeoElement("IT4_Al", "Aluminum", 13, 26981538); + auto* itsSi = new TGeoElement("IT4_Si", "Silicon", 14, 28.0855); + auto* itsP = new TGeoElement("IT4_P", "Phosphorous", 15, 30.973761); + auto* itsS = new TGeoElement("IT4_S", "Sulfur", 16, 32.065); + auto* itsAr = new TGeoElement("IT4_Ar", "Argon", 18, 39.948); + auto* itsTi = new TGeoElement("IT4_Ti", "Titanium", 22, 47.867); + auto* itsCr = new TGeoElement("IT4_Cr", "Chromium", 24, 51.9961); + auto* itsMn = new TGeoElement("IT4_Mn", "Manganese", 25, 54.938049); + auto* itsFe = new TGeoElement("IT4_Fe", "Iron", 26, 55.845); + auto* itsCo = new TGeoElement("IT4_Co", "Cobalt", 27, 58.933200); + auto* itsNi = new TGeoElement("IT4_Ni", "Nickrl", 28, 56.6930); + auto* itsCu = new TGeoElement("IT4_Cu", "Copper", 29, 63.546); + auto* itsZn = new TGeoElement("IT4_Zn", "Zinc", 30, 65.39); + auto* itsKr = new TGeoElement("IT4_Kr", "Krypton", 36, 83.80); + auto* itsMo = new TGeoElement("IT4_Mo", "Molylibdium", 42, 95.94); + auto* itsXe = new TGeoElement("IT4_Xe", "Zeon", 54, 131.293); + + // Start with the Materials since for any one material there + // can be defined more than one Medium. + // Air, dry. at 15degree C, 101325Pa at sea-level, % by volume + // (% by weight). Density is 351 Kg/m^3 + // N2 78.084% (75.47%), O2 20.9476% (23.20%), Ar 0.934 (1.28%)%, + // C02 0.0314% (0.0590%), Ne 0.001818% (0.0012%, CH4 0.002% (), + // He 0.000524% (0.00007%), Kr 0.000114% (0.0003%), H2 0.00005% (3.5E-6%), + // Xe 0.0000087% (0.00004 %), H2O 0.0% (dry) + trace amounts at the ppm + // levels. + auto* itsAir = new TGeoMixture("IT4_Air", 9); + w = 75.47E-2; + itsAir->AddElement(itsN, w); // Nitorgen, atomic + w = 23.29E-2 + // O2 + 5.90E-4 * 2. * 15.994 / (12.0107 + 2. * 15.994); // CO2. + itsAir->AddElement(itsO, w); // Oxygen, atomic + w = 1.28E-2; + itsAir->AddElement(itsAr, w); // Argon, atomic + w = 5.90E-4 * 12.0107 / (12.0107 + 2. * 15.994) + // CO2 + 2.0E-5 * 12.0107 / (12.0107 + 4. * 1.00794); // CH4 + itsAir->AddElement(itsC, w); // Carbon, atomic + w = 1.818E-5; + itsAir->AddElement(itsNe, w); // Ne, atomic + w = 3.5E-8; + itsAir->AddElement(itsHe, w); // Helium, atomic + w = 7.0E-7; + itsAir->AddElement(itsKr, w); // Krypton, atomic + w = 3.0E-6; + itsAir->AddElement(itsH, w); // Hydrogen, atomic + w = 4.0E-7; + itsAir->AddElement(itsXe, w); // Xenon, atomic + itsAir->SetDensity(351.0 * sKgm3); + itsAir->SetPressure(101325 * sPascal); + itsAir->SetTemperature(15.0 * sCelsius); + itsAir->SetState(TGeoMaterial::kMatStateGas); + + // Silicone + auto* itsSiDet = new TGeoMaterial("IT4_Si", itsSi, 2.33 * sGCm3); + itsSiDet->SetTemperature(15.0 * sCelsius); + itsSiDet->SetState(TGeoMaterial::kMatStateSolid); + + // Epoxy C18 H19 O3 + auto* itsEpoxy = new TGeoMixture("IT4_Epoxy", 3); + itsEpoxy->AddElement(itsC, 18); + itsEpoxy->AddElement(itsH, 19); + itsEpoxy->AddElement(itsO, 3); + itsEpoxy->SetDensity(1.8 * sGCm3); + itsEpoxy->SetTemperature(15.0 * sCelsius); + itsEpoxy->SetState(TGeoMaterial::kMatStateSolid); + + // Carbon Fiber, M55J, 60% fiber by volume. Fiber density + // 1.91 g/cm^3. See ToryaCA M55J data sheet. + // Begin_Html + /* + <A HREF="http://torayusa.com/cfa/pdfs/M55JDataSheet.pdf"> Data Sheet + </A> + */ + // End_Html + auto* itsCarbonFiber = new TGeoMixture("IT4_CarbonFiber-M55J", 4); + // Assume that the epoxy fill in the space between the fibers and so + // no change in the total volume. To compute w, assume 1cm^3 total + // volume. + w = 1.91 / (1.91 + (1. - .60) * itsEpoxy->GetDensity()); + itsCarbonFiber->AddElement(itsC, w); + w = (1. - .60) * itsEpoxy->GetDensity() / (1.91 + (1. - .06) * itsEpoxy->GetDensity()); + + for (i = 0; i < itsEpoxy->GetNelements(); i++) { + itsCarbonFiber->AddElement(itsEpoxy->GetElement(i), itsEpoxy->GetWmixt()[i] * w); + } + + itsCarbonFiber->SetDensity((1.91 + (1. - .60) * itsEpoxy->GetDensity()) * sGCm3); + itsCarbonFiber->SetTemperature(22.0 * sCelsius); + itsCarbonFiber->SetState(TGeoMaterial::kMatStateSolid); + + // Rohacell 51A millable foam product. + // C9 H13 N1 O2 52Kg/m^3 + // Elemental composition, Private comunications with + // Bjorn S. Nilsen + // Begin_Html + /* + <A HREF="http://www.rohacell.com/en/performanceplastics8344.html"> + Rohacell-A see Properties + </A> + */ + // End_Html + auto* itsFoam = new TGeoMixture("IT4_Foam", 4); + itsFoam->AddElement(itsC, 9); + itsFoam->AddElement(itsH, 13); + itsFoam->AddElement(itsN, 1); + itsFoam->AddElement(itsO, 2); + itsFoam->SetTitle("Rohacell 51 A"); + itsFoam->SetDensity(52. * sKgm3); + itsFoam->SetTemperature(22.0 * sCelsius); + itsFoam->SetState(TGeoMaterial::kMatStateSolid); + + // Kapton % by weight, H 2.6362, C69.1133, N 7.3270, O 20.0235 + // Density 1.42 g/cm^3 + // Begin_Html + /* + <A HREF="http://www2.dupont.com/Kapton/en_US/assets/downloads/pdf/summaryofprop.pdf"> + Kapton. also see </A> + <A HREF="http://physics.nist.gov/cgi-bin/Star/compos.pl?matno=179"> + </A> + */ + // End_Html + auto* itsKapton = new TGeoMixture("IT4_Kapton", 4); + itsKapton->AddElement(itsH, 0.026362); + itsKapton->AddElement(itsC, 0.691133); + itsKapton->AddElement(itsN, 0.073270); + itsKapton->AddElement(itsO, 0.200235); + itsKapton->SetTitle("Kapton ribon and cable base"); + itsKapton->SetDensity(1.42 * sGCm3); + itsKapton->SetTemperature(22.0 * sCelsius); + itsKapton->SetState(TGeoMaterial::kMatStateSolid); + + // UPILEX-S C16 H6 O4 N2 polymer (a Kapton like material) + // Density 1.47 g/cm^3 + // Begin_Html + /* + <A HREF="http://northamerica.ube.com/page.php?pageid=9"> + UPILEX-S. also see </A> + <A HREF="http://northamerica.ube.com/page.php?pageid=81"> + </A> + */ + // End_Html + auto* itsUpilex = new TGeoMixture("IT4_Upilex", 4); + itsUpilex->AddElement(itsC, 16); + itsUpilex->AddElement(itsH, 6); + itsUpilex->AddElement(itsN, 2); + itsUpilex->AddElement(itsO, 4); + itsUpilex->SetTitle("Upilex ribon, cable, and pcb base"); + itsUpilex->SetDensity(1.47 * sGCm3); + itsUpilex->SetTemperature(22.0 * sCelsius); + itsUpilex->SetState(TGeoMaterial::kMatStateSolid); + + // Aluminum 6061 (Al used by US groups) + // % by weight, Cr 0.04-0.35 range [0.0375 nominal value used] + // Cu 0.15-0.4 [0.275], Fe Max 0.7 [0.35], Mg 0.8-1.2 [1.0], + // Mn Max 0.15 [0.075] Si 0.4-0.8 [0.6], Ti Max 0.15 [0.075], + // Zn Max 0.25 [0.125], Rest Al [97.4625]. Density 2.7 g/cm^3 + // Begin_Html + /* + <A HREG="http://www.matweb.com/SpecificMaterial.asp?bassnum=MA6016&group=General"> + Aluminum 6061 specifications + </A> + */ + // End_Html + auto* itsAl6061 = new TGeoMixture("IT4_Al6061", 9); + itsAl6061->AddElement(itsCr, 0.000375); + itsAl6061->AddElement(itsCu, 0.00275); + itsAl6061->AddElement(itsFe, 0.0035); + itsAl6061->AddElement(itsMg, 0.01); + itsAl6061->AddElement(itsMn, 0.00075); + itsAl6061->AddElement(itsSi, 0.006); + itsAl6061->AddElement(itsTi, 0.00075); + itsAl6061->AddElement(itsZn, 0.00125); + itsAl6061->AddElement(itsAl, 0.974625); + itsAl6061->SetTitle("Aluminum Alloy 6061"); + itsAl6061->SetDensity(2.7 * sGCm3); + itsAl6061->SetTemperature(22.0 * sCelsius); + itsAl6061->SetState(TGeoMaterial::kMatStateSolid); + + // Aluminum 7075 (Al used by Italian groups) + // % by weight, Cr 0.18-0.28 range [0.23 nominal value used] + // Cu 1.2-2.0 [1.6], Fe Max 0.5 [0.25], Mg 2.1-2.9 [2.5], + // Mn Max 0.3 [0.125] Si Max 0.4 [0.2], Ti Max 0.2 [0.1], + // Zn 5.1-6.1 [5.6], Rest Al [89.395]. Density 2.81 g/cm^3 + // Begin_Html + /* + <A HREG="http://asm.matweb.com/search/SpecificMaterial.asp?bassnum=MA7075T6"> + Aluminum 7075 specifications + </A> + */ + // End_Html + auto* itsAl7075 = new TGeoMixture("IT4_Al7075", 9); + itsAl7075->AddElement(itsCr, 0.0023); + itsAl7075->AddElement(itsCu, 0.016); + itsAl7075->AddElement(itsFe, 0.0025); + itsAl7075->AddElement(itsMg, 0.025); + itsAl7075->AddElement(itsMn, 0.00125); + itsAl7075->AddElement(itsSi, 0.002); + itsAl7075->AddElement(itsTi, 0.001); + itsAl7075->AddElement(itsZn, 0.056); + itsAl7075->AddElement(itsAl, 0.89395); + itsAl7075->SetTitle("Aluminum Alloy 7075"); + itsAl7075->SetDensity(2.81 * sGCm3); + itsAl7075->SetTemperature(22.0 * sCelsius); + itsAl7075->SetState(TGeoMaterial::kMatStateSolid); + + // "Ruby" spheres, Al2 O3 + // "Ruby" Sphere posts, Ryton R-4 04 + // Begin_Html + /* + <A HREF=""> + Ruby Sphere Posts + </A> + */ + // End_Html + auto* itsRuby = new TGeoMixture("IT4_RubySphere", 2); + itsRuby->AddElement(itsAl, 2); + itsRuby->AddElement(itsO, 3); + itsRuby->SetTitle("Ruby reference sphere"); + itsRuby->SetDensity(2.81 * sGCm3); + itsRuby->SetTemperature(22.0 * sCelsius); + itsRuby->SetState(TGeoMaterial::kMatStateSolid); + + // Inox, AISI 304L, compoistion % by weight (assumed) + // C Max 0.03 [0.015], Mn Max 2.00 [1.00], Si Max 1.00 [0.50] + // P Max 0.045 [0.0225], S Max 0.03 [0.015], Ni 8.0-10.5 [9.25] + // Cr 18-20 [19.], Mo 2.-2.5 [2.25], rest Fe: density 7.93 Kg/dm^3 + // Begin_Html + /* + <A HREF="http://www.cimap.fr/caracter.pdf"> + Stainless steal (INOX) AISI 304L composition + </A> + */ + // End_Html + auto* itsInox304L = new TGeoMixture("IT4_Inox304L", 9); + itsInox304L->AddElement(itsC, 0.00015); + itsInox304L->AddElement(itsMn, 0.010); + itsInox304L->AddElement(itsSi, 0.005); + itsInox304L->AddElement(itsP, 0.000225); + itsInox304L->AddElement(itsS, 0.00015); + itsInox304L->AddElement(itsNi, 0.0925); + itsInox304L->AddElement(itsCr, 0.1900); + itsInox304L->AddElement(itsMo, 0.0225); + itsInox304L->AddElement(itsFe, 0.679475); // Rest Fe + itsInox304L->SetTitle("ITS Stainless Steal (Inox) type AISI 304L"); + itsInox304L->SetDensity(7.93 * sKgdm3); + itsInox304L->SetTemperature(22.0 * sCelsius); + itsInox304L->SetState(TGeoMaterial::kMatStateSolid); + + // Inox, AISI 316L, composition % by weight (assumed) + // C Max 0.03 [0.015], Mn Max 2.00 [1.00], Si Max 1.00 [0.50] + // P Max 0.045 [0.0225], S Max 0.03 [0.015], Ni 10.0-14. [12.] + // Cr 16-18 [17.], Mo 2-3 [2.5]: density 7.97 Kg/dm^3 + // Begin_Html + /* + <A HREF="http://www.cimap.fr/caracter.pdf"> + Stainless steal (INOX) AISI 316L composition + </A> + */ + // End_Html + auto* itsInox316L = new TGeoMixture("IT4_Inox316L", 9); + itsInox316L->AddElement(itsC, 0.00015); + itsInox316L->AddElement(itsMn, 0.010); + itsInox316L->AddElement(itsSi, 0.005); + itsInox316L->AddElement(itsP, 0.000225); + itsInox316L->AddElement(itsS, 0.00015); + itsInox316L->AddElement(itsNi, 0.12); + itsInox316L->AddElement(itsCr, 0.17); + itsInox316L->AddElement(itsMo, 0.025); + itsInox316L->AddElement(itsFe, 0.66945); // Rest Fe + itsInox316L->SetTitle("ITS Stainless Steal (Inox) type AISI 316L"); + itsInox316L->SetDensity(7.97 * sKgdm3); + itsInox316L->SetTemperature(22.0 * sCelsius); + itsInox316L->SetState(TGeoMaterial::kMatStateSolid); + + // Inox, Phynox or Elgiloy AMS 5833, composition % by weight + // C Max 0.15 [0.15], Mn Max 2.00 [2.00], Be max 0.0001 [none] + // Ni 18. [18.], Cr 21.5 [21.5], Mo 7.5 [7.5], Co 42 [42.]: + // density 8.3 Kg/dm^3 + // Begin_Html + /* + <A HREF="http://www.freepatentsonline.com/20070032816.html"> + Compostion of Phynox or Elgiloy AMS 5833, also see + </A> + <A HREF="http://www.alloywire.com/phynox_alloy.html"> + under corss reference number [0024]. + </A> + */ + // End_Html + auto* itsPhynox = new TGeoMixture("IT4_Phynox", 7); + itsPhynox->AddElement(itsC, 0.0015); + itsPhynox->AddElement(itsMn, 0.020); + itsPhynox->AddElement(itsNi, 0.18); + itsPhynox->AddElement(itsCr, 0.215); + itsPhynox->AddElement(itsMo, 0.075); + itsPhynox->AddElement(itsCo, 0.42); + itsPhynox->AddElement(itsFe, 0.885); + itsPhynox->SetTitle("ITS Cooling tube alloy"); + itsPhynox->SetDensity(8.3 * sGCm3); + itsPhynox->SetTemperature(22.0 * sCelsius); + itsPhynox->SetState(TGeoMaterial::kMatStateSolid); + + // G10FR4 + + // Demineralized Water H2O SDD & SSD Cooling liquid + auto* itsWater = new TGeoMixture("IT4_Water", 2); + itsWater->AddElement(itsH, 2); + itsWater->AddElement(itsO, 1); + itsWater->SetTitle("ITS Cooling Water"); + itsWater->SetDensity(1.0 * sGCm3); + itsWater->SetTemperature(22.0 * sCelsius); + itsWater->SetState(TGeoMaterial::kMatStateLiquid); + + // Freon SPD Cooling liquid PerFluorobuthane C4F10 + // Begin_Html + /* + <A HREF=" + http://st-support-cooling-electronics.web.cern.ch/st-support-cooling-electronics/default.htm"> + SPD 2 phase cooling using PerFluorobuthane + </A> + */ + // End_Html + auto* itsFreon = new TGeoMixture("IT4_SPD_Freon", 2); + itsFreon->AddElement(itsC, 4); + itsFreon->AddElement(itsF, 10); + itsFreon->SetTitle("ITS SPD 2 phase Cooling freon"); + itsFreon->SetDensity(1.52 * sGCm3); + itsFreon->SetTemperature(22.0 * sCelsius); + itsFreon->SetState(TGeoMaterial::kMatStateLiquid); + + // Int_t ifield = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Integ(); + // Float_t fieldm = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Max(); + + // Float_t tmaxfd = 0.1;// 1.0;// Degree + // Float_t stemax = 1.0;// cm + // Float_t deemax = 0.1;// 30.0;// Fraction of particle's energy 0<deemax<=1 + // Float_t epsil = 1.0E-4;// 1.0; cm + // Float_t stmin = 0.0; // cm "Default value used" + + // Float_t tmaxfdSi = 0.1; // .10000E+01; // Degree + // Float_t stemaxSi = 0.0075; // .10000E+01; // cm + // Float_t deemaxSi = 0.1; // Fraction of particle's energy 0<deemax<=1 + // Float_t epsilSi = 1.0E-4;// .10000E+01; + /* + Float_t stminSi = 0.0; // cm "Default value used" + + Float_t tmaxfdAir = 0.1; // .10000E+01; // Degree + Float_t stemaxAir = .10000E+01; // cm + Float_t deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1 + Float_t epsilAir = 1.0E-4;// .10000E+01; + Float_t stminAir = 0.0; // cm "Default value used" + + Float_t tmaxfdServ = 1.0; // 10.0; // Degree + Float_t stemaxServ = 1.0; // 0.01; // cm + Float_t deemaxServ = 0.5; // 0.1; // Fraction of particle's energy 0<deemax<=1 + Float_t epsilServ = 1.0E-3; // 0.003; // cm + Float_t stminServ = 0.0; //0.003; // cm "Default value used" + + // Freon PerFluorobuthane C4F10 see + // http://st-support-cooling-electronics.web.cern.ch/ + // st-support-cooling-electronics/default.htm + Float_t afre[2] = { 12.011,18.9984032 }; + Float_t zfre[2] = { 6., 9. }; + Float_t wfre[2] = { 4.,10. }; + Float_t densfre = 1.52; + + //CM55J + Float_t aCM55J[4]={12.0107,14.0067,15.9994,1.00794}; + Float_t zCM55J[4]={6.,7.,8.,1.}; + Float_t wCM55J[4]={0.908508078,0.010387573,0.055957585,0.025146765}; + Float_t dCM55J = 1.63; + + //ALCM55J + Float_t aALCM55J[5]={12.0107,14.0067,15.9994,1.00794,26.981538}; + Float_t zALCM55J[5]={6.,7.,8.,1.,13.}; + Float_t wALCM55J[5]={0.817657902,0.0093488157,0.0503618265,0.0226320885,0.1}; + Float_t dALCM55J = 1.9866; + + //Si Chips + Float_t aSICHIP[6]={12.0107,14.0067,15.9994,1.00794,28.0855,107.8682}; + Float_t zSICHIP[6]={6.,7.,8.,1.,14., 47.}; + Float_t wSICHIP[6]={0.039730642,0.001396798,0.01169634, + 0.004367771,0.844665,0.09814344903}; + Float_t dSICHIP = 2.36436; + + //Inox + Float_t aINOX[9]={12.0107,54.9380, 28.0855,30.9738,32.066, + 58.6928,55.9961,95.94,55.845}; + Float_t zINOX[9]={6.,25.,14.,15.,16., 28.,24.,42.,26.}; + Float_t wINOX[9]={0.0003,0.02,0.01,0.00045,0.0003,0.12,0.17,0.025,0.654}; + Float_t dINOX = 8.03; + + //SDD HV microcable + Float_t aHVm[5]={12.0107,1.00794,14.0067,15.9994,26.981538}; + Float_t zHVm[5]={6.,1.,7.,8.,13.}; + Float_t wHVm[5]={0.520088819984,0.01983871336,0.0551367996,0.157399667056, 0.247536}; + Float_t dHVm = 1.6087; + + //SDD LV+signal cable + Float_t aLVm[5]={12.0107,1.00794,14.0067,15.9994,26.981538}; + Float_t zLVm[5]={6.,1.,7.,8.,13.}; + Float_t wLVm[5]={0.21722436468,0.0082859922,0.023028867,0.06574077612, 0.68572}; + Float_t dLVm = 2.1035; + + //SDD hybrid microcab + Float_t aHLVm[5]={12.0107,1.00794,14.0067,15.9994,26.981538}; + Float_t zHLVm[5]={6.,1.,7.,8.,13.}; + Float_t wHLVm[5]={0.24281879711,0.00926228815,0.02574224025,0.07348667449, 0.64869}; + Float_t dHLVm = 2.0502; + + //SDD anode microcab + Float_t aALVm[5]={12.0107,1.00794,14.0067,15.9994,26.981538}; + Float_t zALVm[5]={6.,1.,7.,8.,13.}; + Float_t wALVm[5]={0.392653705471,0.0128595919215, + 0.041626868025,0.118832707289, 0.431909}; + Float_t dALVm = 2.0502; + + //X7R capacitors + Float_t aX7R[7]={137.327,47.867,15.9994,58.6928,63.5460,118.710,207.2}; + Float_t zX7R[7]={56.,22.,8.,28.,29.,50.,82.}; + Float_t wX7R[7]={0.251639432,0.084755042,0.085975822, + 0.038244751,0.009471271,0.321736471,0.2081768}; + Float_t dX7R = 7.14567; + + // AIR + Float_t aAir[4]={12.0107,14.0067,15.9994,39.948}; + Float_t zAir[4]={6.,7.,8.,18.}; + Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827}; + Float_t dAir = 1.20479E-3; + + // Water + Float_t aWater[2]={1.00794,15.9994}; + Float_t zWater[2]={1.,8.}; + Float_t wWater[2]={0.111894,0.888106}; + Float_t dWater = 1.0; + + // CERAMICS + // 94.4% Al2O3 , 2.8% SiO2 , 2.3% MnO , 0.5% Cr2O3 + Float_t acer[5] = { 26.981539,15.9994,28.0855,54.93805,51.9961 }; + Float_t zcer[5] = { 13., 8., 14., 25., 24. }; + Float_t wcer[5] = {.4443408,.5213375,.0130872,.0178135,.003421}; + Float_t denscer = 3.6; + + // G10FR4 + Float_t zG10FR4[14] = {14.00, 20.00, 13.00, 12.00, 5.00, + 22.00, 11.00, 19.00, 26.00, 9.00, + 8.00, 6.00, 7.00, 1.00}; + Float_t aG10FR4[14] = {28.0855000,40.0780000,26.9815380,24.3050000, + 10.8110000,47.8670000,22.9897700,39.0983000, + 55.8450000,18.9984000,15.9994000,12.0107000, + 14.0067000,1.0079400}; + Float_t wG10FR4[14] = {0.15144894,0.08147477,0.04128158,0.00904554, + 0.01397570,0.00287685,0.00445114,0.00498089, + 0.00209828,0.00420000,0.36043788,0.27529426, + 0.01415852,0.03427566}; + Float_t densG10FR4= 1.8; + + //--- EPOXY --- C18 H19 O3 + Float_t aEpoxy[3] = {15.9994, 1.00794, 12.0107} ; + Float_t zEpoxy[3] = { 8., 1., 6.} ; + Float_t wEpoxy[3] = { 3., 19., 18.} ; + Float_t dEpoxy = 1.8 ; + + // rohacell: C9 H13 N1 O2 + Float_t arohac[4] = {12.01, 1.01, 14.010, 16.}; + Float_t zrohac[4] = { 6., 1., 7., 8.}; + Float_t wrohac[4] = { 9., 13., 1., 2.}; + Float_t drohac = 0.05; + + // If he/she means stainless steel (inox) + Aluminium and Zeff=15.3383 then + // %Al=81.6164 %inox=100-%Al + Float_t aInAl[5] = {27., 55.847,51.9961,58.6934,28.0855 }; + Float_t zInAl[5] = {13., 26.,24.,28.,14. }; + Float_t wInAl[5] = {.816164, .131443,.0330906,.0183836,.000919182}; + Float_t dInAl = 3.075; + + // Kapton + Float_t aKapton[4]={1.00794,12.0107, 14.010,15.9994}; + Float_t zKapton[4]={1.,6.,7.,8.}; + Float_t wKapton[4]={0.026362,0.69113,0.07327,0.209235}; + Float_t dKapton = 1.42; + + //SDD ruby sph. + Float_t aAlOxide[2] = { 26.981539,15.9994}; + Float_t zAlOxide[2] = { 13., 8.}; + Float_t wAlOxide[2] = {0.4707, 0.5293}; + Float_t dAlOxide = 3.97; + */ +} + +void V11Geometry::drawCrossSection(const TGeoPcon* p, Int_t fillc, Int_t fills, Int_t linec, + Int_t lines, Int_t linew, Int_t markc, Int_t marks, + Float_t marksize) const +{ + Int_t n = 0, m = 0, i = 0; + Double_t *z = nullptr, *r = nullptr; + TPolyMarker* pts = nullptr; + TPolyLine* line = nullptr; + + n = p->GetNz(); + if (n <= 0) { + return; + } + m = 2 * n + 1; + z = new Double_t[m]; + r = new Double_t[m]; + + for (i = 0; i < n; i++) { + z[i] = p->GetZ(i); + r[i] = p->GetRmax(i); + z[i + n] = p->GetZ(n - 1 - i); + r[i + n] = p->GetRmin(n - 1 - i); + } // end for i + z[n - 1] = z[0]; + r[n - 1] = r[0]; + + line = new TPolyLine(n, z, r); + pts = new TPolyMarker(n, z, r); + + line->SetFillColor(fillc); + line->SetFillStyle(fills); + line->SetLineColor(linec); + line->SetLineStyle(lines); + line->SetLineWidth(linew); + pts->SetMarkerColor(markc); + pts->SetMarkerStyle(marks); + pts->SetMarkerSize(marksize); + + line->Draw("f"); + line->Draw(); + pts->Draw(); + + delete[] z; + delete[] r; + + cout << "Hit Return to continue" << endl; + cin >> n; + delete line; + delete pts; + return; +} + +Bool_t V11Geometry::angleOfIntersectionWithLine(Double_t x0, Double_t y0, Double_t x1, Double_t y1, + Double_t xc, Double_t yc, Double_t rc, Double_t& t0, + Double_t& t1) const +{ + Double_t dx, dy, cx, cy, s2, t[4]; + Double_t a0, b0, c0, a1, b1, c1, sinthp, sinthm, costhp, costhm; + Int_t i, j; + + t0 = 400.0; + t1 = 400.0; + dx = x1 - x0; + dy = y1 - y0; + cx = xc - x0; + cy = yc - y0; + s2 = dx * dx + dy * dy; + if (s2 == 0.0) { + return kFALSE; + } + + a0 = rc * rc * s2; + if (a0 == 0.0) { + return kFALSE; + } + b0 = 2.0 * rc * dx * (dx * cy - cx * dy); + c0 = dx * dx * cy * cy - 2.0 * dy * dx * cy * cx + cx * cx * dy * dy - rc * rc * dy * dy; + c0 = 0.25 * b0 * b0 / (a0 * a0) - c0 / a0; + if (c0 < 0.0) { + return kFALSE; + } + sinthp = -0.5 * b0 / a0 + TMath::Sqrt(c0); + sinthm = -0.5 * b0 / a0 - TMath::Sqrt(c0); + + a1 = rc * rc * s2; + if (a1 == 0.0) { + return kFALSE; + } + b1 = 2.0 * rc * dy * (dy * cx - dx * cy); + c1 = dy * dy * cx * cx - 2.0 * dy * dx * cy * cx + dx * dx * cy * cy - rc * rc * dx * dx; + c1 = 0.25 * b1 * b1 / (a1 * a1) - c1 / a1; + if (c1 < 0.0) { + return kFALSE; + } + costhp = -0.5 * b1 / a1 + TMath::Sqrt(c1); + costhm = -0.5 * b1 / a1 - TMath::Sqrt(c1); + + t[0] = t[1] = t[2] = t[3] = 400.; + a0 = TMath::ATan2(sinthp, costhp); + if (a0 < 0.0) { + a0 += 2.0 * TMath::Pi(); + } + a1 = TMath::ATan2(sinthp, costhm); + if (a1 < 0.0) { + a1 += 2.0 * TMath::Pi(); + } + b0 = TMath::ATan2(sinthm, costhp); + if (b0 < 0.0) { + b0 += 2.0 * TMath::Pi(); + } + b1 = TMath::ATan2(sinthm, costhm); + if (b1 < 0.0) { + b1 += 2.0 * TMath::Pi(); + } + x1 = xc + rc * TMath::Cos(a0); + y1 = yc + rc * TMath::Sin(a0); + s2 = dx * (y1 - y0) - dy * (x1 - x0); + if (s2 * s2 < DBL_EPSILON) { + t[0] = a0 * TMath::RadToDeg(); + } + x1 = xc + rc * TMath::Cos(a1); + y1 = yc + rc * TMath::Sin(a1); + s2 = dx * (y1 - y0) - dy * (x1 - x0); + if (s2 * s2 < DBL_EPSILON) { + t[1] = a1 * TMath::RadToDeg(); + } + x1 = xc + rc * TMath::Cos(b0); + y1 = yc + rc * TMath::Sin(b0); + s2 = dx * (y1 - y0) - dy * (x1 - x0); + if (s2 * s2 < DBL_EPSILON) { + t[2] = b0 * TMath::RadToDeg(); + } + x1 = xc + rc * TMath::Cos(b1); + y1 = yc + rc * TMath::Sin(b1); + s2 = dx * (y1 - y0) - dy * (x1 - x0); + if (s2 * s2 < DBL_EPSILON) { + t[3] = b1 * TMath::RadToDeg(); + } + for (i = 0; i < 4; i++) { + for (j = i + 1; j < 4; j++) { + if (t[i] > t[j]) { + t0 = t[i]; + t[i] = t[j]; + t[j] = t0; + } + } // end for i,j + } + t0 = t[0]; + t1 = t[1]; + + return kTRUE; +} + +Double_t V11Geometry::angleForRoundedCorners0(Double_t dx, Double_t dy, Double_t sdr) const +{ + Double_t a, b; + + b = dy * dy + dx * dx - sdr * sdr; + if (b < 0.0) { + Error("AngleForRoundedCorners0", "dx^2(%e)+dy^2(%e)-sdr^2(%e)=b=%e<0", dx, dy, sdr, b); + } + b = TMath::Sqrt(b); + a = -sdr * dy + dx * b; + b = -sdr * dx - dy * b; + return TMath::ATan2(a, b) * TMath::RadToDeg(); +} + +Double_t V11Geometry::angleForRoundedCorners1(Double_t dx, Double_t dy, Double_t sdr) const +{ + Double_t a, b; + + b = dy * dy + dx * dx - sdr * sdr; + if (b < 0.0) { + Error("AngleForRoundedCorners1", "dx^2(%e)+dy^2(%e)-sdr^2(%e)=b=%e<0", dx, dy, sdr, b); + } + b = TMath::Sqrt(b); + a = -sdr * dy - dx * b; + b = -sdr * dx + dy * b; + return TMath::ATan2(a, b) * TMath::RadToDeg(); +} + +void V11Geometry::anglesForRoundedCorners(Double_t x0, Double_t y0, Double_t r0, Double_t x1, + Double_t y1, Double_t r1, Double_t& t0, Double_t& t1) + const +{ + Double_t t; + + if (r0 >= 0.0 && r1 >= 0.0) { // Inside to inside ++ + t = angleForRoundedCorners1(x1 - x0, y1 - y0, r1 - r0); + t0 = t1 = t; + return; + } else if (r0 >= 0.0 && r1 <= 0.0) { // Inside to Outside +- + r1 = -r1; // make positive + t = angleForRoundedCorners0(x1 - x0, y1 - y0, r1 + r0); + t0 = 180.0 + t; + if (t0 < 0.0) { + t += 360.; + } + if (t < 0.0) { + t += 360.; + } + t1 = t; + return; + } else if (r0 <= 0.0 && r1 >= 0.0) { // Outside to Inside -+ + r0 = -r0; // make positive + t = angleForRoundedCorners1(x1 - x0, y1 - y0, r1 + r0); + t0 = 180.0 + t; + if (t0 > 180.) { + t0 -= 360.; + } + if (t > 180.) { + t -= 360.; + } + t1 = t; + return; + } else if (r0 <= 0.0 && r1 <= 0.0) { // Outside to outside -- + r0 = -r0; // make positive + r1 = -r1; // make positive + t = angleForRoundedCorners0(x1 - x0, y1 - y0, r1 - r0); + t0 = t1 = t; + return; + } + return; +} + +void V11Geometry::makeFigure1(Double_t x0, Double_t y0, Double_t r0, Double_t x1, Double_t y1, + Double_t r1) +{ + Double_t t0[4], t1[4], xa0[4], ya0[4], xa1[4], ya1[4], ra0[4], ra1[4]; + Double_t xmin, ymin, xmax, ymax, h; + Int_t j; + + for (j = 0; j < 4; j++) { + ra0[j] = r0; + if (j % 2) { + ra0[j] = -r0; + } + ra1[j] = r1; + if (j > 1) { + ra1[j] = -r1; + } + anglesForRoundedCorners(x0, y0, ra0[j], x1, y1, ra1[j], t0[j], t1[j]); + xa0[j] = TMath::Abs(r0) * cosD(t0[j]) + x0; + ya0[j] = TMath::Abs(r0) * sinD(t0[j]) + y0; + xa1[j] = TMath::Abs(r1) * cosD(t1[j]) + x1; + ya1[j] = TMath::Abs(r1) * sinD(t1[j]) + y1; + } + if (r0 < 0.0) { + r0 = -r0; + } + if (r1 < 0.0) { + r1 = -r1; + } + xmin = TMath::Min(x0 - r0, x1 - r1); + ymin = TMath::Min(y0 - r0, y1 - r1); + xmax = TMath::Max(x0 + r0, x1 + r1); + ymax = TMath::Max(y0 + r0, y1 + r1); + + for (j = 1; j < 4; j++) { + xmin = TMath::Min(xmin, xa0[j]); + xmin = TMath::Min(xmin, xa1[j]); + ymin = TMath::Min(ymin, ya0[j]); + ymin = TMath::Min(ymin, ya1[j]); + + xmax = TMath::Max(xmax, xa0[j]); + xmax = TMath::Max(xmax, xa1[j]); + ymax = TMath::Max(ymax, ya0[j]); + ymax = TMath::Max(ymax, ya1[j]); + } + if (xmin < 0.0) { + xmin *= 1.1; + } else { + xmin *= 0.9; + } + if (ymin < 0.0) { + ymin *= 1.1; + } else { + ymin *= 0.9; + } + if (xmax < 0.0) { + xmax *= 0.9; + } else { + xmax *= 1.1; + } + if (ymax < 0.0) { + ymax *= 0.9; + } else { + ymax *= 1.1; + } + j = (Int_t)(500.0 * (ymax - ymin) / (xmax - xmin)); + auto* can = + new TCanvas("V11Geometry_AnglesForRoundedCorners", "Figure for V11Geometry", 500, j); + h = ymax - ymin; + if (h < 0) { + h = -h; + } + can->Range(xmin, ymin, xmax, ymax); + auto* c0 = new TArc(x0, y0, r0); + auto* c1 = new TArc(x1, y1, r1); + TLine* line[4]; + TArrow* ar0[4]; + TArrow* ar1[4]; + + for (j = 0; j < 4; j++) { + ar0[j] = new TArrow(x0, y0, xa0[j], ya0[j]); + ar1[j] = new TArrow(x1, y1, xa1[j], ya1[j]); + line[j] = new TLine(xa0[j], ya0[j], xa1[j], ya1[j]); + ar0[j]->SetLineColor(j + 1); + ar0[j]->SetArrowSize(0.1 * r0 / h); + ar1[j]->SetLineColor(j + 1); + ar1[j]->SetArrowSize(0.1 * r1 / h); + line[j]->SetLineColor(j + 1); + } + c0->Draw(); + c1->Draw(); + + for (j = 0; j < 4; j++) { + ar0[j]->Draw(); + ar1[j]->Draw(); + line[j]->Draw(); + } + + auto* t = new TText(); + t->SetTextSize(0.02); + Char_t txt[100]; + snprintf(txt, 99, "(x0=%5.2f,y0=%5.2f)", x0, y0); + t->DrawText(x0, y0, txt); + snprintf(txt, 99, "(x1=%5.2f,y1=%5.2f)", x1, y1); + + for (j = 0; j < 4; j++) { + t->SetTextColor(j + 1); + t->DrawText(x1, y1, txt); + snprintf(txt, 99, "r0=%5.2f", ra0[j]); + t->DrawText(0.5 * (x0 + xa0[j]), 0.5 * (y0 + ya0[j]), txt); + snprintf(txt, 99, "r1=%5.2f", ra1[j]); + t->DrawText(0.5 * (x1 + xa1[j]), 0.5 * (y1 + ya1[j]), txt); + } +} diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V1Layer.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V1Layer.cxx new file mode 100644 index 0000000000000..6147ed7467cb7 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V1Layer.cxx @@ -0,0 +1,2762 @@ +// 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 V1Layer.cxx +/// \brief Implementation of the V1Layer class +/// \author Mario Sitta <sitta@to.infn.it> +/// \author Chinorat Kobdaj (kobdaj@g.sut.ac.th) + +#include "ITS4Simulation/V1Layer.h" +#include "ITS4Base/GeometryTGeo.h" +#include "ITS4Simulation/Detector.h" + +#include "FairLogger.h" // for LOG + +#include <TGeoArb8.h> // for TGeoArb8 +#include <TGeoBBox.h> // for TGeoBBox +#include <TGeoCone.h> // for TGeoConeSeg, TGeoCone +#include <TGeoManager.h> // for TGeoManager, gGeoManager +#include <TGeoMatrix.h> // for TGeoCombiTrans, TGeoRotation, etc +#include <TGeoTrd1.h> // for TGeoTrd1 +#include <TGeoTube.h> // for TGeoTube, TGeoTubeSeg +#include <TGeoVolume.h> // for TGeoVolume, TGeoVolumeAssembly +#include <TGeoXtru.h> // for TGeoXtru +#include "TMathBase.h" // for Abs +#include <TMath.h> // for Sin, RadToDeg, DegToRad, Cos, Tan, etc + +#include <cstdio> // for snprintf + +class TGeoMedium; + +using namespace TMath; +using namespace o2::its4; + +// General Parameters +const Int_t V1Layer::sNumberOmInnerLayers = 3; + +const Double_t V1Layer::sDefaultSensorThick = 300 * sMicron; +const Double_t V1Layer::sDefaultStaveThick = 1 * sCm; + +// Inner Barrel Parameters +const Int_t V1Layer::sIBChipsPerRow = 9; +const Int_t V1Layer::sIBNChipRows = 1; + +// Outer Barrel Parameters +const Int_t V1Layer::sOBChipsPerRow = 7; +const Int_t V1Layer::sOBNChipRows = 2; + +const Double_t V1Layer::sOBHalfStaveWidth = 3.01 * sCm; +const Double_t V1Layer::sOBModuleWidth = sOBHalfStaveWidth; +const Double_t V1Layer::sOBModuleGap = 0.01 * sCm; +const Double_t V1Layer::sOBChipXGap = 0.01 * sCm; +const Double_t V1Layer::sOBChipZGap = 0.01 * sCm; +const Double_t V1Layer::sOBFlexCableAlThick = 0.005 * sCm; +const Double_t V1Layer::sOBFlexCableKapThick = 0.01 * sCm; +const Double_t V1Layer::sOBBusCableAlThick = 0.02 * sCm; +const Double_t V1Layer::sOBBusCableKapThick = 0.02 * sCm; +const Double_t V1Layer::sOBColdPlateThick = 0.012 * sCm; +const Double_t V1Layer::sOBCarbonPlateThick = 0.012 * sCm; +const Double_t V1Layer::sOBGlueThick = 0.03 * sCm; +const Double_t V1Layer::sOBModuleZLength = 21.06 * sCm; +const Double_t V1Layer::sOBHalfStaveYTrans = 1.76 * sMm; +const Double_t V1Layer::sOBHalfStaveXOverlap = 4.3 * sMm; +const Double_t V1Layer::sOBGraphiteFoilThick = 30.0 * sMicron; +const Double_t V1Layer::sOBCoolTubeInnerD = 2.052 * sMm; +const Double_t V1Layer::sOBCoolTubeThick = 32.0 * sMicron; +const Double_t V1Layer::sOBCoolTubeXDist = 11.1 * sMm; + +const Double_t V1Layer::sOBSpaceFrameWidth = 42.0 * sMm; +const Double_t V1Layer::sOBSpaceFrameTotHigh = 43.1 * sMm; +const Double_t V1Layer::sOBSFrameBeamRadius = 0.6 * sMm; +const Double_t V1Layer::sOBSpaceFrameLa = 3.0 * sMm; +const Double_t V1Layer::sOBSpaceFrameHa = 0.721979 * sMm; +const Double_t V1Layer::sOBSpaceFrameLb = 3.7 * sMm; +const Double_t V1Layer::sOBSpaceFrameHb = 0.890428 * sMm; +const Double_t V1Layer::sOBSpaceFrameL = 0.25 * sMm; +const Double_t V1Layer::sOBSFBotBeamAngle = 56.5; +const Double_t V1Layer::sOBSFrameBeamSidePhi = 65.0; + +ClassImp(V1Layer); + +#define SQ(A) (A) * (A) + +V1Layer::V1Layer() + : V11Geometry(), + mLayerNumber(0), + mPhi0(0), + mLayerRadius(0), + mZLength(0), + mSensorThickness(0), + mStaveThickness(0), + mStaveWidth(0), + mStaveTilt(0), + mNumberOfStaves(0), + mNumberOfModules(0), + mNumberOfChips(0), + mChipTypeID(0), + mIsTurbo(false), + mBuildLevel(0), + mStaveModel(Detector::kIBModelDummy) +{ + for (int i = kNHLevels; i--;) { + mHierarchy[i] = 0; + } +} + +V1Layer::V1Layer(Int_t debug) + : V11Geometry(debug), + mLayerNumber(0), + mPhi0(0), + mLayerRadius(0), + mZLength(0), + mSensorThickness(0), + mStaveThickness(0), + mStaveWidth(0), + mStaveTilt(0), + mNumberOfStaves(0), + mNumberOfModules(0), + mNumberOfChips(0), + mChipTypeID(0), + mIsTurbo(false), + mBuildLevel(0), + mStaveModel(Detector::kIBModelDummy) +{ + for (int i = kNHLevels; i--;) { + mHierarchy[i] = 0; + } +} + +V1Layer::V1Layer(Int_t lay, Int_t debug) + : V11Geometry(debug), + mLayerNumber(lay), + mPhi0(0), + mLayerRadius(0), + mZLength(0), + mSensorThickness(0), + mStaveThickness(0), + mStaveWidth(0), + mStaveTilt(0), + mNumberOfStaves(0), + mNumberOfModules(0), + mNumberOfChips(0), + mChipTypeID(0), + mIsTurbo(false), + mBuildLevel(0), + mStaveModel(Detector::kIBModelDummy) +{ + for (int i = kNHLevels; i--;) { + mHierarchy[i] = 0; + } +} + +V1Layer::V1Layer(Int_t lay, Bool_t turbo, Int_t debug) + : V11Geometry(debug), + mLayerNumber(lay), + mPhi0(0), + mLayerRadius(0), + mZLength(0), + mSensorThickness(0), + mStaveThickness(0), + mStaveWidth(0), + mStaveTilt(0), + mNumberOfStaves(0), + mNumberOfModules(0), + mNumberOfChips(0), + mChipTypeID(0), + mIsTurbo(turbo), + mBuildLevel(0), + mStaveModel(Detector::kIBModelDummy) +{ + for (int i = kNHLevels; i--;) { + mHierarchy[i] = 0; + } +} + +V1Layer::V1Layer(const V1Layer& s) + : V11Geometry(s.getDebug()), + mLayerNumber(s.mLayerNumber), + mPhi0(s.mPhi0), + mLayerRadius(s.mLayerRadius), + mZLength(s.mZLength), + mSensorThickness(s.mSensorThickness), + mStaveThickness(s.mStaveThickness), + mStaveWidth(s.mStaveWidth), + mStaveTilt(s.mStaveTilt), + mNumberOfStaves(s.mNumberOfStaves), + mNumberOfModules(s.mNumberOfModules), + mNumberOfChips(s.mNumberOfChips), + mChipTypeID(s.mChipTypeID), + mIsTurbo(s.mIsTurbo), + mBuildLevel(s.mBuildLevel), + mStaveModel(s.mStaveModel) +{ + for (int i = kNHLevels; i--;) { + mHierarchy[i] = s.mHierarchy[i]; + } +} + +V1Layer& V1Layer::operator=(const V1Layer& s) +{ + if (&s == this) { + return *this; + } + + mLayerNumber = s.mLayerNumber; + mPhi0 = s.mPhi0; + mLayerRadius = s.mLayerRadius; + mZLength = s.mZLength; + mSensorThickness = s.mSensorThickness; + mStaveThickness = s.mStaveThickness; + mStaveWidth = s.mStaveWidth; + mStaveTilt = s.mStaveTilt; + mNumberOfStaves = s.mNumberOfStaves; + mNumberOfModules = s.mNumberOfModules; + mNumberOfChips = s.mNumberOfChips; + mIsTurbo = s.mIsTurbo; + mChipTypeID = s.mChipTypeID; + mBuildLevel = s.mBuildLevel; + mStaveModel = s.mStaveModel; + for (int i = kNHLevels; i--;) { + mHierarchy[i] = s.mHierarchy[i]; + } + + return *this; +} + +V1Layer::~V1Layer() = default; + +void V1Layer::createLayer(TGeoVolume* motherVolume) +{ + char volumeName[30]; + Double_t xpos, ypos, zpos; + Double_t alpha; + + // Check if the user set the proper parameters + if (mLayerRadius <= 0) { + LOG(FATAL) << "Wrong layer radius " << mLayerRadius; + } + + if (mZLength <= 0) { + LOG(FATAL) << "Wrong layer length " << mZLength; + } + + if (mNumberOfStaves <= 0) { + LOG(FATAL) << "Wrong number of staves " << mNumberOfStaves; + } + + if (mNumberOfChips <= 0) { + LOG(FATAL) << "Wrong number of chips " << mNumberOfChips; + } + + if (mLayerNumber >= sNumberOmInnerLayers && mNumberOfModules <= 0) { + LOG(FATAL) << "Wrong number of modules " << mNumberOfModules; + } + + if (mStaveThickness <= 0) { + LOG(INFO) << "Stave thickness wrong or not set " << mStaveThickness << " using default " + << sDefaultStaveThick; + mStaveThickness = sDefaultStaveThick; + } + + if (mSensorThickness <= 0) { + LOG(INFO) << "Sensor thickness wrong or not set " << mSensorThickness << " using default " + << sDefaultSensorThick; + mSensorThickness = sDefaultSensorThick; + } + + if (mSensorThickness > mStaveThickness) { + LOG(WARNING) << "Sensor thickness " << mSensorThickness << " is greater than stave thickness " + << mStaveThickness << " fixing"; + mSensorThickness = mStaveThickness; + } + + // If a Turbo layer is requested, do it and exit + if (mIsTurbo) { + createLayerTurbo(motherVolume); + return; + } + + // First create the stave container + alpha = (360. / (2 * mNumberOfStaves)) * DegToRad(); + + // mStaveWidth = mLayerRadius*Tan(alpha); + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); + layerVolume->SetUniqueID(mChipTypeID); + + // layerVolume->SetVisibility(kFALSE); + layerVolume->SetVisibility(kTRUE); + layerVolume->SetLineColor(1); + + TGeoVolume* stavVol = createStave(); + + // Now build up the layer + alpha = 360. / mNumberOfStaves; + Double_t r = mLayerRadius + ((TGeoBBox*)stavVol->GetShape())->GetDY(); + for (Int_t j = 0; j < mNumberOfStaves; j++) { + Double_t phi = j * alpha + mPhi0; + xpos = r * cosD(phi); // r*sinD(-phi); + ypos = r * sinD(phi); // r*cosD(-phi); + zpos = 0.; + phi += 90; + layerVolume->AddNode(stavVol, j, + new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", phi, 0, 0))); + } + + // Finally put everything in the mother volume + motherVolume->AddNode(layerVolume, 1, nullptr); + + // geometry is served + return; +} + +void V1Layer::createLayerTurbo(TGeoVolume* motherVolume) +{ + char volumeName[30]; + Double_t xpos, ypos, zpos; + Double_t alpha; + + // Check if the user set the proper (remaining) parameters + if (mStaveWidth <= 0) { + LOG(FATAL) << "Wrong stave width " << mStaveWidth; + } + + if (Abs(mStaveTilt) > 45) { + LOG(WARNING) << "Stave tilt angle (" << mStaveTilt << ") greater than 45deg"; + } + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); + layerVolume->SetUniqueID(mChipTypeID); + layerVolume->SetVisibility(kTRUE); + layerVolume->SetLineColor(1); + TGeoVolume* stavVol = createStave(); + + // Now build up the layer + alpha = 360. / mNumberOfStaves; + Double_t r = mLayerRadius /* +chip thick ?! */; + for (Int_t j = 0; j < mNumberOfStaves; j++) { + Double_t phi = j * alpha + mPhi0; + xpos = r * cosD(phi); // r*sinD(-phi); + ypos = r * sinD(phi); // r*cosD(-phi); + zpos = 0.; + phi += 90; + layerVolume->AddNode( + stavVol, j, + new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", phi - mStaveTilt, 0, 0))); + } + + // Finally put everything in the mother volume + motherVolume->AddNode(layerVolume, 1, nullptr); + + return; +} + +TGeoVolume* V1Layer::createStave(const TGeoManager* /*mgr*/) +{ + char volumeName[30]; + + Double_t xlen, ylen, zlen; + Double_t xpos, ypos; + Double_t alpha; + + // First create all needed shapes + alpha = (360. / (2 * mNumberOfStaves)) * DegToRad(); + + // The stave + xlen = mLayerRadius * Tan(alpha); + if (mIsTurbo) { + xlen = 0.5 * mStaveWidth; + } + ylen = 0.5 * mStaveThickness; + zlen = 0.5 * mZLength; + + Double_t yplus = 0.46; + auto* stave = new TGeoXtru(2); // z sections + Double_t xv[5] = {xlen, xlen, 0, -xlen, -xlen}; + Double_t yv[5] = {ylen + 0.09, -0.15, -yplus - mSensorThickness, -0.15, ylen + 0.09}; + stave->DefinePolygon(5, xv, yv); + stave->DefineSection(0, -zlen, 0, 0, 1.); + stave->DefineSection(1, +zlen, 0, 0, 1.); + + // We have all shapes: now create the real volumes + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); + // TGeoVolume *staveVol = new TGeoVolume(volumeName, stave, medAir); + TGeoVolume* staveVol = new TGeoVolumeAssembly(volumeName); + + // staveVol->SetVisibility(kFALSE); + staveVol->SetVisibility(kTRUE); + staveVol->SetLineColor(2); + TGeoVolume* mechStaveVol = nullptr; + + // Now build up the stave + if (mLayerNumber < sNumberOmInnerLayers) { + TGeoVolume* modVol = createStaveInnerB(xlen, ylen, zlen); + staveVol->AddNode(modVol, 0); + mHierarchy[kHalfStave] = 1; + + // Mechanical stave structure + mechStaveVol = createStaveStructInnerB(xlen, zlen); + if (mechStaveVol) { + ypos = ((TGeoBBox*)(modVol->GetShape()))->GetDY() + + ((TGeoBBox*)(mechStaveVol->GetShape()))->GetDY(); + staveVol->AddNode(mechStaveVol, 1, + new TGeoCombiTrans(0, -ypos, 0, new TGeoRotation("", 0, 0, 180))); + } + } else { + TGeoVolume* hstaveVol = createStaveOuterB(); + if (mStaveModel == Detector::kOBModel0) { // Create simplified stave struct as in v0 + staveVol->AddNode(hstaveVol, 0); + mHierarchy[kHalfStave] = 1; + } else { // (if mStaveModel) Create new stave struct as in TDR + xpos = ((TGeoBBox*)(hstaveVol->GetShape()))->GetDX() - sOBHalfStaveXOverlap / 2; + // ypos is CF height as computed in createSpaceFrameOuterB1 + ypos = (sOBSpaceFrameTotHigh - sOBHalfStaveYTrans) / 2; + staveVol->AddNode(hstaveVol, 0, new TGeoTranslation(-xpos, ypos, 0)); + staveVol->AddNode(hstaveVol, 1, new TGeoTranslation(xpos, ypos + sOBHalfStaveYTrans, 0)); + mHierarchy[kHalfStave] = 2; // RS + mechStaveVol = createSpaceFrameOuterB(); + + if (mechStaveVol) { + staveVol->AddNode(mechStaveVol, 1, + new TGeoCombiTrans(0, 0, 0, new TGeoRotation("", 180, 0, 0))); + } + } + } + // Done, return the stave + return staveVol; +} + +TGeoVolume* V1Layer::createStaveInnerB(const Double_t xsta, const Double_t ysta, + const Double_t zsta, const TGeoManager* mgr) +{ + Double_t xmod, ymod, zmod; + char volumeName[30]; + + // First we create the module (i.e. the HIC with 9 chips) + TGeoVolume* moduleVol = createModuleInnerB(xsta, ysta, zsta); + + // Then we create the fake halfstave and the actual stave + xmod = ((TGeoBBox*)(moduleVol->GetShape()))->GetDX(); + ymod = ((TGeoBBox*)(moduleVol->GetShape()))->GetDY(); + zmod = ((TGeoBBox*)(moduleVol->GetShape()))->GetDZ(); + + auto* hstave = new TGeoBBox(xmod, ymod, zmod); + + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + auto* hstaveVol = new TGeoVolume(volumeName, hstave, medAir); + + // Finally build it up + hstaveVol->AddNode(moduleVol, 0); + mHierarchy[kModule] = 1; + + // Done, return the stave structure + return hstaveVol; +} + +TGeoVolume* V1Layer::createModuleInnerB(Double_t xmod, Double_t ymod, Double_t zmod, + const TGeoManager* mgr) +{ + Double_t zchip; + Double_t zpos; + char volumeName[30]; + + // First create the single chip + zchip = zmod / sIBChipsPerRow; + TGeoVolume* chipVol = createChipInnerB(xmod, ymod, zchip); + + // Then create the module and populate it with the chips + auto* module = new TGeoBBox(xmod, ymod, zmod); + + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + auto* modVol = new TGeoVolume(volumeName, module, medAir); + + // mm (not used) zlen = ((TGeoBBox*)chipVol->GetShape())->GetDZ(); + for (Int_t j = 0; j < sIBChipsPerRow; j++) { + zpos = -zmod + j * 2 * zchip + zchip; + modVol->AddNode(chipVol, j, new TGeoTranslation(0, 0, zpos)); + mHierarchy[kChip]++; + } + // Done, return the module + return modVol; +} + +TGeoVolume* V1Layer::createStaveStructInnerB(const Double_t xsta, const Double_t zsta, + const TGeoManager* mgr) +{ + TGeoVolume* mechStavVol = nullptr; + + switch (mStaveModel) { + case Detector::kIBModelDummy: + mechStavVol = createStaveModelInnerBDummy(xsta, zsta, mgr); + break; + case Detector::kIBModel0: + mechStavVol = createStaveModelInnerB0(xsta, zsta, mgr); + break; + case Detector::kIBModel1: + mechStavVol = createStaveModelInnerB1(xsta, zsta, mgr); + break; + case Detector::kIBModel21: + mechStavVol = createStaveModelInnerB21(xsta, zsta, mgr); + break; + case Detector::kIBModel22: + mechStavVol = createStaveModelInnerB22(xsta, zsta, mgr); + break; + case Detector::kIBModel3: + mechStavVol = createStaveModelInnerB3(xsta, zsta, mgr); + break; + default: + LOG(FATAL) << "Unknown stave model " << mStaveModel; + break; + } + return mechStavVol; +} + +TGeoVolume* V1Layer::createStaveModelInnerBDummy(const Double_t, const Double_t, + const TGeoManager*) const +{ + // Done, return the stave structur + return nullptr; +} + +TGeoVolume* V1Layer::createStaveModelInnerB0(const Double_t xsta, const Double_t zsta, + const TGeoManager* mgr) +{ + // Materials defined in Detector + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + LOG(INFO) << "################################# pointer :" << medWater; + TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); + LOG(INFO) << "################################# pointer :" << medM60J3K; + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); + + // Local parameters + Double_t kConeOutRadius = 0.15 / 2; + Double_t kConeInRadius = 0.1430 / 2; + Double_t kStaveLength = zsta * 2; + Double_t kStaveWidth = xsta * 2 - kConeOutRadius * 2; + Double_t kWidth = kStaveWidth / 4; // 1/2 of kWidth + Double_t kStaveHeight = 0.3; + Double_t kHeight = kStaveHeight / 2; + Double_t kAlpha = 90 - 67; // 90-33.69; + Double_t kTheta = kAlpha * TMath::DegToRad(); + Double_t kS1 = kWidth / TMath::Sin(kTheta); + Double_t kL1 = kWidth / TMath::Tan(kTheta); + Double_t kS2 = TMath::Sqrt(kHeight * kHeight + kS1 * kS1); // TMath::Sin(the2); + Double_t kThe2 = TMath::ATan(kHeight / kS1); + Double_t kBeta = kThe2 * TMath::RadToDeg(); + // Int_t loop = kStaveLength/(kL1); + // Double_t s3 = kWidth/(2*TMath::Sin(kTheta)); + // Double_t s4 = 3*kWidth/(2*TMath::Sin(kTheta)); + + LOG(DEBUG1) << "BuildLevel " << mBuildLevel; + + char volumeName[30]; + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + mLayerNumber); + + Double_t z = 0, y = -0.011 + 0.0150, x = 0; + + TGeoVolume* mechStavVol = nullptr; + + if (mBuildLevel < 5) { + + // world (trapezoid) + auto* mechStruct = new TGeoXtru(2); // z sections + Double_t xv[5] = { + kStaveWidth / 2 + 0.1, kStaveWidth / 2 + 0.1, 0, -kStaveWidth / 2 - 0.1, + -kStaveWidth / 2 - 0.1}; + Double_t yv[5] = {-kConeOutRadius * 2 - 0.07, 0, kStaveHeight, 0, -kConeOutRadius * 2 - 0.07}; + mechStruct->DefinePolygon(5, xv, yv); + mechStruct->DefineSection(0, -kStaveLength - 0.1, 0, 0, 1.); + mechStruct->DefineSection(1, kStaveLength + 0.1, 0, 0, 1.); + + mechStavVol = new TGeoVolume(volumeName, mechStruct, medAir); + mechStavVol->SetLineColor(12); + mechStavVol->SetFillColor(12); + mechStavVol->SetVisibility(kTRUE); + + // detailed structure ++++++++++++++ + // Pipe Kapton grey-35 + auto* coolTube = new TGeoTube(kConeInRadius, kConeOutRadius, kStaveLength / 2); + auto* volCoolTube = new TGeoVolume("pipe", coolTube, medKapton); + volCoolTube->SetFillColor(35); + volCoolTube->SetLineColor(35); + mechStavVol->AddNode(volCoolTube, 0, new TGeoTranslation(x + (kStaveWidth / 2), y - (kHeight - kConeOutRadius), 0)); + mechStavVol->AddNode(volCoolTube, 1, new TGeoTranslation(x - (kStaveWidth / 2), y - (kHeight - kConeOutRadius), 0)); + } + + if (mBuildLevel < 4) { + auto* coolTubeW = new TGeoTube(0., kConeInRadius, kStaveLength / 2); + auto* volCoolTubeW = new TGeoVolume("pipeWater", coolTubeW, medWater); + volCoolTubeW->SetFillColor(4); + volCoolTubeW->SetLineColor(4); + mechStavVol->AddNode(volCoolTubeW, 0, new TGeoTranslation(x + (kStaveWidth / 2), y - (kHeight - kConeOutRadius), 0)); + mechStavVol->AddNode(volCoolTubeW, 1, new TGeoTranslation(x - (kStaveWidth / 2), y - (kHeight - kConeOutRadius), 0)); + } + + // frequency of filament + // n = 4 means very dense(4 filaments per interval) + // n = 2 means dense(2 filaments per interval) + Int_t n = 4; + Int_t loop = (Int_t)(kStaveLength / (4 * kL1 / n) + 2 / n) - 1; + if (mBuildLevel < 3) { + // Top CFRP Filament black-12 Carbon structure TGeoBBox (length,thickness,width) + auto* t2 = new TGeoBBox(kS2, 0.007 / 2, 0.15 / 2); //(kS2,0.002,0.02); + auto* volT2 = new TGeoVolume("TopFilament", t2, medM60J3K); + volT2->SetLineColor(12); + volT2->SetFillColor(12); + + for (int i = 1; i < loop; i++) { // i<60;i++){ + mechStavVol->AddNode( + volT2, 4 * i + 0, + new TGeoCombiTrans( + x + kWidth, y + (2 * kConeOutRadius), + z - kStaveLength / 2 + (i * (4 / n) * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT2", 90, 90 - kAlpha, 90 - kBeta))); + mechStavVol->AddNode( + volT2, 4 * i + 1, + new TGeoCombiTrans( + x - kWidth, y + (2 * kConeOutRadius), + z - kStaveLength / 2 + (i * (4 / n) * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT2", 90, -90 + kAlpha, -90 + kBeta))); + mechStavVol->AddNode( + volT2, 4 * i + 2, + new TGeoCombiTrans( + x + kWidth, y + (2 * kConeOutRadius), + z - kStaveLength / 2 + (i * (4 / n) * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT2", 90, -90 + kAlpha, 90 - kBeta))); + mechStavVol->AddNode( + volT2, 4 * i + 3, + new TGeoCombiTrans( + x - kWidth, y + (2 * kConeOutRadius), + z - kStaveLength / 2 + (i * (4 / n) * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT2", 90, 90 - kAlpha, -90 + kBeta))); + } + + // Bottom CFRP Filament black-12 Carbon structure TGeoBBox (thickness,width,length) + auto* t1 = new TGeoBBox(0.007 / 2, 0.15 / 2, kS1); //(0.002,0.02,kS1); + auto* volT1 = new TGeoVolume("CFRPBottom", t1, medM60J3K); + volT1->SetLineColor(12); + volT1->SetFillColor(12); + + for (int i = 1; i < loop; i++) { + mechStavVol->AddNode( + volT1, 4 * i + 0, + new TGeoCombiTrans(x + kWidth, y - kHeight, z - kStaveLength / 2 + ((4 / n) * kL1 * i) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT1", -90, kAlpha, 0))); + mechStavVol->AddNode( + volT1, 4 * i + 1, + new TGeoCombiTrans(x - kWidth, y - kHeight, z - kStaveLength / 2 + ((4 / n) * kL1 * i) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT1", 90, kAlpha, 0))); + mechStavVol->AddNode( + volT1, 4 * i + 2, + new TGeoCombiTrans(x + kWidth, y - kHeight, z - kStaveLength / 2 + (i * (4 / n) * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT1", -90, -kAlpha, 0))); + mechStavVol->AddNode( + volT1, 4 * i + 3, + new TGeoCombiTrans(x - kWidth, y - kHeight, z - kStaveLength / 2 + (i * (4 / n) * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volT1", -90, +kAlpha, 0))); + } + } + + if (mBuildLevel < 2) { + // Glue CFRP-Silicon layers TGeoBBox(thickness,width,kS1); + auto* tG = new TGeoBBox(0.0075 / 2, 0.18 / 2, kS1); + auto* volTG = new TGeoVolume("Glue1", tG, medGlue); + volTG->SetLineColor(5); + volTG->SetFillColor(5); + + for (int i = 1; i < loop; i++) { // i<60;i++){ + mechStavVol->AddNode( + volTG, 4 * i + 0, + new TGeoCombiTrans(x + kWidth, y - 0.16, z - kStaveLength / 2 + ((4 / n) * kL1 * i) + kS1 / 2, // z-14.25+(2*kL1*i), + new TGeoRotation("volTG", -90, kAlpha, 0))); + mechStavVol->AddNode( + volTG, 4 * i + 1, + new TGeoCombiTrans(x - kWidth, y - 0.16, z - kStaveLength / 2 + ((4 / n) * kL1 * i) + kS1 / 2, // z-14.25+(2*kL1*i), + new TGeoRotation("volTG", 90, kAlpha, 0))); + mechStavVol->AddNode( + volTG, 4 * i + 2, + new TGeoCombiTrans(x + kWidth, y - 0.16, z - kStaveLength / 2 + ((4 / n) * i * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volTG", -90, -kAlpha, 0))); + mechStavVol->AddNode( + volTG, 4 * i + 3, + new TGeoCombiTrans(x - kWidth, y - 0.16, z - kStaveLength / 2 + (i * (4 / n) * kL1) + kS1 / 2, // z-14.25+(i*2*kL1), + new TGeoRotation("volTG", -90, +kAlpha, 0))); + } + + auto* glue = new TGeoBBox(xsta, 0.005 / 2, zsta); + auto* volGlue = new TGeoVolume("Glue2", glue, medGlue); + volGlue->SetLineColor(5); + volGlue->SetFillColor(5); + // mechStavVol->AddNode(volGlue, 0, new TGeoCombiTrans(x, y-0.16, z, new TGeoRotation("",0, 0, + // 0))); + mechStavVol->AddNode(volGlue, 1, new TGeoCombiTrans(x, y - 0.165 - mSensorThickness - 0.005, z, new TGeoRotation("", 0, 0, 0))); + } + + if (mBuildLevel < 1) { + // Flex cable brown-28 TGeoBBox(width,thickness,length); + auto* kapCable = new TGeoBBox(xsta, 0.01 / 2, zsta); + auto* volCable = new TGeoVolume("FlexCable", kapCable, medFlexCable); + volCable->SetLineColor(28); + volCable->SetFillColor(28); + mechStavVol->AddNode(volCable, 0, + new TGeoCombiTrans(x, y - 0.165 - mSensorThickness - 0.005 - 0.01, z, + new TGeoRotation("", 0, 0, 0))); + } + // Done, return the stave structur + return mechStavVol; +} + +TGeoVolume* V1Layer::createStaveModelInnerB1(const Double_t xsta, const Double_t zsta, + const TGeoManager* mgr) +{ + // Materials defined in Detector + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + + TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); + + // Local parameters + Double_t kConeOutRadius = 0.15 / 2; + // Double_t kConeInRadius = 0.1430/2; + Double_t kStaveLength = zsta * 2; + // Double_t kStaveWidth = xsta*2-kConeOutRadius*2; + Double_t kStaveWidth = xsta * 2; + Double_t kWidth = kStaveWidth / 4; // 1/2 of kWidth + Double_t kStaveHeight = 0.3; + Double_t kHeight = kStaveHeight / 2; + Double_t kAlpha = 90 - 33.; // 90-30; + Double_t kTheta = kAlpha * TMath::DegToRad(); + Double_t kS1 = kWidth / TMath::Sin(kTheta); + Double_t kL1 = kWidth / TMath::Tan(kTheta); + Double_t kS2 = TMath::Sqrt(kHeight * kHeight + kS1 * kS1); // TMath::Sin(the2); + Double_t kThe2 = TMath::ATan(kHeight / kS1); + Double_t kBeta = kThe2 * TMath::RadToDeg(); + Int_t loop = (Int_t)((kStaveLength / (2 * kL1)) / 2); + + TGeoVolume* mechStavVol = nullptr; + + char volumeName[30]; + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + mLayerNumber); + + // detailed structure ++++++++++++++ + Double_t z = 0, y = -0.011 + 0.0150, x = 0; + + // Polimide micro channels numbers + Double_t yMC = y - kHeight + 0.01; + Int_t nb = (Int_t)(kStaveWidth / 0.1) + 1; + Double_t xstaMC = (nb * 0.1 - 0.08) / 2; + + if (mBuildLevel < 5) { + // world (trapezoid) + auto* mechStruct = new TGeoXtru(2); // z sections + Double_t xv[5] = { + kStaveWidth / 2 + 0.1, kStaveWidth / 2 + 0.1, 0, -kStaveWidth / 2 - 0.1, + -kStaveWidth / 2 - 0.1}; + Double_t yv[5] = {-kConeOutRadius * 2 - 0.07, 0, kStaveHeight, 0, -kConeOutRadius * 2 - 0.07}; + mechStruct->DefinePolygon(5, xv, yv); + mechStruct->DefineSection(0, -kStaveLength - 0.1, 0, 0, 1.); + mechStruct->DefineSection(1, kStaveLength + 0.1, 0, 0, 1.); + + mechStavVol = new TGeoVolume(volumeName, mechStruct, medAir); + mechStavVol->SetLineColor(12); + mechStavVol->SetFillColor(12); + mechStavVol->SetVisibility(kTRUE); + + // Polimide micro channels numbers + auto* tM0 = new TGeoBBox(xstaMC, 0.005 / 2, zsta); + auto* volTM0 = new TGeoVolume("MicroChanCover", tM0, medKapton); + volTM0->SetLineColor(35); + volTM0->SetFillColor(35); + mechStavVol->AddNode(volTM0, 0, + new TGeoCombiTrans(x, -0.0125 + yMC, z, new TGeoRotation("", 0, 0, 0))); + mechStavVol->AddNode(volTM0, 1, + new TGeoCombiTrans(x, +0.0125 + yMC, z, new TGeoRotation("", 0, 0, 0))); + + auto* tM0b = new TGeoBBox(0.02 / 2, 0.02 / 2, zsta); + auto* volTM0b = new TGeoVolume("MicroChanWalls", tM0b, medKapton); + volTM0b->SetLineColor(35); + volTM0b->SetFillColor(35); + for (Int_t ib = 0; ib < nb; ib++) { + mechStavVol->AddNode(volTM0b, ib, new TGeoCombiTrans(x + ib * 0.1 - xstaMC + 0.01, yMC, z, new TGeoRotation("", 0, 0, 0))); + } + } + + if (mBuildLevel < 4) { + // Water in Polimide micro channels + auto* water = new TGeoBBox(0.08 / 2, 0.02 / 2, zsta + 0.1); + auto* volWater = new TGeoVolume("Water", water, medWater); + volWater->SetLineColor(4); + volWater->SetFillColor(4); + for (Int_t ib = 0; ib < (nb - 1); ib++) { + mechStavVol->AddNode(volWater, ib, new TGeoCombiTrans(x + ib * 0.1 - xstaMC + 0.06, yMC, z, new TGeoRotation("", 0, 0, 0))); + } + } + + if (mBuildLevel < 3) { + // Bottom filament CFRP black-12 Carbon structure TGeoBBox (thickness,width,length) + Double_t filWidth = 0.04; + Double_t filHeight = 0.02; + auto* t1 = new TGeoBBox(filHeight / 2, filWidth / 2, kS1); + auto* volT1 = new TGeoVolume("CFRPBottom", t1, medM60J3K); + volT1->SetLineColor(12); + volT1->SetFillColor(12); + for (int i = 0; i < loop; i++) { // i<30;i++){ + mechStavVol->AddNode(volT1, 4 * i + 0, + new TGeoCombiTrans(x + kWidth, y - kHeight + 0.04 + filHeight / 2, + z - kStaveLength / 2 + (4 * kL1) + kS1 / 2, + new TGeoRotation("volT1", -90, kAlpha, 0))); + mechStavVol->AddNode(volT1, 4 * i + 1, + new TGeoCombiTrans(x - kWidth, y - kHeight + 0.04 + filHeight / 2, + z - kStaveLength / 2 + (4 * kL1 * i) + kS1 / 2, + new TGeoRotation("volT1", 90, kAlpha, 0))); + mechStavVol->AddNode( + volT1, 4 * i + 2, + new TGeoCombiTrans(x + kWidth, y - kHeight + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT1", -90, -kAlpha, 0))); + mechStavVol->AddNode( + volT1, 4 * i + 3, + new TGeoCombiTrans(x - kWidth, y - kHeight + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT1", -90, +kAlpha, 0))); + } + + // Top filament CFRP black-12 Carbon structure TGeoBBox (length,thickness,width) + auto* t2 = new TGeoBBox(kS2, filHeight / 2, filWidth / 2); + auto* volT2 = new TGeoVolume("CFRPTop", t2, medM60J3K); + volT2->SetLineColor(12); + volT2->SetFillColor(12); + for (int i = 0; i < loop; i++) { // i<30;i++){ + mechStavVol->AddNode( + volT2, 4 * i + 0, + new TGeoCombiTrans(x + kWidth, y + 0.04 + filHeight / 2, + z - kStaveLength / 2 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, 90 - kAlpha, 90 - kBeta))); + mechStavVol->AddNode( + volT2, 4 * i + 1, + new TGeoCombiTrans(x - kWidth, y + 0.04 + filHeight / 2, + z - kStaveLength / 2 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, -90 + kAlpha, -90 + kBeta))); + mechStavVol->AddNode( + volT2, 4 * i + 2, + new TGeoCombiTrans(x + kWidth, y + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, -90 + kAlpha, 90 - kBeta))); + mechStavVol->AddNode( + volT2, 4 * i + 3, + new TGeoCombiTrans(x - kWidth, y + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, 90 - kAlpha, -90 + kBeta))); + } + } + + if (mBuildLevel < 2) { + // Glue between filament and polimide micro channel + auto* t3 = new TGeoBBox(0.01 / 2, 0.04, kS1); + auto* volT3 = new TGeoVolume("FilamentGlue", t3, medGlue); + volT3->SetLineColor(5); + volT3->SetFillColor(5); + for (int i = 0; i < loop; i++) { // i<30;i++){ + mechStavVol->AddNode(volT3, 4 * i + 0, + new TGeoCombiTrans(x + kWidth, y - kHeight + 0.0325, + z - kStaveLength / 2 + (4 * kL1 * i) + kS1 / 2, + new TGeoRotation("volT1", -90, kAlpha, 0))); + mechStavVol->AddNode(volT3, 4 * i + 1, + new TGeoCombiTrans(x - kWidth, y - kHeight + 0.0325, + z - kStaveLength / 2 + (4 * kL1 * i) + kS1 / 2, + new TGeoRotation("volT1", 90, kAlpha, 0))); + mechStavVol->AddNode( + volT3, 4 * i + 2, + new TGeoCombiTrans(x + kWidth, y - kHeight + 0.0325, + z - kStaveLength / 2 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT1", -90, -kAlpha, 0))); + mechStavVol->AddNode( + volT3, 4 * i + 3, + new TGeoCombiTrans(x - kWidth, y - kHeight + 0.0325, + z - kStaveLength / 2 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT1", -90, +kAlpha, 0))); + } + + // Glue microchannel and sensor + auto* glueM = new TGeoBBox(xsta, 0.01 / 2, zsta); + auto* volGlueM = new TGeoVolume("MicroChanGlue", glueM, medGlue); + volGlueM->SetLineColor(5); + volGlueM->SetFillColor(5); + mechStavVol->AddNode(volGlueM, 0, + new TGeoCombiTrans(x, y - 0.16, z, new TGeoRotation("", 0, 0, 0))); + + // Glue sensor and kapton + auto* glue = new TGeoBBox(xsta, 0.005 / 2, zsta); + auto* volGlue = new TGeoVolume("SensorGlue", glue, medGlue); + volGlue->SetLineColor(5); + volGlue->SetFillColor(5); + mechStavVol->AddNode(volGlue, 1, new TGeoCombiTrans(x, y - 0.165 - mSensorThickness - 0.005, z, new TGeoRotation("", 0, 0, 0))); + } + + if (mBuildLevel < 1) { + auto* kapCable = new TGeoBBox(xsta, 0.01 / 2, zsta); + auto* volCable = new TGeoVolume("FlexCable", kapCable, medFlexCable); + volCable->SetLineColor(28); + volCable->SetFillColor(28); + mechStavVol->AddNode(volCable, 0, + new TGeoCombiTrans(x, y - 0.165 - mSensorThickness - 0.005 - 0.01, z, + new TGeoRotation("", 0, 0, 0))); + } + // Done, return the stave structur + return mechStavVol; +} + +TGeoVolume* V1Layer::createStaveModelInnerB21(const Double_t xsta, const Double_t zsta, + const TGeoManager* mgr) +{ + // Materials defined in Detector + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + + TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); + TGeoMedium* medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); + TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + + // Local parameters + Double_t kConeOutRadius = 0.151384 / 2; + Double_t kConeInRadius = 0.145034 / 2; + Double_t kStaveLength = zsta; + Double_t kStaveWidth = xsta * 2; + Double_t kWidth = (kStaveWidth + 0.005) / 4; + Double_t kStaveHeigth = 0.33; // 0.33; + Double_t kHeight = (kStaveHeigth + 0.025) / 2; + Double_t kAlpha = 57; // 56.31; + Double_t kTheta = kAlpha * TMath::DegToRad(); + Double_t kS1 = (kStaveWidth / 4) / TMath::Sin(kTheta); + Double_t kL1 = (kStaveWidth / 4) / TMath::Tan(kTheta); + Double_t kS2 = sqrt(kHeight * kHeight + kS1 * kS1); // TMath::Sin(the2); + Double_t kThe2 = TMath::ATan(kHeight / kS1); + Double_t kBeta = kThe2 * TMath::RadToDeg(); + // Double_t lay1 = 0.003157; + Double_t kLay1 = 0.003; // Amec carbon + // Double_t lay2 = 0.0043215;//C Fleece carbon + Double_t kLay2 = 0.002; // C Fleece carbon + Double_t kLay3 = 0.007; // K13D2U carbon + Int_t loop = (Int_t)(kStaveLength / (2 * kL1)); + + char volumeName[30]; + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + mLayerNumber); + + Double_t z = 0, y = -(kConeOutRadius + 0.03) + 0.0385, x = 0; + + TGeoVolume* mechStavVol = nullptr; + + if (mBuildLevel < 5) { + // world (trapezoid) + auto* mechStruct = new TGeoXtru(2); // z sections + Double_t xv[5] = { + kStaveWidth / 2 + 0.1, kStaveWidth / 2 + 0.1, 0, -kStaveWidth / 2 - 0.1, + -kStaveWidth / 2 - 0.1}; + Double_t yv[5] = {-kConeOutRadius * 2 - 0.07, 0, kStaveHeigth, 0, -kConeOutRadius * 2 - 0.07}; + mechStruct->DefinePolygon(5, xv, yv); + mechStruct->DefineSection(0, -kStaveLength - 0.1, 0, 0, 1.); + mechStruct->DefineSection(1, kStaveLength + 0.1, 0, 0, 1.); + + mechStavVol = new TGeoVolume(volumeName, mechStruct, medAir); + mechStavVol->SetLineColor(12); + mechStavVol->SetFillColor(12); + mechStavVol->SetVisibility(kTRUE); + + // Pipe Kapton grey-35 + auto* cone1 = + new TGeoCone(kStaveLength, kConeInRadius, kConeOutRadius, kConeInRadius, kConeOutRadius); + auto* volCone1 = new TGeoVolume("PolyimidePipe", cone1, medKapton); + volCone1->SetFillColor(35); + volCone1->SetLineColor(35); + mechStavVol->AddNode(volCone1, 1, new TGeoTranslation(x + 0.25, y, z)); + mechStavVol->AddNode(volCone1, 2, new TGeoTranslation(x - 0.25, y, z)); + } + + if (mBuildLevel < 4) { + auto* coolTubeW = new TGeoTube(0., kConeInRadius, kStaveLength); + auto* volCoolTubeW = new TGeoVolume("Water", coolTubeW, medWater); + volCoolTubeW->SetFillColor(4); + volCoolTubeW->SetLineColor(4); + mechStavVol->AddNode(volCoolTubeW, 0, new TGeoTranslation(x - 0.25, y, z)); + mechStavVol->AddNode(volCoolTubeW, 1, new TGeoTranslation(x + 0.25, y, z)); + } + + if (mBuildLevel < 3) { + // top fillament + // Top filament M60J black-12 Carbon structure TGeoBBox (length,thickness,width) + auto* t2 = + new TGeoBBox(kS2, 0.02 / 2, 0.04 / 2); // TGeoBBox *t2=new TGeoBBox(kS2,0.01,0.02); + auto* volT2 = new TGeoVolume("TopFilament", t2, medM60J3K); + volT2->SetLineColor(12); + volT2->SetFillColor(12); + + for (int i = 0; i < loop; i++) { // i<28;i++){ + mechStavVol->AddNode( + volT2, i * 4 + 1, + new TGeoCombiTrans(x + kWidth, y + kHeight + (0.12 / 2) - 0.014 + 0.007, + z - kStaveLength + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, 90 - kAlpha, 90 - kBeta))); + mechStavVol->AddNode( + volT2, i * 4 + 2, + new TGeoCombiTrans(x - kWidth, y + kHeight + (0.12 / 2) - 0.014 + 0.007, + z - kStaveLength + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, -90 + kAlpha, -90 + kBeta))); + mechStavVol->AddNode( + volT2, i * 4 + 3, + new TGeoCombiTrans(x + kWidth, y + kHeight + (0.12 / 2) - 0.014 + 0.007, + z - kStaveLength + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, -90 + kAlpha, 90 - kBeta))); + mechStavVol->AddNode( + volT2, i * 4 + 4, + new TGeoCombiTrans(x - kWidth, y + kHeight + (0.12 / 2) - 0.014 + 0.007, + z - kStaveLength + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, 90 - kAlpha, -90 + kBeta))); + // mechStavVol->AddNode(volT2,i*4+1,new + // TGeoCombiTrans(x+kWidth+0.0036,y+kHeight-(0.12/2)+0.072,z+kStaveLength+(i*4*kL1)+kS1/2, new + // TGeoRotation("volT2",90,90-kAlpha,90-kBeta))); + } + + // wall side structure out + auto* box4 = new TGeoBBox(0.03 / 2, 0.12 / 2, kStaveLength - 0.50); + auto* plate4 = new TGeoVolume("WallOut", box4, medM60J3K); + plate4->SetFillColor(35); + plate4->SetLineColor(35); + mechStavVol->AddNode(plate4, 1, + new TGeoCombiTrans(x + (2 * kStaveWidth / 4) - (0.03 / 2), + y - 0.0022 - kConeOutRadius + 0.12 / 2 + 0.007, z, + new TGeoRotation("plate4", 0, 0, 0))); + mechStavVol->AddNode(plate4, 2, + new TGeoCombiTrans(x - (2 * kStaveWidth / 4) + (0.03 / 2), + y - 0.0022 - kConeOutRadius + 0.12 / 2 + 0.007, z, + new TGeoRotation("plate4", 0, 0, 0))); + // wall side in + auto* box5 = new TGeoBBox(0.015 / 2, 0.12 / 2, kStaveLength - 0.50); + auto* plate5 = new TGeoVolume("WallIn", box5, medM60J3K); + plate5->SetFillColor(12); + plate5->SetLineColor(12); + mechStavVol->AddNode(plate5, 1, + new TGeoCombiTrans(x + (2 * kStaveWidth / 4) - 0.03 - 0.015 / 2, + y - 0.0022 - kConeOutRadius + 0.12 / 2 + 0.007, z, + new TGeoRotation("plate5", 0, 0, 0))); + mechStavVol->AddNode(plate5, 2, + new TGeoCombiTrans(x - (2 * kStaveWidth / 4) + 0.03 + 0.015 / 2, + y - 0.0022 - kConeOutRadius + 0.12 / 2 + 0.007, z, + new TGeoRotation("plate5", 0, 0, 0))); + + // Amec Thermasol red-2 cover tube FGS300 + auto* cons1 = + new TGeoConeSeg(kStaveLength - 0.50, kConeOutRadius, kConeOutRadius + kLay1, kConeOutRadius, + kConeOutRadius + kLay1, 0, 180); + auto* cone11 = new TGeoVolume("ThermasolPipeCover", cons1, medFGS003); + cone11->SetFillColor(2); + cone11->SetLineColor(2); + mechStavVol->AddNode(cone11, 1, + new TGeoCombiTrans(x + 0.25, y, z, new TGeoRotation("Cone11", 0, 0, 0))); + mechStavVol->AddNode(cone11, 2, + new TGeoCombiTrans(x - 0.25, y, z, new TGeoRotation("Cone11", 0, 0, 0))); + + auto* box2 = + new TGeoBBox((0.50 - (2 * kConeOutRadius)) / 2, kLay1 / 2, kStaveLength - 0.50); + auto* plate2 = new TGeoVolume("ThermasolMiddle", box2, medFGS003); + plate2->SetFillColor(2); + plate2->SetLineColor(2); + mechStavVol->AddNode(plate2, 1, new TGeoCombiTrans(x, y - kConeOutRadius + (kLay1 / 2), z, new TGeoRotation("plate2", 0, 0, 0))); + + auto* box21 = + new TGeoBBox((0.75 - 0.25 - kConeOutRadius - kLay1) / 2, kLay1 / 2, kStaveLength - 0.50); + auto* plate21 = new TGeoVolume("ThermasolLeftRight", box21, medFGS003); + plate21->SetFillColor(2); + plate21->SetLineColor(2); + mechStavVol->AddNode( + plate21, 1, new TGeoCombiTrans(x + 0.25 + kConeOutRadius + (0.75 - 0.25 - kConeOutRadius) / 2 - (kLay1 / 2), y - kConeOutRadius + (kLay1 / 2), z, new TGeoRotation("plate21", 0, 0, 0))); + mechStavVol->AddNode( + plate21, 2, new TGeoCombiTrans(x - 0.25 - kConeOutRadius - (0.75 - 0.25 - kConeOutRadius) / 2 + (kLay1 / 2), y - kConeOutRadius + (kLay1 / 2), z, new TGeoRotation("plate21", 0, 0, 0))); + + auto* box22 = new TGeoBBox((kLay1 / 2), kConeOutRadius / 2, kStaveLength - 0.50); + auto* plate22 = new TGeoVolume("ThermasolVertical", box22, medFGS003); + plate22->SetFillColor(2); + plate22->SetLineColor(2); + mechStavVol->AddNode(plate22, 1, new TGeoCombiTrans(x + 0.25 + kConeOutRadius + (kLay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + mechStavVol->AddNode(plate22, 2, new TGeoCombiTrans(x + 0.25 - kConeOutRadius - (kLay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + mechStavVol->AddNode(plate22, 3, new TGeoCombiTrans(x - 0.25 + kConeOutRadius + (kLay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + mechStavVol->AddNode(plate22, 4, new TGeoCombiTrans(x - 0.25 - kConeOutRadius - (kLay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + + // C Fleece + auto* cons2 = + new TGeoConeSeg(kStaveLength - 0.50, kConeOutRadius + kLay1, kConeOutRadius + kLay1 + kLay2, + kConeOutRadius + kLay1, kConeOutRadius + kLay1 + kLay2, 0, 180); + auto* cone12 = new TGeoVolume("CFleecePipeCover", cons2, medCarbonFleece); + cone12->SetFillColor(28); + cone12->SetLineColor(28); + mechStavVol->AddNode(cone12, 1, + new TGeoCombiTrans(x + 0.25, y, z, new TGeoRotation("Cone12", 0, 0, 0))); + mechStavVol->AddNode(cone12, 2, + new TGeoCombiTrans(x - 0.25, y, z, new TGeoRotation("Cone12", 0, 0, 0))); + + auto* box3 = + new TGeoBBox((0.50 - (2 * (kConeOutRadius + kLay1))) / 2, kLay2 / 2, kStaveLength - 0.50); + auto* plate3 = new TGeoVolume("CFleeceMiddle", box3, medCarbonFleece); + plate3->SetFillColor(28); + plate3->SetLineColor(28); + mechStavVol->AddNode(plate3, 1, new TGeoCombiTrans(x, y - kConeOutRadius + kLay1 + (kLay2 / 2), z, new TGeoRotation("plate3", 0, 0, 0))); + + auto* box31 = + new TGeoBBox((0.75 - 0.25 - kConeOutRadius - kLay1) / 2, kLay2 / 2, kStaveLength - 0.50); + auto* plate31 = new TGeoVolume("CFleeceLeftRight", box31, medCarbonFleece); + plate31->SetFillColor(28); + plate31->SetLineColor(28); + mechStavVol->AddNode( + plate31, 1, + new TGeoCombiTrans( + x + 0.25 + kConeOutRadius + kLay1 + (0.75 - 0.25 - kConeOutRadius - kLay1) / 2, + y - kConeOutRadius + kLay1 + (kLay2 / 2), z, new TGeoRotation("plate31", 0, 0, 0))); + mechStavVol->AddNode( + plate31, 2, + new TGeoCombiTrans( + x - 0.25 - kConeOutRadius - kLay1 - (0.75 - 0.25 - kConeOutRadius - kLay1) / 2, + y - kConeOutRadius + kLay1 + (kLay2 / 2), z, new TGeoRotation("plate31", 0, 0, 0))); + + auto* box32 = new TGeoBBox((kLay2 / 2), (kConeOutRadius - kLay1) / 2, kStaveLength - 0.50); + auto* plate32 = new TGeoVolume("CFleeceVertical", box32, medCarbonFleece); + plate32->SetFillColor(28); + plate32->SetLineColor(28); + mechStavVol->AddNode(plate32, 1, + new TGeoCombiTrans(x + 0.25 + kConeOutRadius + kLay1 + (kLay2 / 2), + y + (kLay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + mechStavVol->AddNode(plate32, 2, + new TGeoCombiTrans(x + 0.25 - kConeOutRadius - kLay1 - (kLay2 / 2), + y + (kLay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + mechStavVol->AddNode(plate32, 3, + new TGeoCombiTrans(x - 0.25 + kConeOutRadius + kLay1 + (kLay2 / 2), + y + (kLay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + mechStavVol->AddNode(plate32, 4, + new TGeoCombiTrans(x - 0.25 - kConeOutRadius - kLay1 - (kLay2 / 2), + y + (kLay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + + // K13D2U carbon plate + auto* box1 = new TGeoBBox(2 * kWidth, kLay3 / 2, kStaveLength - 0.50); + auto* plate1 = new TGeoVolume("CarbonPlate", box1, medK13D2U2k); + plate1->SetFillColor(5); + plate1->SetLineColor(5); + mechStavVol->AddNode(plate1, 1, new TGeoCombiTrans(x, y - (kConeOutRadius + (kLay3 / 2)), z, new TGeoRotation("plate1", 0, 0, 0))); + + // C Fleece bottom plate + auto* box6 = new TGeoBBox(2 * kWidth, kLay2 / 2, kStaveLength - 0.50); + auto* plate6 = new TGeoVolume("CFleeceBottom", box6, medCarbonFleece); + plate6->SetFillColor(2); + plate6->SetLineColor(2); + mechStavVol->AddNode(plate6, 1, + new TGeoCombiTrans(x, y - (kConeOutRadius + kLay3 + (kLay2 / 2)), z, + new TGeoRotation("plate1", 0, 0, 0))); + } + + if (mBuildLevel < 2) { + // Glue layers and kapton + auto* glue = new TGeoBBox(kStaveWidth / 2, 0.005 / 2, zsta); + auto* volGlue = new TGeoVolume("Glue", glue, medGlue); + volGlue->SetLineColor(5); + volGlue->SetFillColor(5); + mechStavVol->AddNode( + volGlue, 0, new TGeoCombiTrans(x, y - (kConeOutRadius + kLay3 + (kLay2 / 2) + (0.01 / 2)), z, new TGeoRotation("", 0, 0, 0))); + mechStavVol->AddNode(volGlue, 1, + new TGeoCombiTrans(x, y - (kConeOutRadius + kLay3 + (kLay2 / 2) + 0.01 + mSensorThickness + (0.01 / 2)), + z, new TGeoRotation("", 0, 0, 0))); + } + + if (mBuildLevel < 1) { + auto* kapCable = new TGeoBBox(kStaveWidth / 2, 0.01 / 2, zsta); + auto* volCable = new TGeoVolume("FlexCable", kapCable, medFlexCable); + volCable->SetLineColor(28); + volCable->SetFillColor(28); + mechStavVol->AddNode(volCable, 0, + new TGeoCombiTrans(x, y - (kConeOutRadius + kLay3 + (kLay2 / 2) + 0.01 + mSensorThickness + 0.01 + (0.01 / 2)), + z, new TGeoRotation("", 0, 0, 0))); + } + // Done, return the stave structure + return mechStavVol; +} + +// new model22 +TGeoVolume* V1Layer::createStaveModelInnerB22(const Double_t xsta, const Double_t zsta, + const TGeoManager* mgr) +{ + // Materials defined in Detector + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + + TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); + TGeoMedium* medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); + TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + + // Local parameters + Double_t kConeOutRadius = (0.1024 + 0.0025) / 2; // 0.107/2; + Double_t kConeInRadius = 0.1024 / 2; // 0.10105/2 + Double_t kStaveLength = zsta; + Double_t kStaveWidth = xsta * 2; + Double_t kWidth = (kStaveWidth) / 4; + Double_t kStaveHeight = 0.283; // 0.33; + Double_t kHeight = (kStaveHeight) / 2; + Double_t kAlpha = 57; // 56.31; + Double_t kTheta = kAlpha * TMath::DegToRad(); + Double_t kS1 = ((kStaveWidth) / 4) / TMath::Sin(kTheta); + Double_t kL1 = (kStaveWidth / 4) / TMath::Tan(kTheta); + Double_t kS2 = sqrt(kHeight * kHeight + kS1 * kS1); // TMath::Sin(kThe2); + Double_t kThe2 = TMath::ATan(kHeight / (0.375 - 0.036)); + Double_t kBeta = kThe2 * TMath::RadToDeg(); + Double_t klay1 = 0.003; // Amec carbon + Double_t klay2 = 0.002; // C Fleece carbon + Double_t klay3 = 0.007; // CFplate K13D2U carbon + Double_t klay4 = 0.007; // GluekStaveLength/2 + Double_t klay5 = 0.01; // Flex cable + Double_t kTopVertexMaxWidth = 0.072; + Double_t kTopVertexHeight = 0.04; + Double_t kSideVertexMWidth = 0.052; + Double_t kSideVertexHeight = 0.11; + + Int_t loop = (Int_t)(kStaveLength / (2 * kL1)); + + char volumeName[30]; + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + mLayerNumber); + + Double_t z = 0, y = -(2 * kConeOutRadius) + klay1 + klay2 + mSensorThickness / 2 - 0.0004, x = 0; + + TGeoVolume* mechStavVol = nullptr; + + if (mBuildLevel < 5) { + // world (trapezoid) + auto* mechStruct = new TGeoXtru(2); // z sections + Double_t xv[6] = { + kStaveWidth / 2, kStaveWidth / 2, 0.012, + -0.012, -kStaveWidth / 2, -kStaveWidth / 2}; + // Double_t yv[6] = {-2*(kConeOutRadius+klay1+1.5*klay2+klay3+klay4+mSensorThickness+klay5), + // 0-0.02,kStaveHeight+0.01,kStaveHeight+0.01,0-0.02, + // -2*(kConeOutRadius+klay1+1.5*klay2+klay3+klay4+mSensorThickness+klay5)}; + // (kConeOutRadius*2)-0.0635 + Double_t yv[6] = { + -(kConeOutRadius * 2) - 0.06395, 0 - 0.02, kStaveHeight + 0.01, + kStaveHeight + 0.01, 0 - 0.02, -(kConeOutRadius * 2) - 0.06395}; // (kConeOutRadius*2)-0.064 + mechStruct->DefinePolygon(6, xv, yv); + mechStruct->DefineSection(0, -kStaveLength, 0, 0, 1.); + mechStruct->DefineSection(1, kStaveLength, 0, 0, 1.); + + mechStavVol = new TGeoVolume(volumeName, mechStruct, medAir); + mechStavVol->SetLineColor(12); + mechStavVol->SetFillColor(12); + mechStavVol->SetVisibility(kTRUE); + + // Polyimide Pipe Kapton grey-35 + auto* cone1 = new TGeoCone(kStaveLength, kConeInRadius, kConeOutRadius - 0.0001, + kConeInRadius, kConeOutRadius - 0.0001); + auto* volCone1 = new TGeoVolume("PolyimidePipe", cone1, medKapton); + volCone1->SetFillColor(35); + volCone1->SetLineColor(35); + mechStavVol->AddNode(volCone1, 1, new TGeoTranslation(x + 0.25, y, z)); + mechStavVol->AddNode(volCone1, 2, new TGeoTranslation(x - 0.25, y, z)); + } + + if (mBuildLevel < 4) { + auto* coolTubeW = new TGeoTube(0., kConeInRadius - 0.0001, kStaveLength); + auto* volCoolTubeW = new TGeoVolume("Water", coolTubeW, medWater); + volCoolTubeW->SetFillColor(4); + volCoolTubeW->SetLineColor(4); + mechStavVol->AddNode(volCoolTubeW, 0, new TGeoTranslation(x - 0.25, y, z)); + mechStavVol->AddNode(volCoolTubeW, 1, new TGeoTranslation(x + 0.25, y, z)); + } + + if (mBuildLevel < 3) { + // top fillament + // Top filament M60J black-12 Carbon structure TGeoBBox (length,thickness,width) + auto* t2 = new TGeoBBox( + kS2 - 0.028, 0.02 / 2, + 0.02 / 2); // 0.04/2//TGeoBBox *t2=new TGeoBBox(kS2,0.01,0.02);//kS2-0.03 old Config.C + auto* volT2 = new TGeoVolume("TopFilament", t2, medM60J3K); + volT2->SetLineColor(12); + volT2->SetFillColor(12); + for (int i = 0; i < loop; i++) { // i<28;i++){ + // 1) Front Left Top Filament + mechStavVol->AddNode( + volT2, i * 4 + 1, + new TGeoCombiTrans(x + kWidth + 0.0036, y + kHeight + 0.01, + z - kStaveLength + 0.1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, 90 - kAlpha, 90 - kBeta))); + // 2) Front Right Top Filament + mechStavVol->AddNode( + volT2, i * 4 + 2, + new TGeoCombiTrans(x - kWidth - 0.0036, y + kHeight + 0.01, + z - kStaveLength + 0.1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, -90 + kAlpha, -90 + kBeta))); + // 3) Back Left Top Filament + mechStavVol->AddNode( + volT2, i * 4 + 3, + new TGeoCombiTrans(x + kWidth + 0.0036, y + kHeight + 0.01, + z - kStaveLength + 0.1 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, -90 + kAlpha, 90 - kBeta))); + // 4) Back Right Top Filament + mechStavVol->AddNode( + volT2, i * 4 + 4, + new TGeoCombiTrans(x - kWidth - 0.0036, y + kHeight + 0.01, + z - kStaveLength + 0.1 + 2 * kL1 + (i * 4 * kL1) + kS1 / 2, + new TGeoRotation("volT2", 90, 90 - kAlpha, -90 + kBeta))); + } + + // Vertex structure + // top ver trd1 + auto* trd1 = new TGeoTrd1(0, kTopVertexMaxWidth / 2, kStaveLength, kTopVertexHeight / 2); + auto* ibdv = new TGeoVolume("TopVertex", trd1, medM60J3K); + ibdv->SetFillColor(12); + ibdv->SetLineColor(12); + mechStavVol->AddNode( + ibdv, 1, new TGeoCombiTrans(x, y + kStaveHeight + 0.03, z, new TGeoRotation("ibdv", 0., -90, 0))); // y+kStaveHeight+0.056 + + // left trd2 + auto* trd2 = new TGeoTrd1(0, kSideVertexMWidth / 2, kStaveLength, kSideVertexHeight / 2); + auto* ibdv2 = new TGeoVolume("LeftVertex", trd2, medM60J3K); + ibdv2->SetFillColor(12); + ibdv2->SetLineColor(12); + mechStavVol->AddNode( + ibdv2, 1, + new TGeoCombiTrans( + x + kStaveWidth / 2 - 0.06, y - 0.0355, z, + new TGeoRotation("ibdv2", -103.3, 90, 0))); // x-kStaveWidth/2-0.09 old Config.C y-0.0355, + + // right trd3 + auto* trd3 = new TGeoTrd1(0, kSideVertexMWidth / 2, kStaveLength, kSideVertexHeight / 2); + auto* ibdv3 = new TGeoVolume("RightVertex", trd3, medM60J3K); + ibdv3->SetFillColor(12); + ibdv3->SetLineColor(12); + mechStavVol->AddNode( + ibdv3, 1, new TGeoCombiTrans(x - kStaveWidth / 2 + 0.06, y - 0.0355, z, new TGeoRotation("ibdv3", 103.3, 90, 0))); // x-kStaveWidth/2+0.09 old Config.C + + // Carbon Fleece + auto* cons2 = + new TGeoConeSeg(zsta, kConeOutRadius + klay1, kConeOutRadius + klay1 + klay2, + kConeOutRadius + klay1, kConeOutRadius + klay1 + klay2, 0, 180); + auto* cone12 = new TGeoVolume("CarbonFleecePipeCover", cons2, medCarbonFleece); + cone12->SetFillColor(28); + cone12->SetLineColor(28); + mechStavVol->AddNode(cone12, 1, + new TGeoCombiTrans(x + 0.25, y, z, new TGeoRotation("cone12", 0, 0, 0))); + mechStavVol->AddNode(cone12, 2, + new TGeoCombiTrans(x - 0.25, y, z, new TGeoRotation("cone12", 0, 0, 0))); + + auto* box3 = new TGeoBBox((0.50 - (2 * (kConeOutRadius + klay1))) / 2, klay2 / 2, + zsta); // kStaveLength-0.50); + auto* plate3 = new TGeoVolume("CarbonFleeceMiddle", box3, medCarbonFleece); + plate3->SetFillColor(28); + plate3->SetLineColor(28); + mechStavVol->AddNode(plate3, 1, new TGeoCombiTrans(x, y - kConeOutRadius + klay1 + (klay2 / 2), z, new TGeoRotation("plate3", 0, 0, 0))); + + auto* box31 = + new TGeoBBox((0.75 - 0.25 - kConeOutRadius - klay1) / 2 + 0.0025, klay2 / 2, zsta); + auto* plate31 = new TGeoVolume("CarbonFleeceLeftRight", box31, medCarbonFleece); + plate31->SetFillColor(28); + plate31->SetLineColor(28); + mechStavVol->AddNode( + plate31, 1, + new TGeoCombiTrans( + x + 0.25 + kConeOutRadius + klay1 + (0.75 - 0.25 - kConeOutRadius - klay1) / 2, + y - kConeOutRadius + klay1 + (klay2 / 2), z, new TGeoRotation("plate31", 0, 0, 0))); + mechStavVol->AddNode( + plate31, 2, + new TGeoCombiTrans( + x - 0.25 - kConeOutRadius - klay1 - (0.75 - 0.25 - kConeOutRadius - klay1) / 2, + y - kConeOutRadius + klay1 + (klay2 / 2), z, new TGeoRotation("plate31", 0, 0, 0))); + + auto* box32 = new TGeoBBox((klay2 / 2), (kConeOutRadius - klay1) / 2, zsta); + auto* plate32 = new TGeoVolume("CarbonFleeceVertical", box32, medCarbonFleece); + plate32->SetFillColor(28); + plate32->SetLineColor(28); + mechStavVol->AddNode(plate32, 1, + new TGeoCombiTrans(x + 0.25 + kConeOutRadius + klay1 + (klay2 / 2), + y + (klay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + mechStavVol->AddNode(plate32, 2, + new TGeoCombiTrans(x + 0.25 - kConeOutRadius - klay1 - (klay2 / 2), + y + (klay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + mechStavVol->AddNode(plate32, 3, + new TGeoCombiTrans(x - 0.25 + kConeOutRadius + klay1 + (klay2 / 2), + y + (klay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + mechStavVol->AddNode(plate32, 4, + new TGeoCombiTrans(x - 0.25 - kConeOutRadius - klay1 - (klay2 / 2), + y + (klay1 - kConeOutRadius) / 2, z, + new TGeoRotation("plate32", 0, 0, 0))); + + // Amec Thermasol red-2 cover tube FGS300 or Carbon Paper + auto* cons1 = + new TGeoConeSeg(zsta, kConeOutRadius, kConeOutRadius + klay1 - 0.0001, kConeOutRadius, + kConeOutRadius + klay1 - 0.0001, 0, 180); // kConeOutRadius+klay1-0.0001 + auto* cone11 = new TGeoVolume("ThermasolPipeCover", cons1, medFGS003); + cone11->SetFillColor(2); + cone11->SetLineColor(2); + mechStavVol->AddNode(cone11, 1, + new TGeoCombiTrans(x + 0.25, y, z, new TGeoRotation("cone11", 0, 0, 0))); + mechStavVol->AddNode(cone11, 2, + new TGeoCombiTrans(x - 0.25, y, z, new TGeoRotation("cone11", 0, 0, 0))); + + auto* box2 = + new TGeoBBox((0.50 - (2 * kConeOutRadius)) / 2, (klay1 / 2), zsta); // kStaveLength-0.50); + auto* plate2 = new TGeoVolume("ThermasolMiddle", box2, medFGS003); + plate2->SetFillColor(2); + plate2->SetLineColor(2); + mechStavVol->AddNode(plate2, 1, new TGeoCombiTrans(x, y - kConeOutRadius + (klay1 / 2), z, new TGeoRotation("plate2", 0, 0, 0))); + + auto* box21 = + new TGeoBBox((0.75 - 0.25 - kConeOutRadius - klay1) / 2 + 0.0025, (klay1 / 2), zsta); + auto* plate21 = new TGeoVolume("ThermasolLeftRight", box21, medFGS003); + plate21->SetFillColor(2); + plate21->SetLineColor(2); + mechStavVol->AddNode( + plate21, 1, + new TGeoCombiTrans( + x + 0.25 + kConeOutRadius + (0.75 - 0.25 - kConeOutRadius) / 2 - (klay1 / 2) + 0.0025, + y - kConeOutRadius + (klay1 / 2), z, new TGeoRotation("plate21", 0, 0, 0))); + mechStavVol->AddNode( + plate21, 2, + new TGeoCombiTrans( + x - 0.25 - kConeOutRadius - (0.75 - 0.25 - kConeOutRadius) / 2 + (klay1 / 2) - 0.0025, + y - kConeOutRadius + (klay1 / 2), z, new TGeoRotation("plate21", 0, 0, 0))); + + auto* box22 = new TGeoBBox((klay1 / 2), kConeOutRadius / 2, zsta); + auto* plate22 = new TGeoVolume("ThermasolVertical", box22, medFGS003); + plate22->SetFillColor(2); + plate22->SetLineColor(2); + mechStavVol->AddNode(plate22, 1, new TGeoCombiTrans(x + 0.25 + kConeOutRadius + (klay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + mechStavVol->AddNode(plate22, 2, new TGeoCombiTrans(x + 0.25 - kConeOutRadius - (klay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + mechStavVol->AddNode(plate22, 3, new TGeoCombiTrans(x - 0.25 + kConeOutRadius + (klay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + mechStavVol->AddNode(plate22, 4, new TGeoCombiTrans(x - 0.25 - kConeOutRadius - (klay1 / 2), y - kConeOutRadius / 2, z, new TGeoRotation("plate22", 0, 0, 0))); + + // K13D2U CF plate + auto* box1 = new TGeoBBox(2 * kWidth, (klay3) / 2, zsta); + auto* plate1 = new TGeoVolume("CFPlate", box1, medK13D2U2k); + plate1->SetFillColor(5); + plate1->SetLineColor(5); + mechStavVol->AddNode(plate1, 1, new TGeoCombiTrans(x, y - (kConeOutRadius + (klay3 / 2)), z, new TGeoRotation("plate1", 0, 0, 0))); + + // C Fleece bottom plate + auto* box6 = new TGeoBBox(2 * kWidth, (klay2) / 2, zsta); + auto* plate6 = new TGeoVolume("CarbonFleeceBottom", box6, medCarbonFleece); + plate6->SetFillColor(2); + plate6->SetLineColor(2); + mechStavVol->AddNode(plate6, 1, + new TGeoCombiTrans(x, y - (kConeOutRadius + klay3 + (klay2 / 2)), z, + new TGeoRotation("plate6", 0, 0, 0))); + } + if (mBuildLevel < 2) { + // Glue klayers and kapton + auto* glue = new TGeoBBox(kStaveWidth / 2, (klay4) / 2, zsta); + auto* volGlue = new TGeoVolume("Glue", glue, medGlue); + volGlue->SetLineColor(5); + volGlue->SetFillColor(5); + // mechStavVol->AddNode(volGlue, 0, new + // TGeoCombiTrans(x,y-(kConeOutRadius+klay3+klay2+(klay4/2)), z, new TGeoRotation("",0, 0, 0))); + mechStavVol->AddNode( + volGlue, 0, + new TGeoCombiTrans(x, y - (kConeOutRadius + klay3 + klay2 + (klay4) / 2) + 0.00005, z, + new TGeoRotation("", 0, 0, 0))); + } + + if (mBuildLevel < 1) { + // Flex Cable or Bus + auto* kapCable = new TGeoBBox(kStaveWidth / 2, klay5 / 2, zsta); // klay5/2 + auto* volCable = new TGeoVolume("FlexCable", kapCable, medFlexCable); + volCable->SetLineColor(28); + volCable->SetFillColor(28); + // mechStavVol->AddNode(volCable, 0, new TGeoCombiTrans(x, + // y-(kConeOutRadius+klay3+klay2+klay4+mSensorThickness+(klay5)/2)+0.0002, z, new + // TGeoRotation("",0, + // 0, 0))); + mechStavVol->AddNode( + volCable, 0, + new TGeoCombiTrans( + x, y - (kConeOutRadius + klay3 + klay2 + klay4 + mSensorThickness + (klay5) / 2) + 0.01185, + z, new TGeoRotation("", 0, 0, 0))); + } + // Done, return the stave structe + return mechStavVol; +} + +// model3 +TGeoVolume* V1Layer::createStaveModelInnerB3(const Double_t xsta, const Double_t zsta, + const TGeoManager* mgr) +{ + // Materials defined in Detector + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + + TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); + // TGeoMedium *medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); + // TGeoMedium *medFGS003 = mgr->GetMedium("IT4_FGS003$"); + // TGeoMedium *medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + + // Local parameters + Double_t kConeOutRadius = 0.15 / 2; + Double_t kStaveLength = zsta * 2; + Double_t kStaveWidth = xsta * 2; + Double_t w = kStaveWidth / 4; // 1/2 of W + Double_t staveHeight = 0.3; + Double_t h = staveHeight / 2; + Double_t alpha = 90 - 33.; // 90-30; + Double_t the1 = alpha * TMath::DegToRad(); + Double_t s1 = w / TMath::Sin(the1); + Double_t l = w / TMath::Tan(the1); + Double_t s2 = TMath::Sqrt(h * h + s1 * s1); // TMath::Sin(the2); + Double_t the2 = TMath::ATan(h / s1); + Double_t beta = the2 * TMath::RadToDeg(); + Double_t klay4 = 0.007; // Glue + Double_t klay5 = 0.01; // Flexcable + Int_t loop = (Int_t)((kStaveLength / (2 * l)) / 2); + Double_t hh = 0.01; + Double_t ang1 = 0 * TMath::DegToRad(); + Double_t ang2 = 0 * TMath::DegToRad(); + Double_t ang3 = 0 * TMath::DegToRad(); + Int_t chips = 4; + Double_t headWidth = 0.25; + Double_t smcLength = kStaveLength / chips - 2 * headWidth; // 6.25; + Double_t smcWidth = kStaveWidth; + Double_t smcSide1Thick = 0.03; + Double_t vaporThick = 0.032; + Double_t liquidThick = 0.028; + Double_t smcSide2Thick = 0.01; + Double_t smcSide3Thick = 0.0055; + Double_t smcSide4Thick = 0.0095; + Double_t smcSide5Thick = 0.0075; + Double_t smcSpace = 0.01; + + char volumeName[30]; + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + mLayerNumber); + + // detailed structure ++++++++++++++ + Double_t z = 0, y = 0 - 0.007, x = 0; + + // Polimide micro channels numbers + Double_t yMC = y - h + 0.01; + Int_t nb = (Int_t)(kStaveWidth / 0.1) + 1; + Double_t xstaMC = (nb * 0.1 - 0.08) / 2; + + TGeoVolume* mechStavVol = nullptr; + if (mBuildLevel < 5) { + // world (trapezoid) + auto* mechStruct = new TGeoXtru(2); // z sections + Double_t xv[5] = { + kStaveWidth / 2 + 0.1, kStaveWidth / 2 + 0.1, 0, -kStaveWidth / 2 - 0.1, + -kStaveWidth / 2 - 0.1}; + Double_t yv[5] = {-kConeOutRadius * 2 - 0.07, 0, staveHeight, 0, -kConeOutRadius * 2 - 0.07}; + mechStruct->DefinePolygon(5, xv, yv); + mechStruct->DefineSection(0, -kStaveLength - 0.1, 0, 0, 1.); + mechStruct->DefineSection(1, kStaveLength + 0.1, 0, 0, 1.); + mechStavVol = new TGeoVolume(volumeName, mechStruct, medAir); + mechStavVol->SetLineColor(12); + mechStavVol->SetFillColor(12); + mechStavVol->SetVisibility(kTRUE); + + // Silicon micro channels numbers + + auto* tM0a = new TGeoBBox(smcWidth / 2, 0.003 / 2, headWidth / 2); + auto* volTM0a = new TGeoVolume("microChanTop1", tM0a, medKapton); + volTM0a->SetLineColor(35); + volTM0a->SetFillColor(35); + + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0a, 0, + new TGeoCombiTrans(x, yMC + 0.03, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth + smcLength / 2 + (headWidth / 2), + new TGeoRotation("", ang1, ang2, ang3))); + mechStavVol->AddNode( + volTM0a, 1, + new TGeoCombiTrans(x, yMC + 0.03, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth - smcLength / 2 - (headWidth / 2), + new TGeoRotation("", ang1, ang2, ang3))); + } + auto* tM0c = new TGeoBBox(0.3 / 2, 0.003 / 2, smcLength / 2); + auto* volTM0c = new TGeoVolume("microChanTop2", tM0c, medKapton); + volTM0c->SetLineColor(35); + volTM0c->SetFillColor(35); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0c, 0, new TGeoCombiTrans(x + (smcWidth / 2) - (0.3 / 2), yMC + 0.03, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); + mechStavVol->AddNode( + volTM0c, 1, new TGeoCombiTrans(x - (smcWidth / 2) + (0.3 / 2), yMC + 0.03, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0c1 = new TGeoBBox(0.2225 / 2, 0.003 / 2, smcLength / 2); + auto* volTM0c1 = new TGeoVolume("microChanBot1", tM0c1, medKapton); + volTM0c1->SetLineColor(6); + volTM0c1->SetFillColor(6); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0c1, 0, new TGeoCombiTrans(x + smcWidth / 2 - (smcSide1Thick) - (vaporThick) - (smcSide2Thick) - (smcSide3Thick) - (0.2225 / 2), yMC + 0.03 - hh - (0.003), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + mechStavVol->AddNode( + volTM0c1, 1, new TGeoCombiTrans(x - smcWidth / 2 + (smcSide1Thick) + (liquidThick) + (smcSide2Thick) + (smcSide4Thick) + (0.2225 / 2), yMC + 0.03 - hh - (0.003), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0c2 = new TGeoBBox(0.072 / 2, 0.003 / 2, smcLength / 2); + auto* volTM0c2 = new TGeoVolume("microChanBot2", tM0c2, medKapton); + volTM0c2->SetLineColor(35); + volTM0c2->SetFillColor(35); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0c2, 0, new TGeoCombiTrans(x + smcWidth / 2 - (0.072 / 2), yMC + 0.03 - (0.035 + 0.0015) - (0.003) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0c2r = new TGeoBBox(0.068 / 2, 0.003 / 2, smcLength / 2); + auto* volTM0c2r = new TGeoVolume("microChanBot3", tM0c2r, medKapton); + volTM0c2r->SetLineColor(35); + volTM0c2r->SetFillColor(35); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0c2r, 0, new TGeoCombiTrans(x - smcWidth / 2 + (0.068 / 2), yMC + 0.03 - (0.035 + 0.0015) - (0.003) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0d = new TGeoBBox(smcSide1Thick / 2, 0.035 / 2, smcLength / 2); + auto* volTM0d = new TGeoVolume("microChanSide1", tM0d, medKapton); + volTM0d->SetLineColor(12); + volTM0d->SetFillColor(12); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0d, 0, new TGeoCombiTrans(x + smcWidth / 2 - (smcSide1Thick / 2), yMC + 0.03 - 0.0015 - (0.035) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + mechStavVol->AddNode( + volTM0d, 1, new TGeoCombiTrans(x - smcWidth / 2 + (smcSide1Thick / 2), yMC + 0.03 - 0.0015 - (0.035) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + + auto* tM0d1 = new TGeoBBox(smcSide2Thick / 2, 0.035 / 2, smcLength / 2); + auto* volTM0d1 = new TGeoVolume("microChanSide2", tM0d1, medKapton); + volTM0d1->SetLineColor(12); + volTM0d1->SetFillColor(12); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0d1, 0, + new TGeoCombiTrans(x + smcWidth / 2 - (smcSide1Thick) - (vaporThick) - (smcSide2Thick / 2), + yMC + 0.03 - (0.003 + 0.035) / 2, + z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, + new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + mechStavVol->AddNode( + volTM0d1, 1, + new TGeoCombiTrans(x - smcWidth / 2 + (smcSide1Thick) + (liquidThick) + (smcSide2Thick / 2), + yMC + 0.03 - (0.003 + 0.035) / 2, + z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, + new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0d2 = new TGeoBBox(smcSide3Thick / 2, (hh + 0.003) / 2, smcLength / 2); + auto* volTM0d2 = new TGeoVolume("microChanSide3", tM0d2, medKapton); + volTM0d2->SetLineColor(12); + volTM0d2->SetFillColor(12); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0d2, 0, new TGeoCombiTrans(x + smcWidth / 2 - (smcSide1Thick) - (vaporThick) - (smcSide2Thick) - (smcSide3Thick / 2), yMC + 0.03 - (0.003 + hh + 0.003) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0d2r = new TGeoBBox(smcSide4Thick / 2, (hh + 0.003) / 2, smcLength / 2); + auto* volTM0d2r = new TGeoVolume("microChanSide4", tM0d2r, medKapton); + volTM0d2r->SetLineColor(12); + volTM0d2r->SetFillColor(12); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0d2r, 0, + new TGeoCombiTrans(x - smcWidth / 2 + (smcSide1Thick) + (liquidThick) + (smcSide2Thick) + + (smcSide4Thick / 2), + yMC + 0.03 - (0.003 + hh + 0.003) / 2, + z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, + new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0e = new TGeoBBox(smcSide5Thick / 2, hh / 2, smcLength / 2); + auto* volTM0e = new TGeoVolume("microChanSide5", tM0e, medKapton); + volTM0e->SetLineColor(12); + volTM0e->SetFillColor(12); + for (Int_t mo = 1; mo <= chips; mo++) { + for (Int_t ie = 0; ie < 11; ie++) { + mechStavVol->AddNode( + volTM0e, 0, + new TGeoCombiTrans(x - (ie * (smcSpace + smcSide5Thick)) + smcWidth / 2 - + (smcSide1Thick) - (vaporThick) - (smcSide2Thick) - (smcSide3Thick)-smcSpace - (smcSide5Thick / 2), + yMC + 0.03 - (0.003 + hh) / 2, + z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, + new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + mechStavVol->AddNode( + volTM0e, 1, + new TGeoCombiTrans(x + (ie * (smcSpace + smcSide5Thick)) - smcWidth / 2 + + (smcSide1Thick) + (liquidThick) + (smcSide2Thick) + (smcSide4Thick) + + smcSpace + (smcSide5Thick / 2), + yMC + 0.03 - (0.003 + hh) / 2, + z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, + new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + } + + auto* tM0f = new TGeoBBox(0.02 / 2, hh / 2, smcLength / 2); + auto* volTM0f = new TGeoVolume("microChanTop3", tM0f, medKapton); + // Double_t smcChannels=12; + Double_t smcCloseWallvapor = smcWidth / 2 - smcSide1Thick - vaporThick - smcSide2Thick - + smcSide3Thick - 12 * smcSpace - 11 * smcSide5Thick; + Double_t smcCloseWallliquid = smcWidth / 2 - smcSide1Thick - liquidThick - smcSide2Thick - + smcSide4Thick - 12 * smcSpace - 11 * smcSide5Thick; + volTM0f->SetLineColor(12); + volTM0f->SetFillColor(12); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0f, 0, + new TGeoCombiTrans(x + smcCloseWallvapor - (0.02) / 2, yMC + 0.03 - (0.003 + hh) / 2, + z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, + new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + mechStavVol->AddNode( + volTM0f, 1, + new TGeoCombiTrans(x - smcCloseWallliquid + (0.02) / 2, yMC + 0.03 - (0.003 + hh) / 2, + z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, + new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + // Head(back) microchannel + + auto* tM0hb = new TGeoBBox(smcWidth / 2, 0.025 / 2, headWidth / 2); + auto* volTM0hb = new TGeoVolume("microChanHeadBackBottom1", tM0hb, medKapton); + volTM0hb->SetLineColor(4); + volTM0hb->SetFillColor(4); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0hb, 0, new TGeoCombiTrans(x, yMC + 0.03 - 0.0145 - (0.025 / 2), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth + smcLength / 2 + (headWidth / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + mechStavVol->AddNode( + volTM0hb, 1, new TGeoCombiTrans(x, yMC + 0.03 - 0.0145 - (0.025) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth - smcLength / 2 - (headWidth / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0h1 = new TGeoBBox(smcWidth / 2, 0.013 / 2, 0.05 / 2); + auto* volTM0h1 = new TGeoVolume("microChanHeadBackBottom2", tM0h1, medKapton); + volTM0h1->SetLineColor(5); + volTM0h1->SetFillColor(5); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0h1, 0, new TGeoCombiTrans(x, yMC + 0.03 - 0.0015 - (0.013 / 2), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth - smcLength / 2 - headWidth + (0.05 / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0h2 = new TGeoBBox(smcWidth / 2, 0.003 / 2, 0.18 / 2); + auto* volTM0h2 = new TGeoVolume("microChanHeadBackBottom7", tM0h2, medKapton); + volTM0h2->SetLineColor(6); + volTM0h2->SetFillColor(6); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0h2, 0, new TGeoCombiTrans(x, yMC + 0.03 - 0.0015 - 0.01 - (0.003 / 2), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth - smcLength / 2 - 0.02 - (0.18 / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0h3 = new TGeoBBox(smcWidth / 2, 0.013 / 2, 0.02 / 2); + auto* volTM0h3 = new TGeoVolume("microChanHeadBackBottom3", tM0h3, medKapton); + volTM0h3->SetLineColor(5); + volTM0h3->SetFillColor(5); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0h3, 0, new TGeoCombiTrans(x, yMC + 0.03 - 0.0015 - (0.013 / 2), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth - smcLength / 2 - (0.02 / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0b1 = new TGeoBBox(smcWidth / 2, 0.013 / 2, 0.03 / 2); + auto* volTM0b1 = new TGeoVolume("microChanHeadBackBottom4", tM0b1, medKapton); + volTM0b1->SetLineColor(5); + volTM0b1->SetFillColor(5); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0b1, 0, new TGeoCombiTrans(x, yMC + 0.03 - 0.0015 - (0.013 / 2), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth + smcLength / 2 + headWidth - (0.03 / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0b2 = new TGeoBBox(smcWidth / 2, 0.003 / 2, 0.2 / 2); + auto* volTM0b2 = new TGeoVolume("microChanHeadBackBottom5", tM0b2, medKapton); + volTM0b2->SetLineColor(6); + volTM0b2->SetFillColor(6); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0b2, 0, new TGeoCombiTrans(x, yMC + 0.03 - 0.0015 - 0.01 - (0.003 / 2), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth + smcLength / 2 + 0.02 + (0.2 / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0b3 = new TGeoBBox(smcWidth / 2, 0.013 / 2, 0.02 / 2); + auto* volTM0b3 = new TGeoVolume("microChanHeadBackBottom6", tM0b3, medKapton); + volTM0b3->SetLineColor(5); + volTM0b3->SetFillColor(5); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0b3, 0, new TGeoCombiTrans(x, yMC + 0.03 - 0.0015 - (0.013 / 2), z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth + smcLength / 2 + (0.02 / 2), new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + + auto* tM0b = new TGeoBBox(0.02 / 2, 0.02 / 2, zsta); + auto* volTM0b = new TGeoVolume("microChanWalls", tM0b, medKapton); + volTM0b->SetLineColor(35); + volTM0b->SetFillColor(35); + for (Int_t ib = 0; ib < nb; ib++) { + // mechStavVol->AddNode(volTM0b, ib, new TGeoCombiTrans(x+ib*0.1-xstaMC+0.01,yMC, z, new + // TGeoRotation("",0, 0, 0))); + } + } + + if (mBuildLevel < 4) { + // cooling inlet outlet + auto* tM0dv = new TGeoBBox(vaporThick / 2, 0.035 / 2, smcLength / 2); + auto* volTM0dv = new TGeoVolume("microChanVapor", tM0dv, medWater); + volTM0dv->SetLineColor(2); + volTM0dv->SetFillColor(2); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0dv, 0, new TGeoCombiTrans(x + smcWidth / 2 - (smcSide1Thick) - (vaporThick / 2), yMC + 0.03 - 0.0015 - (0.035) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + auto* tM0dl = new TGeoBBox(liquidThick / 2, 0.035 / 2, smcLength / 2); + auto* volTM0dl = new TGeoVolume("microChanLiquid", tM0dl, medWater); + volTM0dl->SetLineColor(3); + volTM0dl->SetFillColor(3); + for (Int_t mo = 1; mo <= chips; mo++) { + mechStavVol->AddNode( + volTM0dl, 0, new TGeoCombiTrans(x - smcWidth / 2 + (smcSide1Thick) + (liquidThick / 2), yMC + 0.03 - 0.0015 - (0.035) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + // small cooling fluid now using water wait for freeon value + auto* tM0dlq = new TGeoBBox(smcSpace / 2, hh / 2, smcLength / 2); + auto* volTM0dlq = new TGeoVolume("smallLiquid", tM0dlq, medWater); + volTM0dlq->SetLineColor(3); + volTM0dlq->SetFillColor(3); + auto* tM0dvp = new TGeoBBox(smcSpace / 2, hh / 2, smcLength / 2); + auto* volTM0dvp = new TGeoVolume("microChanVapor", tM0dvp, medWater); + volTM0dvp->SetLineColor(2); + volTM0dvp->SetFillColor(2); + for (Int_t mo = 1; mo <= chips; mo++) { + for (Int_t is = 0; is < 12; is++) { + mechStavVol->AddNode( + volTM0dlq, 0, new TGeoCombiTrans(x + (is * (smcSpace + smcSide5Thick)) - smcWidth / 2 + (smcSide1Thick) + (vaporThick) + (smcSide2Thick) + (smcSide3Thick) + smcSpace / 2, yMC + 0.03 - (0.003 + hh) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + mechStavVol->AddNode( + volTM0dvp, 1, new TGeoCombiTrans(x - (is * (smcSpace + smcSide5Thick)) + smcWidth / 2 - (smcSide1Thick) - (vaporThick) - (smcSide2Thick) - (smcSide3Thick)-smcSpace / 2, yMC + 0.03 - (0.003 + hh) / 2, z + (mo - 3) * kStaveLength / 4 + smcLength / 2 + headWidth, new TGeoRotation("", ang1, ang2, ang3))); //("",0, 0, 0))); + } + } + } + + if (mBuildLevel < 3) { + // Bottom filament CFRP black-12 Carbon structure TGeoBBox (thickness,width,length) + Double_t filWidth = 0.04; + Double_t filHeight = 0.02; + auto* t1 = new TGeoBBox(filHeight / 2, filWidth / 2, s1); + auto* volT1 = new TGeoVolume("bottomFilament", t1, medM60J3K); + volT1->SetLineColor(12); + volT1->SetFillColor(12); + for (int i = 0; i < loop; i++) { // i<30;i++){ + mechStavVol->AddNode(volT1, 4 * i + 0, + new TGeoCombiTrans(x + w, y - h + 0.04 + filHeight / 2, + z - kStaveLength / 2 + (4 * l * i) + s1 / 2, + new TGeoRotation("volT1", -90, alpha, 0))); + mechStavVol->AddNode(volT1, 4 * i + 1, + new TGeoCombiTrans(x - w, y - h + 0.04 + filHeight / 2, + z - kStaveLength / 2 + (4 * l * i) + s1 / 2, + new TGeoRotation("volT1", 90, alpha, 0))); + mechStavVol->AddNode(volT1, 4 * i + 2, + new TGeoCombiTrans(x + w, y - h + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * l + (i * 4 * l) + s1 / 2, + new TGeoRotation("volT1", -90, -alpha, 0))); + mechStavVol->AddNode(volT1, 4 * i + 3, + new TGeoCombiTrans(x - w, y - h + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * l + (i * 4 * l) + s1 / 2, + new TGeoRotation("volT1", -90, +alpha, 0))); + } + + // Top filament CERP black-12 Carbon structure TGeoBBox (length,thickness,width) + auto* t2 = new TGeoBBox(s2, filHeight / 2, filWidth / 2); + auto* volT2 = new TGeoVolume("topFilament", t2, medM60J3K); + volT2->SetLineColor(12); + volT2->SetFillColor(12); + for (int i = 0; i < loop; i++) { // i<30;i++){ + mechStavVol->AddNode( + volT2, 4 * i + 0, new TGeoCombiTrans(x + w, y + 0.04 + filHeight / 2, z - kStaveLength / 2 + (i * 4 * l) + s1 / 2, new TGeoRotation("volT2", 90, 90 - alpha, 90 - beta))); + mechStavVol->AddNode( + volT2, 4 * i + 1, + new TGeoCombiTrans(x - w, y + 0.04 + filHeight / 2, + z - kStaveLength / 2 + (i * 4 * l) + s1 / 2, + new TGeoRotation("volT2", 90, -90 + alpha, -90 + beta))); + mechStavVol->AddNode( + volT2, 4 * i + 2, + new TGeoCombiTrans(x + w, y + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * l + (i * 4 * l) + s1 / 2, + new TGeoRotation("volT2", 90, -90 + alpha, 90 - beta))); + mechStavVol->AddNode( + volT2, 4 * i + 3, + new TGeoCombiTrans(x - w, y + 0.04 + filHeight / 2, + z - kStaveLength / 2 + 2 * l + (i * 4 * l) + s1 / 2, + new TGeoRotation("volT2", 90, 90 - alpha, -90 + beta))); + } + } + + if (mBuildLevel < 2) { + // Glue Filament and Silicon MicroChannel + auto* tM0 = new TGeoBBox(xstaMC / 5, klay4 / 2, zsta); + auto* volTM0 = new TGeoVolume("glueFM", tM0, medGlue); + volTM0->SetLineColor(5); + volTM0->SetFillColor(5); + mechStavVol->AddNode(volTM0, 0, new TGeoCombiTrans(x - xsta / 2 - 0.25, 0.03 + yMC, z, new TGeoRotation("", 0, 0, 0))); + mechStavVol->AddNode(volTM0, 1, new TGeoCombiTrans(x + xsta / 2 + 0.25, 0.03 + yMC, z, new TGeoRotation("", 0, 0, 0))); + + // Glue microchannel and sensor + auto* glueM = new TGeoBBox(xstaMC / 5, klay4 / 2, zsta); + auto* volGlueM = new TGeoVolume("glueMS", glueM, medGlue); + volGlueM->SetLineColor(5); + volGlueM->SetFillColor(5); + mechStavVol->AddNode(volGlueM, 0, new TGeoCombiTrans(x - xsta / 2 - 0.25, yMC - 0.01, z, new TGeoRotation("", 0, 0, 0))); + mechStavVol->AddNode(volGlueM, 1, new TGeoCombiTrans(x + xsta / 2 + 0.25, yMC - 0.01, z, new TGeoRotation("", 0, 0, 0))); + + // Glue sensor and kapton + auto* glue = new TGeoBBox(xsta, klay4 / 2, zsta); + auto* volGlue = new TGeoVolume("glueSensorBus", glue, medGlue); + volGlue->SetLineColor(5); + volGlue->SetFillColor(5); + mechStavVol->AddNode(volGlue, 1, new TGeoCombiTrans(x, y - 0.154 - mSensorThickness - klay4 / 2, z, new TGeoRotation("", 0, 0, 0))); + } + + if (mBuildLevel < 1) { + auto* kapCable = new TGeoBBox(xsta, klay5 / 2, zsta); + auto* volCable = new TGeoVolume("Flexcable", kapCable, medFlexCable); + volCable->SetLineColor(28); + volCable->SetFillColor(28); + mechStavVol->AddNode(volCable, 0, + new TGeoCombiTrans(x, y - 0.154 - mSensorThickness - klay4 - klay5 / 2, z, + new TGeoRotation("", 0, 0, 0))); + } + // Done, return the stave structure + return mechStavVol; +} + +TGeoVolume* V1Layer::createStaveOuterB(const TGeoManager* mgr) +{ + TGeoVolume* mechStavVol = nullptr; + + switch (mStaveModel) { + case Detector::kOBModelDummy: + mechStavVol = createStaveModelOuterBDummy(mgr); + break; + case Detector::kOBModel0: + mechStavVol = createStaveModelOuterB0(mgr); + break; + case Detector::kOBModel1: + mechStavVol = createStaveModelOuterB1(mgr); + break; + default: + LOG(FATAL) << "Unknown stave model " << mStaveModel; + break; + } + return mechStavVol; +} + +TGeoVolume* V1Layer::createStaveModelOuterBDummy(const TGeoManager*) const +{ + // Done, return the stave structure + return nullptr; +} + +TGeoVolume* V1Layer::createStaveModelOuterB0(const TGeoManager* mgr) +{ + Double_t xmod, ymod, zmod; + Double_t xlen, ylen, zlen; + Double_t ypos, zpos; + char volumeName[30]; + + // First create all needed shapes + // The chip + xlen = sOBHalfStaveWidth; + ylen = 0.5 * mStaveThickness; // TO BE CHECKED + zlen = sOBModuleZLength / 2; + + TGeoVolume* chipVol = createChipInnerB(xlen, ylen, zlen); + + xmod = ((TGeoBBox*)chipVol->GetShape())->GetDX(); + ymod = ((TGeoBBox*)chipVol->GetShape())->GetDY(); + zmod = ((TGeoBBox*)chipVol->GetShape())->GetDZ(); + + auto* module = new TGeoBBox(xmod, ymod, zmod); + + zlen = sOBModuleZLength * mNumberOfModules; + auto* hstave = new TGeoBBox(xlen, ylen, zlen / 2); + + // We have all shapes: now create the real volumes + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + auto* modVol = new TGeoVolume(volumeName, module, medAir); + modVol->SetVisibility(kTRUE); + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + auto* hstaveVol = new TGeoVolume(volumeName, hstave, medAir); + + // Finally build it up + modVol->AddNode(chipVol, 0); + mHierarchy[kChip] = 1; + + for (Int_t j = 0; j < mNumberOfModules; j++) { + ypos = 0.021; // Remove small overlap - M.S: 21may13 + zpos = -hstave->GetDZ() + j * 2 * zmod + zmod; + hstaveVol->AddNode(modVol, j, new TGeoTranslation(0, ypos, zpos)); + mHierarchy[kModule]++; + } + // Done, return the stave structure + return hstaveVol; +} + +TGeoVolume* V1Layer::createStaveModelOuterB1(const TGeoManager* mgr) +{ + Double_t yFlex1 = sOBFlexCableAlThick; + Double_t yFlex2 = sOBFlexCableKapThick; + Double_t flexOverlap = 5; // to be checked + Double_t xHalmSt = sOBHalfStaveWidth / 2; + Double_t rCoolMin = sOBCoolTubeInnerD / 2; + Double_t rCoolMax = rCoolMin + sOBCoolTubeThick; + Double_t kLay1 = 0.004; // to be checked + Double_t kLay2 = sOBGraphiteFoilThick; + + Double_t xlen, ylen; + Double_t ymod, zmod; + Double_t xtru[12], ytru[12]; + Double_t xpos, ypos, ypos1, zpos /*, zpos5cm*/; + Double_t zlen; + char volumeName[30]; + + zlen = (mNumberOfModules * sOBModuleZLength + (mNumberOfModules - 1) * sOBModuleGap) / 2; + + // First create all needed shapes + TGeoVolume* moduleVol = createModuleOuterB(); + moduleVol->SetVisibility(kTRUE); + ymod = ((TGeoBBox*)(moduleVol->GetShape()))->GetDY(); + zmod = ((TGeoBBox*)(moduleVol->GetShape()))->GetDZ(); + + auto* busAl = new TGeoBBox("BusAl", xHalmSt, sOBBusCableAlThick / 2, zlen); + auto* busKap = new TGeoBBox("BusKap", xHalmSt, sOBBusCableKapThick / 2, zlen); + + auto* coldPlate = + new TGeoBBox("ColdPlate", sOBHalfStaveWidth / 2, sOBColdPlateThick / 2, zlen); + + auto* coolTube = new TGeoTube("CoolingTube", rCoolMin, rCoolMax, zlen); + auto* coolWater = new TGeoTube("CoolingWater", 0., rCoolMin, zlen); + + xlen = xHalmSt - sOBCoolTubeXDist / 2 - coolTube->GetRmax(); + auto* graphlat = new TGeoBBox("GraphLateral", xlen / 2, kLay2 / 2, zlen); + + xlen = sOBCoolTubeXDist / 2 - coolTube->GetRmax(); + auto* graphmid = new TGeoBBox("GraphMiddle", xlen, kLay2 / 2, zlen); + + ylen = coolTube->GetRmax() - kLay2; + auto* graphvert = new TGeoBBox("GraphVertical", kLay2 / 2, ylen / 2, zlen); + + auto* graphtub = + new TGeoTubeSeg("GraphTube", rCoolMax, rCoolMax + kLay2, zlen, 180., 360.); + + xlen = xHalmSt - sOBCoolTubeXDist / 2 - coolTube->GetRmax() - kLay2; + auto* fleeclat = new TGeoBBox("FleecLateral", xlen / 2, kLay1 / 2, zlen); + + xlen = sOBCoolTubeXDist / 2 - coolTube->GetRmax() - kLay2; + auto* fleecmid = new TGeoBBox("FleecMiddle", xlen, kLay1 / 2, zlen); + + ylen = coolTube->GetRmax() - kLay2 - kLay1; + auto* fleecvert = new TGeoBBox("FleecVertical", kLay1 / 2, ylen / 2, zlen); + + auto* fleectub = + new TGeoTubeSeg("FleecTube", rCoolMax + kLay2, rCoolMax + kLay1 + kLay2, zlen, 180., 360.); + + auto* flex1_5cm = new TGeoBBox("Flex1MV_5cm", xHalmSt, yFlex1 / 2, flexOverlap / 2); + auto* flex2_5cm = new TGeoBBox("Flex2MV_5cm", xHalmSt, yFlex2 / 2, flexOverlap / 2); + + // The half stave container (an XTru to avoid overlaps between neightbours) + xtru[0] = xHalmSt; + ytru[0] = 0; + xtru[1] = xtru[0]; + ytru[1] = -2 * (ymod + busAl->GetDY() + busKap->GetDY() + coldPlate->GetDY() + graphlat->GetDY() + + fleeclat->GetDY()); + xtru[2] = sOBCoolTubeXDist / 2 + fleectub->GetRmax(); + ytru[2] = ytru[1]; + xtru[3] = xtru[2]; + ytru[3] = ytru[2] - (coolTube->GetRmax() + fleectub->GetRmax()); + xtru[4] = sOBCoolTubeXDist / 2 - fleectub->GetRmax(); + ytru[4] = ytru[3]; + xtru[5] = xtru[4]; + ytru[5] = ytru[2]; + for (Int_t i = 0; i < 6; i++) { + xtru[6 + i] = -xtru[5 - i]; + ytru[6 + i] = ytru[5 - i]; + } + auto* halmStave = new TGeoXtru(2); + halmStave->DefinePolygon(12, xtru, ytru); + halmStave->DefineSection(0, -mZLength / 2); + halmStave->DefineSection(1, mZLength / 2); + + // We have all shapes: now create the real volumes + + TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medCarbon = mgr->GetMedium("IT4_CARBON$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); // amec thermasol + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + auto* busAlVol = new TGeoVolume("BusAlVol", busAl, medAluminum); + busAlVol->SetLineColor(kCyan); + busAlVol->SetFillColor(busAlVol->GetLineColor()); + busAlVol->SetFillStyle(4000); // 0% transparent + + auto* busKapVol = new TGeoVolume("BusKapVol", busKap, medKapton); + busKapVol->SetLineColor(kBlue); + busKapVol->SetFillColor(busKapVol->GetLineColor()); + busKapVol->SetFillStyle(4000); // 0% transparent + + auto* coldPlateVol = new TGeoVolume("ColdPlateVol", coldPlate, medCarbon); + coldPlateVol->SetLineColor(kYellow - 3); + coldPlateVol->SetFillColor(coldPlateVol->GetLineColor()); + coldPlateVol->SetFillStyle(4000); // 0% transparent + + auto* coolTubeVol = new TGeoVolume("CoolingTubeVol", coolTube, medKapton); + coolTubeVol->SetLineColor(kGray); + coolTubeVol->SetFillColor(coolTubeVol->GetLineColor()); + coolTubeVol->SetFillStyle(4000); // 0% transparent + + auto* coolWaterVol = new TGeoVolume("CoolingWaterVol", coolWater, medWater); + coolWaterVol->SetLineColor(kBlue); + coolWaterVol->SetFillColor(coolWaterVol->GetLineColor()); + coolWaterVol->SetFillStyle(4000); // 0% transparent + + auto* graphlatVol = new TGeoVolume("GraphiteFoilLateral", graphlat, medFGS003); + graphlatVol->SetLineColor(kGreen); + graphlatVol->SetFillColor(graphlatVol->GetLineColor()); + graphlatVol->SetFillStyle(4000); // 0% transparent + + auto* graphmidVol = new TGeoVolume("GraphiteFoilMiddle", graphmid, medFGS003); + graphmidVol->SetLineColor(kGreen); + graphmidVol->SetFillColor(graphmidVol->GetLineColor()); + graphmidVol->SetFillStyle(4000); // 0% transparent + + auto* graphvertVol = new TGeoVolume("GraphiteFoilVertical", graphvert, medFGS003); + graphvertVol->SetLineColor(kGreen); + graphvertVol->SetFillColor(graphvertVol->GetLineColor()); + graphvertVol->SetFillStyle(4000); // 0% transparent + + auto* graphtubVol = new TGeoVolume("GraphiteFoilPipeCover", graphtub, medFGS003); + graphtubVol->SetLineColor(kGreen); + graphtubVol->SetFillColor(graphtubVol->GetLineColor()); + graphtubVol->SetFillStyle(4000); // 0% transparent + + auto* fleeclatVol = new TGeoVolume("CarbonFleeceLateral", fleeclat, medCarbonFleece); + fleeclatVol->SetLineColor(kViolet); + fleeclatVol->SetFillColor(fleeclatVol->GetLineColor()); + fleeclatVol->SetFillStyle(4000); // 0% transparent + + auto* fleecmidVol = new TGeoVolume("CarbonFleeceMiddle", fleecmid, medCarbonFleece); + fleecmidVol->SetLineColor(kViolet); + fleecmidVol->SetFillColor(fleecmidVol->GetLineColor()); + fleecmidVol->SetFillStyle(4000); // 0% transparent + + auto* fleecvertVol = new TGeoVolume("CarbonFleeceVertical", fleecvert, medCarbonFleece); + fleecvertVol->SetLineColor(kViolet); + fleecvertVol->SetFillColor(fleecvertVol->GetLineColor()); + fleecvertVol->SetFillStyle(4000); // 0% transparent + + auto* fleectubVol = new TGeoVolume("CarbonFleecePipeCover", fleectub, medCarbonFleece); + fleectubVol->SetLineColor(kViolet); + fleectubVol->SetFillColor(fleectubVol->GetLineColor()); + fleectubVol->SetFillStyle(4000); // 0% transparent + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + auto* halmStaveVol = new TGeoVolume(volumeName, halmStave, medAir); + // halmStaveVol->SetLineColor(12); + // halmStaveVol->SetFillColor(12); + // halmStaveVol->SetVisibility(kTRUE); + + auto* flex1_5cmVol = new TGeoVolume("Flex1Vol5cm", flex1_5cm, medAluminum); + auto* flex2_5cmVol = new TGeoVolume("Flex2Vol5cm", flex2_5cm, medKapton); + + flex1_5cmVol->SetLineColor(kRed); + flex2_5cmVol->SetLineColor(kGreen); + + // Now build up the half stave + ypos = -busKap->GetDY(); + halmStaveVol->AddNode(busKapVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos -= (busKap->GetDY() + busAl->GetDY()); + halmStaveVol->AddNode(busAlVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos -= (busAl->GetDY() + ymod); + for (Int_t j = 0; j < mNumberOfModules; j++) { + zpos = -zlen + j * (2 * zmod + sOBModuleGap) + zmod; + halmStaveVol->AddNode(moduleVol, j, new TGeoTranslation(0, ypos, zpos)); + mHierarchy[kModule]++; + } + + ypos -= (ymod + coldPlate->GetDY()); + halmStaveVol->AddNode(coldPlateVol, 1, new TGeoTranslation(0, ypos, 0)); + + coolTubeVol->AddNode(coolWaterVol, 1, nullptr); + + xpos = sOBCoolTubeXDist / 2; + ypos1 = ypos - (coldPlate->GetDY() + coolTube->GetRmax()); + halmStaveVol->AddNode(coolTubeVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(coolTubeVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + halmStaveVol->AddNode(graphtubVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(graphtubVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + halmStaveVol->AddNode(fleectubVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(fleectubVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + xpos = xHalmSt - graphlat->GetDX(); + ypos1 = ypos - (coldPlate->GetDY() + graphlat->GetDY()); + halmStaveVol->AddNode(graphlatVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(graphlatVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + halmStaveVol->AddNode(graphmidVol, 1, new TGeoTranslation(0, ypos1, 0)); + + xpos = xHalmSt - 2 * graphlat->GetDX() + graphvert->GetDX(); + ypos1 = ypos - (coldPlate->GetDY() + 2 * graphlat->GetDY() + graphvert->GetDY()); + halmStaveVol->AddNode(graphvertVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(graphvertVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + xpos = graphmid->GetDX() - graphvert->GetDX(); + halmStaveVol->AddNode(graphvertVol, 3, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(graphvertVol, 4, new TGeoTranslation(xpos, ypos1, 0)); + + xpos = xHalmSt - fleeclat->GetDX(); + ypos1 = ypos - (coldPlate->GetDY() + 2 * graphlat->GetDY() + fleeclat->GetDY()); + halmStaveVol->AddNode(fleeclatVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(fleeclatVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + halmStaveVol->AddNode(fleecmidVol, 1, new TGeoTranslation(0, ypos1, 0)); + + xpos = xHalmSt - 2 * fleeclat->GetDX() + fleecvert->GetDX(); + ypos1 = ypos - + (coldPlate->GetDY() + 2 * graphlat->GetDY() + 2 * fleeclat->GetDY() + fleecvert->GetDY()); + halmStaveVol->AddNode(fleecvertVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(fleecvertVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + xpos = fleecmid->GetDX() - fleecvert->GetDX(); + halmStaveVol->AddNode(fleecvertVol, 3, new TGeoTranslation(-xpos, ypos1, 0)); + halmStaveVol->AddNode(fleecvertVol, 4, new TGeoTranslation(xpos, ypos1, 0)); + + // THE FOLLOWING IS ONLY A REMINDER FOR WHAT IS STILL MISSING + + // for (Int_t j=0; j<mNumberOfChips; j++) { + + // zpos = -(zact + (mNumberOfChips-1)*modGap)/2 + j*(zMod + modGap) + zMod/2; + // zpos5cm = -(zact + (mNumberOfChips-1)*modGap)/2 + (j+1)*(zMod + modGap) + flexOverlap/2 ; + + // halmStaveVol->AddNode(moduleVol, j, new TGeoTranslation(xPos, -ylen + yPos + 2*rCoolMax + + // yCPlate + yGlue + yModPlate + ymod, zpos)); + // halmStaveVol->AddNode(moduleVol, mNumberOfChips+j, new TGeoTranslation(-xPos, -ylen + yPos + // + + // 2*rCoolMax + yCPlate + yGlue + yModPlate + ymod +deltaY, zpos)); + + // if((j+1)!=mNumberOfChips){ + // halmStaveVol->AddNode(flex1_5cmVol,j,new TGeoTranslation(xPos,-ylen + yPos + 2*rCoolMax + + // yCPlate + yGlue + yModPlate + 2*ymod + yFlex1 + yFlex2 + yFlex1/2,zpos5cm)); + // halmStaveVol->AddNode(flex1_5cmVol,mNumberOfChips+j,new TGeoTranslation(-xPos,-ylen + + // yPos + + // 2*rCoolMax + yCPlate + yGlue + yModPlate + 2*ymod + yFlex1 + yFlex2 + yFlex1/2 + // +deltaY,zpos5cm)); + // halmStaveVol->AddNode(flex2_5cmVol,j,new TGeoTranslation(xPos,-ylen + yPos + 2*rCoolMax + + // yCPlate + yGlue + yModPlate + 2*ymod + 2*yFlex1 + 3*yFlex2/2,zpos5cm)); + // halmStaveVol->AddNode(flex2_5cmVol,mNumberOfChips+j,new TGeoTranslation(-xPos,-ylen + + // yPos + + // 2*rCoolMax + yCPlate + yGlue + yModPlate + 2*ymod + 2*yFlex1 + 3*yFlex2/2 +deltaY,zpos5cm)); + // } + // else { + // halmStaveVol->AddNode(flex1_5cmVol,j,new TGeoTranslation(xPos,-ylen + yPos + 2*rCoolMax + + // yCPlate + yGlue + yModPlate + 2*ymod + yFlex1/2,zpos5cm-modGap)); + // halmStaveVol->AddNode(flex1_5cmVol,mNumberOfChips+j,new TGeoTranslation(-xPos,-ylen + + // yPos + + // 2*rCoolMax + yCPlate + yGlue + yModPlate + 2*ymod + yFlex1/2 +deltaY,zpos5cm-modGap)); + // halmStaveVol->AddNode(flex2_5cmVol,j,new TGeoTranslation(xPos,-ylen + yPos + 2*rCoolMax + + // yCPlate + yGlue + yModPlate +2*ymod + yFlex1 + yFlex2/2,zpos5cm-modGap)); + // halmStaveVol->AddNode(flex2_5cmVol,mNumberOfChips+j,new TGeoTranslation(-xPos,-ylen + + // yPos + + // 2*rCoolMax + yCPlate + yGlue + yModPlate + 2*ymod + yFlex1 + yFlex2/2 +deltaY,zpos5cm-modGap)); + + // } + // } + // Done, return the half stave structure + return halmStaveVol; +} + +TGeoVolume* V1Layer::createSpaceFrameOuterB(const TGeoManager* mgr) +{ + TGeoVolume* mechStavVol = nullptr; + + switch (mStaveModel) { + case Detector::kOBModelDummy: + case Detector::kOBModel0: + mechStavVol = createSpaceFrameOuterBDummy(mgr); + break; + case Detector::kOBModel1: + mechStavVol = createSpaceFrameOuterB1(mgr); + break; + default: + LOG(FATAL) << "Unknown stave model " << mStaveModel; + break; + } + + return mechStavVol; +} + +TGeoVolume* V1Layer::createSpaceFrameOuterBDummy(const TGeoManager*) const +{ + // Done, return the stave structur + return nullptr; +} + +TGeoVolume* V1Layer::createSpaceFrameOuterB1(const TGeoManager* mgr) +{ + // Materials defined in Detector + TGeoMedium* medCarbon = mgr->GetMedium("IT4_CARBON$"); + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + // Local parameters + Double_t sframeWidth = sOBSpaceFrameWidth; + Double_t sframeHeight = sOBSpaceFrameTotHigh - sOBHalfStaveYTrans; + Double_t staveBeamRadius = sOBSFrameBeamRadius; + Double_t staveLa = sOBSpaceFrameLa; + Double_t staveHa = sOBSpaceFrameHa; + Double_t staveLb = sOBSpaceFrameLb; + Double_t staveHb = sOBSpaceFrameHb; + Double_t stavel = sOBSpaceFrameL; + Double_t bottomBeamAngle = sOBSFBotBeamAngle; + Double_t triangleHeight = sframeHeight - staveBeamRadius; + Double_t halmTheta = TMath::ATan(0.5 * sframeWidth / triangleHeight); + // Double_t alpha = TMath::Pi()*3./4. - halmTheta/2.; + Double_t beta = (TMath::Pi() - 2. * halmTheta) / 4.; + // Double_t distCenterSideDown = 0.5*sframeWidth/TMath::Cos(beta); + + Double_t zlen; + Double_t xpos, ypos, zpos; + Double_t seglen; + char volumeName[30]; + + zlen = mNumberOfModules * sOBModuleZLength + (mNumberOfModules - 1) * sOBModuleGap; + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + if (gGeoManager->GetVolume(volumeName)) { // Should always be so + sframeHeight -= ((TGeoBBox*)gGeoManager->GetVolume(volumeName)->GetShape())->GetDY() * 2; + zlen = ((TGeoBBox*)gGeoManager->GetVolume(volumeName)->GetShape())->GetDZ() * 2; + } + seglen = zlen / mNumberOfModules; + + // First create all needed shapes and volumes + auto* spaceFrame = new TGeoBBox(sframeWidth / 2, sframeHeight / 2, zlen / 2); + auto* segment = new TGeoBBox(sframeWidth / 2, sframeHeight / 2, seglen / 2); + + auto* spaceFrameVol = new TGeoVolume("CarbonFrameVolume", spaceFrame, medAir); + spaceFrameVol->SetVisibility(kFALSE); + + auto* segmentVol = new TGeoVolume("segmentVol", segment, medAir); + + // SpaceFrame + + //--- the top V of the Carbon Fiber Stave (segment) + TGeoArb8* cmStavTop1 = createStaveSide("CFstavTopCornerVol1shape", seglen / 2., halmTheta, -1, + staveLa, staveHa, stavel); + auto* cmStavTopVol1 = new TGeoVolume("CFstavTopCornerVol1", cmStavTop1, medCarbon); + cmStavTopVol1->SetLineColor(35); + + TGeoArb8* cmStavTop2 = createStaveSide("CFstavTopCornerVol2shape", seglen / 2., halmTheta, 1, + staveLa, staveHa, stavel); + auto* cmStavTopVol2 = new TGeoVolume("CFstavTopCornerVol2", cmStavTop2, medCarbon); + cmStavTopVol2->SetLineColor(35); + + auto* trTop1 = new TGeoTranslation(0, sframeHeight / 2, 0); + + //--- the 2 side V + TGeoArb8* cmStavSide1 = + createStaveSide("CFstavSideCornerVol1shape", seglen / 2., beta, -1, staveLb, staveHb, stavel); + auto* cmStavSideVol1 = new TGeoVolume("CFstavSideCornerVol1", cmStavSide1, medCarbon); + cmStavSideVol1->SetLineColor(35); + + TGeoArb8* cmStavSide2 = + createStaveSide("CFstavSideCornerVol2shape", seglen / 2., beta, 1, staveLb, staveHb, stavel); + auto* cmStavSideVol2 = new TGeoVolume("CFstavSideCornerVol2", cmStavSide2, medCarbon); + cmStavSideVol2->SetLineColor(35); + + xpos = -sframeWidth / 2; + ypos = -sframeHeight / 2 + staveBeamRadius + staveHb * TMath::Sin(beta); + auto* ctSideR = new TGeoCombiTrans( + xpos, ypos, 0, new TGeoRotation("", 180 - 2 * beta * TMath::RadToDeg(), 0, 0)); + auto* ctSideL = new TGeoCombiTrans( + -xpos, ypos, 0, new TGeoRotation("", -180 + 2 * beta * TMath::RadToDeg(), 0, 0)); + + segmentVol->AddNode(cmStavTopVol1, 1, trTop1); + segmentVol->AddNode(cmStavTopVol2, 1, trTop1); + segmentVol->AddNode(cmStavSideVol1, 1, ctSideR); + segmentVol->AddNode(cmStavSideVol1, 2, ctSideL); + segmentVol->AddNode(cmStavSideVol2, 1, ctSideR); + segmentVol->AddNode(cmStavSideVol2, 2, ctSideL); + + //--- The beams + // Beams on the sides + Double_t beamPhiPrime = TMath::ASin( + 1. / TMath::Sqrt((1 + TMath::Sin(2 * beta) * TMath::Sin(2 * beta) / + (tanD(sOBSFrameBeamSidePhi) * tanD(sOBSFrameBeamSidePhi))))); + Double_t beamLength = TMath::Sqrt(sframeHeight * sframeHeight / + (TMath::Sin(beamPhiPrime) * TMath::Sin(beamPhiPrime)) + + sframeWidth * sframeWidth / 4.) - + staveLa / 2 - staveLb / 2; + auto* sideBeam = new TGeoTubeSeg(0, staveBeamRadius, beamLength / 2, 0, 180); + auto* sideBeamVol = new TGeoVolume("CFstavSideBeamVol", sideBeam, medCarbon); + sideBeamVol->SetLineColor(35); + + auto* beamRot1 = new TGeoRotation("", /*90-2*beta*/ halmTheta * TMath::RadToDeg(), + -beamPhiPrime * TMath::RadToDeg(), -90); + auto* beamRot2 = + new TGeoRotation("", 90 - 2. * beta * TMath::RadToDeg(), beamPhiPrime * TMath::RadToDeg(), -90); + auto* beamRot3 = + new TGeoRotation("", 90 + 2. * beta * TMath::RadToDeg(), beamPhiPrime * TMath::RadToDeg(), -90); + auto* beamRot4 = new TGeoRotation("", 90 + 2. * beta * TMath::RadToDeg(), + -beamPhiPrime * TMath::RadToDeg(), -90); + + TGeoCombiTrans* beamTransf[8]; + xpos = 0.49 * triangleHeight * TMath::Tan(halmTheta); // was 0.5, fix small overlap + ypos = staveBeamRadius / 2; + zpos = seglen / 8; + beamTransf[0] = new TGeoCombiTrans(xpos, ypos, -3 * zpos, beamRot1); + + beamTransf[1] = new TGeoCombiTrans(xpos, ypos, -3 * zpos, beamRot1); + addTranslationToCombiTrans(beamTransf[1], 0, 0, seglen / 2); + + beamTransf[2] = new TGeoCombiTrans(xpos, ypos, -zpos, beamRot2); + + beamTransf[3] = new TGeoCombiTrans(xpos, ypos, -zpos, beamRot2); + addTranslationToCombiTrans(beamTransf[3], 0, 0, seglen / 2); + + beamTransf[4] = new TGeoCombiTrans(-xpos, ypos, -3 * zpos, beamRot3); + + beamTransf[5] = new TGeoCombiTrans(-xpos, ypos, -3 * zpos, beamRot3); + addTranslationToCombiTrans(beamTransf[5], 0, 0, seglen / 2); + + beamTransf[6] = new TGeoCombiTrans(-xpos, ypos, -zpos, beamRot4); + beamTransf[7] = new TGeoCombiTrans(-xpos, ypos, 3 * zpos, beamRot4); + + //--- Beams of the bottom + auto* bottomBeam1 = + new TGeoTubeSeg(0, staveBeamRadius, sframeWidth / 2. - staveLb / 3, 0, 180); + auto* bottomBeam1Vol = new TGeoVolume("CFstavBottomBeam1Vol", bottomBeam1, medCarbon); + bottomBeam1Vol->SetLineColor(35); + + auto* bottomBeam2 = + new TGeoTubeSeg(0, staveBeamRadius, sframeWidth / 2. - staveLb / 3, 0, 90); + auto* bottomBeam2Vol = new TGeoVolume("CFstavBottomBeam2Vol", bottomBeam2, medCarbon); + bottomBeam2Vol->SetLineColor(35); + + auto* bottomBeam3 = new TGeoTubeSeg( + 0, staveBeamRadius, 0.5 * sframeWidth / sinD(bottomBeamAngle) - staveLb / 3, 0, 180); + auto* bottomBeam3Vol = new TGeoVolume("CFstavBottomBeam3Vol", bottomBeam3, medCarbon); + bottomBeam3Vol->SetLineColor(35); + + auto* bottomBeamRot1 = new TGeoRotation("", 90, 90, 90); + auto* bottomBeamRot2 = new TGeoRotation("", -90, 90, -90); + + auto* bottomBeamTransf1 = + new TGeoCombiTrans("", 0, -(sframeHeight / 2 - staveBeamRadius), 0, bottomBeamRot1); + auto* bottomBeamTransf2 = + new TGeoCombiTrans(0, -(sframeHeight / 2 - staveBeamRadius), -seglen / 2, bottomBeamRot1); + auto* bottomBeamTransf3 = + new TGeoCombiTrans(0, -(sframeHeight / 2 - staveBeamRadius), seglen / 2, bottomBeamRot2); + // be careful for beams #3: when "reading" from -z to +z and + // from the bottom of the stave, it should draw a Lambda, and not a V + auto* bottomBeamRot4 = new TGeoRotation("", -90, bottomBeamAngle, -90); + auto* bottomBeamRot5 = new TGeoRotation("", -90, -bottomBeamAngle, -90); + + auto* bottomBeamTransf4 = + new TGeoCombiTrans(0, -(sframeHeight / 2 - staveBeamRadius), -seglen / 4, bottomBeamRot4); + auto* bottomBeamTransf5 = + new TGeoCombiTrans(0, -(sframeHeight / 2 - staveBeamRadius), seglen / 4, bottomBeamRot5); + + segmentVol->AddNode(sideBeamVol, 1, beamTransf[0]); + segmentVol->AddNode(sideBeamVol, 2, beamTransf[1]); + segmentVol->AddNode(sideBeamVol, 3, beamTransf[2]); + segmentVol->AddNode(sideBeamVol, 4, beamTransf[3]); + segmentVol->AddNode(sideBeamVol, 5, beamTransf[4]); + segmentVol->AddNode(sideBeamVol, 6, beamTransf[5]); + segmentVol->AddNode(sideBeamVol, 7, beamTransf[6]); + segmentVol->AddNode(sideBeamVol, 8, beamTransf[7]); + segmentVol->AddNode(bottomBeam1Vol, 1, bottomBeamTransf1); + segmentVol->AddNode(bottomBeam2Vol, 1, bottomBeamTransf2); + segmentVol->AddNode(bottomBeam2Vol, 2, bottomBeamTransf3); + segmentVol->AddNode(bottomBeam3Vol, 1, bottomBeamTransf4); + segmentVol->AddNode(bottomBeam3Vol, 2, bottomBeamTransf5); + + // Then build up the space frame + for (Int_t i = 0; i < mNumberOfModules; i++) { + zpos = -spaceFrame->GetDZ() + (1 + 2 * i) * segment->GetDZ(); + spaceFrameVol->AddNode(segmentVol, i, new TGeoTranslation(0, 0, zpos)); + } + + // Done, return the space frame structure + return spaceFrameVol; +} + +TGeoVolume* V1Layer::createChipInnerB(const Double_t xchip, const Double_t ychip, + const Double_t zchip, const TGeoManager* mgr) +{ + char volumeName[30]; + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + + // First create all needed shapes + + // The chip + auto* chip = new TGeoBBox(xchip, ychip, zchip); + + // The sensor + xlen = chip->GetDX(); + ylen = 0.5 * mSensorThickness; + zlen = chip->GetDZ(); + auto* sensor = new TGeoBBox(xlen, ylen, zlen); + + // We have all shapes: now create the real volumes + TGeoMedium* medSi = mgr->GetMedium("IT4_SI$"); + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); + auto* chipVol = new TGeoVolume(volumeName, chip, medSi); + chipVol->SetVisibility(kTRUE); + chipVol->SetLineColor(1); + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + auto* sensVol = new TGeoVolume(volumeName, sensor, medSi); + sensVol->SetVisibility(kTRUE); + sensVol->SetLineColor(8); + sensVol->SetLineWidth(1); + sensVol->SetFillColor(sensVol->GetLineColor()); + sensVol->SetFillStyle(4000); // 0% transparent + + // Now build up the chip + xpos = 0.; + ypos = -chip->GetDY() + sensor->GetDY(); + zpos = 0.; + + chipVol->AddNode(sensVol, 1, new TGeoTranslation(xpos, ypos, zpos)); + + // Done, return the chip + return chipVol; +} + +TGeoVolume* V1Layer::createModuleOuterB(const TGeoManager* mgr) +{ + char volumeName[30]; + + Double_t xGap = sOBChipXGap; + Double_t zGap = sOBChipZGap; + + Double_t xchip, ychip, zchip; + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + + // First create all needed shapes + + // The chip (the same as for IB) + xlen = (sOBHalfStaveWidth / 2 - xGap / 2) / sOBNChipRows; + ylen = 0.5 * mStaveThickness; // TO BE CHECKED + zlen = (sOBModuleZLength - (sOBChipsPerRow - 1) * zGap) / (2 * sOBChipsPerRow); + + TGeoVolume* chipVol = createChipInnerB(xlen, ylen, zlen); + + xchip = ((TGeoBBox*)chipVol->GetShape())->GetDX(); + ychip = ((TGeoBBox*)chipVol->GetShape())->GetDY(); + zchip = ((TGeoBBox*)chipVol->GetShape())->GetDZ(); + + // The module carbon plate + xlen = sOBHalfStaveWidth / 2; + ylen = sOBCarbonPlateThick / 2; + zlen = sOBModuleZLength / 2; + auto* modPlate = new TGeoBBox("CarbonPlate", xlen, ylen, zlen); + + // The glue + ylen = sOBGlueThick / 2; + auto* glue = new TGeoBBox("Glue", xlen, ylen, zlen); + + // The flex cables + ylen = sOBFlexCableAlThick / 2; + auto* flexAl = new TGeoBBox("FlexAl", xlen, ylen, zlen); + + ylen = sOBFlexCableKapThick / 2; + auto* flexKap = new TGeoBBox("FlexKap", xlen, ylen, zlen); + + // The module + xlen = sOBHalfStaveWidth / 2; + ylen = ychip + modPlate->GetDY() + glue->GetDY() + flexAl->GetDY() + flexKap->GetDY(); + zlen = sOBModuleZLength / 2; + auto* module = new TGeoBBox("OBModule", xlen, ylen, zlen); + + // We have all shapes: now create the real volumes + + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medCarbon = mgr->GetMedium("IT4_CARBON$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + + auto* modPlateVol = new TGeoVolume("CarbonPlateVol", modPlate, medCarbon); + modPlateVol->SetLineColor(kMagenta - 8); + modPlateVol->SetFillColor(modPlateVol->GetLineColor()); + modPlateVol->SetFillStyle(4000); // 0% transparent + + auto* glueVol = new TGeoVolume("GlueVol", glue, medGlue); + glueVol->SetLineColor(kBlack); + glueVol->SetFillColor(glueVol->GetLineColor()); + glueVol->SetFillStyle(4000); // 0% transparent + + auto* flexAlVol = new TGeoVolume("FlexAlVol", flexAl, medAluminum); + flexAlVol->SetLineColor(kRed); + flexAlVol->SetFillColor(flexAlVol->GetLineColor()); + flexAlVol->SetFillStyle(4000); // 0% transparent + + auto* flexKapVol = new TGeoVolume("FlexKapVol", flexKap, medKapton); + flexKapVol->SetLineColor(kGreen); + flexKapVol->SetFillColor(flexKapVol->GetLineColor()); + flexKapVol->SetFillStyle(4000); // 0% transparent + + snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + auto* modVol = new TGeoVolume(volumeName, module, medAir); + modVol->SetVisibility(kTRUE); + + // Now build up the module + ypos = -module->GetDY() + modPlate->GetDY(); + modVol->AddNode(modPlateVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (modPlate->GetDY() + glue->GetDY()); + modVol->AddNode(glueVol, 1, new TGeoTranslation(0, ypos, 0)); + + xpos = -module->GetDX() + xchip; + ypos += (glue->GetDY() + ychip); + for (Int_t k = 0; k < sOBChipsPerRow; k++) { // put 7x2 chip into one module + zpos = -module->GetDZ() + zchip + k * (2 * zchip + zGap); + modVol->AddNode(chipVol, 2 * k, new TGeoTranslation(xpos, ypos, zpos)); + modVol->AddNode(chipVol, 2 * k + 1, + new TGeoCombiTrans(-xpos, ypos, zpos, new TGeoRotation("", 0, 180, 180))); + mHierarchy[kChip] += 2; + } + + ypos += (ychip + flexAl->GetDY()); + modVol->AddNode(flexAlVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (flexAl->GetDY() + flexKap->GetDY()); + modVol->AddNode(flexKapVol, 1, new TGeoTranslation(0, ypos, 0)); + + // Done, return the module + return modVol; +} + +Double_t V1Layer::radiusOmTurboContainer() +{ + Double_t rr, delta, z, lstav, rstav; + + if (mStaveThickness > 89.) { // Very big angle: avoid overflows since surely + return -1; // the radius from lower vertex is the right value + } + + rstav = mLayerRadius + 0.5 * mStaveThickness; + delta = (0.5 * mStaveThickness) / cosD(mStaveTilt); + z = (0.5 * mStaveThickness) * tanD(mStaveTilt); + + rr = rstav - delta; + lstav = (0.5 * mStaveWidth) - z; + + if ((rr * sinD(mStaveTilt) < lstav)) { + return (rr * cosD(mStaveTilt)); + } else { + return -1; + } +} + +void V1Layer::setNumberOfUnits(Int_t u) +{ + if (mLayerNumber < sNumberOmInnerLayers) { + mNumberOfChips = u; + } else { + mNumberOfModules = u; + mNumberOfChips = sOBChipsPerRow; + } +} + +void V1Layer::setStaveTilt(const Double_t t) +{ + if (mIsTurbo) { + mStaveTilt = t; + } else { + LOG(ERROR) << "Not a Turbo layer"; + } +} + +void V1Layer::setStaveWidth(const Double_t w) +{ + if (mIsTurbo) { + mStaveWidth = w; + } else { + LOG(ERROR) << "Not a Turbo layer"; + } +} + +TGeoArb8* V1Layer::createStaveSide(const char* name, Double_t dz, Double_t angle, + Double_t xSign, Double_t L, Double_t H, Double_t l) +{ + // Create one half of the V shape corner of CF stave + + auto* cmStavSide = new TGeoArb8(dz); + cmStavSide->SetName(name); + + // Points must be in clockwise order + cmStavSide->SetVertex(0, 0, 0); + cmStavSide->SetVertex(2, xSign * (L * TMath::Sin(angle) - l * TMath::Cos(angle)), + -L * TMath::Cos(angle) - l * TMath::Sin(angle)); + cmStavSide->SetVertex(4, 0, 0); + cmStavSide->SetVertex(6, xSign * (L * TMath::Sin(angle) - l * TMath::Cos(angle)), + -L * TMath::Cos(angle) - l * TMath::Sin(angle)); + if (xSign < 0) { + cmStavSide->SetVertex(1, 0, -H); + cmStavSide->SetVertex(3, xSign * L * TMath::Sin(angle), -L * TMath::Cos(angle)); + cmStavSide->SetVertex(5, 0, -H); + cmStavSide->SetVertex(7, xSign * L * TMath::Sin(angle), -L * TMath::Cos(angle)); + } else { + cmStavSide->SetVertex(1, xSign * L * TMath::Sin(angle), -L * TMath::Cos(angle)); + cmStavSide->SetVertex(3, 0, -H); + cmStavSide->SetVertex(5, xSign * L * TMath::Sin(angle), -L * TMath::Cos(angle)); + cmStavSide->SetVertex(7, 0, -H); + } + return cmStavSide; +} + +TGeoCombiTrans* V1Layer::createCombiTrans(const char* name, Double_t dy, Double_t dz, + Double_t dphi, Bool_t planeSym) +{ + TGeoTranslation t1(dy * cosD(90. + dphi), dy * sinD(90. + dphi), dz); + TGeoRotation r1("", 0., 0., dphi); + TGeoRotation r2("", 90, 180, -90 - dphi); + + auto* combiTrans1 = new TGeoCombiTrans(name); + combiTrans1->SetTranslation(t1); + if (planeSym) { + combiTrans1->SetRotation(r1); + } else { + combiTrans1->SetRotation(r2); + } + return combiTrans1; +} + +void V1Layer::addTranslationToCombiTrans(TGeoCombiTrans* ct, Double_t dx, Double_t dy, + Double_t dz) const +{ + // Add a dx,dy,dz translation to the initial TGeoCombiTrans + const Double_t* vect = ct->GetTranslation(); + Double_t newVect[3] = {vect[0] + dx, vect[1] + dy, vect[2] + dz}; + ct->SetTranslation(newVect); +} diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx new file mode 100644 index 0000000000000..22d264a981b73 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx @@ -0,0 +1,3840 @@ +// 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 V3Layer.cxx +/// \brief Implementation of the V3Layer class +/// \author Mario Sitta <sitta@to.infn.it> +/// \author Chinorat Kobdaj (kobdaj@g.sut.ac.th) + +#include "ITS4Simulation/V3Layer.h" +#include "ITS4Base/GeometryTGeo.h" +#include "ITS4Simulation/Detector.h" +#include "ITSMFTSimulation/AlpideChip.h" +#include "ITSMFTBase/SegmentationAlpide.h" + +#include "FairLogger.h" // for LOG + +#include <TGeoArb8.h> // for TGeoArb8 +#include <TGeoBBox.h> // for TGeoBBox +#include <TGeoCone.h> // for TGeoConeSeg, TGeoCone +#include <TGeoPcon.h> // for TGeoPcon +#include <TGeoManager.h> // for TGeoManager, gGeoManager +#include <TGeoMatrix.h> // for TGeoCombiTrans, TGeoRotation, etc +#include <TGeoTrd1.h> // for TGeoTrd1 +#include <TGeoTube.h> // for TGeoTube, TGeoTubeSeg +#include <TGeoVolume.h> // for TGeoVolume, TGeoVolumeAssembly +#include <TGeoXtru.h> // for TGeoXtru +#include <TGeoCompositeShape.h> // for TGeoCompositeShape +#include "TMathBase.h" // for Abs +#include <TMath.h> // for Sin, RadToDeg, DegToRad, Cos, Tan, etc + +#include <cstdio> // for snprintf + +class TGeoMedium; + +using namespace TMath; +using namespace o2::its4; +using namespace o2::itsmft; +using AlpideChip = o2::itsmft::AlpideChip; + +// General Parameters +const Int_t V3Layer::sNumberOfInnerLayers = 3; + +// Inner Barrel Parameters +const Int_t V3Layer::sIBChipsPerRow = 9; +const Int_t V3Layer::sIBNChipRows = 1; +const Double_t V3Layer::sIBChipZGap = 150.0 * sMicron; + +const Double_t V3Layer::sIBModuleZLength = 27.12 * sCm; +const Double_t V3Layer::sIBFPCWiderXPlus = 850.0 * sMicron; +const Double_t V3Layer::sIBFPCWiderXNeg = 300.0 * sMicron; +const Double_t V3Layer::sIBFlexCableAlThick = 25.0 * sMicron; +const Double_t V3Layer::sIBFPCAlGNDWidth = (4.1 + 11.15) * sMm; +const Double_t V3Layer::sIBFPCAlAnodeWidth1 = 13.0 * sMm; +const Double_t V3Layer::sIBFPCAlAnodeWidth2 = 14.7 * sMm; +const Double_t V3Layer::sIBFlexCableKapThick = 75.0 * sMicron; +const Double_t V3Layer::sIBFlexCablePolyThick = 20.0 * sMicron; +const Double_t V3Layer::sIBFlexCapacitorXWid = 0.2 * sMm; +const Double_t V3Layer::sIBFlexCapacitorYHi = 0.2 * sMm; +const Double_t V3Layer::sIBFlexCapacitorZLen = 0.4 * sMm; +const Double_t V3Layer::sIBColdPlateWidth = 15.4 * sMm; +const Double_t V3Layer::sIBColdPlateZLen = 290.0 * sMm; +const Double_t V3Layer::sIBGlueThick = 50.0 * sMicron; +const Double_t V3Layer::sIBCarbonFleeceThick = 20.0 * sMicron; +const Double_t V3Layer::sIBCarbonPaperThick = 30.0 * sMicron; +const Double_t V3Layer::sIBCarbonPaperWidth = 12.5 * sMm; +const Double_t V3Layer::sIBCarbonPaperZLen = 280.0 * sMm; +const Double_t V3Layer::sIBK13D2UThick = 70.0 * sMicron; +const Double_t V3Layer::sIBCoolPipeInnerD = 1.024 * sMm; +const Double_t V3Layer::sIBCoolPipeThick = 25.4 * sMicron; +const Double_t V3Layer::sIBCoolPipeXDist = 5.0 * sMm; +const Double_t V3Layer::sIBCoolPipeZLen = 302.0 * sMm; +const Double_t V3Layer::sIBTopVertexWidth1 = 0.258 * sMm; +const Double_t V3Layer::sIBTopVertexWidth2 = 0.072 * sCm; +const Double_t V3Layer::sIBTopVertexHeight = 0.04 * sCm; +const Double_t V3Layer::sIBTopVertexAngle = 60.0; // Deg +const Double_t V3Layer::sIBSideVertexWidth = 0.05 * sCm; +const Double_t V3Layer::sIBSideVertexHeight = 0.074 * sCm; +const Double_t V3Layer::sIBTopFilamentSide = 0.04 * sCm; +const Double_t V3Layer::sIBTopFilamentAlpha = 109.8; // Deg +const Double_t V3Layer::sIBTopFilamentInterZ = 15.0 * sMm; +const Double_t V3Layer::sIBEndSupportThick = 0.149 * sMm; +const Double_t V3Layer::sIBEndSupportZLen = 2.5 * sMm; +const Double_t V3Layer::sIBEndSupportXUp = 1.0 * sMm; +const Double_t V3Layer::sIBEndSupportOpenPhi = 120.0; // Deg + +const Double_t V3Layer::sIBConnectorXWidth = 10.0 * sMm; +const Double_t V3Layer::sIBConnectorYTot = 4.7 * sMm; +const Double_t V3Layer::sIBConnectBlockZLen = 16.5 * sMm; +const Double_t V3Layer::sIBConnBodyYHeight = 2.5 * sMm; +const Double_t V3Layer::sIBConnTailYShift = 0.9 * sMm; +const Double_t V3Layer::sIBConnTailYMid = 2.5 * sMm; +const Double_t V3Layer::sIBConnTailZLen = 2.5 * sMm; +const Double_t V3Layer::sIBConnTailOpenPhi = 120.0; // Deg +const Double_t V3Layer::sIBConnRoundHoleD = 2.0 * sMm; +const Double_t V3Layer::sIBConnRoundHoleZ = (9.0 - 4.0) * sMm; +const Double_t V3Layer::sIBConnSquareHoleX = 2.0 * sMm; +const Double_t V3Layer::sIBConnSquareHoleZ = 2.8 * sMm; +const Double_t V3Layer::sIBConnSquareHoleZPos = 9.0 * sMm; +const Double_t V3Layer::sIBConnInsertHoleD = 2.0 * sMm; +const Double_t V3Layer::sIBConnInsertHoleZPos = 9.0 * sMm; +const Double_t V3Layer::sIBConnTubeHole1D = 1.6 * sMm; +const Double_t V3Layer::sIBConnTubeHole1ZLen = 3.0 * sMm; +const Double_t V3Layer::sIBConnTubeHole1ZLen2 = 2.7 * sMm; +const Double_t V3Layer::sIBConnTubeHole2D = 1.2 * sMm; +const Double_t V3Layer::sIBConnTubeHole3XPos = 1.0 * sMm; +const Double_t V3Layer::sIBConnTubeHole3ZPos = 14.5 * sMm; +const Double_t V3Layer::sIBConnTubesXDist = 5.0 * sMm; +const Double_t V3Layer::sIBConnTubesYPos = 1.25 * sMm; +const Double_t V3Layer::sIBConnInsertD = 2.0 * sMm; +const Double_t V3Layer::sIBConnInsertHeight = 2.3 * sMm; +const Double_t V3Layer::sIBConnSideHole1D = 1.0 * sMm; +const Double_t V3Layer::sIBConnSideHole1YPos = 1.25 * sMm; +const Double_t V3Layer::sIBConnSideHole1ZPos = 11.5 * sMm; +const Double_t V3Layer::sIBConnSideHole1XWid = 1.0 * sMm; +const Double_t V3Layer::sIBConnSideHole2YPos = 1.25 * sMm; +const Double_t V3Layer::sIBConnSideHole2ZPos = 11.0 * sMm; +const Double_t V3Layer::sIBConnSideHole2XWid = 1.0 * sMm; +const Double_t V3Layer::sIBConnSideHole2YWid = 1.0 * sMm; +const Double_t V3Layer::sIBConnSideHole2ZWid = 1.0 * sMm; +const Double_t V3Layer::sIBConnectAFitExtD = 1.65 * sMm; +const Double_t V3Layer::sIBConnectAFitIntD = 1.19 * sMm; +const Double_t V3Layer::sIBConnectAFitZLen = 12.5 * sMm; +const Double_t V3Layer::sIBConnectAFitZOut = 10.0 * sMm; +const Double_t V3Layer::sIBConnPlugInnerD = 0.8 * sMm; +const Double_t V3Layer::sIBConnPlugTotLen = 1.7 * sMm; +const Double_t V3Layer::sIBConnPlugInnerLen = 1.0 * sMm; + +const Double_t V3Layer::sIBStaveHeight = 0.5 * sCm; + +// Outer Barrel Parameters +const Int_t V3Layer::sOBChipsPerRow = 7; +const Int_t V3Layer::sOBNChipRows = 2; + +const Double_t V3Layer::sOBChipThickness = 100.0 * sMicron; + +const Double_t V3Layer::sOBHalfStaveWidth = 3.01 * sCm; +const Double_t V3Layer::sOBModuleGap = 200.0 * sMicron; +const Double_t V3Layer::sOBChipXGap = 150.0 * sMicron; +const Double_t V3Layer::sOBChipZGap = 150.0 * sMicron; +const Double_t V3Layer::sOBFlexCableXWidth = 3.3 * sCm; +const Double_t V3Layer::sOBFlexCableAlThick = 0.005 * sCm; +const Double_t V3Layer::sOBFlexCableKapThick = 75.0 * sMicron; +const Double_t V3Layer::sOBFPCSoldMaskThick = 30.0 * sMicron; +const Double_t V3Layer::sOBFPCCopperThick = 18.0 * sMicron; +const Double_t V3Layer::sOBFPCCuAreaFracGnd = 0.954; // F.Benotto +const Double_t V3Layer::sOBFPCCuAreaFracSig = 0.617; // F.Benotto +const Double_t V3Layer::sOBGlueFPCThick = 50 * sMicron; +const Double_t V3Layer::sOBGlueColdPlThick = 80 * sMicron; +const Double_t V3Layer::sOBPowerBusXWidth = 3.04 * sCm; +const Double_t V3Layer::sOBPowerBusAlThick = 100.0 * sMicron; +const Double_t V3Layer::sOBPowerBusAlFrac = 0.90; // L.Greiner +const Double_t V3Layer::sOBPowerBusDielThick = 50.0 * sMicron; +const Double_t V3Layer::sOBPowerBusKapThick = 27.5 * sMicron; +const Double_t V3Layer::sOBBiasBusXWidth = 7.7 * sMm; +const Double_t V3Layer::sOBBiasBusAlThick = 25.0 * sMicron; +const Double_t V3Layer::sOBBiasBusAlFrac = 0.90; // L.Greiner +const Double_t V3Layer::sOBBiasBusDielThick = 50.0 * sMicron; +const Double_t V3Layer::sOBBiasBusKapThick = 25.0 * sMicron; +const Double_t V3Layer::sOBColdPlateXWidth = 3.04 * sCm; +const Double_t V3Layer::sOBColdPlateZLenML = 87.55 * sCm; +const Double_t V3Layer::sOBColdPlateZLenOL = 150.15 * sCm; +const Double_t V3Layer::sOBColdPlateThick = 0.012 * sCm; +const Double_t V3Layer::sOBHalfStaveYPos = 2.067 * sCm; +const Double_t V3Layer::sOBHalfStaveYTrans = 1.76 * sMm; +const Double_t V3Layer::sOBHalfStaveXOverlap = 7.2 * sMm; +const Double_t V3Layer::sOBGraphiteFoilThick = 30.0 * sMicron; +const Double_t V3Layer::sOBCarbonFleeceThick = 20.0 * sMicron; +const Double_t V3Layer::sOBCoolTubeInnerD = 2.05 * sMm; +const Double_t V3Layer::sOBCoolTubeThick = 32.0 * sMicron; +const Double_t V3Layer::sOBCoolTubeXDist = 10.0 * sMm; + +const Double_t V3Layer::sOBCPConnectorXWidth = 16.0 * sMm; +const Double_t V3Layer::sOBCPConnBlockZLen = 15.0 * sMm; +const Double_t V3Layer::sOBCPConnBlockYHei = 3.6 * sMm; +const Double_t V3Layer::sOBCPConnHollowZLen = 3.0 * sMm; +const Double_t V3Layer::sOBCPConnHollowYHei = 0.9 * sMm; +const Double_t V3Layer::sOBCPConnSquareHoleX = 4.0 * sMm; +const Double_t V3Layer::sOBCPConnSquareHoleZ = 5.0 * sMm; +const Double_t V3Layer::sOBCPConnSqrHoleZPos = 4.0 * sMm; +const Double_t V3Layer::sOBCPConnSqrInsertRZ = 3.5 * sMm; +const Double_t V3Layer::sOBCPConnRoundHoleD = 4.0 * sMm; +const Double_t V3Layer::sOBCPConnRndHoleZPos = 7.0 * sMm; +const Double_t V3Layer::sOBCPConnTubesXDist = 10.0 * sMm; +const Double_t V3Layer::sOBCPConnTubesYPos = 1.8 * sMm; +const Double_t V3Layer::sOBCPConnTubeHole1D = 2.6 * sMm; +const Double_t V3Layer::sOBCPConnTubeHole1Z = 3.5 * sMm; +const Double_t V3Layer::sOBCPConnTubeHole2D = 2.2 * sMm; +const Double_t V3Layer::sOBCPConnFitHoleD = 2.8 * sMm; +const Double_t V3Layer::sOBCPConnTubeHole3XP = 1.0 * sMm; +const Double_t V3Layer::sOBCPConnTubeHole3ZP = 2.0 * sMm; +const Double_t V3Layer::sOBCPConnInstZThick = 1.0 * sMm; +const Double_t V3Layer::sOBCPConnInsertYHei = 3.4 * sMm; +const Double_t V3Layer::sOBCPConnAFitExtD = 2.8 * sMm; +const Double_t V3Layer::sOBCPConnAFitThick = 0.3 * sMm; +const Double_t V3Layer::sOBCPConnAFitZLen = 17.0 * sMm; +const Double_t V3Layer::sOBCPConnAFitZIn = 3.0 * sMm; +const Double_t V3Layer::sOBCPConnPlugInnerD = 0.8 * sMm; +const Double_t V3Layer::sOBCPConnPlugTotLen = 1.7 * sMm; +const Double_t V3Layer::sOBCPConnPlugThick = 0.5 * sMm; + +const Double_t V3Layer::sOBSpaceFrameZLen[2] = {900.0 * sMm, 1526.0 * sMm}; +const Int_t V3Layer::sOBSpaceFrameNUnits[2] = {23, 39}; +const Double_t V3Layer::sOBSpaceFrameUnitLen = 39.1 * sMm; +const Double_t V3Layer::sOBSpaceFrameWidth = 42.44 * sMm; +const Double_t V3Layer::sOBSpaceFrameHeight = 36.45 * sMm; +const Double_t V3Layer::sOBSpaceFrameTopVL = 4.0 * sMm; +const Double_t V3Layer::sOBSpaceFrameTopVH = 0.35 * sMm; +const Double_t V3Layer::sOBSpaceFrameSideVL = 4.5 * sMm; +const Double_t V3Layer::sOBSpaceFrameSideVH = 0.35 * sMm; +const Double_t V3Layer::sOBSpaceFrameVAlpha = 60.0; // deg +const Double_t V3Layer::sOBSpaceFrameVBeta = 68.0; // deg +const Double_t V3Layer::sOBSFrameBaseRibDiam = 1.33 * sMm; +const Double_t V3Layer::sOBSFrameBaseRibPhi = 54.0; // deg +const Double_t V3Layer::sOBSFrameSideRibDiam = 1.25 * sMm; +const Double_t V3Layer::sOBSFrameSideRibPhi = 70.0; // deg +const Double_t V3Layer::sOBSFrameULegLen = 14.2 * sMm; +const Double_t V3Layer::sOBSFrameULegWidth = 1.5 * sMm; +const Double_t V3Layer::sOBSFrameULegHeight1 = 2.7 * sMm; +const Double_t V3Layer::sOBSFrameULegHeight2 = 5.0 * sMm; +const Double_t V3Layer::sOBSFrameULegThick = 0.3 * sMm; +const Double_t V3Layer::sOBSFrameULegXPos = 12.9 * sMm; +const Double_t V3Layer::sOBSFrameConnWidth = 42.0 * sMm; +const Double_t V3Layer::sOBSFrameConnTotLen = 29.0 * sMm; +const Double_t V3Layer::sOBSFrameConnTotHei = 4.8 * sMm; +const Double_t V3Layer::sOBSFrameConnTopLen = 14.0 * sMm; +const Double_t V3Layer::sOBSFrameConnInsWide = 36.869 * sMm; +const Double_t V3Layer::sOBSFrameConnInsBase = 39.6 * sMm; +const Double_t V3Layer::sOBSFrameConnInsHei = 2.8 * sMm; +const Double_t V3Layer::sOBSFrameConnHoleZPos = 7.0 * sMm; +const Double_t V3Layer::sOBSFrameConnHoleZDist = 15.0 * sMm; +const Double_t V3Layer::sOBSFrameConnTopHoleD = 3.0 * sMm; +const Double_t V3Layer::sOBSFrConnTopHoleXDist = 24.0 * sMm; +const Double_t V3Layer::sOBSFrameConnAHoleWid = 4.0 * sMm; +const Double_t V3Layer::sOBSFrameConnAHoleLen = 5.0 * sMm; +const Double_t V3Layer::sOBSFrConnASideHoleD = 3.0 * sMm; +const Double_t V3Layer::sOBSFrConnASideHoleL = 2.5 * sMm; +const Double_t V3Layer::sOBSFrConnASideHoleY = 2.3 * sMm; +const Double_t V3Layer::sOBSFrameConnCHoleZPos = 3.0 * sMm; +const Double_t V3Layer::sOBSFrConnCHoleXDist = 32.0 * sMm; +const Double_t V3Layer::sOBSFrConnCTopHoleD = 4.0 * sMm; +const Double_t V3Layer::sOBSFrameConnInsHoleD = 5.0 * sMm; +const Double_t V3Layer::sOBSFrameConnInsHoleX = 25.8 * sMm; + +ClassImp(V3Layer); + +#define SQ(A) (A) * (A) + +V3Layer::V3Layer() + : V11Geometry(), + mLayerNumber(0), + mNumberOfInnerLayers(0), + mPhi0(0), + mLayerRadius(0), + mSensorThickness(0), + mChipThickness(0), + mStaveWidth(0), + mStaveTilt(0), + mNumberOfStaves(0), + mNumberOfModules(0), + mNumberOfChips(0), + mChipTypeID(0), + mIsTurbo(0), + mIsITS4(0), + mBuildLevel(0), + mStaveModel(Detector::kIBModelDummy), + mAddGammaConv(kFALSE), + mGammaConvDiam(0), + mGammaConvXPos(0), + mIBModuleZLength(0), + mOBModuleZLength(0) +{ + for (int i = kNHLevels; i--;) { + mHierarchy[i] = 0; + } +} + +V3Layer::V3Layer(Int_t lay, Bool_t turbo, Int_t debug) + : V11Geometry(debug), + mLayerNumber(lay), + mNumberOfInnerLayers(sNumberOfInnerLayers), + mPhi0(0), + mLayerRadius(0), + mSensorThickness(0), + mChipThickness(0), + mStaveWidth(0), + mStaveTilt(0), + mNumberOfStaves(0), + mNumberOfModules(0), + mNumberOfChips(0), + mChipTypeID(0), + mIsTurbo(turbo), + mIsITS4(0), + mBuildLevel(0), + mStaveModel(Detector::kIBModelDummy), + mAddGammaConv(kFALSE), + mGammaConvDiam(0), + mGammaConvXPos(0), + mIBModuleZLength(0), + mOBModuleZLength(0) +{ + for (int i = kNHLevels; i--;) { + mHierarchy[i] = 0; + } +} + +V3Layer::~V3Layer() = default; + +void V3Layer::createLayer(TGeoVolume* motherVolume) +{ + const Int_t nameLen = 30; + char volumeName[nameLen]; + Double_t xpos, ypos, zpos; + Double_t alpha; + + // Check if the user set the proper parameters + if (mLayerRadius <= 0) { + LOG(FATAL) << "Wrong layer radius " << mLayerRadius; + } + /* // These checks would fail with new ITS4 geo, let's trust the user here :) + if (mNumberOfStaves <= 0) { + LOG(FATAL) << "Wrong number of staves " << mNumberOfStaves; + } + + if (mNumberOfChips <= 0) { + LOG(FATAL) << "Wrong number of chips " << mNumberOfChips; + } + + if (mLayerNumber >= sNumberOfInnerLayers && mNumberOfModules <= 0) { + LOG(FATAL) << "Wrong number of modules " << mNumberOfModules; + } + + if (mChipThickness <= 0) { + LOG(FATAL) << "Chip thickness wrong or not set " << mChipThickness; + } + + if (mSensorThickness <= 0) { + LOG(FATAL) << "Sensor thickness wrong or not set " << mSensorThickness; + } + + if (mSensorThickness > mChipThickness) { + LOG(FATAL) << "Sensor thickness " << mSensorThickness << " is greater than chip thickness " << mChipThickness; + } +*/ + // If a Turbo layer is requested, do it and exit + if (mIsTurbo) { + createLayerTurbo(motherVolume); + return; + } + + // If a new ITS4 layer is requested, do it and exit + if (mIsITS4) { + createITS4Layer(motherVolume); + return; + } + + // First create the stave container + alpha = (360. / (2 * mNumberOfStaves)) * DegToRad(); + + // mStaveWidth = mLayerRadius*Tan(alpha); + + snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); + layerVolume->SetUniqueID(mChipTypeID); + + // layerVolume->SetVisibility(kFALSE); + layerVolume->SetVisibility(kTRUE); + layerVolume->SetLineColor(1); + + TGeoVolume* stavVol = createStave(); + + // Now build up the layer + alpha = 360. / mNumberOfStaves; + Double_t r = mLayerRadius + (static_cast<TGeoBBox*>(stavVol->GetShape()))->GetDY(); + for (Int_t j = 0; j < mNumberOfStaves; j++) { + Double_t phi = j * alpha + mPhi0; + xpos = r * cosD(phi); // r*sinD(-phi); + ypos = r * sinD(phi); // r*cosD(-phi); + zpos = 0.; + phi += 90; + layerVolume->AddNode(stavVol, j, new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", phi, 0, 0))); + } + + // Finally put everything in the mother volume + motherVolume->AddNode(layerVolume, 1, nullptr); + + // geometry is served + return; +} + +void V3Layer::createLayerTurbo(TGeoVolume* motherVolume) +{ + const Int_t nameLen = 30; + char volumeName[nameLen]; + Double_t xpos, ypos, zpos; + Double_t alpha; + + // Check if the user set the proper (remaining) parameters + if (mStaveWidth <= 0) { + LOG(FATAL) << "Wrong stave width " << mStaveWidth; + } + + if (Abs(mStaveTilt) > 45) { + LOG(WARNING) << "Stave tilt angle (" << mStaveTilt << ") greater than 45deg"; + } + + snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); + layerVolume->SetUniqueID(mChipTypeID); + layerVolume->SetVisibility(kTRUE); + layerVolume->SetLineColor(1); + TGeoVolume* stavVol = createStave(); + + // Now build up the layer + alpha = 360. / mNumberOfStaves; + Double_t r = mLayerRadius /* +chip thick ?! */; + for (Int_t j = 0; j < mNumberOfStaves; j++) { + Double_t phi = j * alpha + mPhi0; + xpos = r * cosD(phi); // r*sinD(-phi); + ypos = r * sinD(phi); // r*cosD(-phi); + zpos = 0.; + phi += 90; + layerVolume->AddNode(stavVol, j, + new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", phi - mStaveTilt, 0, 0))); + } + + // Finally put everything in the mother volume + motherVolume->AddNode(layerVolume, 1, nullptr); + + return; +} + +void V3Layer::createITS4Layer(TGeoVolume* motherVolume, const TGeoManager* mgr) +{ + + Double_t rmin = mLayerRadius; + Double_t rmax = rmin + mSensorThickness; + + const Int_t nameLen = 30; + char chipName[nameLen], sensName[nameLen], moduleName[nameLen], + hsName[nameLen], staveName[nameLen], layerName[nameLen]; + + snprintf(sensName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); + snprintf(moduleName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + snprintf(hsName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(staveName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); + snprintf(layerName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + + TGeoTube* sensor = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); + TGeoTube* chip = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); + TGeoTube* module = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); + TGeoTube* hstave = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); + TGeoTube* stave = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); + TGeoTube* layer = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); + + TGeoMedium* medSi = mgr->GetMedium("IT4_SI$"); + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi); + TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medAir); + TGeoVolume* modVol = new TGeoVolume(moduleName, hstave, medAir); + TGeoVolume* hstaveVol = new TGeoVolume(hsName, hstave, medAir); + TGeoVolume* staveVol = new TGeoVolume(staveName, stave, medAir); + TGeoVolume* layerVol = new TGeoVolume(layerName, layer, medAir); + + LOG(DEBUG) << "Inserting " << sensVol->GetName() << " inside " << chipVol->GetName(); + chipVol->AddNode(sensVol, 1, nullptr); + + LOG(DEBUG) << "Inserting " << chipVol->GetName() << " inside " << modVol->GetName(); + modVol->AddNode(chipVol, 0, nullptr); + mHierarchy[kChip] = 1; + + LOG(DEBUG) << "Inserting " << modVol->GetName() << " inside " << hstaveVol->GetName(); + hstaveVol->AddNode(modVol, 0, nullptr); + mHierarchy[kModule] = 1; + + LOG(DEBUG) << "Inserting " << hstaveVol->GetName() << " inside " << staveVol->GetName(); + staveVol->AddNode(hstaveVol, 0, nullptr); + mHierarchy[kHalfStave] = 1; + + LOG(DEBUG) << "Inserting " << staveVol->GetName() << " inside " << layerVol->GetName(); + layerVol->AddNode(staveVol, 0, nullptr); + mHierarchy[kStave] = 1; + + // Finally put everything in the mother volume + LOG(DEBUG) << "Inserting " << layerVol->GetName() << " inside " << motherVolume->GetName(); + motherVolume->AddNode(layerVol, 1, nullptr); + + return; +} + +TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) +{ + // + // Creates the actual Stave + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 22 Jun 2011 Mario Sitta + // Updated: 18 Dec 2013 Mario Sitta Handle IB and OB + // Updated: 12 Jan 2015 Mario Sitta Fix overlap with new OB space frame + // (by moving the latter, not the sensors to avoid + // spoiling their position in space) + // Updated: 03 Mar 2015 Mario Sitta Fix chip position + // Updated: 16 Mar 2017 Mario Sitta AliceO2 version + // Updated: 10 Jan 2018 Mario Sitta Compute all dimensions using + // AlpideChip as basis + // + + const Int_t nameLen = 30; + char volumeName[nameLen]; + + Double_t xpos, ypos; + Double_t alpha; + + // First create all needed shapes + alpha = (360. / (2 * mNumberOfStaves)) * DegToRad(); + + // The stave + snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); + TGeoVolume* staveVol = new TGeoVolumeAssembly(volumeName); + staveVol->SetVisibility(kTRUE); + staveVol->SetLineColor(2); + + TGeoVolume* mechStaveVol = nullptr; + + // Now build up the stave + if (mLayerNumber < mNumberOfInnerLayers) { + TGeoVolume* modVol = createStaveInnerB(); + ypos = (static_cast<TGeoBBox*>(modVol->GetShape()))->GetDY() - mChipThickness; // = 0 if not kIBModel4 + staveVol->AddNode(modVol, 0, new TGeoTranslation(0, ypos, 0)); + mHierarchy[kHalfStave] = 1; + + // Mechanical stave structure + // mechStaveVol = createStaveStructInnerB(); + if (mechStaveVol) { + ypos = (static_cast<TGeoBBox*>(modVol->GetShape()))->GetDY() - ypos; + if (mStaveModel != Detector::kIBModel4) + ypos += (static_cast<TGeoBBox*>(mechStaveVol->GetShape()))->GetDY(); + staveVol->AddNode(mechStaveVol, 1, new TGeoCombiTrans(0, -ypos, 0, new TGeoRotation("", 0, 0, 180))); + } + } else { + TGeoVolume* hstaveVol = createStaveOuterB(); + if (mStaveModel == Detector::kOBModel0) { // Create simplified stave struct as in v0 + staveVol->AddNode(hstaveVol, 0); + mHierarchy[kHalfStave] = 1; + } else { // (if mStaveModel) Create new stave struct as in TDR + xpos = (static_cast<TGeoBBox*>(hstaveVol->GetShape()))->GetDX() - sOBHalfStaveXOverlap / 2; + // ypos is now a parameter to avoid HS displacement wrt nominal radii + ypos = sOBHalfStaveYPos; + staveVol->AddNode(hstaveVol, 0, new TGeoTranslation(-xpos, ypos, 0)); + staveVol->AddNode(hstaveVol, 1, new TGeoTranslation(xpos, ypos + sOBHalfStaveYTrans, 0)); + mHierarchy[kHalfStave] = 2; // RS + mechStaveVol = createSpaceFrameOuterB(); + + if (mechStaveVol) { + if (mBuildLevel < 6) // Carbon + staveVol->AddNode(mechStaveVol, 1, + new TGeoCombiTrans(0, -sOBSFrameULegHeight1, 0, new TGeoRotation("", 180, 0, 0))); + } + } + } + + staveVol->GetShape()->ComputeBBox(); // RS: enfore recompting of BBox + + // Done, return the stave + return staveVol; +} + +TGeoVolume* V3Layer::createStaveInnerB(const TGeoManager* mgr) +{ + Double_t xmod, ymod, zmod; + const Int_t nameLen = 30; + char volumeName[nameLen]; + + // First we create the module (i.e. the HIC with 9 chips) + TGeoVolume* moduleVol = createModuleInnerB(); + + // Then we create the fake halfstave and the actual stave + xmod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDX(); + ymod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDY(); + zmod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDZ(); + + TGeoBBox* hstave = new TGeoBBox(xmod, ymod, zmod); + + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + TGeoVolume* hstaveVol = new TGeoVolume(volumeName, hstave, medAir); + + // Finally build it up + hstaveVol->AddNode(moduleVol, 0); + mHierarchy[kModule] = 1; + + // Done, return the stave structure + return hstaveVol; +} + +TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) +{ + Double_t xtot, ytot, ztot, xchip, zchip, ymod; + Double_t xpos, ypos, zpos; + Bool_t dummyChip; + const Int_t nameLen = 30; + char chipName[nameLen], sensName[nameLen], volumeName[nameLen]; + + // For material budget studies + if (mBuildLevel < 6) + dummyChip = kFALSE; // will be made of Si + else + dummyChip = kTRUE; // will be made of Air + + // First create the single chip + snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); + snprintf(sensName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + + ymod = 0.5 * mChipThickness; + + TGeoVolume* chipVol = AlpideChip::createChip(ymod, mSensorThickness / 2, chipName, sensName, dummyChip); + + xchip = (static_cast<TGeoBBox*>(chipVol->GetShape()))->GetDX(); + zchip = (static_cast<TGeoBBox*>(chipVol->GetShape()))->GetDZ(); + + mIBModuleZLength = 2 * zchip * sIBChipsPerRow + (sIBChipsPerRow - 1) * sIBChipZGap; + + // Then create the Glue, the Kapton and the two Aluminum cables + xtot = xchip + (sIBFPCWiderXPlus + sIBFPCWiderXNeg) / 2; + ztot = mIBModuleZLength / 2; + + TGeoBBox* glue = new TGeoBBox(xchip, sIBGlueThick / 2, ztot); + TGeoBBox* kapCable = new TGeoBBox(xtot, sIBFlexCableKapThick / 2, ztot); + + TGeoVolume* aluGndCableVol = createIBFPCAlGnd(xtot, ztot); + TGeoVolume* aluAnodeCableVol = createIBFPCAlAnode(xtot, ztot); + + // Finally create the module and populate it with the chips + // (and the FPC Kapton and Aluminum in the most recent IB model) + Double_t ygnd = (static_cast<TGeoBBox*>(aluGndCableVol->GetShape()))->GetDY(); + Double_t yano = (static_cast<TGeoBBox*>(aluAnodeCableVol->GetShape()))->GetDY(); + + ytot = ymod; + if (mStaveModel == Detector::kIBModel4) + ytot += (sIBGlueThick / 2 + ygnd + sIBFlexCableKapThick / 2 + yano + sIBFlexCapacitorYHi / 2); + + TGeoBBox* module = new TGeoBBox(xtot, ytot, ztot); + + // Now the volumes + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE_IBFPC$"); + + snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + TGeoVolume* modVol = new TGeoVolume(volumeName, module, medAir); + + TGeoVolume* glueVol = new TGeoVolume("FPCGlue", glue, medGlue); + glueVol->SetLineColor(kBlack); + glueVol->SetFillColor(kBlack); + + TGeoVolume* kapCableVol = new TGeoVolume("FPCKapton", kapCable, medKapton); + kapCableVol->SetLineColor(kBlue); + kapCableVol->SetFillColor(kBlue); + + // Build up the module + // Chips are rotated by 180deg around Y axis + // in order to have the correct X and Z axis orientation + xpos = -xtot + (static_cast<TGeoBBox*>(chipVol->GetShape()))->GetDX() + sIBFPCWiderXNeg; + ypos = -ytot + ymod; // = 0 if not kIBModel4 + for (Int_t j = 0; j < sIBChipsPerRow; j++) { + zpos = ztot - j * (2 * zchip + sIBChipZGap) - zchip; + modVol->AddNode(chipVol, j, new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 0, 180, 180))); + mHierarchy[kChip]++; + } + + if (mStaveModel == Detector::kIBModel4) { + ypos += (ymod + glue->GetDY()); + if (mBuildLevel < 2) // Glue + modVol->AddNode(glueVol, 1, new TGeoTranslation(xpos, ypos, 0)); + ypos += glue->GetDY(); + + if (mBuildLevel < 4) { // Kapton + ypos += ygnd; + modVol->AddNode(aluGndCableVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (ygnd + kapCable->GetDY()); + modVol->AddNode(kapCableVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (kapCable->GetDY() + yano); + modVol->AddNode(aluAnodeCableVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += yano; + } + } + + // Add the capacitors + createIBCapacitors(modVol, zchip, ypos); + + // Done, return the module + return modVol; +} + +void V3Layer::createIBCapacitors(TGeoVolume* modvol, Double_t zchip, Double_t yzero, const TGeoManager* mgr) +{ + // + // Adds the capacitors to the IB FPC + // + // Created: 13 Feb 2018 Mario Sitta + // Updated: 03 Apr 2019 Mario Sitta Fix positions (180' rotation) + // + + // Position of the various capacitors (A.Junique private communication + // where: X_capacitor = Z_module , Y_capacitor = X_module) + // Capacitors (different groups) + const Double_t xGroup1A = 4265.9 * sMicron; + const Double_t zGroup1A[2] = {-7142.9 * sMicron, 7594.1 * sMicron}; + const Double_t xGroup1B = 690.9 * sMicron; + const Double_t zGroup1B = -7142.9 * sMicron; + const Double_t xGroup2 = 6300.0 * sMicron; + const Double_t zGroup2 = 15075.0 * sMicron; + const Double_t xGroup3 = 5575.0 * sMicron; + const Double_t zGroup3 = 131900.0 * sMicron; + const Double_t xGroup4[2] = {5600.0 * sMicron, 5575.0 * sMicron}; + const Double_t zGroup4[sIBChipsPerRow] = {275.0 * sMicron, 250.0 * sMicron, 275.0 * sMicron, + 250.0 * sMicron, 250.0 * sMicron, 300.0 * sMicron, + 250.0 * sMicron, 300.0 * sMicron, 250.0 * sMicron}; + const Int_t nGroup5A = 5, nGroup5B = 4; + const Double_t xGroup5A[2] = {1400.0 * sMicron, 1350.0 * sMicron}; + const Double_t zGroup5A[nGroup5A] = {-112957.5 * sMicron, -82854.5 * sMicron, 7595.5 * sMicron, 37745.5 * sMicron, + 128194.1 * sMicron}; + const Double_t xGroup5B = 1100.0 * sMicron; + const Double_t zGroup5B[nGroup5B] = {-51525.0 * sMicron, -21375.0 * sMicron, 69075.0 * sMicron, 99225.0 * sMicron}; + // Resistors + const Int_t nResist = 2; + const Double_t xResist = -7975.0 * sMicron; + const Double_t zResist[nResist] = {114403.0 * sMicron, 119222.0 * sMicron}; + + Double_t xpos, ypos, zpos; + Int_t nCapacitors; + + TGeoVolume *capacitor, *resistor; + + // Check whether we already have the volume, otherwise create it + // (so as to avoid creating multiple copies of the very same volume + // for each layer) + capacitor = mgr->GetVolume("IBFPCCapacitor"); + + if (!capacitor) { + TGeoBBox* capsh = new TGeoBBox(sIBFlexCapacitorXWid / 2, sIBFlexCapacitorYHi / 2, sIBFlexCapacitorZLen / 2); + + TGeoMedium* medCeramic = mgr->GetMedium("IT4_CERAMIC$"); + + capacitor = new TGeoVolume("IBFPCCapacitor", capsh, medCeramic); + capacitor->SetLineColor(kBlack); + capacitor->SetFillColor(kBlack); + + TGeoBBox* ressh = new TGeoBBox(sIBFlexCapacitorXWid / 2, // Resistors have + sIBFlexCapacitorYHi / 2, // the same dim's + sIBFlexCapacitorZLen / 2); // as capacitors + + resistor = new TGeoVolume("IBFPCResistor", ressh, medCeramic); + resistor->SetLineColor(kBlack); + resistor->SetFillColor(kBlack); + } else { // Volumes already defined, get them + resistor = mgr->GetVolume("IBFPCResistor"); + } + + // Place all the capacitors (they are really a lot...) + ypos = yzero + sIBFlexCapacitorYHi / 2; + + xpos = xGroup1A; + for (Int_t j = 0; j < sIBChipsPerRow; j++) { + zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup1A[0]; + modvol->AddNode(capacitor, 2 * j + 1, new TGeoTranslation(-xpos, ypos, -zpos)); + zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup1A[1]; + modvol->AddNode(capacitor, 2 * j + 2, new TGeoTranslation(-xpos, ypos, -zpos)); + } + + nCapacitors = 2 * sIBChipsPerRow; + xpos = xGroup1B; + for (Int_t j = 0; j < sIBChipsPerRow; j++) { + zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup1B; + modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); + } + + nCapacitors += sIBChipsPerRow; + xpos = xGroup2; + // We have only 8 in these group, missing the central one + for (Int_t j = 0; j < sIBChipsPerRow - 1; j++) { + zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup2; + modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); + } + + nCapacitors += (sIBChipsPerRow - 1); + xpos = xGroup3; + zpos = zGroup3; + modvol->AddNode(capacitor, 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); + + nCapacitors++; + for (Int_t j = 0; j < sIBChipsPerRow; j++) { + if (j == (sIBChipsPerRow - 1)) + xpos = xGroup4[1]; + else + xpos = xGroup4[0]; + zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup4[j]; + modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); + } + + nCapacitors += sIBChipsPerRow; + for (Int_t j = 0; j < nGroup5A; j++) { + if (j == 0) + xpos = xGroup5A[0]; + else + xpos = xGroup5A[1]; + zpos = zGroup5A[j]; + modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); + } + + nCapacitors += nGroup5A; + xpos = xGroup5B; + for (Int_t j = 0; j < nGroup5B; j++) { + zpos = zGroup5B[j]; + modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); + } + + // Place the resistors + xpos = xResist; + for (Int_t j = 0; j < nResist; j++) { + zpos = zResist[j]; + modvol->AddNode(resistor, j + 1, new TGeoTranslation(-xpos, ypos, -zpos)); + } +} + +TGeoVolume* V3Layer::createIBFPCAlGnd(const Double_t xcable, const Double_t zcable, const TGeoManager* mgr) +{ + // + // Create the IB FPC Aluminum Ground cable + // + // Created: 20 Oct 2017 Mario Sitta + // + + Double_t ytot, ypos; + + // First create all needed shapes + ytot = sIBFlexCablePolyThick + sIBFlexCableAlThick; + TGeoBBox* coverlay = new TGeoBBox(xcable, ytot / 2, zcable); + TGeoBBox* aluminum = new TGeoBBox(xcable, sIBFlexCableAlThick / 2, zcable); + + // Then the volumes + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + + TGeoVolume* coverlayVol = new TGeoVolume("FPCCoverlayGround", coverlay, medKapton); + coverlayVol->SetLineColor(kBlue); + coverlayVol->SetFillColor(kBlue); + + TGeoVolume* aluminumVol = new TGeoVolume("FPCAluminumGround", aluminum, medAluminum); + aluminumVol->SetLineColor(kCyan); + aluminumVol->SetFillColor(kCyan); + + ypos = coverlay->GetDY() - aluminum->GetDY(); + if (mBuildLevel < 1) // Aluminum + coverlayVol->AddNode(aluminumVol, 1, new TGeoTranslation(0, ypos, 0)); + + return coverlayVol; +} + +TGeoVolume* V3Layer::createIBFPCAlAnode(const Double_t xcable, const Double_t zcable, const TGeoManager* mgr) +{ + // + // Create the IB FPC Aluminum Anode cable + // + // + // Created: 20 Oct 2017 Mario Sitta + // Updated: 03 Apr 2019 Mario Sitta Fix Al position (180' rotation) + // + + Double_t ytot, ypos; + Double_t xtru[4], ytru[4]; + + // First create all needed shapes + ytot = sIBFlexCablePolyThick + sIBFlexCableAlThick; + TGeoBBox* coverlay = new TGeoBBox(xcable, ytot / 2, zcable); + + // A trapezoid + xtru[0] = -sIBFPCAlAnodeWidth2 / 2; + ytru[0] = -zcable; + xtru[1] = sIBFPCAlAnodeWidth2 / 2; + ytru[1] = ytru[0]; + xtru[2] = xtru[0] + sIBFPCAlAnodeWidth1; + ytru[2] = zcable; + xtru[3] = xtru[0]; + ytru[3] = ytru[2]; + + TGeoXtru* aluminum = new TGeoXtru(2); + aluminum->DefinePolygon(4, xtru, ytru); + aluminum->DefineSection(0, -sIBFlexCableAlThick / 2); + aluminum->DefineSection(1, sIBFlexCableAlThick / 2); + + // Then the volumes + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + + TGeoVolume* coverlayVol = new TGeoVolume("FPCCoverlayAnode", coverlay, medKapton); + coverlayVol->SetLineColor(kBlue); + coverlayVol->SetFillColor(kBlue); + + TGeoVolume* aluminumVol = new TGeoVolume("FPCAluminumAnode", aluminum, medAluminum); + aluminumVol->SetLineColor(kCyan); + aluminumVol->SetFillColor(kCyan); + + ypos = -coverlay->GetDY() + aluminum->GetZ(1); + if (mBuildLevel < 1) // Aluminum + coverlayVol->AddNode(aluminumVol, 1, new TGeoCombiTrans(0, ypos, 0, new TGeoRotation("", 0, -90, 0))); + + return coverlayVol; +} + +TGeoVolume* V3Layer::createStaveStructInnerB(const TGeoManager* mgr) +{ + // + // Create the mechanical stave structure + // + // Created: 22 Mar 2013 Chinorat Kobdaj + // Updated: 26 Apr 2013 Mario Sitta + // Updated: 04 Apr 2017 Mario Sitta O2 version - All models obsolete except last one + // Updated: 25 Jan 2018 Mario Sitta Stave width is now a constant + // + + TGeoVolume* mechStavVol = nullptr; + + switch (mStaveModel) { + case Detector::kIBModelDummy: + mechStavVol = createStaveModelInnerBDummy(mgr); + break; + case Detector::kIBModel0: + case Detector::kIBModel1: + case Detector::kIBModel21: + case Detector::kIBModel22: + case Detector::kIBModel3: + LOG(FATAL) << "Stave model " << mStaveModel << " obsolete and no longer supported"; + break; + case Detector::kIBModel4: + mechStavVol = createStaveModelInnerB4(mgr); + break; + default: + LOG(FATAL) << "Unknown stave model " << mStaveModel; + break; + } + return mechStavVol; +} + +TGeoVolume* V3Layer::createStaveModelInnerBDummy(const TGeoManager*) const +{ + // + // Create dummy stave + // + // Created: 22 Mar 2013 Chinorat Kobdaj + // Updated: 26 Apr 2013 Mario Sitta + // Updated: 04 Apr 2017 Mario Sitta O2 version + // + + // Done, return the stave structur + return nullptr; +} + +// model4 +//________________________________________________________________________ +TGeoVolume* V3Layer::createStaveModelInnerB4(const TGeoManager* mgr) +{ + // + // Create the mechanical stave structure for Model 4 of TDR + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 04 Dec 2014 Mario Sitta + // Updated: 03 Mar 2015 Mario Sitta FPC in right position (beyond chip) + // Updated: 06 Mar 2015 Mario Sitta Space Frame corrected (C.G. data) + // Updated: 30 Apr 2015 Mario Sitta End-stave connectors added + // Updated: 04 Apr 2017 Mario Sitta O2 version + // Updated: 25 Jan 2018 Mario Sitta Stave width is now a constant + // Updated: 03 Feb 2018 Mario Sitta To last drawings (ALIITSUP0051) + // + + // Local parameters + const Double_t xstave = sIBColdPlateWidth / 2; + + Double_t layerHeight = 0.; + + Double_t rPipeMin = sIBCoolPipeInnerD / 2; + Double_t rPipeMax = rPipeMin + sIBCoolPipeThick; + + const Int_t nv = 16; + Double_t xv[nv], yv[nv]; // The stave container Xtru + Double_t xlen, ylen, zlen, ztot; + Double_t xpos, ypos, zpos, ylay, yposPipe; + Double_t beta, gamma, theta; + + // First create all needed shapes + ztot = sIBColdPlateZLen / 2; + + TGeoBBox* glue = new TGeoBBox(xstave, sIBGlueThick / 2, ztot); + + TGeoBBox* fleecbot = new TGeoBBox(xstave, sIBCarbonFleeceThick / 2, ztot); + + TGeoBBox* cfplate = new TGeoBBox(xstave, sIBK13D2UThick / 2, ztot); + + TGeoTube* pipe = new TGeoTube(rPipeMin, rPipeMax, sIBCoolPipeZLen / 2); + + TGeoTube* water = new TGeoTube(0., rPipeMin, sIBCoolPipeZLen / 2); + + TGeoTubeSeg* cpaptub = new TGeoTubeSeg(rPipeMax, rPipeMax + sIBCarbonPaperThick, sIBCarbonPaperZLen / 2, 0, 180); + + TGeoBBox* cpapvert = new TGeoBBox(sIBCarbonPaperThick / 2, pipe->GetRmax() / 2, sIBCarbonPaperZLen / 2); + + xlen = sIBCoolPipeXDist / 2 - pipe->GetRmax() - sIBCarbonPaperThick; + TGeoBBox* cpapmid = new TGeoBBox(xlen, sIBCarbonPaperThick / 2, sIBCarbonPaperZLen / 2); + + xlen = sIBCarbonPaperWidth / 2 - sIBCoolPipeXDist / 2 - pipe->GetRmax() - sIBCarbonPaperThick; + TGeoBBox* cpaplr = new TGeoBBox(xlen / 2, sIBCarbonPaperThick / 2, sIBCarbonPaperZLen / 2); + + TGeoTubeSeg* fleecpipe = new TGeoTubeSeg(cpaptub->GetRmax(), cpaptub->GetRmax() + sIBCarbonFleeceThick, ztot, 0, 180); + + TGeoBBox* fleecvert = new TGeoBBox(sIBCarbonFleeceThick / 2, (pipe->GetRmax() - sIBCarbonPaperThick) / 2, ztot); + + xlen = sIBCoolPipeXDist / 2 - pipe->GetRmax() - sIBCarbonPaperThick - sIBCarbonFleeceThick; + TGeoBBox* fleecmid = new TGeoBBox(xlen, sIBCarbonFleeceThick / 2, ztot); + + xlen = xstave - sIBCoolPipeXDist / 2 - pipe->GetRmax() - sIBCarbonPaperThick - sIBCarbonFleeceThick; + TGeoBBox* fleeclr = new TGeoBBox(xlen / 2, sIBCarbonFleeceThick / 2, ztot); + + // The total height of the layer can now be computed + layerHeight = 2 * (glue->GetDY() + fleecbot->GetDY() + cfplate->GetDY() + cpaplr->GetDY() + fleeclr->GetDY()); + + // The spaceframe structure + TGeoTrd1* topv = new TGeoTrd1(sIBTopVertexWidth1 / 2, sIBTopVertexWidth2 / 2, ztot, sIBTopVertexHeight / 2); + + xv[0] = 0; + yv[0] = 0; + xv[1] = sIBSideVertexWidth; + yv[1] = yv[0]; + xv[2] = xv[0]; + yv[2] = sIBSideVertexHeight; + + TGeoXtru* sidev = new TGeoXtru(2); + sidev->DefinePolygon(3, xv, yv); + sidev->DefineSection(0, -ztot); + sidev->DefineSection(1, ztot); + + xv[0] = sIBEndSupportXUp / 2; + yv[0] = sIBStaveHeight - sIBEndSupportThick; + xv[1] = xstave - sIBSideVertexWidth; + yv[1] = layerHeight + sIBSideVertexHeight; + xv[2] = xstave; + yv[2] = layerHeight; + xv[3] = xv[2]; + yv[3] = 0; + xv[4] = xstave + sIBEndSupportThick; + yv[4] = yv[3]; + xv[5] = xv[4]; + yv[5] = yv[2]; + xv[6] = xv[1] + sIBEndSupportThick * sinD(sIBEndSupportOpenPhi / 2); + yv[6] = yv[1] + sIBEndSupportThick * cosD(sIBEndSupportOpenPhi / 2); + xv[7] = xv[0]; + yv[7] = sIBStaveHeight; + for (Int_t i = 0; i < nv / 2; i++) { + xv[8 + i] = -xv[7 - i]; + yv[8 + i] = yv[7 - i]; + } + + TGeoXtru* endsupp = new TGeoXtru(2); + endsupp->DefinePolygon(16, xv, yv); + endsupp->DefineSection(0, -sIBEndSupportZLen / 2); + endsupp->DefineSection(1, sIBEndSupportZLen / 2); + + xlen = TMath::Sqrt((yv[7] - yv[6]) * (yv[7] - yv[6]) + (xv[7] - xv[6]) * (xv[7] - xv[6]) + + sIBTopFilamentInterZ * sIBTopFilamentInterZ / 4); + theta = TMath::ATan((yv[7] - yv[6]) / (xv[7] - xv[6])) * TMath::RadToDeg(); + TGeoBBox* topfil = new TGeoBBox(xlen / 2, sIBTopFilamentSide / 2, sIBTopFilamentSide / 2); + + // The half stave container (an XTru to avoid overlaps between neighbours) + xv[0] = xstave + sIBTopFilamentSide; + yv[0] = 0; + xv[1] = xv[0]; + yv[1] = layerHeight + sIBSideVertexHeight + topfil->GetDZ(); + ; + xv[2] = sIBEndSupportXUp / 2; + yv[2] = sIBStaveHeight + sIBTopFilamentSide / sinD(-theta); // theta is neg + for (Int_t i = 0; i < 3; i++) { + xv[3 + i] = -xv[2 - i]; + yv[3 + i] = yv[2 - i]; + } + + TGeoXtru* mechStruct = new TGeoXtru(2); + mechStruct->DefinePolygon(6, xv, yv); + mechStruct->SetName("mechStruct"); + mechStruct->DefineSection(0, -ztot); + mechStruct->DefineSection(1, ztot); + + // The connectors' containers + zlen = sIBConnectBlockZLen - sIBConnTailZLen + sIBConnectAFitZOut; + TGeoBBox* connAside = new TGeoBBox("connAsideIB", sIBConnectorXWidth / 2, sIBConnBodyYHeight / 2, zlen / 2); + + zlen = sIBConnectBlockZLen - sIBConnTailZLen; + TGeoBBox* connCside = new TGeoBBox("connCsideIB", sIBConnectorXWidth / 2, sIBConnBodyYHeight / 2, zlen / 2); + + // The StaveStruct container, a Composite Shape + yposPipe = 2 * glue->GetDY() + 2 * fleecbot->GetDY() + 2 * cfplate->GetDY() + pipe->GetRmax(); + ypos = connAside->GetDY() - sIBConnTubesYPos + yposPipe; + zpos = ztot + connAside->GetDZ(); + TGeoTranslation* transAside = new TGeoTranslation("transAsideIB", 0, ypos, zpos); + transAside->RegisterYourself(); + + ypos = connCside->GetDY() - sIBConnTubesYPos + yposPipe; + zpos = ztot + connCside->GetDZ(); + TGeoTranslation* transCside = new TGeoTranslation("transCsideIB", 0, ypos, -zpos); + transCside->RegisterYourself(); + + TGeoCompositeShape* mechStavSh = + new TGeoCompositeShape("mechStruct+connAsideIB:transAsideIB+connCsideIB:transCsideIB"); + + // We have all shapes: now create the real volumes + + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medM55J6K = mgr->GetMedium("IT4_M55J6K$"); + TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); + TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + + const Int_t nameLen = 30; + char volname[nameLen]; + snprintf(volname, nameLen, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); + TGeoVolume* mechStavVol = new TGeoVolume(volname, mechStavSh, medAir); + mechStavVol->SetLineColor(12); + mechStavVol->SetFillColor(12); + mechStavVol->SetVisibility(kFALSE); + + TGeoVolume* glueVol = new TGeoVolume("Glue", glue, medGlue); + glueVol->SetLineColor(kBlack); + glueVol->SetFillColor(kBlack); + + TGeoVolume* fleecbotVol = new TGeoVolume("CarbonFleeceBottom", fleecbot, medCarbonFleece); + fleecbotVol->SetFillColor(kViolet); + fleecbotVol->SetLineColor(kViolet); + + TGeoVolume* cfplateVol = new TGeoVolume("CFPlate", cfplate, medK13D2U2k); + cfplateVol->SetFillColor(5); // Yellow + cfplateVol->SetLineColor(5); + + TGeoVolume* pipeVol = new TGeoVolume("PolyimidePipe", pipe, medKapton); + pipeVol->SetFillColor(35); // Blue shade + pipeVol->SetLineColor(35); + + TGeoVolume* waterVol = new TGeoVolume("Water", water, medWater); + waterVol->SetFillColor(4); // Bright blue + waterVol->SetLineColor(4); + + TGeoVolume* cpaptubVol = new TGeoVolume("ThermasolPipeCover", cpaptub, medFGS003); + cpaptubVol->SetFillColor(2); // Red + cpaptubVol->SetLineColor(2); + + TGeoVolume* cpapvertVol = new TGeoVolume("ThermasolVertical", cpapvert, medFGS003); + cpapvertVol->SetFillColor(2); // Red + cpapvertVol->SetLineColor(2); + + TGeoVolume* cpapmidVol = new TGeoVolume("ThermasolMiddle", cpapmid, medFGS003); + cpapmidVol->SetFillColor(2); // Red + cpapmidVol->SetLineColor(2); + + TGeoVolume* cpaplrVol = new TGeoVolume("ThermasolLeftRight", cpaplr, medFGS003); + cpaplrVol->SetFillColor(2); // Red + cpaplrVol->SetLineColor(2); + + TGeoVolume* fleecpipeVol = new TGeoVolume("CarbonFleecePipeCover", fleecpipe, medCarbonFleece); + fleecpipeVol->SetFillColor(28); // Brown shade + fleecpipeVol->SetLineColor(28); + + TGeoVolume* fleecvertVol = new TGeoVolume("CarbonFleeceVertical", fleecvert, medCarbonFleece); + fleecvertVol->SetFillColor(28); // Brown shade + fleecvertVol->SetLineColor(28); + + TGeoVolume* fleecmidVol = new TGeoVolume("CarbonFleeceMiddle", fleecmid, medCarbonFleece); + fleecmidVol->SetFillColor(28); // Brown shade + fleecmidVol->SetLineColor(28); + + TGeoVolume* fleeclrVol = new TGeoVolume("CarbonFleeceLeftRight", fleeclr, medCarbonFleece); + fleeclrVol->SetFillColor(28); // Brown shade + fleeclrVol->SetLineColor(28); + + TGeoVolume* topvVol = new TGeoVolume("TopVertex", topv, medM55J6K); + topvVol->SetFillColor(12); // Gray shade + topvVol->SetLineColor(12); + + TGeoVolume* sidevVol = new TGeoVolume("SideVertex", sidev, medM55J6K); + sidevVol->SetFillColor(12); // Gray shade + sidevVol->SetLineColor(12); + + TGeoVolume* topfilVol = new TGeoVolume("TopFilament", topfil, medM60J3K); + topfilVol->SetFillColor(12); // Gray shade + topfilVol->SetLineColor(12); + + TGeoVolume* endsuppVol = new TGeoVolume("EndSupport", endsupp, medM55J6K); + endsuppVol->SetFillColor(12); // Gray shade + endsuppVol->SetLineColor(12); + + // Now build up the half stave + ypos = glue->GetDY(); + if (mBuildLevel < 2) // Glue + mechStavVol->AddNode(glueVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (glue->GetDY() + fleecbot->GetDY()); + if (mBuildLevel < 5) // Carbon + mechStavVol->AddNode(fleecbotVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (fleecbot->GetDY() + cfplate->GetDY()); + if (mBuildLevel < 5) // Carbon + mechStavVol->AddNode(cfplateVol, 1, new TGeoTranslation(0, ypos, 0)); + + ylay = ypos + cfplate->GetDY(); // The level where tubes etc. lay + + xpos = sIBCoolPipeXDist / 2; + ypos = ylay + pipe->GetRmax(); + yposPipe = ypos; // Save for later use + if (mBuildLevel < 4) { // Kapton + mechStavVol->AddNode(pipeVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(pipeVol, 2, new TGeoTranslation(xpos, ypos, 0)); + } + + if (mBuildLevel < 3) { // Water + mechStavVol->AddNode(waterVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(waterVol, 2, new TGeoTranslation(xpos, ypos, 0)); + } + + if (mBuildLevel < 5) { // Carbon (stave components) + mechStavVol->AddNode(cpaptubVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(cpaptubVol, 2, new TGeoTranslation(xpos, ypos, 0)); + + mechStavVol->AddNode(fleecpipeVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(fleecpipeVol, 2, new TGeoTranslation(xpos, ypos, 0)); + + xpos = sIBCoolPipeXDist / 2 - pipe->GetRmax() - cpapvert->GetDX(); + ypos = ylay + cpapvert->GetDY(); + mechStavVol->AddNode(cpapvertVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(cpapvertVol, 2, new TGeoTranslation(xpos, ypos, 0)); + + xpos = sIBCoolPipeXDist / 2 + pipe->GetRmax() + cpapvert->GetDX(); + mechStavVol->AddNode(cpapvertVol, 3, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(cpapvertVol, 4, new TGeoTranslation(xpos, ypos, 0)); + + ypos = ylay + sIBCarbonPaperThick / 2; + mechStavVol->AddNode(cpapmidVol, 1, new TGeoTranslation(0, ypos, 0)); + + xpos = xstave - cpaplr->GetDX(); + mechStavVol->AddNode(cpaplrVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(cpaplrVol, 2, new TGeoTranslation(xpos, ypos, 0)); + + xpos = sIBCoolPipeXDist / 2 - pipe->GetRmax() - 2 * cpapvert->GetDX() - fleecvert->GetDX(); + ypos = ylay + sIBCarbonPaperThick + fleecvert->GetDY(); + mechStavVol->AddNode(fleecvertVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(fleecvertVol, 2, new TGeoTranslation(xpos, ypos, 0)); + + xpos = sIBCoolPipeXDist / 2 + pipe->GetRmax() + 2 * cpapvert->GetDX() + fleecvert->GetDX(); + mechStavVol->AddNode(fleecvertVol, 3, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(fleecvertVol, 4, new TGeoTranslation(xpos, ypos, 0)); + + ypos = ylay + sIBCarbonPaperThick + sIBCarbonFleeceThick / 2; + mechStavVol->AddNode(fleecmidVol, 1, new TGeoTranslation(0, ypos, 0)); + + xpos = xstave - fleeclr->GetDX(); + mechStavVol->AddNode(fleeclrVol, 1, new TGeoTranslation(-xpos, ypos, 0)); + mechStavVol->AddNode(fleeclrVol, 2, new TGeoTranslation(xpos, ypos, 0)); + } + + ylay += (sIBCarbonPaperThick + sIBCarbonFleeceThick); + + if (mBuildLevel < 5) { // Carbon (spaceframe) + ypos = sIBStaveHeight - sIBEndSupportThick - topv->GetDz(); // Due to rotation, z is on Y + mechStavVol->AddNode(topvVol, 1, new TGeoCombiTrans(0, ypos, 0, new TGeoRotation("", 0, -90, 0))); + + xpos = xstave - sidev->GetX(1); + ypos = ylay; + mechStavVol->AddNode(sidevVol, 1, new TGeoTranslation(xpos, ypos, 0)); + mechStavVol->AddNode(sidevVol, 2, new TGeoCombiTrans(-xpos, ypos, 0, new TGeoRotation("", 90, 180, -90))); + + zpos = ztot - endsupp->GetZ(1); + mechStavVol->AddNode(endsuppVol, 1, new TGeoTranslation(0, 0, zpos)); + mechStavVol->AddNode(endsuppVol, 2, new TGeoTranslation(0, 0, -zpos)); + + gamma = 180. - sIBTopFilamentAlpha; + xpos = xstave / 2 + topfil->GetDZ(); + ypos = (endsupp->GetY(7) + endsupp->GetY(6)) / 2; + Int_t nFilamentGroups = (Int_t)(2 * (ztot - sIBEndSupportZLen) / sIBTopFilamentInterZ); + // theta was computed when filament volume was created + for (int i = 0; i < nFilamentGroups; i++) { // i<19 + // 1) Front Left Top Filament + zpos = -(ztot - sIBEndSupportZLen) + i * sIBTopFilamentInterZ + sIBTopFilamentInterZ / 4; + mechStavVol->AddNode(topfilVol, i * 4 + 1, + new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 90 + theta, gamma / 2, -90))); + // 2) Front Right Top Filament + mechStavVol->AddNode(topfilVol, i * 4 + 2, + new TGeoCombiTrans(-xpos, ypos, zpos, new TGeoRotation("", 90 - theta, -gamma / 2, -90))); + // 3) Back Left Top Filament + zpos += sIBTopFilamentInterZ / 2; + mechStavVol->AddNode(topfilVol, i * 4 + 3, + new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 90 + theta, -gamma / 2, -90))); + // 4) Back Right Top Filament + mechStavVol->AddNode(topfilVol, i * 4 + 4, + new TGeoCombiTrans(-xpos, ypos, zpos, new TGeoRotation("", 90 - theta, gamma / 2, -90))); + } + } + + // Add the end-stave connectors + TGeoVolume *connectorASide, *connectorCSide; + + // Check whether we have already all pieces + // Otherwise create them + connectorASide = mgr->GetVolume("IBConnectorASide"); + + if (!connectorASide) { + createIBConnectors(mgr); + connectorASide = mgr->GetVolume("IBConnectorASide"); + } + connectorCSide = mgr->GetVolume("IBConnectorCSide"); + + ypos = (static_cast<TGeoBBox*>(connectorASide->GetShape()))->GetDY() - sIBConnTubesYPos + + yposPipe; // We center the pipe and hole axes + zpos = ztot + (sIBConnectBlockZLen - sIBConnTailZLen + sIBConnectAFitZOut) / 2; + mechStavVol->AddNode(connectorASide, 1, new TGeoTranslation(0, ypos, zpos)); + + zpos = ztot + (sIBConnectBlockZLen - sIBConnTailZLen) / 2; + mechStavVol->AddNode(connectorCSide, 1, new TGeoCombiTrans(0, ypos, -zpos, new TGeoRotation("", 90, 180, -90))); + + // Done, return the stave structure + return mechStavVol; +} + +void V3Layer::createIBConnectors(const TGeoManager* mgr) +{ + // + // Create the end-stave connectors for IB staves + // (simply call the actual creator methods) + // + // Created: 20 Apr 2015 Mario Sitta + // + + createIBConnectorsASide(mgr); + createIBConnectorsCSide(mgr); +} + +void V3Layer::createIBConnectorsASide(const TGeoManager* mgr) +{ + // + // Create the A-Side end-stave connectors for IB staves + // + // Created: 22 Apr 2015 Mario Sitta + // Updated: 04 Apr 2017 Mario Sitta O2 version + // Updated: 28 Jan 2018 Mario Sitta To last drawings (ALIITSUP0051) + // Updated: 19 Jun 2019 Mario Sitta Avoid fake overlaps with EndWheels + // + + // Local variables + const Int_t nv = 8; + Double_t xv[nv], yv[nv]; + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + + // Gather all material pointers + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + TGeoMedium* medInox304 = mgr->GetMedium("IT4_INOX304$"); + + // First create all elements + // (All measures refer to the blueprint ALIITSUP0051) + + // The connector block, two Composite Shapes: + // the body... + xlen = sIBConnectorXWidth; + ylen = sIBConnBodyYHeight; + zlen = sIBConnectBlockZLen - sIBConnTailZLen; + TGeoBBox* connBody = new TGeoBBox("connBodyA", xlen / 2, ylen / 2, zlen / 2); + + TGeoTube* connRoundHole = new TGeoTube("connRoundHoleA", 0., sIBConnRoundHoleD / 2, sIBConnBodyYHeight / 1.5); + + zpos = -connBody->GetDZ() + sIBConnRoundHoleZ; + TGeoCombiTrans* connRoundHoleTrans = + new TGeoCombiTrans("roundHoleTransA", 0, 0, zpos, new TGeoRotation("", 0, 90, 0)); + connRoundHoleTrans->RegisterYourself(); + + xlen = sIBConnSquareHoleX / 2; + ylen = sIBConnBodyYHeight / 1.5; + zlen = sIBConnSquareHoleZ / 2; + TGeoBBox* connSquareHole = new TGeoBBox("connSquareHoleA", xlen, ylen, zlen); + + zpos = -connBody->GetDZ() + sIBConnSquareHoleZPos; + TGeoTranslation* connSquareHoleTrans = new TGeoTranslation("squareHoleTransA", 0, 0, zpos); + connSquareHoleTrans->RegisterYourself(); + + TGeoTube* connTubeHole2 = new TGeoTube("tube2HoleA", 0, sIBConnTubeHole2D / 2, connBody->GetDZ()); + + xpos = sIBConnTubesXDist / 2; + ypos = -connBody->GetDY() + sIBConnTubesYPos; + + TGeoTranslation* connTubes2Trans1 = new TGeoTranslation("tubes2Trans1A", -xpos, ypos, 0); + connTubes2Trans1->RegisterYourself(); + + TGeoTranslation* connTubes2Trans2 = new TGeoTranslation("tubes2Trans2A", xpos, ypos, 0); + connTubes2Trans2->RegisterYourself(); + + zlen = sIBConnTubeHole1ZLen - sIBConnTailZLen; + TGeoTube* connTubeHole3 = new TGeoTube("tube3HoleA", 0, sIBConnTubeHole1D / 2, zlen); + + zpos = connBody->GetDZ(); + TGeoTranslation* connTubes3Trans1 = new TGeoTranslation("tubes3Trans1A", -xpos, ypos, -zpos); + connTubes3Trans1->RegisterYourself(); + TGeoTranslation* connTubes3Trans2 = new TGeoTranslation("tubes3Trans2A", xpos, ypos, -zpos); + connTubes3Trans2->RegisterYourself(); + + zlen = sIBConnTubeHole1ZLen2; + TGeoTube* connFitHole = new TGeoTube("fitHoleA", 0, sIBConnectAFitExtD / 2, zlen); + + TGeoTranslation* connFitHoleTrans1 = new TGeoTranslation("fitTrans1A", -xpos, ypos, zpos); + connFitHoleTrans1->RegisterYourself(); + TGeoTranslation* connFitHoleTrans2 = new TGeoTranslation("fitTrans2A", xpos, ypos, zpos); + connFitHoleTrans2->RegisterYourself(); + + zlen = sIBConnSideHole1XWid / 1.5; + TGeoTube* sideHole1 = new TGeoTube("sideHole1A", 0, sIBConnSideHole1D / 2, zlen); + + xpos = connBody->GetDX() - sIBConnSideHole1XWid + sideHole1->GetDz(); + ypos = connBody->GetDY() - sIBConnSideHole1YPos; + zpos = -connBody->GetDZ() + (sIBConnSideHole1ZPos - sIBConnTailZLen); + TGeoCombiTrans* connSideHole1Trans = + new TGeoCombiTrans("sideHole1TransA", xpos, ypos, zpos, new TGeoRotation("", 90, 90, 0)); + connSideHole1Trans->RegisterYourself(); + + TGeoBBox* sideHole2Box = + new TGeoBBox("sideHole2AB", sIBConnSideHole2XWid, sIBConnSideHole2YWid / 2, sIBConnSideHole2ZWid / 2); + + xpos = -connBody->GetDX(); + ypos = connBody->GetDY() - sIBConnSideHole2YPos; + zpos = -connBody->GetDZ() + (sIBConnSideHole2ZPos - sIBConnTailZLen) + sideHole2Box->GetDZ(); + TGeoTranslation* sideHole2BTrans = new TGeoTranslation("sideHole2TransBA", xpos, ypos, zpos); + sideHole2BTrans->RegisterYourself(); + + TGeoTubeSeg* sideHole2TubeSeg = + new TGeoTubeSeg("sideHole2ATS", 0, sIBConnSideHole2YWid / 2, sIBConnSideHole2XWid, 0, 180); + + zpos = -connBody->GetDZ() + (sIBConnSideHole2ZPos - sIBConnTailZLen); + TGeoCombiTrans* sideHole2TSTrans1 = + new TGeoCombiTrans("sideHole2TSTrans1A", xpos, ypos, zpos, new TGeoRotation("", 90, -90, 0)); + sideHole2TSTrans1->RegisterYourself(); + + zpos = -connBody->GetDZ() + (sIBConnSideHole2ZPos - sIBConnTailZLen) + 2 * sideHole2Box->GetDZ(); + TGeoCombiTrans* sideHole2TSTrans2 = + new TGeoCombiTrans("sideHole2TSTrans2A", xpos, ypos, zpos, new TGeoRotation("", 90, 90, 0)); + sideHole2TSTrans2->RegisterYourself(); + + TGeoCompositeShape* connBodySh = new TGeoCompositeShape( + "connBodyA-connRoundHoleA:roundHoleTransA-connSquareHoleA:squareHoleTransA-tube2HoleA:tubes2Trans1A-tube2HoleA:" + "tubes2Trans2A-fitHoleA:fitTrans1A-fitHoleA:fitTrans2A-tube3HoleA:tubes3Trans1A-tube3HoleA:tubes3Trans2A-" + "sideHole1A:sideHole1TransA-sideHole2AB:sideHole2TransBA-sideHole2ATS:sideHole2TSTrans1A-sideHole2ATS:" + "sideHole2TSTrans2A"); + + TGeoVolume* connBlockBody = new TGeoVolume("IBConnectorBlockBodyASide", connBodySh, medPEEK); + connBlockBody->SetFillColor(42); // Brownish shade + connBlockBody->SetLineColor(42); + + // ...and the tail + xv[0] = sIBConnectorXWidth / 2; + yv[0] = sIBConnTailYShift; + xv[1] = xv[0]; + yv[1] = sIBConnTailYMid; + xv[2] = xv[1] - (sIBConnectorYTot - sIBConnTailYMid) / tanD(90 - sIBConnTailOpenPhi / 2); + yv[2] = sIBConnectorYTot; + + for (Int_t i = 0; i < 3; i++) { + xv[3 + i] = -xv[2 - i]; + yv[3 + i] = yv[2 - i]; + } + + TGeoXtru* connTail = new TGeoXtru(2); + connTail->SetName("connTailA"); + connTail->DefinePolygon(6, xv, yv); + connTail->DefineSection(0, 0); + connTail->DefineSection(1, sIBConnTailZLen); + + TGeoTube* connTubeHole1 = new TGeoTube("tube1HoleA", 0, sIBConnTubeHole1D / 2, sIBConnTubeHole1ZLen / 1.5); + + xpos = sIBConnTubesXDist / 2; + ypos = sIBConnTubesYPos; + zpos = connTail->GetZ(1) / 2; + TGeoTranslation* connTubes1Trans1 = new TGeoTranslation("tubes1Trans1A", -xpos, ypos, zpos); + connTubes1Trans1->RegisterYourself(); + TGeoTranslation* connTubes1Trans2 = new TGeoTranslation("tubes1Trans2A", xpos, ypos, zpos); + connTubes1Trans2->RegisterYourself(); + + TGeoCompositeShape* connTailSh = + new TGeoCompositeShape("connTailA-tube1HoleA:tubes1Trans1A-tube1HoleA:tubes1Trans2A"); + + TGeoVolume* connBlockTail = new TGeoVolume("IBConnectorBlockTailASide", connTailSh, medPEEK); + connBlockTail->SetFillColor(42); // Brownish shade + connBlockTail->SetLineColor(42); + + // The fitting tubes, a Tube + TGeoTube* connFitSh = new TGeoTube(sIBConnectAFitIntD / 2, sIBConnectAFitExtD / 2, sIBConnectAFitZLen / 2); + + TGeoVolume* connFit = new TGeoVolume("IBConnectorFitting", connFitSh, medInox304); + connFit->SetFillColor(kGray); + connFit->SetLineColor(kGray); + + // Now create the container: cannot be a simple box + // to avoid fake overlaps with stave elements + xlen = sIBConnectorXWidth; + ylen = sIBConnBodyYHeight; + zlen = sIBConnectBlockZLen - sIBConnTailZLen + sIBConnectAFitZOut; + + TGeoBBox* connBox = new TGeoBBox("connBoxA", xlen / 2, ylen / 2, zlen / 2); + + ypos = -sIBConnectorYTot / 2 + connBox->GetDY(); + TGeoTranslation* transBodyA = new TGeoTranslation("transBodyA", 0, ypos, 0); + transBodyA->RegisterYourself(); + + ypos = -sIBConnectorYTot / 2; + zpos = -connBox->GetDZ() - connTail->GetZ(1); + TGeoTranslation* transTailA = new TGeoTranslation("transTailA", 0, ypos, zpos); + transTailA->RegisterYourself(); + + TGeoTube* connTubeHollow = new TGeoTube("tubeHollowA", 0, sIBConnTubeHole1D / 2, sIBConnTubeHole1ZLen / 2); + + xpos = sIBConnTubesXDist / 2; + ypos = -sIBConnectorYTot / 2 + sIBConnTubesYPos; + zpos = -connBox->GetDZ() - connTail->GetZ(1) + sIBConnTubeHole1ZLen / 2; + TGeoTranslation* connTubeHollTrans1 = new TGeoTranslation("tubeHollTrans1A", -xpos, ypos, zpos); + connTubeHollTrans1->RegisterYourself(); + TGeoTranslation* connTubeHollTrans2 = new TGeoTranslation("tubeHollTrans2A", xpos, ypos, zpos); + connTubeHollTrans2->RegisterYourself(); + + zpos = -connBox->GetDZ() + connTubeHole2->GetDz() - 2 * connFitHole->GetDz(); + TGeoTranslation* connTubes2Trans1Body = new TGeoTranslation("tubes2Trans1BA", -xpos, ypos, zpos); + connTubes2Trans1Body->RegisterYourself(); + TGeoTranslation* connTubes2Trans2Body = new TGeoTranslation("tubes2Trans2BA", xpos, ypos, zpos); + connTubes2Trans2Body->RegisterYourself(); + + TGeoCompositeShape* connBoxSh = new TGeoCompositeShape( + "connBoxA:transBodyA-tube2HoleA:tubes2Trans1BA-tube2HoleA:tubes2Trans2BA+connTailA:transTailA-tubeHollowA:tubeHollTrans1A-" + "tubeHollowA:tubeHollTrans2A"); + + TGeoVolume* connBoxASide = new TGeoVolume("IBConnectorASide", connBoxSh, medAir); + + // Finally build up the connector + // (NB: the origin is in the connBox, i.e. w/o the tail in Z) + ypos = -sIBConnectorYTot / 2; + zpos = -connBox->GetDZ() - connTail->GetZ(1); + connBoxASide->AddNode(connBlockTail, 1, new TGeoTranslation(0, ypos, zpos)); + + ypos = -sIBConnectorYTot / 2 + connBody->GetDY(); + zpos = -connBox->GetDZ() + connBody->GetDZ(); + connBoxASide->AddNode(connBlockBody, 1, new TGeoTranslation(0, ypos, zpos)); + + xpos = sIBConnTubesXDist / 2; + ypos = -sIBConnectorYTot / 2 + sIBConnTubesYPos; + zpos = connBox->GetDZ() - connFitSh->GetDz(); + connBoxASide->AddNode(connFit, 1, new TGeoTranslation(xpos, ypos, zpos)); + connBoxASide->AddNode(connFit, 2, new TGeoTranslation(-xpos, ypos, zpos)); +} + +void V3Layer::createIBConnectorsCSide(const TGeoManager* mgr) +{ + // + // Create the C-Side end-stave connectors for IB staves + // + // Created: 05 May 2015 Mario Sitta + // Updated: 04 Apr 2017 Mario Sitta O2 version + // Updated: 28 Jan 2018 Mario Sitta To last drawings (ALIITSUP0051) + // Updated: 15 May 2019 Mario Sitta Avoid fake overlaps with EndWheels + // + + // Local variables + const Int_t nv = 8; + Double_t xv[nv], yv[nv]; + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + + // Gather all material pointers + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + + // First create all elements + // (All measures refer to the blueprint ALIITSUP0051) + + // The connector block, two Composite Shapes: + // the body... + xlen = sIBConnectorXWidth; + ylen = sIBConnBodyYHeight; + zlen = sIBConnectBlockZLen - sIBConnTailZLen; + TGeoBBox* connBody = new TGeoBBox("connBodyC", xlen / 2, ylen / 2, zlen / 2); + + TGeoTube* connRoundHole = new TGeoTube("connRoundHoleC", 0., sIBConnRoundHoleD / 2, sIBConnBodyYHeight / 1.5); + + zpos = -connBody->GetDZ() + sIBConnRoundHoleZ; + TGeoCombiTrans* connRoundHoleTrans = + new TGeoCombiTrans("roundHoleTransC", 0, 0, zpos, new TGeoRotation("", 0, 90, 0)); + connRoundHoleTrans->RegisterYourself(); + + TGeoTube* connInsertHole = new TGeoTube("connInsertHoleC", 0, sIBConnInsertHoleD / 2, sIBConnBodyYHeight / 1.5); + + zpos = -connBody->GetDZ() + sIBConnInsertHoleZPos; + TGeoCombiTrans* connInsertHoleTrans = + new TGeoCombiTrans("insertHoleTransC", 0, 0, zpos, new TGeoRotation("", 0, 90, 0)); + connInsertHoleTrans->RegisterYourself(); + + TGeoTube* connTubeHole2 = new TGeoTube("tube2HoleC", 0, sIBConnTubeHole2D / 2, connBody->GetDZ()); + + xpos = sIBConnTubesXDist / 2; + ypos = -connBody->GetDY() + sIBConnTubesYPos; + zpos = sIBConnectBlockZLen - sIBConnTubeHole3ZPos; + TGeoTranslation* connTubes2Trans1 = new TGeoTranslation("tubes2Trans1C", -xpos, ypos, -zpos); + connTubes2Trans1->RegisterYourself(); + TGeoTranslation* connTubes2Trans2 = new TGeoTranslation("tubes2Trans2C", xpos, ypos, -zpos); + connTubes2Trans2->RegisterYourself(); + + zlen = sIBConnectorXWidth; + TGeoTube* connTubeHole3 = new TGeoTube("tube3HoleC", 0, sIBConnTubeHole2D / 2, zlen / 2); + + xpos = sIBConnTubeHole3XPos; + zpos = connBody->GetDZ() - (sIBConnectBlockZLen - sIBConnTubeHole3ZPos); + TGeoCombiTrans* connTubes3Trans = + new TGeoCombiTrans("tubes3TransC", xpos, ypos, zpos, new TGeoRotation("", 90, -90, 90)); + connTubes3Trans->RegisterYourself(); + + zlen = sIBConnTubeHole1ZLen - sIBConnTailZLen; + TGeoTube* connTubeHole4 = new TGeoTube("tube4HoleC", 0, sIBConnTubeHole1D / 2, zlen); + + xpos = sIBConnTubesXDist / 2; + zpos = connBody->GetDZ(); + TGeoTranslation* connTubes4Trans1 = new TGeoTranslation("tubes4Trans1C", -xpos, ypos, -zpos); + connTubes4Trans1->RegisterYourself(); + TGeoTranslation* connTubes4Trans2 = new TGeoTranslation("tubes4Trans2C", xpos, ypos, -zpos); + connTubes4Trans2->RegisterYourself(); + + zlen = sIBConnSideHole1XWid / 1.5; + TGeoTube* sideHole1 = new TGeoTube("sideHole1C", 0, sIBConnSideHole1D / 2, zlen); + + xpos = -connBody->GetDX() + sIBConnSideHole1XWid - sideHole1->GetDz(); + ypos = connBody->GetDY() - sIBConnSideHole1YPos; + zpos = -connBody->GetDZ() + (sIBConnSideHole1ZPos - sIBConnTailZLen); + TGeoCombiTrans* connSideHole1Trans = + new TGeoCombiTrans("sideHole1TransC", xpos, ypos, zpos, new TGeoRotation("", 90, 90, 0)); + connSideHole1Trans->RegisterYourself(); + + TGeoBBox* sideHole2Box = + new TGeoBBox("sideHole2CB", sIBConnSideHole2XWid, sIBConnSideHole2YWid / 2, sIBConnSideHole2ZWid / 2); + + xpos = connBody->GetDX(); + ypos = connBody->GetDY() - sIBConnSideHole2YPos; + zpos = -connBody->GetDZ() + (sIBConnSideHole2ZPos - sIBConnTailZLen) + sideHole2Box->GetDZ(); + TGeoTranslation* sideHole2BTrans = new TGeoTranslation("sideHole2TransBC", xpos, ypos, zpos); + sideHole2BTrans->RegisterYourself(); + + TGeoTubeSeg* sideHole2TubeSeg = + new TGeoTubeSeg("sideHole2CTS", 0, sIBConnSideHole2YWid / 2, sIBConnSideHole2XWid, 180, 360); + + zpos = -connBody->GetDZ() + (sIBConnSideHole2ZPos - sIBConnTailZLen); + TGeoCombiTrans* sideHole2TSTrans1 = + new TGeoCombiTrans("sideHole2TSTrans1C", xpos, ypos, zpos, new TGeoRotation("", -90, 90, 0)); + sideHole2TSTrans1->RegisterYourself(); + + zpos = -connBody->GetDZ() + (sIBConnSideHole2ZPos - sIBConnTailZLen) + 2 * sideHole2Box->GetDZ(); + TGeoCombiTrans* sideHole2TSTrans2 = + new TGeoCombiTrans("sideHole2TSTrans2C", xpos, ypos, zpos, new TGeoRotation("", -90, -90, 0)); + sideHole2TSTrans2->RegisterYourself(); + + TGeoCompositeShape* connBodySh = new TGeoCompositeShape( + "connBodyC-tube2HoleC:tubes2Trans1C-tube2HoleC:tubes2Trans2C-tube3HoleC:tubes3TransC-tube4HoleC:tubes4Trans1C-" + "tube4HoleC:tubes4Trans2C-sideHole1C:sideHole1TransC-sideHole2CTS:sideHole2TSTrans1C-sideHole2CTS:" + "sideHole2TSTrans2C-sideHole2CB:sideHole2TransBC-connRoundHoleC:roundHoleTransC-connInsertHoleC:insertHoleTransC"); + + TGeoVolume* connBlockBody = new TGeoVolume("IBConnectorBlockBodyCSide", connBodySh, medPEEK); + connBlockBody->SetFillColor(42); // Brownish shade + connBlockBody->SetLineColor(42); + + // ...and the tail + xv[0] = sIBConnectorXWidth / 2; + yv[0] = sIBConnTailYShift; + xv[1] = xv[0]; + yv[1] = sIBConnTailYMid; + xv[2] = xv[1] - (sIBConnectorYTot - sIBConnTailYMid) / tanD(90 - sIBConnTailOpenPhi / 2); + yv[2] = sIBConnectorYTot; + + for (Int_t i = 0; i < 3; i++) { + xv[3 + i] = -xv[2 - i]; + yv[3 + i] = yv[2 - i]; + } + + TGeoXtru* connTail = new TGeoXtru(2); + connTail->SetName("connTailC"); + connTail->DefinePolygon(6, xv, yv); + connTail->DefineSection(0, 0); + connTail->DefineSection(1, sIBConnTailZLen); + + TGeoTube* connTubeHole1 = new TGeoTube("tube1HoleC", 0, sIBConnTubeHole1D / 2, sIBConnTubeHole1ZLen / 1.5); + + xpos = sIBConnTubesXDist / 2; + ypos = sIBConnTubesYPos; + zpos = connTail->GetZ(1) / 2; + TGeoTranslation* connTubes1Trans1 = new TGeoTranslation("tubes1Trans1C", -xpos, ypos, zpos); + connTubes1Trans1->RegisterYourself(); + TGeoTranslation* connTubes1Trans2 = new TGeoTranslation("tubes1Trans2C", xpos, ypos, zpos); + connTubes1Trans2->RegisterYourself(); + + TGeoCompositeShape* connTailSh = + new TGeoCompositeShape("connTailC-tube1HoleC:tubes1Trans1C-tube1HoleC:tubes1Trans2C"); + + TGeoVolume* connBlockTail = new TGeoVolume("IBConnectorBlockTailCSide", connTailSh, medPEEK); + connBlockTail->SetFillColor(42); // Brownish shade + connBlockTail->SetLineColor(42); + + // The plug, a Pcon + zlen = sIBConnPlugTotLen - sIBConnPlugInnerLen; + TGeoPcon* connPlugSh = new TGeoPcon(0, 360, 4); + connPlugSh->DefineSection(0, 0., 0., sIBConnTubeHole2D / 2); + connPlugSh->DefineSection(1, zlen, 0., sIBConnTubeHole2D / 2); + connPlugSh->DefineSection(2, zlen, sIBConnPlugInnerD / 2, sIBConnTubeHole2D / 2); + connPlugSh->DefineSection(3, sIBConnPlugTotLen, sIBConnPlugInnerD / 2, sIBConnTubeHole2D / 2); + + TGeoVolume* connPlug = new TGeoVolume("IBConnectorPlugC", connPlugSh, medPEEK); + connPlug->SetFillColor(44); // Brownish shade (a bit darker to spot it) + connPlug->SetLineColor(44); + + // Now create the container: cannot be a simple box + // to avoid fake overlaps with stave elements + xlen = sIBConnectorXWidth; + ylen = sIBConnBodyYHeight; + zlen = sIBConnectBlockZLen - sIBConnTailZLen; + + TGeoBBox* connBox = new TGeoBBox("connBoxC", xlen / 2, ylen / 2, zlen / 2); + + ypos = -sIBConnectorYTot / 2 + connBox->GetDY(); + TGeoTranslation* transBodyC = new TGeoTranslation("transBodyC", 0, ypos, 0); + transBodyC->RegisterYourself(); + + ypos = -sIBConnectorYTot / 2; + zpos = -connBox->GetDZ() - connTail->GetZ(1); + TGeoTranslation* transTailC = new TGeoTranslation("transTailC", 0, ypos, zpos); + transTailC->RegisterYourself(); + + TGeoTube* connTubeHollow = new TGeoTube("tubeHollowC", 0, sIBConnTubeHole1D / 2, sIBConnTubeHole1ZLen / 2); + + xpos = sIBConnTubesXDist / 2; + ypos = -sIBConnectorYTot / 2 + sIBConnTubesYPos; + zpos = -connBox->GetDZ() - connTail->GetZ(1) + sIBConnTubeHole1ZLen / 2; + TGeoTranslation* connTubeHollTrans1 = new TGeoTranslation("tubeHollTrans1C", -xpos, ypos, zpos); + connTubeHollTrans1->RegisterYourself(); + TGeoTranslation* connTubeHollTrans2 = new TGeoTranslation("tubeHollTrans2C", xpos, ypos, zpos); + connTubeHollTrans2->RegisterYourself(); + + zpos = connBody->GetDZ() - (sIBConnectBlockZLen - sIBConnTubeHole3ZPos); + TGeoTranslation* connTubes2Trans1Body = new TGeoTranslation("tubes2Trans1BC", -xpos, ypos, -zpos); + connTubes2Trans1Body->RegisterYourself(); + TGeoTranslation* connTubes2Trans2Body = new TGeoTranslation("tubes2Trans2BC", xpos, ypos, -zpos); + connTubes2Trans2Body->RegisterYourself(); + + TGeoCompositeShape* connBoxSh = new TGeoCompositeShape( + "connBoxC:transBodyC-tube2HoleC:tubes2Trans1BC-tube2HoleC:tubes2Trans2BC+connTailC:transTailC-tubeHollowC:tubeHollTrans1C-" + "tubeHollowC:tubeHollTrans2C"); + + TGeoVolume* connBoxCSide = new TGeoVolume("IBConnectorCSide", connBoxSh, medAir); + + // Finally build up the connector + // (NB: the origin is in the connBox, i.e. w/o the tail in Z) + ypos = -connBoxSh->GetDY(); + zpos = -connBodySh->GetDZ() - connTail->GetZ(1); + connBoxCSide->AddNode(connBlockTail, 1, new TGeoTranslation(0, ypos, zpos)); + + ypos = -connBoxSh->GetDY() + connBody->GetDY(); + connBoxCSide->AddNode(connBlockBody, 1, new TGeoTranslation(0, ypos, 0)); + + xpos = connBox->GetDX(); + ypos = -sIBConnectorYTot / 2 + sIBConnTubesYPos; + zpos = connBody->GetDZ() - (sIBConnectBlockZLen - sIBConnTubeHole3ZPos); + connBoxCSide->AddNode(connPlug, 1, new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 90, -90, 90))); +} + +TGeoVolume* V3Layer::createStaveOuterB(const TGeoManager* mgr) +{ + // Create the chip stave for the Outer Barrel + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 20 Dec 2013 Mario Sitta + // Updated: 12 Mar 2014 Mario Sitta + // Updated: 19 Jul 2017 Mario Sitta O2 version + // + TGeoVolume* mechStavVol = nullptr; + + switch (mStaveModel) { + case Detector::kOBModelDummy: + mechStavVol = createStaveModelOuterBDummy(mgr); + break; + case Detector::kOBModel0: + case Detector::kOBModel1: + LOG(FATAL) << "Stave model " << mStaveModel << " obsolete and no longer supported"; + break; + case Detector::kOBModel2: + mechStavVol = createStaveModelOuterB2(mgr); + break; + default: + LOG(FATAL) << "Unknown stave model " << mStaveModel; + break; + } + return mechStavVol; +} + +TGeoVolume* V3Layer::createStaveModelOuterBDummy(const TGeoManager*) const +{ + // + // Create dummy stave + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 20 Dec 2013 Mario Sitta + // + + // Done, return the stave structure + return nullptr; +} + +TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) +{ + // + // Create the mechanical half stave structure + // for the Outer Barrel as in TDR + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 20 Nov 2013 Anastasia Barbano + // Updated: 16 Jan 2014 Mario Sitta + // Updated: 24 Feb 2014 Mario Sitta + // Updated: 11 Nov 2014 Mario Sitta Model2 + // Updated: 03 Dec 2014 Mario Sitta Revised with C.Gargiulo latest infos + // Updated: 19 Jul 2017 Mario Sitta O2 version + // Updated: 04 Aug 2018 Mario Sitta Updated geometry + // Updated: 25 Aug 2018 Mario Sitta To latest blueprints + // + + // Local parameters + Double_t yFlex1 = sOBFlexCableAlThick; + Double_t yFlex2 = sOBFlexCableKapThick; + Double_t flexOverlap = 5; // to be checked - unused for the time being + Double_t yCFleece = sOBCarbonFleeceThick; + Double_t yGraph = sOBGraphiteFoilThick; + Double_t xHalfSt, yHalfSt; + + Double_t xmod, ymod, zmod, ypowbus; + Double_t xtru[12], ytru[12]; + Double_t xpos, ypos, ypos1, zpos /*, zpos5cm*/; + Double_t xlen, ylen, zlen; + const Int_t nameLen = 30; + char volname[nameLen]; + + Double_t rCoolMin, rCoolMax; + rCoolMin = sOBCoolTubeInnerD / 2; + + rCoolMax = rCoolMin + sOBCoolTubeThick; + + // First create all needed shapes + + TGeoVolume* moduleVol = createModuleOuterB(); + moduleVol->SetVisibility(kTRUE); + xmod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDX(); + ymod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDY(); + zmod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDZ(); + + if (mLayerNumber == mNumberOfInnerLayers || + mLayerNumber == mNumberOfInnerLayers + 1) + zlen = sOBColdPlateZLenML / 2; // Middle Layer + else + zlen = sOBColdPlateZLenOL / 2; // Outer Layer + + xlen = sOBColdPlateXWidth / 2; + + TGeoBBox* coldPlate = new TGeoBBox("ColdPlate", xlen, sOBColdPlateThick / 2, zlen); + + TGeoBBox* fleeccent = new TGeoBBox("FleeceCent", xlen, yCFleece / 2, zlen); + + TGeoTube* coolTube = new TGeoTube("CoolingTube", rCoolMin, rCoolMax, zlen); + TGeoTube* coolWater = new TGeoTube("CoolingWater", 0., rCoolMin, zlen); + + xlen = sOBColdPlateXWidth / 2 - sOBCoolTubeXDist / 2 - coolTube->GetRmax(); + TGeoBBox* graphlat = new TGeoBBox("GraphLateral", xlen / 2, yGraph / 2, zlen); + + xlen = sOBCoolTubeXDist / 2 - coolTube->GetRmax(); + TGeoBBox* graphmid = new TGeoBBox("GraphMiddle", xlen, yGraph / 2, zlen); + + ylen = coolTube->GetRmax() - yGraph; + TGeoBBox* graphvert = new TGeoBBox("GraphVertical", yGraph / 2, ylen / 2, zlen); + + TGeoTubeSeg* graphtub = new TGeoTubeSeg("GraphTube", rCoolMax, rCoolMax + yGraph, zlen, 180., 360.); + + xlen = sOBColdPlateXWidth / 2 - sOBCoolTubeXDist / 2 - coolTube->GetRmax() - yGraph; + TGeoBBox* fleeclat = new TGeoBBox("FleecLateral", xlen / 2, yCFleece / 2, zlen); + + xlen = sOBCoolTubeXDist / 2 - coolTube->GetRmax() - yGraph; + TGeoBBox* fleecmid = new TGeoBBox("FleecMiddle", xlen, yCFleece / 2, zlen); + + ylen = coolTube->GetRmax() - yGraph - yCFleece; + TGeoBBox* fleecvert = new TGeoBBox("FleecVertical", yCFleece / 2, ylen / 2, zlen); + + TGeoTubeSeg* fleectub = + new TGeoTubeSeg("FleecTube", rCoolMax + yGraph, rCoolMax + yCFleece + yGraph, zlen, 180., 360.); + + TGeoTube* gammaConvRod; + if (mAddGammaConv) + gammaConvRod = new TGeoTube("GammaConver", 0, 0.5 * mGammaConvDiam, zlen - sOBCPConnHollowZLen); + + // TGeoBBox* flex1_5cm = new TGeoBBox("Flex1MV_5cm", xHalfSt, yFlex1 / 2, flexOverlap / 2); + // TGeoBBox* flex2_5cm = new TGeoBBox("Flex2MV_5cm", xHalfSt, yFlex2 / 2, flexOverlap / 2); + + // The power bus + TGeoVolume* powerBusVol = createOBPowerBiasBuses(zlen); + powerBusVol->SetVisibility(kTRUE); + ypowbus = (static_cast<TGeoBBox*>(powerBusVol->GetShape()))->GetDY(); + + // The half stave container (an XTru to avoid overlaps between neightbours) + xHalfSt = xmod; // add the cross cables when done! + yHalfSt = ypowbus + ymod + coldPlate->GetDY() + 2 * fleeccent->GetDY() + graphlat->GetDY() + fleeclat->GetDY(); + if (mAddGammaConv) + yHalfSt += mGammaConvDiam; + + xtru[0] = xHalfSt; + ytru[0] = 0; + xtru[1] = xtru[0]; + ytru[1] = -2 * yHalfSt; + xtru[2] = sOBCoolTubeXDist / 2 + fleectub->GetRmax(); + ytru[2] = ytru[1]; + xtru[3] = xtru[2]; + ytru[3] = ytru[2] - (coolTube->GetRmax() + fleectub->GetRmax()); + if (mAddGammaConv) + ytru[3] -= mGammaConvDiam; + xtru[4] = sOBCoolTubeXDist / 2 - fleectub->GetRmax(); + ytru[4] = ytru[3]; + xtru[5] = xtru[4]; + ytru[5] = ytru[2]; + for (Int_t i = 0; i < 6; i++) { + xtru[6 + i] = -xtru[5 - i]; + ytru[6 + i] = ytru[5 - i]; + } + TGeoXtru* halfStaveCent = new TGeoXtru(2); + halfStaveCent->DefinePolygon(12, xtru, ytru); + halfStaveCent->DefineSection(0, -zlen); + halfStaveCent->DefineSection(1, zlen); + snprintf(volname, nameLen, "staveCentral%d", mLayerNumber); + halfStaveCent->SetName(volname); + + // The connectors' containers + TGeoBBox* connAside = new TGeoBBox("connAsideOB", sOBCPConnectorXWidth / 2, sOBCPConnBlockYHei / 2, + (sOBCPConnBlockZLen + sOBCPConnAFitZLen - sOBCPConnAFitZIn) / 2); + + TGeoBBox* connCside = + new TGeoBBox("connCsideOB", sOBCPConnectorXWidth / 2, sOBCPConnBlockYHei / 2, sOBCPConnBlockZLen / 2); + + // The StaveStruct container, a Composite Shape + if (mAddGammaConv) + yHalfSt -= mGammaConvDiam; + ypos = 2 * yHalfSt + connAside->GetDY() - sOBCPConnHollowYHei; + zpos = zlen + connAside->GetDZ() - sOBCPConnHollowZLen; + snprintf(volname, nameLen, "transAsideOB%d", mLayerNumber); + TGeoTranslation* transAside = new TGeoTranslation(volname, 0, -ypos, zpos); + transAside->RegisterYourself(); + + zpos = zlen + connCside->GetDZ() - sOBCPConnHollowZLen; + snprintf(volname, nameLen, "transCsideOB%d", mLayerNumber); + TGeoTranslation* transCside = new TGeoTranslation(volname, 0, -ypos, -zpos); + transCside->RegisterYourself(); + + char componame[70]; + snprintf(componame, 70, "staveCentral%d+connAsideOB:transAsideOB%d+connCsideOB:transCsideOB%d", mLayerNumber, + mLayerNumber, mLayerNumber); + + TGeoCompositeShape* halfStave = new TGeoCompositeShape(componame); + + // We have all shapes: now create the real volumes + + TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medK13D2U120 = mgr->GetMedium("IT4_K13D2U120$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); // amec thermasol + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medTungsten = mgr->GetMedium("IT4_TUNGSTEN$"); + + TGeoVolume* coldPlateVol = new TGeoVolume("ColdPlateVol", coldPlate, medK13D2U120); + coldPlateVol->SetLineColor(kYellow - 3); + coldPlateVol->SetFillColor(coldPlateVol->GetLineColor()); + coldPlateVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* fleeccentVol = new TGeoVolume("CarbonFleeceCentral", fleeccent, medCarbonFleece); + fleeccentVol->SetLineColor(kViolet); + fleeccentVol->SetFillColor(fleeccentVol->GetLineColor()); + fleeccentVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* coolTubeVol = new TGeoVolume("CoolingTubeVol", coolTube, medKapton); + coolTubeVol->SetLineColor(kGray); + coolTubeVol->SetFillColor(coolTubeVol->GetLineColor()); + coolTubeVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* coolWaterVol; + coolWaterVol = new TGeoVolume("CoolingWaterVol", coolWater, medWater); + coolWaterVol->SetLineColor(kBlue); + coolWaterVol->SetFillColor(coolWaterVol->GetLineColor()); + coolWaterVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* graphlatVol = new TGeoVolume("GraphiteFoilLateral", graphlat, medFGS003); + graphlatVol->SetLineColor(kGreen); + graphlatVol->SetFillColor(graphlatVol->GetLineColor()); + graphlatVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* graphmidVol = new TGeoVolume("GraphiteFoilMiddle", graphmid, medFGS003); + graphmidVol->SetLineColor(kGreen); + graphmidVol->SetFillColor(graphmidVol->GetLineColor()); + graphmidVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* graphvertVol = new TGeoVolume("GraphiteFoilVertical", graphvert, medFGS003); + graphvertVol->SetLineColor(kGreen); + graphvertVol->SetFillColor(graphvertVol->GetLineColor()); + graphvertVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* graphtubVol = new TGeoVolume("GraphiteFoilPipeCover", graphtub, medFGS003); + graphtubVol->SetLineColor(kGreen); + graphtubVol->SetFillColor(graphtubVol->GetLineColor()); + graphtubVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* fleeclatVol = new TGeoVolume("CarbonFleeceLateral", fleeclat, medCarbonFleece); + fleeclatVol->SetLineColor(kViolet); + fleeclatVol->SetFillColor(fleeclatVol->GetLineColor()); + fleeclatVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* fleecmidVol = new TGeoVolume("CarbonFleeceMiddle", fleecmid, medCarbonFleece); + fleecmidVol->SetLineColor(kViolet); + fleecmidVol->SetFillColor(fleecmidVol->GetLineColor()); + fleecmidVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* fleecvertVol = new TGeoVolume("CarbonFleeceVertical", fleecvert, medCarbonFleece); + fleecvertVol->SetLineColor(kViolet); + fleecvertVol->SetFillColor(fleecvertVol->GetLineColor()); + fleecvertVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* fleectubVol = new TGeoVolume("CarbonFleecePipeCover", fleectub, medCarbonFleece); + fleectubVol->SetLineColor(kViolet); + fleectubVol->SetFillColor(fleectubVol->GetLineColor()); + fleectubVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* gammaConvRodVol; + if (mAddGammaConv) { + gammaConvRodVol = new TGeoVolume("GammaConversionRod", gammaConvRod, medTungsten); + gammaConvRodVol->SetLineColor(kBlack); + gammaConvRodVol->SetFillColor(gammaConvRodVol->GetLineColor()); + gammaConvRodVol->SetFillStyle(4000); // 0% transparent + } + + snprintf(volname, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + TGeoVolume* halfStaveVol = new TGeoVolume(volname, halfStave, medAir); + // halfStaveVol->SetLineColor(12); + // halfStaveVol->SetFillColor(12); + // halfStaveVol->SetVisibility(kTRUE); + + // TGeoVolume* flex1_5cmVol = new TGeoVolume("Flex1Vol5cm", flex1_5cm, medAluminum); + // TGeoVolume* flex2_5cmVol = new TGeoVolume("Flex2Vol5cm", flex2_5cm, medKapton); + + // flex1_5cmVol->SetLineColor(kRed); + // flex2_5cmVol->SetLineColor(kGreen); + + // Now build up the half stave + ypos = -ypowbus; + halfStaveVol->AddNode(powerBusVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos -= (ypowbus + ymod); + for (Int_t j = 0; j < mNumberOfModules; j++) { + zpos = zlen - j * (2 * zmod + sOBModuleGap) - zmod; + halfStaveVol->AddNode(moduleVol, j, new TGeoTranslation(0, ypos, zpos)); + mHierarchy[kModule]++; + } + + ypos -= ymod; + + ypos -= fleeccent->GetDY(); + if (mBuildLevel < 6) // Carbon + halfStaveVol->AddNode(fleeccentVol, 1, new TGeoTranslation(0, ypos, 0)); + ypos -= fleeccent->GetDY(); + + ypos -= coldPlate->GetDY(); + if (mBuildLevel < 6) // Carbon + halfStaveVol->AddNode(coldPlateVol, 1, new TGeoTranslation(0, ypos, 0)); + ypos -= coldPlate->GetDY(); + + ypos -= fleeccent->GetDY(); + if (mBuildLevel < 6) // Carbon + halfStaveVol->AddNode(fleeccentVol, 2, new TGeoTranslation(0, ypos, 0)); + + xpos = sOBCoolTubeXDist / 2; + ypos1 = ypos - (fleeccent->GetDY() + coolTube->GetRmax()); + if (mBuildLevel < 4) { // Water + halfStaveVol->AddNode(coolWaterVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(coolWaterVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + } + + if (mBuildLevel < 5) { // Kapton + halfStaveVol->AddNode(coolTubeVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(coolTubeVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + } + + if (mBuildLevel < 6) { // Carbon + halfStaveVol->AddNode(graphtubVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(graphtubVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + halfStaveVol->AddNode(fleectubVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(fleectubVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + } + + xpos = sOBColdPlateXWidth / 2 - graphlat->GetDX(); + ypos1 = ypos - (fleeccent->GetDY() + graphlat->GetDY()); + if (mBuildLevel < 6) { // Carbon + halfStaveVol->AddNode(graphlatVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(graphlatVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + halfStaveVol->AddNode(graphmidVol, 1, new TGeoTranslation(0, ypos1, 0)); + + xpos = sOBColdPlateXWidth / 2 - 2 * graphlat->GetDX() + graphvert->GetDX(); + ypos1 = ypos - (fleeccent->GetDY() + 2 * graphlat->GetDY() + graphvert->GetDY()); + halfStaveVol->AddNode(graphvertVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(graphvertVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + xpos = graphmid->GetDX() - graphvert->GetDX(); + halfStaveVol->AddNode(graphvertVol, 3, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(graphvertVol, 4, new TGeoTranslation(xpos, ypos1, 0)); + } + + xpos = sOBColdPlateXWidth / 2 - fleeclat->GetDX(); + ypos1 = ypos - (fleeccent->GetDY() + 2 * graphlat->GetDY() + fleeclat->GetDY()); + if (mBuildLevel < 6) { // Carbon + halfStaveVol->AddNode(fleeclatVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(fleeclatVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + + halfStaveVol->AddNode(fleecmidVol, 1, new TGeoTranslation(0, ypos1, 0)); + + xpos = sOBColdPlateXWidth / 2 - 2 * fleeclat->GetDX() + fleecvert->GetDX(); + ypos1 = ypos - (fleeccent->GetDY() + 2 * graphlat->GetDY() + 2 * fleeclat->GetDY() + fleecvert->GetDY()); + halfStaveVol->AddNode(fleecvertVol, 1, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(fleecvertVol, 2, new TGeoTranslation(xpos, ypos1, 0)); + xpos = fleecmid->GetDX() - fleecvert->GetDX(); + halfStaveVol->AddNode(fleecvertVol, 3, new TGeoTranslation(-xpos, ypos1, 0)); + halfStaveVol->AddNode(fleecvertVol, 4, new TGeoTranslation(xpos, ypos1, 0)); + } + + // Add the Gamma Converter Rod (only on Layer 3) - M.S. 17 Oct 2016 + if (mAddGammaConv) { + xpos = mGammaConvXPos; + ypos1 = ypos - (fleeccent->GetDY() + 2 * graphlat->GetDY() + 2 * fleeclat->GetDY() + gammaConvRod->GetRmax()); + halfStaveVol->AddNode(gammaConvRodVol, 1, new TGeoTranslation(xpos, ypos1, 0)); + } + + // Add the end-stave connectors + TGeoVolume *connectorASide, *connectorCSide; + + // Check whether we have already all pieces + // Otherwise create them + connectorASide = mgr->GetVolume("OBColdPlateConnectorASide"); + + if (!connectorASide) { + createOBColdPlateConnectors(); + connectorASide = mgr->GetVolume("OBColdPlateConnectorASide"); + } + connectorCSide = mgr->GetVolume("OBColdPlateConnectorCSide"); + + ypos = 2 * yHalfSt + (static_cast<TGeoBBox*>(connectorASide->GetShape()))->GetDY() - sOBCPConnHollowYHei; + zpos = zlen + (static_cast<TGeoBBox*>(connectorASide->GetShape()))->GetDZ() - sOBCPConnHollowZLen; + halfStaveVol->AddNode(connectorASide, 1, new TGeoCombiTrans(0, -ypos, zpos, new TGeoRotation("", 180, 0, 0))); + + zpos = zlen + (static_cast<TGeoBBox*>(connectorCSide->GetShape()))->GetDZ() - sOBCPConnHollowZLen; + halfStaveVol->AddNode(connectorCSide, 1, new TGeoCombiTrans(0, -ypos, -zpos, new TGeoRotation("", 180, 0, 0))); + + // Done, return the half stave structure + return halfStaveVol; +} + +TGeoVolume* V3Layer::createOBPowerBiasBuses(const Double_t zcable, const TGeoManager* mgr) +{ + // + // Create the OB Power Bus and Bias Bus cables + // + // Input: + // zcable : the cable half Z length + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // a TGeoVolume with both the Power and the Bias Buses + // + // Created: 05 Aug 2018 Mario Sitta + // Updated: 06 Sep 2018 Mario Sitta + // + + Double_t xcable, ytot, ypos; + + // First create all needed shapes + xcable = sOBPowerBusXWidth / 2; + TGeoBBox* gndPB = new TGeoBBox(xcable, sOBPowerBusAlThick / 2, zcable); + TGeoBBox* dielPB = new TGeoBBox(xcable, sOBPowerBusDielThick / 2, zcable); + TGeoBBox* kapPB = new TGeoBBox(xcable, sOBPowerBusKapThick / 2, zcable); + xcable *= sOBPowerBusAlFrac; + TGeoBBox* topPB = new TGeoBBox(xcable, sOBPowerBusAlThick / 2, zcable); + + xcable = sOBBiasBusXWidth / 2; + TGeoBBox* botBB = new TGeoBBox(xcable, sOBBiasBusAlThick / 2, zcable); + TGeoBBox* dielBB = new TGeoBBox(xcable, sOBBiasBusDielThick / 2, zcable); + TGeoBBox* kapBB = new TGeoBBox(xcable, sOBBiasBusKapThick / 2, zcable); + xcable *= sOBBiasBusAlFrac; + TGeoBBox* topBB = new TGeoBBox(xcable, sOBBiasBusAlThick / 2, zcable); + + // Then the volumes + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + TGeoVolume* gndPBVol = new TGeoVolume("PowerBusGround", gndPB, medAluminum); + gndPBVol->SetLineColor(kCyan); + gndPBVol->SetFillColor(gndPBVol->GetLineColor()); + gndPBVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* dielPBVol = new TGeoVolume("PowerBusDielectric", dielPB, medKapton); + dielPBVol->SetLineColor(kBlue); + dielPBVol->SetFillColor(dielPBVol->GetLineColor()); + dielPBVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* kapPBVol = new TGeoVolume("PowerBusKapton", kapPB, medKapton); + kapPBVol->SetLineColor(kBlue); + kapPBVol->SetFillColor(kapPBVol->GetLineColor()); + kapPBVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* topPBVol = new TGeoVolume("PowerBusTop", topPB, medAluminum); + topPBVol->SetLineColor(kCyan); + topPBVol->SetFillColor(topPBVol->GetLineColor()); + topPBVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* botBBVol = new TGeoVolume("BiasBusBottom", botBB, medAluminum); + botBBVol->SetLineColor(kCyan); + botBBVol->SetFillColor(botBBVol->GetLineColor()); + botBBVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* dielBBVol = new TGeoVolume("BiasBusDielectric", dielBB, medKapton); + dielBBVol->SetLineColor(kBlue); + dielBBVol->SetFillColor(dielBBVol->GetLineColor()); + dielBBVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* kapBBVol = new TGeoVolume("BiasBusKapton", kapBB, medKapton); + kapBBVol->SetLineColor(kBlue); + kapBBVol->SetFillColor(kapBBVol->GetLineColor()); + kapBBVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* topBBVol = new TGeoVolume("BiasBusTop", topBB, medAluminum); + topBBVol->SetLineColor(kCyan); + topBBVol->SetFillColor(topBBVol->GetLineColor()); + topBBVol->SetFillStyle(4000); // 0% transparent + + // Finally the volume containing both the Power Bus and the Bias Bus + xcable = sOBPowerBusXWidth / 2; + ytot = 2 * kapPB->GetDY() + topPB->GetDY() + dielPB->GetDY() + gndPB->GetDY() + 2 * kapBB->GetDY() + topBB->GetDY() + dielBB->GetDY() + botBB->GetDY(); + + TGeoBBox* pnbBus = new TGeoBBox(xcable, ytot, zcable); + + TGeoVolume* pnbBusVol = new TGeoVolume("OBPowerBiasBus", pnbBus, medAir); + + // Volumes are piled up from bottom to top + ypos = -pnbBus->GetDY() + kapPB->GetDY(); + if (mBuildLevel < 5) // Kapton + pnbBusVol->AddNode(kapPBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (kapPB->GetDY() + gndPB->GetDY()); + if (mBuildLevel < 2) // Aluminum + pnbBusVol->AddNode(gndPBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (gndPB->GetDY() + dielPB->GetDY()); + if (mBuildLevel < 5) // Kapton + pnbBusVol->AddNode(dielPBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (dielPB->GetDY() + topPB->GetDY()); + if (mBuildLevel < 2) // Aluminum + pnbBusVol->AddNode(topPBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (topPB->GetDY() + kapPB->GetDY()); + if (mBuildLevel < 5) // Kapton + pnbBusVol->AddNode(kapPBVol, 2, new TGeoTranslation(0, ypos, 0)); + + // + ypos += (kapPB->GetDY() + kapBB->GetDY()); + if (mBuildLevel < 5) // Kapton + pnbBusVol->AddNode(kapBBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (kapBB->GetDY() + botBB->GetDY()); + if (mBuildLevel < 2) // Aluminum + pnbBusVol->AddNode(botBBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (botBB->GetDY() + dielBB->GetDY()); + if (mBuildLevel < 5) // Kapton + pnbBusVol->AddNode(dielBBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (dielBB->GetDY() + topBB->GetDY()); + if (mBuildLevel < 2) // Aluminum + pnbBusVol->AddNode(topBBVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (topBB->GetDY() + kapBB->GetDY()); + if (mBuildLevel < 5) // Kapton + pnbBusVol->AddNode(kapBBVol, 2, new TGeoTranslation(0, ypos, 0)); + + // + return pnbBusVol; +} + +void V3Layer::createOBColdPlateConnectors() +{ + // + // Create the Cold Plate connectors for OB half staves + // (simply call the actual creator methods) + // + // Input: + // + // Output: + // + // Return: + // + // Created: 26 May 2015 Mario Sitta + // + + createOBColdPlateConnectorsASide(); + createOBColdPlateConnectorsCSide(); +} + +void V3Layer::createOBColdPlateConnectorsASide() +{ + // + // Create the A-Side end-stave connectors for IB staves + // + // Input: + // + // Output: + // + // Return: + // + // Created: 26 May 2015 Mario Sitta + // Updated: 20 Jul 2017 Mario Sitta O2 version + // Updated: 15 Oct 2018 Mario Sitta To latest blueprints + // + + // The geoManager + const TGeoManager* mgr = gGeoManager; + + // Local variables + const Int_t nv = 16; + Double_t xv[nv], yv[nv]; + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + + // Gather all material pointers + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + TGeoMedium* medInox304 = mgr->GetMedium("IT4_INOX304$"); + + // First create all elements + + // The connector block, a Composite Shape + xlen = sOBCPConnectorXWidth; + ylen = sOBCPConnBlockYHei; + zlen = sOBCPConnBlockZLen; + TGeoBBox* connBlock = new TGeoBBox("connBlockA", xlen / 2, ylen / 2, zlen / 2); + + xv[0] = sOBCPConnectorXWidth * 0.6; + yv[0] = -sOBCPConnHollowYHei; + xv[1] = xv[0]; + yv[1] = sOBCPConnHollowYHei; + xv[2] = sOBCPConnTubesXDist / 2 + sOBCPConnTubeHole1D / 2; + yv[2] = yv[1]; + xv[3] = xv[2]; + yv[3] = sOBCPConnTubesYPos; + xv[4] = sOBCPConnTubesXDist / 2 - sOBCPConnTubeHole1D / 2; + yv[4] = yv[3]; + xv[5] = xv[4]; + yv[5] = yv[2]; + + for (Int_t i = 0; i < 6; i++) { + xv[6 + i] = -xv[5 - i]; + yv[6 + i] = yv[5 - i]; + } + + TGeoXtru* connBlockHoll = new TGeoXtru(2); + connBlockHoll->SetName("connBlockHollA"); + connBlockHoll->DefinePolygon(12, xv, yv); + connBlockHoll->DefineSection(0, -sOBCPConnHollowZLen); + connBlockHoll->DefineSection(1, sOBCPConnHollowZLen); + + ypos = -connBlock->GetDY(); + zpos = -connBlock->GetDZ(); + TGeoTranslation* transBlockHoll = new TGeoTranslation("transBlockHollA", 0, ypos, zpos); + transBlockHoll->RegisterYourself(); + + xlen = sOBCPConnSquareHoleX / 2; + ylen = sOBCPConnBlockYHei / 1.5; + zlen = sOBCPConnSquareHoleZ / 2; + TGeoBBox* connSquareHole = new TGeoBBox("connASquareHole", xlen, ylen, zlen); + + zpos = + -connBlock->GetDZ() + (sOBCPConnSqrHoleZPos + connSquareHole->GetDZ()); + TGeoTranslation* transSquareHole = new TGeoTranslation("transASquareHole", 0, 0, zpos); + transSquareHole->RegisterYourself(); + + zlen = sOBCPConnTubeHole1Z; + TGeoTube* connTubeHole1 = new TGeoTube("tube1AHole", 0, sOBCPConnTubeHole1D / 2, zlen); + + xpos = sOBCPConnTubesXDist / 2; + ypos = -connBlock->GetDY() + sOBCPConnTubesYPos; + zpos = connBlock->GetDZ(); + TGeoTranslation* trans1Tube1AHole = new TGeoTranslation("trans1Tube1AHole", -xpos, ypos, -zpos); + trans1Tube1AHole->RegisterYourself(); + TGeoTranslation* trans2Tube1AHole = new TGeoTranslation("trans2Tube1AHole", xpos, ypos, -zpos); + trans2Tube1AHole->RegisterYourself(); + + zlen = sOBCPConnBlockZLen; + TGeoTube* connTubeHole2 = new TGeoTube("tube2AHole", 0, sOBCPConnTubeHole2D / 2, zlen); + + TGeoTranslation* trans1Tube2AHole = new TGeoTranslation("trans1Tube2AHole", -xpos, ypos, 0); + trans1Tube2AHole->RegisterYourself(); + TGeoTranslation* trans2Tube2AHole = new TGeoTranslation("trans2Tube2AHole", xpos, ypos, 0); + trans2Tube2AHole->RegisterYourself(); + + zlen = sOBCPConnAFitZIn; + TGeoTube* connFitHole = new TGeoTube("fitAHole", 0, sOBCPConnFitHoleD / 2, zlen); + + TGeoTranslation* trans1FitAHole = new TGeoTranslation("trans1FitAHole", -xpos, ypos, zpos); + trans1FitAHole->RegisterYourself(); + TGeoTranslation* trans2FitAHole = new TGeoTranslation("trans2FitAHole", xpos, ypos, zpos); + trans2FitAHole->RegisterYourself(); + + TGeoCompositeShape* connBlockSh = new TGeoCompositeShape( + "connBlockA-connBlockHollA:transBlockHollA-connASquareHole:transASquareHole-tube1AHole:trans1Tube1AHole-tube1AHole:" + "trans2Tube1AHole-tube2AHole:trans1Tube2AHole-tube2AHole:trans2Tube2AHole-fitAHole:trans1FitAHole-fitAHole:" + "trans2FitAHole"); + + TGeoVolume* connBlockA = new TGeoVolume("OBColdPlateConnectorBlockASide", connBlockSh, medPEEK); + connBlockA->SetFillColor(42); // Brownish shade + connBlockA->SetLineColor(42); + + // The fitting tubes, a Tube + Double_t rmin = sOBCPConnAFitExtD / 2 - sOBCPConnAFitThick; + TGeoTube* connFitSh = new TGeoTube(rmin, sOBCPConnAFitExtD / 2, sOBCPConnAFitZLen / 2); + + TGeoVolume* connFit = new TGeoVolume("OBColdPlateConnectorFitting", connFitSh, medInox304); + connFit->SetFillColor(kGray); + connFit->SetLineColor(kGray); + + // Now create the container: cannot be a simple box + // to avoid fake overlaps with stave elements + xlen = sOBCPConnectorXWidth; + ylen = sOBCPConnBlockYHei; + zlen = sOBCPConnBlockZLen + (sOBCPConnAFitZLen - sOBCPConnAFitZIn); + TGeoBBox* connBox = new TGeoBBox("connectorOBCPA", xlen / 2, ylen / 2, zlen / 2); + + ypos = -connBox->GetDY(); + zpos = -connBox->GetDZ(); + TGeoTranslation* transBoxHoll = new TGeoTranslation("transBoxHollA", 0, ypos, zpos); + transBoxHoll->RegisterYourself(); + + xpos = sOBCPConnTubesXDist / 2; + ypos = -connBox->GetDY() + sOBCPConnTubesYPos; + zpos = connBox->GetDZ(); + TGeoTranslation* trans1BoxHole = new TGeoTranslation("trans1BoxAHole", -xpos, ypos, -zpos); + trans1BoxHole->RegisterYourself(); + TGeoTranslation* trans2BoxHole = new TGeoTranslation("trans2BoxAHole", xpos, ypos, -zpos); + trans2BoxHole->RegisterYourself(); + + TGeoCompositeShape* connectSh = new TGeoCompositeShape( + "connectorOBCPA-connBlockHollA:transBoxHollA-tube1AHole:trans1BoxAHole-tube1AHole:trans2BoxAHole"); + + TGeoVolume* connectorASide = new TGeoVolume("OBColdPlateConnectorASide", connectSh, medAir); + + // Finally build up the connector + zpos = -connectSh->GetDZ() + connBlock->GetDZ(); + connectorASide->AddNode(connBlockA, 1, new TGeoTranslation(0, 0, zpos)); + + xpos = sOBCPConnTubesXDist / 2; + ypos = -connBlock->GetDY() + sOBCPConnTubesYPos; + zpos = connectSh->GetDZ() - connFitSh->GetDz(); + connectorASide->AddNode(connFit, 1, new TGeoTranslation(-xpos, ypos, zpos)); + connectorASide->AddNode(connFit, 2, new TGeoTranslation(xpos, ypos, zpos)); +} + +void V3Layer::createOBColdPlateConnectorsCSide() +{ + // + // Create the C-Side end-stave connectors for IB staves + // + // Input: + // + // Output: + // + // Return: + // + // Created: 29 May 2015 Mario Sitta + // Updated: 20 Jul 2017 Mario Sitta O2 version + // Updated: 15 Oct 2018 Mario Sitta To latest blueprints + // + + // The geoManager + const TGeoManager* mgr = gGeoManager; + + // Local variables + const Int_t nv = 16; + Double_t xv[nv], yv[nv]; + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + + // Gather all material pointers + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + + // First create all elements + + // The connector block, a Composite Shape + xlen = sOBCPConnectorXWidth; + ylen = sOBCPConnBlockYHei; + zlen = sOBCPConnBlockZLen; + TGeoBBox* connBlock = new TGeoBBox("connBlockC", xlen / 2, ylen / 2, zlen / 2); + + xv[0] = sOBCPConnectorXWidth * 0.6; + yv[0] = -sOBCPConnHollowYHei; + xv[1] = xv[0]; + yv[1] = sOBCPConnHollowYHei; + xv[2] = sOBCPConnTubesXDist / 2 + sOBCPConnTubeHole1D / 2; + yv[2] = yv[1]; + xv[3] = xv[2]; + yv[3] = sOBCPConnTubesYPos; + xv[4] = sOBCPConnTubesXDist / 2 - sOBCPConnTubeHole1D / 2; + yv[4] = yv[3]; + xv[5] = xv[4]; + yv[5] = yv[2]; + + for (Int_t i = 0; i < 6; i++) { + xv[6 + i] = -xv[5 - i]; + yv[6 + i] = yv[5 - i]; + } + + TGeoXtru* connBlockHoll = new TGeoXtru(2); + connBlockHoll->SetName("connBlockHollC"); + connBlockHoll->DefinePolygon(12, xv, yv); + connBlockHoll->DefineSection(0, -sOBCPConnHollowZLen); + connBlockHoll->DefineSection(1, sOBCPConnHollowZLen); + + ypos = -connBlock->GetDY(); + zpos = connBlock->GetDZ(); + TGeoTranslation* transBlockHoll = new TGeoTranslation("transBlockHollC", 0, ypos, zpos); + transBlockHoll->RegisterYourself(); + + TGeoTube* connRoundHole = new TGeoTube("connCRoundHole", 0, sOBCPConnRoundHoleD / 2, sOBCPConnBlockYHei / 1.5); + + zpos = connBlock->GetDZ() - sOBCPConnRndHoleZPos; + TGeoCombiTrans* transRoundHole = new TGeoCombiTrans("transCRoundHole", 0, 0, zpos, new TGeoRotation("", 0, 90, 0)); + transRoundHole->RegisterYourself(); + + zlen = sOBCPConnTubeHole1Z; + TGeoTube* connTubeHole1 = new TGeoTube("tube1CHole", 0, sOBCPConnTubeHole1D / 2, zlen); + + xpos = sOBCPConnTubesXDist / 2; + ypos = -connBlock->GetDY() + sOBCPConnTubesYPos; + zpos = connBlock->GetDZ(); + TGeoTranslation* trans1Tube1AHole = new TGeoTranslation("trans1Tube1CHole", -xpos, ypos, zpos); + trans1Tube1AHole->RegisterYourself(); + TGeoTranslation* trans2Tube1AHole = new TGeoTranslation("trans2Tube1CHole", xpos, ypos, zpos); + trans2Tube1AHole->RegisterYourself(); + + TGeoTube* connTubeHole2 = new TGeoTube("tube2CHole", 0, sOBCPConnTubeHole2D / 2, connBlock->GetDZ()); + + zpos = sOBCPConnTubeHole3ZP; + TGeoTranslation* connTubes2Trans1 = new TGeoTranslation("trans1Tube2CHole", -xpos, ypos, zpos); + connTubes2Trans1->RegisterYourself(); + TGeoTranslation* connTubes2Trans2 = new TGeoTranslation("trans2Tube2CHole", xpos, ypos, zpos); + connTubes2Trans2->RegisterYourself(); + + TGeoTube* connTubeHole3 = new TGeoTube("tube3CHole", 0, sOBCPConnTubeHole2D / 2, connBlock->GetDX()); + + xpos = -sOBCPConnTubeHole3XP; + zpos = -connBlock->GetDZ() + sOBCPConnTubeHole3ZP; + TGeoCombiTrans* connTubes3Trans = + new TGeoCombiTrans("transTube3CHole", xpos, ypos, zpos, new TGeoRotation("", 90, -90, 90)); + connTubes3Trans->RegisterYourself(); + + TGeoCompositeShape* connBlockSh = new TGeoCompositeShape( + "connBlockC-connBlockHollC:transBlockHollC-connCRoundHole:transCRoundHole-tube1CHole:trans1Tube1CHole-tube1CHole:" + "trans2Tube1CHole-tube2CHole:trans1Tube2CHole-tube2CHole:trans2Tube2CHole-tube3CHole:transTube3CHole"); + + TGeoVolume* connBlockC = new TGeoVolume("OBColdPlateConnectorBlockCSide", connBlockSh, medPEEK); + connBlockC->SetFillColor(42); // Brownish shade + connBlockC->SetLineColor(42); + + // The plug, a Pcon + TGeoPcon* connPlugSh = new TGeoPcon(0, 360, 4); + connPlugSh->DefineSection(0, 0., 0., sOBCPConnTubeHole2D / 2); + connPlugSh->DefineSection(1, sOBCPConnPlugThick, 0., sOBCPConnTubeHole2D / 2); + connPlugSh->DefineSection(2, sOBCPConnPlugThick, sOBCPConnPlugInnerD / 2, sOBCPConnTubeHole2D / 2); + connPlugSh->DefineSection(3, sOBCPConnPlugTotLen, sOBCPConnPlugInnerD / 2, sOBCPConnTubeHole2D / 2); + + TGeoVolume* connPlug = new TGeoVolume("OBCPConnectorPlugC", connPlugSh, medPEEK); + connPlug->SetFillColor(44); // Brownish shade (a bit darker to spot it) + connPlug->SetLineColor(44); + + // Now create the container: cannot be a simple box + // to avoid fake overlaps with stave elements + xlen = sOBCPConnectorXWidth; + ylen = sOBCPConnBlockYHei; + zlen = sOBCPConnBlockZLen; + TGeoBBox* connBox = new TGeoBBox("connectorOBCPC", xlen / 2, ylen / 2, zlen / 2); + + ypos = -connBox->GetDY(); + zpos = connBox->GetDZ(); + TGeoTranslation* transBoxHoll = new TGeoTranslation("transBoxHollC", 0, ypos, zpos); + transBoxHoll->RegisterYourself(); + + xpos = sOBCPConnTubesXDist / 2; + ypos = -connBox->GetDY() + sOBCPConnTubesYPos; + zpos = connBox->GetDZ(); + TGeoTranslation* trans1BoxHole = new TGeoTranslation("trans1BoxCHole", -xpos, ypos, zpos); + trans1BoxHole->RegisterYourself(); + TGeoTranslation* trans2BoxHole = new TGeoTranslation("trans2BoxCHole", xpos, ypos, zpos); + trans2BoxHole->RegisterYourself(); + + TGeoCompositeShape* connectSh = new TGeoCompositeShape( + "connectorOBCPC-connBlockHollC:transBoxHollC-tube1CHole:trans1BoxCHole-tube1CHole:trans2BoxCHole"); + + TGeoVolume* connectorCSide = new TGeoVolume("OBColdPlateConnectorCSide", connectSh, medAir); + + // Finally build up the connector + connectorCSide->AddNode(connBlockC, 1); + + xpos = -connBlock->GetDX(); + ypos = -connBlock->GetDY() + sOBCPConnTubesYPos; + zpos = -connBlock->GetDZ() + sOBCPConnTubeHole3ZP; + connectorCSide->AddNode(connPlug, 1, new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 90, 90, 90))); +} + +TGeoVolume* V3Layer::createSpaceFrameOuterB(const TGeoManager* mgr) +{ + TGeoVolume* mechStavVol = nullptr; + + switch (mStaveModel) { + case Detector::kOBModelDummy: + case Detector::kOBModel0: + mechStavVol = createSpaceFrameOuterBDummy(mgr); + break; + case Detector::kOBModel1: + case Detector::kOBModel2: + mechStavVol = createSpaceFrameOuterB2(mgr); + break; + default: + LOG(FATAL) << "Unknown stave model " << mStaveModel; + break; + } + + return mechStavVol; +} + +TGeoVolume* V3Layer::createSpaceFrameOuterBDummy(const TGeoManager*) const +{ + // + // Create dummy stave + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + + // Done, return the stave structur + return nullptr; +} + +TGeoVolume* V3Layer::createSpaceFrameOuterB2(const TGeoManager* mgr) +{ + // + // Create the space frame for the Outer Barrel (Model 2) + // The building blocks are created in another method to avoid + // replicating the same volumes for all OB staves + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // a TGeoVolume with the Space Frame of a stave + // + // Created: 03 Feb 2015 Mario Sitta + // Updated: 04 Jun 2015 Mario Sitta Change container to avoid overlaps + // Updated: 20 Jul 2017 Mario Sitta O2 version + // + + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + TGeoVolume *unitVol[2], *next2EndVol[2], *endVol[2]; + Double_t *xtru, *ytru; + Double_t zlen, zpos; + Int_t nPoints; + const Int_t nameLen = 30; + char volname[nameLen]; + + // Check whether we have already all pieces + // Otherwise create them + unitVol[0] = mgr->GetVolume("SpaceFrameUnit0"); + + if (!unitVol[0]) { + createOBSpaceFrameObjects(mgr); + unitVol[0] = mgr->GetVolume("SpaceFrameUnit0"); + } + + unitVol[1] = mgr->GetVolume("SpaceFrameUnit1"); + + next2EndVol[0] = mgr->GetVolume("SpaceFrameNext2EndUnit0"); + next2EndVol[1] = mgr->GetVolume("SpaceFrameNext2EndUnit1"); + + endVol[0] = mgr->GetVolume("SpaceFrameEndUnit0"); + endVol[1] = mgr->GetVolume("SpaceFrameEndUnit1"); + + // Get the shape of the units + // and create a similar shape for the Space Frame container + TGeoXtru* volShape = static_cast<TGeoXtru*>(unitVol[0]->GetShape()); + + nPoints = volShape->GetNvert(); + xtru = new Double_t[nPoints]; + ytru = new Double_t[nPoints]; + + for (Int_t i = 0; i < nPoints; i++) { + xtru[i] = volShape->GetX(i); + ytru[i] = volShape->GetY(i); + } + + Int_t iOBLayer = mLayerNumber - mNumberOfInnerLayers + 3; + Int_t nUnits = sOBSpaceFrameNUnits[iOBLayer / 5]; // 3,4 -> 0 - 5,6 -> 1 + zlen = (nUnits - 2) * sOBSpaceFrameUnitLen; // Take end units out + + TGeoXtru* spaceFrameCentral = new TGeoXtru(2); + spaceFrameCentral->DefinePolygon(nPoints, xtru, ytru); + spaceFrameCentral->DefineSection(0, -zlen / 2); + spaceFrameCentral->DefineSection(1, zlen / 2); + snprintf(volname, nameLen, "sframecentral%d", mLayerNumber); + spaceFrameCentral->SetName(volname); + + zpos = zlen / 2 + sOBSpaceFrameUnitLen / 2; + snprintf(volname, nameLen, "endUnit0Trans%d", mLayerNumber); + TGeoCombiTrans* endUnit0Trans = new TGeoCombiTrans(volname, 0, 0, -zpos, new TGeoRotation("", 90, 180, -90)); + endUnit0Trans->RegisterYourself(); + snprintf(volname, nameLen, "endUnit1Trans%d", mLayerNumber); + TGeoTranslation* endUnit1Trans = new TGeoTranslation(volname, 0, 0, zpos); + endUnit1Trans->RegisterYourself(); + + // The Space Frame container: a Composite Shape to avoid overlaps + // between the U-legs space and the end-stave connectors + // ("endunitcontainer" is defined in CreateOBSpaceFrameObjects) + char componame[100]; + snprintf(componame, 100, "sframecentral%d+endunitcontainer:endUnit0Trans%d+endunitcontainer:endUnit1Trans%d", + mLayerNumber, mLayerNumber, mLayerNumber); + + TGeoCompositeShape* spaceFrame = new TGeoCompositeShape(componame); + + snprintf(volname, nameLen, "SpaceFrameVolumeLay%d", mLayerNumber); + TGeoVolume* spaceFrameVol = new TGeoVolume(volname, spaceFrame, medAir); + spaceFrameVol->SetVisibility(kFALSE); + + // Finally build up the space frame + TGeoXtru* frameUnit = static_cast<TGeoXtru*>(unitVol[0]->GetShape()); + + zpos = -spaceFrame->GetDZ() + frameUnit->GetDZ() + sOBSFrameConnTopLen; + spaceFrameVol->AddNode(endVol[0], 1, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 90, 180, -90))); + + zpos += (2 * frameUnit->GetDZ()); + spaceFrameVol->AddNode(next2EndVol[0], 1, new TGeoTranslation(0, 0, zpos)); + + for (Int_t i = 2; i < nUnits - 2; i++) { + zpos += (2 * frameUnit->GetDZ()); + Int_t j = i / 2; + Int_t k = i - j * 2; // alternatively 0 or 1 + spaceFrameVol->AddNode(unitVol[k], j, new TGeoTranslation(0, 0, zpos)); + } + + zpos += (2 * frameUnit->GetDZ()); + spaceFrameVol->AddNode(next2EndVol[1], 1, new TGeoTranslation(0, 0, zpos)); + + zpos += (2 * frameUnit->GetDZ()); + spaceFrameVol->AddNode(endVol[1], 1, new TGeoTranslation(0, 0, zpos)); + + // Done, clean up and return the space frame structure + delete[] xtru; + delete[] ytru; + + return spaceFrameVol; +} + +void V3Layer::createOBSpaceFrameObjects(const TGeoManager* mgr) +{ + // + // Create the space frame building blocks for the Outer Barrel + // This method is practically identical to previous versions of + // CreateSpaceFrameOuterB1 + // NB: it is pretty cumbersome, because we don't want to use assemblies + // so we are forced to have well-crafted containers to avoid fake overlaps + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // a TGeoVolume with the Space Frame of a stave + // + // Created: 03 Feb 2015 Mario Sitta + // Updated: 03 Jun 2015 Mario Sitta End units w/o U-legs + // Updated: 20 Jul 2017 Mario Sitta O2 version + // Updated: 09 Sep 2019 Mario Sitta Connectors added + // Updated: 27 Sep 2019 Mario Sitta New TopV for End Units + // + + // Materials defined in AliITSUv2 + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); + TGeoMedium* medF6151B05M = mgr->GetMedium("IT4_F6151B05M$"); + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + + // Local parameters + Double_t halfFrameWidth = sOBSpaceFrameWidth / 2; + Double_t triangleHeight = sOBSpaceFrameHeight; + Double_t sframeHeight = triangleHeight + sOBSFrameBaseRibDiam + sOBSFrameULegHeight2 * 2; + Double_t staveLa = sOBSpaceFrameTopVL; + Double_t staveHa = sOBSpaceFrameTopVH; + Double_t staveLb = sOBSpaceFrameSideVL; + Double_t staveHb = sOBSpaceFrameSideVH; + Double_t alphaDeg = sOBSpaceFrameVAlpha; + Double_t alphaRad = alphaDeg * TMath::DegToRad() / 2; + Double_t beta = sOBSpaceFrameVBeta * TMath::DegToRad() / 2; + Double_t sideRibRadius = sOBSFrameSideRibDiam / 2; + Double_t sidePhiDeg = sOBSFrameSideRibPhi; + Double_t sidePhiRad = sidePhiDeg * TMath::DegToRad(); + Double_t baseRibRadius = sOBSFrameBaseRibDiam / 2; + Double_t basePhiDeg = sOBSFrameBaseRibPhi; + Double_t basePhiRad = basePhiDeg * TMath::DegToRad(); + Double_t ulegHalfLen = sOBSFrameULegLen / 2; + Double_t ulegHalfWidth = sOBSFrameULegWidth / 2; + Double_t ulegHigh1 = sOBSFrameULegHeight1; + Double_t ulegHigh2 = sOBSFrameULegHeight2; + Double_t ulegThick = sOBSFrameULegThick; + Double_t topVFactorEU = 0.60; // Fraction of TopV total length for End Units + + Double_t xlen, zlen; + Double_t xpos, ypos, zpos; + Double_t unitlen; + Double_t xtru[22], ytru[22]; + + unitlen = sOBSpaceFrameUnitLen; + + xlen = halfFrameWidth + sideRibRadius; + + // We need a properly shaped Xtru to accomodate the ribs avoiding + // overlaps with the HalfStave cooling tubes + xtru[0] = sOBSFrameULegXPos - ulegHalfLen; + ytru[0] = -(triangleHeight / 2 + baseRibRadius); + xtru[1] = xtru[0]; + ytru[1] = ytru[0] - ulegHigh1; + xtru[2] = xtru[1] + ulegThick; + ytru[2] = ytru[1]; + xtru[3] = xtru[2]; + ytru[3] = ytru[0] - ulegThick; + xtru[7] = sOBSFrameULegXPos + ulegHalfLen; + ytru[7] = ytru[0]; + xtru[6] = xtru[7]; + ytru[6] = ytru[1]; + xtru[5] = xtru[6] - ulegThick; + ytru[5] = ytru[6]; + xtru[4] = xtru[5]; + ytru[4] = ytru[3]; + xtru[8] = xlen; + ytru[8] = ytru[7]; + xtru[9] = xtru[8]; + ytru[9] = 0.9 * ytru[8]; + xtru[10] = 0.3 * xtru[8]; + ytru[10] = triangleHeight / 2; + for (Int_t i = 0; i < 11; i++) { // Reflect on the X negative side + xtru[i + 11] = -xtru[10 - i]; + ytru[i + 11] = ytru[10 - i]; + } + ytru[15] = ytru[0] - ulegHigh2; // U-legs on negative X are longer + ytru[16] = ytru[15]; + ytru[19] = ytru[15]; + ytru[20] = ytru[15]; + + // The space frame single units + // We need two units because the base ribs are alternately oriented + // The next-to-end units are slightly different + TGeoXtru* frameUnit = new TGeoXtru(2); + frameUnit->DefinePolygon(22, xtru, ytru); + frameUnit->DefineSection(0, -unitlen / 2); + frameUnit->DefineSection(1, unitlen / 2); + + TGeoXtru* next2EndUnit = new TGeoXtru(2); + next2EndUnit->DefinePolygon(22, xtru, ytru); + next2EndUnit->DefineSection(0, -unitlen / 2); + next2EndUnit->DefineSection(1, unitlen / 2); + + // The end units have no U-legs, but they contain the end-stave connectors + // so we build a CompositeShape using two Xtru's + xtru[0] = xlen; + ytru[0] = -(triangleHeight / 2 + baseRibRadius); + xtru[1] = xtru[0]; + ytru[1] = 0.9 * ytru[0]; + xtru[2] = 0.3 * xtru[0]; + ytru[2] = triangleHeight / 2; + for (Int_t i = 0; i < 3; i++) { // Reflect on the X negative side + xtru[i + 3] = -xtru[2 - i]; + ytru[i + 3] = ytru[2 - i]; + } + + TGeoXtru* endUnitBody = new TGeoXtru(2); + endUnitBody->SetName("endunitbody"); + endUnitBody->DefinePolygon(6, xtru, ytru); + endUnitBody->DefineSection(0, -unitlen / 2); + endUnitBody->DefineSection(1, 0.8 * unitlen / 2); + + xtru[2] = 0.25 * (3 * xtru[1] + xtru[2]); + ytru[2] = 0.25 * (3 * ytru[1] + ytru[2]); + for (Int_t i = 0; i < 3; i++) { // Reflect on the X negative side + xtru[i + 3] = -xtru[2 - i]; + ytru[i + 3] = ytru[2 - i]; + } + + TGeoXtru* endUnitBodyLow = new TGeoXtru(2); + endUnitBodyLow->SetName("endunitbodylow"); + endUnitBodyLow->DefinePolygon(6, xtru, ytru); + endUnitBodyLow->DefineSection(0, 0.8 * unitlen / 2); + endUnitBodyLow->DefineSection(1, unitlen / 2); + + // (See createOBSpaceFrameConnector lower down for details) + xtru[0] = sOBSFrameConnWidth / 2.; + ytru[0] = 0.; + xtru[1] = xtru[0]; + ytru[1] = sOBSFrameConnInsHei; + xtru[2] = xtru[1] - sOBSFrameConnTotHei + sOBSFrameConnInsHei; + ytru[2] = sOBSFrameConnTotHei; + for (Int_t i = 0; i < 3; i++) { // Reflect on the X negative side + xtru[i + 3] = -xtru[2 - i]; + ytru[i + 3] = ytru[2 - i]; + } + + TGeoXtru* endUnitConn = new TGeoXtru(2); + endUnitConn->SetName("endunitconn"); + endUnitConn->DefinePolygon(6, xtru, ytru); + endUnitConn->DefineSection(0, 0.); + endUnitConn->DefineSection(1, sOBSFrameConnTopLen); + + // We create a fake side V to have its dimensions, needed for + // the creation of the end unit container + TGeoXtru* vside = + createStaveSide("fakeCornerSide", unitlen / 2., alphaRad, beta, staveLb, staveHb, kFALSE); + + ypos = -triangleHeight / 2 + vside->GetY(3); + TGeoTranslation* endUnitConnTrans = new TGeoTranslation("endunitconntrans", 0, ypos, unitlen / 2); + endUnitConnTrans->RegisterYourself(); + + TGeoCompositeShape* endUnit = new TGeoCompositeShape("endunitbody+endunitbodylow+endunitconn:endunitconntrans"); + endUnit->SetName("endunitcontainer"); // Will be used when create spaceframe + + // The air containers + TGeoVolume* unitVol[2]; + unitVol[0] = new TGeoVolume("SpaceFrameUnit0", frameUnit, medAir); + unitVol[1] = new TGeoVolume("SpaceFrameUnit1", frameUnit, medAir); + unitVol[0]->SetVisibility(kFALSE); + unitVol[1]->SetVisibility(kFALSE); + + TGeoVolume* next2EndVol[2]; + next2EndVol[0] = new TGeoVolume("SpaceFrameNext2EndUnit0", next2EndUnit, medAir); + next2EndVol[1] = new TGeoVolume("SpaceFrameNext2EndUnit1", next2EndUnit, medAir); + next2EndVol[0]->SetVisibility(kFALSE); + next2EndVol[1]->SetVisibility(kFALSE); + + TGeoVolume* endVol[2]; + endVol[0] = new TGeoVolume("SpaceFrameEndUnit0", endUnit, medAir); + endVol[1] = new TGeoVolume("SpaceFrameEndUnit1", endUnit, medAir); + endVol[0]->SetVisibility(kFALSE); + endVol[1]->SetVisibility(kFALSE); + + // The actual volumes + + //--- The top V of the Carbon Fiber Stave (segment) + TGeoXtru* cfStavTop = + createStaveSide("CFstavTopCornerVolshape", unitlen / 2., alphaRad, beta, staveLa, staveHa, kTRUE); + + TGeoVolume* cfStavTopVol = new TGeoVolume("CFstavTopCornerVol", cfStavTop, medCarbon); + cfStavTopVol->SetLineColor(35); + + unitVol[0]->AddNode(cfStavTopVol, 1, new TGeoTranslation(0, triangleHeight / 2, 0)); + + unitVol[1]->AddNode(cfStavTopVol, 1, new TGeoTranslation(0, triangleHeight / 2, 0)); + + next2EndVol[0]->AddNode(cfStavTopVol, 1, new TGeoTranslation(0, triangleHeight / 2, 0)); + + next2EndVol[1]->AddNode(cfStavTopVol, 1, new TGeoTranslation(0, triangleHeight / 2, 0)); + + zlen = topVFactorEU * unitlen; + TGeoXtru* cfStavTopEU = + createStaveSide("CFstavTopCornerEUVolshape", zlen / 2., alphaRad, beta, staveLa, staveHa, kTRUE); + + TGeoVolume* cfStavTopVolEU = new TGeoVolume("CFstavTopCornerEUVol", cfStavTopEU, medCarbon); + cfStavTopVol->SetLineColor(35); + + zpos = endUnitBody->GetDZ() - zlen / 2.; + + endVol[0]->AddNode(cfStavTopVolEU, 1, new TGeoTranslation(0, triangleHeight / 2, -zpos)); + + endVol[1]->AddNode(cfStavTopVolEU, 1, new TGeoTranslation(0, triangleHeight / 2, -zpos)); + + //--- The two side V's + TGeoXtru* cfStavSide = + createStaveSide("CFstavSideCornerVolshape", unitlen / 2., alphaRad, beta, staveLb, staveHb, kFALSE); + + TGeoVolume* cfStavSideVol = new TGeoVolume("CFstavSideCornerVol", cfStavSide, medCarbon); + cfStavSideVol->SetLineColor(35); + + unitVol[0]->AddNode(cfStavSideVol, 1, new TGeoTranslation(halfFrameWidth, -triangleHeight / 2, 0)); + unitVol[0]->AddNode(cfStavSideVol, 2, + new TGeoCombiTrans(-halfFrameWidth, -triangleHeight / 2, 0, new TGeoRotation("", 90, 180, -90))); + + unitVol[1]->AddNode(cfStavSideVol, 1, new TGeoTranslation(halfFrameWidth, -triangleHeight / 2, 0)); + unitVol[1]->AddNode(cfStavSideVol, 2, + new TGeoCombiTrans(-halfFrameWidth, -triangleHeight / 2, 0, new TGeoRotation("", 90, 180, -90))); + + next2EndVol[0]->AddNode(cfStavSideVol, 1, new TGeoTranslation(halfFrameWidth, -triangleHeight / 2, 0)); + next2EndVol[0]->AddNode( + cfStavSideVol, 2, new TGeoCombiTrans(-halfFrameWidth, -triangleHeight / 2, 0, new TGeoRotation("", 90, 180, -90))); + + next2EndVol[1]->AddNode(cfStavSideVol, 1, new TGeoTranslation(halfFrameWidth, -triangleHeight / 2, 0)); + next2EndVol[1]->AddNode( + cfStavSideVol, 2, new TGeoCombiTrans(-halfFrameWidth, -triangleHeight / 2, 0, new TGeoRotation("", 90, 180, -90))); + + endVol[0]->AddNode(cfStavSideVol, 1, new TGeoTranslation(halfFrameWidth, -triangleHeight / 2, 0)); + endVol[0]->AddNode(cfStavSideVol, 2, + new TGeoCombiTrans(-halfFrameWidth, -triangleHeight / 2, 0, new TGeoRotation("", 90, 180, -90))); + + endVol[1]->AddNode(cfStavSideVol, 1, new TGeoTranslation(halfFrameWidth, -triangleHeight / 2, 0)); + endVol[1]->AddNode(cfStavSideVol, 2, + new TGeoCombiTrans(-halfFrameWidth, -triangleHeight / 2, 0, new TGeoRotation("", 90, 180, -90))); + + //--- The beams + // Ribs on the sides + Double_t ribZProj = triangleHeight / TMath::Tan(sidePhiRad); + Double_t sideRibLen = + TMath::Sqrt(ribZProj * ribZProj + triangleHeight * triangleHeight + halfFrameWidth * halfFrameWidth); + + TGeoTubeSeg* sideRib = new TGeoTubeSeg(0, sideRibRadius, sideRibLen / 2, 0, 180); + TGeoVolume* sideRibVol = new TGeoVolume("CFstavSideBeamVol", sideRib, medCarbon); + sideRibVol->SetLineColor(35); + + TGeoCombiTrans* sideTransf[4]; + xpos = halfFrameWidth / 2 + 0.8 * staveHa * TMath::Cos(alphaRad / 2); + ypos = -sideRibRadius / 2; + zpos = unitlen / 4; + + sideTransf[0] = new TGeoCombiTrans(xpos, ypos, -zpos, new TGeoRotation("", 90 - alphaDeg, -sidePhiDeg, -90)); + sideTransf[1] = new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 90 - alphaDeg, sidePhiDeg, -90)); + sideTransf[2] = new TGeoCombiTrans(-xpos, ypos, -zpos, new TGeoRotation("", 90 + alphaDeg, sidePhiDeg, -90)); + sideTransf[3] = new TGeoCombiTrans(-xpos, ypos, zpos, new TGeoRotation("", 90 + alphaDeg, -sidePhiDeg, -90)); + + unitVol[0]->AddNode(sideRibVol, 1, sideTransf[0]); + unitVol[0]->AddNode(sideRibVol, 2, sideTransf[1]); + unitVol[0]->AddNode(sideRibVol, 3, sideTransf[2]); + unitVol[0]->AddNode(sideRibVol, 4, sideTransf[3]); + + unitVol[1]->AddNode(sideRibVol, 1, sideTransf[0]); + unitVol[1]->AddNode(sideRibVol, 2, sideTransf[1]); + unitVol[1]->AddNode(sideRibVol, 3, sideTransf[2]); + unitVol[1]->AddNode(sideRibVol, 4, sideTransf[3]); + + next2EndVol[0]->AddNode(sideRibVol, 1, sideTransf[0]); + next2EndVol[0]->AddNode(sideRibVol, 2, sideTransf[1]); + next2EndVol[0]->AddNode(sideRibVol, 3, sideTransf[2]); + next2EndVol[0]->AddNode(sideRibVol, 4, sideTransf[3]); + + next2EndVol[1]->AddNode(sideRibVol, 1, sideTransf[0]); + next2EndVol[1]->AddNode(sideRibVol, 2, sideTransf[1]); + next2EndVol[1]->AddNode(sideRibVol, 3, sideTransf[2]); + next2EndVol[1]->AddNode(sideRibVol, 4, sideTransf[3]); + + endVol[0]->AddNode(sideRibVol, 1, sideTransf[0]); + endVol[0]->AddNode(sideRibVol, 2, sideTransf[1]); + endVol[0]->AddNode(sideRibVol, 3, sideTransf[2]); + endVol[0]->AddNode(sideRibVol, 4, sideTransf[3]); + + endVol[1]->AddNode(sideRibVol, 1, sideTransf[0]); + endVol[1]->AddNode(sideRibVol, 2, sideTransf[1]); + endVol[1]->AddNode(sideRibVol, 3, sideTransf[2]); + endVol[1]->AddNode(sideRibVol, 4, sideTransf[3]); + + // Ribs on the bottom + // Rib1 are the inclined ones, Rib2 the straight ones + Double_t baseRibLen = 0.98 * 2 * halfFrameWidth / TMath::Sin(basePhiRad); + + TGeoTubeSeg* baseRib1 = new TGeoTubeSeg(0, baseRibRadius, baseRibLen / 2, 0, 180); + TGeoVolume* baseRib1Vol = new TGeoVolume("CFstavBaseBeam1Vol", baseRib1, medCarbon); + baseRib1Vol->SetLineColor(35); + + TGeoTubeSeg* baseRib2 = new TGeoTubeSeg(0, baseRibRadius, halfFrameWidth, 0, 90); + TGeoVolume* baseRib2Vol = new TGeoVolume("CFstavBaseBeam2Vol", baseRib2, medCarbon); + baseRib2Vol->SetLineColor(35); + + TGeoTubeSeg* baseEndRib = new TGeoTubeSeg(0, baseRibRadius, halfFrameWidth, 0, 180); + TGeoVolume* baseEndRibVol = new TGeoVolume("CFstavBaseEndBeamVol", baseEndRib, medCarbon); + baseEndRibVol->SetLineColor(35); + + TGeoCombiTrans* baseTransf[6]; + ypos = triangleHeight / 2; + zpos = unitlen / 2; + + baseTransf[0] = new TGeoCombiTrans("", 0, -ypos, -zpos, new TGeoRotation("", 90, 90, 90)); + baseTransf[1] = new TGeoCombiTrans("", 0, -ypos, zpos, new TGeoRotation("", -90, 90, -90)); + baseTransf[2] = new TGeoCombiTrans(0, -ypos, 0, new TGeoRotation("", -90, basePhiDeg, -90)); + baseTransf[3] = new TGeoCombiTrans(0, -ypos, 0, new TGeoRotation("", -90, -basePhiDeg, -90)); + zpos -= baseEndRib->GetRmax(); + baseTransf[4] = new TGeoCombiTrans("", 0, -ypos, -zpos, new TGeoRotation("", 90, 90, 90)); + baseTransf[5] = new TGeoCombiTrans("", 0, -ypos, zpos, new TGeoRotation("", 90, 90, 90)); + + unitVol[0]->AddNode(baseRib2Vol, 1, baseTransf[0]); + unitVol[0]->AddNode(baseRib2Vol, 2, baseTransf[1]); + unitVol[0]->AddNode(baseRib1Vol, 1, baseTransf[2]); + + unitVol[1]->AddNode(baseRib2Vol, 1, baseTransf[0]); + unitVol[1]->AddNode(baseRib2Vol, 2, baseTransf[1]); + unitVol[1]->AddNode(baseRib1Vol, 1, baseTransf[3]); + + next2EndVol[0]->AddNode(baseRib2Vol, 1, baseTransf[0]); + next2EndVol[0]->AddNode(baseRib2Vol, 2, baseTransf[1]); + next2EndVol[0]->AddNode(baseRib1Vol, 1, baseTransf[3]); + + next2EndVol[1]->AddNode(baseRib2Vol, 1, baseTransf[0]); + next2EndVol[1]->AddNode(baseRib2Vol, 2, baseTransf[1]); + next2EndVol[1]->AddNode(baseRib1Vol, 1, baseTransf[3]); + + endVol[0]->AddNode(baseEndRibVol, 1, baseTransf[4]); + endVol[0]->AddNode(baseRib2Vol, 1, baseTransf[1]); + endVol[0]->AddNode(baseRib1Vol, 1, baseTransf[2]); + + endVol[1]->AddNode(baseEndRibVol, 1, baseTransf[5]); + endVol[1]->AddNode(baseRib2Vol, 1, baseTransf[0]); + endVol[1]->AddNode(baseRib1Vol, 1, baseTransf[2]); + + // The Space Frame connectors + ypos = -triangleHeight / 2 + cfStavSide->GetY(3); + zpos = unitlen / 2; + createOBSpaceFrameConnector(endVol[0], ypos, zpos, kFALSE); // Side C + createOBSpaceFrameConnector(endVol[1], ypos, zpos, kTRUE); // Side A + + // U-Legs + // The shorter + xtru[0] = ulegHalfLen; + ytru[0] = 0; + xtru[1] = xtru[0]; + ytru[1] = -ulegHigh1; + xtru[2] = xtru[1] - ulegThick; + ytru[2] = ytru[1]; + xtru[3] = xtru[2]; + ytru[3] = ytru[0] - ulegThick; + for (Int_t i = 0; i < 4; i++) { // Reflect on the X negative side + xtru[i + 4] = -xtru[3 - i]; + ytru[i + 4] = ytru[3 - i]; + } + + TGeoXtru* uleg1full = new TGeoXtru(2); // This will go in the next end units + uleg1full->DefinePolygon(8, xtru, ytru); + uleg1full->DefineSection(0, -ulegHalfWidth); + uleg1full->DefineSection(1, ulegHalfWidth); + + TGeoXtru* uleg1half = new TGeoXtru(2); // This will go in the middle unitys + uleg1half->DefinePolygon(8, xtru, ytru); + uleg1half->DefineSection(0, -ulegHalfWidth / 2); + uleg1half->DefineSection(1, ulegHalfWidth / 2); + + TGeoVolume* uleg1fullVol = new TGeoVolume("CFstavULeg1FullVol", uleg1full, medF6151B05M); + uleg1fullVol->SetLineColor(35); + + TGeoVolume* uleg1halfVol = new TGeoVolume("CFstavULeg1HalfVol", uleg1half, medF6151B05M); + uleg1halfVol->SetLineColor(35); + + // The longer + ytru[1] = -ulegHigh2; + ytru[2] = -ulegHigh2; + ytru[5] = -ulegHigh2; + ytru[6] = -ulegHigh2; + + TGeoXtru* uleg2full = new TGeoXtru(2); // This will go in the next end units + uleg2full->DefinePolygon(8, xtru, ytru); + uleg2full->DefineSection(0, -ulegHalfWidth); + uleg2full->DefineSection(1, ulegHalfWidth); + + TGeoXtru* uleg2half = new TGeoXtru(2); // This will go in the middle unitys + uleg2half->DefinePolygon(8, xtru, ytru); + uleg2half->DefineSection(0, -ulegHalfWidth / 2); + uleg2half->DefineSection(1, ulegHalfWidth / 2); + + TGeoVolume* uleg2fullVol = new TGeoVolume("CFstavULeg2FullVol", uleg2full, medF6151B05M); + uleg2fullVol->SetLineColor(35); + + TGeoVolume* uleg2halfVol = new TGeoVolume("CFstavULeg2HalfVol", uleg2half, medF6151B05M); + uleg2halfVol->SetLineColor(35); + + xpos = sOBSFrameULegXPos; + ypos = triangleHeight / 2 + baseRibRadius; + zpos = unitlen / 2 - uleg1half->GetZ(1); + + unitVol[0]->AddNode(uleg1halfVol, 1, // Shorter on +X + new TGeoTranslation(xpos, -ypos, -zpos)); + unitVol[0]->AddNode(uleg1halfVol, 2, new TGeoTranslation(xpos, -ypos, zpos)); + + unitVol[1]->AddNode(uleg1halfVol, 1, new TGeoTranslation(xpos, -ypos, -zpos)); + unitVol[1]->AddNode(uleg1halfVol, 2, new TGeoTranslation(xpos, -ypos, zpos)); + + unitVol[0]->AddNode(uleg2halfVol, 1, // Longer on -X + new TGeoTranslation(-xpos, -ypos, -zpos)); + unitVol[0]->AddNode(uleg2halfVol, 2, new TGeoTranslation(-xpos, -ypos, zpos)); + + unitVol[1]->AddNode(uleg2halfVol, 1, new TGeoTranslation(-xpos, -ypos, -zpos)); + unitVol[1]->AddNode(uleg2halfVol, 2, new TGeoTranslation(-xpos, -ypos, zpos)); + + next2EndVol[0]->AddNode(uleg1halfVol, 1, new TGeoTranslation(xpos, -ypos, zpos)); + next2EndVol[0]->AddNode(uleg2halfVol, 1, new TGeoTranslation(-xpos, -ypos, zpos)); + + next2EndVol[1]->AddNode(uleg1halfVol, 1, new TGeoTranslation(xpos, -ypos, -zpos)); + next2EndVol[1]->AddNode(uleg2halfVol, 1, new TGeoTranslation(-xpos, -ypos, -zpos)); + + zpos = unitlen / 2 - uleg1full->GetZ(1); + next2EndVol[0]->AddNode(uleg1fullVol, 1, new TGeoTranslation(xpos, -ypos, -zpos)); + next2EndVol[0]->AddNode(uleg2fullVol, 1, new TGeoTranslation(-xpos, -ypos, -zpos)); + + next2EndVol[1]->AddNode(uleg1fullVol, 1, new TGeoTranslation(xpos, -ypos, zpos)); + next2EndVol[1]->AddNode(uleg2fullVol, 1, new TGeoTranslation(-xpos, -ypos, zpos)); + + // Done + return; +} + +void V3Layer::createOBSpaceFrameConnector(TGeoVolume* mother, const Double_t ymot, const Double_t zmot, const Bool_t sideA, const TGeoManager* mgr) +{ + // + // Creates the OB Space Frame Connectors + // (ALIITSUP0070+ALIITSUP0069) + // + // Input: + // mother : the SF unit volume to contain the connector + // ymot : the Y position of the connector in the mother volume + // zmot : the Z position of the connector in the mother volume + // sideA : true for Side A, false for Side C + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 09 Sep 2019 M. Sitta + + // Materials defined in AliITSUv2 + TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + + // Local parameters + TString connName, compoShape; + + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + Double_t xtru[6], ytru[6]; + + // The external (higher) part: a Xtru + ylen = sOBSFrameConnTotHei - sOBSFrameConnInsHei; + + xtru[0] = sOBSFrameConnWidth / 2.; + ytru[0] = 0.; + xtru[1] = xtru[0]; + ytru[1] = sOBSFrameConnInsHei; + xtru[2] = xtru[1] - ylen; // Because side is at 45' so dx = dy + ytru[2] = sOBSFrameConnTotHei; + for (Int_t i = 0; i < 3; i++) { // Reflect on the X negative side + xtru[i + 3] = -xtru[2 - i]; + ytru[i + 3] = ytru[2 - i]; + } + + TGeoXtru* topConn = new TGeoXtru(2); + topConn->SetName("connectorTop"); + topConn->DefinePolygon(6, xtru, ytru); + topConn->DefineSection(0, 0.); + topConn->DefineSection(1, sOBSFrameConnTopLen); + + // The insert: a Xtru + zlen = sOBSFrameConnTotLen - sOBSFrameConnTopLen; + + xtru[0] = sOBSFrameConnInsBase / 2.; + ytru[0] = 0.; + xtru[1] = sOBSFrameConnInsWide / 2.; + ytru[1] = sOBSFrameConnInsHei; + xtru[2] = -xtru[1]; + ytru[2] = ytru[1]; + xtru[3] = -xtru[0]; + ytru[3] = ytru[0]; + + TGeoXtru* insConn = new TGeoXtru(2); + insConn->SetName("connectorIns"); + insConn->DefinePolygon(4, xtru, ytru); + insConn->DefineSection(0, -zlen); + insConn->DefineSection(1, 0.); + + // The holes in the external (higher) part: Tube's and a BBox + TGeoTube* topHoleR = new TGeoTube("topholer", 0., sOBSFrameConnTopHoleD / 2., 1.1 * sOBSFrameConnTotHei); + + xpos = sOBSFrConnTopHoleXDist / 2.; + ypos = sOBSFrameConnTotHei / 2.; + zpos = sOBSFrameConnTopLen - sOBSFrameConnHoleZPos; + TGeoCombiTrans* topHoleR1Trans = new TGeoCombiTrans("topholer1tr", xpos, ypos, zpos, new TGeoRotation("", 0, 90, 0)); + topHoleR1Trans->RegisterYourself(); + + TGeoCombiTrans* topHoleR2Trans = new TGeoCombiTrans("topholer2tr", -xpos, ypos, zpos, new TGeoRotation("", 0, 90, 0)); + topHoleR2Trans->RegisterYourself(); + + xpos = sOBSFrConnCHoleXDist / 2.; + zpos = sOBSFrameConnTopLen - sOBSFrameConnCHoleZPos; + TGeoCombiTrans* topCHoleR1Trans = new TGeoCombiTrans("topcholer1tr", xpos, ypos, zpos, new TGeoRotation("", 0, 90, 0)); + topCHoleR1Trans->RegisterYourself(); + + TGeoCombiTrans* topCHoleR2Trans = new TGeoCombiTrans("topcholer2tr", -xpos, ypos, zpos, new TGeoRotation("", 0, 90, 0)); + topCHoleR2Trans->RegisterYourself(); + + TGeoBBox* topAHole = new TGeoBBox("topahole", sOBSFrameConnAHoleWid / 2., sOBSFrameConnTotHei, sOBSFrameConnAHoleLen / 2.); + + zpos = sOBSFrameConnTopLen - sOBSFrameConnHoleZPos; + TGeoTranslation* topAHoleTrans = new TGeoTranslation("topaholetr", 0, ypos, zpos); + topAHoleTrans->RegisterYourself(); + + TGeoTube* topCHole = new TGeoTube("topchole", 0., sOBSFrConnCTopHoleD / 2., sOBSFrameConnTotHei); + + TGeoCombiTrans* topCHoleTrans = new TGeoCombiTrans("topcholetr", 0, ypos, zpos, new TGeoRotation("", 0, 90, 0)); + topCHoleTrans->RegisterYourself(); + + TGeoTube* topASide = new TGeoTube("topaside", 0., sOBSFrConnASideHoleD / 2., 1.1 * sOBSFrConnASideHoleL); + + zpos = sOBSFrameConnTopLen + topASide->GetDz() - sOBSFrConnASideHoleL; + TGeoTranslation* topASideTrans = new TGeoTranslation("topasidetr", 0, sOBSFrConnASideHoleY, zpos); + topASideTrans->RegisterYourself(); + + // The holes in the insert: a Tube + TGeoTube* insHole = new TGeoTube("inshole", 0., sOBSFrameConnInsHoleD / 2., sOBSFrameConnInsHei); + + xpos = sOBSFrameConnInsHoleX / 2.; + ypos = sOBSFrameConnInsHei / 2.; + zpos = sOBSFrameConnTopLen - sOBSFrameConnHoleZPos - sOBSFrameConnHoleZDist; + TGeoCombiTrans* insHole1Trans = new TGeoCombiTrans("inshole1tr", xpos, ypos, zpos, new TGeoRotation("", 0, 90, 0)); + insHole1Trans->RegisterYourself(); + + TGeoCombiTrans* insHole2Trans = new TGeoCombiTrans("inshole2tr", -xpos, ypos, zpos, new TGeoRotation("", 0, 90, 0)); + insHole2Trans->RegisterYourself(); + + // The connector: a CompositeShape + if (sideA) { + connName = "OBSFConnectorA"; + compoShape = "(connectorTop-topholer:topholer2tr-topholer:topholer1tr-topahole:topaholetr-topaside:topasidetr)+(connectorIns-inshole:inshole1tr-inshole:inshole2tr)"; + } else { + connName = "OBSFConnectorC"; + compoShape = "(connectorTop-topholer:topholer2tr-topholer:topholer1tr-topholer:topcholer1tr-topholer:topcholer2tr-topchole:topcholetr)+(connectorIns-inshole:inshole1tr-inshole:inshole2tr)"; + } + + TGeoCompositeShape* obsfConnSh = new TGeoCompositeShape(compoShape.Data()); + + TGeoVolume* obsfConnVol = new TGeoVolume(connName, obsfConnSh, medPEEK); + + // Finally put the connector into its mother volume + mother->AddNode(obsfConnVol, 1, new TGeoTranslation(0, ymot, zmot)); +} + +TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) +{ + // + // Creates the OB Module: HIC + FPC + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // the module as a TGeoVolume + // + // Created: 18 Dec 2013 M. Sitta, A. Barbano + // Updated: 26 Feb 2014 M. Sitta + // Updated: 12 Nov 2014 M. Sitta Model2 is w/o Carbon Plate and Glue + // and Cu instead of Al + // Updated: 20 Jul 2017 M. Sitta O2 version + // Updated: 30 Jul 2018 M. Sitta Updated geometry + // + + const Int_t nameLen = 30; + char chipName[nameLen], sensName[nameLen], volName[nameLen]; + + Double_t xGap = sOBChipXGap; + Double_t zGap = sOBChipZGap; + + Double_t xchip, ychip, zchip; + Double_t xlen, ylen, zlen; + Double_t xpos, ypos, zpos; + + Bool_t dummyChip; + + // First create all needed shapes + + // For material budget studies + if (mBuildLevel < 7) + dummyChip = kFALSE; // will be made of Si + else + dummyChip = kTRUE; // will be made of Air + + // The chip (the same as for IB) + snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); + snprintf(sensName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + + ylen = 0.5 * sOBChipThickness; + + TGeoVolume* chipVol = AlpideChip::createChip(ylen, mSensorThickness / 2, chipName, sensName, dummyChip); + + xchip = (static_cast<TGeoBBox*>(chipVol->GetShape()))->GetDX(); + ychip = (static_cast<TGeoBBox*>(chipVol->GetShape()))->GetDY(); + zchip = (static_cast<TGeoBBox*>(chipVol->GetShape()))->GetDZ(); + + mOBModuleZLength = 2 * zchip * sOBChipsPerRow + (sOBChipsPerRow - 1) * sOBChipZGap; + + zlen = mOBModuleZLength / 2; + + // The glue + xlen = (4 * xchip + xGap) / 2; + ylen = sOBGlueFPCThick / 2; + TGeoBBox* glueFPC = new TGeoBBox("GlueFPC", xlen, ylen, zlen); + + ylen = sOBGlueColdPlThick / 2; + TGeoBBox* glueCP = new TGeoBBox("GlueCP", xlen, ylen, zlen); + + // The FPC cables + xlen = sOBFlexCableXWidth / 2; + ylen = sOBFlexCableKapThick / 2; + TGeoBBox* flexKap = new TGeoBBox("MidFlexKap", xlen, ylen, zlen); + + TGeoVolume* cuGndCableVol = createOBFPCCuGnd(zlen); + TGeoVolume* cuSignalCableVol = createOBFPCCuSig(zlen); + + // The module + Double_t ygnd = (static_cast<TGeoBBox*>(cuGndCableVol->GetShape()))->GetDY(); + Double_t ysig = (static_cast<TGeoBBox*>(cuSignalCableVol->GetShape()))->GetDY(); + + xlen = (static_cast<TGeoBBox*>(cuGndCableVol->GetShape()))->GetDX(); + ylen = glueCP->GetDY() + ychip + glueFPC->GetDY() + ysig + flexKap->GetDY() + ygnd; + TGeoBBox* module = new TGeoBBox("OBModule", xlen, ylen, zlen); + + // We have all shapes: now create the real volumes + + TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + + TGeoVolume* glueFPCVol = new TGeoVolume("GlueFPCVol", glueFPC, medGlue); + glueFPCVol->SetLineColor(kBlack); + glueFPCVol->SetFillColor(glueFPCVol->GetLineColor()); + glueFPCVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* glueCPVol = new TGeoVolume("GlueColdPlVol", glueCP, medGlue); + glueCPVol->SetLineColor(kBlack); + glueCPVol->SetFillColor(glueCPVol->GetLineColor()); + glueCPVol->SetFillStyle(4000); // 0% transparent + + TGeoVolume* flexKapVol = new TGeoVolume("FPCMidKapVol", flexKap, medKapton); + flexKapVol->SetLineColor(kGreen); + flexKapVol->SetFillColor(flexKapVol->GetLineColor()); + flexKapVol->SetFillStyle(4000); // 0% transparent + + snprintf(volName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + TGeoVolume* modVol = new TGeoVolume(volName, module, medAir); + modVol->SetVisibility(kTRUE); + + // Now build up the module + ypos = -module->GetDY() + glueCP->GetDY(); + + if (mBuildLevel < 3) // Glue + modVol->AddNode(glueCPVol, 1, new TGeoTranslation(0, ypos, 0)); + + xpos = xchip + xGap / 2; + ypos += (ychip + glueCP->GetDY()); + // We use two loops here to have the same chip numbering as in HW + // X ^ | 6| 5| 4| 3| 2| 1| 0| + // ----|--------------------------> Z + // | | 7| 8| 9|10|11|12|13| + // + for (Int_t k = 0; k < sOBChipsPerRow; k++) // put first 7 chip row + { + zpos = module->GetDZ() - zchip - k * (2 * zchip + zGap); + modVol->AddNode(chipVol, k, new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 0, 180, 180))); + mHierarchy[kChip] += 1; + } + + for (Int_t k = 0; k < sOBChipsPerRow; k++) // put second 7 chip row + { + zpos = -module->GetDZ() + zchip + k * (2 * zchip + zGap); + modVol->AddNode(chipVol, k + sOBChipsPerRow, new TGeoTranslation(-xpos, ypos, zpos)); + mHierarchy[kChip] += 1; + } + + ypos += (ychip + glueFPC->GetDY()); + if (mBuildLevel < 3) // Glue + modVol->AddNode(glueFPCVol, 1, new TGeoTranslation(0, ypos, 0)); + ypos += glueFPC->GetDY(); + + if (mBuildLevel < 5) { // Kapton + ypos += ysig; + modVol->AddNode(cuSignalCableVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (ysig + flexKap->GetDY()); + modVol->AddNode(flexKapVol, 1, new TGeoTranslation(0, ypos, 0)); + + ypos += (flexKap->GetDY() + ygnd); + modVol->AddNode(cuGndCableVol, 1, new TGeoTranslation(0, ypos, 0)); + } + + // Done, return the module + return modVol; +} + +TGeoVolume* V3Layer::createOBFPCCuGnd(const Double_t zcable, const TGeoManager* mgr) +{ + // + // Create the OB FPC Copper Ground cable + // + // Input: + // zcable : the cable half Z length + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // the FPC cable as a TGeoVolume + // + // Created: 30 Jul 2018 Mario Sitta + // + + Double_t xcable, ytot, ypos; + + // First create all needed shapes + xcable = sOBFlexCableXWidth / 2; + ytot = sOBFPCSoldMaskThick + sOBFPCCopperThick; + TGeoBBox* soldmask = new TGeoBBox(xcable, ytot / 2, zcable); + xcable *= sOBFPCCuAreaFracGnd; + TGeoBBox* copper = new TGeoBBox(xcable, sOBFPCCopperThick / 2, zcable); + + // Then the volumes + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medCopper = mgr->GetMedium("IT4_COPPER$"); + + TGeoVolume* soldmaskVol = new TGeoVolume("FPCGndSolderMask", soldmask, medKapton); + soldmaskVol->SetLineColor(kBlue); + soldmaskVol->SetFillColor(kBlue); + + TGeoVolume* copperVol = new TGeoVolume("FPCCopperGround", copper, medCopper); + copperVol->SetLineColor(kCyan); + copperVol->SetFillColor(kCyan); + + ypos = -soldmask->GetDY() + copper->GetDY(); + if (mBuildLevel < 1) // Copper + soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + + return soldmaskVol; +} + +TGeoVolume* V3Layer::createOBFPCCuSig(const Double_t zcable, const TGeoManager* mgr) +{ + // + // Create the OB FPC Copper Signal cable + // + // Input: + // zcable : the cable half Z length + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // the FPC cable as a TGeoVolume + // + // Created: 30 Jul 2018 Mario Sitta + // + + Double_t xcable, ytot, ypos; + + // First create all needed shapes + xcable = sOBFlexCableXWidth / 2; + ytot = sOBFPCSoldMaskThick + sOBFPCCopperThick; + TGeoBBox* soldmask = new TGeoBBox(xcable, ytot / 2, zcable); + xcable *= sOBFPCCuAreaFracSig; + TGeoBBox* copper = new TGeoBBox(xcable, sOBFPCCopperThick / 2, zcable); + + // Then the volumes + TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medCopper = mgr->GetMedium("IT4_COPPER$"); + + TGeoVolume* soldmaskVol = new TGeoVolume("FPCSigSolderMask", soldmask, medKapton); + soldmaskVol->SetLineColor(kBlue); + soldmaskVol->SetFillColor(kBlue); + + TGeoVolume* copperVol = new TGeoVolume("FPCCopperSignal", copper, medCopper); + copperVol->SetLineColor(kCyan); + copperVol->SetFillColor(kCyan); + + ypos = soldmask->GetDY() - copper->GetDY(); + if (mBuildLevel < 1) // Copper + soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + + return soldmaskVol; +} + +Double_t V3Layer::getGammaConversionRodDiam() +{ + // + // Gets the diameter of the gamma conversion rods, if defined + // + // + // Input: + // + // Output: + // + // Return: + // the diameter of the gamma conversion rods for this layer + // + // Created: 26 Oct 2016 Mario Sitta + // + + if (!mAddGammaConv) { + LOG(WARNING) << "Gamma Conversion rods not defined for this layer"; + } + return mGammaConvDiam; +} + +Double_t V3Layer::getGammaConversionRodXPos() +{ + // + // Gets the X position of the gamma conversion rods, if defined + // + // + // Input: + // + // Output: + // + // Return: + // the X position of the gamma conversion rods for this layer + // in the Half Stave reference system + // + // Created: 26 Oct 2016 Mario Sitta + // + + if (!mAddGammaConv) { + LOG(WARNING) << "Gamma Conversion rods not defined for this layer"; + } + return mGammaConvXPos; +} + +Double_t V3Layer::radiusOmTurboContainer() +{ + Double_t rr, delta, z, lstav, rstav; + + if (mChipThickness > 89.) { // Very big angle: avoid overflows since surely + return -1; // the radius from lower vertex is the right value + } + + rstav = mLayerRadius + 0.5 * mChipThickness; + delta = (0.5 * mChipThickness) / cosD(mStaveTilt); + z = (0.5 * mChipThickness) * tanD(mStaveTilt); + + rr = rstav - delta; + lstav = (0.5 * mStaveWidth) - z; + + if ((rr * sinD(mStaveTilt) < lstav)) { + return (rr * cosD(mStaveTilt)); + } else { + return -1; + } +} + +void V3Layer::setNumberOfUnits(Int_t u) +{ + if (mLayerNumber < mNumberOfInnerLayers) { + mNumberOfChips = u; + } else { + mNumberOfModules = u; + mNumberOfChips = sOBChipsPerRow; + } +} + +void V3Layer::setStaveTilt(const Double_t t) +{ + if (mIsTurbo) { + mStaveTilt = t; + } else { + LOG(ERROR) << "Not a Turbo layer"; + } +} + +void V3Layer::setStaveWidth(const Double_t w) +{ + if (mIsTurbo) { + mStaveWidth = w; + } else { + LOG(ERROR) << "Not a Turbo layer"; + } +} + +TGeoXtru* V3Layer::createStaveSide(const char* name, Double_t dz, Double_t alpha, Double_t beta, Double_t L, Double_t H, + Bool_t top) +{ + // + // Creates the V-shaped sides of the OB space frame + // (from a similar method with same name and function + // in AliITSv11GeometrySDD class by L.Gaudichet) + // + // Updated: 15 Dec 2014 Mario Sitta Rewritten using Xtru + // Updated: 09 Jan 2015 Mario Sitta Rewritten again using different + // aperture angles (info by C.Gargiulo) + // Updated: 21 Jul 2017 Mario Sitta O2 version + // + + // Create the V shape corner of CF stave + + const Int_t nv = 6; + Double_t xv[nv], yv[nv]; + + TGeoXtru* cfStavSide = new TGeoXtru(2); + cfStavSide->SetName(name); + + Double_t theta = TMath::PiOver2() - beta; + Double_t gamma = beta - alpha; + // Points must be in clockwise order + if (top) { // TOP - vertices not in order + xv[3] = 0; + yv[3] = 0; + xv[2] = L * TMath::Sin(alpha); + yv[2] = -L * TMath::Cos(alpha); + xv[1] = xv[2] - H * TMath::Cos(alpha); + yv[1] = yv[2] - H * TMath::Sin(alpha); + xv[0] = 0; + yv[0] = yv[1] + TMath::Tan(theta) * xv[1]; + xv[4] = -xv[2]; // Reflect + yv[4] = yv[2]; + xv[5] = -xv[1]; + yv[5] = yv[1]; + } else { // SIDE + Double_t m = -TMath::Tan(alpha), n = TMath::Tan(gamma); + xv[0] = 0; + yv[0] = 0; + xv[1] = -L * TMath::Cos(2 * alpha); + yv[1] = L * TMath::Sin(2 * alpha); + xv[2] = xv[1] - H * TMath::Sin(2 * alpha); + yv[2] = yv[1] - H * TMath::Cos(2 * alpha); + xv[4] = -L; + yv[4] = H; + xv[5] = xv[4]; + yv[5] = 0; + xv[3] = (yv[4] - n * xv[4]) / (m - n); + yv[3] = m * xv[3]; + } + + cfStavSide->DefinePolygon(nv, xv, yv); + cfStavSide->DefineSection(0, -dz); + cfStavSide->DefineSection(1, dz); + + return cfStavSide; +} + +TGeoCombiTrans* V3Layer::createCombiTrans(const char* name, Double_t dy, Double_t dz, Double_t dphi, Bool_t planeSym) +{ + TGeoTranslation t1(dy * cosD(90. + dphi), dy * sinD(90. + dphi), dz); + TGeoRotation r1("", 0., 0., dphi); + TGeoRotation r2("", 90, 180, -90 - dphi); + + TGeoCombiTrans* combiTrans1 = new TGeoCombiTrans(name); + combiTrans1->SetTranslation(t1); + if (planeSym) { + combiTrans1->SetRotation(r1); + } else { + combiTrans1->SetRotation(r2); + } + return combiTrans1; +} + +void V3Layer::addTranslationToCombiTrans(TGeoCombiTrans* ct, Double_t dx, Double_t dy, Double_t dz) const +{ + // Add a dx,dy,dz translation to the initial TGeoCombiTrans + const Double_t* vect = ct->GetTranslation(); + Double_t newVect[3] = {vect[0] + dx, vect[1] + dy, vect[2] + dz}; + ct->SetTranslation(newVect); +} diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx new file mode 100644 index 0000000000000..f78117f351ff1 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx @@ -0,0 +1,2340 @@ +// 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 V3Services.cxx +/// \brief Implementation of the V3Services class +/// \author Mario Sitta <sitta@to.infn.it> +/// \author Parinya Namwongsa <parinya.namwongsa@cern.ch> + +#include "ITS4Simulation/V3Services.h" +#include "ITS4Simulation/V11Geometry.h" +#include "ITS4Base/GeometryTGeo.h" +#include "ITS4Simulation/Detector.h" +#include "ITSMFTSimulation/AlpideChip.h" + +#include "FairLogger.h" // for LOG + +//#include <TGeoArb8.h> // for TGeoArb8 +#include <TGeoBBox.h> // for TGeoBBox +#include <TGeoCone.h> // for TGeoConeSeg, TGeoCone +#include <TGeoPcon.h> // for TGeoPcon +#include <TGeoManager.h> // for TGeoManager, gGeoManager +#include <TGeoMatrix.h> // for TGeoCombiTrans, TGeoRotation, etc +//#include <TGeoTrd1.h> // for TGeoTrd1 +#include <TGeoTube.h> // for TGeoTube, TGeoTubeSeg +#include <TGeoVolume.h> // for TGeoVolume, TGeoVolumeAssembly +#include <TGeoXtru.h> // for TGeoXtru +#include <TGeoCompositeShape.h> // for TGeoCompositeShape +#include "TMathBase.h" // for Abs +#include <TMath.h> // for Sin, RadToDeg, DegToRad, Cos, Tan, etc + +#include <cstdio> // for snprintf + +class TGeoMedium; + +using namespace TMath; +using namespace o2::its4; + +// Parameters +const Double_t V3Services::sIBWheelACZdist = 306.0 * sMm; +const Double_t V3Services::sIBCYSSFlangeCZPos = 171.5 * sMm; // Computed from different drawings +const Double_t V3Services::sOBWheelThickness = 2.0 * sMm; +const Double_t V3Services::sMBWheelsZpos = 457.0 * sMm; +const Double_t V3Services::sOBWheelsZpos = 770.0 * sMm; +const Double_t V3Services::sOBConesZpos = 798.0 * sMm; + +ClassImp(V3Services); + +#define SQ(A) (A) * (A) + +V3Services::V3Services() + : V11Geometry() +{ +} + +V3Services::~V3Services() = default; + +TGeoVolume* V3Services::createIBEndWheelsSideA(const TGeoManager* mgr) +{ + // + // Creates the Inner Barrel End Wheels on Side A + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // a TGeoVolume(Assembly) with all the wheels + // + // Created: 19 Jun 2019 Mario Sitta + // (partially based on P.Namwongsa implementation in AliRoot) + // + + TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideA"); + endWheelsVol->SetVisibility(kTRUE); + + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + ibEndWheelSideA(jLay, endWheelsVol, mgr); + + // Return the wheels + return endWheelsVol; +} + +TGeoVolume* V3Services::createIBEndWheelsSideC(const TGeoManager* mgr) +{ + // + // Creates the Inner Barrel End Wheels on Side C + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // a TGeoVolume(Assembly) with all the wheels + // + // Created: 15 May 2019 Mario Sitta + // (partially based on P.Namwongsa implementation in AliRoot) + // + + TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideC"); + endWheelsVol->SetVisibility(kTRUE); + + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + ibEndWheelSideC(jLay, endWheelsVol, mgr); + + // Return the wheels + return endWheelsVol; +} + +TGeoVolume* V3Services::createCYSSAssembly(const TGeoManager* mgr) +{ + // + // Creates the CYSS Assembly (i.e. the supporting cylinder and cone) + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // a TGeoVolume(Assembly) with all the elements + // + // Created: 21 Oct 2019 Mario Sitta + // Updated: 02 Dec 2019 Mario Sitta Full cylinder implemented + // + + static const Double_t sCyssFlangeAZpos = 9.0 * sMm; + static const Double_t sCyssFlangeCZpos = 1.0 * sMm; + + Double_t zlen, zpos; + + TGeoVolume* cyssVol = new TGeoVolumeAssembly("IBCYSSAssembly"); + cyssVol->SetVisibility(kTRUE); + + TGeoVolume* cyssCylinder = ibCyssCylinder(mgr); + zlen = (static_cast<TGeoTubeSeg*>(cyssCylinder->GetShape()))->GetDz(); + zpos = sIBCYSSFlangeCZPos - sCyssFlangeCZpos - zlen; + cyssVol->AddNode(cyssCylinder, 1, new TGeoTranslation(0, 0, -zpos)); + cyssVol->AddNode(cyssCylinder, 2, new TGeoCombiTrans(0, 0, -zpos, new TGeoRotation("", 180, 0, 0))); + + TGeoVolume* cyssCone = ibCyssCone(mgr); + zpos = -zpos + zlen - (static_cast<TGeoPcon*>(cyssCone->GetShape()))->GetZ(2); + cyssVol->AddNode(cyssCone, 1, new TGeoTranslation(0, 0, zpos)); + cyssVol->AddNode(cyssCone, 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 0, 0))); + + TGeoVolume* cyssFlangeA = ibCyssFlangeSideA(mgr); + Int_t nZPlanes = (static_cast<TGeoPcon*>(cyssCone->GetShape()))->GetNz(); + zpos = zpos + (static_cast<TGeoPcon*>(cyssCone->GetShape()))->GetZ(nZPlanes - 1) + sCyssFlangeAZpos; + cyssVol->AddNode(cyssFlangeA, 1, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 180, 0))); + cyssVol->AddNode(cyssFlangeA, 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 0, 180, 0))); + + TGeoVolume* cyssFlangeC = ibCyssFlangeSideC(mgr); + zpos = sIBCYSSFlangeCZPos; + cyssVol->AddNode(cyssFlangeC, 1, new TGeoTranslation(0, 0, -zpos)); + cyssVol->AddNode(cyssFlangeC, 2, new TGeoCombiTrans(0, 0, -zpos, new TGeoRotation("", 180, 0, 0))); + + // Return the whole assembly + return cyssVol; +} + +void V3Services::createMBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Middle Barrel End Wheels on Side A + // + // Input: + // mother : the volume hosting the wheels + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 24 Sep 2019 Mario Sitta + // + + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + obEndWheelSideA(jLay, mother, mgr); +} + +void V3Services::createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Middle Barrel End Wheels on Side C + // + // Input: + // mother : the volume hosting the wheels + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 26 Sep 2019 Mario Sitta + // + + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + mbEndWheelSideC(jLay, mother, mgr); +} + +void V3Services::createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Outer Barrel End Wheels on Side A + // + // Input: + // mother : the volume hosting the wheels + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 27 Sep 2019 Mario Sitta + // + + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + obEndWheelSideA(jLay + sNumberMiddlLayers, mother, mgr); +} + +void V3Services::createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Outer Barrel End Wheels on Side C + // + // Input: + // mother : the volume hosting the wheels + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 27 Sep 2019 Mario Sitta + // + + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + obEndWheelSideC(jLay, mother, mgr); +} + +void V3Services::createOBConeSideA(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Outer Barrel Cone on Side A + // + // Input: + // mother : the volume hosting the cones + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 03 Feb 2020 Mario Sitta + // + + obConeSideA(mother, mgr); + obConeTraysSideA(mother, mgr); +} + +void V3Services::createOBConeSideC(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Outer Barrel Cone on Side C + // + // Input: + // mother : the volume hosting the cones + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 26 Jan 2020 Mario Sitta + // + + obConeSideC(mother, mgr); +} + +void V3Services::ibEndWheelSideA(const Int_t iLay, TGeoVolume* endWheel, const TGeoManager* mgr) +{ + // + // Creates the single End Wheel on Side A + // for a given layer of the Inner Barrel + // (Layer 0: ALIITSSUP0183+ALIITSUP0127) + // (Layer 1: ALIITSSUP0173+ALIITSUP0124) + // (Layer 2: ALIITSSUP0139+ALIITSUP0125) + // + // Input: + // iLay : the layer number + // endWheel : the whole end wheel volume + // where to place the current created wheel + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 19 Jun 2019 Mario Sitta + // (partially based on P.Namwongsa implementation in AliRoot) + // + + // The Basis Cone A Side and the Reinforcement C Side are physically two + // different pieces put together. For sake of simplicity here they are + // made out of the same TGeoPcon volume. Moreover they are two halves, + // so here they are made as a single cone. + static const Double_t sConeATotalLength[3] = {191.0 * sMm, 184.0 * sMm, 177 * sMm}; + static const Double_t sConeAIntSectZlen1[3] = {40.35 * sMm, 39.0 * sMm, 36.0 * sMm}; + static const Double_t sConeAIntSectZlen2[3] = {47.0 * sMm, 44.0 * sMm, 41.0 * sMm}; + static const Double_t sConeAIntSectDmin[3] = {55.8 * sMm, 71.8 * sMm, 87.8 * sMm}; + static const Double_t sConeAIntSectDmax[3] = {57.0 * sMm, 73.0 * sMm, 89.0 * sMm}; + static const Double_t sConeAExtSectZlen1[3] = {60.0 * sMm, 47.0 * sMm, 44.0 * sMm}; + static const Double_t sConeAExtSectZlen2[3] = {66.0 * sMm, 52.0 * sMm, 50.0 * sMm}; + static const Double_t sConeAExtSectDmin[3] = {114.0 * sMm, 174.0 * sMm, 234.0 * sMm}; + static const Double_t sConeAExtSectDmax[3] = {116.0 * sMm, 176.0 * sMm, 236.0 * sMm}; + static const Double_t sConeASectThicker = 0.8 * sMm; + static const Double_t sConeAOpeningAngle[3] = {20.0, 30.0, 40.2}; // Deg + + static const Int_t sConeAWallNHoles[3] = {6, 8, 10}; + static const Double_t sConeAWallHoleD = 4.5 * sMm; + static const Double_t sConeAWallHoleZpos = 4.0 * sMm; + + static const Double_t sConeACentralHole1D = 3.0 * sMm; + static const Double_t sConeACentralHole2D = 3.4 * sMm; + static const Double_t sConeACentralHole3D = 3.0 * sMm; + static const Double_t sConeACentralHole1Z = 20.0 * sMm; + static const Double_t sConeACentralHole2Z = 30.0 * sMm; + static const Double_t sConeACentralHole3Z[3] = {177.0 * sMm, 170.0 * sMm, 163.0 * sMm}; + + // The Cone Reinforcement + static const Double_t sConeARenfDmin[3] = {54.3 * sMm, 69.85 * sMm, 85.0 * sMm}; + static const Double_t sConeARenfZlen = 2.5 * sMm; + static const Double_t sConeARenfZpos = 14.5 * sMm; + + // The Middle Ring + static const Double_t sConeAMidRingDmin[3] = {56.0 * sMm, 116.0 * sMm, 176.0 * sMm}; + static const Double_t sConeAMidRingDmax[3] = {58.0 * sMm, 118.0 * sMm, 178.0 * sMm}; + static const Double_t sConeAMidRingZlen = 42.0 * sMm; + + static const Double_t sConeAMidRingZpos[3] = {5.0 * sMm, 0.0 * sMm, 0.0 * sMm}; + + // The Ribs + static const Int_t sConeANRibs[3] = {6, 8, 10}; + static const Double_t sConeARibsZpos = 17.0 * sMm; + + // The End Wheel Steps + static const Double_t sConeAStepXdispl[3] = {4.0 * sMm, 6.5 * sMm, 8.5 * sMm}; + static const Double_t sConeAStepYdispl[3] = {24.4 * sMm, 32.1 * sMm, 39.6 * sMm}; + static const Double_t sConeAStepR[3] = {27.8 * sMm, 35.8 * sMm, 43.8 * sMm}; + + static const Double_t sConeAStepZlen = 14.0 * sMm; + + static const Double_t sConeAStepHoleXpos = 3.0 * sMm; + static const Double_t sConeAStepHoleZpos = 4.0 * sMm; + static const Double_t sConeAStepHoleZdist = 4.0 * sMm; + + static const Double_t sConeAStepHolePhi[3] = {30.0, 22.5, 18.0}; // Deg + static const Double_t sConeAStepHolePhi0[3] = {0.7, -16.2, -10.5}; // Deg + + // Local variables + Double_t xlen, ylen, zlen; + Double_t rmin, rmax, thick, phimin, dphi; + Double_t xpos, ypos, zpos, zref; + + // Create the whole cone (Basic + Reinforcement) as a CompositeShape + // (a single Pcon minus the holes) + TGeoPcon* coneabasis = new TGeoPcon(Form("coneabasis%d", iLay), 0, 360, 15); + + rmin = sConeAIntSectDmin[iLay] / 2; + rmax = sConeAIntSectDmax[iLay] / 2; + coneabasis->DefineSection(0, 0., rmin, rmax); + zpos = sConeARenfZpos; + coneabasis->DefineSection(1, zpos, rmin, rmax); + rmin = sConeARenfDmin[iLay] / 2; + coneabasis->DefineSection(2, zpos, rmin, rmax); + zpos += sConeARenfZlen; + coneabasis->DefineSection(3, zpos, rmin, rmax); + rmin = coneabasis->GetRmin(0); + coneabasis->DefineSection(4, zpos, rmin, rmax); + coneabasis->DefineSection(5, sConeAIntSectZlen1[iLay], rmin, rmax); + rmax += sConeASectThicker; + coneabasis->DefineSection(6, sConeAIntSectZlen1[iLay], rmin, rmax); + coneabasis->DefineSection(7, sConeAIntSectZlen2[iLay], rmin, rmax); + rmin = coneabasis->GetRmax(1); + coneabasis->DefineSection(8, sConeAIntSectZlen2[iLay], rmin, rmax); + rmin = sConeAExtSectDmin[iLay] / 2 - sConeASectThicker; + rmax = sConeAExtSectDmin[iLay] / 2; + zlen = sConeAIntSectZlen2[iLay] + (rmin - coneabasis->GetRmin(4)) / TMath::Tan(sConeAOpeningAngle[iLay] * TMath::DegToRad()); + coneabasis->DefineSection(9, zlen, rmin, rmax); + zlen = sConeATotalLength[iLay] - sConeAExtSectZlen2[iLay]; + coneabasis->DefineSection(10, zlen, rmin, rmax); + rmax = sConeAExtSectDmax[iLay] / 2; + coneabasis->DefineSection(11, zlen, rmin, rmax); + zlen = sConeATotalLength[iLay] - sConeAExtSectZlen1[iLay]; + coneabasis->DefineSection(12, zlen, rmin, rmax); + rmin = sConeAExtSectDmin[iLay] / 2; + coneabasis->DefineSection(13, zlen, rmin, rmax); + coneabasis->DefineSection(14, sConeATotalLength[iLay], rmin, rmax); + + TString coneAComposite = Form("coneabasis%d", iLay); + + // The holes in the vertical wall + thick = coneabasis->GetRmax(0) - coneabasis->GetRmin(0); + TGeoTube* coneawallhole = new TGeoTube(Form("coneawallhole%d", iLay), 0, sConeAWallHoleD / 2, 4 * thick); + + rmin = sConeAIntSectDmax[iLay] / 2 - thick / 2; + zpos = sConeAWallHoleZpos; + dphi = 180. / sConeAWallNHoles[iLay]; + phimin = dphi / 2.; + for (Int_t ihole = 0; ihole < 2 * sConeAWallNHoles[iLay]; ihole++) { + Double_t phi = phimin + ihole * dphi; + xpos = rmin * TMath::Sin(phi * TMath::DegToRad()); + ypos = rmin * TMath::Cos(phi * TMath::DegToRad()); + TGeoCombiTrans* coneawhmat = new TGeoCombiTrans(Form("coneawhmat%dl%d", ihole, iLay), xpos, ypos, zpos, new TGeoRotation("", -phi, 90, 0)); + coneawhmat->RegisterYourself(); + coneAComposite += Form("-coneawallhole%d:coneawhmat%dl%d", iLay, ihole, iLay); + } + + // The central holes + TGeoTube* coneacenthole1 = new TGeoTube(Form("coneacenthole1l%d", iLay), 0, sConeACentralHole1D / 2, 4 * thick); + + TGeoCombiTrans* coneach1mat1 = new TGeoCombiTrans(Form("coneach1mat1l%d", iLay), 0, rmin, sConeACentralHole1Z, new TGeoRotation("", 0, 90, 0)); + coneach1mat1->RegisterYourself(); + TGeoCombiTrans* coneach1mat2 = new TGeoCombiTrans(Form("coneach1mat2l%d", iLay), 0, -rmin, sConeACentralHole1Z, new TGeoRotation("", 0, 90, 0)); + coneach1mat2->RegisterYourself(); + + coneAComposite += Form("-coneacenthole1l%d:coneach1mat1l%d-coneacenthole1l%d:coneach1mat2l%d", iLay, iLay, iLay, iLay); + + TGeoTube* coneacenthole2 = new TGeoTube(Form("coneacenthole2l%d", iLay), 0, sConeACentralHole2D / 2, 4 * thick); + + TGeoCombiTrans* coneach2mat1 = new TGeoCombiTrans(Form("coneach2mat1l%d", iLay), 0, rmin, sConeACentralHole2Z, new TGeoRotation("", 0, 90, 0)); + coneach2mat1->RegisterYourself(); + TGeoCombiTrans* coneach2mat2 = new TGeoCombiTrans(Form("coneach2mat2l%d", iLay), 0, -rmin, sConeACentralHole2Z, new TGeoRotation("", 0, 90, 0)); + coneach2mat2->RegisterYourself(); + + coneAComposite += Form("-coneacenthole2l%d:coneach2mat1l%d-coneacenthole2l%d:coneach2mat2l%d", iLay, iLay, iLay, iLay); + + TGeoTube* coneacenthole3 = new TGeoTube(Form("coneacenthole3l%d", iLay), 0, sConeACentralHole3D / 2, 4 * thick); + + rmin = sConeAExtSectDmax[iLay] / 2 - thick / 2; + TGeoCombiTrans* coneach3mat1 = new TGeoCombiTrans(Form("coneach3mat1l%d", iLay), 0, rmin, sConeACentralHole3Z[iLay], new TGeoRotation("", 0, 90, 0)); + coneach3mat1->RegisterYourself(); + TGeoCombiTrans* coneach3mat2 = new TGeoCombiTrans(Form("coneach3mat2l%d", iLay), 0, -rmin, sConeACentralHole3Z[iLay], new TGeoRotation("", 0, 90, 0)); + coneach3mat2->RegisterYourself(); + + coneAComposite += Form("-coneacenthole3l%d:coneach3mat1l%d-coneacenthole3l%d:coneach3mat2l%d", iLay, iLay, iLay, iLay); + + TGeoCompositeShape* coneABasisSh = new TGeoCompositeShape(coneAComposite.Data()); + + // The Middle Ring (a Tube) + rmin = sConeAMidRingDmin[iLay] / 2; + rmax = sConeAMidRingDmax[iLay] / 2; + zlen = sConeAMidRingZlen / 2; + TGeoTube* midRingSh = new TGeoTube(Form("midRingSh%d", iLay), rmin, rmax, zlen); + + // A Rib (a TGeoXtru) + TGeoXtru* coneARibSh = ibEndWheelARibShape(iLay); + + // Now the Step as a Composite Shape (subtraction of a Pcon from a BBox) + // (cutting volume should be slightly larger than desired region) + rmin = sConeAStepR[iLay]; + + xlen = TMath::Sqrt(rmin * rmin - sConeAStepYdispl[iLay] * sConeAStepYdispl[iLay]) - sConeAStepXdispl[iLay]; + ylen = TMath::Sqrt(rmin * rmin - sConeAStepXdispl[iLay] * sConeAStepXdispl[iLay]) - sConeAStepYdispl[iLay]; + TGeoBBox* stepBoxSh = new TGeoBBox(Form("stepBoxASh%d", iLay), xlen / 2, ylen / 2, sConeAStepZlen / 2); + + xpos = sConeAStepXdispl[iLay] + stepBoxSh->GetDX(); + ypos = sConeAStepYdispl[iLay] + stepBoxSh->GetDY(); + TGeoTranslation* stepBoxTr = new TGeoTranslation(Form("stepBoxATr%d", iLay), xpos, ypos, 0); + stepBoxTr->RegisterYourself(); + + phimin = 90. - TMath::ACos(sConeAStepYdispl[iLay] / rmin) * TMath::RadToDeg() - 5; + dphi = 90. - TMath::ASin(sConeAStepXdispl[iLay] / rmin) * TMath::RadToDeg() - phimin + 10; + rmax = rmin + 2 * stepBoxSh->GetDY(); + + TGeoPcon* stepPconSh = new TGeoPcon(Form("stepPconASh%d", iLay), phimin, dphi, 2); + stepPconSh->DefineSection(0, -1.05 * sConeAStepZlen / 2, rmin, rmax); + stepPconSh->DefineSection(1, 1.05 * sConeAStepZlen / 2, rmin, rmax); + + TGeoCompositeShape* stepASh = new TGeoCompositeShape(Form("stepBoxASh%d:stepBoxATr%d-stepPconASh%d", iLay, iLay, iLay)); + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + + TGeoVolume* coneABasisVol = new TGeoVolume(Form("ConeABasis%d", iLay), coneABasisSh, medCarbon); + coneABasisVol->SetFillColor(kBlue); + coneABasisVol->SetLineColor(kBlue); + + TGeoVolume* midRingVol = new TGeoVolume(Form("ConeAMidRing%d", iLay), midRingSh, medCarbon); + coneABasisVol->SetFillColor(kBlue); + coneABasisVol->SetLineColor(kBlue); + + TGeoVolume* coneARibVol = new TGeoVolume(Form("ConeARibVol%d", iLay), coneARibSh, medCarbon); + coneARibVol->SetFillColor(kBlue); + coneARibVol->SetLineColor(kBlue); + + TGeoVolume* stepAVol = new TGeoVolume(Form("ConeAStep%d", iLay), stepASh, medPEEK); + stepAVol->SetFillColor(kBlue); + stepAVol->SetLineColor(kBlue); + + // Finally put everything in the mother volume + // (origin of local coordinates is at smaller end of Cone Basis) + zref = sIBWheelACZdist / 2 - (sConeAStepHoleZpos + sConeAStepHoleZdist); + + zpos = zref; + endWheel->AddNode(coneABasisVol, 1, new TGeoTranslation(0, 0, zpos)); + + zpos = zref + sConeATotalLength[iLay] - sConeAMidRingZpos[iLay] - midRingSh->GetDz(); + endWheel->AddNode(midRingVol, 1, new TGeoTranslation(0, 0, zpos)); + + rmin = sConeAExtSectDmin[iLay] / 2 - 0.035; + zpos = zref + sConeATotalLength[iLay] - sConeARibsZpos; + dphi = 180. / sConeANRibs[iLay]; + for (Int_t irib = 0; irib < 2 * sConeANRibs[iLay]; irib++) { + Double_t phi = irib * dphi; + xpos = rmin * TMath::Sin(phi * TMath::DegToRad()); + ypos = rmin * TMath::Cos(phi * TMath::DegToRad()); + endWheel->AddNode(coneARibVol, 1, new TGeoCombiTrans(xpos, -ypos, zpos, new TGeoRotation("", 90 + phi, 90, -90))); + } + + // The position of the Steps is given wrt the holes (see eg. ALIITSUP0187) + dphi = 180. - sConeAStepHolePhi0[iLay]; + + Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(iLay); + zpos = zref + (static_cast<TGeoBBox*>(stepAVol->GetShape()))->GetDZ(); + for (Int_t j = 0; j < numberOfStaves; j++) { + Double_t phi = dphi + j * sConeAStepHolePhi[iLay]; + endWheel->AddNode(stepAVol, j + 1, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 180, -90 - phi))); + } +} + +void V3Services::ibEndWheelSideC(const Int_t iLay, TGeoVolume* endWheel, const TGeoManager* mgr) +{ + // + // Creates the single End Wheel on Side C + // for a given layer of the Inner Barrel + // (Layer 0: ALIITSSUP0186+ALIITSUP0126) + // (Layer 1: ALIITSSUP0176+ALIITSUP0123) + // (Layer 2: ALIITSSUP0143+ALIITSUP0121) + // + // Input: + // iLay : the layer number + // endWheel : the whole end wheel volume + // where to place the current created wheel + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 15 May 2019 Mario Sitta + // (partially based on P.Namwongsa implementation in AliRoot) + // + + // The Basis C Side and the Reinforcement C Side are physically two + // different pieces put together. For sake of simplicity here they are + // made out of the same TGeoPcon volume. Moreover they are two halves, + // so here they are made as a single cylinder. + // The End Wheel Basis + static const Double_t sEndWheelCDmax[3] = {57.0 * sMm, 73.0 * sMm, 89.0 * sMm}; + static const Double_t sEndWheelCDmin[3] = {44.5 * sMm, 58.0 * sMm, 74.0 * sMm}; + static const Double_t sEndWheelCHeigh[3] = {25.0 * sMm, 22.5 * sMm, 20.0 * sMm}; + static const Double_t sEndWheelCThick = 0.6 * sMm; + + static const Int_t sEndWCWallNHoles[3] = {6, 8, 10}; + static const Double_t sEndWCWallHoleD = 4.5 * sMm; + static const Double_t sEndWCWallHoleZpos = 4.0 * sMm; + + static const Int_t sEndWCBaseNBigHoles = 5; + static const Int_t sEndWCBaseNSmalHoles = 6; + static const Double_t sEndWCBaseBigHoleD = 3.6 * sMm; + static const Double_t sEndWCBaseSmalHoleD = 2.5 * sMm; + static const Double_t sEndWCBaseHolesDpos[3] = {50.0 * sMm, 64.0 * sMm, 80.0 * sMm}; + static const Double_t sEndWCBaseHolesPhi = 15.0; // Deg + + // The End Wheel Reinforcement + static const Double_t sEndWCRenfDmin[3] = {44.0 * sMm, 58.0 * sMm, 74.0 * sMm}; + static const Double_t sEndWCRenfDint[3] = {55.0 * sMm, 71.0 * sMm, 87.0 * sMm}; + static const Double_t sEndWCRenfHeigh[3] = {4.0 * sMm, 3.0 * sMm, 3.0 * sMm}; + static const Double_t sEndWCRenfThick = 0.6 * sMm; + + static const Double_t sEndWCRenfZpos = 14.2 * sMm; + + static const Int_t sEndWCRenfNSmalHoles[3] = {5, 7, 9}; + + // The End Wheel Steps + static const Double_t sEndWCStepXdispl[3] = {4.0 * sMm, 6.5 * sMm, 8.5 * sMm}; + static const Double_t sEndWCStepYdispl[3] = {24.4 * sMm, 32.1 * sMm, 39.6 * sMm}; + static const Double_t sEndWCStepR[3] = {27.8 * sMm, 35.8 * sMm, 43.8 * sMm}; + + static const Double_t sEndWCStepZlen = 14.0 * sMm; + + static const Double_t sEndWCStepHoleXpos = 3.0 * sMm; + static const Double_t sEndWCStepHoleZpos = 4.0 * sMm; + static const Double_t sEndWCStepHoleZdist = 4.0 * sMm; + + static const Double_t sEndWCStepHolePhi[3] = {30.0, 22.5, 18.0}; // Deg + static const Double_t sEndWCStepHolePhi0[2] = {9.5, 10.5}; // Deg + static const Double_t sEndWCStepYlow = 7.0 * sMm; + + // Local variables + Double_t xlen, ylen, zlen; + Double_t rmin, rmax, phimin, dphi; + Double_t xpos, ypos, zpos; + + // Create the whole wheel (Basic + Reinforcement) as a CompositeShape + // (a single Pcon minus the (copious!) holes) + TGeoPcon* endwcbasis = new TGeoPcon(Form("endwcbasis%d", iLay), 0, 360, 10); + + rmin = sEndWheelCDmax[iLay] / 2 - sEndWheelCThick; + endwcbasis->DefineSection(0, 0., rmin, sEndWheelCDmax[iLay] / 2); + endwcbasis->DefineSection(1, sEndWCRenfZpos, rmin, sEndWheelCDmax[iLay] / 2); + endwcbasis->DefineSection(2, sEndWCRenfZpos, sEndWCRenfDmin[iLay] / 2, sEndWheelCDmax[iLay] / 2); + zlen = sEndWCRenfZpos + sEndWCRenfThick; + endwcbasis->DefineSection(3, zlen, sEndWCRenfDmin[iLay] / 2, sEndWheelCDmax[iLay] / 2); + endwcbasis->DefineSection(4, zlen, sEndWCRenfDint[iLay] / 2, sEndWheelCDmax[iLay] / 2); + zlen = sEndWCRenfZpos + sEndWCRenfHeigh[iLay]; + endwcbasis->DefineSection(5, zlen, sEndWCRenfDint[iLay] / 2, sEndWheelCDmax[iLay] / 2); + endwcbasis->DefineSection(6, zlen, rmin, sEndWheelCDmax[iLay] / 2); + zlen = sEndWheelCHeigh[iLay] - sEndWheelCThick; + endwcbasis->DefineSection(7, zlen, rmin, sEndWheelCDmax[iLay] / 2); + endwcbasis->DefineSection(8, zlen, sEndWheelCDmin[iLay] / 2, sEndWheelCDmax[iLay] / 2); + endwcbasis->DefineSection(9, sEndWheelCHeigh[iLay], sEndWheelCDmin[iLay] / 2, sEndWheelCDmax[iLay] / 2); + + TString endWheelComposite = Form("endwcbasis%d", iLay); + + // The holes in the vertical wall + TGeoTube* endwcwalhol = new TGeoTube(Form("endwcwalhol%d", iLay), 0, sEndWCWallHoleD / 2, 4 * sEndWheelCThick); + + rmin = sEndWheelCDmax[iLay] / 2 - sEndWheelCThick / 2; + zpos = sEndWCWallHoleZpos; + dphi = 180. / sEndWCWallNHoles[iLay]; + phimin = dphi / 2.; + for (Int_t ihole = 0; ihole < 2 * sEndWCWallNHoles[iLay]; ihole++) { + Double_t phi = phimin + ihole * dphi; + xpos = rmin * TMath::Sin(phi * TMath::DegToRad()); + ypos = rmin * TMath::Cos(phi * TMath::DegToRad()); + TGeoCombiTrans* endwcwhmat = new TGeoCombiTrans(Form("endwcwhmat%dl%d", ihole, iLay), xpos, ypos, zpos, new TGeoRotation("", -phi, 90, 0)); + endwcwhmat->RegisterYourself(); + endWheelComposite += Form("-endwcwalhol%d:endwcwhmat%dl%d", iLay, ihole, iLay); + } + + // The holes in the base + TGeoTube* endwcbasBhol = new TGeoTube(Form("endwcbasBhol%d", iLay), 0, sEndWCBaseBigHoleD / 2, 1.5 * sEndWheelCThick); + + TGeoTube* endwcbasShol = new TGeoTube(Form("endwcbasShol%d", iLay), 0, sEndWCBaseSmalHoleD / 2, 1.5 * sEndWheelCThick); + + rmin = sEndWCBaseHolesDpos[iLay] / 2; + zpos = (endwcbasis->GetZ(8) + endwcbasis->GetZ(9)) / 2; + + char holename[strlen(endwcbasBhol->GetName()) + 1]; + + phimin = 0.; + for (Int_t ihole = 0; ihole < (sEndWCBaseNBigHoles + sEndWCBaseNSmalHoles); ihole++) { + phimin += sEndWCBaseHolesPhi; + xpos = rmin * TMath::Cos(phimin * TMath::DegToRad()); + ypos = rmin * TMath::Sin(phimin * TMath::DegToRad()); + TGeoTranslation* endwcbshmata = new TGeoTranslation(Form("endwcbshmat%dl%da", ihole, iLay), xpos, ypos, zpos); + endwcbshmata->RegisterYourself(); + TGeoTranslation* endwcbshmatb = new TGeoTranslation(Form("endwcbshmat%dl%db", ihole, iLay), -xpos, -ypos, zpos); + endwcbshmatb->RegisterYourself(); + if ((ihole > 1 && ihole < 5) || (ihole > 5 && ihole < 9)) // Small holes + strcpy(holename, endwcbasShol->GetName()); + else + strcpy(holename, endwcbasBhol->GetName()); + endWheelComposite += Form("-%s:endwcbshmat%dl%da-%s:endwcbshmat%dl%db", holename, ihole, iLay, holename, ihole, iLay); + } + + // The holes in the reinforcement + zpos = (endwcbasis->GetZ(2) + endwcbasis->GetZ(3)) / 2; + + phimin = 0.; + dphi = 180. / (sEndWCRenfNSmalHoles[iLay] + 1); + for (Int_t ihole = 0; ihole < sEndWCRenfNSmalHoles[iLay]; ihole++) { + phimin += dphi; + xpos = rmin * TMath::Cos(phimin * TMath::DegToRad()); + ypos = rmin * TMath::Sin(phimin * TMath::DegToRad()); + TGeoTranslation* endwcrshmata = new TGeoTranslation(Form("endwcrshmat%dl%da", ihole, iLay), xpos, ypos, zpos); + endwcrshmata->RegisterYourself(); + TGeoTranslation* endwcrshmatb = new TGeoTranslation(Form("endwcrshmat%dl%db", ihole, iLay), -xpos, -ypos, zpos); + endwcrshmatb->RegisterYourself(); + endWheelComposite += Form("-endwcbasShol%d:endwcrshmat%dl%da-endwcbasShol%d:endwcrshmat%dl%db", iLay, ihole, iLay, iLay, ihole, iLay); + } + + TGeoCompositeShape* endWheelCSh = new TGeoCompositeShape(endWheelComposite.Data()); + + // Now the Step as a Composite Shape (subtraction of a Pcon from a BBox) + // (cutting volume should be slightly larger than desired region) + rmin = sEndWCStepR[iLay]; + + xlen = TMath::Sqrt(rmin * rmin - sEndWCStepYdispl[iLay] * sEndWCStepYdispl[iLay]) - sEndWCStepXdispl[iLay]; + ylen = TMath::Sqrt(rmin * rmin - sEndWCStepXdispl[iLay] * sEndWCStepXdispl[iLay]) - sEndWCStepYdispl[iLay]; + TGeoBBox* stepBoxSh = new TGeoBBox(Form("stepBoxCSh%d", iLay), xlen / 2, ylen / 2, sEndWCStepZlen / 2); + + xpos = sEndWCStepXdispl[iLay] + stepBoxSh->GetDX(); + ypos = sEndWCStepYdispl[iLay] + stepBoxSh->GetDY(); + TGeoTranslation* stepBoxTr = new TGeoTranslation(Form("stepBoxCTr%d", iLay), xpos, ypos, 0); + stepBoxTr->RegisterYourself(); + + phimin = 90. - TMath::ACos(sEndWCStepYdispl[iLay] / rmin) * TMath::RadToDeg() - 5; + dphi = 90. - TMath::ASin(sEndWCStepXdispl[iLay] / rmin) * TMath::RadToDeg() - phimin + 10; + rmax = rmin + 2 * stepBoxSh->GetDY(); + + TGeoPcon* stepPconSh = new TGeoPcon(Form("stepPconCSh%d", iLay), phimin, dphi, 2); + stepPconSh->DefineSection(0, -1.05 * sEndWCStepZlen / 2, rmin, rmax); + stepPconSh->DefineSection(1, 1.05 * sEndWCStepZlen / 2, rmin, rmax); + + TGeoCompositeShape* stepCSh = new TGeoCompositeShape(Form("stepBoxCSh%d:stepBoxCTr%d-stepPconCSh%d", iLay, iLay, iLay)); + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + + TGeoVolume* endWheelCVol = new TGeoVolume(Form("EndWheelCBasis%d", iLay), endWheelCSh, medCarbon); + endWheelCVol->SetFillColor(kBlue); + endWheelCVol->SetLineColor(kBlue); + + TGeoVolume* stepCVol = new TGeoVolume(Form("EndWheelCStep%d", iLay), stepCSh, medPEEK); + stepCVol->SetFillColor(kBlue); + stepCVol->SetLineColor(kBlue); + + // Finally put everything in the mother volume + zpos = sIBWheelACZdist / 2 - (sEndWCStepHoleZpos + sEndWCStepHoleZdist); + endWheel->AddNode(endWheelCVol, 1, new TGeoCombiTrans(0, 0, -zpos, new TGeoRotation("", 0, 180, 0))); + + // The position of the Steps is given wrt the holes (see eg. ALIITSUP0187) + dphi = sEndWCStepHolePhi0[iLay]; + + Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(iLay); + zpos += (static_cast<TGeoBBox*>(stepCVol->GetShape()))->GetDZ(); + for (Int_t j = 0; j < numberOfStaves; j++) { + Double_t phi = dphi + j * sEndWCStepHolePhi[iLay]; + endWheel->AddNode(stepCVol, j + 1, new TGeoCombiTrans(0, 0, -zpos, new TGeoRotation("", 180, 180, -90 - phi))); + } +} + +TGeoXtru* V3Services::ibEndWheelARibShape(const Int_t iLay) +{ + // + // Creates the shape of a Rib on Side A cone + // (Layer 0: ALIITSSUP0182) + // (Layer 1: ALIITSSUP0172) + // (Layer 2: ALIITSSUP0136) + // + // Input: + // iLay : the layer number + // + // Output: + // + // Return: + // the Rib shape as a TGeoXtru + // + // Created: 23 Aug 2019 Mario Sitta + // + + static const Int_t sConeARibNVert = 8; + + static const Double_t sConeARibWidth = 27.3 * sMm; + static const Double_t sConeARibTotalLen[3] = {98.03 * sMm, 104.65 * sMm, 101.43 * sMm}; + static const Double_t sConeARibIntLen[3] = {50.0 * sMm, 40.0 * sMm, 28.5 * sMm}; + static const Double_t sConeARibStep[3] = {1.0 * sMm, 1.1 * sMm, 1.0 * sMm}; + static const Double_t sConeARibLenToStep[3] = {42.0 * sMm, 29.0 * sMm, 26.0 * sMm}; + static const Double_t sConeARibLenAfterStep[3] = {50.5 * sMm, 37.0 * sMm, 33.5 * sMm}; + static const Double_t sConeARibVertexPos[3] = {9.0 * sMm, 40.0 * sMm, 58.0 * sMm}; + static const Double_t sConeARibIntAngle = 45.0; // Deg + static const Double_t sConeARibVertexAngle[2] = {20.0, 30.0}; // Deg + + static const Double_t sConeARibThick = 0.9 * sMm; + + // Local variables + Double_t xtru[sConeARibNVert], ytru[sConeARibNVert]; + + // Rib shapes for Layer 0 and Layers 1,2 are different + xtru[0] = 0.; + ytru[0] = 0.; + xtru[1] = sConeARibLenToStep[iLay]; + ytru[1] = 0.; + xtru[2] = xtru[1]; + ytru[2] = sConeARibStep[iLay]; + xtru[3] = sConeARibLenAfterStep[iLay]; + ytru[3] = ytru[2]; + xtru[4] = sConeARibTotalLen[iLay]; + if (iLay == 0) { + ytru[4] = sConeARibWidth - sConeARibVertexPos[iLay]; + xtru[5] = sConeARibIntLen[iLay] + sConeARibVertexPos[iLay] / TMath::Tan(sConeARibIntAngle * TMath::DegToRad()); + } else { + ytru[4] = sConeARibVertexPos[iLay]; + xtru[5] = sConeARibIntLen[iLay] + (sConeARibVertexPos[iLay] - sConeARibWidth) / TMath::Tan(sConeARibVertexAngle[iLay - 1] * TMath::DegToRad()); + } + ytru[5] = ytru[4]; + xtru[6] = sConeARibIntLen[iLay]; + ytru[6] = sConeARibWidth; + xtru[7] = 0.; + ytru[7] = ytru[6]; + + // The actual Xtru + TGeoXtru* ribShape = new TGeoXtru(2); + ribShape->DefinePolygon(sConeARibNVert, xtru, ytru); + ribShape->DefineSection(0, -sConeARibThick / 2); + ribShape->DefineSection(1, sConeARibThick / 2); + + return ribShape; +} + +TGeoVolume* V3Services::ibCyssCylinder(const TGeoManager* mgr) +{ + // + // Creates the cylinder of the Inner Barrel CYSS + // (ALIITSUP0191) + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // the cylinder as a TGeoVolume + // + // Created: 21 Oct 2019 Mario Sitta + // + + static const Double_t sCyssCylInnerD = 95.6 * sMm; + static const Double_t sCyssCylOuterD = 100.0 * sMm; + static const Double_t sCyssCylZLength = 353.0 * sMm; + static const Double_t sCyssCylFabricThick = 0.1 * sMm; + + // Local variables + Double_t rmin, rmax, zlen, phimin, phimax, dphi; + + // First create the shapes + rmin = sCyssCylInnerD / 2; + rmax = sCyssCylOuterD / 2; + zlen = sCyssCylZLength / 2; + TGeoTubeSeg* cyssOuterCylSh = new TGeoTubeSeg(rmin, rmax, zlen, 180, 360); + + rmin += sCyssCylFabricThick; + rmax -= sCyssCylFabricThick; + zlen -= sCyssCylFabricThick; + + dphi = TMath::ASin(sCyssCylFabricThick / rmax); + phimin = 180 + dphi * TMath::RadToDeg(); + phimax = 360 - dphi * TMath::RadToDeg(); + + TGeoTubeSeg* cyssInnerCylSh = new TGeoTubeSeg(rmin, rmax, zlen, phimin, phimax); + + // We have all shapes: now create the real volumes + TGeoMedium* medPrepreg = mgr->GetMedium("IT4_F6151B05M$"); + TGeoMedium* medRohacell = mgr->GetMedium("IT4_ROHACELL$"); + + TGeoVolume* cyssOuterCylVol = new TGeoVolume("IBCYSSCylinder", cyssOuterCylSh, medPrepreg); + cyssOuterCylVol->SetLineColor(35); + + TGeoVolume* cyssInnerCylVol = new TGeoVolume("IBCYSSCylinderFoam", cyssInnerCylSh, medRohacell); + cyssInnerCylVol->SetLineColor(kGreen); + + cyssOuterCylVol->AddNode(cyssInnerCylVol, 1, nullptr); + + // Finally return the cylinder volume + return cyssOuterCylVol; +} + +TGeoVolume* V3Services::ibCyssCone(const TGeoManager* mgr) +{ + // + // Creates the cone of the Inner Barrel CYSS + // (ALIITSUP0190) + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // the cone as a TGeoVolume + // + // Created: 24 Oct 2019 Mario Sitta + // + + static const Double_t sCyssConeTotalLength = 150.0 * sMm; + + static const Double_t sCyssConeIntSectDmin = 100.0 * sMm; + static const Double_t sCyssConeIntSectDmax = 101.2 * sMm; + static const Double_t sCyssConeIntSectZlen = 23.0 * sMm; + static const Double_t sCyssConeIntCylZlen = 15.0 * sMm; + + static const Double_t sCyssConeExtSectDmin = 246.0 * sMm; + static const Double_t sCyssConeExtSectDmax = 257.2 * sMm; + static const Double_t sCyssConeExtSectZlen = 42.0 * sMm; + static const Double_t sCyssConeExtCylZlen = 40.0 * sMm; + + static const Double_t sCyssConeOpeningAngle = 40.0; // Deg + + static const Double_t sCyssConeFabricThick = 0.3 * sMm; + + // Local variables + Double_t rmin, rmax, zlen1, zlen2, phimin, phirot, dphi; + Double_t x1, y1, x2, y2, x3, y3, m, xin, yin; + + // The CYSS Cone is physically a single piece made by a cylindrical + // section, a conical section, and a second cylindrical section + // The cone and the second cylinder have a foam core + // Both are implemented as two Pcon's + + TGeoPcon* cyssConeSh = new TGeoPcon(180, 180, 6); + + rmin = sCyssConeIntSectDmin / 2; + rmax = sCyssConeIntSectDmax / 2; + cyssConeSh->DefineSection(0, 0, rmin, rmax); + cyssConeSh->DefineSection(1, sCyssConeIntCylZlen, rmin, rmax); + zlen1 = sCyssConeTotalLength - sCyssConeExtSectZlen; + rmax = yFrom2Points(sCyssConeIntCylZlen, sCyssConeIntSectDmax / 2, zlen1, sCyssConeExtSectDmax / 2, sCyssConeIntSectZlen); + cyssConeSh->DefineSection(2, sCyssConeIntSectZlen, rmin, rmax); + zlen2 = sCyssConeTotalLength - sCyssConeExtCylZlen; + rmin = yFrom2Points(sCyssConeIntSectZlen, sCyssConeIntSectDmin / 2, zlen2, sCyssConeExtSectDmin / 2, zlen1); + rmax = sCyssConeExtSectDmax / 2; + cyssConeSh->DefineSection(3, zlen1, rmin, rmax); + rmin = sCyssConeExtSectDmin / 2; + cyssConeSh->DefineSection(4, zlen2, rmin, rmax); + cyssConeSh->DefineSection(5, sCyssConeTotalLength, rmin, rmax); + + dphi = TMath::ASin(sCyssConeFabricThick / (0.5 * sCyssConeIntSectDmax)); + phimin = 180 + dphi * TMath::RadToDeg(); + phirot = 180 - 2 * dphi * TMath::RadToDeg(); + + // The foam cone is built from the points of the outer cone + TGeoPcon* cyssConeFoamSh = new TGeoPcon(phimin, phirot, 5); + + m = TMath::Tan(sCyssConeOpeningAngle * TMath::DegToRad()); + x1 = cyssConeSh->GetZ(2); + y1 = cyssConeSh->GetRmin(2); + x2 = cyssConeSh->GetZ(1); + y2 = cyssConeSh->GetRmin(1); + x3 = x1; + y3 = y2 + m * (x3 - x2); + + insidePoint(x1, y1, x2, y2, x3, y3, -sCyssConeFabricThick, xin, yin); + cyssConeFoamSh->DefineSection(0, xin, yin, yin); + + x3 = cyssConeSh->GetZ(3); + y3 = cyssConeSh->GetRmin(3); + + insidePoint(x3, y3, x1, y1, x2, y2, -sCyssConeFabricThick, xin, yin); + zlen1 = xin; + rmin = yin; + rmax = y2 + m * (zlen1 - x2); + cyssConeFoamSh->DefineSection(1, zlen1, rmin, rmax); + + x1 = cyssConeSh->GetZ(5); + y1 = cyssConeSh->GetRmax(5); + x2 = cyssConeSh->GetZ(3); + y2 = cyssConeSh->GetRmax(3); + x3 = cyssConeSh->GetZ(2); + y3 = cyssConeSh->GetRmax(2); + + insidePoint(x1, y1, x2, y2, x3, y3, -sCyssConeFabricThick, xin, yin); + zlen1 = xin; + rmin = cyssConeFoamSh->GetRmin(1) + m * (zlen1 - cyssConeFoamSh->GetZ(1)); + rmax = sCyssConeExtSectDmax / 2 - sCyssConeFabricThick; + cyssConeFoamSh->DefineSection(2, zlen1, rmin, rmax); + + rmin = sCyssConeExtSectDmin / 2 + sCyssConeFabricThick; + zlen1 = cyssConeSh->GetZ(4); + cyssConeFoamSh->DefineSection(3, zlen1, rmin, rmax); + + zlen1 = sCyssConeTotalLength - sCyssConeFabricThick; + cyssConeFoamSh->DefineSection(4, zlen1, rmin, rmax); + + // We have all shapes: now create the real volumes + TGeoMedium* medPrepreg = mgr->GetMedium("IT4_F6151B05M$"); + TGeoMedium* medRohacell = mgr->GetMedium("IT4_ROHACELL$"); + + TGeoVolume* cyssConeVol = new TGeoVolume("IBCYSSCone", cyssConeSh, medPrepreg); + cyssConeVol->SetLineColor(35); + + TGeoVolume* cyssConeFoamVol = new TGeoVolume("IBCYSSConeFoam", cyssConeFoamSh, medRohacell); + cyssConeFoamVol->SetLineColor(kGreen); + + cyssConeVol->AddNode(cyssConeFoamVol, 1, nullptr); + + // Finally return the cone volume + return cyssConeVol; +} + +TGeoVolume* V3Services::ibCyssFlangeSideA(const TGeoManager* mgr) +{ + // + // Creates the Flange on Side A for the Inner Barrel CYSS + // (ALIITSUP0189) + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // the flange as a TGeoVolume + // + // Created: 28 Oct 2019 Mario Sitta + // + + // Radii of the steps + static const Double_t sCyssFlangeAStep1Dmin = 254.1 * sMm; + static const Double_t sCyssFlangeAStep1Dmax = 287.0 * sMm; + static const Double_t sCyssFlangeAStep2Dmax = 259.0 * sMm; + static const Double_t sCyssFlangeAStep3Dmin = 243.0 * sMm; + static const Double_t sCyssFlangeAStep3Dmax = 245.5 * sMm; + static const Double_t sCyssFlangeAStep4Dmax = 239.0 * sMm; + static const Double_t sCyssFlangeAInnerD = 236.0 * sMm; + static const Double_t sCyssFlangeAInRingD = 238.0 * sMm; + + // Heights of the steps + static const Double_t sCyssFlangeATotHei = 39.0 * sMm; + static const Double_t sCyssFlangeAStep1H = 5.5 * sMm; + static const Double_t sCyssFlangeAInRingH = 7.0 * sMm; + static const Double_t sCyssFlangeAInRingUp = 1.0 * sMm; + static const Double_t sCyssFlangeAStep2H = 9.0 * sMm; + static const Double_t sCyssFlangeAStep3H = 10.0 * sMm; + static const Double_t sCyssFlangeAStep4H = 8.5 * sMm; + + // The wings + static const Double_t sCyssFlangeAWingD = 307.0 * sMm; + static const Double_t sCyssFlangeAWingW = 16.0 * sMm; + + // Holes + static const Double_t sCyssFlangeANotchW = 3.0 * sMm; + + static const Double_t sCyssFlangeAHolesDpos = 274.0 * sMm; + + static const Double_t sCyssFlangeAHole1Num = 8; + static const Double_t sCyssFlangeAHole1D = 5.5 * sMm; + static const Double_t sCyssFlangeAHole1Phi0 = 10; // Deg + static const Double_t sCyssFlangeAHole1PhiStep = 20; // Deg + + static const Double_t sCyssFlangeAHole2D = 4.0 * sMm; + static const Double_t sCyssFlangeAHole2Phi = 20; // Deg + + static const Double_t sCyssFlangeAHole3D = 7.0 * sMm; + static const Double_t sCyssFlangeAHole3Phi = 6; // Deg + + static const Double_t sCyssFlangeAWingHoleD = 8.1 * sMm; + static const Double_t sCyssFlangeAWingHoleYpos = 9.0 * sMm; + static const Double_t sCyssFlangeAWingHoleRpos = 146.0 * sMm; + + // Local variables + Double_t rmin, rmax, zlen, phi, dphi; + Double_t xpos, ypos; + + // The CYSS Flange on Side A is physically a single piece. + // It is implemented as a CompositeShape of two Pcon's and one TubeSeg + // minus a huge number of holes + + // The flange body + TGeoPcon* cyssFlangeABody = new TGeoPcon("cyssflangeabody", 180, 180, 12); + + rmin = sCyssFlangeAStep1Dmin / 2; + rmax = sCyssFlangeAStep1Dmax / 2; + cyssFlangeABody->DefineSection(0, 0, rmin, rmax); + cyssFlangeABody->DefineSection(1, sCyssFlangeAStep1H, rmin, rmax); + rmax = sCyssFlangeAStep2Dmax / 2; + cyssFlangeABody->DefineSection(2, sCyssFlangeAStep1H, rmin, rmax); + cyssFlangeABody->DefineSection(3, sCyssFlangeAInRingH, rmin, rmax); + rmin = sCyssFlangeAStep3Dmin / 2; + cyssFlangeABody->DefineSection(4, sCyssFlangeAInRingH, rmin, rmax); + cyssFlangeABody->DefineSection(5, sCyssFlangeAStep2H, rmin, rmax); + rmax = sCyssFlangeAStep3Dmax / 2; + cyssFlangeABody->DefineSection(6, sCyssFlangeAStep2H, rmin, rmax); + zlen = sCyssFlangeATotHei - sCyssFlangeAStep3H; + cyssFlangeABody->DefineSection(7, zlen, rmin, rmax); + rmin = sCyssFlangeAInnerD / 2; + cyssFlangeABody->DefineSection(8, zlen, rmin, rmax); + zlen = sCyssFlangeATotHei - sCyssFlangeAStep4H; + cyssFlangeABody->DefineSection(9, zlen, rmin, rmax); + rmax = sCyssFlangeAStep4Dmax / 2; + cyssFlangeABody->DefineSection(10, zlen, rmin, rmax); + cyssFlangeABody->DefineSection(11, sCyssFlangeATotHei, rmin, rmax); + + // The inner ring + // We define half of it and put two copies to leave the notch space + rmin = sCyssFlangeAStep3Dmin / 2; + phi = 0.5 * (sCyssFlangeANotchW / rmin) * TMath::RadToDeg(); + + TGeoPcon* cyssFlangeAInRing = new TGeoPcon("cflangearing", 180, 90 - phi, 4); + + rmin = sCyssFlangeAInnerD / 2; + rmax = sCyssFlangeAInRingD / 2; + cyssFlangeAInRing->DefineSection(0, sCyssFlangeAInRingUp, rmin, rmax); + cyssFlangeAInRing->DefineSection(1, sCyssFlangeAInRingH, rmin, rmax); + rmax = sCyssFlangeAStep3Dmin / 2; + cyssFlangeAInRing->DefineSection(2, sCyssFlangeAInRingH, rmin, rmax); + cyssFlangeAInRing->DefineSection(3, sCyssFlangeAStep2H, rmin, rmax); + + TGeoRotation* flangeARingRot = new TGeoRotation("cringrot", 90 + phi, 0, 0); + flangeARingRot->RegisterYourself(); + + TString cyssFlangeAComposite = Form("cyssflangeabody+cflangearing+cflangearing:cringrot"); + + // The wings + rmin = sCyssFlangeAStep1Dmax / 2; + rmax = sCyssFlangeAWingD / 2; + zlen = sCyssFlangeAStep1H / 2; + phi = 0.5 * (sCyssFlangeAWingW / rmin) * TMath::RadToDeg(); + + TGeoTubeSeg* cyssFlangeAWing = new TGeoTubeSeg("cflangeawing", rmin, rmax, zlen, 270 - phi, 270 + phi); + + TGeoTranslation* cwingTR1 = new TGeoTranslation("cwingtr1", 0, 0, zlen); + cwingTR1->RegisterYourself(); + + TGeoCombiTrans* cwingCT2 = new TGeoCombiTrans("cwingct2", 0, 0, zlen, new TGeoRotation("", 90 - phi, 0, 0)); + cwingCT2->RegisterYourself(); + + TGeoCombiTrans* cwingCT3 = new TGeoCombiTrans("cwingct3", 0, 0, zlen, new TGeoRotation("", -90 + phi, 0, 0)); + cwingCT3->RegisterYourself(); + + cyssFlangeAComposite += "+cflangeawing:cwingtr1+cflangeawing:cwingct2+cflangeawing:cwingct3"; + + // The (many) holes + zlen = cyssFlangeAWing->GetDz(); + + // The 8 round holes (4 on each side) + rmax = sCyssFlangeAHole1D / 2; + TGeoTube* hole1 = new TGeoTube("hole1", 0, rmax, 2 * zlen); + + for (Int_t i = 0; i < sCyssFlangeAHole1Num / 2; i++) { + Double_t phi = sCyssFlangeAHole1Phi0 + i * sCyssFlangeAHole1PhiStep; + xpos = 0.5 * sCyssFlangeAHolesDpos * TMath::Sin(phi * TMath::DegToRad()); + ypos = 0.5 * sCyssFlangeAHolesDpos * TMath::Cos(phi * TMath::DegToRad()); + TGeoTranslation* hole1Tr1 = new TGeoTranslation(Form("hole1Tr1%d", i), xpos, -ypos, zlen); + hole1Tr1->RegisterYourself(); + TGeoTranslation* hole1Tr2 = new TGeoTranslation(Form("hole1Tr2%d", i), -xpos, -ypos, zlen); + hole1Tr2->RegisterYourself(); + cyssFlangeAComposite += Form("-hole1:hole1Tr1%d-hole1:hole1Tr2%d", i, i); + } + + // The 2 smaller round holes (1 on each side) + rmax = sCyssFlangeAHole2D / 2; + TGeoTube* hole2 = new TGeoTube("hole2", 0, rmax, 2 * zlen); + + xpos = 0.5 * sCyssFlangeAHolesDpos * TMath::Sin(sCyssFlangeAHole2Phi * TMath::DegToRad()); + ypos = 0.5 * sCyssFlangeAHolesDpos * TMath::Cos(sCyssFlangeAHole2Phi * TMath::DegToRad()); + TGeoTranslation* hole2Tr1 = new TGeoTranslation("hole2Tr1", xpos, -ypos, zlen); + hole2Tr1->RegisterYourself(); + TGeoTranslation* hole2Tr2 = new TGeoTranslation("hole2Tr2", -xpos, -ypos, zlen); + hole2Tr2->RegisterYourself(); + + cyssFlangeAComposite += "-hole2:hole2Tr1-hole2:hole2Tr2"; + + // The 2 bigger round holes (1 on each side) + rmax = sCyssFlangeAHole3D / 2; + TGeoTube* hole3 = new TGeoTube("hole3", 0, rmax, 2 * zlen); + + xpos = 0.5 * sCyssFlangeAHolesDpos * TMath::Sin(sCyssFlangeAHole3Phi * TMath::DegToRad()); + ypos = 0.5 * sCyssFlangeAHolesDpos * TMath::Cos(sCyssFlangeAHole3Phi * TMath::DegToRad()); + TGeoTranslation* hole3Tr1 = new TGeoTranslation("hole3Tr1", xpos, -ypos, zlen); + hole3Tr1->RegisterYourself(); + TGeoTranslation* hole3Tr2 = new TGeoTranslation("hole3Tr2", -xpos, -ypos, zlen); + hole3Tr2->RegisterYourself(); + + cyssFlangeAComposite += "-hole3:hole3Tr1-hole3:hole3Tr2"; + + // The holes in the wings + rmax = sCyssFlangeAWingHoleD / 2; + TGeoTube* wingHole = new TGeoTube("wingHole", 0, rmax, 2 * zlen); + + TGeoTranslation* wingHoleTr1 = new TGeoTranslation("wingHoleTr1", 0, -sCyssFlangeAWingHoleRpos, zlen); + wingHoleTr1->RegisterYourself(); + + TGeoTranslation* wingHoleTr2 = new TGeoTranslation("wingHoleTr2", sCyssFlangeAWingHoleRpos, -sCyssFlangeAWingHoleYpos, zlen); + wingHoleTr2->RegisterYourself(); + + TGeoTranslation* wingHoleTr3 = new TGeoTranslation("wingHoleTr3", -sCyssFlangeAWingHoleRpos, -sCyssFlangeAWingHoleYpos, zlen); + wingHoleTr3->RegisterYourself(); + + cyssFlangeAComposite += "-wingHole:wingHoleTr1-wingHole:wingHoleTr2-wingHole:wingHoleTr3"; + + // Lastly the hollows (évidements): a nightmare deserving its own method + TString cyssFlangeAHollows = ibCreateHollowsCyssFlangeSideA(zlen); + + cyssFlangeAComposite += cyssFlangeAHollows.Data(); + + // The final flange shape + TGeoCompositeShape* cyssFlangeASh = new TGeoCompositeShape(cyssFlangeAComposite.Data()); + + // We have all shapes: now create the real volumes + TGeoMedium* medAlu = mgr->GetMedium("IT4_ALUMINUM$"); + + TGeoVolume* cyssFlangeAVol = new TGeoVolume("IBCYSSFlangeA", cyssFlangeASh, medAlu); + cyssFlangeAVol->SetLineColor(kCyan); + cyssFlangeAVol->SetFillColor(kCyan); + + // Finally return the flange volume + return cyssFlangeAVol; +} + +TString V3Services::ibCreateHollowsCyssFlangeSideA(const Double_t zlen) +{ + // + // Creates the very complicate hollow holes in the Flange + // on Side A for the Inner Barrel CYSS + // (ALIITSUP0189) + // + // Input: + // zlen : the thickness of the ring where the hollows are located + // + // Output: + // + // Return: + // the string describing the holes and their positions + // + // Created: 04 Nov 2019 Mario Sitta + // + + static const Double_t sCyssFlangeAHolesDpos = 274.0 * sMm; + + static const Double_t sCyssFlangeAHole1Phi0 = 10; // Deg + static const Double_t sCyssFlangeAHole1PhiStep = 20; // Deg + + static const Double_t sCyssFlangeAHole2Phi = 20; // Deg + + static const Double_t sCyssFlangeAHollowD = 7.0 * sMm; + static const Double_t sCyssFlangeAHollowPhi0 = 13; // Deg + static const Double_t sCyssFlangeAHollowPhi1 = 8; // Deg + + // Local variables + Double_t rmin, rmax, phi, dphi; + Double_t xpos, ypos; + + TString cyssFlangeAHollows; + + // + rmax = sCyssFlangeAHollowD / 2; + TGeoTubeSeg* roundHalf = new TGeoTubeSeg("roundhalf", 0, rmax, 2 * zlen, 0, 180); + + Double_t rHoles = sCyssFlangeAHolesDpos / 2; + + xpos = rHoles * TMath::Cos(sCyssFlangeAHollowPhi0 * TMath::DegToRad()); + ypos = rHoles * TMath::Sin(sCyssFlangeAHollowPhi0 * TMath::DegToRad()); + TGeoCombiTrans* roundTr1 = new TGeoCombiTrans("roundtr1", xpos, -ypos, zlen, new TGeoRotation("", -sCyssFlangeAHollowPhi0, 0, 0)); + roundTr1->RegisterYourself(); + TGeoCombiTrans* roundTr2 = new TGeoCombiTrans("roundtr2", -xpos, -ypos, zlen, new TGeoRotation("", sCyssFlangeAHollowPhi0, 0, 0)); + roundTr2->RegisterYourself(); + + cyssFlangeAHollows += "-roundhalf:roundtr1-roundhalf:roundtr2"; + + TGeoTranslation* noRot = new TGeoTranslation("norot", 0, 0, zlen); + noRot->RegisterYourself(); + TGeoCombiTrans* yRot180 = new TGeoCombiTrans("yrot180", 0, 0, zlen, new TGeoRotation("", 0, 180, 180)); + yRot180->RegisterYourself(); + + rmin = sCyssFlangeAHolesDpos / 2 - sCyssFlangeAHollowD / 2; + rmax = sCyssFlangeAHolesDpos / 2 + sCyssFlangeAHollowD / 2; + + for (Int_t j = 1; j < 4; j++) { + phi = 90 - (sCyssFlangeAHole1Phi0 + j * sCyssFlangeAHole1PhiStep + 0.5 * sCyssFlangeAHollowPhi1); + xpos = rHoles * TMath::Cos(phi * TMath::DegToRad()); + ypos = rHoles * TMath::Sin(phi * TMath::DegToRad()); + TGeoCombiTrans* roundTr3 = new TGeoCombiTrans(Form("roundtr%d", j + 2), xpos, -ypos, zlen, new TGeoRotation("", 180 - phi, 0, 0)); + roundTr3->RegisterYourself(); + TGeoCombiTrans* roundTr4 = new TGeoCombiTrans(Form("roundtr%d", j + 5), -xpos, -ypos, zlen, new TGeoRotation("", phi - 180, 0, 0)); + roundTr4->RegisterYourself(); + + cyssFlangeAHollows += Form("-roundhalf:roundtr%d-roundhalf:roundtr%d", j + 2, j + 5); + + phi = 360 - phi - 0.05; + if (j == 3) + dphi = 360 - sCyssFlangeAHollowPhi0 + 0.05; + else + dphi = phi + (sCyssFlangeAHole1PhiStep - sCyssFlangeAHollowPhi1) + 0.1; + + TGeoTubeSeg* hollow1 = new TGeoTubeSeg(Form("hollow%d", j), rmin, rmax, 2 * zlen, phi, dphi); + + cyssFlangeAHollows += Form("-hollow%d:norot-hollow%d:yrot180", j, j); + + phi = 90 - (sCyssFlangeAHole1Phi0 + j * sCyssFlangeAHole1PhiStep - 0.5 * sCyssFlangeAHollowPhi1); + xpos = rHoles * TMath::Cos(phi * TMath::DegToRad()); + ypos = rHoles * TMath::Sin(phi * TMath::DegToRad()); + TGeoCombiTrans* roundTr5 = new TGeoCombiTrans(Form("roundtr%d", j + 8), xpos, -ypos, zlen, new TGeoRotation("", -phi, 0, 0)); + roundTr5->RegisterYourself(); + TGeoCombiTrans* roundTr6 = new TGeoCombiTrans(Form("roundtr%d", j + 11), -xpos, -ypos, zlen, new TGeoRotation("", phi, 0, 0)); + roundTr6->RegisterYourself(); + + cyssFlangeAHollows += Form("-roundhalf:roundtr%d-roundhalf:roundtr%d", j + 8, j + 11); + } + + // + phi = 90 - (sCyssFlangeAHole2Phi + 0.5 * sCyssFlangeAHollowPhi1); + xpos = rHoles * TMath::Cos(phi * TMath::DegToRad()); + ypos = rHoles * TMath::Sin(phi * TMath::DegToRad()); + TGeoCombiTrans* roundTr15 = new TGeoCombiTrans("roundtr15", xpos, -ypos, zlen, new TGeoRotation("", 180 - phi, 0, 0)); + roundTr15->RegisterYourself(); + TGeoCombiTrans* roundTr16 = new TGeoCombiTrans("roundtr16", -xpos, -ypos, zlen, new TGeoRotation("", phi - 180, 0, 0)); + roundTr16->RegisterYourself(); + + cyssFlangeAHollows += "-roundhalf:roundtr15-roundhalf:roundtr16"; + + phi = 360 - phi - 0.5; + dphi = phi + (sCyssFlangeAHole1Phi0 + sCyssFlangeAHole1PhiStep - sCyssFlangeAHole2Phi - sCyssFlangeAHollowPhi1) + 0.5; + TGeoTubeSeg* hollow4 = new TGeoTubeSeg("hollow4", rmin, rmax, 2 * zlen, phi, dphi); + + cyssFlangeAHollows += "-hollow4:norot-hollow4:yrot180"; + + // + phi = 90 - (sCyssFlangeAHole2Phi - 0.5 * sCyssFlangeAHollowPhi1); + xpos = rHoles * TMath::Cos(phi * TMath::DegToRad()); + ypos = rHoles * TMath::Sin(phi * TMath::DegToRad()); + TGeoCombiTrans* roundTr17 = new TGeoCombiTrans("roundtr17", xpos, -ypos, zlen, new TGeoRotation("", -phi, 0, 0)); + roundTr17->RegisterYourself(); + TGeoCombiTrans* roundTr18 = new TGeoCombiTrans("roundtr18", -xpos, -ypos, zlen, new TGeoRotation("", phi, 0, 0)); + roundTr18->RegisterYourself(); + + cyssFlangeAHollows += "-roundhalf:roundtr17-roundhalf:roundtr18"; + + phi = 90 - (sCyssFlangeAHole1Phi0 + 0.5 * sCyssFlangeAHollowPhi1); + xpos = rHoles * TMath::Cos(phi * TMath::DegToRad()); + ypos = rHoles * TMath::Sin(phi * TMath::DegToRad()); + TGeoCombiTrans* roundTr19 = new TGeoCombiTrans("roundtr19", xpos, -ypos, zlen, new TGeoRotation("", 180 - phi, 0, 0)); + roundTr19->RegisterYourself(); + TGeoCombiTrans* roundTr20 = new TGeoCombiTrans("roundtr20", -xpos, -ypos, zlen, new TGeoRotation("", phi - 180, 0, 0)); + roundTr20->RegisterYourself(); + + cyssFlangeAHollows += "-roundhalf:roundtr19-roundhalf:roundtr20"; + + TGeoCombiTrans* zRotPhi = new TGeoCombiTrans("zrotphi", 0, 0, zlen, new TGeoRotation("", -sCyssFlangeAHole1Phi0, 0, 0)); + zRotPhi->RegisterYourself(); + TGeoCombiTrans* yzRot180Phi = new TGeoCombiTrans("yzrot180phi", 0, 0, zlen, new TGeoRotation("", 0, 180, 180 - sCyssFlangeAHole1Phi0)); + yzRot180Phi->RegisterYourself(); + + cyssFlangeAHollows += "-hollow4:zrotphi-hollow4:yzrot180phi"; + + // Finally we return the string + return cyssFlangeAHollows; +} + +TGeoVolume* V3Services::ibCyssFlangeSideC(const TGeoManager* mgr) +{ + // + // Creates the Flange on Side C for the Inner Barrel CYSS + // (ALIITSUP0098) + // + // Input: + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // the flange as a TGeoVolume + // + // Created: 23 Oct 2019 Mario Sitta + // + + // Radii of the rings + static const Double_t sCyssFlangeCDmin1 = 44.0 * sMm; + static const Double_t sCyssFlangeCDmin2 = 57.0 * sMm; + static const Double_t sCyssFlangeCDmin3 = 73.0 * sMm; + + static const Double_t sCyssFlangeCDmax1 = 58.8 * sMm; + static const Double_t sCyssFlangeCDmax2 = 74.8 * sMm; + static const Double_t sCyssFlangeCDmax3 = 94.0 * sMm; + + static const Double_t sCyssFlangeCDWallIn = 89.0 * sMm; + static const Double_t sCyssFlangeCDWallOut = 95.6 * sMm; + + static const Double_t sCyssFlangeCDExt = 100.0 * sMm; + + // Thicknesses and heights + static const Double_t sCyssFlangeCTotH = 10.0 * sMm; + static const Double_t sCyssFlangeCExtThick = 1.0 * sMm; + + static const Double_t sCyssFlangeCHmax1 = 1.5 * sMm; + static const Double_t sCyssFlangeCHmax2 = 4.0 * sMm; + static const Double_t sCyssFlangeCHmax3 = 6.5 * sMm; + + static const Double_t sCyssFlangeCHmin2 = 2.5 * sMm; + static const Double_t sCyssFlangeCHmin3 = 5.0 * sMm; + + // Holes + static const Double_t sHoles22Dia = 2.2 * sMm; + static const Double_t sHoles22Phi = 60; // Deg + + static const Double_t sHoles30Dia = 3.0 * sMm; + static const Double_t sHoles30Phi = 15; // Deg + + static const Double_t sHoles12Dia = 1.2 * sMm; + static const Double_t sHoles12Phi = 75; // Deg + + static const Double_t sHolesDdist[3] = {50.0 * sMm, 64.0 * sMm, 80.0 * sMm}; + + static const Double_t sCyssFlangeCNotchH = 3.2 * sMm; + static const Double_t sCyssFlangeCNotchW = 3.0 * sMm; + + // Local variables + Double_t rmin, rmax, zlen; + Double_t xpos, ypos; + + // The CYSS Flange on Side C is physically a single piece. + // It is implemented as a CompositeShape of two Pcon's minus the holes + + // The flange body + TGeoPcon* cyssFlangeCDisks = new TGeoPcon("cyssflangecdisks", 180, 180, 12); + + rmin = sCyssFlangeCDmin1 / 2; + rmax = sCyssFlangeCDmax1 / 2; + cyssFlangeCDisks->DefineSection(0, 0, rmin, rmax); + cyssFlangeCDisks->DefineSection(1, sCyssFlangeCHmax1, rmin, rmax); + rmin = sCyssFlangeCDmin2 / 2; + cyssFlangeCDisks->DefineSection(2, sCyssFlangeCHmax1, rmin, rmax); + cyssFlangeCDisks->DefineSection(3, sCyssFlangeCHmin2, rmin, rmax); + rmax = sCyssFlangeCDmax2 / 2; + cyssFlangeCDisks->DefineSection(4, sCyssFlangeCHmin2, rmin, rmax); + cyssFlangeCDisks->DefineSection(5, sCyssFlangeCHmax2, rmin, rmax); + rmin = sCyssFlangeCDmin3 / 2; + cyssFlangeCDisks->DefineSection(6, sCyssFlangeCHmax2, rmin, rmax); + cyssFlangeCDisks->DefineSection(7, sCyssFlangeCHmin3, rmin, rmax); + rmax = sCyssFlangeCDWallOut / 2; + cyssFlangeCDisks->DefineSection(8, sCyssFlangeCHmin3, rmin, rmax); + cyssFlangeCDisks->DefineSection(9, sCyssFlangeCHmax3, rmin, rmax); + rmin = sCyssFlangeCDWallIn / 2; + cyssFlangeCDisks->DefineSection(10, sCyssFlangeCHmax3, rmin, rmax); + cyssFlangeCDisks->DefineSection(11, sCyssFlangeCTotH, rmin, rmax); + + TGeoPcon* cyssFlangeCExt = new TGeoPcon("cflangecext", 180, 180, 4); + + rmin = sCyssFlangeCDmax3 / 2; + rmax = sCyssFlangeCDExt / 2; + cyssFlangeCExt->DefineSection(0, 0, rmin, rmax); + cyssFlangeCExt->DefineSection(1, sCyssFlangeCExtThick, rmin, rmax); + rmax = sCyssFlangeCDWallOut / 2; + cyssFlangeCExt->DefineSection(2, sCyssFlangeCExtThick, rmin, rmax); + cyssFlangeCExt->DefineSection(3, sCyssFlangeCHmin3, rmin, rmax); + + TString cyssFlangeCComposite = Form("cyssflangecdisks+cflangecext"); + + // The flange holes + rmax = sHoles22Dia / 2; + zlen = sCyssFlangeCTotH / 2; + TGeoTube* hole22 = new TGeoTube("hole22", 0, rmax, 1.1 * zlen); + + for (Int_t j = 0; j < 3; j++) { + ypos = sHolesDdist[j] / 2; + TGeoTranslation* holeCTr = new TGeoTranslation(Form("holeCTr%d", j), 0, -ypos, zlen); + holeCTr->RegisterYourself(); + cyssFlangeCComposite += Form("-hole22:holeCTr%d", j); + + xpos = TMath::Sin(sHoles22Phi * TMath::DegToRad()) * sHolesDdist[j] / 2; + ypos = TMath::Cos(sHoles22Phi * TMath::DegToRad()) * sHolesDdist[j] / 2; + TGeoTranslation* holeLTr = new TGeoTranslation(Form("holeLTr%d", j), xpos, -ypos, zlen); + holeLTr->RegisterYourself(); + cyssFlangeCComposite += Form("-hole22:holeLTr%d", j); + + TGeoTranslation* holeRTr = new TGeoTranslation(Form("holeRTr%d", j), -xpos, -ypos, zlen); + holeRTr->RegisterYourself(); + cyssFlangeCComposite += Form("-hole22:holeRTr%d", j); + } + + rmax = sHoles30Dia / 2; + TGeoTube* hole30 = new TGeoTube("hole30", 0, rmax, zlen); + + for (Int_t k = 0; k < 3; k++) { + Double_t phi = (k + 1) * sHoles30Phi; + for (Int_t j = 0; j < 3; j++) { + xpos = TMath::Sin(phi * TMath::DegToRad()) * sHolesDdist[j] / 2; + ypos = TMath::Cos(phi * TMath::DegToRad()) * sHolesDdist[j] / 2; + + TGeoTranslation* holeLTr = new TGeoTranslation(Form("holeLTr%d%d", k, j), xpos, -ypos, zlen); + holeLTr->RegisterYourself(); + cyssFlangeCComposite += Form("-hole30:holeLTr%d%d", k, j); + + TGeoTranslation* holeRTr = new TGeoTranslation(Form("holeRTr%d%d", k, j), -xpos, -ypos, zlen); + holeRTr->RegisterYourself(); + cyssFlangeCComposite += Form("-hole30:holeRTr%d%d", k, j); + } + } + + rmax = sHoles12Dia / 2; + TGeoTube* hole12 = new TGeoTube("hole12", 0, rmax, 1.1 * zlen); + + for (Int_t j = 0; j < 3; j++) { + xpos = TMath::Sin(sHoles12Phi * TMath::DegToRad()) * sHolesDdist[j] / 2; + ypos = TMath::Cos(sHoles12Phi * TMath::DegToRad()) * sHolesDdist[j] / 2; + TGeoTranslation* holeLTr = new TGeoTranslation(Form("holeLTrM%d", j), xpos, -ypos, zlen); + holeLTr->RegisterYourself(); + cyssFlangeCComposite += Form("-hole12:holeLTrM%d", j); + + TGeoTranslation* holeRTr = new TGeoTranslation(Form("holeRTrM%d", j), -xpos, -ypos, zlen); + holeRTr->RegisterYourself(); + cyssFlangeCComposite += Form("-hole12:holeRTrM%d", j); + } + + TGeoBBox* notch = new TGeoBBox("notch", sCyssFlangeCNotchW / 2, (sCyssFlangeCDWallOut - sCyssFlangeCDWallIn), sCyssFlangeCNotchH); + + ypos = (sCyssFlangeCDWallIn + sCyssFlangeCDWallOut) / 4; + TGeoTranslation* notchTr = new TGeoTranslation("notchTr", 0, -ypos, sCyssFlangeCTotH); + notchTr->RegisterYourself(); + + cyssFlangeCComposite += "-notch:notchTr"; + + // The final flange shape + TGeoCompositeShape* cyssFlangeCSh = new TGeoCompositeShape(cyssFlangeCComposite.Data()); + + // We have all shapes: now create the real volumes + TGeoMedium* medAlu = mgr->GetMedium("IT4_ALUMINUM$"); + + TGeoVolume* cyssFlangeCVol = new TGeoVolume("IBCYSSFlangeC", cyssFlangeCSh, medAlu); + cyssFlangeCVol->SetLineColor(kCyan); + cyssFlangeCVol->SetFillColor(kCyan); + + // Finally return the flange volume + return cyssFlangeCVol; +} + +void V3Services::obEndWheelSideA(const Int_t iLay, TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the single End Wheel on Side A + // for a given layer of the Middle and Outer Barrels + // (Layer 3: ALICE-W3-01-Side_A, Layer 4: ALICE-W4-01-Side_A, + // Layer 5: ALICE-W5-01-Side_A Layer 6: ALICE-W6-01-Side_A) + // + // Input: + // iLay : the layer number (0,1: Middle, 2,3: Outer) + // endWheel : the volume where to place the current created wheel + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 24 Sep 2019 Mario Sitta + // Updated: 27 Sep 2019 Mario Sitta + // + + // The support ring + static const Double_t sOBWheelTotZlen = 55.0 * sMm; + static const Double_t sOBWheelSuppZlen = 35.0 * sMm; + + static const Double_t sOBWheelSuppRmin[4] = {204.0 * sMm, 254.0 * sMm, 352.5 * sMm, 402.0 * sMm}; + static const Double_t sOBWheelSuppRmax[4] = {241.0 * sMm, 291.0 * sMm, 389.0 * sMm, 448.5 * sMm}; + + // The support blocks + static const Double_t sOBWheelShelfWide[4] = {56.05 * sMm, 55.15 * sMm, 54.10 * sMm, 53.81 * sMm}; // TO BE CHECKED + static const Double_t sOBWheelShelfHoleZpos = 48.0 * sMm; + + static const Double_t sOBWheelShelfRpos[4] = {213.0 * sMm, 262.5 * sMm, 361.0 * sMm, 410.5 * sMm}; + static const Double_t sOBWheelShelfPhi0[4] = {0.0, 0.0, 0.0, 0.0}; // Deg + + // Local variables + Double_t xlen, ylen, zlen; + Double_t rmin, rmax, phimin, dphi; + Double_t xpos, ypos, zpos; + + // The Support Wheel is physically a single piece, a hollow ring + // plus the stave support shelves + // For the sake of simplicity we build it up with four TGeoTube's + // one per each wall of the ring (inner, outer, lower, upper) plus + // as many TGeoBBox's as needed for the shelves + + // The inner ring + TGeoTube* innerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], sOBWheelSuppRmax[iLay], sOBWheelThickness / 2); + + // The outer ring + TGeoTube* outerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], sOBWheelSuppRmax[iLay], sOBWheelThickness / 2); + + // The lower ring + rmax = sOBWheelSuppRmin[iLay] + sOBWheelThickness; + zlen = sOBWheelSuppZlen - 2 * sOBWheelThickness; + TGeoTube* lowerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], rmax, zlen / 2); + + // The upper ring + rmin = sOBWheelSuppRmax[iLay] - sOBWheelThickness; + TGeoTube* upperRingSh = new TGeoTube(rmin, sOBWheelSuppRmax[iLay], zlen / 2); + + // The shelf support + xlen = sOBWheelShelfWide[iLay]; + ylen = 2 * sOBWheelThickness; + zlen = sOBWheelTotZlen - sOBWheelSuppZlen; + TGeoBBox* shelfSh = new TGeoBBox(xlen / 2, ylen / 2, zlen / 2); + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + + Int_t nLay = iLay + sNumberInnerLayers; + + TGeoVolume* ringInnerVol = new TGeoVolume(Form("OBEndWheelAInnerRing%d", nLay), innerRingSh, medCarbon); + ringInnerVol->SetFillColor(kBlue); + ringInnerVol->SetLineColor(kBlue); + + TGeoVolume* ringOuterVol = new TGeoVolume(Form("OBEndWheelAOuterRing%d", nLay), outerRingSh, medCarbon); + ringOuterVol->SetFillColor(kBlue); + ringOuterVol->SetLineColor(kBlue); + + TGeoVolume* ringLowerVol = new TGeoVolume(Form("OBEndWheelALowerRing%d", nLay), lowerRingSh, medCarbon); + ringLowerVol->SetFillColor(kBlue); + ringLowerVol->SetLineColor(kBlue); + + TGeoVolume* ringUpperVol = new TGeoVolume(Form("OBEndWheelAUpperRing%d", nLay), upperRingSh, medCarbon); + ringUpperVol->SetFillColor(kBlue); + ringUpperVol->SetLineColor(kBlue); + + TGeoVolume* shelfVol = new TGeoVolume(Form("OBEndWheelAShelf%d", nLay), shelfSh, medCarbon); + shelfVol->SetFillColor(kBlue); + shelfVol->SetLineColor(kBlue); + + // Finally put everything in the mother volume + // In blueprints the Z position is given wrt the shelf holes + // First the ring + if (iLay < sNumberMiddlLayers) + zpos = sMBWheelsZpos + sOBWheelShelfHoleZpos; + else + zpos = sOBWheelsZpos + sOBWheelShelfHoleZpos; + + zpos -= outerRingSh->GetDz(); + mother->AddNode(ringOuterVol, 1, new TGeoTranslation(0, 0, zpos)); + + zpos -= (outerRingSh->GetDz() + lowerRingSh->GetDz()); + mother->AddNode(ringLowerVol, 1, new TGeoTranslation(0, 0, zpos)); + mother->AddNode(ringUpperVol, 1, new TGeoTranslation(0, 0, zpos)); + + zpos -= (lowerRingSh->GetDz() + innerRingSh->GetDz()); + mother->AddNode(ringInnerVol, 1, new TGeoTranslation(0, 0, zpos)); + + // Then the support blocks + Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(nLay); + Double_t alpha = 360. / numberOfStaves; + + rmin = sOBWheelShelfRpos[iLay] + shelfSh->GetDY(); + zpos -= (innerRingSh->GetDz() + shelfSh->GetDZ()); + + for (Int_t j = 0; j < numberOfStaves; j++) { // As in V3Layer::createLayer + Double_t phi = j * alpha + sOBWheelShelfPhi0[iLay]; + xpos = rmin * cosD(phi); + ypos = rmin * sinD(phi); + phi += 90; + mother->AddNode(shelfVol, j, new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", phi, 0, 0))); + } +} + +void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the single End Wheel on Side C + // for a given layer of the Middle Barrel + // (wheels on Side C are very different for Middle and Outer Barrels, + // so we cannot use a single method for both as for Side A) + // (Layer 3: ALICE-W3-04-Side_C, Layer 4: ALICE-W4-05-Side_C) + // + // Input: + // iLay : the layer number (0,1: Middle, 2,3: Outer) + // endWheel : the volume where to place the current created wheel + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 26 Sep 2019 Mario Sitta + // + + // The support ring + static const Double_t sOBWheelTotZlen[2] = {63.0 * sMm, 55.0 * sMm}; + static const Double_t sOBWheelSuppZlen[2] = {43.0 * sMm, 35.0 * sMm}; + + static const Double_t sOBWheelSuppRmin[2] = {200.5 * sMm, 254.0 * sMm}; + static const Double_t sOBWheelSuppRmax[2] = {237.5 * sMm, 291.0 * sMm}; + static const Double_t sOBWheelFlangeR[2] = {255.0 * sMm, 239.5 * sMm}; + static const Double_t sOBWheelFlangeZlen = 8.0 * sMm; + + // The support blocks + static const Double_t sOBWheelShelfWide[2] = {56.05 * sMm, 55.15 * sMm}; // TO BE CHECKED + static const Double_t sOBWheelShelfHoleZpos[2] = {56.0 * sMm, 48.0 * sMm}; + + static const Double_t sOBWheelShelfRpos[2] = {213.0 * sMm, 262.5 * sMm}; + static const Double_t sOBWheelShelfPhi0[2] = {0.0, 0.0}; // Deg + + // Local variables + Double_t xlen, ylen, zlen; + Double_t rmin, rmax, phimin, dphi; + Double_t xpos, ypos, zpos; + Int_t nsect; + + // The Support Wheel is physically a single piece, a hollow ring + // with a flange plus the stave support shelves + // Unfortunately the flange is on opposite sides on the two layers + // (externally to the ring for layer 3, internally for layer 4) + // For the sake of simplicity we build it up with three TGeoTube's and + // one TGeoPcon for each wall of the ring (inner, outer, lower, upper) + // plus as many TGeoBBox's as needed for the shelves + + // The inner ring + TGeoTube* innerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], sOBWheelSuppRmax[iLay], sOBWheelThickness / 2); + + // The outer ring with the flange + if (iLay == 0) + nsect = 6; + else + nsect = 4; + + TGeoPcon* outerRingSh = new TGeoPcon(0, 360, nsect); + + if (iLay == 0) { + rmin = sOBWheelSuppRmax[0] - 2 * sOBWheelThickness; + outerRingSh->DefineSection(0, 0., rmin, sOBWheelFlangeR[0]); + outerRingSh->DefineSection(1, 2 * sOBWheelThickness, rmin, sOBWheelFlangeR[0]); + outerRingSh->DefineSection(2, 2 * sOBWheelThickness, rmin, sOBWheelSuppRmax[0]); + outerRingSh->DefineSection(3, sOBWheelFlangeZlen, rmin, sOBWheelSuppRmax[0]); + outerRingSh->DefineSection(4, sOBWheelFlangeZlen, sOBWheelSuppRmin[0], sOBWheelSuppRmax[0]); + zlen = sOBWheelFlangeZlen + sOBWheelThickness; + outerRingSh->DefineSection(5, zlen, sOBWheelSuppRmin[0], sOBWheelSuppRmax[0]); + } else { + outerRingSh->DefineSection(0, 0., sOBWheelFlangeR[1], sOBWheelSuppRmax[1]); + outerRingSh->DefineSection(1, sOBWheelThickness, sOBWheelFlangeR[1], sOBWheelSuppRmax[1]); + rmax = sOBWheelSuppRmin[1] + sOBWheelThickness; + outerRingSh->DefineSection(2, sOBWheelThickness, sOBWheelFlangeR[1], rmax); + outerRingSh->DefineSection(3, 2 * sOBWheelThickness, sOBWheelFlangeR[1], rmax); + } + + // The lower ring + if (iLay == 0) + zlen = sOBWheelSuppZlen[iLay] - sOBWheelFlangeZlen - 2 * sOBWheelThickness; + else + zlen = sOBWheelSuppZlen[iLay] - sOBWheelThickness - outerRingSh->GetZ(nsect - 1); + + rmax = sOBWheelSuppRmin[iLay] + sOBWheelThickness; + TGeoTube* lowerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], rmax, zlen / 2); + + // The upper ring + if (iLay == 1) // For odd layers the upper and lower rings length is the same + zlen = sOBWheelSuppZlen[iLay] - 2 * sOBWheelThickness; + + rmin = sOBWheelSuppRmax[iLay] - sOBWheelThickness; + TGeoTube* upperRingSh = new TGeoTube(rmin, sOBWheelSuppRmax[iLay], zlen / 2); + + // The shelf support + xlen = sOBWheelShelfWide[iLay]; + ylen = 2 * sOBWheelThickness; + zlen = sOBWheelTotZlen[iLay] - sOBWheelSuppZlen[iLay]; + TGeoBBox* shelfSh = new TGeoBBox(xlen / 2, ylen / 2, zlen / 2); + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + + Int_t nLay = iLay + sNumberInnerLayers; + + TGeoVolume* ringInnerVol = new TGeoVolume(Form("OBEndWheelCInnerRing%d", nLay), innerRingSh, medCarbon); + ringInnerVol->SetFillColor(kBlue); + ringInnerVol->SetLineColor(kBlue); + + TGeoVolume* ringOuterVol = new TGeoVolume(Form("OBEndWheelCOuterRing%d", nLay), outerRingSh, medCarbon); + ringOuterVol->SetFillColor(kBlue); + ringOuterVol->SetLineColor(kBlue); + + TGeoVolume* ringLowerVol = new TGeoVolume(Form("OBEndWheelCLowerRing%d", nLay), lowerRingSh, medCarbon); + ringLowerVol->SetFillColor(kBlue); + ringLowerVol->SetLineColor(kBlue); + + TGeoVolume* ringUpperVol = new TGeoVolume(Form("OBEndWheelCUpperRing%d", nLay), upperRingSh, medCarbon); + ringUpperVol->SetFillColor(kBlue); + ringUpperVol->SetLineColor(kBlue); + + TGeoVolume* shelfVol = new TGeoVolume(Form("OBEndWheelAShelf%d", nLay), shelfSh, medCarbon); + shelfVol->SetFillColor(kBlue); + shelfVol->SetLineColor(kBlue); + + // Finally put everything in the mother volume + // In blueprints the Z position is given wrt the shelf holes + // First the ring + zpos = sMBWheelsZpos + sOBWheelShelfHoleZpos[iLay] - sOBWheelSuppZlen[iLay]; + + zpos += innerRingSh->GetDz(); + mother->AddNode(ringInnerVol, 1, new TGeoTranslation(0, 0, -zpos)); + + zpos += (innerRingSh->GetDz() + upperRingSh->GetDz()); + mother->AddNode(ringUpperVol, 1, new TGeoTranslation(0, 0, -zpos)); + + zpos += (-upperRingSh->GetDz() + lowerRingSh->GetDz()); + mother->AddNode(ringLowerVol, 1, new TGeoTranslation(0, 0, -zpos)); + + zpos += (lowerRingSh->GetDz() + outerRingSh->GetZ(nsect - 1)); + mother->AddNode(ringOuterVol, 1, new TGeoTranslation(0, 0, -zpos)); + + // Then the support blocks + Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(nLay); + Double_t alpha = 360. / numberOfStaves; + + rmin = sOBWheelShelfRpos[iLay] + shelfSh->GetDY(); + zpos = sMBWheelsZpos + sOBWheelShelfHoleZpos[iLay] - sOBWheelSuppZlen[iLay]; + zpos -= shelfSh->GetDZ(); + + for (Int_t j = 0; j < numberOfStaves; j++) { // As in V3Layer::createLayer + Double_t phi = j * alpha + sOBWheelShelfPhi0[iLay]; + xpos = rmin * cosD(phi); + ypos = rmin * sinD(phi); + phi += 90; + mother->AddNode(shelfVol, j, new TGeoCombiTrans(xpos, ypos, -zpos, new TGeoRotation("", phi, 0, 0))); + } +} + +void V3Services::obEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the single End Wheel on Side C + // for a given layer of the Outer Barrel + // (wheels on Side C are very different for Middle and Outer Barrels, + // so we cannot use a single method for both as for Side A) + // (Layer 5: ALICE-W5-04-Side_C, Layer 6: ALICE-W6-04-Side_C) + // + // Input: + // iLay : the layer number (0,1: Middle, 2,3: Outer) + // endWheel : the volume where to place the current created wheel + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 07 Oct 2019 Mario Sitta + // + + // The support ring + static const Double_t sOBWheelTotZlen[2] = {37.0 * sMm, 35.0 * sMm}; + + static const Double_t sOBWheelSuppRmin = 354.0 * sMm; + static const Double_t sOBWheelSuppRmax[2] = {389.5 * sMm, 448.5 * sMm}; + static const Double_t sOBWheelIntFlangeR[2] = {335.0 * sMm, 393.0 * sMm}; + static const Double_t sOBWheelExtFlangeR = 409.0 * sMm; + static const Double_t sOBWheelIntFlangeZ = 4.0 * sMm; // TO BE CHECKED! + + static const Double_t sOBWheelShelfRpos[2] = {361.0 * sMm, 410.5 * sMm}; + static const Double_t sOBWheelShelfHoleZpos[2] = {28.0 * sMm, 26.0 * sMm}; + + // Local variables + Double_t xlen, ylen, zlen; + Double_t rmin, rmax, phimin, dphi; + Double_t xpos, ypos, zpos; + Int_t nsect; + + // The Support Wheels are physically a single piece, a hollow ring + // with one or two flanges + // For the sake of simplicity we build it up with a TGeoTube for the + // external wall and a TGeoPcon for the remaining of the ring for layer 6 + // and with two TGeoPcon's for layer 5 + + // The upper ring: a Pcon for Layer 5, a Tube for Layer 6 + TGeoShape* upperRingSh; + + rmin = sOBWheelSuppRmax[iLay] - sOBWheelThickness; + if (iLay == 0) { + nsect = 4; + TGeoPcon* ring = new TGeoPcon(0, 360, nsect); + ring->DefineSection(0, sOBWheelThickness, rmin, sOBWheelExtFlangeR); + ring->DefineSection(1, 2 * sOBWheelThickness, rmin, sOBWheelExtFlangeR); + ring->DefineSection(2, 2 * sOBWheelThickness, rmin, sOBWheelSuppRmax[iLay]); + zlen = sOBWheelTotZlen[iLay] - sOBWheelThickness; + ring->DefineSection(3, zlen, rmin, sOBWheelSuppRmax[iLay]); + upperRingSh = (TGeoShape*)ring; + } else { + zlen = sOBWheelTotZlen[iLay] - 2 * sOBWheelThickness; + TGeoTube* ring = new TGeoTube(rmin, sOBWheelSuppRmax[iLay], zlen / 2); + upperRingSh = (TGeoShape*)ring; + } + + // The lower ring: a Pcon + TGeoPcon* lowerRingSh; + + if (iLay == 0) { + nsect = 14; + lowerRingSh = new TGeoPcon(0, 360, nsect); + lowerRingSh->DefineSection(0, 0., sOBWheelSuppRmin, sOBWheelExtFlangeR); + lowerRingSh->DefineSection(1, sOBWheelThickness, sOBWheelSuppRmin, sOBWheelExtFlangeR); + rmax = sOBWheelSuppRmin + sOBWheelThickness; + lowerRingSh->DefineSection(2, sOBWheelThickness, sOBWheelSuppRmin, rmax); + lowerRingSh->DefineSection(3, sOBWheelIntFlangeZ, sOBWheelSuppRmin, rmax); + lowerRingSh->DefineSection(4, sOBWheelIntFlangeZ, sOBWheelIntFlangeR[iLay], rmax); + zpos = sOBWheelIntFlangeZ + 2 * sOBWheelThickness; + lowerRingSh->DefineSection(5, zpos, sOBWheelIntFlangeR[iLay], rmax); + lowerRingSh->DefineSection(6, zpos, sOBWheelSuppRmin, rmax); + zpos += sOBWheelIntFlangeZ; + lowerRingSh->DefineSection(7, zpos, sOBWheelSuppRmin, rmax); + rmax = sOBWheelShelfRpos[iLay] + sOBWheelThickness; + lowerRingSh->DefineSection(8, zpos, sOBWheelSuppRmin, rmax); + zpos += sOBWheelThickness; + lowerRingSh->DefineSection(9, zpos, sOBWheelSuppRmin, rmax); + lowerRingSh->DefineSection(10, zpos, sOBWheelShelfRpos[iLay], rmax); + zpos = sOBWheelTotZlen[iLay] - sOBWheelThickness; + lowerRingSh->DefineSection(11, zpos, sOBWheelShelfRpos[iLay], rmax); + lowerRingSh->DefineSection(12, zpos, sOBWheelShelfRpos[iLay], sOBWheelSuppRmax[iLay]); + lowerRingSh->DefineSection(13, sOBWheelTotZlen[iLay], sOBWheelShelfRpos[iLay], sOBWheelSuppRmax[iLay]); + } else { + nsect = 10; + lowerRingSh = new TGeoPcon(0, 360, nsect); + lowerRingSh->DefineSection(0, 0., sOBWheelShelfRpos[iLay], sOBWheelSuppRmax[iLay]); + lowerRingSh->DefineSection(1, sOBWheelThickness, sOBWheelShelfRpos[iLay], sOBWheelSuppRmax[iLay]); + rmax = sOBWheelShelfRpos[iLay] + sOBWheelThickness; + lowerRingSh->DefineSection(2, sOBWheelThickness, sOBWheelShelfRpos[iLay], rmax); + lowerRingSh->DefineSection(3, sOBWheelIntFlangeZ, sOBWheelShelfRpos[iLay], rmax); + lowerRingSh->DefineSection(4, sOBWheelIntFlangeZ, sOBWheelIntFlangeR[iLay], rmax); + zpos = sOBWheelIntFlangeZ + 2 * sOBWheelThickness; + lowerRingSh->DefineSection(5, zpos, sOBWheelIntFlangeR[iLay], rmax); + lowerRingSh->DefineSection(6, zpos, sOBWheelShelfRpos[iLay], rmax); + zpos = sOBWheelTotZlen[iLay] - sOBWheelThickness; + lowerRingSh->DefineSection(7, zpos, sOBWheelShelfRpos[iLay], rmax); + lowerRingSh->DefineSection(8, zpos, sOBWheelShelfRpos[iLay], sOBWheelSuppRmax[iLay]); + lowerRingSh->DefineSection(9, sOBWheelTotZlen[iLay], sOBWheelShelfRpos[iLay], sOBWheelSuppRmax[iLay]); + } + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + + Int_t nLay = iLay + sNumberInnerLayers + sNumberMiddlLayers; + + TGeoVolume* ringUpperVol = new TGeoVolume(Form("OBEndWheelCUpperRing%d", nLay), upperRingSh, medCarbon); + ringUpperVol->SetFillColor(kBlue); + ringUpperVol->SetLineColor(kBlue); + + TGeoVolume* ringLowerVol = new TGeoVolume(Form("OBEndWheelCLowerRing%d", nLay), lowerRingSh, medCarbon); + ringLowerVol->SetFillColor(kBlue); + ringLowerVol->SetLineColor(kBlue); + + // Finally put everything in the mother volume + // In blueprints the Z position is given wrt the shelf holes + zpos = sOBWheelsZpos + sOBWheelShelfHoleZpos[iLay]; + + mother->AddNode(ringLowerVol, 1, new TGeoTranslation(0, 0, -zpos)); + + if (iLay == 1) + zpos -= (sOBWheelThickness + (static_cast<TGeoTube*>(upperRingSh))->GetDz()); + mother->AddNode(ringUpperVol, 1, new TGeoTranslation(0, 0, -zpos)); +} + +void V3Services::obConeSideA(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Cone structure on Side A of the Outer Barrel + // (ALICE-W4-04-Cone_4A) + // + // Input: + // mother : the volume where to place the current created cone + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 03 Feb 2020 Mario Sitta + // + + static const Double_t sOBConeATotZlen = 350.0 * sMm; + static const Double_t sOBConeAStartCyl2 = 170.0 * sMm; + static const Double_t sOBConeAEndCyl1 = 160.8 * sMm; + static const Double_t sOBConeAThinCylZ = 36.0 * sMm; + + static const Double_t sOBConeAIntR = 291.5 * sMm; + static const Double_t sOBConeAExtR = 302.5 * sMm; + + static const Double_t sOBConeARingExtR = 339.5 * sMm; + static const Double_t sOBConeARingZlen = 55.0 * sMm; + static const Double_t sOBConeARingZout = 35.0 * sMm; + + static const Double_t sOBConeAThickAll = 2.0 * sMm; + static const Double_t sOBConeAThickThin = 1.0 * sMm; + + static const Double_t sOBConeAReinfZIn = 1.0 * sMm; + static const Double_t sOBConeAReinfRIn = 301.6 * sMm; + + static const Double_t sOBConeAReinfThick = 6.5 * sMm; + + static const Int_t sOBConeARibNVert = 8; + + // Local variables + Double_t rmin, rmax, zlen; + Double_t xpos, ypos, zpos; + + // The OB Cone on Side A is physically a single piece. + // It is implemented using two Pcon plus a Xtru for the reinforcements + + Double_t phi = sOBConeAReinfThick / sOBConeAIntR; + phi *= TMath::RadToDeg(); + + // The main cone: a Pcon + TGeoPcon* obConeSh = new TGeoPcon(phi, 180 - 2 * phi, 10); + + rmin = sOBConeAIntR; + rmax = sOBConeAReinfRIn; + obConeSh->DefineSection(0, 0., rmin, rmax); + obConeSh->DefineSection(1, sOBConeAReinfZIn, rmin, rmax); + rmax = rmin + sOBConeAThickThin; + obConeSh->DefineSection(2, sOBConeAReinfZIn, rmin, rmax); + obConeSh->DefineSection(3, sOBConeAThinCylZ, rmin, rmax); + rmax = rmin + sOBConeAThickAll; + obConeSh->DefineSection(4, sOBConeAThinCylZ, rmin, rmax); + zlen = sOBConeATotZlen - sOBConeAStartCyl2; + obConeSh->DefineSection(5, zlen, rmin, rmax); + rmin = sOBConeAExtR; + rmax = rmin + sOBConeAThickAll; + zlen = sOBConeATotZlen - sOBConeAEndCyl1; + obConeSh->DefineSection(6, zlen, rmin, rmax); + zlen = sOBConeATotZlen - sOBConeAThickAll; + obConeSh->DefineSection(7, zlen, rmin, rmax); + rmax = sOBConeARingExtR; + obConeSh->DefineSection(8, zlen, rmin, rmax); + obConeSh->DefineSection(9, sOBConeATotZlen, rmin, rmax); + + // The external ring: a Pcon + TGeoPcon* obConeRingSh = new TGeoPcon(phi, 180 - 2 * phi, 6); + + rmin = obConeSh->GetRmax(7); + rmax = rmin + sOBConeAThickAll; + obConeRingSh->DefineSection(0, 0., rmin, rmax); + zlen = sOBConeARingZlen - sOBConeARingZout; + obConeRingSh->DefineSection(1, zlen, rmin, rmax); + rmax = sOBConeARingExtR; + obConeRingSh->DefineSection(2, zlen, rmin, rmax); + zlen += sOBConeAThickAll; + obConeRingSh->DefineSection(3, zlen, rmin, rmax); + rmin = rmax - sOBConeAThickAll; + obConeRingSh->DefineSection(4, zlen, rmin, rmax); + zlen = sOBConeARingZlen - sOBConeAThickAll; + obConeRingSh->DefineSection(5, zlen, rmin, rmax); + + // The reinforcement rib: a Xtru + Double_t xr[sOBConeARibNVert], yr[sOBConeARibNVert]; + + xr[0] = 0; + yr[0] = 0; + xr[1] = obConeSh->GetRmax(0) - obConeSh->GetRmin(0); + yr[1] = yr[0]; + xr[2] = xr[1]; + yr[2] = obConeSh->GetZ(5); + xr[7] = xr[0]; + yr[7] = yr[2]; + xr[6] = obConeSh->GetRmin(6) - obConeSh->GetRmin(5); + yr[6] = obConeSh->GetZ(6); + xr[3] = xr[6] + (xr[1] - xr[0]); + yr[3] = yr[6]; + xr[5] = xr[6]; + yr[5] = sOBConeATotZlen - sOBConeARingZout + sOBConeAThickAll; + xr[4] = xr[3]; + yr[4] = yr[5]; + + TGeoXtru* obConeRibSh = new TGeoXtru(2); + obConeRibSh->DefinePolygon(sOBConeARibNVert, xr, yr); + obConeRibSh->DefineSection(0, 0); + obConeRibSh->DefineSection(1, sOBConeAThickAll); + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + + TGeoVolume* obConeVol = new TGeoVolume("OBConeSideA", obConeSh, medCarbon); + obConeVol->SetFillColor(kBlue); + obConeVol->SetLineColor(kBlue); + + TGeoVolume* obConeRingVol = new TGeoVolume("OBConeRingSideA", obConeRingSh, medCarbon); + obConeRingVol->SetFillColor(kBlue); + obConeRingVol->SetLineColor(kBlue); + + TGeoVolume* obConeRibVol = new TGeoVolume("OBConeRibSideA", obConeRibSh, medCarbon); + obConeRibVol->SetFillColor(kBlue); + obConeRibVol->SetLineColor(kBlue); + + // Finally put everything in the mother volume + zpos = sOBConesZpos - sOBConeATotZlen; + + mother->AddNode(obConeVol, 1, new TGeoTranslation(0, 0, zpos)); + mother->AddNode(obConeVol, 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 0, 0))); + + zpos = sOBConesZpos - sOBConeARingZlen; + + mother->AddNode(obConeRingVol, 1, new TGeoTranslation(0, 0, zpos)); + mother->AddNode(obConeRingVol, 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 0, 0))); + + xpos = obConeSh->GetRmin(0); + ypos = sOBConeAReinfThick; + zpos = sOBConesZpos - sOBConeATotZlen; + + mother->AddNode(obConeRibVol, 1, new TGeoCombiTrans(xpos, ypos, zpos, new TGeoRotation("", 0, 90, 0))); + mother->AddNode(obConeRibVol, 4, new TGeoCombiTrans(-xpos, -ypos, zpos, new TGeoRotation("", 0, -90, 180))); + + ypos = sOBConeAReinfThick - sOBConeAThickAll; + + mother->AddNode(obConeRibVol, 3, new TGeoCombiTrans(-xpos, ypos, zpos, new TGeoRotation("", 0, -90, -180))); + mother->AddNode(obConeRibVol, 4, new TGeoCombiTrans(xpos, -ypos, zpos, new TGeoRotation("", 0, 90, 0))); +} + +void V3Services::obConeTraysSideA(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Cone Trays on Side A of the Outer Barrel + // (ALICE-W3-08-vassoio+ALICE-W5-08_vassoio) + // + // Input: + // mother : the volume where to place the current created cone + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 05 Feb 2020 Mario Sitta + // + + static const Double_t sOBTrayZlen[2] = {112.0 * sMm, 115.0 * sMm}; + static const Double_t sOBTrayRmin[2] = {222.0 * sMm, 370.0 * sMm}; + static const Double_t sOBTrayRmax[2] = {240.0 * sMm, 386.0 * sMm}; + + static const Double_t sOBTrayZpos[2] = {181.0 * sMm, 20.0 * sMm}; + + static const Double_t sOBTrayThick = 2.0 * sMm; + + static const Double_t sOBTrayReinfWide[2] = {27.0 * sMm, 24.0 * sMm}; + static const Double_t sOBTrayReinfYpos = 6.0 * sMm; + + // Local variables + Double_t rmin, rmax, zlen; + Double_t xpos, ypos, zpos; + + // Each OB Tray on Side A is physically a single piece. + // It is implemented using a Pcon plus a BBox for the reinforcements + + TGeoPcon* obTraySh[2]; + TGeoBBox* obTrayRibSh[2]; + + for (Int_t j = 0; j < 2; j++) { + Double_t phi = (sOBTrayReinfYpos + sOBTrayThick) / sOBTrayRmin[j]; + phi *= TMath::RadToDeg(); + + // The main body: a Pcon + obTraySh[j] = new TGeoPcon(180 + phi, 180 - 2 * phi, 4); + + rmin = sOBTrayRmin[j]; + rmax = sOBTrayRmax[j]; + obTraySh[j]->DefineSection(0, 0., rmin, rmax); + obTraySh[j]->DefineSection(1, sOBTrayThick, rmin, rmax); + rmin = rmax - sOBTrayThick; + obTraySh[j]->DefineSection(2, sOBTrayThick, rmin, rmax); + obTraySh[j]->DefineSection(3, sOBTrayZlen[j], rmin, rmax); + + // The reinforcement rib: a BBox + obTrayRibSh[j] = new TGeoBBox(sOBTrayReinfWide[j] / 2, + sOBTrayThick / 2, + sOBTrayZlen[j] / 2); + } // for (j = 0,1) + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + + TGeoVolume *obTrayVol[2], *obTrayRibVol[2]; + + for (Int_t j = 0; j < 2; j++) { + obTrayVol[j] = new TGeoVolume(Form("OBConeTray%d", j), obTraySh[j], medCarbon); + obTrayVol[j]->SetFillColor(kBlue); + obTrayVol[j]->SetLineColor(kBlue); + + obTrayRibVol[j] = new TGeoVolume(Form("OBConeTrayRib%d", j), obTrayRibSh[j], medCarbon); + obTrayRibVol[j]->SetFillColor(kBlue); + obTrayRibVol[j]->SetLineColor(kBlue); + } + + // Finally put everything in the mother volume + + for (Int_t j = 0; j < 2; j++) { + if (j == 0) + zpos = sOBConesZpos - sOBTrayZpos[j] - sOBTrayZlen[j]; + else + zpos = sOBConesZpos + sOBTrayZpos[j]; + + mother->AddNode(obTrayVol[j], 1, new TGeoTranslation(0, 0, zpos)); + mother->AddNode(obTrayVol[j], 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 0, 0))); + + xpos = obTraySh[j]->GetRmin(0) + obTrayRibSh[j]->GetDX(); + ypos = sOBTrayReinfYpos + obTrayRibSh[j]->GetDY(); + zpos += obTrayRibSh[j]->GetDZ(); + + mother->AddNode(obTrayRibVol[j], 1, new TGeoTranslation(xpos, -ypos, zpos)); + mother->AddNode(obTrayRibVol[j], 2, new TGeoTranslation(-xpos, -ypos, zpos)); + mother->AddNode(obTrayRibVol[j], 3, new TGeoTranslation(xpos, ypos, zpos)); + mother->AddNode(obTrayRibVol[j], 4, new TGeoTranslation(-xpos, ypos, zpos)); + } +} + +void V3Services::obConeSideC(TGeoVolume* mother, const TGeoManager* mgr) +{ + // + // Creates the Cone structure on Side C of the Outer Barrel + // (ALICE-W4-06-Cone_4C) + // + // Input: + // mother : the volume where to place the current created cone + // mgr : the GeoManager (used only to get the proper material) + // + // Output: + // + // Return: + // + // Created: 26 Jan 2020 Mario Sitta + // + + static const Double_t sOBConeCTotZlen = 332.5 * sMm; + static const Double_t sOBConeCStartCyl2 = 132.8 * sMm; + static const Double_t sOBConeCEndCyl1 = 82.4 * sMm; + static const Double_t sOBConeCThinCylZ = 36.0 * sMm; + + static const Double_t sOBConeCIntR = 291.5 * sMm; + static const Double_t sOBConeCExtR = 315.0 * sMm; + + static const Double_t sOBConeCRingExtR = 333.0 * sMm; + static const Double_t sOBConeCRingZlen = 61.0 * sMm; + static const Double_t sOBConeCRingZout = 42.0 * sMm; + + static const Double_t sOBConeCThickAll = 2.0 * sMm; + static const Double_t sOBConeCThickThin = 1.0 * sMm; + + static const Double_t sOBConeCReinfZIn = 2.0 * sMm; + static const Double_t sOBConeCReinfRIn = 301.6 * sMm; + static const Double_t sOBConeCReinfROut = 351.5 * sMm; + + static const Double_t sOBConeCReinfThick = 6.5 * sMm; + + static const Int_t sOBConeCRibNVert = 8; + + // Local variables + Double_t rmin, rmax, zlen; + Double_t xpos, ypos, zpos; + + // The OB Cone on Side C is physically a single piece. + // It is implemented using two Pcon plus a Xtru for the reinforcements + + Double_t phi = sOBConeCReinfThick / sOBConeCIntR; + phi *= TMath::RadToDeg(); + + // The main cone: a Pcon + TGeoPcon* obConeSh = new TGeoPcon(phi, 180 - 2 * phi, 10); + + rmin = sOBConeCExtR; + rmax = sOBConeCReinfROut; + obConeSh->DefineSection(0, 0., rmin, rmax); + obConeSh->DefineSection(1, sOBConeCThickAll, rmin, rmax); + rmax = rmin + sOBConeCThickAll; + obConeSh->DefineSection(2, sOBConeCThickAll, rmin, rmax); + obConeSh->DefineSection(3, sOBConeCEndCyl1, rmin, rmax); + rmin = sOBConeCIntR; + rmax = rmin + sOBConeCThickAll; + obConeSh->DefineSection(4, sOBConeCStartCyl2, rmin, rmax); + zlen = sOBConeCTotZlen - sOBConeCThinCylZ; + obConeSh->DefineSection(5, zlen, rmin, rmax); + rmax = rmin + sOBConeCThickThin; + obConeSh->DefineSection(6, zlen, rmin, rmax); + zlen = sOBConeCTotZlen - sOBConeCReinfZIn; + obConeSh->DefineSection(7, zlen, rmin, rmax); + rmax = sOBConeCReinfRIn; + obConeSh->DefineSection(8, zlen, rmin, rmax); + obConeSh->DefineSection(9, sOBConeCTotZlen, rmin, rmax); + + // The external ring: a Pcon + TGeoPcon* obConeRingSh = new TGeoPcon(phi, 180 - 2 * phi, 8); + + rmin = sOBConeCRingExtR - sOBConeCThickAll; + rmax = sOBConeCReinfROut; + obConeRingSh->DefineSection(0, 0., rmin, rmax); + obConeRingSh->DefineSection(1, sOBConeCThickAll, rmin, rmax); + rmax = sOBConeCRingExtR; + obConeRingSh->DefineSection(2, sOBConeCThickAll, rmin, rmax); + zlen = sOBConeCRingZout - sOBConeCThickAll; + obConeRingSh->DefineSection(3, zlen, rmin, rmax); + rmin = sOBConeCExtR + sOBConeCThickAll; + obConeRingSh->DefineSection(4, zlen, rmin, rmax); + obConeRingSh->DefineSection(5, sOBConeCRingZout, rmin, rmax); + rmax = rmin + sOBConeCThickAll; + obConeRingSh->DefineSection(6, sOBConeCRingZout, rmin, rmax); + obConeRingSh->DefineSection(7, sOBConeCRingZlen, rmin, rmax); + + // The reinforcement rib: a Xtru + Double_t xr[sOBConeCRibNVert], yr[sOBConeCRibNVert]; + + xr[0] = 0; + yr[0] = 0; + xr[1] = obConeSh->GetRmax(9) - obConeSh->GetRmin(9); + yr[1] = yr[0]; + xr[2] = xr[1]; + yr[2] = obConeSh->GetZ(9) - obConeSh->GetZ(4); + xr[7] = xr[0]; + yr[7] = yr[2]; + xr[6] = obConeSh->GetRmin(3) - obConeSh->GetRmin(4); + yr[6] = obConeSh->GetZ(9) - obConeSh->GetZ(3); + xr[3] = xr[6] + (xr[1] - xr[0]); + yr[3] = yr[6]; + xr[5] = xr[6]; + yr[5] = sOBConeCTotZlen - sOBConeCRingZout; + xr[4] = xr[3]; + yr[4] = yr[5]; + + TGeoXtru* obConeRibSh = new TGeoXtru(2); + obConeRibSh->DefinePolygon(sOBConeCRibNVert, xr, yr); + obConeRibSh->DefineSection(0, 0); + obConeRibSh->DefineSection(1, sOBConeCThickAll); + + // We have all shapes: now create the real volumes + TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + + TGeoVolume* obConeVol = new TGeoVolume("OBConeSideC", obConeSh, medCarbon); + obConeVol->SetFillColor(kBlue); + obConeVol->SetLineColor(kBlue); + + TGeoVolume* obConeRingVol = new TGeoVolume("OBConeRingSideC", obConeRingSh, medCarbon); + obConeRingVol->SetFillColor(kBlue); + obConeRingVol->SetLineColor(kBlue); + + TGeoVolume* obConeRibVol = new TGeoVolume("OBConeRibSideC", obConeRibSh, medCarbon); + obConeRibVol->SetFillColor(kBlue); + obConeRibVol->SetLineColor(kBlue); + + // Finally put everything in the mother volume + zpos = sOBConesZpos; + + mother->AddNode(obConeVol, 1, new TGeoTranslation(0, 0, -zpos)); + mother->AddNode(obConeVol, 2, new TGeoCombiTrans(0, 0, -zpos, new TGeoRotation("", 180, 0, 0))); + + zpos -= sOBConeCThickAll; + + mother->AddNode(obConeRingVol, 1, new TGeoTranslation(0, 0, -zpos)); + mother->AddNode(obConeRingVol, 2, new TGeoCombiTrans(0, 0, -zpos, new TGeoRotation("", 180, 0, 0))); + + xpos = obConeSh->GetRmin(9); + ypos = sOBConeCReinfThick; + zpos = sOBConesZpos - obConeSh->GetZ(9); + + mother->AddNode(obConeRibVol, 1, new TGeoCombiTrans(xpos, -ypos, -zpos, new TGeoRotation("", 0, -90, 0))); + mother->AddNode(obConeRibVol, 2, new TGeoCombiTrans(-xpos, ypos, -zpos, new TGeoRotation("", 0, 90, 180))); + + ypos = sOBConeCReinfThick - sOBConeCThickAll; + + mother->AddNode(obConeRibVol, 3, new TGeoCombiTrans(xpos, ypos, -zpos, new TGeoRotation("", 0, -90, 0))); + mother->AddNode(obConeRibVol, 4, new TGeoCombiTrans(-xpos, -ypos, -zpos, new TGeoRotation("", 0, 90, 180))); +} diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index d8530594637f2..ae1650bb84db2 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -113,6 +113,7 @@ if (ENABLE_UPGRADES) O2::TPCSimulation O2::ITSSimulation O2::ITS3Simulation + O2::ITS4Simulation O2::MFTSimulation O2::MCHSimulation O2::MIDSimulation diff --git a/macro/build_geometry.C b/macro/build_geometry.C index ef29710ce1283..5628ff0b512fb 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -47,6 +47,7 @@ #ifdef ENABLE_UPGRADES #include <ITS3Simulation/Detector.h> +#include <ITS4Simulation/Detector.h> #endif void finalize_geometry(FairRunSim* run); @@ -191,9 +192,15 @@ void build_geometry(FairRunSim* run = nullptr) #ifdef ENABLE_UPGRADES if (isActivated("IT3")) { // ITS3 - auto its3 = new o2::its3::Detector(kTRUE); + auto its3 = new o2::its3::Detector(true); run->AddModule(its3); } + + if (isActivated("IT4")) { + // ITS4 + auto its4 = new o2::its4::Detector(true); + run->AddModule(its4); + } #endif if (isActivated("ITS")) { diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index dc8efaaaffd49..8e9a5ec00de87 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -26,6 +26,7 @@ target_link_libraries(allsim O2::HMPIDSimulation O2::ITSSimulation O2::ITS3Simulation + O2::ITS4Simulation O2::MCHBase O2::MCHSimulation O2::MFTSimulation diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 469776b67b89d..90d0fe0e8d8e8 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -64,6 +64,7 @@ #ifdef ENABLE_UPGRADES #include <ITS3Simulation/Detector.h> +#include <ITS4Simulation/Detector.h> #endif namespace o2 @@ -742,6 +743,10 @@ void O2HitMerger::initDetInstances() mDetectorInstances[i] = std::move(std::make_unique<o2::its3::Detector>(true)); counter++; } + if (i == DetID::IT4) { + mDetectorInstances[i] = std::move(std::make_unique<o2::its4::Detector>(true)); + counter++; + } #endif // init the detector specific output files initHitTreeAndOutFile(i); From 1109d14ff40b933ceef94966968d04713cf24caf Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 7 Aug 2020 13:39:54 +0200 Subject: [PATCH 0303/1751] Add explicit template instantiation --- Detectors/TPC/base/src/Painter.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/TPC/base/src/Painter.cxx b/Detectors/TPC/base/src/Painter.cxx index 934e6d29165ef..8089c4bc0cc87 100644 --- a/Detectors/TPC/base/src/Painter.cxx +++ b/Detectors/TPC/base/src/Painter.cxx @@ -329,6 +329,8 @@ std::vector<TCanvas*> painter::makeSummaryCanvases(const std::string_view fileNa template TCanvas* painter::draw<float>(const CalDet<float>& calDet, int, float, float); template std::vector<TCanvas*> painter::makeSummaryCanvases<float>(const CalDet<float>& calDet, int, float, float, bool); template TCanvas* painter::draw<float>(const CalArray<float>& calArray); +template void painter::fillHistogram2D<float>(TH2& h2D, const CalDet<float>& calDet, Side side); +template void painter::fillHistogram2D<float>(TH2& h2D, const CalArray<float>& calArray); template TH2* painter::getHistogram2D<float>(const CalDet<float>& calDet, Side side); template TH2* painter::getHistogram2D<float>(const CalArray<float>& calArray); From 6191087e7c438932c311eee1745af2fdf6f23860 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 6 Aug 2020 21:02:36 +0200 Subject: [PATCH 0304/1751] trd updated halfcruheader and tests --- .../TRD/include/DataFormatsTRD/RawData.h | 129 +++++++----------- DataFormats/Detectors/TRD/src/RawData.cxx | 51 +------ Detectors/TRD/base/test/testRawData.cxx | 58 ++++---- 3 files changed, 85 insertions(+), 153 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h index 5b4b3ac336e54..9799528106e03 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -22,119 +22,96 @@ namespace o2 namespace trd { +/// \structure HalfCRUHeader +/// \brief Header for half a cru, each cru has 2 output, 1 for each pciid. +// This comes at the top of the data stream for each event and 1/2cru + struct HalfCRUHeader { + /* Half cru header 64 bits is too wide, hence reduce to 32 to make it readable. - |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| ------------------------------------------------------------------------------------------------- -Word 0 | link 0 errorflags | link 0 datasize | link 1 errorflags | - ------------------------------------------------------------------------------------------------- -Word 0 | link 0 data size | link 2 error flags | link 2 datasize upper| - ------------------------------------------------------------------------------------------------- -Word 1 | link 2 datasize lower | link 3 errorflags | link 3 datasize | - ------------------------------------------------------------------------------------------------- -Word 1 | link 4 errorflags | link 4 datasize | link 5 errorflags | - ------------------------------------------------------------------------------------------------- -Word 2 | link 5 data size | link 6 error flags | link 6 datasize upper| - ------------------------------------------------------------------------------------------------- -Word 2 | link 6 datasize lower | link 7 errorflags | link 7 datasize | - ------------------------------------------------------------------------------------------------- -Word 3 | reserved | +Word 0 | eventtype | end point | stopbit| bunchcrossing | headerversion | ------------------------------------------------------------------------------------------------- -Word 3 | header version | bunch crossing | stop bit | event type | +Word 0 | reserved 1 | ------------------------------------------------------------------------------------------------- -Word 4 | reserved | +Word 1 | link 3 errorflags | link 2 errorflags | link 1 error flags | link 0 error flags | ------------------------------------------------------------------------------------------------- -Word 4 | reserved | +Word 1 | link 7 error flags | link 6 error flags | link 5 error flags | link 4 error flags | ------------------------------------------------------------------------------------------------- -Word 5 | reserved | link 8 error flags | - ------------------------------------------------------------------------------------------------- -Word 5 | link 8 data size | link 9 error flags | link 9 datasize upper| - ------------------------------------------------------------------------------------------------- -Word 6 | link 9 datasize lower | link 10 errorflags | link 10 datasize | - ------------------------------------------------------------------------------------------------- -Word 6 | link 11 errorflags | link 11 datasize | link 12 errorflags | - ------------------------------------------------------------------------------------------------- -Word 7 | link 12 data size | link 13 error flags | link 13 datasize upper| - ------------------------------------------------------------------------------------------------- -Word 7 |link 13 datasize lower | link 14 errorflags | link 14 datasize | - ------------------------------------------------------------------------------------------------- - -alternate candidate : - |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| +Word 2 | link 11 error flags | link 10 error flags | link 9 error flags | link 8 error flags | ------------------------------------------------------------------------------------------------- -Word 0 | header version | bunch crossing | stop bit | event type | +Word 2 | link 12 error flags | link 13 error flags | link 14 error flags | reserved 2 | ------------------------------------------------------------------------------------------------- -Word 0 | reserved | +Word 3 | reserved 3 | ------------------------------------------------------------------------------------------------- -Word 1 | link 0 errorflags | link 1 errorflags | link2 error flags | link 3 error flags | +Word 3 | reserved 4 | ------------------------------------------------------------------------------------------------- -Word 1 | link 4 error flags | link 5 error flags | link 6 error flags | link 7 error flags | +Word 4 | link 1 datasize | link 0 datasize | ------------------------------------------------------------------------------------------------- -Word 2 | link 0 datasize | link 1 datasize | +Word 4 | link 3 datasize | link 2 datasize | ------------------------------------------------------------------------------------------------- -Word 2 | link 2 datasize | link 3 datasize | +Word 5 | link 5 datasize | link 4 datasize | ------------------------------------------------------------------------------------------------- -Word 3 | link 4 data size | link 5 datasize | +Word 5 | link 7 datasize | link 6 datasize | ------------------------------------------------------------------------------------------------- -Word 3 | link 6 datasize | link 7 datasize | +Word 6 | link 9 datasize | link 8 datasize | ------------------------------------------------------------------------------------------------- -Word 4 | reserved | +Word 6 | link 11 datasize | link 10 datasize | ------------------------------------------------------------------------------------------------- -Word 4 | reserved | +Word 7 | link 13 datasize | link 12 datasize | ------------------------------------------------------------------------------------------------- -Word 5 | reserved | link 8 error flags | +Word 7 | reserved 5 | link 14 datasize | ------------------------------------------------------------------------------------------------- -Word 5 | link 9 errorflags | link 10 errorflags | link11 error flags | link 12 error flags | - ------------------------------------------------------------------------------------------------- -Word 6 | link 13 error flags | link 14 error flags | link 8 datasize | - ------------------------------------------------------------------------------------------------- -Word 6 | link 9 datasize | link 10 datasize | - ------------------------------------------------------------------------------------------------- -Word 7 | link 11 datasize | link 12 datasize | - ------------------------------------------------------------------------------------------------- -Word 7 | link 13 datasize | link 14 datasize | - -------------------------------------------------------------------------------------------------- */ union { - uint64_t word02[3]; - struct { - uint64_t errorflags : 8; - uint64_t size : 16; - } __attribute__((__packed__)) linksA[8]; - }; - union { - uint64_t word3 = 0x0; + uint64_t word0 = 0x0; //first word * - // uint64_t: 0x0000000000000000 - // | - | || - // | | | |- 0..7 Event type - // | | | -- 8..11 Stop bit - // | | ------ 12..23 bunch crossing id - // | -------- 24..31 TRD Header version - // --------------- 32..63 reserveda + // 6 5 4 3 2 1 + // 3210987654321098765432109876543210987654321098765432109876543210 + // uint64_t: 0000000000000000000000000000000000000000000000000000000000000000 + // | | | | | |-------- 0..7 TRD Header version + // | | | | |-------------------- 8..19 bunch crossing + // | | | |------------------------ 20..23 stop bit + // | | |---------------------------- 24..27 end point + // | |-------------------------------- 28..31 event type + // |---------------------------------------------------------------- 32..63 reserved1 struct { - uint64_t reserveda : 32; // uint64_t HeaderVersion : 8; // TRD Header Version uint64_t BunchCrossing : 12; // bunch crossing uint64_t StopBit : 4; // 8 .. 11 stop bit 0x1 if TRD packet is last data packet of trigger, else 0x0 TODO why 4 bits if only using 1? - uint64_t EventType : 8; // bit 0..7 event type of the data. Trigger bits from TTC-PON message, distinguish physics from calibration events. + uint64_t EndPoint : 4; // bit 0..7 event type of the data. Trigger bits from TTC-PON message, distinguish physics from calibration events. + uint64_t EventType : 4; // bit 0..7 event type of the data. Trigger bits from TTC-PON message, distinguish physics from calibration events. + uint64_t reserveda : 32; // + } __attribute__((__packed__)); + }; + union { + uint64_t word12[2]; + // 15 8 bit error flags and 1 8 bit reserved. + struct { + struct { + uint8_t errorflag : 8; + } __attribute__((__packed__)) errorflags[15]; + uint8_t reserved2 : 8; } __attribute__((__packed__)); }; union { - uint64_t word4 = 0x0; + uint64_t word3 = 0x0; struct { - uint64_t reservedb; + uint64_t reserved34; } __attribute__((__packed__)); }; union { - uint64_t word57[3]; + uint64_t word47[4]; + //15 16 bit data sizes and 1 16 bit reserved word. struct { - uint64_t errorflags : 8; - uint64_t size : 16; - } __attribute__((__packed__)) linksB[8]; // although this is 8 dont use index 0 as its part of reserved. + struct { + uint64_t size : 16; + } __attribute__((__packed__)) datasizes[15]; // although this is 8 dont use index 0 as its part of reserved. + uint16_t reserved5; + } __attribute__((__packed__)); }; }; diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index 51d3b3c6ef0e6..0e86eab05fb1d 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -18,44 +18,13 @@ namespace o2 namespace trd { -uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data = true) -{ - // cruhead is the incoming header to pass - // link is the link you are requesting information on, 0-14 - // - uint32_t info = 0; - if (link > 14) - return 0xffffffff; - - char* words; - if (link < 8) - words = (char*)&cruhead.word02[0]; - if (link < 15) - words = (char*)&cruhead.word57[0]; - uint32_t byteoffset = link * 3; // each link [size+erroflags] is 24 bits, so 3 bytes. - if (data) - info = ((words[byteoffset + 1]) << 8) + (words[byteoffset + 2]); - else - info = words[byteoffset]; - - return info; -} - uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link) { // link is the link you are requesting information on, 0-14 - uint32_t errorflags = 0; - if (link < 8) { - //dealing with word0-2 - errorflags = cruhead.linksA[link].errorflags; - } else { - if (link < 16) { - errorflags = cruhead.linksB[link - 8 + 1].errorflags; // link 0 [actually 9] is in fact the end part of reserved. - - } else - std::cout << "error link=" << link << " not in range 0-14" << std::endl; - } - return errorflags; + uint32_t errorflag = 0; + //dealing with word0-2 + errorflag = cruhead.errorflags[link].errorflag; + return errorflag; } uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link) @@ -63,15 +32,7 @@ uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link) // link is the link you are requesting information on, 0-14 //return number 32 byte blocks for the link 3x64bit ints. uint32_t size = 0; - if (link < 8) { - size = (cruhead.linksA[link].size); - } else { - if (link < 16) { // link 0 is part of reserved - size = cruhead.linksB[link - 8 + 1].size; - - } else - std::cout << "error link=" << link << " not in range 0-14" << std::endl; - } + size = cruhead.datasizes[link].size; return size; } @@ -175,7 +136,7 @@ std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) // for (int link = 0; link < 15; link++) stream << link << ":" << std::hex << std::setw(2) << getlinkerrorflag(halfcru, link) << ","; stream << std::endl; - stream << "0x" << halfcru.word02[0] << " 0x" << halfcru.word02[1] << " 0x" << halfcru.word02[2] << " 0x" << halfcru.word3 << " 0x" << halfcru.word4 << " 0x" << halfcru.word57[0] << " 0x" << halfcru.word57[1] << " 0x" << halfcru.word57[2] << std::endl; + stream << "0x" << std::hex << halfcru.word0 << " 0x" << halfcru.word12[0] << " 0x" << halfcru.word12[1] << " 0x" << halfcru.word3 << " 0x" << halfcru.word47[0] << " 0x" << halfcru.word47[1] << " 0x" << halfcru.word47[2] << " 0x" << halfcru.word47[3] << std::endl; return stream; } diff --git a/Detectors/TRD/base/test/testRawData.cxx b/Detectors/TRD/base/test/testRawData.cxx index 5c39367cdaac4..f9b88a690be6c 100644 --- a/Detectors/TRD/base/test/testRawData.cxx +++ b/Detectors/TRD/base/test/testRawData.cxx @@ -46,47 +46,41 @@ BOOST_AUTO_TEST_CASE(TRDRawDataHeaderInternals) o2::trd::TrackletMCMData tracklet; o2::trd::TrackletHCHeader halfchamberheader; o2::trd::HalfCRUHeader halfcruheader; - halfcruheader.word02[0] = 0x102; - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags, 2); - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size, 1); - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 0)); - BOOST_CHECK_EQUAL(halfcruheader.linksA[0].size, o2::trd::getlinkdatasize(halfcruheader, 0)); - //ab is size - halfcruheader.word02[2] = 0xffffaa0000000000; - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size, 0xffff); - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags, 0xaa); - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 7)); - BOOST_CHECK_EQUAL(halfcruheader.linksA[7].size, o2::trd::getlinkdatasize(halfcruheader, 7)); - halfcruheader.word3 = (0x222LL) << 40; //bc is at 0x000ffff000000000 + // changed as now nothing spans a 32 or 16 bit boundary + halfcruheader.word0 = 0x22200; //bc is at 0x0000000fff00 BOOST_CHECK_EQUAL(halfcruheader.BunchCrossing, 0x222); - halfcruheader.word3 = 0x7700000000; //headerversion is at 0x00ff0000000 + halfcruheader.word0 = 0x00000077; //headerversion is at 0x000000000 BOOST_CHECK_EQUAL(halfcruheader.HeaderVersion, 119); - halfcruheader.word57[0] = 0x345869faba; - halfcruheader.word57[2] = 0xaaade1277; - //linkb[0] zero is undefined. - BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags, 0x58); - BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size, 0x34); - BOOST_CHECK_EQUAL(halfcruheader.linksB[1].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 8)); - BOOST_CHECK_EQUAL(halfcruheader.linksB[1].size, o2::trd::getlinkdatasize(halfcruheader, 8)); - //ab is size - BOOST_CHECK_EQUAL(halfcruheader.linksB[5].size, 0x1277); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size, 0xaaa); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags, 0xde); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].errorflags, o2::trd::getlinkerrorflag(halfcruheader, 13)); - BOOST_CHECK_EQUAL(halfcruheader.linksB[6].size, o2::trd::getlinkdatasize(halfcruheader, 13)); - //now test the boundary crossing of the int64_t - halfcruheader.word02[0] = (uint64_t)0x1000000000000000; - halfcruheader.word02[1] = (uint64_t)0xa00b000c000d0ebf; - BOOST_CHECK_EQUAL(halfcruheader.linksA[2].size, 0xbf10); // check a size that spans a 64bit word. + //error flags + halfcruheader.word12[0] = 0xa02; + halfcruheader.word12[1] = 0xab0000; + BOOST_CHECK_EQUAL(halfcruheader.errorflags[0].errorflag, 2); + BOOST_CHECK_EQUAL(halfcruheader.errorflags[1].errorflag, 0xa); + halfcruheader.word12[1] = 0x00ed000000000000; // should link 14 error flags. + BOOST_CHECK_EQUAL(halfcruheader.errorflags[14].errorflag, 0xed); + BOOST_CHECK_EQUAL(halfcruheader.errorflags[14].errorflag, o2::trd::getlinkerrorflag(halfcruheader, 14)); + //datasizes + halfcruheader.word47[0] = 0xbdbd; + BOOST_CHECK_EQUAL(halfcruheader.datasizes[0].size, 0xbdbd); + BOOST_CHECK_EQUAL(halfcruheader.datasizes[0].size, o2::trd::getlinkdatasize(halfcruheader, 0)); + halfcruheader.word47[1] = 0xabcd; + BOOST_CHECK_EQUAL(halfcruheader.datasizes[4].size, 0xabcd); + BOOST_CHECK_EQUAL(halfcruheader.datasizes[4].size, o2::trd::getlinkdatasize(halfcruheader, 4)); + halfcruheader.word47[2] = 0xaaade127; + BOOST_CHECK_EQUAL(halfcruheader.datasizes[8].size, 0xe127); + BOOST_CHECK_EQUAL(halfcruheader.datasizes[8].size, o2::trd::getlinkdatasize(halfcruheader, 8)); + halfcruheader.word47[3] = 0xefaadebc0000; + BOOST_CHECK_EQUAL(halfcruheader.datasizes[14].size, 0xefaa); + BOOST_CHECK_EQUAL(halfcruheader.datasizes[14].size, o2::trd::getlinkdatasize(halfcruheader, 14)); o2::trd::TrackletMCMHeader mcmrawdataheader; mcmrawdataheader.word = 0x78000000; BOOST_CHECK_EQUAL(mcmrawdataheader.padrow, 15); mcmrawdataheader.word = 0x06000000; BOOST_CHECK_EQUAL(mcmrawdataheader.col, 3); mcmrawdataheader.word = 0x01fe0000; - BOOST_CHECK_EQUAL(mcmrawdataheader.pid2, 0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 + BOOST_CHECK_EQUAL(mcmrawdataheader.pid2, 0xff); // 8 bits mcmrawdataheader.word = 0x01fe; - BOOST_CHECK_EQUAL(mcmrawdataheader.pid0, 0xff); // 8 bits // gave up seperating pid, so its a flat 24 bit needs to be masked 0xfff 0xfff000 and 0xfff000000 + BOOST_CHECK_EQUAL(mcmrawdataheader.pid0, 0xff); // 8 bits //check tracklet tracklet.word = 0xffc00000; BOOST_CHECK_EQUAL((uint32_t)tracklet.pos, 0x3ff); From 99a00f8a6a26c2f44884ff940685503c354713ab Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 8 Aug 2020 16:20:41 +0200 Subject: [PATCH 0305/1751] Add dummy PATTERNS output to TOF decoder Needed just to comply with TOF CTF encoder inputs, to be changed to meaningfull input by TOF experts --- Detectors/TOF/workflow/src/CompressedDecodingTask.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index a7fe6653ec172..97088ca0bdf4b 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -82,6 +82,10 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, *alldigits); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, *row); + // RS FIXME: At the moment dummy output to comply with CTF encoded inputs + std::vector<uint32_t> patterns; + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, patterns); + // RS this is a hack to be removed once we have correct propagation of the firstTForbit by the framework auto setFirstTFOrbit = [&](const Output& spec, uint32_t orb) { auto* hd = pc.outputs().findMessageHeader(spec); @@ -182,6 +186,7 @@ DataProcessorSpec getCompressedDecodingSpec(const std::string& inputDesc) std::vector<OutputSpec> outputs; outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); // RS FIXME: At the moment dummy output to comply with CTF encoded inputs return DataProcessorSpec{ "tof-compressed-decoder", From d7d15fbed80f890a751f398aa899a16a9519caff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Mon, 10 Aug 2020 12:19:28 +0200 Subject: [PATCH 0306/1751] Add RecoDecay class. (#4112) --- .../DataModel/include/Analysis/RecoDecay.h | 421 +++++++++++++++--- .../include/Analysis/SecondaryVertexHF.h | 10 +- .../include/Analysis/decayUtilities.h | 86 ++++ Analysis/Tasks/hfcandidatecreator2prong.cxx | 36 +- Analysis/Tasks/hftrackindexskimscreator.cxx | 77 ++-- Analysis/Tasks/vertexerhf.cxx | 2 +- 6 files changed, 499 insertions(+), 133 deletions(-) create mode 100644 Analysis/DataModel/include/Analysis/decayUtilities.h diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index ebda753431603..6220e51cee3e7 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -7,78 +7,373 @@ // 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_RECODECAY_H_ -#define O2_ANALYSIS_RECODECAY_H_ -double energy(double px, double py, double pz, double mass) -{ - double en_ = sqrt(mass * mass + px * px + py * py + pz * pz); - return en_; -} +/// \file RecoDecay.h +/// \brief Implementation of the RecoDecay class. +/// +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN -double invmass2prongs2(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1) -{ +#ifndef RECODECAY_H +#define RECODECAY_H - double energy0_ = energy(px0, py0, pz0, mass0); - double energy1_ = energy(px1, py1, pz1, mass1); - double energytot = energy0_ + energy1_; +#include <tuple> +#include <vector> +#include <array> +#include <cmath> - double psum2 = (px0 + px1) * (px0 + px1) + - (py0 + py1) * (py0 + py1) + - (pz0 + pz1) * (pz0 + pz1); - return energytot * energytot - psum2; -} +#include <TDatabasePDG.h> +#include <TPDGCode.h> -double invmass3prongs2(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1, - double px2, double py2, double pz2, double mass2) -{ - double energy0_ = energy(px0, py0, pz0, mass0); - double energy1_ = energy(px1, py1, pz1, mass1); - double energy2_ = energy(px2, py2, pz2, mass2); - double energytot = energy0_ + energy1_ + energy2_; - - double psum2 = (px0 + px1 + px2) * (px0 + px1 + px2) + - (py0 + py1 + py2) * (py0 + py1 + py2) + - (pz0 + pz1 + pz2) * (pz0 + pz1 + pz2); - return energytot * energytot - psum2; -} - -double invmass2prongs(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1) -{ - return sqrt(invmass2prongs2(px0, py0, pz0, mass0, - px1, py1, pz1, mass1)); -} +#include "CommonConstants/MathConstants.h" -double invmass3prongs(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1, - double px2, double py2, double pz2, double mass2) -{ - return sqrt(invmass3prongs2(px0, py0, pz0, mass0, - px1, py1, pz1, mass1, - px2, py2, pz2, mass2)); -} +using std::array; +using namespace o2::constants::math; -double ptcand2prong(double px0, double py0, double px1, double py1) -{ - return sqrt((px0 + px1) * (px0 + px1) + (py0 + py1) * (py0 + py1)); -} +/// Base class for calculating properties of reconstructed decays. -double pttrack(double px, double py) +class RecoDecay { - return sqrt(px * px + py * py); -} + public: + /// Default constructor + RecoDecay() = default; -double declength(double xdecay, double ydecay, double zdecay, double xvtx, double yvtx, double zvtx) -{ - return sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx) + (zdecay - zvtx) * (zdecay - zvtx)); -} + /// Default destructor + ~RecoDecay() = default; -double declengthxy(double xdecay, double ydecay, double xvtx, double yvtx) -{ - return sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx)); -} + // Auxiliary functions + + /// Sums numbers. + /// \param args arbitrary number of numbers of arbitrary types + /// \return sum of numbers + template <typename... T> + static auto sum(const T&... args) + { + return (args + ...); + } + + /// Sums squares of numbers. + /// \note Promotes numbers to double before squaring to avoid precision loss in float multiplication. + /// \param args arbitrary number of numbers of arbitrary types + /// \return sum of squares of numbers + template <typename... T> + static auto sumOfSquares(const T&... args) + { + return (((double)args * (double)args) + ...); + } + + /// Calculates square root of a sum of squares of numbers. + /// \param args arbitrary number of numbers of arbitrary types + /// \return square root of sum of squares of numbers + template <typename... T> + static auto sqrtSumOfSquares(const T&... args) + { + return std::sqrt(sumOfSquares(args...)); + } + + /// Sums i-th elements of containers. + /// \param index element index + /// \param args pack of containers of elements accessible by index + /// \return sum of i-th elements + template <typename... T> + static auto getElement(int index, const T&... args) + { + return (args[index] + ...); + } + + /// Sums 3-vectors. + /// \param args pack of 3-vector arrays + /// \return sum of vectors + template <typename... T> + static auto sumOfVec(const array<T, 3>&... args) + { + return array{getElement(0, args...), getElement(1, args...), getElement(2, args...)}; + } + + /// Calculates scalar product of vectors. + /// \note Promotes numbers to double before squaring to avoid precision loss in float multiplication. + /// \param N dimension + /// \param vec1,vec2 vectors + /// \return scalar product + template <std::size_t N, typename T, typename U> + static auto dotProd(const array<T, N>& vec1, const array<U, N>& vec2) + { + double res{0}; + for (auto iDim = 0; iDim < N; ++iDim) { + res += (double)vec1[iDim] * (double)vec2[iDim]; + } + return res; + } + + /// Calculates magnitude squared of a vector. + /// \param N dimension + /// \param vec vector + /// \return magnitude squared + template <std::size_t N, typename T> + static auto mag2(const array<T, N>& vec) + { + return dotProd(vec, vec); + } + + /// Calculates 3D distance between two points. + /// \param point1,point2 {x, y, z} coordinates of points + /// \return 3D distance between two points + template <typename T, typename U> + static auto distance(const array<T, 3>& point1, const array<U, 3>& point2) + { + return sqrtSumOfSquares(point1[0] - point2[0], point1[1] - point2[1], point1[2] - point2[2]); + } + + /// Calculates 2D {x, y} distance between two points. + /// \param point1,point2 {x, y, z} or {x, y} coordinates of points + /// \return 2D {x, y} distance between two points + template <std::size_t N, std::size_t O, typename T, typename U> + static auto distanceXY(const array<T, N>& point1, const array<U, O>& point2) + { + return sqrtSumOfSquares(point1[0] - point2[0], point1[1] - point2[1]); + } + + // Calculation of kinematic quantities + + /// Calculates pseudorapidity. + /// \param mom 3-momentum array + /// \return pseudorapidity + template <typename T> + static auto Eta(const array<T, 3>& mom) + { + // eta = arctanh(pz/p) + if (std::abs(mom[0]) < Almost0 && std::abs(mom[1]) < Almost0) { // very small px and py + return (double)(mom[2] > 0 ? VeryBig : -VeryBig); + } + return (double)(std::atanh(mom[2] / P(mom))); + } + + /// Calculates rapidity. + /// \param mom 3-momentum array + /// \param mass mass + /// \return rapidity + template <typename T, typename U> + static auto Rapidity(const array<T, 3>& mom, U mass) + { + // y = arctanh(pz/E) + return std::atanh(mom[2] / E(mom, mass)); + } + + /// Calculates cosine of pointing angle. + /// \param posPV {x, y, z} position of the primary vertex + /// \param posSV {x, y, z} position of the secondary vertex + /// \param mom 3-momentum array + /// \return cosine of pointing angle + template <typename T, typename U, typename V> + static auto CPA(const array<T, 3>& posPV, const array<U, 3>& posSV, const array<V, 3>& mom) + { + // CPA = (l . p)/(|l| |p|) + auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1], posSV[2] - posPV[2]}; + auto cos = dotProd(lineDecay, mom) / std::sqrt(mag2(lineDecay) * mag2(mom)); + if (cos < -1.) { + return -1.; + } + if (cos > 1.) { + return 1.; + } + return cos; + } + + /// Calculates cosine of pointing angle in the {x, y} plane. + /// \param posPV {x, y, z} or {x, y} position of the primary vertex + /// \param posSV {x, y, z} or {x, y} position of the secondary vertex + /// \param mom {x, y, z} or {x, y} momentum array + /// \return cosine of pointing angle in {x, y} + template <std::size_t N, std::size_t O, std::size_t P, typename T, typename U, typename V> + static auto CPAXY(const array<T, N>& posPV, const array<U, O>& posSV, const array<V, P>& mom) + { + // CPAXY = (r . pT)/(|r| |pT|) + auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1]}; + auto momXY = array{mom[0], mom[1]}; + auto cos = dotProd(lineDecay, momXY) / std::sqrt(mag2(lineDecay) * mag2(momXY)); + if (cos < -1.) { + return -1.; + } + if (cos > 1.) { + return 1.; + } + return cos; + } + + /// Calculates proper lifetime times c. + /// \note Promotes numbers to double before squaring to avoid precision loss in float multiplication. + /// \param mom 3-momentum array + /// \param mass mass + /// \param length decay length + /// \return proper lifetime times c + template <typename T, typename U, typename V> + static auto Ct(array<T, 3> mom, U mass, V length) + { + // c t = l m c^2/(p c) + return (double)length * (double)mass / P(mom); + } + + /// Sums 3-momenta. + /// \param args pack of 3-momentum arrays + /// \return total 3-momentum array + template <typename... T> + static auto PVec(const array<T, 3>&... args) + { + return sumOfVec(args...); + } + + /// Calculates momentum squared from momentum components. + /// \param px,py,pz {x, y, z} momentum components + /// \return momentum squared + static auto P2(double px, double py, double pz) + { + return sumOfSquares(px, py, pz); + } + + /// Calculates total momentum squared of a sum of 3-momenta. + /// \param args pack of 3-momentum arrays + /// \return total momentum squared + template <typename... T> + static auto P2(const array<T, 3>&... args) + { + return sumOfSquares(getElement(0, args...), getElement(1, args...), getElement(2, args...)); + } + + /// Calculates (total) momentum magnitude. + /// \param args {x, y, z} momentum components or pack of 3-momentum arrays + /// \return (total) momentum magnitude + template <typename... T> + static auto P(const T&... args) + { + return std::sqrt(P2(args...)); + } + + /// Calculates transverse momentum squared from momentum components. + /// \param px,py {x, y} momentum components + /// \return transverse momentum squared + static auto Pt2(double px, double py) + { + return sumOfSquares(px, py); + } + + /// Calculates total transverse momentum squared of a sum of 3-(or 2-)momenta. + /// \param args pack of 3-(or 2-)momentum arrays + /// \return total transverse momentum squared + template <std::size_t N, typename... T> + static auto Pt2(const array<T, N>&... args) + { + return sumOfSquares(getElement(0, args...), getElement(1, args...)); + } + + /// Calculates (total) transverse momentum. + /// \param args {x, y} momentum components or pack of 3-momentum arrays + /// \return (total) transverse momentum + template <typename... T> + static auto Pt(const T&... args) + { + return std::sqrt(Pt2(args...)); + } + + /// Calculates energy squared from momentum and mass. + /// \param args momentum magnitude, mass + /// \param args {x, y, z} momentum components, mass + /// \return energy squared + template <typename... T> + static auto E2(T... args) + { + return sumOfSquares(args...); + } + + /// Calculates energy squared from momentum vector and mass. + /// \param mom 3-momentum array + /// \param mass mass + /// \return energy squared + template <typename T, typename U> + static auto E2(const array<T, 3>& mom, U mass) + { + return E2(mom[0], mom[1], mom[2], mass); + } + + /// Calculates energy from momentum and mass. + /// \param args momentum magnitude, mass + /// \param args {x, y, z} momentum components, mass + /// \param args 3-momentum array, mass + /// \return energy + template <typename... T> + static auto E(T... args) + { + return std::sqrt(E2(args...)); + } + + /// Calculates invariant mass squared from momentum magnitude and energy. + /// \param mom momentum magnitude + /// \param energy energy + /// \return invariant mass squared + static auto M2(double mom, double energy) + { + return energy * energy - mom * mom; + } + + /// Calculates invariant mass squared from momentum aray and energy. + /// \param mom 3-momentum array + /// \param energy energy + /// \return invariant mass squared + template <typename T> + static auto M2(const array<T, 3>& mom, double energy) + { + return energy * energy - P2(mom); + } + + /// Calculates invariant mass squared from momenta and masses of several particles (prongs). + /// \param N number of prongs + /// \param arrMom array of N 3-momentum arrays + /// \param arrMass array of N masses (in the same order as arrMom) + /// \return invariant mass squared + template <std::size_t N, typename T, typename U> + static auto M2(const array<array<T, 3>, N>& arrMom, const array<U, N>& arrMass) + { + array<double, 3> momTotal{0., 0., 0.}; // candidate momentum vector + double energyTot{0.}; // candidate energy + for (auto iProng = 0; iProng < N; ++iProng) { + for (auto iMom = 0; iMom < 3; ++iMom) { + momTotal[iMom] += arrMom[iProng][iMom]; + } // loop over momentum components + energyTot += E(arrMom[iProng], arrMass[iProng]); + } // loop over prongs + return energyTot * energyTot - P2(momTotal); + } + + /// Calculates invariant mass. + /// \param args momentum magnitude, energy + /// \param args 3-momentum array, energy + /// \param args array of momenta, array of masses + /// \return invariant mass + template <typename... T> + static auto M(T... args) + { + return std::sqrt(M2(args...)); + } + + /// Returns particle mass based on PDG code. + /// \param pdg PDG code + /// \return particle mass + static auto getMassPDG(int pdg) + { + // Try to get the particle mass from the list first. + for (const auto& particle : mListMass) { + if (std::get<0>(particle) == pdg) { + return std::get<1>(particle); + } + } + // Get the mass of the new particle and add it in the list. + auto newMass = TDatabasePDG::Instance()->GetParticle(pdg)->Mass(); + mListMass.push_back(std::make_tuple(pdg, newMass)); + return newMass; + } + + private: + static std::vector<std::tuple<int, double>> mListMass; ///< list of particle masses in form (PDG code, mass) +}; + +std::vector<std::tuple<int, double>> RecoDecay::mListMass; -#endif // O2_ANALYSIS_RECODECAY_H_ +#endif // RECODECAY_H diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index b4b70649a3bc9..0c679ce6dc733 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -53,16 +53,16 @@ DECLARE_SOA_COLUMN(DecayVtxZ, decayvtxz, float); DECLARE_SOA_COLUMN(MassD0, massD0, float); DECLARE_SOA_COLUMN(MassD0bar, massD0bar, float); DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptprong0, - [](float px0, float py0) { return pttrack(px0, py0); }); + [](float px0, float py0) { return RecoDecay::Pt(px0, py0); }); DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptprong1, - [](float px1, float py1) { return pttrack(px1, py1); }); + [](float px1, float py1) { return RecoDecay::Pt(px1, py1); }); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, - [](float px0, float py0, float px1, float py1) { return ptcand2prong(px0, py0, px1, py1); }); + [](float px0, float py0, float px1, float py1) { return RecoDecay::Pt(array{px0, py0}, array{px1, py1}); }); DECLARE_SOA_DYNAMIC_COLUMN(DecaylengthXY, decaylengthxy, - [](float xvtxd, float yvtxd, float xvtxp, float yvtxp) { return declengthxy(xvtxd, yvtxd, xvtxp, yvtxp); }); + [](float xvtxd, float yvtxd, float xvtxp, float yvtxp) { return RecoDecay::distanceXY(array{xvtxd, yvtxd}, array{xvtxp, yvtxp}); }); DECLARE_SOA_DYNAMIC_COLUMN(Decaylength, decaylength, [](float xvtxd, float yvtxd, float zvtxd, float xvtxp, - float yvtxp, float zvtxp) { return declength(xvtxd, yvtxd, zvtxd, xvtxp, yvtxp, zvtxp); }); + float yvtxp, float zvtxp) { return RecoDecay::distance(array{xvtxd, yvtxd, zvtxd}, array{xvtxp, yvtxp, zvtxp}); }); } // namespace hfcandprong2 DECLARE_SOA_TABLE(HfTrackIndexProng2, "AOD", "HFTRACKIDXP2", diff --git a/Analysis/DataModel/include/Analysis/decayUtilities.h b/Analysis/DataModel/include/Analysis/decayUtilities.h new file mode 100644 index 0000000000000..879217175499c --- /dev/null +++ b/Analysis/DataModel/include/Analysis/decayUtilities.h @@ -0,0 +1,86 @@ +// 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_RECODECAY_H_ +#define O2_ANALYSIS_RECODECAY_H_ + +#include <cmath> + +double energy(double px, double py, double pz, double mass) +{ + double en_ = std::sqrt(mass * mass + px * px + py * py + pz * pz); + return en_; +} + +double invmass2prongs2(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1) +{ + + double energy0_ = energy(px0, py0, pz0, mass0); + double energy1_ = energy(px1, py1, pz1, mass1); + double energytot = energy0_ + energy1_; + + double psum2 = (px0 + px1) * (px0 + px1) + + (py0 + py1) * (py0 + py1) + + (pz0 + pz1) * (pz0 + pz1); + return energytot * energytot - psum2; +} + +double invmass3prongs2(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1, + double px2, double py2, double pz2, double mass2) +{ + double energy0_ = energy(px0, py0, pz0, mass0); + double energy1_ = energy(px1, py1, pz1, mass1); + double energy2_ = energy(px2, py2, pz2, mass2); + double energytot = energy0_ + energy1_ + energy2_; + + double psum2 = (px0 + px1 + px2) * (px0 + px1 + px2) + + (py0 + py1 + py2) * (py0 + py1 + py2) + + (pz0 + pz1 + pz2) * (pz0 + pz1 + pz2); + return energytot * energytot - psum2; +} + +double invmass2prongs(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1) +{ + return std::sqrt(invmass2prongs2(px0, py0, pz0, mass0, + px1, py1, pz1, mass1)); +} + +double invmass3prongs(double px0, double py0, double pz0, double mass0, + double px1, double py1, double pz1, double mass1, + double px2, double py2, double pz2, double mass2) +{ + return std::sqrt(invmass3prongs2(px0, py0, pz0, mass0, + px1, py1, pz1, mass1, + px2, py2, pz2, mass2)); +} + +double ptcand2prong(double px0, double py0, double px1, double py1) +{ + return std::sqrt((px0 + px1) * (px0 + px1) + (py0 + py1) * (py0 + py1)); +} + +double pttrack(double px, double py) +{ + return std::sqrt(px * px + py * py); +} + +double declength(double xdecay, double ydecay, double zdecay, double xvtx, double yvtx, double zvtx) +{ + return std::sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx) + (zdecay - zvtx) * (zdecay - zvtx)); +} + +double declengthxy(double xdecay, double ydecay, double xvtx, double yvtx) +{ + return std::sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx)); +} + +#endif // O2_ANALYSIS_RECODECAY_H_ diff --git a/Analysis/Tasks/hfcandidatecreator2prong.cxx b/Analysis/Tasks/hfcandidatecreator2prong.cxx index 984a4512ae130..662248d201314 100644 --- a/Analysis/Tasks/hfcandidatecreator2prong.cxx +++ b/Analysis/Tasks/hfcandidatecreator2prong.cxx @@ -14,14 +14,12 @@ #include "Analysis/SecondaryVertexHF.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" #include "Analysis/trackUtilities.h" +#include "Analysis/RecoDecay.h" #include <TFile.h> #include <TH1F.h> -#include <Math/Vector4D.h> -#include <TPDGCode.h> -#include <TDatabasePDG.h> + #include <cmath> #include <array> #include <cstdlib> @@ -30,7 +28,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -using namespace ROOT::Math; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HFCandidateCreator2Prong { @@ -50,8 +47,8 @@ struct HFCandidateCreator2Prong { "stop iterations if largest change of any X is smaller than this"}; Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; - double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); - double massK = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); + double massPi = RecoDecay::getMassPDG(kPiPlus); + double massK = RecoDecay::getMassPDG(kKPlus); void process(aod::Collision const& collision, aod::HfTrackIndexProng2 const& hftrackindexprong2s, @@ -65,8 +62,8 @@ struct HFCandidateCreator2Prong { df.setMinParamChange(d_minparamchange); df.setMinRelChi2Change(d_minrelchi2change); - double mass2PiK{0}; - double mass2KPi{0}; + double massPiK{0}; + double massKPi{0}; // loop over 2-prong secondary vertices for (auto& hfpr2 : hftrackindexprong2s) { @@ -77,27 +74,24 @@ struct HFCandidateCreator2Prong { if (nCand == 0) continue; const auto& vtx = df.getPCACandidate(); - std::array<float, 3> pvec0; - std::array<float, 3> pvec1; + array<float, 3> pvec0; + array<float, 3> pvec1; df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); - mass2PiK = invmass2prongs( - pvec0[0], pvec0[1], pvec0[2], massPi, - pvec1[0], pvec1[1], pvec1[2], massK); - mass2KPi = invmass2prongs( - pvec0[0], pvec0[1], pvec0[2], massK, - pvec1[0], pvec1[1], pvec1[2], massPi); + auto arrMom = array{pvec0, pvec1}; + massPiK = RecoDecay::M(arrMom, array{massPi, massK}); + massKPi = RecoDecay::M(arrMom, array{massK, massPi}); hfcandprong2(collision.posX(), collision.posY(), collision.posZ(), pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], - vtx[0], vtx[1], vtx[2], mass2PiK, mass2KPi); - if (b_dovalplots == true) { + vtx[0], vtx[1], vtx[2], massPiK, massKPi); + if (b_dovalplots) { hvtx_x_out->Fill(vtx[0]); hvtx_y_out->Fill(vtx[1]); hvtx_z_out->Fill(vtx[2]); - hmass2->Fill(mass2PiK); - hmass2->Fill(mass2KPi); + hmass2->Fill(massPiK); + hmass2->Fill(massKPi); } } } diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index 5c30c55c8f1a6..b71320ef82500 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -14,14 +14,12 @@ #include "Analysis/SecondaryVertexHF.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" #include "Analysis/trackUtilities.h" +#include "Analysis/RecoDecay.h" #include <TFile.h> #include <TH1F.h> -#include <Math/Vector4D.h> -#include <TPDGCode.h> -#include <TDatabasePDG.h> + #include <cmath> #include <array> #include <cstdlib> @@ -30,7 +28,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -using namespace ROOT::Math; namespace o2::aod { @@ -110,8 +107,8 @@ struct HFTrackIndexSkimsCreator { Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; Filter seltrack = (aod::seltrack::issel == 1); - double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); - double massK = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); + double massPi = RecoDecay::getMassPDG(kPiPlus); + double massK = RecoDecay::getMassPDG(kKPlus); void process(aod::Collision const& collision, aod::BCs const& bcs, @@ -145,8 +142,7 @@ struct HFTrackIndexSkimsCreator { double mass2PiK{0}; double mass2KPi{0}; - double mass3PiKPiPlus{0}; - double mass3PiKPiMinus{0}; + double mass3PiKPi{0}; // first loop over positive tracks for (auto i_p1 = tracks.begin(); i_p1 != tracks.end(); ++i_p1) { @@ -168,17 +164,14 @@ struct HFTrackIndexSkimsCreator { if (nCand == 0) continue; const auto& vtx = df.getPCACandidate(); - std::array<float, 3> pvec0; - std::array<float, 3> pvec1; + array<float, 3> pvec0; + array<float, 3> pvec1; df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); - mass2PiK = invmass2prongs( - pvec0[0], pvec0[1], pvec0[2], massPi, - pvec1[0], pvec1[1], pvec1[2], massK); - mass2KPi = invmass2prongs( - pvec0[0], pvec0[1], pvec0[2], massK, - pvec1[0], pvec1[1], pvec1[2], massPi); + auto arrMom = array{pvec0, pvec1}; + mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); + mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); if (b_dovalplots) { hmass2->Fill(mass2PiK); @@ -197,12 +190,13 @@ struct HFTrackIndexSkimsCreator { if (track_p2.signed1Pt() < 0) continue; - mass3PiKPiPlus = invmass3prongs( - track_p1.px(), track_p1.py(), track_p1.pz(), massPi, - track_n1.px(), track_n1.py(), track_n1.pz(), massK, - track_p2.px(), track_p2.py(), track_p2.pz(), massPi); + auto arr3Mom = array{ + array{track_p1.px(), track_p1.py(), track_p1.pz()}, + array{track_n1.px(), track_n1.py(), track_n1.pz()}, + array{track_p2.px(), track_p2.py(), track_p2.pz()}}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - if (mass3PiKPiPlus < d_minmassDp || mass3PiKPiPlus > d_maxmassDp) + if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) continue; auto trackparvar_p2 = getTrackParCov(track_p2); @@ -211,20 +205,18 @@ struct HFTrackIndexSkimsCreator { if (nCand3 == 0) continue; const auto& vtx3 = df3.getPCACandidate(); - std::array<float, 3> pvec0; - std::array<float, 3> pvec1; - std::array<float, 3> pvec2; + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; df3.getTrack(0).getPxPyPzGlo(pvec0); df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); - mass3PiKPiPlus = invmass3prongs( - pvec0[0], pvec0[1], pvec0[2], massPi, - pvec1[0], pvec1[1], pvec1[2], massK, - pvec2[0], pvec2[1], pvec2[2], massPi); + arr3Mom = array{pvec0, pvec1, pvec2}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); if (b_dovalplots) { - hmass3->Fill(mass3PiKPiPlus); + hmass3->Fill(mass3PiKPi); } hftrackindexprong3(track_p1.collisionId(), @@ -238,12 +230,13 @@ struct HFTrackIndexSkimsCreator { if (track_n2.signed1Pt() > 0) continue; - mass3PiKPiMinus = invmass3prongs( - track_n1.px(), track_n1.py(), track_n1.pz(), massPi, - track_p1.px(), track_p1.py(), track_p1.pz(), massK, - track_n2.px(), track_n2.py(), track_n2.pz(), massPi); + auto arr3Mom = array{ + array{track_n1.px(), track_n1.py(), track_n1.pz()}, + array{track_p1.px(), track_p1.py(), track_p1.pz()}, + array{track_n2.px(), track_n2.py(), track_n2.pz()}}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - if (mass3PiKPiMinus < d_minmassDp || mass3PiKPiMinus > d_maxmassDp) + if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) continue; auto trackparvar_n2 = getTrackParCov(track_n2); @@ -252,20 +245,18 @@ struct HFTrackIndexSkimsCreator { if (nCand3 == 0) continue; const auto& vtx3 = df3.getPCACandidate(); - std::array<float, 3> pvec0; - std::array<float, 3> pvec1; - std::array<float, 3> pvec2; + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; df3.getTrack(0).getPxPyPzGlo(pvec0); df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); - mass3PiKPiMinus = invmass3prongs( - pvec0[0], pvec0[1], pvec0[2], massPi, - pvec1[0], pvec1[1], pvec1[2], massK, - pvec2[0], pvec2[1], pvec2[2], massPi); + arr3Mom = array{pvec0, pvec1, pvec2}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); if (b_dovalplots) { - hmass3->Fill(mass3PiKPiMinus); + hmass3->Fill(mass3PiKPi); } hftrackindexprong3(track_n1.collisionId(), diff --git a/Analysis/Tasks/vertexerhf.cxx b/Analysis/Tasks/vertexerhf.cxx index 3ab8b2b19a52e..8bec265e41ba4 100644 --- a/Analysis/Tasks/vertexerhf.cxx +++ b/Analysis/Tasks/vertexerhf.cxx @@ -12,7 +12,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "Analysis/SecondaryVertex.h" -#include "Analysis/RecoDecay.h" +#include "Analysis/decayUtilities.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" From c168b1a41c803004095d87d75249661eb5e4eaa3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 10 Aug 2020 17:10:04 +0200 Subject: [PATCH 0307/1751] DPL Output Proxy: use the correct header / payload size when forwarding multipart (#4072) --- Framework/Core/src/ExternalFairMQDeviceProxy.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx index 78e79844db913..7320ba3eda9b6 100644 --- a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx +++ b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx @@ -434,8 +434,8 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, // TODO: we need to make a copy of the messages, maybe we can implement functionality in // the RawDeviceService to forward messages, but this also needs to take into account that // other consumers might exist - size_t headerMsgSize = o2::header::Stack::headerStackSize(reinterpret_cast<o2::byte const*>(first.header)); - auto* dh = o2::header::get<DataHeader*>(first.header); + size_t headerMsgSize = o2::header::Stack::headerStackSize(reinterpret_cast<o2::byte const*>(part.header)); + auto* dh = o2::header::get<DataHeader*>(part.header); if (!dh) { std::stringstream errorMessage; errorMessage << "no data header in " << *first.spec; From 06cbda456797c88a0f0aa9a72c73853c55c872e8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 10 Aug 2020 17:07:07 +0200 Subject: [PATCH 0308/1751] DPL: mark callback service as threadsafe --- Framework/Core/include/Framework/CallbackService.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Framework/Core/include/Framework/CallbackService.h b/Framework/Core/include/Framework/CallbackService.h index 004a660d830aa..deaf9b0a0f9e7 100644 --- a/Framework/Core/include/Framework/CallbackService.h +++ b/Framework/Core/include/Framework/CallbackService.h @@ -11,6 +11,7 @@ #define FRAMEWORK_CALLBACKSERVICE_H #include "CallbackRegistry.h" +#include "Framework/ServiceHandle.h" #include <tuple> class FairMQRegionInfo; @@ -27,6 +28,9 @@ class EndOfStreamContext; class CallbackService { public: + /// Callbacks are a global service because they will always be + /// invoked by the main thread only. + constexpr static ServiceKind service_kind = ServiceKind::Global; /// the defined processing steps at which a callback can be invoked enum class Id { Start, /**< Invoked before the inner loop is started */ From 2cc12c1439008212ca9519954dc6ec9d928d4fd3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 10 Aug 2020 17:08:09 +0200 Subject: [PATCH 0309/1751] DPL: make ControlService threadsafe --- Framework/Core/include/Framework/ControlService.h | 5 +++++ Framework/Core/include/Framework/TextControlService.h | 4 ++++ Framework/Core/src/TextControlService.cxx | 3 +++ 3 files changed, 12 insertions(+) diff --git a/Framework/Core/include/Framework/ControlService.h b/Framework/Core/include/Framework/ControlService.h index 492bc4071bd04..0fcfdcc696b42 100644 --- a/Framework/Core/include/Framework/ControlService.h +++ b/Framework/Core/include/Framework/ControlService.h @@ -10,6 +10,8 @@ #ifndef O2_FRAMEWORK_CONTROLSERVICE_H_ #define O2_FRAMEWORK_CONTROLSERVICE_H_ +#include "Framework/ServiceHandle.h" + namespace o2::framework { @@ -25,9 +27,12 @@ enum struct QuitRequest { /// A service that data processors can use to talk to control and ask for their /// own state change or others. +/// A ControlService is requried to be a ServiceKind::Global kind of service. class ControlService { public: + constexpr static ServiceKind service_kind = ServiceKind::Global; + /// Compatibility with old API. void readyToQuit(bool all) { this->readyToQuit(all ? QuitRequest::All : QuitRequest::Me); } /// Signal control that we are potentially ready to quit some / all diff --git a/Framework/Core/include/Framework/TextControlService.h b/Framework/Core/include/Framework/TextControlService.h index 45c91128f3c4f..fd2e207cb479c 100644 --- a/Framework/Core/include/Framework/TextControlService.h +++ b/Framework/Core/include/Framework/TextControlService.h @@ -10,9 +10,12 @@ #ifndef O2_FRAMEWORK_TEXTCONTROLSERVICE_H_ #define O2_FRAMEWORK_TEXTCONTROLSERVICE_H_ +#include "Framework/ServiceHandle.h" #include "Framework/ControlService.h" + #include <string> #include <regex> +#include <mutex> namespace o2::framework { @@ -49,6 +52,7 @@ class TextControlService : public ControlService bool mOnce = false; ServiceRegistry& mRegistry; DeviceState& mDeviceState; + std::mutex mMutex; }; bool parseControl(std::string const& s, std::smatch& match); diff --git a/Framework/Core/src/TextControlService.cxx b/Framework/Core/src/TextControlService.cxx index 0846c9ba46310..15f15cd565774 100644 --- a/Framework/Core/src/TextControlService.cxx +++ b/Framework/Core/src/TextControlService.cxx @@ -31,12 +31,14 @@ TextControlService::TextControlService(ServiceRegistry& registry, DeviceState& d // This will send an end of stream to all the devices downstream. void TextControlService::endOfStream() { + std::scoped_lock lock(mMutex); mDeviceState.streaming = StreamingState::EndOfStreaming; } // All we do is to printout void TextControlService::readyToQuit(QuitRequest what) { + std::scoped_lock lock(mMutex); if (mOnce == true) { return; } @@ -55,6 +57,7 @@ void TextControlService::readyToQuit(QuitRequest what) void TextControlService::notifyStreamingState(StreamingState state) { + std::scoped_lock lock(mMutex); switch (state) { case StreamingState::Idle: LOG(INFO) << "CONTROL_ACTION: NOTIFY_STREAMING_STATE IDLE"; From b0fc846fae2e7f3b1529ebacdb07c94347331b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Mon, 10 Aug 2020 20:12:19 +0200 Subject: [PATCH 0310/1751] Fix the #define guard. --- Analysis/DataModel/include/Analysis/RecoDecay.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index 6220e51cee3e7..8fafada78433f 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -13,8 +13,8 @@ /// /// \author Vít Kučera <vit.kucera@cern.ch>, CERN -#ifndef RECODECAY_H -#define RECODECAY_H +#ifndef O2_ANALYSIS_RECODECAY_H_ +#define O2_ANALYSIS_RECODECAY_H_ #include <tuple> #include <vector> @@ -376,4 +376,4 @@ class RecoDecay std::vector<std::tuple<int, double>> RecoDecay::mListMass; -#endif // RECODECAY_H +#endif // O2_ANALYSIS_RECODECAY_H_ From e4d10be8b37a3d8a200a84706547a72461283882 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 8 Aug 2020 02:16:03 +0200 Subject: [PATCH 0311/1751] Extra rANS getters for external dictionary creation --- Utilities/rANS/include/rANS/Decoder.h | 4 ++++ Utilities/rANS/include/rANS/Encoder.h | 5 +++++ .../rANS/include/rANS/internal/SymbolTable.h | 21 +++++++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Utilities/rANS/include/rANS/Decoder.h b/Utilities/rANS/include/rANS/Decoder.h index d3220e4f955f1..468f1bb629653 100644 --- a/Utilities/rANS/include/rANS/Decoder.h +++ b/Utilities/rANS/include/rANS/Decoder.h @@ -57,6 +57,10 @@ class Decoder template <typename stream_IT, typename source_IT> void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength) const; + size_t getAlphabetRangeBits() const { return mSymbolTable->getAlphabetRangeBits(); } + int getMinSymbol() const { return mSymbolTable->getMinSymbol(); } + int getMaxSymbol() const { return mSymbolTable->getMaxSymbol(); } + using coder_t = coder_T; using stream_t = stream_T; using source_t = source_T; diff --git a/Utilities/rANS/include/rANS/Encoder.h b/Utilities/rANS/include/rANS/Encoder.h index 3ce5aa8bc5f80..5c61a4cd6e9f0 100644 --- a/Utilities/rANS/include/rANS/Encoder.h +++ b/Utilities/rANS/include/rANS/Encoder.h @@ -57,6 +57,11 @@ class Encoder const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd) const; + size_t getProbabilityBits() const { return mProbabilityBits; } + size_t getAlphabetRangeBits() const { return mSymbolTable->getAlphabetRangeBits(); } + int getMinSymbol() const { return mSymbolTable->getMinSymbol(); } + int getMaxSymbol() const { return mSymbolTable->getMaxSymbol(); } + using coder_t = coder_T; using stream_t = stream_T; using source_t = source_T; diff --git a/Utilities/rANS/include/rANS/internal/SymbolTable.h b/Utilities/rANS/include/rANS/internal/SymbolTable.h index 91ea8e9c4c0d9..77d9380725dff 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolTable.h +++ b/Utilities/rANS/include/rANS/internal/SymbolTable.h @@ -18,7 +18,7 @@ #include <vector> #include <cstdint> - +#include <cmath> #include <fairlogger/Logger.h> #include "SymbolStatistics.h" @@ -43,14 +43,19 @@ class SymbolTable bool isLiteralSymbol(int64_t index) const; + size_t getAlphabetRangeBits() const; + int getMinSymbol() const { return mMin; } + int getMaxSymbol() const { return mMax; } + private: int mMin; + int mMax; std::vector<T*> mIndex; std::vector<T> mSymbols; }; template <typename T> -SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mIndex(), mSymbols() +SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mMax(symbolStats.getMaxSymbol()), mIndex(), mSymbols() { LOG(trace) << "start building symbol table"; @@ -97,6 +102,18 @@ inline const T& SymbolTable<T>::getLiteralSymbol() const return mSymbols.back(); } +template <typename T> +inline size_t SymbolTable<T>::getAlphabetRangeBits() const +{ + if (mMax - mMin > 0) { + return std::ceil(std::log2(mMax - mMin)); + } else if (mMax - mMin == 0) { + return 1; + } else { + return 0; + } +} + } // namespace internal } // namespace rans } // namespace o2 From f42f7132b18cf440d0c417f52d1924610b9fc5dd Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 13:41:17 +0200 Subject: [PATCH 0312/1751] CTFCoder base class to handle external dictionaries --- .../DetectorsCommonDataFormats/NameConf.h | 3 + Detectors/Base/CMakeLists.txt | 4 +- .../Base/include/DetectorsBase/CTFCoderBase.h | 85 +++++++++++++++++++ Detectors/Base/src/CTFCoderBase.cxx | 66 ++++++++++++++ Detectors/Base/src/DetectorsBaseLinkDef.h | 2 + 5 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 Detectors/Base/include/DetectorsBase/CTFCoderBase.h create mode 100644 Detectors/Base/src/CTFCoderBase.cxx diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/NameConf.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/NameConf.h index 1431d7d228479..e2eece219ebff 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/NameConf.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/NameConf.h @@ -82,6 +82,9 @@ class NameConf // standard name for digitization configuration output static constexpr std::string_view DIGITIZATIONCONFIGFILE = "o2simdigitizerworkflow_configuration.ini"; + // public standard CTF dictionary + static constexpr std::string_view CTFDICT = "ctf_dictionary"; // hardcoded + // Block for ITS/TPC matching static constexpr std::string_view TPCITS_TracksBranchName = "TPCITS"; ///< name of branch containing output matched tracks static constexpr std::string_view TPCITS_TPCMCTruthBranchName = "MatchTPCMCTruth"; ///< name of branch for output matched tracks TPC MC diff --git a/Detectors/Base/CMakeLists.txt b/Detectors/Base/CMakeLists.txt index 5fcd16c97e1f2..38a19f74d5fd3 100644 --- a/Detectors/Base/CMakeLists.txt +++ b/Detectors/Base/CMakeLists.txt @@ -18,6 +18,7 @@ o2_add_library(DetectorsBase src/Ray.cxx src/DCAFitter.cxx src/BaseDPLDigitizer.cxx + src/CTFCoderBase.cxx PUBLIC_LINK_LIBRARIES FairRoot::Base O2::CommonUtils O2::DetectorsCommonDataFormats @@ -40,7 +41,8 @@ o2_target_root_dictionary(DetectorsBase include/DetectorsBase/Ray.h include/DetectorsBase/MatCell.h include/DetectorsBase/MatLayerCyl.h - include/DetectorsBase/MatLayerCylSet.h) + include/DetectorsBase/MatLayerCylSet.h + include/DetectorsBase/CTFCoderBase.h) if(BUILD_SIMULATION) o2_add_test( diff --git a/Detectors/Base/include/DetectorsBase/CTFCoderBase.h b/Detectors/Base/include/DetectorsBase/CTFCoderBase.h new file mode 100644 index 0000000000000..031f4049d2072 --- /dev/null +++ b/Detectors/Base/include/DetectorsBase/CTFCoderBase.h @@ -0,0 +1,85 @@ +// 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 CTFCoderBase.h +/// \brief Declarations for CTFCoderBase class (support of external dictionaries) +/// \author ruben.shahoyan@cern.ch + +#ifndef _ALICEO2_CTFCODER_BASE_H_ +#define _ALICEO2_CTFCODER_BASE_H_ + +#include <memory> +#include <TFile.h> +#include <TTree.h> +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "rANS/rans.h" + +namespace o2 +{ +namespace ctf +{ + +/// this is a base class for particular detector CTF coder/decoder, provides common +/// interface to create external entropy encoders/decoders + +using DetID = o2::detectors::DetID; + +class CTFCoderBase +{ + + public: + enum class OpType : int { Encoder, + Decoder }; + + CTFCoderBase() = delete; + CTFCoderBase(int n) : mCoders(n) {} + + std::unique_ptr<TFile> loadDictionaryTreeFile(const std::string& dictPath, DetID det, bool mayFail = false); + + template <typename CTF> + std::vector<char> readDictionaryFromFile(const std::string& dictPath, DetID det, bool mayFail = false) + { + std::vector<char> bufVec; + auto fileDict = loadDictionaryTreeFile(dictPath, det, mayFail); + if (fileDict) { + std::unique_ptr<TTree> tree((TTree*)fileDict->Get(std::string(o2::base::NameConf::CTFDICT).c_str())); + CTF::readFromTree(bufVec, *tree.get(), det.getName()); + } + return bufVec; + } + + template <typename S> + void createCoder(OpType op, const o2::rans::FrequencyTable& freq, uint8_t probabilityBits, int slot) + { + if (op == OpType::Encoder) { + mCoders[slot].reset(new o2::rans::LiteralEncoder64<S>(freq, probabilityBits)); + } else { + mCoders[slot].reset(new o2::rans::LiteralDecoder64<S>(freq, probabilityBits)); + } + } + + void clear() + { + for (auto c : mCoders) { + c.reset(); + } + } + + protected: + std::vector<std::shared_ptr<void>> mCoders; // encoders/decoders + + ClassDefNV(CTFCoderBase, 1); +}; + +} // namespace ctf +} // namespace o2 + +#endif diff --git a/Detectors/Base/src/CTFCoderBase.cxx b/Detectors/Base/src/CTFCoderBase.cxx new file mode 100644 index 0000000000000..57ae2214ac782 --- /dev/null +++ b/Detectors/Base/src/CTFCoderBase.cxx @@ -0,0 +1,66 @@ +// 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 CTFCoderBase.cxx +/// \brief Defintions for CTFCoderBase class (support of external dictionaries) +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsCommonDataFormats/CTFHeader.h" +#include "DetectorsBase/CTFCoderBase.h" + +using namespace o2::ctf; + +template <typename T> +bool readFromTree(TTree& tree, const std::string brname, T& dest, int ev = 0) +{ + auto* br = tree.GetBranch(brname.c_str()); + if (br && br->GetEntries() > ev) { + auto* ptr = &dest; + br->SetAddress(&ptr); + br->GetEntry(ev); + br->ResetAddress(); + return true; + } + return false; +} + +std::unique_ptr<TFile> CTFCoderBase::loadDictionaryTreeFile(const std::string& dictPath, DetID det, bool mayFail) +{ + TDirectory* curd = gDirectory; + std::unique_ptr<TFile> fileDict(TFile::Open(dictPath.c_str())); + if (!fileDict || fileDict->IsZombie()) { + if (mayFail) { + LOG(INFO) << "CTF dictionary file " << dictPath << " for detector " << det.getName() << " is absent, will use dictionaries stored in CTF"; + fileDict.reset(); + return std::move(fileDict); + } + LOG(ERROR) << "Failed to open CTF dictionary file " << dictPath << " for detector " << det.getName(); + throw std::runtime_error("Failed to open dictionary file"); + } + auto tnm = std::string(o2::base::NameConf::CTFDICT); + std::unique_ptr<TTree> tree((TTree*)fileDict->Get(tnm.c_str())); + if (!tree) { + fileDict.reset(); + LOG(ERROR) << "Did not find CTF dictionary tree " << tnm << " in " << dictPath; + throw std::runtime_error("Did not fine CTF dictionary tree in the file"); + } + CTFHeader ctfHeader; + if (!readFromTree(*tree.get(), "CTFHeader", ctfHeader) || !ctfHeader.detectors[det]) { + tree.reset(); + fileDict.reset(); + LOG(ERROR) << "Did not find CTF dictionary header or Detector " << det.getName() << " in it"; + if (!mayFail) { + throw std::runtime_error("did not find CTFHeader with needed detector"); + } + } else { + LOG(INFO) << "Found CTF dictionary for " << det.getName() << " in " << dictPath; + } + return fileDict; +} diff --git a/Detectors/Base/src/DetectorsBaseLinkDef.h b/Detectors/Base/src/DetectorsBaseLinkDef.h index d927d33a8c945..5e7edcfdc77f3 100644 --- a/Detectors/Base/src/DetectorsBaseLinkDef.h +++ b/Detectors/Base/src/DetectorsBaseLinkDef.h @@ -29,4 +29,6 @@ #pragma link C++ class o2::base::DCAFitter + ; +#pragma link C++ class o2::ctf::CTFCoderBase + ; + #endif From e117bf4121f18ca4cea0f86cc492241057a85c26 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 13:45:59 +0200 Subject: [PATCH 0313/1751] EncodedBlocks support external encoders / decoders A (void) pointer on externally created EncoderLiteral or DecoderLiteral can be provided to encode and decode methods respectively. The external decoder will be used for decoding ONLY if the Block does not contain stored dictionary data. --- .../EncodedBlocks.h | 233 +++++++++++------- 1 file changed, 148 insertions(+), 85 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index ceefb8a6c5587..267187a9b48dc 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -108,13 +108,6 @@ struct Registry { return head + offsFreeStart; } - /// advance the head of the writeable space - void shrinkFreeBlock(size_t sz) - { - offsFreeStart = alignSize(offsFreeStart + sz); - assert(offsFreeStart <= size); - } - /// size in bytes available to fill data size_t getFreeSize() const { @@ -135,23 +128,14 @@ struct Block { int nStored = 0; // total length W* payload = nullptr; //[nStored]; - inline const W* getDict() const { return nDict ? payload : nullptr; }; - inline const W* getData() const { return payload ? (payload + nDict) : nullptr; }; - inline const W* getLiterals() const { return nLiterals ? (payload + nDict + nData) : nullptr; }; + inline const W* getDict() const { return nDict ? payload : nullptr; } + inline const W* getData() const { return payload ? (payload + nDict) : nullptr; } + inline const W* getLiterals() const { return nLiterals ? (payload + nDict + nData) : nullptr; } - inline W* getDict() { return payload ? payload : (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())); }; - inline W* getData() { return payload ? (payload + nDict) : (registry ? (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())) : nullptr); }; - W* getLiterals() - { - if (payload) { - return payload + nDict + nData; - } - if (registry) { - payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); - return payload + nDict + nData; - } - return nullptr; - }; + inline W* getCreatePayload() { return payload ? payload : (registry ? (payload = reinterpret_cast<W*>(registry->getFreeBlockStart())) : nullptr); } + inline W* getCreateDict() { return payload ? payload : getCreatePayload(); } + inline W* getCreateData() { return payload ? (payload + nDict) : getCreatePayload(); } + inline W* getCreateLiterals() { return payload ? payload + (nDict + nData) : getCreatePayload(); } inline void setNDict(int _ndict) { @@ -194,9 +178,9 @@ struct Block { } /// estimate free size needed to add new block - static size_t estimateSize(int _ndict, int _ndata, int _nliterals) + static size_t estimateSize(int n) { - return alignSize((_ndict + _ndata + _nliterals) * sizeof(W)); + return alignSize(n * sizeof(W)); } // store a dictionary in an empty block @@ -205,13 +189,14 @@ struct Block { if (getNStored() > 0) { throw std::runtime_error("trying to write in occupied block"); } - size_t sz = estimateSize(_ndict, 0, 0); + size_t sz = estimateSize(_ndict); assert(registry); // this method is valid only for flat version, which has a registry assert(sz <= registry->getFreeSize()); assert((_ndict > 0) == (_dict != nullptr)); setNDict(_ndict); if (nDict) { - memcpy(getDict(), _dict, _ndict * sizeof(W)); + memcpy(getCreateDict(), _dict, _ndict * sizeof(W)); + realignBlock(); } }; @@ -222,13 +207,14 @@ struct Block { throw std::runtime_error("trying to write in occupied block"); } - size_t sz = estimateSize(0, _ndata, 0); + size_t sz = estimateSize(_ndata); assert(registry); // this method is valid only for flat version, which has a registry assert(sz <= registry->getFreeSize()); assert((_ndata > 0) == (_data != nullptr)); setNData(_ndata); if (nData) { - memcpy(getData(), _data, _ndata * sizeof(W)); + memcpy(getCreateData(), _data, _ndata * sizeof(W)); + realignBlock(); } } @@ -239,27 +225,28 @@ struct Block { throw std::runtime_error("trying to write in occupied block"); } - size_t sz = estimateSize(0, 0, _nliterals); + size_t sz = estimateSize(_nliterals); assert(registry); // this method is valid only for flat version, which has a registry assert(sz <= registry->getFreeSize()); // assert((_nliterals > 0) == (_literals != nullptr)); setNLiterals(_nliterals); if (nLiterals) { - memcpy(getLiterals(), _literals, _nliterals * sizeof(W)); + memcpy(getCreateLiterals(), _literals, _nliterals * sizeof(W)); + realignBlock(); } } // resize block and free up unused buffer space. - void endBlock() + void realignBlock() { - size_t sz = estimateSize(getNStored(), 0, 0); - registry->shrinkFreeBlock(sz); + size_t sz = estimateSize(getNStored()); + registry->offsFreeStart = (reinterpret_cast<char*>(payload) - registry->head) + sz; } /// store binary blob data (buffer filled from head to tail) void store(int _ndict, int _ndata, int _nliterals, const W* _dict, const W* _data, const W* _literals) { - size_t sz = estimateSize(_ndict, _ndata, _nliterals); + size_t sz = estimateSize(_ndict + _ndata + _nliterals); assert(registry); // this method is valid only for flat version, which has a registry assert(sz <= registry->getFreeSize()); assert((_ndict > 0) == (_dict != nullptr)); @@ -271,16 +258,16 @@ struct Block { if (getNStored()) { payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); if (getNDict()) { - memcpy(getDict(), _dict, _ndict * sizeof(W)); + memcpy(getCreateDict(), _dict, _ndict * sizeof(W)); } if (getNData()) { - memcpy(getData(), _data, _ndata * sizeof(W)); + memcpy(getCreateData(), _data, _ndata * sizeof(W)); } if (getNLiterals()) { - memcpy(getLiterals(), _literals, _nliterals * sizeof(W)); + memcpy(getCreateLiterals(), _literals, _nliterals * sizeof(W)); } } - registry->shrinkFreeBlock(sz); + realignBlock(); } /// relocate to different head position @@ -307,6 +294,18 @@ class EncodedBlocks const auto& getMetadata() const { return mMetadata; } + auto& getMetadata(int i) const + { + assert(i < N); + return mMetadata[i]; + } + + auto& getBlock(int i) const + { + assert(i < N); + return mBlocks[i]; + } + void setANSHeader(const ANSHeader& h) { mANSHeader = h; } const ANSHeader& getANSHeader() const { return mANSHeader; } ANSHeader& getANSHeader() { return mANSHeader; } @@ -330,7 +329,7 @@ class EncodedBlocks static auto create(VD& v); /// estimate free size needed to add new block - static size_t estimateBlockSize(int _ndict, int _ndata, int _nliterals) { return Block<W>::estimateSize(_ndict, _ndata, _nliterals); } + static size_t estimateBlockSize(int n) { return Block<W>::estimateSize(n); } /// check if empty and valid bool empty() const { return (mRegistry.offsFreeStart == alignSize(sizeof(*this))) && (mRegistry.size >= mRegistry.offsFreeStart); } @@ -373,25 +372,29 @@ class EncodedBlocks /// encode vector src to bloc at provided slot template <typename VE, typename VB> - inline void encode(const VE& src, int slot, uint8_t probabilityBits, Metadata::OptStore opt, VB* buffer = nullptr) + inline void encode(const VE& src, int slot, uint8_t probabilityBits, Metadata::OptStore opt, VB* buffer = nullptr, const void* encoderExt = nullptr) { - encode(&(*src.begin()), &(*src.end()), slot, probabilityBits, opt, buffer); + encode(&(*src.begin()), &(*src.end()), slot, probabilityBits, opt, buffer, encoderExt); } /// encode vector src to bloc at provided slot template <typename S, typename VB> - void encode(const S* const srcBegin, const S* const srcEnd, int slot, uint8_t probabilityBits, Metadata::OptStore opt, VB* buffer = nullptr); + void encode(const S* const srcBegin, const S* const srcEnd, int slot, uint8_t probabilityBits, Metadata::OptStore opt, VB* buffer = nullptr, + const void* encoderExt = nullptr); /// decode block at provided slot to destination vector (will be resized as needed) template <typename VD> - void decode(VD& dest, int slot) const; + void decode(VD& dest, int slot, const void* decoderExt = nullptr) const; /// decode block at provided slot to destination pointer, the needed space assumed to be available template <typename D> - void decode(D* dest, int slot) const; + void decode(D* dest, int slot, const void* decoderExt = nullptr) const; + + /// create a special EncodedBlocks containing only dictionaries made from provided vector of frequency tables + static std::vector<char> createDictionaryBlocks(const std::vector<o2::rans::FrequencyTable>& vfreq, const std::vector<Metadata>& prbits); /// print itself - void print() const; + void print(const std::string& prefix = "") const; protected: static_assert(N > 0, "number of encoded blocks < 1"); @@ -618,7 +621,6 @@ const auto EncodedBlocks<H, N, W>::getImage(const void* newHead) // now fix its pointers // we don't modify newHead, but still need to remove constness for relocation interface relocate(image.mRegistry.head, const_cast<char*>(reinterpret_cast<const char*>(newHead)), reinterpret_cast<char*>(&image)); - image.print(); return std::move(image); } @@ -650,48 +652,68 @@ inline auto EncodedBlocks<H, N, W>::create(VD& v) ///_____________________________________________________________________________ /// print itself template <typename H, int N, typename W> -void EncodedBlocks<H, N, W>::print() const +void EncodedBlocks<H, N, W>::print(const std::string& prefix) const { - LOG(INFO) << "Container " << N << " blocks, size: " << size() << " bytes, unused: " << getFreeSize(); + LOG(INFO) << prefix << "Container of " << N << " blocks, size: " << size() << " bytes, unused: " << getFreeSize(); for (int i = 0; i < N; i++) { - LOG(INFO) << "Block " << i << " NDictWords: " << mBlocks[i].getNDict() << " NDataWords: " << mBlocks[i].getNData(); + LOG(INFO) << "Block " << i << " NDictWords: " << mBlocks[i].getNDict() << " NDataWords: " << mBlocks[i].getNData() + << " NLiteralWords: " << mBlocks[i].getNLiterals(); } } ///_____________________________________________________________________________ template <typename H, int N, typename W> template <typename VD> -inline void EncodedBlocks<H, N, W>::decode(VD& dest, // destination container - int slot) const // slot of the block to decode +inline void EncodedBlocks<H, N, W>::decode(VD& dest, // destination container + int slot, // slot of the block to decode + const void* decoderExt) const // optional externally provided decoder { dest.resize(mMetadata[slot].messageLength); // allocate output buffer - decode(dest.data(), slot); + decode(dest.data(), slot, decoderExt); } ///_____________________________________________________________________________ template <typename H, int N, typename W> template <typename D> -void EncodedBlocks<H, N, W>::decode(D* dest, // destination pointer - int slot) const // slot of the block to decode +void EncodedBlocks<H, N, W>::decode(D* dest, // destination pointer + int slot, // slot of the block to decode + const void* decoderExt) const // optional externally provided decoder { // get references to the right data const auto& block = mBlocks[slot]; const auto& md = mMetadata[slot]; // decode - if (block.getNData()) { + if (block.getNStored()) { if (md.opt == Metadata::OptStore::EENCODE) { - assert(block.getNDict()); // at the moment we expect to have dictionary - o2::rans::FrequencyTable frequencies; - frequencies.addFrequencies(block.getDict(), block.getDict() + block.getNDict(), md.min, md.max); + if (!decoderExt && !block.getNDict()) { + LOG(ERROR) << "Dictionaty is not saved for slot " << slot << " and no external decoder is provided"; + throw std::runtime_error("Dictionary is not saved and no external decoder provided"); + } + const o2::rans::LiteralDecoder64<D>* decoder = reinterpret_cast<const o2::rans::LiteralDecoder64<D>*>(decoderExt); + std::unique_ptr<o2::rans::LiteralDecoder64<D>> decoderLoc; + if (block.getNDict()) { // if dictionaty is saved, prefer it + o2::rans::FrequencyTable frequencies; + frequencies.addFrequencies(block.getDict(), block.getDict() + block.getNDict(), md.min, md.max); + decoderLoc = std::make_unique<o2::rans::LiteralDecoder64<D>>(frequencies, md.probabilityBits); + decoder = decoderLoc.get(); + } else { // verify that decoded corresponds to stored metadata + if (md.min != decoder->getMinSymbol() || md.max != decoder->getMaxSymbol()) { + LOG(ERROR) << "Mismatch between min=" << md.min << "/" << md.max << " symbols in metadata and those in external decoder " + << decoder->getMinSymbol() << "/" << decoder->getMaxSymbol() << " for slot " << slot; + throw std::runtime_error("Mismatch between min/max symbols in metadata and those in external decoder"); + } + } // load incompressible symbols if they existed std::vector<D> literals; - if (md.nLiterals) { + if (block.getNLiterals()) { + // note: here we have to use md.nLiterals (original number of literal words) rather than md.nLiteralWords == block.getNLiterals() + // (number of W-words in the EncodedBlock occupied by literals) as we cast literals stored in W-word array + // to D-word array literals = std::vector<D>{reinterpret_cast<const D*>(block.getLiterals()), reinterpret_cast<const D*>(block.getLiterals()) + md.nLiterals}; } - o2::rans::LiteralDecoder64<D> decoder(frequencies, md.probabilityBits); - decoder.process(dest, block.getData() + block.getNData(), md.messageLength, literals); + decoder->process(dest, block.getData() + block.getNData(), md.messageLength, literals); } else { // data was stored as is std::memcpy(dest, block.payload, md.messageLength * sizeof(D)); } @@ -706,7 +728,9 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source int slot, // slot in encoded data to fill uint8_t probabilityBits, // encoding into Metadata::OptStore opt, // option for data compression - VB* buffer) // optional buffer (vector) providing memory for encoded blocks + VB* buffer, // optional buffer (vector) providing memory for encoded blocks + const void* encoderExt) // optional external encoder + { // fill a new block assert(slot == mRegistry.nFilledBlocks); @@ -725,19 +749,19 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source return; } static_assert(std::is_same<W, stream_t>()); - std::unique_ptr<rans::FrequencyTable> frequencies = nullptr; Metadata md; auto* bl = &mBlocks[slot]; auto* meta = &mMetadata[slot]; // resize underlying buffer of block if necessary and update all pointers. - auto expandStorage = [&](int dictElems, int encodeBufferElems) { - auto szNeed = estimateBlockSize(dictElems, encodeBufferElems, 0); // size in bytes!!! - if (szNeed >= getFreeSize()) { - LOG(INFO) << "Slot " << slot << ": free size: " << getFreeSize() << ", need " << szNeed; + auto expandStorage = [&](int nElems) { + auto eeb = get(bl->registry->head); // extract pointer from the block, as "this" might be invalid + auto szNeed = eeb->estimateBlockSize(nElems); // size in bytes!!! + if (szNeed >= bl->registry->getFreeSize()) { + LOG(INFO) << "Slot " << slot << ": free size: " << bl->registry->getFreeSize() << ", need " << szNeed << " for " << nElems << " words"; if (buffer) { - expand(*buffer, size() + (szNeed - getFreeSize())); + eeb->expand(*buffer, size() + (szNeed - getFreeSize())); meta = &(get(buffer->data())->mMetadata[slot]); bl = &(get(buffer->data())->mBlocks[slot]); // in case of resizing this and any this.xxx becomes invalid } else { @@ -749,47 +773,86 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source // case 3: message where entropy coding should be applied if (opt == Metadata::OptStore::EENCODE) { // build symbol statistics - frequencies = std::make_unique<rans::FrequencyTable>(); - frequencies->addSamples(srcBegin, srcEnd); - const o2::rans::LiteralEncoder64<S> encoder{*frequencies, probabilityBits}; - const int dictSize = frequencies->size(); + const o2::rans::LiteralEncoder64<S>* encoder = reinterpret_cast<const o2::rans::LiteralEncoder64<S>*>(encoderExt); + std::unique_ptr<o2::rans::LiteralEncoder64<S>> encoderLoc; + std::unique_ptr<o2::rans::FrequencyTable> frequencies = nullptr; + int dictSize = 0; + if (!encoder) { // no external encoder provide, create one on spot + frequencies = std::make_unique<o2::rans::FrequencyTable>(); + frequencies->addSamples(srcBegin, srcEnd); + encoderLoc = std::make_unique<o2::rans::LiteralEncoder64<S>>(*frequencies, probabilityBits); + encoder = encoderLoc.get(); + dictSize = frequencies->size(); + } + assert(probabilityBits == encoder->getProbabilityBits()); + // const o2::rans::LiteralEncoder64<S> encoder{*frequencies, probabilityBits}; // estimate size of encode buffer - int dataSize = rans::calculateMaxBufferSize(messageLength, - frequencies->getAlphabetRangeBits(), - sizeof(S)); + int dataSize = rans::calculateMaxBufferSize(messageLength, encoder->getAlphabetRangeBits(), sizeof(S)); // preliminary expansion of storage based on dict size + estimated size of encode buffer - expandStorage(dictSize, dataSize); + expandStorage(dictSize + dataSize); //store dictionary first - bl->storeDict(dictSize, frequencies->data()); + if (dictSize) { + bl->storeDict(dictSize, frequencies->data()); + } // vector of incompressible literal symbols std::vector<S> literals; // directly encode source message into block buffer. - const auto encodedMessageEnd = encoder.process(bl->getData(), bl->getData() + dataSize, srcBegin, srcEnd, literals); + const auto encodedMessageEnd = encoder->process(bl->getCreateData(), bl->getCreateData() + dataSize, srcBegin, srcEnd, literals); dataSize = encodedMessageEnd - bl->getData(); - // update the size claimed by encode message directly inside the block bl->setNData(dataSize); + bl->realignBlock(); + // update the size claimed by encode message directly inside the block // store incompressible symbols if any int literalSize = 0; if (literals.size()) { literalSize = (literals.size() * sizeof(S)) / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); + expandStorage(literalSize); bl->storeLiterals(literalSize, reinterpret_cast<const stream_t*>(literals.data())); } *meta = Metadata{messageLength, literals.size(), sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, - frequencies->getMinSymbol(), frequencies->getMaxSymbol(), dictSize, dataSize, literalSize}; + encoder->getMinSymbol(), encoder->getMaxSymbol(), dictSize, dataSize, literalSize}; } else { // store original data w/o EEncoding const size_t szb = messageLength * sizeof(S); const int dataSize = szb / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); // no dictionary needed - expandStorage(0, dataSize); - *meta = Metadata{messageLength, 0, sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, - 0, 0, 0, dataSize, 0}; + expandStorage(dataSize); + *meta = Metadata{messageLength, 0, sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, 0, 0, 0, dataSize, 0}; bl->storeData(meta->nDataWords, reinterpret_cast<const W*>(srcBegin)); } // resize block if necessary - bl->endBlock(); +} + +/// create a special EncodedBlocks containing only dictionaries made from provided vector of frequency tables +template <typename H, int N, typename W> +std::vector<char> EncodedBlocks<H, N, W>::createDictionaryBlocks(const std::vector<o2::rans::FrequencyTable>& vfreq, const std::vector<Metadata>& vmd) +{ + if (vfreq.size() != N) { + throw std::runtime_error("mismatch between the size of frequencies vector and number of blocks"); + } + size_t sz = sizeof(EncodedBlocks<H, N, W>); + for (int ib = 0; ib < N; ib++) { + LOG(INFO) << "bl " << ib << " sz= " << vfreq[ib].size() << " min/max " << vfreq[ib].getMinSymbol() << "/" << vfreq[ib].getMaxSymbol(); + sz += Block<W>::estimateSize(vfreq[ib].size()); + } + std::vector<char> vdict(sz); // memory space for dictionary + auto dictBlocks = create(vdict.data(), sz); + for (int ib = 0; ib < N; ib++) { + if (vfreq[ib].size()) { + LOG(INFO) << "adding dict of size " << vfreq[ib].size() << " for block " << ib; + dictBlocks->mBlocks[ib].storeDict(vfreq[ib].size(), vfreq[ib].data()); + dictBlocks = get(vdict.data()); // !!! rellocation might have invalidated dictBlocks pointer + dictBlocks->mMetadata[ib] = vmd[ib]; + dictBlocks->mMetadata[ib].opt = Metadata::OptStore::ROOTCompression; // we will compress the dictionary with root! + dictBlocks->mBlocks[ib].realignBlock(); + } else { + dictBlocks->mMetadata[ib].opt = Metadata::OptStore::NONE; + } + dictBlocks->mRegistry.nFilledBlocks++; + } + return std::move(vdict); } } // namespace ctf From 2c1378bd4477c64fe9484fbf247b77dd2b72b93f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 13:53:09 +0200 Subject: [PATCH 0314/1751] ctf-writer-workflow supports writing out dictionary instead of ctf o2-ctf-writer-workflow --output-type ctf / dict allows to chose between writing (default) CTF (per TF) or dictionaty (accumulated over all TFs processed) --- Detectors/CTF/README.md | 18 +++ .../include/CTFWorkflow/CTFWriterSpec.h | 84 +++++++++++- Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 124 +++++++++--------- .../CTF/workflow/src/ctf-writer-workflow.cxx | 12 +- 4 files changed, 171 insertions(+), 67 deletions(-) diff --git a/Detectors/CTF/README.md b/Detectors/CTF/README.md index 18d26a91a072c..b90ef22e2fa39 100644 --- a/Detectors/CTF/README.md +++ b/Detectors/CTF/README.md @@ -27,3 +27,21 @@ Example of usage: ```bash o2-ctf-reader-workflow --onlyDet ITS --ctf-input o2_ctf_0000000000.root | o2-its-reco-workflow --trackerCA --clusters-from-upstream --disable-mc ``` + +## Support for externally provided encoding dictionaries + +By default encoding with generate for every TF and store in the CTF the dictionary information necessary to decode the CTF. +Since the time needed for the creation of dictionary and encoder/decoder may exceed encoding/decoding time, there is a possibility +to create in a separate pass a dictionary stored in the CTF-like object and use it for further encoding/decoding. + +To create a dictionary run usual CTF creation chain but with extra option, e.g.: +```bash +o2-its-reco-workflow --entropy-encoding | o2-ctf-writer-workflow --output-type dict --onlyDet ITS +``` +This will create a file `ctf_dictionary.root` containing dictionary data for all detectors processed by the `o2-ctf-writer-workflow`. +Following encoding / decoding will use external dictionaries automatically if this file is found in the working directory (eventually it will be provided via CCDB). +Note that if the file is found but dictionary data for some detector participating in the workflow are not found, an error will be printed and for given detector +the workflows will use in-ctf dictionaries. +The dictionaries must be provided for decoding of CTF data encoded using external dictionaries (otherwise an exception will be thrown). + +When decoding CTF containing dictionary data (i.e. encoded w/o external dictionaries), the CTF-specific dictionary will be created/used on the fly, ignoring eventually provided external dictionary data. diff --git a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h index 57c40c84bf9d3..31a640072a6fe 100644 --- a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h +++ b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h @@ -19,6 +19,13 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" +#include "DetectorsCommonDataFormats/CTFHeader.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "DetectorsCommonDataFormats/EncodedBlocks.h" +#include "CommonUtils/StringUtils.h" +#include "rANS/rans.h" +#include <vector> +#include <array> #include <TStopwatch.h> namespace o2 @@ -27,11 +34,13 @@ namespace ctf { using DetID = o2::detectors::DetID; +using FTrans = o2::rans::FrequencyTable; class CTFWriterSpec : public o2::framework::Task { public: - CTFWriterSpec(DetID::mask_t dm, uint64_t r) : mDets(dm), mRun(r) + CTFWriterSpec() = delete; + CTFWriterSpec(DetID::mask_t dm, uint64_t r = 0, bool doCTF = true, bool doDict = false, bool dictPerDet = false) : mDets(dm), mRun(r), mWriteCTF(doCTF), mCreateDict(doDict), mDictPerDetector(dictPerDet) { mTimer.Stop(); mTimer.Reset(); @@ -43,13 +52,84 @@ class CTFWriterSpec : public o2::framework::Task bool isPresent(DetID id) const { return mDets[id]; } private: + template <typename C> + void processDet(o2::framework::ProcessingContext& pc, DetID det, CTFHeader& header, TTree* tree); + template <typename C> + void storeDictionary(DetID det, CTFHeader& header); + void storeDictionaries(); + void prepareDictionaryTreeAndFile(DetID det); + DetID::mask_t mDets; // detectors + bool mWriteCTF = false; + bool mCreateDict = false; + bool mDictPerDetector = false; + size_t mNTF = 0; uint64_t mRun = 0; + + std::unique_ptr<TFile> mDictFileOut; // file to store dictionary + std::unique_ptr<TTree> mDictTreeOut; // tree to store dictionary + + // For the external dictionary creation we accumulate for each detector the frequency tables of its each block + // After accumulation over multiple TFs we store the dictionaries data in the standard CTF format of this detector, + // i.e. EncodedBlock stored in a tree, BUT with dictionary data only added to each block. + // The metadata of the block (min,max) will be used for the consistency check at the decoding + std::array<std::vector<FTrans>, DetID::nDetectors> mFreqsAccumulation; + std::array<std::vector<o2::ctf::Metadata>, DetID::nDetectors> mFreqsMetaData; + TStopwatch mTimer; }; +// process data of particular detector +template <typename C> +void CTFWriterSpec::processDet(o2::framework::ProcessingContext& pc, DetID det, CTFHeader& header, TTree* tree) +{ + if (!isPresent(det) || !pc.inputs().isValid(det.getName())) { + return; + } + auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); + const auto ctfImage = C::getImage(ctfBuffer.data()); + ctfImage.print(o2::utils::concat_string(det.getName(), ": ")); + if (mWriteCTF) { + ctfImage.appendToTree(*tree, det.getName()); + header.detectors.set(det); + } + if (mCreateDict) { + if (!mFreqsAccumulation[det].size()) { + mFreqsAccumulation[det].resize(C::getNBlocks()); + mFreqsMetaData[det].resize(C::getNBlocks()); + } + for (int ib = 0; ib < C::getNBlocks(); ib++) { + const auto& bl = ctfImage.getBlock(ib); + if (bl.getNDict()) { + auto& freq = mFreqsAccumulation[det][ib]; + auto& mdSave = mFreqsMetaData[det][ib]; + const auto& md = ctfImage.getMetadata(ib); + freq.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + mdSave = o2::ctf::Metadata{0, 0, md.coderType, md.streamSize, md.probabilityBits, md.opt, freq.getMinSymbol(), freq.getMaxSymbol(), (int)freq.size(), 0, 0}; + } + } + } +} + +// store dictionary of a particular detector +template <typename C> +void CTFWriterSpec::storeDictionary(DetID det, CTFHeader& header) +{ + if (!isPresent(det) || !mFreqsAccumulation[det].size()) { + return; + } + prepareDictionaryTreeAndFile(det); + // create vector whose data contains dictionary in CTF format (EncodedBlock) + auto dictBlocks = C::createDictionaryBlocks(mFreqsAccumulation[det], mFreqsMetaData[det]); + C::get(dictBlocks.data())->print(o2::utils::concat_string("Storing dictionary for ", det.getName(), ": ")); + C::get(dictBlocks.data())->appendToTree(*mDictTreeOut.get(), det.getName()); // cast to EncodedBlock + mFreqsAccumulation[det].clear(); + mFreqsMetaData[det].clear(); + header.detectors.set(det); +} + /// create a processor spec -framework::DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run); +framework::DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run, bool doCTF = true, bool doDict = false, bool dictPerDet = false); } // namespace ctf } // namespace o2 diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index aa2b6586a4948..2506df8d710d5 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -18,11 +18,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/InputSpec.h" -#include "CommonUtils/StringUtils.h" #include "CTFWorkflow/CTFWriterSpec.h" -#include "DetectorsCommonDataFormats/EncodedBlocks.h" -#include "DetectorsCommonDataFormats/CTFHeader.h" -#include "DetectorsCommonDataFormats/NameConf.h" #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" #include "DataFormatsFT0/CTF.h" @@ -57,83 +53,83 @@ void CTFWriterSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); mTimer.Start(false); - auto tfOrb = DataRefUtils::getHeader<o2::header::DataHeader*>(pc.inputs().getByPos(0))->firstTForbit; - TFile flOut(o2::base::NameConf::getCTFFileName(tfOrb).c_str(), "recreate"); - TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + + std::unique_ptr<TFile> fileOut; + std::unique_ptr<TTree> treeOut; + if (mWriteCTF) { + fileOut.reset(TFile::Open(o2::base::NameConf::getCTFFileName(tfOrb).c_str(), "recreate")); + treeOut = std::make_unique<TTree>(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + } // create header CTFHeader header{mRun, tfOrb}; - DetID det; + processDet<o2::itsmft::CTF>(pc, DetID::ITS, header, treeOut.get()); + processDet<o2::itsmft::CTF>(pc, DetID::MFT, header, treeOut.get()); + processDet<o2::tpc::CTF>(pc, DetID::TPC, header, treeOut.get()); + processDet<o2::tof::CTF>(pc, DetID::TOF, header, treeOut.get()); + processDet<o2::ft0::CTF>(pc, DetID::FT0, header, treeOut.get()); - det = DetID::ITS; - if (isPresent(det) && pc.inputs().isValid(det.getName())) { - auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); - const auto ctfImage = o2::itsmft::CTF::getImage(ctfBuffer.data()); - LOG(INFO) << "CTF for " << det.getName(); - ctfImage.print(); - ctfImage.appendToTree(ctfTree, det.getName()); - header.detectors.set(det); - } - - det = DetID::MFT; - if (isPresent(det) && pc.inputs().isValid(det.getName())) { - auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); - const auto ctfImage = o2::itsmft::CTF::getImage(ctfBuffer.data()); - LOG(INFO) << "CTF for " << det.getName(); - ctfImage.print(); - ctfImage.appendToTree(ctfTree, det.getName()); - header.detectors.set(det); - } + mTimer.Stop(); - det = DetID::TPC; - if (isPresent(det) && pc.inputs().isValid(det.getName())) { - auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); - const auto ctfImage = o2::tpc::CTF::getImage(ctfBuffer.data()); - LOG(INFO) << "CTF for " << det.getName(); - ctfImage.print(); - ctfImage.appendToTree(ctfTree, det.getName()); - header.detectors.set(det); + if (mWriteCTF) { + appendToTree(*treeOut.get(), "CTFHeader", header); + treeOut->SetEntries(1); + treeOut->Write(); + treeOut.reset(); + fileOut->Close(); + LOG(INFO) << "TF#" << mNTF << ": wrote " << fileOut->GetName() << " with CTF{" << header << "} in " << mTimer.CpuTime() - cput << " s"; } + mNTF++; +} - det = DetID::FT0; - if (isPresent(det) && pc.inputs().isValid(det.getName())) { - auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); - const auto ctfImage = o2::ft0::CTF::getImage(ctfBuffer.data()); - LOG(INFO) << "CTF for " << det.getName(); - ctfImage.print(); - ctfImage.appendToTree(ctfTree, det.getName()); - header.detectors.set(det); - } +void CTFWriterSpec::endOfStream(EndOfStreamContext& ec) +{ - det = DetID::TOF; - if (isPresent(det) && pc.inputs().isValid(det.getName())) { - auto ctfBuffer = pc.inputs().get<gsl::span<o2::ctf::BufferType>>(det.getName()); - const auto ctfImage = o2::tof::CTF::getImage(ctfBuffer.data()); - LOG(INFO) << "CTF for " << det.getName(); - ctfImage.print(); - ctfImage.appendToTree(ctfTree, det.getName()); - header.detectors.set(det); + if (mCreateDict) { + storeDictionaries(); } - appendToTree(ctfTree, "CTFHeader", header); - - ctfTree.SetEntries(1); - ctfTree.Write(); - flOut.Close(); + LOGF(INFO, "CTF writing total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} - mTimer.Stop(); - LOG(INFO) << "Wrote " << flOut.GetName() << " with CTF{" << header << "} in " << mTimer.CpuTime() - cput << " s"; +void CTFWriterSpec::prepareDictionaryTreeAndFile(DetID det) +{ + if (mDictPerDetector) { + if (mDictTreeOut) { + mDictTreeOut->Write(); + mDictTreeOut.reset(); + mDictFileOut.reset(); + } + } + if (!mDictTreeOut) { + std::string fnm = mDictPerDetector ? o2::utils::concat_string(det.getName(), "_", o2::base::NameConf::CTFDICT, ".root") : o2::utils::concat_string(o2::base::NameConf::CTFDICT, ".root"); + mDictFileOut.reset(TFile::Open(fnm.c_str(), "recreate")); + mDictTreeOut = std::make_unique<TTree>(std::string(o2::base::NameConf::CTFDICT).c_str(), "O2 CTF dictionary"); + } } -void CTFWriterSpec::endOfStream(EndOfStreamContext& ec) +void CTFWriterSpec::storeDictionaries() { - LOGF(INFO, "CTF writing total timing: Cpu: %.3e Real: %.3e s in %d slots", - mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); + CTFHeader header{mRun, 0}; + storeDictionary<o2::itsmft::CTF>(DetID::ITS, header); + storeDictionary<o2::itsmft::CTF>(DetID::MFT, header); + storeDictionary<o2::tpc::CTF>(DetID::TPC, header); + storeDictionary<o2::tof::CTF>(DetID::TOF, header); + storeDictionary<o2::ft0::CTF>(DetID::FT0, header); + // close remnants + if (mDictTreeOut) { + mDictTreeOut->SetEntries(1); + appendToTree(*mDictTreeOut.get(), "CTFHeader", header); + mDictTreeOut->Write(); + mDictTreeOut.reset(); + mDictFileOut.reset(); + } } -DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run) +DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run, bool doCTF, bool doDict, bool dictPerDet) { std::vector<InputSpec> inputs; LOG(INFO) << "Det list:"; @@ -147,7 +143,7 @@ DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run) "ctf-writer", inputs, Outputs{}, - AlgorithmSpec{adaptFromTask<CTFWriterSpec>(dets, run)}, + AlgorithmSpec{adaptFromTask<CTFWriterSpec>(dets, run, doCTF, doDict, dictPerDet)}, Options{}}; } diff --git a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx index e35a3d7d83446..4bac58ca64966 100644 --- a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx @@ -30,6 +30,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) options.push_back(ConfigParamSpec{"onlyDet", VariantType::String, std::string{DetID::NONE}, {"comma separated list of detectors to accept. Overrides skipDet"}}); options.push_back(ConfigParamSpec{"skipDet", VariantType::String, std::string{DetID::NONE}, {"comma separate list of detectors to skip"}}); options.push_back(ConfigParamSpec{"grpfile", VariantType::String, o2::base::NameConf::getGRPFileName(), {"name of the grp file"}}); + options.push_back(ConfigParamSpec{"output-type", VariantType::String, "ctf", {"output types: ctf (per TF) or dict (create dictionaries)"}}); std::swap(workflowOptions, options); } @@ -40,11 +41,20 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { DetID::mask_t dets; long run = 0; + bool doCTF = true, doDict = false; if (!configcontext.helpOnCommandLine()) { std::unique_ptr<o2::parameters::GRPObject> grp(o2::parameters::GRPObject::loadFrom(configcontext.options().get<std::string>("grpfile"))); dets = grp->getDetsReadOut(configcontext.options().get<std::string>("onlyDet"), configcontext.options().get<std::string>("skipDet")); + auto outmode = configcontext.options().get<std::string>("output-type"); + if (outmode == "ctf") { + doCTF = true; + doDict = false; + } else if (outmode == "dict") { + doCTF = false; + doDict = true; + } run = grp->getRun(); } - WorkflowSpec specs{o2::ctf::getCTFWriterSpec(dets, run)}; + WorkflowSpec specs{o2::ctf::getCTFWriterSpec(dets, run, doCTF, doDict)}; return std::move(specs); } From 6fecf33a80b5cfc1a5ac6bbe18a21524932f3d25 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 13:54:12 +0200 Subject: [PATCH 0315/1751] support for external dictionaries in ITS/MFT --- .../common/include/DataFormatsITSMFT/CTF.h | 1 - Detectors/CTF/test/test_ctf_io_itsmft.cxx | 10 ++- .../include/ITSMFTReconstruction/CTFCoder.h | 66 +++++++++++-------- .../common/reconstruction/src/CTFCoder.cxx | 41 ++++++++++++ .../ITSMFTWorkflow/EntropyDecoderSpec.h | 3 + .../ITSMFTWorkflow/EntropyEncoderSpec.h | 3 + .../workflow/src/EntropyDecoderSpec.cxx | 16 ++++- .../workflow/src/EntropyEncoderSpec.cxx | 17 ++++- 8 files changed, 119 insertions(+), 38 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h index 12804de148c57..6002ca330189a 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h @@ -79,7 +79,6 @@ struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 10, uint32_t> { BLCcolInc, BLCpattID, BLCpattMap }; - ClassDefNV(CTF, 1); }; diff --git a/Detectors/CTF/test/test_ctf_io_itsmft.cxx b/Detectors/CTF/test/test_ctf_io_itsmft.cxx index 43d7353372606..262e446d403ff 100644 --- a/Detectors/CTF/test/test_ctf_io_itsmft.cxx +++ b/Detectors/CTF/test/test_ctf_io_itsmft.cxx @@ -69,7 +69,10 @@ BOOST_AUTO_TEST_CASE(CompressedClustersTest) sw.Start(); std::vector<o2::ctf::BufferType> vec; - CTFCoder::encode(vec, rofRecVec, cclusVec, pattVec); // compress + { + CTFCoder coder; + coder.encode(vec, rofRecVec, cclusVec, pattVec); // compress + } sw.Stop(); LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; @@ -103,7 +106,10 @@ BOOST_AUTO_TEST_CASE(CompressedClustersTest) std::vector<unsigned char> pattVecD; sw.Start(); const auto ctfImage = o2::itsmft::CTF::getImage(vec.data()); - CTFCoder::decode(ctfImage, rofRecVecD, cclusVecD, pattVecD); // decompress + { + CTFCoder coder; + coder.decode(ctfImage, rofRecVecD, cclusVecD, pattVecD); // decompress + } sw.Stop(); LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h index c4dfa639e4071..fa894ca6e4aa1 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h @@ -22,6 +22,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITSMFT/CompCluster.h" #include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" #include "rANS/rans.h" class TTree; @@ -31,27 +32,32 @@ namespace o2 namespace itsmft { -class CTFCoder +class CTFCoder : public o2::ctf::CTFCoderBase { public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + ~CTFCoder() = default; + /// entropy-encode clusters to buffer with CTF template <typename VEC> - static void encode(VEC& buff, const gsl::span<const ROFRecord>& rofRecVec, const gsl::span<const CompClusterExt>& cclusVec, const gsl::span<const unsigned char>& pattVec); + void encode(VEC& buff, const gsl::span<const ROFRecord>& rofRecVec, const gsl::span<const CompClusterExt>& cclusVec, const gsl::span<const unsigned char>& pattVec); /// entropy decode clusters from buffer with CTF template <typename VROF, typename VCLUS, typename VPAT> - static void decode(const CTF::base& ec, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec); + void decode(const CTF::base& ec, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec); + + void createCoders(const std::string& dictPath, o2::detectors::DetID det, o2::ctf::CTFCoderBase::OpType op); private: /// compres compact clusters to CompressedClusters - static void compress(CompressedClusters& cc, const gsl::span<const ROFRecord>& rofRecVec, const gsl::span<const CompClusterExt>& cclusVec, const gsl::span<const unsigned char>& pattVec); + void compress(CompressedClusters& cc, const gsl::span<const ROFRecord>& rofRecVec, const gsl::span<const CompClusterExt>& cclusVec, const gsl::span<const unsigned char>& pattVec); /// decompress CompressedClusters to compact clusters template <typename VROF, typename VCLUS, typename VPAT> - static void decompress(const CompressedClusters& cc, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec); + void decompress(const CompressedClusters& cc, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec); - static void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); - static void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ROFRecord>& rofRecVec, std::vector<CompClusterExt>& cclusVec, std::vector<unsigned char>& pattVec); + void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); + void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ROFRecord>& rofRecVec, std::vector<CompClusterExt>& cclusVec, std::vector<unsigned char>& pattVec); protected: ClassDefNV(CTFCoder, 1); @@ -84,20 +90,21 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ROFRecord>& rofRecVec, co ec->getANSHeader().majorVersion = 0; ec->getANSHeader().minorVersion = 1; // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec -#define ENCODE CTF::get(buff.data())->encode +#define ENCODEITSMFT(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODE(cc.firstChipROF, CTF::BLCfirstChipROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCfirstChipROF], &buff); - ENCODE(cc.bcIncROF, CTF::BLCbcIncROF , o2::rans::ProbabilityBits16Bit, optField[CTF::BLCbcIncROF], &buff); - ENCODE(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCorbitIncROF], &buff); - ENCODE(cc.nclusROF, CTF::BLCnclusROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCnclusROF], &buff); + ENCODEITSMFT(cc.firstChipROF, CTF::BLCfirstChipROF, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.nclusROF, CTF::BLCnclusROF, o2::rans::ProbabilityBits16Bit); // - ENCODE(cc.chipInc, CTF::BLCchipInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCchipInc], &buff); - ENCODE(cc.chipMul, CTF::BLCchipMul, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCchipMul], &buff); - ENCODE(cc.row, CTF::BLCrow, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCrow], &buff); - ENCODE(cc.colInc, CTF::BLCcolInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCcolInc], &buff); - ENCODE(cc.pattID, CTF::BLCpattID, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpattID], &buff); - ENCODE(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpattMap], &buff); + ENCODEITSMFT(cc.chipInc, CTF::BLCchipInc, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.chipMul, CTF::BLCchipMul, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.row, CTF::BLCrow, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.colInc, CTF::BLCcolInc, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.pattID, CTF::BLCpattID, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit); // clang-format on + CTF::get(buff.data())->print("ITS done: "); } /// decode entropy-encoded clusters to standard compact clusters @@ -106,18 +113,19 @@ void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VCLUS& cclusVec, VPA { CompressedClusters cc; cc.header = ec.getHeader(); +#define DECODEITSMFT(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off - ec.decode(cc.firstChipROF, CTF::BLCfirstChipROF); - ec.decode(cc.bcIncROF, CTF::BLCbcIncROF); - ec.decode(cc.orbitIncROF, CTF::BLCorbitIncROF); - ec.decode(cc.nclusROF, CTF::BLCnclusROF); - // - ec.decode(cc.chipInc, CTF::BLCchipInc); - ec.decode(cc.chipMul, CTF::BLCchipMul); - ec.decode(cc.row, CTF::BLCrow); - ec.decode(cc.colInc, CTF::BLCcolInc); - ec.decode(cc.pattID, CTF::BLCpattID); - ec.decode(cc.pattMap, CTF::BLCpattMap); + DECODEITSMFT(cc.firstChipROF, CTF::BLCfirstChipROF); + DECODEITSMFT(cc.bcIncROF, CTF::BLCbcIncROF); + DECODEITSMFT(cc.orbitIncROF, CTF::BLCorbitIncROF); + DECODEITSMFT(cc.nclusROF, CTF::BLCnclusROF); + // + DECODEITSMFT(cc.chipInc, CTF::BLCchipInc); + DECODEITSMFT(cc.chipMul, CTF::BLCchipMul); + DECODEITSMFT(cc.row, CTF::BLCrow); + DECODEITSMFT(cc.colInc, CTF::BLCcolInc); + DECODEITSMFT(cc.pattID, CTF::BLCpattID); + DECODEITSMFT(cc.pattMap, CTF::BLCpattMap); // clang-format on // decompress(cc, rofRecVec, cclusVec, pattVec); diff --git a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx index 3e50e5434cfca..9061422d121f5 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx @@ -119,3 +119,44 @@ void CTFCoder::compress(CompressedClusters& cc, // store explicit patters as they are memcpy(cc.pattMap.data(), pattVec.data(), cc.header.nPatternBytes); // RSTODO: do we need this? } + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::detectors::DetID det, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, det, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + CompressedClusters cc; // just to get member types +#define MAKECODER(part, slot) createCoder<decltype(part)::value_type>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(cc.firstChipROF, CTF::BLCfirstChipROF); + MAKECODER(cc.bcIncROF, CTF::BLCbcIncROF ); + MAKECODER(cc.orbitIncROF, CTF::BLCorbitIncROF ); + MAKECODER(cc.nclusROF, CTF::BLCnclusROF ); + // + MAKECODER(cc.chipInc, CTF::BLCchipInc ); + MAKECODER(cc.chipMul, CTF::BLCchipMul ); + MAKECODER(cc.row, CTF::BLCrow ); + MAKECODER(cc.colInc, CTF::BLCcolInc ); + MAKECODER(cc.pattID, CTF::BLCpattID ); + MAKECODER(cc.pattMap, CTF::BLCpattMap ); + // clang-format on +} diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h index 0b83758ba0537..f624eb1781b1f 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h @@ -17,6 +17,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "Headers/DataHeader.h" +#include "ITSMFTReconstruction/CTFCoder.h" #include <TStopwatch.h> namespace o2 @@ -29,11 +30,13 @@ class EntropyDecoderSpec : public o2::framework::Task public: EntropyDecoderSpec(o2::header::DataOrigin orig); ~EntropyDecoderSpec() override = default; + void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; + o2::itsmft::CTFCoder mCTFCoder; TStopwatch mTimer; }; diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h index 8607687028a8f..997f0f5eb192b 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h @@ -18,6 +18,7 @@ #include "Framework/Task.h" #include "Headers/DataHeader.h" #include <TStopwatch.h> +#include "ITSMFTReconstruction/CTFCoder.h" namespace o2 { @@ -30,10 +31,12 @@ class EntropyEncoderSpec : public o2::framework::Task EntropyEncoderSpec(o2::header::DataOrigin orig); ~EntropyEncoderSpec() override = default; void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; + o2::itsmft::CTFCoder mCTFCoder; TStopwatch mTimer; }; diff --git a/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx index 193497bee8010..7726485043400 100644 --- a/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx @@ -15,7 +15,6 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "DataFormatsITSMFT/CompCluster.h" -#include "ITSMFTReconstruction/CTFCoder.h" #include "ITSMFTWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; @@ -32,6 +31,15 @@ EntropyDecoderSpec::EntropyDecoderSpec(o2::header::DataOrigin orig) : mOrigin(or mTimer.Reset(); } +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>((mOrigin == o2::header::gDataOriginITS) ? "its-ctf-dictionary" : "mft-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, mOrigin == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT, + o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + void EntropyDecoderSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); @@ -45,7 +53,7 @@ void EntropyDecoderSpec::run(ProcessingContext& pc) // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object const auto ctfImage = o2::itsmft::CTF::getImage(buff.data()); - CTFCoder::decode(ctfImage, rofs, compcl, patterns); + mCTFCoder.decode(ctfImage, rofs, compcl, patterns); mTimer.Stop(); LOG(INFO) << "Decoded " << compcl.size() << " clusters in " << rofs.size() << " RO frames in " << mTimer.CpuTime() - cput << " s"; @@ -64,12 +72,14 @@ DataProcessorSpec getEntropyDecoderSpec(o2::header::DataOrigin orig) OutputSpec{{"patterns"}, orig, "PATTERNS", 0, Lifetime::Timeframe}, OutputSpec{{"ROframes"}, orig, "CLUSTERSROF", 0, Lifetime::Timeframe}}; + std::string dictOptName = (orig == o2::header::gDataOriginITS) ? "its-ctf-dictionary" : "mft-ctf-dictionary"; + return DataProcessorSpec{ orig == o2::header::gDataOriginITS ? "its-entropy-decoder" : "mft-entropy-decoder", Inputs{InputSpec{"ctf", orig, "CTFDATA", 0, Lifetime::Timeframe}}, outputs, AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>(orig)}, - Options{}}; + Options{{dictOptName, VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; } } // namespace itsmft diff --git a/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx index 6bd7baec5f1e7..38e8efbb03854 100644 --- a/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx @@ -15,8 +15,8 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "DataFormatsITSMFT/CompCluster.h" -#include "ITSMFTReconstruction/CTFCoder.h" #include "ITSMFTWorkflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" using namespace o2::framework; @@ -32,6 +32,15 @@ EntropyEncoderSpec::EntropyEncoderSpec(o2::header::DataOrigin orig) : mOrigin(or mTimer.Reset(); } +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>((mOrigin == o2::header::gDataOriginITS) ? "its-ctf-dictionary" : "mft-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, mOrigin == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT, + o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + void EntropyEncoderSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); @@ -41,7 +50,7 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) auto rofs = pc.inputs().get<gsl::span<o2::itsmft::ROFRecord>>("ROframes"); auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{mOrigin, "CTFDATA", 0, Lifetime::Timeframe}); - CTFCoder::encode(buffer, rofs, compClusters, pspan); + mCTFCoder.encode(buffer, rofs, compClusters, pspan); auto eeb = CTF::get(buffer.data()); // cast to container pointer eeb->compactify(); // eliminate unnecessary padding buffer.resize(eeb->size()); // shrink buffer to strictly necessary size @@ -63,12 +72,14 @@ DataProcessorSpec getEntropyEncoderSpec(o2::header::DataOrigin orig) inputs.emplace_back("patterns", orig, "PATTERNS", 0, Lifetime::Timeframe); inputs.emplace_back("ROframes", orig, "CLUSTERSROF", 0, Lifetime::Timeframe); + std::string dictOptName = (orig == o2::header::gDataOriginITS) ? "its-ctf-dictionary" : "mft-ctf-dictionary"; + return DataProcessorSpec{ orig == o2::header::gDataOriginITS ? "its-entropy-encoder" : "mft-entropy-encoder", inputs, Outputs{{orig, "CTFDATA", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>(orig)}, - Options{}}; + Options{{dictOptName, VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; } } // namespace itsmft From 69f17f63b68e23e17a71325976fe7ddaa1a6b71c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 13:54:43 +0200 Subject: [PATCH 0316/1751] support for external dictionaries in FT0 --- Detectors/CTF/test/test_ctf_io_ft0.cxx | 10 +++- .../include/FT0Reconstruction/CTFCoder.h | 60 +++++++++++-------- .../FIT/FT0/reconstruction/src/CTFCoder.cxx | 39 ++++++++++++ .../include/FT0Workflow/EntropyDecoderSpec.h | 3 + .../include/FT0Workflow/EntropyEncoderSpec.h | 3 + .../FT0/workflow/src/EntropyDecoderSpec.cxx | 13 +++- .../FT0/workflow/src/EntropyEncoderSpec.cxx | 14 ++++- 7 files changed, 108 insertions(+), 34 deletions(-) diff --git a/Detectors/CTF/test/test_ctf_io_ft0.cxx b/Detectors/CTF/test/test_ctf_io_ft0.cxx index e9cddf0abe8f8..49b43b40f2f8a 100644 --- a/Detectors/CTF/test/test_ctf_io_ft0.cxx +++ b/Detectors/CTF/test/test_ctf_io_ft0.cxx @@ -77,7 +77,10 @@ BOOST_AUTO_TEST_CASE(CTFTest) sw.Start(); std::vector<o2::ctf::BufferType> vec; - CTFCoder::encode(vec, digits, channels); // compress + { + CTFCoder coder; + coder.encode(vec, digits, channels); // compress + } sw.Stop(); LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; @@ -111,7 +114,10 @@ BOOST_AUTO_TEST_CASE(CTFTest) sw.Start(); const auto ctfImage = o2::ft0::CTF::getImage(vec.data()); - CTFCoder::decode(ctfImage, digitsD, channelsD); // decompress + { + CTFCoder coder; + coder.decode(ctfImage, digitsD, channelsD); // decompress + } sw.Stop(); LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index 88746ec85cda8..e0646846a7202 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -23,6 +23,7 @@ #include "DataFormatsFT0/Digit.h" #include "DataFormatsFT0/ChannelData.h" #include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" #include "rANS/rans.h" class TTree; @@ -32,27 +33,32 @@ namespace o2 namespace ft0 { -class CTFCoder +class CTFCoder : public o2::ctf::CTFCoderBase { public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + ~CTFCoder() = default; + /// entropy-encode digits to buffer with CTF template <typename VEC> - static void encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); + void encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); /// entropy decode clusters from buffer with CTF template <typename VDIG, typename VCHAN> - static void decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec); + void decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); private: /// compres digits clusters to CompressedDigits - static void compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); + void compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); /// decompress CompressedDigits to digits template <typename VDIG, typename VCHAN> - static void decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec); + void decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec); - static void appendToTree(TTree& tree, CTF& ec); - static void readFromTree(TTree& tree, int entry, std::vector<Digit>& digitVec, std::vector<ChannelData>& channelVec); + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<Digit>& digitVec, std::vector<ChannelData>& channelVec); ClassDefNV(CTFCoder, 1); }; @@ -83,18 +89,19 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g ec->getANSHeader().majorVersion = 0; ec->getANSHeader().minorVersion = 1; // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec -#define ENCODE CTF::get(buff.data())->encode +#define ENCODEFT0(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODE(cd.trigger, CTF::BLC_trigger, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_trigger], &buff); - ENCODE(cd.bcInc, CTF::BLC_bcInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_bcInc], &buff); - ENCODE(cd.orbitInc, CTF::BLC_orbitInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_orbitInc], &buff); - ENCODE(cd.nChan, CTF::BLC_nChan, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_nChan], &buff); - // ENCODE(cd.eventFlags, CTF::BLC_flags, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_flags], &buff); - ENCODE(cd.idChan , CTF::BLC_idChan, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_idChan], &buff); - ENCODE(cd.qtcChain, CTF::BLC_qtcChain, o2::rans::ProbabilityBits8Bit, optField[CTF::BLC_qtcChain], &buff); - ENCODE(cd.cfdTime, CTF::BLC_cfdTime, o2::rans::ProbabilityBits16Bit, optField[CTF::BLC_cfdTime], &buff); - ENCODE(cd.qtcAmpl, CTF::BLC_qtcAmpl, o2::rans::ProbabilityBits25Bit, optField[CTF::BLC_qtcAmpl], &buff); + ENCODEFT0(cd.trigger, CTF::BLC_trigger, o2::rans::ProbabilityBits16Bit); + ENCODEFT0(cd.bcInc, CTF::BLC_bcInc, o2::rans::ProbabilityBits16Bit); + ENCODEFT0(cd.orbitInc, CTF::BLC_orbitInc, o2::rans::ProbabilityBits16Bit); + ENCODEFT0(cd.nChan, CTF::BLC_nChan, o2::rans::ProbabilityBits8Bit); + // ENCODEFT0(cd.eventFlags, CTF::BLC_flags, o2::rans::ProbabilityBits8Bit); + ENCODEFT0(cd.idChan , CTF::BLC_idChan, o2::rans::ProbabilityBits8Bit); + ENCODEFT0(cd.qtcChain, CTF::BLC_qtcChain, o2::rans::ProbabilityBits8Bit); + ENCODEFT0(cd.cfdTime, CTF::BLC_cfdTime, o2::rans::ProbabilityBits16Bit); + ENCODEFT0(cd.qtcAmpl, CTF::BLC_qtcAmpl, o2::rans::ProbabilityBits25Bit); // clang-format on + CTF::get(buff.data())->print("FT0 done: "); } /// decode entropy-encoded clusters to standard compact clusters @@ -103,16 +110,17 @@ void CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec) { CompressedDigits cd; cd.header = ec.getHeader(); +#define DECODEFT0(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off - ec.decode(cd.trigger, CTF::BLC_trigger); - ec.decode(cd.bcInc, CTF::BLC_bcInc); - ec.decode(cd.orbitInc, CTF::BLC_orbitInc); - ec.decode(cd.nChan, CTF::BLC_nChan); - // ec.decode(cd.eventFlags, CTF::BLC_flags); - ec.decode(cd.idChan, CTF::BLC_idChan); - ec.decode(cd.qtcChain, CTF::BLC_qtcChain); - ec.decode(cd.cfdTime, CTF::BLC_cfdTime); - ec.decode(cd.qtcAmpl, CTF::BLC_qtcAmpl); + DECODEFT0(cd.trigger, CTF::BLC_trigger); + DECODEFT0(cd.bcInc, CTF::BLC_bcInc); + DECODEFT0(cd.orbitInc, CTF::BLC_orbitInc); + DECODEFT0(cd.nChan, CTF::BLC_nChan); + // DECODEFT0(cd.eventFlags, CTF::BLC_flags); + DECODEFT0(cd.idChan, CTF::BLC_idChan); + DECODEFT0(cd.qtcChain, CTF::BLC_qtcChain); + DECODEFT0(cd.cfdTime, CTF::BLC_cfdTime); + DECODEFT0(cd.qtcAmpl, CTF::BLC_qtcAmpl); // clang-format on // decompress(cd, digitVec, channelVec); diff --git a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx index 70036155daa3b..ea6181aa9881e 100644 --- a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx @@ -95,3 +95,42 @@ void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digi } } } + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, o2::detectors::DetID::FT0, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + CompressedDigits cd; // just to get member types +#define MAKECODER(part, slot) createCoder<decltype(part)::value_type>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(cd.trigger, CTF::BLC_trigger); + MAKECODER(cd.bcInc, CTF::BLC_bcInc); + MAKECODER(cd.orbitInc, CTF::BLC_orbitInc); + MAKECODER(cd.nChan, CTF::BLC_nChan); + // MAKECODER(cd.eventFlags, CTF::BLC_flags); + MAKECODER(cd.idChan, CTF::BLC_idChan); + MAKECODER(cd.qtcChain, CTF::BLC_qtcChain); + MAKECODER(cd.cfdTime, CTF::BLC_cfdTime); + MAKECODER(cd.qtcAmpl, CTF::BLC_qtcAmpl); + // clang-format on +} diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h index 360e8b1f4cdfa..58b25bbcebe54 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyDecoderSpec.h @@ -16,6 +16,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" +#include "FT0Reconstruction/CTFCoder.h" #include <TStopwatch.h> namespace o2 @@ -29,9 +30,11 @@ class EntropyDecoderSpec : public o2::framework::Task EntropyDecoderSpec(); ~EntropyDecoderSpec() override = default; void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: + o2::ft0::CTFCoder mCTFCoder; TStopwatch mTimer; }; diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h index 498724b7ebcc8..5b42eb0f2cd14 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/EntropyEncoderSpec.h @@ -17,6 +17,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include <TStopwatch.h> +#include "FT0Reconstruction/CTFCoder.h" namespace o2 { @@ -29,9 +30,11 @@ class EntropyEncoderSpec : public o2::framework::Task EntropyEncoderSpec(); ~EntropyEncoderSpec() override = default; void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: + o2::ft0::CTFCoder mCTFCoder; TStopwatch mTimer; }; diff --git a/Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx b/Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx index 612485d6df9af..d69e174deb922 100644 --- a/Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/EntropyDecoderSpec.cxx @@ -14,7 +14,6 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" -#include "FT0Reconstruction/CTFCoder.h" #include "FT0Workflow/EntropyDecoderSpec.h" using namespace o2::framework; @@ -30,6 +29,14 @@ EntropyDecoderSpec::EntropyDecoderSpec() mTimer.Reset(); } +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("ft0-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + void EntropyDecoderSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); @@ -42,7 +49,7 @@ void EntropyDecoderSpec::run(ProcessingContext& pc) // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object const auto ctfImage = o2::ft0::CTF::getImage(buff.data()); - CTFCoder::decode(ctfImage, digits, channels); + mCTFCoder.decode(ctfImage, digits, channels); mTimer.Stop(); LOG(INFO) << "Decoded " << channels.size() << " FT0 channels in " << digits.size() << " digits in " << mTimer.CpuTime() - cput << " s"; @@ -65,7 +72,7 @@ DataProcessorSpec getEntropyDecoderSpec() Inputs{InputSpec{"ctf", "FT0", "CTFDATA", 0, Lifetime::Timeframe}}, outputs, AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, - Options{}}; + Options{{"ft0-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; } } // namespace ft0 diff --git a/Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx b/Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx index 549cdf5277845..93e1d013ba95d 100644 --- a/Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/EntropyEncoderSpec.cxx @@ -14,8 +14,8 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" -#include "FT0Reconstruction/CTFCoder.h" #include "FT0Workflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" using namespace o2::framework; @@ -30,6 +30,14 @@ EntropyEncoderSpec::EntropyEncoderSpec() mTimer.Reset(); } +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("ft0-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + void EntropyEncoderSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); @@ -38,7 +46,7 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) auto channels = pc.inputs().get<gsl::span<o2::ft0::ChannelData>>("channels"); auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"FT0", "CTFDATA", 0, Lifetime::Timeframe}); - CTFCoder::encode(buffer, digits, channels); + mCTFCoder.encode(buffer, digits, channels); auto eeb = CTF::get(buffer.data()); // cast to container pointer eeb->compactify(); // eliminate unnecessary padding buffer.resize(eeb->size()); // shrink buffer to strictly necessary size @@ -64,7 +72,7 @@ DataProcessorSpec getEntropyEncoderSpec() inputs, Outputs{{"FT0", "CTFDATA", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, - Options{}}; + Options{{"ft0-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; } } // namespace ft0 From ad4a50d2d6d4ac2787bdc0cdddd9312e8f656f99 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 13:55:10 +0200 Subject: [PATCH 0317/1751] support for external dictionaries in TPC --- Detectors/CTF/test/test_ctf_io_tpc.cxx | 15 ++- .../include/TPCReconstruction/CTFCoder.h | 108 ++++++++++-------- Detectors/TPC/reconstruction/src/CTFCoder.cxx | 53 +++++++++ .../include/TPCWorkflow/EntropyDecoderSpec.h | 2 + .../include/TPCWorkflow/EntropyEncoderSpec.h | 3 + .../TPC/workflow/src/EntropyDecoderSpec.cxx | 16 +-- .../TPC/workflow/src/EntropyEncoderSpec.cxx | 16 ++- 7 files changed, 149 insertions(+), 64 deletions(-) diff --git a/Detectors/CTF/test/test_ctf_io_tpc.cxx b/Detectors/CTF/test/test_ctf_io_tpc.cxx index 342ffd6b77501..99ebe3a36a5ef 100644 --- a/Detectors/CTF/test/test_ctf_io_tpc.cxx +++ b/Detectors/CTF/test/test_ctf_io_tpc.cxx @@ -39,7 +39,10 @@ BOOST_AUTO_TEST_CASE(CTFTest) bVec.resize(sz); ccFlat = reinterpret_cast<CompressedClustersFlat*>(bVec.data()); auto buff = reinterpret_cast<void*>(reinterpret_cast<char*>(bVec.data()) + sizeCFlatBody); - CTFCoder::setCompClusAddresses(c, buff); + { + CTFCoder coder; + coder.setCompClusAddresses(c, buff); + } ccFlat->set(sz, c); // fill some data @@ -80,7 +83,10 @@ BOOST_AUTO_TEST_CASE(CTFTest) TStopwatch sw; sw.Start(); std::vector<o2::ctf::BufferType> vecIO; - CTFCoder::encode(vecIO, c); // compress + { + CTFCoder coder; + coder.encode(vecIO, c); // compress + } sw.Stop(); LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; @@ -112,7 +118,10 @@ BOOST_AUTO_TEST_CASE(CTFTest) std::vector<char> vecIn; sw.Start(); const auto ctfImage = o2::tpc::CTF::getImage(vecIO.data()); - CTFCoder::decode(ctfImage, vecIn); // decompress + { + CTFCoder coder; + coder.decode(ctfImage, vecIn); // decompress + } sw.Stop(); LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; // diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h index 84b70c69b6b73..cad0dbfa5c15c 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h @@ -21,6 +21,7 @@ #include "DataFormatsTPC/CTF.h" #include "DataFormatsTPC/CompressedClusters.h" #include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" #include "rANS/rans.h" class TTree; @@ -30,15 +31,20 @@ namespace o2 namespace tpc { -class CTFCoder +class CTFCoder : public o2::ctf::CTFCoderBase { public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + ~CTFCoder() = default; + /// entropy-encode compressed clusters to flat buffer template <typename VEC> - static void encode(VEC& buff, const CompressedClusters& ccl); + void encode(VEC& buff, const CompressedClusters& ccl); template <typename VEC> - static void decode(const CTF::base& ec, VEC& buff); + void decode(const CTF::base& ec, VEC& buff); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); static size_t constexpr Alignment = 16; static size_t estimateSize(CompressedClusters& c); @@ -102,32 +108,33 @@ void CTFCoder::encode(VEC& buff, const CompressedClusters& ccl) ec->getANSHeader().majorVersion = 0; ec->getANSHeader().minorVersion = 1; // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec -#define ENCODE CTF::get(buff.data())->encode +#define ENCODETPC(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODE(ccl.qTotA, ccl.qTotA + ccl.nAttachedClusters, CTF::BLCqTotA, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCqTotA], &buff); - ENCODE(ccl.qMaxA, ccl.qMaxA + ccl.nAttachedClusters, CTF::BLCqMaxA, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCqMaxA], &buff); - ENCODE(ccl.flagsA, ccl.flagsA + ccl.nAttachedClusters, CTF::BLCflagsA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCflagsA], &buff); - ENCODE(ccl.rowDiffA, ccl.rowDiffA + ccl.nAttachedClustersReduced, CTF::BLCrowDiffA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCrowDiffA], &buff); - ENCODE(ccl.sliceLegDiffA, ccl.sliceLegDiffA + ccl.nAttachedClustersReduced, CTF::BLCsliceLegDiffA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCsliceLegDiffA], &buff); - ENCODE(ccl.padResA, ccl.padResA + ccl.nAttachedClustersReduced, CTF::BLCpadResA, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpadResA], &buff); - ENCODE(ccl.timeResA, ccl.timeResA + ccl.nAttachedClustersReduced, CTF::BLCtimeResA, o2::rans::ProbabilityBits25Bit, optField[CTF::BLCtimeResA], &buff); - ENCODE(ccl.sigmaPadA, ccl.sigmaPadA + ccl.nAttachedClusters, CTF::BLCsigmaPadA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCsigmaPadA], &buff); - ENCODE(ccl.sigmaTimeA, ccl.sigmaTimeA + ccl.nAttachedClusters, CTF::BLCsigmaTimeA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCsigmaTimeA], &buff); - ENCODE(ccl.qPtA, ccl.qPtA + ccl.nTracks, CTF::BLCqPtA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCqPtA], &buff); - ENCODE(ccl.rowA, ccl.rowA + ccl.nTracks, CTF::BLCrowA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCrowA], &buff); - ENCODE(ccl.sliceA, ccl.sliceA + ccl.nTracks, CTF::BLCsliceA, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCsliceA], &buff); - ENCODE(ccl.timeA, ccl.timeA + ccl.nTracks, CTF::BLCtimeA, o2::rans::ProbabilityBits25Bit, optField[CTF::BLCtimeA], &buff); - ENCODE(ccl.padA, ccl.padA + ccl.nTracks, CTF::BLCpadA, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpadA], &buff); - ENCODE(ccl.qTotU, ccl.qTotU + ccl.nUnattachedClusters, CTF::BLCqTotU, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCqTotU], &buff); - ENCODE(ccl.qMaxU, ccl.qMaxU + ccl.nUnattachedClusters, CTF::BLCqMaxU, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCqMaxU], &buff); - ENCODE(ccl.flagsU, ccl.flagsU + ccl.nUnattachedClusters, CTF::BLCflagsU, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCflagsU], &buff); - ENCODE(ccl.padDiffU, ccl.padDiffU + ccl.nUnattachedClusters, CTF::BLCpadDiffU, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpadDiffU], &buff); - ENCODE(ccl.timeDiffU, ccl.timeDiffU + ccl.nUnattachedClusters, CTF::BLCtimeDiffU, o2::rans::ProbabilityBits25Bit, optField[CTF::BLCtimeDiffU], &buff); - ENCODE(ccl.sigmaPadU, ccl.sigmaPadU + ccl.nUnattachedClusters, CTF::BLCsigmaPadU, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCsigmaPadU], &buff); - ENCODE(ccl.sigmaTimeU, ccl.sigmaTimeU + ccl.nUnattachedClusters, CTF::BLCsigmaTimeU, o2::rans::ProbabilityBits8Bit, optField[CTF::BLCsigmaTimeU], &buff); - ENCODE(ccl.nTrackClusters, ccl.nTrackClusters + ccl.nTracks, CTF::BLCnTrackClusters, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCnTrackClusters], &buff); - ENCODE(ccl.nSliceRowClusters, ccl.nSliceRowClusters + ccl.nSliceRows, CTF::BLCnSliceRowClusters, o2::rans::ProbabilityBits25Bit, optField[CTF::BLCnSliceRowClusters], &buff); + ENCODETPC(ccl.qTotA, ccl.qTotA + ccl.nAttachedClusters, CTF::BLCqTotA, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.qMaxA, ccl.qMaxA + ccl.nAttachedClusters, CTF::BLCqMaxA, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.flagsA, ccl.flagsA + ccl.nAttachedClusters, CTF::BLCflagsA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.rowDiffA, ccl.rowDiffA + ccl.nAttachedClustersReduced, CTF::BLCrowDiffA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.sliceLegDiffA, ccl.sliceLegDiffA + ccl.nAttachedClustersReduced, CTF::BLCsliceLegDiffA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.padResA, ccl.padResA + ccl.nAttachedClustersReduced, CTF::BLCpadResA, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.timeResA, ccl.timeResA + ccl.nAttachedClustersReduced, CTF::BLCtimeResA, o2::rans::ProbabilityBits25Bit); + ENCODETPC(ccl.sigmaPadA, ccl.sigmaPadA + ccl.nAttachedClusters, CTF::BLCsigmaPadA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.sigmaTimeA, ccl.sigmaTimeA + ccl.nAttachedClusters, CTF::BLCsigmaTimeA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.qPtA, ccl.qPtA + ccl.nTracks, CTF::BLCqPtA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.rowA, ccl.rowA + ccl.nTracks, CTF::BLCrowA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.sliceA, ccl.sliceA + ccl.nTracks, CTF::BLCsliceA, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.timeA, ccl.timeA + ccl.nTracks, CTF::BLCtimeA, o2::rans::ProbabilityBits25Bit); + ENCODETPC(ccl.padA, ccl.padA + ccl.nTracks, CTF::BLCpadA, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.qTotU, ccl.qTotU + ccl.nUnattachedClusters, CTF::BLCqTotU, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.qMaxU, ccl.qMaxU + ccl.nUnattachedClusters, CTF::BLCqMaxU, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.flagsU, ccl.flagsU + ccl.nUnattachedClusters, CTF::BLCflagsU, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.padDiffU, ccl.padDiffU + ccl.nUnattachedClusters, CTF::BLCpadDiffU, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.timeDiffU, ccl.timeDiffU + ccl.nUnattachedClusters, CTF::BLCtimeDiffU, o2::rans::ProbabilityBits25Bit); + ENCODETPC(ccl.sigmaPadU, ccl.sigmaPadU + ccl.nUnattachedClusters, CTF::BLCsigmaPadU, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.sigmaTimeU, ccl.sigmaTimeU + ccl.nUnattachedClusters, CTF::BLCsigmaTimeU, o2::rans::ProbabilityBits8Bit); + ENCODETPC(ccl.nTrackClusters, ccl.nTrackClusters + ccl.nTracks, CTF::BLCnTrackClusters, o2::rans::ProbabilityBits16Bit); + ENCODETPC(ccl.nSliceRowClusters, ccl.nSliceRowClusters + ccl.nSliceRows, CTF::BLCnSliceRowClusters, o2::rans::ProbabilityBits25Bit); // clang-format on + CTF::get(buff.data())->print("TPC done: "); } /// decode entropy-encoded bloks to TPC CompressedClusters into the externally provided vector (e.g. PMR vector from DPL) @@ -149,30 +156,31 @@ void CTFCoder::decode(const CTF::base& ec, VEC& buffVec) ccFlat->set(sz, cc); // set offsets // decode encoded data directly to destination buff +#define DECODETPC(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off - ec.decode(cc.qTotA, CTF::BLCqTotA); - ec.decode(cc.qMaxA, CTF::BLCqMaxA); - ec.decode(cc.flagsA, CTF::BLCflagsA); - ec.decode(cc.rowDiffA, CTF::BLCrowDiffA); - ec.decode(cc.sliceLegDiffA, CTF::BLCsliceLegDiffA); - ec.decode(cc.padResA, CTF::BLCpadResA); - ec.decode(cc.timeResA, CTF::BLCtimeResA); - ec.decode(cc.sigmaPadA, CTF::BLCsigmaPadA); - ec.decode(cc.sigmaTimeA, CTF::BLCsigmaTimeA); - ec.decode(cc.qPtA, CTF::BLCqPtA); - ec.decode(cc.rowA, CTF::BLCrowA); - ec.decode(cc.sliceA, CTF::BLCsliceA); - ec.decode(cc.timeA, CTF::BLCtimeA); - ec.decode(cc.padA, CTF::BLCpadA); - ec.decode(cc.qTotU, CTF::BLCqTotU); - ec.decode(cc.qMaxU, CTF::BLCqMaxU); - ec.decode(cc.flagsU, CTF::BLCflagsU); - ec.decode(cc.padDiffU, CTF::BLCpadDiffU); - ec.decode(cc.timeDiffU, CTF::BLCtimeDiffU); - ec.decode(cc.sigmaPadU, CTF::BLCsigmaPadU); - ec.decode(cc.sigmaTimeU, CTF::BLCsigmaTimeU); - ec.decode(cc.nTrackClusters, CTF::BLCnTrackClusters); - ec.decode(cc.nSliceRowClusters, CTF::BLCnSliceRowClusters); + DECODETPC(cc.qTotA, CTF::BLCqTotA); + DECODETPC(cc.qMaxA, CTF::BLCqMaxA); + DECODETPC(cc.flagsA, CTF::BLCflagsA); + DECODETPC(cc.rowDiffA, CTF::BLCrowDiffA); + DECODETPC(cc.sliceLegDiffA, CTF::BLCsliceLegDiffA); + DECODETPC(cc.padResA, CTF::BLCpadResA); + DECODETPC(cc.timeResA, CTF::BLCtimeResA); + DECODETPC(cc.sigmaPadA, CTF::BLCsigmaPadA); + DECODETPC(cc.sigmaTimeA, CTF::BLCsigmaTimeA); + DECODETPC(cc.qPtA, CTF::BLCqPtA); + DECODETPC(cc.rowA, CTF::BLCrowA); + DECODETPC(cc.sliceA, CTF::BLCsliceA); + DECODETPC(cc.timeA, CTF::BLCtimeA); + DECODETPC(cc.padA, CTF::BLCpadA); + DECODETPC(cc.qTotU, CTF::BLCqTotU); + DECODETPC(cc.qMaxU, CTF::BLCqMaxU); + DECODETPC(cc.flagsU, CTF::BLCflagsU); + DECODETPC(cc.padDiffU, CTF::BLCpadDiffU); + DECODETPC(cc.timeDiffU, CTF::BLCtimeDiffU); + DECODETPC(cc.sigmaPadU, CTF::BLCsigmaPadU); + DECODETPC(cc.sigmaTimeU, CTF::BLCsigmaTimeU); + DECODETPC(cc.nTrackClusters, CTF::BLCnTrackClusters); + DECODETPC(cc.nSliceRowClusters, CTF::BLCnSliceRowClusters); // clang-format on } diff --git a/Detectors/TPC/reconstruction/src/CTFCoder.cxx b/Detectors/TPC/reconstruction/src/CTFCoder.cxx index 3de8495c08b10..b38858aae407c 100644 --- a/Detectors/TPC/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TPC/reconstruction/src/CTFCoder.cxx @@ -86,3 +86,56 @@ void CTFCoder::setCompClusAddresses(CompressedClusters& c, void*& buff) setAlignedPtr(buff, c.nTrackClusters, header.nTracks); } } + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, o2::detectors::DetID::TPC, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + CompressedClusters cc; // just to get member types +#define MAKECODER(part, slot) createCoder<std::remove_pointer<decltype(part)>::type>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(cc.qTotA, CTF::BLCqTotA); + MAKECODER(cc.qMaxA, CTF::BLCqMaxA); + MAKECODER(cc.flagsA, CTF::BLCflagsA); + MAKECODER(cc.rowDiffA, CTF::BLCrowDiffA); + MAKECODER(cc.sliceLegDiffA, CTF::BLCsliceLegDiffA); + MAKECODER(cc.padResA, CTF::BLCpadResA); + MAKECODER(cc.timeResA, CTF::BLCtimeResA); + MAKECODER(cc.sigmaPadA, CTF::BLCsigmaPadA); + MAKECODER(cc.sigmaTimeA, CTF::BLCsigmaTimeA); + MAKECODER(cc.qPtA, CTF::BLCqPtA); + MAKECODER(cc.rowA, CTF::BLCrowA); + MAKECODER(cc.sliceA, CTF::BLCsliceA); + MAKECODER(cc.timeA, CTF::BLCtimeA); + MAKECODER(cc.padA, CTF::BLCpadA); + MAKECODER(cc.qTotU, CTF::BLCqTotU); + MAKECODER(cc.qMaxU, CTF::BLCqMaxU); + MAKECODER(cc.flagsU, CTF::BLCflagsU); + MAKECODER(cc.padDiffU, CTF::BLCpadDiffU); + MAKECODER(cc.timeDiffU, CTF::BLCtimeDiffU); + MAKECODER(cc.sigmaPadU, CTF::BLCsigmaPadU); + MAKECODER(cc.sigmaTimeU, CTF::BLCsigmaTimeU); + MAKECODER(cc.nTrackClusters, CTF::BLCnTrackClusters); + MAKECODER(cc.nSliceRowClusters, CTF::BLCnSliceRowClusters); + // clang-format on +} diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h index d85a8d530a3db..cbc15618c3f56 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h @@ -16,6 +16,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "Headers/DataHeader.h" +#include "TPCReconstruction/CTFCoder.h" #include <TStopwatch.h> namespace o2 @@ -36,6 +37,7 @@ class EntropyDecoderSpec : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final; private: + o2::tpc::CTFCoder mCTFCoder; TStopwatch mTimer; }; diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/EntropyEncoderSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/EntropyEncoderSpec.h index 3f91c7049d4b7..50da4378372ca 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/EntropyEncoderSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/EntropyEncoderSpec.h @@ -17,6 +17,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" +#include "TPCReconstruction/CTFCoder.h" #include <TStopwatch.h> namespace o2 @@ -34,9 +35,11 @@ class EntropyEncoderSpec : public o2::framework::Task } ~EntropyEncoderSpec() override = default; void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: + o2::tpc::CTFCoder mCTFCoder; bool mFromFile = false; TStopwatch mTimer; }; diff --git a/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx b/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx index d4ad917b4d972..0e2a33596045f 100644 --- a/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx @@ -16,7 +16,6 @@ #include "Framework/ConfigParamRegistry.h" #include "DataFormatsTPC/CompressedClusters.h" #include "TPCWorkflow/EntropyDecoderSpec.h" -#include "TPCReconstruction/CTFCoder.h" using namespace o2::framework; @@ -25,9 +24,12 @@ namespace o2 namespace tpc { -void EntropyDecoderSpec::init(InitContext& ic) +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) { - // at the moment do nothing + std::string dictPath = ic.options().get<std::string>("tpc-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } } void EntropyDecoderSpec::run(ProcessingContext& pc) @@ -39,21 +41,21 @@ void EntropyDecoderSpec::run(ProcessingContext& pc) auto& compclusters = pc.outputs().make<std::vector<char>>(OutputRef{"output"}); const auto ctfImage = o2::tpc::CTF::getImage(buff.data()); - CTFCoder::decode(ctfImage, compclusters); + mCTFCoder.decode(ctfImage, compclusters); mTimer.Stop(); LOG(INFO) << "Decoded " << buff.size() * sizeof(o2::ctf::BufferType) << " encoded bytes to " - << compclusters.size() << " bytes in" << mTimer.CpuTime() - cput << "\n"; + << compclusters.size() << " bytes in " << mTimer.CpuTime() - cput << " s"; } DataProcessorSpec getEntropyDecoderSpec() { return DataProcessorSpec{ - "TPC", + "tpc-entropy-decoder", Inputs{InputSpec{"ctf", "TPC", "CTFDATA", 0, Lifetime::Timeframe}}, Outputs{OutputSpec{{"output"}, "TPC", "COMPCLUSTERSFLAT", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, - Options{}}; + Options{{"tpc-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; } } // namespace tpc diff --git a/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx b/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx index ba71acba4fe94..b3594bb6b3ff5 100644 --- a/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx @@ -15,7 +15,6 @@ #include "TPCWorkflow/EntropyEncoderSpec.h" #include "DataFormatsTPC/CompressedClusters.h" -#include "TPCReconstruction/CTFCoder.h" #include "Framework/ConfigParamRegistry.h" #include "Headers/DataHeader.h" @@ -27,6 +26,14 @@ namespace o2 namespace tpc { +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("tpc-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + void EntropyEncoderSpec::run(ProcessingContext& pc) { CompressedClusters clusters; @@ -50,7 +57,7 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) mTimer.Start(false); auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"TPC", "CTFDATA", 0, Lifetime::Timeframe}); - CTFCoder::encode(buffer, clusters); + mCTFCoder.encode(buffer, clusters); auto encodedBlocks = CTF::get(buffer.data()); // cast to container pointer encodedBlocks->compactify(); // eliminate unnecessary padding buffer.resize(encodedBlocks->size()); // shrink buffer to strictly necessary size @@ -71,9 +78,10 @@ DataProcessorSpec getEntropyEncoderSpec(bool inputFromFile) header::DataDescription inputType = inputFromFile ? header::DataDescription("COMPCLUSTERS") : header::DataDescription("COMPCLUSTERSFLAT"); return DataProcessorSpec{ "tpc-entropy-encoder", // process id - {{"input", "TPC", inputType, 0, Lifetime::Timeframe}}, + Inputs{{"input", "TPC", inputType, 0, Lifetime::Timeframe}}, Outputs{{"TPC", "CTFDATA", 0, Lifetime::Timeframe}}, - AlgorithmSpec(adaptFromTask<EntropyEncoderSpec>(inputFromFile))}; + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>(inputFromFile)}, + Options{{"tpc-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; } } // namespace tpc From c58890b83d9a60dc33c78315244e1f5d5b15e2d1 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 13:55:27 +0200 Subject: [PATCH 0318/1751] support for external dictionaries in TOF --- Detectors/CTF/workflow/CMakeLists.txt | 1 + .../CTF/workflow/src/ctf-reader-workflow.cxx | 5 +- .../include/TOFReconstruction/CTFCoder.h | 70 +++++++++++-------- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 47 ++++++++++++- .../include/TOFWorkflow/EntropyDecoderSpec.h | 3 + .../include/TOFWorkflow/EntropyEncoderSpec.h | 3 + .../TOF/workflow/src/EntropyDecoderSpec.cxx | 13 +++- .../TOF/workflow/src/EntropyEncoderSpec.cxx | 13 +++- 8 files changed, 114 insertions(+), 41 deletions(-) diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index ece52e2fc9270..acfbd38f1c5c1 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -20,6 +20,7 @@ o2_add_library(CTFWorkflow O2::ITSMFTWorkflow O2::TPCWorkflow O2::FT0Workflow + O2::TOFWorkflow O2::Algorithm O2::CommonUtils) diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index 2a1993a5c2ff9..57f90e8d45b24 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -23,6 +23,7 @@ #include "ITSMFTWorkflow/EntropyDecoderSpec.h" #include "TPCWorkflow/EntropyDecoderSpec.h" #include "FT0Workflow/EntropyDecoderSpec.h" +#include "TOFWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -73,9 +74,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets[DetID::TPC]) { specs.push_back(o2::tpc::getEntropyDecoderSpec()); } + if (dets[DetID::TOF]) { + specs.push_back(o2::tof::getEntropyDecoderSpec()); + } if (dets[DetID::FT0]) { specs.push_back(o2::ft0::getEntropyDecoderSpec()); } - return std::move(specs); } diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index e024064d713d7..90bcdafa1e2f7 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -21,6 +21,7 @@ #include "DataFormatsTOF/CTF.h" #include "DetectorsCommonDataFormats/DetID.h" #include "rANS/rans.h" +#include "DetectorsBase/CTFCoderBase.h" #include "TOFBase/Digit.h" class TTree; @@ -30,27 +31,32 @@ namespace o2 namespace tof { -class CTFCoder +class CTFCoder : public o2::ctf::CTFCoderBase { public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + ~CTFCoder() = default; + /// entropy-encode clusters to buffer with CTF template <typename VEC> - static void encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec); + void encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec); /// entropy decode clusters from buffer with CTF template <typename VROF, typename VDIG, typename VPAT> - static void decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); + void decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); private: /// compres compact clusters to CompressedInfos - static void compress(CompressedInfos& cc, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec); + void compress(CompressedInfos& cc, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec); /// decompress CompressedInfos to compact clusters template <typename VROF, typename VDIG, typename VPAT> - static void decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); + void decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); - static void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); - static void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec); + void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); + void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec); protected: ClassDefNV(CTFCoder, 1); @@ -84,19 +90,20 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRe ec->getANSHeader().majorVersion = 0; ec->getANSHeader().minorVersion = 1; // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec -#define ENCODE CTF::get(buff.data())->encode +#define ENCODETOF(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODE(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCbcIncROF], &buff); - ENCODE(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCorbitIncROF], &buff); - ENCODE(cc.ndigROF, CTF::BLCndigROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCndigROF], &buff); - ENCODE(cc.ndiaROF, CTF::BLCndiaROF, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCndiaROF], &buff); - ENCODE(cc.timeFrameInc, CTF::BLCtimeFrameInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeFrameInc], &buff); - ENCODE(cc.timeTDCInc, CTF::BLCtimeTDCInc, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtimeTDCInc], &buff); - ENCODE(cc.stripID, CTF::BLCstripID, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCstripID], &buff); - ENCODE(cc.chanInStrip, CTF::BLCchanInStrip, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCchanInStrip], &buff); - ENCODE(cc.tot, CTF::BLCtot, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCtot], &buff); - ENCODE(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit, optField[CTF::BLCpattMap], &buff); + ENCODETOF(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.ndigROF, CTF::BLCndigROF, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.ndiaROF, CTF::BLCndiaROF, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.timeFrameInc, CTF::BLCtimeFrameInc, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.timeTDCInc, CTF::BLCtimeTDCInc, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.stripID, CTF::BLCstripID, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.chanInStrip, CTF::BLCchanInStrip, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.tot, CTF::BLCtot, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit); // clang-format on + CTF::get(buff.data())->print("TOF done: "); } ///___________________________________________________________________________________ /// decode entropy-encoded digits to standard compact digits @@ -105,18 +112,19 @@ void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& { CompressedInfos cc; cc.header = ec.getHeader(); +#define DECODETOF(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off - ec.decode(cc.bcIncROF, CTF::BLCbcIncROF); - ec.decode(cc.orbitIncROF, CTF::BLCorbitIncROF); - ec.decode(cc.ndigROF, CTF::BLCndigROF); - ec.decode(cc.ndiaROF, CTF::BLCndiaROF); - - ec.decode(cc.timeFrameInc, CTF::BLCtimeFrameInc); - ec.decode(cc.timeTDCInc, CTF::BLCtimeTDCInc); - ec.decode(cc.stripID, CTF::BLCstripID); - ec.decode(cc.chanInStrip, CTF::BLCchanInStrip); - ec.decode(cc.tot, CTF::BLCtot); - ec.decode(cc.pattMap, CTF::BLCpattMap); + DECODETOF(cc.bcIncROF, CTF::BLCbcIncROF); + DECODETOF(cc.orbitIncROF, CTF::BLCorbitIncROF); + DECODETOF(cc.ndigROF, CTF::BLCndigROF); + DECODETOF(cc.ndiaROF, CTF::BLCndiaROF); + + DECODETOF(cc.timeFrameInc, CTF::BLCtimeFrameInc); + DECODETOF(cc.timeTDCInc, CTF::BLCtimeTDCInc); + DECODETOF(cc.stripID, CTF::BLCstripID); + DECODETOF(cc.chanInStrip, CTF::BLCchanInStrip); + DECODETOF(cc.tot, CTF::BLCtot); + DECODETOF(cc.pattMap, CTF::BLCpattMap); // clang-format on // decompress(cc, rofRecVec, cdigVec, pattVec); @@ -164,14 +172,14 @@ void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdig digCopy.resize(cc.ndigROF[irof]); for (uint32_t idig = 0; idig < cc.ndigROF[irof]; idig++) { auto& digit = digCopy[idig]; //cdigVec[digCount]; - printf("%d) TF=%d, TDC=%d, STRIP=%d, CH=%d\n", idig, cc.timeFrameInc[digCount], cc.timeTDCInc[digCount], cc.stripID[digCount], cc.chanInStrip[digCount]); + LOGF(DEBUG, "%d) TF=%d, TDC=%d, STRIP=%d, CH=%d", idig, cc.timeFrameInc[digCount], cc.timeTDCInc[digCount], cc.stripID[digCount], cc.chanInStrip[digCount]); if (cc.timeFrameInc[digCount]) { // new time frame ctdc = cc.timeTDCInc[digCount]; ctimeframe += cc.timeFrameInc[digCount]; } else { ctdc += cc.timeTDCInc[digCount]; } - printf("BC=%d, TDC=%d, TOT=%d, CH=%d \n", uint32_t(ctimeframe) * 64 + ctdc / 1024 + BCrow, ctdc % 1024, cc.tot[digCount], uint32_t(cc.stripID[digCount]) * 96 + cc.chanInStrip[digCount]); + LOGF(DEBUG, "BC=%d, TDC=%d, TOT=%d, CH=%d", uint32_t(ctimeframe) * 64 + ctdc / 1024 + BCrow, ctdc % 1024, cc.tot[digCount], uint32_t(cc.stripID[digCount]) * 96 + cc.chanInStrip[digCount]); digit.setBC(uint32_t(ctimeframe) * 64 + ctdc / 1024 + BCrow); digit.setTDC(ctdc % 1024); diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index 6092941a3b685..bb04d33a1b049 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -50,7 +50,7 @@ void CTFCoder::compress(CompressedInfos& cc, const auto& rofRec0 = rofRecVec[0]; int nrof = rofRecVec.size(); - printf("TOF compress %d ReadoutWindow with %ld digits\n", nrof, cdigVec.size()); + LOGF(INFO, "TOF compress %d ReadoutWindow with %ld digits", nrof, cdigVec.size()); cc.header.nROFs = nrof; cc.header.firstOrbit = rofRec0.getBCData().orbit; @@ -138,10 +138,51 @@ void CTFCoder::compress(CompressedInfos& cc, cc.stripID[idig] = chan / Geo::NPADS; cc.chanInStrip[idig] = chan % Geo::NPADS; cc.tot[idig] = dig.getTOT(); - printf("%d) TOFBC = %d, deltaBC = %d, TDC = %d, CH=%d\n", irof, rofInBC, deltaBC, cTDC, chan); - printf("%d) TF=%d, TDC=%d, STRIP=%d, CH=%d, TOT=%d\n", idig, cc.timeFrameInc[idig], cc.timeTDCInc[idig], cc.stripID[idig], cc.chanInStrip[idig], cc.tot[idig]); + LOGF(DEBUG, "%d) TOFBC = %d, deltaBC = %d, TDC = %d, CH=%d", irof, rofInBC, deltaBC, cTDC, chan); + LOGF(DEBUG, "%d) TF=%d, TDC=%d, STRIP=%d, CH=%d, TOT=%d", idig, cc.timeFrameInc[idig], cc.timeTDCInc[idig], cc.stripID[idig], cc.chanInStrip[idig], cc.tot[idig]); } } // store explicit patters as they are memcpy(cc.pattMap.data(), pattVec.data(), cc.header.nPatternBytes); // RSTODO: do we need this? } + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, o2::detectors::DetID::TOF, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + CompressedInfos cc; // just to get member types +#define MAKECODER(part, slot) createCoder<decltype(part)::value_type>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(cc.bcIncROF, CTF::BLCbcIncROF); + MAKECODER(cc.orbitIncROF, CTF::BLCorbitIncROF); + MAKECODER(cc.ndigROF, CTF::BLCndigROF); + MAKECODER(cc.ndiaROF, CTF::BLCndiaROF); + + MAKECODER(cc.timeFrameInc, CTF::BLCtimeFrameInc); + MAKECODER(cc.timeTDCInc, CTF::BLCtimeTDCInc); + MAKECODER(cc.stripID, CTF::BLCstripID); + MAKECODER(cc.chanInStrip, CTF::BLCchanInStrip); + MAKECODER(cc.tot, CTF::BLCtot); + MAKECODER(cc.pattMap, CTF::BLCpattMap); + // clang-format on +} diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h index a654b3aa938b0..e699549ab2147 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h @@ -16,6 +16,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" +#include "TOFReconstruction/CTFCoder.h" #include <TStopwatch.h> namespace o2 @@ -29,9 +30,11 @@ class EntropyDecoderSpec : public o2::framework::Task EntropyDecoderSpec(); ~EntropyDecoderSpec() override = default; void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: + o2::tof::CTFCoder mCTFCoder; TStopwatch mTimer; }; diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h index 11d50e09e10fd..2a535abde1eb5 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h @@ -17,6 +17,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "Headers/DataHeader.h" +#include "TOFReconstruction/CTFCoder.h" #include <TStopwatch.h> namespace o2 @@ -30,9 +31,11 @@ class EntropyEncoderSpec : public o2::framework::Task EntropyEncoderSpec(); ~EntropyEncoderSpec() override = default; void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: + o2::tof::CTFCoder mCTFCoder; TStopwatch mTimer; }; diff --git a/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx index 21c52fea23f17..7fa7ba15069ae 100644 --- a/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx @@ -14,7 +14,6 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" -#include "TOFReconstruction/CTFCoder.h" #include "TOFWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; @@ -30,6 +29,14 @@ EntropyDecoderSpec::EntropyDecoderSpec() mTimer.Reset(); } +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("tof-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + void EntropyDecoderSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); @@ -43,7 +50,7 @@ void EntropyDecoderSpec::run(ProcessingContext& pc) // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object const auto ctfImage = o2::tof::CTF::getImage(buff.data()); - CTFCoder::decode(ctfImage, row, digits, patterns); + mCTFCoder.decode(ctfImage, row, digits, patterns); mTimer.Stop(); LOG(INFO) << "Decoded " << digits.size() << " digits in " << row.size() << " ROF in " << mTimer.CpuTime() - cput << " s"; @@ -67,7 +74,7 @@ DataProcessorSpec getEntropyDecoderSpec() Inputs{InputSpec{"ctf", o2::header::gDataOriginTOF, "CTFDATA", 0, Lifetime::Timeframe}}, outputs, AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, - Options{}}; + Options{{"tof-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; } } // namespace tof diff --git a/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx index 3b80f3432219c..e151def630a2d 100644 --- a/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx @@ -15,7 +15,6 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "TOFBase/Digit.h" -#include "TOFReconstruction/CTFCoder.h" #include "TOFWorkflow/EntropyEncoderSpec.h" using namespace o2::framework; @@ -31,6 +30,14 @@ EntropyEncoderSpec::EntropyEncoderSpec() mTimer.Reset(); } +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("tof-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + void EntropyEncoderSpec::run(ProcessingContext& pc) { auto cput = mTimer.CpuTime(); @@ -40,7 +47,7 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) auto rofs = pc.inputs().get<gsl::span<ReadoutWindowData>>("ROframes"); auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{o2::header::gDataOriginTOF, "CTFDATA", 0, Lifetime::Timeframe}); - CTFCoder::encode(buffer, rofs, compDigits, pspan); + mCTFCoder.encode(buffer, rofs, compDigits, pspan); auto eeb = CTF::get(buffer.data()); // cast to container pointer eeb->compactify(); // eliminate unnecessary padding buffer.resize(eeb->size()); // shrink buffer to strictly necessary size @@ -68,7 +75,7 @@ DataProcessorSpec getEntropyEncoderSpec() inputs, Outputs{{o2::header::gDataOriginTOF, "CTFDATA", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, - Options{}}; + Options{{"tof-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; } } // namespace tof From ab3a6e9feb483029c8d4121bc22a7138ff1cc333 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 16:44:12 +0200 Subject: [PATCH 0319/1751] add option of autosaving dictionary after given N TFs --- Detectors/CTF/README.md | 4 ++++ .../include/CTFWorkflow/CTFWriterSpec.h | 12 ++++++++-- Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 23 +++++++++++++++---- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/Detectors/CTF/README.md b/Detectors/CTF/README.md index b90ef22e2fa39..f064019f33f45 100644 --- a/Detectors/CTF/README.md +++ b/Detectors/CTF/README.md @@ -39,6 +39,10 @@ To create a dictionary run usual CTF creation chain but with extra option, e.g.: o2-its-reco-workflow --entropy-encoding | o2-ctf-writer-workflow --output-type dict --onlyDet ITS ``` This will create a file `ctf_dictionary.root` containing dictionary data for all detectors processed by the `o2-ctf-writer-workflow`. +By default the dictionary file is written on the exit from the workflow, in `CTFWriterSpec::endOfStream()` which is currently not called if the workflow is stopped +by `ctrl-C`. Periodic incremental saving of so-far accumulated dictionary data during processing can be triggered by providing an option +``--save-dict-after <N>``. + Following encoding / decoding will use external dictionaries automatically if this file is found in the working directory (eventually it will be provided via CCDB). Note that if the file is found but dictionary data for some detector participating in the workflow are not found, an error will be printed and for given detector the workflows will use in-ctf dictionaries. diff --git a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h index 31a640072a6fe..753c69ca3b71f 100644 --- a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h +++ b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h @@ -58,12 +58,14 @@ class CTFWriterSpec : public o2::framework::Task void storeDictionary(DetID det, CTFHeader& header); void storeDictionaries(); void prepareDictionaryTreeAndFile(DetID det); + void closeDictionaryTreeAndFile(CTFHeader& header); DetID::mask_t mDets; // detectors bool mWriteCTF = false; bool mCreateDict = false; bool mDictPerDetector = false; size_t mNTF = 0; + int mSaveDictAfter = -1; // if positive and mWriteCTF==true, save dictionary after each mSaveDictAfter TFs processed uint64_t mRun = 0; std::unique_ptr<TFile> mDictFileOut; // file to store dictionary @@ -123,9 +125,15 @@ void CTFWriterSpec::storeDictionary(DetID det, CTFHeader& header) auto dictBlocks = C::createDictionaryBlocks(mFreqsAccumulation[det], mFreqsMetaData[det]); C::get(dictBlocks.data())->print(o2::utils::concat_string("Storing dictionary for ", det.getName(), ": ")); C::get(dictBlocks.data())->appendToTree(*mDictTreeOut.get(), det.getName()); // cast to EncodedBlock - mFreqsAccumulation[det].clear(); - mFreqsMetaData[det].clear(); + // mFreqsAccumulation[det].clear(); + // mFreqsMetaData[det].clear(); + if (mDictPerDetector) { + header.detectors.reset(); + } header.detectors.set(det); + if (mDictPerDetector) { + closeDictionaryTreeAndFile(header); + } } /// create a processor spec diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 2506df8d710d5..787a8630ffada 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -47,6 +47,7 @@ void appendToTree(TTree& tree, const std::string brname, T& ptr) void CTFWriterSpec::init(InitContext& ic) { + mSaveDictAfter = ic.options().get<int>("save-dict-after"); } void CTFWriterSpec::run(ProcessingContext& pc) @@ -80,8 +81,13 @@ void CTFWriterSpec::run(ProcessingContext& pc) treeOut.reset(); fileOut->Close(); LOG(INFO) << "TF#" << mNTF << ": wrote " << fileOut->GetName() << " with CTF{" << header << "} in " << mTimer.CpuTime() - cput << " s"; + } else { + LOG(INFO) << "TF#" << mNTF << " CTF writing is disabled"; } mNTF++; + if (mCreateDict && mSaveDictAfter > 0 && (mNTF % mSaveDictAfter) == 0) { + storeDictionaries(); + } } void CTFWriterSpec::endOfStream(EndOfStreamContext& ec) @@ -99,6 +105,7 @@ void CTFWriterSpec::prepareDictionaryTreeAndFile(DetID det) { if (mDictPerDetector) { if (mDictTreeOut) { + mDictTreeOut->SetEntries(1); mDictTreeOut->Write(); mDictTreeOut.reset(); mDictFileOut.reset(); @@ -113,7 +120,7 @@ void CTFWriterSpec::prepareDictionaryTreeAndFile(DetID det) void CTFWriterSpec::storeDictionaries() { - CTFHeader header{mRun, 0}; + CTFHeader header{mRun, uint32_t(mNTF)}; storeDictionary<o2::itsmft::CTF>(DetID::ITS, header); storeDictionary<o2::itsmft::CTF>(DetID::MFT, header); storeDictionary<o2::tpc::CTF>(DetID::TPC, header); @@ -121,9 +128,17 @@ void CTFWriterSpec::storeDictionaries() storeDictionary<o2::ft0::CTF>(DetID::FT0, header); // close remnants if (mDictTreeOut) { - mDictTreeOut->SetEntries(1); + closeDictionaryTreeAndFile(header); + } + LOG(INFO) << "Saved CTF dictionary after " << mNTF << " TFs processed"; +} + +void CTFWriterSpec::closeDictionaryTreeAndFile(CTFHeader& header) +{ + if (mDictTreeOut) { appendToTree(*mDictTreeOut.get(), "CTFHeader", header); - mDictTreeOut->Write(); + mDictTreeOut->SetEntries(1); + mDictTreeOut->Write(mDictTreeOut->GetName(), TObject::kSingleKey); mDictTreeOut.reset(); mDictFileOut.reset(); } @@ -144,7 +159,7 @@ DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run, bool doCTF, inputs, Outputs{}, AlgorithmSpec{adaptFromTask<CTFWriterSpec>(dets, run, doCTF, doDict, dictPerDet)}, - Options{}}; + Options{{"save-dict-after", VariantType::Int, -1, {"In dictionary generation mode save it dictionary after certain number of TFs processed"}}}}; } } // namespace ctf From 3df91375a14c162aa668a1f9fbee383219871d98 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 10 Aug 2020 22:02:52 +0200 Subject: [PATCH 0320/1751] GPU: Some cleanup in visualization --- .../Standalone/display/GPUDisplay.cxx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 310986b318915..33ad8f525c4d3 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -710,7 +710,7 @@ GPUDisplay::vboList GPUDisplay::DrawClusters(const GPUTPCTracker& tracker, int s bool draw = mGlobalPos[cid].w == select; if (mMarkAdjacentClusters) { - const int attach = mMerger.ClusterAttachment()[cid]; + const int attach = tracker.GetConstantMem()->ioPtrs.mergedTrackHitAttachment[cid]; if (attach) { if (mMarkAdjacentClusters >= 16) { if (mQA && mQA->clusterRemovable(cid, mMarkAdjacentClusters == 17)) { @@ -723,7 +723,7 @@ GPUDisplay::vboList GPUDisplay::DrawClusters(const GPUTPCTracker& tracker, int s } else if ((mMarkAdjacentClusters & 4) && (attach & GPUTPCGMMergerTypes::attachGoodLeg) == 0) { draw = select == tMARKED; } else if (mMarkAdjacentClusters & 8) { - if (fabsf(mMerger.OutputTracks()[attach & GPUTPCGMMergerTypes::attachTrackMask].GetParam().GetQPt()) > 20.f) { + if (fabsf(tracker.GetConstantMem()->ioPtrs.mergedTracks[attach & GPUTPCGMMergerTypes::attachTrackMask].GetParam().GetQPt()) > 20.f) { draw = select == tMARKED; } } @@ -878,7 +878,7 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s break; } i = trackList[0][ii]; - track = &mMerger.OutputTracks()[i]; + track = &mMerger.GetConstantMem()->ioPtrs.mergedTracks[i]; size_t startCountInner = mVertexBuffer[iSlice].size(); bool drawing = false; @@ -896,10 +896,10 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s } } for (unsigned int k = 0; k < track->NClusters(); k++) { - if (mHideRejectedClusters && (mMerger.Clusters()[track->FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject)) { + if (mHideRejectedClusters && (mMerger.GetConstantMem()->ioPtrs.mergedTrackHits[track->FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject)) { continue; } - int cid = mMerger.Clusters()[track->FirstClusterRef() + k].num; + int cid = mMerger.GetConstantMem()->ioPtrs.mergedTrackHits[track->FirstClusterRef() + k].num; int w = mGlobalPos[cid].w; if (drawing) { drawPointLinestrip(iSlice, cid, tFINALTRACK, SEPERATE_GLOBAL_TRACKS_LIMIT); @@ -917,7 +917,7 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s drawPointLinestrip(iSlice, cid, tFINALTRACK, SEPERATE_GLOBAL_TRACKS_LIMIT); } if (!drawing && lastCluster != -1) { - drawPointLinestrip(iSlice, mMerger.Clusters()[track->FirstClusterRef() + lastCluster].num, 7, SEPERATE_GLOBAL_TRACKS_LIMIT); + drawPointLinestrip(iSlice, mMerger.GetConstantMem()->ioPtrs.mergedTrackHits[track->FirstClusterRef() + lastCluster].num, 7, SEPERATE_GLOBAL_TRACKS_LIMIT); } drawing = true; } @@ -952,11 +952,11 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s if (iMC == 0) { trkParam.Set(track->GetParam()); if (mMerger.Param().earlyTpcTransform) { - auto cl = mMerger.ClustersXYZ()[track->FirstClusterRef() + lastCluster]; + auto cl = mMerger.ClustersXYZ()[track->FirstClusterRef() + lastCluster]; // Todo: Remove direct usage of merger x = cl.x; ZOffset = track->GetParam().GetTZOffset(); } else { - auto cl = mMerger.Clusters()[track->FirstClusterRef() + lastCluster]; + auto cl = mMerger.GetConstantMem()->ioPtrs.mergedTrackHits[track->FirstClusterRef() + lastCluster]; const auto& cln = mMerger.GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cl.num]; float y, z; GPUTPCConvertImpl::convert(*mMerger.GetConstantMem(), cl.slice, cl.row, cln.getPad(), cln.getTime(), x, y, z); @@ -1152,10 +1152,10 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) mGlobalPosTRD = mGlobalPosPtrTRD.get(); mGlobalPosTRD2 = mGlobalPosPtrTRD2.get(); } - if ((size_t)mMerger.NOutputTracks() > mTRDTrackIds.size()) { - mTRDTrackIds.resize(mMerger.NOutputTracks()); + if ((size_t)mMerger.GetConstantMem()->ioPtrs.nMergedTracks > mTRDTrackIds.size()) { + mTRDTrackIds.resize(mMerger.GetConstantMem()->ioPtrs.nMergedTracks); } - memset(mTRDTrackIds.data(), 0, sizeof(mTRDTrackIds[0]) * mMerger.NOutputTracks()); + memset(mTRDTrackIds.data(), 0, sizeof(mTRDTrackIds[0]) * mMerger.GetConstantMem()->ioPtrs.nMergedTracks); for (int i = 0; i < trdTracker().NTracks(); i++) { if (trdTracker().Tracks()[i].GetNtracklets()) { mTRDTrackIds[trdTracker().Tracks()[i].GetTPCtrackId()] = i; @@ -1601,15 +1601,15 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) } } GPUCA_OPENMP(for) - for (int i = 0; i < mMerger.NOutputTracks(); i++) { - const GPUTPCGMMergedTrack* track = &mMerger.OutputTracks()[i]; + for (unsigned int i = 0; i < mMerger.GetConstantMem()->ioPtrs.nMergedTracks; i++) { + const GPUTPCGMMergedTrack* track = &mMerger.GetConstantMem()->ioPtrs.mergedTracks[i]; if (track->NClusters() == 0) { continue; } if (mHideRejectedTracks && !track->OK()) { continue; } - int slice = mMerger.Clusters()[track->FirstClusterRef() + track->NClusters() - 1].slice; + int slice = mMerger.GetConstantMem()->ioPtrs.mergedTrackHits[track->FirstClusterRef() + track->NClusters() - 1].slice; unsigned int col = 0; if (mNCollissions > 1) { int label = mQA ? mQA->GetMCTrackLabel(i) : -1; From 399ae699ee40dcca7dcc0e07311cb8e5495c355b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 10 Aug 2020 22:49:50 +0200 Subject: [PATCH 0321/1751] GPU: Remove option that is no longer supported --- GPU/GPUTracking/Base/GPUSettingsList.h | 1 - 1 file changed, 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 91623d7863bde..a95ef9c40980b 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -199,7 +199,6 @@ AddOption(runGPUforce, bool, true, "", 0, "Force usage of the specified GPU devi AddOption(noprompt, bool, true, "", 0, "Do prompt for keypress before exiting") AddOption(continueOnError, bool, false, "", 0, "Continue processing after an error") AddOption(seed, int, -1, "", 0, "Set srand seed (-1: random)") -AddOption(cleardebugout, bool, false, "", 0, "Clear debug output file when processing next event") AddOption(StartEvent, int, 0, "", 's', "First event to process", min(0)) AddOption(NEvents, int, -1, "", 'n', "Number of events to process (-1; all)", min(0)) AddOption(runs, int, 1, "runs", 'r', "Number of iterations to perform (repeat each event)", min(0)) From 4deee8d67bcafc732492ea2344c466be88152409 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 10 Aug 2020 23:21:51 +0200 Subject: [PATCH 0322/1751] GPU: Don't obtain the GPU context for CPU threads running concurrently (causes memory corruption) --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 4 ++-- GPU/GPUTracking/Base/GPUReconstruction.h | 2 +- GPU/GPUTracking/Base/GPUReconstructionCPU.h | 2 +- GPU/GPUTracking/Global/GPUChain.h | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 ++-- GPU/GPUTracking/Global/GPUChainTracking.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index cd69a746cf5d2..f841a5659d7a5 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -876,11 +876,11 @@ void GPUReconstruction::PrepareEvent() // TODO: Clean this up, this should not b AllocateRegisteredMemory(nullptr); } -int GPUReconstruction::CheckErrorCodes() +int GPUReconstruction::CheckErrorCodes(bool cpuOnly) { int retVal = 0; for (unsigned int i = 0; i < mChains.size(); i++) { - if (mChains[i]->CheckErrorCodes()) { + if (mChains[i]->CheckErrorCodes(cpuOnly)) { retVal++; } } diff --git a/GPU/GPUTracking/Base/GPUReconstruction.h b/GPU/GPUTracking/Base/GPUReconstruction.h index 2aa74e9dbf0b3..4334bc5265a27 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.h +++ b/GPU/GPUTracking/Base/GPUReconstruction.h @@ -180,7 +180,7 @@ class GPUReconstruction virtual void* getGPUPointer(void* ptr) { return ptr; } virtual void startGPUProfiling() {} virtual void endGPUProfiling() {} - int CheckErrorCodes(); + int CheckErrorCodes(bool cpuOnly = false); void RunPipelineWorker(); void TerminatePipelineWorker(); diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.h b/GPU/GPUTracking/Base/GPUReconstructionCPU.h index adc8594d46fe3..f6c2ccd477a6b 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.h +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.h @@ -300,7 +300,7 @@ inline int GPUReconstructionCPU::runKernel(const krnlExec& x, const krnlRunRange t->AddTime(setup.t); } } - if (mProcessingSettings.debugLevel >= 1 && CheckErrorCodes()) { + if (mProcessingSettings.debugLevel >= 1 && CheckErrorCodes(cpuFallback)) { throw std::runtime_error("kernel error code"); } } diff --git a/GPU/GPUTracking/Global/GPUChain.h b/GPU/GPUTracking/Global/GPUChain.h index a1483cd3a09bb..255672c880fa1 100644 --- a/GPU/GPUTracking/Global/GPUChain.h +++ b/GPU/GPUTracking/Global/GPUChain.h @@ -46,7 +46,7 @@ class GPUChain virtual int RunChain() = 0; virtual void MemorySize(size_t& gpuMem, size_t& pageLockedHostMem) = 0; virtual void PrintMemoryStatistics(){}; - virtual int CheckErrorCodes() { return 0; } + virtual int CheckErrorCodes(bool cpuOnly = false) { return 0; } virtual bool SupportsDoublePipeline() { return false; } virtual int FinalizePipelinedProcessing() { return 0; } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index b0ad632acc79d..869f8d237522d 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2490,10 +2490,10 @@ int GPUChainTracking::HelperOutput(int iSlice, int threadId, GPUReconstructionHe return 0; } -int GPUChainTracking::CheckErrorCodes() +int GPUChainTracking::CheckErrorCodes(bool cpuOnly) { int retVal = 0; - for (int i = 0; i < 1 + mRec->IsGPU(); i++) { + for (int i = 0; i < 1 + (!cpuOnly && mRec->IsGPU()); i++) { if (i) { const auto& threadContext = GetThreadContext(); if (GetProcessingSettings().doublePipeline) { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 8321b224d429e..9e2ff5ff55b55 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -75,7 +75,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega int Finalize() override; int RunChain() override; void MemorySize(size_t& gpuMem, size_t& pageLockedHostMem) override; - int CheckErrorCodes() override; + int CheckErrorCodes(bool cpuOnly = false) override; bool SupportsDoublePipeline() override { return true; } int FinalizePipelinedProcessing() override; void ClearErrorCodes(); From bf5165ce3b7bb07e0d1c08928aae157ceed898e9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 11 Aug 2020 10:37:31 +0200 Subject: [PATCH 0323/1751] GPU: Improve NVIDIA GPU performance with Volta and later GPUs --- GPU/Common/GPUCommonDefAPI.h | 5 +++++ GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx | 1 + GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx | 1 + 3 files changed, 7 insertions(+) diff --git a/GPU/Common/GPUCommonDefAPI.h b/GPU/Common/GPUCommonDefAPI.h index 2a4a9f249f615..c71d99b7456f7 100644 --- a/GPU/Common/GPUCommonDefAPI.h +++ b/GPU/Common/GPUCommonDefAPI.h @@ -45,6 +45,7 @@ #define GPUprivate() // private memory variable declaration #define GPUgeneric() // reference / ptr to generic address space #define GPUbarrier() // synchronize all GPU threads in block + #define GPUbarrierWarp() // synchronize threads inside warp #define GPUAtomic(type) type // atomic variable type #define GPUsharedref() // reference / ptr to shared memory #define GPUglobalref() // reference / ptr to global memory @@ -87,10 +88,12 @@ #define GPUconstexprref() GPUconstexpr() #if defined(__OPENCLCPP__) && !defined(__clang__) #define GPUbarrier() work_group_barrier(mem_fence::global | mem_fence::local); + #define GPUbarrierWarp() #define GPUAtomic(type) atomic<type> static_assert(sizeof(atomic<unsigned int>) == sizeof(unsigned int), "Invalid size of atomic type"); #else #define GPUbarrier() barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE) + #define GPUbarrierWarp() #if defined(__OPENCLCPP__) && defined(GPUCA_OPENCL_CPP_CLANG_C11_ATOMICS) namespace GPUCA_NAMESPACE { namespace gpu { template <class T> struct oclAtomic; @@ -148,6 +151,7 @@ #define GPUprivate() #define GPUgeneric() #define GPUbarrier() __syncthreads() + #define GPUbarrierWarp() #define GPUAtomic(type) type #elif defined(__CUDACC__) //Defines for CUDA #define GPUd() __device__ @@ -169,6 +173,7 @@ #define GPUprivate() #define GPUgeneric() #define GPUbarrier() __syncthreads() + #define GPUbarrierWarp() __syncwarp() #define GPUAtomic(type) type #endif diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 5d01bd41fa213..fa22628435738 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -34,6 +34,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at char lastLeg = 0; int myTrack = 0; for (unsigned int i = get_global_id(0); i < (unsigned int)merger.NOutputTracks(); i += get_global_size(0)) { + GPUbarrierWarp(); const GPUTPCGMMergedTrack& GPUrestrict() trk = merger.OutputTracks()[i]; if (!trk.OK()) { continue; diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx index 2c49c33c3f129..8c4d3a56687ca 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx @@ -41,6 +41,7 @@ GPUdii() void GPUTPCTrackletSelector::Thread<0>(int nBlocks, int nThreads, int i return; } } + GPUbarrierWarp(); GPUglobalref() MEM_GLOBAL(GPUTPCTracklet) & GPUrestrict() tracklet = tracker.Tracklets()[itr]; const int kMaxRowGap = 4; From 653b52ad163c6a5a0bd2e8fb9a09abf7bc44c5d7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 11 Aug 2020 11:37:44 +0200 Subject: [PATCH 0324/1751] Rename --mft to --runmft to avoid ambiguity --- .../ITSMFT/common/workflow/src/digit-writer-workflow.cxx | 4 ++-- .../ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx | 4 ++-- Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx index e93cab39236f0..f969f197380af 100644 --- a/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx @@ -22,7 +22,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) // option allowing to set parameters std::vector<ConfigParamSpec> options{ ConfigParamSpec{"disable-mc", VariantType::Bool, false, {"disable mc truth"}}, - ConfigParamSpec{"mft", VariantType::Bool, false, {"expect MFT data"}}, + ConfigParamSpec{"runmft", VariantType::Bool, false, {"expect MFT data"}}, ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}}; std::swap(workflowOptions, options); @@ -40,7 +40,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); - if (cfgc.options().get<bool>("mft")) { + if (cfgc.options().get<bool>("runmft")) { wf.emplace_back(o2::itsmft::getMFTDigitWriterSpec(useMC)); } else { wf.emplace_back(o2::itsmft::getITSDigitWriterSpec(useMC)); diff --git a/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx index bb7d0868c3d19..2859ab6bcd0c3 100644 --- a/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx @@ -21,7 +21,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { // option allowing to set parameters std::vector<ConfigParamSpec> options{ - ConfigParamSpec{"mft", VariantType::Bool, false, {"source detector is MFT (default ITS)"}}, + ConfigParamSpec{"runmft", VariantType::Bool, false, {"source detector is MFT (default ITS)"}}, ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; std::swap(workflowOptions, options); @@ -37,7 +37,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); - if (cfgc.options().get<bool>("mft")) { + if (cfgc.options().get<bool>("runmft")) { wf.emplace_back(o2::itsmft::getEntropyEncoderSpec("MFT")); } else { wf.emplace_back(o2::itsmft::getEntropyEncoderSpec("ITS")); diff --git a/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx index cb9c73c25d44b..55992bcce62be 100644 --- a/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx @@ -21,7 +21,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { // option allowing to set parameters std::vector<ConfigParamSpec> options{ - ConfigParamSpec{"mft", VariantType::Bool, false, {"source detector is MFT (default ITS)"}}, + ConfigParamSpec{"runmft", VariantType::Bool, false, {"source detector is MFT (default ITS)"}}, ConfigParamSpec{"no-clusters", VariantType::Bool, false, {"do not produce clusters (def: produce)"}}, ConfigParamSpec{"no-cluster-patterns", VariantType::Bool, false, {"do not produce clusters patterns (def: produce)"}}, ConfigParamSpec{"digits", VariantType::Bool, false, {"produce digits (def: skip)"}}, @@ -48,7 +48,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); - if (cfgc.options().get<bool>("mft")) { + if (cfgc.options().get<bool>("runmft")) { wf.emplace_back(o2::itsmft::getSTFDecoderMFTSpec(doClusters, doPatterns, doDigits, dict, noise)); } else { wf.emplace_back(o2::itsmft::getSTFDecoderITSSpec(doClusters, doPatterns, doDigits, dict, noise)); From 146a57d9c63d7c4afb467b95f55e15b57d13fac1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 10 Aug 2020 23:06:44 +0200 Subject: [PATCH 0325/1751] DPL: drop unneeded helper class --- Framework/Core/include/Framework/CallbackService.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Framework/Core/include/Framework/CallbackService.h b/Framework/Core/include/Framework/CallbackService.h index deaf9b0a0f9e7..a44ba60977484 100644 --- a/Framework/Core/include/Framework/CallbackService.h +++ b/Framework/Core/include/Framework/CallbackService.h @@ -60,13 +60,6 @@ class CallbackService RegionInfoCallback }; - template <typename T, T... v> - class EnumRegistry - { - constexpr static T values[] = {v...}; - constexpr static std::size_t size = sizeof...(v); - }; - using StartCallback = std::function<void()>; using StopCallback = std::function<void()>; using ResetCallback = std::function<void()>; From a971316853247388a5efe128947153d21f9f4961 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 11 Aug 2020 00:39:49 +0200 Subject: [PATCH 0326/1751] DPL: clean ups to DataRelayer --- .../Core/include/Framework/DataRelayer.h | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Framework/Core/include/Framework/DataRelayer.h b/Framework/Core/include/Framework/DataRelayer.h index 051517f6bc390..1271f3374ae78 100644 --- a/Framework/Core/include/Framework/DataRelayer.h +++ b/Framework/Core/include/Framework/DataRelayer.h @@ -7,8 +7,8 @@ // 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_DATARELAYER_H -#define FRAMEWORK_DATARELAYER_H +#ifndef O2_FRAMEWORK_DATARELAYER_H_ +#define O2_FRAMEWORK_DATARELAYER_H_ #include "Framework/RootSerializationSupport.h" #include "Framework/InputRoute.h" @@ -23,13 +23,12 @@ class FairMQMessage; -namespace o2 -{ -namespace monitoring +namespace o2::monitoring { class Monitoring; } -namespace framework + +namespace o2::framework { /// Helper struct to hold statistics about the relaying process. @@ -84,10 +83,6 @@ class DataRelayer /// DataRelayer they need to be deleted once the processing is concluded. std::vector<MessageSet> getInputsForTimeslice(TimesliceSlot id); - /// Returns the index of the arguments which have to be forwarded to - /// the next processor - const std::vector<int>& forwardingMask(); - /// Returns how many timeslices we can handle in parallel size_t getParallelTimeslices() const; @@ -130,7 +125,6 @@ class DataRelayer DataRelayerStats mStats; }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif +#endif // O2_FRAMEWORK_DATARELAYER_H_ From 1806c07b5a67cef31d982fc1667d027c0c607ba0 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 11 Aug 2020 15:26:01 +0200 Subject: [PATCH 0327/1751] DPL: forward return type decision to registry Required if we want to return service_ptrs, rather than just references. --- Framework/Core/include/Framework/AlgorithmSpec.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/AlgorithmSpec.h b/Framework/Core/include/Framework/AlgorithmSpec.h index 2b8471da8e01e..49dd495ba0178 100644 --- a/Framework/Core/include/Framework/AlgorithmSpec.h +++ b/Framework/Core/include/Framework/AlgorithmSpec.h @@ -90,11 +90,11 @@ struct AlgorithmSpec { template <typename T> struct ContextElementTraits { - static T& get(ProcessingContext& ctx) + static decltype(auto) get(ProcessingContext& ctx) { return ctx.services().get<T>(); } - static T& get(InitContext& ctx) + static decltype(auto) get(InitContext& ctx) { return ctx.services().get<T>(); } From 203cbf22e71f9b38bb4f98566aacf6e799f9b160 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 1 Aug 2020 13:46:57 +0200 Subject: [PATCH 0328/1751] DPL: make RawDeviceService global FairMQ is thread safe when sending / receiving messages. --- Framework/Core/include/Framework/RawDeviceService.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Framework/Core/include/Framework/RawDeviceService.h b/Framework/Core/include/Framework/RawDeviceService.h index 05a9b6b23e7ce..360de775adfbc 100644 --- a/Framework/Core/include/Framework/RawDeviceService.h +++ b/Framework/Core/include/Framework/RawDeviceService.h @@ -10,6 +10,8 @@ #ifndef FRAMEWORK_RAWDEVICESERVICE_H #define FRAMEWORK_RAWDEVICESERVICE_H +#include "Framework/ServiceHandle.h" + class FairMQDevice; namespace o2 @@ -26,6 +28,8 @@ class DeviceSpec; class RawDeviceService { public: + constexpr static ServiceKind service_kind = ServiceKind::Global; + virtual FairMQDevice* device() = 0; virtual void setDevice(FairMQDevice* device) = 0; virtual DeviceSpec const& spec() = 0; From 45f9e7352701e1c932a09bdbaead289b82e81ec6 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 10 Aug 2020 20:35:08 +0200 Subject: [PATCH 0329/1751] Temp.fix for TOF raw->digit orbit reset to 0 (O2-1633) --- .../TOF/workflow/src/CompressedDecodingTask.cxx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 97088ca0bdf4b..8c1e11fda9009 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -59,13 +59,18 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) std::vector<o2::tof::ReadoutWindowData>* row = mDecoder.getReadoutWindowData(); ReadoutWindowData* last = nullptr; - if (row->size()) - last = &(row->at(row->size() - 1)); - int lastval = last->first() + last->size(); + o2::InteractionRecord lastIR; + int lastval = 0; + if (!row->empty()) { + last = &row->back(); + lastval = last->first() + last->size(); + lastIR = last->mFirstIR; + } while (row->size() < nwindowperTF) { // complete timeframe with empty readout windows - row->emplace_back(lastval, 0); + auto& dummy = row->emplace_back(lastval, 0); + dummy.mFirstIR = lastIR; } while (row->size() > nwindowperTF) { // remove extra readout windows after a check they are empty From 73546a513e17a5e4ac8be2a4a38bd1f5c4b6199d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 10 Aug 2020 17:08:32 +0200 Subject: [PATCH 0330/1751] DPL: make DataProcessingStats threadsafe --- .../include/Framework/DataProcessingStats.h | 19 ++++++++++--------- Framework/Core/src/CommonServices.cxx | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingStats.h b/Framework/Core/include/Framework/DataProcessingStats.h index 958df21d7df9b..4ac9f70652c8d 100644 --- a/Framework/Core/include/Framework/DataProcessingStats.h +++ b/Framework/Core/include/Framework/DataProcessingStats.h @@ -19,22 +19,23 @@ namespace framework /// Helper struct to hold statistics about the data processing happening. struct DataProcessingStats { + constexpr static ServiceKind service_kind = ServiceKind::Global; // We use this to keep track of the latency of the first message we get for a given input record // and of the last one. struct InputLatency { int minLatency = 0; int maxLatency = 0; }; - int pendingInputs = 0; - int incomplete = 0; - int inputParts = 0; - int lastElapsedTimeMs = 0; - int lastTotalProcessedSize = 0; + std::atomic<int> pendingInputs = 0; + std::atomic<int> incomplete = 0; + std::atomic<int> inputParts = 0; + std::atomic<int> lastElapsedTimeMs = 0; + std::atomic<int> lastTotalProcessedSize = 0; - uint64_t lastSlowMetricSentTimestamp = 0; /// The timestamp of the last time we sent slow metrics - uint64_t lastMetricFlushedTimestamp = 0; /// The timestamp of the last time we actually flushed metrics - uint64_t beginIterationTimestamp = 0; /// The timestamp of when the current ConditionalRun was started - InputLatency lastLatency = {}; + std::atomic<uint64_t> lastSlowMetricSentTimestamp = 0; /// The timestamp of the last time we sent slow metrics + std::atomic<uint64_t> lastMetricFlushedTimestamp = 0; /// The timestamp of the last time we actually flushed metrics + std::atomic<uint64_t> beginIterationTimestamp = 0; /// The timestamp of when the current ConditionalRun was started + InputLatency lastLatency = {0, 0}; std::vector<int> relayerState; }; diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 4553e242f04e8..9a351f31eba0a 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -404,7 +404,7 @@ auto sendRelayerMetrics(ServiceRegistry& registry, DataProcessingStats& stats) - monitoring.send(Metric{stats.lastElapsedTimeMs, "elapsed_time_ms"}.addTag(Key::Subsystem, Value::DPL)); monitoring.send(Metric{stats.lastTotalProcessedSize, "processed_input_size_byte"} .addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(stats.lastTotalProcessedSize / (stats.lastElapsedTimeMs ? stats.lastElapsedTimeMs : 1) / 1000), + monitoring.send(Metric{(stats.lastTotalProcessedSize.load() / (stats.lastElapsedTimeMs.load() ? stats.lastElapsedTimeMs.load() : 1) / 1000), "processing_rate_mb_s"} .addTag(Key::Subsystem, Value::DPL)); monitoring.send(Metric{stats.lastLatency.minLatency, "min_input_latency_ms"} @@ -414,7 +414,7 @@ auto sendRelayerMetrics(ServiceRegistry& registry, DataProcessingStats& stats) - monitoring.send(Metric{(stats.lastTotalProcessedSize / (stats.lastLatency.maxLatency ? stats.lastLatency.maxLatency : 1) / 1000), "input_rate_mb_s"} .addTag(Key::Subsystem, Value::DPL)); - stats.lastSlowMetricSentTimestamp = stats.beginIterationTimestamp; + stats.lastSlowMetricSentTimestamp.store(stats.beginIterationTimestamp.load()); O2_SIGNPOST_END(MonitoringStatus::ID, MonitoringStatus::SEND, 0, 0, O2_SIGNPOST_BLUE); }; @@ -438,7 +438,7 @@ auto flushMetrics(ServiceRegistry& registry, DataProcessingStats& stats) -> void } relayer.sendContextState(); monitoring.flushBuffer(); - stats.lastMetricFlushedTimestamp = stats.beginIterationTimestamp; + stats.lastMetricFlushedTimestamp.store(stats.beginIterationTimestamp.load()); O2_SIGNPOST_END(MonitoringStatus::ID, MonitoringStatus::FLUSH, 0, 0, O2_SIGNPOST_RED); }; } // namespace From 542cbfd7ad9ffab083544faf0b9016b0b1ae5ba6 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Wed, 12 Aug 2020 01:46:44 +0200 Subject: [PATCH 0331/1751] throw runtime_error when file can not be read or tree does not exist (#4089) --- .../include/Framework/DataInputDirector.h | 6 ++- Framework/Core/src/AODReaderHelpers.cxx | 26 ----------- Framework/Core/src/DataInputDirector.cxx | 46 ++++++++++++------- Framework/Core/src/DataOutputDirector.cxx | 4 +- 4 files changed, 37 insertions(+), 45 deletions(-) diff --git a/Framework/Core/include/Framework/DataInputDirector.h b/Framework/Core/include/Framework/DataInputDirector.h index 36634a3b4a40f..189f1ec6baf1b 100644 --- a/Framework/Core/include/Framework/DataInputDirector.h +++ b/Framework/Core/include/Framework/DataInputDirector.h @@ -34,6 +34,7 @@ struct DataInputDescriptor { std::unique_ptr<data_matcher::DataDescriptorMatcher> matcher; DataInputDescriptor() = default; + DataInputDescriptor(bool alienSupport); void printOut(); @@ -57,6 +58,7 @@ struct DataInputDescriptor { TFile* getInputFile(int counter); void closeInputFile(); std::string getInputFilename(int counter); + bool isAlienSupportOn() { return mAlienSupport; } private: std::string minputfilesFile = ""; @@ -66,6 +68,7 @@ struct DataInputDescriptor { std::vector<std::string> mfilenames; std::vector<std::string>* mdefaultFilenamesPtr = nullptr; TFile* mcurrentFile = nullptr; + bool mAlienSupport = false; }; struct DataInputDirector { @@ -103,7 +106,8 @@ struct DataInputDirector { std::vector<std::string> mdefaultInputFiles; std::vector<DataInputDescriptor*> mdataInputDescriptors; - bool mdebugmode = false; + bool mDebugMode = false; + bool mAlienSupport = false; bool readJsonDocument(Document* doc); bool isValid(); diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 3fa0189a89f8c..751cd6b4228db 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -187,37 +187,11 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> reques }}; } -namespace -{ -void checkAndEnableAlien(std::string const& filename) -{ - // Check if filename is an alien file or if it contains alien files, - // TGrid::Connect if that is the case. - if (filename.rfind("alien://", 0) == 0) { - LOG(debug) << "AliEn file requested. Enabling support."; - TGrid::Connect("alien://"); - } - if (filename.rfind("@", 0) == 0) { - std::string strippedFilename = filename; - strippedFilename.erase(0, 1); - std::ifstream filenames(strippedFilename); - for (std::string line; std::getline(filenames, line);) { - if (line.rfind("alien://", 0) == 0) { - LOG(debug) << "AliEn file requested. Enabling support."; - TGrid::Connect("alien://"); - break; - } - } - } -} -} // namespace - AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() { auto callback = AlgorithmSpec{adaptStateful([](ConfigParamRegistry const& options, DeviceSpec const& spec) { auto filename = options.get<std::string>("aod-file"); - checkAndEnableAlien(filename); // create a DataInputDirector auto didir = std::make_shared<DataInputDirector>(filename); diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 1a1f2efc64c89..ffb566d1f07c5 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -15,12 +15,19 @@ #include "rapidjson/prettywriter.h" #include "rapidjson/filereadstream.h" +#include "TGrid.h" + namespace o2 { namespace framework { using namespace rapidjson; +DataInputDescriptor::DataInputDescriptor(bool alienSupport) +{ + mAlienSupport = alienSupport; +} + std::string DataInputDescriptor::getInputfilesFilename() { return (minputfilesFile.empty() && minputfilesFilePtr) ? (std::string)*minputfilesFilePtr : minputfilesFile; @@ -38,12 +45,16 @@ std::regex DataInputDescriptor::getFilenamesRegex() void DataInputDescriptor::addFilename(std::string fn) { + if (!mAlienSupport && fn.rfind("alien://", 0) == 0) { + LOG(debug) << "AliEn file requested. Enabling support."; + TGrid::Connect("alien://"); + mAlienSupport = true; + } mfilenames.emplace_back(fn); } TFile* DataInputDescriptor::getInputFile(int counter) { - if (counter < getNumberInputfiles()) { if (mcurrentFile) { if (mcurrentFile->GetName() != mfilenames[counter]) { @@ -53,6 +64,9 @@ TFile* DataInputDescriptor::getInputFile(int counter) } else { mcurrentFile = TFile::Open(mfilenames[counter].c_str()); } + if (!mcurrentFile) { + throw std::runtime_error(fmt::format("Couldn't open file \"{}\"!", mfilenames[counter])); + } } else { closeInputFile(); } @@ -156,7 +170,7 @@ void DataInputDirector::createDefaultDataInputDescriptor() if (mdefaultDataInputDescriptor) { delete mdefaultDataInputDescriptor; } - mdefaultDataInputDescriptor = new DataInputDescriptor(); + mdefaultDataInputDescriptor = new DataInputDescriptor(mAlienSupport); mdefaultDataInputDescriptor->setInputfilesFile(minputfilesFile); mdefaultDataInputDescriptor->setFilenamesRegex(mFilenameRegex); @@ -164,6 +178,8 @@ void DataInputDirector::createDefaultDataInputDescriptor() mdefaultDataInputDescriptor->tablename = "any"; mdefaultDataInputDescriptor->treename = "any"; mdefaultDataInputDescriptor->fillInputfiles(); + + mAlienSupport &= mdefaultDataInputDescriptor->isAlienSupportOn(); } bool DataInputDirector::readJson(std::string const& fnjson) @@ -215,16 +231,16 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) itemName = "debugmode"; if (didirItem.HasMember(itemName)) { if (didirItem[itemName].IsBool()) { - mdebugmode = (didirItem[itemName].GetBool()); + mDebugMode = (didirItem[itemName].GetBool()); } else { LOGP(ERROR, "Check the JSON document! Item \"{}\" must be a boolean!", itemName); return false; } } else { - mdebugmode = false; + mDebugMode = false; } - if (mdebugmode) { + if (mDebugMode) { StringBuffer buffer; buffer.Clear(); PrettyWriter<StringBuffer> writer(buffer); @@ -279,7 +295,7 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) return false; } // create a new dataInputDescriptor - auto didesc = new DataInputDescriptor(); + auto didesc = new DataInputDescriptor(mAlienSupport); didesc->setDefaultInputfiles(&mdefaultInputFiles); itemName = "table"; @@ -360,6 +376,7 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) didesc->printOut(); LOGP(INFO, "This DataInputDescriptor is ignored because its file list is empty!"); } + mAlienSupport &= didesc->isAlienSupportOn(); } } @@ -373,7 +390,7 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) } // print the DataIputDirector - if (mdebugmode) { + if (mDebugMode) { printOut(); } @@ -405,14 +422,13 @@ std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader if (!didesc) { didesc = mdefaultDataInputDescriptor; } + auto file = didesc->getInputFile(counter); - if (file->IsOpen()) { + if (file) { reader = std::make_unique<TTreeReader>(treename.c_str(), file); if (!reader) { - LOGP(ERROR, "Couldn't create TTreeReader for tree \"{}\" in file \"{}\"", treename, file->GetName()); + throw std::runtime_error(fmt::format(R"(Couldn't create TTreeReader for tree "{}" in file "{}")", treename, file->GetName())); } - } else { - LOGP(ERROR, "Couldn't open file \"{}\"", file->GetName()); } return reader; @@ -446,15 +462,13 @@ TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter) didesc = mdefaultDataInputDescriptor; treename = dh.dataDescription.str; } - auto file = didesc->getInputFile(counter); - if (file->IsOpen()) { + auto file = didesc->getInputFile(counter); + if (file) { tree = (TTree*)file->Get(treename); if (!tree) { - LOGP(ERROR, "Couldn't get TTree \"{}\" from \"{}\"", treename, file->GetName()); + throw std::runtime_error(fmt::format(R"(Couldn't get TTree "{}" from "{}")", treename, file->GetName())); } - } else { - LOGP(ERROR, "Couldn't open file \"{}\"", file->GetName()); } return tree; diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index 61d1cfa07d5eb..af9bcbee17fc7 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -108,9 +108,9 @@ void DataOutputDescriptor::printOut() LOGP(INFO, " File name base : {}", getFilenameBase()); LOGP(INFO, " Tree name : {}", treename); if (colnames.empty()) { - LOGP(INFO, " Columns : \"all\""); + LOGP(INFO, " Columns : \"all\""); } else { - LOGP(INFO, " Columns : {}", colnames.size()); + LOGP(INFO, " Columns : {}", colnames.size()); } for (auto cn : colnames) LOGP(INFO, " {}", cn); From b0e2bb323c8bac18b39e0856857cddc78ff9a989 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 12 Aug 2020 08:45:45 +0200 Subject: [PATCH 0332/1751] DPL: force ignore SIGWINCH (#4131) Apparently triggers a state machine transition on linux. --- Framework/Core/src/DataProcessingDevice.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index b62d3bd86f8a2..aab998c66c6a4 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -270,7 +270,7 @@ void DataProcessingDevice::Init() void on_signal_callback(uv_signal_t* handle, int signum) { ZoneScopedN("Signal callaback"); - LOG(debug) << "Signal " << signum << "received." << std::endl; + LOG(debug) << "Signal " << signum << " received."; } void DataProcessingDevice::InitTask() @@ -293,6 +293,11 @@ void DataProcessingDevice::InitTask() uv_signal_t* sigusr1Handle = (uv_signal_t*)malloc(sizeof(uv_signal_t)); uv_signal_init(mState.loop, sigusr1Handle); uv_signal_start(sigusr1Handle, on_signal_callback, SIGUSR1); + // Handle SIGWINCH by simply forcing the event loop to continue. + // This will hopefully hide it from FairMQ on linux. + uv_signal_t* sigwinchHandle = (uv_signal_t*)malloc(sizeof(uv_signal_t)); + uv_signal_init(mState.loop, sigwinchHandle); + uv_signal_start(sigwinchHandle, on_signal_callback, SIGWINCH); // We add a timer only in case a channel poller is not there. if ((mStatefulProcess != nullptr) || (mStatelessProcess != nullptr)) { From 446ce1fe538533313c367cf0317493d7cbac0460 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 12 Aug 2020 08:46:05 +0200 Subject: [PATCH 0333/1751] DPL: fix ServiceRegistry::active method when service is just declared (#4132) Fixes issue where --configuration option was ignored. --- .../Core/include/Framework/ServiceRegistry.h | 3 +++ Framework/Core/src/CommonServices.cxx | 2 +- Framework/Core/test/test_Services.cxx | 22 +++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index 488155ea1acd9..d32cf78d1c4b9 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -218,6 +218,9 @@ struct ServiceRegistry { constexpr auto typeHash = TypeIdHelpers::uniqueId<T>(); auto tid = std::this_thread::get_id(); std::hash<std::thread::id> hasher; + if (this->getPos(typeHash, 0) != -1) { + return true; + } auto result = this->getPos(typeHash, hasher(tid)) != -1; return result; } diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 9a351f31eba0a..d5a06021d645b 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -190,7 +190,7 @@ o2::framework::ServiceSpec CommonServices::configurationSpec() nullptr, nullptr, nullptr, - ServiceKind::Serial}; + ServiceKind::Global}; } o2::framework::ServiceSpec CommonServices::controlSpec() diff --git a/Framework/Core/test/test_Services.cxx b/Framework/Core/test/test_Services.cxx index d3392df309eeb..946e21afd1bb5 100644 --- a/Framework/Core/test/test_Services.cxx +++ b/Framework/Core/test/test_Services.cxx @@ -14,7 +14,10 @@ #include "Framework/ServiceHandle.h" #include "Framework/ServiceRegistry.h" #include "Framework/CallbackService.h" +#include "Framework/CommonServices.h" +#include <Framework/DeviceState.h> #include <boost/test/unit_test.hpp> +#include <options/FairMQProgOptions.h> #include <iostream> #include <memory> @@ -55,6 +58,9 @@ BOOST_AUTO_TEST_CASE(TestServiceRegistry) BOOST_CHECK(registry.get<InterfaceA>().method() == true); BOOST_CHECK(registry.get<InterfaceB>().method() == false); BOOST_CHECK(registry.get<InterfaceC const>().method() == false); + BOOST_CHECK(registry.active<InterfaceA>() == true); + BOOST_CHECK(registry.active<InterfaceB>() == true); + BOOST_CHECK(registry.active<InterfaceC>() == false); BOOST_CHECK_THROW(registry.get<InterfaceA const>(), std::runtime_error); BOOST_CHECK_THROW(registry.get<InterfaceC>(), std::runtime_error); } @@ -161,3 +167,19 @@ BOOST_AUTO_TEST_CASE(TestServiceRegistryCtor) ServiceRegistry registry; registry = ServiceRegistry(); } + +BOOST_AUTO_TEST_CASE(TestServiceDeclaration) +{ + using namespace o2::framework; + ServiceRegistry registry; + DeviceState state; + FairMQProgOptions options; + options.SetProperty("monitoring-backend", "no-op://"); + options.SetProperty("infologger-mode", "no-op://"); + options.SetProperty("infologger-severity", "info"); + options.SetProperty("configuration", "command-line"); + + registry.declareService(CommonServices::callbacksSpec(), state, options); + BOOST_CHECK(registry.active<CallbackService>() == true); + BOOST_CHECK(registry.active<DummyService>() == false); +} From 8356eb161488f62a5532efb94a0f71fbd58885b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Wed, 12 Aug 2020 11:12:13 +0200 Subject: [PATCH 0334/1751] Extend O2 PID Parametrization (#4115) * Update Parametrization base classes - Remove template formulation - Move to an inheritance scheme - Add type to define input/output type of the PID response/parametrization - Move base classes for PID response to dedicated directory * Add base class for each detector response - Update CMakeFile * Update TOF PID Response - Add inheritance from DetectorResponse - Update TOF part in PID response * Update TPC PID Response - Add inheritance from DetectorResponse - Update TPC part in PID response * Update TPC PID task - Add task dedicated to expected signal and task dedicated to Nsigmas * Add Bethe Bloch and TPC reso parametrizations * Add parametrization for the TOF resolution * Move computation of PID values to dedicated tasks * Add handler for the TOF reso param * Add handler for the TPC response param * Update binning in TPC signal QA * Using TPC momentum for Eloss computation --- Analysis/DataModel/CMakeLists.txt | 41 +++++- Analysis/DataModel/include/PID/BetheBloch.h | 41 ++++++ Analysis/DataModel/include/PID/PIDResponse.h | 105 +-------------- Analysis/DataModel/include/PID/PIDTOF.h | 59 ++------ Analysis/DataModel/include/PID/PIDTPC.h | 56 ++------ Analysis/DataModel/include/PID/ParamBase.h | 71 ---------- Analysis/DataModel/include/PID/TOFReso.h | 51 +++++++ Analysis/DataModel/include/PID/TPCReso.h | 41 ++++++ .../include/PIDBase/DetectorResponse.h | 92 +++++++++++++ .../DataModel/include/PIDBase/ParamBase.h | 127 ++++++++++++++++++ .../DataModel/src/AnalysisDataModelLinkDef.h | 21 +++ Analysis/DataModel/src/DetectorResponse.cxx | 56 ++++++++ Analysis/DataModel/src/PIDTOF.cxx | 18 +-- Analysis/DataModel/src/PIDTPC.cxx | 26 ++-- Analysis/DataModel/src/ParamBase.cxx | 52 +++++++ Analysis/DataModel/src/handleParamTOFReso.cxx | 104 ++++++++++++++ .../src/handleParamTPCBetheBloch.cxx | 113 ++++++++++++++++ Analysis/Tasks/CMakeLists.txt | 10 ++ Analysis/Tasks/pidTOF.cxx | 106 +++++++++++++++ Analysis/Tasks/pidTPC.cxx | 95 +++++++++++++ Analysis/Tasks/spectraTOF.cxx | 1 - Analysis/Tasks/spectraTPC.cxx | 53 ++++++-- 22 files changed, 1035 insertions(+), 304 deletions(-) create mode 100644 Analysis/DataModel/include/PID/BetheBloch.h delete mode 100644 Analysis/DataModel/include/PID/ParamBase.h create mode 100644 Analysis/DataModel/include/PID/TOFReso.h create mode 100644 Analysis/DataModel/include/PID/TPCReso.h create mode 100644 Analysis/DataModel/include/PIDBase/DetectorResponse.h create mode 100644 Analysis/DataModel/include/PIDBase/ParamBase.h create mode 100644 Analysis/DataModel/src/AnalysisDataModelLinkDef.h create mode 100644 Analysis/DataModel/src/DetectorResponse.cxx create mode 100644 Analysis/DataModel/src/ParamBase.cxx create mode 100644 Analysis/DataModel/src/handleParamTOFReso.cxx create mode 100644 Analysis/DataModel/src/handleParamTPCBetheBloch.cxx create mode 100644 Analysis/Tasks/pidTOF.cxx create mode 100644 Analysis/Tasks/pidTPC.cxx diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index 9a37c144b8b91..4f9628f883e2f 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -10,13 +10,52 @@ o2_add_library(AnalysisDataModel SOURCES src/dummy.cxx + src/ParamBase.cxx + src/DetectorResponse.cxx src/PIDTOF.cxx src/PIDTPC.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats O2::TPCSimulation ) + +o2_target_root_dictionary(AnalysisDataModel + HEADERS include/PIDBase/ParamBase.h + include/PIDBase/DetectorResponse.h + include/PID/PIDTOF.h + include/PID/TOFReso.h + include/PID/PIDTPC.h + include/PID/BetheBloch.h + include/PID/TPCReso.h + LINKDEF src/AnalysisDataModelLinkDef.h + ) + +install(FILES + include/PIDBase/ParamBase.h + include/PIDBase/DetectorResponse.h + DESTINATION + include/PIDBase) + +install(FILES + include/PID/PIDTOF.h + include/PID/TOFReso.h + include/PID/PIDTPC.h + include/PID/BetheBloch.h + include/PID/TPCReso.h + DESTINATION + include/PID) + o2_add_executable(dump-aod-data-model SOURCES src/dumpDataModel.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel - ) + ) + +o2_add_executable(pidparam-tpc-bethe-bloch + SOURCES src/handleParamTPCBetheBloch.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel + ) + +o2_add_executable(pidparam-tof-reso + SOURCES src/handleParamTOFReso.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel + ) diff --git a/Analysis/DataModel/include/PID/BetheBloch.h b/Analysis/DataModel/include/PID/BetheBloch.h new file mode 100644 index 0000000000000..2ad85cd0f1fc4 --- /dev/null +++ b/Analysis/DataModel/include/PID/BetheBloch.h @@ -0,0 +1,41 @@ +// 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 BetheBloch.h +/// \author Nicolo' Jacazio +/// \since 07/08/2020 +/// \brief Implementation for the TPC PID response of the BB parametrization +/// + +#ifndef O2_ANALYSIS_PID_BETHEBLOCH_H_ +#define O2_ANALYSIS_PID_BETHEBLOCH_H_ + +#include "TPCSimulation/Detector.h" +#include "PIDBase/ParamBase.h" + +namespace o2::pid::tpc +{ + +class BetheBloch : public Parametrization +{ + public: + BetheBloch() : Parametrization("BetheBloch", 7) { Printf("%s", fName.Data()); }; + ~BetheBloch() override = default; + float operator()(const float* x) const override + { + return mParameters[5] * o2::tpc::Detector::BetheBlochAleph(x[0], mParameters[0], mParameters[1], mParameters[2], mParameters[3], mParameters[4]) * TMath::Power(x[1], mParameters[6]); + } + ClassDef(BetheBloch, 1); +}; + +} // namespace o2::pid::tpc + +#endif diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/PID/PIDResponse.h index 8227b05a0cfc7..bd228af285129 100644 --- a/Analysis/DataModel/include/PID/PIDResponse.h +++ b/Analysis/DataModel/include/PID/PIDResponse.h @@ -9,9 +9,10 @@ // or submit itself to any jurisdiction. /// -/// Class to provide PID response /// \file PIDResponse.h /// \author Nicolo' Jacazio +/// \brief Set of tables, tasks and utilities to provide the interface between +/// the analysis data model and the PID response /// #ifndef O2_FRAMEWORK_PIDRESPONSE_H_ @@ -130,106 +131,4 @@ DECLARE_SOA_TABLE(pidRespTPC, "AOD", "pidRespTPC", } // namespace o2::aod -using namespace o2; -using namespace o2::framework; -using namespace o2::pid; -using namespace o2::framework::expressions; -using namespace o2::track; - -struct pidTOFTask { - Produces<aod::pidRespTOF> tofpid; - Produces<aod::pidRespTOFbeta> tofpidbeta; - - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) - { - LOGF(info, "Tracks for collision: %d", tracks.size()); - tof::EventTime evt = tof::EventTime(); - evt.SetEvTime(0, collision.collisionTime()); - evt.SetEvTimeReso(0, collision.collisionTimeRes()); - evt.SetEvTimeMask(0, collision.collisionTimeMask()); - tof::Response resp = tof::Response(); - resp.SetEventTime(evt); - for (auto const& i : tracks) { - resp.UpdateTrack(i.p(), i.tofExpMom() / tof::Response::kCSPEED, i.length(), i.tofSignal()); - tofpidbeta(resp.GetBeta(), - resp.GetBetaExpectedSigma(), - resp.GetExpectedBeta(PID::Electron), - resp.GetBetaExpectedSigma(), - resp.GetBetaNumberOfSigmas(PID::Electron)); - tofpid( - resp.GetExpectedSignal(PID::Electron), - resp.GetExpectedSignal(PID::Muon), - resp.GetExpectedSignal(PID::Pion), - resp.GetExpectedSignal(PID::Kaon), - resp.GetExpectedSignal(PID::Proton), - resp.GetExpectedSignal(PID::Deuteron), - resp.GetExpectedSignal(PID::Triton), - resp.GetExpectedSignal(PID::Helium3), - resp.GetExpectedSignal(PID::Alpha), - resp.GetExpectedSigma(PID::Electron), - resp.GetExpectedSigma(PID::Muon), - resp.GetExpectedSigma(PID::Pion), - resp.GetExpectedSigma(PID::Kaon), - resp.GetExpectedSigma(PID::Proton), - resp.GetExpectedSigma(PID::Deuteron), - resp.GetExpectedSigma(PID::Triton), - resp.GetExpectedSigma(PID::Helium3), - resp.GetExpectedSigma(PID::Alpha), - resp.GetNumberOfSigmas(PID::Electron), - resp.GetNumberOfSigmas(PID::Muon), - resp.GetNumberOfSigmas(PID::Pion), - resp.GetNumberOfSigmas(PID::Kaon), - resp.GetNumberOfSigmas(PID::Proton), - resp.GetNumberOfSigmas(PID::Deuteron), - resp.GetNumberOfSigmas(PID::Triton), - resp.GetNumberOfSigmas(PID::Helium3), - resp.GetNumberOfSigmas(PID::Alpha)); - } - } -}; - -struct pidTPCTask { - Produces<aod::pidRespTPC> tpcpid; - - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) - { - tpc::Response resp = tpc::Response(); - float bbparams[5] = {0.0320981, 19.9768, 2.52666e-16, 2.72123, 6.08092}; - resp.mParam.mBetheBloch.mParameters.Set(bbparams); - float resoparams[2] = {0.07, 0.0}; - resp.mParam.mRelResolution.mParameters.Set(resoparams); - for (auto const& i : tracks) { - resp.UpdateTrack(i.p(), i.tpcSignal(), i.tpcNClsShared()); - tpcpid( - resp.GetExpectedSignal(PID::Electron), - resp.GetExpectedSignal(PID::Muon), - resp.GetExpectedSignal(PID::Pion), - resp.GetExpectedSignal(PID::Kaon), - resp.GetExpectedSignal(PID::Proton), - resp.GetExpectedSignal(PID::Deuteron), - resp.GetExpectedSignal(PID::Triton), - resp.GetExpectedSignal(PID::Helium3), - resp.GetExpectedSignal(PID::Alpha), - resp.GetExpectedSigma(PID::Electron), - resp.GetExpectedSigma(PID::Muon), - resp.GetExpectedSigma(PID::Pion), - resp.GetExpectedSigma(PID::Kaon), - resp.GetExpectedSigma(PID::Proton), - resp.GetExpectedSigma(PID::Deuteron), - resp.GetExpectedSigma(PID::Triton), - resp.GetExpectedSigma(PID::Helium3), - resp.GetExpectedSigma(PID::Alpha), - resp.GetNumberOfSigmas(PID::Electron), - resp.GetNumberOfSigmas(PID::Muon), - resp.GetNumberOfSigmas(PID::Pion), - resp.GetNumberOfSigmas(PID::Kaon), - resp.GetNumberOfSigmas(PID::Proton), - resp.GetNumberOfSigmas(PID::Deuteron), - resp.GetNumberOfSigmas(PID::Triton), - resp.GetNumberOfSigmas(PID::Helium3), - resp.GetNumberOfSigmas(PID::Alpha)); - } - } -}; - #endif // O2_FRAMEWORK_PIDRESPONSE_H_ diff --git a/Analysis/DataModel/include/PID/PIDTOF.h b/Analysis/DataModel/include/PID/PIDTOF.h index caad4a18bd780..3a69ddd5e850c 100644 --- a/Analysis/DataModel/include/PID/PIDTOF.h +++ b/Analysis/DataModel/include/PID/PIDTOF.h @@ -11,6 +11,8 @@ /// /// \file PIDTOF.h /// \author Nicolo' Jacazio +/// \since 02/07/2020 +/// \brief Implementation of the TOF detector response for PID /// #ifndef O2_FRAMEWORK_PIDTOF_H_ @@ -23,6 +25,7 @@ // O2 includes #include "Framework/Logger.h" #include "ReconstructionDataFormats/PID.h" +#include "PIDBase/DetectorResponse.h" namespace o2::pid::tof { @@ -52,49 +55,20 @@ class EventTime float GetEvTimeReso(float mom) const { return mEvTimeReso[GetMomBin(mom)]; } private: - static const uint mNmomBins = 1; /// Number of momentum bin - static constexpr float mMomBins[mNmomBins + 1] = {0, 100}; /// Momentum bins - float mEvTime[mNmomBins]; /// Evtime (best, T0, T0-TOF, ...) of the event as a function of p - float mEvTimeReso[mNmomBins]; /// Evtime (best, T0, T0-TOF, ...) resolution as a function of p - int mEvTimeMask[mNmomBins]; /// Mask withthe T0 used (0x1=T0-TOF,0x2=T0A,0x3=TOC) for p bins + static const unsigned int mNmomBins = 1; /// Number of momentum bin + static constexpr std::array<float, mNmomBins + 1> mMomBins = {0, 100}; /// Momentum bins + std::array<float, mNmomBins> mEvTime; /// Evtime (best, T0, T0-TOF, ...) of the event as a function of p + std::array<float, mNmomBins> mEvTimeReso; /// Evtime (best, T0, T0-TOF, ...) resolution as a function of p + std::array<int, mNmomBins> mEvTimeMask; /// Mask withthe T0 used (0x1=T0-TOF,0x2=T0A,0x3=TOC) for p bins }; -/// \brief Class to handle the parametrization of the detector response -class Param -{ - public: - Param() = default; - ~Param() = default; - - /// Setter for expected time resolution - void SetTimeResolution(float res) { mSigma = res; } - /// Getter for expected time resolution - float GetTimeResolution() const { return mSigma; } - - // Tracking resolution for expected times - /// Setter for resolution parametrization - void SetTrackParameter(uint ip, float value) { ip < mParDim ? mPar[ip] = value : 0.f; }; - /// Getter for resolution parametrization - float GetTrackParameter(uint ip) { return ip < mParDim ? mPar[ip] : -999.f; }; - - /// Getter for the expected resolution. - /// Returns the expected sigma of the PID signal for the specified - /// particle mass/Z. - /// If the operation is not possible, return a negative value. - double GetExpectedSigma(float mom, float tof, float evtimereso, float massZ) const; - - private: - double mSigma; /// intrinsic TOF resolution - static constexpr uint mParDim = 4; - float mPar[mParDim] = {0.008, 0.008, 0.002, 40.0}; /// parameter for expected time resolutions -}; /// \brief Class to handle the the TOF detector response -class Response +class Response : public DetectorResponse { public: Response() = default; - ~Response() = default; + ~Response() override = default; /// Updater for the TOF response to setup the track parameters /// i.e. sets the track of interest @@ -110,10 +84,6 @@ class Response void SetEventTime(EventTime& evtime) { mEventTime = evtime; }; /// Getter for the event time information in the parametrization EventTime GetEventTime() const { return mEventTime; }; - /// Setter for the resolution parametrization - void SetParam(Param& evtime) { mParam = evtime; }; - /// Getter for the resolution parametrization - Param GetParam() const { return mParam; }; // TOF beta /// Computes the beta of a track given a length, a time measurement and an event time @@ -135,20 +105,19 @@ class Response /// Computes the expected time of a track, given it TOF expected momentum static float ComputeExpectedTime(float tofexpmom, float length, float massZ); /// Gets the expected signal of the track of interest under the PID assumption - float GetExpectedSignal(o2::track::PID::ID id) const { return ComputeExpectedTime(mTOFExpMomentum, mLength, o2::track::PID::getMass2Z(id)); } + float GetExpectedSignal(o2::track::PID::ID id) const override { return ComputeExpectedTime(mTOFExpMomentum, mLength, o2::track::PID::getMass2Z(id)); } // Expected resolution /// Gets the expected resolution of the measurement - float GetExpectedSigma(o2::track::PID::ID id) const { return mParam.GetExpectedSigma(mMomentum, mTOFSignal, mEventTime.GetEvTimeReso(mMomentum), o2::track::PID::getMass2Z(id)); } + float GetExpectedSigma(o2::track::PID::ID id) const override; // Nsigma - float GetNumberOfSigmas(o2::track::PID::ID id) const { return (mTOFSignal - mEventTime.GetEvTime(mMomentum) - GetExpectedSignal(id)) / GetExpectedSigma(id); } + float GetSeparation(o2::track::PID::ID id) const override { return (mTOFSignal - mEventTime.GetEvTime(mMomentum) - GetExpectedSignal(id)) / GetExpectedSigma(id); } - // double GetMismatchProbability(double time, double eta) const; + // float GetMismatchProbability(float time, float eta) const; // Utility values static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; /// Speed of light in TOF units (cm/ps) private: - Param mParam; /// Parametrization of the TOF signal // Event of interest information EventTime mEventTime; /// Event time object // Track of interest information diff --git a/Analysis/DataModel/include/PID/PIDTPC.h b/Analysis/DataModel/include/PID/PIDTPC.h index 87cde9af0aa19..a28954fb9971a 100644 --- a/Analysis/DataModel/include/PID/PIDTPC.h +++ b/Analysis/DataModel/include/PID/PIDTPC.h @@ -12,7 +12,7 @@ /// \file PIDTPC.h /// \author Nicolo' Jacazio /// \since 2020-07-24 -/// \brief Handler for the TPC PID response +/// \brief Implementation of the TPC detector response for PID /// #ifndef O2_FRAMEWORK_PIDTPC_H_ @@ -25,73 +25,33 @@ // O2 includes #include "Framework/Logger.h" #include "ReconstructionDataFormats/PID.h" -#include "PID/ParamBase.h" +#include "PIDBase/DetectorResponse.h" namespace o2::pid::tpc { -float BetheBlochF(float x, const std::array<float, 5> p); -float RelResolutionF(float x, const std::array<float, 2> p); - -/// \brief Class to handle the parametrization of the detector response -class Param -{ - public: - Param() = default; - ~Param() = default; - - /// Getter for the expected signal - /// Calculates the expected PID signal as the function of - /// the information stored in the track and the given parameters, - /// for the specified particle type - float GetExpectedSignal(float mom, float mass, float charge) const; - - /// Getter for the charge factor BB goes with z^2, however in reality it is slightly larger (calibration, threshold effects, ...) - float GetChargeFactor(float charge) const { return TMath::Power(charge, 2.3); } - - /// Getter for the expected resolution. - /// Returns the expected sigma of the PID signal. - /// If the operation is not possible, return a negative value. - float GetExpectedSigma(float npoints, float tpcsignal) const; - - /// Bethe-Bloch function normalised to 1 at the minimum - Parametrization<float, 5, BetheBlochF> mBetheBloch = Parametrization<float, 5, BetheBlochF>(); - - /// Parametrization of the resolution - Parametrization<float, 2, RelResolutionF> mRelResolution = Parametrization<float, 2, RelResolutionF>(); - - float mMIP = 50.f; // dEdx for MIP - private: -}; - /// \brief Class to handle the the TPC detector response -class Response +class Response : public DetectorResponse { public: Response() = default; - ~Response() = default; + ~Response() override = default; /// Updater for the TPC response to setup the track parameters /// i.e. sets the track of interest - void UpdateTrack(float mom, float tpcsignal, float tpcpoints) - { - mMomentum = mom; - mTPCSignal = tpcsignal; - mTPCPoints = tpcpoints; - }; + void UpdateTrack(float mom, float tpcsignal, float tpcpoints); // Expected resolution /// Gets the expected resolution of the measurement - float GetExpectedSigma(o2::track::PID::ID id) const { return mParam.GetExpectedSigma(mTPCSignal, mTPCPoints); } + float GetExpectedSigma(o2::track::PID::ID id) const override; // Expected signal /// Gets the expected signal of the measurement - float GetExpectedSignal(o2::track::PID::ID id) const { return mParam.GetExpectedSignal(mMomentum, o2::track::PID::getMass(id), o2::track::PID::getCharge(id)); } + float GetExpectedSignal(o2::track::PID::ID id) const override; // Nsigma - float GetNumberOfSigmas(o2::track::PID::ID id) const { return (mTPCSignal - GetExpectedSignal(id)) / GetExpectedSigma(id); } + float GetSeparation(o2::track::PID::ID id) const override { return (mTPCSignal - GetExpectedSignal(id)) / GetExpectedSigma(id); } - Param mParam; /// Parametrization of the TPC signal private: // Event of interest information // Track of interest information diff --git a/Analysis/DataModel/include/PID/ParamBase.h b/Analysis/DataModel/include/PID/ParamBase.h deleted file mode 100644 index 52275a3b85d7a..0000000000000 --- a/Analysis/DataModel/include/PID/ParamBase.h +++ /dev/null @@ -1,71 +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. - -/// -/// \file ParamBase.h -/// \author Nicolo' Jacazio -/// -/// Set of utilities to handle the parametrization of the PID response for each detector -/// These are the basic storage elements to be kept in the CCDB -/// - -#ifndef O2_FRAMEWORK_PARAMBASE_H_ -#define O2_FRAMEWORK_PARAMBASE_H_ - -// ROOT includes -#include "Rtypes.h" - -namespace o2::pid -{ - -/// \brief Class to handle the parameters of a given detector response -template <typename T, unsigned int size> -class Parameters -{ - public: - Parameters() = default; - ~Parameters() = default; - - /// Setter for parametrization parameters - void Set(unsigned int param_index, T value) { param_index < size ? mPar[param_index] = value : 0.f; } - /// Setter for parametrization parameters - void Set(T const value[size]) - { - for (unsigned int i = 0; i < size; i++) - Set(i, value[i]); - } - /// Getter for parametrization parameters - T Get(unsigned int param_index) const { return param_index < size ? mPar[param_index] : -999.f; } - /// Getter for parametrization parameters - std::array<T, size> Get() const { return mPar; } - - private: - /// parameters - std::array<T, size> mPar; -}; - -/// \brief Class to handle the parameters and the parametrization of a given detector response -template <typename T, unsigned int size, T (*functional_form)(T, const std::array<T, size>)> -class Parametrization -{ - public: - Parametrization() = default; - ~Parametrization() = default; - - /// Getter for parametrization values - T GetValue(T x) const { return functional_form(x, mParameters.Get()); } - - /// Parameters of the parametrization - Parameters<T, size> mParameters = Parameters<T, size>(); -}; - -} // namespace o2::pid - -#endif // O2_FRAMEWORK_PARAMBASE_H_ diff --git a/Analysis/DataModel/include/PID/TOFReso.h b/Analysis/DataModel/include/PID/TOFReso.h new file mode 100644 index 0000000000000..411081f123df4 --- /dev/null +++ b/Analysis/DataModel/include/PID/TOFReso.h @@ -0,0 +1,51 @@ +// 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 TOFReso.h +/// \author Nicolo' Jacazio +/// \since 07/08/2020 +/// \brief Implementation for the TOF PID response of the expected times resolution +/// + +#ifndef O2_ANALYSIS_PID_TOFRESO_H_ +#define O2_ANALYSIS_PID_TOFRESO_H_ + +// Root includes +#include "TMath.h" +// O2 includes +#include "PIDBase/ParamBase.h" + +namespace o2::pid::tof +{ + +class TOFReso : public Parametrization +{ + public: + TOFReso() : Parametrization("TOFReso", 5) { Printf("%s", fName.Data()); }; + ~TOFReso() override = default; + float operator()(const float* x) const override + { + const float mom = abs(x[0]); + if (mom <= 0) + return -999; + const float time = x[1]; + const float evtimereso = x[2]; + const float mass = x[3]; + const float dpp = mParameters[0] + mParameters[1] * mom + mParameters[2] * mass / mom; // mean relative pt resolution; + const float sigma = dpp * time / (1. + mom * mom / (mass * mass)); + return TMath::Sqrt(sigma * sigma + mParameters[3] * mParameters[3] / mom / mom + mParameters[4] * mParameters[4] + evtimereso * evtimereso); + } + ClassDef(TOFReso, 1); +}; + +} // namespace o2::pid::tof + +#endif diff --git a/Analysis/DataModel/include/PID/TPCReso.h b/Analysis/DataModel/include/PID/TPCReso.h new file mode 100644 index 0000000000000..93925bdf4a356 --- /dev/null +++ b/Analysis/DataModel/include/PID/TPCReso.h @@ -0,0 +1,41 @@ +// 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 TPCReso.h +/// \author Nicolo' Jacazio +/// \since 07/08/2020 +/// \brief Implementation for the TPC PID response of the BB resolution +/// + +#ifndef O2_ANALYSIS_PID_TPCRESO_H_ +#define O2_ANALYSIS_PID_TPCRESO_H_ + +#include "PIDBase/ParamBase.h" + +namespace o2::pid::tpc +{ + +class TPCReso : public Parametrization +{ + public: + TPCReso() : Parametrization("TPCReso", 2) { Printf("%s", fName.Data()); }; + ~TPCReso() override = default; + float operator()(const float* x) const override + { + // relative dEdx resolution rel sigma = fRes0*sqrt(1+fResN2/npoint) + return x[0] * mParameters[0] * (x[1] > 0 ? sqrt(1. + mParameters[1] / x[1]) : 1.f); + } + ClassDef(TPCReso, 1); +}; + +} // namespace o2::pid::tpc + +#endif diff --git a/Analysis/DataModel/include/PIDBase/DetectorResponse.h b/Analysis/DataModel/include/PIDBase/DetectorResponse.h new file mode 100644 index 0000000000000..856c6e2231ba5 --- /dev/null +++ b/Analysis/DataModel/include/PIDBase/DetectorResponse.h @@ -0,0 +1,92 @@ +// 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 DetectorResponse.h +/// \author Nicolo' Jacazio +/// \since 2020-07-30 +/// \brief Handler for any detector (or other entity) response. +/// This provides the basic quantities computed by any response i.e. expected values, resolutions and Nsigmas +/// + +#ifndef O2_ANALYSIS_PID_DETECTORRESPONSE_H_ +#define O2_ANALYSIS_PID_DETECTORRESPONSE_H_ + +// ROOT includes +#include "Rtypes.h" +#include "TMath.h" + +// O2 includes +#include "ReconstructionDataFormats/PID.h" +#include "PIDBase/ParamBase.h" + +namespace o2::pid +{ +/// \brief Class to handle the general detector response +class DetectorResponse +{ + public: + DetectorResponse() = default; + virtual ~DetectorResponse() = default; + + /// Enumeration of the different types of parametrizations + enum Param_t { kSignal, + kSigma, + kNParams }; + + static const std::array<TString, kNParams> ParamName; + + /// Getter for the expected resolution, purely virtual and reimplemented in derived classes + /// @param id particle index to compute the expected sigma + /// @return Returns the expected resolution for the hypothesis id + virtual pidvar_t GetExpectedSigma(o2::track::PID::ID id) const = 0; + + /// Getter for the expected signal, purely virtual and reimplemented in derived classes + /// @param id particle index to compute the expected signal + /// @return Returns the expected signal for the hypothesis id + virtual pidvar_t GetExpectedSignal(o2::track::PID::ID id) const = 0; + + /// Getter for the expected discriminating value, can be Nsigmas, probabilities or whatever, purely virtual and reimplemented in derived classes + /// @param id particle index to compute the separation + /// @return Returns the discriminating value for the hypothesis id + virtual pidvar_t GetSeparation(o2::track::PID::ID id) const = 0; + + /// Setter for the parametrization from input TFile + /// \param fname File name used for input + /// \param pname Name of the parametrization in the file + /// \param ptype Type of the parametrization + void LoadParamFromFile(const TString fname, const TString pname, const Param_t ptype); + + /// Setter for the parametrization + /// \param ptype Type of the parametrization + /// \param param Parametrization + void LoadParam(const Param_t ptype, Parametrization* param) { mParam[ptype] = param; } + + /// Getter for the parametrizations + Parametrization* GetParam(const Param_t ptype) const { return mParam[ptype]; } + + /// Setter for the parametrizations parameters, if the parametrization is not yet initialized a new parametrization is created without any implementation and just parameters + /// \param ptype parametrization type + /// \param p vector with parameters + void SetParameters(const Param_t ptype, std::vector<pidvar_t> p); + + /// Getter for the value of the parametrization + /// \param ptype parametrization type + /// \param x array with parameters + virtual pidvar_t operator()(const Param_t ptype, const pidvar_t* x) const { return mParam[ptype]->operator()(x); } + + private: + /// Parametrizations for the expected signal and sigma + std::array<Parametrization*, kNParams> mParam; +}; + +} // namespace o2::pid + +#endif // O2_ANALYSIS_PID_DETECTORRESPONSE_H_ diff --git a/Analysis/DataModel/include/PIDBase/ParamBase.h b/Analysis/DataModel/include/PIDBase/ParamBase.h new file mode 100644 index 0000000000000..111f26079c9d5 --- /dev/null +++ b/Analysis/DataModel/include/PIDBase/ParamBase.h @@ -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. + +/// +/// \file ParamBase.h +/// \author Nicolo' Jacazio +/// +/// \brief Set of utilities to handle the parametrization of the PID response for each detector +/// These are the basic storage elements to be kept in the CCDB +/// + +#ifndef O2_FRAMEWORK_PARAMBASE_H_ +#define O2_FRAMEWORK_PARAMBASE_H_ + +// ROOT includes +#include "TNamed.h" + +namespace o2::pid +{ +/// Variable to use for the pid input/output i.e. float, double et cetera +using pidvar_t = float; + +/// \brief Class to handle the parameters of a given detector response +class Parameters : public TObject +{ + public: + /// Default constructor + Parameters() = default; + + /// Parametric constructor + /// \param npar Number of parameters in the container + Parameters(unsigned int npar) : mPar(std::vector<pidvar_t>(npar)){}; + + /// Parametric constructor + /// \param params Parameters to initialize the container + Parameters(const std::vector<pidvar_t> params) : mPar{} { SetParameters(params); }; + + /// Default destructor + ~Parameters() override = default; + + /// Setter for the parameter at position iparam + /// \param iparam index in the array of the parameters + /// \param value value of the parameter at position iparam + void SetParameter(const unsigned int iparam, const pidvar_t value) { mPar[iparam] = value; } + + /// Setter for the parameter, using an array + /// \param param array with parameters + void SetParameters(const pidvar_t* params) { std::copy(params, params + mPar.size(), mPar.begin()); } + + /// Setter for the parameter, using an array + /// \param params array with parameters + void SetParameters(const std::vector<pidvar_t> params); + + /// Printer of the parameter values + void PrintParameters() const; + + /// Getter for the parameters + /// \return returns an array of parameters + const pidvar_t* GetParameters() const { return mPar.data(); } + + /// Getter for the size of the parameter + /// \return returns the size of the parameter array + unsigned int size() const { return mPar.size(); } + + /// Getter of the parameter at position i + /// \param i index of the parameter to get + /// \return returns the parameter value at position i + pidvar_t operator[](unsigned int i) const { return mPar[i]; } + + private: + /// Vector of the parameter + std::vector<pidvar_t> mPar; + + ClassDef(Parameters, 1); // Container for parameter of parametrizations +}; + +/// \brief Class to handle the parameters and the parametrization of a given detector response +class Parametrization : public TNamed +{ + public: + /// Default constructor + Parametrization() : TNamed("DefaultParametrization", "DefaultParametrization"), mParameters{0} {}; + + /// Parametric constructor + /// \param name Name (and title) of the parametrization + /// \param size Number of parameters of the parametrization + Parametrization(TString name, unsigned int size) : TNamed(name, name), mParameters{size} {}; + + /// Parametric constructor + /// \param name Name (and title) of the parametrization + /// \param params Parameters of the parametrization + Parametrization(TString name, const std::vector<pidvar_t> params) : TNamed(name, name), mParameters{params} {}; + + /// Default destructor + ~Parametrization() override = default; + + /// Getter for parametrization values, to be reimplemented in the custom parametrization of the user + /// \param x array of variables to use in order to compute the return value + virtual pidvar_t operator()(const pidvar_t* x) const; + + /// Printer for parameters + void PrintParametrization() const; + + /// Setter for the parameter, using an array + /// \param params array with parameters + void SetParameters(const std::vector<pidvar_t> params) { mParameters.SetParameters(params); } + + /// Getter for the parameters + Parameters GetParameters() const { return mParameters; } + + protected: + /// Parameters of the parametrization + Parameters mParameters; + + ClassDef(Parametrization, 1); // Container for the parametrization of the response function +}; + +} // namespace o2::pid + +#endif // O2_FRAMEWORK_PARAMBASE_H_ diff --git a/Analysis/DataModel/src/AnalysisDataModelLinkDef.h b/Analysis/DataModel/src/AnalysisDataModelLinkDef.h new file mode 100644 index 0000000000000..5db890293367e --- /dev/null +++ b/Analysis/DataModel/src/AnalysisDataModelLinkDef.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. + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::pid::Parameters + ; +#pragma link C++ class o2::pid::Parametrization + ; + +#pragma link C++ class o2::pid::tof::TOFReso + ; + +#pragma link C++ class o2::pid::tpc::BetheBloch + ; +#pragma link C++ class o2::pid::tpc::TPCReso + ; diff --git a/Analysis/DataModel/src/DetectorResponse.cxx b/Analysis/DataModel/src/DetectorResponse.cxx new file mode 100644 index 0000000000000..0ddb305ae65dc --- /dev/null +++ b/Analysis/DataModel/src/DetectorResponse.cxx @@ -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 ParamBase.cxx +/// \author Nicolo' Jacazio +/// \since 07/08/2020 +/// \brief Set of utilities to handle the parametrization of the PID response for each detector +/// These are the basic storage elements to be kept in the CCDB +/// + +// Root includes +#include "TFile.h" + +// O2 includes +#include "PIDBase/ParamBase.h" +#include "PIDBase/DetectorResponse.h" +#include "Framework/Logger.h" + +namespace o2::pid +{ + +const std::array<TString, DetectorResponse::kNParams> DetectorResponse::ParamName = {{"Signal", "Sigma"}}; + +void DetectorResponse::LoadParamFromFile(const TString fname, const TString pname, const Param_t ptype) +{ + TFile f(fname, "READ"); + if (!f.Get(pname)) { + LOG(fatal) << "Did not find parametrization " << pname << " in file " << fname; + } + LOG(info) << "Loading parametrization " << pname << " from TFile " << fname; + f.GetObject(pname, mParam[ptype]); + f.Close(); + mParam[ptype]->Print(); + mParam[ptype]->PrintParametrization(); +} + +void DetectorResponse::SetParameters(const Param_t ptype, std::vector<pidvar_t> p) +{ + if (!mParam[ptype]) { + const TString pname = ParamName[ptype] + "_default_param"; + LOG(info) << "Creating new parametrization " << pname << " of size " << p.size(); + mParam[ptype] = new Parametrization(pname, p.size()); + mParam[ptype]->Print(); + } + mParam[ptype]->SetParameters(p); +} + +} // namespace o2::pid \ No newline at end of file diff --git a/Analysis/DataModel/src/PIDTOF.cxx b/Analysis/DataModel/src/PIDTOF.cxx index c22fbccaeb164..a56d4603f7fac 100644 --- a/Analysis/DataModel/src/PIDTOF.cxx +++ b/Analysis/DataModel/src/PIDTOF.cxx @@ -22,17 +22,6 @@ uint EventTime::GetMomBin(float mom) const return mNmomBins - 1; } -//_________________________________________________________________________ -double Param::GetExpectedSigma(float mom, float time, float evtimereso, float mass) const -{ - mom = abs(mom); - if (mom <= 0) - return -999; - double dpp = mPar[0] + mPar[1] * mom + mPar[2] * mass / mom; //mean relative pt resolution; - double sigma = dpp * time / (1. + mom * mom / (mass * mass)); - return TMath::Sqrt(sigma * sigma + mPar[3] * mPar[3] / mom / mom + mSigma * mSigma + evtimereso * evtimereso); -} - //_________________________________________________________________________ float Response::ComputeExpectedTime(float tofexpmom, float length, float massZ) { @@ -64,4 +53,11 @@ float Response::GetExpectedBeta(float mom, float mass) return 0; } +//_________________________________________________________________________ +float Response::GetExpectedSigma(o2::track::PID::ID id) const +{ + const float x[4] = {mMomentum, mTOFSignal, mEventTime.GetEvTimeReso(mMomentum), o2::track::PID::getMass2Z(id)}; + return this->operator()(kSigma, x); +} + } // namespace o2::pid::tof diff --git a/Analysis/DataModel/src/PIDTPC.cxx b/Analysis/DataModel/src/PIDTPC.cxx index 31b8bd3ed5b5a..f36eebed232c9 100644 --- a/Analysis/DataModel/src/PIDTPC.cxx +++ b/Analysis/DataModel/src/PIDTPC.cxx @@ -9,31 +9,27 @@ // or submit itself to any jurisdiction. #include "PID/PIDTPC.h" -#include "TPCSimulation/Detector.h" namespace o2::pid::tpc { -float BetheBlochF(float betagamma, const std::array<float, 5> p) +void Response::UpdateTrack(float mom, float tpcsignal, float tpcpoints) { - // Parameters of the ALEPH Bethe-Bloch formula - return o2::tpc::Detector::BetheBlochAleph(betagamma, p[0], p[1], p[2], p[3], p[4]); -} - -float RelResolutionF(float npoints, const std::array<float, 2> p) -{ - // relative dEdx resolution rel sigma = fRes0*sqrt(1+fResN2/npoint) - return p[0] * (npoints > 0 ? sqrt(1. + p[1] / npoints) : 1.f); -} + mMomentum = mom; + mTPCSignal = tpcsignal; + mTPCPoints = tpcpoints; +}; -float Param::GetExpectedSignal(float mom, float mass, float charge) const +float Response::GetExpectedSignal(o2::track::PID::ID id) const { - return mBetheBloch.GetValue(mom / mass) * mMIP * GetChargeFactor(charge); + const float x[2] = {mMomentum / o2::track::PID::getMass(id), (float)o2::track::PID::getCharge(id)}; + return this->operator()(kSignal, x); } -float Param::GetExpectedSigma(float npoints, float tpcsignal) const +float Response::GetExpectedSigma(o2::track::PID::ID id) const { - return tpcsignal * mRelResolution.GetValue(npoints); + const float x[2] = {mTPCSignal, mTPCPoints}; + return this->operator()(kSigma, x); } } // namespace o2::pid::tpc diff --git a/Analysis/DataModel/src/ParamBase.cxx b/Analysis/DataModel/src/ParamBase.cxx new file mode 100644 index 0000000000000..a4267eedfcd87 --- /dev/null +++ b/Analysis/DataModel/src/ParamBase.cxx @@ -0,0 +1,52 @@ +// 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 ParamBase.cxx +/// \author Nicolo' Jacazio +/// \since 07/08/2020 +/// \brief Set of utilities to handle the parametrization of the PID response for each detector +/// These are the basic storage elements to be kept in the CCDB +/// + +#include "PIDBase/ParamBase.h" +#include "Framework/Logger.h" + +namespace o2::pid +{ + +void Parameters::SetParameters(const std::vector<pidvar_t> params) +{ + if (mPar.size() != params.size()) { + LOG(fatal) << "Updating parametrization size!"; + } + mPar.assign(params.begin(), params.end()); +} + +void Parameters::PrintParameters() const +{ + for (unsigned int i = 0; i < size(); i++) { + LOG(info) << "Parameter " << i << "/" << size() - 1 << " is " << mPar[i]; + } +}; + +pidvar_t Parametrization::operator()(const pidvar_t* x) const +{ + LOG(fatal) << "Parametrization " << fName << " is not implemented!"; + return -999.999f; +} + +void Parametrization::PrintParametrization() const +{ + LOG(info) << "Parametrization " << fName; + mParameters.PrintParameters(); +}; + +} // namespace o2::pid \ No newline at end of file diff --git a/Analysis/DataModel/src/handleParamTOFReso.cxx b/Analysis/DataModel/src/handleParamTOFReso.cxx new file mode 100644 index 0000000000000..e7ca0b6b7dcc2 --- /dev/null +++ b/Analysis/DataModel/src/handleParamTOFReso.cxx @@ -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. + +/// +/// \file handleParamTOFBetheBloch.cxx +/// \author Nicolo' Jacazio +/// \since 2020-06-22 +/// \brief A simple tool to produce Bethe Bloch parametrization objects for the TOF PID Response +/// + +#include "CCDB/CcdbApi.h" +#include <boost/program_options.hpp> +#include <FairLogger.h> +#include "TFile.h" +#include "PID/TOFReso.h" + +using namespace o2::pid::tof; +namespace bpo = boost::program_options; + +bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv[], bpo::variables_map& vm) +{ + options.add_options()( + "url,u", bpo::value<std::string>()->default_value("http://ccdb-test.cern.ch:8080"), "URL of the CCDB database")( + "start,s", bpo::value<long>()->default_value(0), "Start timestamp of object validity")( + "stop,S", bpo::value<long>()->default_value(4108971600000), "Stop timestamp of object validity")( + "delete_previous,d", bpo::value<int>()->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")( + "file,f", bpo::value<std::string>()->default_value(""), "Option to save parametrization to file instead of uploading to ccdb")( + "mode,m", bpo::value<unsigned int>()->default_value(0), "Working mode: 0 push 1 pull and test")( + "verbose,v", bpo::value<int>()->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; + } + + const unsigned int mode = vm["mode"].as<unsigned int>(); + const std::string path = "Analysis/PID/TOF"; + std::map<std::string, std::string> metadata; + std::map<std::string, std::string>* headers; + o2::ccdb::CcdbApi api; + const std::string url = vm["url"].as<std::string>(); + api.init(url); + if (!api.isHostReachable()) { + LOG(WARNING) << "CCDB host " << url << " is not reacheable, cannot go forward"; + return 1; + } + if (mode == 0) { // Push mode + const std::vector<float> resoparams = {0.008, 0.008, 0.002, 40.0, 60.f}; + TOFReso reso; + reso.SetParameters(resoparams); + const std::string fname = vm["file"].as<std::string>(); + if (!fname.empty()) { // Saving it to file + TFile f(fname.data(), "RECREATE"); + reso.Write(); + f.ls(); + f.Close(); + } else { // Saving it to CCDB + + long start = vm["start"].as<long>(); + long stop = vm["stop"].as<long>(); + + if (vm["delete_previous"].as<int>()) { + api.truncate(path); + } + api.storeAsTFileAny(&reso, path + "/TOFReso", metadata, start, stop); + } + } else { // Pull and test mode + const float x[2] = {1, 1}; + TOFReso* reso = api.retrieveFromTFileAny<TOFReso>(path + "/TOFReso", metadata, -1, headers); + reso->PrintParametrization(); + LOG(INFO) << "TOFReso " << reso->operator()(x); + } + + return 0; +} diff --git a/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx b/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx new file mode 100644 index 0000000000000..4fbf9a533be05 --- /dev/null +++ b/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx @@ -0,0 +1,113 @@ +// 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 handleParamTPCBetheBloch.cxx +/// \author Nicolo' Jacazio +/// \since 2020-06-22 +/// \brief A simple tool to produce Bethe Bloch parametrization objects for the TPC PID Response +/// + +#include "CCDB/CcdbApi.h" +#include <boost/program_options.hpp> +#include <FairLogger.h> +#include "TFile.h" +#include "PID/BetheBloch.h" +#include "PID/TPCReso.h" + +using namespace o2::pid::tpc; +namespace bpo = boost::program_options; + +bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv[], bpo::variables_map& vm) +{ + options.add_options()( + "url,u", bpo::value<std::string>()->default_value("http://ccdb-test.cern.ch:8080"), "URL of the CCDB database")( + "start,s", bpo::value<long>()->default_value(0), "Start timestamp of object validity")( + "stop,S", bpo::value<long>()->default_value(4108971600000), "Stop timestamp of object validity")( + "delete_previous,d", bpo::value<int>()->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")( + "file,f", bpo::value<std::string>()->default_value(""), "Option to save parametrization to file instead of uploading to ccdb")( + "mode,m", bpo::value<unsigned int>()->default_value(0), "Working mode: 0 push 1 pull and test")( + "verbose,v", bpo::value<int>()->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; + } + + const unsigned int mode = vm["mode"].as<unsigned int>(); + const std::string path = "Analysis/PID/TPC"; + std::map<std::string, std::string> metadata; + std::map<std::string, std::string>* headers; + o2::ccdb::CcdbApi api; + const std::string url = vm["url"].as<std::string>(); + api.init(url); + if (!api.isHostReachable()) { + LOG(WARNING) << "CCDB host " << url << " is not reacheable, cannot go forward"; + return 1; + } + if (mode == 0) { // Push mode + const std::vector<float> bbparams = {0.0320981, 19.9768, 2.52666e-16, 2.72123, 6.08092, 50.f, 2.3}; + const std::vector<float> resoparams = {0.07, 0.0}; + BetheBloch tpc; + tpc.SetParameters(bbparams); + TPCReso reso; + reso.SetParameters(resoparams); + const std::string fname = vm["file"].as<std::string>(); + if (!fname.empty()) { // Saving it to file + TFile f(fname.data(), "RECREATE"); + tpc.Write(); + reso.Write(); + f.ls(); + f.Close(); + } else { // Saving it to CCDB + + long start = vm["start"].as<long>(); + long stop = vm["stop"].as<long>(); + + if (vm["delete_previous"].as<int>()) { + api.truncate(path); + } + api.storeAsTFileAny(&tpc, path + "/BetheBloch", metadata, start, stop); + api.storeAsTFileAny(&reso, path + "/TPCReso", metadata, start, stop); + } + } else { // Pull and test mode + const float x[2] = {1, 1}; + BetheBloch* tpc = api.retrieveFromTFileAny<BetheBloch>(path + "/BetheBloch", metadata, -1, headers); + tpc->PrintParametrization(); + LOG(INFO) << "BetheBloch " << tpc->operator()(x); + TPCReso* reso = api.retrieveFromTFileAny<TPCReso>(path + "/TPCReso", metadata, -1, headers); + reso->PrintParametrization(); + LOG(INFO) << "TPCReso " << reso->operator()(x); + } + + return 0; +} diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 4b7a54b554d4c..dd58f52c61992 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -58,6 +58,16 @@ o2_add_dpl_workflow(spectra-tpc PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) +o2_add_dpl_workflow(pid-tof + SOURCES pidTOF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(pid-tpc + SOURCES pidTPC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(validation SOURCES validation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx new file mode 100644 index 0000000000000..27e47469b15dc --- /dev/null +++ b/Analysis/Tasks/pidTOF.cxx @@ -0,0 +1,106 @@ +// 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 includes +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" +#include <CCDB/BasicCCDBManager.h> + +using namespace o2; +using namespace o2::framework; +using namespace o2::pid; +using namespace o2::framework::expressions; +using namespace o2::track; + +struct pidTOFTask { + Produces<aod::pidRespTOF> tofpid; + Produces<aod::pidRespTOFbeta> tofpidbeta; + tof::Response resp = tof::Response(); + Service<o2::ccdb::BasicCCDBManager> ccdb; + Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; + Configurable<std::string> sigmaname{"param-sigma", "TOFReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"}; + Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable<long> timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(url.value); + ccdb->setTimestamp(timestamp.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now objects + ccdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()); + // + const std::vector<float> p = {0.008, 0.008, 0.002, 40.0}; + resp.SetParameters(DetectorResponse::kSigma, p); + const std::string fname = paramfile.value; + if (!fname.empty()) { // Loading the parametrization from file + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); + } else { // Loading it from CCDB + const std::string path = "Analysis/PID/TOF"; + resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); + } + } + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) + { + LOGF(info, "Tracks for collision: %d", tracks.size()); + tof::EventTime evt = tof::EventTime(); + evt.SetEvTime(0, collision.collisionTime()); + evt.SetEvTimeReso(0, collision.collisionTimeRes()); + evt.SetEvTimeMask(0, collision.collisionTimeMask()); + resp.SetEventTime(evt); + for (auto const& i : tracks) { + resp.UpdateTrack(i.p(), i.tofExpMom() / tof::Response::kCSPEED, i.length(), i.tofSignal()); + tofpidbeta(resp.GetBeta(), + resp.GetBetaExpectedSigma(), + resp.GetExpectedBeta(PID::Electron), + resp.GetBetaExpectedSigma(), + resp.GetBetaNumberOfSigmas(PID::Electron)); + tofpid( + resp.GetExpectedSignal(PID::Electron), + resp.GetExpectedSignal(PID::Muon), + resp.GetExpectedSignal(PID::Pion), + resp.GetExpectedSignal(PID::Kaon), + resp.GetExpectedSignal(PID::Proton), + resp.GetExpectedSignal(PID::Deuteron), + resp.GetExpectedSignal(PID::Triton), + resp.GetExpectedSignal(PID::Helium3), + resp.GetExpectedSignal(PID::Alpha), + resp.GetExpectedSigma(PID::Electron), + resp.GetExpectedSigma(PID::Muon), + resp.GetExpectedSigma(PID::Pion), + resp.GetExpectedSigma(PID::Kaon), + resp.GetExpectedSigma(PID::Proton), + resp.GetExpectedSigma(PID::Deuteron), + resp.GetExpectedSigma(PID::Triton), + resp.GetExpectedSigma(PID::Helium3), + resp.GetExpectedSigma(PID::Alpha), + resp.GetSeparation(PID::Electron), + resp.GetSeparation(PID::Muon), + resp.GetSeparation(PID::Pion), + resp.GetSeparation(PID::Kaon), + resp.GetSeparation(PID::Proton), + resp.GetSeparation(PID::Deuteron), + resp.GetSeparation(PID::Triton), + resp.GetSeparation(PID::Helium3), + resp.GetSeparation(PID::Alpha)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{adaptAnalysisTask<pidTOFTask>("pidTOF-task")}; +} diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx new file mode 100644 index 0000000000000..af8baff6349d7 --- /dev/null +++ b/Analysis/Tasks/pidTPC.cxx @@ -0,0 +1,95 @@ +// 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 includes +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" +#include <CCDB/BasicCCDBManager.h> + +using namespace o2; +using namespace o2::framework; +using namespace o2::pid; +using namespace o2::framework::expressions; +using namespace o2::track; + +struct pidTPCTask { + Produces<aod::pidRespTPC> tpcpid; + tpc::Response resp = tpc::Response(); + Service<o2::ccdb::BasicCCDBManager> ccdb; + Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; + Configurable<std::string> signalname{"param-signal", "BetheBloch", "Name of the parametrization for the expected signal, used in both file and CCDB mode"}; + Configurable<std::string> sigmaname{"param-sigma", "TPCReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"}; + Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable<long> timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(url.value); + ccdb->setTimestamp(timestamp.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now objects + ccdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()); + // + const std::string fname = paramfile.value; + if (!fname.empty()) { // Loading the parametrization from file + resp.LoadParamFromFile(fname.data(), signalname.value, DetectorResponse::kSignal); + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); + } else { // Loading it from CCDB + const std::string path = "Analysis/PID/TPC"; + resp.LoadParam(DetectorResponse::kSignal, ccdb->getForTimeStamp<Parametrization>(path + "/" + signalname.value, timestamp.value)); + resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); + } + } + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) + { + for (auto const& i : tracks) { + resp.UpdateTrack(i.tpcInnerParam(), i.tpcSignal(), i.tpcNClsShared()); + tpcpid( + resp.GetExpectedSignal(PID::Electron), + resp.GetExpectedSignal(PID::Muon), + resp.GetExpectedSignal(PID::Pion), + resp.GetExpectedSignal(PID::Kaon), + resp.GetExpectedSignal(PID::Proton), + resp.GetExpectedSignal(PID::Deuteron), + resp.GetExpectedSignal(PID::Triton), + resp.GetExpectedSignal(PID::Helium3), + resp.GetExpectedSignal(PID::Alpha), + resp.GetExpectedSigma(PID::Electron), + resp.GetExpectedSigma(PID::Muon), + resp.GetExpectedSigma(PID::Pion), + resp.GetExpectedSigma(PID::Kaon), + resp.GetExpectedSigma(PID::Proton), + resp.GetExpectedSigma(PID::Deuteron), + resp.GetExpectedSigma(PID::Triton), + resp.GetExpectedSigma(PID::Helium3), + resp.GetExpectedSigma(PID::Alpha), + resp.GetSeparation(PID::Electron), + resp.GetSeparation(PID::Muon), + resp.GetSeparation(PID::Pion), + resp.GetSeparation(PID::Kaon), + resp.GetSeparation(PID::Proton), + resp.GetSeparation(PID::Deuteron), + resp.GetSeparation(PID::Triton), + resp.GetSeparation(PID::Helium3), + resp.GetSeparation(PID::Alpha)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{adaptAnalysisTask<pidTPCTask>("pidTPC-task")}; +} diff --git a/Analysis/Tasks/spectraTOF.cxx b/Analysis/Tasks/spectraTOF.cxx index fe3b8740c1b7d..f82db52eba3dd 100644 --- a/Analysis/Tasks/spectraTOF.cxx +++ b/Analysis/Tasks/spectraTOF.cxx @@ -148,7 +148,6 @@ struct SpectraTask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<pidTOFTask>("pidTOF-task"), adaptAnalysisTask<TOFPIDQATask>("tofpidqa-task"), adaptAnalysisTask<SpectraTask>("filterEl-task")}; } diff --git a/Analysis/Tasks/spectraTPC.cxx b/Analysis/Tasks/spectraTPC.cxx index 6b22011eb4a5b..0657c25a6ae33 100644 --- a/Analysis/Tasks/spectraTPC.cxx +++ b/Analysis/Tasks/spectraTPC.cxx @@ -28,11 +28,49 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct TPCPIDQATask { +struct TPCPIDQAExpSignalTask { +#define BIN_AXIS 100, 0, 5, 1000, 0, 1000 + + DOTH2F(htpcsignal, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(hexpEl, ";#it{p} (GeV/#it{c});TPC expected signal e;Tracks", BIN_AXIS); + DOTH2F(hexpMu, ";#it{p} (GeV/#it{c});TPC expected signal #mu;Tracks", BIN_AXIS); + DOTH2F(hexpPi, ";#it{p} (GeV/#it{c});TPC expected signal #pi;Tracks", BIN_AXIS); + DOTH2F(hexpKa, ";#it{p} (GeV/#it{c});TPC expected signal K;Tracks", BIN_AXIS); + DOTH2F(hexpPr, ";#it{p} (GeV/#it{c});TPC expected signal p;Tracks", BIN_AXIS); + DOTH2F(hexpDe, ";#it{p} (GeV/#it{c});TPC expected signal d;Tracks", BIN_AXIS); + DOTH2F(hexpTr, ";#it{p} (GeV/#it{c});TPC expected signal t;Tracks", BIN_AXIS); + DOTH2F(hexpHe, ";#it{p} (GeV/#it{c});TPC expected signal ^{3}He;Tracks", BIN_AXIS); + DOTH2F(hexpAl, ";#it{p} (GeV/#it{c});TPC expected signal #alpha;Tracks", BIN_AXIS); + +#undef BIN_AXIS + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) + { + for (auto const& i : tracks) { + // Track selection + const UChar_t clustermap = i.itsClusterMap(); + bool issel = (i.tpcNClsFindable() > 70); + issel = issel && (i.flags() & 0x4); + issel = issel && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); + if (!issel) + continue; + // + htpcsignal->Fill(i.p(), i.tpcSignal()); + hexpEl->Fill(i.p(), i.tpcExpSignalEl()); + hexpMu->Fill(i.p(), i.tpcExpSignalMu()); + hexpPi->Fill(i.p(), i.tpcExpSignalPi()); + hexpKa->Fill(i.p(), i.tpcExpSignalKa()); + hexpPr->Fill(i.p(), i.tpcExpSignalPr()); + hexpDe->Fill(i.p(), i.tpcExpSignalDe()); + hexpTr->Fill(i.p(), i.tpcExpSignalTr()); + hexpHe->Fill(i.p(), i.tpcExpSignalHe()); + hexpAl->Fill(i.p(), i.tpcExpSignalAl()); + } + } +}; + +struct TPCPIDQANSigmaTask { // TPC NSigma - DOTH2F(htpcsignal, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", 100, 0, 5, 100, 0, 1000); - DOTH2F(hexpEl, ";#it{p} (GeV/#it{c});TPC exoected signal e;Tracks", 100, 0, 5, 100, 0, 1000); - DOTH2F(hexpDe, ";#it{p} (GeV/#it{c});TPC exoected signal d;Tracks", 100, 0, 5, 100, 0, 1000); DOTH2F(hnsigmaEl, ";#it{p} (GeV/#it{c});TPC N_{sigma e};Tracks", 100, 0, 5, 100, -10, 10); DOTH2F(hnsigmaMu, ";#it{p} (GeV/#it{c});TPC N_{sigma #mu};Tracks", 100, 0, 5, 100, -10, 10); DOTH2F(hnsigmaPi, ";#it{p} (GeV/#it{c});TPC N_{sigma #pi};Tracks", 100, 0, 5, 100, -10, 10); @@ -54,9 +92,6 @@ struct TPCPIDQATask { if (!issel) continue; // - htpcsignal->Fill(i.p(), i.tpcSignal()); - hexpEl->Fill(i.p(), i.tpcExpSignalEl()); - hexpDe->Fill(i.p(), i.tpcExpSignalDe()); hnsigmaEl->Fill(i.p(), i.tpcNSigmaEl()); hnsigmaMu->Fill(i.p(), i.tpcNSigmaMu()); hnsigmaPi->Fill(i.p(), i.tpcNSigmaPi()); @@ -73,6 +108,6 @@ struct TPCPIDQATask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<pidTPCTask>("pidTPC-task"), - adaptAnalysisTask<TPCPIDQATask>("TPCpidqa-task")}; + adaptAnalysisTask<TPCPIDQAExpSignalTask>("TPCpidqa-expsignal-task"), + adaptAnalysisTask<TPCPIDQANSigmaTask>("TPCpidqa-nsigma-task")}; } From 728e8a2e8b5eb67b2d713ce7380b2bcb9323c5c5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 30 Jul 2020 19:59:25 +0200 Subject: [PATCH 0335/1751] DPL: add service_ptr with policy based locking Depending on the kind of service the user asks for, they will get a smart pointer which includes a locking policy which will lock (or not) the service on creation and unlock it on destruction. Because services declare their (service) dependencies we are guaranteed that two services will lock their dependencies in a compatible manner (otherwise the topological sort of service dependencies will have loops). --- .../Core/include/Framework/ServiceRegistry.h | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index d32cf78d1c4b9..d8c680436737f 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -26,6 +26,7 @@ #include <stdexcept> #include <thread> #include <atomic> +#include <mutex> namespace o2::framework { @@ -35,6 +36,34 @@ struct ServiceMeta { uint64_t threadId = 0; }; +struct NoLocking { + void lock() {} + void unlock() {} +}; + +struct MutexLock { + void lock() { mutex.lock(); } + void unlock() { mutex.unlock(); } + std::mutex& mutex; +}; + +// A pointer to a service. Includes the locking policy +// for that service. +template <typename T, typename LOCKING = NoLocking> +class service_ptr : LOCKING +{ + public: + service_ptr(T* ptr, LOCKING policy) : LOCKING(policy), mPtr{ptr} { this->lock(); } + ~service_ptr() { this->unlock(); } + service_ptr(service_ptr<T, LOCKING> const&) = delete; + service_ptr& operator=(service_ptr<T, LOCKING> const&) = delete; + T& operator*() { return *mPtr; } + T* operator->() { return mPtr; } + + private: + T* mPtr; +}; + struct ServiceRegistry { /// The maximum distance a entry can be from the optimal slot. constexpr static int MAX_DISTANCE = 8; From 42cd281d7505710fca2440df65f2c8761a693edd Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 12 Aug 2020 01:53:06 +0200 Subject: [PATCH 0336/1751] DPL: helper to extract service kind from service itself --- Framework/Core/include/Framework/ServiceRegistry.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index d8c680436737f..ab6d1362bd74e 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -64,6 +64,16 @@ class service_ptr : LOCKING T* mPtr; }; +template <typename, typename = void> +struct ServiceKindExtractor { + constexpr static ServiceKind kind = ServiceKind::Serial; +}; + +template <typename T> +struct ServiceKindExtractor<T, std::void_t<decltype(T::service_kind)>> : std::is_same<decltype(T::service_kind), enum ServiceKind> { + constexpr static ServiceKind kind = T::service_kind; +}; + struct ServiceRegistry { /// The maximum distance a entry can be from the optimal slot. constexpr static int MAX_DISTANCE = 8; From 4c4bdfa27ae2b0f7953c0a3fdb9f5f2e8b87236a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 11 Aug 2020 15:29:54 +0200 Subject: [PATCH 0337/1751] DPL: make DataRelayer / TimesliceIndex threadsafe --- Framework/Core/include/Framework/DataRelayer.h | 6 ++++++ .../Core/include/Framework/TimesliceIndex.h | 15 ++++++++------- Framework/Core/src/DataRelayer.cxx | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Framework/Core/include/Framework/DataRelayer.h b/Framework/Core/include/Framework/DataRelayer.h index 1271f3374ae78..eac69eda0d1f4 100644 --- a/Framework/Core/include/Framework/DataRelayer.h +++ b/Framework/Core/include/Framework/DataRelayer.h @@ -19,6 +19,7 @@ #include "Framework/TimesliceIndex.h" #include <cstddef> +#include <mutex> #include <vector> class FairMQMessage; @@ -42,6 +43,10 @@ struct DataRelayerStats { class DataRelayer { public: + /// DataRelayer is thread safe because we have a lock around + /// each method and there is no particular order in which + /// methods need to be called. + constexpr static ServiceKind service_kind = ServiceKind::Global; enum RelayChoice { WillRelay, WillNotRelay @@ -123,6 +128,7 @@ class DataRelayer static std::vector<std::string> sQueriesMetricsNames; DataRelayerStats mStats; + std::recursive_mutex mMutex; }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/TimesliceIndex.h b/Framework/Core/include/Framework/TimesliceIndex.h index acc5cc4f0f119..43cef66bcee5e 100644 --- a/Framework/Core/include/Framework/TimesliceIndex.h +++ b/Framework/Core/include/Framework/TimesliceIndex.h @@ -8,18 +8,17 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef FRAMEWORK_TIMESLICEINDEX_H -#define FRAMEWORK_TIMESLICEINDEX_H +#ifndef O2_FRAMEWORK_TIMESLICEINDEX_H_ +#define O2_FRAMEWORK_TIMESLICEINDEX_H_ #include "Framework/DataDescriptorMatcher.h" +#include "Framework/ServiceHandle.h" #include <cstdint> #include <tuple> #include <vector> -namespace o2 -{ -namespace framework +namespace o2::framework { struct TimesliceId { @@ -46,6 +45,9 @@ struct TimesliceSlot { class TimesliceIndex { public: + /// TimesliceIndex is threadsafe because it's accessed only by the + /// DataRelayer. + constexpr static ServiceKind service_kind = ServiceKind::Global; /// The outcome for the processing of a given timeslot enum struct ActionTaken { ReplaceUnused, /// An unused / invalid slot is used to hold the new context @@ -104,8 +106,7 @@ class TimesliceIndex std::vector<bool> mDirty; }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #include "TimesliceIndex.inc" #endif // FRAMEWORK_TIMESLICEINDEX_H diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index 9342f66c66482..29e241a0caed9 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -54,6 +54,8 @@ DataRelayer::DataRelayer(const CompletionPolicy& policy, mDistinctRoutesIndex{DataRelayerHelpers::createDistinctRouteIndex(routes)}, mInputMatchers{DataRelayerHelpers::createInputMatchers(routes)} { + std::scoped_lock lock(mMutex); + setPipelineLength(DEFAULT_PIPELINE_LENGTH); // The queries are all the same, so we only have width 1 @@ -74,6 +76,8 @@ DataRelayer::DataRelayer(const CompletionPolicy& policy, DataRelayer::ActivityStats DataRelayer::processDanglingInputs(std::vector<ExpirationHandler> const& expirationHandlers, ServiceRegistry& services) { + std::scoped_lock lock(mMutex); + ActivityStats activity; /// Nothing to do if nothing can expire. if (expirationHandlers.empty()) { @@ -179,6 +183,7 @@ DataRelayer::RelayChoice DataRelayer::relay(std::unique_ptr<FairMQMessage>&& header, std::unique_ptr<FairMQMessage>&& payload) { + std::scoped_lock lock(mMutex); // STATE HOLDING VARIABLES // This is the class level state of the relaying. If we start supporting // multithreading this will have to be made thread safe before we can invoke @@ -383,6 +388,8 @@ DataRelayer::RelayChoice void DataRelayer::getReadyToProcess(std::vector<DataRelayer::RecordAction>& completed) { + std::scoped_lock lock(mMutex); + // THE STATE const auto& cache = mCache; const auto numInputTypes = mDistinctRoutesIndex.size(); @@ -460,6 +467,8 @@ void DataRelayer::getReadyToProcess(std::vector<DataRelayer::RecordAction>& comp std::vector<o2::framework::MessageSet> DataRelayer::getInputsForTimeslice(TimesliceSlot slot) { + std::scoped_lock lock(mMutex); + const auto numInputTypes = mDistinctRoutesIndex.size(); // State of the computation std::vector<MessageSet> messages(numInputTypes); @@ -513,6 +522,8 @@ std::vector<o2::framework::MessageSet> DataRelayer::getInputsForTimeslice(Timesl void DataRelayer::clear() { + std::scoped_lock lock(mMutex); + for (auto& cache : mCache) { cache.clear(); } @@ -533,6 +544,8 @@ size_t /// the time pipelining. void DataRelayer::setPipelineLength(size_t s) { + std::scoped_lock lock(mMutex); + mTimesliceIndex.resize(s); mVariableContextes.resize(s); publishMetrics(); @@ -540,6 +553,8 @@ void DataRelayer::setPipelineLength(size_t s) void DataRelayer::publishMetrics() { + std::scoped_lock lock(mMutex); + auto numInputTypes = mDistinctRoutesIndex.size(); mCache.resize(numInputTypes * mTimesliceIndex.size()); mMetrics.send({(int)numInputTypes, "data_relayer/h"}); @@ -577,6 +592,7 @@ DataRelayerStats const& DataRelayer::getStats() const void DataRelayer::sendContextState() { + std::scoped_lock lock(mMutex); for (size_t ci = 0; ci < mTimesliceIndex.size(); ++ci) { auto slot = TimesliceSlot{ci}; sendVariableContextMetrics(mTimesliceIndex.getPublishedVariablesForSlot(slot), slot, From 825b75ed215165391add4577d43cfc50da12857f Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Tue, 11 Aug 2020 14:51:53 +0200 Subject: [PATCH 0338/1751] [EMCAL-646] Adapt EMCAL raw reader to time-based format - Stand-alone application now based on RawFileReader. Reading full timeframe for EMCAL - EMCAL RawReaderFile can be deleted - EMCAL raw parsing based on RawReaderMemory - Stop condition in RawReaderMemory: pageCounter = 0 - Move to RDHAny and RDHUtils. Drop support for CDHv3 - RawReaderMemory and AltroDecoder no longer need to be templated. - Remove EMCAL CDHv3 as support is dropped - Support for page splitting: + Take RCU trailer from first page as common RCUtrailer + Sum payload size of all trailers in common trailer + Chop page RCUtrailer and append common trailer re- encoded at the end of the payload. - Fix decoding of the RCU trailer by cutting first and last word - Adapt raw fitter test macro to new raw format --- Detectors/EMCAL/base/src/EMCALBaseLinkDef.h | 1 + Detectors/EMCAL/base/src/RCUTrailer.cxx | 8 +- Detectors/EMCAL/reconstruction/CMakeLists.txt | 9 +- .../EMCALReconstruction/AltroDecoder.h | 17 +- .../EMCALReconstruction/RAWDataHeader.h | 109 ------------ .../EMCALReconstruction/RawReaderFile.h | 158 ----------------- .../EMCALReconstruction/RawReaderMemory.h | 17 +- .../reconstruction/macros/RawFitterTESTs.C | 55 ++++-- .../reconstruction/run/rawReaderFile.cxx | 84 +++++---- .../EMCAL/reconstruction/src/AltroDecoder.cxx | 52 ++---- .../src/EMCALReconstructionLinkDef.h | 12 +- .../reconstruction/src/RAWDataHeader.cxx | 66 -------- .../EMCAL/reconstruction/src/RawBuffer.cxx | 14 +- .../reconstruction/src/RawReaderFile.cxx | 159 ------------------ .../reconstruction/src/RawReaderMemory.cxx | 108 +++++++----- .../workflow/src/RawToCellConverterSpec.cxx | 28 +-- 16 files changed, 218 insertions(+), 679 deletions(-) delete mode 100644 Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RAWDataHeader.h delete mode 100644 Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderFile.h delete mode 100644 Detectors/EMCAL/reconstruction/src/RAWDataHeader.cxx delete mode 100644 Detectors/EMCAL/reconstruction/src/RawReaderFile.cxx diff --git a/Detectors/EMCAL/base/src/EMCALBaseLinkDef.h b/Detectors/EMCAL/base/src/EMCALBaseLinkDef.h index c80b7825b65f7..865b3fd0d5e6d 100644 --- a/Detectors/EMCAL/base/src/EMCALBaseLinkDef.h +++ b/Detectors/EMCAL/base/src/EMCALBaseLinkDef.h @@ -18,6 +18,7 @@ #pragma link C++ class o2::emcal::Geometry + ; #pragma link C++ class o2::emcal::Mapper + ; #pragma link C++ class o2::emcal::MappingHandler + ; +#pragma link C++ class o2::emcal::RCUTrailer + ; #pragma link C++ class o2::emcal::ClusterFactory < o2::emcal::Cell> + ; #pragma link C++ class o2::emcal::ClusterFactory < o2::emcal::Digit> + ; diff --git a/Detectors/EMCAL/base/src/RCUTrailer.cxx b/Detectors/EMCAL/base/src/RCUTrailer.cxx index d7451cfbb02c5..4188c1de80561 100644 --- a/Detectors/EMCAL/base/src/RCUTrailer.cxx +++ b/Detectors/EMCAL/base/src/RCUTrailer.cxx @@ -36,8 +36,8 @@ void RCUTrailer::reset() void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payloadwords) { reset(); - int index = payloadwords.size() - 1; - auto word = payloadwords[index]; + int index = payloadwords.size(); + auto word = payloadwords[--index]; if ((word >> 30) != 3) throw Error(Error::ErrorType_t::DECODING_INVALID, "Last RCU trailer word not found!"); mFirmwareVersion = (word >> 16) & 0xFF; @@ -49,6 +49,7 @@ void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payload throw Error(Error::ErrorType_t::SIZE_INVALID, fmt::format("Invalid trailer size found (%d bytes) !", trailerSize * 4).data()); mTrailerSize = trailerSize; + trailerSize -= 2; // Cut first and last trailer words as they are handled separately for (; trailerSize > 0; trailerSize--) { word = payloadwords[--index]; if ((word >> 30) != 2) { @@ -153,6 +154,7 @@ void RCUTrailer::setL1Phase(double l1phase) std::vector<uint32_t> RCUTrailer::encode() const { std::vector<uint32_t> encoded; + encoded.emplace_back(mPayloadSize); encoded.emplace_back(mAltroCFG2 | 7 << 26); encoded.emplace_back(mAltroCFG1 | 6 << 26); encoded.emplace_back(mActiveFECsB | 5 << 26); @@ -161,7 +163,7 @@ std::vector<uint32_t> RCUTrailer::encode() const encoded.emplace_back(mERRREG2 | 2 << 26); encoded.emplace_back(mFECERRB >> 7 | (mFECERRA >> 7) << 13 | 1 << 26); - uint32_t lasttrailerword = 3 << 30 | mFirmwareVersion << 16 | mRCUId << 7 | encoded.size(); + uint32_t lasttrailerword = 3 << 30 | mFirmwareVersion << 16 | mRCUId << 7 | (encoded.size() + 1); encoded.emplace_back(lasttrailerword); return encoded; diff --git a/Detectors/EMCAL/reconstruction/CMakeLists.txt b/Detectors/EMCAL/reconstruction/CMakeLists.txt index c52c191fdae11..514822ba1ec5a 100644 --- a/Detectors/EMCAL/reconstruction/CMakeLists.txt +++ b/Detectors/EMCAL/reconstruction/CMakeLists.txt @@ -9,11 +9,9 @@ # submit itself to any jurisdiction. o2_add_library(EMCALReconstruction - SOURCES src/RawReaderFile.cxx - src/RawReaderMemory.cxx + SOURCES src/RawReaderMemory.cxx src/RawBuffer.cxx src/RawHeaderStream.cxx - src/RAWDataHeader.cxx src/RawPayload.cxx src/AltroDecoder.cxx src/Bunch.cxx @@ -30,17 +28,16 @@ o2_add_library(EMCALReconstruction AliceO2::InfoLogger O2::DataFormatsEMCAL O2::DetectorsBase + O2::DetectorsRaw O2::EMCALBase) o2_target_root_dictionary( EMCALReconstruction - HEADERS include/EMCALReconstruction/RawReaderFile.h - include/EMCALReconstruction/RawReaderMemory.h + HEADERS include/EMCALReconstruction/RawReaderMemory.h include/EMCALReconstruction/AltroDecoder.h include/EMCALReconstruction/RawPayload.h include/EMCALReconstruction/Bunch.h include/EMCALReconstruction/Channel.h - include/EMCALReconstruction/RAWDataHeader.h include/EMCALReconstruction/CaloFitResults.h include/EMCALReconstruction/CaloRawFitter.h include/EMCALReconstruction/CaloRawFitterStandard.h diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/AltroDecoder.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/AltroDecoder.h index 7b453c05e969d..00720e2c5ad65 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/AltroDecoder.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/AltroDecoder.h @@ -17,12 +17,7 @@ #include "EMCALBase/RCUTrailer.h" #include "EMCALReconstruction/Bunch.h" #include "EMCALReconstruction/Channel.h" - -// for template specification -#include "EMCALReconstruction/RawReaderFile.h" #include "EMCALReconstruction/RawReaderMemory.h" -#include "EMCALReconstruction/RAWDataHeader.h" -#include "Headers/RAWDataHeader.h" namespace o2 { @@ -84,13 +79,13 @@ class AltroDecoderError : public std::exception /// the payload, altro header and RCU trailer contents. /// /// Based on AliAltroRawStreamV3 and AliCaloRawStreamV3 by C. Cheshkov -template <class RawReader> + class AltroDecoder { public: /// \brief Constructor /// \param reader Raw reader instance to be decoded - AltroDecoder(RawReader& reader); + AltroDecoder(RawReaderMemory& reader); /// \brief Destructor ~AltroDecoder() = default; @@ -130,7 +125,7 @@ class AltroDecoder /// In case of failure an exception is thrown. void checkRCUTrailer(); - RawReader& mRawReader; ///< underlying raw reader + RawReaderMemory& mRawReader; ///< underlying raw reader RCUTrailer mRCUTrailer; ///< RCU trailer std::vector<Channel> mChannels; ///< vector of channels in the raw stream bool mChannelsInitialized = false; ///< check whether the channels are initialized @@ -138,12 +133,6 @@ class AltroDecoder ClassDefNV(AltroDecoder, 1); }; -// template specifications -using AltroDecoderMemoryRDHvE = AltroDecoder<RawReaderMemory<o2::emcal::RAWDataHeader>>; -using AltroDecoderMemoryRDHv4 = AltroDecoder<RawReaderMemory<o2::header::RAWDataHeaderV4>>; -using AltroDecoderFileRDHvE = AltroDecoder<RawReaderFile<o2::emcal::RAWDataHeader>>; -using AltroDecoderFileRDHv4 = AltroDecoder<RawReaderFile<o2::header::RAWDataHeaderV4>>; - } // namespace emcal } // namespace o2 diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RAWDataHeader.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RAWDataHeader.h deleted file mode 100644 index 652e1c41a9677..0000000000000 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RAWDataHeader.h +++ /dev/null @@ -1,109 +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. - -#ifndef ALICEO2_EMCAL_RAwDATAHEADER_H -#define ALICEO2_EMCAL_RAwDATAHEADER_H - -#include <iosfwd> -#include <cstdint> -#include "Rtypes.h" - -namespace o2 -{ -namespace emcal -{ -struct RAWDataHeader { - union { - uint32_t word0 = 0xFFFFFFFF; // size of the raw data in bytes - }; - - union { - uint32_t word1 = 3 << 24; // bunch crossing, L1 trigger message and format version - struct { - uint32_t triggerBC : 14; ///< bunch crossing [0-13] - uint32_t triggermessageL1 : 8; ///< L1 trigger message [14-21] - uint32_t zero11 : 2; ///< Unassigned [22-23] - uint32_t version : 8; ///< Version [24-31] - }; - }; - - union { - uint32_t word2 = 0; //< Size and offset - struct { - uint32_t offsetToNext : 16; ///< offset [0-15] - uint32_t memorySize : 16; ///< size [16-31] - }; - }; - - union { - uint32_t word3 = 0; ///< Number of packets and linkID - struct { - uint8_t linkID : 8; ///< Link ID [0-7] - uint8_t packetCounter : 8; ///< Number of packets [8-15] - uint16_t zero31 : 16; ///< Unassigned [16-31] - }; - }; - - union { - uint32_t word4 = 0x10000; // status & error bits and mini event ID - struct { - uint32_t triggerOrbit : 12; ///< mini event ID [0-11] - uint32_t status : 16; ///< status & error bits [12-27] - uint32_t zero41 : 4; ///< Unassigned [28-31] - }; - }; - - union { - uint32_t word5; ///< First word of the tirgger types - struct { - uint32_t triggerType : 32; ///< low trigger types [0-49] - }; - }; - - union { - uint32_t word6; ///< Second word of the trigger types - struct { - uint32_t triggerTypesHigh : 18; ///< Second part of the trigger types [0-17] - uint32_t triggerTypesNext50 : 14; ///< First part of the trigger types next 50 [18-31] - }; - }; - - union { - uint32_t word7; ///< Third word of the trigger types - struct { - uint32_t triggerTypesNext50Middle : 32; ///< Second part of the trigger types next 50 - }; - }; - - union { - uint32_t word8; ///< Fourth word of the trigger types - struct { - uint32_t triggerTypesNext50High : 4; ///< Third part of the trigger types next 50 [0-3] - uint32_t zero81 : 24; ///< Unassigned [4-27] - uint32_t roi : 4; ///< First part of the roi [28-31] - }; - }; - - union { - uint32_t word9; ///< Second word of the roi - struct { - uint32_t roiHigh : 32; ///< Second part of the roi - }; - }; -}; - -std::istream& operator>>(std::istream& in, o2::emcal::RAWDataHeader& header); -std::ostream& operator<<(std::ostream& out, const o2::emcal::RAWDataHeader& header); - -} // namespace emcal - -} // namespace o2 - -#endif // _O2_EMCAL_RAwDATAHEADER_H__ \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderFile.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderFile.h deleted file mode 100644 index 9dedf2c087656..0000000000000 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderFile.h +++ /dev/null @@ -1,158 +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. -#ifndef ALICEO2_EMCAL_RAWREADERFILE_H -#define ALICEO2_EMCAL_RAWREADERFILE_H - -#include <array> -#include <bitset> -#include <cstdint> -#include <fstream> -#include <string> - -#include "Rtypes.h" -#include "RStringView.h" - -#include "Headers/RAWDataHeader.h" -#include "EMCALReconstruction/RawBuffer.h" -#include "EMCALReconstruction/RAWDataHeader.h" -#include "EMCALReconstruction/RawPayload.h" - -namespace o2 -{ - -namespace emcal -{ - -/// \class RawReaderFile -/// \brief Reader for raw data produced by the ReadoutCard from a binary file -/// \ingroup EMCALreconstruction -/// \author Markus Fasel <markus.fasel@cern.ch>, Oak Ridge National Laboratory -/// \since Aug. 12, 2019 -/// -/// -template <class RawHeader> -class RawReaderFile -{ - public: - /// \brief Constructor - /// - /// Opening the raw file and determining its size and the number - /// of pages. - RawReaderFile(const std::string_view filename); - - /// \brief Destructor - /// - /// Closing the raw file - ~RawReaderFile(); - - /// \brief Read next payload from the stream - /// - /// Read the next pages until the stop bit is found. - void next(); - - /// \brief Read the next page from the stream (single DMA page) - /// \param resetPayload If true the raw payload is reset - /// \throw Error if the page cannot be read or header or payload cannot be deocded - /// - /// Function reading a single DMA page from the stream. It is called - /// inside the next() function for reading payload from multiple DMA - /// pages. As the function cannot handle payload from multiple pages - /// it should not be called directly by the user. - void nextPage(bool resetPayload = true); - - /// \brief Read page with a given index - /// \param page Index of the page to be decoded - /// \throw RawDecodingError if the page cannot be read or header or payload cannot be deocded - /// - /// The reader will try to read the page with a certain index. In - /// case the page cannot be decoded (page index outside range, - /// decoding of header or payload failed), and excpetion is raised. - void readPage(int page); - - /// \brief access to the raw header of the current page - /// \return Raw header of the current page - /// \throw Error with HEADER_INVALID if the header was not decoded - const RawHeader& getRawHeader() const; - - /// \brief access to the raw buffer (single DMA page) - /// \return Raw buffer of the current page - /// \throw Error with PAYLOAD_INCALID if payload was not decoded - const RawBuffer& getRawBuffer() const; - - /// \brief access to the full raw payload (single or multiple DMA pages) - /// \return Raw Payload of the data until the stop bit is received. - const RawPayload& getPayload() const { return mRawPayload; } - - /// \brief Return size of the payload - /// \return size of the payload - int getPayloadSize() const { return mRawPayload.getPayloadSize(); } - - /// \brief get the size of the file in bytes - /// \return size of the file in byte - int getFileSize() const noexcept { return mFileSize; } - - /// \brief get the number of pages in the file - /// \return number of pages in the file - int getNumberOfPages() const noexcept { return mNumData; } - - /// \brief check if more pages are available in the raw file - /// \return true if there is a next page - bool hasNext() const { return mCurrentPosition < mNumData; } - - static void readFile(const std::string_view filename); - - protected: - /// \brief Init the raw reader - /// - /// Opening the raw file and determining the number of superpages - void init(); - - /// \brief Decode the Raw Data Header - /// \throw RawDecodingError with HEADER_DECODING in case the header decoding failed - /// - /// Decoding the raw header. Function assumes that the pointer - /// is at the beginning of the raw header - void readHeader(); - - /// \brief Decode the payload - /// \throw RawDecodingError with PAYLOAD_DECODING in case the payload decoding failed - /// - /// Decoding the payload. The function assumes that the pointer is at - /// the beginning of the payload of the page. Needs the raw header of the - /// page to be decoded before in order to determine size of the payload - /// and offset. - void readPayload(); - - bool isStop(const o2::emcal::RAWDataHeader& hdr) { return true; } - bool isStop(const o2::header::RAWDataHeaderV4& hdr) { return hdr.stop; } - - private: - std::string mInputFileName; ///< Name of the input file - std::ifstream mDataFile; ///< Stream of the inputfile - RawHeader mRawHeader; ///< Raw header - RawBuffer mRawBuffer; ///< Raw buffer - RawPayload mRawPayload; ///< Raw payload (can consist of multiple pages) - int mCurrentPosition = 0; ///< Current page in file - int mFileSize = 0; ///< Size of the file in bytes - int mNumData = 0; ///< Number of pages - bool mRawHeaderInitialized = false; ///< RDH for current page initialized - bool mPayloadInitialized = false; ///< Payload for current page initialized - - ClassDefNV(RawReaderFile, 1); -}; - -// template specifications -using RawReaderFileRDHvE = RawReaderFile<o2::emcal::RAWDataHeader>; -using RawReaderFileRDHv4 = RawReaderFile<o2::header::RAWDataHeaderV4>; - -} // namespace emcal - -} // namespace o2 -#endif diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderMemory.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderMemory.h index 208c73f0c4319..c6d544e0529ff 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderMemory.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RawReaderMemory.h @@ -13,10 +13,11 @@ #include <gsl/span> #include <Rtypes.h> +#include "EMCALBase/RCUTrailer.h" #include "EMCALReconstruction/RawBuffer.h" -#include "EMCALReconstruction/RAWDataHeader.h" #include "EMCALReconstruction/RawPayload.h" #include "Headers/RAWDataHeader.h" +#include "Headers/RDHAny.h" namespace o2 { @@ -31,7 +32,6 @@ namespace emcal /// \since Nov. 14, 2019 /// /// -template <class RawHeader> class RawReaderMemory { public: @@ -72,7 +72,7 @@ class RawReaderMemory /// \brief access to the raw header of the current page /// \return Raw header of the current page /// \throw RawDecodingError with HEADER_INVALID if the header was not decoded - const RawHeader& getRawHeader() const; + const o2::header::RDHAny& getRawHeader() const; /// \brief access to the raw buffer (single DMA page) /// \return Raw buffer of the current page @@ -105,14 +105,15 @@ class RawReaderMemory /// Rewind stream to the first entry void init(); - bool isStop(const o2::emcal::RAWDataHeader& hdr) { return true; } - bool isStop(const o2::header::RAWDataHeaderV4& hdr) { return hdr.stop; } + o2::header::RDHAny decodeRawHeader(const void* headerwords); private: gsl::span<const char> mRawMemoryBuffer; ///< Memory block with multiple DMA pages RawBuffer mRawBuffer; ///< Raw buffer - RawHeader mRawHeader; ///< Raw header + o2::header::RDHAny mRawHeader; ///< Raw header RawPayload mRawPayload; ///< Raw payload (can consist of multiple pages) + RCUTrailer mCurrentTrailer; ///< RCU trailer + uint64_t mTrailerPayloadWords = 0; ///< Payload words in common trailer int mCurrentPosition = 0; ///< Current page in file int mNumData = 0; ///< Number of pages bool mRawHeaderInitialized = false; ///< RDH for current page initialized @@ -121,10 +122,6 @@ class RawReaderMemory ClassDefNV(RawReaderMemory, 1); }; -// For template specifications -using RawReaderMemoryRDHvE = RawReaderMemory<o2::emcal::RAWDataHeader>; -using RawReaderMemoryRDHv4 = RawReaderMemory<o2::header::RAWDataHeaderV4>; - } // namespace emcal } // namespace o2 diff --git a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C index 25695221d817b..deb09a48db3fd 100644 --- a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C +++ b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C @@ -15,6 +15,7 @@ #include <vector> #include "RStringView.h" #include <Rtypes.h> +#include "DetectorsRaw/RawFileReader.h" #include "EMCALReconstruction/CaloFitResults.h" #include "EMCALReconstruction/Bunch.h" #include "EMCALReconstruction/CaloRawFitterStandard.h" @@ -38,7 +39,12 @@ void RawFitterTESTs() inputDir = aliceO2env; inputDir += "/share/Detectors/EMC/files/"; - o2::emcal::RawReaderFile<o2::header::RAWDataHeaderV4> rawreader(inputDir + "emcal.raw"); + o2::raw::RawFileReader reader; + reader.setDefaultDataOrigin(o2::header::gDataOriginEMC); + reader.setDefaultDataDescription(o2::header::gDataDescriptionRawData); + reader.setDefaultReadoutCardType(o2::raw::RawFileReader::RORC); + reader.addFile(inputDir + "emcal.raw"); + reader.init(); // define the standard raw fitter //o2::emcal::CaloRawFitterStandard RawFitter; @@ -46,28 +52,45 @@ void RawFitterTESTs() RawFitter.setAmpCut(NoiseThreshold); RawFitter.setL1Phase(0.); - // loop over all the DMA pages - while (rawreader.hasNext()) { + while (1) { + int tfID = reader.getNextTFToRead(); + if (tfID >= reader.getNTimeFrames()) { + std::cerr << "nothing left to read after " << tfID << " TFs read"; + break; + } + std::vector<char> dataBuffer; // where to put extracted data + for (int il = 0; il < reader.getNLinks(); il++) { + auto& link = reader.getLink(il); + std::cout << "Decoding link " << il << std::endl; + + auto sz = link.getNextTFSize(); // size in bytes needed for the next TF of this link + dataBuffer.resize(sz); + link.readNextTF(dataBuffer.data()); - rawreader.next(); - std::cout << "next page \n"; + // Parse + o2::emcal::RawReaderMemory parser(dataBuffer); + while (parser.hasNext()) { + parser.next(); + std::cout << "next page \n"; - //std::cout<<rawreader.getRawHeader()<<std::endl; + //std::cout<<rawreader.getRawHeader()<<std::endl; - // use the altro decoder to decode the raw data, and extract the RCU trailer - o2::emcal::AltroDecoder<decltype(rawreader)> decoder(rawreader); - decoder.decode(); + // use the altro decoder to decode the raw data, and extract the RCU trailer + o2::emcal::AltroDecoder decoder(parser); + decoder.decode(); - std::cout << decoder.getRCUTrailer() << std::endl; + std::cout << decoder.getRCUTrailer() << std::endl; - // Loop over all the channels - for (auto& chan : decoder.getChannels()) { + // Loop over all the channels + for (auto& chan : decoder.getChannels()) { - // define the conatiner for the fit results, and perform the raw fitting using the stadnard raw fitter - o2::emcal::CaloFitResults fitResults = RawFitter.evaluate(chan.getBunches(), 0, 0); + // define the conatiner for the fit results, and perform the raw fitting using the stadnard raw fitter + o2::emcal::CaloFitResults fitResults = RawFitter.evaluate(chan.getBunches(), 0, 0); - // print the fit output - std::cout << "The Time is : " << fitResults.getTime() << " And the Amplitude is : " << fitResults.getAmp() << std::endl; + // print the fit output + std::cout << "The Time is : " << fitResults.getTime() << " And the Amplitude is : " << fitResults.getAmp() << std::endl; + } + } } } } diff --git a/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx b/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx index 70808de706187..e899dfe00b0ab 100644 --- a/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx +++ b/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx @@ -8,27 +8,26 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file rawReaderFile.cxx +/// \file rawReaderFileNew.cxx /// \author Markus Fasel <markus.fasel@cern.ch>, Oak Ridge National Laboratory #include <iostream> #include <boost/program_options.hpp> -#include "Headers/RAWDataHeader.h" -#include "EMCALReconstruction/RawHeaderStream.h" -#include "EMCALReconstruction/RAWDataHeader.h" -#include "EMCALReconstruction/RawReaderFile.h" +#include "DetectorsRaw/RawFileReader.h" #include "EMCALReconstruction/AltroDecoder.h" +#include "EMCALReconstruction/RawReaderMemory.h" +#include "FairLogger.h" namespace bpo = boost::program_options; -using namespace o2::emcal; +//using namespace o2::emcal; int main(int argc, char** argv) { bpo::variables_map vm; bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + " <cmds/options>\n" - " Tool will decode the GBTx data for SAMPA 0\n" + " Tool will decode the DDLx data for EMCAL 0\n" "Commands / Options"); bpo::options_description opt_hidden(""); bpo::options_description opt_all; @@ -39,7 +38,6 @@ int main(int argc, char** argv) add_option("help,h", "Print this help message"); add_option("verbose,v", bpo::value<uint32_t>()->default_value(0), "Select verbosity level [0 = no output]"); add_option("version", "Print version information"); - add_option("rdh,r", bpo::value<int>()->default_value(3), "RAW Data Header version (3 - CDHv3, 4 - RDHv4)"); add_option("input-file,i", bpo::value<std::string>()->required(), "Specifies input file."); add_option("debug,d", bpo::value<uint32_t>()->default_value(0), "Select debug output level [0 = no debug output]"); @@ -67,34 +65,52 @@ int main(int argc, char** argv) exit(2); } - auto decode = [](auto reader) { - while (reader.hasNext()) { - reader.next(); - std::cout << reader.getRawHeader(); - o2::emcal::AltroDecoder<decltype(reader)> decoder(reader); - decoder.decode(); - std::cout << decoder.getRCUTrailer() << std::endl; - for (auto& chan : decoder.getChannels()) { - std::cout << "Hw address: " << chan.getHardwareAddress() << std::endl; - for (auto& bunch : chan.getBunches()) { - std::cout << "BunchLength: " << int(bunch.getBunchLength()) << std::endl; - auto adcs = bunch.getADC(); - int time = bunch.getStartTime(); - for (int i = adcs.size() - 1; i >= 0; i--) { - std::cout << "Timebin " << time << ", ADC " << adcs[i] << std::endl; - time--; + auto rawfilename = vm["input-file"].as<std::string>(); + + o2::raw::RawFileReader reader; + reader.setDefaultDataOrigin(o2::header::gDataOriginEMC); + reader.setDefaultDataDescription(o2::header::gDataDescriptionRawData); + reader.setDefaultReadoutCardType(o2::raw::RawFileReader::RORC); + reader.addFile(rawfilename); + reader.init(); + + while (1) { + int tfID = reader.getNextTFToRead(); + if (tfID >= reader.getNTimeFrames()) { + LOG(INFO) << "nothing left to read after " << tfID << " TFs read"; + break; + } + std::vector<char> dataBuffer; // where to put extracted data + for (int il = 0; il < reader.getNLinks(); il++) { + auto& link = reader.getLink(il); + std::cout << "Decoding link " << il << std::endl; + + auto sz = link.getNextTFSize(); // size in bytes needed for the next TF of this link + dataBuffer.resize(sz); + link.readNextTF(dataBuffer.data()); + + // Parse + o2::emcal::RawReaderMemory parser(dataBuffer); + while (parser.hasNext()) { + parser.next(); + o2::emcal::AltroDecoder decoder(parser); + decoder.decode(); + + std::cout << decoder.getRCUTrailer() << std::endl; + for (auto& chan : decoder.getChannels()) { + std::cout << "Hw address: " << chan.getHardwareAddress() << std::endl; + for (auto& bunch : chan.getBunches()) { + std::cout << "BunchLength: " << int(bunch.getBunchLength()) << std::endl; + auto adcs = bunch.getADC(); + int time = bunch.getStartTime(); + for (int i = adcs.size() - 1; i >= 0; i--) { + std::cout << "Timebin " << time << ", ADC " << adcs[i] << std::endl; + time--; + } } } } } - }; - - auto rawfilename = vm["input-file"].as<std::string>(); - auto rawHeaderVersion = vm["rdh"].as<int>(); - if (rawHeaderVersion == 4) { - decode(o2::emcal::RawReaderFileRDHv4(rawfilename)); - } else { - decode(o2::emcal::RawReaderFileRDHvE(rawfilename)); + reader.setNextTFToRead(++tfID); } - return 0; -} +} \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx index 6c42966a68640..1d1eca3495ccc 100644 --- a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx @@ -8,36 +8,28 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include <cstring> -#include <iomanip> -#include <iostream> #include <boost/format.hpp> #include "InfoLogger/InfoLogger.hxx" -#include "Headers/RAWDataHeader.h" #include "EMCALReconstruction/AltroDecoder.h" -#include "EMCALReconstruction/RAWDataHeader.h" -#include "EMCALReconstruction/RawReaderFile.h" #include "EMCALReconstruction/RawReaderMemory.h" using namespace o2::emcal; -template <class RawReader> -AltroDecoder<RawReader>::AltroDecoder(RawReader& reader) : mRawReader(reader), - mRCUTrailer(), - mChannels(), - mChannelsInitialized(false) +AltroDecoder::AltroDecoder(RawReaderMemory& reader) : mRawReader(reader), + mRCUTrailer(), + mChannels(), + mChannelsInitialized(false) { } -template <class RawReader> -void AltroDecoder<RawReader>::decode() +void AltroDecoder::decode() { readRCUTrailer(); checkRCUTrailer(); readChannels(); } -template <class RawReader> -void AltroDecoder<RawReader>::readRCUTrailer() +void AltroDecoder::readRCUTrailer() { try { auto payloadwordsOrig = mRawReader.getPayload().getPayloadWords(); @@ -50,19 +42,16 @@ void AltroDecoder<RawReader>::readRCUTrailer() } } -template <class RawReader> -void AltroDecoder<RawReader>::checkRCUTrailer() +void AltroDecoder::checkRCUTrailer() { } -template <class RawReader> -void AltroDecoder<RawReader>::readChannels() +void AltroDecoder::readChannels() { mChannelsInitialized = false; mChannels.clear(); int currentpos = 0; auto& buffer = mRawReader.getPayload().getPayloadWords(); - std::array<uint16_t, 1024> bunchwords; while (currentpos < buffer.size() - mRCUTrailer.getTrailerSize()) { auto currentword = buffer[currentpos++]; if (currentword >> 30 != 1) { @@ -74,8 +63,8 @@ void AltroDecoder<RawReader>::readChannels() currentchannel.setBadChannel((currentword >> 29) & 0x1); /// decode all words for channel - int numberofsamples = 0, - numberofwords = (currentchannel.getPayloadSize() + 2) / 3; + int numberofwords = (currentchannel.getPayloadSize() + 2) / 3; + std::vector<uint16_t> bunchwords; for (int iword = 0; iword < numberofwords; iword++) { currentword = buffer[currentpos++]; if ((currentword >> 30) != 0) { @@ -85,9 +74,9 @@ void AltroDecoder<RawReader>::readChannels() currentpos--; continue; } - bunchwords[numberofsamples++] = (currentword >> 20) & 0x3FF; - bunchwords[numberofsamples++] = (currentword >> 10) & 0x3FF; - bunchwords[numberofsamples++] = currentword & 0x3FF; + bunchwords.push_back((currentword >> 20) & 0x3FF); + bunchwords.push_back((currentword >> 10) & 0x3FF); + bunchwords.push_back(currentword & 0x3FF); } // decode bunches @@ -96,30 +85,23 @@ void AltroDecoder<RawReader>::readChannels() int bunchlength = bunchwords[currentsample] - 2, // remove words for bunchlength and starttime starttime = bunchwords[currentsample + 1]; auto& currentbunch = currentchannel.createBunch(bunchlength, starttime); - currentbunch.initFromRange(gsl::span<uint16_t>(&bunchwords[currentsample + 2], std::min(bunchlength, numberofsamples - currentsample - 2))); + currentbunch.initFromRange(gsl::span<uint16_t>(&bunchwords[currentsample + 2], std::min((unsigned long)bunchlength, bunchwords.size() - currentsample - 2))); currentsample += bunchlength + 2; } } mChannelsInitialized = true; } -template <class RawReader> -const RCUTrailer& AltroDecoder<RawReader>::getRCUTrailer() const +const RCUTrailer& AltroDecoder::getRCUTrailer() const { if (!mRCUTrailer.isInitialized()) throw AltroDecoderError(AltroDecoderError::ErrorType_t::RCU_TRAILER_ERROR, "RCU trailer was not initialized"); return mRCUTrailer; } -template <class RawReader> -const std::vector<Channel>& AltroDecoder<RawReader>::getChannels() const +const std::vector<Channel>& AltroDecoder::getChannels() const { if (!mChannelsInitialized) throw AltroDecoderError(AltroDecoderError::ErrorType_t::CHANNEL_ERROR, "Channels not initizalized"); return mChannels; -} - -template class o2::emcal::AltroDecoder<o2::emcal::RawReaderFile<o2::emcal::RAWDataHeader>>; -template class o2::emcal::AltroDecoder<o2::emcal::RawReaderFile<o2::header::RAWDataHeaderV4>>; -template class o2::emcal::AltroDecoder<o2::emcal::RawReaderMemory<o2::emcal::RAWDataHeader>>; -template class o2::emcal::AltroDecoder<o2::emcal::RawReaderMemory<o2::header::RAWDataHeaderV4>>; \ No newline at end of file +} \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h b/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h index f52ae19d5d116..2a5f25a56e4c0 100644 --- a/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h +++ b/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h @@ -14,18 +14,12 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class o2::emcal::RawReaderFile < o2::emcal::RAWDataHeader> + ; -#pragma link C++ class o2::emcal::RawReaderFile < o2::header::RAWDataHeaderV4> + ; -#pragma link C++ class o2::emcal::RawReaderMemory < o2::emcal::RAWDataHeader> + ; -#pragma link C++ class o2::emcal::RawReaderMemory < o2::header::RAWDataHeaderV4> + ; -#pragma link C++ class o2::emcal::AltroDecoder < o2::emcal::RawReaderFile < o2::emcal::RAWDataHeader>> + ; -#pragma link C++ class o2::emcal::AltroDecoder < o2::emcal::RawReaderFile < o2::header::RAWDataHeaderV4>> + ; -#pragma link C++ class o2::emcal::AltroDecoder < o2::emcal::RawReaderMemory < o2::emcal::RAWDataHeader>> + ; -#pragma link C++ class o2::emcal::AltroDecoder < o2::emcal::RawReaderMemory < o2::header::RAWDataHeaderV4>> + ; + +#pragma link C++ class o2::emcal::RawReaderMemory + ; +#pragma link C++ class o2::emcal::AltroDecoder + ; #pragma link C++ class o2::emcal::RawPayload + ; #pragma link C++ class o2::emcal::Bunch + ; #pragma link C++ class o2::emcal::Channel + ; -#pragma link C++ class o2::emcal::RCUTrailer + ; #pragma link C++ class o2::emcal::CaloFitResults + ; #pragma link C++ class o2::emcal::CaloRawFitter + ; #pragma link C++ class o2::emcal::CaloRawFitterStandard + ; diff --git a/Detectors/EMCAL/reconstruction/src/RAWDataHeader.cxx b/Detectors/EMCAL/reconstruction/src/RAWDataHeader.cxx deleted file mode 100644 index 3e4e3fab514c5..0000000000000 --- a/Detectors/EMCAL/reconstruction/src/RAWDataHeader.cxx +++ /dev/null @@ -1,66 +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. - -#include <bitset> -#include <iostream> -#include <iomanip> -#include "EMCALReconstruction/RAWDataHeader.h" - -using namespace o2::emcal; - -std::ostream& o2::emcal::operator<<(std::ostream& stream, const o2::emcal::RAWDataHeader& header) -{ - stream << "EMCAL CRORC RAW Header:\n" - << " Size (WORD0): " << header.word0 << "(" << std::hex << header.word0 << std::dec << ")\n" - << " WORD1: " << header.word1 << "(" << std::hex << header.word1 << std::dec << ")\n" - << " Version: " << int(header.version) << "\n" - << " L1 Trigger Message: " << int(header.triggermessageL1) << "\n" - << " EventID1: " << header.triggerBC << "\n" - << " Offset and size (WORD2): " << header.word2 << "(" << std::hex << header.word2 << std::dec << ")\n" - << " Offset: " << header.offsetToNext << "\n" - << " Size: " << header.memorySize << "\n" - << " Package counter and link ID (WORD3): (" << std::hex << header.word3 << std::dec << ")\n" - << " Packet counter: " << int(header.packetCounter) << "\n" - << " Link ID: " << int(header.linkID) << "\n" - << " Status and mini eventID: " << header.word4 << " (" << std::hex << header.word4 << std::dec << ")\n" - << " Status: " << header.status << "\n" - << " Mini EventID: " << header.triggerOrbit << "\n" - /* - << " Trigger Classes: ( " << std::hex << header.words5[0] << " " << header.words5[1] << " " << header.words5[2] << std::dec << ")\n" - << " First 50: " << std::bitset<sizeof(uint64_t)*8>(header.triggerType) << "\n" - << " Second 50: " << std::bitset<sizeof(uint64_t)*8>(header.triggerTypeNext50) << "\n" - << " ROI: (" << std::hex << header.words5[3] << " " << header.words5[4] << std::dec << ")\n" - << " ROI: " << std::bitset<sizeof(uint64_t)*8>(header.roi) << "\n" - */ - << "End Header" << std::endl; - return stream; -} - -std::istream& o2::emcal::operator>>(std::istream& stream, o2::emcal::RAWDataHeader& header) -{ - //std::cout << "called, 10 words" << std::endl; - uint32_t message[10]; - auto address = reinterpret_cast<char*>(message); - for (int i = 0; i < 10; i++) { - stream.read(address + i * sizeof(uint32_t) / sizeof(char), sizeof(message[i])); - //std::cout << "Word " << i << ": " << std::hex << message[i] << std::dec << std::endl; - } - header.word0 = message[0]; - header.word1 = message[1]; - header.word2 = message[2]; - header.word3 = message[3]; - header.word4 = message[4]; - header.word5 = message[5]; - header.word6 = message[6]; - header.word7 = message[7]; - header.word8 = message[8]; - header.word9 = message[9]; - return stream; -} \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx b/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx index 932ccd4464087..1da3635891218 100644 --- a/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx @@ -47,12 +47,14 @@ void RawBuffer::readFromMemoryBuffer(const gsl::span<const char> rawmemory) flush(); auto address = reinterpret_cast<const uint32_t*>(rawmemory.data()); for (auto iword = 0; iword < rawmemory.size() / sizeof(uint32_t); iword++) { - if ((address[iword] & 0xFFF) == 0x082) { - // Termination word - // should normally not be decoded in case the payload size - // is determined correctly - break; - } + // Run2 code, probably not needed for run3 + // if ((address[iword] & 0xFFF) == 0x082) { + // Termination word + // should normally not be decoded in case the payload size + // is determined correctly + //std::cout << "Found termination word" << std::endl; + //break; + // } mDataWords[mNDataWords++] = address[iword]; } } diff --git a/Detectors/EMCAL/reconstruction/src/RawReaderFile.cxx b/Detectors/EMCAL/reconstruction/src/RawReaderFile.cxx deleted file mode 100644 index d2fd6fdf1573e..0000000000000 --- a/Detectors/EMCAL/reconstruction/src/RawReaderFile.cxx +++ /dev/null @@ -1,159 +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. -#include <array> -#include <iostream> -#include <iomanip> - -#include "EMCALBase/RCUTrailer.h" -#include "EMCALReconstruction/RawHeaderStream.h" -#include "EMCALReconstruction/RawReaderFile.h" -#include "EMCALReconstruction/RawDecodingError.h" - -using namespace o2::emcal; - -#define CHECK_BIT(var, pos) ((var) & (1 << (pos))) - -bool isStop(const o2::emcal::RAWDataHeader& hdr) -{ - return true; -} -bool isStop(const o2::header::RAWDataHeaderV4& hdr) { return hdr.stop; } - -template <class RawHeader> -RawReaderFile<RawHeader>::RawReaderFile(const std::string_view filename) : mInputFileName(filename), - mDataFile(), - mRawHeader() -{ - init(); -} -template <class RawHeader> -RawReaderFile<RawHeader>::~RawReaderFile() -{ - mDataFile.close(); -} - -template <class RawHeader> -void RawReaderFile<RawHeader>::init() -{ - mDataFile.open(mInputFileName, std::ifstream::binary); - if (!mDataFile.good()) - throw std::runtime_error("Unable to open or access file " + mInputFileName); - // get length of file in bytes - mDataFile.seekg(0, mDataFile.end); - mFileSize = mDataFile.tellg(); - mDataFile.seekg(0, mDataFile.beg); - // the file is supposed to contain N x 8kB packets. So the number of packets - // can be determined by the file-size. Ideally, this is not required but the - // information is derived directly from the header size and payload size. - // *** to be adapted to header info *** - mNumData = mFileSize / (8 * 1024); -} - -template <class RawHeader> -void RawReaderFile<RawHeader>::next() -{ - mRawPayload.reset(); - bool isDataTerminated = false; - do { - nextPage(false); - // check if we find a valid RCU trailer - // the payload must be at the end of the buffer - // if not present and error will be thrown - try { - RCUTrailer::constructFromPayloadWords(mRawBuffer.getDataWords()); - isDataTerminated = true; - } catch (...) { - } - } while (!isDataTerminated); -} - -template <class RawHeader> -void RawReaderFile<RawHeader>::nextPage(bool doResetPayload) -{ - if (mCurrentPosition >= mNumData) - throw RawDecodingError(RawDecodingError::ErrorType_t::PAGE_NOTFOUND); - if (doResetPayload) - mRawPayload.reset(); - auto start = mDataFile.tellg(); - readHeader(); - readPayload(); - mRawPayload.appendPayloadWords(mRawBuffer.getDataWords()); - mRawPayload.increasePageCount(); - mDataFile.seekg(int(start) + mRawHeader.offsetToNext); - mCurrentPosition++; -} - -template <class RawHeader> -void RawReaderFile<RawHeader>::readPage(int page) -{ - mRawHeaderInitialized = false; - mPayloadInitialized = false; - if (page >= mNumData) - throw RawDecodingError(RawDecodingError::ErrorType_t::PAGE_NOTFOUND); - mDataFile.seekg(page * 8192); - auto start = mDataFile.tellg(); - readHeader(); - readPayload(); - mDataFile.seekg(int(start) + mRawHeader.offsetToNext); - mCurrentPosition = page; -} - -template <class RawHeader> -void RawReaderFile<RawHeader>::readHeader() -{ - try { - // assume the seek is at the header position - mDataFile >> mRawHeader; - } catch (...) { - throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_DECODING); - } - mRawHeaderInitialized = true; -} - -template <class RawHeader> -void RawReaderFile<RawHeader>::readPayload() -{ - try { - // assume the seek is at the payload position - mRawBuffer.readFromStream(mDataFile, mRawHeader.memorySize - sizeof(mRawHeader)); - } catch (...) { - throw RawDecodingError(RawDecodingError::ErrorType_t::PAYLOAD_DECODING); - } - mPayloadInitialized = true; -} - -template <class RawHeader> -const RawHeader& RawReaderFile<RawHeader>::getRawHeader() const -{ - if (!mRawHeaderInitialized) - throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_INVALID); - return mRawHeader; -} - -template <class RawHeader> -const RawBuffer& RawReaderFile<RawHeader>::getRawBuffer() const -{ - if (!mPayloadInitialized) - throw RawDecodingError(RawDecodingError::ErrorType_t::PAYLOAD_INVALID); - return mRawBuffer; -} - -template <class RawHeader> -void RawReaderFile<RawHeader>::readFile(const std::string_view filename) -{ - RawReaderFile reader(filename); - for (int ipage = 0; ipage < reader.getNumberOfPages(); ipage++) { - reader.nextPage(); - std::cout << reader.getRawHeader(); - } -} - -template class o2::emcal::RawReaderFile<o2::emcal::RAWDataHeader>; -template class o2::emcal::RawReaderFile<o2::header::RAWDataHeaderV4>; \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx index d596bc564cc32..418b6261713ae 100644 --- a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx @@ -10,28 +10,39 @@ #include <sstream> #include <string> -#include "EMCALBase/RCUTrailer.h" -#include "EMCALReconstruction/RawHeaderStream.h" #include "EMCALReconstruction/RawReaderMemory.h" #include "EMCALReconstruction/RawDecodingError.h" +#include "DetectorsRaw/RDHUtils.h" using namespace o2::emcal; -template <class RawHeader> -RawReaderMemory<RawHeader>::RawReaderMemory(gsl::span<const char> rawmemory) : mRawMemoryBuffer(rawmemory) +using RDHDecoder = o2::raw::RDHUtils; + +RawReaderMemory::RawReaderMemory(gsl::span<const char> rawmemory) : mRawMemoryBuffer(rawmemory) { init(); } -template <class RawHeader> -void RawReaderMemory<RawHeader>::setRawMemory(const gsl::span<const char> rawmemory) +void RawReaderMemory::setRawMemory(const gsl::span<const char> rawmemory) { mRawMemoryBuffer = rawmemory; init(); } -template <class RawHeader> -void RawReaderMemory<RawHeader>::init() +o2::header::RDHAny RawReaderMemory::decodeRawHeader(const void* payloadwords) +{ + auto headerversion = RDHDecoder::getVersion(payloadwords); + if (headerversion == 4) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV4*>(payloadwords)); + } else if (headerversion == 5) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV5*>(payloadwords)); + } else if (headerversion == 6) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV6*>(payloadwords)); + } + throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_DECODING); +} + +void RawReaderMemory::init() { mCurrentPosition = 0; mRawHeaderInitialized = false; @@ -40,26 +51,36 @@ void RawReaderMemory<RawHeader>::init() mNumData = mRawMemoryBuffer.size() / 8192; // assume fixed 8 kB pages } -template <class RawHeader> -void RawReaderMemory<RawHeader>::next() +void RawReaderMemory::next() { mRawPayload.reset(); + mCurrentTrailer.reset(); bool isDataTerminated = false; do { nextPage(false); - // check if we find a valid RCU trailer - // the payload must be at the end of the buffer - // if not present and error will be thrown - try { - RCUTrailer::constructFromPayloadWords(mRawBuffer.getDataWords()); + if (hasNext()) { + auto nextheader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + /** + * eventually in the future check continuing payload based on the bc/orbit ID + auto currentbc = RDHDecoder::getTriggerBC(mRawHeader), + nextbc = RDHDecoder::getTriggerBC(nextheader); + auto currentorbit = RDHDecoder::getTriggerOrbit(mRawHeader), + nextorbit = RDHDecoder::getTriggerOrbit(nextheader); + **/ + auto nextpagecounter = RDHDecoder::getPageCounter(nextheader); + if (nextpagecounter == 0) { + isDataTerminated = true; + } else + isDataTerminated = false; + } else isDataTerminated = true; - } catch (...) { - } + // Check if the data continues } while (!isDataTerminated); + // add combined trailer to payload + mRawPayload.appendPayloadWords(mCurrentTrailer.encode()); } -template <class RawHeader> -void RawReaderMemory<RawHeader>::nextPage(bool doResetPayload) +void RawReaderMemory::nextPage(bool doResetPayload) { if (!hasNext()) throw RawDecodingError(RawDecodingError::ErrorType_t::PAGE_NOTFOUND); @@ -67,68 +88,71 @@ void RawReaderMemory<RawHeader>::nextPage(bool doResetPayload) mRawPayload.reset(); mRawHeaderInitialized = false; mPayloadInitialized = false; - // Use std::string stream as byte stream - std::string headerwords(mRawMemoryBuffer.data() + mCurrentPosition, sizeof(RawHeader) / sizeof(char)); - std::stringstream headerstream(headerwords); // Read header try { - headerstream >> mRawHeader; + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + RDHDecoder::printRDH(mRawHeader); mRawHeaderInitialized = true; } catch (...) { throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_DECODING); } - if (mCurrentPosition + sizeof(RawHeader) + mRawHeader.memorySize >= mRawMemoryBuffer.size()) { + if (mCurrentPosition + RDHDecoder::getMemorySize(mRawHeader) >= mRawMemoryBuffer.size()) { // Payload incomplete throw RawDecodingError(RawDecodingError::ErrorType_t::PAYLOAD_DECODING); } else { - mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + mCurrentPosition + sizeof(RawHeader), mRawHeader.memorySize)); - mRawPayload.appendPayloadWords(mRawBuffer.getDataWords()); + mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + mCurrentPosition + RDHDecoder::getHeaderSize(mRawHeader), RDHDecoder::getMemorySize(mRawHeader) - RDHDecoder::getHeaderSize(mRawHeader))); + + // Read off and chop trailer + // + // Every page gets a trailer. The trailers from the single pages need to be removed. + // There will be a combined trailer which keeps the sum of the payloads for all trailers. + // This will be appended to the chopped payload. + auto trailer = RCUTrailer::constructFromPayloadWords(mRawBuffer.getDataWords()); + if (!mCurrentTrailer.isInitialized()) { + mCurrentTrailer = trailer; + } else { + mCurrentTrailer.setPayloadSize(mCurrentTrailer.getPayloadSize() + trailer.getPayloadSize()); + } + gsl::span<const uint32_t> payloadWithoutTrailer(mRawBuffer.getDataWords().data(), mRawBuffer.getDataWords().size() - trailer.getTrailerSize()); + + mRawPayload.appendPayloadWords(payloadWithoutTrailer); mRawPayload.increasePageCount(); } - mCurrentPosition += mRawHeader.offsetToNext; /// Assume fixed 8 kB page size + mCurrentPosition += RDHDecoder::getOffsetToNext(mRawHeader); /// Assume fixed 8 kB page size } -template <class RawHeader> -void RawReaderMemory<RawHeader>::readPage(int page) +void RawReaderMemory::readPage(int page) { int currentposition = 8192 * page; if (currentposition >= mRawMemoryBuffer.size()) throw RawDecodingError(RawDecodingError::ErrorType_t::PAGE_NOTFOUND); mRawHeaderInitialized = false; mPayloadInitialized = false; - // Use std::string stream as byte stream - std::string headerwords(mRawMemoryBuffer.data() + currentposition, sizeof(RawHeader) / sizeof(char)); - std::stringstream headerstream(headerwords); // Read header try { - headerstream >> mRawHeader; + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); mRawHeaderInitialized = true; } catch (...) { throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_DECODING); } - if (currentposition + sizeof(RawHeader) + mRawHeader.memorySize >= mRawMemoryBuffer.size()) { + if (currentposition + RDHDecoder::getHeaderSize(mRawHeader) + RDHDecoder::getMemorySize(mRawHeader) >= mRawMemoryBuffer.size()) { // Payload incomplete throw RawDecodingError(RawDecodingError::ErrorType_t::PAYLOAD_DECODING); } else { - mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + currentposition + sizeof(RawHeader), mRawHeader.memorySize)); + mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + currentposition + RDHDecoder::getHeaderSize(mRawHeader), RDHDecoder::getMemorySize(mRawHeader))); } } -template <class RawHeader> -const RawHeader& RawReaderMemory<RawHeader>::getRawHeader() const +const o2::header::RDHAny& RawReaderMemory::getRawHeader() const { if (!mRawHeaderInitialized) throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_INVALID); return mRawHeader; } -template <class RawHeader> -const RawBuffer& RawReaderMemory<RawHeader>::getRawBuffer() const +const RawBuffer& RawReaderMemory::getRawBuffer() const { if (!mPayloadInitialized) throw RawDecodingError(RawDecodingError::ErrorType_t::PAYLOAD_INVALID); return mRawBuffer; } - -template class o2::emcal::RawReaderMemory<o2::emcal::RAWDataHeader>; -template class o2::emcal::RawReaderMemory<o2::header::RAWDataHeaderV4>; \ No newline at end of file diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index ab15eb00b48bf..eab0613681186 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -15,6 +15,7 @@ #include "Framework/ControlService.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "DetectorsRaw/RDHUtils.h" #include "EMCALBase/Geometry.h" #include "EMCALBase/Mapper.h" #include "EMCALReconstruction/CaloFitResults.h" @@ -59,7 +60,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) //o2::emcal::RawReaderMemory<o2::header::RAWDataHeaderV4> rawreader(gsl::span(rawData.payload, o2::framework::DataRefUtils::getPayloadSize(rawData))); - o2::emcal::RawReaderMemory<o2::header::RAWDataHeaderV4> rawreader(o2::framework::DataRefUtils::as<const char>(rawData)); + o2::emcal::RawReaderMemory rawreader(o2::framework::DataRefUtils::as<const char>(rawData)); bool first = true; uint16_t currentTrigger = 0; @@ -70,37 +71,40 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) rawreader.next(); - auto header = rawreader.getRawHeader(); + auto& header = rawreader.getRawHeader(); + auto triggerBC = o2::raw::RDHUtils::getTriggerBC(header); + auto triggerOrbit = o2::raw::RDHUtils::getTriggerOrbit(header); + auto feeID = o2::raw::RDHUtils::getFEEID(header); if (!first) { // check if it is the first event in the payload - std::cout << " triggerBC " << header.triggerBC << " current Trigger " << currentTrigger << std::endl; - if (header.triggerBC > currentTrigger) { //new event + std::cout << " triggerBC " << triggerBC << " current Trigger " << currentTrigger << std::endl; + if (triggerBC > currentTrigger) { //new event mOutputTriggerRecords.emplace_back(o2::InteractionRecord(currentTrigger, currentorbit), firstEntry, mOutputCells.size() - 1); firstEntry = mOutputCells.size(); - currentTrigger = header.triggerBC; - currentorbit = header.triggerOrbit; + currentTrigger = triggerBC; + currentorbit = triggerOrbit; } //new event } else { //first - currentTrigger = header.triggerBC; + currentTrigger = triggerBC; std::cout << " first is true and I set triggerBC to currentTrigger " << currentTrigger << std::endl; - currentorbit = header.triggerOrbit; + currentorbit = triggerOrbit; std::cout << " and set first to false " << std::endl; first = false; } - if (header.feeId > 40) + if (feeID > 40) continue; //skip STU ddl //std::cout<<rawreader.getRawHeader()<<std::endl; // use the altro decoder to decode the raw data, and extract the RCU trailer - o2::emcal::AltroDecoder<decltype(rawreader)> decoder(rawreader); + o2::emcal::AltroDecoder decoder(rawreader); decoder.decode(); std::cout << decoder.getRCUTrailer() << std::endl; - o2::emcal::Mapper map = mMapper->getMappingForDDL(header.feeId); + o2::emcal::Mapper map = mMapper->getMappingForDDL(feeID); // Loop over all the channels for (auto& chan : decoder.getChannels()) { @@ -108,7 +112,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) int iRow = map.getRow(chan.getHardwareAddress()); int iCol = map.getColumn(chan.getHardwareAddress()); ChannelType_t chantype = map.getChannelType(chan.getHardwareAddress()); - int iSM = header.feeId / 2; + int iSM = feeID / 2; int CellID = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iRow, iCol); From a4b93aee5daf7a78fac52f18daeb79f2fa4f9ef1 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Tue, 11 Aug 2020 16:48:14 +0200 Subject: [PATCH 0339/1751] TPCClusterFinder: Fix mc label propagation. --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 869f8d237522d..e8fe1b78a05f4 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1123,7 +1123,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) clusterer.mPmemory->counters.nPeaks = clusterer.mPmemory->counters.nClusters = 0; clusterer.mPmemory->fragment = fragment; - if (propagateMCLabels) { + if (propagateMCLabels && fragment.index == 0) { clusterer.PrepareMC(); clusterer.mPinputLabels = digitsMC->v[iSlice]; // TODO: Why is the number of header entries in truth container @@ -1253,6 +1253,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Lane %d: Found clusters: digits %u peaks %u clusters %u", lane, (int)clusterer.mPmemory->counters.nPositions, (int)clusterer.mPmemory->counters.nPeaks, (int)clusterer.mPmemory->counters.nClusters); } + TransferMemoryResourcesToHost(RecoStep::TPCClusterFinding, &clusterer, lane); laneHasData[lane] = true; if (DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpCountedPeaks, *mDebugFile)) { @@ -1321,6 +1322,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) static o2::dataformats::MCTruthContainer<o2::MCCompLabel> mcLabels; assert(propagateMCLabels ? mcLinearLabels.header.size() == nClsTotal : true); + assert(propagateMCLabels ? mcLinearLabels.data.size() >= nClsTotal : true); mcLabels.setFrom(mcLinearLabels.header, mcLinearLabels.data); From a6be9bf44630ae82fcf065d12d7d8ab44d4a2a51 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 12 Aug 2020 14:17:57 +0200 Subject: [PATCH 0340/1751] report original message length when printing --- .../Common/include/DetectorsCommonDataFormats/EncodedBlocks.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 267187a9b48dc..a4d6d9cac6f4d 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -656,7 +656,8 @@ void EncodedBlocks<H, N, W>::print(const std::string& prefix) const { LOG(INFO) << prefix << "Container of " << N << " blocks, size: " << size() << " bytes, unused: " << getFreeSize(); for (int i = 0; i < N; i++) { - LOG(INFO) << "Block " << i << " NDictWords: " << mBlocks[i].getNDict() << " NDataWords: " << mBlocks[i].getNData() + LOG(INFO) << "Block " << i << " for " << mMetadata[i].messageLength << " message words |" + << " NDictWords: " << mBlocks[i].getNDict() << " NDataWords: " << mBlocks[i].getNData() << " NLiteralWords: " << mBlocks[i].getNLiterals(); } } @@ -704,7 +705,6 @@ void EncodedBlocks<H, N, W>::decode(D* dest, // destination throw std::runtime_error("Mismatch between min/max symbols in metadata and those in external decoder"); } } - // load incompressible symbols if they existed std::vector<D> literals; if (block.getNLiterals()) { From 1c3a90bd73f618e4ee2ffb1bf4806559f01bed46 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 12 Aug 2020 14:19:18 +0200 Subject: [PATCH 0341/1751] CTFCoderBase will hold detectorID --- Detectors/Base/include/DetectorsBase/CTFCoderBase.h | 13 ++++++++----- Detectors/Base/src/CTFCoderBase.cxx | 12 ++++++------ Detectors/CTF/test/test_ctf_io_itsmft.cxx | 4 ++-- .../include/FT0Reconstruction/CTFCoder.h | 5 +++-- Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx | 6 +++--- .../include/ITSMFTReconstruction/CTFCoder.h | 11 ++++++----- .../ITSMFT/common/reconstruction/src/CTFCoder.cxx | 13 ++++++------- .../common/workflow/src/EntropyDecoderSpec.cxx | 6 +++--- .../common/workflow/src/EntropyEncoderSpec.cxx | 6 +++--- .../include/TOFReconstruction/CTFCoder.h | 10 ++++++---- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 11 +++++------ .../include/TPCReconstruction/CTFCoder.h | 6 +++--- Detectors/TPC/reconstruction/src/CTFCoder.cxx | 2 +- 13 files changed, 55 insertions(+), 50 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/CTFCoderBase.h b/Detectors/Base/include/DetectorsBase/CTFCoderBase.h index 031f4049d2072..8cf0e02639e04 100644 --- a/Detectors/Base/include/DetectorsBase/CTFCoderBase.h +++ b/Detectors/Base/include/DetectorsBase/CTFCoderBase.h @@ -40,18 +40,18 @@ class CTFCoderBase Decoder }; CTFCoderBase() = delete; - CTFCoderBase(int n) : mCoders(n) {} + CTFCoderBase(int n, DetID det) : mCoders(n), mDet(det) {} - std::unique_ptr<TFile> loadDictionaryTreeFile(const std::string& dictPath, DetID det, bool mayFail = false); + std::unique_ptr<TFile> loadDictionaryTreeFile(const std::string& dictPath, bool mayFail = false); template <typename CTF> - std::vector<char> readDictionaryFromFile(const std::string& dictPath, DetID det, bool mayFail = false) + std::vector<char> readDictionaryFromFile(const std::string& dictPath, bool mayFail = false) { std::vector<char> bufVec; - auto fileDict = loadDictionaryTreeFile(dictPath, det, mayFail); + auto fileDict = loadDictionaryTreeFile(dictPath, mayFail); if (fileDict) { std::unique_ptr<TTree> tree((TTree*)fileDict->Get(std::string(o2::base::NameConf::CTFDICT).c_str())); - CTF::readFromTree(bufVec, *tree.get(), det.getName()); + CTF::readFromTree(bufVec, *tree.get(), mDet.getName()); } return bufVec; } @@ -74,7 +74,10 @@ class CTFCoderBase } protected: + std::string getPrefix() const { return o2::utils::concat_string(mDet.getName(), "_CTF: "); } + std::vector<std::shared_ptr<void>> mCoders; // encoders/decoders + DetID mDet; ClassDefNV(CTFCoderBase, 1); }; diff --git a/Detectors/Base/src/CTFCoderBase.cxx b/Detectors/Base/src/CTFCoderBase.cxx index 57ae2214ac782..a5e7ff0ed92e8 100644 --- a/Detectors/Base/src/CTFCoderBase.cxx +++ b/Detectors/Base/src/CTFCoderBase.cxx @@ -31,17 +31,17 @@ bool readFromTree(TTree& tree, const std::string brname, T& dest, int ev = 0) return false; } -std::unique_ptr<TFile> CTFCoderBase::loadDictionaryTreeFile(const std::string& dictPath, DetID det, bool mayFail) +std::unique_ptr<TFile> CTFCoderBase::loadDictionaryTreeFile(const std::string& dictPath, bool mayFail) { TDirectory* curd = gDirectory; std::unique_ptr<TFile> fileDict(TFile::Open(dictPath.c_str())); if (!fileDict || fileDict->IsZombie()) { if (mayFail) { - LOG(INFO) << "CTF dictionary file " << dictPath << " for detector " << det.getName() << " is absent, will use dictionaries stored in CTF"; + LOG(INFO) << "CTF dictionary file " << dictPath << " for detector " << mDet.getName() << " is absent, will use dictionaries stored in CTF"; fileDict.reset(); return std::move(fileDict); } - LOG(ERROR) << "Failed to open CTF dictionary file " << dictPath << " for detector " << det.getName(); + LOG(ERROR) << "Failed to open CTF dictionary file " << dictPath << " for detector " << mDet.getName(); throw std::runtime_error("Failed to open dictionary file"); } auto tnm = std::string(o2::base::NameConf::CTFDICT); @@ -52,15 +52,15 @@ std::unique_ptr<TFile> CTFCoderBase::loadDictionaryTreeFile(const std::string& d throw std::runtime_error("Did not fine CTF dictionary tree in the file"); } CTFHeader ctfHeader; - if (!readFromTree(*tree.get(), "CTFHeader", ctfHeader) || !ctfHeader.detectors[det]) { + if (!readFromTree(*tree.get(), "CTFHeader", ctfHeader) || !ctfHeader.detectors[mDet]) { tree.reset(); fileDict.reset(); - LOG(ERROR) << "Did not find CTF dictionary header or Detector " << det.getName() << " in it"; + LOG(ERROR) << "Did not find CTF dictionary header or Detector " << mDet.getName() << " in it"; if (!mayFail) { throw std::runtime_error("did not find CTFHeader with needed detector"); } } else { - LOG(INFO) << "Found CTF dictionary for " << det.getName() << " in " << dictPath; + LOG(INFO) << "Found CTF dictionary for " << mDet.getName() << " in " << dictPath; } return fileDict; } diff --git a/Detectors/CTF/test/test_ctf_io_itsmft.cxx b/Detectors/CTF/test/test_ctf_io_itsmft.cxx index 262e446d403ff..ad67d55574d0e 100644 --- a/Detectors/CTF/test/test_ctf_io_itsmft.cxx +++ b/Detectors/CTF/test/test_ctf_io_itsmft.cxx @@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(CompressedClustersTest) sw.Start(); std::vector<o2::ctf::BufferType> vec; { - CTFCoder coder; + CTFCoder coder(o2::detectors::DetID::ITS); coder.encode(vec, rofRecVec, cclusVec, pattVec); // compress } sw.Stop(); @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(CompressedClustersTest) sw.Start(); const auto ctfImage = o2::itsmft::CTF::getImage(vec.data()); { - CTFCoder coder; + CTFCoder coder(o2::detectors::DetID::ITS); coder.decode(ctfImage, rofRecVecD, cclusVecD, pattVecD); // decompress } sw.Stop(); diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index e0646846a7202..2c1941cbf5160 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -36,7 +36,7 @@ namespace ft0 class CTFCoder : public o2::ctf::CTFCoderBase { public: - CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::FT0) {} ~CTFCoder() = default; /// entropy-encode digits to buffer with CTF @@ -101,7 +101,7 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g ENCODEFT0(cd.cfdTime, CTF::BLC_cfdTime, o2::rans::ProbabilityBits16Bit); ENCODEFT0(cd.qtcAmpl, CTF::BLC_qtcAmpl, o2::rans::ProbabilityBits25Bit); // clang-format on - CTF::get(buff.data())->print("FT0 done: "); + CTF::get(buff.data())->print(getPrefix()); } /// decode entropy-encoded clusters to standard compact clusters @@ -110,6 +110,7 @@ void CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec) { CompressedDigits cd; cd.header = ec.getHeader(); + ec.print(getPrefix()); #define DECODEFT0(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off DECODEFT0(cd.trigger, CTF::BLC_trigger); diff --git a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx index ea6181aa9881e..eb568cc84b5dc 100644 --- a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx @@ -22,7 +22,7 @@ using namespace o2::ft0; // Register encoded data in the tree (Fill is not called, will be done by caller) void CTFCoder::appendToTree(TTree& tree, CTF& ec) { - ec.appendToTree(tree, o2::detectors::DetID::getName(o2::detectors::DetID::FT0)); + ec.appendToTree(tree, mDet.getName()); } ///___________________________________________________________________________________ @@ -32,7 +32,7 @@ void CTFCoder::readFromTree(TTree& tree, int entry, { assert(entry >= 0 && entry < tree.GetEntries()); CTF ec; - ec.readFromTree(tree, o2::detectors::DetID::getName(o2::detectors::DetID::FT0), entry); + ec.readFromTree(tree, mDet.getName(), entry); decode(ec, digitVec, channelVec); } @@ -100,7 +100,7 @@ void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digi void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) { bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception - auto buff = readDictionaryFromFile<CTF>(dictPath, o2::detectors::DetID::FT0, mayFail); + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); if (!buff.size()) { if (mayFail) { return; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h index fa894ca6e4aa1..8332891cb52f3 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h @@ -35,7 +35,7 @@ namespace itsmft class CTFCoder : public o2::ctf::CTFCoderBase { public: - CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + CTFCoder(o2::detectors::DetID det) : o2::ctf::CTFCoderBase(CTF::getNBlocks(), det) {} ~CTFCoder() = default; /// entropy-encode clusters to buffer with CTF @@ -46,7 +46,7 @@ class CTFCoder : public o2::ctf::CTFCoderBase template <typename VROF, typename VCLUS, typename VPAT> void decode(const CTF::base& ec, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec); - void createCoders(const std::string& dictPath, o2::detectors::DetID det, o2::ctf::CTFCoderBase::OpType op); + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); private: /// compres compact clusters to CompressedClusters @@ -56,8 +56,8 @@ class CTFCoder : public o2::ctf::CTFCoderBase template <typename VROF, typename VCLUS, typename VPAT> void decompress(const CompressedClusters& cc, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec); - void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); - void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ROFRecord>& rofRecVec, std::vector<CompClusterExt>& cclusVec, std::vector<unsigned char>& pattVec); + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<ROFRecord>& rofRecVec, std::vector<CompClusterExt>& cclusVec, std::vector<unsigned char>& pattVec); protected: ClassDefNV(CTFCoder, 1); @@ -104,7 +104,7 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ROFRecord>& rofRecVec, co ENCODEITSMFT(cc.pattID, CTF::BLCpattID, o2::rans::ProbabilityBits16Bit); ENCODEITSMFT(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit); // clang-format on - CTF::get(buff.data())->print("ITS done: "); + CTF::get(buff.data())->print(getPrefix()); } /// decode entropy-encoded clusters to standard compact clusters @@ -113,6 +113,7 @@ void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VCLUS& cclusVec, VPA { CompressedClusters cc; cc.header = ec.getHeader(); + ec.print(getPrefix()); #define DECODEITSMFT(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off DECODEITSMFT(cc.firstChipROF, CTF::BLCfirstChipROF); diff --git a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx index 9061422d121f5..d1a722950cd90 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx @@ -20,19 +20,18 @@ using namespace o2::itsmft; ///___________________________________________________________________________________ // Register encoded data in the tree (Fill is not called, will be done by caller) -void CTFCoder::appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) { - ec.appendToTree(tree, id.getName()); + ec.appendToTree(tree, mDet.getName()); } ///___________________________________________________________________________________ // extract and decode data from the tree -void CTFCoder::readFromTree(TTree& tree, int entry, o2::detectors::DetID id, - std::vector<ROFRecord>& rofRecVec, std::vector<CompClusterExt>& cclusVec, std::vector<unsigned char>& pattVec) +void CTFCoder::readFromTree(TTree& tree, int entry, std::vector<ROFRecord>& rofRecVec, std::vector<CompClusterExt>& cclusVec, std::vector<unsigned char>& pattVec) { assert(entry >= 0 && entry < tree.GetEntries()); CTF ec; - ec.readFromTree(tree, id.getName(), entry); + ec.readFromTree(tree, mDet.getName(), entry); decode(ec, rofRecVec, cclusVec, pattVec); } @@ -121,10 +120,10 @@ void CTFCoder::compress(CompressedClusters& cc, } ///________________________________ -void CTFCoder::createCoders(const std::string& dictPath, o2::detectors::DetID det, o2::ctf::CTFCoderBase::OpType op) +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) { bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception - auto buff = readDictionaryFromFile<CTF>(dictPath, det, mayFail); + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); if (!buff.size()) { if (mayFail) { return; diff --git a/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx index 7726485043400..ffd61641dfd4b 100644 --- a/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx @@ -24,7 +24,8 @@ namespace o2 namespace itsmft { -EntropyDecoderSpec::EntropyDecoderSpec(o2::header::DataOrigin orig) : mOrigin(orig) +EntropyDecoderSpec::EntropyDecoderSpec(o2::header::DataOrigin orig) + : mOrigin(orig), mCTFCoder(orig == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT) { assert(orig == o2::header::gDataOriginITS || orig == o2::header::gDataOriginMFT); mTimer.Stop(); @@ -35,8 +36,7 @@ void EntropyDecoderSpec::init(o2::framework::InitContext& ic) { std::string dictPath = ic.options().get<std::string>((mOrigin == o2::header::gDataOriginITS) ? "its-ctf-dictionary" : "mft-ctf-dictionary"); if (!dictPath.empty() && dictPath != "none") { - mCTFCoder.createCoders(dictPath, mOrigin == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT, - o2::ctf::CTFCoderBase::OpType::Decoder); + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); } } diff --git a/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx index 38e8efbb03854..cb9af0129f9ab 100644 --- a/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx @@ -25,7 +25,8 @@ namespace o2 namespace itsmft { -EntropyEncoderSpec::EntropyEncoderSpec(o2::header::DataOrigin orig) : mOrigin(orig) +EntropyEncoderSpec::EntropyEncoderSpec(o2::header::DataOrigin orig) + : mOrigin(orig), mCTFCoder(orig == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT) { assert(orig == o2::header::gDataOriginITS || orig == o2::header::gDataOriginMFT); mTimer.Stop(); @@ -36,8 +37,7 @@ void EntropyEncoderSpec::init(o2::framework::InitContext& ic) { std::string dictPath = ic.options().get<std::string>((mOrigin == o2::header::gDataOriginITS) ? "its-ctf-dictionary" : "mft-ctf-dictionary"); if (!dictPath.empty() && dictPath != "none") { - mCTFCoder.createCoders(dictPath, mOrigin == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT, - o2::ctf::CTFCoderBase::OpType::Encoder); + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); } } diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index 90bcdafa1e2f7..671e35a414ca2 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -34,7 +34,7 @@ namespace tof class CTFCoder : public o2::ctf::CTFCoderBase { public: - CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::TOF) {} ~CTFCoder() = default; /// entropy-encode clusters to buffer with CTF @@ -55,8 +55,8 @@ class CTFCoder : public o2::ctf::CTFCoderBase template <typename VROF, typename VDIG, typename VPAT> void decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); - void appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec); - void readFromTree(TTree& tree, int entry, o2::detectors::DetID id, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec); + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec); protected: ClassDefNV(CTFCoder, 1); @@ -103,14 +103,16 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRe ENCODETOF(cc.tot, CTF::BLCtot, o2::rans::ProbabilityBits16Bit); ENCODETOF(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit); // clang-format on - CTF::get(buff.data())->print("TOF done: "); + CTF::get(buff.data())->print(getPrefix()); } + ///___________________________________________________________________________________ /// decode entropy-encoded digits to standard compact digits template <typename VROF, typename VDIG, typename VPAT> void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec) { CompressedInfos cc; + ec.print(getPrefix()); cc.header = ec.getHeader(); #define DECODETOF(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index bb04d33a1b049..26eb4473e706a 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -20,19 +20,18 @@ using namespace o2::tof; ///___________________________________________________________________________________ // Register encoded data in the tree (Fill is not called, will be done by caller) -void CTFCoder::appendToTree(TTree& tree, o2::detectors::DetID id, CTF& ec) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) { - ec.appendToTree(tree, id.getName()); + ec.appendToTree(tree, mDet.getName()); } ///___________________________________________________________________________________ // extract and decode data from the tree -void CTFCoder::readFromTree(TTree& tree, int entry, o2::detectors::DetID id, - std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec) +void CTFCoder::readFromTree(TTree& tree, int entry, std::vector<ReadoutWindowData>& rofRecVec, std::vector<Digit>& cdigVec, std::vector<uint32_t>& pattVec) { assert(entry >= 0 && entry < tree.GetEntries()); CTF ec; - ec.readFromTree(tree, id.getName(), entry); + ec.readFromTree(tree, mDet.getName(), entry); decode(ec, rofRecVec, cdigVec, pattVec); } @@ -150,7 +149,7 @@ void CTFCoder::compress(CompressedInfos& cc, void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) { bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception - auto buff = readDictionaryFromFile<CTF>(dictPath, o2::detectors::DetID::TOF, mayFail); + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); if (!buff.size()) { if (mayFail) { return; diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h index cad0dbfa5c15c..417f3d4572cfe 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h @@ -34,7 +34,7 @@ namespace tpc class CTFCoder : public o2::ctf::CTFCoderBase { public: - CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks()) {} + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::TPC) {} ~CTFCoder() = default; /// entropy-encode compressed clusters to flat buffer @@ -134,7 +134,7 @@ void CTFCoder::encode(VEC& buff, const CompressedClusters& ccl) ENCODETPC(ccl.nTrackClusters, ccl.nTrackClusters + ccl.nTracks, CTF::BLCnTrackClusters, o2::rans::ProbabilityBits16Bit); ENCODETPC(ccl.nSliceRowClusters, ccl.nSliceRowClusters + ccl.nSliceRows, CTF::BLCnSliceRowClusters, o2::rans::ProbabilityBits25Bit); // clang-format on - CTF::get(buff.data())->print("TPC done: "); + CTF::get(buff.data())->print(getPrefix()); } /// decode entropy-encoded bloks to TPC CompressedClusters into the externally provided vector (e.g. PMR vector from DPL) @@ -154,7 +154,7 @@ void CTFCoder::decode(const CTF::base& ec, VEC& buffVec) setCompClusAddresses(cc, buff); ccFlat->set(sz, cc); // set offsets - + ec.print(getPrefix()); // decode encoded data directly to destination buff #define DECODETPC(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off diff --git a/Detectors/TPC/reconstruction/src/CTFCoder.cxx b/Detectors/TPC/reconstruction/src/CTFCoder.cxx index b38858aae407c..81c4e6206ebc3 100644 --- a/Detectors/TPC/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TPC/reconstruction/src/CTFCoder.cxx @@ -91,7 +91,7 @@ void CTFCoder::setCompClusAddresses(CompressedClusters& c, void*& buff) void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) { bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception - auto buff = readDictionaryFromFile<CTF>(dictPath, o2::detectors::DetID::TPC, mayFail); + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); if (!buff.size()) { if (mayFail) { return; From 7655b1f2baa270d7108635a0df8fca2ccb01945e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 12 Aug 2020 21:15:15 +0200 Subject: [PATCH 0342/1751] Fix in size estimate for CTF dictionary --- .../include/DetectorsCommonDataFormats/EncodedBlocks.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index a4d6d9cac6f4d..67282507502c9 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -832,16 +832,15 @@ std::vector<char> EncodedBlocks<H, N, W>::createDictionaryBlocks(const std::vect if (vfreq.size() != N) { throw std::runtime_error("mismatch between the size of frequencies vector and number of blocks"); } - size_t sz = sizeof(EncodedBlocks<H, N, W>); + size_t sz = alignSize(sizeof(EncodedBlocks<H, N, W>)); for (int ib = 0; ib < N; ib++) { - LOG(INFO) << "bl " << ib << " sz= " << vfreq[ib].size() << " min/max " << vfreq[ib].getMinSymbol() << "/" << vfreq[ib].getMaxSymbol(); sz += Block<W>::estimateSize(vfreq[ib].size()); } std::vector<char> vdict(sz); // memory space for dictionary auto dictBlocks = create(vdict.data(), sz); for (int ib = 0; ib < N; ib++) { if (vfreq[ib].size()) { - LOG(INFO) << "adding dict of size " << vfreq[ib].size() << " for block " << ib; + LOG(INFO) << "adding dictionary of " << vfreq[ib].size() << " words for block " << ib << ", min/max= " << vfreq[ib].getMinSymbol() << "/" << vfreq[ib].getMaxSymbol(); dictBlocks->mBlocks[ib].storeDict(vfreq[ib].size(), vfreq[ib].data()); dictBlocks = get(vdict.data()); // !!! rellocation might have invalidated dictBlocks pointer dictBlocks->mMetadata[ib] = vmd[ib]; From f2594604cf44ddae02375e09b6cd39c4db86b433 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 12 Aug 2020 21:15:55 +0200 Subject: [PATCH 0343/1751] throw exception if CTF dict. creation is asked but it already exists --- .../include/CTFWorkflow/CTFWriterSpec.h | 7 +--- Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 40 +++++++++++++++++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h index 753c69ca3b71f..7569c667d4576 100644 --- a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h +++ b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h @@ -40,11 +40,7 @@ class CTFWriterSpec : public o2::framework::Task { public: CTFWriterSpec() = delete; - CTFWriterSpec(DetID::mask_t dm, uint64_t r = 0, bool doCTF = true, bool doDict = false, bool dictPerDet = false) : mDets(dm), mRun(r), mWriteCTF(doCTF), mCreateDict(doDict), mDictPerDetector(dictPerDet) - { - mTimer.Stop(); - mTimer.Reset(); - } + CTFWriterSpec(DetID::mask_t dm, uint64_t r = 0, bool doCTF = true, bool doDict = false, bool dictPerDet = false); ~CTFWriterSpec() override = default; void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; @@ -59,6 +55,7 @@ class CTFWriterSpec : public o2::framework::Task void storeDictionaries(); void prepareDictionaryTreeAndFile(DetID det); void closeDictionaryTreeAndFile(CTFHeader& header); + std::string dictionaryFileName(const std::string& detName = ""); DetID::mask_t mDets; // detectors bool mWriteCTF = false; diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 787a8630ffada..f04ece2038a8e 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -13,6 +13,7 @@ #include <vector> #include <TFile.h> #include <TTree.h> +#include <TSystem.h> #include "Framework/Logger.h" #include "Framework/ControlService.h" @@ -45,6 +46,28 @@ void appendToTree(TTree& tree, const std::string brname, T& ptr) br->ResetAddress(); } +CTFWriterSpec::CTFWriterSpec(DetID::mask_t dm, uint64_t r, bool doCTF, bool doDict, bool dictPerDet) + : mDets(dm), mRun(r), mWriteCTF(doCTF), mCreateDict(doDict), mDictPerDetector(dictPerDet) +{ + mTimer.Stop(); + mTimer.Reset(); + + if (doDict) { // make sure that there is no local dictonary + for (int id = 0; id < DetID::nDetectors; id++) { + DetID det(id); + if (isPresent(det)) { + auto dictName = dictionaryFileName(det.getName()); + if (gSystem->AccessPathName(dictName.c_str()) == 0) { + throw std::runtime_error(o2::utils::concat_string("CTF dictionary creation is requested but ", dictName, " already exists, remove it!")); + } + if (!mDictPerDetector) { + break; // no point in checking further + } + } + } + } +} + void CTFWriterSpec::init(InitContext& ic) { mSaveDictAfter = ic.options().get<int>("save-dict-after"); @@ -112,12 +135,23 @@ void CTFWriterSpec::prepareDictionaryTreeAndFile(DetID det) } } if (!mDictTreeOut) { - std::string fnm = mDictPerDetector ? o2::utils::concat_string(det.getName(), "_", o2::base::NameConf::CTFDICT, ".root") : o2::utils::concat_string(o2::base::NameConf::CTFDICT, ".root"); - mDictFileOut.reset(TFile::Open(fnm.c_str(), "recreate")); + mDictFileOut.reset(TFile::Open(dictionaryFileName(det.getName()).c_str(), "recreate")); mDictTreeOut = std::make_unique<TTree>(std::string(o2::base::NameConf::CTFDICT).c_str(), "O2 CTF dictionary"); } } +std::string CTFWriterSpec::dictionaryFileName(const std::string& detName) +{ + if (mDictPerDetector) { + if (detName.empty()) { + throw std::runtime_error("Per-detector dictionary files are requested but detector name is not provided"); + } + return o2::utils::concat_string(detName, "_", o2::base::NameConf::CTFDICT, ".root"); + } else { + return o2::utils::concat_string(o2::base::NameConf::CTFDICT, ".root"); + } +} + void CTFWriterSpec::storeDictionaries() { CTFHeader header{mRun, uint32_t(mNTF)}; @@ -147,7 +181,7 @@ void CTFWriterSpec::closeDictionaryTreeAndFile(CTFHeader& header) DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, uint64_t run, bool doCTF, bool doDict, bool dictPerDet) { std::vector<InputSpec> inputs; - LOG(INFO) << "Det list:"; + LOG(INFO) << "Detectors list:"; for (auto id = DetID::First; id <= DetID::Last; id++) { if (dets[id]) { inputs.emplace_back(DetID::getName(id), DetID::getDataOrigin(id), "CTFDATA", 0, Lifetime::Timeframe); From 0aba5abae2e719f189519572d7370bedb371b699 Mon Sep 17 00:00:00 2001 From: arvindkhuntia <akhuntia@cern.ch> Date: Mon, 11 May 2020 13:53:33 +0200 Subject: [PATCH 0344/1751] [FV0] RAW converter --- DataFormats/Detectors/FIT/FV0/CMakeLists.txt | 8 +- .../FIT/FV0/include/DataFormatsFV0/BCData.h | 1 + .../FV0/include/DataFormatsFV0/LookUpTable.h | 116 +++++++++++ .../FV0/include/DataFormatsFV0/RawEventData.h | 175 +++++++++++++++++ .../FIT/FV0/src/DataFormatsFV0LinkDef.h | 6 + .../Detectors/FIT/FV0/src/RawEventData.cxx | 71 +++++++ Detectors/FIT/FV0/CMakeLists.txt | 1 + Detectors/FIT/FV0/base/CMakeLists.txt | 7 +- .../FIT/FV0/base/include/FV0Base/Constants.h | 36 ++++ .../FIT/FV0/base/include/FV0Base/Geometry.h | 23 ++- Detectors/FIT/FV0/base/src/Geometry.cxx | 10 +- Detectors/FIT/FV0/macro/CMakeLists.txt | 1 + Detectors/FIT/FV0/macro/readFV0Digits.C | 15 +- .../FIT/FV0/reconstruction/CMakeLists.txt | 22 +++ .../include/FV0Reconstruction/ReadRaw.h | 67 +++++++ .../src/FV0ReconstructionLinkDef.h | 19 ++ .../FIT/FV0/reconstruction/src/ReadRaw.cxx | 167 ++++++++++++++++ Detectors/FIT/FV0/simulation/CMakeLists.txt | 25 ++- .../FV0Simulation/DigitizationConstant.h | 1 - .../include/FV0Simulation/Digitizer.h | 9 +- .../include/FV0Simulation/Digits2Raw.h | 68 +++++++ .../FIT/FV0/simulation/src/Digitizer.cxx | 9 +- .../FIT/FV0/simulation/src/Digits2Raw.cxx | 184 ++++++++++++++++++ .../FV0/simulation/src/FV0SimulationLinkDef.h | 1 + .../FIT/FV0/simulation/src/digit2raw.cxx | 114 +++++++++++ 25 files changed, 1122 insertions(+), 34 deletions(-) create mode 100644 DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/LookUpTable.h create mode 100644 DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h create mode 100644 DataFormats/Detectors/FIT/FV0/src/RawEventData.cxx create mode 100644 Detectors/FIT/FV0/base/include/FV0Base/Constants.h create mode 100644 Detectors/FIT/FV0/reconstruction/CMakeLists.txt create mode 100644 Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/ReadRaw.h create mode 100644 Detectors/FIT/FV0/reconstruction/src/FV0ReconstructionLinkDef.h create mode 100644 Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx create mode 100644 Detectors/FIT/FV0/simulation/include/FV0Simulation/Digits2Raw.h create mode 100644 Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx create mode 100644 Detectors/FIT/FV0/simulation/src/digit2raw.cxx diff --git a/DataFormats/Detectors/FIT/FV0/CMakeLists.txt b/DataFormats/Detectors/FIT/FV0/CMakeLists.txt index 23d4c88ae6b5d..713fb1b3dbaba 100644 --- a/DataFormats/Detectors/FIT/FV0/CMakeLists.txt +++ b/DataFormats/Detectors/FIT/FV0/CMakeLists.txt @@ -12,11 +12,15 @@ o2_add_library(DataFormatsFV0 SOURCES src/Hit.cxx src/ChannelData.cxx src/BCData.cxx - PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat + src/RawEventData.cxx + PUBLIC_LINK_LIBRARIES O2::FV0Base + O2::SimulationDataFormat O2::CommonDataFormat ms_gsl::ms_gsl) o2_target_root_dictionary(DataFormatsFV0 HEADERS include/DataFormatsFV0/Hit.h include/DataFormatsFV0/BCData.h - include/DataFormatsFV0/ChannelData.h) + include/DataFormatsFV0/ChannelData.h + include/DataFormatsFV0/RawEventData.h + include/DataFormatsFV0/LookUpTable.h) diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h index a1ef3a810340a..238ddf2551072 100644 --- a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h @@ -40,6 +40,7 @@ struct BCData { } gsl::span<const ChannelData> getBunchChannelData(const gsl::span<const ChannelData> tfdata) const; + const o2::InteractionRecord& getIntRecord() const { return ir; }; void print() const; ClassDefNV(BCData, 1); diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/LookUpTable.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/LookUpTable.h new file mode 100644 index 0000000000000..d87375bacde84 --- /dev/null +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/LookUpTable.h @@ -0,0 +1,116 @@ +// 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 RawEventData.h class for RAW data format +// Alla.Maevskaya +// simple look-up table just to feed digits 2 raw procedure. +//Will be really set after module/electronics connections +// +#ifndef ALICEO2_FV0_LOOKUPTABLE_H_ +#define ALICEO2_FV0_LOOKUPTABLE_H_ +//////////////////////////////////////////////// +// Look Up Table FV0 +////////////////////////////////////////////// + +#include <Rtypes.h> +#include <cassert> +#include <iostream> +#include <iomanip> // std::setfill, std::setw - for stream formating +#include <Framework/Logger.h> +#include "FV0Base/Constants.h" + +namespace o2 +{ +namespace fv0 +{ + +struct Topo { + int pmLink = 0; // Number of Processing Module, associated with GBT link ID + int pmCh = 0; // Channel within the Processing Module in range from 0-11 + ClassDefNV(Topo, 1); +}; + +inline bool operator<(Topo const& a, Topo const& b) +{ + return (a.pmLink < b.pmLink || (a.pmLink == b.pmLink && a.pmCh < b.pmCh)); +} + +class LookUpTable +{ + public: + /// + /// Default constructor. + /// It must be kept public for root persistency purposes, + /// but should never be called by the outside world + LookUpTable() = default; + ~LookUpTable() = default; + + explicit LookUpTable(bool fillLinearly) + : mTopoVector(Constants::nPms * Constants::nChannelsPerPm, {0, 0}), + mInvTopo(mTopoVector.size(), 0) + { + if (fillLinearly) { + LOG(INFO) << "Mapping of global channel and (PM, PM channel) pair"; + for (int link = 0; link < Constants::nPms; ++link) { + for (int ch = 0; ch < Constants::nChannelsPerPm; ++ch) { + mTopoVector[link * Constants::nChannelsPerPm + ch] = o2::fv0::Topo{link, ch}; + } + } + } else { + // TODO: If needed: implement more realistic splitting: 1 ring -> 1 PM instead of linear + LOG(WARNING) << "Don't use it - not implemented yet."; + } + + // Fill inverted LUT - matters only if LUT is not linear + for (size_t channel = 0; channel < mTopoVector.size(); ++channel) { + mInvTopo[getIdx(mTopoVector[channel].pmLink, mTopoVector[channel].pmCh)] = channel; + } + } + + int getChannel(int link, int mcp) const { return mInvTopo[getIdx(link, mcp)]; } + int getLink(int channel) const { return mTopoVector[channel].pmLink; } + int getPmChannel(int channel) const { return mTopoVector[channel].pmCh; } + int getTcmLink() const { return mLinkTCM; } + void printFullMap() const + { + std::cout << "o2::fv0::LookUpTable::printFullMap(): mTopoVector: [globalCh link pmCh]" << std::endl; + for (size_t channel = 0; channel < mTopoVector.size(); ++channel) { + std::cout << " " << std::right << std::setw(2) << channel << " "; + std::cout << std::right << std::setw(2) << mTopoVector[channel].pmLink << " "; + std::cout << std::right << std::setw(3) << mTopoVector[channel].pmCh << std::endl; + } + std::cout << "o2::fv0::LookUpTable::printFullMap(): mInvTopo: [idx globalCh link pmCh]" << std::endl; + for (size_t idx = 0; idx < mInvTopo.size(); ++idx) { + std::cout << " " << std::right << std::setw(3) << idx << " "; + std::cout << std::right << std::setw(3) << mInvTopo[idx] << " "; + std::cout << std::right << std::setw(2) << getLinkFromIdx(mInvTopo[idx]) << " "; + std::cout << std::right << std::setw(2) << getPmChannelFromIdx(mInvTopo[idx]) << std::endl; + } + } + + private: + std::vector<Topo> mTopoVector; // iterator of each vector element gives the global channel number + std::vector<int> mInvTopo; // each element is an iterator of mTopoVector + static constexpr int mLinkTCM = Constants::nPms; + + static int getIdx(int link, int pmCh) + { + assert(pmCh < Constants::nChannelsPerPm); + return link * Constants::nChannelsPerPm + pmCh; + } + static int getLinkFromIdx(int idx) { return idx / Constants::nChannelsPerPm; } + static int getPmChannelFromIdx(int idx) { return idx % Constants::nChannelsPerPm; } + + ClassDefNV(LookUpTable, 1); +}; + +} // namespace fv0 +} // namespace o2 +#endif diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h new file mode 100644 index 0000000000000..e7eecc7948cca --- /dev/null +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h @@ -0,0 +1,175 @@ +// 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. +// +// Based on the FT0 file RawEventData.h (almost identical except additional printing) by +// Alla.Maevskaya@cern.ch +// with Artur.Furs +// +#ifndef ALICEO2_FV0_RAWEVENTDATA_H_ +#define ALICEO2_FV0_RAWEVENTDATA_H_ + +#include "FV0Base/Constants.h" +#include "DataFormatsFV0/ChannelData.h" +#include "Headers/RAWDataHeader.h" +#include "DataFormatsFV0/LookUpTable.h" +#include <CommonDataFormat/InteractionRecord.h> +#include <Framework/Logger.h> +#include <iostream> +#include <iomanip> +#include <cstring> +#include "Rtypes.h" + +namespace o2 +{ +namespace fv0 +{ +struct EventHeader { + static constexpr int PayloadSize = 16; + union { + uint64_t word[2] = {}; + struct { + uint64_t bc : 12; + uint64_t orbit : 32; + uint64_t reservedField1 : 20; + uint64_t reservedField2 : 8; + uint64_t nGBTWords : 4; + uint64_t startDescriptor : 4; + uint64_t reservedField3 : 48; + }; + }; +}; +struct EventData { + union { + uint64_t word = {0}; + struct { + int64_t time : 12; + int64_t charge : 13; + uint64_t numberADC : 1, + isDoubleEvent : 1, + is1TimeLostEvent : 1, + is2TimeLostEvent : 1, + isADCinGate : 1, + isTimeInfoLate : 1, + isAmpHigh : 1, + isEventInTVDC : 1, + isTimeInfoLost : 1, + reservedField : 2, + channelID : 4; + }; + }; + uint64_t word_zeros = 0x0; + static const size_t PayloadSizeSecondWord = 11; + static const size_t PayloadSizeFirstWord = 5; +}; + +struct TCMdata { + static constexpr int PayloadSize = 16; + union { + uint64_t word[2] = {0}; + struct { + uint64_t orC : 1, + orA : 1, + sCen : 1, + cen : 1, + vertex : 1, + nChanA : 7, + nChanC : 7; + int64_t amplA : 18, + amplC : 18, + reservedField1 : 1, //56B, PayloadSize1stWord 6 + timeA : 9, + timeC : 9, + reservedField2 : 46; + }; + }; +}; + +class RawEventData +{ + public: + RawEventData() = default; + EventHeader* getEventHeaderPtr() { return &mEventHeader; } + EventData* getEventDataPtr() { return mEventData; } + void print(); + void printHexEventHeader(); + void printHexEventData(uint64_t i); + enum EEventDataBit { kNumberADC, + kIsDoubleEvent, + kIs1TimeLostEvent, + kIs2TimeLostEvent, + kIsADCinGate, + kIsTimeInfoLate, + kIsAmpHigh, + kIsEventInTVDC, + kIsTimeInfoLost }; + const static int gStartDescriptor = 0x0000000f; + + int size() const + { + return 1 + mEventHeader.nGBTWords; // EventHeader + EventData size + } + + std::vector<char> to_vector(bool tcm) + { + constexpr int CRUWordSize = 16; + + std::vector<char> result(size() * CRUWordSize); + char* out = result.data(); + if (!tcm) { + std::memcpy(out, &mEventHeader, EventHeader::PayloadSize); + out += EventHeader::PayloadSize; + LOG(DEBUG) << " Write PM header: nWords: " << (int)mEventHeader.nGBTWords + << " orbit: " << int(mEventHeader.orbit) + << " BC: " << int(mEventHeader.bc) + << " size: " << result.size(); + printHexEventHeader(); + out += CRUWordSize - EventHeader::PayloadSize; // Padding enabled + + for (uint64_t i = 0; i < mEventHeader.nGBTWords; ++i) { + std::memcpy(out, &mEventData[2 * i], EventData::PayloadSizeFirstWord); + out += EventData::PayloadSizeFirstWord; + LOG(DEBUG) << " 1st word: Ch: " << std::setw(2) << mEventData[2 * i].channelID + << " charge: " << std::setw(4) << mEventData[2 * i].charge + << " time: " << std::setw(4) << mEventData[2 * i].time; + std::memcpy(out, &mEventData[2 * i + 1], EventData::PayloadSizeSecondWord); + out += EventData::PayloadSizeSecondWord; + LOG(DEBUG) << " 2nd word: Ch: " << std::setw(2) << mEventData[2 * i + 1].channelID + << " charge: " << std::setw(4) << mEventData[2 * i + 1].charge + << " time: " << std::setw(4) << mEventData[2 * i + 1].time; + + out += CRUWordSize - EventData::PayloadSizeSecondWord - EventData::PayloadSizeFirstWord; + printHexEventData(i); + } + } else { + // TCM data + std::memcpy(out, &mEventHeader, EventHeader::PayloadSize); + out += EventHeader::PayloadSize; + LOG(DEBUG) << " Write TCM header: nWords: " << (int)mEventHeader.nGBTWords + << " orbit: " << int(mEventHeader.orbit) + << " BC: " << int(mEventHeader.bc) + << " size: " << result.size(); + std::memcpy(out, &mTCMdata, sizeof(TCMdata)); + out += sizeof(TCMdata); + // TODO: No TCM payload printing until the meaning of trigger bits and other flags is clarified + } + return result; + } + + public: + EventHeader mEventHeader; + EventData mEventData[Constants::nChannelsPerPm]; + TCMdata mTCMdata; + + ClassDefNV(RawEventData, 1); +}; + +} // namespace fv0 +} // namespace o2 +#endif diff --git a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h index 7682d1dcdc91c..d29bcefbf9a0a 100644 --- a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h +++ b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h @@ -22,4 +22,10 @@ #pragma link C++ class std::vector < o2::fv0::ChannelData> + ; #pragma link C++ class std::vector < o2::fv0::BCData> + ; +#pragma link C++ class o2::fv0::RawEventData + ; +#pragma link C++ class o2::fv0::EventHeader + ; +#pragma link C++ class o2::fv0::EventData + ; +#pragma link C++ class o2::fv0::TCMdata + ; +#pragma link C++ class o2::fv0::Topo + ; + #endif diff --git a/DataFormats/Detectors/FIT/FV0/src/RawEventData.cxx b/DataFormats/Detectors/FIT/FV0/src/RawEventData.cxx new file mode 100644 index 0000000000000..022b003d0ab43 --- /dev/null +++ b/DataFormats/Detectors/FIT/FV0/src/RawEventData.cxx @@ -0,0 +1,71 @@ +// 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 "DataFormatsFV0/RawEventData.h" +#include <sstream> + +using namespace o2::fv0; + +ClassImp(RawEventData); + +void RawEventData::print() +{ + std::cout << "==================Raw event data==================" << std::endl; + std::cout << "##################Header##################" << std::endl; + std::cout << "startDescriptor: " << mEventHeader.startDescriptor << std::endl; + std::cout << "Nchannels: " << mEventHeader.nGBTWords * 2 << std::endl; + std::cout << "BC: " << mEventHeader.bc << std::endl; + std::cout << "Orbit: " << mEventHeader.orbit << std::endl; + std::cout << "##########################################" << std::endl; + std::cout << "###################DATA###################" << std::endl; + for (int iCh = 0; iCh < mEventHeader.nGBTWords * 2; iCh++) { + std::cout << "------------Channel " << mEventData[iCh].channelID << "------------" << std::endl; + std::cout << "Charge: " << mEventData[iCh].charge << std::endl; + std::cout << "Time: " << mEventData[iCh].time << std::endl; + std::cout << "1TimeLostEvent: " << mEventData[iCh].is1TimeLostEvent << std::endl; + std::cout << "2TimeLostEvent: " << mEventData[iCh].is2TimeLostEvent << std::endl; + std::cout << "ADCinGate: " << mEventData[iCh].isADCinGate << std::endl; + std::cout << "AmpHigh: " << mEventData[iCh].isAmpHigh << std::endl; + std::cout << "DoubleEvent: " << mEventData[iCh].isDoubleEvent << std::endl; + std::cout << "EventInTVDC: " << mEventData[iCh].isEventInTVDC << std::endl; + std::cout << "TimeInfoLate: " << mEventData[iCh].isTimeInfoLate << std::endl; + std::cout << "TimeInfoLost: " << mEventData[iCh].isTimeInfoLost << std::endl; + std::cout << "numberADC: " << mEventData[iCh].numberADC << std::endl; + } + std::cout << "##########################################" << std::endl; +} + +void RawEventData::printHexEventHeader() +{ + std::stringstream ssheader; + ssheader << std::setfill('0') << std::setw(16) << std::hex << mEventHeader.word[0] << " " << std::setw(16) << mEventHeader.word[1] << "\n "; + ssheader << std::setw(3) << (0x00000fff & mEventHeader.bc) << " " + << std::setw(8) << (0xffffffff & mEventHeader.orbit) << " " + << std::setw(5) << (0x000fffff & mEventHeader.reservedField1) << " " + << std::setw(2) << (0x000000ff & mEventHeader.reservedField2) << " " + << std::setw(1) << (0x0000000f & mEventHeader.nGBTWords) << " " + << std::setw(1) << (0x0000000f & mEventHeader.startDescriptor) << " " + << std::setw(12) << (0xffffffffffff & mEventHeader.reservedField3); + LOG(DEBUG) << ssheader.str(); +} + +void RawEventData::printHexEventData(uint64_t i) +{ + std::stringstream ssdata; + ssdata << "D0:0x "; + ssdata << std::setfill('0') << std::hex << std::setw(16) << mEventData[2 * i].word << "\n "; + ssdata << std::setw(3) << (0x0fff & mEventData[2 * i].time) << " " + << std::setw(8) << (0x1fff & mEventData[2 * i].charge) << "\n "; + ssdata << "D1:0x "; + ssdata << std::setfill('0') << std::hex << std::setw(16) << mEventData[2 * i + 1].word << "\n "; + ssdata << std::setw(3) << (0x0fff & mEventData[2 * i + 1].time) << " " + << std::setw(8) << (0x1fff & mEventData[2 * i + 1].charge); + LOG(DEBUG) << " | " << ssdata.str(); +} diff --git a/Detectors/FIT/FV0/CMakeLists.txt b/Detectors/FIT/FV0/CMakeLists.txt index 364119694abdb..b26e2454f4b96 100644 --- a/Detectors/FIT/FV0/CMakeLists.txt +++ b/Detectors/FIT/FV0/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(base) add_subdirectory(simulation) add_subdirectory(macro) +add_subdirectory(reconstruction) diff --git a/Detectors/FIT/FV0/base/CMakeLists.txt b/Detectors/FIT/FV0/base/CMakeLists.txt index d96cb91315d66..804c004157da1 100644 --- a/Detectors/FIT/FV0/base/CMakeLists.txt +++ b/Detectors/FIT/FV0/base/CMakeLists.txt @@ -11,8 +11,9 @@ o2_add_library(FV0Base SOURCES src/Geometry.cxx PUBLIC_LINK_LIBRARIES ROOT::Geom - FairRoot::Base - O2::SimulationDataFormat) + FairRoot::Base) -o2_target_root_dictionary(FV0Base HEADERS include/FV0Base/Geometry.h) +o2_target_root_dictionary(FV0Base + HEADERS include/FV0Base/Geometry.h + include/FV0Base/Constants.h) diff --git a/Detectors/FIT/FV0/base/include/FV0Base/Constants.h b/Detectors/FIT/FV0/base/include/FV0Base/Constants.h new file mode 100644 index 0000000000000..965110873e21c --- /dev/null +++ b/Detectors/FIT/FV0/base/include/FV0Base/Constants.h @@ -0,0 +1,36 @@ +// 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 Constants.h +/// \brief General constants in FV0 +/// +/// \author Maciej Slupecki, University of Jyvaskyla, Finland + +#ifndef ALICEO2_FV0_CONSTANTS_ +#define ALICEO2_FV0_CONSTANTS_ + +#include "FV0Base/Geometry.h" + +namespace o2 +{ +namespace fv0 +{ + +struct Constants { + static constexpr int nChannelsPerPm = 12; // Fixed now together with the production of PMs - will remain constant + static constexpr int nPms = 4; // Number of processing modules (PMs); 1 PM per ring, 2 PMs needed for ring 5 + static constexpr int nTcms = 1; // Number of trigger and clock modules (TCMs) + static constexpr int nGbtLinks = nPms + nTcms; + static constexpr int nFv0Channels = Geometry::getNumberOfReadoutChannels(); +}; + +} // namespace fv0 +} // namespace o2 +#endif diff --git a/Detectors/FIT/FV0/base/include/FV0Base/Geometry.h b/Detectors/FIT/FV0/base/include/FV0Base/Geometry.h index 97e9d02cbdbc6..c659c0c47c621 100644 --- a/Detectors/FIT/FV0/base/include/FV0Base/Geometry.h +++ b/Detectors/FIT/FV0/base/include/FV0Base/Geometry.h @@ -23,12 +23,24 @@ #include <TGeoMatrix.h> #include <TGeoVolume.h> #include <TVirtualMC.h> -#include "MathUtils/Cartesian3D.h" namespace o2 { namespace fv0 { + +struct Point3Dsimple { + float x; + float y; + float z; + void SetCoordinates(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + }; +}; + /// FV0 Geometry class Geometry { @@ -98,8 +110,9 @@ class Geometry /// \param y y [cm]. /// \param z z [cm]. void getGlobalPosition(float& x, float& y, float& z); - Point3D<float>& getCellCenter(UInt_t cellId); - Point3D<float>& getReadoutCenter(UInt_t cellId); + Point3Dsimple& getCellCenter(UInt_t cellId); + Point3Dsimple& getReadoutCenter(UInt_t cellId); + static constexpr int getNumberOfReadoutChannels() { return sNumberOfReadoutChannels; }; /// Helper function to check if the cellId belongs to ring 5. /// \param cellId Id of the cell in range from 0 to 39. @@ -459,8 +472,8 @@ class Geometry TGeoMatrix* mRightTransformation; ///< Transformation for the right part of the detector /// Utility arrays derived from constants - std::array<Point3D<float>, sNumberOfCells> mCellCenter; ///< Center of each scintillator cell - std::array<Point3D<float>, sNumberOfReadoutChannels> mReadoutCenter; ///< Similar to mCellCenter, cells in r5 are additionally divided + std::array<Point3Dsimple, sNumberOfCells> mCellCenter; ///< Center of each scintillator cell + std::array<Point3Dsimple, sNumberOfReadoutChannels> mReadoutCenter; ///< Similar to mCellCenter, cells in r5 are additionally divided static Geometry* sInstance; ///< \brief Singleton instance diff --git a/Detectors/FIT/FV0/base/src/Geometry.cxx b/Detectors/FIT/FV0/base/src/Geometry.cxx index d6cc07f42982e..b40df946084af 100644 --- a/Detectors/FIT/FV0/base/src/Geometry.cxx +++ b/Detectors/FIT/FV0/base/src/Geometry.cxx @@ -116,12 +116,12 @@ void Geometry::getGlobalPosition(float& x, float& y, float& z) z = sZGlobal; } -Point3D<float>& Geometry::getCellCenter(UInt_t cellId) +Point3Dsimple& Geometry::getCellCenter(UInt_t cellId) { return mCellCenter.at(cellId); } -Point3D<float>& Geometry::getReadoutCenter(UInt_t cellId) +Point3Dsimple& Geometry::getReadoutCenter(UInt_t cellId) { return mReadoutCenter.at(cellId); } @@ -1222,7 +1222,7 @@ void Geometry::initializeCellCenters() double x = sXGlobal + r * TMath::Cos(lutSect2Phi[sCellToSector[cellId]]); double y = sYGlobal + r * TMath::Sin(lutSect2Phi[sCellToSector[cellId]]); - Point3D<float>* p = &mCellCenter.at(cellId); + Point3Dsimple* p = &mCellCenter.at(cellId); p->SetCoordinates(x, y, sZGlobal); } } @@ -1230,9 +1230,9 @@ void Geometry::initializeCellCenters() void Geometry::initializeReadoutCenters() { for (int channelId = 0; channelId < sNumberOfReadoutChannels; channelId++) { - Point3D<float>* p = &mReadoutCenter.at(channelId); + Point3Dsimple* p = &mReadoutCenter.at(channelId); if (!isRing5(channelId)) { - p->SetCoordinates(getCellCenter(channelId).X(), getCellCenter(channelId).Y(), getCellCenter(channelId).Z()); + p->SetCoordinates(getCellCenter(channelId).x, getCellCenter(channelId).y, getCellCenter(channelId).z); } else { const int numberOfSectorsR5 = sNumberOfCellSectors * 4; // from both halves of the detector const float phi0 = 78.75 * TMath::DegToRad(); // starting phi of one of the sectors diff --git a/Detectors/FIT/FV0/macro/CMakeLists.txt b/Detectors/FIT/FV0/macro/CMakeLists.txt index 1510362c7fb90..d7fadb4a3683c 100644 --- a/Detectors/FIT/FV0/macro/CMakeLists.txt +++ b/Detectors/FIT/FV0/macro/CMakeLists.txt @@ -11,6 +11,7 @@ o2_add_test_root_macro(readFV0Hits.C PUBLIC_LINK_LIBRARIES O2::FV0Simulation LABELS fv0) + o2_add_test_root_macro(readFV0Digits.C PUBLIC_LINK_LIBRARIES O2::FV0Simulation LABELS fv0) diff --git a/Detectors/FIT/FV0/macro/readFV0Digits.C b/Detectors/FIT/FV0/macro/readFV0Digits.C index 80c2914e3d5fa..903e31b526b8e 100644 --- a/Detectors/FIT/FV0/macro/readFV0Digits.C +++ b/Detectors/FIT/FV0/macro/readFV0Digits.C @@ -21,7 +21,7 @@ #include "DataFormatsFV0/ChannelData.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" -#include "FV0Simulation/DigitizationConstant.h" +#include "FV0Base/Constants.h" #include "FV0Simulation/MCLabel.h" #include "FairLogger.h" @@ -55,7 +55,7 @@ void readFV0Digits(std::string digiFName = "fv0digits.root", bool printAllToTerm // Settings for drawing, used with SetRangeUser() const float tMin = 0, tMax = 50, chargeMin = 5, chargeMax = 800; const float chargePerMip = 1. / 16; // Assumes 1-MIP-peak is at 16th ADC channel - const int nChannels = o2::fv0::DigitizationConstant::NCHANNELS; + const int nChannels = o2::fv0::Constants::nFv0Channels; // Init histos std::vector<std::string> vHistoNames; @@ -118,11 +118,12 @@ void readFV0Digits(std::string digiFName = "fv0digits.root", bool printAllToTerm // Fill histos for (int ibc = 0; ibc < nbc; ibc++) { - if (ibc % (nbc / 10) == 0) { + if ((nbc > 10) && (ibc % (nbc / 10) == 0)) { std::cout << " Progress reading tree: " << ibc << "/" << nbc << " ["; std::cout << 100.0 * ibc / nbc << "%]" << std::endl; } const auto& bcd = fv0BCData[ibc]; + std::cout << ibc << " " << nbc << " - " << bcd.ir << std::endl; int chEnt = bcd.ref.getFirstEntry(); int nchPrec = 0; int nchReal = 0; @@ -131,6 +132,7 @@ void readFV0Digits(std::string digiFName = "fv0digits.root", bool printAllToTerm if ((chd.time == -1024.f) && (chd.chargeAdc == 0.f)) { continue; } + std::cout << chd.pmtNumber << " " << chd.chargeAdc << " " << chd.time << std::endl; hTimeCharge->Fill(chd.time, chd.chargeAdc); hTimeCh->Fill(chd.time, chd.pmtNumber); hChargeCh->Fill(chd.chargeAdc, chd.pmtNumber); @@ -253,6 +255,7 @@ void readFV0Digits(std::string digiFName = "fv0digits.root", bool printAllToTerm hNchReal->Write(); hNchPrec->Write(); fout->Close(); + std::cout << "Digits read" << std::endl; } // Root files generated in the previous stage (readFV0Digits()) are used as inputs here @@ -308,7 +311,7 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str const float statX1 = 1. - rmargin, statX2 = statX1 - 0.18; const float statH = 0.3, statY1 = 1. - tmargin, statY2 = statY1 - statH; - // Draw side-by-side comparison of TH2's + /* // Draw side-by-side comparison of TH2's for (UInt_t ih = 0; ih < 4; ih++) { std::stringstream ss; ss << "fv0digi-cmp" << ih; @@ -323,7 +326,7 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str AdjustStatBox(h, statX1, statX2, statY1, statY2); } } - +*/ // Draw the comparison of TH1's Color_t col[3] = {kBlack, kRed, kBlue}; TCanvas* c = new TCanvas("fv0digi-cmp-th1", "fv0digi-cmp-th1", 1800, 500); @@ -336,6 +339,7 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str ss << "p" << ifile; TH1D* ht = h2->ProjectionX((ss.str() + "t_" + h2->GetName()).c_str()); TH1D* hc = h2->ProjectionY((ss.str() + "c_" + h2->GetName()).c_str()); + hc->GetXaxis()->SetRangeUser(0, 100); c->cd(1); gPad->SetMargin(lmargin, rmargin, bmargin, tmargin); gPad->SetLogy(); @@ -344,6 +348,7 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str c->cd(2); gPad->SetMargin(lmargin, rmargin, bmargin, tmargin); gPad->SetLogy(); + hc->SetLineWidth(3.5 - ifile); hc->Draw((ifile == 0) ? "" : "sames"); AdjustStatBox(hc, statX1, statX2, statY1 - statH * ifile, statY2 - statH * ifile); } diff --git a/Detectors/FIT/FV0/reconstruction/CMakeLists.txt b/Detectors/FIT/FV0/reconstruction/CMakeLists.txt new file mode 100644 index 0000000000000..532481c9943c9 --- /dev/null +++ b/Detectors/FIT/FV0/reconstruction/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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_library(FV0Reconstruction + SOURCES src/ReadRaw.cxx + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat + O2::Framework + O2::FV0Base + O2::DataFormatsFV0 + O2::DetectorsRaw + O2::Headers) + +o2_target_root_dictionary(FV0Reconstruction + HEADERS include/FV0Reconstruction/ReadRaw.h +) diff --git a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/ReadRaw.h b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/ReadRaw.h new file mode 100644 index 0000000000000..ade792cc6ee0d --- /dev/null +++ b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/ReadRaw.h @@ -0,0 +1,67 @@ +// 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 ReadRaw.h +/// \brief Reads raw data and converts to digits +/// \author Maciej.Slupecki@cern.ch, arvind.khuntia@cern.ch, based on the FT0 code +// RAW data format description: DataFormat/Detectors/FIT/FV0/RawEventData + +#ifndef ALICEO2_FV0_READRAW_H_ +#define ALICEO2_FV0_READRAW_H_ + +#include <fstream> +#include <iostream> +#include <iomanip> +#include <map> +#include <string> +#include <sstream> +#include <vector> +#include "TBranch.h" +#include "TTree.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsFV0/BCData.h" +#include "DataFormatsFV0/ChannelData.h" +#include "DataFormatsFV0/LookUpTable.h" +#include "DataFormatsFV0/RawEventData.h" + +namespace o2 +{ +namespace fv0 +{ +class ReadRaw +{ + public: + ReadRaw() = default; + ReadRaw(bool doConversionToDigits, const std::string inputRawFilePath = "fv0.raw", const std::string outputRawFilePath = "fv0digitsFromRaw.root"); + void readRawData(const LookUpTable& lut); + void writeDigits(const std::string& outputDigitsFilePath); + void close(); + + private: + std::ifstream mRawFileIn; + std::map<o2::InteractionRecord, std::vector<ChannelData>> mDigitAccum; // digit accumulator + + template <typename T> + TBranch* getOrMakeBranch(TTree& tree, std::string brname, T* ptr) + { + if (auto br = tree.GetBranch(brname.c_str())) { + br->SetAddress(static_cast<void*>(ptr)); + return br; + } + // otherwise make it + return tree.Branch(brname.c_str(), ptr); + } + + ClassDefNV(ReadRaw, 1); +}; + +} // namespace fv0 +} // namespace o2 +#endif diff --git a/Detectors/FIT/FV0/reconstruction/src/FV0ReconstructionLinkDef.h b/Detectors/FIT/FV0/reconstruction/src/FV0ReconstructionLinkDef.h new file mode 100644 index 0000000000000..9c78ce474d9df --- /dev/null +++ b/Detectors/FIT/FV0/reconstruction/src/FV0ReconstructionLinkDef.h @@ -0,0 +1,19 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::fv0::ReadRaw + ; + +#endif diff --git a/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx b/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx new file mode 100644 index 0000000000000..ab8902f6dca54 --- /dev/null +++ b/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx @@ -0,0 +1,167 @@ +// 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 "FV0Reconstruction/ReadRaw.h" +#include "DetectorsRaw/RDHUtils.h" +#include "Framework/Logger.h" +#include "TFile.h" + +using namespace o2::fv0; +using RDHUtils = o2::raw::RDHUtils; + +ClassImp(ReadRaw); + +ReadRaw::ReadRaw(bool doConversionToDigits, const std::string inputRawFilePath, const std::string outputDigitsFilePath) +{ + LOG(INFO) << "o2::fv0::ReadRaw::ReadRaw(): Read Raw file: " << inputRawFilePath.data() << " and convert to: " << outputDigitsFilePath.data(); + mRawFileIn.exceptions(std::ios_base::failbit | std::ios_base::badbit); + mRawFileIn.open(inputRawFilePath, std::fstream::in | std::fstream::binary); + LookUpTable lut(true); + ReadRaw::readRawData(lut); + ReadRaw::writeDigits(outputDigitsFilePath.data()); +} + +void ReadRaw::readRawData(const LookUpTable& lut) +{ + LOG(INFO) << "o2::fv0::ReadRaw::readRawData():Start."; + constexpr int CRUWordSize = 16; + o2::header::RAWDataHeader mRDH; + ChannelData chData; // output to store digits + EventHeader eventHeader; // raw data container + TCMdata mTCMdata; // raw data container + EventData eventData[Constants::nChannelsPerPm]; // raw data container + + // Get input RAW file size + mRawFileIn.seekg(0, mRawFileIn.end); + long rawFileSize = mRawFileIn.tellg(); + mRawFileIn.seekg(0); + + long posInFile = 0; + while (posInFile < rawFileSize - sizeof(mRDH)) { + // Read contents of the next RDH + mRawFileIn.seekg(posInFile); + mRawFileIn.read(reinterpret_cast<char*>(&mRDH), sizeof(mRDH)); + int nwords = RDHUtils::getMemorySize(mRDH); + int offset = RDHUtils::getOffsetToNext(mRDH); + int link = RDHUtils::getLinkID(mRDH); + posInFile += offset; // posInFile is now prepared for the next iteration of the main loop + + int posPayload = 0; + if (nwords > sizeof(mRDH)) { + // RDHUtils::printRDH(mRDH); + // Read the payload following the RDH (only if there is anything to read) + posPayload = int(sizeof(mRDH)); + + while (posPayload < nwords) { + mRawFileIn.read(reinterpret_cast<char*>(&eventHeader), sizeof(eventHeader)); + posPayload += sizeof(eventHeader); + LOG(DEBUG) << " Read internal EventHeader for link: " << link + << " nWords: " << (int)eventHeader.nGBTWords + << " orbit: " << int(eventHeader.orbit) + << " BC: " << int(eventHeader.bc) + << " posInFile: " << posInFile + << " posPayload: " << posPayload; + o2::InteractionRecord intrec{uint16_t(eventHeader.bc), uint32_t(eventHeader.orbit)}; + + if (link == lut.getTcmLink()) { // is TCM payload + mRawFileIn.read(reinterpret_cast<char*>(&mTCMdata), sizeof(mTCMdata)); + posPayload += sizeof(mTCMdata); + LOG(DEBUG) << " Read TCM: posPayload: " << posPayload + << " posInFile: " << posInFile; + } else { // is PM payload + posPayload += CRUWordSize - o2::fv0::EventHeader::PayloadSize; // padding is enabled + for (int i = 0; i < eventHeader.nGBTWords; ++i) { + mRawFileIn.read(reinterpret_cast<char*>(&eventData[2 * i]), o2::fv0::EventData::PayloadSizeFirstWord); + posPayload += o2::fv0::EventData::PayloadSizeFirstWord; + chData = {Short_t(lut.getChannel(link, int(eventData[2 * i].channelID))), + Float_t(eventData[2 * i].time), + Short_t(eventData[2 * i].charge)}; + mDigitAccum[intrec].emplace_back(chData); + LOG(DEBUG) << " Read 1st half-word: (PMchannel, globalChannel, Q, T, posPayload) = " + << std::setw(3) << int(eventData[2 * i].channelID) + << std::setw(4) << lut.getChannel(link, int(eventData[2 * i].channelID)) + << std::setw(5) << int(eventData[2 * i].charge) + << std::setw(5) << float(eventData[2 * i].time) + << std::setw(5) << posPayload; + + Short_t channelIdFirstHalfWord = chData.pmtNumber; + + mRawFileIn.read(reinterpret_cast<char*>(&eventData[2 * i + 1]), EventData::PayloadSizeSecondWord); + posPayload += o2::fv0::EventData::PayloadSizeSecondWord; + chData = {Short_t(lut.getChannel(link, (eventData[2 * i + 1].channelID))), + Float_t(eventData[2 * i + 1].time), + Short_t(eventData[2 * i + 1].charge)}; + if (chData.pmtNumber <= channelIdFirstHalfWord) { + // Don't save the second half-word if it is only filled with zeroes (empty-data) + // TODO: Verify if it works correctly with real data from readout + continue; + } + mDigitAccum[intrec].emplace_back(chData); + LOG(DEBUG) << " Read 2nd half-word: (PMchannel, globalChannel, Q, T, posPayload) = " + << std::setw(3) << int(eventData[2 * i + 1].channelID) + << std::setw(4) << lut.getChannel(link, int(eventData[2 * i + 1].channelID)) + << std::setw(5) << int(eventData[2 * i + 1].charge) + << std::setw(5) << float(eventData[2 * i + 1].time) + << std::setw(5) << posPayload; + } + } + } + } + } + close(); + LOG(INFO) << "o2::fv0::ReadRaw::readRawData():Finished."; +} + +void ReadRaw::close() +{ + if (mRawFileIn.is_open()) + mRawFileIn.close(); +} + +void ReadRaw::writeDigits(const std::string& outputDigitsFilePath) +{ + TFile* outFile = new TFile(outputDigitsFilePath.data(), "RECREATE"); + if (!outFile || outFile->IsZombie()) { + LOG(ERROR) << "Failed to open " << outputDigitsFilePath << " output file"; + } else { + LOG(INFO) << "o2::fv0::ReadRaw::writeDigits(): Opened output file: " << outputDigitsFilePath; + } + TTree* outTree = new TTree("o2sim", "o2sim"); + std::vector<ChannelData> chDataVecTree; + std::vector<BCData> chBcVecTree; + + for (auto& digit : mDigitAccum) { + LOG(DEBUG) << " IR (" << digit.first << ") (i, PMT, Q, T):"; + for (uint16_t i = 0; i < digit.second.size(); i++) { + ChannelData* chd = &(digit.second.at(i)); + LOG(DEBUG) << " " << std::setw(3) << i + << std::setw(4) << chd->pmtNumber + << std::setw(5) << chd->chargeAdc + << std::setw(5) << chd->time; + } + + size_t nStored = 0; + size_t first = chDataVecTree.size(); + for (auto& sec : digit.second) { + chDataVecTree.emplace_back(int(sec.pmtNumber), float(sec.time), Short_t(sec.chargeAdc)); + nStored++; + } + chBcVecTree.emplace_back(first, nStored, digit.first); + } + + outTree->Branch("FV0DigitBC", &chBcVecTree); + outTree->Branch("FV0DigitCh", &chDataVecTree); + outTree->Fill(); + + outFile->cd(); + outTree->Write(); + outFile->Close(); + LOG(INFO) << "o2::fv0::ReadRaw::writeDigits(): Finished converting " << chBcVecTree.size() << " events."; +} diff --git a/Detectors/FIT/FV0/simulation/CMakeLists.txt b/Detectors/FIT/FV0/simulation/CMakeLists.txt index 49ab353556728..99ba6485279a9 100644 --- a/Detectors/FIT/FV0/simulation/CMakeLists.txt +++ b/Detectors/FIT/FV0/simulation/CMakeLists.txt @@ -12,15 +12,30 @@ o2_add_library(FV0Simulation SOURCES src/Detector.cxx src/Digitizer.cxx src/FV0DigParam.cxx + src/Digits2Raw.cxx PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::FV0Base O2::DataFormatsFV0 - ROOT::Physics) + O2::DetectorsRaw + ROOT::Physics + O2::Headers + O2::Framework) o2_target_root_dictionary(FV0Simulation - HEADERS include/FV0Simulation/Detector.h - include/FV0Simulation/DigitizationConstant.h - include/FV0Simulation/Digitizer.h - include/FV0Simulation/FV0DigParam.h) + HEADERS include/FV0Simulation/Detector.h + include/FV0Simulation/DigitizationConstant.h + include/FV0Simulation/Digitizer.h + include/FV0Simulation/FV0DigParam.h + include/FV0Simulation/Digits2Raw.h) +o2_add_executable(digi2raw + COMPONENT_NAME fv0 + SOURCES src/digit2raw.cxx + PUBLIC_LINK_LIBRARIES O2::FV0Simulation + O2::DetectorsRaw + O2::DetectorsCommonDataFormats + O2::CommonUtils + Boost::program_options) + o2_data_file(COPY data DESTINATION Detectors/FV0/simulation) + diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h index 00fca32dd7cd3..d500d1bdf4503 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h @@ -15,7 +15,6 @@ namespace o2::fv0 { struct DigitizationConstant { static constexpr int NCELLSA = 40; // number of scintillator cells - static constexpr int NCHANNELS = 48; // number of readout channels static constexpr float INV_CHARGE_PER_ADC = 1. / 0.6e-12; // charge static constexpr float N_PHOTONS_PER_MEV = 10400; // average #photons generated per 1 MeV of deposited energy diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h index 8800192a86843..0c81394f30b1d 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h @@ -11,6 +11,7 @@ #ifndef ALICEO2_FV0_DIGITIZER_H #define ALICEO2_FV0_DIGITIZER_H +#include "FV0Base/Constants.h" #include <FV0Simulation/MCLabel.h> #include <FV0Simulation/DigitizationConstant.h> #include <FV0Simulation/FV0DigParam.h> @@ -71,10 +72,10 @@ class Digitizer Int_t mSrcId; // signal, background or QED std::vector<fv0::MCLabel> mMCLabels; - std::array<std::vector<Float_t>, DP::NCHANNELS> mPmtChargeVsTime; // Charge time series aka analogue signal pulse from PM - UInt_t mNBins; // Number of bins in pulse series - Float_t mBinSize; // Time width of the pulse bin - HPTDC resolution - Float_t mPmtTimeIntegral; // + std::array<std::vector<Float_t>, Constants::nFv0Channels> mPmtChargeVsTime; // Charge time series: analog pulse from PM + UInt_t mNBins; // Number of bins in pulse series + Float_t mBinSize; // Time width of pulse bin: HPTDC resolution + Float_t mPmtTimeIntegral; // // Random rings HitRandomRingType mRndScintDelay; diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digits2Raw.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digits2Raw.h new file mode 100644 index 0000000000000..8e5c881440f4c --- /dev/null +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digits2Raw.h @@ -0,0 +1,68 @@ +// 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 Digits2Raw.h +/// \brief converts digits to raw format +/// \author Maciej.Slupecki@cern.ch +// based on FT0 + +#ifndef ALICEO2_FV0_DIGITS2RAW_H_ +#define ALICEO2_FV0_DIGITS2RAW_H_ + +#include "Headers/RAWDataHeader.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsFV0/RawEventData.h" +#include "DataFormatsFV0/LookUpTable.h" +#include "DataFormatsFV0/ChannelData.h" +#include "DataFormatsFV0/BCData.h" +#include "DetectorsRaw/HBFUtils.h" +#include "DetectorsRaw/RawFileWriter.h" +#include <FairLogger.h> +#include <TStopwatch.h> +#include <iostream> +#include <string> +#include <vector> +#include <gsl/span> + +namespace o2 +{ +namespace fv0 +{ +class Digits2Raw +{ + public: + Digits2Raw() = default; + void readDigits(const std::string& outDir, const std::string& fileDigitsName); + void convertDigits(o2::fv0::BCData bcdigits, + gsl::span<const ChannelData> pmchannels, + const o2::fv0::LookUpTable& lut); + + o2::raw::RawFileWriter& getWriter() { return mWriter; } + void setFilePerLink(bool v) { mOutputPerLink = v; } + bool getFilePerLink() const { return mOutputPerLink; } + + private: + static constexpr uint32_t sTcmLink = 4; + static constexpr uint16_t sCruId = 0; + static constexpr uint32_t sEndPointId = sCruId; + + void makeGBTHeader(EventHeader& eventHeader, int link, o2::InteractionRecord const& mIntRecord); + void fillSecondHalfWordAndAddData(int iChannelPerLink, int prevPmLink, const o2::InteractionRecord& ir); + RawEventData mRawEventData; + o2::raw::RawFileWriter mWriter{"FV0"}; + bool mOutputPerLink = false; + ///////////////////////////////////////////////// + + ClassDefNV(Digits2Raw, 1); +}; + +} // namespace fv0 +} // namespace o2 +#endif diff --git a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx index d644a78e58e5c..f891e70ab4472 100644 --- a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx @@ -10,6 +10,7 @@ #include "FV0Simulation/Digitizer.h" #include "FV0Base/Geometry.h" +#include "FV0Base/Constants.h" #include <TRandom.h> #include <algorithm> @@ -36,7 +37,7 @@ void Digitizer::init() mNBins = FV0DigParam::Instance().waveformNbins; //Will be computed using detector set-up from CDB mBinSize = FV0DigParam::Instance().waveformBinWidth; //Will be set-up from CDB - for (Int_t i = 0; i < DP::NCHANNELS; i++) { + for (Int_t i = 0; i < Constants::nFv0Channels; i++) { mPmtChargeVsTime[i].resize(mNBins); } @@ -194,7 +195,7 @@ void Digitizer::analyseWaveformsAndStore(std::vector<fv0::BCData>& digitsBC, // Sum charge of all time bins to get total charge collected for a given channel size_t const first = digitsCh.size(); size_t nStored = 0; - for (Int_t ipmt = 0; ipmt < DP::NCHANNELS; ++ipmt) { + for (Int_t ipmt = 0; ipmt < Constants::nFv0Channels; ++ipmt) { Float_t totalCharge = 0.0f; auto const& analogSignal = mPmtChargeVsTime[ipmt]; for (Int_t iTimeBin = 0; iTimeBin < mNBins; ++iTimeBin) { @@ -284,10 +285,10 @@ float Digitizer::getDistFromCellCenter(UInt_t cellId, double hitx, double hity) Geometry* geo = Geometry::instance(); // Parametrize the line (ax+by+c=0) that crosses the detector center and the cell's middle point - Point3D<float>* pCell = &geo->getCellCenter(cellId); + Point3Dsimple* pCell = &geo->getCellCenter(cellId); float x0, y0, z0; geo->getGlobalPosition(x0, y0, z0); - double a = -(y0 - pCell->Y()) / (x0 - pCell->X()); + double a = -(y0 - pCell->y) / (x0 - pCell->x); double b = 1; double c = -(y0 - a * x0); // Return the distance from hit to this line diff --git a/Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx new file mode 100644 index 0000000000000..c57d465e69b45 --- /dev/null +++ b/Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx @@ -0,0 +1,184 @@ +// 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. +// +// RAW data format - DataFormat/Detectors/FIT/FT0/RawEventData + +#include "FV0Base/Constants.h" +#include "FV0Simulation/Digits2Raw.h" +#include <TTree.h> +#include <cassert> + +using namespace o2::fv0; + +ClassImp(Digits2Raw); + +void Digits2Raw::readDigits(const std::string& outDir, const std::string& fileDigitsName) +{ + LOG(INFO) << "==============FV0: Digits2Raw::convertDigits" << std::endl; + LookUpTable lut(true); + + std::string outd = outDir; + if (outd.back() != '/') { + outd += '/'; + } + + // Register PM links linearly + for (int iPmLink = 0; iPmLink < Constants::nPms; ++iPmLink) { + uint64_t feeId = uint64_t(iPmLink); + uint32_t linkId = uint32_t(iPmLink); + std::string outFileLink = mOutputPerLink ? (outd + "fv0_link" + std::to_string(iPmLink) + ".raw") : (outd + "fv0.raw"); + LOG(INFO) << " Register PM link: " << iPmLink << " to file: " << outFileLink; + mWriter.registerLink(feeId, sCruId, linkId, sEndPointId, outFileLink); + } + + // Register TCM link separately + std::string outFileLink = mOutputPerLink ? (outd + "fv0_link" + std::to_string(sTcmLink) + ".raw") : (outd + "fv0.raw"); + LOG(INFO) << " Register TCM link: " << outFileLink; + mWriter.registerLink(uint64_t(sTcmLink), sCruId, sTcmLink, sEndPointId, outFileLink); + + TFile* fdig = TFile::Open(fileDigitsName.data()); + assert(fdig != nullptr); + LOG(INFO) << "Open digits file: " << fileDigitsName.data(); + + TTree* digTree = (TTree*)fdig->Get("o2sim"); + std::vector<o2::fv0::BCData> digitsBC, *fv0BCDataPtr = &digitsBC; + std::vector<o2::fv0::ChannelData> digitsCh, *fv0ChDataPtr = &digitsCh; + digTree->SetBranchAddress("FV0DigitBC", &fv0BCDataPtr); + digTree->SetBranchAddress("FV0DigitCh", &fv0ChDataPtr); + + for (int ient = 0; ient < digTree->GetEntries(); ient++) { + digTree->GetEntry(ient); + int nbc = digitsBC.size(); + for (int ibc = 0; ibc < nbc; ibc++) { + auto& bcd = digitsBC[ibc]; + auto channels = bcd.getBunchChannelData(digitsCh); + + if (!channels.empty()) { + LOG(DEBUG); + LOG(INFO) << "o2::fv0::Digits2Raw::readDigits(): Start to convertDigits() at ibc = " << ibc << " " << bcd.ir + << " iCh0:" << bcd.ref.getFirstEntry() << " nentries:" << bcd.ref.getEntries(); + convertDigits(bcd, channels, lut); + } + } + } +} + +void Digits2Raw::convertDigits(o2::fv0::BCData bcdigits, gsl::span<const ChannelData> pmchannels, + const o2::fv0::LookUpTable& lut) +{ + const o2::InteractionRecord intRecord = bcdigits.getIntRecord(); + int prevPmLink = -1; + int iChannelPerLink = 0; + int nch = pmchannels.size(); + + std::stringstream ss; + ss << " Number of channels: " << nch << " (Ch, PMT, Q, T)\n"; + for (int ich = 0; ich < nch; ich++) { + if (pmchannels[ich].chargeAdc != 0) { + ss << " " << std::setw(2) << ich + << std::setw(3) << pmchannels[ich].pmtNumber + << std::setw(5) << pmchannels[ich].chargeAdc + << std::setw(7) << std::setprecision(3) << pmchannels[ich].time << "\n"; + } + } + LOG(DEBUG) << ss.str().substr(0, ss.str().size() - 1); + + for (int ich = 0; ich < nch; ich++) { + int nLinkPm = lut.getLink(pmchannels[ich].pmtNumber); + if (nLinkPm != prevPmLink) { + if (prevPmLink >= 0) { + fillSecondHalfWordAndAddData(iChannelPerLink, prevPmLink, intRecord); + } + if (ich != nch - 1) { + LOG(DEBUG) << " Switch prevPmLink: " << prevPmLink << ". Save data with nGBTWords=" + << uint((iChannelPerLink + 1) / 2) << " in header."; + makeGBTHeader(mRawEventData.mEventHeader, nLinkPm, intRecord); + iChannelPerLink = 0; + prevPmLink = nLinkPm; + } + } + if (pmchannels[ich].chargeAdc != 0) { + LOG(DEBUG) << " Store data for channel: " << ich << " PmLink = " << nLinkPm << " "; + auto& newData = mRawEventData.mEventData[iChannelPerLink]; + newData.charge = pmchannels[ich].chargeAdc; + newData.time = pmchannels[ich].time; + newData.is1TimeLostEvent = 0; + newData.is2TimeLostEvent = 0; + newData.isADCinGate = 1; + newData.isAmpHigh = 0; + newData.isDoubleEvent = 0; + newData.isEventInTVDC = 1; + newData.isTimeInfoLate = 0; + newData.isTimeInfoLost = 0; + int chain = std::rand() % 2; + newData.numberADC = chain ? 1 : 0; + newData.channelID = lut.getPmChannel(pmchannels[ich].pmtNumber); + iChannelPerLink++; + } + if (ich == nch - 1) { + fillSecondHalfWordAndAddData(iChannelPerLink, prevPmLink, intRecord); + } + } + + // TCM + makeGBTHeader(mRawEventData.mEventHeader, sTcmLink, intRecord); + mRawEventData.mEventHeader.nGBTWords = 1; + auto& tcmdata = mRawEventData.mTCMdata; + tcmdata.vertex = 1; + tcmdata.orA = 1; + tcmdata.orC = 0; + tcmdata.sCen = 0; + tcmdata.cen = 0; + tcmdata.nChanA = 0; + tcmdata.nChanC = 0; + tcmdata.amplA = 0; + tcmdata.amplC = 0; + tcmdata.timeA = 0; + tcmdata.timeC = 0; + + auto data = mRawEventData.to_vector(kTRUE); //for tcm module + uint32_t linkId = uint32_t(sTcmLink); + uint64_t feeId = uint64_t(sTcmLink); + mWriter.addData(feeId, sCruId, linkId, sEndPointId, intRecord, data); + + // fill mEventData[iChannelPerLink] with 0s to flag that this is a dummy data + uint nGBTWords = uint((iChannelPerLink + 1) / 2); + if ((iChannelPerLink % 2) == 1) { + mRawEventData.mEventData[iChannelPerLink] = {}; + } + mRawEventData.mEventHeader.nGBTWords = nGBTWords; + // LOG(DEBUG) << " last link: " << prevPmLink; +} + +//_____________________________________________________________________________________ +void Digits2Raw::makeGBTHeader(EventHeader& eventHeader, int link, o2::InteractionRecord const& mIntRecord) +{ + eventHeader.startDescriptor = 0xf; + eventHeader.reservedField1 = 0; + eventHeader.reservedField2 = 0; + eventHeader.reservedField3 = 0; + eventHeader.bc = mIntRecord.bc; + eventHeader.orbit = mIntRecord.orbit; + LOG(DEBUG) << " makeGBTHeader for link: " << link; +} + +void Digits2Raw::fillSecondHalfWordAndAddData(int iChannelPerLink, int prevPmLink, const o2::InteractionRecord& ir) +{ + uint nGBTWords = uint((iChannelPerLink + 1) / 2); + if ((iChannelPerLink % 2) == 1) { + mRawEventData.mEventData[iChannelPerLink] = {}; + LOG(DEBUG) << " Fill up empty second half-word."; + } + mRawEventData.mEventHeader.nGBTWords = nGBTWords; + auto data = mRawEventData.to_vector(false); + uint32_t linkId = uint32_t(prevPmLink); + uint64_t feeId = uint64_t(prevPmLink); + mWriter.addData(feeId, sCruId, linkId, sEndPointId, ir, data); +} diff --git a/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h b/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h index d12928d1f584e..7e45ff2806326 100644 --- a/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h +++ b/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h @@ -22,5 +22,6 @@ #pragma link C++ class o2::fv0::DigitizationConstant + ; #pragma link C++ class o2::fv0::FV0DigParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::fv0::FV0DigParam> + ; +#pragma link C++ class o2::fv0::Digits2Raw + ; #endif diff --git a/Detectors/FIT/FV0/simulation/src/digit2raw.cxx b/Detectors/FIT/FV0/simulation/src/digit2raw.cxx new file mode 100644 index 0000000000000..00d615a5ec5f0 --- /dev/null +++ b/Detectors/FIT/FV0/simulation/src/digit2raw.cxx @@ -0,0 +1,114 @@ +// 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 digi2raw.cxx +/// \author ruben.shahoyan@cern.ch + +#include <boost/program_options.hpp> +#include <TSystem.h> +#include <TFile.h> +#include <TStopwatch.h> +#include <string> +#include <iomanip> +#include "Framework/Logger.h" +#include "FairLogger.h" +#include "CommonUtils/StringUtils.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "DetectorsRaw/HBFUtils.h" +#include "FV0Simulation/Digits2Raw.h" + +/// MC->raw conversion for FV0 + +namespace bpo = boost::program_options; + +void digi2raw(const std::string& inpName, const std::string& outDir, bool filePerLink, uint32_t rdhV = 6, bool noEmptyHBF = false, + int superPageSizeInB = 1024 * 1024); + +int main(int argc, char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + " (Convert FV0 digits to CRU raw data)\n"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + // add_option("input-file,i", bpo::value<std::string>()->default_value(o2::base::NameConf::getDigitsFileName(o2::detectors::DetID::FV0)),"input FV0 digits file"); // why not used? + add_option("input-file,i", bpo::value<std::string>()->default_value("fv0digits.root"), "input FV0 digits file"); + add_option("file-per-link,l", bpo::value<bool>()->default_value(false)->implicit_value(true), "create output file per CRU (default: per layer)"); + add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); + uint32_t defRDH = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>(); + add_option("rdh-version,r", bpo::value<uint32_t>()->default_value(defRDH), "RDH version to use"); + add_option("no-empty-hbf,e", bpo::value<bool>()->default_value(false)->implicit_value(true), "do not create empty HBF pages (except for HBF starting TF)"); + add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help")) { + std::cout << opt_general << std::endl; + exit(0); + } + + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + o2::conf::ConfigurableParam::updateFromString(vm["configKeyValues"].as<std::string>()); + digi2raw(vm["input-file"].as<std::string>(), + vm["output-dir"].as<std::string>(), + vm["file-per-link"].as<bool>(), + vm["rdh-version"].as<uint32_t>(), + vm["no-empty-hbf"].as<bool>()); + + return 0; +} + +void digi2raw(const std::string& inpName, const std::string& outDir, bool filePerLink, uint32_t rdhV, bool noEmptyHBF, int superPageSizeInB) +{ + TStopwatch swTot; + swTot.Start(); + o2::fv0::Digits2Raw m2r; + m2r.setFilePerLink(filePerLink); + auto& wr = m2r.getWriter(); + wr.setSuperPageSize(superPageSizeInB); + wr.useRDHVersion(rdhV); + wr.setDontFillEmptyHBF(noEmptyHBF); + + std::string outDirName(outDir); + if (outDirName.back() != '/') { + outDirName += '/'; + } + // if needed, create output directory + if (gSystem->AccessPathName(outDirName.c_str())) { + if (gSystem->mkdir(outDirName.c_str(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outDirName; + } else { + LOG(INFO) << "created output directory " << outDirName; + } + } + + m2r.readDigits(outDirName, inpName); + wr.writeConfFile(wr.getOrigin().str, "RAWDATA", o2::utils::concat_string(outDirName, wr.getOrigin().str, "raw.cfg")); + //LOG(INFO)<<o2::utils::concat_string(outDirName, wr.getOrigin().str)<<"\n"; + // + swTot.Stop(); + swTot.Print(); +} From f49d9a3f8147980b4d6e0838245b049ce3023540 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Wed, 5 Aug 2020 16:40:27 +0200 Subject: [PATCH 0345/1751] [rANS] Memory optimized sparse SymbolTable Optimized, sparse storage format for SymbolTable. Reduces storage requirements by up to factor 5x and optimizes cache performance of encoder/ decoder. --- CODEOWNERS | 1 + Utilities/rANS/include/rANS/Decoder.h | 10 +-- Utilities/rANS/include/rANS/FrequencyTable.h | 14 ++-- Utilities/rANS/include/rANS/LiteralDecoder.h | 2 +- Utilities/rANS/include/rANS/LiteralEncoder.h | 6 +- .../include/rANS/internal/SymbolStatistics.h | 42 ++++++++++-- .../rANS/include/rANS/internal/SymbolTable.h | 66 +++++++++++++------ Utilities/rANS/src/SymbolStatistics.cxx | 12 +--- Utilities/rANS/test/test_ransEncodeDecode.cxx | 5 +- 9 files changed, 107 insertions(+), 51 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 6bed50671ba2b..8e61625d42258 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -125,3 +125,4 @@ #/Utilities/Tools #/Utilities/aliceHLTwrapper #/Utilities/hough +/Utilities/rANS @shahor02 @MichaelLettrich diff --git a/Utilities/rANS/include/rANS/Decoder.h b/Utilities/rANS/include/rANS/Decoder.h index 468f1bb629653..af121a60d43aa 100644 --- a/Utilities/rANS/include/rANS/Decoder.h +++ b/Utilities/rANS/include/rANS/Decoder.h @@ -42,7 +42,7 @@ class Decoder { protected: - using decoderSymbol_t = internal::SymbolTable<internal::DecoderSymbol>; + using decoderSymbolTable_t = internal::SymbolTable<internal::DecoderSymbol>; using reverseSymbolLookupTable_t = internal::ReverseSymbolLookupTable; using ransDecoder = internal::Decoder<coder_T, stream_T>; @@ -66,7 +66,7 @@ class Decoder using source_t = source_T; protected: - std::unique_ptr<decoderSymbol_t> mSymbolTable; + std::unique_ptr<decoderSymbolTable_t> mSymbolTable; std::unique_ptr<reverseSymbolLookupTable_t> mReverseLUT; size_t mProbabilityBits; }; @@ -74,14 +74,14 @@ class Decoder template <typename coder_T, typename stream_T, typename source_T> Decoder<coder_T, stream_T, source_T>::Decoder(const Decoder& d) : mSymbolTable(nullptr), mReverseLUT(nullptr), mProbabilityBits(d.mProbabilityBits) { - mSymbolTable = std::make_unique<decoderSymbol_t>(*d.mSymbolTable); + mSymbolTable = std::make_unique<decoderSymbolTable_t>(*d.mSymbolTable); mReverseLUT = std::make_unique<reverseSymbolLookupTable_t>(*d.mReverseLUT); } template <typename coder_T, typename stream_T, typename source_T> Decoder<coder_T, stream_T, source_T>& Decoder<coder_T, stream_T, source_T>::operator=(const Decoder& d) { - mSymbolTable = std::make_unique<decoderSymbol_t>(*d.mSymbolTable); + mSymbolTable = std::make_unique<decoderSymbolTable_t>(*d.mSymbolTable); mReverseLUT = std::make_unique<reverseSymbolLookupTable_t>(*d.mReverseLUT); mProbabilityBits = d.mProbabilityBits; return *this; @@ -96,7 +96,7 @@ Decoder<coder_T, stream_T, source_T>::Decoder(const FrequencyTable& frequencies, RANSTimer t; t.start(); - mSymbolTable = std::make_unique<decoderSymbol_t>(stats, mProbabilityBits); + mSymbolTable = std::make_unique<decoderSymbolTable_t>(stats, mProbabilityBits); t.stop(); LOG(debug1) << "Decoder SymbolTable inclusive time (ms): " << t.getDurationMS(); t.start(); diff --git a/Utilities/rANS/include/rANS/FrequencyTable.h b/Utilities/rANS/include/rANS/FrequencyTable.h index b9f357851dd3e..5304a9dd8d00c 100644 --- a/Utilities/rANS/include/rANS/FrequencyTable.h +++ b/Utilities/rANS/include/rANS/FrequencyTable.h @@ -44,12 +44,15 @@ class FrequencyTable FrequencyTable() : mMin(0), mMax(0), mNumSamples(0), mFrequencyTable(){}; - FrequencyTable(value_t min, value_t max) : mMin(0), mMax(0), mNumSamples(0), mFrequencyTable(mMax - mMin + 1, 0) + FrequencyTable(value_t min, value_t max) : mMin(min), mMax(max), mNumSamples(0), mFrequencyTable(mMax - mMin + 1, 0) { assert(mMax >= mMin); } - FrequencyTable(size_t range) : FrequencyTable(0, internal::bitsToRange(range) - 1) { assert(range >= 1); }; + FrequencyTable(size_t range) : FrequencyTable(0, internal::bitsToRange(range) - 1) + { + assert(range >= 1); + }; template <typename Source_IT> void addSamples(Source_IT begin, Source_IT end, value_t min = 0, value_t max = 0); @@ -109,11 +112,12 @@ void FrequencyTable::addSamples(Source_IT begin, Source_IT end, value_t min, val return; } - if (min != max && (!max && !min)) { - resizeFrequencyTable(min, max); - } else { + if (min == max) { const auto& [minIter, maxIter] = std::minmax_element(begin, end); resizeFrequencyTable(*minIter, *maxIter); + + } else { + resizeFrequencyTable(min, max); } for (auto it = begin; it != end; it++) { diff --git a/Utilities/rANS/include/rANS/LiteralDecoder.h b/Utilities/rANS/include/rANS/LiteralDecoder.h index e87382b4a27a8..4e8b2716184c9 100644 --- a/Utilities/rANS/include/rANS/LiteralDecoder.h +++ b/Utilities/rANS/include/rANS/LiteralDecoder.h @@ -70,7 +70,7 @@ void LiteralDecoder<coder_T, stream_T, source_T>::process(const source_IT output auto cumul = decoder.get(this->mProbabilityBits); const auto streamSymbol = (*this->mReverseLUT)[cumul]; source_T symbol = streamSymbol; - if (this->mSymbolTable->isLiteralSymbol(streamSymbol)) { + if (this->mSymbolTable->isRareSymbol(streamSymbol)) { symbol = literals.back(); literals.pop_back(); } diff --git a/Utilities/rANS/include/rANS/LiteralEncoder.h b/Utilities/rANS/include/rANS/LiteralEncoder.h index 13d4abf265bcd..989ee035cb5e5 100644 --- a/Utilities/rANS/include/rANS/LiteralEncoder.h +++ b/Utilities/rANS/include/rANS/LiteralEncoder.h @@ -80,12 +80,10 @@ const stream_IT LiteralEncoder<coder_T, stream_T, source_T>::process(const strea auto encode = [&literals, this](source_IT symbolIter, stream_IT outputIter, ransCoder& coder) { const source_T symbol = *symbolIter; const auto& encoderSymbol = (*this->mSymbolTable)[symbol]; - if (encoderSymbol.freq != 0) { - return std::tuple(symbolIter, coder.putSymbol(outputIter, encoderSymbol, this->mProbabilityBits)); - } else { + if (this->mSymbolTable->isRareSymbol(symbol)) { literals.push_back(symbol); - return std::tuple(symbolIter, coder.putSymbol(outputIter, this->mSymbolTable->getLiteralSymbol(), this->mProbabilityBits)); } + return std::tuple(symbolIter, coder.putSymbol(outputIter, encoderSymbol, this->mProbabilityBits)); }; // odd number of bytes? diff --git a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h index e648a649f1e1f..52f72f6f2c294 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h @@ -54,8 +54,14 @@ class SymbolStatistics const Iterator& operator++(); + const Iterator& operator--(); + difference_type operator-(const Iterator& other) const; + difference_type operator-(size_t idx) const; + + const Iterator& operator-(size_t idx); + value_type operator*() const; bool operator!=(const Iterator& other) const; @@ -69,7 +75,7 @@ class SymbolStatistics SymbolStatistics(const FrequencyTable& frequencyTable, size_t scaleBits); template <typename Source_IT> - SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits); + SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits, size_t nUsedAlphabetSymbols); std::tuple<uint32_t, uint32_t> operator[](int64_t index) const; std::tuple<uint32_t, uint32_t> at(size_t pos) const; @@ -77,21 +83,24 @@ class SymbolStatistics Iterator begin() const; Iterator end() const; + Iterator getEscapeSymbol() const; + size_t size() const; int64_t getMinSymbol() const; int64_t getMaxSymbol() const; + size_t getNUsedAlphabetSymbols() const; + private: void buildCumulativeFrequencyTable(); void rescale(); - size_t getNUsedAlphabetSymbols() const; - int64_t mMin; int64_t mMax; size_t mScaleBits; + size_t mNUsedAlphabetSymbols; std::vector<uint32_t> mFrequencyTable; std::vector<uint32_t> mCumulativeFrequencyTable; @@ -100,7 +109,7 @@ class SymbolStatistics }; template <typename Source_IT> -SymbolStatistics::SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits) : mMin(min), mMax(max), mScaleBits(scaleBits), mFrequencyTable(), mCumulativeFrequencyTable() +SymbolStatistics::SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits, size_t nUsedAlphabetSymbols) : mMin(min), mMax(max), mScaleBits(scaleBits), mFrequencyTable(), mNUsedAlphabetSymbols(nUsedAlphabetSymbols), mCumulativeFrequencyTable() { using namespace internal; @@ -115,7 +124,7 @@ SymbolStatistics::SymbolStatistics(const Source_IT begin, const Source_IT end, i assert(mScaleBits > 0); - //additional bit for incompressible symbol + //additional bit for escape symbol mFrequencyTable.reserve(std::distance(begin, end) + 1); mFrequencyTable.insert(mFrequencyTable.begin(), begin, end); @@ -191,6 +200,11 @@ inline SymbolStatistics::Iterator SymbolStatistics::end() const return SymbolStatistics::Iterator(mFrequencyTable.size(), *this); } +inline SymbolStatistics::Iterator SymbolStatistics::getEscapeSymbol() const +{ + return mFrequencyTable.size() > 0 ? SymbolStatistics::Iterator(mFrequencyTable.size() - 1, *this) : end(); +} + inline const SymbolStatistics::Iterator& SymbolStatistics::Iterator::operator++() { ++mIndex; @@ -198,11 +212,29 @@ inline const SymbolStatistics::Iterator& SymbolStatistics::Iterator::operator++( return *this; } +inline const SymbolStatistics::Iterator& SymbolStatistics::Iterator::operator--() +{ + --mIndex; + assert(mIndex >= 0); + return *this; +} + inline SymbolStatistics::Iterator::difference_type SymbolStatistics::Iterator::operator-(const Iterator& other) const { return mIndex - other.mIndex; } +inline SymbolStatistics::Iterator::difference_type SymbolStatistics::Iterator::operator-(size_t index) const +{ + return mIndex - index; +} + +inline const SymbolStatistics::Iterator& SymbolStatistics::Iterator::operator-(size_t index) +{ + mIndex -= index; + return *this; +} + inline typename SymbolStatistics::Iterator::value_type SymbolStatistics::Iterator::operator*() const { return std::move(mStats.at(mIndex)); diff --git a/Utilities/rANS/include/rANS/internal/SymbolTable.h b/Utilities/rANS/include/rANS/internal/SymbolTable.h index 77d9380725dff..5a74933cb942d 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolTable.h +++ b/Utilities/rANS/include/rANS/internal/SymbolTable.h @@ -39,9 +39,9 @@ class SymbolTable const T& operator[](int64_t index) const; - const T& getLiteralSymbol() const; + const T& getEscapeSymbol() const; - bool isLiteralSymbol(int64_t index) const; + bool isRareSymbol(int64_t index) const; size_t getAlphabetRangeBits() const; int getMinSymbol() const { return mMin; } @@ -52,22 +52,40 @@ class SymbolTable int mMax; std::vector<T*> mIndex; std::vector<T> mSymbols; + std::unique_ptr<T> mEscapeSymbol; }; template <typename T> -SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mMax(symbolStats.getMaxSymbol()), mIndex(), mSymbols() +SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mMax(symbolStats.getMaxSymbol()), mIndex(), mSymbols(), mEscapeSymbol(nullptr) { LOG(trace) << "start building symbol table"; mIndex.reserve(symbolStats.size()); - mSymbols.reserve(symbolStats.size()); - - for (const auto& entry : symbolStats) { - const auto [symFrequency, symCumulated] = entry; - mSymbols.emplace_back(symCumulated, symFrequency, probabiltyBits); - mIndex.emplace_back(&mSymbols.back()); + mSymbols.reserve(symbolStats.getNUsedAlphabetSymbols()); + + mEscapeSymbol = [&]() -> std::unique_ptr<T> { + const auto it = symbolStats.getEscapeSymbol(); + if (it != symbolStats.end()) { + const auto [symFrequency, symCumulated] = *(it); + return std::make_unique<T>(symCumulated, symFrequency, probabiltyBits); + } else { + return nullptr; + } + }(); + + for (auto it = symbolStats.begin(); it != symbolStats.getEscapeSymbol(); ++it) { + const auto [symFrequency, symCumulated] = *it; + if (symFrequency) { + mSymbols.emplace_back(symCumulated, symFrequency, probabiltyBits); + mIndex.emplace_back(&mSymbols.back()); + } else { + mIndex.emplace_back(mEscapeSymbol.get()); + } } + //escape symbol + mIndex.emplace_back(mEscapeSymbol.get()); + // advanced diagnostics for debug builds #if !defined(NDEBUG) LOG(debug2) << "SymbolTableProperties: {" @@ -81,25 +99,33 @@ SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabil template <typename T> inline const T& SymbolTable<T>::operator[](int64_t index) const { - const auto idx = index - mMin; - assert(idx >= 0); - assert(idx < mSymbols.size()); - return *(mIndex[idx]); + const int64_t idx = index - mMin; + // static cast to unsigned: idx < 0 => (uint)idx > MAX_INT => idx > mIndex.size() + if (static_cast<uint64_t>(idx) < mIndex.size()) { + return *(mIndex[idx]); + } else { + return *mEscapeSymbol; + } } template <typename T> -inline bool SymbolTable<T>::isLiteralSymbol(int64_t index) const +inline bool SymbolTable<T>::isRareSymbol(int64_t index) const { - const auto idx = index - mMin; - assert(idx >= 0); - assert(idx < mSymbols.size()); - return idx == mSymbols.size() - 1; + const int64_t idx = index - mMin; + // static cast to unsigned: idx < 0 => (uint)idx > MAX_INT => idx > mIndex.size() + if (static_cast<uint64_t>(idx) < mIndex.size()) { + assert(mEscapeSymbol != nullptr); + return mIndex[idx] == mEscapeSymbol.get(); + } else { + return true; + } } template <typename T> -inline const T& SymbolTable<T>::getLiteralSymbol() const +inline const T& SymbolTable<T>::getEscapeSymbol() const { - return mSymbols.back(); + assert(mEscapeSymbol != nullptr); + return *mEscapeSymbol; } template <typename T> diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx index 5e41593654b12..2b6a82793ad59 100644 --- a/Utilities/rANS/src/SymbolStatistics.cxx +++ b/Utilities/rANS/src/SymbolStatistics.cxx @@ -25,7 +25,7 @@ namespace rans namespace internal { -SymbolStatistics::SymbolStatistics(const FrequencyTable& frequencyTable, size_t scaleBits) : SymbolStatistics(frequencyTable.begin(), frequencyTable.end(), frequencyTable.getMinSymbol(), frequencyTable.getMaxSymbol(), scaleBits){}; +SymbolStatistics::SymbolStatistics(const FrequencyTable& frequencyTable, size_t scaleBits) : SymbolStatistics(frequencyTable.begin(), frequencyTable.end(), frequencyTable.getMinSymbol(), frequencyTable.getMaxSymbol(), scaleBits, frequencyTable.getUsedAlphabetSize()){}; void SymbolStatistics::rescale() { @@ -43,7 +43,7 @@ void SymbolStatistics::rescale() } const size_t newCumulatedFrequency = bitsToRange(mScaleBits); - assert(newCumulatedFrequency >= mFrequencyTable.size()); + assert(newCumulatedFrequency >= this->getNUsedAlphabetSymbols() + 1); size_t cumulatedFrequencies = mCumulativeFrequencyTable.back(); @@ -104,13 +104,7 @@ void SymbolStatistics::rescale() size_t SymbolStatistics::getNUsedAlphabetSymbols() const { - size_t nUsedAlphabetSymbols = 0; - for (auto symbolCount : mFrequencyTable) { - if (symbolCount > 0) { - ++nUsedAlphabetSymbols; - } - } - return nUsedAlphabetSymbols; + return mNUsedAlphabetSymbols; } void SymbolStatistics::buildCumulativeFrequencyTable() diff --git a/Utilities/rANS/test/test_ransEncodeDecode.cxx b/Utilities/rANS/test/test_ransEncodeDecode.cxx index 500be5f5d3e1b..83389dc06b746 100644 --- a/Utilities/rANS/test/test_ransEncodeDecode.cxx +++ b/Utilities/rANS/test/test_ransEncodeDecode.cxx @@ -75,7 +75,7 @@ typedef boost::mpl::vector<Fixture<uint32_t, uint8_t, 14>, Fixture<uint64_t, uin BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode, T, Fixtures, T) { - + fair::Logger::SetConsoleSeverity("trace"); // iterate over the message and create PDF and CDF for each symbol in the message o2::rans::FrequencyTable frequencies; frequencies.addSamples(std::begin(T::source), std::end(T::source)); @@ -109,6 +109,7 @@ typedef boost::mpl::vector<FixtureFull<uint32_t, uint8_t, 14>, FixtureFull<uint6 BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_literals, T, LiteralFixtures, T) { + fair::Logger::SetConsoleSeverity("trace"); // iterate over the message and create PDF and CDF for each symbol in the message o2::rans::FrequencyTable frequencies; @@ -148,7 +149,7 @@ typedef boost::mpl::vector<FixtureFull<uint32_t, uint8_t, 14>, FixtureFull<uint6 BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_EncodeDecode_dedup, T, DedupFixtures, T) { - + fair::Logger::SetConsoleSeverity("trace"); // iterate over the message and create PDF and CDF for each symbol in the message o2::rans::FrequencyTable frequencies; frequencies.addSamples(std::begin(T::source), std::end(T::source)); From b6135ebd5762c2ef1b2c1be7d7c7406c96a3efc5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 12 Aug 2020 22:43:23 +0200 Subject: [PATCH 0346/1751] TPC: Fix digit MC labels out of sync after zero supression --- .../TPC/reconstruction/src/GPUCATracking.cxx | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index f7eca85185a19..b5c5d956e339a 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -83,50 +83,63 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* float vzbinInv = 1.f / vzbin; Mapper& mapper = Mapper::instance(); - const ClusterNativeAccess* clusters; std::vector<o2::tpc::Digit> gpuDigits[Sector::MAXSECTOR]; + o2::dataformats::MCTruthContainer<o2::MCCompLabel> gpuDigitsMC[Sector::MAXSECTOR]; + GPUTrackingInOutDigits gpuDigitsMap; - GPUTPCDigitsMCInput gpuDigitsMC; + GPUTPCDigitsMCInput gpuDigitsMapMC; GPUTrackingInOutPointers ptrs; - if (data->compressedClusters) { - ptrs.tpcCompressedClusters = data->compressedClusters; - } else if (data->tpcZS) { - ptrs.tpcZS = data->tpcZS; - } else if (data->o2Digits) { - ptrs.clustersNative = nullptr; + ptrs.tpcCompressedClusters = data->compressedClusters; + ptrs.tpcZS = data->tpcZS; + if (data->o2Digits) { const float zsThreshold = mTrackingCAO2Interface->getConfig().configReconstruction.tpcZSthreshold; const int maxContTimeBin = mTrackingCAO2Interface->getConfig().configEvent.continuousMaxTimeBin; for (int i = 0; i < Sector::MAXSECTOR; i++) { const auto& d = (*(data->o2Digits))[i]; - gpuDigits[i].reserve(d.size()); - gpuDigitsMap.tpcDigits[i] = gpuDigits[i].data(); + if (zsThreshold > 0) { + gpuDigits[i].reserve(d.size()); + } for (int j = 0; j < d.size(); j++) { if (maxContTimeBin && d[j].getTimeStamp() >= maxContTimeBin) { throw std::runtime_error("Digit time bin exceeds time frame length"); } - if (d[j].getChargeFloat() >= zsThreshold) { - gpuDigits[i].emplace_back(d[j]); + if (zsThreshold > 0) { + if (d[j].getChargeFloat() >= zsThreshold) { + if (data->o2DigitsMC) { + for (const auto& element : (*data->o2DigitsMC)[i]->getLabels(j)) { + gpuDigitsMC[i].addElement(gpuDigits[i].size(), element); + } + } + gpuDigits[i].emplace_back(d[j]); + } + } + } + if (zsThreshold > 0) { + gpuDigitsMap.tpcDigits[i] = gpuDigits[i].data(); + gpuDigitsMap.nTPCDigits[i] = gpuDigits[i].size(); + if (data->o2DigitsMC) { + gpuDigitsMapMC.v[i] = &gpuDigitsMC[i]; + } + } else { + gpuDigitsMap.tpcDigits[i] = (*(data->o2Digits))[i].data(); + gpuDigitsMap.nTPCDigits[i] = (*(data->o2Digits))[i].size(); + if (data->o2DigitsMC) { + gpuDigitsMapMC.v[i] = (*data->o2DigitsMC)[i].get(); } } - gpuDigitsMap.nTPCDigits[i] = gpuDigits[i].size(); } if (data->o2DigitsMC) { - for (int i = 0; i < Sector::MAXSECTOR; i++) { - gpuDigitsMC.v[i] = (*data->o2DigitsMC)[i].get(); - } - gpuDigitsMap.tpcDigitsMC = &gpuDigitsMC; + gpuDigitsMap.tpcDigitsMC = &gpuDigitsMapMC; } ptrs.tpcPackedDigits = &gpuDigitsMap; - } else { - clusters = data->clusters; - ptrs.clustersNative = clusters; - ptrs.tpcPackedDigits = nullptr; } + ptrs.clustersNative = data->clusters; int retVal = mTrackingCAO2Interface->RunTracking(&ptrs, outputs); if (data->o2Digits || data->tpcZS || data->compressedClusters) { - clusters = ptrs.clustersNative; + data->clusters = ptrs.clustersNative; } + data->compressedClusters = ptrs.tpcCompressedClusters; const GPUTPCGMMergedTrack* tracks = ptrs.mergedTracks; int nTracks = ptrs.nMergedTracks; const GPUTPCGMMergedTrackHit* trackClusters = ptrs.mergedTrackHits; @@ -177,8 +190,8 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* if (lastSide ^ (trackClusters[tracks[i].FirstClusterRef() + iCl].slice < Sector::MAXSECTOR / 2)) { auto& cacl1 = trackClusters[tracks[i].FirstClusterRef() + iCl]; auto& cacl2 = trackClusters[tracks[i].FirstClusterRef() + iCl - 1]; - auto& cl1 = clusters->clustersLinear[cacl1.num]; - auto& cl2 = clusters->clustersLinear[cacl2.num]; + auto& cl1 = data->clusters->clustersLinear[cacl1.num]; + auto& cl2 = data->clusters->clustersLinear[cacl2.num]; delta = fabs(cl1.getTime() - cl2.getTime()) * 0.5f; break; } @@ -188,8 +201,8 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* // estimate max/min time increments which still keep track in the physical limits of the TPC auto& c1 = trackClusters[tracks[i].FirstClusterRef()]; auto& c2 = trackClusters[tracks[i].FirstClusterRef() + tracks[i].NClusters() - 1]; - float t1 = clusters->clustersLinear[c1.num].getTime(); - float t2 = clusters->clustersLinear[c2.num].getTime(); + float t1 = data->clusters->clustersLinear[c1.num].getTime(); + float t2 = data->clusters->clustersLinear[c2.num].getTime(); auto times = std::minmax(t1, t2); tFwd = times.first - time0; tBwd = time0 - (times.second - detParam.TPClength * vzbinInv); @@ -247,7 +260,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* int clusterIdGlobal = trackClusters[tracks[i].FirstClusterRef() + j].num; Sector sector = trackClusters[tracks[i].FirstClusterRef() + j].slice; int globalRow = trackClusters[tracks[i].FirstClusterRef() + j].row; - int clusterIdInRow = clusterIdGlobal - clusters->clusterOffset[sector][globalRow]; + int clusterIdInRow = clusterIdGlobal - data->clusters->clusterOffset[sector][globalRow]; int regionNumber = 0; while (globalRow > mapper.getGlobalRowOffsetRegion(regionNumber) + mapper.getNumberOfRowsRegion(regionNumber)) { regionNumber++; @@ -256,8 +269,8 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* sectorIndexArr[nOutCl] = sector; rowIndexArr[nOutCl] = globalRow; nOutCl++; - if (outputTracksMCTruth && clusters->clustersMCTruth) { - for (const auto& element : clusters->clustersMCTruth->getLabels(clusterIdGlobal)) { + if (outputTracksMCTruth && data->clusters->clustersMCTruth) { + for (const auto& element : data->clusters->clustersMCTruth->getLabels(clusterIdGlobal)) { bool found = false; for (int l = 0; l < labels.size(); l++) { if (labels[l].first == element) { @@ -291,10 +304,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* } } outClusRefs->resize(clusterOffsetCounter.load()); // remove overhead - if (data->o2Digits || data->tpcZS || data->compressedClusters) { - data->clusters = ptrs.clustersNative; - } - data->compressedClusters = ptrs.tpcCompressedClusters; + mTrackingCAO2Interface->Clear(false); return (retVal); From ffc33435cacddcc19a461077f1ab4df7abefd6cc Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 12 Aug 2020 23:32:54 +0200 Subject: [PATCH 0347/1751] TPC: Forward digits and digit MC labels to tracking in case of tpc-zs-on-the-fly, so we can create cluster MC labels --- .../TPC/reconstruction/src/GPUCATracking.cxx | 4 ++-- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index b5c5d956e339a..7f41b76d79cec 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -64,8 +64,8 @@ void GPUCATracking::deinitialize() int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* outputs) { - if ((int)(data->tpcZS != nullptr) + (int)(data->o2Digits != nullptr) + (int)(data->clusters != nullptr) + (int)(data->compressedClusters != nullptr) != 1) { - return 0; + if ((int)(data->tpcZS != nullptr) + (int)(data->o2Digits != nullptr && (data->tpcZS == nullptr || data->o2DigitsMC == nullptr)) + (int)(data->clusters != nullptr) + (int)(data->compressedClusters != nullptr) != 1) { + throw std::runtime_error("Invalid input for gpu tracking"); } std::vector<TrackTPC>* outputTracks = data->outputTracks; diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 536aab8a8cf98..1c1c7d68dd32d 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -268,7 +268,6 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int inputrefs[sector].labels = ref; if (specconfig.caClusterer) { inputDigitsMC[sector] = std::move(pc.inputs().get<const MCLabelContainer*>(ref)); - } else { } validMcInputs |= sectorMask; activeSectors |= sectorHeader->activeSectors; @@ -309,9 +308,9 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int activeSectors |= sectorHeader->activeSectors; validInputs |= sectorMask; inputrefs[sector].data = ref; - if (specconfig.caClusterer && !specconfig.zsOnTheFly) { + if (specconfig.caClusterer && (!specconfig.zsOnTheFly || specconfig.processMC)) { inputDigits[sector] = pc.inputs().get<gsl::span<o2::tpc::Digit>>(ref); - LOG(INFO) << "GOT SPAN FOR SECTOR " << sector << " -> " << inputDigits[sector].size(); + LOG(INFO) << "GOT DIGITS SPAN FOR SECTOR " << sector << " -> " << inputDigits[sector].size(); } } if (specconfig.zsOnTheFly) { @@ -433,7 +432,6 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int pCompClustersFlat = pc.inputs().get<CompressedClustersFlat*>("input").get(); } } else if (!specconfig.zsOnTheFly) { - // FIXME: We can have digits input in zs decoder mode for MC labels // This code path should run optionally also for the zs decoder version auto printInputLog = [&verbosity, &validInputs, &activeSectors](auto& r, const char* comment, auto& s) { if (verbosity > 1) { @@ -522,21 +520,20 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int ptrs.outputTracksMCTruth = (specconfig.processMC ? &tracksMCTruth : nullptr); if (specconfig.caClusterer) { if (specconfig.zsOnTheFly) { - std::cout << "inputZS size: " << inputZS.size() << std::endl; const unsigned long long int* buffer = reinterpret_cast<const unsigned long long int*>(&inputZS[0]); o2::gpu::GPUReconstructionConvert::RunZSEncoderCreateMeta(buffer, tpcZSonTheFlySizes.data(), *&ptrEp, &tpcZS); ptrs.tpcZS = &tpcZS; if (specconfig.processMC) { - throw std::runtime_error("Currently unable to process MC information, tpc-tracker crashing when MC propagated"); + ptrs.o2Digits = &inputDigits; ptrs.o2DigitsMC = &inputDigitsMC; } } else if (specconfig.zsDecoder) { ptrs.tpcZS = &tpcZS; if (specconfig.processMC) { - throw std::runtime_error("Cannot process MC information, none available"); // In fact, passing in MC data with ZS TPC Raw is not yet available + throw std::runtime_error("Cannot process MC information, none available"); } } else { - ptrs.o2Digits = &inputDigits; // TODO: We will also create ClusterNative as output stored in ptrs. Should be added to the output + ptrs.o2Digits = &inputDigits; if (specconfig.processMC) { ptrs.o2DigitsMC = &inputDigitsMC; } @@ -679,16 +676,16 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, specconfig.decompressTPCFromROOT ? header::DataDescription("COMPCLUSTERS") : header::DataDescription("COMPCLUSTERSFLAT")}, Lifetime::Timeframe}); } else if (specconfig.caClusterer) { // We accept digits and MC labels also if we run on ZS Raw data, since they are needed for MC label propagation - if (!specconfig.zsOnTheFly && !specconfig.zsDecoder) { // FIXME: We can have digits input in zs decoder mode for MC labels, to be made optional + if ((!specconfig.zsOnTheFly || specconfig.processMC) && !specconfig.zsDecoder) { inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe}); } } else { inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, "CLUSTERNATIVE"}, Lifetime::Timeframe}); } if (specconfig.processMC) { - if (!specconfig.zsOnTheFly && specconfig.caClusterer) { + if (specconfig.caClusterer) { constexpr o2::header::DataDescription datadesc("DIGITSMCTR"); - if (!specconfig.zsDecoder) { // FIXME: We can have digits input in zs decoder mode for MC labels, to be made optional + if (!specconfig.zsDecoder) { inputs.emplace_back(InputSpec{"mclblin", ConcreteDataTypeMatcher{gDataOriginTPC, datadesc}, Lifetime::Timeframe}); } } else { From 0814f35eaf7ae0de39196d3300de2f3f4e7f05b1 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Sat, 25 Jul 2020 16:46:40 +0200 Subject: [PATCH 0348/1751] trap2raw to convert trap output to cru output --- .../TRD/include/DataFormatsTRD/LinkRecord.h | 1 + .../TRD/include/DataFormatsTRD/RawData.h | 3 +- DataFormats/Detectors/TRD/src/RawData.cxx | 57 +++- Detectors/TRD/simulation/CMakeLists.txt | 11 + .../include/TRDSimulation/Trap2CRU.h | 94 ++++++ .../TRD/simulation/src/TRDSimulationLinkDef.h | 1 + Detectors/TRD/simulation/src/Trap2CRU.cxx | 302 ++++++++++++++++++ Detectors/TRD/simulation/src/trap2raw.cxx | 140 ++++++++ .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 31 +- 9 files changed, 622 insertions(+), 18 deletions(-) create mode 100644 Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h create mode 100644 Detectors/TRD/simulation/src/Trap2CRU.cxx create mode 100644 Detectors/TRD/simulation/src/trap2raw.cxx diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h index f0bf477278351..a7cbef0dc42bf 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h @@ -41,6 +41,7 @@ class LinkRecord void setNumberOfObjects(int nentries) { mDataRange.setEntries(nentries); } uint32_t getLinkId() { return mLinkId; } + uint32_t getLinkHCID() { return mLinkId & 0x7ff; } // the last 11 bits. int getNumberOfObjects() const { return mDataRange.getEntries(); } int getFirstEntry() const { return mDataRange.getFirstEntry(); } diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h index 9799528106e03..33559ae0fe251 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -249,7 +249,8 @@ uint32_t getSlope(const *rawdata, int tracklet) } due to the interplay of TrackletMCMHeader and TrackletMCMData come back to this. TODO */ - +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); uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data); uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link); uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link); diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index 0e86eab05fb1d..7bb3e82973ef5 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -10,6 +10,7 @@ #include <iomanip> #include <iostream> +#include <iomanip> #include "DataFormatsTRD/RawData.h" namespace o2 @@ -53,6 +54,25 @@ uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t, 1 return 0; } +uint32_t setHalfCRUHeader(HalfCRUHeader& cruhead, int crurdhversion, int bunchcrossing, int stopbits, int endpoint, int eventtype, int feeid, int cruid) +{ + cruhead.BunchCrossing = bunchcrossing; + cruhead.StopBit = stopbits; + cruhead.EndPoint = endpoint; + cruhead.EventType = eventtype; + //later versions + // cruhead.rdhversion = crurdhversion; + // cruhead.FeeID = feeid; + // cruhead.CRUID = cruid; + return 0; +} + +uint32_t setHalfCRUHeaderLinkData(HalfCRUHeader& cruhead, int link, int size, int errors) +{ + cruhead.datasizes[link].size = size; + cruhead.errorflags[link].errorflag = errors; + return 0; +} // // Printing methods to dump and display the various structures above in pretty format or hexdump // printNameOfStruct(const NameOfStruct& nameofstruct); @@ -62,37 +82,46 @@ uint32_t getlinkdatasizes(const HalfCRUHeader& cruheader, std::array<uint32_t, 1 std::ostream& operator<<(std::ostream& stream, const TrackletHCHeader halfchamberheader) { - stream << "TrackletHCHeader : Raw:0x" << std::hex << halfchamberheader.word << " " << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; + stream << "TrackletHCHeader : Raw:0x" << std::hex << halfchamberheader.word << " " + << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " + << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; return stream; } std::ostream& operator<<(std::ostream& stream, const TrackletMCMData& tracklet) { // make a pretty output of the tracklet. - stream << "TrackletMCMData: Raw:0x" << std::hex << tracklet.word << " pos=" << tracklet.pos << "::slope=" << tracklet.slope << "::pid=" << tracklet.pid << "::checkbit=" << tracklet.checkbit << std::endl; + stream << "TrackletMCMData: Raw:0x" << std::hex << tracklet.word << " pos=" << tracklet.pos + << "::slope=" << tracklet.slope << "::pid=" << tracklet.pid << "::checkbit=" + << tracklet.checkbit << std::endl; return stream; } void printTrackletMCMData(o2::trd::TrackletMCMData& tracklet) { - LOGF(INFO, "TrackletMCMData: Raw:0x%08x pos:%d slope:%d pid:0x%08x checkbit:0x%02x", tracklet.word, tracklet.pos, tracklet.slope, tracklet.pid, tracklet.checkbit); + LOGF(INFO, "TrackletMCMData: Raw:0x%08x pos:%d slope:%d pid:0x%08x checkbit:0x%02x", + tracklet.word, tracklet.pos, tracklet.slope, tracklet.pid, tracklet.checkbit); } void printTrackletMCMHeader(o2::trd::TrackletMCMHeader& mcmhead) { - LOGF(INFO, "MCMRawHeader: Raw:0x%08x 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d", mcmhead.word, mcmhead.onea, mcmhead.padrow, mcmhead.col, mcmhead.pid2, mcmhead.pid1, mcmhead.pid0, mcmhead.oneb); + LOGF(INFO, "MCMRawHeader: Raw:0x%08x 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d", + mcmhead.word, mcmhead.onea, mcmhead.padrow, mcmhead.col, + mcmhead.pid2, mcmhead.pid1, mcmhead.pid0, mcmhead.oneb); } std::ostream& operator<<(std::ostream& stream, const TrackletMCMHeader& mcmhead) { // make a pretty output of the mcm header. - // stream << "MCMRawHeader:" << mcmhead.checkbits << "::" << (mcmhead.pid&0xfff000000) << ":"<< (mcmhead.pid&0xfff000) << ":"<< (mcmhead.pid&0xfff) << std::endl; - stream << "MCMRawHeader: Raw:0x" << std::hex << mcmhead.word << " " << mcmhead.onea << "::" << mcmhead.pid2 << ":" << mcmhead.pid1 << ":" << mcmhead.pid0 << "::" << mcmhead.oneb << std::endl; + stream << "MCMRawHeader: Raw:0x" << std::hex << mcmhead.word << " " << mcmhead.onea << "::" + << mcmhead.pid2 << ":" << mcmhead.pid1 << ":" << mcmhead.pid0 << "::" + << mcmhead.oneb << std::endl; return stream; } void printHalfChamber(o2::trd::TrackletHCHeader& 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 HCID : 0x%0x MCLK: 0x%0x Format: 0x%0x Always1:0x%0x", + halfchamber.HCID, halfchamber.MCLK, halfchamber.format, halfchamber.one); } void dumpHalfChamber(o2::trd::TrackletHCHeader& halfchamber) @@ -106,23 +135,25 @@ void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) std::array<uint32_t, 15> errorflags; getlinkdatasizes(halfcru, sizes); getlinkerrorflags(halfcru, errorflags); - LOGF(INFO, "V:%d BC:%d SB:%d EType:%d", halfcru.HeaderVersion, halfcru.BunchCrossing, halfcru.StopBit, halfcru.EventType); + LOGF(INFO, "V:%d BC:%d SB:%d EType:%d", halfcru.HeaderVersion, halfcru.BunchCrossing, + halfcru.StopBit, halfcru.EventType); for (int i = 0; i < 15; i++) LOGF(INFO, "Link %d size: %ul eflag: 0x%02x", i, sizes[i], errorflags[i]); } void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) { - std::array<uint32_t, 16> raw{}; + std::array<uint64_t, 8> raw{}; memcpy(&raw[0], &halfcru, sizeof(halfcru)); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 2; i++) { int index = 4 * i; - LOGF(INFO, "[1/2CRUHeader %d] 0x%08x 0x%08x 0x%08x 0x%08x", i, raw[index + 3], raw[index + 2], raw[index + 1], raw[index + 0]); + LOGF(INFO, "[1/2CRUHeader %d] 0x%08x 0x%08x 0x%08x 0x%08x", i, raw[index + 3], raw[index + 2], + raw[index + 1], raw[index + 0]); } } -std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) // make a pretty output of the header. -{ +std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) +{ // make a pretty output of the header. stream << std::hex; stream << "EventType : " << halfcru.EventType << std::endl; stream << "StopBit : " << halfcru.StopBit << std::endl; diff --git a/Detectors/TRD/simulation/CMakeLists.txt b/Detectors/TRD/simulation/CMakeLists.txt index b1107bbc1e9d1..0292114818995 100644 --- a/Detectors/TRD/simulation/CMakeLists.txt +++ b/Detectors/TRD/simulation/CMakeLists.txt @@ -20,6 +20,7 @@ o2_add_library(TRDSimulation src/TrapConfig.cxx src/TrapConfigHandler.cxx src/TrapSimulator.cxx + src/Trap2CRU.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::SimulationDataFormat O2::TRDBase O2::DataFormatsTRD O2::DetectorsRaw) o2_target_root_dictionary(TRDSimulation @@ -29,6 +30,7 @@ o2_target_root_dictionary(TRDSimulation include/TRDSimulation/TRDSimParams.h include/TRDSimulation/TrapConfig.h include/TRDSimulation/TrapConfigHandler.h + include/TRDSimulation/Trap2CRU.h include/TRDSimulation/TrapSimulator.h) if (OpenMP_CXX_FOUND) @@ -38,3 +40,12 @@ endif() o2_data_file(COPY data DESTINATION Detectors/TRD/simulation) +o2_add_executable(trap2raw + COMPONENT_NAME trd + SOURCES src/trap2raw.cxx + PUBLIC_LINK_LIBRARIES O2::TRDSimulation + O2::DetectorsRaw + O2::DetectorsCommonDataFormats + O2::CommonUtils + O2::DataFormatsTRD + Boost::program_options) diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h b/Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h new file mode 100644 index 0000000000000..7b1982c83f5c6 --- /dev/null +++ b/Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h @@ -0,0 +1,94 @@ +// 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. + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD Trap2CRU class // +// Class to take the trap output that arrives at the cru and produce // +// the cru output. I suppose a cru simulator // +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ALICE_O2_TRD_TRAP2CRU_H +#define ALICE_O2_TRD_TRAP2CRU_H + +#include <string> +#include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/LinkRecord.h" +#include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/Tracklet64.h" +//#include "DetectorsRaw/HBFUtils.h" +#include "DetectorsRaw/RawFileWriter.h" + +namespace o2 +{ +namespace trd +{ + +class Trap2CRU +{ + static constexpr int NumberOfCRU = 36; + static constexpr int NumberOfHalfCRU = 72; + static constexpr int NumberOfFLP = 12; + static constexpr int CRUperFLP = 3; + static constexpr int WordSizeInBytes = 256; // word size in bits, everything is done in 256 bit blocks. + static constexpr int WordSize = 8; // 8 standard 32bit words. + static constexpr int NLinksPerHalfCRU = 15; + static constexpr uint32_t PaddWord = 0xeeee; // pad word to fill 256bit blocks or entire block for no data case. + //TODO come back and change the mapping of 1077 channels to a lut and probably configurable. + // + public: + Trap2CRU() = default; + Trap2CRU(const std::string& outputDir, const std::string& inputFilename); + void readTrapData(const std::string& otuputDir, const std::string& inputFilename, int superPageSizeInB); + void convertTrapData(o2::trd::TriggerRecord const& TrigRecord); + // default for now will be file per half cru as per the files Guido did for us. + // TODO come back and give users a choice. + // void setFilePerLink(){mfileGranularity = mgkFilesPerLink;}; + // bool getFilePerLink(){return (mfileGranularity==mgkFilesPerLink);}; + // void setFilePerHalfCRU(){mfileGranularity = mgkFilesPerHalfCRU;}; + // bool getFilePerHalfCRU(){return (mfileGranularity==mgkFilesPerHalfCRU);}; // + int getVerbosity() { return mVerbosity; } + void setVerbosity(int verbosity) { mVerbosity = verbosity; } + void buildCRUPayLoad(); + o2::raw::RawFileWriter& getWriter() { return mWriter; } + uint32_t buildCRUHeader(HalfCRUHeader& header, uint32_t bc, uint32_t halfcru, int startlinkrecord); + void linkSizePadding(uint32_t linksize, uint32_t& crudatasize, uint32_t& padding); + + private: + int mfileGranularity; /// per link or per half cru for each file + uint32_t mLinkID; + uint16_t mCruID; + uint64_t mFeeID; + uint32_t mEndPointID; + std::string mInputFilename; + std::string mOutputFilename; + int mVerbosity = 0; + HalfCRUHeader mHalfCRUHeader; + TrackletMCMHeader mTrackletMCMHeader; + TrackletMCMData mTrackletMCMData; + + std::vector<char> mRawData; // store for building data event for a single half cru + uint32_t mRawDataPos = 0; + TFile* mTrapRawFile; + TTree* mTrapRawTree; // incoming data tree + // locations to store the incoming data branches + std::vector<o2::trd::LinkRecord> mLinkRecords, *mLinkRecordsPtr = &mLinkRecords; + std::vector<o2::trd::TriggerRecord> mTriggerRecords, *mTriggerRecordsPtr = &mTriggerRecords; + std::vector<uint32_t> mTrapRawData, *mTrapRawDataPtr = &mTrapRawData; + + const o2::raw::HBFUtils& mSampler = o2::raw::HBFUtils::Instance(); + o2::raw::RawFileWriter mWriter{"TRD"}; + + ClassDefNV(Trap2CRU, 1); +}; + +} // end namespace trd +} // end namespace o2 +#endif diff --git a/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h b/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h index b7c96d2753619..851660dbdd90c 100644 --- a/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h +++ b/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h @@ -25,6 +25,7 @@ #pragma link C++ class o2::trd::TrapConfig::TrapDmemWord + ; #pragma link C++ class o2::trd::TrapConfig::TrapRegister + ; #pragma link C++ class o2::trd::TrapSimulator + ; +#pragma link C++ class o2::trd::Trap2CRU + ; #pragma link C++ class o2::trd::TRDSimParams + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::trd::TRDSimParams> + ; diff --git a/Detectors/TRD/simulation/src/Trap2CRU.cxx b/Detectors/TRD/simulation/src/Trap2CRU.cxx new file mode 100644 index 0000000000000..d2492ff84b9ee --- /dev/null +++ b/Detectors/TRD/simulation/src/Trap2CRU.cxx @@ -0,0 +1,302 @@ +// 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. + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD Trap2CRU class // +// Class to take the trap output that arrives at the cru and produce // +// the cru output. A data mapping more than a cru simulator // +/////////////////////////////////////////////////////////////////////////////// + +#include <string> + +#include "Headers/RAWDataHeader.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/LinkRecord.h" +#include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/Tracklet64.h" +#include "DetectorsRaw/HBFUtils.h" +#include "DetectorsRaw/RawFileWriter.h" +#include "TRDSimulation/Trap2CRU.h" +#include "CommonUtils/StringUtils.h" +#include "TRDBase/TRDCommonParam.h" +#include "TFile.h" +#include "TTree.h" +#include <TStopwatch.h> +#include <cassert> +#include <fstream> +#include <iostream> +#include <array> +#include <string> +#include <bitset> +#include <vector> +#include <gsl/span> + +using namespace o2::raw; + +namespace o2 +{ +namespace trd +{ + +Trap2CRU::Trap2CRU(const std::string& outputDir, const std::string& inputFilename) +{ + readTrapData(outputDir, inputFilename, 1024 * 1024); +} + +void Trap2CRU::readTrapData(const std::string& otuputDir, const std::string& inputFilename, int superPageSizeInB) +{ + //set things up, read the file and then deligate to convertTrapdata to do the conversion. + // + mRawData.reserve(1024 * 1024); //TODO take out the hardcoded 1MB its supposed to come in from the options + LOG(info) << "Trap2CRU::readTrapData"; + // data comes in index by event (triggerrecord) and link (linke record) both sequentially. + // first 15 links go to cru0a, second 15 links go to cru0b, 3rd 15 links go to cru1a ... first 90 links to flp0 and then repate for 12 flp + // then do next event + + // lets register our links + for (int link = 0; link < NumberOfCRU; link++) { + mFeeID = link; + mCruID = link; + mEndPointID = link * 2; + mLinkID = link; + std::string outputFilelink = o2::utils::concat_string("trd_cru_", std::to_string(link), "_a.raw"); + mWriter.registerLink(mFeeID, mCruID, mLinkID, mEndPointID, outputFilelink); + outputFilelink = o2::utils::concat_string("trd_cru_", std::to_string(link), "_b.raw"); + mEndPointID++; + mWriter.registerLink(mFeeID, mCruID, mLinkID, mEndPointID, outputFilelink); + } + mTrapRawFile = TFile::Open(inputFilename.data()); + assert(mTrapRawFile != nullptr); + LOG(info) << "Trap Raw file open " << inputFilename; + mTrapRawTree = (TTree*)mTrapRawFile->Get("o2sim"); + + mTrapRawTree->SetBranchAddress("TrapLinkRecord", &mLinkRecordsPtr); // branch with the link records + mTrapRawTree->SetBranchAddress("RawTriggerRecord", &mTriggerRecordsPtr); // branch with the trigger records + mTrapRawTree->SetBranchAddress("TrapRaw", &mTrapRawDataPtr); // branch with the actual incoming data. + + for (int entry = 0; entry < mTrapRawTree->GetEntries(); entry++) { + mTrapRawTree->GetEntry(entry); + LOG(debug) << "Before Trigger Reord loop Event starts at:" << mTriggerRecords[0].getFirstEntry() << " and has " << mTriggerRecords[0].getNumberOfObjects() << " entries"; + uint32_t linkcount = 0; + for (auto trigger : mTriggerRecords) { + //get the event limits from TriggerRecord; + uint32_t eventstart = trigger.getFirstEntry(); + uint32_t eventend = trigger.getFirstEntry() + trigger.getNumberOfObjects(); + LOG(info) << "Event starts at:" << eventstart << " and ends at :" << eventend; + convertTrapData(trigger); + } + } +} + +void Trap2CRU::buildCRUPayLoad() +{ + // go through the data for the event in question, produce the raw stream for each cru. + // i.e. 30 link per cru, 3cru per flp. + // 30x [HalfCRUHeader, TrackletHCHeader0, [MCMHeader TrackletMCMData. .....] TrackletHCHeader1 ..... TrackletHCHeader30 ...] + // + // data must be padded into blocks of 256bit so on average 4 padding 32 bit words. +} + +void Trap2CRU::linkSizePadding(uint32_t linksize, uint32_t& crudatasize, uint32_t& padding) +{ + // all data must be 256 bit aligned (8x64bit). + // if zero the whole 256 bit must be padded (empty link) + // crudatasize is the size to be stored in the cruheader, i.e. units of 256bits. + // linksize is the incoming link size from the linkrecord, + // padding is of course the amount of padding in 32bit words. + uint32_t rem = 0; + if (linksize != 0) { + //data, so figure out padding cru word, the other case is simple, full padding if size=0 + rem = linksize % 8; + if (rem != 0) { + crudatasize = linksize / 8 + 1; + padding = 8 - rem; + } else { + + crudatasize = linksize / 8; // 32 bit word to 256 bit word. + padding = 0; + } + LOG(debug) << "We have data with linkdatasize=" << linksize << " with size number in header of:" << crudatasize << " padded with " << padding << " 32bit words"; + } else { + //linksize is zero so no data, pad fully. + crudatasize = 1; + padding = 8; + LOG(debug) << "We have data with linkdatasize=" << linksize << " with size number in header of:" << crudatasize << " padded with " << padding << " 32bit words"; + } + LOG(debug) << "linkSizePadding : CRUDATASIZE : " << crudatasize; +} + +uint32_t Trap2CRU::buildCRUHeader(HalfCRUHeader& header, uint32_t bc, uint32_t halfcru, int startlinkrecord) +{ + int bunchcrossing = bc; + int stopbits = 0x01; // do we care about this and eventtype in simulations? + int eventtype = 0x01; + int crurdhversion = 6; + int feeid = 0; //TODO must be in cruheader down the road, inside the reserved somewhere ... + int cruid = 0; //TODO """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + uint32_t crudatasize = 0; //link size in units of 256 bits. + int endpoint = halfcru % 2 ? 1 : 0; //TODO figure out a value ... endpoint needs a rebase to PR4106 + uint32_t padding = 0; + //setHalfCRUHeader(halfcruheader, rdhversion, bunchcrossing, stopbits, endpoint, eventtype); //TODO come back and pull this from somewhere. + setHalfCRUHeader(header, crurdhversion, bunchcrossing, stopbits, endpoint, eventtype, feeid, cruid); //TODO come back and pull this from somewhere. + // memset(&tmpLinkInfo[0],0,sizeof(tmpLinkInfo[0])*tmpLinkInfo.size()); + + // halfcruheader from the relevant mLinkRecords. + int linkrecord = startlinkrecord; + int totallinkdatasize = 0; //in units of 256bits + for (int link = 0; link < NLinksPerHalfCRU; link++) { + int hcid = link + halfcru * NLinksPerHalfCRU; // TODO this might have to change to a lut I dont think the mapping is linear. + int errors = 0; + int linksize = 0; // linkSizePadding will convert it to 1 for the no data case. + if (mLinkRecords[linkrecord].getLinkHCID() == hcid) { + linksize = mLinkRecords[linkrecord].getNumberOfObjects(); + // this can be done differently by keeping a pointer to halfcruheader and setting it after reading it all in and going back per link to set the size. + // LOG(info) << "setting CRU HEADER for halfcru : " << halfcru << "and link : " << link << " contents" << halfcruheader << ":" << link << ":" << linksize << ":" << errors; + linkrecord++; // increment locally for walking through linkrecords. + } + linkSizePadding(linksize, crudatasize, padding); + setHalfCRUHeaderLinkData(header, link, crudatasize, errors); // write one padding block for empty links. + totallinkdatasize += crudatasize; + } + return totallinkdatasize; +} + +void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) +{ + + //build a HalfCRUHeader for this event/cru/endpoint + //loop over cru's + // loop over all half chambers, thankfully they data is sorted. + // check if current chamber has a link + // if not blank, else fill in data from link records + // dump data to rawwriter + //finished for event. this method is only called per event. + int currentlinkrecord = 0; + char* traprawdataptr = (char*)&mTrapRawData[0]; + for (int halfcru = 0; halfcru < NumberOfHalfCRU; halfcru++) { //TODO come back and replace 72 with something. + // TrackletHC + memset(&mRawData[0], 0, sizeof(mRawData[0]) * mRawData.size()); // zero the rawdata storage + int numberofdetectors = o2::trd::kNdet; + HalfCRUHeader halfcruheader; + //now write the cruheader at the head of all the data for this halfcru. + LOG(debug) << "cru before building cruheader for halfcru index : " << halfcru << " with contents \n" + << halfcruheader; + uint32_t totalhalfcrudatasize = buildCRUHeader(halfcruheader, TrigRecord.getBCData().bc, halfcru, currentlinkrecord); + + std::vector<char> rawdatavector(totalhalfcrudatasize * 32 + sizeof(halfcruheader)); // sum of link sizes + padding in units of bytes and some space for the header (512 bytes). + char* rawdataptr = rawdatavector.data(); + LOG(info) << "before writing halfcruheader pionter is sitting at " << std::hex << static_cast<void*>(rawdataptr); + dumpHalfCRUHeader(halfcruheader); + memcpy(rawdataptr, (char*)&halfcruheader, sizeof(halfcruheader)); + std::array<uint64_t, 8> raw{}; + memcpy((char*)&raw[0], rawdataptr, sizeof(halfcruheader)); + for (int i = 0; i < 2; i++) { + int index = 4 * i; + LOGF(debug, "[1/2rawdaptr %d] 0x%08x 0x%08x 0x%08x 0x%08x", i, raw[index + 3], raw[index + 2], raw[index + 1], raw[index + 0]); + } + rawdataptr += sizeof(halfcruheader); + LOG(info) << "For writing halfcruheader pionter advanced by " << std::dec << sizeof(halfcruheader) << " ptr is now at:" << std::hex << static_cast<void*>(rawdataptr); + LOG(debug) << "Just wrote cruheader for halfcru index : " << halfcru << " with contents \n" + << halfcruheader; + LOG(debug) << "end of halfcruheader"; + + int linkdatasize = 0; // in 32 bit words + int link = halfcru / 2; + int endpoint = halfcru; + for (int halfcrulink = 0; halfcrulink < NLinksPerHalfCRU; halfcrulink++) { + //links run from 0 to 14, so hcid offset is halfcru*15; + int hcid = halfcrulink + halfcru * NLinksPerHalfCRU; // TODO this might have to change to a lut I dont think the mapping is linear. + LOG(info) << "Currently checking for data on hcid : " << hcid << " from halfcru=" << halfcru << " and halfcrulink:" << halfcrulink << " ?? " << hcid << "==" << mLinkRecords[currentlinkrecord].getLinkHCID(); + int errors = 0; // put no errors in for now. + int size = 0; // in 32 bit words + int datastart = 0; // in 32 bit words + int dataend = 0; // in 32 bit words + uint32_t paddingsize = 0; // in 32 bit words + uint32_t crudatasize = 0; // in 256 bit words. + if (mLinkRecords[currentlinkrecord].getLinkHCID() == hcid) { + //this link has data in the stream. + LOG(info) << "+++ We have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; + linkdatasize = mLinkRecords[currentlinkrecord].getNumberOfObjects(); + datastart = mLinkRecords[currentlinkrecord].getFirstEntry(); + dataend = datastart + size; + LOG(info) << "We have data on hcid = " << hcid << " and linksize : " << linkdatasize << " so :" << linkdatasize / 8 << " 256 bit words"; + currentlinkrecord++; + } else { + assert(mLinkRecords[currentlinkrecord].getLinkId() < hcid); + LOG(info) << "---We do not have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; + //blank data for this link??? what do i do? + // put in a 1 256 bit word of data for the link and padd with 0xeeee x 8 + // tmpLinkInfo[halfcrulink] = -1; + linkdatasize = 0; + paddingsize = 8; + } + // now copy data to rawdata, padding as and where needed. + // + linkSizePadding(linkdatasize, crudatasize, paddingsize); //TODO this can come out as we have already called it, but previously we have lost the #padding words, solve to remove. + + LOG(info) << "WRITING " << crudatasize << " 256 bit data words to output stream"; + LOG(info) << "setting CRY HEADER for " << halfcruheader << ":" << halfcrulink << ":" << crudatasize << ":" << errors; + // now pad .... + LOG(info) << " now to pump data into the stream with : " << linkdatasize << " crudatasize:" << crudatasize << " paddingsize: " << paddingsize << " and rem:" << linkdatasize % 8; + char* olddataptr = rawdataptr; // store the old pointer so we can do some sanity checks for how far we advance. + //linkdatasize is the #of 32 bit words coming from the incoming tree. + //paddingsize is the number of padding words to add 0xeeee + uint32_t bytestocopy = linkdatasize * (sizeof(uint32_t)); + LOG(info) << "copying " << bytestocopy << " bytes of link tracklet data at pos:" << std::hex << static_cast<void*>(rawdataptr); + memcpy(rawdataptr, traprawdataptr, bytestocopy); + //increment pointer + rawdataptr += bytestocopy; + traprawdataptr += bytestocopy; + //now for padding + uint16_t padbytes = paddingsize * sizeof(uint32_t); + LOG(info) << "writing " << padbytes << " bytes of padding data at pos:" << std::hex << static_cast<void*>(rawdataptr); + memset(rawdataptr, 0xee, padbytes); + //increment pointer. + rawdataptr += padbytes; + if (padbytes + bytestocopy != crudatasize * 32) { + LOG(info) << "something wrong with data size writing padbytes:" << padbytes << " bytestocopy : " << bytestocopy << " crudatasize:" << crudatasize; + } + LOG(debug3) << std::hex << " rawdataptr:" << static_cast<void*>(rawdataptr) << " traprawdataptr " << static_cast<void*>(traprawdataptr); + // printf(std::cout << std::hex << " rawdataptr:0x"<<&rawdataptr << " traprawdataptr 0x"<<&traprawdataptr << std::endl; + //sanity check for now: + if (((char*)rawdataptr - (char*)olddataptr) != crudatasize * 32) { // cru words are 8 uint32 and comparison is in bytes. + LOG(debug) << "according to pointer arithmatic we have added " << rawdataptr - olddataptr << "bytes from " << static_cast<void*>(rawdataptr) << "-" << static_cast<void*>(olddataptr) << " when we should have added " << crudatasize * 8 * 4 << " because crudatasize=" << crudatasize; + } + if (crudatasize != o2::trd::getlinkdatasize(halfcruheader, halfcrulink)) { + // we have written the wrong amount of data .... + LOG(debug) << "crudata is ! = get link data size " << crudatasize << "!=" << o2::trd::getlinkdatasize(halfcruheader, halfcrulink); + } + // if(crudatasize ==0)LOG(info) << "CRUDATASIZ EIS ZERO" ; + // if(crudatasize>0){ + // std::ofstream out1("crutestdumphalfcrurawdata"); + // std::ofstream out2("crutestdumprawdatavector"); + // LOG(info) << "writing out " << halfcrurawdata.size() << " and" << crudatasize*32; + // out1.write(halfcrurawdata.data(),halfcrurawdata.size()); + // out2.write(rawdatavector.data(),crudatasize*32); + // out1.flush(); + // out2.flush(); + // exit(1); + // } + LOG(info) << "copied " << crudatasize * 32 << "bytes to halfcrurawdata which now has size of " << rawdatavector.size() << " for " << link << ":" << endpoint; + } + // std::vector<char> halfcrurawdata(crudatasize * 32); // vector of 256bit words * 32 to get to 8 bit words + + mWriter.addData(link, link, link, endpoint, TrigRecord.getBCData(), rawdatavector); + std::ofstream out2("crutestdumprawdatavector"); + out2.write(rawdatavector.data(), rawdatavector.size()); + out2.flush(); + // halfcru = NumberOfHalfCRU; // exit loop after 1 half cru for now. + } +} + +} // end namespace trd +} // end namespace o2 diff --git a/Detectors/TRD/simulation/src/trap2raw.cxx b/Detectors/TRD/simulation/src/trap2raw.cxx new file mode 100644 index 0000000000000..bcba5a7c959dd --- /dev/null +++ b/Detectors/TRD/simulation/src/trap2raw.cxx @@ -0,0 +1,140 @@ +// 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. + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD Raw data format generation // +// Take the output of the trapsimulator the [2-4]x32 bit words and // +// associated headers and links etc. and produce the output of the cru. // +// Hence the incredibly original name. // +// // +// Some parts bare a striking resemblence to (at least when written) // +// FIT/FTO/simulation/src/digit2raw.cxx // +/////////////////////////////////////////////////////////////////////////////// + +#include "fairlogger/Logger.h" + +#include <DataFormatsTRD/RawData.h> +#include <DataFormatsTRD/Tracklet64.h> +#include <DataFormatsTRD/LinkRecord.h> +#include <DataFormatsTRD/TriggerRecord.h> + +#include "CommonUtils/StringUtils.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "DetectorsRaw/HBFUtils.h" +#include "TRDSimulation/Trap2CRU.h" +#include "DataFormatsParameters/GRPObject.h" + +#include <boost/program_options.hpp> +#include <TSystem.h> +#include <TFile.h> +#include <TStopwatch.h> +#include <string> +#include <iomanip> +#include <iostream> +#include <iomanip> +#include "TCanvas.h" +#include <TTree.h> +#include <TFile.h> +#include <ostream> +#include <fstream> + +namespace bpo = boost::program_options; + +void trap2raw(const std::string& inpName, const std::string& outDir, int verbosity, + bool filePerLink, uint32_t rdhV = 4, bool noEmptyHBF = false, + int superPageSizeInB = 1024 * 1024); + +int main(int argc, char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + "Convert TRD sim otuput to CRU raw data\n"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + add_option("verbosity,v", bpo::value<int>()->default_value(0), "verbosity level"); + add_option("input-file,i", bpo::value<std::string>()->default_value("trdtrapraw.root"), "input Trapsim raw file"); + add_option("file-per-halfcru,l", bpo::value<bool>()->default_value(false)->implicit_value(true), "create output file per half cru, 2 files per cru 15 links each."); + add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); + uint32_t defRDH = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>(); + add_option("rdh-version,r", bpo::value<uint32_t>()->default_value(defRDH), "RDH version to use"); + add_option("no-empty-hbf,e", bpo::value<bool>()->default_value(false)->implicit_value(true), "do not create empty HBF pages (except for HBF starting TF)"); + // add_option("data-format,d", bpo::value<uint32_t>()->default_value(1)->implicit_value(true), "format of data, default 1, see documentation."); + add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help")) { + std::cout << opt_general << std::endl; + exit(0); + } + + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + // o2::conf::ConfigurableParam::updateFromString(vm["configKeyValues"].as<std::string>()); + + std::cout << "yay it ran" << std::endl; + trap2raw(vm["input-file"].as<std::string>(), vm["output-dir"].as<std::string>(), vm["verbosity"].as<int>(), + vm["file-per-halfcru"].as<bool>(), vm["rdh-version"].as<uint32_t>(), vm["no-empty-hbf"].as<bool>()); + + return 0; +} + +void trap2raw(const std::string& inpName, const std::string& outDir, int verbosity, bool filePerLink, uint32_t rdhV, bool noEmptyHBF, int superPageSizeInB) +{ + + TStopwatch swTot; + swTot.Start(); + o2::trd::Trap2CRU mc2raw; + //mc2raw.setFilePerLink(filePerLink); TODO come back to this, lets get it working first. + mc2raw.setVerbosity(verbosity); + auto& wr = mc2raw.getWriter(); + std::string inputGRP = o2::base::NameConf::getGRPFileName(); + const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP); + // wr.setContinuousReadout(grp->isDetContinuousReadOut(o2::detectors::DetID::TRD)); // must be set explicitly + wr.setContinuousReadout(false); // above should work, but I know this is correct, come back TODO + wr.setSuperPageSize(superPageSizeInB); + wr.useRDHVersion(rdhV); + wr.setDontFillEmptyHBF(noEmptyHBF); + + std::string outDirName(outDir); + if (outDirName.back() != '/') { + outDirName += '/'; + } + // if needed, create output directory + if (gSystem->AccessPathName(outDirName.c_str())) { + if (gSystem->mkdir(outDirName.c_str(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outDirName; + } else { + LOG(INFO) << "created output directory " << outDirName; + } + } + + mc2raw.readTrapData(outDirName, inpName, superPageSizeInB); + wr.writeConfFile(wr.getOrigin().str, "RAWDATA", o2::utils::concat_string(outDirName, wr.getOrigin().str, "raw.cfg")); + // + swTot.Stop(); + swTot.Print(); +} diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 10773f8d9f28e..4c1163b4c2221 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -70,23 +70,43 @@ bool msgDigitSortComparator(o2::trd::Digit const& a, o2::trd::Digit const& b) int rowb = b.getRow(); int pada = a.getPad(); int padb = b.getPad(); + int deta = a.getDetector(); + int detb = b.getDetector(); double timea = a.getTimeStamp(); double timeb = b.getTimeStamp(); int roba = fee->getROBfromPad(rowa, pada); int robb = fee->getROBfromPad(rowb, padb); int mcma = fee->getMCMfromPad(rowa, pada); int mcmb = fee->getMCMfromPad(rowb, padb); + int hcida = deta * 2 + roba % 2; + int hcidb = detb * 2 + robb % 2; //LOG(info) << "comparing " << rowa << ":" << pada <<":" << roba <<" "<< mcma << " with " << rowb << ":" << padb <<":" << robb <<" "<< mcmb; if (timea < timeb) { // LOG(info) << "yip timea < timeb " << timea <<"<" << timeb; return 1; } else if (timea == timeb) { + if (hcida < hcidb) + return 1; + else { + if (hcida == hcidb) { + if (mcma < mcmb) + return 1; + else + return 0; + } else + return 0; + } + return 0; - if (a.getDetector() < b.getDetector()) + /* + if (deta < detb) return 1; else { - if (a.getDetector() == b.getDetector()) { - if (roba < robb) + if (deta == detb) { + if(hcida < hcidb) + return 1; + else { + if (roba < robb) return 1; else { if (roba == robb) { @@ -100,8 +120,10 @@ bool msgDigitSortComparator(o2::trd::Digit const& a, o2::trd::Digit const& b) return 0; } return 0; + } + return 0; } - return 0; + return 0;*/ } return 0; } @@ -516,6 +538,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) //mTotalRawWordsWritten++; //no longer writing to raw stream mNewTrackletHCHeaderHasBeenWritten = true; LOG(debug) << mTrackletHCHeader; + LOG(info) << " add HCID : " << mTrackletHCHeader.HCID; } LOG(debug) << "getting trackletsteram for trapcounter = " << trapcounter; auto wordswritten = mTrapSimulator[trapcounter].getTrackletStream(rawdata, mTotalRawWordsWritten); // view of data from current marker and only 5 words long (can only have 4 words at most in the trackletstream for 1 MCM) From e2c8d0d0696f0b695012d40c7ead5ed1d0a2240a Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 13 Aug 2020 00:31:01 +0200 Subject: [PATCH 0349/1751] Move FV0 MCLabel to DataFormats --- DataFormats/Detectors/FIT/FV0/CMakeLists.txt | 1 + .../Detectors/FIT/FV0/include/DataFormatsFV0}/MCLabel.h | 0 DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h | 1 + Detectors/FIT/FV0/macro/readFV0Digits.C | 2 +- Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h | 2 +- Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h | 1 - Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h | 2 +- Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx | 2 +- macro/analyzeDigitLabels.C | 2 +- 9 files changed, 7 insertions(+), 6 deletions(-) rename {Detectors/FIT/FV0/simulation/include/FV0Simulation => DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0}/MCLabel.h (100%) diff --git a/DataFormats/Detectors/FIT/FV0/CMakeLists.txt b/DataFormats/Detectors/FIT/FV0/CMakeLists.txt index 713fb1b3dbaba..e2f0eee2e9163 100644 --- a/DataFormats/Detectors/FIT/FV0/CMakeLists.txt +++ b/DataFormats/Detectors/FIT/FV0/CMakeLists.txt @@ -21,6 +21,7 @@ o2_add_library(DataFormatsFV0 o2_target_root_dictionary(DataFormatsFV0 HEADERS include/DataFormatsFV0/Hit.h include/DataFormatsFV0/BCData.h + include/DataFormatsFV0/MCLabel.h include/DataFormatsFV0/ChannelData.h include/DataFormatsFV0/RawEventData.h include/DataFormatsFV0/LookUpTable.h) diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/MCLabel.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/MCLabel.h similarity index 100% rename from Detectors/FIT/FV0/simulation/include/FV0Simulation/MCLabel.h rename to DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/MCLabel.h diff --git a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h index d29bcefbf9a0a..cb225df825988 100644 --- a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h +++ b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h @@ -16,6 +16,7 @@ #pragma link C++ class o2::fv0::Hit + ; #pragma link C++ class vector < o2::fv0::Hit> + ; +#pragma link C++ class o2::fv0::MCLabel + ; #pragma link C++ class o2::fv0::ChannelData + ; #pragma link C++ class o2::fv0::BCData + ; diff --git a/Detectors/FIT/FV0/macro/readFV0Digits.C b/Detectors/FIT/FV0/macro/readFV0Digits.C index 903e31b526b8e..96ae58a540646 100644 --- a/Detectors/FIT/FV0/macro/readFV0Digits.C +++ b/Detectors/FIT/FV0/macro/readFV0Digits.C @@ -22,7 +22,7 @@ #include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "FV0Base/Constants.h" -#include "FV0Simulation/MCLabel.h" +#include "DataFormatsFV0/MCLabel.h" #include "FairLogger.h" void AdjustStatBox(TH1* h, float x1ndc, float x2ndc, float y1ndc, float y2ndc) diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h index 0c81394f30b1d..557e8518a105b 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h @@ -12,7 +12,7 @@ #define ALICEO2_FV0_DIGITIZER_H #include "FV0Base/Constants.h" -#include <FV0Simulation/MCLabel.h> +#include <DataFormatsFV0/MCLabel.h> #include <FV0Simulation/DigitizationConstant.h> #include <FV0Simulation/FV0DigParam.h> #include <DataFormatsFV0/ChannelData.h> diff --git a/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h b/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h index 7e45ff2806326..96ff6069e78ba 100644 --- a/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h +++ b/Detectors/FIT/FV0/simulation/src/FV0SimulationLinkDef.h @@ -17,7 +17,6 @@ #pragma link C++ class o2::fv0::Detector + ; #pragma link C++ class o2::base::DetImpl < o2::fv0::Detector> + ; #pragma link C++ class o2::fv0::Digitizer + ; -#pragma link C++ class o2::fv0::MCLabel + ; #pragma link C++ class o2::dataformats::MCTruthContainer < o2::fv0::MCLabel> + ; #pragma link C++ class o2::fv0::DigitizationConstant + ; #pragma link C++ class o2::fv0::FV0DigParam + ; diff --git a/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h b/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h index 6e2474086277e..842e4c947da0d 100644 --- a/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h +++ b/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h @@ -16,7 +16,7 @@ #include "Framework/InputSpec.h" #include "DataFormatsFV0/ChannelData.h" #include "DataFormatsFV0/BCData.h" -#include "FV0Simulation/MCLabel.h" +#include "DataFormatsFV0/MCLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx index b96aa8a5ef4ef..4de8f3c51d9e5 100644 --- a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx @@ -25,7 +25,7 @@ #include "DataFormatsParameters/GRPObject.h" #include "FV0Simulation/Digitizer.h" #include "FV0Simulation/DigitizationConstant.h" -#include "FV0Simulation/MCLabel.h" +#include "DataFormatsFV0/MCLabel.h" #include "SimulationDataFormat/MCCompLabel.h" #include "DetectorsBase/BaseDPLDigitizer.h" #include <TFile.h> diff --git a/macro/analyzeDigitLabels.C b/macro/analyzeDigitLabels.C index a476c620bbb44..ad1902f65bff6 100644 --- a/macro/analyzeDigitLabels.C +++ b/macro/analyzeDigitLabels.C @@ -7,7 +7,7 @@ #include "DataFormatsPHOS/MCLabel.h" #include "DataFormatsFT0/MCLabel.h" #include "DataFormatsFDD/MCLabel.h" -#include "FV0Simulation/MCLabel.h" +#include "DataFormatsFV0/MCLabel.h" #include "ZDCSimulation/MCLabel.h" #include "MIDSimulation/MCLabel.h" #include "TRDBase/MCLabel.h" From 516751ea330403a454c02d3f5476b960f94a4e00 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 13 Aug 2020 00:38:19 +0200 Subject: [PATCH 0350/1751] DigitReader + its workflow for FV0 --- .../include/FV0Workflow/DigitReaderSpec.h | 45 +++++++++ .../FIT/FV0/workflow/src/DigitReaderSpec.cxx | 91 +++++++++++++++++++ .../workflow/src/digits-reader-workflow.cxx | 45 +++++++++ 3 files changed, 181 insertions(+) create mode 100644 Detectors/FIT/FV0/workflow/include/FV0Workflow/DigitReaderSpec.h create mode 100644 Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx create mode 100644 Detectors/FIT/FV0/workflow/src/digits-reader-workflow.cxx diff --git a/Detectors/FIT/FV0/workflow/include/FV0Workflow/DigitReaderSpec.h b/Detectors/FIT/FV0/workflow/include/FV0Workflow/DigitReaderSpec.h new file mode 100644 index 0000000000000..7a71ae588a030 --- /dev/null +++ b/Detectors/FIT/FV0/workflow/include/FV0Workflow/DigitReaderSpec.h @@ -0,0 +1,45 @@ +// 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_FV0_DIGITREADERSPEC_H +#define O2_FV0_DIGITREADERSPEC_H + +#include "TFile.h" +#include "TTree.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" + +namespace o2 +{ +namespace fv0 +{ + +class DigitReader : public framework::Task +{ + public: + DigitReader(bool useMC) : mUseMC(useMC) {} + ~DigitReader() override = default; + void init(framework::InitContext& ic) final; + void run(framework::ProcessingContext& pc) final; + + private: + bool mUseMC = true; + std::unique_ptr<TTree> mTree; + std::unique_ptr<TFile> mFile; +}; + +/// create a processor spec +/// read simulated FV0 digits from a root file +framework::DataProcessorSpec getDigitReaderSpec(bool useMC); + +} // end namespace fv0 +} // end namespace o2 + +#endif // O2_FV0_DIGITREADERSPEC_H diff --git a/Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx b/Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx new file mode 100644 index 0000000000000..2643f32a13aa4 --- /dev/null +++ b/Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx @@ -0,0 +1,91 @@ +// 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 DigitReaderSpec.cxx + +#include <vector> + +#include "TTree.h" + +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "FV0Workflow/DigitReaderSpec.h" +#include "DataFormatsFV0/BCData.h" +#include "DataFormatsFV0/ChannelData.h" +#include "DataFormatsFV0/MCLabel.h" +#include "SimulationDataFormat/MCTruthContainer.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace fv0 +{ + +void DigitReader::init(InitContext& ic) +{ + auto filename = ic.options().get<std::string>("fv0-digit-infile"); + mFile = std::make_unique<TFile>(filename.c_str(), "OLD"); + if (!mFile->IsOpen()) { + LOG(ERROR) << "Cannot open the " << filename.c_str() << " file !"; + throw std::runtime_error("cannot open input digits file"); + } + mTree.reset((TTree*)mFile->Get("o2sim")); + if (!mTree) { + LOG(ERROR) << "Did not find o2sim tree in " << filename.c_str(); + throw std::runtime_error("Did not fine o2sim file in FV0 digits tree"); + } +} + +void DigitReader::run(ProcessingContext& pc) +{ + + std::vector<o2::fv0::BCData> digits, *pdigits = &digits; + std::vector<o2::fv0::ChannelData> channels, *pchannels = &channels; + mTree->SetBranchAddress("FV0DigitBC", &pdigits); + mTree->SetBranchAddress("FV0DigitCh", &pchannels); + + o2::dataformats::MCTruthContainer<o2::fv0::MCLabel> labels, *plabels = &labels; + if (mUseMC) { + mTree->SetBranchAddress("FV0DigitLabels", &plabels); + } + mTree->GetEntry(0); + + LOG(INFO) << "FV0DigitReader pushed " << channels.size() << " channels in " << digits.size() << " digits"; + + pc.outputs().snapshot(Output{"FV0", "DIGITSBC", 0, Lifetime::Timeframe}, digits); + pc.outputs().snapshot(Output{"FV0", "DIGITSCH", 0, Lifetime::Timeframe}, channels); + if (mUseMC) { + pc.outputs().snapshot(Output{"FV0", "DIGITSMCTR", 0, Lifetime::Timeframe}, labels); + } + pc.services().get<ControlService>().endOfStream(); + pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); +} + +DataProcessorSpec getDigitReaderSpec(bool useMC) +{ + std::vector<OutputSpec> outputs; + outputs.emplace_back("FV0", "DIGITSBC", 0, Lifetime::Timeframe); + outputs.emplace_back("FV0", "DIGITSCH", 0, Lifetime::Timeframe); + if (useMC) { + outputs.emplace_back("FV0", "DIGITSMCTR", 0, Lifetime::Timeframe); + } + + return DataProcessorSpec{ + "fv0-digit-reader", + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask<DigitReader>(useMC)}, + Options{ + {"fv0-digit-infile", VariantType::String, "fv0digits.root", {"Name of the input file"}}}}; +} + +} // namespace fv0 +} // namespace o2 diff --git a/Detectors/FIT/FV0/workflow/src/digits-reader-workflow.cxx b/Detectors/FIT/FV0/workflow/src/digits-reader-workflow.cxx new file mode 100644 index 0000000000000..a833355c2bb9b --- /dev/null +++ b/Detectors/FIT/FV0/workflow/src/digits-reader-workflow.cxx @@ -0,0 +1,45 @@ +// 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 digits-reader-workflow.cxx +/// \brief Implementation of FV0 digits reader +/// +/// \author ruben.shahoyan@cern.ch + +#include "Framework/CallbackService.h" +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Task.h" +#include "FV0Workflow/DigitReaderSpec.h" +#include "CommonUtils/ConfigurableParam.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<o2::framework::ConfigParamSpec> options{ + {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}}; + std::string keyvaluehelp("Semicolon separated key=value strings"); + options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(const ConfigContext& ctx) +{ + WorkflowSpec specs; + + DataProcessorSpec producer = o2::fv0::getDigitReaderSpec(ctx.options().get<bool>("disable-mc")); + specs.push_back(producer); + return specs; +} From 3a68f00ff95fbe9d121d8632bf8f19d09cfe31ec Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 13 Aug 2020 00:38:40 +0200 Subject: [PATCH 0351/1751] CTF support for FV0 --- DataFormats/Detectors/FIT/FT0/CMakeLists.txt | 7 +- DataFormats/Detectors/FIT/FV0/CMakeLists.txt | 4 +- .../FIT/FV0/include/DataFormatsFV0/CTF.h | 78 +++++++++ DataFormats/Detectors/FIT/FV0/src/CTF.cxx | 32 ++++ .../FIT/FV0/src/DataFormatsFV0LinkDef.h | 4 + Detectors/CTF/CMakeLists.txt | 8 + Detectors/CTF/test/test_ctf_io_ft0.cxx | 2 - Detectors/CTF/test/test_ctf_io_fv0.cxx | 115 +++++++++++++ Detectors/CTF/workflow/CMakeLists.txt | 3 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 + Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 3 + Detectors/FIT/FV0/CMakeLists.txt | 3 +- .../FIT/FV0/reconstruction/CMakeLists.txt | 6 +- .../include/FV0Reconstruction/CTFCoder.h | 158 ++++++++++++++++++ .../FIT/FV0/reconstruction/src/CTFCoder.cxx | 130 ++++++++++++++ Detectors/FIT/FV0/workflow/CMakeLists.txt | 33 ++++ .../include/FV0Workflow/EntropyDecoderSpec.h | 47 ++++++ .../include/FV0Workflow/EntropyEncoderSpec.h | 47 ++++++ .../FV0/workflow/src/EntropyDecoderSpec.cxx | 79 +++++++++ .../FV0/workflow/src/EntropyEncoderSpec.cxx | 78 +++++++++ .../workflow/src/entropy-encoder-workflow.cxx | 39 +++++ 21 files changed, 876 insertions(+), 8 deletions(-) create mode 100644 DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/CTF.h create mode 100644 DataFormats/Detectors/FIT/FV0/src/CTF.cxx create mode 100644 Detectors/CTF/test/test_ctf_io_fv0.cxx create mode 100644 Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h create mode 100644 Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx create mode 100644 Detectors/FIT/FV0/workflow/CMakeLists.txt create mode 100644 Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyDecoderSpec.h create mode 100644 Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyEncoderSpec.h create mode 100644 Detectors/FIT/FV0/workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/FIT/FV0/workflow/src/EntropyEncoderSpec.cxx create mode 100644 Detectors/FIT/FV0/workflow/src/entropy-encoder-workflow.cxx diff --git a/DataFormats/Detectors/FIT/FT0/CMakeLists.txt b/DataFormats/Detectors/FIT/FT0/CMakeLists.txt index 787af014d4242..58699a2cd95a3 100644 --- a/DataFormats/Detectors/FIT/FT0/CMakeLists.txt +++ b/DataFormats/Detectors/FIT/FT0/CMakeLists.txt @@ -15,9 +15,10 @@ o2_add_library(DataFormatsFT0 SOURCES src/RecPoints.cxx SOURCES src/RawEventData.cxx src/CTF.cxx - PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers - O2::SimulationDataFormat O2::FT0Base - ) + PUBLIC_LINK_LIBRARIES O2::CommonDataFormat + O2::Headers + O2::SimulationDataFormat + O2::FT0Base) o2_target_root_dictionary(DataFormatsFT0 HEADERS include/DataFormatsFT0/Digit.h diff --git a/DataFormats/Detectors/FIT/FV0/CMakeLists.txt b/DataFormats/Detectors/FIT/FV0/CMakeLists.txt index e2f0eee2e9163..faa74c2eaccff 100644 --- a/DataFormats/Detectors/FIT/FV0/CMakeLists.txt +++ b/DataFormats/Detectors/FIT/FV0/CMakeLists.txt @@ -13,6 +13,7 @@ o2_add_library(DataFormatsFV0 src/ChannelData.cxx src/BCData.cxx src/RawEventData.cxx + src/CTF.cxx PUBLIC_LINK_LIBRARIES O2::FV0Base O2::SimulationDataFormat O2::CommonDataFormat @@ -24,4 +25,5 @@ o2_target_root_dictionary(DataFormatsFV0 include/DataFormatsFV0/MCLabel.h include/DataFormatsFV0/ChannelData.h include/DataFormatsFV0/RawEventData.h - include/DataFormatsFV0/LookUpTable.h) + include/DataFormatsFV0/LookUpTable.h + include/DataFormatsFV0/CTF.h) diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/CTF.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/CTF.h new file mode 100644 index 0000000000000..d2c7be2fb6d4d --- /dev/null +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/CTF.h @@ -0,0 +1,78 @@ +// 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 CTF.h +/// \author ruben.shahoyan@cern.ch +/// \brief Definitions for FV0 CTF data + +#ifndef O2_FV0_CTF_H +#define O2_FV0_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" + +namespace o2 +{ +namespace fv0 +{ + +/// Header for a single CTF +struct CTFHeader { + uint32_t nTriggers = 0; /// number of triggers in TF + uint32_t firstOrbit = 0; /// 1st orbit of TF + uint16_t firstBC = 0; /// 1st BC of TF + + ClassDefNV(CTFHeader, 1); +}; + +/// Intermediate, compressed but not yet entropy-encoded digits +struct CompressedDigits { + + CTFHeader header; + + // BC data + std::vector<uint16_t> bcInc; // increment in BC if the same orbit, otherwise abs bc + std::vector<uint32_t> orbitInc; // increment in orbit + std::vector<uint8_t> nChan; // number of fired channels + + // channel data + std::vector<uint8_t> idChan; // channels ID: 1st on absolute, then increment + std::vector<int16_t> time; // time + std::vector<int16_t> charge; // Amplitude + + CompressedDigits() = default; + + void clear(); + + ClassDefNV(CompressedDigits, 1); +}; + +/// wrapper for the Entropy-encoded clusters of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 6, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { + BLC_bcInc, // increment in BC + BLC_orbitInc, // increment in orbit + BLC_nChan, // number of fired channels + + BLC_idChan, // channels ID: 1st on absolute, then increment + BLC_time, // time + BLC_charge // amplitude + }; + + ClassDefNV(CTF, 1); +}; + +} // namespace fv0 +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/FIT/FV0/src/CTF.cxx b/DataFormats/Detectors/FIT/FV0/src/CTF.cxx new file mode 100644 index 0000000000000..8b85884c7e091 --- /dev/null +++ b/DataFormats/Detectors/FIT/FV0/src/CTF.cxx @@ -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. + +#include <stdexcept> +#include <cstring> +#include "Framework/Logger.h" +#include "DataFormatsFV0/CTF.h" + +using namespace o2::fv0; + +///________________________________ +void CompressedDigits::clear() +{ + bcInc.clear(); + orbitInc.clear(); + nChan.clear(); + + idChan.clear(); + time.clear(); + charge.clear(); + + header.nTriggers = 0; + header.firstOrbit = 0; + header.firstBC = 0; +} diff --git a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h index cb225df825988..baa12012401b6 100644 --- a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h +++ b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h @@ -29,4 +29,8 @@ #pragma link C++ class o2::fv0::TCMdata + ; #pragma link C++ class o2::fv0::Topo + ; +#pragma link C++ class o2::fv0::CTFHeader + ; +#pragma link C++ class o2::fv0::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::fv0::CTFHeader, 6, uint32_t> + ; + #endif diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index 3e0f269c6430a..8e2f06775cf9a 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -33,3 +33,11 @@ o2_add_test(ft0 SOURCES test/test_ctf_io_ft0.cxx COMPONENT_NAME ctf LABELS ctf) + +o2_add_test(fv0 + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::FV0Reconstruction + O2::DataFormatsFV0 + SOURCES test/test_ctf_io_fv0.cxx + COMPONENT_NAME ctf + LABELS ctf) diff --git a/Detectors/CTF/test/test_ctf_io_ft0.cxx b/Detectors/CTF/test/test_ctf_io_ft0.cxx index 49b43b40f2f8a..6570f7a02363e 100644 --- a/Detectors/CTF/test/test_ctf_io_ft0.cxx +++ b/Detectors/CTF/test/test_ctf_io_ft0.cxx @@ -12,8 +12,6 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include <boost/test/unit_test.hpp> -#include "DataFormatsTPC/CompressedClusters.h" -#include "DataFormatsTPC/CTF.h" #include "DetectorsCommonDataFormats/NameConf.h" #include "FT0Reconstruction/CTFCoder.h" #include "Framework/Logger.h" diff --git a/Detectors/CTF/test/test_ctf_io_fv0.cxx b/Detectors/CTF/test/test_ctf_io_fv0.cxx new file mode 100644 index 0000000000000..3e395de8ec7c7 --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_fv0.cxx @@ -0,0 +1,115 @@ +// 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. + +#define BOOST_TEST_MODULE Test FV0CTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DetectorsCommonDataFormats/NameConf.h" +#include "FV0Reconstruction/CTFCoder.h" +#include "FV0Base/Constants.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <cstring> + +using namespace o2::fv0; + +BOOST_AUTO_TEST_CASE(CTFTest) +{ + std::vector<BCData> digits; + std::vector<ChannelData> channels; + + TStopwatch sw; + sw.Start(); + o2::InteractionRecord ir(0, 0); + + constexpr int MAXChan = Constants::nChannelsPerPm * Constants::nPms; // RSFIXME is this correct ? + for (int idig = 0; idig < 1000; idig++) { + ir += 1 + gRandom->Integer(200); + uint8_t ich = gRandom->Poisson(10); + auto start = channels.size(); + while (ich < MAXChan) { + int16_t t = -2048 + gRandom->Integer(2048 * 2); + uint16_t q = gRandom->Integer(4096); + channels.emplace_back(ich, t, q); + ich += 1 + gRandom->Poisson(10); + } + auto end = channels.size(); + digits.emplace_back(start, end - start, ir); + } + + LOG(INFO) << "Generated " << channels.size() << " channels in " << digits.size() << " digits " << sw.CpuTime() << " s"; + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + { + CTFCoder coder; + coder.encode(vec, digits, channels); // compress + } + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + TFile flOut("test_ctf_fv0.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + auto* ctfImage = o2::fv0::CTF::get(vec.data()); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "FV0"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + { + sw.Start(); + TFile flIn("test_ctf_fv0.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + o2::fv0::CTF::readFromTree(vec, *(tree.get()), "FV0"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<BCData> digitsD; + std::vector<ChannelData> channelsD; + + sw.Start(); + const auto ctfImage = o2::fv0::CTF::getImage(vec.data()); + { + CTFCoder coder; + coder.decode(ctfImage, digitsD, channelsD); // decompress + } + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + BOOST_CHECK(digitsD.size() == digits.size()); + BOOST_CHECK(channelsD.size() == channels.size()); + LOG(INFO) << " BOOST_CHECK digitsD.size() " << digitsD.size() << " digits.size() " << digits.size() << " BOOST_CHECK(channelsD.size() " << channelsD.size() << " channels.size()) " << channels.size(); + + for (int i = digits.size(); i--;) { + const auto& dor = digits[i]; + const auto& ddc = digitsD[i]; + BOOST_CHECK(dor.ir == ddc.ir); + BOOST_CHECK(dor.ref == ddc.ref); + } + for (int i = channels.size(); i--;) { + const auto& cor = channels[i]; + const auto& cdc = channelsD[i]; + BOOST_CHECK(cor.pmtNumber == cdc.pmtNumber); + BOOST_CHECK(cor.time == cdc.time); + BOOST_CHECK(cor.chargeAdc == cdc.chargeAdc); + } +} diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index acfbd38f1c5c1..02b5050aaa4f0 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -16,10 +16,13 @@ o2_add_library(CTFWorkflow O2::DataFormatsITSMFT O2::DataFormatsTPC O2::DataFormatsTOF + O2::DataFormatsFT0 + O2::DataFormatsFV0 O2::DataFormatsParameters O2::ITSMFTWorkflow O2::TPCWorkflow O2::FT0Workflow + O2::FV0Workflow O2::TOFWorkflow O2::Algorithm O2::CommonUtils) diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 2b26bbf251859..db9d2ce38cf76 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -26,6 +26,7 @@ #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" #include "DataFormatsFT0/CTF.h" +#include "DataFormatsFV0/CTF.h" #include "DataFormatsTOF/CTF.h" #include "Algorithm/RangeTokenizer.h" @@ -134,6 +135,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::FV0; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::fv0::CTF)); + o2::fv0::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + det = DetID::TOF; if (detsTF[det]) { auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::tof::CTF)); diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index f04ece2038a8e..209927a42da49 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -23,6 +23,7 @@ #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" #include "DataFormatsFT0/CTF.h" +#include "DataFormatsFV0/CTF.h" #include "DataFormatsTOF/CTF.h" using namespace o2::framework; @@ -94,6 +95,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) processDet<o2::tpc::CTF>(pc, DetID::TPC, header, treeOut.get()); processDet<o2::tof::CTF>(pc, DetID::TOF, header, treeOut.get()); processDet<o2::ft0::CTF>(pc, DetID::FT0, header, treeOut.get()); + processDet<o2::fv0::CTF>(pc, DetID::FV0, header, treeOut.get()); mTimer.Stop(); @@ -160,6 +162,7 @@ void CTFWriterSpec::storeDictionaries() storeDictionary<o2::tpc::CTF>(DetID::TPC, header); storeDictionary<o2::tof::CTF>(DetID::TOF, header); storeDictionary<o2::ft0::CTF>(DetID::FT0, header); + storeDictionary<o2::fv0::CTF>(DetID::FV0, header); // close remnants if (mDictTreeOut) { closeDictionaryTreeAndFile(header); diff --git a/Detectors/FIT/FV0/CMakeLists.txt b/Detectors/FIT/FV0/CMakeLists.txt index b26e2454f4b96..e4164be8f405c 100644 --- a/Detectors/FIT/FV0/CMakeLists.txt +++ b/Detectors/FIT/FV0/CMakeLists.txt @@ -10,5 +10,6 @@ add_subdirectory(base) add_subdirectory(simulation) -add_subdirectory(macro) add_subdirectory(reconstruction) +add_subdirectory(workflow) +add_subdirectory(macro) diff --git a/Detectors/FIT/FV0/reconstruction/CMakeLists.txt b/Detectors/FIT/FV0/reconstruction/CMakeLists.txt index 532481c9943c9..7e588e3928b7b 100644 --- a/Detectors/FIT/FV0/reconstruction/CMakeLists.txt +++ b/Detectors/FIT/FV0/reconstruction/CMakeLists.txt @@ -10,13 +10,17 @@ o2_add_library(FV0Reconstruction SOURCES src/ReadRaw.cxx + src/CTFCoder.cxx PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::Framework O2::FV0Base O2::DataFormatsFV0 O2::DetectorsRaw + O2::CommonDataFormat + O2::rANS O2::Headers) o2_target_root_dictionary(FV0Reconstruction HEADERS include/FV0Reconstruction/ReadRaw.h -) + include/FV0Reconstruction/CTFCoder.h) + diff --git a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h new file mode 100644 index 0000000000000..ca4067dcb7838 --- /dev/null +++ b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h @@ -0,0 +1,158 @@ +// 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 CTFCoder.h +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of FV0 digits data + +#ifndef O2_FV0_CTFCODER_H +#define O2_FV0_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include "FV0Base/Geometry.h" +#include "DataFormatsFV0/CTF.h" +#include "DataFormatsFV0/BCData.h" +#include "DataFormatsFV0/ChannelData.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" +#include "rANS/rans.h" + +class TTree; + +namespace o2 +{ +namespace fv0 +{ + +class CTFCoder : public o2::ctf::CTFCoderBase +{ + public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::FV0) {} + ~CTFCoder() = default; + + /// entropy-encode digits to buffer with CTF + template <typename VEC> + void encode(VEC& buff, const gsl::span<const BCData>& digitVec, const gsl::span<const ChannelData>& channelVec); + + /// entropy decode clusters from buffer with CTF + template <typename VDIG, typename VCHAN> + void decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); + + private: + /// compres digits clusters to CompressedDigits + void compress(CompressedDigits& cd, const gsl::span<const BCData>& digitVec, const gsl::span<const ChannelData>& channelVec); + + /// decompress CompressedDigits to digits + template <typename VDIG, typename VCHAN> + void decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec); + + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<BCData>& digitVec, std::vector<ChannelData>& channelVec); + + ClassDefNV(CTFCoder, 1); +}; + +/// entropy-encode clusters to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const BCData>& digitVec, const gsl::span<const ChannelData>& channelVec) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, // BLC_bcInc + MD::EENCODE, // BLC_orbitInc + MD::EENCODE, // BLC_nChan + + MD::EENCODE, // BLC_idChan + MD::EENCODE, // BLC_time + MD::EENCODE // BLC_charge + }; + CompressedDigits cd; + compress(cd, digitVec, channelVec); + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(cd.header); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODEFV0(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); + // clang-format off + ENCODEFV0(cd.bcInc, CTF::BLC_bcInc, o2::rans::ProbabilityBits16Bit); + ENCODEFV0(cd.orbitInc, CTF::BLC_orbitInc, o2::rans::ProbabilityBits16Bit); + ENCODEFV0(cd.nChan, CTF::BLC_nChan, o2::rans::ProbabilityBits8Bit); + + ENCODEFV0(cd.idChan , CTF::BLC_idChan, o2::rans::ProbabilityBits8Bit); + ENCODEFV0(cd.time, CTF::BLC_time, o2::rans::ProbabilityBits16Bit); + ENCODEFV0(cd.charge, CTF::BLC_charge, o2::rans::ProbabilityBits25Bit); + // clang-format on + CTF::get(buff.data())->print(getPrefix()); +} + +/// decode entropy-encoded clusters to standard compact clusters +template <typename VDIG, typename VCHAN> +void CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec) +{ + CompressedDigits cd; + cd.header = ec.getHeader(); + ec.print(getPrefix()); +#define DECODEFV0(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) + // clang-format off + DECODEFV0(cd.bcInc, CTF::BLC_bcInc); + DECODEFV0(cd.orbitInc, CTF::BLC_orbitInc); + DECODEFV0(cd.nChan, CTF::BLC_nChan); + + DECODEFV0(cd.idChan, CTF::BLC_idChan); + DECODEFV0(cd.time, CTF::BLC_time); + DECODEFV0(cd.charge, CTF::BLC_charge); + // clang-format on + // + decompress(cd, digitVec, channelVec); +} + +/// decompress compressed digits to standard digits +template <typename VDIG, typename VCHAN> +void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec) +{ + digitVec.clear(); + channelVec.clear(); + digitVec.reserve(cd.header.nTriggers); + channelVec.reserve(cd.idChan.size()); + + uint32_t firstEntry = 0, clCount = 0, chipCount = 0; + o2::InteractionRecord ir(cd.header.firstBC, cd.header.firstOrbit); + + for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) { + // restore ROFRecord + if (cd.orbitInc[idig]) { // non-0 increment => new orbit + ir.bc = cd.bcInc[idig]; // bcInc has absolute meaning + ir.orbit += cd.orbitInc[idig]; + } else { + ir.bc += cd.bcInc[idig]; + } + + firstEntry = channelVec.size(); + uint8_t chID = 0; + for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { + auto icc = channelVec.size(); + const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.time[icc], cd.charge[icc]); + } + digitVec.emplace_back(firstEntry, cd.nChan[idig], ir); + } +} + +} // namespace fv0 +} // namespace o2 + +#endif // O2_FV0_CTFCODER_H diff --git a/Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx new file mode 100644 index 0000000000000..b168b7c07dd19 --- /dev/null +++ b/Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx @@ -0,0 +1,130 @@ +// 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 CTFCoder.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of FV0 digits data + +#include "FV0Reconstruction/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::fv0; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) +{ + ec.appendToTree(tree, mDet.getName()); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, + std::vector<BCData>& digitVec, std::vector<ChannelData>& channelVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, mDet.getName(), entry); + decode(ec, digitVec, channelVec); +} + +///________________________________ +void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const BCData>& digitVec, const gsl::span<const ChannelData>& channelVec) +{ + // convert digits/channel to their compressed version + cd.clear(); + if (!digitVec.size()) { + return; + } + const auto& dig0 = digitVec[0]; + cd.header.nTriggers = digitVec.size(); + cd.header.firstOrbit = dig0.ir.orbit; + cd.header.firstBC = dig0.ir.bc; + + cd.bcInc.resize(cd.header.nTriggers); + cd.orbitInc.resize(cd.header.nTriggers); + cd.nChan.resize(cd.header.nTriggers); + + cd.idChan.resize(channelVec.size()); + cd.time.resize(channelVec.size()); + cd.charge.resize(channelVec.size()); + + uint16_t prevBC = cd.header.firstBC; + uint32_t prevOrbit = cd.header.firstOrbit; + uint32_t ccount = 0; + for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) { + const auto& digit = digitVec[idig]; + const auto chanels = digit.getBunchChannelData(channelVec); // we assume the channels are sorted + + // fill trigger info + if (prevOrbit == digit.ir.orbit) { + cd.bcInc[idig] = digit.ir.bc - prevBC; + cd.orbitInc[idig] = 0; + } else { + cd.bcInc[idig] = digit.ir.bc; + cd.orbitInc[idig] = digit.ir.orbit - prevOrbit; + } + prevBC = digit.ir.bc; + prevOrbit = digit.ir.orbit; + // fill channels info + cd.nChan[idig] = chanels.size(); + if (!cd.nChan[idig]) { + LOG(ERROR) << "Digits with no channels"; + continue; + } + uint8_t prevChan = 0; + for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { + assert(prevChan <= chanels[ic].pmtNumber); + cd.idChan[ccount] = chanels[ic].pmtNumber - prevChan; + cd.time[ccount] = chanels[ic].time; // make sure it fits to short!!! + cd.charge[ccount] = chanels[ic].chargeAdc; // make sure we really need short!!! + prevChan = chanels[ic].pmtNumber; + ccount++; + } + } +} + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + CompressedDigits cd; // just to get member types +#define MAKECODER(part, slot) createCoder<decltype(part)::value_type>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(cd.bcInc, CTF::BLC_bcInc); + MAKECODER(cd.orbitInc, CTF::BLC_orbitInc); + MAKECODER(cd.nChan, CTF::BLC_nChan); + + MAKECODER(cd.idChan, CTF::BLC_idChan); + MAKECODER(cd.time, CTF::BLC_time); + MAKECODER(cd.charge, CTF::BLC_charge); + // clang-format on +} diff --git a/Detectors/FIT/FV0/workflow/CMakeLists.txt b/Detectors/FIT/FV0/workflow/CMakeLists.txt new file mode 100644 index 0000000000000..6166157112792 --- /dev/null +++ b/Detectors/FIT/FV0/workflow/CMakeLists.txt @@ -0,0 +1,33 @@ +# 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_library(FV0Workflow + SOURCES src/EntropyEncoderSpec.cxx + src/EntropyDecoderSpec.cxx + src/DigitReaderSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DataFormatsFV0 + O2::FV0Reconstruction + O2::DetectorsCommonDataFormats + O2::DPLUtils) + +o2_add_executable(entropy-encoder-workflow + SOURCES src/entropy-encoder-workflow.cxx + COMPONENT_NAME fv0 + PUBLIC_LINK_LIBRARIES O2::FV0Workflow) + +o2_add_executable(digit-reader-workflow + SOURCES src/digits-reader-workflow.cxx + COMPONENT_NAME fv0 + PUBLIC_LINK_LIBRARIES O2::FV0Workflow) + +if(NOT APPLE) + set_property(TARGET ${fitrecoexe} PROPERTY LINK_WHAT_YOU_USE ON) +endif() diff --git a/Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyDecoderSpec.h b/Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..744ad441effca --- /dev/null +++ b/Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyDecoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to FV0 digit/channels strean + +#ifndef O2_FV0_ENTROPYDECODER_SPEC +#define O2_FV0_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "FV0Reconstruction/CTFCoder.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace fv0 +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::fv0::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace fv0 +} // namespace o2 + +#endif diff --git a/Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyEncoderSpec.h b/Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..0b38260cad14f --- /dev/null +++ b/Detectors/FIT/FV0/workflow/include/FV0Workflow/EntropyEncoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert clusters streams to CTF (EncodedBlocks) + +#ifndef O2_FV0_ENTROPYENCODER_SPEC +#define O2_FV0_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> +#include "FV0Reconstruction/CTFCoder.h" + +namespace o2 +{ +namespace fv0 +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::fv0::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace fv0 +} // namespace o2 + +#endif diff --git a/Detectors/FIT/FV0/workflow/src/EntropyDecoderSpec.cxx b/Detectors/FIT/FV0/workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..6f5cb5b0b3a06 --- /dev/null +++ b/Detectors/FIT/FV0/workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "FV0Workflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace fv0 +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("fv0-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& digits = pc.outputs().make<std::vector<o2::fv0::BCData>>(OutputRef{"digits"}); + auto& channels = pc.outputs().make<std::vector<o2::fv0::ChannelData>>(OutputRef{"channels"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::fv0::CTF::getImage(buff.data()); + mCTFCoder.decode(ctfImage, digits, channels); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << channels.size() << " FV0 channels in " << digits.size() << " digits in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "FV0 Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"digits"}, "FV0", "DIGITSBC", 0, Lifetime::Timeframe}, + OutputSpec{{"channels"}, "FV0", "DIGITSCH", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "fv0-entropy-decoder", + Inputs{InputSpec{"ctf", "FV0", "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{{"fv0-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; +} + +} // namespace fv0 +} // namespace o2 diff --git a/Detectors/FIT/FV0/workflow/src/EntropyEncoderSpec.cxx b/Detectors/FIT/FV0/workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..ff8f7bd5f6c5a --- /dev/null +++ b/Detectors/FIT/FV0/workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,78 @@ +// 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 EntropyEncoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "FV0Workflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace fv0 +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("fv0-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto digits = pc.inputs().get<gsl::span<o2::fv0::BCData>>("digits"); + auto channels = pc.inputs().get<gsl::span<o2::fv0::ChannelData>>("channels"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"FV0", "CTFDATA", 0, Lifetime::Timeframe}); + mCTFCoder.encode(buffer, digits, channels); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for FV0 in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "FV0 Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("digits", "FV0", "DIGITSBC", 0, Lifetime::Timeframe); + inputs.emplace_back("channels", "FV0", "DIGITSCH", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "fv0-entropy-encoder", + inputs, + Outputs{{"FV0", "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{{"fv0-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; +} + +} // namespace fv0 +} // namespace o2 diff --git a/Detectors/FIT/FV0/workflow/src/entropy-encoder-workflow.cxx b/Detectors/FIT/FV0/workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..58455959b0854 --- /dev/null +++ b/Detectors/FIT/FV0/workflow/src/entropy-encoder-workflow.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. + +#include "FV0Workflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::fv0::getEntropyEncoderSpec()); + return wf; +} From 164756759324f26d4cc95acbda7986ac1caf6ab9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 13 Aug 2020 08:56:24 +0200 Subject: [PATCH 0352/1751] Logger: Remove obsolete workarounds --- Framework/Logger/include/Framework/Logger.h | 81 --------------------- 1 file changed, 81 deletions(-) diff --git a/Framework/Logger/include/Framework/Logger.h b/Framework/Logger/include/Framework/Logger.h index 8835c1e46dd43..cf1c7511c850d 100644 --- a/Framework/Logger/include/Framework/Logger.h +++ b/Framework/Logger/include/Framework/Logger.h @@ -10,91 +10,10 @@ #ifndef O2_FRAMEWORK_LOGGER_H_ #define O2_FRAMEWORK_LOGGER_H_ -// FIXME: until we actually have fmt widely available we simply print out the -// format string. -// If FairLogger is not available, we use fmt::printf directly, with no level. -#if __has_include(<fairlogger/Logger.h>) #include <fairlogger/Logger.h> -#if (!defined(LOGP)) && __has_include(<fmt/format.h>) -#include <fmt/format.h> -#include <fmt/printf.h> -FMT_BEGIN_NAMESPACE -#if FMT_VERSION >= 60000 -template <typename S, typename Char = char_t<S>> -inline int vfprintf(fair::Logger& logger, - const S& format, - basic_format_args<basic_printf_context_t<Char>> args) -{ - basic_memory_buffer<Char> buffer; - printf(buffer, to_string_view(format), args); - logger << std::string_view(buffer.data(), buffer.size()); - return static_cast<int>(buffer.size()); -} -template <typename S, typename... Args> -inline enable_if_t<internal::is_string<S>::value, int> - fprintf(fair::Logger& logger, - const S& format_str, const Args&... args) -{ - internal::check_format_string<Args...>(format_str); - using context = basic_printf_context_t<char_t<S>>; - format_arg_store<context, Args...> as{args...}; - return vfprintf(logger, to_string_view(format_str), - basic_format_args<context>(as)); -} -#else -template <typename S, typename Char = FMT_CHAR(S)> -inline int vfprintf(fair::Logger& logger, - const S& format, - basic_format_args<typename basic_printf_context_t< - internal::basic_buffer<Char>>::type> - args) -{ - basic_memory_buffer<Char> buffer; - printf(buffer, to_string_view(format), args); - logger << std::string_view(buffer.data(), buffer.size()); - return static_cast<int>(buffer.size()); -} - -template <typename S, typename... Args> -inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int) - fprintf(fair::Logger& logger, - const S& format_str, const Args&... args) -{ - internal::check_format_string<Args...>(format_str); - typedef internal::basic_buffer<FMT_CHAR(S)> buffer; - typedef typename basic_printf_context_t<buffer>::type context; - format_arg_store<context, Args...> as{args...}; - return vfprintf(logger, to_string_view(format_str), - basic_format_args<context>(as)); -} -#endif -FMT_END_NAMESPACE - -// clang-format off -// Must not add braces since it can break the usage in certain if clauses -#define LOGF(severity, ...) \ - if (fair::Logger::SuppressSeverity(fair::Severity::severity)) ; else \ - for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \ - fmt::fprintf(fair::Logger(fair::Severity::severity, __FILE__, CONVERTTOSTRING(__LINE__), __FUNCTION__).Log(), __VA_ARGS__) -// clang-format on -#define LOGP(severity, ...) \ - LOG(severity) << fmt::format(__VA_ARGS__) -#elif (!defined(LOGP)) -#define O2_FIRST_ARG(N, ...) N -#define LOGF(level, ...) LOG(level) << O2_FIRST_ARG(__VA_ARGS__) -#define LOGP(level, ...) LOG(level) << O2_FIRST_ARG(__VA_ARGS__) -#endif #define O2DEBUG(...) LOGF(debug, __VA_ARGS__) #define O2INFO(...) LOGF(info, __VA_ARGS__) #define O2ERROR(...) LOGF(error, __VA_ARGS__) -#elif (!defined(LOGP)) && __has_include(<fmt/format.h>) -#include <fmt/format.h> -#define LOGF(level, ...) fmt::printf(__VA_ARGS__) -#define LOGP(level, ...) fmt::print(__VA_ARGS__) -#define O2DEBUG(...) LOGF("dummy", __VA_ARGS__) -#define O2INFO(...) LOGF("dummy", __VA_ARGS__) -#define O2ERROR(...) LOGF("dummy", __VA_ARGS__) -#endif #endif // O2_FRAMEWORK_LOGGER_H_ From 7f509c147dc87658ff7b54b3399e92bcd51343ad Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Wed, 12 Aug 2020 20:17:24 +0200 Subject: [PATCH 0353/1751] Correct Q2 calculation for TrapSimulator --- .../TRD/simulation/include/TRDSimulation/TrapSimulator.h | 3 +++ Detectors/TRD/simulation/src/TrapSimulator.cxx | 8 ++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h index 7dde07da45ff3..bb57c4b772b15 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h @@ -201,6 +201,9 @@ class TrapSimulator static const int mgkDmemAddrTimeOffset = 0xc3fe; // DMEM address of time offset t0 static const int mgkDmemAddrYcorr = 0xc3ff; // DMEM address of y correction (mis-alignment) static const int mgkMaxTracklets = 4; // maximum number of tracklet-words submitted per MCM (one per CPU) + static constexpr int mQ2Startbin = 3; // Start range of Q2, for now here. TODO pull from a revised TrapConfig? + static constexpr int mQ2Endbin = 5; // End range of Q2, also pull from a revised trapconfig at some point. + std::vector<Tracklet>& getTrackletArray() { return mTrackletArray; } std::vector<Tracklet64>& getTrackletArray64() { return mTrackletArray64; } void getTracklet64s(std::vector<Tracklet64>& TrackletStore); // place the trapsim 64 bit tracklets nto the incoming vector diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 4fb06cf5c78e4..9cc923eb49023 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -17,7 +17,6 @@ // // /////////////////////////////////////////////////////////////////////////////// -//#include "TTreeStream.h" #include "TRDBase/TRDSimParam.h" #include "TRDBase/TRDCommonParam.h" @@ -1470,12 +1469,9 @@ void TrapSimulator::addHitToFitreg(int adc, unsigned short timebin, unsigned sho (timebin < mTrapConfig->getTrapReg(TrapConfig::kTPQE1, mDetector, mRobPos, mMcmPos))) { mFitReg[adc].mQ1 += qtot; } - - if ((timebin > mTrapConfig->getTrapReg(TrapConfig::kTPQE1, mDetector, mRobPos, mMcmPos)) && - (timebin > mTrapConfig->getTrapReg(TrapConfig::kTPQE0, mDetector, mRobPos, mMcmPos)) && - (timebin < mNTimeBin)) { + // Q2 is simply the addition of times from 3 to 5, for now consts in the header file till they come from a config. + if (timebin > mQ2Startbin && timebin < mQ2Endbin) { mFitReg[adc].mQ2 += qtot; - // TODO I am not sure what happens with Q2, for now just assume its the rest of the time windows after Q0 and Q1 and before the end of the time bins. } if ((timebin >= mTrapConfig->getTrapReg(TrapConfig::kTPFS, mDetector, mRobPos, mMcmPos)) && From b4a8d433d3f904d34a8746b582159743b2b0dacc Mon Sep 17 00:00:00 2001 From: saganatt <8majak8@gmail.com> Date: Thu, 13 Aug 2020 18:33:49 +0200 Subject: [PATCH 0354/1751] Added helper functions for most common combinations cases --- .../Core/include/Framework/ASoAHelpers.h | 24 ++++ Framework/Core/test/test_ASoAHelpers.cxx | 119 ++++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/Framework/Core/include/Framework/ASoAHelpers.h b/Framework/Core/include/Framework/ASoAHelpers.h index 9d10f5cafe457..04c23187ed550 100644 --- a/Framework/Core/include/Framework/ASoAHelpers.h +++ b/Framework/Core/include/Framework/ASoAHelpers.h @@ -926,6 +926,18 @@ auto selfCombinations(const char* categoryColumnName, int categoryNeighbours, co return CombinationsGenerator<CombinationsBlockStrictlyUpperSameIndexPolicy<T1, T2, T2s...>>(CombinationsBlockStrictlyUpperSameIndexPolicy(categoryColumnName, categoryNeighbours, outsider, table, tables...)); } +template <typename T1, typename T2> +auto selfPairCombinations(const char* categoryColumnName, int categoryNeighbours, const T1& outsider, const T2& table) +{ + return CombinationsGenerator<CombinationsBlockStrictlyUpperSameIndexPolicy<T1, T2, T2>>(CombinationsBlockStrictlyUpperSameIndexPolicy(categoryColumnName, categoryNeighbours, outsider, table, table)); +} + +template <typename T1, typename T2> +auto selfTripleCombinations(const char* categoryColumnName, int categoryNeighbours, const T1& outsider, const T2& table) +{ + return CombinationsGenerator<CombinationsBlockStrictlyUpperSameIndexPolicy<T1, T2, T2, T2>>(CombinationsBlockStrictlyUpperSameIndexPolicy(categoryColumnName, categoryNeighbours, outsider, table, table, table)); +} + template <typename T1, typename T2, typename... T2s> auto combinations(const char* categoryColumnName, int categoryNeighbours, const T1& outsider, const T2& table, const T2s&... tables) { @@ -956,6 +968,18 @@ auto combinations(const T2& table, const T2s&... tables) } } +template <typename T2> +auto pairCombinations(const T2& table) +{ + return CombinationsGenerator<CombinationsStrictlyUpperIndexPolicy<T2, T2>>(CombinationsStrictlyUpperIndexPolicy(table, table)); +} + +template <typename T2> +auto tripleCombinations(const T2& table) +{ + return CombinationsGenerator<CombinationsStrictlyUpperIndexPolicy<T2, T2, T2>>(CombinationsStrictlyUpperIndexPolicy(table, table, table)); +} + template <typename T2, typename... T2s> auto combinations(const o2::framework::expressions::Filter& filter, const T2& table, const T2s&... tables) { diff --git a/Framework/Core/test/test_ASoAHelpers.cxx b/Framework/Core/test/test_ASoAHelpers.cxx index 907f8dab09939..9fb4e598ebe63 100644 --- a/Framework/Core/test/test_ASoAHelpers.cxx +++ b/Framework/Core/test/test_ASoAHelpers.cxx @@ -1228,3 +1228,122 @@ BOOST_AUTO_TEST_CASE(BlockCombinations) } BOOST_CHECK_EQUAL(count, 0); } + +BOOST_AUTO_TEST_CASE(CombinationsHelpers) +{ + TableBuilder builderA; + auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"}); + rowWriterA(0, 0, 0); + rowWriterA(0, 1, 0); + rowWriterA(0, 2, 0); + rowWriterA(0, 3, 0); + rowWriterA(0, 4, 0); + rowWriterA(0, 5, 0); + rowWriterA(0, 6, 0); + rowWriterA(0, 7, 0); + auto tableA = builderA.finalize(); + BOOST_REQUIRE_EQUAL(tableA->num_rows(), 8); + + using TestA = o2::soa::Table<o2::soa::Index<>, test::X, test::Y>; + + TestA testsA{tableA}; + + BOOST_REQUIRE_EQUAL(8, testsA.size()); + int nA = testsA.size(); + + int count = 0; + int i = 0; + int j = 1; + for (auto& [t0, t1] : pairCombinations(testsA)) { + BOOST_CHECK_EQUAL(t0.x(), i); + BOOST_CHECK_EQUAL(t1.x(), j); + count++; + j++; + if (j == nA) { + i++; + j = i + 1; + } + } + BOOST_CHECK_EQUAL(count, 28); + + count = 0; + i = 0; + j = 1; + int k = 2; + for (auto& [t0, t1, t2] : tripleCombinations(testsA)) { + BOOST_CHECK_EQUAL(t0.x(), i); + BOOST_CHECK_EQUAL(t1.x(), j); + BOOST_CHECK_EQUAL(t2.x(), k); + count++; + k++; + if (k == nA) { + if (j == nA - 2) { + i++; + j = i; + } + j++; + k = j + 1; + } + } + BOOST_CHECK_EQUAL(count, 56); + + TableBuilder builderB; + auto rowWriterB = builderB.persist<int32_t, int32_t, float>({"x", "y", "floatZ"}); + rowWriterB(0, 0, 25, -6.0f); + rowWriterB(0, 1, 18, 0.0f); + rowWriterB(0, 2, 48, 8.0f); + rowWriterB(0, 3, 103, 2.0f); + rowWriterB(0, 4, 28, -6.0f); + rowWriterB(0, 5, 102, 2.0f); + rowWriterB(0, 6, 12, 0.0f); + rowWriterB(0, 7, 24, -7.0f); + rowWriterB(0, 8, 41, 8.0f); + rowWriterB(0, 9, 49, 8.0f); + auto tableB = builderB.finalize(); + BOOST_REQUIRE_EQUAL(tableB->num_rows(), 10); + + using TestB = o2::soa::Table<o2::soa::Index<>, test::X, test::Y, test::FloatZ>; + TestB testB{tableB}; + BOOST_REQUIRE_EQUAL(10, testB.size()); + + // Grouped data: + // [3, 5] [0, 4, 7], [1, 6], [2, 8, 9] + // Assuming bins intervals: [ , ) + std::vector<uint32_t> yBins{0, 5, 10, 20, 30, 40, 50, 101}; + std::vector<float> zBins{-7.0f, -5.0f, -3.0f, -1.0f, 1.0f, 3.0f, 5.0f, 7.0f}; + + TableBuilder builderAux; + auto rowWriterAux = builderAux.persist<int32_t, int32_t>({"x", "y"}); + for (auto it = testB.begin(); it != testB.end(); it++) { + auto& elem = *it; + rowWriterAux(0, elem.x(), getHash(yBins, zBins, elem.y(), elem.floatZ())); + } + auto tableAux = builderAux.finalize(); + BOOST_REQUIRE_EQUAL(tableAux->num_rows(), 10); + + // Auxiliary table: testsAux with id and hash, hash is the category for grouping + using TestsAux = o2::soa::Table<o2::soa::Index<>, test::X, test::Y>; + TestsAux testAux{tableAux}; + BOOST_REQUIRE_EQUAL(10, testAux.size()); + + std::vector<std::tuple<int32_t, int32_t>> expectedStrictlyUpperPairs{ + {0, 4}, {0, 7}, {4, 7}, {1, 6}, {3, 5}, {2, 8}, {2, 9}, {8, 9}}; + count = 0; + for (auto& [c0, c1] : selfPairCombinations("y", 2, -1, testAux)) { + BOOST_CHECK_EQUAL(c0.x(), std::get<0>(expectedStrictlyUpperPairs[count])); + BOOST_CHECK_EQUAL(c1.x(), std::get<1>(expectedStrictlyUpperPairs[count])); + count++; + } + BOOST_CHECK_EQUAL(count, expectedStrictlyUpperPairs.size()); + + std::vector<std::tuple<int32_t, int32_t, int32_t>> expectedStrictlyUpperTriples{ + {0, 4, 7}, {2, 8, 9}}; + count = 0; + for (auto& [c0, c1, c2] : selfTripleCombinations("y", 2, -1, testAux)) { + BOOST_CHECK_EQUAL(c0.x(), std::get<0>(expectedStrictlyUpperTriples[count])); + BOOST_CHECK_EQUAL(c1.x(), std::get<1>(expectedStrictlyUpperTriples[count])); + BOOST_CHECK_EQUAL(c2.x(), std::get<2>(expectedStrictlyUpperTriples[count])); + count++; + } + BOOST_CHECK_EQUAL(count, expectedStrictlyUpperTriples.size()); +} From 53fafde284e3c4508bb94f89c178d1cc38541d3f Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Thu, 13 Aug 2020 14:48:48 +0200 Subject: [PATCH 0355/1751] [rANS] automatic calculation of rescaling factor the rescaling factor determines the precision of the rANS compression algorithm SymbolTable and this it's compression efficiency and performance. Until now it had to be set manually. The parameter now has become optional and the optimal precision is automatically estimated based on the FrequencyTable that is used to compress the data. --- .../EncodedBlocks.h | 4 +- .../include/FT0Reconstruction/CTFCoder.h | 18 ++++---- .../include/FV0Reconstruction/CTFCoder.h | 12 ++--- .../include/ITSMFTReconstruction/CTFCoder.h | 20 ++++---- .../include/TOFReconstruction/CTFCoder.h | 20 ++++---- .../include/TPCReconstruction/CTFCoder.h | 46 +++++++++---------- Utilities/rANS/include/rANS/Decoder.h | 3 +- Utilities/rANS/include/rANS/Encoder.h | 3 +- .../include/rANS/internal/SymbolStatistics.h | 22 ++++++++- .../rANS/include/rANS/internal/SymbolTable.h | 8 ++-- Utilities/rANS/include/rANS/rans.h | 5 -- Utilities/rANS/run/bin-encode-decode.cxx | 5 +- 12 files changed, 89 insertions(+), 77 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 67282507502c9..b8372e90d605e 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -784,8 +784,6 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source encoder = encoderLoc.get(); dictSize = frequencies->size(); } - assert(probabilityBits == encoder->getProbabilityBits()); - // const o2::rans::LiteralEncoder64<S> encoder{*frequencies, probabilityBits}; // estimate size of encode buffer int dataSize = rans::calculateMaxBufferSize(messageLength, encoder->getAlphabetRangeBits(), sizeof(S)); @@ -811,7 +809,7 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source expandStorage(literalSize); bl->storeLiterals(literalSize, reinterpret_cast<const stream_t*>(literals.data())); } - *meta = Metadata{messageLength, literals.size(), sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, + *meta = Metadata{messageLength, literals.size(), sizeof(uint64_t), sizeof(stream_t), static_cast<uint8_t>(encoder->getProbabilityBits()), opt, encoder->getMinSymbol(), encoder->getMaxSymbol(), dictSize, dataSize, literalSize}; } else { // store original data w/o EEncoding diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index 2c1941cbf5160..ffc678e3c6510 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -91,15 +91,15 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec #define ENCODEFT0(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODEFT0(cd.trigger, CTF::BLC_trigger, o2::rans::ProbabilityBits16Bit); - ENCODEFT0(cd.bcInc, CTF::BLC_bcInc, o2::rans::ProbabilityBits16Bit); - ENCODEFT0(cd.orbitInc, CTF::BLC_orbitInc, o2::rans::ProbabilityBits16Bit); - ENCODEFT0(cd.nChan, CTF::BLC_nChan, o2::rans::ProbabilityBits8Bit); - // ENCODEFT0(cd.eventFlags, CTF::BLC_flags, o2::rans::ProbabilityBits8Bit); - ENCODEFT0(cd.idChan , CTF::BLC_idChan, o2::rans::ProbabilityBits8Bit); - ENCODEFT0(cd.qtcChain, CTF::BLC_qtcChain, o2::rans::ProbabilityBits8Bit); - ENCODEFT0(cd.cfdTime, CTF::BLC_cfdTime, o2::rans::ProbabilityBits16Bit); - ENCODEFT0(cd.qtcAmpl, CTF::BLC_qtcAmpl, o2::rans::ProbabilityBits25Bit); + ENCODEFT0(cd.trigger, CTF::BLC_trigger, 0); + ENCODEFT0(cd.bcInc, CTF::BLC_bcInc, 0); + ENCODEFT0(cd.orbitInc, CTF::BLC_orbitInc, 0); + ENCODEFT0(cd.nChan, CTF::BLC_nChan, 0); + // ENCODEFT0(cd.eventFlags, CTF::BLC_flags, 0); + ENCODEFT0(cd.idChan , CTF::BLC_idChan, 0); + ENCODEFT0(cd.qtcChain, CTF::BLC_qtcChain, 0); + ENCODEFT0(cd.cfdTime, CTF::BLC_cfdTime, 0); + ENCODEFT0(cd.qtcAmpl, CTF::BLC_qtcAmpl, 0); // clang-format on CTF::get(buff.data())->print(getPrefix()); } diff --git a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h index ca4067dcb7838..c3e5bec7accd4 100644 --- a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h @@ -89,13 +89,13 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const BCData>& digitVec, const // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec #define ENCODEFV0(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODEFV0(cd.bcInc, CTF::BLC_bcInc, o2::rans::ProbabilityBits16Bit); - ENCODEFV0(cd.orbitInc, CTF::BLC_orbitInc, o2::rans::ProbabilityBits16Bit); - ENCODEFV0(cd.nChan, CTF::BLC_nChan, o2::rans::ProbabilityBits8Bit); + ENCODEFV0(cd.bcInc, CTF::BLC_bcInc, 0); + ENCODEFV0(cd.orbitInc, CTF::BLC_orbitInc, 0); + ENCODEFV0(cd.nChan, CTF::BLC_nChan, 0); - ENCODEFV0(cd.idChan , CTF::BLC_idChan, o2::rans::ProbabilityBits8Bit); - ENCODEFV0(cd.time, CTF::BLC_time, o2::rans::ProbabilityBits16Bit); - ENCODEFV0(cd.charge, CTF::BLC_charge, o2::rans::ProbabilityBits25Bit); + ENCODEFV0(cd.idChan , CTF::BLC_idChan, 0); + ENCODEFV0(cd.time, CTF::BLC_time, 0); + ENCODEFV0(cd.charge, CTF::BLC_charge, 0); // clang-format on CTF::get(buff.data())->print(getPrefix()); } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h index 8332891cb52f3..acbb25878a941 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h @@ -92,17 +92,17 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ROFRecord>& rofRecVec, co // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec #define ENCODEITSMFT(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODEITSMFT(cc.firstChipROF, CTF::BLCfirstChipROF, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.nclusROF, CTF::BLCnclusROF, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.firstChipROF, CTF::BLCfirstChipROF, 0); + ENCODEITSMFT(cc.bcIncROF, CTF::BLCbcIncROF, 0); + ENCODEITSMFT(cc.orbitIncROF, CTF::BLCorbitIncROF, 0); + ENCODEITSMFT(cc.nclusROF, CTF::BLCnclusROF, 0); // - ENCODEITSMFT(cc.chipInc, CTF::BLCchipInc, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.chipMul, CTF::BLCchipMul, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.row, CTF::BLCrow, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.colInc, CTF::BLCcolInc, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.pattID, CTF::BLCpattID, o2::rans::ProbabilityBits16Bit); - ENCODEITSMFT(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit); + ENCODEITSMFT(cc.chipInc, CTF::BLCchipInc, 0); + ENCODEITSMFT(cc.chipMul, CTF::BLCchipMul, 0); + ENCODEITSMFT(cc.row, CTF::BLCrow, 0); + ENCODEITSMFT(cc.colInc, CTF::BLCcolInc, 0); + ENCODEITSMFT(cc.pattID, CTF::BLCpattID, 0); + ENCODEITSMFT(cc.pattMap, CTF::BLCpattMap, 0); // clang-format on CTF::get(buff.data())->print(getPrefix()); } diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index 671e35a414ca2..ff9e28032df20 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -92,16 +92,16 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRe // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec #define ENCODETOF(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODETOF(cc.bcIncROF, CTF::BLCbcIncROF, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.orbitIncROF, CTF::BLCorbitIncROF, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.ndigROF, CTF::BLCndigROF, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.ndiaROF, CTF::BLCndiaROF, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.timeFrameInc, CTF::BLCtimeFrameInc, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.timeTDCInc, CTF::BLCtimeTDCInc, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.stripID, CTF::BLCstripID, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.chanInStrip, CTF::BLCchanInStrip, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.tot, CTF::BLCtot, o2::rans::ProbabilityBits16Bit); - ENCODETOF(cc.pattMap, CTF::BLCpattMap, o2::rans::ProbabilityBits16Bit); + ENCODETOF(cc.bcIncROF, CTF::BLCbcIncROF, 0); + ENCODETOF(cc.orbitIncROF, CTF::BLCorbitIncROF, 0); + ENCODETOF(cc.ndigROF, CTF::BLCndigROF, 0); + ENCODETOF(cc.ndiaROF, CTF::BLCndiaROF, 0); + ENCODETOF(cc.timeFrameInc, CTF::BLCtimeFrameInc, 0); + ENCODETOF(cc.timeTDCInc, CTF::BLCtimeTDCInc, 0); + ENCODETOF(cc.stripID, CTF::BLCstripID, 0); + ENCODETOF(cc.chanInStrip, CTF::BLCchanInStrip, 0); + ENCODETOF(cc.tot, CTF::BLCtot, 0); + ENCODETOF(cc.pattMap, CTF::BLCpattMap, 0); // clang-format on CTF::get(buff.data())->print(getPrefix()); } diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h index 417f3d4572cfe..5c8dcad4f57b9 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h @@ -110,29 +110,29 @@ void CTFCoder::encode(VEC& buff, const CompressedClusters& ccl) // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec #define ENCODETPC(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODETPC(ccl.qTotA, ccl.qTotA + ccl.nAttachedClusters, CTF::BLCqTotA, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.qMaxA, ccl.qMaxA + ccl.nAttachedClusters, CTF::BLCqMaxA, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.flagsA, ccl.flagsA + ccl.nAttachedClusters, CTF::BLCflagsA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.rowDiffA, ccl.rowDiffA + ccl.nAttachedClustersReduced, CTF::BLCrowDiffA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.sliceLegDiffA, ccl.sliceLegDiffA + ccl.nAttachedClustersReduced, CTF::BLCsliceLegDiffA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.padResA, ccl.padResA + ccl.nAttachedClustersReduced, CTF::BLCpadResA, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.timeResA, ccl.timeResA + ccl.nAttachedClustersReduced, CTF::BLCtimeResA, o2::rans::ProbabilityBits25Bit); - ENCODETPC(ccl.sigmaPadA, ccl.sigmaPadA + ccl.nAttachedClusters, CTF::BLCsigmaPadA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.sigmaTimeA, ccl.sigmaTimeA + ccl.nAttachedClusters, CTF::BLCsigmaTimeA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.qPtA, ccl.qPtA + ccl.nTracks, CTF::BLCqPtA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.rowA, ccl.rowA + ccl.nTracks, CTF::BLCrowA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.sliceA, ccl.sliceA + ccl.nTracks, CTF::BLCsliceA, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.timeA, ccl.timeA + ccl.nTracks, CTF::BLCtimeA, o2::rans::ProbabilityBits25Bit); - ENCODETPC(ccl.padA, ccl.padA + ccl.nTracks, CTF::BLCpadA, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.qTotU, ccl.qTotU + ccl.nUnattachedClusters, CTF::BLCqTotU, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.qMaxU, ccl.qMaxU + ccl.nUnattachedClusters, CTF::BLCqMaxU, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.flagsU, ccl.flagsU + ccl.nUnattachedClusters, CTF::BLCflagsU, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.padDiffU, ccl.padDiffU + ccl.nUnattachedClusters, CTF::BLCpadDiffU, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.timeDiffU, ccl.timeDiffU + ccl.nUnattachedClusters, CTF::BLCtimeDiffU, o2::rans::ProbabilityBits25Bit); - ENCODETPC(ccl.sigmaPadU, ccl.sigmaPadU + ccl.nUnattachedClusters, CTF::BLCsigmaPadU, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.sigmaTimeU, ccl.sigmaTimeU + ccl.nUnattachedClusters, CTF::BLCsigmaTimeU, o2::rans::ProbabilityBits8Bit); - ENCODETPC(ccl.nTrackClusters, ccl.nTrackClusters + ccl.nTracks, CTF::BLCnTrackClusters, o2::rans::ProbabilityBits16Bit); - ENCODETPC(ccl.nSliceRowClusters, ccl.nSliceRowClusters + ccl.nSliceRows, CTF::BLCnSliceRowClusters, o2::rans::ProbabilityBits25Bit); + ENCODETPC(ccl.qTotA, ccl.qTotA + ccl.nAttachedClusters, CTF::BLCqTotA, 0); + ENCODETPC(ccl.qMaxA, ccl.qMaxA + ccl.nAttachedClusters, CTF::BLCqMaxA, 0); + ENCODETPC(ccl.flagsA, ccl.flagsA + ccl.nAttachedClusters, CTF::BLCflagsA, 0); + ENCODETPC(ccl.rowDiffA, ccl.rowDiffA + ccl.nAttachedClustersReduced, CTF::BLCrowDiffA, 0); + ENCODETPC(ccl.sliceLegDiffA, ccl.sliceLegDiffA + ccl.nAttachedClustersReduced, CTF::BLCsliceLegDiffA, 0); + ENCODETPC(ccl.padResA, ccl.padResA + ccl.nAttachedClustersReduced, CTF::BLCpadResA, 0); + ENCODETPC(ccl.timeResA, ccl.timeResA + ccl.nAttachedClustersReduced, CTF::BLCtimeResA, 0); + ENCODETPC(ccl.sigmaPadA, ccl.sigmaPadA + ccl.nAttachedClusters, CTF::BLCsigmaPadA, 0); + ENCODETPC(ccl.sigmaTimeA, ccl.sigmaTimeA + ccl.nAttachedClusters, CTF::BLCsigmaTimeA, 0); + ENCODETPC(ccl.qPtA, ccl.qPtA + ccl.nTracks, CTF::BLCqPtA, 0); + ENCODETPC(ccl.rowA, ccl.rowA + ccl.nTracks, CTF::BLCrowA, 0); + ENCODETPC(ccl.sliceA, ccl.sliceA + ccl.nTracks, CTF::BLCsliceA, 0); + ENCODETPC(ccl.timeA, ccl.timeA + ccl.nTracks, CTF::BLCtimeA, 0); + ENCODETPC(ccl.padA, ccl.padA + ccl.nTracks, CTF::BLCpadA, 0); + ENCODETPC(ccl.qTotU, ccl.qTotU + ccl.nUnattachedClusters, CTF::BLCqTotU, 0); + ENCODETPC(ccl.qMaxU, ccl.qMaxU + ccl.nUnattachedClusters, CTF::BLCqMaxU, 0); + ENCODETPC(ccl.flagsU, ccl.flagsU + ccl.nUnattachedClusters, CTF::BLCflagsU, 0); + ENCODETPC(ccl.padDiffU, ccl.padDiffU + ccl.nUnattachedClusters, CTF::BLCpadDiffU, 0); + ENCODETPC(ccl.timeDiffU, ccl.timeDiffU + ccl.nUnattachedClusters, CTF::BLCtimeDiffU, 0); + ENCODETPC(ccl.sigmaPadU, ccl.sigmaPadU + ccl.nUnattachedClusters, CTF::BLCsigmaPadU, 0); + ENCODETPC(ccl.sigmaTimeU, ccl.sigmaTimeU + ccl.nUnattachedClusters, CTF::BLCsigmaTimeU, 0); + ENCODETPC(ccl.nTrackClusters, ccl.nTrackClusters + ccl.nTracks, CTF::BLCnTrackClusters, 0); + ENCODETPC(ccl.nSliceRowClusters, ccl.nSliceRowClusters + ccl.nSliceRows, CTF::BLCnSliceRowClusters, 0); // clang-format on CTF::get(buff.data())->print(getPrefix()); } diff --git a/Utilities/rANS/include/rANS/Decoder.h b/Utilities/rANS/include/rANS/Decoder.h index af121a60d43aa..b9ace6e49fc2b 100644 --- a/Utilities/rANS/include/rANS/Decoder.h +++ b/Utilities/rANS/include/rANS/Decoder.h @@ -93,10 +93,11 @@ Decoder<coder_T, stream_T, source_T>::Decoder(const FrequencyTable& frequencies, using namespace internal; SymbolStatistics stats(frequencies, mProbabilityBits); + mProbabilityBits = stats.getSymbolTablePrecision(); RANSTimer t; t.start(); - mSymbolTable = std::make_unique<decoderSymbolTable_t>(stats, mProbabilityBits); + mSymbolTable = std::make_unique<decoderSymbolTable_t>(stats); t.stop(); LOG(debug1) << "Decoder SymbolTable inclusive time (ms): " << t.getDurationMS(); t.start(); diff --git a/Utilities/rANS/include/rANS/Encoder.h b/Utilities/rANS/include/rANS/Encoder.h index 5c61a4cd6e9f0..907302b14202c 100644 --- a/Utilities/rANS/include/rANS/Encoder.h +++ b/Utilities/rANS/include/rANS/Encoder.h @@ -103,10 +103,11 @@ Encoder<coder_T, stream_T, source_T>::Encoder(const FrequencyTable& frequencies, using namespace internal; SymbolStatistics stats(frequencies, mProbabilityBits); + mProbabilityBits = stats.getSymbolTablePrecision(); RANSTimer t; t.start(); - mSymbolTable = std::make_unique<encoderSymbolTable_t>(stats, probabilityBits); + mSymbolTable = std::make_unique<encoderSymbolTable_t>(stats); t.stop(); LOG(debug1) << "Encoder SymbolTable inclusive time (ms): " << t.getDurationMS(); } diff --git a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h index 52f72f6f2c294..686c470a11f6c 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h @@ -37,6 +37,9 @@ namespace rans namespace internal { +constexpr size_t MIN_SCALE = 16; +constexpr size_t MAX_SCALE = 27; + class SymbolStatistics { @@ -72,7 +75,7 @@ class SymbolStatistics }; public: - SymbolStatistics(const FrequencyTable& frequencyTable, size_t scaleBits); + SymbolStatistics(const FrequencyTable& frequencyTable, size_t scaleBits = 0); template <typename Source_IT> SymbolStatistics(const Source_IT begin, const Source_IT end, int64_t min, int64_t max, size_t scaleBits, size_t nUsedAlphabetSymbols); @@ -92,6 +95,8 @@ class SymbolStatistics size_t getNUsedAlphabetSymbols() const; + size_t getSymbolTablePrecision() const; + private: void buildCumulativeFrequencyTable(); @@ -122,7 +127,15 @@ SymbolStatistics::SymbolStatistics(const Source_IT begin, const Source_IT end, i return; } - assert(mScaleBits > 0); + // if we did not calculate renormalization size, calculate it. + if (scaleBits == 0) { + mScaleBits = [&, this]() { + const size_t minScale = MIN_SCALE; + const size_t maxScale = MAX_SCALE; + const size_t calculated = static_cast<uint32_t>(3 * std::ceil(std::log2(getNUsedAlphabetSymbols())) / 2 + 2); + return std::max(minScale, std::min(maxScale, calculated)); + }(); + } //additional bit for escape symbol mFrequencyTable.reserve(std::distance(begin, end) + 1); @@ -178,6 +191,11 @@ inline size_t SymbolStatistics::size() const return mFrequencyTable.size(); } +inline size_t SymbolStatistics::getSymbolTablePrecision() const +{ + return mScaleBits; +} + inline std::tuple<uint32_t, uint32_t> SymbolStatistics::operator[](int64_t index) const { assert(index - mMin < mFrequencyTable.size()); diff --git a/Utilities/rANS/include/rANS/internal/SymbolTable.h b/Utilities/rANS/include/rANS/internal/SymbolTable.h index 5a74933cb942d..d13fb340853db 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolTable.h +++ b/Utilities/rANS/include/rANS/internal/SymbolTable.h @@ -35,7 +35,7 @@ class SymbolTable { public: - SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits); + SymbolTable(const SymbolStatistics& symbolStats); const T& operator[](int64_t index) const; @@ -56,7 +56,7 @@ class SymbolTable }; template <typename T> -SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabiltyBits) : mMin(symbolStats.getMinSymbol()), mMax(symbolStats.getMaxSymbol()), mIndex(), mSymbols(), mEscapeSymbol(nullptr) +SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats) : mMin(symbolStats.getMinSymbol()), mMax(symbolStats.getMaxSymbol()), mIndex(), mSymbols(), mEscapeSymbol(nullptr) { LOG(trace) << "start building symbol table"; @@ -67,7 +67,7 @@ SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabil const auto it = symbolStats.getEscapeSymbol(); if (it != symbolStats.end()) { const auto [symFrequency, symCumulated] = *(it); - return std::make_unique<T>(symCumulated, symFrequency, probabiltyBits); + return std::make_unique<T>(symCumulated, symFrequency, symbolStats.getSymbolTablePrecision()); } else { return nullptr; } @@ -76,7 +76,7 @@ SymbolTable<T>::SymbolTable(const SymbolStatistics& symbolStats, size_t probabil for (auto it = symbolStats.begin(); it != symbolStats.getEscapeSymbol(); ++it) { const auto [symFrequency, symCumulated] = *it; if (symFrequency) { - mSymbols.emplace_back(symCumulated, symFrequency, probabiltyBits); + mSymbols.emplace_back(symCumulated, symFrequency, symbolStats.getSymbolTablePrecision()); mIndex.emplace_back(&mSymbols.back()); } else { mIndex.emplace_back(mEscapeSymbol.get()); diff --git a/Utilities/rANS/include/rANS/rans.h b/Utilities/rANS/include/rANS/rans.h index be2fd50b8fd42..4353abbec8001 100644 --- a/Utilities/rANS/include/rANS/rans.h +++ b/Utilities/rANS/include/rANS/rans.h @@ -59,11 +59,6 @@ using DedupDecoder32 = DedupDecoder<uint32_t, uint8_t, source_T>; template <typename source_T> using DedupDecoder64 = DedupDecoder<uint64_t, uint32_t, source_T>; -//rans default values -constexpr size_t ProbabilityBits8Bit = 10; -constexpr size_t ProbabilityBits16Bit = 22; -constexpr size_t ProbabilityBits25Bit = 25; - inline size_t calculateMaxBufferSize(size_t num, size_t rangeBits, size_t sizeofStreamT) { // // RS: w/o safety margin the o2-test-ctf-io produces an overflow in the Encoder::process diff --git a/Utilities/rANS/run/bin-encode-decode.cxx b/Utilities/rANS/run/bin-encode-decode.cxx index d11416b6f9f31..a3af57b308e0e 100644 --- a/Utilities/rANS/run/bin-encode-decode.cxx +++ b/Utilities/rANS/run/bin-encode-decode.cxx @@ -29,7 +29,6 @@ using source_t = SOURCE_T; using coder_t = uint64_t; using stream_t = uint32_t; static const uint REPETITIONS = 5; -static const uint PROB_BITS = 18; template <typename T> void readFile(const std::string& filename, std::vector<T>* tokens) @@ -68,7 +67,7 @@ int main(int argc, char* argv[]) ("help,h", "print usage message") ("file,f",bpo::value<std::string>(), "file to compress") ("samples,s",bpo::value<uint32_t>(), "how often to run benchmark") - ("bits,b",bpo::value<uint32_t>()->default_value(20), "resample dictionary to N Bits") + ("bits,b",bpo::value<uint32_t>(), "resample dictionary to N Bits") ("range,r",bpo::value<uint32_t>()->default_value(0), "range of the source data") ("log_severity,l",bpo::value<std::string>(), "severity of FairLogger"); // clang-format on @@ -95,7 +94,7 @@ int main(int argc, char* argv[]) if (vm.count("bits")) { return vm["bits"].as<uint32_t>(); } else { - return PROB_BITS; + return 0u; } }(); From 6f67e44693756fe4190fe2c3c399e9fcff45d14e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Aug 2020 10:41:40 +0200 Subject: [PATCH 0356/1751] TPC: protect against missing omp.h --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 7f41b76d79cec..0d339e6e0f6a9 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -35,7 +35,9 @@ #include "GPUHostDataTypes.h" #include <atomic> +#ifdef WITH_OPENMP #include <omp.h> +#endif using namespace o2::gpu; using namespace o2::tpc; From 8c10ba6f455703aa01d20e1a7dfc72ba791cd854 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Aug 2020 10:42:19 +0200 Subject: [PATCH 0357/1751] DPL: make Monitoring and ParallelContext a Global services --- Framework/Core/include/Framework/Monitoring.h | 26 +++++++++++++++++++ .../Core/include/Framework/ParallelContext.h | 14 +++++----- Framework/Core/src/CommonServices.cxx | 2 +- Framework/Core/src/DataProcessingDevice.cxx | 2 +- Framework/Core/src/Dispatcher.cxx | 9 +++---- Framework/Core/src/runDataProcessing.cxx | 1 + Framework/Core/test/test_Task.cxx | 3 +-- .../TestWorkflows/src/o2DummyWorkflow.cxx | 2 +- Utilities/Mergers/test/emptyLoopBenchmark.cxx | 3 ++- 9 files changed, 43 insertions(+), 19 deletions(-) create mode 100644 Framework/Core/include/Framework/Monitoring.h diff --git a/Framework/Core/include/Framework/Monitoring.h b/Framework/Core/include/Framework/Monitoring.h new file mode 100644 index 0000000000000..26d4c1c38c34a --- /dev/null +++ b/Framework/Core/include/Framework/Monitoring.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_FRAMEWORK_MONITORING_H_ +#define O2_FRAMEWORK_MONITORING_H_ + +#include "Framework/ServiceHandle.h" + +#include <Monitoring/Monitoring.h> + +namespace o2::framework +{ +template <> +struct ServiceKindExtractor<o2::monitoring::Monitoring> { + constexpr static ServiceKind kind = ServiceKind::Global; +}; +} // namespace o2::framework + +#endif // O2_FRAMEWORK_MONITORING_H_ diff --git a/Framework/Core/include/Framework/ParallelContext.h b/Framework/Core/include/Framework/ParallelContext.h index 5718f9d1ab75a..79c0de7d70a4f 100644 --- a/Framework/Core/include/Framework/ParallelContext.h +++ b/Framework/Core/include/Framework/ParallelContext.h @@ -8,12 +8,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef FRAMEWORK_PARALLELCONTEXT_H -#define FRAMEWORK_PARALLELCONTEXT_H +#ifndef O2_FRAMEWORK_PARALLELCONTEXT_H_ +#define O2_FRAMEWORK_PARALLELCONTEXT_H_ -namespace o2 -{ -namespace framework +#include "Framework/ServiceHandle.h" + +namespace o2::framework { /// Purpose of this class is to provide DataProcessors which @@ -31,6 +31,7 @@ namespace framework class ParallelContext { public: + constexpr static ServiceKind service_kind = ServiceKind::Global; // FIXME: find better names... rank1D and rank1DSize? ParallelContext(size_t index1D, size_t index1DSize) : mIndex1D{index1D}, @@ -46,6 +47,5 @@ class ParallelContext size_t mIndex1DSize; }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index d5a06021d645b..6b08496ba7046 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -22,12 +22,12 @@ #include "Framework/DanglingContext.h" #include "Framework/EndOfStreamContext.h" #include "Framework/Tracing.h" +#include "Framework/Monitoring.h" #include "../src/DataProcessingStatus.h" #include <Configuration/ConfigurationInterface.h> #include <Configuration/ConfigurationFactory.h> #include <Monitoring/MonitoringFactory.h> -#include <Monitoring/Monitoring.h> #include <InfoLogger/InfoLogger.hxx> #include <options/FairMQProgOptions.h> diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index aab998c66c6a4..b2fd9b69dc2dd 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -31,6 +31,7 @@ #include "Framework/Signpost.h" #include "Framework/SourceInfoHeader.h" #include "Framework/Logger.h" +#include "Framework/Monitoring.h" #include "DataProcessingStatus.h" #include "DataProcessingHelpers.h" #include "DataRelayerHelpers.h" @@ -44,7 +45,6 @@ #include <options/FairMQProgOptions.h> #include <Configuration/ConfigurationInterface.h> #include <Configuration/ConfigurationFactory.h> -#include <Monitoring/Monitoring.h> #include <TMessage.h> #include <TClonesArray.h> diff --git a/Framework/Core/src/Dispatcher.cxx b/Framework/Core/src/Dispatcher.cxx index 2f1246ab7a621..275d02e96dd3b 100644 --- a/Framework/Core/src/Dispatcher.cxx +++ b/Framework/Core/src/Dispatcher.cxx @@ -23,7 +23,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/InputRecordWalker.h" -#include <Monitoring/Monitoring.h> +#include "Framework/Monitoring.h" #include <Configuration/ConfigurationInterface.h> #include <Configuration/ConfigurationFactory.h> #include <fairmq/FairMQDevice.h> @@ -31,9 +31,7 @@ using namespace o2::configuration; using namespace o2::monitoring; -namespace o2 -{ -namespace framework +namespace o2::framework { Dispatcher::Dispatcher(std::string name, const std::string reconfigurationSource) @@ -222,5 +220,4 @@ Outputs Dispatcher::getOutputSpecs() return outputs; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 2407e0c528cc2..98e2cd1139f0c 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -42,6 +42,7 @@ #include "Framework/TextControlService.h" #include "Framework/CallbackService.h" #include "Framework/WorkflowSpec.h" +#include "Framework/Monitoring.h" #include "ComputingResourceHelpers.h" #include "DataProcessingStatus.h" diff --git a/Framework/Core/test/test_Task.cxx b/Framework/Core/test/test_Task.cxx index 90e2ee15b9c7f..379c56960a614 100644 --- a/Framework/Core/test/test_Task.cxx +++ b/Framework/Core/test/test_Task.cxx @@ -10,8 +10,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/Task.h" #include "Framework/ControlService.h" -#include <Monitoring/Monitoring.h> -#include "Framework/ControlService.h" +#include "Framework/Monitoring.h" #define ASSERT_ERROR(condition) \ if ((condition) == false) { \ diff --git a/Framework/TestWorkflows/src/o2DummyWorkflow.cxx b/Framework/TestWorkflows/src/o2DummyWorkflow.cxx index 8ae63bbb8d077..ae4c86ade35f2 100644 --- a/Framework/TestWorkflows/src/o2DummyWorkflow.cxx +++ b/Framework/TestWorkflows/src/o2DummyWorkflow.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. #include "Framework/DataRefUtils.h" #include "Framework/runDataProcessing.h" -#include <Monitoring/Monitoring.h> +#include "Framework/Monitoring.h" #include "Framework/Logger.h" #include <chrono> diff --git a/Utilities/Mergers/test/emptyLoopBenchmark.cxx b/Utilities/Mergers/test/emptyLoopBenchmark.cxx index be98727faf80b..2ec37b5f8895e 100644 --- a/Utilities/Mergers/test/emptyLoopBenchmark.cxx +++ b/Utilities/Mergers/test/emptyLoopBenchmark.cxx @@ -17,6 +17,7 @@ #include "Framework/CompletionPolicy.h" #include "Framework/CompletionPolicyHelpers.h" #include "Framework/DeviceSpec.h" +#include "Framework/Monitoring.h" using namespace o2::framework; @@ -116,4 +117,4 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) specs.push_back(heWhoRequestsExit); return specs; -} \ No newline at end of file +} From 4212e28a3e4133bf624146d3f63918b3d4339f3e Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 13 Aug 2020 14:56:55 +0200 Subject: [PATCH 0358/1751] Put TRD constants in namespace o2::trd::constants --- DataFormats/Detectors/TRD/CMakeLists.txt | 4 +- .../TRD/include/DataFormatsTRD/Constants.h | 50 ++++ .../TRD/include/DataFormatsTRD/Tracklet64.h | 10 - Detectors/TRD/base/include/TRDBase/CalDet.h | 8 +- Detectors/TRD/base/include/TRDBase/CalPad.h | 10 +- .../include/TRDBase/ChamberCalibrations.h | 9 +- .../TRD/base/include/TRDBase/ChamberNoise.h | 3 +- .../TRD/base/include/TRDBase/ChamberStatus.h | 3 +- Detectors/TRD/base/include/TRDBase/Digit.h | 3 +- Detectors/TRD/base/include/TRDBase/FeeParam.h | 45 +--- .../base/include/TRDBase/PadCalibrations.h | 3 +- .../TRD/base/include/TRDBase/PadParameters.h | 17 +- .../TRD/base/include/TRDBase/PadResponse.h | 4 +- .../base/include/TRDBase/TRDCalPadStatus.h | 8 +- .../TRD/base/include/TRDBase/TRDCommonParam.h | 2 - .../base/include/TRDBase/TRDGeometryBase.h | 21 +- .../base/include/TRDBase/TRDGeometryFlat.h | 3 +- .../TRD/base/include/TRDBase/TRDSimParam.h | 7 +- Detectors/TRD/base/src/CalDet.cxx | 75 +++--- .../TRD/base/src/CalOnlineGainTables.cxx | 6 +- Detectors/TRD/base/src/CalPad.cxx | 57 ++--- Detectors/TRD/base/src/FeeParam.cxx | 87 +++---- Detectors/TRD/base/src/PadResponse.cxx | 11 +- Detectors/TRD/base/src/TRDCalPadStatus.cxx | 21 +- Detectors/TRD/base/src/TRDGeometry.cxx | 237 +++++++++--------- Detectors/TRD/base/src/TRDGeometryBase.cxx | 9 +- Detectors/TRD/base/src/TRDGeometryFlat.cxx | 5 +- Detectors/TRD/macros/CMakeLists.txt | 3 +- Detectors/TRD/macros/CheckDigits.C | 3 +- .../include/TRDSimulation/Digitizer.h | 9 +- .../include/TRDSimulation/TrapConfigHandler.h | 4 - .../include/TRDSimulation/TrapSimulator.h | 9 +- Detectors/TRD/simulation/src/Detector.cxx | 6 +- Detectors/TRD/simulation/src/Digitizer.cxx | 15 +- Detectors/TRD/simulation/src/Trap2CRU.cxx | 3 +- Detectors/TRD/simulation/src/TrapConfig.cxx | 14 +- .../TRD/simulation/src/TrapConfigHandler.cxx | 14 +- .../TRD/simulation/src/TrapSimulator.cxx | 94 +++---- GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h | 3 +- 39 files changed, 465 insertions(+), 430 deletions(-) create mode 100644 DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h diff --git a/DataFormats/Detectors/TRD/CMakeLists.txt b/DataFormats/Detectors/TRD/CMakeLists.txt index 4554b4df53635..d41cc697843a9 100644 --- a/DataFormats/Detectors/TRD/CMakeLists.txt +++ b/DataFormats/Detectors/TRD/CMakeLists.txt @@ -19,5 +19,5 @@ o2_add_library(DataFormatsTRD HEADERS include/DataFormatsTRD/TriggerRecord.h include/DataFormatsTRD/LinkRecord.h include/DataFormatsTRD/Tracklet64.h - include/DataFormatsTRD/RawData.h) - + include/DataFormatsTRD/RawData.h + include/DataFormatsTRD/Constants.h) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h new file mode 100644 index 0000000000000..39aa176c0e0a7 --- /dev/null +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h @@ -0,0 +1,50 @@ +// 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 Constants.h +/// \brief Global TRD definitions and constants +/// \author ole.schmidt@cern.ch + +#ifndef AliceO2_TRD_Constants_H +#define AliceO2_TRD_Constants_H + +namespace o2 +{ +namespace trd +{ +namespace constants +{ +constexpr int NSECTOR = 18; // the number of sectors +constexpr int NSTACK = 5; // the number of stacks per sector +constexpr int NLAYER = 6; // the number of layers +constexpr int NCHAMBERPERSEC = 30; // the number of chambers per sector +constexpr int MAXCHAMBER = 540; // the maximum number of installed chambers +constexpr int NCHAMBER = 521; // the number of chambers actually installed + +constexpr int NCOLUMN = 144; // the number of pad columns for each chamber +constexpr int NROWC0 = 12; // the number of pad rows for chambers of type C0 (installed stack 0,1,3 and 4) +constexpr int NROWC1 = 16; // the number of pad rows for chambers of type C1 (installed in stack 2) + +constexpr int NMCMROB = 16; // the number of MCMs per ROB +constexpr int NMCMROBINROW = 4; // the number of MCMs per ROB in row direction +constexpr int NMCMROBINCOL = 4; // the number of MCMs per ROB in column direction +constexpr int NROBC0 = 6; // the number of ROBs per C0 chamber +constexpr int NROBC1 = 8; // the number of ROBs per C1 chamber +constexpr int NADCMCM = 21; // the number of ADC channels per MCM +constexpr int NCOLMCM = 18; // the number of pads per MCM + +// OS: Should this not be flexible for example in case of Kr calib? +constexpr int TIMEBINS = 30; // the number of time bins + +} //namespace constants +} // namespace trd +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index 7550c081ea166..465d0f9f195e5 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -82,16 +82,6 @@ class Tracklet64 mtrackletWord = trackletword; return 0; } - static const int mgkNmcmRob = 16; // Number of MCMs per ROB - static const int mgkNmcmRobInRow = 4; // Number of MCMs per ROB in row dir. - static const int mgkNmcmRobInCol = 4; // Number of MCMs per ROB in col dir. - static const int mgkNrobC0 = 6; // Number of ROBs per C0 chamber - static const int mgkNrobC1 = 8; // Number of ROBs per C1 chamber - static const int mgkNadcMcm = 21; // Number of ADC channels per MCM - static const int mgkNcol = 144; // Number of pads per padplane row - static const int mgkNcolMcm = 18; // Number of pads per MCM - static const int mgkNrowC0 = 12; // Number of Rows per C0 chamber - static const int mgkNrowC1 = 16; // Number of Rows per C1 chamber // ----- Getters for tracklet information ----- int getMCM() const diff --git a/Detectors/TRD/base/include/TRDBase/CalDet.h b/Detectors/TRD/base/include/TRDBase/CalDet.h index 5216976a3b3d9..15df17376723a 100644 --- a/Detectors/TRD/base/include/TRDBase/CalDet.h +++ b/Detectors/TRD/base/include/TRDBase/CalDet.h @@ -18,6 +18,8 @@ // // /////////////////////////////////////////////////////////////////////////////// +#include "DataFormatsTRD/Constants.h" + class TRDGeometry; class TRDPadPlane; @@ -31,10 +33,6 @@ namespace trd class CalDet { public: - enum { kNplan = 6, - kNcham = 5, - kNsect = 18, - kNdet = 540 }; CalDet(std::string name = "CalDet", std::string title = "CalDet") : mName(name), mTitle(title){}; ~CalDet() = default; // @@ -71,7 +69,7 @@ class CalDet void divide(const CalDet* calDet); protected: - std::array<float, kNdet> mData{}; // Data + std::array<float, constants::NSECTOR> mData{}; // Data std::string mName; // name for spectra, carried over originally from inheritence from TNamed std::string mTitle; // title prepend for spectra, carried over originally from inheritence from TNamed }; diff --git a/Detectors/TRD/base/include/TRDBase/CalPad.h b/Detectors/TRD/base/include/TRDBase/CalPad.h index 9795dcff40052..a9708af8d1f49 100644 --- a/Detectors/TRD/base/include/TRDBase/CalPad.h +++ b/Detectors/TRD/base/include/TRDBase/CalPad.h @@ -17,6 +17,8 @@ // // /////////////////////////////////////////////////////////////////////////////// +#include "DataFormatsTRD/Constants.h" + class CalROC; class CalDet; class TH2F; @@ -26,10 +28,6 @@ class CalPad { public: - enum { kNplan = 6, - kNcham = 5, - kNsect = 18, - kNdet = 540 }; CalPad(); CalPad(const std::string& name, const std::String& title); @@ -37,7 +35,7 @@ class CalPad ~CalPad(); CalPad& operator=(const CalPad& c); - static int getDet(int p, int c, int s) { return p + c * kNplan + s * kNplan * kNcham; }; + static int getDet(int p, int c, int s) { return p + c * Constants::NLAYER + s * Constants::NLAYER * Constants::NSTACK; }; CalROC* getCalROC(int d) const { return mROC[d]; }; CalROC* getCalROC(int p, int c, int s) const @@ -69,7 +67,7 @@ class CalPad bool divide(const CalPad* pad, const CalDet* calDet1 = 0, const CalDet* calDet2 = 0, int type = 0); protected: - std::vector<CalROC> mROC(kNdet); // Array of ROC objects which contain the values per pad + std::vector<CalROC> mROC(Constants::MAXCHAMBER); // Array of ROC objects which contain the values per pad ClassDef(CalPad, 1) // TRD calibration class for parameters which are saved per pad }; diff --git a/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h b/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h index da27f66b7b856..f286178b252d9 100644 --- a/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h +++ b/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h @@ -19,6 +19,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "TRDBase/TRDSimParam.h" +#include "DataFormatsTRD/Constants.h" // class TRDGeometry; @@ -52,10 +53,10 @@ class ChamberCalibrations bool init(int run2run = 0); protected: - std::array<float, TRDSimParam::kNdet> mVDrift{}; // mean drift velocity per chamber. - std::array<float, TRDSimParam::kNdet> mGainFactor{}; // mean gas gain per chamber - std::array<float, TRDSimParam::kNdet> mT0{}; // Min timeoffset in the chamber - std::array<float, TRDSimParam::kNdet> mExB{}; // + std::array<float, constants::MAXCHAMBER> mVDrift{}; // mean drift velocity per chamber. + std::array<float, constants::MAXCHAMBER> mGainFactor{}; // mean gas gain per chamber + std::array<float, constants::MAXCHAMBER> mT0{}; // Min timeoffset in the chamber + std::array<float, constants::MAXCHAMBER> mExB{}; // }; } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/ChamberNoise.h b/Detectors/TRD/base/include/TRDBase/ChamberNoise.h index dfa477457d7cc..37147afd9a216 100644 --- a/Detectors/TRD/base/include/TRDBase/ChamberNoise.h +++ b/Detectors/TRD/base/include/TRDBase/ChamberNoise.h @@ -19,6 +19,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "TRDBase/TRDSimParam.h" +#include "DataFormatsTRD/Constants.h" // class TRDGeometry; @@ -38,7 +39,7 @@ class ChamberNoise void setNoise(int det, float noise) { mNoise[det] = noise; }; //bulk gets ? protected: - std::array<float, TRDSimParam::kNdet> mNoise{}; + std::array<float, constants::MAXCHAMBER> mNoise{}; }; } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/ChamberStatus.h b/Detectors/TRD/base/include/TRDBase/ChamberStatus.h index afd6951a0d0cf..759aacbb273c7 100644 --- a/Detectors/TRD/base/include/TRDBase/ChamberStatus.h +++ b/Detectors/TRD/base/include/TRDBase/ChamberStatus.h @@ -23,6 +23,7 @@ #include <array> #include "TRDBase/TRDGeometry.h" #include "TRDBase/TRDSimParam.h" +#include "DataFormatsTRD/Constants.h" class TH2D; namespace o2 @@ -67,7 +68,7 @@ class ChamberStatus TH2D* plotBadCalibrated(int sm, int rphi); // Plot calibration status for sm and halfchamberside TH2D* plot(int sm); // Plot mStatus for sm protected: - std::array<char, TRDSimParam::kNdet> mStatus{}; + std::array<char, constants::MAXCHAMBER> mStatus{}; }; } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/Digit.h b/Detectors/TRD/base/include/TRDBase/Digit.h index 31436dcd4d283..8c6bb74629226 100644 --- a/Detectors/TRD/base/include/TRDBase/Digit.h +++ b/Detectors/TRD/base/include/TRDBase/Digit.h @@ -19,6 +19,7 @@ #include "CommonDataFormat/TimeStamp.h" #include "TRDBase/TRDCommonParam.h" +#include "DataFormatsTRD/Constants.h" namespace o2 { @@ -26,7 +27,7 @@ namespace trd { using ADC_t = std::uint16_t; -using ArrayADC = std::array<ADC_t, kTimeBins>; +using ArrayADC = std::array<ADC_t, constants::TIMEBINS>; using TimeStamp = o2::dataformats::TimeStamp<double>; diff --git a/Detectors/TRD/base/include/TRDBase/FeeParam.h b/Detectors/TRD/base/include/TRDBase/FeeParam.h index f514f0cf6f6c2..1088a751b4db4 100644 --- a/Detectors/TRD/base/include/TRDBase/FeeParam.h +++ b/Detectors/TRD/base/include/TRDBase/FeeParam.h @@ -26,6 +26,8 @@ // // //////////////////////////////////////////////////////////////////////////// +#include "DataFormatsTRD/Constants.h" + #include <array> #include <vector> @@ -67,31 +69,6 @@ class FeeParam static short chipmaskToMCMlist(unsigned int cmA, unsigned int cmB, unsigned short linkpair, int* mcmList, int listSize); static short getRobAB(unsigned short robsel, unsigned short linkpair); // Returns the chamber side (A=0, B=0) of a ROB - // geometry - static float getSamplingFrequency() { return (float)mgkLHCfrequency / 4000000.0; } //TODO put the 40MHz into a static variable somewhere. - static int getNmcmRob() { return mgkNmcmRob; } - static int getNmcmRobInRow() { return mgkNmcmRobInRow; } - static int getNmcmRobInCol() { return mgkNmcmRobInCol; } - static int getNrobC0() { return mgkNrobC0; } - static int getNrobC1() { return mgkNrobC1; } - static int getNadcMcm() { return mgkNadcMcm; } - static int getNcol() { return mgkNcol; } - static int getNcolMcm() { return mgkNcolMcm; } - static int getNrowC0() { return mgkNrowC0; } - static int getNrowC1() { return mgkNrowC1; } - // Basic Geometrical numbers - static const int mgkLHCfrequency = 40079000; // [Hz] LHC clock - static const int mgkNmcmRob = 16; // Number of MCMs per ROB - static const int mgkNmcmRobInRow = 4; // Number of MCMs per ROB in row dir. - static const int mgkNmcmRobInCol = 4; // Number of MCMs per ROB in col dir. - static const int mgkNrobC0 = 6; // Number of ROBs per C0 chamber - static const int mgkNrobC1 = 8; // Number of ROBs per C1 chamber - static const int mgkNadcMcm = 21; // Number of ADC channels per MCM - static const int mgkNcol = 144; // Number of pads per padplane row - static const int mgkNcolMcm = 18; // Number of pads per MCM - static const int mgkNrowC0 = 12; // Number of Rows per C0 chamber - static const int mgkNrowC1 = 16; // Number of Rows per C1 chamber - // tracklet simulation bool getTracklet() const { return mgTracklet; } static void setTracklet(bool trackletSim = true) { mgTracklet = trackletSim; } @@ -174,17 +151,17 @@ class FeeParam static const int mgkMaxRAWversion = 3; // Maximum raw version number supported // geometry constants - static std::array<float, 30> mgZrow; // z-position of pad row edge 6x5 - static std::array<float, 6> mgX; // x-position for all layers - static std::array<float, 6> mgInvX; // inverse x-position for all layers (to remove divisions) - static std::array<float, 6> mgTiltingAngle; // tilting angle for every layer - static std::array<float, 6> mgTiltingAngleTan; // tan of tilting angle for every layer (look up table to avoid tan calculations) - static std::array<float, 6> mgWidthPad; // pad width for all layers - static std::array<float, 6> mgInvWidthPad; // inverse pad width for all layers (to remove divisions) + static std::array<float, constants::NCHAMBERPERSEC> mgZrow; // z-position of pad row edge 6x5 + static std::array<float, constants::NLAYER> mgX; // x-position for all layers + static std::array<float, constants::NLAYER> mgInvX; // inverse x-position for all layers (to remove divisions) + static std::array<float, constants::NLAYER> mgTiltingAngle; // tilting angle for every layer + static std::array<float, constants::NLAYER> mgTiltingAngleTan; // tan of tilting angle for every layer (look up table to avoid tan calculations) + static std::array<float, constants::NLAYER> mgWidthPad; // pad width for all layers + static std::array<float, constants::NLAYER> mgInvWidthPad; // inverse pad width for all layers (to remove divisions) static float mgLengthInnerPadC0; // inner pad length C0 chamber static float mgLengthOuterPadC0; // outer pad length C0 chamber - static std::array<float, 6> mgLengthInnerPadC1; // inner pad length C1 chambers - static std::array<float, 6> mgLengthOuterPadC1; // outer pad length C1 chambers + static std::array<float, constants::NLAYER> mgLengthInnerPadC1; // inner pad length C1 chambers + static std::array<float, constants::NLAYER> mgLengthOuterPadC1; // outer pad length C1 chambers static float mgScalePad; // scaling factor for pad width static float mgDriftLength; // length of the parse gaintbl Krypton_2009-01 drift region static float mgBinDy; // bin in dy (140 um) diff --git a/Detectors/TRD/base/include/TRDBase/PadCalibrations.h b/Detectors/TRD/base/include/TRDBase/PadCalibrations.h index d6391b3c36431..f42e5d524d2ac 100644 --- a/Detectors/TRD/base/include/TRDBase/PadCalibrations.h +++ b/Detectors/TRD/base/include/TRDBase/PadCalibrations.h @@ -22,6 +22,7 @@ #include "TRDBase/PadParameters.h" #include "TRDBase/TRDSimParam.h" +#include "DataFormatsTRD/Constants.h" class TRDGeometry; @@ -46,7 +47,7 @@ class PadCalibrations void reset(int roc, int col, int row, std::vector<T>& data); void init(); protected: - std::array<PadParameters<T>, TRDSimParam::kNdet> mreadOutChamber; + std::array<PadParameters<T>, constants::MAXCHAMBER> mreadOutChamber; }; template <class T> diff --git a/Detectors/TRD/base/include/TRDBase/PadParameters.h b/Detectors/TRD/base/include/TRDBase/PadParameters.h index 4c99bf020d6e6..56168216caf12 100644 --- a/Detectors/TRD/base/include/TRDBase/PadParameters.h +++ b/Detectors/TRD/base/include/TRDBase/PadParameters.h @@ -25,6 +25,7 @@ #include "TRDBase/TRDGeometry.h" #include "TRDBase/TRDSimParam.h" #include "TRDBase/FeeParam.h" +#include "DataFormatsTRD/Constants.h" namespace o2 { @@ -52,12 +53,12 @@ class PadParameters int reset(int chamberindex, int col, int row, std::vector<T>& data); protected: - int mPlane{0}; // Plane number - int mChamber{0}; // Chamber number - int mNrows{0}; // Number of rows - int mNcols{FeeParam::mgkNcol}; // Number of columns - int mNchannels; // Number of channels = rows*columns - std::vector<T> mData; // Size is mNchannels + int mPlane{0}; // Plane number + int mChamber{0}; // Chamber number + int mNrows{0}; // Number of rows + int mNcols{constants::NCOLUMN}; // Number of columns + int mNchannels; // Number of channels = rows*columns + std::vector<T> mData; // Size is mNchannels }; template <class T> @@ -72,9 +73,9 @@ int PadParameters<T>::init(int chamberindex) mPlane = TRDGeometry::getLayer(chamberindex); mChamber = TRDGeometry::getStack(chamberindex); if (mChamber == 2) - mNrows = FeeParam::mgkNrowC0; + mNrows = constants::NROWC0; else - mNrows = FeeParam::mgkNrowC1; + mNrows = constants::NROWC1; // the FeeParam variables need to be unprotected, and dont want to change FeeParam in this PR. mNchannels = mNrows * mNcols; mData.resize(mNchannels); diff --git a/Detectors/TRD/base/include/TRDBase/PadResponse.h b/Detectors/TRD/base/include/TRDBase/PadResponse.h index 30dac688942ab..b655ba847b119 100644 --- a/Detectors/TRD/base/include/TRDBase/PadResponse.h +++ b/Detectors/TRD/base/include/TRDBase/PadResponse.h @@ -12,7 +12,7 @@ #define ALICEO2_TRD_PADRESPONSE_H_ #include <array> -#include "TRDBase/TRDCommonParam.h" // For kNLayer +#include "DataFormatsTRD/Constants.h" namespace o2 { @@ -32,7 +32,7 @@ class PadResponse static constexpr float mPRFhi{1.5}; // Higher boundary of the PRF float mPRFwid; // Bin width of the sampled PRF int mPRFpad; // Distance to next pad in PRF - std::array<float, kNlayer * mPRFbin> mPRFsmp{}; // Sampled pad response + std::array<float, constants::NLAYER * mPRFbin> mPRFsmp{}; // Sampled pad response }; } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/TRDCalPadStatus.h b/Detectors/TRD/base/include/TRDBase/TRDCalPadStatus.h index a5edb6f325c59..a3307b36b72d6 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDCalPadStatus.h +++ b/Detectors/TRD/base/include/TRDBase/TRDCalPadStatus.h @@ -11,6 +11,8 @@ #ifndef O2_TRDCALPADSTATUS_H #define O2_TRDCALPADSTATUS_H +#include "DataFormatsTRD/Constants.h" + #include "TH1F.h" #include "TH2F.h" #include <string> @@ -32,10 +34,6 @@ class TRDCalPadStatus { public: - enum { kNplan = 6, - kNcham = 5, - kNsect = 18, - kNdet = 540 }; enum { kMasked = 2, kPadBridgedLeft = 4, kPadBridgedRight = 8, @@ -86,7 +84,7 @@ class TRDCalPadStatus void setName(const std::string newName) { mName = newName; }; protected: - TRDCalSingleChamberStatus* mROC[kNdet]; // Array of ROC objects which contain the values per pad + TRDCalSingleChamberStatus* mROC[constants::MAXCHAMBER]; // Array of ROC objects which contain the values per pad private: std::string mName; diff --git a/Detectors/TRD/base/include/TRDBase/TRDCommonParam.h b/Detectors/TRD/base/include/TRDBase/TRDCommonParam.h index 173a7eeac151b..a3a957347c26b 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDCommonParam.h +++ b/Detectors/TRD/base/include/TRDBase/TRDCommonParam.h @@ -19,8 +19,6 @@ namespace trd { class TRDPadPlane; -constexpr int kNlayer = 6, kNstack = 5, kNsector = 18, kNdet = 540; -constexpr int kTimeBins = 30; class TRDCommonParam { diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h b/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h index e26333d245ce9..87e54b6802160 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h +++ b/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h @@ -13,6 +13,7 @@ #include "GPUCommonDef.h" #include "TRDBase/TRDCommonParam.h" +#include "DataFormatsTRD/Constants.h" #include "TRDBase/TRDPadPlane.h" namespace o2 @@ -39,11 +40,11 @@ class TRDGeometryBase } } GPUd() bool getSMstatus(int sm) const { return (mSMStatus & (0x1 << sm)) != 0; } - GPUd() static int getDetectorSec(int det) { return (det % (kNlayer * kNstack)); } - GPUd() static int getDetectorSec(int layer, int stack) { return (layer + stack * kNlayer); } - GPUd() static int getDetector(int layer, int stack, int sector) { return (layer + stack * kNlayer + sector * kNlayer * kNstack); } - GPUd() static int getLayer(int det) { return (det % kNlayer); } - GPUd() static int getStack(int det) { return ((det % (kNlayer * kNstack)) / kNlayer); } + GPUd() static int getDetectorSec(int det) { return (det % (constants::NLAYER * constants::NSTACK)); } + GPUd() static int getDetectorSec(int layer, int stack) { return (layer + stack * constants::NLAYER); } + GPUd() static int getDetector(int layer, int stack, int sector) { return (layer + stack * constants::NLAYER + sector * constants::NLAYER * constants::NSTACK); } + GPUd() static int getLayer(int det) { return (det % constants::NLAYER); } + GPUd() static int getStack(int det) { return ((det % (constants::NLAYER * constants::NSTACK)) / constants::NLAYER); } GPUd() int getStack(float z, int layer) const; GPUd() const TRDPadPlane* getPadPlane(int layer, int stack) const { return &mPadPlanes[getDetectorSec(layer, stack)]; } @@ -59,13 +60,13 @@ class TRDGeometryBase GPUd() float getRow0(int layer, int stack) { return mPadPlanes[getDetectorSec(layer, stack)].getRow0(); } GPUd() float getRowEnd(int layer, int stack) { return mPadPlanes[getDetectorSec(layer, stack)].getRowEnd(); } - static constexpr int getSector(int det) { return (det / (kNlayer * kNstack)); } + static constexpr int getSector(int det) { return (det / (constants::NLAYER * constants::NSTACK)); } static constexpr float getTime0(int layer) { return TIME0[layer]; } static constexpr float getXtrdBeg() { return XTRDBEG; } static constexpr float getXtrdEnd() { return XTRDEND; } static constexpr float getChamberWidth(int layer) { return CWIDTH[layer]; } static constexpr float getChamberLength(int layer, int stack) { return CLENGTH[layer][stack]; } - static constexpr float getAlpha() { return 2.0 * 3.14159265358979324 / kNsector; } + static constexpr float getAlpha() { return 2.0 * 3.14159265358979324 / constants::NSECTOR; } static constexpr float cheight() { return CH; } static constexpr float cheightSV() { return CHSV; } static constexpr float cspace() { return VSPACE; } @@ -199,11 +200,11 @@ class TRDGeometryBase static constexpr float XTRDEND = 366.33; ///< X-coordinate in tracking system of end of TRD mother volume // The outer width of the chambers - static constexpr float CWIDTH[kNlayer] = {90.4, 94.8, 99.3, 103.7, 108.1, 112.6}; + static constexpr float CWIDTH[constants::NLAYER] = {90.4, 94.8, 99.3, 103.7, 108.1, 112.6}; // The outer lengths of the chambers // Includes the spacings between the chambers! - static constexpr float CLENGTH[kNlayer][kNstack] = { + static constexpr float CLENGTH[constants::NLAYER][constants::NSTACK] = { {124.0, 124.0, 110.0, 124.0, 124.0}, {124.0, 124.0, 110.0, 124.0, 124.0}, {131.0, 131.0, 110.0, 131.0, 131.0}, @@ -211,7 +212,7 @@ class TRDGeometryBase {145.0, 145.0, 110.0, 145.0, 145.0}, {147.0, 147.0, 110.0, 147.0, 147.0}}; - TRDPadPlane mPadPlanes[kNlayer * kNstack]; + TRDPadPlane mPadPlanes[constants::NLAYER * constants::NSTACK]; int mSMStatus = 0x3ffff; diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h index 3cf643d84b6df..01597c854c6b9 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h +++ b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h @@ -19,6 +19,7 @@ #include "GPUCommonTransform3D.h" #include "TRDBase/TRDGeometryBase.h" #include "TRDBase/TRDPadPlane.h" +#include "DataFormatsTRD/Constants.h" using namespace o2::trd; @@ -58,7 +59,7 @@ class TRDGeometryFlat : public o2::gpu::FlatObject, public TRDGeometryBase private: o2::gpu::Transform3D mMatrixCache[MAXMATRICES]; - short mMatrixIndirection[kNdet]; + short mMatrixIndirection[constants::MAXCHAMBER]; }; } // namespace trd diff --git a/Detectors/TRD/base/include/TRDBase/TRDSimParam.h b/Detectors/TRD/base/include/TRDBase/TRDSimParam.h index 8e555527f0380..3440682c7078a 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDSimParam.h +++ b/Detectors/TRD/base/include/TRDBase/TRDSimParam.h @@ -26,11 +26,8 @@ namespace trd class TRDSimParam { public: - enum { kNplan = 6, - kNcham = 5, - kNsect = 18, - kNdet = 540, - kNPadsInPadResponse = 3 // Number of pads included in the pad response + enum { + kNPadsInPadResponse = 3 // Number of pads included in the pad response }; static TRDSimParam* Instance(); diff --git a/Detectors/TRD/base/src/CalDet.cxx b/Detectors/TRD/base/src/CalDet.cxx index b429399eaccc4..bb0ffc10f85d6 100644 --- a/Detectors/TRD/base/src/CalDet.cxx +++ b/Detectors/TRD/base/src/CalDet.cxx @@ -26,6 +26,7 @@ // #include "AliMathBase.h" using namespace o2::trd; +using namespace o2::trd::constants; //___________________________________________________________________________________ double CalDet::getMean(CalDet* const outlierDet) const @@ -35,11 +36,11 @@ double CalDet::getMean(CalDet* const outlierDet) const // if (!outlierDet) { - return TMath::Mean(kNdet, mData.data()); + return TMath::Mean(MAXCHAMBER, mData.data()); } - std::array<double, kNdet> ddata; + std::array<double, MAXCHAMBER> ddata; int nPoints = 0; - for (int i = 0; i < kNdet; i++) { + for (int i = 0; i < MAXCHAMBER; i++) { if (!(outlierDet->getValue(i))) { ddata[nPoints] = mData[nPoints]; nPoints++; @@ -56,11 +57,11 @@ double CalDet::getMedian(CalDet* const outlierDet) const // if (!outlierDet) { - return (double)TMath::Median(kNdet, mData.data()); + return (double)TMath::Median(MAXCHAMBER, mData.data()); } - std::array<double, kNdet> ddata; + std::array<double, MAXCHAMBER> ddata; int nPoints = 0; - for (int i = 0; i < kNdet; i++) { + for (int i = 0; i < MAXCHAMBER; i++) { if (!(outlierDet->getValue(i))) { ddata[nPoints] = mData[nPoints]; nPoints++; @@ -77,11 +78,11 @@ double CalDet::getRMS(CalDet* const outlierDet) const // if (!outlierDet) { - return TMath::RMS(kNdet, mData.data()); + return TMath::RMS(MAXCHAMBER, mData.data()); } - std::array<double, kNdet> ddata; + std::array<double, MAXCHAMBER> ddata; int nPoints = 0; - for (int i = 0; i < kNdet; i++) { + for (int i = 0; i < MAXCHAMBER; i++) { if (!(outlierDet->getValue(i))) { ddata[nPoints] = mData[nPoints]; nPoints++; @@ -98,26 +99,26 @@ double CalDet::getRMSRobust(double robust) const // // sorted - std::array<int, kNdet> index; - TMath::Sort((int)kNdet, mData.data(), index.data()); + std::array<int, MAXCHAMBER> index; + TMath::Sort((int)MAXCHAMBER, mData.data(), index.data()); // reject - double reject = (int)(kNdet * (1 - robust) / 2.0); + double reject = (int)(MAXCHAMBER * (1 - robust) / 2.0); if (reject <= 0) { reject = 0; } - if (reject >= kNdet) { + if (reject >= MAXCHAMBER) { reject = 0; } - std::array<double, kNdet> ddata; + std::array<double, MAXCHAMBER> ddata; int nPoints = 0; - for (int i = 0; i < kNdet; i++) { + for (int i = 0; i < MAXCHAMBER; i++) { bool rej = kFALSE; for (int k = 0; k < reject; k++) { if (i == index[k]) rej = kTRUE; - if (i == index[kNdet - (k + 1)]) + if (i == index[MAXCHAMBER - (k + 1)]) rej = kTRUE; } if (!rej) { @@ -136,24 +137,24 @@ double CalDet::getMeanRobust(double robust) const // // sorted - std::array<int, kNdet> index; - TMath::Sort((int)kNdet, mData.data(), index.data()); + std::array<int, MAXCHAMBER> index; + TMath::Sort((int)MAXCHAMBER, mData.data(), index.data()); // reject - double reject = (int)(kNdet * (1 - robust) / 2.0); + double reject = (int)(MAXCHAMBER * (1 - robust) / 2.0); if (reject <= 0) reject = 0; - if (reject >= kNdet) + if (reject >= MAXCHAMBER) reject = 0; - std::array<double, kNdet> ddata; + std::array<double, MAXCHAMBER> ddata; int nPoints = 0; - for (int i = 0; i < kNdet; i++) { + for (int i = 0; i < MAXCHAMBER; i++) { bool rej = kFALSE; for (int k = 0; k < reject; k++) { if (i == index[k]) rej = kTRUE; - if (i == index[kNdet - (k + 1)]) + if (i == index[MAXCHAMBER - (k + 1)]) rej = kTRUE; } if (!rej) { @@ -171,10 +172,10 @@ double CalDet::getLTM(double* sigma, double fraction, CalDet* const outlierDet) // Calculate LTM mean and sigma // - std::array<double, kNdet> ddata; + std::array<double, MAXCHAMBER> ddata; double mean = 0, lsigma = 0; unsigned int nPoints = 0; - for (int i = 0; i < kNdet; i++) { + for (int i = 0; i < MAXCHAMBER; i++) { if (!outlierDet || !(outlierDet->getValue(i))) { ddata[nPoints] = mData[nPoints]; nPoints++; @@ -232,7 +233,7 @@ TH1F* CalDet::makeHisto1Distribution(float min, float max, int type) title << mTitle.c_str() << " CalDet 1Distribution"; std::string titlestr = title.str(); TH1F* his = new TH1F(mName.c_str(), titlestr.c_str(), 100, min, max); - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { his->Fill(getValue(idet)); } return his; @@ -276,8 +277,8 @@ TH1F* CalDet::makeHisto1DAsFunctionOfDet(float min, float max, int type) std::stringstream title; title << mTitle.c_str() << " CalDet as function of det"; std::string titlestr = title.str(); - TH1F* his = new TH1F(mName.c_str(), titlestr.c_str(), kNdet, 0, kNdet); - for (int det = 0; det < kNdet; det++) { + TH1F* his = new TH1F(mName.c_str(), titlestr.c_str(), MAXCHAMBER, 0, MAXCHAMBER); + for (int det = 0; det < MAXCHAMBER; det++) { his->Fill(det + 0.5, getValue(det)); } his->SetMaximum(max); @@ -334,8 +335,8 @@ TH2F* CalDet::makeHisto2DCh(int ch, float min, float max, int type) // Where we begin int offsetch = 6 * ch; - for (int isec = 0; isec < kNsect; isec++) { - for (int ipl = 0; ipl < kNplan; ipl++) { + for (int isec = 0; isec < NSECTOR; isec++) { + for (int ipl = 0; ipl < NLAYER; ipl++) { int det = offsetch + isec * 30 + ipl; const TRDPadPlane* padPlane = trdGeo->getPadPlane(ipl, ch); for (int icol = 0; icol < padPlane->getNcols(); icol++) { @@ -406,9 +407,9 @@ TH2F* CalDet::makeHisto2DSmPl(int sm, int pl, float min, float max, int type) // Where we begin int offsetsmpl = 30 * sm + pl; - for (int k = 0; k < kNcham; k++) { + for (int k = 0; k < NSTACK; k++) { int det = offsetsmpl + k * 6; - int kb = kNcham - 1 - k; + int kb = NSTACK - 1 - k; his->SetBinContent(kb + 1, 2, mData[det]); his->SetBinContent(kb + 1, 3, mData[det]); } @@ -427,7 +428,7 @@ void CalDet::add(float c1) // Add constant for all detectors // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { mData[idet] += c1; } } @@ -439,7 +440,7 @@ void CalDet::multiply(float c1) // multiply constant for all detectors // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { mData[idet] *= c1; } } @@ -451,7 +452,7 @@ void CalDet::add(const CalDet* calDet, double c1) // add caldet channel by channel multiplied by c1 // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { mData[idet] += calDet->getValue(idet) * c1; } } @@ -463,7 +464,7 @@ void CalDet::multiply(const CalDet* calDet) // multiply caldet channel by channel // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { mData[idet] *= calDet->getValue(idet); } } @@ -476,7 +477,7 @@ void CalDet::divide(const CalDet* calDet) // float eps = 0.00000000000000001; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (TMath::Abs(calDet->getValue(idet)) > eps) { mData[idet] /= calDet->getValue(idet); } diff --git a/Detectors/TRD/base/src/CalOnlineGainTables.cxx b/Detectors/TRD/base/src/CalOnlineGainTables.cxx index 3e5311c6b24a2..4d01a770608ba 100644 --- a/Detectors/TRD/base/src/CalOnlineGainTables.cxx +++ b/Detectors/TRD/base/src/CalOnlineGainTables.cxx @@ -18,8 +18,10 @@ #include "TRDBase/CalOnlineGainTables.h" #include "TRDBase/TRDGeometry.h" #include "TRDBase/FeeParam.h" +#include "DataFormatsTRD/Constants.h" using namespace o2::trd; +using namespace o2::trd::constants; using namespace std; float o2::trd::CalOnlineGainTables::UnDef = -999.0; @@ -30,7 +32,7 @@ int CalOnlineGainTables::getArrayOffset(int det, int row, int col) const int rob = mFeeParam->getROBfromPad(row, col); int mcm = mFeeParam->getMCMfromPad(row, col); int detoffset = det * 128; //TODO find this constant from somewhere else max rob=8, max mcm=16, so 7x16+15=127 - int mcmoffset = rob * (mFeeParam->mgkNmcmRob) + mcm; + int mcmoffset = rob * NMCMROB + mcm; return detoffset + mcmoffset; } @@ -41,7 +43,7 @@ int CalOnlineGainTables::getChannel(int col) const int CalOnlineGainTables::getArrayOffsetrm(int det, int rob, int mcm) const { - return det * 128 + rob * FeeParam::instance()->mgkNmcmRob + mcm; + return det * 128 + rob * NMCMROB + mcm; } float CalOnlineGainTables::getGainCorrectionFactor(int det, int row, int col) const diff --git a/Detectors/TRD/base/src/CalPad.cxx b/Detectors/TRD/base/src/CalPad.cxx index f27dfd8efaf5d..acee7e291ca6d 100644 --- a/Detectors/TRD/base/src/CalPad.cxx +++ b/Detectors/TRD/base/src/CalPad.cxx @@ -21,6 +21,7 @@ #include "CalDet.h" using namespace o2::trd; +using namespace o2::trd::constants; /////////////////////////////////////////////////////////////////////////////// // // @@ -35,7 +36,7 @@ CalPad::CalPad() // CalPad default constructor // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { fROC[idet] = nullptr; } } @@ -47,9 +48,9 @@ CalPad::CalPad(const Text_t* name, const Text_t* title) // CalPad constructor // - for (int isec = 0; isec < kNsect; isec++) { - for (int ipla = 0; ipla < kNplan; ipla++) { - for (int icha = 0; icha < kNcham; icha++) { + for (int isec = 0; isec < NSECTOR; isec++) { + for (int ipla = 0; ipla < NLAYER; ipla++) { + for (int icha = 0; icha < NSTACK; icha++) { int idet = getDet(ipla, icha, isec); fROC[idet] = new CalROC(ipla, icha); } @@ -66,7 +67,7 @@ CalPad::CalPad(const CalPad& c) // CalPad copy constructor // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { fROC[idet] = new CalROC(*((CalPad&)c).fROC[idet]); } mName = c.mName; @@ -80,7 +81,7 @@ CalPad::~CalPad() // CalPad destructor // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (fROC[idet]) { delete fROC[idet]; fROC[idet] = 0; @@ -107,7 +108,7 @@ void CalPad::Copy(TObject& c) const // Copy function // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (((CalPad&)c).fROC[idet]) { delete ((CalPad&)c).fROC[idet]; } @@ -133,7 +134,7 @@ bool CalPad::scaleROCs(const CalDet* values) if (!values) return kFALSE; bool result = kTRUE; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (fROC[idet]) { if (!fROC[idet]->multiply(values->getValue(idet))) result = kFALSE; @@ -172,7 +173,7 @@ double CalPad::getMeanRMS(double& rms, const CalDet* calDet, int type) if (type == 0) factor = 1.0; double sum = 0, sum2 = 0, n = 0, val; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet) factor = calDet->getValue(idet); CalROC* calRoc = fROC[idet]; @@ -208,9 +209,9 @@ double CalPad::getMean(const CalDet* calDet, int type, CalPad* const outlierPad) double factor = 0.0; if (type == 0) factor = 1.0; - double arr[kNdet]; + double arr[MAXCHAMBER]; int n = 0; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet) factor = calDet->getValue(idet); CalROC* calRoc = fROC[idet]; @@ -240,9 +241,9 @@ double CalPad::getRMS(const CalDet* calDet, int type, CalPad* const outlierPad) double factor = 0.0; if (type == 0) factor = 1.0; - double arr[kNdet]; + double arr[MAXCHAMBER]; int n = 0; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet) factor = calDet->getValue(idet); CalROC* calRoc = fROC[idet]; @@ -272,9 +273,9 @@ double CalPad::getMedian(const CalDet* calDet, int type, CalPad* const outlierPa double factor = 0.0; if (type == 0) factor = 1.0; - double arr[kNdet]; + double arr[MAXCHAMBER]; int n = 0; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet) factor = calDet->getValue(idet); CalROC* calRoc = fROC[idet]; @@ -304,12 +305,12 @@ double CalPad::getLTM(double* sigma, double fraction, const CalDet* calDet, int double factor = 0.0; if (type == 0) factor = 1.0; - double arrm[kNdet]; - double arrs[kNdet]; + double arrm[MAXCHAMBER]; + double arrs[MAXCHAMBER]; double* sTemp = 0x0; int n = 0; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet) factor = calDet->getValue(idet); CalROC* calRoc = fROC[idet]; @@ -390,7 +391,7 @@ TH1F* CalPad::makeHisto1D(const CalDet* calDet, int typedet, float min, float ma char name[1000]; snprintf(name, 1000, "%s Pad 1D", getTitle()); TH1F* his = new TH1F(name, name, 100, min, max); - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet) factor = calDet->getValue(idet); if (fROC[idet]) { @@ -478,7 +479,7 @@ TH2F* CalPad::makeHisto2DSmPl(int sm, int pl, const CalDet* calDet, int typedet, // Where we begin int offsetsmpl = 30 * sm + pl; - for (int k = 0; k < kNcham; k++) { + for (int k = 0; k < NSTACK; k++) { int det = offsetsmpl + k * 6; if (calDet) factor = calDet->getValue(det); @@ -488,7 +489,7 @@ TH2F* CalPad::makeHisto2DSmPl(int sm, int pl, const CalDet* calDet, int typedet, for (int icol = 0; icol < calRoc->getNcols(); icol++) { if (TMath::Abs(calRoc->getValue(icol, irow)) > kEpsilon) { int binz = 0; - int kb = kNcham - 1 - k; + int kb = NSTACK - 1 - k; int krow = calRoc->getNrows() - 1 - irow; int kcol = calRoc->getNcols() - 1 - icol; if (kb > 2) @@ -584,8 +585,8 @@ TH2F* CalPad::makeHisto2DCh(int ch, const CalDet* calDet, int typedet, float min // Where we begin int offsetch = 6 * ch; - for (int isec = 0; isec < kNsect; isec++) { - for (int ipl = 0; ipl < kNplan; ipl++) { + for (int isec = 0; isec < NSECTOR; isec++) { + for (int ipl = 0; ipl < NLAYER; ipl++) { int det = offsetch + isec * 30 + ipl; if (calDet) factor = calDet->getValue(det); @@ -635,7 +636,7 @@ bool CalPad::add(float c1) // bool result = kTRUE; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (fROC[idet]) { if (!fROC[idet]->add(c1)) result = kFALSE; @@ -651,7 +652,7 @@ bool CalPad::multiply(float c1) // multiply constant for all channels of all ROCs // bool result = kTRUE; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (fROC[idet]) { if (!fROC[idet]->multiply(c1)) result = kFALSE; @@ -680,7 +681,7 @@ bool CalPad::add(const CalPad* pad, double c1, const CalDet* calDet1, const CalD factor2 = 1.0; } bool result = kTRUE; - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet1) factor1 = calDet1->getValue(idet); if (calDet2) @@ -723,7 +724,7 @@ bool CalPad::multiply(const CalPad* pad, const CalDet* calDet1, const CalDet* ca factor1 = 1.0; factor2 = 1.0; } - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet1) factor1 = calDet1->getValue(idet); if (calDet2) @@ -773,7 +774,7 @@ bool CalPad::divide(const CalPad* pad, const CalDet* calDet1, const CalDet* calD factor1 = 1.0; factor2 = 1.0; } - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (calDet1) factor1 = calDet1->getValue(idet); if (calDet2) diff --git a/Detectors/TRD/base/src/FeeParam.cxx b/Detectors/TRD/base/src/FeeParam.cxx index add0a182a0886..4baebf0463062 100644 --- a/Detectors/TRD/base/src/FeeParam.cxx +++ b/Detectors/TRD/base/src/FeeParam.cxx @@ -42,6 +42,7 @@ using namespace std; using namespace o2::trd; +using namespace o2::trd::constants; //_____________________________________________________________________________ @@ -55,24 +56,24 @@ bool FeeParam::mgLUTPadNumberingFilled = false; std::vector<short> FeeParam::mgLUTPadNumbering; // definition of geometry constants -std::array<float, 30> FeeParam::mgZrow = { +std::array<float, NCHAMBERPERSEC> FeeParam::mgZrow = { 301, 177, 53, -57, -181, 301, 177, 53, -57, -181, 315, 184, 53, -57, -188, 329, 191, 53, -57, -195, 343, 198, 53, -57, -202, 347, 200, 53, -57, -204}; -std::array<float, 6> FeeParam::mgX = {300.65, 313.25, 325.85, 338.45, 351.05, 363.65}; -std::array<float, 6> FeeParam::mgTiltingAngle = {-2., 2., -2., 2., -2., 2.}; +std::array<float, NLAYER> FeeParam::mgX = {300.65, 313.25, 325.85, 338.45, 351.05, 363.65}; +std::array<float, NLAYER> FeeParam::mgTiltingAngle = {-2., 2., -2., 2., -2., 2.}; int FeeParam::mgDyMax = 63; int FeeParam::mgDyMin = -64; float FeeParam::mgBinDy = 140e-4; -std::array<float, 6> FeeParam::mgWidthPad = {0.635, 0.665, 0.695, 0.725, 0.755, 0.785}; -std::array<float, 6> FeeParam::mgLengthInnerPadC1 = {7.5, 7.5, 8.0, 8.5, 9.0, 9.0}; -std::array<float, 6> FeeParam::mgLengthOuterPadC1 = {7.5, 7.5, 7.5, 7.5, 7.5, 8.5}; -std::array<float, 6> FeeParam::mgInvX; -std::array<float, 6> FeeParam::mgTiltingAngleTan; -std::array<float, 6> FeeParam::mgInvWidthPad; +std::array<float, NLAYER> FeeParam::mgWidthPad = {0.635, 0.665, 0.695, 0.725, 0.755, 0.785}; +std::array<float, NLAYER> FeeParam::mgLengthInnerPadC1 = {7.5, 7.5, 8.0, 8.5, 9.0, 9.0}; +std::array<float, NLAYER> FeeParam::mgLengthOuterPadC1 = {7.5, 7.5, 7.5, 7.5, 7.5, 8.5}; +std::array<float, NLAYER> FeeParam::mgInvX; +std::array<float, NLAYER> FeeParam::mgTiltingAngleTan; +std::array<float, NLAYER> FeeParam::mgInvWidthPad; float FeeParam::mgLengthInnerPadC0 = 9.0; float FeeParam::mgLengthOuterPadC0 = 8.0; @@ -196,7 +197,7 @@ int FeeParam::getPadRowFromMCM(int irob, int imcm) const // Return on which pad row this mcm sits // - return mgkNmcmRobInRow * (irob / 2) + imcm / mgkNmcmRobInCol; + return NMCMROBINROW * (irob / 2) + imcm / NMCMROBINCOL; } //_____________________________________________________________________________ @@ -215,11 +216,11 @@ int FeeParam::getPadColFromADC(int irob, int imcm, int iadc) const // http://wiki.kip.uni-heidelberg.de/ti/TRD/index.php/Image:ROB_MCM_numbering.pdf // - if (iadc < 0 || iadc > mgkNadcMcm) + if (iadc < 0 || iadc > NADCMCM) return -100; - int mcmcol = imcm % mgkNmcmRobInCol + getRobSide(irob) * mgkNmcmRobInCol; // MCM column number on ROC [0..7] - int padcol = mcmcol * mgkNcolMcm + mgkNcolMcm + 1 - iadc; - if (padcol < 0 || padcol >= mgkNcol) { + int mcmcol = imcm % NMCMROBINCOL + getRobSide(irob) * NMCMROBINCOL; // MCM column number on ROC [0..7] + int padcol = mcmcol * NCOLMCM + NCOLMCM + 1 - iadc; + if (padcol < 0 || padcol >= NCOLUMN) { return -1; // this is commented because of reason above OK } return padcol; @@ -234,10 +235,10 @@ int FeeParam::getExtendedPadColFromADC(int irob, int imcm, int iadc) const // so we have to introduce new virtual pad numbering scheme for this purpose. // - if (iadc < 0 || iadc > mgkNadcMcm) + if (iadc < 0 || iadc > NADCMCM) return -100; - int mcmcol = imcm % mgkNmcmRobInCol + getRobSide(irob) * mgkNmcmRobInCol; // MCM column number on ROC [0..7] - int padcol = mcmcol * mgkNadcMcm + mgkNcolMcm + 2 - iadc; + int mcmcol = imcm % NMCMROBINCOL + getRobSide(irob) * NMCMROBINCOL; // MCM column number on ROC [0..7] + int padcol = mcmcol * NADCMCM + NCOLMCM + 2 - iadc; return padcol; } @@ -250,9 +251,9 @@ int FeeParam::getMCMfromPad(int irow, int icol) const // Return -1 for error. // - if (irow < 0 || icol < 0 || irow > mgkNrowC1 || icol > mgkNcol) + if (irow < 0 || icol < 0 || irow > NROWC1 || icol > NCOLUMN) return -1; - return (icol % (mgkNcol / 2)) / mgkNcolMcm + mgkNmcmRobInCol * (irow % mgkNmcmRobInRow); + return (icol % (NCOLUMN / 2)) / NCOLMCM + NMCMROBINCOL * (irow % NMCMROBINROW); } //_____________________________________________________________________________ @@ -263,7 +264,7 @@ int FeeParam::getMCMfromSharedPad(int irow, int icol) const // Return -1 for error. // - if (irow < 0 || icol < 0 || irow > mgkNrowC1 || icol > mgkNcol + 8 * 3) + if (irow < 0 || icol < 0 || irow > NROWC1 || icol > NCOLUMN + 8 * 3) return -1; int adc = 20 - (icol % 18) - 1; @@ -282,7 +283,7 @@ int FeeParam::getMCMfromSharedPad(int irow, int icol) const break; } - return (icol % (mgkNcol / 2)) / mgkNcolMcm + mgkNmcmRobInCol * (irow % mgkNmcmRobInRow); + return (icol % (NCOLUMN / 2)) / NCOLMCM + NMCMROBINCOL * (irow % NMCMROBINROW); } //_____________________________________________________________________________ @@ -291,7 +292,7 @@ int FeeParam::getROBfromPad(int irow, int icol) const // // Return on which rob this pad is // - return (int)((int)irow / (int)mgkNmcmRobInRow) * 2 + getColSide(icol); + return (irow / NMCMROBINROW) * 2 + getColSide(icol); } //_____________________________________________________________________________ @@ -302,9 +303,9 @@ int FeeParam::getROBfromSharedPad(int irow, int icol) const // if (icol < 72) { - return (irow / mgkNmcmRobInRow) * 2 + getColSide(icol + 5); + return (irow / NMCMROBINROW) * 2 + getColSide(icol + 5); } else { - return (irow / mgkNmcmRobInRow) * 2 + getColSide(icol - 5); + return (irow / NMCMROBINROW) * 2 + getColSide(icol - 5); } } @@ -315,7 +316,7 @@ int FeeParam::getRobSide(int irob) const // Return on which side this rob sits (A side = 0, B side = 1) // - if (irob < 0 || irob >= mgkNrobC1) + if (irob < 0 || irob >= NROBC1) return -1; return irob % 2; @@ -328,10 +329,10 @@ int FeeParam::getColSide(int icol) const // Return on which side this column sits (A side = 0, B side = 1) // - if (icol < 0 || icol >= mgkNcol) + if (icol < 0 || icol >= NCOLUMN) return -1; - return icol / (mgkNcol / 2); + return icol / (NCOLUMN / 2); } unsigned int FeeParam::aliToExtAli(int rob, int aliid) @@ -491,7 +492,7 @@ void FeeParam::setRAWversion(int rawver) } } -/* +/* * This was originally moved here from arrayADC, signalADC etc. We now longer use those classes * so removing this for now as its crashing. */ @@ -504,9 +505,9 @@ void FeeParam::createPad2MCMLookUpTable() // if (!mgLUTPadNumberingFilled) { - LOG(debug) << " resizing lookup array to : " << getNcol() << " elements previously : " << mgLUTPadNumbering.size(); - mgLUTPadNumbering.resize(FeeParam::getNcol()); - memset(&mgLUTPadNumbering[0], 0, sizeof(mgLUTPadNumbering[0]) * getNcol()); + LOG(debug) << " resizing lookup array to : " << NCOLUMN << " elements previously : " << mgLUTPadNumbering.size(); + mgLUTPadNumbering.resize(NCOLUMN); + memset(&mgLUTPadNumbering[0], 0, sizeof(mgLUTPadNumbering[0]) * NCOLUMN); for (int mcm = 0; mcm < 8; mcm++) { int lowerlimit = 0 + mcm * 18; int upperlimit = 18 + mcm * 18; @@ -524,7 +525,7 @@ int FeeParam::getDyCorrection(int det, int rob, int mcm) const // calculate the correction of the deflection // i.e. Lorentz angle and tilt correction (if active) - int layer = det % 6; + int layer = det % NLAYER; float dyTilt = (mgDriftLength * std::tan(mgTiltingAngle[layer] * M_PI / 180.) * getLocalZ(det, rob, mcm) * mgInvX[layer]); @@ -598,7 +599,7 @@ float FeeParam::getElongation(int det, int rob, int mcm, int ch) const // calculate the ratio of the distance to the primary vertex and the // distance in x-direction for the given ADC channel - int layer = det % 6; + int layer = det % NLAYER; float elongation = std::abs(getDist(det, rob, mcm, ch) * mgInvX[layer]); @@ -638,7 +639,7 @@ float FeeParam::getX(int det, int /* rob */, int /* mcm */) const { // return the distance to the beam axis in x-direction - int layer = det % 6; + int layer = det % NLAYER; return mgX[layer]; } @@ -646,7 +647,7 @@ float FeeParam::getLocalY(int det, int rob, int mcm, int ch) const { // get local y-position (r-phi) w.r.t. the chamber centre - int layer = det % 6; + int layer = det % NLAYER; // calculate the pad position as in the TRAP float ypos = (-4 + 1 + (rob & 0x1) * 4 + (mcm & 0x3)) * 18 - ch - 0.5; // y position in bins of pad widths return ypos * mgWidthPad[layer]; @@ -656,24 +657,24 @@ float FeeParam::getLocalZ(int det, int rob, int mcm) const { // get local z-position w.r.t. to the chamber boundary - int stack = (det % 30) / 6; - int layer = det % 6; + int stack = (det % NCHAMBERPERSEC) / NLAYER; + int layer = det % NLAYER; int row = (rob / 2) * 4 + mcm / 4; if (stack == 2) { if (row == 0) - return (mgZrow[layer * 6 + stack] - 0.5 * mgLengthOuterPadC0); + return (mgZrow[layer * NLAYER + stack] - 0.5 * mgLengthOuterPadC0); else if (row == 11) - return (mgZrow[layer * 6 + stack] - 1.5 * mgLengthOuterPadC0 - (row - 1) * mgLengthInnerPadC0); + return (mgZrow[layer * NLAYER + stack] - 1.5 * mgLengthOuterPadC0 - (row - 1) * mgLengthInnerPadC0); else - return (mgZrow[layer * 6 + stack] - mgLengthOuterPadC0 - (row - 0.5) * mgLengthInnerPadC0); + return (mgZrow[layer * NLAYER + stack] - mgLengthOuterPadC0 - (row - 0.5) * mgLengthInnerPadC0); } else { if (row == 0) - return (mgZrow[layer * 6 + stack] - 0.5 * mgLengthOuterPadC1[layer]); + return (mgZrow[layer * NLAYER + stack] - 0.5 * mgLengthOuterPadC1[layer]); else if (row == 15) - return (mgZrow[layer * 6 + stack] - 1.5 * mgLengthOuterPadC1[layer] - (row - 1) * mgLengthInnerPadC1[layer]); + return (mgZrow[layer * NLAYER + stack] - 1.5 * mgLengthOuterPadC1[layer] - (row - 1) * mgLengthInnerPadC1[layer]); else - return (mgZrow[layer * 6 + stack] - mgLengthOuterPadC1[layer] - (row - 0.5) * mgLengthInnerPadC1[layer]); + return (mgZrow[layer * NLAYER + stack] - mgLengthOuterPadC1[layer] - (row - 0.5) * mgLengthInnerPadC1[layer]); } } diff --git a/Detectors/TRD/base/src/PadResponse.cxx b/Detectors/TRD/base/src/PadResponse.cxx index ce533a1d8a7df..070b007f416d3 100644 --- a/Detectors/TRD/base/src/PadResponse.cxx +++ b/Detectors/TRD/base/src/PadResponse.cxx @@ -11,6 +11,7 @@ #include "TRDBase/PadResponse.h" using namespace o2::trd; +using namespace o2::trd::constants; void PadResponse::samplePRF() { @@ -19,7 +20,7 @@ void PadResponse::samplePRF() // constexpr int kPRFbin = 61; // arbitraty value - need documentation/ref. - constexpr float prf[kNlayer][kPRFbin] = { + constexpr float prf[NLAYER][kPRFbin] = { {2.9037e-02, 3.3608e-02, 3.9020e-02, 4.5292e-02, 5.2694e-02, 6.1362e-02, 7.1461e-02, 8.3362e-02, 9.7063e-02, 1.1307e-01, 1.3140e-01, 1.5235e-01, @@ -132,7 +133,7 @@ void PadResponse::samplePRF() int ipos2; float diff; - for (int iLayer = 0; iLayer < kNlayer; ++iLayer) { + for (int iLayer = 0; iLayer < NLAYER; ++iLayer) { for (int iBin = 0; iBin < mPRFbin; ++iBin) { float bin = (((float)iBin) + 0.5) * mPRFwid + mPRFlo; ipos1 = ipos2 = 0; @@ -171,16 +172,16 @@ int PadResponse::getPRF(double signal, double dist, int layer, double* pad) cons pad[1] = 0; pad[2] = 0; - if ((iBin1 >= 0) && (iBin1 < (mPRFbin * kNlayer))) { + if ((iBin1 >= 0) && (iBin1 < (mPRFbin * NLAYER))) { if (iBin0 >= 0) { pad[0] = signal * mPRFsmp[iBin0]; } pad[1] = signal * mPRFsmp[iBin1]; - if (iBin2 < (mPRFbin * kNlayer)) { + if (iBin2 < (mPRFbin * NLAYER)) { pad[2] = signal * mPRFsmp[iBin2]; } return 1; } else { return 0; } -} \ No newline at end of file +} diff --git a/Detectors/TRD/base/src/TRDCalPadStatus.cxx b/Detectors/TRD/base/src/TRDCalPadStatus.cxx index 6a91bf074a941..f4852f457aea3 100644 --- a/Detectors/TRD/base/src/TRDCalPadStatus.cxx +++ b/Detectors/TRD/base/src/TRDCalPadStatus.cxx @@ -29,6 +29,7 @@ #include "TRDBase/TRDCalPadStatus.h" using namespace o2::trd; +using namespace o2::trd::constants; //_____________________________________________________________________________ TRDCalPadStatus::TRDCalPadStatus() @@ -37,7 +38,7 @@ TRDCalPadStatus::TRDCalPadStatus() // TRDCalPadStatus default constructor // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { mROC[idet] = nullptr; } } @@ -49,9 +50,9 @@ TRDCalPadStatus::TRDCalPadStatus(const Text_t* name, const Text_t* title) // TRDCalPadStatus constructor // //TRDGeometry fgeom; - for (int isec = 0; isec < kNsect; isec++) { - for (int ipla = 0; ipla < kNplan; ipla++) { - for (int icha = 0; icha < kNcham; icha++) { + for (int isec = 0; isec < NSECTOR; isec++) { + for (int ipla = 0; ipla < NLAYER; ipla++) { + for (int icha = 0; icha < NSTACK; icha++) { int idet = o2::trd::TRDGeometry::getDetector(ipla, icha, isec); // int idet = fgeom.getDetector(ipla,icha,isec);//TRDGeometryBase::getDetector(ipla,icha,isec); mROC[idet] = new TRDCalSingleChamberStatus(ipla, icha, 144); @@ -79,7 +80,7 @@ TRDCalPadStatus::~TRDCalPadStatus() // TRDCalPadStatus destructor // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (mROC[idet]) { delete mROC[idet]; mROC[idet] = nullptr; @@ -106,7 +107,7 @@ void TRDCalPadStatus::Copy(TRDCalPadStatus& c) const // Copy function // - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (mROC[idet]) { mROC[idet]->Copy(*((TRDCalPadStatus&)c).mROC[idet]); } @@ -156,7 +157,7 @@ TH1F* TRDCalPadStatus::makeHisto1D() his->GetXaxis()->SetBinLabel(5, "ReadSecond"); his->GetXaxis()->SetBinLabel(6, "NotConnected"); - for (int idet = 0; idet < kNdet; idet++) { + for (int idet = 0; idet < MAXCHAMBER; idet++) { if (mROC[idet]) { for (int ichannel = 0; ichannel < mROC[idet]->getNchannels(); ichannel++) { int status = (int)mROC[idet]->getStatus(ichannel); @@ -198,14 +199,14 @@ TH2F* TRDCalPadStatus::makeHisto2DSmPl(int sm, int pl) // Where we begin int offsetsmpl = 30 * sm + pl; - for (int k = 0; k < kNcham; k++) { + for (int k = 0; k < NSTACK; k++) { int det = offsetsmpl + k * 6; if (mROC[det]) { TRDCalSingleChamberStatus* calRoc = mROC[det]; for (int icol = 0; icol < calRoc->getNcols(); icol++) { for (int irow = 0; irow < calRoc->getNrows(); irow++) { int binz = 0; - int kb = kNcham - 1 - k; + int kb = NSTACK - 1 - k; int krow = calRoc->getNrows() - 1 - irow; int kcol = calRoc->getNcols() - 1 - icol; if (kb > 2) @@ -220,7 +221,7 @@ TH2F* TRDCalPadStatus::makeHisto2DSmPl(int sm, int pl) for (int icol = 1; icol < 147; icol++) { for (int l = 0; l < 2; l++) { int binz = 0; - int kb = kNcham - 1 - k; + int kb = NSTACK - 1 - k; if (kb > 2) binz = 16 * (kb - 1) + 12 + 1 + 2 * (kb + 1) - (l + 1); else diff --git a/Detectors/TRD/base/src/TRDGeometry.cxx b/Detectors/TRD/base/src/TRDGeometry.cxx index f849b3d188599..560b7a1dfe0eb 100644 --- a/Detectors/TRD/base/src/TRDGeometry.cxx +++ b/Detectors/TRD/base/src/TRDGeometry.cxx @@ -20,6 +20,7 @@ #include "TRDBase/TRDPadPlane.h" using namespace o2::trd; +using namespace o2::trd::constants; //_____________________________________________________________________________ @@ -40,7 +41,7 @@ bool TRDGeometry::rotateBack(int det, const float* const loc, float* glb) const // int sector = getSector(det); - float phi = 2.0 * TMath::Pi() / (float)kNsector * ((float)sector + 0.5); + float phi = 2.0 * TMath::Pi() / (float)NSECTOR * ((float)sector + 0.5); glb[0] = loc[0] * TMath::Cos(phi) - loc[1] * TMath::Sin(phi); glb[1] = loc[0] * TMath::Sin(phi) + loc[1] * TMath::Cos(phi); @@ -56,8 +57,8 @@ void TRDGeometry::createPadPlaneArray() // Creates the array of TRDPadPlane objects // - for (int ilayer = 0; ilayer < kNlayer; ilayer++) { - for (int istack = 0; istack < kNstack; istack++) { + for (int ilayer = 0; ilayer < NLAYER; ilayer++) { + for (int istack = 0; istack < NSTACK; istack++) { createPadPlane(ilayer, istack); } } @@ -371,8 +372,8 @@ void TRDGeometry::createVolumes(std::vector<int> const& idtmed) createVolume("UTF1", "TRD1", idtmed[2], parTrd, kNparTrd); createVolume("UTF2", "TRD1", idtmed[2], parTrd, kNparTrd); - for (int istack = 0; istack < kNstack; istack++) { - for (int ilayer = 0; ilayer < kNlayer; ilayer++) { + for (int istack = 0; istack < NSTACK; istack++) { + for (int ilayer = 0; ilayer < NLAYER; ilayer++) { int iDet = getDetectorSec(ilayer, istack); // The lower part of the readout chambers (drift volume + radiator) @@ -705,8 +706,8 @@ void TRDGeometry::createVolumes(std::vector<int> const& idtmed) // Create the volumes of the services createServices(idtmed); - for (int istack = 0; istack < kNstack; istack++) { - for (int ilayer = 0; ilayer < kNlayer; ilayer++) { + for (int istack = 0; istack < NSTACK; istack++) { + for (int ilayer = 0; ilayer < NLAYER; ilayer++) { assembleChamber(ilayer, istack); } } @@ -732,7 +733,7 @@ void TRDGeometry::createVolumes(std::vector<int> const& idtmed) xpos = 0.0; ypos = 0.0; zpos = 0.0; - for (int isector = 0; isector < kNsector; isector++) { + for (int isector = 0; isector < NSECTOR; isector++) { if (getSMstatus(isector)) { snprintf(cTagV, kTag, "BTRD%d", isector); switch (isector) { @@ -763,7 +764,7 @@ void TRDGeometry::createVolumes(std::vector<int> const& idtmed) xpos = 0.0; ypos = 0.5 * SLENGTH + 0.5 * FLENGTH; zpos = 0.0; - for (int isector = 0; isector < kNsector; isector++) { + for (int isector = 0; isector < NSECTOR; isector++) { if (getSMstatus(isector)) { snprintf(cTagV, kTag, "BTRD%d", isector); TVirtualMC::GetMC()->Gspos("UTF1", 1, cTagV, xpos, ypos, zpos, 0, "ONLY"); @@ -937,19 +938,19 @@ void TRDGeometry::createFrame(std::vector<int> const& idtmed) xpos = 0.0; ypos = 0.0; zpos = 0.0; - for (ilayer = 1; ilayer < kNlayer; ilayer++) { + for (ilayer = 1; ilayer < NLAYER; ilayer++) { xpos = CWIDTH[ilayer] / 2.0 + kSRLwidA / 2.0 + kSRLdst; ypos = 0.0; zpos = VROCSM + SMPLTT - CALZPOS - SHEIGHT / 2.0 + CRAH + CDRH - CALH - kSRLhgt / 2.0 + ilayer * (CH + VSPACE); TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1, "UTI1", xpos, ypos, zpos, matrix[2], "ONLY"); - TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + kNlayer, "UTI1", -xpos, ypos, zpos, matrix[3], "ONLY"); - TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 2 * kNlayer, "UTI2", xpos, ypos, zpos, matrix[2], "ONLY"); - TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 3 * kNlayer, "UTI2", -xpos, ypos, zpos, matrix[3], "ONLY"); - TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 4 * kNlayer, "UTI3", xpos, ypos, zpos, matrix[2], "ONLY"); - TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 5 * kNlayer, "UTI3", -xpos, ypos, zpos, matrix[3], "ONLY"); - TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 6 * kNlayer, "UTI4", xpos, ypos, zpos, matrix[2], "ONLY"); - TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 7 * kNlayer, "UTI4", -xpos, ypos, zpos, matrix[3], "ONLY"); + TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + NLAYER, "UTI1", -xpos, ypos, zpos, matrix[3], "ONLY"); + TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 2 * NLAYER, "UTI2", xpos, ypos, zpos, matrix[2], "ONLY"); + TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 3 * NLAYER, "UTI2", -xpos, ypos, zpos, matrix[3], "ONLY"); + TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 4 * NLAYER, "UTI3", xpos, ypos, zpos, matrix[2], "ONLY"); + TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 5 * NLAYER, "UTI3", -xpos, ypos, zpos, matrix[3], "ONLY"); + TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 6 * NLAYER, "UTI4", xpos, ypos, zpos, matrix[2], "ONLY"); + TVirtualMC::GetMC()->Gspos("USRL", ilayer + 1 + 7 * NLAYER, "UTI4", -xpos, ypos, zpos, matrix[3], "ONLY"); } // @@ -972,7 +973,7 @@ void TRDGeometry::createFrame(std::vector<int> const& idtmed) xpos = 0.0; ypos = 0.0; zpos = 0.0; - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { // The aluminum of the cross bars parSCB[0] = CWIDTH[ilayer] / 2.0 + kSRLdst / 2.0; snprintf(cTagV, kTag, "USF%01d", ilayer); @@ -1025,7 +1026,7 @@ void TRDGeometry::createFrame(std::vector<int> const& idtmed) const int kNparSCH = 3; float parSCH[kNparSCH]; - for (ilayer = 1; ilayer < kNlayer - 1; ilayer++) { + for (ilayer = 1; ilayer < NLAYER - 1; ilayer++) { parSCH[0] = CWIDTH[ilayer] / 2.0; parSCH[1] = (CLENGTH[ilayer + 1][2] / 2.0 + CLENGTH[ilayer + 1][1] - CLENGTH[ilayer][2] / 2.0 - CLENGTH[ilayer][1]) / @@ -1593,7 +1594,7 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) TVirtualMC::GetMC()->Gspos("UTC2", 1, "UTC1", xpos, ypos, zpos, 0, "ONLY"); TVirtualMC::GetMC()->Gspos("UTC4", 1, "UTC3", xpos, ypos, zpos, 0, "ONLY"); - for (ilayer = 1; ilayer < kNlayer; ilayer++) { + for (ilayer = 1; ilayer < NLAYER; ilayer++) { // Along the chambers xpos = CWIDTH[ilayer] / 2.0 + kCOLwid / 2.0 + kCOLposx; ypos = 0.0; @@ -1603,19 +1604,19 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[1] = SLENGTH / 2.0; parCOL[2] = kCOLhgt / 2.0; TVirtualMC::GetMC()->Gsposp("UTC1", ilayer, "UTI1", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + kNlayer, "UTI1", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + NLAYER, "UTI1", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 6 * kNlayer, "UTI2", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 6 * NLAYER, "UTI2", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 7 * kNlayer, "UTI2", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 7 * NLAYER, "UTI2", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 8 * kNlayer, "UTI3", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 8 * NLAYER, "UTI3", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 9 * kNlayer, "UTI3", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 9 * NLAYER, "UTI3", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 10 * kNlayer, "UTI4", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 10 * NLAYER, "UTI4", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 11 * kNlayer, "UTI4", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC1", ilayer + 11 * NLAYER, "UTI4", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); // Front of supermodules @@ -1626,17 +1627,17 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[0] = kCOLwid / 2.0; parCOL[1] = FLENGTH / 2.0; parCOL[2] = kCOLhgt / 2.0; - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 2 * kNlayer, "UTF1", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 2 * NLAYER, "UTF1", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 3 * kNlayer, "UTF1", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 3 * NLAYER, "UTF1", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 4 * kNlayer, "UTF2", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 4 * NLAYER, "UTF2", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 5 * kNlayer, "UTF2", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 5 * NLAYER, "UTF2", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); } - for (ilayer = 1; ilayer < kNlayer; ilayer++) { + for (ilayer = 1; ilayer < NLAYER; ilayer++) { // In baby frame xpos = CWIDTH[ilayer] / 2.0 + kCOLwid / 2.0 + kCOLposx - 2.5; ypos = kBBSdz / 2.0 - kBBMdz / 2.0; @@ -1645,13 +1646,13 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[0] = kCOLwid / 2.0; parCOL[1] = kBBSdz / 2.0; parCOL[2] = kCOLhgt / 2.0; - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 6 * kNlayer, "BBTRD", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 6 * NLAYER, "BBTRD", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 7 * kNlayer, "BBTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 7 * NLAYER, "BBTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); } - for (ilayer = 1; ilayer < kNlayer; ilayer++) { + for (ilayer = 1; ilayer < NLAYER; ilayer++) { // In back frame xpos = CWIDTH[ilayer] / 2.0 + kCOLwid / 2.0 + kCOLposx - 0.3; ypos = -kBFSdz / 2.0 + kBFMdz / 2.0; @@ -1660,9 +1661,9 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[0] = kCOLwid / 2.0; parCOL[1] = kBFSdz / 2.0; parCOL[2] = kCOLhgt / 2.0; - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 6 * kNlayer, "BFTRD", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 6 * NLAYER, "BFTRD", xpos, ypos, zpos, matrix[0], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 7 * kNlayer, "BFTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, + TVirtualMC::GetMC()->Gsposp("UTC3", ilayer + 7 * NLAYER, "BFTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parCOL, kNparCOL); } @@ -1675,13 +1676,13 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[1] = SLENGTH / 2.0; parCOL[2] = kCOLhgt / 2.0; TVirtualMC::GetMC()->Gsposp("UTC1", 6, "UTI1", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", 6 + kNlayer, "UTI1", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 6 * kNlayer, "UTI2", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 7 * kNlayer, "UTI2", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 8 * kNlayer, "UTI3", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 9 * kNlayer, "UTI3", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 10 * kNlayer, "UTI4", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 11 * kNlayer, "UTI4", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC1", 6 + NLAYER, "UTI1", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 6 * NLAYER, "UTI2", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 7 * NLAYER, "UTI2", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 8 * NLAYER, "UTI3", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 9 * NLAYER, "UTI3", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 10 * NLAYER, "UTI4", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC1", 6 + 11 * NLAYER, "UTI4", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); // Front of supermodules xpos = CWIDTH[5] / 2.0 - kCOLhgt / 2.0 - 1.3; ypos = 0.0; @@ -1689,10 +1690,10 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[0] = kCOLwid / 2.0; parCOL[1] = FLENGTH / 2.0; parCOL[2] = kCOLhgt / 2.0; - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 2 * kNlayer, "UTF1", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 3 * kNlayer, "UTF1", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 4 * kNlayer, "UTF2", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 5 * kNlayer, "UTF2", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 2 * NLAYER, "UTF1", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 3 * NLAYER, "UTF1", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 4 * NLAYER, "UTF2", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 5 * NLAYER, "UTF2", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); // In baby frame xpos = CWIDTH[5] / 2.0 - kCOLhgt / 2.0 - 3.1; ypos = kBBSdz / 2.0 - kBBMdz / 2.0; @@ -1700,8 +1701,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[0] = kCOLwid / 2.0; parCOL[1] = kBBSdz / 2.0; parCOL[2] = kCOLhgt / 2.0; - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 6 * kNlayer, "BBTRD", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 7 * kNlayer, "BBTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 6 * NLAYER, "BBTRD", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 7 * NLAYER, "BBTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); // In back frame xpos = CWIDTH[5] / 2.0 - kCOLhgt / 2.0 - 1.3; ypos = -kBFSdz / 2.0 + kBFMdz / 2.0; @@ -1709,8 +1710,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parCOL[0] = kCOLwid / 2.0; parCOL[1] = kBFSdz / 2.0; parCOL[2] = kCOLhgt / 2.0; - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 6 * kNlayer, "BFTRD", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); - TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 7 * kNlayer, "BFTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 6 * NLAYER, "BFTRD", xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); + TVirtualMC::GetMC()->Gsposp("UTC3", 6 + 7 * NLAYER, "BFTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parCOL, kNparCOL); // // The power bus bars @@ -1731,7 +1732,7 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) createVolume("UTP1", "BOX ", idtmed[25], parPWR, 0); createVolume("UTP3", "BOX ", idtmed[25], parPWR, 0); - for (ilayer = 1; ilayer < kNlayer; ilayer++) { + for (ilayer = 1; ilayer < NLAYER; ilayer++) { // Along the chambers xpos = CWIDTH[ilayer] / 2.0 + kPWRwid / 2.0 + kPWRposx; ypos = 0.0; @@ -1741,19 +1742,19 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[1] = SLENGTH / 2.0; parPWR[2] = kPWRhgtA / 2.0; TVirtualMC::GetMC()->Gsposp("UTP1", ilayer, "UTI1", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + kNlayer, "UTI1", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + NLAYER, "UTI1", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 6 * kNlayer, "UTI2", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 6 * NLAYER, "UTI2", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 7 * kNlayer, "UTI2", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 7 * NLAYER, "UTI2", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 8 * kNlayer, "UTI3", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 8 * NLAYER, "UTI3", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 9 * kNlayer, "UTI3", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 9 * NLAYER, "UTI3", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 10 * kNlayer, "UTI4", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 10 * NLAYER, "UTI4", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 11 * kNlayer, "UTI4", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP1", ilayer + 11 * NLAYER, "UTI4", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); // Front of supermodule @@ -1764,17 +1765,17 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[0] = kPWRwid / 2.0; parPWR[1] = FLENGTH / 2.0; parPWR[2] = kPWRhgtA / 2.0; - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 2 * kNlayer, "UTF1", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 2 * NLAYER, "UTF1", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 3 * kNlayer, "UTF1", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 3 * NLAYER, "UTF1", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 4 * kNlayer, "UTF2", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 4 * NLAYER, "UTF2", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 5 * kNlayer, "UTF2", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 5 * NLAYER, "UTF2", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); } - for (ilayer = 1; ilayer < kNlayer; ilayer++) { + for (ilayer = 1; ilayer < NLAYER; ilayer++) { // In baby frame xpos = CWIDTH[ilayer] / 2.0 + kPWRwid / 2.0 + kPWRposx - 2.5; ypos = kBBSdz / 2.0 - kBBMdz / 2.0; @@ -1783,13 +1784,13 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[0] = kPWRwid / 2.0; parPWR[1] = kBBSdz / 2.0; parPWR[2] = kPWRhgtB / 2.0; - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 6 * kNlayer, "BBTRD", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 6 * NLAYER, "BBTRD", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 7 * kNlayer, "BBTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 7 * NLAYER, "BBTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); } - for (ilayer = 1; ilayer < kNlayer; ilayer++) { + for (ilayer = 1; ilayer < NLAYER; ilayer++) { // In back frame xpos = CWIDTH[ilayer] / 2.0 + kPWRwid / 2.0 + kPWRposx - 0.3; ypos = -kBFSdz / 2.0 + kBFMdz / 2.0; @@ -1798,9 +1799,9 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[0] = kPWRwid / 2.0; parPWR[1] = kBFSdz / 2.0; parPWR[2] = kPWRhgtB / 2.0; - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 8 * kNlayer, "BFTRD", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 8 * NLAYER, "BFTRD", xpos, ypos, zpos, matrix[0], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 9 * kNlayer, "BFTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, + TVirtualMC::GetMC()->Gsposp("UTP3", ilayer + 9 * NLAYER, "BFTRD", -xpos, ypos, zpos, matrix[1], "ONLY", parPWR, kNparPWR); } @@ -1813,13 +1814,13 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[1] = SLENGTH / 2.0; parPWR[2] = kPWRhgtB / 2.0; TVirtualMC::GetMC()->Gsposp("UTP1", 6, "UTI1", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", 6 + kNlayer, "UTI1", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 6 * kNlayer, "UTI2", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 7 * kNlayer, "UTI2", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 8 * kNlayer, "UTI3", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 9 * kNlayer, "UTI3", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 10 * kNlayer, "UTI4", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 11 * kNlayer, "UTI4", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP1", 6 + NLAYER, "UTI1", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 6 * NLAYER, "UTI2", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 7 * NLAYER, "UTI2", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 8 * NLAYER, "UTI3", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 9 * NLAYER, "UTI3", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 10 * NLAYER, "UTI4", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP1", 6 + 11 * NLAYER, "UTI4", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); // Front of supermodules xpos = CWIDTH[5] / 2.0 + kPWRhgtB / 2.0 - 1.3; ypos = 0.0; @@ -1827,10 +1828,10 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[0] = kPWRwid / 2.0; parPWR[1] = FLENGTH / 2.0; parPWR[2] = kPWRhgtB / 2.0; - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 2 * kNlayer, "UTF1", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 3 * kNlayer, "UTF1", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 4 * kNlayer, "UTF2", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 5 * kNlayer, "UTF2", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 2 * NLAYER, "UTF1", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 3 * NLAYER, "UTF1", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 4 * NLAYER, "UTF2", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 5 * NLAYER, "UTF2", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); // In baby frame xpos = CWIDTH[5] / 2.0 + kPWRhgtB / 2.0 - 3.0; ypos = kBBSdz / 2.0 - kBBMdz / 2.0; @@ -1838,8 +1839,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[0] = kPWRwid / 2.0; parPWR[1] = kBBSdz / 2.0; parPWR[2] = kPWRhgtB / 2.0; - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 6 * kNlayer, "BBTRD", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 7 * kNlayer, "BBTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 6 * NLAYER, "BBTRD", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 7 * NLAYER, "BBTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); // In back frame xpos = CWIDTH[5] / 2.0 + kPWRhgtB / 2.0 - 1.3; ypos = -kBFSdz / 2.0 + kBFMdz / 2.0; @@ -1847,8 +1848,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parPWR[0] = kPWRwid / 2.0; parPWR[1] = kBFSdz / 2.0; parPWR[2] = kPWRhgtB / 2.0; - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 8 * kNlayer, "BFTRD", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); - TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 9 * kNlayer, "BFTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 8 * NLAYER, "BFTRD", xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); + TVirtualMC::GetMC()->Gsposp("UTP3", 6 + 9 * NLAYER, "BFTRD", -xpos, ypos, zpos, matrix[3], "ONLY", parPWR, kNparPWR); // // The gas tubes connecting the chambers in the super modules with holes @@ -1868,7 +1869,7 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) ypos = 0.0; zpos = 0.0; TVirtualMC::GetMC()->Gspos("UTG2", 1, "UTG1", xpos, ypos, zpos, 0, "ONLY"); - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { xpos = CWIDTH[ilayer] / 2.0 + kCOLwid / 2.0 - 1.5; ypos = 0.0; zpos = VROCSM + SMPLTT + kCOLhgt / 2.0 - SHEIGHT / 2.0 + 5.0 + ilayer * (CH + VSPACE); @@ -1901,8 +1902,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) const int kNparServ = 3; float parServ[kNparServ]; - for (istack = 0; istack < kNstack; istack++) { - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (istack = 0; istack < NSTACK; istack++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { int iDet = getDetectorSec(ilayer, istack); snprintf(cTagV, kTag, "UU%02d", iDet); @@ -1934,8 +1935,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) TVirtualMC::GetMC()->Gspos("UTCH", 1, "UTCP", xpos, ypos, zpos, 0, "ONLY"); // Position the cooling pipes in the mother volume - for (istack = 0; istack < kNstack; istack++) { - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (istack = 0; istack < NSTACK; istack++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { int iDet = getDetectorSec(ilayer, istack); int iCopy = getDetector(ilayer, istack, 0) * 100; int nMCMrow = getRowMax(ilayer, istack, 0); @@ -1966,8 +1967,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) createVolume("UTPL", "TUBE", idtmed[5], parTube, 0); // Position the power lines in the mother volume - for (istack = 0; istack < kNstack; istack++) { - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (istack = 0; istack < NSTACK; istack++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { int iDet = getDetectorSec(ilayer, istack); int iCopy = getDetector(ilayer, istack, 0) * 100; int nMCMrow = getRowMax(ilayer, istack, 0); @@ -2041,8 +2042,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) TVirtualMC::GetMC()->Gspos("UMC4", 1, "UMCM", xpos, ypos, zpos, 0, "ONLY"); // Position the MCMs in the mother volume - for (istack = 0; istack < kNstack; istack++) { - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (istack = 0; istack < NSTACK; istack++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { int iDet = getDetectorSec(ilayer, istack); int iCopy = getDetector(ilayer, istack, 0) * 1000; int nMCMrow = getRowMax(ilayer, istack, 0); @@ -2121,8 +2122,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) TVirtualMC::GetMC()->Gspos("UDC3", 1, "UDCS", xpos, ypos, zpos, 0, "ONLY"); // Put the DCS board in the chamber services mother volume - for (istack = 0; istack < kNstack; istack++) { - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (istack = 0; istack < NSTACK; istack++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { int iDet = getDetectorSec(ilayer, istack); int iCopy = iDet + 1; xpos = CWIDTH[ilayer] / 2.0 - @@ -2181,8 +2182,8 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) TVirtualMC::GetMC()->Gspos("UOR3", 1, "UORI", xpos, ypos, zpos, 0, "ONLY"); // Put the ORI board in the chamber services mother volume - for (istack = 0; istack < kNstack; istack++) { - for (ilayer = 0; ilayer < kNlayer; ilayer++) { + for (istack = 0; istack < NSTACK; istack++) { + for (ilayer = 0; ilayer < NLAYER; ilayer++) { int iDet = getDetectorSec(ilayer, istack); int iCopy = iDet + 1; xpos = CWIDTH[ilayer] / 2.0 - @@ -2196,7 +2197,7 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) ypos = -16.0; zpos = kORIz / 2.0 - CSVH / 2.0; snprintf(cTagV, kTag, "UU%02d", iDet); - TVirtualMC::GetMC()->Gspos("UORI", iCopy + kNdet, cTagV, xpos, ypos, zpos, 0, "ONLY"); + TVirtualMC::GetMC()->Gspos("UORI", iCopy + MAXCHAMBER, cTagV, xpos, ypos, zpos, 0, "ONLY"); } } @@ -2218,7 +2219,7 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) ypos = 0.0; zpos = 0.0; TVirtualMC::GetMC()->Gspos("UTG4", 1, "UTG3", xpos, ypos, zpos, 0, "ONLY"); - for (ilayer = 0; ilayer < kNlayer - 1; ilayer++) { + for (ilayer = 0; ilayer < NLAYER - 1; ilayer++) { xpos = 0.0; ypos = CLENGTH[ilayer][2] / 2.0 + CLENGTH[ilayer][1] + CLENGTH[ilayer][0]; zpos = 9.0 - SHEIGHT / 2.0 + ilayer * (CH + VSPACE); @@ -2226,19 +2227,19 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parTube[1] = 1.5 / 2.0; parTube[2] = CWIDTH[ilayer] / 2.0 - 2.5; TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1, "UTI1", xpos, ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); - TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 1 * kNlayer, "UTI1", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, + TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 1 * NLAYER, "UTI1", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); - TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 2 * kNlayer, "UTI2", xpos, ypos, zpos, matrix[2], "ONLY", parTube, + TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 2 * NLAYER, "UTI2", xpos, ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); - TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 3 * kNlayer, "UTI2", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, + TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 3 * NLAYER, "UTI2", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); - TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 4 * kNlayer, "UTI3", xpos, ypos, zpos, matrix[2], "ONLY", parTube, + TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 4 * NLAYER, "UTI3", xpos, ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); - TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 5 * kNlayer, "UTI3", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, + TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 5 * NLAYER, "UTI3", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); - TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 6 * kNlayer, "UTI4", xpos, ypos, zpos, matrix[2], "ONLY", parTube, + TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 6 * NLAYER, "UTI4", xpos, ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); - TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 7 * kNlayer, "UTI4", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, + TVirtualMC::GetMC()->Gsposp("UTG3", ilayer + 1 + 7 * NLAYER, "UTI4", xpos, -ypos, zpos, matrix[2], "ONLY", parTube, kNparTube); } @@ -2346,18 +2347,18 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) parBox[1] = 15.0 / 2.0; parBox[2] = 7.0 / 2.0; createVolume("UTPC", "BOX ", idtmed[25], parBox, kNparBox); - for (ilayer = 0; ilayer < kNlayer - 1; ilayer++) { + for (ilayer = 0; ilayer < NLAYER - 1; ilayer++) { xpos = CWIDTH[ilayer] / 2.0 + kPWRwid / 2.0; ypos = 0.0; zpos = VROCSM + SMPLTT + kPWRhgtA / 2.0 - SHEIGHT / 2.0 + kPWRposz + (ilayer + 1) * (CH + VSPACE); TVirtualMC::GetMC()->Gspos("UTPC", ilayer, "UTF1", xpos, ypos, zpos, matrix[0], "ONLY"); - TVirtualMC::GetMC()->Gspos("UTPC", ilayer + kNlayer, "UTF1", -xpos, ypos, zpos, matrix[1], "ONLY"); + TVirtualMC::GetMC()->Gspos("UTPC", ilayer + NLAYER, "UTF1", -xpos, ypos, zpos, matrix[1], "ONLY"); } xpos = CWIDTH[5] / 2.0 + kPWRhgtA / 2.0 - 2.0; ypos = 0.0; zpos = SHEIGHT / 2.0 - SMPLTT - 2.0; TVirtualMC::GetMC()->Gspos("UTPC", 5, "UTF1", xpos, ypos, zpos, matrix[3], "ONLY"); - TVirtualMC::GetMC()->Gspos("UTPC", 5 + kNlayer, "UTF1", -xpos, ypos, zpos, matrix[3], "ONLY"); + TVirtualMC::GetMC()->Gspos("UTPC", 5 + NLAYER, "UTF1", -xpos, ypos, zpos, matrix[3], "ONLY"); // Power connection panel (Al) parBox[0] = 60.0 / 2.0; @@ -2571,9 +2572,9 @@ void TRDGeometry::fillMatrixCache(int mask) const std::string vpApp3c{"/UTR3_1/UTS3_1/UTI3_1"}; const std::string vpApp3d{"/UTR4_1/UTS4_1/UTI4_1"}; - for (int ilayer = 0; ilayer < kNlayer; ilayer++) { - for (int isector = 0; isector < kNsector; isector++) { - for (int istack = 0; istack < kNstack; istack++) { + for (int ilayer = 0; ilayer < NLAYER; ilayer++) { + for (int isector = 0; isector < NSECTOR; isector++) { + for (int istack = 0; istack < NSTACK; istack++) { Int_t lid = getDetector(ilayer, istack, isector); // Check for disabled supermodules volPath = vpStr; @@ -2661,7 +2662,7 @@ void TRDGeometry::addAlignableVolumes() const // The super modules // The symbolic names are: TRD/sm00 ... TRD/sm17 - for (int isector = 0; isector < kNsector; isector++) { + for (int isector = 0; isector < NSECTOR; isector++) { volPath = vpStr; volPath += std::to_string(isector); volPath += vpApp1; @@ -2674,11 +2675,11 @@ void TRDGeometry::addAlignableVolumes() const // The readout chambers // The symbolic names are: TRD/sm00/st0/pl0 ... TRD/sm17/st4/pl5 - for (int isector = 0; isector < kNsector; isector++) { + for (int isector = 0; isector < NSECTOR; isector++) { if (!getSMstatus(isector)) continue; - for (int ilayer = 0; ilayer < kNlayer; ilayer++) { - for (int istack = 0; istack < kNstack; istack++) { + for (int ilayer = 0; ilayer < NLAYER; ilayer++) { + for (int istack = 0; istack < NSTACK; istack++) { Int_t lid = getDetector(ilayer, istack, isector); int idet = getDetectorSec(ilayer, istack); @@ -2750,7 +2751,7 @@ bool TRDGeometry::createClusterMatrixArray() return true; // already initialized } - setSize(MAXMATRICES, kNdet); //Only MAXMATRICES=521 of kNdet matrices are filled + setSize(MAXMATRICES, MAXCHAMBER); //Only MAXMATRICES=521 of MAXCHAMBER matrices are filled fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L) | o2::utils::bit2Mask(o2::TransformType::L2G) | o2::utils::bit2Mask(o2::TransformType::T2G) | o2::utils::bit2Mask(o2::TransformType::T2GRot)); return true; diff --git a/Detectors/TRD/base/src/TRDGeometryBase.cxx b/Detectors/TRD/base/src/TRDGeometryBase.cxx index 85fc87c7af839..bd86f5c0b8cba 100644 --- a/Detectors/TRD/base/src/TRDGeometryBase.cxx +++ b/Detectors/TRD/base/src/TRDGeometryBase.cxx @@ -11,6 +11,7 @@ #include "TRDBase/TRDGeometryBase.h" using namespace o2::trd; +using namespace o2::trd::constants; //_____________________________________________________________________________ GPUd() int TRDGeometryBase::getStack(float z, int layer) const @@ -21,10 +22,10 @@ GPUd() int TRDGeometryBase::getStack(float z, int layer) const // The return function has to be protected for positiveness !! // - if ((layer < 0) || (layer >= kNlayer)) + if ((layer < 0) || (layer >= NLAYER)) return -1; - int istck = kNstack; + int istck = NSTACK; float zmin = 0.0; float zmax = 0.0; @@ -49,11 +50,11 @@ GPUd() bool TRDGeometryBase::isOnBoundary(int det, float y, float z, float eps) // int ly = getLayer(det); - if ((ly < 0) || (ly >= kNlayer)) + if ((ly < 0) || (ly >= NLAYER)) return true; int stk = getStack(det); - if ((stk < 0) || (stk >= kNstack)) + if ((stk < 0) || (stk >= NSTACK)) return true; const TRDPadPlane* pp = &mPadPlanes[getDetectorSec(ly, stk)]; diff --git a/Detectors/TRD/base/src/TRDGeometryFlat.cxx b/Detectors/TRD/base/src/TRDGeometryFlat.cxx index 2f1dc0e72358c..2fac44700569e 100644 --- a/Detectors/TRD/base/src/TRDGeometryFlat.cxx +++ b/Detectors/TRD/base/src/TRDGeometryFlat.cxx @@ -10,6 +10,9 @@ #include "TRDBase/TRDGeometryFlat.h" #include "TRDBase/TRDGeometry.h" +#include "DataFormatsTRD/Constants.h" + +using namespace o2::trd::constants; TRDGeometryFlat::TRDGeometryFlat(const TRDGeometry& geo) { @@ -17,7 +20,7 @@ TRDGeometryFlat::TRDGeometryFlat(const TRDGeometry& geo) const TRDGeometryBase& b2 = geo; memcpy((void*)&b1, (void*)&b2, sizeof(b1)); int matrixCount = 0; - for (int i = 0; i < kNdet; i++) { + for (int i = 0; i < MAXCHAMBER; i++) { if (geo.chamberInGeometry(i)) { double v[12]; geo.getMatrixT2L(i).GetComponents(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11]); diff --git a/Detectors/TRD/macros/CMakeLists.txt b/Detectors/TRD/macros/CMakeLists.txt index 610afda87fdb3..405687d0f308f 100644 --- a/Detectors/TRD/macros/CMakeLists.txt +++ b/Detectors/TRD/macros/CMakeLists.txt @@ -14,8 +14,9 @@ o2_add_test_root_macro(CheckCCDBvalues.C o2_add_test_root_macro(CheckDigits.C PUBLIC_LINK_LIBRARIES O2::TRDBase + O2::DataFormatsTRD LABELS trd) o2_add_test_root_macro(CheckHits.C PUBLIC_LINK_LIBRARIES O2::TRDBase O2::TRDSimulation - LABELS trd) \ No newline at end of file + LABELS trd) diff --git a/Detectors/TRD/macros/CheckDigits.C b/Detectors/TRD/macros/CheckDigits.C index 181bd2211af98..c754c6c163034 100644 --- a/Detectors/TRD/macros/CheckDigits.C +++ b/Detectors/TRD/macros/CheckDigits.C @@ -24,6 +24,7 @@ #include "TRDBase/Digit.h" #include "TRDBase/TRDSimParam.h" #include "TRDBase/TRDCommonParam.h" +#include "DataFormatsTRD/Constants.h" #endif using namespace o2::trd; @@ -74,7 +75,7 @@ void CheckDigits(std::string digifile = "trddigits.root", hDet->Fill(det); hRow->Fill(row); hPad->Fill(pad); - for (int tb = 0; tb < kTimeBins; ++tb) { + for (int tb = 0; tb < o2::trd::constants::TIMEBINS; ++tb) { ADC_t adc = adcs[tb]; if (adc == (ADC_t)TRDSimParam::Instance()->GetADCoutRange()) { // LOG(INFO) << "Out of range ADC " << adc; diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h index 38555f1adb6c4..984a8d593bdef 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h @@ -18,6 +18,7 @@ #include "TRDBase/MCLabel.h" #include "TRDBase/TRDCommonParam.h" #include "TRDBase/TRDDiffAndTimeStructEstimator.h" +#include "DataFormatsTRD/Constants.h" #include "MathUtils/RandomRing.h" #include "SimulationDataFormat/MCTruthContainer.h" @@ -40,7 +41,7 @@ class PadResponse; struct SignalArray { double firstTBtime; // first TB time - std::array<float, kTimeBins> signals{}; // signals + std::array<float, constants::TIMEBINS> signals{}; // signals std::unordered_map<int, int> trackIds; // tracks Ids associated to the signal std::vector<MCLabel> labels; // labels associated to the signal }; @@ -115,10 +116,10 @@ class Digitizer // Digitization containers std::vector<HitType> mHitContainer; // the container of hits in a given detector std::vector<MCLabel> mMergedLabels; // temporary label container - std::array<SignalContainer, kNdet> mSignalsMapCollection; // container for caching signals over a timeframe - std::deque<std::array<SignalContainer, kNdet>> mPileupSignals; // container for piled up signals + std::array<SignalContainer, constants::MAXCHAMBER> mSignalsMapCollection; // container for caching signals over a timeframe + std::deque<std::array<SignalContainer, constants::MAXCHAMBER>> mPileupSignals; // container for piled up signals - void getHitContainerPerDetector(const std::vector<HitType>&, std::array<std::vector<HitType>, kNdet>&); + void getHitContainerPerDetector(const std::vector<HitType>&, std::array<std::vector<HitType>, constants::MAXCHAMBER>&); void setSimulationParameters(); // Digitization chain methods diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapConfigHandler.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapConfigHandler.h index fa23021d32a58..bd3738fbc1529 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapConfigHandler.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapConfigHandler.h @@ -77,10 +77,6 @@ class TrapConfigHandler static const unsigned int mgkScsnCmdOri = 26; // SCSN command for ORI configuration static const unsigned int mgkScsnLTUparam = 27; // extended SCSN command for the LTU configuration - static const int mgkMCMperROBCol = 4; // MCMs per ROB column - static const int mgkPadsPerMCM = 18; // readout pads per MCM - static const int mgkMCMperROBRow = 4; // MCMs per ROB row - static const int mgkMaxLinkPairs = 4; // number of linkpairs used during configuration static const int mgkMcmlistSize = 256; // list of MCMs to which a value has to be written diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h index bb57c4b772b15..eb2bc36480b26 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h @@ -34,6 +34,7 @@ #include "SimulationDataFormat/MCTruthContainer.h" //#include "DataFormatsTRD/RawData.h" #include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/Constants.h" class TH2F; @@ -287,7 +288,7 @@ class TrapSimulator mSumXY = 0; } }; - std::array<FitReg, FeeParam::mgkNadcMcm> mFitReg{}; + std::array<FitReg, constants::NADCMCM> mFitReg{}; protected: void setNTimebins(int ntimebins); // allocate data arrays corr. to the no. of timebins @@ -302,7 +303,7 @@ class TrapSimulator //TODO adcr adcf labels zerosupressionmap can all go into their own class. Refactor when stable. std::vector<int> mADCR; // Array with MCM ADC values (Raw, 12 bit) 2d with dimension mNTimeBin std::vector<int> mADCF; // Array with MCM ADC values (Filtered, 12 bit) 2d with dimension mNTimeBin - std::array<std::vector<o2::MCCompLabel>, FeeParam::mgkNadcMcm> mADCLabels{}; // MC Labels sent in from the digits coming in. + std::array<std::vector<o2::MCCompLabel>, constants::NADCMCM> mADCLabels{}; // MC Labels sent in from the digits coming in. std::vector<unsigned int> mMCMT; // tracklet word for one mcm/trap-chip std::vector<Tracklet> mTrackletArray; // Array of TRDtrackletMCM which contains MC information in addition to the tracklet word std::vector<Tracklet64> mTrackletArray64; // Array of TRDtrackletMCM which contains MC information in addition to the tracklet word @@ -319,9 +320,9 @@ class TrapSimulator TrapConfigHandler mTrapConfigHandler; // CalOnlineGainTables mGainTable; - static const int NOfAdcPerMcm = FeeParam::mgkNadcMcm; + static const int NOfAdcPerMcm = constants::NADCMCM; - std::array<FilterReg, FeeParam::mgkNadcMcm> mInternalFilterRegisters; + std::array<FilterReg, constants::NADCMCM> mInternalFilterRegisters; int mADCFilled = 0; // stores bitpattern of fillted adc, for know when to fill with pure baseline, for use with setData(int iadc, const ArrayADC& adc); int mNHits; // Number of detected hits diff --git a/Detectors/TRD/simulation/src/Detector.cxx b/Detectors/TRD/simulation/src/Detector.cxx index f9b8e4bb9a634..f2e69fb2b78ba 100644 --- a/Detectors/TRD/simulation/src/Detector.cxx +++ b/Detectors/TRD/simulation/src/Detector.cxx @@ -13,6 +13,7 @@ #include "TRDBase/TRDCommonParam.h" #include "TRDBase/TRDGeometry.h" #include "TRDSimulation/TRsim.h" +#include "DataFormatsTRD/Constants.h" #include "CommonUtils/ShmAllocator.h" #include "SimulationDataFormat/Stack.h" @@ -27,6 +28,7 @@ #include <string> using namespace o2::trd; +using namespace o2::trd::constants; Detector::Detector(Bool_t active) : o2::base::DetImpl<Detector>("TRD", active) @@ -118,12 +120,12 @@ bool Detector::ProcessHits(FairVolume* v) if (r2 != 1) { LOG(FATAL) << "Something went wrong with the geometry volume name " << fMC->CurrentVolOffName(7); } - if (sector < 0 || sector >= kNsector) { + if (sector < 0 || sector >= NSECTOR) { LOG(FATAL) << "Sector out of bounds"; } // The detector number (0 - 539) int det = mGeom->getDetector(mGeom->getLayer(idChamber), mGeom->getStack(idChamber), sector); - if (det < 0 || det >= kNdet) { + if (det < 0 || det >= MAXCHAMBER) { LOG(FATAL) << "Detector number out of bounds"; } diff --git a/Detectors/TRD/simulation/src/Digitizer.cxx b/Detectors/TRD/simulation/src/Digitizer.cxx index 6b9dfecc48675..e3c770b655271 100644 --- a/Detectors/TRD/simulation/src/Digitizer.cxx +++ b/Detectors/TRD/simulation/src/Digitizer.cxx @@ -28,6 +28,7 @@ #endif using namespace o2::trd; +using namespace o2::trd::constants; using namespace o2::math_utils; // init method for late initialization @@ -78,8 +79,8 @@ void Digitizer::setSimulationParameters() if (mSimParam->TRFOn()) { mTimeBinTRFend = ((int)(mSimParam->GetTRFhi() * mCommonParam->GetSamplingFrequency())) - 1; } - mMaxTimeBins = kTimeBins; // for signals, usually set at 30 tb = 3 microseconds - mMaxTimeBinsTRAP = kTimeBins; // for adcs; should be read from the CCDB or the TRAP config + mMaxTimeBins = TIMEBINS; // for signals, usually set at 30 tb = 3 microseconds + mMaxTimeBinsTRAP = TIMEBINS; // for adcs; should be read from the CCDB or the TRAP config mSamplingRate = mCommonParam->GetSamplingFrequency(); mElAttachProp = mSimParam->GetElAttachProp() / 100; } @@ -119,7 +120,7 @@ SignalContainer Digitizer::addSignalsFromPileup() int count = 0; SignalContainer addedSignalsMap; for (const auto& collection : mPileupSignals) { - for (int det = 0; det < kNdet; ++det) { + for (int det = 0; det < MAXCHAMBER; ++det) { const auto& signalMap = collection[det]; //--> a map with active pads only for this chamber for (const auto& signal : signalMap) { // loop over active pads only, if there is any const int& key = signal.first; @@ -222,7 +223,7 @@ void Digitizer::process(std::vector<HitType> const& hits, DigitContainer& digits int status = triggerEventProcessing(digits, labels); // Get the a hit container for all the hits in a given detector then call convertHits for a given detector (0 - 539) - std::array<std::vector<HitType>, kNdet> hitsPerDetector; + std::array<std::vector<HitType>, MAXCHAMBER> hitsPerDetector; getHitContainerPerDetector(hits, hitsPerDetector); #ifdef WITH_OPENMP @@ -230,7 +231,7 @@ void Digitizer::process(std::vector<HitType> const& hits, DigitContainer& digits // Loop over all TRD detectors (in a parallel fashion) #pragma omp parallel for schedule(dynamic) #endif - for (int det = 0; det < kNdet; ++det) { + for (int det = 0; det < MAXCHAMBER; ++det) { #ifdef WITH_OPENMP const int threadid = omp_get_thread_num(); #else @@ -258,10 +259,10 @@ void Digitizer::process(std::vector<HitType> const& hits, DigitContainer& digits } } -void Digitizer::getHitContainerPerDetector(const std::vector<HitType>& hits, std::array<std::vector<HitType>, kNdet>& hitsPerDetector) +void Digitizer::getHitContainerPerDetector(const std::vector<HitType>& hits, std::array<std::vector<HitType>, MAXCHAMBER>& hitsPerDetector) { // - // Fill an array of size kNdet (540) + // Fill an array of size MAXCHAMBER (540) // The i-element of the array contains the hit collection for the i-detector // To be called once, before doing the loop over all detectors and process the hits // diff --git a/Detectors/TRD/simulation/src/Trap2CRU.cxx b/Detectors/TRD/simulation/src/Trap2CRU.cxx index d2492ff84b9ee..08c08b28f9cc2 100644 --- a/Detectors/TRD/simulation/src/Trap2CRU.cxx +++ b/Detectors/TRD/simulation/src/Trap2CRU.cxx @@ -23,6 +23,7 @@ #include "DataFormatsTRD/LinkRecord.h" #include "DataFormatsTRD/RawData.h" #include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/Constants.h" #include "DetectorsRaw/HBFUtils.h" #include "DetectorsRaw/RawFileWriter.h" #include "TRDSimulation/Trap2CRU.h" @@ -185,7 +186,7 @@ void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) for (int halfcru = 0; halfcru < NumberOfHalfCRU; halfcru++) { //TODO come back and replace 72 with something. // TrackletHC memset(&mRawData[0], 0, sizeof(mRawData[0]) * mRawData.size()); // zero the rawdata storage - int numberofdetectors = o2::trd::kNdet; + int numberofdetectors = o2::trd::constants::MAXCHAMBER; HalfCRUHeader halfcruheader; //now write the cruheader at the head of all the data for this halfcru. LOG(debug) << "cru before building cruheader for halfcru index : " << halfcru << " with contents \n" diff --git a/Detectors/TRD/simulation/src/TrapConfig.cxx b/Detectors/TRD/simulation/src/TrapConfig.cxx index 1333e8c59f1e3..f9fbf83b15774 100644 --- a/Detectors/TRD/simulation/src/TrapConfig.cxx +++ b/Detectors/TRD/simulation/src/TrapConfig.cxx @@ -19,6 +19,7 @@ #include "TRDBase/TRDGeometry.h" #include "TRDBase/FeeParam.h" #include "TRDSimulation/TrapConfig.h" +#include "DataFormatsTRD/Constants.h" #include <fairlogger/Logger.h> #include <fstream> @@ -28,6 +29,7 @@ using namespace std; using namespace o2::trd; +using namespace o2::trd::constants; bool TrapConfig::mgRegAddressMapInitialized = false; @@ -663,9 +665,9 @@ bool TrapConfig::printTrapReg(TrapReg_t reg, int det, int rob, int mcm) // print the value stored in the given register // if it is individual a valid MCM has to be specified - if ((det >= 0 && det < kNdet) && - (rob >= 0 && rob < FeeParam::getNrobC1()) && - (mcm >= 0 && mcm < FeeParam::getNmcmRob() + 2)) { + if ((det >= 0 && det < MAXCHAMBER) && + (rob >= 0 && rob < NROBC1) && + (mcm >= 0 && mcm < NMCMROB + 2)) { LOG(info) << getRegName((TrapReg_t)reg) << "(" << std::setw(2) << getRegNBits((TrapReg_t)reg) << " bits) at 0x" << hex << std::setw(4) << getRegAddress((TrapReg_t)reg) << " is 0x" << hex << std::setw(8) << mRegisterValue[reg].getValue(det, rob, mcm) @@ -999,7 +1001,7 @@ void TrapConfig::configureOnlineGains() { // we dont want to do this anymore .... but here for future reference. /* if (hasOnlineFilterGain()) { - const int nDets = kNdet; + const int nDets = MAXCHAMBER; const int nMcms = TRDGeometry::MCMmax(); const int nChs = TRDGeometry::ADCmax(); @@ -1011,8 +1013,8 @@ void TrapConfig::configureOnlineGains() } for (int iDet = 0; iDet < nDets; ++iDet) { - //const int MaxRows = TRDGeometry::getStack(iDet) == 2 ? FeeParam::mgkNrowC0 : FeeParam::mgkNrowC1; - int MaxCols = FeeParam::mgkNcol; + //const int MaxRows = TRDGeometry::getStack(iDet) == 2 ? NROWC0 : NROWC1; + int MaxCols = NCOLUMN; // CalOnlineGainTableROC gainTbl = mGainTable.getGainTableROC(iDet); const int nRobs = TRDGeometry::getStack(iDet) == 2 ? TRDGeometry::ROBmaxC0() : TRDGeometry::ROBmaxC1(); diff --git a/Detectors/TRD/simulation/src/TrapConfigHandler.cxx b/Detectors/TRD/simulation/src/TrapConfigHandler.cxx index 3aa22a9b9fefa..888be9dd15c4f 100644 --- a/Detectors/TRD/simulation/src/TrapConfigHandler.cxx +++ b/Detectors/TRD/simulation/src/TrapConfigHandler.cxx @@ -28,12 +28,14 @@ #include "TRDSimulation/TrapConfigHandler.h" #include "TRDSimulation/TrapConfig.h" #include "TRDSimulation/TrapSimulator.h" +#include "DataFormatsTRD/Constants.h" #include "TMath.h" #include "TGeoMatrix.h" #include "TGraph.h" using namespace std; using namespace o2::trd; +using namespace o2::trd::constants; TrapConfigHandler::TrapConfigHandler(TrapConfig* cfg) : mFeeParam(), mRestrictiveMask((0x3ffff << 11) | (0x1f << 6) | 0x3f), mTrapConfig(cfg), mGtbl() { @@ -276,7 +278,7 @@ int TrapConfigHandler::loadConfig(std::string filename) if (cmd != 999 && addr != -1 && extali != -1) { if (cmd == mgkScsnCmdWrite) { - for (int det = 0; det < kNdet; det++) { + for (int det = 0; det < MAXCHAMBER; det++) { unsigned int rocpos = (1 << (TRDGeometry::getSector(det) + 11)) | (1 << (TRDGeometry::getStack(det) + 6)) | (1 << TRDGeometry::getLayer(det)); LOG(debug) << "checking restriction: mask=0x" << hex << std::setw(8) << mRestrictiveMask << " rocpos=0x" << hex << std::setw(8) << rocpos; if ((mRestrictiveMask & rocpos) == rocpos) { @@ -304,7 +306,7 @@ int TrapConfigHandler::loadConfig(std::string filename) else if (cmd == mgkScsnCmdSetHC) { int fullVersion = ((data & 0x7F00) >> 1) | (data & 0x7f); - for (int iDet = 0; iDet < kNdet; iDet++) { + for (int iDet = 0; iDet < MAXCHAMBER; iDet++) { int smls = (TRDGeometry::getSector(iDet) << 6) | (TRDGeometry::getLayer(iDet) << 3) | TRDGeometry::getStack(iDet); for (int iRob = 0; iRob < 8; iRob++) { @@ -383,7 +385,7 @@ void TrapConfigHandler::processLTUparam(int dest, int addr, unsigned int data) switch (dest) { case 0: // set the parameters in TrapConfig - for (int det = 0; det < kNdet; det++) { + for (int det = 0; det < MAXCHAMBER; det++) { configureDyCorr(det); configureDRange(det); // deflection range configureNTimebins(det); // timebins in the drift region @@ -551,10 +553,10 @@ void TrapConfigHandler::configurePIDcorr(int det) int MaxRows; FeeParam* feeparam = FeeParam::instance(); if (TRDGeometry::getStack(det) == 2) - MaxRows = FeeParam::mgkNrowC0; + MaxRows = NROWC0; else - MaxRows = FeeParam::mgkNrowC1; - int MaxCols = FeeParam::mgkNcol; + MaxRows = NROWC1; + int MaxCols = NCOLUMN; for (int row = 0; row < MaxRows; row++) { //TODO put this back to rob/mcm and not row/col as done in TrapSimulator for (int col = 0; col < MaxCols; col++) { readoutboard = feeparam->getROBfromPad(row, col); diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 9cc923eb49023..11ade2970fbcb 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -54,6 +54,7 @@ using namespace o2::trd; using namespace std; +using namespace o2::trd::constants; #define DEBUGTRAP 1 @@ -99,16 +100,16 @@ void TrapSimulator::init(TrapConfig* trapconfig, int det, int robPos, int mcmPos if (!mInitialized) { mNTimeBin = mTrapConfig->getTrapReg(TrapConfig::kC13CPUA, mDetector, mRobPos, mMcmPos); - mZSMap.resize(FeeParam::getNadcMcm()); + mZSMap.resize(NADCMCM); // tracklet calculation - //now a 25 slot array mFitReg.resize(FeeParam::getNadcMcm()); //TODO for now this is constant size in an array not a vector + //now a 25 slot array mFitReg.resize(NADCMCM); //TODO for now this is constant size in an array not a vector // mTrackletArray-.resize(mgkMaxTracklets); //now a 100 slot array as per run2 mHits.resize(50); mMCMT.resize(mgkMaxTracklets); - mADCR.resize(mNTimeBin * FeeParam::getNadcMcm()); - mADCF.resize(mNTimeBin * FeeParam::getNadcMcm()); + mADCR.resize(mNTimeBin * NADCMCM); + mADCF.resize(mNTimeBin * NADCMCM); } mInitialized = true; @@ -140,7 +141,7 @@ void TrapSimulator::reset() for (auto filterreg : mInternalFilterRegisters) filterreg.ClearReg(); // Default unread, low active bit mask - memset(&mZSMap[0], 0, sizeof(mZSMap[0]) * FeeParam::getNadcMcm()); + memset(&mZSMap[0], 0, sizeof(mZSMap[0]) * NADCMCM); memset(&mMCMT[0], 0, sizeof(mMCMT[0]) * mgkMaxTracklets); //mDict1.clear(); //mDict2.clear(); @@ -194,25 +195,25 @@ std::ostream& o2::trd::operator<<(std::ostream& os, const TrapSimulator& mcm) os << "----- Unfiltered ADC data (10 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) os << std::setw(5) << iChannel; os << std::endl; for (int iTimeBin = 0; iTimeBin < mcm.getNumberOfTimeBins(); iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) { + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(5) << (mcm.getDataRaw(iChannel, iTimeBin) >> mcm.mgkAddDigits); } os << std::endl; } os << "----- Filtered ADC data (10+2 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) os << std::setw(4) << iChannel << ((~mcm.getZeroSupressionMap(iChannel) != 0) ? "!" : " "); os << std::endl; for (int iTimeBin = 0; iTimeBin < mcm.getNumberOfTimeBins(); iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) { + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(4) << (mcm.getDataFiltered(iChannel, iTimeBin)) << (((mcm.getZeroSupressionMap(iChannel) & (1 << iTimeBin)) == 0) ? "!" : " "); } @@ -227,7 +228,7 @@ std::ostream& o2::trd::operator<<(std::ostream& os, const TrapSimulator& mcm) int addrStep = 0x80; for (int iTimeBin = 0; iTimeBin < mcm.getNumberOfTimeBins(); iTimeBin++) { - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) { + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(5) << 10 << std::setw(5) << addrOffset + iChannel * addrStep + iTimeBin << std::setw(5) << (mcm.getDataFiltered(iChannel, iTimeBin)) @@ -353,7 +354,7 @@ void TrapSimulator::printAdcDatTxt(ostream& os) const os << "# MCM " << mMcmPos << " on ROB " << mRobPos << " in detector " << mDetector << std::endl; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); ++iChannel) { + for (int iChannel = 0; iChannel < NADCMCM; ++iChannel) { os << std::setw(5) << (getDataRaw(iChannel, iTimeBin) >> mgkAddDigits); } os << std::endl; @@ -368,12 +369,12 @@ void TrapSimulator::printAdcDatHuman(ostream& os) const os << "----- Unfiltered ADC data (10 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) os << std::setw(5) << iChannel; os << std::endl; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) { + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(5) << (getDataRaw(iChannel, iTimeBin) >> mgkAddDigits); } os << std::endl; @@ -381,13 +382,13 @@ void TrapSimulator::printAdcDatHuman(ostream& os) const os << "----- Filtered ADC data (10+2 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) os << std::setw(4) << iChannel << ((~mZSMap[iChannel] != 0) ? "!" : " "); os << std::endl; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) { + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(4) << (getDataFiltered(iChannel, iTimeBin)) << (((mZSMap[iChannel] & (1 << iTimeBin)) == 0) ? "!" : " "); } @@ -407,7 +408,7 @@ void TrapSimulator::printAdcDatXml(ostream& os) const os << " <ro-board rob=\"" << mRobPos << "\">" << std::endl; os << " <m mcm=\"" << mMcmPos << "\">" << std::endl; - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) { + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << " <ch chnr=\"" << iChannel << "\">" << std::endl; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { os << "<tb>" << mADCF[iChannel * mNTimeBin + iTimeBin] / 4 << "</tb>"; @@ -435,7 +436,7 @@ void TrapSimulator::printAdcDatDatx(ostream& os, bool broadcast, int timeBinOffs int addrOffsetEBSIA = 0x20; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { - for (int iChannel = 0; iChannel < FeeParam::getNadcMcm(); iChannel++) { + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { if ((iTimeBin < timeBinOffset) || (iTimeBin >= mNTimeBin + timeBinOffset)) { if (broadcast == false) mTrapConfig->printDatx(os, addrOffset + iChannel * addrStep + addrOffsetEBSIA + iTimeBin, 10, getRobPos(), getMcmPos()); @@ -485,7 +486,7 @@ void TrapSimulator::setNTimebins(int ntimebins) return; mNTimeBin = ntimebins; - // for( int iAdc = 0 ; iAdc < FeeParam::getNadcMcm(); iAdc++ ) { + // for( int iAdc = 0 ; iAdc < NADCMCM; iAdc++ ) { // delete [] mADCR[iAdc]; // delete [] mADCF[iAdc]; // mADCR[iAdc] = new int[mNTimeBin]; @@ -674,9 +675,9 @@ void TrapSimulator::draw(int choice, int index) TCanvas* c1 = new TCanvas(Form("canvas_%i_%i:%i:%i_%i", index, mDetector, mRobPos, mMcmPos, (int)mTrackletArray.size())); TH2F* hist = new TH2F(Form("mcmdata_%i", index), Form("Data of MCM %i on ROB %i in detector %i ", mMcmPos, mRobPos, mDetector), - FeeParam::getNadcMcm(), + NADCMCM, -0.5, - FeeParam::getNadcMcm() - 0.5, + NADCMCM - 0.5, getNumberOfTimeBins(), -0.5, getNumberOfTimeBins() - 0.5); @@ -685,9 +686,9 @@ void TrapSimulator::draw(int choice, int index) hist->SetStats(false); TH2F* histfiltered = new TH2F(Form("mcmdataf_%i", index), Form("Data of MCM %i on ROB %i in detector %i filtered", mMcmPos, mRobPos, mDetector), - FeeParam::getNadcMcm(), + NADCMCM, -0.5, - FeeParam::getNadcMcm() - 0.5, + NADCMCM - 0.5, getNumberOfTimeBins(), -0.5, getNumberOfTimeBins() - 0.5); @@ -696,14 +697,14 @@ void TrapSimulator::draw(int choice, int index) if ((choice & PLOTRAW) != 0) { for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { hist->SetBinContent(iAdc + 1, iTimeBin + 1, mADCR[iAdc * mNTimeBin + iTimeBin] >> mgkAddDigits); } } hist->Draw("COLZ"); } else { for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { histfiltered->SetBinContent(iAdc + 1, iTimeBin + 1, mADCF[iAdc * mNTimeBin + iTimeBin] >> mgkAddDigits); } } @@ -766,8 +767,8 @@ void TrapSimulator::setData(int adc, const ArrayADC& data, std::vector<o2::MCCom if (!checkInitialized()) return; - if (adc < 0 || adc >= FeeParam::getNadcMcm()) { - // LOG(error) << "Error: ADC " << adc << " is out of range (0 .. " << FeeParam::getNadcMcm() - 1 << ")"; + if (adc < 0 || adc >= NADCMCM) { + // LOG(error) << "Error: ADC " << adc << " is out of range (0 .. " << NADCMCM - 1 << ")"; return; } @@ -797,8 +798,8 @@ void TrapSimulator::setData(int adc, int it, int data) if (!checkInitialized()) return; - if (adc < 0 || adc >= FeeParam::getNadcMcm()) { - LOG(error) << "Error: ADC " << adc << " is out of range (0 .. " << FeeParam::getNadcMcm() - 1 << ")"; + if (adc < 0 || adc >= NADCMCM) { + LOG(error) << "Error: ADC " << adc << " is out of range (0 .. " << NADCMCM - 1 << ")"; return; } @@ -816,7 +817,7 @@ void TrapSimulator::setBaselines() LOG(info) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " for " << mDetector << ":" << mRobPos << ":" << mMcmPos; //loop over all adcs. - for (int adc = 0; adc < FeeParam::getNadcMcm(); adc++) { + for (int adc = 0; adc < NADCMCM; adc++) { LOG(info) << "Setting baselines for adc: " << adc << " of " << mDetector << ":" << mRobPos << ":" << mMcmPos << hex << mADCFilled << " if of : " << (mADCFilled & (1 << adc)); if ((mADCFilled & (1 << adc)) == 0) { // adc is empty by construction of mADCFilled. LOG(info) << "past if Setting baselines for adc: " << adc << " of " << mDetector << ":" << mRobPos << ":" << mMcmPos; @@ -837,7 +838,7 @@ void TrapSimulator::setDataPedestal(int adc) if (!checkInitialized()) return; - if (adc < 0 || adc >= FeeParam::getNadcMcm()) { + if (adc < 0 || adc >= NADCMCM) { return; } @@ -880,7 +881,7 @@ int TrapSimulator::getCol(int adc) return -1; int col = mFeeParam->getPadColFromADC(mRobPos, mMcmPos, adc); - if (col < 0 || col >= mFeeParam->getNcol()) + if (col < 0 || col >= NCOLUMN) return -1; else return col; @@ -907,8 +908,8 @@ int TrapSimulator::packData(std::vector<uint32_t>& rawdata, uint32_t offset) mcmhead.oneb = 1; mcmhead.onea = 1; mcmhead.padrow = ((mRobPos >> 1) << 2) | (mMcmPos >> 2); - int mcmcol = mMcmPos % FeeParam::mgkNmcmRobInCol + (mRobPos % 2) * FeeParam::mgkNmcmRobInCol; - int padcol = mcmcol * FeeParam::mgkNcolMcm + FeeParam::mgkNcolMcm + 1; + int mcmcol = mMcmPos % NMCMROBINCOL + (mRobPos % 2) * NMCMROBINCOL; + int padcol = mcmcol * NCOLMCM + NCOLMCM + 1; mcmhead.col = 1; //TODO check this, cant call FeeParam due to virtual function LOG(debug) << "packing data with trackletarry64 size of : " << mTrackletArray64.size(); for (int i = 0; i < 3; i++) { @@ -1005,7 +1006,7 @@ int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, uns if (rawVer >= 3 && (mTrapConfig->getTrapReg(TrapConfig::kC15CPUA, mDetector, mRobPos, mMcmPos) & (1 << 13))) { // check for zs flag in TRAP configuration int nActiveADC = 0; // number numberOverFlowWordsWritten activated ADC bits in a word - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { if (~mZSMap[iAdc] != 0) { // 0 means not suppressed adcMask |= (1 << (iAdc + 4)); // last 4 digit reserved for 1100=0xc nActiveADC++; // number numberOverFlowWordsWritten 1 in mmm....m @@ -1123,7 +1124,7 @@ void TrapSimulator::filterPedestalInit(int baseline) unsigned short fptc = mTrapConfig->getTrapReg(TrapConfig::kFPTC, mDetector, mRobPos, mMcmPos); // 0..3, 0 - fastest, 3 - slowest - for (int adc = 0; adc < FeeParam::getNadcMcm(); adc++) + for (int adc = 0; adc < NADCMCM; adc++) mInternalFilterRegisters[adc].mPedAcc = (baseline << 2) * (1 << mgkFPshifts[fptc]); // LOG(info) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; } @@ -1179,7 +1180,7 @@ void TrapSimulator::filterPedestal() // LOG(info) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { int oldadc = mADCF[iAdc * mNTimeBin + iTimeBin]; mADCF[iAdc * mNTimeBin + iTimeBin] = filterPedestalNextSample(iAdc, iTimeBin, mADCR[iAdc * mNTimeBin + iTimeBin]); // LOG(info) << "mADCF : time : " << iTimeBin << " adc : " << iAdc << " change : " << oldadc << " -> " << mADCF[iAdc * mNTimeBin + iTimeBin]; @@ -1193,7 +1194,7 @@ void TrapSimulator::filterGainInit() // Initializes the gain filter. In this case, only threshold // counters are reset. - for (int adc = 0; adc < FeeParam::getNadcMcm(); adc++) { + for (int adc = 0; adc < NADCMCM; adc++) { // these are counters which in hardware continue // until maximum or reset mInternalFilterRegisters[adc].mGainCounterA = 0; @@ -1256,7 +1257,7 @@ void TrapSimulator::filterGain() { // Read data from mADCF and apply gain filter. - for (int adc = 0; adc < FeeParam::getNadcMcm(); adc++) { + for (int adc = 0; adc < NADCMCM; adc++) { for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { mADCF[adc * mNTimeBin + iTimeBin] = filterGainNextSample(adc, mADCF[adc * mNTimeBin + iTimeBin]); } @@ -1290,7 +1291,7 @@ void TrapSimulator::filterTailInit(int baseline) ql = lambdaL * (1 - lambdaS) * alphaL; qs = lambdaS * (1 - lambdaL) * (1 - alphaL); - for (int adc = 0; adc < FeeParam::getNadcMcm(); adc++) { + for (int adc = 0; adc < NADCMCM; adc++) { int value = baseline & 0xFFF; int corr = (value * mTrapConfig->getTrapReg(TrapConfig::TrapReg_t(TrapConfig::kFGF0 + adc), mDetector, mRobPos, mMcmPos)) >> 11; corr = corr > 0xfff ? 0xfff : corr; @@ -1357,7 +1358,7 @@ void TrapSimulator::filterTail() // Apply tail cancellation filter to all data. for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { mADCF[iAdc * mNTimeBin + iTimeBin] = filterTailNextSample(iAdc, mADCF[iAdc * mNTimeBin + iTimeBin]); } } @@ -1381,7 +1382,7 @@ void TrapSimulator::zeroSupressionMapping() int eBIL = mTrapConfig->getTrapReg(TrapConfig::kEBIL, mDetector, mRobPos, mMcmPos); int eBIN = mTrapConfig->getTrapReg(TrapConfig::kEBIN, mDetector, mRobPos, mMcmPos); - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) mZSMap[iAdc] = -1; for (int it = 0; it < mNTimeBin; it++) { @@ -1411,7 +1412,7 @@ void TrapSimulator::zeroSupressionMapping() } // ----- last channel ----- - iAdc = FeeParam::getNadcMcm() - 1; + iAdc = NADCMCM - 1; ap = mADCF[(iAdc - 1) * mNTimeBin + it] >> mgkAddDigits; // previous ac = mADCF[iAdc * mNTimeBin + it] >> mgkAddDigits; // current @@ -1429,7 +1430,7 @@ void TrapSimulator::zeroSupressionMapping() } // ----- middle channels ----- - for (iAdc = 1; iAdc < FeeParam::getNadcMcm() - 1; iAdc++) { + for (iAdc = 1; iAdc < NADCMCM - 1; iAdc++) { ap = mADCF[(iAdc - 1) * mNTimeBin + it] >> mgkAddDigits; // previous ac = mADCF[iAdc * mNTimeBin + it] >> mgkAddDigits; // current an = mADCF[(iAdc + 1) * mNTimeBin + it] >> mgkAddDigits; // next @@ -1563,7 +1564,7 @@ void TrapSimulator::calcFitreg() for (timebin = timebin1; timebin < timebin2; timebin++) { // first find the hit candidates and store the total cluster charge in qTotal array // in case of not hit store 0 there. - for (adcch = 0; adcch < FeeParam::getNadcMcm() - 2; adcch++) { + for (adcch = 0; adcch < NADCMCM - 2; adcch++) { if (((adcMask >> adcch) & 7) == 7) //??? all 3 channels are present in case of ZS { adcLeft = mADCF[adcch * mNTimeBin + timebin]; @@ -1729,8 +1730,8 @@ void TrapSimulator::calcFitreg() } } } - /* - for (int iAdc = 0; iAdc < FeeParam::getNadcMcm(); iAdc++) { + /* + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { if (mFitReg[iAdc].mNhits != 0) { LOG(debug) << "fitreg[" << iAdc << "]: nHits = " << mFitReg[iAdc].mNhits << "]: sumX = " << mFitReg[iAdc].mSumX << ", sumY = " << mFitReg[iAdc].mSumY << ", sumX2 = " << mFitReg[iAdc].mSumX2 << ", sumY2 = " << mFitReg[iAdc].mSumY2 << ", sumXY = " << mFitReg[iAdc].mSumXY; } @@ -2529,4 +2530,3 @@ bool TrapSimulator::readPackedConfig(TrapConfig* cfg, int hc, unsigned int* data LOG(debug) << "no end marker! " << idx << " words read"; return -err; // only if the max length of the block reached! } - diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h b/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h index d31f146499321..a06fcf6181eba 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h @@ -49,6 +49,7 @@ class TObjArray; #include "GPUDef.h" #include "TRDBase/TRDGeometryFlat.h" #include "TRDBase/TRDPadPlane.h" +#include "DataFormatsTRD/Constants.h" #include "GPUCommonTransform3D.h" namespace GPUCA_NAMESPACE @@ -98,7 +99,7 @@ class GPUTRDGeometry : private o2::trd::TRDGeometryFlat GPUd() int GetRowMax(int layer, int stack, int sector) const { return getRowMax(layer, stack, sector); } GPUd() bool ChamberInGeometry(int det) const { return chamberInGeometry(det); } - static constexpr int kNstack = o2::trd::kNstack; + static constexpr int kNstack = o2::trd::constants::NSTACK; }; } // namespace gpu } // namespace GPUCA_NAMESPACE From ced5005f1229813e8331b3a1d6592fbe2c372ead Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 13 Aug 2020 15:32:51 +0200 Subject: [PATCH 0359/1751] Put TPC constants in namespace instead of class --- .../include/DataFormatsTPC/ClusterNative.h | 12 ++++---- .../DataFormatsTPC/ClusterNativeHelper.h | 12 ++++---- .../TPC/include/DataFormatsTPC/Constants.h | 29 ++++++++++++------- .../include/DataFormatsTPC/TPCSectorHeader.h | 2 +- .../Detectors/TPC/src/ClusterNativeHelper.cxx | 11 +++---- .../src/TPCITSMatchingSpec.cxx | 6 ++-- .../src/TPCInterpolationSpec.cxx | 6 ++-- Detectors/TPC/base/include/TPCBase/Sector.h | 2 +- Detectors/TPC/base/src/ZeroSuppress.cxx | 3 +- .../SpacePoints/SpacePointsCalibParam.h | 2 +- .../include/SpacePoints/TrackInterpolation.h | 2 +- Detectors/TPC/qc/macro/runClusters.C | 6 ++-- .../DigitalCurrentClusterIntegrator.h | 2 +- .../src/DigitalCurrentClusterIntegrator.cxx | 9 +++--- .../src/HardwareClusterDecoder.cxx | 18 ++++++------ .../reconstruction/test/testGPUCATracking.cxx | 4 +-- Detectors/TPC/simulation/src/SpaceCharge.cxx | 13 +++++---- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 +- .../Detectors/src/DataInterpreterTPC.cxx | 4 +-- GPU/Common/GPUDefConstantsAndSettings.h | 4 +-- GPU/GPUTracking/Base/GPUHostDataTypes.h | 2 +- .../Base/GPUReconstructionConvert.cxx | 9 +++--- GPU/GPUTracking/Global/GPUChainTracking.cxx | 5 ++-- .../Interface/GPUO2InterfaceConfiguration.h | 4 +-- .../TPCClusterFinder/GPUTPCCFDecodeZS.cxx | 3 +- macro/runCATrackingClusterNative.C | 4 +-- 26 files changed, 95 insertions(+), 81 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h index 79581f7494233..4947314ca0340 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h @@ -156,11 +156,11 @@ struct ClusterNative { // the data inside a buffer. struct ClusterNativeAccess { const ClusterNative* clustersLinear; - const ClusterNative* clusters[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW]; + const ClusterNative* clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clustersMCTruth; - unsigned int nClusters[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW]; - unsigned int nClustersSector[Constants::MAXSECTOR]; - unsigned int clusterOffset[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW]; + unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; + unsigned int nClustersSector[constants::MAXSECTOR]; + unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; unsigned int nClustersTotal; void setOffsetPtrs(); @@ -169,9 +169,9 @@ struct ClusterNativeAccess { inline void ClusterNativeAccess::setOffsetPtrs() { int offset = 0; - for (unsigned int i = 0; i < Constants::MAXSECTOR; i++) { + for (unsigned int i = 0; i < constants::MAXSECTOR; i++) { nClustersSector[i] = 0; - for (unsigned int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (unsigned int j = 0; j < constants::MAXGLOBALPADROW; j++) { clusterOffset[i][j] = offset; clusters[i][j] = &clustersLinear[offset]; nClustersSector[i] += nClusters[i][j]; diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h index 8ccc6b10a1b63..830830eab211a 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h @@ -82,7 +82,7 @@ struct ClusterNativeBuffer : public ClusterGroupHeader { // This is the header for the transport format of TPC ClusterNative data, // followed by a linear buffer of clusters. struct alignas(64) ClusterCountIndex { - unsigned int nClusters[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW]; + unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; }; // @struct ClusterCountIndex @@ -91,13 +91,13 @@ struct alignas(64) ClusterCountIndex { struct alignas(64) ClusterIndexBuffer { using value_type = ClusterNative; - unsigned int nClusters[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW]; + unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; size_t getNClusters() const { size_t count = 0; - for (auto sector = 0; sector < Constants::MAXSECTOR; sector++) { - for (auto row = 0; row < Constants::MAXGLOBALPADROW; row++) { + for (auto sector = 0; sector < constants::MAXSECTOR; sector++) { + for (auto row = 0; row < constants::MAXGLOBALPADROW; row++) { count += nClusters[sector][row]; } } @@ -135,8 +135,8 @@ class ClusterNativeHelper ClusterNativeHelper() = default; ~ClusterNativeHelper() = default; - constexpr static unsigned int NSectors = Constants::MAXSECTOR; - constexpr static unsigned int NPadRows = Constants::MAXGLOBALPADROW; + constexpr static unsigned int NSectors = constants::MAXSECTOR; + constexpr static unsigned int NPadRows = constants::MAXGLOBALPADROW; /// convert clusters stored in binary cluster native format to a tree and write to root file /// the cluster parameters are stored in the tree together with sector and padrow numbers. diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h index 69b627e3b9e9d..3090b0082bdf7 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h @@ -20,23 +20,30 @@ namespace o2 { namespace tpc { - -class Constants +namespace constants { - public: - // the number of sectors - static constexpr int MAXSECTOR = 36; - // the number of global pad rows +// the number of sectors +constexpr int MAXSECTOR = 36; + +// the number of global pad rows #if defined(GPUCA_STANDALONE) && !defined(GPUCA_O2_LIB) && !defined(GPUCA_TPC_GEOMETRY_O2) - static constexpr int MAXGLOBALPADROW = 159; // Number of pad rows in Run 2, used for GPU TPC tests with Run 2 data +constexpr int MAXGLOBALPADROW = 159; // Number of pad rows in Run 2, used for GPU TPC tests with Run 2 data #else - static constexpr int MAXGLOBALPADROW = 152; // Correct number of pad rows in Run 3 +constexpr int MAXGLOBALPADROW = 152; // Correct number of pad rows in Run 3 #endif - // number of LHC bunch crossings per TPC time bin (40 MHz / 5 MHz) - static constexpr int LHCBCPERTIMEBIN = 8; -}; +// number of LHC bunch crossings per TPC time bin (40 MHz / 5 MHz) +constexpr int LHCBCPERTIMEBIN = 8; +} // namespace constants + +// FIXME: Temporary workaround to not break the QC build which depends on the removed class o2::tpc::Constants +// Once https://github.com/AliceO2Group/QualityControl/pull/459 is merged this can be removed +namespace Constants +{ +using namespace constants; +} + } // namespace tpc } // namespace o2 diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TPCSectorHeader.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TPCSectorHeader.h index 14daef1ce8c3a..c9221ff5fb37a 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TPCSectorHeader.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TPCSectorHeader.h @@ -25,7 +25,7 @@ struct TPCSectorHeader : public o2::header::BaseHeader { // Required to do the lookup constexpr static const o2::header::HeaderType sHeaderType = "TPCSectH"; static const uint32_t sVersion = 2; - static constexpr int NSectors = o2::tpc::Constants::MAXSECTOR; + static constexpr int NSectors = o2::tpc::constants::MAXSECTOR; TPCSectorHeader(int s) : BaseHeader(sizeof(TPCSectorHeader), sHeaderType, o2::header::gSerializationMethodNone, sVersion), sectorBits(((uint64_t)0x1) << s) diff --git a/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx b/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx index ac047133db6ac..ee0c0a5b12907 100644 --- a/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx +++ b/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx @@ -20,6 +20,7 @@ #include <iostream> using namespace o2::tpc; +using namespace o2::tpc::constants; void ClusterNativeHelper::convert(const char* fromFile, const char* toFile, const char* toTreeName) { @@ -177,7 +178,7 @@ int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, st } int ClusterNativeHelper::Reader::parseSector(const char* buffer, size_t size, gsl::span<MCLabelContainer const> const& mcinput, ClusterNativeAccess& clusterIndex, - const MCLabelContainer* (&clustersMCTruth)[Constants::MAXSECTOR]) + const MCLabelContainer* (&clustersMCTruth)[MAXSECTOR]) { if (!buffer || size < sizeof(ClusterCountIndex)) { return 0; @@ -187,9 +188,9 @@ int ClusterNativeHelper::Reader::parseSector(const char* buffer, size_t size, gs ClusterCountIndex const& counts = *reinterpret_cast<const ClusterCountIndex*>(buffer); ClusterNative const* clusters = reinterpret_cast<ClusterNative const*>(buffer + sizeof(ClusterCountIndex)); size_t numberOfClusters = 0; - for (int i = 0; i < Constants::MAXSECTOR; i++) { + for (int i = 0; i < MAXSECTOR; i++) { int nSectorClusters = 0; - for (int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (int j = 0; j < MAXGLOBALPADROW; j++) { if (counts.nClusters[i][j] == 0) { continue; } @@ -246,8 +247,8 @@ int ClusterNativeHelper::TreeWriter::fillFrom(ClusterNativeAccess const& cluster return -1; } int result = 0; - for (size_t sector = 0; sector < Constants::MAXSECTOR; ++sector) { - for (size_t padrow = 0; padrow < Constants::MAXGLOBALPADROW; ++padrow) { + for (size_t sector = 0; sector < MAXSECTOR; ++sector) { + for (size_t padrow = 0; padrow < MAXGLOBALPADROW; ++padrow) { int locres = fillFrom(sector, padrow, clusterIndex.clusters[sector][padrow], clusterIndex.nClusters[sector][padrow]); if (result >= 0 && locres >= 0) { result += locres; diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index d1ae7eb3a433d..8d97c3294552a 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -101,7 +101,7 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) //---------------------------->> TPC Clusters loading >>------------------------------------------ int operation = 0; uint64_t activeSectors = 0; - std::bitset<o2::tpc::Constants::MAXSECTOR> validSectors = 0; + std::bitset<o2::tpc::constants::MAXSECTOR> validSectors = 0; std::map<int, DataRef> datarefs; std::vector<InputSpec> filter = { {"check", ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}, Lifetime::Timeframe}, @@ -114,7 +114,7 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) throw std::runtime_error("sector header missing on header stack"); } int sector = sectorHeader->sector(); - std::bitset<o2::tpc::Constants::MAXSECTOR> sectorMask(sectorHeader->sectorBits); + std::bitset<o2::tpc::constants::MAXSECTOR> sectorMask(sectorHeader->sectorBits); LOG(INFO) << "Reading TPC cluster data, sector mask is " << sectorMask; if ((validSectors & sectorMask).any()) { // have already data for this sector, this should not happen in the current @@ -133,7 +133,7 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) << std::endl // << " input status: " << validSectors // << std::endl // - << " active sectors: " << std::bitset<o2::tpc::Constants::MAXSECTOR>(activeSectors); + << " active sectors: " << std::bitset<o2::tpc::constants::MAXSECTOR>(activeSectors); }; if (activeSectors == 0 || (activeSectors & validSectors.to_ulong()) != activeSectors) { diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx index 11d6c64c14fdd..8ac3dc05d7fc5 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx @@ -54,7 +54,7 @@ void TPCInterpolationDPL::run(ProcessingContext& pc) //---------------------------->> TPC Clusters loading >>------------------------------------------ int operation = 0; uint64_t activeSectors = 0; - std::bitset<o2::tpc::Constants::MAXSECTOR> validSectors = 0; + std::bitset<o2::tpc::constants::MAXSECTOR> validSectors = 0; std::map<int, DataRef> datarefs; std::vector<InputSpec> filter = { {"check", ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}, Lifetime::Timeframe}, @@ -67,7 +67,7 @@ void TPCInterpolationDPL::run(ProcessingContext& pc) throw std::runtime_error("sector header missing on header stack"); } const int& sector = sectorHeader->sector(); - std::bitset<o2::tpc::Constants::MAXSECTOR> sectorMask(sectorHeader->sectorBits); + std::bitset<o2::tpc::constants::MAXSECTOR> sectorMask(sectorHeader->sectorBits); LOG(INFO) << "Reading TPC cluster data, sector mask is " << sectorMask; if ((validSectors & sectorMask).any()) { // have already data for this sector, this should not happen in the current @@ -86,7 +86,7 @@ void TPCInterpolationDPL::run(ProcessingContext& pc) << std::endl // << " input status: " << validSectors // << std::endl // - << " active sectors: " << std::bitset<o2::tpc::Constants::MAXSECTOR>(activeSectors); + << " active sectors: " << std::bitset<o2::tpc::constants::MAXSECTOR>(activeSectors); }; if (activeSectors == 0 || (activeSectors & validSectors.to_ulong()) != activeSectors) { diff --git a/Detectors/TPC/base/include/TPCBase/Sector.h b/Detectors/TPC/base/include/TPCBase/Sector.h index 19a492f4a45b1..4a4fde29ff4ae 100644 --- a/Detectors/TPC/base/include/TPCBase/Sector.h +++ b/Detectors/TPC/base/include/TPCBase/Sector.h @@ -40,7 +40,7 @@ class Sector { public: // the number of sectors - static constexpr int MAXSECTOR = Constants::MAXSECTOR; + static constexpr int MAXSECTOR = constants::MAXSECTOR; /// constructor Sector() = default; diff --git a/Detectors/TPC/base/src/ZeroSuppress.cxx b/Detectors/TPC/base/src/ZeroSuppress.cxx index 100a9c5671e14..70cb7ca21b6c2 100644 --- a/Detectors/TPC/base/src/ZeroSuppress.cxx +++ b/Detectors/TPC/base/src/ZeroSuppress.cxx @@ -27,6 +27,7 @@ #include "DataFormatsTPC/Helpers.h" using namespace o2::tpc; +using namespace o2::tpc::constants; void ZeroSuppress::process() { @@ -62,7 +63,7 @@ void ZeroSuppress::DecodeZSPages(gsl::span<const ZeroSuppressedContainer8kb>* z0 const o2::header::RAWDataHeader* rdh = (const o2::header::RAWDataHeader*)&inputPage; auto orbit = o2::raw::RDHUtils::getHeartBeatOrbit(rdh); - int timeBin = (_timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / Constants::LHCBCPERTIMEBIN; + int timeBin = (_timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN; unsigned int ct = 0; startPtr += (sizeof(z0Container->rdh) + sizeof(z0Container->hdr)); // move to first time bin diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibParam.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibParam.h index 48ad4eb80cb4b..4f1eeb9be16bb 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibParam.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibParam.h @@ -51,7 +51,7 @@ static constexpr float RowX[NPadRows] = { ///< x-posi #else // not defined TPC_RUN2 /// TPC geometric constants for Run 3+ -static constexpr int NPadRows = o2::tpc::Constants::MAXGLOBALPADROW; +static constexpr int NPadRows = o2::tpc::constants::MAXGLOBALPADROW; static constexpr int NROCTypes = 4; static constexpr int NRowsPerROC[NROCTypes] = {63, 34, 30, 25}; static constexpr int NRowsAccumulated[NROCTypes] = {63, 97, 127, 152}; diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h index fed4d99745a02..0ff93475cb93e 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h @@ -197,7 +197,7 @@ class TrackInterpolation std::vector<TPCClusterResiduals> mClRes{}; ///< residuals for each available TPC cluster of all tracks // cache - std::array<CacheStruct, Constants::MAXGLOBALPADROW> mCache{{}}; ///< caching positions, covariances and angles for track extrapolations and interpolation + std::array<CacheStruct, constants::MAXGLOBALPADROW> mCache{{}}; ///< caching positions, covariances and angles for track extrapolations and interpolation // helpers std::unique_ptr<TPCFastTransform> mFastTransform{}; ///< TPC cluster transformation diff --git a/Detectors/TPC/qc/macro/runClusters.C b/Detectors/TPC/qc/macro/runClusters.C index 242c093f7ced8..62c3df227c4af 100644 --- a/Detectors/TPC/qc/macro/runClusters.C +++ b/Detectors/TPC/qc/macro/runClusters.C @@ -38,8 +38,8 @@ void runClusters(std::string_view outputFile = "ClusterQC.root", std::string_vie tpcClusterReader.read(i); tpcClusterReader.fillIndex(clusterIndex, clusterBuffer, clusterMCBuffer); size_t iClusters = 0; - for (int isector = 0; isector < Constants::MAXSECTOR; ++isector) { - for (int irow = 0; irow < Constants::MAXGLOBALPADROW; ++irow) { + for (int isector = 0; isector < constants::MAXSECTOR; ++isector) { + for (int irow = 0; irow < constants::MAXGLOBALPADROW; ++irow) { const int nClusters = clusterIndex.nClusters[isector][irow]; if (!nClusters) { continue; @@ -57,4 +57,4 @@ void runClusters(std::string_view outputFile = "ClusterQC.root", std::string_vie } clusters.analyse(); clusters.dumpToFile(outputFile.data()); -} \ No newline at end of file +} diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h index 1efcb10e7a5dd..7023025781622 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h @@ -55,7 +55,7 @@ class DigitalCurrentClusterIntegrator void reset(); //Free all allocated current buffers private: - std::unique_ptr<unsigned long long int[]> mIntegratedCurrents[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW]; + std::unique_ptr<unsigned long long int[]> mIntegratedCurrents[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; }; } // namespace tpc diff --git a/Detectors/TPC/reconstruction/src/DigitalCurrentClusterIntegrator.cxx b/Detectors/TPC/reconstruction/src/DigitalCurrentClusterIntegrator.cxx index fff40b59221ce..23e53d0817058 100644 --- a/Detectors/TPC/reconstruction/src/DigitalCurrentClusterIntegrator.cxx +++ b/Detectors/TPC/reconstruction/src/DigitalCurrentClusterIntegrator.cxx @@ -14,11 +14,12 @@ #include "TPCReconstruction/DigitalCurrentClusterIntegrator.h" using namespace o2::tpc; +using namespace o2::tpc::constants; void DigitalCurrentClusterIntegrator::clear() { - for (int i = 0; i < Constants::MAXSECTOR; i++) { - for (int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (int i = 0; i < MAXSECTOR; i++) { + for (int j = 0; j < MAXGLOBALPADROW; j++) { if (mIntegratedCurrents[i][j]) { int nPads = Mapper::instance().getNumberOfPadsInRowSector(j); memset(&mIntegratedCurrents[i][j][0], 0, nPads * sizeof(mIntegratedCurrents[i][j][0])); @@ -29,8 +30,8 @@ void DigitalCurrentClusterIntegrator::clear() void DigitalCurrentClusterIntegrator::reset() { - for (int i = 0; i < Constants::MAXSECTOR; i++) { - for (int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (int i = 0; i < MAXSECTOR; i++) { + for (int j = 0; j < MAXGLOBALPADROW; j++) { mIntegratedCurrents[i][j].reset(nullptr); } } diff --git a/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx b/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx index bd14d2002e827..cf3a326e29eab 100644 --- a/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx +++ b/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx @@ -47,10 +47,10 @@ int HardwareClusterDecoder::decodeClusters(std::vector<std::pair<const ClusterHa } ClusterNative* outputClusterBuffer = nullptr; // the number of clusters in a {sector,row} - int nRowClusters[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW] = {0}; + int nRowClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW] = {0}; // offset of first cluster of {sector,row} in the output buffer - size_t clusterOffsets[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW] = {0}; - int containerRowCluster[Constants::MAXSECTOR][Constants::MAXGLOBALPADROW] = {0}; + size_t clusterOffsets[constants::MAXSECTOR][constants::MAXGLOBALPADROW] = {0}; + int containerRowCluster[constants::MAXSECTOR][constants::MAXGLOBALPADROW] = {0}; Mapper& mapper = Mapper::instance(); int numberOfOutputContainers = 0; for (int loop = 0; loop < 2; loop++) { @@ -105,8 +105,8 @@ int HardwareClusterDecoder::decodeClusters(std::vector<std::pair<const ClusterHa } if (loop == 1) { //We are done with filling the buffers, sort all output buffers - for (int i = 0; i < Constants::MAXSECTOR; i++) { - for (int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (int i = 0; i < constants::MAXSECTOR; i++) { + for (int j = 0; j < constants::MAXGLOBALPADROW; j++) { if (nRowClusters[i][j] == 0) { continue; } @@ -129,8 +129,8 @@ int HardwareClusterDecoder::decodeClusters(std::vector<std::pair<const ClusterHa outputClusterBuffer = reinterpret_cast<ClusterNative*>(rawOutputBuffer + sizeof(ClusterCountIndex)); nTotalClusters = 0; numberOfOutputContainers = 0; - for (int i = 0; i < Constants::MAXSECTOR; i++) { - for (int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (int i = 0; i < constants::MAXSECTOR; i++) { + for (int j = 0; j < constants::MAXGLOBALPADROW; j++) { clusterCounts.nClusters[i][j] = nRowClusters[i][j]; if (nRowClusters[i][j] == 0) { continue; @@ -149,8 +149,8 @@ int HardwareClusterDecoder::decodeClusters(std::vector<std::pair<const ClusterHa if (outMCLabels) { auto& labels = *outMCLabels; int nCls = 0; - for (int i = 0; i < Constants::MAXSECTOR; i++) { - for (int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (int i = 0; i < constants::MAXSECTOR; i++) { + for (int j = 0; j < constants::MAXGLOBALPADROW; j++) { if (nRowClusters[i][j] == 0) { continue; } diff --git a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx index 8b7037120aecf..162d94d7de3e6 100644 --- a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx @@ -78,9 +78,9 @@ BOOST_AUTO_TEST_CASE(CATracking_test1) config.configCalib.dEdxSplines = dEdxSplines.get(); tracker.initialize(config); - std::vector<ClusterNativeContainer> cont(Constants::MAXGLOBALPADROW); + std::vector<ClusterNativeContainer> cont(constants::MAXGLOBALPADROW); - for (int i = 0; i < Constants::MAXGLOBALPADROW; i++) { + for (int i = 0; i < constants::MAXGLOBALPADROW; i++) { cont[i].sector = 0; cont[i].globalPadRow = i; cont[i].clusters.resize(1); diff --git a/Detectors/TPC/simulation/src/SpaceCharge.cxx b/Detectors/TPC/simulation/src/SpaceCharge.cxx index 6cc7d8b141f98..8af0e6027ce99 100644 --- a/Detectors/TPC/simulation/src/SpaceCharge.cxx +++ b/Detectors/TPC/simulation/src/SpaceCharge.cxx @@ -28,6 +28,7 @@ #include "TPCSimulation/SpaceCharge.h" using namespace o2::tpc; +using namespace o2::tpc::constants; using namespace o2::math_utils; const float o2::tpc::SpaceCharge::sEzField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; @@ -35,23 +36,23 @@ const float o2::tpc::SpaceCharge::sEzField = (AliTPCPoissonSolver::fgkCathodeV - SpaceCharge::SpaceCharge() : mNZ(MaxNZ), mNPhi(MaxNPhi), - mNR(Constants::MAXGLOBALPADROW), + mNR(MAXGLOBALPADROW), mVoxelSizeZ(AliTPCPoissonSolver::fgkTPCZ0 / (MaxNZ - 1)), mDriftTimeVoxel(IonDriftTime / (MaxNZ - 1)), mVoxelSizePhi(TWOPI / MaxNPhi), - mVoxelSizeR((AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (Constants::MAXGLOBALPADROW - 1)), + mVoxelSizeR((AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (MAXGLOBALPADROW - 1)), mCoordZ(MaxNZ), mCoordPhi(MaxNPhi), - mCoordR(Constants::MAXGLOBALPADROW), + mCoordR(MAXGLOBALPADROW), mInterpolationOrder(2), mUseInitialSCDensity(false), mInitLookUpTables(false), mMemoryAllocated(false), mTimeInit(-1), mSCDistortionType(SpaceCharge::SCDistortionType::SCDistortionsRealistic), - mLookUpTableCalculator(Constants::MAXGLOBALPADROW, MaxNZ, MaxNPhi, 2, 3, 0), - mSpaceChargeDensityA(MaxNPhi * Constants::MAXGLOBALPADROW * MaxNZ), - mSpaceChargeDensityC(MaxNPhi * Constants::MAXGLOBALPADROW * MaxNZ), + mLookUpTableCalculator(MAXGLOBALPADROW, MaxNZ, MaxNPhi, 2, 3, 0), + mSpaceChargeDensityA(MaxNPhi * MAXGLOBALPADROW * MaxNZ), + mSpaceChargeDensityC(MaxNPhi * MAXGLOBALPADROW * MaxNZ), mRandomFlat(RandomRing<>::RandomType::Flat) { mLookUpTableCalculator.SetCorrectionType(0); diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 1c1c7d68dd32d..65704838d091d 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -120,7 +120,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int config.configInterface.dumpEvents = confParam.dump; if (config.configEvent.continuousMaxTimeBin == -1) { - config.configEvent.continuousMaxTimeBin = (o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * o2::constants::lhc::LHCMaxBunches + 2 * Constants::LHCBCPERTIMEBIN - 2) / Constants::LHCBCPERTIMEBIN; + config.configEvent.continuousMaxTimeBin = (o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * o2::constants::lhc::LHCMaxBunches + 2 * constants::LHCBCPERTIMEBIN - 2) / constants::LHCBCPERTIMEBIN; } if (config.configProcessing.deviceNum == -2) { int myId = ic.services().get<const o2::framework::DeviceSpec>().inputTimesliceId; diff --git a/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx b/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx index 8b90c2d4ac835..c09db2c6395dd 100644 --- a/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx +++ b/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx @@ -67,8 +67,8 @@ std::unique_ptr<VisualisationEvent> DataInterpreterTPC::interpretDataForType(TOb const auto& mapper = tpc::Mapper::instance(); const auto& clusterRefs = access->clusters; - for (int sector = 0; sector < o2::tpc::Constants::MAXSECTOR; sector++) { - for (int row = 0; row < o2::tpc::Constants::MAXGLOBALPADROW; row++) { + for (int sector = 0; sector < o2::tpc::constants::MAXSECTOR; sector++) { + for (int row = 0; row < o2::tpc::constants::MAXGLOBALPADROW; row++) { const auto& c = clusterRefs[sector][row]; const auto pad = mapper.globalPadNumber(tpc::PadPos(row, c->getPad())); diff --git a/GPU/Common/GPUDefConstantsAndSettings.h b/GPU/Common/GPUDefConstantsAndSettings.h index 0d7b9b004508c..e298cb51e8631 100644 --- a/GPU/Common/GPUDefConstantsAndSettings.h +++ b/GPU/Common/GPUDefConstantsAndSettings.h @@ -61,8 +61,8 @@ #if defined(HAVE_O2HEADERS) && (!defined(__OPENCL__) || defined(__OPENCLCPP__)) && !(defined(ROOT_VERSION_CODE) && ROOT_VERSION_CODE < 393216) //Use definitions from the O2 headers if available for nicer code and type safety #include "DataFormatsTPC/Constants.h" - #define GPUCA_NSLICES o2::tpc::Constants::MAXSECTOR - #define GPUCA_ROW_COUNT o2::tpc::Constants::MAXGLOBALPADROW + #define GPUCA_NSLICES o2::tpc::constants::MAXSECTOR + #define GPUCA_ROW_COUNT o2::tpc::constants::MAXGLOBALPADROW #else //Define it manually, if O2 headers not available, ROOT5, and OpenCL 1.2, which do not know C++11. #define GPUCA_NSLICES 36 diff --git a/GPU/GPUTracking/Base/GPUHostDataTypes.h b/GPU/GPUTracking/Base/GPUHostDataTypes.h index 0f90719ccbfc5..c09116b11efdb 100644 --- a/GPU/GPUTracking/Base/GPUHostDataTypes.h +++ b/GPU/GPUTracking/Base/GPUHostDataTypes.h @@ -38,7 +38,7 @@ namespace gpu { struct GPUTPCDigitsMCInput { - std::array<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*, o2::tpc::Constants::MAXSECTOR> v; + std::array<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*, o2::tpc::constants::MAXSECTOR> v; }; struct GPUTPCClusterMCInterim { diff --git a/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx b/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx index 9cb9c13061f8e..316da974137b0 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx @@ -40,6 +40,7 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; +using namespace o2::tpc::constants; void GPUReconstructionConvert::ConvertNativeToClusterData(o2::tpc::ClusterNativeAccess* native, std::unique_ptr<GPUTPCClusterData[]>* clusters, unsigned int* nClusters, const TPCFastTransform* transform, int continuousMaxTimeBin) { @@ -160,7 +161,7 @@ int GPUReconstructionConvert::GetMaxTimeBin(const GPUTrackingInOutZS& zspages) for (unsigned int l = 0; l < zspages.slice[i].nZSPtr[j][k]; l++) { RAWDataHeaderGPU* rdh = (RAWDataHeaderGPU*)(page + l * TPCZSHDR::TPC_ZS_PAGE_SIZE); TPCZSHDR* hdr = (TPCZSHDR*)(page + l * TPCZSHDR::TPC_ZS_PAGE_SIZE + sizeof(RAWDataHeaderGPU)); - unsigned int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / Constants::LHCBCPERTIMEBIN + hdr->nTimeBins; + unsigned int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN + hdr->nTimeBins; if (timeBin > retVal) { retVal = timeBin; } @@ -308,7 +309,7 @@ void GPUReconstructionConvert::RunZSEncoder(const S& in, std::unique_ptr<unsigne lastEndpoint = -1; } if (ZSEncoderGetTime(tmpBuffer[k]) != lastTime) { - nexthbf = ((long)ZSEncoderGetTime(tmpBuffer[k]) * Constants::LHCBCPERTIMEBIN + bcShiftInFirstHBF) / o2::constants::lhc::LHCMaxBunches; + nexthbf = ((long)ZSEncoderGetTime(tmpBuffer[k]) * LHCBCPERTIMEBIN + bcShiftInFirstHBF) / o2::constants::lhc::LHCMaxBunches; if (hbf != nexthbf) { lastEndpoint = -2; } @@ -389,7 +390,7 @@ void GPUReconstructionConvert::RunZSEncoder(const S& in, std::unique_ptr<unsigne hdr->cruID = i * 10 + region; rawcru = i * 10 + region; rawendpoint = endpoint & 1; - hdr->timeOffset = ZSEncoderGetTime(tmpBuffer[k]) * Constants::LHCBCPERTIMEBIN - (hbf - 0) * o2::constants::lhc::LHCMaxBunches; + hdr->timeOffset = ZSEncoderGetTime(tmpBuffer[k]) * LHCBCPERTIMEBIN - (hbf - 0) * o2::constants::lhc::LHCMaxBunches; lastTime = -1; tbHdr = nullptr; lastEndpoint = endpoint; @@ -474,7 +475,7 @@ void GPUReconstructionConvert::RunZSEncoder(const S& in, std::unique_ptr<unsigne } int nRowsRegion = param.tpcGeometry.GetRegionRows(region); - int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstOrbit) * o2::constants::lhc::LHCMaxBunches) / Constants::LHCBCPERTIMEBIN; + int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstOrbit) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN; for (int l = 0; l < hdr->nTimeBins; l++) { if ((pagePtr - reinterpret_cast<unsigned char*>(page)) & 1) { pagePtr++; diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index e8fe1b78a05f4..6c637938a09d9 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -70,6 +70,7 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; using namespace o2::trd; +using namespace o2::tpc::constants; namespace GPUCA_NAMESPACE { @@ -483,7 +484,7 @@ std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCo continue; } const TPCZSHDR* const hdr = (const TPCZSHDR*)(page + sizeof(RAWDataHeaderGPU)); - unsigned int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / Constants::LHCBCPERTIMEBIN; + unsigned int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN; for (unsigned int m = 0; m < 2; m++) { CfFragment& fm = m ? fNext : f; if (timeBin + hdr->nTimeBins >= (unsigned int)fm.first() && timeBin < (unsigned int)fm.last() && !fm.isEnd()) { @@ -1265,7 +1266,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) bool anyLaneHasData = false; for (int lane = 0; lane < GetProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { unsigned int iSlice = iSliceBase + lane; - std::fill(&tmpNative->nClusters[iSlice][0], &tmpNative->nClusters[iSlice][0] + tpc::Constants::MAXGLOBALPADROW, 0); + std::fill(&tmpNative->nClusters[iSlice][0], &tmpNative->nClusters[iSlice][0] + MAXGLOBALPADROW, 0); SynchronizeStream(lane); GPUTPCClusterFinder& clusterer = processors()->tpcClusterer[iSlice]; GPUTPCClusterFinder& clustererShadow = doGPU ? processorsShadow()->tpcClusterer[iSlice] : clusterer; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index 24c1f2459b00f..97e61ef7b294a 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -107,8 +107,8 @@ struct GPUO2InterfaceConfiguration { struct GPUO2InterfaceIOPtrs { // Input: TPC clusters in cluster native format, or digits, or list of ZS pages - const as it can only be input const o2::tpc::ClusterNativeAccess* clusters = nullptr; - const std::array<gsl::span<const o2::tpc::Digit>, o2::tpc::Constants::MAXSECTOR>* o2Digits = nullptr; - std::array<std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>>, o2::tpc::Constants::MAXSECTOR>* o2DigitsMC = nullptr; + const std::array<gsl::span<const o2::tpc::Digit>, o2::tpc::constants::MAXSECTOR>* o2Digits = nullptr; + std::array<std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>>, o2::tpc::constants::MAXSECTOR>* o2DigitsMC = nullptr; const o2::gpu::GPUTrackingInOutZS* tpcZS = nullptr; // Input / Output for Merged TPC tracks, two ptrs, for the tracks themselves, and for the MC labels. diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx index fcdeb2d608481..6314fff368122 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx @@ -24,6 +24,7 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace GPUCA_NAMESPACE::gpu::tpccf; using namespace o2::tpc; +using namespace o2::tpc::constants; template <> GPUdii() void GPUTPCCFDecodeZS::Thread<GPUTPCCFDecodeZS::decodeZS>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, int firstHBF) @@ -87,7 +88,7 @@ GPUdii() void GPUTPCCFDecodeZS::decode(GPUTPCClusterFinder& clusterer, GPUShared const unsigned int decodeBits = decode12bit ? TPCZSHDR::TPC_ZS_NBITS_V2 : TPCZSHDR::TPC_ZS_NBITS_V1; const float decodeBitsFactor = 1.f / (1 << (decodeBits - 10)); unsigned int mask = (1 << decodeBits) - 1; - int timeBin = (hdr->timeOffset + (GPURawDataUtils::getOrbit(rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / Constants::LHCBCPERTIMEBIN; + int timeBin = (hdr->timeOffset + (GPURawDataUtils::getOrbit(rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN; const int rowOffset = s.regionStartRow + ((endpoint & 1) ? (s.nRowsRegion / 2) : 0); const int nRows = (endpoint & 1) ? (s.nRowsRegion - s.nRowsRegion / 2) : (s.nRowsRegion / 2); diff --git a/macro/runCATrackingClusterNative.C b/macro/runCATrackingClusterNative.C index 1f8efc1837eaa..f31c79917982b 100644 --- a/macro/runCATrackingClusterNative.C +++ b/macro/runCATrackingClusterNative.C @@ -74,8 +74,8 @@ int runCATrackingClusterNative(TString inputFile, TString outputFile) bool doMC = true; TFile fin(inputFile); - for (int i = 0; i < Constants::MAXSECTOR; i++) { - for (int j = 0; j < Constants::MAXGLOBALPADROW; j++) { + for (int i = 0; i < o2::tpc::constants::MAXSECTOR; i++) { + for (int j = 0; j < o2::tpc::constants::MAXGLOBALPADROW; j++) { TString contName = Form("clusters_sector_%d_row_%d", i, j); TObject* tmp = fin.FindObjectAny(contName); if (tmp == nullptr) { From b3799c602ccc7953d7f00d6195f7ad6b19816935 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Fri, 14 Aug 2020 11:24:19 +0200 Subject: [PATCH 0360/1751] [EMCAL-646] Fix encoding of the RCU trailer - Trailer marker (2<<30) added to trailer words during encoding - CaloRawFitterGamma2 added to reconstruction LinkDef - Fix test macro for raw fitter --- Detectors/EMCAL/base/src/RCUTrailer.cxx | 16 ++++++------- .../reconstruction/macros/RawFitterTESTs.C | 24 ++++++++++++------- .../src/EMCALReconstructionLinkDef.h | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Detectors/EMCAL/base/src/RCUTrailer.cxx b/Detectors/EMCAL/base/src/RCUTrailer.cxx index 4188c1de80561..11e3a8313d57d 100644 --- a/Detectors/EMCAL/base/src/RCUTrailer.cxx +++ b/Detectors/EMCAL/base/src/RCUTrailer.cxx @@ -154,14 +154,14 @@ void RCUTrailer::setL1Phase(double l1phase) std::vector<uint32_t> RCUTrailer::encode() const { std::vector<uint32_t> encoded; - encoded.emplace_back(mPayloadSize); - encoded.emplace_back(mAltroCFG2 | 7 << 26); - encoded.emplace_back(mAltroCFG1 | 6 << 26); - encoded.emplace_back(mActiveFECsB | 5 << 26); - encoded.emplace_back(mActiveFECsA | 4 << 26); - encoded.emplace_back(mERRREG3 | 3 << 26); - encoded.emplace_back(mERRREG2 | 2 << 26); - encoded.emplace_back(mFECERRB >> 7 | (mFECERRA >> 7) << 13 | 1 << 26); + encoded.emplace_back(mPayloadSize | 2 << 30); + encoded.emplace_back(mAltroCFG2 | 7 << 26 | 2 << 30); + encoded.emplace_back(mAltroCFG1 | 6 << 26 | 2 << 30); + encoded.emplace_back(mActiveFECsB | 5 << 26 | 2 << 30); + encoded.emplace_back(mActiveFECsA | 4 << 26 | 2 << 30); + encoded.emplace_back(mERRREG3 | 3 << 26 | 2 << 30); + encoded.emplace_back(mERRREG2 | 2 << 26 | 2 << 30); + encoded.emplace_back(mFECERRB >> 7 | (mFECERRA >> 7) << 13 | 1 << 26 | 2 << 30); uint32_t lasttrailerword = 3 << 30 | mFirmwareVersion << 16 | mRCUId << 7 | (encoded.size() + 1); encoded.emplace_back(lasttrailerword); diff --git a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C index deb09a48db3fd..dca05281523ad 100644 --- a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C +++ b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C @@ -16,6 +16,7 @@ #include "RStringView.h" #include <Rtypes.h> #include "DetectorsRaw/RawFileReader.h" +#include "DetectorsRaw/RDHUtils.h" #include "EMCALReconstruction/CaloFitResults.h" #include "EMCALReconstruction/Bunch.h" #include "EMCALReconstruction/CaloRawFitterStandard.h" @@ -27,23 +28,27 @@ using namespace o2::emcal; /// \brief Testing the standard raw fitter on run2 to run3 converted data -void RawFitterTESTs() +void RawFitterTESTs(const char* filename = "") { const Int_t NoiseThreshold = 3; - // Use the RawReaderFile to read the raw data file - const char* aliceO2env = std::getenv("O2_ROOT"); - std::string inputDir = " "; - if (aliceO2env) - inputDir = aliceO2env; - inputDir += "/share/Detectors/EMC/files/"; + std::string inputfile = filename; + if (!inputfile.length()) { + // Use the RawReaderFile to read the raw data file + const char* aliceO2env = std::getenv("O2_ROOT"); + std::string inputDir = " "; + if (aliceO2env) + inputDir = aliceO2env; + inputDir += "/share/Detectors/EMC/files/"; + inputfile = inputDir + "emcal.raw"; + } o2::raw::RawFileReader reader; reader.setDefaultDataOrigin(o2::header::gDataOriginEMC); reader.setDefaultDataDescription(o2::header::gDataDescriptionRawData); reader.setDefaultReadoutCardType(o2::raw::RawFileReader::RORC); - reader.addFile(inputDir + "emcal.raw"); + reader.addFile(inputfile.data()); reader.init(); // define the standard raw fitter @@ -55,7 +60,7 @@ void RawFitterTESTs() while (1) { int tfID = reader.getNextTFToRead(); if (tfID >= reader.getNTimeFrames()) { - std::cerr << "nothing left to read after " << tfID << " TFs read"; + std::cerr << "nothing left to read after " << tfID << " TFs read" << std::endl; break; } std::vector<char> dataBuffer; // where to put extracted data @@ -92,5 +97,6 @@ void RawFitterTESTs() } } } + reader.setNextTFToRead(++tfID); } } diff --git a/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h b/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h index 2a5f25a56e4c0..3267e83f6d89f 100644 --- a/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h +++ b/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h @@ -14,7 +14,6 @@ #pragma link off all classes; #pragma link off all functions; - #pragma link C++ class o2::emcal::RawReaderMemory + ; #pragma link C++ class o2::emcal::AltroDecoder + ; #pragma link C++ class o2::emcal::RawPayload + ; @@ -23,6 +22,7 @@ #pragma link C++ class o2::emcal::CaloFitResults + ; #pragma link C++ class o2::emcal::CaloRawFitter + ; #pragma link C++ class o2::emcal::CaloRawFitterStandard + ; +#pragma link C++ class o2::emcal::CaloRawFitterGamma2 + ; //#pragma link C++ namespace o2::emcal+; #pragma link C++ class o2::emcal::ClusterizerParameters + ; From 1fb35a277e8093e06f3f5dfefa58b549a0ba8c05 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Aug 2020 15:23:51 +0200 Subject: [PATCH 0361/1751] Avoid non-const reference to bitfield --- DataFormats/Detectors/TRD/src/RawData.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index 7bb3e82973ef5..2583757d45052 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -96,13 +96,13 @@ std::ostream& operator<<(std::ostream& stream, const TrackletMCMData& tracklet) << tracklet.checkbit << std::endl; return stream; } -void printTrackletMCMData(o2::trd::TrackletMCMData& tracklet) +void printTrackletMCMData(o2::trd::TrackletMCMData const& tracklet) { LOGF(INFO, "TrackletMCMData: Raw:0x%08x pos:%d slope:%d pid:0x%08x checkbit:0x%02x", tracklet.word, tracklet.pos, tracklet.slope, tracklet.pid, tracklet.checkbit); } -void printTrackletMCMHeader(o2::trd::TrackletMCMHeader& mcmhead) +void printTrackletMCMHeader(o2::trd::TrackletMCMHeader const& mcmhead) { LOGF(INFO, "MCMRawHeader: Raw:0x%08x 1:%d padrow: 0x%02x col: 0x%01x pid2 0x%02x pid1: 0x%02x pid0: 0x%02x 1:%d", mcmhead.word, mcmhead.onea, mcmhead.padrow, mcmhead.col, @@ -118,18 +118,18 @@ std::ostream& operator<<(std::ostream& stream, const TrackletMCMHeader& mcmhead) return stream; } -void printHalfChamber(o2::trd::TrackletHCHeader& halfchamber) +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); } -void dumpHalfChamber(o2::trd::TrackletHCHeader& halfchamber) +void dumpHalfChamber(o2::trd::TrackletHCHeader const& halfchamber) { LOGF(INFO, "HalfChamber : 0x%08x", halfchamber.word); } -void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) +void printHalfCRUHeader(o2::trd::HalfCRUHeader const& halfcru) { std::array<uint32_t, 15> sizes; std::array<uint32_t, 15> errorflags; From 32004701c9e79e235216235361d39c163f81df42 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Aug 2020 10:42:19 +0200 Subject: [PATCH 0362/1751] DPL: make Configuration a Global services --- Framework/Core/src/DataProcessingDevice.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index b2fd9b69dc2dd..61e63fea3c048 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -75,6 +75,11 @@ constexpr int BACKOFF_DELAY_STEP = 100; namespace o2::framework { +template <> +struct ServiceKindExtractor<ConfigurationInterface> { + constexpr static ServiceKind kind = ServiceKind::Global; +}; + /// We schedule a timer to reduce CPU usage. /// Watching stdin for commands probably a better approach. void idle_timer(uv_timer_t* handle) From 3db96b3240716e8460895eec85841987ce918451 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 10 Aug 2020 22:28:19 +0200 Subject: [PATCH 0363/1751] DPL: make InfoLoggerContext a global service --- Framework/Core/src/CommonServices.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 6b08496ba7046..8ef19771c09d5 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -46,6 +46,13 @@ using Value = o2::monitoring::tags::Value; namespace o2::framework { + +/// This is a global service because read only +template <> +struct ServiceKindExtractor<InfoLoggerContext> { + constexpr static ServiceKind kind = ServiceKind::Global; +}; + o2::framework::ServiceSpec CommonServices::monitoringSpec() { return ServiceSpec{"monitoring", From 22f0fb120e52e0703f77612cd410cf688e645f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:18:33 +0200 Subject: [PATCH 0364/1751] Fix momentum column (#4153) --- Framework/Core/include/Framework/AnalysisDataModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index eadce4cf050ec..f28bdca35311e 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -117,7 +117,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float signed1Pt, float tgl) -> float { return pt * tgl; }); -DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, nsqrt((1.f + aod::track::tgl * aod::track::tgl) / nabs(aod::track::signed1Pt))); +DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, 0.5f * (ntan(0.25f * static_cast<float>(M_PI) - 0.5f * natan(aod::track::tgl)) + 1.f / ntan(0.25f * static_cast<float>(M_PI) - 0.5f * natan(aod::track::tgl))) / nabs(aod::track::signed1Pt)); // TRACKPARCOV TABLE definition DECLARE_SOA_COLUMN(SigmaY, sigmaY, float); From 96c25d43133bf195bf073d435453d3d7b197abcc Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Fri, 14 Aug 2020 20:46:26 +0200 Subject: [PATCH 0365/1751] Revert alias namespace workaround for QC build --- .../Detectors/TPC/include/DataFormatsTPC/Constants.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h index 3090b0082bdf7..a7d4c6c410975 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Constants.h @@ -36,14 +36,6 @@ constexpr int MAXGLOBALPADROW = 152; // Correct number of pad rows in Run 3 // number of LHC bunch crossings per TPC time bin (40 MHz / 5 MHz) constexpr int LHCBCPERTIMEBIN = 8; } // namespace constants - -// FIXME: Temporary workaround to not break the QC build which depends on the removed class o2::tpc::Constants -// Once https://github.com/AliceO2Group/QualityControl/pull/459 is merged this can be removed -namespace Constants -{ -using namespace constants; -} - } // namespace tpc } // namespace o2 From 1c9d1231f92026f873aad479c38e690205251c9b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Aug 2020 19:31:40 +0200 Subject: [PATCH 0366/1751] DPL: improve data relayer GUI Trying to debug threading issue with DataRelayer itself. --- Framework/Core/src/DataRelayer.cxx | 1 - .../Core/src/FrameworkGUIDataRelayerUsage.cxx | 18 ++++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index 29e241a0caed9..ec40a61048e1e 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -43,7 +43,6 @@ constexpr int INVALID_INPUT = -1; // The number should really be tuned at runtime for each processor. constexpr int DEFAULT_PIPELINE_LENGTH = 16; -// FIXME: do we really need to pass the forwards? DataRelayer::DataRelayer(const CompletionPolicy& policy, std::vector<InputRoute> const& routes, monitoring::Monitoring& metrics, diff --git a/Framework/Core/src/FrameworkGUIDataRelayerUsage.cxx b/Framework/Core/src/FrameworkGUIDataRelayerUsage.cxx index 0534afb3dd974..0a5b5e865793d 100644 --- a/Framework/Core/src/FrameworkGUIDataRelayerUsage.cxx +++ b/Framework/Core/src/FrameworkGUIDataRelayerUsage.cxx @@ -17,11 +17,7 @@ static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); } static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } -namespace o2 -{ -namespace framework -{ -namespace gui +namespace o2::framework::gui { // This is to display the information in the data relayer @@ -137,14 +133,18 @@ void displayDataRelayer(DeviceMetricsInfo const& metrics, }; auto describeCell = [&metrics, &variablesIndex, &queriesIndex](int input, int slot) -> void { ImGui::BeginTooltip(); + ImGui::Text("Input query matched values for slot: %d", slot); for (size_t vi = 0; vi < variablesIndex.w; ++vi) { auto idx = (slot * variablesIndex.w) + vi; assert(idx < variablesIndex.indexes.size()); MetricInfo const& metricInfo = metrics.metrics[variablesIndex.indexes[idx]]; assert(metricInfo.storeIdx < metrics.stringMetrics.size()); - //assert(metricInfo.type == MetricType::String); auto& data = metrics.stringMetrics[metricInfo.storeIdx]; - ImGui::Text("$%zu: %s", vi, data[(metricInfo.pos - 1) % data.size()].data); + if (vi == 0) { + ImGui::Text("$%zu (timeslice): %s", vi, data[(metricInfo.pos - 1) % data.size()].data); + } else { + ImGui::Text("$%zu: %s", vi, data[(metricInfo.pos - 1) % data.size()].data); + } } ImGui::EndTooltip(); }; @@ -162,6 +162,4 @@ void displayDataRelayer(DeviceMetricsInfo const& metrics, } } -} // namespace gui -} // namespace framework -} // namespace o2 +} // namespace o2::framework::gui From d97c5d4fb9bd739aaf7c538f407ee1d80dec2b98 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 15 Aug 2020 00:29:16 +0200 Subject: [PATCH 0367/1751] DPL: demote message to debug --- Framework/Core/src/runDataProcessing.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 98e2cd1139f0c..3e5311d114024 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -755,7 +755,7 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f /// Create all the requested services and initialise them for (auto& service : spec.services) { - LOG(info) << "Declaring service " << service.name; + LOG(debug) << "Declaring service " << service.name; serviceRegistry.declareService(service, *deviceState.get(), r.fConfig); } if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(spec.resourceMonitoringInterval)) { From 7c43a8ad1b435ffaf09db8c3cee7e2ded69ae204 Mon Sep 17 00:00:00 2001 From: saganatt <8majak8@gmail.com> Date: Sat, 15 Aug 2020 08:31:30 +0200 Subject: [PATCH 0368/1751] DPL Analysis: Extended histogram registry to use TH2 and TH3 (#4063) --- .../include/Framework/HistogramRegistry.h | 139 ++++++++++++++++-- .../Core/test/benchmark_HistogramRegistry.cxx | 2 +- .../Core/test/test_HistogramRegistry.cxx | 6 +- 3 files changed, 129 insertions(+), 18 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 75ca56a0eea43..6ad5db6d480de 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -32,31 +32,66 @@ namespace o2 namespace framework { +// Most common histogram types +enum HistogramType { + kTH1D, + kTH1F, + kTH1I, + kTH2D, + kTH2F, + kTH2I, + kTH3D, + kTH3F, + kTH3I +}; + +/// Description of a single histogram axis +struct AxisSpec { + AxisSpec(int nBins_, std::vector<double> bins_, std::string label_ = "") + : nBins(nBins_), + bins(bins_), + binsEqual(false), + label(label_) + { + } + + AxisSpec(int nBins_, double binMin_, double binMax_, std::string label_ = "") + : nBins(nBins_), + bins({binMin_, binMax_}), + binsEqual(true), + label(label_) + { + } + + AxisSpec() : nBins(1), binsEqual(false), bins(), label("") {} + + int nBins; + std::vector<double> bins; + bool binsEqual; // if true, then bins specify min and max for equidistant binning + std::string label; +}; + /// Data sctructure that will allow to construct a fully qualified TH* histogram -/// Currently only supports TH1F struct HistogramConfigSpec { - HistogramConfigSpec(char const* const kind_, unsigned int nBins_, double xmin_, double xmax_) - : kind(kind_), - nBins(nBins_), - xmin(xmin_), - xmax(xmax_) + HistogramConfigSpec(HistogramType type_, std::vector<AxisSpec> axes_) + : type(type_), + axes(axes_), + binsEqual(axes.size() > 0 ? axes[0].binsEqual : false) { } HistogramConfigSpec() - : kind(""), - nBins(1), - xmin(0), - xmax(1) + : type(HistogramType::kTH1F), + axes(), + binsEqual(false) { } HistogramConfigSpec(HistogramConfigSpec const& other) = default; HistogramConfigSpec(HistogramConfigSpec&& other) = default; - std::string kind; - unsigned int nBins; - double xmin; - double xmax; + HistogramType type; + std::vector<AxisSpec> axes; + bool binsEqual; }; /// Data structure containing histogram specification for the HistogramRegistry @@ -86,6 +121,80 @@ struct HistogramSpec { HistogramConfigSpec config; }; +class HistogramFactory +{ + public: + static std::unique_ptr<TH1> create(HistogramSpec& spec) + { + const auto& it = lookup().find(spec.config.type); + if (it == lookup().end()) { + return nullptr; + } + return std::move(it->second->createImpl(spec)); + } + + protected: + static std::map<HistogramType, HistogramFactory*>& lookup() + { + static std::map<HistogramType, HistogramFactory*> histMap; + return histMap; + } + + private: + virtual std::unique_ptr<TH1> createImpl(HistogramSpec const& spec) = 0; +}; + +template <typename T> +class HistogramFactoryImpl : public HistogramFactory +{ + public: + HistogramFactoryImpl(HistogramType type) + : position(this->lookup().insert(std::make_pair(type, this)).first) + { + } + + ~HistogramFactoryImpl() + { + this->lookup().erase(position); + } + + private: + std::unique_ptr<TH1> createImpl(HistogramSpec const& spec) override + { + if (spec.config.axes.size() == 0) { + throw std::runtime_error("No arguments available in spec to create a histogram"); + } + if constexpr (std::is_base_of_v<TH3, T>) { + if (spec.config.binsEqual) { + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1], spec.config.axes[2].nBins, spec.config.axes[2].bins[0], spec.config.axes[2].bins[1]); + } + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data(), spec.config.axes[2].nBins, spec.config.axes[2].bins.data()); + } else if constexpr (std::is_base_of_v<TH2, T>) { + if (spec.config.binsEqual) { + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1]); + } + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data()); + } else if constexpr (std::is_base_of_v<TH1, T>) { + if (spec.config.binsEqual) { + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1]); + } + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data()); + } + } + + typename std::map<HistogramType, HistogramFactory*>::iterator position; +}; + +HistogramFactoryImpl<TH1D> const hf1d(HistogramType::kTH1D); +HistogramFactoryImpl<TH1F> const hf1f(HistogramType::kTH1F); +HistogramFactoryImpl<TH1I> const hf1i(HistogramType::kTH1I); +HistogramFactoryImpl<TH2D> const hf2d(HistogramType::kTH2D); +HistogramFactoryImpl<TH2F> const hf2f(HistogramType::kTH2F); +HistogramFactoryImpl<TH2I> const hf2i(HistogramType::kTH2I); +HistogramFactoryImpl<TH3D> const hf3d(HistogramType::kTH3D); +HistogramFactoryImpl<TH3F> const hf3f(HistogramType::kTH3F); +HistogramFactoryImpl<TH3I> const hf3i(HistogramType::kTH3I); + /// Histogram registry for an analysis task that allows to define needed histograms /// and serves as the container/wrapper to fill them class HistogramRegistry @@ -148,7 +257,7 @@ class HistogramRegistry for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { if (mRegistryValue[imask(j + i)].get() == nullptr) { mRegistryKey[imask(j + i)] = spec.id; - mRegistryValue[imask(j + i)] = {std::make_unique<TH1F>(spec.name.data(), spec.readableName.data(), spec.config.nBins, spec.config.xmin, spec.config.xmax)}; + mRegistryValue[imask(j + i)] = HistogramFactory::create(spec); lookup += j; return; } diff --git a/Framework/Core/test/benchmark_HistogramRegistry.cxx b/Framework/Core/test/benchmark_HistogramRegistry.cxx index 18c09d1a31f34..f91436dcc4cdd 100644 --- a/Framework/Core/test/benchmark_HistogramRegistry.cxx +++ b/Framework/Core/test/benchmark_HistogramRegistry.cxx @@ -30,7 +30,7 @@ static void BM_HashedNameLookup(benchmark::State& state) state.PauseTiming(); std::vector<HistogramSpec> specs; for (auto i = 0; i < state.range(0); ++i) { - specs.push_back({(boost::format("histo%1%") % (i + 1)).str().c_str(), (boost::format("Histo %1%") % (i + 1)).str().c_str(), {"TH1F", 100, 0, 1}}); + specs.push_back({fmt::format("histo{}", i + 1).c_str(), fmt::format("Histo {}", i + 1).c_str(), {HistogramType::kTH1F, {{100, 0, 1}}}}); } HistogramRegistry registry{"registry", true, specs}; state.ResumeTiming(); diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 5edccb200622c..040f1191a624b 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -19,18 +19,20 @@ using namespace o2::framework; HistogramRegistry foo() { - return {"r", true, {{"histo", "histo", {"TH1F", 100, 0, 1}}}}; + return {"r", true, {{"histo", "histo", {HistogramType::kTH1F, {{100, 0, 1}}}}}}; } BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) { /// Construct a registry object with direct declaration - HistogramRegistry registry{"registry", true, {{"eta", "#Eta", {"TH1F", 100, -2.0, 2.0}}, {"phi", "#Phi", {"TH1D", 102, 0, 2 * M_PI}}, {"pt", "p_{T}", {"TH1D", 1002, -0.01, 50.1}}}}; + HistogramRegistry registry{"registry", true, {{"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}}}}; /// Get histograms by name BOOST_REQUIRE_EQUAL(registry.get("eta")->GetNbinsX(), 100); BOOST_REQUIRE_EQUAL(registry.get("phi")->GetNbinsX(), 102); BOOST_REQUIRE_EQUAL(registry.get("pt")->GetNbinsX(), 1002); + BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsX(), 100); + BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsY(), 100); /// Get a pointer to the histogram auto histo = registry.get("pt").get(); From cb9ebb958f49fd285f24ef9c3ce3eb5b4793c21a Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan <shahor02@users.noreply.github.com> Date: Sun, 16 Aug 2020 09:15:36 +0200 Subject: [PATCH 0369/1751] Set boost parsing style explictily to exclude allow_guessing (#4163) Co-authored-by: shahoian <ruben.shahoyan@cern.ch> --- Framework/Core/src/BoostOptionsRetriever.cxx | 7 +++++-- Framework/Core/src/DeviceSpecHelpers.cxx | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index 4502385de1a9d..e3081aee4b143 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -69,8 +69,11 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> const& specs, }; } - auto parsed = mIgnoreUnknown ? bpo::command_line_parser(mArgc, mArgv).options(mDescription).allow_unregistered().run() - : bpo::parse_command_line(mArgc, mArgv, mDescription); + 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); bpo::variables_map vmap; bpo::store(parsed, vmap); PropertyTreeHelpers::populate(specs, store, vmap, provenance); diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 3d9d98319d2ff..8d77da062c78c 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -909,8 +909,12 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, // if found in the argument list. If not found they will be added with the default value FilterFunctionT filterArgsFct = [&](int largc, char** largv, const bpo::options_description& odesc) { // spec contains options + 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); + bpo::command_line_parser parser{largc, largv}; parser.options(odesc).allow_unregistered(); + parser.style(style); bpo::parsed_options parsed_options = parser.run(); bpo::variables_map varmap; From a41e7915277c6eac6799368d1b61d579622ec09c Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sun, 16 Aug 2020 09:20:09 +0200 Subject: [PATCH 0370/1751] DPL: add support for arrow >= 1.0 (#4155) --- Framework/Core/CMakeLists.txt | 1 - Framework/Core/include/Framework/ASoA.h | 1 - .../Core/include/Framework/ASoAHelpers.h | 2 - .../Core/include/Framework/AnalysisTask.h | 8 +- Framework/Core/include/Framework/Kernels.h | 133 +++++++++++------- Framework/Core/src/Kernels.cxx | 48 ------- Framework/Core/src/TableTreeHelpers.cxx | 9 +- Framework/Core/test/test_Kernels.cxx | 108 +++++++------- 8 files changed, 143 insertions(+), 167 deletions(-) delete mode 100644 Framework/Core/src/Kernels.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 52b765447b2d1..b8323476367df 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -84,7 +84,6 @@ o2_add_library(Framework src/InputRecord.cxx src/InputSpec.cxx src/OutputSpec.cxx - src/Kernels.cxx src/LifetimeHelpers.cxx src/LocalRootFileService.cxx src/RootConfigParamHelpers.cxx diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 82a4fdb94f2b4..7051367a82ec4 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -21,7 +21,6 @@ #include <arrow/table.h> #include <arrow/array.h> #include <arrow/util/variant.h> -#include <arrow/compute/context.h> #include <arrow/compute/kernel.h> #include <gandiva/selection_vector.h> #include <cassert> diff --git a/Framework/Core/include/Framework/ASoAHelpers.h b/Framework/Core/include/Framework/ASoAHelpers.h index 04c23187ed550..bf1d992688540 100644 --- a/Framework/Core/include/Framework/ASoAHelpers.h +++ b/Framework/Core/include/Framework/ASoAHelpers.h @@ -15,8 +15,6 @@ #include "Framework/Kernels.h" #include <arrow/table.h> -#include <arrow/compute/context.h> - #include <iterator> #include <tuple> #include <utility> diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 7b32ad4a8400b..aabfe6e52a8e2 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -31,7 +31,6 @@ #include "Framework/OutputObjHeader.h" #include "Framework/RootConfigParamHelpers.h" -#include <arrow/compute/context.h> #include <arrow/compute/kernel.h> #include <arrow/table.h> #include <gandiva/node.h> @@ -636,7 +635,6 @@ struct AnalysisDataProcessorBuilder { groupSelection = >.getSelectedRows(); } auto indexColumnName = getLabelFromType(); - arrow::compute::FunctionContext ctx; /// prepare slices and offsets for all associated tables that have index /// to grouping table /// @@ -644,9 +642,9 @@ struct AnalysisDataProcessorBuilder { using xt = std::decay_t<decltype(x)>; constexpr auto index = framework::has_type_at<std::decay_t<decltype(x)>>(associated_pack_t{}); if (hasIndexTo<std::decay_t<G>>(typename xt::persistent_columns_t{})) { - auto result = o2::framework::sliceByColumn(&ctx, indexColumnName, - static_cast<int32_t>(gt.size()), + auto result = o2::framework::sliceByColumn(indexColumnName.c_str(), x.asArrowTable(), + static_cast<int32_t>(gt.size()), &groups[index], &offsets[index]); if (result.ok() == false) { @@ -773,7 +771,7 @@ struct AnalysisDataProcessorBuilder { uint64_t position = 0; soa::SelectionVector* groupSelection = nullptr; - std::array<std::vector<arrow::compute::Datum>, sizeof...(A)> groups; + std::array<std::vector<arrow::Datum>, sizeof...(A)> groups; std::array<std::vector<uint64_t>, sizeof...(A)> offsets; std::array<soa::SelectionVector const*, sizeof...(A)> selections; std::array<soa::SelectionVector::const_iterator, sizeof...(A)> starts; diff --git a/Framework/Core/include/Framework/Kernels.h b/Framework/Core/include/Framework/Kernels.h index a53eae4da1f26..b3c5388e79e54 100644 --- a/Framework/Core/include/Framework/Kernels.h +++ b/Framework/Core/include/Framework/Kernels.h @@ -21,53 +21,16 @@ #include <string> +#if (ARROW_VERSION < 1000000) namespace arrow { -class Array; -class DataType; - -namespace compute -{ -class FunctionContext; -} // namespace compute -} // namespace arrow +using Datum = compute::Datum; +} +#endif namespace o2::framework { - -struct ARROW_EXPORT HashByColumnOptions { - std::string columnName; -}; - -/// A kernel which provides a unique hash based on the contents of a given -/// column -/// * The input datum has to be a table like object. -/// * The output datum will be a column of integers which define the -/// category. -class ARROW_EXPORT HashByColumnKernel : public arrow::compute::UnaryKernel -{ - public: - HashByColumnKernel(HashByColumnOptions options = {}); - arrow::Status Call(arrow::compute::FunctionContext* ctx, - arrow::compute::Datum const& table, - arrow::compute::Datum* hashes) override; - -#pragma GCC diagnostic push -#ifdef __clang__ -#pragma GCC diagnostic ignored "-Winconsistent-missing-override" -#endif // __clang__ - - std::shared_ptr<arrow::DataType> out_type() const final - { - return mType; - } -#pragma GCC diagnostic pop - - private: - HashByColumnOptions mOptions; - std::shared_ptr<arrow::DataType> mType; -}; - +#if (ARROW_VERSION < 1000000) template <typename T> struct ARROW_EXPORT GroupByOptions { std::string columnName; @@ -80,7 +43,7 @@ class ARROW_EXPORT SortedGroupByKernel : public arrow::compute::UnaryKernel { public: explicit SortedGroupByKernel(GroupByOptions<T> options = {}) : mOptions(options){}; - arrow::Status Call(arrow::compute::FunctionContext* ctx, + arrow::Status Call(arrow::compute::FunctionContext*, arrow::compute::Datum const& table, arrow::compute::Datum* outputRanges) override { @@ -151,22 +114,19 @@ class ARROW_EXPORT SortedGroupByKernel : public arrow::compute::UnaryKernel /// slice was split. /// Slice a given table is a vector of tables each containing a slice. template <typename T> -arrow::Status sliceByColumn(arrow::compute::FunctionContext* context, - std::string const& key, +arrow::Status sliceByColumn(std::string const& key, + std::shared_ptr<arrow::Table> const& input, T size, - arrow::compute::Datum const& inputTable, std::vector<arrow::compute::Datum>* outputSlices, std::vector<uint64_t>* offsets = nullptr) { - if (inputTable.kind() != arrow::compute::Datum::TABLE) { - return arrow::Status::Invalid("Input Datum was not a table"); - } + arrow::compute::Datum inputTable{input}; // build all the ranges on the fly. arrow::compute::Datum outRanges; auto table = arrow::util::get<std::shared_ptr<arrow::Table>>(inputTable.value); o2::framework::SortedGroupByKernel<T, soa::arrow_array_for_t<T>> kernel{GroupByOptions<T>{key, size}}; - ARROW_RETURN_NOT_OK(kernel.Call(context, inputTable, &outRanges)); + ARROW_RETURN_NOT_OK(kernel.Call(nullptr, inputTable, &outRanges)); auto ranges = arrow::util::get<std::shared_ptr<arrow::Table>>(outRanges.value); outputSlices->reserve(ranges->num_rows()); if (offsets) { @@ -199,6 +159,79 @@ arrow::Status sliceByColumn(arrow::compute::FunctionContext* context, 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. +/// @a offset the offset in the original table at which the corresponding +/// slice was split. +template <typename T> +auto sliceByColumn(char const* key, + std::shared_ptr<arrow::Table> const& input, + T fullSize, + std::vector<arrow::Datum>* slices, + std::vector<uint64_t>* offsets = nullptr) +{ + arrow::Datum value_counts; + auto options = arrow::compute::CountOptions::Defaults(); + ARROW_ASSIGN_OR_RAISE(value_counts, + arrow::compute::CallFunction("value_counts", {input->GetColumnByName(key)}, + &options)); + auto pair = static_cast<arrow::StructArray>(value_counts.array()); + auto values = static_cast<arrow::NumericArray<typename detail::ConversionTraits<T>::ArrowType>>(pair.field(0)->data()); + auto counts = static_cast<arrow::NumericArray<arrow::Int64Type>>(pair.field(1)->data()); + + // create slices and offsets + auto offset = 0; + auto count = 0; + auto size = values.length(); + for (auto r = 0; r < size; ++r) { + count = counts.Value(r); + std::shared_ptr<arrow::Schema> schema(input->schema()); + std::vector<std::shared_ptr<arrow::ChunkedArray>> sliceArray; + sliceArray.reserve(schema->num_fields()); + for (auto ci = 0; ci < schema->num_fields(); ++ci) { + sliceArray.emplace_back(input->column(ci)->Slice(offset, count)); + } + slices->emplace_back(arrow::Datum(arrow::Table::Make(schema, sliceArray))); + if (offsets) { + offsets->emplace_back(offset); + } + offset += count; + sliceArray.clear(); + if (r < size - 1) { + auto nextValue = values.Value(r + 1); + while (nextValue - values.Value(r) > 1) { + for (auto ci = 0; ci < schema->num_fields(); ++ci) { + sliceArray.emplace_back(input->column(ci)->Slice(offset, 0)); + } + slices->emplace_back(arrow::Datum(arrow::Table::Make(schema, sliceArray))); + if (offsets) { + offsets->emplace_back(offset); + } + sliceArray.clear(); + nextValue -= 1; + } + } + } + if (values.Value(size - 1) < fullSize) { + for (auto v = values.Value(size - 1) + 1; v < fullSize; ++v) { + std::shared_ptr<arrow::Schema> schema(input->schema()); + std::vector<std::shared_ptr<arrow::ChunkedArray>> sliceArray; + for (auto ci = 0; ci < schema->num_fields(); ++ci) { + sliceArray.emplace_back(input->column(ci)->Slice(offset, 0)); + } + slices->emplace_back(arrow::Datum(arrow::Table::Make(schema, sliceArray))); + if (offsets) { + offsets->emplace_back(offset); + } + } + } + + return arrow::Status::OK(); +} +#endif + } // namespace o2::framework #endif // O2_FRAMEWORK_KERNELS_H_ diff --git a/Framework/Core/src/Kernels.cxx b/Framework/Core/src/Kernels.cxx deleted file mode 100644 index eb5ebb4f0e578..0000000000000 --- a/Framework/Core/src/Kernels.cxx +++ /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. -#include "Framework/Kernels.h" -#include "Framework/ArrowTypes.h" - -#include "ArrowDebugHelpers.h" - -#include <arrow/builder.h> -#include <arrow/status.h> -#include <arrow/type.h> -#include <arrow/util/variant.h> -#include <memory> -#include <iostream> - -using namespace arrow; -using namespace arrow::compute; - -namespace o2 -{ -namespace framework -{ - -HashByColumnKernel::HashByColumnKernel(HashByColumnOptions options) - : mOptions{options} -{ -} - -Status HashByColumnKernel::Call(FunctionContext* ctx, Datum const& inputTable, Datum* hashes) -{ - if (inputTable.kind() == Datum::TABLE) { - auto table = arrow::util::get<std::shared_ptr<arrow::Table>>(inputTable.value); - auto columnIndex = table->schema()->GetFieldIndex(mOptions.columnName); - auto chunkedArray = table->column(columnIndex); - *hashes = std::move(chunkedArray); - return arrow::Status::OK(); - } - return Status::Invalid("Input Datum was not a table"); -} - -} // namespace framework -} // namespace o2 diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index c79c50d1e57de..3d0cb70cd1c39 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -32,12 +32,19 @@ BranchIterator::BranchIterator(TTree* tree, std::shared_ptr<arrow::ChunkedArray> 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<const arrow::FixedSizeListType*>(mField->type().get())->list_size(); mLeaflistString += "[" + std::to_string(mNumberElements) + "]"; diff --git a/Framework/Core/test/test_Kernels.cxx b/Framework/Core/test/test_Kernels.cxx index 5817e2a7b1b80..c14c35c76b057 100644 --- a/Framework/Core/test/test_Kernels.cxx +++ b/Framework/Core/test/test_Kernels.cxx @@ -12,21 +12,25 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK -#include "Framework/AnalysisDataModel.h" #include "Framework/Kernels.h" #include "Framework/TableBuilder.h" -#include <arrow/compute/context.h> -#include <arrow/compute/kernels/hash.h> +#include "Framework/Pack.h" #include <boost/test/unit_test.hpp> using namespace o2::framework; using namespace arrow; using namespace arrow::compute; -BOOST_AUTO_TEST_CASE(TestHashByColumnKernel) +#if (ARROW_VERSION < 1000000) +namespace arrow +{ +using Datum = compute::Datum; +} +#else +BOOST_AUTO_TEST_CASE(TestSlicing) { TableBuilder builder; - auto rowWriter = builder.persist<uint64_t, uint64_t>({"x", "y"}); + auto rowWriter = builder.persist<int32_t, int32_t>({"x", "y"}); rowWriter(0, 0, 0); rowWriter(0, 0, 1); rowWriter(0, 0, 2); @@ -35,68 +39,54 @@ BOOST_AUTO_TEST_CASE(TestHashByColumnKernel) rowWriter(0, 1, 5); rowWriter(0, 1, 6); rowWriter(0, 1, 7); - rowWriter(0, 2, 8); + rowWriter(0, 2, 7); + rowWriter(0, 4, 8); + rowWriter(0, 5, 9); + rowWriter(0, 5, 10); auto table = builder.finalize(); - arrow::compute::FunctionContext ctx; - HashByColumnKernel kernel{{"x"}}; - std::shared_ptr<arrow::Array> out; - auto outDatum = arrow::compute::Datum(out); - BOOST_CHECK_EQUAL(kernel.Call(&ctx, arrow::compute::Datum(table), &outDatum).ok(), true); - auto indices = arrow::util::get<std::shared_ptr<arrow::ChunkedArray>>(outDatum.value); - BOOST_CHECK_EQUAL(indices->length(), table->num_rows()); + auto options = arrow::compute::CountOptions::Defaults(); + auto value_counts = arrow::compute::CallFunction("value_counts", {table->GetColumnByName("x")}, &options).ValueOrDie(); + auto array = static_cast<arrow::StructArray>(value_counts.array()); - std::shared_ptr<arrow::Array> uniqueValues; - BOOST_CHECK_EQUAL(Unique(&ctx, arrow::compute::Datum(indices), &uniqueValues).ok(), true); - BOOST_REQUIRE(uniqueValues.get() != nullptr); - BOOST_CHECK_EQUAL(uniqueValues->length(), 3); + auto arr0 = static_cast<NumericArray<Int32Type>>(array.field(0)->data()); + auto arr1 = static_cast<NumericArray<Int64Type>>(array.field(1)->data()); - arrow::compute::Datum outRanges; - SortedGroupByKernel<uint64_t, arrow::UInt64Array> groupBy{{"x", 3}}; - BOOST_CHECK_EQUAL(groupBy.Call(&ctx, arrow::compute::Datum(table), &outRanges).ok(), true); - auto result = arrow::util::get<std::shared_ptr<arrow::Table>>(outRanges.value); - BOOST_REQUIRE(result.get() != nullptr); - BOOST_CHECK_EQUAL(result->num_rows(), 3); + std::array<int, 5> v{0, 1, 2, 4, 5}; + std::array<int, 5> c{4, 4, 1, 1, 2}; - std::vector<Datum> splitted; - BOOST_CHECK_EQUAL(sliceByColumn(&ctx, "x", static_cast<uint64_t>(3), arrow::compute::Datum(table), &splitted).ok(), true); - BOOST_REQUIRE_EQUAL(splitted.size(), 3); - BOOST_CHECK_EQUAL(util::get<std::shared_ptr<Table>>(splitted[0].value)->num_rows(), 4); - BOOST_CHECK_EQUAL(util::get<std::shared_ptr<Table>>(splitted[1].value)->num_rows(), 4); - BOOST_CHECK_EQUAL(util::get<std::shared_ptr<Table>>(splitted[2].value)->num_rows(), 1); + for (auto i = 0; i < arr0.length(); ++i) { + BOOST_REQUIRE_EQUAL(arr0.Value(i), v[i]); + BOOST_REQUIRE_EQUAL(arr1.Value(i), c[i]); + } } +#endif -BOOST_AUTO_TEST_CASE(TestWithSOATables) +BOOST_AUTO_TEST_CASE(TestSlicingFramework) { - using namespace o2; - TableBuilder builder2; - auto tracksCursor = builder2.cursor<aod::StoredTracks>(); - tracksCursor(0, 0, 2, 3, 4, 5, 6, 7, 8, 9); - tracksCursor(0, 0, 2, 3, 4, 5, 6, 7, 8, 9); - tracksCursor(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); - tracksCursor(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); - tracksCursor(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); - tracksCursor(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); - tracksCursor(0, 2, 2, 3, 4, 5, 6, 7, 8, 9); - auto tracks = builder2.finalize(); - - arrow::compute::FunctionContext ctx; - arrow::compute::Datum outRanges; - SortedGroupByKernel<int32_t, arrow::Int32Array> groupBy{{"fCollisionsID", 3}}; - BOOST_CHECK_EQUAL(groupBy.Call(&ctx, arrow::compute::Datum(tracks), &outRanges).ok(), true); - auto result = arrow::util::get<std::shared_ptr<arrow::Table>>(outRanges.value); - BOOST_REQUIRE(result.get() != nullptr); - BOOST_CHECK_EQUAL(result->num_rows(), 3); + TableBuilder builder; + auto rowWriter = builder.persist<int32_t, int32_t>({"x", "y"}); + rowWriter(0, 0, 0); + rowWriter(0, 0, 1); + rowWriter(0, 0, 2); + rowWriter(0, 0, 3); + rowWriter(0, 1, 4); + rowWriter(0, 1, 5); + rowWriter(0, 1, 6); + rowWriter(0, 1, 7); + rowWriter(0, 2, 7); + rowWriter(0, 4, 8); + rowWriter(0, 5, 9); + rowWriter(0, 5, 10); + auto table = builder.finalize(); - std::vector<Datum> splitted; std::vector<uint64_t> offsets; - BOOST_CHECK_EQUAL(sliceByColumn(&ctx, "fCollisionsID", static_cast<int32_t>(3), arrow::compute::Datum(tracks), &splitted, &offsets).ok(), true); - BOOST_REQUIRE_EQUAL(splitted.size(), 3); - BOOST_CHECK_EQUAL(util::get<std::shared_ptr<Table>>(splitted[0].value)->num_rows(), 2); - BOOST_CHECK_EQUAL(util::get<std::shared_ptr<Table>>(splitted[1].value)->num_rows(), 4); - BOOST_CHECK_EQUAL(util::get<std::shared_ptr<Table>>(splitted[2].value)->num_rows(), 1); - - BOOST_CHECK_EQUAL(offsets[0], 0); - BOOST_CHECK_EQUAL(offsets[1], 2); - BOOST_CHECK_EQUAL(offsets[2], 6); + std::vector<arrow::Datum> slices; + auto status = sliceByColumn<int32_t>("x", table, 12, &slices, &offsets); + BOOST_REQUIRE(status.ok()); + BOOST_REQUIRE_EQUAL(slices.size(), 12); + std::array<int, 12> sizes{4, 4, 1, 0, 1, 2, 0, 0, 0, 0, 0, 0}; + for (auto i = 0u; i < slices.size(); ++i) { + BOOST_REQUIRE_EQUAL(slices[i].table()->num_rows(), sizes[i]); + } } From 3fae559766c9792905e49f5e5825510553d56972 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 16 Aug 2020 23:50:35 +0200 Subject: [PATCH 0371/1751] DPL GUI: display services information in Device Inspector (#4161) --- .../Core/src/FrameworkGUIDeviceInspector.cxx | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx index dcf8aac9a45fe..1822dc750b31e 100644 --- a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx +++ b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx @@ -144,6 +144,41 @@ void optionsTable(const char* label, std::vector<ConfigParamSpec> const& options ImGui::Columns(1); } +void servicesTable(const char* label, std::vector<ServiceSpec> const& services) +{ + if (services.empty()) { + return; + } + if (ImGui::CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Columns(2); + auto labels = {"Service", "Kind"}; + for (auto& label : labels) { + ImGui::TextUnformatted(label); + ImGui::NextColumn(); + } + for (auto& service : services) { + ImGui::TextUnformatted(service.name.c_str()); + ImGui::NextColumn(); + switch (service.kind) { + case ServiceKind::Serial: + ImGui::TextUnformatted("Serial"); + break; + case ServiceKind::Global: + ImGui::TextUnformatted("Global"); + break; + case ServiceKind::Stream: + ImGui::TextUnformatted("Stream"); + break; + default: + ImGui::TextUnformatted("unknown"); + } + ImGui::NextColumn(); + } + } + + ImGui::Columns(1); +} + void displayDeviceInspector(DeviceSpec const& spec, DeviceInfo const& info, DeviceMetricsInfo const& metrics, @@ -215,6 +250,7 @@ void displayDeviceInspector(DeviceSpec const& spec, } configurationTable(info.currentConfig, info.currentProvenance); optionsTable("Workflow Options", metadata.workflowOptions, control); + servicesTable("Services", spec.services); if (ImGui::CollapsingHeader("Command line arguments", ImGuiTreeNodeFlags_DefaultOpen)) { for (auto& arg : metadata.cmdLineArgs) { ImGui::Text("%s", arg.c_str()); From f740082d2ed575ed938a358499cb4d5a09291020 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 15 Aug 2020 01:44:50 +0200 Subject: [PATCH 0372/1751] Fix: TRD digitizer must report triggered mode to GRPUpdater --- Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx index bcb69e2094181..4e2f62fcfe016 100644 --- a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx @@ -140,7 +140,7 @@ class TRDDPLDigitizerTask : public o2::base::BaseDPLDigitizer Digitizer mDigitizer; std::vector<TChain*> mSimChains; // RS: at the moment using hardcoded flag for continuos readout - o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::CONTINUOUS; // readout mode + o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::PRESENT; // readout mode }; o2::framework::DataProcessorSpec getTRDDigitizerSpec(int channel, bool mctruth) From ec59b92fccb3b5dd697f1cfe29f2262a9a8a4cef Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Tue, 28 Jul 2020 16:31:59 +0200 Subject: [PATCH 0373/1751] Minor adjustments and additions to Pythia8 generator/decayer --- .../include/Generators/DecayerPythia8Param.h | 3 ++- Generators/src/DecayerPythia8.cxx | 25 ++++++++++------- Generators/src/GeneratorFactory.cxx | 6 ----- Generators/src/GeneratorPythia8.cxx | 27 ++++++++++++++++--- .../README.md | 3 ++- .../ForceDecay_Lambda_Neutron_Dalitz/run.sh | 5 ++-- 6 files changed, 45 insertions(+), 24 deletions(-) diff --git a/Generators/include/Generators/DecayerPythia8Param.h b/Generators/include/Generators/DecayerPythia8Param.h index 94b3111de2c42..b3f2397af94d8 100644 --- a/Generators/include/Generators/DecayerPythia8Param.h +++ b/Generators/include/Generators/DecayerPythia8Param.h @@ -29,8 +29,9 @@ namespace eventgen **/ struct DecayerPythia8Param : public o2::conf::ConfigurableParamHelper<DecayerPythia8Param> { - std::string config = "${O2_ROOT}/share/Generators/pythia8/decays/base.cfg"; + std::string config[8] = {"${O2_ROOT}/share/Generators/pythia8/decays/base.cfg", "", "", "", "", "", "", ""}; bool verbose = false; + bool showChanged = false; O2ParamDef(DecayerPythia8Param, "DecayerPythia8"); }; diff --git a/Generators/src/DecayerPythia8.cxx b/Generators/src/DecayerPythia8.cxx index adb4b00f36df1..ec8df5fc3315e 100644 --- a/Generators/src/DecayerPythia8.cxx +++ b/Generators/src/DecayerPythia8.cxx @@ -38,22 +38,27 @@ void DecayerPythia8::Init() auto& param = DecayerPythia8Param::Instance(); LOG(INFO) << "Init \'DecayerPythia8\' with following parameters"; LOG(INFO) << param; - if (!param.config.empty()) { - std::stringstream ss(param.config); - std::string config; - while (getline(ss, config, ' ')) { - config = gSystem->ExpandPathName(config.c_str()); - if (!mPythia.readFile(config, true)) { - LOG(FATAL) << "Failed to init \'DecayerPythia8\': problems with configuration file " - << config; - return; - } + for (int i = 0; i < 8; ++i) { + if (param.config[i].empty()) + continue; + std::string config = gSystem->ExpandPathName(param.config[i].c_str()); + LOG(INFO) << "Reading configuration from file: " << config; + if (!mPythia.readFile(config, true)) { + LOG(FATAL) << "Failed to init \'DecayerPythia8\': problems with configuration file " + << config; + return; } } /** verbose flag **/ mVerbose = param.verbose; + /** show changed particle data **/ + if (param.showChanged) + mPythia.readString(std::string("Init:showChangedParticleData on")); + else + mPythia.readString(std::string("Init:showChangedParticleData off")); + /** initialise **/ if (!mPythia.init()) { LOG(FATAL) << "Failed to init \'DecayerPythia8\': init returned with error"; diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index bb225f2fed689..6c1c5eec50cb1 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -64,12 +64,6 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair auto gen = new o2::eventgen::GeneratorPythia8(); LOG(INFO) << "Reading \'Pythia8\' base configuration: " << config << std::endl; gen->readFile(config); - auto& param = GeneratorPythia8Param::Instance(); - LOG(INFO) << "Init \'Pythia8\' generator with following parameters"; - LOG(INFO) << param; - gen->setConfig(param.config); - gen->setHooksFileName(param.hooksFileName); - gen->setHooksFuncName(param.hooksFuncName); auto seed = (gRandom->GetSeed() % 900000000); LOG(INFO) << "Using random seed from gRandom % 900000000: " << seed; gen->readString("Random:setSeed on"); diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 47b608ea9733b..23086e5237fe0 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -11,11 +11,15 @@ /// \author R+Preghenella - January 2020 #include "Generators/GeneratorPythia8.h" +#include "Generators/GeneratorPythia8Param.h" #include "Generators/ConfigurationMacroHelper.h" #include "FairLogger.h" #include "TParticle.h" #include "FairMCEventHeader.h" #include "Pythia8/HIUserHooks.h" +#include "TSystem.h" + +#include <iostream> namespace o2 { @@ -31,6 +35,14 @@ GeneratorPythia8::GeneratorPythia8() : Generator("ALICEo2", "ALICEo2 Pythia8 Gen mInterface = reinterpret_cast<void*>(&mPythia); mInterfaceName = "pythia8"; + + auto& param = GeneratorPythia8Param::Instance(); + LOG(INFO) << "Instance \'Pythia8\' generator with following parameters"; + LOG(INFO) << param; + + setConfig(param.config); + setHooksFileName(param.hooksFileName); + setHooksFuncName(param.hooksFuncName); } /*****************************************************************/ @@ -54,15 +66,22 @@ Bool_t GeneratorPythia8::Init() /** read configuration **/ if (!mConfig.empty()) { - if (!mPythia.readFile(mConfig, true)) { - LOG(FATAL) << "Failed to init \'Pythia8\': problems with configuration file " - << mConfig; - return false; + std::stringstream ss(mConfig); + std::string config; + while (getline(ss, config, ' ')) { + config = gSystem->ExpandPathName(config.c_str()); + LOG(INFO) << "Reading configuration from file: " << config; + if (!mPythia.readFile(config, true)) { + LOG(FATAL) << "Failed to init \'Pythia8\': problems with configuration file " + << config; + return false; + } } } /** user hooks via configuration macro **/ if (!mHooksFileName.empty()) { + LOG(INFO) << "Applying \'Pythia8\' user hooks: " << mHooksFileName << " -> " << mHooksFuncName; auto hooks = GetFromMacro<Pythia8::UserHooks*>(mHooksFileName, mHooksFuncName, "Pythia8::UserHooks*", "pythia8_user_hooks"); if (!hooks) { LOG(FATAL) << "Failed to init \'Pythia8\': problem with user hooks configuration "; diff --git a/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/README.md b/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/README.md index 607a745c28fbe..edbead91dac14 100644 --- a/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/README.md +++ b/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/README.md @@ -19,10 +19,11 @@ On top of that we have to setup the external decayer to perform the decay forcin The default external decayer configuration is loaded from ``` ${O2_ROOT}/share/Generators/pythia8/decays/base.cfg +which is assigned to the slot #0 of the configuration parameter 'DecayerPythia8.config'. ``` What we want to do is to add on top of the default configuration some extra settings that are provided in the `decay_lambda_neutron_dalitz.cfg` file. This can be done with ``` ---configKeyValues 'DecayerPythia8.config=${O2_ROOT}/share/Generators/pythia8/decays/base.cfg decay_lambda_neutron_dalitz.cfg' +--configKeyValues 'DecayerPythia8.config[1]=decay_lambda_neutron_dalitz.cfg' ``` diff --git a/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/run.sh b/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/run.sh index 95a916080cc61..5185e6625672f 100755 --- a/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/run.sh +++ b/run/SimExamples/ForceDecay_Lambda_Neutron_Dalitz/run.sh @@ -14,13 +14,14 @@ # On top of that we have to setup the external decayer to perform the decay forcing the channels we desire. # The default external decayer configuration is loaded from # ${O2_ROOT}/share/Generators/pythia8/decays/base.cfg +# which is assigned to the slot #0 of the configuration parameter 'DecayerPythia8.config'. # # What we want to do is to add on top of the default configuration some extra settings that are provided in the `decay_lambda_neutron_dalitz.cfg` file. # This can be done with -# --configKeyValues 'DecayerPythia8.config=${O2_ROOT}/share/Generators/pythia8/decays/base.cfg decay_lambda_neutron_dalitz.cfg' +# --configKeyValues 'DecayerPythia8.config[1]=decay_lambda_neutron_dalitz.cfg' # set -x NEV=10 -o2-sim -j 20 -n ${NEV} -g boxgen -m PIPE ITS TPC --configKeyValues 'BoxGun.pdg=3122;BoxGun.number=1;SimUserDecay.pdglist=3122 111;DecayerPythia8.config=${O2_ROOT}/share/Generators/pythia8/decays/base.cfg decay_lambda_neutron_dalitz.cfg;DecayerPythia8.verbose=true' +o2-sim -j 20 -n ${NEV} -g boxgen -m PIPE ITS TPC --configKeyValues 'BoxGun.pdg=3122;BoxGun.number=1;SimUserDecay.pdglist=3122 111;DecayerPythia8.config[1]=decay_lambda_neutron_dalitz.cfg;DecayerPythia8.verbose=true' From 3344e1b98e6881fb255df1527466bfd5f4ad1058 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Tue, 4 Aug 2020 10:49:19 +0200 Subject: [PATCH 0374/1751] HF benchmark simulation example --- doc/DetectorSimulation.md | 1 + .../HF_Embedding_Pythia8/GeneratorHF.macro | 118 ++++++++++++++++++ .../decays/force_hadronic_D.cfg | 96 ++++++++++++++ .../force_hadronic_D_forceLcChannel1.cfg | 12 ++ .../force_hadronic_D_forceLcChannel2.cfg | 12 ++ .../decays/force_hadronic_D_use4bodies.cfg | 15 +++ .../decays/force_hadronic_D_useDtoV0.cfg | 13 ++ .../o2sim_configuration_bkg.ini | 8 ++ .../o2sim_configuration_sgn.ini | 12 ++ .../pythia8_ccbar.template | 19 +++ .../pythia8_userhooks_ccbar.macro | 47 +++++++ run/SimExamples/HF_Embedding_Pythia8/run.sh | 68 ++++++++++ run/SimExamples/README.md | 1 + 13 files changed, 422 insertions(+) create mode 100644 run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro create mode 100644 run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D.cfg create mode 100644 run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_forceLcChannel1.cfg create mode 100644 run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_forceLcChannel2.cfg create mode 100644 run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_use4bodies.cfg create mode 100644 run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_useDtoV0.cfg create mode 100644 run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_bkg.ini create mode 100644 run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini create mode 100644 run/SimExamples/HF_Embedding_Pythia8/pythia8_ccbar.template create mode 100644 run/SimExamples/HF_Embedding_Pythia8/pythia8_userhooks_ccbar.macro create mode 100755 run/SimExamples/HF_Embedding_Pythia8/run.sh diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index 7aec8594c2530..7b46e0a18ae29 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -450,6 +450,7 @@ Other helpful resources are the scripts used for regression testing in [prodtest | Example | Short Description | | --------------------- | -------------------------------------------------------------------------------------- | +| [HF_Embedding_Pythia8](../run/SimExamples/HF_Embedding_Pythia8) | Example showing how to setup a complex HF simulation for embedding | | [AliRoot_Hijing](../run/SimExamples/AliRoot_Hijing) | Example showing how to use Hijing from AliRoot for event generation | | [AliRoot_AMPT](../run/SimExamples/AliRoot_AMPT) | Example showing how to use AMPT from AliRoot for event generation | | [Adaptive_Pythia8](../run/SimExamples/Adaptive_Pythia8) | Complex example showing **generator configuration for embedding** that cat adapt the response based on the background event | diff --git a/run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro b/run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro new file mode 100644 index 0000000000000..249d9de05221c --- /dev/null +++ b/run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro @@ -0,0 +1,118 @@ +/// \author R+Preghenella - July 2020 + +// Example of an implementation of an event generator +// that provides HF signals for embedding in background + +#include "Pythia8/Pythia.h" + +namespace o2 { +namespace eventgen { + +class GeneratorHF : public GeneratorPythia8 +{ + +public: + + GeneratorHF() : GeneratorPythia8() { }; + ~GeneratorHF() = default; + + // We initialise the local Pythia8 event where we store the particles + // of the signal event that is the sum of multiple Pythia8 events + // generated according to the generateEvent() function below. + Bool_t Init() override { + mOutputEvent.init("(GeneratorHF output event)", &mPythia.particleData); + return GeneratorPythia8::Init(); + } + + // This function is called by the primary generator + // for each event in case we are in embedding mode. + // We use it to setup the number of signal events + // to be generated and to be embedded on the background. + void notifyEmbedding(const FairMCEventHeader *bkgHeader) override { + mEvents = mFormula.Eval(bkgHeader->GetB()); + std::cout << " --- notify embedding: impact parameter is " << bkgHeader->GetB() << ", generating " << mEvents << " signal events " << std::endl; + }; + + // We override this function to be able to generate multiple + // events and build an output event that is the sum of them + // where we have stripped out only the sub-event starting from + // the c-cbar ancestor particle + Bool_t generateEvent() override { + + // reset counter and event + mOutputEvent.reset(); + + // loop over number of events to be generated + int nEvents = 0; + while (nEvents < mEvents) { + + // generate event + if (!GeneratorPythia8::generateEvent()) return false; + + // find the c-cbar ancestor + auto ancestor = findAncestor(mPythia.event); + if (ancestor < 0) continue; + + // append ancestor and its daughters to the output event + selectFromAncestor(ancestor, mPythia.event, mOutputEvent); + nEvents++; + } + + if (mVerbose) mOutputEvent.list(); + + return true; + }; + + // We override this event to import the particles from the + // output event that we have constructed as the sum of multiple + // Pythia8 sub-events as generated above + Bool_t importParticles() override { + return GeneratorPythia8::importParticles(mOutputEvent); + } + + // search for c-cbar mother with at least one c at midrapidity + int findAncestor(Pythia8::Event& event) { + for (int ipa = 0; ipa < event.size(); ++ipa) { + auto daughterList = event[ipa].daughterList(); + bool hasc = false, hascbar = false, atmidy = false; + for (auto ida : daughterList) { + if (event[ida].id() == 4) hasc = true; + if (event[ida].id() == -4) hascbar = true; + if (fabs(event[ida].y()) < mRapidity) atmidy = true; + } + if (hasc && hascbar && atmidy) + return ipa; + } + return -1; + }; + + void setRapidity(double val) { mRapidity = val; }; + void setVerbose(bool val) { mVerbose = val; }; + void setFormula(std::string val) { mFormula.Compile(val.c_str()); }; + +private: + + TFormula mFormula; + int mEvents = 1; + Pythia8::Event mOutputEvent; + double mRapidity = 1.5; + bool mVerbose = false; + +}; + +}} + +/** generator instance and settings **/ + +FairGenerator* +GeneratorHF(double rapidity = 1.5, bool verbose = false) +{ + auto gen = new o2::eventgen::GeneratorHF(); + gen->setRapidity(rapidity); + gen->setVerbose(verbose); + gen->setFormula("max(1.,120.*(x<5.)+80.*(1.-x/20.)*(x>5.)*(x<11.)+240.*(1.-x/13.)*(x>11.))"); + + return gen; +} + + diff --git a/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D.cfg b/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D.cfg new file mode 100644 index 0000000000000..e51167aae4398 --- /dev/null +++ b/run/SimExamples/HF_Embedding_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/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_forceLcChannel1.cfg b/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_forceLcChannel1.cfg new file mode 100644 index 0000000000000..33abbb1b6f340 --- /dev/null +++ b/run/SimExamples/HF_Embedding_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/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_forceLcChannel2.cfg b/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_forceLcChannel2.cfg new file mode 100644 index 0000000000000..d79dec4d8b88f --- /dev/null +++ b/run/SimExamples/HF_Embedding_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/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_use4bodies.cfg b/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_use4bodies.cfg new file mode 100644 index 0000000000000..3178dad7d368b --- /dev/null +++ b/run/SimExamples/HF_Embedding_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/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_useDtoV0.cfg b/run/SimExamples/HF_Embedding_Pythia8/decays/force_hadronic_D_useDtoV0.cfg new file mode 100644 index 0000000000000..5b50c59e0130c --- /dev/null +++ b/run/SimExamples/HF_Embedding_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/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_bkg.ini b/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_bkg.ini new file mode 100644 index 0000000000000..5242ab6ef7e1d --- /dev/null +++ b/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_bkg.ini @@ -0,0 +1,8 @@ +[Diamond] +position[0]=0.0 +position[1]=0.0 +position[2]=0.1 + +width[0]=0.05 +width[1]=0.05 +width[2]=6.0 diff --git a/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini b/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini new file mode 100644 index 0000000000000..e4c4d58ed8659 --- /dev/null +++ b/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini @@ -0,0 +1,12 @@ +[Pythia8] +config = pythia8.cfg +hooksFileName = pythia8_userhooks_ccbar.macro +hooksFuncName = pythia8_userhooks_ccbar(1.5) + +[DecayerPythia8] +config[0] = ${O2_ROOT}/share/Generators/pythia8/decays/base.cfg +config[1] = decays/force_hadronic_D.cfg +config[2] = decays/force_hadronic_D_use4bodies.cfg + +[SimUserDecay] +pdglist = 411 421 431 4112 4122 4232 4132 diff --git a/run/SimExamples/HF_Embedding_Pythia8/pythia8_ccbar.template b/run/SimExamples/HF_Embedding_Pythia8/pythia8_ccbar.template new file mode 100644 index 0000000000000..70c45acc4299b --- /dev/null +++ b/run/SimExamples/HF_Embedding_Pythia8/pythia8_ccbar.template @@ -0,0 +1,19 @@ +### random seed +Random:setSeed on +Random:seed ${rndSeed} + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 14000. # GeV + +### processes +HardQCD:hardccbar on # scatterings g-g / q-qbar -> c-cbar + +### phase space cuts +PhaseSpace:pTHatMin ${pTHatMin} # the minimum invariant pT +PhaseSpace:pTHatMax ${pTHatMax} # the maximum invariant pT + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 0.001 diff --git a/run/SimExamples/HF_Embedding_Pythia8/pythia8_userhooks_ccbar.macro b/run/SimExamples/HF_Embedding_Pythia8/pythia8_userhooks_ccbar.macro new file mode 100644 index 0000000000000..6cba98017684e --- /dev/null +++ b/run/SimExamples/HF_Embedding_Pythia8/pythia8_userhooks_ccbar.macro @@ -0,0 +1,47 @@ +/// \author R+Preghenella - July 2020 + +/// This Pythia8 UserHooks can veto the processing at parton level. +/// The partonic event is scanned searching for a c-cbar mother +/// with at least one of the c quarks produced withing a fiducial +/// window around midrapidity that can be specified by the user. + +#include "Pythia8/Pythia.h" + +class UserHooks_ccbar : public Pythia8::UserHooks +{ + + public: + UserHooks_ccbar() = default; + ~UserHooks_ccbar() = default; + bool canVetoPartonLevel() override { return true; }; + bool doVetoPartonLevel(const Pythia8::Event& event) override { + // search for c-cbar mother with at least one c at midrapidity + for (int ipa = 0; ipa < event.size(); ++ipa) { + auto daughterList = event[ipa].daughterList(); + bool hasc = false, hascbar = false, atmidy = false; + for (auto ida : daughterList) { + if (event[ida].id() == 4) hasc = true; + if (event[ida].id() == -4) hascbar = true; + if (fabs(event[ida].y()) < mRapidity) atmidy = true; + } + if (hasc && hascbar && atmidy) + return false; // found it, do not veto event + } + return true; // did not find it, veto event + }; + + void setRapidity(double val) { mRapidity = val; }; + +private: + + double mRapidity = 1.5; + +}; + +Pythia8::UserHooks* + pythia8_userhooks_ccbar(double rapidity = 1.5) +{ + auto hooks = new UserHooks_ccbar(); + hooks->setRapidity(rapidity); + return hooks; +} diff --git a/run/SimExamples/HF_Embedding_Pythia8/run.sh b/run/SimExamples/HF_Embedding_Pythia8/run.sh new file mode 100755 index 0000000000000..c5dfb1d68c04a --- /dev/null +++ b/run/SimExamples/HF_Embedding_Pythia8/run.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# +# This is a simulation example showing the following things +# +# a) how to run a simple background event simulation with some parameter customization +# b) how to generate a pythia8 configuration file replacing values from a template configuration +# c) how to run a simulation producing signal events using several specific pythia8 settings and user hooks +# d) how to run digitization embedding/overlaying background and signal hits +# +# The main focus in this example is on PART c). PART b) just relaces some template values in the Pythia8 configuration file. +# +# An external event generator configuration `-g extgen` is loaded from the file `--extGenFile "GeneratorHF.macro"` +# by running the code defined in the function `--extGenFunc "GeneratorHF()"`. +# Special configuration parameters are loaded from the INI file `--configFile o2sim_configuration_sgn.ini`. +# +# Pythia8.config defines the Pythia8 configuration file name. +# +# We configured to bias towards c-cbar processes where we can select them baed on pt-hat bins. +# +# Pythia8.hooksFileName defines the file name where to load the custom Pythia8 hooks +# Pythia8.hooskFuncName defines the function call to be run to retrieve the custom Pythia8 hools. +# +# Hooks are used in this example to speedup the event generation. Event generation is paused at parton level. +# We check if there are the partons of our interest, if not we veto the event. This saves time because we +# do not have to process the full hadronisation step of uninteresting events. +# Look inside `pythia8_userhooks_ccbar.macro` for details on how this is implemented +# +# DecayerPythia8.config[0], [1] and [2] define several configuration files for the external decayer. +# The files are loaded in series. Look inside the corresponding `.cfg` for details. +# +# SimUserDecay.pdglist instructs Geant not to process the decays, but to hand them to the external decayer. +# + +set -x + +MODULES="PIPE ITS TPC" +BKGEVENTS=5 +SIGEVENTS=20 +NWORKERS=8 + +# PART a) + +o2-sim -j ${NWORKERS} -n ${BKGEVENTS} -g pythia8hi -m ${MODULES} -o bkg \ + --configFile o2sim_configuration_bkg.ini \ + > logbkg 2>&1 + +# PART b) + +RNDSEED=0 # [default = 0] time-based random seed +PTHATMIN=0. # [default = 0] +PTHATMAX=-1. # [default = -1] + +sed -e "s/\${rndSeed}/$RNDSEED/" \ + -e "s/\${pTHatMin}/$PTHATMIN/" \ + -e "s/\${pTHatMax}/$PTHATMAX/" \ + pythia8_ccbar.template > pythia8.cfg + +# PART c) + +o2-sim -j ${NWORKERS} -n ${SIGEVENTS} -g extgen -m ${MODULES} -o sgn \ + --extGenFile "GeneratorHF.macro" --extGenFunc "GeneratorHF()" \ + --configFile o2sim_configuration_sgn.ini \ + --embedIntoFile bkg_Kine.root \ + > logsgn 2>&1 + +# PART d) + +o2-sim-digitizer-workflow --sims bkg,sgn --tpc-lanes 4 -b --run diff --git a/run/SimExamples/README.md b/run/SimExamples/README.md index ed77f8b00f2cf..d589dc43a1115 100644 --- a/run/SimExamples/README.md +++ b/run/SimExamples/README.md @@ -5,6 +5,7 @@ # Simulation Examples <!-- doxy +* \subpage refrunSimExamplesHF_Embedding_Pythia8 * \subpage refrunSimExamplesSignal_ImpactB * \subpage refrunSimExamplesTrigger_ImpactB_Pythia8 * \subpage refrunSimExamplesAdaptive_Pythia8 From 2f4f21d4f8f156940f6a8a770002955ade7d9955 Mon Sep 17 00:00:00 2001 From: Jason Barrella <32719308+jbarrella@users.noreply.github.com> Date: Mon, 17 Aug 2020 10:48:16 +0200 Subject: [PATCH 0375/1751] conversion macro for run2 digits (#4121) * initial conversion macro for run2 digits * use AliTRDCommonParam and AliTRDfeeParam to get TRD geometry parameters * now writes trigger record for compatibility with TrapSim --- .../TRD/macros/convertRun2ToRun3Digits.C | 241 ++++++++++++++++++ cmake/O2RootMacroExclusionList.cmake | 1 + 2 files changed, 242 insertions(+) create mode 100644 Detectors/TRD/macros/convertRun2ToRun3Digits.C diff --git a/Detectors/TRD/macros/convertRun2ToRun3Digits.C b/Detectors/TRD/macros/convertRun2ToRun3Digits.C new file mode 100644 index 0000000000000..f67bc7a45bfd7 --- /dev/null +++ b/Detectors/TRD/macros/convertRun2ToRun3Digits.C @@ -0,0 +1,241 @@ +#if !defined(__CINT__) || defined(__MAKECINT__) +#include <TClonesArray.h> + +#include <AliRunLoader.h> +#include <AliLoader.h> +#include <AliDataLoader.h> +#include <AliTreeLoader.h> +#include <AliTRDarrayADC.h> + +#include <iostream> + +#include "TH1F.h" +#include "TRDBase/Digit.h" +#include "TRDBase/Tracklet.h" + +#include <AliRawReaderRoot.h> +#include <AliRawReaderDateOnline.h> +#include <AliTRDrawStream.h> +#include <AliRawReader.h> +#endif + +using namespace o2; +using namespace trd; +using namespace std; + +// qa.root +// 18000283989033.808.root +// TRD.Digits.root +void convertRun2ToRun3Digits(TString qaOutPath = "", + TString rawDataInPath = "", + TString run2DigitsInPath = "", + TString run3DigitsOutPath = "trddigits.root", + int nRawEvents = 1000) +{ + vector<o2::trd::Digit> run3Digits; + vector<o2::trd::TriggerRecord> triggerRecords; + + TH1F* hAdc = new TH1F("hADC", "ADC spectrum", 1024, -0.5, 1023.5); + TH1F* hTBsum = new TH1F("hTBsum", "TBsum", 3000, -0.5, 2999.5); + + // convert raw data if path set + if (rawDataInPath != "") { + cout << "Converting RAW data..." << endl; + AliRawReader* reader; + if (rawDataInPath.Contains(".root")) { + cout << "[I] Reading with ROOT" << endl; + AliRawReaderRoot* readerDate = new AliRawReaderRoot(rawDataInPath); + readerDate->SelectEquipment(0, 1024, 1024); + readerDate->Select("TRD"); + //readerDate->SelectEvents(7); + reader = (AliRawReader*)readerDate; + + } else if (rawDataInPath.Contains(":")) { + cout << "[I] Reading DATE monitoring events" << endl; + AliRawReaderDateOnline* readerRoot = new AliRawReaderDateOnline(rawDataInPath); + readerRoot->SelectEquipment(0, 1024, 1041); + readerRoot->Select("TRD"); + //readerRoot->SelectEvents(7); + reader = (AliRawReader*)readerRoot; + } + + AliTRDdigitsManager* digitMan = new AliTRDdigitsManager; + digitMan->CreateArrays(); + + AliTRDrawStream* rawStream = new AliTRDrawStream(reader); + + TClonesArray trkl("AliTRDtrackletMCM"); + rawStream->SetTrackletArray(&trkl); + + int ievent = 0; + while (reader->NextEvent()) { + ievent++; + int eventtime = ievent * 12; + + if (ievent >= nRawEvents) + break; + + //digitMan->ResetArrays(); + + if (ievent % 10 == 0) { + cout << "Event " << ievent << endl; + } + + // hntrkl->Fill(trkl.GetEntries()); + while (rawStream->NextChamber(digitMan) >= 0) { + //hptphase->Fill(digMan->GetDigitsParam()->GetPretriggerPhase()); + } + + for (int det = 0; det < AliTRDCommonParam::kNdet; det++) { + AliTRDSignalIndex* idx = digitMan->GetIndexes(det); + + if (!idx) + continue; + if (!idx->HasEntry()) + continue; + + int row, col; + while (idx->NextRCIndex(row, col)) { + int tbsum = 0; + ArrayADC adctimes; + for (int timebin = 0; timebin < digitMan->GetDigits(det)->GetNtime(); timebin++) { + int adc = digitMan->GetDigits(det)->GetData(row, col, timebin); + hAdc->Fill(adc); + tbsum += adc; + + adctimes[timebin] = adc; + } + + if (tbsum > 0) { + run3Digits.push_back(o2::trd::Digit(det, row, col, adctimes, eventtime)); + } + + hTBsum->Fill(tbsum); + } + } + trkl.Clear(); + } + + delete rawStream; + if (reader) + delete reader; + } + + // convert run2 digits if path set + if (run2DigitsInPath != "") { + cout << "Converting Run2 digits..." << endl; + + TFile run2DigitsFile(run2DigitsInPath); + AliTRDdigitsManager* digitMan = new AliTRDdigitsManager; + digitMan->CreateArrays(); + + TIter next(run2DigitsFile.GetListOfKeys()); + + uint64_t triggerRecordsStart = 0; + int recordSize = 0; + int ievent = 0; + while (TObject* obj = next()) { + cout << "Processing " << obj->GetName() << endl; + + // eventTime needs to be some increasing integer + string eventNumber(obj->GetName(), 5, 3); + int eventTime = stoi(eventNumber) * 12; + + TTree* tr = (TTree*)run2DigitsFile.Get(Form("%s/TreeD", obj->GetName())); + + for (int det = 0; det < AliTRDCommonParam::kNdet; det++) { + digitMan->ClearArrays(det); + digitMan->ClearIndexes(det); + } + + digitMan->ReadDigits(tr); + + for (int det = 0; det < AliTRDCommonParam::kNdet; det++) { + if (!digitMan->GetDigits(det)) + continue; + + int sector = det / 30; + int stack = (det - sector * 30) / 6; + + digitMan->GetDigits(det)->Expand(); + + int nrows = AliTRDfeeParam::GetNrowC1(); + if (stack == 2) { + nrows = AliTRDfeeParam::GetNrowC0(); + } + + // cout << "det: " << det << " | " << "sector: " << sector << " | " << "stack: " << stack << " | " << "rows: " << nrows << endl; + + for (int row = 0; row < nrows; row++) { + for (int col = 0; col < AliTRDfeeParam::GetNcol(); col++) { + int tbsum = 0; + ArrayADC adctimes; + + for (int timebin = 0; timebin < digitMan->GetDigits(det)->GetNtime(); timebin++) { + + if (digitMan->GetDigits(det)->GetNtime() > 30) { + cout << "----!!! --- number of times is greater than 30" << endl; + } + + int adc = digitMan->GetDigitAmp(row, col, timebin, det); + adctimes[timebin] = adc; + + // this value seems to indicate no digit -> skip + if (adc == -7169) + continue; + + hAdc->Fill(adc); + tbsum += adc; + } + + if (tbsum > 0) { + run3Digits.push_back(o2::trd::Digit(det, row, col, adctimes, eventTime)); + } + + if (tbsum > 0) { + hTBsum->Fill(tbsum); + } + } + } + recordSize = run3Digits.size() - triggerRecordsStart; + triggerRecords.emplace_back(ievent, triggerRecordsStart, recordSize); + triggerRecordsStart = run3Digits.size(); + ievent++; + } + } + } + + // show and write QA + if (qaOutPath != "") { + hAdc->SetXTitle("ADC value"); + hAdc->SetYTitle("number of entries"); + + TCanvas* cnv_adc = new TCanvas("cnv_adc", "cnv_adc"); + cnv_adc->SetLogy(); + hAdc->Draw(); + + TCanvas* cnv_tbsum = new TCanvas("cnv_tbsum", "cnv_tbsum"); + cnv_adc->SetLogy(); + hTBsum->Draw(); + + TFile* outFile = new TFile(qaOutPath, "RECREATE"); + hAdc->Write(); + hTBsum->Write(); + + cout << "QA output written to: " << qaOutPath << endl; + } + + // write run3 digits + if (run3Digits.size() != 0) { + TFile* digitsFile = new TFile(run3DigitsOutPath, "RECREATE"); + TTree* digitTree = new TTree("o2sim", "run2 digits"); + std::vector<o2::trd::Digit>* run3pdigits = &run3Digits; + digitTree->Branch("TRDDigit", &run3pdigits); + digitTree->Branch("TriggerRecord", &triggerRecords); + digitTree->Fill(); + cout << run3Digits.size() << " run3 digits written to: " << run3DigitsOutPath << endl; + digitTree->Write(); + delete digitTree; + delete digitsFile; + } +} diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 4130e4f4a564a..7f00bd28c0b29 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -28,6 +28,7 @@ list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Detectors/TRD/base/macros/Readocdb.C Detectors/TRD/base/macros/PrintTrapConfig.C Detectors/TRD/base/macros/ConvertRun2DigitsAndTracklets.C + Detectors/TRD/macros/convertRun2ToRun3Digits.C Detectors/TRD/macros/ParseTrapRawOutput.C Detectors/EMCAL/calib/macros/ReadTestBadChannelMap_CCDBApi.C GPU/GPUTracking/Merger/macros/checkPropagation.C # Needs AliRoot AliExternalTrackParam From ca589b32704fd4f0918f1590341e2a53c896b209 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 6 Aug 2020 16:25:54 +0200 Subject: [PATCH 0376/1751] Make DecoderBase class an abstract one --- .../include/TOFReconstruction/DecoderBase.h | 13 ++++--------- Detectors/TOF/reconstruction/src/DecoderBase.cxx | 2 +- .../include/TOFWorkflow/CompressedDecodingTask.h | 4 ++++ .../include/TOFWorkflow/CompressedInspectorTask.h | 2 ++ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h index bef010acc2cd7..54e9d3031ebf3 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h @@ -63,20 +63,15 @@ class DecoderBaseT private: /** handlers **/ - virtual void rdhHandler(const RDH* rdh){}; - virtual void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit){}; + virtual void rdhHandler(const RDH* rdh) = 0; + virtual void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) = 0; virtual void frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, - const FrameHeader_t* frameHeader, const PackedHit_t* packedHits){}; + const FrameHeader_t* frameHeader, const PackedHit_t* packedHits) = 0; virtual void trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics, - const Error_t* errors){}; - - /** old API, deprecated **/ - - virtual void trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, - const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics){}; + const Error_t* errors) = 0; bool processHBF(); bool processDRM(); diff --git a/Detectors/TOF/reconstruction/src/DecoderBase.cxx b/Detectors/TOF/reconstruction/src/DecoderBase.cxx index 5e80b7af217fe..a52b6277cb1a1 100644 --- a/Detectors/TOF/reconstruction/src/DecoderBase.cxx +++ b/Detectors/TOF/reconstruction/src/DecoderBase.cxx @@ -188,7 +188,7 @@ bool DecoderBaseT<RDH>::processDRM() auto crateTrailer = reinterpret_cast<const CrateTrailer_t*>(mDecoderPointer); #ifdef DECODER_VERBOSE if (mDecoderVerbose) { - printf(" %08x CrateTrailer (numberOfDiagnostics=%d, numberOfErrors=%d) \n ", *mDecoderPointer, crateTrailer->numberOfDiagnostics, numberOfErrors); + printf(" %08x CrateTrailer (numberOfDiagnostics=%d, numberOfErrors=%d) \n ", *mDecoderPointer, crateTrailer->numberOfDiagnostics, crateTrailer->numberOfErrors); } #endif mDecoderPointer++; diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h index 85dc44202c6c8..1913eec763909 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h @@ -46,8 +46,12 @@ class CompressedDecodingTask : public DecoderBase, public Task private: /** decoding handlers **/ void rdhHandler(const o2::header::RAWDataHeader* rdh) override; + void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) override{}; void frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, const FrameHeader_t* frameHeader, const PackedHit_t* packedHits) override; + void trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics, + const Error_t* errors) override{}; o2::tof::compressed::Decoder mDecoder; std::vector<std::vector<o2::tof::Digit>> mDigits; diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h index 18da10a73bcb5..535bdd61f2d47 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h @@ -46,6 +46,8 @@ class CompressedInspectorTask : public DecoderBaseT<RDH>, public Task private: /** decoding handlers **/ + void rdhHandler(const RDH* rdh) override{}; + void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) override; void frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, From 12cf825d8fc815fbdd071423d7d9f24fcea3843b Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Mon, 17 Aug 2020 10:57:59 +0200 Subject: [PATCH 0377/1751] Momentum vector components added to the Muons table in AnalysisDataModel (#4122) * Initial commit for test base classes for Event, Track and Analysis objects * Added a task which produces trees of ReducedEvent objects * first commit for an example skimmed data table maker and reader * Tables in ReducedInfoTables redefined using the existing columns in the central data model. Removed dependency on the VarManager for the HistogramManager * Removed commented parts in the code * Small changes to the Histogram and Variable managers. First commit of the analysis cut classes * AnalysisCut and AnalysisCompositeCut classes added; other small improvements * Update in the DQ skimmed data model (muon tables); added templated Fill() functions in the VarManager; trigger aliases included in the event table; added more developments in the table maker and table reader tasks * added calculation of MUON track momentum --- Analysis/Core/include/Analysis/AnalysisCut.h | 6 +- Analysis/Core/src/AnalysisCut.cxx | 2 +- Analysis/Tasks/CMakeLists.txt | 5 - Analysis/Tasks/invMassAnalysis.cxx | 135 ------------------ Analysis/Tasks/tableMaker.cxx | 17 +-- Analysis/Tasks/tableReader.cxx | 2 +- .../include/Framework/AnalysisDataModel.h | 40 +++++- Framework/Core/src/AODReaderHelpers.cxx | 4 +- 8 files changed, 44 insertions(+), 167 deletions(-) delete mode 100644 Analysis/Tasks/invMassAnalysis.cxx diff --git a/Analysis/Core/include/Analysis/AnalysisCut.h b/Analysis/Core/include/Analysis/AnalysisCut.h index 7b5ce3f781a54..2a9bc68822a7b 100644 --- a/Analysis/Core/include/Analysis/AnalysisCut.h +++ b/Analysis/Core/include/Analysis/AnalysisCut.h @@ -19,8 +19,6 @@ #include <TF1.h> #include <vector> -using std::vector; - //_________________________________________________________________________ class AnalysisCut : public TNamed { @@ -43,7 +41,7 @@ class AnalysisCut : public TNamed // But this would require to have access to the VarManager for extracting variables virtual bool IsSelected(float* values); - static vector<int> fgUsedVars; //! vector of used variables + static std::vector<int> fgUsedVars; //! vector of used variables struct CutContainer { short fVar; // variable to be cut upon @@ -66,7 +64,7 @@ class AnalysisCut : public TNamed }; protected: - vector<CutContainer> fCuts; + std::vector<CutContainer> fCuts; ClassDef(AnalysisCut, 1); }; diff --git a/Analysis/Core/src/AnalysisCut.cxx b/Analysis/Core/src/AnalysisCut.cxx index 02289075cfa20..64dc65874cefb 100644 --- a/Analysis/Core/src/AnalysisCut.cxx +++ b/Analysis/Core/src/AnalysisCut.cxx @@ -16,7 +16,7 @@ using std::endl; ClassImp(AnalysisCut); -vector<int> AnalysisCut::fgUsedVars = {}; +std::vector<int> AnalysisCut::fgUsedVars = {}; //____________________________________________________________________________ AnalysisCut::AnalysisCut() : TNamed(), diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index dd58f52c61992..3569d83a655b1 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -116,11 +116,6 @@ o2_add_dpl_workflow(centrality-qa PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) -o2_add_dpl_workflow(invmass-an - SOURCES invMassAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - o2_add_dpl_workflow(table-maker SOURCES tableMaker.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore diff --git a/Analysis/Tasks/invMassAnalysis.cxx b/Analysis/Tasks/invMassAnalysis.cxx deleted file mode 100644 index 7403df356a15f..0000000000000 --- a/Analysis/Tasks/invMassAnalysis.cxx +++ /dev/null @@ -1,135 +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. -#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 <TH1F.h> -#include <TH2F.h> -#include <TMath.h> -#include "TVector3.h" -#include "TLorentzVector.h" -#include <cmath> -#include <vector> - -const float gkMass = 0.0005; - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -// This is a very simple example showing how to create an histogram -// FIXME: this should really inherit from AnalysisTask but -// we need GCC 7.4+ for that - -struct InvMassAnalysis { - // needs to be initialized with a label or an obj - // when adding an object to OutputObj later, the object name will be - // *reset* to OutputObj label - needed for correct placement in the output file - OutputObj<TH1F> centV0M{TH1F("centV0M", "centrality V0", 100, 0.0, 100.0)}; - OutputObj<TH1F> vtxZ{TH1F("vtxZ", "vtx Z", 200, -20.0, 20.0)}; - - OutputObj<TH1F> ptH{TH1F("pt", "pt", 100, -0.01, 10.01)}; - OutputObj<TH2F> ptCorr{TH2F("ptToPt", "ptToPt", 100, -0.01, 10.01, 100, -0.01, 10.01)}; - OutputObj<TH2F> tpcDedx{TH2F("tpcDedx", "TPC de/dx", 100, 0.0, 10.0, 100, 0.0, 200.0)}; - OutputObj<TH1I> itsHits{TH1I("itsHits", "ITS hits per layer", 6, -0.5, 5.5)}; - OutputObj<TH2I> itsHitsVsPt{TH2I("itsHitsVsPt", "ITS hits per layer", 6, -0.5, 5.5, 100, 0.0, 10.0)}; - OutputObj<TH1I> itsChi2{TH1I("itsChi2", "ITS chi2", 100, 0.0, 20.0)}; - OutputObj<TH1I> tpcChi2{TH1I("tpcChi2", "TPC chi2", 100, 0.0, 10.0)}; - OutputObj<TH1I> tpcCls{TH1I("tpcCls", "TPC clusters", 160, 0.0, 160.0)}; - OutputObj<TH1I> flagsHist{TH1I("flagsHist", "Flags", 64, -0.5, 63.5)}; - OutputObj<TH1F> invMassPM{TH1F("invMassPM", "Invariant mass, SEPM", 125, 0.0, 5.0)}; - OutputObj<TH1F> invMassPP{TH1F("invMassPP", "Invariant mass, SEPP", 125, 0.0, 5.0)}; - OutputObj<TH1F> invMassMM{TH1F("invMassMM", "Invariant mass, SEMM", 125, 0.0, 5.0)}; - OutputObj<TH2F> invMassVsPt{TH2F("invMassVsPt", "Invariant mass", 125, 0.0, 5.0, 10, 0.0, 10.0)}; - OutputObj<TH2F> invMassVsCentrality{TH2F("invMassVsCentrality", "Invariant mass", 125, 0.0, 5.0, 10, 0.0, 100.0)}; - OutputObj<TH1F> trZ{"trZ", OutputObjHandlingPolicy::QAObject}; - //Configurable<float> ptlow{"ptlow", 1.0f, "Lower pT limit"}; - //Configurable<float> pthigh{"pthigh", 1.0f, "Higher pT limit"}; - - float ptlow = 1.0; - float pthigh = 5.0; - Filter ptFilter = ((1.0f / aod::track::signed1Pt > ptlow) && (1.0f / aod::track::signed1Pt < pthigh)) || ((1.0f / aod::track::signed1Pt > -1.0f * pthigh) && (1.0f / aod::track::signed1Pt < -1.0f * ptlow)); - //Filter spdAnyFilter = (aod::track::itsClusterMap & (uint8_t(1)<<0)) || (aod::track::itsClusterMap & (uint8_t(1)<<1)); - float dedxLow = 75.0; - float dedxHigh = 90.0; - Filter dedxFilter = (aod::track::tpcSignal > dedxLow) && (aod::track::tpcSignal < dedxHigh); - float tpcChi2Max = 4.0; - float itsChi2Max = 36; - Filter qualityFilter = (aod::track::tpcChi2NCl < tpcChi2Max) && (aod::track::itsChi2NCl < itsChi2Max); - - void init(InitContext const&) - { - trZ.setObject(new TH1F("Z", "Z", 100, -10., 10.)); - } - - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra>> const& tracks) - { - - if (!collision.sel7()) - return; - - centV0M->Fill(collision.centV0M()); - vtxZ->Fill(collision.posZ()); - - for (auto& track : tracks) { - //if (track.pt() < ptlow) - // continue; - ptH->Fill(track.pt()); - trZ->Fill(track.z()); - itsChi2->Fill(track.itsChi2NCl()); - for (int i = 0; i < 6; i++) { - if (track.itsClusterMap() & (uint8_t(1) << i)) - itsHits->Fill(i); - if (track.itsClusterMap() & (uint8_t(1) << i)) - itsHitsVsPt->Fill(i, track.pt()); - } - tpcDedx->Fill(track.tpcInnerParam(), track.tpcSignal()); - tpcChi2->Fill(track.tpcChi2NCl()); - tpcCls->Fill(track.tpcNClsFound()); - for (int i = 0; i < 64; i++) { - if (track.flags() & (uint64_t(1) << i)) - flagsHist->Fill(i); - } - } - for (auto& [t0, t1] : combinations(tracks, tracks)) { - ptCorr->Fill(t0.pt(), t1.pt()); - if (!((t0.itsClusterMap() & (uint8_t(1) << 0)) || (t0.itsClusterMap() & (uint8_t(1) << 1)))) - continue; - if (!((t1.itsClusterMap() & (uint8_t(1) << 0)) || (t1.itsClusterMap() & (uint8_t(1) << 1)))) - continue; - - TLorentzVector p1, p2, p; - p1.SetXYZM(t0.px(), t0.py(), t0.pz(), gkMass); - p2.SetXYZM(t1.px(), t1.py(), t1.pz(), gkMass); - p = p1 + p2; - - if (t0.charge() * t1.charge() < 0) { - invMassPM->Fill(p.M()); - invMassVsPt->Fill(p.M(), p.Pt()); - invMassVsCentrality->Fill(p.M(), collision.centV0M()); - } else { - if (t0.charge() > 0) - invMassPP->Fill(p.M()); - if (t0.charge() < 0) - invMassMM->Fill(p.M()); - } - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<InvMassAnalysis>("InvMassAnalysis")}; -} diff --git a/Analysis/Tasks/tableMaker.cxx b/Analysis/Tasks/tableMaker.cxx index 09aa452ee7acf..2252e3872c3a2 100644 --- a/Analysis/Tasks/tableMaker.cxx +++ b/Analysis/Tasks/tableMaker.cxx @@ -21,8 +21,6 @@ #include "Analysis/ReducedInfoTables.h" #include "Analysis/VarManager.h" #include "Analysis/HistogramManager.h" -#include <TH1F.h> -#include <TMath.h> #include <iostream> using std::cout; @@ -105,18 +103,7 @@ struct TableMaker { if (muon.bc() != collision.bc()) continue; trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track - //TODO: the calculation of the muon momentum vector should be done in the central data model - float xSlope = tan(muon.thetaX()); - float ySlope = tan(muon.thetaY()); - float pz = -sqrt(1.0 + ySlope * ySlope) / abs(muon.inverseBendingMomentum()); - float pt = abs(pz) * sqrt(xSlope * xSlope + ySlope * ySlope); - float phi = atan2(ySlope, xSlope); - phi = (phi >= 0.0 ? phi : phi + TMath::TwoPi()); - float eta = acos(pz / sqrt(pt * pt + pz * pz)); - eta = tan(0.5 * eta); - if (eta > 0.0) - eta = -log(eta); - muonBasic(collision, trackFilteringTag, pt, eta, phi, (muon.inverseBendingMomentum() > 0.0 ? short(1) : short(-1))); + muonBasic(collision, trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); } } @@ -151,7 +138,7 @@ struct TableMaker { } }; -WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const&) +WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<TableMaker>("table-maker")}; diff --git a/Analysis/Tasks/tableReader.cxx b/Analysis/Tasks/tableReader.cxx index 805920c0a0663..e773bcb5f330b 100644 --- a/Analysis/Tasks/tableReader.cxx +++ b/Analysis/Tasks/tableReader.cxx @@ -229,7 +229,7 @@ struct TableReader { 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, 200, 0.0, 20.0, VarManager::kPz); + fHistMan->AddHistogram(classStr.Data(), "Pz", "p_{z} distribution", false, 400, -20.0, 20.0, VarManager::kPz); if (classStr.Contains("Barrel")) { fHistMan->AddHistogram(classStr.Data(), "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 100, 0.0, 20.0, VarManager::kPin, diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index f28bdca35311e..3ccf48e016a9d 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -309,13 +309,43 @@ DECLARE_SOA_COLUMN(NonBendingCoor, nonBendingCoor, float); // DECLARE_SOA_COLUMN(Covariances, covariances, float[], "fCovariances"); DECLARE_SOA_COLUMN(Chi2, chi2, float); DECLARE_SOA_COLUMN(Chi2MatchTrigger, chi2MatchTrigger, float); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float inverseBendingMomentum, float thetaX, float thetaY) -> float { + float pz = -std::sqrt(1.0 + std::tan(thetaY) * std::tan(thetaY)) / std::abs(inverseBendingMomentum); + float pt = std::abs(pz) * std::sqrt(std::tan(thetaX) * std::tan(thetaX) + std::tan(thetaY) * std::tan(thetaY)); + float eta = std::acos(pz / std::sqrt(pt * pt + pz * pz)); + eta = std::tan(0.5 * eta); + if (eta > 0.0) + return -std::log(eta); + else + return 0.0; +}); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float thetaX, float thetaY) -> float { + float phi = std::atan2(std::tan(thetaY), std::tan(thetaX)); + constexpr float twopi = 2.0f * static_cast<float>(M_PI); + return (phi >= 0.0 ? phi : phi + twopi); +}); +DECLARE_SOA_EXPRESSION_COLUMN(Pt, pt, float, nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) * nsqrt(ntan(aod::muon::thetaX) * ntan(aod::muon::thetaX) + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, -1.0f * ntan(aod::muon::thetaX) * nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, -1.0f * ntan(aod::muon::thetaY) * nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, -1.0f * nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); +DECLARE_SOA_DYNAMIC_COLUMN(Charge, charge, [](float inverseBendingMomentum) -> short { return (inverseBendingMomentum > 0.0f) ? 1 : -1; }); } // namespace muon -DECLARE_SOA_TABLE(Muons, "AOD", "MUON", - muon::BCId, muon::InverseBendingMomentum, - muon::ThetaX, muon::ThetaY, muon::ZMu, - muon::BendingCoor, muon::NonBendingCoor, - muon::Chi2, muon::Chi2MatchTrigger); +DECLARE_SOA_TABLE_FULL(StoredMuons, "Muons", "AOD", "MUON", + muon::BCId, muon::InverseBendingMomentum, + muon::ThetaX, muon::ThetaY, muon::ZMu, + muon::BendingCoor, muon::NonBendingCoor, + muon::Chi2, muon::Chi2MatchTrigger, + muon::Eta<muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY>, + muon::Phi<muon::ThetaX, muon::ThetaY>, + muon::Charge<muon::InverseBendingMomentum>); + +DECLARE_SOA_EXTENDED_TABLE(Muons, StoredMuons, "MUON", + aod::muon::Pt, + aod::muon::Px, + aod::muon::Py, + aod::muon::Pz); + using Muon = Muons::iterator; // NOTE for now muon tracks are uniquely assigned to a BC / GlobalBC assuming they contain an MID hit. Discussion on tracks without MID hit is ongoing. diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 751cd6b4228db..d58cc43322bff 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -179,6 +179,8 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> reques outputs.adopt(Output{origin, description}, maker(o2::aod::TracksMetadata{})); } else if (description == header::DataDescription{"TRACKPARCOV"}) { outputs.adopt(Output{origin, description}, maker(o2::aod::TracksCovMetadata{})); + } else if (description == header::DataDescription{"MUON"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::MuonsMetadata{})); } else { throw std::runtime_error("Not an extended table"); } @@ -262,7 +264,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() tableMaker(o2::aod::TracksExtraMetadata{}, AODTypeMask::TrackExtra, "O2track"); tableMaker(o2::aod::CalosMetadata{}, AODTypeMask::Calo, "O2calo"); tableMaker(o2::aod::CaloTriggersMetadata{}, AODTypeMask::Calo, "O2calotrigger"); - tableMaker(o2::aod::MuonsMetadata{}, AODTypeMask::Muon, "O2muon"); + tableMaker(o2::aod::StoredMuonsMetadata{}, AODTypeMask::Muon, "O2muon"); tableMaker(o2::aod::MuonClustersMetadata{}, AODTypeMask::Muon, "O2muoncluster"); tableMaker(o2::aod::ZdcsMetadata{}, AODTypeMask::Zdc, "O2zdc"); tableMaker(o2::aod::BCsMetadata{}, AODTypeMask::BC, "O2bc"); From 5b61e453c8c4cbe8432f709175254e0a7df5b9fc Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Mon, 17 Aug 2020 15:32:43 +0200 Subject: [PATCH 0378/1751] [EMCAL-646] Reject STU DDLs for FEE raw parsing STU DDLs numbered 44 and 45 will be rejected as the raw format is different. --- Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C | 2 ++ Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx | 3 +++ 2 files changed, 5 insertions(+) diff --git a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C index dca05281523ad..e5106ef2971e6 100644 --- a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C +++ b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C @@ -77,6 +77,8 @@ void RawFitterTESTs(const char* filename = "") while (parser.hasNext()) { parser.next(); std::cout << "next page \n"; + if (o2::raw::RDHUtils::getFEEID(parser.getRawHeader()) >= 40) + continue; //std::cout<<rawreader.getRawHeader()<<std::endl; diff --git a/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx b/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx index e899dfe00b0ab..69daeafbdf80b 100644 --- a/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx +++ b/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx @@ -93,6 +93,9 @@ int main(int argc, char** argv) o2::emcal::RawReaderMemory parser(dataBuffer); while (parser.hasNext()) { parser.next(); + // Exclude STU DDLs + if (o2::raw::RDHUtils::getFEEID(parser.getRawHeader()) >= 40) + continue; o2::emcal::AltroDecoder decoder(parser); decoder.decode(); From 4412e19b9871780d6e9b10c45c16c482e9cbe370 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 15 Aug 2020 18:01:38 +0200 Subject: [PATCH 0379/1751] Changes to allow reading of incomplete/corrupted data Allows to read data missing TF flags --- Detectors/Raw/include/DetectorsRaw/RawFileReader.h | 2 ++ Detectors/Raw/src/RawFileReader.cxx | 12 +++++++----- Detectors/Raw/src/RawFileReaderWorkflow.cxx | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index 7754ac7cf7661..af651f51744b7 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -223,6 +223,7 @@ class RawFileReader size_t getBufferSize() const { return mBufferSize; } void setMaxTFToRead(uint32_t n) { mMaxTFToRead = n; } + bool isEmpty() const { return mEmpty; } uint32_t getMaxTFToRead() const { return mMaxTFToRead; } uint32_t getNTimeFrames() const { return mNTimeFrames; } uint32_t getOrbitMin() const { return mOrbitMin; } @@ -259,6 +260,7 @@ class RawFileReader std::vector<std::unique_ptr<char[]>> mFileBuffers; //! buffers for input files std::vector<OrigDescCard> mDataSpecs; //! data origin and description for every input file + readout card type bool mInitDone = false; + bool mEmpty = true; std::unordered_map<LinkSpec_t, int> mLinkEntries; //! mapping between RDH specs and link entry in the mLinksData std::vector<LinkData> mLinksData; //! info on links data in the files std::vector<int> mOrderedIDs; //! links entries ordered in Specs diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index 669c4a1fa6e6c..a10217ee73dd5 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -512,7 +512,7 @@ bool RawFileReader::preprocessFile(int ifl) long int nr = 0; mPosInFile = 0; size_t nRDHread = 0, boffs; - bool ok = true, readMore = true; + bool readMore = true; while (readMore && (nr = fread(buffer.get(), 1, mBufferSize, fl))) { boffs = 0; while (1) { @@ -556,7 +556,7 @@ bool RawFileReader::preprocessFile(int ifl) } LOGF(INFO, "File %3d : %9li bytes scanned, %6d RDH read for %4d links from %s", mCurrentFileID, mPosInFile, nRDHread, int(mLinkEntries.size()), mFileNames[mCurrentFileID]); - return ok; + return nRDHread > 0; } //_____________________________________________________________________ @@ -638,9 +638,11 @@ bool RawFileReader::init() } int nf = mFiles.size(); - bool ok = true; + mEmpty = true; for (int i = 0; i < nf; i++) { - ok &= preprocessFile(i); + if (preprocessFile(i)) { + mEmpty = false; + } } mOrderedIDs.resize(mLinksData.size()); for (int i = mLinksData.size(); i--;) { @@ -691,7 +693,7 @@ bool RawFileReader::init() } mInitDone = true; - return ok; + return !mEmpty; } //_____________________________________________________________________ diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index 779628a8d34cf..f8ff628bf2412 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -70,7 +70,7 @@ class RawReaderSpecs : public o2f::Task mReader->init(); mTimer[TimerInit].Stop(); if (mMaxTFID >= mReader->getNTimeFrames()) { - mMaxTFID = mReader->getNTimeFrames() - 1; + mMaxTFID = mReader->getNTimeFrames() ? mReader->getNTimeFrames() - 1 : 0; } } @@ -111,7 +111,7 @@ class RawReaderSpecs : public o2f::Task std::unordered_map<std::string, std::unique_ptr<FairMQParts>> messagesPerRoute; if (tfID > mMaxTFID) { - if (mReader->getNTimeFrames() && --mLoop) { + if (!mReader->isEmpty() && --mLoop) { mLoopsDone++; tfID = 0; LOG(INFO) << "Starting new loop " << mLoopsDone << " from the beginning of data"; From 48404ce61350aa042ddbfa6473384c970d697319 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 18 Aug 2020 09:55:24 +0200 Subject: [PATCH 0380/1751] adding transient collision id table for v0 and cascades (#4167) --- Analysis/DataModel/src/dumpDataModel.cxx | 4 +- Analysis/Tutorials/CMakeLists.txt | 3 + Analysis/Tutorials/src/vzeroIteration.cxx | 70 +++++++++++++++++++ .../include/Framework/AnalysisDataModel.h | 14 +++- 4 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 Analysis/Tutorials/src/vzeroIteration.cxx diff --git a/Analysis/DataModel/src/dumpDataModel.cxx b/Analysis/DataModel/src/dumpDataModel.cxx index ab9467e910f57..d88b7ba67f16b 100644 --- a/Analysis/DataModel/src/dumpDataModel.cxx +++ b/Analysis/DataModel/src/dumpDataModel.cxx @@ -154,8 +154,8 @@ edge[dir=back, arrowtail=empty] dumpTable<MuonClusters>(); dumpTable<Zdcs>(); dumpTable<Run2V0s>(); - dumpTable<V0s>(); - dumpTable<Cascades>(); + dumpTable<StoredV0s>(); + dumpTable<StoredCascades>(); dumpTable<BCs>(); dumpTable<FT0s>(); dumpTable<FV0s>(); diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index 43c73dab44567..6f88aac54e65a 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -112,3 +112,6 @@ o2_add_dpl_workflow(custom-index PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) +o2_add_dpl_workflow(vzero-iteration + SOURCES src/vzeroIteration.cxx + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/vzeroIteration.cxx b/Analysis/Tutorials/src/vzeroIteration.cxx new file mode 100644 index 0000000000000..50d46e0290290 --- /dev/null +++ b/Analysis/Tutorials/src/vzeroIteration.cxx @@ -0,0 +1,70 @@ +// 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" + +using namespace o2; +using namespace o2::framework; + +struct ATask { + Produces<aod::TransientV0s> transientV0s; + Produces<aod::TransientCascades> transientCascades; + + void process(aod::StoredV0s const& v0s, aod::StoredCascades const& cascades, aod::Tracks const& tracks) + { + for (auto& v0 : v0s) { + transientV0s(v0.posTrack().collisionId()); + } + for (auto& cascade : cascades) { + transientCascades(cascade.bachelor().collisionId()); + } + } +}; + +struct BTask { + void process(aod::V0s const& v0s, aod::Tracks const& tracks) + { + for (auto& v0 : v0s) { + LOGF(DEBUG, "V0 (%d, %d, %d)", v0.posTrack().collisionId(), v0.negTrack().collisionId(), v0.collisionId()); + } + } +}; + +struct CTask { + void process(aod::Cascades const& cascades, aod::Tracks const& tracks) + { + for (auto& cascade : cascades) { + LOGF(DEBUG, "Cascade (%d, %d)", cascade.bachelor().collisionId(), cascade.collisionId()); + } + } +}; + +// Grouping +struct DTask { + void process(aod::Collision const& collision, aod::V0s const& v0s, aod::Tracks const& tracks) + { + LOGF(INFO, "Collision %d has %d V0s", collision.globalIndex(), v0s.size()); + + for (auto& v0 : v0s) { + LOGF(DEBUG, "Collision %d V0 %d (%d, %d)", collision.globalIndex(), v0.globalIndex(), v0.posTrackId(), v0.negTrackId()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<ATask>("produce-v0index"), + adaptAnalysisTask<BTask>("consume-v0"), + adaptAnalysisTask<CTask>("consume-cascades"), + adaptAnalysisTask<DTask>("consume-grouped-v0"), + }; +} diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 3ccf48e016a9d..ce5dc815e8d53 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -441,19 +441,27 @@ namespace v0 { DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, Tracks, "fPosTrackID"); DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, Tracks, "fNegTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace v0 -DECLARE_SOA_TABLE(V0s, "AOD", "V0", v0::PosTrackId, v0::NegTrackId); +DECLARE_SOA_TABLE(StoredV0s, "AOD", "O2v0", o2::soa::Index<>, v0::PosTrackId, v0::NegTrackId); +DECLARE_SOA_TABLE(TransientV0s, "AOD", "V0INDEX", v0::CollisionId); + +using V0s = soa::Join<TransientV0s, StoredV0s>; using V0 = V0s::iterator; namespace cascade { DECLARE_SOA_INDEX_COLUMN(V0, v0); DECLARE_SOA_INDEX_COLUMN_FULL(Bachelor, bachelor, int, Tracks, "fTracksID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace cascade -DECLARE_SOA_TABLE(Cascades, "AOD", "CASCADE", cascade::V0Id, cascade::BachelorId); -using Casecade = Cascades::iterator; +DECLARE_SOA_TABLE(StoredCascades, "AOD", "O2cascade", o2::soa::Index<>, cascade::V0Id, cascade::BachelorId); +DECLARE_SOA_TABLE(TransientCascades, "AOD", "CASCADEINDEX", cascade::CollisionId); + +using Cascades = soa::Join<TransientCascades, StoredCascades>; +using Cascade = Cascades::iterator; // ---- LEGACY tables ---- From e62bc7512e09ef7308a91afe4e32451d91b37dcb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 18 Aug 2020 13:11:08 +0200 Subject: [PATCH 0381/1751] Revert "DPL Analysis: Extended histogram registry to use TH2 and TH3 (#4063)" This reverts commit 7c43a8ad1b435ffaf09db8c3cee7e2ded69ae204. --- .../include/Framework/HistogramRegistry.h | 139 ++---------------- .../Core/test/benchmark_HistogramRegistry.cxx | 2 +- .../Core/test/test_HistogramRegistry.cxx | 6 +- 3 files changed, 18 insertions(+), 129 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 6ad5db6d480de..75ca56a0eea43 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -32,66 +32,31 @@ namespace o2 namespace framework { -// Most common histogram types -enum HistogramType { - kTH1D, - kTH1F, - kTH1I, - kTH2D, - kTH2F, - kTH2I, - kTH3D, - kTH3F, - kTH3I -}; - -/// Description of a single histogram axis -struct AxisSpec { - AxisSpec(int nBins_, std::vector<double> bins_, std::string label_ = "") - : nBins(nBins_), - bins(bins_), - binsEqual(false), - label(label_) - { - } - - AxisSpec(int nBins_, double binMin_, double binMax_, std::string label_ = "") - : nBins(nBins_), - bins({binMin_, binMax_}), - binsEqual(true), - label(label_) - { - } - - AxisSpec() : nBins(1), binsEqual(false), bins(), label("") {} - - int nBins; - std::vector<double> bins; - bool binsEqual; // if true, then bins specify min and max for equidistant binning - std::string label; -}; - /// Data sctructure that will allow to construct a fully qualified TH* histogram +/// Currently only supports TH1F struct HistogramConfigSpec { - HistogramConfigSpec(HistogramType type_, std::vector<AxisSpec> axes_) - : type(type_), - axes(axes_), - binsEqual(axes.size() > 0 ? axes[0].binsEqual : false) + HistogramConfigSpec(char const* const kind_, unsigned int nBins_, double xmin_, double xmax_) + : kind(kind_), + nBins(nBins_), + xmin(xmin_), + xmax(xmax_) { } HistogramConfigSpec() - : type(HistogramType::kTH1F), - axes(), - binsEqual(false) + : kind(""), + nBins(1), + xmin(0), + xmax(1) { } HistogramConfigSpec(HistogramConfigSpec const& other) = default; HistogramConfigSpec(HistogramConfigSpec&& other) = default; - HistogramType type; - std::vector<AxisSpec> axes; - bool binsEqual; + std::string kind; + unsigned int nBins; + double xmin; + double xmax; }; /// Data structure containing histogram specification for the HistogramRegistry @@ -121,80 +86,6 @@ struct HistogramSpec { HistogramConfigSpec config; }; -class HistogramFactory -{ - public: - static std::unique_ptr<TH1> create(HistogramSpec& spec) - { - const auto& it = lookup().find(spec.config.type); - if (it == lookup().end()) { - return nullptr; - } - return std::move(it->second->createImpl(spec)); - } - - protected: - static std::map<HistogramType, HistogramFactory*>& lookup() - { - static std::map<HistogramType, HistogramFactory*> histMap; - return histMap; - } - - private: - virtual std::unique_ptr<TH1> createImpl(HistogramSpec const& spec) = 0; -}; - -template <typename T> -class HistogramFactoryImpl : public HistogramFactory -{ - public: - HistogramFactoryImpl(HistogramType type) - : position(this->lookup().insert(std::make_pair(type, this)).first) - { - } - - ~HistogramFactoryImpl() - { - this->lookup().erase(position); - } - - private: - std::unique_ptr<TH1> createImpl(HistogramSpec const& spec) override - { - if (spec.config.axes.size() == 0) { - throw std::runtime_error("No arguments available in spec to create a histogram"); - } - if constexpr (std::is_base_of_v<TH3, T>) { - if (spec.config.binsEqual) { - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1], spec.config.axes[2].nBins, spec.config.axes[2].bins[0], spec.config.axes[2].bins[1]); - } - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data(), spec.config.axes[2].nBins, spec.config.axes[2].bins.data()); - } else if constexpr (std::is_base_of_v<TH2, T>) { - if (spec.config.binsEqual) { - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1]); - } - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data()); - } else if constexpr (std::is_base_of_v<TH1, T>) { - if (spec.config.binsEqual) { - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1]); - } - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data()); - } - } - - typename std::map<HistogramType, HistogramFactory*>::iterator position; -}; - -HistogramFactoryImpl<TH1D> const hf1d(HistogramType::kTH1D); -HistogramFactoryImpl<TH1F> const hf1f(HistogramType::kTH1F); -HistogramFactoryImpl<TH1I> const hf1i(HistogramType::kTH1I); -HistogramFactoryImpl<TH2D> const hf2d(HistogramType::kTH2D); -HistogramFactoryImpl<TH2F> const hf2f(HistogramType::kTH2F); -HistogramFactoryImpl<TH2I> const hf2i(HistogramType::kTH2I); -HistogramFactoryImpl<TH3D> const hf3d(HistogramType::kTH3D); -HistogramFactoryImpl<TH3F> const hf3f(HistogramType::kTH3F); -HistogramFactoryImpl<TH3I> const hf3i(HistogramType::kTH3I); - /// Histogram registry for an analysis task that allows to define needed histograms /// and serves as the container/wrapper to fill them class HistogramRegistry @@ -257,7 +148,7 @@ class HistogramRegistry for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { if (mRegistryValue[imask(j + i)].get() == nullptr) { mRegistryKey[imask(j + i)] = spec.id; - mRegistryValue[imask(j + i)] = HistogramFactory::create(spec); + mRegistryValue[imask(j + i)] = {std::make_unique<TH1F>(spec.name.data(), spec.readableName.data(), spec.config.nBins, spec.config.xmin, spec.config.xmax)}; lookup += j; return; } diff --git a/Framework/Core/test/benchmark_HistogramRegistry.cxx b/Framework/Core/test/benchmark_HistogramRegistry.cxx index f91436dcc4cdd..18c09d1a31f34 100644 --- a/Framework/Core/test/benchmark_HistogramRegistry.cxx +++ b/Framework/Core/test/benchmark_HistogramRegistry.cxx @@ -30,7 +30,7 @@ static void BM_HashedNameLookup(benchmark::State& state) state.PauseTiming(); std::vector<HistogramSpec> specs; for (auto i = 0; i < state.range(0); ++i) { - specs.push_back({fmt::format("histo{}", i + 1).c_str(), fmt::format("Histo {}", i + 1).c_str(), {HistogramType::kTH1F, {{100, 0, 1}}}}); + specs.push_back({(boost::format("histo%1%") % (i + 1)).str().c_str(), (boost::format("Histo %1%") % (i + 1)).str().c_str(), {"TH1F", 100, 0, 1}}); } HistogramRegistry registry{"registry", true, specs}; state.ResumeTiming(); diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 040f1191a624b..5edccb200622c 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -19,20 +19,18 @@ using namespace o2::framework; HistogramRegistry foo() { - return {"r", true, {{"histo", "histo", {HistogramType::kTH1F, {{100, 0, 1}}}}}}; + return {"r", true, {{"histo", "histo", {"TH1F", 100, 0, 1}}}}; } BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) { /// Construct a registry object with direct declaration - HistogramRegistry registry{"registry", true, {{"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}}}}; + HistogramRegistry registry{"registry", true, {{"eta", "#Eta", {"TH1F", 100, -2.0, 2.0}}, {"phi", "#Phi", {"TH1D", 102, 0, 2 * M_PI}}, {"pt", "p_{T}", {"TH1D", 1002, -0.01, 50.1}}}}; /// Get histograms by name BOOST_REQUIRE_EQUAL(registry.get("eta")->GetNbinsX(), 100); BOOST_REQUIRE_EQUAL(registry.get("phi")->GetNbinsX(), 102); BOOST_REQUIRE_EQUAL(registry.get("pt")->GetNbinsX(), 1002); - BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsX(), 100); - BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsY(), 100); /// Get a pointer to the histogram auto histo = registry.get("pt").get(); From 9e810d75ccc9ffadb380b12078e182f8dbcda62f Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Wed, 12 Aug 2020 19:08:46 +0200 Subject: [PATCH 0382/1751] fix feeid, sorting, ori<->hcid --- .../TRD/include/DataFormatsTRD/RawData.h | 85 ++++-------- DataFormats/Detectors/TRD/src/RawData.cxx | 9 ++ Detectors/TRD/base/include/TRDBase/FeeParam.h | 9 ++ Detectors/TRD/base/src/FeeParam.cxx | 98 +++++++++++++- .../include/TRDSimulation/Trap2CRU.h | 13 +- Detectors/TRD/simulation/src/Trap2CRU.cxx | 124 ++++++++++-------- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 54 ++++++-- 7 files changed, 255 insertions(+), 137 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h index 33559ae0fe251..226ee073932ce 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -156,7 +156,7 @@ struct TrackletMCMHeader { // || | | | ----------- 1-8 pid for tracklet 3 second part // || | | -------------------- 9-16 pid for tracklet 2 second part // || | ---------------------------- 17-24 pid for tracklet 1 second part - // || ------------------------------ 25-26 coly + // || ------------------------------ 25-26 col // |---------------------------------- 27-30 padrow // ----------------------------------- 31 1 //TODO need to check endianness, I have a vague memory the trap chip has different endianness to x86. @@ -189,66 +189,31 @@ struct TrackletMCMData { // This is a bad name as part of the tracklet data is i }; }; -/* -std::vector<uint32_t> getPID(char *rawdata, int tracklet) -{ - // extract the 2 parts of the pid and return the combined PID - // rawdata starts with the mcmheader - uint32_t pid = 1;//(rawdata.pid[tracklet]<<15) + rawdata.pid[]; TODO figure out a better way that is not *undefined* c++ to progress to following 32bit words after TrackletMCMHeader. - //TODO come back here, marker to come back. - std::vector<uint32_t> pids; - TrackletMCMHeader mcmheader; - TrackletMCMData trackletdata; - //memcpy(&mcmheader,&rawdata[0],sizeof(mcmheader)); - std::copy(rawdata.begin(), rawdata.begin()+sizeof(mcmheader),(char*)&mcmheader); - for(int tracklet=0;tracklet<3;tracklet++){ - memcpy(&trackletdata,&rawdata[0]+sizeof(mcmheader)+tracklet*sizeof(trackletdata),sizeof(TrackletMCMData)); - uint32_t headpid=0; - switch(tracklet){ - case 0 : headpid=mcmheader.pid0;break; - case 1 : headpid=mcmheader.pid1;break; - case 2 : headpid=mcmheader.pid2;break; - } - pids[tracklet] = (headpid<<15) + trackletdata.pid; - } - // memcpy(rawdata,) - return pids; -} - -uint32_t getPadRow(const char *rawdata) -{ - TrackletMCMHeader mcmheader; - memcpy(&mcmheader, rawdata,sizeof(TrackletMCMHeader)); - return mcmheader.padrow; - -} -uint32_t getCol(const char* rawdata) -{ - TrackletMCMHeader mcmheader; - memcpy(&mcmheader, rawdata,sizeof(TrackletMCMHeader)); - return mcmheader.col; +/// \structure TRDFeeID +/// \brief Frontend Electronics ID, is made up of supermodule, a/c side and the end point encoded as below. + +struct TRDFeeID { + // + // 5432109876543210 + // uint16_t: 0000000000000000 + // mmmmmmmm --- supermodule 0 - 17 + // xxx --- unused1 + // s --- side 0=A C=1 + // xxx --- unused 2; + // e --- endpoint 0=lower, 1=upper + union { + uint16_t word; + struct { + uint8_t endpoint : 1; // the pci end point of the cru in question + uint8_t unused2 : 3; // seperate so easier to read in hex dumps + uint8_t side : 1; // the A=0 or C=1 side of the supermodule being readout + uint8_t unused1 : 3; // seperate so easier to read in hex dumps + uint8_t supermodule : 8; // the supermodule being read out 0-17 + } __attribute__((__packed__)); + }; +}; -} -int16_t getPos(const char* rawdata, int tracklet) -{ - // extract y from the tracklet word, raw data points to the mcmheader of this data. - //rawdata points to the TrackletMCMHeader - TrackletMCMData trackletdata; - TrackletMCMHeader mcmrawdataheader; - memcpy(&mcmrawdataheader,rawdata,sizeof(TrackletMCMHeader)); - memcpy(&trackletdata,rawdata+sizeof(TrackletMCMHeader)); - return trackletdata.pos; - return 1; -} -uint32_t getSlope(const *rawdata, int tracklet) -{ - // extract dy or slope from the tracklet word, raw data points to the mcmheader of this data. - TrackletMCMData trackletdata; - memcpy(&trackletdata,&rawdata[0]+sizeof(TrackletMCMHeader)+tracklet*sizeof(trackletdata),sizeof(TrackletMCMData)); - return trackletdata.slope; -} -due to the interplay of TrackletMCMHeader and TrackletMCMData come back to this. TODO -*/ +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); uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data); diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index 2583757d45052..80b2ac4a1aad1 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -19,6 +19,15 @@ namespace o2 namespace trd { +uint16_t buildTRDFeeID(int supermodule, int side, int endpoint) +{ + TRDFeeID feeid; + feeid.supermodule = supermodule; + feeid.side = side; + feeid.endpoint = endpoint; + return feeid.word; +} + uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link) { // link is the link you are requesting information on, 0-14 diff --git a/Detectors/TRD/base/include/TRDBase/FeeParam.h b/Detectors/TRD/base/include/TRDBase/FeeParam.h index 1088a751b4db4..f0c43617a695c 100644 --- a/Detectors/TRD/base/include/TRDBase/FeeParam.h +++ b/Detectors/TRD/base/include/TRDBase/FeeParam.h @@ -69,6 +69,13 @@ class FeeParam static short chipmaskToMCMlist(unsigned int cmA, unsigned int cmB, unsigned short linkpair, int* mcmList, int listSize); static short getRobAB(unsigned short robsel, unsigned short linkpair); // Returns the chamber side (A=0, B=0) of a ROB + // wiring + virtual int getORI(int detector, int readoutboard) const; + virtual int getORIinSM(int detector, int readoutboard) const; + // virtual void createORILookUpTable(); + virtual int getORIfromHCID(int hcid) const; + virtual int getHCIDfromORI(int ori, int readoutboard) const; // TODO we need more info than just ori, for now readoutboard is there ... might change + // tracklet simulation bool getTracklet() const { return mgTracklet; } static void setTracklet(bool trackletSim = true) { mgTracklet = trackletSim; } @@ -167,6 +174,8 @@ class FeeParam static float mgBinDy; // bin in dy (140 um) static int mgDyMax; // max dy for a tracklet (hard limit) static int mgDyMin; // min dy for a tracklet (hard limit) + //std::array<int,30> mgAsideLUT; // A side LUT to map ORI to stack/layer/side + //std::array<int,30> mgCsideLUT; // C side LUT to map ORI to stack/layer/side // settings float mMagField; // magnetic field diff --git a/Detectors/TRD/base/src/FeeParam.cxx b/Detectors/TRD/base/src/FeeParam.cxx index 4baebf0463062..c4eb5f5f36e27 100644 --- a/Detectors/TRD/base/src/FeeParam.cxx +++ b/Detectors/TRD/base/src/FeeParam.cxx @@ -33,12 +33,14 @@ #include <TMath.h> #include <TVirtualMC.h> #include <fairlogger/Logger.h> +#include <array> #include "DetectorsBase/GeometryManager.h" #include "TRDBase/TRDGeometry.h" #include "TRDBase/TRDPadPlane.h" #include "TRDBase/FeeParam.h" #include "TRDBase/TRDCommonParam.h" +//#include "DataFormatsTRD/Constants.h" using namespace std; using namespace o2::trd; @@ -455,6 +457,98 @@ short FeeParam::getRobAB(unsigned short robsel, unsigned short linkpair) return 0; } +/* +void FeeParam::createORILookUpTable() +{ + int ori; + for(int trdstack=0;trdstack<3;trdstack++) + { + for(int side=0;side<2;side++) + { + + for(int trdlayer=5;trdlayer>=0;trdlayer++) + { + ori=trdstack*12 + (5-trdlayer + side*6) +trdlayer/6 + side; + mgAsideLUT[ori]= (trdstack<<8) + (trdlayer<<4) + side; // A side LUT to map ORI to stack/layer/side + if(ori==29) break; + + } + if(ori==29) break; + } + if(ori==29) break; + } + for(int trdstack=4;trdstack>1;trdstack--) + { + for(int side=0;side<2;side++) + { + + for(int trdlayer=5;trdlayer>=0;trdlayer++) + { + ori = (4-trdstack)*12 + (5-trdlayer + side*5) +trdlayer/6 + side; + int newside; + if(ori >=24) newside=1; else newside=side; // a hack as I am not typing this all out. + mgCsideLUT[ori]= (trdstack<<8) + (trdlayer<<4) + newside; // A side LUT to map ORI to stack/layer/side + if(ori==29) break; + } + if(ori==29) break; + } + if(ori==29) break; + } +} +*/ + +int FeeParam::getORI(int detector, int readoutboard) const +{ + int supermodule = detector / 30; + LOG(debug3) << "getORI : " << detector << " :: " << readoutboard << getORIinSM(detector, readoutboard) + 60 * detector; + return getORIinSM(detector, readoutboard) + 2 * detector; // 2 ORI per detector +} + +int FeeParam::getORIinSM(int detector, int readoutboard) const +{ + int ori = -1; + int chamberside = 0; + int trdstack = TRDGeometry::getStack(detector); + int trdlayer = TRDGeometry::getLayer(detector); + int side = getRobSide(readoutboard); + //see TDP for explanation of mapping TODO should probably come from CCDB for the instances where the mapping of ori fibers is misconfigured (accidental fibre swaps). + if (trdstack < 2 || (trdstack == 2 && side == 0)) // A Side + { + ori = trdstack * 12 + (5 - trdlayer + side * 5) + trdlayer / 6 + side; // <- that is correct for A side at least for now, probably not for very long LUT as that will come form CCDB ni anycase. + } else { + if (trdstack > 2 || (trdstack == 2 && side == 1)) // CSide + { + int newside = side; + if (trdstack == 2) + newside = 0; // the last part of C side CRU is a special case. + ori = (4 - trdstack) * 12 + (5 - trdlayer + newside * 5) + trdlayer / 6 + newside; + } else + LOG(warn) << " something wrong with calculation of ORI for detector " << detector << " and readoutboard" << readoutboard; + } + // now offset for supermodule (+60*supermodule); + + return ori; +} + +int FeeParam::getORIfromHCID(int hcid) const +{ + int detector = hcid / 2; + int side = hcid % 2; // 0 for side 0, 1 for side 1; + int ori = -1; + int chamberside = 0; + int trdstack = TRDGeometry::getStack(detector); + int trdlayer = TRDGeometry::getLayer(detector); + return getORIinSM(detector, side); // it takes readoutboard but only cares if its odd or even hence side here. + return 1; +} +int FeeParam::getHCIDfromORI(int ori, int readoutboard) const +{ + // ori = 60*SM+offset[0-29 A, 30-59 C] + // from the offset, we can derive the stack/layer/side combination giving the decector. + //TODO do we need this, currently I dont, others might? come back if need be. + // + return 1; +} short FeeParam::chipmaskToMCMlist(unsigned int cmA, unsigned int cmB, unsigned short linkpair, int* mcmList, int listSize) { @@ -495,10 +589,9 @@ void FeeParam::setRAWversion(int rawver) /* * This was originally moved here from arrayADC, signalADC etc. We now longer use those classes * so removing this for now as its crashing. -*/ + */ void FeeParam::createPad2MCMLookUpTable() { - // // Initializes the Look Up Table to relate // pad numbering and mcm channel numbering @@ -516,7 +609,6 @@ void FeeParam::createPad2MCMLookUpTable() mgLUTPadNumbering[index] = index + shiftposition; } } - mgLUTPadNumberingFilled = true; } } diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h b/Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h index 7b1982c83f5c6..c1e672262b1bd 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/Trap2CRU.h @@ -37,12 +37,14 @@ class Trap2CRU static constexpr int NumberOfHalfCRU = 72; static constexpr int NumberOfFLP = 12; static constexpr int CRUperFLP = 3; - static constexpr int WordSizeInBytes = 256; // word size in bits, everything is done in 256 bit blocks. - static constexpr int WordSize = 8; // 8 standard 32bit words. - static constexpr int NLinksPerHalfCRU = 15; + static constexpr int WordSizeInBytes = 256; // word size in bits, everything is done in 256 bit blocks. + static constexpr int WordSize = 8; // 8 standard 32bit words. + static constexpr int NLinksPerHalfCRU = 15; // number of fibers per each half cru + static constexpr int TRDLinkID = 15; // hard coded link id. TODO give reason? static constexpr uint32_t PaddWord = 0xeeee; // pad word to fill 256bit blocks or entire block for no data case. - //TODO come back and change the mapping of 1077 channels to a lut and probably configurable. - // + static constexpr bool DebugDataWriting = false; //dump put very first vector of data to see if the thing going into the rawwriter is correct. + //TODO come back and change the mapping of 1077 channels to a lut addnd probably configurable. + // public: Trap2CRU() = default; Trap2CRU(const std::string& outputDir, const std::string& inputFilename); @@ -57,6 +59,7 @@ class Trap2CRU int getVerbosity() { return mVerbosity; } void setVerbosity(int verbosity) { mVerbosity = verbosity; } void buildCRUPayLoad(); + int sortByORI(); o2::raw::RawFileWriter& getWriter() { return mWriter; } uint32_t buildCRUHeader(HalfCRUHeader& header, uint32_t bc, uint32_t halfcru, int startlinkrecord); void linkSizePadding(uint32_t linksize, uint32_t& crudatasize, uint32_t& padding); diff --git a/Detectors/TRD/simulation/src/Trap2CRU.cxx b/Detectors/TRD/simulation/src/Trap2CRU.cxx index 08c08b28f9cc2..688bb2cb0881e 100644 --- a/Detectors/TRD/simulation/src/Trap2CRU.cxx +++ b/Detectors/TRD/simulation/src/Trap2CRU.cxx @@ -53,31 +53,39 @@ Trap2CRU::Trap2CRU(const std::string& outputDir, const std::string& inputFilenam readTrapData(outputDir, inputFilename, 1024 * 1024); } -void Trap2CRU::readTrapData(const std::string& otuputDir, const std::string& inputFilename, int superPageSizeInB) +void Trap2CRU::readTrapData(const std::string& outputDir, const std::string& inputFilename, int superPageSizeInB) { //set things up, read the file and then deligate to convertTrapdata to do the conversion. // mRawData.reserve(1024 * 1024); //TODO take out the hardcoded 1MB its supposed to come in from the options - LOG(info) << "Trap2CRU::readTrapData"; + LOG(debug) << "Trap2CRU::readTrapData"; // data comes in index by event (triggerrecord) and link (linke record) both sequentially. // first 15 links go to cru0a, second 15 links go to cru0b, 3rd 15 links go to cru1a ... first 90 links to flp0 and then repate for 12 flp // then do next event // lets register our links - for (int link = 0; link < NumberOfCRU; link++) { - mFeeID = link; - mCruID = link; - mEndPointID = link * 2; - mLinkID = link; - std::string outputFilelink = o2::utils::concat_string("trd_cru_", std::to_string(link), "_a.raw"); - mWriter.registerLink(mFeeID, mCruID, mLinkID, mEndPointID, outputFilelink); - outputFilelink = o2::utils::concat_string("trd_cru_", std::to_string(link), "_b.raw"); - mEndPointID++; + std::string prefix = outputDir; + if (!prefix.empty() && prefix.back() != '/') { + prefix += '/'; + } + + for (int link = 0; link < NumberOfHalfCRU; link++) { + // FeeID *was* 0xFEED, now is indicates the cru Supermodule, side (A/C) and endpoint. See RawData.cxx for details. + int supermodule = link / 4; + int endpoint = link / 2; + int side = link % 2 ? 1 : 0; + mFeeID = buildTRDFeeID(supermodule, side, endpoint); + mCruID = link / 2; + mEndPointID = link % 2 ? 1 : 0; //TODO figure out a value ... endpoint needs a rebase to PR4106 + mLinkID = TRDLinkID; + std::string trdside = link % 2 ? "c" : "a"; // the side of supermodule readout A or C, odd numbered CRU are A, even numbered CRU are C. + // filenmae structure of trd_cru_[CRU#]_[upper/lower].raw + std::string outputFilelink = o2::utils::concat_string(prefix, "trd_cru_", std::to_string(mCruID), "_", trdside, ".raw"); mWriter.registerLink(mFeeID, mCruID, mLinkID, mEndPointID, outputFilelink); } mTrapRawFile = TFile::Open(inputFilename.data()); assert(mTrapRawFile != nullptr); - LOG(info) << "Trap Raw file open " << inputFilename; + LOG(debug) << "Trap Raw file open " << inputFilename; mTrapRawTree = (TTree*)mTrapRawFile->Get("o2sim"); mTrapRawTree->SetBranchAddress("TrapLinkRecord", &mLinkRecordsPtr); // branch with the link records @@ -92,15 +100,25 @@ void Trap2CRU::readTrapData(const std::string& otuputDir, const std::string& inp //get the event limits from TriggerRecord; uint32_t eventstart = trigger.getFirstEntry(); uint32_t eventend = trigger.getFirstEntry() + trigger.getNumberOfObjects(); - LOG(info) << "Event starts at:" << eventstart << " and ends at :" << eventend; + LOG(debug) << "Event starts at:" << eventstart << " and ends at :" << eventend; convertTrapData(trigger); } } } +int Trap2CRU::sortByORI() +{ + // data comes in sorted by padcolum, a row of 8 trap chips. + // this is sadly not how the electronics is actually connected. + // we therefore need to resort the data according to the ORI link. + // TODO consider unpacking an entire event into memory into a per ori vector, then dump it all out. + // this is not for production running so the performance hit of sortin is probably ok ?? TODO ask someone to verify that. + return 1; +} + void Trap2CRU::buildCRUPayLoad() { - // go through the data for the event in question, produce the raw stream for each cru. + // go through the data for the event in question, sort via above method, produce the raw stream for each cru. // i.e. 30 link per cru, 3cru per flp. // 30x [HalfCRUHeader, TrackletHCHeader0, [MCMHeader TrackletMCMData. .....] TrackletHCHeader1 ..... TrackletHCHeader30 ...] // @@ -161,7 +179,7 @@ uint32_t Trap2CRU::buildCRUHeader(HalfCRUHeader& header, uint32_t bc, uint32_t h if (mLinkRecords[linkrecord].getLinkHCID() == hcid) { linksize = mLinkRecords[linkrecord].getNumberOfObjects(); // this can be done differently by keeping a pointer to halfcruheader and setting it after reading it all in and going back per link to set the size. - // LOG(info) << "setting CRU HEADER for halfcru : " << halfcru << "and link : " << link << " contents" << halfcruheader << ":" << link << ":" << linksize << ":" << errors; + LOG(debug3) << "setting CRU HEADER for halfcru : " << halfcru << "and link : " << link << " contents" << header << ":" << link << ":" << linksize << ":" << errors; linkrecord++; // increment locally for walking through linkrecords. } linkSizePadding(linksize, crudatasize, padding); @@ -183,8 +201,15 @@ void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) //finished for event. this method is only called per event. int currentlinkrecord = 0; char* traprawdataptr = (char*)&mTrapRawData[0]; - for (int halfcru = 0; halfcru < NumberOfHalfCRU; halfcru++) { //TODO come back and replace 72 with something. - // TrackletHC + for (int halfcru = 0; halfcru < NumberOfHalfCRU; halfcru++) { + int supermodule = halfcru / 4; + int endpoint = halfcru / 2; + int side = halfcru % 2 ? 1 : 0; + mFeeID = buildTRDFeeID(supermodule, side, endpoint); + mCruID = halfcru / 2; + mLinkID = TRDLinkID; + mEndPointID = halfcru % 2 ? 1 : 0; + memset(&mRawData[0], 0, sizeof(mRawData[0]) * mRawData.size()); // zero the rawdata storage int numberofdetectors = o2::trd::constants::MAXCHAMBER; HalfCRUHeader halfcruheader; @@ -195,28 +220,23 @@ void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) std::vector<char> rawdatavector(totalhalfcrudatasize * 32 + sizeof(halfcruheader)); // sum of link sizes + padding in units of bytes and some space for the header (512 bytes). char* rawdataptr = rawdatavector.data(); - LOG(info) << "before writing halfcruheader pionter is sitting at " << std::hex << static_cast<void*>(rawdataptr); - dumpHalfCRUHeader(halfcruheader); + + //dumpHalfCRUHeader(halfcruheader); memcpy(rawdataptr, (char*)&halfcruheader, sizeof(halfcruheader)); std::array<uint64_t, 8> raw{}; memcpy((char*)&raw[0], rawdataptr, sizeof(halfcruheader)); for (int i = 0; i < 2; i++) { int index = 4 * i; - LOGF(debug, "[1/2rawdaptr %d] 0x%08x 0x%08x 0x%08x 0x%08x", i, raw[index + 3], raw[index + 2], raw[index + 1], raw[index + 0]); + LOG(debug) << "[1/2rawdaptr " << i << " " << std::hex << raw[index + 3] << " " << raw[index + 2] << " " << raw[index + 1] << " " << raw[index + 0]; } rawdataptr += sizeof(halfcruheader); - LOG(info) << "For writing halfcruheader pionter advanced by " << std::dec << sizeof(halfcruheader) << " ptr is now at:" << std::hex << static_cast<void*>(rawdataptr); - LOG(debug) << "Just wrote cruheader for halfcru index : " << halfcru << " with contents \n" - << halfcruheader; - LOG(debug) << "end of halfcruheader"; int linkdatasize = 0; // in 32 bit words int link = halfcru / 2; - int endpoint = halfcru; for (int halfcrulink = 0; halfcrulink < NLinksPerHalfCRU; halfcrulink++) { //links run from 0 to 14, so hcid offset is halfcru*15; - int hcid = halfcrulink + halfcru * NLinksPerHalfCRU; // TODO this might have to change to a lut I dont think the mapping is linear. - LOG(info) << "Currently checking for data on hcid : " << hcid << " from halfcru=" << halfcru << " and halfcrulink:" << halfcrulink << " ?? " << hcid << "==" << mLinkRecords[currentlinkrecord].getLinkHCID(); + int hcid = halfcrulink + halfcru * NLinksPerHalfCRU; + LOG(debug) << "Currently checking for data on hcid : " << hcid << " from halfcru=" << halfcru << " and halfcrulink:" << halfcrulink << " ?? " << hcid << "==" << mLinkRecords[currentlinkrecord].getLinkHCID(); int errors = 0; // put no errors in for now. int size = 0; // in 32 bit words int datastart = 0; // in 32 bit words @@ -225,18 +245,17 @@ void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) uint32_t crudatasize = 0; // in 256 bit words. if (mLinkRecords[currentlinkrecord].getLinkHCID() == hcid) { //this link has data in the stream. - LOG(info) << "+++ We have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; + LOG(debug) << "+++ We have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; linkdatasize = mLinkRecords[currentlinkrecord].getNumberOfObjects(); datastart = mLinkRecords[currentlinkrecord].getFirstEntry(); dataend = datastart + size; - LOG(info) << "We have data on hcid = " << hcid << " and linksize : " << linkdatasize << " so :" << linkdatasize / 8 << " 256 bit words"; + LOG(debug) << "We have data on hcid = " << hcid << " and linksize : " << linkdatasize << " so :" << linkdatasize / 8 << " 256 bit words"; currentlinkrecord++; } else { assert(mLinkRecords[currentlinkrecord].getLinkId() < hcid); - LOG(info) << "---We do not have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; - //blank data for this link??? what do i do? + LOG(debug) << "---We do not have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; + //blank data for this link // put in a 1 256 bit word of data for the link and padd with 0xeeee x 8 - // tmpLinkInfo[halfcrulink] = -1; linkdatasize = 0; paddingsize = 8; } @@ -244,30 +263,29 @@ void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) // linkSizePadding(linkdatasize, crudatasize, paddingsize); //TODO this can come out as we have already called it, but previously we have lost the #padding words, solve to remove. - LOG(info) << "WRITING " << crudatasize << " 256 bit data words to output stream"; - LOG(info) << "setting CRY HEADER for " << halfcruheader << ":" << halfcrulink << ":" << crudatasize << ":" << errors; + LOG(debug) << "WRITING " << crudatasize << " 256 bit data words to output stream"; + LOG(debug) << "setting CRY HEADER for " << halfcruheader << ":" << halfcrulink << ":" << crudatasize << ":" << errors; // now pad .... - LOG(info) << " now to pump data into the stream with : " << linkdatasize << " crudatasize:" << crudatasize << " paddingsize: " << paddingsize << " and rem:" << linkdatasize % 8; + LOG(debug) << " now to pump data into the stream with : " << linkdatasize << " crudatasize:" << crudatasize << " paddingsize: " << paddingsize << " and rem:" << linkdatasize % 8; char* olddataptr = rawdataptr; // store the old pointer so we can do some sanity checks for how far we advance. //linkdatasize is the #of 32 bit words coming from the incoming tree. //paddingsize is the number of padding words to add 0xeeee uint32_t bytestocopy = linkdatasize * (sizeof(uint32_t)); - LOG(info) << "copying " << bytestocopy << " bytes of link tracklet data at pos:" << std::hex << static_cast<void*>(rawdataptr); + LOG(debug) << "copying " << bytestocopy << " bytes of link tracklet data at pos:" << std::hex << static_cast<void*>(rawdataptr); memcpy(rawdataptr, traprawdataptr, bytestocopy); //increment pointer rawdataptr += bytestocopy; traprawdataptr += bytestocopy; //now for padding uint16_t padbytes = paddingsize * sizeof(uint32_t); - LOG(info) << "writing " << padbytes << " bytes of padding data at pos:" << std::hex << static_cast<void*>(rawdataptr); + LOG(debug) << "writing " << padbytes << " bytes of padding data at pos:" << std::hex << static_cast<void*>(rawdataptr); memset(rawdataptr, 0xee, padbytes); //increment pointer. rawdataptr += padbytes; if (padbytes + bytestocopy != crudatasize * 32) { - LOG(info) << "something wrong with data size writing padbytes:" << padbytes << " bytestocopy : " << bytestocopy << " crudatasize:" << crudatasize; + LOG(debug) << "something wrong with data size writing padbytes:" << padbytes << " bytestocopy : " << bytestocopy << " crudatasize:" << crudatasize; } LOG(debug3) << std::hex << " rawdataptr:" << static_cast<void*>(rawdataptr) << " traprawdataptr " << static_cast<void*>(traprawdataptr); - // printf(std::cout << std::hex << " rawdataptr:0x"<<&rawdataptr << " traprawdataptr 0x"<<&traprawdataptr << std::endl; //sanity check for now: if (((char*)rawdataptr - (char*)olddataptr) != crudatasize * 32) { // cru words are 8 uint32 and comparison is in bytes. LOG(debug) << "according to pointer arithmatic we have added " << rawdataptr - olddataptr << "bytes from " << static_cast<void*>(rawdataptr) << "-" << static_cast<void*>(olddataptr) << " when we should have added " << crudatasize * 8 * 4 << " because crudatasize=" << crudatasize; @@ -276,26 +294,16 @@ void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) // we have written the wrong amount of data .... LOG(debug) << "crudata is ! = get link data size " << crudatasize << "!=" << o2::trd::getlinkdatasize(halfcruheader, halfcrulink); } - // if(crudatasize ==0)LOG(info) << "CRUDATASIZ EIS ZERO" ; - // if(crudatasize>0){ - // std::ofstream out1("crutestdumphalfcrurawdata"); - // std::ofstream out2("crutestdumprawdatavector"); - // LOG(info) << "writing out " << halfcrurawdata.size() << " and" << crudatasize*32; - // out1.write(halfcrurawdata.data(),halfcrurawdata.size()); - // out2.write(rawdatavector.data(),crudatasize*32); - // out1.flush(); - // out2.flush(); - // exit(1); - // } - LOG(info) << "copied " << crudatasize * 32 << "bytes to halfcrurawdata which now has size of " << rawdatavector.size() << " for " << link << ":" << endpoint; + LOG(debug) << "copied " << crudatasize * 32 << "bytes to halfcrurawdata which now has size of " << rawdatavector.size() << " for " << link << ":" << endpoint; + } + LOG(debug) << "writing to " << std::hex << mFeeID << std::dec << " : " << mCruID << " : " << mLinkID << " : " << mEndPointID; + mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, TrigRecord.getBCData(), rawdatavector); + if (DebugDataWriting) { + std::ofstream out2("crutestdumprawdatavector"); + out2.write(rawdatavector.data(), rawdatavector.size()); + out2.flush(); + halfcru = NumberOfHalfCRU; // exit loop after 1 half cru for now. } - // std::vector<char> halfcrurawdata(crudatasize * 32); // vector of 256bit words * 32 to get to 8 bit words - - mWriter.addData(link, link, link, endpoint, TrigRecord.getBCData(), rawdatavector); - std::ofstream out2("crutestdumprawdatavector"); - out2.write(rawdatavector.data(), rawdatavector.size()); - out2.flush(); - // halfcru = NumberOfHalfCRU; // exit loop after 1 half cru for now. } } diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 4c1163b4c2221..a4bcbd2803a25 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -65,6 +65,11 @@ namespace trd bool msgDigitSortComparator(o2::trd::Digit const& a, o2::trd::Digit const& b) { + // sort digits. + // order of sort, is time, detector, hlaf chamber index, readout board, mcm. + // the pads wont be in order they are in, in the pad row. + // it however does not matter as all the relevant pads will be loaded into the 8 mcms of the pad row. + // so the shared pad issue is fixed. FeeParam* fee = FeeParam::instance(); int rowa = a.getRow(); int rowb = b.getRow(); @@ -98,8 +103,7 @@ bool msgDigitSortComparator(o2::trd::Digit const& a, o2::trd::Digit const& b) } return 0; - /* - if (deta < detb) + /* if (deta < detb) return 1; else { if (deta == detb) { @@ -198,7 +202,7 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() LOG(info) << "looking for TRAPconfig " << mTrapConfigName; auto& ccdbmgr = o2::ccdb::BasicCCDBManager::instance(); - ccdbmgr.setTimestamp(297595); + ccdbmgr.setTimestamp(mRunNumber); //default is : mTrapConfigName="cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"; mTrapConfigName = "c"; mTrapConfig = ccdbmgr.get<o2::trd::TrapConfig>("TRD_test/TrapConfig2020/c"); @@ -445,6 +449,19 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) for (auto& trig : trackletTriggerRecords) { LOG(debug) << "Trigger Tracklet Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); } + //print digits to check the sorting. + LOG(debug4) << " Digits : "; + for (auto& digit : msgDigits) { + LOG(debug4) << "sorted digit time:" << digit.getTimeStamp() << " detector:row:pad:rob:mcm ::" + << digit.getDetector() << ":" << digit.getRow() << ":" << digit.getPad() << ":" + << mFeeParam->getROBfromPad(digit.getRow(), digit.getPad()) << ":" + << mFeeParam->getMCMfromPad(digit.getRow(), digit.getPad()) + << " HCID:" << getHalfChamberID(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << "\t\t SM:stack:layer:side " + << digit.getDetector() / 30 << ":" << TRDGeometry::getStack(digit.getDetector()) + << ":" << TRDGeometry::getLayer(digit.getDetector()) << ":" << FeeParam::instance()->getRobSide(mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) + << " with ORI# : " << mFeeParam->getORI(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) + << " within SM ori#:" << mFeeParam->getORIinSM(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())); + } //accounting variables for various things. //TODO make them class members, i dont want to fiddle right now though. int olddetector = -1; @@ -462,6 +479,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // now to loop over the incoming digits. auto digitloopstart = std::chrono::high_resolution_clock::now(); uint64_t digitcounter = 0; + double b = 0; LOG(debug4) << "now for digit loop "; for (auto digititerator = msgDigits.begin(); digititerator != msgDigits.end() /* && std::distance(msgDigits.begin(),digititerator)<7*/; ++digititerator) { //in here we have an entire padrow which corresponds to 8 TRAPs. @@ -474,8 +492,18 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) int detector = digititerator->getDetector(); int rob = mFeeParam->getROBfromPad(row, pad); int mcm = mFeeParam->getMCMfromPad(row, pad); - LOG(debug3) << "calculated rob and mcm at top of loop with detector:row:pad:rob:mcm" << detector << ":" << row << ":" << pad << ":" << rob << ":" << mcm; + int trdstack = TRDGeometry::getStack(detector); + int trdlayer = TRDGeometry::getLayer(detector); + int fibreside = FeeParam::instance()->getRobSide(rob); + LOG(debug) << "calculated rob and mcm at top of loop with detector:row:pad:rob:mcm ::" + << detector << ":" << row << ":" << pad << ":" << rob << ":" << mcm + << " HCID:" << getHalfChamberID(detector, rob) << "\t\t SM:stack:layer:side " << detector / 30 << ":" << trdstack << ":" << trdlayer << ":" << fibreside + << " with ORI : " << mFeeParam->getORI(detector, rob) << " and within supermodule ori index:" << mFeeParam->getORIinSM(detector, rob); LOG(debug) << "digit time : " << digittime; + if (row == 4 && pad == 17 && rob == 2 & mcm == 0) { + // here for debugging. + b = sin(30); + } if (digititerator == msgDigits.begin()) { // first time in loop oldrow = row; olddetector = detector; @@ -529,16 +557,15 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // .. fix the previous linkrecord to note its end of range. if (mLinkRecords.size() == 0) { // special case for the first entry into the linkrecords vector. mLinkRecords.emplace_back(mTrackletHCHeader.word, 0, -1); + LOG(debug) << " added HCID :[record.size==0] " << mTrackletHCHeader.HCID << " with number of bytes : " << mTotalRawWordsWritten << "-" << mLinkRecords.back().getFirstEntry(); } else { mLinkRecords.back().setNumberOfObjects(mTotalRawWordsWritten - mLinkRecords.back().getFirstEntry()); // current number of words written - the start of this index record. + LOG(debug) << " added HCID : " << mTrackletHCHeader.HCID << " with number of bytes : " << mTotalRawWordsWritten << "-" << mLinkRecords.back().getFirstEntry(); //..... so write the new one thing - mLinkRecords.emplace_back(mTrackletHCHeader.word, mTotalRawWordsWritten, -1); // set the number of elements to -1 for an error condition } - //mTotalRawWordsWritten++; //no longer writing to raw stream mNewTrackletHCHeaderHasBeenWritten = true; LOG(debug) << mTrackletHCHeader; - LOG(info) << " add HCID : " << mTrackletHCHeader.HCID; } LOG(debug) << "getting trackletsteram for trapcounter = " << trapcounter; auto wordswritten = mTrapSimulator[trapcounter].getTrackletStream(rawdata, mTotalRawWordsWritten); // view of data from current marker and only 5 words long (can only have 4 words at most in the trackletstream for 1 MCM) @@ -553,7 +580,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) mTrapSimAccumulatedTime += std::chrono::high_resolution_clock::now() - trapsimtimerstart; if (mShowTrackletStats > 0) { if (trapTrackletsAccum.size() - oldsize > mShowTrackletStats) { - LOG(info) << "TrapSim Accumulated tracklets: " << trapTrackletsAccum.size() << " :: " << trapTracklets.size(); + LOG(debug) << "TrapSim Accumulated tracklets: " << trapTrackletsAccum.size() << " :: " << trapTracklets.size(); oldsize = trapTrackletsAccum.size(); } } @@ -564,7 +591,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // mTrapSimulator[trapcounter].draw(mDrawTrackletOptions, loopindex); if (mDebugRejectedTracklets) { //&& trapTracklets.size()==0) { mTrapSimulator[trapcounter].draw(7, loopindex); //draw adc when no tracklets are found.A - LOG(info) << "loop index : " << loopindex; + LOG(debug) << "loop index : " << loopindex; mTrapSimulator[trapcounter].print(1); // if(loopindex==320) LOG(fatal) <<"exiting at trap loop count 320"; } @@ -577,7 +604,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) } else { LOG(debug) << "if statement is init failed [" << trapcounter << "] PROCESSING TRAP !"; } - // LOG(info) << "Finishe MCM : : " << trapcounter; + // LOG(debug) << "Finishe MCM : : " << trapcounter; } //end of loop over trap chips //timing info @@ -616,18 +643,23 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) tmplabels.push_back(tmplabel); } LOG(debug) << "tmplabels for set data : " << tmplabels.size() << " and gslspan digitlabels size of : " << digitslabels.size(); + LOG(debug) << " setting data with pad=" << pad << " ti=" << trapindex + 1; mTrapSimulator[trapindex].setData(adc, digititerator->getADC(), tmplabels); // now take care of the case of shared pads (the whole reason for doing this pad row wise). if (pad % 18 == 0 || (pad + 1) % 18 == 0) { //case of pad 18 and 19 must be shared to preceding trap chip adc 1 and 0 respectively. adc = 20 - (pad % 18) - 1; - mTrapSimulator[trapindex - 1].setData(adc, digititerator->getADC(), tmplabels); + if (trapindex != 0) { // avoid the case of the first trap chip + LOG(debug) << " setting data preceding with pad=" << pad << " ti=" << trapindex - 1; + mTrapSimulator[trapindex - 1].setData(adc, digititerator->getADC(), tmplabels); + } } if ((pad - 1) % 18 == 0) { // case of pad 17 must shared to next trap chip as adc 20 //check trap is initialised. adc = 20 - (pad % 18) - 1; if (trapindex + 1 != 8) { // avoid the case of the last trap chip. + LOG(debug) << " setting data proceeding with pad=" << pad << " ti=" << trapindex + 1; mTrapSimulator[trapindex + 1].setData(adc, digititerator->getADC(), tmplabels); } } From c1bb97caee22bf218984639b2b9d1430579c989c Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sun, 16 Aug 2020 20:06:56 +0200 Subject: [PATCH 0383/1751] DPL: add missing include arrow/config.h --- Framework/Core/include/Framework/Kernels.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Framework/Core/include/Framework/Kernels.h b/Framework/Core/include/Framework/Kernels.h index b3c5388e79e54..c0a7b2ed4984f 100644 --- a/Framework/Core/include/Framework/Kernels.h +++ b/Framework/Core/include/Framework/Kernels.h @@ -14,6 +14,12 @@ #include "Framework/BasicOps.h" #include "Framework/TableBuilder.h" +#if __has_include(<arrow/config.h>) +#include <arrow/config.h> +#endif +#if __has_include(<arrow/util/config.h>) +#include <arrow/util/config.h> +#endif #include <arrow/compute/kernel.h> #include <arrow/status.h> #include <arrow/util/visibility.h> From 1d0592f7e6c6b0e0d7a8820c0a42404d0d658ca6 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 18 Aug 2020 09:40:43 +0200 Subject: [PATCH 0384/1751] trigger re-check --- Framework/Core/include/Framework/Kernels.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/include/Framework/Kernels.h b/Framework/Core/include/Framework/Kernels.h index c0a7b2ed4984f..615617c569bda 100644 --- a/Framework/Core/include/Framework/Kernels.h +++ b/Framework/Core/include/Framework/Kernels.h @@ -20,6 +20,7 @@ #if __has_include(<arrow/util/config.h>) #include <arrow/util/config.h> #endif + #include <arrow/compute/kernel.h> #include <arrow/status.h> #include <arrow/util/visibility.h> From c687c68acce4680761ea56a02744bf7c3727ef92 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 18 Aug 2020 10:04:04 +0200 Subject: [PATCH 0385/1751] includes for arrow version --- Framework/Core/src/TableTreeHelpers.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 3d0cb70cd1c39..9ea4ac8e5febf 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -10,6 +10,13 @@ #include "Framework/TableTreeHelpers.h" #include "Framework/Logger.h" +#if __has_include(<arrow/config.h>) +#include <arrow/config.h> +#endif +#if __has_include(<arrow/util/config.h>) +#include <arrow/util/config.h> +#endif + #include "arrow/type_traits.h" namespace o2 From 1c20d70081961b52e58dabe86514c3d499e92338 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 18 Aug 2020 22:37:19 +0200 Subject: [PATCH 0386/1751] DPL Analysis: grouping with index tables (#4171) --- Analysis/Tutorials/src/custom_index.cxx | 13 ++++++- Framework/Core/include/Framework/ASoA.h | 38 +++++++++++++++---- .../Core/include/Framework/AnalysisTask.h | 33 +++++++++++++--- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/Analysis/Tutorials/src/custom_index.cxx b/Analysis/Tutorials/src/custom_index.cxx index 0da64f533496b..a00f0f369d51c 100644 --- a/Analysis/Tutorials/src/custom_index.cxx +++ b/Analysis/Tutorials/src/custom_index.cxx @@ -39,8 +39,19 @@ struct ATask { } }; +struct BTask { + void process(aod::Matched::iterator const& m, aod::Tracks const& tracks) + { + LOGF(INFO, "Collision %d; Ntrk: %d", m.collisionId(), tracks.size()); + auto t1 = tracks.begin(); + auto t2 = t1 + (tracks.size() - 1); + LOGF(INFO, "track 1 from %d; track %d from %d", t1.collisionId(), tracks.size(), t2.collisionId()); + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<ATask>("produce-index")}; + adaptAnalysisTask<ATask>("produce-index"), + adaptAnalysisTask<BTask>("consume-index")}; } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 7051367a82ec4..6bb0ba45ff5c5 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -47,6 +47,12 @@ constexpr bool is_type_with_originals_v = false; template <typename T> constexpr bool is_type_with_originals_v<T, std::void_t<decltype(sizeof(typename T::originals))>> = true; +template <typename T, typename = void> +constexpr bool is_type_with_parent_v = false; + +template <typename T> +constexpr bool is_type_with_parent_v<T, std::void_t<decltype(sizeof(typename T::parent_t))>> = true; + template <typename, typename = void> constexpr bool is_type_with_metadata_v = false; @@ -84,6 +90,8 @@ constexpr auto make_originals_from_type() return typename decayed::originals{}; } else if constexpr (is_type_with_originals_v<typename decayed::table_t>) { return typename decayed::table_t::originals{}; + } else if constexpr (is_type_with_parent_v<decayed>) { + return make_originals_from_type(decayed::parent_t); } else { return framework::pack<decayed>{}; } @@ -1298,10 +1306,9 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "AOD", _Description_, __VA_ARGS__) #define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, ...) \ - using _Name_ = o2::soa::IndexTable<_Key_, soa::Index<>, __VA_ARGS__>; \ + using _Name_ = o2::soa::IndexTable<_Key_, __VA_ARGS__>; \ \ struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ - using table_t = _Name_; \ using Key = _Key_; \ using index_pack_t = framework::pack<__VA_ARGS__>; \ using originals = decltype(soa::extractBindings(index_pack_t{})); \ @@ -1316,7 +1323,16 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); }; \ \ template <> \ - struct MetadataTrait<_Name_::unfiltered_iterator> { \ + struct MetadataTrait<_Name_::base_t> { \ + using metadata = _Name_##Metadata; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_::iterator> { \ + using metadata = _Name_##Metadata; \ + }; \ + template <> \ + struct MetadataTrait<_Name_::base_t::iterator> { \ using metadata = _Name_##Metadata; \ }; @@ -1720,14 +1736,14 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) /// are index columns defined for the required tables. /// First index will be used by process() as the grouping template <typename Key, typename H, typename... Ts> -struct IndexTable : Table<H, Ts...> { - using table_t = Table<H, Ts...>; +struct IndexTable : Table<soa::Index<>, H, Ts...> { + using base_t = Table<soa::Index<>, H, Ts...>; using indexing_t = Key; - using first_t = H; - using rest_t = framework::pack<Ts...>; + using first_t = typename H::binding_t; + using rest_t = framework::pack<typename Ts::binding_t...>; IndexTable(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) - : table_t{table, offset} + : base_t{table, offset} { } @@ -1735,8 +1751,14 @@ struct IndexTable : Table<H, Ts...> { IndexTable(IndexTable&&) = default; IndexTable& operator=(IndexTable const&) = default; IndexTable& operator=(IndexTable&&) = default; + + using iterator = typename base_t::template RowView<IndexTable<Key, H, Ts...>, base_t>; + using const_iterator = iterator; }; +template <typename T> +using is_soa_index_table_t = typename framework::is_specialization<T, soa::IndexTable>; + } // namespace o2::soa #endif // O2_FRAMEWORK_ASOA_H_ diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index aabfe6e52a8e2..282853328d2db 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -616,7 +616,17 @@ struct AnalysisDataProcessorBuilder { auto getLabelFromType() { - if constexpr (soa::is_type_with_originals_v<std::decay_t<G>>) { + if constexpr (soa::is_soa_index_table_t<std::decay_t<G>>::value) { + using T = typename std::decay_t<G>::first_t; + if constexpr (soa::is_type_with_originals_v<std::decay_t<T>>) { + using O = typename framework::pack_element_t<0, typename std::decay_t<G>::originals>; + using groupingMetadata = typename aod::MetadataTrait<O>::metadata; + return std::string("f") + groupingMetadata::tableLabel() + "ID"; + } else { + using groupingMetadata = typename aod::MetadataTrait<T>::metadata; + return std::string("f") + groupingMetadata::tableLabel() + "ID"; + } + } else if constexpr (soa::is_type_with_originals_v<std::decay_t<G>>) { using T = typename framework::pack_element_t<0, typename std::decay_t<G>::originals>; using groupingMetadata = typename aod::MetadataTrait<T>::metadata; return std::string("f") + groupingMetadata::tableLabel() + "ID"; @@ -688,12 +698,23 @@ struct AnalysisDataProcessorBuilder { constexpr bool isIndexTo() { if constexpr (soa::is_type_with_binding_v<C>) { - if constexpr (soa::is_type_with_originals_v<std::decay_t<B>>) { - using TT = typename framework::pack_element_t<0, typename std::decay_t<B>::originals>; - return std::is_same_v<typename C::binding_t, TT>; + if constexpr (soa::is_soa_index_table_t<std::decay_t<B>>::value) { + using T = typename std::decay_t<B>::first_t; + if constexpr (soa::is_type_with_originals_v<std::decay_t<T>>) { + using TT = typename framework::pack_element_t<0, typename std::decay_t<T>::originals>; + return std::is_same_v<typename C::binding_t, TT>; + } else { + using TT = std::decay_t<T>; + return std::is_same_v<typename C::binding_t, TT>; + } } else { - using TT = std::decay_t<B>; - return std::is_same_v<typename C::binding_t, TT>; + if constexpr (soa::is_type_with_originals_v<std::decay_t<B>>) { + using TT = typename framework::pack_element_t<0, typename std::decay_t<B>::originals>; + return std::is_same_v<typename C::binding_t, TT>; + } else { + using TT = std::decay_t<B>; + return std::is_same_v<typename C::binding_t, TT>; + } } } return false; From e43aafd7c1292249723117854532946e180cb786 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 18 Aug 2020 23:10:08 +0200 Subject: [PATCH 0387/1751] DPL: improve error message when matching resources (#4169) --- Framework/Core/src/SimpleResourceManager.cxx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Framework/Core/src/SimpleResourceManager.cxx b/Framework/Core/src/SimpleResourceManager.cxx index 99961dd41b4e5..7becac3926160 100644 --- a/Framework/Core/src/SimpleResourceManager.cxx +++ b/Framework/Core/src/SimpleResourceManager.cxx @@ -9,12 +9,11 @@ // or submit itself to any jurisdiction. #include "SimpleResourceManager.h" #include "Framework/ComputingResource.h" +#include <fmt/format.h> #include <exception> #include <stdexcept> -namespace o2 -{ -namespace framework +namespace o2::framework { /// The simplest implementation of this allocates mMaxPorts ports starting from @@ -66,9 +65,14 @@ void SimpleResourceManager::notifyAcceptedOffer(ComputingOffer const& offer) } if (resourceFound == false) { - throw std::runtime_error("Could not match offer to original resource."); + std::string resources = "Available resources:\n"; + for (auto& resource : mResources) { + resources += fmt::format("- ({}, {}, {}, {})\n", resource.hostname.c_str(), resource.cpu, resource.memory, resource.startPort); + } + throw std::runtime_error(fmt::format("Could not match offer (host:{}, cpu:{}, mem:{}, ports:{}) to original resource.\n", + offer.hostname, offer.cpu, offer.memory, offer.rangeSize) + + resources); } } -} // namespace framework -} // namespace o2 +} // namespace o2::framework From 63f9c8c7583c3247bd62bc6e0c79b260813566a8 Mon Sep 17 00:00:00 2001 From: dsekihat <daiki.sekihata@cern.ch> Date: Wed, 19 Aug 2020 14:56:15 +0900 Subject: [PATCH 0388/1751] DQ-related Analysis: add PID variables in reduced info tables. (#4145) --- Analysis/Core/include/Analysis/VarManager.h | 44 ++++++++++++++++--- Analysis/Core/src/VarManager.cxx | 22 ++++++++++ .../include/Analysis/ReducedInfoTables.h | 16 ++++++- Analysis/Tasks/tableMaker.cxx | 20 +++++++-- Analysis/Tasks/tableReader.cxx | 41 +++++++++++++---- 5 files changed, 124 insertions(+), 19 deletions(-) diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 0f5a0a81b805f..9438ec0e3cfae 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -42,7 +42,8 @@ class VarManager : public TObject ReducedTrack = BIT(3), ReducedTrackBarrel = BIT(4), ReducedTrackBarrelCov = BIT(5), - ReducedTrackMuon = BIT(6) + ReducedTrackBarrelPID = BIT(6), + ReducedTrackMuon = BIT(7) }; public: @@ -94,12 +95,23 @@ class VarManager : public TObject kTPCsignal, kTRDsignal, kTOFsignal, + kTOFbeta, kTrackLength, kTrackCYY, kTrackCZZ, kTrackCSnpSnp, kTrackCTglTgl, kTrackC1Pt21Pt2, + kTPCnSigmaEl, + kTPCnSigmaMu, + kTPCnSigmaPi, + kTPCnSigmaKa, + kTPCnSigmaPr, + kTOFnSigmaEl, + kTOFnSigmaMu, + kTOFnSigmaPi, + kTOFnSigmaKa, + kTOFnSigmaPr, kNBarrelTrackVariables, // Muon track variables @@ -262,9 +274,10 @@ void VarManager::FillTrack(T const& track, float* values) values[kITSchi2] = track.itsChi2NCl(); values[kTPCncls] = track.tpcNClsFound(); values[kTPCchi2] = track.tpcChi2NCl(); - values[kTPCsignal] = track.tpcSignal(); - values[kTRDsignal] = track.trdSignal(); - values[kTOFsignal] = track.tofSignal(); + //values[kTPCsignal] = track.tpcSignal(); + //values[kTRDsignal] = track.trdSignal(); + //values[kTOFsignal] = track.tofSignal(); + //values[kTOFbeta] = track.beta(); values[kTrackLength] = track.length(); } @@ -299,9 +312,9 @@ void VarManager::FillTrack(T const& track, float* values) values[kITSchi2] = track.itsChi2NCl(); values[kTPCncls] = track.tpcNClsFound(); values[kTPCchi2] = track.tpcChi2NCl(); - values[kTPCsignal] = track.tpcSignal(); - values[kTRDsignal] = track.trdSignal(); - values[kTOFsignal] = track.tofSignal(); + //values[kTPCsignal] = track.tpcSignal(); + //values[kTRDsignal] = track.trdSignal(); + //values[kTOFsignal] = track.tofSignal(); values[kTrackLength] = track.length(); } @@ -313,6 +326,23 @@ void VarManager::FillTrack(T const& track, float* values) values[kTrackC1Pt21Pt2] = track.c1Pt21Pt2(); } + if constexpr ((fillMap & ReducedTrackBarrelPID) > 0) { + values[kTPCnSigmaEl] = track.tpcNSigmaEl(); + values[kTPCnSigmaMu] = track.tpcNSigmaMu(); + values[kTPCnSigmaPi] = track.tpcNSigmaPi(); + values[kTPCnSigmaKa] = track.tpcNSigmaKa(); + values[kTPCnSigmaPr] = track.tpcNSigmaPr(); + values[kTOFnSigmaEl] = track.tofNSigmaEl(); + values[kTOFnSigmaMu] = track.tofNSigmaMu(); + values[kTOFnSigmaPi] = track.tofNSigmaPi(); + values[kTOFnSigmaKa] = track.tofNSigmaKa(); + values[kTOFnSigmaPr] = track.tofNSigmaPr(); + values[kTPCsignal] = track.tpcSignal(); + values[kTRDsignal] = track.trdSignal(); + values[kTOFsignal] = track.tofSignal(); + values[kTOFbeta] = track.beta(); + } + if constexpr ((fillMap & ReducedTrackMuon) > 0) { values[kMuonInvBendingMomentum] = track.inverseBendingMomentum(); values[kMuonThetaX] = track.thetaX(); diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index c8091956a3b53..b942531ac2046 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -167,8 +167,30 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kTRDsignal] = ""; fgVariableNames[kTOFsignal] = "TOF signal"; fgVariableUnits[kTOFsignal] = ""; + fgVariableNames[kTOFbeta] = "TOF #beta"; + fgVariableUnits[kTOFbeta] = ""; fgVariableNames[kTrackLength] = "track length"; fgVariableUnits[kTrackLength] = "cm"; + fgVariableNames[kTPCnSigmaEl] = "n #sigma_{e}^{TPC}"; + fgVariableUnits[kTPCnSigmaEl] = ""; + fgVariableNames[kTPCnSigmaMu] = "n #sigma_{#mu}^{TPC}"; + fgVariableUnits[kTPCnSigmaMu] = ""; + fgVariableNames[kTPCnSigmaPi] = "n #sigma_{#pi}^{TPC}"; + fgVariableUnits[kTPCnSigmaPi] = ""; + fgVariableNames[kTPCnSigmaKa] = "n #sigma_{K}^{TPC}"; + fgVariableUnits[kTPCnSigmaKa] = ""; + fgVariableNames[kTPCnSigmaPr] = "n #sigma_{p}^{TPC}"; + fgVariableUnits[kTPCnSigmaPr] = ""; + fgVariableNames[kTOFnSigmaEl] = "n #sigma_{e}^{TOF}"; + fgVariableUnits[kTOFnSigmaEl] = ""; + fgVariableNames[kTOFnSigmaMu] = "n #sigma_{#mu}^{TOF}"; + fgVariableUnits[kTOFnSigmaMu] = ""; + fgVariableNames[kTOFnSigmaPi] = "n #sigma_{#pi}^{TOF}"; + fgVariableUnits[kTOFnSigmaPi] = ""; + fgVariableNames[kTOFnSigmaKa] = "n #sigma_{K}^{TOF}"; + fgVariableUnits[kTOFnSigmaKa] = ""; + fgVariableNames[kTOFnSigmaPr] = "n #sigma_{p}^{TOF}"; + fgVariableUnits[kTOFnSigmaPr] = ""; fgVariableNames[kMuonInvBendingMomentum] = "Inverse bending mom."; fgVariableUnits[kMuonInvBendingMomentum] = "1/(GeV/c)"; fgVariableNames[kMuonThetaX] = "theta X"; diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 403e605529701..5d78f05e48b7a 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -17,6 +17,7 @@ #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Analysis/Centrality.h" +#include "PID/PIDResponse.h" #include "MathUtils/Utils.h" #include <cmath> @@ -81,7 +82,7 @@ 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::TPCSignal, track::TRDSignal, track::TOFSignal, track::TRDChi2, track::TOFChi2, track::Length, track::TPCNClsFound<track::TPCNClsFindable, track::TPCNClsFindableMinusFound>, track::TPCNClsCrossedRows<track::TPCNClsFindable, track::TPCNClsFindableMinusCrossedRows>); @@ -91,6 +92,18 @@ DECLARE_SOA_TABLE(ReducedTracksBarrelCov, "AOD", "RTBARRELCOV", track::CYY, track::CZZ, track::CSnpSnp, track::CTglTgl, track::C1Pt21Pt2); +// barrel PID information +DECLARE_SOA_TABLE(ReducedTracksBarrelPID, "AOD", "RTBARRELPID", + track::TPCSignal, + pidTPC::TPCNSigmaEl, pidTPC::TPCNSigmaMu, + pidTPC::TPCNSigmaPi, pidTPC::TPCNSigmaKa, pidTPC::TPCNSigmaPr, + pidTPC::TPCNSigmaDe, pidTPC::TPCNSigmaTr, pidTPC::TPCNSigmaHe, pidTPC::TPCNSigmaAl, + track::TOFSignal, pidTOFbeta::Beta, + pidTOF::TOFNSigmaEl, pidTOF::TOFNSigmaMu, + pidTOF::TOFNSigmaPi, pidTOF::TOFNSigmaKa, pidTOF::TOFNSigmaPr, + pidTOF::TOFNSigmaDe, pidTOF::TOFNSigmaTr, pidTOF::TOFNSigmaHe, pidTOF::TOFNSigmaAl, + track::TRDSignal); + // muon quantities namespace reducedmuon { @@ -125,6 +138,7 @@ DECLARE_SOA_TABLE(ReducedMuonsExtended, "AOD", "RTMUONEXTENDED", using ReducedTrack = ReducedTracks::iterator; using ReducedTrackBarrel = ReducedTracksBarrel::iterator; using ReducedTrackBarrelCov = ReducedTracksBarrelCov::iterator; +using ReducedTrackBarrelPID = ReducedTracksBarrelPID::iterator; using ReducedMuon = ReducedMuons::iterator; using ReducedMuonExtended = ReducedMuonsExtended::iterator; } // namespace o2::aod diff --git a/Analysis/Tasks/tableMaker.cxx b/Analysis/Tasks/tableMaker.cxx index 2252e3872c3a2..83fd1c5c713cc 100644 --- a/Analysis/Tasks/tableMaker.cxx +++ b/Analysis/Tasks/tableMaker.cxx @@ -21,6 +21,7 @@ #include "Analysis/ReducedInfoTables.h" #include "Analysis/VarManager.h" #include "Analysis/HistogramManager.h" +#include "PID/PIDResponse.h" #include <iostream> using std::cout; @@ -39,6 +40,7 @@ struct TableMaker { Produces<ReducedTracks> trackBasic; Produces<ReducedTracksBarrel> trackBarrel; Produces<ReducedTracksBarrelCov> trackBarrelCov; + Produces<ReducedTracksBarrelPID> trackBarrelPID; Produces<ReducedMuons> muonBasic; Produces<ReducedMuonsExtended> muonExtended; @@ -66,7 +68,7 @@ struct TableMaker { VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill } - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov> const& tracksBarrel) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracksBarrel) { uint64_t tag = 0; uint32_t triggerAliases = 0; @@ -85,17 +87,29 @@ struct TableMaker { uint64_t trackFilteringTag = 0; for (auto& track : tracksBarrel) { - if (track.pt() < 1.0) + if (track.pt() < 0.15) + continue; + if (TMath::Abs(track.eta()) > 0.9) continue; trackBasic(collision, track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), - track.tpcSignal(), track.trdSignal(), track.tofSignal(), + //track.tpcSignal(), track.trdSignal(), track.tofSignal(), track.trdChi2(), track.tofChi2(), track.length()); trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); + trackBarrelPID( + track.tpcSignal(), + track.tpcNSigmaEl(), track.tpcNSigmaMu(), + track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), + track.tofSignal(), track.beta(), + track.tofNSigmaEl(), track.tofNSigmaMu(), + track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), + track.trdSignal()); } for (auto& muon : tracksMuon) { diff --git a/Analysis/Tasks/tableReader.cxx b/Analysis/Tasks/tableReader.cxx index e773bcb5f330b..8d372398c052e 100644 --- a/Analysis/Tasks/tableReader.cxx +++ b/Analysis/Tasks/tableReader.cxx @@ -51,7 +51,7 @@ struct TableReader { // 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; + 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; void init(o2::framework::InitContext&) @@ -63,7 +63,7 @@ struct TableReader { fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); DefineHistograms("Event_BeforeCuts;Event_AfterCuts;TrackBarrel_BeforeCuts;TrackBarrel_AfterCuts;TrackMuon_BeforeCuts;TrackMuon_AfterCuts;PairsBarrel;PairsMuon;"); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill DefineCuts(); } @@ -84,10 +84,12 @@ struct TableReader { fTrackCut = new AnalysisCompositeCut(true); // true: use AND AnalysisCut* cut1 = new AnalysisCut(); - cut1->AddCut(VarManager::kPt, 1.0, 20.0); + cut1->AddCut(VarManager::kPt, 0.15, 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); AnalysisCut* cut2 = new AnalysisCut(); cut2->AddCut(VarManager::kPt, 0.5, 3.0); fTrackCut->AddCut(cut1); @@ -102,7 +104,7 @@ struct TableReader { } void process(soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator event, - soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov> const& tracks, + soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID> const& tracks, soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended> const& muons) { // Reset the fgValues array @@ -223,8 +225,8 @@ struct TableReader { 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(), "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); @@ -232,8 +234,31 @@ struct TableReader { fHistMan->AddHistogram(classStr.Data(), "Pz", "p_{z} distribution", false, 400, -20.0, 20.0, VarManager::kPz); if (classStr.Contains("Barrel")) { - fHistMan->AddHistogram(classStr.Data(), "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 100, 0.0, 20.0, VarManager::kPin, - 200, 0.0, 200., VarManager::kTPCsignal); // TH2F histogram + + 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 } From f1ae941b4aa8e5bc9d7fcd8d5b0cca2e4f1c8ed1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 19 Aug 2020 10:28:35 +0200 Subject: [PATCH 0389/1751] DPL: drop obsolete code --- Framework/Core/src/DataProcessingDevice.cxx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 61e63fea3c048..05a8b47f6a86f 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -65,13 +65,6 @@ using DataHeader = o2::header::DataHeader; constexpr unsigned int MONITORING_QUEUE_SIZE = 100; constexpr unsigned int MIN_RATE_LOGGING = 60; -// This should result in a minimum of 10Hz which should guarantee we do not use -// much time when idle. We do not sleep at all when we are at less then 100us, -// because that's what the default rate enforces in any case. -constexpr int MAX_BACKOFF = 6; -constexpr int MIN_BACKOFF_DELAY = 100; -constexpr int BACKOFF_DELAY_STEP = 100; - namespace o2::framework { From 9872e3081c4f0d6e915b4622c81425ef8c3f485f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 18 Aug 2020 15:24:27 +0200 Subject: [PATCH 0390/1751] DPL: fix offer accounting when empty workflow is provided --- Framework/Core/src/DeviceSpecHelpers.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 8d77da062c78c..a6eef7615cb12 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -390,7 +390,9 @@ void DeviceSpecHelpers::processOutEdgeActions(std::vector<DeviceSpec>& devices, } appendOutputRouteToSourceDeviceChannel(edge, device, channel); } - resourceManager.notifyAcceptedOffer(acceptedOffer); + if (std::string(acceptedOffer.hostname) != "") { + resourceManager.notifyAcceptedOffer(acceptedOffer); + } sortDeviceIndex(); } @@ -643,7 +645,9 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices, } appendInputRouteToDestDeviceChannel(edge, consumerDevice, channel); } - resourceManager.notifyAcceptedOffer(acceptedOffer); + if (acceptedOffer.hostname != "") { + resourceManager.notifyAcceptedOffer(acceptedOffer); + } } // Construct the list of actual devices we want, given a workflow. From 0951b32941295ba316320ac068acba476918231a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 14 Jul 2020 10:35:39 +0200 Subject: [PATCH 0391/1751] DPL: add tracing to message backends sending method --- Framework/Core/src/CommonMessageBackends.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index 1729042b9ad6c..1b2126c7ff125 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -17,6 +17,7 @@ #include "Framework/RawDeviceService.h" #include "Framework/DeviceSpec.h" #include "Framework/EndOfStreamContext.h" +#include "Framework/Tracing.h" #include <options/FairMQProgOptions.h> @@ -41,6 +42,7 @@ struct CommonMessageBackendsHelpers { static ServiceProcessingCallback sendCallback() { return [](ProcessingContext& ctx, void* service) { + ZoneScopedN("send message callback"); T* context = reinterpret_cast<T*>(service); auto& device = ctx.services().get<RawDeviceService>(); DataProcessor::doSend(*device.device(), *context); From 3557d515a104bf415cb25a104ddd205af6a741cd Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 15 Aug 2020 00:28:54 +0200 Subject: [PATCH 0392/1751] DPL: trace information for DataRelayer lock --- Framework/Core/include/Framework/DataRelayer.h | 3 ++- Framework/Core/src/DataRelayer.cxx | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Framework/Core/include/Framework/DataRelayer.h b/Framework/Core/include/Framework/DataRelayer.h index eac69eda0d1f4..18dc109592cda 100644 --- a/Framework/Core/include/Framework/DataRelayer.h +++ b/Framework/Core/include/Framework/DataRelayer.h @@ -17,6 +17,7 @@ #include "Framework/CompletionPolicy.h" #include "Framework/MessageSet.h" #include "Framework/TimesliceIndex.h" +#include "Framework/Tracing.h" #include <cstddef> #include <mutex> @@ -128,7 +129,7 @@ class DataRelayer static std::vector<std::string> sQueriesMetricsNames; DataRelayerStats mStats; - std::recursive_mutex mMutex; + TracyLockableN(std::recursive_mutex, mMutex, "data relayer mutex"); }; } // namespace o2::framework diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index ec40a61048e1e..8ee9257de9470 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -53,7 +53,7 @@ DataRelayer::DataRelayer(const CompletionPolicy& policy, mDistinctRoutesIndex{DataRelayerHelpers::createDistinctRouteIndex(routes)}, mInputMatchers{DataRelayerHelpers::createInputMatchers(routes)} { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); setPipelineLength(DEFAULT_PIPELINE_LENGTH); @@ -75,7 +75,7 @@ DataRelayer::DataRelayer(const CompletionPolicy& policy, DataRelayer::ActivityStats DataRelayer::processDanglingInputs(std::vector<ExpirationHandler> const& expirationHandlers, ServiceRegistry& services) { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); ActivityStats activity; /// Nothing to do if nothing can expire. @@ -182,7 +182,7 @@ DataRelayer::RelayChoice DataRelayer::relay(std::unique_ptr<FairMQMessage>&& header, std::unique_ptr<FairMQMessage>&& payload) { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); // STATE HOLDING VARIABLES // This is the class level state of the relaying. If we start supporting // multithreading this will have to be made thread safe before we can invoke @@ -387,7 +387,7 @@ DataRelayer::RelayChoice void DataRelayer::getReadyToProcess(std::vector<DataRelayer::RecordAction>& completed) { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); // THE STATE const auto& cache = mCache; @@ -466,7 +466,7 @@ void DataRelayer::getReadyToProcess(std::vector<DataRelayer::RecordAction>& comp std::vector<o2::framework::MessageSet> DataRelayer::getInputsForTimeslice(TimesliceSlot slot) { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); const auto numInputTypes = mDistinctRoutesIndex.size(); // State of the computation @@ -521,7 +521,7 @@ std::vector<o2::framework::MessageSet> DataRelayer::getInputsForTimeslice(Timesl void DataRelayer::clear() { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); for (auto& cache : mCache) { cache.clear(); @@ -543,7 +543,7 @@ size_t /// the time pipelining. void DataRelayer::setPipelineLength(size_t s) { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); mTimesliceIndex.resize(s); mVariableContextes.resize(s); @@ -552,7 +552,7 @@ void DataRelayer::setPipelineLength(size_t s) void DataRelayer::publishMetrics() { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); auto numInputTypes = mDistinctRoutesIndex.size(); mCache.resize(numInputTypes * mTimesliceIndex.size()); @@ -591,7 +591,7 @@ DataRelayerStats const& DataRelayer::getStats() const void DataRelayer::sendContextState() { - std::scoped_lock lock(mMutex); + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); for (size_t ci = 0; ci < mTimesliceIndex.size(); ++ci) { auto slot = TimesliceSlot{ci}; sendVariableContextMetrics(mTimesliceIndex.getPublishedVariablesForSlot(slot), slot, From a1159f4b2d5e9dd43f3686bcd6287cceb901c92e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 19 Aug 2020 21:19:56 +0200 Subject: [PATCH 0393/1751] DPL: {cpu} expands to always the same CPU The cpu is guaranteed to have been used by the parent. --- Framework/Core/src/runDataProcessing.cxx | 26 ++++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 3e5311d114024..1300530fa8eb2 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -383,7 +383,9 @@ void spawnDevice(std::string const& forwardedStdin, ServiceRegistry& serviceRegistry, boost::program_options::variables_map& varmap, uv_loop_t* loop, - std::vector<uv_poll_t*> handles) + std::vector<uv_poll_t*> handles, + unsigned parentCPU, + unsigned parentNode) { int childstdin[2]; int childstdout[2]; @@ -445,19 +447,12 @@ void spawnDevice(std::string const& forwardedStdin, execvp(execution.args[0], execution.args.data()); } if (varmap.count("post-fork-command")) { - unsigned cpu = -1; - unsigned node = -1; -#if __has_include(<linux/getcpu.h>) - getcpu(&cpu, &node, nullptr); -#elif __has_include(<cpuid.h>) - GETCPU(cpu); -#endif auto templateCmd = varmap["post-fork-command"]; auto cmd = fmt::format(templateCmd.as<std::string>(), fmt::arg("pid", id), fmt::arg("id", spec.id), - fmt::arg("cpu", cpu), - fmt::arg("node", node), + fmt::arg("cpu", parentCPU), + fmt::arg("node", parentNode), fmt::arg("name", spec.name), fmt::arg("timeslice0", spec.inputTimesliceId), fmt::arg("timeslice1", spec.inputTimesliceId + 1), @@ -1054,6 +1049,15 @@ int runStateMachine(DataProcessorSpecs const& workflow, std::ostringstream forwardedStdin; WorkflowSerializationHelpers::dump(forwardedStdin, workflow, dataProcessorInfos); infos.reserve(deviceSpecs.size()); + + // This is guaranteed to be a single CPU. + unsigned parentCPU = -1; + unsigned parentNode = -1; +#if __has_include(<linux/getcpu.h>) + getcpu(&parentCPU, &parentNode, nullptr); +#elif __has_include(<cpuid.h>) + GETCPU(parentCPU); +#endif for (size_t di = 0; di < deviceSpecs.size(); ++di) { if (deviceSpecs[di].resource.hostname != driverInfo.deployHostname) { spawnRemoteDevice(forwardedStdin.str(), @@ -1062,7 +1066,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, spawnDevice(forwardedStdin.str(), deviceSpecs[di], driverInfo, controls[di], deviceExecutions[di], infos, - serviceRegistry, varmap, loop, pollHandles); + serviceRegistry, varmap, loop, pollHandles, parentCPU, parentNode); } } assert(infos.empty() == false); From f9cf1bed0225feccaf7e826ad7a5f32044a15c07 Mon Sep 17 00:00:00 2001 From: Maciej Slupecki <maciej.slupecki@gmail.com> Date: Tue, 18 Aug 2020 21:19:07 +0300 Subject: [PATCH 0394/1751] [FV0] Digitizer: simplification, proper digits format (floats replaced with shorts); bug fix in RAW conversion --- .../FV0/include/DataFormatsFV0/ChannelData.h | 2 +- .../FV0/include/DataFormatsFV0/RawEventData.h | 12 ++ .../Detectors/FIT/FV0/src/ChannelData.cxx | 2 +- Detectors/FIT/FV0/macro/readFV0Digits.C | 26 +-- .../FV0Simulation/DigitizationConstant.h | 12 +- .../include/FV0Simulation/Digitizer.h | 30 +--- .../include/FV0Simulation/FV0DigParam.h | 25 +-- .../FIT/FV0/simulation/src/Digitizer.cxx | 157 +++++------------- .../FIT/FV0/simulation/src/Digits2Raw.cxx | 23 +-- 9 files changed, 92 insertions(+), 197 deletions(-) diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/ChannelData.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/ChannelData.h index 5bc80ee55ae83..5cda22e706ab8 100644 --- a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/ChannelData.h +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/ChannelData.h @@ -24,7 +24,7 @@ namespace fv0 struct ChannelData { Short_t pmtNumber = -1; // PhotoMultiplier number (0 to 47) - Float_t time = -1; // [ns] Time associated with rising edge of the singal in a given channel + Short_t time = -1; // [ns] Time associated with rising edge of the singal in a given channel Short_t chargeAdc = -1; // ADC sample as present in raw data ChannelData() = default; diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h index e7eecc7948cca..383f46e9fba07 100644 --- a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/RawEventData.h @@ -67,6 +67,18 @@ struct EventData { uint64_t word_zeros = 0x0; static const size_t PayloadSizeSecondWord = 11; static const size_t PayloadSizeFirstWord = 5; + void generateFlags() + { + numberADC = std::rand() % 2; + isDoubleEvent = 0; + is1TimeLostEvent = 0; + is2TimeLostEvent = 1; + isADCinGate = 0; + isTimeInfoLate = 0; + isAmpHigh = 0; + isEventInTVDC = 1; + isTimeInfoLost = 0; + } }; struct TCMdata { diff --git a/DataFormats/Detectors/FIT/FV0/src/ChannelData.cxx b/DataFormats/Detectors/FIT/FV0/src/ChannelData.cxx index 890ca7fbc1edb..7507b29c0f033 100644 --- a/DataFormats/Detectors/FIT/FV0/src/ChannelData.cxx +++ b/DataFormats/Detectors/FIT/FV0/src/ChannelData.cxx @@ -14,5 +14,5 @@ using namespace o2::fv0; void ChannelData::print() const { - printf(" Pmt=%2d | time =%8.3f | charge =%6d\n", pmtNumber, time, chargeAdc); + printf(" Pmt=%2d | time =%4d | charge =%6d\n", pmtNumber, time, chargeAdc); } diff --git a/Detectors/FIT/FV0/macro/readFV0Digits.C b/Detectors/FIT/FV0/macro/readFV0Digits.C index 96ae58a540646..02fd810e93d5d 100644 --- a/Detectors/FIT/FV0/macro/readFV0Digits.C +++ b/Detectors/FIT/FV0/macro/readFV0Digits.C @@ -53,15 +53,15 @@ void readFV0Digits(std::string digiFName = "fv0digits.root", bool printAllToTerm { gStyle->SetOptStat("noumri"); // Settings for drawing, used with SetRangeUser() - const float tMin = 0, tMax = 50, chargeMin = 5, chargeMax = 800; + const float tMin = -30, tMax = 70, chargeMin = 0, chargeMax = 800; const float chargePerMip = 1. / 16; // Assumes 1-MIP-peak is at 16th ADC channel const int nChannels = o2::fv0::Constants::nFv0Channels; // Init histos std::vector<std::string> vHistoNames; InitHistoNames(vHistoNames); - TH2F* hTimeCharge = new TH2F(vHistoNames.at(0).c_str(), "", 2000, 0, 200, 4096, 0, 4096); - TH2F* hTimeCh = new TH2F(vHistoNames.at(1).c_str(), "", 2000, 0, 200, nChannels, 0, nChannels); + TH2F* hTimeCharge = new TH2F(vHistoNames.at(0).c_str(), "", 400, -200, 200, 4096, 0, 4096); + TH2F* hTimeCh = new TH2F(vHistoNames.at(1).c_str(), "", 400, -200, 200, nChannels, 0, nChannels); TH2F* hChargeCh = new TH2F(vHistoNames.at(2).c_str(), "", 4096, 0, 4096, nChannels, 0, nChannels); TH2F* hMipsCh = new TH2F(vHistoNames.at(3).c_str(), "", 256, 0, 256, nChannels, 0, nChannels); TH1F* hNchReal = new TH1F(vHistoNames.at(4).c_str(), "", 600, 0, 600); @@ -118,7 +118,7 @@ void readFV0Digits(std::string digiFName = "fv0digits.root", bool printAllToTerm // Fill histos for (int ibc = 0; ibc < nbc; ibc++) { - if ((nbc > 10) && (ibc % (nbc / 10) == 0)) { + if ((nbc > 100) && (ibc % (nbc / 100) == 0)) { std::cout << " Progress reading tree: " << ibc << "/" << nbc << " ["; std::cout << 100.0 * ibc / nbc << "%]" << std::endl; } @@ -129,9 +129,6 @@ void readFV0Digits(std::string digiFName = "fv0digits.root", bool printAllToTerm int nchReal = 0; for (int ic = 0; ic < bcd.ref.getEntries(); ic++) { const auto& chd = fv0ChData[chEnt++]; - if ((chd.time == -1024.f) && (chd.chargeAdc == 0.f)) { - continue; - } std::cout << chd.pmtNumber << " " << chd.chargeAdc << " " << chd.time << std::endl; hTimeCharge->Fill(chd.time, chd.chargeAdc); hTimeCh->Fill(chd.time, chd.pmtNumber); @@ -305,8 +302,6 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str } std::cout << " <I> Read: " << vh.size() << " histos" << std::endl; - // TH1D* ht = hTimeCharge->ProjectionX("hTime_prX"); - // TH1D* hc = hTimeCharge->ProjectionY("hCharge_prY"); const float rmargin = 0.12, lmargin = 0.13, tmargin = 0.02, bmargin = 0.15; const float statX1 = 1. - rmargin, statX2 = statX1 - 0.18; const float statH = 0.3, statY1 = 1. - tmargin, statY2 = statY1 - statH; @@ -330,7 +325,7 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str // Draw the comparison of TH1's Color_t col[3] = {kBlack, kRed, kBlue}; TCanvas* c = new TCanvas("fv0digi-cmp-th1", "fv0digi-cmp-th1", 1800, 500); - c->Divide(3, 1); + c->Divide(2, 1); for (UInt_t ifile = 0; ifile < nFiles; ifile++) { TH2F* h2 = (TH2F*)vh.at(ifile * nHistos); h2->SetLineColor(col[ifile]); @@ -343,6 +338,7 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str c->cd(1); gPad->SetMargin(lmargin, rmargin, bmargin, tmargin); gPad->SetLogy(); + ht->SetLineWidth(3.5 - ifile); ht->Draw((ifile == 0) ? "" : "sames"); AdjustStatBox(ht, statX1, statX2, statY1 - statH * ifile, statY2 - statH * ifile); c->cd(2); @@ -352,16 +348,6 @@ int compareFV0Digits(std::string digiFName1 = "fv0digi-rawhistos.root", std::str hc->Draw((ifile == 0) ? "" : "sames"); AdjustStatBox(hc, statX1, statX2, statY1 - statH * ifile, statY2 - statH * ifile); } - c->cd(3); - gPad->SetMargin(lmargin, rmargin, bmargin, tmargin); - gPad->SetLogy(); - for (UInt_t ifile = 0; ifile < nFiles; ifile++) { - TH1* h = vh.at(ifile * nHistos + 4); - h->SetLineColor(col[ifile]); - h->SetLineWidth(2); - h->Draw((ifile == 0) ? "" : "sames"); - AdjustStatBox(h, statX1, statX2, statY1 - statH * ifile, statY2 - statH * ifile); - } return 0; } diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h index d500d1bdf4503..6faa00ff54bec 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/DigitizationConstant.h @@ -14,14 +14,10 @@ namespace o2::fv0 { struct DigitizationConstant { - static constexpr int NCELLSA = 40; // number of scintillator cells - static constexpr float INV_CHARGE_PER_ADC = 1. / 0.6e-12; // charge - static constexpr float N_PHOTONS_PER_MEV = 10400; // average #photons generated per 1 MeV of deposited energy - - //TODO: optimize random ring sizes to balance between sim quality and execution time - static constexpr int PHE_RANDOM_RING_SIZE = 1e5; // size of random ring to be used inside photoelectron loop - static constexpr int HIT_RANDOM_RING_SIZE = 1e4; // size of random ring to be used inside hit loop - static constexpr int NUM_PMT_RESPONSE_TABLES = 9; // number of PMT response tables + static constexpr int NCELLSA = 40; // number of scintillator cells + static constexpr float INV_CHARGE_PER_ADC = 1. / 0.6e-12; // charge conversion + static constexpr float INV_TIME_PER_TDCCHANNEL = 1. / 0.01302; // time conversion from ns to TDC channels + static constexpr float N_PHOTONS_PER_MEV = 10400; // average #photons generated per 1 MeV of deposited energy }; } // namespace o2::fv0 #endif diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h index 557e8518a105b..e4f9fa53d4a38 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h @@ -32,12 +32,10 @@ class Digitizer { private: using DP = DigitizationConstant; - typedef math_utils::RandomRing<float_v::size() * DP::HIT_RANDOM_RING_SIZE> HitRandomRingType; - typedef math_utils::RandomRing<float_v::size() * DP::PHE_RANDOM_RING_SIZE> PheRandomRingType; public: Digitizer() - : mTimeStamp(0), mIntRecord(), mEventId(-1), mSrcId(-1), mMCLabels(), mPmtChargeVsTime(), mNBins(), mRndScintDelay(HitRandomRingType::RandomType::CustomTF1), mRndGainVar(PheRandomRingType::RandomType::CustomTF1), mRndSignalShape(PheRandomRingType::RandomType::CustomTF1), mPmtResponseTables() + : mTimeStamp(0), mIntRecord(), mEventId(-1), mSrcId(-1), mMCLabels(), mPmtChargeVsTime(), mNBins(), mPmtResponseGlobal(), mPmtResponseTemp() { } @@ -72,33 +70,23 @@ class Digitizer Int_t mSrcId; // signal, background or QED std::vector<fv0::MCLabel> mMCLabels; - std::array<std::vector<Float_t>, Constants::nFv0Channels> mPmtChargeVsTime; // Charge time series: analog pulse from PM + std::array<std::vector<Float_t>, Constants::nFv0Channels> mPmtChargeVsTime; // Charge time series aka analogue signal pulse from PM UInt_t mNBins; // Number of bins in pulse series - Float_t mBinSize; // Time width of pulse bin: HPTDC resolution - Float_t mPmtTimeIntegral; // + Float_t mBinSize; // Time width of the pulse bin - HPTDC resolution - // Random rings - HitRandomRingType mRndScintDelay; - PheRandomRingType mRndGainVar; - PheRandomRingType mRndSignalShape; + /// vectors to store the PMT signal from cosmic muons + std::vector<Double_t> mPmtResponseGlobal; + std::vector<Double_t> mPmtResponseTemp; - // 8 tables starting at different sub-bin positions, i.e, [-4:4] / 8 * mBinSize - // wit each table containg values for start + [-2:2:mBinSize] * DigitizationParameters::mPmtTransitTime - std::array<std::vector<Float_t>, DP::NUM_PMT_RESPONSE_TABLES> mPmtResponseTables; - - // Internal helper methods related to conversion of energy-deposition into photons -> photoelectrons -> el. signal + /// Internal helper methods related to conversion of energy-deposition into el. signal Int_t SimulateLightYield(Int_t pmt, Int_t nPhot) const; Float_t SimulateTimeCfd(Int_t channel) const; - static Double_t PmtResponse(Double_t x); - static Double_t PmtResponse(Double_t* x, Double_t*); - static Double_t SinglePhESpectrum(Double_t* x, Double_t* par); - - // Functions related to splitting ring-5 cell signal to two readout channels + /// Functions related to splitting ring-5 cell signal to two readout channels static float getDistFromCellCenter(UInt_t cellId, double hitx, double hity); static float getSignalFraction(float distanceFromXc, bool isFirstChannel); - ClassDefNV(Digitizer, 1); + ClassDefNV(Digitizer, 2); }; // Function used to split the ring-5 cell signal into two readout channels depending on hit position diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h index 2d9d0ad991d70..c70c4464ccf6a 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h @@ -23,22 +23,25 @@ namespace fv0 struct FV0DigParam : public o2::conf::ConfigurableParamHelper<FV0DigParam> { float intrinsicTimeRes = 0.91; // time resolution float photoCathodeEfficiency = 0.23; // quantum efficiency = nOfPhotoE_emitted_by_photocathode / nIncidentPhotons - float lightYield = 0.1; // light collection efficiency to be tuned using collision data + float lightYield = 0.01; // light collection efficiency to be tuned using collision data [1%] float pmtGain = 5e4; // value for PMT R5924-70 at default FV0 gain float pmtTransitTime = 9.5; // PMT response time (corresponds to 1.9 ns rise time) float pmtTransparency = 0.25; // Transparency of the first dynode of the PMT - float pmtNbOfSecElec = 9.0; // Number of secondary electrons emitted from first dynode (per ph.e.) - float shapeConst = 0.029; // Crystal ball const parameter - float shapeMean = 10.2; // Crystal ball mean parameter - float shapeAlpha = -0.34; // Crystal ball alpha parameter - float shapeN = 7.6e06; // Crystal ball N parameter - float shapeSigma = 3.013; // Crystal ball sigma parameter + float shapeConst = 1.18059e-14; // Crystal ball const parameter + float shapeMean = 1.70518e+01; // Crystal ball mean parameter + float shapeAlpha = -6.56586e-01; // Crystal ball alpha parameter + float shapeN = 2.36408e+00; // Crystal ball N parameter + float shapeSigma = 3.55445; // Crystal ball sigma parameter float timeShiftCfd = 3.3; // TODO: adjust after PM design for FV0 is fixed - int photoelMin = 0; // integration lower limit - int photoelMax = 30; // integration upper limit float singleMipThreshold = 3.0; // in [MeV] of deposited energy - float waveformNbins = 2000; // number of bins for the analog pulse waveform - float waveformBinWidth = 0.09765625; // number of bins for the analog (25.0 / 256.0) + float waveformNbins = 10000; // number of bins for the analog pulse waveform + float waveformBinWidth = 0.01302; // number of bins for the analog + float timeCompensate = 23.25; // in ns + float chargeIntBinMin = (timeCompensate - 6.0) / waveformBinWidth; //Charge integration offset (cfd mean time - 6 ns) + float chargeIntBinMax = (timeCompensate + 14.0) / waveformBinWidth; //Charge integration offset (cfd mean time + 14 ns) + bool isIntegrateFull = false; + float cfdCheckWindow = 2.5; // in ns + int avgPhElectron = 201; //Optimization-related, derived constants float oneOverPmtTransitTime2 = 1.0 / (pmtTransitTime * pmtTransitTime); diff --git a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx index f891e70ab4472..2cc2bafbf07d2 100644 --- a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx @@ -37,60 +37,26 @@ void Digitizer::init() mNBins = FV0DigParam::Instance().waveformNbins; //Will be computed using detector set-up from CDB mBinSize = FV0DigParam::Instance().waveformBinWidth; //Will be set-up from CDB - for (Int_t i = 0; i < Constants::nFv0Channels; i++) { - mPmtChargeVsTime[i].resize(mNBins); + for (Int_t detID = 0; detID < Constants::nFv0Channels; detID++) { + mPmtChargeVsTime[detID].resize(mNBins); } - auto const roundVc = [&](int i) -> int { - return (i / Vc::float_v::Size) * Vc::float_v::Size; - }; - // set up PMT response tables - Float_t offset = -0.5f * mBinSize; // offset \in [-0.5..0.5] * mBinSize - Int_t const nBins = roundVc(std::lround(4.0f * FV0DigParam::Instance().pmtTransitTime / mBinSize)); - for (auto& table : mPmtResponseTables) { - table.resize(nBins); - Float_t t = -2.0f * FV0DigParam::Instance().pmtTransitTime + offset; // t \in offset + [-2 2] * FV0DigParam::Instance().mPmtTransitTime - for (Int_t j = 0; j < nBins; ++j) { - table[j] = Digitizer::PmtResponse(t); - t += mBinSize; - } - offset += mBinSize / Float_t(DP::NUM_PMT_RESPONSE_TABLES - 1); - } - - TF1 scintDelayFn("fScintDelay", "gaus", - -6.0f * FV0DigParam::Instance().intrinsicTimeRes, - +6.0f * FV0DigParam::Instance().intrinsicTimeRes); - scintDelayFn.SetParameters(1, 0, FV0DigParam::Instance().intrinsicTimeRes); - mRndScintDelay.initialize(scintDelayFn); - - // Initialize function describing the PMT time response - TF1 pmtResponseFn("mPmtResponse", - &Digitizer::PmtResponse, - -1.0f * FV0DigParam::Instance().pmtTransitTime, - +2.0f * FV0DigParam::Instance().pmtTransitTime, 0); - pmtResponseFn.SetNpx(100); - mPmtTimeIntegral = pmtResponseFn.Integral(-1.0f * FV0DigParam::Instance().pmtTransitTime, - +2.0f * FV0DigParam::Instance().pmtTransitTime); - - // Initialize function describing PMT response to the single photoelectron - TF1 singlePhESpectrumFn("mSinglePhESpectrum", - &Digitizer::SinglePhESpectrum, - FV0DigParam::Instance().photoelMin, - FV0DigParam::Instance().photoelMax, 0); - Float_t const meansPhE = singlePhESpectrumFn.Mean(FV0DigParam::Instance().photoelMin, FV0DigParam::Instance().photoelMax); - mRndGainVar.initialize([&]() -> float { - return singlePhESpectrumFn.GetRandom(FV0DigParam::Instance().photoelMin, FV0DigParam::Instance().photoelMax) / meansPhE; - }); - + // set up PMT response function [avg] TF1 signalShapeFn("signalShape", "crystalball", 0, 200); signalShapeFn.SetParameters(FV0DigParam::Instance().shapeConst, FV0DigParam::Instance().shapeMean, FV0DigParam::Instance().shapeSigma, FV0DigParam::Instance().shapeAlpha, FV0DigParam::Instance().shapeN); - mRndSignalShape.initialize([&]() -> float { - return signalShapeFn.GetRandom(0, mBinSize * Float_t(mNBins)); - }); + + // PMT response per hit [Global] + float x = mBinSize; + mPmtResponseGlobal.resize(mNBins); + for (Int_t j = 0; j < mPmtResponseGlobal.size(); ++j) { + mPmtResponseGlobal[j] = signalShapeFn.Eval(x); + //LOG(INFO)<<x<<" "<<mPmtResponseGlobal[j]; + x += mBinSize; + } LOG(INFO) << "V0Digitizer::init -> finished"; } @@ -103,9 +69,6 @@ void Digitizer::process(const std::vector<o2::fv0::Hit>& hits) std::iota(std::begin(hitIdx), std::end(hitIdx), 0); std::sort(std::begin(hitIdx), std::end(hitIdx), [&hits](int a, int b) { return hits[a].GetTrackID() < hits[b].GetTrackID(); }); - auto const roundVc = [&](int i) -> int { - return (i / Vc::float_v::Size) * Vc::float_v::Size; - }; Int_t parentIdPrev = -10; // use ordered hits for (auto ids : hitIdx) { @@ -134,50 +97,28 @@ void Digitizer::process(const std::vector<o2::fv0::Hit>& hits) // Split signal magnitude to fractions depending on the distance of the hit from the cell center hitEdep = (hit.GetHitValue() * 1e3) * getSignalFraction(distanceFromXc, iChannelPerCell == 0); - LOG(INFO) << " detId: " << detId << "-" << iChannelPerCell << " hitEdep: " << hitEdep << " distanceFromXc: " << distanceFromXc; + //LOG(INFO) << " detId: " << detId << "-" << iChannelPerCell << " hitEdep: " << hitEdep << " distanceFromXc: " << distanceFromXc; ++iChannelPerCell; } else { iChannelPerCell = 2; // not a ring 5 cell -> don't repeat the loop } Double_t const nPhotons = hitEdep * DP::N_PHOTONS_PER_MEV; - Int_t const nPhE = SimulateLightYield(detId, nPhotons); - Float_t const t = hit.GetTime() * 1e9 + FV0DigParam::Instance().pmtTransitTime; - Float_t const charge = TMath::Qe() * FV0DigParam::Instance().pmtGain * mBinSize / mPmtTimeIntegral; - - auto& analogSignal = mPmtChargeVsTime[detId]; - for (Int_t iPhE = 0; iPhE < nPhE; ++iPhE) { - Float_t const tPhE = t + mRndSignalShape.getNextValue(); - Int_t const firstBin = roundVc( - TMath::Max((Int_t)0, (Int_t)((tPhE - FV0DigParam::Instance().pmtTransitTime) / mBinSize))); - Int_t const lastBin = TMath::Min((Int_t)mNBins - 1, - (Int_t)((tPhE + 2. * FV0DigParam::Instance().pmtTransitTime) / mBinSize)); - Float_t const tempT = mBinSize * (0.5f + firstBin) - tPhE; - Float_t* p = analogSignal.data() + firstBin; - long iStart = std::lround((tempT + 2.0f * FV0DigParam::Instance().pmtTransitTime) / mBinSize); - float const offset = tempT + 2.0f * FV0DigParam::Instance().pmtTransitTime - Float_t(iStart) * mBinSize; - long const iOffset = std::lround(offset / mBinSize * Float_t(DP::NUM_PMT_RESPONSE_TABLES - 1)); - if (iStart < 0) { // this should not happen - LOG(ERROR) << "V0Digitizer: table lookup failure"; - } - iStart = roundVc(std::max(long(0), iStart)); - - Vc::float_v workVc; - Vc::float_v pmtVc; - Float_t const* q = mPmtResponseTables[DP::NUM_PMT_RESPONSE_TABLES / 2 + iOffset].data() + iStart; - Float_t const* qEnd = &mPmtResponseTables[DP::NUM_PMT_RESPONSE_TABLES / 2 + iOffset].back(); - for (Int_t i = firstBin, iEnd = roundVc(lastBin); q < qEnd && i < iEnd; i += Vc::float_v::Size) { - pmtVc.load(q); - q += Vc::float_v::Size; - Vc::prefetchForOneRead(q); - workVc.load(p); - workVc += mRndGainVar.getNextValueVc() * charge * pmtVc; - workVc.store(p); - p += Vc::float_v::Size; - Vc::prefetchForOneRead(p); - } - } //photo electron loop - + float const nPhE = SimulateLightYield(detId, nPhotons); + float avgMip = float(nPhE / FV0DigParam::Instance().avgPhElectron); + Float_t const hitTime = hit.GetTime() * 1e9; + //------------------------------------------------------------------------------ + mPmtResponseTemp = mPmtResponseGlobal; + Size_t NBinShift = std::lround(hitTime / FV0DigParam::Instance().waveformBinWidth); + for (int m = 0; m < NBinShift; m++) + mPmtResponseTemp.push_back(0); + // rotate the vector element to shift all the elements by hit time + std::rotate(mPmtResponseTemp.rbegin(), mPmtResponseTemp.rbegin() + NBinShift, mPmtResponseTemp.rend()); + mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins); + + for (int mm = 0; mm < mPmtResponseTemp.size(); mm++) { + mPmtChargeVsTime[detId][mm] += (mPmtResponseTemp[mm] * avgMip); + } // Charged particles in MCLabel Int_t const parentId = hit.GetTrackID(); if (parentId != parentIdPrev) { @@ -196,14 +137,22 @@ void Digitizer::analyseWaveformsAndStore(std::vector<fv0::BCData>& digitsBC, size_t const first = digitsCh.size(); size_t nStored = 0; for (Int_t ipmt = 0; ipmt < Constants::nFv0Channels; ++ipmt) { + float time = SimulateTimeCfd(ipmt) - FV0DigParam::Instance().timeCompensate; + if (time < -FV0DigParam::Instance().cfdCheckWindow || time > FV0DigParam::Instance().cfdCheckWindow) + continue; Float_t totalCharge = 0.0f; auto const& analogSignal = mPmtChargeVsTime[ipmt]; - for (Int_t iTimeBin = 0; iTimeBin < mNBins; ++iTimeBin) { + + int chargeIntMin = FV0DigParam::Instance().isIntegrateFull ? 0 : FV0DigParam::Instance().chargeIntBinMin; + int chargeIntMax = FV0DigParam::Instance().isIntegrateFull ? FV0DigParam::Instance().waveformNbins : FV0DigParam::Instance().chargeIntBinMax; + + for (Int_t iTimeBin = chargeIntMin; iTimeBin < chargeIntMax; ++iTimeBin) { Float_t const timeBinCharge = mPmtChargeVsTime[ipmt][iTimeBin]; totalCharge += timeBinCharge; } totalCharge *= DP::INV_CHARGE_PER_ADC; - digitsCh.emplace_back(ipmt, SimulateTimeCfd(ipmt), std::lround(totalCharge)); + time *= DP::INV_TIME_PER_TDCCHANNEL; + digitsCh.emplace_back(ipmt, static_cast<short int>(std::round(time)), static_cast<short int>(std::round(totalCharge))); ++nStored; } @@ -229,7 +178,7 @@ Int_t Digitizer::SimulateLightYield(Int_t pmt, Int_t nPhot) const } const Int_t n = Int_t(nPhot < 100 ? gRandom->Binomial(nPhot, p) - : gRandom->Gaus(p * nPhot + 0.5, TMath::Sqrt(p * (1 - p) * nPhot))); + : gRandom->Gaus((p * nPhot) + 0.5, TMath::Sqrt(p * (1. - p) * nPhot))); return n; } @@ -251,35 +200,7 @@ Float_t Digitizer::SimulateTimeCfd(Int_t channel) const return timeCfd; } -Double_t Digitizer::PmtResponse(Double_t* x, Double_t*) -{ - return Digitizer::PmtResponse(x[0]); -} -//_______________________________________________________________________ -Double_t Digitizer::PmtResponse(Double_t x) -{ - // this function describes the PMT time response to a single photoelectron - if (x > 2 * FV0DigParam::Instance().pmtTransitTime) - return 0.0; - if (x < -FV0DigParam::Instance().pmtTransitTime) - return 0.0; - x += FV0DigParam::Instance().pmtTransitTime; - Double_t const x2 = x * x; - return x2 * std::exp(-x2 * FV0DigParam::Instance().oneOverPmtTransitTime2); -} - -Double_t Digitizer::SinglePhESpectrum(Double_t* x, Double_t*) -{ - // x -- number of photo-electrons emitted from the first dynode - // this function describes the PMT amplitude response to a single photoelectron - if (x[0] < 0.0) - return 0.0; - return (TMath::Poisson(x[0], FV0DigParam::Instance().pmtNbOfSecElec) + - FV0DigParam::Instance().pmtTransparency * TMath::Poisson(x[0], 1.0)); -} - // The Distance is positive for top half-sectors (when the hit position is above the cell center (has higher y)) -// TODO: performance check needed float Digitizer::getDistFromCellCenter(UInt_t cellId, double hitx, double hity) { Geometry* geo = Geometry::instance(); diff --git a/Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx index c57d465e69b45..0e2424b6729dd 100644 --- a/Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digits2Raw.cxx @@ -96,29 +96,16 @@ void Digits2Raw::convertDigits(o2::fv0::BCData bcdigits, gsl::span<const Channel if (prevPmLink >= 0) { fillSecondHalfWordAndAddData(iChannelPerLink, prevPmLink, intRecord); } - if (ich != nch - 1) { - LOG(DEBUG) << " Switch prevPmLink: " << prevPmLink << ". Save data with nGBTWords=" - << uint((iChannelPerLink + 1) / 2) << " in header."; - makeGBTHeader(mRawEventData.mEventHeader, nLinkPm, intRecord); - iChannelPerLink = 0; - prevPmLink = nLinkPm; - } + makeGBTHeader(mRawEventData.mEventHeader, nLinkPm, intRecord); + iChannelPerLink = 0; + prevPmLink = nLinkPm; } if (pmchannels[ich].chargeAdc != 0) { LOG(DEBUG) << " Store data for channel: " << ich << " PmLink = " << nLinkPm << " "; auto& newData = mRawEventData.mEventData[iChannelPerLink]; newData.charge = pmchannels[ich].chargeAdc; newData.time = pmchannels[ich].time; - newData.is1TimeLostEvent = 0; - newData.is2TimeLostEvent = 0; - newData.isADCinGate = 1; - newData.isAmpHigh = 0; - newData.isDoubleEvent = 0; - newData.isEventInTVDC = 1; - newData.isTimeInfoLate = 0; - newData.isTimeInfoLost = 0; - int chain = std::rand() % 2; - newData.numberADC = chain ? 1 : 0; + newData.generateFlags(); newData.channelID = lut.getPmChannel(pmchannels[ich].pmtNumber); iChannelPerLink++; } @@ -181,4 +168,6 @@ void Digits2Raw::fillSecondHalfWordAndAddData(int iChannelPerLink, int prevPmLin uint32_t linkId = uint32_t(prevPmLink); uint64_t feeId = uint64_t(prevPmLink); mWriter.addData(feeId, sCruId, linkId, sEndPointId, ir, data); + LOG(DEBUG) << " Switch prevPmLink: " << prevPmLink << ". Save data with nGBTWords=" + << nGBTWords << " in header. Last channel: " << iChannelPerLink; } From 5463578aa17d26d22fb31ece1219703b98068650 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Fri, 14 Aug 2020 13:49:18 -0300 Subject: [PATCH 0395/1751] Kalman update step moved to TrackParCovFwd - rename TrackFitter::addCluster -> computeCluster - fix track chi2 --- .../ReconstructionDataFormats/TrackFwd.h | 3 + DataFormats/Reconstruction/src/TrackFwd.cxx | 47 ++++++++ .../include/MFTTracking/TrackFitter.h | 4 +- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 101 +++++------------- 4 files changed, 75 insertions(+), 80 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index 2ae69b75e63d7..930dd46ecd751 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -143,6 +143,9 @@ class TrackParCovFwd : public TrackParFwd // Add Multiple Coulomb Scattering effects void addMCSEffect(double dZ, double x2X0); + // Kalman filter/fitting + bool update(const std::array<float, 2>& p, const std::array<float, 2>& cov); + private: /// Covariance matrix of track parameters, ordered as follows: <pre> /// <X,X> <Y,X> <PHI,X> <TANL,X> <INVQPT,X> diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 7e19da02e3d09..5e07b75f008e6 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -268,6 +268,53 @@ void TrackParCovFwd::propagateToZhelix(double zEnd, double zField) setCovariances(ROOT::Math::Similarity(jacob, mCovariances)); } +//__________________________________________________________________________ +bool TrackParCovFwd::update(const std::array<float, 2>& p, const std::array<float, 2>& cov) +{ + /// Kalman update step: computes new track parameters with a new cluster position and uncertainties + /// The current track is expected to have been propagated to the cluster z position + /// Returns false in case of failure + + // get new cluster parameters (m) + SMatrix5 clusterParam; + clusterParam(0) = p[0]; + clusterParam(1) = p[1]; + + // compute the actual parameter weight (W) + SMatrix55 paramWeight(mCovariances); + if (!(paramWeight.Invert())) { + std::cout << "runKalmanFilter ERROR: Determinant = 0\n"; + return false; + } + + // compute the new cluster weight (U) + SMatrix55 clusterWeight; + clusterWeight(0, 0) = 1. / cov[0]; + clusterWeight(1, 1) = 1. / cov[1]; + + // compute the new parameters covariance matrix ((W+U)^-1) + SMatrix55 newParamCov(paramWeight + clusterWeight); + if (!newParamCov.Invert()) { + std::cout << "runKalmanFilter ERROR: Determinant = 0\n"; + return false; + } + mCovariances = newParamCov; + + // compute the new parameters: (p' = ((W+U)^-1)U(m-p) + p) + // Parameters increment: p' - p = ((W+U)^-1)U(m-p) + SMatrix5 predict_residuals(clusterParam - mParameters); // m-p -> residuals of prediction + SMatrix5 tmp(clusterWeight * predict_residuals); // U(m-p) + SMatrix5 newParamDelta(newParamCov * tmp); // ((W+U)^-1)U(m-p) + mParameters += newParamDelta; // ((W+U)^-1)U(m-p) + p + + // compute the additional addChi2 = ((p'-p)^t)W(p'-p) + ((p'-m)^t)U(p'-m) + SMatrix5 tmp2(mParameters - clusterParam); // (p'-m) + auto addChi2Track(ROOT::Math::Similarity(newParamDelta, paramWeight) + ROOT::Math::Similarity(tmp2, clusterWeight)); + mTrackChi2 += addChi2Track; + + return true; +} + //__________________________________________________________________________ void TrackParCovFwd::addMCSEffect(double dZ, double x_over_X0) { diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h index 3bbcf41f9b0cc..91601db595087 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackFitter.h @@ -49,13 +49,11 @@ class TrackFitter bool initTrack(TrackLTF& track, bool outward = false); bool fit(TrackLTF& track, bool outward = false); - bool runKalmanFilter(TrackLTF& track, int cluster); - /// Return the maximum chi2 above which the track can be considered as abnormal static constexpr double getMaxChi2() { return SMaxChi2; } private: - bool addCluster(TrackLTF& track, int cluster); + bool computeCluster(TrackLTF& track, int cluster); Float_t mBZField; // kiloGauss. static constexpr double SMaxChi2 = 2.e10; ///< maximum chi2 above which the track can be considered as abnormal diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index b0adaed5167a8..cb96f0046d093 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -53,8 +53,7 @@ void TrackFitter::setBz(float bZ) bool TrackFitter::fit(TrackLTF& track, bool outward) { - /// Fit a track to its attached clusters - /// Fit the entire track or only the part upstream itStartingParam + /// Fit a track using its attached clusters /// Returns false in case of failure auto& mftTrackingParam = MFTTrackingParam::Instance(); @@ -66,26 +65,25 @@ bool TrackFitter::fit(TrackLTF& track, bool outward) << std::endl; } - // recursively add clusters and update the track parameters - if (!outward) { // Inward + // recursively compute clusters, updating the track parameters + if (!outward) { // Inward for vertexing nClusters--; while (nClusters-- > 0) { - if (!addCluster(track, nClusters)) { + if (!computeCluster(track, nClusters)) { return false; } } } else { // Outward for MCH matching int ncl = 1; while (ncl < nClusters) { - if (!addCluster(track, ncl)) { + if (!computeCluster(track, ncl)) { return false; } ncl++; } } if (mftTrackingParam.verbose) { - // std::cout << "Track covariances:"; - // trac->getCovariances().Print(); + // Print final covariances? std::cout << "Track covariances:"; track->getCovariances().Print(); std::cout << "Track Chi2 = " << track.getTrackChi2() << std::endl; std::cout << " ***************************** Done fitting *****************************\n"; } @@ -105,7 +103,6 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) auto nPoints = track.getNPoints(); auto k = TMath::Abs(o2::constants::math::B2C * mBZField); auto Hz = std::copysign(1, mBZField); - //invQPtSeed = invQPtFromParabola(track, mBZField, chi2invqptquad); invQPtSeed = invQPtFromFCF(track, mBZField, chi2invqptquad); if (mftTrackingParam.verbose) { @@ -117,21 +114,17 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) track.setChi2QPtSeed(chi2invqptquad); track.setInvQPt(invQPtSeed); - /// Compute the initial track parameters - /// The covariance matrix is computed such that the last cluster is the only constraint - /// (by assigning an infinite dispersion to the other cluster) - /// These parameters are the seed for the Kalman filter + /// Compute the initial track parameters to seed the Kalman filter - // compute track parameters - int where; // First or last cluster? + int start; // Start fitting by the first or the last cluster if (outward) - where = 0; + start = 0; else - where = nPoints - 1; + start = nPoints - 1; - double x0 = track.getXCoordinates()[where]; - double y0 = track.getYCoordinates()[where]; - double z0 = track.getZCoordinates()[where]; + double x0 = track.getXCoordinates()[start]; + double y0 = track.getYCoordinates()[start]; + double z0 = track.getZCoordinates()[start]; double deltaX = track.getXCoordinates()[nPoints - 1] - track.getXCoordinates()[0]; double deltaY = track.getYCoordinates()[nPoints - 1] - track.getYCoordinates()[0]; double deltaZ = track.getZCoordinates()[nPoints - 1] - track.getZCoordinates()[0]; @@ -143,8 +136,8 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) double r0cu = r0sq * TMath::Sqrt(r0sq); double invr0sq = 1.0 / r0sq; double invr0cu = 1.0 / r0cu; - double sigmax0sq = track.getSigmasX2()[where]; - double sigmay0sq = track.getSigmasY2()[where]; + double sigmax0sq = track.getSigmasX2()[start]; + double sigmay0sq = track.getSigmasY2()[start]; double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond double sigmaboost = mftTrackingParam.sigmaboost; // Boost q/pt seed covariances double seedH_k = mftTrackingParam.seedH_k; // SeedH constant @@ -207,7 +200,7 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) } //_________________________________________________________________________________________________ -bool TrackFitter::addCluster(TrackLTF& track, int cluster) +bool TrackFitter::computeCluster(TrackLTF& track, int cluster) { /// Propagate track to the z position of the new cluster /// accounting for MCS dispersion in the current layer and the other(s) crossed @@ -218,6 +211,8 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) const auto& clx = track.getXCoordinates()[cluster]; const auto& cly = track.getYCoordinates()[cluster]; const auto& clz = track.getZCoordinates()[cluster]; + const auto& sigmaX2 = track.getSigmasX2()[cluster]; + const auto& sigmaY2 = track.getSigmasY2()[cluster]; if (track.getZ() == clz) { LOG(INFO) << "AddCluster ERROR: The new cluster must be upstream! Bug on TrackFinder. " << (track.isCA() ? " CATrack" : "LTFTrack"); @@ -225,7 +220,7 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) return true; } if (mftTrackingParam.verbose) - std::cout << "addCluster: X = " << clx << " Y = " << cly << " Z = " << clz << " nCluster = " << cluster << std::endl; + std::cout << "computeCluster: X = " << clx << " Y = " << cly << " Z = " << clz << " nCluster = " << cluster << std::endl; // add MCS effects for the new cluster using o2::mft::constants::LayerZPosition; @@ -281,8 +276,11 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) if (mftTrackingParam.verbose) std::cout << " AfterExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; - // recompute the parameters - if (runKalmanFilter(track, cluster)) { + // recompute parameters + const std::array<float, 2>& pos = {clx, cly}; + const std::array<float, 2>& cov = {sigmaX2, sigmaY2}; + + if (track.update(pos, cov)) { if (mftTrackingParam.verbose) { std::cout << " New Cluster: X = " << clx << " Y = " << cly << " Z = " << clz << std::endl; std::cout << " AfterKalman: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; @@ -295,57 +293,6 @@ bool TrackFitter::addCluster(TrackLTF& track, int cluster) return false; } -//_________________________________________________________________________________________________ -bool TrackFitter::runKalmanFilter(TrackLTF& track, int cluster) -{ - /// Compute the new track parameters including the attached cluster with the Kalman filter - /// The current track is expected to have been propagated to the cluster z position - /// Retruns false in case of failure - - // get propagated track parameters (p) - auto param = track.getParameters(); - - // get new cluster parameters (m) - SMatrix5 clusterParam; - clusterParam(0) = track.getXCoordinates()[cluster]; - clusterParam(1) = track.getYCoordinates()[cluster]; - - // compute the actual parameter weight (W) - SMatrix55 paramWeight(track.getCovariances()); - if (!(paramWeight.Invert())) { - LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; - return false; - } - - // compute the new cluster weight (U) - SMatrix55 clusterWeight; - clusterWeight(0, 0) = 1. / track.getSigmasX2()[cluster]; - clusterWeight(1, 1) = 1. / track.getSigmasY2()[cluster]; - - // compute the new parameters covariance matrix ((W+U)^-1) - SMatrix55 newParamCov(paramWeight + clusterWeight); - if (!newParamCov.Invert()) { - LOG(INFO) << "runKalmanFilter ERROR: Determinant = 0"; - return false; - } - track.setCovariances(newParamCov); - - // compute the new parameters: (p' = ((W+U)^-1)U(m-p) + p) - // Parameters increment: p' - p = ((W+U)^-1)U(m-p) - SMatrix5 predict_residuals(clusterParam - param); // m-p -> residuals of prediction - SMatrix5 tmp(clusterWeight * predict_residuals); // U(m-p) - SMatrix5 newParamDelta(newParamCov * tmp); // ((W+U)^-1)U(m-p) - SMatrix5 newParam = newParamDelta + param; // ((W+U)^-1)U(m-p) + p - track.setParameters(newParam); - - // compute the additional addChi2 = ((p'-p)^t)W(p'-p) + ((p'-m)^t)U(p'-m) - SMatrix5 tmp2(clusterParam - newParam); // (m-p) - auto addChi2Track(ROOT::Math::Similarity(newParamDelta, paramWeight) + ROOT::Math::Similarity(tmp2, clusterWeight)); - track.setTrackChi2(track.getTrackChi2() + addChi2Track); - - return true; -} - //_________________________________________________________________________________________________ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) { From eda2d5ac40963c04bcf1eb02ef9ff117a2607180 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Mon, 17 Aug 2020 13:26:40 -0300 Subject: [PATCH 0396/1751] Trivial optimizations on parameter propagation --- DataFormats/Reconstruction/src/TrackFwd.cxx | 51 ++++++--------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 5e07b75f008e6..3e7961c7ac6e0 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -37,18 +37,14 @@ void TrackParFwd::propagateParamToZlinear(double zEnd) // Compute track parameters auto dZ = (zEnd - getZ()); - auto x0 = getX(); - auto y0 = getY(); auto phi0 = getPhi(); double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); auto invtanl0 = 1.0 / getTanl(); auto n = dZ * invtanl0; - auto x = x0 + n * cosphi0; - auto y = y0 + n * sinphi0; - setX(x); - setY(y); - setZ(zEnd); + mParameters(0) += n * cosphi0; + mParameters(1) += n * sinphi0; + mZ = zEnd; } //__________________________________________________________________________ @@ -58,8 +54,6 @@ void TrackParCovFwd::propagateToZlinear(double zEnd) // Calculate the jacobian related to the track parameters extrapolated to "zEnd" auto dZ = (zEnd - getZ()); - auto x0 = getX(); - auto y0 = getY(); auto phi0 = getPhi(); auto tanl0 = getTanl(); auto invtanl0 = 1.0 / tanl0; @@ -123,8 +117,6 @@ void TrackParCovFwd::propagateToZquadratic(double zEnd, double zField) // Compute track parameters auto dZ = (zEnd - getZ()); - auto x0 = getX(); - auto y0 = getY(); auto phi0 = getPhi(); double cosphi0, sinphi0; o2::utils::sincos(phi0, sinphi0, cosphi0); @@ -137,13 +129,10 @@ void TrackParCovFwd::propagateToZquadratic(double zEnd, double zField) auto theta = -invqpt0 * dZ * k * invtanl0; // Extrapolate track parameters to "zEnd" - auto x = x0 + n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; - auto y = y0 + n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; - auto phi = phi0 + Hz * theta; - setX(x); - setY(y); - setZ(zEnd); - setPhi(phi); + mParameters(0) += n * cosphi0 - 0.5 * n * theta * Hz * sinphi0; + mParameters(1) += n * sinphi0 + 0.5 * n * theta * Hz * cosphi0; + mParameters(2) += Hz * theta; + mZ = zEnd; // Calculate Jacobian SMatrix55 jacob = ROOT::Math::SMatrixIdentity(); @@ -172,8 +161,6 @@ void TrackParFwd::propagateParamToZhelix(double zEnd, double zField) // Compute track parameters auto dZ = (zEnd - getZ()); - auto x0 = getX(); - auto y0 = getY(); auto phi0 = getPhi(); auto tanl0 = getTanl(); auto invtanl0 = 1.0 / tanl0; @@ -195,13 +182,10 @@ void TrackParFwd::propagateParamToZhelix(double zEnd, double zField) auto XS = X * sintheta; // Extrapolate track parameters to "zEnd" - auto x = x0 + Hz * (Y - YC) - XS; - auto y = y0 + Hz * (-X + XC) - YS; - auto phi = phi0 + Hz * theta; - setX(x); - setY(y); - setZ(zEnd); - setPhi(phi); + mParameters(0) += Hz * (Y - YC) - XS; + mParameters(1) += Hz * (-X + XC) - YS; + mParameters(2) += Hz * theta; + mZ = zEnd; } //__________________________________________________________________________ @@ -211,8 +195,6 @@ void TrackParCovFwd::propagateToZhelix(double zEnd, double zField) // using helix track model auto dZ = (zEnd - getZ()); - auto x0 = getX(); - auto y0 = getY(); auto phi0 = getPhi(); auto tanl0 = getTanl(); auto invtanl0 = 1.0 / tanl0; @@ -245,13 +227,10 @@ void TrackParCovFwd::propagateToZhelix(double zEnd, double zField) auto m = n * invtanl0; // Extrapolate track parameters to "zEnd" - auto x = x0 + Hz * (Y - YC) - XS; - auto y = y0 + Hz * (-X + XC) - YS; - auto phi = phi0 + Hz * theta; - setX(x); - setY(y); - setZ(zEnd); - setPhi(phi); + mParameters(0) += Hz * (Y - YC) - XS; + mParameters(1) += Hz * (-X + XC) - YS; + mParameters(2) += Hz * theta; + mZ = zEnd; // Calculate Jacobian SMatrix55 jacob = ROOT::Math::SMatrixIdentity(); From 4400e15ed04b927073bb9c780e84d95d6d73fad6 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Wed, 19 Aug 2020 12:33:07 -0300 Subject: [PATCH 0397/1751] Kalman gain formalism on forward tracking update --- DataFormats/Reconstruction/src/TrackFwd.cxx | 81 ++++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 3e7961c7ac6e0..9741168a72863 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -252,43 +252,52 @@ bool TrackParCovFwd::update(const std::array<float, 2>& p, const std::array<floa { /// Kalman update step: computes new track parameters with a new cluster position and uncertainties /// The current track is expected to have been propagated to the cluster z position - /// Returns false in case of failure - - // get new cluster parameters (m) - SMatrix5 clusterParam; - clusterParam(0) = p[0]; - clusterParam(1) = p[1]; - - // compute the actual parameter weight (W) - SMatrix55 paramWeight(mCovariances); - if (!(paramWeight.Invert())) { - std::cout << "runKalmanFilter ERROR: Determinant = 0\n"; - return false; - } - - // compute the new cluster weight (U) - SMatrix55 clusterWeight; - clusterWeight(0, 0) = 1. / cov[0]; - clusterWeight(1, 1) = 1. / cov[1]; - // compute the new parameters covariance matrix ((W+U)^-1) - SMatrix55 newParamCov(paramWeight + clusterWeight); - if (!newParamCov.Invert()) { - std::cout << "runKalmanFilter ERROR: Determinant = 0\n"; - return false; - } - mCovariances = newParamCov; - - // compute the new parameters: (p' = ((W+U)^-1)U(m-p) + p) - // Parameters increment: p' - p = ((W+U)^-1)U(m-p) - SMatrix5 predict_residuals(clusterParam - mParameters); // m-p -> residuals of prediction - SMatrix5 tmp(clusterWeight * predict_residuals); // U(m-p) - SMatrix5 newParamDelta(newParamCov * tmp); // ((W+U)^-1)U(m-p) - mParameters += newParamDelta; // ((W+U)^-1)U(m-p) + p - - // compute the additional addChi2 = ((p'-p)^t)W(p'-p) + ((p'-m)^t)U(p'-m) - SMatrix5 tmp2(mParameters - clusterParam); // (p'-m) - auto addChi2Track(ROOT::Math::Similarity(newParamDelta, paramWeight) + ROOT::Math::Similarity(tmp2, clusterWeight)); + using SVector2 = ROOT::Math::SVector<double, 2>; + using SMatrix22 = ROOT::Math::SMatrix<double, 2>; + using SMatrix25 = ROOT::Math::SMatrix<double, 2, 5>; + using SMatrix52 = ROOT::Math::SMatrix<double, 5, 2>; + using SMatrix55Std = ROOT::Math::SMatrix<double, 5>; + + SMatrix55 I = ROOT::Math::SMatrixIdentity(); + SMatrix25 H_k; + SMatrix22 V_k; + SVector2 m_k(p[0], p[1]), r_k_kminus1; + V_k(0, 0) = cov[0]; + V_k(1, 1) = cov[1]; + H_k(0, 0) = 1.0; + H_k(1, 1) = 1.0; + + // Covariance of residuals + SMatrix22 invResCov = (V_k + ROOT::Math::Similarity(H_k, mCovariances)); + invResCov.Invert(); + + // Kalman Gain Matrix + SMatrix52 K_k = mCovariances * ROOT::Math::Transpose(H_k) * invResCov; + + // Update Parameters + r_k_kminus1 = m_k - H_k * mParameters; // Residuals of prediction + mParameters = mParameters + K_k * r_k_kminus1; + + // Update covariances Matrix + SMatrix55Std updatedCov = (I - K_k * H_k) * mCovariances; + mCovariances(0, 0) = updatedCov(0, 0); + mCovariances(0, 1) = updatedCov(0, 1); + mCovariances(0, 2) = updatedCov(0, 2); + mCovariances(0, 3) = updatedCov(0, 3); + mCovariances(0, 4) = updatedCov(0, 4); + mCovariances(1, 1) = updatedCov(1, 1); + mCovariances(1, 2) = updatedCov(1, 2); + mCovariances(1, 3) = updatedCov(1, 3); + mCovariances(1, 4) = updatedCov(1, 4); + mCovariances(2, 2) = updatedCov(2, 2); + mCovariances(2, 3) = updatedCov(2, 3); + mCovariances(2, 4) = updatedCov(2, 4); + mCovariances(3, 3) = updatedCov(3, 3); + mCovariances(3, 4) = updatedCov(3, 4); + mCovariances(4, 4) = updatedCov(4, 4); + + auto addChi2Track = ROOT::Math::Similarity(r_k_kminus1, invResCov); mTrackChi2 += addChi2Track; return true; From afd4d98da8e0d54fa5a4638f8f346fe4bb40b1cc Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaya@cern.ch> Date: Thu, 20 Aug 2020 12:54:42 +0300 Subject: [PATCH 0398/1751] FT0: add DigitsWriter to data reader (#4104) * add DigitsWriter to data reader * rename FT0DigitWriterSpec Co-authored-by: AllaMaevskaya <Alla.Maevskaia@cern.ch> --- Detectors/FIT/FT0/workflow/CMakeLists.txt | 8 +++- Detectors/FIT/FT0/workflow/README.md | 17 +++++++ .../FT0Workflow/FT0DigitWriterDPLSpec.h | 31 +++++++++++++ .../include/FT0Workflow/FT0DigitWriterSpec.h | 31 +++++++++++++ .../include/FT0Workflow/FT0Workflow.h | 4 +- .../workflow/src/FT0DigitWriterDPLSpec.cxx | 46 +++++++++++++++++++ .../FT0/workflow/src/FT0DigitWriterSpec.cxx | 46 +++++++++++++++++++ .../FIT/FT0/workflow/src/FT0Workflow.cxx | 12 +++-- .../FIT/FT0/workflow/src/ft0-flp-workflow.cxx | 44 +++++++++++++----- 9 files changed, 221 insertions(+), 18 deletions(-) create mode 100644 Detectors/FIT/FT0/workflow/README.md create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterDPLSpec.h create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterSpec.h create mode 100644 Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx create mode 100644 Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx diff --git a/Detectors/FIT/FT0/workflow/CMakeLists.txt b/Detectors/FIT/FT0/workflow/CMakeLists.txt index 993e4d3aeec66..e56e686e0a47e 100644 --- a/Detectors/FIT/FT0/workflow/CMakeLists.txt +++ b/Detectors/FIT/FT0/workflow/CMakeLists.txt @@ -19,7 +19,8 @@ o2_add_library(FT0Workflow src/FT0Workflow.cxx src/FT0DataProcessDPLSpec.cxx src/FT0DataReaderDPLSpec.cxx - PUBLIC_LINK_LIBRARIES O2::Framework + src/FT0DigitWriterDPLSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsFT0 O2::FT0Reconstruction O2::DetectorsCommonDataFormats @@ -49,5 +50,8 @@ o2_add_executable(flp-dpl-workflow TARGETVARNAME ft0flpexe) if(NOT APPLE) + set_property(TARGET ${fitrecoexe} PROPERTY LINK_WHAT_YOU_USE ON) -endif() + +endif() + diff --git a/Detectors/FIT/FT0/workflow/README.md b/Detectors/FIT/FT0/workflow/README.md new file mode 100644 index 0000000000000..735c41436d65a --- /dev/null +++ b/Detectors/FIT/FT0/workflow/README.md @@ -0,0 +1,17 @@ +# FLP DPL workflow, for reading raw data blocks from payload, and converting them into digits. + +To run with source file: + +o2-raw-file-reader-workflow -b --input-conf /home/fitdaq/work/data_raw_reader/run_raw_reader_v6.cfg|o2-ft0-flp-dpl-workflow -b + +If you want to dump digits in reader DPL: + +o2-raw-file-reader-workflow -b --input-conf /home/fitdaq/work/data_raw_reader/run_raw_reader_v6.cfg|o2-ft0-flp-dpl-workflow -b --dump-blocks-reader + +If you need to check data at "proccessor" DPL: + +o2-raw-file-reader-workflow -b --input-conf /home/fitdaq/work/data_raw_reader/run_raw_reader_v6.cfg|o2-ft0-flp-dpl-workflow -b --dump-blocks-process --use-process + +Special TCM extended mode (only for special technical runs): + +o2-raw-file-reader-workflow -b --input-conf /home/fitdaq/work/data_raw_reader/run_raw_reader_v6.cfg|o2-ft0-flp-dpl-workflow -b --tcm-extended-mode \ No newline at end of file diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterDPLSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterDPLSpec.h new file mode 100644 index 0000000000000..a5f985c0149b9 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterDPLSpec.h @@ -0,0 +1,31 @@ +// 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 FT0DigitWriterSpec.h + +#ifndef O2_FT0DIGITWRITERDPL_H +#define O2_FT0DIGITWRITERDPL_H + +#include "Framework/DataProcessorSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +/// create a processor spec +framework::DataProcessorSpec getFT0DigitWriterDPLSpec(); + +} // namespace ft0 +} // namespace o2 + +#endif /* O2_FT0DIGITWRITER_H */ diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterSpec.h new file mode 100644 index 0000000000000..13f5534745990 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DigitWriterSpec.h @@ -0,0 +1,31 @@ +// 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 FT0DigitWriterSpec.h + +#ifndef O2_FT0DIGITWRITER_H +#define O2_FT0DIGITWRITER_H + +#include "Framework/DataProcessorSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +/// create a processor spec +framework::DataProcessorSpec getFT0DigitWriterSpec(); + +} // namespace ft0 +} // namespace o2 + +#endif /* O2_FT0DIGITWRITER_H */ diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h index 5e833c0103cfc..518773debf15b 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h @@ -19,7 +19,9 @@ namespace o2 { namespace fit { -framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, bool dumpProcessor, bool dumpReader); +framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, + bool dumpProcessor, bool dumpReader, + bool disableRootOut); } // namespace fit } // namespace o2 #endif diff --git a/Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx new file mode 100644 index 0000000000000..4169700cada0f --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx @@ -0,0 +1,46 @@ +// 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 FT0DigitWriterSpec.cxx + +#include <vector> + +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "DataFormatsFT0/ChannelData.h" +#include "DataFormatsFT0/Digit.h" +#include "FT0Workflow/FT0DigitWriterDPLSpec.h" +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +template <typename T> +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; +DataProcessorSpec getFT0DigitWriterDPLSpec() +{ + using DigitType = std::vector<o2::ft0::Digit>; + using ChanDataType = std::vector<o2::ft0::ChannelData>; + // Spectators for logging + auto logger = [](DigitType const& digits) { + LOG(INFO) << "FT0DigitWriter pulled " << digits.size() << " digits"; + }; + return MakeRootTreeWriterSpec( + "ft0-digit-writer", "o2digit_ft0.root", "o2digits", + BranchDefinition<DigitType>{InputSpec{"digits", "FT0", "DIGITSBC", 0}, + "FT0Digits", "ft0-digits-branch-name", 1, + logger}, + BranchDefinition<ChanDataType>{InputSpec{"digch", "FT0", "DIGITSCH", 0}, + "FT0ChData", "ft0-chhdata-branch-name"})(); +} + +} // namespace ft0 +} // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx new file mode 100644 index 0000000000000..7b2c2e02ade88 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx @@ -0,0 +1,46 @@ +// 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 FT0DigitWriterSpec.cxx + +#include <vector> + +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "DataFormatsFT0/ChannelData.h" +#include "DataFormatsFT0/Digit.h" +#include "FT0Workflow/FT0DigitWriterSpec.h" +using namespace o2::framework; + +namespace o2 +{ +namespace ft0 +{ + +template <typename T> +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; +DataProcessorSpec getFT0DigitWriterSpec() +{ + using DigitType = std::vector<o2::ft0::Digit>; + using ChanDataType = std::vector<o2::ft0::ChannelData>; + // Spectators for logging + auto logger = [](DigitType const& digits) { + LOG(INFO) << "FT0DigitWriter pulled " << digits.size() << " digits"; + }; + return MakeRootTreeWriterSpec( + "ft0-digit-writer", "o2digit_ft0.root", "o2digits", + BranchDefinition<DigitType>{InputSpec{"digits", "FT0", "DIGITSBC", 0}, + "FT0Digits", "ft0-digits-branch-name", 1, + logger}, + BranchDefinition<ChanDataType>{InputSpec{"digch", "FT0", "DIGITSCH", 0}, + "FT0ChData", "ft0-chhdata-branch-name"})(); +} + +} // namespace ft0 +} // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx index 8bc57045e8822..0031832efd2bd 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx @@ -11,21 +11,27 @@ /// @file FT0Workflow.cxx #include "FT0Workflow/FT0Workflow.h" -#include "FT0Workflow/FT0DataReaderDPLSpec.h" #include "FT0Workflow/FT0DataProcessDPLSpec.h" +#include "FT0Workflow/FT0DataReaderDPLSpec.h" +#include "FT0Workflow/FT0DigitWriterDPLSpec.h" namespace o2 { namespace fit { -framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, bool dumpProcessor, bool dumpReader) +framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, + bool dumpProcessor, bool dumpReader, + bool disableRootOut) { LOG(INFO) << "framework::WorkflowSpec getFT0Workflow"; framework::WorkflowSpec specs; - specs.emplace_back(o2::ft0::getFT0DataReaderDPLSpec(dumpReader, isExtendedMode)); + specs.emplace_back( + o2::ft0::getFT0DataReaderDPLSpec(dumpReader, isExtendedMode)); if (useProcess) specs.emplace_back(o2::ft0::getFT0DataProcessDPLSpec(dumpProcessor)); + if (!disableRootOut) + specs.emplace_back(o2::ft0::getFT0DigitWriterDPLSpec()); return specs; } diff --git a/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx b/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx index 4a4f1d73b333a..059dda0028a86 100644 --- a/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "FT0Workflow/FT0Workflow.h" #include "CommonUtils/ConfigurableParam.h" +#include "FT0Workflow/FT0Workflow.h" using namespace o2::framework; @@ -19,15 +19,33 @@ using namespace o2::framework; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { // option allowing to set parameters - workflowOptions.push_back(ConfigParamSpec{ - "tcm-extended-mode", o2::framework::VariantType::Bool, false, {"in case of extended TCM mode (1 header + 1 TCMdata + 8 TCMdataExtended)"}}); - - workflowOptions.push_back(ConfigParamSpec{ - "use-process", o2::framework::VariantType::Bool, false, {"enable processor for data taking/dumping"}}); - workflowOptions.push_back(ConfigParamSpec{ - "dump-blocks-process", o2::framework::VariantType::Bool, false, {"enable dumping of event blocks at processor side"}}); - workflowOptions.push_back(ConfigParamSpec{ - "dump-blocks-reader", o2::framework::VariantType::Bool, false, {"enable dumping of event blocks at reader side"}}); + workflowOptions.push_back( + ConfigParamSpec{"tcm-extended-mode", + o2::framework::VariantType::Bool, + false, + {"in case of extended TCM mode (1 header + 1 TCMdata + 8 " + "TCMdataExtended)"}}); + + workflowOptions.push_back( + ConfigParamSpec{"use-process", + o2::framework::VariantType::Bool, + false, + {"enable processor for data taking/dumping"}}); + workflowOptions.push_back( + ConfigParamSpec{"dump-blocks-process", + o2::framework::VariantType::Bool, + false, + {"enable dumping of event blocks at processor side"}}); + workflowOptions.push_back( + ConfigParamSpec{"dump-blocks-reader", + o2::framework::VariantType::Bool, + false, + {"enable dumping of event blocks at reader side"}}); + workflowOptions.push_back( + ConfigParamSpec{"disable-root-output", + o2::framework::VariantType::Bool, + false, + {"disable root-files output writers"}}); } // ------------------------------------------------------------------ @@ -41,7 +59,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto dumpProcessor = configcontext.options().get<bool>("dump-blocks-process"); auto dumpReader = configcontext.options().get<bool>("dump-blocks-reader"); auto isExtendedMode = configcontext.options().get<bool>("tcm-extended-mode"); - + auto disableRootOut = + configcontext.options().get<bool>("disable-root-output"); LOG(INFO) << "WorkflowSpec FLPWorkflow"; - return std::move(o2::fit::getFT0Workflow(isExtendedMode, useProcessor, dumpProcessor, dumpReader)); + return std::move(o2::fit::getFT0Workflow( + isExtendedMode, useProcessor, dumpProcessor, dumpReader, disableRootOut)); } From 2babd8806dc587974516fb7c48da28da23d55184 Mon Sep 17 00:00:00 2001 From: saganatt <8majak8@gmail.com> Date: Thu, 20 Aug 2020 14:27:17 +0200 Subject: [PATCH 0399/1751] DPL Analysis: Extending Histogram Registry support to TH2, TH3 - corrected (#4176) --- .../include/Framework/HistogramRegistry.h | 181 ++++++++++++++++-- .../Core/test/benchmark_HistogramRegistry.cxx | 2 +- .../Core/test/test_HistogramRegistry.cxx | 6 +- 3 files changed, 170 insertions(+), 19 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 75ca56a0eea43..9c7bf0d5a29f8 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -32,31 +32,66 @@ namespace o2 namespace framework { +// Most common histogram types +enum HistogramType : unsigned int { + kTH1D = 0, + kTH1F = 1, + kTH1I = 2, + kTH2D = 3, + kTH2F = 4, + kTH2I = 5, + kTH3D = 6, + kTH3F = 7, + kTH3I = 8 +}; + +/// Description of a single histogram axis +struct AxisSpec { + AxisSpec(int nBins_, std::vector<double> bins_, std::string label_ = "") + : nBins(nBins_), + bins(bins_), + binsEqual(false), + label(label_) + { + } + + AxisSpec(int nBins_, double binMin_, double binMax_, std::string label_ = "") + : nBins(nBins_), + bins({binMin_, binMax_}), + binsEqual(true), + label(label_) + { + } + + AxisSpec() : nBins(1), binsEqual(false), bins(), label("") {} + + int nBins; + std::vector<double> bins; + bool binsEqual; // if true, then bins specify min and max for equidistant binning + std::string label; +}; + /// Data sctructure that will allow to construct a fully qualified TH* histogram -/// Currently only supports TH1F struct HistogramConfigSpec { - HistogramConfigSpec(char const* const kind_, unsigned int nBins_, double xmin_, double xmax_) - : kind(kind_), - nBins(nBins_), - xmin(xmin_), - xmax(xmax_) + HistogramConfigSpec(HistogramType type_, std::vector<AxisSpec> axes_) + : type(type_), + axes(axes_), + binsEqual(axes.size() > 0 ? axes[0].binsEqual : false) { } HistogramConfigSpec() - : kind(""), - nBins(1), - xmin(0), - xmax(1) + : type(HistogramType::kTH1F), + axes(), + binsEqual(false) { } HistogramConfigSpec(HistogramConfigSpec const& other) = default; HistogramConfigSpec(HistogramConfigSpec&& other) = default; - std::string kind; - unsigned int nBins; - double xmin; - double xmax; + HistogramType type; + std::vector<AxisSpec> axes; + bool binsEqual; }; /// Data structure containing histogram specification for the HistogramRegistry @@ -86,6 +121,110 @@ struct HistogramSpec { HistogramConfigSpec config; }; +template <typename T> +std::unique_ptr<TH1> createTH1FromSpec(HistogramSpec const& spec) +{ + if (spec.config.axes.size() == 0) { + throw std::runtime_error("No arguments available in spec to create a histogram"); + } + if (spec.config.binsEqual) { + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1]); + } + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data()); +} + +template <typename T> +std::unique_ptr<TH2> createTH2FromSpec(HistogramSpec const& spec) +{ + if (spec.config.axes.size() == 0) { + throw std::runtime_error("No arguments available in spec to create a histogram"); + } + if (spec.config.binsEqual) { + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1]); + } + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data()); +} + +template <typename T> +std::unique_ptr<TH3> createTH3FromSpec(HistogramSpec const& spec) +{ + if (spec.config.axes.size() == 0) { + throw std::runtime_error("No arguments available in spec to create a histogram"); + } + if (spec.config.binsEqual) { + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1], spec.config.axes[2].nBins, spec.config.axes[2].bins[0], spec.config.axes[2].bins[1]); + } + return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data(), spec.config.axes[2].nBins, spec.config.axes[2].bins.data()); +} + +using HistogramCreationCallback = std::function<std::unique_ptr<TH1>(HistogramSpec const& spec)>; + +// Wrapper to avoid multiple function definitinions error +struct HistogramCallbacks { + static HistogramCreationCallback createTH1D() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH1FromSpec<TH1D>(spec); + }; + } + + static HistogramCreationCallback createTH1F() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH1FromSpec<TH1F>(spec); + }; + } + + static HistogramCreationCallback createTH1I() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH1FromSpec<TH1I>(spec); + }; + } + + static HistogramCreationCallback createTH2D() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH2FromSpec<TH2D>(spec); + }; + } + + static HistogramCreationCallback createTH2F() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH2FromSpec<TH2F>(spec); + }; + } + + static HistogramCreationCallback createTH2I() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH2FromSpec<TH2I>(spec); + }; + } + + static HistogramCreationCallback createTH3D() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH3FromSpec<TH3D>(spec); + }; + } + + static HistogramCreationCallback createTH3F() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH3FromSpec<TH3F>(spec); + }; + } + + static HistogramCreationCallback createTH3I() + { + return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { + return createTH3FromSpec<TH3I>(spec); + }; + } +}; + /// Histogram registry for an analysis task that allows to define needed histograms /// and serves as the container/wrapper to fill them class HistogramRegistry @@ -95,7 +234,16 @@ class HistogramRegistry : name(name_), enabled(enable), mRegistryKey(), - mRegistryValue() + mRegistryValue(), + mHistogramCreationCallbacks({HistogramCallbacks::createTH1D(), + HistogramCallbacks::createTH1F(), + HistogramCallbacks::createTH1I(), + HistogramCallbacks::createTH2D(), + HistogramCallbacks::createTH2F(), + HistogramCallbacks::createTH2I(), + HistogramCallbacks::createTH3D(), + HistogramCallbacks::createTH3F(), + HistogramCallbacks::createTH3I()}) { mRegistryKey.fill(0u); for (auto& spec : specs) { @@ -148,7 +296,7 @@ class HistogramRegistry for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { if (mRegistryValue[imask(j + i)].get() == nullptr) { mRegistryKey[imask(j + i)] = spec.id; - mRegistryValue[imask(j + i)] = {std::make_unique<TH1F>(spec.name.data(), spec.readableName.data(), spec.config.nBins, spec.config.xmin, spec.config.xmax)}; + mRegistryValue[imask(j + i)] = mHistogramCreationCallbacks[spec.config.type](spec); lookup += j; return; } @@ -169,6 +317,7 @@ class HistogramRegistry static constexpr uint32_t MAX_REGISTRY_SIZE = mask + 1; std::array<uint32_t, MAX_REGISTRY_SIZE> mRegistryKey; std::array<std::unique_ptr<TH1>, MAX_REGISTRY_SIZE> mRegistryValue; + std::vector<HistogramCreationCallback> mHistogramCreationCallbacks; }; } // namespace framework diff --git a/Framework/Core/test/benchmark_HistogramRegistry.cxx b/Framework/Core/test/benchmark_HistogramRegistry.cxx index 18c09d1a31f34..f91436dcc4cdd 100644 --- a/Framework/Core/test/benchmark_HistogramRegistry.cxx +++ b/Framework/Core/test/benchmark_HistogramRegistry.cxx @@ -30,7 +30,7 @@ static void BM_HashedNameLookup(benchmark::State& state) state.PauseTiming(); std::vector<HistogramSpec> specs; for (auto i = 0; i < state.range(0); ++i) { - specs.push_back({(boost::format("histo%1%") % (i + 1)).str().c_str(), (boost::format("Histo %1%") % (i + 1)).str().c_str(), {"TH1F", 100, 0, 1}}); + specs.push_back({fmt::format("histo{}", i + 1).c_str(), fmt::format("Histo {}", i + 1).c_str(), {HistogramType::kTH1F, {{100, 0, 1}}}}); } HistogramRegistry registry{"registry", true, specs}; state.ResumeTiming(); diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 5edccb200622c..040f1191a624b 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -19,18 +19,20 @@ using namespace o2::framework; HistogramRegistry foo() { - return {"r", true, {{"histo", "histo", {"TH1F", 100, 0, 1}}}}; + return {"r", true, {{"histo", "histo", {HistogramType::kTH1F, {{100, 0, 1}}}}}}; } BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) { /// Construct a registry object with direct declaration - HistogramRegistry registry{"registry", true, {{"eta", "#Eta", {"TH1F", 100, -2.0, 2.0}}, {"phi", "#Phi", {"TH1D", 102, 0, 2 * M_PI}}, {"pt", "p_{T}", {"TH1D", 1002, -0.01, 50.1}}}}; + HistogramRegistry registry{"registry", true, {{"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}}}}; /// Get histograms by name BOOST_REQUIRE_EQUAL(registry.get("eta")->GetNbinsX(), 100); BOOST_REQUIRE_EQUAL(registry.get("phi")->GetNbinsX(), 102); BOOST_REQUIRE_EQUAL(registry.get("pt")->GetNbinsX(), 1002); + BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsX(), 100); + BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsY(), 100); /// Get a pointer to the histogram auto histo = registry.get("pt").get(); From 702d96702880bf1762214cfb6d95a508117ad062 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Thu, 20 Aug 2020 15:46:18 +0200 Subject: [PATCH 0400/1751] DPL Analysis: function to get size of the original table from iterator (#4180) --- Framework/Core/include/Framework/ASoA.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 6bb0ba45ff5c5..70b681c426435 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -484,6 +484,12 @@ struct DefaultIndexPolicy : IndexPolicyBase { { return O2_BUILTIN_UNLIKELY(this->mRowIndex == sentinel.index); } + + auto size() const + { + return mMaxRow; + } + int64_t mMaxRow = 0; }; @@ -568,11 +574,16 @@ struct FilteredIndexPolicy : IndexPolicyBase { this->mRowIndex = -1; } - int64_t getSelectionRow() const + auto getSelectionRow() const { return mSelectionRow; } + auto size() const + { + return mMaxSelection; + } + private: inline void updateRow() { @@ -854,6 +865,8 @@ class Table } } + using IP::size; + using RowViewCore<IP, C...>::operator++; /// Allow incrementing by more than one the iterator From 1faed77200cf76c11cae56c04919f856cfed4494 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 13 Aug 2020 08:55:26 +0200 Subject: [PATCH 0401/1751] ITS: Respect debug level for logging --- .../ITS/tracking/include/ITStracking/Tracker.h | 12 ++++++++---- .../ITS/tracking/include/ITStracking/Vertexer.h | 16 +++++++++++----- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 4 ++-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 4c8e35914f5eb..ebf45963c3eef 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -34,6 +34,8 @@ #include "DataFormatsITS/TrackITS.h" #include "SimulationDataFormat/MCCompLabel.h" +#include "Framework/Logger.h" + namespace o2 { namespace gpu @@ -147,10 +149,12 @@ float Tracker::evaluateTask(void (Tracker::*task)(T...), const char* taskName, s std::chrono::duration<double, std::milli> diff_t{end - start}; diff = diff_t.count(); - if (taskName == nullptr) { - ostream << diff << "\t"; - } else { - ostream << std::setw(2) << " - " << taskName << " completed in: " << diff << " ms" << std::endl; + if (fair::Logger::Logging(fair::Severity::info)) { + if (taskName == nullptr) { + ostream << diff << "\t"; + } else { + ostream << std::setw(2) << " - " << taskName << " completed in: " << diff << " ms" << std::endl; + } } } else { (this->*task)(std::forward<T>(args)...); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index ba73fb6ca00c6..ebf6857ec2cf6 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -31,6 +31,8 @@ #include "ITStracking/Tracklet.h" #include "ITStracking/Cluster.h" +#include "Framework/Logger.h" + class TTree; namespace o2 @@ -137,7 +139,9 @@ inline std::vector<Vertex> Vertexer::exportVertices() { std::vector<Vertex> vertices; for (auto& vertex : mTraits->getVertices()) { - std::cout << "\t\tFound vertex with: " << std::setw(6) << vertex.mContributors << " contributors" << std::endl; + if (fair::Logger::Logging(fair::Severity::info)) { + std::cout << "\t\tFound vertex with: " << std::setw(6) << vertex.mContributors << " contributors" << std::endl; + } vertices.emplace_back(Point3D<float>(vertex.mX, vertex.mY, vertex.mZ), vertex.mRMS2, vertex.mContributors, vertex.mAvgDistance2); vertices.back().setTimeStamp(vertex.mTimeStamp); } @@ -158,10 +162,12 @@ float Vertexer::evaluateTask(void (Vertexer::*task)(T...), const char* taskName, std::chrono::duration<double, std::milli> diff_t{end - start}; diff = diff_t.count(); - if (taskName == nullptr) { - ostream << diff << "\t"; - } else { - ostream << std::setw(2) << " - " << taskName << " completed in: " << diff << " ms" << std::endl; + if (fair::Logger::Logging(fair::Severity::info)) { + if (taskName == nullptr) { + ostream << diff << "\t"; + } else { + ostream << std::setw(2) << " - " << taskName << " completed in: " << diff << " ms" << std::endl; + } } } else { (this->*task)(std::forward<T>(args)...); diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 844c90aa56e7f..8d0703a7242c6 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -69,10 +69,10 @@ void Tracker::clustersToTracks(const ROframe& event, std::ostream& timeBenchmark total += evaluateTask(&Tracker::findRoads, "Road finding", timeBenchmarkOutputStream, iteration); total += evaluateTask(&Tracker::findTracks, "Track finding", timeBenchmarkOutputStream, event); } - - if (constants::DoTimeBenchmarks) + if (constants::DoTimeBenchmarks && fair::Logger::Logging(fair::Severity::info)) { timeBenchmarkOutputStream << std::setw(2) << " - " << "Vertex processing completed in: " << total << "ms" << std::endl; + } } if (event.hasMCinformation()) { computeTracksMClabels(event); From 354c2f1b48cfe9366e81db27cac15be075376501 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 20 Aug 2020 12:34:10 +0200 Subject: [PATCH 0402/1751] Opt. to call carry-over method for last chunk to fix the trailer --- Detectors/Raw/README.md | 10 ++++-- .../Raw/include/DetectorsRaw/RawFileWriter.h | 4 +++ Detectors/Raw/src/RawFileWriter.cxx | 34 +++++++++++++++---- Detectors/Raw/test/testRawReaderWriter.cxx | 14 +++++++- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Detectors/Raw/README.md b/Detectors/Raw/README.md index e35c82c4158ce..a04841f24c3aa 100644 --- a/Detectors/Raw/README.md +++ b/Detectors/Raw/README.md @@ -125,12 +125,18 @@ header : what it wants to add right after the RDH of the new CRU page before th the payload (starting at ptr+actualSize) will be written ``` -The method mast return actual size of the bloc which can be written (`<=maxSize`). +The method must return actual size of the bloc which can be written (`<=maxSize`). If this method populates the trailer, it must ensure that it returns the actual size such that `actualSize + trailer.size() <= maxSize`. -In case returned `actualSize` is 0, current CRU page will be closed w/o adding anything, and new +In case returned `actualSize` is 0, current CRU page will be closed just with user trailer added (if any) and new query of this method will be done on the new CRU page. +By default, the carry-over callback is not called if remaining data fits to the free space of the 8KB page (or the super-page). +In case the splitting affects the information written in the payload trailer, user may set `writer.setApplyCarryOverToLastPage(true)`. +With this flag set to `ON`, if there was at least one splitting for the user payload provided to `addData` method, then the carry-over +method will be called also for the very last chunk (which by definition does not need splitting) and the supplied trailer will overwrite +the tail of the this chunk instead of adding it incrementally. + Additionally, in case detector wants to add some information between `empty` HBF packet's opening and closing RDHs (they will be added automatically using the HBFUtils functionality for all HBFs w/o data between the orbit 0 and last orbit of the TF seen in the simulations), it may implement a callback method diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h b/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h index d9a59eb8dfb63..ee895a5a3d599 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h @@ -341,9 +341,12 @@ class RawFileWriter } } + void setApplyCarryOverToLastPage(bool v) { mApplyCarryOverToLastPage = v; } + bool isRORCDetector() const { return !mCRUDetector; } bool isCRUDetector() const { return mCRUDetector; } bool isRDHStopUsed() const { return mUseRDHStop; } + bool isCarryOverToLastPageApplied() const { return mApplyCarryOverToLastPage; } private: void fillFromCache(); @@ -369,6 +372,7 @@ class RawFileWriter bool mAddSeparateHBFStopPage = true; // HBF stop is added on a separate CRU page bool mUseRDHStop = true; // detector uses STOP in RDH bool mCRUDetector = true; // Detector readout via CRU ( RORC if false) + bool mApplyCarryOverToLastPage = false; // call CarryOver method also for last chunk and overwrite modified trailer //>> caching -------------- bool mCachingStage = false; // signal that current data should be cached diff --git a/Detectors/Raw/src/RawFileWriter.cxx b/Detectors/Raw/src/RawFileWriter.cxx index 0aaebd76a8330..ca0b497278234 100644 --- a/Detectors/Raw/src/RawFileWriter.cxx +++ b/Detectors/Raw/src/RawFileWriter.cxx @@ -308,7 +308,7 @@ void RawFileWriter::LinkData::addData(const IR& ir, const gsl::span<char> data, // in case particular detector CRU pages need to be self-consistent, when carrying-over // large payload to new CRU page we may need to write optional trailer and header before // and after the new RDH. - bool carryOver = false; + bool carryOver = false, wasSplit = false, lastSplitPart = false; int splitID = 0; std::vector<char> carryOverHeader; while (dataSize > 0) { @@ -328,26 +328,46 @@ void RawFileWriter::LinkData::addData(const IR& ir, const gsl::span<char> data, addHBFPage(); // start new CRU page, if needed, the completed superpage is flushed continue; } - if (dataSize <= sizeLeft) { // add all remaining data + + if (dataSize <= sizeLeft) { + if (wasSplit && writer->mApplyCarryOverToLastPage) { + lastSplitPart = true; + carryOver = true; + } + } else { + carryOver = true; + wasSplit = true; + } + + if (!carryOver) { // add all remaining data LOG(DEBUG) << "Adding payload " << dataSize << " bytes in IR " << ir << " (carryover=" << carryOver << " ) to " << describe(); pushBack(ptr, dataSize); dataSize = 0; } else { // need to carryOver payload, determine 1st wsize bytes to write starting from ptr - carryOver = true; + if (sizeLeft > dataSize) { + sizeLeft = dataSize; + } int sizeActual = sizeLeft; std::vector<char> carryOverTrailer; if (writer->carryOverFunc) { sizeActual = writer->carryOverFunc(&rdhCopy, data, ptr, sizeLeft, splitID++, carryOverTrailer, carryOverHeader); } LOG(DEBUG) << "Adding carry-over " << splitID - 1 << " fitted payload " << sizeActual << " bytes in IR " << ir << " to " << describe(); - if (sizeActual < 0 || sizeActual + carryOverTrailer.size() > sizeLeft) { + if (sizeActual < 0 || (!lastSplitPart && (sizeActual + carryOverTrailer.size() > sizeLeft))) { throw std::runtime_error(std::string("wrong carry-over data size provided by carryOverMethod") + std::to_string(sizeActual)); } - pushBack(ptr, sizeActual); // write payload fitting to this page + // if there is carry-over trailer at the very last chunk, it must overwrite existing trailer + int trailerOffset = 0; + if (lastSplitPart) { + trailerOffset = carryOverTrailer.size(); + if (sizeActual - trailerOffset < 0) { + throw std::runtime_error("trailer size of last split chunk cannot exceed actual size as it overwrites the existing trailer"); + } + } + pushBack(ptr, sizeActual - trailerOffset); // write payload fitting to this page dataSize -= sizeActual; ptr += sizeActual; - LOG(DEBUG) << "Adding carryOverTrailer " << carryOverTrailer.size() << " bytes in IR " - << ir << " to " << describe(); + LOG(DEBUG) << "Adding carryOverTrailer " << carryOverTrailer.size() << " bytes in IR " << ir << " to " << describe(); pushBack(carryOverTrailer.data(), carryOverTrailer.size()); } } diff --git a/Detectors/Raw/test/testRawReaderWriter.cxx b/Detectors/Raw/test/testRawReaderWriter.cxx index c816e59b49704..d11c7aba41e19 100644 --- a/Detectors/Raw/test/testRawReaderWriter.cxx +++ b/Detectors/Raw/test/testRawReaderWriter.cxx @@ -81,6 +81,8 @@ struct TestRawWriter { // simple class to create detector payload for multiple l writer.setEmptyPageCallBack(this); // we want the writer to ask the detector code what to put in empty HBFs } writer.setCarryOverCallBack(this); // we want that writer to ask the detector code how to split large payloads + + writer.setApplyCarryOverToLastPage(true); // call CarryOver method also for the last chunk } //_________________________________________________________________ @@ -155,10 +157,17 @@ struct TestRawWriter { // simple class to create detector payload for multiple l { // how we want to split the large payloads. The data is the full payload which was sent for writing and // it is already equiped with header and trailer + static int verboseCount = 0; + if (maxSize <= RDHUtils::GBTWord) { // do not carry over trailer or header only return 0; } + int bytesLeft = data.size() - (ptr - &data[0]); + bool lastPage = bytesLeft <= maxSize; + if (verboseCount++ < 100) { + LOG(INFO) << "Carry-over method for chunk of size " << bytesLeft << " is called, MaxSize = " << maxSize << (lastPage ? " : last chunk being processed!" : ""); + } // here we simply copy the header/trailer of the payload to every CRU page of this payload header.resize(RDHUtils::GBTWord); std::memcpy(header.data(), &data[0], RDHUtils::GBTWord); @@ -166,7 +175,10 @@ struct TestRawWriter { // simple class to create detector payload for multiple l std::memcpy(trailer.data(), &data[data.size() - RDHUtils::GBTWord], RDHUtils::GBTWord); // since we write an extra GBT word (trailer) in the end of the CRU page, we ask to write // not the block ptr : ptr+maxSize, but ptr : ptr+maxSize - GBTWord; - int sz = maxSize - RDHUtils::GBTWord; + int sz = maxSize; // if the method is called for the last page, then the trailer is overwritten !!! + if (!lastPage) { // otherwise it is added incrementally, so its size must be accounted + sz -= trailer.size(); + } return sz; } }; From 80005d792d3124543954df8481ad5bfa74fba396 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 21 Aug 2020 00:49:53 +0200 Subject: [PATCH 0403/1751] Allocate large CTF buffer in advance to avoid rebooking --- .../EncodedBlocks.h | 3 +- .../include/FT0Reconstruction/CTFCoder.h | 6 +++ .../FIT/FT0/reconstruction/src/CTFCoder.cxx | 24 ++++++++++++ .../include/FV0Reconstruction/CTFCoder.h | 6 +++ .../FIT/FV0/reconstruction/src/CTFCoder.cxx | 22 +++++++++++ .../include/ITSMFTReconstruction/CTFCoder.h | 5 +++ .../common/reconstruction/src/CTFCoder.cxx | 27 +++++++++++++ .../include/TOFReconstruction/CTFCoder.h | 6 ++- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 26 +++++++++++++ .../include/TPCReconstruction/CTFCoder.h | 5 +++ Detectors/TPC/reconstruction/src/CTFCoder.cxx | 38 +++++++++++++++++++ 11 files changed, 166 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index b8372e90d605e..4f5dd67a97675 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -786,8 +786,9 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source } // estimate size of encode buffer - int dataSize = rans::calculateMaxBufferSize(messageLength, encoder->getAlphabetRangeBits(), sizeof(S)); + int dataSize = rans::calculateMaxBufferSize(messageLength, encoder->getAlphabetRangeBits(), sizeof(S)); // size in bytes // preliminary expansion of storage based on dict size + estimated size of encode buffer + dataSize = dataSize / sizeof(W) + (sizeof(S) < sizeof(W)); // size in words of output stream expandStorage(dictSize + dataSize); //store dictionary first if (dictSize) { diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index ffc678e3c6510..5a6dd6bb5ddea 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -52,6 +52,7 @@ class CTFCoder : public o2::ctf::CTFCoderBase private: /// compres digits clusters to CompressedDigits void compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); + size_t estimateCompressedSize(const CompressedDigits& cc); /// decompress CompressedDigits to digits template <typename VDIG, typename VCHAN> @@ -82,6 +83,11 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g }; CompressedDigits cd; compress(cd, digitVec, channelVec); + + // book output size with some margin + auto szIni = estimateCompressedSize(cd); + buff.resize(szIni); + auto ec = CTF::create(buff); using ECB = CTF::base; diff --git a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx index eb568cc84b5dc..3dc5aa2c36e19 100644 --- a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx @@ -134,3 +134,27 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: MAKECODER(cd.qtcAmpl, CTF::BLC_qtcAmpl); // clang-format on } + +///________________________________ +size_t CTFCoder::estimateCompressedSize(const CompressedDigits& cd) +{ + size_t sz = 0; + // clang-format off + // RS FIXME this is very crude estimate, instead, an empirical values should be used +#define VTP(vec) typename std::remove_reference<decltype(vec)>::type::value_type +#define ESTSIZE(vec, slot) mCoders[int(slot)] ? \ + rans::calculateMaxBufferSize(vec.size(), reinterpret_cast<const o2::rans::LiteralEncoder64<VTP(vec)>*>(mCoders[int(slot)].get())->getAlphabetRangeBits(), sizeof(VTP(vec)) ) : vec.size()*sizeof(VTP(vec)) + sz += ESTSIZE(cd.trigger, CTF::BLC_trigger); + sz += ESTSIZE(cd.bcInc, CTF::BLC_bcInc); + sz += ESTSIZE(cd.orbitInc, CTF::BLC_orbitInc); + sz += ESTSIZE(cd.nChan, CTF::BLC_nChan); + // sz += ESTSIZE(cd.eventFlags, CTF::BLC_flags); + sz += ESTSIZE(cd.idChan, CTF::BLC_idChan); + sz += ESTSIZE(cd.qtcChain, CTF::BLC_qtcChain); + sz += ESTSIZE(cd.cfdTime, CTF::BLC_cfdTime); + sz += ESTSIZE(cd.qtcAmpl, CTF::BLC_qtcAmpl); + // clang-format on + + LOG(INFO) << "Estimated output size is " << sz << " bytes"; + return sz; +} diff --git a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h index c3e5bec7accd4..4b60fd86d1271 100644 --- a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h @@ -52,6 +52,7 @@ class CTFCoder : public o2::ctf::CTFCoderBase private: /// compres digits clusters to CompressedDigits void compress(CompressedDigits& cd, const gsl::span<const BCData>& digitVec, const gsl::span<const ChannelData>& channelVec); + size_t estimateCompressedSize(const CompressedDigits& cc); /// decompress CompressedDigits to digits template <typename VDIG, typename VCHAN> @@ -80,6 +81,11 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const BCData>& digitVec, const }; CompressedDigits cd; compress(cd, digitVec, channelVec); + + // book output size with some margin + auto szIni = estimateCompressedSize(cd); + buff.resize(szIni); + auto ec = CTF::create(buff); using ECB = CTF::base; diff --git a/Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx index b168b7c07dd19..c7b7a8d994ecf 100644 --- a/Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx +++ b/Detectors/FIT/FV0/reconstruction/src/CTFCoder.cxx @@ -128,3 +128,25 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: MAKECODER(cd.charge, CTF::BLC_charge); // clang-format on } + +///________________________________ +size_t CTFCoder::estimateCompressedSize(const CompressedDigits& cd) +{ + size_t sz = 0; + // clang-format off + // RS FIXME this is very crude estimate, instead, an empirical values should be used +#define VTP(vec) typename std::remove_reference<decltype(vec)>::type::value_type +#define ESTSIZE(vec, slot) mCoders[int(slot)] ? \ + rans::calculateMaxBufferSize(vec.size(), reinterpret_cast<const o2::rans::LiteralEncoder64<VTP(vec)>*>(mCoders[int(slot)].get())->getAlphabetRangeBits(), sizeof(VTP(vec)) ) : vec.size()*sizeof(VTP(vec)) + sz += ESTSIZE(cd.bcInc, CTF::BLC_bcInc); + sz += ESTSIZE(cd.orbitInc, CTF::BLC_orbitInc); + sz += ESTSIZE(cd.nChan, CTF::BLC_nChan); + + sz += ESTSIZE(cd.idChan, CTF::BLC_idChan); + sz += ESTSIZE(cd.time, CTF::BLC_time); + sz += ESTSIZE(cd.charge, CTF::BLC_charge); + // clang-format on + + LOG(INFO) << "Estimated output size is " << sz << " bytes"; + return sz; +} diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h index acbb25878a941..3934e84220578 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h @@ -51,6 +51,7 @@ class CTFCoder : public o2::ctf::CTFCoderBase private: /// compres compact clusters to CompressedClusters void compress(CompressedClusters& cc, const gsl::span<const ROFRecord>& rofRecVec, const gsl::span<const CompClusterExt>& cclusVec, const gsl::span<const unsigned char>& pattVec); + size_t estimateCompressedSize(const CompressedClusters& cc); /// decompress CompressedClusters to compact clusters template <typename VROF, typename VCLUS, typename VPAT> @@ -83,6 +84,10 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ROFRecord>& rofRecVec, co }; CompressedClusters cc; compress(cc, rofRecVec, cclusVec, pattVec); + // book output size with some margin + auto szIni = estimateCompressedSize(cc); + buff.resize(szIni); + auto ec = CTF::create(buff); using ECB = CTF::base; diff --git a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx index d1a722950cd90..c06dc9c60f555 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx @@ -159,3 +159,30 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: MAKECODER(cc.pattMap, CTF::BLCpattMap ); // clang-format on } + +///________________________________ +size_t CTFCoder::estimateCompressedSize(const CompressedClusters& cc) +{ + size_t sz = 0; + // clang-format off + // RS FIXME this is very crude estimate, instead, an empirical values should be used +#define VTP(vec) typename std::remove_reference<decltype(vec)>::type::value_type +#define ESTSIZE(vec, slot) mCoders[int(slot)] ? \ + rans::calculateMaxBufferSize(vec.size(), reinterpret_cast<const o2::rans::LiteralEncoder64<VTP(vec)>*>(mCoders[int(slot)].get())->getAlphabetRangeBits(), sizeof(VTP(vec)) ) : vec.size()*sizeof(VTP(vec)) + sz += ESTSIZE(cc.firstChipROF, CTF::BLCfirstChipROF); + sz += ESTSIZE(cc.bcIncROF, CTF::BLCbcIncROF ); + sz += ESTSIZE(cc.orbitIncROF, CTF::BLCorbitIncROF ); + sz += ESTSIZE(cc.nclusROF, CTF::BLCnclusROF ); + // + sz += ESTSIZE(cc.chipInc, CTF::BLCchipInc ); + sz += ESTSIZE(cc.chipMul, CTF::BLCchipMul ); + sz += ESTSIZE(cc.row, CTF::BLCrow ); + sz += ESTSIZE(cc.colInc, CTF::BLCcolInc ); + sz += ESTSIZE(cc.pattID, CTF::BLCpattID ); + sz += ESTSIZE(cc.pattMap, CTF::BLCpattMap ); + + // clang-format on + + LOG(INFO) << "Estimated output size is " << sz << " bytes"; + return sz; +} diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index ff9e28032df20..6d393a065f31e 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -50,7 +50,7 @@ class CTFCoder : public o2::ctf::CTFCoderBase private: /// compres compact clusters to CompressedInfos void compress(CompressedInfos& cc, const gsl::span<const ReadoutWindowData>& rofRecVec, const gsl::span<const Digit>& cdigVec, const gsl::span<const uint32_t>& pattVec); - + size_t estimateCompressedSize(const CompressedInfos& cc); /// decompress CompressedInfos to compact clusters template <typename VROF, typename VDIG, typename VPAT> void decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdigVec, VPAT& pattVec); @@ -83,6 +83,10 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRe }; CompressedInfos cc; compress(cc, rofRecVec, cdigVec, pattVec); + // book output size with some margin + auto szIni = estimateCompressedSize(cc); + buff.resize(szIni); + auto ec = CTF::create(buff); using ECB = CTF::base; diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index 26eb4473e706a..507e923122375 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -185,3 +185,29 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: MAKECODER(cc.pattMap, CTF::BLCpattMap); // clang-format on } + +///________________________________ +size_t CTFCoder::estimateCompressedSize(const CompressedInfos& cc) +{ + size_t sz = 0; + // clang-format off + // RS FIXME this is very crude estimate, instead, an empirical values should be used +#define VTP(vec) typename std::remove_reference<decltype(vec)>::type::value_type +#define ESTSIZE(vec, slot) mCoders[int(slot)] ? \ + rans::calculateMaxBufferSize(vec.size(), reinterpret_cast<const o2::rans::LiteralEncoder64<VTP(vec)>*>(mCoders[int(slot)].get())->getAlphabetRangeBits(), sizeof(VTP(vec)) ) : vec.size()*sizeof(VTP(vec)) + + sz += ESTSIZE(cc.bcIncROF, CTF::BLCbcIncROF); + sz += ESTSIZE(cc.orbitIncROF, CTF::BLCorbitIncROF); + sz += ESTSIZE(cc.ndigROF, CTF::BLCndigROF); + sz += ESTSIZE(cc.ndiaROF, CTF::BLCndiaROF); + sz += ESTSIZE(cc.timeFrameInc, CTF::BLCtimeFrameInc); + sz += ESTSIZE(cc.timeTDCInc, CTF::BLCtimeTDCInc); + sz += ESTSIZE(cc.stripID, CTF::BLCstripID); + sz += ESTSIZE(cc.chanInStrip, CTF::BLCchanInStrip); + sz += ESTSIZE(cc.tot, CTF::BLCtot); + sz += ESTSIZE(cc.pattMap, CTF::BLCpattMap); + // clang-format on + + LOG(INFO) << "Estimated output size is " << sz << " bytes"; + return sz; +} diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h index 5c8dcad4f57b9..c6bbe1c134fe6 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h @@ -45,6 +45,7 @@ class CTFCoder : public o2::ctf::CTFCoderBase void decode(const CTF::base& ec, VEC& buff); void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); + size_t estimateCompressedSize(const CompressedClusters& ccl); static size_t constexpr Alignment = 16; static size_t estimateSize(CompressedClusters& c); @@ -103,6 +104,10 @@ void CTFCoder::encode(VEC& buff, const CompressedClusters& ccl) MD::EENCODE //nSliceRowClusters }; + // book output size with some margin + auto szIni = estimateCompressedSize(ccl); + buff.resize(szIni); + auto ec = CTF::create(buff); ec->setHeader(reinterpret_cast<const CompressedClustersCounters&>(ccl)); ec->getANSHeader().majorVersion = 0; diff --git a/Detectors/TPC/reconstruction/src/CTFCoder.cxx b/Detectors/TPC/reconstruction/src/CTFCoder.cxx index 81c4e6206ebc3..174544009faf8 100644 --- a/Detectors/TPC/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TPC/reconstruction/src/CTFCoder.cxx @@ -139,3 +139,41 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: MAKECODER(cc.nSliceRowClusters, CTF::BLCnSliceRowClusters); // clang-format on } + +///________________________________ +size_t CTFCoder::estimateCompressedSize(const CompressedClusters& ccl) +{ + size_t sz = 0; + // clang-format off + // RS FIXME this is very crude estimate, instead, an empirical values should be used +#define ESTSIZE(slot, ptr, n) mCoders[int(slot)] ? \ + rans::calculateMaxBufferSize(n, reinterpret_cast<const o2::rans::LiteralEncoder64<std::remove_pointer<decltype(ptr)>::type>*>(mCoders[int(slot)].get())->getAlphabetRangeBits(), \ + sizeof(std::remove_pointer<decltype(ptr)>::type)) : n*sizeof(std::remove_pointer<decltype(ptr)>) + sz += ESTSIZE(CTF::BLCqTotA, ccl.qTotA, ccl.nAttachedClusters); + sz += ESTSIZE(CTF::BLCqMaxA, ccl.qMaxA, ccl.nAttachedClusters); + sz += ESTSIZE(CTF::BLCflagsA, ccl.flagsA, ccl.nAttachedClusters); + sz += ESTSIZE(CTF::BLCrowDiffA, ccl.rowDiffA, ccl.nAttachedClustersReduced); + sz += ESTSIZE(CTF::BLCsliceLegDiffA, ccl.sliceLegDiffA, ccl.nAttachedClustersReduced); + sz += ESTSIZE(CTF::BLCpadResA, ccl.padResA, ccl.nAttachedClustersReduced); + sz += ESTSIZE(CTF::BLCtimeResA, ccl.timeResA, ccl.nAttachedClustersReduced); + sz += ESTSIZE(CTF::BLCsigmaPadA, ccl.sigmaPadA, ccl.nAttachedClusters); + sz += ESTSIZE(CTF::BLCsigmaTimeA, ccl.sigmaTimeA, ccl.nAttachedClusters); + sz += ESTSIZE(CTF::BLCqPtA, ccl.qPtA, ccl.nTracks); + sz += ESTSIZE(CTF::BLCrowA, ccl.rowA, ccl.nTracks); + sz += ESTSIZE(CTF::BLCsliceA, ccl.sliceA, ccl.nTracks); + sz += ESTSIZE(CTF::BLCtimeA, ccl.timeA, ccl.nTracks); + sz += ESTSIZE(CTF::BLCpadA, ccl.padA, ccl.nTracks); + sz += ESTSIZE(CTF::BLCqTotU, ccl.qTotU, ccl.nUnattachedClusters); + sz += ESTSIZE(CTF::BLCqMaxU, ccl.qMaxU, ccl.nUnattachedClusters); + sz += ESTSIZE(CTF::BLCflagsU, ccl.flagsU, ccl.nUnattachedClusters); + sz += ESTSIZE(CTF::BLCpadDiffU, ccl.padDiffU, ccl.nUnattachedClusters); + sz += ESTSIZE(CTF::BLCtimeDiffU, ccl.timeDiffU, ccl.nUnattachedClusters); + sz += ESTSIZE(CTF::BLCsigmaPadU, ccl.sigmaPadU, ccl.nUnattachedClusters); + sz += ESTSIZE(CTF::BLCsigmaTimeU, ccl.sigmaTimeU, ccl.nUnattachedClusters); + sz += ESTSIZE(CTF::BLCnTrackClusters, ccl.nTrackClusters, ccl.nTracks); + sz += ESTSIZE(CTF::BLCnSliceRowClusters, ccl.nSliceRowClusters, ccl.nSliceRows); + // clang-format on + + LOG(INFO) << "Estimated output size is " << sz << " bytes"; + return sz; +} From da63125ecd25e8c0cdaf89f7bdf2d277878eec4e Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Fri, 21 Aug 2020 13:26:05 +0200 Subject: [PATCH 0404/1751] [EMCAL-610, EMCAL-659, EMCAL-661] EMCAL digit to raw converter stand alone application (#4045) * [EMCAL-610, EMCAL-659] Output raw stream based on RawFileWriter - Replace usage of RawOutputPageHandler with RawFileWriter for output streaming - Initialize RawFileWriter using a single output file and a linear link assignment for C-RORC/Link ID untill final link assignment on production FLPs is fixed - Convert input handing from std::vectors to gsl::span * [EMCAL-610, EMCAL-661] Add stand-alone application for digits to raw conversion Stand alone application reading digits file and processing digits to raw conversion for each timeframe entry in the digits tree. Open points: - First IR need to be specified for methods in RawFileWriter - Raw writer settings to come from the CCDB * [EMCAL-610] Use carryOverMethod in order to append RCU trailer to each raw page CarryOverMethod cuts the payload in size - size of the RCU trailer and adds the RCU trailer from the last page, in which the payload size is adapted to the size in the page. * [EMCAL-610] Add option to split to multiple files - Add option to split to file per full detector, subdector or crorc+link - Change rawfile to output location in order to support multiple raw files - Add parising of the configuration file in order to configure tf handling - Add writing of the output config - Remove obsolete classes * [EMCAL-610] Adapt carryOverMethod in order to adapt payload size of the last RCU trailer Specify also using carryOverMethod for the last page --- Detectors/EMCAL/simulation/CMakeLists.txt | 8 +- .../include/EMCALSimulation/DMAOutputStream.h | 126 -------------- .../EMCALSimulation/RawOutputPageHandler.h | 162 ------------------ .../include/EMCALSimulation/RawWriter.h | 52 ++++-- .../EMCAL/simulation/src/DMAOutputStream.cxx | 91 ---------- .../simulation/src/EMCALSimulationLinkDef.h | 2 - Detectors/EMCAL/simulation/src/RawCreator.cxx | 102 +++++++++++ .../simulation/src/RawOutputPageHandler.cxx | 83 --------- Detectors/EMCAL/simulation/src/RawWriter.cxx | 116 +++++++++++-- 9 files changed, 240 insertions(+), 502 deletions(-) delete mode 100644 Detectors/EMCAL/simulation/include/EMCALSimulation/DMAOutputStream.h delete mode 100644 Detectors/EMCAL/simulation/include/EMCALSimulation/RawOutputPageHandler.h delete mode 100644 Detectors/EMCAL/simulation/src/DMAOutputStream.cxx create mode 100644 Detectors/EMCAL/simulation/src/RawCreator.cxx delete mode 100644 Detectors/EMCAL/simulation/src/RawOutputPageHandler.cxx diff --git a/Detectors/EMCAL/simulation/CMakeLists.txt b/Detectors/EMCAL/simulation/CMakeLists.txt index db2953b1a0f8b..6149eeda5bda5 100644 --- a/Detectors/EMCAL/simulation/CMakeLists.txt +++ b/Detectors/EMCAL/simulation/CMakeLists.txt @@ -11,7 +11,7 @@ o2_add_library(EMCALSimulation SOURCES src/Detector.cxx src/Digitizer.cxx src/DigitizerTask.cxx src/SpaceFrame.cxx src/SimParam.cxx src/LabeledDigit.cxx - src/RawWriter.cxx src/DMAOutputStream.cxx src/RawOutputPageHandler.cxx + src/RawWriter.cxx PUBLIC_LINK_LIBRARIES O2::EMCALBase O2::DetectorsBase O2::SimConfig O2::SimulationDataFormat O2::Headers O2::DetectorsRaw) o2_target_root_dictionary(EMCALSimulation @@ -19,9 +19,13 @@ o2_target_root_dictionary(EMCALSimulation include/EMCALSimulation/Digitizer.h include/EMCALSimulation/DigitizerTask.h include/EMCALSimulation/RawWriter.h - include/EMCALSimulation/DMAOutputStream.h include/EMCALSimulation/SpaceFrame.h include/EMCALSimulation/SimParam.h include/EMCALSimulation/LabeledDigit.h) +o2_add_executable(rawcreator + COMPONENT_NAME emcal + PUBLIC_LINK_LIBRARIES O2::EMCALSimulation + SOURCES src/RawCreator.cxx) + o2_data_file(COPY data DESTINATION Detectors/EMC/simulation) diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/DMAOutputStream.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/DMAOutputStream.h deleted file mode 100644 index 8bbc036732338..0000000000000 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/DMAOutputStream.h +++ /dev/null @@ -1,126 +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. -#ifndef ALICEO2_EMCAL_DMAOUTPUTSTREAM_H -#define ALICEO2_EMCAL_DMAOUTPUTSTREAM_H - -#include <exception> -#include <fstream> -#include <string> - -#include <gsl/span> - -#include "Rtypes.h" -#include "RStringView.h" - -#include "Headers/RAWDataHeader.h" - -namespace o2 -{ - -namespace emcal -{ - -/// \class DMAOutputStream -/// \brief Output stream of a payload to DMA raw files -/// \ingroup EMCALsimulation -/// \author Markus Fasel <markus.fasel@cern.ch>, Oak Ridge National Laboratory -/// \since Nov 6, 2019 -/// -/// Stream of output payload with variable size to DMA pages in -/// a binary raw file. The output payload can be larger than the -/// size of a DMA page (default: 8 kB) the output is split into -/// multiple pages. Page counter, memory size, page size and -/// stop bit are handled internally and are overwritten in the -/// raw data header provided. All other header information must be -/// handled externally. -class DMAOutputStream -{ - public: - using RawHeader = o2::header::RAWDataHeaderV4; - - class OutputFileException : public std::exception - { - public: - OutputFileException() = default; - OutputFileException(const std::string_view filename) : std::exception(), mFilePath(filename), mMessage("Path \"" + mFilePath + "\" invalid") {} - ~OutputFileException() noexcept final = default; - - const char* what() const noexcept final - { - return mMessage.data(); - } - - private: - std::string mFilePath = ""; - std::string mMessage = ""; - }; - - /// \brief Constructor - DMAOutputStream() = default; - - /// \brief Constructor - /// \param filename Name of the output file - DMAOutputStream(const char* filename); - - /// \brief Destructor - /// - /// Closing file I/O - ~DMAOutputStream(); - - /// \brief Open the output stream - /// \throw OutputFileException - /// - /// Opening output file I/O - void open(); - - /// \brief Set the name of the output file - /// \param filename Name of the output file - void setOutputFilename(const char* filename) { mFilename = filename; } - - /// \brief Write output payload to the output stream - /// \param header Raw data header - /// \param buffer Raw data payload - /// \return Current page count - /// - /// Converting output payload to DMA papges. If the payload is larger than - /// the pagesize - header size the payload is automatically split to multiple - /// pages. Page counter, memory size, page size and stop bit of the header are - /// handled internally and are overwritten from the header provided. All other - /// header information must be provided externally. - int writeData(RawHeader header, gsl::span<const char> buffer); - - /// \brief Write single raw data header - /// \param header raw data header - /// - /// Write header with no payload assinged. Function is used for writing - /// open/close header of the timeframe - void writeSingleHeader(const RawHeader& header); - - protected: - /// \brief Write DMA page - /// \param header Raw data header for page - /// \param payload Page payload (includes size of teh payload) - /// \param pagesize Size of the DMA page (not size of the payload) - /// - /// Expects that the size of the payload is smaller than the size ot the DMA - /// page. Parameter pagesize supporting variable page size. - void writeDMAPage(const RawHeader& header, gsl::span<const char> payload, int pagesize); - - private: - std::string mFilename = ""; ///< Name of the output file - std::ofstream mOutputFile; ///< Handler for output raw file - bool mInitialized = false; ///< Switch for whether the output stream is initialized - - ClassDefNV(DMAOutputStream, 1); -}; -} // namespace emcal -} // namespace o2 - -#endif \ No newline at end of file diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawOutputPageHandler.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawOutputPageHandler.h deleted file mode 100644 index 7417bfec6380e..0000000000000 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawOutputPageHandler.h +++ /dev/null @@ -1,162 +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. - -#include <exception> -#include <map> -#include <string> -#include <vector> -#include <CommonDataFormat/InteractionRecord.h> -#include <EMCALSimulation/DMAOutputStream.h> - -namespace o2 -{ -namespace emcal -{ - -/// \class RawOutputPageHandler -/// \brief Handler for EMCAL raw page buffering, timeframe building and output streaming -/// \ingroup EMCALsimulation -/// \author Markus Fasel <markus.fasel@cern.ch>, Oak Ridge National Laboratory -/// \since March 22, 2020 -/// -/// # General -/// The raw format for EMCAL consists of separate superpages of timeframes arranged per -/// (DDL) link. Each timeframe consists of -/// - Empty RDH without payload indicating start of timeframe. Counters are reset -/// - Pages with RDH and payload for each trigger BC within the timeframe -/// - Empty RDH without payload indicating end of timeframe. Contains the number of pages -/// in the timeframe, the stop bit and the timeframe trigger. -/// At the start of data an empty timeframe (without pages) consisting only of star and stop -/// RDH will mark the beginning of the data stream. -/// -/// # Usage -/// For each new trigger the function initTrigger is to be called with the InteractionRecord -/// of the bunch crossing corresponding to the trigger. Pages created by the raw writer and added -/// via addPageForLink are buffered per link. The HBFUtils, provided from outside, decide on whether -/// a new timeframe is triggered. In case of a new timeframe raw timeframes are created for all -/// links with pages, containing all pages of a link and streamed to file (in initTrigger). In case -/// the buffer still contains pages when the destructor is called, the pages are streamed as remaining -/// pages of the last timeframe (in the destructor). -class RawOutputPageHandler -{ - public: - using RawHeader = o2::header::RAWDataHeaderV4; - - /// \class LinkIDException - /// \brief Exception handling invalid link IDs (outside the range of EMCAL links) - class LinkIDException : public std::exception - { - public: - /// \brief Constructor, defining - LinkIDException(int linkID); - - /// \brief Destructor - ~LinkIDException() noexcept final = default; - - /// \brief Access to error message of the exception - /// \return Error message of the exception - const char* what() const noexcept final { return mMessage.data(); } - - /// \brief Access to Link ID raising the exception - /// \return Link ID raising the exception - int getLinkID() const { return mLinkID; } - - private: - int mLinkID; ///< ID of the link raising the exception - std::string mMessage; ///< Error message; - }; - - /// \class RawPageBuffer - /// \brief Buffer for raw pages - /// - /// Internal helper class for buffering raw pages within a timeframe for a certain link. - /// The functionality consists of: - /// - add page: adding new page to the raw buffer - /// - getPages: access to all pages. Mainly used when building the timeframe - /// - flush: clear buffer (after timeframe building) - class RawPageBuffer - { - public: - /// \struct PageData - /// \brief Structure for a raw page (header and payload words) - struct PageData { - RawHeader mHeader; ///< Header template of the page, containing link ID, fee ID and trigger - std::vector<char> mPage; ///< Payload page - }; - - /// \brief Constructor - RawPageBuffer() = default; - - /// \brief Destructor - ~RawPageBuffer() = default; - - /// \brief Adding new raw page to the page buffer - /// \brief header Template raw header, containing link/fee ID and trigger - /// \brief page Raw page (as char words) to be added to the buffer - void addPage(const RawHeader& header, const std::vector<char>& page) { mPages.push_back({header, page}); } - - /// \brief Cleaning page buffer - void flush() { mPages.clear(); } - - /// \brief Access to pages in the buffer - /// \return vector with all pages in the buffer - const std::vector<PageData>& getPages() const { return mPages; } - - private: - std::vector<PageData> mPages; ///< Buffer for pages - }; - - /// \brief Constructor, initializing page handler with output filename and HBF utils - /// \param rawfilename Name of the output file - RawOutputPageHandler(const char* rawfilename); - - /// \brief Destructor - /// - /// In case buffers contain payload the page is streamed as last - /// timeframe for the links containing payload pages. - ~RawOutputPageHandler(); - - /// \brief Initialize new trigger - /// \param currentIR Interaction record of the collision triggering - /// - /// Initialize new trigger. In case the Timeframe changes with the trigger - /// the buffers belonging to the previous buffer are streamed to file. For - /// each link a separate timeframe is created, starting with empty open/close - /// raw data header. Timeframes are only created for links which buffer pages. - void initTrigger(const o2::InteractionRecord& currentIR); - - /// \brief Add new page for link to the page buffer - /// \param linkID ID of the link - /// \param header Template raw header of the page - /// \param dmapage Payload page - /// \throw LinkIDException in case link ID is invalid - void addPageForLink(int linkID, const RawHeader& header, const std::vector<char>& dmapage); - - private: - /// \brief Write timeframe for an entire link - /// \param linkID ID of the link - /// \param pagebuffer Buffer with raw pages in timeframe belonging to the link - /// - /// Timeframes for raw data in EMCAL contain: - /// - Empty RDH, indicating start of timeframe. No payload assigned. Counters 0 - /// - Raw page for every trigger in the timeframe: Each raw page starts with a - /// RDH. In case the payload exceeds the 8 kB page it is split into multiple - /// pages. The page counter is calculated with respect to the first header in a - /// timeframe - /// - Empty RDH, closing the timeframe, containing the number of pages in the - /// timeframe - void writeTimeframe(int linkID, const RawPageBuffer& pagebuffer); - - int mCurrentTimeframe = -1; ///< Current timeframe ID (needed to detect whether a new timeframe starts) - std::map<int, RawPageBuffer> mRawPages; ///< Buffer with raw pages for all links - DMAOutputStream mOutputStream; ///< File output stream -}; -} // namespace emcal -} // namespace o2 \ No newline at end of file diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h index dd6427c56ea38..a9e1c2632ef2f 100644 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h +++ b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h @@ -11,6 +11,8 @@ #ifndef ALICEO2_EMCAL_RAWWRITER_H #define ALICEO2_EMCAL_RAWWRITER_H +#include <gsl/span> + #include <array> #include <fstream> #include <memory> @@ -20,9 +22,8 @@ #include "Rtypes.h" +#include "DetectorsRaw/RawFileWriter.h" #include "EMCALBase/Mapper.h" -#include "EMCALSimulation/DMAOutputStream.h" -#include "EMCALSimulation/RawOutputPageHandler.h" #include "DataFormatsEMCAL/Digit.h" #include "DataFormatsEMCAL/TriggerRecord.h" @@ -74,42 +75,57 @@ union CaloBunchWord { class RawWriter { public: + enum class FileFor_t { + kFullDet, + kSubDet, + kLink + }; RawWriter() = default; - RawWriter(const char* rawfilename) { setRawFileName(rawfilename); } + RawWriter(const char* outputdir) { setOutputLocation(outputdir); } ~RawWriter() = default; - void setRawFileName(const char* filename) { mRawFilename = filename; } - void setDigits(std::vector<o2::emcal::Digit>* digits) { mDigits = digits; } - void setTriggerRecords(std::vector<o2::emcal::TriggerRecord>* triggers); + o2::raw::RawFileWriter& getWriter() const { return *mRawWriter; } + + void setOutputLocation(const char* outputdir) { mOutputLocation = outputdir; } + void setDigits(gsl::span<o2::emcal::Digit> digits) { mDigits = digits; } + void setFileFor(FileFor_t filefor) { mFileFor = filefor; } + void setTriggerRecords(gsl::span<o2::emcal::TriggerRecord> 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(); } + bool hasNextTrigger() const { return mCurrentTrigger != mTriggers.end(); } void init(); void process(); - void processNextTrigger(); + void digitsToRaw(gsl::span<o2::emcal::Digit> digits, gsl::span<o2::emcal::TriggerRecord> triggers); + bool processNextTrigger(); + + int carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data, + const char* ptr, int maxSize, int splitID, + std::vector<char>& trailer, std::vector<char>& header) const; protected: std::vector<AltroBunch> findBunches(const std::vector<o2::emcal::Digit*>& channelDigits); std::tuple<int, int, int> getOnlineID(int towerID); + std::tuple<int, int> getLinkAssignment(int ddlID); ChannelHeader createChannelHeader(int hardwareAddress, int payloadSize, bool isBadChannel); std::vector<char> createRCUTrailer(int payloadsize, int feca, int fecb, double timesample, double l1phase); std::vector<int> encodeBunchData(const std::vector<int>& data); private: - int mNADCSamples = 15; ///< Number of time samples - int mPedestal = 0; ///< Pedestal - o2::emcal::Geometry* mGeometry = nullptr; ///< EMCAL geometry - std::string mRawFilename; ///< Rawfile name - std::array<o2::emcal::Mapper, 4> mMappers; ///< EMCAL mappers - std::vector<o2::emcal::Digit>* mDigits; ///< Digits input vector - must be in digitized format including the time response - std::vector<o2::emcal::TriggerRecord>* mTriggers; ///< Trigger records, separating the data from different triggers - std::vector<SRUDigitContainer> mSRUdata; ///< Internal helper of digits assigned to SRUs - std::vector<o2::emcal::TriggerRecord>::iterator mCurrentTrigger; ///< Current trigger in the trigger records - std::unique_ptr<RawOutputPageHandler> mPageHandler; ///< Output page handler + 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::array<o2::emcal::Mapper, 4> mMappers; ///< EMCAL mappers + gsl::span<o2::emcal::Digit> mDigits; ///< Digits input vector - must be in digitized format including the time response + gsl::span<o2::emcal::TriggerRecord> mTriggers; ///< Trigger records, separating the data from different triggers + std::vector<SRUDigitContainer> mSRUdata; ///< Internal helper of digits assigned to SRUs + gsl::span<o2::emcal::TriggerRecord>::iterator mCurrentTrigger; ///< Current trigger in the trigger records + std::unique_ptr<o2::raw::RawFileWriter> mRawWriter; ///< Raw writer ClassDefNV(RawWriter, 1); }; diff --git a/Detectors/EMCAL/simulation/src/DMAOutputStream.cxx b/Detectors/EMCAL/simulation/src/DMAOutputStream.cxx deleted file mode 100644 index 6211b0a9f6755..0000000000000 --- a/Detectors/EMCAL/simulation/src/DMAOutputStream.cxx +++ /dev/null @@ -1,91 +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. - -#include "EMCALSimulation/DMAOutputStream.h" - -using namespace o2::emcal; - -DMAOutputStream::DMAOutputStream(const char* filename) : mFilename(filename) {} - -DMAOutputStream::~DMAOutputStream() -{ - if (mOutputFile.is_open()) - mOutputFile.close(); -} - -void DMAOutputStream::open() -{ - if (!mOutputFile.is_open()) { - if (!mFilename.length()) - throw OutputFileException(mFilename); - mOutputFile.open(mFilename, std::ios::out | std::ios::binary); - mInitialized = true; - } -} - -void DMAOutputStream::writeSingleHeader(const RawHeader& header) -{ - if (!mInitialized) - open(); - std::vector<char> outputpage(sizeof(RawHeader)); - RawHeader* outputheader = reinterpret_cast<RawHeader*>(outputpage.data()); - *outputheader = header; - outputheader->memorySize = sizeof(RawHeader); - outputheader->offsetToNext = sizeof(RawHeader); - mOutputFile.write(outputpage.data(), outputpage.size()); -} - -int DMAOutputStream::writeData(RawHeader header, gsl::span<const char> buffer) -{ - if (!mInitialized) - open(); - - constexpr int PAGESIZE = 8192; - // Handling of the termination word (0x001d3082): The termination word is added to the payload - // but not included in the payload size (as done in the hardware). Therefore it has to be subtracted - // from the maximum possible payload size - constexpr int MAXNWORDS = PAGESIZE - sizeof(header) - sizeof(uint32_t); - bool writeNext = true; - int pagecounter = header.pageCnt, currentindex = 0; - while (writeNext) { - int sizeRemain = buffer.size() - currentindex; - int nwordspage = MAXNWORDS; - if (sizeRemain < MAXNWORDS) { - // Last page - nwordspage = sizeRemain; - writeNext = false; - } - header.pageCnt = pagecounter; - header.memorySize = nwordspage + sizeof(RawHeader); - header.offsetToNext = 8192; - - writeDMAPage(header, gsl::span(buffer.data() + currentindex, nwordspage), PAGESIZE); - - if (writeNext) { - currentindex += nwordspage; - } - pagecounter++; - } - return pagecounter; -} - -void DMAOutputStream::writeDMAPage(const RawHeader& header, gsl::span<const char> payload, int pagesize) -{ - std::vector<char> dmapage(pagesize); - RawHeader* outheader = reinterpret_cast<RawHeader*>(dmapage.data()); - *outheader = header; - char* outpayload = dmapage.data() + sizeof(header); - memcpy(outpayload, payload.data(), payload.size()); - // Write termination character - uint32_t terminationCharacter = 0x001d3082; - char* terminationString = reinterpret_cast<char*>(&terminationCharacter); - memcpy(outpayload + payload.size(), terminationString, sizeof(uint32_t)); - mOutputFile.write(dmapage.data(), dmapage.size()); -} \ No newline at end of file diff --git a/Detectors/EMCAL/simulation/src/EMCALSimulationLinkDef.h b/Detectors/EMCAL/simulation/src/EMCALSimulationLinkDef.h index 21d1a42246d59..461faa35bf6c0 100644 --- a/Detectors/EMCAL/simulation/src/EMCALSimulationLinkDef.h +++ b/Detectors/EMCAL/simulation/src/EMCALSimulationLinkDef.h @@ -18,11 +18,9 @@ #pragma link C++ class o2::base::DetImpl < o2::emcal::Detector> + ; #pragma link C++ class o2::emcal::Digitizer + ; #pragma link C++ class o2::emcal::DigitizerTask + ; -#pragma link C++ class o2::emcal::DMAOutputStream + ; #pragma link C++ class o2::emcal::SimParam + ; #pragma link C++ class o2::emcal::LabeledDigit + ; #pragma link C++ class o2::emcal::RawWriter + ; -#pragma link C++ class o2::emcal::DMAOutputStream + ; #pragma link C++ class std::list < o2::emcal::LabeledDigit > +; diff --git a/Detectors/EMCAL/simulation/src/RawCreator.cxx b/Detectors/EMCAL/simulation/src/RawCreator.cxx new file mode 100644 index 0000000000000..149f0f624281f --- /dev/null +++ b/Detectors/EMCAL/simulation/src/RawCreator.cxx @@ -0,0 +1,102 @@ +// 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 <memory> +#include <string> +#include <vector> + +#include <boost/program_options.hpp> + +#include <TFile.h> +#include <TTree.h> +#include <TTreeReader.h> + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/StringUtils.h" +#include "DataFormatsEMCAL/Digit.h" +#include "DataFormatsEMCAL/TriggerRecord.h" +#include "EMCALBase/Geometry.h" +#include "EMCALSimulation/RawWriter.h" + +namespace bpo = boost::program_options; + +int main(int argc, const char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + " <cmds/options>\n" + " Tool will encode emcal raw data from input file\n" + "Commands / Options"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + add_option("verbose,v", bpo::value<uint32_t>()->default_value(0), "Select verbosity level [0 = no output]"); + add_option("input-file,i", bpo::value<std::string>()->required(), "Specifies digit input file."); + add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,subdet,link"); + add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); + add_option("debug,d", bpo::value<uint32_t>()->default_value(0), "Select debug output level [0 = no debug output]"); + add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help") || argc == 1) { + std::cout << opt_general << std::endl; + exit(0); + } + + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + + o2::conf::ConfigurableParam::updateFromString(vm["configKeyValues"].as<std::string>()); + + auto digitfilename = vm["input-file"].as<std::string>(), + outputdir = vm["output-dir"].as<std::string>(), + filefor = vm["file-for"].as<std::string>(); + + std::unique_ptr<TFile> digitfile(TFile::Open(digitfilename.data(), "READ")); + auto treereader = std::make_unique<TTreeReader>(static_cast<TTree*>(digitfile->Get("o2sim"))); + TTreeReaderValue<std::vector<o2::emcal::Digit>> digitbranch(*treereader, "EMCALDigit"); + TTreeReaderValue<std::vector<o2::emcal::TriggerRecord>> triggerbranch(*treereader, "EMCALDigitTRGR"); + + o2::emcal::RawWriter::FileFor_t granularity = o2::emcal::RawWriter::FileFor_t::kFullDet; + if (filefor == "all") { + granularity = o2::emcal::RawWriter::FileFor_t::kFullDet; + } else if (filefor == "subdet") { + granularity = o2::emcal::RawWriter::FileFor_t::kSubDet; + } else if (filefor == "link") { + granularity = o2::emcal::RawWriter::FileFor_t::kLink; + } + + o2::emcal::RawWriter rawwriter; + rawwriter.setOutputLocation(outputdir.data()); + rawwriter.setFileFor(granularity); + rawwriter.setGeometry(o2::emcal::Geometry::GetInstanceFromRunNumber(300000)); + rawwriter.setNumberOfADCSamples(15); // @TODO Needs to come from CCDB + rawwriter.setPedestal(0); // @TODO Needs to come from CCDB + rawwriter.init(); + + // Loop over all entries in the tree, where each tree entry corresponds to a time frame + for (auto en : *treereader) { + rawwriter.digitsToRaw(*digitbranch, *triggerbranch); + } + rawwriter.getWriter().writeConfFile("EMC", "RAWDATA", o2::utils::concat_string(outputdir, "raw.cfg")); +} \ No newline at end of file diff --git a/Detectors/EMCAL/simulation/src/RawOutputPageHandler.cxx b/Detectors/EMCAL/simulation/src/RawOutputPageHandler.cxx deleted file mode 100644 index 87019c239a00d..0000000000000 --- a/Detectors/EMCAL/simulation/src/RawOutputPageHandler.cxx +++ /dev/null @@ -1,83 +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. - -#include <fmt/format.h> -#include <Headers/RAWDataHeader.h> -#include <DetectorsRaw/HBFUtils.h> -#include <EMCALSimulation/RawOutputPageHandler.h> - -using namespace o2::emcal; - -RawOutputPageHandler::RawOutputPageHandler(const char* rawfilename) : mOutputStream(rawfilename), mCurrentTimeframe(-1) -{ - // create page buffers for all (40) links - for (int ilink = 0; ilink < 40; ilink++) - mRawPages[ilink] = RawPageBuffer(); - mOutputStream.open(); -} - -RawOutputPageHandler::~RawOutputPageHandler() -{ - // write pages for last timeframe to file - for (const auto& [linkID, pagebuffer] : mRawPages) { - // only write pages for links which send data - if (pagebuffer.getPages().size()) - writeTimeframe(linkID, pagebuffer); - } -} - -void RawOutputPageHandler::initTrigger(const o2::InteractionRecord& irtrigger) -{ - auto currenttimeframe = raw::HBFUtils::Instance().getTF(irtrigger); - if (currenttimeframe != mCurrentTimeframe) { - // write pages to file - for (auto& [linkID, pagebuffer] : mRawPages) { - // only write pages for links which send data - if (pagebuffer.getPages().size()) - writeTimeframe(linkID, pagebuffer); - pagebuffer.flush(); - } - // set the new timeframe - mCurrentTimeframe = currenttimeframe; - } -} - -void RawOutputPageHandler::writeTimeframe(int linkID, const RawPageBuffer& pagebuffer) -{ - // write pages to file - // Write timeframe open - RawHeader timeframeheader; - timeframeheader.linkID = linkID; - mOutputStream.writeSingleHeader(timeframeheader); - int pagecounter = 1; - for (const auto& page : pagebuffer.getPages()) { - auto header = page.mHeader; - header.pageCnt = pagecounter; - pagecounter = mOutputStream.writeData(header, gsl::span<const char>(page.mPage.data(), page.mPage.size())); - } - - // end of timeframe - timeframeheader.pageCnt = pagecounter; - timeframeheader.stop = 1; - timeframeheader.triggerType = o2::trigger::TF; - mOutputStream.writeSingleHeader(timeframeheader); -} - -void RawOutputPageHandler::addPageForLink(int linkID, const RawHeader& header, const std::vector<char>& page) -{ - if (linkID > 40) - throw LinkIDException(linkID); - mRawPages[linkID].addPage(header, page); -} - -RawOutputPageHandler::LinkIDException::LinkIDException(int linkID) : std::exception(), mLinkID(linkID), mMessage() -{ - mMessage = fmt::format("Link ID invalid: %d (max 40)", linkID); -} \ No newline at end of file diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index 013cbdc7fad5d..733953048a33b 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -8,25 +8,53 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include <fmt/core.h> #include <gsl/span> #include <TSystem.h> #include "DataFormatsEMCAL/Constants.h" #include "EMCALBase/Geometry.h" #include "EMCALBase/RCUTrailer.h" #include "EMCALSimulation/RawWriter.h" -#include "Headers/RAWDataHeader.h" using namespace o2::emcal; -void RawWriter::setTriggerRecords(std::vector<o2::emcal::TriggerRecord>* triggers) +void RawWriter::setTriggerRecords(gsl::span<o2::emcal::TriggerRecord> triggers) { mTriggers = triggers; - mCurrentTrigger = triggers->begin(); + mCurrentTrigger = triggers.begin(); } void RawWriter::init() { - mPageHandler = std::make_unique<RawOutputPageHandler>(mRawFilename.data()); + mRawWriter = std::make_unique<o2::raw::RawFileWriter>(o2::header::gDataOriginEMC, false); + mRawWriter->setCarryOverCallBack(this); + mRawWriter->setApplyCarryOverToLastPage(true); + for (auto iddl = 0; iddl < 40; iddl++) { + // For EMCAL set + // - FEE ID = DDL ID + // - C-RORC and link increasing with DDL ID + // @TODO replace with link assignment on production FLPs, + // eventually storing in CCDB + auto [crorc, link] = getLinkAssignment(iddl); + std::string rawfilename = mOutputLocation; + switch (mFileFor) { + case FileFor_t::kFullDet: + rawfilename += "/emcal.root"; + break; + case FileFor_t::kSubDet: { + std::string detstring; + if (iddl < 22) + detstring = "emcal"; + else + detstring = "dcal"; + rawfilename += fmt::format("/%s", detstring.data()); + break; + }; + case FileFor_t::kLink: + rawfilename += fmt::format("/emcal_%d_%d.root", crorc, link); + } + mRawWriter->registerLink(iddl, crorc, link, 0, rawfilename.data()); + } // initialize mappers std::array<char, 4> sides = {{'A', 'C'}}; for (auto iside = 0; iside < sides.size(); iside++) { @@ -43,15 +71,28 @@ void RawWriter::init() } } -void RawWriter::processNextTrigger() +void RawWriter::process() +{ + while (processNextTrigger()) + ; +} + +void RawWriter::digitsToRaw(gsl::span<o2::emcal::Digit> digitsbranch, gsl::span<o2::emcal::TriggerRecord> triggerbranch) +{ + setDigits(digitsbranch); + setTriggerRecords(triggerbranch); + process(); +} + +bool RawWriter::processNextTrigger() { - // initialize page handler when processing the first trigger - mPageHandler->initTrigger(mCurrentTrigger->getBCData()); + if (mCurrentTrigger == mTriggers.end()) + return false; for (auto srucont : mSRUdata) srucont.mChannels.clear(); std::vector<o2::emcal::Digit*>* bunchDigits; int lasttower = -1; - for (auto& dig : gsl::span(&mDigits->data()[mCurrentTrigger->getFirstEntry()], mCurrentTrigger->getNumberOfObjects())) { + for (auto& dig : gsl::span(mDigits.data() + mCurrentTrigger->getFirstEntry(), mCurrentTrigger->getNumberOfObjects())) { auto tower = dig.getTower(); if (tower != lasttower) { lasttower = tower; @@ -72,13 +113,6 @@ void RawWriter::processNextTrigger() // Create and fill DMA pages for each channel std::vector<char> payload; for (auto srucont : mSRUdata) { - // EMCAL does not set HBF triggers, only set trigger BC and orbit - o2::header::RAWDataHeaderV4 rawheader; - rawheader.triggerBC = mCurrentTrigger->getBCData().bc; - rawheader.triggerOrbit = mCurrentTrigger->getBCData().orbit; - // @TODO: Set trigger type - rawheader.feeId = srucont.mSRUid; - rawheader.linkID = srucont.mSRUid; for (const auto& [tower, channel] : srucont.mChannels) { // Find out hardware address of the channel @@ -105,13 +139,17 @@ void RawWriter::processNextTrigger() } // Create RCU trailer - auto trailerwords = createRCUTrailer(payload.size(), 16, 16, 100., 0.); + auto trailerwords = createRCUTrailer(payload.size() / 4, 16, 16, 100., 0.); for (auto word : trailerwords) payload.emplace_back(word); - // write DMA page to stream - mPageHandler->addPageForLink(srucont.mSRUid, rawheader, payload); + // register output data + auto ddlid = srucont.mSRUid; + auto [crorc, link] = getLinkAssignment(ddlid); + mRawWriter->addData(ddlid, crorc, link, 0, mCurrentTrigger->getBCData(), payload); } + mCurrentTrigger++; + return true; } std::vector<AltroBunch> RawWriter::findBunches(const std::vector<o2::emcal::Digit*>& channelDigits) @@ -168,6 +206,14 @@ std::tuple<int, int, int> RawWriter::getOnlineID(int towerID) return std::make_tuple(sruID, row, col); } +std::tuple<int, int> RawWriter::getLinkAssignment(int ddlID) +{ + // Temporary link assignment (till final link assignment is known - + // eventually taken from CCDB) + // - Link (0-5) and C-RORC ID linear with ddlID + return std::make_tuple(ddlID / 6, ddlID % 6); +} + std::vector<int> RawWriter::encodeBunchData(const std::vector<int>& data) { std::vector<int> encoded; @@ -218,4 +264,38 @@ std::vector<char> RawWriter::createRCUTrailer(int payloadsize, int feca, int fec std::vector<char> encoded(trailerwords.size() * sizeof(uint32_t)); memcpy(encoded.data(), trailerwords.data(), trailerwords.size() * sizeof(uint32_t)); return encoded; +} + +int RawWriter::carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data, + const char* ptr, int maxSize, int splitID, + std::vector<char>& trailer, std::vector<char>& header) const +{ + int offs = ptr - &data[0]; // offset wrt the head of the payload + // make sure ptr and end of the suggested block are within the payload + assert(offs >= 0 && size_t(offs + maxSize) <= data.size()); + + // Read trailer template from the end of payload + gsl::span<const uint32_t> payloadwords(reinterpret_cast<const uint32_t*>(data.data()), data.size() / sizeof(uint32_t)); + auto rcutrailer = RCUTrailer::constructFromPayloadWords(payloadwords); + + int sizeNoTrailer = maxSize - rcutrailer.getTrailerSize(); + // calculate payload size for RCU trailer: + // assume actualsize is in byte + // Payload size is defined as the number of 32-bit payload words + // -> actualSize to be converted to size of 32 bit words + auto payloadsize = sizeNoTrailer / sizeof(uint32_t); + rcutrailer.setPayloadSize(payloadsize); + auto trailerwords = rcutrailer.encode(); + trailer.resize(trailerwords.size() * sizeof(uint32_t)); + memcpy(trailer.data(), trailerwords.data(), trailer.size()); + // Size to return differs between intermediate pages and last page + // - intermediate page: Size of the trailer needs to be removed as the trailer gets appended + // - last page: Size of the trailer needs to be included as the trailer gets replaced + int bytesLeft = data.size() - (ptr - &data[0]); + bool lastPage = bytesLeft <= maxSize; + int actualSize = maxSize; + if (!lastPage) { + actualSize = sizeNoTrailer; + } + return actualSize; } \ No newline at end of file From a56d32819fa02b98f447d2684936bf166ea09947 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Fri, 14 Aug 2020 17:52:54 +0200 Subject: [PATCH 0405/1751] [EMCAL-630] Adapt raw fitter spec to changes in raw decoding - Fix input spec - Add internal cache for cells for the same IR from multiple links - Convert internal cache to output vector at the end of the processing - Add option to select standard or gamma2 raw fitter - Add abstract function evaluate to CaloRawFitter --- .../EMCALReconstruction/CaloRawFitter.h | 6 +- .../EMCALReconstruction/CaloRawFitterGamma2.h | 8 +- .../CaloRawFitterStandard.h | 8 +- .../EMCALWorkflow/RawToCellConverterSpec.h | 9 +- .../workflow/src/RawToCellConverterSpec.cxx | 102 +++++++++++------- 5 files changed, 79 insertions(+), 54 deletions(-) diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h index e01806428a522..5a91557dbe5de 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitter.h @@ -43,7 +43,11 @@ class CaloRawFitter CaloRawFitter(const char* name, const char* nameshort); /// \brief Destructor - ~CaloRawFitter() = default; + virtual ~CaloRawFitter() = default; + + virtual CaloFitResults evaluate(const std::vector<Bunch>& bunchvector, + std::optional<unsigned int> altrocfg1, + std::optional<unsigned int> altrocfg2) = 0; /// \brief Method to do the selection of what should possibly be fitted. /// \return Size of the sub-selected sample, diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h index e6a31d953d182..a0bc73dc2ce4c 100755 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h @@ -45,7 +45,7 @@ class CaloRawFitterGamma2 : public CaloRawFitter CaloRawFitterGamma2(); /// \brief Destructor - ~CaloRawFitterGamma2() = default; + ~CaloRawFitterGamma2() final = default; void setNiterationsMax(int n) { mNiterationsMax = n; } int getNiterations() { return mNiter; } @@ -53,9 +53,9 @@ class CaloRawFitterGamma2 : public CaloRawFitter /// \brief Evaluation Amplitude and TOF /// return Container with the fit results (amp, time, chi2, ...) - virtual CaloFitResults evaluate(const std::vector<Bunch>& bunchvector, - std::optional<unsigned int> altrocfg1, - std::optional<unsigned int> altrocfg2); + CaloFitResults evaluate(const std::vector<Bunch>& bunchvector, + std::optional<unsigned int> altrocfg1, + std::optional<unsigned int> altrocfg2) final; private: int mNiter = 0; ///< number of iteraions diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h index 801fd8efd2db7..9d42b9547458e 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h @@ -47,7 +47,7 @@ class CaloRawFitterStandard : public CaloRawFitter CaloRawFitterStandard(); /// \brief Destructor - ~CaloRawFitterStandard() = default; + ~CaloRawFitterStandard() final = default; /// \brief Approximate response function of the EMCal electronics. /// \param x: bin @@ -57,9 +57,9 @@ class CaloRawFitterStandard : public CaloRawFitter /// \brief Evaluation Amplitude and TOF /// return Container with the fit results (amp, time, chi2, ...) - virtual CaloFitResults evaluate(const std::vector<Bunch>& bunchvector, - std::optional<unsigned int> altrocfg1, - std::optional<unsigned int> altrocfg2); + CaloFitResults evaluate(const std::vector<Bunch>& bunchvector, + std::optional<unsigned int> altrocfg1, + std::optional<unsigned int> altrocfg2) final; /// \brief Fits the raw signal time distribution /// \return the fit parameters: amplitude, time, chi2, fit status. diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h index 06fbeffa3eb88..a37af9554fb6b 100644 --- a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h @@ -10,14 +10,13 @@ #include <vector> -#include "DataFormatsEMCAL/Cell.h" #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" +#include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/TriggerRecord.h" #include "EMCALBase/Geometry.h" #include "EMCALBase/Mapper.h" -#include "DataFormatsEMCAL/TriggerRecord.h" -#include "EMCALReconstruction/CaloRawFitterStandard.h" -#include "EMCALReconstruction/CaloRawFitterGamma2.h" +#include "EMCALReconstruction/CaloRawFitter.h" namespace o2 { @@ -63,7 +62,7 @@ class RawToCellConverterSpec : public framework::Task int mNoiseThreshold = 0; o2::emcal::Geometry* mGeometry = nullptr; ///!<! Geometry pointer std::unique_ptr<o2::emcal::MappingHandler> mMapper = nullptr; ///!<! Mapper - o2::emcal::CaloRawFitterGamma2 mRawFitter; ///!<! Raw fitter + std::unique_ptr<o2::emcal::CaloRawFitter> mRawFitter; ///!<! Raw fitter std::vector<o2::emcal::Cell> mOutputCells; ///< Container with output cells std::vector<o2::emcal::TriggerRecord> mOutputTriggerRecords; ///< Container with output cells }; diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index eab0613681186..35d40a6ec7f4e 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.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 <string> + #include "FairLogger.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" #include "DataFormatsEMCAL/EMCALBlockHeader.h" #include "DataFormatsEMCAL/TriggerRecord.h" -#include "EMCALWorkflow/RawToCellConverterSpec.h" -#include "Framework/ControlService.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "DetectorsRaw/RDHUtils.h" #include "EMCALBase/Geometry.h" #include "EMCALBase/Mapper.h" @@ -23,7 +25,9 @@ #include "EMCALReconstruction/CaloRawFitterStandard.h" #include "EMCALReconstruction/CaloRawFitterGamma2.h" #include "EMCALReconstruction/AltroDecoder.h" -#include "CommonDataFormat/InteractionRecord.h" +#include "EMCALWorkflow/RawToCellConverterSpec.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCTruthContainer.h" using namespace o2::emcal::reco_workflow; @@ -44,16 +48,24 @@ void RawToCellConverterSpec::init(framework::InitContext& ctx) LOG(ERROR) << "Failed to initialize mapper"; } - mRawFitter.setAmpCut(mNoiseThreshold); - mRawFitter.setL1Phase(0.); + auto fitmethod = ctx.options().get<std::string>("fitmethod"); + if (fitmethod == "standard") { + LOG(INFO) << "Using standard raw fitter"; + mRawFitter = std::unique_ptr<o2::emcal::CaloRawFitter>(new o2::emcal::CaloRawFitterStandard); + } else if (fitmethod == "gamma2") { + mRawFitter = std::unique_ptr<o2::emcal::CaloRawFitter>(new o2::emcal::CaloRawFitterGamma2); + } + + mRawFitter->setAmpCut(mNoiseThreshold); + mRawFitter->setL1Phase(0.); } void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) { LOG(DEBUG) << "[EMCALRawToCellConverter - run] called"; - mOutputCells.clear(); - mOutputTriggerRecords.clear(); + // Cache cells from for bunch crossings as the component reads timeframes from many links consecutively + std::map<o2::InteractionRecord, std::shared_ptr<std::vector<o2::emcal::Cell>>> cellBuffer; // Internal cell buffer int firstEntry = 0; for (const auto& rawData : ctx.inputs()) { @@ -62,10 +74,6 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) o2::emcal::RawReaderMemory rawreader(o2::framework::DataRefUtils::as<const char>(rawData)); - bool first = true; - uint16_t currentTrigger = 0; - uint32_t currentorbit = 0; - // loop over all the DMA pages while (rawreader.hasNext()) { @@ -76,21 +84,14 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) auto triggerOrbit = o2::raw::RDHUtils::getTriggerOrbit(header); auto feeID = o2::raw::RDHUtils::getFEEID(header); - if (!first) { // check if it is the first event in the payload - std::cout << " triggerBC " << triggerBC << " current Trigger " << currentTrigger << std::endl; - if (triggerBC > currentTrigger) { //new event - mOutputTriggerRecords.emplace_back(o2::InteractionRecord(currentTrigger, currentorbit), firstEntry, mOutputCells.size() - 1); - firstEntry = mOutputCells.size(); - - currentTrigger = triggerBC; - currentorbit = triggerOrbit; - } //new event - } else { //first - currentTrigger = triggerBC; - std::cout << " first is true and I set triggerBC to currentTrigger " << currentTrigger << std::endl; - currentorbit = triggerOrbit; - std::cout << " and set first to false " << std::endl; - first = false; + o2::InteractionRecord currentIR(triggerBC, triggerOrbit); + std::shared_ptr<std::vector<o2::emcal::Cell>> currentCellContainer; + auto found = cellBuffer.find(currentIR); + if (found == cellBuffer.end()) { + currentCellContainer = std::make_shared<std::vector<o2::emcal::Cell>>(); + cellBuffer[currentIR] = currentCellContainer; + } else { + currentCellContainer = found->second; } if (feeID > 40) @@ -105,29 +106,49 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) std::cout << decoder.getRCUTrailer() << std::endl; o2::emcal::Mapper map = mMapper->getMappingForDDL(feeID); + int iSM = feeID / 2; // Loop over all the channels for (auto& chan : decoder.getChannels()) { - int iRow = map.getRow(chan.getHardwareAddress()); - int iCol = map.getColumn(chan.getHardwareAddress()); - ChannelType_t chantype = map.getChannelType(chan.getHardwareAddress()); - int iSM = feeID / 2; + int iRow, iCol; + ChannelType_t chantype; + try { + iRow = map.getRow(chan.getHardwareAddress()); + iCol = map.getColumn(chan.getHardwareAddress()); + chantype = map.getChannelType(chan.getHardwareAddress()); + } catch (Mapper::AddressNotFoundException& ex) { + std::cerr << ex.what() << std::endl; + continue; + }; int CellID = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iRow, iCol); // define the conatiner for the fit results, and perform the raw fitting using the stadnard raw fitter - o2::emcal::CaloFitResults fitResults = mRawFitter.evaluate(chan.getBunches(), 0, 0); - - if (fitResults.getAmp() < 0 && fitResults.getTime() < 0) { + double amp = 0., time = 0.; + o2::emcal::CaloFitResults fitResults = mRawFitter->evaluate(chan.getBunches(), 0, 0); + if (fitResults.getAmp() > 0) fitResults.setAmp(0.); + if (fitResults.getTime() < 0) fitResults.setTime(0.); - } - mOutputCells.emplace_back(CellID, fitResults.getAmp(), fitResults.getTime(), chantype); + currentCellContainer->emplace_back(CellID, amp, time, chantype); } } } + // Loop over BCs, sort cells with increasing tower ID and write to output containers + mOutputCells.clear(); + mOutputTriggerRecords.clear(); + for (auto [bc, cells] : cellBuffer) { + mOutputTriggerRecords.emplace_back(bc, mOutputCells.size(), cells->size()); + if (cells->size()) { + // Sort cells according to cell ID + std::sort(cells->begin(), cells->end(), [](o2::emcal::Cell& lhs, o2::emcal::Cell& rhs) { return lhs.getTower() < rhs.getTower(); }); + for (auto cell : *cells) + mOutputCells.push_back(cell); + } + } + LOG(DEBUG) << "[EMCALRawToCellConverter - run] Writing " << mOutputCells.size() << " cells ..."; ctx.outputs().snapshot(o2::framework::Output{"EMC", "CELLS", 0, o2::framework::Lifetime::Timeframe}, mOutputCells); ctx.outputs().snapshot(o2::framework::Output{"EMC", "CELLSTRGR", 0, o2::framework::Lifetime::Timeframe}, mOutputTriggerRecords); @@ -138,12 +159,13 @@ o2::framework::DataProcessorSpec o2::emcal::reco_workflow::getRawToCellConverter std::vector<o2::framework::InputSpec> inputs; std::vector<o2::framework::OutputSpec> outputs; - inputs.emplace_back("readout-proxy", "FLP", "RAWDATA", 0, o2::framework::Lifetime::Timeframe); outputs.emplace_back("EMC", "CELLS", 0, o2::framework::Lifetime::Timeframe); outputs.emplace_back("EMC", "CELLSTRGR", 0, o2::framework::Lifetime::Timeframe); return o2::framework::DataProcessorSpec{"EMCALRawToCellConverterSpec", - inputs, + o2::framework::select("A:EMC/RAWDATA"), outputs, - o2::framework::adaptFromTask<o2::emcal::reco_workflow::RawToCellConverterSpec>()}; + o2::framework::adaptFromTask<o2::emcal::reco_workflow::RawToCellConverterSpec>(), + o2::framework::Options{ + {"fitmethod", o2::framework::VariantType::String, "standard", {"Fit method (standard or gamma2)"}}}}; } From 80e04236c485ac7ed2da9819ba09604af18d1fc2 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 24 Aug 2020 08:38:07 +0200 Subject: [PATCH 0406/1751] using full tracks for V0 and cascades (#4177) --- Analysis/Tutorials/CMakeLists.txt | 4 ++-- .../src/{vzeroIteration.cxx => weakDecayIteration.cxx} | 8 ++++---- Framework/Core/include/Framework/AnalysisDataModel.h | 9 ++++++--- 3 files changed, 12 insertions(+), 9 deletions(-) rename Analysis/Tutorials/src/{vzeroIteration.cxx => weakDecayIteration.cxx} (89%) diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index 6f88aac54e65a..d7a19c1eeca35 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -112,6 +112,6 @@ o2_add_dpl_workflow(custom-index PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) -o2_add_dpl_workflow(vzero-iteration - SOURCES src/vzeroIteration.cxx +o2_add_dpl_workflow(weak-decay-iteration + SOURCES src/weakDecayIteration.cxx COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/vzeroIteration.cxx b/Analysis/Tutorials/src/weakDecayIteration.cxx similarity index 89% rename from Analysis/Tutorials/src/vzeroIteration.cxx rename to Analysis/Tutorials/src/weakDecayIteration.cxx index 50d46e0290290..e36420ec56042 100644 --- a/Analysis/Tutorials/src/vzeroIteration.cxx +++ b/Analysis/Tutorials/src/weakDecayIteration.cxx @@ -18,7 +18,7 @@ struct ATask { Produces<aod::TransientV0s> transientV0s; Produces<aod::TransientCascades> transientCascades; - void process(aod::StoredV0s const& v0s, aod::StoredCascades const& cascades, aod::Tracks const& tracks) + void process(aod::StoredV0s const& v0s, aod::StoredCascades const& cascades, aod::FullTracks const& tracks) { for (auto& v0 : v0s) { transientV0s(v0.posTrack().collisionId()); @@ -30,7 +30,7 @@ struct ATask { }; struct BTask { - void process(aod::V0s const& v0s, aod::Tracks const& tracks) + void process(aod::V0s const& v0s, aod::FullTracks const& tracks) { for (auto& v0 : v0s) { LOGF(DEBUG, "V0 (%d, %d, %d)", v0.posTrack().collisionId(), v0.negTrack().collisionId(), v0.collisionId()); @@ -39,7 +39,7 @@ struct BTask { }; struct CTask { - void process(aod::Cascades const& cascades, aod::Tracks const& tracks) + void process(aod::Cascades const& cascades, aod::FullTracks const& tracks) { for (auto& cascade : cascades) { LOGF(DEBUG, "Cascade (%d, %d)", cascade.bachelor().collisionId(), cascade.collisionId()); @@ -49,7 +49,7 @@ struct CTask { // Grouping struct DTask { - void process(aod::Collision const& collision, aod::V0s const& v0s, aod::Tracks const& tracks) + void process(aod::Collision const& collision, aod::V0s const& v0s, aod::FullTracks const& tracks) { LOGF(INFO, "Collision %d has %d V0s", collision.globalIndex(), v0s.size()); diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index ce5dc815e8d53..512366648ccc2 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -251,6 +251,9 @@ using Track = Tracks::iterator; using TrackCov = TracksCov::iterator; using TrackExtra = TracksExtra::iterator; +using FullTracks = soa::Join<Tracks, TracksCov, TracksExtra>; +using FullTrack = FullTracks::iterator; + namespace unassignedtracks { DECLARE_SOA_INDEX_COLUMN(Collision, collision); @@ -439,8 +442,8 @@ using FDD = FDDs::iterator; namespace v0 { -DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, Tracks, "fPosTrackID"); -DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, Tracks, "fNegTrackID"); +DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, FullTracks, "fPosTrackID"); +DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, FullTracks, "fNegTrackID"); DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace v0 @@ -453,7 +456,7 @@ using V0 = V0s::iterator; namespace cascade { DECLARE_SOA_INDEX_COLUMN(V0, v0); -DECLARE_SOA_INDEX_COLUMN_FULL(Bachelor, bachelor, int, Tracks, "fTracksID"); +DECLARE_SOA_INDEX_COLUMN_FULL(Bachelor, bachelor, int, FullTracks, "fTracksID"); DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace cascade From 87352ef90898e8b01d2ec332e6a8477d2ed07efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Mon, 24 Aug 2020 08:40:26 +0200 Subject: [PATCH 0407/1751] Update in PID tasks and handlers of PID param (#4181) Update TPC qa plots - Using log binning for momentum - Using TPC momentum instead of momentum at vertex Extend QA plots for TOF PID - add event wide info - using different tasks for different observables Add TPC with TOF plots - Add log axes Add param setter from the index Add possibility to read param from file in TPC param handler --- Analysis/DataModel/include/PID/BetheBloch.h | 2 +- Analysis/DataModel/include/PID/TOFReso.h | 2 +- Analysis/DataModel/include/PID/TPCReso.h | 2 +- .../DataModel/include/PIDBase/ParamBase.h | 5 + .../src/handleParamTPCBetheBloch.cxx | 52 ++-- Analysis/Tasks/pidTOF.cxx | 1 - Analysis/Tasks/spectraTOF.cxx | 186 ++++++++----- Analysis/Tasks/spectraTPC.cxx | 249 +++++++++++++++--- 8 files changed, 376 insertions(+), 123 deletions(-) diff --git a/Analysis/DataModel/include/PID/BetheBloch.h b/Analysis/DataModel/include/PID/BetheBloch.h index 2ad85cd0f1fc4..63f670e2bd265 100644 --- a/Analysis/DataModel/include/PID/BetheBloch.h +++ b/Analysis/DataModel/include/PID/BetheBloch.h @@ -27,7 +27,7 @@ namespace o2::pid::tpc class BetheBloch : public Parametrization { public: - BetheBloch() : Parametrization("BetheBloch", 7) { Printf("%s", fName.Data()); }; + BetheBloch() : Parametrization("BetheBloch", 7){}; ~BetheBloch() override = default; float operator()(const float* x) const override { diff --git a/Analysis/DataModel/include/PID/TOFReso.h b/Analysis/DataModel/include/PID/TOFReso.h index 411081f123df4..6b71105ceccb1 100644 --- a/Analysis/DataModel/include/PID/TOFReso.h +++ b/Analysis/DataModel/include/PID/TOFReso.h @@ -29,7 +29,7 @@ namespace o2::pid::tof class TOFReso : public Parametrization { public: - TOFReso() : Parametrization("TOFReso", 5) { Printf("%s", fName.Data()); }; + TOFReso() : Parametrization("TOFReso", 5){}; ~TOFReso() override = default; float operator()(const float* x) const override { diff --git a/Analysis/DataModel/include/PID/TPCReso.h b/Analysis/DataModel/include/PID/TPCReso.h index 93925bdf4a356..7ffc1a7f8e3d0 100644 --- a/Analysis/DataModel/include/PID/TPCReso.h +++ b/Analysis/DataModel/include/PID/TPCReso.h @@ -26,7 +26,7 @@ namespace o2::pid::tpc class TPCReso : public Parametrization { public: - TPCReso() : Parametrization("TPCReso", 2) { Printf("%s", fName.Data()); }; + TPCReso() : Parametrization("TPCReso", 2){}; ~TPCReso() override = default; float operator()(const float* x) const override { diff --git a/Analysis/DataModel/include/PIDBase/ParamBase.h b/Analysis/DataModel/include/PIDBase/ParamBase.h index 111f26079c9d5..9681800e7dc39 100644 --- a/Analysis/DataModel/include/PIDBase/ParamBase.h +++ b/Analysis/DataModel/include/PIDBase/ParamBase.h @@ -108,6 +108,11 @@ class Parametrization : public TNamed /// Printer for parameters void PrintParametrization() const; + /// Setter for the parameter at position iparam + /// \param iparam index in the array of the parameters + /// \param value value of the parameter at position iparam + void SetParameter(const unsigned int iparam, const pidvar_t value) { mParameters.SetParameter(iparam, value); } + /// Setter for the parameter, using an array /// \param params array with parameters void SetParameters(const std::vector<pidvar_t> params) { mParameters.SetParameters(params); } diff --git a/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx b/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx index 4fbf9a533be05..3e542a744f116 100644 --- a/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx +++ b/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx @@ -31,8 +31,9 @@ bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv "url,u", bpo::value<std::string>()->default_value("http://ccdb-test.cern.ch:8080"), "URL of the CCDB database")( "start,s", bpo::value<long>()->default_value(0), "Start timestamp of object validity")( "stop,S", bpo::value<long>()->default_value(4108971600000), "Stop timestamp of object validity")( - "delete_previous,d", bpo::value<int>()->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")( - "file,f", bpo::value<std::string>()->default_value(""), "Option to save parametrization to file instead of uploading to ccdb")( + "delete-previous,d", bpo::value<int>()->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")( + "save-to-file,f", bpo::value<std::string>()->default_value(""), "Option to save parametrization to file instead of uploading to ccdb")( + "read-from-file", bpo::value<std::string>()->default_value(""), "Option to get parametrization from a file")( "mode,m", bpo::value<unsigned int>()->default_value(0), "Working mode: 0 push 1 pull and test")( "verbose,v", bpo::value<int>()->default_value(0), "Verbose level 0, 1")( "help,h", "Produce help message."); @@ -75,17 +76,34 @@ int main(int argc, char* argv[]) return 1; } if (mode == 0) { // Push mode - const std::vector<float> bbparams = {0.0320981, 19.9768, 2.52666e-16, 2.72123, 6.08092, 50.f, 2.3}; - const std::vector<float> resoparams = {0.07, 0.0}; - BetheBloch tpc; - tpc.SetParameters(bbparams); - TPCReso reso; - reso.SetParameters(resoparams); - const std::string fname = vm["file"].as<std::string>(); + BetheBloch* bb = nullptr; + TPCReso* reso = nullptr; + const std::string input_file_name = vm["read-from-file"].as<std::string>(); + + if (!input_file_name.empty()) { + TFile f(input_file_name.data(), "READ"); + if (!f.IsOpen()) { + LOG(WARNING) << "Input file " << input_file_name << " is not reacheable, cannot get param from file"; + } + f.GetObject("BetheBloch", bb); + f.GetObject("TPCReso", reso); + f.Close(); + } + if (!bb) { + bb = new BetheBloch(); + const std::vector<float> bbparams = {0.0320981, 19.9768, 2.52666e-16, 2.72123, 6.08092, 50.f, 2.3}; + bb->SetParameters(bbparams); + } + if (!reso) { + reso = new TPCReso(); + const std::vector<float> resoparams = {0.07, 0.0}; + reso->SetParameters(resoparams); + } + const std::string fname = vm["save-to-file"].as<std::string>(); if (!fname.empty()) { // Saving it to file TFile f(fname.data(), "RECREATE"); - tpc.Write(); - reso.Write(); + bb->Write(); + reso->Write(); f.ls(); f.Close(); } else { // Saving it to CCDB @@ -93,17 +111,17 @@ int main(int argc, char* argv[]) long start = vm["start"].as<long>(); long stop = vm["stop"].as<long>(); - if (vm["delete_previous"].as<int>()) { + if (vm["delete-previous"].as<int>()) { api.truncate(path); } - api.storeAsTFileAny(&tpc, path + "/BetheBloch", metadata, start, stop); - api.storeAsTFileAny(&reso, path + "/TPCReso", metadata, start, stop); + api.storeAsTFileAny(bb, path + "/BetheBloch", metadata, start, stop); + api.storeAsTFileAny(reso, path + "/TPCReso", metadata, start, stop); } } else { // Pull and test mode const float x[2] = {1, 1}; - BetheBloch* tpc = api.retrieveFromTFileAny<BetheBloch>(path + "/BetheBloch", metadata, -1, headers); - tpc->PrintParametrization(); - LOG(INFO) << "BetheBloch " << tpc->operator()(x); + BetheBloch* bb = api.retrieveFromTFileAny<BetheBloch>(path + "/BetheBloch", metadata, -1, headers); + bb->PrintParametrization(); + LOG(INFO) << "BetheBloch " << bb->operator()(x); TPCReso* reso = api.retrieveFromTFileAny<TPCReso>(path + "/TPCReso", metadata, -1, headers); reso->PrintParametrization(); LOG(INFO) << "TPCReso " << reso->operator()(x); diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index 27e47469b15dc..d2b4d3b0d6abe 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -55,7 +55,6 @@ struct pidTOFTask { void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) { - LOGF(info, "Tracks for collision: %d", tracks.size()); tof::EventTime evt = tof::EventTime(); evt.SetEvTime(0, collision.collisionTime()); evt.SetEvTimeReso(0, collision.collisionTimeRes()); diff --git a/Analysis/Tasks/spectraTOF.cxx b/Analysis/Tasks/spectraTOF.cxx index f82db52eba3dd..3cad077b5a146 100644 --- a/Analysis/Tasks/spectraTOF.cxx +++ b/Analysis/Tasks/spectraTOF.cxx @@ -28,80 +28,133 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct TOFPIDQATask { +#define TRACKSELECTION \ + UChar_t clustermap = i.itsClusterMap(); \ + bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); \ + issel = issel && (i.flags() & 0x2000); \ + issel = issel && (i.flags() & 0x80000000); \ + if (!issel) \ + continue; + +// #define TRACKSELECTION 1; + +struct TOFQATask { + // Event quantities + DOTH1F(hvtxz, ";Vertex Z position;Events", 300, -15, 15); + DOTH1F(hevtime, ";Event time (ns);Tracks", 100, -2, 2); // Track quantities - DOTH1F(hp_NoCut, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hp_TrkCut, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hp_TOFCut, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); - // TOF Quantities - DOTH1F(hlength_NoCut, ";Track Length (cm);Tracks", 100, 0, 1000); - DOTH1F(htime_NoCut, ";TOF Time (ns);Tracks", 1000, 0, 600); - DOTH1F(hevtime_NoCut, ";Event time (ns);Tracks", 100, -2, 2); - DOTH2F(hp_pTOFexp_NoCut, ";#it{p} (GeV/#it{c});#it{p}_{Exp TOF} (GeV/#it{c});Tracks", 100, 0, 20, 100, 0, 20); - // T-Texp - DOTH2F(htimediffEl_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e});Tracks", 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffMu_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu});Tracks", 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffPi_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi});Tracks", 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffKa_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K});Tracks", 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffPr_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p});Tracks", 100, 0, 5, 100, -1000, 1000); - // NSigma - DOTH2F(hnsigmaEl_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e})/N_{sigma e};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaMu_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu})/N_{sigma #mu};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaPi_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi})/N_{sigma #pi};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaKa_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K})/N_{sigma K};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaPr_NoCut, ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p})/N_{sigma p};Tracks", 100, 0, 5, 100, -10, 10); + DOTH1F(heta, ";#eta;Tracks", 100, -1, 1); + DOTH1F(hp, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hpt, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); + DOTH1F(hlength, ";Track Length (cm);Tracks", 100, 0, 1000); + DOTH1F(htime, ";TOF Time (ns);Tracks", 1000, 0, 600); // Beta DOTH2F(hp_beta, ";#it{p} (GeV/#it{c});TOF #beta;Tracks", 100, 0, 20, 100, 0, 2); void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) { + hvtxz->Fill(collision.posZ()); for (auto i : tracks) { - hp_NoCut->Fill(i.p()); // Track selection - UChar_t clustermap = i.itsClusterMap(); - bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); - if (issel) - hp_TrkCut->Fill(i.p()); - issel = issel && (i.flags() & 0x2000); //kTOFout - issel = issel && (i.flags() & 0x80000000); //kTIME - if (issel) - hp_TOFCut->Fill(i.p()); - hp_pTOFexp_NoCut->Fill(i.p(), i.tofExpMom() / (TMath::C() * 1.0e2f * 1.0e-12f)); - // - hlength_NoCut->Fill(i.length()); - htime_NoCut->Fill(i.tofSignal() / 1000); + TRACKSELECTION; // - hevtime_NoCut->Fill(collision.collisionTime() / 1000); - // hevtime_NoCut->Fill(collision.collisionTime0() / 1000); + hevtime->Fill(collision.collisionTime() / 1000); + // hevtime->Fill(collision.collisionTime0() / 1000); + const float psq = sqrt(i.px() * i.px() + i.py() * i.py() + i.pz() * i.pz()); + heta->Fill(i.eta()); + hp->Fill(i.p()); + hpt->Fill(i.pt()); // - htimediffEl_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalEl()); - htimediffMu_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalMu()); - htimediffPi_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalPi()); - htimediffKa_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalKa()); - htimediffPr_NoCut->Fill(i.p(), i.tofSignal() - collision.collisionTime() - i.tofExpSignalPr()); - // - hnsigmaEl_NoCut->Fill(i.p(), i.tofNSigmaEl()); - hnsigmaMu_NoCut->Fill(i.p(), i.tofNSigmaMu()); - hnsigmaPi_NoCut->Fill(i.p(), i.tofNSigmaPi()); - hnsigmaKa_NoCut->Fill(i.p(), i.tofNSigmaKa()); - hnsigmaPr_NoCut->Fill(i.p(), i.tofNSigmaPr()); + hlength->Fill(i.length()); + htime->Fill(i.tofSignal() / 1000); // Beta hp_beta->Fill(i.p(), i.beta()); } } }; -struct SpectraTask { +struct TOFExpTimeQATask { + // T-Texp +#define TIT(part) Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp %s});Tracks", part) + DOTH2F(htimediffEl, TIT("e"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffMu, TIT("#mu"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffPi, TIT("#pi"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffKa, TIT("K"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffPr, TIT("p"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffDe, TIT("d"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffTr, TIT("t"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffHe, TIT("^{3}He"), 100, 0, 5, 100, -1000, 1000); + DOTH2F(htimediffAl, TIT("#alpha"), 100, 0, 5, 100, -1000, 1000); +#undef TIT + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) + { + for (auto i : tracks) { + // Track selection + TRACKSELECTION; + // + const float tof = i.tofSignal() - collision.collisionTime(); + htimediffEl->Fill(i.p(), tof - i.tofExpSignalEl()); + htimediffMu->Fill(i.p(), tof - i.tofExpSignalMu()); + htimediffPi->Fill(i.p(), tof - i.tofExpSignalPi()); + htimediffKa->Fill(i.p(), tof - i.tofExpSignalKa()); + htimediffPr->Fill(i.p(), tof - i.tofExpSignalPr()); + htimediffDe->Fill(i.p(), tof - i.tofExpSignalDe()); + htimediffTr->Fill(i.p(), tof - i.tofExpSignalTr()); + htimediffHe->Fill(i.p(), tof - i.tofExpSignalHe()); + htimediffAl->Fill(i.p(), tof - i.tofExpSignalAl()); + } + } +}; + +struct TOFNSigmaQATask { + // NSigma +#define TIT(part) Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp %s})/N_{sigma %s};Tracks", part, part) + DOTH2F(hnsigmaEl, TIT("e"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaMu, TIT("#mu"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaPi, TIT("#pi"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaKa, TIT("K"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaPr, TIT("p"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaDe, TIT("d"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaTr, TIT("t"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaHe, TIT("^{3}He"), 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaAl, TIT("#alpha"), 100, 0, 5, 100, -10, 10); +#undef TIT + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) + { + for (auto i : tracks) { + // Track selection + TRACKSELECTION; + // + hnsigmaEl->Fill(i.p(), i.tofNSigmaEl()); + hnsigmaMu->Fill(i.p(), i.tofNSigmaMu()); + hnsigmaPi->Fill(i.p(), i.tofNSigmaPi()); + hnsigmaKa->Fill(i.p(), i.tofNSigmaKa()); + hnsigmaPr->Fill(i.p(), i.tofNSigmaPr()); + hnsigmaDe->Fill(i.p(), i.tofNSigmaDe()); + hnsigmaTr->Fill(i.p(), i.tofNSigmaTr()); + hnsigmaHe->Fill(i.p(), i.tofNSigmaHe()); + hnsigmaAl->Fill(i.p(), i.tofNSigmaAl()); + } + } +}; + +struct TOFSpectraTask { // Pt - DOTH1F(hpt_El, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hpt_Pi, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hpt_Ka, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hpt_Pr, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); +#define TIT ";#it{p}_{T} (GeV/#it{c});Tracks" + DOTH1F(hpt_El, TIT, 100, 0, 20); + DOTH1F(hpt_Pi, TIT, 100, 0, 20); + DOTH1F(hpt_Ka, TIT, 100, 0, 20); + DOTH1F(hpt_Pr, TIT, 100, 0, 20); +#undef TIT // P - DOTH1F(hp_El, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hp_Pi, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hp_Ka, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hp_Pr, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); +#define TIT ";#it{p} (GeV/#it{c});Tracks" + DOTH1F(hp_El, TIT, 100, 0, 20); + DOTH1F(hp_Pi, TIT, 100, 0, 20); + DOTH1F(hp_Ka, TIT, 100, 0, 20); + DOTH1F(hp_Pr, TIT, 100, 0, 20); +#undef TIT // DOTH1F(hlength_El, ";Track Length (cm);Tracks", 100, 0, 1000); DOTH1F(htime_El, ";TOF Time (ns);Tracks", 1000, 0, 600); @@ -115,15 +168,12 @@ struct SpectraTask { void process(soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) { for (auto i : tracks) { - UChar_t clustermap = i.itsClusterMap(); - bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); - issel = issel && (i.flags() & 0x2000); //kTOFout - issel = issel && (i.flags() & 0x80000000); //kTIME - if (!issel) - continue; + // Track selection + TRACKSELECTION; + // if (TMath::Abs(i.tofNSigmaPi()) < 3) { - hp_El->Fill(i.p()); - hpt_El->Fill(i.pt()); + hp_Pi->Fill(i.p()); + hpt_Pi->Fill(i.pt()); } else if (TMath::Abs(i.tofNSigmaKa()) < 3) { hp_Ka->Fill(i.p()); hpt_Ka->Fill(i.pt()); @@ -148,6 +198,10 @@ struct SpectraTask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<TOFPIDQATask>("tofpidqa-task"), - adaptAnalysisTask<SpectraTask>("filterEl-task")}; + adaptAnalysisTask<TOFQATask>("tofqa-task"), + adaptAnalysisTask<TOFExpTimeQATask>("tofexptime-task"), + adaptAnalysisTask<TOFNSigmaQATask>("tofnsigma-task"), + adaptAnalysisTask<TOFSpectraTask>("tofspectra-task")}; } + +#undef TRACKSELECTION diff --git a/Analysis/Tasks/spectraTPC.cxx b/Analysis/Tasks/spectraTPC.cxx index 0657c25a6ae33..4344fee782c20 100644 --- a/Analysis/Tasks/spectraTPC.cxx +++ b/Analysis/Tasks/spectraTPC.cxx @@ -24,12 +24,42 @@ #define DOTH2F(OBJ, ...) \ OutputObj<TH2F> OBJ{TH2F(#OBJ, __VA_ARGS__)}; +#define TRACKSELECTION \ + UChar_t clustermap = i.itsClusterMap(); \ + bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); \ + if (!issel) \ + continue; + +// #define TRACKSELECTION 1; + +#define makelogaxis(h) \ + { \ + const Int_t nbins = h->GetNbinsX(); \ + double binp[nbins + 1]; \ + double max = h->GetXaxis()->GetBinUpEdge(nbins); \ + double min = h->GetXaxis()->GetBinLowEdge(1); \ + double lmin = TMath::Log10(min); \ + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); \ + for (int i = 0; i < nbins; i++) { \ + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); \ + } \ + binp[nbins] = max + 1; \ + h->GetXaxis()->Set(nbins, binp); \ + } + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"add-tof-histos", VariantType::Bool, false, {"Generate TPC with TOF histograms"}}}; + std::swap(workflowOptions, options); +} + struct TPCPIDQAExpSignalTask { -#define BIN_AXIS 100, 0, 5, 1000, 0, 1000 +#define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000 DOTH2F(htpcsignal, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); DOTH2F(hexpEl, ";#it{p} (GeV/#it{c});TPC expected signal e;Tracks", BIN_AXIS); @@ -44,54 +74,81 @@ struct TPCPIDQAExpSignalTask { #undef BIN_AXIS + void init(o2::framework::InitContext&) + { + // Log binning for p + makelogaxis(htpcsignal); + makelogaxis(hexpEl); + makelogaxis(hexpMu); + makelogaxis(hexpPi); + makelogaxis(hexpKa); + makelogaxis(hexpPr); + makelogaxis(hexpDe); + makelogaxis(hexpTr); + makelogaxis(hexpHe); + makelogaxis(hexpAl); + } + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) { for (auto const& i : tracks) { // Track selection - const UChar_t clustermap = i.itsClusterMap(); - bool issel = (i.tpcNClsFindable() > 70); - issel = issel && (i.flags() & 0x4); - issel = issel && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); - if (!issel) - continue; + TRACKSELECTION; // - htpcsignal->Fill(i.p(), i.tpcSignal()); - hexpEl->Fill(i.p(), i.tpcExpSignalEl()); - hexpMu->Fill(i.p(), i.tpcExpSignalMu()); - hexpPi->Fill(i.p(), i.tpcExpSignalPi()); - hexpKa->Fill(i.p(), i.tpcExpSignalKa()); - hexpPr->Fill(i.p(), i.tpcExpSignalPr()); - hexpDe->Fill(i.p(), i.tpcExpSignalDe()); - hexpTr->Fill(i.p(), i.tpcExpSignalTr()); - hexpHe->Fill(i.p(), i.tpcExpSignalHe()); - hexpAl->Fill(i.p(), i.tpcExpSignalAl()); + + // const float mom = i.p(); + const float mom = i.tpcInnerParam(); + htpcsignal->Fill(mom, i.tpcSignal()); + hexpEl->Fill(mom, i.tpcExpSignalEl()); + hexpMu->Fill(mom, i.tpcExpSignalMu()); + hexpPi->Fill(mom, i.tpcExpSignalPi()); + hexpKa->Fill(mom, i.tpcExpSignalKa()); + hexpPr->Fill(mom, i.tpcExpSignalPr()); + hexpDe->Fill(mom, i.tpcExpSignalDe()); + hexpTr->Fill(mom, i.tpcExpSignalTr()); + hexpHe->Fill(mom, i.tpcExpSignalHe()); + hexpAl->Fill(mom, i.tpcExpSignalAl()); } } }; struct TPCPIDQANSigmaTask { +#define BIN_AXIS 1000, 0.001, 20, 1000, -10, 10 + // TPC NSigma - DOTH2F(hnsigmaEl, ";#it{p} (GeV/#it{c});TPC N_{sigma e};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaMu, ";#it{p} (GeV/#it{c});TPC N_{sigma #mu};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaPi, ";#it{p} (GeV/#it{c});TPC N_{sigma #pi};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaKa, ";#it{p} (GeV/#it{c});TPC N_{sigma K};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaPr, ";#it{p} (GeV/#it{c});TPC N_{sigma p};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaDe, ";#it{p} (GeV/#it{c});TPC N_{sigma d};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaTr, ";#it{p} (GeV/#it{c});TPC N_{sigma t};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaHe, ";#it{p} (GeV/#it{c});TPC N_{sigma ^{3}He};Tracks", 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaAl, ";#it{p} (GeV/#it{c});TPC N_{sigma #alpha};Tracks", 100, 0, 5, 100, -10, 10); + DOTH2F(hnsigmaEl, ";#it{p} (GeV/#it{c});TPC N_{sigma e};Tracks", BIN_AXIS); + DOTH2F(hnsigmaMu, ";#it{p} (GeV/#it{c});TPC N_{sigma #mu};Tracks", BIN_AXIS); + DOTH2F(hnsigmaPi, ";#it{p} (GeV/#it{c});TPC N_{sigma #pi};Tracks", BIN_AXIS); + DOTH2F(hnsigmaKa, ";#it{p} (GeV/#it{c});TPC N_{sigma K};Tracks", BIN_AXIS); + DOTH2F(hnsigmaPr, ";#it{p} (GeV/#it{c});TPC N_{sigma p};Tracks", BIN_AXIS); + DOTH2F(hnsigmaDe, ";#it{p} (GeV/#it{c});TPC N_{sigma d};Tracks", BIN_AXIS); + DOTH2F(hnsigmaTr, ";#it{p} (GeV/#it{c});TPC N_{sigma t};Tracks", BIN_AXIS); + DOTH2F(hnsigmaHe, ";#it{p} (GeV/#it{c});TPC N_{sigma ^{3}He};Tracks", BIN_AXIS); + DOTH2F(hnsigmaAl, ";#it{p} (GeV/#it{c});TPC N_{sigma #alpha};Tracks", BIN_AXIS); + +#undef BIN_AXIS + + void init(o2::framework::InitContext&) + { + // Log binning for p + makelogaxis(hnsigmaEl); + makelogaxis(hnsigmaMu); + makelogaxis(hnsigmaPi); + makelogaxis(hnsigmaKa); + makelogaxis(hnsigmaPr); + makelogaxis(hnsigmaDe); + makelogaxis(hnsigmaTr); + makelogaxis(hnsigmaHe); + makelogaxis(hnsigmaAl); + } void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) { for (auto const& i : tracks) { // Track selection - const UChar_t clustermap = i.itsClusterMap(); - bool issel = (i.tpcNClsFindable() > 70); - issel = issel && (i.flags() & 0x4); - issel = issel && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); - if (!issel) - continue; + TRACKSELECTION; // + hnsigmaEl->Fill(i.p(), i.tpcNSigmaEl()); hnsigmaMu->Fill(i.p(), i.tpcNSigmaMu()); hnsigmaPi->Fill(i.p(), i.tpcNSigmaPi()); @@ -105,9 +162,129 @@ struct TPCPIDQANSigmaTask { } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +struct TPCPIDQASignalwTOFTask { +#define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000 + + DOTH2F(htpcsignalEl, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalMu, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalPi, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalKa, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalPr, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalDe, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalTr, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalHe, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH2F(htpcsignalAl, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + +#undef BIN_AXIS + + void init(o2::framework::InitContext&) + { + // Log binning for p + makelogaxis(htpcsignalEl); + makelogaxis(htpcsignalMu); + makelogaxis(htpcsignalPi); + makelogaxis(htpcsignalKa); + makelogaxis(htpcsignalPr); + makelogaxis(htpcsignalDe); + makelogaxis(htpcsignalTr); + makelogaxis(htpcsignalHe); + makelogaxis(htpcsignalAl); + } + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF> const& tracks) + { + for (auto const& i : tracks) { + // Track selection + TRACKSELECTION; + // Require kTIME and kTOFout + if (!(i.flags() & 0x2000)) + continue; + if (!(i.flags() & 0x80000000)) + continue; + // + + // const float mom = i.p(); + const float mom = i.tpcInnerParam(); + if (abs(i.tofNSigmaEl()) < 2) { + htpcsignalEl->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaMu()) < 2) { + htpcsignalMu->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaPi()) < 2) { + htpcsignalPi->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaKa()) < 2) { + htpcsignalKa->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaPr()) < 2) { + htpcsignalPr->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaDe()) < 2) { + htpcsignalDe->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaTr()) < 2) { + htpcsignalTr->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaHe()) < 2) { + htpcsignalHe->Fill(mom, i.tpcSignal()); + } + if (abs(i.tofNSigmaAl()) < 2) { + htpcsignalAl->Fill(mom, i.tpcSignal()); + } + } + } +}; + +struct TPCSpectraTask { + // Pt +#define TIT ";#it{p}_{T} (GeV/#it{c});Tracks" + DOTH1F(hpt_El, TIT, 100, 0, 20); + DOTH1F(hpt_Pi, TIT, 100, 0, 20); + DOTH1F(hpt_Ka, TIT, 100, 0, 20); + DOTH1F(hpt_Pr, TIT, 100, 0, 20); +#undef TIT + // P +#define TIT ";#it{p} (GeV/#it{c});Tracks" + DOTH1F(hp_El, TIT, 100, 0, 20); + DOTH1F(hp_Pi, TIT, 100, 0, 20); + DOTH1F(hp_Ka, TIT, 100, 0, 20); + DOTH1F(hp_Pr, TIT, 100, 0, 20); +#undef TIT + + void process(soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) + { + for (auto i : tracks) { + // Track selection + TRACKSELECTION; + // + if (TMath::Abs(i.tpcNSigmaEl()) < 3) { + hp_El->Fill(i.p()); + hpt_El->Fill(i.pt()); + } + if (TMath::Abs(i.tpcNSigmaPi()) < 3) { + hp_Pi->Fill(i.p()); + hpt_Pi->Fill(i.pt()); + } + if (TMath::Abs(i.tpcNSigmaKa()) < 3) { + hp_Ka->Fill(i.p()); + hpt_Ka->Fill(i.pt()); + } + if (TMath::Abs(i.tpcNSigmaPr()) < 3) { + hp_Pr->Fill(i.p()); + hpt_Pr->Fill(i.pt()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask<TPCPIDQAExpSignalTask>("TPCpidqa-expsignal-task"), - adaptAnalysisTask<TPCPIDQANSigmaTask>("TPCpidqa-nsigma-task")}; + bool TPCwTOF = cfgc.options().get<bool>("add-tof-histos"); + WorkflowSpec workflow{adaptAnalysisTask<TPCPIDQAExpSignalTask>("TPCpidqa-expsignal-task"), + adaptAnalysisTask<TPCPIDQANSigmaTask>("TPCpidqa-nsigma-task"), + adaptAnalysisTask<TPCSpectraTask>("tpcspectra-task")}; + if (TPCwTOF) + workflow.push_back(adaptAnalysisTask<TPCPIDQASignalwTOFTask>("TPCpidqa-signalwTOF-task")); + return workflow; } From 148dc2486d2e58b7d5c3f40a7a31b06c74934f18 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 23 Aug 2020 23:35:52 +0200 Subject: [PATCH 0408/1751] On-demand calculation of PCA cov.matrix in DCAFitterN --- .../include/DetectorsVertexing/DCAFitterN.h | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h index f5000b7ccbd5b..74b9830f51784 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h @@ -30,15 +30,15 @@ namespace vertexing struct TrackCovI { float sxx, syy, syz, szz; - TrackCovI(const o2::track::TrackParCov& trc) { set(trc); } + TrackCovI(const o2::track::TrackParCov& trc, float xerrFactor = 1.) { set(trc, xerrFactor); } TrackCovI() = default; - void set(const o2::track::TrackParCov& trc) + void set(const o2::track::TrackParCov& trc, float xerrFactor = 1) { // we assign Y error to X for DCA calculation // (otherwise for quazi-collinear tracks the X will not be constrained) - float cyy = trc.getSigmaY2(), czz = trc.getSigmaZ2(), cyz = trc.getSigmaZY(), cxx = cyy; + float cyy = trc.getSigmaY2(), czz = trc.getSigmaZ2(), cyz = trc.getSigmaZY(), cxx = cyy * xerrFactor; float detYZ = cyy * czz - cyz * cyz; if (detYZ > 0.) { auto detYZI = 1. / detYZ; @@ -75,7 +75,7 @@ class DCAFitterN static constexpr double NMax = 4; static constexpr double NInv = 1. / N; static constexpr int MAXHYP = 2; - + static constexpr float XerrFactor = 5.; // factor for conversion of track covYY to dummy covXX using Track = o2::track::TrackParCov; using TrackAuxPar = o2::track::TrackAuxPar; using CrossInfo = o2::track::CrossInfo; @@ -129,6 +129,8 @@ class DCAFitterN return mCandTr[mOrder[cand]][i]; } + MatSym3D calcPCACovMatrix(int cand = 0) const; + const Track* getOrigTrackPtr(int i) const { return mOrigTrPtr[i]; } ///< return number of iterations during minimization (no check for its validity) @@ -180,6 +182,27 @@ class DCAFitterN bool closerToAlternative() const; static double getAbsMax(const VecND& v); + MatStd3D getTrackRotMatrix(int i) const // generate 3D matrix for track rotation to global frame + { + MatStd3D mat; + mat(2, 2) = 1; + mat(0, 0) = mat(1, 1) = mTrAux[i].c; + mat(0, 1) = -mTrAux[i].s; + mat(1, 0) = mTrAux[i].s; + return std::move(mat); + } + + MatSym3D getTrackCovMatrix(int i, int cand = 0) const // generate covariance matrix of track position, adding fake X error + { + const auto& trc = mCandTr[mOrder[cand]][i]; + MatSym3D mat; + mat(0, 0) = trc.getSigmaY2() * XerrFactor; + mat(1, 1) = trc.getSigmaY2(); + mat(2, 2) = trc.getSigmaZ2(); + mat(2, 1) = trc.getSigmaZY(); + return std::move(mat); + } + void assign(int) {} template <class T, class... Tr> void assign(int i, const T& t, const Tr&... args) @@ -570,6 +593,18 @@ void DCAFitterN<N, Args...>::calcPCANoErr() pca[2] *= NInv; } +//___________________________________________________________________ +template <int N, typename... Args> +ROOT::Math::SMatrix<double, 3, 3, ROOT::Math::MatRepSym<double, 3>> DCAFitterN<N, Args...>::calcPCACovMatrix(int cand) const +{ + // calculate covariance matrix for the point of closest approach + MatSym3D covm; + for (int i = N; i--;) { + covm += ROOT::Math::Similarity(mUseAbsDCA ? getTrackRotMatrix(i) : mTrCFVT[mOrder[cand]][i], getTrackCovMatrix(i, cand)); + } + return std::move(covm); +} + //___________________________________________________________________ template <int N, typename... Args> void DCAFitterN<N, Args...>::calcTrackResiduals() @@ -686,7 +721,7 @@ bool DCAFitterN<N, Args...>::minimizeChi2() return false; } setTrackPos(mTrPos[mCurHyp][i], mCandTr[mCurHyp][i]); // prepare positions - mTrcEInv[mCurHyp][i].set(mCandTr[mCurHyp][i]); // prepare inverse cov.matrices at starting point + mTrcEInv[mCurHyp][i].set(mCandTr[mCurHyp][i], XerrFactor); // prepare inverse cov.matrices at starting point } if (mMaxDZIni > 0 && !roughDZCut()) { // apply rough cut on tracks Z difference From 7397510367428ecc4511a12164896807bad5d4d0 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 18 Aug 2020 22:55:11 +0200 Subject: [PATCH 0409/1751] MCLabel for event of vertex: ID + weight --- DataFormats/simulation/CMakeLists.txt | 7 + .../SimulationDataFormat/MCEventLabel.h | 120 ++++++++++++++++++ DataFormats/simulation/src/MCEventLabel.cxx | 36 ++++++ .../simulation/src/SimulationDataLinkDef.h | 2 + .../simulation/test/testMCEventLabel.cxx | 38 ++++++ 5 files changed, 203 insertions(+) create mode 100644 DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h create mode 100644 DataFormats/simulation/src/MCEventLabel.cxx create mode 100644 DataFormats/simulation/test/testMCEventLabel.cxx diff --git a/DataFormats/simulation/CMakeLists.txt b/DataFormats/simulation/CMakeLists.txt index fec3ebbd23e70..27aab16c6496c 100644 --- a/DataFormats/simulation/CMakeLists.txt +++ b/DataFormats/simulation/CMakeLists.txt @@ -12,6 +12,7 @@ o2_add_library(SimulationDataFormat SOURCES src/Stack.cxx src/MCTrack.cxx src/MCCompLabel.cxx + src/MCEventLabel.cxx src/DigitizationContext.cxx src/StackParam.cxx src/MCEventHeader.cxx @@ -29,6 +30,7 @@ o2_target_root_dictionary( include/SimulationDataFormat/BaseHits.h include/SimulationDataFormat/MCTruthContainer.h include/SimulationDataFormat/MCCompLabel.h + include/SimulationDataFormat/MCEventLabel.h include/SimulationDataFormat/TrackReference.h include/SimulationDataFormat/PrimaryChunk.h include/SimulationDataFormat/DigitizationContext.h @@ -56,6 +58,11 @@ o2_add_test(MCCompLabel COMPONENT_NAME SimulationDataFormat PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat) +o2_add_test(MCEventLabel + SOURCES test/testMCEventLabel.cxx + COMPONENT_NAME SimulationDataFormat + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat) + o2_add_test(MCTrack SOURCES test/MCTrack.cxx COMPONENT_NAME SimulationDataFormat diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h b/DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h new file mode 100644 index 0000000000000..4ff57f2be253e --- /dev/null +++ b/DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h @@ -0,0 +1,120 @@ +// 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_MCVEVENTLABEL_H +#define ALICEO2_MCVEVENTLABEL_H + +#include "GPUCommonRtypes.h" +#include <cmath> +#include <cassert> + +namespace o2 +{ +// Composed Label to encode MC event and the source (file) + weight + +class MCEventLabel +{ + private: + static constexpr uint32_t NotSet = 0xffffffff; + uint32_t mLabel = NotSet; ///< MC label encoding MCevent origin and fraction of correct contributors + + public: + static constexpr int nbitsEvID = 16; // number of bits reserved for MC event ID + static constexpr int nbitsSrcID = 7; // number of bits reserved for MC source ID + static constexpr int nbitsCorrW = sizeof(mLabel) * 8 - nbitsEvID - nbitsSrcID - 1; + + // Mask to extract MC event ID + static constexpr uint32_t MaskEvID = (0x1 << nbitsEvID) - 1; + // Mask to extract MC source ID + static constexpr uint32_t MaskSrcID = (0x1 << nbitsSrcID) - 1; + // Mask to extract MC correct contribution weight + static constexpr uint32_t MaskCorrW = (0x1 << nbitsCorrW) - 1; + static constexpr float WeightNorm = 1. / float(MaskCorrW); + + MCEventLabel(int evID, int srcID, float corrw = 1.0) { set(evID, srcID, corrw); } + MCEventLabel() = default; + ~MCEventLabel() = default; + + // check if label was assigned + bool isSet() const { return mLabel != NotSet; } + // check if label was not assigned + bool isEmpty() const { return mLabel == NotSet; } + + // conversion operator + operator uint32_t() const { return mLabel; } + // allow to retrieve bare label + uint32_t getRawValue() const { return mLabel; } + + // get only combined identifier, discarding weight info + uint32_t getIDOnly() const { return mLabel & (0x1 << (nbitsEvID + nbitsSrcID)); } + + // compare + bool compare(const MCEventLabel& other, bool strict = false) const + { + return strict ? (getRawValue() == other.getRawValue()) : (getIDOnly() == other.getIDOnly()); + } + + // comparison operator, compares only label, not eventual weight or correctness info + bool operator==(const MCEventLabel& other) const { return compare(other); } + + // invalidate + void unset() { mLabel = NotSet; } + + /// compose label + void set(int evID, int srcID, float corrW) + { + uint32_t iw = static_cast<uint32_t>(std::round(corrW * MaskCorrW)); + assert(iw <= MaskCorrW); + mLabel = (iw << (nbitsEvID + nbitsSrcID)) | ((MaskSrcID & static_cast<uint32_t>(srcID)) << nbitsEvID) | (MaskEvID & static_cast<uint32_t>(evID)); + } + void setCorrWeight(float corrW) + { + uint32_t iw = static_cast<uint32_t>(std::round(corrW * MaskCorrW)); + assert(iw <= MaskCorrW); + mLabel = (mLabel & ((MaskSrcID << nbitsEvID) | MaskEvID)) | (iw << (nbitsEvID + nbitsSrcID)); + } + + int getEventID() const { return mLabel & MaskEvID; } + int getSourceID() const { return (mLabel >> nbitsEvID) & MaskSrcID; } + float getCorrWeight() const { return ((mLabel >> (nbitsEvID + nbitsSrcID)) & MaskCorrW) * WeightNorm; } + + void get(int& evID, int& srcID, float& corrW) + { + /// parse label + evID = getEventID(); + srcID = getSourceID(); + corrW = getCorrWeight(); + } + + void print() const; + + static constexpr uint32_t MaxSourceID() { return MaskSrcID; } + static constexpr uint32_t MaxEventID() { return MaskEvID; } + static constexpr float WeightPrecision() { return WeightNorm; } + ClassDefNV(MCEventLabel, 1); +}; +} // namespace o2 + +std::ostream& operator<<(std::ostream& os, const o2::MCEventLabel& c); + +namespace std +{ +// defining std::hash for MCEventLabel in order to be used with unordered_maps +template <> +struct hash<o2::MCEventLabel> { + public: + size_t operator()(o2::MCEventLabel const& label) const + { + return static_cast<uint32_t>(label); + } +}; +} // namespace std + +#endif diff --git a/DataFormats/simulation/src/MCEventLabel.cxx b/DataFormats/simulation/src/MCEventLabel.cxx new file mode 100644 index 0000000000000..f12b6bf5d1dc1 --- /dev/null +++ b/DataFormats/simulation/src/MCEventLabel.cxx @@ -0,0 +1,36 @@ +// 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 "SimulationDataFormat/MCEventLabel.h" +#include <iomanip> +#include <ios> +#include <iostream> +#include <cassert> + +using namespace o2; + +//_____________________________________________ +void MCEventLabel::print() const +{ + // print itself + std::cout << (MCEventLabel) * this << std::endl; +} + +//_____________________________________________ +std::ostream& operator<<(std::ostream& os, const o2::MCEventLabel& c) +{ + // stream itself + if (c.isSet()) { + os << '[' << c.getSourceID() << '/' << c.getEventID() << '/' << c.getCorrWeight() << ']'; + } else { + os << "[unset]"; + } + return os; +} diff --git a/DataFormats/simulation/src/SimulationDataLinkDef.h b/DataFormats/simulation/src/SimulationDataLinkDef.h index b48037d6cc9d4..8977197322fec 100644 --- a/DataFormats/simulation/src/SimulationDataLinkDef.h +++ b/DataFormats/simulation/src/SimulationDataLinkDef.h @@ -32,6 +32,7 @@ #pragma link C++ class std::vector < o2::MCTrackT < double>> + ; #pragma link C++ class std::vector < o2::MCTrackT < float>> + ; #pragma link C++ class o2::MCCompLabel + ; +#pragma link C++ class o2::MCEventLabel + ; #pragma link C++ class o2::BaseHit + ; #pragma link C++ class o2::BasicXYZVHit < float, float, float> + ; @@ -47,6 +48,7 @@ #pragma link C++ class o2::dataformats::MCTruthContainer < o2::MCCompLabel > -; #pragma link C++ class std::vector < o2::dataformats::MCTruthContainer < o2::MCCompLabel>> + ; #pragma link C++ class std::vector < o2::MCCompLabel> + ; +#pragma link C++ class std::vector < o2::MCEventLabel> + ; #pragma link C++ class std::vector < o2::dataformats::MCTruthHeaderElement> + ; #pragma link C++ class o2::SimTrackStatus + ; diff --git a/DataFormats/simulation/test/testMCEventLabel.cxx b/DataFormats/simulation/test/testMCEventLabel.cxx new file mode 100644 index 0000000000000..0ea2c8af288a9 --- /dev/null +++ b/DataFormats/simulation/test/testMCEventLabel.cxx @@ -0,0 +1,38 @@ +// 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. + +#define BOOST_TEST_MODULE Test MCEventLabel class +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "Framework/Logger.h" +#include "SimulationDataFormat/MCEventLabel.h" +#include <TRandom.h> + +using namespace o2; + +BOOST_AUTO_TEST_CASE(MCEventLabel_test) +{ + MCEventLabel lbUndef; + BOOST_CHECK(!lbUndef.isSet()); // test invalid label status + + for (int itr = 0; itr < 100; itr++) { + int ev = gRandom->Integer(MCEventLabel::MaxEventID()), src = gRandom->Integer(MCEventLabel::MaxSourceID()); + float w = gRandom->Rndm(); + MCEventLabel lb(ev, src, w); + LOG(INFO) << "Input: [" << src << '/' << ev << '/' << w << ']'; + LOG(INFO) << "Encoded: " << lb << " (packed: " << uint32_t(lb) << ")"; + int evE, srcE; + float wE; + lb.get(evE, srcE, wE); + LOG(INFO) << "Decoded: [" << srcE << '/' << evE << '/' << wE << ']'; + BOOST_CHECK(ev == evE && src == srcE && std::abs(w - wE) < MCEventLabel::WeightPrecision()); + } +} From 0e12e197358f354c3281742253f7f0ae22c19a16 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 23 Aug 2020 00:11:43 +0200 Subject: [PATCH 0410/1751] add mean/rms accumulator class to math.utils --- Common/MathUtils/include/MathUtils/Utils.h | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index adf4e4bdb5e81..45b1ad4c324a8 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -210,6 +210,65 @@ GPUhdi() float FastATan2(float y, float x) return o2::gpu::GPUCommonMath::Copysign(atan2P(o2::gpu::CAMath::Abs(y), x), y); } +struct StatAccumulator { + // mean / RMS accumulator + double sum = 0.; + double sum2 = 0.; + double wsum = 0.; + int n = 0; + void add(float v, float w = 1.) + { + auto c = v * w; + sum += c; + sum2 += c * v; + wsum += w; + n++; + } + double getMean() const { return wsum > 0. ? sum / wsum : 0.; } + bool getMeanRMS2(double& mean, double& rms2) const + { + if (!wsum) { + mean = rms2 = 0; + return false; + } + auto wi = 1. / wsum; + mean = sum * wi; + rms2 = sum2 * wi - mean * mean; + return true; + } + bool getMeanRMS2(float& mean, float& rms2) const + { + if (!wsum) { + mean = rms2 = 0; + return false; + } + auto wi = 1. / wsum; + mean = sum * wi; + rms2 = sum2 * wi - mean * mean; + return true; + } + StatAccumulator& operator+=(const StatAccumulator& other) + { + sum += other.sum; + sum2 += other.sum2; + wsum += other.wsum; + return *this; + } + + StatAccumulator operator+(const StatAccumulator& other) const + { + StatAccumulator res = *this; + res += other; + return res; + } + + void clear() + { + sum = sum2 = wsum = 0.; + n = 0; + } +}; + } // namespace utils //} } // namespace o2 From d692d1702ef286e2cc5273d2f2502fc4318f87c6 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 26 Jul 2020 19:22:43 +0200 Subject: [PATCH 0411/1751] Primary vertex finder + related changes --- .../ReconstructionDataFormats/Vertex.h | 5 +- .../src/ReconstructionDataFormatsLinkDef.h | 4 +- DataFormats/Reconstruction/src/Vertex.cxx | 15 +- .../Reconstruction/test/testVertex.cxx | 2 +- .../common/src/CommonDataFormatLinkDef.h | 4 +- Detectors/Vertexing/CMakeLists.txt | 9 +- .../include/DetectorsVertexing/PVertexer.h | 156 +++++ .../DetectorsVertexing/PVertexerHelpers.h | 304 +++++++++ .../DetectorsVertexing/PVertexerParams.h | 52 ++ .../Vertexing/src/DetectorsVertexingLinkDef.h | 4 + Detectors/Vertexing/src/PVertexer.cxx | 640 ++++++++++++++++++ Detectors/Vertexing/src/PVertexerHelpers.cxx | 27 + Detectors/Vertexing/src/PVertexerParams.cxx | 17 + 13 files changed, 1229 insertions(+), 10 deletions(-) create mode 100644 Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h create mode 100644 Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h create mode 100644 Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h create mode 100644 Detectors/Vertexing/src/PVertexer.cxx create mode 100644 Detectors/Vertexing/src/PVertexerHelpers.cxx create mode 100644 Detectors/Vertexing/src/PVertexerParams.cxx diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h index c723e26778f32..858df1847351c 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h @@ -46,6 +46,7 @@ class VertexBase #ifndef ALIGPU_GPUCODE void print() const; + std::string asString() const; #endif // getting the cartesian coordinates and errors @@ -123,6 +124,7 @@ class Vertex : public VertexBase ushort getNContributors() const { return mNContributors; } void setNContributors(ushort v) { mNContributors = v; } + void addContributor() { mNContributors++; } ushort getBits() const { return mBits; } bool isBitSet(int bit) const { return mBits & (FlagsMask & (0x1 << bit)); } @@ -153,7 +155,8 @@ template <typename Stamp> inline std::ostream& operator<<(std::ostream& os, const o2::dataformats::Vertex<Stamp>& v) { // stream itself - os << (const VertexBase&)v << "\n NCont: " << v.getNContributors() << " Chi2: " << v.getChi2() << " TimeStamp: " << v.getTimeStamp(); + os << (const VertexBase&)v << " " + << "NCont: " << v.getNContributors() << " Chi2: " << v.getChi2() << " TimeStamp: " << v.getTimeStamp(); return os; } diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index b617c8913a0e9..bdf11877fafa0 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -34,8 +34,10 @@ #pragma link C++ class o2::dataformats::VertexBase + ; #pragma link C++ class o2::dataformats::Vertex < int> + ; #pragma link C++ class o2::dataformats::Vertex < o2::dataformats::TimeStamp < int>> + ; -#pragma link C++ class o2::dataformats::Vertex < o2::dataformats::TimeStampWithError < double, double>> + ; +#pragma link C++ class o2::dataformats::Vertex < o2::dataformats::TimeStampWithError < float, float>> + ; + #pragma link C++ class std::vector < o2::dataformats::Vertex < o2::dataformats::TimeStamp < int>>> + ; +#pragma link C++ class std::vector < o2::dataformats::Vertex < o2::dataformats::TimeStampWithError < float, float>>> + ; #pragma link C++ class o2::dataformats::DCA + ; diff --git a/DataFormats/Reconstruction/src/Vertex.cxx b/DataFormats/Reconstruction/src/Vertex.cxx index c35c2e395c322..b6165566e8aa1 100644 --- a/DataFormats/Reconstruction/src/Vertex.cxx +++ b/DataFormats/Reconstruction/src/Vertex.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "ReconstructionDataFormats/Vertex.h" +#include <fmt/printf.h> #include <iostream> namespace o2 @@ -17,14 +18,17 @@ namespace dataformats { #ifndef ALIGPU_GPUCODE + +std::string VertexBase::asString() const +{ + return fmt::format("Vtx {{{:+.4e},{:+.4e},{:+.4e}}} Cov.:{{{{{:.3e}..}},{{{:.3e},{:.3e}..}},{{{:.3e},{:.3e},{:.3e}}}}}", + mPos.X(), mPos.Y(), mPos.Z(), mCov[0], mCov[1], mCov[2], mCov[3], mCov[4], mCov[5]); +} + std::ostream& operator<<(std::ostream& os, const o2::dataformats::VertexBase& v) { // stream itself - os << std::scientific << "Vertex X: " << v.getX() << " Y: " << v.getY() << " Z: " << v.getZ() - << " Cov.mat:\n" - << v.getSigmaX2() << '\n' - << v.getSigmaXY() << ' ' << v.getSigmaY2() << '\n' - << v.getSigmaXZ() << ' ' << v.getSigmaYZ() << ' ' << v.getSigmaZ2() << '\n'; + os << v.asString(); return os; } @@ -32,6 +36,7 @@ void VertexBase::print() const { std::cout << *this << std::endl; } + #endif } // namespace dataformats diff --git a/DataFormats/Reconstruction/test/testVertex.cxx b/DataFormats/Reconstruction/test/testVertex.cxx index d65b6adeb509e..94c7066d3c0f9 100644 --- a/DataFormats/Reconstruction/test/testVertex.cxx +++ b/DataFormats/Reconstruction/test/testVertex.cxx @@ -19,7 +19,7 @@ namespace o2 { -using myTS = o2::dataformats::TimeStampWithError<double, double>; +using myTS = o2::dataformats::TimeStampWithError<float, float>; using myVtx = o2::dataformats::Vertex<myTS>; // basic Vertex tests diff --git a/DataFormats/common/src/CommonDataFormatLinkDef.h b/DataFormats/common/src/CommonDataFormatLinkDef.h index 6119655bfc723..269fb2c5433b2 100644 --- a/DataFormats/common/src/CommonDataFormatLinkDef.h +++ b/DataFormats/common/src/CommonDataFormatLinkDef.h @@ -38,7 +38,9 @@ #pragma link C++ class o2::dataformats::RangeRefComp < 4> + ; // reference to a set with 15 entries max (ITS clusters) #pragma link C++ class o2::dataformats::RangeRefComp < 5> + ; // reference to a set with 15 entries max (ZDC BCData) #pragma link C++ class o2::dataformats::RangeRefComp < 6> + ; // reference to a set with 63 entries max (FV0 BCData) -#pragma link C++ class o2::dataformats::RangeRefComp < 8> + ; // +#pragma link C++ class o2::dataformats::RangeRefComp < 8> + ; // + +#pragma link C++ class std::vector < o2::dataformats::RangeReference < int, int>> + ; #pragma link C++ class o2::InteractionRecord + ; #pragma link C++ class o2::InteractionTimeRecord + ; diff --git a/Detectors/Vertexing/CMakeLists.txt b/Detectors/Vertexing/CMakeLists.txt index 85103ac22c8d0..a79cab48e5c46 100644 --- a/Detectors/Vertexing/CMakeLists.txt +++ b/Detectors/Vertexing/CMakeLists.txt @@ -10,12 +10,19 @@ o2_add_library(DetectorsVertexing SOURCES src/DCAFitterN.cxx + src/PVertexer.cxx + src/PVertexerHelpers.cxx + src/PVertexerParams.cxx PUBLIC_LINK_LIBRARIES ROOT::Core O2::CommonUtils - O2::ReconstructionDataFormats) + O2::ReconstructionDataFormats + O2::SimulationDataFormat + ms_gsl::ms_gsl) o2_target_root_dictionary(DetectorsVertexing HEADERS include/DetectorsVertexing/HelixHelper.h + include/DetectorsVertexing/PVertexer.h + include/DetectorsVertexing/PVertexerHelpers.h include/DetectorsVertexing/DCAFitterN.h) o2_add_test( diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h new file mode 100644 index 0000000000000..51d0643da3784 --- /dev/null +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -0,0 +1,156 @@ +// 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 PVertexer.h +/// \brief Primary vertex finder +/// \author ruben.shahoyan@cern.ch + +#ifndef O2_PVERTEXER_H +#define O2_PVERTEXER_H + +#include <array> +#include "CommonDataFormat/TimeStamp.h" +#include "CommonDataFormat/RangeReference.h" +#include "SimulationDataFormat/MCEventLabel.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "MathUtils/Utils.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/Vertex.h" +#include "DetectorsVertexing/PVertexerHelpers.h" +#include "DetectorsVertexing/PVertexerParams.h" +#include "gsl/span" + +namespace o2 +{ +namespace vertexing +{ + +namespace o2d = o2::dataformats; + +class VertexSeed; +class TrackVF; +class VertexingInput; +class SeedHisto; +class TimeCluster; + +class PVertexer +{ + + public: + enum class FitStatus : int { Failure, + PoolEmpty, + NotEnoughTracks, + IterateFurther, + OK }; + + using TimeEst = o2::dataformats::TimeStampWithError<float, float>; + using Vertex = o2::dataformats::Vertex<TimeEst>; + using V2TRef = o2::dataformats::RangeReference<int, int>; + + void init(); + int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, + gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx); + int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); + static void createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, + const std::vector<Vertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, + std::vector<o2::MCEventLabel>& lblVtx); + bool findVertex(const VertexingInput& input, Vertex& vtx); + + void setTukey(float t) + { + mTukey2I = t > 0.f ? 1.f / (t * t) : 1.f / (PVertexerParams::kDefTukey * PVertexerParams::kDefTukey); + } + float getTukey() const; + + void finalizeVertex(const VertexingInput& input, const Vertex& vtx, std::vector<Vertex>& vertices, std::vector<V2TRef>& v2tRefs, std::vector<int>& vertexTrackIDs, SeedHisto& histo); + + void setBz(float bz) { mBz = bz; } + + auto& getTracksPool() const { return mTracksPool; } + auto& getTimeClusters() const { return mTimesClusters; } + auto& getSortedTrackIndices() const { return mSortedTrackID; } + + auto& getMeanVertex() const { return mMeanVertex; } + void setMeanVertex(const o2d::VertexBase& v) + { + mMeanVertex = v; + initMeanVertexConstraint(); + } + + float estimateScale2() + { + float minrange = std::min(mParams->zHistoBinSize, mParams->minZSeedRange); + auto sc = mParams->zHistoBinSize * mParams->zHistoBinSize * mTukey2I / (mStatZErr.getMean() * mStatZErr.getMean()); + return sc; + } + + private: + FitStatus fitIteration(const VertexingInput& input, VertexSeed& vtxSeed); + void accountTrack(TrackVF& trc, VertexSeed& vtxSeed) const; + bool solveVertex(VertexSeed& vtxSeed) const; + FitStatus evalIterations(VertexSeed& vtxSeed, Vertex& vtx) const; + TimeEst timeEstimate(const VertexingInput& input) const; + float findZSeedHistoPeak() const; + void initMeanVertexConstraint(); + void applyConstraint(VertexSeed& vtxSeed) const; + bool upscaleSigma(VertexSeed& vtxSeed) const; + void createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC); + void clusterizeTimeBruteForce(float margin = 0.1, float cut = 25); + void clusterizeTime(float binSize = 0.1, float maxTDist = 0.6); + int findVertices(const VertexingInput& input, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); + + o2d::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; + std::array<float, 3> mXYConstraintInvErr = {1.0f, 0.f, 1.0f}; ///< nominal vertex constraint inverted errors^2 + // + o2::utils::StatAccumulator mStatZErr; + o2::utils::StatAccumulator mStatTErr; + std::vector<TrackVF> mTracksPool; ///< tracks in internal representation used for vertexing + std::vector<int> mSortedTrackID; ///< indices of tracks sorted in time + std::vector<TimeCluster> mTimesClusters; ///< set of time clusters + float mBz = 0.; ///< mag.field at beam line + + ///========== Parameters to be set externally, e.g. from CCDB ==================== + const PVertexerParams* mParams = nullptr; + float mTukey2I = 0; ///< 1./[Tukey parameter]^2 + static constexpr float kDefTukey = 5.0f; ///< def.value for tukey constant + static constexpr float kHugeF = 1.e12; ///< very large float + static constexpr float kAlmost0F = 1e-12; ///< tiny float + static constexpr double kAlmost0D = 1e-16; ///< tiny double + + ClassDefNV(PVertexer, 1); +}; + +//___________________________________________________________________ +inline void PVertexer::applyConstraint(VertexSeed& vtxSeed) const +{ + // impose meanVertex constraint, i.e. account terms + // (V_i-Constrain_i)^2/sig2constr_i for i=X,Y in the fit chi2 definition + vtxSeed.cxx += mXYConstraintInvErr[0]; + vtxSeed.cyy += mXYConstraintInvErr[1]; + vtxSeed.cx0 += mXYConstraintInvErr[0] * mMeanVertex.getX(); + vtxSeed.cy0 += mXYConstraintInvErr[1] * mMeanVertex.getY(); +} + +//___________________________________________________________________ +inline bool PVertexer::upscaleSigma(VertexSeed& vtxSeed) const +{ + // scale upward the scaleSigma2 if needes + if (vtxSeed.scaleSigma2 < mParams->maxScale2) { + auto s = vtxSeed.scaleSigma2 * mParams->upscaleFactor; + vtxSeed.setScale(s > mParams->maxScale2 ? mParams->maxScale2 : s, mTukey2I); + return true; + } + return false; +} + +} // namespace vertexing +} // namespace o2 +#endif diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h new file mode 100644 index 0000000000000..8db973eeb9c81 --- /dev/null +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h @@ -0,0 +1,304 @@ +// 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 PVertexerHelpers.h +/// \brief Primary vertex finder helper classes +/// \author ruben.shahoyan@cern.ch + +#ifndef O2_PVERTEXER_HELPERS_H +#define O2_PVERTEXER_HELPERS_H + +#include "gsl/span" +#include "ReconstructionDataFormats/Vertex.h" +#include "ReconstructionDataFormats/Track.h" +#include "CommonDataFormat/TimeStamp.h" +#include "CommonDataFormat/RangeReference.h" + +namespace o2 +{ +namespace vertexing +{ + +using TimeEst = o2::dataformats::TimeStampWithError<float, float>; +using Vertex = o2::dataformats::Vertex<TimeEst>; +using V2TRef = o2::dataformats::RangeReference<int, int>; + +///< weights and scaling params for current vertex +struct VertexSeed : public Vertex { + double wghSum = 0.; // sum of tracks weights + double wghChi2 = 0.; // sum of tracks weighted chi2's + double tMeanAcc = 0.; // sum of track times * inv.err^2 + double tMeanAccErr = 0.; // some of tracks times inv.err^2 + double cxx = 0., cyy = 0., czz = 0., cxy = 0., cxz = 0., cyz = 0., cx0 = 0., cy0 = 0., cz0 = 0.; // elements of lin.equation matrix + float scaleSigma2 = 1.; // scaling parameter on top of Tukey param + float scaleSigma2Prev = 1.; + float maxScaleSigma2Tested = 0.; + float scaleSig2ITuk2I = 0; // inverse squared Tukey parameter scaled by scaleSigma2 + int nScaleSlowConvergence = 0; + int nScaleIncrease = 0; + int nIterations = 0; + bool useConstraint = true; + bool fillErrors = true; + + void setScale(float scale2, float tukey2I) + { + scaleSigma2Prev = scaleSigma2; + scaleSigma2 = scale2; + scaleSig2ITuk2I = tukey2I / scale2; + } + + void resetForNewIteration() + { + setNContributors(0); + //setTimeStamp({0., 0.}); + wghSum = 0; + wghChi2 = 0; + tMeanAcc = 0; + tMeanAccErr = 0; + cxx = cyy = czz = cxy = cxz = cyz = cx0 = cy0 = cz0 = 0.; + } + + VertexSeed() = default; + VertexSeed(const Vertex& vtx, bool _constraint, bool _errors) + : Vertex(vtx), useConstraint(_constraint), fillErrors(_errors) {} + + void print() const; +}; + +struct TrackVF { + /** Straight track parameterization in the frame defined by alpha angle. + Assumed to be defined in the proximity to vertex, so that the + straight-line extrapolation Y=mY+mTgP*(x-mX) and Z=mZ+mTgL*(x-mX) is + precise + */ + enum { kUsed, + kNoVtx = -1, + kDiscarded = kNoVtx - 1 }; + float x; ///< reference X + float y; ///< Y at X + float z; ///< Z at X + float sig2YI; ///< YY component of inverse cov.matrix + float sig2ZI; ///< ZZ component of inverse cov.matrix + float sigYZI; ///< YZ component of inverse cov.matrix + float tgP; ///< tangent(phi) in tracking frame + float tgL; ///< tangent(lambda) + float cosAlp; ///< cos of alpha frame + float sinAlp; ///< sin of alpha frame + + TimeEst timeEst; + float wgh = 0.; ///< track weight wrt current vertex seed + uint32_t entry = 0; + int16_t bin = -1; // seeds histo bin + uint8_t srcID = 0; + uint8_t flags = 0; + int vtxID = kNoVtx; ///< assigned vertex + + // + bool canAssign() const { return wgh > 0. && vtxID == kNoVtx; } + bool canUse() const { return vtxID == kNoVtx; } + bool canUse(float zmin, float zmax) const + { + return canUse() && (z > zmin && z < zmax); + } + bool operator<(const TrackVF& trc) const { return z < trc.z; } + + float getZForXY(float vx, float vy) const + { + return z + tgL * (vx * cosAlp + vy * sinAlp - x); + } + + float getResiduals(const Vertex& vtx, float& dy, float& dz) const + { + // get residuals (Y and Z DCA in track frame) and calculate chi2 + float dx = vtx.getX() * cosAlp + vtx.getY() * sinAlp - x; // VX rotated to track frame - trackX + dy = y + tgP * dx - (-vtx.getX() * sinAlp + vtx.getY() * cosAlp); + dz = z + tgL * dx - vtx.getZ(); + return (dy * dy * sig2YI + dz * dz * sig2ZI) + 2. * dy * dz * sigYZI; + } + + TrackVF() = default; + TrackVF(const o2::track::TrackParCov& src, const TimeEst& t_est, uint32_t _entry, uint8_t _srcID) + : x(src.getX()), y(src.getY()), z(src.getZ()), tgL(src.getTgl()), tgP(src.getSnp() / std::sqrt(1. - src.getSnp()) * (1. + src.getSnp())), timeEst(t_est), entry(_entry), srcID(_srcID) + { + o2::utils::sincosf(src.getAlpha(), sinAlp, cosAlp); + auto det = src.getSigmaY2() * src.getSigmaZ2() - src.getSigmaZY() * src.getSigmaZY(); + auto detI = 1. / det; + sig2YI = src.getSigmaZ2() * detI; + sig2ZI = src.getSigmaY2() * detI; + sigYZI = -src.getSigmaZY() * detI; + } +}; + +struct VertexingInput { + gsl::span<TrackVF> tracks; + gsl::span<int> idRange; + TimeEst timeEst{0, -1.}; // negative error means don't use time info + float scaleSigma2 = 10; + bool useConstraint = false; + bool fillErrors = true; +}; + +struct SeedHisto { + float range = 20; + float binSize = 0.5; + float binSizeInv = 0.; + int nFilled = 0; + std::vector<int> data; + + SeedHisto() = delete; + SeedHisto(float _range = 20., float _binsize = 0.5) : range(_range), binSize(_binsize) + { + auto zr = 2 * range; + int nzb = zr / binSize; + if (nzb * binSize < zr - 1e-9) { + nzb++; + } + binSizeInv = 1. / binSize; + range = nzb * binSize / 2.; + data.resize(nzb); + } + + int size() const { return data.size(); } + + void fill(float z) + { + incrementBin(findBin(z)); + } + + void incrementBin(int bin) + { + data[bin]++; + nFilled++; + } + + void decrementBin(int bin) + { + data[bin]--; + nFilled--; + } + + int findBin(float z) + { + auto d = z + range; + if (d < 0.) { + return 0; + } + uint32_t n = d * binSizeInv; + return n < data.size() ? n : data.size() - 1; + } + + int findHighestPeakBin() const + { + if (nFilled < 2) { + return -1; + } + int n = data.size(), maxBin = -1, maxv = 0; + for (int i = 0; i < n; i++) { + if (data[i] > maxv) { + maxv = data[(maxBin = i)]; + } + } + return maxBin; + } + + bool isValidBin(int ib) const + { + return static_cast<uint32_t>(ib) < data.size(); + } + + float getBinCenter(int ib) const + { + return (ib + 0.5) * binSize - range; // no check for being in the range!!! + } + + void discardBin(int ib) + { // no check for being in the range!!! + nFilled -= data[ib]; + data[ib] = 0; + } +}; + +struct TimeCluster { + TimeEst timeEst; + int first = -1; + int last = -1; + int count = 0; + + void clear() + { + first = last = -1; + count = 0; + } + + void addTrack(int i, const TimeEst& trcT) + { + auto trcTErr2 = trcT.getTimeStampError() * trcT.getTimeStampError(); + auto trcTErr2Inv = 1. / trcTErr2; + if (first < 0) { + first = last = i; + timeEst.setTimeStamp(trcT.getTimeStamp()); + timeEst.setTimeStampError(trcT.getTimeStampError()); + } else { + auto vtxTErr2Inv = 1. / (timeEst.getTimeStampError() * timeEst.getTimeStampError()); + auto vtxTErr2UpdInv = trcTErr2Inv + vtxTErr2Inv; + auto vtxTErr2Upd = 1. / vtxTErr2UpdInv; + timeEst.setTimeStamp((timeEst.getTimeStamp() * vtxTErr2Inv + trcT.getTimeStamp() * trcTErr2Inv) * vtxTErr2Upd); + timeEst.setTimeStampError(std::sqrt(vtxTErr2Upd)); + if (i > last) { + last = i; + } + } + count++; + } + + bool isCompatible(const TimeEst& c, float margin, float cut) const + { + if (first < 0) { + return true; + } + float dt = timeEst.getTimeStamp() - c.getTimeStamp(); + if (c.getTimeStampError() && timeEst.getTimeStampError()) { + float trcTErr2 = c.getTimeStampError() * c.getTimeStampError(); + float err = trcTErr2 + timeEst.getTimeStampError() + margin; + return dt * dt / err < cut; + } else { + return std::abs(dt) < cut; + } + } + + void merge(TimeCluster& c) + { + if (c.first < last) { + first = c.first; + } else { + last = c.last; + } + if (timeEst.getTimeStampError() && c.timeEst.getTimeStampError()) { // weighted average + auto cTErr2 = c.timeEst.getTimeStampError() * c.timeEst.getTimeStampError(); + auto cTErr2Inv = 1. / cTErr2; + + auto tErr2 = timeEst.getTimeStampError(); + auto tErr2Inv = 1. / (tErr2 * tErr2); + auto tErr2UpdInv = cTErr2Inv + tErr2Inv; + auto tErr2Upd = 1. / tErr2UpdInv; + timeEst.setTimeStamp((timeEst.getTimeStamp() * tErr2Inv + c.timeEst.getTimeStamp() * cTErr2Inv) * tErr2Upd); + timeEst.setTimeStampError(std::sqrt(tErr2Upd)); + } else { + timeEst.setTimeStamp((timeEst.getTimeStamp() * count + c.timeEst.getTimeStamp() * c.count) / (count + c.count)); + count += c.count; + c.count = 0; + } + } +}; + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h new file mode 100644 index 0000000000000..f86320c452f23 --- /dev/null +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -0,0 +1,52 @@ +// 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 ruben.shahoyan@cern.ch + +#ifndef ALICEO2_PVERTEXER_PARAMS_H +#define ALICEO2_PVERTEXER_PARAMS_H + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace vertexing +{ + +// There are configurable params for Primary Vertexer +struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParams> { + static constexpr float kDefTukey = 5.0f; ///< def.value for tukey constant + + // parameters + float minZSeedRange = 0.5; ///< min proximity of Zseed which should be covered by 1st iteration + float zHistoRange = 20.; ///< +-range of the Zseed histo + float zHistoBinSize = 0.5; ///< size of the Zseed histo bin + float tukey = kDefTukey; ///< 1./[Tukey parameter]^2 + float minScale2 = 1.; ///< min slaling factor^2 + float acceptableScale2 = 4.; ///< if below this factor, try to refit with minScale2 + float maxScale2 = 1.e6; ///< max slaling factor^2 + float upscaleFactor = 9.; ///< factor for upscaling if not candidate is found + float slowConvergenceFactor = 0.5; ///< consider convergence as slow if ratio new/old scale2 exceeds it + // stopping condition params + float maxChi2Mean = 10.; ///< max mean chi2 of vertex to accept + int minTracksPerVtx = 2; ///< min N tracks per vertex + int maxIterations = 20; ///< max iterations per vertex fit + int maxNScaleIncreased = 2; ///< max number of scaling-non-decreasing iterations + int maxNScaleSlowConvergence = 3; ///< max number of weak scaling decrease iterations + bool useTimeInChi2 = true; ///< use track-vertex time difference in chi2 calculation + + O2ParamDef(PVertexerParams, "pvertexer"); +}; + +} // namespace vertexing +} // end namespace o2 + +#endif diff --git a/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h b/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h index 94c2ba3af839e..331aad662a1c4 100644 --- a/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h +++ b/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h @@ -19,6 +19,10 @@ // this aliase are defined in the DCAFitterN.h as o2::vertexing::DCAFitterN<3,o2::track::TrackParCov> #pragma link C++ class o2::vertexing::DCAFitter3 + ; +#pragma link C++ class o2::vertexing::PVertexer + ; +#pragma link C++ class o2::vertexing::PVertexerParams + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::vertexing::PVertexerParams> + ; + #pragma link C++ class o2::track::TrackAuxPar + ; #pragma link C++ class o2::track::CrossInfo + ; diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx new file mode 100644 index 0000000000000..815f70c443476 --- /dev/null +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -0,0 +1,640 @@ +// 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 PVertexer.cxx +/// \brief Primary vertex finder +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/PVertexer.h" +#include "ReconstructionDataFormats/DCA.h" +#include "Math/SMatrix.h" +#include "Math/SVector.h" +#include <numeric> +#include <unordered_map> + +using namespace o2::vertexing; + +constexpr float PVertexer::kAlmost0F; +constexpr double PVertexer::kAlmost0D; +constexpr float PVertexer::kHugeF; + +//___________________________________________________________________ +int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) +{ + createTracksPool(tracksITSTPC); + + //clusterizeTimeBruteForce(); + clusterizeTime(); + + std::vector<Vertex> verticesLoc; + std::vector<int> vertexTrackIDsLoc; + std::vector<V2TRef> v2tRefsLoc; + + for (auto tc : mTimesClusters) { + VertexingInput inp; + inp.idRange = gsl::span<int>((int*)&mSortedTrackID[tc.first], tc.count); + inp.scaleSigma2 = 3. * estimateScale2(); + inp.timeEst = tc.timeEst; + findVertices(inp, verticesLoc, vertexTrackIDsLoc, v2tRefsLoc); + } + + // sort in time + std::vector<int> vtTimeSortID(verticesLoc.size()); + std::iota(vtTimeSortID.begin(), vtTimeSortID.end(), 0); + std::sort(vtTimeSortID.begin(), vtTimeSortID.end(), [&verticesLoc](int i, int j) { + return verticesLoc[i].getTimeStamp().getTimeStamp() < verticesLoc[j].getTimeStamp().getTimeStamp(); + }); + + vertices.clear(); + v2tRefs.clear(); + vertexTrackIDs.clear(); + vertices.reserve(verticesLoc.size()); + v2tRefs.reserve(v2tRefsLoc.size()); + vertexTrackIDs.resize(vertexTrackIDsLoc.size()); + + int trCopied = 0, count = 0; + for (auto i : vtTimeSortID) { + vertices.push_back(verticesLoc[i]); + memcpy(&vertexTrackIDs[trCopied], &vertexTrackIDsLoc[v2tRefsLoc[i].getFirstEntry()], v2tRefsLoc[i].getEntries() * sizeof(int)); + v2tRefs.emplace_back(trCopied, v2tRefsLoc[i].getEntries()); + trCopied += v2tRefsLoc[i].getEntries(); + LOG(DEBUG) << "#" << count++ << " " << vertices.back() << " | " << v2tRefs.back().getEntries() << " indices from " << v2tRefs.back().getFirstEntry(); // RS REM + } + + return vertices.size(); +} + +//___________________________________________________________________ +int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, + gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx) +{ + auto nv = process(tracksITSTPC, vertices, vertexTrackIDs, v2tRefs); + if (lblITS.size() && lblTPC.size()) { + createMCLabels(lblITS, lblTPC, vertices, vertexTrackIDs, v2tRefs, lblVtx); + } + return nv; +} + +//______________________________________________ +int PVertexer::findVertices(const VertexingInput& input, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) +{ + // find vertices using tracks with indices (sorted in time) from idRange from "tracks" pool. The pool may containt arbitrary number of tracks, + // only those which are in the idRange and have canUse()==true, will be used. + // Results are placed in vertices and v2tRefs vectors + int nfound = 0, ntr = input.idRange.size(); + if (ntr < mParams->minTracksPerVtx) { + return nfound; + } + // + SeedHisto seedHisto(mParams->zHistoRange, mParams->zHistoBinSize); + + for (int i : input.idRange) { + if (mTracksPool[i].canUse()) { + mTracksPool[i].bin = seedHisto.findBin(mTracksPool[i].getZForXY(mMeanVertex.getX(), mMeanVertex.getY())); + seedHisto.incrementBin(mTracksPool[i].bin); + } + } + if (seedHisto.nFilled < mParams->minTracksPerVtx) { + return nfound; + } + + while (1) { + int peakBin = seedHisto.findHighestPeakBin(); // find next seed + if (!seedHisto.isValidBin(peakBin)) { + break; + } + float zv = seedHisto.getBinCenter(peakBin); + LOG(DEBUG) << "Seeding with Z=" << zv << " bin " << peakBin; + Vertex vtx; + vtx.setXYZ(mMeanVertex.getX(), mMeanVertex.getY(), zv); + vtx.setTimeStamp(input.timeEst); + if (findVertex(input, vtx)) { + finalizeVertex(input, vtx, vertices, v2tRefs, vertexTrackIDs, seedHisto); + nfound++; + } else { // suppress failed seeding bin and its proximities + auto delta = std::sqrt(vtx.getChi2()) * mStatZErr.getMean() * getTukey(); // largest scale used will be transferred as chi2 + int proximity = delta * seedHisto.binSizeInv; + int bmin = std::max(0, peakBin - proximity), bmax = std::min(peakBin + proximity + 1, seedHisto.size()); + LOG(DEBUG) << "suppress bins for delta=" << delta << " (" << std::sqrt(vtx.getChi2()) << "*" << mStatZErr.getMean() << "*" << getTukey() << ")" + << " bins " << bmin << " : " << bmax - 1; + for (int i = bmin; i < bmax; i++) { + seedHisto.discardBin(i); + } + } + } + return nfound; +} + +//______________________________________________ +bool PVertexer::findVertex(const VertexingInput& input, Vertex& vtx) +{ + // fit vertex taking provided vertex as a seed + // tracks pool may contain arbitrary number of tracks, only those which are in + // the idRange (indices of tracks sorted in time) will be used. + + VertexSeed vtxSeed(vtx, input.useConstraint, input.fillErrors); + vtxSeed.setScale(input.scaleSigma2, mTukey2I); + vtxSeed.scaleSigma2Prev = input.scaleSigma2; + // vtxSeed.setTimeStamp( timeEstimate(input) ); + LOG(DEBUG) << "Start time guess: " << vtxSeed.getTimeStamp(); + vtx.setChi2(1.e30); + // + FitStatus result = FitStatus::IterateFurther; + bool found = false; + while (result == FitStatus::IterateFurther) { + vtxSeed.resetForNewIteration(); + vtxSeed.nIterations++; + LOG(DEBUG) << "iter " << vtxSeed.nIterations << " with scale=" << vtxSeed.scaleSigma2 << " prevScale=" << vtxSeed.scaleSigma2Prev; + result = fitIteration(input, vtxSeed); + + if (result == FitStatus::OK) { + result = evalIterations(vtxSeed, vtx); + } else if (result == FitStatus::NotEnoughTracks) { + if (vtxSeed.nIterations <= mParams->maxIterations && upscaleSigma(vtxSeed)) { + LOG(DEBUG) << "Upscaling scale to " << vtxSeed.scaleSigma2; + result = FitStatus::IterateFurther; + continue; // redo with stronger rescaling + } else { + break; + } + } else if (result == FitStatus::PoolEmpty || result == FitStatus::Failure) { + break; + } else { + LOG(FATAL) << "Unknown fit status " << int(result); + } + } + LOG(DEBUG) << "Stopped with scale=" << vtxSeed.scaleSigma2 << " prevScale=" << vtxSeed.scaleSigma2Prev << " result = " << int(result); + + if (result != FitStatus::OK) { + vtx.setChi2(vtxSeed.maxScaleSigma2Tested); + return false; + } else { + return true; + } +} + +//___________________________________________________________________ +PVertexer::FitStatus PVertexer::fitIteration(const VertexingInput& input, VertexSeed& vtxSeed) +{ + int nTested = 0; + for (int i : input.idRange) { + if (mTracksPool[i].canUse()) { + nTested++; + accountTrack(mTracksPool[i], vtxSeed); + } + } + vtxSeed.maxScaleSigma2Tested = vtxSeed.scaleSigma2; + if (vtxSeed.getNContributors() < mParams->minTracksPerVtx) { + return nTested < mParams->minTracksPerVtx ? FitStatus::PoolEmpty : FitStatus::NotEnoughTracks; + } + if (vtxSeed.useConstraint) { + applyConstraint(vtxSeed); + } + if (!solveVertex(vtxSeed)) { + return FitStatus::Failure; + } + return FitStatus::OK; +} + +//___________________________________________________________________ +void PVertexer::accountTrack(TrackVF& trc, VertexSeed& vtxSeed) const +{ + // deltas defined as track - vertex + float dt, trErr2I = 0, dy, dz, chi2T = trc.getResiduals(vtxSeed, dy, dz); // track-vertex residuals and chi2 + auto& timeV = vtxSeed.getTimeStamp(); + auto& timeT = trc.timeEst; + float ndff = 1. / 2; + bool noTime = false; + if (timeV.getTimeStampError() < 0.) { + noTime = true; + } else { + dt = timeT.getTimeStamp() - timeV.getTimeStamp(); + trErr2I = 1. / (timeT.getTimeStampError() * timeT.getTimeStampError()); + if (mParams->useTimeInChi2) { + chi2T += dt * dt * trErr2I; + ndff = 1. / 3.; + } + } + chi2T *= ndff; + float wghT = (1.f - chi2T * vtxSeed.scaleSig2ITuk2I); // weighted distance to vertex + if (wghT < kAlmost0F) { + trc.wgh = 0.f; + return; + } + float syyI(trc.sig2YI), szzI(trc.sig2ZI), syzI(trc.sigYZI); + + // + vtxSeed.wghSum += wghT; + vtxSeed.wghChi2 += wghT * chi2T; + // + syyI *= wghT; + syzI *= wghT; + szzI *= wghT; + trc.wgh = wghT; + // + // aux variables + double tmpSP = trc.sinAlp * trc.tgP, tmpCP = trc.cosAlp * trc.tgP, + tmpSC = trc.sinAlp + tmpCP, tmpCS = -trc.cosAlp + tmpSP, + tmpCL = trc.cosAlp * trc.tgL, tmpSL = trc.sinAlp * trc.tgL, + tmpYXP = trc.y - trc.tgP * trc.x, tmpZXL = trc.z - trc.tgL * trc.x, + tmpCLzz = tmpCL * szzI, tmpSLzz = tmpSL * szzI, tmpSCyz = tmpSC * syzI, + tmpCSyz = tmpCS * syzI, tmpCSyy = tmpCS * syyI, tmpSCyy = tmpSC * syyI, + tmpSLyz = tmpSL * syzI, tmpCLyz = tmpCL * syzI; + // + // symmetric matrix equation + vtxSeed.cxx += tmpCL * (tmpCLzz + tmpSCyz + tmpSCyz) + tmpSC * tmpSCyy; // dchi^2/dx/dx + vtxSeed.cxy += tmpCL * (tmpSLzz + tmpCSyz) + tmpSL * tmpSCyz + tmpSC * tmpCSyy; // dchi^2/dx/dy + vtxSeed.cxz += -trc.sinAlp * syzI - tmpCLzz - tmpCP * syzI; // dchi^2/dx/dz + vtxSeed.cx0 += -(tmpCLyz + tmpSCyy) * tmpYXP - (tmpCLzz + tmpSCyz) * tmpZXL; // RHS + // + vtxSeed.cyy += tmpSL * (tmpSLzz + tmpCSyz + tmpCSyz) + tmpCS * tmpCSyy; // dchi^2/dy/dy + vtxSeed.cyz += -(tmpCSyz + tmpSLzz); // dchi^2/dy/dz + vtxSeed.cy0 += -tmpYXP * (tmpCSyy + tmpSLyz) - tmpZXL * (tmpCSyz + tmpSLzz); // RHS + // + vtxSeed.czz += szzI; // dchi^2/dz/dz + vtxSeed.cz0 += tmpZXL * szzI + tmpYXP * syzI; // RHS + // + if (!noTime) { + trErr2I *= wghT; + vtxSeed.tMeanAcc += timeT.getTimeStamp() * trErr2I; + vtxSeed.tMeanAccErr += trErr2I; + } + vtxSeed.addContributor(); +} + +//___________________________________________________________________ +bool PVertexer::solveVertex(VertexSeed& vtxSeed) const +{ + ROOT::Math::SMatrix<double, 3, 3, ROOT::Math::MatRepSym<double, 3>> mat; + mat(0, 0) = vtxSeed.cxx; + mat(0, 1) = vtxSeed.cxy; + mat(0, 2) = vtxSeed.cxz; + mat(1, 1) = vtxSeed.cyy; + mat(1, 2) = vtxSeed.cyz; + mat(2, 2) = vtxSeed.czz; + if (!mat.InvertFast()) { + LOG(ERROR) << "Failed to invert matrix" << mat; + return false; + } + ROOT::Math::SVector<double, 3> rhs(vtxSeed.cx0, vtxSeed.cy0, vtxSeed.cz0); + auto sol = mat * rhs; + vtxSeed.setXYZ(sol(0), sol(1), sol(2)); + if (vtxSeed.fillErrors) { + vtxSeed.setCov(mat(0, 0), mat(1, 0), mat(1, 1), mat(2, 0), mat(2, 1), mat(2, 2)); + } + if (vtxSeed.tMeanAccErr > 0.) { + auto err2 = 1. / vtxSeed.tMeanAccErr; + vtxSeed.setTimeStamp({float(vtxSeed.tMeanAcc * err2), float(std::sqrt(err2))}); + } + + vtxSeed.setChi2((vtxSeed.getNContributors() - vtxSeed.wghSum) / vtxSeed.scaleSig2ITuk2I); // calculate chi^2 + auto newScale = vtxSeed.wghChi2 / vtxSeed.wghSum; + LOG(DEBUG) << "Solve: wghChi2=" << vtxSeed.wghChi2 << " wghSum=" << vtxSeed.wghSum << " -> scale= " << newScale << " old scale " << vtxSeed.scaleSigma2 << " prevScale: " << vtxSeed.scaleSigma2Prev; + //vtxSeed.print(); + vtxSeed.setScale(newScale < mParams->minScale2 ? mParams->minScale2 : newScale, mTukey2I); + return true; +} + +//___________________________________________________________________ +PVertexer::FitStatus PVertexer::evalIterations(VertexSeed& vtxSeed, Vertex& vtx) const +{ + // decide if new iteration should be done, prepare next one if needed + // if scaleSigma2 reached its lower limit stop + PVertexer::FitStatus result = PVertexer::FitStatus::IterateFurther; + + if (vtxSeed.nIterations > mParams->maxIterations) { + result = PVertexer::FitStatus::Failure; + } else if (vtxSeed.scaleSigma2Prev <= mParams->minScale2 + kAlmost0F) { + result = PVertexer::FitStatus::OK; + LOG(DEBUG) << "stop on simga :" << vtxSeed.scaleSigma2 << " prev: " << vtxSeed.scaleSigma2Prev; + } + if (fair::Logger::Logging(fair::Severity::debug)) { + auto dchi = (vtx.getChi2() - vtxSeed.getChi2()) / vtxSeed.getChi2(); + auto dx = vtxSeed.getX() - vtx.getX(), dy = vtxSeed.getY() - vtx.getY(), dz = vtxSeed.getZ() - vtx.getZ(); + auto dst = std::sqrt(dx * dx + dy * dy + dz * dz); + + LOG(DEBUG) << "dChi:" << vtx.getChi2() << "->" << vtxSeed.getChi2() << " :-> " << dchi; + LOG(DEBUG) << "dx: " << dx << " dy: " << dy << " dz: " << dz << " -> " << dst; + } + + vtx = vtxSeed; + + if (result == PVertexer::FitStatus::OK) { + auto chi2Mean = vtxSeed.getChi2() / vtxSeed.getNContributors(); + if (chi2Mean > mParams->maxChi2Mean) { + result = PVertexer::FitStatus::Failure; + LOG(DEBUG) << "Rejecting at iteration " << vtxSeed.nIterations << " and ScalePrev " << vtxSeed.scaleSigma2Prev << " with meanChi2 = " << chi2Mean; + } else { + return result; + } + } + + if (vtxSeed.scaleSigma2 > vtxSeed.scaleSigma2Prev) { + if (++vtxSeed.nScaleIncrease > mParams->maxNScaleIncreased) { + result = PVertexer::FitStatus::Failure; + LOG(DEBUG) << "Rejecting at iteration " << vtxSeed.nIterations << " with NScaleIncreased " << vtxSeed.nScaleIncrease; + } + } else if (vtxSeed.scaleSigma2 > mParams->slowConvergenceFactor * vtxSeed.scaleSigma2Prev) { + if (++vtxSeed.nScaleSlowConvergence > mParams->maxNScaleSlowConvergence) { + if (vtxSeed.scaleSigma2 < mParams->acceptableScale2) { + vtxSeed.setScale(mParams->minScale2, mTukey2I); + LOG(DEBUG) << "Forcing scale2 to " << mParams->minScale2; + result = PVertexer::FitStatus::IterateFurther; + } else { + result = PVertexer::FitStatus::Failure; + LOG(DEBUG) << "Rejecting at iteration " << vtxSeed.nIterations << " with NScaleSlowConvergence " << vtxSeed.nScaleSlowConvergence; + } + } + } else { + vtxSeed.nScaleSlowConvergence = 0; + } + + return result; +} + +//___________________________________________________________________ +void PVertexer::initMeanVertexConstraint() +{ + // set mean vertex constraint and its errors + double det = mMeanVertex.getSigmaY2() * mMeanVertex.getSigmaZ2() - mMeanVertex.getSigmaYZ() * mMeanVertex.getSigmaYZ(); + if (det <= kAlmost0D || mMeanVertex.getSigmaY2() < kAlmost0D || mMeanVertex.getSigmaZ2() < kAlmost0D) { + throw std::runtime_error(fmt::format("Singular matrix for vertex constraint: syy={:+.4e} syz={:+.4e} szz={:+.4e}", + mMeanVertex.getSigmaY2(), mMeanVertex.getSigmaYZ(), mMeanVertex.getSigmaZ2())); + } + mXYConstraintInvErr[0] = mMeanVertex.getSigmaZ2() / det; + mXYConstraintInvErr[2] = mMeanVertex.getSigmaY2() / det; + mXYConstraintInvErr[1] = -mMeanVertex.getSigmaYZ() / det; +} + +//______________________________________________ +float PVertexer::getTukey() const +{ + // convert 1/tukey^2 to tukey + return sqrtf(1. / mTukey2I); +} + +//___________________________________________________________________ +TimeEst PVertexer::timeEstimate(const VertexingInput& input) const +{ + o2::utils::StatAccumulator test; + for (int i : input.idRange) { + if (mTracksPool[i].canUse()) { + const auto& timeT = mTracksPool[i].timeEst; + auto trErr2I = 1. / (timeT.getTimeStampError() * timeT.getTimeStampError()); + test.add(timeT.getTimeStamp(), trErr2I); + } + } + if (test.wsum > 0) { + float t = 0., te2 = 0.; + test.getMeanRMS2(t, te2); + return {t, te2}; + } else { + return {0., 0.}; + } +} + +//___________________________________________________________________ +void PVertexer::init() +{ + mParams = &PVertexerParams::Instance(); + setTukey(mParams->tukey); + initMeanVertexConstraint(); +} + +//___________________________________________________________________ +void PVertexer::finalizeVertex(const VertexingInput& input, const Vertex& vtx, + std::vector<Vertex>& vertices, std::vector<V2TRef>& v2tRefs, std::vector<int>& vertexTrackIDs, + SeedHisto& histo) +{ + int lastID = vertices.size(); + vertices.emplace_back(vtx); + auto& ref = v2tRefs.emplace_back(vertexTrackIDs.size(), 0); + for (int i : input.idRange) { + if (mTracksPool[i].canAssign()) { + vertexTrackIDs.push_back(mTracksPool[i].entry); + mTracksPool[i].vtxID = lastID; + + // remove track from ZSeeds histo + histo.decrementBin(mTracksPool[i].bin); + } + } + ref.setEntries(vertexTrackIDs.size() - ref.getFirstEntry()); +} + +//___________________________________________________________________ +void PVertexer::createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC) +{ + // create pull of all candidate tracks in a global array ordered in time + mTracksPool.clear(); + mSortedTrackID.clear(); + + auto ntGlo = tracksITSTPC.size(); + mTracksPool.reserve(ntGlo); + // check all containers + float vtxErr2 = 0.5 * (mMeanVertex.getSigmaX2() + mMeanVertex.getSigmaY2()); + float dcaToler = 1.0 + 3. * std::sqrt(vtxErr2); // RS FIXME tolerance should be a parameter + float pullIniCut = 9.; // RS FIXME pullIniCut should be a parameter + o2d::DCA dca; + + for (uint32_t i = 0; i < ntGlo; i++) { + o2::track::TrackParCov trc = tracksITSTPC[i]; + if (!trc.propagateToDCA(mMeanVertex, mBz, &dca, dcaToler) || + dca.getY() * dca.getY() / (dca.getSigmaY2() + vtxErr2) > pullIniCut) { + continue; + } + auto& tvf = mTracksPool.emplace_back(trc, tracksITSTPC[i].getTimeMUS(), i, 0); + mStatZErr.add(std::sqrt(trc.getSigmaZ2())); + mStatTErr.add(tvf.timeEst.getTimeStampError()); + } + // TODO: try to narrow timestamps using tof times + float zerrMean, zerrRMS; + mStatZErr.getMeanRMS2(zerrMean, zerrRMS); + + float terrMean, terrRMS; + mStatTErr.getMeanRMS2(terrMean, terrRMS); + + if (mTracksPool.empty()) { + return; + } + // + mSortedTrackID.resize(mTracksPool.size()); + std::iota(mSortedTrackID.begin(), mSortedTrackID.end(), 0); + + std::sort(mSortedTrackID.begin(), mSortedTrackID.end(), [this](int i, int j) { + return this->mTracksPool[i].timeEst.getTimeStamp() < this->mTracksPool[j].timeEst.getTimeStamp(); + }); + + auto tMin = mTracksPool[mSortedTrackID.front()].timeEst.getTimeStamp(); + auto tMax = mTracksPool[mSortedTrackID.back()].timeEst.getTimeStamp(); +} + +//___________________________________________________________________ +void PVertexer::clusterizeTimeBruteForce(float margin, float cut) +{ + std::vector<TimeCluster> tclist; + mTimesClusters.clear(); + auto* vtxT = &tclist.emplace_back(); + int ntr = mSortedTrackID.size(); + for (int i = 0; i < ntr; i++) { + int icur = mSortedTrackID[i]; + const auto& trc = mTracksPool[icur]; + if (!vtxT->isCompatible(trc.timeEst, margin, cut)) { + if (vtxT->count < mParams->minTracksPerVtx) { + vtxT->clear(); + } else { + vtxT = &tclist.emplace_back(); + } + } + vtxT->addTrack(i, trc.timeEst); + } + if (tclist.back().count < mParams->minTracksPerVtx) { + tclist.pop_back(); + } + // final sort in decreasing multiplicity + std::vector<int> tcselSort(tclist.size()); + std::iota(tcselSort.begin(), tcselSort.end(), 0); + + std::sort(tcselSort.begin(), tcselSort.end(), [&tclist](int i, int j) { return tclist[i].count > tclist[j].count; }); + mTimesClusters.reserve(tcselSort.size()); + for (auto i : tcselSort) { + if (tclist[i].count >= mParams->minTracksPerVtx) { + mTimesClusters.push_back(tclist[i]); + auto& tc = mTimesClusters.back(); + // tc.print(); + } + } +} + +//___________________________________________________________________ +void PVertexer::clusterizeTime(float binSize, float maxTDist) +{ + // moving average density + std::vector<int> tclistIdx, tcselSort; + std::vector<TimeCluster> tclist; + mTimesClusters.clear(); + + int ntr = mTracksPool.size(), first = 0, last = 0, count = 1; + float tfirst = mTracksPool[mSortedTrackID[first]].timeEst.getTimeStamp(), tlast = tfirst, tMean = tfirst; + for (int i = 1; i < ntr; i++) { + if (mTracksPool[mSortedTrackID[i]].timeEst.getTimeStamp() - tfirst < binSize) { + last = i; + tlast = mTracksPool[mSortedTrackID[last]].timeEst.getTimeStamp(); + tMean += tlast; + count++; + } else { + tclist.emplace_back(TimeCluster{{tMean / count, 0.}, first, last, count}); + first = last = i; + tMean = tfirst = mTracksPool[mSortedTrackID[last]].timeEst.getTimeStamp(); + count = 1; + } + } + tMean += mTracksPool[mSortedTrackID[last]].timeEst.getTimeStamp(); + tclist.emplace_back(TimeCluster{{tMean / count, 0.}, first, last, count}); + + int ncl = tclist.size(); + tclistIdx.resize(ncl); + tcselSort.reserve(ncl); + std::iota(tclistIdx.begin(), tclistIdx.end(), 0); + std::sort(tclistIdx.begin(), tclistIdx.end(), [&tclist](int i, int j) { return tclist[i].count > tclist[j].count; }); + + for (auto it : tclistIdx) { + auto& best = tclist[it]; + if (!best.count) { + continue; // already merged + } + // check if it can absorm neighbours + int iBef = it, iAft = it; + bool merged; + do { + merged = false; + if (--iBef >= 0) { + if (tclist[iBef].count && best.isCompatible(tclist[iBef].timeEst, 0, maxTDist)) { + best.merge(tclist[iBef]); + merged = true; + } else { + iBef = -1; // don't check those before + } + } + if (++iAft < ncl) { + if (tclist[iAft].count && best.isCompatible(tclist[iAft].timeEst, 0, maxTDist)) { + best.merge(tclist[iAft]); + merged = true; + } else { + iAft = ncl; // don't check those after + } + } + } while (merged); + if (best.count > 1) { // RS FIXME + tcselSort.push_back(it); + } + } + // final sort in decreasing multiplicity + std::sort(tcselSort.begin(), tcselSort.end(), [&tclist](int i, int j) { return tclist[i].count > tclist[j].count; }); + mTimesClusters.reserve(tcselSort.size()); + for (auto i : tcselSort) { + mTimesClusters.push_back(tclist[i]); + // mTimesClusters.back().print(); + } +} + +//___________________________________________________________________ +void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, + const std::vector<Vertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, + std::vector<o2::MCEventLabel>& lblVtx) +{ + lblVtx.clear(); + int nv = vertices.size(); + if (lblITS.size() != lblITS.size() || !lblITS.size()) { + LOG(ERROR) << "labels are not provided or incorrect"; + return; + } + std::unordered_map<o2::MCEventLabel, int> labelOccurenceCorr, labelOccurenceITS; + + auto bestLbl = [](std::unordered_map<o2::MCEventLabel, int> mp, int norm) -> o2::MCEventLabel { + o2::MCEventLabel best; + int bestCount = 0; + for (auto [lbl, cnt] : mp) { + if (cnt > bestCount) { + bestCount = cnt; + best = lbl; + } + } + if (bestCount && norm) { + best.setCorrWeight(float(bestCount) / norm); + } + return best; + }; + + for (const auto& v2t : v2tRefs) { + int tref = v2t.getFirstEntry(), last = tref + v2t.getEntries(); + labelOccurenceCorr.clear(); + labelOccurenceITS.clear(); + o2::MCEventLabel winner; // unset at the moment + for (; tref < last; tref++) { + int tid = vertexTrackIDs[tref]; + const auto& lITS = lblITS[tid]; + const auto& lTPC = lblTPC[tid]; + if (!lITS.isSet() || !lTPC.isSet()) { + break; + } + if (lITS.getTrackID() == lITS.getTrackID() && lITS.getEventID() == lTPC.getEventID() && lITS.getSourceID() == lTPC.getSourceID()) { + labelOccurenceCorr[{lITS.getEventID(), lITS.getSourceID(), 0.}]++; + } else { + labelOccurenceITS[{lITS.getEventID(), lITS.getSourceID(), 0.}]++; + } + } + if (labelOccurenceCorr.size()) { + winner = bestLbl(labelOccurenceCorr, v2t.getEntries()); + } else if (labelOccurenceITS.size()) { + winner = bestLbl(labelOccurenceITS, 0); // in absence of correct matches, set the ITS only label but set its weight to 0 + } + lblVtx.push_back(winner); + } +} diff --git a/Detectors/Vertexing/src/PVertexerHelpers.cxx b/Detectors/Vertexing/src/PVertexerHelpers.cxx new file mode 100644 index 0000000000000..dc6a8d0f04616 --- /dev/null +++ b/Detectors/Vertexing/src/PVertexerHelpers.cxx @@ -0,0 +1,27 @@ +// 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 PVertexerHelpers.cxx +/// \brief Primary vertex finder helper classes +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/PVertexerHelpers.h" + +using namespace o2::vertexing; + +void VertexSeed::print() const +{ + auto terr2 = tMeanAccErr > 0 ? 1. / tMeanAccErr : 0.; + LOGF(INFO, "VtxSeed: Scale: %+e ScalePrev: %+e |NScaleIncreased: %d NSlowDecrease: %d| WChi2: %e WSum: %e | TMean: %e TMeanE: %e\n", + scaleSigma2, scaleSigma2Prev, nScaleIncrease, nScaleSlowConvergence, wghChi2, wghSum, tMeanAcc * terr2, std::sqrt(terr2)); + double dZP, rmsZP, dZN, rmsZN, dTP, rmsTP, dTN, rmsTN; + double dZ, rmsZ, dT, rmsT; + Vertex::print(); +} diff --git a/Detectors/Vertexing/src/PVertexerParams.cxx b/Detectors/Vertexing/src/PVertexerParams.cxx new file mode 100644 index 0000000000000..d18d70057f310 --- /dev/null +++ b/Detectors/Vertexing/src/PVertexerParams.cxx @@ -0,0 +1,17 @@ +// 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 PVertexerParams.cxx +/// \brief Configurable params for primary vertexer +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/PVertexerParams.h" + +O2ParamImpl(o2::vertexing::PVertexerParams); From 8e4ac86dfe6941b9e9b1590c4a3051e5894f6a1f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 23 Aug 2020 20:52:10 +0200 Subject: [PATCH 0412/1751] Workflows for primary vertex finding, writing and reading --- .../GlobalTrackingWorkflow/CMakeLists.txt | 29 +++++- .../PrimaryVertexReaderSpec.h | 73 ++++++++++++++ .../PrimaryVertexWriterSpec.h | 29 ++++++ .../PrimaryVertexingSpec.h | 49 ++++++++++ .../src/PrimaryVertexReaderSpec.cxx | 96 ++++++++++++++++++ .../src/PrimaryVertexWriterSpec.cxx | 55 +++++++++++ .../src/PrimaryVertexingSpec.cxx | 97 +++++++++++++++++++ .../src/primary-vertex-reader-workflow.cxx | 45 +++++++++ .../src/primary-vertexing-workflow.cxx | 60 ++++++++++++ 9 files changed, 528 insertions(+), 5 deletions(-) create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/primary-vertex-reader-workflow.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index fb975f6d7711a..2ab0a946f9025 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -10,16 +10,35 @@ # FIXME: do we actually need a library here, or is the executable enough ? o2_add_library(GlobalTrackingWorkflow - SOURCES src/TrackWriterTPCITSSpec.cxx src/TPCITSMatchingSpec.cxx - src/MatchTPCITSWorkflow.cxx src/TrackTPCITSReaderSpec.cxx - PUBLIC_LINK_LIBRARIES O2::GlobalTracking O2::ITStracking O2::ITSWorkflow - O2::TPCWorkflow O2::FT0Workflow - O2::ITSMFTWorkflow) + SOURCES src/TrackWriterTPCITSSpec.cxx + src/TPCITSMatchingSpec.cxx + src/MatchTPCITSWorkflow.cxx + src/TrackTPCITSReaderSpec.cxx + src/PrimaryVertexingSpec.cxx + src/PrimaryVertexWriterSpec.cxx + src/PrimaryVertexReaderSpec.cxx + PUBLIC_LINK_LIBRARIES O2::GlobalTracking + O2::ITStracking + O2::ITSWorkflow + O2::TPCWorkflow + O2::FT0Workflow + O2::ITSMFTWorkflow + O2::DetectorsVertexing) o2_add_executable(match-workflow COMPONENT_NAME tpcits SOURCES src/tpcits-match-workflow.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) +o2_add_executable(vertexing-workflow + COMPONENT_NAME primary + SOURCES src/primary-vertexing-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) + +o2_add_executable(vertex-reader-workflow + COMPONENT_NAME primary + 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 new file mode 100644 index 0000000000000..ee18c953b6a08 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h @@ -0,0 +1,73 @@ +// 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 PrimaryVertexReaderSpec.h + +#ifndef O2_PRIMARY_VERTEXREADER +#define O2_PRIMARY_VERTEXREADER + +#include "TFile.h" +#include "TTree.h" + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" + +#include "CommonDataFormat/TimeStamp.h" +#include "CommonDataFormat/RangeReference.h" +#include "ReconstructionDataFormats/Vertex.h" +#include "SimulationDataFormat/MCEventLabel.h" + +namespace o2 +{ +namespace vertexing +{ +// read primary vertices produces by the o2-primary-vertexing-workflow + +class PrimaryVertexReader : public o2::framework::Task +{ + using TimeEst = o2::dataformats::TimeStampWithError<float, float>; + using Vertex = o2::dataformats::Vertex<TimeEst>; + using V2TRef = o2::dataformats::RangeReference<int, int>; + using Label = o2::MCEventLabel; + + public: + PrimaryVertexReader(bool useMC) : mUseMC(useMC) {} + ~PrimaryVertexReader() override = default; + void init(o2::framework::InitContext& ic) final; + void run(o2::framework::ProcessingContext& pc) final; + + protected: + void connectTree(const std::string& filename); + + bool mUseMC = false; + + std::vector<Vertex> mVertices, *mVerticesPtr = &mVertices; + std::vector<int> mPVTrIdx, *mPVTrIdxPtr = &mPVTrIdx; + std::vector<V2TRef> mPV2TrIdx, *mPV2TrIdxPtr = &mPV2TrIdx; + std::vector<Label> mLabels, *mLabelsPtr = &mLabels; + + std::unique_ptr<TFile> mFile; + std::unique_ptr<TTree> mTree; + std::string mFileName = ""; + std::string mVertexTreeName = "o2sim"; + std::string mVertexBranchName = "PrimaryVertex"; + std::string mVertexTrackIDsBranchName = "PVTrackIndices"; + std::string mVertex2TrackIDRefsBranchName = "PV2TrackRefs"; + std::string mVertexLabelsBranchName = "PVMCTruth"; +}; + +/// create a processor spec +/// read primary vertex data from a root file +o2::framework::DataProcessorSpec getPrimaryVertexReaderSpec(bool useMC); + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h new file mode 100644 index 0000000000000..8da592ee5a45a --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h @@ -0,0 +1,29 @@ +// 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 PrimaryVertexWriterSpec.h + +#ifndef O2_PRIMARY_VERTEX_WRITER +#define O2_PRIMARY_VERTEX_WRITER + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +namespace vertexing +{ + +/// create a processor spec +framework::DataProcessorSpec getPrimaryVertexWriterSpec(bool useMC); + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h new file mode 100644 index 0000000000000..24cded57599bb --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h @@ -0,0 +1,49 @@ +// 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_PRIMARY_VERTEXER_SPEC_H +#define O2_PRIMARY_VERTEXER_SPEC_H + +/// @file PrimaryVertexingSpec.h + +#include "DetectorsVertexing/PVertexer.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "TStopwatch.h" + +namespace o2 +{ +namespace vertexing +{ + +using namespace o2::framework; + +class PrimaryVertexingSpec : public Task +{ + public: + PrimaryVertexingSpec(bool useMC) : mUseMC(useMC) {} + ~PrimaryVertexingSpec() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + void endOfStream(EndOfStreamContext& ec) final; + + private: + o2::vertexing::PVertexer mVertexer; + bool mUseMC{false}; ///< MC flag + TStopwatch mTimer; +}; + +/// create a processor spec +DataProcessorSpec getPrimaryVertexingSpec(bool useMC); + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx new file mode 100644 index 0000000000000..a9d518ded3827 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx @@ -0,0 +1,96 @@ +// 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 VertexReaderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace vertexing +{ + +void PrimaryVertexReader::init(InitContext& ic) +{ + mFileName = ic.options().get<std::string>("primary-vertex-infile"); + connectTree(mFileName); +} + +void PrimaryVertexReader::run(ProcessingContext& pc) +{ + auto ent = mTree->GetReadEntry() + 1; + assert(ent < mTree->GetEntries()); // this should not happen + mTree->GetEntry(ent); + LOG(INFO) << "Pushing " << mVerticesPtr->size() << " vertices at entry " << ent; + + pc.outputs().snapshot(Output{"GLO", "PVERTEX", 0, Lifetime::Timeframe}, mVertices); + pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe}, mPV2TrIdx); + pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe}, mPVTrIdx); + + if (mUseMC) { + pc.outputs().snapshot(Output{"GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe}, mLabels); + } + + if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) { + pc.services().get<ControlService>().endOfStream(); + pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); + } +} + +void PrimaryVertexReader::connectTree(const std::string& filename) +{ + mTree.reset(nullptr); // in case it was already loaded + mFile.reset(TFile::Open(filename.c_str())); + assert(mFile && !mFile->IsZombie()); + mTree.reset((TTree*)mFile->Get(mVertexTreeName.c_str())); + assert(mTree); + assert(mTree->GetBranch(mVertexBranchName.c_str())); + assert(mTree->GetBranch(mVertexTrackIDsBranchName.c_str())); + assert(mTree->GetBranch(mVertex2TrackIDRefsBranchName.c_str())); + + mTree->SetBranchAddress(mVertexBranchName.c_str(), &mVerticesPtr); + mTree->SetBranchAddress(mVertexTrackIDsBranchName.c_str(), &mPVTrIdxPtr); + mTree->SetBranchAddress(mVertex2TrackIDRefsBranchName.c_str(), &mPV2TrIdxPtr); + + if (mUseMC) { + assert(mTree->GetBranch(mVertexLabelsBranchName.c_str())); + mTree->SetBranchAddress(mVertexLabelsBranchName.c_str(), &mLabelsPtr); + } + + LOG(INFO) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries"; +} + +DataProcessorSpec getPrimaryVertexReaderSpec(bool useMC) +{ + std::vector<OutputSpec> outputs; + outputs.emplace_back("GLO", "PVERTEX", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe); + if (useMC) { + outputs.emplace_back("GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe); + } + + return DataProcessorSpec{ + "primary-vertex-reader", + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask<PrimaryVertexReader>(useMC)}, + Options{ + {"primary-vertex-infile", VariantType::String, "o2_primary_vertex.root", {"Name of the input primary vertex file"}}}}; +} + +} // namespace vertexing +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx new file mode 100644 index 0000000000000..8f3fcc653851e --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx @@ -0,0 +1,55 @@ +// 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 PrimaryVertexWriterSpec.cxx + +#include <vector> + +#include "GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h" +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "CommonDataFormat/TimeStamp.h" +#include "CommonDataFormat/RangeReference.h" +#include "ReconstructionDataFormats/Vertex.h" +#include "SimulationDataFormat/MCEventLabel.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace vertexing +{ + +template <typename T> +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; + +using TimeEst = o2::dataformats::TimeStampWithError<float, float>; +using Vertex = o2::dataformats::Vertex<TimeEst>; +using V2TRef = o2::dataformats::RangeReference<int, int>; +using Label = o2::MCEventLabel; + +using namespace o2::header; + +DataProcessorSpec getPrimaryVertexWriterSpec(bool useMC) +{ + auto logger = [](std::vector<Vertex> const& v) { + LOG(INFO) << "PrimaryVertexWriter pulled " << v.size() << " vertices"; + }; + + return MakeRootTreeWriterSpec("primary-vertex-writer", + "o2_primary_vertex.root", + MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree with Primary Vertices"}, + BranchDefinition<std::vector<Vertex>>{InputSpec{"vertices", "GLO", "PVERTEX", 0}, "PrimaryVertex", logger}, + BranchDefinition<std::vector<V2TRef>>{InputSpec{"v2tref", "GLO", "PVERTEX_TRIDREFS", 0}, "PV2TrackRefs"}, + BranchDefinition<std::vector<int>>{InputSpec{"vttrackID", "GLO", "PVERTEX_TRID", 0}, "PVTrackIndices"}, + BranchDefinition<std::vector<Label>>{InputSpec{"labels", "GLO", "PVERTEX_MCTR", 0}, "PVMCTruth", (useMC ? 1 : 0), ""})(); +} + +} // namespace vertexing +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx new file mode 100644 index 0000000000000..a3b0dc0b324ca --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.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. + +/// @file PrimaryVertexingSpec.cxx + +#include <vector> +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "DetectorsBase/Propagator.h" +#include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" +#include "SimulationDataFormat/MCEventLabel.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace vertexing +{ + +void PrimaryVertexingSpec::init(InitContext& ic) +{ + //-------- init geometry and field --------// + o2::base::Propagator::initFieldFromGRP("o2sim_grp.root"); + mTimer.Stop(); + mTimer.Reset(); + mVertexer.init(); +} + +void PrimaryVertexingSpec::run(ProcessingContext& pc) +{ + mTimer.Start(false); + double timeCPU0 = mTimer.CpuTime(), timeReal0 = mTimer.RealTime(); + const auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("match"); + gsl::span<const o2::MCCompLabel> lblITS, lblTPC; + if (mUseMC) { + lblITS = pc.inputs().get<gsl::span<o2::MCCompLabel>>("lblITS"); + lblTPC = pc.inputs().get<gsl::span<o2::MCCompLabel>>("lblTPC"); + } + std::vector<Vertex> vertices; + std::vector<int> vertexTrackIDs; + std::vector<V2TRef> v2tRefs; + std::vector<o2::MCEventLabel> lblVtx; + + mVertexer.process(tracksITSTPC, vertices, vertexTrackIDs, v2tRefs, lblITS, lblTPC, lblVtx); + + pc.outputs().snapshot(Output{"GLO", "PVERTEX", 0, Lifetime::Timeframe}, vertices); + pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe}, v2tRefs); + pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe}, vertexTrackIDs); + + if (mUseMC) { + pc.outputs().snapshot(Output{"GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe}, lblVtx); + } + + mTimer.Stop(); + LOG(INFO) << "Found " << vertices.size() << " primary vertices, timing: CPU: " + << mTimer.CpuTime() - timeCPU0 << " Real: " << mTimer.RealTime() - timeReal0 << " s"; +} + +void PrimaryVertexingSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "Primary vertexing total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getPrimaryVertexingSpec(bool useMC) +{ + std::vector<InputSpec> inputs; + std::vector<OutputSpec> outputs; + + inputs.emplace_back("match", "GLO", "TPCITS", 0, Lifetime::Timeframe); + + outputs.emplace_back("GLO", "PVERTEX", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe); + + if (useMC) { + inputs.emplace_back("lblITS", "GLO", "TPCITS_ITSMC", 0, Lifetime::Timeframe); + inputs.emplace_back("lblTPC", "GLO", "TPCITS_TPCMC", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe); + } + + return DataProcessorSpec{ + "primary-vertexing", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<PrimaryVertexingSpec>(useMC)}, + Options{}}; +} + +} // namespace vertexing +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/primary-vertex-reader-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/primary-vertex-reader-workflow.cxx new file mode 100644 index 0000000000000..1342cdb22a4b0 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/primary-vertex-reader-workflow.cxx @@ -0,0 +1,45 @@ +// 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 "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/ConfigParamSpec.h" +#include "GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<o2::framework::ConfigParamSpec> options{ + {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); + + auto useMC = !configcontext.options().get<bool>("disable-mc"); + + WorkflowSpec specs; + specs.emplace_back(o2::vertexing::getPrimaryVertexReaderSpec(useMC)); + return std::move(specs); +} diff --git a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx new file mode 100644 index 0000000000000..89afb1c0b9cb3 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx @@ -0,0 +1,60 @@ +// 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 "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" +#include "GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h" +#include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" + +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<o2::framework::ConfigParamSpec> options{ + {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation"}}, + {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, + {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); + // write the configuration used for the workflow + o2::conf::ConfigurableParam::writeINI("o2primary-vertexing-workflow_configuration.ini"); + + auto useMC = !configcontext.options().get<bool>("disable-mc"); + auto disableRootInp = configcontext.options().get<bool>("disable-root-input"); + auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); + + WorkflowSpec specs; + if (!disableRootInp) { + specs.emplace_back(o2::globaltracking::getTrackTPCITSReaderSpec(useMC)); + } + specs.emplace_back(o2::vertexing::getPrimaryVertexingSpec(useMC)); + if (!disableRootOut) { + specs.emplace_back(o2::vertexing::getPrimaryVertexWriterSpec(useMC)); + } + return std::move(specs); +} From f3fb1b9ff8e9fa29819a0220b39c9315b707b756 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 24 Aug 2020 11:35:22 +0200 Subject: [PATCH 0413/1751] adding example to access cascades (#4193) --- Analysis/Tutorials/src/weakDecayIteration.cxx | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Analysis/Tutorials/src/weakDecayIteration.cxx b/Analysis/Tutorials/src/weakDecayIteration.cxx index e36420ec56042..8fdcd4f585f75 100644 --- a/Analysis/Tutorials/src/weakDecayIteration.cxx +++ b/Analysis/Tutorials/src/weakDecayIteration.cxx @@ -47,7 +47,7 @@ struct CTask { } }; -// Grouping +// Grouping V0s struct DTask { void process(aod::Collision const& collision, aod::V0s const& v0s, aod::FullTracks const& tracks) { @@ -59,12 +59,26 @@ struct DTask { } }; +// Grouping V0s and cascades +// NOTE that you need to subscribe to V0s even if you only process cascades +struct ETask { + void process(aod::Collision const& collision, aod::V0s const& v0s, aod::Cascades const& cascades, aod::FullTracks const& tracks) + { + LOGF(INFO, "Collision %d has %d cascades", collision.globalIndex(), cascades.size()); + + for (auto& cascade : cascades) { + LOGF(INFO, "Collision %d Cascade %d (%d, %d, %d)", collision.globalIndex(), cascade.globalIndex(), cascade.v0().posTrackId(), cascade.v0().negTrackId(), cascade.bachelorId()); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<ATask>("produce-v0index"), - adaptAnalysisTask<BTask>("consume-v0"), + adaptAnalysisTask<BTask>("consume-v0s"), adaptAnalysisTask<CTask>("consume-cascades"), - adaptAnalysisTask<DTask>("consume-grouped-v0"), + adaptAnalysisTask<DTask>("consume-grouped-v0s"), + adaptAnalysisTask<ETask>("consume-grouped-cascades"), }; } From 403c273ae6f8dad5e022e04391d6fc9b978d81b9 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Tue, 14 Jul 2020 11:00:10 +0200 Subject: [PATCH 0414/1751] HepMC via configurable params, cleanup of deprecated old HepMC version support --- .../SimConfig/include/SimConfig/SimConfig.h | 2 - Common/SimConfig/src/SimConfig.cxx | 3 -- Generators/CMakeLists.txt | 16 +----- .../include/Generators/GeneratorHepMCParam.h | 40 ++++++++++++++ .../share/egconfig/pythia8_userhooks_charm.C | 2 +- Generators/src/GeneratorFactory.cxx | 8 ++- Generators/src/GeneratorHepMC.cxx | 52 +++---------------- Generators/src/GeneratorHepMCParam.cxx | 14 +++++ Generators/src/GeneratorsLinkDef.h | 1 + dependencies/O2SimulationDependencies.cmake | 12 +---- doc/DetectorSimulation.md | 3 +- prodtests/embedding_benchmark.sh | 4 +- run/CMakeLists.txt | 4 +- run/SimExamples/Adaptive_Pythia8/run.sh | 2 +- run/SimExamples/AliRoot_Hijing/run.sh | 2 +- run/SimExamples/HepMC_STARlight/run.sh | 3 +- .../pythia8_userhooks_jets.macro | 2 +- run/SimExamples/Jet_Embedding_Pythia8/run.sh | 4 +- run/SimExamples/Signal_ImpactB/run.sh | 2 +- 19 files changed, 84 insertions(+), 92 deletions(-) create mode 100644 Generators/include/Generators/GeneratorHepMCParam.h create mode 100644 Generators/src/GeneratorHepMCParam.cxx diff --git a/Common/SimConfig/include/SimConfig/SimConfig.h b/Common/SimConfig/include/SimConfig/SimConfig.h index 435e9a1312786..0ecd9c8dbdad4 100644 --- a/Common/SimConfig/include/SimConfig/SimConfig.h +++ b/Common/SimConfig/include/SimConfig/SimConfig.h @@ -27,7 +27,6 @@ struct SimConfigData { std::string mTrigger; // chosen VMC generator trigger unsigned int mNEvents; // number of events to be simulated std::string mExtKinFileName; // file name of external kinematics file (needed for ext kinematics generator) - std::string mHepMCFileName; // file name of HepMC file std::string mExtGenFileName; // file name containing the external generator configuration std::string mExtGenFuncName; // function call to retrieve the external generator configuration std::string mExtTrgFileName; // file name containing the external trigger configuration @@ -101,7 +100,6 @@ class SimConfig unsigned int getNEvents() const { return mConfigData.mNEvents; } std::string getExtKinematicsFileName() const { return mConfigData.mExtKinFileName; } - std::string getHepMCFileName() const { return mConfigData.mHepMCFileName; } std::string getExtGeneratorFileName() const { return mConfigData.mExtGenFileName; } std::string getExtGeneratorFuncName() const { return mConfigData.mExtGenFuncName; } std::string getExtTriggerFileName() const { return mConfigData.mExtTrgFileName; } diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index 54089d9a484f3..050720278683d 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -31,8 +31,6 @@ void SimConfig::initOptions(boost::program_options::options_description& options "startEvent", bpo::value<unsigned int>()->default_value(0), "index of first event to be used (when applicable)")( "extKinFile", bpo::value<std::string>()->default_value("Kinematics.root"), "name of kinematics file for event generator from file (when applicable)")( - "HepMCFile", bpo::value<std::string>()->default_value("kinematics.hepmc"), - "name of HepMC file for event generator from file (when applicable)")( "extGenFile", bpo::value<std::string>()->default_value("extgen.C"), "name of .C file with definition of external event generator")( "extGenFunc", bpo::value<std::string>()->default_value(""), @@ -94,7 +92,6 @@ bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& mConfigData.mTrigger = vm["trigger"].as<std::string>(); mConfigData.mNEvents = vm["nEvents"].as<unsigned int>(); mConfigData.mExtKinFileName = vm["extKinFile"].as<std::string>(); - mConfigData.mHepMCFileName = vm["HepMCFile"].as<std::string>(); mConfigData.mExtGenFileName = vm["extGenFile"].as<std::string>(); mConfigData.mExtGenFuncName = vm["extGenFunc"].as<std::string>(); mConfigData.mExtTrgFileName = vm["extTrgFile"].as<std::string>(); diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index f8651bb079625..178ed69529ab5 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -16,10 +16,6 @@ if(pythia_FOUND) set(pythiaTarget MC::Pythia) endif() -if(HepMC_FOUND) - set(hepmcTarget MC::HepMC) -endif() - if(HepMC3_FOUND) set(hepmcTarget MC::HepMC3) endif() @@ -43,8 +39,8 @@ o2_add_library(Generators $<$<BOOL:${pythia_FOUND}>:src/DecayerPythia8.cxx> $<$<BOOL:${pythia_FOUND}>:src/GeneratorPythia8Param.cxx> $<$<BOOL:${pythia_FOUND}>:src/DecayerPythia8Param.cxx> - $<$<BOOL:${HepMC_FOUND}>:src/GeneratorHepMC.cxx> $<$<BOOL:${HepMC3_FOUND}>:src/GeneratorHepMC.cxx> + $<$<BOOL:${HepMC3_FOUND}>:src/GeneratorHepMCParam.cxx> PUBLIC_LINK_LIBRARIES FairRoot::Base O2::SimConfig O2::CommonUtils O2::SimulationDataFormat ${pythia6Target} ${pythiaTarget} ${hepmcTarget} FairRoot::Gen @@ -58,11 +54,6 @@ if(pythia_FOUND) target_compile_definitions(${targetName} PUBLIC GENERATORS_WITH_PYTHIA8) endif() -if(HepMC_FOUND) - target_compile_definitions(${targetName} PUBLIC GENERATORS_WITH_HEPMC3) - target_compile_definitions(${targetName} PUBLIC GENERATORS_WITH_HEPMC3_DEPRECATED) -endif() - if(HepMC3_FOUND) target_compile_definitions(${targetName} PUBLIC GENERATORS_WITH_HEPMC3) endif() @@ -95,12 +86,9 @@ if(pythia_FOUND) include/Generators/GeneratorFactory.h) endif() -if(HepMC_FOUND) - list(APPEND headers include/Generators/GeneratorHepMC.h) -endif() - if(HepMC3_FOUND) list(APPEND headers include/Generators/GeneratorHepMC.h) + list(APPEND headers include/Generators/GeneratorHepMCParam.h) endif() o2_target_root_dictionary(Generators HEADERS ${headers}) diff --git a/Generators/include/Generators/GeneratorHepMCParam.h b/Generators/include/Generators/GeneratorHepMCParam.h new file mode 100644 index 0000000000000..0c2826a687c85 --- /dev/null +++ b/Generators/include/Generators/GeneratorHepMCParam.h @@ -0,0 +1,40 @@ +// 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 R+Preghenella - January 2020 + +#ifndef ALICEO2_EVENTGEN_GENERATORHEPMCPARAM_H_ +#define ALICEO2_EVENTGEN_GENERATORHEPMCPARAM_H_ + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" +#include <string> + +namespace o2 +{ +namespace eventgen +{ + +/** + ** a parameter class/struct to keep the settings of + ** the HepMC event generator and + ** allow the user to modify them + **/ + +struct GeneratorHepMCParam : public o2::conf::ConfigurableParamHelper<GeneratorHepMCParam> { + std::string fileName = ""; + int version = 2; + O2ParamDef(GeneratorHepMCParam, "HepMC"); +}; + +} // end namespace eventgen +} // end namespace o2 + +#endif // ALICEO2_EVENTGEN_GENERATORHEPMCPARAM_H_ diff --git a/Generators/share/egconfig/pythia8_userhooks_charm.C b/Generators/share/egconfig/pythia8_userhooks_charm.C index 95f824a8c9aae..de3ef244cce5b 100644 --- a/Generators/share/egconfig/pythia8_userhooks_charm.C +++ b/Generators/share/egconfig/pythia8_userhooks_charm.C @@ -1,6 +1,6 @@ // Pythia8 UserHooks // -// usage: o2sim -g pythia8 --configKeyValue "Pythia8.hooksFileName=pythia8_userhooks_charm.C" +// usage: o2sim -g pythia8 --configKeyValues "Pythia8.hooksFileName=pythia8_userhooks_charm.C" // /// \author R+Preghenella - February 2020 diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index 6c1c5eec50cb1..82f4206b8a3b7 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -28,6 +28,7 @@ #include <Generators/GeneratorTGenerator.h> #ifdef GENERATORS_WITH_HEPMC3 #include <Generators/GeneratorHepMC.h> +#include <Generators/GeneratorHepMCParam.h> #endif #include <Generators/BoxGunParam.h> #include <Generators/TriggerParticle.h> @@ -136,9 +137,12 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair #ifdef GENERATORS_WITH_HEPMC3 } else if (genconfig.compare("hepmc") == 0) { // external HepMC file + auto& param = GeneratorHepMCParam::Instance(); + LOG(INFO) << "Init \'GeneratorHepMC\' with following parameters"; + LOG(INFO) << param; auto hepmcGen = new o2::eventgen::GeneratorHepMC(); - hepmcGen->setFileName(conf.getHepMCFileName()); - hepmcGen->setVersion(2); + hepmcGen->setFileName(param.fileName); + hepmcGen->setVersion(param.version); primGen->AddGenerator(hepmcGen); #endif #ifdef GENERATORS_WITH_PYTHIA6 diff --git a/Generators/src/GeneratorHepMC.cxx b/Generators/src/GeneratorHepMC.cxx index fc970adcfc5ce..47dd365aec2c3 100644 --- a/Generators/src/GeneratorHepMC.cxx +++ b/Generators/src/GeneratorHepMC.cxx @@ -10,28 +10,8 @@ /// \author R+Preghenella - August 2017 -#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED - -#include "Generators/GeneratorHepMC.h" -#include "HepMC/ReaderAscii.h" -#include "HepMC/ReaderAsciiHepMC2.h" -#include "HepMC/GenEvent.h" -#include "HepMC/GenParticle.h" -#include "HepMC/GenVertex.h" -#include "HepMC/FourVector.h" -#include "TParticle.h" - -/** - HepMC/Errors.h of HepMC3 defines DEBUG as a logging macro, and this interferes with FairLogger. - Undefining it for the time being, while thinking about a possible solution for this issue. -**/ -#ifdef DEBUG -#undef DEBUG -#endif - -#else - #include "Generators/GeneratorHepMC.h" +#include "Generators/GeneratorHepMCParam.h" #include "HepMC3/ReaderAscii.h" #include "HepMC3/ReaderAsciiHepMC2.h" #include "HepMC3/GenEvent.h" @@ -39,8 +19,7 @@ #include "HepMC3/GenVertex.h" #include "HepMC3/FourVector.h" #include "TParticle.h" - -#endif +#include "TSystem.h" #include "FairLogger.h" #include "FairPrimaryGenerator.h" @@ -59,11 +38,7 @@ GeneratorHepMC::GeneratorHepMC() { /** default constructor **/ -#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED - mEvent = new HepMC::GenEvent(); -#else mEvent = new HepMC3::GenEvent(); -#endif mInterface = reinterpret_cast<void*>(mEvent); mInterfaceName = "hepmc"; } @@ -75,11 +50,7 @@ GeneratorHepMC::GeneratorHepMC(const Char_t* name, const Char_t* title) { /** constructor **/ -#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED - mEvent = new HepMC::GenEvent(); -#else mEvent = new HepMC3::GenEvent(); -#endif mInterface = reinterpret_cast<void*>(mEvent); mInterfaceName = "hepmc"; } @@ -112,11 +83,7 @@ Bool_t GeneratorHepMC::generateEvent() if (mReader->failed()) return kFALSE; /** set units to desired output **/ -#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED - mEvent->set_units(HepMC::Units::GEV, HepMC::Units::MM); -#else mEvent->set_units(HepMC3::Units::GEV, HepMC3::Units::MM); -#endif /** success **/ return kTRUE; @@ -180,9 +147,10 @@ Bool_t GeneratorHepMC::Init() Generator::Init(); /** open file **/ - mStream.open(mFileName); + std::string filename = gSystem->ExpandPathName(mFileName.c_str()); + mStream.open(filename); if (!mStream.is_open()) { - LOG(FATAL) << "Cannot open input file: " << mFileName << std::endl; + LOG(FATAL) << "Cannot open input file: " << filename << std::endl; return kFALSE; } @@ -190,18 +158,10 @@ Bool_t GeneratorHepMC::Init() switch (mVersion) { case 2: mStream.close(); -#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED - mReader = new HepMC::ReaderAsciiHepMC2(mFileName); -#else - mReader = new HepMC3::ReaderAsciiHepMC2(mFileName); -#endif + mReader = new HepMC3::ReaderAsciiHepMC2(filename); break; case 3: -#ifdef GENERATORS_WITH_HEPMC3_DEPRECATED - mReader = new HepMC::ReaderAscii(mStream); -#else mReader = new HepMC3::ReaderAscii(mStream); -#endif break; default: LOG(FATAL) << "Unsupported HepMC version: " << mVersion << std::endl; diff --git a/Generators/src/GeneratorHepMCParam.cxx b/Generators/src/GeneratorHepMCParam.cxx new file mode 100644 index 0000000000000..cf838412e3bc5 --- /dev/null +++ b/Generators/src/GeneratorHepMCParam.cxx @@ -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. + +/// \author R+Preghenella - January 2020 + +#include "Generators/GeneratorHepMCParam.h" +O2ParamImpl(o2::eventgen::GeneratorHepMCParam); diff --git a/Generators/src/GeneratorsLinkDef.h b/Generators/src/GeneratorsLinkDef.h index b4ed8bec7610d..0d0d00c3a2064 100644 --- a/Generators/src/GeneratorsLinkDef.h +++ b/Generators/src/GeneratorsLinkDef.h @@ -29,6 +29,7 @@ #pragma link C++ class o2::eventgen::GeneratorTGenerator + ; #ifdef GENERATORS_WITH_HEPMC3 #pragma link C++ class o2::eventgen::GeneratorHepMC + ; +#pragma link C++ class o2::eventgen::GeneratorHepMCParam + ; #endif #ifdef GENERATORS_WITH_PYTHIA6 #pragma link C++ class o2::eventgen::GeneratorPythia6 + ; diff --git a/dependencies/O2SimulationDependencies.cmake b/dependencies/O2SimulationDependencies.cmake index 0370093c14d4f..6d69d467a024d 100644 --- a/dependencies/O2SimulationDependencies.cmake +++ b/dependencies/O2SimulationDependencies.cmake @@ -66,22 +66,12 @@ set_package_properties(Geant4VMC PROPERTIES TYPE ${mcPackageRequirement}) find_package(VGM MODULE) set_package_properties(VGM PROPERTIES TYPE ${mcPackageRequirement}) -find_package(HepMC MODULE) -set_package_properties(HepMC - PROPERTIES - TYPE OPTIONAL DESCRIPTION - "the HepMC3 event record package (deprecated old find_package call)") - find_package(HepMC3 MODULE) set_package_properties(HepMC3 PROPERTIES TYPE OPTIONAL DESCRIPTION "the HepMC3 event record package") -if(HepMC_FOUND AND HepMC3_FOUND) - message(ERROR "Both HepMC3 packages have been found, something is wrong") -endif() - set(doBuildSimulation OFF) if(pythia_FOUND @@ -90,7 +80,7 @@ if(pythia_FOUND AND Geant4_FOUND AND Geant4VMC_FOUND AND VGM_FOUND - AND (HepMC_FOUND OR HepMC3_FOUND)) + AND HepMC3_FOUND) set(doBuildSimulation ON) endif() diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index 7b46e0a18ae29..04befd2dd2d99 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -92,6 +92,7 @@ Important parameters influencing the transport simulation are: | Diamond | Parameter allowing to set the interaction vertex location and the spread/width. Is used in all event generators. | | Pythia6 | Parameters that influence the pythia6 generator. | | Pythia8 | Parameters that influence the pythia8 generator. | +| HepMC | Parameters that influence the HepMC generator. | | TriggerParticle | Parameters influencing the trigger mechanism in particle generators. | Detectors may also have parameters influencing various pieces such geometry layout, material composition etc. @@ -258,7 +259,7 @@ This functionality might be of use for users who want to be able to steer the ev An example of a configuration macro is this one ``` -// usage: o2sim -g pythia8 --configKeyValue "Pythia8.hooksFileName=pythia8_userhooks_charm.C" +// usage: o2sim -g pythia8 --configKeyValues "Pythia8.hooksFileName=pythia8_userhooks_charm.C" #include "Generators/Trigger.h" #include "Pythia8/Pythia.h" diff --git a/prodtests/embedding_benchmark.sh b/prodtests/embedding_benchmark.sh index 47035b7e8a09e..11b97cf6523a9 100755 --- a/prodtests/embedding_benchmark.sh +++ b/prodtests/embedding_benchmark.sh @@ -169,13 +169,13 @@ done produce_background() { echo "Running background simulation for $nevBG $collSyst events with $generBG generator and engine $engine" - taskwrapper sim_bg.log o2-sim -j ${NCPUS} -n"$nevBG" --configKeyValue "Diamond.width[2]=6." -g "$generBG" -e "$engine" -o o2simbg --skipModules ZDC --seed ${SEED:-1} + taskwrapper sim_bg.log o2-sim -j ${NCPUS} -n"$nevBG" --configKeyValues "Diamond.width[2]=6." -g "$generBG" -e "$engine" -o o2simbg --skipModules ZDC --seed ${SEED:-1} } produce_signal() { echo "Running signal simulation for $nevS $collSyst events with $generS generator and engine $engine" - taskwrapper sim_s.log o2-sim -j ${NCPUS} -n"$nevS" --configKeyValue "Diamond.width[2]=6." -g "$generS" -e "$engine" -o o2sims --embedIntoFile o2simbg_Kine.root --skipModules ZDC --seed ${SEED:-1} + taskwrapper sim_s.log o2-sim -j ${NCPUS} -n"$nevS" --configKeyValues "Diamond.width[2]=6." -g "$generS" -e "$engine" -o o2sims --embedIntoFile o2simbg_Kine.root --skipModules ZDC --seed ${SEED:-1} } do_transport_local() diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index 8e9a5ec00de87..3dc66a1d5f853 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -221,8 +221,8 @@ o2_add_test_wrapper(NAME o2sim_hepmc 2 -g hepmc - --HepMCFile - ${CMAKE_SOURCE_DIR}/Generators/share/data/pythia.hepmc + --configKeyValues + "HepMC.fileName=${CMAKE_SOURCE_DIR}/Generators/share/data/pythia.hepmc;HepMC.version=2" -o o2simhepmc LABELS long sim hepmc3 diff --git a/run/SimExamples/Adaptive_Pythia8/run.sh b/run/SimExamples/Adaptive_Pythia8/run.sh index 61a7af344611d..47b41a74db602 100755 --- a/run/SimExamples/Adaptive_Pythia8/run.sh +++ b/run/SimExamples/Adaptive_Pythia8/run.sh @@ -11,7 +11,7 @@ set -x # PART a) NBGR=5 -o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS -o bkg --configKeyValue \ +o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS -o bkg --configKeyValues \ "Diamond.position[2]=0.1;Diamond.width[2]=0.05" # PART b) diff --git a/run/SimExamples/AliRoot_Hijing/run.sh b/run/SimExamples/AliRoot_Hijing/run.sh index 2a99a81083a76..78b5d92a28eb9 100755 --- a/run/SimExamples/AliRoot_Hijing/run.sh +++ b/run/SimExamples/AliRoot_Hijing/run.sh @@ -27,4 +27,4 @@ BMIN=0 BMAX=20. o2-sim -j 20 -n ${NEV} -g extgen -m PIPE ITS TPC -o sim \ --extGenFile "aliroot_hijing.macro" --extGenFunc "hijing(${ENERGY}, ${BMIN}, ${BMAX})" \ - --configKeyValue "Diamond.position[2]=0.1;Diamond.width[2]=0.05" + --configKeyValues "Diamond.position[2]=0.1;Diamond.width[2]=0.05" diff --git a/run/SimExamples/HepMC_STARlight/run.sh b/run/SimExamples/HepMC_STARlight/run.sh index 5cc7e5ad477b3..b75cee52b7117 100755 --- a/run/SimExamples/HepMC_STARlight/run.sh +++ b/run/SimExamples/HepMC_STARlight/run.sh @@ -15,5 +15,4 @@ env -i HOME="$HOME" USER="$USER" PATH="/bin:/usr/bin:/usr/local/bin" \ # PART b) NEV=1000 o2-sim -j 20 -n ${NEV} -g hepmc -m PIPE ITS -o sim \ - --HepMCFile starlight.hepmc \ - --configKeyValue "Diamond.position[2]=0.1;Diamond.width[2]=0.05" + --configKeyValues "HepMC.fileName=starlight.hepmc;HepMC.version=2;Diamond.position[2]=0.1;Diamond.width[2]=0.05" diff --git a/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro b/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro index 16bdede325310..9cd5249f89f98 100644 --- a/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro +++ b/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro @@ -1,6 +1,6 @@ // Pythia8 UserHooks // -// usage: o2sim -g pythia8 --configKeyValue "Pythia8.hooksFileName=pythia8_userhooks_jets.C" +// usage: o2sim -g pythia8 --configKeyValues "Pythia8.hooksFileName=pythia8_userhooks_jets.C" // /// \author R+Preghenella - April 2020 diff --git a/run/SimExamples/Jet_Embedding_Pythia8/run.sh b/run/SimExamples/Jet_Embedding_Pythia8/run.sh index db1bc07c028fe..e27ccf6e88a22 100755 --- a/run/SimExamples/Jet_Embedding_Pythia8/run.sh +++ b/run/SimExamples/Jet_Embedding_Pythia8/run.sh @@ -12,14 +12,14 @@ set -x # PART a) NBGR=5 -o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS TPC -o bkg --configKeyValue \ +o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS TPC -o bkg --configKeyValues \ "Diamond.position[2]=0.1;Diamond.width[2]=0.05" # PART b) # produce hard jets using a pythia8 configuration given in a file 'pythia8_hard.cfg'; event selection is done by a user hook specified # in file 'pythia8_userhooks_jets.macro' and using same vertex setting as background events (via --embedInto) NSGN=10 -o2-sim -j 20 -n ${NSGN} -g pythia8 -m PIPE ITS TPC --configKeyValue "Pythia8.config=pythia8_hard.cfg;Pythia8.hooksFileName=pythia8_userhooks_jets.macro" --embedIntoFile bkg_Kine.root -o sgn > logsgn 2>&1 +o2-sim -j 20 -n ${NSGN} -g pythia8 -m PIPE ITS TPC --configKeyValues "Pythia8.config=pythia8_hard.cfg;Pythia8.hooksFileName=pythia8_userhooks_jets.macro" --embedIntoFile bkg_Kine.root -o sgn > logsgn 2>&1 # PART c) # digitization with summation of signal on top of background events diff --git a/run/SimExamples/Signal_ImpactB/run.sh b/run/SimExamples/Signal_ImpactB/run.sh index e6d8a54cd29f7..c5e06b0993af4 100755 --- a/run/SimExamples/Signal_ImpactB/run.sh +++ b/run/SimExamples/Signal_ImpactB/run.sh @@ -11,7 +11,7 @@ set -x # PART a) NBGR=5 -o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS -o bkg --configKeyValue \ +o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS -o bkg --configKeyValues \ "Diamond.position[2]=0.1;Diamond.width[2]=0.05" # PART b) From 61b0c0325abc8eeaf8a5b6cc664922ea547c11d0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 23 Jul 2020 21:28:49 +0200 Subject: [PATCH 0415/1751] HIP Workaround: Add option to use a global file-lock to mutex the registration of memory for GPU --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 27 +++++++++++++++++--- GPU/GPUTracking/Base/GPUSettingsList.h | 1 + 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 65704838d091d..53973a11afc33 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -56,6 +56,9 @@ #include <iomanip> #include <stdexcept> #include <regex> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> #include "GPUReconstructionConvert.h" #include "DetectorsRaw/RDHUtils.h" @@ -96,6 +99,8 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int auto processAttributes = std::make_shared<ProcessAttributes>(); auto initFunction = [processAttributes, specconfig](InitContext& ic) { + GPUO2InterfaceConfiguration config; + GPUSettingsO2 confParam; { auto& parser = processAttributes->parser; auto& tracker = processAttributes->tracker; @@ -103,8 +108,6 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int tracker = std::make_unique<GPUCATracking>(); // Create configuration object and fill settings - - GPUO2InterfaceConfiguration config; const auto grp = o2::parameters::GRPObject::loadFrom("o2sim_grp.root"); if (grp) { config.configEvent.solenoidBz = 5.00668f * grp->getL3Current() / 30000.; @@ -113,7 +116,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } else { throw std::runtime_error("Failed to initialize run parameters from GRP"); } - const GPUSettingsO2& confParam = config.ReadConfigurableParam(); + confParam = config.ReadConfigurableParam(); processAttributes->allocateOutputOnTheFly = confParam.allocateOutputOnTheFly; processAttributes->outputBufferSize = confParam.outputBufferSize; processAttributes->suppressOutput = (confParam.dump == 2); @@ -200,12 +203,28 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } auto& callbacks = ic.services().get<CallbackService>(); - callbacks.set(CallbackService::Id::RegionInfoCallback, [&processAttributes](FairMQRegionInfo const& info) { + callbacks.set(CallbackService::Id::RegionInfoCallback, [&processAttributes, confParam](FairMQRegionInfo const& info) { if (info.size) { + int fd = 0; + if (confParam.mutexMemReg) { + fd = open("/tmp/o2_gpu_memlock_mutex.lock", O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); + if (fd == -1) { + throw std::runtime_error("Error opening lock file"); + } + if (lockf(fd, F_LOCK, 0)) { + throw std::runtime_error("Error locking file"); + } + } auto& tracker = processAttributes->tracker; if (tracker->registerMemoryForGPU(info.ptr, info.size)) { throw std::runtime_error("Error registering memory for GPU"); } + if (confParam.mutexMemReg) { + if (lockf(fd, F_ULOCK, 0)) { + throw std::runtime_error("Error unlocking file"); + } + close(fd); + } } }); diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index a95ef9c40980b..ce0396b72d6dd 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -261,6 +261,7 @@ AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") AddOption(outputBufferSize, unsigned long, 200000000ul, "", 0, "Size of the output buffers to be allocated") AddOption(synchronousProcessing, bool, false, "", 0, "Apply performance shortcuts for synchronous processing, disable unneeded steps") +AddOption(mutexMemReg, bool, false, "", 0, "Global mutex to serialize GPU memory registration") EndConfig() #endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE From cd53f552cdbe2d330cd9236405db44d9a1712210 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 23 Aug 2020 18:46:52 +0200 Subject: [PATCH 0416/1751] Add missing include path to standalone benchmark --- GPU/GPUTracking/Standalone/CMakeLists.txt | 1 + GPU/GPUTracking/Standalone/tools/testCL.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 7d57de2bfc234..b4b42185ef4c8 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -126,6 +126,7 @@ include_directories(${CMAKE_SOURCE_DIR}/TPCClusterFinder ${CMAKE_SOURCE_DIR}/../../../DataFormats/Detectors/Common/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/Detectors/ITSMFT/ITS/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/Detectors/TPC/include + ${CMAKE_SOURCE_DIR}/../../../DataFormats/Detectors/TRD/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/Headers/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/MemoryResources/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/Reconstruction/include diff --git a/GPU/GPUTracking/Standalone/tools/testCL.sh b/GPU/GPUTracking/Standalone/tools/testCL.sh index 257591d3de3e5..a980531bbe8d1 100755 --- a/GPU/GPUTracking/Standalone/tools/testCL.sh +++ b/GPU/GPUTracking/Standalone/tools/testCL.sh @@ -12,7 +12,7 @@ LLVM_SPIRV=llvm-spirv INCLUDES="-I../. -I../Base -I../SliceTracker -I../Common -I../Merger -I../TRDTracking -I../ITS -I../dEdx -I../TPCConvert -I../TPCFastTransformation -I../DataCompression -I../TPCClusterFinder -I../Global -I ../GPUUtils \ -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/common/include -I$HOME/alice/O2/DataFormats/Detectors/TRD/include" DEFINES="-DGPUCA_STANDALONE -DGPUCA_GPULIBRARY=OCL -DNDEBUG -D__OPENCLCPP__ -DHAVE_O2HEADERS -DGPUCA_TPC_GEOMETRY_O2" FLAGS="-O3 -cl-denorms-are-zero -cl-mad-enable -cl-no-signed-zeros -ferror-limit=1000 -Xclang -finclude-default-header -Dcl_clang_storage_class_specifiers" From e3a97ab1e2a4af3a2fd0bf7fcccbee801ba41e8e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 23 Aug 2020 18:58:50 +0200 Subject: [PATCH 0417/1751] GPU: Add option to override number of blocks derrived from launch bounds --- GPU/Common/GPUDefGPUParameters.h | 2 +- GPU/Common/GPUDefMacros.h | 5 +++++ GPU/GPUTracking/Base/GPUReconstruction.h | 5 +++-- GPU/GPUTracking/Base/GPUReconstructionCPU.h | 2 +- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 2 +- GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index f029480c1f4a5..6b6de1c07d597 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -41,7 +41,7 @@ #define GPUCA_LB_GPUTPCCFDecodeZS 64, 4 #define GPUCA_LB_GPUTPCCFGather 1024, 1 #define GPUCA_LB_GPUTPCGMMergerTrackFit 64, 1 - #define GPUCA_LB_GPUTPCGMMergerFollowLoopers 256, 1 + #define GPUCA_LB_GPUTPCGMMergerFollowLoopers 256, 1, 200 #define GPUCA_LB_GPUTPCGMMergerSliceRefit 256 #define GPUCA_LB_GPUTPCGMMergerUnpackResetIds 256 #define GPUCA_LB_GPUTPCGMMergerUnpackGlobal 256 diff --git a/GPU/Common/GPUDefMacros.h b/GPU/Common/GPUDefMacros.h index 4c5946de3bb8e..81b350ecd0329 100644 --- a/GPU/Common/GPUDefMacros.h +++ b/GPU/Common/GPUDefMacros.h @@ -31,12 +31,17 @@ #define GPUCA_M_FIRST(...) GPUCA_M_FIRST_A(__VA_ARGS__) #define GPUCA_M_SHIFT_A(a, ...) __VA_ARGS__ #define GPUCA_M_SHIFT(...) GPUCA_M_SHIFT_A(__VA_ARGS__) +#define GPUCA_M_FIRST2_A(a, b, ...) a, b +#define GPUCA_M_FIRST2(...) GPUCA_M_FIRST2_A(__VA_ARGS__, 0) #define GPUCA_M_STRIP_FIRST(a) GPUCA_M_FIRST(GPUCA_M_STRIP(a)) #define GPUCA_M_COUNT_A(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, N, ...) N +#define GPUCA_M_COUNT3_A(_1, _2, _3, N, ...) N #define GPUCA_M_COUNT(...) GPUCA_M_COUNT_A(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #define GPUCA_M_SINGLEOPT(...) GPUCA_M_COUNT_A(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) +#define GPUCA_M_MAX2_3(...) GPUCA_M_COUNT3_A(__VA_ARGS__, GPUCA_M_FIRST2(__VA_ARGS__), GPUCA_M_FIRST2(__VA_ARGS__), GPUCA_M_FIRST(__VA_ARGS__), ) +#define GPUCA_M_MAX1_3(...) GPUCA_M_COUNT3_A(__VA_ARGS__, GPUCA_M_FIRST(__VA_ARGS__), GPUCA_M_FIRST(__VA_ARGS__), GPUCA_M_FIRST(__VA_ARGS__), ) #define GPUCA_M_UNROLL_ #define GPUCA_M_UNROLL_U(...) _Pragma(GPUCA_M_STR(unroll __VA_ARGS__)) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.h b/GPU/GPUTracking/Base/GPUReconstruction.h index 4334bc5265a27..188200ff9e275 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.h +++ b/GPU/GPUTracking/Base/GPUReconstruction.h @@ -147,10 +147,11 @@ class GPUReconstruction }; struct krnlProperties { - krnlProperties(int t = 0, int b = 1) : nThreads(t), minBlocks(b) {} + krnlProperties(int t = 0, int b = 1, int b2 = 0) : nThreads(t), minBlocks(b), forceBlocks(b2) {} unsigned int nThreads; unsigned int minBlocks; - unsigned int total() { return nThreads * minBlocks; } + unsigned int forceBlocks; + unsigned int total() { return forceBlocks ? forceBlocks : (nThreads * minBlocks); } }; struct krnlSetup { diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.h b/GPU/GPUTracking/Base/GPUReconstructionCPU.h index f6c2ccd477a6b..4ec3c3edee858 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.h +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.h @@ -251,7 +251,7 @@ inline int GPUReconstructionCPU::runKernel(const krnlExec& x, const krnlRunRange unsigned int nBlocks = x.nBlocks; auto prop = getKernelProperties<S, I>(); const int autoThreads = cpuFallback ? 1 : prop.nThreads; - const int autoBlocks = cpuFallback ? 1 : (prop.minBlocks * mBlockCount); + const int autoBlocks = cpuFallback ? 1 : (prop.forceBlocks ? prop.forceBlocks : (prop.minBlocks * mBlockCount)); if (nBlocks == (unsigned int)-1) { nBlocks = (nThreads + autoThreads - 1) / autoThreads; nThreads = autoThreads; diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 86a35195018cd..a5342ee411eae 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -128,7 +128,7 @@ GPUg() void runKernelCUDA(GPUCA_CONSMEM_PTR int iSlice_internal, Args... args) */ #undef GPUCA_KRNL_REG -#define GPUCA_KRNL_REG(args) __launch_bounds__(GPUCA_M_STRIP(args)) +#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_PROP(x_class, x_attributes) \ GPUCA_KRNL_WRAP(GPUCA_KRNL_, x_class, x_attributes, x_arguments, x_forward) diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index fb883e432df21..e835943b1fa09 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -123,7 +123,7 @@ GPUg() void runKernelHIP(GPUCA_CONSMEM_PTR int iSlice_internal, Args... args) */ #undef GPUCA_KRNL_REG -#define GPUCA_KRNL_REG(args) __launch_bounds__(GPUCA_M_STRIP(args)) +#define GPUCA_KRNL_REG(args) __launch_bounds__(GPUCA_M_MAX2_3(GPUCA_M_STRIP(args))) #undef GPUCA_KRNL_CUSTOM #define GPUCA_KRNL_CUSTOM(args) GPUCA_M_STRIP(args) #undef GPUCA_KRNL_BACKEND_XARGS From a3cde369b779f915422afcc3653db5ac4bc18609 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 23 Aug 2020 19:00:14 +0200 Subject: [PATCH 0418/1751] AMD Workaround: workaround for memory allocation problem in rocThrust --- GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index e835943b1fa09..aae9ad1cefac2 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -11,6 +11,7 @@ /// \file GPUReconstructionHIP.hip.cxx /// \author David Rohr +#define __HIP_ENABLE_DEVICE_MALLOC__ 1 //Fix SWDEV-239120 #define GPUCA_GPUTYPE_VEGA #define GPUCA_UNROLL(CUDA, HIP) GPUCA_M_UNROLL_##HIP #define GPUdic(CUDA, HIP) GPUCA_GPUdic_select_##HIP() From 146d1a29a9808c018f283c41feb5d2dba5b826d0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 23 Aug 2020 19:00:52 +0200 Subject: [PATCH 0419/1751] AMD Workaround: Workaround for HIP unable to compile our logging headers --- GPU/Common/GPULogging.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/Common/GPULogging.h b/GPU/Common/GPULogging.h index bc677c546ba5b..c78e21dce9941 100644 --- a/GPU/Common/GPULogging.h +++ b/GPU/Common/GPULogging.h @@ -23,7 +23,7 @@ #define GPUWarning(...) #define GPUError(...) #define GPUFatal(...) -#elif defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE_DEVICE) && !defined(GPUCA_NO_FMT) +#elif defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE_DEVICE) && !defined(GPUCA_NO_FMT) && !defined(__HIPCC__) #include <fmt/printf.h> #define GPUInfo(string, ...) \ { \ @@ -40,7 +40,7 @@ fmt::fprintf(stderr, string "\n", ##__VA_ARGS__); \ throw std::exception(); \ } -#elif defined(GPUCA_STANDALONE) || defined(GPUCA_GPUCODE_DEVICE) || (defined(GPUCA_ALIROOT_LIB) && defined(GPUCA_GPUCODE) && defined(__cplusplus) && __cplusplus < 201703L) +#elif defined(GPUCA_STANDALONE) || defined(GPUCA_GPUCODE_DEVICE) || (defined(GPUCA_ALIROOT_LIB) && defined(GPUCA_GPUCODE) && defined(__cplusplus) && __cplusplus < 201703L) || defined(__HIPCC__) // For standalone / CUDA / HIP, we just use printf, which should be available // Temporarily, we also have to handle CUDA on AliRoot with O2 defaults due to ROOT / CUDA incompatibilities #define GPUInfo(string, ...) \ @@ -48,7 +48,7 @@ printf(string "\n", ##__VA_ARGS__); \ } #define GPUImportant(...) GPUInfo(__VA_ARGS__) - #ifdef GPUCA_GPUCODE_DEVICE + #if defined(GPUCA_GPUCODE_DEVICE) || defined(__HIPCC__) #define GPUWarning(...) GPUInfo(__VA_ARGS__) #define GPUError(...) GPUInfo(__VA_ARGS__) #define GPUFatal(...) GPUInfo(__VA_ARGS__) From 23e186bb4325702b504791e71825168448ef17a3 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 23 Aug 2020 19:02:15 +0200 Subject: [PATCH 0420/1751] Revert AMD workaround: hip-clang reports correct constant memory size now --- GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index aae9ad1cefac2..9ddc6a308fe73 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -291,7 +291,6 @@ int GPUReconstructionHIPBackend::InitDevice_Runtime() mDeviceId = bestDevice; GPUFailedMsgI(hipGetDeviceProperties(&hipDeviceProp, mDeviceId)); - hipDeviceProp.totalConstMem = 65536; // TODO: Remove workaround, fixes incorrectly reported HIP constant memory if (mProcessingSettings.debugLevel >= 2) { GPUInfo("Using HIP Device %s with Properties:", hipDeviceProp.name); From 0dcec95aa264219cf8ee7e77c5dcae16881b45ed Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 19 Jun 2020 14:51:29 +0200 Subject: [PATCH 0421/1751] GPU: Remove HIP workaround to remove -g CXX flag --- GPU/GPUTracking/Base/hip/CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index c24925582f824..b4d64230ec872 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -13,12 +13,6 @@ set(MODULE GPUTrackingHIP) set(CMAKE_CXX_COMPILER ${hip_HIPCC_EXECUTABLE}) set(CMAKE_CXX_EXTENSIONS OFF) -string(REPLACE " -g " " " CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} ") -string(REPLACE " -g " " " CMAKE_CXX_FLAGS_${CMAKE_BUILT_TYPE} " ${CMAKE_CXX_FLAGS_${CMAKE_BUILT_TYPE}} ") - -string(REPLACE " -ggdb " " " CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} ") -string(REPLACE " -ggdb " " " CMAKE_CXX_FLAGS_${CMAKE_BUILT_TYPE} " ${CMAKE_CXX_FLAGS_${CMAKE_BUILT_TYPE}} ") - #setting flags as a global option for all HIP targets. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-gpu-rdc -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -Wno-invalid-constexpr -Wno-ignored-optimization-argument -Wno-unused-private-field") if(DEFINED HIP_AMDGPUTARGET) From 91224a7544311226fc4e5ffaf7694d15953ce006 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 26 Jun 2020 17:24:08 +0200 Subject: [PATCH 0422/1751] GPU: Flush denormals to zero also for HIP --- GPU/GPUTracking/Base/hip/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index b4d64230ec872..8bbe0f7a29964 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -14,7 +14,7 @@ set(CMAKE_CXX_COMPILER ${hip_HIPCC_EXECUTABLE}) set(CMAKE_CXX_EXTENSIONS OFF) #setting flags as a global option for all HIP targets. -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-gpu-rdc -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -Wno-invalid-constexpr -Wno-ignored-optimization-argument -Wno-unused-private-field") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-gpu-rdc -fcuda-flush-denormals-to-zero -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -Wno-invalid-constexpr -Wno-ignored-optimization-argument -Wno-unused-private-field") if(DEFINED HIP_AMDGPUTARGET) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --amdgpu-target=${HIP_AMDGPUTARGET}") set(TMP_TARGET "(GPU Target ${HIP_AMDGPUTARGET})") From 0643be8905b16102e1630e9a456ca82d59039ead Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 24 Aug 2020 13:13:48 +0200 Subject: [PATCH 0423/1751] GPU: Define HIP CXX flags globally and add gpu-rdc to ITS code (no longer default with hip-clang) --- Detectors/ITSMFT/ITS/tracking/hip/CMakeLists.txt | 16 +++------------- GPU/GPUTracking/Base/hip/CMakeLists.txt | 3 +-- dependencies/FindO2GPU.cmake | 4 ++++ 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/hip/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/hip/CMakeLists.txt index f4c90624a626a..b857741663c64 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/hip/CMakeLists.txt @@ -10,10 +10,7 @@ set(CMAKE_CXX_COMPILER ${hip_HIPCC_EXECUTABLE}) set(CMAKE_CXX_EXTENSIONS OFF) - -if(DEFINED HIP_AMDGPUTARGET) - set(TMP_TARGET "(GPU Target ${HIP_AMDGPUTARGET})") -endif() +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${O2_HIP_CMAKE_CXX_FLAGS} -fgpu-rdc") message(STATUS "Building ITS HIP vertexer") o2_add_library(ITStrackingHIP @@ -24,7 +21,7 @@ o2_add_library(ITStrackingHIP src/StreamHIP.hip.cxx # src/TrackerTraitsHIP.hip.cxx src/VertexerTraitsHIP.hip.cxx - src/UtilsHIP.hip.cxx + src/UtilsHIP.hip.cxx PUBLIC_LINK_LIBRARIES O2::ITStracking hip::host hip::device @@ -35,13 +32,6 @@ target_compile_definitions( ${targetName} PRIVATE $<TARGET_PROPERTY:O2::ITStracking,COMPILE_DEFINITIONS>) if(HIP_AMDGPUTARGET) + # Need to add gpu target also to link flags due to gpu-rdc option target_link_options(${targetName} PUBLIC --amdgpu-target=${HIP_AMDGPUTARGET}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --amdgpu-target=${HIP_AMDGPUTARGET}") endif() - -target_compile_options(${targetName} - PUBLIC -Wno-invalid-command-line-argument - -Wno-unused-command-line-argument - -Wno-invalid-constexpr - -Wno-ignored-optimization-argument - -Wno-unused-private-field) \ No newline at end of file diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index 8bbe0f7a29964..e05996e2c44c4 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -14,9 +14,8 @@ set(CMAKE_CXX_COMPILER ${hip_HIPCC_EXECUTABLE}) set(CMAKE_CXX_EXTENSIONS OFF) #setting flags as a global option for all HIP targets. -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-gpu-rdc -fcuda-flush-denormals-to-zero -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -Wno-invalid-constexpr -Wno-ignored-optimization-argument -Wno-unused-private-field") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${O2_HIP_CMAKE_CXX_FLAGS} -fno-gpu-rdc") if(DEFINED HIP_AMDGPUTARGET) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --amdgpu-target=${HIP_AMDGPUTARGET}") set(TMP_TARGET "(GPU Target ${HIP_AMDGPUTARGET})") endif() diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 2a91c46dda45b..06886f02f16ca 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -202,6 +202,10 @@ if(ENABLE_HIP) set_target_properties(rocthrust PROPERTIES IMPORTED_GLOBAL TRUE) add_library(ROCm::rocThrust ALIAS rocthrust) message(STATUS "HIP Found (${hip_HIPCC_EXECUTABLE})") + set(O2_HIP_CMAKE_CXX_FLAGS "-fcuda-flush-denormals-to-zero -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -Wno-invalid-constexpr -Wno-ignored-optimization-argument -Wno-unused-private-field") + if(HIP_AMDGPUTARGET) + set(O2_HIP_CMAKE_CXX_FLAGS "${O2_HIP_CMAKE_CXX_FLAGS} --amdgpu-target=${HIP_AMDGPUTARGET}") + endif() endif() endif() if(NOT HIP_ENABLED AND NOT ENABLE_HIP STREQUAL "AUTO") From 7072735b79a3415c291ece83d636454a7b200e3b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 20 Aug 2020 15:21:29 +0200 Subject: [PATCH 0424/1751] GPU: Query device timers only when debug mode enabled --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 2 +- GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 2 +- .../Base/opencl-common/GPUReconstructionOCLInternals.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index a5342ee411eae..e8ac56ab1afe4 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -150,7 +150,7 @@ void GPUReconstructionCUDABackend::runKernelBackendInternal<GPUMemClean16, 0>(kr template <class T, int I, typename... Args> void GPUReconstructionCUDABackend::runKernelBackendInternal(krnlSetup& _xyz, const Args&... args) { - GPUDebugTiming timer(mProcessingSettings.deviceTimers, (void**)mDebugEvents, mInternals->Streams, _xyz); + GPUDebugTiming timer(mProcessingSettings.deviceTimers && mProcessingSettings.debugLevel > 0, (void**)mDebugEvents, mInternals->Streams, _xyz); backendInternal<T, I>::runKernelBackendMacro(_xyz, this, args...); } diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index 9ddc6a308fe73..7f93338f4b2cd 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -157,7 +157,7 @@ void GPUReconstructionHIPBackend::runKernelBackendInternal<GPUMemClean16, 0>(krn template <class T, int I, typename... Args> void GPUReconstructionHIPBackend::runKernelBackendInternal(krnlSetup& _xyz, const Args&... args) { - if (mProcessingSettings.deviceTimers) { + if (mProcessingSettings.deviceTimers && mProcessingSettings.debugLevel > 0) { #ifdef __CUDACC__ GPUFailedMsg(hipEventRecord((hipEvent_t)mDebugEvents->DebugStart, mInternals->Streams[x.stream])); #endif diff --git a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h index ae3291bebb0a4..10d397ed9fe0a 100644 --- a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h +++ b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCLInternals.h @@ -202,14 +202,14 @@ int GPUReconstructionOCL::runKernelBackendCommon(krnlSetup& _xyz, K& k, const Ar cl_event ev; cl_event* evr; bool tmpEvent = false; - if (z.ev == nullptr && mProcessingSettings.deviceTimers) { + if (z.ev == nullptr && mProcessingSettings.deviceTimers && mProcessingSettings.debugLevel > 0) { evr = &ev; tmpEvent = true; } else { evr = (cl_event*)z.ev; } int retVal = clExecuteKernelA(mInternals->command_queue[x.stream], k, x.nThreads, x.nThreads * x.nBlocks, evr, (cl_event*)z.evList, z.nEvents); - if (mProcessingSettings.deviceTimers) { + if (mProcessingSettings.deviceTimers && mProcessingSettings.debugLevel > 0) { cl_ulong time_start, time_end; GPUFailedMsg(clWaitForEvents(1, evr)); GPUFailedMsg(clGetEventProfilingInfo(*evr, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, nullptr)); From 6a4335932910085a0d50a2b0c0bd575e7aa70295 Mon Sep 17 00:00:00 2001 From: Jochen Klein <Jochen.Klein@cern.ch> Date: Fri, 21 Aug 2020 18:36:35 +0200 Subject: [PATCH 0425/1751] Add access to jet constituents --- Analysis/Tutorials/src/jetAnalysis.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Analysis/Tutorials/src/jetAnalysis.cxx b/Analysis/Tutorials/src/jetAnalysis.cxx index 92f6c15ff5616..bc42f586fa14b 100644 --- a/Analysis/Tutorials/src/jetAnalysis.cxx +++ b/Analysis/Tutorials/src/jetAnalysis.cxx @@ -27,21 +27,24 @@ using namespace o2; using namespace o2::framework; struct JetAnalysis { - OutputObj<TH1F> hJetPt{"pt"}; + OutputObj<TH1F> hJetPt{"jetPt"}; + OutputObj<TH1F> hConstPt{"constPt"}; void init(InitContext const&) { - hJetPt.setObject(new TH1F("pt", "jet p_{T};p_{T} (GeV/#it{c})", + hJetPt.setObject(new TH1F("jetPt", "jet p_{T};p_{T} (GeV/#it{c})", 100, 0., 100.)); + hConstPt.setObject(new TH1F("constPt", "constituent p_{T};p_{T} (GeV/#it{c})", + 100, 0., 100.)); } - // TODO: add aod::Tracks (when available) void process(aod::Jet const& jet, - aod::JetConstituents const& constituents) + aod::JetConstituents const& constituents, aod::Tracks const& tracks) { hJetPt->Fill(jet.pt()); for (const auto c : constituents) { - LOGF(INFO, "jet %d: track id %d", jet.index(), c.trackId()); + LOGF(DEBUG, "jet %d: track id %d, track pt %g", jet.index(), c.trackId(), c.track().pt()); + hConstPt->Fill(c.track().pt()); } } }; From 9a50d348a138b037463be96ddbc31a40f4a1f840 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 24 Aug 2020 23:15:33 +0200 Subject: [PATCH 0426/1751] DPL Analysis: introduce policies for index building (#4196) --- Analysis/Tutorials/src/custom_index.cxx | 28 ++- Framework/Core/include/Framework/ASoA.h | 65 +++---- .../Core/include/Framework/AnalysisTask.h | 159 ++++++++++++++++-- .../Core/include/Framework/TableBuilder.h | 70 +------- Framework/Core/src/TableBuilder.cxx | 5 +- Framework/Core/test/test_IndexBuilder.cxx | 37 +++- 6 files changed, 240 insertions(+), 124 deletions(-) diff --git a/Analysis/Tutorials/src/custom_index.cxx b/Analysis/Tutorials/src/custom_index.cxx index a00f0f369d51c..53049a86e2d3f 100644 --- a/Analysis/Tutorials/src/custom_index.cxx +++ b/Analysis/Tutorials/src/custom_index.cxx @@ -20,8 +20,8 @@ DECLARE_SOA_INDEX_COLUMN(Collision, collision); DECLARE_SOA_INDEX_COLUMN(Zdc, zdc); } // namespace indices -DECLARE_SOA_INDEX_TABLE(Matched, BCs, "MATCHED", indices::CollisionId, indices::BCId, indices::ZdcId); - +DECLARE_SOA_INDEX_TABLE(MatchedExclusive, BCs, "MATCHED", indices::CollisionId, indices::BCId, indices::ZdcId); +DECLARE_SOA_INDEX_TABLE(MatchedSparse, BCs, "MATCHED", indices::CollisionId, indices::BCId, indices::ZdcId); } // namespace o2::aod using namespace o2; @@ -33,16 +33,33 @@ using namespace o2::framework::expressions; // FIXME: this should really inherit from AnalysisTask but // we need GCC 7.4+ for that struct ATask { - Builds<aod::Matched> matched; + Builds<aod::MatchedExclusive> matched_e; + Builds<aod::MatchedSparse> matched_s; void init(o2::framework::InitContext&) { } }; struct BTask { - void process(aod::Matched::iterator const& m, aod::Tracks const& tracks) + void process(aod::MatchedExclusive::iterator const& m, aod::Zdcs const&, aod::Tracks const& tracks) + { + LOGF(INFO, "Collision %d; Ntrk: %d", m.collisionId(), tracks.size()); + LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", m.zdc().energyZEM1(), m.zdc().energyZEM2()); + auto t1 = tracks.begin(); + auto t2 = t1 + (tracks.size() - 1); + LOGF(INFO, "track 1 from %d; track %d from %d", t1.collisionId(), tracks.size(), t2.collisionId()); + } +}; + +struct CTask { + void process(aod::MatchedSparse::iterator const& m, aod::Zdcs const&, aod::Tracks const& tracks) { LOGF(INFO, "Collision %d; Ntrk: %d", m.collisionId(), tracks.size()); + if (m.has_zdc()) { + LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", m.zdc().energyZEM1(), m.zdc().energyZEM2()); + } else { + LOGF(INFO, "No ZDC info"); + } auto t1 = tracks.begin(); auto t2 = t1 + (tracks.size() - 1); LOGF(INFO, "track 1 from %d; track %d from %d", t1.collisionId(), tracks.size(), t2.collisionId()); @@ -53,5 +70,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<ATask>("produce-index"), - adaptAnalysisTask<BTask>("consume-index")}; + adaptAnalysisTask<BTask>("consume-index-exclusive"), + adaptAnalysisTask<CTask>("consume-index-sparse")}; } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 70b681c426435..8383117dc153f 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1174,11 +1174,17 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); return *mColumnIterator; \ } \ \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ binding_t::iterator _Getter_() const \ { \ assert(mBinding != nullptr); \ return mBinding->begin() + *mColumnIterator; \ } \ + \ template <typename T> \ bool setCurrent(T* current) \ { \ @@ -1318,35 +1324,32 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); #define DECLARE_SOA_EXTENDED_TABLE_USER(_Name_, _Table_, _Description_, ...) \ DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "AOD", _Description_, __VA_ARGS__) -#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, ...) \ - using _Name_ = o2::soa::IndexTable<_Key_, __VA_ARGS__>; \ - \ - struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ - using Key = _Key_; \ - using index_pack_t = framework::pack<__VA_ARGS__>; \ - using originals = decltype(soa::extractBindings(index_pack_t{})); \ - static constexpr char const* mLabel = #_Name_; \ - static constexpr char const mOrigin[4] = _Origin_; \ - static constexpr char const mDescription[16] = _Description_; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_> { \ - using metadata = _Name_##Metadata; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_::base_t> { \ - using metadata = _Name_##Metadata; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_::iterator> { \ - using metadata = _Name_##Metadata; \ - }; \ - template <> \ - struct MetadataTrait<_Name_::base_t::iterator> { \ - using metadata = _Name_##Metadata; \ +#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, ...) \ + struct _Name_ : o2::soa::IndexTable<_Key_, __VA_ARGS__> { \ + _Name_(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : o2::soa::IndexTable<_Key_, __VA_ARGS__>(table, offset){}; \ + _Name_(_Name_ const&) = default; \ + _Name_(_Name_&&) = default; \ + using iterator = typename base_t::template RowView<_Name_, _Name_>; \ + using const_iterator = iterator; \ + }; \ + \ + struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ + using Key = _Key_; \ + using index_pack_t = framework::pack<__VA_ARGS__>; \ + using originals = decltype(soa::extractBindings(index_pack_t{})); \ + static constexpr char const* mLabel = #_Name_; \ + static constexpr char const mOrigin[4] = _Origin_; \ + static constexpr char const mDescription[16] = _Description_; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_> { \ + using metadata = _Name_##Metadata; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_::iterator> { \ + using metadata = _Name_##Metadata; \ }; #define DECLARE_SOA_INDEX_TABLE(_Name_, _Key_, _Description_, ...) \ @@ -1765,12 +1768,12 @@ struct IndexTable : Table<soa::Index<>, H, Ts...> { IndexTable& operator=(IndexTable const&) = default; IndexTable& operator=(IndexTable&&) = default; - using iterator = typename base_t::template RowView<IndexTable<Key, H, Ts...>, base_t>; + using iterator = typename base_t::template RowView<IndexTable<Key, H, Ts...>, IndexTable<Key, H, Ts...>>; using const_iterator = iterator; }; template <typename T> -using is_soa_index_table_t = typename framework::is_specialization<T, soa::IndexTable>; +using is_soa_index_table_t = typename framework::is_base_of_template<soa::IndexTable, T>; } // namespace o2::soa diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 282853328d2db..42b1f4f20aeae 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -208,8 +208,131 @@ struct Spawns : TransformTable<T> { } }; +/// Policy to control index building +/// Exclusive index: each entry in a row has a valid index +struct IndexExclusive { + /// Generic builder for in index table + template <typename... Cs, typename Key, typename T1, typename... T> + static auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) + { + static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); + using tables_t = framework::pack<T...>; + using first_t = T1; + auto tail = tuple_tail(tables); + TableBuilder builder; + auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); + + std::array<int32_t, sizeof...(T)> values; + iterator_tuple_t<std::decay_t<T>...> iterators = std::apply( + [](auto&&... x) { + return std::make_tuple(x.begin()...); + }, + tail); + + using rest_it_t = decltype(pack_from_tuple(iterators)); + + int32_t idx = -1; + auto setValue = [&](auto& x) -> bool { + using type = std::decay_t<decltype(x)>; + constexpr auto position = framework::has_type_at<type>(rest_it_t{}); + + lowerBound<Key>(idx, x); + if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { + return false; + } else if (x.template getId<Key>() != idx) { + return false; + } else { + values[position] = x.globalIndex(); + ++x; + return true; + } + }; + + auto first = std::get<first_t>(tables); + for (auto& row : first) { + idx = row.template getId<Key>(); + + if (std::apply( + [](auto&... x) { + return ((x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) && ...); + }, + iterators)) { + break; + } + + auto result = std::apply( + [&](auto&... x) { + std::array<bool, sizeof...(T)> results{setValue(x)...}; + return (results[framework::has_type_at<std::decay_t<decltype(x)>>(rest_it_t{})] && ...); + }, + iterators); + + if (result) { + cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); + } + } + return builder.finalize(); + } +}; +/// Sparse index: values in a row can be (-1), index table is isomorphic (joinable) +/// to T1 +struct IndexSparse { + template <typename... Cs, typename Key, typename T1, typename... T> + static auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) + { + static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); + using tables_t = framework::pack<T...>; + using first_t = T1; + auto tail = tuple_tail(tables); + TableBuilder builder; + auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); + + std::array<int32_t, sizeof...(T)> values; + + iterator_tuple_t<std::decay_t<T>...> iterators = std::apply( + [](auto&&... x) { + return std::make_tuple(x.begin()...); + }, + tail); + + using rest_it_t = decltype(pack_from_tuple(iterators)); + + int32_t idx = -1; + auto setValue = [&](auto& x) -> bool { + using type = std::decay_t<decltype(x)>; + constexpr auto position = framework::has_type_at<type>(rest_it_t{}); + + lowerBound<Key>(idx, x); + if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { + values[position] = -1; + return false; + } else if (x.template getId<Key>() != idx) { + values[position] = -1; + return false; + } else { + values[position] = x.globalIndex(); + ++x; + return true; + } + }; + + auto first = std::get<first_t>(tables); + for (auto& row : first) { + idx = row.template getId<Key>(); + std::apply( + [&](auto&... x) { + (setValue(x), ...); + }, + iterators); + + cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); + } + return builder.finalize(); + } +}; + /// This helper struct allows you to declare index tables to be created in a task -template <typename T> +template <typename T, typename IP = IndexSparse> struct Builds : TransformTable<T> { using metadata = typename TransformTable<T>::metadata; using originals = typename metadata::originals; @@ -222,8 +345,18 @@ struct Builds : TransformTable<T> { { return index_pack_t{}; } + + template <typename... Cs, typename Key, typename T1, typename... Ts> + auto build(framework::pack<Cs...>, Key const& key, std::tuple<T1, Ts...> tables) + { + this->table = std::make_shared<T>(IP::indexBuilder(framework::pack<Cs...>{}, key, tables)); + return (this->table != nullptr); + } }; +template <typename T> +using BuildsExclusive = Builds<T, IndexExclusive>; + /// This helper class allows you to declare things which will be created by a /// given analysis task. Currently wrapped objects are limited to be TNamed /// descendants. Objects will be written to a ROOT file at the end of the @@ -1079,28 +1212,28 @@ static auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) return std::make_tuple(extractTypedOriginal<Os>(pc)...); } -template <typename T> -struct OutputManager<Builds<T>> { - static bool appendOutput(std::vector<OutputSpec>& outputs, Builds<T>& what, uint32_t) +template <typename T, typename P> +struct OutputManager<Builds<T, P>> { + static bool appendOutput(std::vector<OutputSpec>& outputs, Builds<T, P>& what, uint32_t) { outputs.emplace_back(what.spec()); return true; } - static bool prepare(ProcessingContext& pc, Builds<T>& what) + static bool prepare(ProcessingContext& pc, Builds<T, P>& what) { using metadata = typename std::decay_t<decltype(what)>::metadata; - auto source_tables = extractOriginalsTuple(typename metadata::originals{}, pc); - what.table = std::make_shared<T>(indexBuilder(typename metadata::index_pack_t{}, extractTypedOriginal<typename metadata::Key>(pc), source_tables)); - return true; + return what.build(typename metadata::index_pack_t{}, + extractTypedOriginal<typename metadata::Key>(pc), + extractOriginalsTuple(typename metadata::originals{}, pc)); } - static bool finalize(ProcessingContext&, Builds<T>&) + static bool finalize(ProcessingContext&, Builds<T, P>&) { return true; } - static bool postRun(EndOfStreamContext& eosc, Builds<T>& what) + static bool postRun(EndOfStreamContext& eosc, Builds<T, P>& what) { using metadata = typename std::decay_t<decltype(what)>::metadata; eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); @@ -1215,9 +1348,9 @@ struct IndexManager { static bool requestInputs(std::vector<InputSpec>&, T const&) { return false; }; }; -template <typename IDX> -struct IndexManager<Builds<IDX>> { - static bool requestInputs(std::vector<InputSpec>& inputs, Builds<IDX>& builds) +template <typename IDX, typename P> +struct IndexManager<Builds<IDX, P>> { + static bool requestInputs(std::vector<InputSpec>& inputs, Builds<IDX, P>& builds) { auto base_specs = builds.base_specs(); for (auto& base_spec : base_specs) { diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index 0b725bbdc5bf7..9cc22025c0d46 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -38,12 +38,11 @@ class Table; class Array; } // namespace arrow -namespace o2 -{ -namespace framework +namespace o2::framework { namespace detail { +/// FIXME: adapt type conversion to arrow 1.0 // This is needed by Arrow 0.12.0 which dropped // // using ArrowType = ArrowType_; @@ -637,68 +636,5 @@ void lowerBound(int32_t value, T& start) template <typename... T> using iterator_tuple_t = std::tuple<typename T::iterator...>; - -/// Generic builder for in index table -template <typename... Cs, typename Key, typename T1, typename... T> -auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) -{ - static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); - using tables_t = framework::pack<T...>; - using first_t = T1; - auto tail = tuple_tail(tables); - TableBuilder builder; - auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); - - std::array<int32_t, sizeof...(T)> values; - iterator_tuple_t<std::decay_t<T>...> begins = std::apply( - [](auto&&... x) { - return std::make_tuple(x.begin()...); - }, - tail); - - using rest_it_t = decltype(pack_from_tuple(begins)); - - auto first = std::get<first_t>(tables); - for (auto& row : first) { - auto idx = row.template getId<Key>(); - auto setValue = [&](auto& x) -> bool { - using type = std::decay_t<decltype(x)>; - constexpr auto position = framework::has_type_at<type>(rest_it_t{}); - - lowerBound<Key>(idx, x); - if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { - return false; - } else if (x.template getId<Key>() != idx) { - return false; - } else { - values[position] = x.globalIndex(); - ++x; - return true; - } - }; - - if (std::apply( - [](auto&... x) { - return ((x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) && ...); - }, - begins)) { - break; - } - - auto result = std::apply( - [&](auto&... x) { - std::array<bool, sizeof...(T)> results{setValue(x)...}; - return (results[framework::has_type_at<std::decay_t<decltype(x)>>(rest_it_t{})] && ...); - }, - begins); - - if (result) { - cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); - } - } - return builder.finalize(); -} - -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif // FRAMEWORK_TABLEBUILDER_H diff --git a/Framework/Core/src/TableBuilder.cxx b/Framework/Core/src/TableBuilder.cxx index c52ba0dda8827..6c88e0477c97c 100644 --- a/Framework/Core/src/TableBuilder.cxx +++ b/Framework/Core/src/TableBuilder.cxx @@ -53,12 +53,11 @@ std::shared_ptr<arrow::Table> mFinalizer(); std::vector<std::shared_ptr<arrow::ChunkedArray>> columns; columns.reserve(mArrays.size()); - for (size_t i = 0; i < mSchema->num_fields(); ++i) { + for (auto i = 0; i < mSchema->num_fields(); ++i) { auto column = std::make_shared<arrow::ChunkedArray>(mArrays[i]); columns.emplace_back(column); } - auto table_ = arrow::Table::Make(mSchema, columns); - return table_; + return arrow::Table::Make(mSchema, columns); } } // namespace o2::framework diff --git a/Framework/Core/test/test_IndexBuilder.cxx b/Framework/Core/test/test_IndexBuilder.cxx index 59ec528f80ee0..907f160a6a0d0 100644 --- a/Framework/Core/test/test_IndexBuilder.cxx +++ b/Framework/Core/test/test_IndexBuilder.cxx @@ -13,7 +13,7 @@ #define BOOST_TEST_DYN_LINK #include "Framework/AnalysisDataModel.h" -#include "Framework/TableBuilder.h" +#include "Framework/AnalysisTask.h" #include <boost/test/unit_test.hpp> using namespace o2::framework; @@ -75,9 +75,9 @@ BOOST_AUTO_TEST_CASE(TestIndexBuilder) w1(0, i * 2., i * 3., i * 4.); } - std::array<int, 7> d = {0, 1, 2, 4, 7, 8, 9}; - std::array<int, 5> f = {0, 1, 2, 5, 8}; - std::array<int, 7> c = {0, 1, 2, 3, 5, 7, 8}; + std::array<int, 7> d{0, 1, 2, 4, 7, 8, 9}; + std::array<int, 5> f{0, 1, 2, 5, 8}; + std::array<int, 7> c{0, 1, 2, 3, 5, 7, 8}; for (auto i : d) { w2(0, i, i * 10.); @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(TestIndexBuilder) auto t4 = b4.finalize(); Categorys st4{t4}; - auto t5 = indexBuilder(typename IDXs::persistent_columns_t{}, st1, std::tie(st1, st2, st3, st4)); + auto t5 = IndexExclusive::indexBuilder(typename IDXs::persistent_columns_t{}, st1, std::tie(st1, st2, st3, st4)); BOOST_REQUIRE_EQUAL(t5->num_rows(), 4); IDXs idxt{t5}; idxt.bindExternalIndices(&st1, &st2, &st3, &st4); @@ -109,4 +109,31 @@ BOOST_AUTO_TEST_CASE(TestIndexBuilder) BOOST_REQUIRE(row.flag().pointId() == row.pointId()); BOOST_REQUIRE(row.category().pointId() == row.pointId()); } + + auto t6 = IndexSparse::indexBuilder(typename IDXs::persistent_columns_t{}, st1, std::tie(st1, st2, st3, st4)); + BOOST_REQUIRE_EQUAL(t6->num_rows(), st1.size()); + IDXs idxs{t6}; + std::array<int, 10> ds{0, 1, 2, -1, 4, -1, -1, 7, 8, 9}; + std::array<int, 10> fs{0, 1, 2, -1, -1, 5, -1, -1, 8, -1}; + std::array<int, 10> cs{0, 1, 2, 3, -1, 5, -1, 7, 8, -1}; + idxs.bindExternalIndices(&st1, &st2, &st3, &st4); + auto i = 0; + for (auto& row : idxs) { + if (row.has_distance()) { + BOOST_REQUIRE(row.distance().pointId() == ds[i]); + } else { + BOOST_REQUIRE(row.distanceId() == ds[i]); + } + if (row.has_flag()) { + BOOST_REQUIRE(row.flag().pointId() == fs[i]); + } else { + BOOST_REQUIRE(row.flagId() == fs[i]); + } + if (row.has_category()) { + BOOST_REQUIRE(row.category().pointId() == cs[i]); + } else { + BOOST_REQUIRE(row.categoryId() == cs[i]); + } + ++i; + } } From f4f1c0534de5ea684511583e95d28f072a190c28 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 24 Aug 2020 23:20:56 +0200 Subject: [PATCH 0427/1751] Do not include runDataProcessing.h in DataModel (#4199) --- Analysis/DataModel/include/PID/PIDResponse.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/PID/PIDResponse.h index bd228af285129..96f8dd79821e8 100644 --- a/Analysis/DataModel/include/PID/PIDResponse.h +++ b/Analysis/DataModel/include/PID/PIDResponse.h @@ -20,7 +20,6 @@ // O2 includes #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "ReconstructionDataFormats/Track.h" From 8d50afaaa2c4fc65548dfd74dff74664c1b182b7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 25 Aug 2020 01:34:26 +0200 Subject: [PATCH 0428/1751] Analysis: add a few more tables to the data model diagram (#4200) --- Analysis/DataModel/src/dumpDataModel.cxx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Analysis/DataModel/src/dumpDataModel.cxx b/Analysis/DataModel/src/dumpDataModel.cxx index d88b7ba67f16b..4e9ae1f748307 100644 --- a/Analysis/DataModel/src/dumpDataModel.cxx +++ b/Analysis/DataModel/src/dumpDataModel.cxx @@ -9,6 +9,11 @@ // or submit itself to any jurisdiction. #include "Framework/AnalysisDataModel.h" #include "Analysis/SecondaryVertex.h" +#include "Analysis/SecondaryVertexHF.h" +#include "PID/PIDResponse.h" +#include "Analysis/Multiplicity.h" +#include "Analysis/Centrality.h" +#include "Analysis/TrackSelectionTables.h" #include "Analysis/Jet.h" #include <fmt/printf.h> #include <map> @@ -146,11 +151,12 @@ size="5,5" node[shape=plain,style=filled,fillcolor=gray95] edge[dir=back, arrowtail=empty] )"); - dumpCluster<Tracks, TracksCov, TracksExtra>(); + dumpCluster<Tracks, TracksCov, TracksExtra, TracksExtended, TrackSelection>(); dumpTable<Collisions>(); dumpTable<Calos>(); dumpTable<CaloTriggers>(); dumpTable<Muons>(); + dumpTable<StoredMuons>(); dumpTable<MuonClusters>(); dumpTable<Zdcs>(); dumpTable<Run2V0s>(); @@ -160,8 +166,17 @@ edge[dir=back, arrowtail=empty] dumpTable<FT0s>(); dumpTable<FV0s>(); dumpTable<FDDs>(); + dumpTable<Timestamps>(); dumpTable<SecVtx2Prong>(true, StyleType::GREEN); dumpTable<Cand2Prong>(true, StyleType::GREEN); + dumpTable<HfTrackIndexProng2>(true, StyleType::GREEN); + dumpTable<HfTrackIndexProng3>(true, StyleType::GREEN); + + dumpTable<pidRespTOF>(true, StyleType::GREEN); + dumpTable<pidRespTPC>(true, StyleType::GREEN); + dumpTable<Mults>(true, StyleType::GREEN); + dumpTable<Cents>(true, StyleType::GREEN); + dumpTable<Jets>(true, StyleType::BLUE); dumpTable<JetConstituents>(true, StyleType::BLUE); dumpTable<UnassignedTracks>(); From 45fcc742a328384c2ccc66c2f1cf7f511a3b64e7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 20 Aug 2020 18:49:38 +0200 Subject: [PATCH 0429/1751] GPU: Don't obtain timer objects when they are not required --- GPU/GPUTracking/Base/GPUReconstructionCPU.h | 12 ++++++------ GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 2 +- .../Base/hip/GPUReconstructionHIP.hip.cxx | 2 +- .../Base/opencl-common/GPUReconstructionOCL.cxx | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.h b/GPU/GPUTracking/Base/GPUReconstructionCPU.h index 4ec3c3edee858..8b0bc183d70a1 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.h +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.h @@ -273,7 +273,7 @@ inline int GPUReconstructionCPU::runKernel(const krnlExec& x, const krnlRunRange if (nThreads == 0 || nBlocks == 0) { return 0; } - if (mProcessingSettings.debugLevel >= 0) { + if (mProcessingSettings.debugLevel >= 1) { t = &getKernelTimer<S, I, J>(myStep, !IsGPU() || cpuFallback ? getOMPThreadNum() : x.stream); if (!mProcessingSettings.deviceTimers || !IsGPU() || cpuFallback) { t->Start(); @@ -289,10 +289,10 @@ inline int GPUReconstructionCPU::runKernel(const krnlExec& x, const krnlRunRange return 1; } } - if (mProcessingSettings.debugLevel >= 0) { - if (GPUDebug(GetKernelName<S, I>(), x.stream)) { - throw std::runtime_error("kernel failure"); - } + if (GPUDebug(GetKernelName<S, I>(), x.stream)) { + throw std::runtime_error("kernel failure"); + } + if (mProcessingSettings.debugLevel >= 1) { if (t) { if (!mProcessingSettings.deviceTimers || !IsGPU() || cpuFallback) { t->Stop(); @@ -300,7 +300,7 @@ inline int GPUReconstructionCPU::runKernel(const krnlExec& x, const krnlRunRange t->AddTime(setup.t); } } - if (mProcessingSettings.debugLevel >= 1 && CheckErrorCodes(cpuFallback)) { + if (CheckErrorCodes(cpuFallback)) { throw std::runtime_error("kernel error code"); } } diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index e8ac56ab1afe4..2eb78b46afaea 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -619,7 +619,7 @@ int GPUReconstructionCUDABackend::GPUDebug(const char* state, int stream) GPUError("Cuda Error %s while running kernel (%s) (Stream %d)", cudaGetErrorString(cuErr), state, stream); return (1); } - if (mProcessingSettings.debugLevel == 0) { + if (mProcessingSettings.debugLevel <= 0) { return (0); } if (GPUFailedMsgI(cudaDeviceSynchronize())) { diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index 7f93338f4b2cd..c598317071b1c 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -554,7 +554,7 @@ int GPUReconstructionHIPBackend::GPUDebug(const char* state, int stream) GPUError("HIP Error %s while running kernel (%s) (Stream %d)", hipGetErrorString(cuErr), state, stream); return (1); } - if (mProcessingSettings.debugLevel == 0) { + if (mProcessingSettings.debugLevel <= 0) { return (0); } if (GPUFailedMsgI(hipDeviceSynchronize())) { diff --git a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx index 15970c59f7163..15b6076b4b4e8 100644 --- a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx +++ b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx @@ -465,7 +465,7 @@ bool GPUReconstructionOCL::IsEventDone(deviceEvent* evList, int nEvents) int GPUReconstructionOCL::GPUDebug(const char* state, int stream) { // Wait for OPENCL-Kernel to finish and check for OPENCL errors afterwards, in case of debugmode - if (mProcessingSettings.debugLevel == 0) { + if (mProcessingSettings.debugLevel <= 0) { return (0); } for (int i = 0; i < mNStreams; i++) { From 657498cb7c806072e9d03b93612004bf4cfacc31 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Tue, 25 Aug 2020 08:39:20 +0200 Subject: [PATCH 0430/1751] Moved the DQ analysis tasks in dedicated PWGDQ directory (#4198) Co-authored-by: Ionut Arsene <iarsene@cern.ch> --- Analysis/Tasks/CMakeLists.txt | 12 ++---------- Analysis/Tasks/PWGDQ/CMakeLists.txt | 9 +++++++++ Analysis/Tasks/{ => PWGDQ}/tableMaker.cxx | 0 Analysis/Tasks/{ => PWGDQ}/tableReader.cxx | 0 4 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 Analysis/Tasks/PWGDQ/CMakeLists.txt rename Analysis/Tasks/{ => PWGDQ}/tableMaker.cxx (100%) rename Analysis/Tasks/{ => PWGDQ}/tableReader.cxx (100%) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 3569d83a655b1..407b20581aa04 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -8,6 +8,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +add_subdirectory(PWGDQ) + o2_add_dpl_workflow(trackselection SOURCES trackselection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore @@ -116,16 +118,6 @@ o2_add_dpl_workflow(centrality-qa PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) -o2_add_dpl_workflow(table-maker - SOURCES tableMaker.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore - COMPONENT_NAME Analysis) - -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(timestamp SOURCES timestamp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::DetectorsRaw O2::AnalysisCore O2::CommonDataFormat O2::CCDB diff --git a/Analysis/Tasks/PWGDQ/CMakeLists.txt b/Analysis/Tasks/PWGDQ/CMakeLists.txt new file mode 100644 index 0000000000000..9eac2e83b667b --- /dev/null +++ b/Analysis/Tasks/PWGDQ/CMakeLists.txt @@ -0,0 +1,9 @@ +o2_add_dpl_workflow(table-maker + SOURCES tableMaker.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(table-reader + SOURCES tableReader.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx similarity index 100% rename from Analysis/Tasks/tableMaker.cxx rename to Analysis/Tasks/PWGDQ/tableMaker.cxx diff --git a/Analysis/Tasks/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx similarity index 100% rename from Analysis/Tasks/tableReader.cxx rename to Analysis/Tasks/PWGDQ/tableReader.cxx From e816d36b6bcaefdc185c57bcc18821b4350d5773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 25 Aug 2020 08:43:12 +0200 Subject: [PATCH 0431/1751] Extend RecoDecay, candidate tables and tasks. (#4201) Add more RecoDecay functions. Add more columns to candidate tables. Add helper function for getting primary vertex. Rearrange code. Reorganise namespaces. Clean up code (includes, namespaces). Improve naming of variables. Improve documentation. --- .../DataModel/include/Analysis/RecoDecay.h | 95 ++++++- .../include/Analysis/SecondaryVertexHF.h | 248 +++++++++++++----- .../include/Analysis/trackUtilities.h | 17 +- Analysis/Tasks/hfcandidatecreator2prong.cxx | 126 +++++---- Analysis/Tasks/hftrackindexskimscreator.cxx | 203 +++++++------- Analysis/Tasks/taskdzero.cxx | 48 ++-- 6 files changed, 508 insertions(+), 229 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index 8fafada78433f..06c3561c1931d 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -51,6 +51,16 @@ class RecoDecay return (args + ...); } + /// Squares a number. + /// \note Promotes number to double before squaring to avoid precision loss in float multiplication. + /// \param num a number of arbitrary type + /// \return number squared + template <typename T> + auto static sq(T num) + { + return (double)num * (double)num; + } + /// Sums squares of numbers. /// \note Promotes numbers to double before squaring to avoid precision loss in float multiplication. /// \param args arbitrary number of numbers of arbitrary types @@ -152,7 +162,7 @@ class RecoDecay /// \param mass mass /// \return rapidity template <typename T, typename U> - static auto Rapidity(const array<T, 3>& mom, U mass) + static auto Y(const array<T, 3>& mom, U mass) { // y = arctanh(pz/E) return std::atanh(mom[2] / E(mom, mass)); @@ -206,12 +216,89 @@ class RecoDecay /// \param length decay length /// \return proper lifetime times c template <typename T, typename U, typename V> - static auto Ct(array<T, 3> mom, U mass, V length) + static auto Ct(const array<T, 3>& mom, U length, V mass) { // c t = l m c^2/(p c) return (double)length * (double)mass / P(mom); } + /// Calculates cosine of θ* (theta star). + /// \note Implemented for 2 prongs only. + /// \note "Multiply by gamma" version + /// \param arrMom array of two 3-momentum arrays + /// \param arrMass array of two masses (in the same order as arrMom) + /// \param iProng index of the prong + /// \return cosine of θ* of the i-th prong + template <typename T, typename U> + static auto CosThetaStarM(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) + { + auto eProng = E(arrMom[iProng], arrMass[iProng]); // energy of the prong + auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the 2-prong system + auto pTot = P(pVecTot); // magnitude of the momentum of the 2-prong system + auto mTot = M(arrMom, arrMass); // invariant mass of the 2-prong system + auto eTot = eProng + E(arrMom[1 - iProng], arrMass[1 - iProng]); // energy of the 2-prong system + auto gamma = eTot / mTot; // γ, Lorentz gamma factor of the 2-prong system + auto beta = pTot / eTot; // β, velocity of the 2-prong system + auto pStar = std::sqrt(sq(sq(mTot) - sq(arrMass[0]) - sq(arrMass[1])) - sq(2 * arrMass[0] * arrMass[1])) / (2 * mTot); // p*, prong momentum in the rest frame of the 2-prong system + // p* = √[(M^2 - m1^2 - m2^2)^2 - 4 m1^2 m2^2]/2M + // Lorentz transformation of the longitudinal momentum of the prong into the rest frame of the 2-prong system: + // p*_L,i = γ (p_L,i - β E_i) + // p*_L,i = p* cos(θ*_i) + // cos(θ*_i) = γ (p_L,i - β E_i)/p* + return gamma * (dotProd(arrMom[iProng], pVecTot) / pTot - beta * eProng) / pStar; + } + + /// Calculates cosine of θ* (theta star). + /// \note Implemented for 2 prongs only. + /// \note "Divide by gamma" version + /// \param arrMom array of two 3-momentum arrays + /// \param arrMass array of two masses (in the same order as arrMom) + /// \param iProng index of the prong + /// \return cosine of θ* of the i-th prong + template <typename T, typename U> + static auto CosThetaStarD(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) + { + auto eProng = E(arrMom[iProng], arrMass[iProng]); // energy of the prong + auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the 2-prong system + auto pTot = P(pVecTot); // magnitude of the momentum of the 2-prong system + auto mTot = M(arrMom, arrMass); // invariant mass of the 2-prong system + auto eTot = eProng + E(arrMom[1 - iProng], arrMass[1 - iProng]); // energy of the 2-prong system + auto gamma = eTot / mTot; // γ, Lorentz gamma factor of the 2-prong system + auto beta = pTot / eTot; // β, velocity of the 2-prong system + auto pStar = std::sqrt(sq(sq(mTot) - sq(arrMass[0]) - sq(arrMass[1])) - sq(2 * arrMass[0] * arrMass[1])) / (2 * mTot); // p*, prong momentum in the rest frame of the 2-prong system + // p* = √[(M^2 - m1^2 - m2^2)^2 - 4 m1^2 m2^2]/2M + // Lorentz transformation of the longitudinal momentum of the prong into the detector frame: + // p_L,i = γ (p*_L,i + β E*_i) + // p*_L,i = p_L,i/γ - β E*_i (less sensitive too incorrect masses?) + // cos(θ*_i) = (p_L,i/γ - β E*_i)/p* + return (dotProd(arrMom[iProng], pVecTot) / (pTot * gamma) - beta * E(pStar, arrMass[iProng])) / pStar; + } + + /// Calculates cosine of θ* (theta star). + /// \note Implemented for 2 prongs only. + /// \note AliRoot version + /// \param arrMom array of two 3-momentum arrays + /// \param arrMass array of two masses (in the same order as arrMom) + /// \param iProng index of the prong + /// \param mTot assumed mass of mother particle + /// \return cosine of θ* of the i-th prong under the assumption of the invariant mass + template <typename T, typename U, typename V> + static auto CosThetaStarA(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, V mTot, int iProng) + { + auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the mother particle + auto pTot = P(pVecTot); // magnitude of the momentum of the mother particle + auto eTot = E(pTot, mTot); // energy of the mother particle + auto gamma = eTot / mTot; // γ, Lorentz gamma factor of the mother particle + auto beta = pTot / eTot; // β, velocity of the mother particle + auto pStar = std::sqrt(sq(sq(mTot) - sq(arrMass[0]) - sq(arrMass[1])) - sq(2 * arrMass[0] * arrMass[1])) / (2 * mTot); // p*, prong momentum in the rest frame of the mother particle + // p* = √[(M^2 - m1^2 - m2^2)^2 - 4 m1^2 m2^2]/2M + // Lorentz transformation of the longitudinal momentum of the prong into the detector frame: + // p_L,i = γ (p*_L,i + β E*_i) + // p*_L,i = p_L,i/γ - β E*_i) + // cos(θ*_i) = (p_L,i/γ - β E*_i)/p* + return (dotProd(arrMom[iProng], pVecTot) / (pTot * gamma) - beta * E(pStar, arrMass[iProng])) / pStar; + } + /// Sums 3-momenta. /// \param args pack of 3-momentum arrays /// \return total 3-momentum array @@ -299,7 +386,7 @@ class RecoDecay /// \param args 3-momentum array, mass /// \return energy template <typename... T> - static auto E(T... args) + static auto E(const T&... args) { return std::sqrt(E2(args...)); } @@ -348,7 +435,7 @@ class RecoDecay /// \param args array of momenta, array of masses /// \return invariant mass template <typename... T> - static auto M(T... args) + static auto M(const T&... args) { return std::sqrt(M2(args...)); } diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index 0c679ce6dc733..2a1f3d237745a 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -7,6 +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. + +/// \file SecondaryVertexHF.h +/// \brief Definitions of tables of heavy-flavour decay candidates. +/// +/// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + #ifndef O2_ANALYSIS_SECONDARYVERTEXHF_H_ #define O2_ANALYSIS_SECONDARYVERTEXHF_H_ @@ -15,84 +22,201 @@ namespace o2::aod { -namespace hftrackindexprong2 -{ // FIXME: this is a workaround until we get the index columns to work with joins. using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra>; +namespace hf_track_index +{ DECLARE_SOA_INDEX_COLUMN(Collision, collision); DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, BigTracks, "fIndex0"); DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, BigTracks, "fIndex1"); +DECLARE_SOA_INDEX_COLUMN_FULL(Index2, index2, int, BigTracks, "fIndex2"); +DECLARE_SOA_INDEX_COLUMN_FULL(Index3, index3, int, BigTracks, "fIndex3"); DECLARE_SOA_COLUMN(HFflag, hfflag, int); -} // namespace hftrackindexprong2 +} // namespace hf_track_index -namespace hftrackindexprong3 +DECLARE_SOA_TABLE(HfTrackIndexProng2, "AOD", "HFTRACKIDXP2", + hf_track_index::CollisionId, + hf_track_index::Index0Id, + hf_track_index::Index1Id, + hf_track_index::HFflag); + +DECLARE_SOA_TABLE(HfTrackIndexProng3, "AOD", "HFTRACKIDXP3", + hf_track_index::CollisionId, + hf_track_index::Index0Id, + hf_track_index::Index1Id, + hf_track_index::Index2Id, + hf_track_index::HFflag); + +// general decay properties +namespace hf_cand { -// FIXME: this is a workaround until we get the index columns to work with joins. -using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra>; +// secondary vertex +DECLARE_SOA_COLUMN(XSecondaryVertex, xSecondaryVertex, float); +DECLARE_SOA_COLUMN(YSecondaryVertex, ySecondaryVertex, float); +DECLARE_SOA_COLUMN(ZSecondaryVertex, zSecondaryVertex, float); +DECLARE_SOA_DYNAMIC_COLUMN(RSecondaryVertex, rSecondaryVertex, [](float xVtxS, float yVtxS) { return RecoDecay::sqrtSumOfSquares(xVtxS, yVtxS); }); +// prong properties +DECLARE_SOA_COLUMN(PxProng0, pxProng0, float); +DECLARE_SOA_COLUMN(PyProng0, pyProng0, float); +DECLARE_SOA_COLUMN(PzProng0, pzProng0, float); +DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, [](float px, float py) { return RecoDecay::Pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong0, pt2Prong0, [](float px, float py) { return RecoDecay::Pt2(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng0, pVectorProng0, [](float px, float py, float pz) { return array{px, py, pz}; }); +DECLARE_SOA_COLUMN(ImpactParameter0, impactParameter0, float); +DECLARE_SOA_COLUMN(ErrorImpactParameter0, errorImpactParameter0, float); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, [](float dca, float err) { return dca / err; }); +DECLARE_SOA_COLUMN(PxProng1, pxProng1, float); +DECLARE_SOA_COLUMN(PyProng1, pyProng1, float); +DECLARE_SOA_COLUMN(PzProng1, pzProng1, float); +DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, [](float px, float py) { return RecoDecay::Pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong1, pt2Prong1, [](float px, float py) { return RecoDecay::Pt2(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng1, pVectorProng1, [](float px, float py, float pz) { return array{px, py, pz}; }); +DECLARE_SOA_COLUMN(ImpactParameter1, impactParameter1, float); +DECLARE_SOA_COLUMN(ErrorImpactParameter1, errorImpactParameter1, float); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, [](float dca, float err) { return dca / err; }); +DECLARE_SOA_COLUMN(PxProng2, pxProng2, float); +DECLARE_SOA_COLUMN(PyProng2, pyProng2, float); +DECLARE_SOA_COLUMN(PzProng2, pzProng2, float); +DECLARE_SOA_DYNAMIC_COLUMN(PtProng2, ptProng2, [](float px, float py) { return RecoDecay::Pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong2, pt2Prong2, [](float px, float py) { return RecoDecay::Pt2(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng2, pVectorProng2, [](float px, float py, float pz) { return array{px, py, pz}; }); +DECLARE_SOA_COLUMN(ImpactParameter2, impactParameter2, float); +DECLARE_SOA_COLUMN(ErrorImpactParameter2, errorImpactParameter2, float); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, [](float dca, float err) { return dca / err; }); +// candidate properties +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) { return RecoDecay::Pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt2, pt2, [](float px, float py) { return RecoDecay::Pt2(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) { return RecoDecay::P(px, py, pz); }); +DECLARE_SOA_DYNAMIC_COLUMN(P2, p2, [](float px, float py, float pz) { return RecoDecay::P2(px, py, pz); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, [](float px, float py, float pz) { return array{px, py, pz}; }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) { return RecoDecay::Eta(array{px, py, pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Y, y, [](float px, float py, float pz, double m) { return RecoDecay::Y(array{px, py, pz}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(E, e, [](float px, float py, float pz, double m) { return RecoDecay::E(px, py, pz, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(E2, e2, [](float px, float py, float pz, double m) { return RecoDecay::E2(px, py, pz, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(DecayLength, decayLength, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) { return RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}); }); +DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthXY, decayLengthXY, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS) { return RecoDecay::distanceXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}); }); +DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthNormalised, decayLengthNormalised, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float err) { return RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}) / err; }); +DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float err) { return RecoDecay::distanceXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}) / err; }); +DECLARE_SOA_COLUMN(ErrorDecayLength, errorDecayLength, float); +DECLARE_SOA_COLUMN(ErrorDecayLengthXY, errorDecayLengthXY, float); +DECLARE_SOA_DYNAMIC_COLUMN(CPA, cpa, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) { return RecoDecay::CPA(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(CPAXY, cpaXY, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float px, float py) { return RecoDecay::CPAXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, array{px, py}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Ct, ct, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) { return RecoDecay::Ct(array{px, py, pz}, RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}), m); }); +} // namespace hf_cand -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, BigTracks, "fIndex0"); -DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, BigTracks, "fIndex1"); -DECLARE_SOA_INDEX_COLUMN_FULL(Index2, index2, int, BigTracks, "fIndex2"); -DECLARE_SOA_COLUMN(HFflag, hfflag, int); -} // namespace hftrackindexprong3 +// specific 2-prong decay properties +namespace hf_cand_prong2 +{ +DECLARE_SOA_COLUMN(DCA, dca, float); +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, 1.f * aod::hf_cand::pxProng0 + 1.f * aod::hf_cand::pxProng1); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, 1.f * aod::hf_cand::pyProng0 + 1.f * aod::hf_cand::pyProng1); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, [](float dca1, float dca2) { return dca1 * dca2; }); +DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m, double mTot, int iProng) { return RecoDecay::CosThetaStarA(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); + +// functions for specific particles + +// D0(bar) → π± K∓ -namespace hfcandprong2 +template <typename T> +auto CtD0(T candidate) { -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -DECLARE_SOA_COLUMN(PxProng0, pxprong0, float); -DECLARE_SOA_COLUMN(PyProng0, pyprong0, float); -DECLARE_SOA_COLUMN(PzProng0, pzprong0, float); -DECLARE_SOA_COLUMN(PxProng1, pxprong1, float); -DECLARE_SOA_COLUMN(PyProng1, pyprong1, float); -DECLARE_SOA_COLUMN(PzProng1, pzprong1, float); -DECLARE_SOA_COLUMN(DecayVtxX, decayvtxx, float); -DECLARE_SOA_COLUMN(DecayVtxY, decayvtxy, float); -DECLARE_SOA_COLUMN(DecayVtxZ, decayvtxz, float); -DECLARE_SOA_COLUMN(MassD0, massD0, float); -DECLARE_SOA_COLUMN(MassD0bar, massD0bar, float); -DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptprong0, - [](float px0, float py0) { return RecoDecay::Pt(px0, py0); }); -DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptprong1, - [](float px1, float py1) { return RecoDecay::Pt(px1, py1); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, - [](float px0, float py0, float px1, float py1) { return RecoDecay::Pt(array{px0, py0}, array{px1, py1}); }); -DECLARE_SOA_DYNAMIC_COLUMN(DecaylengthXY, decaylengthxy, - [](float xvtxd, float yvtxd, float xvtxp, float yvtxp) { return RecoDecay::distanceXY(array{xvtxd, yvtxd}, array{xvtxp, yvtxp}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Decaylength, decaylength, - [](float xvtxd, float yvtxd, float zvtxd, float xvtxp, - float yvtxp, float zvtxp) { return RecoDecay::distance(array{xvtxd, yvtxd, zvtxd}, array{xvtxp, yvtxp, zvtxp}); }); -} // namespace hfcandprong2 + return candidate.ct(RecoDecay::getMassPDG(421)); +} -DECLARE_SOA_TABLE(HfTrackIndexProng2, "AOD", "HFTRACKIDXP2", - hftrackindexprong2::CollisionId, - hftrackindexprong2::Index0Id, - hftrackindexprong2::Index1Id, - hftrackindexprong2::HFflag); +template <typename T> +auto YD0(T candidate) +{ + return candidate.y(RecoDecay::getMassPDG(421)); +} -DECLARE_SOA_TABLE(HfTrackIndexProng3, "AOD", "HFTRACKIDXP3", - hftrackindexprong3::CollisionId, - hftrackindexprong3::Index0Id, - hftrackindexprong3::Index1Id, - hftrackindexprong3::Index2Id, - hftrackindexprong3::HFflag); +template <typename T> +auto ED0(T candidate) +{ + return candidate.e(RecoDecay::getMassPDG(421)); +} + +template <typename T> +auto InvMassD0(T candidate) +{ + return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus)}); +} + +template <typename T> +auto InvMassD0bar(T candidate) +{ + return candidate.m(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); +} -DECLARE_SOA_TABLE(HfCandProng2, "AOD", "HFCANDPRONG2", +template <typename T> +auto CosThetaStarD0(T candidate) +{ + return candidate.cosThetaStar(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus)}, RecoDecay::getMassPDG(421), 1); +} + +template <typename T> +auto CosThetaStarD0bar(T candidate) +{ + return candidate.cosThetaStar(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}, RecoDecay::getMassPDG(421), 0); +} +} // namespace hf_cand_prong2 + +DECLARE_SOA_TABLE(HfCandBase, "AOD", "HFCANDBASE", collision::PosX, collision::PosY, collision::PosZ, - hfcandprong2::PxProng0, hfcandprong2::PyProng0, hfcandprong2::PzProng0, - hfcandprong2::PxProng1, hfcandprong2::PyProng1, hfcandprong2::PzProng1, - hfcandprong2::DecayVtxX, hfcandprong2::DecayVtxY, hfcandprong2::DecayVtxZ, - hfcandprong2::MassD0, hfcandprong2::MassD0bar, - hfcandprong2::PtProng0<hfcandprong2::PxProng0, hfcandprong2::PyProng0>, - hfcandprong2::PtProng1<hfcandprong2::PxProng1, hfcandprong2::PyProng1>, - hfcandprong2::Pt<hfcandprong2::PxProng0, hfcandprong2::PyProng0, - hfcandprong2::PxProng1, hfcandprong2::PyProng1>, - hfcandprong2::DecaylengthXY<hfcandprong2::DecayVtxX, hfcandprong2::DecayVtxY, - collision::PosX, collision::PosY>, - hfcandprong2::Decaylength<hfcandprong2::DecayVtxX, hfcandprong2::DecayVtxY, - hfcandprong2::DecayVtxZ, collision::PosX, - collision::PosY, collision::PosZ>); + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, + /* dynamic columns */ + hf_cand::RSecondaryVertex<hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, + hf_cand::ImpactParameterNormalised0<hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0>, + hf_cand::ImpactParameterNormalised1<hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter1>, + hf_cand::PtProng0<hf_cand::PxProng0, hf_cand::PyProng0>, + hf_cand::Pt2Prong0<hf_cand::PxProng0, hf_cand::PyProng0>, + hf_cand::PVectorProng0<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0>, + hf_cand::PtProng1<hf_cand::PxProng1, hf_cand::PyProng1>, + hf_cand::Pt2Prong1<hf_cand::PxProng1, hf_cand::PyProng1>, + hf_cand::PVectorProng1<hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, + hf_cand::DecayLength<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex>, + hf_cand::DecayLengthXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, + hf_cand::DecayLengthNormalised<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand::ErrorDecayLength>, + hf_cand::DecayLengthXYNormalised<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ErrorDecayLengthXY>, //); + + //DECLARE_SOA_TABLE(HfCandProng2Base, "AOD", "HFCANDPRG2BASE", // TODO split table + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, + hf_cand_prong2::DCA, + /* dynamic columns */ + hf_cand_prong2::ImpactParameterProduct<hf_cand::ImpactParameter0, hf_cand::ImpactParameter1>, + hf_cand_prong2::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, + hf_cand_prong2::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, + hf_cand_prong2::CosThetaStar<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt<hf_cand_prong2::Px, hf_cand_prong2::Py>, + hf_cand::Pt2<hf_cand_prong2::Px, hf_cand_prong2::Py>, + hf_cand::P<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::P2<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::PVector<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::CPA<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::CPAXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py>, + hf_cand::Ct<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::Eta<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::Y<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::E<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::E2<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>); + +//using HfCandProng2Origin = soa::Join<HfCandBase, HfCandProng2Base>; // TODO split table +using HfCandProng2Origin = HfCandBase; + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng2Ext, HfCandProng2Origin, "HFCANDPRG2EXT", + hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz); + +using HfCandProng2 = HfCandProng2Ext; + } // namespace o2::aod #endif // O2_ANALYSIS_SECONDARYVERTEXHF_H_ diff --git a/Analysis/DataModel/include/Analysis/trackUtilities.h b/Analysis/DataModel/include/Analysis/trackUtilities.h index 47dcdacc24300..43f6393e8add1 100644 --- a/Analysis/DataModel/include/Analysis/trackUtilities.h +++ b/Analysis/DataModel/include/Analysis/trackUtilities.h @@ -7,14 +7,19 @@ // 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 "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/Vertex.h" -/// \file Utilities for manipulating track parameters +/// \file trackUtilities.h +/// \brief Utilities for manipulating track parameters /// /// \author Vít Kučera <vit.kucera@cern.ch>, CERN #ifndef O2_ANALYSIS_TRACKUTILITIES_H_ #define O2_ANALYSIS_TRACKUTILITIES_H_ +/// Extracts track parameters and covariance matrix from a track. +/// \return o2::track::TrackParCov template <typename T> auto getTrackParCov(T track) { @@ -29,4 +34,14 @@ auto getTrackParCov(T track) return o2::track::TrackParCov(track.x(), track.alpha(), std::move(arraypar), std::move(covpar)); } +/// Extracts primary vertex position and covariance matrix from a collision. +/// \return o2::dataformats::VertexBase +template <typename T> +auto getPrimaryVertex(T collision) +{ + Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); + std::array<float, 6> vtxCov{collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}; + return o2::dataformats::VertexBase{std::move(vtxXYZ), std::move(vtxCov)}; +} + #endif // O2_ANALYSIS_TRACKUTILITIES_H_ diff --git a/Analysis/Tasks/hfcandidatecreator2prong.cxx b/Analysis/Tasks/hfcandidatecreator2prong.cxx index 662248d201314..20b527a15a450 100644 --- a/Analysis/Tasks/hfcandidatecreator2prong.cxx +++ b/Analysis/Tasks/hfcandidatecreator2prong.cxx @@ -7,89 +7,110 @@ // 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 hfcandidatecreator2prong.cxx +/// \brief Reconstruction of heavy-flavour 2-prong decay candidates +/// +/// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Analysis/SecondaryVertexHF.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" +#include "Analysis/SecondaryVertexHF.h" #include "Analysis/trackUtilities.h" -#include "Analysis/RecoDecay.h" - -#include <TFile.h> -#include <TH1F.h> - -#include <cmath> -#include <array> -#include <cstdlib> +#include "ReconstructionDataFormats/DCA.h" using namespace o2; using namespace o2::framework; -using namespace o2::framework::expressions; using std::array; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HFCandidateCreator2Prong { - Produces<aod::HfCandProng2> hfcandprong2; + Produces<aod::HfCandBase> rowCandidateBase; + //Produces<aod::HfCandProng2Base> rowCandidateProng2Base; // TODO split table + Configurable<double> magneticField{"d_bz", 5.0, "magnetic field"}; + Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; + Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; + Configurable<double> d_maxdzini{"d_maxdzini", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; + Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 100, -0.1, 0.1)}; OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 100, -0.1, 0.1)}; OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hmass2{TH1F("hmass2", "2-track inv mass", 500, 0, 5.0)}; - Configurable<double> d_bz{"d_bz", 5.0, "bz field"}; - Configurable<bool> b_propdca{"b_propdca", true, - "create tracks version propagated to PCA"}; - Configurable<double> d_maxr{"d_maxr", 200, "reject PCA's above this radius"}; - Configurable<double> d_maxdzini{"d_maxdzini", 4, - "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; - Configurable<double> d_minparamchange{"d_minparamchange", 1e-3, - "stop iterations if largest change of any X is smaller than this"}; - Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, - "stop iterations is chi2/chi2old > this"}; + OutputObj<TH1F> hmass2{TH1F("hmass2", "2-track inv mass", 500, 0., 5.0)}; + double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); + double massPiK{0}; + double massKPi{0}; void process(aod::Collision const& collision, - aod::HfTrackIndexProng2 const& hftrackindexprong2s, + aod::HfTrackIndexProng2 const& rowsTrackIndexProng2, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) { + // 2-prong vertex fitter o2::vertexing::DCAFitterN<2> df; - df.setBz(d_bz); + df.setBz(magneticField); df.setPropagateToPCA(b_propdca); df.setMaxR(d_maxr); df.setMaxDZIni(d_maxdzini); df.setMinParamChange(d_minparamchange); df.setMinRelChi2Change(d_minrelchi2change); + df.setUseAbsDCA(true); - double massPiK{0}; - double massKPi{0}; + // loop over pairs of track indeces + for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { + auto trackParVarPos1 = getTrackParCov(rowTrackIndexProng2.index0()); + auto trackParVarNeg1 = getTrackParCov(rowTrackIndexProng2.index1()); - // loop over 2-prong secondary vertices - for (auto& hfpr2 : hftrackindexprong2s) { - auto trackparvar_p1 = getTrackParCov(hfpr2.index0()); - auto trackparvar_n1 = getTrackParCov(hfpr2.index1()); - df.setUseAbsDCA(true); - int nCand = df.process(trackparvar_p1, trackparvar_n1); - if (nCand == 0) + // reconstruct the 2-prong secondary vertex + if (df.process(trackParVarPos1, trackParVarNeg1) == 0) continue; - const auto& vtx = df.getPCACandidate(); + const auto& secondaryVertex = df.getPCACandidate(); + auto trackParVar0 = df.getTrack(0); + auto trackParVar1 = df.getTrack(1); + + // get track momenta array<float, 3> pvec0; array<float, 3> pvec1; - df.getTrack(0).getPxPyPzGlo(pvec0); - df.getTrack(1).getPxPyPzGlo(pvec1); + trackParVar0.getPxPyPzGlo(pvec0); + trackParVar1.getPxPyPzGlo(pvec1); + + // calculate invariant masses + auto arrayMomenta = array{pvec0, pvec1}; + massPiK = RecoDecay::M(arrayMomenta, array{massPi, massK}); + massKPi = RecoDecay::M(arrayMomenta, array{massK, massPi}); + + // get track impact parameters + // This modifies track momenta! + auto primaryVertex = getPrimaryVertex(collision); + o2::dataformats::DCA impactParameter0; + o2::dataformats::DCA impactParameter1; + trackParVar0.propagateToDCA(primaryVertex, magneticField, &impactParameter0); + trackParVar1.propagateToDCA(primaryVertex, magneticField, &impactParameter1); - auto arrMom = array{pvec0, pvec1}; - massPiK = RecoDecay::M(arrMom, array{massPi, massK}); - massKPi = RecoDecay::M(arrMom, array{massK, massPi}); + // TODO + float dcaDaughters = 0.; + float errorDecayLength = 1., errorDecayLengthXY = 1.; - hfcandprong2(collision.posX(), collision.posY(), collision.posZ(), - pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], - vtx[0], vtx[1], vtx[2], massPiK, massKPi); + // fill candidate table rows + rowCandidateBase(collision.posX(), collision.posY(), collision.posZ(), + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + errorDecayLength, errorDecayLengthXY, //); + //rowCandidateProng2Base( // TODO split table + pvec0[0], pvec0[1], pvec0[2], + pvec1[0], pvec1[1], pvec1[2], + impactParameter0.getY(), impactParameter1.getY(), + std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), + dcaDaughters); + + // fill histograms if (b_dovalplots) { - hvtx_x_out->Fill(vtx[0]); - hvtx_y_out->Fill(vtx[1]); - hvtx_z_out->Fill(vtx[2]); + hvtx_x_out->Fill(secondaryVertex[0]); + hvtx_y_out->Fill(secondaryVertex[1]); + hvtx_z_out->Fill(secondaryVertex[2]); hmass2->Fill(massPiK); hmass2->Fill(massKPi); } @@ -97,8 +118,15 @@ struct HFCandidateCreator2Prong { } }; +/// Extends the base table with expression columns. +struct HFCandidateCreator2ProngExpressions { + Spawns<aod::HfCandProng2Ext> rowCandidateProng2; + void init(InitContext const&) {} +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<HFCandidateCreator2Prong>("vertexerhf-hfcandcreator2prong")}; + adaptAnalysisTask<HFCandidateCreator2Prong>("vertexerhf-hfcandcreator2prong"), + adaptAnalysisTask<HFCandidateCreator2ProngExpressions>("vertexerhf-hfcandcreator2prong-expressions")}; } diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/hftrackindexskimscreator.cxx index b71320ef82500..eda08bc6a8b43 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/hftrackindexskimscreator.cxx @@ -7,22 +7,18 @@ // 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 hftrackindexskimscreator.cxx +/// \brief Pre-selection of 2-prong and 3-prong secondary vertices of heavy-flavour decay candidates +/// +/// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Analysis/SecondaryVertexHF.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" +#include "Analysis/SecondaryVertexHF.h" #include "Analysis/trackUtilities.h" -#include "Analysis/RecoDecay.h" - -#include <TFile.h> -#include <TH1F.h> - -#include <cmath> -#include <array> -#include <cstdlib> using namespace o2; using namespace o2::framework; @@ -33,17 +29,16 @@ namespace o2::aod { namespace seltrack { -DECLARE_SOA_COLUMN(IsSel, issel, int); -DECLARE_SOA_COLUMN(DCAPrim0, dcaprim0, float); -DECLARE_SOA_COLUMN(DCAPrim1, dcaprim1, float); +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); +DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", seltrack::IsSel, seltrack::DCAPrim0, seltrack::DCAPrim1); } // namespace o2::aod /// Track selection struct SelectTracks { - Produces<aod::SelTrack> seltrack; + Produces<aod::SelTrack> rowSelectedTrack; Configurable<double> ptmintrack{"ptmintrack", -1, "ptmin single track"}; Configurable<double> dcatoprimxymin{"dcatoprimxymin", 0, "dca xy to prim vtx min"}; Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min number of tpc cls >="}; @@ -57,73 +52,76 @@ struct SelectTracks { soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) { Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); - for (auto it0 = tracks.begin(); it0 != tracks.end(); ++it0) { - auto& track_0 = *it0; + for (auto& track : tracks) { int status = 1; // selection flag if (b_dovalplots) - hpt_nocuts->Fill(track_0.pt()); - if (track_0.pt() < ptmintrack) + hpt_nocuts->Fill(track.pt()); + if (track.pt() < ptmintrack) status = 0; - UChar_t clustermap_0 = track_0.itsClusterMap(); - bool isselected_0 = track_0.tpcNClsFound() >= d_tpcnclsfound && track_0.flags() & 0x4; + UChar_t clustermap_0 = track.itsClusterMap(); + bool isselected_0 = track.tpcNClsFound() >= d_tpcnclsfound && track.flags() & 0x4; isselected_0 = isselected_0 && (TESTBIT(clustermap_0, 0) || TESTBIT(clustermap_0, 1)); if (!isselected_0) status = 0; array<float, 2> dca; - auto trackparvar0 = getTrackParCov(track_0); - trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca); + auto trackparvar0 = getTrackParCov(track); + trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca); // get impact parameters if (abs(dca[0]) < dcatoprimxymin) status = 0; if (b_dovalplots) { if (status == 1) { - hpt_cuts->Fill(track_0.pt()); + hpt_cuts->Fill(track.pt()); hdcatoprimxy_cuts->Fill(dca[0]); } } - seltrack(status, dca[0], dca[1]); + rowSelectedTrack(status, dca[0], dca[1]); } } }; /// Pre-selection of 2-prong and 3-prong secondary vertices struct HFTrackIndexSkimsCreator { - OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; - OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; - Produces<aod::HfTrackIndexProng2> hftrackindexprong2; - Produces<aod::HfTrackIndexProng3> hftrackindexprong3; + Produces<aod::HfTrackIndexProng2> rowTrackIndexProng2; + Produces<aod::HfTrackIndexProng3> rowTrackIndexProng3; Configurable<int> triggerindex{"triggerindex", -1, "trigger index"}; Configurable<int> do3prong{"do3prong", 0, "do 3 prong"}; Configurable<double> d_bz{"d_bz", 5.0, "bz field"}; - Configurable<bool> b_propdca{"b_propdca", true, - "create tracks version propagated to PCA"}; + Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; Configurable<double> d_maxr{"d_maxr", 200, "reject PCA's above this radius"}; - Configurable<double> d_maxdzini{"d_maxdzini", 4, - "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; - Configurable<double> d_minparamchange{"d_minparamchange", 1e-3, - "stop iterations if largest change of any X is smaller than this"}; - Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, - "stop iterations is chi2/chi2old > this"}; + Configurable<double> d_maxdzini{"d_maxdzini", 4, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable<double> d_minparamchange{"d_minparamchange", 1e-3, "stop iterations if largest change of any X is smaller than this"}; + Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min mass dplus presel"}; Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - Filter seltrack = (aod::seltrack::issel == 1); + OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; + OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; + + Filter filterSelectTracks = aod::seltrack::isSel == 1; + using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>>; + // FIXME + //Partition<SelectedTracks> tracksPos = aod::track::signed1Pt > 0.f; + //Partition<SelectedTracks> tracksNeg = aod::track::signed1Pt < 0.f; + double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); + double mass2PiK{0}; + double mass2KPi{0}; + double mass3PiKPi{0}; void process(aod::Collision const& collision, aod::BCs const& bcs, - soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>> const& tracks) + SelectedTracks const& tracks) { int trigindex = int{triggerindex}; if (trigindex != -1) { - //LOGF(info, "Selecting on trigger bit %d", trigindex); uint64_t triggerMask = collision.bc().triggerMask(); bool isTriggerClassFired = triggerMask & 1ul << (trigindex - 1); if (!isTriggerClassFired) return; } - LOGF(info, "N. of Tracks for collision: %d", tracks.size()); + // 2-prong vertex fitter o2::vertexing::DCAFitterN<2> df; df.setBz(d_bz); df.setPropagateToPCA(b_propdca); @@ -131,7 +129,9 @@ struct HFTrackIndexSkimsCreator { df.setMaxDZIni(d_maxdzini); df.setMinParamChange(d_minparamchange); df.setMinRelChi2Change(d_minrelchi2change); + df.setUseAbsDCA(true); + // 3-prong vertex fitter o2::vertexing::DCAFitterN<3> df3; df3.setBz(d_bz); df3.setPropagateToPCA(b_propdca); @@ -139,36 +139,38 @@ struct HFTrackIndexSkimsCreator { df3.setMaxDZIni(d_maxdzini); df3.setMinParamChange(d_minparamchange); df3.setMinRelChi2Change(d_minrelchi2change); - - double mass2PiK{0}; - double mass2KPi{0}; - double mass3PiKPi{0}; + df3.setUseAbsDCA(true); // first loop over positive tracks - for (auto i_p1 = tracks.begin(); i_p1 != tracks.end(); ++i_p1) { - auto& track_p1 = *i_p1; - if (track_p1.signed1Pt() < 0) + //for (auto trackPos1 = tracksPos.begin(); trackPos1 != tracksPos.end(); ++trackPos1) { + for (auto trackPos1 = tracks.begin(); trackPos1 != tracks.end(); ++trackPos1) { + if (trackPos1.signed1Pt() < 0) continue; - auto trackparvar_p1 = getTrackParCov(track_p1); + + auto trackParVarPos1 = getTrackParCov(trackPos1); // first loop over negative tracks - for (auto i_n1 = tracks.begin(); i_n1 != tracks.end(); ++i_n1) { - auto& track_n1 = *i_n1; - if (track_n1.signed1Pt() > 0) + //for (auto trackNeg1 = tracksNeg.begin(); trackNeg1 != tracksNeg.end(); ++trackNeg1) { + for (auto trackNeg1 = tracks.begin(); trackNeg1 != tracks.end(); ++trackNeg1) { + if (trackNeg1.signed1Pt() > 0) continue; - auto trackparvar_n1 = getTrackParCov(track_n1); + + auto trackParVarNeg1 = getTrackParCov(trackNeg1); // reconstruct the 2-prong secondary vertex - df.setUseAbsDCA(true); - int nCand = df.process(trackparvar_p1, trackparvar_n1); - if (nCand == 0) + if (df.process(trackParVarPos1, trackParVarNeg1) == 0) continue; - const auto& vtx = df.getPCACandidate(); + + // get vertex + //const auto& vtx = df.getPCACandidate(); + + // get track momenta array<float, 3> pvec0; array<float, 3> pvec1; df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); + // calculate invariant masses auto arrMom = array{pvec0, pvec1}; mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); @@ -178,33 +180,39 @@ struct HFTrackIndexSkimsCreator { hmass2->Fill(mass2KPi); } - hftrackindexprong2(track_p1.collisionId(), - track_p1.globalIndex(), - track_n1.globalIndex(), 1); + // fill table row + rowTrackIndexProng2(trackPos1.collisionId(), + trackPos1.globalIndex(), + trackNeg1.globalIndex(), 1); // 3-prong vertex reconstruction if (do3prong == 1) { // second loop over positive tracks - for (auto i_p2 = i_p1 + 1; i_p2 != tracks.end(); ++i_p2) { - auto& track_p2 = *i_p2; - if (track_p2.signed1Pt() < 0) + //for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracksPos.end(); ++trackPos2) { + for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracks.end(); ++trackPos2) { + if (trackPos2.signed1Pt() < 0) continue; + // calculate invariant mass auto arr3Mom = array{ - array{track_p1.px(), track_p1.py(), track_p1.pz()}, - array{track_n1.px(), track_n1.py(), track_n1.pz()}, - array{track_p2.px(), track_p2.py(), track_p2.pz()}}; + array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, + array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, + array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) continue; - auto trackparvar_p2 = getTrackParCov(track_p2); - df3.setUseAbsDCA(true); - int nCand3 = df3.process(trackparvar_p1, trackparvar_n1, trackparvar_p2); - if (nCand3 == 0) + auto trackParVarPos2 = getTrackParCov(trackPos2); + + // reconstruct the 3-prong secondary vertex + if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) continue; - const auto& vtx3 = df3.getPCACandidate(); + + // get vertex + //const auto& vtx3 = df3.getPCACandidate(); + + // get track momenta array<float, 3> pvec0; array<float, 3> pvec1; array<float, 3> pvec2; @@ -212,6 +220,7 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); + // calculate invariant mass arr3Mom = array{pvec0, pvec1, pvec2}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); @@ -219,32 +228,38 @@ struct HFTrackIndexSkimsCreator { hmass3->Fill(mass3PiKPi); } - hftrackindexprong3(track_p1.collisionId(), - track_p1.globalIndex(), - track_n1.globalIndex(), - track_p2.globalIndex(), 2); + // fill table row + rowTrackIndexProng3(trackPos1.collisionId(), + trackPos1.globalIndex(), + trackNeg1.globalIndex(), + trackPos2.globalIndex(), 2); } // second loop over negative tracks - for (auto i_n2 = i_n1 + 1; i_n2 != tracks.end(); ++i_n2) { - auto& track_n2 = *i_n2; - if (track_n2.signed1Pt() > 0) + //for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracksNeg.end(); ++trackNeg2) { + for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracks.end(); ++trackNeg2) { + if (trackNeg2.signed1Pt() > 0) continue; + // calculate invariant mass auto arr3Mom = array{ - array{track_n1.px(), track_n1.py(), track_n1.pz()}, - array{track_p1.px(), track_p1.py(), track_p1.pz()}, - array{track_n2.px(), track_n2.py(), track_n2.pz()}}; + array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, + array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, + array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) continue; - auto trackparvar_n2 = getTrackParCov(track_n2); - df3.setUseAbsDCA(true); - int nCand3 = df3.process(trackparvar_n1, trackparvar_p1, trackparvar_n2); - if (nCand3 == 0) + auto trackParVarNeg2 = getTrackParCov(trackNeg2); + + // reconstruct the 3-prong secondary vertex + if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) continue; - const auto& vtx3 = df3.getPCACandidate(); + + // get vertex + //const auto& vtx3 = df3.getPCACandidate(); + + // get track momenta array<float, 3> pvec0; array<float, 3> pvec1; array<float, 3> pvec2; @@ -252,6 +267,7 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); + // calculate invariant mass arr3Mom = array{pvec0, pvec1, pvec2}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); @@ -259,10 +275,11 @@ struct HFTrackIndexSkimsCreator { hmass3->Fill(mass3PiKPi); } - hftrackindexprong3(track_n1.collisionId(), - track_n1.globalIndex(), - track_p1.globalIndex(), - track_n2.globalIndex(), 2); + // fill table row + rowTrackIndexProng3(trackNeg1.collisionId(), + trackNeg1.globalIndex(), + trackPos1.globalIndex(), + trackNeg2.globalIndex(), 2); } } } diff --git a/Analysis/Tasks/taskdzero.cxx b/Analysis/Tasks/taskdzero.cxx index 9bc98f51d530c..5d0cf63c03dd9 100644 --- a/Analysis/Tasks/taskdzero.cxx +++ b/Analysis/Tasks/taskdzero.cxx @@ -7,23 +7,20 @@ // 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 taskdzero.h +/// \brief D0 analysis task +/// +/// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "Analysis/SecondaryVertexHF.h" -#include "DetectorsVertexing/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" - -#include <TFile.h> -#include <TH1F.h> -#include <cmath> -#include <array> -#include <cstdlib> using namespace o2; using namespace o2::framework; -using namespace o2::framework::expressions; +using namespace o2::aod::hf_cand_prong2; using std::array; /// D0 analysis task @@ -34,17 +31,28 @@ struct TaskDzero { OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0, 10.0)}; OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 100, 0., 1.0)}; OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 100, 0., 1.0)}; + OutputObj<TH1F> hd0{TH1F("hd0", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; + OutputObj<TH1F> hd0d0{TH1F("hd0d0", "product of dca xy to prim. vertex (cm^{2})", 100, -1.0, 1.0)}; + OutputObj<TH1F> hCTS{TH1F("hCTS", "cos #it{#theta}*", 120, -1.1, 1.1)}; + OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; + OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; - void process(aod::HfCandProng2 const& hfcandprong2s) + void process(aod::HfCandProng2 const& candidates) { - for (auto& hfcandprong2 : hfcandprong2s) { - hmass->Fill(hfcandprong2.massD0()); - hmass->Fill(hfcandprong2.massD0bar()); - hptprong0->Fill(hfcandprong2.ptprong0()); - hptprong1->Fill(hfcandprong2.ptprong1()); - hptcand->Fill(hfcandprong2.pt()); - hdeclength->Fill(hfcandprong2.decaylength()); - hdeclengthxy->Fill(hfcandprong2.decaylengthxy()); + for (auto& candidate : candidates) { + hmass->Fill(InvMassD0(candidate)); + hmass->Fill(InvMassD0bar(candidate)); + hptcand->Fill(candidate.pt()); + hptprong0->Fill(candidate.ptProng0()); + hptprong1->Fill(candidate.ptProng1()); + hdeclength->Fill(candidate.decayLength()); + hdeclengthxy->Fill(candidate.decayLengthXY()); + hd0->Fill(candidate.impactParameter0()); + hd0->Fill(candidate.impactParameter1()); + hd0d0->Fill(candidate.impactParameterProduct()); + hCTS->Fill(CosThetaStarD0(candidate)); + hCt->Fill(CtD0(candidate)); + hEta->Fill(candidate.eta()); } } }; From d115043c9d1d26d729c7c5f6cacc5d6e34f66549 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 25 Aug 2020 11:18:41 +0200 Subject: [PATCH 0432/1751] splitting into weak decay index builder and tutorial task (#4202) --- Analysis/Tasks/CMakeLists.txt | 5 +++ Analysis/Tasks/weakDecayIndices.cxx | 37 +++++++++++++++++++ Analysis/Tutorials/src/weakDecayIteration.cxx | 22 +++-------- 3 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 Analysis/Tasks/weakDecayIndices.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 407b20581aa04..210872b581253 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -122,3 +122,8 @@ o2_add_dpl_workflow(timestamp SOURCES timestamp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::DetectorsRaw O2::AnalysisCore O2::CommonDataFormat O2::CCDB COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(weak-decay-indices + SOURCES weakDecayIndices.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/weakDecayIndices.cxx b/Analysis/Tasks/weakDecayIndices.cxx new file mode 100644 index 0000000000000..3aa244a343ae6 --- /dev/null +++ b/Analysis/Tasks/weakDecayIndices.cxx @@ -0,0 +1,37 @@ +// 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" + +using namespace o2; +using namespace o2::framework; + +struct ATask { + Produces<aod::TransientV0s> transientV0s; + Produces<aod::TransientCascades> transientCascades; + + void process(aod::StoredV0s const& v0s, aod::StoredCascades const& cascades, aod::FullTracks const& tracks) + { + for (auto& v0 : v0s) { + transientV0s(v0.posTrack().collisionId()); + } + for (auto& cascade : cascades) { + transientCascades(cascade.bachelor().collisionId()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<ATask>("weak-decay-indices"), + }; +} diff --git a/Analysis/Tutorials/src/weakDecayIteration.cxx b/Analysis/Tutorials/src/weakDecayIteration.cxx index 8fdcd4f585f75..c5cb393c2a460 100644 --- a/Analysis/Tutorials/src/weakDecayIteration.cxx +++ b/Analysis/Tutorials/src/weakDecayIteration.cxx @@ -11,24 +11,13 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +// Example how to enumerate V0s and cascades +// Needs weak-decay-indices in the workflow +// Example usage: o2-analysis-weak-decay-indices --aod-file AO2D.root | o2-analysistutorial-weak-decay-iteration + using namespace o2; using namespace o2::framework; -struct ATask { - Produces<aod::TransientV0s> transientV0s; - Produces<aod::TransientCascades> transientCascades; - - void process(aod::StoredV0s const& v0s, aod::StoredCascades const& cascades, aod::FullTracks const& tracks) - { - for (auto& v0 : v0s) { - transientV0s(v0.posTrack().collisionId()); - } - for (auto& cascade : cascades) { - transientCascades(cascade.bachelor().collisionId()); - } - } -}; - struct BTask { void process(aod::V0s const& v0s, aod::FullTracks const& tracks) { @@ -67,7 +56,7 @@ struct ETask { LOGF(INFO, "Collision %d has %d cascades", collision.globalIndex(), cascades.size()); for (auto& cascade : cascades) { - LOGF(INFO, "Collision %d Cascade %d (%d, %d, %d)", collision.globalIndex(), cascade.globalIndex(), cascade.v0().posTrackId(), cascade.v0().negTrackId(), cascade.bachelorId()); + LOGF(DEBUG, "Collision %d Cascade %d (%d, %d, %d)", collision.globalIndex(), cascade.globalIndex(), cascade.v0().posTrackId(), cascade.v0().negTrackId(), cascade.bachelorId()); } } }; @@ -75,7 +64,6 @@ struct ETask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<ATask>("produce-v0index"), adaptAnalysisTask<BTask>("consume-v0s"), adaptAnalysisTask<CTask>("consume-cascades"), adaptAnalysisTask<DTask>("consume-grouped-v0s"), From 63611f8b7b2c3e5f8460b34f2573033e36d2ec74 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 19 Jun 2020 14:52:02 +0200 Subject: [PATCH 0433/1751] GPU: Adapt to hip-clang runtime --- GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index c598317071b1c..72aaf443c0e9f 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -586,7 +586,7 @@ void* GPUReconstructionHIPBackend::getGPUPointer(void* ptr) void GPUReconstructionHIPBackend::PrintKernelOccupancies() { - unsigned int maxBlocks, threads, suggestedBlocks; + int maxBlocks, threads, suggestedBlocks; #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) \ GPUFailedMsg(hipOccupancyMaxPotentialBlockSize(&suggestedBlocks, &threads, GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)), 0, 0)); \ From 9b27ec45f69da7f74d8a88b5a8307500ec7e2039 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 21 May 2020 19:09:56 +0200 Subject: [PATCH 0434/1751] GPU: Enable __device__ keyword for lambdas in CUDA --- dependencies/FindO2GPU.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 06886f02f16ca..f11580e2f29e7 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -59,7 +59,7 @@ if(ENABLE_CUDA) # Forward CXX flags to CUDA C++ Host compiler (for warnings, gdb, etc.) STRING(REGEX REPLACE "\-std=[^ ]*" "" CMAKE_CXX_FLAGS_NOSTD ${CMAKE_CXX_FLAGS}) # Need to strip c++17 imposed by alidist defaults - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr -Xptxas -v") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda -Xptxas -v") set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -lineinfo -Xcompiler \"${CMAKE_CXX_FLAGS_DEBUG}\" -Xptxas -O0 -Xcompiler -O0") if(NOT CMAKE_BUILD_TYPE STREQUAL "DEBUG") set(CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE} "${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE}} -Xcompiler \"${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}\" -Xptxas -O4 -Xcompiler -O4 -use_fast_math --ftz=true") From ffe3bf5099c6742fa04655c1270aed3ef888331f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 13 Mar 2020 19:12:37 +0100 Subject: [PATCH 0435/1751] GPU: Use constexpr __constant__ on HIP --- GPU/Common/GPUCommonDefAPI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/GPUCommonDefAPI.h b/GPU/Common/GPUCommonDefAPI.h index c71d99b7456f7..22df336776d94 100644 --- a/GPU/Common/GPUCommonDefAPI.h +++ b/GPU/Common/GPUCommonDefAPI.h @@ -147,7 +147,7 @@ #define GPUglobal() #endif #define GPUconstant() __constant__ - #define GPUconstexpr() __constant__ + #define GPUconstexpr() constexpr __constant__ #define GPUprivate() #define GPUgeneric() #define GPUbarrier() __syncthreads() From 24bb8a1af0360819b30a0247bfb45028ed4c2f8f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 9 Jun 2020 10:18:20 +0200 Subject: [PATCH 0436/1751] GPU: Adjust CMake for hip-clang --- GPU/GPUTracking/Base/hip/CMakeLists.txt | 8 ++++---- dependencies/FindO2GPU.cmake | 19 +++---------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index e05996e2c44c4..62a171ef7cf28 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -28,7 +28,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") o2_add_library( ${MODULE} SOURCES ${SRCS} - PUBLIC_LINK_LIBRARIES O2::GPUTracking O2::ITStrackingHIP hip::host hip::device hip::hipcub ROCm::rocThrust + PUBLIC_LINK_LIBRARIES O2::GPUTracking O2::ITStrackingHIP hip::host hip::device hip::hipcub roc::rocthrust PUBLIC_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src ${CMAKE_SOURCE_DIR}/Detectors/Base/src TARGETVARNAME targetName) @@ -41,7 +41,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") o2_add_test(GPUsortHIP NAME test_GPUsortHIP SOURCES test/testGPUsortHIP.hip.cxx - PUBLIC_LINK_LIBRARIES O2::GPUCommon hip::host hip::device hip::hipcub ROCm::rocThrust + PUBLIC_LINK_LIBRARIES O2::GPUCommon hip::host hip::device hip::hipcub roc::rocthrust COMPONENT_NAME GPU LABELS gpu) endif() @@ -66,7 +66,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") set(ALILIBSTESTED ${ALILIBSTESTED} CACHE INTERNAL "ALILIBSTESTED") # HIP run-time and driver - target_link_libraries(Ali${MODULE} PUBLIC AliGPUTracking hip::host hip::device hip::hipcub ROCm::rocThrust) + target_link_libraries(Ali${MODULE} PUBLIC AliGPUTracking hip::host hip::device hip::hipcub roc::rocthrust) # Additional compilation flags set_target_properties(Ali${MODULE} PROPERTIES COMPILE_FLAGS "") @@ -81,7 +81,7 @@ endif() if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") add_definitions(-DGPUCA_GPULIBRARY=HIP) add_library(${MODULE} SHARED ${SRCS}) - target_link_libraries(${MODULE} GPUTracking hip::host hip::device hip::hipcub ROCm::rocThrust) + target_link_libraries(${MODULE} GPUTracking hip::host hip::device hip::hipcub roc::rocthrust) set(targetName "${MODULE}") install(TARGETS GPUTrackingHIP) endif() diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index f11580e2f29e7..0d9039adce81b 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -167,21 +167,9 @@ if(ENABLE_HIP) CACHE PATH "Path to which HIP has been installed") endif() endif() - if(NOT DEFINED HCC_HOME) - if(NOT DEFINED ENV{HCC_HOME}) - set(HCC_HOME - "${HIP_PATH}/../hcc" - CACHE PATH "Path to which HCC has been installed") - else() - set(HCC_HOME - $ENV{HCC_HOME} - CACHE PATH "Path to which HCC has been installed") - endif() - endif() - if(EXISTS "${HIP_PATH}" AND EXISTS "${HCC_HOME}") + if(EXISTS "${HIP_PATH}") get_filename_component(hip_ROOT "${HIP_PATH}" ABSOLUTE) - get_filename_component(hcc_ROOT "${HCC_HOME}" ABSOLUTE) find_package(hip) find_package(hipcub) find_package(rocprim) @@ -199,8 +187,7 @@ if(ENABLE_HIP) endif() if(hip_FOUND AND hipcub_FOUND AND rocthrust_FOUND AND rocprim_FOUND AND hip_HIPCC_EXECUTABLE) set(HIP_ENABLED ON) - set_target_properties(rocthrust PROPERTIES IMPORTED_GLOBAL TRUE) - add_library(ROCm::rocThrust ALIAS rocthrust) + set_target_properties(roc::rocthrust PROPERTIES IMPORTED_GLOBAL TRUE) message(STATUS "HIP Found (${hip_HIPCC_EXECUTABLE})") set(O2_HIP_CMAKE_CXX_FLAGS "-fcuda-flush-denormals-to-zero -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -Wno-invalid-constexpr -Wno-ignored-optimization-argument -Wno-unused-private-field") if(HIP_AMDGPUTARGET) @@ -211,7 +198,7 @@ if(ENABLE_HIP) if(NOT HIP_ENABLED AND NOT ENABLE_HIP STREQUAL "AUTO") message( FATAL_ERROR - "HIP requested but HIP_PATH=${HIP_PATH} or HCC_HOME=${HCC_HOME} does not exist" + "HIP requested but HIP_PATH=${HIP_PATH} does not exist" ) endif() From 1dad6ed18cf12aea47c29dd127107611201964e9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 8 Jun 2020 20:46:48 +0200 Subject: [PATCH 0437/1751] GPU: Switch to CUDA 11 --- .../ITSMFT/ITS/tracking/cuda/CMakeLists.txt | 1 - .../tracking/cuda/src/VertexerTraitsGPU.cu | 6 ++--- GPU/Common/CMakeLists.txt | 2 +- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 4 +-- .../cuda/GPUReconstructionCUDAInternals.h | 5 ++-- dependencies/FindO2GPU.cmake | 13 +++------- dependencies/Findcub.cmake | 25 ------------------- 7 files changed, 12 insertions(+), 44 deletions(-) delete mode 100644 dependencies/Findcub.cmake diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/cuda/CMakeLists.txt index 939755448b999..4b38a02a1da3f 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/cuda/CMakeLists.txt @@ -21,7 +21,6 @@ o2_add_library(ITStrackingCUDA src/Utils.cu PUBLIC_LINK_LIBRARIES O2::ITStracking O2::SimConfig - cub::cub O2::SimulationDataFormat TARGETVARNAME targetName) diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu index d914e6499d2a0..033dd69e2d526 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu @@ -151,11 +151,11 @@ GPUg() void trackleterKernel( phiBinsNum += PhiBins; } const size_t nClustersAdjacentLayer = store.getClusters()[static_cast<int>(adjacentLayerIndex)].size(); - for (size_t iPhiBin{selectedBinsRect.y}, iPhiCount{0}; iPhiCount < phiBinsNum; iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) { + for (size_t iPhiBin{(size_t)selectedBinsRect.y}, iPhiCount{0}; iPhiCount < (size_t)phiBinsNum; iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) { const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect.x, iPhiBin)}; const int firstRowClusterIndex{store.getIndexTable(adjacentLayerIndex)[firstBinIndex]}; const int maxRowClusterIndex{store.getIndexTable(adjacentLayerIndex)[firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1]}; - for (size_t iAdjacentCluster{firstRowClusterIndex}; iAdjacentCluster < maxRowClusterIndex && iAdjacentCluster < nClustersAdjacentLayer; ++iAdjacentCluster) { + for (size_t iAdjacentCluster{(size_t)firstRowClusterIndex}; iAdjacentCluster < (size_t)maxRowClusterIndex && iAdjacentCluster < nClustersAdjacentLayer; ++iAdjacentCluster) { const Cluster& adjacentCluster = store.getClusters()[static_cast<int>(adjacentLayerIndex)][iAdjacentCluster]; // assign-constructor may be a problem, check if (gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - adjacentCluster.phiCoordinate) < phiCut) { if (storedTracklets < store.getConfig().maxTrackletsPerCluster) { @@ -276,7 +276,7 @@ GPUg() void computeZCentroidsKernel(DeviceStoreVertexerGPU& store, store.getBeamPosition().emplace(1, wY / sumWY); float fakeBeamPoint1[3] = {store.getBeamPosition()[0], store.getBeamPosition()[1], -1}; // get two points laying at different z, to create line object float fakeBeamPoint2[3] = {store.getBeamPosition()[0], store.getBeamPosition()[1], 1}; - Line pseudoBeam = Line::Line(fakeBeamPoint1, fakeBeamPoint2); + Line pseudoBeam = {fakeBeamPoint1, fakeBeamPoint2}; if (Line::getDCA(store.getLines()[currentThreadIndex], pseudoBeam) < pairCut) { ClusterLinesGPU cluster{store.getLines()[currentThreadIndex], pseudoBeam}; store.getZCentroids().emplace(currentThreadIndex, cluster.getVertex()[2]); diff --git a/GPU/Common/CMakeLists.txt b/GPU/Common/CMakeLists.txt index 8cff6021f2cc3..744365ac798e5 100644 --- a/GPU/Common/CMakeLists.txt +++ b/GPU/Common/CMakeLists.txt @@ -42,7 +42,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") if(CUDA_ENABLED) o2_add_test(GPUsortCUDA NAME test_GPUsortCUDA SOURCES test/testGPUsortCUDA.cu - PUBLIC_LINK_LIBRARIES O2::${MODULE} cub::cub + PUBLIC_LINK_LIBRARIES O2::${MODULE} COMPONENT_NAME GPU LABELS gpu) endif() diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 21173bed8ad3f..7dd1b795c6a83 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -25,7 +25,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/Detectors/Base/src ${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src - PUBLIC_LINK_LIBRARIES O2::GPUTracking O2::ITStrackingCUDA cub::cub + PUBLIC_LINK_LIBRARIES O2::GPUTracking O2::ITStrackingCUDA TARGETVARNAME targetName) target_compile_definitions( @@ -69,7 +69,7 @@ endif() if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") add_definitions(-DGPUCA_GPULIBRARY=CUDA) add_library(${MODULE} SHARED ${SRCS}) - target_link_libraries(${MODULE} PUBLIC GPUTracking cub::cub) + target_link_libraries(${MODULE} PUBLIC GPUTracking) set(targetName ${MODULE}) install(TARGETS GPUTrackingCUDA) endif() diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h index f335a118e51ab..a02f6133ee354 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h @@ -68,7 +68,8 @@ class ThrustVolatileAsyncAllocator } // namespace GPUCA_NAMESPACE // Override synchronize call at end of thrust algorithm running on stream, just don't run cudaStreamSynchronize -THRUST_BEGIN_NS +namespace thrust +{ namespace cuda_cub { @@ -85,6 +86,6 @@ __host__ __device__ inline cudaError_t synchronize<thrustStreamPolicy>(thrustStr } } // namespace cuda_cub -THRUST_END_NS +} // namespace thrust #endif diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 0d9039adce81b..7d4d88a266838 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -27,7 +27,7 @@ string(TOUPPER "${ENABLE_HIP}" ENABLE_HIP) # Detect and enable CUDA if(ENABLE_CUDA) - set(CUDA_MINIMUM_VERSION "10.1") + set(CUDA_MINIMUM_VERSION "11.0") set(CMAKE_CUDA_STANDARD 14) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) include(CheckLanguage) @@ -39,14 +39,7 @@ if(ENABLE_CUDA) set(CMAKE_CUDA_COMPILER "nvcc") #check_language does not treat the HOST_COMPILER flag correctly, we force it and will fail below if wrong. endif() endif() - if (ENABLE_CUDA STREQUAL "AUTO") - find_package(cub) - set_package_properties(cub PROPERTIES TYPE OPTIONAL) - else() - find_package(cub REQUIRED) - set_package_properties(cub PROPERTIES TYPE REQUIRED) - endif() - if(CMAKE_CUDA_COMPILER AND CUB_FOUND) + if(CMAKE_CUDA_COMPILER) enable_language(CUDA) get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) if(NOT CUDA IN_LIST LANGUAGES) @@ -77,7 +70,7 @@ if(ENABLE_CUDA) set(CUDA_ENABLED ON) message(STATUS "CUDA found (Version ${CMAKE_CUDA_COMPILER_VERSION})") elseif(NOT ENABLE_CUDA STREQUAL "AUTO") - message(FATAL_ERROR "CUDA not found (Compiler: ${CMAKE_CUDA_COMPILER}, CUB: ${CUB_FOUND})") + message(FATAL_ERROR "CUDA not found (Compiler: ${CMAKE_CUDA_COMPILER})") endif() endif() diff --git a/dependencies/Findcub.cmake b/dependencies/Findcub.cmake deleted file mode 100644 index 733799b2c4f2f..0000000000000 --- a/dependencies/Findcub.cmake +++ /dev/null @@ -1,25 +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. - -find_path(CUB_INCLUDE_DIR cub/cub.cuh PATHS ${cub_ROOT} $ENV{CUB_ROOT} ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) - -if(NOT CUB_INCLUDE_DIR) - set(CUB_FOUND FALSE) - return() -endif() - -set(CUB_FOUND TRUE) - -if(NOT TARGET cub::cub) - add_library(cub::cub INTERFACE IMPORTED) - target_include_directories(cub::cub SYSTEM INTERFACE ${CUB_INCLUDE_DIR}) -endif() - -mark_as_advanced(CUB_INCLUDE_DIR) From 2f162f4e45cfde9849ab7dc0a2b6bfeb32014de1 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Thu, 11 Jun 2020 15:56:27 +0200 Subject: [PATCH 0438/1751] GPU: Improve gather kernel performance - Buffer data in shared memory for more efficent dma writes - Distribute work equally among all threads - Add flag to switch between kernels --- GPU/Common/GPUCommonAlgorithm.h | 16 + GPU/Common/GPUDefGPUParameters.h | 14 +- GPU/GPUTracking/Base/GPUGeneralKernels.h | 2 + GPU/GPUTracking/Base/GPUReconstruction.cxx | 3 + .../Base/GPUReconstructionKernels.h | 16 +- .../DataCompression/GPUTPCCompression.h | 1 + .../GPUTPCCompressionKernels.cxx | 280 +++++++++++++++--- .../GPUTPCCompressionKernels.h | 88 +++--- GPU/GPUTracking/Global/GPUChainTracking.cxx | 24 +- 9 files changed, 354 insertions(+), 90 deletions(-) diff --git a/GPU/Common/GPUCommonAlgorithm.h b/GPU/Common/GPUCommonAlgorithm.h index 7464f1e941d50..4d15faac5d5f7 100644 --- a/GPU/Common/GPUCommonAlgorithm.h +++ b/GPU/Common/GPUCommonAlgorithm.h @@ -363,6 +363,16 @@ GPUdi() T work_group_broadcast_FUNC(T v, int i, S& smem) return retVal; } +#define work_group_reduce_add(v) work_group_reduce_add_FUNC(v, smem) +template <class T, class S> +GPUdi() T work_group_reduce_add_FUNC(T v, S& smem) +{ + v = typename S::BlockReduce(smem.cubReduceTmpMem).Sum(v); + __syncthreads(); + v = work_group_broadcast(v, 0); + return v; +} + #define warp_scan_inclusive_add(v) warp_scan_inclusive_add_FUNC(v, smem) template <class T, class S> GPUdi() T warp_scan_inclusive_add_FUNC(T v, S& smem) @@ -380,6 +390,12 @@ GPUdi() T work_group_scan_inclusive_add(T v) return v; } +template <class T> +GPUdi() T work_group_reduce_add(T v) +{ + return v; +} + template <class T> GPUdi() T work_group_broadcast(T v, int i) { diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 6b6de1c07d597..12205729e5ec6 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -69,7 +69,7 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 256 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512 - #define GPUCA_LB_GPUTPCCompressionKernels_step2gather 128 + #define GPUCA_LB_COMPRESSION_GATHER 1024 #define GPUCA_LB_CLUSTER_FINDER 512 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 5 #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 20 @@ -122,7 +122,7 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 128 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 - #define GPUCA_LB_GPUTPCCompressionKernels_step2gather 1024 + #define GPUCA_LB_COMPRESSION_GATHER 1024 #define GPUCA_LB_CLUSTER_FINDER 512 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 4 #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 20 @@ -174,15 +174,15 @@ #ifndef GPUCA_LB_GPUTPCCompressionKernels_step1unattached #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 256 #endif - #ifndef GPUCA_LB_GPUTPCCompressionKernels_step2gather - #define GPUCA_LB_GPUTPCCompressionKernels_step2gather 256 - #endif #ifndef GPUCA_LB_GPUTPCCFDecodeZS #define GPUCA_LB_GPUTPCCFDecodeZS 128, 4 #endif #ifndef GPUCA_LB_GPUTPCCFGather #define GPUCA_LB_GPUTPCCFGather 1024, 1 #endif + #ifndef GPUCA_LB_COMPRESSION_GATHER + #define GPUCA_LB_COMPRESSION_GATHER 1024 + #endif #ifndef GPUCA_LB_CLUSTER_FINDER #define GPUCA_LB_CLUSTER_FINDER 128 #endif @@ -301,6 +301,10 @@ #define GPUCA_LB_GPUTPCCFStreamCompaction_compactDigits GPUCA_THREAD_COUNT_SCAN #define GPUCA_LB_GPUTPCTrackletConstructor_singleSlice GPUCA_LB_GPUTPCTrackletConstructor #define GPUCA_LB_GPUTPCTrackletConstructor_allSlices GPUCA_LB_GPUTPCTrackletConstructor +#define GPUCA_LB_GPUTPCCompressionGatherKernels_unbuffered GPUCA_LB_COMPRESSION_GATHER +#define GPUCA_LB_GPUTPCCompressionGatherKernels_buffered32 GPUCA_LB_COMPRESSION_GATHER +#define GPUCA_LB_GPUTPCCompressionGatherKernels_buffered64 GPUCA_LB_COMPRESSION_GATHER +#define GPUCA_LB_GPUTPCCompressionGatherKernels_buffered128 GPUCA_LB_COMPRESSION_GATHER #ifndef GPUCA_NEIGHBORSFINDER_REGS #define GPUCA_NEIGHBORSFINDER_REGS NONE, 0 diff --git a/GPU/GPUTracking/Base/GPUGeneralKernels.h b/GPU/GPUTracking/Base/GPUGeneralKernels.h index 1a29fd3dc22ac..50289adeaec35 100644 --- a/GPU/GPUTracking/Base/GPUGeneralKernels.h +++ b/GPU/GPUTracking/Base/GPUGeneralKernels.h @@ -54,9 +54,11 @@ class GPUKernelTemplate // Provides the shared memory resources for CUB collectives #if (defined(__CUDACC__) || defined(__HIPCC__)) && defined(GPUCA_GPUCODE) typedef GPUCA_CUB::BlockScan<T, I> BlockScan; + typedef GPUCA_CUB::BlockReduce<T, I> BlockReduce; typedef GPUCA_CUB::WarpScan<T> WarpScan; union { typename BlockScan::TempStorage cubTmpMem; + typename BlockReduce::TempStorage cubReduceTmpMem; typename WarpScan::TempStorage cubWarpTmpMem; int tmpBroadcast; }; diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index f841a5659d7a5..e3e408f9f241d 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -232,6 +232,9 @@ int GPUReconstruction::InitPhaseBeforeDevice() if (mProcessingSettings.tpcCompressionGatherMode < 0) { mProcessingSettings.tpcCompressionGatherMode = (mRecoStepsGPU & GPUDataTypes::RecoStep::TPCCompression) ? 2 : 0; } + if (mProcessingSettings.tpcCompressionGatherModeKernel < 0) { + mProcessingSettings.tpcCompressionGatherModeKernel = 0; + } if (!(mRecoStepsGPU & GPUDataTypes::RecoStep::TPCMerging)) { mProcessingSettings.mergerSortTracks = false; } diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index adb6b460463cb..29866885f2379 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -61,12 +61,16 @@ GPUCA_KRNL_LB((GPUTPCGMMergerFinalize, step2 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTRDTrackerKernels ), (simple), (), ()) GPUCA_KRNL_LB((GPUITSFitterKernel ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCConvertKernel ), (simple), (), ()) -GPUCA_KRNL_LB((GPUTPCCompressionKernels, step0attached ), (simple), (), ()) -GPUCA_KRNL_LB((GPUTPCCompressionKernels, step1unattached ), (simple), (), ()) -GPUCA_KRNL_LB((GPUTPCCompressionKernels, step2gather ), (simple), (), ()) -GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillIndexMap ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillFromDigits ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, findFragmentStart), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCompressionKernels, step0attached ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCCompressionKernels, step1unattached ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, unbuffered ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered32 ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered64 ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered128 ), (simple), (), ()) + +GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillIndexMap ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillFromDigits ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, findFragmentStart ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFPeakFinder ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, noiseSuppression ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, updatePeaks ), (single), (), ()) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompression.h b/GPU/GPUTracking/DataCompression/GPUTPCCompression.h index f9f427372028f..5db9aa4a25500 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompression.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompression.h @@ -45,6 +45,7 @@ class GPUTPCGMMerger; class GPUTPCCompression : public GPUProcessor { friend class GPUTPCCompressionKernels; + friend class GPUTPCCompressionGatherKernels; friend class GPUChainTracking; public: diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index fa22628435738..5ec50793667ac 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -182,13 +182,13 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = processors.ioPtrs.clustersNative; GPUTPCCompression& GPUrestrict() compressor = processors.tpcCompressor; GPUParam& GPUrestrict() param = processors.param; - unsigned int* sortBuffer = smem.step1.sortBuffer; + unsigned int* sortBuffer = smem.sortBuffer; for (int iSliceRow = iBlock; iSliceRow < GPUCA_NSLICES * GPUCA_ROW_COUNT; iSliceRow += nBlocks) { const int iSlice = iSliceRow / GPUCA_ROW_COUNT; const int iRow = iSliceRow % GPUCA_ROW_COUNT; const int idOffset = clusters->clusterOffset[iSlice][iRow]; if (iThread == nThreads - 1) { - smem.step1.nCount = 0; + smem.nCount = 0; } unsigned int totalCount = 0; GPUbarrier(); @@ -232,23 +232,23 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un int myIndex = work_group_scan_inclusive_add(cidx); int storeLater = -1; if (cidx) { - if (smem.step1.nCount + myIndex <= GPUCA_TPC_COMP_CHUNK_SIZE) { - sortBuffer[smem.step1.nCount + myIndex - 1] = i; + if (smem.nCount + myIndex <= GPUCA_TPC_COMP_CHUNK_SIZE) { + sortBuffer[smem.nCount + myIndex - 1] = i; } else { - storeLater = smem.step1.nCount + myIndex - 1 - GPUCA_TPC_COMP_CHUNK_SIZE; + storeLater = smem.nCount + myIndex - 1 - GPUCA_TPC_COMP_CHUNK_SIZE; } } GPUbarrier(); if (iThread == nThreads - 1) { - smem.step1.nCount += myIndex; + smem.nCount += myIndex; } GPUbarrier(); - if (smem.step1.nCount < GPUCA_TPC_COMP_CHUNK_SIZE && i < nn) { + if (smem.nCount < GPUCA_TPC_COMP_CHUNK_SIZE && i < nn) { continue; } - const unsigned int count = CAMath::Min(smem.step1.nCount, (unsigned int)GPUCA_TPC_COMP_CHUNK_SIZE); + const unsigned int count = CAMath::Min(smem.nCount, (unsigned int)GPUCA_TPC_COMP_CHUNK_SIZE); if (param.rec.tpcCompressionModes & GPUSettings::CompressionDifferences) { if (param.rec.tpcCompressionSortOrder == GPUSettings::SortZPadTime) { CAAlgo::sortInBlock(sortBuffer, sortBuffer + count, GPUTPCCompressionKernels_Compare<GPUSettings::SortZPadTime>(clusters->clusters[iSlice][iRow])); @@ -273,7 +273,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un lastPad = orgClPre.padPacked; lastTime = orgClPre.getTimePacked(); } else if (totalCount != 0) { - const ClusterNative& GPUrestrict() orgClPre = clusters->clusters[iSlice][iRow][smem.step1.lastIndex]; + const ClusterNative& GPUrestrict() orgClPre = clusters->clusters[iSlice][iRow][smem.lastIndex]; lastPad = orgClPre.padPacked; lastTime = orgClPre.getTimePacked(); } @@ -306,8 +306,8 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un } totalCount += count; if (iThread == nThreads - 1 && count) { - smem.step1.lastIndex = sortBuffer[count - 1]; - smem.step1.nCount -= count; + smem.lastIndex = sortBuffer[count - 1]; + smem.nCount -= count; } } @@ -319,14 +319,40 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un } } -template <typename T> -GPUdi() bool GPUTPCCompressionKernels::isAlignedTo(const void* ptr) +template <> +GPUdi() GPUTPCCompressionGatherKernels::Vec32* GPUTPCCompressionGatherKernels::GPUSharedMemory::getBuffer<GPUTPCCompressionGatherKernels::Vec32>(int iWarp) +{ + return buf32[iWarp]; +} + +template <> +GPUdi() GPUTPCCompressionGatherKernels::Vec64* GPUTPCCompressionGatherKernels::GPUSharedMemory::getBuffer<GPUTPCCompressionGatherKernels::Vec64>(int iWarp) +{ + return buf64[iWarp]; +} + +template <> +GPUdi() GPUTPCCompressionGatherKernels::Vec128* GPUTPCCompressionGatherKernels::GPUSharedMemory::getBuffer<GPUTPCCompressionGatherKernels::Vec128>(int iWarp) +{ + return buf128[iWarp]; +} + +template <typename T, typename S> +GPUdi() bool GPUTPCCompressionGatherKernels::isAlignedTo(const S* ptr) { - return reinterpret_cast<size_t>(ptr) % alignof(T) == 0; + CONSTEXPRIF(alignof(S) >= alignof(T)) + { + static_cast<void>(ptr); + return true; + } + else + { + return reinterpret_cast<size_t>(ptr) % alignof(T) == 0; + } } template <> -GPUdi() void GPUTPCCompressionKernels::compressorMemcpy<unsigned char>(unsigned char* GPUrestrict() dst, const unsigned char* GPUrestrict() src, unsigned int size, int nThreads, int iThread) +GPUdi() void GPUTPCCompressionGatherKernels::compressorMemcpy<unsigned char>(unsigned char* GPUrestrict() dst, const unsigned char* GPUrestrict() src, unsigned int size, int nThreads, int iThread) { CONSTEXPR int vec128Elems = CpyVector<unsigned char, Vec128>::Size; CONSTEXPR int vec64Elems = CpyVector<unsigned char, Vec64>::Size; @@ -347,7 +373,7 @@ GPUdi() void GPUTPCCompressionKernels::compressorMemcpy<unsigned char>(unsigned } template <> -GPUdi() void GPUTPCCompressionKernels::compressorMemcpy<unsigned short>(unsigned short* GPUrestrict() dst, const unsigned short* GPUrestrict() src, unsigned int size, int nThreads, int iThread) +GPUdi() void GPUTPCCompressionGatherKernels::compressorMemcpy<unsigned short>(unsigned short* GPUrestrict() dst, const unsigned short* GPUrestrict() src, unsigned int size, int nThreads, int iThread) { CONSTEXPR int vec128Elems = CpyVector<unsigned short, Vec128>::Size; CONSTEXPR int vec64Elems = CpyVector<unsigned short, Vec64>::Size; @@ -365,7 +391,7 @@ GPUdi() void GPUTPCCompressionKernels::compressorMemcpy<unsigned short>(unsigned } template <> -GPUdi() void GPUTPCCompressionKernels::compressorMemcpy<unsigned int>(unsigned int* GPUrestrict() dst, const unsigned int* GPUrestrict() src, unsigned int size, int nThreads, int iThread) +GPUdi() void GPUTPCCompressionGatherKernels::compressorMemcpy<unsigned int>(unsigned int* GPUrestrict() dst, const unsigned int* GPUrestrict() src, unsigned int size, int nThreads, int iThread) { CONSTEXPR int vec128Elems = CpyVector<unsigned int, Vec128>::Size; CONSTEXPR int vec64Elems = CpyVector<unsigned int, Vec64>::Size; @@ -379,18 +405,8 @@ GPUdi() void GPUTPCCompressionKernels::compressorMemcpy<unsigned int>(unsigned i } } -template <typename T> -GPUdi() void GPUTPCCompressionKernels::compressorMemcpyBasic(T* GPUrestrict() dst, const T* GPUrestrict() src, unsigned int size, int nThreads, int iThread, int nBlocks, int iBlock) -{ - unsigned int start = (size + nBlocks - 1) / nBlocks * iBlock + iThread; - unsigned int end = CAMath::Min(size, (size + nBlocks - 1) / nBlocks * (iBlock + 1)); - for (unsigned int i = start; i < end; i += nThreads) { - dst[i] = src[i]; - } -} - template <typename Scalar, typename BaseVector> -GPUdi() void GPUTPCCompressionKernels::compressorMemcpyVectorised(Scalar* dst, const Scalar* src, unsigned int size, int nThreads, int iThread) +GPUdi() void GPUTPCCompressionGatherKernels::compressorMemcpyVectorised(Scalar* dst, const Scalar* src, unsigned int size, int nThreads, int iThread) { if (not isAlignedTo<BaseVector>(dst)) { size_t dsti = reinterpret_cast<size_t>(dst); @@ -424,25 +440,92 @@ GPUdi() void GPUTPCCompressionKernels::compressorMemcpyVectorised(Scalar* dst, c } template <typename T> -GPUdi() unsigned int GPUTPCCompressionKernels::calculateWarpOffsets(GPUSharedMemory& smem, T* nums, unsigned int start, unsigned int end, int iWarp, int nLanes, int iLane) +GPUdi() void GPUTPCCompressionGatherKernels::compressorMemcpyBasic(T* GPUrestrict() dst, const T* GPUrestrict() src, unsigned int size, int nThreads, int iThread, int nBlocks, int iBlock) { - unsigned int offset = 0; - if (iWarp > -1) { - for (unsigned int i = start + iLane; i < end; i += nLanes) { - offset += nums[i]; + unsigned int start = (size + nBlocks - 1) / nBlocks * iBlock + iThread; + unsigned int end = CAMath::Min(size, (size + nBlocks - 1) / nBlocks * (iBlock + 1)); + for (unsigned int i = start; i < end; i += nThreads) { + dst[i] = src[i]; + } +} + +template <typename V, typename T, typename S> +GPUdi() void GPUTPCCompressionGatherKernels::compressorMemcpyBuffered(V* buf, T* GPUrestrict() dst, const T* GPUrestrict() src, const S* GPUrestrict() nums, const unsigned int* GPUrestrict() srcOffsets, unsigned int nTracks, int nLanes, int iLane, int diff) +{ + int shmPos = 0; + unsigned int dstOffset = 0; + V* GPUrestrict() dstAligned = nullptr; + + T* bufT = reinterpret_cast<T*>(buf); + CONSTEXPR int bufSize = GPUCA_WARP_SIZE; + CONSTEXPR int bufTSize = bufSize * sizeof(V) / sizeof(T); + + for (unsigned int i = 0; i < nTracks; i++) { + unsigned int srcPos = 0; + unsigned int srcOffset = srcOffsets[i] + diff; + unsigned int srcSize = nums[i] - diff; + + if (dstAligned == nullptr) { + if (not isAlignedTo<V>(dst)) { + size_t dsti = reinterpret_cast<size_t>(dst); + unsigned int offset = (alignof(V) - dsti % alignof(V)) / sizeof(T); + offset = CAMath::Min<unsigned int>(offset, srcSize); + compressorMemcpyBasic(dst, src + srcOffset, offset, nLanes, iLane); + dst += offset; + srcPos += offset; + } + if (isAlignedTo<V>(dst)) { + dstAligned = reinterpret_cast<V*>(dst); + } } + while (srcPos < srcSize) { + unsigned int shmElemsLeft = bufTSize - shmPos; + unsigned int srcElemsLeft = srcSize - srcPos; + unsigned int size = CAMath::Min(srcElemsLeft, shmElemsLeft); + compressorMemcpyBasic(bufT + shmPos, src + srcOffset + srcPos, size, nLanes, iLane); + srcPos += size; + shmPos += size; + + if (shmPos >= bufTSize) { + compressorMemcpyBasic(dstAligned + dstOffset, buf, bufSize, nLanes, iLane); + dstOffset += bufSize; + shmPos = 0; + } + } + } + + compressorMemcpyBasic(reinterpret_cast<T*>(dstAligned + dstOffset), bufT, shmPos, nLanes, iLane); +} + +template <typename T> +GPUdi() unsigned int GPUTPCCompressionGatherKernels::calculateWarpOffsets(GPUSharedMemory& smem, T* nums, unsigned int start, unsigned int end, int nWarps, int iWarp, int nLanes, int iLane) +{ + unsigned int blockOffset = 0; + int iThread = nLanes * iWarp + iLane; + int nThreads = nLanes * nWarps; + unsigned int blockStart = work_group_broadcast(start, 0); + for (unsigned int i = iThread; i < blockStart; i += nThreads) { + blockOffset += nums[i]; } - offset = work_group_scan_inclusive_add(int(offset)); // FIXME: use scan with unsigned int + blockOffset = work_group_reduce_add(blockOffset); + + unsigned int offset = 0; + for (unsigned int i = start + iLane; i < end; i += nLanes) { + offset += nums[i]; + } + offset = work_group_scan_inclusive_add(offset); if (iWarp > -1 && iLane == nLanes - 1) { - smem.step2.warpOffset[iWarp] = offset; + smem.warpOffset[iWarp] = offset; } GPUbarrier(); - offset = (iWarp <= 0) ? 0 : smem.step2.warpOffset[iWarp - 1]; + offset = (iWarp <= 0) ? 0 : smem.warpOffset[iWarp - 1]; + GPUbarrier(); - return offset; + return offset + blockOffset; } + template <> -GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step2gather>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +GPUdii() void GPUTPCCompressionGatherKernels::Thread<GPUTPCCompressionGatherKernels::unbuffered>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) { GPUTPCCompression& GPUrestrict() compressor = processors.tpcCompressor; const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = processors.ioPtrs.clustersNative; @@ -459,8 +542,12 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step2ga unsigned int rowsPerWarp = (nRows + nWarps - 1) / nWarps; unsigned int rowStart = rowsPerWarp * iWarp; unsigned int rowEnd = CAMath::Min(nRows, rowStart + rowsPerWarp); + if (rowStart >= nRows) { + rowStart = 0; + rowEnd = 0; + } - unsigned int rowsOffset = calculateWarpOffsets(smem, compressor.mPtrs.nSliceRowClusters, rowStart, rowEnd, iWarp, nLanes, iLane); + unsigned int rowsOffset = calculateWarpOffsets(smem, compressor.mPtrs.nSliceRowClusters, rowStart, rowEnd, nWarps, iWarp, nLanes, iLane); compressorMemcpy(compressor.mOutput->nSliceRowClusters, compressor.mPtrs.nSliceRowClusters, compressor.NSLICES * GPUCA_ROW_COUNT, nThreads, iThread); compressorMemcpy(compressor.mOutput->nTrackClusters, compressor.mPtrs.nTrackClusters, compressor.mMemory->nStoredTracks, nThreads, iThread); @@ -495,8 +582,12 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step2ga unsigned int tracksPerWarp = (compressor.mMemory->nStoredTracks + nWarps - 1) / nWarps; unsigned int trackStart = tracksPerWarp * iWarp; unsigned int trackEnd = CAMath::Min(compressor.mMemory->nStoredTracks, trackStart + tracksPerWarp); + if (trackStart >= compressor.mMemory->nStoredTracks) { + trackStart = 0; + trackEnd = 0; + } - unsigned int tracksOffset = calculateWarpOffsets(smem, compressor.mPtrs.nTrackClusters, trackStart, trackEnd, iWarp, nLanes, iLane); + unsigned int tracksOffset = calculateWarpOffsets(smem, compressor.mPtrs.nTrackClusters, trackStart, trackEnd, nWarps, iWarp, nLanes, iLane); for (unsigned int i = trackStart; i < trackEnd; i += nLanes) { unsigned int nTrackClusters = 0; @@ -506,14 +597,14 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step2ga nTrackClusters = compressor.mPtrs.nTrackClusters[i + iLane]; srcOffset = compressor.mAttachedClusterFirstIndex[i + iLane]; } - smem.step2.sizes[iWarp][iLane] = nTrackClusters; - smem.step2.srcOffsets[iWarp][iLane] = srcOffset; + smem.unbuffered.sizes[iWarp][iLane] = nTrackClusters; + smem.unbuffered.srcOffsets[iWarp][iLane] = srcOffset; unsigned int elems = (i + nLanes < trackEnd) ? nLanes : (trackEnd - i); for (unsigned int j = 0; j < elems; j++) { - nTrackClusters = smem.step2.sizes[iWarp][j]; - srcOffset = smem.step2.srcOffsets[iWarp][j]; + nTrackClusters = smem.unbuffered.sizes[iWarp][j]; + srcOffset = smem.unbuffered.srcOffsets[iWarp][j]; unsigned int idx = i + j; compressorMemcpy(compressor.mOutput->qTotA + tracksOffset, compressor.mPtrs.qTotA + srcOffset, nTrackClusters, nLanes, iLane); compressorMemcpy(compressor.mOutput->qMaxA + tracksOffset, compressor.mPtrs.qMaxA + srcOffset, nTrackClusters, nLanes, iLane); @@ -532,3 +623,104 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step2ga } } } + +template <typename V> +GPUdii() void GPUTPCCompressionGatherKernels::gatherBuffered(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +{ + + GPUTPCCompression& GPUrestrict() compressor = processors.tpcCompressor; + const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = processors.ioPtrs.clustersNative; + + int nWarps = nThreads / GPUCA_WARP_SIZE; + int iWarp = iThread / GPUCA_WARP_SIZE; + + int nGlobalWarps = nWarps * nBlocks; + int iGlobalWarp = nWarps * iBlock + iWarp; + + int nLanes = GPUCA_WARP_SIZE; + int iLane = iThread % GPUCA_WARP_SIZE; + + auto& input = compressor.mPtrs; + auto* output = compressor.mOutput; + + unsigned int nRows = compressor.NSLICES * GPUCA_ROW_COUNT; + unsigned int rowsPerWarp = (nRows + nGlobalWarps - 1) / nGlobalWarps; + unsigned int rowStart = rowsPerWarp * iGlobalWarp; + unsigned int rowEnd = CAMath::Min(nRows, rowStart + rowsPerWarp); + if (rowStart >= nRows) { + rowStart = 0; + rowEnd = 0; + } + rowsPerWarp = rowEnd - rowStart; + + unsigned int rowsOffset = calculateWarpOffsets(smem, input.nSliceRowClusters, rowStart, rowEnd, nWarps, iWarp, nLanes, iLane); + + unsigned int nStoredTracks = compressor.mMemory->nStoredTracks; + unsigned int tracksPerWarp = (nStoredTracks + nGlobalWarps - 1) / nGlobalWarps; + unsigned int trackStart = tracksPerWarp * iGlobalWarp; + unsigned int trackEnd = CAMath::Min(nStoredTracks, trackStart + tracksPerWarp); + if (trackStart >= nStoredTracks) { + trackStart = 0; + trackEnd = 0; + } + tracksPerWarp = trackEnd - trackStart; + + unsigned int tracksOffset = calculateWarpOffsets(smem, input.nTrackClusters, trackStart, trackEnd, nWarps, iWarp, nLanes, iLane); + + if (iBlock == 0) { + compressorMemcpyBasic(output->nSliceRowClusters, input.nSliceRowClusters, compressor.NSLICES * GPUCA_ROW_COUNT, nThreads, iThread); + compressorMemcpyBasic(output->nTrackClusters, input.nTrackClusters, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->qPtA, input.qPtA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->rowA, input.rowA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->sliceA, input.sliceA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->timeA, input.timeA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->padA, input.padA, compressor.mMemory->nStoredTracks, nThreads, iThread); + } + + const unsigned int* clusterOffsets = reinterpret_cast<const unsigned int*>(clusters->clusterOffset) + rowStart; + const unsigned int* nSliceRowClusters = input.nSliceRowClusters + rowStart; + + auto* buf = smem.getBuffer<V>(iWarp); + + compressorMemcpyBuffered(buf, output->qTotU + rowsOffset, input.qTotU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->qMaxU + rowsOffset, input.qMaxU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->flagsU + rowsOffset, input.flagsU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->padDiffU + rowsOffset, input.padDiffU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->timeDiffU + rowsOffset, input.timeDiffU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaPadU + rowsOffset, input.sigmaPadU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaTimeU + rowsOffset, input.sigmaTimeU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + + const unsigned short* nTrackClustersPtr = input.nTrackClusters + trackStart; + const unsigned int* aClsFstIdx = compressor.mAttachedClusterFirstIndex + trackStart; + + compressorMemcpyBuffered(buf, output->qTotA + tracksOffset, input.qTotA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->qMaxA + tracksOffset, input.qMaxA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->flagsA + tracksOffset, input.flagsA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaPadA + tracksOffset, input.sigmaPadA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaTimeA + tracksOffset, input.sigmaTimeA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + + // First index stored with track + unsigned int tracksOffsetDiff = tracksOffset - trackStart; + compressorMemcpyBuffered(buf, output->rowDiffA + tracksOffsetDiff, input.rowDiffA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); + compressorMemcpyBuffered(buf, output->sliceLegDiffA + tracksOffsetDiff, input.sliceLegDiffA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); + compressorMemcpyBuffered(buf, output->padResA + tracksOffsetDiff, input.padResA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); + compressorMemcpyBuffered(buf, output->timeResA + tracksOffsetDiff, input.timeResA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); +} + +template <> +GPUdii() void GPUTPCCompressionGatherKernels::Thread<GPUTPCCompressionGatherKernels::buffered32>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +{ + gatherBuffered<Vec32>(nBlocks, nThreads, iBlock, iThread, smem, processors); +} + +template <> +GPUdii() void GPUTPCCompressionGatherKernels::Thread<GPUTPCCompressionGatherKernels::buffered64>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +{ + gatherBuffered<Vec64>(nBlocks, nThreads, iBlock, iThread, smem, processors); +} + +template <> +GPUdii() void GPUTPCCompressionGatherKernels::Thread<GPUTPCCompressionGatherKernels::buffered128>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +{ + gatherBuffered<Vec128>(nBlocks, nThreads, iBlock, iThread, smem, processors); +} diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h index 74e2634589100..a041608f612aa 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h @@ -36,28 +36,39 @@ class GPUTPCCompressionKernels : public GPUKernelTemplate enum K : int { step0attached = 0, step1unattached = 1, - step2gather = 2, }; -#if GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step1unattached) > GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step2gather) -#define GPUCA_COMPRESSION_SCAN_MAX_THREADS GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step1unattached) -#else -#define GPUCA_COMPRESSION_SCAN_MAX_THREADS GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step2gather) -#endif + struct GPUSharedMemory : public GPUKernelTemplate::GPUSharedMemoryScan64<int, GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step1unattached)> { + GPUAtomic(unsigned int) nCount; + unsigned int lastIndex; + unsigned int sortBuffer[GPUCA_TPC_COMP_CHUNK_SIZE]; + }; - struct GPUSharedMemory : public GPUKernelTemplate::GPUSharedMemoryScan64<int, GPUCA_COMPRESSION_SCAN_MAX_THREADS> { - union { - struct { - GPUAtomic(unsigned int) nCount; - unsigned int lastIndex; - unsigned int sortBuffer[GPUCA_TPC_COMP_CHUNK_SIZE]; - } step1; - struct { - unsigned int warpOffset[GPUCA_GET_WARP_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step2gather)]; - unsigned int sizes[GPUCA_GET_WARP_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step2gather)][GPUCA_WARP_SIZE]; - unsigned int srcOffsets[GPUCA_GET_WARP_COUNT(GPUCA_LB_GPUTPCCompressionKernels_step2gather)][GPUCA_WARP_SIZE]; - } step2; - }; + template <int iKernel = defaultKernel> + GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); + + public: + template <int I> + class GPUTPCCompressionKernels_Compare + { + public: + GPUhdi() GPUTPCCompressionKernels_Compare(const o2::tpc::ClusterNative* p) : mClsPtr(p) {} + GPUd() bool operator()(unsigned int a, unsigned int b) const; + + protected: + const o2::tpc::ClusterNative* mClsPtr; + }; +}; + +class GPUTPCCompressionGatherKernels : public GPUKernelTemplate +{ + + public: + enum K : int { + unbuffered, + buffered32, + buffered64, + buffered128, }; using Vec16 = unsigned short; @@ -65,6 +76,22 @@ class GPUTPCCompressionKernels : public GPUKernelTemplate using Vec64 = unsigned long int; using Vec128 = uint4; + struct GPUSharedMemory : public GPUKernelTemplate::GPUSharedMemoryScan64<unsigned int, GPUCA_GET_THREAD_COUNT(GPUCA_LB_COMPRESSION_GATHER)> { + union { + unsigned int warpOffset[GPUCA_GET_WARP_COUNT(GPUCA_LB_COMPRESSION_GATHER)]; + Vec32 buf32[GPUCA_GET_WARP_COUNT(GPUCA_LB_COMPRESSION_GATHER)][GPUCA_WARP_SIZE]; + Vec64 buf64[GPUCA_GET_WARP_COUNT(GPUCA_LB_COMPRESSION_GATHER)][GPUCA_WARP_SIZE]; + Vec128 buf128[GPUCA_GET_WARP_COUNT(GPUCA_LB_COMPRESSION_GATHER)][GPUCA_WARP_SIZE]; + struct { + unsigned int sizes[GPUCA_GET_WARP_COUNT(GPUCA_LB_COMPRESSION_GATHER)][GPUCA_WARP_SIZE]; + unsigned int srcOffsets[GPUCA_GET_WARP_COUNT(GPUCA_LB_COMPRESSION_GATHER)][GPUCA_WARP_SIZE]; + } unbuffered; + }; + + template <typename V> + GPUdi() V* getBuffer(int iWarp); + }; + template <typename Scalar, typename BaseVector> union CpyVector { enum { @@ -77,8 +104,8 @@ class GPUTPCCompressionKernels : public GPUKernelTemplate template <int iKernel = defaultKernel> GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); - template <typename T> - GPUdi() static bool isAlignedTo(const void* ptr); + template <typename T, typename S> + GPUdi() static bool isAlignedTo(const S* ptr); template <typename T> GPUdi() static void compressorMemcpy(GPUgeneric() T* dst, GPUgeneric() const T* src, unsigned int size, int nThreads, int iThread); @@ -89,21 +116,16 @@ class GPUTPCCompressionKernels : public GPUKernelTemplate template <typename T> GPUdi() static void compressorMemcpyBasic(T* dst, const T* src, unsigned int size, int nThreads, int iThread, int nBlocks = 1, int iBlock = 0); - template <typename T> - GPUdi() static unsigned int calculateWarpOffsets(GPUSharedMemory& smem, T* nums, unsigned int start, unsigned int end, int iWarp, int nLanes, int iLane); + template <typename V, typename T, typename S> + GPUdi() static void compressorMemcpyBuffered(V* buf, T* dst, const T* src, const S* nums, const unsigned int* srcOffets, unsigned int nTracks, int nLanes, int iLane, int diff = 0); - public: - template <int I> - class GPUTPCCompressionKernels_Compare - { - public: - GPUhdi() GPUTPCCompressionKernels_Compare(const o2::tpc::ClusterNative* p) : mClsPtr(p) {} - GPUd() bool operator()(unsigned int a, unsigned int b) const; + template <typename T> + GPUdi() static unsigned int calculateWarpOffsets(GPUSharedMemory& smem, T* nums, unsigned int start, unsigned int end, int nWarps, int iWarp, int nLanes, int iLane); - protected: - const o2::tpc::ClusterNative* mClsPtr; - }; + template <typename V> + GPUdii() static void gatherBuffered(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); }; + } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 6c637938a09d9..8262d47c9d857 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2113,8 +2113,28 @@ int GPUChainTracking::RunTPCCompression() } TransferMemoryResourcesToGPU(myStep, &Compressor, outputStream); unsigned int nBlocks = 2; - runKernel<GPUTPCCompressionKernels, GPUTPCCompressionKernels::step2gather>(GetGridBlk(nBlocks, outputStream), krnlRunRangeNone, krnlEventNone); - getKernelTimer<GPUTPCCompressionKernels, GPUTPCCompressionKernels::step2gather>(RecoStep::TPCCompression, 0, outputSize); + switch (ProcessingSettings().tpcCompressionGatherModeKernel) { + case 0: + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::unbuffered>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::unbuffered>(RecoStep::TPCCompression, 0, outputSize); + break; + case 1: + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered32>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered32>(RecoStep::TPCCompression, 0, outputSize); + break; + case 2: + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered64>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered64>(RecoStep::TPCCompression, 0, outputSize); + break; + case 3: + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered128>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered128>(RecoStep::TPCCompression, 0, outputSize); + break; + default: + GPUError("Invalid compression kernel selected."); + return 1; + } + } else { char direction = 0; if (ProcessingSettings().tpcCompressionGatherMode == 0) { From dc09cd0aee265ad94a612334bc368d21b070fe8a Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Sat, 22 Aug 2020 16:42:29 +0200 Subject: [PATCH 0439/1751] TPCClusterFinder: Improve performance for mc labels. --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- .../GPUTPCCFChargeMapFiller.cxx | 34 ++++++++++++++----- .../GPUTPCCFChargeMapFiller.h | 3 ++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 8262d47c9d857..b662d2f9fc0cc 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1111,7 +1111,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) std::vector<bool> laneHasData(GetProcessingSettings().nTPCClustererLanes, false); for (CfFragment fragment = mCFContext->fragmentFirst; !fragment.isEnd(); fragment = fragment.next()) { if (GetProcessingSettings().debugLevel >= 3) { - GPUInfo("Processing time bins [%d, %d)", fragment.start, fragment.last()); + GPUInfo("Processing time bins [%d, %d) for sectors %d to %d", fragment.start, fragment.last(), iSliceBase, iSliceBase + GetProcessingSettings().nTPCClustererLanes - 1); } for (int lane = 0; lane < GetProcessingSettings().nTPCClustererLanes && iSliceBase + lane < NSLICES; lane++) { if (fragment.index != 0) { diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx index fa4e3e438da4f..959b3f1a762db 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx @@ -67,21 +67,37 @@ GPUd() void GPUTPCCFChargeMapFiller::fillFromDigitsImpl(int nBlocks, int nThread template <> GPUdii() void GPUTPCCFChargeMapFiller::Thread<GPUTPCCFChargeMapFiller::findFragmentStart>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer) { - // TODO: use binary search - if (get_global_id(0) != 0) { + if (iThread != 0) { return; } size_t nDigits = clusterer.mPmemory->counters.nDigits; const tpc::Digit* digits = clusterer.mPdigits; - size_t st = 0; - for (; st < nDigits && digits[st].getTimeStamp() < clusterer.mPmemory->fragment.first(); st++) { - } - - size_t end = st; - for (; end < nDigits && digits[end].getTimeStamp() < clusterer.mPmemory->fragment.last(); end++) { - } + size_t st = findTransition(clusterer.mPmemory->fragment.first(), digits, nDigits, 0); + size_t end = findTransition(clusterer.mPmemory->fragment.last(), digits, nDigits, st); clusterer.mPmemory->fragment.digitsStart = st; clusterer.mPmemory->counters.nPositions = end - st; } + +GPUd() size_t GPUTPCCFChargeMapFiller::findTransition(int time, const tpc::Digit* digits, size_t nDigits, size_t lower) +{ + size_t upper = nDigits - 1; + + while (lower <= upper) { + size_t middle = (lower + upper) / 2; + + if (middle == 0) { + return 0; + } + + if (digits[middle].getTimeStamp() < time) { + lower = middle + 1; + } else if (digits[middle - 1].getTimeStamp() < time) { + return middle; + } else { + upper = middle - 1; + } + } + return lower; +} diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h index aa3244679f723..c92169383f70c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h @@ -64,6 +64,9 @@ class GPUTPCCFChargeMapFiller : public GPUKernelTemplate static GPUd() void fillIndexMapImpl(int, int, int, int, const CfFragment&, const tpc::Digit*, Array2D<uint>&, size_t); static GPUd() void fillFromDigitsImpl(int, int, int, int, const CfFragment&, size_t, const tpc::Digit*, ChargePos*, Array2D<PackedCharge>&); + + private: + static GPUd() size_t findTransition(int, const tpc::Digit*, size_t, size_t); }; } // namespace gpu From cb4c9259eab7497e6a73dd46a7b441d403167dee Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Sat, 22 Aug 2020 18:14:57 +0200 Subject: [PATCH 0440/1751] TPCClusterFinder: Fix mc propagation with ZS enabled. --- GPU/GPUTracking/Base/GPUReconstructionKernels.h | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 ++-- .../TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx | 12 +++++++++--- .../TPCClusterFinder/GPUTPCClusterFinder.cxx | 3 +-- .../TPCClusterFinder/GPUTPCClusterFinder.h | 1 + 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index 29866885f2379..1350ca1c5f289 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -70,7 +70,7 @@ GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered128 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillIndexMap ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillFromDigits ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, findFragmentStart ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, findFragmentStart ), (single), (, char setPositions), (, setPositions)) GPUCA_KRNL_LB((GPUTPCCFPeakFinder ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, noiseSuppression ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, updatePeaks ), (single), (), ()) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index b662d2f9fc0cc..810aff99267d7 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1167,7 +1167,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } if (propagateMCLabels || not mIOPtrs.tpcZS) { - runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::findFragmentStart>(GetGrid(1, lane), {iSlice}, {}); + runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::findFragmentStart>(GetGrid(1, lane), {iSlice}, {}, mIOPtrs.tpcZS == nullptr); TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); } @@ -1206,7 +1206,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } if (propagateMCLabels) { - runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::fillIndexMap>(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); + runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::fillIndexMap>(GetGrid(clusterer.mPmemory->counters.nDigitsInFragment, lane), {iSlice}, {}); } runKernel<GPUTPCCFPeakFinder>(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx index 959b3f1a762db..4beb572999aff 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx @@ -22,7 +22,7 @@ template <> GPUdii() void GPUTPCCFChargeMapFiller::Thread<GPUTPCCFChargeMapFiller::fillIndexMap>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer) { Array2D<uint> indexMap(clusterer.mPindexMap); - fillIndexMapImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), clusterer.mPmemory->fragment, clusterer.mPdigits, indexMap, clusterer.mPmemory->counters.nPositions); + fillIndexMapImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), clusterer.mPmemory->fragment, clusterer.mPdigits, indexMap, clusterer.mPmemory->counters.nDigitsInFragment); } GPUd() void GPUTPCCFChargeMapFiller::fillIndexMapImpl(int nBlocks, int nThreads, int iBlock, int iThread, @@ -65,7 +65,7 @@ GPUd() void GPUTPCCFChargeMapFiller::fillFromDigitsImpl(int nBlocks, int nThread } template <> -GPUdii() void GPUTPCCFChargeMapFiller::Thread<GPUTPCCFChargeMapFiller::findFragmentStart>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer) +GPUdii() void GPUTPCCFChargeMapFiller::Thread<GPUTPCCFChargeMapFiller::findFragmentStart>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, char setPositions) { if (iThread != 0) { return; @@ -77,7 +77,13 @@ GPUdii() void GPUTPCCFChargeMapFiller::Thread<GPUTPCCFChargeMapFiller::findFragm size_t end = findTransition(clusterer.mPmemory->fragment.last(), digits, nDigits, st); clusterer.mPmemory->fragment.digitsStart = st; - clusterer.mPmemory->counters.nPositions = end - st; + + size_t elems = end - st; + + clusterer.mPmemory->counters.nDigitsInFragment = elems; + if (setPositions) { + clusterer.mPmemory->counters.nPositions = elems; + } } GPUd() size_t GPUTPCCFChargeMapFiller::findTransition(int time, const tpc::Digit* digits, size_t nDigits, size_t lower) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx index 6de2623d70614..e654057b675df 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx @@ -32,6 +32,7 @@ void GPUTPCClusterFinder::InitializeProcessor() GPUTPCClusterFinder::~GPUTPCClusterFinder() { + delete[] mMinMaxCN; clearMCMemory(); } @@ -147,6 +148,4 @@ void GPUTPCClusterFinder::clearMCMemory() mPlabelHeaderOffset = nullptr; delete[] mPlabelDataOffset; mPlabelDataOffset = nullptr; - delete[] mMinMaxCN; - mMinMaxCN = nullptr; } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index a582595ed32d5..3444899311a33 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -52,6 +52,7 @@ class GPUTPCClusterFinder : public GPUProcessor struct Memory { struct counters_t { size_t nDigits = 0; + tpccf::SizeT nDigitsInFragment = 0; // num of digits in fragment can differ from nPositions if ZS is active tpccf::SizeT nPositions = 0; tpccf::SizeT nPeaks = 0; tpccf::SizeT nClusters = 0; From 542f311677432ef0acba35264476525972461692 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 12:31:50 +0200 Subject: [PATCH 0441/1751] GPU: Fix codechecker warning --- GPU/GPUTracking/Standalone/qa/GPUQA.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index a18a17d0bce49..383f89bcfaf14 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -49,7 +49,7 @@ class GPUQA void SetMCTrackRange(int min, int max) {} bool SuppressTrack(int iTrack) const { return false; } bool SuppressHit(int iHit) const { return false; } - bool HitAttachStatus(int iHit) const { return false; } + int HitAttachStatus(int iHit) const { return false; } int GetMCTrackLabel(unsigned int trackId) const { return -1; } bool clusterRemovable(int cid, bool prot) const { return false; } static bool QAAvailable() { return false; } @@ -95,7 +95,7 @@ class GPUQA void SetMCTrackRange(int min, int max); bool SuppressTrack(int iTrack) const; bool SuppressHit(int iHit) const; - bool HitAttachStatus(int iHit) const; + int HitAttachStatus(int iHit) const; int GetMCTrackLabel(unsigned int trackId) const; bool clusterRemovable(int cid, bool prot) const; static bool QAAvailable() { return true; } @@ -315,7 +315,7 @@ class GPUQA inline bool GPUQA::SuppressTrack(int iTrack) const { return (mConfig.matchMCLabels.size() && !mGoodTracks[mNEvents][iTrack]); } inline bool GPUQA::SuppressHit(int iHit) const { return (mConfig.matchMCLabels.size() && !mGoodHits[mNEvents - 1][iHit]); } -inline bool GPUQA::HitAttachStatus(int iHit) const { return (mClusterParam.size() && mClusterParam[iHit].fakeAttached ? (mClusterParam[iHit].attached ? 1 : 2) : 0); } +inline int GPUQA::HitAttachStatus(int iHit) const { return (mClusterParam.size() && mClusterParam[iHit].fakeAttached ? (mClusterParam[iHit].attached ? 1 : 2) : 0); } } // namespace gpu } // namespace GPUCA_NAMESPACE From c381bd48b63187c3939d3f6b954d262e68c2e056 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 24 Jul 2020 22:11:49 +0200 Subject: [PATCH 0442/1751] GPU: Select fastest gather kernel depending on architecture --- GPU/Common/GPUDefGPUParameters.h | 6 ++++++ GPU/GPUTracking/Base/GPUReconstruction.cxx | 3 --- GPU/GPUTracking/Base/GPUReconstructionIncludes.h | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 12205729e5ec6..ee4d5f0f920cf 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -80,6 +80,7 @@ #define GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION 1 #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_NO_ATOMIC_PRECHECK 1 + #define GPUCA_COMP_GATHER_KERNEL 3 #elif defined(GPUCA_GPUTYPE_TURING) #define GPUCA_WARP_SIZE 32 #define GPUCA_THREAD_COUNT 512 @@ -133,6 +134,7 @@ #define GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION 1 #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_NO_ATOMIC_PRECHECK 1 + #define GPUCA_COMP_GATHER_KERNEL 0 // #define GPUCA_USE_TEXTURES #elif defined(GPUCA_GPUTYPE_OPENCL) #elif defined(GPUCA_GPUCODE) @@ -334,6 +336,9 @@ #ifndef GPUCA_TRACKLET_SELECTOR_SLICE_COUNT #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 8 // Currently must be smaller than avaiable MultiProcessors on GPU or will result in wrong results #endif + #ifndef GPUCA_COMP_GATHER_KERNEL + #define GPUCA_COMP_GATHER_KERNEL 0 + #endif #else #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 0 #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 0 @@ -344,6 +349,7 @@ #define GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION 0 #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_THREAD_COUNT_FINDER 1 + #define GPUCA_COMP_GATHER_KERNEL 0 #endif #ifndef GPUCA_WARP_SIZE diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index e3e408f9f241d..f841a5659d7a5 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -232,9 +232,6 @@ int GPUReconstruction::InitPhaseBeforeDevice() if (mProcessingSettings.tpcCompressionGatherMode < 0) { mProcessingSettings.tpcCompressionGatherMode = (mRecoStepsGPU & GPUDataTypes::RecoStep::TPCCompression) ? 2 : 0; } - if (mProcessingSettings.tpcCompressionGatherModeKernel < 0) { - mProcessingSettings.tpcCompressionGatherModeKernel = 0; - } if (!(mRecoStepsGPU & GPUDataTypes::RecoStep::TPCMerging)) { mProcessingSettings.mergerSortTracks = false; } diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h index 6c2af2842bc68..d08ed50241ac7 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h @@ -61,6 +61,9 @@ } \ if (param().rec.loopInterpolationInExtraPass < 0) { \ param().rec.loopInterpolationInExtraPass = GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION; \ + } \ + if (mProcessingSettings.tpcCompressionGatherModeKernel < 0) { \ + mProcessingSettings.tpcCompressionGatherModeKernel = GPUCA_COMP_GATHER_KERNEL; \ } #endif From 7d23b2d2cfb64d7cf757c682e06a9b0a5370cacd Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 26 Aug 2020 08:36:01 +0200 Subject: [PATCH 0443/1751] DPL Analysis: fix a corner case in slicing/grouping (#4205) * DPL Analysis: fix a corner case in slicing/grouping * Simplify slicing algorithm * Prevent re-creating arrays and extra checks in a loop --- .../Core/include/Framework/AnalysisTask.h | 2 +- Framework/Core/include/Framework/Kernels.h | 56 +++++++++---------- Framework/Core/test/test_Kernels.cxx | 18 ++---- 3 files changed, 34 insertions(+), 42 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 42b1f4f20aeae..46b2eaef2c5ce 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -794,7 +794,7 @@ struct AnalysisDataProcessorBuilder { throw std::runtime_error("Cannot split collection"); } if (groups[index].size() != gt.tableSize()) { - throw std::runtime_error("Splitting collection resulted in different group number than there is rows in the grouping table."); + throw std::runtime_error(fmt::format("Splitting collection resulted in different group number ({}) than there is rows in the grouping table ({}).", groups[index].size(), gt.tableSize())); }; } }; diff --git a/Framework/Core/include/Framework/Kernels.h b/Framework/Core/include/Framework/Kernels.h index 615617c569bda..2dc39e85619c5 100644 --- a/Framework/Core/include/Framework/Kernels.h +++ b/Framework/Core/include/Framework/Kernels.h @@ -191,12 +191,12 @@ auto sliceByColumn(char const* key, // create slices and offsets auto offset = 0; auto count = 0; + auto size = values.length(); - for (auto r = 0; r < size; ++r) { - count = counts.Value(r); - std::shared_ptr<arrow::Schema> schema(input->schema()); - std::vector<std::shared_ptr<arrow::ChunkedArray>> sliceArray; - sliceArray.reserve(schema->num_fields()); + std::shared_ptr<arrow::Schema> schema(input->schema()); + std::vector<std::shared_ptr<arrow::ChunkedArray>> sliceArray; + + auto injectSlice = [&](T count) { for (auto ci = 0; ci < schema->num_fields(); ++ci) { sliceArray.emplace_back(input->column(ci)->Slice(offset, count)); } @@ -204,34 +204,32 @@ auto sliceByColumn(char const* key, if (offsets) { offsets->emplace_back(offset); } - offset += count; sliceArray.clear(); - if (r < size - 1) { - auto nextValue = values.Value(r + 1); - while (nextValue - values.Value(r) > 1) { - for (auto ci = 0; ci < schema->num_fields(); ++ci) { - sliceArray.emplace_back(input->column(ci)->Slice(offset, 0)); - } - slices->emplace_back(arrow::Datum(arrow::Table::Make(schema, sliceArray))); - if (offsets) { - offsets->emplace_back(offset); - } - sliceArray.clear(); - nextValue -= 1; - } + }; + + auto current = 0; + auto v = values.Value(0); + while (v - current >= 1) { + injectSlice(0); + ++current; + } + + for (auto r = 0; r < size - 1; ++r) { + count = counts.Value(r); + injectSlice(count); + offset += count; + auto nextValue = values.Value(r + 1); + auto value = values.Value(r); + while (nextValue - value > 1) { + injectSlice(0); + ++value; } } - if (values.Value(size - 1) < fullSize) { + injectSlice(counts.Value(size - 1)); + + if (values.Value(size - 1) < fullSize - 1) { for (auto v = values.Value(size - 1) + 1; v < fullSize; ++v) { - std::shared_ptr<arrow::Schema> schema(input->schema()); - std::vector<std::shared_ptr<arrow::ChunkedArray>> sliceArray; - for (auto ci = 0; ci < schema->num_fields(); ++ci) { - sliceArray.emplace_back(input->column(ci)->Slice(offset, 0)); - } - slices->emplace_back(arrow::Datum(arrow::Table::Make(schema, sliceArray))); - if (offsets) { - offsets->emplace_back(offset); - } + injectSlice(0); } } diff --git a/Framework/Core/test/test_Kernels.cxx b/Framework/Core/test/test_Kernels.cxx index c14c35c76b057..46a2087c22b95 100644 --- a/Framework/Core/test/test_Kernels.cxx +++ b/Framework/Core/test/test_Kernels.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test Framework AlgorithmSpec +#define BOOST_TEST_MODULE Test Framework Kernels #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK @@ -31,10 +31,7 @@ BOOST_AUTO_TEST_CASE(TestSlicing) { TableBuilder builder; auto rowWriter = builder.persist<int32_t, int32_t>({"x", "y"}); - rowWriter(0, 0, 0); - rowWriter(0, 0, 1); - rowWriter(0, 0, 2); - rowWriter(0, 0, 3); + rowWriter(0, 1, 4); rowWriter(0, 1, 5); rowWriter(0, 1, 6); @@ -52,8 +49,8 @@ BOOST_AUTO_TEST_CASE(TestSlicing) auto arr0 = static_cast<NumericArray<Int32Type>>(array.field(0)->data()); auto arr1 = static_cast<NumericArray<Int64Type>>(array.field(1)->data()); - std::array<int, 5> v{0, 1, 2, 4, 5}; - std::array<int, 5> c{4, 4, 1, 1, 2}; + std::array<int, 4> v{1, 2, 4, 5}; + std::array<int, 4> c{4, 1, 1, 2}; for (auto i = 0; i < arr0.length(); ++i) { BOOST_REQUIRE_EQUAL(arr0.Value(i), v[i]); @@ -66,10 +63,7 @@ BOOST_AUTO_TEST_CASE(TestSlicingFramework) { TableBuilder builder; auto rowWriter = builder.persist<int32_t, int32_t>({"x", "y"}); - rowWriter(0, 0, 0); - rowWriter(0, 0, 1); - rowWriter(0, 0, 2); - rowWriter(0, 0, 3); + rowWriter(0, 1, 4); rowWriter(0, 1, 5); rowWriter(0, 1, 6); @@ -85,7 +79,7 @@ BOOST_AUTO_TEST_CASE(TestSlicingFramework) auto status = sliceByColumn<int32_t>("x", table, 12, &slices, &offsets); BOOST_REQUIRE(status.ok()); BOOST_REQUIRE_EQUAL(slices.size(), 12); - std::array<int, 12> sizes{4, 4, 1, 0, 1, 2, 0, 0, 0, 0, 0, 0}; + std::array<int, 12> sizes{0, 4, 1, 0, 1, 2, 0, 0, 0, 0, 0, 0}; for (auto i = 0u; i < slices.size(); ++i) { BOOST_REQUIRE_EQUAL(slices[i].table()->num_rows(), sizes[i]); } From ddd815e1c2d53cf48b7556e56801f8ca45fbc541 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 18:41:30 +0200 Subject: [PATCH 0444/1751] GPU: Disable some settings by default when incompatible to the configuration --- GPU/GPUTracking/Base/GPUSettingsList.h | 2 +- GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx | 2 ++ GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx | 2 ++ GPU/GPUTracking/Standalone/standalone.cxx | 4 ++++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index ce0396b72d6dd..061b09acd9257 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -234,7 +234,7 @@ AddOption(recoSteps, int, -1, "", 0, "Bitmask for RecoSteps") AddOption(recoStepsGPU, int, -1, "", 0, "Bitmask for RecoSteps") AddOption(runMerger, int, 1, "", 0, "Run track merging / refit", min(0), max(1)) AddOption(runTRD, int, -1, "", 0, "Enable TRD processing") -AddOption(rundEdx, int, 1, "", 0, "Enable dEdx processing") +AddOption(rundEdx, int, -1, "", 0, "Enable dEdx processing") AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") AddHelp("help", 'h') diff --git a/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx b/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx index 8b5af42c399dd..a9c24968bbb37 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx @@ -305,6 +305,8 @@ int GPUTPCGlobalMergerComponent::Configure(const char* cdbEntry, const char* cha rec.mergerInterpolateErrors = false; rec.NonConsecutiveIDs = true; rec.mergerReadFromTrackerDirectly = false; + devProc.ompThreads = 1; + devProc.ompKernels = false; GPURecoStepConfiguration steps; steps.steps.set(GPUDataTypes::RecoStep::TPCMerging); diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx index a436d1bd971e3..58039886112ce 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerComponent.cxx @@ -391,6 +391,8 @@ int GPUTPCTrackerComponent::ConfigureSlices() devProc.stuckProtection = fGPUStuckProtection; rec.NonConsecutiveIDs = true; rec.mergerReadFromTrackerDirectly = false; + devProc.ompThreads = 1; + devProc.ompKernels = false; GPURecoStepConfiguration steps; steps.steps.set(GPUDataTypes::RecoStep::TPCSliceTracking); diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 77e016cfa6a9d..10f48ca9e0439 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -175,6 +175,10 @@ int ReadConfiguration(int argc, char** argv) #endif #ifndef GPUCA_TPC_GEOMETRY_O2 configStandalone.rec.mergerReadFromTrackerDirectly = 0; + configStandalone.proc.ompKernels = false; + if (configStandalone.rundEdx == -1) { + configStandalone.rundEdx = 0; + } #endif #ifndef GPUCA_BUILD_QA if (configStandalone.proc.runQA || configStandalone.eventGenerator) { From 654261147538dd86cf6e1859f09844eb34547fb2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 17:44:36 +0200 Subject: [PATCH 0445/1751] Fix new codechecker errors from clang10 --- .../DataFormatsEMCAL/AnalysisCluster.h | 2 +- .../include/DataFormatsEMCAL/Constants.h | 2 +- .../include/DataFormatsEMCAL/EventHandler.h | 6 ++-- .../include/CPVSimulation/GeometryParams.h | 2 +- .../base/include/EMCALBase/ClusterFactory.h | 4 +-- .../base/include/EMCALBase/GeometryBase.h | 12 +++---- .../EMCAL/base/include/EMCALBase/Mapper.h | 2 +- .../EMCAL/calib/include/EMCALCalib/CalibDB.h | 4 +-- .../EMCALReconstruction/CaloRawFitterGamma2.h | 2 +- .../CaloRawFitterStandard.h | 2 +- .../ITSMFTReconstruction/RawPixelDecoder.h | 2 +- .../Clustering/src/ClusterFinderOriginal.cxx | 2 +- .../PHOS/calib/include/PHOSCalib/CalibDB.h | 4 +-- .../include/PHOSSimulation/GeometryParams.h | 2 +- .../TOFCalibration/LHCClockCalibrator.h | 2 +- .../TOFCalibration/TOFChannelCalibrator.h | 2 +- .../Upgrades/IT3/simulation/src/Detector.cxx | 33 ++++++++++++------- .../PostLS4/IT4/simulation/src/Detector.cxx | 33 ++++++++++++------- .../DataInterpreterITS.h | 2 +- .../DataInterpreterTPC.h | 2 +- .../DataInterpreterVSD.h | 2 +- .../EventVisualisationView/EventManager.h | 2 +- .../SliceTracker/GPUTPCSliceData.cxx | 4 +-- .../DigitizerWorkflow/src/CPVDigitizerSpec.h | 2 +- .../src/EMCALDigitizerSpec.h | 2 +- .../DigitizerWorkflow/src/PHOSDigitizerSpec.h | 2 +- .../include/DataFlow/EPNReceiverDevice.h | 2 +- .../include/DataFlow/FLPSenderDevice.h | 2 +- .../include/DataFlow/HeartbeatSampler.h | 2 +- .../include/DataFlow/SubframeBuilderDevice.h | 2 +- .../include/Publishers/DataPublisherDevice.h | 2 +- run/O2PrimaryServerDevice.h | 2 +- run/O2SimDevice.h | 2 +- 33 files changed, 86 insertions(+), 64 deletions(-) diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h index 5cc0936c4721a..376938a02cb61 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h @@ -39,7 +39,7 @@ class AnalysisCluster /// \class CellOutOfRangeException /// \brief Exception handling non-existing cell indices /// \ingroup EMCALbase - class CellOutOfRangeException : public std::exception + class CellOutOfRangeException final : public std::exception { public: /// \brief Constructor, setting cell wrong cell index raising the exception diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h index 9bae3c01c08d7..b538c3a34fd58 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Constants.h @@ -38,7 +38,7 @@ enum ChannelType_t { /// \class InvalidChanneltypeException /// \brief Error handling invalid channel types -class InvalidChanneltypeException : public std::exception +class InvalidChanneltypeException final : public std::exception { public: /// \brief Constructor initializing the exception diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/EventHandler.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/EventHandler.h index c2c55b1e3f764..f510f48915705 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/EventHandler.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/EventHandler.h @@ -88,7 +88,7 @@ class EventHandler /// \class RangeException /// \brief Exception handling errors due to exceeding the range of triggers handled by the handler - class RangeException : public std::exception + class RangeException final : public std::exception { public: /// \brief Constructor defining the error @@ -125,7 +125,7 @@ class EventHandler /// \class NotInitializedException /// \brief Exception handling unitialized event handler - class NotInitializedException : public std::exception + class NotInitializedException final : public std::exception { public: /// \brief Constructor initializing the exception @@ -141,7 +141,7 @@ class EventHandler /// \class InteractionRecordInvalidException /// \brief Error handling in case the interaction records from various sources do not match - class InteractionRecordInvalidException : public std::exception + class InteractionRecordInvalidException final : public std::exception { public: /// \brief Constructor initializing the exception diff --git a/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h b/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h index 4fef031b0bf8f..26ffdc379dcd4 100644 --- a/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h +++ b/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h @@ -21,7 +21,7 @@ namespace o2 { namespace cpv { -class GeometryParams : public TNamed +class GeometryParams final : public TNamed { public: /// Default constructor diff --git a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h index b114a10c4bcac..dbed03b9be585 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h +++ b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h @@ -38,7 +38,7 @@ class ClusterFactory { public: - class ClusterRangeException : public std::exception + class ClusterRangeException final : public std::exception { public: /// \brief Constructor defining the error @@ -73,7 +73,7 @@ class ClusterFactory std::string mErrorMessage; ///< Error message }; - class CellIndexRangeException : public std::exception + class CellIndexRangeException final : public std::exception { public: /// \brief Constructor defining the error diff --git a/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h b/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h index 3af58c7f8ab1c..4b760ef78792b 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h +++ b/Detectors/EMCAL/base/include/EMCALBase/GeometryBase.h @@ -35,7 +35,7 @@ const std::string DEFAULT_GEOMETRY = "EMCAL_COMPLETE12SMV1_DCAL_8SM"; /// \class InvalidModuleException /// \brief Error Handling when an invalid module ID (outside the limits) is called /// \ingroup EMCALbase -class InvalidModuleException : public std::exception +class InvalidModuleException final : public std::exception { public: /// \brief Constructor @@ -72,7 +72,7 @@ class InvalidModuleException : public std::exception /// \class InvalidPositionException /// \brief Exception handling errors due to positions not in the EMCAL area /// \ingroup EMCALbase -class InvalidPositionException : public std::exception +class InvalidPositionException final : public std::exception { public: /// \brief Constructor, setting the position raising the exception @@ -109,7 +109,7 @@ class InvalidPositionException : public std::exception /// \class InvalidCellIDException /// \brief Exception handling non-existing cell IDs /// \ingroup EMCALbase -class InvalidCellIDException : public std::exception +class InvalidCellIDException final : public std::exception { public: /// \brief Constructor, setting cell ID raising the exception @@ -139,7 +139,7 @@ class InvalidCellIDException : public std::exception /// \class InvalidSupermoduleTypeException /// \brief Exception handling improper or uninitialized supermodule types /// \ingroup EMCALbase -class InvalidSupermoduleTypeException : public std::exception +class InvalidSupermoduleTypeException final : public std::exception { public: /// \brief constructor @@ -155,7 +155,7 @@ class InvalidSupermoduleTypeException : public std::exception /// \class SupermoduleIndexException /// \brief Handling error due to invalid supermodule /// \ingroup EMCALbase -class SupermoduleIndexException : public std::exception +class SupermoduleIndexException final : public std::exception { public: /// \brief Constructor, initializing the exception @@ -192,7 +192,7 @@ class SupermoduleIndexException : public std::exception /// \class RowColException /// \brief Handling error for invalid positions in row-column space /// \ingroup EMCALBase -class RowColException : public std::exception +class RowColException final : public std::exception { public: /// \brief Constructor, initializing the exception with invalid row-column position diff --git a/Detectors/EMCAL/base/include/EMCALBase/Mapper.h b/Detectors/EMCAL/base/include/EMCALBase/Mapper.h index 6403f29206300..518803527b487 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Mapper.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Mapper.h @@ -306,7 +306,7 @@ class MappingHandler /// /// Error thrown in queries to the MappingHandler where the DDL ID is /// out-of-range for EMCAL. - class DDLInvalid : public std::exception + class DDLInvalid final : public std::exception { public: DDLInvalid(int ddlID) : mDDL(ddlID) { mMessage = fmt::format("DDL {0} not existing for EMCAL", mDDL); }; diff --git a/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h b/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h index 0cb355264cca5..d34a3052311a5 100644 --- a/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h +++ b/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h @@ -65,7 +65,7 @@ class CalibDB /// - Incorrect path /// - Wrong timestamp /// - Meta data not set - class ObjectNotFoundException : public std::exception + class ObjectNotFoundException final : public std::exception { public: /// \brief Constructor with query parameters @@ -123,7 +123,7 @@ class CalibDB /// a certain path and with a certain timestamp was valid, the object /// however has a different type than the expected one (something was /// screwed up when writing to the CCDB) - class TypeMismatchException : public std::exception + class TypeMismatchException final : public std::exception { public: /// \brief Constructor diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h index a0bc73dc2ce4c..84a797d617176 100755 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterGamma2.h @@ -37,7 +37,7 @@ namespace emcal /// Newton's method used for solving the set of non-linear equations. /// Ported from class AliCaloRawAnalyzerGamma2 from AliRoot -class CaloRawFitterGamma2 : public CaloRawFitter +class CaloRawFitterGamma2 final : public CaloRawFitter { public: diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h index 9d42b9547458e..54fe091322810 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CaloRawFitterStandard.h @@ -39,7 +39,7 @@ namespace emcal /// least square fit for the /// Moment assuming identical and /// independent errors (equivalent with chi square) -class CaloRawFitterStandard : public CaloRawFitter +class CaloRawFitterStandard final : public CaloRawFitter { public: diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 537f1337fee98..5208f564bfb46 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -40,7 +40,7 @@ namespace itsmft class ChipPixelData; template <class Mapping> -class RawPixelDecoder : public PixelReader +class RawPixelDecoder final : public PixelReader { using RDH = o2::header::RAWDataHeader; diff --git a/Detectors/MUON/MCH/Clustering/src/ClusterFinderOriginal.cxx b/Detectors/MUON/MCH/Clustering/src/ClusterFinderOriginal.cxx index 9efb874af05ea..065d50fb6e9d1 100644 --- a/Detectors/MUON/MCH/Clustering/src/ClusterFinderOriginal.cxx +++ b/Detectors/MUON/MCH/Clustering/src/ClusterFinderOriginal.cxx @@ -173,7 +173,7 @@ void ClusterFinderOriginal::resetPreCluster(gsl::span<const Digit>& digits) double y = mSegmentation->padPositionY(padID); double dx = mSegmentation->padSizeX(padID) / 2.; double dy = mSegmentation->padSizeY(padID) / 2.; - double charge = static_cast<double>(digit.getADC()) / std::numeric_limits<unsigned long>::max() * 1024; + double charge = static_cast<double>(digit.getADC()) / static_cast<double>(std::numeric_limits<unsigned long>::max()) * 1024; bool isSaturated = digit.getTime().time > 0; int plane = mSegmentation->isBendingPad(padID) ? 0 : 1; diff --git a/Detectors/PHOS/calib/include/PHOSCalib/CalibDB.h b/Detectors/PHOS/calib/include/PHOSCalib/CalibDB.h index 3e100b018e7ec..cd1c2e5c6e834 100644 --- a/Detectors/PHOS/calib/include/PHOSCalib/CalibDB.h +++ b/Detectors/PHOS/calib/include/PHOSCalib/CalibDB.h @@ -58,7 +58,7 @@ class CalibDB /// - Incorrect path /// - Wrong timestamp /// - Meta data not set - class ObjectNotFoundException : public std::exception + class ObjectNotFoundException final : public std::exception { public: /// \brief Constructor with query parameters @@ -116,7 +116,7 @@ class CalibDB /// a certain path and with a certain timestamp was valid, the object /// however has a different type than the expected one (something was /// screwed up when writing to the CCDB) - class TypeMismatchException : public std::exception + class TypeMismatchException final : public std::exception { public: /// \brief Constructor diff --git a/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h b/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h index 50e6af8893924..4ad5347afbe77 100644 --- a/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h +++ b/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h @@ -21,7 +21,7 @@ namespace o2 { namespace phos { -class GeometryParams : public TNamed +class GeometryParams final : public TNamed { public: /// Default constructor diff --git a/Detectors/TOF/calibration/include/TOFCalibration/LHCClockCalibrator.h b/Detectors/TOF/calibration/include/TOFCalibration/LHCClockCalibrator.h index 08007e27fc95d..09ef16b5dc1b9 100644 --- a/Detectors/TOF/calibration/include/TOFCalibration/LHCClockCalibrator.h +++ b/Detectors/TOF/calibration/include/TOFCalibration/LHCClockCalibrator.h @@ -51,7 +51,7 @@ struct LHCClockDataHisto { ClassDefNV(LHCClockDataHisto, 1); }; -class LHCClockCalibrator : public o2::calibration::TimeSlotCalibration<o2::dataformats::CalibInfoTOF, o2::tof::LHCClockDataHisto> +class LHCClockCalibrator final : public o2::calibration::TimeSlotCalibration<o2::dataformats::CalibInfoTOF, o2::tof::LHCClockDataHisto> { using TFType = uint64_t; using Slot = o2::calibration::TimeSlot<o2::tof::LHCClockDataHisto>; diff --git a/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h b/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h index 7fcea42e3e964..f2e7cc3d5412b 100644 --- a/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h +++ b/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h @@ -95,7 +95,7 @@ class TOFChannelData ClassDefNV(TOFChannelData, 1); }; -class TOFChannelCalibrator : public o2::calibration::TimeSlotCalibration<o2::dataformats::CalibInfoTOF, o2::tof::TOFChannelData> +class TOFChannelCalibrator final : public o2::calibration::TimeSlotCalibration<o2::dataformats::CalibInfoTOF, o2::tof::TOFChannelData> { using TFType = uint64_t; using Slot = o2::calibration::TimeSlot<o2::tof::TOFChannelData>; diff --git a/Detectors/Upgrades/IT3/simulation/src/Detector.cxx b/Detectors/Upgrades/IT3/simulation/src/Detector.cxx index 40b262c1b17fb..a564dcb442087 100644 --- a/Detectors/Upgrades/IT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/IT3/simulation/src/Detector.cxx @@ -1205,12 +1205,14 @@ void Detector::addAlignableVolumes() const LOG(DEBUG) << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } Int_t lastUID = 0; - for (Int_t lr = 0; lr < mTotalNumberOfLayers; lr++) + for (Int_t lr = 0; lr < mTotalNumberOfLayers; lr++) { addAlignableVolumesLayer(lr, path, lastUID); + } return; } @@ -1235,13 +1237,15 @@ void Detector::addAlignableVolumesLayer(int lr, TString& parent, Int_t& lastUID) LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } const V3Layer* lrobj = mGeometry[lr]; Int_t nstaves = lrobj->getNumberOfStavesPerParent(); - for (int st = 0; st < nstaves; st++) + for (int st = 0; st < nstaves; st++) { addAlignableVolumesStave(lr, st, path, lastUID); + } return; } @@ -1258,14 +1262,16 @@ void Detector::addAlignableVolumesStave(Int_t lr, Int_t st, TString& parent, Int LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } const V3Layer* lrobj = mGeometry[lr]; Int_t nhstave = lrobj->getNumberOfHalfStavesPerParent(); Int_t start = nhstave > 0 ? 0 : -1; - for (Int_t sst = start; sst < nhstave; sst++) + for (Int_t sst = start; sst < nhstave; sst++) { addAlignableVolumesHalfStave(lr, st, sst, path, lastUID); + } return; } @@ -1285,15 +1291,17 @@ void Detector::addAlignableVolumesHalfStave(Int_t lr, Int_t st, Int_t hst, TStri LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } } const V3Layer* lrobj = mGeometry[lr]; Int_t nmodules = lrobj->getNumberOfModulesPerParent(); Int_t start = nmodules > 0 ? 0 : -1; - for (Int_t md = start; md < nmodules; md++) + for (Int_t md = start; md < nmodules; md++) { addAlignableVolumesModule(lr, st, hst, md, path, lastUID); + } return; } @@ -1313,14 +1321,16 @@ void Detector::addAlignableVolumesModule(Int_t lr, Int_t st, Int_t hst, Int_t md LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } } const V3Layer* lrobj = mGeometry[lr]; Int_t nchips = lrobj->getNumberOfChipsPerParent(); - for (Int_t ic = 0; ic < nchips; ic++) + for (Int_t ic = 0; ic < nchips; ic++) { addAlignableVolumesChip(lr, st, hst, md, ic, path, lastUID); + } return; } @@ -1340,8 +1350,9 @@ void Detector::addAlignableVolumesChip(Int_t lr, Int_t st, Int_t hst, Int_t md, LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname, path.Data(), modUID)) + if (!gGeoManager->SetAlignableEntry(sname, path.Data(), modUID)) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } return; } diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx index f740ba40eab1c..68ae078f94f37 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx @@ -1107,12 +1107,14 @@ void Detector::addAlignableVolumes() const LOG(DEBUG) << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } Int_t lastUID = 0; - for (Int_t lr = 0; lr < mTotalNumberOfLayers; lr++) + for (Int_t lr = 0; lr < mTotalNumberOfLayers; lr++) { addAlignableVolumesLayer(lr, path, lastUID); + } return; } @@ -1137,13 +1139,15 @@ void Detector::addAlignableVolumesLayer(int lr, TString& parent, Int_t& lastUID) LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } const V3Layer* lrobj = mGeometry[lr]; Int_t nstaves = lrobj->getNumberOfStavesPerParent(); - for (int st = 0; st < nstaves; st++) + for (int st = 0; st < nstaves; st++) { addAlignableVolumesStave(lr, st, path, lastUID); + } return; } @@ -1160,14 +1164,16 @@ void Detector::addAlignableVolumesStave(Int_t lr, Int_t st, TString& parent, Int LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } const V3Layer* lrobj = mGeometry[lr]; Int_t nhstave = lrobj->getNumberOfHalfStavesPerParent(); Int_t start = nhstave > 0 ? 0 : -1; - for (Int_t sst = start; sst < nhstave; sst++) + for (Int_t sst = start; sst < nhstave; sst++) { addAlignableVolumesHalfStave(lr, st, sst, path, lastUID); + } return; } @@ -1187,15 +1193,17 @@ void Detector::addAlignableVolumesHalfStave(Int_t lr, Int_t st, Int_t hst, TStri LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } } const V3Layer* lrobj = mGeometry[lr]; Int_t nmodules = lrobj->getNumberOfModulesPerParent(); Int_t start = nmodules > 0 ? 0 : -1; - for (Int_t md = start; md < nmodules; md++) + for (Int_t md = start; md < nmodules; md++) { addAlignableVolumesModule(lr, st, hst, md, path, lastUID); + } return; } @@ -1215,14 +1223,16 @@ void Detector::addAlignableVolumesModule(Int_t lr, Int_t st, Int_t hst, Int_t md LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) + if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } } const V3Layer* lrobj = mGeometry[lr]; Int_t nchips = lrobj->getNumberOfChipsPerParent(); - for (Int_t ic = 0; ic < nchips; ic++) + for (Int_t ic = 0; ic < nchips; ic++) { addAlignableVolumesChip(lr, st, hst, md, ic, path, lastUID); + } return; } @@ -1242,8 +1252,9 @@ void Detector::addAlignableVolumesChip(Int_t lr, Int_t st, Int_t hst, Int_t md, LOG(DEBUG) << "Add " << sname << " <-> " << path; - if (!gGeoManager->SetAlignableEntry(sname, path.Data(), modUID)) + if (!gGeoManager->SetAlignableEntry(sname, path.Data(), modUID)) { LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } return; } diff --git a/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterITS.h b/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterITS.h index bd06d6f97e497..20755fd52a93e 100644 --- a/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterITS.h +++ b/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterITS.h @@ -28,7 +28,7 @@ namespace o2 namespace event_visualisation { -class DataInterpreterITS : public DataInterpreter +class DataInterpreterITS final : public DataInterpreter { public: // Default constructor diff --git a/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterTPC.h b/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterTPC.h index f159653fbc9d9..c0572e468c861 100644 --- a/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterTPC.h +++ b/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterTPC.h @@ -29,7 +29,7 @@ namespace o2 namespace event_visualisation { -class DataInterpreterTPC : public DataInterpreter +class DataInterpreterTPC final : public DataInterpreter { public: // Default constructor diff --git a/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterVSD.h b/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterVSD.h index 701984979934f..6f7a18614a5c5 100644 --- a/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterVSD.h +++ b/EventVisualisation/Detectors/include/EventVisualisationDetectors/DataInterpreterVSD.h @@ -33,7 +33,7 @@ namespace o2 namespace event_visualisation { -class DataInterpreterVSD : public DataInterpreter +class DataInterpreterVSD final : public DataInterpreter { private: void LoadClusters(TEvePointSet*& ps, const TString& det_name, Int_t det_id); diff --git a/EventVisualisation/View/include/EventVisualisationView/EventManager.h b/EventVisualisation/View/include/EventVisualisationView/EventManager.h index 313576de03d37..b76b8d178e260 100644 --- a/EventVisualisation/View/include/EventVisualisationView/EventManager.h +++ b/EventVisualisation/View/include/EventVisualisationView/EventManager.h @@ -43,7 +43,7 @@ namespace event_visualisation class DataSource; -class EventManager : public TEveEventManager, public TQObject +class EventManager final : public TEveEventManager, public TQObject { public: enum EDataSource { diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx index 7e2a54fabf624..474ed31c54f76 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx @@ -215,7 +215,7 @@ GPUdii() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int const unsigned int NumberOfClusters = EarlyTransformWithoutClusterNative ? NumberOfClustersInRow[rowIndex] : mem->ioPtrs.clustersNative->nClusters[iSlice][rowIndex]; const unsigned int RowOffset = EarlyTransformWithoutClusterNative ? RowOffsets[rowIndex] : (mem->ioPtrs.clustersNative->clusterOffset[iSlice][rowIndex] - mem->ioPtrs.clustersNative->clusterOffset[iSlice][0]); - CONSTEXPR unsigned int maxN = sizeof(calink) < 3 ? (1 << (sizeof(calink) * 8)) : (1 << 24); + CONSTEXPR unsigned int maxN = 1u << (sizeof(calink) < 3 ? (sizeof(calink) * 8) : 24); if (NumberOfClusters >= maxN) { if (iThread == 0) { mem->errorCodes.raiseError(GPUErrors::ERROR_SLICEDATA_HITINROW_OVERFLOW, rowIndex, NumberOfClusters, maxN); @@ -310,7 +310,7 @@ GPUdii() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int GPUbarrier(); const GPUTPCGrid& grid = row.mGrid; const int numberOfBins = grid.N(); - CONSTEXPR int maxBins = sizeof(calink) < 4 ? (1 << (sizeof(calink) * 8)) : 0x7FFFFFFF; + CONSTEXPR int maxBins = sizeof(calink) < 4 ? (1 << (sizeof(calink) * 8)) : 0x7FFFFFFF; // NOLINT: false warning if (sizeof(calink) < 4 && numberOfBins >= maxBins) { if (iThread == 0) { mem->errorCodes.raiseError(GPUErrors::ERROR_SLICEDATA_BIN_OVERFLOW, rowIndex, numberOfBins, maxBins); diff --git a/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.h b/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.h index ef1bc66fa7709..909fea0f6a316 100644 --- a/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.h +++ b/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.h @@ -30,7 +30,7 @@ namespace cpv /// \author Dmitri Peresunko, NRC "Kurchatov institute" /// \author Adopted from PHOS code /// \since Jan, 2020 -class DigitizerSpec : public o2::base::BaseDPLDigitizer +class DigitizerSpec final : public o2::base::BaseDPLDigitizer { public: /// \brief Constructor diff --git a/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.h b/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.h index 52e9ad30a72f2..6820ae102ae34 100644 --- a/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.h +++ b/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.h @@ -35,7 +35,7 @@ namespace emcal /// \author Anders Garritt Knospe <anders.knospe@cern.ch>, University of Houston /// \author Markus Fasel <markus.fasel@cern.ch> Oak Ridge National laboratory /// \since Nov 12, 2018 -class DigitizerSpec : public o2::base::BaseDPLDigitizer +class DigitizerSpec final : public o2::base::BaseDPLDigitizer { public: /// \brief Constructor diff --git a/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.h b/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.h index 7b655b0b01482..b4af953807142 100644 --- a/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.h +++ b/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.h @@ -31,7 +31,7 @@ namespace phos /// \author Dmitri Peresunko, NRC "Kurchatov institute" /// \author Adopted from EMCAL code write by Markus Fasel /// \since Dec, 2019 -class DigitizerSpec : public o2::base::BaseDPLDigitizer +class DigitizerSpec final : public o2::base::BaseDPLDigitizer { public: /// \brief Constructor diff --git a/Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h b/Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h index 3e3127283b852..f13fc8cd88585 100644 --- a/Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h +++ b/Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h @@ -33,7 +33,7 @@ struct TFBuffer { /// Receives sub-timeframes from the flpSenders and merges these into full timeframes. -class EPNReceiverDevice : public FairMQDevice +class EPNReceiverDevice final : public FairMQDevice { public: EPNReceiverDevice() = default; diff --git a/Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h b/Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h index 3492c0f5853d5..08cda323677b9 100644 --- a/Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h +++ b/Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h @@ -29,7 +29,7 @@ namespace devices /// and are sent to epnReceivers. Target epnReceiver is determined from the timeframe ID: /// targetEpnReceiver = timeframeId % numEPNs (numEPNs is same for every flpSender, although some may be inactive). -class FLPSenderDevice : public FairMQDevice +class FLPSenderDevice final : public FairMQDevice { public: /// Default constructor diff --git a/Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h b/Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h index d979cc2961aa5..a6bf6dce79ff6 100644 --- a/Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h +++ b/Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h @@ -38,7 +38,7 @@ namespace data_flow /// /// TODO: the class can evolve to a general clock sampler device with /// configurable period, even randomly distributed -class HeartbeatSampler : public base::O2Device +class HeartbeatSampler final : public base::O2Device { public: typedef o2::base::O2Message O2Message; diff --git a/Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h b/Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h index f4f6d2dc261d7..0eda40bf51d0f 100644 --- a/Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h +++ b/Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h @@ -53,7 +53,7 @@ namespace data_flow /// The duration should be with respect to a time constant, which in /// itself needs to be configurable, now the time constant is /// hard-coded microseconds -class SubframeBuilderDevice : public base::O2Device +class SubframeBuilderDevice final : public base::O2Device { public: using O2Message = o2::base::O2Message; diff --git a/Utilities/Publishers/include/Publishers/DataPublisherDevice.h b/Utilities/Publishers/include/Publishers/DataPublisherDevice.h index f48a722407146..342acbf3dbbc6 100644 --- a/Utilities/Publishers/include/Publishers/DataPublisherDevice.h +++ b/Utilities/Publishers/include/Publishers/DataPublisherDevice.h @@ -35,7 +35,7 @@ namespace utilities /// Utility device for data publishing /// /// TODO: Generalize with an input policy -class DataPublisherDevice : public base::O2Device +class DataPublisherDevice final : public base::O2Device { public: typedef o2::base::O2Message O2Message; diff --git a/run/O2PrimaryServerDevice.h b/run/O2PrimaryServerDevice.h index 7e1c34326e1c4..9af897b5131a8 100644 --- a/run/O2PrimaryServerDevice.h +++ b/run/O2PrimaryServerDevice.h @@ -37,7 +37,7 @@ namespace o2 namespace devices { -class O2PrimaryServerDevice : public FairMQDevice +class O2PrimaryServerDevice final : public FairMQDevice { public: /// Default constructor diff --git a/run/O2SimDevice.h b/run/O2SimDevice.h index c0736bbe6229b..90f8dad60eea3 100644 --- a/run/O2SimDevice.h +++ b/run/O2SimDevice.h @@ -39,7 +39,7 @@ class TMessageWrapper : public TMessage }; // device representing a simulation worker -class O2SimDevice : public FairMQDevice +class O2SimDevice final : public FairMQDevice { public: O2SimDevice() = default; From 778d205b05f683af82722f50509c396ec58c7248 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 17:09:34 +0200 Subject: [PATCH 0446/1751] GPU: Use TPC ca-clusterer and on-the-fly zero-suppression as default --- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 27 ++++++++++++------- .../TPC/workflow/src/tpc-reco-workflow.cxx | 4 +-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 901590b220d82..c8b05b5aacb7b 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -88,7 +88,6 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec int caClusterer, int zsOnTheFly, int zs10bit, float zsThreshold) { InputType inputType; - try { inputType = InputMap.at(cfgInput); } catch (std::out_of_range&) { @@ -104,6 +103,22 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec return std::find(outputTypes.begin(), outputTypes.end(), type) != outputTypes.end(); }; + bool decompressTPC = inputType == InputType::CompClustersCTF || inputType == InputType::CompClusters; + // Disable not applicable settings depending on TPC input, no need to disable manually + if (decompressTPC && (isEnabled(OutputType::Clusters) || isEnabled(OutputType::Tracks))) { + caClusterer = false; + zsOnTheFly = false; + propagateMC = false; + } + if (inputType == InputType::ZSRaw) { + caClusterer = true; + zsOnTheFly = false; + propagateMC = false; + } + if (!caClusterer) { + zsOnTheFly = false; + } + if (inputType == InputType::ClustersHardware && isEnabled(OutputType::Digits)) { throw std::invalid_argument("input/output type mismatch, can not produce 'digits' from 'clustershardware'"); } @@ -113,10 +128,6 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec if (inputType == InputType::ZSRaw && isEnabled(OutputType::ClustersHardware)) { throw std::invalid_argument("input/output type mismatch, can not produce 'clustershardware' from 'zsraw'"); } - - if (inputType == InputType::ZSRaw && !caClusterer) { - throw std::invalid_argument("zsraw input needs caclusterer"); - } if (caClusterer && (inputType == InputType::Clusters || inputType == InputType::ClustersHardware)) { throw std::invalid_argument("ca-clusterer requires digits as input"); } @@ -209,16 +220,12 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec bool runClusterer = !caClusterer && (runHWDecoder || isEnabled(OutputType::ClustersHardware)); bool zsDecoder = inputType == InputType::ZSRaw; bool runClusterEncoder = isEnabled(OutputType::EncodedClusters); - bool decompressTPC = inputType == InputType::CompClustersCTF || inputType == InputType::CompClusters; + // input matrix runClusterer &= inputType == InputType::Digitizer || inputType == InputType::Digits; runHWDecoder &= runClusterer || inputType == InputType::ClustersHardware; runTracker &= caClusterer || runHWDecoder || inputType == InputType::Clusters || decompressTPC; - if (decompressTPC && (isEnabled(OutputType::Clusters) || isEnabled(OutputType::Tracks)) && (caClusterer || zsOnTheFly || propagateMC)) { - throw std::invalid_argument("Compressed clusters as input are incompatible to ca-clusterer, zs-on-the-fly, propagate-mc"); - } - bool outRaw = inputType == InputType::Digits && isEnabled(OutputType::ZSRaw); //bool runZSDecode = inputType == InputType::ZSRaw; bool zsToDigit = inputType == InputType::ZSRaw && isEnabled(OutputType::Digits); diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index fb8ce7de652fd..7fd422e354095 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -44,12 +44,12 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) std::vector<ConfigParamSpec> options{ {"input-type", VariantType::String, "digits", {"digitizer, digits, zsraw, clustershw, clustersnative, compressed-clusters, compressed-clusters-ctf"}}, {"output-type", VariantType::String, "tracks", {"digits, zsraw, clustershw, clustersnative, tracks, compressed-clusters, encoded-clusters, disable-writer"}}, - {"ca-clusterer", VariantType::Bool, false, {"Use clusterer of GPUCATracking"}}, + {"ca-clusterer", VariantType::Bool, true, {"Use clusterer of GPUCATracking"}}, {"disable-mc", VariantType::Bool, false, {"disable sending of MC information"}}, {"tpc-sectors", VariantType::String, "0-35", {"TPC sector range, e.g. 5-7,8,9"}}, {"tpc-lanes", VariantType::Int, 1, {"number of parallel lanes up to the tracker"}}, {"dispatching-mode", VariantType::String, "prompt", {"determines when to dispatch: prompt, complete"}}, - {"tpc-zs-on-the-fly", VariantType::Bool, false, {"use TPC zero suppression on the fly, true/false"}}, + {"tpc-zs-on-the-fly", VariantType::Bool, true, {"use TPC zero suppression on the fly, true/false"}}, {"zs-threshold", VariantType::Float, 2.0f, {"zero suppression threshold"}}, {"zs-10bit", VariantType::Bool, false, {"use 10 bit ADCs for TPC zero suppression, true/false, default/false = 12 bit ADC"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings (e.g.: 'TPCHwClusterer.peakChargeThreshold=4;...')"}}, From 86d6b3df81299ed6c8ed896139995e51afd58dfd Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 20:19:09 +0200 Subject: [PATCH 0447/1751] GPU: Reduce memory for TPC clusterer MC label attachment --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 810aff99267d7..261377d381474 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1084,19 +1084,14 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) auto* digitsMC = propagateMCLabels ? processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC : nullptr; - GPUTPCLinearLabels mcLinearLabels; - if (propagateMCLabels) { - mcLinearLabels.header.reserve(mRec->MemoryScalers()->nTPCHits); - mcLinearLabels.data.reserve(mRec->MemoryScalers()->nTPCHits * 16); // Assumption: cluster will have less than 16 labels on average - } - if (param().continuousMaxTimeBin > 0 && mCFContext->tpcMaxTimeBin >= (unsigned int)std::max(param().continuousMaxTimeBin + 1, TPC_MAX_FRAGMENT_LEN)) { GPUError("Input data has invalid time bin\n"); return 1; } bool buildNativeGPU = (mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCConversion) || (mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || (mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCMerging) || (mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCCompression); bool buildNativeHost = mRec->GetRecoStepsOutputs() & GPUDataTypes::InOutType::TPCClusters; // TODO: Should do this also when clusters are needed for later steps on the host but not requested as output - mInputsHost->mNClusterNative = mInputsShadow->mNClusterNative = mRec->MemoryScalers()->NTPCClusters(mRec->MemoryScalers()->nTPCdigits); + mRec->MemoryScalers()->nTPCHits = mRec->MemoryScalers()->NTPCClusters(mRec->MemoryScalers()->nTPCdigits); + mInputsHost->mNClusterNative = mInputsShadow->mNClusterNative = mRec->MemoryScalers()->nTPCHits; if (buildNativeGPU) { AllocateRegisteredMemory(mInputsHost->mResourceClusterNativeBuffer); } @@ -1104,6 +1099,13 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) AllocateRegisteredMemory(mInputsHost->mResourceClusterNativeOutput, mOutputClustersNative); } + GPUTPCLinearLabels mcLinearLabels; + if (propagateMCLabels) { + // No need to overallocate here, nTPCHits is anyway an upper bound used for the GPU cluster buffer, and we can always enlarge the buffer anyway + mcLinearLabels.header.reserve(mRec->MemoryScalers()->nTPCHits / 2); + mcLinearLabels.data.reserve(mRec->MemoryScalers()->nTPCHits); + } + char transferRunning[NSLICES] = {0}; unsigned int outputQueueStart = mOutputQueue.size(); @@ -1305,6 +1307,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::flatten>(GetGrid(clusterer.mPclusterInRow[j], lane), {iSlice}, {}, j, &mcLinearLabels); } + clusterer.clearMCMemory(); } if (buildNativeHost && buildNativeGPU && anyLaneHasData) { if (GetProcessingSettings().delayedOutput) { From e0372b0ebd46947b8d76007a79af6a24834b6e43 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 22:53:56 +0200 Subject: [PATCH 0448/1751] TPC: Don't create a zs-filtered copy of digits when we have tpc-zs raw data anyway --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 0d339e6e0f6a9..80f0914a67faa 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -99,7 +99,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* const int maxContTimeBin = mTrackingCAO2Interface->getConfig().configEvent.continuousMaxTimeBin; for (int i = 0; i < Sector::MAXSECTOR; i++) { const auto& d = (*(data->o2Digits))[i]; - if (zsThreshold > 0) { + if (zsThreshold > 0 && data->tpcZS == nullptr) { gpuDigits[i].reserve(d.size()); } for (int j = 0; j < d.size(); j++) { @@ -117,7 +117,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* } } } - if (zsThreshold > 0) { + if (zsThreshold > 0 && data->tpcZS == nullptr) { gpuDigitsMap.tpcDigits[i] = gpuDigits[i].data(); gpuDigitsMap.nTPCDigits[i] = gpuDigits[i].size(); if (data->o2DigitsMC) { From 2195ca58843fe5da18f26e05b0cdc6103baf4e69 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 23:00:22 +0200 Subject: [PATCH 0449/1751] TPC: Initialize GPU for on-the-fly tpc-zs encoding properly to get threshold from configKeyValues --- Detectors/TPC/workflow/src/ZSSpec.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/workflow/src/ZSSpec.cxx b/Detectors/TPC/workflow/src/ZSSpec.cxx index f2caffca49296..c0bf8db513211 100644 --- a/Detectors/TPC/workflow/src/ZSSpec.cxx +++ b/Detectors/TPC/workflow/src/ZSSpec.cxx @@ -97,8 +97,10 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi GPUTrackingInOutDigits inDigitsGPU; GPUParam _GPUParam; - _GPUParam.SetDefaults(5.00668); - const GPUParam mGPUParam = _GPUParam; + GPUO2InterfaceConfiguration config; + config.configEvent.solenoidBz = 5.00668; + config.ReadConfigurableParam(); + _GPUParam.SetDefaults(&config.configEvent, &config.configReconstruction, &config.configProcessing, nullptr); int operation = 0; std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe}}; @@ -128,7 +130,7 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi sizes.resize(NSectors * NEndpoints); bool zs12bit = !zs10bit; o2::InteractionRecord ir = o2::raw::HBFUtils::Instance().getFirstIR(); - zsEncoder->RunZSEncoder<o2::tpc::Digit, DigitArray>(inputDigits, &zsoutput, sizes.data(), nullptr, &ir, mGPUParam, zs12bit, verify, threshold); + zsEncoder->RunZSEncoder<o2::tpc::Digit, DigitArray>(inputDigits, &zsoutput, sizes.data(), nullptr, &ir, _GPUParam, zs12bit, verify, threshold); ZeroSuppressedContainer8kb* page = reinterpret_cast<ZeroSuppressedContainer8kb*>(zsoutput.get()); unsigned int offset = 0; for (unsigned int i = 0; i < NSectors; i++) { @@ -179,7 +181,7 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi if (useGrouping != LinksGrouping::Link) { writer.useCaching(); } - zsEncoder->RunZSEncoder<o2::tpc::Digit>(inputDigits, nullptr, nullptr, &writer, &ir, mGPUParam, zs12bit, false, threshold); + zsEncoder->RunZSEncoder<o2::tpc::Digit>(inputDigits, nullptr, nullptr, &writer, &ir, _GPUParam, zs12bit, false, threshold); writer.writeConfFile("TPC", "RAWDATA", fmt::format("{}tpcraw.cfg", outDir)); } zsoutput.reset(nullptr); From dd545b0948d5a3f66cac7b4643f3a7ccc49ccc3c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 26 Aug 2020 10:08:28 +0200 Subject: [PATCH 0450/1751] DPL: used fixed notation for resource monitoring (#4204) * Notice std::to_string truncates at 6 digits * Cleanup style --- .../Core/src/ResourcesMonitoringHelper.h | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/Framework/Core/src/ResourcesMonitoringHelper.h b/Framework/Core/src/ResourcesMonitoringHelper.h index b0fae70b5318e..c231be960a00f 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.h +++ b/Framework/Core/src/ResourcesMonitoringHelper.h @@ -8,18 +8,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef __RESOURCES_MONITORING_MANAGER__H__ -#define __RESOURCES_MONITORING_MANAGER__H__ +#ifndef O2_FRAMEWORK_RESOURCESMONITORINGHELPER_H_ +#define O2_FRAMEWORK_RESOURCESMONITORINGHELPER_H_ -#include <vector> #include "Framework/DeviceMetricsInfo.h" #include "Monitoring/ProcessMonitor.h" #include <boost/property_tree/ptree.hpp> #include "Framework/DeviceSpec.h" -namespace o2 -{ -namespace framework +#include <vector> +#include <type_traits> + +namespace o2::framework { class ResourcesMonitoringHelper @@ -57,13 +57,16 @@ boost::property_tree::ptree ResourcesMonitoringHelper::fillNodeWithValue(const D for (unsigned int idx = 0; idx < loopRange; ++idx) { boost::property_tree::ptree values; values.add("timestamp", deviceMetrics.timestamps[labelIndex][idx]); - values.add("value", retriveValue(std::cref(metricsStorage[storageIndex][idx]))); + if constexpr (std::is_arithmetic_v<T>) { + values.add("value", std::to_string(retriveValue(std::cref(metricsStorage[storageIndex][idx])))); + } else { + values.add("value", retriveValue(std::cref(metricsStorage[storageIndex][idx]))); + } metricNode.push_back(std::make_pair("", values)); } return metricNode; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif +#endif // O2_FRAMEWORK_RESOURCESMONITORINGHELPER_H_ From 3de3b1b89a7e46016b605c8a30a1d65a86df5298 Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez.sebastian@gmail.com> Date: Wed, 26 Aug 2020 11:27:17 +0200 Subject: [PATCH 0451/1751] Two-particle transverse momentum correlations task first commit (#4191) --- Analysis/Tasks/CMakeLists.txt | 1 + Analysis/Tasks/PWGCF/CMakeLists.txt | 15 + Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 407 ++++++++++++++++++++ 3 files changed, 423 insertions(+) create mode 100644 Analysis/Tasks/PWGCF/CMakeLists.txt create mode 100644 Analysis/Tasks/PWGCF/dptdptcorrelations.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 210872b581253..4a5cd1e2403d5 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -8,6 +8,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +add_subdirectory(PWGCF) add_subdirectory(PWGDQ) o2_add_dpl_workflow(trackselection diff --git a/Analysis/Tasks/PWGCF/CMakeLists.txt b/Analysis/Tasks/PWGCF/CMakeLists.txt new file mode 100644 index 0000000000000..27f3ec9a4c86a --- /dev/null +++ b/Analysis/Tasks/PWGCF/CMakeLists.txt @@ -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. + +o2_add_dpl_workflow(dptdptcorrelations + SOURCES dptdptcorrelations.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME Analysis) + diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx new file mode 100644 index 0000000000000..1815182edaaba --- /dev/null +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -0,0 +1,407 @@ +// 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/EventSelection.h" +#include "Analysis/Centrality.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include <TROOT.h> +#include <TList.h> +#include <TDirectory.h> +#include <TH1.h> +#include <TH2.h> +#include <TH3.h> +#include <TProfile3D.h> + +#include <cmath> + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; + +namespace o2 +{ +namespace aod +{ +using CollisionEvSelCent = soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator; +using TrackData = soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection>::iterator; + +/* we have to change from int to bool when bool columns work properly */ +namespace dptdptcorrelations +{ +DECLARE_SOA_COLUMN(EventAccepted, eventaccepted, uint8_t); +DECLARE_SOA_COLUMN(TrackacceptedAsOne, trackacceptedasone, uint8_t); +DECLARE_SOA_COLUMN(TrackacceptedAsTwo, trackacceptedastwo, uint8_t); +} // namespace dptdptcorrelations +DECLARE_SOA_TABLE(AcceptedEvents, "AOD", "ACCEPTEDEVENTS", dptdptcorrelations::EventAccepted); +DECLARE_SOA_TABLE(ScannedTracks, "AOD", "SCANNEDTRACKS", dptdptcorrelations::TrackacceptedAsOne, dptdptcorrelations::TrackacceptedAsTwo); +} // namespace aod +} // namespace o2 + +namespace dptdptcorrelations +{ +/* all this bins have to be make configurable */ +int ptbins = 18; +float ptlow = 0.2, ptup = 2.0; +int etabins = 16; +float etalow = -0.8, etaup = 0.8; +int zvtxbins = 40; +float zvtxlow = -10.0, zvtxup = 10.0; +int phibins = 72; +std::string fTaskConfigurationString = "PendingToConfigure"; + +Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; +Configurable<int> cfgTrackOneCharge("trk1charge", 1, "Trakc one charge: 1 = positive, -1 = negative"); +Configurable<int> cfgTrackTwoCharge("trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"); +Configurable<bool> cfgProcessPairs("processpairs", true, "Process pairs: false = no, just singles, true = yes, process pairs"); + +/* while we don't have proper bool columnst */ +uint8_t DPTDPT_TRUE = 1; +uint8_t DPTDPT_FALSE = 0; + +/// \enum SystemType +/// \brief The type of the system under analysis +enum SystemType { + kNoSystem = 0, ///< no system defined + kpp, ///< **p-p** system + kpPb, ///< **p-Pb** system + kPbp, ///< **Pb-p** system + kPbPb, ///< **Pb-Pb** system + kXeXe, ///< **Xe-Xe** system + knSystems ///< number of handled systems +}; + +/* probably this will not work in the context of distributed processes */ +/* we need to revisit it!!!! */ +SystemType fSystem = kNoSystem; +TH1F* fhCentMultB = nullptr; +TH1F* fhCentMultA = nullptr; +TH1F* fhVertexZB = nullptr; +TH1F* fhVertexZA = nullptr; +TH1F* fhPtB = nullptr; +TH1F* fhPtA = nullptr; +TH1F* fhPtPosB = nullptr; +TH1F* fhPtPosA = nullptr; +TH1F* fhPtNegB = nullptr; +TH1F* fhPtNegA = nullptr; + +TH1F* fhEtaB = nullptr; +TH1F* fhEtaA = nullptr; + +TH1F* fhPhiB = nullptr; +TH1F* fhPhiA = nullptr; + +TH2F* fhEtaVsPhiB = nullptr; +TH2F* fhEtaVsPhiA = nullptr; + +TH2F* fhPtVsEtaB = nullptr; +TH2F* fhPtVsEtaA = nullptr; + +SystemType getSystemType() +{ + /* we have to figure out how extract the system type */ + return kPbPb; +} + +bool IsEvtSelected(aod::CollisionEvSelCent const& collision) +{ + if (collision.alias()[kINT7]) { + if (collision.sel7()) { + if (zvtxlow < collision.posZ() and collision.posZ() < zvtxup) { + return true; + } + return false; + } + } + return false; +} + +bool matchTrackType(aod::TrackData const& track) +{ + switch (cfgTrackType) { + case 1: + if (track.isGlobalTrack() != 0) + return true; + else + return false; + break; + case 2: + if (track.isGlobalTrackSDD() != 0) + return true; + else + return false; + break; + default: + return false; + } +} + +std::tuple<uint8_t, uint8_t> AcceptTrack(aod::TrackData const& track) +{ + + uint8_t asone = DPTDPT_FALSE; + uint8_t astwo = DPTDPT_FALSE; + + /* TODO: incorporate a mask in the scanned tracks table for the rejecting track reason */ + if (matchTrackType(track)) { + if (ptlow < track.pt() and track.pt() < ptup and etalow < track.eta() and track.eta() < etaup) { + if (((track.charge() > 0) and (cfgTrackOneCharge > 0)) or ((track.charge() < 0) and (cfgTrackOneCharge < 0))) { + asone = DPTDPT_TRUE; + } else if (((track.charge() > 0) and (cfgTrackTwoCharge > 0)) or ((track.charge() < 0) and (cfgTrackTwoCharge < 0))) { + astwo = DPTDPT_TRUE; + } + } + } + return std::make_tuple(asone, astwo); +} +} /* end namespace dptdptcorrelations */ + +// Task for <dpt,dpt> correlations analysis +// FIXME: this should really inherit from AnalysisTask but +// we need GCC 7.4+ for that + +using namespace dptdptcorrelations; + +struct DptDptCorrelationsFilterAnalysisTask { + + OutputObj<TDirectory> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; + + OutputObj<TH1F> fOutCentMultB{"CentralityB", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutCentMultA{"CentralityA", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutVertexZB{"VertexZB", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutVertexZA{"VertexZA", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPtB{"fHistPtB", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPtA{"fHistPtA", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPtPosB{"fHistPtPosB", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPtPosA{"fHistPtPosA", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPtNegB{"fHistPtNegB", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPtNegA{"fHistPtNegA", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutEtaB{"fHistEtaB", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutEtaA{"fHistEtaA", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPhiB{"fHistPhiB", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> fOutPhiA{"fHistPhiA", OutputObjHandlingPolicy::AnalysisObject}; + // no more histograms for the time being + // OutputObj<TH2F> fOutEtaVsPhiB{"CSTaskEtaVsPhiB", OutputObjHandlingPolicy::AnalysisObject}; + // OutputObj<TH2F> fOutEtaVsPhiA{"CSTaskEtaVsPhiA", OutputObjHandlingPolicy::AnalysisObject}; + // OutputObj<TH2F> fOutPtVsEtaB{"fhPtVsEtaB", OutputObjHandlingPolicy::AnalysisObject}; + // OutputObj<TH2F> fOutPtVsEtaA{"fhPtVsEtaA", OutputObjHandlingPolicy::AnalysisObject}; + + Produces<aod::AcceptedEvents> acceptedevents; + Produces<aod::ScannedTracks> scannedtracks; + + void init(InitContext const&) + { + /* if the system type is not known at this time, we have to put the initalization somwhere else */ + fSystem = getSystemType(); + + if (fSystem > kPbp) { + fhCentMultB = new TH1F("CentralityB", "Centrality before cut; centrality (%)", 100, 0, 100); + fhCentMultA = new TH1F("CentralityA", "Centrality; centrality (%)", 100, 0, 100); + } else { + /* for pp, pPb and Pbp systems use multiplicity instead */ + fhCentMultB = new TH1F("MultiplicityB", "Multiplicity before cut; multiplicity (%)", 100, 0, 100); + fhCentMultA = new TH1F("MultiplicityA", "Multiplicity; multiplicity (%)", 100, 0, 100); + } + fhVertexZB = new TH1F("VertexZB", "Vertex Z; z_{vtx}", 60, -15, 15); + fhVertexZA = new TH1F("VertexZA", "Vertex Z; z_{vtx}", zvtxbins, zvtxlow, zvtxup); + + fhPtB = new TH1F("fHistPtB", "p_{T} distribution for reconstructed before;p_{T} (GeV/c);dN/dP_{T} (c/GeV)", 100, 0.0, 15.0); + fhPtA = new TH1F("fHistPtA", "p_{T} distribution for reconstructed;p_{T} (GeV/c);dN/dP_{T} (c/GeV)", ptbins, ptlow, ptup); + fhPtPosB = new TH1F("fHistPtPosB", "P_{T} distribution for reconstructed (#{+}) before;P_{T} (GeV/c);dN/dP_{T} (c/GeV)", 100, 0.0, 15.0); + fhPtPosA = new TH1F("fHistPtPosA", "P_{T} distribution for reconstructed (#{+});P_{T} (GeV/c);dN/dP_{T} (c/GeV)", ptbins, ptlow, ptup); + fhPtNegB = new TH1F("fHistPtNegB", "P_{T} distribution for reconstructed (#{-}) before;P_{T} (GeV/c);dN/dP_{T} (c/GeV)", 100, 0.0, 15.0); + fhPtNegA = new TH1F("fHistPtNegA", "P_{T} distribution for reconstructed (#{-});P_{T} (GeV/c);dN/dP_{T} (c/GeV)", ptbins, ptlow, ptup); + fhEtaB = new TH1F("fHistEtaB", "#eta distribution for reconstructed before;#eta;counts", 40, 2.0, 2.0); + fhEtaA = new TH1F("fHistEtaA", "#eta distribution for reconstructed;#eta;counts", etabins, etalow, etaup); + fhPhiB = new TH1F("fHistPhiB", "#phi distribution for reconstructed before;#phi;counts", 360, 0.0, 2 * M_PI); + fhPhiA = new TH1F("fHistPhiA", "#phi distribution for reconstructed;#phi;counts", 360, 0.0, 2 * M_PI); + // no more histograms for the time being + // fhEtaVsPhiB = new TH2F(TString::Format("CSTaskEtaVsPhiB_%s",fTaskConfigurationString.c_str()),"#eta vs #phi before;#phi;#eta", 360, 0.0, 2*M_PI, 100, -2.0, 2.0); + // fhEtaVsPhiA = new TH2F(TString::Format("CSTaskEtaVsPhiA_%s",fTaskConfigurationString.c_str()),"#eta vs #phi;#phi;#eta", 360, 0.0, 2*M_PI, etabins, etalow, etaup); + // fhPtVsEtaB = new TH2F(TString::Format("fhPtVsEtaB_%s",fTaskConfigurationString.c_str()),"p_{T} vs #eta before;#eta;p_{T} (GeV/c)",etabins,etalow,etaup,100,0.0,15.0); + // fhPtVsEtaA = new TH2F(TString::Format("fhPtVsEtaA_%s",fTaskConfigurationString.c_str()),"p_{T} vs #eta;#eta;p_{T} (GeV/c)",etabins,etalow,etaup,ptbins,ptlow,ptup); + + fOutCentMultB.setObject(fhCentMultB); + fOutCentMultA.setObject(fhCentMultA); + fOutVertexZB.setObject(fhVertexZB); + fOutVertexZA.setObject(fhVertexZA); + fOutPtB.setObject(fhPtB); + fOutPtA.setObject(fhPtA); + fOutPtPosB.setObject(fhPtPosB); + fOutPtPosA.setObject(fhPtPosA); + fOutPtNegB.setObject(fhPtNegB); + fOutPtNegA.setObject(fhPtNegA); + fOutEtaB.setObject(fhEtaB); + fOutEtaA.setObject(fhEtaA); + fOutPhiB.setObject(fhPhiB); + fOutPhiA.setObject(fhPhiA); + // no more histograms for the time being + // fOutEtaVsPhiB.setObject(fhEtaVsPhiB); + // fOutEtaVsPhiA.setObject(fhEtaVsPhiA); + // fOutPtVsEtaB.setObject(fhPtVsEtaB); + // fOutPtVsEtaA.setObject(fhPtVsEtaA); + } + + void process(aod::CollisionEvSelCent const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection> const& ftracks) + { + // LOGF(INFO,"New collision with %d filtered tracks", ftracks.size()); + fhCentMultB->Fill(collision.centV0M()); + fhVertexZB->Fill(collision.posZ()); + int acceptedevent = DPTDPT_FALSE; + if (IsEvtSelected(collision)) { + acceptedevent = DPTDPT_TRUE; + fhCentMultA->Fill(collision.centV0M()); + fhVertexZA->Fill(collision.posZ()); + // LOGF(INFO,"New accepted collision with %d filtered tracks", ftracks.size()); + + for (auto& track : ftracks) { + /* before track selection */ + fhPtB->Fill(track.pt()); + fhEtaB->Fill(track.eta()); + fhPhiB->Fill(track.phi()); + // no more histograms for the time being + // fhEtaVsPhiB->Fill(track.phi(),track.eta()); + // fhPtVsEtaB->Fill(track.eta(),track.pt()); + if (track.charge() > 0) { + fhPtPosB->Fill(track.pt()); + } else { + fhPtNegB->Fill(track.pt()); + } + + /* track selection */ + /* tricky because the boolean columns issue */ + auto [asone, astwo] = AcceptTrack(track); + if ((asone == DPTDPT_TRUE) or (astwo == DPTDPT_TRUE)) { + /* the track has been accepted */ + fhPtA->Fill(track.pt()); + fhEtaA->Fill(track.eta()); + fhPhiA->Fill(track.phi()); + // no more histograms for the time being + // fhEtaVsPhiA->Fill(track.phi(),track.eta()); + // fhPtVsEtaA->Fill(track.eta(),track.pt()); + if (track.charge() > 0) { + fhPtPosA->Fill(track.pt()); + } else { + fhPtNegA->Fill(track.pt()); + } + } + scannedtracks(asone, astwo); + } + } else { + for (auto& track : ftracks) { + scannedtracks(DPTDPT_FALSE, DPTDPT_FALSE); + } + } + acceptedevents(acceptedevent); + } +}; + +// Task for building <dpt,dpt> correlations +struct DptDptCorrelationsTask { + + Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); + Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); + + using FilteredTracks = soa::Filtered<soa::Join<aod::Tracks, aod::ScannedTracks>>; + Partition<FilteredTracks> Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE; + Partition<FilteredTracks> Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE; + + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents, aod::AcceptedEvents>>::iterator const& collision, + FilteredTracks const& tracks) + { + if (cfgProcessPairs) { + /* process pairs of tracks */ + // this will be desireable + // for (auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(Tracks1, Tracks2))) { + for (auto& track1 : Tracks1) { + for (auto& track2 : Tracks2) { + /* checkiing the same track id condition */ + if (track1.index() == track2.index()) { + LOGF(INFO, "Tracks with the same Id: %d", track1.index()); + } + /* now it is just to collect the two particle information */ + } + } + } else { + /* process single tracks */ + } + } +}; + +// Task for building <dpt,dpt> correlations +struct TracksAndEventClassificationQA { + + OutputObj<TH1F> fTracksOne{TH1F("TracksOne", "Tracks as track one;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fTracksTwo{TH1F("TracksTwo", "Tracks as track two;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fTracksOneAndTwo{TH1F("TracksOneAndTwo", "Tracks as track one and as track two;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fTracksNone{TH1F("TracksNone", "Not selected tracks;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fTracksOneUnsel{TH1F("TracksOneUnsel", "Tracks as track one;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fTracksTwoUnsel{TH1F("TracksTwoUnsel", "Tracks as track two;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fTracksOneAndTwoUnsel{TH1F("TracksOneAndTwoUnsel", "Tracks as track one and as track two;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fTracksNoneUnsel{TH1F("TracksNoneUnsel", "Not selected tracks;number of tracks;events", 1500, 0.0, 1500.0)}; + OutputObj<TH1F> fSelectedEvents{TH1F("SelectedEvents", "Selected events;number of tracks;events", 2, 0.0, 2.0)}; + + Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); + Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); + + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents, aod::AcceptedEvents>>::iterator const& collision, + soa::Filtered<soa::Join<aod::Tracks, aod::ScannedTracks>> const& tracks) + { + if (collision.eventaccepted() != DPTDPT_TRUE) { + fSelectedEvents->Fill(0.5); + } else { + fSelectedEvents->Fill(1.5); + } + + int ntracks_one = 0; + int ntracks_two = 0; + int ntracks_one_and_two = 0; + int ntracks_none = 0; + for (auto& track : tracks) { + if ((track.trackacceptedasone() != DPTDPT_TRUE) and (track.trackacceptedastwo() != DPTDPT_TRUE)) { + ntracks_none++; + } + if ((track.trackacceptedasone() == DPTDPT_TRUE) and (track.trackacceptedastwo() == DPTDPT_TRUE)) { + ntracks_one_and_two++; + } + if (track.trackacceptedasone() == DPTDPT_TRUE) { + ntracks_one++; + } + if (track.trackacceptedastwo() == DPTDPT_TRUE) { + ntracks_two++; + } + } + if (collision.eventaccepted() != DPTDPT_TRUE) { + /* control for non selected events */ + fTracksOneUnsel->Fill(ntracks_one); + fTracksTwoUnsel->Fill(ntracks_two); + fTracksNoneUnsel->Fill(ntracks_none); + fTracksOneAndTwoUnsel->Fill(ntracks_one_and_two); + } else { + fTracksOne->Fill(ntracks_one); + fTracksTwo->Fill(ntracks_two); + fTracksNone->Fill(ntracks_none); + fTracksOneAndTwo->Fill(ntracks_one_and_two); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<DptDptCorrelationsFilterAnalysisTask>("DptDptCorrelationsFilterAnalysisTask"), + adaptAnalysisTask<DptDptCorrelationsTask>("DptDptCorrelationsTask"), + adaptAnalysisTask<TracksAndEventClassificationQA>("TracksAndEventClassificationQA"), + }; +} From 9559be395401cf463e8b85769738e3451429ef2f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 26 Aug 2020 12:32:35 +0200 Subject: [PATCH 0452/1751] DPL: fix data race in ServiceRegistry::bindService (#4215) --- Framework/Core/src/ServiceRegistry.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Framework/Core/src/ServiceRegistry.cxx b/Framework/Core/src/ServiceRegistry.cxx index 7efcad9fb29ea..1890483b69724 100644 --- a/Framework/Core/src/ServiceRegistry.cxx +++ b/Framework/Core/src/ServiceRegistry.cxx @@ -73,6 +73,8 @@ void ServiceRegistry::declareService(ServiceSpec const& spec, DeviceState& state void ServiceRegistry::bindService(ServiceSpec const& spec, void* service) { + static TracyLockableN(std::mutex, bindMutex, "bind mutex"); + std::scoped_lock<LockableBase(std::mutex)> lock(bindMutex); if (spec.preProcessing) { mPreProcessingHandles.push_back(ServiceProcessingHandle{spec.preProcessing, service}); } From 3bd4b880d8cf7708f111b0f748c8d4f1c0386301 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 26 Aug 2020 10:02:13 +0200 Subject: [PATCH 0453/1751] DPL: fix equality of DataDescriptorMatchers If the operations are different, matches should be considered different. Test was also wrong. --- Framework/Core/src/DataDescriptorMatcher.cxx | 2 +- Framework/Core/test/test_DataDescriptorMatcher.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DataDescriptorMatcher.cxx b/Framework/Core/src/DataDescriptorMatcher.cxx index c067233a6d3b2..5d38036cb6335 100644 --- a/Framework/Core/src/DataDescriptorMatcher.cxx +++ b/Framework/Core/src/DataDescriptorMatcher.cxx @@ -314,7 +314,7 @@ bool DataDescriptorMatcher::match(char const* d, VariableContext& context) const bool DataDescriptorMatcher::operator==(DataDescriptorMatcher const& other) const { - if (mOp != this->mOp) { + if (other.mOp != this->mOp) { return false; } diff --git a/Framework/Core/test/test_DataDescriptorMatcher.cxx b/Framework/Core/test/test_DataDescriptorMatcher.cxx index c12e0c7f0cb69..45335adccef15 100644 --- a/Framework/Core/test/test_DataDescriptorMatcher.cxx +++ b/Framework/Core/test/test_DataDescriptorMatcher.cxx @@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE(TestMatcherInvariants) DataDescriptorMatcher::Op::Just, ConstantValueMatcher{1}, DescriptionValueMatcher{"TPC"}}; - BOOST_CHECK(matcherA == matcherB); + BOOST_CHECK_NE(matcherA, matcherB); } { From 24fb349617f5714f95b4b722a4c3e65168ec5522 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 26 Aug 2020 10:03:16 +0200 Subject: [PATCH 0454/1751] DPL: improve report for DataDescriptorMatcher test --- Framework/Core/test/test_DataDescriptorMatcher.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Framework/Core/test/test_DataDescriptorMatcher.cxx b/Framework/Core/test/test_DataDescriptorMatcher.cxx index 45335adccef15..6501a31a7e705 100644 --- a/Framework/Core/test/test_DataDescriptorMatcher.cxx +++ b/Framework/Core/test/test_DataDescriptorMatcher.cxx @@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(TestMatcherInvariants) DataDescriptorMatcher matcherB{ DataDescriptorMatcher::Op::Just, OriginValueMatcher{"TPC"}}; - BOOST_CHECK(matcherA == matcherB); + BOOST_CHECK_EQUAL(matcherA, matcherB); } { @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(TestMatcherInvariants) DataDescriptorMatcher matcherB{ DataDescriptorMatcher::Op::Just, DescriptionValueMatcher{"TRACKS"}}; - BOOST_CHECK(matcherA == matcherB); + BOOST_CHECK_EQUAL(matcherA, matcherB); } { @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(TestMatcherInvariants) DataDescriptorMatcher matcherB{ DataDescriptorMatcher::Op::Just, SubSpecificationTypeValueMatcher{1}}; - BOOST_CHECK(matcherA == matcherB); + BOOST_CHECK_EQUAL(matcherA, matcherB); } { @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE(TestMatcherInvariants) DataDescriptorMatcher matcherB{ DataDescriptorMatcher::Op::Just, ConstantValueMatcher{1}}; - BOOST_CHECK(matcherA == matcherB); + BOOST_CHECK_EQUAL(matcherA, matcherB); } { @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(TestMatcherInvariants) DataDescriptorMatcher::Op::And, SubSpecificationTypeValueMatcher{1}, ConstantValueMatcher{true}))}; - BOOST_CHECK(matcherA == matcherB); + BOOST_CHECK_EQUAL(matcherA, matcherB); } } @@ -572,7 +572,7 @@ BOOST_AUTO_TEST_CASE(DataQuery) StartTimeValueMatcher{ContextRef{0}})))}; auto matcher = std::get_if<DataDescriptorMatcher>(&result0[0].matcher); BOOST_REQUIRE(matcher != nullptr); - BOOST_CHECK(expectedMatcher00 == *matcher); + BOOST_CHECK_EQUAL(expectedMatcher00, *matcher); std::ostringstream ss0; ss0 << *matcher; std::ostringstream expectedSS00; From 52b6702202a1f66ad2b1e658df0ed2580d0bcc34 Mon Sep 17 00:00:00 2001 From: Gian Michele Innocenti <gminnocen@gmail.com> Date: Wed, 26 Aug 2020 15:58:27 +0200 Subject: [PATCH 0455/1751] Add skeleton QA task (#4206) --- Analysis/Tasks/CMakeLists.txt | 4 ++++ Analysis/Tasks/qaTask.cxx | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 Analysis/Tasks/qaTask.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 4a5cd1e2403d5..393b627805be5 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -51,6 +51,10 @@ o2_add_dpl_workflow(taskdzero PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing COMPONENT_NAME Analysis) +o2_add_dpl_workflow(qatask + SOURCES qaTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) o2_add_dpl_workflow(spectra-tof SOURCES spectraTOF.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx new file mode 100644 index 0000000000000..38634ed8c4492 --- /dev/null +++ b/Analysis/Tasks/qaTask.cxx @@ -0,0 +1,43 @@ +// 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 "Analysis/MC.h" + +#include <TH1F.h> +#include <cmath> + +using namespace o2; +using namespace o2::framework; + +struct QATrackingKine { + OutputObj<TH1F> hpt{TH1F("pt", ";p_{T} [GeV]", 100, 0., 200.)}; + OutputObj<TH1F> hphi{TH1F("phi", ";#phi", 100, 0, 2 * M_PI)}; + OutputObj<TH1F> heta{TH1F("eta", ";#eta", 100, -6, 6)}; + + void process(aod::Collision const& collision, + aod::BCs const& bcs, + soa::Join<aod::Tracks, aod::TracksCov> const& tracks) + { + for (auto& track : tracks) { + heta->Fill(track.eta()); + hphi->Fill(track.phi()); + hpt->Fill(track.pt()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<QATrackingKine>("qa-tracking-kine"), + }; +} From 6b695d99120199002b4d97ce54d3c185c6dd5cb5 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Wed, 26 Aug 2020 13:40:18 +0200 Subject: [PATCH 0456/1751] TPCClusterFinder: Reduce memory usage on MC propagation. --- GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx index 3f5afeb0d3d20..a408b2763ff4d 100644 --- a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx @@ -23,9 +23,6 @@ using namespace GPUCA_NAMESPACE::gpu::tpccf; MCLabelAccumulator::MCLabelAccumulator(GPUTPCClusterFinder& clusterer) : mIndexMap(clusterer.mPindexMap), mLabels(clusterer.mPinputLabels), mOutput(clusterer.mPlabelsByRow) { - if (engaged()) { - mClusterLabels.reserve(32); - } } void MCLabelAccumulator::collect(const ChargePos& pos, Charge q) From a3cf4c00127be2fbef7d7eb288804613376410fb Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 13:52:19 +0200 Subject: [PATCH 0457/1751] GPU: Fix typo leading to memory corruption --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 261377d381474..e4b8aa058bd6e 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1739,11 +1739,11 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() if (!((GetRecoStepsOutputs() & GPUDataTypes::InOutType::TPCSectorTracks) || (doGPU && !(GetRecoStepsGPU() & RecoStep::TPCMerging)))) { unsigned int sliceLeft, sliceRight; GPUTPCGlobalTracking::GlobalTrackingSliceLeftRight(tmpSlice, sliceLeft, sliceRight); - if (!blocking[tmpSlice * mRec->NStreams() + sliceLeft] % mRec->NStreams()) { + if (!blocking[tmpSlice * mRec->NStreams() + sliceLeft % mRec->NStreams()]) { StreamWaitForEvents(tmpSlice % mRec->NStreams(), &mEvents->slice[sliceLeft]); blocking[tmpSlice * mRec->NStreams() + sliceLeft % mRec->NStreams()] = true; } - if (!blocking[tmpSlice * mRec->NStreams() + sliceRight] % mRec->NStreams()) { + if (!blocking[tmpSlice * mRec->NStreams() + sliceRight % mRec->NStreams()]) { StreamWaitForEvents(tmpSlice % mRec->NStreams(), &mEvents->slice[sliceRight]); blocking[tmpSlice * mRec->NStreams() + sliceRight % mRec->NStreams()] = true; } From 8292063c12081a9bdcd5ecd7740ea13a15100b61 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 14:06:19 +0200 Subject: [PATCH 0458/1751] GPU: No need to reinitialize pointers that were not initialized in the first place --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index f841a5659d7a5..363717826998d 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -406,7 +406,7 @@ size_t GPUReconstruction::AllocateRegisteredMemory(GPUProcessor* proc, bool rese if (proc == nullptr ? !mMemoryResources[i].mProcessor->mAllocateAndInitializeLate : mMemoryResources[i].mProcessor == proc) { if (!(mMemoryResources[i].mType & GPUMemoryResource::MEMORY_CUSTOM)) { total += AllocateRegisteredMemory(i); - } else if (resetCustom) { + } else if (resetCustom && (mMemoryResources[i].mPtr || mMemoryResources[i].mPtrDevice)) { ResetRegisteredMemoryPointers(i); } } From d5fee9ecc7b017c6ada5916f8af5f619fcea5169 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 14:26:26 +0200 Subject: [PATCH 0459/1751] GPU: Apply GPU global memory reuse also for individual host allocations --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 25 ++++++++++++++++++---- GPU/GPUTracking/Base/GPUReconstruction.h | 4 +++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 363717826998d..be400bdbe5683 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -511,6 +511,9 @@ void GPUReconstruction::AllocateRegisteredMemoryInternal(GPUMemoryResource* res, if (mProcessingSettings.allocDebugLevel >= 2) { std::cout << (res->mReuse >= 0 ? "Reused " : "Allocated ") << res->mName << ": " << res->mSize << "\n"; } + if (res->mType & GPUMemoryResource::MEMORY_STACK) { + mNonPersistentIndividualAllocations.emplace_back(res); + } } } else { if (res->mPtr != nullptr) { @@ -642,7 +645,11 @@ void GPUReconstruction::FreeRegisteredMemory(GPUProcessor* proc, bool freeCustom void GPUReconstruction::FreeRegisteredMemory(short ires) { - GPUMemoryResource* res = &mMemoryResources[ires]; + FreeRegisteredMemory(&mMemoryResources[ires]); +} + +void GPUReconstruction::FreeRegisteredMemory(GPUMemoryResource* res) +{ if (mProcessingSettings.allocDebugLevel >= 2 && (res->mPtr || res->mPtrDevice)) { std::cout << "Freeing " << res->mName << ": size " << res->mSize << " (reused " << res->mReuse << ")\n"; } @@ -663,7 +670,7 @@ void GPUReconstruction::ReturnVolatileDeviceMemory() void GPUReconstruction::PushNonPersistentMemory() { - mNonPersistentMemoryStack.emplace_back(mHostMemoryPoolEnd, mDeviceMemoryPoolEnd); + mNonPersistentMemoryStack.emplace_back(mHostMemoryPoolEnd, mDeviceMemoryPoolEnd, mNonPersistentIndividualAllocations.size()); } void GPUReconstruction::PopNonPersistentMemory(RecoStep step) @@ -674,8 +681,17 @@ void GPUReconstruction::PopNonPersistentMemory(RecoStep step) if (mProcessingSettings.keepDisplayMemory || mProcessingSettings.disableMemoryReuse) { return; } - mHostMemoryPoolEnd = mNonPersistentMemoryStack.back().first; - mDeviceMemoryPoolEnd = mNonPersistentMemoryStack.back().second; + mHostMemoryPoolEnd = std::get<0>(mNonPersistentMemoryStack.back()); + mDeviceMemoryPoolEnd = std::get<1>(mNonPersistentMemoryStack.back()); + for (unsigned int i = std::get<2>(mNonPersistentMemoryStack.back()); i < mNonPersistentIndividualAllocations.size(); i++) { + GPUMemoryResource* res = mNonPersistentIndividualAllocations[i]; + if (res->mReuse < 0) { + operator delete(res->mPtrDevice GPUCA_OPERATOR_NEW_ALIGNMENT); + } + res->mPtr = nullptr; + res->mPtrDevice = nullptr; + } + mNonPersistentIndividualAllocations.resize(std::get<2>(mNonPersistentMemoryStack.back())); mNonPersistentMemoryStack.pop_back(); } @@ -716,6 +732,7 @@ void GPUReconstruction::ClearAllocatedMemory(bool clearOutputs) mUnmanagedChunks.clear(); mVolatileMemoryStart = nullptr; mNonPersistentMemoryStack.clear(); + mNonPersistentIndividualAllocations.clear(); mHostMemoryPoolEnd = mHostMemoryPoolBlocked ? mHostMemoryPoolBlocked : ((char*)mHostMemoryBase + mHostMemorySize); mDeviceMemoryPoolEnd = mDeviceMemoryPoolBlocked ? mDeviceMemoryPoolBlocked : ((char*)mDeviceMemoryBase + mDeviceMemorySize); } diff --git a/GPU/GPUTracking/Base/GPUReconstruction.h b/GPU/GPUTracking/Base/GPUReconstruction.h index 188200ff9e275..fbd8ae15da8a5 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.h +++ b/GPU/GPUTracking/Base/GPUReconstruction.h @@ -261,6 +261,7 @@ class GPUReconstruction protected: void AllocateRegisteredMemoryInternal(GPUMemoryResource* res, GPUOutputControl* control, GPUReconstruction* recPool); + void FreeRegisteredMemory(GPUMemoryResource* res); GPUReconstruction(const GPUSettingsDeviceBackend& cfg); // Constructor int InitPhaseBeforeDevice(); virtual void UpdateSettings() {} @@ -381,7 +382,8 @@ class GPUReconstruction std::vector<unsigned short> res; }; std::unordered_map<GPUMemoryReuse::ID, MemoryReuseMeta> mMemoryReuse1to1; - std::vector<std::pair<void*, void*>> mNonPersistentMemoryStack; + std::vector<std::tuple<void*, void*, size_t>> mNonPersistentMemoryStack; + std::vector<GPUMemoryResource*> mNonPersistentIndividualAllocations; std::unique_ptr<GPUReconstructionPipelineContext> mPipelineContext; From d4b886471f9a55bb7b8e5da130aad6c2524ccf4c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 26 Aug 2020 12:48:08 +0200 Subject: [PATCH 0460/1751] DPL: fix compilation in case DebugGUI is not there --- Framework/Core/CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index b8323476367df..7c235e03d9b73 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -8,16 +8,14 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -if(GLFW_FOUND) +if (TARGET AliceO2::DebugGUI) set(GUI_SOURCES src/FrameworkGUIDebugger.cxx src/FrameworkGUIDevicesGraph.cxx src/FrameworkGUIDeviceInspector.cxx src/FrameworkGUIDataRelayerUsage.cxx src/PaletteHelpers.cxx) + set(DEBUGGUI_TARGET AliceO2::DebugGUI) else() set(GUI_SOURCES src/FrameworkDummyDebugger.cxx) endif() -if (TARGET AliceO2::DebugGUI) - set(DEBUGGUI_TARGET AliceO2::DebugGUI) -endif() # Given GCC 7.3 does not provide std::filesystem we use Boost instead # Drop this once we move to GCC 8.2+ From 07587c02d5b0736ac875ca85fefe831cee7c085b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 13:42:18 +0200 Subject: [PATCH 0461/1751] GPU: Build standalone visualization only when DebugGUI present --- Detectors/TPC/workflow/CMakeLists.txt | 2 +- GPU/GPUTracking/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/workflow/CMakeLists.txt b/Detectors/TPC/workflow/CMakeLists.txt index 735b3c9fee684..9a7b53474aae2 100644 --- a/Detectors/TPC/workflow/CMakeLists.txt +++ b/Detectors/TPC/workflow/CMakeLists.txt @@ -46,7 +46,7 @@ o2_add_test(workflow ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage) if(GPUCA_EVENT_DISPLAY OR - (OPENGL_FOUND AND GLFW_FOUND AND GLEW_FOUND AND OPENGL_GLU_FOUND + (OPENGL_FOUND AND GLFW_FOUND AND TARGET AliceO2::DebugGUI AND OPENGL_GLU_FOUND AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")) target_compile_definitions(${targetName} PRIVATE GPUCA_BUILD_EVENT_DISPLAY) endif() diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index bba284aa634b9..c6fd5c4ffac74 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -21,7 +21,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") else() if(OPENGL_FOUND AND GLFW_FOUND - AND (ALIGPU_BUILD_TYPE STREQUAL "O2" OR GLEW_FOUND) + AND ((ALIGPU_BUILD_TYPE STREQUAL "O2" AND TARGET AliceO2::DebugGUI) OR GLEW_FOUND) AND OPENGL_GLU_FOUND AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(GPUCA_EVENT_DISPLAY ON) From 17241922d288ff84d299493e5f69528cf0b6ee0f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 13:42:52 +0200 Subject: [PATCH 0462/1751] GPU: Read missing setting that was lost when switching to configKeyValues --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 9 +++++++++ GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/Standalone/cmake/config.cmake | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 53973a11afc33..da9c0f7850d33 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -121,6 +121,15 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int processAttributes->outputBufferSize = confParam.outputBufferSize; processAttributes->suppressOutput = (confParam.dump == 2); config.configInterface.dumpEvents = confParam.dump; + if (confParam.display) { +#ifdef GPUCA_BUILD_EVENT_DISPLAY + processAttributes->displayBackend.reset(new GPUDisplayBackendGlfw); + config.configProcessing.eventDisplay = processAttributes->displayBackend.get(); + LOG(INFO) << "Event display enabled"; +#else + throw std::runtime_error("Standalone Event Display not enabled at build time!"); +#endif + } if (config.configEvent.continuousMaxTimeBin == -1) { config.configEvent.continuousMaxTimeBin = (o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * o2::constants::lhc::LHCMaxBunches + 2 * constants::LHCBCPERTIMEBIN - 2) / constants::LHCBCPERTIMEBIN; diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 061b09acd9257..526b7eab68458 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -262,6 +262,7 @@ AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffer AddOption(outputBufferSize, unsigned long, 200000000ul, "", 0, "Size of the output buffers to be allocated") AddOption(synchronousProcessing, bool, false, "", 0, "Apply performance shortcuts for synchronous processing, disable unneeded steps") AddOption(mutexMemReg, bool, false, "", 0, "Global mutex to serialize GPU memory registration") +AddOption(display, bool, false, "", 0, "Enable standalone gpu tracking visualizaion") EndConfig() #endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE diff --git a/GPU/GPUTracking/Standalone/cmake/config.cmake b/GPU/GPUTracking/Standalone/cmake/config.cmake index 1535aa5fd642d..f4d4330760e23 100644 --- a/GPU/GPUTracking/Standalone/cmake/config.cmake +++ b/GPU/GPUTracking/Standalone/cmake/config.cmake @@ -1,5 +1,5 @@ -#This is the configuration file for the standalone build -#Its options do not affect the O2 build +# This is the configuration file for the standalone build +# Its options do not affect the O2 build !!!! set(ENABLE_CUDA AUTO) set(ENABLE_HIP AUTO) From 63e6af7fb6867dcbb8cf87c9463e2e918c429ea5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 24 Aug 2020 23:23:28 +0200 Subject: [PATCH 0463/1751] GPU: Use C++17 in CUDA compilation with CUDA 11/CMake 3.18 --- GPU/GPUTracking/Standalone/CMakeLists.txt | 2 +- dependencies/FindO2GPU.cmake | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index b4b42185ef4c8..325aec20fb796 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -9,7 +9,7 @@ # submit itself to any jurisdiction. # Some general CMake settings -cmake_minimum_required(VERSION 3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.18 FATAL_ERROR) project(GPUTrackingStandalone) include(FeatureSummary) set(CMAKE_INSTALL_BINDIR "${CMAKE_INSTALL_PREFIX}") diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 7d4d88a266838..95490cc320b4c 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -28,7 +28,7 @@ string(TOUPPER "${ENABLE_HIP}" ENABLE_HIP) # Detect and enable CUDA if(ENABLE_CUDA) set(CUDA_MINIMUM_VERSION "11.0") - set(CMAKE_CUDA_STANDARD 14) + set(CMAKE_CUDA_STANDARD 17) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) include(CheckLanguage) check_language(CUDA) @@ -40,6 +40,7 @@ if(ENABLE_CUDA) endif() endif() if(CMAKE_CUDA_COMPILER) + cmake_minimum_required(VERSION 3.18 FATAL_ERROR) enable_language(CUDA) get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) if(NOT CUDA IN_LIST LANGUAGES) From 2f10fe86355bc4aae3abdb3f84dd75cb8b0752d9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 24 Aug 2020 23:25:43 +0200 Subject: [PATCH 0464/1751] GPU: Disable CUDA host compiler check --- dependencies/FindO2GPU.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 95490cc320b4c..075f933ecd1ae 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -53,7 +53,7 @@ if(ENABLE_CUDA) # Forward CXX flags to CUDA C++ Host compiler (for warnings, gdb, etc.) STRING(REGEX REPLACE "\-std=[^ ]*" "" CMAKE_CXX_FLAGS_NOSTD ${CMAKE_CXX_FLAGS}) # Need to strip c++17 imposed by alidist defaults - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda -Xptxas -v") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda --allow-unsupported-compiler -Xptxas -v") set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -lineinfo -Xcompiler \"${CMAKE_CXX_FLAGS_DEBUG}\" -Xptxas -O0 -Xcompiler -O0") if(NOT CMAKE_BUILD_TYPE STREQUAL "DEBUG") set(CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE} "${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE}} -Xcompiler \"${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}\" -Xptxas -O4 -Xcompiler -O4 -use_fast_math --ftz=true") From 8211b2cf749524e8f1beb5e1034387657b203cd2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 11:22:19 +0200 Subject: [PATCH 0465/1751] GPU: Use C++17 namespace syntax in more places --- GPU/GPUTracking/Base/GPUReconstructionTimeframe.h | 7 ++----- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 7 ++----- .../Base/hip/GPUReconstructionHIP.hip.cxx | 7 ++----- .../DataCompression/GPUTPCClusterStatistics.h | 14 ++++---------- .../DataCompression/GPUTPCCompression.h | 14 ++++---------- .../DataCompression/GPUTPCCompressionKernels.h | 14 ++++---------- .../DataCompression/GPUTPCCompressionTrackModel.h | 7 ++----- .../DataCompression/TPCClusterDecompressor.h | 14 ++++---------- GPU/GPUTracking/ITS/GPUITSFitter.h | 14 ++++---------- GPU/GPUTracking/ITS/GPUITSFitterKernels.h | 14 ++++---------- GPU/GPUTracking/ITS/GPUITSTrack.h | 7 ++----- GPU/GPUTracking/Standalone/qa/GPUQA.h | 7 ++----- GPU/GPUTracking/TPCClusterFinder/Array2D.h | 7 ++----- GPU/GPUTracking/TPCClusterFinder/CfFragment.h | 7 ++----- GPU/GPUTracking/TPCClusterFinder/CfUtils.h | 7 ++----- .../TPCClusterFinder/GPUTPCCFChargeMapFiller.h | 14 ++++---------- .../TPCClusterFinder/GPUTPCCFClusterizer.h | 12 ++++-------- .../TPCClusterFinder/GPUTPCCFDecodeZS.h | 7 ++----- .../TPCClusterFinder/GPUTPCCFDeconvolution.h | 7 ++----- GPU/GPUTracking/TPCClusterFinder/GPUTPCCFGather.h | 7 ++----- .../TPCClusterFinder/GPUTPCCFMCLabelFlattener.h | 7 ++----- .../TPCClusterFinder/GPUTPCCFNoiseSuppression.h | 7 ++----- .../TPCClusterFinder/GPUTPCCFPeakFinder.h | 7 ++----- .../TPCClusterFinder/GPUTPCCFStreamCompaction.h | 7 ++----- .../TPCClusterFinder/GPUTPCClusterFinder.h | 7 ++----- .../TPCClusterFinder/MCLabelAccumulator.h | 11 ++++------- GPU/GPUTracking/TPCClusterFinder/PackedCharge.h | 7 ++----- GPU/TPCFastTransformation/test/testSplines.cxx | 7 ++----- 28 files changed, 74 insertions(+), 180 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.h b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.h index 20996b2de1f87..c0f21f7b94f23 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionTimeframe.h +++ b/GPU/GPUTracking/Base/GPUReconstructionTimeframe.h @@ -20,13 +20,10 @@ #include <random> #include <tuple> -namespace o2 -{ -namespace tpc +namespace o2::tpc { struct ClusterNative; -} -} // namespace o2 +} // namespace o2::tpc namespace GPUCA_NAMESPACE { diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 2eb78b46afaea..dcaabc9bc781d 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -63,9 +63,7 @@ __global__ void dummyInitKernel(void* foo) #include "ITStrackingCUDA/TrackerTraitsNV.h" #include "ITStrackingCUDA/VertexerTraitsGPU.h" #else -namespace o2 -{ -namespace its +namespace o2::its { class TrackerTraitsNV : public TrackerTraits { @@ -73,8 +71,7 @@ class TrackerTraitsNV : public TrackerTraits class VertexerTraitsGPU : public VertexerTraits { }; -} // namespace its -} // namespace o2 +} // namespace o2::its #endif class GPUDebugTiming diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index 72aaf443c0e9f..f8fd21c4d4904 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -59,9 +59,7 @@ __global__ void dummyInitKernel(void* foo) {} #if defined(HAVE_O2HEADERS) && !defined(GPUCA_NO_ITS_TRAITS) #include "ITStrackingHIP/VertexerTraitsHIP.h" #else -namespace o2 -{ -namespace its +namespace o2::its { class VertexerTraitsHIP : public VertexerTraits { @@ -69,8 +67,7 @@ class VertexerTraitsHIP : public VertexerTraits class TrackerTraitsHIP : public TrackerTraits { }; -} // namespace its -} // namespace o2 +} // namespace o2::its #endif class GPUDebugTiming diff --git a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h index 9605ff508b04f..1c1279d529b3c 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h @@ -18,17 +18,12 @@ #include "TPCClusterDecompressor.h" #include <vector> -namespace o2 -{ -namespace tpc +namespace o2::tpc { struct ClusterNativeAccess; -} -} // namespace o2 +} // namespace o2::tpc -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCClusterStatistics { @@ -93,7 +88,6 @@ class GPUTPCClusterStatistics size_t mNTotalClusters = 0; #endif }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompression.h b/GPU/GPUTracking/DataCompression/GPUTPCCompression.h index 5db9aa4a25500..acc64b439c91b 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompression.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompression.h @@ -22,9 +22,7 @@ #ifdef HAVE_O2HEADERS #include "DataFormatsTPC/CompressedClusters.h" #else -namespace o2 -{ -namespace tpc +namespace o2::tpc { struct CompressedClustersPtrs { }; @@ -32,13 +30,10 @@ struct CompressedClusters { }; struct CompressedClustersFlat { }; -} // namespace tpc -} // namespace o2 +} // namespace o2::tpc #endif -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCGMMerger; @@ -125,7 +120,6 @@ GPUdi() void GPUTPCCompression::truncateSignificantBits(T& v, unsigned int nBits v = val; } } -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h index a041608f612aa..94227cf8474e2 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h @@ -16,17 +16,12 @@ #include "GPUGeneralKernels.h" -namespace o2 -{ -namespace tpc +namespace o2::tpc { struct ClusterNative; -} -} // namespace o2 +} // namespace o2::tpc -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCCompressionKernels : public GPUKernelTemplate { @@ -126,7 +121,6 @@ class GPUTPCCompressionGatherKernels : public GPUKernelTemplate GPUdii() static void gatherBuffered(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h index 3b1ccf89cb981..28d9392f039bb 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h @@ -31,9 +31,7 @@ #error Not yet implemented #endif -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { // ATTENTION! This track model is used for the data compression. // Changes to the propagation and fit will prevent the decompression of data @@ -79,7 +77,6 @@ class GPUTPCCompressionTrackModel #endif }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h index 0922339de22c1..991151bade1e9 100644 --- a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h +++ b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h @@ -18,18 +18,13 @@ #include <vector> #include <functional> -namespace o2 -{ -namespace tpc +namespace o2::tpc { struct ClusterNativeAccess; struct ClusterNative; -} // namespace tpc -} // namespace o2 +} // namespace o2::tpc -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { struct GPUParam; @@ -42,7 +37,6 @@ class TPCClusterDecompressor protected: }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/ITS/GPUITSFitter.h b/GPU/GPUTracking/ITS/GPUITSFitter.h index 9c2cd61c4edd0..c45efa0048adf 100644 --- a/GPU/GPUTracking/ITS/GPUITSFitter.h +++ b/GPU/GPUTracking/ITS/GPUITSFitter.h @@ -17,20 +17,15 @@ #include "GPUProcessor.h" #include "GPUITSTrack.h" -namespace o2 -{ -namespace its +namespace o2::its { class Road; struct TrackingFrameInfo; struct Cluster; class Cell; -} // namespace its -} // namespace o2 +} // namespace o2::its -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUITSTrack; @@ -97,7 +92,6 @@ class GPUITSFitter : public GPUProcessor short mMemoryResTracks = -1; short mMemoryResMemory = -1; }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/ITS/GPUITSFitterKernels.h b/GPU/GPUTracking/ITS/GPUITSFitterKernels.h index 9e3528174502b..59ff83030f546 100644 --- a/GPU/GPUTracking/ITS/GPUITSFitterKernels.h +++ b/GPU/GPUTracking/ITS/GPUITSFitterKernels.h @@ -15,17 +15,12 @@ #define GPUITSFITTERKERNELS_H #include "GPUGeneralKernels.h" -namespace o2 -{ -namespace its +namespace o2::its { struct TrackingFrameInfo; -} -} // namespace o2 +} // namespace o2::its -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCGMPropagator; class GPUITSFitter; @@ -41,7 +36,6 @@ class GPUITSFitterKernel : public GPUKernelTemplate protected: GPUd() static bool fitTrack(GPUITSFitter& Fitter, GPUTPCGMPropagator& prop, GPUITSTrack& track, int start, int end, int step); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/ITS/GPUITSTrack.h b/GPU/GPUTracking/ITS/GPUITSTrack.h index 7b5183d2be20c..3ced243587ba5 100644 --- a/GPU/GPUTracking/ITS/GPUITSTrack.h +++ b/GPU/GPUTracking/ITS/GPUITSTrack.h @@ -16,9 +16,7 @@ #include "GPUTPCGMTrackParam.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUITSTrack : public GPUTPCGMTrackParam { @@ -27,7 +25,6 @@ class GPUITSTrack : public GPUTPCGMTrackParam float mAlpha; int mClusters[7]; }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 383f89bcfaf14..a9e6e98dcca2a 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -74,9 +74,7 @@ class MCCompLabel; class AliHLTTPCClusterMCLabel; -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUChainTracking; class GPUTPCMCInfo; @@ -317,8 +315,7 @@ inline bool GPUQA::SuppressTrack(int iTrack) const { return (mConfig.matchMCLabe inline bool GPUQA::SuppressHit(int iHit) const { return (mConfig.matchMCLabels.size() && !mGoodHits[mNEvents - 1][iHit]); } inline int GPUQA::HitAttachStatus(int iHit) const { return (mClusterParam.size() && mClusterParam[iHit].fakeAttached ? (mClusterParam[iHit].attached ? 1 : 2) : 0); } -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/Array2D.h b/GPU/GPUTracking/TPCClusterFinder/Array2D.h index c25d4d2b210be..07964d4031c63 100644 --- a/GPU/GPUTracking/TPCClusterFinder/Array2D.h +++ b/GPU/GPUTracking/TPCClusterFinder/Array2D.h @@ -17,9 +17,7 @@ #include "clusterFinderDefs.h" #include "ChargePos.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { template <typename T, typename Layout> @@ -122,7 +120,6 @@ using TPCMapMemoryLayout = LinearLayout; template <typename T> using Array2D = AbstractArray2D<T, TPCMapMemoryLayout<T>>; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/CfFragment.h b/GPU/GPUTracking/TPCClusterFinder/CfFragment.h index 089c481b03913..2d1574a98ad34 100644 --- a/GPU/GPUTracking/TPCClusterFinder/CfFragment.h +++ b/GPU/GPUTracking/TPCClusterFinder/CfFragment.h @@ -17,9 +17,7 @@ #include "clusterFinderDefs.h" #include "GPUCommonMath.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { struct CfFragment { @@ -98,7 +96,6 @@ struct CfFragment { } }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/CfUtils.h b/GPU/GPUTracking/TPCClusterFinder/CfUtils.h index 183fc8ab3905d..b3cd7ab7eb059 100644 --- a/GPU/GPUTracking/TPCClusterFinder/CfUtils.h +++ b/GPU/GPUTracking/TPCClusterFinder/CfUtils.h @@ -20,9 +20,7 @@ #include "CfConsts.h" #include "GPUTPCClusterFinderKernels.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class CfUtils @@ -166,7 +164,6 @@ class CfUtils } }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h index c92169383f70c..40432943fa362 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.h @@ -21,17 +21,12 @@ #include "Array2D.h" #include "PackedCharge.h" -namespace o2 -{ -namespace tpc +namespace o2::tpc { class Digit; -} -} // namespace o2 +} // namespace o2::tpc -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { struct ChargePos; @@ -69,7 +64,6 @@ class GPUTPCCFChargeMapFiller : public GPUKernelTemplate static GPUd() size_t findTransition(int, const tpc::Digit*, size_t, size_t); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h index 5add50ee1a904..58ab6452ab604 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h @@ -21,15 +21,12 @@ #include "Array2D.h" #include "PackedCharge.h" -namespace GPUCA_NAMESPACE -{ - -namespace tpc +namespace o2::tpc { struct ClusterNative; -} +} // namespace o2::tpc -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class ClusterAccumulator; @@ -73,7 +70,6 @@ class GPUTPCCFClusterizer : public GPUKernelTemplate static GPUd() uint sortIntoBuckets(const tpc::ClusterNative&, uint, uint, uint*, tpc::ClusterNative*); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.h index 4833b630de7bb..602515675f7a0 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.h @@ -19,9 +19,7 @@ #include "GPUConstantMem.h" #include "DataFormatsTPC/ZeroSuppression.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCClusterFinder; @@ -62,7 +60,6 @@ class GPUTPCCFDecodeZS : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h index bc95cddba526e..d2af024ef221e 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h @@ -21,9 +21,7 @@ #include "Array2D.h" #include "PackedCharge.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCCFDeconvolution : public GPUKernelTemplate @@ -60,7 +58,6 @@ class GPUTPCCFDeconvolution : public GPUKernelTemplate static GPUdi() char countPeaksOuter(ushort, uchar, const uchar*); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFGather.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFGather.h index d6d4f83df1129..37dcb4eda0833 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFGather.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFGather.h @@ -17,9 +17,7 @@ #include "GPUGeneralKernels.h" #include "GPUConstantMem.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCClusterFinder; @@ -44,7 +42,6 @@ class GPUTPCCFGather : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.h index 79441b43c399b..23c4717af237a 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.h @@ -20,9 +20,7 @@ #include "GPUTPCClusterFinder.h" #include "GPUConstantMem.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { struct GPUTPCLinearLabels; @@ -58,7 +56,6 @@ class GPUTPCCFMCLabelFlattener : public GPUKernelTemplate static void setGlobalOffsetsAndAllocate(GPUTPCClusterFinder&, GPUTPCLinearLabels&); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h index 028363f007b07..a9a385203be20 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h @@ -21,9 +21,7 @@ #include "Array2D.h" #include "PackedCharge.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { struct ChargePos; @@ -74,7 +72,6 @@ class GPUTPCCFNoiseSuppression : public GPUKernelTemplate static GPUd() void findMinimaAndPeaks(const Array2D<PackedCharge>&, const Array2D<uchar>&, float, const ChargePos&, ChargePos*, PackedCharge*, ulong*, ulong*, ulong*); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h index 646e8c221ed69..f78945a43132b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h @@ -21,9 +21,7 @@ #include "Array2D.h" #include "PackedCharge.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { struct ChargePos; @@ -59,7 +57,6 @@ class GPUTPCCFPeakFinder : public GPUKernelTemplate static GPUd() bool isPeak(GPUSharedMemory&, tpccf::Charge, const ChargePos&, ushort, const Array2D<o2::gpu::PackedCharge>&, ChargePos*, PackedCharge*); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h index f817fdc13f5a5..2090b7835dab0 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h @@ -19,9 +19,7 @@ #include "GPUConstantMem.h" #include "GPUTPCClusterFinder.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCCFStreamCompaction : public GPUKernelTemplate @@ -76,7 +74,6 @@ class GPUTPCCFStreamCompaction : public GPUKernelTemplate static GPUd() int compactionElems(processorType& clusterer, int stage); }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index 3444899311a33..f50f357180f3b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -38,9 +38,7 @@ class Digit; } // namespace o2 -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { struct GPUTPCClusterMCInterim; @@ -140,7 +138,6 @@ class GPUTPCClusterFinder : public GPUProcessor #endif }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h index 641721ce9d999..ca52c15c69900 100644 --- a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h +++ b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h @@ -20,15 +20,13 @@ #include <bitset> #include <vector> -namespace GPUCA_NAMESPACE -{ -namespace dataformats +namespace o2::dataformats { template <typename T> class MCTruthContainer; -} +} // namespace o2::dataformats -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class GPUTPCClusterFinder; @@ -57,7 +55,6 @@ class MCLabelAccumulator std::vector<o2::MCCompLabel> mClusterLabels; }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/PackedCharge.h b/GPU/GPUTracking/TPCClusterFinder/PackedCharge.h index 64d8e71ba5816..e610508b1864b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/PackedCharge.h +++ b/GPU/GPUTracking/TPCClusterFinder/PackedCharge.h @@ -17,9 +17,7 @@ #include "clusterFinderDefs.h" #include "GPUCommonMath.h" -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace GPUCA_NAMESPACE::gpu { class PackedCharge @@ -57,7 +55,6 @@ class PackedCharge BasicType mVal; }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu #endif diff --git a/GPU/TPCFastTransformation/test/testSplines.cxx b/GPU/TPCFastTransformation/test/testSplines.cxx index 62cbcadb218a2..2774c7911fa14 100644 --- a/GPU/TPCFastTransformation/test/testSplines.cxx +++ b/GPU/TPCFastTransformation/test/testSplines.cxx @@ -19,9 +19,7 @@ #include "Spline1D.h" #include "Spline2D.h" -namespace o2 -{ -namespace gpu +namespace o2::gpu { /// @brief Basic test if we can create the interface @@ -36,5 +34,4 @@ BOOST_AUTO_TEST_CASE(Spline_test1) int err2 = s2.test(0); BOOST_CHECK_MESSAGE(err2 == 0, "test of GPU/TPCFastTransform/Spline2D failed with the error code " << err2); } -} // namespace gpu -} // namespace o2 +} // namespace o2::gpu From 01581309f9b36912f8304cd859af7607d2fc9ad9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 12:33:32 +0200 Subject: [PATCH 0466/1751] GPU: Fix AliRoot compilation --- GPU/Common/GPUCommonMath.h | 2 +- GPU/GPUTracking/Base/GPUDataTypes.h | 3 + GPU/GPUTracking/Base/GPUO2FakeClasses.h | 2 + GPU/GPUTracking/CMakeLists.txt | 1 + GPU/GPUTracking/Global/GPUChainTracking.cxx | 316 +++++++++--------- GPU/GPUTracking/Global/GPUChainTracking.h | 2 + .../GPUChainTrackingDebugAndProfiling.cxx | 2 + .../Merger/GPUTPCGMMergedTrackHit.h | 4 + GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 6 + 9 files changed, 173 insertions(+), 165 deletions(-) diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 866a1dd501f7c..873b0019f6978 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -473,7 +473,7 @@ GPUdi() void GPUCommonMath::AtomicMinInt(S* addr, T val) #endif // GPUCA_GPUCODE } -#if defined(__CUDACC__) || defined(__HIPCC__) +#if (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(__ROOTCINT__) && !defined(G__ROOT) #define GPUCA_HAVE_ATOMIC_MINMAX_FLOAT template <> GPUdii() void GPUCommonMath::AtomicMaxInt(GPUglobalref() GPUgeneric() GPUAtomic(float) * addr, float val) diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index aa866b024ebfa..6d8c8cbce5ed6 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -36,6 +36,9 @@ namespace tpc struct ClusterNativeAccess; struct CompressedClustersFlat; class Digit; +namespace constants +{ +} // namespace constants } // namespace tpc } // namespace o2 #endif diff --git a/GPU/GPUTracking/Base/GPUO2FakeClasses.h b/GPU/GPUTracking/Base/GPUO2FakeClasses.h index bdb625767a80f..c4e49ca52d612 100644 --- a/GPU/GPUTracking/Base/GPUO2FakeClasses.h +++ b/GPU/GPUTracking/Base/GPUO2FakeClasses.h @@ -99,6 +99,8 @@ class GPUTPCCompression class GPUTPCClusterFinder { }; +struct GPUTPCCFChainContext { +}; #ifndef __OPENCL__ struct GPUParam; class GPUTPCClusterStatistics diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index c6fd5c4ffac74..cd942a7adfd04 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -322,6 +322,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") ${CMAKE_SOURCE_DIR}/GPU/Common ${CMAKE_SOURCE_DIR}/GPU/Utils ${CMAKE_SOURCE_DIR}/GPU/GPUTracking + ${CMAKE_SOURCE_DIR}/GPU/GPUTracking/Standalone ${CMAKE_SOURCE_DIR}/GPU/GPUTracking/Base ${CMAKE_SOURCE_DIR}/GPU/GPUTracking/SliceTracker ${CMAKE_SOURCE_DIR}/GPU/GPUTracking/Merger diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index e4b8aa058bd6e..8d4489868b893 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -389,162 +389,6 @@ int GPUChainTracking::Init() return 0; } -std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCountUpdate(unsigned int iSlice, const CfFragment& fragment) -{ - bool doGPU = mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCClusterFinding; -#ifdef HAVE_O2HEADERS - GPUTPCClusterFinder& clusterer = processors()->tpcClusterer[iSlice]; - GPUTPCClusterFinder::ZSOffset* o = processors()->tpcClusterer[iSlice].mPzsOffsets; - unsigned int digits = 0; - unsigned short pages = 0; - for (unsigned short j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { - unsigned short posInEndpoint = 0; - unsigned short pagesEndpoint = 0; - clusterer.mMinMaxCN[j] = mCFContext->fragmentData[fragment.index].minMaxCN[iSlice][j]; - if (doGPU) { - for (unsigned int k = clusterer.mMinMaxCN[j].minC; k < clusterer.mMinMaxCN[j].maxC; k++) { - const unsigned int minL = (k == clusterer.mMinMaxCN[j].minC) ? clusterer.mMinMaxCN[j].minN : 0; - const unsigned int maxL = (k + 1 == clusterer.mMinMaxCN[j].maxC) ? clusterer.mMinMaxCN[j].maxN : mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]; - for (unsigned int l = minL; l < maxL; l++) { - unsigned short pageDigits = mCFContext->fragmentData[fragment.index].pageDigits[iSlice][j][posInEndpoint++]; - if (pageDigits) { - *(o++) = GPUTPCClusterFinder::ZSOffset{digits, j, pagesEndpoint}; - digits += pageDigits; - } - pagesEndpoint++; - } - } - pages += pagesEndpoint; - } else { - clusterer.mPzsOffsets[j] = GPUTPCClusterFinder::ZSOffset{digits, j, 0}; - digits += mCFContext->fragmentData[fragment.index].nDigits[iSlice][j]; - pages += mCFContext->fragmentData[fragment.index].nPages[iSlice][j]; - } - } - - return {digits, pages}; -#else - return {0, 0}; -#endif -} - -std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCount(unsigned int iSlice, const CfFragment& fragment) -{ - mRec->getGeneralStepTimer(GeneralStep::Prepare).Start(); - unsigned int nDigits = 0; - unsigned int nPages = 0; -#ifdef HAVE_O2HEADERS - bool doGPU = mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCClusterFinding; - int firstHBF = o2::raw::RDHUtils::getHeartBeatOrbit(*(const RAWDataHeaderGPU*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[0][0]); - - for (unsigned short j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { - for (unsigned int k = 0; k < mCFContext->nFragments; k++) { - mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxC = mIOPtrs.tpcZS->slice[iSlice].count[j]; - mCFContext->fragmentData[k].minMaxCN[iSlice][j].minC = mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxC; - mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxN = mIOPtrs.tpcZS->slice[iSlice].count[j] ? mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][mIOPtrs.tpcZS->slice[iSlice].count[j] - 1] : 0; - mCFContext->fragmentData[k].minMaxCN[iSlice][j].minN = mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxN; - } - -#ifndef GPUCA_NO_VC - if (GetProcessingSettings().prefetchTPCpageScan >= 3 && j < GPUTrackingInOutZS::NENDPOINTS - 1) { - for (unsigned int k = 0; k < mIOPtrs.tpcZS->slice[iSlice].count[j + 1]; k++) { - for (unsigned int l = 0; l < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j + 1][k]; l++) { - Vc::Common::prefetchMid(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j + 1][k]) + l * TPCZSHDR::TPC_ZS_PAGE_SIZE); - Vc::Common::prefetchMid(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j + 1][k]) + l * TPCZSHDR::TPC_ZS_PAGE_SIZE + sizeof(RAWDataHeaderGPU)); - } - } - } -#endif - - bool firstNextFound = false; - CfFragment f = fragment; - CfFragment fNext = f.next(); - bool firstSegment = true; - - for (unsigned int k = 0; k < mIOPtrs.tpcZS->slice[iSlice].count[j]; k++) { - for (unsigned int l = 0; l < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]; l++) { - if (f.isEnd()) { - GPUError("Time bin passed last fragment"); - return {0, 0}; - } -#ifndef GPUCA_NO_VC - if (GetProcessingSettings().prefetchTPCpageScan >= 2 && l + 1 < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]) { - Vc::Common::prefetchForOneRead(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + (l + 1) * TPCZSHDR::TPC_ZS_PAGE_SIZE); - Vc::Common::prefetchForOneRead(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + (l + 1) * TPCZSHDR::TPC_ZS_PAGE_SIZE + sizeof(RAWDataHeaderGPU)); - } -#endif - const unsigned char* const page = ((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + l * TPCZSHDR::TPC_ZS_PAGE_SIZE; - const RAWDataHeaderGPU* rdh = (const RAWDataHeaderGPU*)page; - if (o2::raw::RDHUtils::getMemorySize(*rdh) == sizeof(RAWDataHeaderGPU)) { - nPages++; - if (mCFContext->fragmentData[f.index].nPages[iSlice][j]) { - mCFContext->fragmentData[f.index].nPages[iSlice][j]++; - mCFContext->fragmentData[f.index].pageDigits[iSlice][j].emplace_back(0); - } - continue; - } - const TPCZSHDR* const hdr = (const TPCZSHDR*)(page + sizeof(RAWDataHeaderGPU)); - unsigned int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN; - for (unsigned int m = 0; m < 2; m++) { - CfFragment& fm = m ? fNext : f; - if (timeBin + hdr->nTimeBins >= (unsigned int)fm.first() && timeBin < (unsigned int)fm.last() && !fm.isEnd()) { - mCFContext->fragmentData[fm.index].nPages[iSlice][j]++; - mCFContext->fragmentData[fm.index].nDigits[iSlice][j] += hdr->nADCsamples; - if (doGPU) { - mCFContext->fragmentData[fm.index].pageDigits[iSlice][j].emplace_back(hdr->nADCsamples); - } - } - } - if (firstSegment && timeBin + hdr->nTimeBins >= (unsigned int)f.first()) { - mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].minC = k; - mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].minN = l; - firstSegment = false; - } - if (!firstNextFound && timeBin + hdr->nTimeBins >= (unsigned int)fNext.first() && !fNext.isEnd()) { - mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minC = k; - mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minN = l; - firstNextFound = true; - } - while (!f.isEnd() && timeBin >= (unsigned int)f.last()) { - if (!firstNextFound && !fNext.isEnd()) { - mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minC = k; - mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minN = l; - } - mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].maxC = k + 1; - mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].maxN = l; - f = fNext; - fNext = f.next(); - firstNextFound = false; - } - if (timeBin + hdr->nTimeBins > mCFContext->tpcMaxTimeBin) { - mCFContext->tpcMaxTimeBin = timeBin + hdr->nTimeBins; - } - - nPages++; - nDigits += hdr->nADCsamples; - } - } - } -#endif - mCFContext->nPagesTotal += nPages; - mCFContext->nPagesSector[iSlice] = nPages; - mCFContext->nPagesSectorMax = std::max(mCFContext->nPagesSectorMax, nPages); - - unsigned int digitsFragment = 0; - for (unsigned int i = 0; i < mCFContext->nFragments; i++) { - unsigned int pages = 0; - unsigned int digits = 0; - for (unsigned short j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { - pages += mCFContext->fragmentData[i].nPages[iSlice][j]; - digits += mCFContext->fragmentData[i].nDigits[iSlice][j]; - } - mCFContext->nPagesFragmentMax = std::max(mCFContext->nPagesSectorMax, pages); - digitsFragment = std::max(digitsFragment, digits); - } - mRec->getGeneralStepTimer(GeneralStep::Prepare).Stop(); - return {nDigits, digitsFragment}; -} - int GPUChainTracking::PrepareEvent() { mRec->MemoryScalers()->nTRDTracklets = mIOPtrs.nTRDTracklets; @@ -863,9 +707,159 @@ int GPUChainTracking::GlobalTracking(unsigned int iSlice, int threadId, bool syn return (0); } +#ifdef GPUCA_TPC_GEOMETRY_O2 +std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCountUpdate(unsigned int iSlice, const CfFragment& fragment) +{ + bool doGPU = mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCClusterFinding; + GPUTPCClusterFinder& clusterer = processors()->tpcClusterer[iSlice]; + GPUTPCClusterFinder::ZSOffset* o = processors()->tpcClusterer[iSlice].mPzsOffsets; + unsigned int digits = 0; + unsigned short pages = 0; + for (unsigned short j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { + unsigned short posInEndpoint = 0; + unsigned short pagesEndpoint = 0; + clusterer.mMinMaxCN[j] = mCFContext->fragmentData[fragment.index].minMaxCN[iSlice][j]; + if (doGPU) { + for (unsigned int k = clusterer.mMinMaxCN[j].minC; k < clusterer.mMinMaxCN[j].maxC; k++) { + const unsigned int minL = (k == clusterer.mMinMaxCN[j].minC) ? clusterer.mMinMaxCN[j].minN : 0; + const unsigned int maxL = (k + 1 == clusterer.mMinMaxCN[j].maxC) ? clusterer.mMinMaxCN[j].maxN : mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]; + for (unsigned int l = minL; l < maxL; l++) { + unsigned short pageDigits = mCFContext->fragmentData[fragment.index].pageDigits[iSlice][j][posInEndpoint++]; + if (pageDigits) { + *(o++) = GPUTPCClusterFinder::ZSOffset{digits, j, pagesEndpoint}; + digits += pageDigits; + } + pagesEndpoint++; + } + } + pages += pagesEndpoint; + } else { + clusterer.mPzsOffsets[j] = GPUTPCClusterFinder::ZSOffset{digits, j, 0}; + digits += mCFContext->fragmentData[fragment.index].nDigits[iSlice][j]; + pages += mCFContext->fragmentData[fragment.index].nPages[iSlice][j]; + } + } + + return {digits, pages}; +} + +std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCount(unsigned int iSlice, const CfFragment& fragment) +{ + mRec->getGeneralStepTimer(GeneralStep::Prepare).Start(); + unsigned int nDigits = 0; + unsigned int nPages = 0; + bool doGPU = mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCClusterFinding; + int firstHBF = o2::raw::RDHUtils::getHeartBeatOrbit(*(const RAWDataHeaderGPU*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[0][0]); + + for (unsigned short j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { + for (unsigned int k = 0; k < mCFContext->nFragments; k++) { + mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxC = mIOPtrs.tpcZS->slice[iSlice].count[j]; + mCFContext->fragmentData[k].minMaxCN[iSlice][j].minC = mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxC; + mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxN = mIOPtrs.tpcZS->slice[iSlice].count[j] ? mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][mIOPtrs.tpcZS->slice[iSlice].count[j] - 1] : 0; + mCFContext->fragmentData[k].minMaxCN[iSlice][j].minN = mCFContext->fragmentData[k].minMaxCN[iSlice][j].maxN; + } + +#ifndef GPUCA_NO_VC + if (GetProcessingSettings().prefetchTPCpageScan >= 3 && j < GPUTrackingInOutZS::NENDPOINTS - 1) { + for (unsigned int k = 0; k < mIOPtrs.tpcZS->slice[iSlice].count[j + 1]; k++) { + for (unsigned int l = 0; l < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j + 1][k]; l++) { + Vc::Common::prefetchMid(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j + 1][k]) + l * TPCZSHDR::TPC_ZS_PAGE_SIZE); + Vc::Common::prefetchMid(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j + 1][k]) + l * TPCZSHDR::TPC_ZS_PAGE_SIZE + sizeof(RAWDataHeaderGPU)); + } + } + } +#endif + + bool firstNextFound = false; + CfFragment f = fragment; + CfFragment fNext = f.next(); + bool firstSegment = true; + + for (unsigned int k = 0; k < mIOPtrs.tpcZS->slice[iSlice].count[j]; k++) { + for (unsigned int l = 0; l < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]; l++) { + if (f.isEnd()) { + GPUError("Time bin passed last fragment"); + return {0, 0}; + } +#ifndef GPUCA_NO_VC + if (GetProcessingSettings().prefetchTPCpageScan >= 2 && l + 1 < mIOPtrs.tpcZS->slice[iSlice].nZSPtr[j][k]) { + Vc::Common::prefetchForOneRead(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + (l + 1) * TPCZSHDR::TPC_ZS_PAGE_SIZE); + Vc::Common::prefetchForOneRead(((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + (l + 1) * TPCZSHDR::TPC_ZS_PAGE_SIZE + sizeof(RAWDataHeaderGPU)); + } +#endif + const unsigned char* const page = ((const unsigned char*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[j][k]) + l * TPCZSHDR::TPC_ZS_PAGE_SIZE; + const RAWDataHeaderGPU* rdh = (const RAWDataHeaderGPU*)page; + if (o2::raw::RDHUtils::getMemorySize(*rdh) == sizeof(RAWDataHeaderGPU)) { + nPages++; + if (mCFContext->fragmentData[f.index].nPages[iSlice][j]) { + mCFContext->fragmentData[f.index].nPages[iSlice][j]++; + mCFContext->fragmentData[f.index].pageDigits[iSlice][j].emplace_back(0); + } + continue; + } + const TPCZSHDR* const hdr = (const TPCZSHDR*)(page + sizeof(RAWDataHeaderGPU)); + unsigned int timeBin = (hdr->timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN; + for (unsigned int m = 0; m < 2; m++) { + CfFragment& fm = m ? fNext : f; + if (timeBin + hdr->nTimeBins >= (unsigned int)fm.first() && timeBin < (unsigned int)fm.last() && !fm.isEnd()) { + mCFContext->fragmentData[fm.index].nPages[iSlice][j]++; + mCFContext->fragmentData[fm.index].nDigits[iSlice][j] += hdr->nADCsamples; + if (doGPU) { + mCFContext->fragmentData[fm.index].pageDigits[iSlice][j].emplace_back(hdr->nADCsamples); + } + } + } + if (firstSegment && timeBin + hdr->nTimeBins >= (unsigned int)f.first()) { + mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].minC = k; + mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].minN = l; + firstSegment = false; + } + if (!firstNextFound && timeBin + hdr->nTimeBins >= (unsigned int)fNext.first() && !fNext.isEnd()) { + mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minC = k; + mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minN = l; + firstNextFound = true; + } + while (!f.isEnd() && timeBin >= (unsigned int)f.last()) { + if (!firstNextFound && !fNext.isEnd()) { + mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minC = k; + mCFContext->fragmentData[fNext.index].minMaxCN[iSlice][j].minN = l; + } + mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].maxC = k + 1; + mCFContext->fragmentData[f.index].minMaxCN[iSlice][j].maxN = l; + f = fNext; + fNext = f.next(); + firstNextFound = false; + } + if (timeBin + hdr->nTimeBins > mCFContext->tpcMaxTimeBin) { + mCFContext->tpcMaxTimeBin = timeBin + hdr->nTimeBins; + } + + nPages++; + nDigits += hdr->nADCsamples; + } + } + } + mCFContext->nPagesTotal += nPages; + mCFContext->nPagesSector[iSlice] = nPages; + mCFContext->nPagesSectorMax = std::max(mCFContext->nPagesSectorMax, nPages); + + unsigned int digitsFragment = 0; + for (unsigned int i = 0; i < mCFContext->nFragments; i++) { + unsigned int pages = 0; + unsigned int digits = 0; + for (unsigned short j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { + pages += mCFContext->fragmentData[i].nPages[iSlice][j]; + digits += mCFContext->fragmentData[i].nDigits[iSlice][j]; + } + mCFContext->nPagesFragmentMax = std::max(mCFContext->nPagesSectorMax, pages); + digitsFragment = std::max(digitsFragment, digits); + } + mRec->getGeneralStepTimer(GeneralStep::Prepare).Stop(); + return {nDigits, digitsFragment}; +} + void GPUChainTracking::RunTPCClusterizer_compactPeaks(GPUTPCClusterFinder& clusterer, GPUTPCClusterFinder& clustererShadow, int stage, bool doGPU, int lane) { -#ifdef HAVE_O2HEADERS auto& in = stage ? clustererShadow.mPpeakPositions : clustererShadow.mPpositions; auto& out = stage ? clustererShadow.mPfilteredPeakPositions : clustererShadow.mPpeakPositions; if (doGPU) { @@ -912,12 +906,10 @@ void GPUChainTracking::RunTPCClusterizer_compactPeaks(GPUTPCClusterFinder& clust } nOut = count; } -#endif } std::pair<unsigned int, unsigned int> GPUChainTracking::RunTPCClusterizer_transferZS(int iSlice, const CfFragment& fragment, int lane) { -#ifdef GPUCA_TPC_GEOMETRY_O2 bool doGPU = GetRecoStepsGPU() & RecoStep::TPCClusterFinding; const auto& retVal = TPCClusterizerDecodeZSCountUpdate(iSlice, fragment); if (doGPU) { @@ -947,14 +939,10 @@ std::pair<unsigned int, unsigned int> GPUChainTracking::RunTPCClusterizer_transf GPUMemCpy(RecoStep::TPCClusterFinding, clustererShadow.mPzsOffsets, clusterer.mPzsOffsets, clusterer.mNMaxPages * sizeof(*clusterer.mPzsOffsets), lane, true); } return retVal; -#else - return {0, 0}; -#endif } int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) { -#ifdef GPUCA_TPC_GEOMETRY_O2 if (restorePointers) { for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { processors()->tpcClusterer[iSlice].mPzsOffsets = mCFContext->ptrSave[iSlice].zsOffsetHost; @@ -1040,9 +1028,9 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) mCFContext->ptrSave[iSlice].zsDevice = processorsShadow()->tpcClusterer[iSlice].mPzs; } } -#endif return 0; } +#endif int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 9e2ff5ff55b55..b296c16136ae2 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -256,10 +256,12 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega int RunChainFinalize(); int RunTPCTrackingSlices_internal(); int RunTPCClusterizer_prepare(bool restorePointers); +#ifdef GPUCA_TPC_GEOMETRY_O2 std::pair<unsigned int, unsigned int> RunTPCClusterizer_transferZS(int iSlice, const CfFragment& fragment, int lane); void RunTPCClusterizer_compactPeaks(GPUTPCClusterFinder& clusterer, GPUTPCClusterFinder& clustererShadow, int stage, bool doGPU, int lane); std::pair<unsigned int, unsigned int> TPCClusterizerDecodeZSCount(unsigned int iSlice, const CfFragment& fragment); std::pair<unsigned int, unsigned int> TPCClusterizerDecodeZSCountUpdate(unsigned int iSlice, const CfFragment& fragment); +#endif void RunTPCTrackingMerger_MergeBorderTracks(char withinSlice, char mergeMode, GPUReconstruction::krnlDeviceType deviceType); void RunTPCTrackingMerger_Resolve(char useOrigTrackParam, char mergeAll, GPUReconstruction::krnlDeviceType deviceType); diff --git a/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx b/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx index d15ae64a01904..c853a02bc82da 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx @@ -135,8 +135,10 @@ void GPUChainTracking::PrintMemoryStatistics() { std::map<std::string, GPUChainTrackingMemUsage> usageMap; for (int i = 0; i < NSLICES; i++) { +#ifdef GPUCA_TPC_GEOMETRY_O2 addToMap("TPC Clusterer Sector Peaks", usageMap, processors()->tpcClusterer[i].mPmemory->counters.nPeaks, processors()->tpcClusterer[i].mNMaxPeaks); addToMap("TPC Clusterer Sector Clusters", usageMap, processors()->tpcClusterer[i].mPmemory->counters.nClusters, processors()->tpcClusterer[i].mNMaxClusters); +#endif addToMap("TPC Start Hits", usageMap, *processors()->tpcTrackers[i].NStartHits(), processors()->tpcTrackers[i].NMaxStartHits()); addToMap("TPC Tracklets", usageMap, *processors()->tpcTrackers[i].NTracklets(), processors()->tpcTrackers[i].NMaxTracklets()); addToMap("TPC TrackletHits", usageMap, *processors()->tpcTrackers[i].NRowHits(), processors()->tpcTrackers[i].NMaxRowHits()); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergedTrackHit.h b/GPU/GPUTracking/Merger/GPUTPCGMMergedTrackHit.h index ebfef2c40f508..50cc8ac2e9412 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergedTrackHit.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergedTrackHit.h @@ -23,6 +23,10 @@ namespace gpu struct GPUTPCGMMergedTrackHit { unsigned int num; unsigned char slice, row, leg, state; +#ifdef GPUCA_ALIROOT_LIB + float x, y, z; + unsigned short amp; +#endif // NOTE: the lower states must match those from ClusterNative! enum hitState { flagSplitPad = 0x1, diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 72b1088445755..df3d27498ec94 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -1634,6 +1634,12 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int i const ClusterNative& c = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[trackClusters[i].id]; state = c.getFlags(); } +#ifdef GPUCA_ALIROOT_LIB + cl[i].x = clXYZ[i].x; + cl[i].y = clXYZ[i].y; + cl[i].z = clXYZ[i].z; + cl[i].amp = clXYZ[i].amp; +#endif cl[i].state = state & GPUTPCGMMergedTrackHit::clustererAndSharedFlags; // Only allow edge, deconvoluted, and shared flags cl[i].row = trackClusters[i].row; if (!Param().rec.NonConsecutiveIDs) // We already have global consecutive numbers from the slice tracker, and we need to keep them for late cluster attachment From f14298a0b2daa4ff490371f0e43d7672ac289948 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Thu, 27 Aug 2020 08:45:12 +0200 Subject: [PATCH 0467/1751] Streamlining run2 and run3 collision - table matching (#4217) --- Analysis/Tasks/CMakeLists.txt | 10 ++ Analysis/Tasks/run2Matcher.cxx | 35 +++++++ Analysis/Tasks/run3Matcher.cxx | 36 +++++++ Analysis/Tutorials/CMakeLists.txt | 9 +- Analysis/Tutorials/src/ZDCVZeroIteration.cxx | 95 +++++++++++++++++++ Analysis/Tutorials/src/custom_index.cxx | 75 --------------- .../include/Framework/AnalysisDataModel.h | 29 +++++- 7 files changed, 205 insertions(+), 84 deletions(-) create mode 100644 Analysis/Tasks/run2Matcher.cxx create mode 100644 Analysis/Tasks/run3Matcher.cxx create mode 100644 Analysis/Tutorials/src/ZDCVZeroIteration.cxx delete mode 100644 Analysis/Tutorials/src/custom_index.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 393b627805be5..a7538c8af9795 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -132,3 +132,13 @@ o2_add_dpl_workflow(weak-decay-indices SOURCES weakDecayIndices.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(run2-matcher + SOURCES run2Matcher.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(run3-matcher + SOURCES run3Matcher.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/run2Matcher.cxx b/Analysis/Tasks/run2Matcher.cxx new file mode 100644 index 0000000000000..e5ba8984f44d5 --- /dev/null +++ b/Analysis/Tasks/run2Matcher.cxx @@ -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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +// This task prepares the matching between collisions and other tables available +// in run2 converted data through the bc column. +// For an example how to use this, please see: o2-analysistutorial-zdc-vzero-iteration + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct Run2Matcher { + Builds<aod::Run2MatchedExclusive> matched_e; + Builds<aod::Run2MatchedSparse> matched_s; + void init(o2::framework::InitContext&) + { + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<Run2Matcher>("produce-run2-bc-matching"), + }; +} diff --git a/Analysis/Tasks/run3Matcher.cxx b/Analysis/Tasks/run3Matcher.cxx new file mode 100644 index 0000000000000..f9a798a1bd973 --- /dev/null +++ b/Analysis/Tasks/run3Matcher.cxx @@ -0,0 +1,36 @@ +// 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" + +// This task prepares the matching between collisions and other tables available +// in run 3 data. +// For an example how to use this (but based on run 2 data), +// please see: o2-analysistutorial-zdc-vzero-iteration + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct Run3Matcher { + Builds<aod::Run3MatchedExclusive> matched_e; + Builds<aod::Run3MatchedSparse> matched_s; + void init(o2::framework::InitContext&) + { + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<Run3Matcher>("produce-run3-bc-matching"), + }; +} diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index d7a19c1eeca35..e660dbf25ba32 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -107,11 +107,10 @@ o2_add_dpl_workflow(ccdbaccess PUBLIC_LINK_LIBRARIES O2::AnalysisCore O2::CCDB O2::Framework O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) -o2_add_dpl_workflow(custom-index - SOURCES src/custom_index.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel - COMPONENT_NAME AnalysisTutorial) - o2_add_dpl_workflow(weak-decay-iteration SOURCES src/weakDecayIteration.cxx COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(zdc-vzero-iteration + SOURCES src/ZDCVZeroIteration.cxx + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx new file mode 100644 index 0000000000000..954e53b2eff09 --- /dev/null +++ b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx @@ -0,0 +1,95 @@ +// 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" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// This task shows how to access the ZDC and the Run2 V0 information which belongs to a collision +// The association is made through the BC column (and in Run 3 may not be unique!) +// To run this workflow, the o2-analysis-run2-matcher has to be run as well. +// Example: o2-analysis-run2-matcher --aod-file AO2D.root | o2-analysistutorial-zdc-vzero-iteration + +// This example access the collisions and the related Run2V0 information. +// Note that one has to subscribe to aod::Collisions const& and aod::Run2V0s const& to load +// the relevant data even if you access the data itself through m.collision() and m.run2v0() +// Here the "sparse" matcher is used which means, there can be collisions without Run2V0 information +// To find out, m.has_run2v0() has to be called. Otherwise m.run2v0() will fail. +struct IterateV0 { + void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::Run2V0s const&) + { + LOGF(INFO, "Vertex = %f", m.collision().posZ()); + if (m.has_run2v0()) { + auto v0 = m.run2v0(); + LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + } else { + LOGF(INFO, "No V0 info"); + } + } +}; + +// This example is identical to IterateV0, but uses the exclusive match. This means that lines where any +// of the tables asked for in Run2MatchedExclusive (see AnalysisDataModel.h) are missing are not listed. +// Only to be used if one is sure that all your events have the desired information +struct IterateV0Exclusive { + void process(aod::Run2MatchedExclusive::iterator const& m, aod::Collisions const&, aod::Run2V0s const&) + { + LOGF(INFO, "Vertex = %f", m.collision().posZ()); + auto v0 = m.run2v0(); + LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + } +}; + +// This example builds on IterateV0 and in addition accesses also the tracks grouped to the specific collision. +// The tracks are directly access through its pointer. +struct IterateV0Tracks { + void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::Run2V0s const&, aod::Tracks const& tracks) + { + LOGF(INFO, "Vertex = %f. %d tracks", m.collision().posZ(), tracks.size()); + if (m.has_run2v0()) { + auto v0 = m.run2v0(); + LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + } else { + LOGF(INFO, "No V0 info"); + } + } +}; + +// This example accesses V0 and ZDC information +struct IterateV0ZDC { + void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::Run2V0s const&, aod::Zdcs const&) + { + LOGF(INFO, "Vertex = %f", m.collision().posZ()); + if (m.has_run2v0()) { + auto v0 = m.run2v0(); + LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + } else { + LOGF(INFO, "No V0 info"); + } + if (m.has_zdc()) { + LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", m.zdc().energyZEM1(), m.zdc().energyZEM2()); + } else { + LOGF(INFO, "No ZDC info"); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<IterateV0>("iterate-v0"), + adaptAnalysisTask<IterateV0Exclusive>("iterate-v0-exclusive"), + adaptAnalysisTask<IterateV0Tracks>("iterate-v0-tracks"), + adaptAnalysisTask<IterateV0ZDC>("iterate-v0-zdc"), + }; +} diff --git a/Analysis/Tutorials/src/custom_index.cxx b/Analysis/Tutorials/src/custom_index.cxx deleted file mode 100644 index 53049a86e2d3f..0000000000000 --- a/Analysis/Tutorials/src/custom_index.cxx +++ /dev/null @@ -1,75 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - -namespace o2::aod -{ -namespace indices -{ -DECLARE_SOA_INDEX_COLUMN(BC, bc); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -DECLARE_SOA_INDEX_COLUMN(Zdc, zdc); -} // namespace indices - -DECLARE_SOA_INDEX_TABLE(MatchedExclusive, BCs, "MATCHED", indices::CollisionId, indices::BCId, indices::ZdcId); -DECLARE_SOA_INDEX_TABLE(MatchedSparse, BCs, "MATCHED", indices::CollisionId, indices::BCId, indices::ZdcId); -} // namespace o2::aod - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -// This is a very simple example showing how to iterate over tracks -// and create a new collection for them. -// FIXME: this should really inherit from AnalysisTask but -// we need GCC 7.4+ for that -struct ATask { - Builds<aod::MatchedExclusive> matched_e; - Builds<aod::MatchedSparse> matched_s; - void init(o2::framework::InitContext&) - { - } -}; - -struct BTask { - void process(aod::MatchedExclusive::iterator const& m, aod::Zdcs const&, aod::Tracks const& tracks) - { - LOGF(INFO, "Collision %d; Ntrk: %d", m.collisionId(), tracks.size()); - LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", m.zdc().energyZEM1(), m.zdc().energyZEM2()); - auto t1 = tracks.begin(); - auto t2 = t1 + (tracks.size() - 1); - LOGF(INFO, "track 1 from %d; track %d from %d", t1.collisionId(), tracks.size(), t2.collisionId()); - } -}; - -struct CTask { - void process(aod::MatchedSparse::iterator const& m, aod::Zdcs const&, aod::Tracks const& tracks) - { - LOGF(INFO, "Collision %d; Ntrk: %d", m.collisionId(), tracks.size()); - if (m.has_zdc()) { - LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", m.zdc().energyZEM1(), m.zdc().energyZEM2()); - } else { - LOGF(INFO, "No ZDC info"); - } - auto t1 = tracks.begin(); - auto t2 = t1 + (tracks.size() - 1); - LOGF(INFO, "track 1 from %d; track %d from %d", t1.collisionId(), tracks.size(), t2.collisionId()); - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<ATask>("produce-index"), - adaptAnalysisTask<BTask>("consume-index-exclusive"), - adaptAnalysisTask<CTask>("consume-index-sparse")}; -} diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 512366648ccc2..8b84781a09d23 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -409,7 +409,7 @@ DECLARE_SOA_COLUMN(TimeC, timeC, float); DECLARE_SOA_COLUMN(BCSignal, triggerSignal, uint8_t); } // namespace ft0 -DECLARE_SOA_TABLE(FT0s, "AOD", "FT0", ft0::BCId, +DECLARE_SOA_TABLE(FT0s, "AOD", "FT0", o2::soa::Index<>, ft0::BCId, ft0::Amplitude, ft0::TimeA, ft0::TimeC, ft0::BCSignal); using FT0 = FT0s::iterator; @@ -422,7 +422,7 @@ DECLARE_SOA_COLUMN(TimeA, timeA, float); DECLARE_SOA_COLUMN(BCSignal, triggerSignal, uint8_t); } // namespace fv0 -DECLARE_SOA_TABLE(FV0s, "AOD", "FV0", fv0::BCId, +DECLARE_SOA_TABLE(FV0s, "AOD", "FV0", o2::soa::Index<>, fv0::BCId, fv0::Amplitude, fv0::TimeA, fv0::BCSignal); using FV0 = FV0s::iterator; @@ -435,7 +435,7 @@ DECLARE_SOA_COLUMN(TimeC, timeC, float); DECLARE_SOA_COLUMN(BCSignal, triggerSignal, uint8_t); } // namespace fdd -DECLARE_SOA_TABLE(FDDs, "AOD", "FDD", fdd::BCId, +DECLARE_SOA_TABLE(FDDs, "AOD", "FDD", o2::soa::Index<>, fdd::BCId, fdd::Amplitude, fdd::TimeA, fdd::TimeC, fdd::BCSignal); using FDD = FDDs::iterator; @@ -482,7 +482,7 @@ DECLARE_SOA_COLUMN(BBFlag, bbFlag, uint64_t); DECLARE_SOA_COLUMN(BGFlag, bgFlag, uint64_t); } // namespace run2v0 -DECLARE_SOA_TABLE(Run2V0s, "AOD", "RUN2V0", run2v0::BCId, +DECLARE_SOA_TABLE(Run2V0s, "AOD", "RUN2V0", o2::soa::Index<>, run2v0::BCId, run2v0::Adc, run2v0::Time, run2v0::Width, run2v0::MultA, run2v0::MultC, run2v0::TimeA, run2v0::TimeC, @@ -584,6 +584,27 @@ DECLARE_SOA_TABLE(McCollisionLabels, "AOD", "MCCOLLISLABEL", mccollisionlabel::LabelId, mccollisionlabel::LabelMask); using McCollisionLabel = McCollisionLabels::iterator; +// --- Matching between collisions and other tables through BC --- + +namespace indices +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_INDEX_COLUMN(BC, bc); +DECLARE_SOA_INDEX_COLUMN(Zdc, zdc); +DECLARE_SOA_INDEX_COLUMN(FT0, ft0); +DECLARE_SOA_INDEX_COLUMN(FV0, fv0); +DECLARE_SOA_INDEX_COLUMN(FDD, fdd); +DECLARE_SOA_INDEX_COLUMN(Run2V0, run2v0); +} // namespace indices + +#define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::Run2V0Id +DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MATCHED", INDEX_LIST_RUN2); +DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MATCHED", INDEX_LIST_RUN2); + +#define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0Id, indices::FDDId +DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MATCHED", INDEX_LIST_RUN3); +DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MATCHED", INDEX_LIST_RUN3); + } // namespace aod } // namespace o2 From c3c1e5916540f63f417f9dd41cef6889dc1bf741 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Thu, 27 Aug 2020 08:45:41 +0200 Subject: [PATCH 0468/1751] sanity check in weak decay indexer (#4218) --- Analysis/Tasks/weakDecayIndices.cxx | 25 ++++++++++++++++--- Analysis/Tutorials/src/weakDecayIteration.cxx | 9 ++++--- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Analysis/Tasks/weakDecayIndices.cxx b/Analysis/Tasks/weakDecayIndices.cxx index 3aa244a343ae6..10890bea7bf09 100644 --- a/Analysis/Tasks/weakDecayIndices.cxx +++ b/Analysis/Tasks/weakDecayIndices.cxx @@ -14,16 +14,32 @@ using namespace o2; using namespace o2::framework; -struct ATask { +// Tasks to build transient indices to group V0s and cascades to collisions + +struct IndexV0s { Produces<aod::TransientV0s> transientV0s; - Produces<aod::TransientCascades> transientCascades; - void process(aod::StoredV0s const& v0s, aod::StoredCascades const& cascades, aod::FullTracks const& tracks) + void process(aod::StoredV0s const& v0s, aod::FullTracks const& tracks) { for (auto& v0 : v0s) { + if (v0.posTrack().collisionId() != v0.negTrack().collisionId()) { + LOGF(WARNING, "V0 %d has inconsistent collision information (%d, %d)", v0.globalIndex(), v0.posTrack().collisionId(), v0.negTrack().collisionId()); + } transientV0s(v0.posTrack().collisionId()); } + } +}; + +// NOTE These tasks have to be split because for the cascades, V0s and not StoredV0s are needed +struct IndexCascades { + Produces<aod::TransientCascades> transientCascades; + + void process(aod::V0s const& v0s, aod::StoredCascades const& cascades, aod::FullTracks const& tracks) + { for (auto& cascade : cascades) { + if (cascade.bachelor().collisionId() != cascade.v0().posTrack().collisionId() || cascade.v0().posTrack().collisionId() != cascade.v0().negTrack().collisionId()) { + LOGF(WARNING, "Cascade %d has inconsistent collision information (%d, %d, %d)", cascade.globalIndex(), cascade.bachelor().collisionId(), cascade.v0().posTrack().collisionId(), cascade.v0().negTrack().collisionId()); + } transientCascades(cascade.bachelor().collisionId()); } } @@ -32,6 +48,7 @@ struct ATask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<ATask>("weak-decay-indices"), + adaptAnalysisTask<IndexV0s>("weak-decay-indices-v0"), + adaptAnalysisTask<IndexCascades>("weak-decay-indices-cascades"), }; } diff --git a/Analysis/Tutorials/src/weakDecayIteration.cxx b/Analysis/Tutorials/src/weakDecayIteration.cxx index c5cb393c2a460..ad350d7407c80 100644 --- a/Analysis/Tutorials/src/weakDecayIteration.cxx +++ b/Analysis/Tutorials/src/weakDecayIteration.cxx @@ -28,10 +28,10 @@ struct BTask { }; struct CTask { - void process(aod::Cascades const& cascades, aod::FullTracks const& tracks) + void process(aod::Cascades const& cascades, aod::V0s const& v0s, aod::FullTracks const& tracks) { for (auto& cascade : cascades) { - LOGF(DEBUG, "Cascade (%d, %d)", cascade.bachelor().collisionId(), cascade.collisionId()); + LOGF(DEBUG, "Cascade %d (%d, %d, %d, %d)", cascade.globalIndex(), cascade.bachelor().collisionId(), cascade.v0().posTrack().collisionId(), cascade.v0().negTrack().collisionId(), cascade.collisionId()); } } }; @@ -53,10 +53,11 @@ struct DTask { struct ETask { void process(aod::Collision const& collision, aod::V0s const& v0s, aod::Cascades const& cascades, aod::FullTracks const& tracks) { - LOGF(INFO, "Collision %d has %d cascades", collision.globalIndex(), cascades.size()); + LOGF(INFO, "Collision %d has %d cascades (%d tracks)", collision.globalIndex(), cascades.size(), tracks.size()); for (auto& cascade : cascades) { - LOGF(DEBUG, "Collision %d Cascade %d (%d, %d, %d)", collision.globalIndex(), cascade.globalIndex(), cascade.v0().posTrackId(), cascade.v0().negTrackId(), cascade.bachelorId()); + LOGF(INFO, "Collision %d Cascade %d (%d, %d, %d)", collision.globalIndex(), cascade.globalIndex(), cascade.v0().posTrackId(), cascade.v0().negTrackId(), cascade.bachelorId()); + LOGF(INFO, " IDs: %d %d %d", cascade.v0().posTrack().collisionId(), cascade.v0().negTrack().collisionId(), cascade.bachelor().collisionId()); } } }; From be31e3962d67c0acfadb626342aea4c846f28e84 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Thu, 27 Aug 2020 08:45:56 +0200 Subject: [PATCH 0469/1751] moving to expression columns (#4219) --- Analysis/Tasks/correlationsCollection.cxx | 105 ++++++---------------- 1 file changed, 28 insertions(+), 77 deletions(-) diff --git a/Analysis/Tasks/correlationsCollection.cxx b/Analysis/Tasks/correlationsCollection.cxx index fb61687e217a3..874c21efcd45f 100644 --- a/Analysis/Tasks/correlationsCollection.cxx +++ b/Analysis/Tasks/correlationsCollection.cxx @@ -21,49 +21,17 @@ #include <cmath> #include <TDirectory.h> -namespace o2::aod -{ -namespace etaphi -{ -DECLARE_SOA_COLUMN(Etam, etam, float); -DECLARE_SOA_COLUMN(Phim, phim, float); -DECLARE_SOA_COLUMN(Ptm, ptm, float); -} // namespace etaphi -DECLARE_SOA_TABLE(EtaPhi, "AOD", "ETAPHI", - etaphi::Etam, etaphi::Phim, etaphi::Ptm); -} // namespace o2::aod - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct ATask { - Produces<aod::EtaPhi> etaphi; - - void process(aod::Tracks const& tracks) - { - for (auto& track : tracks) { - float eta = log(tan(0.25f * static_cast<float>(M_PI) - 0.5f * atan(track.tgl()))); - float phi = asin(track.snp()) + track.alpha() + static_cast<float>(M_PI); - float pt = fabs(1.0f / track.signed1Pt()); - - etaphi(eta, phi, pt); - } - } -}; - #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP}; struct CorrelationTask { // Filters and input definitions -#define MYFILTER -#ifdef MYFILTER - Filter trackFilter = (aod::etaphi::etam > -0.8f) && (aod::etaphi::etam < 0.8f) && (aod::etaphi::ptm > 1.0f); - using myTracks = soa::Filtered<soa::Join<aod::Tracks, aod::EtaPhi>>; -#else - using myTracks = soa::Join<aod::Tracks, aod::EtaPhi>; -#endif + Filter trackFilter = (aod::track::eta > -0.8f) && (aod::track::eta < 0.8f) && (aod::track::pt > 1.0f); + using myTracks = soa::Filtered<aod::Tracks>; // Output definitions OutputObj<CorrelationContainer> same{"sameEvent"}; @@ -141,9 +109,6 @@ struct CorrelationTask { void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, aod::BCs const& bcs, aod::Run2V0s const& vzeros, myTracks const& tracks) { LOGF(info, "Tracks for collision: %d | Trigger mask: %lld | INT7: %d | V0M: %.1f", tracks.size(), collision.bc().triggerMask(), collision.sel7(), collision.centV0M()); - // for (auto& vzero : vzeros) - // if (vzero.bc() == collision.bc()) - // LOGF(info, "V0: %f %f", vzero.adc()[0], vzero.adc()[1]); if (!collision.sel7()) return; @@ -153,17 +118,10 @@ struct CorrelationTask { for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { -#ifndef MYFILTER - if (track1.pt2() < pTCut) - continue; - if (track1.eta2() < -0.8 || track1.eta2() > 0.8) - continue; -#endif - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) continue; - //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta2(), track1.phi(), track1.phi2(), track1.pt(), track1.pt2()); + //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); double eventValues[3]; eventValues[0] = track1.pt(); @@ -174,12 +132,6 @@ struct CorrelationTask { //mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); for (auto track2 = track1 + 1; track2 != tracks.end(); ++track2) { -#ifndef MYFILTER - if (track2.pt2() < pTCut) - continue; - if (track2.eta2() < -0.8 || track2.eta2() > 0.8) - continue; -#endif if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) continue; @@ -194,12 +146,12 @@ struct CorrelationTask { double values[6] = {0}; - values[0] = track1.etam() - track2.etam(); + values[0] = track1.eta() - track2.eta(); values[1] = track1.pt(); values[2] = track2.pt(); values[3] = collision.centV0M(); - values[4] = track1.phim() - track2.phim(); + values[4] = track1.phi() - track2.phi(); if (values[4] > 1.5 * TMath::Pi()) values[4] -= TMath::TwoPi(); if (values[4] < -0.5 * TMath::Pi()) @@ -214,7 +166,7 @@ struct CorrelationTask { } // Version with combinations - void process2(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::EtaPhi>> const& tracks) + void process2(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& tracks) { LOGF(info, "Tracks for collision (Combination run): %d", tracks.size()); @@ -225,7 +177,7 @@ struct CorrelationTask { if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) continue; - // LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta2(), track1.phi(), track1.phi2(), track1.pt(), track1.pt2()); + // LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); double eventValues[3]; eventValues[0] = track1.pt(); @@ -254,12 +206,12 @@ struct CorrelationTask { double values[6] = {0}; - values[0] = track1.etam() - track2.etam(); + values[0] = track1.eta() - track2.eta(); values[1] = track1.pt(); values[2] = track2.pt(); values[3] = 0; // collision.v0mult(); - values[4] = track1.phim() - track2.phim(); + values[4] = track1.phi() - track2.phi(); if (values[4] > 1.5 * TMath::Pi()) values[4] -= TMath::TwoPi(); if (values[4] < -0.5 * TMath::Pi()) @@ -300,7 +252,7 @@ struct CorrelationTask { template <typename T> bool conversionCut(T const& track1, T const& track2, PairCuts conv, double cut) { - //LOGF(info, "pt is %f %f", track1.pt2(), track2.pt2()); + //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); if (cut < 0) return false; @@ -361,21 +313,21 @@ struct CorrelationTask { float tantheta1 = 1e10; - if (track1.etam() < -1e-10 || track1.etam() > 1e-10) { - float expTmp = TMath::Exp(-track1.etam()); + if (track1.eta() < -1e-10 || track1.eta() > 1e-10) { + float expTmp = TMath::Exp(-track1.eta()); tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); } float tantheta2 = 1e10; - if (track2.etam() < -1e-10 || track2.etam() > 1e-10) { - float expTmp = TMath::Exp(-track2.etam()); + if (track2.eta() < -1e-10 || track2.eta() > 1e-10) { + float expTmp = TMath::Exp(-track2.eta()); tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); } float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); - float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.ptm() * track2.ptm() * (TMath::Cos(track1.phim() - track2.phim()) + 1.0 / tantheta1 / tantheta2))); + float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (TMath::Cos(track1.phi() - track2.phi()) + 1.0 / tantheta1 / tantheta2))); // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); @@ -387,12 +339,12 @@ struct CorrelationTask { { // calculate inv mass squared approximately - const float eta1 = track1.etam(); - const float eta2 = track2.etam(); - const float phi1 = track1.phim(); - const float phi2 = track2.phim(); - const float pt1 = track1.ptm(); - const float pt2 = track2.ptm(); + const float eta1 = track1.eta(); + const float eta2 = track2.eta(); + const float phi1 = track1.phi(); + const float phi2 = track2.phi(); + const float pt1 = track1.pt(); + const float pt2 = track2.pt(); float tantheta1 = 1e10; @@ -438,7 +390,7 @@ struct CorrelationTask { // the variables & cuthave been developed by the HBT group // see e.g. https://indico.cern.ch/materialDisplay.py?contribId=36&sessionId=6&materialId=slides&confId=142700 - auto deta = track1.etam() - track2.etam(); + auto deta = track1.eta() - track2.eta(); // optimization if (TMath::Abs(deta) < cfgTwoTrackCut * 2.5 * 3) { @@ -465,7 +417,7 @@ struct CorrelationTask { qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); if (dphistarminabs < cfgTwoTrackCut && TMath::Abs(deta) < cfgTwoTrackCut) { - //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt2(), track1.charge(), track2.phi2(), track2.pt2(), track2.charge(), bSign); + //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.charge(), track2.phi2(), track2.pt(), track2.charge(), bSign); return true; } @@ -483,12 +435,12 @@ struct CorrelationTask { // calculates dphistar // - auto phi1 = track1.phim(); - auto pt1 = track1.ptm(); + auto phi1 = track1.phi(); + auto pt1 = track1.pt(); auto charge1 = track1.charge(); - auto phi2 = track2.phim(); - auto pt2 = track2.ptm(); + auto phi2 = track2.phi(); + auto pt2 = track2.pt(); auto charge2 = track2.charge(); float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); @@ -512,7 +464,7 @@ struct CorrelationTask { // static_assert("Need to pass aod::track"); // // - // // LOGF(info, "pt %f", track1.pt2()); + // // LOGF(info, "pt %f", track1.pt()); // return false; // } @@ -522,6 +474,5 @@ struct CorrelationTask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<ATask>("produce-etaphi"), adaptAnalysisTask<CorrelationTask>("correlation-task")}; } From f2275effa688e57d57a4a129e1f655ecfa85cd26 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 22:10:15 +0200 Subject: [PATCH 0470/1751] TPC: bugfix, need to check for tpcZS ptr in all places --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 80f0914a67faa..e522978f63e3d 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -106,7 +106,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* if (maxContTimeBin && d[j].getTimeStamp() >= maxContTimeBin) { throw std::runtime_error("Digit time bin exceeds time frame length"); } - if (zsThreshold > 0) { + if (zsThreshold > 0 && data->tpcZS == nullptr) { if (d[j].getChargeFloat() >= zsThreshold) { if (data->o2DigitsMC) { for (const auto& element : (*data->o2DigitsMC)[i]->getLabels(j)) { From c3c45762bd49ecabb04726dc2469349c9fd7d275 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 22:15:32 +0200 Subject: [PATCH 0471/1751] TPC: Don't move digit labels into owning pointer --- .../TPC/reconstruction/src/GPUCATracking.cxx | 2 +- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 15 +++++++-------- .../Interface/GPUO2InterfaceConfiguration.h | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index e522978f63e3d..9ac6ac3cf7c57 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -127,7 +127,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* gpuDigitsMap.tpcDigits[i] = (*(data->o2Digits))[i].data(); gpuDigitsMap.nTPCDigits[i] = (*(data->o2Digits))[i].size(); if (data->o2DigitsMC) { - gpuDigitsMapMC.v[i] = (*data->o2DigitsMC)[i].get(); + gpuDigitsMapMC.v[i] = (*data->o2DigitsMC)[i]; } } } diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index da9c0f7850d33..d745e2895693b 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -265,7 +265,8 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int const void** tpcZSmetaPointers2[GPUTrackingInOutZS::NSLICES][GPUTrackingInOutZS::NENDPOINTS]; const unsigned int* tpcZSmetaSizes2[GPUTrackingInOutZS::NSLICES][GPUTrackingInOutZS::NENDPOINTS]; std::array<gsl::span<const o2::tpc::Digit>, NSectors> inputDigits; - std::array<std::unique_ptr<const MCLabelContainer>, NSectors> inputDigitsMC; + std::vector<CachedMCLabelContainer> inputDigitsMC; + std::array<const MCLabelContainer*, constants::MAXSECTOR> inputDigitsMCPtrs; std::array<unsigned int, NEndpoints * NSectors> tpcZSonTheFlySizes; gsl::span<const ZeroSuppressedContainer8kb> inputZS; @@ -295,7 +296,8 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } inputrefs[sector].labels = ref; if (specconfig.caClusterer) { - inputDigitsMC[sector] = std::move(pc.inputs().get<const MCLabelContainer*>(ref)); + inputDigitsMC.emplace_back(pc.inputs().get<const MCLabelContainer*>(ref)); + inputDigitsMCPtrs[sector] = inputDigitsMC.back().get(); } validMcInputs |= sectorMask; activeSectors |= sectorHeader->activeSectors; @@ -491,7 +493,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int continue; } if (refentry.second.labels.header != nullptr && refentry.second.labels.payload != nullptr) { - mcInputs.emplace_back(std::move(pc.inputs().get<const MCLabelContainer*>(refentry.second.labels))); + mcInputs.emplace_back(pc.inputs().get<const MCLabelContainer*>(refentry.second.labels)); } inputs.emplace_back(gsl::span(ref.payload, DataRefUtils::getPayloadSize(ref))); printInputLog(ref, "received", sector); @@ -553,7 +555,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int ptrs.tpcZS = &tpcZS; if (specconfig.processMC) { ptrs.o2Digits = &inputDigits; - ptrs.o2DigitsMC = &inputDigitsMC; + ptrs.o2DigitsMC = &inputDigitsMCPtrs; } } else if (specconfig.zsDecoder) { ptrs.tpcZS = &tpcZS; @@ -563,7 +565,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } else { ptrs.o2Digits = &inputDigits; if (specconfig.processMC) { - ptrs.o2DigitsMC = &inputDigitsMC; + ptrs.o2DigitsMC = &inputDigitsMCPtrs; } } } else if (specconfig.decompressTPC) { @@ -685,9 +687,6 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int validInputs.reset(); if (specconfig.processMC) { validMcInputs.reset(); - for (auto& mcInput : mcInputs) { - mcInput.reset(); - } } }; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index 97e61ef7b294a..81673bcd9a6be 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -108,7 +108,7 @@ struct GPUO2InterfaceIOPtrs { // Input: TPC clusters in cluster native format, or digits, or list of ZS pages - const as it can only be input const o2::tpc::ClusterNativeAccess* clusters = nullptr; const std::array<gsl::span<const o2::tpc::Digit>, o2::tpc::constants::MAXSECTOR>* o2Digits = nullptr; - std::array<std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>>, o2::tpc::constants::MAXSECTOR>* o2DigitsMC = nullptr; + std::array<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*, o2::tpc::constants::MAXSECTOR>* o2DigitsMC = nullptr; const o2::gpu::GPUTrackingInOutZS* tpcZS = nullptr; // Input / Output for Merged TPC tracks, two ptrs, for the tracks themselves, and for the MC labels. From 29ed57b60cb3baf0f83d6eb219fc1a9b43d8a765 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 26 Aug 2020 22:48:34 +0200 Subject: [PATCH 0472/1751] GPU: Use only a single lane for clusterizing on CPU (saves memory, and they are anyway processed serially) --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index be400bdbe5683..96421d0047de1 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -237,6 +237,7 @@ int GPUReconstruction::InitPhaseBeforeDevice() } if (!IsGPU()) { mProcessingSettings.nDeviceHelperThreads = 0; + mProcessingSettings.nTPCClustererLanes = 1; } if (param().rec.NonConsecutiveIDs) { From 934c1233cded0396fd2ed72a52b64e5896431598 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 25 Aug 2020 19:35:16 +0200 Subject: [PATCH 0473/1751] Use FAIR_MIN_SEVERITY=info for non-debug builts (changed to opt-in) --- dependencies/O2CompileFlags.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dependencies/O2CompileFlags.cmake b/dependencies/O2CompileFlags.cmake index f54e05cad7b4b..85a98847e1511 100644 --- a/dependencies/O2CompileFlags.cmake +++ b/dependencies/O2CompileFlags.cmake @@ -33,6 +33,9 @@ IF(ENABLE_CASSERT) #For the CI, we want to have <cassert> assertions enabled ELSE() set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG") + if (CMAKE_BUILD_TYPE STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO") + set(FAIR_MIN_SEVERITY "info") + endif() ENDIF() set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_Fortran_FLAGS_RELEASE "-O2") From 0e3c78bf0d0a1ac8e2eb2a62a2f6d9d863169802 Mon Sep 17 00:00:00 2001 From: Ivana Hrivnacova <Ivana.Hrivnacova@cern.ch> Date: Tue, 25 Aug 2020 16:57:00 +0200 Subject: [PATCH 0474/1751] Fixes in doxygen: Added doxugen keywords where missing --- Detectors/FIT/FT0/workflow/README.md | 4 ++++ Detectors/FIT/README.md | 1 + Detectors/MUON/MCH/README.md | 1 + doc/README.md | 1 + doc/Upgrades.md | 4 ++++ 5 files changed, 11 insertions(+) diff --git a/Detectors/FIT/FT0/workflow/README.md b/Detectors/FIT/FT0/workflow/README.md index 735c41436d65a..0bf3d1312ed2c 100644 --- a/Detectors/FIT/FT0/workflow/README.md +++ b/Detectors/FIT/FT0/workflow/README.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refFITFT0workflow FIT/FT0 FLP DPL workflow +/doxy --> + # FLP DPL workflow, for reading raw data blocks from payload, and converting them into digits. To run with source file: diff --git a/Detectors/FIT/README.md b/Detectors/FIT/README.md index 2613f7f311154..87c8647513541 100644 --- a/Detectors/FIT/README.md +++ b/Detectors/FIT/README.md @@ -8,4 +8,5 @@ This is a top page for the FIT detector documentation. <!-- doxy * \subpage refFITbenchmark +* \subpage refFITFT0workflow /doxy --> diff --git a/Detectors/MUON/MCH/README.md b/Detectors/MUON/MCH/README.md index d19561f506d46..8b49bf20caf2d 100644 --- a/Detectors/MUON/MCH/README.md +++ b/Detectors/MUON/MCH/README.md @@ -8,6 +8,7 @@ This is a top page for the MCH detector documentation. <!-- doxy \subpage refDetectorsMUONMCHContour +\subpage refDetectorsMUONMCHClustering \subpage refDetectorsMUONMCHRaw \subpage refDetectorsMUONMCHMapping \subpage refDetectorsMUONMCHWorkflow diff --git a/doc/README.md b/doc/README.md index 4c8224a712850..b699306179b00 100644 --- a/doc/README.md +++ b/doc/README.md @@ -14,4 +14,5 @@ This module contains the documentation pages. * \subpage refdocDetectorSimulation * \subpage refdocDoxygenInstructions * \subpage refdocManPages +* \subpage refdocUpgrades /doxy --> diff --git a/doc/Upgrades.md b/doc/Upgrades.md index e0de38e04c19d..1051082894dab 100644 --- a/doc/Upgrades.md +++ b/doc/Upgrades.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refdocUpgrades Upgrades +/doxy --> + # Detector upgrades in O2 ## Conventions From 13ea5c87f0b7b519371624b90aa705c58d0c692f Mon Sep 17 00:00:00 2001 From: Matteo Concas <mconcas@cern.ch> Date: Thu, 27 Aug 2020 10:51:45 +0200 Subject: [PATCH 0475/1751] Update Definitions.h --- .../ITSMFT/ITS/tracking/include/ITStracking/Definitions.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index 13ad78a0362bb..1343887077276 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -29,9 +29,9 @@ #define CA_DEBUGGER(x) \ do { \ } while (0) -#ifndef NDEBUG -#define NDEBUG 1 -#endif +// #ifndef NDEBUG +// #define NDEBUG 1 +// #endif #endif #if defined(CUDA_ENABLED) From eeddcdfec516b0aec1dc28ae95da9dc15a8881f7 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 27 Aug 2020 12:12:23 +0200 Subject: [PATCH 0476/1751] Update sim_challenge.sh apply shared mem segement size to all workflows. Fixes https://alice.its.cern.ch/jira/browse/O2-1657. --- prodtests/sim_challenge.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 65a288563ae2a..094fb0669b280 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -122,7 +122,7 @@ generPbPb="pythia8hi" engine="TGeant3" # options to pass to every workflow -gloOpt=" -b --run " +gloOpt=" -b --run --shm-segment-size 10000000000" # option to set the number of sim workers simWorker="" @@ -196,7 +196,7 @@ fi if [ "$dodigi" == "1" ]; then echo "Running digitization for $intRate kHz interaction rate" intRate=$((1000*(intRate))); - taskwrapper digi.log o2-sim-digitizer-workflow $gloOpt --shm-segment-size 10000000000 --interactionRate $intRate $tpcLanes + taskwrapper digi.log o2-sim-digitizer-workflow $gloOpt --interactionRate $intRate $tpcLanes echo "Return status of digitization: $?" # existing checks #root -b -q O2/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C+ From 26c1d846101f78dce942198b0595c8119bc99102 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 24 Aug 2020 20:41:38 +0200 Subject: [PATCH 0477/1751] Fix in MC2ROFRecord::getNROFs getter --- .../ITSMFT/common/include/DataFormatsITSMFT/ROFRecord.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ROFRecord.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ROFRecord.h index d099f529117a6..9568b2abca15f 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ROFRecord.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ROFRecord.h @@ -103,7 +103,7 @@ struct MC2ROFRecord { MC2ROFRecord() = default; MC2ROFRecord(int evID, int rofRecID, ROFtype mnrof, ROFtype mxrof) : eventRecordID(evID), rofRecordID(rofRecID), minROF(mnrof), maxROF(mxrof) {} - int getNROFs() const { return eventRecordID < 0 ? 0 : (maxROF - minROF); } + int getNROFs() const { return (rofRecordID < 0 || minROF > maxROF) ? 0 : (maxROF - minROF); } void print() const; ClassDefNV(MC2ROFRecord, 1); }; From aab71f25bc1611a468a68495e1624dc11b221759 Mon Sep 17 00:00:00 2001 From: Luca Barioglio <luca.barioglio@cern.ch> Date: Mon, 24 Aug 2020 16:30:49 +0200 Subject: [PATCH 0478/1751] Fix Err2 for rare topologies --- .../ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h | 2 +- DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx | 2 +- .../common/reconstruction/src/BuildTopologyDictionary.cxx | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h index c19eb8114b36a..f25dab5768854 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h @@ -82,7 +82,7 @@ class ClusterTopology /// Hashcode computed from the pattern /// /// The first four bytes are computed with MurMur2 hash-function. The remaining - /// four bytes are the first 32 pixels of the pattern. If the number of pixles + /// four bytes are the first 32 pixels of the pattern. If the number of pixels /// is less than 32, the remaining bits are set to 0. unsigned long mHash; diff --git a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx index 374a9df6de8ea..4b56f7d110d06 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx @@ -41,7 +41,7 @@ TopologyDictionary::TopologyDictionary(std::string fileName) std::ostream& operator<<(std::ostream& os, const TopologyDictionary& dict) { for (auto& p : dict.mVectorOfIDs) { - os << "Hash: " << p.mHash << " ErrX: " << p.mErrX << " ErrZ : " << p.mErrZ << " xCOG: " << p.mXCOG << " zCOG: " << p.mZCOG << " Npixles: " << p.mNpixels << " Frequency: " << p.mFrequency << " isGroup : " << std::boolalpha << p.mIsGroup << std::endl + os << "Hash: " << p.mHash << " ErrX: " << p.mErrX << " ErrZ : " << p.mErrZ << " xCOG: " << p.mXCOG << " zCOG: " << p.mZCOG << " Npixels: " << p.mNpixels << " Frequency: " << p.mFrequency << " isGroup : " << std::boolalpha << p.mIsGroup << std::endl << p.mPattern << std::endl << "*********************************************************" << std::endl << std::endl; diff --git a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx index bbd5b74b2b01f..70c3ce701ae11 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx @@ -174,6 +174,8 @@ void BuildTopologyDictionary::groupRareTopologies() gr.mHash = (((unsigned long)(grNum)) << 32) & 0xffffffff00000000; gr.mErrX = (rowBinEdge)*o2::itsmft::SegmentationAlpide::PitchRow / std::sqrt(12); gr.mErrZ = (colBinEdge)*o2::itsmft::SegmentationAlpide::PitchCol / std::sqrt(12); + gr.mErr2X = gr.mErrX * gr.mErrX; + gr.mErr2Z = gr.mErrZ * gr.mErrZ; gr.mXCOG = 0; gr.mZCOG = 0; gr.mNpixels = rowBinEdge * colBinEdge; From 40d96100b9c8b91c9d1ee2e7182b97fdce0aecf4 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 27 Aug 2020 12:21:55 +0200 Subject: [PATCH 0479/1751] Fix wrong assert --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 8d0703a7242c6..97beddc7139fe 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -39,7 +39,7 @@ Tracker::Tracker(o2::its::TrackerTraits* traits) /// Initialise standard configuration with 1 iteration mTrkParams.resize(1); mMemParams.resize(1); - assert(mTracks != nullptr); + assert(mTraits != nullptr); mTraits = traits; mPrimaryVertexContext = mTraits->getPrimaryVertexContext(); } From ac456026c032989bd6a3ead0539eb7ca53e79a30 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 27 Aug 2020 16:16:03 +0200 Subject: [PATCH 0480/1751] Fix ITS Compilation without -DNDEBUG --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 97beddc7139fe..f056ae7c7e1b4 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -246,7 +246,7 @@ void Tracker::findTracks(const ROframe& event) } } - assert(nClusters >= mTrkParams[0].MinTrackLength); + CA_DEBUGGER(assert(nClusters >= mTrkParams[0].MinTrackLength)); CA_DEBUGGER(roadCounters[nClusters - 4]++); if (lastCellLevel == constants::its::UnusedIndex) @@ -287,7 +287,7 @@ void Tracker::findTracks(const ROframe& event) CA_DEBUGGER(refitCounters[nClusters - 4]++); temporaryTrack.setROFrame(mROFrame); tracks.emplace_back(temporaryTrack); - assert(nClusters == temporaryTrack.getNumberOfClusters()); + CA_DEBUGGER(assert(nClusters == temporaryTrack.getNumberOfClusters())); } //mTraits->refitTracks(event.getTrackingFrameInfo(), tracks); From 7008b8890d9cf8290cc738fae7d69976abe27c68 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 27 Aug 2020 16:52:48 +0200 Subject: [PATCH 0481/1751] ITS DigiParam: suppress initialization from c-tor do in only once run-time parameters are set --- Detectors/ITSMFT/common/simulation/src/DigiParams.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Detectors/ITSMFT/common/simulation/src/DigiParams.cxx b/Detectors/ITSMFT/common/simulation/src/DigiParams.cxx index 88e9792706c1e..86023fff83424 100644 --- a/Detectors/ITSMFT/common/simulation/src/DigiParams.cxx +++ b/Detectors/ITSMFT/common/simulation/src/DigiParams.cxx @@ -22,7 +22,6 @@ using namespace o2::itsmft; DigiParams::DigiParams() { // make sure the defaults are consistent - setROFrameLength(mROFrameLength); setNSimSteps(mNSimSteps); } From 02cbabd89be518ffd5d7f272f1198bcba98e1045 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Thu, 27 Aug 2020 21:33:17 +0200 Subject: [PATCH 0482/1751] DPL Analysis: functions to attach dynamic or extended columns to a table on the fly (#4216) --- Analysis/Tutorials/CMakeLists.txt | 5 +++ Analysis/Tutorials/src/dynamicColumns.cxx | 50 ++++------------------ Analysis/Tutorials/src/extendedColumns.cxx | 42 ++++++++++++++++++ Framework/Core/include/Framework/ASoA.h | 32 +++++++++++++- 4 files changed, 87 insertions(+), 42 deletions(-) create mode 100644 Analysis/Tutorials/src/extendedColumns.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index e660dbf25ba32..84a1ae813f974 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -111,6 +111,11 @@ o2_add_dpl_workflow(weak-decay-iteration SOURCES src/weakDecayIteration.cxx COMPONENT_NAME AnalysisTutorial) +o2_add_dpl_workflow(extended-columns + SOURCES src/extendedColumns.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + COMPONENT_NAME AnalysisTutorial) + o2_add_dpl_workflow(zdc-vzero-iteration SOURCES src/ZDCVZeroIteration.cxx COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/dynamicColumns.cxx b/Analysis/Tutorials/src/dynamicColumns.cxx index ae851d6e519bd..e8e2c25eec425 100644 --- a/Analysis/Tutorials/src/dynamicColumns.cxx +++ b/Analysis/Tutorials/src/dynamicColumns.cxx @@ -13,46 +13,23 @@ namespace o2::aod { -namespace etaphi +namespace extension { -DECLARE_SOA_COLUMN(Tgl, tgl, float); -DECLARE_SOA_COLUMN(Snp, snp, float); -DECLARE_SOA_COLUMN(Alpha, alpha, float); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float tgl) { return log(tan(0.25 * M_PI - 0.5 * atan(tgl))); }); -DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float snp, float alpha) { return asin(snp) + alpha + M_PI; }); +DECLARE_SOA_DYNAMIC_COLUMN(P2, p2, [](float p) { return p * p; }); } // namespace etaphi -DECLARE_SOA_TABLE(EtaPhis, "AOD", "ETAPHI", - etaphi::Tgl, etaphi::Snp, etaphi::Alpha, - etaphi::Eta<etaphi::Tgl>, - etaphi::Phi<etaphi::Snp, etaphi::Alpha>); } // namespace o2::aod using namespace o2; using namespace o2::framework; -// This is a very simple example showing how to iterate over tracks -// and create a new collection for them. -// FIXME: this should really inherit from AnalysisTask but -// we need GCC 7.4+ for that struct ATask { - Produces<aod::EtaPhis> etaphi; - - void process(aod::Tracks const& tracks) + void process(aod::Collision const&, aod::Tracks const& tracks) { - for (auto& track : tracks) { - etaphi(track.tgl(), track.snp(), track.alpha()); - } - } -}; - -struct BTask { - void process(aod::EtaPhis const& etaPhis) - { - for (auto& etaPhi : etaPhis) { - auto phi = asin(etaPhi.snp()) + etaPhi.alpha() + M_PI; - auto eta = log(tan(0.25 * M_PI - 0.5 * atan(etaPhi.tgl()))); - - //LOGF(INFO, "(%f, %f, %f, %f)", etaPhi.eta(), etaPhi.phi(), eta - etaPhi.eta(), phi - etaPhi.phi()); + auto table_with_extra_dynamic_columns = soa::Attach<aod::Tracks, aod::extension::P2<aod::track::P>>(tracks); + for (auto& row : table_with_extra_dynamic_columns) { + if (row.trackType() != 3) { + LOGF(info, "P^2 = %.3f", row.p2()); + } } } }; @@ -61,14 +38,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) { // create and use table return WorkflowSpec{ - adaptAnalysisTask<ATask>("produce-track-copy"), - adaptAnalysisTask<BTask>("check-eta-phi")}; - - // only create table -> tabwle is written to file - //return WorkflowSpec{ - // adaptAnalysisTask<ATask>("produce-track-copy")}; - - // only use table -> table is read from file - //return WorkflowSpec{ - // adaptAnalysisTask<BTask>("check-eta-phi")}; + adaptAnalysisTask<ATask>("attach-showcase")}; } diff --git a/Analysis/Tutorials/src/extendedColumns.cxx b/Analysis/Tutorials/src/extendedColumns.cxx new file mode 100644 index 0000000000000..ad93833eb09d4 --- /dev/null +++ b/Analysis/Tutorials/src/extendedColumns.cxx @@ -0,0 +1,42 @@ +// 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" + +namespace o2::aod +{ +namespace extension +{ +DECLARE_SOA_EXPRESSION_COLUMN(P2, p2, float, track::p* track::p); +} // namespace extension +} // namespace o2::aod + +using namespace o2; +using namespace o2::framework; + +struct ATask { + void process(aod::Collision const&, aod::Tracks const& tracks) + { + auto table_extension = soa::Extend<aod::Tracks, aod::extension::P2>(tracks); + for (auto& row : table_extension) { + if (row.trackType() != 3) { + LOGF(info, "P^2 = %.3f", row.p2()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + // create and use table + return WorkflowSpec{ + adaptAnalysisTask<ATask>("extend-showcase")}; +} diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 8383117dc153f..6d428062d725d 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -65,6 +65,12 @@ constexpr bool is_type_with_binding_v = false; template <typename T> constexpr bool is_type_with_binding_v<T, std::void_t<decltype(sizeof(typename T::binding_t))>> = true; +template <typename, typename = void> +constexpr bool is_type_spawnable_v = false; + +template <typename T> +constexpr bool is_type_spawnable_v<T, std::void_t<decltype(sizeof(typename T::spawnable_t))>> = true; + template <typename T, typename TLambda> void call_if_has_originals(TLambda&& lambda) { @@ -966,7 +972,11 @@ class Table { return mTable; } - + /// Return offset + auto offset() const + { + return mOffset; + } /// Size of the table, in rows. int64_t size() const { @@ -1112,6 +1122,7 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); using base = o2::soa::Column<_Type_, _Name_>; \ using type = _Type_; \ using column_t = _Name_; \ + using spawnable_t = std::true_type; \ _Name_(arrow::ChunkedArray const* column) \ : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator<type>(column)) \ { \ @@ -1746,6 +1757,15 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) return arrow::Table::Make(std::make_shared<arrow::Schema>(new_fields), new_columns); } +/// On-the-fly adding of expression columns +template <typename T, typename... Cs> +auto Extend(T const& table) +{ + static_assert((soa::is_type_spawnable_v<Cs> && ...), "You can only extend a table with expression columns"); + using output_t = JoinBase<T, soa::Table<Cs...>>; + return output_t{spawner(framework::pack<Cs...>{}, table.asArrowTable().get()), table.offset()}; +} + /// Template for building an index table to access matching rows from non- /// joinable, but compatible tables, e.g. Collisions and ZDCs. /// First argument is the key table (BCs for the Collisions+ZDCs case), the rest @@ -1775,6 +1795,16 @@ struct IndexTable : Table<soa::Index<>, H, Ts...> { template <typename T> using is_soa_index_table_t = typename framework::is_base_of_template<soa::IndexTable, T>; +/// Template function to attach dynamic columns on-the-fly (e.g. inside +/// process() function). Dynamic columns need to be compatible with the table. +template <typename T, typename... Cs> +auto Attach(T const& table) +{ + static_assert((framework::is_base_of_template<o2::soa::DynamicColumn, Cs>::value && ...), "You can only attach dynamic columns"); + using output_t = JoinBase<T, o2::soa::Table<Cs...>>; + return output_t{table.asArrowTable(), table.offset()}; +} + } // namespace o2::soa #endif // O2_FRAMEWORK_ASOA_H_ From bca6140fed82ba7d0b2322421c37ed7410cd5da1 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 27 Aug 2020 17:30:47 +0200 Subject: [PATCH 0483/1751] GPU: Use CMake 3.18 style to set CUDA GPU Targets --- dependencies/FindO2GPU.cmake | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 075f933ecd1ae..68862e3431089 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -62,10 +62,9 @@ if(ENABLE_CUDA) set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Werror=cross-execution-space-call") endif() if(CUDA_COMPUTETARGET) - set( - CMAKE_CUDA_FLAGS - "${CMAKE_CUDA_FLAGS} -gencode arch=compute_${CUDA_COMPUTETARGET},code=sm_${CUDA_COMPUTETARGET}" - ) + set(CMAKE_CUDA_ARCHITECTURES ${CUDA_COMPUTETARGET}) + else() + set(CMAKE_CUDA_ARCHITECTURES OFF) endif() set(CUDA_ENABLED ON) From 82c6f7a16d9f1f28bcd5c5ef3e758f81c0a829a6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 29 Jul 2020 21:26:41 +0200 Subject: [PATCH 0484/1751] GPU: Some preparation work to support GPU run-time-compilation in the future --- Common/MathUtils/include/MathUtils/Utils.h | 12 +- .../include/DataFormatsTPC/ClusterNative.h | 2 +- .../TPC/include/DataFormatsTPC/Digit.h | 2 +- .../include/DataFormatsTPC/ZeroSuppression.h | 2 +- .../Headers/include/Headers/RAWDataHeader.h | 2 +- DataFormats/Headers/include/Headers/RDHAny.h | 6 +- .../Base/include/DetectorsBase/MatLayerCyl.h | 2 +- .../ITS/tracking/include/ITStracking/Cell.h | 2 +- .../tracking/include/ITStracking/Cluster.h | 2 +- .../tracking/include/ITStracking/Constants.h | 2 +- .../include/ITStracking/Definitions.h | 6 +- .../include/ITStracking/IndexTableUtils.h | 2 +- .../tracking/include/ITStracking/MathUtils.h | 2 +- .../ITS/tracking/include/ITStracking/Road.h | 2 +- Detectors/Raw/include/DetectorsRaw/RDHUtils.h | 4 +- .../base/include/TRDBase/TRDGeometryBase.h | 68 +++---- .../base/include/TRDBase/TRDGeometryFlat.h | 2 +- GPU/Common/GPUCommonAlgorithm.h | 6 +- GPU/Common/GPUCommonAlgorithmThrust.h | 2 + GPU/Common/GPUCommonLogger.h | 11 +- GPU/Common/GPUCommonMath.h | 77 +++---- GPU/GPUTracking/Base/GPUDataTypes.h | 4 +- GPU/GPUTracking/Base/GPUGeneralKernels.h | 4 +- GPU/GPUTracking/Base/GPUSettings.h | 2 +- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 2 +- .../Base/cuda/GPUReconstructionCUDArtc.cu | 27 +++ .../Base/cuda/GPUReconstructionCUDArtcPre.h | 31 +++ .../GPUTPCCompressionKernels.cxx | 1 + GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 8 +- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 4 - GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx | 3 - GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h | 2 +- .../SliceTracker/GPUTPCSliceData.cxx | 4 +- .../Standalone/tools/rtc/rtcsource.sh | 16 ++ GPU/GPUTracking/Standalone/tools/rtc/test.cu | 86 ++++++++ GPU/GPUTracking/Standalone/utils/bitfield.h | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 4 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 2 +- GPU/GPUTracking/dEdx/GPUdEdx.cxx | 2 + .../TPCFastTransformGeo.h | 2 +- GPU/Utils/FlatObject.h | 189 +++++++++--------- 42 files changed, 392 insertions(+), 221 deletions(-) create mode 100644 GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu create mode 100644 GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h create mode 100755 GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh create mode 100644 GPU/GPUTracking/Standalone/tools/rtc/test.cu diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index 45b1ad4c324a8..760e75fc287ad 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -15,7 +15,7 @@ #ifndef ALICEO2_COMMON_MATH_UTILS_ #define ALICEO2_COMMON_MATH_UTILS_ -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #include <cmath> #endif @@ -69,17 +69,17 @@ inline void BringToPMPiGen(float& phi) } } -inline void sincosf(float ang, float& s, float& c) +GPUdi() void sincosf(float ang, float& s, float& c) { o2::gpu::GPUCommonMath::SinCos(ang, s, c); } -inline void sincos(float ang, float& s, float& c) +GPUdi() void sincos(float ang, float& s, float& c) { o2::gpu::GPUCommonMath::SinCos(ang, s, c); } -inline void sincos(double ang, double& s, double& c) +GPUdi() void sincos(double ang, double& s, double& c) { o2::gpu::GPUCommonMath::SinCos(ang, s, c); } @@ -110,12 +110,12 @@ inline void rotateZInv(double xG, double yG, double& xL, double& yL, double snAl rotateZ(xG, yG, xL, yL, -snAlp, csAlp); } -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE inline void RotateZ(std::array<float, 3>& xy, float alpha) { // transforms vector in tracking frame alpha to global frame float sn, cs, x = xy[0]; - sincosf(alpha, sn, cs); + o2::gpu::GPUCommonMath::SinCos(alpha, sn, cs); xy[0] = x * cs - xy[1] * sn; xy[1] = x * sn + xy[1] * cs; } diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h index 4947314ca0340..4dcabd1913159 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h @@ -13,7 +13,7 @@ /// \author David Rohr #ifndef ALICEO2_DATAFORMATSTPC_CLUSTERNATIVE_H #define ALICEO2_DATAFORMATSTPC_CLUSTERNATIVE_H -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstdint> #include <cstddef> // for size_t #endif diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Digit.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Digit.h index 728bd405f6deb..4c446024324c5 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Digit.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Digit.h @@ -18,7 +18,7 @@ #include "GPUCommonRtypes.h" #include "GPUCommonDef.h" #include "CommonDataFormat/TimeStamp.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <climits> #endif diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppression.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppression.h index 3a14b0fd34dad..2fd6c82b920af 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppression.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ZeroSuppression.h @@ -13,7 +13,7 @@ /// \author David Rohr #ifndef ALICEO2_DATAFORMATSTPC_ZEROSUPPRESSION_H #define ALICEO2_DATAFORMATSTPC_ZEROSUPPRESSION_H -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstdint> #include <cstddef> // for size_t #endif diff --git a/DataFormats/Headers/include/Headers/RAWDataHeader.h b/DataFormats/Headers/include/Headers/RAWDataHeader.h index 588080abd2746..8f68a0356c9c3 100644 --- a/DataFormats/Headers/include/Headers/RAWDataHeader.h +++ b/DataFormats/Headers/include/Headers/RAWDataHeader.h @@ -15,7 +15,7 @@ /// @since 2017-11-22 /// @brief Definition of the RAW Data Header -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstdint> #endif diff --git a/DataFormats/Headers/include/Headers/RDHAny.h b/DataFormats/Headers/include/Headers/RDHAny.h index 6a93835fe7d49..b4a57d362abf4 100644 --- a/DataFormats/Headers/include/Headers/RDHAny.h +++ b/DataFormats/Headers/include/Headers/RDHAny.h @@ -15,8 +15,10 @@ #define ALICEO2_HEADER_RDHANY_H #include "GPUCommonDef.h" #include "Headers/RAWDataHeader.h" +#ifndef GPUCA_GPUCODE_DEVICE #include <type_traits> #include <stdexcept> +#endif namespace o2 { @@ -50,7 +52,7 @@ struct RDHAny { template <typename RDH> GPUhdi() static constexpr void sanityCheckStrict() { -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE static_assert(std::is_same<RDH, RDHv4>::value || std::is_same<RDH, RDHv5>::value || std::is_same<RDH, RDHv6>::value, "not an RDH"); @@ -61,7 +63,7 @@ struct RDHAny { template <typename RDH> GPUhdi() static constexpr void sanityCheckLoose() { -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE static_assert(std::is_same<RDH, RDHv4>::value || std::is_same<RDH, RDHv5>::value || std::is_same<RDH, RDHv6>::value || std::is_same<RDHAny, RDH>::value, "not an RDH or RDHAny"); diff --git a/Detectors/Base/include/DetectorsBase/MatLayerCyl.h b/Detectors/Base/include/DetectorsBase/MatLayerCyl.h index ccb7df1c23198..b2dac5df80439 100644 --- a/Detectors/Base/include/DetectorsBase/MatLayerCyl.h +++ b/Detectors/Base/include/DetectorsBase/MatLayerCyl.h @@ -14,7 +14,7 @@ #ifndef ALICEO2_MATLAYERCYL_H #define ALICEO2_MATLAYERCYL_H -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cmath> #include <cstring> #endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h index 244e15f495426..8e71bade83e5f 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h @@ -15,7 +15,7 @@ #ifndef TRACKINGITSU_INCLUDE_CACELL_H_ #define TRACKINGITSU_INCLUDE_CACELL_H_ -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #include <vector> #endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h index 66bfab666c23b..68c09dc52f5a5 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h @@ -15,7 +15,7 @@ #ifndef TRACKINGITSU_INCLUDE_CACLUSTER_H_ #define TRACKINGITSU_INCLUDE_CACLUSTER_H_ -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index d4e25ea415014..87ff6041fde2d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -15,7 +15,7 @@ #ifndef TRACKINGITSU_INCLUDE_CONSTANTS_H_ #define TRACKINGITSU_INCLUDE_CONSTANTS_H_ -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <climits> #include <vector> #endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index 1343887077276..c3f9ca43f2ac0 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -17,7 +17,7 @@ // #define _ALLOW_DEBUG_TREES_ITS_ // to allow debug (vertexer only) -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #endif @@ -59,10 +59,12 @@ #define MATH_CEIL ceil +#ifndef GPUCA_GPUCODE_DEVICE #include <cstddef> +#endif #include "ITStrackingCUDA/Array.h" -template <typename T, std::size_t Size> +template <typename T, size_t Size> using GPUArray = o2::its::GPU::Array<T, Size>; typedef cudaStream_t GPUStream; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h index f703711ee3679..228defce3b650 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h @@ -15,7 +15,7 @@ #ifndef TRACKINGITSU_INCLUDE_INDEXTABLEUTILS_H_ #define TRACKINGITSU_INCLUDE_INDEXTABLEUTILS_H_ -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #include <utility> #include <vector> diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h index d6cfa1d6f6670..b2eea8045ee0e 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h @@ -15,7 +15,7 @@ #ifndef TRACKINGITSU_INCLUDE_CAUTILS_H_ #define TRACKINGITSU_INCLUDE_CAUTILS_H_ -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #include <cmath> #include <cassert> diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h index 51762c5261239..9650eb9fa9ab7 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h @@ -15,7 +15,7 @@ #ifndef TRACKINGITSU_INCLUDE_ROAD_H_ #define TRACKINGITSU_INCLUDE_ROAD_H_ -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #endif diff --git a/Detectors/Raw/include/DetectorsRaw/RDHUtils.h b/Detectors/Raw/include/DetectorsRaw/RDHUtils.h index 1d1a6df6abe40..181ce7c5aca5c 100644 --- a/Detectors/Raw/include/DetectorsRaw/RDHUtils.h +++ b/Detectors/Raw/include/DetectorsRaw/RDHUtils.h @@ -55,7 +55,7 @@ struct RDHUtils { template <typename H> static constexpr int getVersion() { -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE RDHAny::sanityCheckStrict<H>(); if (std::is_same<H, RDHv6>::value) { return 6; @@ -68,7 +68,7 @@ struct RDHUtils { } #else return -1; // dummy value as this method will be used on the CPU only -#endif // __OPENCL__ +#endif // GPUCA_GPUCODE_DEVICE } ///_______________________________ diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h b/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h index 87e54b6802160..8a345d5c62e7f 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h +++ b/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h @@ -60,40 +60,40 @@ class TRDGeometryBase GPUd() float getRow0(int layer, int stack) { return mPadPlanes[getDetectorSec(layer, stack)].getRow0(); } GPUd() float getRowEnd(int layer, int stack) { return mPadPlanes[getDetectorSec(layer, stack)].getRowEnd(); } - static constexpr int getSector(int det) { return (det / (constants::NLAYER * constants::NSTACK)); } - static constexpr float getTime0(int layer) { return TIME0[layer]; } - static constexpr float getXtrdBeg() { return XTRDBEG; } - static constexpr float getXtrdEnd() { return XTRDEND; } - static constexpr float getChamberWidth(int layer) { return CWIDTH[layer]; } - static constexpr float getChamberLength(int layer, int stack) { return CLENGTH[layer][stack]; } - static constexpr float getAlpha() { return 2.0 * 3.14159265358979324 / constants::NSECTOR; } - static constexpr float cheight() { return CH; } - static constexpr float cheightSV() { return CHSV; } - static constexpr float cspace() { return VSPACE; } - static constexpr float craHght() { return CRAH; } - static constexpr float cdrHght() { return CDRH; } - static constexpr float camHght() { return CAMH; } - static constexpr float croHght() { return CROH; } - static constexpr float csvHght() { return CSVH; } - static constexpr float croWid() { return CROW; } - static constexpr float anodePos() { return ANODEPOS; } - static constexpr float myThick() { return RMYTHICK; } - static constexpr float drThick() { return DRTHICK; } - static constexpr float amThick() { return AMTHICK; } - static constexpr float drZpos() { return DRZPOS; } - static constexpr float rpadW() { return RPADW; } - static constexpr float cpadW() { return CPADW; } - static constexpr float cwidcha() { return (SWIDTH2 - SWIDTH1) / SHEIGHT * (CH + VSPACE); } - static constexpr int MCMmax() { return MCMMAX; } - static constexpr int MCMrow() { return MCMROW; } - static constexpr int ROBmaxC0() { return ROBMAXC0; } - static constexpr int ROBmaxC1() { return ROBMAXC1; } - static constexpr int ADCmax() { return ADCMAX; } - static constexpr int TBmax() { return TBMAX; } - static constexpr int padmax() { return PADMAX; } - static constexpr int colmax() { return COLMAX; } - static constexpr int rowmaxC0() { return ROWMAXC0; } - static constexpr int rowmaxC1() { return ROWMAXC1; } + static constexpr GPUd() int getSector(int det) { return (det / (constants::NLAYER * constants::NSTACK)); } + static constexpr GPUd() float getTime0(int layer) { return TIME0[layer]; } + static constexpr GPUd() float getXtrdBeg() { return XTRDBEG; } + static constexpr GPUd() float getXtrdEnd() { return XTRDEND; } + static constexpr GPUd() float getChamberWidth(int layer) { return CWIDTH[layer]; } + static constexpr GPUd() float getChamberLength(int layer, int stack) { return CLENGTH[layer][stack]; } + static constexpr GPUd() float getAlpha() { return 2.0 * 3.14159265358979324 / constants::NSECTOR; } + static constexpr GPUd() float cheight() { return CH; } + static constexpr GPUd() float cheightSV() { return CHSV; } + static constexpr GPUd() float cspace() { return VSPACE; } + static constexpr GPUd() float craHght() { return CRAH; } + static constexpr GPUd() float cdrHght() { return CDRH; } + static constexpr GPUd() float camHght() { return CAMH; } + static constexpr GPUd() float croHght() { return CROH; } + static constexpr GPUd() float csvHght() { return CSVH; } + static constexpr GPUd() float croWid() { return CROW; } + static constexpr GPUd() float anodePos() { return ANODEPOS; } + static constexpr GPUd() float myThick() { return RMYTHICK; } + static constexpr GPUd() float drThick() { return DRTHICK; } + static constexpr GPUd() float amThick() { return AMTHICK; } + static constexpr GPUd() float drZpos() { return DRZPOS; } + static constexpr GPUd() float rpadW() { return RPADW; } + static constexpr GPUd() float cpadW() { return CPADW; } + static constexpr GPUd() float cwidcha() { return (SWIDTH2 - SWIDTH1) / SHEIGHT * (CH + VSPACE); } + static constexpr GPUd() int MCMmax() { return MCMMAX; } + static constexpr GPUd() int MCMrow() { return MCMROW; } + static constexpr GPUd() int ROBmaxC0() { return ROBMAXC0; } + static constexpr GPUd() int ROBmaxC1() { return ROBMAXC1; } + static constexpr GPUd() int ADCmax() { return ADCMAX; } + static constexpr GPUd() int TBmax() { return TBMAX; } + static constexpr GPUd() int padmax() { return PADMAX; } + static constexpr GPUd() int colmax() { return COLMAX; } + static constexpr GPUd() int rowmaxC0() { return ROWMAXC0; } + static constexpr GPUd() int rowmaxC1() { return ROWMAXC1; } protected: TRDGeometryBase() = default; diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h index 01597c854c6b9..5324faac97e22 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h +++ b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h @@ -11,7 +11,7 @@ #ifndef O2_TRDGEOMETRYFLAT_H #define O2_TRDGEOMETRYFLAT_H -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstring> #endif #include "FlatObject.h" diff --git a/GPU/Common/GPUCommonAlgorithm.h b/GPU/Common/GPUCommonAlgorithm.h index 4d15faac5d5f7..b4822e1cf441a 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__) +#if ((defined(__CUDACC__) && !defined(__clang__)) || defined(__HIPCC__)) && !defined(GPUCA_GPUCODE_GENRTC) #include "GPUCommonAlgorithmThrust.h" @@ -332,14 +332,16 @@ GPUdi() void GPUCommonAlgorithm::swap(T& a, T& b) #ifdef __OPENCL__ // Nothing to do, work_group functions available -#elif defined(__CUDACC__) || defined(__HIPCC__) +#elif (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(GPUCA_GPUCODE_GENRTC) // CUDA and HIP work the same way using cub, need just different header +#ifndef GPUCA_GPUCODE_GENRTC #if defined(__CUDACC__) #include <cub/cub.cuh> #elif defined(__HIPCC__) #include <hipcub/hipcub.hpp> #endif +#endif #define work_group_scan_inclusive_add(v) work_group_scan_inclusive_add_FUNC(v, smem) template <class T, class S> diff --git a/GPU/Common/GPUCommonAlgorithmThrust.h b/GPU/Common/GPUCommonAlgorithmThrust.h index cd5e4227bace5..b4fdfacde3d85 100644 --- a/GPU/Common/GPUCommonAlgorithmThrust.h +++ b/GPU/Common/GPUCommonAlgorithmThrust.h @@ -14,12 +14,14 @@ #ifndef GPUCOMMONALGORITHMTHRUST_H #define GPUCOMMONALGORITHMTHRUST_H +#ifndef GPUCA_GPUCODE_GENRTC #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #include <thrust/sort.h> #include <thrust/execution_policy.h> #include <thrust/device_ptr.h> #pragma GCC diagnostic pop +#endif #include "GPUCommonDef.h" diff --git a/GPU/Common/GPUCommonLogger.h b/GPU/Common/GPUCommonLogger.h index c3e93414371d3..e418987edc66e 100644 --- a/GPU/Common/GPUCommonLogger.h +++ b/GPU/Common/GPUCommonLogger.h @@ -17,12 +17,18 @@ #if defined(__OPENCL__) #define LOG(...) #define LOGF(...) + +#elif defined(GPUCA_GPUCODE_DEVICE) +#define LOG(...) +#define LOGF(type, string, ...) \ + { \ + printf(string "\n", ##__VA_ARGS__); \ + } + #elif defined(GPUCA_STANDALONE) || \ defined(GPUCA_ALIROOT_LIB) || \ - defined(GPUCA_GPUCODE_DEVICE) || \ (!defined(__cplusplus) || __cplusplus < 201703L) || \ (defined(__HIPCC__) && (!defined(_GLIBCXX_USE_CXX11_ABI) || _GLIBCXX_USE_CXX11_ABI == 0)) - #include <iostream> #include <cstdio> #define LOG(type) std::cout @@ -32,7 +38,6 @@ } #else - #include <Framework/Logger.h> #endif diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 873b0019f6978..924b045feff75 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -20,7 +20,7 @@ #include <sm_20_atomic_functions.h> #endif -#if !defined(__OPENCL__) +#if !defined(GPUCA_GPUCODE_DEVICE) #include <cmath> #include <algorithm> #endif @@ -35,39 +35,39 @@ namespace gpu class GPUCommonMath { public: - GPUhdni() static float2 MakeFloat2(float x, float y); // TODO: Find better appraoch that is constexpr + GPUd() static float2 MakeFloat2(float x, float y); // TODO: Find better appraoch that is constexpr template <class T> GPUhd() static T Min(const T x, const T y); template <class T> GPUhd() static T Max(const T x, const T y); template <class T, class S, class R> - GPUhd() static T MinWithRef(T x, T y, S refX, S refY, R& r); + GPUd() static T MinWithRef(T x, T y, S refX, S refY, R& r); template <class T, class S, class R> - GPUhd() static T MaxWithRef(T x, T y, S refX, S refY, R& r); + GPUd() static T MaxWithRef(T x, T y, S refX, S refY, R& r); template <class T, class S, class R> - GPUhd() static T MaxWithRef(T x, T y, T z, T w, S refX, S refY, S refZ, S refW, R& r); + GPUd() static T MaxWithRef(T x, T y, T z, T w, S refX, S refY, S refZ, S refW, R& r); GPUhdni() static float Sqrt(float x); - GPUhdni() static float FastInvSqrt(float x); + GPUd() static float FastInvSqrt(float x); template <class T> GPUhd() static T Abs(T x); - GPUhdni() static float ASin(float x); - GPUhdni() static float ATan(float x); - GPUhdni() static float ATan2(float y, float x); - GPUhdni() static float Sin(float x); - GPUhdni() static float Cos(float x); + GPUd() static float ASin(float x); + GPUd() static float ATan(float x); + GPUd() static float ATan2(float y, float x); + GPUd() static float Sin(float x); + GPUd() static float Cos(float x); GPUhdni() static void SinCos(float x, float& s, float& c); GPUhdni() static void SinCos(double x, double& s, double& c); - GPUhdni() static float Tan(float x); + GPUd() static float Tan(float x); GPUhdni() static float Copysign(float x, float y); - GPUhdni() static float TwoPi() { return 6.28319f; } - GPUhdni() static float Pi() { return 3.1415926535897f; } - GPUhdni() static int Nint(float x); - GPUhdni() static bool Finite(float x); - GPUhdni() static unsigned int Clz(unsigned int val); - GPUhdni() static unsigned int Popcount(unsigned int val); - - GPUhdni() static float Log(float x); + GPUd() static float TwoPi() { return 6.28319f; } + GPUd() static float Pi() { return 3.1415926535897f; } + GPUd() static int Nint(float x); + GPUd() static bool Finite(float x); + GPUd() static unsigned int Clz(unsigned int val); + GPUd() static unsigned int Popcount(unsigned int val); + + GPUd() static float Log(float x); template <class T> GPUdi() static T AtomicExch(GPUglobalref() GPUgeneric() GPUAtomic(T) * addr, T val) { @@ -178,9 +178,10 @@ GPUdi() CONSTEXPR17 T GPUCommonMath::nextMultipleOf(T val) { return (val + I - 1) & ~(T)(I - 1); } + return 0; // BUG: Cuda complains about missing return value with constexpr if } -GPUhdi() float2 GPUCommonMath::MakeFloat2(float x, float y) +GPUdi() float2 GPUCommonMath::MakeFloat2(float x, float y) { #if !defined(GPUCA_GPUCODE) || defined(__OPENCL__) || defined(__OPENCL_HOST__) float2 ret = {x, y}; @@ -190,7 +191,7 @@ GPUhdi() float2 GPUCommonMath::MakeFloat2(float x, float y) #endif // GPUCA_GPUCODE } -GPUhdi() int GPUCommonMath::Nint(float x) +GPUdi() int GPUCommonMath::Nint(float x) { int i; if (x >= 0) { @@ -205,15 +206,15 @@ GPUhdi() int GPUCommonMath::Nint(float x) return i; } -GPUhdi() bool GPUCommonMath::Finite(float x) { return CHOICE(std::isfinite(x), true, true); } +GPUdi() bool GPUCommonMath::Finite(float x) { return CHOICE(std::isfinite(x), true, true); } -GPUhdi() float GPUCommonMath::ATan(float x) { return CHOICE(atanf(x), atanf(x), atan(x)); } +GPUdi() float GPUCommonMath::ATan(float x) { return CHOICE(atanf(x), atanf(x), atan(x)); } -GPUhdi() float GPUCommonMath::ATan2(float y, float x) { return CHOICE(atan2f(y, x), atan2f(y, x), atan2(y, x)); } +GPUdi() float GPUCommonMath::ATan2(float y, float x) { return CHOICE(atan2f(y, x), atan2f(y, x), atan2(y, x)); } -GPUhdi() float GPUCommonMath::Sin(float x) { return CHOICE(sinf(x), sinf(x), sin(x)); } +GPUdi() float GPUCommonMath::Sin(float x) { return CHOICE(sinf(x), sinf(x), sin(x)); } -GPUhdi() float GPUCommonMath::Cos(float x) { return CHOICE(cosf(x), cosf(x), cos(x)); } +GPUdi() float GPUCommonMath::Cos(float x) { return CHOICE(cosf(x), cosf(x), cos(x)); } GPUhdi() void GPUCommonMath::SinCos(float x, float& s, float& c) { @@ -237,9 +238,9 @@ GPUhdi() void GPUCommonMath::SinCos(double x, double& s, double& c) #endif } -GPUhdi() float GPUCommonMath::Tan(float x) { return CHOICE(tanf(x), tanf(x), tan(x)); } +GPUdi() float GPUCommonMath::Tan(float x) { return CHOICE(tanf(x), tanf(x), tan(x)); } -GPUhdi() unsigned int GPUCommonMath::Clz(unsigned int x) +GPUdi() unsigned int GPUCommonMath::Clz(unsigned int x) { #if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__)) && (!defined(__OPENCL__) || defined(__OPENCLCPP__)) return x == 0 ? 32 : CHOICE(__builtin_clz(x), __clz(x), __builtin_clz(x)); // use builtin if available @@ -253,7 +254,7 @@ GPUhdi() unsigned int GPUCommonMath::Clz(unsigned int x) #endif } -GPUhdi() unsigned int GPUCommonMath::Popcount(unsigned int x) +GPUdi() unsigned int GPUCommonMath::Popcount(unsigned int x) { #if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__)) && (!defined(__OPENCL__) /*|| defined(__OPENCLCPP__)*/) // TODO: remove OPENCLCPP workaround when reported SPIR-V bug is fixed return CHOICE(__builtin_popcount(x), __popc(x), __builtin_popcount(x)); // use builtin if available @@ -271,17 +272,17 @@ GPUhdi() unsigned int GPUCommonMath::Popcount(unsigned int x) template <class T> GPUhdi() T GPUCommonMath::Min(const T x, const T y) { - return CHOICE(std::min(x, y), std::min(x, y), (x < y ? x : y)); + return CHOICE(std::min(x, y), min(x, y), (x < y ? x : y)); } template <class T> GPUhdi() T GPUCommonMath::Max(const T x, const T y) { - return CHOICE(std::max(x, y), std::max(x, y), (x > y ? x : y)); + return CHOICE(std::max(x, y), max(x, y), (x > y ? x : y)); } template <class T, class S, class R> -GPUhdi() T GPUCommonMath::MinWithRef(T x, T y, S refX, S refY, R& r) +GPUdi() T GPUCommonMath::MinWithRef(T x, T y, S refX, S refY, R& r) { if (x < y) { r = refX; @@ -292,7 +293,7 @@ GPUhdi() T GPUCommonMath::MinWithRef(T x, T y, S refX, S refY, R& r) } template <class T, class S, class R> -GPUhdi() T GPUCommonMath::MaxWithRef(T x, T y, S refX, S refY, R& r) +GPUdi() T GPUCommonMath::MaxWithRef(T x, T y, S refX, S refY, R& r) { if (x > y) { r = refX; @@ -303,7 +304,7 @@ GPUhdi() T GPUCommonMath::MaxWithRef(T x, T y, S refX, S refY, R& r) } template <class T, class S, class R> -GPUhdi() T GPUCommonMath::MaxWithRef(T x, T y, T z, T w, S refX, S refY, S refZ, S refW, R& r) +GPUdi() T GPUCommonMath::MaxWithRef(T x, T y, T z, T w, S refX, S refY, S refZ, S refW, R& r) { T retVal = x; S retRef = refX; @@ -325,7 +326,7 @@ GPUhdi() T GPUCommonMath::MaxWithRef(T x, T y, T z, T w, S refX, S refY, S refZ, GPUhdi() float GPUCommonMath::Sqrt(float x) { return CHOICE(sqrtf(x), sqrtf(x), sqrt(x)); } -GPUhdi() float GPUCommonMath::FastInvSqrt(float _x) +GPUdi() float GPUCommonMath::FastInvSqrt(float _x) { // the function calculates fast inverse sqrt union { @@ -358,9 +359,9 @@ GPUhdi() int GPUCommonMath::Abs<int>(int x) return CHOICE(abs(x), abs(x), abs(x)); } -GPUhdi() float GPUCommonMath::ASin(float x) { return CHOICE(asinf(x), asinf(x), asin(x)); } +GPUdi() float GPUCommonMath::ASin(float x) { return CHOICE(asinf(x), asinf(x), asin(x)); } -GPUhdi() float GPUCommonMath::Log(float x) { return CHOICE(logf(x), logf(x), log(x)); } +GPUdi() float GPUCommonMath::Log(float x) { return CHOICE(logf(x), logf(x), log(x)); } GPUhdi() float GPUCommonMath::Copysign(float x, float y) { diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index 6d8c8cbce5ed6..de0e15928f535 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -18,7 +18,7 @@ // These are basic and non-comprex data types, which will also be visible on the GPU. // Please add complex data types required on the host but not GPU to GPUHostDataTypes.h and forward-declare! -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstddef> #endif #ifdef GPUCA_NOCOMPAT_ALLOPENCL @@ -85,7 +85,7 @@ namespace gpu #define GPUCA_RECO_STEP GPUDataTypes #endif -#ifdef __OPENCL__ +#if defined(__OPENCL__) && !defined(__OPENCLCPP__) MEM_CLASS_PRE() // Macro with some template magic for OpenCL 1.2 #endif class GPUTPCTrack; diff --git a/GPU/GPUTracking/Base/GPUGeneralKernels.h b/GPU/GPUTracking/Base/GPUGeneralKernels.h index 50289adeaec35..f9e7d8a9e6a52 100644 --- a/GPU/GPUTracking/Base/GPUGeneralKernels.h +++ b/GPU/GPUTracking/Base/GPUGeneralKernels.h @@ -17,6 +17,7 @@ #include "GPUDef.h" #include "GPUDataTypes.h" +#ifndef GPUCA_GPUCODE_GENRTC #ifdef GPUCA_GPUCODE #ifdef __CUDACC__ #include <cub/cub.cuh> @@ -26,6 +27,7 @@ #define GPUCA_CUB hipcub #endif #endif +#endif namespace GPUCA_NAMESPACE { @@ -52,7 +54,7 @@ class GPUKernelTemplate template <class T, int I> struct GPUSharedMemoryScan64 { // Provides the shared memory resources for CUB collectives -#if (defined(__CUDACC__) || defined(__HIPCC__)) && defined(GPUCA_GPUCODE) +#if (defined(__CUDACC__) || defined(__HIPCC__)) && defined(GPUCA_GPUCODE) && !defined(GPUCA_GPUCODE_GENRTC) typedef GPUCA_CUB::BlockScan<T, I> BlockScan; typedef GPUCA_CUB::BlockReduce<T, I> BlockReduce; typedef GPUCA_CUB::WarpScan<T> WarpScan; diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index b7fa6225ba4c2..00f03ebaba744 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -15,7 +15,7 @@ #define GPUSETTINGS_H #include "GPUCommonDef.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <vector> #include <string> #endif diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 7dd1b795c6a83..22a2ba4e7fc4e 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -75,4 +75,4 @@ if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") endif() # Since -target_link_libraries(${targetName} PRIVATE cuda cudart) +target_link_libraries(${targetName} PRIVATE cuda cudart nvrtc) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu new file mode 100644 index 0000000000000..52ebaf6fb9a03 --- /dev/null +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu @@ -0,0 +1,27 @@ +// 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 GPUReconstructionCUDArtc.cu +/// \author David Rohr + +#include <cuda_runtime.h> +#include <cuda.h> + +#include "GPUReconstructionCUDArtcPre.h" + +#define GPUCA_GPUTYPE_TURING +#include "GPUReconstructionIncludesDevice.h" + +extern "C" __global__ void foo() +{ + if (threadIdx.x || blockIdx.x) + return; + printf("test\n"); +} diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h new file mode 100644 index 0000000000000..d994f04c93a1e --- /dev/null +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h @@ -0,0 +1,31 @@ +// 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 GPUReconstructionCUDArtcPre.h +/// \author David Rohr + +//#include <cub/block/block_scan.cuh> +//#include <thrust/sort.h> +//#include <thrust/execution_policy.h> +//#include <thrust/device_ptr.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(...) +{ +} diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 5ec50793667ac..f183f8957872e 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -349,6 +349,7 @@ GPUdi() bool GPUTPCCompressionGatherKernels::isAlignedTo(const S* ptr) { return reinterpret_cast<size_t>(ptr) % alignof(T) == 0; } + return false; // BUG: Cuda complains about missing return value with constexpr if } template <> diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index df3d27498ec94..69817111e7309 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -13,17 +13,17 @@ #define GPUCA_CADEBUG 0 -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstdio> #include <cstring> #include <cmath> +#include "GPUReconstruction.h" #endif #include "GPUTPCTracker.h" #include "GPUTPCClusterData.h" #include "GPUTPCTrackParam.h" #include "GPUTPCGMMerger.h" -#include "GPUReconstruction.h" #include "GPUO2DataTypes.h" #include "TPCFastTransform.h" #include "GPUTPCConvertImpl.h" @@ -691,7 +691,7 @@ GPUd() void GPUTPCGMMerger::MergeBorderTracks<1>(int nBlocks, int nThreads, int } } -#if defined(__CUDACC__) || defined(__HIPCC__) // Specialize MergeBorderTracks<3> +#if (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(GPUCA_GPUCODE_GENRTC) // Specialize MergeBorderTracks<3> struct MergeBorderTracks_compMax { GPUd() bool operator()(const GPUTPCGMBorderRange& a, const GPUTPCGMBorderRange& b) { @@ -1725,7 +1725,7 @@ GPUd() void GPUTPCGMMerger::PrepareClustersForFit0(int nBlocks, int nThreads, in } } -#if defined(__CUDACC__) || defined(__HIPCC__) // Specialize GPUTPCGMMergerSortTracks and GPUTPCGMMergerSortTracksQPt +#if (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(GPUCA_GPUCODE_GENRTC) // Specialize GPUTPCGMMergerSortTracks and GPUTPCGMMergerSortTracksQPt struct GPUTPCGMMergerSortTracks_comp { const GPUTPCGMMergedTrack* const mCmp; GPUhd() GPUTPCGMMergerSortTracks_comp(GPUTPCGMMergedTrack* cmp) : mCmp(cmp) {} diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index cbf6050271cb8..bf31f6efb47ad 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -19,10 +19,6 @@ #include "GPUParam.inc" #include "GPUTPCGMMergerTypes.h" -#ifndef __OPENCL__ -#include <cmath> -#endif - #if defined(GPUCA_GM_USE_FULL_FIELD) #include "AliTracker.h" #include "AliMagF.h" diff --git a/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx b/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx index c91de763bc92b..c7b8b67ac8cc9 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx @@ -18,9 +18,6 @@ #include "GPUTPCGMMerger.h" #include "GPUTPCConvertImpl.h" #include "GPUParam.inc" -#ifndef __OPENCLCPP__ -#include <cmath> -#endif using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index b9b3482a317d3..d5dcb2936d9e6 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -42,7 +42,7 @@ #include "AliHLTTPCClusterMCData.h" #endif -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cmath> #include <cstdlib> #endif diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h index 233231d2618d5..756f012b7eac9 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h @@ -19,7 +19,7 @@ #include "GPUCommonMath.h" #include "GPUdEdxInfo.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstddef> #endif diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx index 474ed31c54f76..ddf0c76d5ad33 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx @@ -15,16 +15,16 @@ #include "GPUTPCClusterData.h" #include "GPUTPCHit.h" #include "GPUTPCSliceData.h" -#include "GPUReconstruction.h" #include "GPUProcessor.h" #include "GPUO2DataTypes.h" #include "GPUTPCConvertImpl.h" #include "GPUCommonMath.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include "utils/vecpod.h" #include <iostream> #include <cstring> +#include "GPUReconstruction.h" #endif using namespace GPUCA_NAMESPACE::gpu; diff --git a/GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh b/GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh new file mode 100755 index 0000000000000..a23e8a23e1a78 --- /dev/null +++ b/GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh @@ -0,0 +1,16 @@ +#!/bin/bash +cat <<EOT > 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 <type_traits> +int main(int, char**) {return 0;} +EOT +nvcc -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 \ + ~/alice/O2/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu \ +| sed '1,/^# 1 ".*GPUReconstructionCUDArtcPre.h" 1$/d' \ +>> source.cu diff --git a/GPU/GPUTracking/Standalone/tools/rtc/test.cu b/GPU/GPUTracking/Standalone/tools/rtc/test.cu new file mode 100644 index 0000000000000..c99aab15f342b --- /dev/null +++ b/GPU/GPUTracking/Standalone/tools/rtc/test.cu @@ -0,0 +1,86 @@ +#include <cuda.h> +#include <nvrtc.h> +#include <iostream> + +#define NVRTC_SAFE_CALL(x) \ + do { \ + nvrtcResult result = x; \ + if (result != NVRTC_SUCCESS) { \ + std::cerr << "\nerror: " #x " failed with error " \ + << nvrtcGetErrorString(result) << '\n'; \ + exit(1); \ + } \ + } while (0) + +#define CUDA_SAFE_CALL(x) \ + do { \ + CUresult result = x; \ + if (result != CUDA_SUCCESS) { \ + const char* msg; \ + cuGetErrorName(result, &msg); \ + std::cerr << "\nerror: " #x " failed with error " \ + << msg << '\n'; \ + exit(1); \ + } \ + } while (0) + +int main(int argc, char** argv) +{ + //Read Sourcecode from file + unsigned int filesize; + FILE* pFile; + //Open file + if ((pFile = fopen("source.cu", "rb")) == NULL) + exit(1); + //Optain File Size + fseek(pFile, 0, SEEK_END); + filesize = ftell(pFile); + rewind(pFile); + //Read file + char* sourceCode = new char[filesize + 1]; + if (fread(sourceCode, 1, filesize, pFile) != filesize) + exit(1); + //Make sourceCode 0-terminated + sourceCode[filesize] = 0; + fclose(pFile); + + nvrtcProgram prog; + NVRTC_SAFE_CALL(nvrtcCreateProgram(&prog, // prog + sourceCode, // buffer + "saxpy.cu", // name + 0, // numHeaders + NULL, // headers + NULL)); // includeNames + delete[] sourceCode; + //const char *opts[] = {"-default-device -std=c++17 --extended-lambda -Xptxas -O4 -Xcompiler -O4 -use_fast_math --ftz=true"}; + const char* opts[] = {"-default-device", "--std=c++17", "-use_fast_math", "-ftz=true"}; + nvrtcResult compileResult = nvrtcCompileProgram(prog, // prog + sizeof(opts) / sizeof(opts[0]), // numOptions + opts); // options + size_t logSize; + NVRTC_SAFE_CALL(nvrtcGetProgramLogSize(prog, &logSize)); + char* log = new char[logSize]; + NVRTC_SAFE_CALL(nvrtcGetProgramLog(prog, log)); + std::cout << log << '\n'; + delete[] log; + if (compileResult != NVRTC_SUCCESS) { + exit(1); + } + size_t ptxSize; + NVRTC_SAFE_CALL(nvrtcGetPTXSize(prog, &ptxSize)); + char* ptx = new char[ptxSize]; + NVRTC_SAFE_CALL(nvrtcGetPTX(prog, ptx)); + NVRTC_SAFE_CALL(nvrtcDestroyProgram(&prog)); + CUmodule module; + CUfunction kernel; + CUDA_SAFE_CALL(cuModuleLoadDataEx(&module, ptx, 0, 0, 0)); + CUDA_SAFE_CALL(cuModuleGetFunction(&kernel, module, "foo")); + void* args[] = {}; + CUDA_SAFE_CALL( + cuLaunchKernel(kernel, + 1, 1, 1, // grid dim + 32, 1, 1, // block dim + 0, NULL, // shared mem and stream + args, 0)); // arguments + return 0; +} diff --git a/GPU/GPUTracking/Standalone/utils/bitfield.h b/GPU/GPUTracking/Standalone/utils/bitfield.h index 981804b4bb2af..366de17584713 100644 --- a/GPU/GPUTracking/Standalone/utils/bitfield.h +++ b/GPU/GPUTracking/Standalone/utils/bitfield.h @@ -91,7 +91,7 @@ class bitfield return retVal; } -#ifdef GPUCA_NOCOMPAT_ALLOPENCL +#if defined(GPUCA_NOCOMPAT_ALLOPENCL) && !defined(GPUCA_GPUCODE_DEVICE) static_assert(std::is_integral<S>::value, "Storage type non integral"); static_assert(sizeof(S) >= sizeof(T), "Storage type has insufficient capacity"); #endif diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index f11316502faea..9b06a3267d662 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -22,7 +22,6 @@ #include "GPUTRDTrackletWord.h" #include "GPUTRDGeometry.h" #include "GPUTRDTrackerDebug.h" -#include "GPUReconstruction.h" #include "GPUMemoryResource.h" #include "GPUCommonMath.h" #include "GPUCommonAlgorithm.h" @@ -33,7 +32,8 @@ class GPUTPCGMPolynomialField; #ifndef GPUCA_GPUCODE -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE +#include "GPUReconstruction.h" #ifdef WITH_OPENMP #include <omp.h> #endif diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index ba99f630dc62e..51134e321fbbb 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -24,7 +24,7 @@ #include "GPUTRDTrack.h" #include "GPULogging.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <vector> #endif diff --git a/GPU/GPUTracking/dEdx/GPUdEdx.cxx b/GPU/GPUTracking/dEdx/GPUdEdx.cxx index ff13cdbce96d5..5443b36456ff0 100644 --- a/GPU/GPUTracking/dEdx/GPUdEdx.cxx +++ b/GPU/GPUTracking/dEdx/GPUdEdx.cxx @@ -19,7 +19,9 @@ using namespace GPUCA_NAMESPACE::gpu; +#ifndef GPUCA_GPUCODE_DEVICE GPUd() void GPUdEdx::clear() { new (this) GPUdEdx; } +#endif GPUd() void GPUdEdx::computedEdx(GPUdEdxInfo& GPUrestrict() output, const GPUParam& GPUrestrict() param) { diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.h b/GPU/TPCFastTransformation/TPCFastTransformGeo.h index 4deabbbb1b48d..c8676c61751b1 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.h +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.h @@ -17,7 +17,7 @@ #define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_TPCFASTTRANSFORMGEO_H #include "GPUCommonDef.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <memory> #endif diff --git a/GPU/Utils/FlatObject.h b/GPU/Utils/FlatObject.h index 9299f1f0da1b8..0f973a2256ba9 100644 --- a/GPU/Utils/FlatObject.h +++ b/GPU/Utils/FlatObject.h @@ -386,30 +386,7 @@ inline void FlatObject::cloneFromObject(const FlatObject& obj, char* newFlatBuff std::memcpy(mFlatBufferPtr, obj.mFlatBufferPtr, obj.mFlatBufferSize); mConstructionMask = (unsigned int)ConstructionState::Constructed; } -#endif - -inline char* FlatObject::releaseInternalBuffer() -{ - // returns an pointer to the internal buffer. Makes the internal container variable empty. - char* contPtr = mFlatBufferContainer; - mFlatBufferContainer = nullptr; - return contPtr; -} - -inline void FlatObject::adoptInternalBuffer(char* buf) -{ - // buf becomes the new internal buffer, after it was already set as new setActualBufferAddress - assert((mFlatBufferPtr == buf)); - mFlatBufferContainer = buf; -} - -inline void FlatObject::clearInternalBufferPtr() -{ - // we just release the internal buffer ressetting it to nullptr - mFlatBufferContainer = nullptr; -} -#ifndef GPUCA_GPUCODE // code invisible on GPU inline void FlatObject::moveBufferTo(char* newFlatBufferPtr) { /// sets buffer pointer to the new address, move the buffer content there. @@ -423,33 +400,70 @@ inline void FlatObject::moveBufferTo(char* newFlatBufferPtr) mFlatBufferContainer = mFlatBufferPtr; } } -#endif -inline void FlatObject::setActualBufferAddress(char* actualFlatBufferPtr) +template <class T> +inline std::string FlatObject::stressTest(T& obj) { - /// Sets the actual location of the external flat buffer after it has been moved (i.e. to another maschine) + /// Test the flat object functionality for an object of a child class T + /// the obj is modified here. Check if it is functional after the test. /// - /// It sets mFlatBufferPtr to actualFlatBufferPtr. - /// A daughter class should update all the pointers inside the buffer in the new location. + std::string err; - mFlatBufferPtr = actualFlatBufferPtr; + if (!obj.isConstructed()) + return "tested object is not constructed!"; + + T tst; + tst.cloneFromObject(obj, nullptr); + if (!tst.isConstructed() || !tst.isBufferInternal()) + return "error at cloneFromObject()!"; + + obj.destroy(); + + char* buf0 = tst.releaseInternalBuffer(); + char* buf1 = new char[tst.getFlatBufferSize()]; + char* buf2 = new char[tst.getFlatBufferSize()]; + std::memcpy(buf1, tst.getFlatBufferPtr(), tst.getFlatBufferSize()); + tst.setActualBufferAddress(buf1); + delete[] buf0; + + tst.setFutureBufferAddress(buf2); + std::memcpy(buf2, buf1, tst.getFlatBufferSize()); + delete[] buf1; + + if (tst.isBufferInternal()) + return err = "error, buffer should be external!"; + + tst.adoptInternalBuffer(buf2); + if (!tst.isBufferInternal()) + return err = "error, buffer should be internal!"; + + obj.cloneFromObject(tst, nullptr); + if (!obj.isBufferInternal()) + return err = "error, buffer should be internal!"; + + return err; } -inline void FlatObject::setFutureBufferAddress(char* futureFlatBufferPtr) +inline void FlatObject::printC() const { - /// Sets a future location of the external flat buffer before moving it to this location. - /// - /// A daughter class should already reset all the pointers inside the current buffer to the future location - /// without touching memory in the future location. - - assert(!isBufferInternal()); - mFlatBufferPtr = futureFlatBufferPtr; -#ifndef GPUCA_GPUCODE // code invisible on GPU - delete[] mFlatBufferContainer; // for a case.. -#endif // !GPUCA_GPUCODE - mFlatBufferContainer = nullptr; + /// Print the content of the flat buffer + bool lfdone = false; + for (int i = 0; i < mFlatBufferSize; i++) { + unsigned char v = mFlatBufferPtr[i]; + lfdone = false; + printf("0x%02x ", v); + if (i && ((i + 1) % 20) == 0) { + printf("\n"); + lfdone = true; + } + } + if (!lfdone) { + printf("\n"); + } } +#endif // GPUCA_GPUCODE + #if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU template <class T, class TFile> inline int FlatObject::writeToFile(T& obj, TFile& outf, const char* name) @@ -494,72 +508,57 @@ inline T* FlatObject::readFromFile(TFile& inpf, const char* name) pobj->setActualBufferAddress(pobj->mFlatBufferContainer); return pobj; } -#endif +#endif // GPUCA_GPUCODE || GPUCA_STANDALONE -#if !defined(GPUCA_GPUCODE) // code invisible on GPU +#ifndef GPUCA_GPUCODE_DEVICE -template <class T> -inline std::string FlatObject::stressTest(T& obj) +inline char* FlatObject::releaseInternalBuffer() { - /// Test the flat object functionality for an object of a child class T - /// the obj is modified here. Check if it is functional after the test. - /// - std::string err; - - if (!obj.isConstructed()) - return "tested object is not constructed!"; - - T tst; - tst.cloneFromObject(obj, nullptr); - if (!tst.isConstructed() || !tst.isBufferInternal()) - return "error at cloneFromObject()!"; - - obj.destroy(); - - char* buf0 = tst.releaseInternalBuffer(); - char* buf1 = new char[tst.getFlatBufferSize()]; - char* buf2 = new char[tst.getFlatBufferSize()]; - std::memcpy(buf1, tst.getFlatBufferPtr(), tst.getFlatBufferSize()); - tst.setActualBufferAddress(buf1); - delete[] buf0; - - tst.setFutureBufferAddress(buf2); - std::memcpy(buf2, buf1, tst.getFlatBufferSize()); - delete[] buf1; + // returns an pointer to the internal buffer. Makes the internal container variable empty. + char* contPtr = mFlatBufferContainer; + mFlatBufferContainer = nullptr; + return contPtr; +} - if (tst.isBufferInternal()) - return err = "error, buffer should be external!"; +inline void FlatObject::adoptInternalBuffer(char* buf) +{ + // buf becomes the new internal buffer, after it was already set as new setActualBufferAddress + assert((mFlatBufferPtr == buf)); + mFlatBufferContainer = buf; +} - tst.adoptInternalBuffer(buf2); - if (!tst.isBufferInternal()) - return err = "error, buffer should be internal!"; +inline void FlatObject::clearInternalBufferPtr() +{ + // we just release the internal buffer ressetting it to nullptr + mFlatBufferContainer = nullptr; +} - obj.cloneFromObject(tst, nullptr); - if (!obj.isBufferInternal()) - return err = "error, buffer should be internal!"; +inline void FlatObject::setActualBufferAddress(char* actualFlatBufferPtr) +{ + /// Sets the actual location of the external flat buffer after it has been moved (i.e. to another maschine) + /// + /// It sets mFlatBufferPtr to actualFlatBufferPtr. + /// A daughter class should update all the pointers inside the buffer in the new location. - return err; + mFlatBufferPtr = actualFlatBufferPtr; } -inline void FlatObject::printC() const +inline void FlatObject::setFutureBufferAddress(char* futureFlatBufferPtr) { - /// Print the content of the flat buffer - bool lfdone = false; - for (int i = 0; i < mFlatBufferSize; i++) { - unsigned char v = mFlatBufferPtr[i]; - lfdone = false; - printf("0x%02x ", v); - if (i && ((i + 1) % 20) == 0) { - printf("\n"); - lfdone = true; - } - } - if (!lfdone) { - printf("\n"); - } + /// Sets a future location of the external flat buffer before moving it to this location. + /// + /// A daughter class should already reset all the pointers inside the current buffer to the future location + /// without touching memory in the future location. + + assert(!isBufferInternal()); + mFlatBufferPtr = futureFlatBufferPtr; +#ifndef GPUCA_GPUCODE // code invisible on GPU + delete[] mFlatBufferContainer; // for a case.. +#endif // !GPUCA_GPUCODE + mFlatBufferContainer = nullptr; } -#endif // GPUCA_GPUCODE +#endif //GPUCA_GPUCODE_DEVICE } // namespace gpu } // namespace GPUCA_NAMESPACE From 2af2a272c49acda4ce807c34cd33e74813d18881 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 27 Aug 2020 17:46:16 +0200 Subject: [PATCH 0485/1751] Don't mess with the NDEBUG settings of other people --- GPU/Utils/FlatObject.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/GPU/Utils/FlatObject.h b/GPU/Utils/FlatObject.h index 0f973a2256ba9..c4896e50c0f8b 100644 --- a/GPU/Utils/FlatObject.h +++ b/GPU/Utils/FlatObject.h @@ -16,8 +16,6 @@ #ifndef ALICEOW_GPUCOMMON_TPCFASTTRANSFORMATION_FLATOBJECT_H #define ALICEOW_GPUCOMMON_TPCFASTTRANSFORMATION_FLATOBJECT_H -#undef NDEBUG - #if !defined(GPUCA_GPUCODE_DEVICE) #include <cstddef> #include <memory> From ac62bbd35b08a5ad6ab685610018145b8c1d29d5 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 28 Aug 2020 02:14:40 +0200 Subject: [PATCH 0486/1751] DPL Analysis: fix for index hierarchy not being bound (#4234) --- Framework/Core/include/Framework/AnalysisTask.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 46b2eaef2c5ce..6f7a297127587 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -989,6 +989,13 @@ struct AnalysisDataProcessorBuilder { }; groupingTable.bindExternalIndices(&std::get<std::decay_t<Associated>>(associatedTables)...); + // always pre-bind full tables to support index hierarchy + std::apply( + [&](auto&&... x) { + (binder(x), ...); + }, + associatedTables); + if constexpr (soa::is_soa_iterator_t<std::decay_t<G>>::value) { // grouping case auto slicer = GroupSlicer(groupingTable, associatedTables); @@ -1013,12 +1020,6 @@ struct AnalysisDataProcessorBuilder { } else { // non-grouping case - std::apply( - [&](auto&&... x) { - (binder(x), ...); - }, - associatedTables); - // bind partitions and grouping table std::apply([&groupingTable](auto&... x) { (PartitionManager<std::decay_t<decltype(x)>>::bindExternalIndices(x, &groupingTable), ...); From 909154454f53828ecdf8f1a72fbef79d2e3c266a Mon Sep 17 00:00:00 2001 From: Luca Barioglio <luca.barioglio@cern.ch> Date: Wed, 26 Aug 2020 16:57:15 +0200 Subject: [PATCH 0487/1751] Fix grouping of rare topologies --- .../DataFormatsITSMFT/TopologyDictionary.h | 12 +-- .../ITSMFT/common/src/TopologyDictionary.cxx | 3 +- .../BuildTopologyDictionary.h | 2 +- .../include/ITSMFTReconstruction/LookUp.h | 2 +- .../src/BuildTopologyDictionary.cxx | 77 +++++++++---------- .../common/reconstruction/src/LookUp.cxx | 8 +- macro/compareTopologyDistributions.C | 5 +- 7 files changed, 55 insertions(+), 54 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h index f46c244b0852e..5938126cb7485 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h @@ -73,11 +73,11 @@ class TopologyDictionary /// constexpr for the definition of the groups of rare topologies. /// The attritbution of the group ID is stringly dependent on the following parameters: it must be a power of 2. - static constexpr int RowClassSpan = 4; ///< Row span of the classes of rare topologies - static constexpr int ColClassSpan = 4; ///< Column span of the classes of rare topologies - static constexpr int MinimumClassArea = RowClassSpan * ColClassSpan; ///< Area of the smallest class of rare topologies (used as reference) - static constexpr int MaxNumberOfClasses = ClusterPattern::MaxPatternBits / MinimumClassArea; ///< Maximum number of row/column classes for the groups of rare topologies - static constexpr int NumberOfRareGroups = MaxNumberOfClasses * MaxNumberOfClasses; ///< Number of entries corresponding to groups of rare topologies (those whos matrix exceed the max number of bytes are empty). + static constexpr int RowClassSpan = 4; ///< Row span of the classes of rare topologies + static constexpr int ColClassSpan = 4; ///< Column span of the classes of rare topologies + static constexpr int MaxNumberOfRowClasses = 1 + (ClusterPattern::MaxRowSpan - 1) / RowClassSpan; ///< Maximum number of row classes for the groups of rare topologies + static constexpr int MaxNumberOfColClasses = 1 + (ClusterPattern::MaxColSpan - 1) / ColClassSpan; ///< Maximum number of col classes for the groups of rare topologies + static constexpr int NumberOfRareGroups = MaxNumberOfRowClasses * MaxNumberOfColClasses; ///< Number of entries corresponding to groups of rare topologies (those whos matrix exceed the max number of bytes are empty). /// Prints the dictionary friend std::ostream& operator<<(std::ostream& os, const TopologyDictionary& dictionary); /// Prints the dictionary in a binary file @@ -169,7 +169,7 @@ class TopologyDictionary int mSmallTopologiesLUT[8 * 255 + 1]; ///< Look-Up Table for the topologies with 1-byte linearised matrix std::vector<GroupStruct> mVectorOfIDs; ///< Vector of topologies and groups - ClassDefNV(TopologyDictionary, 3); + ClassDefNV(TopologyDictionary, 4); }; // namespace itsmft } // namespace itsmft } // namespace o2 diff --git a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx index 4b56f7d110d06..45b33b3e32825 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx @@ -40,8 +40,9 @@ TopologyDictionary::TopologyDictionary(std::string fileName) std::ostream& operator<<(std::ostream& os, const TopologyDictionary& dict) { + int ID = 0; for (auto& p : dict.mVectorOfIDs) { - os << "Hash: " << p.mHash << " ErrX: " << p.mErrX << " ErrZ : " << p.mErrZ << " xCOG: " << p.mXCOG << " zCOG: " << p.mZCOG << " Npixels: " << p.mNpixels << " Frequency: " << p.mFrequency << " isGroup : " << std::boolalpha << p.mIsGroup << std::endl + os << "ID: " << ID++ << " Hash: " << p.mHash << " ErrX: " << p.mErrX << " ErrZ : " << p.mErrZ << " xCOG: " << p.mXCOG << " zCOG: " << p.mZCOG << " Npixles: " << p.mNpixels << " Frequency: " << p.mFrequency << " isGroup : " << std::boolalpha << p.mIsGroup << std::endl << p.mPattern << std::endl << "*********************************************************" << std::endl << std::endl; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h index 12114b7f9ce5a..97d28e542bd1b 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h @@ -82,7 +82,7 @@ class BuildTopologyDictionary std::unordered_map<long unsigned, TopologyInfo> mMapInfo; - ClassDefNV(BuildTopologyDictionary, 3); + ClassDefNV(BuildTopologyDictionary, 4); }; } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h index fd504e6f4694c..44594da48d07b 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h @@ -45,7 +45,7 @@ class LookUp TopologyDictionary mDictionary; int mTopologiesOverThreshold; - ClassDefNV(LookUp, 2); + ClassDefNV(LookUp, 3); }; } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx index 70c3ce701ae11..f22604766f14d 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx @@ -156,56 +156,53 @@ void BuildTopologyDictionary::groupRareTopologies() mDictionary.mVectorOfIDs.push_back(gr); } // groupRareTopologies based on binning over number of rows and columns (TopologyDictionary::NumberOfRowClasses * - // NumberOfColClasse) + // NumberOfColClasses) std::unordered_map<int, std::pair<GroupStruct, unsigned long>> tmp_GroupMap; //<group ID, <Group struct, counts>> int grNum = 0; int rowBinEdge = 0; int colBinEdge = 0; - for (int iRowClass = 0; iRowClass < TopologyDictionary::MaxNumberOfClasses; iRowClass++) { - for (int iColClass = 0; iColClass < TopologyDictionary::MaxNumberOfClasses; iColClass++) { - if ((iRowClass + 1) * (iColClass + 1) <= TopologyDictionary::MaxNumberOfClasses) { - rowBinEdge = (iRowClass + 1) * TopologyDictionary::RowClassSpan; - colBinEdge = (iColClass + 1) * TopologyDictionary::ColClassSpan; - grNum = LookUp::groupFinder(rowBinEdge, colBinEdge); - // Create a structure for a group of rare topologies - GroupStruct gr; - gr.mHash = (((unsigned long)(grNum)) << 32) & 0xffffffff00000000; - gr.mErrX = (rowBinEdge)*o2::itsmft::SegmentationAlpide::PitchRow / std::sqrt(12); - gr.mErrZ = (colBinEdge)*o2::itsmft::SegmentationAlpide::PitchCol / std::sqrt(12); - gr.mErr2X = gr.mErrX * gr.mErrX; - gr.mErr2Z = gr.mErrZ * gr.mErrZ; - gr.mXCOG = 0; - gr.mZCOG = 0; - gr.mNpixels = rowBinEdge * colBinEdge; - gr.mIsGroup = true; - gr.mFrequency = 0.; - /// A dummy pattern with all fired pixels in the bounding box is assigned to groups of rare topologies. - unsigned char dummyPattern[ClusterPattern::kExtendedPatternBytes] = {0}; - dummyPattern[0] = (unsigned char)rowBinEdge; - dummyPattern[1] = (unsigned char)colBinEdge; - int nBits = rowBinEdge * colBinEdge; - int nBytes = nBits / 8; - for (int iB = 2; iB < nBytes + 2; iB++) { - dummyPattern[iB] = (unsigned char)255; - } - int residualBits = nBits % 8; - if (residualBits) { - unsigned char tempChar = 0; - while (residualBits > 0) { - residualBits--; - tempChar |= 1 << (7 - residualBits); - } - dummyPattern[nBytes + 2] = tempChar; + for (int iRowClass = 0; iRowClass < TopologyDictionary::MaxNumberOfRowClasses; iRowClass++) { + for (int iColClass = 0; iColClass < TopologyDictionary::MaxNumberOfColClasses; iColClass++) { + rowBinEdge = (iRowClass + 1) * TopologyDictionary::RowClassSpan; + colBinEdge = (iColClass + 1) * TopologyDictionary::ColClassSpan; + grNum = LookUp::groupFinder(rowBinEdge, colBinEdge); + // Create a structure for a group of rare topologies + GroupStruct gr; + gr.mHash = (((unsigned long)(grNum)) << 32) & 0xffffffff00000000; + gr.mErrX = (rowBinEdge)*o2::itsmft::SegmentationAlpide::PitchRow / std::sqrt(12); + gr.mErrZ = (colBinEdge)*o2::itsmft::SegmentationAlpide::PitchCol / std::sqrt(12); + gr.mErr2X = gr.mErrX * gr.mErrX; + gr.mErr2Z = gr.mErrZ * gr.mErrZ; + gr.mXCOG = 0; + gr.mZCOG = 0; + gr.mNpixels = rowBinEdge * colBinEdge; + gr.mIsGroup = true; + gr.mFrequency = 0.; + /// A dummy pattern with all fired pixels in the bounding box is assigned to groups of rare topologies. + unsigned char dummyPattern[ClusterPattern::kExtendedPatternBytes] = {0}; + dummyPattern[0] = (unsigned char)rowBinEdge; + dummyPattern[1] = (unsigned char)colBinEdge; + int nBits = rowBinEdge * colBinEdge; + int nBytes = nBits / 8; + for (int iB = 2; iB < nBytes + 2; iB++) { + dummyPattern[iB] = (unsigned char)255; + } + int residualBits = nBits % 8; + if (residualBits) { + unsigned char tempChar = 0; + while (residualBits > 0) { + residualBits--; + tempChar |= 1 << (7 - residualBits); } - gr.mPattern.setPattern(dummyPattern); - // Filling the map for groups - tmp_GroupMap[grNum] = std::make_pair(gr, 0); + dummyPattern[nBytes + 2] = tempChar; } + gr.mPattern.setPattern(dummyPattern); + // Filling the map for groups + tmp_GroupMap[grNum] = std::make_pair(gr, 0); } } - int rs; int cs; int index; diff --git a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx index 2aaf9cda3162b..d8bbc3781db9f 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx @@ -47,11 +47,13 @@ int LookUp::groupFinder(int nRow, int nCol) if (nCol % TopologyDictionary::RowClassSpan == 0) { col_index--; } - if (row_index > TopologyDictionary::MaxNumberOfClasses || col_index > TopologyDictionary::MaxNumberOfClasses) { - return TopologyDictionary::NumberOfRareGroups - 1; + int grNum = -1; + if (row_index > TopologyDictionary::MaxNumberOfRowClasses || col_index > TopologyDictionary::MaxNumberOfColClasses) { + grNum = TopologyDictionary::NumberOfRareGroups - 1; } else { - return row_index * TopologyDictionary::MaxNumberOfClasses + col_index; + grNum = row_index * TopologyDictionary::MaxNumberOfColClasses + col_index; } + return grNum; } int LookUp::findGroupID(int nRow, int nCol, const unsigned char patt[ClusterPattern::MaxPatternBytes]) diff --git a/macro/compareTopologyDistributions.C b/macro/compareTopologyDistributions.C index 3104cf23d7794..1224eb8a5e120 100644 --- a/macro/compareTopologyDistributions.C +++ b/macro/compareTopologyDistributions.C @@ -24,9 +24,8 @@ void compareTopologyDistributions( string output_file_name = "comparison.root") { if (dictionary_file_name.empty()) { - dictionary_file_name = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, "", ".root"); + dictionary_file_name = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, "", ".bin"); } - TFile dictionary_file(dictionary_file_name.c_str()); o2::itsmft::TopologyDictionary dict; dict.readBinaryFile(dictionary_file_name.c_str()); int dict_size = dict.getSize(); @@ -49,6 +48,8 @@ void compareTopologyDistributions( hRec->Scale(1 / hRec->Integral()); TFile output_file(output_file_name.c_str(), "RECREATE"); + hRec->Write(); + hDictio->Write(); TCanvas* cOut = new TCanvas("cOut", "cOut", 800, 600); cOut->SetLogy(); hDictio->GetYaxis()->SetRangeUser(1.e-8, 1.2); From d1a3639395e138455d20ff725cde819a8b61cc92 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 26 Aug 2020 00:18:15 +0200 Subject: [PATCH 0488/1751] Define dedicated PrimaryVertex class with assignable IR + improve printing --- DataFormats/Reconstruction/CMakeLists.txt | 2 + .../ReconstructionDataFormats/PrimaryVertex.h | 52 +++++++++++++++++++ .../ReconstructionDataFormats/Vertex.h | 41 ++++----------- .../Reconstruction/src/PrimaryVertex.cxx | 45 ++++++++++++++++ .../src/ReconstructionDataFormatsLinkDef.h | 2 + .../CommonDataFormat/InteractionRecord.h | 13 +++-- DataFormats/common/src/InteractionRecord.cxx | 19 +++++-- 7 files changed, 137 insertions(+), 37 deletions(-) create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h create mode 100644 DataFormats/Reconstruction/src/PrimaryVertex.cxx diff --git a/DataFormats/Reconstruction/CMakeLists.txt b/DataFormats/Reconstruction/CMakeLists.txt index a1bd82619d9f0..5ba2f75d63cf1 100644 --- a/DataFormats/Reconstruction/CMakeLists.txt +++ b/DataFormats/Reconstruction/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library(ReconstructionDataFormats src/BaseCluster.cxx src/TrackTPCITS.cxx src/Vertex.cxx + src/PrimaryVertex.cxx src/MatchInfoTOF.cxx src/TrackLTIntegral.cxx src/PID.cxx @@ -29,6 +30,7 @@ o2_target_root_dictionary( include/ReconstructionDataFormats/BaseCluster.h include/ReconstructionDataFormats/TrackTPCITS.h include/ReconstructionDataFormats/Vertex.h + include/ReconstructionDataFormats/PrimaryVertex.h include/ReconstructionDataFormats/MatchInfoTOF.h include/ReconstructionDataFormats/TrackLTIntegral.h include/ReconstructionDataFormats/PID.h diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h new file mode 100644 index 0000000000000..90d6f8ab74277 --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h @@ -0,0 +1,52 @@ +// 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_PRIMARYVERTEX_H +#define ALICEO2_PRIMARYVERTEX_H + +#include "CommonDataFormat/InteractionRecord.h" +#include "ReconstructionDataFormats/Vertex.h" + +namespace o2 +{ +namespace dataformats +{ + +// primary vertex class: position, time with error + IR (by default: not assigned) + +class PrimaryVertex : public Vertex<TimeStampWithError<float, float>> +{ + public: + using Vertex<TimeStampWithError<float, float>>::Vertex; + PrimaryVertex() = default; + PrimaryVertex(const PrimaryVertex&) = default; + ~PrimaryVertex() = default; + + const InteractionRecord& getIR() const { return mIR; } + void setIR(const InteractionRecord& ir) { mIR = ir; } + +#ifndef ALIGPU_GPUCODE + void print() const; + std::string asString() const; +#endif + + protected: + InteractionRecord mIR{}; ///< by default not assigned! + + ClassDefNV(PrimaryVertex, 1); +}; + +#ifndef ALIGPU_GPUCODE +std::ostream& operator<<(std::ostream& os, const o2::dataformats::PrimaryVertex& v); +#endif + +} // namespace dataformats +} // namespace o2 +#endif diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h index 858df1847351c..9749d75c64c71 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h @@ -17,8 +17,6 @@ #include <array> #endif #ifndef ALIGPU_GPUCODE -#include <iomanip> -#include <ios> #include <iosfwd> #endif @@ -104,12 +102,15 @@ class VertexBase // The Stamp template parameter allows to define vertex (time)stamp in different // formats (ITS ROFrame ID, real time + error etc) -template <typename Stamp = o2::dataformats::TimeStamp<int>> +template <typename Stamp> class Vertex : public VertexBase { public: using ushort = unsigned short; - static ushort constexpr FlagsMask = 0xffff; + enum Flags : ushort { + TimeValidated = 0x1 << 0, // Flag that the vertex was validated by external time measurement (e.g. FIT) + FlagsMask = 0xffff + }; Vertex() = default; ~Vertex() = default; @@ -118,19 +119,14 @@ class Vertex : public VertexBase { } -#ifndef ALIGPU_GPUCODE - void print() const; -#endif - ushort getNContributors() const { return mNContributors; } void setNContributors(ushort v) { mNContributors = v; } void addContributor() { mNContributors++; } - ushort getBits() const { return mBits; } - bool isBitSet(int bit) const { return mBits & (FlagsMask & (0x1 << bit)); } - void setBits(ushort b) { mBits = b; } - void setBit(int bit) { mBits |= FlagsMask & (0x1 << bit); } - void resetBit(int bit) { mBits &= ~(FlagsMask & (0x1 << bit)); } + ushort getFlags() const { return mBits; } + bool isFlagSet(uint f) const { return mBits & (FlagsMask & f); } + void setFlags(ushort f) { mBits |= FlagsMask & f; } + void resetFrags(ushort f = FlagsMask) { mBits &= ~(FlagsMask & f); } void setChi2(float v) { mChi2 = v; } float getChi2() const { return mChi2; } @@ -139,32 +135,17 @@ class Vertex : public VertexBase Stamp& getTimeStamp() { return mTimeStamp; } void setTimeStamp(const Stamp& v) { mTimeStamp = v; } - private: + protected: float mChi2 = 0; ///< chi2 or quality of tracks to vertex attachment ushort mNContributors = 0; ///< N contributors ushort mBits = 0; ///< bit field for flags Stamp mTimeStamp; ///< vertex time-stamp - ClassDefNV(Vertex, 2); + ClassDefNV(Vertex, 3); }; #ifndef ALIGPU_GPUCODE std::ostream& operator<<(std::ostream& os, const o2::dataformats::VertexBase& v); - -template <typename Stamp> -inline std::ostream& operator<<(std::ostream& os, const o2::dataformats::Vertex<Stamp>& v) -{ - // stream itself - os << (const VertexBase&)v << " " - << "NCont: " << v.getNContributors() << " Chi2: " << v.getChi2() << " TimeStamp: " << v.getTimeStamp(); - return os; -} - -template <typename Stamp> -void Vertex<Stamp>::print() const -{ - std::cout << *this << std::endl; -} #endif } // namespace dataformats diff --git a/DataFormats/Reconstruction/src/PrimaryVertex.cxx b/DataFormats/Reconstruction/src/PrimaryVertex.cxx new file mode 100644 index 0000000000000..387e707d47fe5 --- /dev/null +++ b/DataFormats/Reconstruction/src/PrimaryVertex.cxx @@ -0,0 +1,45 @@ +// 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 "ReconstructionDataFormats/PrimaryVertex.h" +#include <fmt/printf.h> +#include <iostream> +#include "CommonUtils/StringUtils.h" + +namespace o2 +{ +namespace dataformats +{ + +#ifndef ALIGPU_GPUCODE + +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()); +} + +std::ostream& operator<<(std::ostream& os, const o2::dataformats::PrimaryVertex& v) +{ + // stream itself + os << v.asString(); + return os; +} + +void PrimaryVertex::print() const +{ + std::cout << *this << std::endl; +} + +#endif + +} // namespace dataformats +} // namespace o2 diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index bdf11877fafa0..8016fc3888756 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -35,9 +35,11 @@ #pragma link C++ class o2::dataformats::Vertex < int> + ; #pragma link C++ class o2::dataformats::Vertex < o2::dataformats::TimeStamp < int>> + ; #pragma link C++ class o2::dataformats::Vertex < o2::dataformats::TimeStampWithError < float, float>> + ; +#pragma link C++ class o2::dataformats::PrimaryVertex + ; #pragma link C++ class std::vector < o2::dataformats::Vertex < o2::dataformats::TimeStamp < int>>> + ; #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::DCA + ; diff --git a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h index bbcee574f32ff..b6d34aa5d7605 100644 --- a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h +++ b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h @@ -14,9 +14,11 @@ #define ALICEO2_INTERACTIONRECORD_H #include "GPUCommonRtypes.h" +#ifndef ALIGPU_GPUCODE #include <iosfwd> -#include <cmath> #include <cstdint> +#endif +#include <cmath> #include "CommonConstants/LHCConstants.h" namespace o2 @@ -232,10 +234,11 @@ struct InteractionRecord { return InteractionRecord(l % o2::constants::lhc::LHCMaxBunches, l / o2::constants::lhc::LHCMaxBunches); } +#ifndef ALIGPU_GPUCODE void print() const; - + std::string asString() const; friend std::ostream& operator<<(std::ostream& stream, InteractionRecord const& ir); - +#endif ClassDefNV(InteractionRecord, 3); }; @@ -309,9 +312,11 @@ struct InteractionTimeRecord : public InteractionRecord { return !((*this) > other); } +#ifndef ALIGPU_GPUCODE void print() const; - + std::string asString() const; friend std::ostream& operator<<(std::ostream& stream, InteractionTimeRecord const& ir); +#endif ClassDefNV(InteractionTimeRecord, 1); }; diff --git a/DataFormats/common/src/InteractionRecord.cxx b/DataFormats/common/src/InteractionRecord.cxx index fb4c3459a0435..4ceb8f957a45c 100644 --- a/DataFormats/common/src/InteractionRecord.cxx +++ b/DataFormats/common/src/InteractionRecord.cxx @@ -9,21 +9,32 @@ // or submit itself to any jurisdiction. #include "CommonDataFormat/InteractionRecord.h" #include <iostream> +#include <fmt/printf.h> namespace o2 { -//const double InteractionRecord::DummyTime = InteractionRecord::bc2ns(0xffff,0xffffffff); +#ifndef ALIGPU_GPUCODE + +std::string InteractionRecord::asString() const +{ + return isDummy() ? std::string{"NotSet"} : fmt::format("BCid: {:4d} Orbit: {:6d}", bc, orbit); +} std::ostream& operator<<(std::ostream& stream, o2::InteractionRecord const& ir) { - stream << "BCid: " << ir.bc << " Orbit: " << ir.orbit; + stream << ir.asString(); return stream; } +std::string InteractionTimeRecord::asString() const +{ + return isDummy() ? InteractionRecord::asString() : InteractionRecord::asString() + fmt::format(" |T in BC(ns): {:.3f}", timeInBCNS); +} + std::ostream& operator<<(std::ostream& stream, o2::InteractionTimeRecord const& ir) { - stream << "BCid: " << ir.bc << " Orbit: " << ir.orbit << " T in BC(ns): " << ir.timeInBCNS; + stream << ir.asString(); return stream; } @@ -37,4 +48,6 @@ void InteractionTimeRecord::print() const std::cout << (*this) << std::endl; } +#endif + } // namespace o2 From 9507ca6fba5d851e7d169f0c8b4e009528add7b1 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 26 Aug 2020 00:19:20 +0200 Subject: [PATCH 0489/1751] Add optional PV validation/rejection using FT0 timing --- .../PrimaryVertexReaderSpec.h | 9 ++- .../PrimaryVertexingSpec.h | 7 +- .../src/PrimaryVertexWriterSpec.cxx | 9 +-- .../src/PrimaryVertexingSpec.cxx | 21 ++++-- .../src/primary-vertexing-workflow.cxx | 8 ++- Detectors/Vertexing/CMakeLists.txt | 1 + .../include/DetectorsVertexing/PVertexer.h | 39 ++++++----- .../DetectorsVertexing/PVertexerHelpers.h | 12 ++-- .../DetectorsVertexing/PVertexerParams.h | 8 +++ Detectors/Vertexing/src/PVertexer.cxx | 70 +++++++++++++++---- Detectors/Vertexing/src/PVertexerHelpers.cxx | 2 +- 11 files changed, 127 insertions(+), 59 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h index ee18c953b6a08..a9b9f5729c0ce 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h @@ -21,7 +21,7 @@ #include "CommonDataFormat/TimeStamp.h" #include "CommonDataFormat/RangeReference.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "ReconstructionDataFormats/PrimaryVertex.h" #include "SimulationDataFormat/MCEventLabel.h" namespace o2 @@ -32,10 +32,9 @@ namespace vertexing class PrimaryVertexReader : public o2::framework::Task { - using TimeEst = o2::dataformats::TimeStampWithError<float, float>; - using Vertex = o2::dataformats::Vertex<TimeEst>; - using V2TRef = o2::dataformats::RangeReference<int, int>; using Label = o2::MCEventLabel; + using V2TRef = o2::dataformats::RangeReference<int, int>; + using PVertex = o2::dataformats::PrimaryVertex; public: PrimaryVertexReader(bool useMC) : mUseMC(useMC) {} @@ -48,7 +47,7 @@ class PrimaryVertexReader : public o2::framework::Task bool mUseMC = false; - std::vector<Vertex> mVertices, *mVerticesPtr = &mVertices; + std::vector<PVertex> mVertices, *mVerticesPtr = &mVertices; std::vector<int> mPVTrIdx, *mPVTrIdxPtr = &mPVTrIdx; std::vector<V2TRef> mPV2TrIdx, *mPV2TrIdxPtr = &mPV2TrIdx; std::vector<Label> mLabels, *mLabelsPtr = &mLabels; diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h index 24cded57599bb..b419f788dc220 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h @@ -28,7 +28,7 @@ using namespace o2::framework; class PrimaryVertexingSpec : public Task { public: - PrimaryVertexingSpec(bool useMC) : mUseMC(useMC) {} + PrimaryVertexingSpec(bool validateWithFT0, bool useMC) : mUseMC(useMC), mValidateWithFT0(validateWithFT0) {} ~PrimaryVertexingSpec() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -36,12 +36,13 @@ class PrimaryVertexingSpec : public Task private: o2::vertexing::PVertexer mVertexer; - bool mUseMC{false}; ///< MC flag + bool mUseMC{false}; ///< MC flag + bool mValidateWithFT0{false}; ///< require vertex validation with FT0 TStopwatch mTimer; }; /// create a processor spec -DataProcessorSpec getPrimaryVertexingSpec(bool useMC); +DataProcessorSpec getPrimaryVertexingSpec(bool validateWithFT0, bool useMC); } // namespace vertexing } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx index 8f3fcc653851e..51478d775cd1c 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx @@ -15,8 +15,8 @@ #include "GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" #include "CommonDataFormat/TimeStamp.h" +#include "DetectorsVertexing/PVertexerHelpers.h" #include "CommonDataFormat/RangeReference.h" -#include "ReconstructionDataFormats/Vertex.h" #include "SimulationDataFormat/MCEventLabel.h" using namespace o2::framework; @@ -29,23 +29,20 @@ namespace vertexing template <typename T> using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; -using TimeEst = o2::dataformats::TimeStampWithError<float, float>; -using Vertex = o2::dataformats::Vertex<TimeEst>; -using V2TRef = o2::dataformats::RangeReference<int, int>; using Label = o2::MCEventLabel; using namespace o2::header; DataProcessorSpec getPrimaryVertexWriterSpec(bool useMC) { - auto logger = [](std::vector<Vertex> const& v) { + auto logger = [](std::vector<PVertex> const& v) { LOG(INFO) << "PrimaryVertexWriter pulled " << v.size() << " vertices"; }; return MakeRootTreeWriterSpec("primary-vertex-writer", "o2_primary_vertex.root", MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree with Primary Vertices"}, - BranchDefinition<std::vector<Vertex>>{InputSpec{"vertices", "GLO", "PVERTEX", 0}, "PrimaryVertex", logger}, + BranchDefinition<std::vector<PVertex>>{InputSpec{"vertices", "GLO", "PVERTEX", 0}, "PrimaryVertex", logger}, BranchDefinition<std::vector<V2TRef>>{InputSpec{"v2tref", "GLO", "PVERTEX_TRIDREFS", 0}, "PV2TrackRefs"}, BranchDefinition<std::vector<int>>{InputSpec{"vttrackID", "GLO", "PVERTEX_TRID", 0}, "PVTrackIndices"}, BranchDefinition<std::vector<Label>>{InputSpec{"labels", "GLO", "PVERTEX_MCTR", 0}, "PVMCTruth", (useMC ? 1 : 0), ""})(); diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx index a3b0dc0b324ca..a7a7901dc6d74 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx @@ -29,26 +29,34 @@ void PrimaryVertexingSpec::init(InitContext& ic) o2::base::Propagator::initFieldFromGRP("o2sim_grp.root"); mTimer.Stop(); mTimer.Reset(); + mVertexer.setValidateWithFT0(mValidateWithFT0); mVertexer.init(); } void PrimaryVertexingSpec::run(ProcessingContext& pc) { - mTimer.Start(false); double timeCPU0 = mTimer.CpuTime(), timeReal0 = mTimer.RealTime(); + mTimer.Start(false); const auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("match"); gsl::span<const o2::MCCompLabel> lblITS, lblTPC; + gsl::span<const o2::ft0::RecPoints> ft0Data; + if (mValidateWithFT0) { + ft0Data = pc.inputs().get<gsl::span<o2::ft0::RecPoints>>("fitInfo"); + } if (mUseMC) { lblITS = pc.inputs().get<gsl::span<o2::MCCompLabel>>("lblITS"); lblTPC = pc.inputs().get<gsl::span<o2::MCCompLabel>>("lblTPC"); } - std::vector<Vertex> vertices; + std::vector<PVertex> vertices; std::vector<int> vertexTrackIDs; std::vector<V2TRef> v2tRefs; std::vector<o2::MCEventLabel> lblVtx; - mVertexer.process(tracksITSTPC, vertices, vertexTrackIDs, v2tRefs, lblITS, lblTPC, lblVtx); + // RS FIXME this will not have effect until the 1st orbit is propagated, until that will work only for TF starting at orbit 0 + const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("match").header); + mVertexer.setStartIR({0, dh->firstTForbit}); + mVertexer.process(tracksITSTPC, ft0Data, vertices, vertexTrackIDs, v2tRefs, lblITS, lblTPC, lblVtx); pc.outputs().snapshot(Output{"GLO", "PVERTEX", 0, Lifetime::Timeframe}, vertices); pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe}, v2tRefs); pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe}, vertexTrackIDs); @@ -68,12 +76,15 @@ void PrimaryVertexingSpec::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getPrimaryVertexingSpec(bool useMC) +DataProcessorSpec getPrimaryVertexingSpec(bool validateWithFT0, bool useMC) { std::vector<InputSpec> inputs; std::vector<OutputSpec> outputs; inputs.emplace_back("match", "GLO", "TPCITS", 0, Lifetime::Timeframe); + if (validateWithFT0) { + inputs.emplace_back("fitInfo", "FT0", "RECPOINTS", 0, Lifetime::Timeframe); + } outputs.emplace_back("GLO", "PVERTEX", 0, Lifetime::Timeframe); outputs.emplace_back("GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe); @@ -89,7 +100,7 @@ DataProcessorSpec getPrimaryVertexingSpec(bool useMC) "primary-vertexing", inputs, outputs, - AlgorithmSpec{adaptFromTask<PrimaryVertexingSpec>(useMC)}, + AlgorithmSpec{adaptFromTask<PrimaryVertexingSpec>(validateWithFT0, useMC)}, Options{}}; } diff --git a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx index 89afb1c0b9cb3..bbc6ac2a20071 100644 --- a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx @@ -11,6 +11,7 @@ #include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" #include "GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h" #include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" +#include "FT0Workflow/RecPointReaderSpec.h" #include "CommonUtils/ConfigurableParam.h" #include "Framework/CompletionPolicy.h" @@ -28,6 +29,7 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation"}}, {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, + {"validate-with-ft0", o2::framework::VariantType::Bool, false, {"use FT0 time for vertex validation"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; std::swap(workflowOptions, options); @@ -47,12 +49,16 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto useMC = !configcontext.options().get<bool>("disable-mc"); auto disableRootInp = configcontext.options().get<bool>("disable-root-input"); auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); + auto validateWithFT0 = configcontext.options().get<bool>("validate-with-ft0"); WorkflowSpec specs; if (!disableRootInp) { specs.emplace_back(o2::globaltracking::getTrackTPCITSReaderSpec(useMC)); + if (validateWithFT0) { + specs.emplace_back(o2::ft0::getRecPointReaderSpec(false)); + } } - specs.emplace_back(o2::vertexing::getPrimaryVertexingSpec(useMC)); + specs.emplace_back(o2::vertexing::getPrimaryVertexingSpec(validateWithFT0, useMC)); if (!disableRootOut) { specs.emplace_back(o2::vertexing::getPrimaryVertexWriterSpec(useMC)); } diff --git a/Detectors/Vertexing/CMakeLists.txt b/Detectors/Vertexing/CMakeLists.txt index a79cab48e5c46..ec04a9db02ccf 100644 --- a/Detectors/Vertexing/CMakeLists.txt +++ b/Detectors/Vertexing/CMakeLists.txt @@ -17,6 +17,7 @@ o2_add_library(DetectorsVertexing O2::CommonUtils O2::ReconstructionDataFormats O2::SimulationDataFormat + O2::DataFormatsFT0 ms_gsl::ms_gsl) o2_target_root_dictionary(DetectorsVertexing diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index 51d0643da3784..facdb13ef69fc 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -16,6 +16,7 @@ #define O2_PVERTEXER_H #include <array> +#include "CommonConstants/LHCConstants.h" #include "CommonDataFormat/TimeStamp.h" #include "CommonDataFormat/RangeReference.h" #include "SimulationDataFormat/MCEventLabel.h" @@ -23,7 +24,8 @@ #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "ReconstructionDataFormats/PrimaryVertex.h" +#include "DataFormatsFT0/RecPoints.h" #include "DetectorsVertexing/PVertexerHelpers.h" #include "DetectorsVertexing/PVertexerParams.h" #include "gsl/span" @@ -35,12 +37,6 @@ namespace vertexing namespace o2d = o2::dataformats; -class VertexSeed; -class TrackVF; -class VertexingInput; -class SeedHisto; -class TimeCluster; - class PVertexer { @@ -51,18 +47,18 @@ class PVertexer IterateFurther, OK }; - using TimeEst = o2::dataformats::TimeStampWithError<float, float>; - using Vertex = o2::dataformats::Vertex<TimeEst>; - using V2TRef = o2::dataformats::RangeReference<int, int>; - void init(); - int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, + int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, + std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx); - int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); + int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, + std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); static void createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, - const std::vector<Vertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, + const std::vector<PVertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, std::vector<o2::MCEventLabel>& lblVtx); - bool findVertex(const VertexingInput& input, Vertex& vtx); + bool findVertex(const VertexingInput& input, PVertex& vtx); + + void setStartIR(const o2::InteractionRecord& ir) { mStartIR = ir; } ///< set InteractionRecods for the beginning of the TF void setTukey(float t) { @@ -70,9 +66,11 @@ class PVertexer } float getTukey() const; - void finalizeVertex(const VertexingInput& input, const Vertex& vtx, std::vector<Vertex>& vertices, std::vector<V2TRef>& v2tRefs, std::vector<int>& vertexTrackIDs, SeedHisto& histo); + void finalizeVertex(const VertexingInput& input, const PVertex& vtx, std::vector<PVertex>& vertices, std::vector<V2TRef>& v2tRefs, std::vector<int>& vertexTrackIDs, SeedHisto& histo); void setBz(float bz) { mBz = bz; } + void setValidateWithFT0(bool v) { mValidateWithFT0 = v; } + bool getValidateWithFT0() const { return mValidateWithFT0; } auto& getTracksPool() const { return mTracksPool; } auto& getTimeClusters() const { return mTimesClusters; } @@ -96,7 +94,7 @@ class PVertexer FitStatus fitIteration(const VertexingInput& input, VertexSeed& vtxSeed); void accountTrack(TrackVF& trc, VertexSeed& vtxSeed) const; bool solveVertex(VertexSeed& vtxSeed) const; - FitStatus evalIterations(VertexSeed& vtxSeed, Vertex& vtx) const; + FitStatus evalIterations(VertexSeed& vtxSeed, PVertex& vtx) const; TimeEst timeEstimate(const VertexingInput& input) const; float findZSeedHistoPeak() const; void initMeanVertexConstraint(); @@ -105,7 +103,9 @@ class PVertexer void createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC); void clusterizeTimeBruteForce(float margin = 0.1, float cut = 25); void clusterizeTime(float binSize = 0.1, float maxTDist = 0.6); - int findVertices(const VertexingInput& input, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); + int findVertices(const VertexingInput& input, std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); + float getTimeMSFromTFStart(const o2::InteractionRecord& bc) const { return bc.differenceInBC(mStartIR) * 1e-3 * o2::constants::lhc::LHCBunchSpacingNS; } + int compatibleTimes(const TimeEst& t, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const; o2d::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; std::array<float, 3> mXYConstraintInvErr = {1.0f, 0.f, 1.0f}; ///< nominal vertex constraint inverted errors^2 @@ -116,6 +116,9 @@ class PVertexer std::vector<int> mSortedTrackID; ///< indices of tracks sorted in time std::vector<TimeCluster> mTimesClusters; ///< set of time clusters float mBz = 0.; ///< mag.field at beam line + bool mValidateWithFT0 = false; ///< require vertex validation with FT0 (if available) + + o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF ///========== Parameters to be set externally, e.g. from CCDB ==================== const PVertexerParams* mParams = nullptr; diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h index 8db973eeb9c81..98275a1124595 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h @@ -16,7 +16,7 @@ #define O2_PVERTEXER_HELPERS_H #include "gsl/span" -#include "ReconstructionDataFormats/Vertex.h" +#include "ReconstructionDataFormats/PrimaryVertex.h" #include "ReconstructionDataFormats/Track.h" #include "CommonDataFormat/TimeStamp.h" #include "CommonDataFormat/RangeReference.h" @@ -26,12 +26,12 @@ namespace o2 namespace vertexing { +using PVertex = o2::dataformats::PrimaryVertex; using TimeEst = o2::dataformats::TimeStampWithError<float, float>; -using Vertex = o2::dataformats::Vertex<TimeEst>; using V2TRef = o2::dataformats::RangeReference<int, int>; ///< weights and scaling params for current vertex -struct VertexSeed : public Vertex { +struct VertexSeed : public PVertex { double wghSum = 0.; // sum of tracks weights double wghChi2 = 0.; // sum of tracks weighted chi2's double tMeanAcc = 0.; // sum of track times * inv.err^2 @@ -66,8 +66,8 @@ struct VertexSeed : public Vertex { } VertexSeed() = default; - VertexSeed(const Vertex& vtx, bool _constraint, bool _errors) - : Vertex(vtx), useConstraint(_constraint), fillErrors(_errors) {} + VertexSeed(const PVertex& vtx, bool _constraint, bool _errors) + : PVertex(vtx), useConstraint(_constraint), fillErrors(_errors) {} void print() const; }; @@ -114,7 +114,7 @@ struct TrackVF { return z + tgL * (vx * cosAlp + vy * sinAlp - x); } - float getResiduals(const Vertex& vtx, float& dy, float& dz) const + float getResiduals(const PVertex& vtx, float& dy, float& dz) const { // get residuals (Y and Z DCA in track frame) and calculate chi2 float dx = vtx.getX() * cosAlp + vtx.getY() * sinAlp - x; // VX rotated to track frame - trackX diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h index f86320c452f23..1f8b8ffea58f1 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -35,6 +35,14 @@ struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParam float maxScale2 = 1.e6; ///< max slaling factor^2 float upscaleFactor = 9.; ///< factor for upscaling if not candidate is found float slowConvergenceFactor = 0.5; ///< consider convergence as slow if ratio new/old scale2 exceeds it + // + // validation with FT0 + bool requireFT0ValidTimeMean = false; //true;///< require both FT0A/C + int minNContributorsForFT0cut = 4; ///< do not apply FT0 cut to vertice below FT0 efficiency threshold + float maxTError = 0.2; ///< use min of vertex time error or this for nsigma evaluation + float minTError = 0.003; ///< don't use error smaller than that (~BC/2/minNContributorsForFT0cut) + float nSigmaFT0cut = 4.; ///< eliminate vertex if there is no FT0 signal within this cut + // // stopping condition params float maxChi2Mean = 10.; ///< max mean chi2 of vertex to accept int minTracksPerVtx = 2; ///< min N tracks per vertex diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index 815f70c443476..21ea67536ab7b 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -26,16 +26,18 @@ constexpr double PVertexer::kAlmost0D; constexpr float PVertexer::kHugeF; //___________________________________________________________________ -int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) +int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, + std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) { createTracksPool(tracksITSTPC); //clusterizeTimeBruteForce(); clusterizeTime(); - std::vector<Vertex> verticesLoc; + std::vector<PVertex> verticesLoc; std::vector<int> vertexTrackIDsLoc; std::vector<V2TRef> v2tRefsLoc; + std::vector<float> validationTimes; for (auto tc : mTimesClusters) { VertexingInput inp; @@ -59,23 +61,38 @@ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vect v2tRefs.reserve(v2tRefsLoc.size()); vertexTrackIDs.resize(vertexTrackIDsLoc.size()); - int trCopied = 0, count = 0; + int trCopied = 0, count = 0, vtimeID = 0; for (auto i : vtTimeSortID) { - vertices.push_back(verticesLoc[i]); + auto& vtx = verticesLoc[i]; + // do we need to validate by FT0 ? + if (mValidateWithFT0) { + auto bestMatch = compatibleTimes(vtx.getTimeStamp(), ft0Data, vtimeID); + if (bestMatch >= 0) { // RS FIXME eventually, we should assign the IR to vertex? + vtx.setFlags(PVertex::TimeValidated); + vtx.setIR(ft0Data[bestMatch].getInteractionRecord()); + LOG(DEBUG) << "Validated with t0" << bestMatch; + } else if (vtx.getNContributors() >= mParams->minNContributorsForFT0cut) { + LOG(DEBUG) << "Discarding " << vtx; + continue; // reject + } + } + vertices.push_back(vtx); memcpy(&vertexTrackIDs[trCopied], &vertexTrackIDsLoc[v2tRefsLoc[i].getFirstEntry()], v2tRefsLoc[i].getEntries() * sizeof(int)); v2tRefs.emplace_back(trCopied, v2tRefsLoc[i].getEntries()); trCopied += v2tRefsLoc[i].getEntries(); LOG(DEBUG) << "#" << count++ << " " << vertices.back() << " | " << v2tRefs.back().getEntries() << " indices from " << v2tRefs.back().getFirstEntry(); // RS REM } + vertexTrackIDs.resize(trCopied); return vertices.size(); } //___________________________________________________________________ -int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, +int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, + std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx) { - auto nv = process(tracksITSTPC, vertices, vertexTrackIDs, v2tRefs); + auto nv = process(tracksITSTPC, ft0Data, vertices, vertexTrackIDs, v2tRefs); if (lblITS.size() && lblTPC.size()) { createMCLabels(lblITS, lblTPC, vertices, vertexTrackIDs, v2tRefs, lblVtx); } @@ -83,7 +100,7 @@ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, std::vect } //______________________________________________ -int PVertexer::findVertices(const VertexingInput& input, std::vector<Vertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) +int PVertexer::findVertices(const VertexingInput& input, std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) { // find vertices using tracks with indices (sorted in time) from idRange from "tracks" pool. The pool may containt arbitrary number of tracks, // only those which are in the idRange and have canUse()==true, will be used. @@ -112,7 +129,7 @@ int PVertexer::findVertices(const VertexingInput& input, std::vector<Vertex>& ve } float zv = seedHisto.getBinCenter(peakBin); LOG(DEBUG) << "Seeding with Z=" << zv << " bin " << peakBin; - Vertex vtx; + PVertex vtx; vtx.setXYZ(mMeanVertex.getX(), mMeanVertex.getY(), zv); vtx.setTimeStamp(input.timeEst); if (findVertex(input, vtx)) { @@ -133,7 +150,7 @@ int PVertexer::findVertices(const VertexingInput& input, std::vector<Vertex>& ve } //______________________________________________ -bool PVertexer::findVertex(const VertexingInput& input, Vertex& vtx) +bool PVertexer::findVertex(const VertexingInput& input, PVertex& vtx) { // fit vertex taking provided vertex as a seed // tracks pool may contain arbitrary number of tracks, only those which are in @@ -303,7 +320,7 @@ bool PVertexer::solveVertex(VertexSeed& vtxSeed) const } //___________________________________________________________________ -PVertexer::FitStatus PVertexer::evalIterations(VertexSeed& vtxSeed, Vertex& vtx) const +PVertexer::FitStatus PVertexer::evalIterations(VertexSeed& vtxSeed, PVertex& vtx) const { // decide if new iteration should be done, prepare next one if needed // if scaleSigma2 reached its lower limit stop @@ -324,7 +341,7 @@ PVertexer::FitStatus PVertexer::evalIterations(VertexSeed& vtxSeed, Vertex& vtx) LOG(DEBUG) << "dx: " << dx << " dy: " << dy << " dz: " << dz << " -> " << dst; } - vtx = vtxSeed; + vtx = reinterpret_cast<const PVertex&>(vtxSeed); if (result == PVertexer::FitStatus::OK) { auto chi2Mean = vtxSeed.getChi2() / vtxSeed.getNContributors(); @@ -409,8 +426,8 @@ void PVertexer::init() } //___________________________________________________________________ -void PVertexer::finalizeVertex(const VertexingInput& input, const Vertex& vtx, - std::vector<Vertex>& vertices, std::vector<V2TRef>& v2tRefs, std::vector<int>& vertexTrackIDs, +void PVertexer::finalizeVertex(const VertexingInput& input, const PVertex& vtx, + std::vector<PVertex>& vertices, std::vector<V2TRef>& v2tRefs, std::vector<int>& vertexTrackIDs, SeedHisto& histo) { int lastID = vertices.size(); @@ -586,7 +603,7 @@ void PVertexer::clusterizeTime(float binSize, float maxTDist) //___________________________________________________________________ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, - const std::vector<Vertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, + const std::vector<PVertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, std::vector<o2::MCEventLabel>& lblVtx) { lblVtx.clear(); @@ -638,3 +655,28 @@ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::spa lblVtx.push_back(winner); } } + +//___________________________________________________________________ +int PVertexer::compatibleTimes(const TimeEst& t, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const +{ + // check if the times stamp is compatible with any entry startinge from currEntry in ft0Data vector, return best matching time + int best = -1, n = ft0Data.size(); + + while (currEntry < n && getTimeMSFromTFStart(ft0Data[currEntry].getInteractionRecord()) + mParams->nSigmaFT0cut * mParams->maxTError < t.getTimeStamp()) { + currEntry++; // skip all times which have no chance to be matched + } + float cut = mParams->nSigmaFT0cut * std::min(mParams->maxTError, std::max(mParams->minTError, t.getTimeStampError())), bestDf = cut, df = 0; + int i = currEntry; + while (i < n) { + if ((df = getTimeMSFromTFStart(ft0Data[i].getInteractionRecord()) - t.getTimeStamp()) > bestDf) { + break; + } + auto dfa = std::abs(df); + if (dfa <= bestDf) { + bestDf = dfa; + best = i; + } + i++; + } + return best; +} diff --git a/Detectors/Vertexing/src/PVertexerHelpers.cxx b/Detectors/Vertexing/src/PVertexerHelpers.cxx index dc6a8d0f04616..d3cf1756172cc 100644 --- a/Detectors/Vertexing/src/PVertexerHelpers.cxx +++ b/Detectors/Vertexing/src/PVertexerHelpers.cxx @@ -23,5 +23,5 @@ void VertexSeed::print() const scaleSigma2, scaleSigma2Prev, nScaleIncrease, nScaleSlowConvergence, wghChi2, wghSum, tMeanAcc * terr2, std::sqrt(terr2)); double dZP, rmsZP, dZN, rmsZN, dTP, rmsTP, dTN, rmsTN; double dZ, rmsZ, dT, rmsT; - Vertex::print(); + PVertex::print(); } From 9a9d0bc4c92977ae6c82ed9ca7d689495cd5a23d Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 26 Aug 2020 19:27:29 +0200 Subject: [PATCH 0490/1751] Add extra header to silence JIT compiler --- macro/run_trac_its.C | 1 + 1 file changed, 1 insertion(+) diff --git a/macro/run_trac_its.C b/macro/run_trac_its.C index 0421a33e5ad15..41482067789b9 100644 --- a/macro/run_trac_its.C +++ b/macro/run_trac_its.C @@ -31,6 +31,7 @@ #include "DetectorsCommonDataFormats/NameConf.h" #endif +#include "ReconstructionDataFormats/PrimaryVertex.h" // hack to silence JIT compiler #include "ITStracking/ROframe.h" #include "ITStracking/IOUtils.h" #include "ITStracking/Vertexer.h" From af452133242a8e4c51598d6b39487ecec98f86e7 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 26 Aug 2020 20:30:38 +0200 Subject: [PATCH 0491/1751] Add T0 trigger selection parametes for vertex validation --- .../include/DetectorsVertexing/PVertexer.h | 7 +++++-- .../DetectorsVertexing/PVertexerParams.h | 2 ++ Detectors/Vertexing/src/PVertexer.cxx | 17 ++++++++++------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index facdb13ef69fc..8735919dd9d10 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -104,8 +104,11 @@ class PVertexer void clusterizeTimeBruteForce(float margin = 0.1, float cut = 25); void clusterizeTime(float binSize = 0.1, float maxTDist = 0.6); int findVertices(const VertexingInput& input, std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); - float getTimeMSFromTFStart(const o2::InteractionRecord& bc) const { return bc.differenceInBC(mStartIR) * 1e-3 * o2::constants::lhc::LHCBunchSpacingNS; } - int compatibleTimes(const TimeEst& t, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const; + float getTimeMSFromTFStart(const o2::InteractionRecord& bc) const + { + return bc.differenceInBC(mStartIR) * 1e-3 * o2::constants::lhc::LHCBunchSpacingNS + mParams->timeBiasMS; + } + int getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const; o2d::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; std::array<float, 3> mXYConstraintInvErr = {1.0f, 0.f, 1.0f}; ///< nominal vertex constraint inverted errors^2 diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h index 1f8b8ffea58f1..0be19eabaa426 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -39,6 +39,8 @@ struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParam // validation with FT0 bool requireFT0ValidTimeMean = false; //true;///< require both FT0A/C int minNContributorsForFT0cut = 4; ///< do not apply FT0 cut to vertice below FT0 efficiency threshold + int minFT0AmplitudeAC = 20; ///< use only FT0 triggers with high enough aplitude + float timeBiasMS = 0.0; ///< relative bias in ms between TPC/ITS time and IR float maxTError = 0.2; ///< use min of vertex time error or this for nsigma evaluation float minTError = 0.003; ///< don't use error smaller than that (~BC/2/minNContributorsForFT0cut) float nSigmaFT0cut = 4.; ///< eliminate vertex if there is no FT0 signal within this cut diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index 21ea67536ab7b..c3e2d58ab34d9 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -66,7 +66,7 @@ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span auto& vtx = verticesLoc[i]; // do we need to validate by FT0 ? if (mValidateWithFT0) { - auto bestMatch = compatibleTimes(vtx.getTimeStamp(), ft0Data, vtimeID); + auto bestMatch = getBestFT0Trigger(vtx, ft0Data, vtimeID); if (bestMatch >= 0) { // RS FIXME eventually, we should assign the IR to vertex? vtx.setFlags(PVertex::TimeValidated); vtx.setIR(ft0Data[bestMatch].getInteractionRecord()); @@ -657,11 +657,11 @@ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::spa } //___________________________________________________________________ -int PVertexer::compatibleTimes(const TimeEst& t, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const +int PVertexer::getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const { // check if the times stamp is compatible with any entry startinge from currEntry in ft0Data vector, return best matching time int best = -1, n = ft0Data.size(); - + auto t = vtx.getTimeStamp(); while (currEntry < n && getTimeMSFromTFStart(ft0Data[currEntry].getInteractionRecord()) + mParams->nSigmaFT0cut * mParams->maxTError < t.getTimeStamp()) { currEntry++; // skip all times which have no chance to be matched } @@ -671,10 +671,13 @@ int PVertexer::compatibleTimes(const TimeEst& t, gsl::span<const o2::ft0::RecPoi if ((df = getTimeMSFromTFStart(ft0Data[i].getInteractionRecord()) - t.getTimeStamp()) > bestDf) { break; } - auto dfa = std::abs(df); - if (dfa <= bestDf) { - bestDf = dfa; - best = i; + auto ft0Trigger = ft0Data[i].getTrigger(); + if (ft0Trigger.amplA + ft0Trigger.amplC > mParams->minFT0AmplitudeAC) { + auto dfa = std::abs(df); + if (dfa <= bestDf) { + bestDf = dfa; + best = i; + } } i++; } From 24ace48800d1ae0c24576b199dd864cf549c259e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 28 Aug 2020 04:20:27 +0200 Subject: [PATCH 0492/1751] In rANS 0 lgt messages/dictionaries are legit, do not produce warning --- Utilities/rANS/include/rANS/FrequencyTable.h | 4 ++-- Utilities/rANS/include/rANS/internal/SymbolStatistics.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Utilities/rANS/include/rANS/FrequencyTable.h b/Utilities/rANS/include/rANS/FrequencyTable.h index 5304a9dd8d00c..a3c74072b9550 100644 --- a/Utilities/rANS/include/rANS/FrequencyTable.h +++ b/Utilities/rANS/include/rANS/FrequencyTable.h @@ -108,7 +108,7 @@ void FrequencyTable::addSamples(Source_IT begin, Source_IT end, value_t min, val t.start(); if (begin == end) { - LOG(warning) << "Passed empty message to " << __func__; + LOG(debug) << "Passed empty message to " << __func__; // RS this is ok for empty columns return; } @@ -145,7 +145,7 @@ void FrequencyTable::addFrequencies(Freq_IT begin, Freq_IT end, value_t min, val t.start(); if (begin == end) { - LOG(warning) << "Passed empty FrequencyTable to " << __func__; + LOG(debug) << "Passed empty FrequencyTable to " << __func__; // RS this is ok for empty columns return; } diff --git a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h index 686c470a11f6c..18af55e313c6c 100644 --- a/Utilities/rANS/include/rANS/internal/SymbolStatistics.h +++ b/Utilities/rANS/include/rANS/internal/SymbolStatistics.h @@ -123,7 +123,7 @@ SymbolStatistics::SymbolStatistics(const Source_IT begin, const Source_IT end, i t.start(); if (begin == end) { - LOG(warning) << "Passed empty message to " << __func__; + LOG(debug) << "Passed empty message to " << __func__; // RS this is ok for empty columns return; } From 45108d5cd9dc44151317b533ed4334b49aed9d39 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 28 Aug 2020 04:21:57 +0200 Subject: [PATCH 0493/1751] Fix: set the CTF tree entries + misc features --- .../Common/include/DetectorsCommonDataFormats/EncodedBlocks.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 4f5dd67a97675..aec0469bf148e 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -255,6 +255,7 @@ struct Block { setNDict(_ndict); setNData(_ndata); setNLiterals(_nliterals); + getCreatePayload(); // do this even for empty block!!! if (getNStored()) { payload = reinterpret_cast<W*>(registry->getFreeBlockStart()); if (getNDict()) { @@ -291,6 +292,7 @@ class EncodedBlocks void setHeader(const H& h) { mHeader = h; } const H& getHeader() const { return mHeader; } H& getHeader() { return mHeader; } + std::shared_ptr<H> cloneHeader() const { return std::shared_ptr<H>(new H(mHeader)); } // for dictionary creation const auto& getMetadata() const { return mMetadata; } @@ -472,6 +474,7 @@ void EncodedBlocks<H, N, W>::appendToTree(TTree& tree, const std::string& name) int compression = mMetadata[i].opt == Metadata::OptStore::ROOTCompression ? 1 : 0; fillTreeBranch(tree, o2::utils::concat_string(name, "_block.", std::to_string(i), "."), const_cast<Block<W>&>(mBlocks[i]), compression); } + tree.SetEntries(tree.GetEntries() + 1); } ///_____________________________________________________________________________ From 3529ccbb26a1acafbdb2c27bec0ca447307712d8 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 28 Aug 2020 04:23:07 +0200 Subject: [PATCH 0494/1751] store detectors CTFHeader (from 1st TF) in dictionary --- Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h index 7569c667d4576..c0b95b787f9ad 100644 --- a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h +++ b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h @@ -74,6 +74,7 @@ class CTFWriterSpec : public o2::framework::Task // The metadata of the block (min,max) will be used for the consistency check at the decoding std::array<std::vector<FTrans>, DetID::nDetectors> mFreqsAccumulation; std::array<std::vector<o2::ctf::Metadata>, DetID::nDetectors> mFreqsMetaData; + std::array<std::shared_ptr<void>, DetID::nDetectors> mHeaders; TStopwatch mTimer; }; @@ -97,6 +98,9 @@ void CTFWriterSpec::processDet(o2::framework::ProcessingContext& pc, DetID det, mFreqsAccumulation[det].resize(C::getNBlocks()); mFreqsMetaData[det].resize(C::getNBlocks()); } + if (!mHeaders[det]) { // store 1st header + mHeaders[det] = ctfImage.cloneHeader(); + } for (int ib = 0; ib < C::getNBlocks(); ib++) { const auto& bl = ctfImage.getBlock(ib); if (bl.getNDict()) { @@ -120,6 +124,8 @@ void CTFWriterSpec::storeDictionary(DetID det, CTFHeader& header) prepareDictionaryTreeAndFile(det); // create vector whose data contains dictionary in CTF format (EncodedBlock) auto dictBlocks = C::createDictionaryBlocks(mFreqsAccumulation[det], mFreqsMetaData[det]); + auto& h = C::get(dictBlocks.data())->getHeader(); + h = *reinterpret_cast<typename std::remove_reference<decltype(h)>::type*>(mHeaders[det].get()); C::get(dictBlocks.data())->print(o2::utils::concat_string("Storing dictionary for ", det.getName(), ": ")); C::get(dictBlocks.data())->appendToTree(*mDictTreeOut.get(), det.getName()); // cast to EncodedBlock // mFreqsAccumulation[det].clear(); From 1761e990f83523b98948d2b8acb6001171467bdb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 28 Aug 2020 04:23:58 +0200 Subject: [PATCH 0495/1751] Option (Def=on) to merge in the TPC CTF correlated columns --- .../TPC/include/DataFormatsTPC/CTF.h | 28 ++- .../Detectors/TPC/src/DataFormatsTPCLinkDef.h | 3 +- .../include/TPCReconstruction/CTFCoder.h | 220 +++++++++++++++--- Detectors/TPC/reconstruction/src/CTFCoder.cxx | 54 ++++- .../TPC/workflow/src/EntropyEncoderSpec.cxx | 4 +- 5 files changed, 259 insertions(+), 50 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CTF.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CTF.h index fded32542461e..c501776e34e06 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CTF.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CTF.h @@ -23,35 +23,49 @@ namespace o2 namespace tpc { +struct CTFHeader : public CompressedClustersCounters { + enum : uint32_t { CombinedColumns = 0x1 }; + uint32_t flags = 0; + + ClassDefNV(CTFHeader, 1); +}; + /// wrapper for the Entropy-encoded clusters of the TF -struct CTF : public o2::ctf::EncodedBlocks<CompressedClustersCounters, 23, uint32_t> { +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 23, uint32_t> { static constexpr size_t N = getNBlocks(); + static constexpr int NBitsQTot = 16; + static constexpr int NBitsQMax = 10; + static constexpr int NBitsSigmaPad = 8; + static constexpr int NBitsSigmaTime = 8; + static constexpr int NBitsRowDiff = 8; + static constexpr int NBitsSliceLegDiff = 7; + enum Slots { BLCqTotA, - BLCqMaxA, + BLCqMaxA, // can be combined with BLCqTotA BLCflagsA, BLCrowDiffA, - BLCsliceLegDiffA, + BLCsliceLegDiffA, // can be combined with BLCrowDiffA BLCpadResA, BLCtimeResA, BLCsigmaPadA, - BLCsigmaTimeA, + BLCsigmaTimeA, // can be combined with BLCsigmaPadA BLCqPtA, BLCrowA, BLCsliceA, BLCtimeA, BLCpadA, BLCqTotU, - BLCqMaxU, + BLCqMaxU, // can be combined with BLCqTotU BLCflagsU, BLCpadDiffU, BLCtimeDiffU, BLCsigmaPadU, - BLCsigmaTimeU, + BLCsigmaTimeU, // can be combined with BLCsigmaPadU BLCnTrackClusters, BLCnSliceRowClusters }; - ClassDefNV(CTF, 1); + ClassDefNV(CTF, 2); }; } // namespace tpc diff --git a/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h b/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h index fac8b3e0c86b3..a8eb060a3d400 100644 --- a/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h +++ b/DataFormats/Detectors/TPC/src/DataFormatsTPCLinkDef.h @@ -46,7 +46,8 @@ #pragma link C++ class o2::tpc::CompressedClusters + ; #pragma link C++ class o2::tpc::CompressedClustersROOT - ; #pragma link C++ class o2::tpc::CTF + ; -#pragma link C++ class o2::ctf::EncodedBlocks < o2::tpc::CompressedClustersCounters, 23, uint32_t> + ; +#pragma link C++ class o2::tpc::CTFHeader + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::tpc::CTFHeader, 23, uint32_t> + ; #pragma link C++ enum o2::tpc::StatisticsType; #endif diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h index c6bbe1c134fe6..6e2bca379cfcd 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h @@ -18,6 +18,10 @@ #include <algorithm> #include <iterator> #include <string> +#include <cassert> +#include <type_traits> +#include <typeinfo> +#include <vector> #include "DataFormatsTPC/CTF.h" #include "DataFormatsTPC/CompressedClusters.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -69,9 +73,63 @@ class CTFCoder : public o2::ctf::CTFCoderBase ptrR += res ? sz + (ALG - res) : sz; } + bool getCombineColumns() const { return mCombineColumns; } + void setCombineColumns(bool v) { mCombineColumns = v; } + + private: + void checkDataDictionaryConsistency(const CTFHeader& h); + + template <int NU, int NL> + static constexpr auto MVAR() + { + typename std::conditional<(NU + NL > 16), uint32_t, typename std::conditional<(NU + NL > 8), uint16_t, uint8_t>::type>::type tp = 0; + return tp; + } + template <int NU, int NL> + static constexpr auto MPTR() + { + typename std::conditional<(NU + NL > 16), uint32_t, typename std::conditional<(NU + NL > 8), uint16_t, uint8_t>::type>::type* tp = nullptr; + return tp; + } +#define MTYPE(A, B) decltype(CTFCoder::MVAR<A, B>()) + + template <int NU, int NL, typename CU, typename CL> + static void splitColumns(const std::vector<MTYPE(NU, NL)>& vm, CU*& vu, CL*& vl); + + template <int NU, int NL, typename CU, typename CL> + static auto mergeColumns(const CU* vu, const CL* vl, size_t nelem); + + bool mCombineColumns = false; // combine correlated columns + ClassDefNV(CTFCoder, 1); }; +/// split words of input vector to columns assigned to provided pointers (memory must be allocated in advance) +template <int NU, int NL, typename CU, typename CL> +void CTFCoder::splitColumns(const std::vector<MTYPE(NU, NL)>& vm, CU*& vu, CL*& vl) +{ + static_assert(NU <= sizeof(CU) * 8 && NL <= sizeof(CL) * 8, "output columns bit count is wrong"); + size_t n = vm.size(); + for (size_t i = 0; i < n; i++) { + vu[i] = static_cast<CU>(vm[i] >> NL); + vl[i] = static_cast<CL>(vm[i] & ((0x1 << NL) - 1)); + } +} + +/// merge elements of 2 columns pointed by vu and vl to a single vector with wider field +template <int NU, int NL, typename CU, typename CL> +auto CTFCoder::mergeColumns(const CU* vu, const CL* vl, size_t nelem) +{ + // merge 2 columns to 1 + static_assert(NU <= sizeof(NU) * 8 && NL <= sizeof(NL) * 8, "input columns bit count is wrong"); + std::vector<MTYPE(NU, NL)> outv; + outv.reserve(nelem); + for (size_t i = 0; i < nelem; i++) { + outv.push_back((static_cast<MTYPE(NU, NL)>(vu[i]) << NL) | static_cast<MTYPE(NU, NL)>(vl[i])); + } + return std::move(outv); +} + /// entropy-encode clusters to buffer with CTF template <typename VEC> void CTFCoder::encode(VEC& buff, const CompressedClusters& ccl) @@ -109,33 +167,77 @@ void CTFCoder::encode(VEC& buff, const CompressedClusters& ccl) buff.resize(szIni); auto ec = CTF::create(buff); - ec->setHeader(reinterpret_cast<const CompressedClustersCounters&>(ccl)); + uint32_t flags = 0; + if (mCombineColumns) { + flags |= CTFHeader::CombinedColumns; + } + ec->setHeader(CTFHeader{reinterpret_cast<const CompressedClustersCounters&>(ccl), flags}); ec->getANSHeader().majorVersion = 0; ec->getANSHeader().minorVersion = 1; // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec #define ENCODETPC(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); // clang-format off - ENCODETPC(ccl.qTotA, ccl.qTotA + ccl.nAttachedClusters, CTF::BLCqTotA, 0); - ENCODETPC(ccl.qMaxA, ccl.qMaxA + ccl.nAttachedClusters, CTF::BLCqMaxA, 0); + + if (mCombineColumns) { + auto mrg = mergeColumns<CTF::NBitsQTot, CTF::NBitsQMax>(ccl.qTotA, ccl.qMaxA, ccl.nAttachedClusters); + ENCODETPC(&mrg[0], (&mrg[0]) + ccl.nAttachedClusters, CTF::BLCqTotA, 0); + } + else { + ENCODETPC(ccl.qTotA, ccl.qTotA + ccl.nAttachedClusters, CTF::BLCqTotA, 0); + } + ENCODETPC(ccl.qMaxA, ccl.qMaxA + (mCombineColumns ? 0 : ccl.nAttachedClusters), CTF::BLCqMaxA, 0); + ENCODETPC(ccl.flagsA, ccl.flagsA + ccl.nAttachedClusters, CTF::BLCflagsA, 0); - ENCODETPC(ccl.rowDiffA, ccl.rowDiffA + ccl.nAttachedClustersReduced, CTF::BLCrowDiffA, 0); - ENCODETPC(ccl.sliceLegDiffA, ccl.sliceLegDiffA + ccl.nAttachedClustersReduced, CTF::BLCsliceLegDiffA, 0); + + if (mCombineColumns) { + auto mrg = mergeColumns<CTF::NBitsRowDiff, CTF::NBitsSliceLegDiff>(ccl.rowDiffA, ccl.sliceLegDiffA, ccl.nAttachedClustersReduced); + ENCODETPC(&mrg[0], (&mrg[0]) + ccl.nAttachedClustersReduced, CTF::BLCrowDiffA, 0); + } + else { + ENCODETPC(ccl.rowDiffA, ccl.rowDiffA + ccl.nAttachedClustersReduced, CTF::BLCrowDiffA, 0); + } + ENCODETPC(ccl.sliceLegDiffA, ccl.sliceLegDiffA + (mCombineColumns ? 0 : ccl.nAttachedClustersReduced), CTF::BLCsliceLegDiffA, 0); + ENCODETPC(ccl.padResA, ccl.padResA + ccl.nAttachedClustersReduced, CTF::BLCpadResA, 0); ENCODETPC(ccl.timeResA, ccl.timeResA + ccl.nAttachedClustersReduced, CTF::BLCtimeResA, 0); - ENCODETPC(ccl.sigmaPadA, ccl.sigmaPadA + ccl.nAttachedClusters, CTF::BLCsigmaPadA, 0); - ENCODETPC(ccl.sigmaTimeA, ccl.sigmaTimeA + ccl.nAttachedClusters, CTF::BLCsigmaTimeA, 0); + + if (mCombineColumns) { + auto mrg = mergeColumns<CTF::NBitsSigmaPad, CTF::NBitsSigmaTime>(ccl.sigmaPadA, ccl.sigmaTimeA, ccl.nAttachedClusters); + ENCODETPC(&mrg[0], &mrg[0] + ccl.nAttachedClusters, CTF::BLCsigmaPadA, 0); + } + else { + ENCODETPC(ccl.sigmaPadA, ccl.sigmaPadA + ccl.nAttachedClusters, CTF::BLCsigmaPadA, 0); + } + ENCODETPC(ccl.sigmaTimeA, ccl.sigmaTimeA + (mCombineColumns ? 0 : ccl.nAttachedClusters), CTF::BLCsigmaTimeA, 0); + ENCODETPC(ccl.qPtA, ccl.qPtA + ccl.nTracks, CTF::BLCqPtA, 0); ENCODETPC(ccl.rowA, ccl.rowA + ccl.nTracks, CTF::BLCrowA, 0); ENCODETPC(ccl.sliceA, ccl.sliceA + ccl.nTracks, CTF::BLCsliceA, 0); ENCODETPC(ccl.timeA, ccl.timeA + ccl.nTracks, CTF::BLCtimeA, 0); ENCODETPC(ccl.padA, ccl.padA + ccl.nTracks, CTF::BLCpadA, 0); - ENCODETPC(ccl.qTotU, ccl.qTotU + ccl.nUnattachedClusters, CTF::BLCqTotU, 0); - ENCODETPC(ccl.qMaxU, ccl.qMaxU + ccl.nUnattachedClusters, CTF::BLCqMaxU, 0); + + if (mCombineColumns) { + auto mrg = mergeColumns<CTF::NBitsQTot, CTF::NBitsQMax>(ccl.qTotU,ccl.qMaxU,ccl.nUnattachedClusters); + ENCODETPC(&mrg[0], &mrg[0] + ccl.nUnattachedClusters, CTF::BLCqTotU, 0); + } + else { + ENCODETPC(ccl.qTotU, ccl.qTotU + ccl.nUnattachedClusters, CTF::BLCqTotU, 0); + } + ENCODETPC(ccl.qMaxU, ccl.qMaxU + (mCombineColumns ? 0 : ccl.nUnattachedClusters), CTF::BLCqMaxU, 0); + ENCODETPC(ccl.flagsU, ccl.flagsU + ccl.nUnattachedClusters, CTF::BLCflagsU, 0); ENCODETPC(ccl.padDiffU, ccl.padDiffU + ccl.nUnattachedClusters, CTF::BLCpadDiffU, 0); ENCODETPC(ccl.timeDiffU, ccl.timeDiffU + ccl.nUnattachedClusters, CTF::BLCtimeDiffU, 0); - ENCODETPC(ccl.sigmaPadU, ccl.sigmaPadU + ccl.nUnattachedClusters, CTF::BLCsigmaPadU, 0); - ENCODETPC(ccl.sigmaTimeU, ccl.sigmaTimeU + ccl.nUnattachedClusters, CTF::BLCsigmaTimeU, 0); + + if (mCombineColumns) { + auto mrg = mergeColumns<CTF::NBitsSigmaPad, CTF::NBitsSigmaTime>(ccl.sigmaPadU, ccl.sigmaTimeU, ccl.nUnattachedClusters); + ENCODETPC(&mrg[0], &mrg[0] + ccl.nUnattachedClusters, CTF::BLCsigmaPadU, 0); + } + else { + ENCODETPC(ccl.sigmaPadU, ccl.sigmaPadU + ccl.nUnattachedClusters, CTF::BLCsigmaPadU, 0); + } + ENCODETPC(ccl.sigmaTimeU, ccl.sigmaTimeU + (mCombineColumns ? 0 : ccl.nUnattachedClusters), CTF::BLCsigmaTimeU, 0); + ENCODETPC(ccl.nTrackClusters, ccl.nTrackClusters + ccl.nTracks, CTF::BLCnTrackClusters, 0); ENCODETPC(ccl.nSliceRowClusters, ccl.nSliceRowClusters + ccl.nSliceRows, CTF::BLCnSliceRowClusters, 0); // clang-format on @@ -148,7 +250,9 @@ void CTFCoder::decode(const CTF::base& ec, VEC& buffVec) { CompressedClusters cc; CompressedClustersCounters& ccCount = cc; - ccCount = ec.getHeader(); // ec.getHeader is a saved copy of the CompressedClustersCounters + auto& header = ec.getHeader(); + checkDataDictionaryConsistency(header); + ccCount = reinterpret_cast<const CompressedClustersCounters&>(header); CompressedClustersFlat* ccFlat = nullptr; size_t sizeCFlatBody = alignSize(ccFlat); size_t sz = sizeCFlatBody + estimateSize(cc); // total size of the buffVec accounting for the alignment @@ -160,34 +264,80 @@ void CTFCoder::decode(const CTF::base& ec, VEC& buffVec) setCompClusAddresses(cc, buff); ccFlat->set(sz, cc); // set offsets ec.print(getPrefix()); + // decode encoded data directly to destination buff #define DECODETPC(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off - DECODETPC(cc.qTotA, CTF::BLCqTotA); - DECODETPC(cc.qMaxA, CTF::BLCqMaxA); - DECODETPC(cc.flagsA, CTF::BLCflagsA); - DECODETPC(cc.rowDiffA, CTF::BLCrowDiffA); - DECODETPC(cc.sliceLegDiffA, CTF::BLCsliceLegDiffA); - DECODETPC(cc.padResA, CTF::BLCpadResA); - DECODETPC(cc.timeResA, CTF::BLCtimeResA); - DECODETPC(cc.sigmaPadA, CTF::BLCsigmaPadA); - DECODETPC(cc.sigmaTimeA, CTF::BLCsigmaTimeA); - DECODETPC(cc.qPtA, CTF::BLCqPtA); - DECODETPC(cc.rowA, CTF::BLCrowA); - DECODETPC(cc.sliceA, CTF::BLCsliceA); - DECODETPC(cc.timeA, CTF::BLCtimeA); - DECODETPC(cc.padA, CTF::BLCpadA); - DECODETPC(cc.qTotU, CTF::BLCqTotU); - DECODETPC(cc.qMaxU, CTF::BLCqMaxU); - DECODETPC(cc.flagsU, CTF::BLCflagsU); - DECODETPC(cc.padDiffU, CTF::BLCpadDiffU); - DECODETPC(cc.timeDiffU, CTF::BLCtimeDiffU); - DECODETPC(cc.sigmaPadU, CTF::BLCsigmaPadU); - DECODETPC(cc.sigmaTimeU, CTF::BLCsigmaTimeU); - DECODETPC(cc.nTrackClusters, CTF::BLCnTrackClusters); - DECODETPC(cc.nSliceRowClusters, CTF::BLCnSliceRowClusters); + if (mCombineColumns) { + std::vector<MTYPE(CTF::NBitsQTot, CTF::NBitsQMax)> mrg; + DECODETPC(mrg, CTF::BLCqTotA); + splitColumns<CTF::NBitsQTot, CTF::NBitsQMax>(mrg, cc.qTotA, cc.qMaxA); + } + else { + DECODETPC(cc.qTotA, CTF::BLCqTotA); + DECODETPC(cc.qMaxA, CTF::BLCqMaxA); + } + + DECODETPC(cc.flagsA, CTF::BLCflagsA); + + if (mCombineColumns) { + std::vector<MTYPE(CTF::NBitsRowDiff, CTF::NBitsSliceLegDiff)> mrg; + DECODETPC(mrg, CTF::BLCrowDiffA); + splitColumns<CTF::NBitsRowDiff, CTF::NBitsSliceLegDiff>(mrg, cc.rowDiffA, cc.sliceLegDiffA); + } + else { + DECODETPC(cc.rowDiffA, CTF::BLCrowDiffA); + DECODETPC(cc.sliceLegDiffA, CTF::BLCsliceLegDiffA); + } + + DECODETPC(cc.padResA, CTF::BLCpadResA); + DECODETPC(cc.timeResA, CTF::BLCtimeResA); + + if (mCombineColumns) { + std::vector<MTYPE(CTF::NBitsSigmaPad, CTF::NBitsSigmaTime)> mrg; + DECODETPC(mrg, CTF::BLCsigmaPadA); + splitColumns<CTF::NBitsSigmaPad, CTF::NBitsSigmaTime>(mrg, cc.sigmaPadA, cc.sigmaTimeA); + } + else { + DECODETPC(cc.sigmaPadA, CTF::BLCsigmaPadA); + DECODETPC(cc.sigmaTimeA, CTF::BLCsigmaTimeA); + } + + DECODETPC(cc.qPtA, CTF::BLCqPtA); + DECODETPC(cc.rowA, CTF::BLCrowA); + DECODETPC(cc.sliceA, CTF::BLCsliceA); + DECODETPC(cc.timeA, CTF::BLCtimeA); + DECODETPC(cc.padA, CTF::BLCpadA); + + if (mCombineColumns) { + std::vector<MTYPE(CTF::NBitsQTot, CTF::NBitsQMax)> mrg; + DECODETPC(mrg, CTF::BLCqTotU); + splitColumns<CTF::NBitsQTot, CTF::NBitsQMax>(mrg, cc.qTotU, cc.qMaxU); + } + else { + DECODETPC(cc.qTotU, CTF::BLCqTotU); + DECODETPC(cc.qMaxU, CTF::BLCqMaxU); + } + + DECODETPC(cc.flagsU, CTF::BLCflagsU); + DECODETPC(cc.padDiffU, CTF::BLCpadDiffU); + DECODETPC(cc.timeDiffU, CTF::BLCtimeDiffU); + + if (mCombineColumns) { + std::vector<MTYPE(CTF::NBitsSigmaPad, CTF::NBitsSigmaTime)> mrg; + DECODETPC(mrg, CTF::BLCsigmaPadU); + splitColumns<CTF::NBitsSigmaPad, CTF::NBitsSigmaTime>(mrg, cc.sigmaPadU, cc.sigmaTimeU); + } + else { + DECODETPC(cc.sigmaPadU, CTF::BLCsigmaPadU); + DECODETPC(cc.sigmaTimeU, CTF::BLCsigmaTimeU); + } + + DECODETPC(cc.nTrackClusters, CTF::BLCnTrackClusters); + DECODETPC(cc.nSliceRowClusters, CTF::BLCnSliceRowClusters); // clang-format on } +#undef MTYPE } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/reconstruction/src/CTFCoder.cxx b/Detectors/TPC/reconstruction/src/CTFCoder.cxx index 174544009faf8..07a3ce315c8a7 100644 --- a/Detectors/TPC/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TPC/reconstruction/src/CTFCoder.cxx @@ -13,6 +13,7 @@ /// \brief class for entropy encoding/decoding of TPC compressed clusters data #include "TPCReconstruction/CTFCoder.h" +#include <fmt/format.h> using namespace o2::tpc; @@ -99,6 +100,8 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: throw std::runtime_error("Failed to create CTF dictionaty"); } const auto* ctf = CTF::get(buff.data()); + mCombineColumns = ctf->getHeader().flags & CTFHeader::CombinedColumns; + LOG(INFO) << "TPC CTF Columns Combining " << (mCombineColumns ? "ON" : "OFF"); auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { o2::rans::FrequencyTable ft; @@ -114,32 +117,71 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: CompressedClusters cc; // just to get member types #define MAKECODER(part, slot) createCoder<std::remove_pointer<decltype(part)>::type>(op, getFreq(slot), getProbBits(slot), int(slot)) // clang-format off - MAKECODER(cc.qTotA, CTF::BLCqTotA); + if (mCombineColumns) { + MAKECODER( (MPTR<CTF::NBitsQTot, CTF::NBitsQMax>()), CTF::BLCqTotA); // merged qTotA and qMaxA + } + else { + MAKECODER(cc.qTotA, CTF::BLCqTotA); + } MAKECODER(cc.qMaxA, CTF::BLCqMaxA); MAKECODER(cc.flagsA, CTF::BLCflagsA); - MAKECODER(cc.rowDiffA, CTF::BLCrowDiffA); + if (mCombineColumns) { + MAKECODER( (MPTR<CTF::NBitsRowDiff, CTF::NBitsSliceLegDiff>()), CTF::BLCrowDiffA); // merged rowDiffA and sliceLegDiffA + } + else { + MAKECODER(cc.rowDiffA, CTF::BLCrowDiffA); + } MAKECODER(cc.sliceLegDiffA, CTF::BLCsliceLegDiffA); MAKECODER(cc.padResA, CTF::BLCpadResA); MAKECODER(cc.timeResA, CTF::BLCtimeResA); - MAKECODER(cc.sigmaPadA, CTF::BLCsigmaPadA); - MAKECODER(cc.sigmaTimeA, CTF::BLCsigmaTimeA); + if (mCombineColumns) { + MAKECODER( (MPTR<CTF::NBitsSigmaPad, CTF::NBitsSigmaTime>()), CTF::BLCsigmaPadA); // merged sigmaPadA and sigmaTimeA + } + else { + MAKECODER(cc.sigmaPadA, CTF::BLCsigmaPadA); + } + MAKECODER(cc.sigmaTimeA, CTF::BLCsigmaTimeA); MAKECODER(cc.qPtA, CTF::BLCqPtA); MAKECODER(cc.rowA, CTF::BLCrowA); MAKECODER(cc.sliceA, CTF::BLCsliceA); MAKECODER(cc.timeA, CTF::BLCtimeA); MAKECODER(cc.padA, CTF::BLCpadA); - MAKECODER(cc.qTotU, CTF::BLCqTotU); + if (mCombineColumns) { + MAKECODER( (MPTR<CTF::NBitsQTot, CTF::NBitsQMax>()), CTF::BLCqTotU); // merged qTotU and qMaxU + } + else { + MAKECODER(cc.qTotU, CTF::BLCqTotU); + } MAKECODER(cc.qMaxU, CTF::BLCqMaxU); MAKECODER(cc.flagsU, CTF::BLCflagsU); MAKECODER(cc.padDiffU, CTF::BLCpadDiffU); MAKECODER(cc.timeDiffU, CTF::BLCtimeDiffU); - MAKECODER(cc.sigmaPadU, CTF::BLCsigmaPadU); + if (mCombineColumns) { + MAKECODER( (MPTR<CTF::NBitsSigmaPad, CTF::NBitsSigmaTime>()), CTF::BLCsigmaPadU); // merged sigmaPadA and sigmaTimeA + } + else { + MAKECODER(cc.sigmaPadU, CTF::BLCsigmaPadU); + } MAKECODER(cc.sigmaTimeU, CTF::BLCsigmaTimeU); MAKECODER(cc.nTrackClusters, CTF::BLCnTrackClusters); MAKECODER(cc.nSliceRowClusters, CTF::BLCnSliceRowClusters); // clang-format on } +/// make sure loaded dictionaries (if any) are consistent with data +void CTFCoder::checkDataDictionaryConsistency(const CTFHeader& h) +{ + if (mCoders[0]) { // if external dictionary is provided (it will set , make sure its columns combining option is the same as + if (mCombineColumns != (h.flags & CTFHeader::CombinedColumns)) { + throw std::runtime_error(fmt::format("Mismatch in columns combining mode, Dictionary:{:s} CTFHeader:{:s}", + mCombineColumns ? "ON" : "OFF", (h.flags & CTFHeader::CombinedColumns) ? "ON" : "OFF")); + } + } else { + setCombineColumns(h.flags & CTFHeader::CombinedColumns); + LOG(INFO) << "CTF with stored dictionaries, columns combining " << (mCombineColumns ? "ON" : "OFF"); + } +} + ///________________________________ size_t CTFCoder::estimateCompressedSize(const CompressedClusters& ccl) { diff --git a/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx b/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx index b3594bb6b3ff5..e89992a9cf963 100644 --- a/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx @@ -28,6 +28,7 @@ namespace tpc void EntropyEncoderSpec::init(o2::framework::InitContext& ic) { + mCTFCoder.setCombineColumns(!ic.options().get<bool>("no-ctf-columns-combining")); std::string dictPath = ic.options().get<std::string>("tpc-ctf-dictionary"); if (!dictPath.empty() && dictPath != "none") { mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); @@ -81,7 +82,8 @@ DataProcessorSpec getEntropyEncoderSpec(bool inputFromFile) Inputs{{"input", "TPC", inputType, 0, Lifetime::Timeframe}}, Outputs{{"TPC", "CTFDATA", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>(inputFromFile)}, - Options{{"tpc-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; + Options{{"tpc-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}, + {"no-ctf-columns-combining", VariantType::Bool, false, {"Do not combine correlated columns in CTF"}}}}; } } // namespace tpc From ddbb9d0ed5ca69d6bd6efec83966e8952cf0786c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 28 Aug 2020 14:45:32 +0200 Subject: [PATCH 0496/1751] Add helper script to profile compilation (#4245) --- scripts/profile-compilation | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 scripts/profile-compilation diff --git a/scripts/profile-compilation b/scripts/profile-compilation new file mode 100755 index 0000000000000..e3624b9f084f8 --- /dev/null +++ b/scripts/profile-compilation @@ -0,0 +1,7 @@ +#!/bin/bash + +COMPILE_COMMADS=$PWD/compile_commands.json +FILENAME=$PWD/$1 +CLANG_PATH=${CLANG_PATH:-clang++} +cd `cat $COMPILE_COMMADS | jq ".[] | select(.file == \"$FILENAME\")" | jq -r '.directory'` +`cat $COMPILE_COMMADS | jq ".[] | select(.file == \"$FILENAME\")" | jq ".command |= (sub(\"^.*/c[+][+]\";\"$CLANG_PATH -ftime-trace\"))" | jq -r '.command'` From 237933cef56e02c7a6edf5acd2fefc0b3b295bef Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Wed, 26 Aug 2020 14:13:54 +0200 Subject: [PATCH 0497/1751] add tof ctf unit test --- Detectors/CTF/CMakeLists.txt | 10 ++ Detectors/CTF/test/test_ctf_io_tof.cxx | 142 +++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 Detectors/CTF/test/test_ctf_io_tof.cxx diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index 8e2f06775cf9a..89266ddd5fd5e 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -41,3 +41,13 @@ o2_add_test(fv0 SOURCES test/test_ctf_io_fv0.cxx COMPONENT_NAME ctf LABELS ctf) + +o2_add_test(tof + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::TOFBase + O2::TOFReconstruction + O2::DataFormatsTOF + SOURCES test/test_ctf_io_tof.cxx + COMPONENT_NAME ctf + LABELS ctf) + diff --git a/Detectors/CTF/test/test_ctf_io_tof.cxx b/Detectors/CTF/test/test_ctf_io_tof.cxx new file mode 100644 index 0000000000000..dce6d920c19e6 --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_tof.cxx @@ -0,0 +1,142 @@ +// 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. + +#define BOOST_TEST_MODULE Test TOFCTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DataFormatsTOF/CTF.h" +#include "TOFBase/Geo.h" +#include "TOFBase/Digit.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "TOFReconstruction/CTFCoder.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <cstring> + +using namespace o2::tof; + +BOOST_AUTO_TEST_CASE(CompressedClustersTest) +{ + + std::vector<Digit> digits; + std::vector<ReadoutWindowData> rows; + std::vector<uint32_t> pattVec; + + TStopwatch sw; + sw.Start(); + std::vector<int> row, col; + for (int irof = 0; irof < 100; irof++) { // loop over row + auto& rofr = rows.emplace_back(); + int orbit = irof / Geo::NWINDOW_IN_ORBIT; + int bc = Geo::BC_IN_ORBIT / Geo::NWINDOW_IN_ORBIT * (irof % 3); + rofr.SetOrbit(orbit); + rofr.SetBC(bc); + int ndig = gRandom->Poisson(50); + + rofr.setFirstEntry(digits.size()); + rofr.setNEntries(ndig); + // fill empty pattern (to be changed) + rofr.setFirstEntryDia(pattVec.size()); + rofr.setNEntriesDia(0); + std::vector<int> istrip; + for (int i = 0; i < ndig; i++) { + istrip.emplace_back(gRandom->Integer(Geo::NSTRIPS)); + } + std::sort(istrip.begin(), istrip.end()); + + for (int i = 0; i < ndig; i++) { + int ch = istrip[i] * Geo::NPADS + gRandom->Integer(Geo::NPADS); + uint16_t TDC = gRandom->Integer(1024); + uint16_t TOT = gRandom->Integer(2048); + uint64_t BC = Geo::BC_IN_ORBIT * orbit + bc + gRandom->Integer(Geo::BC_IN_ORBIT / Geo::NWINDOW_IN_ORBIT); + + digits.emplace_back(ch, TDC, TOT, BC); + } + + std::sort(digits.begin(), digits.end(), + [](const Digit& a, const Digit& b) { + int strip1 = a.getChannel() / Geo::NPADS, strip2 = b.getChannel() / Geo::NPADS; + if (strip1 == strip2) { + if (a.getBC() == b.getBC()) + return a.getTDC() < b.getTDC(); + return a.getBC() < b.getBC(); + } + return strip1 < strip2; + }); + + // for (int i = 0; i < ndig; i++) + // LOG(INFO) << "ROW = " << irof << " - Strip = " << digits[i].getChannel() / Geo::NPADS << " - BC = " << digits[i].getBC() << " - TDC = " << digits[i].getTDC(); + } + sw.Stop(); + LOG(INFO) << "Generated " << digits.size() << " in " << rows.size() << " ROFs in " << sw.CpuTime() << " s"; + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + { + CTFCoder coder; + coder.encode(vec, rows, digits, pattVec); // compress + } + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + TFile flOut("test_ctf_tof.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + auto* ctfImage = CTF::get(vec.data()); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "TOF"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + { + sw.Start(); + TFile flIn("test_ctf_tof.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + CTF::readFromTree(vec, *(tree.get()), "TOF"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<Digit> digitsD; + std::vector<ReadoutWindowData> rowsD; + std::vector<uint32_t> pattVecD; + sw.Start(); + const auto ctfImage = CTF::getImage(vec.data()); + { + CTFCoder coder; + coder.decode(ctfImage, rowsD, digitsD, pattVecD); // decompress + } + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + // + // simple checks + BOOST_CHECK(rows.size() == rowsD.size()); + BOOST_CHECK(digits.size() == digitsD.size()); + BOOST_CHECK(pattVec.size() == pattVecD.size()); + + // more sophisticated checks + + // checks on patterns + int npatt = ctfImage.getHeader().nPatternBytes; + for (int i = 0; i < npatt; i += 100) { + BOOST_CHECK(pattVecD[i] == pattVec[i]); + } +} From 97ecf8bab751283f428ef36a887fb36054677338 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 29 Aug 2020 07:57:36 +0200 Subject: [PATCH 0498/1751] DPL: expose TimesliceIndex only through DataRelayer (#4248) --- Framework/Core/include/Framework/DataRelayer.h | 4 ++++ Framework/Core/src/DataProcessingDevice.cxx | 5 +++-- Framework/Core/src/DataRelayer.cxx | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/DataRelayer.h b/Framework/Core/include/Framework/DataRelayer.h index 18dc109592cda..506213c72f4b8 100644 --- a/Framework/Core/include/Framework/DataRelayer.h +++ b/Framework/Core/include/Framework/DataRelayer.h @@ -102,6 +102,10 @@ class DataRelayer void sendContextState(); void publishMetrics(); + /// Get timeslice associated to a given slot. + /// Notice how this avoids exposing the timesliceIndex directly + /// so that we can mutex on it. + TimesliceId getTimesliceForSlot(TimesliceSlot slot); /// Remove all pending messages void clear(); diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 05a8b47f6a86f..0a1ad1b66d0a6 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -766,8 +766,9 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, // create messages) because the messages need to have the timeslice id into // it. auto prepareAllocatorForCurrentTimeSlice = [& timingInfo = context.timingInfo, - ×liceIndex = context.registry->get<TimesliceIndex>()](TimesliceSlot i) { - auto timeslice = timesliceIndex.getTimesliceForSlot(i); + &relayer = context.relayer](TimesliceSlot i) { + ZoneScopedN("DataProcessingDevice::prepareForCurrentTimeslice"); + auto timeslice = relayer->getTimesliceForSlot(i); timingInfo->timeslice = timeslice.value; }; diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index 8ee9257de9470..b332304ca432d 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -72,6 +72,12 @@ DataRelayer::DataRelayer(const CompletionPolicy& policy, } } +TimesliceId DataRelayer::getTimesliceForSlot(TimesliceSlot slot) +{ + std::scoped_lock<LockableBase(std::recursive_mutex)> lock(mMutex); + return mTimesliceIndex.getTimesliceForSlot(slot); +} + DataRelayer::ActivityStats DataRelayer::processDanglingInputs(std::vector<ExpirationHandler> const& expirationHandlers, ServiceRegistry& services) { From b18206b13c6c572f02a059bb284d6fa3442a774f Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Wed, 26 Aug 2020 17:07:02 +0200 Subject: [PATCH 0499/1751] TPCClusterFinder: Improve mc label performance. --- GPU/GPUTracking/Base/GPUHostDataTypes.h | 3 -- .../Base/GPUReconstructionKernels.h | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 12 ++--- .../GPUTPCCFMCLabelFlattener.cxx | 48 ++++++++++--------- .../TPCClusterFinder/GPUTPCClusterFinder.cxx | 9 ++-- .../TPCClusterFinder/GPUTPCClusterFinder.h | 5 +- 6 files changed, 36 insertions(+), 43 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUHostDataTypes.h b/GPU/GPUTracking/Base/GPUHostDataTypes.h index c09116b11efdb..f87f49f251e0a 100644 --- a/GPU/GPUTracking/Base/GPUHostDataTypes.h +++ b/GPU/GPUTracking/Base/GPUHostDataTypes.h @@ -26,8 +26,6 @@ #include <vector> #include <array> -#include <memory> -#include <mutex> #include "DataFormatsTPC/Constants.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" @@ -43,7 +41,6 @@ struct GPUTPCDigitsMCInput { struct GPUTPCClusterMCInterim { std::vector<o2::MCCompLabel> labels; - uint offset; }; struct GPUTPCLinearLabels { diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index 1350ca1c5f289..558ce569f9952 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -77,7 +77,7 @@ GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, updatePeaks ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFDeconvolution ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFClusterizer ), (single), (), ()) GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, setRowOffsets ), (single), (), ()) -GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, flatten ), (single), (, unsigned int row, GPUPtr1(GPUTPCLinearLabels*, out)), (, row, GPUPtr2(GPUTPCLinearLabels*, out))) +GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, flatten ), (single), (, GPUPtr1(GPUTPCLinearLabels*, out)), (, GPUPtr2(GPUTPCLinearLabels*, out))) GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanStart ), (single), (, int iBuf, int stage), (, iBuf, stage)) GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanUp ), (single), (, int iBuf, int nElems), (, iBuf, nElems)) GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanTop ), (single), (, int iBuf, int nElems), (, iBuf, nElems)) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 8d4489868b893..63aecd685abec 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1287,15 +1287,9 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) continue; } - runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::setRowOffsets>(GetGrid(GPUCA_ROW_COUNT, lane), {iSlice}, {}); - GPUTPCCFMCLabelFlattener::setGlobalOffsetsAndAllocate(clusterer, mcLinearLabels); - for (unsigned int j = 0; j < GPUCA_ROW_COUNT; j++) { - if (clusterer.mPclusterInRow[j] == 0) { - continue; - } - runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::flatten>(GetGrid(clusterer.mPclusterInRow[j], lane), {iSlice}, {}, j, &mcLinearLabels); - } - clusterer.clearMCMemory(); + runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::setRowOffsets>(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}); + GPUTPCCFMCLabelFlattener::setGlobalOffsetsAndAllocate(clusterer, mcLinearLabels); // TODO: use clustererShadow here + runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::flatten>(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}, &mcLinearLabels); } if (buildNativeHost && buildNativeGPU && anyLaneHasData) { if (GetProcessingSettings().delayedOutput) { diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx index 01d1701fdacac..7e1cc4d487810 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx @@ -28,16 +28,12 @@ void GPUTPCCFMCLabelFlattener::setGlobalOffsetsAndAllocate( uint headerOffset = labels.header.size(); uint dataOffset = labels.data.size(); + cls.mPlabelsHeaderGlobalOffset = headerOffset; + cls.mPlabelsDataGlobalOffset = dataOffset; + for (Row row = 0; row < GPUCA_ROW_COUNT; row++) { - cls.mPlabelHeaderOffset[row] = headerOffset; headerOffset += cls.mPclusterInRow[row]; - - cls.mPlabelDataOffset[row] = dataOffset; - if (cls.mPclusterInRow[row] > 0) { - auto& lastInterim = cls.mPlabelsByRow[cls.mNMaxClusterPerRow * row + cls.mPclusterInRow[row] - 1]; - uint labelsInRow = lastInterim.offset + lastInterim.labels.size(); - dataOffset += labelsInRow; - } + dataOffset += cls.mPlabelsInRow[row]; } labels.header.resize(headerOffset); @@ -52,32 +48,40 @@ GPUd() void GPUTPCCFMCLabelFlattener::Thread<GPUTPCCFMCLabelFlattener::setRowOff Row row = get_global_id(0); uint clusterInRow = clusterer.mPclusterInRow[row]; - uint offset = 0; + uint labelCount = 0; for (uint i = 0; i < clusterInRow; i++) { auto& interim = clusterer.mPlabelsByRow[row * clusterer.mNMaxClusterPerRow + i]; - interim.offset = offset; - offset += interim.labels.size(); + labelCount += interim.labels.size(); } + + clusterer.mPlabelsInRow[row] = labelCount; #endif } template <> -GPUd() void GPUTPCCFMCLabelFlattener::Thread<GPUTPCCFMCLabelFlattener::flatten>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory&, processorType& clusterer, uint row, GPUTPCLinearLabels* out) +GPUd() void GPUTPCCFMCLabelFlattener::Thread<GPUTPCCFMCLabelFlattener::flatten>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory&, processorType& clusterer, GPUTPCLinearLabels* out) { #if !defined(GPUCA_GPUCODE) - uint idx = get_global_id(0); - - GPUTPCClusterMCInterim& interim = clusterer.mPlabelsByRow[row * clusterer.mNMaxClusterPerRow + idx]; + uint row = get_global_id(0); - uint headerOffset = clusterer.mPlabelHeaderOffset[row] + idx; - uint dataOffset = clusterer.mPlabelDataOffset[row] + interim.offset; - - assert(dataOffset + interim.labels.size() <= out->data.size()); + uint headerOffset = clusterer.mPlabelsHeaderGlobalOffset; + uint dataOffset = clusterer.mPlabelsDataGlobalOffset; + for (int r = 0; r < row; r++) { + headerOffset += clusterer.mPclusterInRow[r]; + dataOffset += clusterer.mPlabelsInRow[r]; + } - out->header[headerOffset] = dataOffset; - std::copy(interim.labels.cbegin(), interim.labels.cend(), out->data.begin() + dataOffset); + auto* labels = &clusterer.mPlabelsByRow[row * clusterer.mNMaxClusterPerRow]; + for (uint c = 0; c < clusterer.mPclusterInRow[row]; c++) { + GPUTPCClusterMCInterim& interim = labels[c]; + assert(dataOffset + interim.labels.size() <= out->data.size()); + out->header[headerOffset] = dataOffset; + std::copy(interim.labels.cbegin(), interim.labels.cend(), out->data.begin() + dataOffset); - interim = {}; // ensure interim labels are destroyed to prevent memleak + headerOffset++; + dataOffset += interim.labels.size(); + interim = {}; // ensure interim labels are destroyed to prevent memleak + } #endif } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx index e654057b675df..5bdcf9fc475aa 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx @@ -134,8 +134,7 @@ void GPUTPCClusterFinder::PrepareMC() clearMCMemory(); mPindexMap = new uint[TPCMapMemoryLayout<decltype(*mPindexMap)>::items()]; mPlabelsByRow = new GPUTPCClusterMCInterim[GPUCA_ROW_COUNT * mNMaxClusterPerRow]; - mPlabelHeaderOffset = new uint[GPUCA_ROW_COUNT]; - mPlabelDataOffset = new uint[GPUCA_ROW_COUNT]; + mPlabelsInRow = new uint[GPUCA_ROW_COUNT]; } void GPUTPCClusterFinder::clearMCMemory() @@ -144,8 +143,6 @@ void GPUTPCClusterFinder::clearMCMemory() mPindexMap = nullptr; delete[] mPlabelsByRow; mPlabelsByRow = nullptr; - delete[] mPlabelHeaderOffset; - mPlabelHeaderOffset = nullptr; - delete[] mPlabelDataOffset; - mPlabelDataOffset = nullptr; + delete[] mPlabelsInRow; + mPlabelsInRow = nullptr; } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index f50f357180f3b..81670d98fed26 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -107,8 +107,9 @@ class GPUTPCClusterFinder : public GPUProcessor Memory* mPmemory = nullptr; o2::dataformats::MCTruthContainer<o2::MCCompLabel> const* mPinputLabels = nullptr; - uint* mPlabelHeaderOffset = nullptr; - uint* mPlabelDataOffset = nullptr; + uint* mPlabelsInRow = nullptr; + uint mPlabelsHeaderGlobalOffset = 0; + uint mPlabelsDataGlobalOffset = 0; int mISlice = 0; constexpr static int mScanWorkGroupSize = GPUCA_THREAD_COUNT_SCAN; From 9191664a9958e6dd8816b98ea37c6c704cf523cc Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Wed, 26 Aug 2020 13:37:41 +0200 Subject: [PATCH 0500/1751] TPCClusterFinder: Allow propagating mc labels when running on GPU. --- .../Base/GPUReconstructionKernels.h | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 31 +++++++++++++------ .../TPCClusterFinder/GPUTPCCFClusterizer.cxx | 31 +++++++++++++------ .../TPCClusterFinder/GPUTPCCFClusterizer.h | 6 ++-- .../GPUTPCCFMCLabelFlattener.cxx | 2 +- .../TPCClusterFinder/GPUTPCClusterFinder.cxx | 11 ++++++- .../TPCClusterFinder/GPUTPCClusterFinder.h | 4 +++ 7 files changed, 61 insertions(+), 26 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index 558ce569f9952..ad8c00cb68c9e 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -75,7 +75,7 @@ GPUCA_KRNL_LB((GPUTPCCFPeakFinder ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, noiseSuppression ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, updatePeaks ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFDeconvolution ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFClusterizer ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFClusterizer ), (single), (, char onlyMC), (, onlyMC)) GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, setRowOffsets ), (single), (), ()) GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, flatten ), (single), (, GPUPtr1(GPUTPCLinearLabels*, out)), (, GPUPtr2(GPUTPCLinearLabels*, out))) GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanStart ), (single), (, int iBuf, int stage), (, iBuf, stage)) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 63aecd685abec..947c8fc5b3d7b 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1068,7 +1068,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) ClusterNativeAccess* tmpNative = mClusterNativeAccess.get(); // setup MC Labels - bool propagateMCLabels = !doGPU && GetProcessingSettings().runMC && processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC != nullptr; + bool propagateMCLabels = GetProcessingSettings().runMC && processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC != nullptr; auto* digitsMC = propagateMCLabels ? processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC : nullptr; @@ -1122,14 +1122,17 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) assert(clusterer.mPinputLabels->getIndexedSize() >= mIOPtrs.tpcPackedDigits->nTPCDigits[iSlice]); } - if (not mIOPtrs.tpcZS || propagateMCLabels) { + { + bool setDigitsOnGPU = doGPU && not mIOPtrs.tpcZS; + bool setDigitsOnHost = (not doGPU && not mIOPtrs.tpcZS) || propagateMCLabels; auto* inDigits = mIOPtrs.tpcPackedDigits; size_t numDigits = inDigits->nTPCDigits[iSlice]; - clusterer.mPmemory->counters.nDigits = numDigits; - if (doGPU) { + if (setDigitsOnGPU) { GPUMemCpy(RecoStep::TPCClusterFinding, clustererShadow.mPdigits, inDigits->tpcDigits[iSlice], sizeof(clustererShadow.mPdigits[0]) * numDigits, lane, true); - } else { - clustererShadow.mPdigits = const_cast<o2::tpc::Digit*>(inDigits->tpcDigits[iSlice]); // TODO: Needs fixing (invalid const cast) + clusterer.mPmemory->counters.nDigits = numDigits; + } else if (setDigitsOnHost) { + clusterer.mPdigits = const_cast<o2::tpc::Digit*>(inDigits->tpcDigits[iSlice]); // TODO: Needs fixing (invalid const cast) + clusterer.mPmemory->counters.nDigits = numDigits; } } @@ -1156,9 +1159,12 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) continue; } - if (propagateMCLabels || not mIOPtrs.tpcZS) { + if (not mIOPtrs.tpcZS) { runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::findFragmentStart>(GetGrid(1, lane), {iSlice}, {}, mIOPtrs.tpcZS == nullptr); TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); + } else if (propagateMCLabels) { + runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::findFragmentStart>(GetGrid(1, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}, mIOPtrs.tpcZS == nullptr); + TransferMemoryResourceLinkToGPU(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); } if (mIOPtrs.tpcZS) { @@ -1196,7 +1202,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } if (propagateMCLabels) { - runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::fillIndexMap>(GetGrid(clusterer.mPmemory->counters.nDigitsInFragment, lane), {iSlice}, {}); + runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::fillIndexMap>(GetGrid(clusterer.mPmemory->counters.nDigitsInFragment, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}); } runKernel<GPUTPCCFPeakFinder>(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); @@ -1240,7 +1246,12 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) runKernel<GPUTPCCFDeconvolution>(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); - runKernel<GPUTPCCFClusterizer>(GetGrid(clusterer.mPmemory->counters.nClusters, lane), {iSlice}, {}); + runKernel<GPUTPCCFClusterizer>(GetGrid(clusterer.mPmemory->counters.nClusters, lane), {iSlice}, {}, 0); + if (doGPU && propagateMCLabels) { + TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mScratchId, lane); + SynchronizeStream(lane); + runKernel<GPUTPCCFClusterizer>(GetGrid(clusterer.mPmemory->counters.nClusters, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}, 1); + } if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Lane %d: Found clusters: digits %u peaks %u clusters %u", lane, (int)clusterer.mPmemory->counters.nPositions, (int)clusterer.mPmemory->counters.nPeaks, (int)clusterer.mPmemory->counters.nClusters); } @@ -1288,7 +1299,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::setRowOffsets>(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}); - GPUTPCCFMCLabelFlattener::setGlobalOffsetsAndAllocate(clusterer, mcLinearLabels); // TODO: use clustererShadow here + GPUTPCCFMCLabelFlattener::setGlobalOffsetsAndAllocate(clusterer, mcLinearLabels); runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::flatten>(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}, &mcLinearLabels); } if (buildNativeHost && buildNativeGPU && anyLaneHasData) { diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx index 31ff57058a77a..213c111310fb7 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx @@ -25,13 +25,15 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace GPUCA_NAMESPACE::gpu::tpccf; template <> -GPUdii() void GPUTPCCFClusterizer::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer) +GPUdii() void GPUTPCCFClusterizer::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, char onlyMC) { Array2D<PackedCharge> chargeMap(reinterpret_cast<PackedCharge*>(clusterer.mPchargeMap)); CPU_ONLY( MCLabelAccumulator labelAcc(clusterer)); - GPUTPCCFClusterizer::computeClustersImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), clusterer.mPmemory->fragment, smem, chargeMap, clusterer.mPfilteredPeakPositions, CPU_PTR(&labelAcc), clusterer.mPmemory->counters.nClusters, clusterer.mNMaxClusterPerRow, clusterer.mPclusterInRow, clusterer.mPclusterByRow); + tpc::ClusterNative* clusterOut = (onlyMC) ? nullptr : clusterer.mPclusterByRow; + + GPUTPCCFClusterizer::computeClustersImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), clusterer.mPmemory->fragment, smem, chargeMap, clusterer.mPfilteredPeakPositions, CPU_PTR(&labelAcc), clusterer.mPmemory->counters.nClusters, clusterer.mNMaxClusterPerRow, clusterer.mPclusterInRow, clusterOut, clusterer.mPclusterPosInRow); } GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads, int iBlock, int iThread, @@ -43,7 +45,8 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads uint clusternum, uint maxClusterPerRow, uint* clusterInRow, - tpc::ClusterNative* clusterByRow) + tpc::ClusterNative* clusterByRow, + uint* clusterPosInRow) { uint idx = get_global_id(0); @@ -80,16 +83,24 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads #endif if (!aboveQTotCutoff) { + clusterPosInRow[idx] = maxClusterPerRow; return; } - uint rowIndex = sortIntoBuckets( - myCluster, - pos.row(), - maxClusterPerRow, - clusterInRow, - clusterByRow); - static_cast<void>(rowIndex); // Avoid unused varible warning on GPU. + uint rowIndex; + if (clusterByRow != nullptr) { + rowIndex = sortIntoBuckets( + myCluster, + pos.row(), + maxClusterPerRow, + clusterInRow, + clusterByRow); + if (clusterPosInRow != nullptr) { + clusterPosInRow[idx] = rowIndex; + } + } else { + rowIndex = clusterPosInRow[idx]; + } CPU_ONLY(labelAcc->commit(pos.row(), rowIndex, maxClusterPerRow)); } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h index 58ab6452ab604..f47278a54038c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h @@ -55,10 +55,10 @@ class GPUTPCCFClusterizer : public GPUKernelTemplate return GPUDataTypes::RecoStep::TPCClusterFinding; } - template <int iKernel = defaultKernel, typename... Args> - GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); + template <int iKernel = defaultKernel> + GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, char); - static GPUd() void computeClustersImpl(int, int, int, int, const CfFragment&, GPUSharedMemory&, const Array2D<PackedCharge>&, const ChargePos*, MCLabelAccumulator*, uint, uint, uint*, tpc::ClusterNative*); + static GPUd() void computeClustersImpl(int, int, int, int, const CfFragment&, GPUSharedMemory&, const Array2D<PackedCharge>&, const ChargePos*, MCLabelAccumulator*, uint, uint, uint*, tpc::ClusterNative*, uint*); private: static GPUd() void updateClusterInner(ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*, uchar*); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx index 7e1cc4d487810..cbeb7fe2edef2 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx @@ -67,7 +67,7 @@ GPUd() void GPUTPCCFMCLabelFlattener::Thread<GPUTPCCFMCLabelFlattener::flatten>( uint headerOffset = clusterer.mPlabelsHeaderGlobalOffset; uint dataOffset = clusterer.mPlabelsDataGlobalOffset; - for (int r = 0; r < row; r++) { + for (uint r = 0; r < row; r++) { headerOffset += clusterer.mPclusterInRow[r]; dataOffset += clusterer.mPlabelsInRow[r]; } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx index 5bdcf9fc475aa..bab748e6f44b6 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx @@ -78,6 +78,9 @@ void* GPUTPCClusterFinder::SetPointersScratch(void* mem) computePointerWithAlignment(mem, mPpositions, mNMaxDigitsFragment); computePointerWithAlignment(mem, mPpeakPositions, mNMaxPeaks); computePointerWithAlignment(mem, mPfilteredPeakPositions, mNMaxClusters); + if (mRec->GetProcessingSettings().runMC) { + computePointerWithAlignment(mem, mPclusterPosInRow, mNMaxClusters); + } computePointerWithAlignment(mem, mPisPeak, mNMaxDigitsFragment); computePointerWithAlignment(mem, mPchargeMap, TPCMapMemoryLayout<decltype(*mPchargeMap)>::items()); computePointerWithAlignment(mem, mPpeakMap, TPCMapMemoryLayout<decltype(*mPpeakMap)>::items()); @@ -90,7 +93,13 @@ void GPUTPCClusterFinder::RegisterMemoryAllocation() { AllocateAndInitializeLate(); mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersInput, GPUMemoryResource::MEMORY_INPUT | GPUMemoryResource::MEMORY_GPU | GPUMemoryResource::MEMORY_STACK, "TPCClustererInput"); - mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCClustererScratch", GPUMemoryReuse{GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::ClustererScratch, (unsigned short)(mISlice % mRec->GetProcessingSettings().nTPCClustererLanes)}); + + int scratchType = GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK; + if (mRec->GetProcessingSettings().runMC) { + scratchType |= GPUMemoryResource::MEMORY_HOST | GPUMemoryResource::MEMORY_GPU; + } + mScratchId = mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersScratch, scratchType, "TPCClustererScratch", GPUMemoryReuse{GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::ClustererScratch, (unsigned short)(mISlice % mRec->GetProcessingSettings().nTPCClustererLanes)}); + mMemoryId = mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersMemory, GPUMemoryResource::MEMORY_PERMANENT, "TPCClustererMemory"); mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersOutput, GPUMemoryResource::MEMORY_OUTPUT | GPUMemoryResource::MEMORY_STACK, "TPCClustererOutput"); mZSId = mRec->RegisterMemoryAllocation(this, &GPUTPCClusterFinder::SetPointersZS, GPUMemoryResource::MEMORY_CUSTOM | GPUMemoryResource::MEMORY_CUSTOM_TRANSFER | GPUMemoryResource::MEMORY_GPU | GPUMemoryResource::MEMORY_STACK, "TPCClustererZSData", GPUMemoryReuse{GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::ClustererZS, (unsigned short)(mISlice % mRec->GetProcessingSettings().nTPCClustererLanes)}); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index 81670d98fed26..c29aff7887392 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -97,6 +97,9 @@ class GPUTPCClusterFinder : public GPUProcessor ChargePos* mPpeakPositions = nullptr; ChargePos* mPfilteredPeakPositions = nullptr; unsigned char* mPisPeak = nullptr; + uint* mPclusterPosInRow = nullptr; // store the index where the corresponding cluster is stored in a bucket. + // Required when MC are enabled to write the mc data to the correct position. + // Set to >= mNMaxClusterPerRow if cluster was discarded. ushort* mPchargeMap = nullptr; unsigned char* mPpeakMap = nullptr; uint* mPindexMap = nullptr; @@ -123,6 +126,7 @@ class GPUTPCClusterFinder : public GPUProcessor unsigned int mNBufs = 0; short mMemoryId = -1; + short mScratchId = -1; short mZSId = -1; short mZSOffsetId = -1; short mOutputId = -1; From 54076da82f09aa871e8e11db907cad410f913c38 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 29 Aug 2020 15:42:23 +0200 Subject: [PATCH 0501/1751] Updated mat.budget LUT builder segmentation --- Detectors/Base/CMakeLists.txt | 2 +- Detectors/Base/test/buildMatBudLUT.C | 170 ++++++++++++++++++++++----- 2 files changed, 143 insertions(+), 29 deletions(-) diff --git a/Detectors/Base/CMakeLists.txt b/Detectors/Base/CMakeLists.txt index 38a19f74d5fd3..5d0b031415a4c 100644 --- a/Detectors/Base/CMakeLists.txt +++ b/Detectors/Base/CMakeLists.txt @@ -49,7 +49,7 @@ if(BUILD_SIMULATION) MatBudLUT SOURCES test/testMatBudLUT.cxx COMPONENT_NAME DetectorsBase - PUBLIC_LINK_LIBRARIES O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::ITSMFTReconstruction LABELS detectorsbase ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/${CMAKE_INSTALL_DATADIR}) diff --git a/Detectors/Base/test/buildMatBudLUT.C b/Detectors/Base/test/buildMatBudLUT.C index 6244b6cec0018..b0f0d0d2ac2b3 100644 --- a/Detectors/Base/test/buildMatBudLUT.C +++ b/Detectors/Base/test/buildMatBudLUT.C @@ -15,9 +15,11 @@ #include "DetectorsBase/MatLayerCylSet.h" #include "DetectorsBase/MatLayerCyl.h" #include "DetectorsBase/GeometryManager.h" +#include "ITSMFTReconstruction/ChipMappingITS.h" #include "DetectorsCommonDataFormats/NameConf.h" #include <TFile.h> #include <TSystem.h> +#include <TStopwatch.h> #endif #ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version @@ -60,16 +62,22 @@ bool buildMatBudLUT(int nTst, int maxLr, std::string outName, std::string outFil } for (int i = 0; i < maxLr; i++) { auto& l = lrData[i]; + printf("L:%3d %6.2f<R<%6.2f ZH=%5.1f | dz = %6.2f drph = %6.2f\n", i, l.rMin, l.rMax, l.zHalf, l.dZMin, l.dRPhiMin); mbLUT.addLayer(l.rMin, l.rMax, l.zHalf, l.dZMin, l.dRPhiMin); } + TStopwatch sw; mbLUT.populateFromTGeo(nTst); mbLUT.optimizePhiSlices(); // move to populateFromTGeo mbLUT.flatten(); // move to populateFromTGeo mbLUT.writeToFile(outFile, outName); - + sw.Stop(); + sw.Print(); + sw.Start(false); mbLUT.dumpToTree("matbudTree.root"); + sw.Stop(); + sw.Print(); return true; } @@ -172,18 +180,23 @@ bool testMBLUT(std::string lutName, std::string lutFile) //_______________________________________________________________________ void configLayers() { + const int NSect = 18; + const float kToler = 1e-3; float drStep = 0.f, zSpanH = 0.f, zBin = 0.f, rphiBin = 0.f, phiBin = 0.f; + o2::itsmft::ChipMappingITS mp; + int nStave = 0; + // rMin rMax zHalf lrData.emplace_back(LrData(0.0f, 1.8f, 30.f)); // beam pipe - lrData.emplace_back(LrData(lrData.back().rMax, 1.9f, 30.f)); + lrData.emplace_back(LrData(lrData.back().rMax, 2.0f, 30.f)); // ITS Inner Barrel drStep = 0.1; - zSpanH = 17.; + zSpanH = 20.; rphiBin = 0.2; // 0.1; zBin = 0.5; do { @@ -191,64 +204,140 @@ void configLayers() } while (lrData.back().rMax < 5.2 + kToler); // air space between Inner and Middle Barrels - lrData.emplace_back(LrData(lrData.back().rMax, 18.0, zSpanH)); + zSpanH = 40.; + zBin = 5.; + rphiBin = 2.; + lrData.emplace_back(LrData(lrData.back().rMax, 19.0, zSpanH, zBin, rphiBin)); + //=================================================================================== // ITS Middle Barrel - drStep = 0.2; - zSpanH = 50.; - rphiBin = 0.5; + nStave = mp.getNStavesOnLr(3); // Lr 3 + zSpanH = 55.; zBin = 0.5; + drStep = 0.2; + do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 20.5 + kToler); + + drStep = 0.5; + do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 24. + kToler); + + nStave = mp.getNStavesOnLr(3); // Lr 4 + drStep = 0.2; + do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 25.6 + kToler); + drStep = 0.5; do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); } while (lrData.back().rMax < 29. + kToler); + //=================================================================================== + // air space between Middle and Outer Barrels zSpanH = 80.f; lrData.emplace_back(LrData(lrData.back().rMax, 33.5, zSpanH)); + //=================================================================================== // ITS Outer barrel - drStep = 0.5; + nStave = mp.getNStavesOnLr(5); // Lr 5 + drStep = 0.25; zSpanH = 80.; - rphiBin = 1.; zBin = 1.; do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); - } while (lrData.back().rMax < 45.5 + kToler); + } while (lrData.back().rMax < 36. + kToler); + + drStep = 1.; + do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 38.5 + kToler); + + nStave = mp.getNStavesOnLr(6); // Lr 6 + drStep = 0.25; + do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 41. + kToler); + + drStep = 1.; + do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (nStave * 10); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 44. + kToler); + + //=================================================================================== - // air space between Outer Barrel and shell zSpanH = 100.f; - lrData.emplace_back(LrData(lrData.back().rMax, 59.5, zSpanH)); + zBin = 5.; + lrData.emplace_back(LrData(lrData.back().rMax, 47., zSpanH, zBin)); - // Shell - drStep = 0.5; - zSpanH = 100.; - rphiBin = 1.; - zBin = 1.; + drStep = 2.; + zBin = 5.; + rphiBin = 2.; do { lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); - } while (lrData.back().rMax < 63. + kToler); + } while (lrData.back().rMax < 53. + kToler); - // air space between Shell and TPC - zSpanH = 250.f; - lrData.emplace_back(LrData(lrData.back().rMax, 76, zSpanH)); + zSpanH = 120.f; + lrData.emplace_back(LrData(lrData.back().rMax, 56.5, zSpanH)); + + zSpanH = 150.f; + drStep = 4.; + zBin = 15.; + rphiBin = 10; + do { + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 68.5 + kToler); + zSpanH = 250.f; + zBin = 25.; + rphiBin = 5; + { + auto rmean = (lrData.back().rMax + 76) / 2.; + rphiBin = rmean * TMath::Pi() * 2 / (NSect * 2); + lrData.emplace_back(LrData(lrData.back().rMax, 76, zSpanH, zBin, rphiBin)); + } // TPC inner vessel // up to r = 78.5 zSpanH = 250.f; - rphiBin = 1.; zBin = 25.; - lrData.emplace_back(LrData(lrData.back().rMax, 78.5, zSpanH, zBin, rphiBin)); - + { + auto rmean = (lrData.back().rMax + 78.5) / 2; + rphiBin = rmean * TMath::Pi() * 2 / (NSect * 12); + lrData.emplace_back(LrData(lrData.back().rMax, 78.5, zSpanH, zBin, rphiBin)); + } // zSpanH = 250.f; - rphiBin = 2.; zBin = 2; - lrData.emplace_back(LrData(lrData.back().rMax, 84.5, zSpanH, zBin, rphiBin)); + { + auto rmean = (lrData.back().rMax + 78.5) / 2; + rphiBin = rmean * TMath::Pi() * 2 / (NSect * 12); + lrData.emplace_back(LrData(lrData.back().rMax, 84.5, zSpanH, zBin, rphiBin)); + } // TPC drum zSpanH = 250.f; lrData.emplace_back(LrData(lrData.back().rMax, 250.0, zSpanH)); + //=============================== + // TPC outer vessel zSpanH = 247.f; // ignore large lumps of material at |z|>247 rphiBin = 2.; @@ -260,13 +349,38 @@ void configLayers() zBin = 999.; // no segmentation in Z lrData.emplace_back(LrData(lrData.back().rMax, 280., zSpanH, zBin, rphiBin)); + // TRD + + zSpanH = 360.; + drStep = 1; + zBin = 10; + do { + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (NSect * 12); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 370); + + // TOF + zSpanH = 380.; drStep = 1; - zBin = 5; + zBin = 10; rphiBin = 5.; do { - zSpanH = lrData.back().rMax; + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (NSect * 12); lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); } while (lrData.back().rMax < 400); + + // rest + drStep = 1; + zBin = 10; + rphiBin = 5.; + do { + zSpanH = lrData.back().rMax; + auto rmean = lrData.back().rMax + drStep / 2; + rphiBin = rmean * TMath::Pi() * 2 / (NSect * 12); + lrData.emplace_back(LrData(lrData.back().rMax, lrData.back().rMax + drStep, zSpanH, zBin, rphiBin)); + } while (lrData.back().rMax < 500); } #endif //!_COMPILED_ON_GPU_ From ece711f91e028ad2b0245c9d17aa66fdf41a5ad8 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Sat, 29 Aug 2020 18:15:21 +0200 Subject: [PATCH 0502/1751] [EMCAL-610] Use mapping handler to access channel address mapping The mapping handler takes care of caching the mapping and providing the correct channel mapping for a given DDL ID. Replacing internal caching which was buggy. --- .../simulation/include/EMCALSimulation/RawWriter.h | 2 +- Detectors/EMCAL/simulation/src/RawWriter.cxx | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h index a9e1c2632ef2f..5eff51302fe83 100644 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h +++ b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h @@ -120,7 +120,7 @@ class RawWriter FileFor_t mFileFor = FileFor_t::kFullDet; ///< Granularity of the output files o2::emcal::Geometry* mGeometry = nullptr; ///< EMCAL geometry std::string mOutputLocation; ///< Rawfile name - std::array<o2::emcal::Mapper, 4> mMappers; ///< EMCAL mappers + std::unique_ptr<o2::emcal::MappingHandler> mMappingHandler; ///< Mapping handler gsl::span<o2::emcal::Digit> mDigits; ///< Digits input vector - must be in digitized format including the time response gsl::span<o2::emcal::TriggerRecord> mTriggers; ///< Trigger records, separating the data from different triggers std::vector<SRUDigitContainer> mSRUdata; ///< Internal helper of digits assigned to SRUs diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index 733953048a33b..3fa207f840518 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -56,12 +56,8 @@ void RawWriter::init() mRawWriter->registerLink(iddl, crorc, link, 0, rawfilename.data()); } // initialize mappers - std::array<char, 4> sides = {{'A', 'C'}}; - for (auto iside = 0; iside < sides.size(); iside++) { - for (auto isru = 0; isru < 20; isru++) { - mMappers[iside * 2 + isru].setMapping(Form("%s/share/Detectors/EMC/file/RCU%d%c.data", gSystem->Getenv("O2_ROOT"), isru, sides[iside])); - } - } + if (!mMappingHandler) + mMappingHandler = std::make_unique<o2::emcal::MappingHandler>(); // initialize containers for SRU for (auto isru = 0; isru < 40; isru++) { @@ -116,7 +112,7 @@ bool RawWriter::processNextTrigger() for (const auto& [tower, channel] : srucont.mChannels) { // Find out hardware address of the channel - auto hwaddress = mMappers[srucont.mSRUid].getHardwareAddress(channel.mRow, channel.mCol, ChannelType_t::HIGH_GAIN); // @TODO distinguish between high- and low-gain cells + auto hwaddress = mMappingHandler->getMappingForDDL(srucont.mSRUid).getHardwareAddress(channel.mRow, channel.mCol, ChannelType_t::HIGH_GAIN); // @TODO distinguish between high- and low-gain cells std::vector<int> rawbunches; for (auto& bunch : findBunches(channel.mDigits)) { From d25da5682f6b781bd38718744dc0e24e69108d05 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 29 Aug 2020 17:37:21 +0200 Subject: [PATCH 0503/1751] Create output dir. if needed, use default digits name --- Detectors/EMCAL/simulation/src/RawCreator.cxx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/simulation/src/RawCreator.cxx b/Detectors/EMCAL/simulation/src/RawCreator.cxx index 149f0f624281f..01bdcc1fabad0 100644 --- a/Detectors/EMCAL/simulation/src/RawCreator.cxx +++ b/Detectors/EMCAL/simulation/src/RawCreator.cxx @@ -11,12 +11,14 @@ #include <memory> #include <string> #include <vector> +#include "Framework/Logger.h" #include <boost/program_options.hpp> #include <TFile.h> #include <TTree.h> #include <TTreeReader.h> +#include <TSystem.h> #include "CommonUtils/ConfigurableParam.h" #include "CommonUtils/StringUtils.h" @@ -42,7 +44,7 @@ int main(int argc, const char** argv) auto add_option = opt_general.add_options(); add_option("help,h", "Print this help message"); add_option("verbose,v", bpo::value<uint32_t>()->default_value(0), "Select verbosity level [0 = no output]"); - add_option("input-file,i", bpo::value<std::string>()->required(), "Specifies digit input file."); + add_option("input-file,i", bpo::value<std::string>()->default_value("emcaldigits.root"), "Specifies digit input file."); add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,subdet,link"); add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); add_option("debug,d", bpo::value<uint32_t>()->default_value(0), "Select debug output level [0 = no debug output]"); @@ -72,6 +74,15 @@ int main(int argc, const char** argv) outputdir = vm["output-dir"].as<std::string>(), filefor = vm["file-for"].as<std::string>(); + // if needed, create output directory + if (gSystem->AccessPathName(outputdir.c_str())) { + if (gSystem->mkdir(outputdir.c_str(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outputdir; + } else { + LOG(INFO) << "created output directory " << outputdir; + } + } + std::unique_ptr<TFile> digitfile(TFile::Open(digitfilename.data(), "READ")); auto treereader = std::make_unique<TTreeReader>(static_cast<TTree*>(digitfile->Get("o2sim"))); TTreeReaderValue<std::vector<o2::emcal::Digit>> digitbranch(*treereader, "EMCALDigit"); @@ -99,4 +110,4 @@ int main(int argc, const char** argv) rawwriter.digitsToRaw(*digitbranch, *triggerbranch); } rawwriter.getWriter().writeConfFile("EMC", "RAWDATA", o2::utils::concat_string(outputdir, "raw.cfg")); -} \ No newline at end of file +} From 5c2e8d214a946f7023806e92a9ef2d92a5aff696 Mon Sep 17 00:00:00 2001 From: Matteo Concas <mconcas@cern.ch> Date: Sun, 30 Aug 2020 09:34:02 +0200 Subject: [PATCH 0504/1751] Workaround on ITS upgrade to pass tests (#4249) * Workaround on ITS upgrade to make tests happy @davidrohr : I cannot reproduce the issue myself at the moment, the most reasonable workaround I see at the moment is this, I'll anyway iterate on these files on Monday. If the issues were only the ones pointed in #4210 it should be sufficient, let me know otherwise. * Fix format * Update SimConfig.cxx This will exclude run4/run5 modules from default initialization but will allow their initialization by explicit option to o2-sim. * Fix clang-format Co-authored-by: David Rohr <github@jwdt.org> --- Common/SimConfig/src/SimConfig.cxx | 6 ++ .../PostLS4/IT4/base/src/GeometryTGeo.cxx | 99 ++++++++++--------- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index 050720278683d..5746a40462c82 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -67,7 +67,13 @@ bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& if (active.size() == 1 && active[0] == "all") { active.clear(); for (int d = DetID::First; d <= DetID::Last; ++d) { +#ifdef ENABLE_UPGRADES + if (d != DetID::IT3 && d != DetID::IT4) { + active.emplace_back(DetID::getName(d)); + } +#else active.emplace_back(DetID::getName(d)); +#endif } // add passive components manually (make a PassiveDetID for them!) active.emplace_back("HALL"); diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx index d686f3010e25d..b56970ed1eba9 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx @@ -450,55 +450,56 @@ void GeometryTGeo::fillTrackingFramesCache() //__________________________________________________________________________ int GeometryTGeo::extractNumberOfLayers() { - int numberOfLayers = 0; - - TGeoVolume* itsV = gGeoManager->GetVolume(getITSVolPattern()); - if (!itsV) { - LOG(FATAL) << "ITS volume " << getITSVolPattern() << " is not in the geometry"; - } - - // Loop on all ITSV nodes, count Layer volumes by checking names - // Build on the fly layer - wrapper correspondence - TObjArray* nodes = itsV->GetNodes(); - int nNodes = nodes->GetEntriesFast(); - - for (int j = 0; j < nNodes; j++) { - int lrID = -1; - TGeoNode* nd = (TGeoNode*)nodes->At(j); - const char* name = nd->GetName(); - - if (strstr(name, getITSLayerPattern())) { - numberOfLayers++; - if ((lrID = extractVolumeCopy(name, GeometryTGeo::getITSLayerPattern())) < 0) { - LOG(FATAL) << "Failed to extract layer ID from the " << name; - exit(1); - } - - mLayerToWrapper[lrID] = -1; // not wrapped - } else if (strstr(name, getITSWrapVolPattern())) { // this is a wrapper volume, may cointain layers - int wrID = -1; - if ((wrID = extractVolumeCopy(name, GeometryTGeo::getITSWrapVolPattern())) < 0) { - LOG(FATAL) << "Failed to extract wrapper ID from the " << name; - exit(1); - } - - TObjArray* nodesW = nd->GetNodes(); - int nNodesW = nodesW->GetEntriesFast(); - - for (int jw = 0; jw < nNodesW; jw++) { - TGeoNode* ndW = (TGeoNode*)nodesW->At(jw); - if (strstr(ndW->GetName(), getITSLayerPattern())) { - if ((lrID = extractVolumeCopy(ndW->GetName(), GeometryTGeo::getITSLayerPattern())) < 0) { - LOG(FATAL) << "Failed to extract layer ID from the " << name; - exit(1); - } - numberOfLayers++; - mLayerToWrapper[lrID] = wrID; - } - } - } - } - return numberOfLayers; + // int numberOfLayers = 0; + + // TGeoVolume* itsV = gGeoManager->GetVolume(getITSVolPattern()); + // if (!itsV) { + // LOG(FATAL) << "ITS volume " << getITSVolPattern() << " is not in the geometry"; + // } + + // // Loop on all ITSV nodes, count Layer volumes by checking names + // // Build on the fly layer - wrapper correspondence + // TObjArray* nodes = itsV->GetNodes(); + // int nNodes = nodes->GetEntriesFast(); + + // for (int j = 0; j < nNodes; j++) { + // int lrID = -1; + // TGeoNode* nd = (TGeoNode*)nodes->At(j); + // const char* name = nd->GetName(); + + // if (strstr(name, getITSLayerPattern())) { + // numberOfLayers++; + // if ((lrID = extractVolumeCopy(name, GeometryTGeo::getITSLayerPattern())) < 0) { + // LOG(FATAL) << "Failed to extract layer ID from the " << name; + // exit(1); + // } + + // mLayerToWrapper[lrID] = -1; // not wrapped + // } else if (strstr(name, getITSWrapVolPattern())) { // this is a wrapper volume, may cointain layers + // int wrID = -1; + // if ((wrID = extractVolumeCopy(name, GeometryTGeo::getITSWrapVolPattern())) < 0) { + // LOG(FATAL) << "Failed to extract wrapper ID from the " << name; + // exit(1); + // } + + // TObjArray* nodesW = nd->GetNodes(); + // int nNodesW = nodesW->GetEntriesFast(); + + // for (int jw = 0; jw < nNodesW; jw++) { + // TGeoNode* ndW = (TGeoNode*)nodesW->At(jw); + // if (strstr(ndW->GetName(), getITSLayerPattern())) { + // if ((lrID = extractVolumeCopy(ndW->GetName(), GeometryTGeo::getITSLayerPattern())) < 0) { + // LOG(FATAL) << "Failed to extract layer ID from the " << name; + // exit(1); + // } + // numberOfLayers++; + // mLayerToWrapper[lrID] = wrID; + // } + // } + // } + // } + // return numberOfLayers; + return 10; } //__________________________________________________________________________ From 66d55242f15475706c95eeda0e3c6d14eb8aa314 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 29 Aug 2020 15:38:07 +0200 Subject: [PATCH 0505/1751] Extract FT0 interaction selection params to separate configurable class --- .../FIT/FT0/reconstruction/CMakeLists.txt | 10 ++-- .../FT0Reconstruction/InteractionTag.h | 47 +++++++++++++++ .../src/FT0ReconstructionLinkDef.h | 1 + .../FT0/reconstruction/src/InteractionTag.cxx | 17 ++++++ Detectors/Vertexing/CMakeLists.txt | 1 + .../include/DetectorsVertexing/PVertexer.h | 18 +++--- .../DetectorsVertexing/PVertexerParams.h | 4 +- Detectors/Vertexing/src/PVertexer.cxx | 57 ++++++++++--------- 8 files changed, 110 insertions(+), 45 deletions(-) create mode 100644 Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h create mode 100644 Detectors/FIT/FT0/reconstruction/src/InteractionTag.cxx diff --git a/Detectors/FIT/FT0/reconstruction/CMakeLists.txt b/Detectors/FIT/FT0/reconstruction/CMakeLists.txt index 2a640cbde7df6..16a4eb8ffd97c 100644 --- a/Detectors/FIT/FT0/reconstruction/CMakeLists.txt +++ b/Detectors/FIT/FT0/reconstruction/CMakeLists.txt @@ -10,8 +10,9 @@ o2_add_library(FT0Reconstruction SOURCES src/CollisionTimeRecoTask.cxx - SOURCES src/ReadRaw.cxx - src/CTFCoder.cxx + src/ReadRaw.cxx + src/CTFCoder.cxx + src/InteractionTag.cxx PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::Framework O2::FT0Base @@ -24,6 +25,7 @@ o2_add_library(FT0Reconstruction o2_target_root_dictionary( FT0Reconstruction HEADERS include/FT0Reconstruction/CollisionTimeRecoTask.h - HEADERS include/FT0Reconstruction/ReadRaw.h - include/FT0Reconstruction/CTFCoder.h + include/FT0Reconstruction/ReadRaw.h + include/FT0Reconstruction/CTFCoder.h + include/FT0Reconstruction/InteractionTag.h ) diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h new file mode 100644 index 0000000000000..ca781e4d02009 --- /dev/null +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h @@ -0,0 +1,47 @@ +// 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 ruben.shahoyan@cern.ch + +#ifndef ALICEO2_FT0_INTERACTIONTAG_H +#define ALICEO2_FT0_INTERACTIONTAG_H + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" +#include "DataFormatsFT0/RecPoints.h" +#include "CommonConstants/LHCConstants.h" + +namespace o2 +{ +namespace ft0 +{ + +// These are configurable params for FT0 selection as interaction tag +struct InteractionTag : public o2::conf::ConfigurableParamHelper<InteractionTag> { + 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 + { + return rp.isValidTime(RecPoints::TimeMean) && (rp.getTrigger().amplA + rp.getTrigger().amplC) > minAmplitudeAC; + } + + 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? + } + + O2ParamDef(InteractionTag, "ft0tag"); +}; + +} // namespace ft0 +} // end namespace o2 + +#endif diff --git a/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h b/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h index 0296660c18f1d..e8811907900b5 100644 --- a/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h +++ b/Detectors/FIT/FT0/reconstruction/src/FT0ReconstructionLinkDef.h @@ -17,5 +17,6 @@ #pragma link C++ class o2::ft0::CollisionTimeRecoTask + ; #pragma link C++ class o2::ft0::ReadRaw + ; #pragma link C++ class o2::ft0::CTFCoder + ; +#pragma link C++ class o2::ft0::InteractionTag + ; #endif diff --git a/Detectors/FIT/FT0/reconstruction/src/InteractionTag.cxx b/Detectors/FIT/FT0/reconstruction/src/InteractionTag.cxx new file mode 100644 index 0000000000000..a384e40f28895 --- /dev/null +++ b/Detectors/FIT/FT0/reconstruction/src/InteractionTag.cxx @@ -0,0 +1,17 @@ +// 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 PVertexerParams.cxx +/// \brief Configurable params for primary vertexer +/// \author ruben.shahoyan@cern.ch + +#include "FT0Reconstruction/InteractionTag.h" + +O2ParamImpl(o2::ft0::InteractionTag); diff --git a/Detectors/Vertexing/CMakeLists.txt b/Detectors/Vertexing/CMakeLists.txt index ec04a9db02ccf..a650d99a4e91b 100644 --- a/Detectors/Vertexing/CMakeLists.txt +++ b/Detectors/Vertexing/CMakeLists.txt @@ -17,6 +17,7 @@ o2_add_library(DetectorsVertexing O2::CommonUtils O2::ReconstructionDataFormats O2::SimulationDataFormat + O2::FT0Reconstruction O2::DataFormatsFT0 ms_gsl::ms_gsl) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index 8735919dd9d10..39870ec6e2b15 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -28,6 +28,7 @@ #include "DataFormatsFT0/RecPoints.h" #include "DetectorsVertexing/PVertexerHelpers.h" #include "DetectorsVertexing/PVertexerParams.h" +#include "FT0Reconstruction/InteractionTag.h" #include "gsl/span" namespace o2 @@ -85,8 +86,8 @@ class PVertexer float estimateScale2() { - float minrange = std::min(mParams->zHistoBinSize, mParams->minZSeedRange); - auto sc = mParams->zHistoBinSize * mParams->zHistoBinSize * mTukey2I / (mStatZErr.getMean() * mStatZErr.getMean()); + float minrange = std::min(mPVParams->zHistoBinSize, mPVParams->minZSeedRange); + auto sc = mPVParams->zHistoBinSize * mPVParams->zHistoBinSize * mTukey2I / (mStatZErr.getMean() * mStatZErr.getMean()); return sc; } @@ -104,10 +105,6 @@ class PVertexer void clusterizeTimeBruteForce(float margin = 0.1, float cut = 25); void clusterizeTime(float binSize = 0.1, float maxTDist = 0.6); int findVertices(const VertexingInput& input, std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); - float getTimeMSFromTFStart(const o2::InteractionRecord& bc) const - { - return bc.differenceInBC(mStartIR) * 1e-3 * o2::constants::lhc::LHCBunchSpacingNS + mParams->timeBiasMS; - } int getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const; o2d::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; @@ -124,7 +121,8 @@ class PVertexer o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF ///========== Parameters to be set externally, e.g. from CCDB ==================== - const PVertexerParams* mParams = nullptr; + const PVertexerParams* mPVParams = nullptr; + const o2::ft0::InteractionTag* mFT0Params = nullptr; float mTukey2I = 0; ///< 1./[Tukey parameter]^2 static constexpr float kDefTukey = 5.0f; ///< def.value for tukey constant static constexpr float kHugeF = 1.e12; ///< very large float @@ -149,9 +147,9 @@ inline void PVertexer::applyConstraint(VertexSeed& vtxSeed) const inline bool PVertexer::upscaleSigma(VertexSeed& vtxSeed) const { // scale upward the scaleSigma2 if needes - if (vtxSeed.scaleSigma2 < mParams->maxScale2) { - auto s = vtxSeed.scaleSigma2 * mParams->upscaleFactor; - vtxSeed.setScale(s > mParams->maxScale2 ? mParams->maxScale2 : s, mTukey2I); + if (vtxSeed.scaleSigma2 < mPVParams->maxScale2) { + auto s = vtxSeed.scaleSigma2 * mPVParams->upscaleFactor; + vtxSeed.setScale(s > mPVParams->maxScale2 ? mPVParams->maxScale2 : s, mTukey2I); return true; } return false; diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h index 0be19eabaa426..128c0ca436a6b 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -21,7 +21,7 @@ namespace o2 namespace vertexing { -// There are configurable params for Primary Vertexer +// These are configurable params for Primary Vertexer struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParams> { static constexpr float kDefTukey = 5.0f; ///< def.value for tukey constant @@ -39,8 +39,6 @@ struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParam // validation with FT0 bool requireFT0ValidTimeMean = false; //true;///< require both FT0A/C int minNContributorsForFT0cut = 4; ///< do not apply FT0 cut to vertice below FT0 efficiency threshold - int minFT0AmplitudeAC = 20; ///< use only FT0 triggers with high enough aplitude - float timeBiasMS = 0.0; ///< relative bias in ms between TPC/ITS time and IR float maxTError = 0.2; ///< use min of vertex time error or this for nsigma evaluation float minTError = 0.003; ///< don't use error smaller than that (~BC/2/minNContributorsForFT0cut) float nSigmaFT0cut = 4.; ///< eliminate vertex if there is no FT0 signal within this cut diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index c3e2d58ab34d9..5f94a5bb585ac 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -71,7 +71,7 @@ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span vtx.setFlags(PVertex::TimeValidated); vtx.setIR(ft0Data[bestMatch].getInteractionRecord()); LOG(DEBUG) << "Validated with t0" << bestMatch; - } else if (vtx.getNContributors() >= mParams->minNContributorsForFT0cut) { + } else if (vtx.getNContributors() >= mPVParams->minNContributorsForFT0cut) { LOG(DEBUG) << "Discarding " << vtx; continue; // reject } @@ -106,11 +106,11 @@ int PVertexer::findVertices(const VertexingInput& input, std::vector<PVertex>& v // only those which are in the idRange and have canUse()==true, will be used. // Results are placed in vertices and v2tRefs vectors int nfound = 0, ntr = input.idRange.size(); - if (ntr < mParams->minTracksPerVtx) { + if (ntr < mPVParams->minTracksPerVtx) { return nfound; } // - SeedHisto seedHisto(mParams->zHistoRange, mParams->zHistoBinSize); + SeedHisto seedHisto(mPVParams->zHistoRange, mPVParams->zHistoBinSize); for (int i : input.idRange) { if (mTracksPool[i].canUse()) { @@ -118,7 +118,7 @@ int PVertexer::findVertices(const VertexingInput& input, std::vector<PVertex>& v seedHisto.incrementBin(mTracksPool[i].bin); } } - if (seedHisto.nFilled < mParams->minTracksPerVtx) { + if (seedHisto.nFilled < mPVParams->minTracksPerVtx) { return nfound; } @@ -174,7 +174,7 @@ bool PVertexer::findVertex(const VertexingInput& input, PVertex& vtx) if (result == FitStatus::OK) { result = evalIterations(vtxSeed, vtx); } else if (result == FitStatus::NotEnoughTracks) { - if (vtxSeed.nIterations <= mParams->maxIterations && upscaleSigma(vtxSeed)) { + if (vtxSeed.nIterations <= mPVParams->maxIterations && upscaleSigma(vtxSeed)) { LOG(DEBUG) << "Upscaling scale to " << vtxSeed.scaleSigma2; result = FitStatus::IterateFurther; continue; // redo with stronger rescaling @@ -208,8 +208,8 @@ PVertexer::FitStatus PVertexer::fitIteration(const VertexingInput& input, Vertex } } vtxSeed.maxScaleSigma2Tested = vtxSeed.scaleSigma2; - if (vtxSeed.getNContributors() < mParams->minTracksPerVtx) { - return nTested < mParams->minTracksPerVtx ? FitStatus::PoolEmpty : FitStatus::NotEnoughTracks; + if (vtxSeed.getNContributors() < mPVParams->minTracksPerVtx) { + return nTested < mPVParams->minTracksPerVtx ? FitStatus::PoolEmpty : FitStatus::NotEnoughTracks; } if (vtxSeed.useConstraint) { applyConstraint(vtxSeed); @@ -234,7 +234,7 @@ void PVertexer::accountTrack(TrackVF& trc, VertexSeed& vtxSeed) const } else { dt = timeT.getTimeStamp() - timeV.getTimeStamp(); trErr2I = 1. / (timeT.getTimeStampError() * timeT.getTimeStampError()); - if (mParams->useTimeInChi2) { + if (mPVParams->useTimeInChi2) { chi2T += dt * dt * trErr2I; ndff = 1. / 3.; } @@ -315,7 +315,7 @@ bool PVertexer::solveVertex(VertexSeed& vtxSeed) const auto newScale = vtxSeed.wghChi2 / vtxSeed.wghSum; LOG(DEBUG) << "Solve: wghChi2=" << vtxSeed.wghChi2 << " wghSum=" << vtxSeed.wghSum << " -> scale= " << newScale << " old scale " << vtxSeed.scaleSigma2 << " prevScale: " << vtxSeed.scaleSigma2Prev; //vtxSeed.print(); - vtxSeed.setScale(newScale < mParams->minScale2 ? mParams->minScale2 : newScale, mTukey2I); + vtxSeed.setScale(newScale < mPVParams->minScale2 ? mPVParams->minScale2 : newScale, mTukey2I); return true; } @@ -326,9 +326,9 @@ PVertexer::FitStatus PVertexer::evalIterations(VertexSeed& vtxSeed, PVertex& vtx // if scaleSigma2 reached its lower limit stop PVertexer::FitStatus result = PVertexer::FitStatus::IterateFurther; - if (vtxSeed.nIterations > mParams->maxIterations) { + if (vtxSeed.nIterations > mPVParams->maxIterations) { result = PVertexer::FitStatus::Failure; - } else if (vtxSeed.scaleSigma2Prev <= mParams->minScale2 + kAlmost0F) { + } else if (vtxSeed.scaleSigma2Prev <= mPVParams->minScale2 + kAlmost0F) { result = PVertexer::FitStatus::OK; LOG(DEBUG) << "stop on simga :" << vtxSeed.scaleSigma2 << " prev: " << vtxSeed.scaleSigma2Prev; } @@ -345,7 +345,7 @@ PVertexer::FitStatus PVertexer::evalIterations(VertexSeed& vtxSeed, PVertex& vtx if (result == PVertexer::FitStatus::OK) { auto chi2Mean = vtxSeed.getChi2() / vtxSeed.getNContributors(); - if (chi2Mean > mParams->maxChi2Mean) { + if (chi2Mean > mPVParams->maxChi2Mean) { result = PVertexer::FitStatus::Failure; LOG(DEBUG) << "Rejecting at iteration " << vtxSeed.nIterations << " and ScalePrev " << vtxSeed.scaleSigma2Prev << " with meanChi2 = " << chi2Mean; } else { @@ -354,15 +354,15 @@ PVertexer::FitStatus PVertexer::evalIterations(VertexSeed& vtxSeed, PVertex& vtx } if (vtxSeed.scaleSigma2 > vtxSeed.scaleSigma2Prev) { - if (++vtxSeed.nScaleIncrease > mParams->maxNScaleIncreased) { + if (++vtxSeed.nScaleIncrease > mPVParams->maxNScaleIncreased) { result = PVertexer::FitStatus::Failure; LOG(DEBUG) << "Rejecting at iteration " << vtxSeed.nIterations << " with NScaleIncreased " << vtxSeed.nScaleIncrease; } - } else if (vtxSeed.scaleSigma2 > mParams->slowConvergenceFactor * vtxSeed.scaleSigma2Prev) { - if (++vtxSeed.nScaleSlowConvergence > mParams->maxNScaleSlowConvergence) { - if (vtxSeed.scaleSigma2 < mParams->acceptableScale2) { - vtxSeed.setScale(mParams->minScale2, mTukey2I); - LOG(DEBUG) << "Forcing scale2 to " << mParams->minScale2; + } else if (vtxSeed.scaleSigma2 > mPVParams->slowConvergenceFactor * vtxSeed.scaleSigma2Prev) { + if (++vtxSeed.nScaleSlowConvergence > mPVParams->maxNScaleSlowConvergence) { + if (vtxSeed.scaleSigma2 < mPVParams->acceptableScale2) { + vtxSeed.setScale(mPVParams->minScale2, mTukey2I); + LOG(DEBUG) << "Forcing scale2 to " << mPVParams->minScale2; result = PVertexer::FitStatus::IterateFurther; } else { result = PVertexer::FitStatus::Failure; @@ -420,8 +420,9 @@ TimeEst PVertexer::timeEstimate(const VertexingInput& input) const //___________________________________________________________________ void PVertexer::init() { - mParams = &PVertexerParams::Instance(); - setTukey(mParams->tukey); + mPVParams = &PVertexerParams::Instance(); + mFT0Params = &o2::ft0::InteractionTag::Instance(); + setTukey(mPVParams->tukey); initMeanVertexConstraint(); } @@ -503,7 +504,7 @@ void PVertexer::clusterizeTimeBruteForce(float margin, float cut) int icur = mSortedTrackID[i]; const auto& trc = mTracksPool[icur]; if (!vtxT->isCompatible(trc.timeEst, margin, cut)) { - if (vtxT->count < mParams->minTracksPerVtx) { + if (vtxT->count < mPVParams->minTracksPerVtx) { vtxT->clear(); } else { vtxT = &tclist.emplace_back(); @@ -511,7 +512,7 @@ void PVertexer::clusterizeTimeBruteForce(float margin, float cut) } vtxT->addTrack(i, trc.timeEst); } - if (tclist.back().count < mParams->minTracksPerVtx) { + if (tclist.back().count < mPVParams->minTracksPerVtx) { tclist.pop_back(); } // final sort in decreasing multiplicity @@ -521,7 +522,7 @@ void PVertexer::clusterizeTimeBruteForce(float margin, float cut) std::sort(tcselSort.begin(), tcselSort.end(), [&tclist](int i, int j) { return tclist[i].count > tclist[j].count; }); mTimesClusters.reserve(tcselSort.size()); for (auto i : tcselSort) { - if (tclist[i].count >= mParams->minTracksPerVtx) { + if (tclist[i].count >= mPVParams->minTracksPerVtx) { mTimesClusters.push_back(tclist[i]); auto& tc = mTimesClusters.back(); // tc.print(); @@ -662,17 +663,17 @@ int PVertexer::getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::Re // check if the times stamp is compatible with any entry startinge from currEntry in ft0Data vector, return best matching time int best = -1, n = ft0Data.size(); auto t = vtx.getTimeStamp(); - while (currEntry < n && getTimeMSFromTFStart(ft0Data[currEntry].getInteractionRecord()) + mParams->nSigmaFT0cut * mParams->maxTError < t.getTimeStamp()) { + float cut = mPVParams->nSigmaFT0cut * mPVParams->maxTError, bestDf = cut, df = 0; + while (currEntry < n && mFT0Params->getInteractionTimeNS(ft0Data[currEntry], mStartIR) * 1e-3 + cut < t.getTimeStamp()) { currEntry++; // skip all times which have no chance to be matched } - float cut = mParams->nSigmaFT0cut * std::min(mParams->maxTError, std::max(mParams->minTError, t.getTimeStampError())), bestDf = cut, df = 0; + cut = mPVParams->nSigmaFT0cut * std::min(mPVParams->maxTError, std::max(mPVParams->minTError, t.getTimeStampError())); int i = currEntry; while (i < n) { - if ((df = getTimeMSFromTFStart(ft0Data[i].getInteractionRecord()) - t.getTimeStamp()) > bestDf) { + if ((df = mFT0Params->getInteractionTimeNS(ft0Data[i], mStartIR) * 1e-3) > bestDf) { break; } - auto ft0Trigger = ft0Data[i].getTrigger(); - if (ft0Trigger.amplA + ft0Trigger.amplC > mParams->minFT0AmplitudeAC) { + if (mFT0Params->isSelected(ft0Data[i])) { auto dfa = std::abs(df); if (dfa <= bestDf) { bestDf = dfa; From cd042fb232b17bbbf5e24b4880d649fc46eba1c6 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 29 Aug 2020 17:03:33 +0200 Subject: [PATCH 0506/1751] Optional use of FT0 time for ITS/TPC match selection or validation Providing option --use-ft0 option to o2-tpcits-match-workflow will add FIT (currently FT0) recpoints input which can be used either for validation or for selection of matching candidates. Option provided via MatchITSTPCParams configurable param: --configKeyValues "tpcitsMatch.validateMatchByFIT=Disable" will force to ignore FT0 data --configKeyValues "tpcitsMatch.validateMatchByFIT=Prefer" will affect comparison of matching candidates: the one with FIT match will be preferred irrespectively to chi2 of its competitor w/o such FIT tag. --configKeyValues "tpcitsMatch.validateMatchByFIT=Require" will require obligatory match to FIT for every TPC/ITS match. --- Detectors/GlobalTracking/CMakeLists.txt | 1 + .../include/GlobalTracking/MatchTPCITS.h | 68 +++++-- .../GlobalTracking/MatchTPCITSParams.h | 17 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 177 +++++++++++------- .../MatchTPCITSWorkflow.h | 2 +- .../TPCITSMatchingSpec.h | 6 +- .../src/MatchTPCITSWorkflow.cxx | 6 +- .../src/TPCITSMatchingSpec.cxx | 9 +- .../src/tpcits-match-workflow.cxx | 4 +- 9 files changed, 192 insertions(+), 98 deletions(-) diff --git a/Detectors/GlobalTracking/CMakeLists.txt b/Detectors/GlobalTracking/CMakeLists.txt index 92d10c7906c32..da30ffd8a8d79 100644 --- a/Detectors/GlobalTracking/CMakeLists.txt +++ b/Detectors/GlobalTracking/CMakeLists.txt @@ -19,6 +19,7 @@ o2_add_library( O2::DataFormatsFT0 O2::DataFormatsTOF O2::ITSReconstruction + O2::FT0Reconstruction O2::TPCFastTransformation O2::GPUTracking O2::TPCBase diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 0eabf19c2b8a6..2e69179244f2e 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -40,6 +40,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITS/TrackITS.h" #include "DataFormatsFT0/RecPoints.h" +#include "FT0Reconstruction/InteractionTag.h" #include "DataFormatsTPC/ClusterNativeHelper.h" #include "ITSReconstruction/RecoGeomHelper.h" #include "TPCFastTransform.h" @@ -121,15 +122,28 @@ struct TrackLocITS : public o2::track::TrackParCov { }; ///< record TPC or ITS track associated with single ITS or TPC track and reference on -///< the next (worse chi2) matchRecord of the same TPC or ITS track -struct matchRecord { +///< the next (worse chi2) MatchRecord of the same TPC or ITS track +struct MatchRecord { float chi2 = -1.f; ///< matching chi2 int partnerID = MinusOne; ///< id of parnter track entry in mTPCWork or mITSWork containers int nextRecID = MinusOne; ///< index of eventual next record + int matchedIC = MinusOne; ///< index of eventually matched InteractionCandidate + MatchRecord(int partID, float chi2match, int nxt = MinusOne, int candIC = MinusOne) : partnerID(partID), chi2(chi2match), nextRecID(nxt), matchedIC(candIC) {} + MatchRecord() = default; + + bool isBetter(float otherChi2, int otherIC = MinusOne) const + { // prefer record with matched IC candidate, otherwise, better chi2 + if (otherIC == MinusOne) { + return matchedIC == MinusOne ? chi2 < otherChi2 : true; + } else { + return matchedIC == MinusOne ? false : chi2 < otherChi2; + } + } - matchRecord(int partID, float chi2match) : partnerID(partID), chi2(chi2match) {} - matchRecord(int partID, float chi2match, int nxt) : partnerID(partID), chi2(chi2match), nextRecID(nxt) {} - matchRecord() = default; + bool isBetter(const MatchRecord& other) const + { + return isBetter(other.chi2, other.matchedIC); + } }; ///< Link of the AfterBurner track: update at sertain cluster @@ -313,6 +327,9 @@ class MatchTPCITS void setITSTriggered(bool v) { mITSTriggered = v; } bool isITSTriggered() const { return mITSTriggered; } + void setUseFT0(bool v) { mUseFT0 = v; } + bool getUseFT0() const { return mUseFT0; } + ///< set ITS ROFrame duration in microseconds void setITSROFrameLengthMUS(float fums) { mITSROFrameLengthMUS = fums; } ///< set ITS ROFrame duration in BC (continuous mode only) @@ -447,6 +464,8 @@ class MatchTPCITS #endif private: + void updateTPCTimeDependentParams(); + int findLaddersToCheckBOn(int ilr, int lad0, const o2::utils::CircleXY& circle, float errYFrac, std::array<int, MaxLadderCand>& lad2Check) const; int findLaddersToCheckBOff(int ilr, int lad0, const o2::utils::IntervalXY& trcLinPar, float errYFrac, @@ -486,8 +505,8 @@ class MatchTPCITS void addLastTrackCloneForNeighbourSector(int sector); ///------------------- manipulations with matches records ---------------------- - bool registerMatchRecordTPC(int iITS, int iTPC, float chi2); - void registerMatchRecordITS(int iITS, int iTPC, float chi2); + bool registerMatchRecordTPC(int iITS, int iTPC, float chi2, int candIC = MinusOne); + void registerMatchRecordITS(int iITS, int iTPC, float chi2, int candIC = MinusOne); void suppressMatchRecordITS(int iITS, int iTPC); ///< get number of matching records for TPC track @@ -510,10 +529,16 @@ class MatchTPCITS ///< convert ITS ROFrame to TPC time bin units // TOREMOVE float itsROFrame2TPCTimeBin(int rof) const { return rof * mITSROFrame2TPCBin; } + ///< convert time in microseconds to TPC time bin units + float time2TPCTimeBin(float tms) const + { + return tms * mTPCTBinMUSInv; + } + ///< convert Interaction Record for TPC time bin units float intRecord2TPCTimeBin(const o2::InteractionRecord& bc) const { - return bc.differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS / 1000 / mTPCTBinMUS; + return time2TPCTimeBin(bc.differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS * 1e-3); } ///< convert Z interval to TPC time-bins @@ -527,6 +552,21 @@ class MatchTPCITS { return delta > toler ? rejFlag : (delta < -toler ? -rejFlag : Accept); } + + ///< correct TPC time0 (int TPC time-bins) + float getTPCTrackCorrectedTimeBin(const o2::tpc::TrackTPC& trc, float delta) const + { + float timeTB = trc.getTime0(); + if (trc.hasASideClustersOnly()) { + timeTB += delta; + } else if (trc.hasCSideClustersOnly()) { + timeTB -= delta; + } else { + // TODO : special treatment of tracks crossing the CE + } + return timeTB; + } + //================================================================ bool mInitDone = false; ///< flag init already done @@ -537,10 +577,12 @@ class MatchTPCITS ///========== Parameters to be set externally, e.g. from CCDB ==================== const Params* mParams = nullptr; + const o2::ft0::InteractionTag* mFT0Params = nullptr; MatCorrType mUseMatCorrFlag = MatCorrType::USEMatCorrTGeo; bool mITSTriggered = false; ///< ITS readout is triggered + bool mUseFT0 = false; ///< FT0 information is available ///< do we use track Z difference to reject fake matches? makes sense for triggered mode only bool mCompareTracksDZ = false; @@ -556,6 +598,7 @@ class MatchTPCITS float mTPCVDrift0 = -1.; ///< TPC nominal drift speed in cm/microseconds float mTPCVDrift0Inv = -1.; ///< inverse TPC nominal drift speed in cm/microseconds float mTPCTBinMUS = 0.; ///< TPC time bin duration in microseconds + float mTPCTBinMUSInv = 0.; ///< inverse TPC time bin duration in microseconds float mITSROFrame2TPCBin = 0.; ///< conversion coeff from ITS ROFrame units to TPC time-bin float mTPCBin2ITSROFrame = 0.; ///< conversion coeff from TPC time-bin to ITS ROFrame units float mZ2TPCBin = 0.; ///< conversion coeff from Z to TPC time-bin @@ -588,11 +631,12 @@ class MatchTPCITS /// <<<----- std::vector<InteractionCandidate> mInteractions; ///< possible interaction times + std::vector<o2::dataformats::RangeRefComp<8>> mITSROFIntCandEntries; ///< entries of InteractionCandidate vector for every ITS ROF bin ///< container for record the match of TPC track to single ITS track - std::vector<matchRecord> mMatchRecordsTPC; - ///< container for reference to matchRecord involving particular ITS track - std::vector<matchRecord> mMatchRecordsITS; + std::vector<MatchRecord> mMatchRecordsTPC; + ///< container for reference to MatchRecord involving particular ITS track + std::vector<MatchRecord> mMatchRecordsITS; std::vector<int> mITSROFofTPCBin; ///< aux structure for mapping of TPC time-bins on ITS ROFs std::vector<BracketF> mITSROFTimes; ///< min/max times of ITS ROFs in TPC time-bins @@ -692,7 +736,7 @@ inline void MatchTPCITS::removeTPCfromITS(int tpcID, int itsID) if (isValidatedITS(tITS)) { return; } - int topID = MinusOne, next = tITS.matchID; // ITS matchRecord + int topID = MinusOne, next = tITS.matchID; // ITS MatchRecord while (next > MinusOne) { auto& rcITS = mMatchRecordsITS[next]; if (rcITS.partnerID == tpcID) { diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h index 98a5ba13e19cd..9c7cdd404dbfc 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h @@ -25,7 +25,12 @@ namespace globaltracking // There are configurable params for TPC-ITS matching struct MatchITSTPCParams : public o2::conf::ConfigurableParamHelper<MatchITSTPCParams> { - bool runAfterBurner = false; + enum ValidateMatchByFIT { Disable, + Prefer, + Require }; // flags for usage of FT0 in match validation + + bool runAfterBurner = false; ///< run afterburner for TPCtrack-ITScluster matching + ValidateMatchByFIT validateMatchByFIT = Prefer; ///< when comparing ITS-TPC matches, prefer those which have time of Interaction Candidate float crudeAbsDiffCut[o2::track::kNParams] = {2.f, 2.f, 0.2f, 0.2f, 4.f}; float crudeNSigma2Cut[o2::track::kNParams] = {49.f, 49.f, 49.f, 49.f, 49.f}; @@ -40,13 +45,15 @@ struct MatchITSTPCParams : public o2::conf::ConfigurableParamHelper<MatchITSTPCP int maxMatchCandidates = 5; ///< max allowed matching candidates per TPC track - int ABRequireToReachLayer = 5; ///< AB tracks should reach at least this layer from above + int requireToReachLayerAB = 5; ///< AB tracks should reach at least this layer from above + + float safeMarginTPCITSTimeBin = 1.f; ///< safety margin (in TPC time bins) for ITS-TPC tracks time (in TPC time bins!) comparison - float TPCITSTimeBinSafeMargin = 1.f; ///< safety margin (in TPC time bins) for ITS-TPC tracks time (in TPC time bins!) comparison + float safeMarginTPCTimeEdge = 20.f; ///< safety margin in cm when estimating TPC track tMin and tMax from assigned time0 and its track Z position - float TPCTimeEdgeZSafeMargin = 20.f; ///< safety margin in cm when estimating TPC track tMin and tMax from assigned time0 and its track Z position + float timeBinTolerance = 10.f; ///<tolerance in time-bin for ITS-TPC time bracket matching (not used ? TODO) - float TimeBinTolerance = 10.f; ///<tolerance in time-bin for ITS-TPC time bracket matching (not used ? TODO) + float tpcTimeICMatchingNSigma = 4.; ///< nsigma for matching TPC corrected time and InteractionCandidate from FT0 o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; /// Material correction type diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 593291f0c2436..859d0f0e76b7e 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -104,7 +104,7 @@ void MatchTPCITS::printABTracksTree(const ABTrackLinksList& llist) const }; int cnt = 0; // tmp - for (int lowest = llist.lowestLayer; lowest <= mParams->ABRequireToReachLayer; lowest++) { + for (int lowest = llist.lowestLayer; lowest <= mParams->requireToReachLayerAB; lowest++) { int nextHyp = llist.firstInLr[lowest]; while (nextHyp > MinusOne) { if (mABTrackLinks[nextHyp].nDaughters == 0) { // select only head links, w/o daughters @@ -142,7 +142,7 @@ void MatchTPCITS::dumpABTracksDebugTree(const ABTrackLinksList& llist) lblTrc = mTPCTrkLabels->getLabels(mTPCWork[llist.trackID].sourceID)[0]; // tmp } int ord = 0; - for (int lowest = llist.lowestLayer; lowest <= mParams->ABRequireToReachLayer; lowest++) { + for (int lowest = llist.lowestLayer; lowest <= mParams->requireToReachLayerAB; lowest++) { int nextHyp = llist.firstInLr[lowest]; while (nextHyp > MinusOne) { if (mABTrackLinks[nextHyp].nDaughters != 0) { // select only head links, w/o daughters @@ -247,6 +247,7 @@ void MatchTPCITS::run() if (!mInitDone) { LOG(FATAL) << "init() was not done yet"; } + updateTPCTimeDependentParams(); ProcInfo_t procInfoStart, procInfoStop; gSystem->GetProcInfo(&procInfoStart); @@ -260,6 +261,10 @@ void MatchTPCITS::run() if (!prepareITSTracks() || !prepareTPCTracks() || !prepareFITInfo()) { return; } + if (mUseFT0) { + prepareInteractionTimes(); + } + mTimer[SWDoMatching].Start(false); for (int sec = o2::constants::math::NSectors; sec--;) { doMatching(sec); @@ -276,7 +281,7 @@ void MatchTPCITS::run() refitWinners(); - if (Params::Instance().runAfterBurner) { + if (mUseFT0 && Params::Instance().runAfterBurner) { runAfterBurner(); } @@ -325,6 +330,7 @@ void MatchTPCITS::init() mTimer[i].Reset(); } mParams = &Params::Instance(); + mFT0Params = &o2::ft0::InteractionTag::Instance(); setUseMatCorrFlag(mParams->matCorr); auto* prop = o2::base::Propagator::Instance(); if (!prop->getMatLUT() && mParams->matCorr == o2::base::Propagator::MatCorrType::USEMatCorrLUT) { @@ -336,28 +342,6 @@ void MatchTPCITS::init() o2::its::GeometryTGeo::Instance()->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2GRot)); mSectEdgeMargin2 = mParams->crudeAbsDiffCut[o2::track::kY] * mParams->crudeAbsDiffCut[o2::track::kY]; ///< precalculated ^2 - - auto& gasParam = o2::tpc::ParameterGas::Instance(); - auto& elParam = o2::tpc::ParameterElectronics::Instance(); - auto& detParam = o2::tpc::ParameterDetector::Instance(); - mTPCTBinMUS = elParam.ZbinWidth; - mTPCVDrift0 = gasParam.DriftV; - mTPCZMax = detParam.TPClength; - - assert(mITSROFrameLengthMUS > 0.0f); - if (mITSTriggered) { - mITSROFrame2TPCBin = mITSROFrameLengthMUS / mTPCTBinMUS; - } else { - mITSROFrame2TPCBin = mITSROFrameLengthMUS / mTPCTBinMUS; // RSTODO use both ITS and TPC times BCs once will be available for TPC also - } - mTPCBin2ITSROFrame = 1. / mITSROFrame2TPCBin; - mTPCBin2Z = mTPCTBinMUS * mTPCVDrift0; - mZ2TPCBin = 1. / mTPCBin2Z; - mTPCVDrift0Inv = 1. / mTPCVDrift0; - mNTPCBinsFullDrift = mTPCZMax * mZ2TPCBin; - - mTPCTimeEdgeTSafeMargin = z2TPCBin(mParams->TPCTimeEdgeZSafeMargin); - std::unique_ptr<TPCTransform> fastTransform = (o2::tpc::TPCFastTransformHelperO2::instance()->create(0)); mTPCTransform = std::move(fastTransform); mTPCClusterParam = std::make_unique<o2::gpu::GPUParam>(); @@ -386,6 +370,31 @@ void MatchTPCITS::init() print(); } +//______________________________________________ +void MatchTPCITS::updateTPCTimeDependentParams() +{ + ///< update parameters depending on TPC drift properties + auto& gasParam = o2::tpc::ParameterGas::Instance(); + auto& elParam = o2::tpc::ParameterElectronics::Instance(); + auto& detParam = o2::tpc::ParameterDetector::Instance(); + mTPCTBinMUS = elParam.ZbinWidth; + mTPCVDrift0 = gasParam.DriftV; + mTPCZMax = detParam.TPClength; + mTPCTBinMUSInv = 1. / mTPCTBinMUS; + assert(mITSROFrameLengthMUS > 0.0f); + if (mITSTriggered) { + mITSROFrame2TPCBin = mITSROFrameLengthMUS * mTPCTBinMUSInv; + } else { + mITSROFrame2TPCBin = mITSROFrameLengthMUS * mTPCTBinMUSInv; // RSTODO use both ITS and TPC times BCs once will be available for TPC also + } + mTPCBin2ITSROFrame = 1. / mITSROFrame2TPCBin; + mTPCBin2Z = mTPCTBinMUS * mTPCVDrift0; + mZ2TPCBin = 1. / mTPCBin2Z; + mTPCVDrift0Inv = 1. / mTPCVDrift0; + mNTPCBinsFullDrift = mTPCZMax * mZ2TPCBin; + mTPCTimeEdgeTSafeMargin = z2TPCBin(mParams->safeMarginTPCTimeEdge); +} + //______________________________________________ void MatchTPCITS::selectBestMatches() { @@ -557,7 +566,7 @@ bool MatchTPCITS::prepareTPCTracks() } /// full drift time + safety margin - float maxTDriftSafe = (mNTPCBinsFullDrift + mParams->TPCITSTimeBinSafeMargin + mTPCTimeEdgeTSafeMargin); + float maxTDriftSafe = (mNTPCBinsFullDrift + mParams->safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin); float maxTimeBin = 0; int nITSROFs = mITSROFTimes.size(); @@ -783,26 +792,25 @@ void MatchTPCITS::doMatching(int sec) auto& tbinStartITS = mITSTimeBinStart[sec]; int nTracksTPC = cacheTPC.size(), nTracksITS = cacheITS.size(); if (!nTracksTPC || !nTracksITS) { - LOG(INFO) << "Matchng sector " << sec << " : N tracks TPC:" << nTracksTPC << " ITS:" << nTracksITS << " in sector " - << sec; + LOG(INFO) << "Matchng sector " << sec << " : N tracks TPC:" << nTracksTPC << " ITS:" << nTracksITS << " in sector " << sec; return; } /// full drift time + safety margin - float maxTDriftSafe = (mNTPCBinsFullDrift + mParams->TPCITSTimeBinSafeMargin + mTPCTimeEdgeTSafeMargin); + float maxTDriftSafe = (mNTPCBinsFullDrift + mParams->safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin); // get min ROFrame (in TPC time-bins) of ITS tracks currently in cache auto minROFITS = mITSWork[cacheITS.front()].roFrame; if (minROFITS >= int(tbinStartTPC.size())) { - LOG(INFO) << "ITS min ROFrame " << minROFITS << " exceeds all cached TPC track ROF eqiuvalent " - << cacheTPC.size() - 1; + LOG(INFO) << "ITS min ROFrame " << minROFITS << " exceeds all cached TPC track ROF eqiuvalent " << cacheTPC.size() - 1; return; } int nCheckTPCControl = 0, nCheckITSControl = 0, nMatchesControl = 0; // temporary - int idxMinTPC = tbinStartTPC[minROFITS]; // index of 1st cached TPC track within cached ITS ROFrames + auto t2nbs = mZ2TPCBin * mParams->tpcTimeICMatchingNSigma; + bool checkInteractionCandidates = mUseFT0 && mParams->validateMatchByFIT != MatchITSTPCParams::Disable; for (int itpc = idxMinTPC; itpc < nTracksTPC; itpc++) { auto& trefTPC = mTPCWork[cacheTPC[itpc]]; // estimate ITS 1st ROframe bin this track may match to: TPC track are sorted according to their @@ -857,7 +865,33 @@ void MatchTPCITS::doMatching(int sec) if (rejFlag != Accept) { continue; } - registerMatchRecordTPC(cacheITS[iits], cacheTPC[itpc], chi2); // register matching candidate + 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<float> trange(timeTB - timeTBErr, timeTB + timeTBErr); + int idIC = interactionRefs.getFirstEntry(), maxIC = idIC + nic; + for (; idIC < maxIC; idIC++) { + auto cmp = mInteractions[idIC].timeBins.isOutside(trange); + if (cmp == o2::utils::Bracket<float>::Above) { // trange is above this interaction candidate, the following ones may match + continue; + } + if (cmp == o2::utils::Bracket<float>::Inside) { + matchedIC = idIC; + } + break; // we loop till 1st matching IC or the one above the trange (since IC are ordered, all others will be above too) + } + } + } + if (mParams->validateMatchByFIT == MatchITSTPCParams::Require && matchedIC == MinusOne) { + continue; + } + registerMatchRecordTPC(cacheITS[iits], cacheTPC[itpc], chi2, matchedIC); // register matching candidate nMatchesControl++; } } @@ -889,15 +923,15 @@ void MatchTPCITS::suppressMatchRecordITS(int itsID, int tpcID) } //______________________________________________ -bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2) +bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2, int candIC) { ///< record matching candidate, making sure that number of ITS candidates per TPC track, sorted ///< in matching chi2 does not exceed allowed number - auto& tTPC = mTPCWork[iTPC]; // get matchRecord structure of this TPC track, create if none + auto& tTPC = mTPCWork[iTPC]; // get MatchRecord structure of this TPC track, create if none if (tTPC.matchID < 0) { // no matches yet, just add new record - registerMatchRecordITS(iITS, iTPC, chi2); // register TPC track in the ITS records + registerMatchRecordITS(iITS, iTPC, chi2, candIC); // register TPC track in the ITS records tTPC.matchID = mMatchRecordsTPC.size(); // new record will be added in the end - mMatchRecordsTPC.emplace_back(iITS, chi2); // create new record with empty reference on next match + mMatchRecordsTPC.emplace_back(iITS, chi2, MinusOne, candIC); // create new record with empty reference on next match return true; } @@ -905,14 +939,16 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2) do { auto& nextMatchRec = mMatchRecordsTPC[nextID]; count++; - if (chi2 < nextMatchRec.chi2) { // need to insert new record before nextMatchRec? + if (!nextMatchRec.isBetter(chi2, candIC)) { // need to insert new record before nextMatchRec? if (count < mParams->maxMatchCandidates) { break; // will insert in front of nextID } else { // max number of candidates reached, will overwrite the last one - nextMatchRec.chi2 = chi2; suppressMatchRecordITS(nextMatchRec.partnerID, iTPC); // flag as disabled the overriden ITS match - registerMatchRecordITS(iITS, iTPC, chi2); // register TPC track entry in the ITS records - nextMatchRec.partnerID = iITS; // reuse the record of suppressed ITS match to store better one + registerMatchRecordITS(iITS, iTPC, chi2, candIC); // register TPC track entry in the ITS records + // reuse the record of suppressed ITS match to store better one + nextMatchRec.chi2 = chi2; + nextMatchRec.matchedIC = candIC; + nextMatchRec.partnerID = iITS; return true; } } @@ -930,8 +966,8 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2) topID = mMatchRecordsTPC[topID].nextRecID = mMatchRecordsTPC.size(); // register to his parent } // nextID==-1 will mean that the while loop run over all candidates->the new one is the worst (goes to the end) - registerMatchRecordITS(iITS, iTPC, chi2); // register TPC track in the ITS records - mMatchRecordsTPC.emplace_back(iITS, chi2, nextID); // create new record with empty reference on next match + registerMatchRecordITS(iITS, iTPC, chi2, candIC); // register TPC track in the ITS records + mMatchRecordsTPC.emplace_back(iITS, chi2, nextID, candIC); // create new record with empty reference on next match // make sure that after addition the number of candidates don't exceed allowed number count++; while (nextID > MinusOne) { @@ -952,22 +988,22 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2) } //______________________________________________ -void MatchTPCITS::registerMatchRecordITS(int iITS, int iTPC, float chi2) +void MatchTPCITS::registerMatchRecordITS(int iITS, int iTPC, float chi2, int candIC) { - ///< register TPC match in ITS tracks match records, ordering then in chi2 + ///< register TPC match in ITS tracks match records, ordering them in quality auto& tITS = mITSWork[iITS]; int idnew = mMatchRecordsITS.size(); - auto& newRecord = mMatchRecordsITS.emplace_back(iTPC, chi2); // associate iTPC with this record + auto& newRecord = mMatchRecordsITS.emplace_back(iTPC, chi2, MinusOne, candIC); // associate iTPC with this record if (tITS.matchID < 0) { tITS.matchID = idnew; return; } - // there are other matches for this ITS track, insert the new record preserving chi2 order + // there are other matches for this ITS track, insert the new record preserving quality order // navigate till last record or the one with worse chi2 int topID = MinusOne, nextRecord = tITS.matchID; do { - auto& recITS = mMatchRecordsITS[nextRecord]; - if (chi2 < recITS.chi2) { // insert before this one + auto& nextMatchRec = mMatchRecordsITS[nextRecord]; + if (!nextMatchRec.isBetter(chi2, candIC)) { // need to insert new record before nextMatchRec? newRecord.nextRecID = nextRecord; // new one will refer to old one it overtook if (topID < 0) { tITS.matchID = idnew; // the new one is the best match, track will refer to it @@ -1218,8 +1254,8 @@ void MatchTPCITS::print() const } printf("\n"); - printf("TPC-ITS time(bins) bracketing safety margin: %6.2f\n", mParams->TimeBinTolerance); - printf("TPC Z->time(bins) bracketing safety margin: %6.2f\n", mParams->TPCTimeEdgeZSafeMargin); + printf("TPC-ITS time(bins) bracketing safety margin: %6.2f\n", mParams->timeBinTolerance); + printf("TPC Z->time(bins) bracketing safety margin: %6.2f\n", mParams->safeMarginTPCTimeEdge); #ifdef _ALLOW_DEBUG_TREES_ @@ -1342,14 +1378,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) /// precise time estimate auto tpcTrOrig = mTPCTracksArray[tTPC.sourceID]; - float timeTB = tpcTrOrig.getTime0(); - if (tpcTrOrig.hasASideClustersOnly()) { - timeTB += deltaT; - } else if (tpcTrOrig.hasCSideClustersOnly()) { - timeTB -= deltaT; - } else { - // TODO : special treatment of tracks crossing the CE - } + float timeTB = getTPCTrackCorrectedTimeBin(tpcTrOrig, deltaT); // convert time in timebins to time in microseconds float time = timeTB * mTPCTBinMUS; // estimate the error on time @@ -1763,27 +1792,37 @@ int MatchTPCITS::prepareTPCTracksAfterBurner() int MatchTPCITS::prepareInteractionTimes() { // guess interaction times from various sources and relate with ITS rofs - const float T0UncertaintyTB = 0.5 / (1e3 * mTPCTBinMUS); // assumed T0 time uncertainty (~0.5ns) in TPC timeBins + float ft0UncertaintyTB = 0.5e-3 * mTPCTBinMUSInv; // assumed T0 time uncertainty (~0.5ns) in TPC timeBins mInteractions.clear(); + mITSROFIntCandEntries.clear(); + int nITSROFs = mITSROFTimes.size(); + mITSROFIntCandEntries.resize(nITSROFs); + if (mFITInfo.size()) { + int rof = 0; for (const auto& ft : mFITInfo) { - if (!ft.isValidTime(o2::ft0::RecPoints::TimeMean)) { + if (!mFT0Params->isSelected(ft)) { continue; } - auto fitTime = intRecord2TPCTimeBin(ft.getInteractionRecord()); // FIT time in TPC timebins + auto fitTime = time2TPCTimeBin(mFT0Params->getInteractionTimeNS(ft, mStartIR) * 1e-3); // FIT time in TPC timebins // find corresponding ITS ROF, works both in cont. and trigg. modes (ignore T0 MeanTime within the BC) - int nITSROFs = mITSROFTimes.size(); - for (int rof = 0; rof < nITSROFs; rof++) { + for (; rof < nITSROFs; rof++) { if (mITSROFTimes[rof] < fitTime) { continue; } if (fitTime >= mITSROFTimes[rof].min()) { // belongs to this ROF - mInteractions.emplace_back(ft.getInteractionRecord(), fitTime, T0UncertaintyTB, rof, o2::detectors::DetID::FT0); + auto& ref = mITSROFIntCandEntries[rof]; + if (!ref.getEntries()) { + ref.setFirstEntry(mInteractions.size()); // register entry + } + ref.changeEntriesBy(1); // increment counter + mInteractions.emplace_back(ft.getInteractionRecord(), fitTime, ft0UncertaintyTB, rof, o2::detectors::DetID::FT0); } break; // this or next ITSrof in time is > fitTime } } } + return mInteractions.size(); } @@ -1792,7 +1831,7 @@ void MatchTPCITS::runAfterBurner() { mABTrackLinks.clear(); - int nIntCand = prepareInteractionTimes(); + int nIntCand = mInteractions.size(); int nTPCCand = prepareTPCTracksAfterBurner(); LOG(INFO) << "AfterBurner will check " << nIntCand << " interaction candindates for " << nTPCCand << " TPC tracks"; if (!nIntCand || !nTPCCand) { @@ -1899,7 +1938,7 @@ bool MatchTPCITS::runAfterBurner(int tpcWID, int iCStart, int iCEnd) // printABTracksTree(abTrackLinksList); // tmp tmp } // disable link-list if neiher of seeds reached highest requested layer - if (abTrackLinksList.lowestLayer > mParams->ABRequireToReachLayer) { + if (abTrackLinksList.lowestLayer > mParams->requireToReachLayerAB) { destroyLastABTrackLinksList(); tTPC.matchID = MinusTen; return false; @@ -2153,7 +2192,7 @@ void MatchTPCITS::buildABCluster2TracksLinks() continue; } // register all clusters of all seeds starting from the innermost layer - for (int lr = trList.lowestLayer; lr <= mParams->ABRequireToReachLayer; lr++) { + for (int lr = trList.lowestLayer; lr <= mParams->requireToReachLayerAB; lr++) { int finalTrackLinkIdx = trList.firstInLr[lr]; while (finalTrackLinkIdx > MinusOne) { // loop over all links of this layer auto& finalTrackLink = mABTrackLinks[finalTrackLinkIdx]; @@ -2496,7 +2535,7 @@ void MatchTPCITS::buildBestLinksList(int ilink) trList.bestOrdLinkID = start; // now check if shorter seed links from layers above need to be considered as final track candidates - while (++lowestLayer <= mParams->ABRequireToReachLayer) { + while (++lowestLayer <= mParams->requireToReachLayerAB) { nextID = trList.firstInLr[lowestLayer]; while (nextID > MinusOne) { diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h index 922557c48cfea..4dad9f6506780 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h @@ -20,7 +20,7 @@ namespace o2 namespace globaltracking { -framework::WorkflowSpec getMatchTPCITSWorkflow(bool useMC, bool disableRootInp, bool disableRootOut); +framework::WorkflowSpec getMatchTPCITSWorkflow(bool useFT0, bool useMC, bool disableRootInp, bool disableRootOut); } // namespace globaltracking } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h index a33aa93159abe..dd6c561182bf4 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h @@ -32,8 +32,7 @@ namespace globaltracking class TPCITSMatchingDPL : public Task { public: - TPCITSMatchingDPL(bool useMC) - : mUseMC(useMC) {} + TPCITSMatchingDPL(bool useFT0, bool useMC) : mUseFT0(useFT0), mUseMC(useMC) {} ~TPCITSMatchingDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -42,12 +41,13 @@ class TPCITSMatchingDPL : public Task private: o2::globaltracking::MatchTPCITS mMatching; // matching engine o2::itsmft::TopologyDictionary mITSDict; // cluster patterns dictionary + bool mUseFT0 = false; bool mUseMC = true; TStopwatch mTimer; }; /// create a processor spec -framework::DataProcessorSpec getTPCITSMatchingSpec(bool useMC, const std::vector<int>& tpcClusLanes); +framework::DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool useMC, const std::vector<int>& tpcClusLanes); } // namespace globaltracking } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx b/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx index 15a41178d841e..de2e206045298 100644 --- a/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx @@ -27,7 +27,7 @@ namespace o2 namespace globaltracking { -framework::WorkflowSpec getMatchTPCITSWorkflow(bool useMC, bool disableRootInp, bool disableRootOut) +framework::WorkflowSpec getMatchTPCITSWorkflow(bool useFT0, bool useMC, bool disableRootInp, bool disableRootOut) { framework::WorkflowSpec specs; @@ -53,11 +53,11 @@ framework::WorkflowSpec getMatchTPCITSWorkflow(bool useMC, bool disableRootInp, tpcClusLanes}, useMC)); - if (o2::globaltracking::MatchITSTPCParams::Instance().runAfterBurner) { + if (useFT0) { specs.emplace_back(o2::ft0::getRecPointReaderSpec(useMC)); } } - specs.emplace_back(o2::globaltracking::getTPCITSMatchingSpec(useMC, tpcClusLanes)); + specs.emplace_back(o2::globaltracking::getTPCITSMatchingSpec(useFT0, useMC, tpcClusLanes)); if (!disableRootOut) { specs.emplace_back(o2::globaltracking::getTrackWriterTPCITSSpec(useMC)); diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index 8d97c3294552a..622c1e2ff2d8a 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -62,6 +62,7 @@ void TPCITSMatchingDPL::init(InitContext& ic) mMatching.setITSROFrameLengthInBC(alpParams.roFrameLengthInBC); // ITS ROFrame duration in \mus } mMatching.setMCTruthOn(mUseMC); + mMatching.setUseFT0(mUseFT0); // std::string dictPath = ic.options().get<std::string>("its-dictionary-path"); std::string dictFile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, dictPath, ".bin"); @@ -238,7 +239,7 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) mMatching.setTPCTrkLabelsInp(lblTPCPtr); } - if (o2::globaltracking::MatchITSTPCParams::Instance().runAfterBurner) { + if (mUseFT0) { // Note: the particular variable will go out of scope, but the span is passed by copy to the // worker and the underlying memory is valid throughout the whole computation auto fitInfo = pc.inputs().get<gsl::span<o2::ft0::RecPoints>>("fitInfo"); @@ -269,7 +270,7 @@ void TPCITSMatchingDPL::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTPCITSMatchingSpec(bool useMC, const std::vector<int>& tpcClusLanes) +DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool useMC, const std::vector<int>& tpcClusLanes) { std::vector<InputSpec> inputs; @@ -285,7 +286,7 @@ DataProcessorSpec getTPCITSMatchingSpec(bool useMC, const std::vector<int>& tpcC inputs.emplace_back("clusTPC", ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}, Lifetime::Timeframe); - if (o2::globaltracking::MatchITSTPCParams::Instance().runAfterBurner) { + if (useFT0) { inputs.emplace_back("fitInfo", "FT0", "RECPOINTS", 0, Lifetime::Timeframe); } @@ -304,7 +305,7 @@ DataProcessorSpec getTPCITSMatchingSpec(bool useMC, const std::vector<int>& tpcC "itstpc-track-matcher", inputs, outputs, - AlgorithmSpec{adaptFromTask<TPCITSMatchingDPL>(useMC)}, + AlgorithmSpec{adaptFromTask<TPCITSMatchingDPL>(useFT0, useMC)}, Options{ {"its-dictionary-path", VariantType::String, "", {"Path of the cluster-topology dictionary file"}}, {"material-lut-path", VariantType::String, "", {"Path of the material LUT file"}}}}; diff --git a/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx index 9562be20529df..656ce73af2e84 100644 --- a/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx @@ -22,6 +22,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { // option allowing to set parameters std::vector<o2::framework::ConfigParamSpec> options{ + {"use-ft0", o2::framework::VariantType::Bool, false, {"use FT0 in matching"}}, {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}, {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, @@ -52,8 +53,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // write the configuration used for the workflow o2::conf::ConfigurableParam::writeINI("o2matchtpcits-workflow_configuration.ini"); + auto useFT0 = configcontext.options().get<bool>("use-ft0"); auto useMC = !configcontext.options().get<bool>("disable-mc"); auto disableRootInp = configcontext.options().get<bool>("disable-root-input"); auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); - return std::move(o2::globaltracking::getMatchTPCITSWorkflow(useMC, disableRootInp, disableRootOut)); + return std::move(o2::globaltracking::getMatchTPCITSWorkflow(useFT0, useMC, disableRootInp, disableRootOut)); } From 9f587108fe0e6eaabf8c642cc3ea81443ec7ad28 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <maximiliano.puccio@cern.ch> Date: Fri, 28 Aug 2020 12:08:42 +0200 Subject: [PATCH 0507/1751] [ITSCA] Level 1 marks the end of the road --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index f056ae7c7e1b4..0396101592e46 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -421,8 +421,7 @@ void Tracker::traverseCellsTree(const int currentCellId, const int currentLayerI mPrimaryVertexContext->getRoads().back().addCell(currentLayerId, currentCellId); - if (currentLayerId > 0) { - + if (currentLayerId > 0 && currentCellLevel > 1) { const int cellNeighboursNum{static_cast<int>( mPrimaryVertexContext->getCellsNeighbours()[currentLayerId - 1][currentCellId].size())}; bool isFirstValidNeighbour = true; From bc7faf62ecbe6490631224d592d5a81d3fa87d15 Mon Sep 17 00:00:00 2001 From: Gian Michele Innocenti <gminnocen@gmail.com> Date: Mon, 31 Aug 2020 10:39:56 +0200 Subject: [PATCH 0508/1751] Add pt and eta resolution (#4253) --- Analysis/Tasks/qaTask.cxx | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx index 38634ed8c4492..40c9952f19104 100644 --- a/Analysis/Tasks/qaTask.cxx +++ b/Analysis/Tasks/qaTask.cxx @@ -7,19 +7,24 @@ // 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 Peter Hristov <Peter.Hristov@cern.ch>, CERN +/// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Analysis/MC.h" #include <TH1F.h> +#include <TH2F.h> #include <cmath> using namespace o2; using namespace o2::framework; struct QATrackingKine { - OutputObj<TH1F> hpt{TH1F("pt", ";p_{T} [GeV]", 100, 0., 200.)}; + Configurable<bool> ismc{"ismc", false, "option to flag mc"}; + OutputObj<TH1F> hpt{TH1F("pt", ";p_{T} [GeV]", 100, 0., 10.)}; OutputObj<TH1F> hphi{TH1F("phi", ";#phi", 100, 0, 2 * M_PI)}; OutputObj<TH1F> heta{TH1F("eta", ";#eta", 100, -6, 6)}; @@ -35,9 +40,38 @@ struct QATrackingKine { } }; +struct QATrackingResolution { + OutputObj<TH1F> etaDiff{TH1F("etaDiff", ";eta_{MC} - eta_{Rec}", 100, -2, 2)}; + OutputObj<TH1F> phiDiff{TH1F("phiDiff", ";phi_{MC} - phi_{Rec}", 100, -M_PI, M_PI)}; + OutputObj<TH1F> ptDiff{TH1F("ptDiff", ";p_{T}_{MC} - p_{T}_{Rec}", 400, -2., 2.)}; + OutputObj<TH1F> ptRes{TH1F("ptDRes", ";p_{T}_{MC} - p_{T}_{Rec} / p_{T}_{Rec} ", 400, -2., 2.)}; + OutputObj<TH2F> ptResvspt{TH2F("ptDResvspt", ";p_{T};Res p_{T}", 100, 0., 10., 400, -2., 2.)}; + OutputObj<TH2F> ptResvseta{TH2F("ptDResvseta", ";#eta;Res p_{T}", 400, -4., 4., 400, -2., 2.)}; + + void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const& collision, soa::Join<aod::Tracks, aod::McTrackLabels> const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcCollisions) + { + LOGF(info, "vtx-z (data) = %f | vtx-z (MC) = %f", collision.posZ(), collision.label().posZ()); + for (auto& track : tracks) { + ptDiff->Fill(track.label().pt() - track.pt()); + ptRes->Fill((track.label().pt() - track.pt()) / track.pt()); + ptResvspt->Fill(track.pt(), abs(track.label().pt() - track.pt()) / track.pt()); + ptResvseta->Fill(track.eta(), abs(track.label().pt() - track.pt()) / track.pt()); + etaDiff->Fill(track.label().eta() - track.eta()); + + auto delta = track.label().phi() - track.phi(); + if (delta > M_PI) + delta -= 2 * M_PI; + if (delta < -M_PI) + delta += 2 * M_PI; + phiDiff->Fill(delta); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<QATrackingKine>("qa-tracking-kine"), + adaptAnalysisTask<QATrackingResolution>("qa-tracking-resolution"), }; } From 7e5cbad01855d8c93313f645b472998e57e03951 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 18:40:22 +0200 Subject: [PATCH 0509/1751] Fix ITS ca-tracks cluster index extraction --- Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index d49c94467aee7..4e49022a6050f 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -35,6 +35,7 @@ #include "ITSReconstruction/FastMultEstConfig.h" #include "ITSReconstruction/FastMultEst.h" +#include <fmt/format.h> namespace o2 { @@ -132,10 +133,15 @@ void TrackerDPL::run(ProcessingContext& pc) auto copyTracks = [](auto& tracks, auto& allTracks, auto& allClusIdx, int offset = 0) { for (auto& trc : tracks) { trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices - int ncl = trc.getNumberOfClusters(); - for (int ic = ncl; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! - allClusIdx.push_back(trc.getClusterIndex(ic) + offset); + int ncl = trc.getNumberOfClusters(), nclf = 0; + for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! + auto clid = trc.getClusterIndex(ic); + if (clid >= 0) { + allClusIdx.push_back(clid + offset); + nclf++; + } } + assert(ncl == nclf); allTracks.emplace_back(trc); } }; From 41350e88324d39912ded6098ba7e32f8beaa1557 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 15:45:55 +0200 Subject: [PATCH 0510/1751] Add async. reco mode to ITS workflow with ca-tracker --- .../workflow/include/ITSWorkflow/RecoWorkflow.h | 2 +- .../workflow/include/ITSWorkflow/TrackerSpec.h | 5 +++-- .../ITSMFT/ITS/workflow/src/RecoWorkflow.cxx | 4 ++-- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 17 +++++++++++++---- .../ITS/workflow/src/its-reco-workflow.cxx | 10 +++++++++- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h index 66be2b63d23f3..7ef7ae7ae7ca3 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h @@ -27,7 +27,7 @@ namespace its namespace reco_workflow { -framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU, +framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, bool async, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU, bool upstreamDigits = false, bool upstreamClusters = false, bool disableRootOutput = false, bool eencode = false); } diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h index cf62efe019dd0..374371f344005 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h @@ -38,7 +38,7 @@ namespace its class TrackerDPL : public framework::Task { public: - TrackerDPL(bool isMC, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); // : mIsMC{isMC} {} + TrackerDPL(bool isMC, bool async, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); // : mIsMC{isMC} {} ~TrackerDPL() override = default; void init(framework::InitContext& ic) final; void run(framework::ProcessingContext& pc) final; @@ -46,6 +46,7 @@ class TrackerDPL : public framework::Task private: bool mIsMC = false; + bool mAsyncMode = false; o2::itsmft::TopologyDictionary mDict; std::unique_ptr<o2::gpu::GPUReconstruction> mRecChain = nullptr; std::unique_ptr<parameters::GRPObject> mGRP = nullptr; @@ -56,7 +57,7 @@ class TrackerDPL : public framework::Task /// create a processor spec /// run ITS CA tracker -framework::DataProcessorSpec getTrackerSpec(bool useMC, o2::gpu::GPUDataTypes::DeviceType dType); +framework::DataProcessorSpec getTrackerSpec(bool useMC, bool async, o2::gpu::GPUDataTypes::DeviceType dType); } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx index caecf2ea11bdc..1b8cbaa7525e0 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx @@ -28,7 +28,7 @@ namespace its namespace reco_workflow { -framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, o2::gpu::GPUDataTypes::DeviceType dtype, +framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, bool async, o2::gpu::GPUDataTypes::DeviceType dtype, bool upstreamDigits, bool upstreamClusters, bool disableRootOutput, bool eencode) { @@ -45,7 +45,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, o2::gpu::GPUD specs.emplace_back(o2::its::getClusterWriterSpec(useMC)); } if (useCAtracker) { - specs.emplace_back(o2::its::getTrackerSpec(useMC, dtype)); + specs.emplace_back(o2::its::getTrackerSpec(useMC, async, dtype)); } else { specs.emplace_back(o2::its::getCookedTrackerSpec(useMC)); } diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 4e49022a6050f..05f7042f8a052 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -44,8 +44,7 @@ namespace its { using Vertex = o2::dataformats::Vertex<o2::dataformats::TimeStamp<int>>; -TrackerDPL::TrackerDPL(bool isMC, o2::gpu::GPUDataTypes::DeviceType dType) : mIsMC{isMC}, - mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)} +TrackerDPL::TrackerDPL(bool isMC, bool async, o2::gpu::GPUDataTypes::DeviceType dType) : mIsMC{isMC}, mAsyncMode{async}, mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)} { } @@ -69,6 +68,16 @@ void TrackerDPL::init(InitContext& ic) mRecChain->Init(); mVertexer = std::make_unique<Vertexer>(chainITS->GetITSVertexerTraits()); mTracker = std::make_unique<Tracker>(chainITS->GetITSTrackerTraits()); + if (mAsyncMode) { + std::vector<TrackingParameters> trackParams(3); + trackParams[0].TrackletMaxDeltaPhi = 0.05f; + trackParams[1].TrackletMaxDeltaPhi = 0.1f; + trackParams[2].MinTrackLength = 4; + trackParams[2].TrackletMaxDeltaPhi = 0.3; + std::vector<MemoryParameters> memParams(3); + mTracker->setParameters(memParams, trackParams); + LOG(INFO) << "Initializing tracker in async. phase reconstruction with " << trackParams.size() << " passes"; + } mVertexer->getGlobalConfiguration(); // mVertexer->dumpTraits(); double origD[3] = {0., 0., 0.}; @@ -237,7 +246,7 @@ void TrackerDPL::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTrackerSpec(bool useMC, o2::gpu::GPUDataTypes::DeviceType dType) +DataProcessorSpec getTrackerSpec(bool useMC, bool async, o2::gpu::GPUDataTypes::DeviceType dType) { std::vector<InputSpec> inputs; inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe); @@ -263,7 +272,7 @@ DataProcessorSpec getTrackerSpec(bool useMC, o2::gpu::GPUDataTypes::DeviceType d "its-tracker", inputs, outputs, - AlgorithmSpec{adaptFromTask<TrackerDPL>(useMC, dType)}, + AlgorithmSpec{adaptFromTask<TrackerDPL>(useMC, async, dType)}, Options{ {"grp-file", VariantType::String, "o2sim_grp.root", {"Name of the grp file"}}, {"its-dictionary-path", VariantType::String, "", {"Path of the cluster-topology dictionary file"}}}}; diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx index ff864e259cec4..6ca83b2160247 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx @@ -31,6 +31,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) {"disable-root-output", o2::framework::VariantType::Bool, false, {"do not write output root files"}}, {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}, {"trackerCA", o2::framework::VariantType::Bool, false, {"use trackerCA (default: trackerCM)"}}, + {"async-phase", o2::framework::VariantType::Bool, false, {"perform multiple passes for async. phase reconstruction"}}, {"entropy-encoding", o2::framework::VariantType::Bool, false, {"produce entropy encoded data"}}, {"gpuDevice", o2::framework::VariantType::Int, 1, {"use gpu device: CPU=1,CUDA=2,HIP=3 (default: CPU)"}}}; @@ -43,6 +44,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) // ------------------------------------------------------------------ #include "Framework/runDataProcessing.h" +#include "Framework/Logger.h" WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { @@ -53,10 +55,16 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto useMC = !configcontext.options().get<bool>("disable-mc"); auto useCAtracker = configcontext.options().get<bool>("trackerCA"); + auto async = configcontext.options().get<bool>("async-phase"); auto gpuDevice = static_cast<o2::gpu::GPUDataTypes::DeviceType>(configcontext.options().get<int>("gpuDevice")); auto extDigits = configcontext.options().get<bool>("digits-from-upstream"); auto extClusters = configcontext.options().get<bool>("clusters-from-upstream"); auto disableRootOutput = configcontext.options().get<bool>("disable-root-output"); auto eencode = configcontext.options().get<bool>("entropy-encoding"); - return std::move(o2::its::reco_workflow::getWorkflow(useMC, useCAtracker, gpuDevice, extDigits, extClusters, disableRootOutput, eencode)); + + if (async && !useCAtracker) { + LOG(ERROR) << "Async.mode is not supported by CookedTracker, use --trackerCA"; + throw std::runtime_error("incompatible options provided"); + } + return std::move(o2::its::reco_workflow::getWorkflow(useMC, useCAtracker, async, gpuDevice, extDigits, extClusters, disableRootOutput, eencode)); } From 096ec0e9fdc330b6c1fbc806394d3bdb1e55e083 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 19:51:59 +0200 Subject: [PATCH 0511/1751] remove mass and ROFRame, add PID and layers pattern in ITStracks --- .../ITS/include/DataFormatsITS/TrackITS.h | 25 +++++++++++-------- .../include/ITSReconstruction/CookedTracker.h | 1 + Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 1 - .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 3 +++ GPU/GPUTracking/Global/GPUChainITS.cxx | 1 - 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index 03f2d16a1ff81..e39917d94afe2 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -42,8 +42,8 @@ class TrackITS : public o2::track::TrackParCov TrackITS() = default; TrackITS(const TrackITS& t) = default; TrackITS(const o2::track::TrackParCov& parcov) : TrackParCov{parcov} {} - TrackITS(const o2::track::TrackParCov& parCov, float chi2, std::uint32_t rof, const o2::track::TrackParCov& outer) - : o2::track::TrackParCov{parCov}, mChi2{chi2}, mROFrame{rof}, mParamOut{outer} {} + TrackITS(const o2::track::TrackParCov& parCov, float chi2, const o2::track::TrackParCov& outer) + : o2::track::TrackParCov{parCov}, mChi2{chi2}, mParamOut{outer} {} TrackITS& operator=(const TrackITS& tr) = default; ~TrackITS() = default; @@ -82,21 +82,26 @@ class TrackITS : public o2::track::TrackParCov void setChi2(float chi2) { mChi2 = chi2; } - std::uint32_t getROFrame() const { return mROFrame; } - void setROFrame(std::uint32_t f) { mROFrame = f; } bool isBetter(const TrackITS& best, float maxChi2) const; o2::track::TrackParCov& getParamOut() { return mParamOut; } const o2::track::TrackParCov& getParamOut() const { return mParamOut; } + void setPID(uint8_t p) { mPID = p; } + int getPID() const { return mPID; } + + void setPattern(uint8_t p) { mPattern = p; } + int getPattern() const { return mPattern; } + bool hasHitOnLayer(int i) { return mPattern & (0x1 << i); } + private: - float mMass = 0.139; ///< Assumed mass for this track - float mChi2 = 0.; ///< Chi2 for this track - std::uint32_t mROFrame = 0; ///< RO Frame o2::track::TrackParCov mParamOut; ///< parameter at largest radius ClusRefs mClusRef; ///< references on clusters + float mChi2 = 0.; ///< Chi2 for this track + uint8_t mPID = 0; ///< pid info (at the moment not used) + uint8_t mPattern = 0; ///< layers pattern - ClassDefNV(TrackITS, 3); + ClassDefNV(TrackITS, 4); }; class TrackITSExt : public TrackITS @@ -106,9 +111,9 @@ class TrackITSExt : public TrackITS static constexpr int MaxClusters = 7; using TrackITS::TrackITS; // inherit base constructors - TrackITSExt(o2::track::TrackParCov&& parCov, short ncl, float chi2, std::uint32_t rof, + TrackITSExt(o2::track::TrackParCov&& parCov, short ncl, float chi2, o2::track::TrackParCov&& outer, std::array<int, MaxClusters> cls) - : TrackITS(parCov, chi2, rof, outer), mIndex{cls} + : TrackITS(parCov, chi2, outer), mIndex{cls} { setNumberOfClusters(ncl); } diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h index 9db42bd271b5f..f65ca90f0023a 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h @@ -91,6 +91,7 @@ class CookedTracker clusIdx.emplace_back(idx); } trackNew.setClusterRefs(clEntry, noc); + trackNew.setPattern(0x7f); // this tracker finds only complete tracks return tracks.size(); }; process(clusters, it, dict, inserter, rof); diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 0396101592e46..416e997e42355 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -285,7 +285,6 @@ void Tracker::findTracks(const ROframe& event) if (!fitSuccess) continue; CA_DEBUGGER(refitCounters[nClusters - 4]++); - temporaryTrack.setROFrame(mROFrame); tracks.emplace_back(temporaryTrack); CA_DEBUGGER(assert(nClusters == temporaryTrack.getNumberOfClusters())); } diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 05f7042f8a052..451ba01706f20 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -143,14 +143,17 @@ void TrackerDPL::run(ProcessingContext& pc) for (auto& trc : tracks) { trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices int ncl = trc.getNumberOfClusters(), nclf = 0; + uint8_t patt = 0; for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! auto clid = trc.getClusterIndex(ic); if (clid >= 0) { allClusIdx.push_back(clid + offset); nclf++; + patt |= 0x1 << ic; } } assert(ncl == nclf); + trc.setPattern(patt); allTracks.emplace_back(trc); } }; diff --git a/GPU/GPUTracking/Global/GPUChainITS.cxx b/GPU/GPUTracking/Global/GPUChainITS.cxx index 90bca4dbd39d7..c828884b69328 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.cxx +++ b/GPU/GPUTracking/Global/GPUChainITS.cxx @@ -113,7 +113,6 @@ int GPUChainITS::RunITSTrackFit(std::vector<Road>& roads, std::array<const Clust {trkin.Cov()[0], trkin.Cov()[1], trkin.Cov()[2], trkin.Cov()[3], trkin.Cov()[4], trkin.Cov()[5], trkin.Cov()[6], trkin.Cov()[7], trkin.Cov()[8], trkin.Cov()[9], trkin.Cov()[10], trkin.Cov()[11], trkin.Cov()[12], trkin.Cov()[13], trkin.Cov()[14]}}, (short int)((trkin.NDF() + 5) / 2), trkin.Chi2(), - 0, {trkin.mOuterParam.X, trkin.mOuterParam.alpha, {trkin.mOuterParam.P[0], trkin.mOuterParam.P[1], trkin.mOuterParam.P[2], trkin.mOuterParam.P[3], trkin.mOuterParam.P[4]}, From 7bedc0bed617d911ac26448681c2d4548acb9029 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 19:52:34 +0200 Subject: [PATCH 0512/1751] Suppress duplicate pragma entries in GlobalTrackingLinkDef --- Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h b/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h index 3463aa2d88977..ee2df157f55dd 100644 --- a/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h +++ b/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h @@ -26,9 +26,5 @@ #pragma link C++ class std::pair < o2::dataformats::EvIndex < int, int>, o2::dataformats::MatchInfoTOF> + ; #pragma link C++ class std::vector < std::pair < o2::dataformats::EvIndex < int, int>, o2::dataformats::MatchInfoTOF>> + ; -#pragma link C++ class std::vector < o2::dataformats::TrackTPCITS> + ; -#pragma link C++ class std::vector < o2::tpc::TrackTPC> + ; -#pragma link C++ class std::vector < o2::its::TrackITS> + ; -#pragma link C++ class std::vector < o2::tof::Cluster> + ; #endif From 68993641fdc5548d29d50b40c74138a594b4b859 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 26 Aug 2020 12:29:18 +0200 Subject: [PATCH 0513/1751] DPL: fix data race in DataProcessingStats Thread sanitizer spotted a benign data race in the DataProcessingStats. Since the resize only happen in the beginning and since the data hold by the DataProcessingStats is only to be displayed in the GUI, it probably did not have any implications beyond some misreported "green square" in the GUI. --- .../include/Framework/DataProcessingStats.h | 20 +++++++++--------- Framework/Core/src/CommonServices.cxx | 7 ++++--- Framework/Core/src/DataProcessingDevice.cxx | 21 +++++++++++++++---- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingStats.h b/Framework/Core/include/Framework/DataProcessingStats.h index 4ac9f70652c8d..b4d9fb5c26210 100644 --- a/Framework/Core/include/Framework/DataProcessingStats.h +++ b/Framework/Core/include/Framework/DataProcessingStats.h @@ -7,19 +7,18 @@ // 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_DataProcessingStats_H_INCLUDED -#define o2_framework_DataProcessingStats_H_INCLUDED +#ifndef O2_FRAMEWORK_DATAPROCESSINGSTATS_H_ +#define O2_FRAMEWORK_DATAPROCESSINGSTATS_H_ #include <cstdint> -namespace o2 +namespace o2::framework { -namespace framework -{ - /// Helper struct to hold statistics about the data processing happening. struct DataProcessingStats { constexpr static ServiceKind service_kind = ServiceKind::Global; + // If we have more than this, we probably have other issues in any case + constexpr static int MAX_RELAYER_STATES = 4096; // We use this to keep track of the latency of the first message we get for a given input record // and of the last one. struct InputLatency { @@ -36,10 +35,11 @@ struct DataProcessingStats { std::atomic<uint64_t> lastMetricFlushedTimestamp = 0; /// The timestamp of the last time we actually flushed metrics std::atomic<uint64_t> beginIterationTimestamp = 0; /// The timestamp of when the current ConditionalRun was started InputLatency lastLatency = {0, 0}; - std::vector<int> relayerState; + + std::atomic<int> relayerState[MAX_RELAYER_STATES]; + std::atomic<size_t> statesSize; }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif // o2_framework_DataProcessingStats_H_INCLUDED +#endif // O2_FRAMEWORK_DATAPROCESSINGSTATS_H_ diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 8ef19771c09d5..741f0874036d3 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -439,9 +439,10 @@ auto flushMetrics(ServiceRegistry& registry, DataProcessingStats& stats) -> void // Send all the relevant metrics for the relayer to update the GUI // FIXME: do a delta with the previous version if too many metrics are still // sent... - for (size_t si = 0; si < stats.relayerState.size(); ++si) { - auto state = stats.relayerState[si]; - monitoring.send({state, "data_relayer/" + std::to_string(si)}); + for (size_t si = 0; si < stats.statesSize.load(); ++si) { + auto value = std::atomic_load_explicit(&stats.relayerState[si], std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); + monitoring.send({value, fmt::format("data_relayer/{}", si)}); } relayer.sendContextState(); monitoring.flushBuffer(); diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 0a1ad1b66d0a6..e555786bee572 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -701,6 +701,15 @@ auto calculateTotalInputRecordSize(InputRecord const& record) -> int } return totalInputSize; }; + +template <typename T> +void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept +{ + T prev_value = maximum_value; + while (prev_value < value && + !maximum_value.compare_exchange_weak(prev_value, value)) { + } +} } // namespace bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, std::vector<DataRelayer::RecordAction>& completed) @@ -902,11 +911,13 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, } auto postUpdateStats = [& stats = context.registry->get<DataProcessingStats>()](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { + std::atomic_thread_fence(std::memory_order_release); for (size_t ai = 0; ai != record.size(); ai++) { auto cacheId = action.slot.index * record.size() + ai; auto state = record.isValid(ai) ? 3 : 0; - stats.relayerState.resize(std::max(cacheId + 1, stats.relayerState.size()), 0); - stats.relayerState[cacheId] = state; + update_maximum(stats.statesSize, cacheId + 1); + assert(cacheId < DataProcessingStats::MAX_RELAYER_STATES); + stats.relayerState[cacheId].store(state); } uint64_t tEnd = uv_hrtime(); stats.lastElapsedTimeMs = tEnd - tStart; @@ -915,11 +926,13 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, }; auto preUpdateStats = [& stats = context.registry->get<DataProcessingStats>()](DataRelayer::RecordAction const& action, InputRecord const& record, uint64_t tStart) { + std::atomic_thread_fence(std::memory_order_release); for (size_t ai = 0; ai != record.size(); ai++) { auto cacheId = action.slot.index * record.size() + ai; auto state = record.isValid(ai) ? 2 : 0; - stats.relayerState.resize(std::max(cacheId + 1, stats.relayerState.size()), 0); - stats.relayerState[cacheId] = state; + update_maximum(stats.statesSize, cacheId + 1); + assert(cacheId < DataProcessingStats::MAX_RELAYER_STATES); + stats.relayerState[cacheId].store(state); } }; From 0a5c8490bbf279375dab33beda653c1f1b34537f Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <mpuccio@users.noreply.github.com> Date: Mon, 31 Aug 2020 13:29:12 +0200 Subject: [PATCH 0514/1751] Fix faulty assert @davidrohr --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 416e997e42355..725593791dfbe 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -39,7 +39,7 @@ Tracker::Tracker(o2::its::TrackerTraits* traits) /// Initialise standard configuration with 1 iteration mTrkParams.resize(1); mMemParams.resize(1); - assert(mTraits != nullptr); + assert(traits != nullptr); mTraits = traits; mPrimaryVertexContext = mTraits->getPrimaryVertexContext(); } From 3131e8329f9ad2a7d3c11c9ab4acea3eb273683c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 16:13:17 +0200 Subject: [PATCH 0515/1751] Use vector as ITS tracks MCLabels instead of MCTruthContainer --- .../include/ITSReconstruction/CookedTracker.h | 5 ++--- .../ITSMFT/ITS/reconstruction/src/CookedTracker.cxx | 2 +- .../ITS/tracking/include/ITStracking/Tracker.h | 9 ++------- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 2 +- .../workflow/include/ITSWorkflow/TrackReaderSpec.h | 2 +- .../ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx | 2 +- .../ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx | 2 +- Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 12 ++++++------ 8 files changed, 15 insertions(+), 21 deletions(-) diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h index f65ca90f0023a..c998efa35a048 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h @@ -100,8 +100,7 @@ class CookedTracker const Cluster* getCluster(Int_t index) const; void setGeometry(o2::its::GeometryTGeo* geom); - void setMCTruthContainers(const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clsLabels, - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* trkLabels) + void setMCTruthContainers(const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clsLabels, std::vector<o2::MCCompLabel>* trkLabels) { mClsLabels = clsLabels; mTrkLabels = trkLabels; @@ -136,7 +135,7 @@ class CookedTracker bool mContinuousMode = true; ///< triggered or cont. mode const o2::its::GeometryTGeo* mGeom = nullptr; /// interface to geometry const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mClsLabels = nullptr; /// Cluster MC labels - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mTrkLabels = nullptr; /// Track MC labels + std::vector<o2::MCCompLabel>* mTrkLabels = nullptr; /// Track MC labels std::uint32_t mFirstInFrame = 0; ///< Index of the 1st cluster of a frame (within the loaded vector of clusters) Int_t mNumOfThreads; ///< Number of tracking threads diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx index 009e5c9ec5c6d..e80b502cdee47 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx @@ -571,7 +571,7 @@ std::tuple<int, int> CookedTracker::processLoadedClusters(TrackInserter& inserte } // the inserter returns the size of the track vector, the index of the last // inserted track is thus n - 1 - mTrkLabels->addElement(nAllTracks - 1, label); + mTrkLabels->emplace_back(label); } } } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index ebf45963c3eef..920ac2f2ae949 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -62,7 +62,7 @@ class Tracker float getBz() const; std::vector<TrackITSExt>& getTracks(); - dataformats::MCTruthContainer<MCCompLabel>& getTrackLabels(); + auto& getTrackLabels() { return mTrackLabels; } void clustersToTracks(const ROframe&, std::ostream& = std::cout); @@ -99,7 +99,7 @@ class Tracker float mBz = 5.f; std::uint32_t mROFrame = 0; std::vector<TrackITSExt> mTracks; - dataformats::MCTruthContainer<MCCompLabel> mTrackLabels; + std::vector<MCCompLabel> mTrackLabels; o2::gpu::GPUChainITS* mRecoChain = nullptr; }; @@ -130,11 +130,6 @@ inline std::vector<TrackITSExt>& Tracker::getTracks() return mTracks; } -inline dataformats::MCTruthContainer<MCCompLabel>& Tracker::getTrackLabels() -{ - return mTrackLabels; -} - template <typename... T> float Tracker::evaluateTask(void (Tracker::*task)(T...), const char* taskName, std::ostream& ostream, T&&... args) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 725593791dfbe..e58317517a189 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -566,7 +566,7 @@ void Tracker::computeTracksMClabels(const ROframe& event) if (isFakeTrack) { maxOccurrencesValue.setFakeFlag(); } - mTrackLabels.addElement(mTrackLabels.getIndexedSize(), maxOccurrencesValue); + mTrackLabels.emplace_back(maxOccurrencesValue); } } diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h index 1e3c1cbe8a192..066b679c1c026 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h @@ -48,7 +48,7 @@ class TrackReader : public o2::framework::Task std::vector<o2::its::TrackITS> mTracks, *mTracksInp = &mTracks; std::vector<Vertex> mVertices, *mVerticesInp = &mVertices; std::vector<int> mClusInd, *mClusIndInp = &mClusInd; - o2::dataformats::MCTruthContainer<o2::MCCompLabel> mMCTruth, *mMCTruthInp = &mMCTruth; + std::vector<o2::MCCompLabel> mMCTruth, *mMCTruthInp = &mMCTruth; o2::header::DataOrigin mOrigin = o2::header::gDataOriginITS; diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index e601c49953408..3ae9eb90fecfd 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -112,7 +112,7 @@ void CookedTrackerDPL::run(ProcessingContext& pc) LOG(INFO) << "ITSCookedTracker pulled " << compClusters.size() << " clusters, in " << rofs.size() << " RO frames"; - o2::dataformats::MCTruthContainer<o2::MCCompLabel> trackLabels; + std::vector<o2::MCCompLabel> trackLabels; if (mUseMC) { mTracker.setMCTruthContainers(labels.get(), &trackLabels); } diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx index 1e2fc141fb06b..f67dce3a96f79 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx @@ -30,7 +30,7 @@ using Vertex = o2::dataformats::Vertex<o2::dataformats::TimeStamp<int>>; template <typename T> using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; -using LabelsType = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; +using LabelsType = std::vector<o2::MCCompLabel>; using ROFRecLblT = std::vector<o2::itsmft::MC2ROFRecord>; using namespace o2::header; diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 451ba01706f20..83047fed62448 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -122,9 +122,9 @@ void TrackerDPL::run(ProcessingContext& pc) std::vector<o2::its::TrackITSExt> tracks; auto& allClusIdx = pc.outputs().make<std::vector<int>>(Output{"ITS", "TRACKCLSID", 0, Lifetime::Timeframe}); - o2::dataformats::MCTruthContainer<o2::MCCompLabel> trackLabels; + std::vector<o2::MCCompLabel> trackLabels; auto& allTracks = pc.outputs().make<std::vector<o2::its::TrackITS>>(Output{"ITS", "TRACKS", 0, Lifetime::Timeframe}); - o2::dataformats::MCTruthContainer<o2::MCCompLabel> allTrackLabels; + std::vector<o2::MCCompLabel> allTrackLabels; auto& vertROFvec = pc.outputs().make<std::vector<o2::itsmft::ROFRecord>>(Output{"ITS", "VERTICESROF", 0, Lifetime::Timeframe}); auto& vertices = pc.outputs().make<std::vector<Vertex>>(Output{"ITS", "VERTICES", 0, Lifetime::Timeframe}); @@ -211,13 +211,13 @@ void TrackerDPL::run(ProcessingContext& pc) tracks.swap(mTracker->getTracks()); LOG(INFO) << "Found tracks: " << tracks.size(); int number = tracks.size(); - trackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. + trackLabels.swap(mTracker->getTrackLabels()); /// FIXME: assignment ctor is not optimal. int shiftIdx = -rof.getFirstEntry(); // cluster entry!!! rof.setFirstEntry(first); rof.setNEntries(number); copyTracks(tracks, allTracks, allClusIdx, shiftIdx); - allTrackLabels.mergeAtBack(trackLabels); - + std::copy(trackLabels.begin(), trackLabels.end(), std::back_inserter(allTrackLabels)); + trackLabels.clear(); vtxROF.setNEntries(vtxVecLoc.size()); for (const auto& vtx : vtxVecLoc) { vertices.push_back(vtx); @@ -232,7 +232,7 @@ void TrackerDPL::run(ProcessingContext& pc) mTracker->clustersToTracks(event); tracks.swap(mTracker->getTracks()); copyTracks(tracks, allTracks, allClusIdx); - allTrackLabels = mTracker->getTrackLabels(); /// FIXME: assignment ctor is not optimal. + allTrackLabels.swap(mTracker->getTrackLabels()); /// FIXME: assignment ctor is not optimal. } LOG(INFO) << "ITSTracker pushed " << allTracks.size() << " tracks"; From 6c7865c8bb4b4d299a394b15d4380dff74fdb820 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 16:35:32 +0200 Subject: [PATCH 0516/1751] Use vector as TPC tracks MCLabels instead of MCTruthContainer --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 6 +++--- .../TPC/workflow/include/TPCWorkflow/TrackReaderSpec.h | 2 +- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 4 ++-- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 2 +- Detectors/TPC/workflow/src/TrackReaderSpec.cxx | 4 ++-- GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 9ac6ac3cf7c57..d5c3ea09f2deb 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -72,7 +72,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* std::vector<TrackTPC>* outputTracks = data->outputTracks; std::vector<uint32_t>* outClusRefs = data->outputClusRefs; - MCLabelContainer* outputTracksMCTruth = data->outputTracksMCTruth; + std::vector<o2::MCCompLabel>* outputTracksMCTruth = data->outputTracksMCTruth; if (!outputTracks || !outClusRefs) { LOG(ERROR) << "Output tracks or clusRefs vectors are not initialized"; @@ -288,7 +288,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* } if (outputTracksMCTruth) { if (labels.size() == 0) { - outputTracksMCTruth->addElement(iTmp, MCCompLabel()); //default constructor creates NotSet label + outputTracksMCTruth->emplace_back(); //default constructor creates NotSet label } else { int bestLabelNum = 0, bestLabelCount = 0; for (int j = 0; j < labels.size(); j++) { @@ -301,7 +301,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* if (bestLabelCount < (1.f - sTrackMCMaxFake) * nOutCl) { bestLabel.setFakeFlag(); } - outputTracksMCTruth->addElement(iTmp, bestLabel); + outputTracksMCTruth->emplace_back(bestLabel); } } } diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TrackReaderSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TrackReaderSpec.h index 61a75e795a064..f9899344a4213 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TrackReaderSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TrackReaderSpec.h @@ -45,7 +45,7 @@ class TrackReader : public Task std::vector<o2::tpc::TrackTPC>*mTracksInp = nullptr, mTracksOut; std::vector<o2::tpc::TPCClRefElem>*mCluRefVecInp = nullptr, mCluRefVecOut; - o2::dataformats::MCTruthContainer<o2::MCCompLabel>*mMCTruthInp = nullptr, mMCTruthOut; + std::vector<o2::MCCompLabel>*mMCTruthInp = nullptr, mMCTruthOut; std::unique_ptr<TFile> mFile; std::unique_ptr<TTree> mTree; diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index d745e2895693b..a56aa3246254a 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -539,7 +539,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int std::vector<TrackTPC> tracks; std::vector<uint32_t> clusRefs; - MCLabelContainer tracksMCTruth; + std::vector<o2::MCCompLabel> tracksMCTruth; GPUO2InterfaceIOPtrs ptrs; ClusterNativeAccess clusterIndex; std::unique_ptr<ClusterNative[]> clusterBuffer; @@ -637,7 +637,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int pc.outputs().snapshot(OutputRef{"outTracks"}, tracks); pc.outputs().snapshot(OutputRef{"outClusRefs"}, clusRefs); if (specconfig.processMC) { - LOG(INFO) << "sending " << tracksMCTruth.getIndexedSize() << " track label(s)"; + LOG(INFO) << "sending " << tracksMCTruth.size() << " track label(s)"; pc.outputs().snapshot(OutputRef{"mclblout"}, tracksMCTruth); } } diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index c8b05b5aacb7b..0d6d5c7eda855 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -444,7 +444,7 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec using ClusRefsOutputType = std::vector<o2::tpc::TPCClRefElem>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabelContainer = std::vector<o2::MCCompLabel>; // a spectator callback which will be invoked by the tree writer with the extracted object // we are using it for printing a log message auto logger = BranchDefinition<TrackOutputType>::Spectator([](TrackOutputType const& tracks) { diff --git a/Detectors/TPC/workflow/src/TrackReaderSpec.cxx b/Detectors/TPC/workflow/src/TrackReaderSpec.cxx index 69069c3078221..7f1c12b54c8ff 100644 --- a/Detectors/TPC/workflow/src/TrackReaderSpec.cxx +++ b/Detectors/TPC/workflow/src/TrackReaderSpec.cxx @@ -60,7 +60,7 @@ void TrackReader::accumulate(int from, int n) mTracksOut.swap(*mTracksInp); mCluRefVecOut.swap(*mCluRefVecInp); if (mUseMC) { - mMCTruthOut.mergeAtBack(*mMCTruthInp); + std::copy(mMCTruthInp->begin(), mMCTruthInp->end(), std::back_inserter(mMCTruthOut)); } } else { for (int iev = 0; iev < n; iev++) { @@ -83,7 +83,7 @@ void TrackReader::accumulate(int from, int n) std::copy(tr0, tr1, std::back_inserter(mTracksOut)); // MC if (mUseMC) { - mMCTruthOut.mergeAtBack(*mMCTruthInp); + std::copy(mMCTruthInp->begin(), mMCTruthInp->end(), std::back_inserter(mMCTruthOut)); } } } diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index 81673bcd9a6be..b7dda0118f17f 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -114,7 +114,7 @@ struct GPUO2InterfaceIOPtrs { // Input / Output for Merged TPC tracks, two ptrs, for the tracks themselves, and for the MC labels. std::vector<o2::tpc::TrackTPC>* outputTracks = nullptr; std::vector<uint32_t>* outputClusRefs = nullptr; - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* outputTracksMCTruth = nullptr; + std::vector<o2::MCCompLabel>* outputTracksMCTruth = nullptr; // Output for entropy-reduced clusters of TPC compression const o2::tpc::CompressedClustersFlat* compressedClusters = nullptr; From 6b4159b092728e7e7d303053ac36f2b71d76d1e8 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 17:33:19 +0200 Subject: [PATCH 0517/1751] Move ITS/TPC matching from MCTruthContainer to vector for track labels --- .../include/GlobalTracking/MatchTPCITS.h | 31 ++++++++++--------- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 27 +++++++++------- .../src/TPCITSMatchingSpec.cxx | 25 ++++++--------- 3 files changed, 41 insertions(+), 42 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 2e69179244f2e..4a75d53c2e943 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -269,7 +269,9 @@ class MatchTPCITS { using ITSCluster = o2::BaseCluster<float>; using ClusRange = o2::dataformats::RangeReference<int, int>; - using MCLabCont = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabContCl = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabContTr = std::vector<o2::MCCompLabel>; + using MCLabSpan = gsl::span<const o2::MCCompLabel>; using TPCTransform = o2::gpu::TPCFastTransform; using BracketF = o2::utils::Bracket<float>; using Params = o2::globaltracking::MatchITSTPCParams; @@ -392,19 +394,19 @@ class MatchTPCITS } ///< set input ITS track MC labels - void setITSTrkLabelsInp(const MCLabCont* lbl) + void setITSTrkLabelsInp(const MCLabSpan& lbl) { mITSTrkLabels = lbl; } ///< set input ITS clusters MC labels - void setITSClsLabelsInp(const MCLabCont* lbl) + void setITSClsLabelsInp(const MCLabContCl* lbl) { mITSClsLabels = lbl; } ///< set input TPC track MC labels - void setTPCTrkLabelsInp(const MCLabCont* lbl) + void setTPCTrkLabelsInp(const MCLabSpan& lbl) { mTPCTrkLabels = lbl; } @@ -423,8 +425,8 @@ class MatchTPCITS void printCandidatesITS() const; std::vector<o2::dataformats::TrackTPCITS>& getMatchedTracks() { return mMatchedTracks; } - std::vector<o2::MCCompLabel>& getMatchedITSLabels() { return mOutITSLabels; } - std::vector<o2::MCCompLabel>& getMatchedTPCLabels() { return mOutTPCLabels; } + MCLabContTr& getMatchedITSLabels() { return mOutITSLabels; } + MCLabContTr& getMatchedTPCLabels() { return mOutTPCLabels; } //>>> ====================== options =============================>>> void setUseMatCorrFlag(MatCorrType f) { mUseMatCorrFlag = f; } @@ -477,8 +479,7 @@ class MatchTPCITS bool prepareFITInfo(); int preselectChipClusters(std::vector<int>& clVecOut, const ClusRange& clRange, const ITSChipClustersRefs& clRefs, - float trackY, float trackZ, float tolerY, float tolerZ, - const o2::MCCompLabel& lblTrc) const; + float trackY, float trackZ, float tolerY, float tolerZ, const o2::MCCompLabel& lblTrc) const; void fillClustersForAfterBurner(ITSChipClustersRefs& refCont, int rofStart, int nROFs = 1); void cleanAfterBurnerClusRefCache(int currentIC, int& startIC); void flagUsedITSClusters(const o2::its::TrackITS& track, int rofOffset); @@ -625,9 +626,9 @@ class MatchTPCITS const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices - const MCLabCont* mITSTrkLabels = nullptr; ///< input ITS Track MC labels - const MCLabCont* mITSClsLabels = nullptr; ///< input ITS Cluster MC labels - const MCLabCont* mTPCTrkLabels = nullptr; ///< input TPC Track MC labels + const MCLabContCl* mITSClsLabels = nullptr; ///< input ITS Cluster MC labels + MCLabSpan mITSTrkLabels; ///< input ITS Track MC labels + MCLabSpan mTPCTrkLabels; ///< input TPC Track MC labels /// <<<----- std::vector<InteractionCandidate> mInteractions; ///< possible interaction times @@ -642,8 +643,8 @@ class MatchTPCITS std::vector<BracketF> mITSROFTimes; ///< min/max times of ITS ROFs in TPC time-bins std::vector<TrackLocTPC> mTPCWork; ///< TPC track params prepared for matching std::vector<TrackLocITS> mITSWork; ///< ITS track params prepared for matching - std::vector<o2::MCCompLabel> mTPCLblWork; ///< TPC track labels - std::vector<o2::MCCompLabel> mITSLblWork; ///< ITS track labels + MCLabContTr mTPCLblWork; ///< TPC track labels + MCLabContTr mITSLblWork; ///< ITS track labels std::vector<float> mWinnerChi2Refit; ///< vector of refitChi2 for winners std::deque<ITSChipClustersRefs> mITSChipClustersRefs; ///< range of clusters for each chip in ITS (for AfterBurner) @@ -676,8 +677,8 @@ class MatchTPCITS ///< outputs tracks container std::vector<o2::dataformats::TrackTPCITS> mMatchedTracks; - std::vector<o2::MCCompLabel> mOutITSLabels; ///< ITS label of matched track - std::vector<o2::MCCompLabel> mOutTPCLabels; ///< TPC label of matched track + MCLabContTr mOutITSLabels; ///< ITS label of matched track + MCLabContTr mOutTPCLabels; ///< TPC label of matched track o2::its::RecoGeomHelper mRGHelper; ///< helper for cluster and geometry access float mITSFiducialZCut = 9999.; ///< eliminate TPC seeds outside of this range diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 859d0f0e76b7e..acef77170e097 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -65,14 +65,14 @@ void MatchTPCITS::printABTracksTree(const ABTrackLinksList& llist) const return; } o2::MCCompLabel lblTrc; - if (mTPCTrkLabels) { - lblTrc = mTPCTrkLabels->getLabels(mTPCWork[llist.trackID].sourceID)[0]; + if (mMCTruthON) { + lblTrc = mTPCTrkLabels[mTPCWork[llist.trackID].sourceID]; } LOG(INFO) << "Matches for track " << llist.trackID << " lowest lr: " << int(llist.lowestLayer) << " " << lblTrc << " pT= " << mTPCWork[llist.trackID].getPt(); auto printHyp = [this, &lblTrc](int nextHyp, int cnt) { - printf("#%d Lr/IC/Lnk/ClID/Chi2/Chi2Nrm/{MC}:%c ", cnt++, mTPCTrkLabels ? (lblTrc.isFake() ? 'F' : 'C') : '-'); + printf("#%d Lr/IC/Lnk/ClID/Chi2/Chi2Nrm/{MC}:%c ", cnt++, mTPCTrkLabels.size() ? (lblTrc.isFake() ? 'F' : 'C') : '-'); int nFakeClus = 0, nTotClus = 0, parID = nextHyp; // print particular hypothesis while (1) { const auto& lnk = mABTrackLinks[parID]; @@ -90,7 +90,7 @@ void MatchTPCITS::printABTracksTree(const ABTrackLinksList& llist) const mcEv = mcTr = -999; // noise nFakeClus++; } - } else if (lnk.isDummyTop() && mTPCTrkLabels) { // top layer, use TPC MC lbl + } else if (lnk.isDummyTop() && mMCTruthON) { // top layer, use TPC MC lbl mcEv = lblTrc.getEventID(); mcTr = lblTrc.getTrackID(); } @@ -138,8 +138,8 @@ void MatchTPCITS::dumpABTracksDebugTree(const ABTrackLinksList& llist) } LOG(INFO) << "Dump AB Matches for track " << llist.trackID; o2::MCCompLabel lblTrc; - if (mTPCTrkLabels) { - lblTrc = mTPCTrkLabels->getLabels(mTPCWork[llist.trackID].sourceID)[0]; // tmp + if (mMCTruthON) { + lblTrc = mTPCTrkLabels[mTPCWork[llist.trackID].sourceID]; // tmp } int ord = 0; for (int lowest = llist.lowestLayer; lowest <= mParams->requireToReachLayerAB; lowest++) { @@ -545,7 +545,7 @@ bool MatchTPCITS::prepareTPCTracks() continue; } if (mMCTruthON) { - mTPCLblWork.emplace_back(mTPCTrkLabels->getLabels(it)[0]); + mTPCLblWork.emplace_back(mTPCTrkLabels[it]); } float time0 = trcOrig.getTime0(); @@ -711,7 +711,7 @@ bool MatchTPCITS::prepareITSTracks() continue; // add to cache only those ITS tracks which reached ref.X and have reasonable snp } if (mMCTruthON) { - mITSLblWork.emplace_back(mITSTrkLabels->getLabels(it)[0]); + mITSLblWork.emplace_back(mITSTrkLabels[it]); } trc.roFrame = irof; @@ -1191,7 +1191,7 @@ void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector) // TODO: use faster prop here, no 3d field, materials mITSSectIndexCache[sector].push_back(mITSWork.size() - 1); // register track CLONE if (mMCTruthON) { - mITSLblWork.emplace_back(mITSTrkLabels->getLabels(trc.sourceID)[0]); + mITSLblWork.emplace_back(mITSTrkLabels[trc.sourceID]); } } else { mITSWork.pop_back(); // rotation / propagation failed @@ -1999,8 +1999,11 @@ int MatchTPCITS::checkABSeedFromLr(int lrSeed, int seedID, ABTrackLinksList& lli std::array<int, MaxLadderCand> lad2Check; nLad2Check = mFieldON ? findLaddersToCheckBOn(lrTgt, ladIDguess, trcCircle, errYFrac, lad2Check) : findLaddersToCheckBOff(lrTgt, ladIDguess, trcLinPar, errYFrac, lad2Check); - const auto& tTPC = mTPCWork[llist.trackID]; // tmp - auto lblTrc = mTPCTrkLabels->getLabels(tTPC.sourceID)[0]; // tmp + const auto& tTPC = mTPCWork[llist.trackID]; // tmp + o2::MCCompLabel lblTrc; + if (mMCTruthON) { + lblTrc = mTPCTrkLabels[tTPC.sourceID]; // tmp + } for (int ilad = nLad2Check; ilad--;) { int ladID = lad2Check[ilad]; const auto& lad = lr.ladders[ladID]; @@ -2496,7 +2499,7 @@ bool MatchTPCITS::validateABMatch(int ilink) if (linkCl.linkedABTrack != headID) { // best link for this cluster differs from the link we are checking return false; } - } else if (lnk.isDummyTop() && mTPCTrkLabels) { // top layer reached, this is winner + } else if (lnk.isDummyTop()) { // top layer reached, this is winner break; } parID = lnk.parentID; // check next cluster of the same link diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index 622c1e2ff2d8a..6cf056eb529d3 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -39,7 +39,8 @@ #include "DetectorsRaw/HBFUtils.h" using namespace o2::framework; -using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; +using MCLabelsCl = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; +using MCLabelsTr = gsl::span<const o2::MCCompLabel>; namespace o2 { @@ -197,24 +198,18 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) //----------------------------<< TPC Clusters loading <<------------------------------------------ // - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* lblITSPtr = nullptr; - std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>> lblITS; + MCLabelsTr lblITS; + MCLabelsTr lblTPC; - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* lblClusITSPtr = nullptr; - std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>> lblClusITS; - - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* lblTPCPtr = nullptr; - std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>> lblTPC; + const MCLabelsCl* lblClusITSPtr = nullptr; + std::unique_ptr<const MCLabelsCl> lblClusITS; if (mUseMC) { - lblITS = pc.inputs().get<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("trackITSMCTR"); - lblITSPtr = lblITS.get(); + lblITS = pc.inputs().get<gsl::span<o2::MCCompLabel>>("trackITSMCTR"); + lblTPC = pc.inputs().get<gsl::span<o2::MCCompLabel>>("trackTPCMCTR"); lblClusITS = pc.inputs().get<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("clusITSMCTR"); lblClusITSPtr = lblClusITS.get(); - - lblTPC = pc.inputs().get<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("trackTPCMCTR"); - lblTPCPtr = lblTPC.get(); } // // create ITS clusters as spacepoints in tracking frame @@ -234,9 +229,9 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) mMatching.setTPCClustersInp(&clusterIndex); if (mUseMC) { - mMatching.setITSTrkLabelsInp(lblITSPtr); + mMatching.setITSTrkLabelsInp(lblITS); + mMatching.setTPCTrkLabelsInp(lblTPC); mMatching.setITSClsLabelsInp(lblClusITSPtr); - mMatching.setTPCTrkLabelsInp(lblTPCPtr); } if (mUseFT0) { From 83e047aad699d658137d16a7369e66785e9c9162 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 30 Aug 2020 17:34:27 +0200 Subject: [PATCH 0518/1751] Adapt macros to use vector instead of MCTruthContainer for ITS,TPC track labels --- .../ITSMFT/ITS/macros/test/CheckTracks.C | 6 +-- .../ITSMFT/ITS/macros/test/DisplayTrack.C | 4 +- macro/checkTOFMatching.C | 38 ++++++++----------- macro/runCATrackingClusterNative.C | 2 +- macro/run_trac_ca_its.C | 2 +- macro/run_trac_its.C | 3 +- 6 files changed, 24 insertions(+), 31 deletions(-) diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTracks.C b/Detectors/ITSMFT/ITS/macros/test/CheckTracks.C index fd7a50706db82..27f382b289e36 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTracks.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTracks.C @@ -103,7 +103,7 @@ void CheckTracks(std::string tracfile = "o2trac_its.root", std::string clusfile std::vector<TrackITS>* recArr = nullptr; recTree->SetBranchAddress("ITSTrack", &recArr); // Track MC labels - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* trkLabArr = nullptr; + std::vector<o2::MCCompLabel>* trkLabArr = nullptr; recTree->SetBranchAddress("ITSTrackMCTruth", &trkLabArr); Int_t lastEventIDcl = -1, cf = 0; @@ -154,7 +154,7 @@ void CheckTracks(std::string tracfile = "o2trac_its.root", std::string clusfile continue; int loadedEventTracks = frame; for (unsigned int i = 0; i < recArr->size(); i++) { // Find the last MC event within this reconstructed entry - auto lab = (trkLabArr->getLabels(i))[0]; + auto lab = (*trkLabArr)[i]; if (!lab.isValid()) { const TrackITS& recTrack = (*recArr)[i]; fak->Fill(recTrack.getPt()); @@ -210,7 +210,7 @@ void CheckTracks(std::string tracfile = "o2trac_its.root", std::string clusfile long lastIndex = (frame == f.lastFrame) ? f.lastIndex : nentr - 1; for (long i = firstIndex; i <= lastIndex; i++) { - auto lab = (trkLabArr->getLabels(i))[0]; + auto lab = (*trkLabArr)[i]; if (!lab.isValid() || lab.getSourceID() != 0 || lab.getEventID() != n) continue; int mcid = lab.getTrackID(); diff --git a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C index c29742199485f..8bbb8628cc4d3 100644 --- a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C +++ b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C @@ -205,7 +205,7 @@ found: tree->SetBranchAddress("ITSTrack", &trkArr); tree->SetBranchAddress("ITSTrackClusIdx", &clIdx); // Track MC labels - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* trkLabArr = nullptr; + std::vector<o2::MCCompLabel>* trkLabArr = nullptr; tree->SetBranchAddress("ITSTrackMCTruth", &trkLabArr); tree->GetEvent(0); @@ -214,7 +214,7 @@ found: n = 0; while (nt--) { const TrackITS& t = (*trkArr)[nt]; - auto lab = (trkLabArr->getLabels(nt))[0]; + auto lab = (*trkLabArr)[nt]; if (TMath::Abs(lab.getEventID()) != event) continue; if (TMath::Abs(lab.getTrackID()) != track) diff --git a/macro/checkTOFMatching.C b/macro/checkTOFMatching.C index 0678d69b9f544..80f07ebf52b7a 100644 --- a/macro/checkTOFMatching.C +++ b/macro/checkTOFMatching.C @@ -40,7 +40,7 @@ void checkTOFMatching(bool batchMode = true) TTree* tpcTree = (TTree*)ftracksTPC->Get("events"); std::vector<o2::tpc::TrackTPC>* mTPCTracksArrayInp = new std::vector<o2::tpc::TrackTPC>; tpcTree->SetBranchAddress("Tracks", &mTPCTracksArrayInp); - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mcTPC = new o2::dataformats::MCTruthContainer<o2::MCCompLabel>(); + std::vector<o2::MCCompLabel>* mcTPC = new std::vector<o2::MCCompLabel>(); tpcTree->SetBranchAddress("TracksMCTruth", &mcTPC); // getting the ITS tracks @@ -48,7 +48,7 @@ void checkTOFMatching(bool batchMode = true) TTree* itsTree = (TTree*)ftracksITS->Get("o2sim"); std::vector<o2::its::TrackITS>* mITSTracksArrayInp = new std::vector<o2::its::TrackITS>; itsTree->SetBranchAddress("ITSTrack", &mITSTracksArrayInp); - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mcITS = new o2::dataformats::MCTruthContainer<o2::MCCompLabel>(); + std::vector<o2::MCCompLabel>* mcITS = new std::vector<o2::MCCompLabel>(); itsTree->SetBranchAddress("ITSTrackMCTruth", &mcITS); // getting the TOF clusters @@ -274,23 +274,19 @@ void checkTOFMatching(bool batchMode = true) Printf("matched ITStrack index = %d", evIdxITS); #endif // getting the TPC labels - const auto& labelsTPC = mcTPC->getLabels(evIdxTPC); + const auto& labelsTPC = (*mcTPC)[evIdxTPC]; #ifdef DEBUG - for (uint ilabel = 0; ilabel < labelsTPC.size(); ilabel++) { - Printf("TPC label %d: trackID = %d, eventID = %d, sourceID = %d", ilabel, labelsTPC[ilabel].getTrackID(), labelsTPC[ilabel].getEventID(), labelsTPC[ilabel].getSourceID()); - } + Printf("TPC label: trackID = %d, eventID = %d, sourceID = %d", labelsTPC.getTrackID(), labelsTPC.getEventID(), labelsTPC.getSourceID()); #endif // getting the ITS labels - const auto& labelsITS = mcITS->getLabels(evIdxITS); + const auto& labelsITS = (*mcITS)[evIdxITS]; #ifdef DEBUG - for (uint ilabel = 0; ilabel < labelsITS.size(); ilabel++) { - Printf("ITS label %d: trackID = %d, eventID = %d, sourceID = %d", ilabel, labelsITS[ilabel].getTrackID(), labelsITS[ilabel].getEventID(), labelsITS[ilabel].getSourceID()); - } + Printf("ITS label: trackID = %d, eventID = %d, sourceID = %d", ilabel, labelsITS.getTrackID(), labelsITS.getEventID(), labelsITS.getSourceID()); #endif bool bMatched = kFALSE; for (uint ilabel = 0; ilabel < labelsTOF.size(); ilabel++) { - if ((abs(labelsTPC[0].getTrackID()) == labelsTOF[ilabel].getTrackID() && labelsTPC[0].getEventID() == labelsTOF[ilabel].getEventID() && labelsTPC[0].getSourceID() == labelsTOF[ilabel].getSourceID()) || (labelsITS[0].getTrackID() == labelsTOF[ilabel].getTrackID() && labelsITS[0].getEventID() == labelsTOF[ilabel].getEventID() && labelsITS[0].getSourceID() == labelsTOF[ilabel].getSourceID())) { + if ((abs(labelsTPC.getTrackID()) == labelsTOF[ilabel].getTrackID() && labelsTPC.getEventID() == labelsTOF[ilabel].getEventID() && labelsTPC.getSourceID() == labelsTOF[ilabel].getSourceID()) || (labelsITS.getTrackID() == labelsTOF[ilabel].getTrackID() && labelsITS.getEventID() == labelsTOF[ilabel].getEventID() && labelsITS.getSourceID() == labelsTOF[ilabel].getSourceID())) { nGoodMatches++; bMatched = kTRUE; break; @@ -352,23 +348,19 @@ void checkTOFMatching(bool batchMode = true) o2::dataformats::TrackTPCITS trackITSTPC = mTracksArrayInp->at(i); const auto evIdxTPCcheck = trackITSTPC.getRefTPC(); const auto evIdxITScheck = trackITSTPC.getRefITS(); - const auto& labelsTPCcheck = mcTPC->getLabels(evIdxTPCcheck); - for (uint ilabel = 0; ilabel < labelsTPCcheck.size(); ilabel++) { - if (abs(labelsTPCcheck[ilabel].getTrackID()) == trackIdTOF && labelsTPCcheck[ilabel].getEventID() == eventIdTOF && labelsTPCcheck[ilabel].getSourceID() == sourceIdTOF) { + const auto& labelsTPCcheck = (*mcTPC)[evIdxTPCcheck]; + if (abs(labelsTPCcheck.getTrackID()) == trackIdTOF && labelsTPCcheck.getEventID() == eventIdTOF && labelsTPCcheck.getSourceID() == sourceIdTOF) { #ifdef DEBUG - Printf("The TPC track that should have been matched to TOF is number %d", i); + Printf("The TPC track that should have been matched to TOF is number %d", i); #endif - TPCfound = true; - } + TPCfound = true; } - const auto& labelsITScheck = mcITS->getLabels(evIdxITScheck); - for (uint ilabel = 0; ilabel < labelsITScheck.size(); ilabel++) { - if (labelsITScheck[ilabel].getTrackID() == trackIdTOF && labelsITScheck[ilabel].getEventID() == eventIdTOF && labelsITScheck[ilabel].getSourceID() == sourceIdTOF) { + const auto& labelsITScheck = (*mcITS)[evIdxITScheck]; + if (labelsITScheck.getTrackID() == trackIdTOF && labelsITScheck.getEventID() == eventIdTOF && labelsITScheck.getSourceID() == sourceIdTOF) { #ifdef DEBUG - Printf("The ITS track that should have been matched to TOF is number %d", i); + Printf("The ITS track that should have been matched to TOF is number %d", i); #endif - ITSfound = true; - } + ITSfound = true; } } #ifdef DEBUG diff --git a/macro/runCATrackingClusterNative.C b/macro/runCATrackingClusterNative.C index f31c79917982b..07921750eecb9 100644 --- a/macro/runCATrackingClusterNative.C +++ b/macro/runCATrackingClusterNative.C @@ -100,7 +100,7 @@ int runCATrackingClusterNative(TString inputFile, TString outputFile) vector<TrackTPC> tracks; vector<TPCClRefElem> trackClusRefs; - MCLabelContainer tracksMC; + std::vector<o2::MCCompLabel> tracksMC; TFile fout(outputFile, "recreate"); TTree tout("events", "events"); diff --git a/macro/run_trac_ca_its.C b/macro/run_trac_ca_its.C index 3dbedbafc4abf..c004c3dfd15a6 100644 --- a/macro/run_trac_ca_its.C +++ b/macro/run_trac_ca_its.C @@ -165,7 +165,7 @@ void run_trac_ca_its(std::string path = "./", std::vector<o2::itsmft::ROFRecord> vertROFvec, *vertROFvecPtr = &vertROFvec; std::vector<Vertex> vertices, *verticesPtr = &vertices; - MCLabCont trackLabels, *trackLabelsPtr = &trackLabels; + std::vector<o2::MCCompLabel> trackLabels, *trackLabelsPtr = &trackLabels; outTree.Branch("ITSTrack", &tracksITSPtr); outTree.Branch("ITSTrackClusIdx", &trackClIdxPtr); outTree.Branch("ITSTrackMCTruth", &trackLabelsPtr); diff --git a/macro/run_trac_its.C b/macro/run_trac_its.C index 41482067789b9..4f9c7c8e23e95 100644 --- a/macro/run_trac_its.C +++ b/macro/run_trac_its.C @@ -38,6 +38,7 @@ #include "ITStracking/VertexerTraits.h" using MCLabCont = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; +using MCLabContTr = std::vector<o2::MCCompLabel>; using Vertex = o2::dataformats::Vertex<o2::dataformats::TimeStamp<int>>; void run_trac_its(std::string path = "./", std::string outputfile = "o2trac_its.root", @@ -141,7 +142,7 @@ void run_trac_its(std::string path = "./", std::string outputfile = "o2trac_its. std::vector<o2::itsmft::ROFRecord> vertROFvec, *vertROFvecPtr = &vertROFvec; std::vector<Vertex> vertices, *verticesPtr = &vertices; - MCLabCont trackLabels, *trackLabelsPtr = &trackLabels; + MCLabContTr trackLabels, *trackLabelsPtr = &trackLabels; outTree.Branch("ITSTrack", &tracksITSPtr); outTree.Branch("ITSTrackClusIdx", &trackClIdxPtr); outTree.Branch("ITSTrackMCTruth", &trackLabelsPtr); From 7b6ea2e1cf6f8f24ff030e7a2e4f09126574fa25 Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez@cern.ch> Date: Tue, 1 Sep 2020 09:00:26 +0200 Subject: [PATCH 0519/1751] The singles distribution for NUA correction extraction (#4254) Also - circumvent the number of output objects limitation - circumvent the use of HistogramsRegistry - circumvent the number of task scope variables limitation --- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 396 ++++++++++++++++---- 1 file changed, 319 insertions(+), 77 deletions(-) diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index 1815182edaaba..e6e83fae6eb91 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -16,6 +16,7 @@ #include "Analysis/TrackSelection.h" #include "Analysis/TrackSelectionTables.h" #include <TROOT.h> +#include <TParameter.h> #include <TList.h> #include <TDirectory.h> #include <TH1.h> @@ -34,9 +35,6 @@ namespace o2 { namespace aod { -using CollisionEvSelCent = soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator; -using TrackData = soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection>::iterator; - /* we have to change from int to bool when bool columns work properly */ namespace dptdptcorrelations { @@ -46,25 +44,34 @@ DECLARE_SOA_COLUMN(TrackacceptedAsTwo, trackacceptedastwo, uint8_t); } // namespace dptdptcorrelations DECLARE_SOA_TABLE(AcceptedEvents, "AOD", "ACCEPTEDEVENTS", dptdptcorrelations::EventAccepted); DECLARE_SOA_TABLE(ScannedTracks, "AOD", "SCANNEDTRACKS", dptdptcorrelations::TrackacceptedAsOne, dptdptcorrelations::TrackacceptedAsTwo); + +using CollisionEvSelCent = soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator; +using TrackData = soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection>::iterator; +using FilteredTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::ScannedTracks>>; } // namespace aod } // namespace o2 namespace dptdptcorrelations { -/* all this bins have to be make configurable */ +/* all this is made configurable */ int ptbins = 18; float ptlow = 0.2, ptup = 2.0; int etabins = 16; float etalow = -0.8, etaup = 0.8; int zvtxbins = 40; float zvtxlow = -10.0, zvtxup = 10.0; +/* this still panding of being configurable */ int phibins = 72; -std::string fTaskConfigurationString = "PendingToConfigure"; -Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; -Configurable<int> cfgTrackOneCharge("trk1charge", 1, "Trakc one charge: 1 = positive, -1 = negative"); -Configurable<int> cfgTrackTwoCharge("trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"); -Configurable<bool> cfgProcessPairs("processpairs", true, "Process pairs: false = no, just singles, true = yes, process pairs"); +float philow = 0.0; +float phiup = TMath::TwoPi(); +float etabinwidth = (etaup - etalow) / float(etabins); +float phibinwidth = (phiup - philow) / float(phibins); +int tracktype = 1; +int trackonecharge = 1; +int tracktwocharge = -1; +bool processpairs = false; +std::string fTaskConfigurationString = "PendingToConfigure"; /* while we don't have proper bool columnst */ uint8_t DPTDPT_TRUE = 1; @@ -82,8 +89,9 @@ enum SystemType { knSystems ///< number of handled systems }; -/* probably this will not work in the context of distributed processes */ -/* we need to revisit it!!!! */ +//============================================================================================ +// The DptDptCorrelationsFilterAnalysisTask output objects +//============================================================================================ SystemType fSystem = kNoSystem; TH1F* fhCentMultB = nullptr; TH1F* fhCentMultA = nullptr; @@ -108,6 +116,41 @@ TH2F* fhEtaVsPhiA = nullptr; TH2F* fhPtVsEtaB = nullptr; TH2F* fhPtVsEtaA = nullptr; +//============================================================================================ +// The DptDptCorrelationsAnalysisTask output objects +//============================================================================================ +/* histograms */ +TH1F* fhN1_1_vsPt; //!<! track 1 weighted single particle distribution vs \f$p_T\f$ +TH2F* fhN1_1_vsEtaPhi; //!<! track 1 weighted single particle distribution vs \f$\eta,\;\phi\f$ +TH2F* fhSum1Pt_1_vsEtaPhi; //!<! track 1 accumulated sum of weighted \f$p_T\f$ vs \f$\eta,\;\phi\f$ +TH3F* fhN1_1_vsZEtaPhiPt; //!<! track 1 single particle distribution vs \f$\mbox{vtx}_z,\; \eta,\;\phi,\;p_T\f$ +TH1F* fhN1_2_vsPt; //!<! track 2 weighted single particle distribution vs \f$p_T\f$ +TH2F* fhN1_2_vsEtaPhi; //!<! track 2 weighted single particle distribution vs \f$\eta,\;\phi\f$ +TH2F* fhSum1Pt_2_vsEtaPhi; //!<! track 2 accumulated sum of weighted \f$p_T\f$ vs \f$\eta,\;\phi\f$ +TH3F* fhN1_2_vsZEtaPhiPt; //!<! track 2 single particle distribution vs \f$\mbox{vtx}_z,\;\eta,\;\phi,\;p_T\f$ +TH2F* fhN2_12_vsPtPt; //!<! track 1 and 2 weighted two particle distribution vs \f${p_T}_1, {p_T}_2\f$ +TH1F* fhN2_12_vsEtaPhi; //!<! track 1 and 2 weighted two particle distribution vs \f$\eta,\;\phi\f$ +TH1F* fhSum2PtPt_12_vsEtaPhi; //!<! track 1 and 2 weighted accumulated \f${p_T}_1 {p_T}_2\f$ distribution vs \f$\eta,\;\phi\f$ +TH1F* fhSum2PtN_12_vsEtaPhi; //!<! track 1 and 2 weighted accumulated \f${p_T}_1 n_2\f$ distribution vs \f$\eta,\;\phi\f$ +TH1F* fhSum2NPt_12_vsEtaPhi; //!<! track 1 and 2 weighted accumulated \f$n_1 {p_T}_2\f$ distribution vs \f$\eta,\;\phi\f$ +/* versus centrality/multiplicity profiles */ +TProfile* fhN1_1_vsC; //!<! track 1 weighted single particle distribution vs event centrality +TProfile* fhSum1Pt_1_vsC; //!<! track 1 accumulated sum of weighted \f$p_T\f$ vs event centrality +TProfile* fhN1nw_1_vsC; //!<! track 1 un-weighted single particle distribution vs event centrality +TProfile* fhSum1Ptnw_1_vsC; //!<! track 1 accumulated sum of un-weighted \f$p_T\f$ vs event centrality +TProfile* fhN1_2_vsC; //!<! track 2 weighted single particle distribution vs event centrality +TProfile* fhSum1Pt_2_vsC; //!<! track 2 accumulated sum of weighted \f$p_T\f$ vs event centrality +TProfile* fhN1nw_2_vsC; //!<! track 2 un-weighted single particle distribution vs event centrality +TProfile* fhSum1Ptnw_2_vsC; //!<! track 2 accumulated sum of un-weighted \f$p_T\f$ vs event centrality +TProfile* fhN2_12_vsC; //!<! track 1 and 2 weighted two particle distribution vs event centrality +TProfile* fhSum2PtPt_12_vsC; //!<! track 1 and 2 weighted accumulated \f${p_T}_1 {p_T}_2\f$ distribution vs event centrality +TProfile* fhSum2PtN_12_vsC; //!<! track 1 and 2 weighted accumulated \f${p_T}_1 n_2\f$ distribution vs event centrality +TProfile* fhSum2NPt_12_vsC; //!<! track 1 and 2 weighted accumulated \f$n_1 {p_T}_2\f$ distribution vs event centrality +TProfile* fhN2nw_12_vsC; //!<! track 1 and 2 un-weighted two particle distribution vs event centrality +TProfile* fhSum2PtPtnw_12_vsC; //!<! track 1 and 2 un-weighted accumulated \f${p_T}_1 {p_T}_2\f$ distribution vs event centrality +TProfile* fhSum2PtNnw_12_vsC; //!<! track 1 and 2 un-weighted accumulated \f${p_T}_1 n_2\f$ distribution vs event centrality +TProfile* fhSum2NPtnw_12_vsC; //!<! track 1 and 2 un-weighted accumulated \f$n_1 {p_T}_2\f$ distribution vs event centrality + SystemType getSystemType() { /* we have to figure out how extract the system type */ @@ -129,7 +172,7 @@ bool IsEvtSelected(aod::CollisionEvSelCent const& collision) bool matchTrackType(aod::TrackData const& track) { - switch (cfgTrackType) { + switch (tracktype) { case 1: if (track.isGlobalTrack() != 0) return true; @@ -147,7 +190,7 @@ bool matchTrackType(aod::TrackData const& track) } } -std::tuple<uint8_t, uint8_t> AcceptTrack(aod::TrackData const& track) +inline std::tuple<uint8_t, uint8_t> AcceptTrack(aod::TrackData const& track) { uint8_t asone = DPTDPT_FALSE; @@ -156,15 +199,31 @@ std::tuple<uint8_t, uint8_t> AcceptTrack(aod::TrackData const& track) /* TODO: incorporate a mask in the scanned tracks table for the rejecting track reason */ if (matchTrackType(track)) { if (ptlow < track.pt() and track.pt() < ptup and etalow < track.eta() and track.eta() < etaup) { - if (((track.charge() > 0) and (cfgTrackOneCharge > 0)) or ((track.charge() < 0) and (cfgTrackOneCharge < 0))) { + if (((track.charge() > 0) and (trackonecharge > 0)) or ((track.charge() < 0) and (trackonecharge < 0))) { asone = DPTDPT_TRUE; - } else if (((track.charge() > 0) and (cfgTrackTwoCharge > 0)) or ((track.charge() < 0) and (cfgTrackTwoCharge < 0))) { + } else if (((track.charge() > 0) and (tracktwocharge > 0)) or ((track.charge() < 0) and (tracktwocharge < 0))) { astwo = DPTDPT_TRUE; } } } return std::make_tuple(asone, astwo); } + +/// \brief Returns the zero based bin index of the eta phi passed values +/// \param eta the eta value +/// \param phi the phi value +/// \return the zero based bin index +/// +/// According to the bining structure, to the track eta will correspond +/// a zero based bin index and similarlly for the track phi +/// The returned index is the composition of both considering eta as +/// the first index component +inline int GetEtaPhiIndex(float eta, float phi) +{ + int etaix = int((eta - etalow) / etabinwidth); + int phiix = int((phi - philow) / phibinwidth); + return etaix * phibins + phiix; +} } /* end namespace dptdptcorrelations */ // Task for <dpt,dpt> correlations analysis @@ -175,36 +234,53 @@ using namespace dptdptcorrelations; struct DptDptCorrelationsFilterAnalysisTask { - OutputObj<TDirectory> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; - - OutputObj<TH1F> fOutCentMultB{"CentralityB", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutCentMultA{"CentralityA", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutVertexZB{"VertexZB", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutVertexZA{"VertexZA", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPtB{"fHistPtB", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPtA{"fHistPtA", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPtPosB{"fHistPtPosB", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPtPosA{"fHistPtPosA", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPtNegB{"fHistPtNegB", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPtNegA{"fHistPtNegA", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutEtaB{"fHistEtaB", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutEtaA{"fHistEtaA", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPhiB{"fHistPhiB", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TH1F> fOutPhiA{"fHistPhiA", OutputObjHandlingPolicy::AnalysisObject}; - // no more histograms for the time being - // OutputObj<TH2F> fOutEtaVsPhiB{"CSTaskEtaVsPhiB", OutputObjHandlingPolicy::AnalysisObject}; - // OutputObj<TH2F> fOutEtaVsPhiA{"CSTaskEtaVsPhiA", OutputObjHandlingPolicy::AnalysisObject}; - // OutputObj<TH2F> fOutPtVsEtaB{"fhPtVsEtaB", OutputObjHandlingPolicy::AnalysisObject}; - // OutputObj<TH2F> fOutPtVsEtaA{"fhPtVsEtaA", OutputObjHandlingPolicy::AnalysisObject}; + Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; + Configurable<int> cfgTrackOneCharge{"trk1charge", 1, "Trakc one charge: 1 = positive, -1 = negative"}; + Configurable<int> cfgTrackTwoCharge{"trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"}; + + Configurable<int> cfgPtBins{"ptbins", 18, "Number of pT bins, default 18"}; + Configurable<int> cfgZVtxBins{"zvtxbins", 28, "Number of z_vtx bins, default 28"}; + Configurable<int> cfgEtaBins{"etabins", 16, "Number of eta bins, default 16"}; + Configurable<float> cfgPtLow{"ptlow", 0.2f, "Lowest pT (GeV/c), default 0.2"}; + Configurable<float> cfgPtHigh{"pthigh", 2.0f, "Highest pT (GeV/c), default 2.0"}; + Configurable<float> cfgZVtxLow{"zvtxlow", -7.0f, "Lowest z_vtx distance (cm), default -7.0"}; + Configurable<float> cfgZVtxHigh{"zvtxhigh", 7.0f, "Highest z_vtx distance (cm), default 7.0"}; + Configurable<float> cfgEtaLow{"etalow", -0.8f, "Lowest eta value, default -0.8"}; + Configurable<float> cfgEtaHigh{"etahigh", 0.8f, "Highest eta value, default 0.8"}; + + OutputObj<TList> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; Produces<aod::AcceptedEvents> acceptedevents; Produces<aod::ScannedTracks> scannedtracks; void init(InitContext const&) { - /* if the system type is not known at this time, we have to put the initalization somwhere else */ + /* update the configurable values */ + ptbins = cfgPtBins.value; + ptlow = cfgPtLow.value; + ptup = cfgPtHigh.value; + etabins = cfgEtaBins.value; + etalow = cfgEtaLow.value; + etaup = cfgEtaHigh.value; + zvtxbins = cfgZVtxBins.value; + zvtxlow = cfgZVtxLow.value; + zvtxup = cfgZVtxHigh.value; + tracktype = cfgTrackType.value; + trackonecharge = cfgTrackOneCharge.value; + tracktwocharge = cfgTrackTwoCharge.value; + + /* still missing configuration */ + phibins = 72; + + /* if the system type is not known at this time, we have to put the initalization somewhere else */ fSystem = getSystemType(); + /* create the output list which will own the task histograms */ + TList* fOutputList = new TList(); + fOutputList->SetOwner(true); + fOutput.setObject(fOutputList); + + /* create the histograms */ if (fSystem > kPbp) { fhCentMultB = new TH1F("CentralityB", "Centrality before cut; centrality (%)", 100, 0, 100); fhCentMultA = new TH1F("CentralityA", "Centrality; centrality (%)", 100, 0, 100); @@ -213,6 +289,7 @@ struct DptDptCorrelationsFilterAnalysisTask { fhCentMultB = new TH1F("MultiplicityB", "Multiplicity before cut; multiplicity (%)", 100, 0, 100); fhCentMultA = new TH1F("MultiplicityA", "Multiplicity; multiplicity (%)", 100, 0, 100); } + fhVertexZB = new TH1F("VertexZB", "Vertex Z; z_{vtx}", 60, -15, 15); fhVertexZA = new TH1F("VertexZA", "Vertex Z; z_{vtx}", zvtxbins, zvtxlow, zvtxup); @@ -226,31 +303,30 @@ struct DptDptCorrelationsFilterAnalysisTask { fhEtaA = new TH1F("fHistEtaA", "#eta distribution for reconstructed;#eta;counts", etabins, etalow, etaup); fhPhiB = new TH1F("fHistPhiB", "#phi distribution for reconstructed before;#phi;counts", 360, 0.0, 2 * M_PI); fhPhiA = new TH1F("fHistPhiA", "#phi distribution for reconstructed;#phi;counts", 360, 0.0, 2 * M_PI); - // no more histograms for the time being - // fhEtaVsPhiB = new TH2F(TString::Format("CSTaskEtaVsPhiB_%s",fTaskConfigurationString.c_str()),"#eta vs #phi before;#phi;#eta", 360, 0.0, 2*M_PI, 100, -2.0, 2.0); - // fhEtaVsPhiA = new TH2F(TString::Format("CSTaskEtaVsPhiA_%s",fTaskConfigurationString.c_str()),"#eta vs #phi;#phi;#eta", 360, 0.0, 2*M_PI, etabins, etalow, etaup); - // fhPtVsEtaB = new TH2F(TString::Format("fhPtVsEtaB_%s",fTaskConfigurationString.c_str()),"p_{T} vs #eta before;#eta;p_{T} (GeV/c)",etabins,etalow,etaup,100,0.0,15.0); - // fhPtVsEtaA = new TH2F(TString::Format("fhPtVsEtaA_%s",fTaskConfigurationString.c_str()),"p_{T} vs #eta;#eta;p_{T} (GeV/c)",etabins,etalow,etaup,ptbins,ptlow,ptup); - - fOutCentMultB.setObject(fhCentMultB); - fOutCentMultA.setObject(fhCentMultA); - fOutVertexZB.setObject(fhVertexZB); - fOutVertexZA.setObject(fhVertexZA); - fOutPtB.setObject(fhPtB); - fOutPtA.setObject(fhPtA); - fOutPtPosB.setObject(fhPtPosB); - fOutPtPosA.setObject(fhPtPosA); - fOutPtNegB.setObject(fhPtNegB); - fOutPtNegA.setObject(fhPtNegA); - fOutEtaB.setObject(fhEtaB); - fOutEtaA.setObject(fhEtaA); - fOutPhiB.setObject(fhPhiB); - fOutPhiA.setObject(fhPhiA); - // no more histograms for the time being - // fOutEtaVsPhiB.setObject(fhEtaVsPhiB); - // fOutEtaVsPhiA.setObject(fhEtaVsPhiA); - // fOutPtVsEtaB.setObject(fhPtVsEtaB); - // fOutPtVsEtaA.setObject(fhPtVsEtaA); + fhEtaVsPhiB = new TH2F(TString::Format("CSTaskEtaVsPhiB_%s", fTaskConfigurationString.c_str()), "#eta vs #phi before;#phi;#eta", 360, 0.0, 2 * M_PI, 100, -2.0, 2.0); + fhEtaVsPhiA = new TH2F(TString::Format("CSTaskEtaVsPhiA_%s", fTaskConfigurationString.c_str()), "#eta vs #phi;#phi;#eta", 360, 0.0, 2 * M_PI, etabins, etalow, etaup); + fhPtVsEtaB = new TH2F(TString::Format("fhPtVsEtaB_%s", fTaskConfigurationString.c_str()), "p_{T} vs #eta before;#eta;p_{T} (GeV/c)", etabins, etalow, etaup, 100, 0.0, 15.0); + fhPtVsEtaA = new TH2F(TString::Format("fhPtVsEtaA_%s", fTaskConfigurationString.c_str()), "p_{T} vs #eta;#eta;p_{T} (GeV/c)", etabins, etalow, etaup, ptbins, ptlow, ptup); + + /* add the hstograms to the output list */ + fOutputList->Add(fhCentMultB); + fOutputList->Add(fhCentMultA); + fOutputList->Add(fhVertexZB); + fOutputList->Add(fhVertexZA); + fOutputList->Add(fhPtB); + fOutputList->Add(fhPtA); + fOutputList->Add(fhPtPosB); + fOutputList->Add(fhPtPosA); + fOutputList->Add(fhPtNegB); + fOutputList->Add(fhPtNegA); + fOutputList->Add(fhEtaB); + fOutputList->Add(fhEtaA); + fOutputList->Add(fhPhiB); + fOutputList->Add(fhPhiA); + fOutputList->Add(fhEtaVsPhiB); + fOutputList->Add(fhEtaVsPhiA); + fOutputList->Add(fhPtVsEtaB); + fOutputList->Add(fhPtVsEtaA); } void process(aod::CollisionEvSelCent const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection> const& ftracks) @@ -270,9 +346,8 @@ struct DptDptCorrelationsFilterAnalysisTask { fhPtB->Fill(track.pt()); fhEtaB->Fill(track.eta()); fhPhiB->Fill(track.phi()); - // no more histograms for the time being - // fhEtaVsPhiB->Fill(track.phi(),track.eta()); - // fhPtVsEtaB->Fill(track.eta(),track.pt()); + fhEtaVsPhiB->Fill(track.phi(), track.eta()); + fhPtVsEtaB->Fill(track.eta(), track.pt()); if (track.charge() > 0) { fhPtPosB->Fill(track.pt()); } else { @@ -287,9 +362,8 @@ struct DptDptCorrelationsFilterAnalysisTask { fhPtA->Fill(track.pt()); fhEtaA->Fill(track.eta()); fhPhiA->Fill(track.phi()); - // no more histograms for the time being - // fhEtaVsPhiA->Fill(track.phi(),track.eta()); - // fhPtVsEtaA->Fill(track.eta(),track.pt()); + fhEtaVsPhiA->Fill(track.phi(), track.eta()); + fhPtVsEtaA->Fill(track.eta(), track.pt()); if (track.charge() > 0) { fhPtPosA->Fill(track.pt()); } else { @@ -310,17 +384,181 @@ struct DptDptCorrelationsFilterAnalysisTask { // Task for building <dpt,dpt> correlations struct DptDptCorrelationsTask { + Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; + Configurable<int> cfgTrackOneCharge{"trk1charge", 1, "Trakc one charge: 1 = positive, -1 = negative"}; + Configurable<int> cfgTrackTwoCharge{"trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"}; + Configurable<bool> cfgProcessPairs{"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}; + + Configurable<int> cfgPtBins{"ptbins", 18, "Number of pT bins, default 18"}; + Configurable<int> cfgZVtxBins{"zvtxbins", 28, "Number of z_vtx bins, default 28"}; + Configurable<int> cfgEtaBins{"etabins", 16, "Number of eta bins, default 16"}; + Configurable<float> cfgPtLow{"ptlow", 0.2f, "Lowest pT (GeV/c), default 0.2"}; + Configurable<float> cfgPtHigh{"pthigh", 2.0f, "Highest pT (GeV/c), default 2.0"}; + Configurable<float> cfgZVtxLow{"zvtxlow", -7.0f, "Lowest z_vtx distance (cm), default -7.0"}; + Configurable<float> cfgZVtxHigh{"zvtxhigh", 7.0f, "Highest z_vtx distance (cm), default 7.0"}; + Configurable<float> cfgEtaLow{"etalow", -0.8f, "Lowest eta value, default -0.8"}; + Configurable<float> cfgEtaHigh{"etahigh", 0.8f, "Highest eta value, default 0.8"}; + + OutputObj<TList> fOutput{"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + /* update the configurable values */ + ptbins = cfgPtBins.value; + ptlow = cfgPtLow.value; + ptup = cfgPtHigh.value; + etabins = cfgEtaBins.value; + etalow = cfgEtaLow.value; + etaup = cfgEtaHigh.value; + zvtxbins = cfgZVtxBins.value; + zvtxlow = cfgZVtxLow.value; + zvtxup = cfgZVtxHigh.value; + tracktype = cfgTrackType.value; + trackonecharge = cfgTrackOneCharge.value; + tracktwocharge = cfgTrackTwoCharge.value; + processpairs = cfgProcessPairs.value; + + /* still missing configuration */ + phibins = 72; + /* TODO: shift of the azimuthal angle origin */ + philow = 0.0; + phiup = TMath::TwoPi(); + + /* create the output list which will own the task histograms */ + TList* fOutputList = new TList(); + fOutputList->SetOwner(true); + fOutput.setObject(fOutputList); + + /* incorporate configuration parameters to the output */ + fOutputList->Add(new TParameter<Int_t>("NoBinsVertexZ", zvtxbins, 'f')); + fOutputList->Add(new TParameter<Int_t>("NoBinsPt", ptbins, 'f')); + fOutputList->Add(new TParameter<Int_t>("NoBinsEta", etabins, 'f')); + fOutputList->Add(new TParameter<Int_t>("NoBinsPhi", phibins, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinVertexZ", zvtxlow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxVertexZ", zvtxup, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinPt", ptlow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxPt", ptup, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinEta", etalow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxEta", etaup, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinPhi", philow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxPhi", phiup, 'f')); + + /* TODO: the shift in the origen of the azimuthal angle */ + + /* create the histograms */ + Bool_t oldstatus = TH1::AddDirectoryStatus(); + TH1::AddDirectory(kFALSE); + + if (!processpairs) { + fhN1_1_vsPt = new TH1F("n1_1_vsPt", "#LT n_{1} #GT;p_{t,1} (GeV/c);#LT n_{1} #GT", ptbins, ptlow, ptup); + fhN1_1_vsZEtaPhiPt = new TH3F("n1_1_vsZ_vsEtaPhi_vsPt", "#LT n_{1} #GT;vtx_{z};#eta_{1}#times#varphi_{1};p_{t,1} (GeV/c)", + zvtxbins, zvtxlow, zvtxup, etabins * phibins, 0.0, double(etabins * phibins), ptbins, ptlow, ptup); + + fhN1_2_vsPt = new TH1F("n1_2_vsPt", "#LT n_{1} #GT;p_{t,2} (GeV/c);#LT n_{1} #GT", ptbins, ptlow, ptup); + fhN1_2_vsZEtaPhiPt = new TH3F("n1_2_vsZ_vsEtaPhi_vsPt", "#LT n_{2} #GT;vtx_{z};#eta_{2}#times#varphi_{2};p_{t,2} (GeV/c)", + zvtxbins, zvtxlow, zvtxup, etabins * phibins, 0.0, double(etabins * phibins), ptbins, ptlow, ptup); + + fOutputList->Add(fhN1_1_vsPt); + fOutputList->Add(fhN1_1_vsZEtaPhiPt); + fOutputList->Add(fhN1_2_vsPt); + fOutputList->Add(fhN1_2_vsZEtaPhiPt); + } else { + fhN1_1_vsEtaPhi = new TH2F("n1_1_vsEtaPhi", "#LT n_{1} #GT;#eta_{1};#varphi_{1} (radian);#LT n_{1} #GT", + etabins, etalow, etaup, phibins, philow, phiup); + fhSum1Pt_1_vsEtaPhi = new TH2F("sumPt_1_vsEtaPhi", "#LT #Sigma p_{t,1} #GT;#eta_{1};#varphi_{1} (radian);#LT #Sigma p_{t,1} #GT (GeV/c)", + etabins, etalow, etaup, phibins, philow, phiup); + fhN1_1_vsC = new TProfile("n1_1_vsM", "#LT n_{1} #GT (weighted);Centrality (%);#LT n_{1} #GT", 100, 0.0, 100.0); + fhSum1Pt_1_vsC = new TProfile("sumPt_1_vsM", "#LT #Sigma p_{t,1} #GT (weighted);Centrality (%);#LT #Sigma p_{t,1} #GT (GeV/c)", 100, 0.0, 100.0); + fhN1nw_1_vsC = new TProfile("n1Nw_1_vsM", "#LT n_{1} #GT;Centrality (%);#LT n_{1} #GT", 100, 0.0, 100.0); + fhSum1Ptnw_1_vsC = new TProfile("sumPtNw_1_vsM", "#LT #Sigma p_{t,1} #GT;Centrality (%);#LT #Sigma p_{t,1} #GT (GeV/c)", 100, 0.0, 100.0); + + fhN1_2_vsEtaPhi = new TH2F("n1_2_vsEtaPhi", "#LT n_{1} #GT;#eta_{2};#varphi_{2} (radian);#LT n_{1} #GT", + etabins, etalow, etaup, phibins, philow, phiup); + fhSum1Pt_2_vsEtaPhi = new TH2F("sumPt_2_vsEtaPhi", "#LT #Sigma p_{t,2} #GT;#eta_{2};#varphi_{2} (radian);#LT #Sigma p_{t,2} #GT (GeV/c)", + etabins, etalow, etaup, phibins, philow, phiup); + fhN1_2_vsC = new TProfile("n1_2_vsM", "#LT n_{1} #GT (weighted);Centrality (%);#LT n_{1} #GT", 100, 0.0, 100.0); + fhSum1Pt_2_vsC = new TProfile("sumPt_2_vsM", "#LT #Sigma p_{t,1} #GT (weighted);Centrality (%);#LT #Sigma p_{t,1} #GT (GeV/c)", 100, 0.0, 100.0); + fhN1nw_2_vsC = new TProfile("n1Nw_2_vsM", "#LT n_{1} #GT;Centrality (%);#LT n_{1} #GT", 100, 0.0, 100.0); + fhSum1Ptnw_2_vsC = new TProfile("sumPtNw_2_vsM", "#LT #Sigma p_{t,1} #GT;Centrality (%);#LT #Sigma p_{t,1} #GT (GeV/c)", 100, 0.0, 100.0); + + fhN2_12_vsEtaPhi = new TH1F("n2_12_vsEtaPhi", "#LT n_{2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT n_{2} #GT", + etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); + fhSum2PtPt_12_vsEtaPhi = new TH1F("sumPtPt_12_vsEtaPhi", "#LT #Sigma p_{t,1}p_{t,2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT #Sigma p_{t,1}p_{t,2} #GT (GeV)^{2}", + etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); + fhSum2PtN_12_vsEtaPhi = new TH1F("sumPtN_12_vsEtaPhi", "#LT #Sigma p_{t,1}N #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT #Sigma p_{t,1}N #GT (GeV)", + etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); + fhSum2NPt_12_vsEtaPhi = new TH1F("sumNPt_12_vsEtaPhi", "#LT N#Sigma p_{t,2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT N#Sigma p_{t,2} #GT (GeV)", + etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); + fhN2_12_vsPtPt = new TH2F("n2_12_vsPtVsPt", "#LT n_{2} #GT;p_{t,1} (GeV/c);p_{t,2} (GeV/c);#LT n_{2} #GT", + ptbins, ptlow, ptup, ptbins, ptlow, ptup); + fhN2_12_vsC = new TProfile("n2_12_vsM", "#LT n_{2} #GT (weighted);Centrality (%);#LT n_{2} #GT", 100, 0.0, 100.0); + fhSum2PtPt_12_vsC = new TProfile("sumPtPt_12_vsM", "#LT #Sigma p_{t,1}p_{t,2} #GT (weighted);Centrality (%);#LT #Sigma p_{t,1}p_{t,2} #GT (GeV)^{2}", 100, 0.0, 100.0); + fhSum2PtN_12_vsC = new TProfile("sumPtN_12_vsM", "#LT #Sigma p_{t,1}N #GT (weighted);Centrality (%);#LT #Sigma p_{t,1}N #GT (GeV)", 100, 0.0, 100.0); + fhSum2NPt_12_vsC = new TProfile("sumNPt_12_vsM", "#LT N#Sigma p_{t,2} #GT (weighted);Centrality (%);#LT N#Sigma p_{t,2} #GT (GeV)", 100, 0.0, 100.0); + fhN2nw_12_vsC = new TProfile("n2Nw_12_vsM", "#LT n_{2} #GT;Centrality (%);#LT n_{2} #GT", 100, 0.0, 100.0); + fhSum2PtPtnw_12_vsC = new TProfile("sumPtPtNw_12_vsM", "#LT #Sigma p_{t,1}p_{t,2} #GT;Centrality (%);#LT #Sigma p_{t,1}p_{t,2} #GT (GeV)^{2}", 100, 0.0, 100.0); + fhSum2PtNnw_12_vsC = new TProfile("sumPtNNw_12_vsM", "#LT #Sigma p_{t,1}N #GT;Centrality (%);#LT #Sigma p_{t,1}N #GT (GeV)", 100, 0.0, 100.0); + fhSum2NPtnw_12_vsC = new TProfile("sumNPtNw_12_vsM", "#LT N#Sigma p_{t,2} #GT;Centrality (%);#LT N#Sigma p_{t,2} #GT (GeV)", 100, 0.0, 100.0); + + /* the statistical uncertainties will be estimated by the subsamples method so let's get rid of error tracking */ + fhN2_12_vsEtaPhi->Sumw2(false); + fhSum2PtPt_12_vsEtaPhi->Sumw2(false); + fhSum2PtN_12_vsEtaPhi->Sumw2(false); + fhSum2NPt_12_vsEtaPhi->Sumw2(false); + + fOutputList->Add(fhN1_1_vsEtaPhi); + fOutputList->Add(fhSum1Pt_1_vsEtaPhi); + fOutputList->Add(fhN1_1_vsC); + fOutputList->Add(fhSum1Pt_1_vsC); + fOutputList->Add(fhN1nw_1_vsC); + fOutputList->Add(fhSum1Ptnw_1_vsC); + fOutputList->Add(fhN1_2_vsEtaPhi); + fOutputList->Add(fhSum1Pt_2_vsEtaPhi); + fOutputList->Add(fhN1_2_vsC); + fOutputList->Add(fhSum1Pt_2_vsC); + fOutputList->Add(fhN1nw_2_vsC); + fOutputList->Add(fhSum1Ptnw_2_vsC); + + fOutputList->Add(fhN2_12_vsEtaPhi); + fOutputList->Add(fhSum2PtPt_12_vsEtaPhi); + fOutputList->Add(fhSum2PtN_12_vsEtaPhi); + fOutputList->Add(fhSum2NPt_12_vsEtaPhi); + fOutputList->Add(fhN2_12_vsPtPt); + fOutputList->Add(fhN2_12_vsC); + fOutputList->Add(fhSum2PtPt_12_vsC); + fOutputList->Add(fhSum2PtN_12_vsC); + fOutputList->Add(fhSum2NPt_12_vsC); + fOutputList->Add(fhN2nw_12_vsC); + fOutputList->Add(fhSum2PtPtnw_12_vsC); + fOutputList->Add(fhSum2PtNnw_12_vsC); + fOutputList->Add(fhSum2NPtnw_12_vsC); + } + + TH1::AddDirectory(oldstatus); + } + Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); - using FilteredTracks = soa::Filtered<soa::Join<aod::Tracks, aod::ScannedTracks>>; - Partition<FilteredTracks> Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE; - Partition<FilteredTracks> Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE; + Partition<aod::FilteredTracks> Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE; + Partition<aod::FilteredTracks> Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents, aod::AcceptedEvents>>::iterator const& collision, - FilteredTracks const& tracks) + aod::FilteredTracks const& tracks) { - if (cfgProcessPairs) { + if (!processpairs) { + /* process single tracks */ + for (auto& track1 : Tracks1) { + double corr = 1.0; /* TODO: track correction weights */ + fhN1_1_vsPt->Fill(track1.pt(), corr); + fhN1_1_vsZEtaPhiPt->Fill(collision.posZ(), GetEtaPhiIndex(track1.eta(), track1.phi()) + 0.5, track1.pt(), corr); + } + for (auto& track2 : Tracks2) { + double corr = 1.0; /* TODO: track correction weights */ + fhN1_2_vsPt->Fill(track2.pt(), corr); + fhN1_2_vsZEtaPhiPt->Fill(collision.posZ(), GetEtaPhiIndex(track2.eta(), track2.phi()) + 0.5, track2.pt(), corr); + } + } else { /* process pairs of tracks */ // this will be desireable // for (auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(Tracks1, Tracks2))) { @@ -329,12 +567,10 @@ struct DptDptCorrelationsTask { /* checkiing the same track id condition */ if (track1.index() == track2.index()) { LOGF(INFO, "Tracks with the same Id: %d", track1.index()); + } else { } - /* now it is just to collect the two particle information */ } } - } else { - /* process single tracks */ } } }; @@ -350,7 +586,13 @@ struct TracksAndEventClassificationQA { OutputObj<TH1F> fTracksTwoUnsel{TH1F("TracksTwoUnsel", "Tracks as track two;number of tracks;events", 1500, 0.0, 1500.0)}; OutputObj<TH1F> fTracksOneAndTwoUnsel{TH1F("TracksOneAndTwoUnsel", "Tracks as track one and as track two;number of tracks;events", 1500, 0.0, 1500.0)}; OutputObj<TH1F> fTracksNoneUnsel{TH1F("TracksNoneUnsel", "Not selected tracks;number of tracks;events", 1500, 0.0, 1500.0)}; - OutputObj<TH1F> fSelectedEvents{TH1F("SelectedEvents", "Selected events;number of tracks;events", 2, 0.0, 2.0)}; + OutputObj<TH1F> fSelectedEvents{TH1F("SelectedEvents", "Selected events;;events", 2, 0.0, 2.0)}; + + void init(InitContext const&) + { + fSelectedEvents->GetXaxis()->SetBinLabel(1, "Not selected events"); + fSelectedEvents->GetXaxis()->SetBinLabel(2, "Selected events"); + } Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); From d85ec047b41d71c8251140bfebc7c0f9e2906351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 1 Sep 2020 09:28:19 +0200 Subject: [PATCH 0520/1751] Complete RecoDecay. Update related tables and tasks. (#4256) Implement calculation of decay length uncertainty. Replace DCA with Chi2. Rename tasks and move to PWGHF. Remove obsolete files. Minor fixes. --- Analysis/DataModel/CMakeLists.txt | 3 +- .../DataModel/include/Analysis/RecoDecay.h | 12 +- .../include/Analysis/SecondaryVertex.h | 75 ----- .../include/Analysis/SecondaryVertexHF.h | 18 +- .../include/Analysis/decayUtilities.h | 86 ------ .../include/Analysis/trackUtilities.h | 50 ++- Analysis/DataModel/src/dummy.cxx | 10 - Analysis/DataModel/src/dumpDataModel.cxx | 3 - Analysis/Tasks/CMakeLists.txt | 26 +- Analysis/Tasks/PWGHF/CMakeLists.txt | 24 ++ .../HFCandidateCreator2Prong.cxx} | 23 +- .../HFTrackIndexSkimsCreator.cxx} | 4 +- .../Tasks/{taskdzero.cxx => PWGHF/taskD0.cxx} | 4 +- Analysis/Tasks/vertexerhf.cxx | 289 ------------------ 14 files changed, 107 insertions(+), 520 deletions(-) delete mode 100644 Analysis/DataModel/include/Analysis/SecondaryVertex.h delete mode 100644 Analysis/DataModel/include/Analysis/decayUtilities.h delete mode 100644 Analysis/DataModel/src/dummy.cxx create mode 100644 Analysis/Tasks/PWGHF/CMakeLists.txt rename Analysis/Tasks/{hfcandidatecreator2prong.cxx => PWGHF/HFCandidateCreator2Prong.cxx} (83%) rename Analysis/Tasks/{hftrackindexskimscreator.cxx => PWGHF/HFTrackIndexSkimsCreator.cxx} (98%) rename Analysis/Tasks/{taskdzero.cxx => PWGHF/taskD0.cxx} (97%) delete mode 100644 Analysis/Tasks/vertexerhf.cxx diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index 4f9628f883e2f..df43c7280c5d8 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -9,8 +9,7 @@ # submit itself to any jurisdiction. o2_add_library(AnalysisDataModel - SOURCES src/dummy.cxx - src/ParamBase.cxx + SOURCES src/ParamBase.cxx src/DetectorResponse.cxx src/PIDTOF.cxx src/PIDTPC.cxx diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index 06c3561c1931d..c4cbbfc0e7db3 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -56,7 +56,7 @@ class RecoDecay /// \param num a number of arbitrary type /// \return number squared template <typename T> - auto static sq(T num) + static auto sq(T num) { return (double)num * (double)num; } @@ -128,7 +128,7 @@ class RecoDecay /// \param point1,point2 {x, y, z} coordinates of points /// \return 3D distance between two points template <typename T, typename U> - static auto distance(const array<T, 3>& point1, const array<U, 3>& point2) + static auto distance(const T& point1, const U& point2) { return sqrtSumOfSquares(point1[0] - point2[0], point1[1] - point2[1], point1[2] - point2[2]); } @@ -136,8 +136,8 @@ class RecoDecay /// Calculates 2D {x, y} distance between two points. /// \param point1,point2 {x, y, z} or {x, y} coordinates of points /// \return 2D {x, y} distance between two points - template <std::size_t N, std::size_t O, typename T, typename U> - static auto distanceXY(const array<T, N>& point1, const array<U, O>& point2) + template <typename T, typename U> + static auto distanceXY(const T& point1, const U& point2) { return sqrtSumOfSquares(point1[0] - point2[0], point1[1] - point2[1]); } @@ -279,8 +279,8 @@ class RecoDecay /// \note AliRoot version /// \param arrMom array of two 3-momentum arrays /// \param arrMass array of two masses (in the same order as arrMom) - /// \param iProng index of the prong /// \param mTot assumed mass of mother particle + /// \param iProng index of the prong /// \return cosine of θ* of the i-th prong under the assumption of the invariant mass template <typename T, typename U, typename V> static auto CosThetaStarA(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, V mTot, int iProng) @@ -294,7 +294,7 @@ class RecoDecay // p* = √[(M^2 - m1^2 - m2^2)^2 - 4 m1^2 m2^2]/2M // Lorentz transformation of the longitudinal momentum of the prong into the detector frame: // p_L,i = γ (p*_L,i + β E*_i) - // p*_L,i = p_L,i/γ - β E*_i) + // p*_L,i = p_L,i/γ - β E*_i // cos(θ*_i) = (p_L,i/γ - β E*_i)/p* return (dotProd(arrMom[iProng], pVecTot) / (pTot * gamma) - beta * E(pStar, arrMass[iProng])) / pStar; } diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertex.h b/Analysis/DataModel/include/Analysis/SecondaryVertex.h deleted file mode 100644 index bac1456896728..0000000000000 --- a/Analysis/DataModel/include/Analysis/SecondaryVertex.h +++ /dev/null @@ -1,75 +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. -#ifndef O2_ANALYSIS_SECONDARYVERTEX_H_ -#define O2_ANALYSIS_SECONDARYVERTEX_H_ - -#include "Framework/AnalysisDataModel.h" - -namespace o2::aod -{ -namespace secvtx2prong -{ -// FIXME: this is a workaround until we get the index columns to work with joins. -using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra>; - -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -DECLARE_SOA_COLUMN(Posdecayx, posdecayx, float); -DECLARE_SOA_COLUMN(Posdecayy, posdecayy, float); -DECLARE_SOA_COLUMN(Posdecayz, posdecayz, float); -DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, BigTracks, "fIndex0"); -DECLARE_SOA_COLUMN(Px0, px0, float); -DECLARE_SOA_COLUMN(Py0, py0, float); -DECLARE_SOA_COLUMN(Pz0, pz0, float); -DECLARE_SOA_COLUMN(Y0, y0, float); -DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, BigTracks, "fIndex1"); -DECLARE_SOA_COLUMN(Px1, px1, float); -DECLARE_SOA_COLUMN(Py1, py1, float); -DECLARE_SOA_COLUMN(Pz1, pz1, float); -DECLARE_SOA_COLUMN(Y1, y1, float); -DECLARE_SOA_COLUMN(Mass, mass, float); -DECLARE_SOA_COLUMN(Massbar, massbar, float); -DECLARE_SOA_DYNAMIC_COLUMN(DecaylengthXY, decaylengthXY, - [](float xvtxd, float yvtxd, float xvtxp, float yvtxp) { return sqrtf((yvtxd - yvtxp) * (yvtxd - yvtxp) + (xvtxd - xvtxp) * (xvtxd - xvtxp)); }); -DECLARE_SOA_DYNAMIC_COLUMN(Decaylength, decaylength, - [](float xvtxd, float yvtxd, float zvtxd, float xvtxp, - float yvtxp, float zvtxp) { return sqrtf((yvtxd - yvtxp) * (yvtxd - yvtxp) + (xvtxd - xvtxp) * (xvtxd - xvtxp) + (zvtxd - zvtxp) * (zvtxd - zvtxp)); }); -//old way of doing it -//DECLARE_SOA_COLUMN(Decaylength, decaylength, float); -//DECLARE_SOA_COLUMN(DecaylengthXY, decaylengthXY, float); - -} // namespace secvtx2prong -namespace cand2prong -{ -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -DECLARE_SOA_COLUMN(MassD0, massD0, float); -DECLARE_SOA_COLUMN(MassD0bar, massD0bar, float); -} // namespace cand2prong - -DECLARE_SOA_TABLE(SecVtx2Prong, "AOD", "VTX2PRONG", - secvtx2prong::CollisionId, - collision::PosX, collision::PosY, collision::PosZ, - secvtx2prong::Posdecayx, secvtx2prong::Posdecayy, secvtx2prong::Posdecayz, - secvtx2prong::Index0Id, - secvtx2prong::Px0, secvtx2prong::Py0, secvtx2prong::Pz0, secvtx2prong::Y0, - secvtx2prong::Index1Id, - secvtx2prong::Px1, secvtx2prong::Py1, secvtx2prong::Pz1, secvtx2prong::Y1, - secvtx2prong::Mass, secvtx2prong::Massbar, - secvtx2prong::DecaylengthXY<secvtx2prong::Posdecayx, secvtx2prong::Posdecayy, - collision::PosX, collision::PosY>, - secvtx2prong::Decaylength<secvtx2prong::Posdecayx, secvtx2prong::Posdecayy, - secvtx2prong::Posdecayz, collision::PosX, - collision::PosY, collision::PosZ>); - -DECLARE_SOA_TABLE(Cand2Prong, "AOD", "CANDDZERO", - //cand2prong::CollisionId, - cand2prong::MassD0, cand2prong::MassD0bar); -} // namespace o2::aod - -#endif // O2_ANALYSIS_SECONDARYVERTEX_H_ diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index 2a1f3d237745a..4e9fa74e80198 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -56,6 +56,7 @@ DECLARE_SOA_COLUMN(XSecondaryVertex, xSecondaryVertex, float); DECLARE_SOA_COLUMN(YSecondaryVertex, ySecondaryVertex, float); DECLARE_SOA_COLUMN(ZSecondaryVertex, zSecondaryVertex, float); DECLARE_SOA_DYNAMIC_COLUMN(RSecondaryVertex, rSecondaryVertex, [](float xVtxS, float yVtxS) { return RecoDecay::sqrtSumOfSquares(xVtxS, yVtxS); }); +DECLARE_SOA_COLUMN(Chi2PCA, chi2PCA, float); // sum of (non-weighted) distances of the secondary vertex to its prongs // prong properties DECLARE_SOA_COLUMN(PxProng0, pxProng0, float); DECLARE_SOA_COLUMN(PyProng0, pyProng0, float); @@ -108,7 +109,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(Ct, ct, [](float xVtxP, float yVtxP, float zVtxP, flo // specific 2-prong decay properties namespace hf_cand_prong2 { -DECLARE_SOA_COLUMN(DCA, dca, float); DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, 1.f * aod::hf_cand::pxProng0 + 1.f * aod::hf_cand::pxProng1); DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, 1.f * aod::hf_cand::pyProng0 + 1.f * aod::hf_cand::pyProng1); DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1); @@ -122,43 +122,43 @@ DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, // D0(bar) → π± K∓ template <typename T> -auto CtD0(T candidate) +auto CtD0(const T& candidate) { return candidate.ct(RecoDecay::getMassPDG(421)); } template <typename T> -auto YD0(T candidate) +auto YD0(const T& candidate) { return candidate.y(RecoDecay::getMassPDG(421)); } template <typename T> -auto ED0(T candidate) +auto ED0(const T& candidate) { return candidate.e(RecoDecay::getMassPDG(421)); } template <typename T> -auto InvMassD0(T candidate) +auto InvMassD0(const T& candidate) { return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus)}); } template <typename T> -auto InvMassD0bar(T candidate) +auto InvMassD0bar(const T& candidate) { return candidate.m(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); } template <typename T> -auto CosThetaStarD0(T candidate) +auto CosThetaStarD0(const T& candidate) { return candidate.cosThetaStar(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus)}, RecoDecay::getMassPDG(421), 1); } template <typename T> -auto CosThetaStarD0bar(T candidate) +auto CosThetaStarD0bar(const T& candidate) { return candidate.cosThetaStar(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}, RecoDecay::getMassPDG(421), 0); } @@ -168,6 +168,7 @@ DECLARE_SOA_TABLE(HfCandBase, "AOD", "HFCANDBASE", collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, /* dynamic columns */ hf_cand::RSecondaryVertex<hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, hf_cand::ImpactParameterNormalised0<hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0>, @@ -188,7 +189,6 @@ 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_cand_prong2::DCA, /* dynamic columns */ hf_cand_prong2::ImpactParameterProduct<hf_cand::ImpactParameter0, hf_cand::ImpactParameter1>, hf_cand_prong2::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, diff --git a/Analysis/DataModel/include/Analysis/decayUtilities.h b/Analysis/DataModel/include/Analysis/decayUtilities.h deleted file mode 100644 index 879217175499c..0000000000000 --- a/Analysis/DataModel/include/Analysis/decayUtilities.h +++ /dev/null @@ -1,86 +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. -#ifndef O2_ANALYSIS_RECODECAY_H_ -#define O2_ANALYSIS_RECODECAY_H_ - -#include <cmath> - -double energy(double px, double py, double pz, double mass) -{ - double en_ = std::sqrt(mass * mass + px * px + py * py + pz * pz); - return en_; -} - -double invmass2prongs2(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1) -{ - - double energy0_ = energy(px0, py0, pz0, mass0); - double energy1_ = energy(px1, py1, pz1, mass1); - double energytot = energy0_ + energy1_; - - double psum2 = (px0 + px1) * (px0 + px1) + - (py0 + py1) * (py0 + py1) + - (pz0 + pz1) * (pz0 + pz1); - return energytot * energytot - psum2; -} - -double invmass3prongs2(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1, - double px2, double py2, double pz2, double mass2) -{ - double energy0_ = energy(px0, py0, pz0, mass0); - double energy1_ = energy(px1, py1, pz1, mass1); - double energy2_ = energy(px2, py2, pz2, mass2); - double energytot = energy0_ + energy1_ + energy2_; - - double psum2 = (px0 + px1 + px2) * (px0 + px1 + px2) + - (py0 + py1 + py2) * (py0 + py1 + py2) + - (pz0 + pz1 + pz2) * (pz0 + pz1 + pz2); - return energytot * energytot - psum2; -} - -double invmass2prongs(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1) -{ - return std::sqrt(invmass2prongs2(px0, py0, pz0, mass0, - px1, py1, pz1, mass1)); -} - -double invmass3prongs(double px0, double py0, double pz0, double mass0, - double px1, double py1, double pz1, double mass1, - double px2, double py2, double pz2, double mass2) -{ - return std::sqrt(invmass3prongs2(px0, py0, pz0, mass0, - px1, py1, pz1, mass1, - px2, py2, pz2, mass2)); -} - -double ptcand2prong(double px0, double py0, double px1, double py1) -{ - return std::sqrt((px0 + px1) * (px0 + px1) + (py0 + py1) * (py0 + py1)); -} - -double pttrack(double px, double py) -{ - return std::sqrt(px * px + py * py); -} - -double declength(double xdecay, double ydecay, double zdecay, double xvtx, double yvtx, double zvtx) -{ - return std::sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx) + (zdecay - zvtx) * (zdecay - zvtx)); -} - -double declengthxy(double xdecay, double ydecay, double xvtx, double yvtx) -{ - return std::sqrt((xdecay - xvtx) * (xdecay - xvtx) + (ydecay - yvtx) * (ydecay - yvtx)); -} - -#endif // O2_ANALYSIS_RECODECAY_H_ diff --git a/Analysis/DataModel/include/Analysis/trackUtilities.h b/Analysis/DataModel/include/Analysis/trackUtilities.h index 43f6393e8add1..4941a4eb268a2 100644 --- a/Analysis/DataModel/include/Analysis/trackUtilities.h +++ b/Analysis/DataModel/include/Analysis/trackUtilities.h @@ -7,21 +7,25 @@ // 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 "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/Vertex.h" /// \file trackUtilities.h -/// \brief Utilities for manipulating track parameters +/// \brief Utilities for manipulating parameters of tracks and vertices /// /// \author Vít Kučera <vit.kucera@cern.ch>, CERN #ifndef O2_ANALYSIS_TRACKUTILITIES_H_ #define O2_ANALYSIS_TRACKUTILITIES_H_ +#include <cmath> + +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/Vertex.h" +#include "Analysis/RecoDecay.h" + /// Extracts track parameters and covariance matrix from a track. /// \return o2::track::TrackParCov template <typename T> -auto getTrackParCov(T track) +auto getTrackParCov(const T& track) { std::array<float, 5> arraypar = {track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt()}; @@ -37,11 +41,47 @@ auto getTrackParCov(T track) /// Extracts primary vertex position and covariance matrix from a collision. /// \return o2::dataformats::VertexBase template <typename T> -auto getPrimaryVertex(T collision) +auto getPrimaryVertex(const T& collision) { Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); std::array<float, 6> vtxCov{collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}; return o2::dataformats::VertexBase{std::move(vtxXYZ), std::move(vtxCov)}; } +/// Calculates direction of one point w.r.t another point. +/// \param point1,point2 points with {x, y, z} coordinates accessible by index +/// \param phi azimuth angle in the {x, y} plane (taken w.r.t. the x-axis towards the y-axis) +/// \param theta angle w.r.t the {x, y} plane towards the z-axis +/// \return phi,theta of point2 w.r.t. point1 +template <typename T, typename U, typename V, typename W> +void getPointDirection(const T& point1, const U& point2, V& phi, W& theta) +{ + phi = std::atan2(point2[1] - point1[1], point2[0] - point1[0]); + //auto x1 = point1[0] * std::cos(phi) + point1[1] * std::sin(phi); + //auto x2 = point2[0] * std::cos(phi) + point2[1] * std::sin(phi); + //theta = std::atan2(point2[2] - point1[2], x2 - x1); + theta = std::atan2(point2[2] - point1[2], RecoDecay::distanceXY(point1, point2)); +} + +/// Calculates the XX element of a XYZ covariance matrix after rotation of the coordinate system +/// by phi around the z-axis and by minus theta around the new y-axis. +/// \param matrix matrix +/// \param phi azimuth angle in the {x, y} plane (taken w.r.t. the x-axis towards the y-axis) +/// \param theta angle w.r.t the {x, y} plane towards the z-axis +/// \return XX element of the rotated covariance matrix +template <typename T, typename U, typename V> +auto getRotatedCovMatrixXX(const T& matrix, U phi, V theta) +{ + auto cp = std::cos(phi); + auto sp = std::sin(phi); + auto ct = std::cos(theta); + auto st = std::sin(theta); + return matrix[0] * cp * cp * ct * ct // covXX + + matrix[1] * 2. * cp * sp * ct * ct // covXY + + matrix[2] * sp * sp * ct * ct // covYY + + matrix[3] * 2. * cp * ct * st // covXZ + + matrix[4] * 2. * sp * ct * st // covYZ + + matrix[5] * st * st; // covZZ +} + #endif // O2_ANALYSIS_TRACKUTILITIES_H_ diff --git a/Analysis/DataModel/src/dummy.cxx b/Analysis/DataModel/src/dummy.cxx deleted file mode 100644 index 03082405d8cf5..0000000000000 --- a/Analysis/DataModel/src/dummy.cxx +++ /dev/null @@ -1,10 +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. -#include "Analysis/SecondaryVertex.h" diff --git a/Analysis/DataModel/src/dumpDataModel.cxx b/Analysis/DataModel/src/dumpDataModel.cxx index 4e9ae1f748307..b549f53a0af81 100644 --- a/Analysis/DataModel/src/dumpDataModel.cxx +++ b/Analysis/DataModel/src/dumpDataModel.cxx @@ -8,7 +8,6 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/AnalysisDataModel.h" -#include "Analysis/SecondaryVertex.h" #include "Analysis/SecondaryVertexHF.h" #include "PID/PIDResponse.h" #include "Analysis/Multiplicity.h" @@ -167,8 +166,6 @@ edge[dir=back, arrowtail=empty] dumpTable<FV0s>(); dumpTable<FDDs>(); dumpTable<Timestamps>(); - dumpTable<SecVtx2Prong>(true, StyleType::GREEN); - dumpTable<Cand2Prong>(true, StyleType::GREEN); dumpTable<HfTrackIndexProng2>(true, StyleType::GREEN); dumpTable<HfTrackIndexProng3>(true, StyleType::GREEN); diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index a7538c8af9795..0065fb0085e91 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(PWGCF) add_subdirectory(PWGDQ) +add_subdirectory(PWGHF) o2_add_dpl_workflow(trackselection SOURCES trackselection.cxx @@ -31,30 +32,11 @@ o2_add_dpl_workflow(correlations-mixed PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore COMPONENT_NAME Analysis) -o2_add_dpl_workflow(vertexing-hf - SOURCES vertexerhf.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(hftrackindexskimscreator - SOURCES hftrackindexskimscreator.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(hfcandidatecreator2prong - SOURCES hfcandidatecreator2prong.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(taskdzero - SOURCES taskdzero.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing +o2_add_dpl_workflow(qatask + SOURCES qaTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) -o2_add_dpl_workflow(qatask - SOURCES qaTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore - COMPONENT_NAME Analysis) o2_add_dpl_workflow(spectra-tof SOURCES spectraTOF.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel diff --git a/Analysis/Tasks/PWGHF/CMakeLists.txt b/Analysis/Tasks/PWGHF/CMakeLists.txt new file mode 100644 index 0000000000000..862040fb645c3 --- /dev/null +++ b/Analysis/Tasks/PWGHF/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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(hf-track-index-skims-creator + SOURCES HFTrackIndexSkimsCreator.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(hf-candidate-creator-2prong + SOURCES HFCandidateCreator2Prong.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(hf-task-d0 + SOURCES taskD0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/hfcandidatecreator2prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx similarity index 83% rename from Analysis/Tasks/hfcandidatecreator2prong.cxx rename to Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 20b527a15a450..88c95eac5fd2a 100644 --- a/Analysis/Tasks/hfcandidatecreator2prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -69,6 +69,8 @@ struct HFCandidateCreator2Prong { if (df.process(trackParVarPos1, trackParVarNeg1) == 0) continue; const auto& secondaryVertex = df.getPCACandidate(); + auto chi2PCA = df.getChi2AtPCACandidate(); + auto covMatrixPCA = df.calcPCACovMatrix().Array(); auto trackParVar0 = df.getTrack(0); auto trackParVar1 = df.getTrack(1); @@ -86,25 +88,28 @@ struct HFCandidateCreator2Prong { // get track impact parameters // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); o2::dataformats::DCA impactParameter0; o2::dataformats::DCA impactParameter1; trackParVar0.propagateToDCA(primaryVertex, magneticField, &impactParameter0); trackParVar1.propagateToDCA(primaryVertex, magneticField, &impactParameter1); - // TODO - float dcaDaughters = 0.; - float errorDecayLength = 1., errorDecayLengthXY = 1.; + // get uncertainty of the decay length + double phi, theta; + getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); // fill candidate table rows rowCandidateBase(collision.posX(), collision.posY(), collision.posZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], - errorDecayLength, errorDecayLengthXY, //); - //rowCandidateProng2Base( // TODO split table + errorDecayLength, errorDecayLengthXY, + chi2PCA, //); + //rowCandidateProng2Base( // TODO split table pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], impactParameter0.getY(), impactParameter1.getY(), - std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), - dcaDaughters); + std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2())); // fill histograms if (b_dovalplots) { @@ -127,6 +132,6 @@ struct HFCandidateCreator2ProngExpressions { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<HFCandidateCreator2Prong>("vertexerhf-hfcandcreator2prong"), - adaptAnalysisTask<HFCandidateCreator2ProngExpressions>("vertexerhf-hfcandcreator2prong-expressions")}; + adaptAnalysisTask<HFCandidateCreator2Prong>("hf-cand-creator-2prong"), + adaptAnalysisTask<HFCandidateCreator2ProngExpressions>("hf-cand-creator-2prong-expressions")}; } diff --git a/Analysis/Tasks/hftrackindexskimscreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx similarity index 98% rename from Analysis/Tasks/hftrackindexskimscreator.cxx rename to Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index eda08bc6a8b43..5647cfb773d90 100644 --- a/Analysis/Tasks/hftrackindexskimscreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -290,6 +290,6 @@ struct HFTrackIndexSkimsCreator { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<SelectTracks>("produce-sel-track"), - adaptAnalysisTask<HFTrackIndexSkimsCreator>("vertexerhf-hftrackindexskimscreator")}; + adaptAnalysisTask<SelectTracks>("hf-produce-sel-track"), + adaptAnalysisTask<HFTrackIndexSkimsCreator>("hf-track-index-skims-creator")}; } diff --git a/Analysis/Tasks/taskdzero.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx similarity index 97% rename from Analysis/Tasks/taskdzero.cxx rename to Analysis/Tasks/PWGHF/taskD0.cxx index 5d0cf63c03dd9..9005341ea7844 100644 --- a/Analysis/Tasks/taskdzero.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -24,7 +24,7 @@ using namespace o2::aod::hf_cand_prong2; using std::array; /// D0 analysis task -struct TaskDzero { +struct TaskD0 { OutputObj<TH1F> hmass{TH1F("hmass", "2-track inv mass", 500, 0, 5.0)}; OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0, 10.0)}; OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0, 10.0)}; @@ -60,5 +60,5 @@ struct TaskDzero { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<TaskDzero>("hf-taskdzero")}; + adaptAnalysisTask<TaskD0>("hf-task-d0")}; } diff --git a/Analysis/Tasks/vertexerhf.cxx b/Analysis/Tasks/vertexerhf.cxx deleted file mode 100644 index 8bec265e41ba4..0000000000000 --- a/Analysis/Tasks/vertexerhf.cxx +++ /dev/null @@ -1,289 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Analysis/SecondaryVertex.h" -#include "Analysis/decayUtilities.h" -#include "DetectorsVertexing/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" - -#include <TFile.h> -#include <TH1F.h> -#include <cmath> -#include <array> - -using namespace o2; -using namespace o2::framework; - -struct DecayVertexBuilder2Prong { - // primary vertex position - OutputObj<TH1F> hvtxp_x_out{TH1F("hvertexx", "x primary vtx", 100, -10., 10.)}; - OutputObj<TH1F> hvtxp_y_out{TH1F("hvertexy", "y primary vtx", 100, -10., 10.)}; - OutputObj<TH1F> hvtxp_z_out{TH1F("hvertexz", "z primary vtx", 100, -10., 10.)}; - // track distributions before cuts - OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "pt tracks (#GeV)", 100, 0., 10.)}; - OutputObj<TH1F> htgl_nocuts{TH1F("htgl_nocuts", "tgl tracks (#GeV)", 100, 0., 10.)}; - OutputObj<TH1F> hitsmap_nocuts{TH1F("hitsmap_nocuts", "hitsmap", 100, 0., 100.)}; - // track distributions after cuts - OutputObj<TH1F> hpt_cuts{TH1F("hpt_cuts", "pt tracks (#GeV)", 100, 0., 10.)}; - OutputObj<TH1F> htgl_cuts{TH1F("htgl_cuts", "tgl tracks (#GeV)", 100, 0., 10.)}; - OutputObj<TH1F> hitsmap_cuts{TH1F("hitsmap_cuts", "hitsmap", 100, 0., 100.)}; - // secondary vertex position - OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hchi2dca{TH1F("hchi2dca", "chi2 DCA decay", 1000, 0., 0.0002)}; - - Produces<aod::SecVtx2Prong> secvtx2prong; - //Configurable<std::string> triggersel{"triggersel", "test", "A string configurable"}; - Configurable<int> triggerindex{"triggerindex", -1, "trigger index"}; - - void process(aod::Collision const& collision, - aod::BCs const& bcs, - soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) - { - //LOGP(error, "Trigger selection {}", std::string{triggersel}); - int trigindex = int{triggerindex}; - if (trigindex != -1) { - LOGF(info, "Selecting on trigger bit %d", trigindex); - uint64_t triggerMask = collision.bc().triggerMask(); - bool isTriggerClassFired = triggerMask & 1ul << (trigindex - 1); - if (!isTriggerClassFired) - return; - } - - LOGF(info, "N. of Tracks for collision: %d", tracks.size()); - o2::vertexing::DCAFitterN<2> df; - df.setBz(5.0); - // After finding the vertex, propagate tracks to the DCA. This is default anyway - df.setPropagateToPCA(true); - // do not consider V0 seeds with 2D circles crossing above this R. This is default anyway - df.setMaxR(200); - // do not consider V0 seeds with tracks Z-distance exceeding this. This is default anyway - df.setMaxDZIni(4); - // stop iterations if max correction is below this value. This is default anyway - df.setMinParamChange(1e-3); - // stop iterations if chi2 improves by less that this factor - df.setMinRelChi2Change(0.9); - - hvtxp_x_out->Fill(collision.posX()); - hvtxp_y_out->Fill(collision.posY()); - hvtxp_z_out->Fill(collision.posZ()); - for (auto it0 = tracks.begin(); it0 != tracks.end(); ++it0) { - auto& track_0 = *it0; - - UChar_t clustermap_0 = track_0.itsClusterMap(); - //fill track distribution before selection - hitsmap_nocuts->Fill(clustermap_0); - hpt_nocuts->Fill(track_0.pt()); - htgl_nocuts->Fill(track_0.tgl()); - bool isselected_0 = track_0.tpcNClsFound() > 70 && track_0.flags() & 0x4; - isselected_0 = isselected_0 && (TESTBIT(clustermap_0, 0) || TESTBIT(clustermap_0, 1)); - if (!isselected_0) - continue; - //fill track distribution after selection - hitsmap_cuts->Fill(clustermap_0); - hpt_cuts->Fill(track_0.pt()); - htgl_cuts->Fill(track_0.tgl()); - - float x0_ = track_0.x(); - float alpha0_ = track_0.alpha(); - std::array<float, 5> arraypar0 = {track_0.y(), track_0.z(), track_0.snp(), - track_0.tgl(), track_0.signed1Pt()}; - std::array<float, 15> covpar0 = {track_0.cYY(), track_0.cZY(), track_0.cZZ(), - track_0.cSnpY(), track_0.cSnpZ(), - track_0.cSnpSnp(), track_0.cTglY(), track_0.cTglZ(), - track_0.cTglSnp(), track_0.cTglTgl(), - track_0.c1PtY(), track_0.c1PtZ(), track_0.c1PtSnp(), - track_0.c1PtTgl(), track_0.c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar0(x0_, alpha0_, arraypar0, covpar0); - for (auto it1 = it0 + 1; it1 != tracks.end(); ++it1) { - auto& track_1 = *it1; - UChar_t clustermap_1 = track_1.itsClusterMap(); - bool isselected_1 = track_1.tpcNClsFound() > 70 && track_1.flags() & 0x4; - isselected_1 = isselected_1 && (TESTBIT(clustermap_1, 0) || TESTBIT(clustermap_1, 1)); - if (!isselected_1) - continue; - if (track_0.signed1Pt() * track_1.signed1Pt() > 0) - continue; - float x1_ = track_1.x(); - float alpha1_ = track_1.alpha(); - std::array<float, 5> arraypar1 = {track_1.y(), track_1.z(), track_1.snp(), - track_1.tgl(), track_1.signed1Pt()}; - std::array<float, 15> covpar1 = {track_1.cYY(), track_1.cZY(), track_1.cZZ(), - track_1.cSnpY(), track_1.cSnpZ(), - track_1.cSnpSnp(), track_1.cTglY(), track_1.cTglZ(), - track_1.cTglSnp(), track_1.cTglTgl(), - track_1.c1PtY(), track_1.c1PtZ(), track_1.c1PtSnp(), - track_1.c1PtTgl(), track_1.c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar1(x1_, alpha1_, arraypar1, covpar1); - df.setUseAbsDCA(true); - int nCand = df.process(trackparvar0, trackparvar1); - if (nCand == 0) - continue; - const auto& vtx = df.getPCACandidate(); - LOGF(info, "vertex x %f", vtx[0]); - hvtx_x_out->Fill(vtx[0]); - hvtx_y_out->Fill(vtx[1]); - hvtx_z_out->Fill(vtx[2]); - o2::track::TrackParCov trackdec0 = df.getTrack(0); - o2::track::TrackParCov trackdec1 = df.getTrack(1); - std::array<float, 3> pvec0; - std::array<float, 3> pvec1; - trackdec0.getPxPyPzGlo(pvec0); - trackdec1.getPxPyPzGlo(pvec1); - float masspion = 0.140; - float masskaon = 0.494; - float mass_ = invmass2prongs(pvec0[0], pvec0[1], pvec0[2], masspion, - pvec1[0], pvec1[1], pvec1[2], masskaon); - float masssw_ = invmass2prongs(pvec0[0], pvec0[1], pvec0[2], masskaon, - pvec1[0], pvec1[1], pvec1[2], masspion); - secvtx2prong(track_0.collisionId(), - collision.posX(), collision.posY(), collision.posZ(), - vtx[0], vtx[1], vtx[2], track_0.globalIndex(), - pvec0[0], pvec0[1], pvec0[2], track_0.y(), - track_1.globalIndex(), pvec1[0], pvec1[1], pvec1[2], track_1.y(), - mass_, masssw_); - hchi2dca->Fill(df.getChi2AtPCACandidate()); - } - } - } -}; - -struct CandidateBuildingDzero { - Produces<aod::Cand2Prong> cand2prong; - void process(aod::SecVtx2Prong const& secVtx2Prongs, - soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) - { - LOGF(info, "NEW EVENT CANDIDATE"); - - o2::vertexing::DCAFitterN<2> df; - df.setBz(5.0); - // After finding the vertex, propagate tracks to the DCA. This is default anyway - df.setPropagateToPCA(true); - // do not consider V0 seeds with 2D circles crossing above this R. This is default anyway - df.setMaxR(200); - // do not consider V0 seeds with tracks Z-distance exceeding this. This is default anyway - df.setMaxDZIni(4); - // stop iterations if max correction is below this value. This is default anyway - df.setMinParamChange(1e-3); - // stop iterations if chi2 improves by less that this factor - df.setMinRelChi2Change(0.9); - - for (auto& secVtx2prong : secVtx2Prongs) { - LOGF(INFO, " ------- new event ---------"); - LOGF(INFO, " track0 y from secvtx tab. %f", secVtx2prong.y0()); - LOGF(INFO, " track0 y from track %f", secVtx2prong.index0().y()); - LOGF(INFO, " track1 y from secvtx table %f", secVtx2prong.y1()); - LOGF(INFO, " track1 y from track %f", secVtx2prong.index1().y()); - - float x0_ = secVtx2prong.index0().x(); - float alpha0_ = secVtx2prong.index0().alpha(); - std::array<float, 5> arraypar0 = {secVtx2prong.index0().y(), secVtx2prong.index0().z(), - secVtx2prong.index0().snp(), secVtx2prong.index0().tgl(), - secVtx2prong.index0().signed1Pt()}; - std::array<float, 15> covpar0 = {secVtx2prong.index0().cYY(), secVtx2prong.index0().cZY(), - secVtx2prong.index0().cZZ(), secVtx2prong.index0().cSnpY(), - secVtx2prong.index0().cSnpZ(), secVtx2prong.index0().cSnpSnp(), - secVtx2prong.index0().cTglY(), secVtx2prong.index0().cTglZ(), - secVtx2prong.index0().cTglSnp(), secVtx2prong.index0().cTglTgl(), - secVtx2prong.index0().c1PtY(), secVtx2prong.index0().c1PtZ(), - secVtx2prong.index0().c1PtSnp(), secVtx2prong.index0().c1PtTgl(), - secVtx2prong.index0().c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar0(x0_, alpha0_, arraypar0, covpar0); - - float x1_ = secVtx2prong.index1().x(); - float alpha1_ = secVtx2prong.index1().alpha(); - std::array<float, 5> arraypar1 = {secVtx2prong.index1().y(), secVtx2prong.index1().z(), - secVtx2prong.index1().snp(), secVtx2prong.index1().tgl(), - secVtx2prong.index1().signed1Pt()}; - std::array<float, 15> covpar1 = {secVtx2prong.index1().cYY(), secVtx2prong.index1().cZY(), - secVtx2prong.index1().cZZ(), secVtx2prong.index1().cSnpY(), - secVtx2prong.index1().cSnpZ(), secVtx2prong.index1().cSnpSnp(), - secVtx2prong.index1().cTglY(), secVtx2prong.index1().cTglZ(), - secVtx2prong.index1().cTglSnp(), secVtx2prong.index1().cTglTgl(), - secVtx2prong.index1().c1PtY(), secVtx2prong.index1().c1PtZ(), - secVtx2prong.index1().c1PtSnp(), secVtx2prong.index1().c1PtTgl(), - secVtx2prong.index1().c1Pt21Pt2()}; - o2::track::TrackParCov trackparvar1(x1_, alpha1_, arraypar1, covpar1); - - df.setUseAbsDCA(true); - //FIXME: currently I rebuild the vertex for each track-track pair and - //select the candidate via its index. It is redundant cause the secondary - //vertex recostruction is performed more than once for each dca candidate - int nCand = df.process(trackparvar0, trackparvar1); - if (nCand == 0) { - LOGF(error, " DCAFitter failing in the candidate building: it should not happen"); - } - const auto& secvtx = df.getPCACandidate(); - float masspion = 0.140; - float masskaon = 0.494; - float mass_ = invmass2prongs(secVtx2prong.px0(), secVtx2prong.py0(), - secVtx2prong.pz0(), masspion, - secVtx2prong.px1(), secVtx2prong.py1(), - secVtx2prong.pz1(), masskaon); - float masssw_ = invmass2prongs(secVtx2prong.px0(), secVtx2prong.py0(), - secVtx2prong.pz0(), masskaon, - secVtx2prong.px1(), secVtx2prong.py1(), - secVtx2prong.pz1(), masspion); - cand2prong(mass_, masssw_); - o2::track::TrackParCov trackdec0 = df.getTrack(0); - o2::track::TrackParCov trackdec1 = df.getTrack(1); - std::array<float, 3> pvec0; - std::array<float, 3> pvec1; - trackdec0.getPxPyPzGlo(pvec0); - trackdec1.getPxPyPzGlo(pvec1); - LOGF(info, "Pt track 0 from table %f and from calc %f", secVtx2prong.px0(), pvec0[0]); - if (abs(secVtx2prong.px0() - pvec0[0]) > 0.000000001) { - LOGF(info, "BIG ERRROR"); - } - } - } -}; - -struct DzeroHistoTask { - // secondary vertex position - OutputObj<TH1F> hvtx_x_outt{TH1F("hvtx_xt", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hvtx_y_outt{TH1F("hvtx_yt", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hvtx_z_outt{TH1F("hvtx_zt", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hmass_nocuts_out{TH1F("hmass_nocuts", "2-track inv mass", 500, 0, 5.0)}; - OutputObj<TH1F> hdecayxy{TH1F("hdecayxy", "decay length xy", 100, 0., 1.0)}; - OutputObj<TH1F> hdecayxyz{TH1F("hdecayxyz", "decay length", 100, 0., 1.0)}; - - void process(soa::Join<aod::Cand2Prong, aod::SecVtx2Prong> const& secVtx2Prongs) - { - LOGF(info, "NEW EVENT"); - - for (auto& secVtx2prong : secVtx2Prongs) { - hvtx_y_outt->Fill(secVtx2prong.posdecayy()); - hvtx_z_outt->Fill(secVtx2prong.posdecayz()); - hvtx_x_outt->Fill(secVtx2prong.posdecayx()); - hvtx_y_outt->Fill(secVtx2prong.posdecayy()); - hvtx_z_outt->Fill(secVtx2prong.posdecayz()); - hdecayxy->Fill(secVtx2prong.decaylengthXY()); - hdecayxyz->Fill(secVtx2prong.decaylength()); - hmass_nocuts_out->Fill(secVtx2prong.mass()); - hmass_nocuts_out->Fill(secVtx2prong.massbar()); - LOGF(info, "new event"); - LOGF(info, "mass %f", secVtx2prong.mass()); - LOGF(info, "mass from cand %f", secVtx2prong.massD0()); - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<DecayVertexBuilder2Prong>("vertexerhf-decayvertexbuilder2prong"), - adaptAnalysisTask<CandidateBuildingDzero>("vertexerhf-candidatebuildingDzero"), - adaptAnalysisTask<DzeroHistoTask>("vertexerhf-Dzerotask")}; -} From 33f8ab7f9d0bab905cbd922f27c502e5db3dc69e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 1 Sep 2020 00:28:41 +0200 Subject: [PATCH 0521/1751] getCircleParams treats as straight track with too small sagitta If sagitta of between the beam-line and the middle of the TPC is <0.01cm, treat the track as straight line instead of circle in XY. --- .../Reconstruction/include/ReconstructionDataFormats/Track.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h index 68d6505f8ede2..10d8533b55a9c 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h @@ -348,7 +348,9 @@ inline void TrackPar::getCircleParamsLoc(float bz, o2::utils::CircleXY& c) const { // get circle params in track local frame, for straight line just set to local coordinates c.rC = getCurvature(bz); - if (std::abs(c.rC) > o2::constants::math::Almost0) { + // treat as straight track if sagitta between the vertex and middle of TPC is below 0.01 cm + constexpr float MinSagitta = 0.01, TPCMidR = 160., MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR); + if (std::abs(c.rC) > MinCurv) { c.rC = 1.f / getCurvature(bz); float sn = getSnp(), cs = sqrtf((1. - sn) * (1. + sn)); c.xC = getX() - sn * c.rC; // center in tracking From 6d492745560029834814b7f876aeea94e5482e16 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 1 Sep 2020 00:31:31 +0200 Subject: [PATCH 0522/1751] Test alt.crossing point if propagation to other fails --- Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h index 74b9830f51784..e270062471c0c 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h @@ -313,7 +313,7 @@ int DCAFitterN<N, Args...>::process(const Tr&... args) if (mUseAbsDCA ? minimizeChi2NoErr() : minimizeChi2()) { mOrder[mCurHyp] = mCurHyp; if (mPropagateToPCA && !propagateTracksToVertex(mCurHyp)) { - return false; + continue; // discard candidate if failed to propagate to it } mCurHyp++; } From 031c78511204fc575377a44b6439be0b58df261b Mon Sep 17 00:00:00 2001 From: noferini <noferini@bo.infn.it> Date: Mon, 31 Aug 2020 14:16:29 +0200 Subject: [PATCH 0523/1751] change TOF digit structure: longBC to InteractionRecord --- Detectors/TOF/base/include/TOFBase/Digit.h | 13 +++++++------ Detectors/TOF/base/src/Digit.cxx | 11 ++++++++--- Detectors/TOF/base/src/WindowFiller.cxx | 7 +++++++ .../TOF/workflow/src/CompressedDecodingTask.cxx | 5 +++-- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index 0e66989d4360d..cfad7f4b6fcfc 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -32,6 +32,7 @@ class Digit Digit() = default; Digit(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t label = -1, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); + Digit(Int_t channel, Int_t tdc, Int_t tot, uint32_t orbit, uint16_t bc, Int_t label = -1, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); ~Digit() = default; /// Get global ordering key made of @@ -41,7 +42,7 @@ class Digit } ULong64_t getOrderingKey() { - return getOrderingKey(mChannel, mBC, mTDC); + return getOrderingKey(mChannel, mIR.toLong(), mTDC); } Int_t getChannel() const { return mChannel; } @@ -53,8 +54,8 @@ class Digit uint16_t getTOT() const { return mTOT; } void setTOT(uint16_t tot) { mTOT = tot; } - uint64_t getBC() const { return mBC; } - void setBC(uint64_t bc) { mBC = bc; } + uint64_t getBC() const { return mIR.toLong(); } + void setBC(uint64_t bc) { mIR.setFromLong(bc); } Int_t getLabel() const { return mLabel; } void setLabel(Int_t label) { mLabel = label; } @@ -91,19 +92,19 @@ class Digit private: friend class boost::serialization::access; - Double_t mCalibratedTime; //!< time of the digits after calibration (not persistent; it will be filled during clusterization) Int_t mChannel; ///< TOF channel index uint16_t mTDC; ///< TDC bin number uint16_t mTOT; ///< TOT bin number - uint64_t mBC; ///< Bunch Crossing // RS: since it is used as absolute bunch counter from orbit 0, it has to be 64 bits + InteractionRecord mIR{0, 0}; ///< InteractionRecord (orbit and bc) when digit occurs Int_t mLabel; ///< Index of the corresponding entry in the MC label array + Double_t mCalibratedTime; //!< time of the digits after calibration (not persistent; it will be filled during clusterization) Int_t mElectronIndex; //!/< index in electronic format uint32_t mTriggerOrbit = 0; //!< orbit id of trigger event // RS: orbit must be 32bits long uint16_t mTriggerBunch = 0; //!< bunch id of trigger event Bool_t mIsUsedInCluster; //!/< flag to declare that the digit was used to build a cluster Bool_t mIsProblematic = false; //!< flag to tell whether the channel of the digit was problemati; not persistent; default = ok - ClassDefNV(Digit, 3); + ClassDefNV(Digit, 4); }; std::ostream& operator<<(std::ostream& stream, const Digit& dig); diff --git a/Detectors/TOF/base/src/Digit.cxx b/Detectors/TOF/base/src/Digit.cxx index 9d2503287cd50..a019e61d6b32d 100644 --- a/Detectors/TOF/base/src/Digit.cxx +++ b/Detectors/TOF/base/src/Digit.cxx @@ -17,15 +17,20 @@ using namespace o2::tof; ClassImp(o2::tof::Digit); Digit::Digit(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t label, uint32_t triggerorbit, uint16_t triggerbunch) - : mChannel(channel), mTDC(tdc), mTOT(tot), mBC(bc), mLabel(label), mTriggerOrbit(triggerorbit), mTriggerBunch(triggerbunch), mIsUsedInCluster(kFALSE) + : mChannel(channel), mTDC(tdc), mTOT(tot), mIR(0, 0), mLabel(label), mTriggerOrbit(triggerorbit), mTriggerBunch(triggerbunch), mIsUsedInCluster(kFALSE) +{ + mIR.setFromLong(bc); +} +//______________________________________________________________________ +Digit::Digit(Int_t channel, Int_t tdc, Int_t tot, uint32_t orbit, uint16_t bc, Int_t label, uint32_t triggerorbit, uint16_t triggerbunch) + : mChannel(channel), mTDC(tdc), mTOT(tot), mIR(bc, orbit), mLabel(label), mTriggerOrbit(triggerorbit), mTriggerBunch(triggerbunch), mIsUsedInCluster(kFALSE) { } - //______________________________________________________________________ void Digit::printStream(std::ostream& stream) const { - stream << "TOF Digit: Channel " << mChannel << " TDC " << mTDC << " TOT " << mTOT << "Bunch Crossing index" << mBC << " Label " << mLabel << "\n"; + stream << "TOF Digit: Channel " << mChannel << " TDC " << mTDC << " TOT " << mTOT << "Bunch Crossing index" << mIR.toLong() << " Label " << mLabel << "\n"; } //______________________________________________________________________ diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index ff357c69caeaa..12d633295015f 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -175,6 +175,13 @@ void WindowFiller::flushOutputContainer(std::vector<Digit>& digits) for (Int_t i = 0; i < MAXWINDOWS; i++) { fillOutputContainer(digits); // fill last readout windows } + + int nwindowperTF = o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * Geo::NWINDOW_IN_ORBIT; + + // check that all orbits are complete in terms of number of readout windows + while ((mReadoutWindowData.size() % nwindowperTF)) { + fillOutputContainer(digits); // fill windows without digits to complete all orbits in the last TF + } } } //______________________________________________________________________ diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 8c1e11fda9009..fd2e4a4733112 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -52,8 +52,6 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) mHasToBePosted = false; mDecoder.FillWindows(); - int nwindowperTF = o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * 3; - // send output message std::vector<o2::tof::Digit>* alldigits = mDecoder.getDigitPerTimeFrame(); std::vector<o2::tof::ReadoutWindowData>* row = mDecoder.getReadoutWindowData(); @@ -67,6 +65,8 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) lastIR = last->mFirstIR; } + /* + int nwindowperTF = o2::raw::HBFUtils::Instance().getNOrbitsPerTF() * 3; while (row->size() < nwindowperTF) { // complete timeframe with empty readout windows auto& dummy = row->emplace_back(lastval, 0); @@ -76,6 +76,7 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) // remove extra readout windows after a check they are empty row->pop_back(); } +*/ int n_tof_window = row->size(); int n_orbits = n_tof_window / 3; From 031a3cd6abd8bbe7f9ecaa9e705f8f48e830ca87 Mon Sep 17 00:00:00 2001 From: Raymond Ehlers <raymond.ehlers@gmail.com> Date: Sun, 30 Aug 2020 20:38:19 +0200 Subject: [PATCH 0524/1751] [EMCAL-651] Add const for cell indices in cluster The indices aren't modified, so const is appropriate. Further, this makes the interface more consistent for converting clusters from the clusterizer into analysis clusters. --- .../base/include/EMCALBase/ClusterFactory.h | 26 +++++++++---------- Detectors/EMCAL/base/src/ClusterFactory.cxx | 22 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h index dbed03b9be585..d6e0e1e1ec99a 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h +++ b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h @@ -178,7 +178,7 @@ class ClusterFactory /// \param clustersContainer cluster container /// \param inputsContainer cells/digits container /// \param cellsIndices for cells/digits indices - ClusterFactory(gsl::span<const o2::emcal::Cluster> clustersContainer, gsl::span<const InputType> inputsContainer, gsl::span<int> cellsIndices); + ClusterFactory(gsl::span<const o2::emcal::Cluster> clustersContainer, gsl::span<const InputType> inputsContainer, gsl::span<const int> cellsIndices); /// /// Copy constructor @@ -225,17 +225,17 @@ class ClusterFactory /// /// Calculates the center of gravity in the local EMCAL-module coordinates - void evalLocalPosition(gsl::span<int> inputsIndices, AnalysisCluster& cluster) const; + void evalLocalPosition(gsl::span<const int> inputsIndices, AnalysisCluster& cluster) const; /// /// Calculates the center of gravity in the global ALICE coordinates - void evalGlobalPosition(gsl::span<int> inputsIndices, AnalysisCluster& cluster) const; + void evalGlobalPosition(gsl::span<const int> inputsIndices, AnalysisCluster& cluster) const; void evalLocal2TrackingCSTransform() const; /// /// evaluates local position of clusters in SM - void evalLocalPositionFit(Double_t deff, Double_t w0, Double_t phiSlope, gsl::span<int> inputsIndices, AnalysisCluster& cluster) const; + void evalLocalPositionFit(Double_t deff, Double_t w0, Double_t phiSlope, gsl::span<const int> inputsIndices, AnalysisCluster& cluster) const; /// /// Applied for simulation data with threshold 3 adc @@ -250,11 +250,11 @@ class ClusterFactory /// \return the index of the cells with max enegry /// \return the maximum energy /// \return the total energy of the cluster - std::tuple<int, float, float> getMaximalEnergyIndex(gsl::span<int> inputsIndices) const; + std::tuple<int, float, float> getMaximalEnergyIndex(gsl::span<const int> inputsIndices) const; /// /// Calculates the multiplicity of digits/cells with energy larger than level*energy - int getMultiplicityAtLevel(float level, gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const; + int getMultiplicityAtLevel(float level, gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const; int getSuperModuleNumber() const { return mSuperModuleNumber; } @@ -287,7 +287,7 @@ class ClusterFactory mInputsContainer = cellContainer; } - void setCellsIndicesContainer(gsl::span<int> indicesContainer) + void setCellsIndicesContainer(gsl::span<const int> indicesContainer) { mCellsIndices = indicesContainer; } @@ -305,21 +305,21 @@ class ClusterFactory /// should be less than 2% /// Unfinished - Nov 15,2006 /// Distance is calculate in (phi,eta) units - void evalCoreEnergy(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const; + void evalCoreEnergy(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const; /// /// Calculates the dispersion of the shower at the origin of the cluster /// in cell units - void evalDispersion(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const; + void evalDispersion(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const; /// /// Calculates the axis of the shower ellipsoid in eta and phi /// in cell units - void evalElipsAxis(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const; + void evalElipsAxis(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const; /// /// Time is set to the time of the digit with the maximum energy - void evalTime(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const; + void evalTime(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const; /// /// Converts Theta (Radians) to Eta (Radians) @@ -344,9 +344,9 @@ class ClusterFactory gsl::span<const o2::emcal::Cluster> mClustersContainer; ///< Container for all the clusters in the event gsl::span<const InputType> mInputsContainer; ///< Container for all the cells/digits in the event - gsl::span<int> mCellsIndices; ///< Container for cells indices in the event + gsl::span<const int> mCellsIndices; ///< Container for cells indices in the event - ClassDefNV(ClusterFactory, 1); + ClassDefNV(ClusterFactory, 2); }; } // namespace emcal diff --git a/Detectors/EMCAL/base/src/ClusterFactory.cxx b/Detectors/EMCAL/base/src/ClusterFactory.cxx index 3232466da7d43..2ab67b1e0b783 100644 --- a/Detectors/EMCAL/base/src/ClusterFactory.cxx +++ b/Detectors/EMCAL/base/src/ClusterFactory.cxx @@ -25,7 +25,7 @@ using namespace o2::emcal; template <class InputType> -ClusterFactory<InputType>::ClusterFactory(gsl::span<const o2::emcal::Cluster> clustersContainer, gsl::span<const InputType> inputsContainer, gsl::span<int> cellsIndices) +ClusterFactory<InputType>::ClusterFactory(gsl::span<const o2::emcal::Cluster> clustersContainer, gsl::span<const InputType> inputsContainer, gsl::span<const int> cellsIndices) { setClustersContainer(clustersContainer); setCellsContainer(inputsContainer); @@ -55,7 +55,7 @@ o2::emcal::AnalysisCluster ClusterFactory<InputType>::buildCluster(int clusterIn int firstCellIndex = mClustersContainer[clusterIndex].getCellIndexFirst(); int nCells = mClustersContainer[clusterIndex].getNCells(); - gsl::span<int> inputsIndices = gsl::span<int>(&mCellsIndices[firstCellIndex], nCells); + gsl::span<const int> inputsIndices = gsl::span<const int>(&mCellsIndices[firstCellIndex], nCells); // First calculate the index of input with maximum amplitude and get // the supermodule number where it sits. @@ -107,7 +107,7 @@ o2::emcal::AnalysisCluster ClusterFactory<InputType>::buildCluster(int clusterIn /// in cell units //____________________________________________________________________________ template <class InputType> -void ClusterFactory<InputType>::evalDispersion(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const +void ClusterFactory<InputType>::evalDispersion(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { double d = 0., wtot = 0.; int nstat = 0; @@ -180,7 +180,7 @@ void ClusterFactory<InputType>::evalDispersion(gsl::span<int> inputsIndices, Ana /// Calculates the center of gravity in the local EMCAL-module coordinates //____________________________________________________________________________ template <class InputType> -void ClusterFactory<InputType>::evalLocalPosition(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const +void ClusterFactory<InputType>::evalLocalPosition(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { int nstat = 0; @@ -249,7 +249,7 @@ void ClusterFactory<InputType>::evalLocalPosition(gsl::span<int> inputsIndices, /// Calculates the center of gravity in the global ALICE coordinates //____________________________________________________________________________ template <class InputType> -void ClusterFactory<InputType>::evalGlobalPosition(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const +void ClusterFactory<InputType>::evalGlobalPosition(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { int i = 0, nstat = 0; @@ -319,7 +319,7 @@ void ClusterFactory<InputType>::evalGlobalPosition(gsl::span<int> inputsIndices, //____________________________________________________________________________ template <class InputType> void ClusterFactory<InputType>::evalLocalPositionFit(double deff, double mLogWeight, - double phiSlope, gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const + double phiSlope, gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { int i = 0, nstat = 0; double clXYZ[3] = {0., 0., 0.}, clRmsXYZ[3] = {0., 0., 0.}, xyzi[3], wtot = 0., w = 0.; @@ -416,7 +416,7 @@ void ClusterFactory<InputType>::getDeffW0(const double esum, double& deff, doubl /// Distance is calculate in (phi,eta) units //______________________________________________________________________________ template <class InputType> -void ClusterFactory<InputType>::evalCoreEnergy(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const +void ClusterFactory<InputType>::evalCoreEnergy(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { float coreEnergy = 0.; @@ -444,7 +444,7 @@ void ClusterFactory<InputType>::evalCoreEnergy(gsl::span<int> inputsIndices, Ana /// in cell units //____________________________________________________________________________ template <class InputType> -void ClusterFactory<InputType>::evalElipsAxis(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const +void ClusterFactory<InputType>::evalElipsAxis(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { TString gn(mGeomPtr->GetName()); @@ -521,7 +521,7 @@ void ClusterFactory<InputType>::evalElipsAxis(gsl::span<int> inputsIndices, Anal /// Finds the maximum energy in the cluster and computes the Summed amplitude of digits/cells //____________________________________________________________________________ template <class InputType> -std::tuple<int, float, float> ClusterFactory<InputType>::getMaximalEnergyIndex(gsl::span<int> inputsIndices) const +std::tuple<int, float, float> ClusterFactory<InputType>::getMaximalEnergyIndex(gsl::span<const int> inputsIndices) const { float energy = 0.; @@ -544,7 +544,7 @@ std::tuple<int, float, float> ClusterFactory<InputType>::getMaximalEnergyIndex(g /// Calculates the multiplicity of inputs with energy larger than H*energy //____________________________________________________________________________ template <class InputType> -int ClusterFactory<InputType>::getMultiplicityAtLevel(float H, gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const +int ClusterFactory<InputType>::getMultiplicityAtLevel(float H, gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { int multipl = 0; for (auto iInput : inputsIndices) { @@ -559,7 +559,7 @@ int ClusterFactory<InputType>::getMultiplicityAtLevel(float H, gsl::span<int> in /// Time is set to the time of the input with the maximum energy //____________________________________________________________________________ template <class InputType> -void ClusterFactory<InputType>::evalTime(gsl::span<int> inputsIndices, AnalysisCluster& clusterAnalysis) const +void ClusterFactory<InputType>::evalTime(gsl::span<const int> inputsIndices, AnalysisCluster& clusterAnalysis) const { float maxE = 0; unsigned short maxAt = 0; From 3dd2eb97a459c8b533a30052be973464a3fe0621 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 1 Sep 2020 16:59:38 +0200 Subject: [PATCH 0525/1751] DPL Analysis: fix for filtered grouping --- Framework/Core/include/Framework/ASoA.h | 2 +- Framework/Core/include/Framework/AnalysisTask.h | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 6d428062d725d..8072b53168f42 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1706,7 +1706,7 @@ class Filtered<Filtered<T>> : public FilteredPolicy<typename T::table_t> }; template <typename T> -using is_soa_filtered_t = typename framework::is_specialization<T, soa::Filtered>; +using is_soa_filtered_t = typename framework::is_base_of_template<soa::FilteredPolicy, T>; template <typename T> auto filter(T&& t, framework::expressions::Filter const& expr) diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 6f7a297127587..80272907e3624 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -890,9 +890,11 @@ struct AnalysisDataProcessorBuilder { { constexpr auto index = framework::has_type_at<A1>(associated_pack_t{}); if (hasIndexTo<G>(typename std::decay_t<A1>::persistent_columns_t{})) { - auto pos = position; + uint64_t pos; if constexpr (soa::is_soa_filtered_t<std::decay_t<G>>::value) { - pos = groupSelection[position]; + pos = (*groupSelection)[position]; + } else { + pos = position; } if constexpr (soa::is_soa_filtered_t<std::decay_t<A1>>::value) { auto groupedElementsTable = arrow::util::get<std::shared_ptr<arrow::Table>>(((groups[index])[pos]).value); @@ -923,7 +925,7 @@ struct AnalysisDataProcessorBuilder { std::tuple<A...>* mAt; typename grouping_t::iterator mGroupingElement; uint64_t position = 0; - soa::SelectionVector* groupSelection = nullptr; + soa::SelectionVector const* groupSelection = nullptr; std::array<std::vector<arrow::Datum>, sizeof...(A)> groups; std::array<std::vector<uint64_t>, sizeof...(A)> offsets; From 46648d67c368c3dca6762172c295342df167a506 Mon Sep 17 00:00:00 2001 From: LucasNL <nunes.lopes@ufrgs.br> Date: Fri, 28 Aug 2020 14:06:46 -0300 Subject: [PATCH 0526/1751] Adapted CheckTopologies for MFT --- Detectors/ITSMFT/MFT/macros/CMakeLists.txt | 1 + .../ITSMFT/MFT/macros/test/CMakeLists.txt | 19 ++ .../ITSMFT/MFT/macros/test/CheckTopologies.C | 292 ++++++++++++++++++ 3 files changed, 312 insertions(+) create mode 100644 Detectors/ITSMFT/MFT/macros/test/CMakeLists.txt create mode 100644 Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C diff --git a/Detectors/ITSMFT/MFT/macros/CMakeLists.txt b/Detectors/ITSMFT/MFT/macros/CMakeLists.txt index 261554a493d41..016c6ec06431e 100644 --- a/Detectors/ITSMFT/MFT/macros/CMakeLists.txt +++ b/Detectors/ITSMFT/MFT/macros/CMakeLists.txt @@ -9,3 +9,4 @@ # submit itself to any jurisdiction. add_subdirectory(mapping) +add_subdirectory(test) diff --git a/Detectors/ITSMFT/MFT/macros/test/CMakeLists.txt b/Detectors/ITSMFT/MFT/macros/test/CMakeLists.txt new file mode 100644 index 0000000000000..dc80010644a91 --- /dev/null +++ b/Detectors/ITSMFT/MFT/macros/test/CMakeLists.txt @@ -0,0 +1,19 @@ +# 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_test_root_macro(CheckTopologies.C + PUBLIC_LINK_LIBRARIES O2::MathUtils + O2::MFTBase + O2::ITSMFTReconstruction + O2::ITSMFTSimulation + O2::DataFormatsITSMFT + O2::SimulationDataFormat + LABELS mft) + diff --git a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C new file mode 100644 index 0000000000000..f23568d16510b --- /dev/null +++ b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C @@ -0,0 +1,292 @@ +/// \file CheckTopologies.C +/// Macros to test the generation of a dictionary of topologies. Three dictionaries are generated: one with signal-cluster only, one with noise-clusters only and one with all the clusters. + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include <TAxis.h> +#include <TCanvas.h> +#include <TSystem.h> +#include <TFile.h> +#include <TH1F.h> +#include <TH2F.h> +#include <TNtuple.h> +#include <TString.h> +#include <TStyle.h> +#include <TTree.h> +#include <TStopwatch.h> +#include <fstream> +#include <string> + +#include "MathUtils/Utils.h" +#include "MFTBase/GeometryTGeo.h" +#include "ITSMFTReconstruction/BuildTopologyDictionary.h" +#include "DataFormatsITSMFT/CompCluster.h" +#include "DataFormatsITSMFT/ClusterTopology.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "ITSMFTSimulation/Hit.h" +#include "MathUtils/Cartesian3D.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "SimulationDataFormat/DigitizationContext.h" +#include "Framework/Logger.h" +#include <unordered_map> +#endif + +void CheckTopologies(std::string clusfile = "mftclusters.root", + std::string hitfile = "o2sim_HitsMFT.root", + std::string collContextfile = "collisioncontext.root", + std::string inputGeom = "") +{ + const int QEDSourceID = 99; // Clusters from this MC source correspond to QED electrons + + using namespace o2::base; + using namespace o2::mft; + + using o2::itsmft::BuildTopologyDictionary; + using o2::itsmft::ClusterTopology; + using o2::itsmft::CompCluster; + using o2::itsmft::CompClusterExt; + using o2::itsmft::Hit; + using ROFRec = o2::itsmft::ROFRecord; + using MC2ROF = o2::itsmft::MC2ROFRecord; + using HitVec = std::vector<Hit>; + using MC2HITS_map = std::unordered_map<uint64_t, int>; // maps (track_ID<<16 + chip_ID) to entry in the hit vector + std::unordered_map<int, int> hadronicMCMap; // mapping from MC event entry to hadronic event ID + std::vector<HitVec*> hitVecPool; + std::vector<MC2HITS_map> mc2hitVec; + const o2::steer::DigitizationContext* digContext = nullptr; + TStopwatch sw; + sw.Start(); + + // Geometry + o2::base::GeometryManager::loadGeometry(inputGeom); + auto gman = o2::mft::GeometryTGeo::Instance(); + gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, + o2::TransformType::L2G)); // request cached transforms + + // Hits + TFile* fileH = nullptr; + TTree* hitTree = nullptr; + + if (!hitfile.empty() && !collContextfile.empty() && !gSystem->AccessPathName(hitfile.c_str()) && !gSystem->AccessPathName(collContextfile.c_str())) { + fileH = TFile::Open(hitfile.data()); + hitTree = (TTree*)fileH->Get("o2sim"); + mc2hitVec.resize(hitTree->GetEntries()); + hitVecPool.resize(hitTree->GetEntries(), nullptr); + digContext = o2::steer::DigitizationContext::loadFromFile(collContextfile); + + auto& intGlo = digContext->getEventParts(digContext->isQEDProvided()); + int hadrID = -1, nGlo = intGlo.size(), nHadro = 0; + for (int iglo = 0; iglo < nGlo; iglo++) { + const auto& parts = intGlo[iglo]; + bool found = false; + for (auto& part : parts) { + if (part.sourceID == 0) { // we use underlying background + hadronicMCMap[iglo] = part.entryID; + found = true; + nHadro++; + break; + } + } + if (!found) { + hadronicMCMap[iglo] = -1; + } + } + if (nHadro < hitTree->GetEntries()) { + LOG(FATAL) << "N=" << nHadro << " hadronic events < " + << " N=" << hitTree->GetEntries() << " Hit enties."; + } + } + + // Clusters + TFile* fileCl = TFile::Open(clusfile.data()); + TTree* clusTree = (TTree*)fileCl->Get("o2sim"); + std::vector<CompClusterExt>* clusArr = nullptr; + clusTree->SetBranchAddress("MFTClusterComp", &clusArr); + std::vector<unsigned char>* patternsPtr = nullptr; + auto pattBranch = clusTree->GetBranch("MFTClusterPatt"); + if (pattBranch) { + pattBranch->SetAddress(&patternsPtr); + } + + // ROFrecords + std::vector<ROFRec> rofRecVec, *rofRecVecP = &rofRecVec; + clusTree->SetBranchAddress("MFTClustersROF", &rofRecVecP); + + // Cluster MC labels + o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clusLabArr = nullptr; + std::vector<MC2ROF> mc2rofVec, *mc2rofVecP = &mc2rofVec; + if (hitTree && clusTree->GetBranch("MFTClusterMCTruth")) { + clusTree->SetBranchAddress("MFTClusterMCTruth", &clusLabArr); + clusTree->SetBranchAddress("MFTClustersMC2ROF", &mc2rofVecP); + } + clusTree->GetEntry(0); + + // Topologies dictionaries: 1) all clusters 2) signal clusters only 3) noise clusters only + BuildTopologyDictionary completeDictionary; + BuildTopologyDictionary signalDictionary; + BuildTopologyDictionary noiseDictionary; + + int nROFRec = (int)rofRecVec.size(); + std::vector<int> mcEvMin, mcEvMax; + + if (clusLabArr) { // >> build min and max MC events used by each ROF + mcEvMin.resize(nROFRec, hitTree->GetEntries()); + mcEvMax.resize(nROFRec, -1); + for (int imc = mc2rofVec.size(); imc--;) { + int hadrID = hadronicMCMap[imc]; + if (hadrID < 0) { + continue; + } + const auto& mc2rof = mc2rofVec[imc]; + if (mc2rof.rofRecordID < 0) { + continue; // this MC event did not contribute to any ROF + } + for (int irfd = mc2rof.maxROF - mc2rof.minROF + 1; irfd--;) { + int irof = mc2rof.rofRecordID + irfd; + if (mcEvMin[irof] > hadrID) { + mcEvMin[irof] = hadrID; + } + if (mcEvMax[irof] < hadrID) { + mcEvMax[irof] = hadrID; + } + } + } + } // << build min and max MC events used by each ROF + + auto pattIdx = patternsPtr->cbegin(); + for (int irof = 0; irof < nROFRec; irof++) { + const auto& rofRec = rofRecVec[irof]; + + rofRec.print(); + + if (clusLabArr) { // >> read and map MC events contributing to this ROF + for (int im = mcEvMin[irof]; im <= mcEvMax[irof]; im++) { + if (!hitVecPool[im]) { + hitTree->SetBranchAddress("MFTHit", &hitVecPool[im]); + hitTree->GetEntry(im); + auto& mc2hit = mc2hitVec[im]; + const auto* hitArray = hitVecPool[im]; + for (int ih = hitArray->size(); ih--;) { + const auto& hit = (*hitArray)[ih]; + uint64_t key = (uint64_t(hit.GetTrackID()) << 32) + hit.GetDetectorID(); + mc2hit.emplace(key, ih); + } + } + } + } // << cache MC events contributing to this ROF + + for (int icl = 0; icl < rofRec.getNEntries(); icl++) { + int clEntry = rofRec.getFirstEntry() + icl; // entry of icl-th cluster of this ROF in the vector of clusters + // do we read MC data? + + const auto& cluster = (*clusArr)[clEntry]; + + if (cluster.getPatternID() != CompCluster::InvalidPatternID) { + LOG(WARNING) << "Encountered patternID = " << cluster.getPatternID() << " != " << CompCluster::InvalidPatternID; + LOG(WARNING) << "Clusters have already been generated with a dictionary! Quitting"; + return; + } + + ClusterTopology topology; + o2::itsmft::ClusterPattern pattern(pattIdx); + topology.setPattern(pattern); + + float dX = BuildTopologyDictionary::IgnoreVal, dZ = BuildTopologyDictionary::IgnoreVal; + if (clusLabArr) { + const auto& lab = (clusLabArr->getLabels(clEntry))[0]; + auto srcID = lab.getSourceID(); + if (lab.isValid() && srcID != QEDSourceID) { // use MC truth info only for non-QED and non-noise clusters + auto trID = lab.getTrackID(); + const auto& mc2hit = mc2hitVec[lab.getEventID()]; + const auto* hitArray = hitVecPool[lab.getEventID()]; + Int_t chipID = cluster.getSensorID(); + uint64_t key = (uint64_t(trID) << 32) + chipID; + auto hitEntry = mc2hit.find(key); + if (hitEntry != mc2hit.end()) { + const auto& hit = (*hitArray)[hitEntry->second]; + auto locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local + auto locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); + locH.SetXYZ(0.5 * (locH.X() + locHsta.X()), 0.5 * (locH.Y() + locHsta.Y()), 0.5 * (locH.Z() + locHsta.Z())); + const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern); + dX = locH.X() - locC.X(); + dZ = locH.Z() - locC.Z(); + } else { + printf("Failed to find MC hit entry for Tr:%d chipID:%d\n", trID, chipID); + lab.print(); + } + signalDictionary.accountTopology(topology, dX, dZ); + } else { + noiseDictionary.accountTopology(topology, dX, dZ); + } + } + completeDictionary.accountTopology(topology, dX, dZ); + } + // clean MC cache for events which are not needed anymore + if (clusLabArr) { + int irfNext = irof; + int limMC = irfNext == nROFRec ? hitVecPool.size() : mcEvMin[irfNext]; // can clean events up to this + for (int imc = mcEvMin[irof]; imc < limMC; imc++) { + delete hitVecPool[imc]; + hitVecPool[imc] = nullptr; + mc2hitVec[imc].clear(); + } + } + } + auto dID = o2::detectors::DetID::MFT; + + completeDictionary.setThreshold(0.0001); + completeDictionary.groupRareTopologies(); + completeDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "", ".bin")); + completeDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "", ".txt")); + completeDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "", ".root")); + + TFile histogramOutput("histograms.root", "recreate"); + TCanvas* cComplete = new TCanvas("cComplete", "Distribution of all the topologies"); + cComplete->cd(); + cComplete->SetLogy(); + TH1F* hComplete = nullptr; + o2::itsmft::TopologyDictionary::getTopologyDistribution(completeDictionary.getDictionary(), hComplete, "hComplete"); + hComplete->SetDirectory(0); + hComplete->Draw("hist"); + hComplete->Write(); + cComplete->Write(); + + TCanvas* cNoise = nullptr; + TCanvas* cSignal = nullptr; + TH1F* hNoise = nullptr; + TH1F* hSignal = nullptr; + + if (clusLabArr) { + noiseDictionary.setThreshold(0.0001); + noiseDictionary.groupRareTopologies(); + noiseDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".bin")); + noiseDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".txt")); + noiseDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "noise", ".root")); + signalDictionary.setThreshold(0.0001); + signalDictionary.groupRareTopologies(); + signalDictionary.printDictionaryBinary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".bin")); + signalDictionary.printDictionary(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".txt")); + signalDictionary.saveDictionaryRoot(o2::base::NameConf::getDictionaryFileName(dID, "signal", ".root")); + cNoise = new TCanvas("cNoise", "Distribution of noise topologies"); + cNoise->cd(); + cNoise->SetLogy(); + o2::itsmft::TopologyDictionary::getTopologyDistribution(noiseDictionary.getDictionary(), hNoise, "hNoise"); + hNoise->SetDirectory(0); + hNoise->Draw("hist"); + histogramOutput.cd(); + hNoise->Write(); + cNoise->Write(); + cSignal = new TCanvas("cSignal", "cSignal"); + cSignal->cd(); + cSignal->SetLogy(); + o2::itsmft::TopologyDictionary::getTopologyDistribution(signalDictionary.getDictionary(), hSignal, "hSignal"); + hSignal->SetDirectory(0); + hSignal->Draw("hist"); + histogramOutput.cd(); + hSignal->Write(); + cSignal->Write(); + sw.Stop(); + sw.Print(); + } +} From 405307cb60da98defa79555f3cc4ad83f3414ea5 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Tue, 25 Aug 2020 16:58:09 +0200 Subject: [PATCH 0527/1751] MFT: fill vector tree with cluster external indices --- .../MFT/include/DataFormatsMFT/TrackMFT.h | 61 +++++------------ .../tracking/include/MFTTracking/Cluster.h | 4 +- .../tracking/include/MFTTracking/ROframe.h | 5 +- .../tracking/include/MFTTracking/TrackCA.h | 67 ++++++++++--------- .../tracking/include/MFTTracking/Tracker.h | 2 +- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 8 ++- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 27 ++++---- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 60 ++++++++++------- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 10 ++- 9 files changed, 113 insertions(+), 131 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h index cdf7a2160ad05..bcd6cd04b77f5 100644 --- a/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h +++ b/DataFormats/Detectors/ITSMFT/MFT/include/DataFormatsMFT/TrackMFT.h @@ -53,44 +53,25 @@ class TrackMFT : public o2::track::TrackParCovFwd void setChi2QPtSeed(Double_t chi2) { mSeedinvQPtFitChi2 = chi2; } const Double_t getChi2QPtSeed() const { return mSeedinvQPtFitChi2; } - // Other functions - int getNumberOfClusters() const { return mClusRef.getEntries(); } - int getFirstClusterEntry() const { return mClusRef.getFirstEntry(); } - int getClusterEntry(int i) const { return getFirstClusterEntry() + i; } - void shiftFirstClusterEntry(int bias) - { - mClusRef.setFirstEntry(mClusRef.getFirstEntry() + bias); - } - void setFirstClusterEntry(int offs) - { - mClusRef.setFirstEntry(offs); - } - void setNumberOfClusters(int n) - { - mClusRef.setEntries(n); - } - void setClusterRefs(int firstEntry, int n) - { - mClusRef.set(firstEntry, n); - } - - const ClusRefs& getClusterRefs() const { return mClusRef; } - ClusRefs& getClusterRefs() { return mClusRef; } - std::uint32_t getROFrame() const { return mROFrame; } void setROFrame(std::uint32_t f) { mROFrame = f; } - const Int_t getNPoints() const { return mNPoints; } + const int getNumberOfPoints() const { return mClusRef.getEntries(); } + + const int getExternalClusterIndexOffset() const { return mClusRef.getFirstEntry(); } + + void setExternalClusterIndexOffset(int offset = 0) { mClusRef.setFirstEntry(offset); } + + void setNumberOfPoints(int n) { mClusRef.setEntries(n); } void print() const; - const o2::track::TrackParCovFwd& GetOutParam() const { return mOutParameters; } - void SetOutParam(const o2::track::TrackParCovFwd parcov) { mOutParameters = parcov; } + const o2::track::TrackParCovFwd& getOutParam() const { return mOutParameters; } + void setOutParam(const o2::track::TrackParCovFwd parcov) { mOutParameters = parcov; } private: - std::uint32_t mROFrame = 0; ///< RO Frame - Int_t mNPoints{0}; // Number of clusters - Bool_t mIsCA = false; // Track finding method CA vs. LTF + std::uint32_t mROFrame = 0; ///< RO Frame + Bool_t mIsCA = false; // Track finding method CA vs. LTF ClusRefs mClusRef; ///< references on clusters @@ -114,24 +95,16 @@ class TrackMFTExt : public TrackMFT static constexpr int MaxClusters = 10; using TrackMFT::TrackMFT; // inherit base constructors - void setClusterIndex(int l, int i, int ncl) - { - mIndex[ncl] = (l << 27) + i; - getClusterRefs().setEntries(ncl); - } - - int getClusterIndex(int lr) const { return mIndex[lr]; } + int getExternalClusterIndex(int i) const { return mExtClsIndex[i]; } - void setExternalClusterIndex(int layer, int idx, bool newCluster = false) + void setExternalClusterIndex(int np, int idx) { - if (newCluster) { - getClusterRefs().setEntries(getNumberOfClusters() + 1); - } - mIndex[layer] = idx; + mExtClsIndex[np] = idx; } - private: - std::array<int, MaxClusters> mIndex = {-1}; ///< Indices of associated clusters + protected: + std::array<int, MaxClusters> mExtClsIndex = {-1}; ///< External indices of associated clusters + ClassDefNV(TrackMFTExt, 1); }; } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index 50478f827fd53..5dc5e4a16740d 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -26,11 +26,11 @@ namespace mft { struct Cluster : public o2::BaseCluster<float> { - Cluster(const Float_t x, const Float_t y, const Float_t z, const Float_t phi, const Float_t r, const Int_t idx, const Int_t bin, const Float_t sigX2, const Float_t sigY2, const Int_t sensorID) + Cluster(const Float_t x, const Float_t y, const Float_t z, const Float_t phi, const Float_t r, const Int_t id, const Int_t bin, const Float_t sigX2, const Float_t sigY2, const Int_t sensorID) : BaseCluster(sensorID, x, y, z), phiCoordinate{phi}, rCoordinate{r}, - clusterId{idx}, + clusterId{id}, indexTableBin{bin}, sigmaX2{sigX2}, sigmaY2{sigY2} {}; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h index e7d062eb0cfa5..f6f0b039a8ad8 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h @@ -52,10 +52,10 @@ class ROframe final const std::vector<Cluster>& getClustersInLayer(Int_t layerId) const { return mClusters[layerId]; } const MCCompLabel& getClusterLabels(Int_t layerId, const Cluster& cl) const { return mClusterLabels[layerId][cl.clusterId]; } - const MCCompLabel& getClusterLabels(Int_t layerId, const Int_t clId) const { return mClusterLabels[layerId][clId]; } + const MCCompLabel& getClusterLabels(Int_t layerId, const Int_t clusterId) const { return mClusterLabels[layerId][clusterId]; } const std::map<Int_t, std::pair<Int_t, Int_t>>& getClusterBinIndexRange(Int_t layerId) const { return mClusterBinIndexRange[layerId]; } - Int_t getClusterExternalIndex(Int_t layerId, const Int_t clId) const { return mClusterExternalIndices[layerId][clId]; } + const Int_t getClusterExternalIndex(Int_t layerId, const Int_t clusterId) const { return mClusterExternalIndices[layerId][clusterId]; } const std::array<std::vector<Cell>, constants::mft::LayersNumber>& getCells() const; const std::vector<Cell>& getCellsInLayer(Int_t layerId) const { return mCells[layerId]; } @@ -135,7 +135,6 @@ inline Bool_t ROframe::isClusterUsed(Int_t layer, Int_t clusterId) const inline void ROframe::markUsedCluster(Int_t layer, Int_t clusterId) { mUsedClusters[layer][clusterId] = kTRUE; } - inline TrackLTF& ROframe::getCurrentTrackLTF() { return mTracksLTF.back(); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index 4412127322c27..19f27a6a19f55 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -33,7 +33,6 @@ class TrackLTF : public TrackMFTExt TrackLTF() = default; TrackLTF(const TrackLTF& t) = default; ~TrackLTF() = default; - const Int_t getNPoints() const { return mNPoints; } const std::array<Float_t, constants::mft::LayersNumber>& getXCoordinates() const { return mX; } const std::array<Float_t, constants::mft::LayersNumber>& getYCoordinates() const { return mY; } const std::array<Float_t, constants::mft::LayersNumber>& getZCoordinates() const { return mZ; } @@ -42,13 +41,10 @@ class TrackLTF : public TrackMFTExt const std::array<Int_t, constants::mft::LayersNumber>& getLayers() const { return mLayer; } const std::array<Int_t, constants::mft::LayersNumber>& getClustersId() const { return mClusterId; } const std::array<MCCompLabel, constants::mft::LayersNumber>& getMCCompLabels() const { return mMCCompLabels; } - void setPoint(const Cluster, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); + void setPoint(const Cluster, const Int_t layer, const Int_t clusterId, const MCCompLabel label, const Int_t extClsIndex, Bool_t& newPoint); void sort(); - protected: - Int_t mNPoints{0}; - private: std::array<Float_t, constants::mft::LayersNumber> mX = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; std::array<Float_t, constants::mft::LayersNumber> mY = {-25., -25., -25., -25., -25., -25., -25., -25., -25., -25.}; @@ -105,46 +101,48 @@ inline void TrackCA::removeLastCell(Int_t& layer, Int_t& cellId) layer = mCellLayer[mNCells - 1]; cellId = mCellId[mNCells - 1]; - if (mNPoints == 2) { // we have only a single cell in the track - mNPoints--; + auto nPoints = getNumberOfPoints(); + if (nPoints == 2) { // we have only a single cell in the track + setNumberOfPoints(--nPoints); } - mNPoints--; + setNumberOfPoints(--nPoints); mNCells--; } //_________________________________________________________________________________________________ -inline void TrackLTF::setPoint(const Cluster cl, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint) +inline void TrackLTF::setPoint(const Cluster cl, const Int_t layer, const Int_t clusterId, const MCCompLabel label, const Int_t extClsIndex, Bool_t& newPoint) { + auto nPoints = getNumberOfPoints(); if (newPoint) { - if (mNPoints > 0) - if (mZ[mNPoints - 1] == cl.getZ()) { + if (nPoints > 0) + if (mZ[nPoints - 1] == cl.getZ()) { LOG(WARN) << "MFT TrackLTF: skipping setPoint (1 cluster per layer!)"; return; } - if (mNPoints >= constants::mft::LayersNumber - 1) { + if (nPoints > constants::mft::LayersNumber) { LOG(WARN) << "MFT TrackLTF Overflow"; return; } - mX[mNPoints] = cl.getX(); - mY[mNPoints] = cl.getY(); - mZ[mNPoints] = cl.getZ(); - mSigmaX2[mNPoints] = cl.sigmaX2; - mSigmaY2[mNPoints] = cl.sigmaY2; - mLayer[mNPoints] = layer; - mClusterId[mNPoints] = clusterId; - mMCCompLabels[mNPoints] = label; - mNPoints++; - setClusterIndex(layer, clusterId, mNPoints); + mX[nPoints] = cl.getX(); + mY[nPoints] = cl.getY(); + mZ[nPoints] = cl.getZ(); + mSigmaX2[nPoints] = cl.sigmaX2; + mSigmaY2[nPoints] = cl.sigmaY2; + mLayer[nPoints] = layer; + mClusterId[nPoints] = clusterId; + mMCCompLabels[nPoints] = label; + setExternalClusterIndex(nPoints, extClsIndex); + setNumberOfPoints(nPoints + 1); } else { - mX[mNPoints] = cl.getX(); - mY[mNPoints] = cl.getY(); - mZ[mNPoints] = cl.getZ(); - mSigmaX2[mNPoints] = cl.sigmaX2; - mSigmaY2[mNPoints] = cl.sigmaY2; - mLayer[mNPoints] = layer; - mClusterId[mNPoints] = clusterId; - mMCCompLabels[mNPoints] = label; - setClusterIndex(layer, clusterId, mNPoints); + mX[nPoints] = cl.getX(); + mY[nPoints] = cl.getY(); + mZ[nPoints] = cl.getZ(); + mSigmaX2[nPoints] = cl.sigmaX2; + mSigmaY2[nPoints] = cl.sigmaY2; + mLayer[nPoints] = layer; + mClusterId[nPoints] = clusterId; + mMCCompLabels[nPoints] = label; + setExternalClusterIndex(nPoints, extClsIndex); } } @@ -161,11 +159,12 @@ inline void TrackLTF::sort() Int_t layer; Int_t clusterId; MCCompLabel label; + Int_t extClsIndex; }; std::vector<ClusterData> points; // Loading cluster data - for (Int_t point = 0; point < getNPoints(); ++point) { + for (Int_t point = 0; point < getNumberOfPoints(); ++point) { auto& somepoint = points.emplace_back(); somepoint.x = mX[point]; somepoint.y = mY[point]; @@ -175,13 +174,14 @@ inline void TrackLTF::sort() somepoint.layer = mLayer[point]; somepoint.clusterId = mClusterId[point]; somepoint.label = mMCCompLabels[point]; + somepoint.extClsIndex = mExtClsIndex[point]; } // Sorting cluster data std::sort(points.begin(), points.end(), [](ClusterData a, ClusterData b) { return a.z > b.z; }); // Storing sorted cluster data - for (Int_t point = 0; point < getNPoints(); ++point) { + for (Int_t point = 0; point < getNumberOfPoints(); ++point) { mX[point] = points[point].x; mY[point] = points[point].y; mZ[point] = points[point].z; @@ -190,6 +190,7 @@ inline void TrackLTF::sort() mLayer[point] = points[point].layer; mClusterId[point] = points[point].clusterId; mMCCompLabels[point] = points[point].label; + mExtClsIndex[point] = points[point].extClsIndex; } } diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index ab9c04bad1361..e72b66536d2a9 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -255,7 +255,7 @@ inline void Tracker::computeTracksMClabels(const T& tracks) MCCompLabel maxOccurrencesValue{-1, -1, -1, false}; int count{0}; bool isFakeTrack{false}; - auto nClusters = track.getNumberOfClusters(); + auto nClusters = track.getNumberOfPoints(); for (int iCluster = 0; iCluster < nClusters; ++iCluster) { const MCCompLabel& currentLabel = track.getMCCompLabels()[iCluster]; if (currentLabel == maxOccurrencesValue) { diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index a87a1a756b43c..568b5ac14c83c 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -49,8 +49,11 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g Point3D<float> locXYZ; float sigmaX2 = ioutils::DefClusError2Row, sigmaY2 = ioutils::DefClusError2Col; //Dummy COG errors (about half pixel size) if (pattID != itsmft::CompCluster::InvalidPatternID) { - sigmaX2 = dict.getErr2X(pattID); // ALPIDE local X coordinate => MFT global X coordinate (ALPIDE rows) - sigmaY2 = dict.getErr2Z(pattID); // ALPIDE local Z coordinate => MFT global Y coordinate (ALPIDE columns) + //sigmaX2 = dict.getErr2X(pattID); // ALPIDE local X coordinate => MFT global X coordinate (ALPIDE rows) + //sigmaY2 = dict.getErr2Z(pattID); // ALPIDE local Z coordinate => MFT global Y coordinate (ALPIDE columns) + // temporary, until ITS bug fix + sigmaX2 = dict.getErrX(pattID) * dict.getErrX(pattID); + sigmaY2 = dict.getErrZ(pattID) * dict.getErrZ(pattID); if (!dict.isGroup(pattID)) { locXYZ = dict.getClusterCoordinates(c); } else { @@ -73,7 +76,6 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g int phiBinIndex = constants::index_table::getPhiBinIndex(phiCoord); int binIndex = constants::index_table::getBinIndex(rBinIndex, phiBinIndex); // TODO: Check consistency of sigmaX2 and sigmaY2 - // std::cout << "ClusterID = " << clusterId << " ; pattID = " << pattID << " ; sigmaX2 = " << sigmaX2 << " ; sigmaY2 = " << sigmaY2 << std::endl; event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), phiCoord, rCoord, event.getClustersInLayer(layer).size(), binIndex, sigmaX2, sigmaY2, sensorID); if (mcLabels) { event.addClusterLabelToLayer(layer, *(mcLabels->getLabels(first + clusterId).begin())); diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index cb96f0046d093..8e6bcc21e64eb 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -57,7 +57,7 @@ bool TrackFitter::fit(TrackLTF& track, bool outward) /// Returns false in case of failure auto& mftTrackingParam = MFTTrackingParam::Instance(); - auto nClusters = track.getNPoints(); + auto nClusters = track.getNumberOfPoints(); if (mftTrackingParam.verbose) { std::cout << "Seed covariances: \n" @@ -100,7 +100,7 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) // initialize the starting track parameters and cluster double chi2invqptquad; double invQPtSeed; - auto nPoints = track.getNPoints(); + auto nPoints = track.getNumberOfPoints(); auto k = TMath::Abs(o2::constants::math::B2C * mBZField); auto Hz = std::copysign(1, mBZField); invQPtSeed = invQPtFromFCF(track, mBZField, chi2invqptquad); @@ -171,6 +171,8 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; } + auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; + // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) SMatrix55 lastParamCov; lastParamCov(0, 0) = sigmax0sq; // <X,X> @@ -297,14 +299,14 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) { - const std::array<Float_t, constants::mft::LayersNumber>& xPositons = track.getXCoordinates(); - const std::array<Float_t, constants::mft::LayersNumber>& yPositons = track.getYCoordinates(); - const std::array<Float_t, constants::mft::LayersNumber>& zPositons = track.getZCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& xPositions = track.getXCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& yPositions = track.getYCoordinates(); + const std::array<Float_t, constants::mft::LayersNumber>& zPositions = track.getZCoordinates(); const std::array<Float_t, constants::mft::LayersNumber>& SigmasX2 = track.getSigmasX2(); const std::array<Float_t, constants::mft::LayersNumber>& SigmasY2 = track.getSigmasY2(); // Fast Circle Fit (Hansroul, Jeremie, Savard, 1987) - auto nPoints = track.getNPoints(); + auto nPoints = track.getNumberOfPoints(); Double_t* xVal = new Double_t[nPoints]; Double_t* yVal = new Double_t[nPoints]; Double_t* zVal = new Double_t[nPoints]; @@ -319,15 +321,15 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) xErr[np] = SigmasX2[np]; yErr[np] = SigmasY2[np]; if (np > 0) { - xVal[np] = xPositons[np] - xVal[0]; - yVal[np] = yPositons[np] - yVal[0]; + xVal[np] = xPositions[np] - xVal[0]; + yVal[np] = yPositions[np] - yVal[0]; xErr[np] *= std::sqrt(2.); yErr[np] *= std::sqrt(2.); } else { xVal[np] = 0.; yVal[np] = 0.; } - zVal[np] = zPositons[np]; + zVal[np] = zPositions[np]; } for (int i = 0; i < (nPoints - 1); i++) { x2 = xVal[i + 1] * xVal[i + 1]; @@ -335,13 +337,13 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) invx2y2 = 1. / (x2 + y2); uVal[i] = xVal[i + 1] * invx2y2; vVal[i] = yVal[i + 1] * invx2y2; - vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2)) * invx2y2 * invx2y2; + vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2) * (x2 - y2)) * invx2y2 * invx2y2; } Double_t invqpt_fcf; Int_t qfcf; chi2 = 0.; - if (LinearRegression((nPoints - 1), uVal, vVal, yErr, a, ae, b, be)) { + if (LinearRegression((nPoints - 1), uVal, vVal, vErr, a, ae, b, be)) { // v = a * u + b // circle passing through (0,0): // (x - rx)^2 + (y - ry)^2 = r^2 @@ -350,7 +352,6 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) ry = 1. / (2. * b); rx = -a * ry; r = std::sqrt(rx * rx + ry * ry); - // pt ---> Double_t invpt = 1. / (o2::constants::math::B2C * bFieldZ * r); @@ -378,7 +379,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) invqpt_fcf = qfcf * invpt; } else { // the linear regression failed... - printf("BV LinearRegression failed!\n"); + LOG(WARN) << "LinearRegression failed!"; invqpt_fcf = 1. / 100.; } diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index cb0e033505591..65793fba75579 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -110,6 +110,7 @@ void Tracker::findTracksLTF(ROframe& event) Int_t nClsInLayer1, nClsInLayer2, nClsInLayer; Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; + Int_t extClsIndex; Float_t dR, dRmin, dRcut = constants::mft::LTFclsRCut; std::vector<Int_t> binsR, binsPhi, binsRS, binsPhiS; Bool_t hasDisk[constants::mft::DisksNumber], newPoint, seed = kTRUE; @@ -186,7 +187,8 @@ void Tracker::findTracksLTF(ROframe& event) // add the first seed-point mcCompLabel = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentTrackLTF().setPoint(cluster1, layer1, clsLayer1, mcCompLabel, newPoint); + extClsIndex = event.getClusterExternalIndex(layer1, cluster1.clusterId); + event.getCurrentTrackLTF().setPoint(cluster1, layer1, clsLayer1, mcCompLabel, extClsIndex, newPoint); for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { @@ -226,7 +228,10 @@ void Tracker::findTracksLTF(ROframe& event) hasDisk[layer / 2] = kTRUE; mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); - event.getCurrentTrackLTF().setPoint(cluster, layer, clsLayer, mcCompLabel, newPoint); + extClsIndex = event.getClusterExternalIndex(layer, cluster.clusterId); + event.getCurrentTrackLTF().setPoint(cluster, layer, clsLayer, mcCompLabel, extClsIndex, newPoint); + // retain only the closest point in DistanceToSeed + newPoint = false; } // end clusters bin intermediate layer } // end intermediate layers } // end binPhi @@ -235,10 +240,11 @@ void Tracker::findTracksLTF(ROframe& event) // add the second seed-point mcCompLabel = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); newPoint = kTRUE; - event.getCurrentTrackLTF().setPoint(cluster2, layer2, clsLayer2, mcCompLabel, newPoint); + extClsIndex = event.getClusterExternalIndex(layer2, cluster2.clusterId); + event.getCurrentTrackLTF().setPoint(cluster2, layer2, clsLayer2, mcCompLabel, extClsIndex, newPoint); // keep only tracks fulfilling the minimum length condition - if (event.getCurrentTrackLTF().getNPoints() < constants::mft::MinTrackPoints) { + if (event.getCurrentTrackLTF().getNumberOfPoints() < constants::mft::MinTrackPoints) { event.removeCurrentTrackLTF(); continue; } @@ -254,7 +260,7 @@ void Tracker::findTracksLTF(ROframe& event) // mark the used clusters //Int_t lay, layMin = 10, layMax = -1; - for (Int_t point = 0; point < event.getCurrentTrackLTF().getNPoints(); ++point) { + for (Int_t point = 0; point < event.getCurrentTrackLTF().getNumberOfPoints(); ++point) { event.markUsedCluster(event.getCurrentTrackLTF().getLayers()[point], event.getCurrentTrackLTF().getClustersId()[point]); //lay = event.getCurrentTrackLTF().getLayers()[point]; //layMin = (lay < layMin) ? lay : layMin; @@ -693,7 +699,7 @@ const Float_t Tracker::getCellChisquare(ROframe& event, const Cell& cell) const Float_t x[constants::mft::MaxTrackPoints], y[constants::mft::MaxTrackPoints], z[constants::mft::MaxTrackPoints], err[constants::mft::MaxTrackPoints]; Int_t point; - for (point = 0; point < trackCA.getNPoints(); ++point) { + for (point = 0; point < trackCA.getNumberOfPoints(); ++point) { x[point] = trackCA.getXCoordinates()[point]; y[point] = trackCA.getYCoordinates()[point]; z[point] = trackCA.getZCoordinates()[point]; @@ -707,17 +713,17 @@ const Float_t Tracker::getCellChisquare(ROframe& event, const Cell& cell) const // linear regression in the plane z:x // x = zxApar * z + zxBpar Float_t zxApar, zxBpar, zxAparErr, zxBparErr, chisqZX = 0.0; - if (!LinearRegression(trackCA.getNPoints() + 1, z, x, err, zxApar, zxAparErr, zxBpar, zxBparErr, chisqZX)) { + if (!LinearRegression(trackCA.getNumberOfPoints() + 1, z, x, err, zxApar, zxAparErr, zxBpar, zxBparErr, chisqZX)) { return -1.0; } // linear regression in the plane z:y // y = zyApar * z + zyBpar Float_t zyApar, zyBpar, zyAparErr, zyBparErr, chisqZY = 0.0; - if (!LinearRegression(trackCA.getNPoints() + 1, z, y, err, zyApar, zyAparErr, zyBpar, zyBparErr, chisqZY)) { + if (!LinearRegression(trackCA.getNumberOfPoints() + 1, z, y, err, zyApar, zyAparErr, zyBpar, zyBparErr, chisqZY)) { return -1.0; } - Int_t nDegFree = 2 * (trackCA.getNPoints() + 1) - 4; + Int_t nDegFree = 2 * (trackCA.getNumberOfPoints() + 1) - 4; return (chisqZX + chisqZY) / (Float_t)nDegFree; } @@ -728,15 +734,15 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce Road& road = event.getCurrentRoad(); const Cell& cell = road.getCellsInLayer(layer1)[cellId]; const Int_t layer2 = cell.getSecondLayerId(); - const Int_t cls1Id = cell.getFirstClusterIndex(); - const Int_t cls2Id = cell.getSecondClusterIndex(); + const Int_t clsLayer1 = cell.getFirstClusterIndex(); + const Int_t clsLayer2 = cell.getSecondClusterIndex(); - const Cluster& cluster1 = event.getClustersInLayer(layer1)[cls1Id]; - const Cluster& cluster2 = event.getClustersInLayer(layer2)[cls2Id]; + const Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; + const Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; - if (trackCA.getNPoints() > 0) { - const Float_t xLast = trackCA.getXCoordinates()[trackCA.getNPoints() - 1]; - const Float_t yLast = trackCA.getYCoordinates()[trackCA.getNPoints() - 1]; + if (trackCA.getNumberOfPoints() > 0) { + const Float_t xLast = trackCA.getXCoordinates()[trackCA.getNumberOfPoints() - 1]; + const Float_t yLast = trackCA.getYCoordinates()[trackCA.getNumberOfPoints() - 1]; Float_t dx = xLast - cluster2.getX(); Float_t dy = yLast - cluster2.getY(); Float_t dr = std::sqrt(dx * dx + dy * dy); @@ -749,27 +755,29 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce MCCompLabel mcCompLabel2 = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); Bool_t newPoint; + Int_t extClsIndex; - if (trackCA.getNPoints() == 0) { + if (trackCA.getNumberOfPoints() == 0) { newPoint = kTRUE; - trackCA.setPoint(cluster2, layer2, cls2Id, mcCompLabel2, newPoint); + extClsIndex = event.getClusterExternalIndex(layer2, cluster2.clusterId); + trackCA.setPoint(cluster2, layer2, clsLayer2, mcCompLabel2, extClsIndex, newPoint); } newPoint = kTRUE; - trackCA.setPoint(cluster1, layer1, cls1Id, mcCompLabel1, newPoint); + extClsIndex = event.getClusterExternalIndex(layer1, cluster1.clusterId); + trackCA.setPoint(cluster1, layer1, clsLayer1, mcCompLabel1, extClsIndex, newPoint); trackCA.addCell(layer1, cellId); // update the chisquare - if (trackCA.getNPoints() == 2) { - + if (trackCA.getNumberOfPoints() == 2) { trackCA.setChiSquareZX(0.0); trackCA.setChiSquareZY(0.0); return kTRUE; } Float_t x[constants::mft::MaxTrackPoints], y[constants::mft::MaxTrackPoints], z[constants::mft::MaxTrackPoints], err[constants::mft::MaxTrackPoints]; - for (Int_t point = 0; point < trackCA.getNPoints(); ++point) { + for (Int_t point = 0; point < trackCA.getNumberOfPoints(); ++point) { x[point] = trackCA.getXCoordinates()[point]; y[point] = trackCA.getYCoordinates()[point]; z[point] = trackCA.getZCoordinates()[point]; @@ -779,7 +787,7 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce // linear regression in the plane z:x // x = zxApar * z + zxBpar Float_t zxApar, zxBpar, zxAparErr, zxBparErr, chisqZX = 0.0; - if (LinearRegression(trackCA.getNPoints(), z, x, err, zxApar, zxAparErr, zxBpar, zxBparErr, chisqZX)) { + if (LinearRegression(trackCA.getNumberOfPoints(), z, x, err, zxApar, zxAparErr, zxBpar, zxBparErr, chisqZX)) { trackCA.setChiSquareZX(chisqZX); } else { return kFALSE; @@ -788,7 +796,7 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce // linear regression in the plane z:y // y = zyApar * z + zyBpar Float_t zyApar, zyBpar, zyAparErr, zyBparErr, chisqZY = 0.0; - if (LinearRegression(trackCA.getNPoints(), z, y, err, zyApar, zyAparErr, zyBpar, zyBparErr, chisqZY)) { + if (LinearRegression(trackCA.getNumberOfPoints(), z, y, err, zyApar, zyAparErr, zyBpar, zyBparErr, chisqZY)) { trackCA.setChiSquareZY(chisqZY); } else { return kFALSE; @@ -874,7 +882,7 @@ bool Tracker::fitTracks(ROframe& event) mTrackFitter->fit(track); mTrackFitter->initTrack(outParam, true); mTrackFitter->fit(outParam, true); - track.SetOutParam(outParam); + track.setOutParam(outParam); } for (auto& track : event.getTracksCA()) { track.sort(); @@ -883,7 +891,7 @@ bool Tracker::fitTracks(ROframe& event) mTrackFitter->fit(track); mTrackFitter->initTrack(outParam, true); mTrackFitter->fit(outParam, true); - track.SetOutParam(outParam); + track.setOutParam(outParam); } return true; diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 1af1434713712..464fb145b5d66 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -113,14 +113,12 @@ void TrackerDPL::run(ProcessingContext& pc) LOG(INFO) << "MFTTracker RO: continuous=" << continuous; // snippet to convert found tracks to final output tracks with separate cluster indices - auto copyTracks = [&event](auto& tracks, auto& allTracks, auto& allClusIdx, int offset = 0) { + auto copyTracks = [&event](auto& tracks, auto& allTracks, auto& allClusIdx) { for (auto& trc : tracks) { - trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices - int ncl = trc.getNumberOfClusters(); + trc.setExternalClusterIndexOffset(allClusIdx.size()); + int ncl = trc.getNumberOfPoints(); for (int ic = 0; ic < ncl; ic++) { - auto layer_clID = trc.getClustersId()[ic]; - auto layer = trc.getLayers()[ic]; - auto externalClusterID = event.getClusterExternalIndex(layer, trc.getClustersId()[ic]); + auto externalClusterID = trc.getExternalClusterIndex(ic); allClusIdx.push_back(externalClusterID); } allTracks.emplace_back(trc); From cd861be110cf5465c5a34b6184d79649eb433048 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 1 Sep 2020 20:19:30 +0200 Subject: [PATCH 0528/1751] DPL Analysis: add test for filtered grouping --- Framework/Core/test/test_GroupSlicer.cxx | 49 ++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/Framework/Core/test/test_GroupSlicer.cxx b/Framework/Core/test/test_GroupSlicer.cxx index 13008121bc0c6..0c3dfcb7711c7 100644 --- a/Framework/Core/test/test_GroupSlicer.cxx +++ b/Framework/Core/test/test_GroupSlicer.cxx @@ -229,3 +229,52 @@ BOOST_AUTO_TEST_CASE(GroupSlicerMismatchedGroups) ++count; } } + +BOOST_AUTO_TEST_CASE(GroupSlicerMismatchedFilteredGroups) +{ + TableBuilder builderE; + auto evtsWriter = builderE.cursor<aod::Events>(); + for (auto i = 0; i < 20; ++i) { + evtsWriter(0, 0.5f * i, 2.f * i, 3.f * i); + } + auto evtTable = builderE.finalize(); + + TableBuilder builderT; + auto trksWriter = builderT.cursor<aod::TrksX>(); + for (auto i = 0; i < 20; ++i) { + if (i == 3 || i == 10 || i == 12 || i == 16) { + continue; + } + for (auto j = 0.f; j < 5; j += 0.5f) { + trksWriter(0, i, 0.5f * j); + } + } + auto trkTable = builderT.finalize(); + using FilteredEvents = soa::Filtered<aod::Events>; + soa::SelectionVector rows{2, 4, 10, 9, 15}; + FilteredEvents e{{evtTable}, {2, 4, 10, 9, 15}}; + aod::TrksX t{trkTable}; + BOOST_CHECK_EQUAL(e.size(), 5); + BOOST_CHECK_EQUAL(t.size(), 10 * (20 - 4)); + + auto tt = std::make_tuple(t); + o2::framework::AnalysisDataProcessorBuilder::GroupSlicer g(e, tt); + + unsigned int count = 0; + + for (auto& slice : g) { + auto as = slice.associatedTables(); + auto gg = slice.groupingElement(); + BOOST_CHECK_EQUAL(gg.globalIndex(), rows[count]); + auto trks = std::get<aod::TrksX>(as); + if (rows[count] == 3 || rows[count] == 10 || rows[count] == 12 || rows[count] == 16) { + BOOST_CHECK_EQUAL(trks.size(), 0); + } else { + BOOST_CHECK_EQUAL(trks.size(), 10); + } + for (auto& trk : trks) { + BOOST_CHECK_EQUAL(trk.eventId(), rows[count]); + } + ++count; + } +} From 5b8c98a27366e105ccb558c9e43baa528a341206 Mon Sep 17 00:00:00 2001 From: Iouri Belikov <iouri.belikov@cern.ch> Date: Fri, 28 Aug 2020 18:50:28 +0200 Subject: [PATCH 0529/1751] Keep InvalidPatternID for huge clusters --- .../reconstruction/include/ITSMFTReconstruction/Clusterer.h | 2 +- Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h index 4982de1b5aebd..c94fb25d8705b 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h @@ -132,7 +132,7 @@ class Clusterer void streamCluster(const std::vector<PixelData>& pixbuf, uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, - MCTruth* labelsClusPtr, int nlab); + MCTruth* labelsClusPtr, int nlab, bool isHuge = false); void fetchMCLabels(int digID, const MCTruth* labelsDig, int& nfilled); void initChip(const ChipPixelData* curChipData, uint32_t first); diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index 584bdd011428e..ecb21366e0822 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -276,7 +276,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus // Stream a piece of cluster only if the reduced bounding box is not empty if (!pixbuf.empty()) { streamCluster(pixbuf, r, rsp, colMin, colSpan, chipID, - compClusPtr, patternsPtr, labelsClusPtr, nlab); + compClusPtr, patternsPtr, labelsClusPtr, nlab, true); } r += rsp; rsp = o2::itsmft::ClusterPattern::MaxRowSpan; @@ -289,7 +289,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus } } -void Clusterer::ClustererThread::streamCluster(const std::vector<PixelData>& pixbuf, uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab) +void Clusterer::ClustererThread::streamCluster(const std::vector<PixelData>& pixbuf, uint16_t rowMin, uint16_t rowSpanW, uint16_t colMin, uint16_t colSpanW, uint16_t chipID, CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isHuge) { if (labelsClusPtr) { // MC labels were requested auto cnt = compClusPtr->size(); @@ -305,7 +305,7 @@ void Clusterer::ClustererThread::streamCluster(const std::vector<PixelData>& pix int nbits = ir * colSpanW + ic; patt[nbits >> 3] |= (0x1 << (7 - (nbits % 8))); } - uint16_t pattID = (parent->mPattIdConverter.size() == 0) ? CompCluster::InvalidPatternID : parent->mPattIdConverter.findGroupID(rowSpanW, colSpanW, patt); + uint16_t pattID = (isHuge || parent->mPattIdConverter.size() == 0) ? CompCluster::InvalidPatternID : parent->mPattIdConverter.findGroupID(rowSpanW, colSpanW, patt); if (pattID == CompCluster::InvalidPatternID || parent->mPattIdConverter.isGroup(pattID)) { float xCOG = 0., zCOG = 0.; ClusterPattern::getCOG(rowSpanW, colSpanW, patt, xCOG, zCOG); From 54bce8ada0a8bfff0345c90318ecff37103d2819 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 1 Sep 2020 18:38:21 +0200 Subject: [PATCH 0530/1751] port from aliroot tracks xyzPxPyPz cov.matrix extraction --- .../include/ReconstructionDataFormats/Track.h | 2 + DataFormats/Reconstruction/src/Track.cxx | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h index 10d8533b55a9c..655d4409fe440 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h @@ -257,6 +257,8 @@ class TrackParCov : public TrackPar float getCovarElem(int i, int j) const { return mC[CovarMap[i][j]]; } float getDiagError2(int i) const { return mC[DiagMap[i]]; } + bool getCovXYZPxPyPzGlo(std::array<float, 21>& c) const; + #ifndef GPUCA_ALIGPUCODE void print() const; std::string asString() const; diff --git a/DataFormats/Reconstruction/src/Track.cxx b/DataFormats/Reconstruction/src/Track.cxx index aff40fe2b46ac..d83a82913377e 100644 --- a/DataFormats/Reconstruction/src/Track.cxx +++ b/DataFormats/Reconstruction/src/Track.cxx @@ -1649,6 +1649,68 @@ bool TrackParCov::correctForMaterial(float x2x0, float xrho, float mass, bool an return true; } +//______________________________________________________________ +bool TrackParCov::getCovXYZPxPyPzGlo(std::array<float, 21>& cv) const +{ + //--------------------------------------------------------------------- + // This function returns the global covariance matrix of the track params + // + // Cov(x,x) ... : cv[0] + // Cov(y,x) ... : cv[1] cv[2] + // Cov(z,x) ... : cv[3] cv[4] cv[5] + // Cov(px,x)... : cv[6] cv[7] cv[8] cv[9] + // Cov(py,x)... : cv[10] cv[11] cv[12] cv[13] cv[14] + // Cov(pz,x)... : cv[15] cv[16] cv[17] cv[18] cv[19] cv[20] + // + // Results for (nearly) straight tracks are meaningless ! + //--------------------------------------------------------------------- + if (std::abs(getQ2Pt()) <= Almost0 || std::abs(getSnp()) > Almost1) { + for (int i = 0; i < 21; i++) { + cv[i] = 0.; + } + return false; + } + + auto pt = getPt(); + float sn, cs; + o2::utils::sincos(getAlpha(), sn, cs); + auto r = std::sqrt((1. - getSnp()) * (1. + getSnp())); + auto m00 = -sn, m10 = cs; + auto m23 = -pt * (sn + getSnp() * cs / r), m43 = -pt * pt * (r * cs - getSnp() * sn); + auto m24 = pt * (cs - getSnp() * sn / r), m44 = -pt * pt * (r * sn + getSnp() * cs); + auto m35 = pt, m45 = -pt * pt * getTgl(); + + if (getSign() < 0) { + m43 = -m43; + m44 = -m44; + m45 = -m45; + } + + cv[0] = mC[0] * m00 * m00; + cv[1] = mC[0] * m00 * m10; + cv[2] = mC[0] * m10 * m10; + cv[3] = mC[1] * m00; + cv[4] = mC[1] * m10; + cv[5] = mC[2]; + cv[6] = m00 * (mC[3] * m23 + mC[10] * m43); + cv[7] = m10 * (mC[3] * m23 + mC[10] * m43); + cv[8] = mC[4] * m23 + mC[11] * m43; + cv[9] = m23 * (mC[5] * m23 + mC[12] * m43) + m43 * (mC[12] * m23 + mC[14] * m43); + cv[10] = m00 * (mC[3] * m24 + mC[10] * m44); + cv[11] = m10 * (mC[3] * m24 + mC[10] * m44); + cv[12] = mC[4] * m24 + mC[11] * m44; + cv[13] = m23 * (mC[5] * m24 + mC[12] * m44) + m43 * (mC[12] * m24 + mC[14] * m44); + cv[14] = m24 * (mC[5] * m24 + mC[12] * m44) + m44 * (mC[12] * m24 + mC[14] * m44); + cv[15] = m00 * (mC[6] * m35 + mC[10] * m45); + cv[16] = m10 * (mC[6] * m35 + mC[10] * m45); + cv[17] = mC[7] * m35 + mC[11] * m45; + cv[18] = m23 * (mC[8] * m35 + mC[12] * m45) + m43 * (mC[13] * m35 + mC[14] * m45); + cv[19] = m24 * (mC[8] * m35 + mC[12] * m45) + m44 * (mC[13] * m35 + mC[14] * m45); + cv[20] = m35 * (mC[9] * m35 + mC[13] * m45) + m45 * (mC[13] * m35 + mC[14] * m45); + + return true; +} + #ifndef GPUCA_ALIGPUCODE //______________________________________________________________ std::string TrackParCov::asString() const From 00ddc3a40ee8ed0fd32833b9f749c3ae8f47e6bf Mon Sep 17 00:00:00 2001 From: Raymond Ehlers <raymond.ehlers@gmail.com> Date: Tue, 1 Sep 2020 13:42:07 +0200 Subject: [PATCH 0531/1751] [EMCAL-668] Fix calo trigger AOD metadata The CaloTrigger was wrongly assigned to the calo cells. Credit for finding the fix to Markus --- Framework/Core/src/AODReaderHelpers.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index d58cc43322bff..ca839bb14cdfa 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -263,7 +263,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() tableMaker(o2::aod::StoredTracksCovMetadata{}, AODTypeMask::TrackCov, "O2track"); tableMaker(o2::aod::TracksExtraMetadata{}, AODTypeMask::TrackExtra, "O2track"); tableMaker(o2::aod::CalosMetadata{}, AODTypeMask::Calo, "O2calo"); - tableMaker(o2::aod::CaloTriggersMetadata{}, AODTypeMask::Calo, "O2calotrigger"); + tableMaker(o2::aod::CaloTriggersMetadata{}, AODTypeMask::CaloTrigger, "O2calotrigger"); tableMaker(o2::aod::StoredMuonsMetadata{}, AODTypeMask::Muon, "O2muon"); tableMaker(o2::aod::MuonClustersMetadata{}, AODTypeMask::Muon, "O2muoncluster"); tableMaker(o2::aod::ZdcsMetadata{}, AODTypeMask::Zdc, "O2zdc"); From dfe9e3028166e564325693a23b16a6c795a32814 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Sun, 30 Aug 2020 17:05:38 +0200 Subject: [PATCH 0532/1751] [EMCAL-610] Fix handling of the time sample The digitizer creates time samples however it stores them in ns. The time needs to be converted to sample ID dividing by the length of the time sample. --- Detectors/EMCAL/simulation/src/RawWriter.cxx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index 3fa207f840518..e3a48f70a53e0 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -8,6 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "FairLogger.h" + #include <fmt/core.h> #include <gsl/span> #include <TSystem.h> @@ -102,7 +104,15 @@ bool RawWriter::processNextTrigger() } else { bunchDigits = &(towerdata->second.mDigits); } - (*bunchDigits)[int(dig.getTimeStamp())] = &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; } } From d325902acd078985eb501305dd7f3d83865043e2 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 2 Sep 2020 22:28:00 +0200 Subject: [PATCH 0533/1751] Dont require 16B words for RORC detectors in RawFileWriter --- Detectors/Raw/src/RawFileWriter.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Raw/src/RawFileWriter.cxx b/Detectors/Raw/src/RawFileWriter.cxx index ca0b497278234..d17d6858a447a 100644 --- a/Detectors/Raw/src/RawFileWriter.cxx +++ b/Detectors/Raw/src/RawFileWriter.cxx @@ -159,7 +159,7 @@ RawFileWriter::LinkData& RawFileWriter::registerLink(uint16_t fee, uint16_t cru, void RawFileWriter::addData(uint16_t feeid, uint16_t cru, uint8_t lnk, uint8_t endpoint, const IR& ir, const gsl::span<char> data, bool preformatted, uint32_t trigger) { // add payload to relevant links - if (data.size() % RDHUtils::GBTWord) { + if (isCRUDetector() && (data.size() % RDHUtils::GBTWord)) { LOG(ERROR) << "provided payload size " << data.size() << " is not multiple of GBT word size"; throw std::runtime_error("payload size is not mutiple of GBT word size"); } From 4ad867073e395e36abce37f75e02cb9e68642d31 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Thu, 3 Sep 2020 12:29:07 +0200 Subject: [PATCH 0534/1751] [EMCAL-610] Fix segfault in Raw creator - Fix buffer overrun in findBunches leading to segfault - In getting online ID (SRU ID in supermodule had to be scaled with the number of supermodules in order to get the DDL ID) - Convert trailer size as size in 32bit words to size in byte in carryOverMethod in order to calculate properly the payload size --- .../EMCAL/base/include/EMCALBase/RCUTrailer.h | 4 +-- Detectors/EMCAL/base/src/Mapper.cxx | 2 +- Detectors/EMCAL/simulation/src/RawWriter.cxx | 35 ++++++++++--------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Detectors/EMCAL/base/include/EMCALBase/RCUTrailer.h b/Detectors/EMCAL/base/include/EMCALBase/RCUTrailer.h index 98d2798e31bb0..fb3f6e640ffb1 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/RCUTrailer.h +++ b/Detectors/EMCAL/base/include/EMCALBase/RCUTrailer.h @@ -161,8 +161,8 @@ class RCUTrailer private: int mRCUId = -1; ///< current RCU identifier unsigned char mFirmwareVersion = 0; ///< RCU firmware version - unsigned int mTrailerSize = 0; ///< Size of the trailer - unsigned int mPayloadSize = 0; ///< Size of the payload + unsigned int mTrailerSize = 0; ///< Size of the trailer (in number of 32 bit words) + unsigned int mPayloadSize = 0; ///< Size of the payload (in nunber of 32 bit words) unsigned int mFECERRA = 0; ///< contains errors related to ALTROBUS transactions unsigned int mFECERRB = 0; ///< contains errors related to ALTROBUS transactions unsigned short mERRREG2 = 0; ///< contains errors related to ALTROBUS transactions or trailer of ALTRO channel block diff --git a/Detectors/EMCAL/base/src/Mapper.cxx b/Detectors/EMCAL/base/src/Mapper.cxx index 1b603689dc691..80eaf25a509f9 100644 --- a/Detectors/EMCAL/base/src/Mapper.cxx +++ b/Detectors/EMCAL/base/src/Mapper.cxx @@ -115,6 +115,6 @@ Mapper& MappingHandler::getMappingForDDL(int ddl) std::ostream& o2::emcal::operator<<(std::ostream& stream, const Mapper::ChannelID& channel) { - stream << "Row " << channel.mRow << ", Column " << channel.mColumn << ", type " << o2::emcal::channelTypeToString(channel.mChannelType); + stream << "Row " << static_cast<int>(channel.mRow) << ", Column " << static_cast<int>(channel.mColumn) << ", type " << o2::emcal::channelTypeToString(channel.mChannelType); return stream; } \ No newline at end of file diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index e3a48f70a53e0..2bac5412c1e0c 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -152,6 +152,7 @@ bool RawWriter::processNextTrigger() // register output data 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); } mCurrentTrigger++; @@ -162,30 +163,32 @@ std::vector<AltroBunch> RawWriter::findBunches(const std::vector<o2::emcal::Digi { std::vector<AltroBunch> result; AltroBunch* currentBunch = nullptr; - int starttime = 0; - for (auto ien = channelDigits.size() - 1;; ien--) { - auto dig = channelDigits[ien]; + // Digits in ALTRO bunch in time-reversed order + int itime; + for (itime = channelDigits.size() - 1; itime >= 0; itime--) { + auto dig = channelDigits[itime]; if (!dig) { - starttime++; continue; } - int adc = dig->getEnergy() / constants::EMCAL_ADCENERGY; /// conversion Energy <-> ADC := 16 MeV/ADC + int adc = dig->getAmplitudeADC(); if (adc < mPedestal) { // Stop bunch + // Set the start time to the time sample of previous (passing) digit + currentBunch->mStarttime = itime + 1; currentBunch = nullptr; - starttime++; continue; } if (!currentBunch) { // start new bunch AltroBunch bunch; - bunch.mStarttime = starttime; result.push_back(bunch); currentBunch = &(result.back()); } currentBunch->mADCs.emplace_back(adc); - starttime++; } + // if we have a last bunch set time start time to the time bin of teh previous digit + if (currentBunch) + currentBunch->mStarttime = itime + 1; return result; } @@ -197,19 +200,19 @@ std::tuple<int, int, int> RawWriter::getOnlineID(int towerID) auto etaphishift = mGeometry->ShiftOfflineToOnlineCellIndexes(supermoduleID, std::get<0>(etaphi), std::get<1>(etaphi)); int row = std::get<0>(etaphishift), col = std::get<1>(etaphishift); - int sruID = -1; + int ddlInSupermoudel = -1; if (0 <= row && row < 8) - sruID = 0; // first cable row + ddlInSupermoudel = 0; // first cable row else if (8 <= row && row < 16 && 0 <= col && col < 24) - sruID = 0; // first half; + ddlInSupermoudel = 0; // first half; else if (8 <= row && row < 16 && 24 <= col && col < 48) - sruID = 1; // second half; + ddlInSupermoudel = 1; // second half; else if (16 <= row && row < 24) - sruID = 1; // third cable row + ddlInSupermoudel = 1; // third cable row if (supermoduleID % 2 == 1) - sruID = 1 - sruID; // swap for odd=C side, to allow us to cable both sides the same + ddlInSupermoudel = 1 - ddlInSupermoudel; // swap for odd=C side, to allow us to cable both sides the same - return std::make_tuple(sruID, row, col); + return std::make_tuple(supermoduleID * 2 + ddlInSupermoudel, row, col); } std::tuple<int, int> RawWriter::getLinkAssignment(int ddlID) @@ -284,7 +287,7 @@ int RawWriter::carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> gsl::span<const uint32_t> payloadwords(reinterpret_cast<const uint32_t*>(data.data()), data.size() / sizeof(uint32_t)); auto rcutrailer = RCUTrailer::constructFromPayloadWords(payloadwords); - int sizeNoTrailer = maxSize - rcutrailer.getTrailerSize(); + int sizeNoTrailer = maxSize - rcutrailer.getTrailerSize() * sizeof(uint32_t); // calculate payload size for RCU trailer: // assume actualsize is in byte // Payload size is defined as the number of 32-bit payload words From fa6f5c08ba25ec84222dad56be39efb39b1febf9 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Fri, 4 Sep 2020 10:11:22 +0200 Subject: [PATCH 0535/1751] unifying correlation example (#4279) --- Analysis/Tasks/CMakeLists.txt | 5 - Analysis/Tasks/correlations.cxx | 405 +++++++++++++++++- Analysis/Tasks/correlationsCollection.cxx | 478 ---------------------- 3 files changed, 387 insertions(+), 501 deletions(-) delete mode 100644 Analysis/Tasks/correlationsCollection.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 0065fb0085e91..d5a267f78032a 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -22,11 +22,6 @@ o2_add_dpl_workflow(correlations PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore COMPONENT_NAME Analysis) -o2_add_dpl_workflow(correlations-collection - SOURCES correlationsCollection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore - COMPONENT_NAME Analysis) - o2_add_dpl_workflow(correlations-mixed SOURCES correlationsMixed.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore diff --git a/Analysis/Tasks/correlations.cxx b/Analysis/Tasks/correlations.cxx index 1ac440d299248..560c8cbd006df 100644 --- a/Analysis/Tasks/correlations.cxx +++ b/Analysis/Tasks/correlations.cxx @@ -7,24 +7,71 @@ // 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/EventSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/Centrality.h" #include "Analysis/StepTHn.h" #include "Analysis/CorrelationContainer.h" + #include <TH1F.h> #include <cmath> +#include <TDirectory.h> using namespace o2; using namespace o2::framework; +using namespace o2::framework::expressions; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP}; 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<soa::Join<aod::Tracks, aod::TrackSelection>>; + + // Output definitions OutputObj<CorrelationContainer> same{"sameEvent"}; - //OutputObj<CorrelationContainer> mixed{"mixedEvent"}; + OutputObj<CorrelationContainer> mixed{"mixedEvent"}; + //OutputObj<TDirectory> qaOutput{"qa"}; + + // Configuration + 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"); + + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value"); + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); + + O2_DEFINE_CONFIGURABLE(cfgPairCutPhoton, float, -1, "Pair cut on photons: -1 = off; >0 otherwise distance value (suggested: 0.004)") + O2_DEFINE_CONFIGURABLE(cfgPairCutK0, float, -1, "Pair cut on K0s: -1 = off; >0 otherwise distance value (suggested: 0.005)") + O2_DEFINE_CONFIGURABLE(cfgPairCutLambda, float, -1, "Pair cut on Lambda: -1 = off; >0 otherwise distance value (suggested: 0.005)") + 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") + + enum PairCuts { Photon = 0, + K0, + Lambda, + Phi, + Rho }; + struct Config { + bool mPairCuts = false; + //THn* mEfficiencyTrigger = nullptr; + //THn* mEfficiencyAssociated = nullptr; + } cfg; + + struct QA { + TH3F* mTwoTrackDistancePt[2] = {nullptr}; // control histograms for two-track efficiency study: dphi*_min vs deta (0 = before cut, 1 = after cut) + TH2F* mControlConvResoncances = nullptr; // control histograms for cuts on conversions and resonances + } qa; void init(o2::framework::InitContext&) { + // --- CONFIGURATION --- const char* binning = "vertex: -7, -5, -3, -1, 1, 3, 5, 7\n" "delta_phi: -1.570796, -1.483530, -1.396263, -1.308997, -1.221730, -1.134464, -1.047198, -0.959931, -0.872665, -0.785398, -0.698132, -0.610865, -0.523599, -0.436332, -0.349066, -0.261799, -0.174533, -0.087266, 0.0, 0.087266, 0.174533, 0.261799, 0.349066, 0.436332, 0.523599, 0.610865, 0.698132, 0.785398, 0.872665, 0.959931, 1.047198, 1.134464, 1.221730, 1.308997, 1.396263, 1.483530, 1.570796, 1.658063, 1.745329, 1.832596, 1.919862, 2.007129, 2.094395, 2.181662, 2.268928, 2.356194, 2.443461, 2.530727, 2.617994, 2.705260, 2.792527, 2.879793, 2.967060, 3.054326, 3.141593, 3.228859, 3.316126, 3.403392, 3.490659, 3.577925, 3.665191, 3.752458, 3.839724, 3.926991, 4.014257, 4.101524, 4.188790, 4.276057, 4.363323, 4.450590, 4.537856, 4.625123, 4.712389\n" @@ -38,40 +85,71 @@ struct CorrelationTask { "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" "vertex_eff: -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10\n"; + if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) + cfg.mPairCuts = true; + + // --- OBJECT INIT --- same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentrality", binning)); - //mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentrality", binning)); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentrality", binning)); + //qaOutput.setObject(new TDirectory("qa", "qa")); + + if (cfgTwoTrackCut > 0) { + qa.mTwoTrackDistancePt[0] = new TH3F("TwoTrackDistancePt[0]", ";#Delta#eta;#Delta#varphi^{*}_{min};#Delta p_{T}", 100, -0.15, 0.15, 100, -0.05, 0.05, 20, 0, 10); + qa.mTwoTrackDistancePt[1] = (TH3F*)qa.mTwoTrackDistancePt[0]->Clone("TwoTrackDistancePt[1]"); + //qaOutput->Add(qa.mTwoTrackDistancePt[0]); + //qaOutput->Add(qa.mTwoTrackDistancePt[1]); + } + + if (cfg.mPairCuts) { + qa.mControlConvResoncances = new TH2F("ControlConvResoncances", ";id;delta mass", 6, -0.5, 5.5, 500, -0.5, 0.5); + //qaOutput->Add(qa.mControlConvResoncances); + } } - void process(aod::Collision const& collision, aod::Tracks const& tracks) + // Version with explicit nested loop + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, aod::BCs const& bcs, aod::Run2V0s const& vzeros, myTracks const& tracks) { - LOGF(info, "Tracks for collision: %d (z: %f V0: %f)", tracks.size(), -1.0, collision.posZ()); + LOGF(info, "Tracks for collision: %d | Trigger mask: %lld | INT7: %d | V0M: %.1f", tracks.size(), collision.bc().triggerMask(), collision.sel7(), collision.centV0M()); - for (auto it1 = tracks.begin(); it1 != tracks.end(); ++it1) { - auto& track1 = *it1; - if (track1.pt() < 0.5) + if (!collision.sel7()) + return; + + int bSign = 1; // TODO magnetic field from CCDB + + for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { + + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) continue; + //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); + double eventValues[3]; eventValues[0] = track1.pt(); - eventValues[1] = 0; //collision.v0mult(); + eventValues[1] = collision.centV0M(); eventValues[2] = collision.posZ(); same->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); //mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - for (auto it2 = it1 + 1; it2 != tracks.end(); ++it2) { - auto& track2 = *it2; - //if (track1 == track2) - // continue; - if (track2.pt() < 0.5) + for (auto track2 = track1 + 1; track2 != tracks.end(); ++track2) { + + if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) + continue; + if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) + continue; + + if (cfg.mPairCuts && conversionCuts(track1, track2)) continue; - double values[6]; + if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) + continue; + + double values[6] = {0}; values[0] = track1.eta() - track2.eta(); values[1] = track1.pt(); values[2] = track2.pt(); - values[3] = 0; //collision.v0mult(); + values[3] = collision.centV0M(); values[4] = track1.phi() - track2.phi(); if (values[4] > 1.5 * TMath::Pi()) @@ -86,11 +164,302 @@ struct CorrelationTask { } } } + + // Version with combinations + void process2(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& tracks) + { + LOGF(info, "Tracks for collision (Combination run): %d", tracks.size()); + + int bSign = 1; // TODO magnetic field from CCDB + + for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { + + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + continue; + + // LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); + + double eventValues[3]; + eventValues[0] = track1.pt(); + eventValues[1] = 0; // collision.v0mult(); + eventValues[2] = collision.posZ(); + + same->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + //mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + } + + for (auto& [track1, track2] : combinations(tracks, tracks)) { + //LOGF(info, "Combination %d %d", track1.index(), track2.index()); + + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + continue; + if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) + continue; + if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) + continue; + + if (cfg.mPairCuts && conversionCuts(track1, track2)) + continue; + + if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) + continue; + + double values[6] = {0}; + + values[0] = track1.eta() - track2.eta(); + values[1] = track1.pt(); + values[2] = track2.pt(); + values[3] = 0; // collision.v0mult(); + + values[4] = track1.phi() - track2.phi(); + if (values[4] > 1.5 * TMath::Pi()) + values[4] -= TMath::TwoPi(); + if (values[4] < -0.5 * TMath::Pi()) + values[4] += TMath::TwoPi(); + + values[5] = collision.posZ(); + + same->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + //mixed->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + } + } + + template <typename T> + bool conversionCuts(T const& track1, T const& track2) + { + // skip if like sign + if (track1.charge() * track2.charge() > 0) + return false; + + bool decision = false; + + if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) + decision = true; + if (conversionCut(track1, track2, K0, cfgPairCutK0)) + decision = true; + if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) + decision = true; + if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) + decision = true; + if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) + decision = true; + if (conversionCut(track1, track2, Rho, cfgPairCutRho)) + decision = true; + + return decision; + } + + template <typename T> + bool conversionCut(T const& track1, T const& track2, PairCuts conv, double cut) + { + //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); + + if (cut < 0) + return false; + + double massD1, massD2, massM; + + switch (conv) { + case Photon: + massD1 = 0.51e-3; + massD2 = 0.51e-3; + massM = 0; + break; + case K0: + massD1 = 0.1396; + massD2 = 0.1396; + massM = 0.4976; + break; + case Lambda: + massD1 = 0.9383; + massD2 = 0.1396; + massM = 1.115; + break; + case Phi: + massD1 = 0.4937; + massD2 = 0.4937; + massM = 1.019; + break; + case Rho: + massD1 = 0.1396; + massD2 = 0.1396; + massM = 0.770; + break; + } + + auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); + + if (TMath::Abs(massC - massM * massM) > cut * 5) + return false; + + massC = getInvMassSquared(track1, massD1, track2, massD2); + qa.mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) + return true; + + return false; + } + + template <typename T> + double getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2) + { + // calculate inv mass squared + // same can be achieved, but with more computing time with + /*TLorentzVector photon, p1, p2; + p1.SetPtEtaPhiM(triggerParticle->Pt(), triggerEta, triggerParticle->Phi(), 0.510e-3); + p2.SetPtEtaPhiM(particle->Pt(), eta[j], particle->Phi(), 0.510e-3); + photon = p1+p2; + photon.M()*/ + + float tantheta1 = 1e10; + + if (track1.eta() < -1e-10 || track1.eta() > 1e-10) { + float expTmp = TMath::Exp(-track1.eta()); + tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float tantheta2 = 1e10; + if (track2.eta() < -1e-10 || track2.eta() > 1e-10) { + float expTmp = TMath::Exp(-track2.eta()); + tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); + + float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (TMath::Cos(track1.phi() - track2.phi()) + 1.0 / tantheta1 / tantheta2))); + + // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); + + return mass2; + } + + template <typename T> + double getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2) + { + // calculate inv mass squared approximately + + const float eta1 = track1.eta(); + const float eta2 = track2.eta(); + const float phi1 = track1.phi(); + const float phi2 = track2.phi(); + const float pt1 = track1.pt(); + const float pt2 = track2.pt(); + + float tantheta1 = 1e10; + + if (eta1 < -1e-10 || eta1 > 1e-10) { + float expTmp = 1.0 - eta1 + eta1 * eta1 / 2 - eta1 * eta1 * eta1 / 6 + eta1 * eta1 * eta1 * eta1 / 24; + tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float tantheta2 = 1e10; + if (eta2 < -1e-10 || eta2 > 1e-10) { + float expTmp = 1.0 - eta2 + eta2 * eta2 / 2 - eta2 * eta2 * eta2 / 6 + eta2 * eta2 * eta2 * eta2 / 24; + tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + pt1 * pt1 * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + pt2 * pt2 * (1.0 + 1.0 / tantheta2 / tantheta2); + + // fold onto 0...pi + float deltaPhi = TMath::Abs(phi1 - phi2); + while (deltaPhi > TMath::TwoPi()) + deltaPhi -= TMath::TwoPi(); + if (deltaPhi > TMath::Pi()) + deltaPhi = TMath::TwoPi() - deltaPhi; + + float cosDeltaPhi = 0; + if (deltaPhi < TMath::Pi() / 3) + cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; + else if (deltaPhi < 2 * TMath::Pi() / 3) + cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); + else + cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); + + double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); + + // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); + + return mass2; + } + + template <typename T> + bool twoTrackCut(T const& track1, T const& track2, int bSign) + { + // the variables & cuthave been developed by the HBT group + // see e.g. https://indico.cern.ch/materialDisplay.py?contribId=36&sessionId=6&materialId=slides&confId=142700 + + auto deta = track1.eta() - track2.eta(); + + // optimization + if (TMath::Abs(deta) < cfgTwoTrackCut * 2.5 * 3) { + // check first boundaries to see if is worth to loop and find the minimum + float dphistar1 = getDPhiStar(track1, track2, cfgTwoTrackCutMinRadius, bSign); + float dphistar2 = getDPhiStar(track1, track2, 2.5, bSign); + + const float kLimit = cfgTwoTrackCut * 3; + + if (TMath::Abs(dphistar1) < kLimit || TMath::Abs(dphistar2) < kLimit || dphistar1 * dphistar2 < 0) { + float dphistarminabs = 1e5; + float dphistarmin = 1e5; + for (Double_t rad = cfgTwoTrackCutMinRadius; rad < 2.51; rad += 0.01) { + float dphistar = getDPhiStar(track1, track2, rad, bSign); + + float dphistarabs = TMath::Abs(dphistar); + + if (dphistarabs < dphistarminabs) { + dphistarmin = dphistar; + dphistarminabs = dphistarabs; + } + } + + qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + + if (dphistarminabs < cfgTwoTrackCut && TMath::Abs(deta) < cfgTwoTrackCut) { + //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.charge(), track2.phi2(), track2.pt(), track2.charge(), bSign); + return true; + } + + qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + } + } + + return false; + } + + template <typename T> + float getDPhiStar(T const& track1, T const& track2, float radius, float bSign) + { + // + // calculates dphistar + // + + auto phi1 = track1.phi(); + auto pt1 = track1.pt(); + auto charge1 = track1.charge(); + + auto phi2 = track2.phi(); + auto pt2 = track2.pt(); + auto charge2 = track2.charge(); + + float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); + + static const Double_t kPi = TMath::Pi(); + + if (dphistar > kPi) + dphistar = kPi * 2 - dphistar; + if (dphistar < -kPi) + dphistar = -kPi * 2 - dphistar; + if (dphistar > kPi) // might look funny but is needed + dphistar = kPi * 2 - dphistar; + + return dphistar; + } }; WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<CorrelationTask>("correlation-task"), - }; + adaptAnalysisTask<CorrelationTask>("correlation-task")}; } diff --git a/Analysis/Tasks/correlationsCollection.cxx b/Analysis/Tasks/correlationsCollection.cxx deleted file mode 100644 index 874c21efcd45f..0000000000000 --- a/Analysis/Tasks/correlationsCollection.cxx +++ /dev/null @@ -1,478 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" -#include "Analysis/StepTHn.h" -#include "Analysis/CorrelationContainer.h" - -#include <TH1F.h> -#include <cmath> -#include <TDirectory.h> - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP}; - -struct CorrelationTask { - - // Filters and input definitions - Filter trackFilter = (aod::track::eta > -0.8f) && (aod::track::eta < 0.8f) && (aod::track::pt > 1.0f); - using myTracks = soa::Filtered<aod::Tracks>; - - // Output definitions - OutputObj<CorrelationContainer> same{"sameEvent"}; - OutputObj<CorrelationContainer> mixed{"mixedEvent"}; - //OutputObj<TDirectory> qaOutput{"qa"}; - - // Configuration - 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"); - - O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value"); - O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); - - O2_DEFINE_CONFIGURABLE(cfgPairCutPhoton, float, -1, "Pair cut on photons: -1 = off; >0 otherwise distance value (suggested: 0.004)") - O2_DEFINE_CONFIGURABLE(cfgPairCutK0, float, -1, "Pair cut on K0s: -1 = off; >0 otherwise distance value (suggested: 0.005)") - O2_DEFINE_CONFIGURABLE(cfgPairCutLambda, float, -1, "Pair cut on Lambda: -1 = off; >0 otherwise distance value (suggested: 0.005)") - 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") - - enum PairCuts { Photon = 0, - K0, - Lambda, - Phi, - Rho }; - struct Config { - bool mPairCuts = false; - //THn* mEfficiencyTrigger = nullptr; - //THn* mEfficiencyAssociated = nullptr; - } cfg; - - struct QA { - TH3F* mTwoTrackDistancePt[2] = {nullptr}; // control histograms for two-track efficiency study: dphi*_min vs deta (0 = before cut, 1 = after cut) - TH2F* mControlConvResoncances = nullptr; // control histograms for cuts on conversions and resonances - } qa; - - void init(o2::framework::InitContext&) - { - // --- CONFIGURATION --- - const char* binning = - "vertex: -7, -5, -3, -1, 1, 3, 5, 7\n" - "delta_phi: -1.570796, -1.483530, -1.396263, -1.308997, -1.221730, -1.134464, -1.047198, -0.959931, -0.872665, -0.785398, -0.698132, -0.610865, -0.523599, -0.436332, -0.349066, -0.261799, -0.174533, -0.087266, 0.0, 0.087266, 0.174533, 0.261799, 0.349066, 0.436332, 0.523599, 0.610865, 0.698132, 0.785398, 0.872665, 0.959931, 1.047198, 1.134464, 1.221730, 1.308997, 1.396263, 1.483530, 1.570796, 1.658063, 1.745329, 1.832596, 1.919862, 2.007129, 2.094395, 2.181662, 2.268928, 2.356194, 2.443461, 2.530727, 2.617994, 2.705260, 2.792527, 2.879793, 2.967060, 3.054326, 3.141593, 3.228859, 3.316126, 3.403392, 3.490659, 3.577925, 3.665191, 3.752458, 3.839724, 3.926991, 4.014257, 4.101524, 4.188790, 4.276057, 4.363323, 4.450590, 4.537856, 4.625123, 4.712389\n" - "delta_eta: -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 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, 1.6, 1.7, 1.8, 1.9, 2.0\n" - "p_t_assoc: 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0\n" - "p_t_trigger: 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0\n" - "multiplicity: 0, 5, 10, 20, 30, 40, 50, 100.1\n" - "eta: -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0\n" - "p_t_leading: 0.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, 8.5, 9.0, 9.5, 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5, 20.0, 20.5, 21.0, 21.5, 22.0, 22.5, 23.0, 23.5, 24.0, 24.5, 25.0, 25.5, 26.0, 26.5, 27.0, 27.5, 28.0, 28.5, 29.0, 29.5, 30.0, 30.5, 31.0, 31.5, 32.0, 32.5, 33.0, 33.5, 34.0, 34.5, 35.0, 35.5, 36.0, 36.5, 37.0, 37.5, 38.0, 38.5, 39.0, 39.5, 40.0, 40.5, 41.0, 41.5, 42.0, 42.5, 43.0, 43.5, 44.0, 44.5, 45.0, 45.5, 46.0, 46.5, 47.0, 47.5, 48.0, 48.5, 49.0, 49.5, 50.0\n" - "p_t_leading_course: 0.5, 1.0, 2.0, 3.0, 4.0, 6.0, 8.0\n" - "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" - "vertex_eff: -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10\n"; - - if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) - cfg.mPairCuts = true; - - // --- OBJECT INIT --- - same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentrality", binning)); - mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentrality", binning)); - //qaOutput.setObject(new TDirectory("qa", "qa")); - - if (cfgTwoTrackCut > 0) { - qa.mTwoTrackDistancePt[0] = new TH3F("TwoTrackDistancePt[0]", ";#Delta#eta;#Delta#varphi^{*}_{min};#Delta p_{T}", 100, -0.15, 0.15, 100, -0.05, 0.05, 20, 0, 10); - qa.mTwoTrackDistancePt[1] = (TH3F*)qa.mTwoTrackDistancePt[0]->Clone("TwoTrackDistancePt[1]"); - //qaOutput->Add(qa.mTwoTrackDistancePt[0]); - //qaOutput->Add(qa.mTwoTrackDistancePt[1]); - } - - if (cfg.mPairCuts) { - qa.mControlConvResoncances = new TH2F("ControlConvResoncances", ";id;delta mass", 6, -0.5, 5.5, 500, -0.5, 0.5); - //qaOutput->Add(qa.mControlConvResoncances); - } - } - - // Version with explicit nested loop - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, aod::BCs const& bcs, aod::Run2V0s const& vzeros, myTracks const& tracks) - { - LOGF(info, "Tracks for collision: %d | Trigger mask: %lld | INT7: %d | V0M: %.1f", tracks.size(), collision.bc().triggerMask(), collision.sel7(), collision.centV0M()); - - if (!collision.sel7()) - return; - - int bSign = 1; // TODO magnetic field from CCDB - const float pTCut = 1.0; - - for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { - - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) - continue; - - //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); - - double eventValues[3]; - eventValues[0] = track1.pt(); - eventValues[1] = collision.centV0M(); - eventValues[2] = collision.posZ(); - - same->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - //mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - - for (auto track2 = track1 + 1; track2 != tracks.end(); ++track2) { - - if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) - continue; - if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) - continue; - - if (cfg.mPairCuts && conversionCuts(track1, track2)) - continue; - - if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) - continue; - - double values[6] = {0}; - - values[0] = track1.eta() - track2.eta(); - values[1] = track1.pt(); - values[2] = track2.pt(); - values[3] = collision.centV0M(); - - values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) - values[4] -= TMath::TwoPi(); - if (values[4] < -0.5 * TMath::Pi()) - values[4] += TMath::TwoPi(); - - values[5] = collision.posZ(); - - same->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); - //mixed->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); - } - } - } - - // Version with combinations - void process2(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& tracks) - { - LOGF(info, "Tracks for collision (Combination run): %d", tracks.size()); - - int bSign = 1; // TODO magnetic field from CCDB - - for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { - - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) - continue; - - // LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); - - double eventValues[3]; - eventValues[0] = track1.pt(); - eventValues[1] = 0; // collision.v0mult(); - eventValues[2] = collision.posZ(); - - same->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - //mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - } - - for (auto& [track1, track2] : combinations(tracks, tracks)) { - //LOGF(info, "Combination %d %d", track1.index(), track2.index()); - - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) - continue; - if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) - continue; - if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) - continue; - - if (cfg.mPairCuts && conversionCuts(track1, track2)) - continue; - - if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) - continue; - - double values[6] = {0}; - - values[0] = track1.eta() - track2.eta(); - values[1] = track1.pt(); - values[2] = track2.pt(); - values[3] = 0; // collision.v0mult(); - - values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) - values[4] -= TMath::TwoPi(); - if (values[4] < -0.5 * TMath::Pi()) - values[4] += TMath::TwoPi(); - - values[5] = collision.posZ(); - - same->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); - //mixed->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); - } - } - - template <typename T> - bool conversionCuts(T const& track1, T const& track2) - { - // skip if like sign - if (track1.charge() * track2.charge() > 0) - return false; - - bool decision = false; - - if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) - decision = true; - if (conversionCut(track1, track2, K0, cfgPairCutK0)) - decision = true; - if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) - decision = true; - if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) - decision = true; - if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) - decision = true; - if (conversionCut(track1, track2, Rho, cfgPairCutRho)) - decision = true; - - return decision; - } - - template <typename T> - bool conversionCut(T const& track1, T const& track2, PairCuts conv, double cut) - { - //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); - - if (cut < 0) - return false; - - double massD1, massD2, massM; - - switch (conv) { - case Photon: - massD1 = 0.51e-3; - massD2 = 0.51e-3; - massM = 0; - break; - case K0: - massD1 = 0.1396; - massD2 = 0.1396; - massM = 0.4976; - break; - case Lambda: - massD1 = 0.9383; - massD2 = 0.1396; - massM = 1.115; - break; - case Phi: - massD1 = 0.4937; - massD2 = 0.4937; - massM = 1.019; - break; - case Rho: - massD1 = 0.1396; - massD2 = 0.1396; - massM = 0.770; - break; - } - - auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); - - if (TMath::Abs(massC - massM * massM) > cut * 5) - return false; - - massC = getInvMassSquared(track1, massD1, track2, massD2); - qa.mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); - if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) - return true; - - return false; - } - - template <typename T> - double getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2) - { - // calculate inv mass squared - // same can be achieved, but with more computing time with - /*TLorentzVector photon, p1, p2; - p1.SetPtEtaPhiM(triggerParticle->Pt(), triggerEta, triggerParticle->Phi(), 0.510e-3); - p2.SetPtEtaPhiM(particle->Pt(), eta[j], particle->Phi(), 0.510e-3); - photon = p1+p2; - photon.M()*/ - - float tantheta1 = 1e10; - - if (track1.eta() < -1e-10 || track1.eta() > 1e-10) { - float expTmp = TMath::Exp(-track1.eta()); - tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float tantheta2 = 1e10; - if (track2.eta() < -1e-10 || track2.eta() > 1e-10) { - float expTmp = TMath::Exp(-track2.eta()); - tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); - float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); - - float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (TMath::Cos(track1.phi() - track2.phi()) + 1.0 / tantheta1 / tantheta2))); - - // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); - - return mass2; - } - - template <typename T> - double getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2) - { - // calculate inv mass squared approximately - - const float eta1 = track1.eta(); - const float eta2 = track2.eta(); - const float phi1 = track1.phi(); - const float phi2 = track2.phi(); - const float pt1 = track1.pt(); - const float pt2 = track2.pt(); - - float tantheta1 = 1e10; - - if (eta1 < -1e-10 || eta1 > 1e-10) { - float expTmp = 1.0 - eta1 + eta1 * eta1 / 2 - eta1 * eta1 * eta1 / 6 + eta1 * eta1 * eta1 * eta1 / 24; - tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float tantheta2 = 1e10; - if (eta2 < -1e-10 || eta2 > 1e-10) { - float expTmp = 1.0 - eta2 + eta2 * eta2 / 2 - eta2 * eta2 * eta2 / 6 + eta2 * eta2 * eta2 * eta2 / 24; - tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float e1squ = m0_1 * m0_1 + pt1 * pt1 * (1.0 + 1.0 / tantheta1 / tantheta1); - float e2squ = m0_2 * m0_2 + pt2 * pt2 * (1.0 + 1.0 / tantheta2 / tantheta2); - - // fold onto 0...pi - float deltaPhi = TMath::Abs(phi1 - phi2); - while (deltaPhi > TMath::TwoPi()) - deltaPhi -= TMath::TwoPi(); - if (deltaPhi > TMath::Pi()) - deltaPhi = TMath::TwoPi() - deltaPhi; - - float cosDeltaPhi = 0; - if (deltaPhi < TMath::Pi() / 3) - cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; - else if (deltaPhi < 2 * TMath::Pi() / 3) - cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); - else - cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); - - double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); - - // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); - - return mass2; - } - - template <typename T> - bool twoTrackCut(T const& track1, T const& track2, int bSign) - { - // the variables & cuthave been developed by the HBT group - // see e.g. https://indico.cern.ch/materialDisplay.py?contribId=36&sessionId=6&materialId=slides&confId=142700 - - auto deta = track1.eta() - track2.eta(); - - // optimization - if (TMath::Abs(deta) < cfgTwoTrackCut * 2.5 * 3) { - // check first boundaries to see if is worth to loop and find the minimum - float dphistar1 = getDPhiStar(track1, track2, cfgTwoTrackCutMinRadius, bSign); - float dphistar2 = getDPhiStar(track1, track2, 2.5, bSign); - - const float kLimit = cfgTwoTrackCut * 3; - - if (TMath::Abs(dphistar1) < kLimit || TMath::Abs(dphistar2) < kLimit || dphistar1 * dphistar2 < 0) { - float dphistarminabs = 1e5; - float dphistarmin = 1e5; - for (Double_t rad = cfgTwoTrackCutMinRadius; rad < 2.51; rad += 0.01) { - float dphistar = getDPhiStar(track1, track2, rad, bSign); - - float dphistarabs = TMath::Abs(dphistar); - - if (dphistarabs < dphistarminabs) { - dphistarmin = dphistar; - dphistarminabs = dphistarabs; - } - } - - qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); - - if (dphistarminabs < cfgTwoTrackCut && TMath::Abs(deta) < cfgTwoTrackCut) { - //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.charge(), track2.phi2(), track2.pt(), track2.charge(), bSign); - return true; - } - - qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); - } - } - - return false; - } - - template <typename T> - float getDPhiStar(T const& track1, T const& track2, float radius, float bSign) - { - // - // calculates dphistar - // - - auto phi1 = track1.phi(); - auto pt1 = track1.pt(); - auto charge1 = track1.charge(); - - auto phi2 = track2.phi(); - auto pt2 = track2.pt(); - auto charge2 = track2.charge(); - - float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); - - static const Double_t kPi = TMath::Pi(); - - if (dphistar > kPi) - dphistar = kPi * 2 - dphistar; - if (dphistar < -kPi) - dphistar = -kPi * 2 - dphistar; - if (dphistar > kPi) // might look funny but is needed - dphistar = kPi * 2 - dphistar; - - return dphistar; - } - - // template<typename... Ts> - // unsigned int getFilterBit(soa::Table<Ts...>::iterator const& track) - // { - // if constexpr(!has_type_v<aod::track::X, pack<Ts...>>) - // static_assert("Need to pass aod::track"); - // - // - // // LOGF(info, "pt %f", track1.pt()); - // return false; - // } - - // float getInvMassSquared(float pt1, float eta1, float phi1, float pt2, float eta2, float phi2, float m0_1, float m0_2) -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<CorrelationTask>("correlation-task")}; -} From 8021ec6ab3664faceffb5db5bd2e9a7d537ac8b1 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 4 Sep 2020 10:23:10 +0200 Subject: [PATCH 0536/1751] DPL Analysis: ability to use some Configurables in filters (#4274) --- Analysis/Tutorials/src/histograms.cxx | 7 +- Analysis/Tutorials/src/partitions.cxx | 12 +- .../Core/include/Framework/AnalysisHelpers.h | 495 +++++++++- .../Core/include/Framework/AnalysisTask.h | 900 +----------------- .../Core/include/Framework/Configurable.h | 43 + .../Core/include/Framework/Expressions.h | 121 ++- Framework/Core/src/AnalysisHelpers.cxx | 2 +- Framework/Core/src/AnalysisManagers.h | 420 ++++++++ Framework/Core/src/ExpressionHelpers.h | 8 + Framework/Core/src/Expressions.cxx | 57 +- Framework/Core/test/test_AnalysisTask.cxx | 2 +- Framework/Core/test/test_Expressions.cxx | 11 + 12 files changed, 1173 insertions(+), 905 deletions(-) create mode 100644 Framework/Core/include/Framework/Configurable.h create mode 100644 Framework/Core/src/AnalysisManagers.h diff --git a/Analysis/Tutorials/src/histograms.cxx b/Analysis/Tutorials/src/histograms.cxx index 01b775f85c426..4b8bf0bac23a5 100644 --- a/Analysis/Tutorials/src/histograms.cxx +++ b/Analysis/Tutorials/src/histograms.cxx @@ -16,6 +16,7 @@ using namespace o2; using namespace o2::framework; +using namespace o2::framework::expressions; // This is a very simple example showing how to create an histogram // FIXME: this should really inherit from AnalysisTask but @@ -58,6 +59,8 @@ struct CTask { OutputObj<TH1F> trZ{"trZ", OutputObjHandlingPolicy::QAObject}; Configurable<float> pTCut{"pTCut", 0.5f, "Lower pT limit"}; + Filter ptfilter = aod::track::pt > pTCut; + void init(InitContext const&) { trZ.setObject(new TH1F("Z", "Z", 100, -10., 10.)); @@ -67,11 +70,9 @@ struct CTask { // trZ.setObject({"Z","Z",100,-10.,10.}); <- creates new } - void process(aod::Tracks const& tracks) + void process(soa::Filtered<aod::Tracks> const& tracks) { for (auto& track : tracks) { - if (track.pt() < pTCut) - continue; ptH->Fill(track.pt()); trZ->Fill(track.z()); } diff --git a/Analysis/Tutorials/src/partitions.cxx b/Analysis/Tutorials/src/partitions.cxx index ca56c4c4209d7..d0c5e10f1af45 100644 --- a/Analysis/Tutorials/src/partitions.cxx +++ b/Analysis/Tutorials/src/partitions.cxx @@ -21,17 +21,17 @@ using namespace o2::framework::expressions; // we need GCC 7.4+ for that struct ATask { float fPI = static_cast<float>(M_PI); - float ptlow = 0.5f; - float ptup = 2.0f; + Configurable<float> ptlow{"pTlow", 0.5f, "Lowest pT"}; + Configurable<float> ptup{"pTup", 2.0f, "highest pT"}; Filter ptFilter_a = aod::track::pt > ptlow; Filter ptFilter_b = aod::track::pt < ptup; - float etalow = -1.0f; - float etaup = 1.0f; + Configurable<float> etalow{"etaLow", -1.0f, "lowest eta"}; + Configurable<float> etaup{"etaUp", 1.0f, "highest eta"}; Filter etafilter = (aod::track::eta < etaup) && (aod::track::eta > etalow); - float philow = 1.0f; - float phiup = 2.0f; + Configurable<float> philow{"phiLow", 1.0f, "lowest phi"}; + Configurable<float> phiup{"phiUp", 2.0f, "highest phi"}; using myTracks = soa::Filtered<aod::Tracks>; diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 08c91d3f993ff..0749cd0dcc2f6 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -10,18 +10,501 @@ #ifndef o2_framework_AnalysisHelpers_H_DEFINED #define o2_framework_AnalysisHelpers_H_DEFINED -#include "Framework/AnalysisHelpers.h" - +#include "Framework/Traits.h" +#include "Framework/TableBuilder.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/OutputSpec.h" +#include "Framework/OutputRef.h" +#include "Framework/InputSpec.h" +#include "Framework/OutputObjHeader.h" +#include "Framework/StringHelpers.h" #include <ROOT/RDataFrame.hxx> #include <string> -namespace o2 -{ -namespace framework +namespace o2::framework { class TableConsumer; -} +template <typename T> +struct WritingCursor { + static_assert(always_static_assert_v<T>, "Type must be a o2::soa::Table"); +}; +/// Helper class actually implementing the cursor which can write to +/// a table. The provided template arguments are if type Column and +/// therefore refer only to the persisted columns. +template <typename... PC> +struct WritingCursor<soa::Table<PC...>> { + using persistent_table_t = soa::Table<PC...>; + using cursor_t = decltype(std::declval<TableBuilder>().cursor<persistent_table_t>()); + + template <typename... T> + void operator()(T... args) + { + static_assert(sizeof...(PC) == sizeof...(T), "Argument number mismatch"); + ++mCount; + cursor(0, extract(args)...); + } + + /// Last index inserted in the table + int64_t lastIndex() + { + return mCount; + } + + bool resetCursor(TableBuilder& builder) + { + mBuilder = &builder; + cursor = std::move(FFL(builder.cursor<persistent_table_t>())); + mCount = -1; + return true; + } + + /// reserve @a size rows when filling, so that we do not + /// spend time reallocating the buffers. + void reserve(int64_t size) + { + mBuilder->reserve(typename persistent_table_t::columns{}, size); + } + + decltype(FFL(std::declval<cursor_t>())) cursor; + + private: + template <typename T> + static decltype(auto) extract(T const& arg) + { + if constexpr (soa::is_soa_iterator_t<T>::value) { + return arg.globalIndex(); + } else { + static_assert(!framework::has_type_v<T, framework::pack<PC...>>, "Argument type mismatch"); + return arg; + } + } + + /// The table builder which actually performs the + /// construction of the table. We keep it around to be + /// able to do all-columns methods like reserve. + TableBuilder* mBuilder = nullptr; + int64_t mCount = -1; +}; + +template <typename T> +struct Produces { + static_assert(always_static_assert_v<T>, "Type must be a o2::soa::Table"); +}; + +/// This helper class allows you to declare things which will be created by a +/// given analysis task. Notice how the actual cursor is implemented by the +/// means of the WritingCursor helper class, from which produces actually +/// derives. +template <typename... C> +struct Produces<soa::Table<C...>> : WritingCursor<typename soa::FilterPersistentColumns<soa::Table<C...>>::persistent_table_t> { + using table_t = soa::Table<C...>; + using metadata = typename aod::MetadataTrait<table_t>::metadata; + + // @return the associated OutputSpec + OutputSpec const spec() + { + return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; + } + + OutputRef ref() + { + return OutputRef{metadata::tableLabel(), 0}; + } +}; + +/// Base template for table transformation declarations +template <typename T> +struct TransformTable { + using metadata = typename aod::MetadataTrait<T>::metadata; + using originals = typename metadata::originals; + + template <typename O> + InputSpec const base_spec() + { + using o_metadata = typename aod::MetadataTrait<O>::metadata; + return InputSpec{ + o_metadata::tableLabel(), + header::DataOrigin{o_metadata::origin()}, + header::DataDescription{o_metadata::description()}}; + } + + template <typename... Os> + std::vector<InputSpec> const base_specs_impl(framework::pack<Os...>) + { + return {base_spec<Os>()...}; + } + + std::vector<InputSpec> const base_specs() + { + return base_specs_impl(originals{}); + } + + OutputSpec const spec() const + { + return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; + } + + OutputRef ref() const + { + return OutputRef{metadata::tableLabel(), 0}; + } + + T* operator->() + { + return table.get(); + } + T& operator*() + { + return *table.get(); + } + + auto asArrowTable() + { + return table->asArrowTable(); + } + std::shared_ptr<T> table = nullptr; +}; + +/// This helper struct allows you to declare extended tables which should be +/// created by the task (as opposed to those pre-defined by data model) +template <typename T> +struct Spawns : TransformTable<T> { + using metadata = typename TransformTable<T>::metadata; + using originals = typename metadata::originals; + using expression_pack_t = typename metadata::expression_pack_t; + + constexpr auto pack() + { + return expression_pack_t{}; + } +}; + +/// Policy to control index building +/// Exclusive index: each entry in a row has a valid index +struct IndexExclusive { + /// Generic builder for in index table + template <typename... Cs, typename Key, typename T1, typename... T> + static auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) + { + static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); + using tables_t = framework::pack<T...>; + using first_t = T1; + auto tail = tuple_tail(tables); + TableBuilder builder; + auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); + + std::array<int32_t, sizeof...(T)> values; + iterator_tuple_t<std::decay_t<T>...> iterators = std::apply( + [](auto&&... x) { + return std::make_tuple(x.begin()...); + }, + tail); + + using rest_it_t = decltype(pack_from_tuple(iterators)); + + int32_t idx = -1; + auto setValue = [&](auto& x) -> bool { + using type = std::decay_t<decltype(x)>; + constexpr auto position = framework::has_type_at<type>(rest_it_t{}); + + lowerBound<Key>(idx, x); + if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { + return false; + } else if (x.template getId<Key>() != idx) { + return false; + } else { + values[position] = x.globalIndex(); + ++x; + return true; + } + }; + + auto first = std::get<first_t>(tables); + for (auto& row : first) { + idx = row.template getId<Key>(); + + if (std::apply( + [](auto&... x) { + return ((x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) && ...); + }, + iterators)) { + break; + } + + auto result = std::apply( + [&](auto&... x) { + std::array<bool, sizeof...(T)> results{setValue(x)...}; + return (results[framework::has_type_at<std::decay_t<decltype(x)>>(rest_it_t{})] && ...); + }, + iterators); + + if (result) { + cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); + } + } + return builder.finalize(); + } +}; +/// Sparse index: values in a row can be (-1), index table is isomorphic (joinable) +/// to T1 +struct IndexSparse { + template <typename... Cs, typename Key, typename T1, typename... T> + static auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) + { + static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); + using tables_t = framework::pack<T...>; + using first_t = T1; + auto tail = tuple_tail(tables); + TableBuilder builder; + auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); + + std::array<int32_t, sizeof...(T)> values; + + iterator_tuple_t<std::decay_t<T>...> iterators = std::apply( + [](auto&&... x) { + return std::make_tuple(x.begin()...); + }, + tail); + + using rest_it_t = decltype(pack_from_tuple(iterators)); + + int32_t idx = -1; + auto setValue = [&](auto& x) -> bool { + using type = std::decay_t<decltype(x)>; + constexpr auto position = framework::has_type_at<type>(rest_it_t{}); + + lowerBound<Key>(idx, x); + if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { + values[position] = -1; + return false; + } else if (x.template getId<Key>() != idx) { + values[position] = -1; + return false; + } else { + values[position] = x.globalIndex(); + ++x; + return true; + } + }; + + auto first = std::get<first_t>(tables); + for (auto& row : first) { + idx = row.template getId<Key>(); + std::apply( + [&](auto&... x) { + (setValue(x), ...); + }, + iterators); + + cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); + } + return builder.finalize(); + } +}; + +/// This helper struct allows you to declare index tables to be created in a task +template <typename T, typename IP = IndexSparse> +struct Builds : TransformTable<T> { + using metadata = typename TransformTable<T>::metadata; + using originals = typename metadata::originals; + using Key = typename T::indexing_t; + using H = typename T::first_t; + using Ts = typename T::rest_t; + using index_pack_t = typename metadata::index_pack_t; + + constexpr auto pack() + { + return index_pack_t{}; + } + + template <typename... Cs, typename Key, typename T1, typename... Ts> + auto build(framework::pack<Cs...>, Key const& key, std::tuple<T1, Ts...> tables) + { + this->table = std::make_shared<T>(IP::indexBuilder(framework::pack<Cs...>{}, key, tables)); + return (this->table != nullptr); + } +}; + +template <typename T> +using BuildsExclusive = Builds<T, IndexExclusive>; + +/// This helper class allows you to declare things which will be created by a +/// given analysis task. Currently wrapped objects are limited to be TNamed +/// descendants. Objects will be written to a ROOT file at the end of the +/// workflow, in directories, corresponding to the task they were declared in. +/// Each object has associated handling policy, which is used by the framework +/// to determine the target file, e.g. analysis result, QA or control histogram, +/// etc. +template <typename T> +struct OutputObj { + using obj_t = T; + + OutputObj(T&& t, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) + : object(std::make_shared<T>(t)), + label(t.GetName()), + policy{policy_}, + mTaskHash{0} + { + } + + OutputObj(std::string const& label_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) + : object(nullptr), + label(label_), + policy{policy_}, + mTaskHash{0} + { + } + + void setObject(T const& t) + { + object = std::make_shared<T>(t); + object->SetName(label.c_str()); + } + + void setObject(T&& t) + { + object = std::make_shared<T>(t); + object->SetName(label.c_str()); + } + + void setObject(T* t) + { + object.reset(t); + object->SetName(label.c_str()); + } + + void setHash(uint32_t hash) + { + mTaskHash = hash; + } + + /// @return the associated OutputSpec + OutputSpec const spec() + { + header::DataDescription desc{}; + auto lhash = compile_time_hash(label.c_str()); + std::memset(desc.str, '_', 16); + std::stringstream s; + s << std::hex << lhash; + s << std::hex << mTaskHash; + s << std::hex << reinterpret_cast<uint64_t>(this); + std::memcpy(desc.str, s.str().c_str(), 12); + return OutputSpec{OutputLabel{label}, "ATSK", desc, 0}; + } + + T* operator->() + { + return object.get(); + } + + T& operator*() + { + return *object.get(); + } + + OutputRef ref() + { + return OutputRef{std::string{label}, 0, + o2::header::Stack{OutputObjHeader{policy, mTaskHash}}}; + } + + std::shared_ptr<T> object; + std::string label; + OutputObjHandlingPolicy policy; + uint32_t mTaskHash; +}; + +/// This helper allows you to fetch a Sevice from the context or +/// by using some singleton. This hopefully will hide the Singleton and +/// We will be able to retrieve it in a more thread safe manner later on. +template <typename T> +struct Service { + T* service; + + T* operator->() const + { + return service; + } +}; + +template <typename T> +struct Partition { + Partition(expressions::Node&& filter_) : filter{std::move(filter_)} + { + } + + void setTable(const T& table) + { + auto schema = table.asArrowTable()->schema(); + expressions::Operations ops = createOperations(filter); + if (isSchemaCompatible(schema, ops)) { + mTree = createExpressionTree(ops, schema); + } else { + throw std::runtime_error("Partition filter does not match declared table type"); + } + + if constexpr (soa::is_soa_filtered_t<std::decay_t<T>>::value) { + mFiltered.reset(new o2::soa::Filtered<T>{{table}, mTree}); + } else { + mFiltered.reset(new o2::soa::Filtered<T>{{table.asArrowTable()}, mTree}); + } + } + + template <typename... Ts> + void bindExternalIndices(Ts*... tables) + { + if (mFiltered != nullptr) { + mFiltered->bindExternalIndices(tables...); + } + } + + template <typename T2> + void getBoundToExternalIndices(T2& table) + { + if (mFiltered != nullptr) { + table.bindExternalIndices(mFiltered.get()); + } + } + + void updatePlaceholders(InitContext& context) + { + expressions::updatePlaceholders(filter, context); + } + + expressions::Filter filter; + gandiva::NodePtr mTree = nullptr; + std::unique_ptr<o2::soa::Filtered<T>> mFiltered = nullptr; + + using filtered_iterator = typename o2::soa::Filtered<T>::iterator; + using filtered_const_iterator = typename o2::soa::Filtered<T>::const_iterator; + inline filtered_iterator begin() + { + return mFiltered->begin(); + } + inline o2::soa::RowViewSentinel end() + { + return mFiltered->end(); + } + inline filtered_const_iterator begin() const + { + return mFiltered->begin(); + } + inline o2::soa::RowViewSentinel end() const + { + return mFiltered->end(); + } + + int64_t size() const + { + return mFiltered->size(); + } +}; + +} // namespace o2::framework + +namespace o2 +{ namespace analysis { diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 80272907e3624..426a7f56a4483 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -11,25 +11,19 @@ #ifndef FRAMEWORK_ANALYSIS_TASK_H_ #define FRAMEWORK_ANALYSIS_TASK_H_ -#include "Framework/Kernels.h" +#include "../../src/AnalysisManagers.h" #include "Framework/AlgorithmSpec.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/CallbackService.h" #include "Framework/ControlService.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/ConfigParamRegistry.h" #include "Framework/DataProcessorSpec.h" #include "Framework/Expressions.h" #include "../src/ExpressionHelpers.h" #include "Framework/EndOfStreamContext.h" #include "Framework/Logger.h" -#include "Framework/HistogramRegistry.h" #include "Framework/StructToTuple.h" #include "Framework/FunctionalHelpers.h" #include "Framework/Traits.h" #include "Framework/VariantHelpers.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/RootConfigParamHelpers.h" #include <arrow/compute/kernel.h> #include <arrow/table.h> @@ -41,7 +35,6 @@ #include <iomanip> namespace o2::framework { - /// A more familiar task API for the DPL analysis framework. /// This allows you to define your own tasks as subclasses /// of o2::framework::AnalysisTask and to pass them in the specification @@ -52,545 +45,6 @@ namespace o2::framework // FIXME: for the moment this needs to stay outside AnalysisTask // because we cannot inherit from it due to a C++17 bug // in GCC 7.3. We need to move to 7.4+ -template <typename T> -struct WritingCursor { - static_assert(always_static_assert_v<T>, "Type must be a o2::soa::Table"); -}; - -template <typename T> -struct Produces { - static_assert(always_static_assert_v<T>, "Type must be a o2::soa::Table"); -}; - -/// Helper class actually implementing the cursor which can write to -/// a table. The provided template arguments are if type Column and -/// therefore refer only to the persisted columns. -template <typename... PC> -struct WritingCursor<soa::Table<PC...>> { - using persistent_table_t = soa::Table<PC...>; - using cursor_t = decltype(std::declval<TableBuilder>().cursor<persistent_table_t>()); - - template <typename... T> - void operator()(T... args) - { - static_assert(sizeof...(PC) == sizeof...(T), "Argument number mismatch"); - ++mCount; - cursor(0, extract(args)...); - } - - /// Last index inserted in the table - int64_t lastIndex() - { - return mCount; - } - - bool resetCursor(TableBuilder& builder) - { - mBuilder = &builder; - cursor = std::move(FFL(builder.cursor<persistent_table_t>())); - mCount = -1; - return true; - } - - /// reserve @a size rows when filling, so that we do not - /// spend time reallocating the buffers. - void reserve(int64_t size) - { - mBuilder->reserve(typename persistent_table_t::columns{}, size); - } - - decltype(FFL(std::declval<cursor_t>())) cursor; - - private: - template <typename T> - static decltype(auto) extract(T const& arg) - { - if constexpr (soa::is_soa_iterator_t<T>::value) { - return arg.globalIndex(); - } else { - static_assert(!framework::has_type_v<T, framework::pack<PC...>>, "Argument type mismatch"); - return arg; - } - } - - /// The table builder which actually performs the - /// construction of the table. We keep it around to be - /// able to do all-columns methods like reserve. - TableBuilder* mBuilder = nullptr; - int64_t mCount = -1; -}; - -/// This helper class allows you to declare things which will be created by a -/// given analysis task. Notice how the actual cursor is implemented by the -/// means of the WritingCursor helper class, from which produces actually -/// derives. -template <typename... C> -struct Produces<soa::Table<C...>> : WritingCursor<typename soa::FilterPersistentColumns<soa::Table<C...>>::persistent_table_t> { - using table_t = soa::Table<C...>; - using metadata = typename aod::MetadataTrait<table_t>::metadata; - - // @return the associated OutputSpec - OutputSpec const spec() - { - return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; - } - - OutputRef ref() - { - return OutputRef{metadata::tableLabel(), 0}; - } -}; - -/// Base template for table transformation declarations -template <typename T> -struct TransformTable { - using metadata = typename aod::MetadataTrait<T>::metadata; - using originals = typename metadata::originals; - - template <typename O> - InputSpec const base_spec() - { - using o_metadata = typename aod::MetadataTrait<O>::metadata; - return InputSpec{ - o_metadata::tableLabel(), - header::DataOrigin{o_metadata::origin()}, - header::DataDescription{o_metadata::description()}}; - } - - template <typename... Os> - std::vector<InputSpec> const base_specs_impl(framework::pack<Os...>) - { - return {base_spec<Os>()...}; - } - - std::vector<InputSpec> const base_specs() - { - return base_specs_impl(originals{}); - } - - OutputSpec const spec() const - { - return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; - } - - OutputRef ref() const - { - return OutputRef{metadata::tableLabel(), 0}; - } - - T* operator->() - { - return table.get(); - } - T& operator*() - { - return *table.get(); - } - - auto asArrowTable() - { - return table->asArrowTable(); - } - std::shared_ptr<T> table = nullptr; -}; - -/// This helper struct allows you to declare extended tables which should be -/// created by the task (as opposed to those pre-defined by data model) -template <typename T> -struct Spawns : TransformTable<T> { - using metadata = typename TransformTable<T>::metadata; - using originals = typename metadata::originals; - using expression_pack_t = typename metadata::expression_pack_t; - - constexpr auto pack() - { - return expression_pack_t{}; - } -}; - -/// Policy to control index building -/// Exclusive index: each entry in a row has a valid index -struct IndexExclusive { - /// Generic builder for in index table - template <typename... Cs, typename Key, typename T1, typename... T> - static auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) - { - static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); - using tables_t = framework::pack<T...>; - using first_t = T1; - auto tail = tuple_tail(tables); - TableBuilder builder; - auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); - - std::array<int32_t, sizeof...(T)> values; - iterator_tuple_t<std::decay_t<T>...> iterators = std::apply( - [](auto&&... x) { - return std::make_tuple(x.begin()...); - }, - tail); - - using rest_it_t = decltype(pack_from_tuple(iterators)); - - int32_t idx = -1; - auto setValue = [&](auto& x) -> bool { - using type = std::decay_t<decltype(x)>; - constexpr auto position = framework::has_type_at<type>(rest_it_t{}); - - lowerBound<Key>(idx, x); - if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { - return false; - } else if (x.template getId<Key>() != idx) { - return false; - } else { - values[position] = x.globalIndex(); - ++x; - return true; - } - }; - - auto first = std::get<first_t>(tables); - for (auto& row : first) { - idx = row.template getId<Key>(); - - if (std::apply( - [](auto&... x) { - return ((x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) && ...); - }, - iterators)) { - break; - } - - auto result = std::apply( - [&](auto&... x) { - std::array<bool, sizeof...(T)> results{setValue(x)...}; - return (results[framework::has_type_at<std::decay_t<decltype(x)>>(rest_it_t{})] && ...); - }, - iterators); - - if (result) { - cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); - } - } - return builder.finalize(); - } -}; -/// Sparse index: values in a row can be (-1), index table is isomorphic (joinable) -/// to T1 -struct IndexSparse { - template <typename... Cs, typename Key, typename T1, typename... T> - static auto indexBuilder(framework::pack<Cs...>, Key const&, std::tuple<T1, T...> tables) - { - static_assert(sizeof...(Cs) == sizeof...(T) + 1, "Number of columns does not coincide with number of supplied tables"); - using tables_t = framework::pack<T...>; - using first_t = T1; - auto tail = tuple_tail(tables); - TableBuilder builder; - auto cursor = framework::FFL(builder.cursor<o2::soa::Table<Cs...>>()); - - std::array<int32_t, sizeof...(T)> values; - - iterator_tuple_t<std::decay_t<T>...> iterators = std::apply( - [](auto&&... x) { - return std::make_tuple(x.begin()...); - }, - tail); - - using rest_it_t = decltype(pack_from_tuple(iterators)); - - int32_t idx = -1; - auto setValue = [&](auto& x) -> bool { - using type = std::decay_t<decltype(x)>; - constexpr auto position = framework::has_type_at<type>(rest_it_t{}); - - lowerBound<Key>(idx, x); - if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { - values[position] = -1; - return false; - } else if (x.template getId<Key>() != idx) { - values[position] = -1; - return false; - } else { - values[position] = x.globalIndex(); - ++x; - return true; - } - }; - - auto first = std::get<first_t>(tables); - for (auto& row : first) { - idx = row.template getId<Key>(); - std::apply( - [&](auto&... x) { - (setValue(x), ...); - }, - iterators); - - cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); - } - return builder.finalize(); - } -}; - -/// This helper struct allows you to declare index tables to be created in a task -template <typename T, typename IP = IndexSparse> -struct Builds : TransformTable<T> { - using metadata = typename TransformTable<T>::metadata; - using originals = typename metadata::originals; - using Key = typename T::indexing_t; - using H = typename T::first_t; - using Ts = typename T::rest_t; - using index_pack_t = typename metadata::index_pack_t; - - constexpr auto pack() - { - return index_pack_t{}; - } - - template <typename... Cs, typename Key, typename T1, typename... Ts> - auto build(framework::pack<Cs...>, Key const& key, std::tuple<T1, Ts...> tables) - { - this->table = std::make_shared<T>(IP::indexBuilder(framework::pack<Cs...>{}, key, tables)); - return (this->table != nullptr); - } -}; - -template <typename T> -using BuildsExclusive = Builds<T, IndexExclusive>; - -/// This helper class allows you to declare things which will be created by a -/// given analysis task. Currently wrapped objects are limited to be TNamed -/// descendants. Objects will be written to a ROOT file at the end of the -/// workflow, in directories, corresponding to the task they were declared in. -/// Each object has associated handling policy, which is used by the framework -/// to determine the target file, e.g. analysis result, QA or control histogram, -/// etc. -template <typename T> -struct OutputObj { - using obj_t = T; - - OutputObj(T&& t, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) - : object(std::make_shared<T>(t)), - label(t.GetName()), - policy{policy_}, - mTaskHash{0} - { - } - - OutputObj(std::string const& label_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) - : object(nullptr), - label(label_), - policy{policy_}, - mTaskHash{0} - { - } - - void setObject(T const& t) - { - object = std::make_shared<T>(t); - object->SetName(label.c_str()); - } - - void setObject(T&& t) - { - object = std::make_shared<T>(t); - object->SetName(label.c_str()); - } - - void setObject(T* t) - { - object.reset(t); - object->SetName(label.c_str()); - } - - void setHash(uint32_t hash) - { - mTaskHash = hash; - } - - /// @return the associated OutputSpec - OutputSpec const spec() - { - header::DataDescription desc{}; - auto lhash = compile_time_hash(label.c_str()); - std::memset(desc.str, '_', 16); - std::stringstream s; - s << std::hex << lhash; - s << std::hex << mTaskHash; - s << std::hex << reinterpret_cast<uint64_t>(this); - std::memcpy(desc.str, s.str().c_str(), 12); - return OutputSpec{OutputLabel{label}, "ATSK", desc, 0}; - } - - T* operator->() - { - return object.get(); - } - - T& operator*() - { - return *object.get(); - } - - OutputRef ref() - { - return OutputRef{std::string{label}, 0, - o2::header::Stack{OutputObjHeader{policy, mTaskHash}}}; - } - - std::shared_ptr<T> object; - std::string label; - OutputObjHandlingPolicy policy; - uint32_t mTaskHash; -}; - -/// This helper allows you to fetch a Sevice from the context or -/// by using some singleton. This hopefully will hide the Singleton and -/// We will be able to retrieve it in a more thread safe manner later on. -template <typename T> -struct Service { - T* service; - - T* operator->() const - { - return service; - } -}; - -/// This helper allows you to create a configurable option associated to a task. -/// Internally it will be bound to a ConfigParamSpec. -template <typename T> -struct Configurable { - Configurable(std::string const& name, T defaultValue, std::string const& help) - : name(name), value(defaultValue), help(help) - { - } - using type = T; - std::string name; - T value; - std::string help; - operator T() - { - return value; - } - T const* operator->() const - { - return &value; - } -}; - -template <typename T> -struct Partition { - Partition(expressions::Node&& node) - { - auto filter = expressions::Filter(std::move(node)); - auto schema = o2::soa::createSchemaFromColumns(typename T::persistent_columns_t{}); - expressions::Operations ops = createOperations(filter); - if (isSchemaCompatible(schema, ops)) { - mTree = createExpressionTree(ops, schema); - } else { - throw std::runtime_error("Partition filter does not match declared table type"); - } - } - - void setTable(const T& table) - { - if constexpr (soa::is_soa_filtered_t<std::decay_t<T>>::value) { - mFiltered.reset(new o2::soa::Filtered<T>{{table}, mTree}); - } else { - mFiltered.reset(new o2::soa::Filtered<T>{{table.asArrowTable()}, mTree}); - } - } - - template <typename... Ts> - void bindExternalIndices(Ts*... tables) - { - if (mFiltered != nullptr) { - mFiltered->bindExternalIndices(tables...); - } - } - - template <typename T2> - void getBoundToExternalIndices(T2& table) - { - if (mFiltered != nullptr) { - table.bindExternalIndices(mFiltered.get()); - } - } - - gandiva::NodePtr mTree; - std::unique_ptr<o2::soa::Filtered<T>> mFiltered; - - using filtered_iterator = typename o2::soa::Filtered<T>::iterator; - using filtered_const_iterator = typename o2::soa::Filtered<T>::const_iterator; - inline filtered_iterator begin() - { - return mFiltered->begin(); - } - inline o2::soa::RowViewSentinel end() - { - return mFiltered->end(); - } - inline filtered_const_iterator begin() const - { - return mFiltered->begin(); - } - inline o2::soa::RowViewSentinel end() const - { - return mFiltered->end(); - } - - int64_t size() const - { - return mFiltered->size(); - } -}; - -template <typename ANY> -struct PartitionManager { - template <typename... T2s> - static void setPartition(ANY&, T2s&...) - { - } - - template <typename... Ts> - static void bindExternalIndices(ANY&, Ts*...) - { - } - - template <typename... Ts> - static void getBoundToExternalIndices(ANY&, Ts&...) - { - } -}; - -template <typename T> -struct PartitionManager<Partition<T>> { - template <typename T2> - static void doSetPartition(Partition<T>& partition, T2& table) - { - if constexpr (std::is_same_v<T, T2>) { - partition.setTable(table); - } - } - - template <typename... T2s> - static void setPartition(Partition<T>& partition, T2s&... tables) - { - (doSetPartition(partition, tables), ...); - } - - template <typename... Ts> - static void bindExternalIndices(Partition<T>& partition, Ts*... tables) - { - partition.bindExternalIndices(tables...); - } - - template <typename... Ts> - static void getBoundToExternalIndices(Partition<T>& partition, Ts&... tables) - { - partition.getBoundToExternalIndices(tables...); - } -}; struct AnalysisTask { }; @@ -1041,330 +495,6 @@ struct AnalysisDataProcessorBuilder { } }; -template <typename ANY> -struct FilterManager { - static bool createExpressionTrees(ANY&, std::vector<ExpressionInfo>&) - { - return false; - } -}; - -template <> -struct FilterManager<expressions::Filter> { - static bool createExpressionTrees(expressions::Filter const& filter, std::vector<ExpressionInfo>& expressionInfos) - { - updateExpressionInfos(filter, expressionInfos); - return true; - } -}; - -/// SFINAE placeholder -template <typename T> -struct OutputManager { - template <typename ANY> - static bool appendOutput(std::vector<OutputSpec>&, ANY&, uint32_t) - { - return false; - } - - template <typename ANY> - static bool prepare(ProcessingContext&, ANY&) - { - return false; - } - - template <typename ANY> - static bool postRun(EndOfStreamContext&, ANY&) - { - return true; - } - - template <typename ANY> - static bool finalize(ProcessingContext&, ANY&) - { - return true; - } -}; - -/// Produces specialization -template <typename TABLE> -struct OutputManager<Produces<TABLE>> { - static bool appendOutput(std::vector<OutputSpec>& outputs, Produces<TABLE>& what, uint32_t) - { - outputs.emplace_back(what.spec()); - return true; - } - static bool prepare(ProcessingContext& context, Produces<TABLE>& what) - { - what.resetCursor(context.outputs().make<TableBuilder>(what.ref())); - return true; - } - static bool finalize(ProcessingContext&, Produces<TABLE>&) - { - return true; - } - static bool postRun(EndOfStreamContext&, Produces<TABLE>&) - { - return true; - } -}; - -/// HistogramRegistry specialization -template <> -struct OutputManager<HistogramRegistry> { - static bool appendOutput(std::vector<OutputSpec>& outputs, HistogramRegistry& what, uint32_t) - { - outputs.emplace_back(what.spec()); - return true; - } - static bool prepare(ProcessingContext&, HistogramRegistry&) - { - return true; - } - - static bool finalize(ProcessingContext&, HistogramRegistry&) - { - return true; - } - - static bool postRun(EndOfStreamContext&, HistogramRegistry&) - { - return true; - } -}; - -/// OutputObj specialization -template <typename T> -struct OutputManager<OutputObj<T>> { - static bool appendOutput(std::vector<OutputSpec>& outputs, OutputObj<T>& what, uint32_t hash) - { - what.setHash(hash); - outputs.emplace_back(what.spec()); - return true; - } - static bool prepare(ProcessingContext&, OutputObj<T>&) - { - return true; - } - - static bool finalize(ProcessingContext&, OutputObj<T>&) - { - return true; - } - - static bool postRun(EndOfStreamContext& context, OutputObj<T>& what) - { - context.outputs().snapshot(what.ref(), *what); - return true; - } -}; - -/// Spawns specializations -template <typename O> -static auto extractOriginal(ProcessingContext& pc) -{ - return pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable(); -} - -template <typename... Os> -static std::vector<std::shared_ptr<arrow::Table>> extractOriginals(framework::pack<Os...>, ProcessingContext& pc) -{ - return {extractOriginal<Os>(pc)...}; -} - -template <typename T> -struct OutputManager<Spawns<T>> { - static bool appendOutput(std::vector<OutputSpec>& outputs, Spawns<T>& what, uint32_t) - { - outputs.emplace_back(what.spec()); - return true; - } - - static bool prepare(ProcessingContext& pc, Spawns<T>& what) - { - using metadata = typename std::decay_t<decltype(what)>::metadata; - auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(typename metadata::originals{}, pc)); - what.table = std::make_shared<T>(o2::soa::spawner(what.pack(), original_table.get())); - return true; - } - - static bool finalize(ProcessingContext&, Spawns<T>&) - { - return true; - } - - static bool postRun(EndOfStreamContext& eosc, Spawns<T>& what) - { - using metadata = typename std::decay_t<decltype(what)>::metadata; - eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); - return true; - } -}; - -/// Builds specialization -template <typename O> -static auto extractTypedOriginal(ProcessingContext& pc) -{ - ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables - return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; -} - -template <typename... Os> -static auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) -{ - return std::make_tuple(extractTypedOriginal<Os>(pc)...); -} - -template <typename T, typename P> -struct OutputManager<Builds<T, P>> { - static bool appendOutput(std::vector<OutputSpec>& outputs, Builds<T, P>& what, uint32_t) - { - outputs.emplace_back(what.spec()); - return true; - } - - static bool prepare(ProcessingContext& pc, Builds<T, P>& what) - { - using metadata = typename std::decay_t<decltype(what)>::metadata; - return what.build(typename metadata::index_pack_t{}, - extractTypedOriginal<typename metadata::Key>(pc), - extractOriginalsTuple(typename metadata::originals{}, pc)); - } - - static bool finalize(ProcessingContext&, Builds<T, P>&) - { - return true; - } - - static bool postRun(EndOfStreamContext& eosc, Builds<T, P>& what) - { - using metadata = typename std::decay_t<decltype(what)>::metadata; - eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); - return true; - } -}; - -template <typename T> -class has_instance -{ - typedef char one; - struct two { - char x[2]; - }; - - template <typename C> - static one test(decltype(&C::instance)); - template <typename C> - static two test(...); - - public: - enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; -}; - -template <typename T> -struct ServiceManager { - template <typename ANY> - static bool prepare(InitContext&, ANY&) - { - return false; - } -}; - -template <typename T> -struct ServiceManager<Service<T>> { - static bool prepare(InitContext& context, Service<T>& service) - { - if constexpr (has_instance<T>::value) { - service.service = &(T::instance()); // Sigh... - return true; - } else { - service.service = context.services().get<T>(); - return true; - } - return false; - } -}; - -template <typename T> -struct OptionManager { - template <typename ANY> - static bool appendOption(std::vector<ConfigParamSpec>&, ANY&) - { - return false; - } - - template <typename ANY> - static bool prepare(InitContext&, ANY&) - { - return false; - } -}; - -template <typename T> -struct OptionManager<Configurable<T>> { - static bool appendOption(std::vector<ConfigParamSpec>& options, Configurable<T>& what) - { - if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { - options.emplace_back(ConfigParamSpec{what.name, variant_trait_v<typename std::decay<T>::type>, what.value, {what.help}}); - } else { - auto specs = RootConfigParamHelpers::asConfigParamSpecs<T>(what.name, what.value); - options.insert(options.end(), specs.begin(), specs.end()); - } - return true; - } - - static bool prepare(InitContext& context, Configurable<T>& what) - { - if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { - what.value = context.options().get<T>(what.name.c_str()); - } else { - auto pt = context.options().get<boost::property_tree::ptree>(what.name.c_str()); - what.value = RootConfigParamHelpers::as<T>(pt); - } - return true; - } -}; - -/// Manager template to facilitate extended tables spawning -template <typename T> -struct SpawnManager { - static bool requestInputs(std::vector<InputSpec>&, T const&) { return false; } -}; - -template <typename TABLE> -struct SpawnManager<Spawns<TABLE>> { - static bool requestInputs(std::vector<InputSpec>& inputs, Spawns<TABLE>& spawns) - { - auto base_specs = spawns.base_specs(); - for (auto& base_spec : base_specs) { - if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { - inputs.emplace_back(base_spec); - } - } - return true; - } -}; - -/// Manager template for building index tables -template <typename T> -struct IndexManager { - static bool requestInputs(std::vector<InputSpec>&, T const&) { return false; }; -}; - -template <typename IDX, typename P> -struct IndexManager<Builds<IDX, P>> { - static bool requestInputs(std::vector<InputSpec>& inputs, Builds<IDX, P>& builds) - { - auto base_specs = builds.base_specs(); - for (auto& base_spec : base_specs) { - if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { - inputs.emplace_back(base_spec); - } - } - return true; - } -}; - // SFINAE test template <typename T> class has_process @@ -1436,14 +566,12 @@ DataProcessorSpec adaptAnalysisTask(char const* name, Args&&... args) std::vector<InputSpec> inputs; std::vector<ExpressionInfo> expressionInfos; + /// make sure options and configurables are set before expression infos are created + std::apply([&options, &hash](auto&... x) { return (OptionManager<std::decay_t<decltype(x)>>::appendOption(options, x), ...); }, tupledTask); + if constexpr (has_process<T>::value) { // this pushes (I,schemaPtr,nullptr) into expressionInfos for arguments that are Filtered/filtered_iterators AnalysisDataProcessorBuilder::inputsFromArgs(&T::process, inputs, expressionInfos); - // here the FilterManager will prepare the gandiva trees matched to schemas and put the pointers into expressionInfos - std::apply([&expressionInfos](auto&... x) { - return (FilterManager<std::decay_t<decltype(x)>>::createExpressionTrees(x, expressionInfos), ...); - }, - tupledTask); } //request base tables for spawnable extended tables std::apply([&inputs](auto&... x) { @@ -1458,9 +586,8 @@ DataProcessorSpec adaptAnalysisTask(char const* name, Args&&... args) tupledTask); std::apply([&outputs, &hash](auto&... x) { return (OutputManager<std::decay_t<decltype(x)>>::appendOutput(outputs, x, hash), ...); }, tupledTask); - std::apply([&options, &hash](auto&... x) { return (OptionManager<std::decay_t<decltype(x)>>::appendOption(options, x), ...); }, tupledTask); - auto algo = AlgorithmSpec::InitCallback{[task, expressionInfos](InitContext& ic) { + auto algo = AlgorithmSpec::InitCallback{[task, expressionInfos](InitContext& ic) mutable { auto tupledTask = o2::framework::to_tuple_refs(*task.get()); std::apply([&ic](auto&&... x) { return (OptionManager<std::decay_t<decltype(x)>>::prepare(ic, x), ...); }, tupledTask); std::apply([&ic](auto&&... x) { return (ServiceManager<std::decay_t<decltype(x)>>::prepare(ic, x), ...); }, tupledTask); @@ -1473,9 +600,26 @@ DataProcessorSpec adaptAnalysisTask(char const* name, Args&&... args) }; callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); + if constexpr (has_process<T>::value) { + /// update configurables in filters + std::apply( + [&ic](auto&&... x) { return (FilterManager<std::decay_t<decltype(x)>>::updatePlaceholders(x, ic), ...); }, + tupledTask); + /// update configurables in partitions + std::apply( + [&ic](auto&&... x) { return (PartitionManager<std::decay_t<decltype(x)>>::updatePlaceholders(x, ic), ...); }, + tupledTask); + /// create for filters gandiva trees matched to schemas and store the pointers into expressionInfos + std::apply([&expressionInfos](auto&... x) { + return (FilterManager<std::decay_t<decltype(x)>>::createExpressionTrees(x, expressionInfos), ...); + }, + tupledTask); + } + if constexpr (has_init<T>::value) { task->init(ic); } + return [task, expressionInfos](ProcessingContext& pc) { auto tupledTask = o2::framework::to_tuple_refs(*task.get()); std::apply([&pc](auto&&... x) { return (OutputManager<std::decay_t<decltype(x)>>::prepare(pc, x), ...); }, tupledTask); diff --git a/Framework/Core/include/Framework/Configurable.h b/Framework/Core/include/Framework/Configurable.h new file mode 100644 index 0000000000000..8e6917cc596dd --- /dev/null +++ b/Framework/Core/include/Framework/Configurable.h @@ -0,0 +1,43 @@ +// 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_CONFIGURABLE_H_ +#define O2_FRAMEWORK_CONFIGURABLE_H_ +#include <string> +namespace o2::framework +{ +/// This helper allows you to create a configurable option associated to a task. +/// Internally it will be bound to a ConfigParamSpec. +template <typename T> +struct Configurable { + Configurable(std::string const& name, T defaultValue, std::string const& help) + : name(name), value(defaultValue), help(help) + { + } + using type = T; + std::string name; + T value; + std::string help; + operator T() + { + return value; + } + T const* operator->() const + { + return &value; + } +}; +template <typename T> +std::ostream& operator<<(std::ostream& os, Configurable<T> const& c) +{ + os << c.value; + return os; +} +} // namespace o2::framework +#endif // O2_FRAMEWORK_CONFIGURABLE_H_ diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index 0c66726f59376..c96cf3ef58a79 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -14,6 +14,11 @@ #include "Framework/CompilerBuiltins.h" #include "Framework/Pack.h" #include "Framework/CheckTypes.h" +#include "Framework/Configurable.h" +#include "Framework/Variant.h" +#include "Framework/InitContext.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/RootConfigParamHelpers.h" #include <arrow/type_fwd.h> #include <gandiva/gandiva_aliases.h> #include <arrow/type.h> @@ -85,6 +90,7 @@ struct LiteralNode { LiteralNode(T v) : value{v}, type{selectArrowType<T>()} { } + using var_t = LiteralValue::stored_type; var_t value; atype::type type = atype::NA; @@ -105,12 +111,39 @@ struct OpNode { BasicOp op; }; +/// A placeholder node for simple type configurable +struct PlaceholderNode : LiteralNode { + template <typename T> + PlaceholderNode(Configurable<T> v) : LiteralNode{v.value} + { + if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { + retrieve = [name = v.name](InitContext& context) { return LiteralNode::var_t{context.options().get<T>(name.c_str())}; }; + } else { + retrieve = [name = v.name](InitContext& context) { + auto pt = context.options().get<boost::property_tree::ptree>(name.c_str()); + return LiteralNode::var_t{RootConfigParamHelpers::as<T>(pt)}; + }; + } + } + + void reset(InitContext& context) + { + value = retrieve(context); + } + + std::function<LiteralNode::var_t(InitContext&)> retrieve; +}; + /// A generic tree node struct Node { Node(LiteralNode v) : self{v}, left{nullptr}, right{nullptr} { } + Node(PlaceholderNode v) : self{v}, left{nullptr}, right{nullptr} + { + } + Node(Node&& n) : self{n.self}, left{std::move(n.left)}, right{std::move(n.right)} { } @@ -130,7 +163,7 @@ struct Node { right{nullptr} {} /// variant with possible nodes - using self_t = std::variant<LiteralNode, BindingNode, OpNode>; + using self_t = std::variant<LiteralNode, BindingNode, OpNode, PlaceholderNode>; self_t self; /// pointers to children std::unique_ptr<Node> left; @@ -176,6 +209,42 @@ inline Node operator!=(Node left, T rightValue) return Node{OpNode{BasicOp::NotEqual}, std::move(left), LiteralNode{rightValue}}; } +template <typename T> +inline Node operator>(Node left, Configurable<T> rightValue) +{ + return Node{OpNode{BasicOp::GreaterThan}, std::move(left), PlaceholderNode{rightValue}}; +} + +template <typename T> +inline Node operator<(Node left, Configurable<T> rightValue) +{ + return Node{OpNode{BasicOp::LessThan}, std::move(left), PlaceholderNode{rightValue}}; +} + +template <typename T> +inline Node operator>=(Node left, Configurable<T> rightValue) +{ + return Node{OpNode{BasicOp::GreaterThanOrEqual}, std::move(left), PlaceholderNode{rightValue}}; +} + +template <typename T> +inline Node operator<=(Node left, Configurable<T> rightValue) +{ + return Node{OpNode{BasicOp::LessThanOrEqual}, std::move(left), PlaceholderNode{rightValue}}; +} + +template <typename T> +inline Node operator==(Node left, Configurable<T> rightValue) +{ + return Node{OpNode{BasicOp::Equal}, std::move(left), PlaceholderNode{rightValue}}; +} + +template <typename T> +inline Node operator!=(Node left, Configurable<T> rightValue) +{ + return Node{OpNode{BasicOp::NotEqual}, std::move(left), PlaceholderNode{rightValue}}; +} + /// node comparisons inline Node operator>(Node left, Node right) { @@ -329,6 +398,54 @@ inline Node operator-(T left, Node right) { return Node{OpNode{BasicOp::Subtraction}, LiteralNode{left}, std::move(right)}; } + +template <typename T> +inline Node operator*(Node left, Configurable<T> right) +{ + return Node{OpNode{BasicOp::Multiplication}, std::move(left), PlaceholderNode{right}}; +} + +template <typename T> +inline Node operator*(Configurable<T> left, Node right) +{ + return Node{OpNode{BasicOp::Multiplication}, PlaceholderNode{left}, std::move(right)}; +} + +template <typename T> +inline Node operator/(Node left, Configurable<T> right) +{ + return Node{OpNode{BasicOp::Division}, std::move(left), PlaceholderNode{right}}; +} + +template <typename T> +inline Node operator/(Configurable<T> left, Node right) +{ + return Node{OpNode{BasicOp::Division}, PlaceholderNode{left}, std::move(right)}; +} + +template <typename T> +inline Node operator+(Node left, Configurable<T> right) +{ + return Node{OpNode{BasicOp::Addition}, std::move(left), PlaceholderNode{right}}; +} + +template <typename T> +inline Node operator+(Configurable<T> left, Node right) +{ + return Node{OpNode{BasicOp::Addition}, PlaceholderNode{left}, std::move(right)}; +} + +template <typename T> +inline Node operator-(Node left, Configurable<T> right) +{ + return Node{OpNode{BasicOp::Subtraction}, std::move(left), PlaceholderNode{right}}; +} + +template <typename T> +inline Node operator-(Configurable<T> left, Node right) +{ + return Node{OpNode{BasicOp::Subtraction}, PlaceholderNode{left}, std::move(right)}; +} /// semi-binary template <typename T> inline Node npow(Node left, T right) @@ -438,6 +555,8 @@ void updateExpressionInfos(expressions::Filter const& filter, std::vector<Expres gandiva::ConditionPtr makeCondition(gandiva::NodePtr node); /// Function to create gandiva projecting expression from generic gandiva expression tree gandiva::ExpressionPtr makeExpression(gandiva::NodePtr node, gandiva::FieldPtr result); +/// Update placeholder nodes from context +void updatePlaceholders(Filter& filter, InitContext& context); template <typename... C> std::shared_ptr<gandiva::Projector> createProjectors(framework::pack<C...>, gandiva::SchemaPtr schema) diff --git a/Framework/Core/src/AnalysisHelpers.cxx b/Framework/Core/src/AnalysisHelpers.cxx index 109cb5e2c4dd2..65dc086d2509d 100644 --- a/Framework/Core/src/AnalysisHelpers.cxx +++ b/Framework/Core/src/AnalysisHelpers.cxx @@ -35,7 +35,7 @@ ROOT::RDataFrame doSelfCombinationsWith(std::unique_ptr<framework::TableConsumer using Index = RCombinedDSBlockJoinIndex<int>; auto left = std::make_unique<RArrowDS>(table, std::vector<std::string>{}); auto right = std::make_unique<RArrowDS>(table, std::vector<std::string>{}); - auto combined = std::make_unique<RCombinedDS>(std::move(left), std::move(right), std::move(std::make_unique<Index>(grouping, true, BlockCombinationRule::StrictlyUpper)), name + "_", name + "bar_"); + auto combined = std::make_unique<RCombinedDS>(std::move(left), std::move(right), std::make_unique<Index>(grouping, true, BlockCombinationRule::StrictlyUpper), name + "_", name + "bar_"); ROOT::RDataFrame rdf(std::move(combined)); return rdf; diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h new file mode 100644 index 0000000000000..b0473f96780ed --- /dev/null +++ b/Framework/Core/src/AnalysisManagers.h @@ -0,0 +1,420 @@ +// 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 FRAMEWORK_ANALYSISMANAGERS_H +#define FRAMEWORK_ANALYSISMANAGERS_H +#include "Framework/AnalysisHelpers.h" +#include "Framework/Kernels.h" +#include "Framework/ASoA.h" +#include "Framework/ProcessingContext.h" +#include "Framework/EndOfStreamContext.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/InitContext.h" +#include "Framework/RootConfigParamHelpers.h" +#include "../src/ExpressionHelpers.h" + +namespace o2::framework +{ + +template <typename ANY> +struct PartitionManager { + template <typename... T2s> + static void setPartition(ANY&, T2s&...) + { + } + + template <typename... Ts> + static void bindExternalIndices(ANY&, Ts*...) + { + } + + template <typename... Ts> + static void getBoundToExternalIndices(ANY&, Ts&...) + { + } + + static void updatePlaceholders(ANY&, InitContext&) + { + } +}; + +template <typename T> +struct PartitionManager<Partition<T>> { + template <typename T2> + static void doSetPartition(Partition<T>& partition, T2& table) + { + if constexpr (std::is_same_v<T, T2>) { + partition.setTable(table); + } + } + + template <typename... T2s> + static void setPartition(Partition<T>& partition, T2s&... tables) + { + (doSetPartition(partition, tables), ...); + } + + template <typename... Ts> + static void bindExternalIndices(Partition<T>& partition, Ts*... tables) + { + partition.bindExternalIndices(tables...); + } + + template <typename... Ts> + static void getBoundToExternalIndices(Partition<T>& partition, Ts&... tables) + { + partition.getBoundToExternalIndices(tables...); + } + + static void updatePlaceholders(Partition<T>& partition, InitContext& context) + { + partition.updatePlaceholders(context); + } +}; + +template <typename ANY> +struct FilterManager { + static bool createExpressionTrees(ANY&, std::vector<ExpressionInfo>&) + { + return false; + } + + static bool updatePlaceholders(ANY&, InitContext&) + { + return false; + } +}; + +template <> +struct FilterManager<expressions::Filter> { + static bool createExpressionTrees(expressions::Filter const& filter, std::vector<ExpressionInfo>& expressionInfos) + { + expressions::updateExpressionInfos(filter, expressionInfos); + return true; + } + + static bool updatePlaceholders(expressions::Filter& filter, InitContext& ctx) + { + expressions::updatePlaceholders(filter, ctx); + return true; + } +}; + +/// SFINAE placeholder +template <typename T> +struct OutputManager { + template <typename ANY> + static bool appendOutput(std::vector<OutputSpec>&, ANY&, uint32_t) + { + return false; + } + + template <typename ANY> + static bool prepare(ProcessingContext&, ANY&) + { + return false; + } + + template <typename ANY> + static bool postRun(EndOfStreamContext&, ANY&) + { + return true; + } + + template <typename ANY> + static bool finalize(ProcessingContext&, ANY&) + { + return true; + } +}; + +/// Produces specialization +template <typename TABLE> +struct OutputManager<Produces<TABLE>> { + static bool appendOutput(std::vector<OutputSpec>& outputs, Produces<TABLE>& what, uint32_t) + { + outputs.emplace_back(what.spec()); + return true; + } + static bool prepare(ProcessingContext& context, Produces<TABLE>& what) + { + what.resetCursor(context.outputs().make<TableBuilder>(what.ref())); + return true; + } + static bool finalize(ProcessingContext&, Produces<TABLE>&) + { + return true; + } + static bool postRun(EndOfStreamContext&, Produces<TABLE>&) + { + return true; + } +}; + +/// HistogramRegistry specialization +template <> +struct OutputManager<HistogramRegistry> { + static bool appendOutput(std::vector<OutputSpec>& outputs, HistogramRegistry& what, uint32_t) + { + outputs.emplace_back(what.spec()); + return true; + } + static bool prepare(ProcessingContext&, HistogramRegistry&) + { + return true; + } + + static bool finalize(ProcessingContext&, HistogramRegistry&) + { + return true; + } + + static bool postRun(EndOfStreamContext&, HistogramRegistry&) + { + return true; + } +}; + +/// OutputObj specialization +template <typename T> +struct OutputManager<OutputObj<T>> { + static bool appendOutput(std::vector<OutputSpec>& outputs, OutputObj<T>& what, uint32_t hash) + { + what.setHash(hash); + outputs.emplace_back(what.spec()); + return true; + } + static bool prepare(ProcessingContext&, OutputObj<T>&) + { + return true; + } + + static bool finalize(ProcessingContext&, OutputObj<T>&) + { + return true; + } + + static bool postRun(EndOfStreamContext& context, OutputObj<T>& what) + { + context.outputs().snapshot(what.ref(), *what); + return true; + } +}; + +/// Spawns specializations +template <typename O> +static auto extractOriginal(ProcessingContext& pc) +{ + return pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable(); +} + +template <typename... Os> +static std::vector<std::shared_ptr<arrow::Table>> extractOriginals(framework::pack<Os...>, ProcessingContext& pc) +{ + return {extractOriginal<Os>(pc)...}; +} + +template <typename T> +struct OutputManager<Spawns<T>> { + static bool appendOutput(std::vector<OutputSpec>& outputs, Spawns<T>& what, uint32_t) + { + outputs.emplace_back(what.spec()); + return true; + } + + static bool prepare(ProcessingContext& pc, Spawns<T>& what) + { + using metadata = typename std::decay_t<decltype(what)>::metadata; + auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(typename metadata::originals{}, pc)); + what.table = std::make_shared<T>(o2::soa::spawner(what.pack(), original_table.get())); + return true; + } + + static bool finalize(ProcessingContext&, Spawns<T>&) + { + return true; + } + + static bool postRun(EndOfStreamContext& eosc, Spawns<T>& what) + { + using metadata = typename std::decay_t<decltype(what)>::metadata; + eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); + return true; + } +}; + +/// Builds specialization +template <typename O> +static auto extractTypedOriginal(ProcessingContext& pc) +{ + ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables + return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; +} + +template <typename... Os> +static auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +{ + return std::make_tuple(extractTypedOriginal<Os>(pc)...); +} + +template <typename T, typename P> +struct OutputManager<Builds<T, P>> { + static bool appendOutput(std::vector<OutputSpec>& outputs, Builds<T, P>& what, uint32_t) + { + outputs.emplace_back(what.spec()); + return true; + } + + static bool prepare(ProcessingContext& pc, Builds<T, P>& what) + { + using metadata = typename std::decay_t<decltype(what)>::metadata; + return what.build(typename metadata::index_pack_t{}, + extractTypedOriginal<typename metadata::Key>(pc), + extractOriginalsTuple(typename metadata::originals{}, pc)); + } + + static bool finalize(ProcessingContext&, Builds<T, P>&) + { + return true; + } + + static bool postRun(EndOfStreamContext& eosc, Builds<T, P>& what) + { + using metadata = typename std::decay_t<decltype(what)>::metadata; + eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); + return true; + } +}; + +template <typename T> +class has_instance +{ + typedef char one; + struct two { + char x[2]; + }; + + template <typename C> + static one test(decltype(&C::instance)); + template <typename C> + static two test(...); + + public: + enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; +}; + +template <typename T> +struct ServiceManager { + template <typename ANY> + static bool prepare(InitContext&, ANY&) + { + return false; + } +}; + +template <typename T> +struct ServiceManager<Service<T>> { + static bool prepare(InitContext& context, Service<T>& service) + { + if constexpr (has_instance<T>::value) { + service.service = &(T::instance()); // Sigh... + return true; + } else { + service.service = context.services().get<T>(); + return true; + } + return false; + } +}; + +template <typename T> +struct OptionManager { + template <typename ANY> + static bool appendOption(std::vector<ConfigParamSpec>&, ANY&) + { + return false; + } + + template <typename ANY> + static bool prepare(InitContext&, ANY&) + { + return false; + } +}; + +template <typename T> +struct OptionManager<Configurable<T>> { + static bool appendOption(std::vector<ConfigParamSpec>& options, Configurable<T>& what) + { + if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { + options.emplace_back(ConfigParamSpec{what.name, variant_trait_v<typename std::decay<T>::type>, what.value, {what.help}}); + } else { + auto specs = RootConfigParamHelpers::asConfigParamSpecs<T>(what.name, what.value); + options.insert(options.end(), specs.begin(), specs.end()); + } + return true; + } + + static bool prepare(InitContext& context, Configurable<T>& what) + { + if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { + what.value = context.options().get<T>(what.name.c_str()); + } else { + auto pt = context.options().get<boost::property_tree::ptree>(what.name.c_str()); + what.value = RootConfigParamHelpers::as<T>(pt); + } + return true; + } +}; + +/// Manager template to facilitate extended tables spawning +template <typename T> +struct SpawnManager { + static bool requestInputs(std::vector<InputSpec>&, T const&) { return false; } +}; + +template <typename TABLE> +struct SpawnManager<Spawns<TABLE>> { + static bool requestInputs(std::vector<InputSpec>& inputs, Spawns<TABLE>& spawns) + { + auto base_specs = spawns.base_specs(); + for (auto& base_spec : base_specs) { + if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { + inputs.emplace_back(base_spec); + } + } + return true; + } +}; + +/// Manager template for building index tables +template <typename T> +struct IndexManager { + static bool requestInputs(std::vector<InputSpec>&, T const&) { return false; }; +}; + +template <typename IDX, typename P> +struct IndexManager<Builds<IDX, P>> { + static bool requestInputs(std::vector<InputSpec>& inputs, Builds<IDX, P>& builds) + { + auto base_specs = builds.base_specs(); + for (auto& base_spec : base_specs) { + if (std::find_if(inputs.begin(), inputs.end(), [&](InputSpec const& spec) { return base_spec.binding == spec.binding; }) == inputs.end()) { + inputs.emplace_back(base_spec); + } + } + return true; + } +}; +} // namespace o2::framework + +#endif // ANALYSISMANAGERS_H diff --git a/Framework/Core/src/ExpressionHelpers.h b/Framework/Core/src/ExpressionHelpers.h index 5797a94180b3c..2d3f9cb704029 100644 --- a/Framework/Core/src/ExpressionHelpers.h +++ b/Framework/Core/src/ExpressionHelpers.h @@ -96,6 +96,14 @@ struct ColumnOperationSpec { result.type = type; } }; + +/// helper struct used to parse trees +struct NodeRecord { + /// pointer to the actual tree node + Node* node_ptr = nullptr; + size_t index = 0; + explicit NodeRecord(Node* node_, size_t index_) : node_ptr(node_), index{index_} {} +}; } // namespace o2::framework::expressions #endif // O2_FRAMEWORK_EXPRESSIONS_HELPERS_H_ diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 6869b2fcad3a3..2455e897f0b0e 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -46,6 +46,13 @@ struct OpNodeHelper { return ColumnOperationSpec{node.op}; } }; + +struct PlaceholderNodeHelper { + DatumSpec operator()(PlaceholderNode node) const + { + return DatumSpec{node.value, node.type}; + } +}; } // namespace std::shared_ptr<arrow::DataType> concreteArrowType(atype::type type) @@ -107,16 +114,47 @@ std::ostream& operator<<(std::ostream& os, DatumSpec const& spec) return os; } -namespace +void updatePlaceholders(Filter& filter, InitContext& context) { -/// helper struct used to parse trees -struct NodeRecord { - /// pointer to the actual tree node - Node* node_ptr = nullptr; - size_t index = 0; - explicit NodeRecord(Node* node_, size_t index_) : node_ptr(node_), index{index_} {} -}; -} // namespace + std::stack<NodeRecord> path; + + // insert the top node into stack + path.emplace(filter.node.get(), 0); + + auto updateNode = [&](Node* node) { + if (node->self.index() == 3) { + std::get_if<3>(&node->self)->reset(context); + } + }; + + auto isLeaf = [](Node const* const node) { + return ((node->left == nullptr) && (node->right == nullptr)); + }; + + // while the stack is not empty + while (path.empty() == false) { + auto& top = path.top(); + + updateNode(top.node_ptr); + + path.pop(); + + if (top.node_ptr->left != nullptr) { + if (isLeaf(top.node_ptr->left.get())) { + updateNode(top.node_ptr->left.get()); + } else { + path.emplace(top.node_ptr->left.get(), 0); + } + } + if (top.node_ptr->right != nullptr) { + if (isLeaf(top.node_ptr->right.get())) { + updateNode(top.node_ptr->right.get()); + } else { + path.emplace(top.node_ptr->right.get(), 0); + } + } + } +} Operations createOperations(Filter const& expression) { @@ -131,6 +169,7 @@ Operations createOperations(Filter const& expression) overloaded{ [lh = LiteralNodeHelper{}](LiteralNode node) { return lh(node); }, [bh = BindingNodeHelper{}](BindingNode node) { return bh(node); }, + [ph = PlaceholderNodeHelper{}](PlaceholderNode node) { return ph(node); }, [](auto&&) { return DatumSpec{}; }}, node->self); }; diff --git a/Framework/Core/test/test_AnalysisTask.cxx b/Framework/Core/test/test_AnalysisTask.cxx index a9ac25d2ced52..4043351815d10 100644 --- a/Framework/Core/test/test_AnalysisTask.cxx +++ b/Framework/Core/test/test_AnalysisTask.cxx @@ -50,7 +50,7 @@ DECLARE_SOA_TABLE(Events, "AOD", "EVENTS", struct ATask { Produces<aod::FooBars> foobars; - void process(o2::aod::Track const& track) + void process(o2::aod::Track const&) { foobars(0.01102005, 0.27092016); // dummy value for phi for now... } diff --git a/Framework/Core/test/test_Expressions.cxx b/Framework/Core/test/test_Expressions.cxx index 5be7c48fab751..c95db424ef650 100644 --- a/Framework/Core/test/test_Expressions.cxx +++ b/Framework/Core/test/test_Expressions.cxx @@ -12,6 +12,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Framework/Configurable.h" #include "../src/ExpressionHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AODReaderHelpers.h" @@ -121,6 +122,16 @@ BOOST_AUTO_TEST_CASE(TestTreeParsing) BOOST_REQUIRE_EQUAL(uspecs[5].left, (DatumSpec{std::string{"eta"}, atype::FLOAT})); BOOST_REQUIRE_EQUAL(uspecs[5].right, (DatumSpec{})); BOOST_REQUIRE_EQUAL(uspecs[5].result, (DatumSpec{5u, atype::FLOAT})); + + Configurable<float> pTCut{"pTCut", 0.5f, "Lower pT limit"}; + Filter ptfilter = o2::aod::track::pt > pTCut; + BOOST_REQUIRE_EQUAL(ptfilter.node->self.index(), 2); + BOOST_REQUIRE_EQUAL(ptfilter.node->left->self.index(), 1); + BOOST_REQUIRE_EQUAL(ptfilter.node->right->self.index(), 3); + auto ptfilterspecs = createOperations(ptfilter); + BOOST_REQUIRE_EQUAL(ptfilterspecs[0].left, (DatumSpec{std::string{"fPt"}, atype::FLOAT})); + BOOST_REQUIRE_EQUAL(ptfilterspecs[0].right, (DatumSpec{LiteralNode::var_t{0.5f}, atype::FLOAT})); + BOOST_REQUIRE_EQUAL(ptfilterspecs[0].result, (DatumSpec{0u, atype::BOOL})); } BOOST_AUTO_TEST_CASE(TestGandivaTreeCreation) From 202c9a32b606e480353511ed0aaa5eb1833c18d8 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Tue, 21 Jul 2020 23:58:36 +0200 Subject: [PATCH 0537/1751] Workflow for TOFcalibCollector It will reformat the calibration information coming from the matching saving them to file, to be subsequently processed to extract the time slewing (which does not seem appropriate for a data processor). Some changes implemented also in the TimeSlotCalibration, when the maxDelay is set to zero (--> we accept all data). Just not to lose work :-) compiling version Changing philosophy. Since we cannot send trees, the tree will have to be filled by the data processor that will then also write the output file. First version of the Spec also committed - but still using the tree. Now it is too late, I will go to bed and take care another time. Addng writer + other changes Things compile, but were not yet tested. Probably to change from std::vector to gsl::span. Fixing issues + new features. E.g.: using gsl::span for the output that goes in the tree. Workflow not yet working, but everything compiles. Fixes Going back to std::vectors (tree cannot contain gsl::span) Fixes to have the whole thing working. One change also to TimeSlotCalibration.h The change in TimeSlotCalibration.h is needed because we want to update at every TF, which means that the mMaxSlotsDelay should be 0. fix for size of vector I think this is correct, but I did not test it move resize fix for TOF channel offset calibration from reco flow Several changes. Main ones: - bug fixes (seg fault due to missing initialization; merging function fixed) - changes in the TimeSlotCalibration to not discard anything if maxDelay = 0 - force sending output at the end of the processing even if there is not necessarily the requested statistics Clang-format code checker clang-format O2 code checker --- .../TOF/include/DataFormatsTOF/CalibInfoTOF.h | 2 +- .../DataFormatsTOF/CalibInfoTOFshort.h | 5 +- .../TimeSlotCalibration.h | 8 +- .../include/TOFWorkflow/CalibInfoReaderSpec.h | 3 + .../tofworkflow/src/CalibInfoReaderSpec.cxx | 36 +++-- .../tofworkflow/src/RecoWorkflowSpec.cxx | 4 +- .../tofworkflow/src/TOFCalibWriterSpec.cxx | 2 +- Detectors/TOF/calibration/CMakeLists.txt | 9 ++ .../include/TOFCalibration/CalibTOFapi.h | 1 + .../TOFCalibration/TOFCalibCollector.h | 95 +++++++++++ .../TOF/calibration/src/TOFCalibCollector.cxx | 147 ++++++++++++++++++ .../calibration/src/TOFCalibrationLinkDef.h | 5 + .../calibration/src/TOFChannelCalibrator.cxx | 134 +++++++++------- .../testWorkflow/DataGeneratorSpec.h | 6 +- .../testWorkflow/LHCClockCalibratorSpec.h | 2 +- .../testWorkflow/TOFCalibCollectorSpec.h | 124 +++++++++++++++ .../TOFCalibCollectorWriterSpec.h | 126 +++++++++++++++ .../testWorkflow/TOFChannelCalibratorSpec.h | 4 +- .../tof-collect-calib-workflow.cxx | 34 ++++ .../testWorkflow/tof-dummy-ccdb-for-calib.cxx | 2 +- 20 files changed, 663 insertions(+), 86 deletions(-) create mode 100644 Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h create mode 100644 Detectors/TOF/calibration/src/TOFCalibCollector.cxx create mode 100644 Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h create mode 100644 Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h create mode 100644 Detectors/TOF/calibration/testWorkflow/tof-collect-calib-workflow.cxx diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOF.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOF.h index eeb2853e1a47b..9fa941afc33ba 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOF.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOF.h @@ -36,7 +36,7 @@ class CalibInfoTOF void setDeltaTimePi(float time) { mDeltaTimePi = time; } float getDeltaTimePi() const { return mDeltaTimePi; } - void setTot(int tot) { mTot = tot; } + void setTot(float tot) { mTot = tot; } float getTot() const { return mTot; } void setFlags(int flags) { mFlags = flags; } diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOFshort.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOFshort.h index 20d0ca199d2fd..3f5579c0bc33a 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOFshort.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibInfoTOFshort.h @@ -14,6 +14,8 @@ #ifndef ALICEO2_CALIBINFOTOFSHORT_H #define ALICEO2_CALIBINFOTOFSHORT_H +#include "Rtypes.h" + namespace o2 { namespace dataformats @@ -43,7 +45,8 @@ class CalibInfoTOFshort float mDeltaTimePi; // raw tof time - expected time for pi hypotesis float mTot; // time-over-threshold unsigned char mFlags; // bit mask with quality flags (to be defined) - // ClassDefNV(CalibInfoTOFshort, 1); + + ClassDefNV(CalibInfoTOFshort, 1); }; } // namespace dataformats } // namespace o2 diff --git a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h index 5c3aa126f637a..74373e7137ae3 100644 --- a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h +++ b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h @@ -31,7 +31,9 @@ class TimeSlotCalibration TimeSlotCalibration() = default; virtual ~TimeSlotCalibration() = default; uint32_t getMaxSlotsDelay() const { return mMaxSlotsDelay; } - void setMaxSlotsDelay(uint32_t v) { mMaxSlotsDelay = v < 1 ? 1 : v; } + void setMaxSlotsDelay(uint32_t v) { mMaxSlotsDelay = v; } + //void setMaxSlotsDelay(uint32_t v) { (mSlotLength == 1 && mMaxSlotsDelay == 0) ? mMaxSlotsDelay = 0 : mMaxSlotsDelay = v < 1 ? 1 : v; } + //void setMaxSlotsDelay(uint32_t v) { mSlotLength == 1 ? mMaxSlotsDelay = 0 : mMaxSlotsDelay = v < 1 ? 1 : v; } uint32_t getSlotLength() const { return mSlotLength; } void setSlotLength(uint32_t v) { mSlotLength = v < 1 ? 1 : v; } @@ -88,7 +90,7 @@ bool TimeSlotCalibration<Input, Container>::process(TFType tf, const gsl::span<c if (!mUpdateAtTheEndOfRunOnly) { int maxDelay = mMaxSlotsDelay * mSlotLength; // if (tf<mLastClosedTF || (!mSlots.empty() && getSlot(0).getTFStart() > tf + maxDelay)) { // ignore TF - if (tf < mLastClosedTF || (!mSlots.empty() && getLastSlot().getTFStart() > tf + maxDelay)) { // ignore TF + if (maxDelay != 0 && (tf < mLastClosedTF || (!mSlots.empty() && getLastSlot().getTFStart() > tf + maxDelay))) { // ignore TF LOG(INFO) << "Ignoring TF " << tf; return false; } @@ -111,7 +113,7 @@ void TimeSlotCalibration<Input, Container>::checkSlotsToFinalize(TFType tf, int // Check which slots can be finalized, provided the newly arrived TF is tf // check if some slots are done for (auto slot = mSlots.begin(); slot != mSlots.end(); slot++) { - if ((slot->getTFEnd() + maxDelay) < tf) { + if (maxDelay == 0 || (slot->getTFEnd() + maxDelay) < tf) { if (hasEnoughData(*slot)) { finalizeSlot(*slot); // will be removed after finalization } else if ((slot + 1) != mSlots.end()) { diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h index b0c8f2562ce36..09494a2191f23 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/CalibInfoReaderSpec.h @@ -19,6 +19,8 @@ #include "Framework/Task.h" #include "DataFormatsTOF/CalibInfoTOF.h" +class TTree; + using namespace o2::framework; namespace o2 @@ -40,6 +42,7 @@ class CalibInfoReader : public Task int mNinstances; const char* mFileName = nullptr; FILE* mFile = nullptr; + TTree* mTree = nullptr; int mCurrentEntry = 0; int mGlobalEntry = 0; std::vector<o2::dataformats::CalibInfoTOF> mVect, *mPvect = &mVect; diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx index 30881cab806fc..dcbd9bd2f220c 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx @@ -11,6 +11,7 @@ /// @file DigitReaderSpec.cxx #include <vector> +#include <unistd.h> #include "TChain.h" #include "TTree.h" @@ -46,30 +47,33 @@ void CalibInfoReader::run(ProcessingContext& pc) } char filename[100]; - int ientry = 0; - while (fscanf(mFile, "%s", filename) == 1) { - TFile* fin = TFile::Open(filename); - TTree* tin = (TTree*)fin->Get("calibTOF"); - tin->SetBranchAddress("TOFCalibInfo", &mPvect); - for (int i = 0; i < tin->GetEntries(); i += mNinstances) { - if ((ientry % mNinstances) == mInstance) { - tin->GetEvent(i); - LOG(INFO) << "Send " << mVect.size() << " calib infos"; - pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CALIBINFOS", 0, Lifetime::Timeframe}, mVect); - } - ientry++; + + if ((mTree && mCurrentEntry < mTree->GetEntries()) || fscanf(mFile, "%s", filename) == 1) { + if (!mTree || mCurrentEntry >= mTree->GetEntries()) { + TFile* fin = TFile::Open(filename); + mTree = (TTree*)fin->Get("calibTOF"); + mCurrentEntry = 0; + mTree->SetBranchAddress("TOFCalibInfo", &mPvect); + } + if ((mGlobalEntry % mNinstances) == mInstance) { + mTree->GetEvent(mCurrentEntry); + LOG(INFO) << "Send " << mVect.size() << " calib infos"; + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CALIBDATA", 0, Lifetime::Timeframe}, mVect); + usleep(10000); } + mGlobalEntry++; + mCurrentEntry++; + } else { + mState = 2; + pc.services().get<ControlService>().endOfStream(); } - - mState = 2; - pc.services().get<ControlService>().endOfStream(); return; } DataProcessorSpec getCalibInfoReaderSpec(int instance, int ninstances, const char* filename) { std::vector<OutputSpec> outputs; - outputs.emplace_back(o2::header::gDataOriginTOF, "CALIBINFOS", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTOF, "CALIBDATA", 0, Lifetime::Timeframe); const char* nameSpec; if (ninstances == 1) diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowSpec.cxx index a358a8971bbae..c7def5fe1cbfe 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowSpec.cxx @@ -115,7 +115,7 @@ class TOFDPLRecoWorkflowTask pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "MATCHTPCINFOSMC", 0, Lifetime::Timeframe}, mMatcher.getMatchedTPCLabelsVector()); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "MATCHITSINFOSMC", 0, Lifetime::Timeframe}, mMatcher.getMatchedITSLabelsVector()); } - pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CALIBINFOS", 0, Lifetime::Timeframe}, mMatcher.getCalibVector()); + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CALIBDATA", 0, Lifetime::Timeframe}, mMatcher.getCalibVector()); mTimer.Stop(); } @@ -152,7 +152,7 @@ o2::framework::DataProcessorSpec getTOFRecoWorkflowSpec(bool useMC, bool useFIT) outputs.emplace_back(o2::header::gDataOriginTOF, "MATCHTPCINFOSMC", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "MATCHITSINFOSMC", 0, Lifetime::Timeframe); } - outputs.emplace_back(o2::header::gDataOriginTOF, "CALIBINFOS", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTOF, "CALIBDATA", 0, Lifetime::Timeframe); return DataProcessorSpec{ "TOFRecoWorkflow", diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx index c3170fdc67db1..384d6df8b7f78 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx @@ -43,7 +43,7 @@ DataProcessorSpec getTOFCalibWriterSpec() return MakeRootTreeWriterSpec("TOFCalibWriter", "o2calib_tof.root", "calibTOF", - BranchDefinition<CalibInfosType>{InputSpec{"input", o2::header::gDataOriginTOF, "CALIBINFOS", 0}, + BranchDefinition<CalibInfosType>{InputSpec{"input", o2::header::gDataOriginTOF, "CALIBDATA", 0}, "TOFCalibInfo", "calibinfo-branch-name", 1, diff --git a/Detectors/TOF/calibration/CMakeLists.txt b/Detectors/TOF/calibration/CMakeLists.txt index 10921f2d0d3ec..75c7ce9d792a8 100644 --- a/Detectors/TOF/calibration/CMakeLists.txt +++ b/Detectors/TOF/calibration/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library(TOFCalibration src/CollectCalibInfoTOF.cxx src/LHCClockCalibrator.cxx src/TOFChannelCalibrator.cxx + src/TOFCalibCollector.cxx PUBLIC_LINK_LIBRARIES O2::DataFormatsTOF O2::TOFBase O2::CCDB O2::DetectorsCalibration @@ -26,6 +27,7 @@ o2_target_root_dictionary(TOFCalibration include/TOFCalibration/CalibTOF.h include/TOFCalibration/LHCClockCalibrator.h include/TOFCalibration/TOFChannelCalibrator.h + include/TOFCalibration/TOFCalibCollector.h include/TOFCalibration/CollectCalibInfoTOF.h) @@ -64,3 +66,10 @@ o2_add_executable(tof-dummy-ccdb-for-calib PUBLIC_LINK_LIBRARIES O2::Framework O2::TOFCalibration O2::DetectorsCalibration) + +o2_add_executable(tof-collect-calib-workflow + COMPONENT_NAME calibration + SOURCES testWorkflow/tof-collect-calib-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::TOFCalibration + O2::DetectorsCalibration) diff --git a/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h b/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h index 0165ad4350620..854edca6f4849 100644 --- a/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h +++ b/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h @@ -58,6 +58,7 @@ class CalibTOFapi SlewParam* getSlewParam() { return mSlewParam; } SlewParam& getSlewParamObj() { return *mSlewParam; } + LhcPhase* getLhcPhase() { return mLHCphase; } private: long mTimeStamp; ///< timeStamp for queries diff --git a/Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h b/Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h new file mode 100644 index 0000000000000..fa235ff501516 --- /dev/null +++ b/Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h @@ -0,0 +1,95 @@ +// 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 TOF_CALIB_COLLECTOR_H_ +#define TOF_CALIB_COLLECTOR_H_ + +#include "DetectorsCalibration/TimeSlotCalibration.h" +#include "DetectorsCalibration/TimeSlot.h" +#include "DataFormatsTOF/CalibInfoTOF.h" +#include "TOFBase/Geo.h" +#include "DataFormatsTOF/CalibInfoTOFshort.h" + +#include <array> + +namespace o2 +{ +namespace tof +{ + +class TOFCalibInfoSlot +{ + + using Slot = o2::calibration::TimeSlot<o2::tof::TOFCalibInfoSlot>; + using Geo = o2::tof::Geo; + + public: + static constexpr int NCHANNELSXSECTOR = o2::tof::Geo::NCHANNELS / o2::tof::Geo::NSECTORS; + + TOFCalibInfoSlot() + { + for (int ch = 0; ch < Geo::NCHANNELS; ch++) { + mEntriesSlot[ch] = 0; + } + } + + ~TOFCalibInfoSlot() = default; + + void print() const; + void printEntries() const; + void fill(const gsl::span<const o2::dataformats::CalibInfoTOF> data); + void merge(const TOFCalibInfoSlot* prev); + + auto& getEntriesPerChannel() const { return mEntriesSlot; } + auto& getEntriesPerChannel() { return mEntriesSlot; } + auto& getCollectedCalibInfoSlot() { return mTOFCollectedCalibInfoSlot; } + auto& getCollectedCalibInfoSlot() const { return mTOFCollectedCalibInfoSlot; } + + private: + std::array<int, Geo::NCHANNELS> mEntriesSlot; // vector containing number of entries per channel + std::vector<o2::dataformats::CalibInfoTOFshort> mTOFCollectedCalibInfoSlot; ///< output TOF calibration info + + ClassDefNV(TOFCalibInfoSlot, 1); +}; + +class TOFCalibCollector final : public o2::calibration::TimeSlotCalibration<o2::dataformats::CalibInfoTOF, o2::tof::TOFCalibInfoSlot> +{ + using TFType = uint64_t; + using Slot = o2::calibration::TimeSlot<o2::tof::TOFCalibInfoSlot>; + + public: + TOFCalibCollector(bool TFsendingPolicy, int maxNumOfHits, bool test = false) : mTFsendingPolicy(TFsendingPolicy), mMaxNumOfHits(maxNumOfHits), mTest(test){}; + + ~TOFCalibCollector() final = default; + + bool hasEnoughData(const Slot& slot) const final; + void initOutput() final; + void finalizeSlot(Slot& slot) final; + Slot& emplaceNewSlot(bool front, TFType tstart, TFType tend) final; + void isTest(bool istest) { mTest = istest; } + auto& getCollectedCalibInfo() const { return mTOFCollectedCalibInfo; } + auto& getEntriesPerChannel() const { return mEntries; } + void isMaxNumberOfHitsAbsolute(bool absNumber) { mAbsMaxNumOfHits = absNumber; } + + private: + bool mTFsendingPolicy = false; // whether we will send information at every TF or only when we have a certain statistics + int mMaxNumOfHits = 500; // maximum number of hits for one single channel to trigger the sending of the information (if mTFsendingPolicy = false) + bool mTest = false; // flag to say whether we are in test mode or not + bool mAbsMaxNumOfHits = true; // to decide if the mMaxNumOfHits should be multiplied by the number of TOF channels + std::array<int, Geo::NCHANNELS> mEntries; // vector containing number of entries per channel + std::vector<o2::dataformats::CalibInfoTOFshort> mTOFCollectedCalibInfo; ///< output TOF calibration info + + ClassDefOverride(TOFCalibCollector, 1); +}; + +} // end namespace tof +} // end namespace o2 + +#endif /* TOF_CHANNEL_CALIBRATOR_H_ */ diff --git a/Detectors/TOF/calibration/src/TOFCalibCollector.cxx b/Detectors/TOF/calibration/src/TOFCalibCollector.cxx new file mode 100644 index 0000000000000..4226253686728 --- /dev/null +++ b/Detectors/TOF/calibration/src/TOFCalibCollector.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 "TOFCalibration/TOFCalibCollector.h" +#include "Framework/Logger.h" +#include <cassert> +#include <iostream> +#include <sstream> +#include <TStopwatch.h> + +namespace o2 +{ +namespace tof +{ + +using Slot = o2::calibration::TimeSlot<o2::tof::TOFCalibInfoSlot>; + +//_____________________________________________ +void TOFCalibInfoSlot::fill(const gsl::span<const o2::dataformats::CalibInfoTOF> data) +{ + // fill container + // we do not apply any calibration at this stage, it will be applied when we + // process the data before filling the CCDB in the separate process + + for (int i = data.size(); i--;) { + auto ch = data[i].getTOFChIndex(); + auto offset = std::accumulate(mEntriesSlot.begin(), mEntriesSlot.begin() + ch, 0); + mTOFCollectedCalibInfoSlot.emplace(mTOFCollectedCalibInfoSlot.begin() + offset, data[i].getTimestamp(), data[i].getDeltaTimePi(), data[i].getTot(), data[i].getFlags()); + mEntriesSlot[ch]++; + } +} + +//_____________________________________________ +void TOFCalibInfoSlot::merge(const TOFCalibInfoSlot* prev) +{ + // merge data of 2 slots + + int addedPerChannel = 0; + int offset = 0; + + LOG(DEBUG) << "Merging two slots with entries: current slot -> " << mTOFCollectedCalibInfoSlot.size() << " , previous slot -> " << prev->mTOFCollectedCalibInfoSlot.size(); + for (int ch = 0; ch < Geo::NCHANNELS; ch++) { + offset += mEntriesSlot[ch]; + if (prev->mEntriesSlot[ch] == 0) + continue; + auto offsetprevStart = addedPerChannel; + auto offsetprevEnd = addedPerChannel + prev->mEntriesSlot[ch]; + addedPerChannel += prev->mEntriesSlot[ch]; + mTOFCollectedCalibInfoSlot.insert(mTOFCollectedCalibInfoSlot.begin() + offset, prev->mTOFCollectedCalibInfoSlot.begin() + offsetprevStart, prev->mTOFCollectedCalibInfoSlot.begin() + offsetprevEnd); + mEntriesSlot[ch] += prev->mEntriesSlot[ch]; + } + LOG(DEBUG) << "After merging the size is " << mTOFCollectedCalibInfoSlot.size(); + return; +} +//_____________________________________________ +void TOFCalibInfoSlot::print() const +{ + // to print number of entries in the tree and the channel with the max number of entries + + LOG(INFO) << "Total number of entries " << mTOFCollectedCalibInfoSlot.size(); + auto maxElementIndex = std::max_element(mEntriesSlot.begin(), mEntriesSlot.end()); + auto channelIndex = std::distance(mEntriesSlot.begin(), maxElementIndex); + LOG(INFO) << "The maximum number of entries per channel in the current mTOFCollectedCalibInfo is " << *maxElementIndex << " for channel " << channelIndex; + return; +} + +//_____________________________________________ +void TOFCalibInfoSlot::printEntries() const +{ + // to print number of entries in the tree and per channel + + LOG(INFO) << "Total number of entries " << mTOFCollectedCalibInfoSlot.size(); + for (int i = 0; i < mEntriesSlot.size(); ++i) { + if (mEntriesSlot[i] != 0) { + LOG(INFO) << "channel " << i << " has " << mEntriesSlot[i] << " entries"; + } + } + return; +} + +//=================================================================== + +//_____________________________________________ +void TOFCalibCollector::initOutput() +{ + // emptying the vectors + + mTOFCollectedCalibInfo.clear(); + for (int ch = 0; ch < Geo::NCHANNELS; ch++) { + mEntries[ch] = 0; + } + + return; +} + +//_____________________________________________ +bool TOFCalibCollector::hasEnoughData(const Slot& slot) const +{ + + // We define that we have enough data if the tree is big enough. + // each CalibInfoTOFShort is composed of one int, two floats, one unsigned char --> 13 bytes + // E.g. supposing that we have 256 entries per channel (which is an upper limit ) --> ~523 MB + // we can check if we have at least 1 GB of data --> 500*o2::tof::Geo::NCHANNELS entries in the vector + // (see header file for the fact that mMaxNumOfHits = 500) + // The case in which mScaleMaxNumOfHits = false allows for a fast check + + if (mTest) + return true; + const o2::tof::TOFCalibInfoSlot* c = slot.getContainer(); + LOG(DEBUG) << "we have " << c->getCollectedCalibInfoSlot().size() << " entries"; + int maxNumberOfHits = mAbsMaxNumOfHits ? mMaxNumOfHits : mMaxNumOfHits * o2::tof::Geo::NCHANNELS; + if (mTFsendingPolicy || c->getCollectedCalibInfoSlot().size() > maxNumberOfHits) + return true; + return false; +} + +//_____________________________________________ +void TOFCalibCollector::finalizeSlot(Slot& slot) +{ + // here we fill the tree with the remaining stuff that was not filled before + + o2::tof::TOFCalibInfoSlot* c = slot.getContainer(); + mTOFCollectedCalibInfo = c->getCollectedCalibInfoSlot(); + LOG(DEBUG) << "vector of CalibTOFInfoShort received with size = " << mTOFCollectedCalibInfo.size(); + mEntries = c->getEntriesPerChannel(); + return; +} + +//_____________________________________________ +Slot& TOFCalibCollector::emplaceNewSlot(bool front, TFType tstart, TFType tend) +{ + + auto& cont = getSlots(); + auto& slot = front ? cont.emplace_front(tstart, tend) : cont.emplace_back(tstart, tend); + slot.setContainer(std::make_unique<TOFCalibInfoSlot>()); + return slot; +} + +} // end namespace tof +} // end namespace o2 diff --git a/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h b/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h index 004e5f03f4ace..9b7043720f9f0 100644 --- a/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h +++ b/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h @@ -28,4 +28,9 @@ #pragma link C++ class o2::calibration::TimeSlot < o2::tof::TOFChannelData> + ; #pragma link C++ class o2::calibration::TimeSlotCalibration < o2::dataformats::CalibInfoTOF, o2::tof::TOFChannelData> + ; +#pragma link C++ class o2::tof::TOFCalibInfoSlot + ; +#pragma link C++ class o2::tof::TOFCalibCollector + ; +#pragma link C++ class o2::calibration::TimeSlot < o2::tof::TOFCalibInfoSlot> + ; +#pragma link C++ class o2::calibration::TimeSlotCalibration < o2::dataformats::CalibInfoTOF, o2::tof::TOFCalibInfoSlot> + ; + #endif diff --git a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx index e242d5f441cd3..241044be3aae4 100644 --- a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx +++ b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx @@ -43,11 +43,15 @@ void TOFChannelData::fill(const gsl::span<const o2::dataformats::CalibInfoTOF> d int sector = ch / o2::tof::Geo::NPADSXSECTOR; int chInSect = ch % o2::tof::Geo::NPADSXSECTOR; auto dt = data[i].getDeltaTimePi(); + auto tot = data[i].getTot(); // TO BE DISCUSSED: could it be that the LHCphase is too old? If we ar ein sync mode, it could be that it is not yet created for the current run, so the one from the previous run (which could be very old) is used. But maybe it does not matter much, since soon enough a calibrated LHC phase should be produced auto corr = mCalibTOFapi->getTimeCalibration(ch, tot); // we take into account LHCphase, offsets and time slewing LOG(DEBUG) << "inserting in channel " << ch << ": dt = " << dt << ", tot = " << tot << ", corr = " << corr << ", corrected dt = " << dt - corr; - mHisto[sector](dt - corr, chInSect); // we pass the calibrated time + + dt -= corr; + + mHisto[sector](dt, chInSect); // we pass the calibrated time mEntries[ch] += 1; } } @@ -59,6 +63,9 @@ void TOFChannelData::merge(const TOFChannelData* prev) for (int isect = 0; isect < o2::tof::Geo::NSECTORS; isect++) { mHisto[isect] += prev->getHisto(isect); } + for (int ich = 0; ich < o2::tof::Geo::NCHANNELS; ich++) { + mEntries[ich] += prev->mEntries[ich]; + } } //_____________________________________________ @@ -74,7 +81,7 @@ bool TOFChannelData::hasEnoughData(int minEntries) const auto minElementIndex = std::min_element(mEntries.begin(), mEntries.end()); LOG(INFO) << "minElement is at position " << std::distance(mEntries.begin(), minElementIndex) << " and is " << *minElementIndex; bool enough = *minElementIndex < minEntries ? false : true; - LOG(INFO) << "hasEnough = " << (int)enough; + LOG(INFO) << "hasEnough = (minEntry=" << minEntries << ") " << (int)enough; return enough; } @@ -155,10 +162,12 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) { // calculates the integral in [chmin, chmax] and in [binmin, binmax] - if (binmin < -mRange || binmax > mRange || chmin < 0 || chmax >= o2::tof::Geo::NCHANNELS) + if (binmin < -mRange || binmax > mRange || chmin < 0 || chmax >= o2::tof::Geo::NCHANNELS) { throw std::runtime_error("Check your bins, we cannot calculate the integrals in under/overflows bins"); - if (binmax < binmin || chmax < chmin) + } + if (binmax < binmin || chmax < chmin) { throw std::runtime_error("Check your bin limits!"); + } int sector = chmin / o2::tof::Geo::NPADSXSECTOR; if (sector != chmax / o2::tof::Geo::NPADSXSECTOR) @@ -173,31 +182,31 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) // ", chinsectormin = " << chinsectormin << ", chinsector max = " << chinsectormax; float res2 = 0; - TStopwatch t3; + //TStopwatch t3; int ind = -1; int binxmin = findBin(binmin); int binxmax = findBin(binmax); LOG(DEBUG) << "binxmin = " << binxmin << ", binxmax = " << binxmax; - t3.Start(); + //t3.Start(); for (unsigned j = chinsectormin; j <= chinsectormax; ++j) { for (unsigned i = binxmin; i <= binxmax; ++i) { const auto& v = mHisto[sector].at(i, j); res2 += v; } } - t3.Stop(); - LOG(INFO) << "Time for integral looping over axis (result = " << res2 << "):"; - t3.Print(); + //t3.Stop(); + //LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; + //t3.Print(); return res2; /* // what is below is only for alternative methods which all proved to be slower float res = 0, res1 = 0; - TStopwatch t1, t2, + //TStopwatch t1, t2, int startCount = chinsectormin * mNBins + binxmin; int endCount = chinsectormax * mNBins + binxmax; // = startCount + (chinsectormax - chinsectormin) * mNBins + (binxmax - binxmin); LOG(DEBUG) << "startCount = " << startCount << " endCount = " << endCount-1; - t2.Start(); + //t2.Start(); int counts = -1; for (auto&& x : indexed(mHisto[sector])) { counts++; @@ -217,10 +226,10 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) // << x.bin(0).upper() << "], and bin " << x.index(1) << " along y" << " with content " << x.get() << " --> res1 = " << res1; } } - t2.Stop(); - LOG(INFO) << "Time for integral looping over restricted range (result = " << res1 << "):"; - t2.Print(); - t1.Start(); + //t2.Stop(); + //LOG(DEBUG) << "Time for integral looping over restricted range (result = " << res1 << "):"; + //t2.Print(); + //t1.Start(); ind = -1; for (auto&& x : indexed(mHisto[sector])) { ind++; @@ -231,12 +240,12 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) // << x.bin(0).upper() << "], and bin " << x.index(1) << " along y" << " with content " << x.get(); } } - t1.Stop(); - LOG(INFO) << "Time for integral looping (result = " << res << "):"; - t1.Print(); - LOG(INFO) << "Reducing... "; - TStopwatch t; - t.Start(); + //t1.Stop(); + //LOG(DEBUG) << "Time for integral looping (result = " << res << "):"; + //t1.Print(); + LOG(DEBUG) << "Reducing... "; + //TStopwatch t; + //t.Start(); if (binmin == binmax) binmax += 1.e-1; float chinsectorminfl = float(chinsectormin); float chinsectormaxfl = float(chinsectormax); @@ -246,10 +255,10 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) auto hch = boost::histogram::algorithm::reduce(mHisto[sector], boost::histogram::algorithm::shrink(1, chinsectorminfl, chinsectormaxfl), boost::histogram::algorithm::shrink(0, binmin, binmax)); - t.Stop(); - LOG(INFO) << "Time for projection with shrink"; - t.Print(); - LOG(INFO) << "...done."; + //t.Stop(); + //LOG(DEBUG) << "Time for projection with shrink"; + //t.Print(); + //LOG(DEBUG) << "...done."; //int sizeBeforeAxis1 = mHisto[sector].axis(1).size(); //int sizeAfterAxis1 = hch.axis(1).size(); @@ -258,12 +267,12 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) //std::cout << "axis size before reduction: axis 0: " << sizeBeforeAxis0 << ", axis 1: " << sizeBeforeAxis1 << std::endl; //std::cout << "axis size after reduction: axis 0: " << sizeAfterAxis0 << ", axis 1: " << sizeAfterAxis1 << std::endl; - t.Start(); + //t.Start(); auto indhch = indexed(hch); const double enthchInd = std::accumulate(indhch.begin(), indhch.end(), 0.0); - t.Stop(); - LOG(INFO) << "Time for accumulate (result = " << enthchInd << ")"; - t.Print(); + //t.Stop(); + //LOG(DEBUG) << "Time for accumulate (result = " << enthchInd << ")"; + //t.Print(); return enthchInd; */ @@ -284,8 +293,9 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c if (binxmin < 0 || binxmax > mNBins || chmin < 0 || chmax >= o2::tof::Geo::NCHANNELS) throw std::runtime_error("Check your bins, we cannot calculate the integrals in under/overflows bins"); - if (binxmax < binxmin || chmax < chmin) + if (binxmax < binxmin || chmax < chmin) { throw std::runtime_error("Check your bin limits!"); + } int sector = chmin / o2::tof::Geo::NPADSXSECTOR; if (sector != chmax / o2::tof::Geo::NPADSXSECTOR) @@ -299,27 +309,27 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c // ", chmin = " << chmin << ", chmax" << chmax << // ", chinsectormin = " << chinsector min << ", chinsector max = " << chinsectormax; float res2 = 0; - TStopwatch t3; - t3.Start(); + //TStopwatch t3; + //t3.Start(); for (unsigned j = chinsectormin; j <= chinsectormax; ++j) { for (unsigned i = binxmin; i <= binxmax; ++i) { const auto& v = mHisto[sector].at(i, j); res2 += v; } } - t3.Stop(); - LOG(INFO) << "Time for integral looping over axis (result = " << res2 << "):"; - t3.Print(); + //t3.Stop(); + //LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; + //t3.Print(); return res2; /* // all that is below is alternative methods, all proved to be slower float res = 0, res1 = 0; - TStopwatch t1, t2; + //TStopwatch t1, t2; int ind = -1; int startCount = chinsectormin * mNBins + binxmin; int endCount = chinsectormax * mNBins + binxmax; // = startCount + (chinsectormax - chinsectormin) * mNBins + (binxmax - binxmin); LOG(DEBUG) << "startCount = " << startCount << " endCount = " << endCount-1; - t2.Start(); + //t2.Start(); int counts = -1; for (auto&& x : indexed(mHisto[sector])) { counts++; @@ -341,10 +351,10 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c // << " --> res1 = " << res1; } } - t2.Stop(); - LOG(INFO) << "Time for integral looping over restricted range (result = " << res1 << "):"; - t2.Print(); - t1.Start(); + //t2.Stop(); + //LOG(DEBUG) << "Time for integral looping over restricted range (result = " << res1 << "):"; + //t2.Print(); + //t1.Start(); for (auto&& x : indexed(mHisto[sector])) { ind++; if ((x.index(0) >= binxmin && x.index(0) <= binxmax) && (x.index(1) >= chinsectormin && x.index(1) <= chinsectormax)) { @@ -352,18 +362,18 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c //LOG(INFO) << "ind = " << ind << " will add bin " << x.index(0) << " along x and bin " << x.index(1) << " along y"; } } - t1.Stop(); - LOG(INFO) << "Time for integral looping (result = " << res << "):"; - t1.Print(); - LOG(INFO) << "Reducing... "; - TStopwatch t; - t.Start(); + //t1.Stop(); + //LOG(DEBUG) << "Time for integral looping (result = " << res << "):"; + //t1.Print(); + //LOG(DEBUG) << "Reducing... "; + //TStopwatch t; + //t.Start(); auto hch = boost::histogram::algorithm::reduce(mHisto[sector], boost::histogram::algorithm::slice(1, chinsectormin, chinsectormax+1), boost::histogram::algorithm::slice(0, binxmin, binxmax+1)); // we need to add "+1" - t.Stop(); - LOG(INFO) << "Time for projection with slice"; - t.Print(); + //t.Stop(); + //LOG(DEBUG) << "Time for projection with slice"; + //t.Print(); //LOG(INFO) << "...done."; //int sizeBeforeAxis1 = mHisto[sector].axis(1).size(); @@ -374,12 +384,12 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c //std::cout << "axis size after reduction: axis 0: " << sizeAfterAxis0 << ", axis 1: " << sizeAfterAxis1 << std::endl; // first way: using indexed (which excludes under/overflow) - t.Start(); + //t.Start(); auto indhch = indexed(hch); const double enthchInd = std::accumulate(indhch.begin(), indhch.end(), 0.0); - t.Stop(); - LOG(INFO) << "Time for accumulate (result = " << enthchInd << ")"; - t.Print(); + //t.Stop(); + //LOG(DEBUG) << "Time for accumulate (result = " << enthchInd << ")"; + //t.Print(); return enthchInd; */ } @@ -455,6 +465,7 @@ void TOFChannelCalibrator::finalizeSlot(Slot& slot) */ std::vector<int> entriesPerChannel = c->getEntriesPerChannel(); if (entriesPerChannel.at(ich) == 0) { + continue; // skip always since a channel with 0 entries is normal, it will be flagged as problematic if (mTest) { LOG(DEBUG) << "Skipping channel " << ich << " because it has zero entries, but it should not be"; // should become error! continue; @@ -473,15 +484,28 @@ void TOFChannelCalibrator::finalizeSlot(Slot& slot) } int fitres = fitGaus(c->getNbins(), histoValues.data(), -(c->getRange()), c->getRange(), fitValues); + + if (fitValues[2] < 0) + fitValues[2] = -fitValues[2]; + if (fitres >= 0) { LOG(DEBUG) << "Channel " << ich << " :: Fit result " << fitres << " Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; } else { - LOG(ERROR) << "Channel " << ich << " :: Fit failed with result = " << fitres; + LOG(INFO) << "Channel " << ich << " :: Fit failed with result = " << fitres; } float fractionUnderPeak; float intmin = fitValues[1] - 5 * fitValues[2]; // mean - 5*sigma float intmax = fitValues[1] + 5 * fitValues[2]; // mean + 5*sigma + if (intmin < -mRange) + intmin = -mRange; + if (intmax < -mRange) + intmax = -mRange; + if (intmin > mRange) + intmin = mRange; + if (intmax > mRange) + intmax = mRange; + /* // needed if we calculate the integral using the values int binmin = c->findBin(intmin); diff --git a/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h b/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h index c4e5ae2047eb6..1fa36db94a241 100644 --- a/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h @@ -122,7 +122,7 @@ DataProcessorSpec getTFDispatcherSpec() return DataProcessorSpec{ "calib-tf-dispatcher", Inputs{}, - Outputs{{{"output"}, "DUM", "DATASIZE"}}, + Outputs{{{"output"}, "TOF", "DATASIZE"}}, AlgorithmSpec{adaptFromTask<o2::calibration::TFDispatcher>()}, Options{{"max-timeframes", VariantType::Int64, 99999999999ll, {"max TimeFrames to generate"}}}}; } @@ -131,8 +131,8 @@ DataProcessorSpec getTFProcessorSpec() { return DataProcessorSpec{ "calib-tf-data-processor", - Inputs{{"input", "DUM", "DATASIZE"}}, - Outputs{{{"output"}, "DUM", "CALIBDATA"}}, + Inputs{{"input", "TOF", "DATASIZE"}}, + Outputs{{{"output"}, "TOF", "CALIBDATA"}}, AlgorithmSpec{adaptFromTask<o2::calibration::TFProcessor>()}, Options{ {"mean-latency", VariantType::Int, 1000, {"mean latency of the generator in microseconds"}}, diff --git a/Detectors/TOF/calibration/testWorkflow/LHCClockCalibratorSpec.h b/Detectors/TOF/calibration/testWorkflow/LHCClockCalibratorSpec.h index 45cbd80bf8d91..9999aad1d81c2 100644 --- a/Detectors/TOF/calibration/testWorkflow/LHCClockCalibratorSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/LHCClockCalibratorSpec.h @@ -107,7 +107,7 @@ DataProcessorSpec getLHCClockCalibDeviceSpec() outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); return DataProcessorSpec{ "calib-lhcclock-calibration", - Inputs{{"input", "DUM", "CALIBDATA"}}, + Inputs{{"input", "TOF", "CALIBDATA"}}, outputs, AlgorithmSpec{adaptFromTask<device>()}, Options{ diff --git a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h new file mode 100644 index 0000000000000..c9d7133910c08 --- /dev/null +++ b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h @@ -0,0 +1,124 @@ +// 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_CALIBRATION_TOFCALIB_COLLECTOR_H +#define O2_CALIBRATION_TOFCALIB_COLLECTOR_H + +/// @file TOFCalibCollectorSpec.h +/// @brief Device to collect information for TOF time slewing calibration. + +#include "TOFCalibration/TOFCalibCollector.h" +#include "DetectorsCalibration/Utils.h" +#include "DataFormatsTOF/CalibInfoTOF.h" +#include "Framework/Task.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace calibration +{ + +class TOFCalibCollectorDevice : public o2::framework::Task +{ + + public: + void init(o2::framework::InitContext& ic) final + { + + bool isTFsendingPolicy = ic.options().get<bool>("tf-sending-policy"); + int maxEnt = ic.options().get<int>("max-number-hits-to-fill-tree"); + bool isTest = ic.options().get<bool>("running-in-test-mode"); + bool absMaxEnt = ic.options().get<bool>("is-max-number-hits-to-fill-tree-absolute"); + mCollector = std::make_unique<o2::tof::TOFCalibCollector>(isTFsendingPolicy, maxEnt); + mCollector->isTest(isTest); + mCollector->isMaxNumberOfHitsAbsolute(absMaxEnt); + mCollector->setSlotLength(1); + mCollector->setMaxSlotsDelay(0); + } + + void run(o2::framework::ProcessingContext& pc) final + { + + auto tfcounter = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; // is this the timestamp of the current TF? + auto data = pc.inputs().get<gsl::span<o2::dataformats::CalibInfoTOF>>("input"); + LOG(INFO) << "Processing TF " << tfcounter << " with " << data.size() << " tracks"; + mCollector->process(tfcounter, data); + sendOutput(pc.outputs()); + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + constexpr uint64_t INFINITE_TF = 0xffffffffffffffff; + mCollector->checkSlotsToFinalize(INFINITE_TF); + // we force finalizing slot zero (unless everything was already finalized), no matter how many entries we had + if (mCollector->getNSlots() != 0) + mCollector->finalizeSlot(mCollector->getSlot(0)); + sendOutput(ec.outputs()); + } + + private: + std::unique_ptr<o2::tof::TOFCalibCollector> mCollector; + int mMaxNumOfHits = 0; + + //________________________________________________________________ + void sendOutput(DataAllocator& output) + { + // in output we send the calibration tree + auto& collectedInfo = mCollector->getCollectedCalibInfo(); + LOG(DEBUG) << "In CollectorSpec sendOutput: size = " << collectedInfo.size(); + if (collectedInfo.size()) { + auto entries = collectedInfo.size(); + // this means that we are ready to send the output + auto entriesPerChannel = mCollector->getEntriesPerChannel(); + output.snapshot(Output{o2::header::gDataOriginTOF, "COLLECTEDINFO", 0, Lifetime::Timeframe}, collectedInfo); + output.snapshot(Output{o2::header::gDataOriginTOF, "ENTRIESCH", 0, Lifetime::Timeframe}, entriesPerChannel); + mCollector->initOutput(); // reset the output for the next round + } + } +}; + +} // namespace calibration + +namespace framework +{ + +DataProcessorSpec getTOFCalibCollectorDeviceSpec() +{ + using device = o2::calibration::TOFCalibCollectorDevice; + using clbUtils = o2::calibration::Utils; + + std::vector<OutputSpec> outputs; + outputs.emplace_back(o2::header::gDataOriginTOF, "COLLECTEDINFO", 0, Lifetime::Timeframe); + // or should I use the ConcreteDataTypeMatcher? e.g.: outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); + outputs.emplace_back(o2::header::gDataOriginTOF, "ENTRIESCH", 0, Lifetime::Timeframe); + + std::vector<InputSpec> inputs; + inputs.emplace_back("input", "TOF", "CALIBDATA"); + + return DataProcessorSpec{ + "calib-tofcalib-collector", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<device>()}, + Options{ + {"max-number-hits-to-fill-tree", VariantType::Int, 500, {"maximum number of entries in one channel to trigger teh filling of the tree"}}, + {"is-max-number-hits-to-fill-tree-absolute", VariantType::Bool, false, {"to decide if we want to multiply the max-number-hits-to-fill-tree by the number of channels (when set to true), or not (when set to false) for fast checks"}}, + {"tf-sending-policy", VariantType::Bool, false, {"if we are sending output at every TF; otherwise, we use the max-number-hits-to-fill-tree"}}, + {"running-in-test-mode", VariantType::Bool, false, {"to run in test mode for simplification"}}}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h new file mode 100644 index 0000000000000..222d59aeb3021 --- /dev/null +++ b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h @@ -0,0 +1,126 @@ +// 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_CALIBRATION_TOFCALIB_COLLECTOR_WRITER_H +#define O2_CALIBRATION_TOFCALIB_COLLECTOR_WRITER_H + +/// @file TOFCalibCollectorWriterSpec.h +/// @brief Device to write to tree the information for TOF time slewing calibration. + +#include "TOFCalibration/TOFCalibCollector.h" +#include "DataFormatsTOF/CalibInfoTOFshort.h" +#include <TTree.h> +#include <gsl/span> + +using namespace o2::framework; + +namespace o2 +{ +namespace calibration +{ + +class TOFCalibCollectorWriter : public o2::framework::Task +{ + + using Geo = o2::tof::Geo; + + public: + void createAndOpenFileAndTree() + { + TString filename = TString::Format("collTOF_%d.root", mCount); + LOG(DEBUG) << "opening file " << filename.Data(); + mfileOut = new TFile(TString::Format("%s", filename.Data()), "RECREATE"); + mOutputTree = new TTree("treeCollectedCalibInfo", "Tree with TOF calib info for Time Slewing"); + mOutputTree->Branch(mOutputBranchName.data(), &mPTOFCalibInfoOut); + } + + void init(o2::framework::InitContext& ic) final + { + mCount = 0; + createAndOpenFileAndTree(); + } + + void run(o2::framework::ProcessingContext& pc) final + { + auto collectedInfo = pc.inputs().get<std::vector<o2::dataformats::CalibInfoTOFshort>>("collectedInfo"); + //auto collectedInfo = pc.inputs().get<gsl::span<const o2::dataformats::CalibInfoTOFshort>>("collectedInfo"); + auto entriesPerChannel = pc.inputs().get<std::array<int, Geo::NCHANNELS>>("entriesCh"); + int offsetStart = 0; + for (int ich = 0; ich < o2::tof::Geo::NCHANNELS; ich++) { + mTOFCalibInfoOut.clear(); + auto offsetEnd = offsetStart + entriesPerChannel[ich] - 1; + if (offsetEnd >= offsetStart) { + mTOFCalibInfoOut.resize(entriesPerChannel[ich]); + std::copy(collectedInfo.begin() + offsetStart, collectedInfo.begin() + offsetEnd + 1, mTOFCalibInfoOut.begin()); //mTOFCalibInfoOut->begin()); // this is very inefficient; maybe instead of vectors, using span and then one could avoid copying? https://solarianprogrammer.com/2019/11/03/cpp-20-span-tutorial/ --> did not work + } + mOutputTree->Fill(); + offsetStart += entriesPerChannel[ich]; + } + sendOutput(pc.outputs()); + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + mIsEndOfStream = true; + sendOutput(ec.outputs()); + } + + private: + int mCount = 0; // how many times we filled the tree + bool mIsEndOfStream = false; + std::vector<o2::dataformats::CalibInfoTOFshort> mTOFCalibInfoOut, *mPTOFCalibInfoOut = &mTOFCalibInfoOut; ///< these are the object and pointer to the CalibInfo of a specific channel that we need to fill the output tree + TTree* mOutputTree; ///< tree for the collected calib tof info + std::string mTOFCalibInfoBranchName = "TOFCalibInfo"; ///< name of branch containing input TOF calib infos + std::string mOutputBranchName = "TOFCollectedCalibInfo"; ///< name of branch containing output + TFile* mfileOut = nullptr; // file in which to write the output + + //________________________________________________________________ + void sendOutput(DataAllocator& output) + { + // This is to fill the tree. + // One file with an empty tree will be created at the end, because we have to have a + // tree opened before processing, since we do not know a priori if something else + // will still come. The size of this extra file is ~6.5 kB + + mfileOut->cd(); + mOutputTree->Write(); + mfileOut->Close(); + delete mfileOut; + mCount++; + if (!mIsEndOfStream) + createAndOpenFileAndTree(); + } +}; +} // namespace calibration + +namespace framework +{ + +DataProcessorSpec getTOFCalibCollectorWriterSpec() +{ + using device = o2::calibration::TOFCalibCollectorWriter; + std::vector<InputSpec> inputs; + inputs.emplace_back("collectedInfo", o2::header::gDataOriginTOF, "COLLECTEDINFO"); + inputs.emplace_back("entriesCh", o2::header::gDataOriginTOF, "ENTRIESCH"); + + std::vector<OutputSpec> outputs; // empty + + return DataProcessorSpec{ + "calib-tofcalib-collector-writer", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<device>()}, + Options{}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h index feebb45599c6f..15b44e250b27a 100644 --- a/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h @@ -43,7 +43,7 @@ class TOFChannelCalibDevice : public o2::framework::Task void init(o2::framework::InitContext& ic) final { - int minEnt = std::max(50, ic.options().get<int>("min-entries")); + int minEnt = ic.options().get<int>("min-entries"); //std::max(50, ic.options().get<int>("min-entries")); int nb = std::max(500, ic.options().get<int>("nbins")); float range = ic.options().get<float>("range"); int isTest = ic.options().get<bool>("do-TOF-channel-calib-in-test-mode"); @@ -186,7 +186,7 @@ DataProcessorSpec getTOFChannelCalibDeviceSpec(bool useCCDB, bool attachChannelO outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); std::vector<InputSpec> inputs; - inputs.emplace_back("input", "DUM", "CALIBDATA"); + inputs.emplace_back("input", "TOF", "CALIBDATA"); if (useCCDB) { inputs.emplace_back("tofccdbLHCphase", o2::header::gDataOriginTOF, "LHCphase"); inputs.emplace_back("tofccdbChannelCalib", o2::header::gDataOriginTOF, "ChannelCalib"); diff --git a/Detectors/TOF/calibration/testWorkflow/tof-collect-calib-workflow.cxx b/Detectors/TOF/calibration/testWorkflow/tof-collect-calib-workflow.cxx new file mode 100644 index 0000000000000..f31c9ce7984ae --- /dev/null +++ b/Detectors/TOF/calibration/testWorkflow/tof-collect-calib-workflow.cxx @@ -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. + +#include "TOFCalibCollectorSpec.h" +#include "TOFCalibCollectorWriterSpec.h" +#include "Framework/DataProcessorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getTOFCalibCollectorDeviceSpec()); + specs.emplace_back(getTOFCalibCollectorWriterSpec()); + + return specs; +} diff --git a/Detectors/TOF/calibration/testWorkflow/tof-dummy-ccdb-for-calib.cxx b/Detectors/TOF/calibration/testWorkflow/tof-dummy-ccdb-for-calib.cxx index 3bb4c2df855fb..1ad9eb8662b1e 100644 --- a/Detectors/TOF/calibration/testWorkflow/tof-dummy-ccdb-for-calib.cxx +++ b/Detectors/TOF/calibration/testWorkflow/tof-dummy-ccdb-for-calib.cxx @@ -22,7 +22,7 @@ std::vector<DataProcessorSpec> defineDataProcessing(ConfigContext const&) return { DataProcessorSpec{ "simple", - Inputs{{"input", "DUM", "CALIBDATA"}}, + Inputs{{"input", "TOF", "CALIBDATA"}}, Outputs{OutputSpec{{"phase"}, "TOF", "LHCphase"}, OutputSpec{{"timeSlewing"}, "TOF", "ChannelCalib"}, OutputSpec{{"startLHCphase"}, "TOF", "StartLHCphase"}, From 091fbfb8b42d604ec22acc3b474350a49705c803 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Wed, 2 Sep 2020 23:47:20 +0200 Subject: [PATCH 0538/1751] Following review to PR clang-format --- .../TOFCalibration/TOFCalibCollector.h | 4 +- .../TOFCalibration/TOFChannelCalibrator.h | 2 +- .../TOF/calibration/src/TOFCalibCollector.cxx | 52 +++++++++++++------ .../testWorkflow/TOFCalibCollectorSpec.h | 4 +- .../TOFCalibCollectorWriterSpec.h | 21 ++++---- .../testWorkflow/TOFChannelCalibratorSpec.h | 2 +- 6 files changed, 52 insertions(+), 33 deletions(-) diff --git a/Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h b/Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h index fa235ff501516..a5a664b8e9208 100644 --- a/Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h +++ b/Detectors/TOF/calibration/include/TOFCalibration/TOFCalibCollector.h @@ -73,10 +73,10 @@ class TOFCalibCollector final : public o2::calibration::TimeSlotCalibration<o2:: void initOutput() final; void finalizeSlot(Slot& slot) final; Slot& emplaceNewSlot(bool front, TFType tstart, TFType tend) final; - void isTest(bool istest) { mTest = istest; } + void setIsTest(bool istest) { mTest = istest; } auto& getCollectedCalibInfo() const { return mTOFCollectedCalibInfo; } auto& getEntriesPerChannel() const { return mEntries; } - void isMaxNumberOfHitsAbsolute(bool absNumber) { mAbsMaxNumOfHits = absNumber; } + void setIsMaxNumberOfHitsAbsolute(bool absNumber) { mAbsMaxNumOfHits = absNumber; } private: bool mTFsendingPolicy = false; // whether we will send information at every TF or only when we have a certain statistics diff --git a/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h b/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h index f2e7cc3d5412b..9927e1e549354 100644 --- a/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h +++ b/Detectors/TOF/calibration/include/TOFCalibration/TOFChannelCalibrator.h @@ -120,7 +120,7 @@ class TOFChannelCalibrator final : public o2::calibration::TimeSlotCalibration<o const CcdbObjectInfoVector& getTimeSlewingInfoVector() const { return mInfoVector; } CcdbObjectInfoVector& getTimeSlewingInfoVector() { return mInfoVector; } - void isTest(bool isTest) { mTest = isTest; } + void setIsTest(bool isTest) { mTest = isTest; } bool isTest() const { return mTest; } void setCalibTOFapi(CalibTOFapi* api) { mCalibTOFapi = api; } diff --git a/Detectors/TOF/calibration/src/TOFCalibCollector.cxx b/Detectors/TOF/calibration/src/TOFCalibCollector.cxx index 4226253686728..2e69bf9d6a42d 100644 --- a/Detectors/TOF/calibration/src/TOFCalibCollector.cxx +++ b/Detectors/TOF/calibration/src/TOFCalibCollector.cxx @@ -29,33 +29,51 @@ void TOFCalibInfoSlot::fill(const gsl::span<const o2::dataformats::CalibInfoTOF> // we do not apply any calibration at this stage, it will be applied when we // process the data before filling the CCDB in the separate process - for (int i = data.size(); i--;) { - auto ch = data[i].getTOFChIndex(); - auto offset = std::accumulate(mEntriesSlot.begin(), mEntriesSlot.begin() + ch, 0); - mTOFCollectedCalibInfoSlot.emplace(mTOFCollectedCalibInfoSlot.begin() + offset, data[i].getTimestamp(), data[i].getDeltaTimePi(), data[i].getTot(), data[i].getFlags()); + // we first order the data that arrived, to improve speed when filling + int nd = data.size(); + LOG(DEBUG) << "entries in incoming data = " << nd; + std::vector<int> ord(nd); + std::iota(ord.begin(), ord.end(), 0); + std::sort(ord.begin(), ord.end(), [&data](int i, int j) { return data[i].getTOFChIndex() < data[j].getTOFChIndex(); }); + int chPrev = 0, offsPrev = 0; + for (int i = 0; i < nd; i++) { + const auto& dti = data[ord[i]]; + auto ch = dti.getTOFChIndex(); + auto offset = offsPrev; + if (ch > chPrev) { + offset += std::accumulate(mEntriesSlot.begin() + chPrev, mEntriesSlot.begin() + ch, 0); + } + offsPrev = offset; + chPrev = ch; + mTOFCollectedCalibInfoSlot.emplace(mTOFCollectedCalibInfoSlot.begin() + offset, data[ord[i]].getTimestamp(), data[ord[i]].getDeltaTimePi(), data[ord[i]].getTot(), data[ord[i]].getFlags()); mEntriesSlot[ch]++; } } - //_____________________________________________ void TOFCalibInfoSlot::merge(const TOFCalibInfoSlot* prev) { // merge data of 2 slots - int addedPerChannel = 0; - int offset = 0; - LOG(DEBUG) << "Merging two slots with entries: current slot -> " << mTOFCollectedCalibInfoSlot.size() << " , previous slot -> " << prev->mTOFCollectedCalibInfoSlot.size(); + + int offset = 0, offsetPrev = 0; + std::vector<o2::dataformats::CalibInfoTOFshort> tmpVector; for (int ch = 0; ch < Geo::NCHANNELS; ch++) { - offset += mEntriesSlot[ch]; - if (prev->mEntriesSlot[ch] == 0) - continue; - auto offsetprevStart = addedPerChannel; - auto offsetprevEnd = addedPerChannel + prev->mEntriesSlot[ch]; - addedPerChannel += prev->mEntriesSlot[ch]; - mTOFCollectedCalibInfoSlot.insert(mTOFCollectedCalibInfoSlot.begin() + offset, prev->mTOFCollectedCalibInfoSlot.begin() + offsetprevStart, prev->mTOFCollectedCalibInfoSlot.begin() + offsetprevEnd); - mEntriesSlot[ch] += prev->mEntriesSlot[ch]; + if (mEntriesSlot[ch] != 0) { + for (int i = offset; i < offset + mEntriesSlot[ch]; i++) { + tmpVector.emplace_back(mTOFCollectedCalibInfoSlot[i]); + } + offset += mEntriesSlot[ch]; + } + if (prev->mEntriesSlot[ch] != 0) { + for (int i = offsetPrev; i < offsetPrev + prev->mEntriesSlot[ch]; i++) { + tmpVector.emplace_back(prev->mTOFCollectedCalibInfoSlot[i]); + } + offsetPrev += prev->mEntriesSlot[ch]; + mEntriesSlot[ch] += prev->mEntriesSlot[ch]; + } } + mTOFCollectedCalibInfoSlot.swap(tmpVector); LOG(DEBUG) << "After merging the size is " << mTOFCollectedCalibInfoSlot.size(); return; } @@ -114,7 +132,7 @@ bool TOFCalibCollector::hasEnoughData(const Slot& slot) const if (mTest) return true; const o2::tof::TOFCalibInfoSlot* c = slot.getContainer(); - LOG(DEBUG) << "we have " << c->getCollectedCalibInfoSlot().size() << " entries"; + LOG(INFO) << "we have " << c->getCollectedCalibInfoSlot().size() << " entries"; int maxNumberOfHits = mAbsMaxNumOfHits ? mMaxNumOfHits : mMaxNumOfHits * o2::tof::Geo::NCHANNELS; if (mTFsendingPolicy || c->getCollectedCalibInfoSlot().size() > maxNumberOfHits) return true; diff --git a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h index c9d7133910c08..f1d8542481111 100644 --- a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h @@ -41,8 +41,8 @@ class TOFCalibCollectorDevice : public o2::framework::Task bool isTest = ic.options().get<bool>("running-in-test-mode"); bool absMaxEnt = ic.options().get<bool>("is-max-number-hits-to-fill-tree-absolute"); mCollector = std::make_unique<o2::tof::TOFCalibCollector>(isTFsendingPolicy, maxEnt); - mCollector->isTest(isTest); - mCollector->isMaxNumberOfHitsAbsolute(absMaxEnt); + mCollector->setIsTest(isTest); + mCollector->setIsMaxNumberOfHitsAbsolute(absMaxEnt); mCollector->setSlotLength(1); mCollector->setMaxSlotsDelay(0); } diff --git a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h index 222d59aeb3021..2120a023c8b44 100644 --- a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h @@ -36,8 +36,8 @@ class TOFCalibCollectorWriter : public o2::framework::Task { TString filename = TString::Format("collTOF_%d.root", mCount); LOG(DEBUG) << "opening file " << filename.Data(); - mfileOut = new TFile(TString::Format("%s", filename.Data()), "RECREATE"); - mOutputTree = new TTree("treeCollectedCalibInfo", "Tree with TOF calib info for Time Slewing"); + mfileOut.reset(TFile::Open(TString::Format("%s", filename.Data()), "RECREATE")); + mOutputTree = std::make_unique<TTree>("treeCollectedCalibInfo", "Tree with TOF calib info for Time Slewing"); mOutputTree->Branch(mOutputBranchName.data(), &mPTOFCalibInfoOut); } @@ -45,20 +45,21 @@ class TOFCalibCollectorWriter : public o2::framework::Task { mCount = 0; createAndOpenFileAndTree(); + mTOFCalibInfoOut.reserve(500 * o2::tof::Geo::NCHANNELS); // should be a reasonable number of entries per channel, which allows 1 GB of data } void run(o2::framework::ProcessingContext& pc) final { auto collectedInfo = pc.inputs().get<std::vector<o2::dataformats::CalibInfoTOFshort>>("collectedInfo"); - //auto collectedInfo = pc.inputs().get<gsl::span<const o2::dataformats::CalibInfoTOFshort>>("collectedInfo"); auto entriesPerChannel = pc.inputs().get<std::array<int, Geo::NCHANNELS>>("entriesCh"); int offsetStart = 0; for (int ich = 0; ich < o2::tof::Geo::NCHANNELS; ich++) { mTOFCalibInfoOut.clear(); - auto offsetEnd = offsetStart + entriesPerChannel[ich] - 1; - if (offsetEnd >= offsetStart) { + if (entriesPerChannel[ich] > 0) { mTOFCalibInfoOut.resize(entriesPerChannel[ich]); - std::copy(collectedInfo.begin() + offsetStart, collectedInfo.begin() + offsetEnd + 1, mTOFCalibInfoOut.begin()); //mTOFCalibInfoOut->begin()); // this is very inefficient; maybe instead of vectors, using span and then one could avoid copying? https://solarianprogrammer.com/2019/11/03/cpp-20-span-tutorial/ --> did not work + auto subSpanVect = gsl::span<const o2::dataformats::CalibInfoTOFshort>(&collectedInfo[offsetStart], entriesPerChannel[ich]); + memcpy(&mTOFCalibInfoOut[0], subSpanVect.data(), sizeof(o2::dataformats::CalibInfoTOFshort) * subSpanVect.size()); + const o2::dataformats::CalibInfoTOFshort* tmp = subSpanVect.data(); } mOutputTree->Fill(); offsetStart += entriesPerChannel[ich]; @@ -76,10 +77,10 @@ class TOFCalibCollectorWriter : public o2::framework::Task int mCount = 0; // how many times we filled the tree bool mIsEndOfStream = false; std::vector<o2::dataformats::CalibInfoTOFshort> mTOFCalibInfoOut, *mPTOFCalibInfoOut = &mTOFCalibInfoOut; ///< these are the object and pointer to the CalibInfo of a specific channel that we need to fill the output tree - TTree* mOutputTree; ///< tree for the collected calib tof info + std::unique_ptr<TTree> mOutputTree; ///< tree for the collected calib tof info std::string mTOFCalibInfoBranchName = "TOFCalibInfo"; ///< name of branch containing input TOF calib infos std::string mOutputBranchName = "TOFCollectedCalibInfo"; ///< name of branch containing output - TFile* mfileOut = nullptr; // file in which to write the output + std::unique_ptr<TFile> mfileOut = nullptr; // file in which to write the output //________________________________________________________________ void sendOutput(DataAllocator& output) @@ -91,8 +92,8 @@ class TOFCalibCollectorWriter : public o2::framework::Task mfileOut->cd(); mOutputTree->Write(); - mfileOut->Close(); - delete mfileOut; + mOutputTree.reset(); + mfileOut.reset(); mCount++; if (!mIsEndOfStream) createAndOpenFileAndTree(); diff --git a/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h index 15b44e250b27a..12847abd5c364 100644 --- a/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/TOFChannelCalibratorSpec.h @@ -49,7 +49,7 @@ class TOFChannelCalibDevice : public o2::framework::Task int isTest = ic.options().get<bool>("do-TOF-channel-calib-in-test-mode"); mCalibrator = std::make_unique<o2::tof::TOFChannelCalibrator>(minEnt, nb, range); mCalibrator->setUpdateAtTheEndOfRunOnly(); - mCalibrator->isTest(isTest); + mCalibrator->setIsTest(isTest); // calibration objects set to zero mPhase.addLHCphase(0, 0); From 6dd970a0a4adb423d923ce8035c62ded83c214cb Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Thu, 3 Sep 2020 10:25:38 +0200 Subject: [PATCH 0539/1751] Using gsl::span to retrieve input Adjusting commented out lines and logs. clang format. --- .../calibration/src/TOFChannelCalibrator.cxx | 44 +++++++------------ .../TOFCalibCollectorWriterSpec.h | 6 +-- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx index 241044be3aae4..19dc2766a8ca7 100644 --- a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx +++ b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx @@ -123,7 +123,7 @@ void TOFChannelData::print(int isect) const LOG(INFO) << "Number of entries in histogram: " << boost::histogram::algorithm::sum(mHisto[isect]); for (auto&& x : indexed(mHisto[isect])) { // does not work also when I use indexed(*(mHisto[sector])) cnt++; - //LOG(INFO) << " c " << cnt << " i " << x.index(0) << " j " << x.index(1) << " b0 " << x.bin(0) << " b1 " << x.bin(1) << " val= " << *x << "|" << x.get(); + LOG(DEBUG) << " c " << cnt << " i " << x.index(0) << " j " << x.index(1) << " b0 " << x.bin(0) << " b1 " << x.bin(1) << " val= " << *x << "|" << x.get(); if (x.get() > 0) { LOG(INFO) << "x = " << x.get() << " c " << cnt; } @@ -148,12 +148,11 @@ int TOFChannelData::findBin(float v) const if (v == mRange) v -= 1.e-1; - /* - LOG(INFO) << "In FindBin, v = : " << v; - LOG(INFO) << "bin0 limits: lower = " << mHisto[0].axis(0).bin(0).lower() << ", upper = " << mHisto[0].axis(0).bin(0).upper(); - LOG(INFO) << "bin1000 limits: lower = " << mHisto[0].axis(0).bin(mNBins-1).lower() << ", upper = " << mHisto[0].axis(0).bin(mNBins-1).upper(); - LOG(INFO) << "v = " << v << " is in bin " << mHisto[0].axis(0).index(v); - */ + LOG(DEBUG) << "In FindBin, v = : " << v; + LOG(DEBUG) << "bin0 limits: lower = " << mHisto[0].axis(0).bin(0).lower() << ", upper = " << mHisto[0].axis(0).bin(0).upper(); + LOG(DEBUG) << "bin1000 limits: lower = " << mHisto[0].axis(0).bin(mNBins - 1).lower() << ", upper = " << mHisto[0].axis(0).bin(mNBins - 1).upper(); + LOG(DEBUG) << "v = " << v << " is in bin " << mHisto[0].axis(0).index(v); + return mHisto[0].axis(0).index(v); } @@ -175,28 +174,23 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) int chinsectormin = chmin % o2::tof::Geo::NPADSXSECTOR; int chinsectormax = chmax % o2::tof::Geo::NPADSXSECTOR; - //LOG(INFO) << "Calculating integral for channel " << ich << " which is in sector " << sector - // << " (channel in sector is " << chinsector << ")";; - // LOG(INFO) << "Bin min = " << binmin << ", binmax = " << binmax << - // ", chmin = " << chmin << ", chmax = " << chmax << - // ", chinsectormin = " << chinsectormin << ", chinsector max = " << chinsectormax; float res2 = 0; - //TStopwatch t3; + TStopwatch t3; int ind = -1; int binxmin = findBin(binmin); int binxmax = findBin(binmax); LOG(DEBUG) << "binxmin = " << binxmin << ", binxmax = " << binxmax; - //t3.Start(); + t3.Start(); for (unsigned j = chinsectormin; j <= chinsectormax; ++j) { for (unsigned i = binxmin; i <= binxmax; ++i) { const auto& v = mHisto[sector].at(i, j); res2 += v; } } - //t3.Stop(); - //LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; - //t3.Print(); + t3.Stop(); + LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; + t3.Print(); return res2; @@ -303,23 +297,19 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c int chinsectormin = chmin % o2::tof::Geo::NPADSXSECTOR; int chinsectormax = chmax % o2::tof::Geo::NPADSXSECTOR; - //LOG(INFO) << "Calculating integral for channel " << ich << " which is in sector " << sector - // << " (channel in sector is " << chinsector << ")";; - //LOG(INFO) << "Bin min = " << binmin << ", binmax = " << binmax << - // ", chmin = " << chmin << ", chmax" << chmax << - // ", chinsectormin = " << chinsector min << ", chinsector max = " << chinsectormax; + float res2 = 0; - //TStopwatch t3; - //t3.Start(); + TStopwatch t3; + t3.Start(); for (unsigned j = chinsectormin; j <= chinsectormax; ++j) { for (unsigned i = binxmin; i <= binxmax; ++i) { const auto& v = mHisto[sector].at(i, j); res2 += v; } } - //t3.Stop(); - //LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; - //t3.Print(); + t3.Stop(); + LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; + t3.Print(); return res2; /* // all that is below is alternative methods, all proved to be slower diff --git a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h index 2120a023c8b44..07808b0802ab9 100644 --- a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h @@ -50,14 +50,14 @@ class TOFCalibCollectorWriter : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final { - auto collectedInfo = pc.inputs().get<std::vector<o2::dataformats::CalibInfoTOFshort>>("collectedInfo"); - auto entriesPerChannel = pc.inputs().get<std::array<int, Geo::NCHANNELS>>("entriesCh"); + auto collectedInfo = pc.inputs().get<gsl::span<o2::dataformats::CalibInfoTOFshort>>("collectedInfo"); + auto entriesPerChannel = pc.inputs().get<gsl::span<int>>("entriesCh"); int offsetStart = 0; for (int ich = 0; ich < o2::tof::Geo::NCHANNELS; ich++) { mTOFCalibInfoOut.clear(); if (entriesPerChannel[ich] > 0) { mTOFCalibInfoOut.resize(entriesPerChannel[ich]); - auto subSpanVect = gsl::span<const o2::dataformats::CalibInfoTOFshort>(&collectedInfo[offsetStart], entriesPerChannel[ich]); + auto subSpanVect = collectedInfo.subspan(offsetStart, entriesPerChannel[ich]); memcpy(&mTOFCalibInfoOut[0], subSpanVect.data(), sizeof(o2::dataformats::CalibInfoTOFshort) * subSpanVect.size()); const o2::dataformats::CalibInfoTOFshort* tmp = subSpanVect.data(); } From c702fb4c417d4b2e59bb10344776b233fd519e60 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 4 Sep 2020 13:08:13 +0200 Subject: [PATCH 0540/1751] Add workflow to prepare a release --- .github/workflows/release.yml | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000000..bd39cc5b037dc --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,42 @@ +name: Prepare O2 tag + +on: + workflow_dispatch: + inputs: + tag: + description: 'Tag to prepare' + required: true + default: 'vX.Y.Z' +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Decide which branch to use + run: | + cat << EOF + ::set-output name=branch::$(echo ${{ github.event.inputs.tag }}-patches | tr . - | sed -e's/-[0-9]*-patches$/-patches/') + EOF + id: decide_release_branch + - uses: actions/checkout@v2 + with: + ref: "dev" + - name: Tag branch (or create one before tagging if does not exists) + run: | + set -x + git fetch origin + git checkout -B ${{ steps.decide_release_branch.outputs.branch }} origin/${{ steps.decide_release_branch.outputs.branch }} + git config --global user.email "alibuild@cern.ch" + git config --global user.name "ALICE Action Bot" + git tag ${{ github.event.inputs.tag }} + git push --set-upstream origin ${{ github.event.inputs.tag }} + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.event.inputs.tag }} + release_name: ${{ github.event.inputs.tag }} + draft: false + prerelease: false From b3ab80efbc93943894f265ff2ded061fbadebf6e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 4 Sep 2020 15:01:09 +0200 Subject: [PATCH 0541/1751] Interface and params for AEGIS Cosmics generator --- Generators/CMakeLists.txt | 9 ++- .../include/Generators/GenCosmicsParam.h | 56 +++++++++++++ Generators/share/external/GenCosmics.C | 80 +++++++++++++++++++ Generators/share/external/GenCosmicsLoader.C | 35 ++++++++ Generators/share/external/README.md | 14 +++- Generators/src/GenCosmicsParam.cxx | 15 ++++ Generators/src/GeneratorsLinkDef.h | 2 + cmake/O2RootMacroExclusionList.cmake | 2 + 8 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 Generators/include/Generators/GenCosmicsParam.h create mode 100644 Generators/share/external/GenCosmics.C create mode 100644 Generators/share/external/GenCosmicsLoader.C create mode 100644 Generators/src/GenCosmicsParam.cxx 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 $<$<BOOL:${pythia6_FOUND}>:src/GeneratorPythia6.cxx> $<$<BOOL:${pythia6_FOUND}>: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<GenCosmicsParam> { + 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 <FairLogger.h> + +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/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/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() From 8802dbc0d48b2cf711c8adf5a657d4ff0c70dcbc Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Thu, 3 Sep 2020 13:03:10 +0200 Subject: [PATCH 0542/1751] TPCClusterFinder: Fix memory issue introduced in #4238. --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 947c8fc5b3d7b..0aa006aafcc80 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1301,6 +1301,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::setRowOffsets>(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}); GPUTPCCFMCLabelFlattener::setGlobalOffsetsAndAllocate(clusterer, mcLinearLabels); runKernel<GPUTPCCFMCLabelFlattener, GPUTPCCFMCLabelFlattener::flatten>(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}, &mcLinearLabels); + clusterer.clearMCMemory(); } if (buildNativeHost && buildNativeGPU && anyLaneHasData) { if (GetProcessingSettings().delayedOutput) { From dc484a8ef2d2006ee259bc7a530900df2c8a079b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 5 Sep 2020 17:29:20 +0200 Subject: [PATCH 0543/1751] Fix missing includes --- Analysis/Tutorials/src/partitions.cxx | 6 +++--- Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx | 1 + Detectors/FIT/FDD/workflow/src/RecPointReaderSpec.cxx | 1 + Detectors/FIT/FDD/workflow/src/ReconstructorSpec.cxx | 1 + Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx | 1 + Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx | 1 + Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx | 1 + Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx | 1 + .../GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx | 1 + .../tofworkflow/src/CalibInfoReaderSpec.cxx | 1 + Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx | 1 + Detectors/ITSMFT/ITS/workflow/src/VertexReaderSpec.cxx | 1 + Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx | 1 + Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx | 1 + Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx | 1 + Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx | 1 + Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx | 1 + Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx | 1 + Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx | 1 + Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx | 1 + Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx | 1 + Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx | 1 + .../MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx | 1 + Detectors/MUON/MCH/Workflow/src/ClusterSinkSpec.cxx | 1 + Detectors/MUON/MCH/Workflow/src/DigitSamplerSpec.cxx | 1 + Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx | 1 + Detectors/MUON/MCH/Workflow/src/PreClusterSinkSpec.cxx | 1 + Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h | 1 + Detectors/TOF/workflow/src/CompressedInspectorTask.cxx | 2 +- Detectors/TOF/workflow/src/DigitReaderSpec.cxx | 1 + Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx | 1 + Framework/Core/include/Framework/AODReaderHelpers.h | 1 + Framework/Core/include/Framework/runDataProcessing.h | 1 + Framework/Core/src/DataSamplingPolicy.cxx | 1 + Framework/Core/src/DataSpecUtils.cxx | 1 + Framework/Core/src/FrameworkGUIDeviceInspector.cxx | 1 + Framework/Core/src/FrameworkGUIDevicesGraph.cxx | 1 + Framework/Core/test/benchmark_TreeToTable.cxx | 1 + Framework/Core/test/test_DataOutputDirector.cxx | 2 +- Framework/Utils/include/DPLUtils/DPLRawParser.h | 1 + Framework/Utils/include/DPLUtils/RootTreeReader.h | 1 + Framework/Utils/include/DPLUtils/RootTreeWriter.h | 1 + Utilities/DataFlow/src/TimeframeValidationTool.cxx | 1 + Utilities/DataFlow/test/test_TimeframeParser.cxx | 1 + Utilities/Mergers/src/FullHistoryMerger.cxx | 2 +- Utilities/Mergers/src/IntegratingMerger.cxx | 1 + 46 files changed, 48 insertions(+), 6 deletions(-) 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/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 <vector> #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/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 <vector> #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/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx index a9d518ded3827..55f1ef2a10048 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx @@ -14,6 +14,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h" using namespace o2::framework; diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx index dcbd9bd2f220c..b1ad021285f92 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx @@ -18,6 +18,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "TOFWorkflow/CalibInfoReaderSpec.h" using namespace o2::framework; diff --git a/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx index cc5d7ab29a378..befc48e62071a 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" +#include "Framework/Logger.h" #include "ITSWorkflow/DigitReaderSpec.h" #include "DataFormatsITSMFT/Digit.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/ITSMFT/ITS/workflow/src/VertexReaderSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/VertexReaderSpec.cxx index 02c8b31ac169e..31a3d29dacfed 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/VertexReaderSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/VertexReaderSpec.cxx @@ -14,6 +14,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "ITSWorkflow/VertexReaderSpec.h" using namespace o2::framework; diff --git a/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx index 70c2af1ac969d..cb6318809c17a 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx @@ -17,6 +17,7 @@ #include "TTree.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "DataFormatsITSMFT/CompCluster.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx index 031133a161f23..31fdeb964b5d8 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx @@ -17,6 +17,7 @@ #include "TTree.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "DataFormatsITSMFT/Digit.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx index b8ba2a8564306..5047a52807531 100644 --- a/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "ITSMFTWorkflow/ClusterReaderSpec.h" #include <cassert> diff --git a/Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx b/Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx index 04da59e121c1b..3d5b94503ed87 100644 --- a/Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx @@ -27,6 +27,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/ClusterBlock.h" diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx index 661c0aa2d3d51..faf2ae3de8d15 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx @@ -26,6 +26,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/ClusterBlock.h" #include "MCHBase/TrackBlock.h" diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx index 00492d6f016c9..68da3ac602722 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx @@ -27,6 +27,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/ClusterBlock.h" #include "MCHBase/TrackBlock.h" diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx index 52d2035aa75a7..8a9fb1bb0080a 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx @@ -24,6 +24,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/ClusterBlock.h" #include "MCHBase/TrackBlock.h" diff --git a/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx index 2fe970caf4f6c..a18f533605003 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx @@ -27,6 +27,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" namespace o2 { diff --git a/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx index eeb0b41b5dda0..ca1c7f954f124 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx @@ -26,6 +26,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Lifetime.h" #include "Framework/Task.h" +#include "Framework/Logger.h" namespace o2 { diff --git a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx b/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx index 7a7422e27c4d3..a0cae8c3f10cb 100644 --- a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx @@ -28,6 +28,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MathUtils/Cartesian3D.h" diff --git a/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx b/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx index b45f9ff46ff93..1b18156c737b3 100644 --- a/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx @@ -29,6 +29,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/Digit.h" #include "MCHBase/PreCluster.h" diff --git a/Detectors/MUON/MCH/Workflow/src/ClusterSinkSpec.cxx b/Detectors/MUON/MCH/Workflow/src/ClusterSinkSpec.cxx index d666faaceeb09..d8ed38121c68b 100644 --- a/Detectors/MUON/MCH/Workflow/src/ClusterSinkSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/ClusterSinkSpec.cxx @@ -28,6 +28,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Lifetime.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/Digit.h" #include "MCHBase/ClusterBlock.h" diff --git a/Detectors/MUON/MCH/Workflow/src/DigitSamplerSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DigitSamplerSpec.cxx index 336232406092b..0d5338affcaaf 100644 --- a/Detectors/MUON/MCH/Workflow/src/DigitSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DigitSamplerSpec.cxx @@ -31,6 +31,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/Digit.h" diff --git a/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx index 6784d39fe917a..3c50d2d9f2d3c 100644 --- a/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx @@ -29,6 +29,7 @@ #include "Framework/Lifetime.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/Digit.h" #include "MCHBase/PreCluster.h" diff --git a/Detectors/MUON/MCH/Workflow/src/PreClusterSinkSpec.cxx b/Detectors/MUON/MCH/Workflow/src/PreClusterSinkSpec.cxx index fccb8fe77cfb0..2721d8c624a2b 100644 --- a/Detectors/MUON/MCH/Workflow/src/PreClusterSinkSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/PreClusterSinkSpec.cxx @@ -28,6 +28,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Lifetime.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "MCHBase/Digit.h" #include "MCHBase/PreCluster.h" diff --git a/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h b/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h index 1fa36db94a241..34b56e2ab5d01 100644 --- a/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h @@ -21,6 +21,7 @@ #include "Framework/ControlService.h" #include "Framework/WorkflowSpec.h" #include "Framework/Task.h" +#include "Framework/Logger.h" #include "DataFormatsTOF/CalibInfoTOF.h" #include "TOFBase/Geo.h" #include "CommonConstants/MathConstants.h" diff --git a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx index eb96808b91687..5753434153b2a 100644 --- a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx @@ -16,7 +16,7 @@ #include "TOFWorkflow/CompressedInspectorTask.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" - +#include "Framework/Logger.h" #include "Headers/RAWDataHeader.h" #include "DataFormatsTOF/CompressedDataFormat.h" diff --git a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx index 39c1872d39af4..bfee442814a24 100644 --- a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "TOFWorkflow/DigitReaderSpec.h" #include "DataFormatsParameters/GRPObject.h" diff --git a/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx index f98d83ae1b92f..858b71717bbc5 100644 --- a/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx @@ -13,6 +13,7 @@ #include "TOFWorkflow/TOFRawWriterSpec.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "DetectorsRaw/HBFUtils.h" #include "TOFBase/Geo.h" #include "CommonUtils/StringUtils.h" diff --git a/Framework/Core/include/Framework/AODReaderHelpers.h b/Framework/Core/include/Framework/AODReaderHelpers.h index ef0460febe28c..90c4e2af04fec 100644 --- a/Framework/Core/include/Framework/AODReaderHelpers.h +++ b/Framework/Core/include/Framework/AODReaderHelpers.h @@ -13,6 +13,7 @@ #include "Framework/TableBuilder.h" #include "Framework/AlgorithmSpec.h" +#include "Framework/Logger.h" #include <uv.h> namespace o2 diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 2ee228f1e8be6..d4807a782b646 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -20,6 +20,7 @@ #include "Framework/BoostOptionsRetriever.h" #include "Framework/CustomWorkflowTerminationHook.h" #include "Framework/CommonServices.h" +#include "Framework/Logger.h" #include <boost/program_options/options_description.hpp> #include <boost/program_options/variables_map.hpp> diff --git a/Framework/Core/src/DataSamplingPolicy.cxx b/Framework/Core/src/DataSamplingPolicy.cxx index 2a6684a16397c..e4d55b41803cb 100644 --- a/Framework/Core/src/DataSamplingPolicy.cxx +++ b/Framework/Core/src/DataSamplingPolicy.cxx @@ -18,6 +18,7 @@ #include "Framework/DataSamplingConditionFactory.h" #include "Framework/DataSpecUtils.h" #include "Framework/DataDescriptorQueryBuilder.h" +#include "Framework/Logger.h" #include <boost/property_tree/ptree.hpp> 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 <cstring> #include <cinttypes> 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 <csignal> 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/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 <benchmark/benchmark.h> #include <random> #include <vector> 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 <boost/test/unit_test.hpp> - #include "Headers/DataHeader.h" #include "Framework/DataOutputDirector.h" +#include <fstream> BOOST_AUTO_TEST_CASE(TestDataOutputDirector) { 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 <utility> // 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 <TChain.h> #include <TTree.h> 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 <TFile.h> #include <TTree.h> #include <TBranch.h> 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 <vector> #include <string> #include <cctype> 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 <FairMQParts.h> #include <istream> #include <cstdlib> 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 <Monitoring/MonitoringFactory.h> 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 <Monitoring/MonitoringFactory.h> #include "Framework/InputRecordWalker.h" +#include "Framework/Logger.h" //#include "Framework/DataRef.h" //using namespace o2; From a0e03ea86fc87fc7deebdf550c6ee02d542c861c Mon Sep 17 00:00:00 2001 From: mfasel <markus.fasel@cern.ch> Date: Fri, 4 Sep 2020 15:29:08 +0200 Subject: [PATCH 0544/1751] [EMCAL-610] Circumvent out-of-bounds error The iterator mCurrentTrigger seems to be incorrectly initialized on linux systems, leading to corrupted trigger recond entries creating an out-of-bounds exception when iterating over the range in the digits vector. Circumvented by passing the current trigger directly to the process method and not storing the trigger records. --- .../include/EMCALSimulation/RawWriter.h | 26 ++++------ Detectors/EMCAL/simulation/src/RawWriter.cxx | 49 ++++++++----------- 2 files changed, 30 insertions(+), 45 deletions(-) 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<o2::emcal::Digit> digits) { mDigits = digits; } void setFileFor(FileFor_t filefor) { mFileFor = filefor; } - void setTriggerRecords(gsl::span<o2::emcal::TriggerRecord> 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<o2::emcal::Digit> digits, gsl::span<o2::emcal::TriggerRecord> triggers); - bool processNextTrigger(); + bool processTrigger(const o2::emcal::TriggerRecord& trg); int carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data, const char* ptr, int maxSize, int splitID, @@ -115,17 +111,15 @@ class RawWriter std::vector<int> encodeBunchData(const std::vector<int>& 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<o2::emcal::MappingHandler> mMappingHandler; ///< Mapping handler - gsl::span<o2::emcal::Digit> mDigits; ///< Digits input vector - must be in digitized format including the time response - gsl::span<o2::emcal::TriggerRecord> mTriggers; ///< Trigger records, separating the data from different triggers - std::vector<SRUDigitContainer> mSRUdata; ///< Internal helper of digits assigned to SRUs - gsl::span<o2::emcal::TriggerRecord>::iterator mCurrentTrigger; ///< Current trigger in the trigger records - std::unique_ptr<o2::raw::RawFileWriter> 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<o2::emcal::MappingHandler> mMappingHandler; ///< Mapping handler + gsl::span<o2::emcal::Digit> mDigits; ///< Digits input vector - must be in digitized format including the time response + std::vector<SRUDigitContainer> mSRUdata; ///< Internal helper of digits assigned to SRUs + std::unique_ptr<o2::raw::RawFileWriter> mRawWriter; ///< Raw writer ClassDefNV(RawWriter, 1); }; diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index 2bac5412c1e0c..292ddb2dd9501 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<o2::emcal::TriggerRecord> triggers) -{ - mTriggers = triggers; - mCurrentTrigger = triggers.begin(); -} - void RawWriter::init() { mRawWriter = std::make_unique<o2::raw::RawFileWriter>(o2::header::gDataOriginEMC, false); @@ -69,31 +63,26 @@ void RawWriter::init() } } -void RawWriter::process() -{ - while (processNextTrigger()) - ; -} - void RawWriter::digitsToRaw(gsl::span<o2::emcal::Digit> digitsbranch, gsl::span<o2::emcal::TriggerRecord> 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<o2::emcal::Digit*>* 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<char> 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; } From daa15b4358215fbe2b2c3f6dda2a608474380b3e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 4 Sep 2020 18:29:07 +0200 Subject: [PATCH 0545/1751] Fix in output file names --- Detectors/EMCAL/simulation/src/RawCreator.cxx | 2 +- Detectors/EMCAL/simulation/src/RawWriter.cxx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) 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 292ddb2dd9501..b4c6d3b202b4b 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -35,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; @@ -43,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()); } @@ -298,4 +298,4 @@ int RawWriter::carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> actualSize = sizeNoTrailer; } return actualSize; -} \ No newline at end of file +} From ac30578813e37eedd65af94f9b9434e844955cd5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 31 Aug 2020 12:42:15 +0200 Subject: [PATCH 0546/1751] GPU: Remove duplicate compile option --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 22a2ba4e7fc4e..ab29f84956224 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -32,8 +32,6 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") ${targetName} PUBLIC GPUCA_GPULIBRARY=CUDA $<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>) - target_compile_options(${targetName} PUBLIC --expt-relaxed-constexpr) - set_target_properties(${targetName} PROPERTIES LINKER_LANGUAGE CXX) install(FILES ${HDRS} DESTINATION include/GPU) From 4405bce1a9f94e036dce61440bcdcb6e6be749d8 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 30 Aug 2020 12:47:07 +0200 Subject: [PATCH 0547/1751] GPU: Add RTC compilation feature for CUDA --- GPU/Common/GPUCommonAlgorithm.h | 4 +- GPU/GPUTracking/Base/GPUGeneralKernels.h | 12 +- GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/Base/cuda/CMakeLists.txt | 77 +++++++++++ .../Base/cuda/GPUReconstructionCUDA.cu | 127 +++++++++++++++--- .../cuda/GPUReconstructionCUDAInternals.h | 13 +- .../Base/cuda/GPUReconstructionCUDArtc.cu | 20 ++- .../Base/cuda/GPUReconstructionCUDArtcPre.h | 17 +-- .../Base/cuda/GPUReconstructionCUDArtcPre2.h | 23 ++++ GPU/GPUTracking/Base/opencl2/CMakeLists.txt | 10 +- GPU/GPUTracking/Standalone/standalone.cxx | 2 - .../Standalone/tools/rtc/rtcsource.sh | 7 +- 12 files changed, 251 insertions(+), 62 deletions(-) create mode 100644 GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h 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/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 <cub/cub.cuh> -#define GPUCA_CUB cub #elif defined(__HIPCC__) #include <hipcub/hipcub.hpp> -#define GPUCA_CUB hipcub #endif #endif #endif @@ -54,7 +58,7 @@ class GPUKernelTemplate template <class T, int I> 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<T, I> BlockScan; typedef GPUCA_CUB::BlockReduce<T, I> BlockReduce; typedef GPUCA_CUB::WarpScan<T> WarpScan; @@ -98,4 +102,6 @@ class GPUMemClean16 : public GPUKernelTemplate } // namespace gpu } // namespace GPUCA_NAMESPACE +#undef GPUCA_CUB + #endif 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 ab29f84956224..a185a87cbe279 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -18,6 +18,83 @@ message(STATUS "Building GPUTracking with CUDA support ${TMP_TARGET}") set(SRCS GPUReconstructionCUDA.cu) set(HDRS GPUReconstructionCUDA.h GPUReconstructionCUDAInternals.h) +# -------------------------------- Prepare RTC ------------------------------------------------------- +if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") + set(CURTC_DEFINES "-D$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>,$<SEMICOLON>-D>" + "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>" + -DGPUCA_GPUCODE_GENRTC -DGPUCA_NO_ITS_TRAITS -DGPUCA_GPULIBRARY=CUDA + ) + + 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}") + 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 echo "\\# 1 \"\\\"\"${GPUDIR}/Base/cuda/GPUReconstructionCUDArtc.cu\"\\\"\"" > ${CURTC_BIN}.src + COMMAND echo "\\# 1 \"\\\"\"${GPUDIR}/Base/cuda/GPUReconstructionCUDArtcPre.h\"\\\"\" 1" >> ${CURTC_BIN}.src + COMMAND cat ${GPUDIR}/Base/cuda/GPUReconstructionCUDArtcPre2.h >> ${CURTC_BIN}.src + COMMAND ${CMAKE_CUDA_COMPILER} ${CURTC_DEFINES} ${CUDARTC_FLAGS} -E ${CURTC_SRC} > ${CURTC_BIN}.src.tmp + COMMAND cat ${CURTC_BIN}.src.tmp | sed '1,/^\# 1 \".*GPUReconstructionCUDArtcPre.h\" 1$$/d' >> ${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/GPUReconstructionCUDArtc.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_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/GPUReconstructionCUDArtc.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( ${MODULE} diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index dcaabc9bc781d..665749aed3ddc 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -22,6 +22,7 @@ #include <thrust/sort.h> #include <thrust/device_ptr.h> #pragma GCC diagnostic pop +#include <unistd.h> #ifdef __clang__ #define assert(...) @@ -114,6 +115,10 @@ class GPUDebugTiming #include "GPUReconstructionIncludesDevice.h" +extern "C" char _curtc_GPUReconstructionCUDArtc_cu_src[]; +extern "C" unsigned int _curtc_GPUReconstructionCUDArtc_cu_src_size; +extern "C" char _curtc_GPUReconstructionCUDArtc_cu_command[]; + /* // Not using templated kernel any more, since nvidia profiler does not resolve template names template <class T, int I, typename... Args> @@ -137,6 +142,16 @@ GPUg() void runKernelCUDA(GPUCA_CONSMEM_PTR int iSlice_internal, Args... args) #include "GPUReconstructionKernels.h" #undef GPUCA_KRNL +template <bool multi, class T, int I> +int GPUReconstructionCUDAInternals::getRTCkernelNum(int k) +{ + static int num = k; + if (num < 0) { + throw std::runtime_error("Invalid kernel"); + } + return num; +} + template <> void GPUReconstructionCUDABackend::runKernelBackendInternal<GPUMemClean16, 0>(krnlSetup& _xyz, void* const& ptr, unsigned long const& size) { @@ -144,11 +159,36 @@ void GPUReconstructionCUDABackend::runKernelBackendInternal<GPUMemClean16, 0>(kr GPUFailedMsg(cudaMemsetAsync(ptr, 0, size, mInternals->Streams[_xyz.x.stream])); } +static void getArgPtrs(const void** pArgs) {} +template <typename T, typename... Args> +static void getArgPtrs(const void** pArgs, const T& arg, const Args&... args) +{ + *pArgs = &arg; + getArgPtrs(pArgs + 1, args...); +} + template <class T, int I, typename... Args> void GPUReconstructionCUDABackend::runKernelBackendInternal(krnlSetup& _xyz, const Args&... args) { GPUDebugTiming timer(mProcessingSettings.deviceTimers && mProcessingSettings.debugLevel > 0, (void**)mDebugEvents, mInternals->Streams, _xyz); - backendInternal<T, I>::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<false, T, I>()], 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<true, T, I>()], x.nBlocks, 1, 1, x.nThreads, 1, 1, 0, mInternals->Streams[x.stream], (void**)pArgs, nullptr)); + } + } else { + backendInternal<T, I>::runKernelBackendMacro(_xyz, this, args...); + } } template <class T, int I, typename... Args> @@ -409,25 +449,68 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() } } + dummyInitKernel<<<mBlockCount, 256>>>(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); + + if (mProcessingSettings.enableRTC) { + 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<false, GPUCA_M_KRNL_TEMPLATE(x_class)>(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<true, GPUCA_M_KRNL_TEMPLATE(x_class)>(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()); + GPUInfo("RTC Compilation finished (%f seconds)", rtcTimer.GetCurrentElapsedTime()); + } 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<<<mBlockCount, 256>>>(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<GPUReconstructionCUDABackend*>(mMaster); mDeviceId = master->mDeviceId; @@ -546,15 +629,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/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 <vector> +#include <memory> 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<std::unique_ptr<CUfunction>> 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 <bool multi, class T, int I = 0> + 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..797e4078a453f 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu @@ -19,9 +19,19 @@ #define GPUCA_GPUTYPE_TURING #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/cuda/GPUReconstructionCUDArtcPre.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h index d994f04c93a1e..016c4ee84401e 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h @@ -11,21 +11,6 @@ /// \file GPUReconstructionCUDArtcPre.h /// \author David Rohr -//#include <cub/block/block_scan.cuh> -//#include <thrust/sort.h> -//#include <thrust/execution_policy.h> -//#include <thrust/device_ptr.h> +// Included during RTC preprocessing #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(...) -{ -} diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h new file mode 100644 index 0000000000000..a9c54f55c9a5f --- /dev/null +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h @@ -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. + +/// \file GPUReconstructionCUDArtcPre2.h +/// \author David Rohr + +// Included during RTC compilation + +#define GPUCA_CONSMEM_PTR +#define GPUCA_CONSMEM_CALL + +#include <stdint.h> +#include <cub/block/block_scan.cuh> +#include <thrust/sort.h> +#include <thrust/execution_policy.h> +#include <thrust/device_ptr.h> 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$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>,$<SEMICOLON>-D>" +set(OCL_DEFINECL "-D$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>,$<SEMICOLON>-D>" "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-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/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 <<EOT > 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 <type_traits> -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 From 9adbb6de666467f736a871de4deb87875a4ec06f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 30 Aug 2020 23:05:49 +0200 Subject: [PATCH 0548/1751] GPU: Use CMAKE_CXX_COMPILER instead of CMAKE_CUDA_COMPILER for preprocessing RTC code to avoid automatic CUDA includes --- GPU/Common/GPUCommonMath.h | 2 +- GPU/GPUTracking/Base/GPUDataTypes.h | 2 +- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 10 +++++----- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 8 ++++++-- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu | 3 --- .../Base/cuda/GPUReconstructionCUDArtcPre2.h | 3 +++ GPU/GPUTracking/SliceTracker/GPUTPCGrid.cxx | 2 +- GPU/GPUTracking/Standalone/utils/bitfield.h | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDTrackletWord.cxx | 2 +- 9 files changed, 19 insertions(+), 15 deletions(-) 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 <sm_20_atomic_functions.h> #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 <cstddef> -#endif #ifdef GPUCA_NOCOMPAT_ALLOPENCL #include <type_traits> #endif +#endif #ifdef GPUCA_NOCOMPAT #include "GPUTRDDef.h" diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index a185a87cbe279..d8a8bcd0a7d5f 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -28,6 +28,9 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") 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) @@ -43,11 +46,8 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") # cmake-format: off add_custom_command( OUTPUT ${CURTC_BIN}.src - COMMAND echo "\\# 1 \"\\\"\"${GPUDIR}/Base/cuda/GPUReconstructionCUDArtc.cu\"\\\"\"" > ${CURTC_BIN}.src - COMMAND echo "\\# 1 \"\\\"\"${GPUDIR}/Base/cuda/GPUReconstructionCUDArtcPre.h\"\\\"\" 1" >> ${CURTC_BIN}.src - COMMAND cat ${GPUDIR}/Base/cuda/GPUReconstructionCUDArtcPre2.h >> ${CURTC_BIN}.src - COMMAND ${CMAKE_CUDA_COMPILER} ${CURTC_DEFINES} ${CUDARTC_FLAGS} -E ${CURTC_SRC} > ${CURTC_BIN}.src.tmp - COMMAND cat ${CURTC_BIN}.src.tmp | sed '1,/^\# 1 \".*GPUReconstructionCUDArtcPre.h\" 1$$/d' >> ${CURTC_BIN}.src + COMMAND cat ${GPUDIR}/Base/cuda/GPUReconstructionCUDArtcPre2.h > ${CURTC_BIN}.src + COMMAND ${CMAKE_CXX_COMPILER} ${CURTC_DEFINES} -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 diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 665749aed3ddc..7234ecb3cf20b 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -454,7 +454,9 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() (long long int)mDeviceMemorySize, (int)GPUCA_GPU_STACK_SIZE, (long long int)gGPUConstantMemBufferSize); if (mProcessingSettings.enableRTC) { - GPUInfo("Starting CUDA RTC Compilation"); + if (mProcessingSettings.debugLevel >= 0) { + GPUInfo("Starting CUDA RTC Compilation"); + } HighResTimer rtcTimer; rtcTimer.ResetStart(); std::string filename = "/tmp/o2cagpu_rtc_"; @@ -498,7 +500,9 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() remove((filename + ".cu").c_str()); remove((filename + ".o").c_str()); - GPUInfo("RTC Compilation finished (%f seconds)", rtcTimer.GetCurrentElapsedTime()); + if (mProcessingSettings.debugLevel >= 0) { + GPUInfo("RTC Compilation finished (%f seconds)", rtcTimer.GetCurrentElapsedTime()); + } } void* devPtrConstantMem; #ifndef GPUCA_NO_CONSTANT_MEMORY diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu index 797e4078a453f..5df857bd136be 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu @@ -11,9 +11,6 @@ /// \file GPUReconstructionCUDArtc.cu /// \author David Rohr -#include <cuda_runtime.h> -#include <cuda.h> - #include "GPUReconstructionCUDArtcPre.h" #define GPUCA_GPUTYPE_TURING diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h index a9c54f55c9a5f..060d1ece7aaca 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h @@ -17,7 +17,10 @@ #define GPUCA_CONSMEM_CALL #include <stdint.h> +#include <cuda_runtime.h> +#include <cuda.h> #include <cub/block/block_scan.cuh> #include <thrust/sort.h> #include <thrust/execution_policy.h> #include <thrust/device_ptr.h> +#include <sm_20_atomic_functions.h> 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 <cassert> #endif 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 <type_traits> #endif diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackletWord.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackletWord.cxx index 1a899c409620d..f12833a6ddb9f 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackletWord.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackletWord.cxx @@ -13,7 +13,7 @@ #include "GPUTRDTrackletWord.h" using namespace GPUCA_NAMESPACE::gpu; -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <new> #endif From 8ede5658ec5e279c39a11a013aaa562107546e07 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 31 Aug 2020 11:42:43 +0200 Subject: [PATCH 0549/1751] GPU: Merge CUDA normal compile and rtc defs and includes into header files --- .../Base/GPUReconstructionIncludes.h | 6 ---- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 13 +++---- .../Base/cuda/GPUReconstructionCUDA.cu | 28 ++------------- .../Base/cuda/GPUReconstructionCUDADef.h | 34 +++++++++++++++++++ ...Pre2.h => GPUReconstructionCUDAIncludes.h} | 14 +++++--- .../Base/cuda/GPUReconstructionCUDArtc.cu | 4 +-- .../Base/cuda/GPUReconstructionCUDArtcPre.h | 16 --------- 7 files changed, 53 insertions(+), 62 deletions(-) create mode 100644 GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h rename GPU/GPUTracking/Base/cuda/{GPUReconstructionCUDArtcPre2.h => GPUReconstructionCUDAIncludes.h} (73%) delete mode 100644 GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h 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 <sys/syscall.h> #include <semaphore.h> diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index d8a8bcd0a7d5f..cad6a7ae40d11 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -16,14 +16,15 @@ 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 GPUReconstructionCUDIncludes.h) # -------------------------------- Prepare RTC ------------------------------------------------------- if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") set(CURTC_DEFINES "-D$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>,$<SEMICOLON>-D>" - "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>" - -DGPUCA_GPUCODE_GENRTC -DGPUCA_NO_ITS_TRAITS -DGPUCA_GPULIBRARY=CUDA + -DGPUCA_GPUCODE_GENRTC -DGPUCA_GPULIBRARY=CUDA ) + set(CURTC_INCLUDES "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>") + #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) @@ -46,8 +47,8 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") # cmake-format: off add_custom_command( OUTPUT ${CURTC_BIN}.src - COMMAND cat ${GPUDIR}/Base/cuda/GPUReconstructionCUDArtcPre2.h > ${CURTC_BIN}.src - COMMAND ${CMAKE_CXX_COMPILER} ${CURTC_DEFINES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -D__CUDACC__ -x c++ -E ${CURTC_SRC} >> ${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 @@ -61,7 +62,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") add_custom_command( OUTPUT ${CURTC_BIN}.command - COMMAND echo -n "${CMAKE_CUDA_COMPILER} ${CUDARTC_FLAGS}" > ${CURTC_BIN}.command + COMMAND echo -n "${CMAKE_CUDA_COMPILER} ${CUDARTC_FLAGS} ${CURTC_DEFINES}" > ${CURTC_BIN}.command COMMAND_EXPAND_LISTS VERBATIM ) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 7234ecb3cf20b..83a30d81c8f30 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -11,36 +11,12 @@ /// \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 <cuda.h> #include <cuda_profiler_api.h> -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#include <thrust/sort.h> -#include <thrust/device_ptr.h> -#pragma GCC diagnostic pop #include <unistd.h> -#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 "GPUReconstructionCUDA.h" #include "GPUReconstructionCUDAInternals.h" #include "GPUReconstructionIncludes.h" 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/GPUReconstructionCUDArtcPre2.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h similarity index 73% rename from GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h rename to GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h index 060d1ece7aaca..fff90de9349f8 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre2.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h @@ -8,19 +8,23 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file GPUReconstructionCUDArtcPre2.h +/// \file GPUReconstructionCUDIncludes.h /// \author David Rohr -// Included during RTC compilation - -#define GPUCA_CONSMEM_PTR -#define GPUCA_CONSMEM_CALL +#ifndef O2_GPU_GPURECONSTRUCTIONCUDAINCLUDES_H +#define O2_GPU_GPURECONSTRUCTIONCUDAINCLUDES_H #include <stdint.h> #include <cuda_runtime.h> #include <cuda.h> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include <cub/cub.cuh> #include <cub/block/block_scan.cuh> #include <thrust/sort.h> #include <thrust/execution_policy.h> #include <thrust/device_ptr.h> +#pragma GCC diagnostic pop #include <sm_20_atomic_functions.h> + +#endif diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu index 5df857bd136be..194093439f34b 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu @@ -11,9 +11,7 @@ /// \file GPUReconstructionCUDArtc.cu /// \author David Rohr -#include "GPUReconstructionCUDArtcPre.h" - -#define GPUCA_GPUTYPE_TURING +#include "GPUReconstructionCUDADef.h" #include "GPUReconstructionIncludesDevice.h" #ifndef GPUCA_GPUCODE_DEVICE diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h deleted file mode 100644 index 016c4ee84401e..0000000000000 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h +++ /dev/null @@ -1,16 +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. - -/// \file GPUReconstructionCUDArtcPre.h -/// \author David Rohr - -// Included during RTC preprocessing - -#define GPUCA_CONSMEM (gGPUConstantMemBuffer.v) From c834c0f7a1eaa1b7326dde0da4f6c9e543b1c8c1 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 31 Aug 2020 12:39:37 +0200 Subject: [PATCH 0550/1751] GPU: Fix CUDA run time compilation for AliRoot compilation and with tpc-reco-workflow --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 14 ++++++++++---- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 4 ++++ GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index cad6a7ae40d11..5d5e41b5fa28d 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -16,14 +16,20 @@ endif() message(STATUS "Building GPUTracking with CUDA support ${TMP_TARGET}") set(SRCS GPUReconstructionCUDA.cu) -set(HDRS GPUReconstructionCUDA.h GPUReconstructionCUDAInternals.h GPUReconstructionCUDADef.h GPUReconstructionCUDIncludes.h) +set(HDRS GPUReconstructionCUDA.h GPUReconstructionCUDAInternals.h GPUReconstructionCUDADef.h GPUReconstructionCUDAIncludes.h) # -------------------------------- Prepare RTC ------------------------------------------------------- if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") set(CURTC_DEFINES "-D$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>,$<SEMICOLON>-D>" -DGPUCA_GPUCODE_GENRTC -DGPUCA_GPULIBRARY=CUDA ) - set(CURTC_INCLUDES "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>") + set(CURTC_INCLUDES "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-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$<JOIN:$<TARGET_PROPERTY:O2::ITStrackingCUDA,INCLUDE_DIRECTORIES>,$<SEMICOLON>-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}") @@ -56,7 +62,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") 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/GPUReconstructionCUDArtc.src/g" > ${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 ) @@ -69,7 +75,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") 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/GPUReconstructionCUDArtc.command/g" > ${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 ) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 83a30d81c8f30..0e0d0636b1e4a 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -91,9 +91,11 @@ 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 @@ -429,6 +431,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() 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"); @@ -480,6 +483,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUInfo("RTC Compilation finished (%f seconds)", rtcTimer.GetCurrentElapsedTime()); } } +#endif void* devPtrConstantMem; #ifndef GPUCA_NO_CONSTANT_MEMORY if (mProcessingSettings.enableRTC) { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 0aa006aafcc80..a8b4268b277be 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2075,12 +2075,14 @@ int GPUChainTracking::RunTPCCompression() runKernel<GPUTPCCompressionKernels, GPUTPCCompressionKernels::step0attached>(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); runKernel<GPUTPCCompressionKernels, GPUTPCCompressionKernels::step1unattached>(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)); From 5bafbc32614453fa11fa53a22ac095bf1230cd34 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 28 Aug 2020 16:04:12 +0200 Subject: [PATCH 0551/1751] TPC: Remove obsolete functionality --- .../reconstruction/include/TPCReconstruction/GPUCATracking.h | 2 -- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 2 -- 2 files changed, 4 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/GPUCATracking.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/GPUCATracking.h index 9ec0e70bdfca8..7ff7d2d0e8729 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/GPUCATracking.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/GPUCATracking.h @@ -59,7 +59,6 @@ class GPUCATracking int runTracking(o2::gpu::GPUO2InterfaceIOPtrs* data, o2::gpu::GPUInterfaceOutputs* outputs = nullptr); float getPseudoVDrift(); //Return artificial VDrift used to convert time to Z - int getNTracksASide() { return mNTracksASide; } void GetClusterErrors2(int row, float z, float sinPhi, float DzDs, short clusterState, float& ErrY2, float& ErrZ2) const; int registerMemoryForGPU(const void* ptr, size_t size); @@ -71,7 +70,6 @@ class GPUCATracking //The GPUCATracking class interfaces this library via this pointer to GPUTPCO2Interface class. static constexpr float sTrackMCMaxFake = 0.1; - int mNTracksASide = 0; }; } // namespace tpc diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index d5c3ea09f2deb..2a572c58a2703 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -164,8 +164,6 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* std::sort(trackSort.data() + tmp2, trackSort.data() + tmp, [](const auto& a, const auto& b) { return (a.second > b.second); }); tmp2 = tmp; - if (cside == 0) - mNTracksASide = tmp; } nTracks = tmp; outputTracks->resize(nTracks); From 6a1c8d5c3561a86c12331ce655b27e6b6a6d5fea Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 5 Sep 2020 13:25:05 +0200 Subject: [PATCH 0552/1751] Fix compiler warning about initialization order --- .../Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 93323ec9355d91e86206f6030e7d976d0be7ea20 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 4 Sep 2020 22:46:37 +0200 Subject: [PATCH 0553/1751] RawPixelDecoder will fill chip decoding errors/statistics When AlpideCoder is compiled with ALPIDE_DECODING_STAT defined, the chip decoding statistics and errors will be filled in the ChipStat chipStat stuct of every GBT link. All counters (also those of GBTLink::statistics for the link level errors) can be reset via RawPixelDecoder::clearStat(). Note that in ALPIDE_DECODING_STAT the decoding will add a chip to the list of non-empty chips (i.e. it will be accessible by RawPixelDecoder::getNextChipData) even if it had no any hit but had at least 1 error set. These errors on the single trigger level can be accessed via uint32_t ChipPixelData::getErrorFlags() method, with each bit corresponding to ChipStat::DecErrors enum --- .../common/reconstruction/CMakeLists.txt | 4 +- .../ITSMFTReconstruction/AlpideCoder.h | 77 +++++++-- .../ITSMFTReconstruction/DecodingStat.h | 155 ++++++++++++++++++ .../include/ITSMFTReconstruction/GBTLink.h | 67 +------- .../include/ITSMFTReconstruction/PixelData.h | 10 ++ .../ITSMFTReconstruction/RUDecodeData.h | 35 ++-- .../ITSMFTReconstruction/RawPixelDecoder.h | 9 +- .../common/reconstruction/src/AlpideCoder.cxx | 5 + .../reconstruction/src/DecodingStat.cxx | 68 ++++++++ .../common/reconstruction/src/GBTLink.cxx | 112 +++++-------- .../src/ITSMFTReconstructionLinkDef.h | 1 + .../reconstruction/src/RUDecodeData.cxx | 8 + .../reconstruction/src/RawPixelDecoder.cxx | 21 ++- 13 files changed, 402 insertions(+), 170 deletions(-) create mode 100644 Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h create mode 100644 Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx diff --git a/Detectors/ITSMFT/common/reconstruction/CMakeLists.txt b/Detectors/ITSMFT/common/reconstruction/CMakeLists.txt index 6d5b8f97fd9eb..a1de05e673e1a 100644 --- a/Detectors/ITSMFT/common/reconstruction/CMakeLists.txt +++ b/Detectors/ITSMFT/common/reconstruction/CMakeLists.txt @@ -27,6 +27,7 @@ o2_add_library(ITSMFTReconstruction src/RUDecodeData.cxx src/RawPixelDecoder.cxx src/CTFCoder.cxx + src/DecodingStat.cxx PUBLIC_LINK_LIBRARIES O2::ITSMFTBase O2::CommonDataFormat O2::DetectorsRaw @@ -55,7 +56,8 @@ o2_target_root_dictionary( include/ITSMFTReconstruction/AlpideCoder.h include/ITSMFTReconstruction/GBTWord.h include/ITSMFTReconstruction/PayLoadCont.h - include/ITSMFTReconstruction/PayLoadSG.h + include/ITSMFTReconstruction/PayLoadSG.h + include/ITSMFTReconstruction/DecodingStat.h include/ITSMFTReconstruction/RUInfo.h) if (OpenMP_CXX_FOUND) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h index 824393966a625..fa0a5f0aaf921 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h @@ -17,14 +17,17 @@ #include <vector> #include <string> #include <cstdint> -#include <FairLogger.h> -#include <iostream> +#include "Framework/Logger.h" #include "PayLoadCont.h" #include <map> +#include <fmt/format.h> #include "ITSMFTReconstruction/PixelData.h" +#include "ITSMFTReconstruction/DecodingStat.h" #include "DataFormatsITSMFT/NoiseMap.h" +#define ALPIDE_DECODING_STAT + /// \file AlpideCoder.h /// \brief class for the ALPIDE data decoding/encoding /// \author Ruben Shahoyan, ruben.shahoyan@cern.ch @@ -68,6 +71,7 @@ class AlpideCoder static constexpr uint32_t ExpectChipEmpty = 0x1 << 2; static constexpr uint32_t ExpectRegion = 0x1 << 3; static constexpr uint32_t ExpectData = 0x1 << 4; + static constexpr uint32_t ExpectBUSY = 0x1 << 5; static constexpr int NRows = 512; static constexpr int NCols = 1024; static constexpr int NRegions = 32; @@ -80,7 +84,10 @@ class AlpideCoder static constexpr uint32_t MaskDColID = MaskEncoder | MaskPixID; // mask for encoder + dcolumn combination static constexpr uint32_t MaskRegion = 0x1f; // region ID takes 5 bits max (0:31) static constexpr uint32_t MaskChipID = 0x0f; // chip id in module takes 4 bit max - static constexpr uint32_t MaskROFlags = 0x0f; // RO flags in chip header takes 4 bit max + static constexpr uint32_t MaskROFlags = 0x0f; // RO flags in chip trailer takes 4 bit max + static constexpr uint8_t MaskErrBusyViolation = 0x1 << 3; + static constexpr uint8_t MaskErrDataOverrun = 0x3 << 2; + static constexpr uint8_t MaskErrFatal = 0x7 << 1; static constexpr uint32_t MaskTimeStamp = 0xff; // Time stamps as BUNCH_COUNTER[10:3] bits static constexpr uint32_t MaskReserved = 0xff; // mask for reserved byte static constexpr uint32_t MaskHitMap = 0x7f; // mask for hit map: at most 7 hits in bits (0:6) @@ -92,6 +99,8 @@ class AlpideCoder static constexpr uint32_t CHIPEMPTY = 0xe0; // flag for empty chip static constexpr uint32_t DATALONG = 0x0000; // flag for DATALONG static constexpr uint32_t DATASHORT = 0x4000; // flag for DATASHORT + static constexpr uint32_t BUSYOFF = 0xf0; // flag for BUSY_OFF + static constexpr uint32_t BUSYON = 0xf1; // flag for BUSY_ON // true if corresponds to DATALONG or DATASHORT: highest bit must be 0 static bool isData(uint16_t v) { return (v & (0x1 << 15)) == 0; } @@ -132,8 +141,11 @@ class AlpideCoder uint8_t dataCM = dataC & (~MaskChipID); // if ((expectInp & ExpectChipEmpty) && dataCM == CHIPEMPTY) { // empty chip was expected - //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module + //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module // now set upstream if (!buffer.next(timestamp)) { +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::TruncatedChipEmpty); +#endif return unexpectedEOF("CHIP_EMPTY:Timestamp"); } expectInp = ExpectChipHeader | ExpectChipEmpty; @@ -141,8 +153,11 @@ class AlpideCoder } if ((expectInp & ExpectChipHeader) && dataCM == CHIPHEADER) { // chip header was expected - //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module + //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module // now set upstream if (!buffer.next(timestamp)) { +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::TruncatedChipHeader); +#endif return unexpectedEOF("CHIP_HEADER"); } expectInp = ExpectRegion; // now expect region info @@ -159,6 +174,18 @@ class AlpideCoder if ((expectInp & ExpectChipTrailer) && dataCM == CHIPTRAILER) { // chip trailer was expected expectInp = ExpectChipHeader | ExpectChipEmpty; chipData.setROFlags(dataC & MaskROFlags); +#ifdef ALPIDE_DECODING_STAT + uint8_t roErr = dataC & MaskROFlags; + if (roErr) { + if (roErr == MaskErrBusyViolation) { + chipData.setError(ChipStat::BusyViolation); + } else if (roErr == MaskErrDataOverrun) { + chipData.setError(ChipStat::DataOverrun); + } else if (roErr == MaskErrFatal) { + chipData.setError(ChipStat::Fatal); + } + } +#endif // in case there are entries in the "right" columns buffer, add them to the container if (nRightCHits) { colDPrev++; @@ -175,6 +202,9 @@ class AlpideCoder // note that here we are checking on the byte rather than the short, need complete to ushort dataS = dataC << 8; if (!buffer.next(dataC)) { +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::TruncatedRegion); +#endif return unexpectedEOF("CHIPDATA"); } dataS |= dataC; @@ -211,8 +241,16 @@ class AlpideCoder if ((dataS & (~MaskDColID)) == DATALONG) { // multiple hits ? uint8_t hitsPattern = 0; if (!buffer.next(hitsPattern)) { +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::TruncatedLondData); +#endif return unexpectedEOF("CHIP_DATA_LONG:Pattern"); } +#ifdef ALPIDE_DECODING_STAT + if (hitsPattern & (~MaskHitMap)) { + chipData.setError(ChipStat::WrongDataLongPattern); + } +#endif for (int ip = 0; ip < HitMapSize; ip++) { if (hitsPattern & (0x1 << ip)) { uint16_t addr = pixID + ip + 1, rowE = addr >> 1; @@ -227,6 +265,9 @@ class AlpideCoder } } } else { +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::NoDataFound); +#endif LOG(ERROR) << "Expected DataShort or DataLong mask, got : " << dataS; return Error; } @@ -234,13 +275,27 @@ class AlpideCoder continue; // end of DATA(SHORT or LONG) processing } + if (dataC == BUSYON) { +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::BusyOn); +#endif + continue; + } + if (dataC == BUSYOFF) { +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::BusyOff); +#endif + continue; + } + if (!dataC) { buffer.clear(); // 0 padding reached (end of the cable data), no point in continuing break; } - std::stringstream stream; - stream << "Unknown word 0x" << std::hex << int(dataC) << " [mode = 0x" << int(expectInp) << "]"; - return unexpectedEOF(stream.str().c_str()); // error +#ifdef ALPIDE_DECODING_STAT + chipData.setError(ChipStat::UnknownWord); +#endif + return unexpectedEOF(fmt::format("Unknown word 0x{:x} [expectation = 0x{:x}]", int(dataC), int(expectInp))); // error } return chipData.getData().size(); @@ -362,11 +417,7 @@ class AlpideCoder void resetMap(); ///< error message on unexpected EOF - static int unexpectedEOF(const char* message) - { - printf("Error: unexpected EOF on %s\n", message); - return Error; - } + static int unexpectedEOF(const std::string& message); // ===================================================================== // diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h new file mode 100644 index 0000000000000..c6f5cebb672a8 --- /dev/null +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h @@ -0,0 +1,155 @@ +// 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 DecodingStat.h +/// \brief Alpide Chip and GBT link decoding statistics + +#ifndef _ALICEO2_DECODINGSTAT_H_ +#define _ALICEO2_DECODINGSTAT_H_ + +#include <string> +#include <array> +#include <Rtypes.h> +#include "ITSMFTReconstruction/GBTWord.h" + +namespace o2 +{ +namespace itsmft +{ + +struct ChipStat { + + enum DecErrors : int { + BusyViolation, + DataOverrun, + Fatal, + BusyOn, + BusyOff, + TruncatedChipEmpty, // Data was truncated after ChipEmpty + TruncatedChipHeader, // Data was truncated after ChipHeader + TruncatedRegion, // Data was truncated after Region record + TruncatedLondData, // Data was truncated in the LongData record + WrongDataLongPattern, // LongData pattern has highest bit set + NoDataFound, // Region is not followed by Short or Long data + UnknownWord, // Unknow word was seen + NErrorsDefined + }; + + static constexpr std::array<std::string_view, NErrorsDefined> ErrNames = { + "BusyViolation flag ON", // BusyViolation + "DataOverrun flag ON", // DataOverrun + "Fatal flag ON", // Fatal + "BusyON", // BusyOn + "BusyOFF", // BusyOff + "Data truncated after ChipEmpty", // TruncatedChipEmpty + "Data truncated after ChipHeader", // TruncatedChipHeader + "Data truncated after Region", // TruncatedRegion + "Data truncated after LongData", // TruncatedLondData + "LongData pattern has highest bit set", // WrongDataLongPattern + "Region is not followed by Short or Long data", // NoDataFound + "Unknow word" // UnknownWord + }; + + uint16_t chipID = 0; + size_t nHits = 0; + std::array<uint32_t, NErrorsDefined> errorCounts = {}; + ChipStat() = default; + ChipStat(uint16_t id) : chipID(id) {} + + void clear() + { + memset(errorCounts.data(), 0, sizeof(uint32_t) * errorCounts.size()); + nHits = 0; + } + + uint32_t getNErrors() const; + + void addErrors(uint32_t mask) + { + if (mask) { + for (int i = NErrorsDefined; i--;) { + if (mask & (0x1 << i)) { + errorCounts[i]++; + } + } + } + } + + void print(bool skipEmpty = true) const; + + ClassDefNV(ChipStat, 1); +}; + +/// Statistics for per-link decoding +struct GBTLinkDecodingStat { + /// counters for format checks + + enum DecErrors : int { + ErrNoRDHAtStart, // page does not start with RDH + ErrPageNotStopped, // new HB/trigger page started w/o stopping previous one + ErrStopPageNotEmpty, // Page with RDH.stop is not empty + ErrPageCounterDiscontinuity, // RDH page counters for the same RU/trigger are not continuous + ErrRDHvsGBTHPageCnt, // RDH and GBT header page counters are not consistent + ErrMissingGBTTrigger, // GBT trigger word was expected but not found + ErrMissingGBTHeader, // GBT payload header was expected but not found + ErrMissingGBTTrailer, // GBT payload trailer was expected but not found + ErrNonZeroPageAfterStop, // all lanes were stopped but the page counter in not 0 + ErrUnstoppedLanes, // end of FEE data reached while not all lanes received stop + ErrDataForStoppedLane, // data was received for stopped lane + ErrNoDataForActiveLane, // no data was seen for lane (which was not in timeout) + ErrIBChipLaneMismatch, // chipID (on module) was different from the lane ID on the IB stave + ErrCableDataHeadWrong, // cable data does not start with chip header or empty chip + ErrInvalidActiveLanes, // active lanes pattern conflicts with expected for given RU type + ErrPacketCounterJump, // jump in RDH.packetCounter + ErrPacketDoneMissing, // packet done is missing in the trailer while CRU page is not over + NErrorsDefined + }; + static constexpr std::array<std::string_view, NErrorsDefined> ErrNames = { + "Page data not start with expected RDH", // ErrNoRDHAtStart + "New HB/trigger page started w/o stopping previous one", // ErrPageNotStopped + "Page with RDH.stop is not empty", // ErrStopPageNotEmpty + "RDH page counters for the same RU/trigger are not continuous", // ErrPageCounterDiscontinuity + "RDH and GBT header page counters are not consistent", // ErrRDHvsGBTHPageCnt + "GBT trigger word was expected but not found", // ErrMissingGBTTrigger + "GBT payload header was expected but not found", // ErrMissingGBTHeader + "GBT payload trailer was expected but not found", // ErrMissingGBTTrailer + "All lanes were stopped but the page counter in not 0", // ErrNonZeroPageAfterStop + "End of FEE data reached while not all lanes received stop", // ErrUnstoppedLanes + "Data was received for stopped lane", // ErrDataForStoppedLane + "No data was seen for lane (which was not in timeout)", // ErrNoDataForActiveLane + "ChipID (on module) was different from the lane ID on the IB stave", // ErrIBChipLaneMismatch + "Cable data does not start with chip header or empty chip", // ErrCableDataHeadWrong + "Active lanes pattern conflicts with expected for given RU type", // ErrInvalidActiveLanes + "Jump in RDH_packetCounter", // ErrPacketCounterJump + "Packet done is missing in the trailer while CRU page is not over" // ErrPacketDoneMissing + }; + + uint32_t ruLinkID = 0; // Link ID within RU + + // Note: packet here is meant as a group of CRU pages belonging to the same trigger + uint32_t nPackets = 0; // total number of packets + std::array<uint32_t, NErrorsDefined> errorCounts = {}; // error counters + std::array<uint32_t, GBTDataTrailer::MaxStateCombinations> packetStates = {}; // packet status from the trailer + + void clear() + { + nPackets = 0; + errorCounts.fill(0); + packetStates.fill(0); + } + + void print(bool skipEmpty = true) const; + + ClassDefNV(GBTLinkDecodingStat, 1); +}; + +} // namespace itsmft +} // namespace o2 +#endif diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h index 54f77b739362d..85e05b6db5227 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h @@ -23,6 +23,7 @@ #include "ITSMFTReconstruction/PayLoadSG.h" #include "ITSMFTReconstruction/GBTWord.h" #include "ITSMFTReconstruction/RUDecodeData.h" +#include "ITSMFTReconstruction/DecodingStat.h" #include "ITSMFTReconstruction/RUInfo.h" #include "Headers/RAWDataHeader.h" #include "DetectorsRaw/RDHUtils.h" @@ -39,69 +40,6 @@ namespace o2 namespace itsmft { -/// Statistics for per-link decoding -struct GBTLinkDecodingStat { - /// counters for format checks - - enum DecErrors : int { - ErrNoRDHAtStart, // page does not start with RDH - ErrPageNotStopped, // new HB/trigger page started w/o stopping previous one - ErrStopPageNotEmpty, // Page with RDH.stop is not empty - ErrPageCounterDiscontinuity, // RDH page counters for the same RU/trigger are not continuous - ErrRDHvsGBTHPageCnt, // RDH and GBT header page counters are not consistent - ErrMissingGBTTrigger, // GBT trigger word was expected but not found - ErrMissingGBTHeader, // GBT payload header was expected but not found - ErrMissingGBTTrailer, // GBT payload trailer was expected but not found - ErrNonZeroPageAfterStop, // all lanes were stopped but the page counter in not 0 - ErrUnstoppedLanes, // end of FEE data reached while not all lanes received stop - ErrDataForStoppedLane, // data was received for stopped lane - ErrNoDataForActiveLane, // no data was seen for lane (which was not in timeout) - ErrIBChipLaneMismatch, // chipID (on module) was different from the lane ID on the IB stave - ErrCableDataHeadWrong, // cable data does not start with chip header or empty chip - ErrInvalidActiveLanes, // active lanes pattern conflicts with expected for given RU type - ErrPacketCounterJump, // jump in RDH.packetCounter - ErrPacketDoneMissing, // packet done is missing in the trailer while CRU page is not over - NErrorsDefined - }; - static constexpr std::array<std::string_view, NErrorsDefined> ErrNames = { - "Page data not start with expected RDH", // ErrNoRDHAtStart - "New HB/trigger page started w/o stopping previous one", // ErrPageNotStopped - "Page with RDH.stop is not empty", // ErrStopPageNotEmpty - "RDH page counters for the same RU/trigger are not continuous", // ErrPageCounterDiscontinuity - "RDH and GBT header page counters are not consistent", // ErrRDHvsGBTHPageCnt - "GBT trigger word was expected but not found", // ErrMissingGBTTrigger - "GBT payload header was expected but not found", // ErrMissingGBTHeader - "GBT payload trailer was expected but not found", // ErrMissingGBTTrailer - "All lanes were stopped but the page counter in not 0", // ErrNonZeroPageAfterStop - "End of FEE data reached while not all lanes received stop", // ErrUnstoppedLanes - "Data was received for stopped lane", // ErrDataForStoppedLane - "No data was seen for lane (which was not in timeout)", // ErrNoDataForActiveLane - "ChipID (on module) was different from the lane ID on the IB stave", // ErrIBChipLaneMismatch - "Cable data does not start with chip header or empty chip", // ErrCableDataHeadWrong - "Active lanes pattern conflicts with expected for given RU type", // ErrInvalidActiveLanes - "Jump in RDH_packetCounter", // ErrPacketCounterJump - "Packet done is missing in the trailer while CRU page is not over" // ErrPacketDoneMissing - }; - - uint32_t ruLinkID = 0; // Link ID within RU - - // Note: packet here is meant as a group of CRU pages belonging to the same trigger - uint32_t nPackets = 0; // total number of packets - std::array<int, NErrorsDefined> errorCounts = {}; // error counters - std::array<int, GBTDataTrailer::MaxStateCombinations> packetStates = {}; // packet status from the trailer - - void clear() - { - nPackets = 0; - errorCounts.fill(0); - packetStates.fill(0); - } - - void print(bool skipEmpty = true) const; - - ClassDefNV(GBTLinkDecodingStat, 1); -}; - struct RUDecodeData; // forward declaration to allow its linking in the GBTlink struct GBTHeader; struct GBTTrailer; @@ -159,7 +97,8 @@ struct GBTLink { uint32_t errorBits = 0; // bits of the error code of last frame decoding (if any) const RDH* lastRDH = nullptr; o2::InteractionRecord ir; // interaction record - GBTLinkDecodingStat statistics; // decoding statistics + GBTLinkDecodingStat statistics; // link decoding statistics + ChipStat chipStat; // chip decoding statistics RUDecodeData* ruPtr = nullptr; // pointer on the parent RU PayLoadSG rawData; // scatter-gatter buffer for cached CRU pages, each starting with RDH diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelData.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelData.h index 43548be90a3c7..9472b40263bfd 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelData.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelData.h @@ -15,6 +15,8 @@ #include "DataFormatsITSMFT/Digit.h" #include "CommonDataFormat/InteractionRecord.h" +#include "ITSMFTReconstruction/DecodingStat.h" + #include <vector> #include <utility> #include <cstdint> @@ -116,11 +118,18 @@ class ChipPixelData void setFirstUnmasked(uint32_t n) { mFirstUnmasked = n; } void setTrigger(uint32_t t) { mTrigger = t; } + void setError(ChipStat::DecErrors i) { mErrors |= 0x1 << i; } + void setErrorFlags(uint32_t f) { mErrors |= f; } + bool isErrorSet(ChipStat::DecErrors i) const { return mErrors & (0x1 << i); } + bool isErrorSet() const { return mErrors != 0; } + uint32_t getErrorFlags() const { return mErrors; } + void clear() { mPixels.clear(); mROFlags = 0; mFirstUnmasked = 0; + mErrors = 0; } void swap(ChipPixelData& other) @@ -222,6 +231,7 @@ class ChipPixelData uint32_t mFirstUnmasked = 0; // first unmasked entry in the mPixels uint32_t mStartID = 0; // entry of the 1st pixel data in the whole detector data, for MCtruth access uint32_t mTrigger = 0; // trigger pattern + uint32_t mErrors = 0; // errors set during decoding o2::InteractionRecord mInteractionRecord = {}; // interaction record std::vector<PixelData> mPixels; // vector of pixeld diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h index 0a43f63cc9617..1000a9e258e05 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h @@ -37,7 +37,7 @@ struct RUDecodeData { std::array<int, MaxLinksPerRU> links; // link entry RSTODO: consider removing this and using pointer std::array<uint8_t, MaxCablesPerRU> cableHWID; // HW ID of cable whose data is in the corresponding slot of cableData std::array<uint8_t, MaxCablesPerRU> cableLinkID; // ID of the GBT link transmitting this cable data - std::array<const GBTLink*, MaxCablesPerRU> cableLinkPtr; // Ptr of the GBT link transmitting this cable data + std::array<GBTLink*, MaxCablesPerRU> cableLinkPtr; // Ptr of the GBT link transmitting this cable data int ruSWID = -1; // SW (stave) ID int nCables = 0; // total number of cables decoded for single trigger @@ -55,6 +55,7 @@ struct RUDecodeData { void setROFInfo(ChipPixelData* chipData, const GBTLink* lnk); template <class Mapping> int decodeROF(const Mapping& mp); + void fillChipStatistics(int icab, const ChipPixelData* chipData); ClassDefNV(RUDecodeData, 1); }; @@ -72,28 +73,28 @@ int RUDecodeData::decodeROF(const Mapping& mp) if (!cableData[icab].getSize()) { continue; } - int nhits = 0; int cid = AlpideCoder::getChipID(cableData[icab]); if (cid < 0) { continue; } chipData->setChipID(mp.getGlobalChipID(cid, cableHWID[icab], *ruInfo)); - while ((nhits = AlpideCoder::decodeChip(*chipData, cableData[icab]))) { // we register only chips with hits or errors flags set - if (nhits > 0) { - // convert HW chip id within the module to absolute chip id - //chipData->setChipID(mp.getGlobalChipID(chipData->getChipID(), cableHWID[icab], *ruInfo)); - setROFInfo(chipData, cableLinkPtr[icab]); - ntot += nhits; - if (++nChipsFired < chipsData.size()) { // fetch next free chip - chipData = &chipsData[nChipsFired]; - cid = AlpideCoder::getChipID(cableData[icab]); - if (cid < 0) { - continue; - } - chipData->setChipID(mp.getGlobalChipID(cid, cableHWID[icab], *ruInfo)); - } else { - break; // last chip decoded + while (AlpideCoder::decodeChip(*chipData, cableData[icab]) || chipData->isErrorSet()) { // we register only chips with hits or errors flags set + // convert HW chip id within the module to absolute chip id + //chipData->setChipID(mp.getGlobalChipID(chipData->getChipID(), cableHWID[icab], *ruInfo)); + setROFInfo(chipData, cableLinkPtr[icab]); + ntot += chipData->getData().size(); +#ifdef ALPIDE_DECODING_STAT + fillChipStatistics(icab, chipData); +#endif + if (++nChipsFired < chipsData.size()) { // fetch next free chip + chipData = &chipsData[nChipsFired]; + cid = AlpideCoder::getChipID(cableData[icab]); + if (cid < 0) { + continue; } + chipData->setChipID(mp.getGlobalChipID(cid, cableHWID[icab], *ruInfo)); + } else { + break; // last chip decoded } } } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 5208f564bfb46..1eb3c7b2057c5 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -76,7 +76,9 @@ class RawPixelDecoder final : public PixelReader void setVerbosity(int v); int getVerbosity() const { return mVerbosity; } - void printReport() const; + void printReport(bool decstat = false, bool skipEmpty = true) const; + + void clearStat(); TStopwatch& getTimerTFStart() { return mTimerTFStart; } TStopwatch& getTimerDecode() { return mTimerDecode; } @@ -101,9 +103,8 @@ class RawPixelDecoder final : public PixelReader std::vector<GBTLink> mGBTLinks; // active links pool std::unordered_map<uint32_t, LinkEntry> mSubsSpec2LinkID; // link subspec to link entry in the pool mapping - - std::vector<RUDecodeData> mRUDecodeVec; // set of active RUs - std::array<int, Mapping::getNRUs()> mRUEntry; // entry of the RU with given SW ID in the mRUDecodeVec + std::vector<RUDecodeData> mRUDecodeVec; // set of active RUs + std::array<short, Mapping::getNRUs()> mRUEntry; // entry of the RU with given SW ID in the mRUDecodeVec std::string mSelfName; // self name header::DataOrigin mUserDataOrigin = o2::header::gDataOriginInvalid; // alternative user-provided data origin to pick uint16_t mCurRUDecodeID = NORUDECODED; // index of currently processed RUDecode container diff --git a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx index 05376a1298ae4..f9a62ac0667fa 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx @@ -149,3 +149,8 @@ void AlpideCoder::resetMap() } //_____________________________________ +int AlpideCoder::unexpectedEOF(const std::string& message) +{ + LOG(ERROR) << message; + return Error; +} diff --git a/Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx b/Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx new file mode 100644 index 0000000000000..270b6bd129c44 --- /dev/null +++ b/Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx @@ -0,0 +1,68 @@ +// 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 ChipStat.cxx +/// \brief Alpide Chip decoding statistics + +#include <bitset> +#include "ITSMFTReconstruction/DecodingStat.h" +#include "Framework/Logger.h" + +using namespace o2::itsmft; +constexpr std::array<std::string_view, ChipStat::NErrorsDefined> ChipStat::ErrNames; + +///_________________________________________________________________ +/// print chip decoding statistics +void ChipStat::print(bool skipEmpty) const +{ + uint32_t nErr = 0; + for (int i = NErrorsDefined; i--;) { + nErr += errorCounts[i]; + } + LOGF(INFO, "Chip#%5d NHits: %9zu errors: %u", chipID, nHits, nErr); + for (int i = 0; i < NErrorsDefined; i++) { + if (!skipEmpty || errorCounts[i]) { + LOGF(INFO, "%-70s: %u", ErrNames[i].data(), errorCounts[i]); + } + } +} + +///_________________________________________________________________ +uint32_t ChipStat::getNErrors() const +{ + uint32_t nerr = 0; + for (int i = NErrorsDefined; i--;) { + nerr += errorCounts[i]; + } + return nerr; +} + +///_________________________________________________________________ +/// print link decoding statistics +void GBTLinkDecodingStat::print(bool skipEmpty) const +{ + int nErr = 0; + for (int i = NErrorsDefined; i--;) { + nErr += errorCounts[i]; + } + LOGF(INFO, "GBTLink#0x%d Packet States Statistics (total packets: %d)", ruLinkID, nPackets); + for (int i = 0; i < GBTDataTrailer::MaxStateCombinations; i++) { + if (packetStates[i]) { + std::bitset<GBTDataTrailer::NStatesDefined> patt(i); + LOGF(INFO, "counts for triggers B[%s] : %d", patt.to_string().c_str(), packetStates[i]); + } + } + LOGF(INFO, "Decoding errors: %u", nErr); + for (int i = 0; i < NErrorsDefined; i++) { + if (!skipEmpty || errorCounts[i]) { + LOGF(INFO, "%-70s: %u", ErrNames[i].data(), errorCounts[i]); + } + } +} diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index dc9e5dc3009b0..18eee05516f20 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -21,37 +21,9 @@ using namespace o2::itsmft; -///====================================================================== -/// Decoding statistics for a single GBT link -///====================================================================== -using GBTS = GBTLinkDecodingStat; using RDHUtils = o2::raw::RDHUtils; using RDH = o2::header::RAWDataHeader; -constexpr std::array<std::string_view, GBTS::NErrorsDefined> GBTS::ErrNames; - -///_________________________________________________________________ -/// print link decoding statistics -void GBTS::print(bool skipEmpty) const -{ - int nErr = 0; - for (int i = NErrorsDefined; i--;) { - nErr += errorCounts[i]; - } - printf("GBTLink#0x%d Packet States Statistics (total packets: %d)\n", ruLinkID, nPackets); - for (int i = 0; i < GBTDataTrailer::MaxStateCombinations; i++) { - if (packetStates[i]) { - std::bitset<GBTDataTrailer::NStatesDefined> patt(i); - printf("counts for triggers B[%s] : %d\n", patt.to_string().c_str(), packetStates[i]); - } - } - printf("Decoding errors: %d\n", nErr); - for (int i = 0; i < NErrorsDefined; i++) { - if (!skipEmpty || errorCounts[i]) { - printf("%-70s: %d\n", ErrNames[i].data(), errorCounts[i]); - } - } -} ///====================================================================== /// GBT Link data decoding class @@ -127,11 +99,11 @@ void GBTLink::printTrailer(const GBTDataTrailer* gbtT) GBTLink::ErrorType GBTLink::checkErrorsRDH(const RDH& rdh) { if (!RDHUtils::checkRDH(rdh, true)) { - statistics.errorCounts[GBTS::ErrNoRDHAtStart]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrNoRDHAtStart]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrNoRDHAtStart]; + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrNoRDHAtStart]; } - errorBits |= 0x1 << int(GBTS::ErrNoRDHAtStart); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrNoRDHAtStart); return Abort; // fatal error } if (format == OldFormat && RDHUtils::getVersion(rdh) > 4) { @@ -142,12 +114,12 @@ GBTLink::ErrorType GBTLink::checkErrorsRDH(const RDH& rdh) return Abort; } if ((RDHUtils::getPacketCounter(rdh) > packetCounter + 1) && packetCounter >= 0) { - statistics.errorCounts[GBTS::ErrPacketCounterJump]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrPacketCounterJump]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrPacketCounterJump] + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrPacketCounterJump] << " : jump from " << int(packetCounter) << " to " << int(RDHUtils::getPacketCounter(rdh)); } - errorBits |= 0x1 << int(GBTS::ErrPacketCounterJump); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrPacketCounterJump); return Warning; } packetCounter = RDHUtils::getPacketCounter(rdh); @@ -160,13 +132,13 @@ GBTLink::ErrorType GBTLink::checkErrorsRDHStop(const RDH& rdh) { if (format == NewFormat && lastRDH && RDHUtils::getHeartBeatOrbit(*lastRDH) != RDHUtils::getHeartBeatOrbit(rdh) // new HB starts && !RDHUtils::getStop(*lastRDH)) { - statistics.errorCounts[GBTS::ErrPageNotStopped]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrPageNotStopped]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrPageNotStopped]; + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrPageNotStopped]; RDHUtils::printRDH(*lastRDH); RDHUtils::printRDH(rdh); } - errorBits |= 0x1 << int(GBTS::ErrPageNotStopped); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrPageNotStopped); return Warning; } return NoError; @@ -177,12 +149,12 @@ GBTLink::ErrorType GBTLink::checkErrorsRDHStop(const RDH& rdh) GBTLink::ErrorType GBTLink::checkErrorsRDHStopPageEmpty(const RDH& rdh) { if (format == NewFormat && RDHUtils::getStop(rdh) && RDHUtils::getMemorySize(rdh) != sizeof(RDH)) { - statistics.errorCounts[GBTS::ErrStopPageNotEmpty]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrStopPageNotEmpty]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrStopPageNotEmpty]; + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrStopPageNotEmpty]; RDHUtils::printRDH(rdh); } - errorBits |= 0x1 << int(GBTS::ErrStopPageNotEmpty); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrStopPageNotEmpty); return Warning; } return NoError; @@ -194,11 +166,11 @@ GBTLink::ErrorType GBTLink::checkErrorsTriggerWord(const GBTTrigger* gbtTrg) { if (!gbtTrg->isTriggerWord()) { // check trigger word gbtTrg->printX(); - statistics.errorCounts[GBTS::ErrMissingGBTTrigger]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrMissingGBTTrigger]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrMissingGBTTrigger]; + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrMissingGBTTrigger]; } - errorBits |= 0x1 << int(GBTS::ErrMissingGBTTrigger); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrMissingGBTTrigger); return Abort; } return NoError; @@ -209,35 +181,35 @@ GBTLink::ErrorType GBTLink::checkErrorsTriggerWord(const GBTTrigger* gbtTrg) GBTLink::ErrorType GBTLink::checkErrorsHeaderWord(const GBTDataHeader* gbtH) { if (!gbtH->isDataHeader()) { // check header word - statistics.errorCounts[GBTS::ErrMissingGBTHeader]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrMissingGBTHeader]++; gbtH->printX(); if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrMissingGBTHeader]; + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrMissingGBTHeader]; } - errorBits |= 0x1 << int(GBTS::ErrMissingGBTHeader); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrMissingGBTHeader); return Abort; } int cnt = RDHUtils::getPageCounter(*lastRDH); // RSTODO: this makes sense only for old format, where every trigger has its RDH if (format == OldFormat && gbtH->packetIdx != cnt) { - statistics.errorCounts[GBTS::ErrRDHvsGBTHPageCnt]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrRDHvsGBTHPageCnt]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrRDHvsGBTHPageCnt] << ": diff in GBT header " + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrRDHvsGBTHPageCnt] << ": diff in GBT header " << gbtH->packetIdx << " and RDH page " << cnt << " counters"; } - errorBits |= 0x1<<int(GBTS::ErrRDHvsGBTHPageCnt); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrRDHvsGBTHPageCnt); return Warning; } // RSTODO CHECK if (lanesActive == lanesStop) { // all lanes received their stop, new page 0 expected //if (cnt) { // makes sens for old format only if (gbtH->packetIdx) { - statistics.errorCounts[GBTS::ErrNonZeroPageAfterStop]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrNonZeroPageAfterStop]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrNonZeroPageAfterStop] + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrNonZeroPageAfterStop] << ": Non-0 page counter (" << cnt << ") while all lanes were stopped"; } - errorBits |= 0x1 << int(GBTS::ErrNonZeroPageAfterStop); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrNonZeroPageAfterStop); return Warning; } } @@ -249,13 +221,13 @@ GBTLink::ErrorType GBTLink::checkErrorsHeaderWord(const GBTDataHeader* gbtH) GBTLink::ErrorType GBTLink::checkErrorsActiveLanes(int cbl) { if (~cbl & lanesActive) { // are there wrong lanes? - statistics.errorCounts[GBTS::ErrInvalidActiveLanes]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrInvalidActiveLanes]++; std::bitset<32> expectL(cbl), gotL(lanesActive); if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrInvalidActiveLanes] + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrInvalidActiveLanes] << gotL << " vs " << expectL << " skip page"; } - errorBits |= 0x1 << int(GBTS::ErrInvalidActiveLanes); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrInvalidActiveLanes); return Warning; } return NoError; @@ -267,12 +239,12 @@ GBTLink::ErrorType GBTLink::checkErrorsGBTData(int cablePos) { lanesWithData |= 0x1 << cablePos; // flag that the data was seen on this lane if (lanesStop & (0x1 << cablePos)) { // make sure stopped lanes do not transmit the data - statistics.errorCounts[GBTS::ErrDataForStoppedLane]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrDataForStoppedLane]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrDataForStoppedLane] + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrDataForStoppedLane] << cablePos; } - errorBits |= 0x1 << int(GBTS::ErrDataForStoppedLane); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrDataForStoppedLane); return Warning; } @@ -285,11 +257,11 @@ GBTLink::ErrorType GBTLink::checkErrorsTrailerWord(const GBTDataTrailer* gbtT) { if (!gbtT->isDataTrailer()) { gbtT->printX(); - statistics.errorCounts[GBTS::ErrMissingGBTTrailer]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrMissingGBTTrailer]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrMissingGBTTrailer]; + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrMissingGBTTrailer]; } - errorBits |= 0x1 << int(GBTS::ErrMissingGBTTrailer); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrMissingGBTTrailer); return Abort; } lanesTimeOut |= gbtT->lanesTimeout; // register timeouts @@ -302,11 +274,11 @@ GBTLink::ErrorType GBTLink::checkErrorsTrailerWord(const GBTDataTrailer* gbtT) GBTLink::ErrorType GBTLink::checkErrorsPacketDoneMissing(const GBTDataTrailer* gbtT, bool notEnd) { if (!gbtT->packetDone && notEnd) { // Done may be missing only in case of carry-over to new CRU page - statistics.errorCounts[GBTS::ErrPacketDoneMissing]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrPacketDoneMissing]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrPacketDoneMissing]; + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrPacketDoneMissing]; } - errorBits |= 0x1 << int(GBTS::ErrPacketDoneMissing); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrPacketDoneMissing); return Warning; } return NoError; @@ -320,25 +292,25 @@ GBTLink::ErrorType GBTLink::checkErrorsLanesStops() auto err = NoError; if ((lanesActive & ~lanesStop)) { if (RDHUtils::getTriggerType(*lastRDH) != o2::trigger::SOT) { // only SOT trigger allows unstopped lanes? - statistics.errorCounts[GBTS::ErrUnstoppedLanes]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrUnstoppedLanes]++; std::bitset<32> active(lanesActive), stopped(lanesStop); if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrUnstoppedLanes] + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrUnstoppedLanes] << " | active: " << active << " stopped: " << stopped; } - errorBits |= 0x1 << int(GBTS::ErrUnstoppedLanes); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrUnstoppedLanes); } err = Warning; } // make sure all active lanes (except those in time-out) have sent some data if ((~lanesWithData & lanesActive) != lanesTimeOut) { std::bitset<32> withData(lanesWithData), active(lanesActive), timeOut(lanesTimeOut); - statistics.errorCounts[GBTS::ErrNoDataForActiveLane]++; + statistics.errorCounts[GBTLinkDecodingStat::ErrNoDataForActiveLane]++; if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTS::ErrNoDataForActiveLane] + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrNoDataForActiveLane] << " | with data: " << withData << " active: " << active << " timeOut: " << timeOut; } - errorBits |= 0x1 << int(GBTS::ErrNoDataForActiveLane); + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrNoDataForActiveLane); err = Warning; } return err; diff --git a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h index 19d2a85352fd2..4c84473abfcaa 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h +++ b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h @@ -41,6 +41,7 @@ #pragma link C++ class o2::itsmft::GBTLink + ; #pragma link C++ class o2::itsmft::RUDecodeData + ; #pragma link C++ class o2::itsmft::RawDecodingStat + ; +#pragma link C++ class o2::itsmft::ChipStat + ; #pragma link C++ class std::map < unsigned long, std::pair < o2::itsmft::ClusterTopology, unsigned long>> + ; diff --git a/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx b/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx index 4006892dfaaa0..3641991899487 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx @@ -47,5 +47,13 @@ void RUDecodeData::setROFInfo(ChipPixelData* chipData, const GBTLink* lnk) chipData->setInteractionRecord(lnk->ir); } +///_________________________________________________________________ +/// fill chip decoding statistics +void RUDecodeData::fillChipStatistics(int icab, const ChipPixelData* chipData) +{ + cableLinkPtr[icab]->chipStat.nHits += chipData->getData().size(); + cableLinkPtr[icab]->chipStat.addErrors(chipData->getErrorFlags()); +} + } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx index 5d88c8ae54ea1..f84c11ceb2bc0 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx @@ -39,7 +39,7 @@ RawPixelDecoder<Mapping>::RawPixelDecoder() ///______________________________________________________________ /// template <class Mapping> -void RawPixelDecoder<Mapping>::printReport() const +void RawPixelDecoder<Mapping>::printReport(bool decstat, bool skipEmpty) const { LOGF(INFO, "%s Decoded %zu hits in %zu non-empty chips in %u ROFs with %d threads", mSelfName, mNPixelsFired, mNChipsFired, mROFCounter, mNThreads); double cpu = 0, real = 0; @@ -57,6 +57,15 @@ void RawPixelDecoder<Mapping>::printReport() const real += tmrF.RealTime(); LOGF(INFO, "%s Timing Total: CPU = %.3e Real = %.3e in %d slots in %s mode", mSelfName, cpu, real, tmrS.Counter() - 1, mDecodeNextAuto ? "AutoDecode" : "ExternalCall"); + + if (decstat) { + LOG(INFO) << "GBT Links decoding statistics"; + for (auto& lnk : mGBTLinks) { + LOG(INFO) << lnk.describe(); + lnk.statistics.print(skipEmpty); + lnk.chipStat.print(skipEmpty); + } + } } ///______________________________________________________________ @@ -300,5 +309,15 @@ void RawPixelDecoder<Mapping>::setFormat(GBTLink::Format f) mFormat = f; } +///______________________________________________________________________ +template <class Mapping> +void RawPixelDecoder<Mapping>::clearStat() +{ + // clear statistics + for (auto& lnk : mGBTLinks) { + lnk.clear(true, false); + } +} + template class o2::itsmft::RawPixelDecoder<o2::itsmft::ChipMappingITS>; template class o2::itsmft::RawPixelDecoder<o2::itsmft::ChipMappingMFT>; From b62f04f8a24e1114c0ee20b0358c658764798295 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 4 Sep 2020 18:01:39 +0200 Subject: [PATCH 0554/1751] Speedup navigation to need TF in RawFileReader --- .../Raw/include/DetectorsRaw/RawFileReader.h | 1 + Detectors/Raw/src/RawFileReader.cxx | 64 +++++++++++++------ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index af651f51744b7..40e521e2c3f81 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -147,6 +147,7 @@ class RawFileReader std::string fairMQChannel{}; //! name of the fairMQ channel for the output int nErrors = 0; //! std::vector<LinkBlock> blocks; //! + std::vector<std::pair<int, uint32_t>> tfStartBlock; // // transient info during processing bool openHB = false; //! diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index a10217ee73dd5..ba55b5f6196c9 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -104,10 +104,12 @@ size_t RawFileReader::LinkData::getNextHBFSize() const // estimate the memory size of the next HBF to read // The blocks are guaranteed to not cover more than 1 HB size_t sz = 0; - int ibl = nextBlock2Read, nbl = blocks.size(); - while (ibl < nbl && (blocks[ibl].ir == blocks[nextBlock2Read].ir)) { - sz += blocks[ibl].size; - ibl++; + if (nextBlock2Read >= 0) { // negative nextBlock2Read signals absence of data + int ibl = nextBlock2Read, nbl = blocks.size(); + while (ibl < nbl && (blocks[ibl].ir == blocks[nextBlock2Read].ir)) { + sz += blocks[ibl].size; + ibl++; + } } return sz; } @@ -117,6 +119,9 @@ size_t RawFileReader::LinkData::readNextHBF(char* buff) { // read data of the next complete HB, buffer of getNextHBFSize() must be allocated in advance size_t sz = 0; + if (nextBlock2Read < 0) { // negative nextBlock2Read signals absence of data + return sz; + } int ibl = nextBlock2Read, nbl = blocks.size(); bool error = false; while (ibl < nbl) { @@ -149,6 +154,9 @@ size_t RawFileReader::LinkData::skipNextHBF() { // skip next complete HB size_t sz = 0; + if (nextBlock2Read < 0) { // negative nextBlock2Read signals absence of data + return sz; + } int ibl = nextBlock2Read, nbl = blocks.size(); while (ibl < nbl) { const auto& blc = blocks[ibl]; @@ -168,10 +176,12 @@ size_t RawFileReader::LinkData::getNextTFSize() const // estimate the memory size of the next TF to read // (assuming nextBlock2Read is at the start of the TF) size_t sz = 0; - int ibl = nextBlock2Read, nbl = blocks.size(); - while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { - sz += blocks[ibl].size; - ibl++; + if (nextBlock2Read >= 0) { // negative nextBlock2Read signals absence of data + int ibl = nextBlock2Read, nbl = blocks.size(); + while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { + sz += blocks[ibl].size; + ibl++; + } } return sz; } @@ -181,6 +191,9 @@ size_t RawFileReader::LinkData::readNextTF(char* buff) { // read next complete TF, buffer of getNextTFSize() must be allocated in advance size_t sz = 0; + if (nextBlock2Read < 0) { // negative nextBlock2Read signals absence of data + return sz; + } int ibl0 = nextBlock2Read, nbl = blocks.size(); bool error = false; while (nextBlock2Read < nbl && (blocks[nextBlock2Read].tfID == blocks[ibl0].tfID)) { // nextBlock2Read is incremented by the readNextHBF! @@ -198,6 +211,9 @@ size_t RawFileReader::LinkData::skipNextTF() { // skip next complete TF size_t sz = 0; + if (nextBlock2Read < 0) { // negative nextBlock2Read signals absence of data + return sz; + } int ibl0 = nextBlock2Read, nbl = blocks.size(); bool error = false; while (nextBlock2Read < nbl && (blocks[nextBlock2Read].tfID == blocks[ibl0].tfID)) { // nextBlock2Read is incremented by the readNextHBF! @@ -214,9 +230,11 @@ size_t RawFileReader::LinkData::skipNextTF() void RawFileReader::LinkData::rewindToTF(uint32_t tf) { // go to given TF - nextBlock2Read = 0; - for (uint32_t i = 0; i < tf; i++) { - skipNextTF(); + if (tf < tfStartBlock.size()) { + nextBlock2Read = tfStartBlock[tf].first; + } else { + LOG(WARNING) << "No TF " << tf << " for link " << describe(); + nextBlock2Read = -1; } } @@ -225,11 +243,13 @@ int RawFileReader::LinkData::getNHBFinTF() const { // estimate number of HBFs left in the TF int ibl = nextBlock2Read, nbl = blocks.size(), nHB = 0; - while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { - if (blocks[ibl].testFlag(LinkBlock::StartHB)) { - nHB++; + if (nextBlock2Read >= 0) { // negative nextBlock2Read signals absence of data + while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { + if (blocks[ibl].testFlag(LinkBlock::StartHB)) { + nHB++; + } + ibl++; } - ibl++; } return nHB; } @@ -239,6 +259,9 @@ size_t RawFileReader::LinkData::readNextSuperPage(char* buff, const RawFileReade { // read data of the next complete HB, buffer of getNextHBFSize() must be allocated in advance size_t sz = 0; + if (nextBlock2Read < 0) { // negative nextBlock2Read signals absence of data + return sz; + } int ibl = nextBlock2Read, nbl = blocks.size(); auto tfID = blocks[nextBlock2Read].tfID; bool error = false; @@ -424,8 +447,12 @@ bool RawFileReader::LinkData::preprocessCRUPage(const RDHAny& rdh, bool newSPage } if (newTF || newSPage || newHB) { + int nbl = blocks.size(); auto& bl = blocks.emplace_back(reader->mCurrentFileID, reader->mPosInFile); + bl.ir = hbIR; + bl.tfID = HBU.getTF(hbIR); // nTimeFrames - 1; if (newTF) { + tfStartBlock.emplace_back(nbl, bl.tfID); nTimeFrames++; bl.setFlag(LinkBlock::StartTF); if (reader->mCheckErrors & (0x1 << ErrNoSuperPageForTF) && cruDetector) { @@ -436,8 +463,6 @@ bool RawFileReader::LinkData::preprocessCRUPage(const RDHAny& rdh, bool newSPage } } // end of check errors } - bl.ir = hbIR; - bl.tfID = HBU.getTF(hbIR); // nTimeFrames - 1; if (newSPage) { nSPages++; @@ -658,7 +683,7 @@ bool RawFileReader::init() LOGF(INFO, "Summary of preprocessing:"); for (int i = 0; i < int(mLinksData.size()); i++) { - const auto& link = getLink(i); + auto& link = getLink(i); auto msp = link.getLargestSuperPage(); auto mtf = link.getLargestTF(); if (maxSP < msp) { @@ -681,6 +706,9 @@ bool RawFileReader::init() if (link.blocks.back().ir.orbit > mOrbitMax) { mOrbitMax = link.blocks.back().ir.orbit; } + if (link.tfStartBlock.empty() && !link.blocks.empty()) { + link.tfStartBlock.emplace_back(0, 0); + } if ((mCheckErrors & (0x1 << ErrWrongNumberOfTF)) && (mNTimeFrames != link.nTimeFrames)) { LOGF(ERROR, "%s for %s: %u TFs while %u were seen for other links", ErrNames[ErrWrongNumberOfTF], link.describe(), link.nTimeFrames, mNTimeFrames); From c2fe6d3a2f75ebc283dc59c13abddbef565f7bd0 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 5 Sep 2020 16:05:09 +0200 Subject: [PATCH 0555/1751] With --detect-tf0 raw-reader will autodetect HBFUtils 1st IR --- Detectors/Raw/README.md | 6 +- .../Raw/include/DetectorsRaw/RawFileReader.h | 18 ++++-- Detectors/Raw/src/RawFileReader.cxx | 55 +++++++++++++------ Detectors/Raw/src/RawFileReaderWorkflow.cxx | 11 ++-- Detectors/Raw/src/RawFileReaderWorkflow.h | 2 +- Detectors/Raw/src/rawfile-reader-workflow.cxx | 4 +- Detectors/Raw/src/rawfileCheck.cxx | 4 +- 7 files changed, 68 insertions(+), 32 deletions(-) diff --git a/Detectors/Raw/README.md b/Detectors/Raw/README.md index a04841f24c3aa..a364302317016 100644 --- a/Detectors/Raw/README.md +++ b/Detectors/Raw/README.md @@ -312,7 +312,7 @@ o2-raw-file-reader-workflow --part-per-hbf FMQ parts per superpage (default) of HBF --raw-channel-config arg optional raw FMQ channel for non-DPL output --cache-data cache data at 1st reading, may require excessive memory!!! - + --detect-tf0 autodetect HBFUtils start Orbit/BC from 1st TF seen --configKeyValues arg semicolon separated key=value strings # to suppress various error checks / reporting @@ -362,7 +362,9 @@ Options: -m [ --max-tf] arg (=0xffffffff) max. TF ID to read (counts from 0) -v [ --verbosity ] arg (=0) 1: long report, 2 or 3: print or dump all RDH -s [ --spsize ] arg (=1048576) nominal super-page size in bytes - -t [ --hbfpertf ] arg (=256) nominal number of HBFs per TF + --detect-tf0 autodetect HBFUtils start Orbit/BC from 1st TF seen + --rorc impose RORC as default detector mode + --configKeyValues arg semicolon separated key=value strings --nocheck-packet-increment ignore /Wrong RDH.packetCounter increment/ --nocheck-page-increment ignore /Wrong RDH.pageCnt increment/ --check-stop-on-page0 check /RDH.stop set of 1st HBF page/ diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index 40e521e2c3f81..643834c485d37 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -54,6 +54,11 @@ class RawFileReader ErrNoSuperPageForTF, NErrorsDefined }; + + enum class FirstTFDetection : int { Disabled, + Pending, + Done }; + static constexpr std::string_view ErrNames[] = { // long names for error codes "Wrong RDH.packetCounter increment", // ErrWrongPacketCounterIncrement @@ -156,7 +161,7 @@ class RawFileReader LinkData() = default; template <typename H> - LinkData(const H& rdh, const RawFileReader* r) : rdhl(rdh), reader(r) + LinkData(const H& rdh, RawFileReader* r) : rdhl(rdh), reader(r) { } bool preprocessCRUPage(const RDHAny& rdh, bool newSPage); @@ -174,12 +179,11 @@ class RawFileReader size_t skipNextTF(); void rewindToTF(uint32_t tf); - void print(bool verbose = false, const std::string& pref = "") const; std::string describe() const; private: - const RawFileReader* reader = nullptr; //! + RawFileReader* reader = nullptr; //! }; //===================================================================================== @@ -237,6 +241,10 @@ class RawFileReader o2::header::DataDescription getDefaultDataSpecification() const { return mDefDataDescription; } ReadoutCardType getDefaultReadoutCardType() const { return mDefCardType; } + void imposeFirstTF(uint32_t orbit, uint16_t bc); + void setTFAutodetect(FirstTFDetection v) { mFirstTFAutodetect = v; } + FirstTFDetection getTFAutodetect() const { return mFirstTFAutodetect; } + static o2::header::DataOrigin getDataOrigin(const std::string& ors); static o2::header::DataDescription getDataDescription(const std::string& ors); static InputsMap parseInput(const std::string& confUri); @@ -277,8 +285,8 @@ class RawFileReader bool mMultiLinkFile = false; //! was > than 1 link seen in the file? bool mCacheData = false; //! cache data to block after 1st scan (may require excessive memory, use with care) uint32_t mCheckErrors = 0; //! mask for errors to check - int mVerbosity = 0; - + FirstTFDetection mFirstTFAutodetect = FirstTFDetection::Disabled; //! + int mVerbosity = 0; //! ClassDefNV(RawFileReader, 1); }; diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index ba55b5f6196c9..635ff5927e9ae 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -76,24 +76,24 @@ size_t RawFileReader::LinkData::getNextTFSuperPagesStat(std::vector<RawFileReade { // get stat. of superpages for this link in this TF. We treat as a start of a superpage the discontinuity in the link data, new TF // or continuous data exceeding a threshold (e.g. 1MB) - int sz = 0; - int nSP = 0; - int ibl = nextBlock2Read, nbl = blocks.size(), nblPart = 0; - parts.clear(); - while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { - if (ibl > nextBlock2Read && (blocks[ibl].testFlag(LinkBlock::StartSP) || - (sz + blocks[ibl].size) > reader->mNominalSPageSize || - (blocks[ibl - 1].offset + blocks[ibl - 1].size) < blocks[ibl].offset)) { // new superpage + if (nextBlock2Read >= 0) { // negative nextBlock2Read signals absence of data + int sz = 0, nSP = 0, ibl = nextBlock2Read, nbl = blocks.size(), nblPart = 0; + parts.clear(); + while (ibl < nbl && (blocks[ibl].tfID == blocks[nextBlock2Read].tfID)) { + if (ibl > nextBlock2Read && (blocks[ibl].testFlag(LinkBlock::StartSP) || + (sz + blocks[ibl].size) > reader->mNominalSPageSize || + (blocks[ibl - 1].offset + blocks[ibl - 1].size) < blocks[ibl].offset)) { // new superpage + parts.emplace_back(RawFileReader::PartStat{sz, nblPart}); + sz = 0; + nblPart = 0; + } + sz += blocks[ibl].size; + nblPart++; + ibl++; + } + if (sz) { parts.emplace_back(RawFileReader::PartStat{sz, nblPart}); - sz = 0; - nblPart = 0; } - sz += blocks[ibl].size; - nblPart++; - ibl++; - } - if (sz) { - parts.emplace_back(RawFileReader::PartStat{sz, nblPart}); } return parts.size(); } @@ -452,6 +452,14 @@ bool RawFileReader::LinkData::preprocessCRUPage(const RDHAny& rdh, bool newSPage bl.ir = hbIR; bl.tfID = HBU.getTF(hbIR); // nTimeFrames - 1; if (newTF) { + if (reader->getTFAutodetect() == FirstTFDetection::Pending) { // impose first TF + if (cruDetector) { + reader->imposeFirstTF(hbIR.orbit, hbIR.bc); + bl.tfID = HBU.getTF(hbIR); // update + } else { + throw std::runtime_error("HBFUtil first orbit/bc autodetection cannot be done with first link from CRORC detector"); + } + } tfStartBlock.emplace_back(nbl, bl.tfID); nTimeFrames++; bl.setFlag(LinkBlock::StartTF); @@ -714,7 +722,7 @@ bool RawFileReader::init() link.describe(), link.nTimeFrames, mNTimeFrames); } } - LOGF(INFO, "First orbit: %d, Last orbit: %d", mOrbitMin, mOrbitMax); + LOGF(INFO, "First orbit: %u, Last orbit: %u", mOrbitMin, mOrbitMax); LOGF(INFO, "Largest super-page: %zu B, largest TF: %zu B", maxSP, maxTF); if (!mCheckErrors) { LOGF(INFO, "Detailed data format check was disabled"); @@ -865,6 +873,19 @@ RawFileReader::InputsMap RawFileReader::parseInput(const std::string& confUri) return entries; } +void RawFileReader::imposeFirstTF(uint32_t orbit, uint16_t bc) +{ + if (mFirstTFAutodetect != FirstTFDetection::Pending) { + throw std::runtime_error("reader was not expecting imposing first TF"); + } + auto& hbu = o2::raw::HBFUtils::Instance(); + o2::raw::HBFUtils::setValue("HBFUtils", "orbitFirst", orbit); + o2::raw::HBFUtils::setValue("HBFUtils", "bcFirst", bc); + LOG(INFO) << "Imposed data-driven TF start"; + mFirstTFAutodetect = FirstTFDetection::Done; + hbu.printKeyValues(); +} + std::string RawFileReader::nochk_opt(RawFileReader::ErrTypes e) { std::string opt = ErrCheckDefaults[e] ? "nocheck-" : "check-"; diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index f8ff628bf2412..a10f5fff61cf9 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -46,7 +46,7 @@ class RawReaderSpecs : public o2f::Task { public: explicit RawReaderSpecs(const std::string& config, int loop = 1, uint32_t delay_us = 0, - uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, bool cache = false, + uint32_t errmap = 0xffffffff, uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, bool cache = false, bool autodetectTF0 = false, size_t spSize = 1024L * 1024L, size_t buffSize = 5 * 1024UL, const std::string& rawChannelName = "") : mLoop(loop < 0 ? INT_MAX : (loop < 1 ? 1 : loop)), mDelayUSec(delay_us), mMinTFID(minTF), mMaxTFID(maxTF), mPartPerSP(partPerSP), mReader(std::make_unique<o2::raw::RawFileReader>(config, 0, buffSize)), mRawChannelName(rawChannelName) @@ -55,6 +55,7 @@ class RawReaderSpecs : public o2f::Task mReader->setMaxTFToRead(maxTF); mReader->setNominalSPageSize(spSize); mReader->setCacheData(cache); + mReader->setTFAutodetect(autodetectTF0 ? RawFileReader::FirstTFDetection::Pending : RawFileReader::FirstTFDetection::Disabled); LOG(INFO) << "Will preprocess files with buffer size of " << buffSize << " bytes"; LOG(INFO) << "Number of loops over whole data requested: " << mLoop; for (int i = NTimers; i--;) { @@ -246,7 +247,7 @@ class RawReaderSpecs : public o2f::Task }; o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t delay_us, uint32_t errmap, - uint32_t minTF, uint32_t maxTF, bool partPerSP, bool cache, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) + uint32_t minTF, uint32_t maxTF, bool partPerSP, bool cache, bool autodetectTF0, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) { // check which inputs are present in files to read o2f::DataProcessorSpec spec; @@ -277,15 +278,15 @@ o2f::DataProcessorSpec getReaderSpec(std::string config, int loop, uint32_t dela LOG(INFO) << "Will send output to non-DPL channel " << rawChannelConfig; } - spec.algorithm = o2f::adaptFromTask<RawReaderSpecs>(config, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, spSize, buffSize, rawChannelName); + spec.algorithm = o2f::adaptFromTask<RawReaderSpecs>(config, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, autodetectTF0, spSize, buffSize, rawChannelName); return spec; } o2f::WorkflowSpec o2::raw::getRawFileReaderWorkflow(std::string inifile, int loop, uint32_t delay_us, uint32_t errmap, uint32_t minTF, uint32_t maxTF, - bool partPerSP, bool cache, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) + bool partPerSP, bool cache, bool autodetectTF0, size_t spSize, size_t buffSize, const std::string& rawChannelConfig) { o2f::WorkflowSpec specs; - specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, spSize, buffSize, rawChannelConfig)); + specs.emplace_back(getReaderSpec(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, autodetectTF0, spSize, buffSize, rawChannelConfig)); return specs; } diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.h b/Detectors/Raw/src/RawFileReaderWorkflow.h index 731921eb46a5d..c209fd088f573 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.h +++ b/Detectors/Raw/src/RawFileReaderWorkflow.h @@ -22,7 +22,7 @@ namespace raw { framework::WorkflowSpec getRawFileReaderWorkflow(std::string inifile, int loop = 1, uint32_t delay_us = 0, uint32_t errMap = 0xffffffff, - uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, bool cache = false, + uint32_t minTF = 0, uint32_t maxTF = 0xffffffff, bool partPerSP = true, bool cache = false, bool autodetectTF0 = false, size_t spSize = 1024L * 1024L, size_t bufferSize = 1024L * 1024L, const std::string& rawChannelConfig = ""); diff --git a/Detectors/Raw/src/rawfile-reader-workflow.cxx b/Detectors/Raw/src/rawfile-reader-workflow.cxx index 5a752cfd07fd9..7f1062969e6b8 100644 --- a/Detectors/Raw/src/rawfile-reader-workflow.cxx +++ b/Detectors/Raw/src/rawfile-reader-workflow.cxx @@ -33,6 +33,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) options.push_back(ConfigParamSpec{"part-per-hbf", VariantType::Bool, false, {"FMQ parts per superpage (default) of HBF"}}); options.push_back(ConfigParamSpec{"raw-channel-config", VariantType::String, "", {"optional raw FMQ channel for non-DPL output"}}); options.push_back(ConfigParamSpec{"cache-data", VariantType::Bool, false, {"cache data at 1st reading, may require excessive memory!!!"}}); + options.push_back(ConfigParamSpec{"detect-tf0", VariantType::Bool, false, {"autodetect HBFUtils start Orbit/BC from 1st TF seen"}}); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}); // options for error-check suppression @@ -57,6 +58,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) uint64_t spSize = uint64_t(configcontext.options().get<int64_t>("super-page-size")); bool partPerSP = !configcontext.options().get<bool>("part-per-hbf"); bool cache = configcontext.options().get<bool>("cache-data"); + bool autodetectTF0 = configcontext.options().get<bool>("detect-tf0"); std::string rawChannelConfig = configcontext.options().get<std::string>("raw-channel-config"); uint32_t errmap = 0; for (int i = RawFileReader::NErrorsDefined; i--;) { @@ -69,5 +71,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); uint32_t delay_us = uint32_t(1e6 * configcontext.options().get<float>("delay")); // delay in microseconds - return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, spSize, buffSize, rawChannelConfig)); + return std::move(o2::raw::getRawFileReaderWorkflow(inifile, loop, delay_us, errmap, minTF, maxTF, partPerSP, cache, autodetectTF0, spSize, buffSize, rawChannelConfig)); } diff --git a/Detectors/Raw/src/rawfileCheck.cxx b/Detectors/Raw/src/rawfileCheck.cxx index 7f2400acec9c9..cb29425cc7250 100644 --- a/Detectors/Raw/src/rawfileCheck.cxx +++ b/Detectors/Raw/src/rawfileCheck.cxx @@ -39,6 +39,7 @@ int main(int argc, char* argv[]) desc_add_option("verbosity,v", bpo::value<int>()->default_value(reader.getVerbosity()), "1: long report, 2 or 3: print or dump all RDH"); desc_add_option("spsize,s", bpo::value<int>()->default_value(reader.getNominalSPageSize()), "nominal super-page size in bytes"); desc_add_option("buffer-size,b", bpo::value<size_t>()->default_value(reader.getNominalSPageSize()), "buffer size for files preprocessing"); + desc_add_option("detect-tf0", "autodetect HBFUtils start Orbit/BC from 1st TF seen"); desc_add_option("rorc", "impose RORC as default detector mode"); desc_add_option("configKeyValues", bpo::value(&configKeyValues)->default_value(""), "semicolon separated key=value strings"); for (int i = 0; i < RawFileReader::NErrorsDefined; i++) { @@ -84,13 +85,14 @@ int main(int argc, char* argv[]) RawFileReader::RDH rdh; LOG(INFO) << "RawDataHeader v" << int(rdh.version) << " is assumed"; - o2::raw::RawFileReader::ReadoutCardType rocard = vm.count("rorc") ? o2::raw::RawFileReader::ReadoutCardType::RORC : o2::raw::RawFileReader::ReadoutCardType::CRU; + RawFileReader::ReadoutCardType rocard = vm.count("rorc") ? o2::raw::RawFileReader::ReadoutCardType::RORC : o2::raw::RawFileReader::ReadoutCardType::CRU; reader.setVerbosity(vm["verbosity"].as<int>()); reader.setNominalSPageSize(vm["spsize"].as<int>()); reader.setMaxTFToRead(vm["max-tf"].as<uint32_t>()); reader.setBufferSize(vm["buffer-size"].as<size_t>()); reader.setDefaultReadoutCardType(rocard); + reader.setTFAutodetect(vm.count("detect-tf0") ? RawFileReader::FirstTFDetection::Pending : RawFileReader::FirstTFDetection::Disabled); uint32_t errmap = 0; for (int i = RawFileReader::NErrorsDefined; i--;) { auto ei = RawFileReader::ErrTypes(i); From bfa374b441b97d77fa610c217898bf506c7ee8c8 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Fri, 28 Aug 2020 16:37:24 +0200 Subject: [PATCH 0556/1751] Add more decay configurations in share --- .../share/pythia8/decays/force_hadronic_D.cfg | 96 +++++++++++++++++++ .../force_hadronic_D_forceLcChannel1.cfg | 12 +++ .../force_hadronic_D_forceLcChannel2.cfg | 12 +++ .../decays/force_hadronic_D_use4bodies.cfg | 15 +++ .../decays/force_hadronic_D_useDtoV0.cfg | 13 +++ .../share/pythia8/decays/hypertriton.cfg | 12 +++ 6 files changed, 160 insertions(+) create mode 100644 Generators/share/pythia8/decays/force_hadronic_D.cfg create mode 100644 Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel1.cfg create mode 100644 Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel2.cfg create mode 100644 Generators/share/pythia8/decays/force_hadronic_D_use4bodies.cfg create mode 100644 Generators/share/pythia8/decays/force_hadronic_D_useDtoV0.cfg create mode 100644 Generators/share/pythia8/decays/hypertriton.cfg 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 + From 329a1e9625b8d9083f443dd63a241f9cae72edcd Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Mon, 7 Sep 2020 10:44:54 +0200 Subject: [PATCH 0557/1751] Changed the workflow of the tableReader task (#4291) * optimizations to the DQ table-reader task * optimizations for the table-reader task * table reader task modified to use Partition for candidate track-leg selection * Added a task for dilepton - hadron combinations in the tableReader workflow --- Analysis/Core/include/Analysis/VarManager.h | 60 +- Analysis/Core/src/VarManager.cxx | 12 +- .../include/Analysis/ReducedInfoTables.h | 4 +- Analysis/Tasks/PWGDQ/tableReader.cxx | 601 ++++++++++++------ 4 files changed, 483 insertions(+), 194 deletions(-) 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 <TObject.h> #include <TString.h> +#include <Math/Vector4D.h> +#include <TMath.h> #include <vector> #include <map> @@ -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 <typename T> static void FillPair(T const& t1, T const& t2, float* values = nullptr); + template <typename T1, typename T2> + 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 <typename T1, typename T2> +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/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/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 5d78f05e48b7a..77015e807bbf9 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); }); @@ -113,7 +113,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/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 <THashList.h> #include <TString.h> #include <iostream> -#include <vector> -#include <typeinfo> 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::Pt, reducedpair::Phi>, reducedpair::Py<reducedpair::Pt, reducedpair::Phi>, + reducedpair::Pz<reducedpair::Pt, reducedpair::Eta>, reducedpair::Pmom<reducedpair::Pt, reducedpair::Eta>); +using Dilepton = Dileptons::iterator; +} // namespace o2::aod + +using MyEvent = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended>::iterator; +using MyEventVtxCov = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator; +using MyBarrelTracks = soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID>; +using MyBarrelTracksSelected = soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID, aod::BarrelTrackCuts>; +using MyMuonTracks = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended>; +using MyMuonTracksSelected = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended, aod::MuonTrackCuts>; + +void DefineHistograms(o2::framework::OutputObj<HistogramManager> 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<aod::BarrelTrackCuts> trackSel; OutputObj<HistogramManager> 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<fgEventFillMap>(event, fValues); + + for (auto& track : tracks) { + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValues[i] = -9999.0f; + VarManager::FillTrack<fgTrackFillMap>(track, fValues); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + + if (fTrackCut->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); + } else + trackSel(0); + } + } +}; + +struct MuonTrackSelection { + Produces<aod::MuonTrackCuts> trackSel; + OutputObj<HistogramManager> 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<fgEventFillMap>(event, fValues); + + for (auto& muon : muons) { + for (int i = VarManager::kNBarrelTrackVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValues[i] = -9999.0f; + VarManager::FillTrack<fgMuonFillMap>(muon, fValues); + fHistMan->FillHistClass("TrackMuon_BeforeCuts", fValues); + + if (fTrackCut->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); + } else + trackSel(0); + } + } +}; + +struct TableReader { + Produces<aod::Dileptons> dileptonList; + OutputObj<HistogramManager> fHistMan{"output"}; + AnalysisCompositeCut* fEventCut; + //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition + + Partition<MyBarrelTracksSelected> posTracks = aod::reducedtrack::charge > 0 && aod::reducedtrack::isBarrelSelected == 1; + Partition<MyBarrelTracksSelected> negTracks = aod::reducedtrack::charge < 0 && aod::reducedtrack::isBarrelSelected == 1; + Partition<MyMuonTracksSelected> posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; + Partition<MyMuonTracksSelected> 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<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator event, - soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID> const& tracks, - soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended> 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<fgEventFillMap>(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<std::decay_t<decltype(tracks)>::iterator> selectedTracksPos; - std::vector<std::decay_t<decltype(tracks)>::iterator> selectedTracksNeg; - for (auto& track : tracks) { - - VarManager::ResetValues(VarManager::kNEventWiseVariables, VarManager::kNMuonTrackVariables); - - VarManager::FillTrack<fgTrackFillMap>(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<std::decay_t<decltype(muons)>::iterator> selectedMuonsPos; - std::vector<std::decay_t<decltype(muons)>::iterator> selectedMuonsNeg; - for (auto& muon : muons) { - VarManager::FillTrack<fgMuonFillMap>(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<HistogramManager> 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<aod::Dileptons> 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<fgEventFillMap>(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<fgDileptonFillMap>(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<fgTrackFillMap>(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<TableReader>("table-reader")}; + adaptAnalysisTask<BarrelTrackSelection>("barrel-track-selection"), + adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), + adaptAnalysisTask<TableReader>("table-reader"), + adaptAnalysisTask<DileptonHadronAnalysis>("dilepton-hadron")}; +} + +void DefineHistograms(o2::framework::OutputObj<HistogramManager> 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 } From 5c38e3e971d95a1e05300fa118ab0cabad3e91bf Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 7 Sep 2020 12:11:57 +0200 Subject: [PATCH 0558/1751] DPL Analysis: redefine extended tables as Join (#4283) --- Analysis/DataModel/src/dumpDataModel.cxx | 8 +- Framework/Core/include/Framework/ASoA.h | 100 +++++++++------- .../Core/include/Framework/AnalysisHelpers.h | 88 ++++++++++---- .../Core/include/Framework/AnalysisTask.h | 1 - .../Core/include/Framework/TableBuilder.h | 10 +- Framework/Core/src/AODReaderHelpers.cxx | 8 +- Framework/Core/src/AnalysisManagers.h | 6 +- Framework/Core/src/WorkflowHelpers.cxx | 8 +- Framework/Core/src/verifyAODFile.cxx | 10 +- Framework/Core/test/benchmark_ASoA.cxx | 107 ++---------------- Framework/Core/test/benchmark_ASoAHelpers.cxx | 52 ++++----- .../Core/test/test_AnalysisDataModel.cxx | 39 ++++--- Framework/Core/test/test_AnalysisTask.cxx | 31 ++--- Framework/Core/test/test_Expressions.cxx | 1 + Framework/Core/test/test_SimpleTracksED.cxx | 10 +- Framework/Foundation/include/Framework/Pack.h | 39 +++++++ .../test/test_FunctionalHelpers.cxx | 6 + .../src/o2SimpleTracksAnalysis.cxx | 20 ++-- 18 files changed, 283 insertions(+), 261 deletions(-) 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<Ts>(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<Tracks, TracksCov, TracksExtra, TracksExtended, TrackSelection>(); + /// FIXME: topology should account for predefined Joins + dumpCluster<StoredTracks, TracksExtension, StoredTracksCov, TracksCovExtension, TracksExtra, TracksExtended, TrackSelection>(); dumpTable<Collisions>(); dumpTable<Calos>(); dumpTable<CaloTriggers>(); - dumpTable<Muons>(); - dumpTable<StoredMuons>(); + dumpCluster<StoredMuons, MuonsExtension>(); dumpTable<MuonClusters>(); dumpTable<Zdcs>(); dumpTable<Run2V0s>(); diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 8072b53168f42..d4d503fac778e 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1032,16 +1032,10 @@ struct PackToTable<framework::pack<C...>> { using table = o2::soa::Table<C...>; }; -template <typename T> -struct FilterPersistentColumns { - static_assert(framework::always_static_assert_v<T>, "Not a soa::Table"); -}; - -template <typename... C> -struct FilterPersistentColumns<soa::Table<C...>> { - using columns = typename soa::Table<C...>::columns; - using persistent_columns_pack = framework::selected_pack<is_persistent_t, C...>; - using persistent_table_t = typename PackToTable<persistent_columns_pack>::table; +template <typename... T> +struct TableWrap { + using all_columns = framework::concatenated_pack_unique_t<typename T::columns...>; + using table_t = typename PackToTable<all_columns>::table; }; /// Template trait which allows to map a given @@ -1056,11 +1050,47 @@ class TableMetadata }; template <typename... C1, typename... C2> -constexpr auto join(o2::soa::Table<C1...> const& t1, o2::soa::Table<C2...> const& t2) +constexpr auto joinTables(o2::soa::Table<C1...> const& t1, o2::soa::Table<C2...> const& t2) { return o2::soa::Table<C1..., C2...>(ArrowHelpers::joinTables({t1.asArrowTable(), t2.asArrowTable()})); } +template <typename T, typename... C, typename... O> +constexpr auto joinLeft(T const& t1, o2::soa::Table<C...> const& t2, framework::pack<O...>) +{ + return typename o2::soa::TableWrap<O..., o2::soa::Table<C...>>::table_t(ArrowHelpers::joinTables({t1.asArrowTable(), t2.asArrowTable()})); +} + +template <typename T, typename... C, typename... O> +constexpr auto joinRight(o2::soa::Table<C...> const& t1, T const& t2, framework::pack<O...>) +{ + return typename o2::soa::TableWrap<o2::soa::Table<C...>, O...>::table_t(ArrowHelpers::joinTables({t1.asArrowTable(), t2.asArrowTable()})); +} + +template <typename T1, typename T2, typename... O1, typename... O2> +constexpr auto joinBoth(T1 const& t1, T2 const& t2, framework::pack<O1...>, framework::pack<O2...>) +{ + return typename o2::soa::TableWrap<O1..., O2...>::table_t(ArrowHelpers::joinTables({t1.asArrowTable(), t2.asArrowTable()})); +} + +template <typename T1, typename T2> +constexpr auto join(T1 const& t1, T2 const& t2) +{ + if constexpr (soa::is_type_with_originals_v<T1>) { + if constexpr (soa::is_type_with_originals_v<T2>) { + return joinBoth(t1, t2, typename T1::originals{}, typename T2::originals{}); + } else { + return joinLeft(t1, t2, typename T1::originals{}); + } + } else { + if constexpr (soa::is_type_with_originals_v<T2>) { + return joinRight(t1, t2, typename T2::originals{}); + } else { + return joinTables(t1, t2); + } + } +} + template <typename T1, typename T2, typename... Ts> constexpr auto join(T1 const& t1, T2 const& t2, Ts const&... ts) { @@ -1306,27 +1336,23 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); #define DECLARE_SOA_TABLE(_Name_, _Origin_, _Description_, ...) \ DECLARE_SOA_TABLE_FULL(_Name_, #_Name_, _Origin_, _Description_, __VA_ARGS__); -#define DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, _Origin_, _Description_, ...) \ - using _Name_ = o2::soa::JoinBase<typename _Table_::table_t, o2::soa::Table<__VA_ARGS__>>; \ - \ - struct _Name_##Metadata : o2::soa::TableMetadata<_Name_##Metadata> { \ - using table_t = _Name_; \ - using base_table_t = _Table_; \ - using expression_pack_t = framework::pack<__VA_ARGS__>; \ - using originals = soa::originals_pack_t<_Table_>; \ - static constexpr char const* mLabel = #_Name_; \ - static constexpr char const mOrigin[4] = _Origin_; \ - static constexpr char const mDescription[16] = _Description_; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_> { \ - using metadata = _Name_##Metadata; \ - }; \ - \ - template <> \ - struct MetadataTrait<_Name_::unfiltered_iterator> { \ - using metadata = _Name_##Metadata; \ +#define DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, _Origin_, _Description_, ...) \ + using _Name_##Extension = o2::soa::Table<__VA_ARGS__>; \ + using _Name_ = o2::soa::Join<_Name_##Extension, _Table_>; \ + \ + struct _Name_##ExtensionMetadata : o2::soa::TableMetadata<_Name_##ExtensionMetadata> { \ + using table_t = _Name_##Extension; \ + using base_table_t = typename _Table_::table_t; \ + using expression_pack_t = framework::pack<__VA_ARGS__>; \ + using originals = soa::originals_pack_t<_Table_>; \ + static constexpr char const* mLabel = #_Name_ "Extension"; \ + static constexpr char const mOrigin[4] = _Origin_; \ + static constexpr char const mDescription[16] = _Description_; \ + }; \ + \ + template <> \ + struct MetadataTrait<_Name_##Extension> { \ + using metadata = _Name_##ExtensionMetadata; \ }; #define DECLARE_SOA_EXTENDED_TABLE(_Name_, _Table_, _Description_, ...) \ @@ -1745,16 +1771,12 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) arrays[i] = std::make_shared<arrow::ChunkedArray>(chunks[i]); } - auto extra_schema = o2::soa::createSchemaFromColumns(columns); - auto original_fields = atable->schema()->fields(); - auto original_columns = atable->columns(); - std::vector<std::shared_ptr<arrow::Field>> new_fields(original_fields); - std::vector<std::shared_ptr<arrow::ChunkedArray>> new_columns(original_columns); + auto new_schema = o2::soa::createSchemaFromColumns(columns); + std::vector<std::shared_ptr<arrow::ChunkedArray>> new_columns; for (auto i = 0u; i < sizeof...(C); ++i) { - new_fields.emplace_back(extra_schema->field(i)); new_columns.push_back(arrays[i]); } - return arrow::Table::Make(std::make_shared<arrow::Schema>(new_fields), new_columns); + return arrow::Table::Make(new_schema, new_columns); } /// On-the-fly adding of expression columns diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 0749cd0dcc2f6..457c3d5b139c0 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -97,7 +97,7 @@ struct Produces { /// means of the WritingCursor helper class, from which produces actually /// derives. template <typename... C> -struct Produces<soa::Table<C...>> : WritingCursor<typename soa::FilterPersistentColumns<soa::Table<C...>>::persistent_table_t> { +struct Produces<soa::Table<C...>> : WritingCursor<typename soa::PackToTable<typename soa::Table<C...>::persistent_columns_t>::table> { using table_t = soa::Table<C...>; using metadata = typename aod::MetadataTrait<table_t>::metadata; @@ -113,12 +113,19 @@ struct Produces<soa::Table<C...>> : WritingCursor<typename soa::FilterPersistent } }; -/// Base template for table transformation declarations +/// This helper struct allows you to declare extended tables which should be +/// created by the task (as opposed to those pre-defined by data model) template <typename T> -struct TransformTable { - using metadata = typename aod::MetadataTrait<T>::metadata; - using originals = typename metadata::originals; +struct Spawns { + using extension_t = framework::pack_head_t<typename T::originals>; + using metadata = typename aod::MetadataTrait<extension_t>::metadata; + using sources = typename metadata::originals; + using expression_pack_t = typename metadata::expression_pack_t; + constexpr auto pack() + { + return expression_pack_t{}; + } template <typename O> InputSpec const base_spec() { @@ -137,7 +144,7 @@ struct TransformTable { std::vector<InputSpec> const base_specs() { - return base_specs_impl(originals{}); + return base_specs_impl(sources{}); } OutputSpec const spec() const @@ -161,23 +168,10 @@ struct TransformTable { auto asArrowTable() { - return table->asArrowTable(); - } - std::shared_ptr<T> table = nullptr; -}; - -/// This helper struct allows you to declare extended tables which should be -/// created by the task (as opposed to those pre-defined by data model) -template <typename T> -struct Spawns : TransformTable<T> { - using metadata = typename TransformTable<T>::metadata; - using originals = typename metadata::originals; - using expression_pack_t = typename metadata::expression_pack_t; - - constexpr auto pack() - { - return expression_pack_t{}; + return extension->asArrowTable(); } + std::shared_ptr<typename T::table_t> table = nullptr; + std::shared_ptr<extension_t> extension = nullptr; }; /// Policy to control index building @@ -305,14 +299,60 @@ struct IndexSparse { /// This helper struct allows you to declare index tables to be created in a task template <typename T, typename IP = IndexSparse> -struct Builds : TransformTable<T> { - using metadata = typename TransformTable<T>::metadata; +struct Builds { + using metadata = typename aod::MetadataTrait<T>::metadata; using originals = typename metadata::originals; using Key = typename T::indexing_t; using H = typename T::first_t; using Ts = typename T::rest_t; using index_pack_t = typename metadata::index_pack_t; + template <typename O> + InputSpec const base_spec() + { + using o_metadata = typename aod::MetadataTrait<O>::metadata; + return InputSpec{ + o_metadata::tableLabel(), + header::DataOrigin{o_metadata::origin()}, + header::DataDescription{o_metadata::description()}}; + } + + template <typename... Os> + std::vector<InputSpec> const base_specs_impl(framework::pack<Os...>) + { + return {base_spec<Os>()...}; + } + + std::vector<InputSpec> const base_specs() + { + return base_specs_impl(originals{}); + } + + OutputSpec const spec() const + { + return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; + } + + OutputRef ref() const + { + return OutputRef{metadata::tableLabel(), 0}; + } + + T* operator->() + { + return table.get(); + } + T& operator*() + { + return *table.get(); + } + + auto asArrowTable() + { + return table->asArrowTable(); + } + std::shared_ptr<T> table = nullptr; + constexpr auto pack() { return index_pack_t{}; diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 426a7f56a4483..9c83d8ee38763 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -45,7 +45,6 @@ namespace o2::framework // FIXME: for the moment this needs to stay outside AnalysisTask // because we cannot inherit from it due to a C++17 bug // in GCC 7.3. We need to move to 7.4+ - struct AnalysisTask { }; 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 <typename T> auto cursor() { - using persistent_filter = soa::FilterPersistentColumns<T>; - 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<typename persistent_filter::persistent_table_t>(std::make_index_sequence<persistent_size>()); + return cursorHelper<typename soa::PackToTable<persistent_columns_pack>::table>(std::make_index_sequence<persistent_size>()); } template <typename T, typename E> auto cursor() { - using persistent_filter = soa::FilterPersistentColumns<T>; - 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<typename persistent_filter::persistent_table_t, E>(std::make_index_sequence<persistent_size>()); + return cursorHelper<typename soa::PackToTable<persistent_columns_pack>::table, E>(std::make_index_sequence<persistent_size>()); } template <typename... ARGS> diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index ca839bb14cdfa..2a614f356a6d5 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -116,7 +116,7 @@ uint64_t getMask(header::DataDescription description) } } -uint64_t calculateReadMask(std::vector<OutputRoute> const& routes, header::DataOrigin const& origin) +uint64_t calculateReadMask(std::vector<OutputRoute> const& routes, header::DataOrigin const&) { uint64_t readMask = None; for (auto& route : routes) { @@ -176,11 +176,11 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> 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..d40e8aebce8bd 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -233,9 +233,9 @@ struct OutputManager<Spawns<T>> { static bool prepare(ProcessingContext& pc, Spawns<T>& what) { - using metadata = typename std::decay_t<decltype(what)>::metadata; - auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(typename metadata::originals{}, pc)); - what.table = std::make_shared<T>(o2::soa::spawner(what.pack(), original_table.get())); + auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(typename Spawns<T>::sources{}, pc)); + what.extension = std::make_shared<typename Spawns<T>::extension_t>(o2::soa::spawner(what.pack(), original_table.get())); + what.table = std::make_shared<typename T::table_t>(soa::ArrowHelpers::joinTables({what.extension->asArrowTable(), original_table})); return true; } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 275f4746cac23..9ffaaf1af00b3 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -335,7 +335,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 +356,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select outputs of type AOD std::vector<InputSpec> OutputsInputsAOD; std::vector<bool> 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 +379,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select dangling outputs which are not of type AOD std::vector<InputSpec> 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 +783,7 @@ std::vector<InputSpec> WorkflowHelpers::computeDanglingOutputs(WorkflowSpec cons auto [OutputsInputs, outputtypes] = analyzeOutputs(workflow); std::vector<InputSpec> 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/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<o2::aod::Collisions>(infile.get(), "O2collisions"); - verifyTable<o2::aod::Tracks>(infile.get(), "O2tracks"); - verifyTable<o2::aod::TracksCov>(infile.get(), "O2tracks"); - verifyTable<o2::aod::TracksExtra>(infile.get(), "O2tracks"); + verifyTable<o2::aod::Collisions>(infile.get(), "O2collision"); + verifyTable<o2::aod::StoredTracks>(infile.get(), "O2track"); + verifyTable<o2::aod::StoredTracksCov>(infile.get(), "O2track"); + verifyTable<o2::aod::TracksExtra>(infile.get(), "O2track"); verifyTable<o2::aod::Calos>(infile.get(), "O2calo"); - verifyTable<o2::aod::Muons>(infile.get(), "O2muon"); + verifyTable<o2::aod::StoredMuons>(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<test::X, test::Y>); + #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<float> 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<float> 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<float> 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<float> 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<float> 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<float> uniform_dist(0, 1); - - TableBuilder builder; - auto rowWriter = builder.cursor<o2::aod::StoredTracks>(); - 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<float> 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<float> uniform_dist(0, 1); - - TableBuilder builder; - auto rowWriter = builder.cursor<o2::aod::StoredTracks>(); - 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<float> uniform_dist(0, 1); - - TableBuilder builder; - auto rowWriter = builder.cursor<o2::aod::StoredTracks>(); - 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<float> 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<float> uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor<o2::aod::StoredTracks>(); + auto rowWriter = builder.cursor<o2::aod::Calos>(); 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<float> uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor<o2::aod::StoredTracks>(); + auto rowWriter = builder.cursor<o2::aod::Calos>(); 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<float> uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor<o2::aod::StoredTracks>(); + auto rowWriter = builder.cursor<o2::aod::Calos>(); 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<float> uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor<o2::aod::StoredTracks>(); + auto rowWriter = builder.cursor<o2::aod::Calos>(); 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<float> uniform_dist(0, 1); TableBuilder builderA; - auto rowWriterA = builderA.cursor<o2::aod::StoredTracks>(); + auto rowWriterA = builderA.cursor<o2::aod::Calos>(); 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<o2::aod::StoredTracks>(); + auto rowWriterB = builderB.cursor<o2::aod::Calos>(); 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<o2::aod::Tracks, o2::aod::Tracks>; + using ConcatTest = Concat<o2::aod::Calos, o2::aod::Calos>; - 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/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<Tracks>(); - trackWriter(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - auto tracks = trackBuilder.finalize(); + auto xyWriter = XYBuilder.cursor<XY>(); + xyWriter(0, 0, 0); + auto tXY = XYBuilder.finalize(); - TableBuilder trackParCovBuilder; - auto trackParCovWriter = trackParCovBuilder.cursor<StoredTracksCov>(); - 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<ZD>(); + zdWriter(0, 7, 1); + auto tZD = ZDBuilder.finalize(); - using Test = Join<Tracks, StoredTracksCov>; + using Test = o2::soa::Join<XY, ZD>; - 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<Test::table_t, decltype(tests2)>, "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<ATask>("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<BTask>("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<CTask>("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<DTask>("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<ETask>("test5"); BOOST_CHECK_EQUAL(task5.inputs.size(), 1); 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_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<TableConsumer>("tracks"); + auto input = inputs.get<TableConsumer>("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/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index 983a256b6e7b9..b8b5f4806a2a0 100644 --- a/Framework/Foundation/include/Framework/Pack.h +++ b/Framework/Foundation/include/Framework/Pack.h @@ -48,6 +48,15 @@ struct pack_element<0, pack<Head, Tail...>> { template <std::size_t I, typename T> using pack_element_t = typename pack_element<I, T>::type; +template <typename T> +using pack_head_t = typename pack_element<0, T>::type; + +template <typename Head, typename... Tail> +constexpr auto pack_tail(pack<Head, Tail...>) +{ + return pack<Tail...>{}; +} + /// Templates for manipulating type lists in pack /// (see https://codereview.stackexchange.com/questions/201209/filter-template-meta-function/201222#201222) /// Example of use: @@ -161,6 +170,36 @@ struct intersect_pack { template <typename S1, typename S2> using intersected_pack_t = typename intersect_pack<S1, S2>::type; +/// Subtract two packs +template <typename S1, typename S2> +struct subtract_pack { + template <std::size_t... Indices> + static constexpr auto make_subtraction(std::index_sequence<Indices...>) + { + return filtered_pack<std::is_void, + std::conditional_t< + !has_type_v<pack_element_t<Indices, S1>, S2>, + pack_element_t<Indices, S1>, void>...>{}; + } + using type = decltype(make_subtraction(std::make_index_sequence<pack_size(S1{})>{})); +}; + +template <typename... Args1, typename... Args2> +constexpr auto concatenate_pack_unique(pack<Args1...>, pack<Args2...>) +{ + using p1 = typename subtract_pack<pack<Args1...>, pack<Args2...>>::type; + return concatenate_pack(p1{}, pack<Args2...>{}); +} + +template <typename P1, typename P2, typename... Ps> +constexpr auto concatenate_pack_unique(P1 p1, P2 p2, Ps... ps) +{ + return concatenate_pack_unique(p1, concatenate_pack_unique(p2, ps...)); +} + +template <typename... Ps> +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<concatenated_pack_t<pack<int, float, char>, pack<float, double>>, pack<int, float, char, float, double>>, "pack should be concatenated"); static_assert(std::is_same_v<concatenated_pack_t<pack<int, float, char>, pack<float, double>, pack<char, short>>, pack<int, float, char, float, double, char, short>>, "pack should be concatenated"); + using p1 = pack<int, float, bool>; + using p2 = pack<int, double, char>; + using p3 = concatenated_pack_unique_t<p1, p2>; + print_pack<p3>(); + static_assert(std::is_same_v<p3, pack<float, bool, int, double, char>>, "pack should not have duplicated types"); + struct ForwardDeclared; static_assert(is_type_complete_v<ForwardDeclared> == false, "This should not be complete because the struct is simply forward declared."); diff --git a/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx b/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx index eaa6eb2d081aa..f19c808aa221b 100644 --- a/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx +++ b/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx @@ -20,9 +20,7 @@ using namespace ROOT::RDF; using namespace o2; using namespace o2::framework; -namespace o2 -{ -namespace aod +namespace o2::aod { namespace tracks { @@ -31,9 +29,7 @@ DECLARE_SOA_COLUMN(Phi, phi, float); } // namespace tracks using TracksDerived = o2::soa::Table<tracks::Eta, tracks::Phi>; - -} // namespace aod -} // namespace o2 +} // namespace o2::aod // A dummy workflow which creates a few of the tables proposed by Ruben, // using ARROW @@ -57,8 +53,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 +64,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<TableConsumer>("tracks"); + auto input1 = inputs.get<TableConsumer>("Tracks"); + auto input2 = inputs.get<TableConsumer>("TracksExtension"); /// Get a table builder to build the results auto& etaPhiBuilder = outputs.make<TableBuilder>(Output{"AOD", "TRACKDERIVED"}); auto etaPhiWriter = etaPhiBuilder.cursor<o2::aod::TracksDerived>(); - /// 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; From e0cff40c286ac38dda54ff89f1630d8cb2a0e0ae Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 7 Sep 2020 12:36:32 +0200 Subject: [PATCH 0559/1751] configurable cuts (#4284) --- Analysis/Tasks/correlations.cxx | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) 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<soa::Join<aod::Tracks, aod::TrackSelection>>; - - // Output definitions - OutputObj<CorrelationContainer> same{"sameEvent"}; - OutputObj<CorrelationContainer> mixed{"mixedEvent"}; - //OutputObj<TDirectory> 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<soa::Join<aod::Tracks, aod::TrackSelection>>; + + // Output definitions + OutputObj<CorrelationContainer> same{"sameEvent"}; + OutputObj<CorrelationContainer> mixed{"mixedEvent"}; + //OutputObj<TDirectory> qaOutput{"qa"}; + enum PairCuts { Photon = 0, K0, Lambda, From 86122ef3f32be97bcb8e0835a7443b3806095286 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Tue, 1 Sep 2020 08:35:54 +0200 Subject: [PATCH 0560/1751] replace halfchamber id with struct of supermodule, stack, layer,side --- .../TRD/include/DataFormatsTRD/LinkRecord.h | 45 +++++++++++++++---- .../TRD/include/DataFormatsTRD/RawData.h | 23 ++++++---- DataFormats/Detectors/TRD/src/LinkRecord.cxx | 36 +++++++++++++-- DataFormats/Detectors/TRD/src/RawData.cxx | 30 +++++++++++-- Detectors/TRD/simulation/src/Trap2CRU.cxx | 20 ++++----- .../TRDWorkflow/TRDTrapSimulatorSpec.h | 3 +- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 21 +++++---- 7 files changed, 132 insertions(+), 46 deletions(-) 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 <iostream> #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 <iostream> #include <iomanip> #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/Detectors/TRD/simulation/src/Trap2CRU.cxx b/Detectors/TRD/simulation/src/Trap2CRU.cxx index 688bb2cb0881e..c1279c29395af 100644 --- a/Detectors/TRD/simulation/src/Trap2CRU.cxx +++ b/Detectors/TRD/simulation/src/Trap2CRU.cxx @@ -173,10 +173,10 @@ uint32_t Trap2CRU::buildCRUHeader(HalfCRUHeader& header, uint32_t bc, uint32_t h int linkrecord = startlinkrecord; int totallinkdatasize = 0; //in units of 256bits for (int link = 0; link < NLinksPerHalfCRU; link++) { - int hcid = link + halfcru * NLinksPerHalfCRU; // TODO this might have to change to a lut I dont think the mapping is linear. + int linkid = link + halfcru * NLinksPerHalfCRU; // TODO this might have to change to a lut I dont think the mapping is linear. int errors = 0; int linksize = 0; // linkSizePadding will convert it to 1 for the no data case. - if (mLinkRecords[linkrecord].getLinkHCID() == hcid) { + if (mLinkRecords[linkrecord].getLinkId() == linkid) { linksize = mLinkRecords[linkrecord].getNumberOfObjects(); // this can be done differently by keeping a pointer to halfcruheader and setting it after reading it all in and going back per link to set the size. LOG(debug3) << "setting CRU HEADER for halfcru : " << halfcru << "and link : " << link << " contents" << header << ":" << link << ":" << linksize << ":" << errors; @@ -234,26 +234,26 @@ void Trap2CRU::convertTrapData(o2::trd::TriggerRecord const& TrigRecord) int linkdatasize = 0; // in 32 bit words int link = halfcru / 2; for (int halfcrulink = 0; halfcrulink < NLinksPerHalfCRU; halfcrulink++) { - //links run from 0 to 14, so hcid offset is halfcru*15; - int hcid = halfcrulink + halfcru * NLinksPerHalfCRU; - LOG(debug) << "Currently checking for data on hcid : " << hcid << " from halfcru=" << halfcru << " and halfcrulink:" << halfcrulink << " ?? " << hcid << "==" << mLinkRecords[currentlinkrecord].getLinkHCID(); + //links run from 0 to 14, so linkid offset is halfcru*15; + int linkid = halfcrulink + halfcru * NLinksPerHalfCRU; + LOG(debug) << "Currently checking for data on linkid : " << linkid << " from halfcru=" << halfcru << " and halfcrulink:" << halfcrulink << " ?? " << linkid << "==" << mLinkRecords[currentlinkrecord].getLinkId(); int errors = 0; // put no errors in for now. int size = 0; // in 32 bit words int datastart = 0; // in 32 bit words int dataend = 0; // in 32 bit words uint32_t paddingsize = 0; // in 32 bit words uint32_t crudatasize = 0; // in 256 bit words. - if (mLinkRecords[currentlinkrecord].getLinkHCID() == hcid) { + if (mLinkRecords[currentlinkrecord].getLinkId() == linkid) { //this link has data in the stream. - LOG(debug) << "+++ We have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; + LOG(debug) << "+++ We have data on linkid = " << linkid << " halfcrulink : " << halfcrulink; linkdatasize = mLinkRecords[currentlinkrecord].getNumberOfObjects(); datastart = mLinkRecords[currentlinkrecord].getFirstEntry(); dataend = datastart + size; - LOG(debug) << "We have data on hcid = " << hcid << " and linksize : " << linkdatasize << " so :" << linkdatasize / 8 << " 256 bit words"; + LOG(debug) << "We have data on linkid = " << linkid << " and linksize : " << linkdatasize << " so :" << linkdatasize / 8 << " 256 bit words"; currentlinkrecord++; } else { - assert(mLinkRecords[currentlinkrecord].getLinkId() < hcid); - LOG(debug) << "---We do not have data on hcid = " << hcid << " halfcrulink : " << halfcrulink; + assert(mLinkRecords[currentlinkrecord].getLinkId() < linkid); + LOG(debug) << "---We do not have data on linkid = " << linkid << " halfcrulink : " << halfcrulink; //blank data for this link // put in a 1 256 bit word of data for the link and padd with 0xeeee x 8 linkdatasize = 0; diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h index a69092e7c64bb..a1aa8b1f443a1 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h @@ -86,13 +86,12 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task std::chrono::duration<double> mSortingTime{0}; ///< full timer uint64_t mTotalRawWordsWritten = 0; // words written for the raw format of 4x32bits, where 4 can be 2 to 4 depending on # of tracklets in the block. - int32_t mOldHalfChamberID = 0; + int32_t mOldHalfChamberLinkId = 0; bool mNewTrackletHCHeaderHasBeenWritten{false}; TrackletHCHeader mTrackletHCHeader; // the current half chamber header, that will be written if a first tracklet is found for this halfchamber. TrapConfig* getTrapConfig(); void loadTrapConfig(); void setOnlineGainTables(); - uint32_t getHalfChamberID(uint32_t detector, uint32_t rob) { return detector * 2 + rob % 2; }; }; o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec(); diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index a4bcbd2803a25..46d4cd760a2a8 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -456,7 +456,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) << digit.getDetector() << ":" << digit.getRow() << ":" << digit.getPad() << ":" << mFeeParam->getROBfromPad(digit.getRow(), digit.getPad()) << ":" << mFeeParam->getMCMfromPad(digit.getRow(), digit.getPad()) - << " HCID:" << getHalfChamberID(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << "\t\t SM:stack:layer:side " + << " LinkId:" << LinkRecord::getHalfChamberLinkId(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << "\t\t SM:stack:layer:side " << digit.getDetector() / 30 << ":" << TRDGeometry::getStack(digit.getDetector()) << ":" << TRDGeometry::getLayer(digit.getDetector()) << ":" << FeeParam::instance()->getRobSide(mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << " with ORI# : " << mFeeParam->getORI(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) @@ -473,7 +473,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) double trackletrate; unsigned long oldtrackletcount = 0; mTotalRawWordsWritten = 0; // words written for the raw format of 4x32bits, where 4 can be 2 to 4 depending on # of tracklets in the block. - mOldHalfChamberID = 0; + mOldHalfChamberLinkId = 0; mNewTrackletHCHeaderHasBeenWritten = false; // now to loop over the incoming digits. @@ -495,9 +495,10 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) int trdstack = TRDGeometry::getStack(detector); int trdlayer = TRDGeometry::getLayer(detector); int fibreside = FeeParam::instance()->getRobSide(rob); + LOG(debug) << "calculated rob and mcm at top of loop with detector:row:pad:rob:mcm ::" << detector << ":" << row << ":" << pad << ":" << rob << ":" << mcm - << " HCID:" << getHalfChamberID(detector, rob) << "\t\t SM:stack:layer:side " << detector / 30 << ":" << trdstack << ":" << trdlayer << ":" << fibreside + << " LinkId:" << LinkRecord::getHalfChamberLinkId(detector, rob) << "\t\t SM:stack:layer:side " << detector / 30 << ":" << trdstack << ":" << trdlayer << ":" << fibreside << " with ORI : " << mFeeParam->getORI(detector, rob) << " and within supermodule ori index:" << mFeeParam->getORIinSM(detector, rob); LOG(debug) << "digit time : " << digittime; if (row == 4 && pad == 17 && rob == 2 & mcm == 0) { @@ -509,14 +510,12 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) olddetector = detector; } //Are we on a new half chamber ? - if (mOldHalfChamberID != getHalfChamberID(detector, rob)) { + if (mOldHalfChamberLinkId != LinkRecord::getHalfChamberLinkId(detector, rob)) { // hcid= detector*2 + robpos%2; // new half chamber so add the header to the raw data stream. - mTrackletHCHeader.HCID = getHalfChamberID(detector, rob); - mTrackletHCHeader.one = 1; - mTrackletHCHeader.MCLK = currentTriggerRecord * 42; // 42 because its the universally true answer, this is fake in anycase, so long as its always bigger than the previous one and increasing. - mTrackletHCHeader.format = 4; - mOldHalfChamberID = getHalfChamberID(detector, rob); + buildTrackletHCHeaderd(mTrackletHCHeader, detector, rob, currentTriggerRecord * 42, 4); + //buildTrackletHCHeader(mTrackletHCHeader,sector,stack,layer,side,currentTriggerRecord*42,4); + mOldHalfChamberLinkId = LinkRecord::getHalfChamberLinkId(detector, rob); // now we have a problem. We must only write the halfchamberheader if a tracklet is written i.e. if the digits for this half chamber actually produce 1 or more tracklets! mNewTrackletHCHeaderHasBeenWritten = false; } @@ -557,10 +556,10 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // .. fix the previous linkrecord to note its end of range. if (mLinkRecords.size() == 0) { // special case for the first entry into the linkrecords vector. mLinkRecords.emplace_back(mTrackletHCHeader.word, 0, -1); - LOG(debug) << " added HCID :[record.size==0] " << mTrackletHCHeader.HCID << " with number of bytes : " << mTotalRawWordsWritten << "-" << mLinkRecords.back().getFirstEntry(); + // LOG(debug) << " added HCID :[record.size==0] " << mTrackletHCHeader.HCID << " with number of bytes : " << mTotalRawWordsWritten << "-" << mLinkRecords.back().getFirstEntry(); } else { mLinkRecords.back().setNumberOfObjects(mTotalRawWordsWritten - mLinkRecords.back().getFirstEntry()); // current number of words written - the start of this index record. - LOG(debug) << " added HCID : " << mTrackletHCHeader.HCID << " with number of bytes : " << mTotalRawWordsWritten << "-" << mLinkRecords.back().getFirstEntry(); + // LOG(debug) << " added HCID : " << mTrackletHCHeader.HCID << " with number of bytes : " << mTotalRawWordsWritten << "-" << mLinkRecords.back().getFirstEntry(); //..... so write the new one thing mLinkRecords.emplace_back(mTrackletHCHeader.word, mTotalRawWordsWritten, -1); // set the number of elements to -1 for an error condition } From 6d741e78d9595d04902ab63185c5bf7b91c02636 Mon Sep 17 00:00:00 2001 From: Valentina Zaccolo <valentina.zaccolo@to.infn.it> Date: Mon, 7 Sep 2020 16:05:53 +0200 Subject: [PATCH 0561/1751] v1 of run2 tracklets multiplicity task (#4244) --- Analysis/Tasks/PWGMM/CMakeLists.txt | 14 +++++ Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx | 64 ++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 Analysis/Tasks/PWGMM/CMakeLists.txt create mode 100644 Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx 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 <TH1F.h> +#include <TH2F.h> +#include <cmath> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct PseudorapidityDensity { + + Configurable<double> etaBinWidth{"etaBinWidth", 0.1, "eta bin width"}; + Configurable<float> etaMax{"etaMax", 1.5, "max eta value"}; + Configurable<float> etaMin{"etaMin", -1.5, "min eta value"}; + Configurable<float> vtxZMax{"vtxZMax", 10, "max z vertex"}; + Configurable<float> vtxZMin{"vtxZMin", -10, "min z vertex"}; + int etaBins = TMath::Nint((etaMax - etaMin) / etaBinWidth); + int vtxZBins = TMath::Nint(vtxZMax - vtxZMin); + + OutputObj<TH1F> hStat{TH1F("hStat", "TotalEvents", 1, 0.5, 1.5)}; + OutputObj<TH1F> hdNdeta{TH1F("hdNdeta", "dNdeta", 50, -2.5, 2.5)}; + OutputObj<TH2F> vtxZEta{TH2F("vtxZEta", ";#eta;vtxZ", 50, -2.5, 2.5, 60, -30, 30)}; + OutputObj<TH2F> 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<uint8_t>(aod::track::TrackTypeEnum::Run2Tracklet)); + Filter posZFilter = (aod::collision::posZ < (float)vtxZMax) && (aod::collision::posZ > (float)vtxZMin); + + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& collisions, soa::Filtered<aod::Tracks> 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<PseudorapidityDensity>("dNdetaRun2Tracklets-analysis")}; +} From 70aee0b41d9d0dd9e1a33f7a9b69b84f3519b0f9 Mon Sep 17 00:00:00 2001 From: dstocco <dstocco@users.noreply.github.com> Date: Mon, 7 Sep 2020 16:41:29 +0200 Subject: [PATCH 0562/1751] Correctly initialize pointer function (#4271) --- Detectors/MUON/MID/Tracking/include/MIDTracking/Tracker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/MUON/MID/Tracking/include/MIDTracking/Tracker.h b/Detectors/MUON/MID/Tracking/include/MIDTracking/Tracker.h index 79a06f830da9a..52fa2a0b8eee2 100644 --- a/Detectors/MUON/MID/Tracking/include/MIDTracking/Tracker.h +++ b/Detectors/MUON/MID/Tracking/include/MIDTracking/Tracker.h @@ -89,7 +89,7 @@ class Tracker GeometryTransformer mTransformer{}; ///< Geometry transformer typedef bool (Tracker::*TrackerMemFn)(const Track&, bool, bool); - TrackerMemFn mFollowTrack{nullptr}; ///! Choice of the function to follow the track + TrackerMemFn mFollowTrack{&Tracker::followTrackKeepBest}; ///! Choice of the function to follow the track }; } // namespace mid } // namespace o2 From e2e6ef340aa4621db1fa175bb0a4e28ffd0c0245 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 7 Sep 2020 21:32:11 +0200 Subject: [PATCH 0563/1751] DPL: do proper endOfStream for test_RegionInfoCallbackService (#4296) Somehow breaks only during the threading setup --- Framework/Core/test/test_RegionInfoCallbackService.cxx | 2 ++ 1 file changed, 2 insertions(+) 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<int>(OutputRef{"test", 0}); + ctx.services().get<ControlService>().endOfStream(); + ctx.services().get<ControlService>().readyToQuit(QuitRequest::Me); }}}, {"dest", Inputs{ From de840a921bd1ca99fec233ea4f41a8d5eaf999e1 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 8 Sep 2020 07:47:23 +0200 Subject: [PATCH 0564/1751] DPL Analysis: reintroduce TableTransform base class (#4295) --- .../Core/include/Framework/AnalysisHelpers.h | 96 ++++++++----------- Framework/Core/src/AnalysisManagers.h | 15 ++- 2 files changed, 47 insertions(+), 64 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 457c3d5b139c0..8d4c3c03b77fd 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -18,6 +18,7 @@ #include "Framework/InputSpec.h" #include "Framework/OutputObjHeader.h" #include "Framework/StringHelpers.h" +#include "Framework/Output.h" #include <ROOT/RDataFrame.hxx> #include <string> @@ -113,23 +114,23 @@ struct Produces<soa::Table<C...>> : WritingCursor<typename soa::PackToTable<type } }; -/// This helper struct allows you to declare extended tables which should be -/// created by the task (as opposed to those pre-defined by data model) -template <typename T> -struct Spawns { - using extension_t = framework::pack_head_t<typename T::originals>; - using metadata = typename aod::MetadataTrait<extension_t>::metadata; - using sources = typename metadata::originals; - using expression_pack_t = typename metadata::expression_pack_t; +/// Helper template for table transformations +template <typename METADATA> +struct TableTransform { + using SOURCES = typename METADATA::originals; - constexpr auto pack() + using metadata = METADATA; + using sources = SOURCES; + + constexpr auto sources_pack() const { - return expression_pack_t{}; + return SOURCES{}; } - template <typename O> - InputSpec const base_spec() + + template <typename Oi> + constexpr auto base_spec() const { - using o_metadata = typename aod::MetadataTrait<O>::metadata; + using o_metadata = typename aod::MetadataTrait<Oi>::metadata; return InputSpec{ o_metadata::tableLabel(), header::DataOrigin{o_metadata::origin()}, @@ -137,24 +138,42 @@ struct Spawns { } template <typename... Os> - std::vector<InputSpec> const base_specs_impl(framework::pack<Os...>) + std::vector<InputSpec> base_specs_impl(framework::pack<Os...>) const { return {base_spec<Os>()...}; } - std::vector<InputSpec> const base_specs() + std::vector<InputSpec> base_specs() const { - return base_specs_impl(sources{}); + return base_specs_impl(sources_pack()); } - OutputSpec const spec() const + constexpr auto spec() const { - return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; + return OutputSpec{OutputLabel{METADATA::tableLabel()}, METADATA::origin(), METADATA::description()}; } - OutputRef ref() const + constexpr auto output() const { - return OutputRef{metadata::tableLabel(), 0}; + return Output{METADATA::origin(), METADATA::description()}; + } + + constexpr auto ref() const + { + return OutputRef{METADATA::tableLabel(), 0}; + } +}; + +/// This helper struct allows you to declare extended tables which should be +/// created by the task (as opposed to those pre-defined by data model) +template <typename T> +struct Spawns : TableTransform<typename aod::MetadataTrait<framework::pack_head_t<typename T::originals>>::metadata> { + using extension_t = framework::pack_head_t<typename T::originals>; + using expression_pack_t = typename aod::MetadataTrait<extension_t>::metadata::expression_pack_t; + + constexpr auto pack() + { + return expression_pack_t{}; } T* operator->() @@ -299,44 +318,11 @@ struct IndexSparse { /// This helper struct allows you to declare index tables to be created in a task template <typename T, typename IP = IndexSparse> -struct Builds { - using metadata = typename aod::MetadataTrait<T>::metadata; - using originals = typename metadata::originals; +struct Builds : TableTransform<typename aod::MetadataTrait<T>::metadata> { using Key = typename T::indexing_t; using H = typename T::first_t; using Ts = typename T::rest_t; - using index_pack_t = typename metadata::index_pack_t; - - template <typename O> - InputSpec const base_spec() - { - using o_metadata = typename aod::MetadataTrait<O>::metadata; - return InputSpec{ - o_metadata::tableLabel(), - header::DataOrigin{o_metadata::origin()}, - header::DataDescription{o_metadata::description()}}; - } - - template <typename... Os> - std::vector<InputSpec> const base_specs_impl(framework::pack<Os...>) - { - return {base_spec<Os>()...}; - } - - std::vector<InputSpec> const base_specs() - { - return base_specs_impl(originals{}); - } - - OutputSpec const spec() const - { - return OutputSpec{OutputLabel{metadata::tableLabel()}, metadata::origin(), metadata::description()}; - } - - OutputRef ref() const - { - return OutputRef{metadata::tableLabel(), 0}; - } + using index_pack_t = typename aod::MetadataTrait<T>::metadata::index_pack_t; T* operator->() { diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index d40e8aebce8bd..e5045f3c81bc7 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -233,7 +233,7 @@ struct OutputManager<Spawns<T>> { static bool prepare(ProcessingContext& pc, Spawns<T>& what) { - auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(typename Spawns<T>::sources{}, pc)); + auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(what.sources_pack(), pc)); what.extension = std::make_shared<typename Spawns<T>::extension_t>(o2::soa::spawner(what.pack(), original_table.get())); what.table = std::make_shared<typename T::table_t>(soa::ArrowHelpers::joinTables({what.extension->asArrowTable(), original_table})); return true; @@ -246,8 +246,7 @@ struct OutputManager<Spawns<T>> { static bool postRun(EndOfStreamContext& eosc, Spawns<T>& what) { - using metadata = typename std::decay_t<decltype(what)>::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<Builds<T, P>> { static bool prepare(ProcessingContext& pc, Builds<T, P>& what) { - using metadata = typename std::decay_t<decltype(what)>::metadata; - return what.build(typename metadata::index_pack_t{}, - extractTypedOriginal<typename metadata::Key>(pc), - extractOriginalsTuple(typename metadata::originals{}, pc)); + return what.build(what.pack(), + extractTypedOriginal<typename Builds<T, P>::Key>(pc), + extractOriginalsTuple(what.sources_pack(), pc)); } static bool finalize(ProcessingContext&, Builds<T, P>&) @@ -289,8 +287,7 @@ struct OutputManager<Builds<T, P>> { static bool postRun(EndOfStreamContext& eosc, Builds<T, P>& what) { - using metadata = typename std::decay_t<decltype(what)>::metadata; - eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); + eosc.outputs().adopt(what.output(), what.asArrowTable()); return true; } }; From 0ac009b964335bc59c7a4d137c38a5ac44b64cd9 Mon Sep 17 00:00:00 2001 From: dsekihat <daiki.sekihata@cern.ch> Date: Tue, 8 Sep 2020 15:53:10 +0900 Subject: [PATCH 0565/1751] add dilepton ee task (#4276) --- .../include/Analysis/ReducedInfoTables.h | 1 - Analysis/Tasks/PWGDQ/CMakeLists.txt | 5 + Analysis/Tasks/PWGDQ/dileptonEE.cxx | 350 ++++++++++++++++++ 3 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 Analysis/Tasks/PWGDQ/dileptonEE.cxx diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 77015e807bbf9..a04365bd5cae1 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -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::TPCNClsFindable, track::TPCNClsFindableMinusFound>, track::TPCNClsCrossedRows<track::TPCNClsFindable, track::TPCNClsFindableMinusCrossedRows>); 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..dcc2afb1dcc2f --- /dev/null +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -0,0 +1,350 @@ +// 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 <TH1F.h> +#include <TMath.h> +#include <THashList.h> +#include <TString.h> +#include <iostream> + +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<aod::ReducedEvents, aod::ReducedEventsExtended>::iterator; +using MyEventVtxCov = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator; +using MyBarrelTracks = soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID>; +using MyBarrelTracksSelected = soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID, aod::BarrelTrackCuts>; + +void DefineHistograms(o2::framework::OutputObj<HistogramManager> 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<aod::BarrelTrackCuts> trackSel; + OutputObj<HistogramManager> 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, 69.5, 159.5); + cut1->AddCut(VarManager::kTPCsignal, 70, 100, false); //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<fgEventFillMap>(event, fValues); + + for (auto& track : tracks) { + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValues[i] = -9999.0f; + VarManager::FillTrack<fgTrackFillMap>(track, fValues); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + + if (fTrackCut->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); + } else + trackSel(0); + } + } +}; + +struct DileptonEE { + OutputObj<HistogramManager> fHistMan{"output"}; + AnalysisCompositeCut* fEventCut; + //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition + + Partition<MyBarrelTracksSelected> posTracks = aod::reducedtrack::charge > 0 && aod::reducedtrack::isBarrelSelected == 1; + Partition<MyBarrelTracksSelected> 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<fgEventFillMap>(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<BarrelTrackSelection>("barrel-track-selection"), + adaptAnalysisTask<DileptonEE>("dilepton-ee")}; +} + +void DefineHistograms(o2::framework::OutputObj<HistogramManager> 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 +} From 153c6e6cb4825bd69d551a6bece821af65a56503 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <maximiliano.puccio@cern.ch> Date: Mon, 31 Aug 2020 17:22:30 +0200 Subject: [PATCH 0566/1751] [ITSCA] Tracker performance tuning Finer grid size gives ~1.4x speedup in the tracker. However, the physics performance is quite stable with efficiency oscillations between two values that differ of ~0.2 per mille. This are currently being investigated. --- .../ITS/tracking/include/ITStracking/Constants.h | 4 ++-- .../include/ITStracking/PrimaryVertexContext.h | 5 +++++ .../tracking/include/ITStracking/TrackerTraits.h | 8 ++++---- .../ITS/tracking/src/PrimaryVertexContext.cxx | 5 +++++ .../ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx | 13 ++++++++----- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index 87ff6041fde2d..e6353c9cae8af 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -66,8 +66,8 @@ GPU_HOST_DEVICE constexpr GPUArray<float, 3> VertexerHistogramVolume() namespace index_table { -constexpr int ZBins{20}; -constexpr int PhiBins{20}; +constexpr int ZBins{256}; +constexpr int PhiBins{128}; constexpr float InversePhiBinSize{constants::index_table::PhiBins / constants::math::TwoPi}; GPU_HOST_DEVICE constexpr GPUArray<float, its::LayersNumber> InverseZBinSize() { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h index a91aef364af3c..3c363c4d7219f 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h @@ -51,6 +51,9 @@ class PrimaryVertexContext std::array<std::vector<std::vector<int>>, constants::its::CellsPerRoad - 1>& getCellsNeighbours(); std::vector<Road>& getRoads(); + float getMinR(int layer) { return mMinR[layer]; } + float getMaxR(int layer) { return mMaxR[layer]; } + bool isClusterUsed(int layer, int clusterId) const; void markUsedCluster(int layer, int clusterId); @@ -67,6 +70,8 @@ class PrimaryVertexContext protected: float3 mPrimaryVertex; + std::array<float, constants::its::LayersNumber> mMinR; + std::array<float, constants::its::LayersNumber> mMaxR; std::array<std::vector<Cluster>, constants::its::LayersNumber> mUnsortedClusters; std::array<std::vector<Cluster>, constants::its::LayersNumber> mClusters; std::array<std::vector<bool>, constants::its::LayersNumber> mUsedClusters; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 9a33762586cf1..65500276c3374 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -49,7 +49,7 @@ class TrackerTraits virtual ~TrackerTraits() = default; GPU_HOST_DEVICE static constexpr int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } - GPU_DEVICE static const int4 getBinsRect(const Cluster&, const int, const float, float maxdeltaz, float maxdeltaphi); + GPU_DEVICE static const int4 getBinsRect(const Cluster&, const int, const float, const float, float maxdeltaz, float maxdeltaphi); void SetRecoChain(o2::gpu::GPUChainITS* chain, FuncRunITSTrackFit_t&& funcRunITSTrackFit) { @@ -78,11 +78,11 @@ inline void TrackerTraits::UpdateTrackingParameters(const TrackingParameters& tr } inline GPU_DEVICE const int4 TrackerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, - const float directionZIntersection, float maxdeltaz, float maxdeltaphi) + const float z1, const float z2, float maxdeltaz, float maxdeltaphi) { - const float zRangeMin = directionZIntersection - 2 * maxdeltaz; + const float zRangeMin = gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; const float phiRangeMin = currentCluster.phiCoordinate - maxdeltaphi; - const float zRangeMax = directionZIntersection + 2 * maxdeltaz; + const float zRangeMax = gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; if (zRangeMax < -constants::its::LayersZCoordinate()[layerIndex + 1] || diff --git a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx index 87ec5bb5719f3..d4dcbe5f36fc9 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx @@ -57,6 +57,9 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st cHelper.clear(); cHelper.resize(clustersNum); + mMinR[iLayer] = 1000.f; + mMaxR[iLayer] = -1.f; + for (int iCluster{0}; iCluster < clustersNum; ++iCluster) { const Cluster& c = currentLayer[iCluster]; ClusterHelper& h = cHelper[iCluster]; @@ -67,6 +70,8 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st index_table_utils::getPhiBinIndex(phi)); h.phi = phi; h.r = math_utils::calculateRCoordinate(x, y); + mMinR[iLayer] = gpu::GPUCommonMath::Min(h.r, mMinR[iLayer]); + mMaxR[iLayer] = gpu::GPUCommonMath::Max(h.r, mMaxR[iLayer]); h.bin = bin; h.ind = clsPerBin[bin]++; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx index b34bfce0cb928..5925a66c7a204 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx @@ -50,11 +50,14 @@ void TrackerTraitsCPU::computeLayerTracklets() } const float tanLambda{(currentCluster.zCoordinate - primaryVertex.z) / currentCluster.rCoordinate}; - const float directionZIntersection{tanLambda * (constants::its::LayersRCoordinate()[iLayer + 1] - - currentCluster.rCoordinate) + - currentCluster.zCoordinate}; - - const int4 selectedBinsRect{getBinsRect(currentCluster, iLayer, directionZIntersection, + const float zAtRmin{tanLambda * (mPrimaryVertexContext->getMinR(iLayer + 1) - + currentCluster.rCoordinate) + + currentCluster.zCoordinate}; + const float zAtRmax{tanLambda * (mPrimaryVertexContext->getMaxR(iLayer + 1) - + currentCluster.rCoordinate) + + currentCluster.zCoordinate}; + + const int4 selectedBinsRect{getBinsRect(currentCluster, iLayer, zAtRmin, zAtRmax, mTrkParams.TrackletMaxDeltaZ[iLayer], mTrkParams.TrackletMaxDeltaPhi)}; if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) { From 321c9738e2e4d51c75568d100676c0e784925258 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <maximiliano.puccio@cern.ch> Date: Mon, 31 Aug 2020 19:17:51 +0200 Subject: [PATCH 0567/1751] Fix CUDA code compilation --- .../include/ITStrackingCUDA/DeviceStoreNV.h | 20 ++++++++++++++++++- .../ITStrackingCUDA/PrimaryVertexContextNV.h | 2 +- .../ITS/tracking/cuda/src/DeviceStoreNV.cu | 6 +++++- .../ITS/tracking/cuda/src/TrackerTraitsNV.cu | 5 +++-- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h index 2b17798c2d0d7..d5e38ff3b6319 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h @@ -41,7 +41,9 @@ class DeviceStoreNV final const std::array<std::vector<Cluster>, constants::its::LayersNumber>&, const std::array<std::vector<Tracklet>, constants::its::TrackletsPerRoad>&, const std::array<std::vector<Cell>, constants::its::CellsPerRoad>&, - const std::array<std::vector<int>, constants::its::CellsPerRoad - 1>&); + const std::array<std::vector<int>, constants::its::CellsPerRoad - 1>&, + const std::array<float, constants::its::LayersNumber>&, + const std::array<float, constants::its::LayersNumber>&); GPU_DEVICE const float3& getPrimaryVertex(); GPU_HOST_DEVICE Array<Vector<Cluster>, constants::its::LayersNumber>& getClusters(); GPU_DEVICE Array<Array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, @@ -55,9 +57,14 @@ class DeviceStoreNV final GPU_HOST_DEVICE Array<Vector<int>, constants::its::CellsPerRoad - 1>& getCellsPerTrackletTable(); Array<Vector<int>, constants::its::CellsPerRoad>& getTempTableArray(); + GPU_HOST_DEVICE float getRmin(int layer); + GPU_HOST_DEVICE float getRmax(int layer); + private: UniquePointer<float3> mPrimaryVertex; Array<Vector<Cluster>, constants::its::LayersNumber> mClusters; + Array<float, constants::its::LayersNumber> mRmin; + Array<float, constants::its::LayersNumber> mRmax; Array<Array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, constants::its::TrackletsPerRoad> mIndexTables; Array<Vector<Tracklet>, constants::its::TrackletsPerRoad> mTracklets; @@ -112,6 +119,17 @@ GPU_HOST_DEVICE inline Array<Vector<int>, constants::its::CellsPerRoad - 1>& { return mCellsPerTrackletTable; } + +GPU_HOST_DEVICE inline float DeviceStoreNV::getRmin(int layer) +{ + return mRmin[layer]; +} + +GPU_HOST_DEVICE inline float DeviceStoreNV::getRmax(int layer) +{ + return mRmax[layer]; +} + } // namespace GPU } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h index 51c30fdb10fa8..d5d3493a52292 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h @@ -128,7 +128,7 @@ inline void PrimaryVertexContextNV::initialise(const MemoryParameters& memParam, const std::array<float, 3>& pv, const int iteration) { this->PrimaryVertexContext::initialise(memParam, cl, pv, iteration); - mGPUContextDevicePointer = mGPUContext.initialise(mPrimaryVertex, mClusters, mTracklets, mCells, mCellsLookupTable); + mGPUContextDevicePointer = mGPUContext.initialise(mPrimaryVertex, mClusters, mTracklets, mCells, mCellsLookupTable, mMinR, mMaxR); } } // namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu index 353804900e5e1..14eb74ff41bde 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu @@ -124,11 +124,15 @@ UniquePointer<DeviceStoreNV> DeviceStoreNV::initialise(const float3& primaryVert const std::array<std::vector<Cluster>, constants::its::LayersNumber>& clusters, const std::array<std::vector<Tracklet>, constants::its::TrackletsPerRoad>& tracklets, const std::array<std::vector<Cell>, constants::its::CellsPerRoad>& cells, - const std::array<std::vector<int>, constants::its::CellsPerRoad - 1>& cellsLookupTable) + const std::array<std::vector<int>, constants::its::CellsPerRoad - 1>& cellsLookupTable, + const std::array<float, constants::its::LayersNumber>& rmin, + const std::array<float, constants::its::LayersNumber>& rmax) { mPrimaryVertex = UniquePointer<float3>{primaryVertex}; for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { + this->mRmin[iLayer] = rmin[iLayer]; + this->mRmax[iLayer] = rmax[iLayer]; this->mClusters[iLayer] = Vector<Cluster>{&clusters[iLayer][0], static_cast<int>(clusters[iLayer].size())}; diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu index de818bfe605ca..6155a94cc5d83 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu @@ -58,9 +58,10 @@ __device__ void computeLayerTracklets(DeviceStoreNV& devStore, const int layerIn }*/ const float tanLambda{(currentCluster.zCoordinate - devStore.getPrimaryVertex().z) / currentCluster.rCoordinate}; - const float directionZIntersection{tanLambda * ((constants::its::LayersRCoordinate())[layerIndex + 1] - currentCluster.rCoordinate) + currentCluster.zCoordinate}; + const float zAtRmin{tanLambda * (devStore.getRmin(layerIndex + 1) - currentCluster.rCoordinate) + currentCluster.zCoordinate}; + const float zAtRmax{tanLambda * (devStore.getRmax(layerIndex + 1) - currentCluster.rCoordinate) + currentCluster.zCoordinate}; - const int4 selectedBinsRect{TrackerTraits::getBinsRect(currentCluster, layerIndex, directionZIntersection, + const int4 selectedBinsRect{TrackerTraits::getBinsRect(currentCluster, layerIndex, zAtRmin, zAtRmax, kTrkPar.TrackletMaxDeltaZ[layerIndex], kTrkPar.TrackletMaxDeltaPhi)}; if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) { From 790cf1753ad3983912a0ab909d5abd9ffdcb3064 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 8 Sep 2020 00:13:07 +0200 Subject: [PATCH 0568/1751] TrackPar(Cov) can be invalidated by calling invalidate() method This will set its mX to meaningless value, which can be checked by isValid() method. --- .../Reconstruction/include/ReconstructionDataFormats/Track.h | 4 ++++ 1 file changed, 4 insertions(+) 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 From 00d407984c868fc01ca1577c215d4df20c97b190 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 8 Sep 2020 00:23:11 +0200 Subject: [PATCH 0569/1751] Fast DCAFitterN method to get track params at PCA w/o full propagation Only a TrackPar copy will be propagated and returned, in case of propagation failure TrackPar::isValid() will return false. --- .../include/DetectorsVertexing/DCAFitterN.h | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h index e270062471c0c..d2b2001cfefe1 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h @@ -109,15 +109,12 @@ class DCAFitterN ///< return Chi2 at PCA candidate (no check for its validity) float getChi2AtPCACandidate(int cand = 0) const { return mChi2[mOrder[cand]]; } - ///< track param positions at V0 candidate (no check for the candidate validity) - const Vec3D& getTrackPos(int i, int cand = 0) const { return mTrPos[mOrder[cand]][i]; } - - ///< prapare copies of tracks at the V0 candidate (no check for the candidate validity) + ///< prepare copies of tracks at the V0 candidate (no check for the candidate validity) /// must be called before getTrack(i,cand) query bool propagateTracksToVertex(int cand = 0); - ///< track X-param at V0 candidate (no check for the candidate validity) - float getTrackX(int i, int cand = 0) const { return getTrackPos(i, cand)[0]; } + ///< check if propagation of tracks to candidate vertex was done + bool isPropagateTracksToVertexDone(int cand = 0) const { return mTrPropDone[mOrder[cand]]; } ///< track param propagated to V0 candidate (no check for the candidate validity) /// propagateTracksToVertex must be called in advance @@ -129,6 +126,9 @@ class DCAFitterN return mCandTr[mOrder[cand]][i]; } + ///< calculate on the fly track param (no cov mat) at candidate, check isValid to make sure propagation was successful + o2::track::TrackPar getTrackParamAtPCA(int i, int cand = 0) const; + MatSym3D calcPCACovMatrix(int cand = 0) const; const Track* getOrigTrackPtr(int i) const { return mOrigTrPtr[i]; } @@ -182,6 +182,12 @@ class DCAFitterN bool closerToAlternative() const; static double getAbsMax(const VecND& v); + ///< track param positions at V0 candidate (no check for the candidate validity) + const Vec3D& getTrackPos(int i, int cand = 0) const { return mTrPos[mOrder[cand]][i]; } + + ///< track X-param at V0 candidate (no check for the candidate validity) + float getTrackX(int i, int cand = 0) const { return getTrackPos(i, cand)[0]; } + MatStd3D getTrackRotMatrix(int i) const // generate 3D matrix for track rotation to global frame { MatStd3D mat; @@ -695,6 +701,22 @@ bool DCAFitterN<N, Args...>::propagateTracksToVertex(int icand) return true; } +//___________________________________________________________________ +template <int N, typename... Args> +inline o2::track::TrackPar DCAFitterN<N, Args...>::getTrackParamAtPCA(int i, int icand) const +{ + // propagate tracks param only to current vertex (if not already done) + int ord = mOrder[icand]; + o2::track::TrackPar trc(mCandTr[ord][i]); + if (!mTrPropDone[ord]) { + auto x = mTrAux[i].c * mPCA[ord][0] + mTrAux[i].s * mPCA[ord][1]; // X of PCA in the track frame + if (!trc.propagateParamTo(x, mBz)) { + trc.invalidate(); + } + } + return std::move(trc); +} + //___________________________________________________________________ template <int N, typename... Args> inline double DCAFitterN<N, Args...>::getAbsMax(const VecND& v) From 180ab2deda5578c4f46120b4d2a0d088bfcfef11 Mon Sep 17 00:00:00 2001 From: Luca Barioglio <lbariogl@users.noreply.github.com> Date: Tue, 8 Sep 2020 11:21:07 +0200 Subject: [PATCH 0570/1751] Add task for nuclei (#4301) --- Analysis/Tasks/CMakeLists.txt | 1 + Analysis/Tasks/PWGLF/CMakeLists.txt | 14 ++++++++ Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx | 41 ++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 Analysis/Tasks/PWGLF/CMakeLists.txt create mode 100644 Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx 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/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..960cc376981b7 --- /dev/null +++ b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx @@ -0,0 +1,41 @@ +// 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 <TH1F.h> +#include <TH2F.h> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct NucleiSpecraTask { + + OutputObj<TH2F> hTPCsignal{TH2F("hTPCsignal", ";#it{p} (GeV/#it{c}); d#it{E}/d#it{X} (a. u.)", 600, 0., 3, 1400, 0, 1400)}; + OutputObj<TH1F> hMomentum{TH1F("hMomentum", ";#it{p} (GeV/#it{c});", 600, 0., 3.)}; + + void process(soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) + { + for (auto& track : tracks) { + hTPCsignal->Fill(track.p(), track.tpcSignal()); + hMomentum->Fill(track.p()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<NucleiSpecraTask>("nuclei-spectra")}; +} From 797254724dc7eb6e778d6081c7b9f45325aaa9ea Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 8 Sep 2020 12:10:17 +0200 Subject: [PATCH 0571/1751] DPL Analysis: drop arrow v0.17 compatibility (#4304) --- Framework/Core/include/Framework/Kernels.h | 145 --------------------- Framework/Core/src/TableTreeHelpers.cxx | 15 --- Framework/Core/test/test_Kernels.cxx | 7 - 3 files changed, 167 deletions(-) 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(<arrow/config.h>) -#include <arrow/config.h> -#endif -#if __has_include(<arrow/util/config.h>) -#include <arrow/util/config.h> -#endif - #include <arrow/compute/kernel.h> #include <arrow/status.h> #include <arrow/util/visibility.h> @@ -28,145 +21,8 @@ #include <string> -#if (ARROW_VERSION < 1000000) -namespace arrow -{ -using Datum = compute::Datum; -} -#endif - namespace o2::framework { -#if (ARROW_VERSION < 1000000) -template <typename T> -struct ARROW_EXPORT GroupByOptions { - std::string columnName; - T size; -}; - -/// Build ranges -template <typename T, typename ARRAY> -class ARROW_EXPORT SortedGroupByKernel : public arrow::compute::UnaryKernel -{ - public: - explicit SortedGroupByKernel(GroupByOptions<T> 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<std::shared_ptr<arrow::Table>>(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<arrow::DataType> out_type() const final - { - return mType; - } -#pragma GCC diagnostic pop - - private: - arrow::Status doGrouping(std::shared_ptr<arrow::ChunkedArray> chunkedArray, arrow::compute::Datum* outputRanges) - { - o2::framework::TableBuilder builder; - auto writer = builder.persist<T, T, T>({"start", "count", "index"}); - auto zeroChunk = std::static_pointer_cast<ARRAY>(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<ARRAY>(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<arrow::DataType> mType; - GroupByOptions<T> 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 <typename T> -arrow::Status sliceByColumn(std::string const& key, - std::shared_ptr<arrow::Table> const& input, - T size, - std::vector<arrow::compute::Datum>* outputSlices, - std::vector<uint64_t>* offsets = nullptr) -{ - arrow::compute::Datum inputTable{input}; - // build all the ranges on the fly. - arrow::compute::Datum outRanges; - auto table = arrow::util::get<std::shared_ptr<arrow::Table>>(inputTable.value); - o2::framework::SortedGroupByKernel<T, soa::arrow_array_for_t<T>> kernel{GroupByOptions<T>{key, size}}; - - ARROW_RETURN_NOT_OK(kernel.Call(nullptr, inputTable, &outRanges)); - auto ranges = arrow::util::get<std::shared_ptr<arrow::Table>>(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<soa::arrow_array_for_t<T>>(startChunks->chunk(0))->raw_values(); - auto countData = std::static_pointer_cast<soa::arrow_array_for_t<T>>(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<std::shared_ptr<arrow::ChunkedArray>> 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/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(<arrow/config.h>) -#include <arrow/config.h> -#endif -#if __has_include(<arrow/util/config.h>) -#include <arrow/util/config.h> -#endif - #include "arrow/type_traits.h" namespace o2 @@ -39,19 +32,11 @@ BranchIterator::BranchIterator(TTree* tree, std::shared_ptr<arrow::ChunkedArray> 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<const arrow::FixedSizeListType*>(mField->type().get())->list_size(); mLeaflistString += "[" + std::to_string(mNumberElements) + "]"; 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) { From e58031ea872cbf4e3c9011201d653c2c8ffce36c Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Fri, 4 Sep 2020 16:49:20 +0200 Subject: [PATCH 0572/1751] Workflow for plug-in TOF analyses of compressed data --- Detectors/TOF/compression/CMakeLists.txt | 6 ++ .../src/tof-compressed-analysis.cxx | 43 ++++++++ Detectors/TOF/workflow/CMakeLists.txt | 1 + .../include/TOFWorkflow/CompressedAnalysis.h | 46 +++++++++ .../TOFWorkflow/CompressedAnalysisTask.h | 94 ++++++++++++++++++ .../workflow/src/CompressedAnalysisTask.cxx | 98 +++++++++++++++++++ 6 files changed, 288 insertions(+) create mode 100644 Detectors/TOF/compression/src/tof-compressed-analysis.cxx create mode 100644 Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysis.h create mode 100644 Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysisTask.h create mode 100644 Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx diff --git a/Detectors/TOF/compression/CMakeLists.txt b/Detectors/TOF/compression/CMakeLists.txt index 9dcbfc25f2c94..adef2471c81e4 100644 --- a/Detectors/TOF/compression/CMakeLists.txt +++ b/Detectors/TOF/compression/CMakeLists.txt @@ -27,4 +27,10 @@ o2_add_executable(compressed-inspector PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils ) +o2_add_executable(compressed-analysis + COMPONENT_NAME tof + SOURCES src/tof-compressed-analysis.cxx + PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils + ) + diff --git a/Detectors/TOF/compression/src/tof-compressed-analysis.cxx b/Detectors/TOF/compression/src/tof-compressed-analysis.cxx new file mode 100644 index 0000000000000..0e610b60b4e41 --- /dev/null +++ b/Detectors/TOF/compression/src/tof-compressed-analysis.cxx @@ -0,0 +1,43 @@ +// 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 tof-compressor.cxx +/// @author Roberto Preghenella +/// @since 2019-12-18 +/// @brief Basic DPL workflow for TOF raw data compression + +#include "TOFWorkflow/CompressedAnalysisTask.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/ConfigParamSpec.h" +#include "FairLogger.h" + +using namespace o2::framework; + +// add workflow options, note that customization needs to be declared before +// including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ +} + +#include "Framework/runDataProcessing.h" // the main driver + +/// This function hooks up the the workflow specifications into the DPL driver. +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + DataProcessorSpec{"compressed-analysis", + select("x:TOF/CRAWDATA"), + Outputs{}, + AlgorithmSpec(adaptFromTask<o2::tof::CompressedAnalysisTask>()), + Options{ + {"tof-compressed-analysis-conet-mode", VariantType::Bool, false, {"CONET mode"}}, + {"tof-compressed-analysis-filename", VariantType::String, "", {"Analysis file name"}}, + {"tof-compressed-analysis-function", VariantType::String, "", {"Analysis function call"}}}}}; +} diff --git a/Detectors/TOF/workflow/CMakeLists.txt b/Detectors/TOF/workflow/CMakeLists.txt index 1cda6cfabe976..d75c55259ff79 100644 --- a/Detectors/TOF/workflow/CMakeLists.txt +++ b/Detectors/TOF/workflow/CMakeLists.txt @@ -17,6 +17,7 @@ o2_add_library(TOFWorkflowUtils src/TOFRawWriterSpec.cxx src/CompressedDecodingTask.cxx src/CompressedInspectorTask.cxx + src/CompressedAnalysisTask.cxx src/EntropyEncoderSpec.cxx src/EntropyDecoderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction) diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysis.h b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysis.h new file mode 100644 index 0000000000000..32d5a28f63ff9 --- /dev/null +++ b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysis.h @@ -0,0 +1,46 @@ +// 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 CompressedAnalysisTask.h +/// @author Roberto Preghenella +/// @since 2020-09-04 +/// @brief TOF compressed data analysis base class + +#ifndef O2_TOF_COMPRESSEDANALYSIS +#define O2_TOF_COMPRESSEDANALYSIS + +#include "Headers/RAWDataHeader.h" +#include "DataFormatsTOF/CompressedDataFormat.h" +#include "TOFReconstruction/DecoderBase.h" + +using namespace o2::tof::compressed; + +namespace o2 +{ +namespace tof +{ + +class CompressedAnalysis : public DecoderBaseT<o2::header::RAWDataHeaderV6> +{ + + public: + CompressedAnalysis() = default; + ~CompressedAnalysis() override = default; + + virtual bool initialize() = 0; + virtual bool finalize() = 0; + + private: +}; + +} // namespace tof +} // namespace o2 + +#endif /* O2_TOF_COMPRESSEDANALYSIS */ diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysisTask.h b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysisTask.h new file mode 100644 index 0000000000000..638030454b38d --- /dev/null +++ b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysisTask.h @@ -0,0 +1,94 @@ +// 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 CompressedAnalysisTask.h +/// @author Roberto Preghenella +/// @since 2020-09-04 +/// @brief TOF compressed data analysis task + +#ifndef O2_TOF_COMPRESSEDANALYSISTASK +#define O2_TOF_COMPRESSEDANALYSISTASK + +#include "Framework/Task.h" +#include "TOFWorkflow/CompressedAnalysis.h" + +#include "TROOT.h" +#include "TSystem.h" +#include "TGlobal.h" +#include "TFunction.h" +#include <string> +#include <iostream> + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +class CompressedAnalysisTask : public Task +{ + public: + CompressedAnalysisTask() = default; + ~CompressedAnalysisTask() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + + private: + CompressedAnalysis* mAnalysis = nullptr; + bool mStatus = false; + + template <typename T> + T GetFromMacro(const std::string& file, const std::string& funcname, const std::string& type, const std::string& unique) + { + + /** tweak the string to get the required global function **/ + auto func = funcname; + if (func.empty()) { + auto size = file.size(); + auto firstindex = file.find_last_of("/") + 1; + auto lastindex = file.find_last_of("."); + func = file.substr(firstindex < size ? firstindex : 0, + lastindex < size ? lastindex - firstindex : size - firstindex) + + "()"; + } + auto gfunc = func.substr(0, func.find_first_of('(')); + + /** load macro is global function is not already defined **/ + if (!gROOT->GetGlobalFunction(gfunc.c_str())) { + if (gROOT->LoadMacro(file.c_str()) != 0) { + std::cout << "Cannot find " << file << std::endl; + return nullptr; + } + if (!gROOT->GetGlobalFunction(gfunc.c_str())) { + std::cout << "Global function '" << gfunc << "' not defined" << std::endl; + return nullptr; + } + } + + /** check the return type matches the required one **/ + if (strcmp(gROOT->GetGlobalFunction(gfunc.c_str())->GetReturnTypeName(), type.c_str())) { + std::cout << "Global function '" << gfunc << "' does not return a '" << type << "' type" << std::endl; + return nullptr; + } + + /** process function and retrieve pointer to the returned type **/ + gROOT->ProcessLine(Form("%s __%s__ = %s;", type.c_str(), unique.c_str(), func.c_str())); + auto ptr = (T*)gROOT->GetGlobal(Form("__%s__", unique.c_str()))->GetAddress(); + + /** success **/ + return *ptr; + } +}; + +} // namespace tof +} // namespace o2 + +#endif /* O2_TOF_COMPRESSEDANALYSISTASK */ diff --git a/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx new file mode 100644 index 0000000000000..4f6037852f186 --- /dev/null +++ b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx @@ -0,0 +1,98 @@ +// 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 CompressedAnalysisTask.cxx +/// @author Roberto Preghenella +/// @since 2020-09-04 +/// @brief TOF compressed data analysis task + +#include "TOFWorkflow/CompressedAnalysisTask.h" +#include "Framework/Task.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/CallbackService.h" +#include "Framework/ConcreteDataMatcher.h" +#include "Framework/RawDeviceService.h" +#include "Framework/DeviceSpec.h" +#include <fairmq/FairMQDevice.h> + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +void CompressedAnalysisTask::init(InitContext& ic) +{ + + auto conetmode = ic.options().get<bool>("tof-compressed-analysis-conet-mode"); + auto filename = ic.options().get<std::string>("tof-compressed-analysis-filename"); + auto function = ic.options().get<std::string>("tof-compressed-analysis-function"); + + if (filename.empty()) { + LOG(ERROR) << "No analysis filename defined"; + mStatus = true; + return; + } + + if (function.empty()) { + LOG(ERROR) << "No analysis function defined"; + mStatus = true; + return; + } + + mAnalysis = GetFromMacro<CompressedAnalysis*>(filename, function, "CompressedAnalysis*", "compressed_analysis"); + if (!mAnalysis) { + LOG(ERROR) << "Could not retrieve analysis from file: " << filename; + mStatus = true; + return; + } + + mAnalysis->setDecoderCONET(conetmode); + mAnalysis->initialize(); + + auto finishFunction = [this]() { + LOG(INFO) << "CompressedBaseTask finish"; + mAnalysis->finalize(); + }; + ic.services().get<CallbackService>().set(CallbackService::Id::Stop, finishFunction); +} + +void CompressedAnalysisTask::run(ProcessingContext& pc) +{ + + /** check status **/ + if (mStatus) { + pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); + return; + } + + /** loop over inputs routes **/ + for (auto iit = pc.inputs().begin(), iend = pc.inputs().end(); iit != iend; ++iit) { + if (!iit.isValid()) + continue; + + /** loop over input parts **/ + for (auto const& ref : iit) { + + const auto* headerIn = DataRefUtils::getHeader<o2::header::DataHeader*>(ref); + auto payloadIn = ref.payload; + auto payloadInSize = headerIn->payloadSize; + + mAnalysis->setDecoderBuffer(payloadIn); + mAnalysis->setDecoderBufferSize(payloadInSize); + mAnalysis->run(); + } + } +} + +} // namespace tof +} // namespace o2 From 2ec086d69717d7f383ac5dd8504000470c4c50d2 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Sep 2020 13:03:52 +0200 Subject: [PATCH 0573/1751] DPL: add RawDeviceService::waitFor method (#4303) This avoids exposing FairMQDevice.h to the user in a few more places. Every inclusion of FairMQDevice.h results in 1GB of RAM and 2 seconds of compilations in my naive tests. --- Framework/Core/CMakeLists.txt | 1 + .../Core/include/Framework/RawDeviceService.h | 18 ++++++++------- .../Framework/SimpleRawDeviceService.h | 15 ++++++------ Framework/Core/src/AODReaderHelpers.cxx | 1 - Framework/Core/src/SimpleRawDeviceService.cxx | 23 +++++++++++++++++++ Framework/Core/src/WorkflowHelpers.cxx | 3 +-- .../test_SimpleDataProcessingDevice01.cxx | 3 +-- .../Core/test/test_StaggeringWorkflow.cxx | 6 ++--- 8 files changed, 45 insertions(+), 25 deletions(-) create mode 100644 Framework/Core/src/SimpleRawDeviceService.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 7c235e03d9b73..8d22c05aec48d 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -97,6 +97,7 @@ o2_add_library(Framework src/ResourcesMonitoringHelper.cxx src/ServiceRegistry.cxx src/SimpleResourceManager.cxx + src/SimpleRawDeviceService.cxx src/StreamOperators.cxx src/TMessageSerializer.cxx src/TableBuilder.cxx 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/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/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 2a614f356a6d5..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 <FairMQDevice.h> #include <ROOT/RDataFrame.hxx> #include <TGrid.h> #include <TFile.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 <FairMQDevice.h> + +namespace o2::framework +{ + +void SimpleRawDeviceService::waitFor(unsigned int ms) +{ + mDevice->WaitFor(std::chrono::milliseconds(ms)); +} + +} // namespace o2::framework diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 9ffaaf1af00b3..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 <algorithm> #include <list> @@ -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<RawDeviceService>().device()->WaitFor(std::chrono::seconds(2)); + pc.services().get<RawDeviceService>().waitFor(2000); }; }}; 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 <Monitoring/Monitoring.h> -#include <FairMQDevice.h> using namespace o2::framework; @@ -40,7 +39,7 @@ std::vector<DataProcessorSpec> 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<FakeCluster>(Output{"TPC", "CLUSTERS", 0}, 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 <FairMQDevice.h> -#include <chrono> #include <cstring> #include <iostream> #include <regex> @@ -88,9 +86,9 @@ std::vector<DataProcessorSpec> 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); From 985099d9f87094f1de830b402d31bc9f0df17d1d Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Mon, 6 Jul 2020 16:07:54 +0200 Subject: [PATCH 0574/1751] MID: add library MIDWorkflow --- Detectors/MUON/MID/Workflow/CMakeLists.txt | 79 ++++++++++------------ 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/CMakeLists.txt b/Detectors/MUON/MID/Workflow/CMakeLists.txt index 487556cd975f8..239e8d98caa8f 100644 --- a/Detectors/MUON/MID/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MID/Workflow/CMakeLists.txt @@ -8,27 +8,42 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +o2_add_library(MIDWorkflow + TARGETVARNAME targetName + SOURCES src/RecoWorkflow.cxx + src/ClusterizerMCSpec.cxx + src/DigitReaderSpec.cxx + src/RecoWorkflowMC.cxx + src/TrackerMCSpec.cxx + src/ClusterizerSpec.cxx + src/RecoWorkflow.cxx + src/RawDecoderSpec.cxx + src/RawAggregatorSpec.cxx + src/TrackerSpec.cxx + src/DigitReaderSpec.cxx + src/DigitsToRawWorkflow.cxx + src/RawWriterSpec.cxx + PUBLIC_LINK_LIBRARIES + O2::Framework + O2::SimConfig + ms_gsl::ms_gsl + O2::DetectorsBase + O2::SimulationDataFormat + O2::DataFormatsMID + O2::DPLUtils + O2::MIDSimulation + O2::MIDClustering + O2::MIDTracking + O2::MIDRaw + ) + o2_add_executable( reco-workflow-mc COMPONENT_NAME mid SOURCES src/mid-reco-workflow-mc.cxx - src/ClusterizerMCSpec.cxx - src/DigitReaderSpec.cxx - src/RecoWorkflowMC.cxx - src/TrackerMCSpec.cxx - TARGETVARNAME - exenamerecomc + TARGETVARNAME exenamerecomc PUBLIC_LINK_LIBRARIES - O2::Framework - O2::SimConfig - ms_gsl::ms_gsl - O2::DetectorsBase - O2::SimulationDataFormat - O2::DataFormatsMID - O2::DPLUtils - O2::MIDSimulation - O2::MIDClustering - O2::MIDTracking) + O2::MIDWorkflow) target_include_directories( ${exenamerecomc} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) @@ -37,23 +52,9 @@ o2_add_executable( reco-workflow COMPONENT_NAME mid SOURCES src/mid-reco-workflow.cxx - src/ClusterizerSpec.cxx - src/RecoWorkflow.cxx - src/RawDecoderSpec.cxx - src/RawAggregatorSpec.cxx - src/TrackerSpec.cxx - TARGETVARNAME - exenamereco + TARGETVARNAME exenamereco PUBLIC_LINK_LIBRARIES - O2::Framework - O2::SimConfig - ms_gsl::ms_gsl - O2::DetectorsBase - O2::DataFormatsMID - O2::DPLUtils - O2::MIDClustering - O2::MIDRaw - O2::MIDTracking) + O2::MIDWorkflow) target_include_directories( ${exenamereco} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) @@ -61,18 +62,10 @@ target_include_directories( o2_add_executable( digits-to-raw-workflow COMPONENT_NAME mid - SOURCES src/mid-digits-to-raw.cxx src/DigitReaderSpec.cxx - src/DigitsToRawWorkflow.cxx src/RawWriterSpec.cxx TARGETVARNAME - exenameraw + SOURCES src/mid-digits-to-raw.cxx + TARGETVARNAME exenameraw PUBLIC_LINK_LIBRARIES - O2::Framework - O2::SimConfig - ms_gsl::ms_gsl - O2::SimulationDataFormat - O2::DataFormatsMID - O2::DPLUtils - O2::MIDSimulation - O2::MIDRaw) + O2::MIDWorkflow) target_include_directories( ${exenameraw} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) From 594ae1d97eea79e892f887f9e98f9cfe8e61cc22 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 8 Sep 2020 14:32:00 +0200 Subject: [PATCH 0575/1751] Add method to enforce oldest slot finalization/removal --- .../DetectorsCalibration/TimeSlotCalibration.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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<const Input> 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<Input, Container>::checkSlotsToFinalize(TFType tf, int } } +//_________________________________________________ +template <typename Input, typename Container> +void TimeSlotCalibration<Input, Container>::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 <typename Input, typename Container> inline TFType TimeSlotCalibration<Input, Container>::tf2SlotMin(TFType tf) const From 6ddb56c1c37eed6b89e69abcc0885a974cd1336c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 7 Sep 2020 18:36:57 +0200 Subject: [PATCH 0576/1751] Init mag.field before initializing generator --- run/O2PrimaryServerDevice.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/run/O2PrimaryServerDevice.h b/run/O2PrimaryServerDevice.h index 9af897b5131a8..07d8507b574ad 100644 --- a/run/O2PrimaryServerDevice.h +++ b/run/O2PrimaryServerDevice.h @@ -27,6 +27,8 @@ #include <SimConfig/SimConfig.h> #include <CommonUtils/ConfigurableParam.h> #include <CommonUtils/RngHelper.h> +#include "Field/MagneticField.h" +#include <TGeoGlobalMagField.h> #include <typeinfo> #include <thread> #include <TROOT.h> @@ -60,6 +62,31 @@ 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 + int fld = conf.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); + TGeoGlobalMagField::Instance()->SetField(field); + TGeoGlobalMagField::Instance()->Lock(); + o2::eventgen::GeneratorFactory::setPrimaryGenerator(conf, &mPrimGen); mPrimGen.SetEvent(&mEventHeader); From 825842c976954c142c17220de6358b53f0604b68 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 8 Sep 2020 11:42:54 +0200 Subject: [PATCH 0577/1751] Dedicate field creator method for construction from nominal rounded L3 field value --- Common/Field/include/Field/MagneticField.h | 3 +++ Common/Field/src/MagneticField.cxx | 23 ++++++++++++++++++++++ macro/build_geometry.C | 22 +-------------------- run/O2PrimaryServerDevice.h | 21 +------------------- 4 files changed, 28 insertions(+), 41 deletions(-) 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/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 07d8507b574ad..655b3fae8b815 100644 --- a/run/O2PrimaryServerDevice.h +++ b/run/O2PrimaryServerDevice.h @@ -64,26 +64,7 @@ class O2PrimaryServerDevice final : public FairMQDevice auto& conf = o2::conf::SimConfig::Instance(); // init magnetic field as it might be needed by the generator - int fld = conf.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(conf.getConfigData().mField); TGeoGlobalMagField::Instance()->SetField(field); TGeoGlobalMagField::Instance()->Lock(); From 937e1a98cc773b6a1bdb6b124b17327fadc61eac Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 9 Sep 2020 00:24:19 +0200 Subject: [PATCH 0578/1751] DPL Foundation: use intrinsict for pack element, when available (#4312) --- Framework/Foundation/include/Framework/Pack.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Framework/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index b8b5f4806a2a0..8e0badcdff474 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<Ts...> const&) template <std::size_t I, typename T> struct pack_element; +#ifdef __clang__ +template <std::size_t I, typename... Ts> +struct pack_element<I, pack<Ts...>> { + using type = __type_pack_element<I, Ts...>; +}; +#else + // recursive case template <std::size_t I, typename Head, typename... Tail> struct pack_element<I, pack<Head, Tail...>> @@ -44,6 +51,7 @@ template <typename Head, typename... Tail> struct pack_element<0, pack<Head, Tail...>> { typedef Head type; }; +#endif template <std::size_t I, typename T> using pack_element_t = typename pack_element<I, T>::type; From 898abc648fa77c527cf3d4f760de84b3907a6d22 Mon Sep 17 00:00:00 2001 From: dsekihat <daiki.sekihata@cern.ch> Date: Wed, 9 Sep 2020 17:16:28 +0900 Subject: [PATCH 0579/1751] update eID (#4314) --- Analysis/Tasks/PWGDQ/dileptonEE.cxx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx index dcc2afb1dcc2f..9bf806fc14b28 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -104,8 +104,13 @@ struct BarrelTrackSelection { 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, 69.5, 159.5); - cut1->AddCut(VarManager::kTPCsignal, 70, 100, false); //exclude = false + 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"); From 740be0c832f06e9e49ed1a5d628acf0a0c24eefe Mon Sep 17 00:00:00 2001 From: Luca Barioglio <lbariogl@users.noreply.github.com> Date: Wed, 9 Sep 2020 10:17:18 +0200 Subject: [PATCH 0580/1751] Add filters to nuclei task (#4311) --- Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx | 26 +++++++++++++++++-- .../include/Framework/AnalysisDataModel.h | 10 ++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx index 960cc376981b7..902385b40b8dd 100644 --- a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx +++ b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx @@ -22,12 +22,34 @@ using namespace o2::framework::expressions; struct NucleiSpecraTask { - OutputObj<TH2F> hTPCsignal{TH2F("hTPCsignal", ";#it{p} (GeV/#it{c}); d#it{E}/d#it{X} (a. u.)", 600, 0., 3, 1400, 0, 1400)}; + OutputObj<TH2F> hTPCsignal{TH2F("hTPCsignal", ";#it{p} (GeV/#it{c}); d#it{E} / d#it{X} (a. u.)", 600, 0., 3, 1400, 0, 1400)}; OutputObj<TH1F> hMomentum{TH1F("hMomentum", ";#it{p} (GeV/#it{c});", 600, 0., 3.)}; - void process(soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) + Configurable<float> absEtaMax{"absEtaMax", 0.8, "pseudo-rapidity edges"}; + Configurable<float> absYmax{"absYmax", 0.5, "rapidity edges"}; + Configurable<float> beamRapidity{"yBeam", 0., "beam rapidity"}; + Configurable<float> chi2TPCperNDF{"chi2TPCperNDF", 4., "chi2 per NDF in TPC"}; + Configurable<float> foundFractionTPC{"foundFractionTPC", 0., "TPC clusters / TPC crossed rows"}; + Configurable<int> recPointsTPC{"recPointsTPC", 0, "clusters in TPC"}; + Configurable<int> signalClustersTPC{"signalClustersTPC", 70, "clusters with PID in TPC"}; + Configurable<float> minEnergyLoss{"minEnergyLoss", 0., "energy loss in TPC"}; + Configurable<int> recPointsITS{"recPointsITS", 2, "number of ITS points"}; + Configurable<int> 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<soa::Join<aod::Tracks, aod::TracksExtra>> 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()); } diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 8b84781a09d23..e7bb1e6edc148 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -180,6 +180,14 @@ DECLARE_SOA_DYNAMIC_COLUMN(ITSNCls, itsNCls, [](uint8_t itsClusterMap) -> uint8_ itsNcls++; return itsNcls; }); +DECLARE_SOA_DYNAMIC_COLUMN(ITSNClsInnerBarrel, itsNClsInnerBarrel, [](uint8_t itsClusterMap) -> uint8_t { + uint8_t itsNclsInnerBarrel = 0; + constexpr uint8_t bit = 1; + for (int layer = 0; layer < 3; layer++) + if (itsClusterMap & (bit << layer)) + itsNclsInnerBarrel++; + return itsNclsInnerBarrel; +}); DECLARE_SOA_DYNAMIC_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, [](uint8_t tpcNClsFindable, uint8_t tpcNClsFindableMinusCrossedRows) -> float { @@ -243,7 +251,7 @@ DECLARE_SOA_TABLE(TracksExtra, "AOD", "TRACKEXTRA", track::TPCSignal, track::TRDSignal, track::TOFSignal, track::Length, track::TOFExpMom, track::TPCNClsFound<track::TPCNClsFindable, track::TPCNClsFindableMinusFound>, track::TPCNClsCrossedRows<track::TPCNClsFindable, track::TPCNClsFindableMinusCrossedRows>, - track::ITSNCls<track::ITSClusterMap>, + track::ITSNCls<track::ITSClusterMap>, track::ITSNClsInnerBarrel<track::ITSClusterMap>, track::TPCCrossedRowsOverFindableCls<track::TPCNClsFindable, track::TPCNClsFindableMinusCrossedRows>, track::TPCFractionSharedCls<track::TPCNClsShared, track::TPCNClsFindable, track::TPCNClsFindableMinusFound>); From b59767ba9c15b645aecc47246a8eb3359fa0a1fb Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 9 Sep 2020 10:40:24 +0200 Subject: [PATCH 0581/1751] DPL Analysis: adapt Attach/Extend to new Join (#4307) --- Analysis/Tutorials/src/dynamicColumns.cxx | 4 ++- Analysis/Tutorials/src/extendedColumns.cxx | 4 ++- Framework/Core/include/Framework/ASoA.h | 40 ++++++++++------------ 3 files changed, 25 insertions(+), 23 deletions(-) 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<aod::Tracks, aod::extension::P2<aod::track::P>>(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<aod::Tracks, aod::extension::P2>(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/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index d4d503fac778e..a059aa12abc21 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -908,10 +908,10 @@ class Table Table(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : mTable(table), - mEnd{static_cast<uint64_t>(table->num_rows())}, + mEnd{table == nullptr ? 0 : static_cast<uint64_t>(table->num_rows())}, mOffset(offset) { - if (mTable->num_rows() == 0) { + if ((mTable == nullptr) or (mTable->num_rows() == 0)) { for (size_t ci = 0; ci < sizeof...(C); ++ci) { mColumnChunks[ci] = nullptr; } @@ -1766,26 +1766,12 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) chunks[i].emplace_back(v.at(i)); } } - std::array<std::shared_ptr<arrow::ChunkedArray>, sizeof...(C)> arrays; + std::vector<std::shared_ptr<arrow::ChunkedArray>> arrays; for (auto i = 0u; i < sizeof...(C); ++i) { - arrays[i] = std::make_shared<arrow::ChunkedArray>(chunks[i]); + arrays.push_back(std::make_shared<arrow::ChunkedArray>(chunks[i])); } - auto new_schema = o2::soa::createSchemaFromColumns(columns); - std::vector<std::shared_ptr<arrow::ChunkedArray>> new_columns; - for (auto i = 0u; i < sizeof...(C); ++i) { - new_columns.push_back(arrays[i]); - } - return arrow::Table::Make(new_schema, new_columns); -} - -/// On-the-fly adding of expression columns -template <typename T, typename... Cs> -auto Extend(T const& table) -{ - static_assert((soa::is_type_spawnable_v<Cs> && ...), "You can only extend a table with expression columns"); - using output_t = JoinBase<T, soa::Table<Cs...>>; - return output_t{spawner(framework::pack<Cs...>{}, table.asArrowTable().get()), table.offset()}; + return arrow::Table::Make(new_schema, arrays); } /// Template for building an index table to access matching rows from non- @@ -1817,14 +1803,26 @@ struct IndexTable : Table<soa::Index<>, H, Ts...> { template <typename T> using is_soa_index_table_t = typename framework::is_base_of_template<soa::IndexTable, T>; +/// On-the-fly adding of expression columns +template <typename T, typename... Cs> +auto Extend(T const& table) +{ + static_assert((soa::is_type_spawnable_v<Cs> && ...), "You can only extend a table with expression columns"); + using output_t = Join<T, soa::Table<Cs...>>; + if (table.tableSize() > 0) { + return output_t{{spawner(framework::pack<Cs...>{}, table.asArrowTable().get()), table.asArrowTable()}, 0}; + } + return output_t{{nullptr}, 0}; +} + /// Template function to attach dynamic columns on-the-fly (e.g. inside /// process() function). Dynamic columns need to be compatible with the table. template <typename T, typename... Cs> auto Attach(T const& table) { static_assert((framework::is_base_of_template<o2::soa::DynamicColumn, Cs>::value && ...), "You can only attach dynamic columns"); - using output_t = JoinBase<T, o2::soa::Table<Cs...>>; - return output_t{table.asArrowTable(), table.offset()}; + using output_t = Join<T, o2::soa::Table<Cs...>>; + return output_t{{table.asArrowTable()}, table.offset()}; } } // namespace o2::soa From e8e149e45eabd346e084c1fa0d82d5b29fd3e8af Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 9 Sep 2020 11:32:14 +0200 Subject: [PATCH 0582/1751] Add script to merge multiple -ftime-trace outputs. --- scripts/profile-compilation-merge | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100755 scripts/profile-compilation-merge 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) From 2b75bf0b061eb1d3d1070de2bf2dd3e43d8a08bf Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 9 Sep 2020 11:33:13 +0200 Subject: [PATCH 0583/1751] Ignore .clangd folder Cache for Language Server compilations --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) 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 From 0712f7ac176ee85e66b9f64697aa848c39d90cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Wed, 9 Sep 2020 12:03:56 +0200 Subject: [PATCH 0584/1751] Use CCDB headers to get SOR timestamp for run (#4305) - Update timestamp table maker task - Caching requested timestamps for later use - Remove old utilities for Run to Timestamp conversion --- Analysis/Core/CMakeLists.txt | 8 - .../Core/include/Analysis/RunToTimestamp.h | 48 ----- Analysis/Core/src/AnalysisCoreLinkDef.h | 1 - Analysis/Core/src/InsertNewRunToTimestamp.cxx | 103 ----------- Analysis/Core/src/RunToTimestamp.cxx | 60 ------- .../Scripts/insert_Run2_run_to_timestamps.py | 168 ------------------ .../Scripts/inspect_Run2_run_to_timestamps.py | 34 ---- Analysis/Tasks/timestamp.cxx | 68 +++++-- Analysis/Tutorials/src/ccdbaccess.cxx | 1 - 9 files changed, 51 insertions(+), 440 deletions(-) delete mode 100644 Analysis/Core/include/Analysis/RunToTimestamp.h delete mode 100644 Analysis/Core/src/InsertNewRunToTimestamp.cxx delete mode 100644 Analysis/Core/src/RunToTimestamp.cxx delete mode 100755 Analysis/Scripts/insert_Run2_run_to_timestamps.py delete mode 100755 Analysis/Scripts/inspect_Run2_run_to_timestamps.py 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/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 <map> -#include <Rtypes.h> - -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<unsigned int, long> mMap; - ClassDefNV(RunToTimestamp, 1) // converter class between run number and timestamp -}; - -#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 <boost/program_options.hpp> -#include <FairLogger.h> - -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<unsigned int>()->required(), "Run number to use")( - "timestamp,t", bpo::value<long>()->required(), "Timestamp to use equivalent to the run number")( - "path,p", bpo::value<std::string>()->default_value("Analysis/Core/RunToTimestamp"), "Path to the object in the CCDB repository")( - "url,u", bpo::value<std::string>()->default_value("http://ccdb-test.cern.ch:8080"), "URL of the CCDB database")( - "start,s", bpo::value<long>()->default_value(0), "Start timestamp of object validity")( - "stop,S", bpo::value<long>()->default_value(4108971600000), "Stop timestamp of object validity")( - "update,u", bpo::value<int>()->default_value(0), "Flag to update the object instead of inserting the new timestamp")( - "delete_previous,d", bpo::value<int>()->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<int>()->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<std::string>(); - 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::string>(); - std::map<std::string, std::string> metadata; - std::map<std::string, std::string>* headers; - long start = vm["start"].as<long>(); - long stop = vm["stop"].as<long>(); - - RunToTimestamp* converter = api.retrieveFromTFileAny<RunToTimestamp>(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<int>()) { - api.truncate(path); - } - - if (vm["update"].as<int>()) - converter->update(vm["run"].as<unsigned int>(), vm["timestamp"].as<long>()); - else - converter->insert(vm["run"].as<unsigned int>(), vm["timestamp"].as<long>()); - - if (vm["verbose"].as<int>()) - 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 <FairLogger.h> - -ClassImp(RunToTimestamp); - -bool RunToTimestamp::insert(unsigned int runNumber, long timestamp) -{ - std::pair<std::map<unsigned int, long>::iterator, bool> check; - check = mMap.insert(std::pair<unsigned int, long>(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/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/timestamp.cxx b/Analysis/Tasks/timestamp.cxx index 496baa443bc1a..83708c8681ddc 100644 --- a/Analysis/Tasks/timestamp.cxx +++ b/Analysis/Tasks/timestamp.cxx @@ -10,55 +10,89 @@ // // 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 <CCDB/BasicCCDBManager.h> #include "CommonDataFormat/InteractionRecord.h" #include "DetectorsRaw/HBFUtils.h" #include <map> + using namespace o2::framework; using namespace o2::header; using namespace o2; struct TimestampTask { - Produces<aod::Timestamps> ts_table; - RunToTimestamp* converter = nullptr; - std::map<int, int>* mapStartOrbit = nullptr; - Service<o2::ccdb::BasicCCDBManager> ccdb; - Configurable<std::string> path{"ccdb-path", "Analysis/Core/RunToTimestamp", "path to the ccdb object"}; - Configurable<long> timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + Produces<aod::Timestamps> ts_table; /// Table with SOR timestamps produced by the task + Service<o2::ccdb::BasicCCDBManager> ccdb; /// Object manager in CCDB + o2::ccdb::CcdbApi api; /// API to access CCDB + std::map<int, int>* mapStartOrbit = nullptr; /// Map of the starting orbit for the run + std::pair<int, long> lastCall; /// Last run number processed and its timestamp, needed for caching + std::map<int, long> mapRunToTimestamp; /// Cache of processed run numbers + + // Configurables + Configurable<bool> verbose{"verbose", false, "verbose mode"}; + Configurable<std::string> path{"ccdb-path", "RCT/RunInformation/", "path to the ccdb object"}; + Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "URL of the CCDB database"}; void init(o2::framework::InitContext&) { LOGF(info, "Initializing TimestampTask"); - converter = ccdb->get<RunToTimestamp>(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<std::map<int, int>>("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()); + 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<std::string, std::string> 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<std::map<int, long>::iterator, bool> check; + check = mapRunToTimestamp.insert(std::pair<int, long>(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 currentBC = bc.globalBC() % o2::constants::lhc::LHCMaxBunches; uint32_t currentOrbit = bc.globalBC() / o2::constants::lhc::LHCMaxBunches; uint16_t initialBC = 0; // exact bc number not relevant due to ms precision of timestamps uint32_t initialOrbit = mapStartOrbit->at(bc.runNumber()); 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/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 <CCDB/BasicCCDBManager.h> #include "CommonDataFormat/InteractionRecord.h" From f434bc728223f8b91d64332778488634379ef55f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 9 Sep 2020 01:20:03 +0200 Subject: [PATCH 0585/1751] Base class for compact index with provenance and flags info --- DataFormats/common/CMakeLists.txt | 3 +- .../include/CommonDataFormat/AbstractRef.h | 82 +++++++++++++++++++ .../common/src/CommonDataFormatLinkDef.h | 2 + 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 DataFormats/common/include/CommonDataFormat/AbstractRef.h 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 <Rtypes.h> + +namespace o2 +{ +namespace dataformats +{ + +template <int NBIdx, int NBSrc, int NBFlg> +class AbstractRef +{ + template <int NBIT> + 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<NBIdx + NBSrc + NBFlg>()); + using Idx_t = decltype(AbstractRef::MVAR<NBIdx>()); + using Src_t = decltype(AbstractRef::MVAR<NBSrc>()); + using Flg_t = decltype(AbstractRef::MVAR<NBFlg>()); + + 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<Idx_t>(mRef & IdxMask); } + void setIndex(Idx_t idx) { mRef = (mRef & (BaseMask & ~IdxMask)) | (IdxMask & idx); } + + // + Src_t getSource() const { return static_cast<Idx_t>((mRef >> NBIdx) & SrcMask); } + void setSource(Src_t src) { mRef = (mRef & (BaseMask & ~(SrcMask << NBIdx))) | ((SrcMask & src) << NBIdx); } + + // + Flg_t getFlags() const { return static_cast<Flg_t>((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/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 From b7a2f3ea2006e8e4bab716c41a6703866784eb6f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 9 Sep 2020 01:20:25 +0200 Subject: [PATCH 0586/1751] Global track index for vertex->track reference --- DataFormats/Reconstruction/CMakeLists.txt | 4 +- .../ReconstructionDataFormats/VtxTrackIndex.h | 51 +++++++++++++++++++ .../src/ReconstructionDataFormatsLinkDef.h | 3 ++ .../Reconstruction/src/VtxTrackIndex.cxx | 39 ++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h create mode 100644 DataFormats/Reconstruction/src/VtxTrackIndex.cxx 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/VtxTrackIndex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h new file mode 100644 index 0000000000000..0088c489e574f --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h @@ -0,0 +1,51 @@ +// 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 "CommonDataFormat/AbstractRef.h" +#include <iosfwd> +#include <string> + +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 + Attached, // flag that it is attached w/o contributing + 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 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 <fmt/printf.h> +#include <iostream> +#include <bitset> + +using namespace o2::dataformats; + +std::string VtxTrackIndex::asString() const +{ + std::bitset<NBitsFlags()> 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(); +} From 0440ac25534a2f28a2ab560d9cc82f57adb8f3d8 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen <evgeny.kryshen@cern.ch> Date: Wed, 9 Sep 2020 20:25:43 +0200 Subject: [PATCH 0587/1751] Event selection adapted to MC (#4319) --- Analysis/Tasks/eventSelection.cxx | 7 +++++++ Analysis/Tasks/eventSelectionQa.cxx | 4 +++- Analysis/Tasks/timestamp.cxx | 5 +++-- 3 files changed, 13 insertions(+), 3 deletions(-) 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<aod::EvSels> evsel; Service<o2::ccdb::BasicCCDBManager> ccdb; + Configurable<bool> 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<TH1F> hTimeFDAacc{TH1F("hTimeFDAacc", "", 1000, -100., 100.)}; OutputObj<TH1F> hTimeFDCacc{TH1F("hTimeFDCacc", "", 1000, -100., 100.)}; + Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; + void process(soa::Join<aod::Collisions, aod::EvSels>::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 83708c8681ddc..79d823ed5e21b 100644 --- a/Analysis/Tasks/timestamp.cxx +++ b/Analysis/Tasks/timestamp.cxx @@ -37,6 +37,7 @@ struct TimestampTask { Configurable<bool> verbose{"verbose", false, "verbose mode"}; Configurable<std::string> path{"ccdb-path", "RCT/RunInformation/", "path to the ccdb object"}; Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "URL of the CCDB database"}; + Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; void init(o2::framework::InitContext&) { @@ -85,10 +86,10 @@ struct TimestampTask { if (verbose.value) { LOGF(info, "Run-number to timestamp found! %i %llu ms", bc.runNumber(), ts); } - uint16_t currentBC = bc.globalBC() % o2::constants::lhc::LHCMaxBunches; - uint32_t currentOrbit = bc.globalBC() / o2::constants::lhc::LHCMaxBunches; 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); ts += (current - initial).bc2ns() / 1000000; From ef09f9f23ffab8606877f937c205be72e4398d43 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 9 Sep 2020 11:26:14 +0200 Subject: [PATCH 0588/1751] DPL Analysis: move ROOT helpers in a separate file --- .../Core/include/Framework/AnalysisHelpers.h | 19 ----------- .../include/Framework/RootAnalysisHelpers.h | 32 +++++++++++++++++++ Framework/TestWorkflows/src/o2D0Analysis.cxx | 1 + .../src/o2SimpleTracksAnalysis.cxx | 1 + 4 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 Framework/Core/include/Framework/RootAnalysisHelpers.h diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 8d4c3c03b77fd..9a62b86cac9da 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -529,23 +529,4 @@ struct Partition { } // namespace o2::framework -namespace o2 -{ -namespace analysis -{ - -/// Do a single loop on all the entries of the @a input table -ROOT::RDataFrame doSingleLoopOn(std::unique_ptr<framework::TableConsumer>& 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 `<name>_` while the entries for the inner loop are prefixed with -/// `<name>bar_`. -ROOT::RDataFrame doSelfCombinationsWith(std::unique_ptr<framework::TableConsumer>& input, - std::string name = "p", - std::string grouping = "eventID"); - -} // namespace analysis -} // namespace o2 - #endif // o2_framework_AnalysisHelpers_H_DEFINED 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 <ROOT/RDataFrame.hxx> + +namespace o2::analysis +{ + +/// Do a single loop on all the entries of the @a input table +ROOT::RDataFrame doSingleLoopOn(std::unique_ptr<framework::TableConsumer>& 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 `<name>_` while the entries for the inner loop are prefixed with +/// `<name>bar_`. +ROOT::RDataFrame doSelfCombinationsWith(std::unique_ptr<framework::TableConsumer>& input, + std::string name = "p", + std::string grouping = "eventID"); + +} // namespace o2::analysis + +#endif // O2_FRAMEWORK_ROOTANALYSISHELPERS_H_ 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 <ROOT/RDataFrame.hxx> diff --git a/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx b/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx index f19c808aa221b..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" From c31bffd923a4fd35cd1e92fff5d5a08db9f17e30 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 9 Sep 2020 16:08:48 +0200 Subject: [PATCH 0589/1751] Fix: protection for processing empty sector --- GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx | 3 +++ 1 file changed, 3 insertions(+) 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<GPUTPCCFChargeMapFiller::findFragm GPUd() size_t GPUTPCCFChargeMapFiller::findTransition(int time, const tpc::Digit* digits, size_t nDigits, size_t lower) { + if (!nDigits) { + return 0; + } size_t upper = nDigits - 1; while (lower <= upper) { From f8aa1864a2523d7dc4b2b8ac1010e29a74e748cf Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 10 Sep 2020 08:21:26 +0200 Subject: [PATCH 0590/1751] DPL Foundation: speedup has_type_at (#4315) Use multiple inheritance rather than recursion to speedup compilation and hopefully reduce memory usage. --- Framework/Core/include/Framework/ASoA.h | 4 +-- .../Core/include/Framework/AnalysisHelpers.h | 10 +++--- .../Core/include/Framework/AnalysisTask.h | 28 +++++++-------- Framework/Foundation/include/Framework/Pack.h | 36 +++++++++++++++++++ 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index a059aa12abc21..01073b2ed94df 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -629,7 +629,7 @@ struct RowViewCore : public IP, C... { RowViewCore(arrow::ChunkedArray* columnData[sizeof...(C)], IP&& policy) : IP{policy}, - C(columnData[framework::has_type_at<C>(all_columns{})])... + C(columnData[framework::has_type_at_v<C>(all_columns{})])... { bindIterators(persistent_columns_t{}); bindAllDynamicColumns(dynamic_columns_t{}); @@ -862,7 +862,7 @@ class Table auto getId() const { if constexpr (framework::has_type_v<std::decay_t<TI>, bindings_pack_t>) { - constexpr auto idx = framework::has_type_at<std::decay_t<TI>>(bindings_pack_t{}); + constexpr auto idx = framework::has_type_at_v<std::decay_t<TI>>(bindings_pack_t{}); return framework::pack_element_t<idx, external_index_columns_t>::getId(); } else if constexpr (std::is_same_v<std::decay_t<TI>, Parent>) { return this->globalIndex(); diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 9a62b86cac9da..8b1e5ca59026b 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -219,7 +219,7 @@ struct IndexExclusive { int32_t idx = -1; auto setValue = [&](auto& x) -> bool { using type = std::decay_t<decltype(x)>; - constexpr auto position = framework::has_type_at<type>(rest_it_t{}); + constexpr auto position = framework::has_type_at_v<type>(rest_it_t{}); lowerBound<Key>(idx, x); if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { @@ -248,12 +248,12 @@ struct IndexExclusive { auto result = std::apply( [&](auto&... x) { std::array<bool, sizeof...(T)> results{setValue(x)...}; - return (results[framework::has_type_at<std::decay_t<decltype(x)>>(rest_it_t{})] && ...); + return (results[framework::has_type_at_v<std::decay_t<decltype(x)>>(rest_it_t{})] && ...); }, iterators); if (result) { - cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); + cursor(0, row.globalIndex(), values[framework::has_type_at_v<T>(tables_t{})]...); } } return builder.finalize(); @@ -285,7 +285,7 @@ struct IndexSparse { int32_t idx = -1; auto setValue = [&](auto& x) -> bool { using type = std::decay_t<decltype(x)>; - constexpr auto position = framework::has_type_at<type>(rest_it_t{}); + constexpr auto position = framework::has_type_at_v<type>(rest_it_t{}); lowerBound<Key>(idx, x); if (x == soa::RowViewSentinel{static_cast<uint64_t>(x.mMaxRow)}) { @@ -310,7 +310,7 @@ struct IndexSparse { }, iterators); - cursor(0, row.globalIndex(), values[framework::has_type_at<T>(tables_t{})]...); + cursor(0, row.globalIndex(), values[framework::has_type_at_v<T>(tables_t{})]...); } return builder.finalize(); } diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 9c83d8ee38763..762a97c00cb91 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -67,15 +67,15 @@ struct AnalysisDataProcessorBuilder { (doAppendInputWithMetadata<Args>(inputs), ...); } - template <typename T, size_t At> - static void appendSomethingWithMetadata(std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos) + template <typename T> + static void appendSomethingWithMetadata(std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos, size_t at) { using dT = std::decay_t<T>; if constexpr (framework::is_specialization<dT, soa::Filtered>::value) { - 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}); } else if constexpr (soa::is_soa_iterator_t<dT>::value) { if constexpr (std::is_same_v<typename dT::policy_t, soa::FilteredIndexPolicy>) { - 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<dT>(), inputs); @@ -84,7 +84,7 @@ struct AnalysisDataProcessorBuilder { template <typename R, typename C, typename... Args> static void inputsFromArgs(R (C::*)(Args...), std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos) { - (appendSomethingWithMetadata<Args, has_type_at<Args>(pack<Args...>{})>(inputs, eInfos), ...); + (appendSomethingWithMetadata<Args>(inputs, eInfos, o2::framework::has_type_at_v<Args>(pack<Args...>{})), ...); } template <typename R, typename C, typename Grouping, typename... Args> @@ -96,7 +96,7 @@ struct AnalysisDataProcessorBuilder { template <typename R, typename C, typename Grouping, typename... Args> static auto bindGroupingTable(InputRecord& record, R (C::*)(Grouping, Args...), std::vector<ExpressionInfo> const& infos) { - return extractSomethingFromRecord<Grouping, 0>(record, infos); + return extractSomethingFromRecord<Grouping>(record, infos, 0); } template <typename R, typename C> @@ -137,20 +137,20 @@ struct AnalysisDataProcessorBuilder { } } - template <typename T, size_t At> - static auto extractSomethingFromRecord(InputRecord& record, std::vector<ExpressionInfo> const infos) + template <typename T> + static auto extractSomethingFromRecord(InputRecord& record, std::vector<ExpressionInfo> const infos, size_t at) { using decayed = std::decay_t<T>; if constexpr (soa::is_soa_filtered_t<decayed>::value) { for (auto& info : infos) { - if (info.index == At) + if (info.index == at) return extractFilteredFromRecord<decayed>(record, info, soa::make_originals_from_type<decayed>()); } } else if constexpr (soa::is_soa_iterator_t<decayed>::value) { if constexpr (std::is_same_v<typename decayed::policy_t, soa::FilteredIndexPolicy>) { for (auto& info : infos) { - if (info.index == At) + if (info.index == at) return extractFilteredFromRecord<decayed>(record, info, soa::make_originals_from_type<decayed>()); } } else { @@ -165,7 +165,7 @@ struct AnalysisDataProcessorBuilder { template <typename R, typename C, typename Grouping, typename... Args> static auto bindAssociatedTables(InputRecord& record, R (C::*)(Grouping, Args...), std::vector<ExpressionInfo> const infos) { - return std::make_tuple(extractSomethingFromRecord<Args, has_type_at<Args>(pack<Args...>{}) + 1u>(record, infos)...); + return std::make_tuple(extractSomethingFromRecord<Args>(record, infos, has_type_at_v<Args>(pack<Args...>{}) + 1u)...); } template <typename R, typename C> @@ -236,7 +236,7 @@ struct AnalysisDataProcessorBuilder { /// auto splitter = [&](auto&& x) { using xt = std::decay_t<decltype(x)>; - constexpr auto index = framework::has_type_at<std::decay_t<decltype(x)>>(associated_pack_t{}); + constexpr auto index = framework::has_type_at_v<std::decay_t<decltype(x)>>(associated_pack_t{}); if (hasIndexTo<std::decay_t<G>>(typename xt::persistent_columns_t{})) { auto result = o2::framework::sliceByColumn(indexColumnName.c_str(), x.asArrowTable(), @@ -261,7 +261,7 @@ struct AnalysisDataProcessorBuilder { auto extractor = [&](auto&& x) { using xt = std::decay_t<decltype(x)>; if constexpr (soa::is_soa_filtered_t<xt>::value) { - constexpr auto index = framework::has_type_at<std::decay_t<decltype(x)>>(associated_pack_t{}); + constexpr auto index = framework::has_type_at_v<std::decay_t<decltype(x)>>(associated_pack_t{}); selections[index] = &x.getSelectedRows(); starts[index] = selections[index]->begin(); offsets[index].push_back(std::get<xt>(at).tableSize()); @@ -341,7 +341,7 @@ struct AnalysisDataProcessorBuilder { template <typename A1> auto prepareArgument() { - constexpr auto index = framework::has_type_at<A1>(associated_pack_t{}); + constexpr auto index = framework::has_type_at_v<A1>(associated_pack_t{}); if (hasIndexTo<G>(typename std::decay_t<A1>::persistent_columns_t{})) { uint64_t pos; if constexpr (soa::is_soa_filtered_t<std::decay_t<G>>::value) { diff --git a/Framework/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index 8e0badcdff474..0b97e72bd6feb 100644 --- a/Framework/Foundation/include/Framework/Pack.h +++ b/Framework/Foundation/include/Framework/Pack.h @@ -161,6 +161,42 @@ constexpr size_t has_type_at(pack<T1, Ts...> const&) return sizeof...(Ts) + 2; } +namespace +{ +template <std::size_t I, typename T> +struct indexed { + using type = T; + constexpr static std::size_t index = I; +}; + +template <typename Is, typename... Ts> +struct indexer; + +template <std::size_t... Is, typename... Ts> +struct indexer<std::index_sequence<Is...>, Ts...> + : indexed<Is, Ts>... { +}; + +template <typename T, std::size_t I> +indexed<I, T> select(indexed<I, T>); + +template <typename W, typename... Ts> +constexpr std::size_t has_type_at_t = decltype(select<W>( + indexer<std::index_sequence_for<Ts...>, Ts...>{}))::index; +} // namespace + +template <typename W> +constexpr std::size_t has_type_at_v(o2::framework::pack<> p) +{ + return -1; +} + +template <typename W, typename... Ts> +constexpr std::size_t has_type_at_v(o2::framework::pack<Ts...> p) +{ + return has_type_at_t<W, Ts...>; +} + /// Intersect two packs template <typename S1, typename S2> struct intersect_pack { From 35989058846eae53014a67cec80f215391e6d7e8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 10 Sep 2020 14:49:37 +0200 Subject: [PATCH 0591/1751] DPL: hide a few more headers (#4310) --- .../Core/include/Framework/BoostOptionsRetriever.h | 12 ++++++++++-- .../include/Framework/ChannelConfigurationPolicy.h | 2 +- Framework/Core/include/Framework/runDataProcessing.h | 4 ---- Framework/Core/src/BoostOptionsRetriever.cxx | 9 +++++---- Framework/Core/src/DriverInfo.h | 2 ++ 5 files changed, 18 insertions(+), 11 deletions(-) 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 <boost/property_tree/ptree_fwd.hpp> -#include <boost/program_options/options_description.hpp> +#include <memory> #include <vector> +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<boost::program_options::options_description> 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 <vector> #include <functional> namespace o2 diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index d4807a782b646..3bed257a41fe4 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -13,7 +13,6 @@ #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" @@ -22,9 +21,6 @@ #include "Framework/CommonServices.h" #include "Framework/Logger.h" -#include <boost/program_options/options_description.hpp> -#include <boost/program_options/variables_map.hpp> - #include <unistd.h> #include <vector> #include <cstring> 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 <boost/program_options.hpp> +#include <boost/program_options/options_description.hpp> #include <string> #include <vector> @@ -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<boost::program_options::options_description>("ALICE O2 Framework - Available options")}, mIgnoreUnknown{ignoreUnknown}, mArgc{argc}, mArgv{argv} @@ -39,7 +40,7 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> 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<ConfigParamSpec> 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/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 From e2c74a2409f76fdf4c4d953a318cdde7a800b8ec Mon Sep 17 00:00:00 2001 From: dstocco <dstocco@users.noreply.github.com> Date: Fri, 11 Sep 2020 10:11:35 +0200 Subject: [PATCH 0592/1751] Use the new raw data decoders in the checks (#4321) Use the new raw data decoders in the checks - Move checkers to a dedicated directory - Use a lighter raw file reader - Improve the raw dumper, allowing to dump the decoded data on demand --- Detectors/MUON/MID/CMakeLists.txt | 1 + Detectors/MUON/MID/QC/CMakeLists.txt | 16 + Detectors/MUON/MID/QC/exe/CMakeLists.txt | 15 + Detectors/MUON/MID/QC/exe/README.md | 46 ++ Detectors/MUON/MID/QC/exe/raw-checker.cxx | 190 +++++++ .../MID/QC/include/MIDQC/GBTRawDataChecker.h | 108 ++++ .../MID/QC/include/MIDQC/RawDataChecker.h | 52 ++ .../MUON/MID/QC/src/GBTRawDataChecker.cxx | 511 ++++++++++++++++++ Detectors/MUON/MID/QC/src/RawDataChecker.cxx | 96 ++++ Detectors/MUON/MID/README.md | 1 + Detectors/MUON/MID/Raw/CMakeLists.txt | 2 - Detectors/MUON/MID/Raw/exe/CMakeLists.txt | 8 +- .../MUON/MID/Raw/exe/CRUBareDataChecker.cxx | 199 ------- .../MUON/MID/Raw/exe/CRUBareDataChecker.h | 56 -- Detectors/MUON/MID/Raw/exe/README.md | 32 +- .../MUON/MID/Raw/exe/mid-raw-checker.cxx | 139 ----- Detectors/MUON/MID/Raw/exe/mid-rawdump.cxx | 95 ---- Detectors/MUON/MID/Raw/exe/rawdump.cxx | 188 +++++++ .../MID/Raw/include/MIDRaw/CRUBareDecoder.h | 68 --- .../MUON/MID/Raw/include/MIDRaw/RawBuffer.h | 72 --- .../MID/Raw/include/MIDRaw/RawFileReader.h | 28 +- .../MUON/MID/Raw/include/MIDRaw/RawUnit.h | 43 -- Detectors/MUON/MID/Raw/src/CRUBareDecoder.cxx | 152 ------ Detectors/MUON/MID/Raw/src/RawBuffer.cxx | 181 ------- Detectors/MUON/MID/Raw/src/RawFileReader.cxx | 104 +--- 25 files changed, 1264 insertions(+), 1139 deletions(-) create mode 100644 Detectors/MUON/MID/QC/CMakeLists.txt create mode 100644 Detectors/MUON/MID/QC/exe/CMakeLists.txt create mode 100644 Detectors/MUON/MID/QC/exe/README.md create mode 100644 Detectors/MUON/MID/QC/exe/raw-checker.cxx create mode 100644 Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h create mode 100644 Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h create mode 100644 Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx create mode 100644 Detectors/MUON/MID/QC/src/RawDataChecker.cxx delete mode 100644 Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.cxx delete mode 100644 Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.h delete mode 100644 Detectors/MUON/MID/Raw/exe/mid-raw-checker.cxx delete mode 100644 Detectors/MUON/MID/Raw/exe/mid-rawdump.cxx create mode 100644 Detectors/MUON/MID/Raw/exe/rawdump.cxx delete mode 100644 Detectors/MUON/MID/Raw/include/MIDRaw/CRUBareDecoder.h delete mode 100644 Detectors/MUON/MID/Raw/include/MIDRaw/RawBuffer.h delete mode 100644 Detectors/MUON/MID/Raw/include/MIDRaw/RawUnit.h delete mode 100644 Detectors/MUON/MID/Raw/src/CRUBareDecoder.cxx delete mode 100644 Detectors/MUON/MID/Raw/src/RawBuffer.cxx diff --git a/Detectors/MUON/MID/CMakeLists.txt b/Detectors/MUON/MID/CMakeLists.txt index 8615904d2a6b8..f36641cb8592d 100644 --- a/Detectors/MUON/MID/CMakeLists.txt +++ b/Detectors/MUON/MID/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(Base) add_subdirectory(Clustering) +add_subdirectory(QC) add_subdirectory(Raw) add_subdirectory(Simulation) add_subdirectory(TestingSimTools) diff --git a/Detectors/MUON/MID/QC/CMakeLists.txt b/Detectors/MUON/MID/QC/CMakeLists.txt new file mode 100644 index 0000000000000..d7440379f2571 --- /dev/null +++ b/Detectors/MUON/MID/QC/CMakeLists.txt @@ -0,0 +1,16 @@ +# 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_library( + MIDQC + SOURCES src/GBTRawDataChecker.cxx src/RawDataChecker.cxx + PUBLIC_LINK_LIBRARIES ms_gsl::ms_gsl O2::MIDRaw) + +add_subdirectory(exe) diff --git a/Detectors/MUON/MID/QC/exe/CMakeLists.txt b/Detectors/MUON/MID/QC/exe/CMakeLists.txt new file mode 100644 index 0000000000000..87be3a2e49bbf --- /dev/null +++ b/Detectors/MUON/MID/QC/exe/CMakeLists.txt @@ -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. + +o2_add_executable( + raw-checker + COMPONENT_NAME mid + SOURCES raw-checker.cxx + PUBLIC_LINK_LIBRARIES O2::MIDQC) diff --git a/Detectors/MUON/MID/QC/exe/README.md b/Detectors/MUON/MID/QC/exe/README.md new file mode 100644 index 0000000000000..05068536f3268 --- /dev/null +++ b/Detectors/MUON/MID/QC/exe/README.md @@ -0,0 +1,46 @@ +<!-- doxy +\page refMUONMIDQCExe MID QC executable +/doxy --> + +# Checkers for MID RAW data +This directory contains executable code to verify the raw data. +This is particularly important for testing and debugging the MID read-out. + +## MID raw file checker +This utility allows to test files produced by the CRU w/o using the User Logic. +Basic usage: +```bash +o2-mid-raw-checker --feeId-config-file feeId_filename filename [filename_2 filename_3 ...] +``` +The `feeId_filename` is a file allowing to tell which feeId is readout by the configured GBT. +The file should be in the form explained [here](../../Raw/README.md) + +The output is a file (or a series of files if a list of inputs is provided), named after the input file as `check_filename.txt`, so that it is easy to understand to which input file the output is referring to. +The different e-links are read out and then grouped according to their interaction record. +The output file contains: +- a list of possible problems (if any) for each event processed +- a summary with the number of faulty events + +The list of problems is provided per interaction record. +This should be unique, but it is not always the case, since it can happen that either the decoded local clock information is wrong, or some reset is performed and the same interaction record is repeated. +The data corresponding to one interaction record can be found in different pages. Notice that this also happens for a perfectly good event in case the information does not fit inside the maximum page size. +For debugging purposes, we try to keep track of the page (HB) where the data corresponding to the interaction record were found. +This is rather accurate, although sometimes the data can be found in the preceding page. +We therefore print the interaction records and the corresponding pages (HB), together with the line in the file where the page start. +The line is counted assuming that one reads the file as a series of 4 words of 32 bits each (this is the typical way the binary file is converted into text during the tests). + +For a list of the other available options: +```bash +o2-mid-raw-checker --help +``` +### Performed checks +The decoded information is read HB per HB (multiple pages are read out when needed). +For each HB, the decoded information are gathered according to their interaction. +Notice that, in principle, events belonging to different HBs should have different interaction records, so one could in principle read the full file and then perform the check. +However, in the tests the RDH is not always correctly set, and the orbit number might not increase. That is why we read the HB one by one, and limit the tests to 1 HB at the time. This makes it easier to tag HBs with issues in the RO. +For each interaction record, a number of checks are performed: +- The number of local cards read must be compatible with the number of non-null cards provided by the regional cards. Notice that a mismatch can occur when the local board is busy (but does not correctly signal it) and we therefore get the regional info but not the corresponding local card. An incompatibility can also appear in case of corrupted data reading. +- The word describing the event (SOX, EOX, HC, Calibration, etc.) should be the same for all cards in the interaction record. +- The number of non-zero patterns read must match the information written in the corresponding word that indicates the non-zero detector planes. +- For each card we check that the information is consistent. For example we cannot have SOX and Calibration bits fired at the same time. Also, during an HC, we expect to have no chamber fired for the local boards. Notice that during tests this information is added by hand, so we should not have any issue by design. +- When the overwritten bit is fired, the readout data is actually filled with the masks. In this case we therefore check that the masks are as expected (i.e. they are compatible with the masks that are transmitted at the SOX) diff --git a/Detectors/MUON/MID/QC/exe/raw-checker.cxx b/Detectors/MUON/MID/QC/exe/raw-checker.cxx new file mode 100644 index 0000000000000..575f6a27c9504 --- /dev/null +++ b/Detectors/MUON/MID/QC/exe/raw-checker.cxx @@ -0,0 +1,190 @@ +// 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 MID/QC/exe/raw-checker.cxx +/// \brief Raw data checker for MID +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 09 December 2019 + +#include <iostream> +#include <fstream> +#include "boost/program_options.hpp" +#include "MIDRaw/FEEIdConfig.h" +#include "MIDRaw/CrateMasks.h" +#include "MIDRaw/Decoder.h" +#include "MIDRaw/RawFileReader.h" +#include "MIDQC/RawDataChecker.h" + +namespace po = boost::program_options; + +std::string getOutFilename(const char* inFilename, const char* outDir) +{ + std::string basename(inFilename); + std::string fdir = "./"; + auto pos = basename.find_last_of("/"); + if (pos != std::string::npos) { + basename.erase(0, pos + 1); + fdir = inFilename; + fdir.erase(pos); + } + basename.insert(0, "check_"); + basename += ".txt"; + std::string outputDir(outDir); + if (outputDir.empty()) { + outputDir = fdir; + } + if (outputDir.back() != '/') { + outputDir += "/"; + } + std::string outFilename = outputDir + basename; + return outFilename; +} + +template <typename GBTDECODER> +int process(po::variables_map& vm) +{ + std::vector<std::string> inputfiles{vm["input"].as<std::vector<std::string>>()}; + + o2::mid::Decoder<GBTDECODER> decoder; + o2::mid::RawDataChecker checker; + if (vm.count("feeId-config-file")) { + o2::mid::FEEIdConfig feeIdConfig(vm["feeId-config-file"].as<std::string>().c_str()); + decoder.setFeeIdConfig(feeIdConfig); + } + if (vm.count("crate-masks-file")) { + o2::mid::CrateMasks crateMasks(vm["crate-masks-file"].as<std::string>().c_str()); + decoder.setCrateMasks(crateMasks); + checker.init(crateMasks); + } else { + checker.init(o2::mid::CrateMasks()); + } + decoder.init(true); + + auto nHBs = vm["nHBs"].as<unsigned long int>(); + auto nMaxErrors = vm["max-errors"].as<unsigned long int>(); + + for (auto& filename : inputfiles) { + o2::mid::RawFileReader rawFileReader; + if (!rawFileReader.init(filename.c_str())) { + return 2; + } + if (vm.count("custom-memory-size")) { + rawFileReader.setCustomPayloadSize(vm["custom-memory-size"].as<uint16_t>()); + } + std::string outFilename = getOutFilename(filename.c_str(), vm["output-dir"].as<std::string>().c_str()); + std::ofstream outFile(outFilename.c_str()); + if (!outFile.is_open()) { + std::cout << "Error: cannot create " << outFilename << std::endl; + return 2; + } + std::cout << "Writing output to: " << outFilename << " ..." << std::endl; + + std::vector<o2::mid::LocalBoardRO> data; + std::vector<o2::mid::ROFRecord> rofRecords; + std::vector<o2::mid::ROFRecord> hbRecords; + + checker.clear(); + unsigned long int iHB = 0; + std::stringstream summary; + while (rawFileReader.readHB(vm.count("only-closed-HBs") > 0)) { + decoder.process(rawFileReader.getData()); + rawFileReader.clear(); + size_t offset = data.size(); + data.insert(data.end(), decoder.getData().begin(), decoder.getData().end()); + for (auto& rof : decoder.getROFRecords()) { + rofRecords.emplace_back(rof.interactionRecord, rof.eventType, rof.firstEntry + offset, rof.nEntries); + } + o2::InteractionRecord hb(0, iHB); + hbRecords.emplace_back(hb, o2::mid::EventType::Noise, offset, decoder.getData().size()); + ++iHB; + if ((nHBs > 0 && iHB >= nHBs)) { + break; + } + bool isComplete = true; //(vm.count("bare") && decoder.isComplete()); + // Partial check + if (isComplete) { + // The check assumes that we have all data corresponding to one event. + // However this might not be true since we read one HB at the time. + // So we must test that the event was fully read before running the check. + if (!checker.process(data, rofRecords, hbRecords)) { + outFile << checker.getDebugMessage() << "\n"; + } + data.clear(); + rofRecords.clear(); + hbRecords.clear(); + + if (checker.getNEventsFaulty() >= nMaxErrors) { + summary << "Too many errors found: abort check!\n"; + break; + } + } + } + // Check the remaining data + if (data.size() > 0 && !checker.process(data, rofRecords, hbRecords)) { + outFile << checker.getDebugMessage() << "\n"; + } + summary << "Number of busy raised: " << checker.getNBusyRaised() << "\n"; + summary << "Fraction of faulty events: " << checker.getNEventsFaulty() << " / " << checker.getNEventsProcessed() << " = " << static_cast<double>(checker.getNEventsFaulty()) / ((checker.getNEventsProcessed() > 0) ? static_cast<double>(checker.getNEventsProcessed()) : 1.) << "\n"; + outFile << summary.str(); + std::cout << summary.str(); + + outFile.close(); + } + + return 0; +} + +int main(int argc, char* argv[]) +{ + po::variables_map vm; + po::options_description generic("Generic options"); + + // clang-format off + generic.add_options() + ("help", "produce help message") + ("nHBs", po::value<unsigned long int>()->default_value(0),"Number of HBs read") + ("only-closed-HBs", po::value<bool>()->implicit_value(true),"Return only closed HBs") + ("custom-memory-size", po::value<uint16_t>()->implicit_value(0x2000 - 0x100),"Ignore read RDH. Use custom memory size") + ("max-errors", po::value<unsigned long int>()->default_value(10000),"Maximum number of errors before aborting") + ("feeId-config-file", po::value<std::string>(),"Filename with crate FEE ID correspondence") + ("crate-masks-file", po::value<std::string>(),"Filename with crate masks") + ("output-dir", po::value<std::string>()->default_value(""),"Output directory") + ("bare", po::value<bool>()->implicit_value(true),"Use bare decoder"); + + + po::options_description hidden("hidden options"); + hidden.add_options() + ("input", po::value<std::vector<std::string>>(),"Input filename"); + // clang-format on + + po::options_description cmdline; + cmdline.add(generic).add(hidden); + + po::positional_options_description pos; + pos.add("input", -1); + + po::store(po::command_line_parser(argc, argv).options(cmdline).positional(pos).run(), vm); + po::notify(vm); + + if (vm.count("help")) { + std::cout << "Usage: " << argv[0] << " <input_raw_filename> [input_raw_filename_1 ...]\n"; + std::cout << generic << std::endl; + return 2; + } + if (vm.count("input") == 0) { + std::cout << "no input file specified" << std::endl; + return 1; + } + + if (vm.count("bare")) { + return process<o2::mid::GBTBareDecoder>(vm); + } + return process<o2::mid::GBTUserLogicDecoder>(vm); +} diff --git a/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h b/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h new file mode 100644 index 0000000000000..6e25d85d787f6 --- /dev/null +++ b/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h @@ -0,0 +1,108 @@ +// 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 MIDQC/GBTRawDataChecker.h +/// \brief Class to check the raw data from a GBT link +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 28 April 2020 +#ifndef O2_MID_GBTRawDataChecker_H +#define O2_MID_GBTRawDataChecker_H + +#include <cstdint> +#include <map> +#include <string> +#include <tuple> +#include <vector> +#include <unordered_map> +#include <gsl/gsl> +#include "DataFormatsMID/ROFRecord.h" +#include "MIDRaw/LocalBoardRO.h" + +namespace o2 +{ +namespace mid +{ +class GBTRawDataChecker +{ + public: + void init(uint16_t feeId, uint8_t mask); + bool process(gsl::span<const LocalBoardRO> localBoards, gsl::span<const ROFRecord> rofRecords, gsl::span<const ROFRecord> pageRecords); + /// Gets the number of processed events + unsigned int getNEventsProcessed() const { return mStatistics[0]; } + /// Gets the number of faulty events + unsigned int getNEventsFaulty() const { return mStatistics[1]; } + /// Gets the number of busy raised + unsigned int getNBusyRaised() const { return mStatistics[2]; } + /// Gets the + std::string getDebugMessage() const { return mDebugMsg; } + void clear(); + + private: + struct Mask { + std::array<uint16_t, 4> patternsBP{}; /// Bending plane mask + std::array<uint16_t, 4> patternsNBP{}; /// Non-bending plane mask + }; + + struct GBT { + std::vector<LocalBoardRO> regs{}; /// Regional boards + std::vector<LocalBoardRO> locs{}; /// Local boards + std::vector<long int> pages{}; /// Pages information + }; + + struct BoardInfo { + LocalBoardRO board{}; + o2::InteractionRecord interactionRecord{}; + long int page{-1}; + }; + + void clearChecked(bool isTriggered, bool clearTrigEvents); + bool checkEvent(bool isTriggered, const std::vector<LocalBoardRO>& regs, const std::vector<LocalBoardRO>& locs); + bool checkEvents(bool isTriggered); + bool checkConsistency(const LocalBoardRO& board); + bool checkConsistency(const std::vector<LocalBoardRO>& boards); + bool checkMasks(const std::vector<LocalBoardRO>& locs); + bool checkLocalBoardSize(const LocalBoardRO& board); + bool checkLocalBoardSize(const std::vector<LocalBoardRO>& boards); + bool checkRegLocConsistency(const std::vector<LocalBoardRO>& regs, const std::vector<LocalBoardRO>& locs); + uint8_t getElinkId(const LocalBoardRO& board) const; + unsigned int getLastCompleteTrigEvent(); + bool isCompleteSelfTrigEvent(const o2::InteractionRecord& ir) const; + std::string printBoards(const std::vector<LocalBoardRO>& boards) const; + void sortEvents(bool isTriggered); + + std::string mEventDebugMsg{}; /// Debug message for the event + std::string mDebugMsg{}; /// Debug message + std::array<unsigned long int, 3> mStatistics{}; /// Processed events statistics + std::unordered_map<uint8_t, Mask> mMasks; /// Masks + uint8_t mCrateMask{0xFF}; /// Crate mask + uint16_t mFeeId{0}; /// FeeId + uint16_t mResetVal{0}; /// Reset value + + std::map<o2::InteractionRecord, uint16_t> mTrigEvents{}; ///! Index of triggered events + + std::unordered_map<uint8_t, bool> mBusyFlagTrig; /// Busy flag for triggered events + std::unordered_map<uint8_t, bool> mBusyFlagSelfTrig; /// Busy flag for self-triggered events + + std::unordered_map<uint8_t, std::vector<BoardInfo>> mBoardsTrig{}; ///! Boards with triggered events + std::unordered_map<uint8_t, std::vector<BoardInfo>> mBoardsSelfTrig{}; ///! Boards with self-triggered events + + std::map<o2::InteractionRecord, std::vector<std::pair<uint8_t, size_t>>> mOrderedIndexesTrig{}; ///! Ordered indexes for triggered boards + std::map<o2::InteractionRecord, std::vector<std::pair<uint8_t, size_t>>> mOrderedIndexesSelfTrig{}; ///! Ordered indexes for self-triggered boards + + std::unordered_map<uint8_t, size_t> mLastIndexTrig{}; ///! Last checked index for triggered boards + std::unordered_map<uint8_t, size_t> mLastIndexSelfTrig{}; ///! Last checked index for self-triggered boards + + o2::InteractionRecord mLastCompleteIRTrig{}; ///! Last complete IR for triggered boards + o2::InteractionRecord mLastCompleteIRSelfTrig{}; ///! Last complete IR for self-triggered boards +}; +} // namespace mid +} // namespace o2 + +#endif /* O2_MID_GBTRawDataChecker_H */ diff --git a/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h b/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h new file mode 100644 index 0000000000000..79e86091aecbc --- /dev/null +++ b/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h @@ -0,0 +1,52 @@ +// 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 MIDQC/RawDataChecker.h +/// \brief Class to check the raw data +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 9 December 2019 +#ifndef O2_MID_RAWDATACHECKER_H +#define O2_MID_RAWDATACHECKER_H + +#include <array> +#include <string> +#include <gsl/gsl> +#include "DataFormatsMID/ROFRecord.h" +#include "MIDRaw/CrateMasks.h" +#include "MIDRaw/LocalBoardRO.h" +#include "MIDQC/GBTRawDataChecker.h" + +namespace o2 +{ +namespace mid +{ +class RawDataChecker +{ + public: + void init(const CrateMasks& masks); + bool process(gsl::span<const LocalBoardRO> localBoards, gsl::span<const ROFRecord> rofRecords, gsl::span<const ROFRecord> pageRecords); + /// Gets the number of processed events + unsigned int getNEventsProcessed() const; + /// Gets the number of faulty events + unsigned int getNEventsFaulty() const; + /// Gets the number of busy raised + unsigned int getNBusyRaised() const; + /// Gets the debug message + std::string getDebugMessage() const { return mDebugMsg; } + void clear(); + + private: + std::array<GBTRawDataChecker, crateparams::sNGBTs> mCheckers{}; /// GBT raw data checker + std::string mDebugMsg{}; /// Debug message +}; +} // namespace mid +} // namespace o2 + +#endif /* O2_MID_RAWDATACHECKER_H */ diff --git a/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx b/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx new file mode 100644 index 0000000000000..5aa54a8f25309 --- /dev/null +++ b/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx @@ -0,0 +1,511 @@ +// 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 MID/QC/src/GBTRawDataChecker.cxx +/// \brief Class to check the raw data from a GBT link +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 28 April 2020 + +#include "MIDQC/GBTRawDataChecker.h" + +#include <sstream> +#include <fmt/format.h> +#include "MIDRaw/CrateParameters.h" + +namespace o2 +{ +namespace mid +{ + +void GBTRawDataChecker::init(uint16_t feeId, uint8_t mask) +{ + /// Initializer + mFeeId = feeId; + mCrateMask = mask; +} + +bool GBTRawDataChecker::checkLocalBoardSize(const LocalBoardRO& board) +{ + /// Checks that the board has the expected non-null patterns + + // This test only make sense when we have a self-trigger, + // since in this case we expect to have a variable number of non-zero pattern + // as indicated by the corresponding word. + for (int ich = 0; ich < 4; ++ich) { + bool isExpectedNull = (((board.firedChambers >> ich) & 0x1) == 0); + bool isNull = (board.patternsBP[ich] == 0 && board.patternsNBP[ich] == 0); + if (isExpectedNull != isNull) { + std::stringstream ss; + ss << "wrong size for local board:\n"; + ss << board << "\n"; + mEventDebugMsg += ss.str(); + return false; + } + } + return true; +} + +bool GBTRawDataChecker::checkLocalBoardSize(const std::vector<LocalBoardRO>& boards) +{ + /// Checks that the boards have the expected non-null patterns + for (auto& board : boards) { + if (!checkLocalBoardSize(board)) { + return false; + } + } + return true; +} + +bool GBTRawDataChecker::checkConsistency(const LocalBoardRO& board) +{ + /// Checks that the event information is consistent + + bool isSoxOrReset = board.triggerWord & (raw::sSOX | raw::sEOX | raw::sRESET); + bool isCalib = raw::isCalibration(board.triggerWord); + bool isPhys = board.triggerWord & raw::sPHY; + + if (isPhys) { + if (isCalib) { + mEventDebugMsg += "inconsistent trigger: calibration and physics trigger cannot be fired together\n"; + return false; + } + if (raw::isLoc(board.statusWord)) { + if (board.firedChambers) { + mEventDebugMsg += "inconsistent trigger: fired chambers should be 0\n"; + return false; + } + } + } + if (isSoxOrReset && (isCalib || isPhys)) { + mEventDebugMsg += "inconsistent trigger: cannot be SOX and calibration\n"; + return false; + } + + return true; +} + +bool GBTRawDataChecker::checkConsistency(const std::vector<LocalBoardRO>& boards) +{ + /// Checks that the event information is consistent + for (auto& board : boards) { + if (!checkConsistency(board)) { + std::stringstream ss; + ss << board << "\n"; + mEventDebugMsg += ss.str(); + return false; + } + } + return true; +} + +bool GBTRawDataChecker::checkMasks(const std::vector<LocalBoardRO>& locs) +{ + /// Checks the masks + for (auto loc : locs) { + // The board patterns coincide with the masks ("overwritten" mode) + if (loc.statusWord & raw::sOVERWRITTEN) { + auto maskItem = mMasks.find(loc.boardId); + for (int ich = 0; ich < 4; ++ich) { + uint16_t maskBP = 0; + uint16_t maskNBP = 0; + if (maskItem != mMasks.end()) { + maskBP = maskItem->second.patternsBP[ich]; + maskNBP = maskItem->second.patternsNBP[ich]; + } + if (maskBP != loc.patternsBP[ich] || maskNBP != loc.patternsNBP[ich]) { + std::stringstream ss; + ss << "Pattern is not compatible with mask for:\n"; + ss << loc << "\n"; + mEventDebugMsg += ss.str(); + return false; + } + } + } + } + return true; +} + +bool GBTRawDataChecker::checkRegLocConsistency(const std::vector<LocalBoardRO>& regs, const std::vector<LocalBoardRO>& locs) +{ + /// Checks consistency between local and regional info + uint8_t regFired{0}; + for (auto& reg : regs) { + uint8_t ireg = crateparams::getLocId(reg.boardId) % 2; + auto busyItem = mBusyFlagSelfTrig.find(8 + ireg); + if (reg.triggerWord == 0) { + // Self-triggered event: check the decision + regFired |= (reg.firedChambers << (4 * ireg)); + } else { + // Triggered event: all active boards must answer + regFired |= (mCrateMask & (0xF << (4 * ireg))); + } + } + uint8_t locFired{0}, locBusy{0}; + for (auto& loc : locs) { + auto linkId = getElinkId(loc); + uint8_t mask = (1 << linkId); + if (loc.triggerWord == 0) { + // Self-triggered event: check the decision + if (loc.firedChambers) { + locFired |= mask; + } + } else { + // Triggered event: all active boards must answer + locFired |= mask; + } + } + + // The XOR returns 1 in case of a difference + uint8_t problems = (regFired ^ locFired); + + if (problems) { + // It can be that a busy signal was raised by one of the board in previous events + // If the board is still busy it will not answer. + uint8_t busy{0}; + for (uint8_t iboard = 0; iboard < crateparams::sNELinksPerGBT; ++iboard) { + auto busyItem = mBusyFlagSelfTrig.find(iboard); + if (busyItem != mBusyFlagSelfTrig.end() && busyItem->second) { + busy |= (iboard < crateparams::sMaxNBoardsInLink) ? (1 << iboard) : (0xF << (4 * (iboard % 2))); + } + } + + if (problems & ~busy) { + std::stringstream ss; + ss << fmt::format("loc-reg inconsistency: fired locals ({:08b}) != expected from reg ({:08b});\n", locFired, regFired); + ss << printBoards(regs); + ss << printBoards(locs); + mEventDebugMsg += ss.str(); + return false; + } + } + return true; +} + +std::string GBTRawDataChecker::printBoards(const std::vector<LocalBoardRO>& boards) const +{ + /// Prints the boards + std::stringstream ss; + for (auto& board : boards) { + ss << board << "\n"; + } + return ss.str(); +} + +bool GBTRawDataChecker::checkEvent(bool isTriggered, const std::vector<LocalBoardRO>& regs, const std::vector<LocalBoardRO>& locs) +{ + /// Checks the cards belonging to the same BC + mEventDebugMsg.clear(); + if (!checkRegLocConsistency(regs, locs)) { + return false; + } + + if (!checkConsistency(regs) || !checkConsistency(locs)) { + return false; + } + + if (!isTriggered) { + if (!checkLocalBoardSize(locs)) { + return false; + } + + if (!checkMasks(locs)) { + return false; + } + } + + return true; +} + +uint8_t GBTRawDataChecker::getElinkId(const LocalBoardRO& board) const +{ + /// Returns the e-link ID + if (raw::isLoc(board.statusWord)) { + return board.boardId % 8; + } + return 8 + board.boardId % 8; +} + +void GBTRawDataChecker::clearChecked(bool isTriggered, bool clearTrigEvents) +{ + /// Clears the checked events + + auto& boards = isTriggered ? mBoardsTrig : mBoardsSelfTrig; + auto& lastIndexes = isTriggered ? mLastIndexTrig : mLastIndexSelfTrig; + // Create a new board map with the checked events stripped + std::unordered_map<uint8_t, std::vector<BoardInfo>> newBoards{}; + for (auto& lastIdxItem : lastIndexes) { + auto firstIdx = lastIdxItem.second + 1; + auto& boardVec = boards[lastIdxItem.first]; + if (firstIdx < boardVec.size()) { + auto& newVec = newBoards[lastIdxItem.first]; + newVec.insert(newVec.end(), boardVec.begin() + firstIdx, boardVec.end()); + } + } + boards.swap(newBoards); + + if (clearTrigEvents) { + // Clears the map with the processed triggers + auto& lastCompleteTrigIR = isTriggered ? mLastCompleteIRTrig : mLastCompleteIRSelfTrig; + auto low = mTrigEvents.begin(); + auto up = mTrigEvents.upper_bound(lastCompleteTrigIR); + mTrigEvents.erase(low, up); + } +} + +bool GBTRawDataChecker::isCompleteSelfTrigEvent(const o2::InteractionRecord& ir) const +{ + /// Checks if the self-triggered events are complete + + // The regional board information in self-triggered events is delayed + // compared to triggered events. + // So, we expect information from a previous orbit after having received an orbit trigger. + // Let us check that we have all boards with the same orbit + bool isIncluded = false; + for (uint8_t ireg = 8; ireg < 10; ++ireg) { + auto item = mBoardsSelfTrig.find(ireg); + if (item != mBoardsSelfTrig.end()) { + if (item->second.front().interactionRecord.orbit <= ir.orbit) { + isIncluded = true; + } + if (item->second.back().interactionRecord.orbit <= ir.orbit) { + return false; + } + } + } + return isIncluded; +} + +unsigned int GBTRawDataChecker::getLastCompleteTrigEvent() +{ + /// Checks if we have a triggered event with the information from all active boards + /// The function returns true if it finds a complete event + /// and it returns its interaction record as well. + + // The information for an event comes at different times for different boards, + // depending on the length of the self-triggered event for that board. + // So, before testing the consistency of the event, + // we must wait to have received the information from all boards. + // This can be checked in triggered events, since all boards should be present. + + unsigned int completeMask = 0; + + // Check if we have a triggered event with the information from all active boards + mLastCompleteIRSelfTrig = o2::InteractionRecord(); + uint16_t fullMask = (3 << 8) | mCrateMask; + auto trigEventIt = mTrigEvents.rbegin(); + auto end = mTrigEvents.rend(); + for (; trigEventIt != end; ++trigEventIt) { + if ((trigEventIt->second & fullMask) == fullMask) { + // The trigger events contain the unprocessed events for both triggered and self-triggered events + // These might not be synchronized (typically the latest complete self-triggered events lies behind) + // If the latest IR in memory is more recent than the current complete event found, + // then it means that we need to wait for more HBs. + if (mLastCompleteIRTrig.isDummy() || mLastCompleteIRTrig < trigEventIt->first) { + completeMask |= 1; + mLastCompleteIRTrig = trigEventIt->first; + } + auto trIt = trigEventIt; + while (trIt != end) { + if (isCompleteSelfTrigEvent(trIt->first)) { + completeMask |= (1 << 1); + mLastCompleteIRSelfTrig = trIt->first; + break; + } + ++trIt; + } + return completeMask; + } + } + + return completeMask; +} + +void GBTRawDataChecker::sortEvents(bool isTriggered) +{ + /// Sorts the event in time + auto& orderedIndexes = isTriggered ? mOrderedIndexesTrig : mOrderedIndexesSelfTrig; + auto& lastIndexes = isTriggered ? mLastIndexTrig : mLastIndexSelfTrig; + auto& boards = isTriggered ? mBoardsTrig : mBoardsSelfTrig; + auto& lastCompleteTrigEventIR = isTriggered ? mLastCompleteIRTrig : mLastCompleteIRSelfTrig; + orderedIndexes.clear(); + lastIndexes.clear(); + for (auto& boardItem : boards) { + size_t lastIdx = 0; + for (auto boardIt = boardItem.second.begin(), end = boardItem.second.end(); boardIt != end; ++boardIt) { + if (boardIt->interactionRecord > lastCompleteTrigEventIR) { + break; + } + lastIdx = std::distance(boardItem.second.begin(), boardIt); + orderedIndexes[boardIt->interactionRecord].emplace_back(boardItem.first, lastIdx); + } + lastIndexes[boardItem.first] = lastIdx; + } +} + +bool GBTRawDataChecker::checkEvents(bool isTriggered) +{ + /// Checks the events + bool isOk = true; + auto& boards = isTriggered ? mBoardsTrig : mBoardsSelfTrig; + auto& orderedIndexes = isTriggered ? mOrderedIndexesTrig : mOrderedIndexesSelfTrig; + auto& busyFlag = isTriggered ? mBusyFlagTrig : mBusyFlagSelfTrig; + // Loop on the event indexes + for (auto& evtIdxItem : orderedIndexes) { + // All of these boards have the same timestamp + GBT gbtEvent; + bool busyRaised = false; + for (auto& evtPair : evtIdxItem.second) { + auto& boardInfo = boards[evtPair.first][evtPair.second]; + uint8_t triggerId = boardInfo.board.triggerWord; + auto elinkId = getElinkId(boardInfo.board); + + bool isBusy = ((boardInfo.board.statusWord & raw::sREJECTING) != 0); + busyRaised |= isBusy; + busyFlag[elinkId] = isBusy; + if (isBusy && !isTriggered) { + // This is a special event that just signals a busy. + // Do not add the board to the events to be tested. + // Even because this event can have the same IR and triggerWord (0) of a self-triggered event + continue; + } + if (raw::isLoc(boardInfo.board.statusWord)) { + gbtEvent.locs.push_back(boardInfo.board); + } else { + gbtEvent.regs.push_back(boardInfo.board); + } + if (boardInfo.page >= 0) { + if (std::find(gbtEvent.pages.begin(), gbtEvent.pages.end(), boardInfo.page) == gbtEvent.pages.end()) { + gbtEvent.pages.push_back(boardInfo.page); + } + } + } + if (busyRaised && !isTriggered) { + ++mStatistics[2]; + } + ++mStatistics[0]; + if (!checkEvent(isTriggered, gbtEvent.regs, gbtEvent.locs)) { + std::stringstream ss; + ss << std::hex << std::showbase << evtIdxItem.first; + if (!gbtEvent.pages.empty()) { + ss << " [in"; + for (auto& page : gbtEvent.pages) { + ss << std::dec << " page: " << page << " (line: " << 512 * page + 1 << ") "; + } + ss << "]"; + } + ss << "\n"; + isOk = false; + ss << mEventDebugMsg << "\n"; + mDebugMsg += ss.str(); + ++mStatistics[1]; + } + } + + return isOk; +} + +bool GBTRawDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl::span<const ROFRecord> rofRecords, gsl::span<const ROFRecord> pageRecords) +{ + /// Checks the raw data + mDebugMsg.clear(); + + // Fill board information + for (auto rofIt = rofRecords.begin(); rofIt != rofRecords.end(); ++rofIt) { + for (auto locIt = localBoards.begin() + rofIt->firstEntry; locIt != localBoards.begin() + rofIt->firstEntry + rofIt->nEntries; ++locIt) { + // Find what page this event corresponds to. + // This is useful for debugging. + long int page = -1; + for (auto& rofPage : pageRecords) { + if (rofIt->firstEntry >= rofPage.firstEntry && rofIt->firstEntry < rofPage.firstEntry + rofPage.nEntries) { + page = rofPage.interactionRecord.orbit; + break; + } + } + + // Store the information per local board. + // The information should be already ordered in time + auto id = getElinkId(*locIt); + auto& elinkVec = (locIt->triggerWord == 0) ? mBoardsSelfTrig[id] : mBoardsTrig[id]; + elinkVec.push_back({*locIt, rofIt->interactionRecord, page}); + + if (locIt->triggerWord == 0) { + continue; + } + + // Keep track of the busy + if (locIt->statusWord & raw::sREJECTING) { + auto& selfVec = mBoardsSelfTrig[id]; + auto board = *locIt; + board.triggerWord = 0; + auto ir = rofIt->interactionRecord; + if (id >= crateparams::sMaxNBoardsInLink) { + uint16_t delayRegLocal = 6; + if (rofIt->interactionRecord.bc < delayRegLocal) { + ir -= (constants::lhc::LHCMaxBunches - mResetVal - 1); + } + ir -= delayRegLocal; + } + selfVec.push_back({*locIt, ir, page}); + } + + // Keep track of the orbit triggers + if (locIt->triggerWord & raw::sORB) { + mTrigEvents[rofIt->interactionRecord] |= (1 << id); + mResetVal = rofIt->interactionRecord.bc; + } + + // Compute the masks + if (locIt->triggerWord & raw::sSOX) { + if (raw::isLoc(locIt->statusWord)) { + auto maskItem = mMasks.find(locIt->boardId); + // Check if we have already a mask for this + if (maskItem == mMasks.end()) { + // If not, read the map + auto& mask = mMasks[locIt->boardId]; + for (int ich = 0; ich < 4; ++ich) { + mask.patternsBP[ich] = locIt->patternsBP[ich]; + mask.patternsNBP[ich] = locIt->patternsNBP[ich]; + } + } + } + } + } // loop on local boards + } // loop on ROF records + + auto completeMask = getLastCompleteTrigEvent(); + + bool isOk = true; + + if (completeMask & 0x1) { + sortEvents(true); + isOk &= checkEvents(true); + clearChecked(true, mBoardsSelfTrig.empty()); + } + + if (completeMask & 0x2) { + sortEvents(false); + isOk &= checkEvents(false); + clearChecked(false, true); + } + + return isOk; +} + +void GBTRawDataChecker::clear() +{ + /// Resets the masks and flags + mMasks.clear(); + mBusyFlagTrig.clear(); + mBusyFlagSelfTrig.clear(); + mStatistics.fill(0); +} + +} // namespace mid +} // namespace o2 diff --git a/Detectors/MUON/MID/QC/src/RawDataChecker.cxx b/Detectors/MUON/MID/QC/src/RawDataChecker.cxx new file mode 100644 index 0000000000000..9f622534d2a1e --- /dev/null +++ b/Detectors/MUON/MID/QC/src/RawDataChecker.cxx @@ -0,0 +1,96 @@ +// 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 MID/QC/src/RawDataChecker.cxx +/// \brief Class to check the raw data +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 9 December 2019 + +#include "MIDQC/RawDataChecker.h" + +#include <unordered_map> +#include "MIDRaw/CrateParameters.h" + +namespace o2 +{ +namespace mid +{ + +void RawDataChecker::init(const CrateMasks& crateMasks) +{ + /// Initializes the checkers + for (uint16_t igbt = 0; igbt < crateparams::sNGBTs; ++igbt) { + mCheckers[igbt].init(igbt, crateMasks.getMask(igbt)); + } +} + +bool RawDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl::span<const ROFRecord> rofRecords, gsl::span<const ROFRecord> pageRecords) +{ + /// Checks the raw data + + bool isOk = true; + mDebugMsg.clear(); + std::unordered_map<uint16_t, std::vector<ROFRecord>> rofs; + for (auto& rof : rofRecords) { + auto& loc = localBoards[rof.firstEntry]; + auto crateId = crateparams::getCrateId(loc.boardId); + auto linkId = crateparams::getGBTIdFromBoardInCrate(crateparams::getLocId(loc.boardId)); + auto feeId = crateparams::makeROId(crateId, linkId); + rofs[feeId].emplace_back(rof); + } + + for (auto& item : rofs) { + isOk &= mCheckers[item.first].process(localBoards, item.second, pageRecords); + mDebugMsg += mCheckers[item.first].getDebugMessage(); + } + + return isOk; +} + +unsigned int RawDataChecker::getNEventsProcessed() const +{ + /// Gets the number of processed events + unsigned int sum = 0; + for (auto& checker : mCheckers) { + sum += checker.getNEventsProcessed(); + } + return sum; +} + +unsigned int RawDataChecker::getNEventsFaulty() const +{ + /// Gets the number of faulty events + unsigned int sum = 0; + for (auto& checker : mCheckers) { + sum += checker.getNEventsFaulty(); + } + return sum; +} + +unsigned int RawDataChecker::getNBusyRaised() const +{ + /// Gets the number of busy raised + unsigned int sum = 0; + for (auto& checker : mCheckers) { + sum += checker.getNBusyRaised(); + } + return sum; +} + +void RawDataChecker::clear() +{ + /// Clears the statistics + for (auto& checker : mCheckers) { + checker.clear(); + } +} + +} // namespace mid +} // namespace o2 diff --git a/Detectors/MUON/MID/README.md b/Detectors/MUON/MID/README.md index 07a0b28aaefa1..1ac569734d269 100644 --- a/Detectors/MUON/MID/README.md +++ b/Detectors/MUON/MID/README.md @@ -8,6 +8,7 @@ This is a top page for the MID detector documentation. <!-- doxy * \subpage refMUONMIDClustering +* \subpage refMUONMIDQCExe * \subpage refMUONMIDRaw * \subpage refMUONMIDRawExe * \subpage refMUONMIDTracking diff --git a/Detectors/MUON/MID/Raw/CMakeLists.txt b/Detectors/MUON/MID/Raw/CMakeLists.txt index cfa1931853db8..8c63889365a96 100644 --- a/Detectors/MUON/MID/Raw/CMakeLists.txt +++ b/Detectors/MUON/MID/Raw/CMakeLists.txt @@ -13,7 +13,6 @@ o2_add_library( SOURCES src/ColumnDataToLocalBoard.cxx src/CrateMapper.cxx src/CrateMasks.cxx - src/CRUBareDecoder.cxx src/Decoder.cxx src/ELinkDecoder.cxx src/Encoder.cxx @@ -23,7 +22,6 @@ o2_add_library( src/GBTUserLogicDecoder.cxx src/GBTUserLogicEncoder.cxx src/LocalBoardRO.cxx - src/RawBuffer.cxx src/DecodedDataAggregator.cxx src/RawFileReader.cxx PUBLIC_LINK_LIBRARIES diff --git a/Detectors/MUON/MID/Raw/exe/CMakeLists.txt b/Detectors/MUON/MID/Raw/exe/CMakeLists.txt index c1255b85b24eb..cd2f0dabeda44 100644 --- a/Detectors/MUON/MID/Raw/exe/CMakeLists.txt +++ b/Detectors/MUON/MID/Raw/exe/CMakeLists.txt @@ -11,11 +11,5 @@ o2_add_executable( rawdump COMPONENT_NAME mid - SOURCES mid-rawdump.cxx - PUBLIC_LINK_LIBRARIES O2::MIDRaw) - -o2_add_executable( - raw-checker - COMPONENT_NAME mid - SOURCES mid-raw-checker.cxx CRUBareDataChecker.cxx + SOURCES rawdump.cxx PUBLIC_LINK_LIBRARIES O2::MIDRaw) diff --git a/Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.cxx b/Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.cxx deleted file mode 100644 index 77590341b759f..0000000000000 --- a/Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.cxx +++ /dev/null @@ -1,199 +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. - -/// \file CRUBareDataChecker.cxx -/// \brief Class to check the bare data from the CRU -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 9 December 2019 - -#include "CRUBareDataChecker.h" - -#include <array> -#include <sstream> - -namespace o2 -{ -namespace mid -{ - -bool CRUBareDataChecker::checkSameEventWord(const std::vector<LocalBoardRO>& boards, uint8_t refEventWord) const -{ - /// Checks the event word - for (auto loc : boards) { - if (loc.triggerWord != refEventWord) { - return false; - } - } - return true; -} - -bool CRUBareDataChecker::checkPatterns(const LocalBoardRO& board, uint8_t expected) const -{ - /// Checks that the board has the expected non-null patterns - uint8_t inputs = (expected > 0xF) ? board.firedChambers : expected; - for (int ich = 0; ich < 4; ++ich) { - bool isExpectedNull = (((inputs >> ich) & 0x1) == 0); - bool isNull = (board.patternsBP[ich] == 0 && board.patternsNBP[ich] == 0); - if (isExpectedNull != isNull) { - return false; - } - } - return true; -} - -bool CRUBareDataChecker::checkPatterns(const std::vector<LocalBoardRO>& boards, uint8_t expected) const -{ - /// Checks that the boards have the expected non-null patterns - for (auto& board : boards) { - if (!checkPatterns(board, expected)) { - return false; - } - } - return true; -} - -bool CRUBareDataChecker::checkConsistency(const LocalBoardRO& board) const -{ - /// Checks that the event information is consistent - - bool isSoxOrReset = board.triggerWord & 0xc2; - bool isCalib = raw::isCalibration(board.triggerWord); - bool isPhysOrHC = board.triggerWord & 0x5; - - if (isPhysOrHC) { - if (isCalib) { - return false; - } - if (raw::isLoc(board.statusWord)) { - if (board.firedChambers) { - return false; - } - } - } - if (isSoxOrReset && (isCalib || isPhysOrHC)) { - return false; - } - - return true; -} - -bool CRUBareDataChecker::checkConsistency(const std::vector<LocalBoardRO>& boards) const -{ - /// Checks that the event information is consistent - for (auto& board : boards) { - if (!checkConsistency(board)) { - return false; - } - } - return true; -} - -bool CRUBareDataChecker::checkBC(const std::vector<LocalBoardRO>& regs, const std::vector<LocalBoardRO>& locs, std::string& debugMsg) -{ - /// Checks the cards belonging to the same BC - bool isOk = true; - - if (locs.size() != 4 * regs.size()) { - std::stringstream ss; - ss << "missing cards info: nLocs (" << locs.size() << ") != 4 x nRegs (" << regs.size() << "); "; - debugMsg += ss.str(); - isOk = false; - } - - uint8_t refEventWord = 0; - if (!regs.empty()) { - refEventWord = regs.front().triggerWord; - } else if (!locs.empty()) { - // FIXME: in some files, a series of 0xeeee wrongly added before the new RDH - // This is a known problem, so we do not check further in this case - // if (locs.front().statusWord == 0xee && locs.front().triggerWord == 0xee && locs.front().firedChambers == 0xe) { - // return true; - // } - refEventWord = locs.front().triggerWord; - } - - if (!checkSameEventWord(regs, refEventWord) || !checkSameEventWord(locs, refEventWord)) { - debugMsg += "wrong event word; "; - isOk = false; - } - - if (!checkPatterns(regs, 0) || !checkPatterns(locs)) { - debugMsg += "wrong size; "; - isOk = false; - } - - if (!checkConsistency(regs) || !checkConsistency(locs)) { - debugMsg += "inconsistency in the event; "; - isOk = false; - } - - return isOk; -} - -bool CRUBareDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl::span<const ROFRecord> rofRecords, bool resetStat) -{ - /// Checks the raw data - - bool isOk = true; - if (resetStat) { - mStatistics.fill(0); - } - - mDebugMsg.clear(); - - // Fill the map with ordered events - for (auto rofIt = rofRecords.begin(); rofIt != rofRecords.end(); ++rofIt) { - mOrderIndexes[rofIt->interactionRecord.toLong()].emplace_back(rofIt - rofRecords.begin()); - } - - std::vector<LocalBoardRO> locs; - std::vector<LocalBoardRO> regs; - - for (auto& item : mOrderIndexes) { - for (auto& idx : item.second) { - // In principle all of these ROF records have the same timestamp - for (size_t iloc = rofRecords[idx].firstEntry; iloc < rofRecords[idx].firstEntry + rofRecords[idx].nEntries; ++iloc) { - if (raw::isLoc(localBoards[iloc].statusWord)) { - // This is a local card - locs.push_back(localBoards[iloc]); - } else { - regs.push_back(localBoards[iloc]); - } - } - } - // std::sort(locs.begin(), locs.end(), [](const LocalBoardRO& a, const LocalBoardRO& b) { return a.boardId < b.boardId; }); - ++mStatistics[0]; - std::string debugStr; - if (!checkBC(regs, locs, debugStr)) { - isOk = false; - std::stringstream ss; - ss << std::hex << std::showbase << rofRecords[item.second.front()].interactionRecord << " problems: " << debugStr << "\n"; - for (auto& reg : regs) { - ss << " " << reg << "\n"; - } - for (auto& loc : locs) { - ss << " " << loc << "\n"; - } - mDebugMsg += ss.str(); - ++mStatistics[1]; - } - - locs.clear(); - regs.clear(); - } - - // Clear the inner objects when the computation is done - mOrderIndexes.clear(); - - return isOk; -} - -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.h b/Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.h deleted file mode 100644 index 9d4e7d5a12f73..0000000000000 --- a/Detectors/MUON/MID/Raw/exe/CRUBareDataChecker.h +++ /dev/null @@ -1,56 +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. - -/// \file CRUBareDataChecker.h -/// \brief Class to check the bare data from the CRU -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 9 December 2019 -#ifndef O2_MID_CRUBAREDATACHECKER_H -#define O2_MID_CRUBAREDATACHECKER_H - -#include <cstdint> -#include <vector> -#include <string> -#include <map> -#include <gsl/gsl> -#include "DataFormatsMID/ROFRecord.h" -#include "MIDRaw/LocalBoardRO.h" - -namespace o2 -{ -namespace mid -{ -class CRUBareDataChecker -{ - public: - bool process(gsl::span<const LocalBoardRO> localBoards, gsl::span<const ROFRecord> rofRecords, bool resetStat = true); - /// Gets the number of processed events - unsigned int getNBCsProcessed() const { return mStatistics[0]; } - /// Gets the number of faulty events - unsigned int getNBCsFaulty() const { return mStatistics[1]; } - /// Gets the - std::string getDebugMessage() const { return mDebugMsg; } - - private: - bool checkBC(const std::vector<LocalBoardRO>& regs, const std::vector<LocalBoardRO>& locs, std::string& debugMsg); - bool checkSameEventWord(const std::vector<LocalBoardRO>& boards, uint8_t refEventWord) const; - bool checkConsistency(const LocalBoardRO& board) const; - bool checkConsistency(const std::vector<LocalBoardRO>& boards) const; - bool checkPatterns(const LocalBoardRO& board, uint8_t expected = 0xFF) const; - bool checkPatterns(const std::vector<LocalBoardRO>& boards, uint8_t expected = 0xFF) const; - - std::map<uint64_t, std::vector<size_t>> mOrderIndexes; /// Map for time ordering the entries - std::string mDebugMsg{}; /// Debug message - std::array<unsigned long int, 2> mStatistics{}; /// Processed events statistics -}; -} // namespace mid -} // namespace o2 - -#endif /* O2_MID_CRUBAREDATACHECKER_H */ diff --git a/Detectors/MUON/MID/Raw/exe/README.md b/Detectors/MUON/MID/Raw/exe/README.md index 386f75dbfbae7..1e9bad6ea0a9b 100644 --- a/Detectors/MUON/MID/Raw/exe/README.md +++ b/Detectors/MUON/MID/Raw/exe/README.md @@ -3,7 +3,7 @@ /doxy --> # Utilities for MID RAW data -This directory contains two utilities that can be executed to verify the raw data. +This directory contains utilities that can be executed to test the raw data. This is particularly important for testing and debugging the MID Read-out. ## MID raw dumper @@ -20,33 +20,3 @@ For a list of the other available options: ```bash o2-mid-rawdump --help ``` - -## MID raw file checker -This utility allows to test files produced by the CRU w/o using the User Logic. -Basic usage: -```bash -o2-mid-raw-checker filename [filename_2 filename_3 ...] -``` -The output is a file (or a series of files if a list of inputs is provided), named after the input file as `check_filename.txt`, so that it is easy to understand to which input file the output is referring to. -The different e-links are read out and then grouped according to their interaction record. -The output file contains: -- a list of possible problems (if any) for each event processed - -- a summary with the number of faulty events -The list of problems is preceded by the identifier of the processed HB and the corresponding "line" in the file where the HB is. -The line is counted assuming that one reads the file as a series of 4 words of 32 bits each (this is the typical way the binary file is converted into text during the tests). -Notice that one can have more than 1 HB per event, since the data might be split into different pages if the maximum page size is reached. -For a list of the other available options: -```bash -o2-mid-raw-checker --help -``` -### Performed checks -The decoded information is read HB per HB (multiple pages are read out when needed). -For each HB, the decoded information are gathered according to their interaction. -Notice that, in principle, events belonging to different HBs should have different interaction records, so one could in principle read the full file and then perform the check. -However, in the tests the RDH is not always correctly set, and the orbit number might not increase. That is why we read the HB one by one, and limit the tests to 1 HB at the time. This makes it easier to tag HBs with issues in the RO. -For each interaction record, a number of checks are performed: -- The number of local cards read must be 4 times the number of regional cards. Notice that this error often implies that there is a mismatch between the regional and local clocks (so the cards gets split into different interaction records) -- The word describing the event (SOX, EOX, HC, Calibration, etc.) should be the same for all cards in the interaction record. -- The number of non-zero patterns read must match the information written in the corresponding word that indicates the non-zero detector planes. Notice that this might not be true when the patterns represent the masks, since in this case it is fine to transmit a zero pattern. However, for the sake of simplicity, we do not account for this possibility. Of course, this implies that must run the check on tests where all masks are non-zero. -- For each card we check that the information is consistent. For example we cannot have SOX and Calibration bits fired at the same time. Also, during an HC, we expect to have no chamber fired for the local boards. Notice that during tests this information is added by hand, so we should not have any issue by design. \ No newline at end of file diff --git a/Detectors/MUON/MID/Raw/exe/mid-raw-checker.cxx b/Detectors/MUON/MID/Raw/exe/mid-raw-checker.cxx deleted file mode 100644 index 38faa81c0aeac..0000000000000 --- a/Detectors/MUON/MID/Raw/exe/mid-raw-checker.cxx +++ /dev/null @@ -1,139 +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. - -/// \file mid-raw-checker.cxx -/// \brief CRU bare data checker for MID -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 09 December 2019 - -#include <iostream> -#include <fstream> -#include "boost/program_options.hpp" -#include "MIDRaw/CRUBareDecoder.h" -#include "MIDRaw/RawFileReader.h" -#include "CRUBareDataChecker.h" - -namespace po = boost::program_options; - -o2::header::RAWDataHeader buildCustomRDH() -{ - o2::header::RAWDataHeader rdh; - rdh.word1 |= 0x2000; - rdh.word1 |= ((0x2000 - 0x100)) << 16; - return rdh; -} - -int main(int argc, char* argv[]) -{ - po::variables_map vm; - po::options_description generic("Generic options"); - unsigned long int nHBs = 0; - bool onlyClosedHBs = false; - bool ignoreRDH = true; - - // clang-format off - generic.add_options() - ("help", "produce help message") - ("nHBs", po::value<unsigned long int>(&nHBs),"Number of HBs read") - ("only-closed-HBs", po::value<bool>(&onlyClosedHBs)->implicit_value(true),"Return only closed HBs") - ("ignore-RDH", po::value<bool>(&ignoreRDH)->implicit_value(true),"Ignore read RDH. Use custom one instead"); - - - po::options_description hidden("hidden options"); - hidden.add_options() - ("input", po::value<std::vector<std::string>>(),"Input filename"); - // clang-format on - - po::options_description cmdline; - cmdline.add(generic).add(hidden); - - po::positional_options_description pos; - pos.add("input", -1); - - po::store(po::command_line_parser(argc, argv).options(cmdline).positional(pos).run(), vm); - po::notify(vm); - - if (vm.count("help")) { - std::cout << "Usage: " << argv[0] << " <input_raw_filename> [input_raw_filename_1 ...]\n"; - std::cout << generic << std::endl; - return 2; - } - if (vm.count("input") == 0) { - std::cout << "no input file specified" << std::endl; - return 1; - } - - std::vector<std::string> inputfiles{vm["input"].as<std::vector<std::string>>()}; - - o2::mid::CRUBareDecoder decoder; - decoder.init(true); - - o2::mid::CRUBareDataChecker checker; - - unsigned long int iHB = 0; - - for (auto& filename : inputfiles) { - o2::mid::RawFileReader<uint8_t> rawFileReader; - std::string outFilename = filename; - auto pos = outFilename.find_last_of("/"); - if (pos == std::string::npos) { - pos = 0; - } else { - ++pos; - } - outFilename.insert(pos, "check_"); - outFilename += ".txt"; - std::ofstream outFile(outFilename.c_str()); - if (!rawFileReader.init(filename.c_str())) { - return 2; - } - if (ignoreRDH) { - rawFileReader.setCustomRDH(buildCustomRDH()); - } - std::vector<o2::mid::LocalBoardRO> data; - std::vector<o2::mid::ROFRecord> rofRecords; - std::stringstream ss; - bool isFirst = true; - while (rawFileReader.getState() == 0) { - rawFileReader.readHB(onlyClosedHBs); - decoder.process(rawFileReader.getData()); - rawFileReader.clear(); - size_t offset = data.size(); - std::copy(decoder.getData().begin(), decoder.getData().end(), std::back_inserter(data)); - for (auto& rof : decoder.getROFRecords()) { - rofRecords.emplace_back(rof.interactionRecord, rof.eventType, rof.firstEntry + offset, rof.nEntries); - } - ss << " HB: " << iHB << " (line: " << 512 * iHB + 1 << ")"; - if (decoder.isComplete()) { - // The check assumes that we have all data corresponding to one event. - // However this might not be true since we read one HB at the time. - // So we must test that the event was fully read before running the check. - if (!checker.process(data, rofRecords, isFirst)) { - outFile << ss.str() << "\n"; - outFile << checker.getDebugMessage() << "\n"; - } - isFirst = false; - std::stringstream clean; - ss.swap(clean); - data.clear(); - rofRecords.clear(); - } - ++iHB; - if (nHBs > 0 && iHB >= nHBs) { - break; - } - } - outFile << "Fraction of faulty events: " << checker.getNBCsFaulty() << " / " << checker.getNBCsProcessed() << " = " << static_cast<double>(checker.getNBCsFaulty()) / static_cast<double>(checker.getNBCsProcessed()); - - outFile.close(); - } - - return 0; -} diff --git a/Detectors/MUON/MID/Raw/exe/mid-rawdump.cxx b/Detectors/MUON/MID/Raw/exe/mid-rawdump.cxx deleted file mode 100644 index 47f8519ba00d6..0000000000000 --- a/Detectors/MUON/MID/Raw/exe/mid-rawdump.cxx +++ /dev/null @@ -1,95 +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. - -/// \file mid-rawdump.cxx -/// \brief Raw dumper for MID -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 05 December 2019 - -#include <iostream> -#include "boost/program_options.hpp" -#include "MIDRaw/CRUBareDecoder.h" -#include "MIDRaw/RawFileReader.h" - -namespace po = boost::program_options; - -int main(int argc, char* argv[]) -{ - po::variables_map vm; - po::options_description generic("Generic options"); - std::string outFilename = "mid_raw.txt"; - unsigned long int nHBs = 0; - bool onlyClosedHBs = false; - - // clang-format off - generic.add_options() - ("help", "produce help message") - ("output", po::value<std::string>(&outFilename),"Output text file") - ("nHBs", po::value<unsigned long int>(&nHBs),"Number of HBs read") - ("only-closed-HBs", po::value<bool>(&onlyClosedHBs)->implicit_value(true),"Return only closed HBs"); - - - po::options_description hidden("hidden options"); - hidden.add_options() - ("input", po::value<std::vector<std::string>>(),"Input filename"); - // clang-format on - - po::options_description cmdline; - cmdline.add(generic).add(hidden); - - po::positional_options_description pos; - pos.add("input", -1); - - po::store(po::command_line_parser(argc, argv).options(cmdline).positional(pos).run(), vm); - po::notify(vm); - - if (vm.count("help")) { - std::cout << "Usage: " << argv[0] << " <input_raw_filename> [input_raw_filename_1 ...]\n"; - std::cout << generic << std::endl; - return 2; - } - if (vm.count("input") == 0) { - std::cout << "no input file specified" << std::endl; - return 1; - } - - std::vector<std::string> inputfiles{vm["input"].as<std::vector<std::string>>()}; - - o2::mid::CRUBareDecoder decoder; - - std::ofstream outFile(outFilename); - - unsigned long int iHB = 0; - - for (auto& filename : inputfiles) { - o2::mid::RawFileReader<uint8_t> rawFileReader; - if (!rawFileReader.init(filename.c_str())) { - return 2; - } - while (rawFileReader.getState() == 0) { - rawFileReader.readHB(onlyClosedHBs); - decoder.process(rawFileReader.getData()); - rawFileReader.clear(); - for (auto& rof : decoder.getROFRecords()) { - outFile << "Orbit: " << rof.interactionRecord.orbit << " bc: " << rof.interactionRecord.bc << std::endl; - for (auto colIt = decoder.getData().begin() + rof.firstEntry; colIt != decoder.getData().begin() + rof.firstEntry + rof.nEntries; ++colIt) { - outFile << *colIt << std::endl; - } - } - ++iHB; - if (nHBs > 0 && iHB >= nHBs) { - break; - } - } - } - outFile.close(); - - return 0; -} diff --git a/Detectors/MUON/MID/Raw/exe/rawdump.cxx b/Detectors/MUON/MID/Raw/exe/rawdump.cxx new file mode 100644 index 0000000000000..3210b66b6c440 --- /dev/null +++ b/Detectors/MUON/MID/Raw/exe/rawdump.cxx @@ -0,0 +1,188 @@ +// 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 MID/Raw/exe/rawdump.cxx +/// \brief Raw data dumper for MID +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 05 December 2019 + +#include <iostream> +#include "fmt/format.h" +#include "boost/program_options.hpp" +#include "DPLUtils/RawParser.h" +#include "MIDRaw/FEEIdConfig.h" +#include "MIDRaw/Decoder.h" +#include "MIDRaw/GBTBareDecoder.h" +#include "MIDRaw/GBTUserLogicDecoder.h" +#include "MIDRaw/RawFileReader.h" + +namespace po = boost::program_options; + +std::string getOutFilename(const char* inFilename, const char* outDir) +{ + std::string basename(inFilename); + std::string fdir = "./"; + auto pos = basename.find_last_of("/"); + if (pos != std::string::npos) { + basename.erase(0, pos + 1); + fdir = inFilename; + fdir.erase(pos); + } + basename.insert(0, "dump_"); + basename += ".txt"; + std::string outputDir(outDir); + if (outputDir.empty()) { + outputDir = fdir; + } + if (outputDir.back() != '/') { + outputDir += "/"; + } + std::string outFilename = outputDir + basename; + return outFilename; +} + +template <typename GBTDECODER, typename RDH> +void decode(o2::mid::Decoder<GBTDECODER>& decoder, gsl::span<const uint8_t> payload, const RDH& rdh, std::ostream& out) +{ + decoder.clear(); + decoder.process(payload, rdh); + decoder.flush(); + for (auto& rof : decoder.getROFRecords()) { + std::stringstream ss; + ss << std::hex << std::showbase << rof.interactionRecord; + out << ss.str() << std::endl; + for (auto colIt = decoder.getData().begin() + rof.firstEntry; colIt != decoder.getData().begin() + rof.firstEntry + rof.nEntries; ++colIt) { + out << *colIt << std::endl; + } + } +} + +int main(int argc, char* argv[]) +{ + po::variables_map vm; + po::options_description generic("Generic options"); + std::string outFilename = "", feeIdConfigFilename = ""; + unsigned long int nHBs = 0; + unsigned long int firstHB = 0; + + // clang-format off + generic.add_options() + ("help", "produce help message") + ("output", po::value<std::string>(&outFilename),"Output text file") + ("first", po::value<unsigned long int>(&firstHB),"First HB to read") + ("nHBs", po::value<unsigned long int>(&nHBs),"Number of HBs read") + ("rdh-only", po::value<bool>()->implicit_value(true),"Only show RDHs") + ("decode", po::value<bool>()->implicit_value(true),"Decode output") + ("feeId-config-file", po::value<std::string>(&feeIdConfigFilename),"Filename with crate FEE ID correspondence") + ("bare", po::value<bool>()->implicit_value(true),"Bare decoder"); + + + po::options_description hidden("hidden options"); + hidden.add_options() + ("input", po::value<std::vector<std::string>>(),"Input filename"); + // clang-format on + + po::options_description cmdline; + cmdline.add(generic).add(hidden); + + po::positional_options_description pos; + pos.add("input", -1); + + po::store(po::command_line_parser(argc, argv).options(cmdline).positional(pos).run(), vm); + po::notify(vm); + + if (vm.count("help")) { + std::cout << "Usage: " << argv[0] << " <input_raw_filename> [input_raw_filename_1 ...]\n"; + std::cout << generic << std::endl; + return 2; + } + if (vm.count("input") == 0) { + std::cout << "no input file specified" << std::endl; + return 1; + } + + std::vector<std::string> inputfiles{vm["input"].as<std::vector<std::string>>()}; + + bool isBare = (vm.count("bare") > 0); + bool runDecoder = (vm.count("decode") > 0); + + o2::mid::Decoder<o2::mid::GBTUserLogicDecoder> ulDecoder; + o2::mid::Decoder<o2::mid::GBTBareDecoder> bareDecoder; + + if (runDecoder) { + if (!feeIdConfigFilename.empty()) { + o2::mid::FEEIdConfig feeIdConfig(feeIdConfigFilename.c_str()); + bareDecoder.setFeeIdConfig(feeIdConfig); + ulDecoder.setFeeIdConfig(feeIdConfig); + } + bareDecoder.init(true); + ulDecoder.init(true); + } + + std::ofstream outFile; + std::ostream& out = (outFilename.empty()) ? std::cout : (outFile.open(outFilename), outFile); + + unsigned long int iHB = 0; + bool isRdhOnly = vm.count("rdh-only") > 0; + + for (auto& filename : inputfiles) { + // Here we use a custom file reader to be able to read all kind of raw data, + // even those with a malformed structure in terms of number of HBFs per time frame + o2::mid::RawFileReader rawFileReader; + if (!rawFileReader.init(filename.c_str())) { + return 2; + } + while (rawFileReader.readHB()) { + if (iHB >= firstHB) { + o2::framework::RawParser parser(rawFileReader.getData().data(), rawFileReader.getData().size()); + auto it = parser.begin(); // We only have 1 HB + auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(it.raw()); + if (!runDecoder) { + o2::raw::RDHUtils::printRDH(rdhPtr); + } + if (it.size() > 0) { + gsl::span<const uint8_t> payload(it.data(), it.size()); + if (runDecoder) { + if (isBare) { + decode(bareDecoder, payload, *rdhPtr, out); + } else { + decode(ulDecoder, payload, *rdhPtr, out); + } + } else if (!isRdhOnly) { + for (size_t iword = 0; iword < payload.size(); iword += 16) { + auto word = payload.subspan(iword, 16); + for (auto it = word.rbegin(); it != word.rend(); ++it) { + auto ibInWord = word.rend() - it; + if (isBare) { + if (ibInWord == 4 || ibInWord == 9) { + out << " "; + } + if (ibInWord == 5 || ibInWord == 10) { + out << " "; + } + } + out << fmt::format("{:02x}", static_cast<int>(*it)); + } + out << "\n"; + } + } + } + } + rawFileReader.clear(); + ++iHB; + if (nHBs > 0 && iHB >= nHBs + firstHB) { + break; + } + } // loop on HBs + } // loop on files + outFile.close(); + + return 0; +} diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/CRUBareDecoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/CRUBareDecoder.h deleted file mode 100644 index a041527fc95a9..0000000000000 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/CRUBareDecoder.h +++ /dev/null @@ -1,68 +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. - -/// \file MIDRaw/CRUBareDecoder.h -/// \brief MID CRU core decoder -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 18 November 2019 -#ifndef O2_MID_CRUBAREDECODER_H -#define O2_MID_CRUBAREDECODER_H - -#include <cstdint> -#include <vector> -#include <gsl/gsl> -#include "DataFormatsMID/ROFRecord.h" -#include "MIDRaw/CrateMapper.h" -#include "MIDRaw/CrateParameters.h" -#include "MIDRaw/ELinkDecoder.h" -#include "MIDRaw/LocalBoardRO.h" -#include "MIDRaw/RawBuffer.h" - -namespace o2 -{ -namespace mid -{ -class CRUBareDecoder -{ - public: - void init(bool debugMode = false); - void process(gsl::span<const uint8_t> bytes); - /// Gets the vector of data - const std::vector<LocalBoardRO>& getData() const { return mData; } - - /// Gets the vector of data RO frame records - const std::vector<ROFRecord>& getROFRecords() const { return mROFRecords; } - - bool isComplete() const; - - private: - RawBuffer<uint8_t> mBuffer{}; /// Raw buffer handler - std::vector<LocalBoardRO> mData{}; /// Vector of output data - std::vector<ROFRecord> mROFRecords{}; /// List of ROF records - CrateMapper mCrateMapper{}; /// Crate mapper - uint8_t mCrateId{0}; /// Crate ID - std::array<uint16_t, crateparams::sNELinksPerGBT> mCalibClocks{}; /// Calibration clock - std::array<ELinkDecoder, crateparams::sNELinksPerGBT> mELinkDecoders{}; /// E-link decoders - std::function<void(size_t)> mAddReg{[](size_t) {}}; ///! Add regional board - - std::function<bool(size_t)> mCheckBoard{std::bind(&CRUBareDecoder::checkBoard, this, std::placeholders::_1)}; ///! Check board - - bool nextGBTWord(); - void processGBT(size_t offset); - void reset(); - void addBoard(size_t ilink); - bool checkBoard(size_t ilink); - void addLoc(size_t ilink); - uint16_t getPattern(uint16_t pattern, bool invert) const; -}; -} // namespace mid -} // namespace o2 - -#endif /* O2_MID_CRUBAREDECODER_H */ diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/RawBuffer.h b/Detectors/MUON/MID/Raw/include/MIDRaw/RawBuffer.h deleted file mode 100644 index 6f7e8078d9134..0000000000000 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/RawBuffer.h +++ /dev/null @@ -1,72 +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. - -/// \file MIDRaw/RawBuffer.h -/// \brief Handler of the RAW buffer -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 28 November 2019 -#ifndef O2_MID_RAWBUFFER_H -#define O2_MID_RAWBUFFER_H - -#include <cstdint> -#include <vector> -#include <gsl/gsl> -#include "Headers/RAWDataHeader.h" - -namespace o2 -{ -namespace mid -{ -template <typename T> -class RawBuffer -{ - public: - enum class ResetMode { - all, // Reset buffer and indexes - keepUnconsumed, // Keep the last unconsumed HB - bufferOnly // Do not reset indexes - }; - - void setBuffer(gsl::span<const T> bytes, ResetMode resetMode = ResetMode::keepUnconsumed); - - /// Gets the current RDH - const header::RAWDataHeader* getRDH() { return mRDH; } - - unsigned int next(unsigned int nBits); - T next(); - - bool nextHeader(); - - bool hasNext(unsigned int nBytes); - - void skipOverhead(); - - bool isHBClosed(); - - private: - gsl::span<const T> mBytes{}; /// gsl span with encoded information - gsl::span<const T> mCurrentBuffer{}; /// gsl span with the current encoded information - std::vector<T> mUnconsumed{}; /// Unconsumed buffer - size_t mElementIndex{0}; /// Index of the current element in the buffer - size_t mBitIndex{0}; /// Index of the current bit - size_t mHeaderIndex{0}; /// Index of the current header - size_t mNextHeaderIndex{0}; /// Index of the next header - size_t mEndOfPayloadIndex{0}; /// Index of the end of payload - const unsigned int mElementSizeInBytes{sizeof(T)}; /// Element size in bytes - const unsigned int mElementSizeInBits{mElementSizeInBytes * 8}; /// Element size in bits - const header::RAWDataHeader* mRDH{nullptr}; /// Current header (not owner) - - bool nextPayload(); - void reset(); -}; -} // namespace mid -} // namespace o2 - -#endif /* O2_MID_RAWBUFFER_H */ diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/RawFileReader.h b/Detectors/MUON/MID/Raw/include/MIDRaw/RawFileReader.h index 9f91f830cf254..0df1da74bc6c8 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/RawFileReader.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/RawFileReader.h @@ -15,48 +15,40 @@ #ifndef O2_MID_RAWFILEREADER_H #define O2_MID_RAWFILEREADER_H +#include <cstdint> #include <fstream> #include <vector> -#include <array> -#include "MIDRaw/CrateParameters.h" -#include "MIDRaw/RawBuffer.h" -#include "MIDRaw/RawUnit.h" +#include "Headers/RAWDataHeader.h" namespace o2 { namespace mid { -template <typename T> class RawFileReader { public: bool init(const char* inFilename, bool readContinuous = false); - bool readAllGBTs(bool reset = true); - bool readHB(bool sendCompleteHBs = true); + bool readHB(bool sendCompleteHBs = false); void clear(); - /// Gets the number of HBs read - unsigned long int getNumberOfHBs(uint16_t feeId) { return mHBCounters.at(feeId); } - /// Gets the state int getState() { return mState; } /// Gets the vector of data - const std::vector<T>& getData() { return mBytes; } + const std::vector<uint8_t>& getData() { return mBytes; } void setCustomRDH(const header::RAWDataHeader& rdh) { mCustomRDH = rdh; } + void setCustomPayloadSize(uint16_t memorySize = 0x2000, uint16_t offsetToNext = 0x2000); private: void read(size_t nBytes); - bool hasFullInfo(); bool replaceRDH(size_t headerIndex); - std::ifstream mFile{}; /// Raw file - std::vector<T> mBytes; /// Buffer - RawBuffer<T> mBuffer; /// Raw buffer handler - std::array<unsigned long int, crateparams::sNGBTs> mHBCounters{}; /// HB counters per GBT - bool mReadContinuous{false}; /// Continuous readout mode - int mState{0}; /// Status flag + std::ifstream mFile{}; /// Raw file + std::vector<uint8_t> mBytes; /// Buffer + static constexpr unsigned int sHeaderSize{64}; /// Header size in bytes + bool mReadContinuous{false}; /// Continuous readout mode + int mState{0}; /// Status flag header::RAWDataHeader mCustomRDH{}; /// Custom RDH }; diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/RawUnit.h b/Detectors/MUON/MID/Raw/include/MIDRaw/RawUnit.h deleted file mode 100644 index 0487a9fa55528..0000000000000 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/RawUnit.h +++ /dev/null @@ -1,43 +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. - -/// \file MIDRaw/RawUnit.h -/// \brief Raw data format MID -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 30 September 2019 -#ifndef O2_MID_RAWUNIT_H -#define O2_MID_RAWUNIT_H - -#include <cstdint> -#include <cstddef> -#include "Headers/RAWDataHeader.h" - -namespace o2 -{ -namespace mid -{ -namespace raw -{ -typedef uint32_t RawUnit; - -// Buffer size -static constexpr size_t sElementSizeInBytes = sizeof(RawUnit); -static constexpr size_t sMaxBufferSize = 8192 / sElementSizeInBytes; -static constexpr size_t sElementSizeInBits = 8 * sElementSizeInBytes; - -// Header size -static constexpr size_t sHeaderSizeInBytes = sizeof(header::RAWDataHeader); -static constexpr size_t sHeaderSizeInElements = sHeaderSizeInBytes / sElementSizeInBytes; - -} // namespace raw -} // namespace mid -} // namespace o2 - -#endif /* O2_MID_RAWUNIT_H */ \ No newline at end of file diff --git a/Detectors/MUON/MID/Raw/src/CRUBareDecoder.cxx b/Detectors/MUON/MID/Raw/src/CRUBareDecoder.cxx deleted file mode 100644 index 3ec0291141401..0000000000000 --- a/Detectors/MUON/MID/Raw/src/CRUBareDecoder.cxx +++ /dev/null @@ -1,152 +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. - -/// \file MID/Raw/src/CRUBareDecoder.cxx -/// \brief MID CRU core decoder -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 30 September 2019 - -#include "MIDRaw/CRUBareDecoder.h" - -#include "RawInfo.h" -#include "DetectorsRaw/RDHUtils.h" - -namespace o2 -{ -namespace mid -{ -using RDHUtils = o2::raw::RDHUtils; - -void CRUBareDecoder::reset() -{ - /// Rewind bytes - mData.clear(); - mROFRecords.clear(); -} - -void CRUBareDecoder::init(bool debugMode) -{ - /// Initializes the task - if (debugMode == true) { - mAddReg = std::bind(&CRUBareDecoder::addBoard, this, std::placeholders::_1); - mCheckBoard = [](size_t) { return true; }; - } -} - -void CRUBareDecoder::process(gsl::span<const uint8_t> bytes) -{ - /// Decodes the buffer - reset(); - - mBuffer.setBuffer(bytes); - - // Each CRU word consists of 128 bits, i.e 16 bytes - while (mBuffer.hasNext(16)) { - processGBT(0); - processGBT(5); - // The GBT word consists of 10 bytes - // but the CRU word is 16 bytes - // So we have 6 empty bytes - for (int iword = 0; iword < 6; ++iword) { - mBuffer.next(); - } - } -} - -void CRUBareDecoder::processGBT(size_t offset) -{ - /// Processes the GBT - - // Regional link - // loc#0 loc#1 loc#2 loc#3 reg - std::array<uint8_t, 5> bytes{mBuffer.next(), mBuffer.next(), mBuffer.next(), mBuffer.next(), mBuffer.next()}; - - // Byte corresponding to regional - size_t ibyte = 4; - size_t ilink = offset + ibyte; - - if (mELinkDecoders[ilink].add(bytes[ibyte], 0x80) && mELinkDecoders[ilink].isComplete()) { - // In principle, in the same HB we should have the info of only 1 crate - // So it should be safe to store this information - // and apply it to all subsequent e-links, without checking the clock - mCrateId = mELinkDecoders[ilink].getId(); - mAddReg(ilink); - mELinkDecoders[ilink].reset(); - } - - // local links - for (ibyte = 0; ibyte < 4; ++ibyte) { - ilink = offset + ibyte; - if (mELinkDecoders[ilink].add(bytes[ibyte], 0xc0) && mELinkDecoders[ilink].isComplete()) { - if (mCheckBoard(ilink)) { - addLoc(ilink); - } - mELinkDecoders[ilink].reset(); - } - } -} - -bool CRUBareDecoder::checkBoard(size_t ilink) -{ - /// Performs checks on the board - uint8_t expectedId = ilink - (ilink / 5); - return (expectedId == mELinkDecoders[ilink].getId() % 8); -} - -void CRUBareDecoder::addBoard(size_t ilink) -{ - /// Adds the local or regional board to the output data vector - uint16_t localClock = mELinkDecoders[ilink].getCounter(); - EventType eventType = EventType::Standard; - if (mELinkDecoders[ilink].getTriggerWord() & (1 << 4)) { - mCalibClocks[ilink] = localClock; - eventType = EventType::Noise; - } else if (localClock == mCalibClocks[ilink] + sDelayCalibToFET) { - eventType = EventType::Dead; - } - auto firstEntry = mData.size(); - InteractionRecord intRec(localClock - sDelayBCToLocal, RDHUtils::getTriggerOrbit(*mBuffer.getRDH())); - mData.push_back({mELinkDecoders[ilink].getStatusWord(), mELinkDecoders[ilink].getTriggerWord(), crateparams::makeUniqueLocID(mCrateId, mELinkDecoders[ilink].getId()), mELinkDecoders[ilink].getInputs()}); - mROFRecords.emplace_back(intRec, eventType, firstEntry, 1); -} - -void CRUBareDecoder::addLoc(size_t ilink) -{ - /// Adds the local board to the output data vector - addBoard(ilink); - bool invert = (mROFRecords.back().eventType == EventType::Dead); - for (int ich = 0; ich < 4; ++ich) { - if ((mData.back().firedChambers & (1 << ich))) { - mData.back().patternsBP[ich] = getPattern(mELinkDecoders[ilink].getPattern(0, ich), invert); - mData.back().patternsNBP[ich] = getPattern(mELinkDecoders[ilink].getPattern(1, ich), invert); - } - } - mELinkDecoders[ilink].reset(); -} - -uint16_t CRUBareDecoder::getPattern(uint16_t pattern, bool invert) const -{ - /// Gets the proper pattern - return (invert) ? ~pattern : pattern; -} - -bool CRUBareDecoder::isComplete() const -{ - /// Checks that all links have finished reading - for (auto& elink : mELinkDecoders) { - if (elink.getNBytes() > 0) { - return false; - } - } - return true; -} - -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/RawBuffer.cxx b/Detectors/MUON/MID/Raw/src/RawBuffer.cxx deleted file mode 100644 index 713f0a6a09757..0000000000000 --- a/Detectors/MUON/MID/Raw/src/RawBuffer.cxx +++ /dev/null @@ -1,181 +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. - -/// \file MID/Raw/src/RawBuffer.cxx -/// \brief MID CRU user logic decoder -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 30 September 2019 - -#include "MIDRaw/RawBuffer.h" - -#include "MIDRaw/RawUnit.h" -#include "RawInfo.h" -#include "DetectorsRaw/RDHUtils.h" - -namespace o2 -{ -namespace mid -{ -using RDHUtils = o2::raw::RDHUtils; - -template <typename T> -unsigned int RawBuffer<T>::next(unsigned int nBits) -{ - /// Reads the next nBits - if (mNextHeaderIndex == 0) { - // This is the first entry - nextPayload(); - } - unsigned int value = 0; - for (int ibit = 0; ibit < nBits; ++ibit) { - if (mBitIndex == mElementSizeInBits) { - mBitIndex = 0; - ++mElementIndex; - nextPayload(); - } - bool isOn = (mBytes[mElementIndex] >> mBitIndex) & 0x1; - if (isOn) { - value |= (1 << ibit); - } - ++mBitIndex; - } - return value; -} - -template <typename T> -T RawBuffer<T>::next() -{ - /// Reads the next word - nextPayload(); - return mBytes[mElementIndex++]; -} - -template <typename T> -bool RawBuffer<T>::nextHeader() -{ - /// Goes to next RDH - if (mNextHeaderIndex >= mBytes.size()) { - // This is the end of the buffer - if (mUnconsumed.empty()) { - mElementIndex = mNextHeaderIndex; - mEndOfPayloadIndex = mNextHeaderIndex; - return false; - } - // We were reading the unconsumed part: switch to new buffer - mUnconsumed.clear(); - reset(); - mBytes = mCurrentBuffer; - } - mHeaderIndex = mNextHeaderIndex; - mRDH = reinterpret_cast<const header::RAWDataHeader*>(&mBytes[mHeaderIndex]); - mEndOfPayloadIndex = mHeaderIndex + (RDHUtils::getMemorySize(*mRDH) / mElementSizeInBytes); - // Go to end of header, i.e. beginning of payload - mElementIndex = mHeaderIndex + (RDHUtils::getHeaderSize(*mRDH) / mElementSizeInBytes); - mNextHeaderIndex = mHeaderIndex + RDHUtils::getOffsetToNext(*mRDH) / mElementSizeInBytes; - mBitIndex = 0; - - return true; -} - -template <typename T> -bool RawBuffer<T>::nextPayload() -{ - /// Goes to next payload - while (mElementIndex == mEndOfPayloadIndex) { - if (!nextHeader()) { - return false; - } - } - return true; -} - -template <typename T> -void RawBuffer<T>::reset() -{ - /// Rewind bytes - mElementIndex = 0; - mHeaderIndex = 0; - mNextHeaderIndex = 0; - mEndOfPayloadIndex = 0; - mBitIndex = 0; - mRDH = nullptr; - mUnconsumed.clear(); -} - -template <typename T> -void RawBuffer<T>::setBuffer(gsl::span<const T> bytes, ResetMode resetMode) -{ - /// Sets the buffer and reset the internal indexes - if (resetMode == ResetMode::keepUnconsumed && !mUnconsumed.empty()) { - // There are some unconsumed bytes from the previous buffer - mNextHeaderIndex -= mHeaderIndex; - mEndOfPayloadIndex -= mHeaderIndex; - mElementIndex -= mHeaderIndex; - mHeaderIndex = 0; - mBytes = gsl::span<const T>(mUnconsumed); - } else { - mBytes = bytes; - if (resetMode != ResetMode::bufferOnly) { - reset(); - } - } - mCurrentBuffer = bytes; -} - -template <typename T> -bool RawBuffer<T>::isHBClosed() -{ - /// Tests if the HB is closed - if (!mRDH) { - return false; - } - return RDHUtils::getStop(*mRDH); -} - -template <typename T> -void RawBuffer<T>::skipOverhead() -{ - /// This function must be called after reading a block of data - /// if the payload is not provided and/or readout in bytes. - /// - /// In this case, indeed, there can be an overhead between the last useful bit and the declared memory size, - /// which is in bytes. - /// Calling this function allows to jump directly to the next header when needed - if (mElementIndex == mEndOfPayloadIndex - 1) { - mElementIndex = mEndOfPayloadIndex; - mBitIndex = 0; - } -} - -template <typename T> -bool RawBuffer<T>::hasNext(unsigned int nBytes) -{ - /// Tests if the buffer has nBytes left - - // We first need to go to the next payload - // If we do not, we could have a set of empty HBs in front of us - // With lot of memory left in the buffer but no payload - nextPayload(); - bool isOk = mCurrentBuffer.size() + mUnconsumed.size() - mNextHeaderIndex + mEndOfPayloadIndex - mElementIndex >= nBytes / mElementSizeInBytes; - if (!isOk && mElementIndex != mCurrentBuffer.size()) { - // Store the remaining bits for further use - // We need to do it here because the vector of which the mBytes is just a span might not be valid afterwards - // (e.g. when we do the next setBuffer) - // If we do not want to invalidate the mRDH pointer, we need to copy bytes from the last header - mUnconsumed.insert(mUnconsumed.end(), mBytes.begin() + mHeaderIndex, mBytes.end()); - } - return isOk; -} - -template class RawBuffer<raw::RawUnit>; -template class RawBuffer<uint8_t>; - -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/RawFileReader.cxx b/Detectors/MUON/MID/Raw/src/RawFileReader.cxx index 763d37d7adc44..a039749839075 100644 --- a/Detectors/MUON/MID/Raw/src/RawFileReader.cxx +++ b/Detectors/MUON/MID/Raw/src/RawFileReader.cxx @@ -17,16 +17,15 @@ #include <iostream> #include "Headers/RAWDataHeader.h" +#include "Headers/RDHAny.h" +#include "DPLUtils/RawParser.h" #include "DetectorsRaw/RDHUtils.h" namespace o2 { namespace mid { -using RDHUtils = o2::raw::RDHUtils; - -template <typename T> -bool RawFileReader<T>::init(const char* inFilename, bool readContinuous) +bool RawFileReader::init(const char* inFilename, bool readContinuous) { /// Initializes the raw file reader mFile.open(inFilename, std::ios::binary); @@ -35,71 +34,41 @@ bool RawFileReader<T>::init(const char* inFilename, bool readContinuous) mState = 2; return false; } - mBytes.reserve(2 * raw::sMaxBufferSize); mReadContinuous = readContinuous; - mHBCounters.fill(0); - return true; } -template <typename T> -void RawFileReader<T>::read(size_t nBytes) +void RawFileReader::read(size_t nBytes) { /// Reads nBytes of the file size_t currentIndex = mBytes.size(); - mBytes.resize(currentIndex + nBytes / sizeof(T)); + mBytes.resize(currentIndex + nBytes); mFile.read(reinterpret_cast<char*>(&(mBytes[currentIndex])), nBytes); } -template <typename T> -void RawFileReader<T>::clear() +void RawFileReader::clear() { /// Clears the bytes and counters mBytes.clear(); - mBuffer.setBuffer(mBytes, RawBuffer<T>::ResetMode::all); - mHBCounters.fill(0); -} - -template <typename T> -bool RawFileReader<T>::hasFullInfo() -{ - /// Tests if we have read the same number of HBs for all GBT links - - // We assume here that we read the data of one HV for all of the GBT links - // before moving to the next HB - for (uint16_t feeId = 1; feeId < crateparams::sNGBTs; ++feeId) { - if (mHBCounters[feeId] != mHBCounters[0]) { - return false; - } - } - return mHBCounters[0] != 0; } -template <typename T> -bool RawFileReader<T>::readAllGBTs(bool reset) +void RawFileReader::setCustomPayloadSize(uint16_t memorySize, uint16_t offsetToNext) { - /// Keeps reading the file until it reads the information of all GBT links - /// It returns the number of HBs read - - if (reset) { - clear(); - } - - while (!hasFullInfo()) { - if (!readHB()) { - return false; - } - } - return true; + /// Sets a custom memory and payload size + /// This is done to be able to correctly read test data + /// that have a wrong RDH + o2::header::RAWDataHeader rdh; + rdh.word1 |= offsetToNext; + rdh.word1 |= (memorySize << 16); + setCustomRDH(rdh); } -template <typename T> -bool RawFileReader<T>::replaceRDH(size_t headerIndex) +bool RawFileReader::replaceRDH(size_t headerIndex) { /// Replaces the current RDH with a custom one if needed. /// This is done to be able to correctly read test data /// that have a wrong RDH - if (RDHUtils::getOffsetToNext(mCustomRDH) > 0) { + if (o2::raw::RDHUtils::getOffsetToNext(mCustomRDH) > 0) { header::RAWDataHeader* rdh = reinterpret_cast<header::RAWDataHeader*>(&mBytes[headerIndex]); *rdh = mCustomRDH; return true; @@ -107,19 +76,17 @@ bool RawFileReader<T>::replaceRDH(size_t headerIndex) return false; } -template <typename T> -bool RawFileReader<T>::readHB(bool sendCompleteHBs) +bool RawFileReader::readHB(bool sendCompleteHBs) { /// Reads one HB if (mState != 0) { return false; } - auto gbtId = 0; bool isHBClosed = false; while (!isHBClosed) { // Read header size_t headerIndex = mBytes.size(); - read(raw::sHeaderSizeInBytes); + read(sHeaderSize); // The check on the eof needs to be placed here and not at the beginning of the function. // The reason is that the eof flag is set if we try to read after the eof @@ -132,7 +99,7 @@ bool RawFileReader<T>::readHB(bool sendCompleteHBs) if (mReadContinuous) { mFile.clear(); mFile.seekg(0, std::ios::beg); - read(raw::sHeaderSizeInBytes); + read(sHeaderSize); } else { mState = 1; return false; @@ -140,38 +107,23 @@ bool RawFileReader<T>::readHB(bool sendCompleteHBs) } replaceRDH(headerIndex); // We use the buffer only to correctly initialize the RDH - mBuffer.setBuffer(mBytes, RawBuffer<T>::ResetMode::bufferOnly); - mBuffer.nextHeader(); - isHBClosed = mBuffer.isHBClosed(); - gbtId = RDHUtils::getFEEID(*mBuffer.getRDH()); - if (gbtId >= crateparams::sNGBTs) { - // FIXME: this is a problem of the header of some test files - gbtId = 0; + o2::framework::RawParser parser(mBytes.data(), mBytes.size()); + auto lastIt = parser.begin(); + for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { + lastIt = it; } - if (RDHUtils::getOffsetToNext(*mBuffer.getRDH()) > raw::sHeaderSizeInBytes) { - read(RDHUtils::getOffsetToNext(*mBuffer.getRDH()) - raw::sHeaderSizeInBytes); - // CAVEAT: to save memory / CPU time, the RawBuffer does not hold a copy of the buffer, - // but just a span of it. - // If we add bytes to mBytes, the vector can go beyond the capacity - // and the memory is re-allocated. - // If this happens, the span is no longer valid, and we can no longer - // call mBuffer.getRDH() until we pass it mBytes again - // To do so, you need to call: - // mBuffer.setBuffer(mBytes, RawBuffer<T>::ResetMode::bufferOnly); - // mBuffer.nextHeader(); + auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(lastIt.raw()); + isHBClosed = o2::raw::RDHUtils::getStop(rdhPtr); + auto offsetNext = o2::raw::RDHUtils::getOffsetToNext(rdhPtr); + if (offsetNext > sHeaderSize) { + read(offsetNext - sHeaderSize); } if (!sendCompleteHBs) { break; } } - - ++mHBCounters[gbtId]; - return true; } -template class RawFileReader<raw::RawUnit>; -template class RawFileReader<uint8_t>; - } // namespace mid } // namespace o2 From fb9f2d14605723e0d16082c712a63a80ae2f3624 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Fri, 11 Sep 2020 15:28:24 +0200 Subject: [PATCH 0593/1751] add some histogram helpers (#4239) --- Analysis/Core/include/Analysis/HistHelpers.h | 274 +++++++++++++++++++ Analysis/Tutorials/CMakeLists.txt | 5 + Analysis/Tutorials/src/histHelpersTest.cxx | 147 ++++++++++ 3 files changed, 426 insertions(+) create mode 100644 Analysis/Core/include/Analysis/HistHelpers.h create mode 100644 Analysis/Tutorials/src/histHelpersTest.cxx 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 <mario.kruger@cern.ch> +// +// Some helper templates to simplify working with histograms +// + +#ifndef HistHelpers_H +#define HistHelpers_H + +#include <TH1.h> +#include <TH2.h> +#include <TH3.h> +#include <THn.h> +#include <THnSparse.h> +#include <TObjArray.h> + +#include "Framework/Logger.h" + +namespace o2 +{ +namespace experimental +{ +namespace histhelpers +{ + +template <typename T> +struct is_shared_ptr : std::false_type { +}; +template <typename T> +struct is_shared_ptr<std::shared_ptr<T>> : 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<TH3>, std::shared_ptr<TH2>, std::shared_ptr<TH1>, std::shared_ptr<THn>, std::shared_ptr<THnSparse>>; + + template <typename T> + 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<T>::value) + mHistos[histID] = DownCast(hist); + else { + mHistos[histID] = DownCast(std::make_shared<T>(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<TH1>(), Get<TH2>(), Get<TH3>(), Get<THn>(), Get<THnSparse>() + template <typename T> + std::shared_ptr<T> Get(uint8_t histID) + { + return *std::get_if<std::shared_ptr<T>>(&mHistos[histID]); + } + + template <typename... Ts> + void Fill(uint8_t histID, Ts&&... position) + { + std::visit([this, &position...](auto&& hist) { GenericFill(hist, std::forward<Ts>(position)...); }, mHistos[histID]); + } + + private: + std::map<uint8_t, HistType> mHistos; + + // disallow user to call TObjArray::Add() + using TObjArray::Add; + + template <typename T, typename... Ts> + void GenericFill(std::shared_ptr<T> hist, const Ts&... position) + { + constexpr bool isValidTH3 = (std::is_same_v<TH3, T> && sizeof...(Ts) == 3); + constexpr bool isValidTH2 = (std::is_same_v<TH2, T> && sizeof...(Ts) == 2); + constexpr bool isValidTH1 = (std::is_same_v<TH1, T> && 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<THnBase, T>::value; + + if constexpr (isValidPrimitive) { + hist->Fill(static_cast<double>(position)...); + } else if constexpr (isValidComplex) { + // savety check for n dimensional histograms (runtime overhead) + // if(hist->GetNdimensions() != sizeof...(position)) return; + double tempArray[] = {static_cast<double>(position)...}; + hist->Fill(tempArray); + } + }; + + template <typename T> + HistType DownCast(std::shared_ptr<T> 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<TH3, T>) { + return std::static_pointer_cast<TH3>(hist); + } else if constexpr (std::is_base_of_v<TH2, T>) { + return std::static_pointer_cast<TH2>(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<double> binEdges{}; + int nBins{}; // 0 when bin edges are specified directly FIXME: make this std::optional +}; + +template <typename RootHist_t> +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<Axis>& 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<double>& binEdges) + { + mAxes.push_back({name, title, binEdges, 0}); + } + + std::shared_ptr<RootHist_t> 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<THnBase, RootHist_t>) + 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<Axis> mAxes; + std::shared_ptr<RootHist_t> 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<THnBase, RootHist_t>) { + return new RootHist_t(name.data(), title.data(), nDim, nBins, lowerBounds, upperBounds); + } else if constexpr (std::is_base_of_v<TH3, RootHist_t>) { + 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<TH2, RootHist_t>) { + 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<TH1, RootHist_t>) { + 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<THnBase, RootHist_t>) { + 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/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/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 <cmath> + +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<HistContainer> test{HistContainer("Test"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistContainer> kine{HistContainer("Kine"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistContainer> tpc{HistContainer("TPC"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistContainer> 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<TH1D> 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<TH2F> 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<double> 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<double> 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<THnI> 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<THnSparseC> 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<aod::Tracks, aod::TracksExtra>::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<TH2>(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<HistHelpersTest>("hist-helpers-test")}; +} From 7c508b67fe0fa6c48e9668a6c466887ec58d3601 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 11 Sep 2020 19:34:00 +0200 Subject: [PATCH 0594/1751] DPL Analysis: first draft for more generic index binding (#4325) --- Analysis/Tutorials/src/associatedExample.cxx | 31 +++++++------------ Framework/Core/include/Framework/ASoA.h | 23 +++++++++++--- Framework/Foundation/include/Framework/Pack.h | 4 +-- 3 files changed, 31 insertions(+), 27 deletions(-) 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<aod::EtaPhi> etaphi; - Produces<aod::EtaPhiPt> etaphipt; void process(aod::Tracks const& tracks) { for (auto& track : tracks) { float phi = asin(track.snp()) + track.alpha() + static_cast<float>(M_PI); float eta = log(tan(0.25f * static_cast<float>(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<aod::EtaPhi, aod::EtaPhiPt> const& concatenated) - { - LOGF(INFO, "ID: %d", collision.globalIndex()); - LOGF(INFO, "Tracks: %d", concatenated.size()); - } -}; - struct TTask { + using myCol = soa::Join<aod::Collisions, aod::CollisionsExtra>; void process(soa::Join<aod::Collisions, aod::CollisionsExtra>::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<myCol>().globalIndex(), track0.collision_as<myCol>().mult(), tracks.size()); + } } }; @@ -97,7 +89,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) return WorkflowSpec{ adaptAnalysisTask<ATask>("produce-etaphi"), adaptAnalysisTask<BTask>("consume-etaphi"), - adaptAnalysisTask<CTask>("consume-etaphi-twice"), adaptAnalysisTask<MTask>("produce-mult"), adaptAnalysisTask<TTask>("consume-mult")}; } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 01073b2ed94df..d4160f0d33a4c 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1110,6 +1110,13 @@ using JoinBase = decltype(join(std::declval<Ts>()...)); template <typename T1, typename T2> using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); +template <typename T1, typename T2> +constexpr auto is_binding_compatible_v() +{ + return framework::pack_size( + framework::intersected_pack_t<originals_pack_t<T1>, originals_pack_t<T2>>{}) > 0; +} + } // namespace o2::soa #define DECLARE_SOA_STORE() \ @@ -1220,24 +1227,30 @@ using ConcatBase = decltype(concat(std::declval<T1>(), std::declval<T2>())); return *mColumnIterator >= 0; \ } \ \ - binding_t::iterator _Getter_() const \ + template <typename T> \ + auto _Getter_##_as() const \ { \ assert(mBinding != nullptr); \ - return mBinding->begin() + *mColumnIterator; \ + return static_cast<T*>(mBinding)->begin() + *mColumnIterator; \ + } \ + \ + auto _Getter_() const \ + { \ + return _Getter_##_as<binding_t>(); \ } \ \ template <typename T> \ bool setCurrent(T* current) \ { \ - if constexpr (std::is_same_v<T, binding_t>) { \ + if constexpr (o2::soa::is_binding_compatible_v<T, binding_t>()) { \ assert(current != nullptr); \ this->mBinding = current; \ return true; \ } \ return false; \ } \ - binding_t* getCurrent() { return mBinding; } \ - binding_t* mBinding = nullptr; \ + binding_t* getCurrent() { return static_cast<binding_t*>(mBinding); } \ + void* mBinding = nullptr; \ }; \ static const o2::framework::expressions::BindingNode _Getter_##Id { _Label_, \ o2::framework::expressions::selectArrowType<_Type_>() } diff --git a/Framework/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index 0b97e72bd6feb..b357e51af53af 100644 --- a/Framework/Foundation/include/Framework/Pack.h +++ b/Framework/Foundation/include/Framework/Pack.h @@ -186,13 +186,13 @@ constexpr std::size_t has_type_at_t = decltype(select<W>( } // namespace template <typename W> -constexpr std::size_t has_type_at_v(o2::framework::pack<> p) +constexpr std::size_t has_type_at_v(o2::framework::pack<>) { return -1; } template <typename W, typename... Ts> -constexpr std::size_t has_type_at_v(o2::framework::pack<Ts...> p) +constexpr std::size_t has_type_at_v(o2::framework::pack<Ts...>) { return has_type_at_t<W, Ts...>; } From e8bd9fe610e7ce3cba6467b5e2a967509b1a788f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Sep 2020 23:39:33 +0200 Subject: [PATCH 0595/1751] Make TPC fwd/bwd time margins float --- .../TPC/include/DataFormatsTPC/TrackTPC.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 From 98a239e35ba0d69af8dd42ee1538c8b641a5a935 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Sep 2020 23:41:13 +0200 Subject: [PATCH 0596/1751] Enforce minimal fwd/bwd delta for CE crossing TPC tracks --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 2a572c58a2703..e894824d51742 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -172,6 +172,9 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* std::atomic_int clusterOffsetCounter; clusterOffsetCounter.store(0); + constexpr float MinDelta = 0.1; + float maxDriftTime = detParam.TPClength * vzbinInv; + #ifdef WITH_OPENMP #pragma omp parallel for if(!outputTracksMCTruth) num_threads(4) #endif @@ -179,7 +182,6 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* auto& oTrack = (*outputTracks)[iTmp]; const int i = trackSort[iTmp].first; float time0 = 0.f, tFwd = 0.f, tBwd = 0.f; - if (mTrackingCAO2Interface->GetParamContinuous()) { time0 = tracks[i].GetParam().GetTZOffset(); @@ -193,6 +195,9 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* auto& cl1 = data->clusters->clustersLinear[cacl1.num]; auto& cl2 = data->clusters->clustersLinear[cacl2.num]; delta = fabs(cl1.getTime() - cl2.getTime()) * 0.5f; + if (delta < MinDelta) { + delta = MinDelta; + } break; } } @@ -205,7 +210,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* float t2 = data->clusters->clustersLinear[c2.num].getTime(); auto times = std::minmax(t1, t2); tFwd = times.first - time0; - tBwd = time0 - (times.second - detParam.TPClength * vzbinInv); + tBwd = time0 - (times.second - maxDriftTime); } } From 24ec3f0bb03929f06ec9753e11958c2020f52a91 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Sep 2020 23:42:46 +0200 Subject: [PATCH 0597/1751] Add BunchFilling methods to get 1st and last filled bunch --- .../include/CommonDataFormat/BunchFilling.h | 2 ++ DataFormats/common/src/BunchFilling.cxx | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+) 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/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) { From 25b438c2389709e86489bd1ab2c1a0c01a66bda1 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Sep 2020 23:44:00 +0200 Subject: [PATCH 0598/1751] Add InteractionRecord method to get diff. in ns to other IR --- .../include/CommonDataFormat/InteractionRecord.h | 10 ++++++++++ .../include/FT0Reconstruction/InteractionTag.h | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) 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/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<InteractionTag> { 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<InteractionTag> 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"); From a3beec26e3aebdb5e094db4609c1edd8b08ddaef Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Sep 2020 23:53:53 +0200 Subject: [PATCH 0599/1751] PrimaryVertex min/max IR coverage support --- .../ReconstructionDataFormats/PrimaryVertex.h | 22 ++++++++++++++++--- .../Reconstruction/src/PrimaryVertex.cxx | 10 ++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) 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<TimeStampWithError<float, float>> 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<TimeStampWithError<float, float>> #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 <typename T> +struct is_messageable; +template <> +struct is_messageable<o2::dataformats::PrimaryVertex> : std::true_type { +}; +} // namespace framework + } // 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) From 93f769435babc71a3c6886803394e606d0a4221a Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Sep 2020 23:56:45 +0200 Subject: [PATCH 0600/1751] Validate P.Vertex by bunch filling, set min/max IR --- .../ReconstructionDataFormats/VtxTrackIndex.h | 7 +- .../GlobalTrackingWorkflow/CMakeLists.txt | 1 + .../src/PrimaryVertexingSpec.cxx | 25 ++-- .../include/DetectorsVertexing/PVertexer.h | 18 ++- .../DetectorsVertexing/PVertexerHelpers.h | 2 + .../DetectorsVertexing/PVertexerParams.h | 4 +- Detectors/Vertexing/src/PVertexer.cxx | 110 ++++++++++++++---- 7 files changed, 130 insertions(+), 37 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h index 0088c489e574f..b001d3f8a73c1 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h @@ -12,6 +12,9 @@ /// \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 <iosfwd> #include <string> @@ -32,7 +35,7 @@ class VtxTrackIndex : public AbstractRef<26, 3, 3> }; enum Flags : uint8_t { Contributor, // flag that it contributes to vertex fit - Attached, // flag that it is attached w/o contributing + Reserved, // Ambiguous, // flag that attachment is ambiguous NFlags }; @@ -49,3 +52,5 @@ std::ostream& operator<<(std::ostream& os, const o2::dataformats::VtxTrackIndex& } // namespace dataformats } // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index 2ab0a946f9025..c657d7dd35c97 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -23,6 +23,7 @@ o2_add_library(GlobalTrackingWorkflow O2::TPCWorkflow O2::FT0Workflow O2::ITSMFTWorkflow + O2::SimulationDataFormat O2::DetectorsVertexing) o2_add_executable(match-workflow diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx index a7a7901dc6d74..27995a0db2962 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx @@ -15,6 +15,8 @@ #include "DetectorsBase/Propagator.h" #include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" #include "SimulationDataFormat/MCEventLabel.h" +#include "CommonDataFormat/BunchFilling.h" +#include "SimulationDataFormat/DigitizationContext.h" using namespace o2::framework; @@ -30,6 +32,11 @@ void PrimaryVertexingSpec::init(InitContext& ic) mTimer.Stop(); mTimer.Reset(); mVertexer.setValidateWithFT0(mValidateWithFT0); + + // set bunch filling. Eventually, this should come from CCDB + const auto* digctx = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + const auto& bcfill = digctx->getBunchFilling(); + mVertexer.setBunchFilling(bcfill); mVertexer.init(); } @@ -48,7 +55,7 @@ void PrimaryVertexingSpec::run(ProcessingContext& pc) lblTPC = pc.inputs().get<gsl::span<o2::MCCompLabel>>("lblTPC"); } std::vector<PVertex> vertices; - std::vector<int> vertexTrackIDs; + std::vector<GIndex> vertexTrackIDs; std::vector<V2TRef> v2tRefs; std::vector<o2::MCEventLabel> lblVtx; @@ -57,12 +64,12 @@ void PrimaryVertexingSpec::run(ProcessingContext& pc) mVertexer.setStartIR({0, dh->firstTForbit}); mVertexer.process(tracksITSTPC, ft0Data, vertices, vertexTrackIDs, v2tRefs, lblITS, lblTPC, lblVtx); - pc.outputs().snapshot(Output{"GLO", "PVERTEX", 0, Lifetime::Timeframe}, vertices); - pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe}, v2tRefs); - pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe}, vertexTrackIDs); + pc.outputs().snapshot(Output{"GLO", "PVTX", 0, Lifetime::Timeframe}, vertices); + pc.outputs().snapshot(Output{"GLO", "PVTX_CONTIDREFS", 0, Lifetime::Timeframe}, v2tRefs); + pc.outputs().snapshot(Output{"GLO", "PVTX_CONTID", 0, Lifetime::Timeframe}, vertexTrackIDs); if (mUseMC) { - pc.outputs().snapshot(Output{"GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe}, lblVtx); + pc.outputs().snapshot(Output{"GLO", "PVTX_MCTR", 0, Lifetime::Timeframe}, lblVtx); } mTimer.Stop(); @@ -86,14 +93,14 @@ DataProcessorSpec getPrimaryVertexingSpec(bool validateWithFT0, bool useMC) inputs.emplace_back("fitInfo", "FT0", "RECPOINTS", 0, Lifetime::Timeframe); } - outputs.emplace_back("GLO", "PVERTEX", 0, Lifetime::Timeframe); - outputs.emplace_back("GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe); - outputs.emplace_back("GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_CONTID", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_CONTIDREFS", 0, Lifetime::Timeframe); if (useMC) { inputs.emplace_back("lblITS", "GLO", "TPCITS_ITSMC", 0, Lifetime::Timeframe); inputs.emplace_back("lblTPC", "GLO", "TPCITS_TPCMC", 0, Lifetime::Timeframe); - outputs.emplace_back("GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_MCTR", 0, Lifetime::Timeframe); } return DataProcessorSpec{ diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index 39870ec6e2b15..410cc95ab9cd1 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -16,9 +16,11 @@ #define O2_PVERTEXER_H #include <array> +#include <utility> #include "CommonConstants/LHCConstants.h" #include "CommonDataFormat/TimeStamp.h" #include "CommonDataFormat/RangeReference.h" +#include "CommonDataFormat/BunchFilling.h" #include "SimulationDataFormat/MCEventLabel.h" #include "SimulationDataFormat/MCCompLabel.h" #include "MathUtils/Utils.h" @@ -50,12 +52,14 @@ class PVertexer void init(); int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, - std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, + std::vector<PVertex>& vertices, std::vector<o2d::VtxTrackIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx); + int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, - std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); + std::vector<PVertex>& vertices, std::vector<o2d::VtxTrackIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); + static void createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, - const std::vector<PVertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, + const std::vector<PVertex> vertices, const std::vector<o2d::VtxTrackIndex> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, std::vector<o2::MCEventLabel>& lblVtx); bool findVertex(const VertexingInput& input, PVertex& vtx); @@ -68,6 +72,9 @@ class PVertexer float getTukey() const; void finalizeVertex(const VertexingInput& input, const PVertex& vtx, std::vector<PVertex>& vertices, std::vector<V2TRef>& v2tRefs, std::vector<int>& vertexTrackIDs, SeedHisto& histo); + bool setCompatibleIR(PVertex& vtx); + + void setBunchFilling(const o2::BunchFilling& bf); void setBz(float bz) { mBz = bz; } void setValidateWithFT0(bool v) { mValidateWithFT0 = v; } @@ -105,8 +112,11 @@ class PVertexer void clusterizeTimeBruteForce(float margin = 0.1, float cut = 25); void clusterizeTime(float binSize = 0.1, float maxTDist = 0.6); int findVertices(const VertexingInput& input, std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); - int getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const; + std::pair<int, int> getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const; + o2::BunchFilling mBunchFilling; + std::array<int16_t, o2::constants::lhc::LHCMaxBunches> mClosestBunchAbove; // closest filled bunch from above + std::array<int16_t, o2::constants::lhc::LHCMaxBunches> mClosestBunchBelow; // closest filled bunch from below o2d::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; std::array<float, 3> mXYConstraintInvErr = {1.0f, 0.f, 1.0f}; ///< nominal vertex constraint inverted errors^2 // diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h index 98275a1124595..3d3b322fcff17 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h @@ -18,6 +18,7 @@ #include "gsl/span" #include "ReconstructionDataFormats/PrimaryVertex.h" #include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/VtxTrackIndex.h" #include "CommonDataFormat/TimeStamp.h" #include "CommonDataFormat/RangeReference.h" @@ -29,6 +30,7 @@ namespace vertexing using PVertex = o2::dataformats::PrimaryVertex; using TimeEst = o2::dataformats::TimeStampWithError<float, float>; using V2TRef = o2::dataformats::RangeReference<int, int>; +using GIndex = o2::dataformats::VtxTrackIndex; ///< weights and scaling params for current vertex struct VertexSeed : public PVertex { diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h index 128c0ca436a6b..42c45afdadbe4 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -41,7 +41,9 @@ struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParam int minNContributorsForFT0cut = 4; ///< do not apply FT0 cut to vertice below FT0 efficiency threshold float maxTError = 0.2; ///< use min of vertex time error or this for nsigma evaluation float minTError = 0.003; ///< don't use error smaller than that (~BC/2/minNContributorsForFT0cut) - float nSigmaFT0cut = 4.; ///< eliminate vertex if there is no FT0 signal within this cut + float nSigmaTimeCut = 4.; ///< eliminate vertex if there is no FT0 signal within this cut + float timeBiasMS = -0.035; ///< relative bias in ms to add to TPCITS-based time stamp + // // stopping condition params float maxChi2Mean = 10.; ///< max mean chi2 of vertex to accept diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index 5f94a5bb585ac..bb37951a7ad82 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -27,7 +27,7 @@ constexpr float PVertexer::kHugeF; //___________________________________________________________________ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, - std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) + std::vector<PVertex>& vertices, std::vector<GIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) { createTracksPool(tracksITSTPC); @@ -59,37 +59,46 @@ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span vertexTrackIDs.clear(); vertices.reserve(verticesLoc.size()); v2tRefs.reserve(v2tRefsLoc.size()); - vertexTrackIDs.resize(vertexTrackIDsLoc.size()); + vertexTrackIDs.reserve(vertexTrackIDsLoc.size()); int trCopied = 0, count = 0, vtimeID = 0; for (auto i : vtTimeSortID) { auto& vtx = verticesLoc[i]; + + bool irSet = setCompatibleIR(vtx); + if (!irSet) { + continue; + } // do we need to validate by FT0 ? if (mValidateWithFT0) { auto bestMatch = getBestFT0Trigger(vtx, ft0Data, vtimeID); - if (bestMatch >= 0) { // RS FIXME eventually, we should assign the IR to vertex? + if (bestMatch.first >= 0) { vtx.setFlags(PVertex::TimeValidated); - vtx.setIR(ft0Data[bestMatch].getInteractionRecord()); - LOG(DEBUG) << "Validated with t0" << bestMatch; + if (bestMatch.second == 1) { + vtx.setIR(ft0Data[bestMatch.first].getInteractionRecord()); + } + LOG(DEBUG) << "Validated with t0 " << bestMatch.first << " with " << bestMatch.second << " candidates"; } else if (vtx.getNContributors() >= mPVParams->minNContributorsForFT0cut) { LOG(DEBUG) << "Discarding " << vtx; continue; // reject } } vertices.push_back(vtx); - memcpy(&vertexTrackIDs[trCopied], &vertexTrackIDsLoc[v2tRefsLoc[i].getFirstEntry()], v2tRefsLoc[i].getEntries() * sizeof(int)); - v2tRefs.emplace_back(trCopied, v2tRefsLoc[i].getEntries()); - trCopied += v2tRefsLoc[i].getEntries(); + int it = v2tRefsLoc[i].getFirstEntry(), itEnd = it + v2tRefsLoc[i].getEntries(), dest0 = vertexTrackIDs.size(); + for (; it < itEnd; it++) { + auto& gid = vertexTrackIDs.emplace_back(vertexTrackIDsLoc[it], GIndex::TPCITS); + gid.setBit(GIndex::Contributor); + } + v2tRefs.emplace_back(dest0, v2tRefsLoc[i].getEntries()); LOG(DEBUG) << "#" << count++ << " " << vertices.back() << " | " << v2tRefs.back().getEntries() << " indices from " << v2tRefs.back().getFirstEntry(); // RS REM } - vertexTrackIDs.resize(trCopied); return vertices.size(); } //___________________________________________________________________ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data, - std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, + std::vector<PVertex>& vertices, std::vector<GIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs, gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx) { auto nv = process(tracksITSTPC, ft0Data, vertices, vertexTrackIDs, v2tRefs); @@ -604,7 +613,7 @@ void PVertexer::clusterizeTime(float binSize, float maxTDist) //___________________________________________________________________ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, - const std::vector<PVertex> vertices, const std::vector<int> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, + const std::vector<PVertex> vertices, const std::vector<o2::dataformats::VtxTrackIndex> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, std::vector<o2::MCEventLabel>& lblVtx) { lblVtx.clear(); @@ -636,7 +645,7 @@ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::spa labelOccurenceITS.clear(); o2::MCEventLabel winner; // unset at the moment for (; tref < last; tref++) { - int tid = vertexTrackIDs[tref]; + int tid = vertexTrackIDs[tref].getIndex(); const auto& lITS = lblITS[tid]; const auto& lTPC = lblTPC[tid]; if (!lITS.isSet() || !lTPC.isSet()) { @@ -658,23 +667,23 @@ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::spa } //___________________________________________________________________ -int PVertexer::getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const +std::pair<int, int> PVertexer::getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const { - // check if the times stamp is compatible with any entry startinge from currEntry in ft0Data vector, return best matching time + // select best matching FT0 recpoint int best = -1, n = ft0Data.size(); - auto t = vtx.getTimeStamp(); - float cut = mPVParams->nSigmaFT0cut * mPVParams->maxTError, bestDf = cut, df = 0; - while (currEntry < n && mFT0Params->getInteractionTimeNS(ft0Data[currEntry], mStartIR) * 1e-3 + cut < t.getTimeStamp()) { + while (currEntry < n && ft0Data[currEntry].getInteractionRecord() < vtx.getIRMin()) { currEntry++; // skip all times which have no chance to be matched } - cut = mPVParams->nSigmaFT0cut * std::min(mPVParams->maxTError, std::max(mPVParams->minTError, t.getTimeStampError())); - int i = currEntry; + int i = currEntry, nCompatible = 0; + float bestDf = 1e12; + auto tVtxNS = (vtx.getTimeStamp().getTimeStamp() + mPVParams->timeBiasMS) * 1e3; // time in ns while (i < n) { - if ((df = mFT0Params->getInteractionTimeNS(ft0Data[i], mStartIR) * 1e-3) > bestDf) { + if (ft0Data[i].getInteractionRecord() > vtx.getIRMax()) { break; } if (mFT0Params->isSelected(ft0Data[i])) { - auto dfa = std::abs(df); + nCompatible++; + auto dfa = std::abs(mFT0Params->getInteractionTimeNS(ft0Data[i], mStartIR) - tVtxNS); if (dfa <= bestDf) { bestDf = dfa; best = i; @@ -682,5 +691,62 @@ int PVertexer::getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::Re } i++; } - return best; + return {best, nCompatible}; +} + +//___________________________________________________________________ +void PVertexer::setBunchFilling(const o2::BunchFilling& bf) +{ + mBunchFilling = bf; + // find closest (from above) filled bunch + int minBC = bf.getFirstFilledBC(), maxBC = bf.getLastFilledBC(); + if (minBC < 0) { + throw std::runtime_error("Bunch filling is not set in PVertexer"); + } + int bcAbove = minBC; + for (int i = o2::constants::lhc::LHCMaxBunches; i--;) { + if (bf.testBC(i)) { + bcAbove = i; + } + mClosestBunchAbove[i] = bcAbove; + } + int bcBelow = maxBC; + for (int i = 0; i < o2::constants::lhc::LHCMaxBunches; i++) { + if (bf.testBC(i)) { + bcBelow = i; + } + mClosestBunchBelow[i] = bcBelow; + } +} + +//___________________________________________________________________ +bool PVertexer::setCompatibleIR(PVertex& vtx) +{ + // assign compatible IRs accounting for the bunch filling scheme + const auto& vtxT = vtx.getTimeStamp(); + o2::InteractionRecord irMin(mStartIR), irMax(mStartIR); + auto rangeT = mPVParams->nSigmaTimeCut * std::max(mPVParams->minTError, std::min(mPVParams->maxTError, vtxT.getTimeStampError())); + float t = vtxT.getTimeStamp() + mPVParams->timeBiasMS; + if (t > rangeT) { + irMin += o2::InteractionRecord(1.e3 * (t - rangeT)); + } + irMax += o2::InteractionRecord(1.e3 * (t + rangeT)); + irMax++; // to account for rounding + // restrict using bunch filling + int bc = mClosestBunchAbove[irMin.bc]; + if (bc < irMin.bc) { + irMin.orbit++; + } + irMin.bc = bc; + bc = mClosestBunchBelow[irMax.bc]; + if (bc > irMax.bc) { + if (irMax.orbit == 0) { + return false; + } + irMax.orbit--; + } + irMax.bc = bc; + vtx.setIRMin(irMin); + vtx.setIRMax(irMax); + return irMax >= irMin; } From f093899a46d8e980cbb7402026a6a3266318aee3 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 14 Sep 2020 00:08:02 +0200 Subject: [PATCH 0601/1751] P.Vertex-tracks matching class + related workflows update At the moment the pr.vertex - track matching is done in time only (except vertex fit contributor TPC/ITS tracks), for every vertex list of global indices (VtxTrackIndex) is added, providing the source (global, or ITS or TPC track), ID in the source and bit flags for contributors and ambigous assignment. --- .../GlobalTrackingWorkflow/CMakeLists.txt | 2 + .../PrimaryVertexReaderSpec.h | 10 +- .../PrimaryVertexWriterSpec.h | 2 +- .../VertexTrackMatcherSpec.h | 50 ++++ .../src/PrimaryVertexReaderSpec.cxx | 57 ++-- .../src/PrimaryVertexWriterSpec.cxx | 13 +- .../src/VertexTrackMatcherSpec.cxx | 109 ++++++++ .../src/primary-vertexing-workflow.cxx | 14 +- Detectors/Vertexing/CMakeLists.txt | 5 + .../DetectorsVertexing/VertexTrackMatcher.h | 88 +++++++ .../Vertexing/src/DetectorsVertexingLinkDef.h | 1 + .../Vertexing/src/VertexTrackMatcher.cxx | 246 ++++++++++++++++++ 12 files changed, 571 insertions(+), 26 deletions(-) create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/VertexTrackMatcherSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx create mode 100644 Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h create mode 100644 Detectors/Vertexing/src/VertexTrackMatcher.cxx diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index c657d7dd35c97..ce3b5df0d4986 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -17,6 +17,7 @@ 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 @@ -41,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<int, int>; 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<PVertex> mVertices, *mVerticesPtr = &mVertices; - std::vector<int> mPVTrIdx, *mPVTrIdxPtr = &mPVTrIdx; - std::vector<V2TRef> mPV2TrIdx, *mPV2TrIdxPtr = &mPV2TrIdx; std::vector<Label> mLabels, *mLabelsPtr = &mLabels; + std::vector<V2TRef> mPV2MatchIdxRef, *mPV2MatchIdxRefPtr = &mPV2MatchIdxRef; + std::vector<GIndex> mPV2MatchIdx, *mPV2MatchIdxPtr = &mPV2MatchIdx; std::unique_ptr<TFile> mFile; std::unique_ptr<TTree> mTree; std::string mFileName = ""; + std::string mFileNameMatches = ""; std::string mVertexTreeName = "o2sim"; std::string mVertexBranchName = "PrimaryVertex"; std::string mVertexTrackIDsBranchName = "PVTrackIndices"; diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h index 8da592ee5a45a..b722866e17e52 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h @@ -21,7 +21,7 @@ namespace vertexing { /// create a processor spec -framework::DataProcessorSpec getPrimaryVertexWriterSpec(bool useMC); +framework::DataProcessorSpec getPrimaryVertexWriterSpec(bool disableMatching, bool useMC); } // namespace vertexing } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/VertexTrackMatcherSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/VertexTrackMatcherSpec.h new file mode 100644 index 0000000000000..418331b3c6445 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/VertexTrackMatcherSpec.h @@ -0,0 +1,50 @@ +// 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_VERTEX_TRACK_MATCHER_SPEC_H +#define O2_VERTEX_TRACK_MATCHER_SPEC_H + +/// @file VertexTrackMatcherSpec.h +/// @brief Specs for vertex track association device +/// @author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/VertexTrackMatcher.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "TStopwatch.h" + +namespace o2 +{ +namespace vertexing +{ + +using namespace o2::framework; + +class VertexTrackMatcherSpec : public Task +{ + public: + VertexTrackMatcherSpec() = default; + ~VertexTrackMatcherSpec() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + void endOfStream(EndOfStreamContext& ec) final; + + private: + o2::vertexing::VertexTrackMatcher mMatcher; + TStopwatch mTimer; +}; + +/// create a processor spec +DataProcessorSpec getVertexTrackMatcherSpec(); + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx index 55f1ef2a10048..f5154c08f7d90 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx @@ -27,7 +27,7 @@ namespace vertexing void PrimaryVertexReader::init(InitContext& ic) { mFileName = ic.options().get<std::string>("primary-vertex-infile"); - connectTree(mFileName); + connectTree(); } void PrimaryVertexReader::run(ProcessingContext& pc) @@ -37,12 +37,37 @@ void PrimaryVertexReader::run(ProcessingContext& pc) mTree->GetEntry(ent); LOG(INFO) << "Pushing " << mVerticesPtr->size() << " vertices at entry " << ent; - pc.outputs().snapshot(Output{"GLO", "PVERTEX", 0, Lifetime::Timeframe}, mVertices); - pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe}, mPV2TrIdx); - pc.outputs().snapshot(Output{"GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe}, mPVTrIdx); + pc.outputs().snapshot(Output{"GLO", "PVTX", 0, Lifetime::Timeframe}, mVertices); + pc.outputs().snapshot(Output{"GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe}, mPV2MatchIdx); + pc.outputs().snapshot(Output{"GLO", "PVTX_TRMTCREF", 0, Lifetime::Timeframe}, mPV2MatchIdxRef); if (mUseMC) { - pc.outputs().snapshot(Output{"GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe}, mLabels); + pc.outputs().snapshot(Output{"GLO", "PVTX_MCTR", 0, Lifetime::Timeframe}, mLabels); + } + + if (mVerbose) { + int cnt = 0; + for (const auto& vtx : mVertices) { + Label lb; + if (mUseMC) { + lb = mLabels[cnt]; + } + LOG(INFO) << "#" << cnt << " " << vtx << "| NAttached= " << mPV2MatchIdxRef[cnt].getEntries() << " | MC:" << lb; + int idMin = mPV2MatchIdxRef[cnt].getFirstEntry(), idMax = idMin + mPV2MatchIdxRef[cnt].getEntries(); + std::string trIDs; + int cntT = 0; + for (int i = idMin; i < idMax; i++) { + trIDs += mPV2MatchIdx[i].asString() + " "; + if (!((++cntT) % 15)) { + LOG(INFO) << trIDs; + trIDs = ""; + } + } + if (!trIDs.empty()) { + LOG(INFO) << trIDs; + } + cnt++; + } } if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) { @@ -51,10 +76,10 @@ void PrimaryVertexReader::run(ProcessingContext& pc) } } -void PrimaryVertexReader::connectTree(const std::string& filename) +void PrimaryVertexReader::connectTree() { mTree.reset(nullptr); // in case it was already loaded - mFile.reset(TFile::Open(filename.c_str())); + mFile.reset(TFile::Open(mFileName.c_str())); assert(mFile && !mFile->IsZombie()); mTree.reset((TTree*)mFile->Get(mVertexTreeName.c_str())); assert(mTree); @@ -63,25 +88,26 @@ void PrimaryVertexReader::connectTree(const std::string& filename) assert(mTree->GetBranch(mVertex2TrackIDRefsBranchName.c_str())); mTree->SetBranchAddress(mVertexBranchName.c_str(), &mVerticesPtr); - mTree->SetBranchAddress(mVertexTrackIDsBranchName.c_str(), &mPVTrIdxPtr); - mTree->SetBranchAddress(mVertex2TrackIDRefsBranchName.c_str(), &mPV2TrIdxPtr); + mTree->SetBranchAddress(mVertexTrackIDsBranchName.c_str(), &mPV2MatchIdxPtr); + mTree->SetBranchAddress(mVertex2TrackIDRefsBranchName.c_str(), &mPV2MatchIdxRefPtr); if (mUseMC) { assert(mTree->GetBranch(mVertexLabelsBranchName.c_str())); mTree->SetBranchAddress(mVertexLabelsBranchName.c_str(), &mLabelsPtr); } - LOG(INFO) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries"; + LOG(INFO) << "Loaded " << mVertexTreeName << " tree from " << mFileName << " with " << mTree->GetEntries() << " entries"; } DataProcessorSpec getPrimaryVertexReaderSpec(bool useMC) { std::vector<OutputSpec> outputs; - outputs.emplace_back("GLO", "PVERTEX", 0, Lifetime::Timeframe); - outputs.emplace_back("GLO", "PVERTEX_TRIDREFS", 0, Lifetime::Timeframe); - outputs.emplace_back("GLO", "PVERTEX_TRID", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_TRMTCREF", 0, Lifetime::Timeframe); + if (useMC) { - outputs.emplace_back("GLO", "PVERTEX_MCTR", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_MCTR", 0, Lifetime::Timeframe); } return DataProcessorSpec{ @@ -90,7 +116,8 @@ DataProcessorSpec getPrimaryVertexReaderSpec(bool useMC) outputs, AlgorithmSpec{adaptFromTask<PrimaryVertexReader>(useMC)}, Options{ - {"primary-vertex-infile", VariantType::String, "o2_primary_vertex.root", {"Name of the input primary vertex file"}}}}; + {"primary-vertex-infile", VariantType::String, "o2_primary_vertex.root", {"Name of the input primary vertex file"}}, + {"vertex-track-matches-infile", VariantType::String, "o2_pvertex_track_matches.root", {"Name of the input file with primary vertex - tracks matches"}}}}; } } // namespace vertexing diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx index 51478d775cd1c..14770ca5e3be2 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexWriterSpec.cxx @@ -33,19 +33,20 @@ using Label = o2::MCEventLabel; using namespace o2::header; -DataProcessorSpec getPrimaryVertexWriterSpec(bool useMC) +DataProcessorSpec getPrimaryVertexWriterSpec(bool disableMatching, bool useMC) { auto logger = [](std::vector<PVertex> const& v) { LOG(INFO) << "PrimaryVertexWriter pulled " << v.size() << " vertices"; }; - + auto inpID = disableMatching ? InputSpec{"vttrackID", "GLO", "PVTX_CONTID", 0} : InputSpec{"vttrackID", "GLO", "PVTX_TRMTC", 0}; + auto inpIDRef = disableMatching ? InputSpec{"v2tref", "GLO", "PVTX_CONTIDREFS", 0} : InputSpec{"v2tref", "GLO", "PVTX_TRMTCREFS", 0}; return MakeRootTreeWriterSpec("primary-vertex-writer", "o2_primary_vertex.root", MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree with Primary Vertices"}, - BranchDefinition<std::vector<PVertex>>{InputSpec{"vertices", "GLO", "PVERTEX", 0}, "PrimaryVertex", logger}, - BranchDefinition<std::vector<V2TRef>>{InputSpec{"v2tref", "GLO", "PVERTEX_TRIDREFS", 0}, "PV2TrackRefs"}, - BranchDefinition<std::vector<int>>{InputSpec{"vttrackID", "GLO", "PVERTEX_TRID", 0}, "PVTrackIndices"}, - BranchDefinition<std::vector<Label>>{InputSpec{"labels", "GLO", "PVERTEX_MCTR", 0}, "PVMCTruth", (useMC ? 1 : 0), ""})(); + BranchDefinition<std::vector<PVertex>>{InputSpec{"vertices", "GLO", "PVTX", 0}, "PrimaryVertex", logger}, + BranchDefinition<std::vector<V2TRef>>{inpIDRef, "PV2TrackRefs"}, + BranchDefinition<std::vector<GIndex>>{inpID, "PVTrackIndices"}, + BranchDefinition<std::vector<Label>>{InputSpec{"labels", "GLO", "PVTX_MCTR", 0}, "PVMCTruth", (useMC ? 1 : 0), ""})(); } } // namespace vertexing diff --git a/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx new file mode 100644 index 0000000000000..45904dade5560 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx @@ -0,0 +1,109 @@ +// 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 VertexTrackMatcherSpec.cxx +/// @brief Specs for vertex track association device +/// @author ruben.shahoyan@cern.ch + +#include "GlobalTrackingWorkflow/VertexTrackMatcherSpec.h" +#include "DataFormatsParameters/GRPObject.h" +#include "ITSMFTBase/DPLAlpideParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace vertexing +{ + +void VertexTrackMatcherSpec::init(InitContext& ic) +{ + //-------- init geometry and field --------// + mTimer.Stop(); + mTimer.Reset(); + + mMatcher.init(); +} + +void VertexTrackMatcherSpec::run(ProcessingContext& pc) +{ + double timeCPU0 = mTimer.CpuTime(), timeReal0 = mTimer.RealTime(); + mTimer.Start(false); + + // eventually, this should be set per TF from CCDB? + if (mMatcher.getITSROFrameLengthInBC() == 0) { + std::unique_ptr<o2::parameters::GRPObject> grp{o2::parameters::GRPObject::loadFrom(o2::base::NameConf::getGRPFileName())}; + const auto& alpParams = o2::itsmft::DPLAlpideParam<o2::detectors::DetID::ITS>::Instance(); + if (grp->isDetContinuousReadOut(o2::detectors::DetID::ITS)) { + mMatcher.setITSROFrameLengthInBC(alpParams.roFrameLengthInBC); + } else { + mMatcher.setITSROFrameLengthInBC(alpParams.roFrameLengthTrig / o2::constants::lhc::LHCOrbitNS); + } + } + + // RS FIXME this will not have effect until the 1st orbit is propagated, until that will work only for TF starting at orbit 0 + const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("vertices").header); + mMatcher.setStartIR({0, dh->firstTForbit}); + + const auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("tpcits"); + const auto tracksTPC = pc.inputs().get<gsl::span<o2::tpc::TrackTPC>>("tpc"); + const auto tracksITS = pc.inputs().get<gsl::span<o2::its::TrackITS>>("its"); + const auto tracksITSROF = pc.inputs().get<gsl::span<o2::itsmft::ROFRecord>>("itsROF"); + const auto vertices = pc.inputs().get<gsl::span<o2::dataformats::PrimaryVertex>>("vertices"); + const auto vtxTracks = pc.inputs().get<gsl::span<o2::dataformats::VtxTrackIndex>>("vtxTracks"); + const auto vtxTrackRefs = pc.inputs().get<gsl::span<o2::dataformats::RangeReference<int, int>>>("vtxTrackRefs"); + + std::vector<o2::dataformats::VtxTrackIndex> trackIndex; + std::vector<o2::dataformats::RangeReference<int, int>> vtxRefs; + + mMatcher.process(vertices, vtxTracks, vtxTrackRefs, tracksITSTPC, tracksITS, tracksITSROF, tracksTPC, trackIndex, vtxRefs); + + pc.outputs().snapshot(Output{"GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe}, trackIndex); + pc.outputs().snapshot(Output{"GLO", "PVTX_TRMTCREFS", 0, Lifetime::Timeframe}, vtxRefs); + + mTimer.Stop(); + LOG(INFO) << "Made " << trackIndex.size() << " track associationgs for " << vertices.size() << " vertices, timing: CPU: " + << mTimer.CpuTime() - timeCPU0 << " Real: " << mTimer.RealTime() - timeReal0 << " s"; +} + +void VertexTrackMatcherSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "Primary vertex - track matching total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getVertexTrackMatcherSpec() +{ + std::vector<InputSpec> inputs; + std::vector<OutputSpec> outputs; + + inputs.emplace_back("tpcits", "GLO", "TPCITS", 0, Lifetime::Timeframe); + inputs.emplace_back("its", "ITS", "TRACKS", 0, Lifetime::Timeframe); + inputs.emplace_back("itsROF", "ITS", "ITSTrackROF", 0, Lifetime::Timeframe); + inputs.emplace_back("tpc", "TPC", "TRACKS", 0, Lifetime::Timeframe); + + inputs.emplace_back("vertices", "GLO", "PVTX", 0, Lifetime::Timeframe); + inputs.emplace_back("vtxTracks", "GLO", "PVTX_CONTID", 0, Lifetime::Timeframe); + inputs.emplace_back("vtxTrackRefs", "GLO", "PVTX_CONTIDREFS", 0, Lifetime::Timeframe); + + outputs.emplace_back("GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_TRMTCREFS", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "pvertex-track-matching", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<VertexTrackMatcherSpec>()}, + Options{}}; +} + +} // namespace vertexing +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx index bbc6ac2a20071..a7fd115237c5a 100644 --- a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx @@ -11,6 +11,9 @@ #include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" #include "GlobalTrackingWorkflow/PrimaryVertexWriterSpec.h" #include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" +#include "GlobalTrackingWorkflow/VertexTrackMatcherSpec.h" +#include "ITSWorkflow/TrackReaderSpec.h" +#include "TPCWorkflow/TrackReaderSpec.h" #include "FT0Workflow/RecPointReaderSpec.h" #include "CommonUtils/ConfigurableParam.h" @@ -30,6 +33,7 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, {"validate-with-ft0", o2::framework::VariantType::Bool, false, {"use FT0 time for vertex validation"}}, + {"disable-vertex-track-matching", o2::framework::VariantType::Bool, false, {"disable matching of vertex to non-contributor tracks"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; std::swap(workflowOptions, options); @@ -50,6 +54,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto disableRootInp = configcontext.options().get<bool>("disable-root-input"); auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); auto validateWithFT0 = configcontext.options().get<bool>("validate-with-ft0"); + auto disableMatching = configcontext.options().get<bool>("disable-vertex-track-matching"); WorkflowSpec specs; if (!disableRootInp) { @@ -59,8 +64,15 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } } specs.emplace_back(o2::vertexing::getPrimaryVertexingSpec(validateWithFT0, useMC)); + + if (!disableMatching) { + specs.emplace_back(o2::its::getITSTrackReaderSpec(false)); + specs.emplace_back(o2::tpc::getTPCTrackReaderSpec(false)); + specs.emplace_back(o2::vertexing::getVertexTrackMatcherSpec()); + } + if (!disableRootOut) { - specs.emplace_back(o2::vertexing::getPrimaryVertexWriterSpec(useMC)); + specs.emplace_back(o2::vertexing::getPrimaryVertexWriterSpec(disableMatching, useMC)); } return std::move(specs); } diff --git a/Detectors/Vertexing/CMakeLists.txt b/Detectors/Vertexing/CMakeLists.txt index a650d99a4e91b..3cb55ae1654b8 100644 --- a/Detectors/Vertexing/CMakeLists.txt +++ b/Detectors/Vertexing/CMakeLists.txt @@ -13,9 +13,13 @@ o2_add_library(DetectorsVertexing src/PVertexer.cxx src/PVertexerHelpers.cxx src/PVertexerParams.cxx + src/VertexTrackMatcher.cxx PUBLIC_LINK_LIBRARIES ROOT::Core O2::CommonUtils O2::ReconstructionDataFormats + O2::DataFormatsTPC + O2::DataFormatsITS + O2::TPCBase O2::SimulationDataFormat O2::FT0Reconstruction O2::DataFormatsFT0 @@ -25,6 +29,7 @@ o2_target_root_dictionary(DetectorsVertexing HEADERS include/DetectorsVertexing/HelixHelper.h include/DetectorsVertexing/PVertexer.h include/DetectorsVertexing/PVertexerHelpers.h + include/DetectorsVertexing/VertexTrackMatcher.h include/DetectorsVertexing/DCAFitterN.h) o2_add_test( diff --git a/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h new file mode 100644 index 0000000000000..6e2c00b314569 --- /dev/null +++ b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h @@ -0,0 +1,88 @@ +// 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 VertexTrackMatcher.h +/// \brief Class for vertex track association +/// \author ruben.shahoyan@cern.ch + +#ifndef ALICEO2_VERTEX_TRACK_MATCHER_ +#define ALICEO2_VERTEX_TRACK_MATCHER_ + +#include "gsl/span" +#include "ReconstructionDataFormats/PrimaryVertex.h" +#include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "DataFormatsITS/TrackITS.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DetectorsVertexing/PVertexerParams.h" +#include "MathUtils/Bracket.h" + +namespace o2 +{ +namespace vertexing +{ + +class VertexTrackMatcher +{ + public: + using GIndex = o2::dataformats::VtxTrackIndex; + using RRef = o2::dataformats::RangeReference<int, int>; + using PVertex = const o2::dataformats::PrimaryVertex; + using TrackTPCITS = o2::dataformats::TrackTPCITS; + using TrackITS = o2::its::TrackITS; + using ITSROFR = o2::itsmft::ROFRecord; + using TrackTPC = o2::tpc::TrackTPC; + using TmpMap = std::unordered_map<int, std::vector<GIndex>>; + using TimeEst = o2::dataformats::TimeStampWithError<float, float>; + using TBracket = o2::utils::Bracket<float>; + + void init(); + void process(const gsl::span<const PVertex>& vertices, // vertices + const gsl::span<const GIndex>& v2tfitIDs, // IDs of contributor tracks used in fit + const gsl::span<const RRef>& v2tfitRefs, // references on these tracks + const gsl::span<const TrackTPCITS>& tpcits, // global tracks + const gsl::span<const TrackITS>& its, // ITS tracks + const gsl::span<const ITSROFR>& itsROFR, // ITS tracks ROFRecords + const gsl::span<const TrackTPC>& tpc, // TPC tracks + std::vector<GIndex>& trackIndex, // Global ID's for associated tracks + std::vector<RRef>& vtxRefs); // references on these tracks + + ///< set InteractionRecods for the beginning of the TF + void setStartIR(const o2::InteractionRecord& ir) { mStartIR = ir; } + void setITSROFrameLengthInBC(int nbc); + int getITSROFrameLengthInBC() const { return mITSROFrameLengthInBC; } + + private: + void attachTPCITS(TmpMap& tmpMap, const gsl::span<const TrackTPCITS>& tpcits, const std::vector<int>& idTPCITS, const gsl::span<const PVertex>& vertices); + void attachITS(TmpMap& tmpMap, const gsl::span<const TrackITS>& its, const gsl::span<const ITSROFR>& itsROFR, const std::vector<int>& flITS, + const gsl::span<const PVertex>& vertices, std::vector<int>& idxVtx); + void attachTPC(TmpMap& tmpMap, const std::vector<TBracket>& tpcTimes, const std::vector<int>& idTPC, const gsl::span<const PVertex>& vertices, std::vector<int>& idVtx); + bool compatibleTimes(const TimeEst& vtxT, const TimeEst& trcT) const; + void updateTPCTimeDependentParams(); + float tpcTimeBin2MUS(float t) + { // convert TPC time bin to microseconds + return t * mTPCBin2MUS; + } + + o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF + int mITSROFrameLengthInBC = 0; ///< ITS RO frame in BC (for ITS cont. mode only) + float mMaxTPCDriftTimeMUS = 0; + float mTPCBin2MUS = 0; + const o2::vertexing::PVertexerParams* mPVParams = nullptr; + + ClassDefNV(VertexTrackMatcher, 1); +}; + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h b/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h index 331aad662a1c4..7c50e9ebd0e69 100644 --- a/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h +++ b/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h @@ -21,6 +21,7 @@ #pragma link C++ class o2::vertexing::PVertexer + ; #pragma link C++ class o2::vertexing::PVertexerParams + ; +#pragma link C++ class o2::vertexing::VertexTrackMatcher + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::vertexing::PVertexerParams> + ; #pragma link C++ class o2::track::TrackAuxPar + ; diff --git a/Detectors/Vertexing/src/VertexTrackMatcher.cxx b/Detectors/Vertexing/src/VertexTrackMatcher.cxx new file mode 100644 index 0000000000000..ccd9b4a805836 --- /dev/null +++ b/Detectors/Vertexing/src/VertexTrackMatcher.cxx @@ -0,0 +1,246 @@ +// 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 VertexTrackMatcher.cxx +/// \brief Class for vertex track association +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/VertexTrackMatcher.h" +#include <unordered_map> +#include <numeric> +#include "TPCBase/ParameterElectronics.h" +#include "TPCBase/ParameterDetector.h" +#include "TPCBase/ParameterGas.h" + +using namespace o2::vertexing; + +//___________________________________________________________________ +void VertexTrackMatcher::init() +{ + mPVParams = &o2::vertexing::PVertexerParams::Instance(); + updateTPCTimeDependentParams(); // RS FIXME eventually should be set from CCDB for every TF +} + +void VertexTrackMatcher::updateTPCTimeDependentParams() +{ + // tpc time bin in microseconds + auto& gasParam = o2::tpc::ParameterGas::Instance(); + auto& elParam = o2::tpc::ParameterElectronics::Instance(); + auto& detParam = o2::tpc::ParameterDetector::Instance(); + mTPCBin2MUS = elParam.ZbinWidth; + mMaxTPCDriftTimeMUS = detParam.TPClength / gasParam.DriftV; +} + +void VertexTrackMatcher::process(const gsl::span<const PVertex>& vertices, + const gsl::span<const GIndex>& v2tfitIDs, + const gsl::span<const RRef>& v2tfitRefs, + const gsl::span<const TrackTPCITS>& tpcitsTracks, + const gsl::span<const TrackITS>& itsTracks, + const gsl::span<const ITSROFR>& itsROFR, + const gsl::span<const TrackTPC>& tpcTracks, + std::vector<GIndex>& trackIndex, + std::vector<RRef>& vtxRefs) +{ + + TmpMap tmpMap; + tmpMap.reserve(vertices.size()); + + // TPC/ITS and TPC tracks are not sorted in time, do this and exclude indiced of tracks used in the vertex fit + std::vector<int> idTPCITS(tpcitsTracks.size()); // indices of TPCITS tracks sorted in time + std::vector<int> idVtxIRMin(vertices.size()); // indices of vertices sorted in IRmin + std::vector<int> flgITS(itsTracks.size(), 0); + std::vector<int> idTPC(tpcTracks.size()); // indices of TPC tracks sorted in min time + std::iota(idTPC.begin(), idTPC.end(), 0); + std::iota(idTPCITS.begin(), idTPCITS.end(), 0); + std::iota(idVtxIRMin.begin(), idVtxIRMin.end(), 0); + for (auto id : v2tfitIDs) { // flag matched ITS-TPC tracks used in the vertex fit, we exclude them from this association + idTPCITS[id.getIndex()] = -1; + } + for (const auto& tpcits : tpcitsTracks) { // flag standalone ITS and TPC tracks used in global matched, we exclude them from association to vertex + flgITS[tpcits.getRefITS()] = -1; + idTPC[tpcits.getRefTPC()] = -1; + } + std::sort(idVtxIRMin.begin(), idVtxIRMin.end(), [&vertices](int i, int j) { // sort according to IRMin + return vertices[i].getIRMin() < vertices[j].getIRMin(); + }); + std::sort(idTPCITS.begin(), idTPCITS.end(), [&tpcitsTracks](int i, int j) { // sort according to central time + float tI = (i < 0) ? 1e9 : tpcitsTracks[i].getTimeMUS().getTimeStamp(); + float tJ = (j < 0) ? 1e9 : tpcitsTracks[j].getTimeMUS().getTimeStamp(); + return tI < tJ; + }); + + std::vector<TBracket> tpcTimes; + tpcTimes.reserve(tpcTracks.size()); + for (const auto& trc : tpcTracks) { + tpcTimes.emplace_back(tpcTimeBin2MUS(trc.getTime0() - trc.getDeltaTBwd()), tpcTimeBin2MUS(trc.getTime0() + trc.getDeltaTFwd())); + } + std::sort(idTPC.begin(), idTPC.end(), [&tpcTimes](int i, int j) { // sort according to max time + float tI = (i < 0) ? 1e9 : tpcTimes[i].max(); + float tJ = (j < 0) ? 1e9 : tpcTimes[j].max(); + return tI < tJ; + }); + + attachTPCITS(tmpMap, tpcitsTracks, idTPCITS, vertices); + attachITS(tmpMap, itsTracks, itsROFR, flgITS, vertices, idVtxIRMin); + attachTPC(tmpMap, tpcTimes, idTPC, vertices, idVtxIRMin); + + // build vector of global indices + trackIndex.clear(); + vtxRefs.clear(); + memset(idTPCITS.data(), 0, sizeof(int) * idTPCITS.size()); + memset(idTPC.data(), 0, sizeof(int) * idTPC.size()); + memset(flgITS.data(), 0, sizeof(int) * flgITS.size()); + std::array<std::vector<int>*, GIndex::NSources> vptr; + vptr[GIndex::TPCITS] = &idTPCITS; + vptr[GIndex::ITS] = &flgITS; + vptr[GIndex::TPC] = &idTPC; + int nv = vertices.size(); + // flag tracks attached to >1 vertex + for (int iv = 0; iv < nv; iv++) { + const auto& trvec = tmpMap[iv]; + for (auto gid : trvec) { + (*vptr[gid.getSource()])[gid.getIndex()]++; + } + } + for (int iv = 0; iv < nv; iv++) { + int entry = trackIndex.size(); + // 1st: attach indices of global tracks used in vertex fit + int idMin = v2tfitRefs[iv].getFirstEntry(), idMax = idMin + v2tfitRefs[iv].getEntries(); + for (int id = idMin; id < idMax; id++) { + trackIndex.push_back(v2tfitIDs[id]); + } + // 2nd: attach non-contributing tracks + const auto& trvec = tmpMap[iv]; + for (const auto gid0 : trvec) { + auto& gid = trackIndex.emplace_back(gid0); + if ((*vptr[gid.getSource()])[gid.getIndex()] > 1) { + gid.setBit(GIndex::Ambiguous); + } + } + vtxRefs.emplace_back(entry, trackIndex.size() - entry); + } +} + +///______________________________________________________________________________________ +void VertexTrackMatcher::attachTPCITS(TmpMap& tmpMap, const gsl::span<const TrackTPCITS>& tpcits, const std::vector<int>& idTPCITS, const gsl::span<const PVertex>& vertices) +{ + int itrCurr = 0, nvt = vertices.size(), ntr = tpcits.size(); + // indices of tracks used for vertex fit will be in the end, find their start and max error + float maxErr = 0; + for (int i = 0; i < ntr; i++) { + if (idTPCITS[i] < 0) { + ntr = i; + break; + } + float err = tpcits[idTPCITS[i]].getTimeMUS().getTimeStampError(); + if (maxErr < err) { + maxErr = err; + } + } + auto maxErr2 = maxErr * maxErr; + for (int ivtCurr = 0; ivtCurr < nvt; ivtCurr++) { + const auto& vtxT = vertices[ivtCurr].getTimeStamp(); + auto rangeT = mPVParams->nSigmaTimeCut * std::sqrt(maxErr2 + vtxT.getTimeStampError() * vtxT.getTimeStampError()); + float minTime = vtxT.getTimeStamp() - rangeT, maxTime = vtxT.getTimeStamp() + rangeT; + // proceed to the 1st track having compatible time + int itr = itrCurr; + while (itr < ntr) { + const auto& trcT = tpcits[idTPCITS[itr]].getTimeMUS(); + if (trcT.getTimeStamp() < minTime) { + itrCurr = itr; + } else if (trcT.getTimeStamp() > maxTime) { + break; + } else if (compatibleTimes(vtxT, trcT)) { + tmpMap[ivtCurr].emplace_back(idTPCITS[itr], GIndex::TPCITS); + } + itr++; + } + } +} + +///______________________________________________________________________________________ +void VertexTrackMatcher::attachITS(TmpMap& tmpMap, const gsl::span<const TrackITS>& itsTracks, const gsl::span<const ITSROFR>& itsROFR, const std::vector<int>& flITS, + const gsl::span<const PVertex>& vertices, std::vector<int>& idxVtx) +{ + int irofCurr = 0, nvt = vertices.size(), ntr = itsTracks.size(); + int nROFs = itsROFR.size(); + + for (int ivtCurr = 0; ivtCurr < nvt; ivtCurr++) { + const auto& vtx = vertices[idxVtx[ivtCurr]]; // we iterate over vertices in order of their getIRMin() + int irof = irofCurr; + while (irof < nROFs) { + const auto& rofr = itsROFR[irof]; + auto irMin = rofr.getBCData(), irMax = irMin + mITSROFrameLengthInBC; + if (irMax < vtx.getIRMin()) { + irofCurr = irof; + } else if (irMin > vtx.getIRMax()) { + break; + } else { + if (irMax == vtx.getIRMin()) { + irofCurr = irof; + } + int maxItr = rofr.getNEntries() + rofr.getFirstEntry(); + for (int itr = rofr.getFirstEntry(); itr < maxItr; itr++) { + if (flITS[itr] != -1) { + tmpMap[ivtCurr].emplace_back(itr, GIndex::ITS); + } + } + } + irof++; + } + } +} + +///______________________________________________________________________________________ +void VertexTrackMatcher::attachTPC(TmpMap& tmpMap, const std::vector<TBracket>& tpcTimes, const std::vector<int>& idTPC, + const gsl::span<const PVertex>& vertices, std::vector<int>& idVtx) +{ + int itrCurr = 0, nvt = vertices.size(), ntr = idTPC.size(); + // indices of tracks used for vertex fit will be in the end, find their start and max error + for (int i = 0; i < ntr; i++) { + if (idTPC[i] < 0) { + ntr = i; + break; + } + } + for (int ivtCurr = 0; ivtCurr < nvt; ivtCurr++) { + const auto& vtx = vertices[idVtx[ivtCurr]]; + TBracket tV(vtx.getIRMin().differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS * 1e-3, + vtx.getIRMax().differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS * 1e-3); + // proceed to the 1st track having compatible time, idTPC provides track IDs ordered in max time + int itr = itrCurr; + while (itr < ntr) { + const auto& tT = tpcTimes[idTPC[itr]]; + auto rel = tV.isOutside(tT); + if (rel == TBracket::Below) { // tmax of track < tmin of vtx + itrCurr = itr; + } else if (rel == TBracket::Inside) { + tmpMap[ivtCurr].emplace_back(idTPC[itr], GIndex::TPC); + } else if (tT.max() - mMaxTPCDriftTimeMUS > tV.max()) { + break; + } + itr++; + } + } +} + +//______________________________________________ +void VertexTrackMatcher::setITSROFrameLengthInBC(int nbc) +{ + mITSROFrameLengthInBC = nbc; +} + +//______________________________________________ +bool VertexTrackMatcher::compatibleTimes(const TimeEst& vtxT, const TimeEst& trcT) const +{ + float err2 = vtxT.getTimeStampError() * vtxT.getTimeStampError() + trcT.getTimeStampError() * trcT.getTimeStampError(); + float dfred = (vtxT.getTimeStamp() - trcT.getTimeStamp()) * mPVParams->nSigmaTimeCut; + return dfred * dfred < err2; +} From ee8cdfae5881b7ddd360f41cf06c84922d2403f3 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 14 Sep 2020 01:35:46 +0200 Subject: [PATCH 0602/1751] Reject TPCITS match if corr. time is outside of ITS ROF --- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) 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<float> 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<float> trange(timeTB - timeTBErr, timeTB + timeTBErr); int idIC = interactionRefs.getFirstEntry(), maxIC = idIC + nic; for (; idIC < maxIC; idIC++) { auto cmp = mInteractions[idIC].timeBins.isOutside(trange); From a70d6584b069bc9a92fd6a683a53ad282f37bcc9 Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Mon, 14 Sep 2020 13:28:03 +0200 Subject: [PATCH 0603/1751] [QC-357] Move Data Sampling from Framework to Utilities (#4135) --- Framework/Core/CMakeLists.txt | 25 ----- Framework/Core/README.md | 94 ------------------ Framework/TestWorkflows/CMakeLists.txt | 18 ---- Utilities/CMakeLists.txt | 1 + Utilities/DataSampling/CMakeLists.txt | 82 ++++++++++++++++ Utilities/DataSampling/README.md | 95 +++++++++++++++++++ .../etc/exampleDataSamplingConfig.json | 0 .../include/DataSampling}/DataSampling.h | 26 ++--- .../DataSampling}/DataSamplingCondition.h | 4 +- .../DataSamplingConditionFactory.h | 6 +- .../DataSampling}/DataSamplingHeader.h | 4 +- .../DataSampling}/DataSamplingPolicy.h | 16 ++-- .../DataSamplingReadoutAdapter.h | 8 +- .../include/DataSampling}/Dispatcher.h | 26 ++--- .../scripts/o2-datasampling-benchmark.sh | 0 .../DataSampling}/src/DataSampling.cxx | 11 ++- .../src/DataSamplingConditionCustom.cxx | 10 +- .../src/DataSamplingConditionFactory.cxx | 7 +- .../src/DataSamplingConditionNConsecutive.cxx | 10 +- .../src/DataSamplingConditionPayloadSize.cxx | 10 +- .../src/DataSamplingConditionRandom.cxx | 10 +- .../DataSampling}/src/DataSamplingHeader.cxx | 12 +-- .../DataSampling}/src/DataSamplingPolicy.cxx | 12 ++- .../src/DataSamplingReadoutAdapter.cxx | 8 +- .../DataSampling}/src/Dispatcher.cxx | 11 ++- .../test}/dataSamplingBenchmark.cxx | 8 +- .../test}/dataSamplingParallel.cxx | 9 +- .../test}/dataSamplingPodAndRoot.cxx | 14 +-- .../test}/dataSamplingTimePipeline.cxx | 10 +- .../DataSampling}/test/test_DataSampling.cxx | 5 +- .../DataSampling}/test/test_DataSampling.json | 0 .../test/test_DataSamplingCondition.cxx | 3 +- .../test/test_DataSamplingHeader.cxx | 4 +- .../test/test_DataSamplingPolicy.cxx | 3 +- 34 files changed, 316 insertions(+), 246 deletions(-) create mode 100644 Utilities/DataSampling/CMakeLists.txt create mode 100644 Utilities/DataSampling/README.md rename {Framework/TestWorkflows => Utilities/DataSampling}/etc/exampleDataSamplingConfig.json (100%) rename {Framework/Core/include/Framework => Utilities/DataSampling/include/DataSampling}/DataSampling.h (78%) rename {Framework/Core/include/Framework => Utilities/DataSampling/include/DataSampling}/DataSamplingCondition.h (96%) rename {Framework/Core/include/Framework => Utilities/DataSampling/include/DataSampling}/DataSamplingConditionFactory.h (94%) rename {Framework/Core/include/Framework => Utilities/DataSampling/include/DataSampling}/DataSamplingHeader.h (97%) rename {Framework/Core/include/Framework => Utilities/DataSampling/include/DataSampling}/DataSamplingPolicy.h (82%) rename {Framework/Core/include/Framework => Utilities/DataSampling/include/DataSampling}/DataSamplingReadoutAdapter.h (83%) rename {Framework/Core/include/Framework => Utilities/DataSampling/include/DataSampling}/Dispatcher.h (72%) rename {Framework/Core => Utilities/DataSampling}/scripts/o2-datasampling-benchmark.sh (100%) rename {Framework/Core => Utilities/DataSampling}/src/DataSampling.cxx (97%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingConditionCustom.cxx (93%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingConditionFactory.cxx (90%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingConditionNConsecutive.cxx (92%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingConditionPayloadSize.cxx (91%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingConditionRandom.cxx (93%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingHeader.cxx (84%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingPolicy.cxx (95%) rename {Framework/Core => Utilities/DataSampling}/src/DataSamplingReadoutAdapter.cxx (92%) rename {Framework/Core => Utilities/DataSampling}/src/Dispatcher.cxx (97%) rename {Framework/TestWorkflows/src => Utilities/DataSampling/test}/dataSamplingBenchmark.cxx (98%) rename {Framework/TestWorkflows/src => Utilities/DataSampling/test}/dataSamplingParallel.cxx (96%) rename {Framework/TestWorkflows/src => Utilities/DataSampling/test}/dataSamplingPodAndRoot.cxx (96%) rename {Framework/TestWorkflows/src => Utilities/DataSampling/test}/dataSamplingTimePipeline.cxx (96%) rename {Framework/Core => Utilities/DataSampling}/test/test_DataSampling.cxx (98%) rename {Framework/Core => Utilities/DataSampling}/test/test_DataSampling.json (100%) rename {Framework/Core => Utilities/DataSampling}/test/test_DataSamplingCondition.cxx (98%) rename {Framework/Core => Utilities/DataSampling}/test/test_DataSamplingHeader.cxx (97%) rename {Framework/Core => Utilities/DataSampling}/test/test_DataSamplingPolicy.cxx (97%) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 8d22c05aec48d..84d25232ae114 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -54,22 +54,11 @@ o2_add_library(Framework src/DataProcessor.cxx src/DataRelayer.cxx src/DataRelayerHelpers.cxx - 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/DataSpecUtils.cxx src/DeviceConfigInfo.cxx src/DeviceMetricsInfo.cxx src/DeviceSpec.cxx src/DeviceSpecHelpers.cxx - src/Dispatcher.cxx src/DriverControl.cxx src/DriverInfo.cxx src/Expressions.cxx @@ -161,9 +150,6 @@ foreach(t DataProcessorSpec DataRefUtils DataRelayer - DataSamplingCondition - DataSamplingHeader - DataSamplingPolicy DeviceConfigInfo DeviceMetricsInfo DeviceSpec @@ -222,17 +208,6 @@ o2_add_executable(verify-aod-file PUBLIC_LINK_LIBRARIES O2::Framework COMPONENT_NAME Framework) -# tests with input data - -o2_data_file(COPY test/test_DataSampling.json DESTINATION tests) - -o2_add_test(DataSampling NAME test_Framework_test_DataSampling - SOURCES test/test_DataSampling.cxx - COMPONENT_NAME Framework - LABELS framework - PUBLIC_LINK_LIBRARIES O2::Framework - ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage) - # tests with a name not starting with test_... o2_add_test(unittest_DataSpecUtils NAME test_Framework_unittest_DataSpecUtils diff --git a/Framework/Core/README.md b/Framework/Core/README.md index 52034947e7588..58b5f405fdd27 100644 --- a/Framework/Core/README.md +++ b/Framework/Core/README.md @@ -467,100 +467,6 @@ There is also a few demonstrator available in particular: - [MillWheel: Fault-Tolerant Stream Processing at Internet Scale](https://research.google.com/pubs/pub41378.html) : paper about Google previous generation system for stream processing -## 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 "Framework/DataSampling.h" -using namespace o2::framework; -void customize(std::vector<CompletionPolicy>& policies) -{ - DataSampling::CustomizeInfrastructure(policies); -} - -void customize(std::vector<ChannelConfigurationPolicy>& policies) -{ - DataSampling::CustomizeInfrastructure(policies); -} - -#include "Framework/runDataProcessing.h" - -std::vector<DataProcessorSpec> defineDataProcessing(ConfigContext &ctx) -{ - - WorkflowSpec workflow; -// <declaration of other DPL processors> - - 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<InputSpec> 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. - -[o2-datasampling-pod-and-root](https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx) workflow can serve as 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" -} -``` ## Document history * v0.9: proposal for approval at the O2 TB - 19th June 2018 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/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/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<CompletionPolicy>& policies) +{ + DataSampling::CustomizeInfrastructure(policies); +} + +void customize(std::vector<ChannelConfigurationPolicy>& policies) +{ + DataSampling::CustomizeInfrastructure(policies); +} + +#include "Framework/runDataProcessing.h" + +std::vector<DataProcessorSpec> defineDataProcessing(ConfigContext &ctx) +{ + + WorkflowSpec workflow; +// <declaration of other DPL processors> + + 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<InputSpec> 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<CompletionPolicy>&); + static void CustomizeInfrastructure(std::vector<framework::CompletionPolicy>&); /// \brief Applies blocking/nonblocking data sampling configuration to the workflow. - static void CustomizeInfrastructure(std::vector<ChannelConfigurationPolicy>&); + static void CustomizeInfrastructure(std::vector<framework::ChannelConfigurationPolicy>&); /// \brief Provides InputSpecs to receive data for given DataSamplingPolicy - static std::vector<InputSpec> InputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); + static std::vector<framework::InputSpec> InputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); /// \brief Provides InputSpecs to receive data for given DataSamplingPolicy - static std::vector<InputSpec> InputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); + static std::vector<framework::InputSpec> InputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); /// \brief Provides OutputSpecs of given DataSamplingPolicy - static std::vector<OutputSpec> OutputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); + static std::vector<framework::OutputSpec> OutputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); /// \brief Provides OutputSpecs of given DataSamplingPolicy - static std::vector<OutputSpec> OutputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); + static std::vector<framework::OutputSpec> 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<std::string> 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 <boost/property_tree/ptree_fwd.hpp> #include <string> -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 <memory> #include <string> -namespace o2::framework +namespace o2::utilities { /// A factory of DataSamplingConditions children. @@ -42,6 +42,6 @@ class DataSamplingConditionFactory static std::unique_ptr<DataSamplingCondition> 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 <boost/property_tree/ptree_fwd.hpp> -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<std::pair<InputSpec, OutputSpec>>; + using PathVectorBase = std::vector<std::pair<framework::InputSpec, framework::OutputSpec>>; 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<InputSpec, OutputSpec>&); + void registerPath(const std::pair<framework::InputSpec, framework::OutputSpec>&); 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<std::shared_ptr<DataSamplingPolicy>> 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 <Configuration/ConfigurationFactory.h> 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<std::string> 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 <fairlogger/Logger.h> @@ -24,7 +24,9 @@ #include <TSystem.h> #include <boost/property_tree/ptree.hpp> -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<DataSamplingCondition> DataSamplingConditionFactory::createDataS return std::make_unique<DataSamplingConditionCustom>(); } -} // 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 <memory> #include <stdexcept> -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingConditionFactory.h" +using namespace o2::framework; -namespace o2::framework +namespace o2::utilities { std::unique_ptr<DataSamplingCondition> DataSamplingConditionFactory::create(std::string name) @@ -35,4 +36,4 @@ std::unique_ptr<DataSamplingCondition> 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 <boost/property_tree/ptree.hpp> -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { using namespace o2::header; @@ -65,4 +67,4 @@ std::unique_ptr<DataSamplingCondition> DataSamplingConditionFactory::createDataS return std::make_unique<DataSamplingConditionNConsecutive>(); } -} // 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 <boost/property_tree/ptree.hpp> -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { using namespace o2::header; @@ -62,4 +64,4 @@ std::unique_ptr<DataSamplingCondition> DataSamplingConditionFactory::createDataS return std::make_unique<DataSamplingConditionPayloadSize>(); } -} // 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 <boost/property_tree/ptree.hpp> -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<DataSamplingCondition> DataSamplingConditionFactory::createDataS return std::make_unique<DataSamplingConditionRandom>(); } -} // 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<uint64_t>("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<uint64_t>("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 e4d55b41803cb..a68fb6394f1af 100644 --- a/Framework/Core/src/DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/src/DataSamplingPolicy.cxx @@ -13,16 +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 <boost/property_tree/ptree.hpp> -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { using boost::property_tree::ptree; @@ -166,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 <Common/DataBlock.h> -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 <vector> using namespace o2::framework; +using namespace o2::utilities; void customize(std::vector<CompletionPolicy>& 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 <thread> using namespace o2::framework; +using namespace o2::utilities; void customize(std::vector<CompletionPolicy>& policies) { DataSampling::CustomizeInfrastructure(policies); @@ -24,7 +25,7 @@ void customize(std::vector<ChannelConfigurationPolicy>& 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 <thread> using namespace o2::framework; +using namespace o2::utilities; + void customize(std::vector<CompletionPolicy>& policies) { DataSampling::CustomizeInfrastructure(policies); @@ -26,7 +28,7 @@ void customize(std::vector<ChannelConfigurationPolicy>& 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 <TClonesArray.h> #include <TObjString.h> @@ -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 <thread> using namespace o2::framework; +using namespace o2::utilities; + void customize(std::vector<CompletionPolicy>& policies) { DataSampling::CustomizeInfrastructure(policies); @@ -24,7 +26,7 @@ void customize(std::vector<ChannelConfigurationPolicy>& 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 <boost/test/unit_test.hpp> -#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 <Configuration/ConfigurationFactory.h> 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 <boost/test/unit_test.hpp> #include <boost/property_tree/ptree.hpp> -#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 <boost/test/unit_test.hpp> -#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 <boost/test/unit_test.hpp> #include <boost/property_tree/ptree.hpp> -#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 // { From 2ed4e5fc848e6975c522fe9cfeba2a5dea12164c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 7 Sep 2020 10:33:51 +0200 Subject: [PATCH 0604/1751] More efficient structures for MCTruth sharing and ROOT IO This commit achieves/provides the following: * A new class ConstMCTruthContainer, allowing to share **read-only** MC labels in a flat buffer and in shared memory (using the DPL->make mechanism). This avoids going through ROOT IO when communicating between DPL devices and reduces the overall memory usage and CPU time. * A new class IOMCTruthContainerView, allowing to overcome the size limitation of labels when writing to a TTree entry. This is achieved by splitting the buffer into several members, which ROOT serializes separately. * A test workflow is provided, exchanging MClabels between a couple of DPL processes. The workflow can run with the existing as well the new way of sharing labels. --- DataFormats/simulation/CMakeLists.txt | 1 + .../ConstMCTruthContainer.h | 118 ++++++++++++++++ .../IOMCTruthContainerView.h | 105 +++++++++++++++ .../SimulationDataFormat/MCTruthContainer.h | 2 +- .../simulation/src/SimulationDataLinkDef.h | 2 + .../simulation/test/testMCTruthContainer.cxx | 66 +++++++++ Steer/DigitizerWorkflow/CMakeLists.txt | 9 ++ .../DigitizerWorkflow/src/MCTruthReaderSpec.h | 104 ++++++++++++++ .../src/MCTruthSourceSpec.cxx | 97 +++++++++++++ .../DigitizerWorkflow/src/MCTruthSourceSpec.h | 21 +++ .../src/MCTruthTestWorkflow.cxx | 53 ++++++++ .../src/MCTruthWriterSpec.cxx | 127 ++++++++++++++++++ .../DigitizerWorkflow/src/MCTruthWriterSpec.h | 26 ++++ 13 files changed, 730 insertions(+), 1 deletion(-) create mode 100644 DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h create mode 100644 DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h create mode 100644 Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h create mode 100644 Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx create mode 100644 Steer/DigitizerWorkflow/src/MCTruthSourceSpec.h create mode 100644 Steer/DigitizerWorkflow/src/MCTruthTestWorkflow.cxx create mode 100644 Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx create mode 100644 Steer/DigitizerWorkflow/src/MCTruthWriterSpec.h 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 <SimulationDataFormat/MCTruthContainer.h> +#include <Framework/Traits.h> + +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 <typename TruthElement> +class ConstMCTruthContainer : public std::vector<char> +{ + public: + // (unfortunately we need these constructors for DPL) + using std::vector<char>::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<const TruthElement> getLabels(uint32_t dataindex) const + { + if (dataindex >= getIndexedSize()) { + return gsl::span<const TruthElement>(); + } + const auto start = getMCTruthHeader(dataindex).index; + const auto labelsptr = getLabelStart(); + return gsl::span<const TruthElement>(&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<TruthElement>::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<FlatHeader const*>(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<T> +namespace o2::framework +{ +template <typename T> +struct is_specialization<o2::dataformats::ConstMCTruthContainer<T>, 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 <vector> +#include <gsl/span> + +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<char> 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 <typename Alloc> + void copyandflatten(std::vector<char, Alloc>& 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 <typename Alloc> + void copyhelper(const char* input, int size, std::vector<char, Alloc>& output) const + { + gsl::span<const char> 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 <typename ContainerType> - 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 <boost/test/unit_test.hpp> #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/LabelContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include <algorithm> #include <iostream> +#include <TFile.h> +#include <TTree.h> 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<TruthElement>; + 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<TruthElement>; + 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<char> 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<TruthElement>; + 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/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 <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> +#include <SimulationDataFormat/MCCompLabel.h> +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" +#include "TTree.h" +#include "TFile.h" +#include "TString.h" +#include <sstream> + +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<TString*>("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<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{"TST", "LABELS2", 0, Lifetime::Timeframe}); + iocontainer->copyandflatten(sharedlabels); + + } else { + // the original way with the MCTruthContainer + dataformats::MCTruthContainer<MCCompLabel>* 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<ControlService>().readyToQuit(QuitRequest::Me); + mFinished = true; + } + + private: + bool mFinished = false; + bool mNew = false; +}; + +o2::framework::DataProcessorSpec getMCTruthReaderSpec(bool newmctruth) +{ + std::vector<InputSpec> 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<MCTruthReaderTask>(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 <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> +#include <SimulationDataFormat/MCCompLabel.h> +#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<int>("size"); + } + + void run(framework::ProcessingContext& pc) override + { + if (mFinished) { + return; + } + LOG(INFO) << "Creating MCTruth container"; + + using TruthElement = o2::MCCompLabel; + using Container = dataformats::MCTruthContainer<TruthElement>; + 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<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(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<ControlService>().readyToQuit(QuitRequest::Me); + mFinished = true; + } + + private: + bool mFinished = false; + int mSize = 0; + bool mNew = false; + o2::dataformats::MCTruthContainer<long> 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<OutputSpec> outputs; + outputs.emplace_back("TST", "LABELS", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "MCTruthSource", + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask<MCTruthSourceTask>(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 <boost/program_options.hpp> + +#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<o2::framework::ConfigParamSpec>& 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<bool>("newmctruth"); + + // connect the source + specs.emplace_back(o2::getMCTruthSourceSpec(newmctruth)); + // connect some consumers + for (int i = 0; i < configcontext.options().get<int>("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 <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> +#include <SimulationDataFormat/MCCompLabel.h> +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" +#include "TTree.h" +#include "TFile.h" +#include "TString.h" +#include <sstream> + +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<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(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<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>(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<ControlService>().readyToQuit(QuitRequest::Me); + mFinished = true; + } + + private: + bool mFinished = false; + bool mNew = false; + bool mIO = false; + int mID = 0; + o2::dataformats::MCTruthContainer<long> mLabels; // labels which get filled +}; + +o2::framework::DataProcessorSpec getMCTruthWriterSpec(int id, bool doio, bool newmctruth) +{ + std::vector<InputSpec> 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<OutputSpec> outputs; + if (doio) { + outputs.emplace_back("TST", "TRIGGERREAD", 0, Lifetime::Timeframe); + } + return DataProcessorSpec{ + str.str(), + inputs, + outputs, + AlgorithmSpec{adaptFromTask<MCTruthWriterTask>(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_ */ From 21c38a01b7d803ab0ff5cb19b4a6c3aa1ed27e49 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Mon, 7 Sep 2020 17:04:07 +0200 Subject: [PATCH 0605/1751] [EMCAL-671] Fix leftover geometry path which is missing the barrel mothervolume --- Detectors/EMCAL/base/src/Geometry.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index d3f3476a6a082..348560bfa0a9a 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/%s_%d", smName.Data(), smOrder); if (!gGeoManager->cd(path)) { LOG(FATAL) << "Geo manager can not find path " << path << "!\n"; From 801116caf7d62a9fe1f3c381ccd1208e7430207c Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Mon, 7 Sep 2020 17:24:03 +0200 Subject: [PATCH 0606/1751] [EMCAL-671] Rename "barrel" to "barrel_1" --- Detectors/EMCAL/base/src/Geometry.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index 348560bfa0a9a..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/barrel/%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]; From 6e1a98006560ee021cb58061aabb2a1d2e014a9a Mon Sep 17 00:00:00 2001 From: nzardosh <nima.zardoshti@cern.ch> Date: Mon, 14 Sep 2020 14:28:45 +0200 Subject: [PATCH 0607/1751] adding D0 selector (#4294) --- .../Analysis/CandidateSelectionTables.h | 26 ++ .../include/Analysis/SecondaryVertexHF.h | 15 +- Analysis/Tasks/PWGHF/CMakeLists.txt | 5 + .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 10 +- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 412 ++++++++++++++++++ .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 13 +- Analysis/Tasks/PWGHF/taskD0.cxx | 27 +- 7 files changed, 490 insertions(+), 18 deletions(-) create mode 100644 Analysis/DataModel/include/Analysis/CandidateSelectionTables.h create mode 100644 Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx 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/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<Tracks, TracksCov, TracksExtra, SelTrack, pidRespTPC, pidRespTOF>; + // FIXME: this is a workaround until we get the index columns to work with joins. -using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra>; 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::ImpactParameter0, hf_cand::ImpactParameter1>, hf_cand_prong2::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, 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 <cmath> +#include <array> +#include <cstdlib> 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<aod::Tracks, aod::TracksCov, aod::TracksExtra> 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 <nima.zardoshti@cern.ch>, 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 <cmath> +#include <array> +#include <cstdlib> + +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.5<pt<1*/ + {0.400, 300. * 1E-4, 0.8, 0.4, 0.4, 1000. * 1E-4, 1000. * 1E-4, -25000. * 1E-8, 0.80, 0., 0.}, /* 1<pt<1.5 */ + {0.400, 300. * 1E-4, 0.8, 0.4, 0.4, 1000. * 1E-4, 1000. * 1E-4, -25000. * 1E-8, 0.80, 0., 0.}, /* 1.5<pt<2 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -20000. * 1E-8, 0.90, 0., 0.}, /* 2<pt<2.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -20000. * 1E-8, 0.90, 0., 0.}, /* 2.5<pt<3 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -12000. * 1E-8, 0.85, 0., 0.}, /* 3<pt<3.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -12000. * 1E-8, 0.85, 0., 0.}, /* 3.5<pt<4 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0.}, /* 4<pt<4.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0.}, /* 4.5<pt<5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0.}, /* 5<pt<5.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0.}, /* 5.5<pt<6 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0.}, /* 6<pt<6.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0.}, /* 6.5<pt<7 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -7000. * 1E-8, 0.85, 0., 0.}, /* 7<pt<7.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -7000. * 1E-8, 0.85, 0., 0.}, /* 7.5<pt<8 */ + {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0.}, /* 8<pt<9 */ + {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0.}, /* 9<pt<10 */ + {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0.}, /* 10<pt<12 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 10000. * 1E-8, 0.85, 0., 0.}, /* 12<pt<16 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0.}, /* 16<pt<20 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0.}, /* 20<pt<24 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0.}, /* 24<pt<36 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0.}, /* 36<pt<50 */ + {0.400, 300. * 1E-4, 1.0, 0.6, 0.6, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.80, 0., 0.}}; /* pt>50 */ + +/// Struct for applying D0 selection cuts + +struct HFD0CandidateSelector { + + Produces<aod::HFSelD0Candidate> hfSelD0Candidate; + + Configurable<double> d_pTCandMin{"d_pTCandMin", 0.0, "Lower bound of candidate pT"}; + Configurable<double> d_pTCandMax{"d_pTCandMax", 50.0, "Upper bound of candidate pT"}; + + Configurable<double> d_pidTPCMinpT{"d_pidTPCMinpT", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable<double> d_pidTPCMaxpT{"d_pidTPCMaxpT", 5.0, "Upper bound of track pT for TPC PID"}; + Configurable<double> d_pidTOFMinpT{"d_pidTOFMinpT", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable<double> d_pidTOFMaxpT{"d_pidTOFMaxpT", 5.0, "Upper bound of track pT for TOF PID"}; + + Configurable<double> d_TPCNClsFindablePIDCut{"d_TPCNClsFindablePIDCut", 50.0, "Lower bound of TPC findable clusters for good PID"}; + Configurable<double> d_nSigmaTPC{"d_nSigmaTPC", 3.0, "Nsigma cut on TPC only"}; + Configurable<double> d_nSigmaTPCCombined{"d_nSigmaTPCCombined", 5.0, "Nsigma cut on TPC combined with TOF"}; + Configurable<double> d_nSigmaTOF{"d_nSigmaTOF", 3.0, "Nsigma cut on TOF only"}; + Configurable<double> 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T1, typename T2> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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<HFD0CandidateSelector>("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<aod::SelTrack> rowSelectedTrack; @@ -97,7 +86,7 @@ struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; OutputObj<TH1F> 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<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>>; // FIXME //Partition<SelectedTracks> 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 <TFile.h> +#include <TH1F.h> +#include <cmath> +#include <array> +#include <cstdlib> 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<TH1F> hCTS{TH1F("hCTS", "cos #it{#theta}*", 120, -1.1, 1.1)}; OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; + OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; + + Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; + Configurable<int> 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<soa::Join<aod::HfCandProng2, aod::HFSelD0Candidate>> 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)); } } }; From 47d180ad173ecd13c736cf67b4545e83adda9932 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Mon, 14 Sep 2020 15:29:28 +0200 Subject: [PATCH 0608/1751] [EMCAL-668] Add track position on EMCAL surface to TRACKEXTRA table (#4306) --- Framework/Core/include/Framework/AnalysisDataModel.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index e7bb1e6edc148..13bef17ae529a 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -170,6 +170,8 @@ DECLARE_SOA_COLUMN(TRDSignal, trdSignal, float); DECLARE_SOA_COLUMN(TOFSignal, tofSignal, float); DECLARE_SOA_COLUMN(Length, length, float); DECLARE_SOA_COLUMN(TOFExpMom, tofExpMom, float); +DECLARE_SOA_COLUMN(TrackEtaEMCAL, trackEtaEmcal, float); +DECLARE_SOA_COLUMN(TrackPhiEMCAL, trackPhiEmcal, float); DECLARE_SOA_DYNAMIC_COLUMN(TPCNClsFound, tpcNClsFound, [](uint8_t tpcNClsFindable, uint8_t tpcNClsFindableMinusFound) -> int16_t { return tpcNClsFindable - tpcNClsFindableMinusFound; }); DECLARE_SOA_DYNAMIC_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, [](uint8_t tpcNClsFindable, uint8_t TPCNClsFindableMinusCrossedRows) -> int16_t { return tpcNClsFindable - TPCNClsFindableMinusCrossedRows; }); DECLARE_SOA_DYNAMIC_COLUMN(ITSNCls, itsNCls, [](uint8_t itsClusterMap) -> uint8_t { @@ -253,7 +255,8 @@ DECLARE_SOA_TABLE(TracksExtra, "AOD", "TRACKEXTRA", track::TPCNClsCrossedRows<track::TPCNClsFindable, track::TPCNClsFindableMinusCrossedRows>, track::ITSNCls<track::ITSClusterMap>, track::ITSNClsInnerBarrel<track::ITSClusterMap>, track::TPCCrossedRowsOverFindableCls<track::TPCNClsFindable, track::TPCNClsFindableMinusCrossedRows>, - track::TPCFractionSharedCls<track::TPCNClsShared, track::TPCNClsFindable, track::TPCNClsFindableMinusFound>); + track::TPCFractionSharedCls<track::TPCNClsShared, track::TPCNClsFindable, track::TPCNClsFindableMinusFound>, + track::TrackEtaEMCAL, track::TrackPhiEMCAL); using Track = Tracks::iterator; using TrackCov = TracksCov::iterator; From b53b4a0e15b70c3c3618009e24f2a31129caaa62 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 14 Sep 2020 16:30:04 +0200 Subject: [PATCH 0609/1751] DPL: remove spurious message from Monitor::Cleanup (#4334) Requires FairMQ 1.4.23 --- Framework/Core/src/runDataProcessing.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(<fairmq/shmem/Monitor.h>) 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); From 1d5471d6f9f37ec1e190da18ac1676ec6ba24bf5 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 14 Sep 2020 14:40:08 +0200 Subject: [PATCH 0610/1751] Validate ITS/TPC match by Bunch filling scheme (except cosmics mode) --- Common/MathUtils/include/MathUtils/Bracket.h | 4 +- .../include/GlobalTracking/MatchTPCITS.h | 31 +++++- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 95 +++++++++++++++---- .../src/TPCITSMatchingSpec.cxx | 8 ++ 4 files changed, 119 insertions(+), 19 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Bracket.h b/Common/MathUtils/include/MathUtils/Bracket.h index f93c6265da546..ba8912a4fb1b2 100644 --- a/Common/MathUtils/include/MathUtils/Bracket.h +++ b/Common/MathUtils/include/MathUtils/Bracket.h @@ -69,6 +69,8 @@ class Bracket T min() const { return mMin; } T mean() const { return (mMin + mMax) / 2; } T delta() const { return mMax - mMin; } + bool isValid() const { return mMax >= mMin; } + bool isInvalid() const { return mMin > mMax; } void update(T v) { // update limits @@ -91,7 +93,7 @@ class Bracket } private: - T mMin = 0, mMax = 0; + T mMin{}, mMax{}; ClassDefNV(Bracket, 1); }; diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 4a75d53c2e943..210987d2bd6f8 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -34,6 +34,7 @@ #include "CommonDataFormat/EvIndex.h" #include "CommonDataFormat/InteractionRecord.h" #include "CommonDataFormat/RangeReference.h" +#include "CommonDataFormat/BunchFilling.h" #include "SimulationDataFormat/MCCompLabel.h" #include "CommonUtils/TreeStreamRedirector.h" #include "DataFormatsITSMFT/Cluster.h" @@ -267,6 +268,7 @@ struct ITSChipClustersRefs { class MatchTPCITS { + public: using ITSCluster = o2::BaseCluster<float>; using ClusRange = o2::dataformats::RangeReference<int, int>; using MCLabContCl = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; @@ -274,10 +276,10 @@ class MatchTPCITS using MCLabSpan = gsl::span<const o2::MCCompLabel>; using TPCTransform = o2::gpu::TPCFastTransform; using BracketF = o2::utils::Bracket<float>; + using BracketIR = o2::utils::Bracket<o2::InteractionRecord>; using Params = o2::globaltracking::MatchITSTPCParams; using MatCorrType = o2::base::Propagator::MatCorrType; - public: MatchTPCITS(); // std::unique_ptr to forward declared type needs constructor / destructor in .cxx ~MatchTPCITS(); @@ -316,6 +318,9 @@ class MatchTPCITS void destroyLastABTrackLinksList(); void refitABTrack(int ibest) const; + void setCosmics(bool v) { mCosmics = v; } + bool isCosmics() const { return mCosmics; } + ///< perform all initializations void init(); @@ -325,6 +330,9 @@ class MatchTPCITS ///< set InteractionRecods for the beginning of the TF void setStartIR(const o2::InteractionRecord& ir) { mStartIR = ir; } + ///< set Bunch filling and init helpers for validation by BCs + void setBunchFilling(const o2::BunchFilling& bf); + ///< ITS readout mode void setITSTriggered(bool v) { mITSTriggered = v; } bool isITSTriggered() const { return mITSTriggered; } @@ -516,6 +524,9 @@ class MatchTPCITS ///< get number of matching records for ITS track int getNMatchRecordsITS(const TrackLocITS& tITS) const; + ///< convert TPC timebins bracket to IR bracket + BracketIR tpcTimeBin2IRBracket(const BracketF tbrange); + ///< convert TPC time bin to ITS ROFrame units int tpcTimeBin2ITSROFrame(float tbin) const { @@ -536,6 +547,18 @@ class MatchTPCITS return tms * mTPCTBinMUSInv; } + ///< convert TPC time bin to microseconds + float tpcTimeBin2MUS(float tbn) const + { + return tbn * mTPCTBinMUS; + } + + ///< convert TPC time bin to nanoseconds + float tpcTimeBin2NS(float tbn) const + { + return tbn * mTPCTBinNS; + } + ///< convert Interaction Record for TPC time bin units float intRecord2TPCTimeBin(const o2::InteractionRecord& bc) const { @@ -572,6 +595,7 @@ class MatchTPCITS bool mInitDone = false; ///< flag init already done bool mFieldON = true; ///< flag for field ON/OFF + bool mCosmics = false; ///< flag cosmics mode bool mMCTruthON = false; ///< flag availability of MC truth o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF @@ -599,6 +623,7 @@ class MatchTPCITS float mTPCVDrift0 = -1.; ///< TPC nominal drift speed in cm/microseconds float mTPCVDrift0Inv = -1.; ///< inverse TPC nominal drift speed in cm/microseconds float mTPCTBinMUS = 0.; ///< TPC time bin duration in microseconds + float mTPCTBinNS = 0.; ///< TPC time bin duration in ns float mTPCTBinMUSInv = 0.; ///< inverse TPC time bin duration in microseconds float mITSROFrame2TPCBin = 0.; ///< conversion coeff from ITS ROFrame units to TPC time-bin float mTPCBin2ITSROFrame = 0.; ///< conversion coeff from TPC time-bin to ITS ROFrame units @@ -613,6 +638,10 @@ class MatchTPCITS std::unique_ptr<TPCTransform> mTPCTransform; ///< TPC cluster transformation std::unique_ptr<o2::gpu::GPUParam> mTPCClusterParam; ///< TPC clusters error param + o2::BunchFilling mBunchFilling; + std::array<int16_t, o2::constants::lhc::LHCMaxBunches> mClosestBunchAbove; // closest filled bunch from above + std::array<int16_t, o2::constants::lhc::LHCMaxBunches> mClosestBunchBelow; // closest filled bunch from below + ///>>>------ these are input arrays which should not be modified by the matching code // since this info is provided by external device gsl::span<const o2::tpc::TrackTPC> mTPCTracksArray; ///< input TPC tracks span diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 2901067b0298b..87676ee2f770e 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -378,6 +378,7 @@ void MatchTPCITS::updateTPCTimeDependentParams() auto& elParam = o2::tpc::ParameterElectronics::Instance(); auto& detParam = o2::tpc::ParameterDetector::Instance(); mTPCTBinMUS = elParam.ZbinWidth; + mTPCTBinNS = mTPCTBinMUS * 1e3; mTPCVDrift0 = gasParam.DriftV; mTPCZMax = detParam.TPClength; mTPCTBinMUSInv = 1. / mTPCTBinMUS; @@ -876,26 +877,34 @@ void MatchTPCITS::doMatching(int sec) } 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) { - int idIC = interactionRefs.getFirstEntry(), maxIC = idIC + nic; - for (; idIC < maxIC; idIC++) { - auto cmp = mInteractions[idIC].timeBins.isOutside(trange); - if (cmp == o2::utils::Bracket<float>::Above) { // trange is above this interaction candidate, the following ones may match - continue; - } - if (cmp == o2::utils::Bracket<float>::Inside) { - matchedIC = idIC; + if (!isCosmics()) { + // validate by bunch filling scheme + auto irBracket = tpcTimeBin2IRBracket(trange); + if (irBracket.isInvalid()) { + continue; + } + + 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) { + int idIC = interactionRefs.getFirstEntry(), maxIC = idIC + nic; + for (; idIC < maxIC; idIC++) { + auto cmp = mInteractions[idIC].timeBins.isOutside(trange); + if (cmp == o2::utils::Bracket<float>::Above) { // trange is above this interaction candidate, the following ones may match + continue; + } + if (cmp == o2::utils::Bracket<float>::Inside) { + matchedIC = idIC; + } + break; // we loop till 1st matching IC or the one above the trange (since IC are ordered, all others will be above too) } - break; // we loop till 1st matching IC or the one above the trange (since IC are ordered, all others will be above too) } } - } - if (mParams->validateMatchByFIT == MatchITSTPCParams::Require && matchedIC == MinusOne) { - continue; + if (mParams->validateMatchByFIT == MatchITSTPCParams::Require && matchedIC == MinusOne) { + continue; + } } registerMatchRecordTPC(cacheITS[iits], cacheTPC[itpc], chi2, matchedIC); // register matching candidate nMatchesControl++; @@ -2652,6 +2661,58 @@ void MatchTPCITS::setITSROFrameLengthInBC(int nbc) mITSROFrameLengthMUS = nbc * o2::constants::lhc::LHCBunchSpacingNS * 1e-3; } +//___________________________________________________________________ +void MatchTPCITS::setBunchFilling(const o2::BunchFilling& bf) +{ + mBunchFilling = bf; + // find closest (from above) filled bunch + int minBC = bf.getFirstFilledBC(), maxBC = bf.getLastFilledBC(); + if (minBC < 0) { + throw std::runtime_error("Bunch filling is not set in MatchTPCITS"); + } + int bcAbove = minBC; + for (int i = o2::constants::lhc::LHCMaxBunches; i--;) { + if (bf.testBC(i)) { + bcAbove = i; + } + mClosestBunchAbove[i] = bcAbove; + } + int bcBelow = maxBC; + for (int i = 0; i < o2::constants::lhc::LHCMaxBunches; i++) { + if (bf.testBC(i)) { + bcBelow = i; + } + mClosestBunchBelow[i] = bcBelow; + } +} + +//___________________________________________________________________ +MatchTPCITS::BracketIR MatchTPCITS::tpcTimeBin2IRBracket(const BracketF tbrange) +{ + // convert TPC timebins bracket to IR bracket + o2::InteractionRecord irMin(mStartIR), irMax(mStartIR); + if (tbrange.min() > 0) { + irMin += o2::InteractionRecord(tpcTimeBin2NS(tbrange.min())); + } + irMax += o2::InteractionRecord(tpcTimeBin2NS(tbrange.max())); + irMax++; // to account for rounding + int bc = mClosestBunchAbove[irMin.bc]; + if (bc < irMin.bc) { + irMin.orbit++; + } + irMin.bc = bc; + bc = mClosestBunchBelow[irMax.bc]; + if (bc > irMax.bc) { + if (irMax.orbit == 0) { + bc = 0; + } else { + irMax.orbit--; + } + } + irMax.bc = bc; + return {irMin, irMax}; +} + //<<============================= AfterBurner for TPC-track / ITS cluster matching ===================<< #ifdef _ALLOW_DEBUG_TREES_ diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index 6cf056eb529d3..b974b562f55f4 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -18,6 +18,7 @@ #include "ReconstructionDataFormats/TrackTPCITS.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/DigitizationContext.h" #include "DataFormatsITS/TrackITS.h" #include "DataFormatsITSMFT/Cluster.h" #include "DataFormatsITSMFT/CompCluster.h" @@ -34,6 +35,7 @@ #include "DetectorsCommonDataFormats/NameConf.h" #include "DataFormatsParameters/GRPObject.h" #include "Headers/DataHeader.h" +#include "CommonDataFormat/BunchFilling.h" // RSTODO to remove once the framework will start propagating the header.firstTForbit #include "DetectorsRaw/HBFUtils.h" @@ -84,6 +86,12 @@ void TPCITSMatchingDPL::init(InitContext& ic) } else { LOG(INFO) << "Material LUT " << matLUTFile << " file is absent, only TGeo can be used"; } + + // set bunch filling. Eventually, this should come from CCDB + const auto* digctx = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + const auto& bcfill = digctx->getBunchFilling(); + mMatching.setBunchFilling(bcfill); + mMatching.init(); // } From 10f311daede68acedb42b51b07b83f4c94c97605 Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez@cern.ch> Date: Tue, 15 Sep 2020 08:36:21 +0200 Subject: [PATCH 0611/1751] Incorporated full pair processing (#4329) * Incorporated full pair processing - basis for configurable enhanced cuts support - parallel execution per centrality/multiplicity range - filtered per centrality/multiplicity range - task only receive collisions within centrality/multiplicity range - single configurable binning structure - fully implemented at task level - single configurable event selection structure --- .../Tasks/PWGCF/AnalysisConfigurableCuts.cxx | 46 +++ .../Tasks/PWGCF/AnalysisConfigurableCuts.h | 79 ++++ Analysis/Tasks/PWGCF/CMakeLists.txt | 10 +- Analysis/Tasks/PWGCF/PWGCFCoreLinkDef.h | 17 + Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 342 +++++++++++++----- 5 files changed, 403 insertions(+), 91 deletions(-) create mode 100644 Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.cxx create mode 100644 Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h create mode 100644 Analysis/Tasks/PWGCF/PWGCFCoreLinkDef.h diff --git a/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.cxx b/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.cxx new file mode 100644 index 0000000000000..e0f9ff79899eb --- /dev/null +++ b/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.cxx @@ -0,0 +1,46 @@ +// 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 "AnalysisConfigurableCuts.h" + +using namespace o2::analysis; + +ClassImp(SimpleInclusiveCut); + +SimpleInclusiveCut::SimpleInclusiveCut() : TNamed(), + mX(0), + mY(0.0) +{ + // + // default constructor + // +} + +SimpleInclusiveCut::SimpleInclusiveCut(const char* name, int _x, float _y) : TNamed(name, name), + mX(_x), + mY(_y) +{ + // + // explicit constructor + // +} + +SimpleInclusiveCut& SimpleInclusiveCut::operator=(const SimpleInclusiveCut& sic) +{ + // + // assignment operator + // + if (this != &sic) { + TNamed::operator=(sic); + mX = sic.mX; + mY = sic.mY; + } + return (*this); +} diff --git a/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h b/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h new file mode 100644 index 0000000000000..d60324960c3d6 --- /dev/null +++ b/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h @@ -0,0 +1,79 @@ +// 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 ANALYSIS_CONFIGURABLE_CUTS_CLASSES_H +#define ANALYSIS_CONFIGURABLE_CUTS_CLASSES_H + +#include <Rtypes.h> +#include <TObject.h> +#include <TNamed.h> +#include <TMath.h> + +namespace o2 +{ +namespace analysis +{ +/// \class EventSelectionCuts +/// \brief Class which implements configurable event selection cuts +/// +class EventSelectionCuts +{ + public: + int mOfflinetrigger = 1; ///< offline trigger, default MB = 1 + std::string mCentmultestmator = "V0M"; ///< centrality / multiplicity estimation, default V0M + int mRemovepileupcode = 1; ///< Procedure for pile-up removal, default V0M vs TPCout tracks = 1 + std::string mRemovepileupfn = "-2500+5.0*x"; ///< function for pile-up removal, procedure dependent, defaul V0M vs TPCout tracks for LHC15o HIR + + private: + ClassDefNV(EventSelectionCuts, 1); +}; + +/// \class DptDptBinningCuts +/// \brief Class which implements configurable acceptance cuts +/// +class DptDptBinningCuts +{ + public: + int mZVtxbins = 28; ///< the number of z_vtx bins default 28 + float mZVtxmin = -7.0; ///< the minimum z_vtx value, default -7.0 cm + float mZVtxmax = 7.0; ///< the maximum z_vtx value, default 7.0 cm + int mPTbins = 18; ///< the number of pT bins, default 18 + float mPTmin = 0.2; ///< the minimum pT value, default 0.2 GeV + float mPTmax = 2.0; ///< the maximum pT value, default 2.0 GeV + int mEtabins = 16; ///< the number of eta bins default 16 + float mEtamin = -0.8; ///< the minimum eta value, default -0.8 + float mEtamax = 0.8; ///< the maximum eta value, default 0.8 + int mPhibins = 72; ///< the number of phi bins, default 72 + float mPhimin = 0.0; ///< the minimum phi value, default 0.0 + float mPhimax = TMath::TwoPi(); ///< the maximum phi value, default 2*pi + float mPhibinshift = 0.5; ///< the shift in the azimuthal origen, defoult 0.5, i.e half a bin + + private: + ClassDefNV(DptDptBinningCuts, 1); +}; + +class SimpleInclusiveCut : public TNamed +{ + public: + int mX = 1; + float mY = 2.f; + SimpleInclusiveCut(); + SimpleInclusiveCut(const char*, int, float); + SimpleInclusiveCut(const SimpleInclusiveCut&) = default; + ~SimpleInclusiveCut() override = default; + + SimpleInclusiveCut& operator=(const SimpleInclusiveCut&); + + private: + ClassDef(SimpleInclusiveCut, 1); +}; + +} // namespace analysis +} // namespace o2 +#endif // ANALYSIS_CONFIGURABLE_CUTS_CLASSES_H diff --git a/Analysis/Tasks/PWGCF/CMakeLists.txt b/Analysis/Tasks/PWGCF/CMakeLists.txt index 27f3ec9a4c86a..d97dc7fb6cdef 100644 --- a/Analysis/Tasks/PWGCF/CMakeLists.txt +++ b/Analysis/Tasks/PWGCF/CMakeLists.txt @@ -8,8 +8,16 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +o2_add_library(PWGCFCore + SOURCES AnalysisConfigurableCuts.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel) + +o2_target_root_dictionary(PWGCFCore + HEADERS AnalysisConfigurableCuts.h + LINKDEF PWGCFCoreLinkDef.h) + o2_add_dpl_workflow(dptdptcorrelations SOURCES dptdptcorrelations.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel O2::PWGCFCore COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGCF/PWGCFCoreLinkDef.h b/Analysis/Tasks/PWGCF/PWGCFCoreLinkDef.h new file mode 100644 index 0000000000000..9a46f9dc8e5da --- /dev/null +++ b/Analysis/Tasks/PWGCF/PWGCFCoreLinkDef.h @@ -0,0 +1,17 @@ +// 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. + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::analysis::EventSelectionCuts + ; +#pragma link C++ class o2::analysis::DptDptBinningCuts + ; +#pragma link C++ class o2::analysis::SimpleInclusiveCut + ; diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index e6e83fae6eb91..60b8aad57574d 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -7,13 +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. -#include "Framework/runDataProcessing.h" + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "Analysis/EventSelection.h" #include "Analysis/Centrality.h" #include "Analysis/TrackSelection.h" +#include "AnalysisConfigurableCuts.h" #include "Analysis/TrackSelectionTables.h" #include <TROOT.h> #include <TParameter.h> @@ -31,6 +32,20 @@ using namespace o2::framework; using namespace o2::soa; using namespace o2::framework::expressions; +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // std::vector<ConfigParamSpec> options{ + // {"centralities", VariantType::String, "0-5,5-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", {"Centrality/multiplicity ranges in min-max separated by commas"}}}; + // std::swap(workflowOptions, options); + ConfigParamSpec centspec = {"centralities", + VariantType::String, + "0-5,5-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", + {"Centrality/multiplicity ranges in min-max separated by commas"}}; + workflowOptions.push_back(centspec); +} + +#include "Framework/runDataProcessing.h" + namespace o2 { namespace aod @@ -39,15 +54,17 @@ namespace aod namespace dptdptcorrelations { DECLARE_SOA_COLUMN(EventAccepted, eventaccepted, uint8_t); +DECLARE_SOA_COLUMN(EventCentMult, centmult, float); DECLARE_SOA_COLUMN(TrackacceptedAsOne, trackacceptedasone, uint8_t); DECLARE_SOA_COLUMN(TrackacceptedAsTwo, trackacceptedastwo, uint8_t); } // namespace dptdptcorrelations -DECLARE_SOA_TABLE(AcceptedEvents, "AOD", "ACCEPTEDEVENTS", dptdptcorrelations::EventAccepted); +DECLARE_SOA_TABLE(AcceptedEvents, "AOD", "ACCEPTEDEVENTS", dptdptcorrelations::EventAccepted, dptdptcorrelations::EventCentMult); DECLARE_SOA_TABLE(ScannedTracks, "AOD", "SCANNEDTRACKS", dptdptcorrelations::TrackacceptedAsOne, dptdptcorrelations::TrackacceptedAsTwo); using CollisionEvSelCent = soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator; using TrackData = soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection>::iterator; using FilteredTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::ScannedTracks>>; +using FilteredTrackData = Partition<aod::FilteredTracks>::filtered_iterator; } // namespace aod } // namespace o2 @@ -60,11 +77,10 @@ int etabins = 16; float etalow = -0.8, etaup = 0.8; int zvtxbins = 40; float zvtxlow = -10.0, zvtxup = 10.0; -/* this still panding of being configurable */ int phibins = 72; - float philow = 0.0; float phiup = TMath::TwoPi(); +float phibinshift = 0.5; float etabinwidth = (etaup - etalow) / float(etabins); float phibinwidth = (phiup - philow) / float(phibins); int tracktype = 1; @@ -89,6 +105,8 @@ enum SystemType { knSystems ///< number of handled systems }; +namespace filteranalyistask +{ //============================================================================================ // The DptDptCorrelationsFilterAnalysisTask output objects //============================================================================================ @@ -115,7 +133,10 @@ TH2F* fhEtaVsPhiA = nullptr; TH2F* fhPtVsEtaB = nullptr; TH2F* fhPtVsEtaA = nullptr; +} // namespace filteranalyistask +namespace correlationstask +{ //============================================================================================ // The DptDptCorrelationsAnalysisTask output objects //============================================================================================ @@ -150,6 +171,7 @@ TProfile* fhN2nw_12_vsC; //!<! track 1 and 2 un-weighted two particle dist TProfile* fhSum2PtPtnw_12_vsC; //!<! track 1 and 2 un-weighted accumulated \f${p_T}_1 {p_T}_2\f$ distribution vs event centrality TProfile* fhSum2PtNnw_12_vsC; //!<! track 1 and 2 un-weighted accumulated \f${p_T}_1 n_2\f$ distribution vs event centrality TProfile* fhSum2NPtnw_12_vsC; //!<! track 1 and 2 un-weighted accumulated \f$n_1 {p_T}_2\f$ distribution vs event centrality +} // namespace correlationstask SystemType getSystemType() { @@ -157,12 +179,19 @@ SystemType getSystemType() return kPbPb; } -bool IsEvtSelected(aod::CollisionEvSelCent const& collision) +bool IsEvtSelected(aod::CollisionEvSelCent const& collision, const std::string estimator, float& centormult) { if (collision.alias()[kINT7]) { if (collision.sel7()) { + /* TODO: vertex quality checks */ if (zvtxlow < collision.posZ() and collision.posZ() < zvtxup) { - return true; + if (estimator.compare("V0M") == 0) { + if (collision.centV0M() < 100 and 0 < collision.centV0M()) { + centormult = collision.centV0M(); + return true; + } + } + return false; } return false; } @@ -190,37 +219,40 @@ bool matchTrackType(aod::TrackData const& track) } } -inline std::tuple<uint8_t, uint8_t> AcceptTrack(aod::TrackData const& track) +inline void AcceptTrack(aod::TrackData const& track, uint8_t& asone, uint8_t& astwo) { - uint8_t asone = DPTDPT_FALSE; - uint8_t astwo = DPTDPT_FALSE; + asone = DPTDPT_FALSE; + astwo = DPTDPT_FALSE; /* TODO: incorporate a mask in the scanned tracks table for the rejecting track reason */ if (matchTrackType(track)) { if (ptlow < track.pt() and track.pt() < ptup and etalow < track.eta() and track.eta() < etaup) { if (((track.charge() > 0) and (trackonecharge > 0)) or ((track.charge() < 0) and (trackonecharge < 0))) { asone = DPTDPT_TRUE; - } else if (((track.charge() > 0) and (tracktwocharge > 0)) or ((track.charge() < 0) and (tracktwocharge < 0))) { + } + if (((track.charge() > 0) and (tracktwocharge > 0)) or ((track.charge() < 0) and (tracktwocharge < 0))) { astwo = DPTDPT_TRUE; } } } - return std::make_tuple(asone, astwo); } -/// \brief Returns the zero based bin index of the eta phi passed values -/// \param eta the eta value -/// \param phi the phi value +/// \brief Returns the zero based bin index of the eta phi passed track +/// \param t the intended track /// \return the zero based bin index /// /// According to the bining structure, to the track eta will correspond /// a zero based bin index and similarlly for the track phi /// The returned index is the composition of both considering eta as /// the first index component -inline int GetEtaPhiIndex(float eta, float phi) +inline int GetEtaPhiIndex(aod::FilteredTrackData const& t) { - int etaix = int((eta - etalow) / etabinwidth); + int etaix = int((t.eta() - etalow) / etabinwidth); + /* consider a potential phi origin shift */ + float phi = t.phi(); + if (not(phi < phiup)) + phi = phi - 2 * TMath::Pi(); int phiix = int((phi - philow) / phibinwidth); return etaix * phibins + phiix; } @@ -237,16 +269,11 @@ struct DptDptCorrelationsFilterAnalysisTask { Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; Configurable<int> cfgTrackOneCharge{"trk1charge", 1, "Trakc one charge: 1 = positive, -1 = negative"}; Configurable<int> cfgTrackTwoCharge{"trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"}; + Configurable<std::string> cfgCentMultEstimator{"centmultestimator", "V0M", "Centrality/multiplicity estimator detector: default V0M"}; - Configurable<int> cfgPtBins{"ptbins", 18, "Number of pT bins, default 18"}; - Configurable<int> cfgZVtxBins{"zvtxbins", 28, "Number of z_vtx bins, default 28"}; - Configurable<int> cfgEtaBins{"etabins", 16, "Number of eta bins, default 16"}; - Configurable<float> cfgPtLow{"ptlow", 0.2f, "Lowest pT (GeV/c), default 0.2"}; - Configurable<float> cfgPtHigh{"pthigh", 2.0f, "Highest pT (GeV/c), default 2.0"}; - Configurable<float> cfgZVtxLow{"zvtxlow", -7.0f, "Lowest z_vtx distance (cm), default -7.0"}; - Configurable<float> cfgZVtxHigh{"zvtxhigh", 7.0f, "Highest z_vtx distance (cm), default 7.0"}; - Configurable<float> cfgEtaLow{"etalow", -0.8f, "Lowest eta value, default -0.8"}; - Configurable<float> cfgEtaHigh{"etahigh", 0.8f, "Highest eta value, default 0.8"}; + Configurable<o2::analysis::DptDptBinningCuts> cfgBinning{"binning", + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.0, TMath::TwoPi()}, + "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; @@ -255,23 +282,22 @@ struct DptDptCorrelationsFilterAnalysisTask { void init(InitContext const&) { - /* update the configurable values */ - ptbins = cfgPtBins.value; - ptlow = cfgPtLow.value; - ptup = cfgPtHigh.value; - etabins = cfgEtaBins.value; - etalow = cfgEtaLow.value; - etaup = cfgEtaHigh.value; - zvtxbins = cfgZVtxBins.value; - zvtxlow = cfgZVtxLow.value; - zvtxup = cfgZVtxHigh.value; + using namespace filteranalyistask; + + /* update with the configurable values */ + ptbins = cfgBinning->mPTbins; + ptlow = cfgBinning->mPTmin; + ptup = cfgBinning->mPTmax; + etabins = cfgBinning->mEtabins; + etalow = cfgBinning->mEtamin; + etaup = cfgBinning->mEtamax; + zvtxbins = cfgBinning->mZVtxbins; + zvtxlow = cfgBinning->mZVtxmin; + zvtxup = cfgBinning->mZVtxmax; tracktype = cfgTrackType.value; trackonecharge = cfgTrackOneCharge.value; tracktwocharge = cfgTrackTwoCharge.value; - /* still missing configuration */ - phibins = 72; - /* if the system type is not known at this time, we have to put the initalization somewhere else */ fSystem = getSystemType(); @@ -331,11 +357,14 @@ struct DptDptCorrelationsFilterAnalysisTask { void process(aod::CollisionEvSelCent const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection> const& ftracks) { + using namespace filteranalyistask; + // LOGF(INFO,"New collision with %d filtered tracks", ftracks.size()); fhCentMultB->Fill(collision.centV0M()); fhVertexZB->Fill(collision.posZ()); int acceptedevent = DPTDPT_FALSE; - if (IsEvtSelected(collision)) { + float centormult = -100.0; + if (IsEvtSelected(collision, cfgCentMultEstimator, centormult)) { acceptedevent = DPTDPT_TRUE; fhCentMultA->Fill(collision.centV0M()); fhVertexZA->Fill(collision.posZ()); @@ -356,7 +385,8 @@ struct DptDptCorrelationsFilterAnalysisTask { /* track selection */ /* tricky because the boolean columns issue */ - auto [asone, astwo] = AcceptTrack(track); + uint8_t asone, astwo; + AcceptTrack(track, asone, astwo); if ((asone == DPTDPT_TRUE) or (astwo == DPTDPT_TRUE)) { /* the track has been accepted */ fhPtA->Fill(track.pt()); @@ -377,52 +407,76 @@ struct DptDptCorrelationsFilterAnalysisTask { scannedtracks(DPTDPT_FALSE, DPTDPT_FALSE); } } - acceptedevents(acceptedevent); + acceptedevents(acceptedevent, centormult); } }; // Task for building <dpt,dpt> correlations struct DptDptCorrelationsTask { + /* the data memebers for this task */ + /* the centrality / multiplicity limits for collecting data in this task instance */ + float fCentMultMin; + float fCentMultMax; - Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; - Configurable<int> cfgTrackOneCharge{"trk1charge", 1, "Trakc one charge: 1 = positive, -1 = negative"}; - Configurable<int> cfgTrackTwoCharge{"trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"}; Configurable<bool> cfgProcessPairs{"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}; - Configurable<int> cfgPtBins{"ptbins", 18, "Number of pT bins, default 18"}; - Configurable<int> cfgZVtxBins{"zvtxbins", 28, "Number of z_vtx bins, default 28"}; - Configurable<int> cfgEtaBins{"etabins", 16, "Number of eta bins, default 16"}; - Configurable<float> cfgPtLow{"ptlow", 0.2f, "Lowest pT (GeV/c), default 0.2"}; - Configurable<float> cfgPtHigh{"pthigh", 2.0f, "Highest pT (GeV/c), default 2.0"}; - Configurable<float> cfgZVtxLow{"zvtxlow", -7.0f, "Lowest z_vtx distance (cm), default -7.0"}; - Configurable<float> cfgZVtxHigh{"zvtxhigh", 7.0f, "Highest z_vtx distance (cm), default 7.0"}; - Configurable<float> cfgEtaLow{"etalow", -0.8f, "Lowest eta value, default -0.8"}; - Configurable<float> cfgEtaHigh{"etahigh", 0.8f, "Highest eta value, default 0.8"}; + Configurable<o2::analysis::DptDptBinningCuts> cfgBinning{"binning", + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.0, TMath::TwoPi()}, + "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}; + Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); + Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); + + Partition<aod::FilteredTracks> Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE; + Partition<aod::FilteredTracks> Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE; + + DptDptCorrelationsTask(float cmmin, + float cmmax, + Configurable<bool> _cfgProcessPairs = {"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}, + Configurable<o2::analysis::DptDptBinningCuts> _cfgBinning = {"binning", + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.0, TMath::TwoPi()}, + "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}, + OutputObj<TList> _fOutput = {"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}, + Filter _onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE), + Filter _onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)), + Partition<aod::FilteredTracks> _Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE, + Partition<aod::FilteredTracks> _Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE) + : fCentMultMin(cmmin), + fCentMultMax(cmmax), + cfgProcessPairs(_cfgProcessPairs), + cfgBinning(_cfgBinning), + fOutput(_fOutput), + onlyacceptedevents((aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE) and (aod::dptdptcorrelations::centmult > fCentMultMin) and (aod::dptdptcorrelations::centmult < fCentMultMax)), + onlyacceptedtracks((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)), + Tracks1(aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE), + Tracks2(aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE) + { + } + void init(InitContext const&) { - /* update the configurable values */ - ptbins = cfgPtBins.value; - ptlow = cfgPtLow.value; - ptup = cfgPtHigh.value; - etabins = cfgEtaBins.value; - etalow = cfgEtaLow.value; - etaup = cfgEtaHigh.value; - zvtxbins = cfgZVtxBins.value; - zvtxlow = cfgZVtxLow.value; - zvtxup = cfgZVtxHigh.value; - tracktype = cfgTrackType.value; - trackonecharge = cfgTrackOneCharge.value; - tracktwocharge = cfgTrackTwoCharge.value; + using namespace correlationstask; + + /* update with the configurable values */ + ptbins = cfgBinning->mPTbins; + ptlow = cfgBinning->mPTmin; + ptup = cfgBinning->mPTmax; + etabins = cfgBinning->mEtabins; + etalow = cfgBinning->mEtamin; + etaup = cfgBinning->mEtamax; + zvtxbins = cfgBinning->mZVtxbins; + zvtxlow = cfgBinning->mZVtxmin; + zvtxup = cfgBinning->mZVtxmax; + phibins = cfgBinning->mPhibins; + philow = cfgBinning->mPhimin; + phiup = cfgBinning->mPhimax; + phibinshift = cfgBinning->mPhibinshift; processpairs = cfgProcessPairs.value; - - /* still missing configuration */ - phibins = 72; - /* TODO: shift of the azimuthal angle origin */ - philow = 0.0; - phiup = TMath::TwoPi(); + /* update the potential binning change */ + etabinwidth = (etaup - etalow) / float(etabins); + phibinwidth = (phiup - philow) / float(phibins); /* create the output list which will own the task histograms */ TList* fOutputList = new TList(); @@ -442,8 +496,11 @@ struct DptDptCorrelationsTask { fOutputList->Add(new TParameter<Double_t>("MaxEta", etaup, 'f')); fOutputList->Add(new TParameter<Double_t>("MinPhi", philow, 'f')); fOutputList->Add(new TParameter<Double_t>("MaxPhi", phiup, 'f')); + fOutputList->Add(new TParameter<Double_t>("PhiBinShift", phibinshift, 'f')); - /* TODO: the shift in the origen of the azimuthal angle */ + /* after the parameters dump the proper phi limits are set according to the phi shift */ + phiup = phiup - phibinwidth * phibinshift; + philow = philow - phibinwidth * phibinshift; /* create the histograms */ Bool_t oldstatus = TH1::AddDirectoryStatus(); @@ -451,12 +508,22 @@ struct DptDptCorrelationsTask { if (!processpairs) { fhN1_1_vsPt = new TH1F("n1_1_vsPt", "#LT n_{1} #GT;p_{t,1} (GeV/c);#LT n_{1} #GT", ptbins, ptlow, ptup); + fhN1_2_vsPt = new TH1F("n1_2_vsPt", "#LT n_{1} #GT;p_{t,2} (GeV/c);#LT n_{1} #GT", ptbins, ptlow, ptup); + /* we don't want the Sumw2 structure being created here */ + bool defSumw2 = TH1::GetDefaultSumw2(); fhN1_1_vsZEtaPhiPt = new TH3F("n1_1_vsZ_vsEtaPhi_vsPt", "#LT n_{1} #GT;vtx_{z};#eta_{1}#times#varphi_{1};p_{t,1} (GeV/c)", zvtxbins, zvtxlow, zvtxup, etabins * phibins, 0.0, double(etabins * phibins), ptbins, ptlow, ptup); - fhN1_2_vsPt = new TH1F("n1_2_vsPt", "#LT n_{1} #GT;p_{t,2} (GeV/c);#LT n_{1} #GT", ptbins, ptlow, ptup); fhN1_2_vsZEtaPhiPt = new TH3F("n1_2_vsZ_vsEtaPhi_vsPt", "#LT n_{2} #GT;vtx_{z};#eta_{2}#times#varphi_{2};p_{t,2} (GeV/c)", zvtxbins, zvtxlow, zvtxup, etabins * phibins, 0.0, double(etabins * phibins), ptbins, ptlow, ptup); + /* we return it back to previuos state */ + TH1::SetDefaultSumw2(defSumw2); + + /* the statistical uncertainties will be estimated by the subsamples method so let's get rid of the error tracking */ + fhN1_1_vsZEtaPhiPt->SetBit(TH1::kIsNotW); + fhN1_1_vsZEtaPhiPt->Sumw2(false); + fhN1_2_vsZEtaPhiPt->SetBit(TH1::kIsNotW); + fhN1_2_vsZEtaPhiPt->Sumw2(false); fOutputList->Add(fhN1_1_vsPt); fOutputList->Add(fhN1_1_vsZEtaPhiPt); @@ -481,6 +548,8 @@ struct DptDptCorrelationsTask { fhN1nw_2_vsC = new TProfile("n1Nw_2_vsM", "#LT n_{1} #GT;Centrality (%);#LT n_{1} #GT", 100, 0.0, 100.0); fhSum1Ptnw_2_vsC = new TProfile("sumPtNw_2_vsM", "#LT #Sigma p_{t,1} #GT;Centrality (%);#LT #Sigma p_{t,1} #GT (GeV/c)", 100, 0.0, 100.0); + /* we don't want the Sumw2 structure being created here */ + bool defSumw2 = TH1::GetDefaultSumw2(); fhN2_12_vsEtaPhi = new TH1F("n2_12_vsEtaPhi", "#LT n_{2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT n_{2} #GT", etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); fhSum2PtPt_12_vsEtaPhi = new TH1F("sumPtPt_12_vsEtaPhi", "#LT #Sigma p_{t,1}p_{t,2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT #Sigma p_{t,1}p_{t,2} #GT (GeV)^{2}", @@ -489,6 +558,9 @@ struct DptDptCorrelationsTask { etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); fhSum2NPt_12_vsEtaPhi = new TH1F("sumNPt_12_vsEtaPhi", "#LT N#Sigma p_{t,2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT N#Sigma p_{t,2} #GT (GeV)", etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); + /* we return it back to previuos state */ + TH1::SetDefaultSumw2(defSumw2); + fhN2_12_vsPtPt = new TH2F("n2_12_vsPtVsPt", "#LT n_{2} #GT;p_{t,1} (GeV/c);p_{t,2} (GeV/c);#LT n_{2} #GT", ptbins, ptlow, ptup, ptbins, ptlow, ptup); fhN2_12_vsC = new TProfile("n2_12_vsM", "#LT n_{2} #GT (weighted);Centrality (%);#LT n_{2} #GT", 100, 0.0, 100.0); @@ -500,10 +572,14 @@ struct DptDptCorrelationsTask { fhSum2PtNnw_12_vsC = new TProfile("sumPtNNw_12_vsM", "#LT #Sigma p_{t,1}N #GT;Centrality (%);#LT #Sigma p_{t,1}N #GT (GeV)", 100, 0.0, 100.0); fhSum2NPtnw_12_vsC = new TProfile("sumNPtNw_12_vsM", "#LT N#Sigma p_{t,2} #GT;Centrality (%);#LT N#Sigma p_{t,2} #GT (GeV)", 100, 0.0, 100.0); - /* the statistical uncertainties will be estimated by the subsamples method so let's get rid of error tracking */ + /* the statistical uncertainties will be estimated by the subsamples method so let's get rid of the error tracking */ + fhN2_12_vsEtaPhi->SetBit(TH1::kIsNotW); fhN2_12_vsEtaPhi->Sumw2(false); + fhSum2PtPt_12_vsEtaPhi->SetBit(TH1::kIsNotW); fhSum2PtPt_12_vsEtaPhi->Sumw2(false); + fhSum2PtN_12_vsEtaPhi->SetBit(TH1::kIsNotW); fhSum2PtN_12_vsEtaPhi->Sumw2(false); + fhSum2NPt_12_vsEtaPhi->SetBit(TH1::kIsNotW); fhSum2NPt_12_vsEtaPhi->Sumw2(false); fOutputList->Add(fhN1_1_vsEtaPhi); @@ -537,40 +613,114 @@ struct DptDptCorrelationsTask { TH1::AddDirectory(oldstatus); } - Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); - Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); - - Partition<aod::FilteredTracks> Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE; - Partition<aod::FilteredTracks> Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE; - void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents, aod::AcceptedEvents>>::iterator const& collision, aod::FilteredTracks const& tracks) { - if (!processpairs) { + using namespace correlationstask; + + if (not processpairs) { /* process single tracks */ for (auto& track1 : Tracks1) { double corr = 1.0; /* TODO: track correction weights */ fhN1_1_vsPt->Fill(track1.pt(), corr); - fhN1_1_vsZEtaPhiPt->Fill(collision.posZ(), GetEtaPhiIndex(track1.eta(), track1.phi()) + 0.5, track1.pt(), corr); + fhN1_1_vsZEtaPhiPt->Fill(collision.posZ(), GetEtaPhiIndex(track1) + 0.5, track1.pt(), corr); } for (auto& track2 : Tracks2) { double corr = 1.0; /* TODO: track correction weights */ fhN1_2_vsPt->Fill(track2.pt(), corr); - fhN1_2_vsZEtaPhiPt->Fill(collision.posZ(), GetEtaPhiIndex(track2.eta(), track2.phi()) + 0.5, track2.pt(), corr); + fhN1_2_vsZEtaPhiPt->Fill(collision.posZ(), GetEtaPhiIndex(track2) + 0.5, track2.pt(), corr); } } else { + { + /* process track one magnitudes */ + double n1_1 = 0; ///< weighted number of track 1 tracks for current collision + double sum1Pt_1 = 0; ///< accumulated sum of weighted track 1 \f$p_T\f$ for current collision + double n1nw_1 = 0; ///< not weighted number of track 1 tracks for current collision + double sum1Ptnw_1 = 0; ///< accumulated sum of not weighted track 1 \f$p_T\f$ for current collision + for (auto& track1 : Tracks1) { + double corr = 1.0; /* TODO: track correction weights */ + n1_1 += corr; + sum1Pt_1 += track1.pt() * corr; + n1nw_1 += 1; + sum1Ptnw_1 += track1.pt(); + + fhN1_1_vsEtaPhi->Fill(track1.eta(), track1.phi(), corr); + fhSum1Pt_1_vsEtaPhi->Fill(track1.eta(), track1.phi(), track1.pt() * corr); + } + /* TODO: the centrality should be chosen non detector dependent */ + fhN1_1_vsC->Fill(collision.centmult(), n1_1); + fhSum1Pt_1_vsC->Fill(collision.centmult(), sum1Pt_1); + fhN1nw_1_vsC->Fill(collision.centmult(), n1nw_1); + fhSum1Ptnw_1_vsC->Fill(collision.centmult(), sum1Ptnw_1); + } + { + /* process track two magnitudes */ + double n1_2 = 0; ///< weighted number of track 2 tracks for current collisiont + double sum1Pt_2 = 0; ///< accumulated sum of weighted track 2 \f$p_T\f$ for current collision + double n1nw_2 = 0; ///< not weighted number of track 2 tracks for current collision + double sum1Ptnw_2 = 0; ///< accumulated sum of not weighted track 2 \f$p_T\f$ for current collision + for (auto& track2 : Tracks2) { + double corr = 1.0; /* TODO: track correction weights */ + n1_2 += corr; + sum1Pt_2 += track2.pt() * corr; + n1nw_2 += 1; + sum1Ptnw_2 += track2.pt(); + + fhN1_2_vsEtaPhi->Fill(track2.eta(), track2.phi(), corr); + fhSum1Pt_2_vsEtaPhi->Fill(track2.eta(), track2.phi(), track2.pt() * corr); + } + /* TODO: the centrality should be chosen non detector dependent */ + fhN1_2_vsC->Fill(collision.centmult(), n1_2); + fhSum1Pt_2_vsC->Fill(collision.centmult(), sum1Pt_2); + fhN1nw_2_vsC->Fill(collision.centmult(), n1nw_2); + fhSum1Ptnw_2_vsC->Fill(collision.centmult(), sum1Ptnw_2); + } /* process pairs of tracks */ // this will be desireable // for (auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(Tracks1, Tracks2))) { + /* process pair magnitudes */ + double n2_12 = 0; ///< weighted number of track 1 track 2 pairs for current collision + double sum2PtPt_12 = 0; ///< accumulated sum of weighted track 1 track 2 \f${p_T}_1 {p_T}_2\f$ for current collision + double sum2NPt_12 = 0; ///< accumulated sum of weighted number of track 1 tracks times weighted track 2 \f$p_T\f$ for current collision + double sum2PtN_12 = 0; ///< accumulated sum of weighted track 1 \f$p_T\f$ times weighted number of track 2 tracks for current collision + double n2nw_12 = 0; ///< not weighted number of track1 track 2 pairs for current collision + double sum2PtPtnw_12 = 0; ///< accumulated sum of not weighted track 1 track 2 \f${p_T}_1 {p_T}_2\f$ for current collision + double sum2NPtnw_12 = 0; ///< accumulated sum of not weighted number of track 1 tracks times not weighted track 2 \f$p_T\f$ for current collision + double sum2PtNnw_12 = 0; ///< accumulated sum of not weighted track 1 \f$p_T\f$ times not weighted number of track tracks for current collision for (auto& track1 : Tracks1) { for (auto& track2 : Tracks2) { /* checkiing the same track id condition */ if (track1.index() == track2.index()) { - LOGF(INFO, "Tracks with the same Id: %d", track1.index()); + /* exclude autocorrelations */ } else { + /* process pair magnitudes */ + double corr1 = 1.0; /* TODO: track correction weights */ + double corr2 = 1.0; /* TODO: track correction weights */ + double corr = corr1 * corr2; + n2_12 += corr; + sum2PtPt_12 += track1.pt() * track2.pt() * corr; + sum2NPt_12 += corr * track2.pt(); + sum2PtN_12 += track1.pt() * corr; + n2nw_12 += 1; + sum2PtPtnw_12 += track1.pt() * track2.pt(); + sum2NPtnw_12 += track2.pt(); + sum2PtNnw_12 += track1.pt(); + fhN2_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, corr); + fhSum2NPt_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, corr * track2.pt()); + fhSum2PtN_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, track1.pt() * corr); + fhSum2PtPt_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, track1.pt() * track2.pt() * corr); + fhN2_12_vsPtPt->Fill(track1.pt(), track2.pt(), corr); } } } + fhN2_12_vsC->Fill(collision.centmult(), n2_12); + fhSum2PtPt_12_vsC->Fill(collision.centmult(), sum2PtPt_12); + fhSum2PtN_12_vsC->Fill(collision.centmult(), sum2PtN_12); + fhSum2NPt_12_vsC->Fill(collision.centmult(), sum2NPt_12); + fhN2nw_12_vsC->Fill(collision.centmult(), n2nw_12); + fhSum2PtPtnw_12_vsC->Fill(collision.centmult(), sum2PtPtnw_12); + fhSum2PtNnw_12_vsC->Fill(collision.centmult(), sum2PtNnw_12); + fhSum2NPtnw_12_vsC->Fill(collision.centmult(), sum2NPtnw_12); } } }; @@ -578,6 +728,8 @@ struct DptDptCorrelationsTask { // Task for building <dpt,dpt> correlations struct TracksAndEventClassificationQA { + Configurable<o2::analysis::SimpleInclusiveCut> cfg{"mycfg", {"mycfg", 3, 2.0f}, "A Configurable Object, default mycfg.x=3, mycfg.y=2.0"}; + OutputObj<TH1F> fTracksOne{TH1F("TracksOne", "Tracks as track one;number of tracks;events", 1500, 0.0, 1500.0)}; OutputObj<TH1F> fTracksTwo{TH1F("TracksTwo", "Tracks as track two;number of tracks;events", 1500, 0.0, 1500.0)}; OutputObj<TH1F> fTracksOneAndTwo{TH1F("TracksOneAndTwo", "Tracks as track one and as track two;number of tracks;events", 1500, 0.0, 1500.0)}; @@ -639,11 +791,21 @@ struct TracksAndEventClassificationQA { } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ + std::string myoptcentralities = cfgc.options().get<std::string>("centralities"); + TObjArray* tokens = TString(myoptcentralities.c_str()).Tokenize(","); + int nranges = tokens->GetEntries(); + + WorkflowSpec workflow{ adaptAnalysisTask<DptDptCorrelationsFilterAnalysisTask>("DptDptCorrelationsFilterAnalysisTask"), - adaptAnalysisTask<DptDptCorrelationsTask>("DptDptCorrelationsTask"), - adaptAnalysisTask<TracksAndEventClassificationQA>("TracksAndEventClassificationQA"), - }; + adaptAnalysisTask<TracksAndEventClassificationQA>("TracksAndEventClassificationQA")}; + for (int i = 0; i < nranges; ++i) { + float cmmin = 0.0f; + float cmmax = 0.0f; + sscanf(tokens->At(i)->GetName(), "%f-%f", &cmmin, &cmmax); + workflow.push_back(adaptAnalysisTask<DptDptCorrelationsTask>(Form("DptDptCorrelationsTask-%s", tokens->At(i)->GetName()), cmmin, cmmax)); + } + delete tokens; + return workflow; } From 163586a79d6d9f0b41c36a81515780fcc4f33714 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Tue, 15 Sep 2020 08:36:56 +0200 Subject: [PATCH 0612/1751] HistHelpers: improved histogram collection and hist builder (#4330) - support TProfiles - support TList based collections - support weighted fills - allow in-place allocation of root histograms with new - rename HistBuilder -> Hist and remove root pointer member - allow copying Hist objects and adding axes from existing Hist --- Analysis/Core/include/Analysis/HistHelpers.h | 238 ++++++++++++------- Analysis/Tutorials/src/histHelpersTest.cxx | 97 ++++++-- 2 files changed, 229 insertions(+), 106 deletions(-) diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/Analysis/HistHelpers.h index 1cbff6e38fa3b..63b3d2513090a 100644 --- a/Analysis/Core/include/Analysis/HistHelpers.h +++ b/Analysis/Core/include/Analysis/HistHelpers.h @@ -21,7 +21,13 @@ #include <TH3.h> #include <THn.h> #include <THnSparse.h> +#include <TProfile.h> +#include <TProfile2D.h> +#include <TProfile3D.h> + #include <TObjArray.h> +#include <TList.h> +//#include <TDirectory.h> #include "Framework/Logger.h" @@ -42,101 +48,146 @@ struct is_shared_ptr<std::shared_ptr<T>> : 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. + * RootContainer (TObjArray or TList) inheritance is required to interface with O2 file writing functionality. */ //************************************************************************************************** -class HistContainer : public TObjArray +template <class RootContainer> +class HistContainer : public RootContainer { public: - HistContainer(const std::string& name) : TObjArray() + HistContainer(const std::string& name) : RootContainer() + { + RootContainer::SetOwner(false); // let container handle object deletion + RootContainer::SetName(name.data()); + } + HistContainer(const HistContainer& other) { - SetBit(TObject::kSingleKey, false); // not working; seems like WriteObjectAny ignores this... - SetOwner(false); // let container handle object deletion - SetName(name.data()); + // pseudo copy ctor to move around empty collection on construction (no real copy constructor!) + // this is needed to be able to put this in OutputObj + // Memo: default copy ctor does not work for TList based collections since + // their copy constructor is implicitly deleted as opposed to TObjArrays + RootContainer::SetOwner(false); + RootContainer::SetName(other.GetName()); } - using HistType = std::variant<std::shared_ptr<TH3>, std::shared_ptr<TH2>, std::shared_ptr<TH1>, std::shared_ptr<THn>, std::shared_ptr<THnSparse>>; + using HistType = std::variant<std::shared_ptr<THn>, std::shared_ptr<THnSparse>, std::shared_ptr<TH3>, std::shared_ptr<TH2>, std::shared_ptr<TH1>, std::shared_ptr<TProfile3D>, std::shared_ptr<TProfile2D>, std::shared_ptr<TProfile>>; template <typename T> 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); + LOGF(WARNING, "HistContainer %s already holds a histogram at histID = %d. Overriding it now...", RootContainer::GetName(), histID); TObject* oldPtr = nullptr; std::visit([&](const auto& sharedPtr) { oldPtr = sharedPtr.get(); }, mHistos[histID]); - TObjArray::Remove(oldPtr); + RootContainer::Remove(oldPtr); } - // if shared poiner is provided as argument, object itself is used, otherwise copied + // if shared pointers or rvalue raw pointers are provided as argument, the existing object is used + // otherwise the existing object is copied + std::optional<HistType> histVariant{}; if constexpr (is_shared_ptr<T>::value) - mHistos[histID] = DownCast(hist); + histVariant = GetHistVariant(hist); + else if constexpr (std::is_pointer_v<T> && std::is_rvalue_reference_v<decltype(std::forward<T>(hist))>) + histVariant = GetHistVariant(std::shared_ptr<std::remove_pointer_t<T>>(hist)); else { - mHistos[histID] = DownCast(std::make_shared<T>(hist)); + histVariant = GetHistVariant(std::make_shared<T>(hist)); + } + if (histVariant) { + mHistos[histID] = *histVariant; + TObject* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mHistos[histID]); + RootContainer::Add(rawPtr); + } else { + LOGF(FATAL, "Could not create histogram."); } - 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<TH1>(), Get<TH2>(), Get<TH3>(), Get<THn>(), Get<THnSparse>() + // we cannot automatically infer type here so it has to be explicitly specified + // -> Get<TH1>(), Get<TH2>(), Get<TH3>(), Get<THn>(), Get<THnSparse>(), Get<TProfile>(), Get<TProfile2D>(), Get<TProfile3D>() template <typename T> std::shared_ptr<T> Get(uint8_t histID) { return *std::get_if<std::shared_ptr<T>>(&mHistos[histID]); } - template <typename... Ts> + // fill histogram or profile with arguments x,y,z,... and weight if requested + template <bool fillWeight = false, typename... Ts> void Fill(uint8_t histID, Ts&&... position) { - std::visit([this, &position...](auto&& hist) { GenericFill(hist, std::forward<Ts>(position)...); }, mHistos[histID]); + std::visit([this, &position...](auto&& hist) { GenericFill<fillWeight>(hist, std::forward<Ts>(position)...); }, mHistos[histID]); + } + template <typename... Ts> + void FillWeight(uint8_t histID, Ts&&... positionAndWeight) + { + Fill<true>(histID, std::forward<Ts>(positionAndWeight)...); } private: std::map<uint8_t, HistType> mHistos; - // disallow user to call TObjArray::Add() - using TObjArray::Add; + // disallow user to call RootContainer::Add() to avoid memory leaks + using RootContainer::Add; - template <typename T, typename... Ts> + template <bool fillWeight = false, typename T, typename... Ts> void GenericFill(std::shared_ptr<T> hist, const Ts&... position) { - constexpr bool isValidTH3 = (std::is_same_v<TH3, T> && sizeof...(Ts) == 3); - constexpr bool isValidTH2 = (std::is_same_v<TH2, T> && sizeof...(Ts) == 2); - constexpr bool isValidTH1 = (std::is_same_v<TH1, T> && sizeof...(Ts) == 1); - constexpr bool isValidPrimitive = isValidTH1 || isValidTH2 || isValidTH3; + // filling with weights requires one additional argument + constexpr bool isTH3 = (std::is_same_v<TH3, T> && sizeof...(Ts) == 3 + fillWeight); + constexpr bool isTH2 = (std::is_same_v<TH2, T> && sizeof...(Ts) == 2 + fillWeight); + constexpr bool isTH1 = (std::is_same_v<TH1, T> && sizeof...(Ts) == 1 + fillWeight); + constexpr bool isTProfile3D = (std::is_same_v<TProfile3D, T> && sizeof...(Ts) == 4 + fillWeight); + constexpr bool isTProfile2D = (std::is_same_v<TProfile2D, T> && sizeof...(Ts) == 3 + fillWeight); + constexpr bool isTProfile = (std::is_same_v<TProfile, T> && sizeof...(Ts) == 2 + fillWeight); + + constexpr bool isValidPrimitive = isTH1 || isTH2 || isTH3 || isTProfile || isTProfile2D || isTProfile3D; // unfortunately we dont know at compile the dimension of THn(Sparse) - constexpr bool isValidComplex = std::is_base_of<THnBase, T>::value; + constexpr bool isValidComplex = std::is_base_of_v<THnBase, T>; if constexpr (isValidPrimitive) { hist->Fill(static_cast<double>(position)...); } else if constexpr (isValidComplex) { // savety check for n dimensional histograms (runtime overhead) - // if(hist->GetNdimensions() != sizeof...(position)) return; + // if (hist->GetNdimensions() != sizeof...(position) - fillWeight) return; double tempArray[] = {static_cast<double>(position)...}; - hist->Fill(tempArray); + if constexpr (fillWeight) + hist->Fill(tempArray, tempArray[sizeof...(Ts) - 1]); + else + hist->Fill(tempArray); } }; template <typename T> - HistType DownCast(std::shared_ptr<T> hist) + std::optional<HistType> GetHistVariant(std::shared_ptr<TObject> obj) { - // 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<TH3, T>) { - return std::static_pointer_cast<TH3>(hist); - } else if constexpr (std::is_base_of_v<TH2, T>) { - return std::static_pointer_cast<TH2>(hist); - } else { - // all other cases can be left untouched + if (obj->InheritsFrom(T::Class())) { + return std::static_pointer_cast<T>(obj); + } + return std::nullopt; + } + template <typename T, typename Next, typename... Rest> + std::optional<HistType> GetHistVariant(std::shared_ptr<TObject> obj) + { + if (auto hist = GetHistVariant<T>(obj)) { return hist; } + return GetHistVariant<Next, Rest...>(obj); + } + std::optional<HistType> GetHistVariant(std::shared_ptr<TObject> obj) + { + // Remember: TProfile3D is TH3, TProfile2D is TH2, TH3 is TH1, TH2 is TH1, TProfile is TH1 + if (obj) { + return GetHistVariant<THn, THnSparse, TProfile3D, TH3, TProfile2D, TH2, TProfile, TH1>(obj); + } + return std::nullopt; } }; +//************************************************************************************************** +using HistArray = HistContainer<TObjArray>; +using HistList = HistContainer<TList>; +//using HistDirectory = HistContainer<TDirectory>; +//************************************************************************************************** + //************************************************************************************************** /** * Helper class to build all kinds of root histograms with a streamlined user interface. @@ -147,34 +198,51 @@ struct Axis { std::string name{}; std::string title{}; std::vector<double> binEdges{}; - int nBins{}; // 0 when bin edges are specified directly FIXME: make this std::optional + std::optional<int> nBins{}; }; -template <typename RootHist_t> -class HistBuilder +template <typename RootHistType> +class Hist { public: - HistBuilder() : mAxes{}, mHist{nullptr} {} - HistBuilder(const HistBuilder&) = delete; // non construction-copyable - HistBuilder& operator=(const HistBuilder&) = delete; // non copyable + Hist() : mAxes{} {} - void AddAxis(const Axis& axis) { mAxes.push_back(axis); } - void AddAxes(const std::vector<Axis>& axes) + void AddAxis(const Axis& axis) { - mAxes.insert(mAxes.end(), axes.begin(), axes.end()); + mAxes.push_back(axis); } - void AddAxis(const std::string& name, const std::string& title, const int& nBins, - const double& lowerEdge, const double& upperEdge) + + 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<double>& binEdges) { - mAxes.push_back({name, title, binEdges, 0}); + mAxes.push_back({name, title, binEdges}); + } + + void AddAxes(const std::vector<Axis>& axes) + { + mAxes.insert(mAxes.end(), axes.begin(), axes.end()); + } + + // add axes defined in other Hist object + template <typename T> + void AddAxes(const Hist<T>& other) + { + mAxes.insert(mAxes.end(), other.GetAxes().begin(), other.GetAxes().end()); } - std::shared_ptr<RootHist_t> GenerateHist(const std::string& name, bool hasWeights = false) + void Reset() + { + mAxes.clear(); + } + + // create histogram with the defined axes + std::shared_ptr<RootHistType> Create(const std::string& name, bool useWeights = false) { const std::size_t MAX_DIM{10}; const std::size_t nAxes{mAxes.size()}; @@ -188,7 +256,7 @@ class HistBuilder // 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; + 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; @@ -199,70 +267,70 @@ class HistBuilder } // create histogram - mHist.reset(HistFactory(name, title, nAxes, nBins, lowerBounds, upperBounds)); + std::shared_ptr<RootHistType> hist(HistFactory(name, title, nAxes, nBins, lowerBounds, upperBounds)); - if (!mHist) { - LOGF(WARNING, "ERROR: The number of specified dimensions does not match the type."); + if (!hist) { + LOGF(FATAL, "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)}; + TAxis* axis{GetAxis(i, hist)}; if (axis) { axis->SetTitle(mAxes[i].title.data()); - if constexpr (std::is_base_of_v<THnBase, RootHist_t>) + if constexpr (std::is_base_of_v<THnBase, RootHistType>) axis->SetName((std::to_string(i) + "-" + mAxes[i].name).data()); - // move the bin edges in case a variable binnining was requested + // move the bin edges in case a variable binning 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); + LOGF(FATAL, "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; + if (useWeights) + hist->Sumw2(); + return hist; } + const std::vector<Axis>& GetAxes() const { return mAxes; }; + private: std::vector<Axis> mAxes; - std::shared_ptr<RootHist_t> 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[]) + RootHistType* 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<THnBase, RootHist_t>) { - return new RootHist_t(name.data(), title.data(), nDim, nBins, lowerBounds, upperBounds); - } else if constexpr (std::is_base_of_v<TH3, RootHist_t>) { + if constexpr (std::is_base_of_v<THnBase, RootHistType>) { + return new RootHistType(name.data(), title.data(), nDim, nBins, lowerBounds, upperBounds); + } else if constexpr (std::is_base_of_v<TH3, RootHistType>) { 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<TH2, RootHist_t>) { + : new RootHistType(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<TH2, RootHistType>) { 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<TH1, RootHist_t>) { + : new RootHistType(name.data(), title.data(), nBins[0], lowerBounds[0], + upperBounds[0], nBins[1], lowerBounds[1], upperBounds[1]); + } else if constexpr (std::is_base_of_v<TH1, RootHistType>) { return (nDim != 1) ? nullptr - : new RootHist_t(name.data(), title.data(), nBins[0], lowerBounds[0], upperBounds[0]); + : new RootHistType(name.data(), title.data(), nBins[0], lowerBounds[0], upperBounds[0]); } return nullptr; } - TAxis* GetAxis(const int i) + TAxis* GetAxis(const int i, std::shared_ptr<RootHistType> hist) { - if constexpr (std::is_base_of_v<THnBase, RootHist_t>) { - return mHist->GetAxis(i); + if constexpr (std::is_base_of_v<THnBase, RootHistType>) { + return hist->GetAxis(i); } else { - return (i == 0) ? mHist->GetXaxis() - : (i == 1) ? mHist->GetYaxis() : (i == 2) ? mHist->GetZaxis() : nullptr; + return (i == 0) ? hist->GetXaxis() + : (i == 1) ? hist->GetYaxis() : (i == 2) ? hist->GetZaxis() : nullptr; } } }; diff --git a/Analysis/Tutorials/src/histHelpersTest.cxx b/Analysis/Tutorials/src/histHelpersTest.cxx index ab75b660b8b75..aaddbd758abb2 100644 --- a/Analysis/Tutorials/src/histHelpersTest.cxx +++ b/Analysis/Tutorials/src/histHelpersTest.cxx @@ -42,32 +42,42 @@ struct HistHelpersTest { Hist_test_3d_THnI, Hist_test_5d_THnSparseI, + + Hist_test_1d_TProfile, + Hist_test_2d_TProfile2D, + Hist_test_3d_TProfile3D, + + Hist_test_7d_THnF_first, + Hist_test_7d_THnF_second, + Hist_test_8d_THnC_third, LAST, }; - OutputObj<HistContainer> test{HistContainer("Test"), OutputObjHandlingPolicy::QAObject}; - OutputObj<HistContainer> kine{HistContainer("Kine"), OutputObjHandlingPolicy::QAObject}; - OutputObj<HistContainer> tpc{HistContainer("TPC"), OutputObjHandlingPolicy::QAObject}; - OutputObj<HistContainer> its{HistContainer("ITS"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistArray> test{HistArray("Test"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistArray> kine{HistArray("Kine"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistArray> tpc{HistArray("TPC"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistList> its{HistList("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_2d_TH2F, new 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<TH1D> sameAsBefore; - sameAsBefore.AddAxis({"x", "x", {0., 50.}, 100}); - test->Add(Hist_test_1d_TH1D_Builder, sameAsBefore.GenerateHist("testHist_TH1_Builder")); + // alternatively use Hist to generate the histogram and add it to container afterwards + Hist<TH1D> sameAsBefore; + sameAsBefore.AddAxis("x", "x", 100, 0., 50.); + // via Hist::Create() we can generate the actual root histogram with the requested axes + // Parameters: the name and optionally the decision wether to call SumW2 in case we want to fill this histogram with weights + test->Add(Hist_test_1d_TH1D_Builder, sameAsBefore.Create("testHist_TH1_Builder", true)); - // the builder enables us to have combinations of flexible + fixed binning in 2d or 3d histograms + // this helper enables us to have combinations of flexible + fixed binning in 2d or 3d histograms // (which are not available via default root constructors) - HistBuilder<TH2F> 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")); + Hist<TH2F> sameButDifferent; + sameButDifferent.AddAxis("x", "x", 100, -0.5, 0.5); + 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.Create("testHist_TH2_Builder")); // also for n dimensional histograms things become much simpler: std::vector<double> ptBins = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, @@ -83,22 +93,37 @@ struct HistHelpersTest { const int nCuts = 5; Axis cutAxis = {"cut", "cut setting", {-0.5, nCuts - 0.5}, nCuts}; - HistBuilder<THnI> myHistogram; + Hist<THnI> 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")); + test->Add(Hist_test_3d_THnI, myHistogram.Create("testHist_THn")); - HistBuilder<THnSparseC> testSparseHist; + Hist<THnSparseC> 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")); + test->Add(Hist_test_5d_THnSparseI, testSparseHist.Create("testHist_THnSparse")); - // now add some more useful histograms + Hist<TProfile> testProfile; + testProfile.AddAxis(ptAxis); + test->Add(Hist_test_1d_TProfile, testProfile.Create("testProfile_TProfile")); + test->Get<TProfile>(Hist_test_1d_TProfile)->GetYaxis()->SetTitle("eta profile"); + + Hist<TProfile2D> testProfile2d; + testProfile2d.AddAxis(ptAxis); + testProfile2d.AddAxis(etaAxis); + test->Add(Hist_test_2d_TProfile2D, testProfile2d.Create("testProfile_TProfile2D")); + Hist<TProfile3D> testProfile3d; + testProfile3d.AddAxis(ptAxis); + testProfile3d.AddAxis(etaAxis); + testProfile3d.AddAxis(phiAxis); + test->Add(Hist_test_3d_TProfile3D, testProfile3d.Create("testProfile_TProfile3D")); + + // 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)); @@ -108,6 +133,30 @@ struct HistHelpersTest { 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)); + + // we can also re-use axis definitions in case they are similar in many histograms: + Hist<THnF> baseDimensions; + baseDimensions.AddAxis(ptAxis); + baseDimensions.AddAxis(etaAxis); + baseDimensions.AddAxis(phiAxis); + baseDimensions.AddAxis(centAxis); + baseDimensions.AddAxis(cutAxis); + baseDimensions.AddAxis(centAxis); + + Hist<THnF> firstHist = baseDimensions; + firstHist.AddAxis("something", "v (m/s)", 10, -1, 1); + its->Add(Hist_test_7d_THnF_first, firstHist.Create("firstHist")); + + Hist<THnF> secondHist = baseDimensions; + secondHist.AddAxis("somethingElse", "a (m/(s*s))", 10, -1, 1); + its->Add(Hist_test_7d_THnF_second, secondHist.Create("secondHist")); + + // or if we want to have the baseDimensions somewhere in between: + Hist<THnC> thirdHist; + thirdHist.AddAxis("myFirstDimension", "a (m/(s*s))", 10, -1, 1); + thirdHist.AddAxes(baseDimensions); + thirdHist.AddAxis("myLastDimension", "a (m/(s*s))", 10, -1, 1); + its->Add(Hist_test_8d_THnC_third, thirdHist.Create("thirdHist")); } void process(soa::Join<aod::Tracks, aod::TracksExtra>::iterator const& track) @@ -116,15 +165,21 @@ struct HistHelpersTest { 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.); + // this time fill the 1d histogram with weight of 10: + test->FillWeight(Hist_test_1d_TH1D_Builder, 1., 10.); 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: + // we can also directly access to the underlying histogram + // for this the correct type has to be known (TH1, TH2, TH3, THn, THnSparse, TProfile, TProfile2D or TProfile3D) test->Get<TH2>(Hist_test_2d_TH2F)->Fill(0.2, 0.2); + test->Fill(Hist_test_1d_TProfile, track.pt(), track.eta()); + test->Fill(Hist_test_2d_TProfile2D, track.pt(), track.eta(), track.phi()); + test->Fill(Hist_test_3d_TProfile3D, track.pt(), track.eta(), track.phi(), track.tpcNClsFound()); + kine->Fill(Hist_pt, track.pt()); kine->Fill(Hist_eta, track.eta()); kine->Fill(Hist_phi, track.phi()); From fba35fb97daa061aeffbf567ef96ae02b7833a5c Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 15 Sep 2020 08:37:09 +0200 Subject: [PATCH 0613/1751] some refactoring in correlation container (#4328) --- .../include/Analysis/CorrelationContainer.h | 18 +- Analysis/Core/src/CorrelationContainer.cxx | 162 ++++++++++-------- Analysis/Tasks/CMakeLists.txt | 10 -- Analysis/Tasks/PWGCF/CMakeLists.txt | 10 ++ Analysis/Tasks/{ => PWGCF}/correlations.cxx | 28 +-- .../Tasks/{ => PWGCF}/correlationsMixed.cxx | 4 +- Analysis/Tutorials/src/ZDCVZeroIteration.cxx | 17 ++ 7 files changed, 144 insertions(+), 105 deletions(-) rename Analysis/Tasks/{ => PWGCF}/correlations.cxx (94%) rename Analysis/Tasks/{ => PWGCF}/correlationsMixed.cxx (99%) diff --git a/Analysis/Core/include/Analysis/CorrelationContainer.h b/Analysis/Core/include/Analysis/CorrelationContainer.h index 05ce06125536d..f0b54f3e251e6 100644 --- a/Analysis/Core/include/Analysis/CorrelationContainer.h +++ b/Analysis/Core/include/Analysis/CorrelationContainer.h @@ -20,6 +20,7 @@ class TH1; class TH1F; class TH3; class TH3F; +class TH2F; class TH1D; class TH2; class TH2D; @@ -50,12 +51,13 @@ class CorrelationContainer : public TNamed const char* getStepTitle(CFStep step); - StepTHnBase* getTrackHist() { return mTrackHist; } - StepTHnBase* getEventHist() { return mEventHist; } + StepTHnBase* getPairHist() { return mPairHist; } + StepTHnBase* getTriggerHist() { return mTriggerHist; } StepTHnBase* getTrackHistEfficiency() { return mTrackHistEfficiency; } + TH2F* getEventCount() { return mEventCount; } - void setTrackHist(StepTHnBase* hist) { mTrackHist = hist; } - void setEventHist(StepTHnBase* hist) { mEventHist = hist; } + void setPairHist(StepTHnBase* hist) { mPairHist = hist; } + void setTriggerHist(StepTHnBase* hist) { mTriggerHist = hist; } void setTrackHistEfficiency(StepTHnBase* hist) { mTrackHistEfficiency = hist; } void deepCopy(CorrelationContainer* from); @@ -87,6 +89,8 @@ class CorrelationContainer : public TNamed TH2D* getTrackingEfficiencyCorrection(); TH2D* getTrackingEfficiencyCorrectionCentrality(); + void FillEvent(Float_t centrality, CFStep step); + void extendTrackingEfficiency(Bool_t verbose = kFALSE); void setEtaRange(Float_t etaMin, Float_t etaMax) @@ -144,10 +148,12 @@ class CorrelationContainer : public TNamed void weightHistogram(TH3* hist1, TH1* hist2); void multiplyHistograms(THnBase* grid, THnBase* target, TH1* histogram, Int_t var1, Int_t var2); - StepTHnBase* mTrackHist; // container for track level distributions at all analysis steps - StepTHnBase* mEventHist; // container for event level distribution at all analysis steps + StepTHnBase* mPairHist; // container for pair level distributions at all analysis steps + StepTHnBase* mTriggerHist; // container for "trigger" particle (single-particle) level distribution at all analysis steps StepTHnBase* mTrackHistEfficiency; // container for tracking efficiency and contamination (all particles filled including leading one): axes: eta, pT, particle species + TH2F* mEventCount; // event count as function of step, (for pp: event type (plus additional step -1 for all events without vertex range even in MC)) (for PbPb: centrality) + Float_t mEtaMin; // eta min for projections Float_t mEtaMax; // eta max for projections Float_t mPtMin; // pT min for projections (for track pT, not pT,lead) diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index dcf1413d2294c..15b31dea8cfea 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -34,9 +34,10 @@ ClassImp(CorrelationContainer) const Int_t CorrelationContainer::fgkCFSteps = 11; CorrelationContainer::CorrelationContainer() : TNamed(), - mTrackHist(nullptr), - mEventHist(nullptr), + mPairHist(nullptr), + mTriggerHist(nullptr), mTrackHistEfficiency(nullptr), + mEventCount(nullptr), mEtaMin(0), mEtaMax(0), mPtMin(0), @@ -60,9 +61,10 @@ CorrelationContainer::CorrelationContainer() : TNamed(), } CorrelationContainer::CorrelationContainer(const char* name, const char* objTitle, const char* reqHist, const char* binning) : TNamed(name, objTitle), - mTrackHist(nullptr), - mEventHist(nullptr), + mPairHist(nullptr), + mTriggerHist(nullptr), mTrackHistEfficiency(nullptr), + mEventCount(nullptr), mEtaMin(0), mEtaMax(0), mPtMin(0), @@ -249,9 +251,9 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl } if (axis >= 2 && useAliTHn == 1) - mTrackHist = new StepTHnF("mTrackHist", title, nSteps, nTrackVars, iTrackBin, trackBins, trackAxisTitle); + mPairHist = new StepTHnF("mPairHist", title, nSteps, nTrackVars, iTrackBin, trackBins, trackAxisTitle); else if (axis >= 2 && useAliTHn == 2) - mTrackHist = new StepTHnD("mTrackHist", title, nSteps, nTrackVars, iTrackBin, trackBins, trackAxisTitle); + mPairHist = new StepTHnD("mPairHist", title, nSteps, nTrackVars, iTrackBin, trackBins, trackAxisTitle); // event level Int_t nEventVars = 2; @@ -281,7 +283,7 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl eventBins[3] = trackBins[6]; eventAxisTitle[3] = trackAxisTitle[6]; } - mEventHist = new StepTHnF("mEventHist", title, nSteps, nEventVars, iEventBin, eventBins, eventAxisTitle); + mTriggerHist = new StepTHnF("mTriggerHist", title, nSteps, nEventVars, iEventBin, eventBins, eventAxisTitle); // Efficiency histogram @@ -303,6 +305,8 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl mTrackHistEfficiency = new StepTHnD("mTrackHistEfficiency", "Tracking efficiency", 6, 5, iTrackBin, trackBins, trackAxisTitle); + mEventCount = new TH2F("mEventCount", ";step;centrality;count", fgkCFSteps + 2, -2.5, -0.5 + fgkCFSteps, iEventBin[1], eventBins[1]); + delete[] deltaEtaBins; delete[] pTBinsFine; delete[] leadingpTBins; @@ -370,8 +374,8 @@ Double_t* CorrelationContainer::getBinning(const char* configuration, const char //_____________________________________________________________________________ CorrelationContainer::CorrelationContainer(const CorrelationContainer& c) : TNamed(c), - mTrackHist(nullptr), - mEventHist(nullptr), + mPairHist(nullptr), + mTriggerHist(nullptr), mTrackHistEfficiency(nullptr), mEtaMin(0), mEtaMax(0), @@ -404,14 +408,14 @@ CorrelationContainer::~CorrelationContainer() { // Destructor - if (mTrackHist) { - delete mTrackHist; - mTrackHist = nullptr; + if (mPairHist) { + delete mPairHist; + mPairHist = nullptr; } - if (mEventHist) { - delete mEventHist; - mEventHist = nullptr; + if (mTriggerHist) { + delete mTriggerHist; + mTriggerHist = nullptr; } if (mTrackHistEfficiency) { @@ -443,11 +447,11 @@ void CorrelationContainer::Copy(TObject& c) const CorrelationContainer& target = (CorrelationContainer&)c; - if (mTrackHist) - target.mTrackHist = dynamic_cast<StepTHnBase*>(mTrackHist->Clone()); + if (mPairHist) + target.mPairHist = dynamic_cast<StepTHnBase*>(mPairHist->Clone()); - if (mEventHist) - target.mEventHist = dynamic_cast<StepTHnBase*>(mEventHist->Clone()); + if (mTriggerHist) + target.mTriggerHist = dynamic_cast<StepTHnBase*>(mTriggerHist->Clone()); if (mTrackHistEfficiency) target.mTrackHistEfficiency = dynamic_cast<StepTHnBase*>(mTrackHistEfficiency->Clone()); @@ -499,18 +503,18 @@ Long64_t CorrelationContainer::Merge(TCollection* list) if (entry == nullptr) continue; - if (entry->mTrackHist) - lists[0]->Add(entry->mTrackHist); + if (entry->mPairHist) + lists[0]->Add(entry->mPairHist); - lists[1]->Add(entry->mEventHist); + lists[1]->Add(entry->mTriggerHist); lists[2]->Add(entry->mTrackHistEfficiency); count++; } - if (mTrackHist) - mTrackHist->Merge(lists[0]); + if (mPairHist) + mPairHist->Merge(lists[0]); - mEventHist->Merge(lists[1]); + mTriggerHist->Merge(lists[1]); mTrackHistEfficiency->Merge(lists[2]); for (UInt_t i = 0; i < kMaxLists; i++) @@ -556,26 +560,26 @@ void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Flo for (Int_t i = 0; i < 4; i++) { binBegin[i] = 1; - binEnd[i] = mTrackHist->getTHn(step)->GetAxis(i)->GetNbins(); + binEnd[i] = mPairHist->getTHn(step)->GetAxis(i)->GetNbins(); } if (mEtaMax > mEtaMin) { - binBegin[0] = mTrackHist->getTHn(step)->GetAxis(0)->FindBin(mEtaMin); - binEnd[0] = mTrackHist->getTHn(step)->GetAxis(0)->FindBin(mEtaMax); + binBegin[0] = mPairHist->getTHn(step)->GetAxis(0)->FindBin(mEtaMin); + binEnd[0] = mPairHist->getTHn(step)->GetAxis(0)->FindBin(mEtaMax); } if (mPtMax > mPtMin) { - binBegin[1] = mTrackHist->getTHn(step)->GetAxis(1)->FindBin(mPtMin); - binEnd[1] = mTrackHist->getTHn(step)->GetAxis(1)->FindBin(mPtMax); + binBegin[1] = mPairHist->getTHn(step)->GetAxis(1)->FindBin(mPtMin); + binEnd[1] = mPairHist->getTHn(step)->GetAxis(1)->FindBin(mPtMax); } if (ptLeadMax > ptLeadMin) { - binBegin[2] = mTrackHist->getTHn(step)->GetAxis(2)->FindBin(ptLeadMin); - binEnd[2] = mTrackHist->getTHn(step)->GetAxis(2)->FindBin(ptLeadMax); + binBegin[2] = mPairHist->getTHn(step)->GetAxis(2)->FindBin(ptLeadMin); + binEnd[2] = mPairHist->getTHn(step)->GetAxis(2)->FindBin(ptLeadMax); } // start from multiplicity 1 - binBegin[3] = mTrackHist->getTHn(step)->GetAxis(3)->FindBin(1); + binBegin[3] = mPairHist->getTHn(step)->GetAxis(3)->FindBin(1); Int_t total = 0; Int_t count = 0; @@ -584,7 +588,7 @@ void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Flo for (Int_t i = 0; i < 4; i++) vars[i] = binBegin[i]; - THnBase* grid = mTrackHist->getTHn(step); + THnBase* grid = mPairHist->getTHn(step); while (1) { if (grid->GetBin(vars) == 0) { LOGF(warning, "Empty bin at eta=%.2f pt=%.2f pt_lead=%.2f mult=%.1f", @@ -618,7 +622,7 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F // a 2d histogram on event level (as fct of zvtx, multiplicity) // Histograms has to be deleted by the caller of the function - THnBase* sparse = mTrackHist->getTHn(step); + THnBase* sparse = mPairHist->getTHn(step); if (mGetMultCacheOn) { if (!mGetMultCache) { mGetMultCache = changeToThn(sparse); @@ -629,7 +633,7 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F // unzoom all axes resetBinLimits(sparse); - resetBinLimits(mEventHist->getTHn(step)); + resetBinLimits(mTriggerHist->getTHn(step)); setBinLimits(sparse); @@ -637,7 +641,7 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F Int_t lastBin = sparse->GetAxis(2)->FindBin(ptLeadMax); LOGF(info, "Using pT range %d --> %d", firstBin, lastBin); sparse->GetAxis(2)->SetRange(firstBin, lastBin); - mEventHist->getTHn(step)->GetAxis(0)->SetRange(firstBin, lastBin); + mTriggerHist->getTHn(step)->GetAxis(0)->SetRange(firstBin, lastBin); // cut on the second trigger particle if there is a minimum set if (mPt2Min > 0) { @@ -646,17 +650,17 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F if (mPt2Max > 0) lastBinPt2 = sparse->GetAxis(6)->FindBin(mPt2Max); - mEventHist->getTHn(step)->GetAxis(3)->SetRange(firstBinPt2, lastBinPt2); + mTriggerHist->getTHn(step)->GetAxis(3)->SetRange(firstBinPt2, lastBinPt2); } Bool_t hasVertex = kTRUE; - if (!mTrackHist->getTHn(step)->GetAxis(5)) + if (!mPairHist->getTHn(step)->GetAxis(5)) hasVertex = kFALSE; if (hasVertex) { Int_t dimensions[] = {4, 0, 5, 3}; THnBase* tmpTrackHist = sparse->ProjectionND(4, dimensions, "E"); - *eventHist = (TH2*)mEventHist->getTHn(step)->Projection(2, 1); + *eventHist = (TH2*)mTriggerHist->getTHn(step)->Projection(2, 1); // convert to THn *trackHist = changeToThn(tmpTrackHist); delete tmpTrackHist; @@ -698,7 +702,7 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F delete tmpTrackHist; - TH1* projEventHist = (TH1*)mEventHist->getTHn(step)->Projection(1); + TH1* projEventHist = (TH1*)mTriggerHist->getTHn(step)->Projection(1); *eventHist = new TH2F(Form("%s_vtx", projEventHist->GetName()), projEventHist->GetTitle(), 1, vtxAxis, projEventHist->GetNbinsX(), projEventHist->GetXaxis()->GetXbins()->GetArray()); for (Int_t binIdx = 1; binIdx <= projEventHist->GetNbinsX(); binIdx++) { (*eventHist)->SetBinContent(1, binIdx, projEventHist->GetBinContent(binIdx)); @@ -709,7 +713,7 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F } resetBinLimits(sparse); - resetBinLimits(mEventHist->getTHn(step)); + resetBinLimits(mTriggerHist->getTHn(step)); } //____________________________________________________________________ @@ -750,7 +754,7 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati // mixed-event normalization. If step6 is available, the normalization factor is read out from that one. // If step6 is not available we fallback to taking the normalization along all delta phi (WARNING requires a // flat delta phi distribution) - if (stepForMixed == -1 && step == kCFStepBiasStudy && mixed->mEventHist->getTHn(kCFStepReconstructed)->GetEntries() > 0 && !mSkipScaleMixedEvent) { + if (stepForMixed == -1 && step == kCFStepBiasStudy && mixed->mTriggerHist->getTHn(kCFStepReconstructed)->GetEntries() > 0 && !mSkipScaleMixedEvent) { LOGF(info, "Using mixed-event normalization factors from step %d", kCFStepReconstructed); mixed->getHistsZVtxMult(kCFStepReconstructed, ptLeadMin, ptLeadMax, &trackMixedAllStep6, &eventMixedAllStep6); } @@ -996,21 +1000,21 @@ TH1* CorrelationContainer::getTriggersAsFunctionOfMultiplicity(CorrelationContai { // returns the distribution of triggers as function of centrality/multiplicity - resetBinLimits(mEventHist->getTHn(step)); + resetBinLimits(mTriggerHist->getTHn(step)); - Int_t firstBin = mEventHist->getTHn(step)->GetAxis(0)->FindBin(ptLeadMin); - Int_t lastBin = mEventHist->getTHn(step)->GetAxis(0)->FindBin(ptLeadMax); + Int_t firstBin = mTriggerHist->getTHn(step)->GetAxis(0)->FindBin(ptLeadMin); + Int_t lastBin = mTriggerHist->getTHn(step)->GetAxis(0)->FindBin(ptLeadMax); LOGF(info, "Using pT range %d --> %d", firstBin, lastBin); - mEventHist->getTHn(step)->GetAxis(0)->SetRange(firstBin, lastBin); + mTriggerHist->getTHn(step)->GetAxis(0)->SetRange(firstBin, lastBin); if (mZVtxMax > mZVtxMin) { - mEventHist->getTHn(step)->GetAxis(2)->SetRangeUser(mZVtxMin, mZVtxMax); + mTriggerHist->getTHn(step)->GetAxis(2)->SetRangeUser(mZVtxMin, mZVtxMax); LOGF(info, "Restricting z-vtx: %f-%f", mZVtxMin, mZVtxMax); } - TH1* eventHist = mEventHist->getTHn(step)->Projection(1); + TH1* eventHist = mTriggerHist->getTHn(step)->Projection(1); - resetBinLimits(mEventHist->getTHn(step)); + resetBinLimits(mTriggerHist->getTHn(step)); return eventHist; } @@ -1209,7 +1213,7 @@ TH1* CorrelationContainer::getTrackEfficiency(CFStep step1, CFStep step2, Int_t // rebin if required if (source == 2) { - TAxis* axis = mEventHist->getTHn(0)->GetAxis(0); + TAxis* axis = mTriggerHist->getTHn(0)->GetAxis(0); if (axis->GetNbins() < measured->GetNbinsX()) { if (axis2 != -1) { @@ -1303,19 +1307,19 @@ TH1* CorrelationContainer::getEventEfficiency(CFStep step1, CFStep step2, Int_t // projected to axis1 and axis2 (optional if >= 0) if (ptLeadMax > ptLeadMin) { - mEventHist->getTHn(step1)->GetAxis(0)->SetRangeUser(ptLeadMin, ptLeadMax); - mEventHist->getTHn(step2)->GetAxis(0)->SetRangeUser(ptLeadMin, ptLeadMax); + mTriggerHist->getTHn(step1)->GetAxis(0)->SetRangeUser(ptLeadMin, ptLeadMax); + mTriggerHist->getTHn(step2)->GetAxis(0)->SetRangeUser(ptLeadMin, ptLeadMax); } TH1* measured = nullptr; TH1* generated = nullptr; if (axis2 >= 0) { - generated = mEventHist->getTHn(step1)->Projection(axis1, axis2); - measured = mEventHist->getTHn(step2)->Projection(axis1, axis2); + generated = mTriggerHist->getTHn(step1)->Projection(axis1, axis2); + measured = mTriggerHist->getTHn(step2)->Projection(axis1, axis2); } else { - generated = mEventHist->getTHn(step1)->Projection(axis1); - measured = mEventHist->getTHn(step2)->Projection(axis1); + generated = mTriggerHist->getTHn(step1)->Projection(axis1); + measured = mTriggerHist->getTHn(step2)->Projection(axis1); } measured->Divide(measured, generated, 1, 1, "B"); @@ -1323,8 +1327,8 @@ TH1* CorrelationContainer::getEventEfficiency(CFStep step1, CFStep step2, Int_t delete generated; if (ptLeadMax > ptLeadMin) { - mEventHist->getTHn(step1)->GetAxis(0)->SetRangeUser(0, -1); - mEventHist->getTHn(step2)->GetAxis(0)->SetRangeUser(0, -1); + mTriggerHist->getTHn(step1)->GetAxis(0)->SetRangeUser(0, -1); + mTriggerHist->getTHn(step2)->GetAxis(0)->SetRangeUser(0, -1); } return measured; @@ -1367,22 +1371,22 @@ TH1* CorrelationContainer::getBias(CFStep step1, CFStep step2, const char* axis, // 1 = only track bias is returned // 2 = only event bias is returned - StepTHnBase* tmp = mTrackHist; + StepTHnBase* tmp = mPairHist; resetBinLimits(tmp->getTHn(step1)); - resetBinLimits(mEventHist->getTHn(step1)); + resetBinLimits(mTriggerHist->getTHn(step1)); setBinLimits(tmp->getTHn(step1)); resetBinLimits(tmp->getTHn(step2)); - resetBinLimits(mEventHist->getTHn(step2)); + resetBinLimits(mTriggerHist->getTHn(step2)); setBinLimits(tmp->getTHn(step2)); - TH1D* events1 = (TH1D*)mEventHist->getTHn(step1)->Projection(0); + TH1D* events1 = (TH1D*)mTriggerHist->getTHn(step1)->Projection(0); TH3D* hist1 = (TH3D*)tmp->getTHn(step1)->Projection(0, tmp->getNVar() - 1, 2); if (weighting == 0) weightHistogram(hist1, events1); - TH1D* events2 = (TH1D*)mEventHist->getTHn(step2)->Projection(0); + TH1D* events2 = (TH1D*)mTriggerHist->getTHn(step2)->Projection(0); TH3D* hist2 = (TH3D*)tmp->getTHn(step2)->Projection(0, tmp->getNVar() - 1, 2); if (weighting == 0) weightHistogram(hist2, events2); @@ -1590,19 +1594,19 @@ void CorrelationContainer::deepCopy(CorrelationContainer* from) // copies the entries of this object's members from the object <from> to this object // fills using the fill function and thus allows that the objects have different binning - for (Int_t step = 0; step < mTrackHist->getNSteps(); step++) { + for (Int_t step = 0; step < mPairHist->getNSteps(); step++) { LOGF(info, "Copying step %d", step); - THnBase* target = mTrackHist->getTHn(step); - THnBase* source = from->mTrackHist->getTHn(step); + THnBase* target = mPairHist->getTHn(step); + THnBase* source = from->mPairHist->getTHn(step); target->Reset(); target->RebinnedAdd(source); } - for (Int_t step = 0; step < mEventHist->getNSteps(); step++) { + for (Int_t step = 0; step < mTriggerHist->getNSteps(); step++) { LOGF(info, "Ev: Copying step %d", step); - THnBase* target = mEventHist->getTHn(step); - THnBase* source = from->mEventHist->getTHn(step); + THnBase* target = mTriggerHist->getTHn(step); + THnBase* source = from->mTriggerHist->getTHn(step); target->Reset(); target->RebinnedAdd(source); @@ -1625,9 +1629,9 @@ void CorrelationContainer::symmetrizepTBins() { // copy pt,a < pt,t bins to pt,a > pt,t (inverting deltaphi and delta eta as it should be) including symmetric bins - for (Int_t step = 0; step < mTrackHist->getNSteps(); step++) { + for (Int_t step = 0; step < mPairHist->getNSteps(); step++) { LOGF(info, "Copying step %d", step); - THnBase* target = mTrackHist->getTHn(step); + THnBase* target = mPairHist->getTHn(step); if (target->GetEntries() == 0) continue; @@ -1832,11 +1836,11 @@ void CorrelationContainer::Reset() { // resets all contained histograms - for (Int_t step = 0; step < mTrackHist->getNSteps(); step++) - mTrackHist->getTHn(step)->Reset(); + for (Int_t step = 0; step < mPairHist->getNSteps(); step++) + mPairHist->getTHn(step)->Reset(); - for (Int_t step = 0; step < mEventHist->getNSteps(); step++) - mEventHist->getTHn(step)->Reset(); + for (Int_t step = 0; step < mTriggerHist->getNSteps(); step++) + mTriggerHist->getTHn(step)->Reset(); for (Int_t step = 0; step < mTrackHistEfficiency->getNSteps(); step++) mTrackHistEfficiency->getTHn(step)->Reset(); @@ -1862,3 +1866,9 @@ THnBase* CorrelationContainer::changeToThn(THnBase* sparse) return tmpTHn; } + +void CorrelationContainer::FillEvent(Float_t centrality, CFStep step) +{ + // Fill per-event information + mEventCount->Fill(step, centrality); +} diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 751cd40c64c8f..fb984848929b0 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -18,16 +18,6 @@ o2_add_dpl_workflow(trackselection PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) -o2_add_dpl_workflow(correlations - SOURCES correlations.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(correlations-mixed - SOURCES correlationsMixed.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore - COMPONENT_NAME Analysis) - o2_add_dpl_workflow(qatask SOURCES qaTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore diff --git a/Analysis/Tasks/PWGCF/CMakeLists.txt b/Analysis/Tasks/PWGCF/CMakeLists.txt index d97dc7fb6cdef..29309d8cab809 100644 --- a/Analysis/Tasks/PWGCF/CMakeLists.txt +++ b/Analysis/Tasks/PWGCF/CMakeLists.txt @@ -21,3 +21,13 @@ o2_add_dpl_workflow(dptdptcorrelations PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel O2::PWGCFCore COMPONENT_NAME Analysis) +o2_add_dpl_workflow(correlations + SOURCES correlations.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(correlations-mixed + SOURCES correlationsMixed.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/Analysis/Tasks/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx similarity index 94% rename from Analysis/Tasks/correlations.cxx rename to Analysis/Tasks/PWGCF/correlations.cxx index 4b53c581c88f7..a9e4fdfc6ab99 100644 --- a/Analysis/Tasks/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -50,7 +50,7 @@ struct CorrelationTask { // 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); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); using myTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection>>; // Output definitions @@ -116,9 +116,15 @@ struct CorrelationTask { { LOGF(info, "Tracks for collision: %d | Trigger mask: %lld | INT7: %d | V0M: %.1f", tracks.size(), collision.bc().triggerMask(), collision.sel7(), collision.centV0M()); + const auto centrality = collision.centV0M(); + + same->FillEvent(centrality, CorrelationContainer::kCFStepAll); + if (!collision.sel7()) return; + same->FillEvent(centrality, CorrelationContainer::kCFStepTriggered); + int bSign = 1; // TODO magnetic field from CCDB for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { @@ -130,11 +136,11 @@ struct CorrelationTask { double eventValues[3]; eventValues[0] = track1.pt(); - eventValues[1] = collision.centV0M(); + eventValues[1] = centrality; eventValues[2] = collision.posZ(); - same->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - //mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + same->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); for (auto track2 = track1 + 1; track2 != tracks.end(); ++track2) { @@ -154,7 +160,7 @@ struct CorrelationTask { values[0] = track1.eta() - track2.eta(); values[1] = track1.pt(); values[2] = track2.pt(); - values[3] = collision.centV0M(); + values[3] = centrality; values[4] = track1.phi() - track2.phi(); if (values[4] > 1.5 * TMath::Pi()) @@ -164,8 +170,8 @@ struct CorrelationTask { values[5] = collision.posZ(); - same->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); - //mixed->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + same->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + //mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); } } } @@ -189,8 +195,8 @@ struct CorrelationTask { eventValues[1] = 0; // collision.v0mult(); eventValues[2] = collision.posZ(); - same->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - //mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + same->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); } for (auto& [track1, track2] : combinations(tracks, tracks)) { @@ -224,8 +230,8 @@ struct CorrelationTask { values[5] = collision.posZ(); - same->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); - //mixed->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + same->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + //mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); } } diff --git a/Analysis/Tasks/correlationsMixed.cxx b/Analysis/Tasks/PWGCF/correlationsMixed.cxx similarity index 99% rename from Analysis/Tasks/correlationsMixed.cxx rename to Analysis/Tasks/PWGCF/correlationsMixed.cxx index 8d36c33d85987..b07b0051a91fb 100644 --- a/Analysis/Tasks/correlationsMixed.cxx +++ b/Analysis/Tasks/PWGCF/correlationsMixed.cxx @@ -231,7 +231,7 @@ struct CorrelationTask { eventValues[1] = collision1.centV0M(); eventValues[2] = collision1.posZ(); - mixed->getEventHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); for (auto& track2 : tracks2) { @@ -261,7 +261,7 @@ struct CorrelationTask { values[5] = collision1.posZ(); - mixed->getTrackHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); } } } diff --git a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx index 954e53b2eff09..7c762f53888fe 100644 --- a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx +++ b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx @@ -65,6 +65,22 @@ struct IterateV0Tracks { } }; +// IterateV0Tracks with join. Desired version for good readability +// using CollisionMatchedRun2Sparse = soa::Join<aod::Run2MatchedSparse, aod::Collisions>::iterator; +// struct IterateV0Tracks2 { +// void process(CollisionMatchedRun2Sparse const& m, aod::Run2V0s const&, aod::Tracks const& tracks) +// { +// LOGF(INFO, "Vertex = %f. %d tracks", m.posZ(), tracks.size()); +// LOGF(INFO, "Vertex = %f. %d tracks", m.collision().posZ(), tracks.size()); +// if (m.has_run2v0()) { +// auto v0 = m.run2v0(); +// LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); +// } else { +// LOGF(INFO, "No V0 info"); +// } +// } +// }; + // This example accesses V0 and ZDC information struct IterateV0ZDC { void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::Run2V0s const&, aod::Zdcs const&) @@ -90,6 +106,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) adaptAnalysisTask<IterateV0>("iterate-v0"), adaptAnalysisTask<IterateV0Exclusive>("iterate-v0-exclusive"), adaptAnalysisTask<IterateV0Tracks>("iterate-v0-tracks"), + // adaptAnalysisTask<IterateV0Tracks2>("iterate-v0-tracks2"), adaptAnalysisTask<IterateV0ZDC>("iterate-v0-zdc"), }; } From 4e7c9c21268f62c5ac330d94ae1405295314a656 Mon Sep 17 00:00:00 2001 From: dstocco <dstocco@users.noreply.github.com> Date: Tue, 15 Sep 2020 09:44:15 +0200 Subject: [PATCH 0614/1751] Improve performance of MID raw data decoding without the user logic (#4341) --- Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx b/Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx index 13d255cef1998..c5f2c8bf7177a 100644 --- a/Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx @@ -39,25 +39,29 @@ void GBTBareDecoder::process(gsl::span<const uint8_t> bytes, uint16_t bc, uint32 uint8_t byte = 0; size_t ilink = 0, linkMask = 0, byteOffset = 0; - for (size_t idx = 0; idx < bytes.size(); idx += 16) { - for (int ireg = 0; ireg < 2; ++ireg) { - byteOffset = idx + 5 * ireg; - for (int ib = 0; ib < 4; ++ib) { - byte = bytes[byteOffset + ib]; - ilink = ib + 4 * ireg; - linkMask = (1 << ilink); - if ((mMask & linkMask) && ((mIsFeeding & linkMask) || byte)) { - processLoc(ilink, byte); - } - } // loop on locs - byte = bytes[byteOffset + 4]; - ilink = 8 + ireg; - linkMask = (1 << ilink); + for (int ireg = 0; ireg < 2; ++ireg) { + byteOffset = 5 * ireg; + ilink = 8 + ireg; + linkMask = (1 << ilink); + for (size_t idx = byteOffset + 4; idx < bytes.size(); idx += 16) { + byte = bytes[idx]; if ((mIsFeeding & linkMask) || byte) { std::invoke(mProcessReg, this, ilink, byte); } - } // loop on half regional - } // loop on buffer index + } + for (int ib = 0; ib < 4; ++ib) { + ilink = ib + 4 * ireg; + linkMask = (1 << ilink); + if (mMask & linkMask) { + for (size_t idx = byteOffset + ib; idx < bytes.size(); idx += 16) { + byte = bytes[idx]; + if ((mIsFeeding & linkMask) || byte) { + processLoc(ilink, byte); + } + } + } + } + } } void GBTBareDecoder::processLoc(size_t ilink, uint8_t byte) From 47c0280b8bdcfeddf2895af1513217ebbb5f0c68 Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Tue, 15 Sep 2020 10:31:58 +0200 Subject: [PATCH 0615/1751] Improvements in Mergers benchmarks (#4243) * Fix randomness in FullVsDiff comparison of THnSparse * Merger benchmark - merge the same number of data regardless of collection size * use manual time in merger benchmarks pausing and resuming with the interface methods has too much overhead * Force memory allocation before benchmarks start * Comparison of merging, size and (de)serialization of different types fix csv output fix parameters for trees new settings use entries amount in standard histograms fix THnSparse segfaults with multiple repetitions better params for sparse test boost histograms a few anti-optimization tricks use binary_archive for boost serialization - it is faster cleanups --- Utilities/Mergers/CMakeLists.txt | 5 + .../Mergers/test/benchmark_FullVsDiff.cxx | 75 +- .../test/benchmark_MergingCollections.cxx | 442 +++++++---- Utilities/Mergers/test/benchmark_Types.cxx | 740 ++++++++++++++++++ 4 files changed, 1072 insertions(+), 190 deletions(-) create mode 100644 Utilities/Mergers/test/benchmark_Types.cxx diff --git a/Utilities/Mergers/CMakeLists.txt b/Utilities/Mergers/CMakeLists.txt index 071d7f8fe938f..d28670f7c72cf 100644 --- a/Utilities/Mergers/CMakeLists.txt +++ b/Utilities/Mergers/CMakeLists.txt @@ -62,6 +62,11 @@ o2_add_executable(benchmark-full-vs-diff COMPONENT_NAME mergers PUBLIC_LINK_LIBRARIES O2::Mergers benchmark::benchmark) +o2_add_executable(benchmark-types + SOURCES test/benchmark_Types.cxx + COMPONENT_NAME mergers + PUBLIC_LINK_LIBRARIES O2::Mergers benchmark::benchmark) + o2_add_test(InfrastructureBuilder SOURCES test/test_InfrastructureBuilder.cxx COMPONENT_NAME mergers diff --git a/Utilities/Mergers/test/benchmark_FullVsDiff.cxx b/Utilities/Mergers/test/benchmark_FullVsDiff.cxx index 98c24265a984c..b20ea506682d8 100644 --- a/Utilities/Mergers/test/benchmark_FullVsDiff.cxx +++ b/Utilities/Mergers/test/benchmark_FullVsDiff.cxx @@ -20,7 +20,7 @@ #include <TF3.h> #include <TRandom.h> #include <TRandomGen.h> - +#include <chrono> #include <ctime> const size_t entriesInDiff = 50; @@ -45,15 +45,22 @@ static void BM_MergingTH1I(benchmark::State& state) } TH1I* m = new TH1I("merged", "merged", bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + m->SetBinContent(i, 1); + } for (auto _ : state) { - state.PauseTiming(); if (state.range(0) == FULL_OBJECTS) { m->Reset(); } - state.ResumeTiming(); + auto start = std::chrono::high_resolution_clock::now(); m->Merge(collection, "-NOCHECK"); + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } delete collection; @@ -76,15 +83,22 @@ static void BM_MergingTH2I(benchmark::State& state) } TH2I* m = new TH2I("merged", "merged", bins, 0, 1000000, bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + m->SetBinContent(i, 1); + } for (auto _ : state) { - state.PauseTiming(); if (state.range(0) == FULL_OBJECTS) { m->Reset(); } - state.ResumeTiming(); + auto start = std::chrono::high_resolution_clock::now(); m->Merge(collection, "-NOCHECK"); + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } delete collection; @@ -109,15 +123,22 @@ static void BM_MergingTH3I(benchmark::State& state) } TH3I* m = new TH3I("merged", "merged", bins, 0, 1000000, bins, 0, 1000000, bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + m->SetBinContent(i, 1); + } for (auto _ : state) { - state.PauseTiming(); if (state.range(0) == FULL_OBJECTS) { m->Reset(); } - state.ResumeTiming(); + auto start = std::chrono::high_resolution_clock::now(); m->Merge(collection, "-NOCHECK"); + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } delete collection; @@ -142,7 +163,6 @@ static void BM_MergingTHnSparse(benchmark::State& state) auto* m = new THnSparseI("merged", "merged", dim, binsDims, mins, maxs); for (auto _ : state) { - state.PauseTiming(); TCollection* collection = new TObjArray(); collection->SetOwner(true); for (size_t i = 0; i < collectionSize; i++) { @@ -150,7 +170,7 @@ static void BM_MergingTHnSparse(benchmark::State& state) auto* h = new THnSparseI(("test" + std::to_string(i)).c_str(), "test", dim, binsDims, mins, maxs); for (size_t entry = 0; entry < entries; entry++) { gen.RndmArray(dim, randomArray); - for (double r : randomArray) { + for (double& r : randomArray) { r *= max; } h->Fill(randomArray); @@ -162,10 +182,12 @@ static void BM_MergingTHnSparse(benchmark::State& state) m->Reset(); } - state.ResumeTiming(); + auto start = std::chrono::high_resolution_clock::now(); m->Merge(collection); + auto end = std::chrono::high_resolution_clock::now(); - state.PauseTiming(); + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); delete collection; } @@ -198,7 +220,6 @@ static void BM_MergingTTree(benchmark::State& state) TTree* merged = createTree("merged"); for (auto _ : state) { - state.PauseTiming(); TCollection* collection = new TObjArray(); collection->SetOwner(true); for (size_t i = 0; i < collectionSize; i++) { @@ -216,25 +237,25 @@ static void BM_MergingTTree(benchmark::State& state) merged->Reset(); } - state.ResumeTiming(); - merged->Merge(collection); + auto start = std::chrono::high_resolution_clock::now(); + merged->Merge(collection, "-NOCHECK"); + auto end = std::chrono::high_resolution_clock::now(); - state.PauseTiming(); - - delete collection; + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } delete merged; } -BENCHMARK(BM_MergingTH1I)->Arg(DIFF_OBJECTS); -BENCHMARK(BM_MergingTH1I)->Arg(FULL_OBJECTS); -BENCHMARK(BM_MergingTH2I)->Arg(DIFF_OBJECTS); -BENCHMARK(BM_MergingTH2I)->Arg(FULL_OBJECTS); -BENCHMARK(BM_MergingTH3I)->Arg(DIFF_OBJECTS); -BENCHMARK(BM_MergingTH3I)->Arg(FULL_OBJECTS); -BENCHMARK(BM_MergingTHnSparse)->Arg(DIFF_OBJECTS); -BENCHMARK(BM_MergingTHnSparse)->Arg(FULL_OBJECTS); -BENCHMARK(BM_MergingTTree)->Arg(DIFF_OBJECTS); -BENCHMARK(BM_MergingTTree)->Arg(FULL_OBJECTS); +BENCHMARK(BM_MergingTH1I)->Arg(DIFF_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTH1I)->Arg(FULL_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTH2I)->Arg(DIFF_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTH2I)->Arg(FULL_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTH3I)->Arg(DIFF_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTH3I)->Arg(FULL_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTHnSparse)->Arg(DIFF_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTHnSparse)->Arg(FULL_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTTree)->Arg(DIFF_OBJECTS)->UseManualTime(); +BENCHMARK(BM_MergingTTree)->Arg(FULL_OBJECTS)->UseManualTime(); BENCHMARK_MAIN(); \ No newline at end of file diff --git a/Utilities/Mergers/test/benchmark_MergingCollections.cxx b/Utilities/Mergers/test/benchmark_MergingCollections.cxx index 0a5c4585e8fbe..701c4d4d38175 100644 --- a/Utilities/Mergers/test/benchmark_MergingCollections.cxx +++ b/Utilities/Mergers/test/benchmark_MergingCollections.cxx @@ -22,91 +22,143 @@ #include <TRandomGen.h> #include <boost/histogram.hpp> - +#include <chrono> namespace bh = boost::histogram; #include <ctime> +#define MAX_SIZE_COLLECTION (1 << 10) +#define BENCHMARK_RANGE_COLLECTIONS Arg(1)->Arg(1 << 2)->Arg(1 << 4)->Arg(1 << 6)->Arg(1 << 8)->Arg(1 << 10) + static void BM_mergingCollectionsTH1I(benchmark::State& state) { - size_t collectionSize = state.range(0); - size_t bins = 62500; // makes 250kB - - TCollection* collection = new TObjArray(); - collection->SetOwner(true); - TF1* uni = new TF1("uni", "1", 0, 1000000); - for (size_t i = 0; i < collectionSize; i++) { - TH1I* h = new TH1I(("test" + std::to_string(i)).c_str(), "test", bins, 0, 1000000); - h->FillRandom("uni", 50000); - collection->Add(h); - } - - TH1I* m = new TH1I("merged", "merged", bins, 0, 1000000); + const size_t collectionSize = state.range(0); + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; + const size_t bins = 62500; // makes 250kB for (auto _ : state) { - m->Merge(collection, "-NOCHECK"); - } + std::vector<std::unique_ptr<TCollection>> collections; + for (size_t ci = 0; ci < numberOfCollections; ci++) { + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + TF1* uni = new TF1("uni", "1", 0, 1000000); + for (size_t i = 0; i < collectionSize; i++) { + TH1I* h = new TH1I(("test" + std::to_string(ci) + "-" + std::to_string(i)).c_str(), "test", bins, 0, 1000000); + h->FillRandom("uni", 50000); + collection->Add(h); + } + collections.push_back(std::move(collection)); + delete uni; + } + auto m = std::make_unique<TH1I>("merged", "merged", bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + m->SetBinContent(i, 1); + } + auto start = std::chrono::high_resolution_clock::now(); + for (const auto& collection : collections) { + m->Merge(collection.get(), "-NOCHECK"); + } + auto end = std::chrono::high_resolution_clock::now(); - delete collection; - delete m; - delete uni; + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); + } } static void BM_mergingCollectionsTH2I(benchmark::State& state) { + const size_t collectionSize = state.range(0); + // We should always merge the same amount of objects (histograms) in one benchmark cycle. + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; + const size_t bins = 250; // 250 bins * 250 bins * 4B makes 250kB - size_t collectionSize = state.range(0); - size_t bins = 250; // 250 bins * 250 bins * 4B makes 250kB - - TCollection* collection = new TObjArray(); - collection->SetOwner(true); TF2* uni = new TF2("uni", "1", 0, 1000000, 0, 1000000); - for (size_t i = 0; i < collectionSize; i++) { - TH2I* h = new TH2I(("test" + std::to_string(i)).c_str(), "test", bins, 0, 1000000, bins, 0, 1000000); - h->FillRandom("uni", 50000); - collection->Add(h); - } - - TH2I* m = new TH2I("merged", "merged", bins, 0, 1000000, bins, 0, 1000000); for (auto _ : state) { - m->Merge(collection, "-NOCHECK"); - } - delete collection; - delete m; + std::vector<std::unique_ptr<TCollection>> collections; + + for (size_t ci = 0; ci < numberOfCollections; ci++) { + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + for (size_t i = 0; i < collectionSize; i++) { + TH2I* h = new TH2I(("test" + std::to_string(ci) + "-" + std::to_string(i)).c_str(), "test", + bins, 0, 1000000, + bins, 0, 1000000); + h->FillRandom("uni", 50000); + collection->Add(h); + } + collections.push_back(std::move(collection)); + } + auto m = std::make_unique<TH2I>("merged", "merged", bins, 0, 1000000, bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + m->SetBinContent(i, 1); + } + + auto start = std::chrono::high_resolution_clock::now(); + for (const auto& collection : collections) { + m->Merge(collection.get(), "-NOCHECK"); + } + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); + } + delete uni; } static void BM_mergingCollectionsTH3I(benchmark::State& state) { - size_t collectionSize = state.range(0); - size_t bins = 40; // 40 bins * 40 bins * 40 bins * 4B makes 256kB + const size_t collectionSize = state.range(0); + // We should always merge the same amount of objects (histograms) in one benchmark cycle. + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; + const size_t bins = 40; // 40 bins * 40 bins * 40 bins * 4B makes 256kB - TCollection* collection = new TObjArray(); - collection->SetOwner(true); TF3* uni = new TF3("uni", "1", 0, 1000000, 0, 1000000, 0, 1000000); - for (size_t i = 0; i < collectionSize; i++) { - TH3I* h = new TH3I(("test" + std::to_string(i)).c_str(), "test", - bins, 0, 1000000, - bins, 0, 1000000, - bins, 0, 1000000); - h->FillRandom("uni", 50000); - collection->Add(h); - } - - TH3I* m = new TH3I("merged", "merged", bins, 0, 1000000, bins, 0, 1000000, bins, 0, 1000000); for (auto _ : state) { - m->Merge(collection, "-NOCHECK"); + + std::vector<std::unique_ptr<TCollection>> collections; + + for (size_t ci = 0; ci < numberOfCollections; ci++) { + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + for (size_t i = 0; i < collectionSize; i++) { + TH3I* h = new TH3I(("test" + std::to_string(ci) + "-" + std::to_string(i)).c_str(), "test", + bins, 0, 1000000, + bins, 0, 1000000, + bins, 0, 1000000); + h->FillRandom("uni", 50000); + collection->Add(h); + } + collections.push_back(std::move(collection)); + } + auto m = std::make_unique<TH3I>("merged", "merged", bins, 0, 1000000, bins, 0, 1000000, bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + m->SetBinContent(i, 1); + } + + auto start = std::chrono::high_resolution_clock::now(); + for (const auto& collection : collections) { + m->Merge(collection.get(), "-NOCHECK"); + } + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } - delete collection; - delete m; + delete uni; } static void BM_mergingCollectionsTHNSparse(benchmark::State& state) { - size_t collectionSize = state.range(0); + const size_t collectionSize = state.range(0); + // We should always merge the same amount of objects (histograms) in one benchmark cycle. + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; const Double_t min = 0.0; const Double_t max = 1000000.0; @@ -122,36 +174,42 @@ static void BM_mergingCollectionsTHNSparse(benchmark::State& state) for (auto _ : state) { - state.PauseTiming(); - TCollection* collection = new TObjArray(); - collection->SetOwner(true); - for (size_t i = 0; i < collectionSize; i++) { - - auto* h = new THnSparseI(("test" + std::to_string(i)).c_str(), "test", dim, binsDims, mins, maxs); - for (size_t entry = 0; entry < 50000; entry++) { - gen.RndmArray(dim, randomArray); - for (double& r : randomArray) { - r *= max; + std::vector<std::unique_ptr<TCollection>> collections; + + for (size_t ci = 0; ci < numberOfCollections; ci++) { + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + for (size_t i = 0; i < collectionSize; i++) { + auto* h = new THnSparseI(("test" + std::to_string(ci) + "-" + std::to_string(i)).c_str(), "test", dim, binsDims, mins, maxs); + for (size_t entry = 0; entry < 50000; entry++) { + gen.RndmArray(dim, randomArray); + for (double& r : randomArray) { + r *= max; + } + h->Fill(randomArray); } - h->Fill(randomArray); + collection->Add(h); } - collection->Add(h); + collections.push_back(std::move(collection)); } - auto* m = new THnSparseI("merged", "merged", dim, binsDims, mins, maxs); + auto m = std::make_unique<THnSparseI>("merged", "merged", dim, binsDims, mins, maxs); - state.ResumeTiming(); - m->Merge(collection); - - state.PauseTiming(); + auto start = std::chrono::high_resolution_clock::now(); + for (const auto& collection : collections) { + m->Merge(collection.get()); + } + auto end = std::chrono::high_resolution_clock::now(); - delete collection; - delete m; + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } } static void BM_mergingCollectionsTTree(benchmark::State& state) { - size_t collectionSize = state.range(0); + const size_t collectionSize = state.range(0); + // We should always merge the same amount of objects (histograms) in one benchmark cycle. + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; struct format1 { Int_t a; @@ -174,37 +232,47 @@ static void BM_mergingCollectionsTTree(benchmark::State& state) Double_t randomArray[5]; for (auto _ : state) { - state.PauseTiming(); - TCollection* collection = new TObjArray(); - collection->SetOwner(true); - for (size_t i = 0; i < collectionSize; i++) { - TTree* t = createTree(std::to_string(i)); - for (size_t entry = 0; entry < 6250; entry++) { - gen.RndmArray(5, randomArray); - branch1 = {static_cast<Int_t>(randomArray[0]), static_cast<Long64_t>(randomArray[1]), static_cast<Float_t>(randomArray[2]), randomArray[3]}; - branch2 = randomArray[4]; - t->Fill(); + std::vector<std::unique_ptr<TCollection>> collections; + + for (size_t ci = 0; ci < numberOfCollections; ci++) { + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + for (size_t i = 0; i < collectionSize; i++) { + TTree* t = createTree(std::to_string(ci) + "-" + std::to_string(i)); + for (size_t entry = 0; entry < 6250; entry++) { + gen.RndmArray(5, randomArray); + branch1 = {static_cast<Int_t>(randomArray[0]), static_cast<Long64_t>(randomArray[1]), static_cast<Float_t>(randomArray[2]), randomArray[3]}; + branch2 = randomArray[4]; + t->Fill(); + } + collection->Add(t); } - collection->Add(t); + collections.emplace_back(std::move(collection)); } TTree* merged = createTree("merged"); - state.ResumeTiming(); - merged->Merge(collection); + auto start = std::chrono::high_resolution_clock::now(); + for (const auto& collection : collections) { + merged->Merge(collection.get()); + } + auto end = std::chrono::high_resolution_clock::now(); - state.PauseTiming(); + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); - delete collection; delete merged; } } static void BM_mergingPODCollections(benchmark::State& state) { - size_t collectionSize = state.range(0); - size_t bins = 62500; // makes 250kB + const size_t collectionSize = state.range(0); + // We should always merge the same amount of objects (histograms) in one benchmark cycle. + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; + const size_t bins = 62500; // makes 250kB - std::vector<std::vector<float>*> collection; + using PODHistoType = std::vector<float>; + using PODHistoTypePtr = std::unique_ptr<PODHistoType>; TF1* uni = new TF1("uni", "1", 0, 1000000); const size_t randoms = 50000; @@ -212,37 +280,48 @@ static void BM_mergingPODCollections(benchmark::State& state) gen.SetSeed(std::random_device()()); Double_t randomArray[randoms]; - for (size_t i = 0; i < collectionSize; i++) { - auto* v = new std::vector<float>(bins, 0); - gen.RndmArray(randoms, randomArray); - for (double r : randomArray) { - size_t idx = r * bins; - if (idx != bins) { - (*v)[idx] += 1; + for (auto _ : state) { + std::vector<std::unique_ptr<std::vector<PODHistoTypePtr>>> collections; + + for (size_t ci = 0; ci < numberOfCollections; ci++) { + auto collection = std::make_unique<std::vector<PODHistoTypePtr>>(); + for (size_t i = 0; i < collectionSize; i++) { + auto h = PODHistoTypePtr(new PODHistoType(bins, 0)); + gen.RndmArray(randoms, randomArray); + for (double r : randomArray) { + size_t idx = r * bins; + if (idx != bins) { + (*h)[idx] += 1; + } + } + collection->emplace_back(std::move(h)); } + collections.emplace_back(std::move(collection)); } - collection.push_back(v); - } - - auto* m = new std::vector<float>(bins, 0); - - auto merge = [&](size_t i) { - auto* v = collection[i]; - for (size_t b = 0; b < bins; b++) { - (*m)[b] += (*v)[b]; + auto m = PODHistoTypePtr(new PODHistoType(bins, 0)); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + (*m)[i] = 1; } - }; - for (auto _ : state) { - for (size_t i = 0; i < collectionSize; i++) { - merge(i); + auto merge = [&](const std::vector<PODHistoTypePtr>& collection, size_t i) { + auto h = collection[i].get(); + for (size_t b = 0; b < bins; b++) { + (*m)[b] += (*h)[b]; + } + }; + + auto start = std::chrono::high_resolution_clock::now(); + for (const auto& collection : collections) { + for (size_t i = 0; i < collectionSize; i++) { + merge(*collection, i); + } } - } + auto end = std::chrono::high_resolution_clock::now(); - for (size_t i = 0; i < collectionSize; i++) { - delete collection[i]; + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } - delete m; delete uni; } @@ -251,11 +330,15 @@ static void BM_mergingBoostRegular1DCollections(benchmark::State& state) const double min = 0.0; const double max = 1000000.0; const size_t collectionSize = state.range(0); + // We should always merge the same amount of objects (histograms) in one benchmark cycle. + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; const size_t bins = 62500; // makes 250kB auto merged = bh::make_histogram(bh::axis::regular<>(bins, min, max, "x")); + merged += merged; // avoid memory overcommitment by doing something with data. + using HistoType = decltype(merged); + using CollectionHistoType = std::vector<HistoType>; - std::vector<decltype(merged)> collection; TF1* uni = new TF1("uni", "1", 0, 1000000); const size_t randoms = 50000; @@ -263,26 +346,40 @@ static void BM_mergingBoostRegular1DCollections(benchmark::State& state) gen.SetSeed(std::random_device()()); Double_t randomArray[randoms]; - for (size_t i = 0; i < collectionSize; i++) { - collection.emplace_back(std::move(bh::make_histogram(bh::axis::regular<>(bins, min, max, "x")))); + for (auto _ : state) { - auto& h = collection.back(); - static_assert(std::is_reference<decltype(h)>::value); + std::vector<CollectionHistoType> collections; - gen.RndmArray(randoms, randomArray); - for (double r : randomArray) { - h(r * max); + for (size_t ci = 0; ci < numberOfCollections; ci++) { + CollectionHistoType collection; + for (size_t i = 0; i < collectionSize; i++) { + collection.emplace_back(std::move(bh::make_histogram(bh::axis::regular<>(bins, min, max, "x")))); + + auto& h = collection.back(); + static_assert(std::is_reference<decltype(h)>::value); + + gen.RndmArray(randoms, randomArray); + for (double r : randomArray) { + h(r * max); + } + } + collections.emplace_back(std::move(collection)); } - } - auto merge = [&](size_t i) { - merged += collection[i]; - }; + auto merge = [&](const CollectionHistoType& collection) { + for (size_t i = 0; i < collectionSize; i++) { + merged += collection[i]; + } + }; - for (auto _ : state) { - for (size_t i = 0; i < collectionSize; i++) { - merge(i); + auto start = std::chrono::high_resolution_clock::now(); + for (size_t ci = 0; ci < numberOfCollections; ci++) { + merge(collections[ci]); } + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } delete uni; @@ -293,11 +390,15 @@ static void BM_mergingBoostRegular2DCollections(benchmark::State& state) const double min = 0.0; const double max = 1000000.0; const size_t collectionSize = state.range(0); + // We should always merge the same amount of objects (histograms) in one benchmark cycle. + const size_t numberOfCollections = MAX_SIZE_COLLECTION / collectionSize; const size_t bins = 250; // 250 bins * 250 bins * 4B makes 250kB auto merged = bh::make_histogram(bh::axis::regular<>(bins, min, max, "x"), bh::axis::regular<>(bins, min, max, "y")); + merged += merged; // avoid memory overcommitment by doing something with data. + using HistoType = decltype(merged); + using CollectionHistoType = std::vector<HistoType>; - std::vector<decltype(merged)> collection; TF1* uni = new TF1("uni", "1", 0, 1000000); const size_t randoms = 50000; @@ -306,52 +407,67 @@ static void BM_mergingBoostRegular2DCollections(benchmark::State& state) Double_t randomArrayX[randoms]; Double_t randomArrayY[randoms]; - for (size_t i = 0; i < collectionSize; i++) { - collection.emplace_back(std::move(bh::make_histogram(bh::axis::regular<>(bins, min, max, "x"), bh::axis::regular<>(bins, min, max, "y")))); + for (auto _ : state) { - auto& h = collection.back(); - static_assert(std::is_reference<decltype(h)>::value); + state.PauseTiming(); + std::vector<CollectionHistoType> collections; - gen.RndmArray(randoms, randomArrayX); - gen.RndmArray(randoms, randomArrayY); - for (size_t r = 0; r < randoms; r++) { - h(randomArrayX[r] * max, randomArrayY[r] * max); + for (size_t ci = 0; ci < numberOfCollections; ci++) { + CollectionHistoType collection; + for (size_t i = 0; i < collectionSize; i++) { + collection.emplace_back(std::move(bh::make_histogram(bh::axis::regular<>(bins, min, max, "x"), bh::axis::regular<>(bins, min, max, "y")))); + + auto& h = collection.back(); + static_assert(std::is_reference<decltype(h)>::value); + + gen.RndmArray(randoms, randomArrayX); + gen.RndmArray(randoms, randomArrayY); + for (size_t r = 0; r < randoms; r++) { + h(randomArrayX[r] * max, randomArrayY[r] * max); + } + } + collections.emplace_back(std::move(collection)); } - } - auto merge = [&](size_t i) { - merged += collection[i]; - }; + auto merge = [&](const CollectionHistoType& collection) { + for (size_t i = 0; i < collectionSize; i++) { + merged += collection[i]; + } + }; - for (auto _ : state) { - for (size_t i = 0; i < collectionSize; i++) { - merge(i); + auto start = std::chrono::high_resolution_clock::now(); + for (size_t ci = 0; ci < numberOfCollections; ci++) { + merge(collections[ci]); } + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + state.SetIterationTime(elapsed_seconds.count()); } delete uni; } // one by one comparison -BENCHMARK(BM_mergingCollectionsTH1I)->Arg(1); -BENCHMARK(BM_mergingCollectionsTH2I)->Arg(1); -BENCHMARK(BM_mergingCollectionsTH3I)->Arg(1); -BENCHMARK(BM_mergingCollectionsTHNSparse)->Arg(1); -BENCHMARK(BM_mergingPODCollections)->Arg(1); -BENCHMARK(BM_mergingBoostRegular1DCollections)->Arg(1); -BENCHMARK(BM_mergingBoostRegular2DCollections)->Arg(1); -BENCHMARK(BM_mergingCollectionsTTree)->Arg(1); +BENCHMARK(BM_mergingCollectionsTH1I)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTH1I)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTH2I)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTH3I)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTHNSparse)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingPODCollections)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingBoostRegular1DCollections)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingBoostRegular2DCollections)->Arg(1)->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTTree)->Arg(1)->UseManualTime(); // collections -#define BENCHMARK_RANGE_COLLECTIONS Arg(1)->Arg(1 << 2)->Arg(1 << 4)->Arg(1 << 6)->Arg(1 << 8)->Arg(1 << 10) -BENCHMARK(BM_mergingCollectionsTH1I)->BENCHMARK_RANGE_COLLECTIONS; -BENCHMARK(BM_mergingCollectionsTH2I)->BENCHMARK_RANGE_COLLECTIONS; -BENCHMARK(BM_mergingCollectionsTH3I)->BENCHMARK_RANGE_COLLECTIONS; -BENCHMARK(BM_mergingCollectionsTHNSparse)->BENCHMARK_RANGE_COLLECTIONS; -BENCHMARK(BM_mergingPODCollections)->BENCHMARK_RANGE_COLLECTIONS; -BENCHMARK(BM_mergingBoostRegular1DCollections)->BENCHMARK_RANGE_COLLECTIONS; -BENCHMARK(BM_mergingBoostRegular2DCollections)->BENCHMARK_RANGE_COLLECTIONS; -BENCHMARK(BM_mergingCollectionsTTree)->BENCHMARK_RANGE_COLLECTIONS; +BENCHMARK(BM_mergingCollectionsTH1I)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTH2I)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTH3I)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTHNSparse)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); +BENCHMARK(BM_mergingPODCollections)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); +BENCHMARK(BM_mergingBoostRegular1DCollections)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); +BENCHMARK(BM_mergingBoostRegular2DCollections)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); +BENCHMARK(BM_mergingCollectionsTTree)->BENCHMARK_RANGE_COLLECTIONS->UseManualTime(); BENCHMARK_MAIN(); diff --git a/Utilities/Mergers/test/benchmark_Types.cxx b/Utilities/Mergers/test/benchmark_Types.cxx new file mode 100644 index 0000000000000..e1ec7fba59af1 --- /dev/null +++ b/Utilities/Mergers/test/benchmark_Types.cxx @@ -0,0 +1,740 @@ +// 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 <TObjArray.h> +#include <TH1.h> +#include <TH2.h> +#include <TH3.h> +#include <TTree.h> +#include <THnSparse.h> +#include <TF1.h> +#include <TF2.h> +#include <TF3.h> +#include <TRandom.h> +#include <TRandomGen.h> + +#include <chrono> +#include <ctime> +#include <TMessage.h> + +#include "Framework/TMessageSerializer.h" + +#include <type_traits> + +#include <iostream> +#include <fstream> + +#include <boost/archive/binary_iarchive.hpp> +#include <boost/archive/binary_oarchive.hpp> +#include <boost/histogram.hpp> +#include <boost/histogram/serialization.hpp> +#include <sstream> + +namespace bh = boost::histogram; + +enum class Measurement { + Size, + SizeAfterSerialisation, + Deserialisation, + Merging, + Serialisation +}; + +struct Results { + size_t sizeBytes = 0; + size_t sizeSerialisedBytes = 0; + double deserialisationSeconds = 0; + double mergingSeconds = 0; + double serialisationSeconds = 0; +}; + +struct Parameters { + constexpr static Parameters forHistograms(size_t objectSize, size_t entries) + { + return {objectSize, 0, 0, entries}; + } + constexpr static Parameters forSparse(size_t bins, size_t dimensions, size_t entries) + { + return {0, bins, dimensions, entries}; + } + constexpr static Parameters forTrees(size_t branches, size_t branchSize, size_t entries) + { + return {0, 0, 0, entries, branches, branchSize}; + } + size_t objectSize = 0; + size_t bins = 0; + size_t dimensions = 0; + size_t entries = 0; + size_t branches = 0; + size_t branchSize = 0; +}; + +auto measure = [](Measurement m, auto* o, auto* i) -> double { + switch (m) { + case Measurement::Size: { + const double scale = 1.0; //000000000.0; + if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) { + if (o->InheritsFrom(TH1::Class())) { + // this includes TH1, TH2, TH3 + // i don't see an easy way to find out the size of a cell, i assume that they are Int + return reinterpret_cast<TH1*>(o)->GetNcells() * sizeof(Int_t) / scale; + } else if (o->InheritsFrom(THnSparse::Class())) { + auto* sparse = reinterpret_cast<THnSparse*>(o); + // this is has to be multiplied with bin (entry) size, but we cannot get it from th einterface. + return sparse->GetNChunks() * sparse->GetChunkSize() / scale; + } else if (o->InheritsFrom(THnBase::Class())) { + // this includes THn and THnSparse + return reinterpret_cast<THnBase*>(o)->GetNbins() * sizeof(Int_t) / scale; + } else if (o->InheritsFrom(TTree::Class())) { + size_t totalSize = 0; + auto tree = reinterpret_cast<TTree*>(o); + auto branchList = tree->GetListOfBranches(); + for (const auto* branch : *branchList) { + totalSize += dynamic_cast<const TBranch*>(branch)->GetTotalSize(); + } + return totalSize / scale; + } else { + throw std::runtime_error("Object with type '" + std::string(o->ClassName()) + "' is not one of the mergeable types."); + } + } else { + // boost + return o->size() * sizeof(int); + } + } + case Measurement::Merging: { + auto end = std::chrono::high_resolution_clock::now(); + auto start = std::chrono::high_resolution_clock::now(); + if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) { + if (o->InheritsFrom(TH1::Class())) { + // this includes TH1, TH2, TH3 + start = std::chrono::high_resolution_clock::now(); + reinterpret_cast<TH1*>(o)->Merge(i, "-NOCHECK"); + } else if (o->InheritsFrom(THnBase::Class())) { + // this includes THn and THnSparse + start = std::chrono::high_resolution_clock::now(); + reinterpret_cast<THnBase*>(o)->Merge(i); + } else if (o->InheritsFrom(TTree::Class())) { + start = std::chrono::high_resolution_clock::now(); + reinterpret_cast<TTree*>(o)->Merge(i); + } else { + throw std::runtime_error("Object with type '" + std::string(o->ClassName()) + "' is not one of the mergeable types."); + } + end = std::chrono::high_resolution_clock::now(); + } else { + // boost + *o += *i; + end = std::chrono::high_resolution_clock::now(); + (void)*o; + } + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + return elapsed_seconds.count(); + } + case Measurement::Serialisation: { + auto end = std::chrono::high_resolution_clock::now(); + auto start = std::chrono::high_resolution_clock::now(); + if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) { + TMessage* tm = new TMessage(kMESS_OBJECT); + tm->WriteObject(o); + end = std::chrono::high_resolution_clock::now(); + (void)*tm; + delete tm; + } else { + // boost + std::ostringstream os; + std::string buf; + boost::archive::binary_oarchive oa(os); + oa << *o; + end = std::chrono::high_resolution_clock::now(); + (void)os; // hopefully this will prevent from optimising this code out. + } + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + return elapsed_seconds.count(); + } + case Measurement::Deserialisation: { + auto start = std::chrono::high_resolution_clock::now(); + auto end = std::chrono::high_resolution_clock::now(); + if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) { + TMessage* tm = new TMessage(kMESS_OBJECT); + tm->WriteObject(o); + start = std::chrono::high_resolution_clock::now(); + + o2::framework::FairTMessage ftm(const_cast<char*>(tm->Buffer()), tm->BufferSize()); + auto* storedClass = ftm.GetClass(); + if (storedClass == nullptr) { + throw std::runtime_error("Unknown stored class"); + } + auto* tObjectClass = TClass::GetClass(typeid(TObject)); + + if (!storedClass->InheritsFrom(tObjectClass)) { + throw std::runtime_error("Class '" + std::string(storedClass->GetName()) + "'does not inherit from TObject"); + } + + auto* object = ftm.ReadObjectAny(storedClass); + if (object == nullptr) { + throw std::runtime_error("Failed to read object with name '" + std::string(storedClass->GetName()) + "' from message using ROOT serialization."); + } + + auto tobject = static_cast<TObject*>(object); + end = std::chrono::high_resolution_clock::now(); + (void)*tobject; + delete tm; + delete tobject; + } else { + std::ostringstream os; + std::string buf; + boost::archive::binary_oarchive oa(os); + oa << *o; + buf = os.str(); + + start = std::chrono::high_resolution_clock::now(); + auto deserialisedHistogram = typename std::remove_pointer<decltype(o)>::type(); + std::istringstream is(buf); + boost::archive::binary_iarchive ia(is); + ia >> deserialisedHistogram; + end = std::chrono::high_resolution_clock::now(); + assert(deserialisedHistogram == *o); + } + auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); + return elapsed_seconds.count(); + } + case Measurement::SizeAfterSerialisation: { + const double scale = 1.0; //1000000000.0; + if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) { + TMessage* tm = new TMessage(kMESS_OBJECT); + tm->WriteObject(o); + auto serialisedSize = tm->BufferSize(); + delete tm; + return serialisedSize / scale; + } else { + std::ostringstream os; + std::string buf; + boost::archive::binary_oarchive oa(os); + oa << *i; + buf = os.str(); + return buf.size() / scale; + } + } + } + throw; +}; + +static std::vector<Results> BM_TH1I(size_t repetitions, const Parameters p) +{ + const size_t objSize = p.objectSize; + const size_t entries = p.entries; + const size_t bins = objSize / sizeof(Int_t); + + auto m = std::make_unique<TH1I>("merged", "merged", bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins; i++) { + m->SetBinContent(i, 1); + } + + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + auto uni = std::make_unique<TF1>("uni", "1", 0, 1000000); + TH1I* h = new TH1I("test", "test", bins, 0, 1000000); + collection->Add(h); + + std::vector<Results> allResults; + for (size_t r = 0; r < repetitions; r++) { + h->Reset(); + h->FillRandom("uni", entries); + Results iterationResults; + iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get()); + iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get()); + iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get()); + iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get()); + iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get()); + allResults.push_back(iterationResults); + } + return allResults; +} + +static std::vector<Results> BM_TH2I(size_t repetitions, const Parameters p) +{ + const size_t objSize = p.objectSize; + const size_t entries = p.entries; + const size_t bins = std::sqrt(objSize / sizeof(Int_t)); + + auto m = std::make_unique<TH2I>("merged", "merged", bins, 0, 1000000, bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins * bins; i++) { + m->SetBinContent(i, 1); + } + + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + auto uni = std::make_unique<TF2>("uni", "1", 0, 1000000, 0, 1000000); + auto* h = new TH2I("test", "test", bins, 0, 1000000, bins, 0, 1000000); + collection->Add(h); + + std::vector<Results> allResults; + for (size_t r = 0; r < repetitions; r++) { + h->Reset(); + h->FillRandom("uni", entries); + Results iterationResults; + iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get()); + iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get()); + iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get()); + iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get()); + iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get()); + allResults.push_back(iterationResults); + } + return allResults; +} + +static std::vector<Results> BM_TH3I(size_t repetitions, const Parameters p) +{ + const size_t objSize = p.objectSize; + const size_t entries = p.entries; + const size_t bins = std::pow(objSize / sizeof(Int_t), 1 / 3.0); + + auto m = std::make_unique<TH3I>("merged", "merged", bins, 0, 1000000, bins, 0, 1000000, bins, 0, 1000000); + // avoid memory overcommitment by doing something with data. + for (size_t i = 0; i < bins * bins * bins; i++) { + m->SetBinContent(i, 1); + } + + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + auto uni = std::make_unique<TF3>("uni", "1", 0, 1000000, 0, 1000000, 0, 1000000); + auto* h = new TH3I("test", "test", bins, 0, 1000000, bins, 0, 1000000, bins, 0, 1000000); + collection->Add(h); + + std::vector<Results> allResults; + for (size_t r = 0; r < repetitions; r++) { + h->Reset(); + h->FillRandom("uni", entries); + Results iterationResults; + iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get()); + iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get()); + iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get()); + iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get()); + iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get()); + allResults.push_back(iterationResults); + } + return allResults; +} + +template <typename storageT> +static std::vector<Results> BM_BoostRegular1D(size_t repetitions, const Parameters p) +{ + const size_t entries = p.entries; + const size_t bins = p.objectSize / sizeof(int32_t); + const double min = 0.0; + const double max = 1000000.0; + + auto merged = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x")); + merged += merged; // avoid memory overcommitment by doing something with data. + using HistoType = decltype(merged); + + TRandomMixMax gen; + gen.SetSeed(std::random_device()()); + Double_t randomArray[entries]; + + std::vector<Results> allResults; + for (size_t r = 0; r < repetitions; r++) { + auto h = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x")); + gen.RndmArray(entries, randomArray); + for (double rnd : randomArray) { + h(rnd * max); + } + Results iterationResults; + iterationResults.sizeBytes = measure(Measurement::Size, &merged, &h); + iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, &merged, &h); + iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, &merged, &h); + iterationResults.serialisationSeconds = measure(Measurement::Serialisation, &merged, &h); + iterationResults.mergingSeconds = measure(Measurement::Merging, &merged, &h); + allResults.push_back(iterationResults); + } + return allResults; +} + +template <typename storageT> +static std::vector<Results> BM_BoostRegular2D(size_t repetitions, const Parameters p) +{ + const size_t entries = p.entries; + const size_t bins = std::sqrt(p.objectSize / sizeof(int32_t)); + const double min = 0.0; + const double max = 1000000.0; + + auto merged = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x"), bh::axis::regular<>(bins, min, max, "y")); + merged += merged; // avoid memory overcommitment by doing something with data. + + TRandomMixMax gen; + gen.SetSeed(std::random_device()()); + Double_t randomArrayX[entries]; + Double_t randomArrayY[entries]; + + std::vector<Results> allResults; + for (size_t r = 0; r < repetitions; r++) { + auto h = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x"), bh::axis::regular<>(bins, min, max, "y")); + gen.RndmArray(entries, randomArrayX); + gen.RndmArray(entries, randomArrayY); + for (size_t rnd = 0; rnd < entries; rnd++) { + h(randomArrayX[rnd] * max, randomArrayY[rnd] * max); + } + + Results iterationResults; + iterationResults.sizeBytes = measure(Measurement::Size, &merged, &h); + iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, &merged, &h); + iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, &merged, &h); + iterationResults.serialisationSeconds = measure(Measurement::Serialisation, &merged, &h); + iterationResults.mergingSeconds = measure(Measurement::Merging, &merged, &h); + allResults.push_back(iterationResults); + } + return allResults; +} + +static std::vector<Results> BM_THNSparseI(size_t repetitions, const Parameters p) +{ + const size_t bins = p.bins; + const size_t dim = p.dimensions; + const size_t entries = p.entries; + + const Double_t min = 0.0; + const Double_t max = 1000000.0; + const std::vector<Int_t> binsDims(dim, bins); + const std::vector<Double_t> mins(dim, min); + const std::vector<Double_t> maxs(dim, max); + + TRandomMixMax gen; + gen.SetSeed(std::random_device()()); + Double_t randomArray[dim]; + + std::vector<Results> allResults; + for (size_t rep = 0; rep < repetitions; rep++) { + // histograms have to be created in each loop repetition, otherwise i get strange segfaults with large number of entries. + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + auto* h = new THnSparseI("test", "test", dim, binsDims.data(), mins.data(), maxs.data()); + collection->Add(h); + + auto m = std::make_unique<THnSparseI>("merged", "merged", dim, binsDims.data(), mins.data(), maxs.data()); + + for (size_t entry = 0; entry < entries; entry++) { + gen.RndmArray(dim, randomArray); + for (double& r : randomArray) { + r *= max; + } + h->Fill(randomArray); + } + + for (size_t entry = 0; entry < entries; entry++) { + gen.RndmArray(dim, randomArray); + for (double& r : randomArray) { + r *= max; + } + m->Fill(randomArray); + } + + Results iterationResults; + iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get()); + iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get()); + iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get()); + iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get()); + iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get()); + allResults.push_back(iterationResults); + } + return allResults; +} + +static std::vector<Results> BM_TTree(size_t repetitions, const Parameters p) +{ + const size_t branchSize = p.branchSize; + const size_t branches = p.branches; + const size_t entries = p.entries; + + using branch_t = std::vector<uint64_t>; + std::vector<branch_t> branchCollection; + for (size_t i = 0; i < branches; i++) { + branchCollection.emplace_back(branchSize, 0); + } + auto createTree = [&](std::string name) -> TTree* { + TTree* tree = new TTree(); + for (size_t i = 0; i < branchCollection.size(); i++) { + tree->Branch(("b" + std::to_string(i)).c_str(), + &branchCollection[i], + ("array" + std::to_string(i) + "[" + std::to_string(branchSize) + "]:l").c_str()); + } + tree->SetName(name.c_str()); + return tree; + }; + + auto fillTree = [&](TTree* t) { + TRandomMixMax gen; + gen.SetSeed(std::random_device()()); + Float_t randomArray[branchSize]; + + for (size_t entry = 0; entry < entries; entry++) { + for (auto& branch : branchCollection) { + gen.RndmArray(branchSize, randomArray); + for (size_t i = 0; i < branchSize; i++) { + branch[i] = static_cast<uint64_t>(randomArray[i]); + } + } + t->Fill(); + } + }; + + std::vector<Results> allResults; + for (size_t r = 0; r < repetitions; r++) { + std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>(); + collection->SetOwner(true); + TTree* t = createTree("input"); + fillTree(t); + collection->Add(t); + + TTree* m = createTree("merged"); + fillTree(m); + + Results iterationResults; + iterationResults.sizeBytes = measure(Measurement::Size, m, collection.get()); + iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m, collection.get()); + iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m, collection.get()); + iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m, collection.get()); + iterationResults.mergingSeconds = measure(Measurement::Merging, m, collection.get()); + allResults.push_back(iterationResults); + + delete m; + } + return allResults; +} + +void printHeaderCSV(std::ostream& out) +{ + out << "name," + "objectSize,bins,dimensions,entries,branches,branchSize," + "sizeBytes,sizeSerialisedBytes,deserialisationSeconds,mergingSeconds,serialisationSeconds" + "\n"; +} + +void printResultsCSV(std::ostream& out, std::string name, const Parameters& p, const std::vector<Results>& results) +{ + for (const auto r : results) { + out << name << "," + << p.objectSize << "," << p.bins << "," << p.dimensions << "," << p.entries << "," << p.branches << "," << p.branchSize << "," + << r.sizeBytes << "," << r.sizeSerialisedBytes << "," << r.deserialisationSeconds << "," << r.mergingSeconds << "," << r.serialisationSeconds + << '\n'; + } +} + +int main(int argc, const char* argv[]) +{ + if (argc < 2) { + throw std::runtime_error("Output file name expected"); + } + + std::ofstream file; + file.open(argv[1]); + printHeaderCSV(file); + printHeaderCSV(std::cout); + + size_t repetitions = argc < 3 ? 1 : std::atoll(argv[2]); + + { + // TH1I + std::vector<Parameters> parameters{ + Parameters::forHistograms(8 << 0, 50000), + Parameters::forHistograms(8 << 3, 50000), + Parameters::forHistograms(8 << 6, 50000), + Parameters::forHistograms(8 << 9, 50000), + Parameters::forHistograms(8 << 12, 50000), + Parameters::forHistograms(8 << 15, 50000), + Parameters::forHistograms(8 << 18, 50000), + Parameters::forHistograms(8 << 21, 50000)}; + for (const auto& p : parameters) { + auto results = BM_TH1I(repetitions, p); + printResultsCSV(file, "TH1I", p, results); + printResultsCSV(std::cout, "TH1I", p, results); + } + } + + { + // TH2I + std::vector<Parameters> parameters{ + Parameters::forHistograms(8 << 0, 50000), + Parameters::forHistograms(8 << 3, 50000), + Parameters::forHistograms(8 << 6, 50000), + Parameters::forHistograms(8 << 9, 50000), + Parameters::forHistograms(8 << 12, 50000), + Parameters::forHistograms(8 << 15, 50000), + Parameters::forHistograms(8 << 18, 50000), + Parameters::forHistograms(8 << 21, 50000)}; + for (const auto& p : parameters) { + auto results = BM_TH2I(repetitions, p); + printResultsCSV(file, "TH2I", p, results); + printResultsCSV(std::cout, "TH2I", p, results); + } + } + + { + // TH3I + std::vector<Parameters> parameters{ + Parameters::forHistograms(8 << 0, 50000), + Parameters::forHistograms(8 << 3, 50000), + Parameters::forHistograms(8 << 6, 50000), + Parameters::forHistograms(8 << 9, 50000), + Parameters::forHistograms(8 << 12, 50000), + Parameters::forHistograms(8 << 15, 50000), + Parameters::forHistograms(8 << 18, 50000), + Parameters::forHistograms(8 << 21, 50000)}; + for (const auto& p : parameters) { + auto results = BM_TH3I(repetitions, p); + printResultsCSV(file, "TH3I", p, results); + printResultsCSV(std::cout, "TH3I", p, results); + } + } + + { + // THnSparseI + std::vector<Parameters> parameters{ + Parameters::forSparse(8, 8, 512), + Parameters::forSparse(64, 8, 512), + Parameters::forSparse(512, 8, 512), + Parameters::forSparse(4096, 8, 512), + Parameters::forSparse(32768, 8, 512), + Parameters::forSparse(512, 2, 512), + Parameters::forSparse(512, 4, 512), + Parameters::forSparse(512, 8, 512), + Parameters::forSparse(512, 16, 512), + Parameters::forSparse(512, 32, 512), + Parameters::forSparse(512, 64, 512), + Parameters::forSparse(512, 8, 1), + Parameters::forSparse(512, 8, 8), + Parameters::forSparse(512, 8, 64), + Parameters::forSparse(512, 8, 512), + Parameters::forSparse(512, 8, 4096), + Parameters::forSparse(512, 8, 32768), + Parameters::forSparse(512, 8, 262144), + Parameters::forSparse(512, 8, 2097152), + // Parameters::forSparse(512, 8, 16777216), + Parameters::forSparse(32, 4, 1), + Parameters::forSparse(32, 4, 8), + Parameters::forSparse(32, 4, 64), + Parameters::forSparse(32, 4, 512), + Parameters::forSparse(32, 4, 4096), + Parameters::forSparse(32, 4, 32768), + Parameters::forSparse(32, 4, 262144), + Parameters::forSparse(32, 4, 2097152), + Parameters::forSparse(32, 4, 16777216)}; + for (const auto& p : parameters) { + auto results = BM_THNSparseI(repetitions, p); + printResultsCSV(file, "THnSparseI", p, results); + printResultsCSV(std::cout, "THnSparseI", p, results); + } + } + + { + // TTree + std::vector<Parameters> parameters{ + Parameters::forTrees(8, 8, 8), + Parameters::forTrees(8, 8, 8 << 3), + Parameters::forTrees(8, 8, 8 << 6), + Parameters::forTrees(8, 8, 8 << 9), + Parameters::forTrees(8, 8, 8 << 12), + Parameters::forTrees(8, 8, 8 << 15), + Parameters::forTrees(8, 8, 8 << 18), + Parameters::forTrees(8, 1 << 0, 8 << 12), + Parameters::forTrees(8, 1 << 2, 8 << 12), + Parameters::forTrees(8, 1 << 4, 8 << 12), + Parameters::forTrees(8, 1 << 6, 8 << 12), + Parameters::forTrees(8, 1 << 8, 8 << 12), + Parameters::forTrees(1 << 0, 8, 8 << 12), + Parameters::forTrees(1 << 2, 8, 8 << 12), + Parameters::forTrees(1 << 4, 8, 8 << 12), + Parameters::forTrees(1 << 6, 8, 8 << 12), + Parameters::forTrees(1 << 8, 8, 8 << 12)}; + for (const auto& p : parameters) { + auto results = BM_TTree(repetitions, p); + printResultsCSV(file, "TTree", p, results); + printResultsCSV(std::cout, "TTree", p, results); + } + } + + { + // boost regular 1D. We use a combination of template and macro to be able to use static storage (std::array) with different parameters. +#define BM_BOOST1DARRAY_FOR(objSize, entries) \ + { \ + constexpr auto p = Parameters::forHistograms(objSize, entries); \ + auto results = BM_BoostRegular1D<std::array<int32_t, p.objectSize / sizeof(int32_t) + 2>>(repetitions, p); \ + printResultsCSV(file, "BoostRegular1DArray", p, results); \ + printResultsCSV(std::cout, "BoostRegular1DArray", p, results); \ + } + + BM_BOOST1DARRAY_FOR(8 << 0, 50000); + BM_BOOST1DARRAY_FOR(8 << 3, 50000); + BM_BOOST1DARRAY_FOR(8 << 6, 50000); + BM_BOOST1DARRAY_FOR(8 << 9, 50000); + BM_BOOST1DARRAY_FOR(8 << 12, 50000); + BM_BOOST1DARRAY_FOR(8 << 15, 50000); + } + + { + // boost regular 1D. +#define BM_BOOST1DVECTOR_FOR(objSize, entries) \ + { \ + constexpr auto p = Parameters::forHistograms(objSize, entries); \ + auto results = BM_BoostRegular1D<std::vector<int32_t>>(repetitions, p); \ + printResultsCSV(file, "BoostRegular1DVector", p, results); \ + printResultsCSV(std::cout, "BoostRegular1DVector", p, results); \ + } + + BM_BOOST1DVECTOR_FOR(8 << 0, 50000); + BM_BOOST1DVECTOR_FOR(8 << 3, 50000); + BM_BOOST1DVECTOR_FOR(8 << 6, 50000); + BM_BOOST1DVECTOR_FOR(8 << 9, 50000); + BM_BOOST1DVECTOR_FOR(8 << 12, 50000); + BM_BOOST1DVECTOR_FOR(8 << 15, 50000); + BM_BOOST1DVECTOR_FOR(8 << 18, 50000); + BM_BOOST1DVECTOR_FOR(8 << 21, 50000); + } + + { + // boost regular 2D. We use a combination of template and macro to be able to use static storage (std::array) with different parameters. +#define BM_BOOST2DARRAY_FOR(objSize, arrSize, entries) \ + { \ + constexpr auto p = Parameters::forHistograms(objSize, entries); \ + auto results = BM_BoostRegular2D<std::array<int32_t, arrSize>>(repetitions, p); \ + printResultsCSV(file, "BoostRegular2DArray", p, results); \ + printResultsCSV(std::cout, "BoostRegular2DArray", p, results); \ + } + + BM_BOOST2DARRAY_FOR(8 << 0, 10, 50000); + BM_BOOST2DARRAY_FOR(8 << 3, 36, 50000); + BM_BOOST2DARRAY_FOR(8 << 6, 178, 50000); + BM_BOOST2DARRAY_FOR(8 << 9, 1156, 50000); + BM_BOOST2DARRAY_FOR(8 << 12, 8558, 50000); + BM_BOOST2DARRAY_FOR(8 << 15, 66564, 50000); + } + + { + // boost regular 2D. +#define BM_BOOST2DVECTOR_FOR(objSize, entries) \ + { \ + constexpr auto p = Parameters::forHistograms(objSize, entries); \ + auto results = BM_BoostRegular2D<std::vector<int32_t>>(repetitions, p); \ + printResultsCSV(file, "BoostRegular2DVector", p, results); \ + printResultsCSV(std::cout, "BoostRegular2DVector", p, results); \ + } + + BM_BOOST2DVECTOR_FOR(8 << 0, 50000); + BM_BOOST2DVECTOR_FOR(8 << 3, 50000); + BM_BOOST2DVECTOR_FOR(8 << 6, 50000); + BM_BOOST2DVECTOR_FOR(8 << 9, 50000); + BM_BOOST2DVECTOR_FOR(8 << 12, 50000); + BM_BOOST2DVECTOR_FOR(8 << 15, 50000); + BM_BOOST2DVECTOR_FOR(8 << 18, 50000); + BM_BOOST2DVECTOR_FOR(8 << 21, 50000); + } + + file.close(); + return 0; +} \ No newline at end of file From abc588482a6ea8608ab268985ae2a89a4b41b2f2 Mon Sep 17 00:00:00 2001 From: dsekihat <daiki.sekihata@cern.ch> Date: Tue, 15 Sep 2020 21:25:09 +0900 Subject: [PATCH 0616/1751] Analysis/PWGDQ: add tableMaker_pp (#4336) * add tableMaker_pp * update for tableMaker_pp.cxx * remove chanrge from DCA --- Analysis/Core/include/Analysis/VarManager.h | 13 +- Analysis/Core/src/VarManager.cxx | 4 + .../include/Analysis/ReducedInfoTables.h | 4 +- Analysis/Tasks/PWGDQ/CMakeLists.txt | 5 + Analysis/Tasks/PWGDQ/dileptonEE.cxx | 42 +---- Analysis/Tasks/PWGDQ/tableMaker.cxx | 18 +- Analysis/Tasks/PWGDQ/tableMaker_pp.cxx | 173 ++++++++++++++++++ 7 files changed, 212 insertions(+), 47 deletions(-) create mode 100644 Analysis/Tasks/PWGDQ/tableMaker_pp.cxx diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 95df64631efd3..df3ce002134c7 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -100,6 +100,8 @@ class VarManager : public TObject kTOFsignal, kTOFbeta, kTrackLength, + kTrackDCAxy, + kTrackDCAz, kTrackCYY, kTrackCZZ, kTrackCSnpSnp, @@ -284,11 +286,9 @@ void VarManager::FillTrack(T const& track, float* values) values[kITSchi2] = track.itsChi2NCl(); values[kTPCncls] = track.tpcNClsFound(); values[kTPCchi2] = track.tpcChi2NCl(); - //values[kTPCsignal] = track.tpcSignal(); - //values[kTRDsignal] = track.trdSignal(); - //values[kTOFsignal] = track.tofSignal(); - //values[kTOFbeta] = track.beta(); values[kTrackLength] = track.length(); + values[kTrackDCAxy] = track.dcaXY(); + values[kTrackDCAz] = track.dcaZ(); } if constexpr ((fillMap & TrackCov) > 0) { @@ -322,10 +322,9 @@ void VarManager::FillTrack(T const& track, float* values) values[kITSchi2] = track.itsChi2NCl(); values[kTPCncls] = track.tpcNClsFound(); values[kTPCchi2] = track.tpcChi2NCl(); - //values[kTPCsignal] = track.tpcSignal(); - //values[kTRDsignal] = track.trdSignal(); - //values[kTOFsignal] = track.tofSignal(); values[kTrackLength] = track.length(); + values[kTrackDCAxy] = track.dcaXY(); + values[kTrackDCAz] = track.dcaZ(); } if constexpr ((fillMap & ReducedTrackBarrelCov) > 0) { diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 837a6a76dce00..3dab4c1044344 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -171,6 +171,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kTOFbeta] = ""; fgVariableNames[kTrackLength] = "track length"; fgVariableUnits[kTrackLength] = "cm"; + fgVariableNames[kTrackDCAxy] = "DCA_{xy}"; + fgVariableUnits[kTrackDCAxy] = "cm"; + fgVariableNames[kTrackDCAz] = "DCA_{z}"; + fgVariableUnits[kTrackDCAz] = "cm"; fgVariableNames[kTPCnSigmaEl] = "n #sigma_{e}^{TPC}"; fgVariableUnits[kTPCnSigmaEl] = ""; fgVariableNames[kTPCnSigmaMu] = "n #sigma_{#mu}^{TPC}"; diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index a04365bd5cae1..f60c22f63a8c1 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -60,6 +60,8 @@ 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_COLUMN(DcaXY, dcaXY, float); +DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); 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 +84,7 @@ DECLARE_SOA_TABLE(ReducedTracksBarrel, "AOD", "RTBARREL", track::ITSClusterMap, track::ITSChi2NCl, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::TPCChi2NCl, - track::TRDChi2, track::TOFChi2, track::Length, + track::TRDChi2, track::TOFChi2, track::Length, reducedtrack::DcaXY, reducedtrack::DcaZ, track::TPCNClsFound<track::TPCNClsFindable, track::TPCNClsFindableMinusFound>, track::TPCNClsCrossedRows<track::TPCNClsFindable, track::TPCNClsFindableMinusCrossedRows>); diff --git a/Analysis/Tasks/PWGDQ/CMakeLists.txt b/Analysis/Tasks/PWGDQ/CMakeLists.txt index c1e200173f10f..928dbe3444c82 100644 --- a/Analysis/Tasks/PWGDQ/CMakeLists.txt +++ b/Analysis/Tasks/PWGDQ/CMakeLists.txt @@ -12,3 +12,8 @@ o2_add_dpl_workflow(dilepton-ee SOURCES dileptonEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(table-maker-pp + SOURCES tableMaker_pp.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 index 9bf806fc14b28..ef6c8082a0bb9 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -104,47 +104,14 @@ struct BarrelTrackSelection { 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::kTPCncls, 69.5, 159.5); + cut1->AddCut(VarManager::kTrackDCAxy, -1.0, +1.0); + cut1->AddCut(VarManager::kTrackDCAz, -3.0, +3.0); + 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 } @@ -316,6 +283,7 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin 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); + histMan->AddHistogram(classStr.Data(), "DCAxy_DCAz", "DCA_{xy} vs DCA_{z}", false, 100, -5.0, 5.0, VarManager::kTrackDCAxy, 100, -5.0, 5.0, VarManager::kTrackDCAz); // TH2F histogram if (classStr.Contains("Barrel")) { histMan->AddHistogram(classStr.Data(), "TPCncls", "Number of cluster in TPC", false, 160, -0.5, 159.5, VarManager::kTPCncls); // TH1F histogram diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index 83fd1c5c713cc..c0be454ecb5cf 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -85,6 +85,12 @@ struct TableMaker { eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); uint64_t trackFilteringTag = 0; + float sinAlpha = 0.f; + float cosAlpha = 0.f; + float globalX = 0.f; + float globalY = 0.f; + float dcaXY = 0.f; + float dcaZ = 0.f; for (auto& track : tracksBarrel) { if (track.pt() < 0.15) @@ -92,13 +98,21 @@ struct TableMaker { if (TMath::Abs(track.eta()) > 0.9) continue; + sinAlpha = sin(track.alpha()); + cosAlpha = cos(track.alpha()); + globalX = track.x() * cosAlpha - track.y() * sinAlpha; + globalY = track.x() * sinAlpha + track.y() * cosAlpha; + + dcaXY = sqrt(pow((globalX - collision.posX()), 2) + + pow((globalY - collision.posY()), 2)); + dcaZ = sqrt(pow(track.z() - collision.posZ(), 2)); + trackBasic(collision, track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); trackBarrel(track.tpcInnerParam(), track.flags(), 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.length(), dcaXY, dcaZ); trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); trackBarrelPID( track.tpcSignal(), diff --git a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx new file mode 100644 index 0000000000000..95c4c5ee90d04 --- /dev/null +++ b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx @@ -0,0 +1,173 @@ +// 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/Multiplicity.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" +#include "Analysis/TriggerAliases.h" +#include "Analysis/ReducedInfoTables.h" +#include "Analysis/VarManager.h" +#include "Analysis/HistogramManager.h" +#include "PID/PIDResponse.h" +#include <iostream> + +using std::cout; +using std::endl; + +using namespace o2; +using namespace o2::framework; +//using namespace o2::framework::expressions; +using namespace o2::aod; + +struct TableMaker_pp { + + Produces<ReducedEvents> event; + Produces<ReducedEventsExtended> eventExtended; + Produces<ReducedEventsVtxCov> eventVtxCov; + Produces<ReducedTracks> trackBasic; + Produces<ReducedTracksBarrel> trackBarrel; + Produces<ReducedTracksBarrelCov> trackBarrelCov; + Produces<ReducedTracksBarrelPID> trackBarrelPID; + Produces<ReducedMuons> muonBasic; + Produces<ReducedMuonsExtended> muonExtended; + + OutputObj<HistogramManager> fHistMan{"output"}; + + // 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::BC | VarManager::ObjTypes::Collision; + constexpr static uint32_t fgTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackCov; + + 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("Event;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + } + + void process(soa::Join<aod::Collisions, aod::EvSels>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracksBarrel) + { + uint64_t tag = 0; + uint32_t triggerAliases = 0; + for (int i = 0; i < kNaliases; i++) + if (collision.alias()[i] > 0) + triggerAliases |= (uint32_t(1) << i); + + VarManager::ResetValues(); + VarManager::FillEvent<fgEventFillMap>(collision); // extract event information and place it in the fgValues array + fHistMan->FillHistClass("Event", VarManager::fgValues); // automatically fill all the histograms in the class Event + + event(tag, collision.bc().runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib()); + eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), triggerAliases, 0.0f); + eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + + uint64_t trackFilteringTag = 0; + float sinAlpha = 0.f; + float cosAlpha = 0.f; + float globalX = 0.f; + float globalY = 0.f; + float dcaXY = 0.f; + float dcaZ = 0.f; + for (auto& track : tracksBarrel) { + + if (track.pt() < 0.15) + continue; + if (TMath::Abs(track.eta()) > 0.9) + continue; + + sinAlpha = sin(track.alpha()); + cosAlpha = cos(track.alpha()); + globalX = track.x() * cosAlpha - track.y() * sinAlpha; + globalY = track.x() * sinAlpha + track.y() * cosAlpha; + + dcaXY = sqrt(pow((globalX - collision.posX()), 2) + + pow((globalY - collision.posY()), 2)); + dcaZ = sqrt(pow(track.z() - collision.posZ(), 2)); + + trackBasic(collision, track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); + trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), + track.tpcNClsShared(), track.tpcChi2NCl(), + track.trdChi2(), track.tofChi2(), + track.length(), dcaXY, dcaZ); + trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); + trackBarrelPID( + track.tpcSignal(), + track.tpcNSigmaEl(), track.tpcNSigmaMu(), + track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), + track.tofSignal(), track.beta(), + track.tofNSigmaEl(), track.tofNSigmaMu(), + track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), + track.trdSignal()); + } + + for (auto& muon : tracksMuon) { + // TODO: add proper information for muon tracks + if (muon.bc() != collision.bc()) + continue; + trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track + muonBasic(collision, trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); + muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); + } + } + + void DefineHistograms(TString histClasses) + { + 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 + } + } // end loop over histogram classes + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<TableMaker_pp>("table-maker-pp")}; +} From 349ff71c7225e3531329d26a983aa5c5d1fb81a7 Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Tue, 15 Sep 2020 15:52:07 +0200 Subject: [PATCH 0617/1751] DPL Analysis: First version of histogram registry writing (#4343) --- Analysis/Tutorials/CMakeLists.txt | 5 + Analysis/Tutorials/src/histogramRegistry.cxx | 41 ++++++ .../include/Framework/CommonDataProcessors.h | 3 + .../include/Framework/HistogramRegistry.h | 28 +++- Framework/Core/src/AnalysisManagers.h | 7 +- Framework/Core/src/CommonDataProcessors.cxx | 131 +++++++++++++++++- Framework/Core/src/WorkflowHelpers.cxx | 18 ++- 7 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 Analysis/Tutorials/src/histogramRegistry.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index c3624626bc491..98ae8843a15f8 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -124,3 +124,8 @@ o2_add_dpl_workflow(hist-helpers-test SOURCES src/histHelpersTest.cxx PUBLIC_LINK_LIBRARIES O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(histogram-registry + SOURCES src/histogramRegistry.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx new file mode 100644 index 0000000000000..12fe4dd68ee9f --- /dev/null +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -0,0 +1,41 @@ +// 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/HistogramRegistry.h" +#include <TH1F.h> + +#include <cmath> + +using namespace o2; +using namespace o2::framework; + +// This is a very simple example showing how to create an histogram +// FIXME: this should really inherit from AnalysisTask but +// we need GCC 7.4+ for that +struct ATask { + /// Construct a registry object with direct declaration + HistogramRegistry registry{"registry", true, {{"eta", "#eta", {HistogramType::kTH1F, {{102, -2.01, 2.01}}}}, {"phi", "#varphi", {HistogramType::kTH1F, {{100, 0., 2. * M_PI}}}}}}; + + void process(aod::Tracks const& tracks) + { + for (auto& track : tracks) { + registry.get("eta")->Fill(track.eta()); + registry.get("phi")->Fill(track.phi()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<ATask>("eta-and-phi-histograms")}; +} diff --git a/Framework/Core/include/Framework/CommonDataProcessors.h b/Framework/Core/include/Framework/CommonDataProcessors.h index f07133978e5dc..19794032575a9 100644 --- a/Framework/Core/include/Framework/CommonDataProcessors.h +++ b/Framework/Core/include/Framework/CommonDataProcessors.h @@ -26,6 +26,9 @@ using outputObjects = std::vector<std::pair<uint32_t, std::vector<std::string>>> /// Helpers to create a few general data processors struct CommonDataProcessors { + /// Match all inputs of kind HIST and write them to a ROOT file, + /// one root file per originating task. + static DataProcessorSpec getHistogramRegistrySink(outputObjects const& objmap, const outputTasks& tskmap); /// Match all inputs of kind ATSK and write them to a ROOT file, /// one root file per originating task. static DataProcessorSpec getOutputObjSink(outputObjects const& objmap, const outputTasks& tskmap); diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 9c7bf0d5a29f8..a8d89c0ac8322 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -15,15 +15,19 @@ #include "Framework/FunctionalHelpers.h" #include "Framework/Logger.h" #include "Framework/OutputRef.h" +#include "Framework/OutputObjHeader.h" #include "Framework/OutputSpec.h" +#include "Framework/SerializationMethods.h" #include "Framework/StringHelpers.h" #include "Framework/TableBuilder.h" +#include "TClass.h" #include "TH1.h" #include "TH2.h" #include "TH3.h" #include "THn.h" #include "THnSparse.h" +#include "TList.h" #include <string> #include <variant> @@ -230,8 +234,9 @@ struct HistogramCallbacks { class HistogramRegistry { public: - HistogramRegistry(char const* const name_, bool enable, std::vector<HistogramSpec> specs) + HistogramRegistry(char const* const name_, bool enable, std::vector<HistogramSpec> specs, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) : name(name_), + policy(policy_), enabled(enable), mRegistryKey(), mRegistryValue(), @@ -283,7 +288,24 @@ class HistogramRegistry OutputRef ref() { - return OutputRef{this->name, 0}; + return OutputRef{std::string{this->name}, 0, o2::header::Stack{OutputObjHeader{policy, taskHash}}}; + } + void setHash(uint32_t hash) + { + taskHash = hash; + } + + TList* operator*() + { + TList* list = new TList(); + list->SetName(this->name.c_str()); + for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + if (mRegistryValue[j].get() != nullptr) { + auto hist = mRegistryValue[j].get(); + list->Add(hist); + } + } + return list; } /// lookup distance counter for benchmarking @@ -310,6 +332,8 @@ class HistogramRegistry } std::string name; bool enabled; + OutputObjHandlingPolicy policy; + uint32_t taskHash; /// The maximum number of histograms in buffer is currently set to 512 /// which seems to be both reasonably large and allowing for very fast lookup diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index e5045f3c81bc7..8508e2e8830da 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -163,8 +163,9 @@ struct OutputManager<Produces<TABLE>> { /// HistogramRegistry specialization template <> struct OutputManager<HistogramRegistry> { - static bool appendOutput(std::vector<OutputSpec>& outputs, HistogramRegistry& what, uint32_t) + static bool appendOutput(std::vector<OutputSpec>& outputs, HistogramRegistry& what, uint32_t hash) { + what.setHash(hash); outputs.emplace_back(what.spec()); return true; } @@ -178,8 +179,10 @@ struct OutputManager<HistogramRegistry> { return true; } - static bool postRun(EndOfStreamContext&, HistogramRegistry&) + static bool postRun(EndOfStreamContext& context, HistogramRegistry& what) { + TList* list = *what; + context.outputs().snapshot(what.ref(), *list); return true; } }; diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 1fd9a947bdda6..9a6bc85c2bbb6 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -70,6 +70,135 @@ const static std::unordered_map<OutputObjHandlingPolicy, std::string> ROOTfileNa {OutputObjHandlingPolicy::QAObject, "QAResults.root"}}; // ============================================================================= +DataProcessorSpec CommonDataProcessors::getHistogramRegistrySink(outputObjects const& objmap, const outputTasks& tskmap) +{ + auto writerFunction = [objmap, tskmap](InitContext& ic) -> std::function<void(ProcessingContext&)> { + auto& callbacks = ic.services().get<CallbackService>(); + auto inputObjects = std::make_shared<std::vector<std::pair<InputObjectRoute, InputObject>>>(); + + auto endofdatacb = [inputObjects](EndOfStreamContext& context) { + LOG(DEBUG) << "Writing merged histograms to file"; + if (inputObjects->empty()) { + LOG(ERROR) << "Output object map is empty!"; + context.services().get<ControlService>().readyToQuit(QuitRequest::All); + return; + } + std::string currentDirectory = ""; + std::string currentFile = ""; + TFile* f[OutputObjHandlingPolicy::numPolicies]; + for (auto i = 0u; i < OutputObjHandlingPolicy::numPolicies; ++i) { + f[i] = nullptr; + } + for (auto& [route, entry] : *inputObjects) { + auto file = ROOTfileNames.find(route.policy); + if (file != ROOTfileNames.end()) { + auto filename = file->second; + if (f[route.policy] == nullptr) { + f[route.policy] = TFile::Open(filename.c_str(), "RECREATE"); + } + auto nextDirectory = route.directory; + if ((nextDirectory != currentDirectory) || (filename != currentFile)) { + if (!f[route.policy]->FindKey(nextDirectory.c_str())) { + f[route.policy]->mkdir(nextDirectory.c_str()); + } + currentDirectory = nextDirectory; + currentFile = filename; + } + (f[route.policy]->GetDirectory(currentDirectory.c_str()))->WriteObjectAny(entry.obj, entry.kind, entry.name.c_str()); + } + } + for (auto i = 0u; i < OutputObjHandlingPolicy::numPolicies; ++i) { + if (f[i] != nullptr) { + f[i]->Close(); + } + } + LOG(INFO) << "All outputs merged in their respective target files"; + context.services().get<ControlService>().readyToQuit(QuitRequest::All); + }; + + callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); + return [inputObjects, objmap, tskmap](ProcessingContext& pc) mutable -> void { + auto const& ref = pc.inputs().get("y"); + if (!ref.header) { + LOG(ERROR) << "Header not found"; + return; + } + if (!ref.payload) { + LOG(ERROR) << "Payload not found"; + return; + } + auto datah = o2::header::get<o2::header::DataHeader*>(ref.header); + if (!datah) { + LOG(ERROR) << "No data header in stack"; + return; + } + + auto objh = o2::header::get<o2::framework::OutputObjHeader*>(ref.header); + if (!objh) { + LOG(ERROR) << "No output object header in stack"; + return; + } + + FairTMessage tm(const_cast<char*>(ref.payload), static_cast<int>(datah->payloadSize)); + InputObject obj; + obj.kind = tm.GetClass(); + if (obj.kind == nullptr) { + LOG(error) << "Cannot read class info from buffer."; + return; + } + + auto policy = objh->mPolicy; + auto hash = objh->mTaskHash; + + obj.obj = tm.ReadObjectAny(obj.kind); + TNamed* named = static_cast<TNamed*>(obj.obj); + obj.name = named->GetName(); + + auto hpos = std::find_if(tskmap.begin(), tskmap.end(), [&](auto&& x) { return x.first == hash; }); + if (hpos == tskmap.end()) { + LOG(ERROR) << "No task found for hash " << hash; + return; + } + auto taskname = hpos->second; + auto opos = std::find_if(objmap.begin(), objmap.end(), [&](auto&& x) { return x.first == hash; }); + if (opos == objmap.end()) { + LOG(ERROR) << "No object list found for task " << taskname << " (hash=" << hash << ")"; + return; + } + auto objects = opos->second; + if (std::find(objects.begin(), objects.end(), obj.name) == objects.end()) { + LOG(ERROR) << "No object " << obj.name << " in map for task " << taskname; + return; + } + auto nameHash = compile_time_hash(obj.name.c_str()); + InputObjectRoute key{obj.name, nameHash, taskname, hash, policy}; + auto existing = std::find_if(inputObjects->begin(), inputObjects->end(), [&](auto&& x) { return (x.first.uniqueId == nameHash) && (x.first.taskHash == hash); }); + if (existing == inputObjects->end()) { + inputObjects->push_back(std::make_pair(key, obj)); + return; + } + auto merger = existing->second.kind->GetMerge(); + if (!merger) { + LOG(ERROR) << "Already one unmergeable object found for " << obj.name; + return; + } + + TList coll; + coll.Add(static_cast<TObject*>(obj.obj)); + merger(existing->second.obj, &coll, nullptr); + }; + }; + + DataProcessorSpec spec{ + "internal-dpl-global-analysis-file-sink", + {InputSpec("y", DataSpecUtils::dataDescriptorMatcherFrom(header::DataOrigin{"HIST"}))}, + Outputs{}, + AlgorithmSpec(writerFunction), + {}}; + + return spec; +} + DataProcessorSpec CommonDataProcessors::getOutputObjSink(outputObjects const& objmap, outputTasks const& tskmap) { auto writerFunction = [objmap, tskmap](InitContext& ic) -> std::function<void(ProcessingContext&)> { @@ -178,7 +307,7 @@ DataProcessorSpec CommonDataProcessors::getOutputObjSink(outputObjects const& ob } auto merger = existing->second.kind->GetMerge(); if (!merger) { - LOG(error) << "Already one unmergeable object found for " << obj.name; + LOG(ERROR) << "Already one unmergeable object found for " << obj.name; return; } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index aa9646ef59cc3..604565805ea0a 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -162,7 +162,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext LOG(INFO) << "To be hidden / removed at some point."; // mark this dummy process as ready-to-quit ic.services().get<ControlService>().readyToQuit(QuitRequest::Me); - + return [](ProcessingContext& pc) { // this callback is never called since there is no expiring input pc.services().get<RawDeviceService>().waitFor(2000); @@ -216,9 +216,11 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext std::vector<InputSpec> requestedCCDBs; std::vector<OutputSpec> providedCCDBs; std::vector<OutputSpec> providedOutputObj; + std::vector<OutputSpec> providedHist; outputTasks outTskMap; outputObjects outObjMap; + outputObjects outHistMap; for (size_t wi = 0; wi < workflow.size(); ++wi) { auto& processor = workflow[wi]; @@ -285,6 +287,14 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } else { it->second.push_back(output.binding.value); } + } else if (DataSpecUtils::partialMatch(output, header::DataOrigin{"HIST"})) { + providedHist.emplace_back(output); + auto it = std::find_if(outHistMap.begin(), outHistMap.end(), [&](auto&& x) { return x.first == hash; }); + if (it == outHistMap.end()) { + outHistMap.push_back({hash, {output.binding.value}}); + } else { + it->second.push_back(output.binding.value); + } } if (output.lifetime == Lifetime::Condition) { providedCCDBs.push_back(output); @@ -338,6 +348,12 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext auto rootSink = CommonDataProcessors::getOutputObjSink(outObjMap, outTskMap); extraSpecs.push_back(rootSink); } + // This is to inject a file sink so that any dangling HIST object is written + // to a ROOT file. + if (providedHist.empty() == false) { + auto rootSink = CommonDataProcessors::getHistogramRegistrySink(outHistMap, outTskMap); + extraSpecs.push_back(rootSink); + } workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); From 1b6f538c3188c11a3c29f08f5c5ac12fd709e182 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 16:56:06 +0200 Subject: [PATCH 0618/1751] Add ability to code-format a PR. (#4347) --- .github/workflows/code-formatting.yml | 81 +++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/code-formatting.yml diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml new file mode 100644 index 0000000000000..85956c36804a8 --- /dev/null +++ b/.github/workflows/code-formatting.yml @@ -0,0 +1,81 @@ +name: Check PR with clang-format + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - 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: alisw/pull-request@master + with: + source_branch: 'AliceO2Group: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: 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 + + From eb14c40bd4effe816d001a5aca35829bcbe6563d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 17:10:29 +0200 Subject: [PATCH 0619/1751] Push new branch to the alibuild repository --- .github/workflows/code-formatting.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 85956c36804a8..c01f03e12b7d2 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -57,14 +57,14 @@ jobs: 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 + git push --set-upstream https://alibuild:${ALIBUILD_GITHUB_TOKEN}@github.com/AliceO2Group/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi - name: pull-request uses: alisw/pull-request@master with: - source_branch: 'AliceO2Group:alibot-cleanup-${{ github.event.pull_request.number }}' + source_branch: 'alibuild: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 }}" From f3fa84bdb9aafb32b4f3eb81dbcbadfce9c8f6ac Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 17:17:05 +0200 Subject: [PATCH 0620/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index c01f03e12b7d2..28c0cbda58dc6 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -57,7 +57,7 @@ jobs: 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 https://alibuild:${ALIBUILD_GITHUB_TOKEN}@github.com/AliceO2Group/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + git push --set-upstream https://alibuild:${ALIBUILD_GITHUB_TOKEN}@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From 187cadd9a8047c89ffc92e0a5d58c883aa862eac Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 15 Sep 2020 19:14:32 +0200 Subject: [PATCH 0621/1751] fixing dynamic calculation of number of clusters (#4346) * fixing dynamic calculation of number of clusters * fixing default values --- Analysis/Core/src/TrackSelection.cxx | 2 +- .../Core/include/Framework/AnalysisDataModel.h | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Analysis/Core/src/TrackSelection.cxx b/Analysis/Core/src/TrackSelection.cxx index dd281f14137bc..372588d9298cb 100644 --- a/Analysis/Core/src/TrackSelection.cxx +++ b/Analysis/Core/src/TrackSelection.cxx @@ -18,7 +18,7 @@ ClassImp(TrackSelection) TrackSelection::TrackSelection() - : TObject(), mMinPt{0.}, mMaxPt{1e10}, mMinEta{0.}, mMaxEta{1e10}, mMinNClustersTPC{0}, mMinNCrossedRowsTPC{0}, mMinNClustersITS{0}, mMaxChi2PerClusterTPC{1e10}, mMaxChi2PerClusterITS{1e10}, mMinNCrossedRowsOverFindableClustersTPC{1e10}, mMaxDcaXY{1e10}, mMaxDcaZ{1e10}, mRequireITSRefit{false}, mRequireTPCRefit{false} + : TObject(), mMinPt{0.}, mMaxPt{1e10}, mMinEta{-1e10}, mMaxEta{1e10}, mMinNClustersTPC{0}, mMinNCrossedRowsTPC{0}, mMinNClustersITS{0}, mMaxChi2PerClusterTPC{1e10}, mMaxChi2PerClusterITS{1e10}, mMinNCrossedRowsOverFindableClustersTPC{0}, mMaxDcaXY{1e10}, mMaxDcaZ{1e10}, mRequireITSRefit{false}, mRequireTPCRefit{false} { } diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 13bef17ae529a..8a079417ed680 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -172,8 +172,8 @@ DECLARE_SOA_COLUMN(Length, length, float); DECLARE_SOA_COLUMN(TOFExpMom, tofExpMom, float); DECLARE_SOA_COLUMN(TrackEtaEMCAL, trackEtaEmcal, float); DECLARE_SOA_COLUMN(TrackPhiEMCAL, trackPhiEmcal, float); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNClsFound, tpcNClsFound, [](uint8_t tpcNClsFindable, uint8_t tpcNClsFindableMinusFound) -> int16_t { return tpcNClsFindable - tpcNClsFindableMinusFound; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, [](uint8_t tpcNClsFindable, uint8_t TPCNClsFindableMinusCrossedRows) -> int16_t { return tpcNClsFindable - TPCNClsFindableMinusCrossedRows; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNClsFound, tpcNClsFound, [](uint8_t tpcNClsFindable, int8_t tpcNClsFindableMinusFound) -> int16_t { return (int16_t)tpcNClsFindable - tpcNClsFindableMinusFound; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, [](uint8_t tpcNClsFindable, int8_t TPCNClsFindableMinusCrossedRows) -> int16_t { return (int16_t)tpcNClsFindable - TPCNClsFindableMinusCrossedRows; }); DECLARE_SOA_DYNAMIC_COLUMN(ITSNCls, itsNCls, [](uint8_t itsClusterMap) -> uint8_t { uint8_t itsNcls = 0; constexpr uint8_t bit = 1; @@ -192,16 +192,15 @@ DECLARE_SOA_DYNAMIC_COLUMN(ITSNClsInnerBarrel, itsNClsInnerBarrel, [](uint8_t it }); DECLARE_SOA_DYNAMIC_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, - [](uint8_t tpcNClsFindable, uint8_t tpcNClsFindableMinusCrossedRows) -> float { + [](uint8_t tpcNClsFindable, int8_t tpcNClsFindableMinusCrossedRows) -> float { // FIXME: use int16 tpcNClsCrossedRows from dynamic column as argument - int16_t tpcNClsCrossedRows = tpcNClsFindable - tpcNClsFindableMinusCrossedRows; + int16_t tpcNClsCrossedRows = (int16_t)tpcNClsFindable - tpcNClsFindableMinusCrossedRows; return (float)tpcNClsCrossedRows / (float)tpcNClsFindable; - ; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, [](uint8_t tpcNClsShared, uint8_t tpcNClsFindable, uint8_t tpcNClsFindableMinusFound) -> float { +DECLARE_SOA_DYNAMIC_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, [](uint8_t tpcNClsShared, uint8_t tpcNClsFindable, int8_t tpcNClsFindableMinusFound) -> float { // FIXME: use tpcNClsFound from dynamic column as argument - int16_t tpcNClsFound = tpcNClsFindable - tpcNClsFindableMinusFound; + int16_t tpcNClsFound = (int16_t)tpcNClsFindable - tpcNClsFindableMinusFound; return (float)tpcNClsShared / (float)tpcNClsFound; }); } // namespace track From fe811537526db35afb2c370910a0c82d9207f492 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Sat, 29 Aug 2020 11:38:29 +0200 Subject: [PATCH 0622/1751] Fix clang-format in MID Encoder --- Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h index f025fbf27356d..9830372a589da 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h @@ -49,6 +49,7 @@ class Encoder void hbTrigger(const InteractionRecord& ir); o2::raw::RawFileWriter mRawWriter{o2::header::gDataOriginMID}; /// Raw file writer + std::map<uint16_t, LocalBoardRO> mROData{}; /// Map of data per board ColumnDataToLocalBoard mConverter{}; /// ColumnData to LocalBoardRO converter FEEIdConfig mFEEIdConfig{}; /// Crate FEEId mapper From 369df781339f6a9864ad3165106ec2bee2decc69 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 14 Sep 2020 15:32:54 +0200 Subject: [PATCH 0623/1751] TRD digitization: Application of new labels container structure --- .../IOMCTruthContainerView.h | 9 ++++ Detectors/TRD/base/src/TRDBaseLinkDef.h | 4 ++ .../include/TRDWorkflow/TRDDigitReaderSpec.h | 6 --- .../TRD/workflow/src/TRDDigitReaderSpec.cxx | 33 ++++++++---- .../TRD/workflow/src/TRDDigitWriterSpec.cxx | 51 ++++++++++++++++++- .../TRD/workflow/src/TRDDigitizerSpec.cxx | 5 +- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 11 ++-- 7 files changed, 95 insertions(+), 24 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h index db9f80cc7de9b..15e88dc77a1aa 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h +++ b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h @@ -40,6 +40,12 @@ class IOMCTruthContainerView /// 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<char> const& input) + { + adopt(input); + } + + /// "adopt" (without taking ownership) from an existing buffer + void adopt(std::vector<char> const& input) { const auto delta = input.size() / N; N2 = input.size() - (N - 1) * delta; @@ -75,6 +81,9 @@ class IOMCTruthContainerView copyhelper(part10, N2, output); } + /// return total size in bytes + size_t getSize() const { return N1 * (N - 1) + N2; } + private: static constexpr int N = 10; int N1 = 0; diff --git a/Detectors/TRD/base/src/TRDBaseLinkDef.h b/Detectors/TRD/base/src/TRDBaseLinkDef.h index fc6ab2dbf8ac9..65dca8213dee7 100644 --- a/Detectors/TRD/base/src/TRDBaseLinkDef.h +++ b/Detectors/TRD/base/src/TRDBaseLinkDef.h @@ -46,5 +46,9 @@ #pragma link C++ class std::vector < o2::trd::Tracklet > +; #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" + +// this is just needed to please the DPL ROOTTreeWriter facility +#pragma link C++ class o2::dataformats::ConstMCTruthContainer < o2::trd::MCLabel> + ; #endif diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDDigitReaderSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDDigitReaderSpec.h index 427a67af6249e..2837bd004e363 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDDigitReaderSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDDigitReaderSpec.h @@ -11,16 +11,13 @@ #ifndef O2_TRDTRAPSIMULATORRAWREADERSPEC_H #define O2_TRDTRAPSIMULATORRAWREADERSPEC_H -#include "TRDBase/Digit.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" #include "Framework/DataProcessorSpec.h" #include "Framework/DataRefUtils.h" #include "Framework/Lifetime.h" #include "Framework/Task.h" -#include <SimulationDataFormat/MCTruthContainer.h> #include "TRDBase/MCLabel.h" -#include "DataFormatsTRD/TriggerRecord.h" #include "TFile.h" #include "TTree.h" @@ -44,9 +41,6 @@ class TRDDigitReaderSpec : public o2::framework::Task int mChannels; std::unique_ptr<TFile> mFile = nullptr; //std::unique_ptr<TTree> DPLTree; - std::vector<o2::trd::Digit> mDigits, *mPDigits = &mDigits; - o2::dataformats::MCTruthContainer<o2::trd::MCLabel> mMCLabels, *mPMCLabels = &mMCLabels; - std::vector<o2::trd::TriggerRecord> mTriggerRecords, *mPTriggerRecords = &mTriggerRecords; std::string mInputFileName = ""; std::string mDigitTreeName = "o2sim"; std::string mDigitBranchName = "TRDDigit"; diff --git a/Detectors/TRD/workflow/src/TRDDigitReaderSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitReaderSpec.cxx index 521ce7a4f1731..9931ad0269fa2 100644 --- a/Detectors/TRD/workflow/src/TRDDigitReaderSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitReaderSpec.cxx @@ -24,7 +24,8 @@ #include "Steer/HitProcessingManager.h" // for DigitizationContext #include "TChain.h" #include <SimulationDataFormat/MCCompLabel.h> -#include <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> +#include <SimulationDataFormat/IOMCTruthContainerView.h> #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" #include "TRDBase/Digit.h" // for the Digit type @@ -82,16 +83,28 @@ void TRDDigitReaderSpec::run(ProcessingContext& pc) LOG(info) << "mState is not 1"; return; } - TTree* DPLTree = ((TTree*)mFile->Get(mDigitTreeName.c_str())); + auto DPLTree = ((TTree*)mFile->Get(mDigitTreeName.c_str())); if (DPLTree) { - DPLTree->SetBranchAddress(mDigitBranchName.c_str(), &mPDigits); - DPLTree->SetBranchAddress(mTriggerRecordBranchName.c_str(), &mPTriggerRecords); - DPLTree->SetBranchAddress(mMCLabelsBranchName.c_str(), &mPMCLabels); - DPLTree->GetEntry(0); - pc.outputs().snapshot(Output{"TRD", "DIGITS", 0, Lifetime::Timeframe}, mDigits); - pc.outputs().snapshot(Output{"TRD", "TRGRDIG", 0, Lifetime::Timeframe}, mTriggerRecords); - pc.outputs().snapshot(Output{"TRD", "LABELS", 0, Lifetime::Timeframe}, mMCLabels); - LOG(info) << "TRDDigitReader digits size=" << mDigits.size() << " triggerrecords size=" << mTriggerRecords.size() << " mc labels size=" << mMCLabels.getNElements(); + std::vector<o2::trd::Digit>* digits = nullptr; + o2::dataformats::IOMCTruthContainerView* ioLabels = nullptr; + std::vector<o2::trd::TriggerRecord>* triggerRecords = nullptr; + + auto getFromBranch = [DPLTree](const char* name, void** ptr) { + auto br = DPLTree->GetBranch(name); + br->SetAddress(ptr); + br->GetEntry(0); + br->ResetAddress(); + }; + getFromBranch(mDigitBranchName.c_str(), (void**)&digits); + getFromBranch(mTriggerRecordBranchName.c_str(), (void**)&triggerRecords); + getFromBranch(mMCLabelsBranchName.c_str(), (void**)&ioLabels); + + // publish labels in shared memory + auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::trd::MCLabel>>(Output{"TRD", "LABELS", 0, Lifetime::Timeframe}); + ioLabels->copyandflatten(sharedlabels); + pc.outputs().snapshot(Output{"TRD", "DIGITS", 0, Lifetime::Timeframe}, *digits); + pc.outputs().snapshot(Output{"TRD", "TRGRDIG", 0, Lifetime::Timeframe}, *triggerRecords); + LOG(info) << "TRDDigitReader digits size=" << digits->size() << " triggerrecords size=" << triggerRecords->size() << " mc labels size (in bytes) = " << sharedlabels.size(); } //delete DPLTree; // next line will delete the pointer as well. mFile->Close(); diff --git a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx index 568a781715a2b..829e587cac140 100644 --- a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx @@ -16,7 +16,8 @@ #include "Framework/InputSpec.h" #include "TRDBase/Digit.h" #include "DataFormatsTRD/TriggerRecord.h" -#include <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> +#include <SimulationDataFormat/IOMCTruthContainerView.h> #include "TRDBase/MCLabel.h" #include "TRDWorkflow/TRDDigitWriterSpec.h" @@ -32,13 +33,59 @@ o2::framework::DataProcessorSpec getTRDDigitWriterSpec(bool mctruth) { using InputSpec = framework::InputSpec; using MakeRootTreeWriterSpec = framework::MakeRootTreeWriterSpec; + using DataRef = framework::DataRef; + + auto getIndex = [](o2::framework::DataRef const& ref) -> size_t { + return 0; + }; + + // callback to create branch name + auto getName = [](std::string base, size_t index) -> std::string { + return base; + }; + + // the callback to be set as hook for custom action when the writer is closed + auto finishWriting = [](TFile* outputfile, TTree* outputtree) { + outputtree->SetEntries(1); + outputtree->Write(); + outputfile->Close(); + }; + + // custom handler for labels: + // essentially transform the input container (as registered in the branch definition) to the special output format for labels + auto customlabelhandler = [](TBranch& branch, o2::dataformats::ConstMCTruthContainer<o2::trd::MCLabel> const& labeldata, DataRef const& ref) { + // make the actual output object by adopting/casting the buffer + // into a split format + o2::dataformats::IOMCTruthContainerView outputcontainer(labeldata); + auto tree = branch.GetTree(); + auto name = branch.GetName(); + // we need to make something ugly since the original branch is already registered with a different type + // (communicated by Philippe Canal / ROOT team) + branch.DeleteBaskets("all"); + // remove the existing branch and make a new one with the correct type + tree->GetListOfBranches()->Remove(&branch); + auto br = tree->Branch(name, &outputcontainer); + br->Fill(); + br->ResetAddress(); + }; + + auto labelsdef = BranchDefinition<o2::dataformats::ConstMCTruthContainer<o2::trd::MCLabel>>{InputSpec{"labelinput", "TRD", "LABELS"}, + "TRDMCLabels", "labels-branch-name", + // this branch definition is disabled if MC labels are not processed + (mctruth ? 1 : 0), + customlabelhandler, + getIndex, + getName}; + return MakeRootTreeWriterSpec("TRDDigitWriter", "trddigits.root", "o2sim", 1, + // setting a custom callback for closing the writer + MakeRootTreeWriterSpec::CustomClose(finishWriting), BranchDefinition<std::vector<o2::trd::Digit>>{InputSpec{"input", "TRD", "DIGITS"}, "TRDDigit"}, BranchDefinition<std::vector<o2::trd::TriggerRecord>>{InputSpec{"trinput", "TRD", "TRGRDIG"}, "TriggerRecord"}, - BranchDefinition<o2::dataformats::MCTruthContainer<o2::trd::MCLabel>>{InputSpec{"labelinput", "TRD", "LABELS"}, "TRDMCLabels", mctruth ? 1 : 0})(); + std::move(labelsdef))(); } } // end namespace trd diff --git a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx index 4e2f62fcfe016..3fe597f5e627f 100644 --- a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx @@ -20,6 +20,7 @@ #include "TChain.h" #include <SimulationDataFormat/MCCompLabel.h> #include <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" #include "TRDBase/Digit.h" // for the Digit type @@ -125,7 +126,9 @@ class TRDDPLDigitizerTask : public o2::base::BaseDPLDigitizer pc.outputs().snapshot(Output{"TRD", "DIGITS", 0, Lifetime::Timeframe}, digitsAccum); if (mctruth) { LOG(INFO) << "TRD: Sending " << labelsAccum.getNElements() << " labels"; - pc.outputs().snapshot(Output{"TRD", "LABELS", 0, Lifetime::Timeframe}, labelsAccum); + // we are flattening the labels and write to managed shared memory container for further communication + auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::trd::MCLabel>>(Output{"TRD", "LABELS", 0, Lifetime::Timeframe}); + labelsAccum.flatten_to(sharedlabels); } LOG(INFO) << "TRD: Sending ROMode= " << mROMode << " to GRPUpdater"; pc.outputs().snapshot(Output{"TRD", "ROMode", 0, Lifetime::Timeframe}, mROMode); diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 46d4cd760a2a8..a7ec13c7a3e98 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -36,6 +36,7 @@ #include "TChain.h" #include <SimulationDataFormat/MCCompLabel.h> #include <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> #include "fairlogger/Logger.h" #include "CCDB/BasicCCDBManager.h" @@ -383,7 +384,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) auto inputDigits = pc.inputs().get<gsl::span<o2::trd::Digit>>("digitinput"); std::vector<o2::trd::Digit> msgDigits(inputDigits.begin(), inputDigits.end()); // auto digits pc.outputs().make<std::vector<o2::trd::Digit>>(Output{"TRD", "TRKDIGITS", 0, Lifetime::Timeframe}, msgDigits.begin(), msgDigits.end()); - auto digitMCLabels = pc.inputs().get<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("labelinput"); + auto digitMCLabels = pc.inputs().get<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>("labelinput"); // auto rawDataOut = pc.outputs().make<char>(Output{"TRD", "RAWDATA", 0, Lifetime::Timeframe}, 1000); //TODO number is just a place holder until we start using it. o2::dataformats::MCTruthContainer<o2::MCCompLabel> trackletMCLabels; @@ -413,10 +414,10 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) std::vector<unsigned int> msgDigitsIndex; msgDigitsIndex.reserve(msgDigits.size()); - LOG(debug) << "Read in msgDigits with size of : " << msgDigits.size() << " labels contain : " << digitMCLabels->getNElements() << " with and index size of : " << digitMCLabels->getIndexedSize(); + LOG(debug) << "Read in msgDigits with size of : " << msgDigits.size() << " labels contain : " << digitMCLabels.getNElements() << " with and index size of : " << digitMCLabels.getIndexedSize(); - if (digitMCLabels->getIndexedSize() != msgDigits.size()) { - LOG(warn) << "Digits and Labels coming into TrapSimulator are of differing sizes, labels will be jibberish. " << digitMCLabels->getIndexedSize() << "!=" << msgDigits.size(); + if (digitMCLabels.getIndexedSize() != msgDigits.size()) { + LOG(warn) << "Digits and Labels coming into TrapSimulator are of differing sizes, labels will be jibberish. " << digitMCLabels.getIndexedSize() << "!=" << msgDigits.size(); } //set up structures to hold the returning tracklets. std::vector<Tracklet64> trapTracklets; //vector to store the retrieved tracklets from an trapsim object @@ -637,7 +638,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) } int adc = 20 - (pad % 18) - 1; std::vector<o2::MCCompLabel> tmplabels; - auto digitslabels = digitMCLabels->getLabels(digitcounter); + auto digitslabels = digitMCLabels.getLabels(digitcounter); for (auto& tmplabel : digitslabels) { tmplabels.push_back(tmplabel); } From 2945ca1b32f7c0aa89b60705c711e6399c476587 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 15 Sep 2020 14:14:36 +0200 Subject: [PATCH 0624/1751] GPU: Fix compilation when ROOT was compiled with CUDA support --- GPU/Common/GPUCommonDefAPI.h | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/GPU/Common/GPUCommonDefAPI.h b/GPU/Common/GPUCommonDefAPI.h index 22df336776d94..576d03cd897a1 100644 --- a/GPU/Common/GPUCommonDefAPI.h +++ b/GPU/Common/GPUCommonDefAPI.h @@ -52,20 +52,22 @@ #define GPUconstantref() // reference / ptr to constant memory #define GPUconstexprref() // reference / ptr to variable declared as GPUconstexpr() - struct float4 { float x, y, z, w; }; - struct float3 { float x, y, z; }; - struct float2 { float x; float y; }; - struct uchar2 { unsigned char x, y; }; - struct short2 { short x, y; }; - struct ushort2 { unsigned short x, y; }; - struct int2 { int x, y; }; - struct int3 { int x, y, z; }; - struct int4 { int x, y, z, w; }; - struct uint1 { unsigned int x; }; - struct uint2 { unsigned int x, y; }; - struct uint3 { unsigned int x, y, z; }; - struct uint4 { unsigned int x, y, z, w; }; - struct dim3 { unsigned int x, y, z; }; + #ifndef __VECTOR_TYPES_H__ // ROOT will pull in these CUDA definitions if built against CUDA, so we have to add an ugly protection here + struct float4 { float x, y, z, w; }; + struct float3 { float x, y, z; }; + struct float2 { float x; float y; }; + struct uchar2 { unsigned char x, y; }; + struct short2 { short x, y; }; + struct ushort2 { unsigned short x, y; }; + struct int2 { int x, y; }; + struct int3 { int x, y, z; }; + struct int4 { int x, y, z, w; }; + struct uint1 { unsigned int x; }; + struct uint2 { unsigned int x, y; }; + struct uint3 { unsigned int x, y, z; }; + struct uint4 { unsigned int x, y, z, w; }; + struct dim3 { unsigned int x, y, z; }; + #endif #elif defined(__OPENCL__) // Defines for OpenCL #define GPUd() #define GPUdDefault() From aaf9deabebce33a8e003634f8de16ae7002467f1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 21:35:33 +0200 Subject: [PATCH 0625/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 28c0cbda58dc6..7e554bf10f708 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -57,7 +57,7 @@ jobs: 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 https://alibuild:${ALIBUILD_GITHUB_TOKEN}@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + git push --set-upstream https://alibuild:${{ secrets.ALIBUILD_GITHUB_TOKEN }}@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From 1e3af4b7a1a8e4877ce9bd36a4396011d086564f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 21:46:41 +0200 Subject: [PATCH 0626/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 7e554bf10f708..5f13f655b2a8f 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -10,6 +10,7 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false - name: Run clang format id: clang_format run: | From e5e4817765a92da08ad11dcc9de26d3a482fa4df Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 21:57:40 +0200 Subject: [PATCH 0627/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 5f13f655b2a8f..fac2898499544 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} - persist-credentials: false + token: ${{ secrets.ALIBUILD_GITHUB_TOKEN }} - name: Run clang format id: clang_format run: | From 49082874ba018d370aad018fc92e0144b77fcf75 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 22:00:09 +0200 Subject: [PATCH 0628/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index fac2898499544..3d8b865a597d3 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} - token: ${{ secrets.ALIBUILD_GITHUB_TOKEN }} + token: "${{secrets.ALIBUILD_GITHUB_TOKEN}}" - name: Run clang format id: clang_format run: | From 4f40d2a543a84a002eae9b5e66e2926289a6f1da Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 22:02:50 +0200 Subject: [PATCH 0629/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 3d8b865a597d3..1905c24b4dbda 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -11,6 +11,8 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} token: "${{secrets.ALIBUILD_GITHUB_TOKEN}}" + env: + GITHUB_TOKEN: ${{ secrets.ALIBUILD_GITHUB_TOKEN }} - name: Run clang format id: clang_format run: | From 0a013cc9043343b518d09cf79019b3f750d5efa1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 22:08:13 +0200 Subject: [PATCH 0630/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 1905c24b4dbda..e211514d363dd 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -10,9 +10,7 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} - token: "${{secrets.ALIBUILD_GITHUB_TOKEN}}" - env: - GITHUB_TOKEN: ${{ secrets.ALIBUILD_GITHUB_TOKEN }} + persist-credentials: false - name: Run clang format id: clang_format run: | @@ -60,6 +58,8 @@ jobs: echo "Opening a PR to your branch with the fixes" git commit -m "Please consider the following formatting changes" -a git show | cat + echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc + echo $ALIBUILD_GITHUB_TOKEN | wc git push --set-upstream https://alibuild:${{ secrets.ALIBUILD_GITHUB_TOKEN }}@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From b57374a3795ab451ad078156962d1c5a7d8f389d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 22:14:57 +0200 Subject: [PATCH 0631/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index e211514d363dd..21ded8072c602 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -13,6 +13,8 @@ jobs: persist-credentials: false - name: Run clang format id: clang_format + env: + ALIBUILD_GITHUB_TOKEN: ${{secrets.ALIBUILD_GITHUB_TOKEN}} run: | set -x # We need to fetch the other commit. @@ -60,7 +62,7 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - git push --set-upstream https://alibuild:${{ secrets.ALIBUILD_GITHUB_TOKEN }}@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From 3fbcc525112fe361abedb0d1bf97c24de7418520 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 22:38:19 +0200 Subject: [PATCH 0632/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 21ded8072c602..b0a1b7f088cc8 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -62,10 +62,19 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + # git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.ALIBUILD_GITHUB_TOKEN }} + branch: alibot-cleanup-${{ github.event.pull_request.number }} + force: true + repository: alibuild/AliceO2 + continue-on-error: true # We do not create PRs if the branch is not there. + - name: pull-request uses: alisw/pull-request@master with: From cf744a4546949edd16f44e6cfc277d7f6032085f Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Tue, 15 Sep 2020 22:50:47 +0200 Subject: [PATCH 0633/1751] fix small logic bug in track selection (#4350) --- Analysis/Core/include/Analysis/TrackSelection.h | 9 ++++++--- Analysis/Core/src/TrackSelection.cxx | 2 +- Analysis/Tasks/trackselection.cxx | 9 +++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/Analysis/TrackSelection.h index 9825c04fe8014..51aad617a560f 100644 --- a/Analysis/Core/include/Analysis/TrackSelection.h +++ b/Analysis/Core/include/Analysis/TrackSelection.h @@ -31,7 +31,7 @@ class TrackSelection : public TObject template <typename T> bool IsSelected(T const& track) { - if (track.trackType() == o2::aod::track::TrackTypeEnum::GlobalTrack && + if (track.trackType() == mTrackType && track.pt() >= mMinPt && track.pt() < mMaxPt && track.eta() >= mMinEta && track.eta() < mMaxEta && track.tpcNClsFound() >= mMinNClustersTPC && track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC && @@ -40,8 +40,8 @@ class TrackSelection : public TObject (track.itsNCls() >= mMinNClustersITS) && (track.itsChi2NCl() < mMaxChi2PerClusterITS) && (track.tpcChi2NCl() < mMaxChi2PerClusterTPC) && - (mRequireITSRefit && (track.flags() & 0x4)) && - (mRequireTPCRefit && (track.flags() & 0x40)) && + ((mRequireITSRefit) ? (track.flags() & 0x4) : true) && + ((mRequireTPCRefit) ? (track.flags() & 0x40) : true) && FulfillsITSHitRequirements(track.itsClusterMap()) && abs(track.dcaXY()) < mMaxDcaXY && abs(track.dcaZ()) < mMaxDcaZ) { return true; @@ -50,6 +50,7 @@ class TrackSelection : public TObject } } + void SetTrackType(o2::aod::track::TrackTypeEnum trackType) { mTrackType = trackType; } void SetMinPt(float minPt) { mMinPt = minPt; } void SetMaxPt(float maxPt) { mMaxPt = maxPt; } void SetMinEta(float minEta) { mMinEta = minEta; } @@ -110,6 +111,8 @@ class TrackSelection : public TObject private: bool FulfillsITSHitRequirements(uint8_t itsClusterMap); + o2::aod::track::TrackTypeEnum mTrackType; + // kinematic cuts float mMinPt, mMaxPt; // range in pT float mMinEta, mMaxEta; // range in eta diff --git a/Analysis/Core/src/TrackSelection.cxx b/Analysis/Core/src/TrackSelection.cxx index 372588d9298cb..a663acbfa5ad2 100644 --- a/Analysis/Core/src/TrackSelection.cxx +++ b/Analysis/Core/src/TrackSelection.cxx @@ -18,7 +18,7 @@ ClassImp(TrackSelection) TrackSelection::TrackSelection() - : TObject(), mMinPt{0.}, mMaxPt{1e10}, mMinEta{-1e10}, mMaxEta{1e10}, mMinNClustersTPC{0}, mMinNCrossedRowsTPC{0}, mMinNClustersITS{0}, mMaxChi2PerClusterTPC{1e10}, mMaxChi2PerClusterITS{1e10}, mMinNCrossedRowsOverFindableClustersTPC{0}, mMaxDcaXY{1e10}, mMaxDcaZ{1e10}, mRequireITSRefit{false}, mRequireTPCRefit{false} + : TObject(), mTrackType{o2::aod::track::TrackTypeEnum::GlobalTrack}, mMinPt{0.}, mMaxPt{1e10}, mMinEta{-1e10}, mMaxEta{1e10}, mMinNClustersTPC{0}, mMinNCrossedRowsTPC{0}, mMinNClustersITS{0}, mMaxChi2PerClusterTPC{1e10}, mMaxChi2PerClusterITS{1e10}, mMinNCrossedRowsOverFindableClustersTPC{0}, mMaxDcaXY{1e10}, mMaxDcaZ{1e10}, mRequireITSRefit{false}, mRequireTPCRefit{false}, mRequiredITSHits{} { } diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index d94d1974a0ebb..57fb22c81fd4d 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -76,8 +76,7 @@ struct TrackExtensionTask { Produces<aod::TracksExtended> extendedTrackQuantities; - void process(aod::Collision const& collision, - soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov> const& tracks) + void process(aod::Collision const& collision, aod::FullTracks const& tracks) { float sinAlpha = 0.f; float cosAlpha = 0.f; @@ -119,7 +118,7 @@ struct TrackSelectionTask { globalTracksSDD = getGlobalTrackSelectionSDD(); } - void process(soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::TracksExtended> const& tracks) + void process(soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& track : tracks) { filterTable((uint8_t)globalTracks.IsSelected(track), @@ -242,9 +241,7 @@ struct TrackQATask { void init(o2::framework::InitContext&) {} - void process(aod::Collision const& collision, - soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::TracksExtended, - aod::TrackSelection> const& tracks) + void process(aod::Collision const& collision, soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection> const& tracks) { collisionPos->Fill(collision.posX(), collision.posY()); From 99a5d04c3fb1906f72c22c4ef0572e5084bfc24e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 23:35:54 +0200 Subject: [PATCH 0634/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index b0a1b7f088cc8..6ab266c78c79e 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -10,7 +10,6 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} - persist-credentials: false - name: Run clang format id: clang_format env: @@ -62,23 +61,14 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - # git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + # git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/${{ github.event.pull_request.user.login }}/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi - - name: Push changes - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.ALIBUILD_GITHUB_TOKEN }} - branch: alibot-cleanup-${{ github.event.pull_request.number }} - force: true - repository: alibuild/AliceO2 - continue-on-error: true # We do not create PRs if the branch is not there. - - name: pull-request uses: alisw/pull-request@master with: - source_branch: 'alibuild:alibot-cleanup-${{ github.event.pull_request.number }}' + source_branch: '${{ github.event.pull_request.user.login }}: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 }}" @@ -91,5 +81,3 @@ jobs: true) echo "PR clean" ; exit 0 ;; false) echo "PR not clean" ; exit 1 ;; esac - - From 64d599371d6af703c2b0b4e5b01d52eea10f7fb9 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 23:39:47 +0200 Subject: [PATCH 0635/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 6ab266c78c79e..f6f7574bfa71f 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -61,7 +61,7 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - # git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/${{ github.event.pull_request.user.login }}/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/${{ github.event.pull_request.user.login }}/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From 7ed93411d4e2a7654461629ae10a74100dd5ce3a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 23:54:15 +0200 Subject: [PATCH 0636/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index f6f7574bfa71f..bb226f53b9091 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -1,6 +1,6 @@ name: Check PR with clang-format -on: [pull_request] +on: [pull_request_target] jobs: build: @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2 with: - ref: ${{ github.event.pull_request.head.sha }} + ref: ${{ github.event.pull_request_target.head.sha }} - name: Run clang format id: clang_format env: @@ -17,18 +17,20 @@ jobs: run: | set -x # We need to fetch the other commit. - git fetch --depth=1 origin ${{ github.event.pull_request.base.ref }} + git fetch --depth=1 origin ${{ github.event.pull_request_target.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 }} + git checkout -b alibot-cleanup-${{ github.event.pull_request_target.number }} ${{ github.event.pull_request_target.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 }}" + BASE_COMMIT=${{ github.event.pull_request_target.base.sha }} + echo "Running clang-format-8 against branch ${{ github.event.pull_request_target.base.ref }} , with hash ${{ github.event.pull_request_target.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 + 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 @@ -49,7 +51,7 @@ jobs: 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 + git push --set-upstream origin :alibot-cleanup-${{ github.event.pull_request_target.number }} -f || true echo ::set-output name=clean::true else echo "clang-format failed." @@ -61,17 +63,17 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/${{ github.event.pull_request.user.login }}/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request_target.number }} -f echo ::set-output name=clean::false fi - name: pull-request uses: alisw/pull-request@master with: - source_branch: '${{ github.event.pull_request.user.login }}:alibot-cleanup-${{ github.event.pull_request.number }}' - destination_branch: '${{ github.event.pull_request.user.login }}:${{ github.event.pull_request.head.ref }}' + source_branch: '${{ github.event.pull_request_target.user.login }}:alibot-cleanup-${{ github.event.pull_request_target.number }}' + destination_branch: '${{ github.event.pull_request_target.user.login }}:${{ github.event.pull_request_target.head.ref }}' github_token: ${{ secrets.GITHUB_TOKEN }} - pr_title: "Please consider the following formatting changes to #${{ github.event.pull_request.number }}" + pr_title: "Please consider the following formatting changes to #${{ github.event.pull_request_target.number }}" pr_body: "Please consider the following formatting changes" continue-on-error: true # We do not create PRs if the branch is not there. From 2624d9a7e3159a94ecd63eddaff88c73a1631d4c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Sep 2020 23:58:53 +0200 Subject: [PATCH 0637/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index bb226f53b9091..be960b06a2071 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -18,7 +18,8 @@ jobs: set -x # We need to fetch the other commit. git fetch --depth=1 origin ${{ github.event.pull_request_target.base.ref }} - + git fetch --depth=1 origin pull/${{ github.event.pull_request_target.number }}/head:${{ github.event.pull_request_target.head.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" From 08fddf950ffae61471f5aaaf384c4ae85338a984 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 00:04:56 +0200 Subject: [PATCH 0638/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index be960b06a2071..f34686ee851cc 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2 with: - ref: ${{ github.event.pull_request_target.head.sha }} + ref: ${{ github.event.pull_request.head.sha }} - name: Run clang format id: clang_format env: @@ -17,16 +17,16 @@ jobs: run: | set -x # We need to fetch the other commit. - git fetch --depth=1 origin ${{ github.event.pull_request_target.base.ref }} - git fetch --depth=1 origin pull/${{ github.event.pull_request_target.number }}/head:${{ github.event.pull_request_target.head.ref }} + git fetch --depth=1 origin ${{ github.event.pull_request.base.ref }} + git fetch --depth=1 origin pull/${{ github.event.pull_request.number }}/head:${{ github.event.pull_request.head.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_target.number }} ${{ github.event.pull_request_target.head.sha }} + git checkout -b alibot-cleanup-${{ github.event.pull_request.number }} ${{ github.event.pull_request.head.sha }} - BASE_COMMIT=${{ github.event.pull_request_target.base.sha }} - echo "Running clang-format-8 against branch ${{ github.event.pull_request_target.base.ref }} , with hash ${{ github.event.pull_request_target.base.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 \ @@ -52,7 +52,7 @@ jobs: 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_target.number }} -f || true + 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." @@ -64,17 +64,17 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request_target.number }} -f + git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi - name: pull-request uses: alisw/pull-request@master with: - source_branch: '${{ github.event.pull_request_target.user.login }}:alibot-cleanup-${{ github.event.pull_request_target.number }}' - destination_branch: '${{ github.event.pull_request_target.user.login }}:${{ github.event.pull_request_target.head.ref }}' + source_branch: '${{ github.event.pull_request.user.login }}: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_target.number }}" + 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. From fb9cc5534ef727f8efe02c81f9dff7ee6f5eaca9 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 00:09:06 +0200 Subject: [PATCH 0639/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index f34686ee851cc..f25685d749cde 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -18,7 +18,7 @@ jobs: set -x # We need to fetch the other commit. git fetch --depth=1 origin ${{ github.event.pull_request.base.ref }} - git fetch --depth=1 origin pull/${{ github.event.pull_request.number }}/head:${{ github.event.pull_request.head.ref }} + git fetch origin pull/${{ github.event.pull_request.number }}/head:${{ github.event.pull_request.head.ref }} # We create a new branch which we will use for the eventual PR. git config --global user.email "alibuild@cern.ch" From fadb8d8aeedae91768397907a3635e0864b25f06 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 00:16:31 +0200 Subject: [PATCH 0640/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index f25685d749cde..a515c2a1d9e5d 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -64,6 +64,7 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc + git fetch --unshallow https://github.com/${{github.event.pull_request.user.login}}/AliceO2.git git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From 84ec097e2c955fc8ed2e3eb0690b2cd95de0d373 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 00:27:28 +0200 Subject: [PATCH 0641/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index a515c2a1d9e5d..f5ea0238371c3 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -10,6 +10,7 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false - name: Run clang format id: clang_format env: @@ -64,7 +65,7 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - git fetch --unshallow https://github.com/${{github.event.pull_request.user.login}}/AliceO2.git + git fetch --unshallow https://github.com/${{github.event.pull_request.user.login}}/AliceO2.git pull/${{ github.event.pull_request.number }}/head git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From 696f094cc160776804491f5939ea78df1d6b4b1e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 00:30:04 +0200 Subject: [PATCH 0642/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index f5ea0238371c3..40cecf3f25d4a 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -65,7 +65,7 @@ jobs: git show | cat echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc echo $ALIBUILD_GITHUB_TOKEN | wc - git fetch --unshallow https://github.com/${{github.event.pull_request.user.login}}/AliceO2.git pull/${{ github.event.pull_request.number }}/head + git fetch --unshallow https://github.com/AliceO2Group/AliceO2.git pull/${{ github.event.pull_request.number }}/head git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From 0c108f549694e44a4ede3d57dc04fe77383b94ac Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 00:38:26 +0200 Subject: [PATCH 0643/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 40cecf3f25d4a..413a18f539bf2 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -73,11 +73,13 @@ jobs: - name: pull-request uses: alisw/pull-request@master with: - source_branch: '${{ github.event.pull_request.user.login }}:alibot-cleanup-${{ github.event.pull_request.number }}' + source_branch: 'alibuild: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 }} + github_token: ${{ secrets.ALIBUILD_GITHUB_TOKEN }} pr_title: "Please consider the following formatting changes to #${{ github.event.pull_request.number }}" - pr_body: "Please consider the following formatting changes" + pr_body: | + This PR cannot be merged as is. You should either run clang-format yourself and update the pull request, or merge this PR in yours. + You can find AliceO2 coding conventions at http://github.com/AliceO2Group/CodingGuidelines. continue-on-error: true # We do not create PRs if the branch is not there. - name: Exit with error if the PR is not clean From c9bdebd6b6c6b55c82fb28bf9ceaadca7521505e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 01:20:58 +0200 Subject: [PATCH 0644/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 413a18f539bf2..ce62c9221f708 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -30,9 +30,6 @@ jobs: 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 @@ -56,6 +53,9 @@ jobs: git push --set-upstream origin :alibot-cleanup-${{ github.event.pull_request.number }} -f || true echo ::set-output name=clean::true else + git-clang-format-8 --commit $BASE_COMMIT \ + --diff --binary `which \ + clang-format-8` $COMMIT_FILES | patch -p1 echo "clang-format failed." echo "To reproduce it locally please run" echo -e "\tgit checkout $TRAVIS_BRANCH" From 8c57553ed3c340204d1c236f3d684d1ac6db109c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 01:24:35 +0200 Subject: [PATCH 0645/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index ce62c9221f708..d87611f4419ac 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -18,7 +18,7 @@ jobs: run: | set -x # We need to fetch the other commit. - git fetch --depth=1 origin ${{ github.event.pull_request.base.ref }} + git fetch origin ${{ github.event.pull_request.base.ref }} git fetch origin pull/${{ github.event.pull_request.number }}/head:${{ github.event.pull_request.head.ref }} # We create a new branch which we will use for the eventual PR. From e2c6ead67158408f9077446eb8c5af6cf3d32616 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 01:36:36 +0200 Subject: [PATCH 0646/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index d87611f4419ac..d6c21c589e3c0 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -50,7 +50,7 @@ jobs: 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 + git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git :alibot-cleanup-${{ github.event.pull_request.number }} -f || true echo ::set-output name=clean::true else git-clang-format-8 --commit $BASE_COMMIT \ @@ -63,8 +63,6 @@ jobs: echo "Opening a PR to your branch with the fixes" git commit -m "Please consider the following formatting changes" -a git show | cat - echo ${{ secrets.ALIBUILD_GITHUB_TOKEN }} | wc - echo $ALIBUILD_GITHUB_TOKEN | wc git fetch --unshallow https://github.com/AliceO2Group/AliceO2.git pull/${{ github.event.pull_request.number }}/head git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false From 55142b8d7dedd86497228b5af802ed11f00a7cfd Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Wed, 16 Sep 2020 08:24:03 +0200 Subject: [PATCH 0647/1751] [MCH] allow sending full HBframes in MCH custom raw page reader (#4286) This commit adds an option to the MCH CRU page reader that allows to buffer the pages belonging to the same orbit and send them in one single DPL message. The default behavior is to send each CRU page in a separate DPL message. --- .../Workflow/src/cru-page-reader-workflow.cxx | 136 +++++++++++------- 1 file changed, 81 insertions(+), 55 deletions(-) diff --git a/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx index c3e58b2fd19e2..3ce5b2ac6cb49 100644 --- a/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx +++ b/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx @@ -8,6 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// /// /// \file cru-page-reader-workflow.cxx /// \author Andrea Ferrero @@ -62,6 +63,7 @@ class FileReaderTask LOG(INFO) << "initializing file reader"; mFrameMax = ic.options().get<int>("nframes"); mPrint = ic.options().get<bool>("print"); + mFullHBF = ic.options().get<bool>("full-hbf"); auto inputFileName = ic.options().get<std::string>("infile"); mInputFile.open(inputFileName, std::ios::binary); @@ -82,80 +84,103 @@ class FileReaderTask { /// send one RDH block via DPL RDH rdh; + char* buf{nullptr}; + size_t bufSize{0}; - // stop if the required number of frames has been reached - if (mFrameMax == 0) { - pc.services().get<ControlService>().endOfStream(); - return; - } + while (true) { - if (mPrint) { - printf("mFrameMax: %d\n", mFrameMax); - } - if (mFrameMax > 0) { - mFrameMax -= 1; - } + // stop if the required number of frames has been reached + if (mFrameMax == 0) { + pc.services().get<ControlService>().endOfStream(); + return; + } - // read the next RDH, stop if no more data is available - mInputFile.read((char*)(&rdh), sizeof(RDH)); - if (mInputFile.fail()) { if (mPrint) { - std::cout << "end of file reached" << std::endl; + printf("mFrameMax: %d\n", mFrameMax); + } + if (mFrameMax > 0) { + mFrameMax -= 1; } - pc.services().get<ControlService>().endOfStream(); - return; // probably reached eof - } - // check that the RDH version is ok (only RDH versions from 4 to 6 are supported at the moment) - auto rdhVersion = o2::raw::RDHUtils::getVersion(rdh); - auto rdhHeaderSize = o2::raw::RDHUtils::getHeaderSize(rdh); - if (mPrint) { - std::cout << "header_version=" << (int)rdhVersion << std::endl; - } - if (rdhVersion < 4 || rdhVersion > 6 || rdhHeaderSize != 64) { - return; - } + // read the next RDH, stop if no more data is available + mInputFile.read((char*)(&rdh), sizeof(RDH)); + if (mInputFile.fail()) { + if (mPrint) { + std::cout << "end of file reached" << std::endl; + } + pc.services().get<ControlService>().endOfStream(); + return; // probably reached eof + } - // get the frame size from the RDH offsetToNext field - auto frameSize = o2::raw::RDHUtils::getOffsetToNext(rdh); - if (mPrint) { - std::cout << "frameSize=" << frameSize << std::endl; - } + // check that the RDH version is ok (only RDH versions from 4 to 6 are supported at the moment) + auto rdhVersion = o2::raw::RDHUtils::getVersion(rdh); + auto rdhHeaderSize = o2::raw::RDHUtils::getHeaderSize(rdh); + if (mPrint) { + std::cout << "header_version=" << (int)rdhVersion << std::endl; + } + if (rdhVersion < 4 || rdhVersion > 6 || rdhHeaderSize != 64) { + return; + } - // stop if the frame size is too small - if (frameSize < rdhHeaderSize) { - std::cout << mFrameMax << " - frameSize too small: " << frameSize << std::endl; - pc.services().get<ControlService>().endOfStream(); - return; - } + // get the frame size from the RDH offsetToNext field + auto frameSize = o2::raw::RDHUtils::getOffsetToNext(rdh); + if (mPrint) { + std::cout << "frameSize=" << frameSize << std::endl; + } - // allocate the output buffer - char* buf = (char*)malloc(frameSize); + // stop if the frame size is too small + if (frameSize < rdhHeaderSize) { + std::cout << mFrameMax << " - frameSize too small: " << frameSize << std::endl; + pc.services().get<ControlService>().endOfStream(); + return; + } - // copy the RDH into the output buffer - memcpy(buf, &rdh, rdhHeaderSize); + // allocate the output buffer + buf = (char*)realloc(buf, bufSize + frameSize); + if (buf == nullptr) { + std::cout << mFrameMax << " - failed to allocate buffer" << std::endl; + pc.services().get<ControlService>().endOfStream(); + return; + } - // read the frame payload into the output buffer - mInputFile.read(buf + rdhHeaderSize, frameSize - rdhHeaderSize); + // copy the RDH into the output buffer + memcpy(buf + bufSize, &rdh, rdhHeaderSize); - // stop if data cannot be read completely - if (mInputFile.fail()) { - if (mPrint) { - std::cout << "end of file reached" << std::endl; + // read the frame payload into the output buffer + mInputFile.read(buf + bufSize + rdhHeaderSize, frameSize - rdhHeaderSize); + + // stop if data cannot be read completely + if (mInputFile.fail()) { + if (mPrint) { + std::cout << "end of file reached" << std::endl; + } + free(buf); + pc.services().get<ControlService>().endOfStream(); + return; // probably reached eof } - free(buf); - pc.services().get<ControlService>().endOfStream(); - return; // probably reached eof - } - // create the output message - auto freefct = [](void* data, void* /*hint*/) { free(data); }; - pc.outputs().adoptChunk(Output{"ROUT", "RAWDATA"}, buf, frameSize, freefct, nullptr); + // increment the total buffer size + bufSize += frameSize; + + auto stopBit = o2::raw::RDHUtils::getStop(rdh); + + // when requesting full HBframes, the output message is sent only when the stop RDH is reached + // otherwise we send one message for each CRU page + if ((stopBit != 0) || (mFullHBF == false)) { + // create the output message + auto freefct = [](void* data, void* /*hint*/) { free(data); }; + pc.outputs().adoptChunk(Output{"ROUT", "RAWDATA"}, buf, bufSize, freefct, nullptr); + + // stop the readout loop + break; + } + } // while (true) } private: std::ifstream mInputFile{}; ///< input file int mFrameMax; ///< number of frames to process + bool mFullHBF; ///< send full HeartBeat frames bool mPrint = false; ///< print debug messages }; @@ -170,6 +195,7 @@ o2::framework::DataProcessorSpec getFileReaderSpec() AlgorithmSpec{adaptFromTask<FileReaderTask>()}, Options{{"infile", VariantType::String, "", {"input file name"}}, {"nframes", VariantType::Int, -1, {"number of frames to process"}}, + {"full-hbf", VariantType::Bool, false, {"send full HeartBeat frames"}}, {"print", VariantType::Bool, false, {"verbose output"}}}}; } // clang-format on From ba1b7217f2de2282f9e87582bc810fba06f26427 Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Wed, 16 Sep 2020 03:59:19 -0300 Subject: [PATCH 0648/1751] Strangeness tables + strangeness producer, consumer tasks (first commit) (#4316) --- .../DataModel/include/Analysis/Multiplicity.h | 4 +- .../include/Analysis/StrangenessTables.h | 85 +++++++++++++ Analysis/Tasks/CMakeLists.txt | 10 ++ Analysis/Tasks/lambdakzeroconsumer.cxx | 108 ++++++++++++++++ Analysis/Tasks/lambdakzeroproducer.cxx | 118 ++++++++++++++++++ Analysis/Tasks/multiplicityQa.cxx | 3 + Analysis/Tasks/multiplicityTable.cxx | 11 +- 7 files changed, 335 insertions(+), 4 deletions(-) create mode 100644 Analysis/DataModel/include/Analysis/StrangenessTables.h create mode 100644 Analysis/Tasks/lambdakzeroconsumer.cxx create mode 100644 Analysis/Tasks/lambdakzeroproducer.cxx diff --git a/Analysis/DataModel/include/Analysis/Multiplicity.h b/Analysis/DataModel/include/Analysis/Multiplicity.h index e1895b04a5989..004ad2c8e2976 100644 --- a/Analysis/DataModel/include/Analysis/Multiplicity.h +++ b/Analysis/DataModel/include/Analysis/Multiplicity.h @@ -21,8 +21,10 @@ DECLARE_SOA_COLUMN(MultV0C, multV0C, float); DECLARE_SOA_COLUMN(MultZNA, multZNA, float); DECLARE_SOA_COLUMN(MultZNC, multZNC, float); DECLARE_SOA_DYNAMIC_COLUMN(MultV0M, multV0M, [](float multV0A, float multV0C) -> float { return multV0A + multV0C; }); +DECLARE_SOA_COLUMN(MultTracklets, multTracklets, int); + } // namespace mult -DECLARE_SOA_TABLE(Mults, "AOD", "MULT", mult::MultV0A, mult::MultV0C, mult::MultZNA, mult::MultZNC, mult::MultV0M<mult::MultV0A, mult::MultV0C>); +DECLARE_SOA_TABLE(Mults, "AOD", "MULT", mult::MultV0A, mult::MultV0C, mult::MultZNA, mult::MultZNC, mult::MultV0M<mult::MultV0A, mult::MultV0C>, mult::MultTracklets); using Mult = Mults::iterator; } // namespace o2::aod diff --git a/Analysis/DataModel/include/Analysis/StrangenessTables.h b/Analysis/DataModel/include/Analysis/StrangenessTables.h new file mode 100644 index 0000000000000..2242c52095e9e --- /dev/null +++ b/Analysis/DataModel/include/Analysis/StrangenessTables.h @@ -0,0 +1,85 @@ +// 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_STRANGENESSTABLES_H_ +#define O2_ANALYSIS_STRANGENESSTABLES_H_ + +#include "Framework/AnalysisDataModel.h" +#include "Analysis/RecoDecay.h" + +namespace o2::aod +{ +namespace v0data +{ +//General V0 properties: position, momentum +DECLARE_SOA_COLUMN(PxPos, pxpos, float); +DECLARE_SOA_COLUMN(PyPos, pypos, float); +DECLARE_SOA_COLUMN(PzPos, pzpos, float); +DECLARE_SOA_COLUMN(PxNeg, pxneg, float); +DECLARE_SOA_COLUMN(PyNeg, pyneg, float); +DECLARE_SOA_COLUMN(PzNeg, pzneg, float); +DECLARE_SOA_COLUMN(X, x, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Z, z, float); + +//Saved from finding: DCAs +DECLARE_SOA_COLUMN(DCAV0Daughters, dcaV0daughters, float); +DECLARE_SOA_COLUMN(DCAPosToPV, dcapostopv, float); +DECLARE_SOA_COLUMN(DCANegToPV, dcanegtopv, float); + +//Derived expressions +//Momenta +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float pxpos, float pypos, float pxneg, float pyneg) { return RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg); }); + +//Length quantities +DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, [](float x, float y) { return RecoDecay::sqrtSumOfSquares(x, y); }); + +//CosPA +DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { return RecoDecay::CPA(array{pvX, pvY, pvZ}, array{X, Y, Z}, array{Px, Py, Pz}); }); + +//Calculated on the fly with mass assumption + dynamic tables +DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kPiPlus)}); }); +DECLARE_SOA_DYNAMIC_COLUMN(MAntiLambda, mAntiLambda, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kProton)}); }); +DECLARE_SOA_DYNAMIC_COLUMN(MK0Short, mK0Short, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kPiPlus)}); }); +} // namespace v0data + +namespace v0dataext +{ +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, 1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, 1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg); +} // namespace v0dataext + +DECLARE_SOA_TABLE(V0Data, "AOD", "V0DATA", + v0data::X, v0data::Y, v0data::Z, + v0data::PxPos, v0data::PyPos, v0data::PzPos, + v0data::PxNeg, v0data::PyNeg, v0data::PzNeg, + v0data::DCAV0Daughters, v0data::DCAPosToPV, v0data::DCANegToPV, + + //Dynamic columns + v0data::Pt<v0data::PxPos, v0data::PyPos, v0data::PxNeg, v0data::PyNeg>, + v0data::V0Radius<v0data::X, v0data::Y>, + v0data::V0CosPA<v0data::X, v0data::Y, v0data::Z, v0dataext::Px, v0dataext::Py, v0dataext::Pz>, + + //Invariant masses + v0data::MLambda<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>, + v0data::MAntiLambda<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>, + v0data::MK0Short<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>); + +using V0DataOrigin = V0Data; + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(V0DataExt, V0DataOrigin, "V0DATAEXT", + v0dataext::Px, v0dataext::Py, v0dataext::Pz); + +using V0DataFull = V0DataExt; + +} // namespace o2::aod + +#endif // O2_ANALYSIS_STRANGENESSTABLES_H_ diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index fb984848929b0..43d05a6f2bbd1 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -110,3 +110,13 @@ o2_add_dpl_workflow(run3-matcher SOURCES run3Matcher.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(lambdakzeroproducer + SOURCES lambdakzeroproducer + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(lambdakzeroconsumer + SOURCES lambdakzeroconsumer + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/Analysis/Tasks/lambdakzeroconsumer.cxx b/Analysis/Tasks/lambdakzeroconsumer.cxx new file mode 100644 index 0000000000000..6cf17b8f1cebd --- /dev/null +++ b/Analysis/Tasks/lambdakzeroconsumer.cxx @@ -0,0 +1,108 @@ +// 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 "ReconstructionDataFormats/Track.h" +#include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" +#include "Analysis/StrangenessTables.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" + +#include <TFile.h> +#include <TH2F.h> +#include <TProfile.h> +#include <TLorentzVector.h> +#include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> +#include <cmath> +#include <array> +#include <cstdlib> +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +struct lambdakzeroQA { + //Basic checks + OutputObj<TH1F> hMassK0Short{TH1F("hMassK0Short", "", 3000, 0.0, 3.0)}; + OutputObj<TH1F> hMassLambda{TH1F("hMassLambda", "", 3000, 0.0, 3.0)}; + OutputObj<TH1F> hMassAntiLambda{TH1F("hMassAntiLambda", "", 3000, 0.0, 3.0)}; + + OutputObj<TH1F> hV0Radius{TH1F("hV0Radius", "", 1000, 0.0, 100)}; + OutputObj<TH1F> hV0CosPA{TH1F("hV0CosPA", "", 1000, 0.95, 1.0)}; + OutputObj<TH1F> hDCAPosToPV{TH1F("hDCAPosToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCANegToPV{TH1F("hDCANegToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCAV0Dau{TH1F("hDCAV0Dau", "", 1000, 0.0, 10.0)}; + + void process(aod::Collision const& collision, soa::Join<aod::V0s, aod::V0DataExt> const& fullV0s) + { + for (auto& v0 : fullV0s) { + hMassLambda->Fill(v0.mLambda()); + hMassAntiLambda->Fill(v0.mAntiLambda()); + hMassK0Short->Fill(v0.mK0Short()); + + hV0Radius->Fill(v0.v0radius()); + hV0CosPA->Fill(v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + + hDCAPosToPV->Fill(v0.dcapostopv()); + hDCANegToPV->Fill(v0.dcanegtopv()); + hDCAV0Dau->Fill(v0.dcaV0daughters()); + } + } +}; + +struct lambdakzeroconsumer { + OutputObj<TH2F> h2dMassK0Short{TH2F("h2dMassK0Short", "", 200, 0, 10, 200, 0.450, 0.550)}; + OutputObj<TH2F> h2dMassLambda{TH2F("h2dMassLambda", "", 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; + OutputObj<TH2F> h2dMassAntiLambda{TH2F("h2dMassAntiLambda", "", 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; + + //Selection criteria + Configurable<double> v0cospa{"v0cospa", 0.995, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<float> dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<float> v0radius{"v0radius", 5.0, "v0radius"}; + + Filter preFilterV0 = aod::v0data::dcapostopv > dcapostopv&& + aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + + void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::V0s, aod::V0DataExt>> const& fullV0s) + { + for (auto& v0 : fullV0s) { + //FIXME: could not find out how to filter cosPA and radius variables (dynamic columns) + if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa) { + h2dMassLambda->Fill(v0.pt(), v0.mLambda()); + h2dMassAntiLambda->Fill(v0.pt(), v0.mAntiLambda()); + h2dMassK0Short->Fill(v0.pt(), v0.mK0Short()); + } + } + } +}; + +/// Extends the v0data table with expression columns +struct lambdakzeroinitializer { + Spawns<aod::V0DataExt> v0dataext; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<lambdakzeroconsumer>("lf-lambdakzeroconsumer"), + adaptAnalysisTask<lambdakzeroQA>("lf-lambdakzeroQA"), + adaptAnalysisTask<lambdakzeroinitializer>("lf-lambdakzeroinitializer")}; +} diff --git a/Analysis/Tasks/lambdakzeroproducer.cxx b/Analysis/Tasks/lambdakzeroproducer.cxx new file mode 100644 index 0000000000000..a56a3a6f2a31f --- /dev/null +++ b/Analysis/Tasks/lambdakzeroproducer.cxx @@ -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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Analysis/SecondaryVertexHF.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" +#include "Analysis/StrangenessTables.h" + +#include <TFile.h> +#include <TH2F.h> +#include <TProfile.h> +#include <TLorentzVector.h> +#include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> +#include <cmath> +#include <array> +#include <cstdlib> +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +/// Cascade builder task: rebuilds cascades +struct lambdakzeroproducer { + + Produces<aod::V0Data> v0data; + + OutputObj<TH1F> hEventCounter{TH1F("hEventCounter", "", 1, 0, 1)}; + OutputObj<TH1F> hCascCandidate{TH1F("hCascCandidate", "", 10, 0, 10)}; + + //Configurables + Configurable<double> d_bz{"d_bz", -5.0, "bz field"}; + Configurable<double> d_UseAbsDCA{"d_UseAbsDCA", kTRUE, "Use Abs DCAs"}; + + double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + double massKa = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); + double massPr = TDatabasePDG::Instance()->GetParticle(kProton)->Mass(); + + /// Extracts dca in the XY plane + /// \return dcaXY + template <typename T, typename U> + auto getdcaXY(const T& track, const U& coll) + { + //Calculate DCAs + auto sinAlpha = sin(track.alpha()); + auto cosAlpha = cos(track.alpha()); + auto globalX = track.x() * cosAlpha - track.y() * sinAlpha; + auto globalY = track.x() * sinAlpha + track.y() * cosAlpha; + return sqrt(pow((globalX - coll[0]), 2) + + pow((globalY - coll[1]), 2)); + } + + void process(aod::Collision const& collision, aod::V0s const& V0s, aod::FullTracks const& tracks) + { + //Define o2 fitter, 2-prong + o2::vertexing::DCAFitterN<2> fitter; + fitter.setBz(d_bz); + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(d_UseAbsDCA); + + hEventCounter->Fill(0.5); + std::array<float, 3> pVtx = {collision.posX(), collision.posY(), collision.posZ()}; + + for (auto& V0 : V0s) { + std::array<float, 3> pos = {0.}; + std::array<float, 3> pvec0 = {0.}; + std::array<float, 3> pvec1 = {0.}; + + hCascCandidate->Fill(0.5); + auto pTrack = getTrackParCov(V0.posTrack()); + auto nTrack = getTrackParCov(V0.negTrack()); + int nCand = fitter.process(pTrack, nTrack); + if (nCand != 0) { + fitter.propagateTracksToVertex(); + hCascCandidate->Fill(2.5); + const auto& vtx = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) + pos[i] = vtx[i]; + fitter.getTrack(0).getPxPyPzGlo(pvec0); + fitter.getTrack(1).getPxPyPzGlo(pvec1); + } + + v0data(pos[0], pos[1], pos[2], + pvec0[0], pvec0[1], pvec0[2], + pvec1[0], pvec1[1], pvec1[2], + fitter.getChi2AtPCACandidate(), + getdcaXY(V0.posTrack(), pVtx), + getdcaXY(V0.negTrack(), pVtx)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<lambdakzeroproducer>("lf-lambdakzeroproducer")}; +} diff --git a/Analysis/Tasks/multiplicityQa.cxx b/Analysis/Tasks/multiplicityQa.cxx index 43c30bbe518a4..0159a6e9e7e17 100644 --- a/Analysis/Tasks/multiplicityQa.cxx +++ b/Analysis/Tasks/multiplicityQa.cxx @@ -22,6 +22,8 @@ struct MultiplicityQaTask { OutputObj<TH1F> hMultZNA{TH1F("hMultZNA", "", 600, 0., 240000.)}; OutputObj<TH1F> hMultZNC{TH1F("hMultZNC", "", 600, 0., 240000.)}; + OutputObj<TProfile> hMultNtrackletsVsV0M{TProfile("hMultNtrackletsVsV0M", "", 50000, 0., 50000.)}; + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Mults>::iterator const& col) { if (!col.alias()[kINT7]) @@ -34,6 +36,7 @@ struct MultiplicityQaTask { hMultV0M->Fill(col.multV0M()); hMultZNA->Fill(col.multZNA()); hMultZNC->Fill(col.multZNC()); + hMultNtrackletsVsV0M->Fill(col.multV0M(), col.multTracklets()); } }; diff --git a/Analysis/Tasks/multiplicityTable.cxx b/Analysis/Tasks/multiplicityTable.cxx index 8cf85dc398e68..ed5187af5ebcd 100644 --- a/Analysis/Tasks/multiplicityTable.cxx +++ b/Analysis/Tasks/multiplicityTable.cxx @@ -37,7 +37,7 @@ struct MultiplicityTableTask { return dummy; } - void process(aod::Collision const& collision, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros) + void process(aod::Collision const& collision, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::Tracks const& tracks) { auto zdc = getZdc(collision.bc(), zdcs); auto vzero = getVZero(collision.bc(), vzeros); @@ -46,9 +46,14 @@ struct MultiplicityTableTask { float multZNA = zdc.energyCommonZNA(); float multZNC = zdc.energyCommonZNC(); - LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multZNA=%6.0f multZNC=%6.0f", multV0A, multV0C, multZNA, multZNC); + int multTracklets = 0; + for (auto& tr : tracks) + if (tr.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet) + multTracklets++; + + LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multZNA=%6.0f multZNC=%6.0f multTracklets=%i", multV0A, multV0C, multZNA, multZNC, multTracklets); // fill multiplicity columns - mult(multV0A, multV0C, multZNA, multZNC); + mult(multV0A, multV0C, multZNA, multZNC, multTracklets); } }; From d5e681c79dea241f8db1ceea3a4bc883dac93e91 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 3 Sep 2020 15:59:14 +0200 Subject: [PATCH 0649/1751] External trigger configuration moved to configurable params --- .../SimConfig/include/SimConfig/SimConfig.h | 4 -- Common/SimConfig/src/SimConfig.cxx | 6 --- Generators/CMakeLists.txt | 2 + .../include/Generators/TriggerExternalParam.h | 38 +++++++++++++++++++ Generators/share/external/trigger_mpi.C | 3 +- .../share/external/trigger_multiplicity.C | 3 +- Generators/src/GeneratorFactory.cxx | 8 +++- Generators/src/GeneratorsLinkDef.h | 2 + Generators/src/TriggerExternalParam.cxx | 14 +++++++ doc/DetectorSimulation.md | 10 ++--- .../Trigger_ImpactB_Pythia8/README.md | 2 +- .../Trigger_ImpactB_Pythia8/run.sh | 6 +-- 12 files changed, 72 insertions(+), 26 deletions(-) create mode 100644 Generators/include/Generators/TriggerExternalParam.h create mode 100644 Generators/src/TriggerExternalParam.cxx diff --git a/Common/SimConfig/include/SimConfig/SimConfig.h b/Common/SimConfig/include/SimConfig/SimConfig.h index 0ecd9c8dbdad4..6f0e1a70942c0 100644 --- a/Common/SimConfig/include/SimConfig/SimConfig.h +++ b/Common/SimConfig/include/SimConfig/SimConfig.h @@ -29,8 +29,6 @@ struct SimConfigData { std::string mExtKinFileName; // file name of external kinematics file (needed for ext kinematics generator) std::string mExtGenFileName; // file name containing the external generator configuration std::string mExtGenFuncName; // function call to retrieve the external generator configuration - std::string mExtTrgFileName; // file name containing the external trigger configuration - std::string mExtTrgFuncName; // function call to retrieve the external trigger configuration std::string mEmbedIntoFileName; // filename containing the reference events to be used for the embedding unsigned int mStartEvent; // index of first event to be taken float mBMax; // maximum for impact parameter sampling @@ -102,8 +100,6 @@ class SimConfig std::string getExtKinematicsFileName() const { return mConfigData.mExtKinFileName; } std::string getExtGeneratorFileName() const { return mConfigData.mExtGenFileName; } std::string getExtGeneratorFuncName() const { return mConfigData.mExtGenFuncName; } - std::string getExtTriggerFileName() const { return mConfigData.mExtTrgFileName; } - std::string getExtTriggerFuncName() const { return mConfigData.mExtTrgFuncName; } std::string getEmbedIntoFileName() const { return mConfigData.mEmbedIntoFileName; } unsigned int getStartEvent() const { return mConfigData.mStartEvent; } float getBMax() const { return mConfigData.mBMax; } diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index 5746a40462c82..9c12caf3f1e6b 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -35,10 +35,6 @@ void SimConfig::initOptions(boost::program_options::options_description& options "name of .C file with definition of external event generator")( "extGenFunc", bpo::value<std::string>()->default_value(""), "function call to load the definition of external event generator")( - "extTrgFile", bpo::value<std::string>()->default_value("exttrg.C"), - "name of .C file with definition of external event generator trigger")( - "extTrgFunc", bpo::value<std::string>()->default_value(""), - "function call to load the definition of external event generator trigger")( "embedIntoFile", bpo::value<std::string>()->default_value(""), "filename containing the reference events to be used for the embedding")( "bMax,b", bpo::value<float>()->default_value(0.), "maximum value for impact parameter sampling (when applicable)")( @@ -100,8 +96,6 @@ bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& mConfigData.mExtKinFileName = vm["extKinFile"].as<std::string>(); mConfigData.mExtGenFileName = vm["extGenFile"].as<std::string>(); mConfigData.mExtGenFuncName = vm["extGenFunc"].as<std::string>(); - mConfigData.mExtTrgFileName = vm["extTrgFile"].as<std::string>(); - mConfigData.mExtTrgFuncName = vm["extTrgFunc"].as<std::string>(); mConfigData.mEmbedIntoFileName = vm["embedIntoFile"].as<std::string>(); mConfigData.mStartEvent = vm["startEvent"].as<unsigned int>(); mConfigData.mBMax = vm["bMax"].as<float>(); diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index 0fca05335777c..41c6d94cc00cf 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -29,6 +29,7 @@ o2_add_library(Generators src/PDG.cxx src/PrimaryGenerator.cxx src/InteractionDiamondParam.cxx + src/TriggerExternalParam.cxx src/TriggerParticleParam.cxx src/BoxGunParam.cxx src/QEDGenParam.cxx @@ -68,6 +69,7 @@ set(headers include/Generators/PDG.h include/Generators/PrimaryGenerator.h include/Generators/InteractionDiamondParam.h + include/Generators/TriggerExternalParam.h include/Generators/TriggerParticleParam.h include/Generators/ConfigurationMacroHelper.h include/Generators/BoxGunParam.h diff --git a/Generators/include/Generators/TriggerExternalParam.h b/Generators/include/Generators/TriggerExternalParam.h new file mode 100644 index 0000000000000..2360ca16f36c7 --- /dev/null +++ b/Generators/include/Generators/TriggerExternalParam.h @@ -0,0 +1,38 @@ +// 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 R+Preghenella - September 2020 + +#ifndef ALICEO2_EVENTGEN_TRIGGEREXTERNALPARAM_H_ +#define ALICEO2_EVENTGEN_TRIGGEREXTERNALPARAM_H_ + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace eventgen +{ + +/** + ** a parameter class/struct to keep the settings of + ** the event-generator external trigger and + ** allow the user to modify them + **/ +struct TriggerExternalParam : public o2::conf::ConfigurableParamHelper<TriggerExternalParam> { + std::string fileName = ""; + std::string funcName = ""; + O2ParamDef(TriggerExternalParam, "TriggerExternal"); +}; + +} // end namespace eventgen +} // end namespace o2 + +#endif // ALICEO2_EVENTGEN_TRIGGEREXTERNALPARAM_H_ diff --git a/Generators/share/external/trigger_mpi.C b/Generators/share/external/trigger_mpi.C index e4872370796ca..c2feff38ed16d 100644 --- a/Generators/share/external/trigger_mpi.C +++ b/Generators/share/external/trigger_mpi.C @@ -1,7 +1,6 @@ // MPI trigger // -// usage: o2sim --trigger external --extTrgFile trigger_mpi.C -// options: --extTrgFunc "trigger_mpi()" +// usage: o2sim --trigger external --configKeyValues 'TriggerExternal.fileName=trigger_mpi.C;TriggerExternal.funcName="trigger_mpi()"' // /// \author R+Preghenella - February 2020 diff --git a/Generators/share/external/trigger_multiplicity.C b/Generators/share/external/trigger_multiplicity.C index 045fc676e0ad6..94336d43d80d5 100644 --- a/Generators/share/external/trigger_multiplicity.C +++ b/Generators/share/external/trigger_multiplicity.C @@ -1,7 +1,6 @@ // multiplicity trigger // -// usage: o2sim --trigger external --extTrgFile trigger_multiplicity.C -// options: --extTrgFunc "trigger_multiplicity(-0.8, 0.8, 100)" +// usage: o2sim --trigger external --configKeyValues 'TriggerExternal.fileName=trigger_multiplicity.C;TriggerExternal.funcName="trigger_multiplicity(-0.8, 0.8, 100)"' // /// \author R+Preghenella - February 2020 diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index 82f4206b8a3b7..4f3b9e2981362 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -32,6 +32,7 @@ #endif #include <Generators/BoxGunParam.h> #include <Generators/TriggerParticle.h> +#include <Generators/TriggerExternalParam.h> #include <Generators/TriggerParticleParam.h> #include "Generators/ConfigurationMacroHelper.h" @@ -227,8 +228,11 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair trigger = TriggerParticle(TriggerParticleParam::Instance()); } else if (trgconfig.compare("external") == 0) { // external trigger via configuration macro - auto external_trigger_filename = conf.getExtTriggerFileName(); - auto external_trigger_func = conf.getExtTriggerFuncName(); + auto& params = TriggerExternalParam::Instance(); + LOG(INFO) << "Setting up external trigger with following parameters"; + LOG(INFO) << params; + auto external_trigger_filename = params.fileName; + auto external_trigger_func = params.funcName; trigger = GetFromMacro<o2::eventgen::Trigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::Trigger", "trigger"); if (!trigger) { LOG(INFO) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type" << std::endl; diff --git a/Generators/src/GeneratorsLinkDef.h b/Generators/src/GeneratorsLinkDef.h index 93f83e72beb59..0688f7ff235ff 100644 --- a/Generators/src/GeneratorsLinkDef.h +++ b/Generators/src/GeneratorsLinkDef.h @@ -52,6 +52,8 @@ #pragma link C++ enum o2::eventgen::EVertexDistribution; #pragma link C++ class o2::eventgen::InteractionDiamondParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::eventgen::InteractionDiamondParam > +; +#pragma link C++ class o2::eventgen::TriggerExternalParam + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::eventgen::TriggerExternalParam> + ; #pragma link C++ class o2::eventgen::TriggerParticleParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::eventgen::TriggerParticleParam > +; #pragma link C++ class o2::eventgen::BoxGunParam + ; diff --git a/Generators/src/TriggerExternalParam.cxx b/Generators/src/TriggerExternalParam.cxx new file mode 100644 index 0000000000000..0c164bbe06c1d --- /dev/null +++ b/Generators/src/TriggerExternalParam.cxx @@ -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. + +/// \author R+Preghenella - September 2020 + +#include "Generators/TriggerExternalParam.h" +O2ParamImpl(o2::eventgen::TriggerExternalParam); diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index 04befd2dd2d99..13c2113310420 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -187,7 +187,7 @@ o2-sim -g pythia8 -t particle --configKeyValues "TriggerParticle.pdg=333;Trigger Custom triggers can also be constructed by the user to provide unlimited flexibility in the trigger needs. An external trigger function can be specified via command line arguments ``` -o2-sim -g pythia8 -t external --extTrgFile path_to_trigger_macro.C --extTrgFunc "the_function(some, parameters)" +o2-sim -g pythia8 -t external --configKeyValues 'TriggerExternal.fileName=path_to_trigger_macro.C;TriggerExternal.funcName="the_function(some, parameters)"' ``` The function must comply with a simple protocol and return a lambda function defined as follows ``` @@ -205,7 +205,7 @@ To allow users to define triggers that go beyond the particle stack generated by This allows the user to go deep into the core of the event generator, whenever this is possible. For this reason, this is called a 'DeepTrigger'. A 'DeepTrigger' is attached to the simulation in the same way as a normal trigger ``` -o2-sim -g pythia8 -t external --extTrgFile path_to_deep_trigger_macro.C --extTrgFunc "the_deep_function(some, parameters)" +o2-sim -g pythia8 -t external --configKeyValues 'TriggerExternal.fileName=path_to_deep_trigger_macro.C;TriggerExternal.funcName="the_deep_function(some, parameters)"' ``` In this case the function must comply with a similar, but different protocol than before and return a lambda function defined as follows ``` o2::eventgen::DeepTrigger the_deep_function() @@ -227,8 +227,7 @@ Deep triggers is just a name to a new functionality that allows the user to defi Here is an example of a deep trigger implementation in Pythia8. ``` -// usage: o2sim --trigger external --extTrgFile trigger_mpi.C -// options: --extTrgFunc "trigger_mpi()" +// usage: o2sim --trigger external --configKeyValues 'TriggerExternal.fileName=trigger_mpi.C;TriggerExternal.funcName="trigger_mpi()"' #include "Generators/Trigger.h" #include "Pythia8/Pythia.h" @@ -294,8 +293,7 @@ Pythia8::UserHooks* A new Pythia6 interface is provided via GeneratorPythia6. This complies with the o2::eventgen::Generator protocol, and hence the user is allowed to use all the trigger functionalities. The class can also be used for DeepTriggers as this modified macro shows. ``` -// usage: o2sim --trigger external --extTrgFile trigger_mpi.C -// options: --extTrgFunc "trigger_mpi()" +// usage: o2sim --trigger external --configKeyValues "TriggerExternal.fileName=trigger_mpi.C;TriggerExternal.funcName="trigger_mpi()"' #include "Generators/Trigger.h" #include "Pythia8/Pythia.h" diff --git a/run/SimExamples/Trigger_ImpactB_Pythia8/README.md b/run/SimExamples/Trigger_ImpactB_Pythia8/README.md index b72f2597ce9cb..3137c51b367d2 100644 --- a/run/SimExamples/Trigger_ImpactB_Pythia8/README.md +++ b/run/SimExamples/Trigger_ImpactB_Pythia8/README.md @@ -9,7 +9,7 @@ The trigger selection defines impact parameters to be accepted according to a mi The definition and configuration of the external `DeepTrigger` is performed by the function `trigger_impactb_pythia8(double bMin = 0., double bMax = 20.)` defined in the macro `trigger_impactb_pythia8.macro`. -The macro file is specified via the argument of `--extTrgFile` whereas the specific function call to retrieve the configuration is specified via the argument of `--extTrgFunc`. +The macro file and function names are specified via `--configKeyValues` setting `TriggerExternal.fileName` and `TriggerExternal.funcName`, respectively. # WARNING Using a trigger is not always the most efficient way to deal with event generation. diff --git a/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh b/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh index 81f390fdda95c..e1d69bca132ab 100755 --- a/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh +++ b/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh @@ -14,12 +14,12 @@ # the function `trigger_impactb_pythia8(double bMin = 0., double bMax = 20.)` # defined in the macro `trigger_impactb_pythia8.macro`. -# The macro file is specified via the argument of `--extTrgFile` whereas the specific -# function call to retrieve the configuration is specified via the argument of `--extTrgFunc`. +# The macro file and function names are specified via `--configKeyValues` setting +# `TriggerExternal.fileName` and `TriggerExternal.funcName`, respectively. set -x NEV=10 BMIN=15. BMAX=20. -o2-sim -j 20 -n ${NEV} -g pythia8hi -m PIPE ITS TPC --trigger external --extTrgFile trigger_impactb_pythia8.macro --extTrgFunc "trigger_impactb_pythia8(${BMIN}, ${BMAX})" +o2-sim -j 20 -n ${NEV} -g pythia8hi -m PIPE ITS TPC --trigger external --configKeyValues 'TriggerExternal.fileName=trigger_impactb_pythia8.macro;TriggerExternal.funcName="trigger_impactb_pythia8(${BMIN}, ${BMAX})"' From 7a967a6be15e7053c12cf2a9580ce0d8af3ca4ef Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 3 Sep 2020 17:32:59 +0200 Subject: [PATCH 0650/1751] External generator configuration moved to configurable params --- .../SimConfig/include/SimConfig/SimConfig.h | 4 -- Common/SimConfig/src/SimConfig.cxx | 6 --- Generators/CMakeLists.txt | 2 + .../Generators/GeneratorExternalParam.h | 38 +++++++++++++++++++ Generators/share/external/QEDLoader.C | 2 +- Generators/share/external/QEDepem.C | 2 +- Generators/share/external/README.md | 2 +- Generators/share/external/hijing.C | 3 +- Generators/share/external/pythia6.C | 3 +- Generators/src/GeneratorExternalParam.cxx | 14 +++++++ Generators/src/GeneratorFactory.cxx | 10 +++-- Generators/src/GeneratorsLinkDef.h | 1 + doc/DetectorSimulation.md | 8 ++-- prodtests/produce_QEDhits.sh | 2 +- run/SimExamples/Adaptive_Pythia8/README.md | 2 +- .../Adaptive_Pythia8/adaptive_pythia8.macro | 7 ++-- run/SimExamples/Adaptive_Pythia8/run.sh | 4 +- run/SimExamples/AliRoot_AMPT/README.md | 2 +- .../AliRoot_AMPT/aliroot_ampt.macro | 3 +- run/SimExamples/AliRoot_AMPT/run.sh | 4 +- run/SimExamples/AliRoot_Hijing/README.md | 2 +- .../AliRoot_Hijing/aliroot_hijing.macro | 3 +- run/SimExamples/AliRoot_Hijing/run.sh | 9 ++--- run/SimExamples/HF_Embedding_Pythia8/run.sh | 8 ++-- run/SimExamples/Signal_ImpactB/README.md | 2 +- run/SimExamples/Signal_ImpactB/run.sh | 4 +- .../Signal_ImpactB/signal_impactb.macro | 3 +- .../Trigger_ImpactB_Pythia8/run.sh | 2 +- 28 files changed, 97 insertions(+), 55 deletions(-) create mode 100644 Generators/include/Generators/GeneratorExternalParam.h create mode 100644 Generators/src/GeneratorExternalParam.cxx diff --git a/Common/SimConfig/include/SimConfig/SimConfig.h b/Common/SimConfig/include/SimConfig/SimConfig.h index 6f0e1a70942c0..f510a91abcad1 100644 --- a/Common/SimConfig/include/SimConfig/SimConfig.h +++ b/Common/SimConfig/include/SimConfig/SimConfig.h @@ -27,8 +27,6 @@ struct SimConfigData { std::string mTrigger; // chosen VMC generator trigger unsigned int mNEvents; // number of events to be simulated std::string mExtKinFileName; // file name of external kinematics file (needed for ext kinematics generator) - std::string mExtGenFileName; // file name containing the external generator configuration - std::string mExtGenFuncName; // function call to retrieve the external generator configuration std::string mEmbedIntoFileName; // filename containing the reference events to be used for the embedding unsigned int mStartEvent; // index of first event to be taken float mBMax; // maximum for impact parameter sampling @@ -98,8 +96,6 @@ class SimConfig unsigned int getNEvents() const { return mConfigData.mNEvents; } std::string getExtKinematicsFileName() const { return mConfigData.mExtKinFileName; } - std::string getExtGeneratorFileName() const { return mConfigData.mExtGenFileName; } - std::string getExtGeneratorFuncName() const { return mConfigData.mExtGenFuncName; } std::string getEmbedIntoFileName() const { return mConfigData.mEmbedIntoFileName; } unsigned int getStartEvent() const { return mConfigData.mStartEvent; } float getBMax() const { return mConfigData.mBMax; } diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index 9c12caf3f1e6b..6da06aff849a1 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -31,10 +31,6 @@ void SimConfig::initOptions(boost::program_options::options_description& options "startEvent", bpo::value<unsigned int>()->default_value(0), "index of first event to be used (when applicable)")( "extKinFile", bpo::value<std::string>()->default_value("Kinematics.root"), "name of kinematics file for event generator from file (when applicable)")( - "extGenFile", bpo::value<std::string>()->default_value("extgen.C"), - "name of .C file with definition of external event generator")( - "extGenFunc", bpo::value<std::string>()->default_value(""), - "function call to load the definition of external event generator")( "embedIntoFile", bpo::value<std::string>()->default_value(""), "filename containing the reference events to be used for the embedding")( "bMax,b", bpo::value<float>()->default_value(0.), "maximum value for impact parameter sampling (when applicable)")( @@ -94,8 +90,6 @@ bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& mConfigData.mTrigger = vm["trigger"].as<std::string>(); mConfigData.mNEvents = vm["nEvents"].as<unsigned int>(); mConfigData.mExtKinFileName = vm["extKinFile"].as<std::string>(); - mConfigData.mExtGenFileName = vm["extGenFile"].as<std::string>(); - mConfigData.mExtGenFuncName = vm["extGenFunc"].as<std::string>(); mConfigData.mEmbedIntoFileName = vm["embedIntoFile"].as<std::string>(); mConfigData.mStartEvent = vm["startEvent"].as<unsigned int>(); mConfigData.mBMax = vm["bMax"].as<float>(); diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index 41c6d94cc00cf..7985ed8283501 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -25,6 +25,7 @@ o2_add_library(Generators src/Trigger.cxx src/TriggerParticle.cxx src/GeneratorTGenerator.cxx + src/GeneratorExternalParam.cxx src/GeneratorFromFile.cxx src/PDG.cxx src/PrimaryGenerator.cxx @@ -65,6 +66,7 @@ set(headers include/Generators/Trigger.h include/Generators/TriggerParticle.h include/Generators/GeneratorTGenerator.h + include/Generators/GeneratorExternalParam.h include/Generators/GeneratorFromFile.h include/Generators/PDG.h include/Generators/PrimaryGenerator.h diff --git a/Generators/include/Generators/GeneratorExternalParam.h b/Generators/include/Generators/GeneratorExternalParam.h new file mode 100644 index 0000000000000..1fa2fa860cae1 --- /dev/null +++ b/Generators/include/Generators/GeneratorExternalParam.h @@ -0,0 +1,38 @@ +// 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 R+Preghenella - September 2020 + +#ifndef ALICEO2_EVENTGEN_GENERATOREXTERNALPARAM_H_ +#define ALICEO2_EVENTGEN_GENERATOREXTERNALPARAM_H_ + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace eventgen +{ + +/** + ** a parameter class/struct to keep the settings of + ** the external event-generator and + ** allow the user to modify them + **/ +struct GeneratorExternalParam : public o2::conf::ConfigurableParamHelper<GeneratorExternalParam> { + std::string fileName = ""; + std::string funcName = ""; + O2ParamDef(GeneratorExternalParam, "GeneratorExternal"); +}; + +} // end namespace eventgen +} // end namespace o2 + +#endif // ALICEO2_EVENTGEN_GENERATOREXTERNALPARAM_H_ diff --git a/Generators/share/external/QEDLoader.C b/Generators/share/external/QEDLoader.C index c35986b6f6d38..3ea7297490a7a 100644 --- a/Generators/share/external/QEDLoader.C +++ b/Generators/share/external/QEDLoader.C @@ -9,7 +9,7 @@ // 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 T0 MFT --noemptyevents -g extgen --extGenFile QEDloader.C +//< o2-sim -n10000 -m PIPE ITS T0 MFT --noemptyevents -g external --configKeyValues "GeneratorExternal.fileName=QEDloader.C" #include <FairLogger.h> FairGenerator* fg = nullptr; diff --git a/Generators/share/external/QEDepem.C b/Generators/share/external/QEDepem.C index ddb9efa7ca3b9..8c218ffdeb28f 100644 --- a/Generators/share/external/QEDepem.C +++ b/Generators/share/external/QEDepem.C @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. //< Macro to run QED background generator, us it as e.g. -//< o2-sim -n10000 -m PIPE ITS T0 MFT --noemptyevents -g extgen --extGenFile QEDloader.C +//< o2-sim -n10000 -m PIPE ITS T0 MFT --noemptyevents -g external --configKeyValues "GeneratorExternal.fileName=QEDloader.C" R__LOAD_LIBRARY(libTEPEMGEN.so) diff --git a/Generators/share/external/README.md b/Generators/share/external/README.md index 959f4551b5c3d..9a52ce1c01f33 100644 --- a/Generators/share/external/README.md +++ b/Generators/share/external/README.md @@ -13,7 +13,7 @@ - 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. `` -o2-sim -n 1000 -m PIPE ITS -g extgen --extGenFile $O2_ROOT/share/Generators/external/QEDLoader.C --configKeyValues 'QEDGenParam.yMin=-3;QEDGenParam.ptMin=0.001' +o2-sim -n 1000 -m PIPE ITS -g external --configKeyValues 'GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-3;QEDGenParam.ptMin=0.001' `` The x-section of the process depends on the applied cuts, it is calculated on the fly and stored in the ``qedgenparam.ini`` file. diff --git a/Generators/share/external/hijing.C b/Generators/share/external/hijing.C index 393a81b543cbf..cfd13ef384a80 100644 --- a/Generators/share/external/hijing.C +++ b/Generators/share/external/hijing.C @@ -1,6 +1,5 @@ // configures a AliGenHijing class from AliRoot -// usage: o2sim -g extgen --extGenFile hijing.C -// options: --extGenFunc hijing(5020., 0., 20.) +// usage: o2sim -g external --configKeyValues 'GeneratorExternal.fileName=hijing.C;GeneratorExternal.funcName="hijing(5020., 0., 20.)"' /// \author R+Preghenella - October 2018 diff --git a/Generators/share/external/pythia6.C b/Generators/share/external/pythia6.C index e5c012dd51e81..1ba993a1e7eb7 100644 --- a/Generators/share/external/pythia6.C +++ b/Generators/share/external/pythia6.C @@ -1,6 +1,5 @@ // configures a TPythia6 class -// usage: o2sim -g extgen --extGenFile pythia6.C -// options: --extGenFunc pythia6(14000., "pythia.settings") +// usage: o2sim -g external --configKeyValues 'GeneratorExternal.fileName=pythia6.C;GeneratorExternal.funcName="pythia6(14000., "pythia.settings")"' /// \author R+Preghenella - October 2018 diff --git a/Generators/src/GeneratorExternalParam.cxx b/Generators/src/GeneratorExternalParam.cxx new file mode 100644 index 0000000000000..dbed9392540a4 --- /dev/null +++ b/Generators/src/GeneratorExternalParam.cxx @@ -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. + +/// \author R+Preghenella - September 2020 + +#include "Generators/GeneratorExternalParam.h" +O2ParamImpl(o2::eventgen::GeneratorExternalParam); diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index 4f3b9e2981362..bc74f9f0983fb 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -26,6 +26,7 @@ #include <Generators/GeneratorPythia8Param.h> #endif #include <Generators/GeneratorTGenerator.h> +#include <Generators/GeneratorExternalParam.h> #ifdef GENERATORS_WITH_HEPMC3 #include <Generators/GeneratorHepMC.h> #include <Generators/GeneratorHepMCParam.h> @@ -191,10 +192,13 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair auto py8 = makePythia8Gen(py8config); primGen->AddGenerator(py8); #endif - } else if (genconfig.compare("extgen") == 0) { + } else if (genconfig.compare("external") == 0 || genconfig.compare("extgen") == 0) { // external generator via configuration macro - auto extgen_filename = conf.getExtGeneratorFileName(); - auto extgen_func = conf.getExtGeneratorFuncName(); + auto& params = GeneratorExternalParam::Instance(); + LOG(INFO) << "Setting up external generator with following parameters"; + LOG(INFO) << params; + auto extgen_filename = params.fileName; + auto extgen_func = params.funcName; auto extgen = GetFromMacro<FairGenerator*>(extgen_filename, extgen_func, "FairGenerator*", "extgen"); if (!extgen) { LOG(FATAL) << "Failed to retrieve \'extgen\': problem with configuration "; diff --git a/Generators/src/GeneratorsLinkDef.h b/Generators/src/GeneratorsLinkDef.h index 0688f7ff235ff..25632f549ff8d 100644 --- a/Generators/src/GeneratorsLinkDef.h +++ b/Generators/src/GeneratorsLinkDef.h @@ -27,6 +27,7 @@ #pragma link C++ class o2::eventgen::Generator + ; #pragma link C++ class o2::eventgen::GeneratorTGenerator + ; +#pragma link C++ class o2::eventgen::GeneratorExternalParam + ; #ifdef GENERATORS_WITH_HEPMC3 #pragma link C++ class o2::eventgen::GeneratorHepMC + ; #pragma link C++ class o2::eventgen::GeneratorHepMCParam + ; diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index 13c2113310420..08946ecf0aae8 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -132,15 +132,15 @@ o2-sim -m PIPE ITS MFT -g pythia8 -n 50 You may contribute to the documentation by asking a question #### 1. **How can I interface an event generator from ALIROOT**? -In order to access event generators from ALIROOT, such as `THijing` or `TPyhtia6`, you may use the `-g extgen` command line option followed by a ROOT macro setting up the event +In order to access event generators from ALIROOT, such as `THijing` or `TPyhtia6`, you may use the `-g external` command line option followed by a ROOT macro setting up the event generator. Examples thereof are available in the installation directory `$O2_ROOT/share/Generators/external`. For example, in order to simulate with 10 Pythia6 events, the following command can be run: ``` -o2-sim -n 10 -g extgen --extGenFile $O2_ROOT/share/Generators/external/pythia6.C +o2-sim -n 10 -g external --configKeyValues 'GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/pythia6.C' ``` -Macro arguments can be passed via -`--extGenFunc pythia6(14000., "pythia.settings")`. +Macro arguments can be passed setting `GeneratorExternal.funcName` +`GeneratorExternal.funcName=pythia6(14000., "pythia.settings")`. Users may write there own macros in order to customize to their needs. diff --git a/prodtests/produce_QEDhits.sh b/prodtests/produce_QEDhits.sh index bdab7189b0829..d737f1b2d7a4d 100755 --- a/prodtests/produce_QEDhits.sh +++ b/prodtests/produce_QEDhits.sh @@ -26,6 +26,6 @@ echo "Running simulation for $nev $collSyst events with $gener generator and eng # we only need passive material and QED sensitive detectors close to beampipe # set -x -o2-sim -j 8 -m PIPE ABSO DIPO SHIL ITS FT0 MFT -n"$nev" -e "$engine" --noemptyevents -g extgen --extGenFile ${O2_ROOT}/share/Generators/external/QEDLoader.C --configKeyValues "SimCutParams.maxRTracking=300" -o o2simqed +o2-sim -j 8 -m PIPE ABSO DIPO SHIL ITS FT0 MFT -n"$nev" -e "$engine" --noemptyevents -g external --configKeyValues "GeneratorExternal.fileName=${O2_ROOT}/share/Generators/external/QEDLoader.C;SimCutParams.maxRTracking=300" -o o2simqed root -q -b -l ${O2_ROOT}/share/macro/analyzeHits.C\(\"o2simqed\"\) > QEDhitstats.log diff --git a/run/SimExamples/Adaptive_Pythia8/README.md b/run/SimExamples/Adaptive_Pythia8/README.md index b605ff80e2aef..eb97a422993c6 100644 --- a/run/SimExamples/Adaptive_Pythia8/README.md +++ b/run/SimExamples/Adaptive_Pythia8/README.md @@ -11,4 +11,4 @@ Pythia8 events are generated according to the configuration given in the file `a The settings are as such that Pythia8 is initialised using the `pythia8_inel.cfg` configuration file. The customisation allows the generator to receive and react to a notification that signals the embedding status of the simulation, giving the header of the background event for determination of the subsequent actions. In this case, the number of pythia8 events to be embedded is calculated according to a formula that uses the number of primary particles of the background events. -The macro file is specified via the argument of `--extGenFile` whereas the specific function call to retrieve the configuration and define the formula is specified via the argument of `--extGenFunc`. +The macro file is specified via `--configKeyValues` setting `GeneratorExternal.fileName` whereas the specific function call to retrieve the configuration and define the formula is specified via `GeneratorExternal.funcName`. diff --git a/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro b/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro index 170095da3ca34..f0088e2f58313 100644 --- a/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro +++ b/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro @@ -3,15 +3,14 @@ // Example of an implementation of an external event generator // that is used and adapts it behavior in an embedding scenario. // -// usage: o2sim -g extgen --extGenFile adaptive_pythia8.C -// options: --extGenFunc "adaptive_pythia8(\"0.001 * x\") +// usage: o2sim -g external --configKeyValues 'GeneratorExternal.fileName=adaptive_pythia8.C;GeneratorExternal.funcName="adaptive_pythia8(\"0.001 * x\")"' using namespace o2::eventgen; class Adaptive_Pythia8 : public GeneratorPythia8 { public: - Adaptive_Pythia8(char *formula = "0.01 * x") : + Adaptive_Pythia8(const char *formula = "0.01 * x") : GeneratorPythia8(), mFormula("formula", formula) { }; ~Adaptive_Pythia8() = default; @@ -43,7 +42,7 @@ private: }; FairGenerator* -adaptive_pythia8(char *formula = "0.01 * x") +adaptive_pythia8(const char *formula = "0.01 * x") { std::cout << " --- adaptive_pythia8 initialising with formula: " << formula << std::endl; auto py8 = new Adaptive_Pythia8(formula); diff --git a/run/SimExamples/Adaptive_Pythia8/run.sh b/run/SimExamples/Adaptive_Pythia8/run.sh index 47b41a74db602..9e01e36647a4b 100755 --- a/run/SimExamples/Adaptive_Pythia8/run.sh +++ b/run/SimExamples/Adaptive_Pythia8/run.sh @@ -22,6 +22,6 @@ o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS -o bkg --configKeyValues \ # of subsequent actions. In this case, the number of pythia8 events to be embedded is calculated according # to a formula that uses the number of primary particles of the background events NSGN=10 -o2-sim -j 20 -n ${NSGN} extgen -m PIPE ITS \ - -g extgen --extGenFile pythia8_adaptive.macro --extGenFunc "pythia8_adaptive(\"0.002 * x\")" \ +o2-sim -j 20 -n ${NSGN} -m PIPE ITS \ + -g external --configKeyValues 'GeneratorExternal.fileName=adaptive_pythia8.macro;GeneratorExternal.funcName=adaptive_pythia8("0.002 * x")' \ --embedIntoFile bkg_Kine.root -o sgn > logsgn 2>&1 diff --git a/run/SimExamples/AliRoot_AMPT/README.md b/run/SimExamples/AliRoot_AMPT/README.md index bab945e21c0ac..b413f6eeffe11 100644 --- a/run/SimExamples/AliRoot_AMPT/README.md +++ b/run/SimExamples/AliRoot_AMPT/README.md @@ -7,7 +7,7 @@ A wrapper class AliRoot_AMPT is defined to keep the AliGenAmpt instance and conf It also provides methods to set a random event plane before event generation and to update the event header. The overall setup is steered by the function `ampt(double energy = 5020., double bMin = 0., double bMax = 20.)` defined in the macro `aliroot_ampt.macro`. -The macro file is specified via the argument of `--extGenFile` whereas the specific function call to retrieven the configuration is specified via the argument of `--extGenFunc`. +The macro file is specified via `--configKeyValues` setting `GeneratorExternal.fileName` whereas the specific function call to retrieven the configuration is specified via `GeneratorExternal.funcName`. # IMPORTANT To run this example you need to load an AliRoot package compatible with the O2. diff --git a/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro b/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro index 1a26f68cd3410..0d231d1decdc4 100644 --- a/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro +++ b/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro @@ -1,6 +1,5 @@ // configures a AliGenAmpt class from AliRoot -// usage: o2sim -g extgen --extGenFile aliroot_ampt.macro -// options: --extGenFunc aliroot_ampt(5020., 0., 20.) +// usage: o2sim -g external --configKeyValues 'GeneratorExternal.fileName=aliroot_ampt.macro;GeneratorExternal.funcName="aliroot_ampt(5020., 0., 20.)"' /// \author R+Preghenella - October 2018 diff --git a/run/SimExamples/AliRoot_AMPT/run.sh b/run/SimExamples/AliRoot_AMPT/run.sh index 4665cac4af1b3..04635cc35590a 100755 --- a/run/SimExamples/AliRoot_AMPT/run.sh +++ b/run/SimExamples/AliRoot_AMPT/run.sh @@ -9,5 +9,5 @@ NEV=5 ENERGY=5020. BMIN=15. BMAX=20. -o2-sim -j 20 -n ${NEV} -g extgen -m PIPE ITS TPC -o sim \ - --extGenFile "aliroot_ampt.macro" --extGenFunc "ampt(${ENERGY}, ${BMIN}, ${BMAX})" +o2-sim -j 20 -n ${NEV} -g external -m PIPE ITS TPC -o sim \ + --configKeyValues "GeneratorExternal.fileName=aliroot_ampt.macro;GeneratorExternal.funcName=ampt(${ENERGY}, ${BMIN}, ${BMAX})" diff --git a/run/SimExamples/AliRoot_Hijing/README.md b/run/SimExamples/AliRoot_Hijing/README.md index 4b4477f021ecf..581c2659477d6 100644 --- a/run/SimExamples/AliRoot_Hijing/README.md +++ b/run/SimExamples/AliRoot_Hijing/README.md @@ -5,7 +5,7 @@ This is a simple simulation example showing how to run event simulation using the Hijing event generator interface from AliRoot. The configuration of AliGenHijing is performed by the function `hijing(double energy = 5020., double bMin = 0., double bMax = 20.)` defined in the macro `aliroot_hijing.macro`. -The macro file is specified via the argument of `--extGenFile` whereas the specific function call to retrieven the configuration is specified via the argument of `--extGenFunc`. +The macro file is specified via `--configKeyValues` setting `GeneratorExternal.fileName` whereas the specific function call to retrieven the configuration is specified via `GeneratorExternal.funcName`. # IMPORTANT To run this example you need to load an AliRoot package compatible with the O2. diff --git a/run/SimExamples/AliRoot_Hijing/aliroot_hijing.macro b/run/SimExamples/AliRoot_Hijing/aliroot_hijing.macro index 393a81b543cbf..cfd13ef384a80 100644 --- a/run/SimExamples/AliRoot_Hijing/aliroot_hijing.macro +++ b/run/SimExamples/AliRoot_Hijing/aliroot_hijing.macro @@ -1,6 +1,5 @@ // configures a AliGenHijing class from AliRoot -// usage: o2sim -g extgen --extGenFile hijing.C -// options: --extGenFunc hijing(5020., 0., 20.) +// usage: o2sim -g external --configKeyValues 'GeneratorExternal.fileName=hijing.C;GeneratorExternal.funcName="hijing(5020., 0., 20.)"' /// \author R+Preghenella - October 2018 diff --git a/run/SimExamples/AliRoot_Hijing/run.sh b/run/SimExamples/AliRoot_Hijing/run.sh index 78b5d92a28eb9..423f188e96bf7 100755 --- a/run/SimExamples/AliRoot_Hijing/run.sh +++ b/run/SimExamples/AliRoot_Hijing/run.sh @@ -7,9 +7,9 @@ # 'hijing(double energy = 5020., double bMin = 0., double bMax = 20.)' defined # in the macro 'aliroot_hijing.macro'. # -# The macro file is specified via the argument of '--extGenFile' +# The macro file is specified via '--configKeyValues' setting 'GeneratorExternal.fileName' # whereas the specific function call to retrieven the configuration -# is specified via the argument of '--extGenFunc' +# is specified via 'GeneratorExternal.funcName' # # IMPORTANT # To run this example you need to load an AliRoot package compatible with the O2. @@ -25,6 +25,5 @@ NEV=5 ENERGY=5020. BMIN=0 BMAX=20. -o2-sim -j 20 -n ${NEV} -g extgen -m PIPE ITS TPC -o sim \ - --extGenFile "aliroot_hijing.macro" --extGenFunc "hijing(${ENERGY}, ${BMIN}, ${BMAX})" \ - --configKeyValues "Diamond.position[2]=0.1;Diamond.width[2]=0.05" +o2-sim -j 20 -n ${NEV} -g external -m PIPE ITS TPC -o sim \ + --configKeyValues "GeneratorExternal.fileName=aliroot_hijing.macro;GeneratorExternal.funcName=hijing(${ENERGY}, ${BMIN}, ${BMAX})" diff --git a/run/SimExamples/HF_Embedding_Pythia8/run.sh b/run/SimExamples/HF_Embedding_Pythia8/run.sh index c5dfb1d68c04a..11d0332775ec4 100755 --- a/run/SimExamples/HF_Embedding_Pythia8/run.sh +++ b/run/SimExamples/HF_Embedding_Pythia8/run.sh @@ -9,8 +9,8 @@ # # The main focus in this example is on PART c). PART b) just relaces some template values in the Pythia8 configuration file. # -# An external event generator configuration `-g extgen` is loaded from the file `--extGenFile "GeneratorHF.macro"` -# by running the code defined in the function `--extGenFunc "GeneratorHF()"`. +# An external event generator configuration `-g external` is loaded from the file defined via `--configKeyValues` setting +# `GeneratorExternal.fileName=GeneratorHF.macro` by running the code defined in the function `GeneratorExternal.funcName="GeneratorHF()"`. # Special configuration parameters are loaded from the INI file `--configFile o2sim_configuration_sgn.ini`. # # Pythia8.config defines the Pythia8 configuration file name. @@ -57,8 +57,8 @@ sed -e "s/\${rndSeed}/$RNDSEED/" \ # PART c) -o2-sim -j ${NWORKERS} -n ${SIGEVENTS} -g extgen -m ${MODULES} -o sgn \ - --extGenFile "GeneratorHF.macro" --extGenFunc "GeneratorHF()" \ +o2-sim -j ${NWORKERS} -n ${SIGEVENTS} -g external -m ${MODULES} -o sgn \ + --configKeyValues "GeneratorExternal.fileName=GeneratorHF.macro;GeneratorExternal.funcName=GeneratorHF()" \ --configFile o2sim_configuration_sgn.ini \ --embedIntoFile bkg_Kine.root \ > logsgn 2>&1 diff --git a/run/SimExamples/Signal_ImpactB/README.md b/run/SimExamples/Signal_ImpactB/README.md index 539b64acec41d..8230d35241fc9 100644 --- a/run/SimExamples/Signal_ImpactB/README.md +++ b/run/SimExamples/Signal_ImpactB/README.md @@ -11,6 +11,6 @@ Custom signal events generated according to the configuration given in a file 's The custom event generator receives and react to a notification that signals the embedding status of the simulation, giving the header of the background event for determination of subsequent actions. In this case, the impact paramereter from the background event is used to calculate the number of particles to be generated as signal -The macro file is specified via the argument of `--extGenFile` whereas the specific function call to retrieve the configuration and define the formula is specified via the argument of `--extGenFunc`. +The macro file is specified via `--configKeyValues` setting `GeneratorExternal.funcName` whereas the specific function call to retrieve the configuration and define the formula is specified via `GeneratorExternal.funcName`. The event generator for the background embedding needs to be capable of providing an impact parameter. In this case, Pythia8 heavy-ion model provides such value. diff --git a/run/SimExamples/Signal_ImpactB/run.sh b/run/SimExamples/Signal_ImpactB/run.sh index c5e06b0993af4..f82547faf20aa 100755 --- a/run/SimExamples/Signal_ImpactB/run.sh +++ b/run/SimExamples/Signal_ImpactB/run.sh @@ -21,6 +21,6 @@ o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS -o bkg --configKeyValues \ # of subsequent actions. In this case, the impact paramereter from the backgorund event # is used to calculate the number of particles to be generated as signal NSGN=10 -o2-sim -j 20 -n ${NSGN} extgen -m PIPE ITS \ - -g extgen --extGenFile signal_impactb.macro --extGenFunc "signal_impactb(333, \"20. / (x + 1.)\")" \ +o2-sim -j 20 -n ${NSGN} -m PIPE ITS \ + -g external --configKeyValues 'GeneratorExternal.fileName=signal_impactb.macro;GeneratorExternal.funcName=signal_impactb(333, "20. / (x + 1.)")' \ --embedIntoFile bkg_Kine.root -o sgn > logsgn 2>&1 diff --git a/run/SimExamples/Signal_ImpactB/signal_impactb.macro b/run/SimExamples/Signal_ImpactB/signal_impactb.macro index ccc07451b2dcd..5a25c318b3e55 100644 --- a/run/SimExamples/Signal_ImpactB/signal_impactb.macro +++ b/run/SimExamples/Signal_ImpactB/signal_impactb.macro @@ -3,8 +3,7 @@ // Example of an implementation of an external event generator // that is used and adapts it behavior in an embedding scenario. // -// usage: o2sim -g extgen --extGenFile signal_impactb.C -// options: --extGenFunc "signal_impactb(\"20. / (x + 1.)\") +// usage: o2sim -g external --configKeyValues 'GeneratorExternal.fileName=signal_impactb.C;GeneratorExternal.funcName="signal_impactb(\"20. / (x + 1.)\")"' using namespace o2::eventgen; diff --git a/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh b/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh index e1d69bca132ab..924e8e2d0ed2b 100755 --- a/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh +++ b/run/SimExamples/Trigger_ImpactB_Pythia8/run.sh @@ -22,4 +22,4 @@ set -x NEV=10 BMIN=15. BMAX=20. -o2-sim -j 20 -n ${NEV} -g pythia8hi -m PIPE ITS TPC --trigger external --configKeyValues 'TriggerExternal.fileName=trigger_impactb_pythia8.macro;TriggerExternal.funcName="trigger_impactb_pythia8(${BMIN}, ${BMAX})"' +o2-sim -j 20 -n ${NEV} -g pythia8hi -m PIPE ITS TPC --trigger external --configKeyValues "TriggerExternal.fileName=trigger_impactb_pythia8.macro;TriggerExternal.funcName=trigger_impactb_pythia8(${BMIN}, ${BMAX})" From 8f5e731a20778a0de598b9c6ed550693db6aafdf Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 10:54:14 +0200 Subject: [PATCH 0651/1751] DPL: modernize namespaces (#4349) --- .../Core/include/Framework/AODReaderHelpers.h | 16 +++++----------- .../Core/src/FrameworkGUIDeviceInspector.cxx | 10 ++-------- Framework/Core/src/FrameworkGUIDevicesGraph.cxx | 12 +++--------- 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/Framework/Core/include/Framework/AODReaderHelpers.h b/Framework/Core/include/Framework/AODReaderHelpers.h index 90c4e2af04fec..3016f07200fb2 100644 --- a/Framework/Core/include/Framework/AODReaderHelpers.h +++ b/Framework/Core/include/Framework/AODReaderHelpers.h @@ -8,19 +8,15 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef o2_framework_readers_AODReaderHelpers_INCLUDED_H -#define o2_framework_readers_AODReaderHelpers_INCLUDED_H +#ifndef O2_FRAMEWORK_AODREADERHELPERS_H_ +#define O2_FRAMEWORK_AODREADERHELPERS_H_ #include "Framework/TableBuilder.h" #include "Framework/AlgorithmSpec.h" #include "Framework/Logger.h" #include <uv.h> -namespace o2 -{ -namespace framework -{ -namespace readers +namespace o2::framework::readers { struct RuntimeWatchdog { @@ -71,8 +67,6 @@ struct AODReaderHelpers { static AlgorithmSpec aodSpawnerCallback(std::vector<InputSpec> requested); }; -} // namespace readers -} // namespace framework -} // namespace o2 +} // namespace o2::framework::readers -#endif +#endif // O2_FRAMEWORK_AODREADERHELPERS_H_ diff --git a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx index 058c998e75ac7..cd0686b3a6a32 100644 --- a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx +++ b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx @@ -23,11 +23,7 @@ #include <cstdlib> #include <iostream> -namespace o2 -{ -namespace framework -{ -namespace gui +namespace o2::framework::gui { struct ChannelsTableHelper { @@ -292,6 +288,4 @@ void displayDeviceInspector(DeviceSpec const& spec, } } -} // namespace gui -} // namespace framework -} // namespace o2 +} // namespace o2::framework::gui diff --git a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx index 7b81fd8618f28..c4ee6f5020de4 100644 --- a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx +++ b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx @@ -14,6 +14,7 @@ #include "Framework/DeviceInfo.h" #include "Framework/LogParsingHelpers.h" #include "Framework/PaletteHelpers.h" +#include "Framework/Logger.h" #include "FrameworkGUIDeviceInspector.h" #include "Framework/Logger.h" #include "../src/WorkflowHelpers.h" @@ -31,13 +32,8 @@ static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); } static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } -namespace o2 -{ -namespace framework +namespace o2::framework::gui { -namespace gui -{ - struct NodeColor { ImVec4 normal; ImVec4 hovered; @@ -558,6 +554,4 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, ImGui::End(); } -} // namespace gui -} // namespace framework -} // namespace o2 +} // namespace o2::framework::gui From 11e00c0f514ce8982f812e4028ed08cb90a51b7e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 16 Sep 2020 00:54:35 +0200 Subject: [PATCH 0652/1751] Register contributions from all sources in vertex-track references --- DataFormats/Reconstruction/CMakeLists.txt | 4 +- .../ReconstructionDataFormats/VtxTrackIndex.h | 8 ++ .../ReconstructionDataFormats/VtxTrackRef.h | 78 +++++++++++++++++++ .../src/ReconstructionDataFormatsLinkDef.h | 3 + .../Reconstruction/src/VtxTrackIndex.cxx | 2 +- .../Reconstruction/src/VtxTrackRef.cxx | 42 ++++++++++ .../PrimaryVertexReaderSpec.h | 4 +- .../src/PrimaryVertexReaderSpec.cxx | 26 ++++--- .../src/VertexTrackMatcherSpec.cxx | 4 +- .../include/DetectorsVertexing/PVertexer.h | 1 - .../DetectorsVertexing/PVertexerHelpers.h | 4 +- .../DetectorsVertexing/VertexTrackMatcher.h | 7 +- .../Vertexing/src/VertexTrackMatcher.cxx | 29 ++++++- 13 files changed, 185 insertions(+), 27 deletions(-) create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackRef.h create mode 100644 DataFormats/Reconstruction/src/VtxTrackRef.cxx diff --git a/DataFormats/Reconstruction/CMakeLists.txt b/DataFormats/Reconstruction/CMakeLists.txt index 578ceb660a0dd..f09bf663ae41b 100644 --- a/DataFormats/Reconstruction/CMakeLists.txt +++ b/DataFormats/Reconstruction/CMakeLists.txt @@ -20,6 +20,7 @@ o2_add_library(ReconstructionDataFormats src/PID.cxx src/DCA.cxx src/VtxTrackIndex.cxx + src/VtxTrackRef.cxx PUBLIC_LINK_LIBRARIES O2::GPUCommon O2::DetectorsCommonDataFormats O2::CommonDataFormat) @@ -36,7 +37,8 @@ o2_target_root_dictionary( include/ReconstructionDataFormats/TrackLTIntegral.h include/ReconstructionDataFormats/PID.h include/ReconstructionDataFormats/DCA.h - include/ReconstructionDataFormats/VtxTrackIndex.h) + include/ReconstructionDataFormats/VtxTrackIndex.h + include/ReconstructionDataFormats/VtxTrackRef.h) o2_add_test(Vertex SOURCES test/testVertex.cxx diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h index b001d3f8a73c1..b55c0b521fc8e 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h @@ -18,6 +18,8 @@ #include "CommonDataFormat/AbstractRef.h" #include <iosfwd> #include <string> +#include <array> +#include <string_view> namespace o2 { @@ -33,6 +35,11 @@ class VtxTrackIndex : public AbstractRef<26, 3, 3> TPC, NSources }; + static constexpr std::array<std::string_view, NSources> SourceNames = { + "TPCITS", + "ITS", + "TPC"}; + enum Flags : uint8_t { Contributor, // flag that it contributes to vertex fit Reserved, // @@ -42,6 +49,7 @@ class VtxTrackIndex : public AbstractRef<26, 3, 3> using AbstractRef<26, 3, 3>::AbstractRef; + static constexpr std::string_view getSourceName(int i) { return SourceNames[i]; } void print() const; std::string asString() const; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackRef.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackRef.h new file mode 100644 index 0000000000000..fda790cd72108 --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackRef.h @@ -0,0 +1,78 @@ +// 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 VtxTrackRef.h +/// \brief Referenc on track indices contributing to the vertex, with possibility chose tracks from specific source (global, ITS, TPC...) +/// \author ruben.shahoyan@cern.ch + +#ifndef O2_VERTEX_TRACK_REF +#define O2_VERTEX_TRACK_REF + +#include "CommonDataFormat/RangeReference.h" +#include "ReconstructionDataFormats/VtxTrackIndex.h" +#include <cassert> +#include <array> +#include <iosfwd> +#include <string> + +namespace o2 +{ +namespace dataformats +{ + +class VtxTrackRef : public RangeReference<int, int> +{ + public: + VtxTrackRef(int ent, int n) : RangeReference(ent, n) + { + auto end = ent + n; + for (int i = VtxTrackIndex::Source::NSources - 1; i--;) { + mFirstEntrySource[i] = end; // only 1st source (base reference) is filled at constructor level + } + } + using RangeReference<int, int>::RangeReference; + void print() const; + std::string asString() const; + + // get 1st of entry of indices for given source + int getFirstEntryOfSource(int s) const + { + assert(s >= 0 && s < VtxTrackIndex::NSources); + return s ? mFirstEntrySource[s - 1] : getFirstEntry(); + } + + // get number of entries for given source + int getEntriesOfSource(int s) const + { + return (s == VtxTrackIndex::NSources - 1 ? (getFirstEntry() + getEntries()) : getFirstEntryOfSource(s + 1)) - getFirstEntryOfSource(s); + } + + void setFirstEntryOfSource(int s, int i) + { + assert(s >= 0 && s < VtxTrackIndex::NSources); + if (s) { + mFirstEntrySource[s - 1] = i; + } else { + setFirstEntry(i); + } + } + + private: + std::array<int, VtxTrackIndex::Source::NSources - 1> mFirstEntrySource{0}; + + ClassDefNV(VtxTrackRef, 1); +}; + +std::ostream& operator<<(std::ostream& os, const o2::dataformats::VtxTrackRef& v); + +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index 1cf45dcc23905..ea8000cdc3292 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -44,6 +44,9 @@ #pragma link C++ class o2::dataformats::VtxTrackIndex + ; #pragma link C++ class std::vector < o2::dataformats::VtxTrackIndex> + ; +#pragma link C++ class o2::dataformats::VtxTrackRef + ; +#pragma link C++ class std::vector < o2::dataformats::VtxTrackRef> + ; + #pragma link C++ class o2::dataformats::DCA + ; #endif diff --git a/DataFormats/Reconstruction/src/VtxTrackIndex.cxx b/DataFormats/Reconstruction/src/VtxTrackIndex.cxx index 62d0b39905443..4c75f81d4cb1f 100644 --- a/DataFormats/Reconstruction/src/VtxTrackIndex.cxx +++ b/DataFormats/Reconstruction/src/VtxTrackIndex.cxx @@ -26,7 +26,7 @@ std::string VtxTrackIndex::asString() const return fmt::format("[{:d}/{:d}/{:s}]", getIndex(), getSource(), bits.to_string()); } -std::ostream& operator<<(std::ostream& os, const o2::dataformats::VtxTrackIndex& v) +std::ostream& o2::dataformats::operator<<(std::ostream& os, const o2::dataformats::VtxTrackIndex& v) { // stream itself os << v.asString(); diff --git a/DataFormats/Reconstruction/src/VtxTrackRef.cxx b/DataFormats/Reconstruction/src/VtxTrackRef.cxx new file mode 100644 index 0000000000000..d1b0d59dec0b9 --- /dev/null +++ b/DataFormats/Reconstruction/src/VtxTrackRef.cxx @@ -0,0 +1,42 @@ +// 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/VtxTrackRef.h" +#include "Framework/Logger.h" +#include <fmt/printf.h> +#include <iostream> +#include <bitset> + +using namespace o2::dataformats; + +std::string VtxTrackRef::asString() const +{ + std::string str = fmt::format("1st entry: {:d} ", getFirstEntry()); + for (int i = 0; i < VtxTrackIndex::NSources; i++) { + str += fmt::format(", N{:s} : {:d}", VtxTrackIndex::getSourceName(i), getEntriesOfSource(i)); + } + return str; +} + +std::ostream& o2::dataformats::operator<<(std::ostream& os, const o2::dataformats::VtxTrackRef& v) +{ + // stream itself + os << v.asString(); + return os; +} + +void VtxTrackRef::print() const +{ + LOG(INFO) << asString(); +} diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h index d99b6a0227334..6a32eb2c537ce 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h @@ -20,8 +20,8 @@ #include "Framework/Task.h" #include "CommonDataFormat/TimeStamp.h" -#include "CommonDataFormat/RangeReference.h" #include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/VtxTrackRef.h" #include "ReconstructionDataFormats/PrimaryVertex.h" #include "SimulationDataFormat/MCEventLabel.h" @@ -34,7 +34,7 @@ namespace vertexing class PrimaryVertexReader : public o2::framework::Task { using Label = o2::MCEventLabel; - using V2TRef = o2::dataformats::RangeReference<int, int>; + using V2TRef = o2::dataformats::VtxTrackRef; using PVertex = o2::dataformats::PrimaryVertex; using GIndex = o2::dataformats::VtxTrackIndex; diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx index f5154c08f7d90..d87aaa9e99b2f 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx @@ -52,20 +52,24 @@ void PrimaryVertexReader::run(ProcessingContext& pc) if (mUseMC) { lb = mLabels[cnt]; } - LOG(INFO) << "#" << cnt << " " << vtx << "| NAttached= " << mPV2MatchIdxRef[cnt].getEntries() << " | MC:" << lb; - int idMin = mPV2MatchIdxRef[cnt].getFirstEntry(), idMax = idMin + mPV2MatchIdxRef[cnt].getEntries(); - std::string trIDs; - int cntT = 0; - for (int i = idMin; i < idMax; i++) { - trIDs += mPV2MatchIdx[i].asString() + " "; - if (!((++cntT) % 15)) { + LOG(INFO) << "#" << cnt << " " << vtx << " | MC:" << lb; + LOG(INFO) << "References: " << mPV2MatchIdxRef[cnt]; + for (int is = 0; is < GIndex::NSources; is++) { + LOG(INFO) << GIndex::getSourceName(is) << " : " << mPV2MatchIdxRef[cnt].getEntriesOfSource(is) << " attached:"; + int idMin = mPV2MatchIdxRef[cnt].getFirstEntryOfSource(is), idMax = idMin + mPV2MatchIdxRef[cnt].getEntriesOfSource(is); + std::string trIDs; + int cntT = 0; + for (int i = idMin; i < idMax; i++) { + trIDs += mPV2MatchIdx[i].asString() + " "; + if (!((++cntT) % 15)) { + LOG(INFO) << trIDs; + trIDs = ""; + } + } + if (!trIDs.empty()) { LOG(INFO) << trIDs; - trIDs = ""; } } - if (!trIDs.empty()) { - LOG(INFO) << trIDs; - } cnt++; } } diff --git a/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx index 45904dade5560..38e5401753ddc 100644 --- a/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx @@ -59,10 +59,10 @@ void VertexTrackMatcherSpec::run(ProcessingContext& pc) const auto tracksITSROF = pc.inputs().get<gsl::span<o2::itsmft::ROFRecord>>("itsROF"); const auto vertices = pc.inputs().get<gsl::span<o2::dataformats::PrimaryVertex>>("vertices"); const auto vtxTracks = pc.inputs().get<gsl::span<o2::dataformats::VtxTrackIndex>>("vtxTracks"); - const auto vtxTrackRefs = pc.inputs().get<gsl::span<o2::dataformats::RangeReference<int, int>>>("vtxTrackRefs"); + const auto vtxTrackRefs = pc.inputs().get<gsl::span<o2::dataformats::VtxTrackRef>>("vtxTrackRefs"); std::vector<o2::dataformats::VtxTrackIndex> trackIndex; - std::vector<o2::dataformats::RangeReference<int, int>> vtxRefs; + std::vector<o2::dataformats::VtxTrackRef> vtxRefs; mMatcher.process(vertices, vtxTracks, vtxTrackRefs, tracksITSTPC, tracksITS, tracksITSROF, tracksTPC, trackIndex, vtxRefs); diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index 410cc95ab9cd1..fc227f80fb6c7 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -19,7 +19,6 @@ #include <utility> #include "CommonConstants/LHCConstants.h" #include "CommonDataFormat/TimeStamp.h" -#include "CommonDataFormat/RangeReference.h" #include "CommonDataFormat/BunchFilling.h" #include "SimulationDataFormat/MCEventLabel.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h index 3d3b322fcff17..7c481c0495def 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h @@ -19,8 +19,8 @@ #include "ReconstructionDataFormats/PrimaryVertex.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/VtxTrackRef.h" #include "CommonDataFormat/TimeStamp.h" -#include "CommonDataFormat/RangeReference.h" namespace o2 { @@ -29,7 +29,7 @@ namespace vertexing using PVertex = o2::dataformats::PrimaryVertex; using TimeEst = o2::dataformats::TimeStampWithError<float, float>; -using V2TRef = o2::dataformats::RangeReference<int, int>; +using V2TRef = o2::dataformats::VtxTrackRef; using GIndex = o2::dataformats::VtxTrackIndex; ///< weights and scaling params for current vertex diff --git a/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h index 6e2c00b314569..a8d12a73b2ed8 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h @@ -18,6 +18,7 @@ #include "gsl/span" #include "ReconstructionDataFormats/PrimaryVertex.h" #include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/VtxTrackRef.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "DataFormatsTPC/TrackTPC.h" #include "DataFormatsITS/TrackITS.h" @@ -35,7 +36,7 @@ class VertexTrackMatcher { public: using GIndex = o2::dataformats::VtxTrackIndex; - using RRef = o2::dataformats::RangeReference<int, int>; + using VRef = o2::dataformats::VtxTrackRef; using PVertex = const o2::dataformats::PrimaryVertex; using TrackTPCITS = o2::dataformats::TrackTPCITS; using TrackITS = o2::its::TrackITS; @@ -48,13 +49,13 @@ class VertexTrackMatcher void init(); void process(const gsl::span<const PVertex>& vertices, // vertices const gsl::span<const GIndex>& v2tfitIDs, // IDs of contributor tracks used in fit - const gsl::span<const RRef>& v2tfitRefs, // references on these tracks + const gsl::span<const VRef>& v2tfitRefs, // references on these tracks (we used special reference with multiple sources, but currently only TPCITS used) const gsl::span<const TrackTPCITS>& tpcits, // global tracks const gsl::span<const TrackITS>& its, // ITS tracks const gsl::span<const ITSROFR>& itsROFR, // ITS tracks ROFRecords const gsl::span<const TrackTPC>& tpc, // TPC tracks std::vector<GIndex>& trackIndex, // Global ID's for associated tracks - std::vector<RRef>& vtxRefs); // references on these tracks + std::vector<VRef>& vtxRefs); // references on these tracks ///< set InteractionRecods for the beginning of the TF void setStartIR(const o2::InteractionRecord& ir) { mStartIR = ir; } diff --git a/Detectors/Vertexing/src/VertexTrackMatcher.cxx b/Detectors/Vertexing/src/VertexTrackMatcher.cxx index ccd9b4a805836..8c6bea353fc8c 100644 --- a/Detectors/Vertexing/src/VertexTrackMatcher.cxx +++ b/Detectors/Vertexing/src/VertexTrackMatcher.cxx @@ -40,13 +40,13 @@ void VertexTrackMatcher::updateTPCTimeDependentParams() void VertexTrackMatcher::process(const gsl::span<const PVertex>& vertices, const gsl::span<const GIndex>& v2tfitIDs, - const gsl::span<const RRef>& v2tfitRefs, + const gsl::span<const VRef>& v2tfitRefs, const gsl::span<const TrackTPCITS>& tpcitsTracks, const gsl::span<const TrackITS>& itsTracks, const gsl::span<const ITSROFR>& itsROFR, const gsl::span<const TrackTPC>& tpcTracks, std::vector<GIndex>& trackIndex, - std::vector<RRef>& vtxRefs) + std::vector<VRef>& vtxRefs) { TmpMap tmpMap; @@ -87,6 +87,7 @@ void VertexTrackMatcher::process(const gsl::span<const PVertex>& vertices, return tI < tJ; }); + // Important: do this in the same order in which VtxTrackIndex::Source enums are defined! attachTPCITS(tmpMap, tpcitsTracks, idTPCITS, vertices); attachITS(tmpMap, itsTracks, itsROFR, flgITS, vertices, idVtxIRMin); attachTPC(tmpMap, tpcTimes, idTPC, vertices, idVtxIRMin); @@ -109,22 +110,42 @@ void VertexTrackMatcher::process(const gsl::span<const PVertex>& vertices, (*vptr[gid.getSource()])[gid.getIndex()]++; } } + for (int iv = 0; iv < nv; iv++) { + int srcStart[GIndex::NSources + 1]; int entry = trackIndex.size(); + srcStart[GIndex::TPCITS] = entry; + for (int is = 1; is < GIndex::NSources; is++) { + srcStart[is] = -1; + } + // 1st: attach indices of global tracks used in vertex fit int idMin = v2tfitRefs[iv].getFirstEntry(), idMax = idMin + v2tfitRefs[iv].getEntries(); for (int id = idMin; id < idMax; id++) { trackIndex.push_back(v2tfitIDs[id]); } + // 2nd: attach non-contributing tracks const auto& trvec = tmpMap[iv]; for (const auto gid0 : trvec) { + int src = gid0.getSource(); + if (srcStart[src] == -1) { + srcStart[src] = trackIndex.size(); + } auto& gid = trackIndex.emplace_back(gid0); - if ((*vptr[gid.getSource()])[gid.getIndex()] > 1) { + if ((*vptr[src])[gid.getIndex()] > 1) { gid.setBit(GIndex::Ambiguous); } } - vtxRefs.emplace_back(entry, trackIndex.size() - entry); + + auto& vr = vtxRefs.emplace_back(entry, trackIndex.size() - entry); + srcStart[GIndex::NSources] = trackIndex.size(); + for (int is = GIndex::NSources; is > 0; is--) { + if (srcStart[is] == -1) { // in case the source did not contribute + srcStart[is] = srcStart[is + 1]; + } + vr.setFirstEntryOfSource(is, srcStart[is]); + } } } From 644e57c11aa762a72b912cf1d05bb55376c8ac0b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Sep 2020 11:43:49 +0200 Subject: [PATCH 0653/1751] DPL: add helper to match only description (#4357) --- Framework/Core/include/Framework/DataSpecUtils.h | 6 ++++++ Framework/Core/src/DataSpecUtils.cxx | 12 ++++++++++++ Framework/Core/test/unittest_DataSpecUtils.cxx | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/Framework/Core/include/Framework/DataSpecUtils.h b/Framework/Core/include/Framework/DataSpecUtils.h index 9ade6382b7e2c..aeeef13ed9b43 100644 --- a/Framework/Core/include/Framework/DataSpecUtils.h +++ b/Framework/Core/include/Framework/DataSpecUtils.h @@ -72,6 +72,12 @@ struct DataSpecUtils { /// @return true if the OutputSpec will match at least the provided @a origin. static bool partialMatch(OutputSpec const& spec, o2::header::DataOrigin const& origin); + /// @return true if the OutputSpec will match at least the provided @a description. + static bool partialMatch(InputSpec const& spec, o2::header::DataDescription const& description); + + /// @return true if the OutputSpec will match at least the provided @a description. + static bool partialMatch(OutputSpec const& spec, o2::header::DataDescription const& description); + template <typename T> static bool match(const T& spec, const o2::header::DataHeader& header) { diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index 73080bc144e93..8eb02f2629d2a 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -265,6 +265,18 @@ bool DataSpecUtils::partialMatch(InputSpec const& input, header::DataOrigin cons return DataSpecUtils::asConcreteOrigin(input) == origin; } +bool DataSpecUtils::partialMatch(InputSpec const& input, header::DataDescription const& description) +{ + auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(input); + return dataType.description == description; +} + +bool DataSpecUtils::partialMatch(OutputSpec const& output, header::DataDescription const& description) +{ + auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(output); + return dataType.description == description; +} + ConcreteDataMatcher DataSpecUtils::asConcreteDataMatcher(InputSpec const& spec) { return std::get<ConcreteDataMatcher>(spec.matcher); diff --git a/Framework/Core/test/unittest_DataSpecUtils.cxx b/Framework/Core/test/unittest_DataSpecUtils.cxx index 9a394ba481b35..d1d91ad74ae05 100644 --- a/Framework/Core/test/unittest_DataSpecUtils.cxx +++ b/Framework/Core/test/unittest_DataSpecUtils.cxx @@ -201,6 +201,12 @@ BOOST_AUTO_TEST_CASE(PartialMatching) BOOST_CHECK(DataSpecUtils::partialMatch(fullySpecifiedOutput, header::DataOrigin("FOO")) == false); BOOST_CHECK(DataSpecUtils::partialMatch(fullySpecifiedInput, header::DataOrigin("FOO")) == false); + + BOOST_CHECK(DataSpecUtils::partialMatch(fullySpecifiedOutput, header::DataDescription("TEST")) == false); + BOOST_CHECK(DataSpecUtils::partialMatch(fullySpecifiedInput, header::DataDescription("TSET")) == false); + + BOOST_CHECK(DataSpecUtils::partialMatch(fullySpecifiedOutput, header::DataDescription("FOOO")) == true); + BOOST_CHECK(DataSpecUtils::partialMatch(fullySpecifiedInput, header::DataDescription("FOOO")) == true); } BOOST_AUTO_TEST_CASE(GetOptionalSubSpecWithMatcher) From cc0b519e10f2497806fd5d36c83ae89640a8ae98 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 16 Sep 2020 12:21:29 +0200 Subject: [PATCH 0654/1751] GPU: Fix stupid 'typo' --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index a8b4268b277be..89643bf0044a5 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -459,8 +459,8 @@ void GPUChainTracking::AllocateIOMemory() AllocateIOMemoryHelper(mIOPtrs.nSliceTracks[i], mIOPtrs.sliceTracks[i], mIOMem.sliceTracks[i]); AllocateIOMemoryHelper(mIOPtrs.nSliceClusters[i], mIOPtrs.sliceClusters[i], mIOMem.sliceClusters[i]); } - AllocateIOMemoryHelper(mIOMem.clusterNativeAccess->nClustersTotal, mIOMem.clusterNativeAccess->clustersLinear, mIOMem.clustersNative); mIOMem.clusterNativeAccess.reset(new ClusterNativeAccess); + AllocateIOMemoryHelper(mIOMem.clusterNativeAccess->nClustersTotal, mIOMem.clusterNativeAccess->clustersLinear, mIOMem.clustersNative); mIOPtrs.clustersNative = mIOMem.clusterNativeAccess->nClustersTotal ? mIOMem.clusterNativeAccess.get() : nullptr; AllocateIOMemoryHelper(mIOPtrs.nMCLabelsTPC, mIOPtrs.mcLabelsTPC, mIOMem.mcLabelsTPC); AllocateIOMemoryHelper(mIOPtrs.nMCInfosTPC, mIOPtrs.mcInfosTPC, mIOMem.mcInfosTPC); From 2373c15ada4f34ec5f66023ba0440a1a280b0058 Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaia@cern.ch> Date: Thu, 10 Sep 2020 10:24:45 +0300 Subject: [PATCH 0655/1751] all TFs passed to reco --- Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx | 6 +++--- Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx | 6 +++--- Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx | 6 ++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx index 4169700cada0f..052f0f62a69f7 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterDPLSpec.cxx @@ -34,12 +34,12 @@ DataProcessorSpec getFT0DigitWriterDPLSpec() LOG(INFO) << "FT0DigitWriter pulled " << digits.size() << " digits"; }; return MakeRootTreeWriterSpec( - "ft0-digit-writer", "o2digit_ft0.root", "o2digits", + "ft0-digit-writer", "o2digit_ft0.root", "o2sim", BranchDefinition<DigitType>{InputSpec{"digits", "FT0", "DIGITSBC", 0}, - "FT0Digits", "ft0-digits-branch-name", 1, + "FT0DIGITSBC", "ft0-digits-branch-name", 1, logger}, BranchDefinition<ChanDataType>{InputSpec{"digch", "FT0", "DIGITSCH", 0}, - "FT0ChData", "ft0-chhdata-branch-name"})(); + "FT0DIGITSCH", "ft0-chhdata-branch-name"})(); } } // namespace ft0 diff --git a/Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx index 7b2c2e02ade88..92b613f8eebf1 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0DigitWriterSpec.cxx @@ -34,12 +34,12 @@ DataProcessorSpec getFT0DigitWriterSpec() LOG(INFO) << "FT0DigitWriter pulled " << digits.size() << " digits"; }; return MakeRootTreeWriterSpec( - "ft0-digit-writer", "o2digit_ft0.root", "o2digits", + "ft0-digit-writer", "o2digit_ft0.root", "o2sim", BranchDefinition<DigitType>{InputSpec{"digits", "FT0", "DIGITSBC", 0}, - "FT0Digits", "ft0-digits-branch-name", 1, + "FT0DIGITSBC", "ft0-digits-branch-name", 1, logger}, BranchDefinition<ChanDataType>{InputSpec{"digch", "FT0", "DIGITSCH", 0}, - "FT0ChData", "ft0-chhdata-branch-name"})(); + "FT0DIGITSCH", "ft0-chhdata-branch-name"})(); } } // namespace ft0 diff --git a/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx index c75caeb9b1c4f..a9a39d6aac58c 100644 --- a/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx @@ -33,9 +33,6 @@ void ReconstructionDPL::init(InitContext& ic) void ReconstructionDPL::run(ProcessingContext& pc) { - if (mFinished) { - return; - } mRecPoints.clear(); auto digits = pc.inputs().get<gsl::span<o2::ft0::Digit>>("digits"); //auto digits = pc.inputs().get<const std::vector<o2::ft0::Digit>>("digits"); @@ -49,10 +46,12 @@ void ReconstructionDPL::run(ProcessingContext& pc) LOG(INFO) << "Ignoring MC info"; } int nDig = digits.size(); + LOG(DEBUG) << " nDig " << nDig; mRecPoints.reserve(nDig); mRecChData.resize(digch.size()); for (int id = 0; id < nDig; id++) { const auto& digit = digits[id]; + LOG(DEBUG) << " ndig " << id << " bc " << digit.getBC() << " orbit " << digit.getOrbit(); auto channels = digit.getBunchChannelData(digch); gsl::span<o2::ft0::ChannelDataFloat> out_ch(mRecChData); out_ch = out_ch.subspan(digit.ref.getFirstEntry(), digit.ref.getEntries()); @@ -65,7 +64,6 @@ void ReconstructionDPL::run(ProcessingContext& pc) pc.outputs().snapshot(Output{mOrigin, "RECCHDATA", 0, Lifetime::Timeframe}, mRecChData); mFinished = true; - pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); } DataProcessorSpec getReconstructionSpec(bool useMC) From 1536fe7d1153b98d1d86a75140f799e1db840c24 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Wed, 16 Sep 2020 13:37:49 +0200 Subject: [PATCH 0656/1751] add vertex axis, new functions in corr container (#4356) --- .../include/Analysis/CorrelationContainer.h | 13 ++- Analysis/Core/src/CorrelationContainer.cxx | 110 +++++++++++++----- Analysis/Tasks/PWGCF/correlations.cxx | 35 ++++-- 3 files changed, 112 insertions(+), 46 deletions(-) diff --git a/Analysis/Core/include/Analysis/CorrelationContainer.h b/Analysis/Core/include/Analysis/CorrelationContainer.h index f0b54f3e251e6..b644434a13d55 100644 --- a/Analysis/Core/include/Analysis/CorrelationContainer.h +++ b/Analysis/Core/include/Analysis/CorrelationContainer.h @@ -62,13 +62,14 @@ class CorrelationContainer : public TNamed void deepCopy(CorrelationContainer* from); - void getHistsZVtxMult(CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax, THnBase** trackHist, TH2** eventHist); - TH2* getSumOfRatios(CorrelationContainer* mixed, CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax, Int_t multBinBegin, Int_t multBinEnd, Bool_t normalizePerTrigger = kTRUE, Int_t stepForMixed = -1, Int_t* trigger = nullptr); - TH1* getTriggersAsFunctionOfMultiplicity(CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax); + void getHistsZVtxMult(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax, THnBase** trackHist, TH2** eventHist); + TH2* getPerTriggerYield(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax, Bool_t normalizePerTrigger = kTRUE); + TH2* getSumOfRatios(CorrelationContainer* mixed, CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax, Bool_t normalizePerTrigger = kTRUE, Int_t stepForMixed = -1, Int_t* trigger = nullptr); + TH1* getTriggersAsFunctionOfMultiplicity(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax); TH1* getTrackEfficiency(CFStep step1, CFStep step2, Int_t axis1, Int_t axis2 = -1, Int_t source = 1, Int_t axis3 = -1); THnBase* getTrackEfficiencyND(CFStep step1, CFStep step2); - TH1* getEventEfficiency(CFStep step1, CFStep step2, Int_t axis1, Int_t axis2 = -1, Float_t ptLeadMin = -1, Float_t ptLeadMax = -1); + TH1* getEventEfficiency(CFStep step1, CFStep step2, Int_t axis1, Int_t axis2 = -1, Float_t ptTriggerMin = -1, Float_t ptTriggerMax = -1); TH1* getBias(CFStep step1, CFStep step2, const char* axis, Float_t leadPtMin = 0, Float_t leadPtMax = -1, Int_t weighting = 0); TH1D* getTrackingEfficiency(Int_t axis); @@ -89,7 +90,7 @@ class CorrelationContainer : public TNamed TH2D* getTrackingEfficiencyCorrection(); TH2D* getTrackingEfficiencyCorrectionCentrality(); - void FillEvent(Float_t centrality, CFStep step); + void fillEvent(Float_t centrality, CFStep step); void extendTrackingEfficiency(Bool_t verbose = kFALSE); @@ -124,7 +125,7 @@ class CorrelationContainer : public TNamed void setHistogramType(const char* histogramType) { mHistogramType = histogramType; } - void countEmptyBins(CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax); + void countEmptyBins(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax); void symmetrizepTBins(); void setBinLimits(THnBase* grid); diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 15b31dea8cfea..35798f0a7b510 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -551,7 +551,7 @@ void CorrelationContainer::resetBinLimits(THnBase* grid) } //____________________________________________________________________ -void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax) +void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax) { // prints the number of empty bins in the track end event histograms in the given step @@ -573,9 +573,9 @@ void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Flo binEnd[1] = mPairHist->getTHn(step)->GetAxis(1)->FindBin(mPtMax); } - if (ptLeadMax > ptLeadMin) { - binBegin[2] = mPairHist->getTHn(step)->GetAxis(2)->FindBin(ptLeadMin); - binEnd[2] = mPairHist->getTHn(step)->GetAxis(2)->FindBin(ptLeadMax); + if (ptTriggerMax > ptTriggerMin) { + binBegin[2] = mPairHist->getTHn(step)->GetAxis(2)->FindBin(ptTriggerMin); + binEnd[2] = mPairHist->getTHn(step)->GetAxis(2)->FindBin(ptTriggerMax); } // start from multiplicity 1 @@ -616,7 +616,7 @@ void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Flo } //____________________________________________________________________ -void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax, THnBase** trackHist, TH2** eventHist) +void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax, THnBase** trackHist, TH2** eventHist) { // Calculates a 4d histogram with deltaphi, deltaeta, zvtx, multiplicity on track level and // a 2d histogram on event level (as fct of zvtx, multiplicity) @@ -637,9 +637,9 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F setBinLimits(sparse); - Int_t firstBin = sparse->GetAxis(2)->FindBin(ptLeadMin); - Int_t lastBin = sparse->GetAxis(2)->FindBin(ptLeadMax); - LOGF(info, "Using pT range %d --> %d", firstBin, lastBin); + Int_t firstBin = sparse->GetAxis(2)->FindBin(ptTriggerMin); + Int_t lastBin = sparse->GetAxis(2)->FindBin(ptTriggerMax); + LOGF(info, "Using trigger pT range %d --> %d", firstBin, lastBin); sparse->GetAxis(2)->SetRange(firstBin, lastBin); mTriggerHist->getTHn(step)->GetAxis(0)->SetRange(firstBin, lastBin); @@ -716,10 +716,61 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F resetBinLimits(mTriggerHist->getTHn(step)); } -//____________________________________________________________________ -TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax, Int_t multBinBegin, Int_t multBinEnd, Bool_t normalizePerTrigger, Int_t stepForMixed, Int_t* trigger) +TH2* CorrelationContainer::getPerTriggerYield(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax, Bool_t normalizePerTrigger) +{ + // Calculate per trigger yield without considering mixed event + // Sums over all vertex bins, and respects the pT and centrality limits set in the class + // + // returns a 2D histogram: deltaphi, deltaeta + // + // Parameters: + // step: Step for which the histogram is received + // ptTriggerMin, ptTriggerMax: trigger pT range + // normalizePerTrigger: divide through number of triggers + + THnBase* trackSameAll = nullptr; + TH2* eventSameAll = nullptr; + + Long64_t totalEvents = 0; + Int_t nCorrelationFunctions = 0; + + getHistsZVtxMult(step, ptTriggerMin, ptTriggerMax, &trackSameAll, &eventSameAll); + + TAxis* multAxis = trackSameAll->GetAxis(3); + int multBinBegin = 1; + int multBinEnd = multAxis->GetNbins(); + if (mCentralityMin < mCentralityMax) { + multBinBegin = multAxis->FindBin(mCentralityMin + 1e-4); + multBinEnd = multAxis->FindBin(mCentralityMax - 1e-4); + LOGF(info, "Using multiplicity range %d --> %d", multBinBegin, multBinEnd); + } + + if (mCentralityMin < mCentralityMax) { + trackSameAll->GetAxis(3)->SetRange(multBinBegin, multBinEnd); + } + + TH2* yield = trackSameAll->Projection(1, 0, "E"); + Float_t triggers = eventSameAll->Integral(1, eventSameAll->GetXaxis()->GetNbins(), multBinBegin, multBinEnd); + + if (normalizePerTrigger) { + LOGF(info, "Dividing %f tracks by %f triggers", yield->Integral(), triggers); + if (triggers > 0) + yield->Scale(1.0 / triggers); + } + + // normalizate to dphi width + Float_t normalization = yield->GetXaxis()->GetBinWidth(1); + yield->Scale(1.0 / normalization); + + delete trackSameAll; + delete eventSameAll; + + return yield; +} + +TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax, Bool_t normalizePerTrigger, Int_t stepForMixed, Int_t* trigger) { - // Calls GetUEHist(...) for *each* vertex bin and multiplicity bin and performs a sum of ratios: + // Extract 2D per trigger yield with mixed event correction. The quantity is calculated for *each* vertex bin and multiplicity bin and then a sum of ratios is performed: // 1_N [ (same/mixed)_1 + (same/mixed)_2 + (same/mixed)_3 + ... ] // where N is the total number of events/trigger particles and the subscript is the vertex/multiplicity bin // where mixed is normalized such that the information about the number of pairs in same is kept @@ -728,8 +779,9 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati // // Parameters: // mixed: CorrelationContainer containing mixed event corresponding to this object (the histograms are taken from step <stepForMixed> if defined otherwise from step <step>) - // <other parameters> : check documentation of CorrelationContainer::GetUEHist - // normalizePerTrigger: divide through number of triggers + // step: Step for which the histogram is received + // ptTriggerMin, ptTriggerMax: trigger pT range + // normalizePerTrigger: divide through number of triggers // do not add this hists to the directory Bool_t oldStatus = TH1::AddDirectoryStatus(); @@ -747,8 +799,8 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati Long64_t totalEvents = 0; Int_t nCorrelationFunctions = 0; - getHistsZVtxMult(step, ptLeadMin, ptLeadMax, &trackSameAll, &eventSameAll); - mixed->getHistsZVtxMult((stepForMixed == -1) ? step : (CFStep)stepForMixed, ptLeadMin, ptLeadMax, &trackMixedAll, &eventMixedAll); + getHistsZVtxMult(step, ptTriggerMin, ptTriggerMax, &trackSameAll, &eventSameAll); + mixed->getHistsZVtxMult((stepForMixed == -1) ? step : (CFStep)stepForMixed, ptTriggerMin, ptTriggerMax, &trackMixedAll, &eventMixedAll); // If we ask for histograms from step8 (TTR cut applied) there is a hole at 0,0; so this cannot be used for the // mixed-event normalization. If step6 is available, the normalization factor is read out from that one. @@ -756,7 +808,7 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati // flat delta phi distribution) if (stepForMixed == -1 && step == kCFStepBiasStudy && mixed->mTriggerHist->getTHn(kCFStepReconstructed)->GetEntries() > 0 && !mSkipScaleMixedEvent) { LOGF(info, "Using mixed-event normalization factors from step %d", kCFStepReconstructed); - mixed->getHistsZVtxMult(kCFStepReconstructed, ptLeadMin, ptLeadMax, &trackMixedAllStep6, &eventMixedAllStep6); + mixed->getHistsZVtxMult(kCFStepReconstructed, ptTriggerMin, ptTriggerMax, &trackMixedAllStep6, &eventMixedAllStep6); } // Printf("%f %f %f %f", trackSameAll->GetEntries(), eventSameAll->GetEntries(), trackMixedAll->GetEntries(), eventMixedAll->GetEntries()); @@ -767,9 +819,11 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati TAxis* multAxis = trackSameAll->GetAxis(3); - if (multBinEnd < multBinBegin) { - multBinBegin = 1; - multBinEnd = multAxis->GetNbins(); + int multBinBegin = 1; + int multBinEnd = multAxis->GetNbins(); + if (mCentralityMin < mCentralityMax) { + multBinBegin = multAxis->FindBin(mCentralityMin); + multBinEnd = multAxis->FindBin(mCentralityMax); } for (Int_t multBin = TMath::Max(1, multBinBegin); multBin <= TMath::Min(multAxis->GetNbins(), multBinEnd); multBin++) { @@ -996,14 +1050,14 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati return totalTracks; } -TH1* CorrelationContainer::getTriggersAsFunctionOfMultiplicity(CorrelationContainer::CFStep step, Float_t ptLeadMin, Float_t ptLeadMax) +TH1* CorrelationContainer::getTriggersAsFunctionOfMultiplicity(CorrelationContainer::CFStep step, Float_t ptTriggerMin, Float_t ptTriggerMax) { // returns the distribution of triggers as function of centrality/multiplicity resetBinLimits(mTriggerHist->getTHn(step)); - Int_t firstBin = mTriggerHist->getTHn(step)->GetAxis(0)->FindBin(ptLeadMin); - Int_t lastBin = mTriggerHist->getTHn(step)->GetAxis(0)->FindBin(ptLeadMax); + Int_t firstBin = mTriggerHist->getTHn(step)->GetAxis(0)->FindBin(ptTriggerMin); + Int_t lastBin = mTriggerHist->getTHn(step)->GetAxis(0)->FindBin(ptTriggerMax); LOGF(info, "Using pT range %d --> %d", firstBin, lastBin); mTriggerHist->getTHn(step)->GetAxis(0)->SetRange(firstBin, lastBin); @@ -1301,14 +1355,14 @@ TH1* CorrelationContainer::getTrackEfficiency(CFStep step1, CFStep step2, Int_t } //____________________________________________________________________ -TH1* CorrelationContainer::getEventEfficiency(CFStep step1, CFStep step2, Int_t axis1, Int_t axis2, Float_t ptLeadMin, Float_t ptLeadMax) +TH1* CorrelationContainer::getEventEfficiency(CFStep step1, CFStep step2, Int_t axis1, Int_t axis2, Float_t ptTriggerMin, Float_t ptTriggerMax) { // creates a event-level efficiency by dividing step2 by step1 // projected to axis1 and axis2 (optional if >= 0) - if (ptLeadMax > ptLeadMin) { - mTriggerHist->getTHn(step1)->GetAxis(0)->SetRangeUser(ptLeadMin, ptLeadMax); - mTriggerHist->getTHn(step2)->GetAxis(0)->SetRangeUser(ptLeadMin, ptLeadMax); + if (ptTriggerMax > ptTriggerMin) { + mTriggerHist->getTHn(step1)->GetAxis(0)->SetRangeUser(ptTriggerMin, ptTriggerMax); + mTriggerHist->getTHn(step2)->GetAxis(0)->SetRangeUser(ptTriggerMin, ptTriggerMax); } TH1* measured = nullptr; @@ -1326,7 +1380,7 @@ TH1* CorrelationContainer::getEventEfficiency(CFStep step1, CFStep step2, Int_t delete generated; - if (ptLeadMax > ptLeadMin) { + if (ptTriggerMax > ptTriggerMin) { mTriggerHist->getTHn(step1)->GetAxis(0)->SetRangeUser(0, -1); mTriggerHist->getTHn(step2)->GetAxis(0)->SetRangeUser(0, -1); } @@ -1867,7 +1921,7 @@ THnBase* CorrelationContainer::changeToThn(THnBase* sparse) return tmpTHn; } -void CorrelationContainer::FillEvent(Float_t centrality, CFStep step) +void CorrelationContainer::fillEvent(Float_t centrality, CFStep step) { // Fill per-event information mEventCount->Fill(step, centrality); diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index a9e4fdfc6ab99..161c33cbd09b9 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -35,6 +35,7 @@ struct CorrelationTask { 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(cfgPtOrder, int, 1, "Only consider pairs for which pT,1 < pT,2 (0 = OFF, 1 = ON)"); 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"); @@ -94,8 +95,8 @@ struct CorrelationTask { cfg.mPairCuts = true; // --- OBJECT INIT --- - same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentrality", binning)); - mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentrality", binning)); + same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentralityVtx", binning)); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentralityVtx", binning)); //qaOutput.setObject(new TDirectory("qa", "qa")); if (cfgTwoTrackCut > 0) { @@ -112,28 +113,33 @@ struct CorrelationTask { } // Version with explicit nested loop - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, aod::BCs const& bcs, aod::Run2V0s const& vzeros, myTracks const& tracks) + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents>>::iterator const& collision, aod::BCs const& bcs, aod::Run2V0s const& vzeros, myTracks const& tracks) { - LOGF(info, "Tracks for collision: %d | Trigger mask: %lld | INT7: %d | V0M: %.1f", tracks.size(), collision.bc().triggerMask(), collision.sel7(), collision.centV0M()); + LOGF(info, "Tracks for collision: %d | Vertex: %.1f | INT7: %d | V0M: %.1f", tracks.size(), collision.posZ(), collision.sel7(), collision.centV0M()); const auto centrality = collision.centV0M(); - same->FillEvent(centrality, CorrelationContainer::kCFStepAll); + same->fillEvent(centrality, CorrelationContainer::kCFStepAll); if (!collision.sel7()) return; - same->FillEvent(centrality, CorrelationContainer::kCFStepTriggered); + same->fillEvent(centrality, CorrelationContainer::kCFStepTriggered); + + // vertex already checked as filter + same->fillEvent(centrality, CorrelationContainer::kCFStepVertex); + + same->fillEvent(centrality, CorrelationContainer::kCFStepReconstructed); int bSign = 1; // TODO magnetic field from CCDB - for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { + for (auto& track1 : tracks) { + + // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) continue; - //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); - double eventValues[3]; eventValues[0] = track1.pt(); eventValues[1] = centrality; @@ -142,7 +148,12 @@ struct CorrelationTask { same->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); - for (auto track2 = track1 + 1; track2 != tracks.end(); ++track2) { + for (auto& track2 : tracks) { + if (track1 == track2) + continue; + + if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) + continue; if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) continue; @@ -158,8 +169,8 @@ struct CorrelationTask { double values[6] = {0}; values[0] = track1.eta() - track2.eta(); - values[1] = track1.pt(); - values[2] = track2.pt(); + values[1] = track2.pt(); + values[2] = track1.pt(); values[3] = centrality; values[4] = track1.phi() - track2.phi(); From 76b67eae9ff1ec832055ca593724a2e83ab71ea2 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Wed, 16 Sep 2020 14:54:39 +0200 Subject: [PATCH 0657/1751] workflow splitted to contain also an event selection; configuration updated for the analysis challenge (#4353) * optimizations for the table-reader task * Added a task for dilepton - hadron combinations in the tableReader workflow * Added an event selection task in the workflow; a few small fixes --- .../include/Analysis/AnalysisCompositeCut.h | 5 +- Analysis/Core/include/Analysis/VarManager.h | 2 +- Analysis/Core/src/AnalysisCompositeCut.cxx | 9 +- Analysis/Core/src/VarManager.cxx | 6 +- Analysis/Tasks/PWGDQ/tableReader.cxx | 399 +++++++++++------- 5 files changed, 249 insertions(+), 172 deletions(-) diff --git a/Analysis/Core/include/Analysis/AnalysisCompositeCut.h b/Analysis/Core/include/Analysis/AnalysisCompositeCut.h index 59ff82a2ccb5f..d794179a394dc 100644 --- a/Analysis/Core/include/Analysis/AnalysisCompositeCut.h +++ b/Analysis/Core/include/Analysis/AnalysisCompositeCut.h @@ -25,6 +25,8 @@ class AnalysisCompositeCut : public AnalysisCut public: AnalysisCompositeCut(bool useAND = kTRUE); AnalysisCompositeCut(const char* name, const char* title, bool useAND = kTRUE); + AnalysisCompositeCut(const AnalysisCompositeCut& c) = default; + AnalysisCompositeCut& operator=(const AnalysisCompositeCut& c) = default; ~AnalysisCompositeCut() override; void AddCut(AnalysisCut* cut) { fCutList.push_back(*cut); }; @@ -38,9 +40,6 @@ class AnalysisCompositeCut : public AnalysisCut bool fOptionUseAND; // true (default): apply AND on all cuts; false: use OR std::vector<AnalysisCut> fCutList; // list of cuts - AnalysisCompositeCut(const AnalysisCompositeCut& c); - AnalysisCompositeCut& operator=(const AnalysisCompositeCut& c); - ClassDef(AnalysisCompositeCut, 1); }; diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index df3ce002134c7..6df2ec3d36cc0 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -195,7 +195,7 @@ class VarManager : public TObject ~VarManager() override; static float fgValues[kNVars]; // array holding all variables computed during analysis - static void ResetValues(int startValue = 0, int endValue = kNVars); + static void ResetValues(int startValue = 0, int endValue = kNVars, float* values = nullptr); private: static bool fgUsedVars[kNVars]; // holds flags for when the corresponding variable is needed (e.g., in the histogram manager, in cuts, mixing handler, etc.) diff --git a/Analysis/Core/src/AnalysisCompositeCut.cxx b/Analysis/Core/src/AnalysisCompositeCut.cxx index de8a5e61813ff..fa97af1af2275 100644 --- a/Analysis/Core/src/AnalysisCompositeCut.cxx +++ b/Analysis/Core/src/AnalysisCompositeCut.cxx @@ -41,16 +41,15 @@ bool AnalysisCompositeCut::IsSelected(float* values) // // apply cuts // - std::vector<AnalysisCut>::iterator it = fCutList.begin(); for (std::vector<AnalysisCut>::iterator it = fCutList.begin(); it < fCutList.end(); ++it) { if (fOptionUseAND && !(*it).IsSelected(values)) - return kFALSE; + return false; if (!fOptionUseAND && (*it).IsSelected(values)) - return kTRUE; + return true; } if (fOptionUseAND) - return kTRUE; + return true; else - return kFALSE; + return false; } diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 3dab4c1044344..6cbfc7b6eb9a0 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -45,13 +45,15 @@ void VarManager::SetVariableDependencies() } //__________________________________________________________________ -void VarManager::ResetValues(int startValue, int endValue) +void VarManager::ResetValues(int startValue, int endValue, float* values) { // // reset all variables to an "innocent" value // NOTE: here we use -9999.0 as a neutral value, but depending on situation, this may not be the case + if (!values) + values = fgValues; for (Int_t i = startValue; i < endValue; ++i) - fgValues[i] = -9999.; + values[i] = -9999.; } //__________________________________________________________________ diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index 34ff149099222..1e566fbc791c7 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -24,23 +24,32 @@ #include <THashList.h> #include <TString.h> #include <iostream> +#include <vector> using std::cout; using std::endl; using namespace o2; using namespace o2::framework; -//using namespace o2::framework::expressions; +using namespace o2::framework::expressions; using namespace o2::aod; // Some definitions namespace o2::aod { + +namespace reducedevent +{ +DECLARE_SOA_COLUMN(Category, category, int); +DECLARE_SOA_COLUMN(IsEventSelected, isEventSelected, int); +} // namespace reducedevent + namespace reducedtrack { -DECLARE_SOA_COLUMN(IsBarrelSelected, isBarrelSelected, int); +DECLARE_SOA_COLUMN(IsBarrelSelected, isBarrelSelected, uint8_t); DECLARE_SOA_COLUMN(IsMuonSelected, isMuonSelected, int); } // namespace reducedtrack + namespace reducedpair { DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); @@ -49,22 +58,27 @@ 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_COLUMN(FilterMap, filterMap, uint8_t); 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(EventCuts, "AOD", "EVENTCUTS", reducedevent::IsEventSelected); +DECLARE_SOA_TABLE(EventCategories, "AOD", "EVENTCATEGORIES", reducedevent::Category); 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, +DECLARE_SOA_TABLE(Dileptons, "AOD", "DILEPTON", reducedtrack::ReducedEventId, reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Charge, reducedpair::FilterMap, reducedpair::Px<reducedpair::Pt, reducedpair::Phi>, reducedpair::Py<reducedpair::Pt, reducedpair::Phi>, reducedpair::Pz<reducedpair::Pt, reducedpair::Eta>, reducedpair::Pmom<reducedpair::Pt, reducedpair::Eta>); using Dilepton = Dileptons::iterator; } // namespace o2::aod -using MyEvent = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended>::iterator; -using MyEventVtxCov = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator; +using MyEvents = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended>; +using MyEventsSelected = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::EventCuts>; +using MyEventsVtxCov = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>; +using MyEventsVtxCovSelected = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov, aod::EventCuts>; using MyBarrelTracks = soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID>; using MyBarrelTracksSelected = soa::Join<aod::ReducedTracks, aod::ReducedTracksBarrel, aod::ReducedTracksBarrelCov, aod::ReducedTracksBarrelPID, aod::BarrelTrackCuts>; using MyMuonTracks = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended>; @@ -83,63 +97,145 @@ constexpr static uint32_t fgEventFillMap = VarManager::ObjTypes::ReducedEvent | 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; +int gNTrackCuts = 2; + +struct EventSelection { + Produces<aod::EventCuts> eventSel; + OutputObj<HistogramManager> fHistMan{"output"}; + AnalysisCompositeCut* fEventCut; + + 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, "Event_BeforeCuts;Event_AfterCuts;"); // 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); + + fEventCut->AddCut(varCut); + // TODO: Add more cuts, also enable cuts which are not easily possible via the VarManager (e.g. trigger selections) + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvents::iterator const& event) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); + + VarManager::FillEvent<fgEventFillMap>(event, fValues); + fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event + if (fEventCut->IsSelected(fValues)) { + fHistMan->FillHistClass("Event_AfterCuts", fValues); + eventSel(1); + } else + eventSel(0); + } +}; + struct BarrelTrackSelection { Produces<aod::BarrelTrackCuts> trackSel; OutputObj<HistogramManager> fHistMan{"output"}; - AnalysisCompositeCut* fTrackCut; + std::vector<AnalysisCompositeCut> fTrackCuts; float* fValues; // array to be used by the VarManager void init(o2::framework::InitContext&) { + DefineCuts(); + 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 + TString cutNames = "TrackBarrel_BeforeCuts;"; + for (int i = 0; i < gNTrackCuts; i++) + cutNames += Form("TrackBarrel_%s;", fTrackCuts[i].GetName()); - DefineCuts(); + DefineHistograms(fHistMan, cutNames.Data()); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill } void DefineCuts() { - fTrackCut = new AnalysisCompositeCut(true); // true: use AND - AnalysisCut* cut1 = new AnalysisCut(); - 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); - cut1->AddCut(VarManager::kITSncls, 2.5, 7.5); - cut1->AddCut(VarManager::kTPCncls, 69.5, 159.5); - AnalysisCut* cut2 = new AnalysisCut(); - cut2->AddCut(VarManager::kPt, 0.5, 3.0); - fTrackCut->AddCut(cut1); - //fTrackCut->AddCut(cut2); - + AnalysisCut* commonCuts = new AnalysisCut(); + commonCuts->AddCut(VarManager::kPt, 1.0, 20.0); + commonCuts->AddCut(VarManager::kTPCsignal, 70.0, 100.0); + commonCuts->AddCut(VarManager::kEta, -0.9, 0.9); + commonCuts->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + commonCuts->AddCut(VarManager::kITSchi2, 0.1, 36.0); + commonCuts->AddCut(VarManager::kTPCncls, 100.0, 161.); + commonCuts->AddCut(VarManager::kTrackDCAxy, -1.0, 1.0); + commonCuts->AddCut(VarManager::kTrackDCAz, -3.0, 3.0); + + AnalysisCut* pidCut1 = new AnalysisCut(); + TF1* cutLow1 = new TF1("cutLow1", "pol1", 0., 10.); + cutLow1->SetParameters(130., -40.0); + pidCut1->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + + AnalysisCut* pidCut2 = new AnalysisCut(); + pidCut2->AddCut(VarManager::kTPCsignal, 73.0, 100.0); + + AnalysisCompositeCut trackCut1("cut1", "cut1", true); // true: use AND + trackCut1.AddCut(commonCuts); + trackCut1.AddCut(pidCut1); + + AnalysisCompositeCut trackCut2("cut2", "cut2", true); // true: use AND + trackCut2.AddCut(commonCuts); + trackCut2.AddCut(pidCut1); + trackCut2.AddCut(pidCut2); + + fTrackCuts.push_back(trackCut1); + fTrackCuts.push_back(trackCut2); + + //gNTrackCuts = fTrackCuts.size(); VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - void process(MyEvent event, MyBarrelTracks const& tracks) + void process(MyEventsSelected::iterator const& event, MyBarrelTracks const& tracks) { - for (int i = 0; i < VarManager::kNVars; ++i) - fValues[i] = -9999.0f; + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables, fValues); // fill event information which might be needed in histograms that combine track and event properties VarManager::FillEvent<fgEventFillMap>(event, fValues); + uint8_t filterMap = uint8_t(0); + for (auto& track : tracks) { - for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) - fValues[i] = -9999.0f; + filterMap = uint8_t(0); VarManager::FillTrack<fgTrackFillMap>(track, fValues); - fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); - - if (fTrackCut->IsSelected(fValues)) { - trackSel(1); - fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); - } else - trackSel(0); + if (event.isEventSelected()) + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + + if ((track.flags() & (uint64_t(1) << 2)) && // kITSrefit + (track.flags() & (uint64_t(1) << 6)) && // kTPCrefit + ((track.itsClusterMap() & (uint8_t(1) << 0)) || (track.itsClusterMap() & (uint8_t(1) << 1)))) //SPD any + { + int i = 0; + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { + if ((*cut).IsSelected(fValues)) { + filterMap |= (uint8_t(1) << i); + fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut).GetName()), fValues); + } + } + } + trackSel(filterMap); } } }; @@ -175,20 +271,20 @@ struct MuonTrackSelection { VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - void process(MyEvent event, MyMuonTracks const& muons) + void process(MyEventsSelected::iterator const& event, MyMuonTracks const& muons) { - for (int i = 0; i < VarManager::kNVars; ++i) - fValues[i] = -9999.0f; + VarManager::ResetValues(0, VarManager::kNMuonTrackVariables, fValues); VarManager::FillEvent<fgEventFillMap>(event, fValues); for (auto& muon : muons) { - for (int i = VarManager::kNBarrelTrackVariables; i < VarManager::kNMuonTrackVariables; ++i) - fValues[i] = -9999.0f; + //VarManager::ResetValues(VarManager::kNBarrelTrackVariables, VarManager::kNMuonTrackVariables, fValues); VarManager::FillTrack<fgMuonFillMap>(muon, fValues); + //if(event.isEventSelected()) fHistMan->FillHistClass("TrackMuon_BeforeCuts", fValues); if (fTrackCut->IsSelected(fValues)) { trackSel(1); + //if(event.isEventSelected()) fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); } else trackSel(0); @@ -199,55 +295,40 @@ struct MuonTrackSelection { struct TableReader { Produces<aod::Dileptons> dileptonList; OutputObj<HistogramManager> fHistMan{"output"}; - AnalysisCompositeCut* fEventCut; //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition - Partition<MyBarrelTracksSelected> posTracks = aod::reducedtrack::charge > 0 && aod::reducedtrack::isBarrelSelected == 1; - Partition<MyBarrelTracksSelected> negTracks = aod::reducedtrack::charge < 0 && aod::reducedtrack::isBarrelSelected == 1; - Partition<MyMuonTracksSelected> posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; - Partition<MyMuonTracksSelected> negMuons = aod::reducedtrack::charge < 0 && aod::reducedtrack::isMuonSelected == 1; + float* fValues; + + Partition<MyBarrelTracksSelected> posTracks = aod::reducedtrack::charge > 0 && aod::reducedtrack::isBarrelSelected > uint8_t(0); + Partition<MyBarrelTracksSelected> negTracks = aod::reducedtrack::charge < 0 && aod::reducedtrack::isBarrelSelected > uint8_t(0); + //Partition<MyMuonTracksSelected> posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; + //Partition<MyMuonTracksSelected> negMuons = aod::reducedtrack::charge < 0 && aod::reducedtrack::isMuonSelected == 1; 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, "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); + TString histNames = ""; + for (int i = 0; i < gNTrackCuts; i++) + histNames += Form("PairsBarrelPM_cut%d;PairsBarrelPP_cut%d;PairsBarrelMM_cut%d;", i + 1, i + 1, i + 1); - VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + DefineHistograms(fHistMan, histNames.Data()); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill } - void process(MyEventVtxCov event, MyBarrelTracksSelected const& tracks, MyMuonTracksSelected const& muons) + //void process(soa::Filtered<MyEventsVtxCovSelected>::iterator const& event, MyBarrelTracksSelected const& tracks, MyMuonTracksSelected const& muons) + void process(MyEventsVtxCovSelected::iterator const& event, MyBarrelTracksSelected const& tracks /*, MyMuonTracksSelected const& muons*/) { - // Reset the VarManager::fgValues array - // The reset can be done selectively, using arguments in the ResetValues() function - VarManager::ResetValues(); - - VarManager::FillEvent<fgEventFillMap>(event); - fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event - if (!fEventCut->IsSelected(VarManager::fgValues)) + if (!event.isEventSelected()) return; - fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars, fValues); + + VarManager::FillEvent<fgEventFillMap>(event, fValues); // Run the same event pairing for barrel tracks // TODO: Use combinations() when this will work for Partitions @@ -257,35 +338,53 @@ struct TableReader { fHistMan->FillHistClass("PairsBarrelPM", VarManager::fgValues); } */ - + uint8_t filter = 0; for (auto tpos : posTracks) { for (auto tneg : negTracks) { // +- pairs - VarManager::FillPair(tpos, tneg); - dileptonList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], 0); - fHistMan->FillHistClass("PairsBarrelPM", VarManager::fgValues); + filter = tpos.isBarrelSelected() & tneg.isBarrelSelected(); + if (!filter) // the tracks must have at least one filter bit in common to continue + continue; + VarManager::FillPair(tpos, tneg, fValues); + dileptonList(event, fValues[VarManager::kMass], fValues[VarManager::kPt], fValues[VarManager::kEta], fValues[VarManager::kPhi], 0, filter); + for (int i = 0; i < gNTrackCuts; ++i) { + if (filter & (uint8_t(1) << i)) + fHistMan->FillHistClass(Form("PairsBarrelPM_cut%d", i + 1), fValues); + } } 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); + filter = tpos.isBarrelSelected() & tpos2.isBarrelSelected(); + if (!filter) // the tracks must have at least one filter bit in common to continue + continue; + VarManager::FillPair(tpos, tpos2, fValues); + dileptonList(event, fValues[VarManager::kMass], fValues[VarManager::kPt], fValues[VarManager::kEta], fValues[VarManager::kPhi], 2, filter); + for (int i = 0; i < gNTrackCuts; ++i) { + if (filter & (uint8_t(1) << i)) + fHistMan->FillHistClass(Form("PairsBarrelPP_cut%d", i + 1), fValues); + } } } 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); + filter = tneg.isBarrelSelected() & tneg2.isBarrelSelected(); + if (!filter) // the tracks must have at least one filter bit in common to continue + continue; + VarManager::FillPair(tneg, tneg2, fValues); + dileptonList(event, fValues[VarManager::kMass], fValues[VarManager::kPt], fValues[VarManager::kEta], fValues[VarManager::kPhi], -2, filter); + for (int i = 0; i < gNTrackCuts; ++i) { + if (filter & (uint8_t(1) << i)) + fHistMan->FillHistClass(Form("PairsBarrelMM_cut%d", i + 1), fValues); + } } } // same event pairing for muons - for (auto& tpos : posMuons) { + /*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); + VarManager::FillPair(tpos, tneg, fValues); + fHistMan->FillHistClass("PairsMuon", fValues); } - } + }*/ } }; @@ -297,13 +396,15 @@ struct DileptonHadronAnalysis { // It requires the TableReader task to be in the workflow and produce the dilepton table // OutputObj<HistogramManager> fHistMan{"output"}; - AnalysisCompositeCut* fHadronCut; + AnalysisCompositeCut* fHadronCut; // TODO: this cut will be moved into the barrel/muon track selection task //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; + Filter eventFilter = aod::reducedevent::isEventSelected == 1; + Partition<aod::Dileptons> 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; @@ -330,7 +431,7 @@ struct DileptonHadronAnalysis { 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::kITSchi2, 0.1, 36.0); cut1->AddCut(VarManager::kITSncls, 2.5, 7.5); cut1->AddCut(VarManager::kTPCncls, 69.5, 159.5); fHadronCut->AddCut(cut1); @@ -338,33 +439,30 @@ struct DileptonHadronAnalysis { 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) + void process(soa::Filtered<MyEventsVtxCovSelected>::iterator const& event, MyBarrelTracks const& hadrons, aod::Dileptons const& dileptons) { - for (int i = 0; i < VarManager::kNVars; ++i) - fValuesHadron[i] = -9999.0f; + VarManager::ResetValues(0, VarManager::kNVars, fValuesHadron); + VarManager::ResetValues(0, VarManager::kNVars, fValuesDilepton); // fill event information which might be needed in histograms that combine track/pair and event properties VarManager::FillEvent<fgEventFillMap>(event, fValuesHadron); + VarManager::FillEvent<fgEventFillMap>(event, fValuesDilepton); // TODO: check if needed (just for dilepton QA which might be depending on event wise variables) // 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<fgDileptonFillMap>(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<fgTrackFillMap>(hadron, fValuesHadron); - if (!fHadronCut->IsSelected(fValuesHadron)) + if (!fHadronCut->IsSelected(fValuesHadron)) // TODO: this will be moved to a partition when the selection will be done in the barrel/muon track selection continue; 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 + // 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); @@ -376,10 +474,12 @@ struct DileptonHadronAnalysis { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ + adaptAnalysisTask<EventSelection>("my-event-selection"), adaptAnalysisTask<BarrelTrackSelection>("barrel-track-selection"), - adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), - adaptAnalysisTask<TableReader>("table-reader"), - adaptAnalysisTask<DileptonHadronAnalysis>("dilepton-hadron")}; + //adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), + adaptAnalysisTask<TableReader>("table-reader") + //adaptAnalysisTask<DileptonHadronAnalysis>("dilepton-hadron") + }; } void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TString histClasses) @@ -389,8 +489,22 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin // 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}; + const int kNRuns = 135; + int runs[kNRuns] = { + 244917, 244918, 244975, 244980, 244982, 244983, 245064, 245066, 245068, 245145, + 245146, 245151, 245152, 245231, 245232, 245259, 245343, 245345, 245346, 245347, + 245349, 245353, 245396, 245397, 245401, 245407, 245409, 245411, 245439, 245441, + 245446, 245450, 245452, 245454, 245496, 245497, 245501, 245504, 245505, 245507, + 245535, 245540, 245542, 245543, 245544, 245545, 245554, 245683, 245692, 245700, + 245702, 245705, 245829, 245831, 245833, 245923, 245949, 245952, 245954, 245963, + 246001, 246003, 246012, 246036, 246037, 246042, 246048, 246049, 246052, 246053, + 246087, 246089, 246113, 246115, 246148, 246151, 246152, 246153, 246178, 246180, + 246181, 246182, 246185, 246217, 246222, 246225, 246271, 246272, 246275, 246276, + 246391, 246392, 246424, 246428, 246431, 246434, 246487, 246488, 246493, 246495, + 246675, 246676, 246750, 246751, 246757, 246758, 246759, 246760, 246763, 246765, + 246766, 246804, 246805, 246807, 246808, 246809, 246810, 246844, 246845, 246846, + 246847, 246851, 246865, 246867, 246870, 246871, 246928, 246945, 246948, 246980, + 246982, 246984, 246989, 246991, 246994}; TString runsStr; for (int i = 0; i < kNRuns; i++) runsStr += Form("%d;", runs[i]); @@ -403,39 +517,7 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin 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) @@ -444,37 +526,17 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin 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(), "TPCncls_Run", "Number of cluster in TPC", true, kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, + 10, -0.5, 159.5, VarManager::kTPCncls, 10, 0., 1., VarManager::kNothing, runsStr.Data()); // 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 + + histMan->AddHistogram(classStr.Data(), "DCAxy", "DCAxy", false, 100, -3.0, 3.0, VarManager::kTrackDCAxy); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "DCAz", "DCAz", false, 100, -5.0, 5.0, VarManager::kTrackDCAz); // TH1F histogram } if (classStr.Contains("Muon")) { @@ -500,11 +562,26 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin 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")) { + 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_Cent", "", false, 125, 0.0, 5.0, VarManager::kMass, 20, 0.0, 20.0, VarManager::kPt, 10, 0.0, 100.0, VarManager::kCentVZERO); + histMan->AddHistogram(classStr.Data(), "Mass_Pt", "", false, 125, 0.0, 5.0, VarManager::kMass, 100, 0.0, 20.0, VarManager::kPt); + histMan->AddHistogram(classStr.Data(), "Mass", "", false, 125, 0.0, 5.0, VarManager::kMass); + histMan->AddHistogram(classStr.Data(), "Mass_Run", "", true, kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, 10, 0.0, 5.0, VarManager::kMass, + 10, 0., 1., VarManager::kNothing, runsStr.Data()); + } + 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); From 0fd05e45aa5907e4bc727fb13bb5fd77c4acbfce Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Thu, 17 Sep 2020 03:46:25 -0300 Subject: [PATCH 0658/1751] Cascades, V0 finder, more stuff to LF folder (#4366) --- .../include/Analysis/StrangenessTables.h | 116 ++++++++- Analysis/Tasks/CMakeLists.txt | 10 - Analysis/Tasks/PWGLF/CMakeLists.txt | 25 ++ Analysis/Tasks/PWGLF/cascadeconsumer.cxx | 151 +++++++++++ Analysis/Tasks/PWGLF/cascadeproducer.cxx | 168 ++++++++++++ .../Tasks/{ => PWGLF}/lambdakzeroconsumer.cxx | 24 +- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 244 ++++++++++++++++++ .../Tasks/{ => PWGLF}/lambdakzeroproducer.cxx | 0 8 files changed, 720 insertions(+), 18 deletions(-) create mode 100644 Analysis/Tasks/PWGLF/cascadeconsumer.cxx create mode 100644 Analysis/Tasks/PWGLF/cascadeproducer.cxx rename Analysis/Tasks/{ => PWGLF}/lambdakzeroconsumer.cxx (78%) create mode 100644 Analysis/Tasks/PWGLF/lambdakzerofinder.cxx rename Analysis/Tasks/{ => PWGLF}/lambdakzeroproducer.cxx (100%) diff --git a/Analysis/DataModel/include/Analysis/StrangenessTables.h b/Analysis/DataModel/include/Analysis/StrangenessTables.h index 2242c52095e9e..eb7997bed47a5 100644 --- a/Analysis/DataModel/include/Analysis/StrangenessTables.h +++ b/Analysis/DataModel/include/Analysis/StrangenessTables.h @@ -47,6 +47,10 @@ DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, [](float X, float Y, float Z, float DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kPiPlus)}); }); DECLARE_SOA_DYNAMIC_COLUMN(MAntiLambda, mAntiLambda, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kProton)}); }); DECLARE_SOA_DYNAMIC_COLUMN(MK0Short, mK0Short, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kPiPlus)}); }); + +DECLARE_SOA_DYNAMIC_COLUMN(YK0Short, yK0Short, [](float Px, float Py, float Pz) { return RecoDecay::Y(array{Px, Py, Pz}, RecoDecay::getMassPDG(kK0)); }); +DECLARE_SOA_DYNAMIC_COLUMN(YLambda, yLambda, [](float Px, float Py, float Pz) { return RecoDecay::Y(array{Px, Py, Pz}, RecoDecay::getMassPDG(kLambda0)); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float Px, float Py, float Pz) { return RecoDecay::Eta(array{Px, Py, Pz}); }); } // namespace v0data namespace v0dataext @@ -70,7 +74,12 @@ DECLARE_SOA_TABLE(V0Data, "AOD", "V0DATA", //Invariant masses v0data::MLambda<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>, v0data::MAntiLambda<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>, - v0data::MK0Short<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>); + v0data::MK0Short<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>, + + //Longitudinal + v0data::YK0Short<v0dataext::Px, v0dataext::Py, v0dataext::Pz>, + v0data::YLambda<v0dataext::Px, v0dataext::Py, v0dataext::Pz>, + v0data::Eta<v0dataext::Px, v0dataext::Py, v0dataext::Pz>); using V0DataOrigin = V0Data; @@ -80,6 +89,111 @@ DECLARE_SOA_EXTENDED_TABLE_USER(V0DataExt, V0DataOrigin, "V0DATAEXT", using V0DataFull = V0DataExt; +namespace v0finderdata +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +} +DECLARE_SOA_TABLE(V0FinderData, "AOD", "V0FINDERDATA", o2::soa::Index<>, v0finderdata::CollisionId); + +namespace cascdata +{ +//General V0 properties: position, momentum +DECLARE_SOA_COLUMN(Charge, charge, int); +DECLARE_SOA_COLUMN(PxPos, pxpos, float); +DECLARE_SOA_COLUMN(PyPos, pypos, float); +DECLARE_SOA_COLUMN(PzPos, pzpos, float); +DECLARE_SOA_COLUMN(PxNeg, pxneg, float); +DECLARE_SOA_COLUMN(PyNeg, pyneg, float); +DECLARE_SOA_COLUMN(PzNeg, pzneg, float); +DECLARE_SOA_COLUMN(PxBach, pxbach, float); +DECLARE_SOA_COLUMN(PyBach, pybach, float); +DECLARE_SOA_COLUMN(PzBach, pzbach, float); +DECLARE_SOA_COLUMN(X, x, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Z, z, float); +DECLARE_SOA_COLUMN(Xlambda, xlambda, float); +DECLARE_SOA_COLUMN(Ylambda, ylambda, float); +DECLARE_SOA_COLUMN(Zlambda, zlambda, float); + +//Saved from finding: DCAs +DECLARE_SOA_COLUMN(DCAV0Daughters, dcaV0daughters, float); +DECLARE_SOA_COLUMN(DCACascDaughters, dcacascdaughters, float); +DECLARE_SOA_COLUMN(DCAPosToPV, dcapostopv, float); +DECLARE_SOA_COLUMN(DCANegToPV, dcanegtopv, float); +DECLARE_SOA_COLUMN(DCABachToPV, dcabachtopv, float); + +//Derived expressions +//Momenta +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float Px, float Py) { return RecoDecay::sqrtSumOfSquares(Px, Py); }); + +//Length quantities +DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, [](float xlambda, float ylambda) { return RecoDecay::sqrtSumOfSquares(xlambda, ylambda); }); +DECLARE_SOA_DYNAMIC_COLUMN(CascRadius, cascradius, [](float x, float y) { return RecoDecay::sqrtSumOfSquares(x, y); }); + +//CosPAs +DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, [](float Xlambda, float Ylambda, float Zlambda, float PxLambda, float PyLambda, float PzLambda, float pvX, float pvY, float pvZ) { return RecoDecay::CPA(array{pvX, pvY, pvZ}, array{Xlambda, Ylambda, Zlambda}, array{PxLambda, PyLambda, PzLambda}); }); +DECLARE_SOA_DYNAMIC_COLUMN(CascCosPA, casccosPA, [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { return RecoDecay::CPA(array{pvX, pvY, pvZ}, array{X, Y, Z}, array{Px, Py, Pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(DCAV0ToPV, dcav0topv, [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { return TMath::Sqrt((TMath::Power((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + TMath::Power((pvX - X) * Pz - (pvZ - Z) * Px, 2) + TMath::Power((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); +DECLARE_SOA_DYNAMIC_COLUMN(DCACascToPV, dcacasctopv, [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { return TMath::Sqrt((TMath::Power((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + TMath::Power((pvX - X) * Pz - (pvZ - Z) * Px, 2) + TMath::Power((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); + +//Calculated on the fly with mass assumption + dynamic tables +DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, [](int charge, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, charge < 0 ? array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kPiPlus)} : array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kProton)}); }); +//Calculated on the fly with mass assumption + dynamic tables + +DECLARE_SOA_DYNAMIC_COLUMN(MXi, mXi, [](float pxbach, float pybach, float pzbach, float PxLambda, float PyLambda, float PzLambda) { return RecoDecay::M(array{array{pxbach, pybach, pzbach}, array{PxLambda, PyLambda, PzLambda}}, array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kLambda0)}); }); +DECLARE_SOA_DYNAMIC_COLUMN(MOmega, mOmega, [](float pxbach, float pybach, float pzbach, float PxLambda, float PyLambda, float PzLambda) { return RecoDecay::M(array{array{pxbach, pybach, pzbach}, array{PxLambda, PyLambda, PzLambda}}, array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kLambda0)}); }); + +DECLARE_SOA_DYNAMIC_COLUMN(YXi, yXi, [](float Px, float Py, float Pz) { return RecoDecay::Y(array{Px, Py, Pz}, 1.32171); }); +DECLARE_SOA_DYNAMIC_COLUMN(YOmega, yOmega, [](float Px, float Py, float Pz) { return RecoDecay::Y(array{Px, Py, Pz}, 1.67245); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float Px, float Py, float Pz) { return RecoDecay::Eta(array{Px, Py, Pz}); }); +} // namespace cascdata + +namespace cascdataext +{ +DECLARE_SOA_EXPRESSION_COLUMN(PxLambda, pxlambda, float, 1.f * aod::cascdata::pxpos + 1.f * aod::cascdata::pxneg); +DECLARE_SOA_EXPRESSION_COLUMN(PyLambda, pylambda, float, 1.f * aod::cascdata::pypos + 1.f * aod::cascdata::pyneg); +DECLARE_SOA_EXPRESSION_COLUMN(PzLambda, pzlambda, float, 1.f * aod::cascdata::pzpos + 1.f * aod::cascdata::pzneg); +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, 1.f * aod::cascdata::pxpos + 1.f * aod::cascdata::pxneg + 1.f * aod::cascdata::pxbach); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, 1.f * aod::cascdata::pypos + 1.f * aod::cascdata::pyneg + 1.f * aod::cascdata::pybach); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::cascdata::pzpos + 1.f * aod::cascdata::pzneg + 1.f * aod::cascdata::pzbach); +} // namespace cascdataext + +DECLARE_SOA_TABLE(CascData, "AOD", "CASCDATA", + cascdata::Charge, + cascdata::X, cascdata::Y, cascdata::Z, + cascdata::Xlambda, cascdata::Ylambda, cascdata::Zlambda, + cascdata::PxPos, cascdata::PyPos, cascdata::PzPos, + cascdata::PxNeg, cascdata::PyNeg, cascdata::PzNeg, + cascdata::PxBach, cascdata::PyBach, cascdata::PzBach, + cascdata::DCAV0Daughters, cascdata::DCACascDaughters, + cascdata::DCAPosToPV, cascdata::DCANegToPV, cascdata::DCABachToPV, + + //Dynamic columns + cascdata::Pt<cascdataext::Px, cascdataext::Py>, + cascdata::V0Radius<cascdata::Xlambda, cascdata::Ylambda>, + cascdata::CascRadius<cascdata::X, cascdata::Y>, + cascdata::V0CosPA<cascdata::Xlambda, cascdata::Ylambda, cascdata::Zlambda, cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda>, + cascdata::CascCosPA<cascdata::X, cascdata::Y, cascdata::Z, cascdataext::Px, cascdataext::Py, cascdataext::Pz>, + cascdata::DCAV0ToPV<cascdata::Xlambda, cascdata::Ylambda, cascdata::Zlambda, cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda>, + cascdata::DCACascToPV<cascdata::X, cascdata::Y, cascdata::Z, cascdataext::Px, cascdataext::Py, cascdataext::Pz>, + + //Invariant masses + cascdata::MLambda<cascdata::Charge, cascdata::PxPos, cascdata::PyPos, cascdata::PzPos, cascdata::PxNeg, cascdata::PyNeg, cascdata::PzNeg>, + cascdata::MXi<cascdata::PxBach, cascdata::PyBach, cascdata::PzBach, cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda>, + cascdata::MOmega<cascdata::PxBach, cascdata::PyBach, cascdata::PzBach, cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda>, + //Longitudinal + cascdata::YXi<cascdataext::Px, cascdataext::Py, cascdataext::Pz>, + cascdata::YOmega<cascdataext::Px, cascdataext::Py, cascdataext::Pz>, + cascdata::Eta<cascdataext::Px, cascdataext::Py, cascdataext::Pz>); + +using CascDataOrigin = CascData; + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(CascDataExt, CascDataOrigin, "CascDATAEXT", + cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda, + cascdataext::Px, cascdataext::Py, cascdataext::Pz); + +using CascDataFull = CascDataExt; } // namespace o2::aod #endif // O2_ANALYSIS_STRANGENESSTABLES_H_ diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 43d05a6f2bbd1..b0fadfc5dab07 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -109,14 +109,4 @@ o2_add_dpl_workflow(run2-matcher o2_add_dpl_workflow(run3-matcher SOURCES run3Matcher.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(lambdakzeroproducer - SOURCES lambdakzeroproducer - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(lambdakzeroconsumer - SOURCES lambdakzeroconsumer - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt index a517969a90861..76b96f23e02d1 100644 --- a/Analysis/Tasks/PWGLF/CMakeLists.txt +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -12,3 +12,28 @@ o2_add_dpl_workflow(nuclei-spectra SOURCES NucleiSpectraTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(lambdakzeroproducer + SOURCES lambdakzeroproducer + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(lambdakzeroconsumer + SOURCES lambdakzeroconsumer + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(lambdakzerofinder + SOURCES lambdakzerofinder + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(cascadeproducer + SOURCES cascadeproducer + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(cascadeconsumer + SOURCES cascadeconsumer + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx new file mode 100644 index 0000000000000..b511f7fa62b07 --- /dev/null +++ b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx @@ -0,0 +1,151 @@ +// 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 "ReconstructionDataFormats/Track.h" +#include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" +#include "Analysis/StrangenessTables.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" + +#include <TFile.h> +#include <TH2F.h> +#include <TProfile.h> +#include <TLorentzVector.h> +#include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> +#include <cmath> +#include <array> +#include <cstdlib> +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +struct cascadeQA { + //Basic checks + OutputObj<TH1F> hMassXiMinus{TH1F("hMassXiMinus", "", 3000, 0.0, 3.0)}; + OutputObj<TH1F> hMassXiPlus{TH1F("hMassXiPlus", "", 3000, 0.0, 3.0)}; + OutputObj<TH1F> hMassOmegaMinus{TH1F("hMassOmegaMinus", "", 3000, 0.0, 3.0)}; + OutputObj<TH1F> hMassOmegaPlus{TH1F("hMassOmegaPlus", "", 3000, 0.0, 3.0)}; + + OutputObj<TH1F> hV0Radius{TH1F("hV0Radius", "", 1000, 0.0, 100)}; + OutputObj<TH1F> hCascRadius{TH1F("hCascRadius", "", 1000, 0.0, 100)}; + OutputObj<TH1F> hV0CosPA{TH1F("hV0CosPA", "", 1000, 0.95, 1.0)}; + OutputObj<TH1F> hCascCosPA{TH1F("hCascCosPA", "", 1000, 0.95, 1.0)}; + OutputObj<TH1F> hDCAPosToPV{TH1F("hDCAPosToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCANegToPV{TH1F("hDCANegToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCABachToPV{TH1F("hDCABachToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCAV0ToPV{TH1F("hDCAV0ToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCAV0Dau{TH1F("hDCAV0Dau", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCACascDau{TH1F("hDCACascDau", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hLambdaMass{TH1F("hLambdaMass", "", 1000, 0.0, 10.0)}; + + void process(aod::Collision const& collision, soa::Join<aod::Cascades, aod::CascDataExt> const& Cascades) + { + for (auto& casc : Cascades) { + if (casc.charge() < 0) { //FIXME: could be done better... + hMassXiMinus->Fill(casc.mXi()); + hMassOmegaMinus->Fill(casc.mOmega()); + } else { + hMassXiPlus->Fill(casc.mXi()); + hMassOmegaPlus->Fill(casc.mOmega()); + } + //The basic eleven! + hV0Radius->Fill(casc.v0radius()); + hCascRadius->Fill(casc.cascradius()); + hV0CosPA->Fill(casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + hCascCosPA->Fill(casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + hDCAPosToPV->Fill(casc.dcapostopv()); + hDCANegToPV->Fill(casc.dcanegtopv()); + hDCABachToPV->Fill(casc.dcabachtopv()); + hDCAV0ToPV->Fill(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + hDCAV0Dau->Fill(casc.dcaV0daughters()); + hDCACascDau->Fill(casc.dcacascdaughters()); + hLambdaMass->Fill(casc.mLambda()); + } + } +}; + +struct cascadeconsumer { + OutputObj<TH3F> h3dMassXiMinus{TH3F("h3dMassXiMinus", "", 20, 0, 100, 200, 0, 10, 200, 1.322 - 0.100, 1.322 + 0.100)}; + OutputObj<TH3F> h3dMassXiPlus{TH3F("h3dMassXiPlus", "", 20, 0, 100, 200, 0, 10, 200, 1.322 - 0.100, 1.322 + 0.100)}; + OutputObj<TH3F> h3dMassOmegaMinus{TH3F("h3dMassOmegaMinus", "", 20, 0, 100, 200, 0, 10, 200, 1.672 - 0.100, 1.672 + 0.100)}; + OutputObj<TH3F> h3dMassOmegaPlus{TH3F("h3dMassOmegaPlus", "", 20, 0, 100, 200, 0, 10, 200, 1.672 - 0.100, 1.672 + 0.100)}; + + //Selection criteria + Configurable<double> v0cospa{"v0cospa", 0.999, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<double> casccospa{"casccospa", 0.999, "Casc CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<float> dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + Configurable<float> dcacascdau{"dcacascdau", .3, "DCA Casc Daughters"}; + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<float> dcabachtopv{"dcabachtopv", .1, "DCA Bach To PV"}; + Configurable<float> dcav0topv{"dcav0topv", .1, "DCA V0 To PV"}; + Configurable<float> v0radius{"v0radius", 2.0, "v0radius"}; + Configurable<float> cascradius{"cascradius", 1.0, "cascradius"}; + Configurable<float> v0masswindow{"v0masswindow", 0.008, "v0masswindow"}; + + Filter preFilterV0 = + aod::cascdata::dcapostopv > dcapostopv&& aod::cascdata::dcanegtopv > dcanegtopv&& + aod::cascdata::dcabachtopv > dcabachtopv&& + aod::cascdata::dcaV0daughters < dcav0dau&& aod::cascdata::dcacascdaughters < dcacascdau; + + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::Cascades, aod::CascDataExt>> const& Cascades) + { + if (!collision.alias()[kINT7]) + return; + if (!collision.sel7()) + return; + for (auto& casc : Cascades) { + //FIXME: dynamic columns cannot be filtered on? + if (casc.v0radius() > v0radius && + casc.cascradius() > cascradius && + casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && + casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospa && + casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) { + if (casc.charge() < 0) { //FIXME: could be done better... + if (TMath::Abs(casc.yXi()) < 0.5) + h3dMassXiMinus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); + if (TMath::Abs(casc.yOmega()) < 0.5) + h3dMassOmegaMinus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } else { + if (TMath::Abs(casc.yXi()) < 0.5) + h3dMassXiPlus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); + if (TMath::Abs(casc.yOmega()) < 0.5) + h3dMassOmegaPlus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } + } + } + } +}; + +/// Extends the v0data table with expression columns +struct cascadeinitializer { + Spawns<aod::CascDataExt> cascdataext; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<cascadeconsumer>("lf-cascadeconsumer"), + adaptAnalysisTask<cascadeQA>("lf-cascadeQA"), + adaptAnalysisTask<cascadeinitializer>("lf-cascadeinitializer")}; +} diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx new file mode 100644 index 0000000000000..11cf0abe558d3 --- /dev/null +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -0,0 +1,168 @@ +// 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/SecondaryVertexHF.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" +#include "Analysis/StrangenessTables.h" + +#include <TFile.h> +#include <TH2F.h> +#include <TProfile.h> +#include <TLorentzVector.h> +#include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> +#include <cmath> +#include <array> +#include <cstdlib> +#include "PID/PIDResponse.h" +#include "Framework/ASoAHelpers.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +/// Cascade builder task: rebuilds cascades +struct cascadeproducer { + Produces<aod::CascData> cascdata; + + OutputObj<TH1F> hEventCounter{TH1F("hEventCounter", "", 1, 0, 1)}; + OutputObj<TH1F> hCascCandidate{TH1F("hCascCandidate", "", 10, 0, 10)}; + + //Configurables + Configurable<double> d_bz{"d_bz", -5.0, "bz field"}; + Configurable<double> d_UseAbsDCA{"d_UseAbsDCA", kTRUE, "Use Abs DCAs"}; + + /// Extracts dca in the XY plane + /// \return dcaXY + template <typename T, typename U> + auto getdcaXY(const T& track, const U& coll) + { + //Calculate DCAs + auto sinAlpha = sin(track.alpha()); + auto cosAlpha = cos(track.alpha()); + auto globalX = track.x() * cosAlpha - track.y() * sinAlpha; + auto globalY = track.x() * sinAlpha + track.y() * cosAlpha; + return sqrt(pow((globalX - coll[0]), 2) + + pow((globalY - coll[1]), 2)); + } + + void process(aod::Collision const& collision, aod::V0s const& V0s, aod::Cascades const& Cascades, aod::FullTracks const& trackss) + { + //Define o2 fitter, 2-prong + o2::vertexing::DCAFitterN<2> fitterV0, fitterCasc; + fitterV0.setBz(d_bz); + fitterV0.setPropagateToPCA(true); + fitterV0.setMaxR(200.); + fitterV0.setMinParamChange(1e-3); + fitterV0.setMinRelChi2Change(0.9); + fitterV0.setMaxDZIni(1e9); + fitterV0.setMaxChi2(1e9); + fitterV0.setUseAbsDCA(d_UseAbsDCA); + + fitterCasc.setBz(d_bz); + fitterCasc.setPropagateToPCA(true); + fitterCasc.setMaxR(200.); + fitterCasc.setMinParamChange(1e-3); + fitterCasc.setMinRelChi2Change(0.9); + fitterCasc.setMaxDZIni(1e9); + fitterCasc.setMaxChi2(1e9); + fitterCasc.setUseAbsDCA(d_UseAbsDCA); + + hEventCounter->Fill(0.5); + std::array<float, 3> pVtx = {collision.posX(), collision.posY(), collision.posZ()}; + + for (auto& casc : Cascades) { + auto charge = -1; + std::array<float, 3> pos = {0.}; + std::array<float, 3> posXi = {0.}; + std::array<float, 3> pvecpos = {0.}; + std::array<float, 3> pvecneg = {0.}; + std::array<float, 3> pvecbach = {0.}; + + hCascCandidate->Fill(0.5); + + //Acquire basic tracks + auto pTrack = getTrackParCov(casc.v0().posTrack()); + auto nTrack = getTrackParCov(casc.v0().negTrack()); + auto bTrack = getTrackParCov(casc.bachelor()); + if (casc.bachelor().signed1Pt() > 0) + charge = +1; + + int nCand = fitterV0.process(pTrack, nTrack); + if (nCand != 0) { + fitterV0.propagateTracksToVertex(); + hCascCandidate->Fill(1.5); + const auto& v0vtx = fitterV0.getPCACandidate(); + for (int i = 0; i < 3; i++) + pos[i] = v0vtx[i]; + + std::array<float, 21> cov0 = {0}; + std::array<float, 21> cov1 = {0}; + std::array<float, 21> covV0 = {0}; + + //Covariance matrix calculation + const int momInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + fitterV0.getTrack(0).getPxPyPzGlo(pvecpos); + fitterV0.getTrack(1).getPxPyPzGlo(pvecneg); + fitterV0.getTrack(0).getCovXYZPxPyPzGlo(cov0); + fitterV0.getTrack(1).getCovXYZPxPyPzGlo(cov1); + for (int i = 0; i < 6; i++) { + int j = momInd[i]; + covV0[j] = cov0[j] + cov1[j]; + } + auto covVtxV0 = fitterV0.calcPCACovMatrix(); + covV0[0] = covVtxV0(0, 0); + covV0[1] = covVtxV0(1, 0); + covV0[2] = covVtxV0(1, 1); + covV0[3] = covVtxV0(2, 0); + covV0[4] = covVtxV0(2, 1); + covV0[5] = covVtxV0(2, 2); + + const std::array<float, 3> vertex = {(float)v0vtx[0], (float)v0vtx[1], (float)v0vtx[2]}; + const std::array<float, 3> momentum = {pvecpos[0] + pvecneg[0], pvecpos[1] + pvecneg[1], pvecpos[2] + pvecneg[2]}; + + auto tV0 = o2::track::TrackParCov(vertex, momentum, covV0, 0); + tV0.setQ2Pt(0); //No bending, please + int nCand2 = fitterCasc.process(tV0, bTrack); + if (nCand2 != 0) { + fitterCasc.propagateTracksToVertex(); + hCascCandidate->Fill(2.5); + const auto& cascvtx = fitterCasc.getPCACandidate(); + for (int i = 0; i < 3; i++) + posXi[i] = cascvtx[i]; + fitterCasc.getTrack(1).getPxPyPzGlo(pvecbach); + } //end if cascade recoed + } //end if v0 recoed + //Fill table, please + cascdata(charge, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], + pvecpos[0], pvecpos[1], pvecpos[2], + pvecneg[0], pvecneg[1], pvecneg[2], + pvecbach[0], pvecbach[1], pvecbach[2], + fitterV0.getChi2AtPCACandidate(), fitterCasc.getChi2AtPCACandidate(), + getdcaXY(casc.v0().posTrack(), pVtx), + getdcaXY(casc.v0().negTrack(), pVtx), + getdcaXY(casc.bachelor(), pVtx)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<cascadeproducer>("lf-cascadeproducer")}; +} diff --git a/Analysis/Tasks/lambdakzeroconsumer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx similarity index 78% rename from Analysis/Tasks/lambdakzeroconsumer.cxx rename to Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx index 6cf17b8f1cebd..9a133dcfd4cf5 100644 --- a/Analysis/Tasks/lambdakzeroconsumer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx @@ -17,6 +17,8 @@ #include "Analysis/StrangenessTables.h" #include "Analysis/TrackSelection.h" #include "Analysis/TrackSelectionTables.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" #include <TFile.h> #include <TH2F.h> @@ -66,9 +68,9 @@ struct lambdakzeroQA { }; struct lambdakzeroconsumer { - OutputObj<TH2F> h2dMassK0Short{TH2F("h2dMassK0Short", "", 200, 0, 10, 200, 0.450, 0.550)}; - OutputObj<TH2F> h2dMassLambda{TH2F("h2dMassLambda", "", 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; - OutputObj<TH2F> h2dMassAntiLambda{TH2F("h2dMassAntiLambda", "", 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; + OutputObj<TH3F> h3dMassK0Short{TH3F("h3dMassK0Short", "", 20, 0, 100, 200, 0, 10, 200, 0.450, 0.550)}; + OutputObj<TH3F> h3dMassLambda{TH3F("h3dMassLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; + OutputObj<TH3F> h3dMassAntiLambda{TH3F("h3dMassAntiLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; //Selection criteria Configurable<double> v0cospa{"v0cospa", 0.995, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) @@ -80,14 +82,22 @@ struct lambdakzeroconsumer { Filter preFilterV0 = aod::v0data::dcapostopv > dcapostopv&& aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; - void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::V0s, aod::V0DataExt>> const& fullV0s) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::V0s, aod::V0DataExt>> const& fullV0s) { + if (!collision.alias()[kINT7]) + return; + if (!collision.sel7()) + return; + for (auto& v0 : fullV0s) { //FIXME: could not find out how to filter cosPA and radius variables (dynamic columns) if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa) { - h2dMassLambda->Fill(v0.pt(), v0.mLambda()); - h2dMassAntiLambda->Fill(v0.pt(), v0.mAntiLambda()); - h2dMassK0Short->Fill(v0.pt(), v0.mK0Short()); + if (TMath::Abs(v0.yLambda()) < 0.5) { + h3dMassLambda->Fill(collision.centV0M(), v0.pt(), v0.mLambda()); + h3dMassAntiLambda->Fill(collision.centV0M(), v0.pt(), v0.mAntiLambda()); + } + if (TMath::Abs(v0.yK0Short()) < 0.5) + h3dMassK0Short->Fill(collision.centV0M(), v0.pt(), v0.mK0Short()); } } } diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx new file mode 100644 index 0000000000000..9baf319c218e3 --- /dev/null +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -0,0 +1,244 @@ +// 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. +// +// This task re-reconstructs the V0s and cascades + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Analysis/SecondaryVertexHF.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" +#include "PID/PIDResponse.h" +#include "Analysis/StrangenessTables.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" + +#include <TFile.h> +#include <TLorentzVector.h> +#include <TH1F.h> +#include <TH2F.h> +#include <TProfile.h> +#include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> +#include <cmath> +#include <array> +#include <cstdlib> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using namespace ROOT::Math; + +struct lambdakzerofinder { + Produces<aod::V0Data> v0data; + Produces<aod::V0FinderData> v0finderdata; + + OutputObj<TH1F> hCandPerEvent{TH1F("hCandPerEvent", "", 1000, 0, 1000)}; + + OutputObj<TH1F> hV0PosCrossedRows{TH1F("hV0PosCrossedRows", "", 160, 0, 160)}; + OutputObj<TH1F> hV0NegCrossedRows{TH1F("hV0NegCrossedRows", "", 160, 0, 160)}; + OutputObj<TH1F> hV0CosPA{TH1F("hV0CosPA", "", 2000, 0.9, 1)}; + OutputObj<TH1F> hV0Radius{TH1F("hV0Radius", "", 2000, 0, 200)}; + OutputObj<TH1F> hV0DCADaughters{TH1F("hV0DCADaughters", "", 200, 0, 2)}; + OutputObj<TH1F> hV0PosDCAxy{TH1F("hV0PosDCAxy", "", 200, 0, 5)}; + OutputObj<TH1F> hV0NegDCAxy{TH1F("hV0NegDCAxy", "", 200, 0, 5)}; + + //Configurables + Configurable<double> d_bz{"d_bz", +5.0, "bz field"}; + Configurable<double> d_UseAbsDCA{"d_UseAbsDCA", kTRUE, "Use Abs DCAs"}; + + //Selection criteria + Configurable<double> v0cospa{"v0cospa", 0.995, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<float> dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<float> v0radius{"v0radius", 5.0, "v0radius"}; + + //using myTracks = soa::Filtered<aod::Tracks>; + //using myTracks = soa::Filtered<aod::fullTracks>; + + Partition<aod::FullTracks> goodPosTracks = aod::track::signed1Pt > 0.0f; + Partition<aod::FullTracks> goodNegTracks = aod::track::signed1Pt < 0.0f; + + /// Extracts dca in the XY plane + /// \return dcaXY + template <typename T, typename U> + auto getdcaXY(const T& track, const U& coll) + { + //Calculate DCAs + auto sinAlpha = sin(track.alpha()); + auto cosAlpha = cos(track.alpha()); + auto globalX = track.x() * cosAlpha - track.y() * sinAlpha; + auto globalY = track.x() * sinAlpha + track.y() * cosAlpha; + return sqrt(pow((globalX - coll[0]), 2) + + pow((globalY - coll[1]), 2)); + } + + void process(aod::Collision const& collision, + aod::FullTracks const& tracks) + { + //Define o2 fitter, 2-prong + o2::vertexing::DCAFitterN<2> fitter; + fitter.setBz(d_bz); + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(d_UseAbsDCA); + + Long_t lNCand = 0; + + std::array<float, 3> pVtx = {collision.posX(), collision.posY(), collision.posZ()}; + + for (auto& t0 : goodPosTracks) { + auto thisdcapostopv = getdcaXY(t0, pVtx); + if (thisdcapostopv < dcapostopv) + continue; + if (t0.tpcNClsCrossedRows() < 70) + continue; + for (auto& t1 : goodPosTracks) { + auto thisdcanegtopv = getdcaXY(t1, pVtx); + if (thisdcanegtopv < dcanegtopv) + continue; + if (t1.tpcNClsCrossedRows() < 70) + continue; + + auto Track1 = getTrackParCov(t0); + auto Track2 = getTrackParCov(t1); + + //Try to progate to dca + int nCand = fitter.process(Track1, Track2); + if (nCand == 0) + continue; + const auto& vtx = fitter.getPCACandidate(); + + //Fiducial: min radius + auto thisv0radius = TMath::Sqrt(TMath::Power(vtx[0], 2) + TMath::Power(vtx[1], 2)); + if (thisv0radius < v0radius) + continue; + + //DCA V0 daughters + auto thisdcav0dau = fitter.getChi2AtPCACandidate(); + if (thisdcav0dau > dcav0dau) + continue; + + std::array<float, 3> pos = {0.}; + std::array<float, 3> pvec0; + std::array<float, 3> pvec1; + for (int i = 0; i < 3; i++) + pos[i] = vtx[i]; + fitter.getTrack(0).getPxPyPzGlo(pvec0); + fitter.getTrack(1).getPxPyPzGlo(pvec1); + + auto thisv0cospa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, + array{vtx[0], vtx[1], vtx[2]}, array{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}); + if (thisv0cospa < v0cospa) + continue; + + hV0PosCrossedRows->Fill(t0.tpcNClsCrossedRows()); + hV0NegCrossedRows->Fill(t1.tpcNClsCrossedRows()); + hV0PosDCAxy->Fill(thisdcapostopv); + hV0NegDCAxy->Fill(thisdcanegtopv); + hV0CosPA->Fill(thisv0cospa); + hV0Radius->Fill(thisv0radius); + hV0DCADaughters->Fill(thisdcav0dau); + + lNCand++; + v0finderdata(t0.collisionId()); + v0data(pos[0], pos[1], pos[2], + pvec0[0], pvec0[1], pvec0[2], + pvec1[0], pvec1[1], pvec1[2], + fitter.getChi2AtPCACandidate(), + getdcaXY(t0, pVtx), + getdcaXY(t1, pVtx)); + } + } + hCandPerEvent->Fill(lNCand); + } +}; + +struct lambdakzerofinderQA { + //Basic checks + //Selection criteria + Configurable<double> v0cospa{"v0cospa", 0.998, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<float> dcav0dau{"dcav0dau", .6, "DCA V0 Daughters"}; + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<float> v0radius{"v0radius", 5.0, "v0radius"}; + + OutputObj<TH1F> hCandPerEvent{TH1F("hCandPerEvent", "", 1000, 0, 1000)}; + + OutputObj<TH1F> hV0Radius{TH1F("hV0Radius", "", 1000, 0.0, 100)}; + OutputObj<TH1F> hV0CosPA{TH1F("hV0CosPA", "", 1000, 0.95, 1.0)}; + OutputObj<TH1F> hDCAPosToPV{TH1F("hDCAPosToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCANegToPV{TH1F("hDCANegToPV", "", 1000, 0.0, 10.0)}; + OutputObj<TH1F> hDCAV0Dau{TH1F("hDCAV0Dau", "", 1000, 0.0, 10.0)}; + + OutputObj<TH3F> h3dMassK0Short{TH3F("h3dMassK0Short", "", 20, 0, 100, 200, 0, 10, 200, 0.450, 0.550)}; + OutputObj<TH3F> h3dMassLambda{TH3F("h3dMassLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; + OutputObj<TH3F> h3dMassAntiLambda{TH3F("h3dMassAntiLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; + + Filter preFilterV0 = aod::v0data::dcapostopv > dcapostopv&& + aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + + ///Connect to V0FinderData: newly indexed, note: V0DataExt table incompatible with standard V0 table! + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, + soa::Filtered<soa::Join<aod::V0FinderData, aod::V0DataExt>> const& fullV0s) + { + if (!collision.alias()[kINT7]) + return; + if (!collision.sel7()) + return; + + Long_t lNCand = 0; + for (auto& v0 : fullV0s) { + if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa) { + hV0Radius->Fill(v0.v0radius()); + hV0CosPA->Fill(v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + hDCAPosToPV->Fill(v0.dcapostopv()); + hDCANegToPV->Fill(v0.dcanegtopv()); + hDCAV0Dau->Fill(v0.dcaV0daughters()); + + if (TMath::Abs(v0.yLambda()) < 0.5) { + h3dMassLambda->Fill(collision.centV0M(), v0.pt(), v0.mLambda()); + h3dMassAntiLambda->Fill(collision.centV0M(), v0.pt(), v0.mAntiLambda()); + } + if (TMath::Abs(v0.yK0Short()) < 0.5) + h3dMassK0Short->Fill(collision.centV0M(), v0.pt(), v0.mK0Short()); + lNCand++; + } + } + hCandPerEvent->Fill(lNCand); + } +}; + +/// Extends the v0data table with expression columns +struct lambdakzeroinitializer { + Spawns<aod::V0DataExt> v0dataext; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<lambdakzerofinder>("lf-lambdakzerofinder"), + adaptAnalysisTask<lambdakzerofinderQA>("lf-lambdakzerofinderQA"), + adaptAnalysisTask<lambdakzeroinitializer>("lf-lambdakzeroinitializer")}; +} diff --git a/Analysis/Tasks/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx similarity index 100% rename from Analysis/Tasks/lambdakzeroproducer.cxx rename to Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx From 421210f32cc907f42b1d5a117afb2c623fc0abd5 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 17 Sep 2020 09:25:16 +0200 Subject: [PATCH 0659/1751] Update sim_challenge.sh detect bus errors --- prodtests/sim_challenge.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 094fb0669b280..2474bda21a336 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -53,6 +53,7 @@ taskwrapper() { pattern="-e \"xception\" \ -e \"segmentation violation\" \ -e \"error while setting up workflow\" \ + -e \"bus error\" \ -e \"There was a crash.\"" grepcommand="grep -H ${pattern} $logfile >> encountered_exceptions_list 2>/dev/null" From 6da61f5832b8c4cddf15c63439977a47eaac5de1 Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Thu, 17 Sep 2020 09:42:24 +0200 Subject: [PATCH 0660/1751] Replaced TList with TFolder (#4360) --- Framework/Core/include/Framework/HistogramRegistry.h | 12 ++++++------ Framework/Core/src/AnalysisManagers.h | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index a8d89c0ac8322..fdaf9f982a712 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -27,7 +27,7 @@ #include "TH3.h" #include "THn.h" #include "THnSparse.h" -#include "TList.h" +#include "TFolder.h" #include <string> #include <variant> @@ -295,17 +295,17 @@ class HistogramRegistry taskHash = hash; } - TList* operator*() + TFolder* operator*() { - TList* list = new TList(); - list->SetName(this->name.c_str()); + TFolder* folder = new TFolder(this->name.c_str(), this->name.c_str()); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { if (mRegistryValue[j].get() != nullptr) { auto hist = mRegistryValue[j].get(); - list->Add(hist); + folder->Add(hist); } } - return list; + folder->SetOwner(); + return folder; } /// lookup distance counter for benchmarking diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index 8508e2e8830da..9154fa7c77ef6 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -181,8 +181,7 @@ struct OutputManager<HistogramRegistry> { static bool postRun(EndOfStreamContext& context, HistogramRegistry& what) { - TList* list = *what; - context.outputs().snapshot(what.ref(), *list); + context.outputs().snapshot(what.ref(), *(*what)); return true; } }; From 7c281f883b1fc90e4210723f857528b07cdc64b0 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Thu, 10 Sep 2020 17:34:17 +0200 Subject: [PATCH 0661/1751] Correctly read masks written in hexadecimal format --- Detectors/MUON/MID/Raw/src/CrateMasks.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/MUON/MID/Raw/src/CrateMasks.cxx b/Detectors/MUON/MID/Raw/src/CrateMasks.cxx index c247765569827..7a03728310ac9 100644 --- a/Detectors/MUON/MID/Raw/src/CrateMasks.cxx +++ b/Detectors/MUON/MID/Raw/src/CrateMasks.cxx @@ -94,7 +94,7 @@ bool CrateMasks::load(const char* filename) std::getline(ss, token, ' '); uint16_t feeId = std::atoi(token.c_str()); std::getline(ss, token, ' '); - uint8_t mask = std::atoi(token.c_str()); + uint8_t mask = static_cast<uint8_t>(std::strtol(token.c_str(), nullptr, 16)); mActiveBoards[feeId] = mask; } inFile.close(); From d2b9c3d4eea45419234af9a88523d73dcd1f8d6b Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Tue, 28 Jul 2020 15:53:53 +0200 Subject: [PATCH 0662/1751] Correctly encode the first event --- Detectors/MUON/MID/Raw/src/Encoder.cxx | 5 ----- Detectors/MUON/MID/Raw/test/testRaw.cxx | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Detectors/MUON/MID/Raw/src/Encoder.cxx b/Detectors/MUON/MID/Raw/src/Encoder.cxx index c1b7de3a5a0c0..c5b255b578d63 100644 --- a/Detectors/MUON/MID/Raw/src/Encoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Encoder.cxx @@ -45,12 +45,7 @@ void Encoder::hbTrigger(const InteractionRecord& ir) { /// Processes HB trigger if (mLastIR.isDummy()) { - // This is the first HB - for (uint16_t feeId = 0; feeId < crateparams::sNGBTs; ++feeId) { - mGBTEncoders[feeId].processTrigger(o2::constants::lhc::LHCMaxBunches, raw::sORB); - } mLastIR = o2::raw::HBFUtils::Instance().getFirstIR(); - return; } std::vector<InteractionRecord> HBIRVec; diff --git a/Detectors/MUON/MID/Raw/test/testRaw.cxx b/Detectors/MUON/MID/Raw/test/testRaw.cxx index a009ec8af063a..ba01d822c9001 100644 --- a/Detectors/MUON/MID/Raw/test/testRaw.cxx +++ b/Detectors/MUON/MID/Raw/test/testRaw.cxx @@ -230,7 +230,7 @@ BOOST_AUTO_TEST_CASE(SmallSample) std::map<o2::InteractionRecord, std::vector<o2::mid::ColumnData>> inData; // Small standard event - o2::InteractionRecord ir(100, 0); + o2::InteractionRecord ir(100, 1); // Crate 5 link 0 inData[ir].emplace_back(getColData(2, 4, 0x1, 0xFFFF)); @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(SmallSample) // Crate 10 link 1 and crate 11 link 1 inData[ir].emplace_back(getColData(41, 2, 0xFF0F, 0, 0xF0FF, 0xF)); ir.bc = 200; - ir.orbit = 1; + ir.orbit = 2; // Crate 12 link 1 inData[ir].emplace_back(getColData(70, 3, 0xFF00, 0xFF)); @@ -255,7 +255,7 @@ BOOST_AUTO_TEST_CASE(LargeBufferSample) o2::mid::Mapping mapping; std::map<o2::InteractionRecord, std::vector<o2::mid::ColumnData>> inData; // Big event that should pass the 8kB - o2::InteractionRecord ir(0, 0); + o2::InteractionRecord ir(0, 1); for (int irepeat = 0; irepeat < 4000; ++irepeat) { ++ir; for (int ide = 0; ide < o2::mid::detparams::NDetectionElements; ++ide) { From 8a460144c736930ee469f88ce1941a89e6703e95 Mon Sep 17 00:00:00 2001 From: Javier Castillo Castellanos <javier.castillo.castellanos@cern.ch> Date: Wed, 16 Sep 2020 11:44:12 +0200 Subject: [PATCH 0663/1751] Bug fixes in setting parameters --- DataFormats/Detectors/Common/src/AlignParam.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/Common/src/AlignParam.cxx b/DataFormats/Detectors/Common/src/AlignParam.cxx index 633873238941a..4ee234e09dcb6 100644 --- a/DataFormats/Detectors/Common/src/AlignParam.cxx +++ b/DataFormats/Detectors/Common/src/AlignParam.cxx @@ -103,8 +103,8 @@ bool AlignParam::setRotation(const TGeoMatrix& m) double psi, theta, phi; if (!matrixToAngles(rot, psi, theta, phi)) { return false; - setRotation(psi, theta, phi); } + setRotation(psi, theta, phi); } else { mPsi = mTheta = mPhi = 0.; } @@ -190,7 +190,8 @@ bool AlignParam::setLocalParams(const TGeoMatrix& m) m1.Multiply(&gprimeinv); m1.MultiplyLeft(&gprime); - return setLocalParams(m1); + setParams(m1); + return true; } //_____________________________________________________________________________ From 89f37ae94f4b966e2e2f482dd256d501978aa131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Thu, 17 Sep 2020 14:05:34 +0200 Subject: [PATCH 0664/1751] Update spectra TPC task to fix json config issue (#4368) --- Analysis/Tasks/spectraTPC.cxx | 80 +++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/Analysis/Tasks/spectraTPC.cxx b/Analysis/Tasks/spectraTPC.cxx index 4344fee782c20..0a7a746155b05 100644 --- a/Analysis/Tasks/spectraTPC.cxx +++ b/Analysis/Tasks/spectraTPC.cxx @@ -9,29 +9,36 @@ // or submit itself to any jurisdiction. // O2 includes -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "ReconstructionDataFormats/Track.h" #include "PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" +#include "Analysis/TrackSelectionTables.h" // ROOT includes #include <TH1F.h> +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"add-tof-histos", VariantType::Int, 0, {"Generate TPC with TOF histograms"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP}; + #define DOTH1F(OBJ, ...) \ OutputObj<TH1F> OBJ{TH1F(#OBJ, __VA_ARGS__)}; #define DOTH2F(OBJ, ...) \ OutputObj<TH2F> OBJ{TH2F(#OBJ, __VA_ARGS__)}; -#define TRACKSELECTION \ - UChar_t clustermap = i.itsClusterMap(); \ - bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); \ - if (!issel) \ - continue; - -// #define TRACKSELECTION 1; - #define makelogaxis(h) \ { \ const Int_t nbins = h->GetNbinsX(); \ @@ -47,18 +54,11 @@ h->GetXaxis()->Set(nbins, binp); \ } -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) -{ - std::vector<ConfigParamSpec> options{ - {"add-tof-histos", VariantType::Bool, false, {"Generate TPC with TOF histograms"}}}; - std::swap(workflowOptions, options); -} - struct TPCPIDQAExpSignalTask { + // Options + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + #define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000 DOTH2F(htpcsignal, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); @@ -89,13 +89,12 @@ struct TPCPIDQAExpSignalTask { makelogaxis(hexpAl); } - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) + // Filters + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>> const& tracks) { for (auto const& i : tracks) { - // Track selection - TRACKSELECTION; - // - // const float mom = i.p(); const float mom = i.tpcInnerParam(); htpcsignal->Fill(mom, i.tpcSignal()); @@ -113,6 +112,10 @@ struct TPCPIDQAExpSignalTask { }; struct TPCPIDQANSigmaTask { + // Options + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + #define BIN_AXIS 1000, 0.001, 20, 1000, -10, 10 // TPC NSigma @@ -142,13 +145,13 @@ struct TPCPIDQANSigmaTask { makelogaxis(hnsigmaAl); } - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) + // Filters + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + + void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>> const& tracks) { for (auto const& i : tracks) { - // Track selection - TRACKSELECTION; - // - hnsigmaEl->Fill(i.p(), i.tpcNSigmaEl()); hnsigmaMu->Fill(i.p(), i.tpcNSigmaMu()); hnsigmaPi->Fill(i.p(), i.tpcNSigmaPi()); @@ -163,6 +166,10 @@ struct TPCPIDQANSigmaTask { }; struct TPCPIDQASignalwTOFTask { + // Options + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + #define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000 DOTH2F(htpcsignalEl, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); @@ -191,11 +198,13 @@ struct TPCPIDQASignalwTOFTask { makelogaxis(htpcsignalAl); } - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF> const& tracks) + // Filters + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + + void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>> const& tracks) { for (auto const& i : tracks) { - // Track selection - TRACKSELECTION; // Require kTIME and kTOFout if (!(i.flags() & 0x2000)) continue; @@ -255,9 +264,6 @@ struct TPCSpectraTask { void process(soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) { for (auto i : tracks) { - // Track selection - TRACKSELECTION; - // if (TMath::Abs(i.tpcNSigmaEl()) < 3) { hp_El->Fill(i.p()); hpt_El->Fill(i.pt()); @@ -280,7 +286,7 @@ struct TPCSpectraTask { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - bool TPCwTOF = cfgc.options().get<bool>("add-tof-histos"); + int TPCwTOF = cfgc.options().get<int>("add-tof-histos"); WorkflowSpec workflow{adaptAnalysisTask<TPCPIDQAExpSignalTask>("TPCpidqa-expsignal-task"), adaptAnalysisTask<TPCPIDQANSigmaTask>("TPCpidqa-nsigma-task"), adaptAnalysisTask<TPCSpectraTask>("tpcspectra-task")}; From b1c775909f4b81ca63f7a01e1280fc6e151ccf7d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 17 Sep 2020 16:20:25 +0200 Subject: [PATCH 0665/1751] DPL: create matcher from description (#4363) --- .../Core/include/Framework/DataSpecUtils.h | 3 +++ Framework/Core/src/DataSpecUtils.cxx | 18 ++++++++++++++++++ Framework/Core/test/unittest_DataSpecUtils.cxx | 10 ++++++++++ 3 files changed, 31 insertions(+) diff --git a/Framework/Core/include/Framework/DataSpecUtils.h b/Framework/Core/include/Framework/DataSpecUtils.h index aeeef13ed9b43..6e35feed4c214 100644 --- a/Framework/Core/include/Framework/DataSpecUtils.h +++ b/Framework/Core/include/Framework/DataSpecUtils.h @@ -185,6 +185,9 @@ struct DataSpecUtils { /// Build a DataDescriptMatcher which does not care about the subSpec and description. static data_matcher::DataDescriptorMatcher dataDescriptorMatcherFrom(header::DataOrigin const& origin); + + /// Build a DataDescriptMatcher which does not care about the subSpec and origin. + static data_matcher::DataDescriptorMatcher dataDescriptorMatcherFrom(header::DataDescription const& origin); }; } // namespace framework diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index 8eb02f2629d2a..0d1d2f1bff99e 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -480,6 +480,24 @@ DataDescriptorMatcher DataSpecUtils::dataDescriptorMatcherFrom(header::DataOrigi return std::move(matchOnlyOrigin); } +DataDescriptorMatcher DataSpecUtils::dataDescriptorMatcherFrom(header::DataDescription const& description) +{ + char buf[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + strncpy(buf, description.str, 16); + DataDescriptorMatcher matchOnlyOrigin{ + DataDescriptorMatcher::Op::And, + OriginValueMatcher{ContextRef{1}}, + std::make_unique<DataDescriptorMatcher>( + DataDescriptorMatcher::Op::And, + DescriptionValueMatcher{buf}, + std::make_unique<DataDescriptorMatcher>( + DataDescriptorMatcher::Op::And, + SubSpecificationTypeValueMatcher{ContextRef{2}}, + std::make_unique<DataDescriptorMatcher>(DataDescriptorMatcher::Op::Just, + StartTimeValueMatcher{ContextRef{0}})))}; + return std::move(matchOnlyOrigin); +} + InputSpec DataSpecUtils::matchingInput(OutputSpec const& spec) { return std::visit(overloaded{ diff --git a/Framework/Core/test/unittest_DataSpecUtils.cxx b/Framework/Core/test/unittest_DataSpecUtils.cxx index d1d91ad74ae05..ac954fb0da417 100644 --- a/Framework/Core/test/unittest_DataSpecUtils.cxx +++ b/Framework/Core/test/unittest_DataSpecUtils.cxx @@ -242,6 +242,16 @@ BOOST_AUTO_TEST_CASE(GetOptionalSubSpecWithMatcher) BOOST_CHECK_EQUAL(std::string(dataType2.description.as<std::string>()), "FOOO"); } +BOOST_AUTO_TEST_CASE(TestMatcherFromDescription) +{ + auto fromQueryInputSpec = DataSpecUtils::dataDescriptorMatcherFrom(header::DataDescription{"TSET"}); + InputSpec ddSpec{ + "binding", + std::move(fromQueryInputSpec)}; + + BOOST_CHECK_EQUAL(DataSpecUtils::asConcreteDataDescription(ddSpec).as<std::string>(), "TSET"); +} + BOOST_AUTO_TEST_CASE(FindOutputSpec) { std::vector<OutputSpec> specs = { From 1533f539b575d54b4050d10d3c2a04d3677c6117 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 17 Sep 2020 13:24:36 +0200 Subject: [PATCH 0666/1751] Improve DataSpecUtils::asConcreteDataMatcher(InputSpec) Now supports some DataDescriptorMatcher --- Framework/Core/src/DataSpecUtils.cxx | 48 ++++++++++++------- .../Core/test/unittest_DataSpecUtils.cxx | 6 ++- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index 0d1d2f1bff99e..9614c3cbc1163 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -277,24 +277,6 @@ bool DataSpecUtils::partialMatch(OutputSpec const& output, header::DataDescripti return dataType.description == description; } -ConcreteDataMatcher DataSpecUtils::asConcreteDataMatcher(InputSpec const& spec) -{ - return std::get<ConcreteDataMatcher>(spec.matcher); -} - -ConcreteDataMatcher DataSpecUtils::asConcreteDataMatcher(OutputSpec const& spec) -{ - return std::get<ConcreteDataMatcher>(spec.matcher); -} - -ConcreteDataTypeMatcher DataSpecUtils::asConcreteDataTypeMatcher(OutputSpec const& spec) -{ - return std::visit([](auto const& concrete) { - return ConcreteDataTypeMatcher{concrete.origin, concrete.description}; - }, - spec.matcher); -} - struct MatcherInfo { header::DataOrigin origin = header::gDataOriginInvalid; // Whether or not we found an origins (should be a bad query!) header::DataDescription description = header::gDataDescriptionInvalid; // Whether or not we found a description @@ -383,6 +365,36 @@ MatcherInfo extractMatcherInfo(DataDescriptorMatcher const& top) return state; } +ConcreteDataMatcher DataSpecUtils::asConcreteDataMatcher(InputSpec const& spec) +{ + return std::visit(overloaded{[](ConcreteDataMatcher const& concrete) { + return concrete; + }, + [&binding = spec.binding](DataDescriptorMatcher const& matcher) { + auto info = extractMatcherInfo(matcher); + if (info.hasOrigin && info.hasUniqueOrigin && + info.hasDescription && info.hasDescription && + info.hasSubSpec && info.hasUniqueSubSpec) { + return ConcreteDataMatcher{info.origin, info.description, info.subSpec}; + } + throw std::runtime_error("Cannot convert " + binding + " to ConcreteDataMatcher"); + }}, + spec.matcher); +} + +ConcreteDataMatcher DataSpecUtils::asConcreteDataMatcher(OutputSpec const& spec) +{ + return std::get<ConcreteDataMatcher>(spec.matcher); +} + +ConcreteDataTypeMatcher DataSpecUtils::asConcreteDataTypeMatcher(OutputSpec const& spec) +{ + return std::visit([](auto const& concrete) { + return ConcreteDataTypeMatcher{concrete.origin, concrete.description}; + }, + spec.matcher); +} + ConcreteDataTypeMatcher DataSpecUtils::asConcreteDataTypeMatcher(InputSpec const& spec) { return std::visit(overloaded{ diff --git a/Framework/Core/test/unittest_DataSpecUtils.cxx b/Framework/Core/test/unittest_DataSpecUtils.cxx index ac954fb0da417..45c3c077ef80f 100644 --- a/Framework/Core/test/unittest_DataSpecUtils.cxx +++ b/Framework/Core/test/unittest_DataSpecUtils.cxx @@ -125,7 +125,11 @@ BOOST_AUTO_TEST_CASE(MatchingInputs) BOOST_CHECK(DataSpecUtils::match(matchingInput2, concreteExample3) == false); BOOST_CHECK(DataSpecUtils::match(matchingInput2, concreteExample4) == false); - BOOST_CHECK_THROW(DataSpecUtils::asConcreteDataMatcher(matchingInput2), std::bad_variant_access); + BOOST_CHECK_THROW(DataSpecUtils::asConcreteDataMatcher(matchingInput2), std::runtime_error); + auto concrete2 = DataSpecUtils::asConcreteDataMatcher(matchingInput1); + BOOST_CHECK_EQUAL(concrete.origin.as<std::string>(), "TEST"); + BOOST_CHECK_EQUAL(concrete.description.as<std::string>(), "FOOO"); + BOOST_CHECK_EQUAL(concrete.subSpec, 1); } BOOST_AUTO_TEST_CASE(MatchingOutputs) From f13634ef34525814e603fa2acce3d59e46eeed84 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 17 Sep 2020 13:25:26 +0200 Subject: [PATCH 0667/1751] DPL: add o2-dpl-null-sink workflow This workflow can be configured to terminate any other workflow by providing the appropriate --inputs option. --- Framework/Core/CMakeLists.txt | 5 +++ Framework/Core/src/o2NullSink.cxx | 53 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 Framework/Core/src/o2NullSink.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 84d25232ae114..1e0bbb7fa90bf 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -198,6 +198,11 @@ foreach(t PUBLIC_LINK_LIBRARIES O2::Framework) endforeach() +o2_add_executable(dpl-null-sink + SOURCES src/o2NullSink.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + ) + o2_add_executable(dpl-run SOURCES src/dplRun.cxx PUBLIC_LINK_LIBRARIES O2::Framework diff --git a/Framework/Core/src/o2NullSink.cxx b/Framework/Core/src/o2NullSink.cxx new file mode 100644 index 0000000000000..79c18a9f6ba11 --- /dev/null +++ b/Framework/Core/src/o2NullSink.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 "Framework/ConfigContext.h" +#include "Framework/ControlService.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/Logger.h" +#include "Framework/ParallelContext.h" +#include "Framework/DataDescriptorQueryBuilder.h" + +#include <chrono> +#include <thread> +#include <vector> + +/// A DataProcessor which terminates a provided set of +/// inputs. +using namespace o2::framework; + +void customize(std::vector<ConfigParamSpec>& options) +{ + options.push_back(o2::framework::ConfigParamSpec{"inputs", VariantType::String, "", {"inputs for the dataprocessor"}}); +}; + +#include "Framework/runDataProcessing.h" + +// This is a simple consumer / producer workflow where both are +// stateful, i.e. they have context which comes from their initialization. +WorkflowSpec defineDataProcessing(ConfigContext const& context) +{ + WorkflowSpec workflow; + // This is an example of how we can parallelize by subSpec. + // templatedProducer will be instanciated 32 times and the lambda function + // passed to the parallel statement will be applied to each one of the + // instances in order to modify it. Parallel will also make sure the name of + // the instance is amended from "some-producer" to "some-producer-<index>". + auto inputsDesc = context.options().get<std::string>("inputs"); + auto inputs = DataDescriptorQueryBuilder::parse(inputsDesc.c_str()); + + workflow.push_back(DataProcessorSpec{ + "null", + inputs, + {}, + AlgorithmSpec{[](ProcessingContext& ctx) {}}}); + + return workflow; +} From bf6eeae5dbabe9e5e33a4119bd95f388e977814c Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan <shahor02@users.noreply.github.com> Date: Thu, 17 Sep 2020 17:07:15 +0200 Subject: [PATCH 0668/1751] add option to produce per-link raw data files for MID (#4364) * add option to produce per-link raw data files for MID * account for automatice raw extension in MID testRaw Co-authored-by: shahoian <ruben.shahoyan@cern.ch> --- Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h | 2 +- Detectors/MUON/MID/Raw/src/Encoder.cxx | 8 ++++++-- Detectors/MUON/MID/Raw/test/testRaw.cxx | 5 +++-- Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h index 9830372a589da..c3ca341cd32a5 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h @@ -35,7 +35,7 @@ namespace mid class Encoder { public: - void init(const char* filename, int verbosity = 0); + void init(const char* filename, bool perLink = false, int verbosity = 0); void process(gsl::span<const ColumnData> data, const InteractionRecord& ir, EventType eventType = EventType::Standard); /// Sets the maximum size of the superpage void setSuperpageSize(int maxSize) { mRawWriter.setSuperPageSize(maxSize); } diff --git a/Detectors/MUON/MID/Raw/src/Encoder.cxx b/Detectors/MUON/MID/Raw/src/Encoder.cxx index c5b255b578d63..6e1e3eb0d1d35 100644 --- a/Detectors/MUON/MID/Raw/src/Encoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Encoder.cxx @@ -18,13 +18,14 @@ #include "DetectorsRaw/HBFUtils.h" #include "DetectorsRaw/RDHUtils.h" #include "MIDRaw/CrateMasks.h" +#include <fmt/format.h> namespace o2 { namespace mid { -void Encoder::init(const char* filename, int verbosity) +void Encoder::init(const char* filename, bool perLink, int verbosity) { /// Initializes links @@ -32,12 +33,15 @@ void Encoder::init(const char* filename, int verbosity) auto gbtIds = mFEEIdConfig.getConfiguredGBTIds(); mRawWriter.setVerbosity(verbosity); + int lcnt = 0; for (auto& gbtId : gbtIds) { auto feeId = mFEEIdConfig.getFeeId(gbtId); - mRawWriter.registerLink(feeId, mFEEIdConfig.getCRUId(gbtId), mFEEIdConfig.getLinkId(gbtId), mFEEIdConfig.getEndPointId(gbtId), filename); + mRawWriter.registerLink(feeId, mFEEIdConfig.getCRUId(gbtId), mFEEIdConfig.getLinkId(gbtId), mFEEIdConfig.getEndPointId(gbtId), + perLink ? fmt::format("{:s}_L{:d}.raw", filename, lcnt) : fmt::format("{:s}.raw", filename)); mGBTEncoders[feeId].setFeeId(feeId); mGBTEncoders[feeId].setMask(masks.getMask(feeId)); mGBTIds[feeId] = gbtId; + lcnt++; } } diff --git a/Detectors/MUON/MID/Raw/test/testRaw.cxx b/Detectors/MUON/MID/Raw/test/testRaw.cxx index ba01d822c9001..eb675544979dd 100644 --- a/Detectors/MUON/MID/Raw/test/testRaw.cxx +++ b/Detectors/MUON/MID/Raw/test/testRaw.cxx @@ -85,9 +85,10 @@ std::tuple<std::vector<o2::mid::ColumnData>, std::vector<o2::mid::ROFRecord>> en { auto severity = fair::Logger::GetConsoleSeverity(); fair::Logger::SetConsoleSeverity(fair::Severity::WARNING); - std::string tmpFilename = "tmp_mid_raw.dat"; + std::string tmpFilename0 = "tmp_mid_raw"; + std::string tmpFilename = tmpFilename0 + ".raw"; o2::mid::Encoder encoder; - encoder.init(tmpFilename.c_str()); + encoder.init(tmpFilename0.c_str()); for (auto& item : inData) { encoder.process(item.second, item.first, inEventType); } diff --git a/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx b/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx index 6133d59ef291d..159176026b143 100644 --- a/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx @@ -44,6 +44,7 @@ class RawWriterDeviceDPL { auto filename = ic.options().get<std::string>("mid-raw-outfile"); auto dirname = ic.options().get<std::string>("mid-raw-outdir"); + auto perLink = ic.options().get<bool>("mid-raw-perlink"); if (gSystem->AccessPathName(dirname.c_str())) { if (gSystem->mkdir(dirname.c_str(), kTRUE)) { LOG(FATAL) << "could not create output directory " << dirname; @@ -53,7 +54,7 @@ class RawWriterDeviceDPL } std::string fullFName = o2::utils::concat_string(dirname, "/", filename); - mEncoder.init(fullFName.c_str()); + mEncoder.init(fullFName.c_str(), perLink); std::string inputGRP = o2::base::NameConf::getGRPFileName(); std::unique_ptr<o2::parameters::GRPObject> grp{o2::parameters::GRPObject::loadFrom(inputGRP)}; @@ -97,7 +98,8 @@ framework::DataProcessorSpec getRawWriterSpec() of::AlgorithmSpec{of::adaptFromTask<o2::mid::RawWriterDeviceDPL>()}, of::Options{ {"mid-raw-outdir", of::VariantType::String, ".", {"Raw file output directory"}}, - {"mid-raw-outfile", of::VariantType::String, "mid.raw", {"Raw output file name"}}, + {"mid-raw-outfile", of::VariantType::String, "mid", {"Raw output file name"}}, + {"mid-raw-perlink", of::VariantType::Bool, false, {"Output file per link"}}, {"mid-raw-header-offset", of::VariantType::Bool, false, {"Header offset in bytes"}}}}; } } // namespace mid From eb0e5922491d9bd8053fa140bcbb594b260b923b Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez@cern.ch> Date: Thu, 17 Sep 2020 21:28:04 +0200 Subject: [PATCH 0669/1751] Internal codes for centrality/multiplicity estimators names (#4378) Also - processpairs flag also added to filter task for easier configuration - filter task configuration params to output file - default the benchmark configuration (--) --- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 48 +++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index 60b8aad57574d..f228e03a8d1f5 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -105,12 +105,24 @@ enum SystemType { knSystems ///< number of handled systems }; +/// \enum CentMultEstimatorType +/// \brief The detector used to estimate centrality/multiplicity +enum CentMultEstimatorType { + kV0M = 0, ///< V0M centrality/multiplicity estimator + kV0A, ///< V0A centrality/multiplicity estimator + kV0C, ///< V0C centrality/multiplicity estimator + kCL0, ///< CL0 centrality/multiplicity estimator + kCL1, ///< CL1 centrality/multiplicity estimator + knCentMultEstimators ///< number of centrality/mutiplicity estimator +}; + namespace filteranalyistask { //============================================================================================ // The DptDptCorrelationsFilterAnalysisTask output objects //============================================================================================ SystemType fSystem = kNoSystem; +CentMultEstimatorType fCentMultEstimator = kV0M; TH1F* fhCentMultB = nullptr; TH1F* fhCentMultA = nullptr; TH1F* fhVertexZB = nullptr; @@ -179,17 +191,23 @@ SystemType getSystemType() return kPbPb; } -bool IsEvtSelected(aod::CollisionEvSelCent const& collision, const std::string estimator, float& centormult) +bool IsEvtSelected(aod::CollisionEvSelCent const& collision, float& centormult) { + using namespace filteranalyistask; + if (collision.alias()[kINT7]) { if (collision.sel7()) { /* TODO: vertex quality checks */ if (zvtxlow < collision.posZ() and collision.posZ() < zvtxup) { - if (estimator.compare("V0M") == 0) { - if (collision.centV0M() < 100 and 0 < collision.centV0M()) { - centormult = collision.centV0M(); - return true; - } + switch (fCentMultEstimator) { + case kV0M: + if (collision.centV0M() < 100 and 0 < collision.centV0M()) { + centormult = collision.centV0M(); + return true; + } + break; + default: + break; } return false; } @@ -267,8 +285,9 @@ using namespace dptdptcorrelations; struct DptDptCorrelationsFilterAnalysisTask { Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; - Configurable<int> cfgTrackOneCharge{"trk1charge", 1, "Trakc one charge: 1 = positive, -1 = negative"}; + Configurable<int> cfgTrackOneCharge{"trk1charge", -1, "Trakc one charge: 1 = positive, -1 = negative"}; Configurable<int> cfgTrackTwoCharge{"trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"}; + Configurable<bool> cfgProcessPairs{"processpairs", true, "Process pairs: false = no, just singles, true = yes, process pairs"}; Configurable<std::string> cfgCentMultEstimator{"centmultestimator", "V0M", "Centrality/multiplicity estimator detector: default V0M"}; Configurable<o2::analysis::DptDptBinningCuts> cfgBinning{"binning", @@ -285,6 +304,7 @@ struct DptDptCorrelationsFilterAnalysisTask { using namespace filteranalyistask; /* update with the configurable values */ + /* the binning */ ptbins = cfgBinning->mPTbins; ptlow = cfgBinning->mPTmin; ptup = cfgBinning->mPTmax; @@ -294,9 +314,16 @@ struct DptDptCorrelationsFilterAnalysisTask { zvtxbins = cfgBinning->mZVtxbins; zvtxlow = cfgBinning->mZVtxmin; zvtxup = cfgBinning->mZVtxmax; + /* the track types and combinations */ tracktype = cfgTrackType.value; trackonecharge = cfgTrackOneCharge.value; tracktwocharge = cfgTrackTwoCharge.value; + /* the centrality/multiplicity estimation */ + if (cfgCentMultEstimator->compare("V0M") == 0) { + fCentMultEstimator = kV0M; + } else { + LOGF(FATAL, "Centrality/Multiplicity estimator %s not supported yet", cfgCentMultEstimator->c_str()); + } /* if the system type is not known at this time, we have to put the initalization somewhere else */ fSystem = getSystemType(); @@ -306,6 +333,11 @@ struct DptDptCorrelationsFilterAnalysisTask { fOutputList->SetOwner(true); fOutput.setObject(fOutputList); + /* incorporate configuration parameters to the output */ + fOutputList->Add(new TParameter<Int_t>("TrackType", cfgTrackType, 'f')); + fOutputList->Add(new TParameter<Int_t>("TrackOneCharge", cfgTrackOneCharge, 'f')); + fOutputList->Add(new TParameter<Int_t>("TrackTwoCharge", cfgTrackTwoCharge, 'f')); + /* create the histograms */ if (fSystem > kPbp) { fhCentMultB = new TH1F("CentralityB", "Centrality before cut; centrality (%)", 100, 0, 100); @@ -364,7 +396,7 @@ struct DptDptCorrelationsFilterAnalysisTask { fhVertexZB->Fill(collision.posZ()); int acceptedevent = DPTDPT_FALSE; float centormult = -100.0; - if (IsEvtSelected(collision, cfgCentMultEstimator, centormult)) { + if (IsEvtSelected(collision, centormult)) { acceptedevent = DPTDPT_TRUE; fhCentMultA->Fill(collision.centV0M()); fhVertexZA->Fill(collision.posZ()); From 50b0237caf00218aafb70a35b18c0f52301d1eec Mon Sep 17 00:00:00 2001 From: Nazar <nazar.burmasov@cern.ch> Date: Thu, 17 Sep 2020 22:28:26 +0300 Subject: [PATCH 0670/1751] Added trigger selection. Analysis task moved to PWGUD (#4374) --- Analysis/Tasks/CMakeLists.txt | 8 ++------ Analysis/Tasks/PWGUD/CMakeLists.txt | 14 ++++++++++++++ Analysis/Tasks/{ => PWGUD}/upcAnalysis.cxx | 6 ++---- 3 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 Analysis/Tasks/PWGUD/CMakeLists.txt rename Analysis/Tasks/{ => PWGUD}/upcAnalysis.cxx (96%) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index b0fadfc5dab07..8c9db9ab64be2 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory(PWGCF) add_subdirectory(PWGDQ) add_subdirectory(PWGHF) add_subdirectory(PWGLF) +add_subdirectory(PWGUD) o2_add_dpl_workflow(trackselection SOURCES trackselection.cxx @@ -56,11 +57,6 @@ o2_add_dpl_workflow(jetfinder COMPONENT_NAME Analysis) endif() -o2_add_dpl_workflow(upc-an - SOURCES upcAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) - o2_add_dpl_workflow(event-selection SOURCES eventSelection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB @@ -109,4 +105,4 @@ o2_add_dpl_workflow(run2-matcher o2_add_dpl_workflow(run3-matcher SOURCES run3Matcher.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGUD/CMakeLists.txt b/Analysis/Tasks/PWGUD/CMakeLists.txt new file mode 100644 index 0000000000000..ab3c773a4ce99 --- /dev/null +++ b/Analysis/Tasks/PWGUD/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(upc-an + SOURCES upcAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/upcAnalysis.cxx b/Analysis/Tasks/PWGUD/upcAnalysis.cxx similarity index 96% rename from Analysis/Tasks/upcAnalysis.cxx rename to Analysis/Tasks/PWGUD/upcAnalysis.cxx index 36514fa770ac9..57f7583cc9ffd 100644 --- a/Analysis/Tasks/upcAnalysis.cxx +++ b/Analysis/Tasks/PWGUD/upcAnalysis.cxx @@ -38,10 +38,8 @@ struct UPCAnalysis { bool checkFDD = col.bbFDA() || col.bbFDC() || col.bgFDA() || col.bgFDC(); if (checkFDD) return; - // TODO: - // Add trigger class check - // if (!col.alias()[kCUP9]) - // return; + if (!col.alias()[kCUP9]) + return; std::vector<soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection>::iterator> selTracks; for (auto track : tracks) { if (!track.isGlobalTrack()) From 92cd78f56f1a537533b9a7c8f975856c4cded565 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Thu, 17 Sep 2020 21:28:52 +0200 Subject: [PATCH 0671/1751] =?UTF-8?q?=EF=BF=BC=20removed=20tof=20and=20tpc?= =?UTF-8?q?=20pid=20response=20from=20table=20maker=20(#4377)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Analysis/Tasks/PWGDQ/tableMaker.cxx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index c0be454ecb5cf..56a2b7b5aea71 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -68,7 +68,7 @@ struct TableMaker { VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill } - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracksBarrel) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov /*, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta*/> const& tracksBarrel) { uint64_t tag = 0; uint32_t triggerAliases = 0; @@ -114,16 +114,17 @@ struct TableMaker { track.trdChi2(), track.tofChi2(), track.length(), dcaXY, dcaZ); trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); - trackBarrelPID( - track.tpcSignal(), - track.tpcNSigmaEl(), track.tpcNSigmaMu(), + trackBarrelPID(track.tpcSignal(), + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + /* track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), track.tofSignal(), track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), - track.trdSignal()); + track.trdSignal());*/ } for (auto& muon : tracksMuon) { From 7f69a2f79092c22490722732a13ee68376cbb779 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Tue, 15 Sep 2020 16:35:17 +0200 Subject: [PATCH 0672/1751] First commit Moving to Detectors/DCS and fixes (still not compiling) Directory wa snot committed with git commit -a forgotten namespace Forgot #include "Rtypes.h" clang-format Fixing o2checkcode again clang-format Fixing a couple of leftovers Removing ADAPRO Removed unneeded file --- Detectors/CMakeLists.txt | 1 + Detectors/DCS/CMakeLists.txt | 26 + Detectors/DCS/include/DetectorsDCS/Clock.h | 129 ++++ .../DetectorsDCS/DataPointCompositeObject.h | 262 +++++++ .../DetectorsDCS/DataPointIdentifier.h | 219 ++++++ .../DCS/include/DetectorsDCS/DataPointValue.h | 701 ++++++++++++++++++ .../DCS/include/DetectorsDCS/DeliveryType.h | 380 ++++++++++ .../include/DetectorsDCS/GenericFunctions.h | 54 ++ .../DCS/include/DetectorsDCS/StringUtils.h | 156 ++++ Detectors/DCS/src/Clock.cxx | 11 + .../DCS/src/DataPointCompositeObject.cxx | 15 + Detectors/DCS/src/DataPointIdentifier.cxx | 15 + Detectors/DCS/src/DataPointValue.cxx | 15 + Detectors/DCS/src/DeliveryType.cxx | 11 + Detectors/DCS/src/DetectorsDCSLinkDef.h | 21 + Detectors/DCS/src/GenericFunctions.cxx | 11 + Detectors/DCS/src/StringUtils.cxx | 383 ++++++++++ 17 files changed, 2410 insertions(+) create mode 100644 Detectors/DCS/CMakeLists.txt create mode 100644 Detectors/DCS/include/DetectorsDCS/Clock.h create mode 100644 Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h create mode 100644 Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h create mode 100644 Detectors/DCS/include/DetectorsDCS/DataPointValue.h create mode 100644 Detectors/DCS/include/DetectorsDCS/DeliveryType.h create mode 100644 Detectors/DCS/include/DetectorsDCS/GenericFunctions.h create mode 100644 Detectors/DCS/include/DetectorsDCS/StringUtils.h create mode 100644 Detectors/DCS/src/Clock.cxx create mode 100644 Detectors/DCS/src/DataPointCompositeObject.cxx create mode 100644 Detectors/DCS/src/DataPointIdentifier.cxx create mode 100644 Detectors/DCS/src/DataPointValue.cxx create mode 100644 Detectors/DCS/src/DeliveryType.cxx create mode 100644 Detectors/DCS/src/DetectorsDCSLinkDef.h create mode 100644 Detectors/DCS/src/GenericFunctions.cxx create mode 100644 Detectors/DCS/src/StringUtils.cxx diff --git a/Detectors/CMakeLists.txt b/Detectors/CMakeLists.txt index 9b41c803e8ba1..774b14856f6f9 100644 --- a/Detectors/CMakeLists.txt +++ b/Detectors/CMakeLists.txt @@ -34,6 +34,7 @@ add_subdirectory(GlobalTrackingWorkflow) add_subdirectory(Vertexing) add_subdirectory(Calibration) +add_subdirectory(DCS) if(BUILD_SIMULATION) add_subdirectory(gconfig) diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt new file mode 100644 index 0000000000000..436b018b1b3fb --- /dev/null +++ b/Detectors/DCS/CMakeLists.txt @@ -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. + + +o2_add_library(DetectorsDCS + SOURCES src/Clock.cxx + src/DataPointCompositeObject.cxx + src/DataPointIdentifier.cxx + src/DataPointValue.cxx + src/DeliveryType.cxx + src/GenericFunctions.cxx + src/StringUtils.cxx) + +o2_target_root_dictionary(DetectorsDCS + HEADERS include/DetectorsDCS/DataPointCompositeObject.h + include/DetectorsDCS/DataPointIdentifier.h + include/DetectorsDCS/DataPointValue.h) + + diff --git a/Detectors/DCS/include/DetectorsDCS/Clock.h b/Detectors/DCS/include/DetectorsDCS/Clock.h new file mode 100644 index 0000000000000..506626828c6aa --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/Clock.h @@ -0,0 +1,129 @@ +// 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: Clock.hpp + * Author: John Lång (john.larry.lang@cern.ch) + * + * Created on 29 August 2016, 9:29 + */ +#ifndef O2_DCS_CLOCK_H +#define O2_DCS_CLOCK_H + +#include <ctime> +#include <cstdint> +#include <chrono> +#include <memory> +#include <string> + +namespace o2 +{ +namespace dcs +{ +/** + * Returns a simple timestamp presenting the milliseconds of time passed + * since the given time point. + * + * @param beginning The time point used as a reference for the time interval + * calculation. + * @return The amount of milliseconds passed since the given time point. + */ +inline uint64_t time_since( + const std::chrono::steady_clock::time_point beginning) noexcept +{ + return std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::steady_clock::now() - beginning) + .count(); +} + +/** + * Returns the measured number of milliseconds passed since UNIX epoch + * (1 January 1970 01:00:00.000). This function uses system clock. + * + * @return Number of milliseconds since epoch. + * @see ADAPRO::Library::now + */ +inline uint64_t epoch_time() noexcept +{ + return std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()) + .count(); +} + +/** + * Returns a timestamp using steady clock. This function is suitable for + * measuring time intervals, but it's not meant to be used for calculating + * dates. + * + * @return + * @see ADAPRO::Library::epoch_time + */ +inline uint64_t now() noexcept +{ + return std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); +} + +/** + * Returns a timestamp of the current point of time in the local timezone. + * + * @return A simple ISO-8601-esque timestamp (<tt>YYYY-MM-DD HH:MM:SS</tt>). + * Every decimal number in the date string has leading zeros and therefore + * fixed length. + * @see ADAPRO::Control::fs_timestamp + */ +inline std::string timestamp() noexcept +{ + char buffer[20]; + std::time_t now = std::time(nullptr); + std::strftime(buffer, 32, "%F %T", std::localtime(&now)); + return std::string(buffer); +} + +/** + * Returns a timestamp of the current point of time in the local timezone. + * The format of the timestamp is specified with the parameter + * <tt>format</tt>. The format of the format string is the same as is used + * by <tt>std::strftime</tt>. + * + * @return A simple timestamp in a format specified with the parameter + * <tt>format</tt>. + */ +inline std::string timestamp(const std::string& format) noexcept +{ + char buffer[20]; + std::time_t now = std::time(nullptr); + std::strftime(buffer, 32, format.c_str(), std::localtime(&now)); + return std::string(buffer); +} + +/** + * Generates a simple timestamp usable file paths. This function is like + * <tt>ADAPRO::Control::timestamp</tt>, but with spaces replaced with + * underscores and colons with dots in order to ensure compatibility with + * (Linux) filesystems. This function uses local timezone. + * + * @return A simple ISO-8601-esque timestamp (<tt>YYYY-MM-DD_HH.MM.SS</tt>). + * Every decimal number in the date string has leading zeros and therefore + * fixed length. + * @see ADAPRO::Control::timestamp + */ +inline std::string fs_timestamp() noexcept +{ + char buffer[20]; + std::time_t now = std::time(nullptr); + std::strftime(buffer, 32, "%F_%H.%M.%S", std::localtime(&now)); + return std::string(buffer); +} +} // namespace dcs +} // namespace o2 + +#endif /* O2_DCS_CLOCK_H */ diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h b/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h new file mode 100644 index 0000000000000..fea0bab7dfca0 --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h @@ -0,0 +1,262 @@ +// 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: DataPointCompositeObject.h + * Author: John Lång (john.larry.lang@cern.ch) + * + * Created on 23 September 2016, 11:28 + */ +#ifndef O2_DCS_DATAPOINT_COMPOSITE_OBJECT_H +#define O2_DCS_DATAPOINT_COMPOSITE_OBJECT_H + +#include <cstdint> +#include <stdexcept> +#include <ostream> +#include <string> +#include "Rtypes.h" +#include "DetectorsDCS/StringUtils.h" +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DeliveryType.h" + +namespace o2 +{ +namespace dcs +{ +/** + * DataPointCompositeObject is a composition of a DataPointIdentifier and a + * DataPointValue. It is the unit of data points that ADAPOS provides. + * + * @see ADAPRO::ADAPOS::DataPointIdentifier + * @see ADAPRO::ADAPOS::DataPointValue + */ +struct alignas(128) DataPointCompositeObject final { + /** + * The DataPointIdentifier object, which occupies the first 64 bytes of + * the DataPointCompositeObject. This object contains the immutable + * alias and type information. + * + * @see ADAPRO::ADAPOS::DataPointIdentifier + */ + const DataPointIdentifier id; + + /** + * The DataPointValue object, which occupies the last 64 bytes of the + * DataPointCompositeObject. This object contains the mutable parts of + * DataPointCompositeObject. These parts are the ADAPOS flags, + * timestamp, and the payload data. + * + * @see ADAPRO::ADAPOS::DataPointValue + */ + DataPointValue data; + + /** + * The default constructor for DataPointCompositeObject. Uses the + * default constructors of its component, which means that their every + * field will be filled with zeroes. + * + * @see ADAPRO::ADAPOS::DataPointIdentifier + * @see ADAPRO::ADAPOS::DataPointValue + */ + DataPointCompositeObject() noexcept : id(), data() {} + + /** + * This constructor <em>copies</em> the given DataPointIdentifier and + * DataPointValue into the fields <tt>id</tt> and <tt>data</tt>. + * + * @param id The DPID component. + * @param data The DPVAL component. + */ + DataPointCompositeObject( + const DataPointIdentifier& id, + const DataPointValue& data) noexcept : id(id), data(data) {} + + /** + * Bit-by bit equality comparison of DataPointCompositeObjects. + * + * @param other The right-hand operand of equality comparison. + * @return <tt>true</tt> or <tt>false</tt>. + */ + inline bool operator==(const DataPointCompositeObject& other) const + noexcept + { + return id == other.id && data == other.data; + } + + /** + * Negation of the <tt>==</tt> operator. + * + * @param other The right-hand side operand. + * @return <tt>true</tt> or <tt>false</tt>. + */ + inline bool operator!=(const DataPointCompositeObject& other) const + noexcept + { + return id != other.id || data != other.data; + } + + /** + * Overwrites a DataPointCompositeObject with the given <tt>id</tt> and + * <tt>data</tt> values. + * + * @param id The id value. + * @param data The data value. + */ + inline void set(const DataPointIdentifier& id, DataPointValue& data) noexcept + { + DataPointIdentifier::FILL(this->id, (uint64_t*)&id); + this->data = data; + } + + /** + * Overwrites a DataPointCompositeObject as a copy of the given 128-byte + * segment (16 times <tt>sizeof(uint64_t)</tt>) of binary data. + * + * @param data Beginning of the data segment used for reading. The + * length of the segment is assumed to be exactly 128 bytes and contain + * a valid binary representation of a DataPointCompositeObject. + */ + inline void set(const uint64_t* const data) noexcept + { + DataPointIdentifier::FILL(this->id, data); + this->data.set(data + 8, id.get_type()); + } + + /** + * Overwrites the state of the <tt>data</tt> field with the state of the + * given DPVAL object, <em>except for the control flags, that will be + * cleared out</em>. + * + * @param dpval A DPVAL object representing an update event to the + * DPCOM in question. + * + * @see ADAPRO::ADAPOS::DataPointValue + * @see ADAPRO::ADAPOS::DataPointValue::CONTROL_MASK + */ + inline void update(const DataPointValue& dpval) noexcept + { + data.set( + dpval.flags & ~DataPointValue::CONTROL_MASK, + dpval.msec, + dpval.sec, + (uint64_t*)&dpval.payload_pt1, + id.get_type()); + } + + /** + * Returns a pointer to the beginning of the data part to be given to + * DIM, which depends on the <tt>DeliveryType</tt> of this DPCOM. This + * method is specific to ADAPOS Load Generator and ADAPOS Engine. + * + * @return A <tt>(void*)</tt>. + * @throws std::domain_error If the <tt>DeliveryType</tt> of this + * DPCOM object was illegal (i.e. <tt>VOID</tt> or something else than + * the enumerators of <tt>DeliveryType</tt>). + * @see ADAPRO::ADAPOS::DeliveryType + */ + inline void* dim_buffer() const + { + switch (id.get_type()) { + case RAW_INT: + case RAW_UINT: + case RAW_BOOL: + case RAW_CHAR: + case RAW_DOUBLE: + case RAW_TIME: + case RAW_STRING: + case RAW_BINARY: + return (void*)&data.payload_pt1; + case DPVAL_INT: + case DPVAL_UINT: + case DPVAL_BOOL: + case DPVAL_CHAR: + case DPVAL_DOUBLE: + case DPVAL_TIME: + case DPVAL_STRING: + case DPVAL_BINARY: + return (void*)&data; + default: + case VOID: + throw std::domain_error("Illegal DeliveryType."); + } + } + + /** + * Prints a CSV-representation of the DataPointCompositeObject into the + * ostream. The format of the payload data depends on its type and is + * handled automatically. + * + * @param os The output stream. + * @param dpcom The DataPointCompositeObject. + * @return Reference to the stream after the printing operation. + */ + inline friend std::ostream& operator<<(std::ostream& os, + const DataPointCompositeObject& dpcom) noexcept + { + std::string payload; + os << dpcom.id << ";" << dpcom.data << ";"; + union Converter { + uint64_t raw_data; + double double_value; + uint32_t uint_value; + int32_t int_value; + char char_value; + bool bool_value; + } converter; + converter.raw_data = dpcom.data.payload_pt1; + switch (dpcom.id.get_type()) { + case VOID: + return os; + case RAW_INT: + case DPVAL_INT: + return os << converter.int_value; + case RAW_UINT: + case DPVAL_UINT: + return os << converter.uint_value; + case RAW_BOOL: + case DPVAL_BOOL: + return os << (converter.bool_value ? "True" : "False"); + case RAW_CHAR: + case DPVAL_CHAR: + return os << converter.char_value; + case RAW_DOUBLE: + case DPVAL_DOUBLE: + return os << converter.double_value; + case RAW_STRING: + case DPVAL_STRING: + return os << std::string((char*)&dpcom.data.payload_pt1); + case RAW_TIME: + case DPVAL_TIME: { + // I have no idea how to properly test the time_t backend. + // It's probably even hardware/os/kernel specific... +#ifdef __linux__ + char buffer[17]; + std::time_t ts((dpcom.data.payload_pt1) >> 32); + std::strftime(buffer, 32, "%FT%T", std::gmtime(&ts)); + return os << std::string(buffer) << "." << std::setw(3) << std::setfill('0') << std::to_string((dpcom.data.payload_pt1 & 0x00000000FFFF0000) >> 16) + << "Z"; +#else + return os << "[Timestamps not supported on this platform.]"; +#endif + } + case RAW_BINARY: + case DPVAL_BINARY: + default: + return os << o2::dcs::to_hex_little_endian( + (char*)&dpcom.data.payload_pt1, 56); + } + } + ClassDefNV(DataPointCompositeObject, 1); +}; +} // namespace dcs +} // namespace o2 + +#endif /* O2_DCS_DATAPOINT_COMPOSITE_OBJECT_H */ diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h b/Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h new file mode 100644 index 0000000000000..a5ace31a62e17 --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h @@ -0,0 +1,219 @@ +// 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: DataPointIdentifier.h + * Author: John Lång (john.larry.lang@cern.ch) + * + * Created on 23 September 2016, 12:00 + */ +#ifndef O2_DCS_DATAPOINT_IDENTIFIER_H +#define O2_DCS_DATAPOINT_IDENTIFIER_H + +#include <cstring> +#include <string> +#include <cstdint> +#include <iostream> +#include <iomanip> +#include <functional> +#include "Rtypes.h" +#include "DetectorsDCS/StringUtils.h" +#include "DetectorsDCS/GenericFunctions.h" +#include "DetectorsDCS/DeliveryType.h" + +namespace o2 +{ +namespace dcs +{ +/** + * DataPointIdentifier object is responsible for storing the alias and type + * information of a data point. + */ +class alignas(64) DataPointIdentifier final +{ + const uint64_t pt1; + const uint64_t pt2; + const uint64_t pt3; + const uint64_t pt4; + const uint64_t pt5; + const uint64_t pt6; + const uint64_t pt7; + const uint64_t pt8; // Contains the last 6 chars of alias and the type. + + DataPointIdentifier( + const uint64_t pt1, const uint64_t pt2, const uint64_t pt3, + const uint64_t pt4, const uint64_t pt5, const uint64_t pt6, + const uint64_t pt7, const uint64_t pt8) noexcept : pt1(pt1), pt2(pt2), pt3(pt3), pt4(pt4), pt5(pt5), pt6(pt6), pt7(pt7), pt8(pt8) {} + + public: + /** + * The default constructor for DataPointIdentifier. Creates a DPID that + * contains only zeroes. To fill it with alias and type, please use the + * factory procedure <tt>fill</tt>. + * + * @see ADAPRO::ADAPOS::DataPointIdentifier::fill + */ + DataPointIdentifier() noexcept : pt1(0), pt2(0), pt3(0), pt4(0), pt5(0), pt6(0), pt7(0), pt8(0) + { + } + + /** + * A constructor for DataPointIdentifier. Copies the given arguments to + * the memory segment owned by the object under construction. + * + * @param alias The alias of the DataPointIdentifier. Maximum length is + * 62 characaters. + * @param type Type of the payload value associated with the service + * identified by this DataPointIdentifier. + */ + DataPointIdentifier(const std::string& alias, const DeliveryType type) noexcept : DataPointIdentifier() + { + strncpy((char*)this, alias.c_str(), 62); + ((char*)&pt8)[7] = type; + } + + /** + * This stati procedure fills the given DataPointIdentifier object with + * the given parameters. + * + * @param dpid The DataPointIdentifier to be filled (i.e. overwritten). + * @param alias Alias of the data point. This is used for identifying + * the DIM service that publishes updates to a data point. + * @param type Type of the data point payload value. + */ + static inline void FILL( + const DataPointIdentifier& dpid, + const std::string& alias, + const DeliveryType type) noexcept + { + strncpy((char*)&dpid, alias.c_str(), 62); + ((char*)&dpid.pt8)[7] = type; + } + + /** + * This static procedure copies the given 64-byte binary segment into + * the DataPointIdentifier object. + * + * @param dpid The DataPointIdentifier to be filled (i.e. overwritten). + * @param data Beginning of the 64-byte binary segment. + */ + static inline void FILL( + const DataPointIdentifier& dpid, + const uint64_t* const data) noexcept + { + std::strncpy((char*)&dpid, (char*)data, 62); + ((char*)&dpid)[63] = ((data[7] & 0xFF00000000000000) >> 56); + } + + /** + * The equality comparison object of DPIDs. + * + * @param other The other DPID object for comparison. + * @return <tt>true</tt> if and only if the other DPID object + * has exactly (bit-by-bit) the same state. + */ + inline bool operator==(const DataPointIdentifier& other) const + { + return memcmp((char*)this, (char*)&other, 64) == 0; + } + + /** + * Negation of the equality comparison. + * + * @param other The second operand. + * @return <tt>true</tt> or <tt>false</tt>. + */ + inline bool operator!=(const DataPointIdentifier& other) const + { + return !(*this == other); + } + + /** + * Appends DataPointIdentifier object to the given stream using CSV + * format (i.e. <tt><alias> ";" <type></tt>). + */ + friend inline std::ostream& operator<<(std::ostream& os, + const DataPointIdentifier& dpid) noexcept + { + return os << std::string((char*)&dpid) << ";" << o2::dcs::show((DeliveryType)((dpid.pt8 & 0xFF00000000000000) >> 56)); + } + + /** + * Returns the alias of the DPID object as a C-style string (i.e. + * null-terminated char array). + * + * @return The alias. + */ + inline const char* const get_alias() const noexcept + { + return (char*)&pt1; + } + + /** + * Getter for the payload type information. + * + * @return a DeliveryType object. + */ + inline DeliveryType get_type() const noexcept + { + return (DeliveryType)((pt8 & 0xFF00000000000000) >> 56); + } + + /** + * Returns a hash code calculated from the alias. <em>Note that the + * hash code is recalculated every time when this function is called. + * </em> + * + * @return An unsigned integer. + */ + inline size_t hash_code() const noexcept + { + return o2::dcs::hash_code(std::string((char*)&pt1)); + } + + /** + * The destructor for DataPointIdentifier. + */ + ~DataPointIdentifier() noexcept = default; + ClassDefNV(DataPointIdentifier, 1); +}; + +/** + * This simple function object is used for calculating the hash code for a + * DataPointIdentifier object in a STL container. + * + * @param dpid The DataPointIdentifier object, whose hash code is to be + * calculated. + * @return The calculated hash code. + */ +struct DPIDHash { + uint64_t operator()(const o2::dcs::DataPointIdentifier& dpid) + const + { + return dpid.hash_code(); + } +}; +} // namespace dcs + +} // namespace o2 + +// specailized std::hash +namespace std +{ +template <> +struct hash<o2::dcs::DataPointIdentifier> { + std::size_t operator()(const o2::dcs::DataPointIdentifier& dpid) const + { + return std::hash<uint64_t>{}(dpid.hash_code()); + } +}; +} // namespace std + +#endif /* O2_DCS_DATAPOINT_IDENTIFIER_H */ diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointValue.h b/Detectors/DCS/include/DetectorsDCS/DataPointValue.h new file mode 100644 index 0000000000000..0887cf0d28c5d --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/DataPointValue.h @@ -0,0 +1,701 @@ +// 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: DataPointValue.h + * Author: John Lång (john.larry.lang@cern.ch) + * + * Created on 23 September 2016, 12:20 + */ +#ifndef O2_DCS_DATAPOINT_VALUE +#define O2_DCS_DATAPOINT_VALUE + +#include <cstring> +#include <cstdint> +#include <ctime> +#include <atomic> +#include <string> +#include <ostream> +#include <sstream> +#include <iostream> +#include <iomanip> +#include <memory> +#include <stdexcept> +#include "Rtypes.h" +#include "DetectorsDCS/StringUtils.h" +#include "DetectorsDCS/Clock.h" +#include "DetectorsDCS/DeliveryType.h" + +namespace o2 +{ +namespace dcs +{ +/** + * DataPointValue is the struct responsible for containing the flags, + * timestamp, and payload value of a data point. It represents a discrete + * update event to a data point. <em>It should be noted that the + * constructors and setters of this struct, that take an array containing + * binary data as parameter, don't check the length of the given array.</em> + */ +struct alignas(64) DataPointValue final { + /** + * <p>This flag is used for signaling that a DPVAL stream connection is + * working, but there is no data to be sent.</p> + * <p>If this flag is set, it will be denoted with letter <tt>A</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t KEEP_ALIVE_FLAG = 0x0001; + + /** + * <p>This flag is used for signaling the end of transmission.</p> + * <p>If this flag is set, it will be denoted with letter <tt>Z</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t END_FLAG = 0x0002; + + /** + * <p>This flag is set in the ADAPOS FBI Master DPCOM object.</p> + * <p>If this flag is set, it will be denoted with letter <tt>M</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t FBI_FLAG = 0x0004; + + /** + * <p>This flag is set by Producer to signal Consumer that this + * DataPointValue object belongs to a new service, that doesn't yet have + * its DataPointCompositeObject in the image.</p> + * <p>If this flag is set, it will be denoted with letter <tt>N</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t NEW_FLAG = 0x0008; + + /** + * <p>This flag is reserved for the ADAPRO/ADAPOS Producer-Consumer + * model. A DataPointValue is dirty if and only if it's stored in the + * ring buffer but not been fully processed yet. This flag should always + * be set when a DPCOM containing the DataPointValue object arrives from + * ADAPOS Engine via TCP.</p> + * <p>If this flag is set, it will be denoted with letter <tt>D</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t DIRTY_FLAG = 0x0010; + + /** + * <p>This flag is used as a part of the DPVAL mutual exclusion + * mechanism. This flag should be set iff reader has the turn.</p> + * <p>If this flag is set, it will be denoted with letter <tt>U</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint64_t TURN_FLAG = 0x0020; + + /** + * <p>This flag is used by the DPVAL mutual exclusion mechanism.</p> + * <p>If this flag is set, it will be denoted with letter <tt>W</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t WRITE_FLAG = 0x0040; + + /** + * <p>This flag is used by the DPVAL mutual exclusion mechanism.</p> + * <p>If this flag is set, it will be denoted with letter <tt>R</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t READ_FLAG = 0x0080; + + /** + * <p>This flag should be set if and only if there is a ring buffer + * overflow happening. Ring buffer overflow is manifested as an + * overwrite of a dirty DPVAL.</p> + * <p>If this flag is set, it will be denoted with letter <tt>O</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t OVERWRITE_FLAG = 0x0100; + + /** + * <p>In case of buffer overflow, this flag can be used for indicating a + * service that lost an update. <em>Not receiving this flag shouldn't be + * taken as an indication that every update was successfully + * transmitted.</em></p> + * <p>If this flag is set, it will be denoted with letter <tt>V</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t VICTIM_FLAG = 0x0200; + + /** + * <p>This flag should be set if and only if there is a DIM error + * (namely, connection failure with the DIM service) in ADAPOS Engine + * affecting this DataPointValue object.</p> + * <p>If this flag is set, it will be denoted with letter <tt>E</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t DIM_ERROR_FLAG = 0x0400; + + /** + * <p>This flag should be set if and only if the DPID of the DPCOM + * containing this DPVAL has incorrect or unexpected value.</p> + * <p>If this flag is set, it will be denoted with letter <tt>I</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t BAD_DPID_FLAG = 0x0800; + + /** + * <p>This flag should be set if and only if the flags themselves have + * bad or unexpedcted value.</p> + * <p>If this flag is set, it will be denoted with letter <tt>F</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t BAD_FLAGS_FLAG = 0x1000; + + /** + * <p>This flag should be set if and only if the timestamp is + * incorrect.</p> + * <p>If this flag is set, it will be denoted with letter <tt>T</tt> in + * the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t BAD_TIMESTAMP_FLAG = 0x2000; + + /** + * <p>This flag should be set if and only if the payload value is bad. + * </p><p>If this flag is set, it will be denoted with letter <tt>P</tt> + * in the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t BAD_PAYLOAD_FLAG = 0x4000; + + /** + * <p>This flag should be set if it a FBI contains duplicated DPCOMs + * (i.e. DPCOMs with identical DPIDs). Also, partial FBI (with missing + * DPCOMs) can be indicated with this flag.</p> + * </p><p>If this flag is set, it will be denoted with letter <tt>B</tt> + * in the CSV output generated from this DPVAL object.</p> + */ + static constexpr uint16_t BAD_FBI_FLAG = 0x8000; + + /** + * This mask covers the session flags: <tt>KEEP_ALIVE_FLAG</tt>, + * <tt>END_FLAG</tt>, and <tt>FBI_MASTER_FLAG</tt>. + * + * @see ADAPRO::ADAPOS::DataPointValue::KEEPALIVE_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::END_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::FBI_FLAG + */ + static constexpr uint16_t SESSION_MASK = 0x0007; + + /** + * This mask covers the control flags: <tt>NEW_FLAG</tt>, + * <tt>DIRTY_FLAG</tt>, <tt>TURN_FLAG</tt>, <tt>WRITE_FLAG</tt>, and + * <tt>READ_FLAG</tt>. + * + * @see ADAPRO::ADAPOS::DataPointValue::NEW_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::DIRTY_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::TURN_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::WRITE_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::READ_FLAG + */ + static constexpr uint16_t CONTROL_MASK = 0x00F8; + + /** + * This mask covers the error flags: <tt>DIM_ERROR_FLAG</tt>, + * <tt>OVERWRITE_FLAG</tt>, <tt>VICTIM_FLAG</tt>, + * <tt>BAD_DPID_FLAG</tt>, <tt>BAD_FLAGS_FLAG</tt>, + * <tt>BAD_TIMESTAMP_FLAG</tt>, <tt>BAD_PAYLOAD_FLAG</tt>, and + * <tt>BAD_FBI_FLAG</tt>. + * + * @see ADAPRO::ADAPOS::DataPointValue::DIM_ERROR_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::OVERWRITE_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::VICTIM_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_DPID_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_FLAGS_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_TIMESTAMP_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_PAYLOAD_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_FBI_FLAG + */ + static constexpr uint16_t ERROR_MASK = 0xFF00; + + /** + * The ADAPOS flags, i.e. a bitmask of the 16 different DPVAL flags. + * + * @see ADAPRO::ADAPOS::DataPointValue::KEEPALIVE_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::END_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::FBI_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::NEW_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::DIRTY_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::TURN_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::WRITE_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::READ_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::DIM_ERROR_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::OVERWRITE_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_DPID_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_FLAGS_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_TIMESTAMP_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_PAYLOAD_FLAG + * @see ADAPRO::ADAPOS::DataPointValue::BAD_FBI_FLAG + */ + uint16_t flags = 0; + + /** + * Milliseconds of the timestamp. This is the measured number of + * milliseconds passed since the UNIX epoch + * (1 January 1970, 01:00:00.000) modulo 1000. The purpose of this field + * together with <tt>sec</tt> is to store a timestamp indicating the + * moment of creation/modification of the DataPointValue object. + * + * @see ADAPRO::ADAPOS::DataPointValue::sec + */ + uint16_t msec = 0; + + /** + * Seconds of the timestamp. This is the measured number of seconds + * passed since the UNIX epoch (1 January 1970, 01:00:00.000). The + * purpose of this field together with <tt>msec</tt> is to store a + * timestamp indicating the moment of creation/modification of the + * DataPointValue object. + */ + uint32_t sec = 0; + + /** + * First part of the 56-byte binary payload value. + */ + uint64_t payload_pt1 = 0; + + /** + * Second part of the 56-byte binary payload value. + */ + uint64_t payload_pt2 = 0; + + /** + * Third part of the 56-byte binary payload value. + */ + uint64_t payload_pt3 = 0; + + /** + * Fourth part of the 56-byte binary payload value. + */ + uint64_t payload_pt4 = 0; + + /** + * Fifth part of the 56-byte binary payload value. + */ + uint64_t payload_pt5 = 0; + + /** + * Sixth part of the 56-byte binary payload value. + */ + uint64_t payload_pt6 = 0; + + /** + * Seventh part of the 56-byte binary payload value. + */ + uint64_t payload_pt7 = 0; + + /** + * The default constuctor of DataPointValue. Fills the object with + * zeroes. + */ + DataPointValue() = default; + + /** + * The trivial copy constructor of DataPointValue. + * + * @param other The DataPointValue instance, whose state is to be copied + * to the new object. + */ + DataPointValue(const DataPointValue& other) = default; + + /** + * Constructor for DataPointValue. <em>This constructor assumes that the + * <tt>payload</tt> parameter points to a <tt>unit64_t</tt> array with + * (at least) seven elements.</em> The data will be treated as binary + * and will be written to the new DataPointValue object using + * <tt>std::memcpy</tt>. Use of this constructor is discouraged, since + * it might copy garbage data. Please consider using the constructor + * with a <tt>DeliveryType</tt> parameter instead. + * + * @param flags The ADAPOS flags. + * @param milliseconds Milliseconds of the timestamp. + * @param seconds Seconds of the timestamp. + * @param payload Pointer to a memory segment containing the + * binary payload data. The next seven <tt>uint64_t</tt> values (i.e. 56 + * <tt>char</tt>s) will be copied to the DataPointValue object. + * <em>payload</em> must not be <tt>nullptr</tt>. For an empty DPVAL, + * use the default constructor. + * + * @deprecated Since ADAPRO 4.1.0, this constructor has become + * deprecated. Please consider using the constructor with a + * <tt>DeliveryType</tt> parameter instead. + */ + [[deprecated]] DataPointValue( + const uint16_t flags, + const uint16_t milliseconds, + const uint32_t seconds, + const uint64_t* const payload) noexcept : flags(flags), msec(milliseconds), sec(seconds) + { + memcpy((void*)&payload_pt1, (void*)payload, 56); + } + + /** + * <p>Constructor for DataPointValue. Copies a data segment from the + * array <tt>payload</tt>. Length of the copied data is determined by + * the argument <tt>type</tt>. <em>No sanity checks on the given + * array are performed.</em></p> + * <p>If the given <tt>DeliveryType</t> is invalid, then the payload + * of the new DataPointValue object will be filled with zeros.</p> + * + * @param flags The ADAPOS flags. + * @param milliseconds Milliseconds of the timestamp. + * @param seconds Seconds of the timestamp. + * @param payload Pointer to a contiguous block of memory + * containing the binary payload data. + * @param type Used for setting the payload correctly, using + * <tt>set_payload</tt>. If this argument is <tt>VOID</tt>, then the + * contents of the payload remain undefined. + * + * @throws std::domain_error If applied with an invalid DeliveryType. + * @see ADAPRO::Data::DataPointValue::set_payload + */ + DataPointValue( + const uint16_t flags, + const uint16_t milliseconds, + const uint32_t seconds, + const uint64_t* const payload, + const DeliveryType type) + : flags(flags), msec(milliseconds), sec(seconds) + { + set_payload(payload, type); + } + + /** + * Sets the given payload data to the DataPointValue. This setter avoids + * copying garbage, because it uses the type information. However, it + * assumes the given array to have at least the length determined by the + * payload type. + * + * @param data A binary segment containing the new payload data. + * @param type Type of the payload data. + * + * @throws std::domain_error If applied with an invalid DeliveryType. + */ + inline void set_payload( + const uint64_t* const data, + const DeliveryType type) + { + switch (type) { + case RAW_INT: + case DPVAL_INT: + case RAW_UINT: + case DPVAL_UINT: + this->payload_pt1 = data[0] & 0x00000000FFFFFFFF; + break; + case RAW_BOOL: + case DPVAL_BOOL: + this->payload_pt1 = (data[0] ? 1 : 0); + break; + case RAW_CHAR: + case DPVAL_CHAR: + this->payload_pt1 = data[0] & 0x00000000000000FF; + break; + case RAW_DOUBLE: + case DPVAL_DOUBLE: + case RAW_TIME: + case DPVAL_TIME: + this->payload_pt1 = data[0]; + break; + case RAW_STRING: + case DPVAL_STRING: + std::strncpy((char*)&payload_pt1, (char*)data, 56); + break; + case RAW_BINARY: + case DPVAL_BINARY: + memcpy((void*)&payload_pt1, (void*)data, 56); + case VOID: + break; + default: + throw std::domain_error("Invalid DeliveryType."); + } + } + + /** + * Returns the ADAPOS flags of the DataPointValue. + * + * @return ADAPOS flags. + */ + inline uint16_t get_flags() const noexcept + { + return flags; + } + + /** + * Updates the timestamp of this DataPointValue object using system + * clock. + */ + inline void update_timestamp() noexcept + { + const uint64_t current_time(o2::dcs::epoch_time()); + msec = current_time % 1000; + sec = current_time / 1000; + } + + /** + * <p>On Linux platforms, Returns a unique pointer to a string + * containing an ISO 8601 timestamp. The value of the timestamp will be + * calculated from the values of the fields <tt>msec</tt> and + * <tt>sec</tt> and assuming the UTC timezone. The timestamp has the + * following format:</p> + * <p><tt><YYYY-MM-DD> "T" <HH:MM:SS.SSS> "Z"</tt></p> + * + * @return An ISO 8601 compliant timestamp. + */ + inline std::unique_ptr<std::string> get_timestamp() const noexcept + { +#ifdef __linux__ + // time_t should be uint64_t (compatible) on 64-bit Linux platforms: + char buffer[17]; + std::time_t ts((uint64_t)sec); + std::strftime(buffer, 32, "%FT%T", std::gmtime(&ts)); + std::ostringstream oss; + oss << std::string(buffer) << "." << std::setw(3) << std::setfill('0') << std::to_string(msec) << "Z"; + return std::make_unique<std::string>( + std::move(oss.str())); +#else + return std::make_unique<std::string>("Unsupported platform"); +#endif + } + + /** + * Returns a 64-bit unsigned integer containing the timestamp value of + * the DPVAL object. + * + * @return Milliseconds since the UNIX epoch (1.1.1970 01:00:00.000). + */ + inline uint64_t get_epoch_time() const noexcept + { + return (((uint64_t)sec) * 1000) + msec; + } + + /** + * <p>The standard copy assignment operator. Performs a normal deep copy + * operation overwriting this DataPointValue object with the other.</p> + * <p><em>Note that this operator always copies a fixed size data + * segment from the given DPVAL to this DPVAL regardless of the payload + * value type. </em>Therefore, non-zero garbage data might be copied as + * well. Using the setters with the <tt>type</tt> parameter is + * recommended.</p> + * + * @param other The DataPointValue object, whose state will be copied to + * this object. + * @return <tt>*this</tt> after performing the copying. + */ + DataPointValue& operator=(const DataPointValue& other) = default; + + /** + * Bit-by bit equality comparison of DPVAL objects. + * + * @param other The second operand of equality comparison. + * @return <tt>true</tt> or <tt>false</tt>. + */ + inline bool operator==(const DataPointValue& other) const noexcept + { + return memcmp((void*)this, (void*)&other, sizeof(DataPointValue)) == 0; + } + + /** + * Negation of the equality comparison. + * + * @param other The second operand. + * @return <tt>true</tt> or <tt>false</tt>. + */ + inline bool operator!=(const DataPointValue& other) const noexcept + { + return !(*this == other); + } + + /** + * Sets the state of the DataPointValue. Copies a data segment from the + * array <tt>payload</tt>. Length of the copied data is determined by + * the argument <tt>type</tt>. <em>No sanity checks on the given array + * are performed.</em> + * + * @param flags New value for ADAPOS flags. + * @param milliseconds New value for milliseconds. + * @param seconds New value for seconds. + * @param payload New payload data. + * @param type Used for setting the payload correctly, using + * <tt>set_payload</tt>. + * + * @throws std::domain_error If applied with an invalid DeliveryType. + * @see ADAPRO::Data::DataPointValue::set_payload + */ + inline void set( + const uint16_t flags, + const uint16_t milliseconds, + const uint32_t seconds, + const uint64_t* const payload, + const DeliveryType type) + { + this->flags = flags; + this->msec = milliseconds; + this->sec = seconds; + set_payload(payload, type); + } + + /** + * Sets the state of the DataPointValue, except for the flags. This + * setter can be used for safely setting the state of the object without + * interfering with the locking mechanism or invalidating the mutual + * exclusion. This setter was added in <em>ADAPRO 2.4.0</em>. + * + * @param milliseconds Milliseconds of the new timestamp. + * @param seconds Seconds of the new timestamp. + * @param payload New payload. + * @param type Used for setting the payload correctly, using + * <tt>set_payload</tt>. + * + * @throws std::domain_error If applied with an invalid DeliveryType. + * @see ADAPRO::Data::DataPointValue::set_payload + */ + inline void set( + const uint16_t milliseconds, + const uint32_t seconds, + const uint64_t* const payload, + const DeliveryType type) + { + msec = milliseconds; + sec = seconds; + set_payload(payload, type); + } + + /** + * Sets the state of the DataPointValue. <em>No sanity checks on the + * given array are performed.</em> The first array element is assumed to + * contain data for the flags and the timestamp with their respective + * sizes and order, while the rest of the array is assumed to contain + * the payload data. + * + * @param data New DPVAL contents. + * @param type Used for setting the payload correctly, using + * <tt>set_payload</tt>. + * + * @throws std::domain_error If applied with an invalid DeliveryType. + * @see ADAPRO::Data::DataPointValue::set_payload + */ + inline void set( + const uint64_t* const data, + const DeliveryType type) + { + this->flags = data[0]; + this->msec = data[0] >> 16; + this->sec = data[0] >> 32; + set_payload(data + 1, type); + } + + /** + * Prints the flags and timestamp of the DataPointValue object into the + * <tt>ostream</tt>, but not the payload data. The reason for omitting + * the payload value is that DataPointValue lacks payload data typing + * information, so conversion from binary to string is not meaningful. + */ + friend inline std::ostream& operator<<(std::ostream& os, + const DataPointValue& dpval) noexcept + { + return os << ((dpval.flags & KEEP_ALIVE_FLAG) ? "A" : "-") + << ((dpval.flags & END_FLAG) ? "Z" : "-") + << ((dpval.flags & FBI_FLAG) ? "M" : "-") + << ((dpval.flags & NEW_FLAG) ? "N" : "-") + << ((dpval.flags & DIRTY_FLAG) ? "D" : "-") + << ((dpval.flags & TURN_FLAG) ? "U" : "-") + << ((dpval.flags & WRITE_FLAG) ? "W" : "-") + << ((dpval.flags & READ_FLAG) ? "R " : "- ") + << ((dpval.flags & OVERWRITE_FLAG) ? "O" : "-") + << ((dpval.flags & VICTIM_FLAG) ? "V" : "-") + << ((dpval.flags & DIM_ERROR_FLAG) ? "E" : "-") + << ((dpval.flags & BAD_DPID_FLAG) ? "I" : "-") + << ((dpval.flags & BAD_FLAGS_FLAG) ? "F" : "-") + << ((dpval.flags & BAD_TIMESTAMP_FLAG) ? "T" : "-") + << ((dpval.flags & BAD_PAYLOAD_FLAG) ? "P" : "-") + << ((dpval.flags & BAD_FBI_FLAG) ? "B;" : "-;") + << *(dpval.get_timestamp()); + } + + /** + * <p>Acquires the lock for writing into this DPVAL. This method is + * based on Peterson's algorithm (with a spinlock). It can be used for + * ensuring mutual exclusion between two threads accessing this DPVAL + * object. <em>It is important to release the write lock by calling + * <tt>release_write_lock()</tt> after use.</em></p> + * <p><em>This method may or may not work due to CPU instruction + * reordering, caching, and other optimizations.</em> Using + * <tt>std::mutex</tt> instead is recommended.</p> + * + * @see ADAPRO::ADAPOS::DataPointValue::release_write_lock + */ + inline void acquire_write_lock() + { + flags |= WRITE_FLAG; + flags |= TURN_FLAG; + while (flags & READ_FLAG && flags & TURN_FLAG) { + } + } + + /** + * <p>Releases the lock for writing into this DPVAL. This function is + * based on Peterson's algorithm (with a spinlock). It can be used for + * ensuring mutual exclusion between two threads accessing this DPVAL + * object.</p> + * <p><em>This method may or may not work due to CPU instruction + * reordering, caching, and other optimizations.</em> Using + * <tt>std::mutex</tt> instead is recommended.</p> + * + * @see ADAPRO::ADAPOS::DataPointValue::acquire_write_lock + */ + inline void release_write_lock() + { + flags &= ~WRITE_FLAG; + } + + /** + * <p>Acquires the lock for reading from this DPVAL. This function is + * based on Peterson's algorithm (with a spinlock). It can be used for + * ensuring mutual exclusion between two threads accessing this DPVAL + * object. <em>It is important to release the read lock by calling + * <tt>release_read_lock()</tt> after use.</em></p> + * <p><em>This method may or may not work due to CPU instruction + * reordering, caching, and other optimizations.</em> Using + * <tt>std::mutex</tt> instead is recommended.</p> + * + * @see ADAPRO::ADAPOS::DataPointValue::release_read_lock + */ + inline void acquire_read_lock() + { + flags |= READ_FLAG; + flags &= ~TURN_FLAG; + while (flags & WRITE_FLAG && !(flags & TURN_FLAG)) { + } + } + + /** + * <p>Releases the lock for reading from this DPVAL. This function is + * based on Peterson's algorithm (with a spinlock). It can be used for + * ensuring mutual exclusion between two threads accessing this DPVAL + * object.</p> + * <p><em>This method may or may not work due to CPU instruction + * reordering, caching, and other optimizations.</em> Using + * <tt>std::mutex</tt> instead is recommended.</p> + * + * @see ADAPRO::ADAPOS::DataPointValue::acquire_read_lock + */ + inline void release_read_lock() + { + flags &= ~READ_FLAG; + } + ClassDefNV(DataPointValue, 1); +}; +} // namespace dcs +} // namespace o2 + +#endif /* O2_DCS_DATAPOINT_VALUE_H */ diff --git a/Detectors/DCS/include/DetectorsDCS/DeliveryType.h b/Detectors/DCS/include/DetectorsDCS/DeliveryType.h new file mode 100644 index 0000000000000..8da5b2452f1bc --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/DeliveryType.h @@ -0,0 +1,380 @@ +// 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: DeliveryType.h + * Author: John Lång (john.larry.lang@cern.ch) + * + * Created on 17 July 2015, 9:54 + */ + +#ifndef O2_DCS_DELIVERY_TYPE +#define O2_DCS_DELIVERY_TYPE + +#include <string> +#include <regex> +#include <stdexcept> +#include "DetectorsDCS/GenericFunctions.h" + +namespace o2 +{ +namespace dcs +{ +/** + * This regular expression matches with strings representing payload types. + */ +static const std::regex REGEX_PT( + "^(Raw|DPVAL)/(Int|Uint|Double|Bool|Char|String|Time|Binary)$"); + +/** + * <p>DeliveryType is a piece of meta-information used for deducing types of + * DPVAL payloads and DIM service description strings used with services + * providing data to ADAPOS. DPCOMs use the DeliveryType of DPIDs to infer + * the correct interpretation of payload data when being put into a + * <tt>std::ofstream</tt>. Also, ADAPOS Engine uses DeliveryTypes for DIM + * service subscription (and Load Generator for generating services).</p> + * <p>Every DeliveryType, except <tt>VOID</tt>, has a raw and DPVAL + * variant. A DIM service publishing payloads in DPVALs has a different + * format and binary layout than a DIM service publishing only raw data, so + * this distinction is critical to ADAPOS Engine.</p> + * + * @see ADAPRO::ADAPOS::DataPointCompositeObject + * @see ADAPRO::ADAPOS::DataPointIdentifier + * @see ADAPRO::ADAPOS::DataPointValue + */ +enum DeliveryType { + /** + * This DeliveryType is included only for testing and debugging + * when the payload of a DPVAL is not going to be accessed. Accessing + * the payload of a DPVAL with this DeliveryType results in a domain + * error. + */ + VOID = 0, + + /** + * <tt>Binary</tt> is the general payload data type. This is the raw + * variant. + */ + RAW_BINARY = 64, + + /** + * <tt>Binary</tt> is the general payload data type. This is the DPVAL + * variant. + */ + DPVAL_BINARY = 192, + + /** + * <tt>Int</tt> stands for a 32-bit signed integer. This is the raw + * variant. The numerical value of <tt>RAW_INT</tt> corresponds with the + * WinCC constant <tt>DPEL_INT</tt>. + */ + RAW_INT = 21, + + /** + * <tt>Int</tt> stands for a 32-bit signed integer. This is the DPVAL + * variant. + */ + DPVAL_INT = 149, + + /** + * <tt>Uint</tt> stands for a 32-bit unsigned integer. This is the raw + * variant. The numerical value of <tt>RAW_UINT</tt> corresponds with + * the WinCC constant <tt>DPEL_UINT</tt>. + */ + RAW_UINT = 20, + + /** + * <tt>Uint</tt> stands for a 32-bit insigned integer. This is the DPVAL + * variant. + */ + DPVAL_UINT = 148, + + /** + * <tt>Double</tt> stands for IEEE 754 double precision floating point + * number (64 bit). This is the raw variant. The numerical value of + * <tt>RAW_INT</tt> corresponds with the WinCC constant + * <tt>DPEL_FLOAT</tt>. + */ + RAW_DOUBLE = 22, + + /** + * <tt>Double</tt> stands for IEEE 754 double precision floating point + * number (64 bit). This is the DPVAL variant. + */ + DPVAL_DOUBLE = 150, + + /** + * <tt>Bool</tt> stands for a boolean. This is the raw variant. The + * numerical value of <tt>RAW_BOOL</tt> corresponds with the WinCC + * constant <tt>DPEL_BOOL</tt>. + */ + RAW_BOOL = 23, + + /** + * <tt>Bool</tt> stands for a boolean. This is the DPVAL variant. + */ + DPVAL_BOOL = 151, + + /** + * <tt>Char</tt> stands for an ASCII character. This is the raw variant. + * The numerical value of <tt>RAW_CHAR</tt> corresponds with the WinCC + * constant <tt>DPEL_CHAR</tt>. + */ + RAW_CHAR = 19, + + /** + * <tt>Char</tt> stands for an ASCII character. This is the raw variant. + */ + DPVAL_CHAR = 147, + + /** + * <tt>String</tt> stands for a null-terminated array of ASCII + * characters. This is the raw variant. The numerical value of + * <tt>RAW_STRING</tt> corresponds with the WinCC constant + * <tt>DPEL_STRING</tt>. + */ + RAW_STRING = 25, + + /** + * <tt>String</tt> stands for a null-terminated array of ASCII + * characters. This is the DPVAL variant. + */ + DPVAL_STRING = 153, + + /** + * <tt>Time</tt> stands for two 32-bit (unsigned) integers containing + * the milliseconds and secodns of a UNIX timestamp. This is the raw + * variant. The numerical value of <tt>RAW_TIME</tt> corresponds with + * the WinCC constant <tt>DPEL_DYN_UINT</tt>. + */ + RAW_TIME = 4, + + /** + * <tt>Time</tt> stands for two 32-bit (unsigned) integers containing + * the milliseconds and secodns of a UNIX timestamp. This is the DPVAL + * variant. + */ + DPVAL_TIME = 132 +}; + +template <> +inline DeliveryType read(const std::string& str) +{ + if (str == "Raw/Int") { + return RAW_INT; + } else if (str == "Raw/Uint") { + return RAW_UINT; + } else if (str == "Raw/Double") { + return RAW_DOUBLE; + } else if (str == "Raw/Bool") { + return RAW_BOOL; + } else if (str == "Raw/Char") { + return RAW_CHAR; + } else if (str == "Raw/String") { + return RAW_STRING; + } else if (str == "Raw/Binary") { + return RAW_BINARY; + } else if (str == "Raw/Time") { + return RAW_TIME; + } else if (str == "DPVAL/Int") { + return DPVAL_INT; + } else if (str == "DPVAL/Uint") { + return DPVAL_UINT; + } else if (str == "DPVAL/Double") { + return DPVAL_DOUBLE; + } else if (str == "DPVAL/Bool") { + return DPVAL_BOOL; + } else if (str == "DPVAL/Char") { + return DPVAL_CHAR; + } else if (str == "DPVAL/String") { + return DPVAL_STRING; + } else if (str == "DPVAL/Binary") { + return DPVAL_BINARY; + } else if (str == "DPVAL/Time") { + return DPVAL_TIME; + } else if (str == "Void") { + return VOID; + } else { + throw std::domain_error("\"" + str + + "\" doesn't represent a DeliveryType."); + } +} + +template <> +inline std::string show(const DeliveryType type) +{ + switch (type) { + case RAW_INT: + return "Raw/Int"; + case RAW_UINT: + return "Raw/Uint"; + case RAW_BOOL: + return "Raw/Bool"; + case RAW_CHAR: + return "Raw/Char"; + case RAW_DOUBLE: + return "Raw/Double"; + case RAW_TIME: + return "Raw/Time"; + case RAW_STRING: + return "Raw/String"; + case RAW_BINARY: + return "Raw/Binary"; + case DPVAL_INT: + return "DPVAL/Int"; + case DPVAL_UINT: + return "DPVAL/Uint"; + case DPVAL_BOOL: + return "DPVAL/Bool"; + case DPVAL_CHAR: + return "DPVAL/Char"; + case DPVAL_DOUBLE: + return "DPVAL/Double"; + case DPVAL_TIME: + return "DPVAL/Time"; + case DPVAL_STRING: + return "DPVAL/String"; + case DPVAL_BINARY: + return "DPVAL/Binary"; + case VOID: + return "Void"; + default: + throw std::domain_error("Illegal DeliveryType."); + } +} + +/** + * Returns <tt>true</tt> if and only if the given DeliveryType is a DPVAL + * variant. + * + * @param type The DeliveryType to be checked. + * @return The result. + * @throws std::domain_error If applied to an invalid value. + */ +inline bool DPVAL_variant(const DeliveryType type) +{ + switch (type) { + case DPVAL_INT: + case DPVAL_UINT: + case DPVAL_BOOL: + case DPVAL_CHAR: + case DPVAL_DOUBLE: + case DPVAL_TIME: + case DPVAL_STRING: + case DPVAL_BINARY: + return true; + case RAW_INT: + case RAW_UINT: + case RAW_BOOL: + case RAW_CHAR: + case RAW_DOUBLE: + case RAW_TIME: + case RAW_STRING: + case RAW_BINARY: + case VOID: + return false; + default: + throw std::domain_error("Illegal DeliveryType."); + } +} + +/** + * Returns the DIM description string for a DIM service with the given + * DeliveryType. + * + * @param type The DeliveryType. + * @return The corresponding DIM service description string. + * @throws std::domain_error If applied to an invalid value. + */ +inline std::string dim_description(const DeliveryType type) +{ + + switch (type) { + case RAW_INT: + return "I:1"; + case RAW_UINT: + return "I:1"; + case RAW_BOOL: + return "I:1"; + case RAW_CHAR: + return "C:4"; + case RAW_DOUBLE: + return "D:1"; + case RAW_TIME: + return "I:2"; + case RAW_STRING: + return "C:55"; + case RAW_BINARY: + return "C:56"; + case DPVAL_INT: + return "S:2;I:1;I:1"; + case DPVAL_UINT: + return "S:2;I:1;I:1"; + case DPVAL_BOOL: + return "S:2;I:1;I:1"; + case DPVAL_CHAR: + return "S:2;I:1;C:4"; + case DPVAL_DOUBLE: + return "S:2;I:1;D:1"; + case DPVAL_TIME: + return "S:2;I:1;I:2"; + case DPVAL_STRING: + return "S:2;I:1;C:55"; + case DPVAL_BINARY: + return "S:2;I:1;C:56"; + case VOID: + default: + throw std::domain_error("Illegal DeliveryType."); + } +} + +/** + * Returns the size of a buffer required to store the binary contents of a + * DIM service of the given data type. + * + * @param type The DeliveryType. + * @return Size of the payload. + * @throws std::domain_error If applied to an invalid value. + */ +inline size_t dim_buffer_size(const DeliveryType type) +{ + switch (type) { + case RAW_INT: + case RAW_UINT: + case RAW_BOOL: + case RAW_CHAR: + return 4; + case RAW_DOUBLE: + case RAW_TIME: + return 8; + case RAW_STRING: + return 55; + case RAW_BINARY: + return 56; + case DPVAL_INT: + case DPVAL_UINT: + case DPVAL_BOOL: + case DPVAL_CHAR: + case DPVAL_DOUBLE: + case DPVAL_TIME: + case DPVAL_STRING: + case DPVAL_BINARY: + return 64; + case VOID: + return 0; + default: + throw std::domain_error("Illegal DeliveryType."); + } +} +} // namespace dcs + +} // namespace o2 + +#endif /* O2_DCS_DELIVERY_TYPE */ diff --git a/Detectors/DCS/include/DetectorsDCS/GenericFunctions.h b/Detectors/DCS/include/DetectorsDCS/GenericFunctions.h new file mode 100644 index 0000000000000..91937d33f30a3 --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/GenericFunctions.h @@ -0,0 +1,54 @@ +// 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: GenericFunctions.h + * Author: John Lång (john.larry.lang@cern.ch) + * + * Created on 9 June 2017, 17:29 + */ + +#ifndef O2_DCS_GENERIC_FUNCTIONS_H +#define O2_DCS_GENERIC_FUNCTIONS_H + +#include <string> + +namespace o2 +{ +namespace dcs +{ +/** + * This function template is used for converting ADAPRO enumerated values + * into strings in a fashion similar to the function show in the Show type + * class in Haskell. The exact implementation depends on the specialization. + * + * @param input A T value to be converted. + * @return A string representation of the given value. + * @throws std::domain_error The specialized function may throw a domain + * error if applied with an invalid input value. + */ +template <typename T> +std::string show(const T input); + +/** + * This function template is used for parsing strings as ADAPRO enumerated + * values. The exact implementation depends on the specialization. + * + * @param input A string to be interpreted as a T value. + * @return The T value corresponding with the input. + * @throws std::domain_error The specialized function may throw a domain + * error if the given string couldn't be converted into a T value. + */ +template <typename T> +T read(const std::string& input); +} // namespace dcs +} // namespace o2 + +#endif /* O2_DCS_GENERIC_FUNCTIONS_H */ diff --git a/Detectors/DCS/include/DetectorsDCS/StringUtils.h b/Detectors/DCS/include/DetectorsDCS/StringUtils.h new file mode 100644 index 0000000000000..adf0dd2aad59d --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/StringUtils.h @@ -0,0 +1,156 @@ +// 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: StringUtils.h + * Author: John Lång (john.larry.lang@cern.ch) + * + * Created on 14 July 2015, 10:37 + * + * This library contains miscellaneous functions used in this program for + * handling (C-style) strings. + */ + +#ifndef O2_DCS_STRING_UTILS_H +#define O2_DCS_STRING_UTILS_H + +#include <string> +#include <vector> +#include <list> +#include <memory> + +namespace o2 +{ +namespace dcs +{ +/** + * Returns an uniformly distributed string of exactly the given length. The + * alphabet of the string is ASCII characters between <tt>32</tt> + * (<tt>' '</tt>) and <tt>126</tt> (<tt>'~'</tt>), inclusive. + * + * @param length Length for the random string. + * @return The random string. + */ +std::string random_string(const size_t length) noexcept; + +/** + * Returns a random string of exactly the given length. The alphabet for the + * string contains upper case letters, digits and the symbols <tt>'_'</tt>, + * <tt>'/'</tt>, and <tt>'?'</tt>. Their distribution is geometric and tries + * to roughly approximate the symbol frequencies in ALICE DCS DIM service + * aliases. + * + * @param length Length for the random string. + * @return The random string. + */ +std::string random_string2(const size_t length) noexcept; + +/** + * Calculates a hash code for the given string. Up to 52 first characters of + * the string contribute to the hash code. The hash code is case + * insensitive, so for example <tt>"abc"</tt> and <tt>"ABC"</tt> will have + * colliding hash codes. + * + * @param input A string. + * @return An unsigned integer. + */ +uint64_t hash_code(const std::string& input) noexcept; + +/** + * Converts the C-style strings of the command line parameters to a more + * civilized data type. + */ +std::unique_ptr<std::vector<std::string>> convert_strings(const int argc, + char** argv) noexcept; + +/** + * Converts the given string into upper case. <em>This function will change + * the state of the given string</em>, instead of returning a copy. + * + * @param str The string to be converted into upper case. + */ +inline void to_upper_case(std::string& str) noexcept +{ + for (char& c : str) { + c = toupper(c); + } +} + +/** + * Converts the given string into lower case. <em>This function will change + * the state of the given string</em>, instead of returning a copy. + * + * @param str The string to be converted into lower case. + */ +inline void to_lower_case(std::string& str) noexcept +{ + for (char& c : str) { + c = tolower(c); + } +} + +/** + * Splits a string using the given separator. + * + * @param source The string to be splitted. + * @param separator The delimiting character. + * @return A vector containing the substrings. + */ +std::unique_ptr<std::vector<std::string>> split(const std::string& source, + const char separator) noexcept; + +/** + * Splits a string using whitespace as separator. Only the non-whitespace + * substrings will be returned. + * + * @param source The string to be splitted. + * @return A vector containing the substrings. + */ +std::unique_ptr<std::vector<std::string>> split_by_whitespace( + const std::string& source) noexcept; + +/** + * Returns a simple big endian hexadecimal presentation of the given + * segment of memory. + * + * @param start Address of a memory segment. + * @param length Length of the memory segment. + * @return A hexadecimal string representation of the segment in + * bytes. + */ +std::string to_hex_big_endian(const char* const start, size_t length) noexcept; + +/** + * Returns a simple little endian hexadecimal presentation of the given + * segment of memory. + * + * @param start Address of a memory segment. + * @param length Length of the memory segment (in chars). + * @return A hexadecimal string representation of the segment in + * bytes. + */ +std::string to_hex_little_endian(const char* const start, size_t length) noexcept; + +/** + * Prints the given list of key-value pairs. + * + * @param logger The Logger instance used for output. + * @param list_name Name of the list to be printed as a heading. + * @param parameters The list to be printed + */ + +void print_k_v_list( + const std::string& list_name, + const std::list<std::pair<std::string, std::string>>& parameters) noexcept; + +} // namespace dcs +} // namespace o2 + +#endif /* O2_DCS_STRING_UTILS_H */ diff --git a/Detectors/DCS/src/Clock.cxx b/Detectors/DCS/src/Clock.cxx new file mode 100644 index 0000000000000..e8fb9eac9e0ea --- /dev/null +++ b/Detectors/DCS/src/Clock.cxx @@ -0,0 +1,11 @@ +// 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 "DetectorsDCS/Clock.h" diff --git a/Detectors/DCS/src/DataPointCompositeObject.cxx b/Detectors/DCS/src/DataPointCompositeObject.cxx new file mode 100644 index 0000000000000..93aaa674bb2ef --- /dev/null +++ b/Detectors/DCS/src/DataPointCompositeObject.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 "DetectorsDCS/DataPointCompositeObject.h" + +using namespace o2::dcs; + +ClassImp(DataPointCompositeObject); diff --git a/Detectors/DCS/src/DataPointIdentifier.cxx b/Detectors/DCS/src/DataPointIdentifier.cxx new file mode 100644 index 0000000000000..85906ad6dd408 --- /dev/null +++ b/Detectors/DCS/src/DataPointIdentifier.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 "DetectorsDCS/DataPointIdentifier.h" + +using namespace o2::dcs; + +ClassImp(DataPointIdentifier); diff --git a/Detectors/DCS/src/DataPointValue.cxx b/Detectors/DCS/src/DataPointValue.cxx new file mode 100644 index 0000000000000..dc5874b7e3a9b --- /dev/null +++ b/Detectors/DCS/src/DataPointValue.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 "DetectorsDCS/DataPointValue.h" + +using namespace o2::dcs; + +ClassImp(DataPointValue); diff --git a/Detectors/DCS/src/DeliveryType.cxx b/Detectors/DCS/src/DeliveryType.cxx new file mode 100644 index 0000000000000..6ff195fc8fd9d --- /dev/null +++ b/Detectors/DCS/src/DeliveryType.cxx @@ -0,0 +1,11 @@ +// 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 "DetectorsDCS/DeliveryType.h" diff --git a/Detectors/DCS/src/DetectorsDCSLinkDef.h b/Detectors/DCS/src/DetectorsDCSLinkDef.h new file mode 100644 index 0000000000000..78b3c58223100 --- /dev/null +++ b/Detectors/DCS/src/DetectorsDCSLinkDef.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. + +#if defined(__CINT__) || defined(__CLING__) + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ struct o2::dcs::DataPointCompositeObject + ; +#pragma link C++ class o2::dcs::DataPointIdentifier + ; +#pragma link C++ struct o2::dcs::DataPointValue + ; + +#endif diff --git a/Detectors/DCS/src/GenericFunctions.cxx b/Detectors/DCS/src/GenericFunctions.cxx new file mode 100644 index 0000000000000..c8be0880092c4 --- /dev/null +++ b/Detectors/DCS/src/GenericFunctions.cxx @@ -0,0 +1,11 @@ +// 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 "DetectorsDCS/GenericFunctions.h" diff --git a/Detectors/DCS/src/StringUtils.cxx b/Detectors/DCS/src/StringUtils.cxx new file mode 100644 index 0000000000000..a0e96d17a5752 --- /dev/null +++ b/Detectors/DCS/src/StringUtils.cxx @@ -0,0 +1,383 @@ +// 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 <cctype> +#include <cstdint> +#include <cmath> +#include <cstdlib> +#include <string> +#include <random> +#include <vector> +#include <list> +#include <memory> +#include <fstream> +#include <regex> +#include <map> +#include <functional> +#include <utility> +#include <sstream> +#include <istream> +#include <iomanip> +#include <sstream> +#include <iterator> +#include "DetectorsDCS/StringUtils.h" + +using namespace std; + +random_device dev; +default_random_engine gen(dev()); +uniform_int_distribution<char> uniform_dist(32, 126); +geometric_distribution<char> geom_dist(0.1); + +constexpr char ALPHABET[39]{ + 'E', 'T', 'A', 'O', 'I', '_', 'N', 'S', 'H', 'R', + '/', 'D', 'L', '1', '2', 'C', 'U', 'M', 'W', '3', + '4', '5', '6', '7', '8', '9', '0', 'F', 'G', 'Y', + 'P', 'B', 'V', 'K', 'J', 'X', 'Q', 'Z', '?'}; + +/** + * The first 52 prime numbers used for calculating the hash code. Each symbol of + * the alias will be multiplied (mod 256) with a prime of the same index and + * adding the obtained number to the sum that is the hash code. + */ +constexpr uint64_t PRIMES[52]{ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, + 233, 239}; + +/** + * The modulo used in the hash function after calculating the sum. It is the + * prime number closest to 1.5 * 2^63. + */ +constexpr uint64_t MODULO(13835058055282163729ULL); + +/** + * Transforms the given character into a 8-bit unsigned code symbol. + * + * @param input + * @return + */ +uint8_t lookup(const char input) noexcept +{ + switch (input) { + case 'e': + case 'E': + return 0; + case 't': + case 'T': + return 1; + case 'a': + case 'A': + return 2; + case 'o': + case 'O': + return 3; + case 'i': + case 'I': + return 4; + case '_': + return 5; + case 'n': + case 'N': + return 6; + case 's': + case 'S': + return 7; + case 'h': + case 'H': + return 8; + case 'r': + case 'R': + return 9; + case '/': + return 10; + case 'd': + case 'D': + return 11; + case 'l': + case 'L': + return 12; + case '1': + return 13; + case '2': + return 14; + case 'c': + case 'C': + return 15; + case 'u': + case 'U': + return 16; + case 'm': + case 'M': + return 17; + case 'w': + case 'W': + return 18; + case '3': + return 19; + case '4': + return 20; + case '5': + return 21; + case '6': + return 22; + case '7': + return 23; + case '8': + return 24; + case '9': + return 25; + case '0': + return 26; + case 'f': + case 'F': + return 27; + case 'g': + case 'G': + return 28; + case 'y': + case 'Y': + return 29; + case 'p': + case 'P': + return 30; + case 'b': + case 'B': + return 31; + case 'v': + case 'V': + return 32; + case 'k': + case 'K': + return 33; + case 'j': + case 'J': + return 34; + case 'x': + case 'X': + return 35; + case 'q': + case 'Q': + return 36; + case 'z': + case 'Z': + return 37; + default: + return 38; + } +} + +/** + * An all-integer exponent function. The orgiginal algorithm was submitted as an + * answer at StackOverflow, by Elias Yarrkow. The code was obtained from + * http://stackoverflow.com/a/101613 in 14 February 2017, 11:24, and modified to + * work with the unsigned C integer types. It is well-known that these kind of + * functions usually overflow, and overflows are ignored in this case. + * + * @param base The base of the exponent function. + * @param exp The exponent. + * @return The result. + */ +uint64_t exp(uint64_t base, uint8_t exp) noexcept +{ + uint64_t result(1); + while (exp) { + if (exp & 1) { + result *= base; + } + exp >>= 1; + base *= base; + } + return result; +} + +string o2::dcs::random_string(const size_t length) noexcept +{ + string s; + s.reserve(length); + for (size_t i = 0; i < length; ++i) { + s.push_back(uniform_dist(gen)); + } + return s; +} + +string o2::dcs::random_string2(const size_t length) noexcept +{ + string s; + s.reserve(length); + for (size_t i = 0; i < length; ++i) { + s.push_back(ALPHABET[geom_dist(gen) % 39]); + } + return s; +} + +uint64_t o2::dcs::hash_code(const std::string& input) noexcept +{ + size_t result(0); + const size_t length(min(input.length(), (string::size_type)52)); + for (size_t i = 0; i < length; ++i) { + // result += exp(PRIMES[i], (uint8_t) input[i]); + result += exp(PRIMES[i], lookup(input[i])); + // result += exp(PRIMES[i], ((uint8_t) input[i]) & 0x1F); + } + return result; +} + +unique_ptr<vector<string>> o2::dcs::convert_strings(const int argc, + char** argv) noexcept +{ + vector<string>* arguments = new vector<string>(); + + for (int i = 0; i < argc; ++i) { + arguments->push_back(std::move(string(argv[i]))); + } + + return unique_ptr<vector<string>>(arguments); +} + +unique_ptr<vector<string>> o2::dcs::split(const string& source, + const char separator) noexcept +{ + stringstream ss(source); + string item; + vector<string>* substrings = new vector<string>(); + while (getline(ss, item, separator)) { + substrings->push_back(item); + } + return unique_ptr<vector<string>>(substrings); +} + +unique_ptr<vector<string>> o2::dcs::split_by_whitespace(const string& source) noexcept +{ + istringstream buffer(source); + vector<string>* ret = new vector<string>(); + + std::copy(istream_iterator<string>(buffer), + istream_iterator<string>(), + back_inserter(*ret)); + return unique_ptr<vector<string>>(ret); +} + +inline char to_alpha_numeric(const uint8_t c) noexcept +{ + switch (c) { + case 0x00: + return '0'; + case 0x01: + case 0x10: + return '1'; + case 0x02: + case 0x20: + return '2'; + case 0x03: + case 0x30: + return '3'; + case 0x04: + case 0x40: + return '4'; + case 0x05: + case 0x50: + return '5'; + case 0x06: + case 0x60: + return '6'; + case 0x07: + case 0x70: + return '7'; + case 0x08: + case 0x80: + return '8'; + case 0x09: + case 0x90: + return '9'; + case 0x0A: + case 0xA0: + return 'A'; + case 0x0B: + case 0xB0: + return 'B'; + case 0x0C: + case 0xC0: + return 'C'; + case 0x0D: + case 0xD0: + return 'D'; + case 0x0E: + case 0xE0: + return 'E'; + case 0x0F: + case 0xF0: + return 'F'; + default: + return '?'; + } +} + +string o2::dcs::to_hex_big_endian(const char* const start, const size_t length) noexcept +{ + string s; + s.reserve(length * 3); + // My machine is little endian: + size_t i = length - 1; + do { + const char next = start[i]; + s.push_back(to_alpha_numeric(next & 0xF0)); + s.push_back(to_alpha_numeric(next & 0x0F)); + s.push_back(' '); + --i; + } while (i < length); + s.pop_back(); + return s; +} + +string o2::dcs::to_hex_little_endian(const char* const start, const size_t length) noexcept +{ + string s; + s.reserve(length * 3); + // My machine is little endian: + size_t i = 0; + do { + const char next = start[i]; + s.push_back(to_alpha_numeric(next & 0xF0)); + s.push_back(to_alpha_numeric(next & 0x0F)); + s.push_back(' '); + ++i; + } while (i < length); + s.pop_back(); + return s; +} + +void o2::dcs::print_k_v_list( + const string& list_name, + const list<pair<string, string>>& parameters) noexcept +{ + stringstream ss; + ss << list_name << endl + << string(list_name.length() + 26, '-') << endl + << endl; + uint32_t key_length(0); + for (auto k_v : parameters) { + if (k_v.first.length() > key_length) { + key_length = k_v.first.length(); + } + } + key_length += 4 - (key_length % 4); + for (auto k_v : parameters) { + ss << " " << k_v.first << string(key_length - k_v.first.length(), ' ') << k_v.second << endl; + } + ss << endl + << "==========================================================" + "======================" + << endl + << endl; +} From c72106eb5786fb874f0b472dd5da48791db14666 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 18 Sep 2020 05:08:50 +0200 Subject: [PATCH 0673/1751] DPL Analysis: declare projectors static so they are reused (#4375) --- Framework/Core/include/Framework/ASoA.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index d4160f0d33a4c..9cc1e14f3f57c 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1762,7 +1762,7 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) arrow::ArrayVector v; std::array<arrow::ArrayVector, sizeof...(C)> chunks; - auto projectors = framework::expressions::createProjectors(columns, atable->schema()); + static auto projectors = framework::expressions::createProjectors(columns, atable->schema()); while (true) { auto s = reader.ReadNext(&batch); if (!s.ok()) { @@ -1783,7 +1783,7 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) for (auto i = 0u; i < sizeof...(C); ++i) { arrays.push_back(std::make_shared<arrow::ChunkedArray>(chunks[i])); } - auto new_schema = o2::soa::createSchemaFromColumns(columns); + static auto new_schema = o2::soa::createSchemaFromColumns(columns); return arrow::Table::Make(new_schema, arrays); } From 3c9e72af9deeb630f585c79ba8c78ca5de950a84 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 18 Sep 2020 07:04:54 +0200 Subject: [PATCH 0674/1751] DPL: fix wrong casing for variables (#4380) --- Framework/Core/src/WorkflowHelpers.cxx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 604565805ea0a..01f343457ab2c 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -363,27 +363,27 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext /// // First analyze all ouputs // outputtypes = isAOD*2 + isdangling*1 + 0 - auto [OutputsInputs, outputtypes] = analyzeOutputs(workflow); + auto [outputsInputs, outputtypes] = analyzeOutputs(workflow); // file sink for any AOD output extraSpecs.clear(); // select outputs of type AOD - std::vector<InputSpec> OutputsInputsAOD; + std::vector<InputSpec> outputsInputsAOD; std::vector<bool> isdangling; - for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { + for (auto ii = 0u; ii < outputsInputs.size(); ii++) { if ((outputtypes[ii] & 2) == 2) { // temporarily also request to be dangling if ((outputtypes[ii] & 1) == 1) { - OutputsInputsAOD.emplace_back(OutputsInputs[ii]); + outputsInputsAOD.emplace_back(outputsInputs[ii]); isdangling.emplace_back((outputtypes[ii] & 1) == 1); } } } - if (OutputsInputsAOD.size() > 0) { - auto fileSink = CommonDataProcessors::getGlobalAODSink(OutputsInputsAOD, + if (outputsInputsAOD.size() > 0) { + auto fileSink = CommonDataProcessors::getGlobalAODSink(outputsInputsAOD, isdangling); extraSpecs.push_back(fileSink); } @@ -393,16 +393,16 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext extraSpecs.clear(); // select dangling outputs which are not of type AOD - std::vector<InputSpec> OutputsInputsDangling; - for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { + std::vector<InputSpec> outputsInputsDangling; + for (auto ii = 0u; ii < outputsInputs.size(); ii++) { if ((outputtypes[ii] & 1) == 1 && (outputtypes[ii] & 2) == 0) - OutputsInputsDangling.emplace_back(OutputsInputs[ii]); + outputsInputsDangling.emplace_back(outputsInputs[ii]); } std::vector<InputSpec> unmatched; - if (OutputsInputsDangling.size() > 0) { - auto fileSink = CommonDataProcessors::getGlobalFileSink(OutputsInputsDangling, unmatched); - if (unmatched.size() != OutputsInputsDangling.size()) { + if (outputsInputsDangling.size() > 0) { + auto fileSink = CommonDataProcessors::getGlobalFileSink(outputsInputsDangling, unmatched); + if (unmatched.size() != outputsInputsDangling.size()) { extraSpecs.push_back(fileSink); } } From e84b79995fec08e8683e8652ff8a75116b641a2c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 18 Sep 2020 10:41:11 +0200 Subject: [PATCH 0675/1751] Improve helper for compilation profiling (#4384) --- scripts/profile-compilation | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/profile-compilation b/scripts/profile-compilation index e3624b9f084f8..b002a4a8ccd7d 100755 --- a/scripts/profile-compilation +++ b/scripts/profile-compilation @@ -1,7 +1,7 @@ #!/bin/bash COMPILE_COMMADS=$PWD/compile_commands.json -FILENAME=$PWD/$1 +FILENAME=$1 CLANG_PATH=${CLANG_PATH:-clang++} -cd `cat $COMPILE_COMMADS | jq ".[] | select(.file == \"$FILENAME\")" | jq -r '.directory'` -`cat $COMPILE_COMMADS | jq ".[] | select(.file == \"$FILENAME\")" | jq ".command |= (sub(\"^.*/c[+][+]\";\"$CLANG_PATH -ftime-trace\"))" | jq -r '.command'` +cd `cat $COMPILE_COMMADS | jq ".[] | select(.file|test(\".*$FILENAME\"))" | jq -r '.directory'` +`cat $COMPILE_COMMADS | jq ".[] | select(.file|test(\".*$FILENAME\"))" | jq ".command |= (sub(\"^.*/c[+][+]\";\"$CLANG_PATH -ftime-trace\"))" | jq -r '.command'` From e3fa78b44b0d60d20e5f07dccde4fa102de493bf Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 18 Sep 2020 10:28:02 +0200 Subject: [PATCH 0676/1751] Rewrite aod data model graph creator --- Analysis/DataModel/src/dumpDataModel.cxx | 290 +++++++++++++++-------- 1 file changed, 188 insertions(+), 102 deletions(-) diff --git a/Analysis/DataModel/src/dumpDataModel.cxx b/Analysis/DataModel/src/dumpDataModel.cxx index 70652b71f9d76..4683a45e1f8a2 100644 --- a/Analysis/DataModel/src/dumpDataModel.cxx +++ b/Analysis/DataModel/src/dumpDataModel.cxx @@ -14,6 +14,7 @@ #include "Analysis/Centrality.h" #include "Analysis/TrackSelectionTables.h" #include "Analysis/Jet.h" +#include "Analysis/StrangenessTables.h" #include <fmt/printf.h> #include <map> @@ -22,6 +23,108 @@ using namespace o2::aod; using namespace o2::soa; static int count = 0; +static int width = 10; +static int height = 10; + +void inline graphSize() +{ + fmt::printf( + R"( +size="%d,%d"; +)", + width, height); +} + +struct Style { + const char* color; + const char* background; + const char* fontcolor; + const char* headerfontcolor; + const char* headerbgcolor; + const char* methodcolor; + const char* methodbgcolor; + const char* indexcolor; + const char* indexbgcolor; +}; + +static Style styles[] = { + {"black", "gray80", "black", "black", "gray70", "black", "gray60", "black", "gray50"}, + {"/reds9/2", "/reds9/4", "white", "white", "/reds9/7", "black", "/reds9/6", "/reds9/1", "/reds9/5"}, + {"/greens9/2", "/greens9/4", "white", "white", "/greens9/7", "black", "/greens9/6", "/greens9/1", "/greens9/5"}, + {"/blues9/2", "/blues9/4", "white", "white", "/blues9/7", "black", "/blues9/6", "/blues9/1", "/blues9/5"}, +}; + +Style const& getDefaultStyle() +{ + return styles[0]; +} + +enum StyleType : int { + DEFAULT = 0, + RED = 1, + GREEN = 2, + BLUE = 3, +}; + +static std::vector<std::pair<std::string, StyleType>> tableStyles = { + {"HfTrackIndexProng", StyleType::GREEN}, + {"pidResp", StyleType::GREEN}, + {"Mults", StyleType::GREEN}, + {"Cents", StyleType::GREEN}, + {"Jet", StyleType::BLUE}, + {"Mc", StyleType::RED}, + {"V0Data", StyleType::GREEN}, + {"CascData", StyleType::GREEN}}; + +template <typename T> +Style getStyleFor() +{ + auto label = MetadataTrait<T>::metadata::tableLabel(); + auto entry = std::find_if(tableStyles.begin(), tableStyles.end(), [&](auto&& x) { if (std::string(label).find(x.first) != std::string::npos) return true; return false; }); + if (entry != tableStyles.end()) { + auto value = *entry; + return styles[value.second]; + } + return styles[StyleType::DEFAULT]; +} + +void inline nodeEmpty() +{ + fmt::printf( + R"(node[shape=none,height=0,width=0,label=""])"); +} + +void inline nodeNormal() +{ + fmt::printf( + R"(node[shape=plain,style=filled,fillcolor=gray95])"); +} + +void inline graphHeader(char const* type, char const* name) +{ + fmt::printf(R"(%s %s { +edge[dir=back, arrowtail=empty] +)", + type, name); + nodeNormal(); +} + +void inline graphFooter() +{ + fmt::printf("}\n"); +} + +template <typename T> +void displayEntity(); + +template <typename... Ts> +void displayOriginals(pack<Ts...>) +{ + graphHeader("subgraph", fmt::format("cluster_{}", count++).c_str()); + fmt::printf("label = %s;\n", MetadataTrait<pack_element_t<1, pack<Ts...>>>::metadata::tableLabel()); + (..., displayEntity<Ts>()); + graphFooter(); +} template <typename C> void printColumn(char const* fg, char const* bg) @@ -39,6 +142,20 @@ void printIndexColumn(char const* fg, char const* bg) } } +template <typename... C> +void displayColumns(pack<C...>, const char* fg, const char* bg) +{ + (printColumn<C>(fg, bg), ...); + fmt::printf("%s", "\n"); +} + +template <typename... C> +void displayIndexColumns(pack<C...>, char const* fg, char const* bg) +{ + (printIndexColumn<C>(fg, bg), ...); + fmt::printf("%s", "\n"); +} + template <typename C, typename T> void printIndex() { @@ -47,27 +164,13 @@ void printIndex() auto b = MetadataTrait<T>::metadata::tableLabel(); fmt::printf("%s -> %s []\n", a, b); } else { - using main_original = pack_element_t<0, typename C::binding_t::originals>; + using main_original = pack_element_t<1, typename C::binding_t::originals>; auto a = MetadataTrait<main_original>::metadata::tableLabel(); auto b = MetadataTrait<T>::metadata::tableLabel(); fmt::printf("%s -> %s []\n", a, b); } } -template <typename... C> -void dumpColumns(pack<C...>, const char* fg, const char* bg) -{ - (printColumn<C>(fg, bg), ...); - fmt::printf("%s", "\n"); -} - -template <typename... C> -void dumpIndexColumns(pack<C...>, char const* fg, char const* bg) -{ - (printIndexColumn<C>(fg, bg), ...); - fmt::printf("%s", "\n"); -} - template <typename T, typename... C> void dumpIndex(pack<C...>) { @@ -75,112 +178,95 @@ void dumpIndex(pack<C...>) fmt::printf("%s", "\n"); } -struct Style { - const char* color; - const char* background; - const char* fontcolor; - const char* headerfontcolor; - const char* headerbgcolor; - const char* methodcolor; - const char* methodbgcolor; - const char* indexcolor; - const char* indexbgcolor; -}; - -static Style styles[] = { - {"black", "gray80", "black", "black", "gray70", "black", "gray60", "black", "gray50"}, - {"/reds9/2", "/reds9/4", "white", "white", "/reds9/7", "black", "/reds9/6", "/reds9/1", "/reds9/5"}, - {"/greens9/2", "/greens9/4", "white", "white", "/greens9/7", "black", "/greens9/6", "/greens9/1", "/greens9/5"}, - {"/blues9/2", "/blues9/4", "white", "white", "/blues9/7", "black", "/blues9/6", "/blues9/1", "/blues9/5"}, -}; - -Style const& getDefaultStyle() -{ - return styles[0]; -} - -enum struct StyleType : int { - DEFAULT = 0, - RED = 1, - GREEN = 2, - BLUE = 3, -}; - template <typename T> -void dumpTable(bool index = true, enum StyleType styleId = StyleType::DEFAULT) +void displayTable() { - auto style = styles[static_cast<int>(styleId)]; - // nodes.push_back({MetadataTrait<T>::metadata::label(), nodeCount}); + auto style = getStyleFor<T>(); auto label = MetadataTrait<T>::metadata::tableLabel(); fmt::printf(R"(%s[color="%s" cellpadding="0" fillcolor="%s" fontcolor="%s" label = < <TABLE cellpadding='2' cellspacing='0' cellborder='0' ><TH cellpadding='0' bgcolor="black"><TD bgcolor="%s"><font color="%s">%s</font></TD></TH>)", label, style.color, style.background, style.fontcolor, style.headerbgcolor, style.headerfontcolor, label); if (pack_size(typename T::iterator::persistent_columns_t{}) - - pack_size(typename T::iterator::external_index_columns_t{})) { - dumpColumns(typename T::iterator::persistent_columns_t{}, style.color, style.background); + pack_size(typename T::iterator::external_index_columns_t{}) > + 0) { + displayColumns(typename T::iterator::persistent_columns_t{}, style.color, style.background); fmt::printf("%s", "HR"); } if (pack_size(typename T::iterator::dynamic_columns_t{})) { - dumpColumns(typename T::iterator::dynamic_columns_t{}, style.methodcolor, style.methodbgcolor); + displayColumns(typename T::iterator::dynamic_columns_t{}, style.methodcolor, style.methodbgcolor); fmt::printf("%s", "HR"); } - dumpIndexColumns(typename T::iterator::external_index_columns_t{}, style.indexcolor, style.indexbgcolor); + displayIndexColumns(typename T::iterator::external_index_columns_t{}, style.indexcolor, style.indexbgcolor); fmt::printf("%s", "</TABLE>\n>]\n"); - if (index) - dumpIndex<T>(typename T::iterator::external_index_columns_t{}); + dumpIndex<T>(typename T::iterator::external_index_columns_t{}); } -template <typename... Ts> -void dumpCluster() +template <typename T> +void displayEntity() { - fmt::printf(R"(subgraph cluster_%d { -node[shape=plain,style=filled,fillcolor=gray95] -edge[dir=back, arrowtail=empty] -)", - count++); - (dumpTable<Ts>(false), ...); - fmt::printf("%s", "}\n"); - (dumpIndex<Ts>(typename Ts::iterator::external_index_columns_t{}), ...); + if constexpr (is_soa_join_t<T>::value) { + displayOriginals(typename T::originals{}); + } else { + displayTable<T>(); + } +} + +template <typename... T> +void displayEntities() +{ + graphHeader("subgraph", fmt::format("cluster_{}", count++).c_str()); + (..., displayEntity<T>()); + graphFooter(); } 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] + graphHeader("digraph", "hierarchy"); + graphSize(); + fmt::printf(R"(compound = true; )"); - /// FIXME: topology should account for predefined Joins - dumpCluster<StoredTracks, TracksExtension, StoredTracksCov, TracksCovExtension, TracksExtra, TracksExtended, TrackSelection>(); - dumpTable<Collisions>(); - dumpTable<Calos>(); - dumpTable<CaloTriggers>(); - dumpCluster<StoredMuons, MuonsExtension>(); - dumpTable<MuonClusters>(); - dumpTable<Zdcs>(); - dumpTable<Run2V0s>(); - dumpTable<StoredV0s>(); - dumpTable<StoredCascades>(); - dumpTable<BCs>(); - dumpTable<FT0s>(); - dumpTable<FV0s>(); - dumpTable<FDDs>(); - dumpTable<Timestamps>(); - dumpTable<HfTrackIndexProng2>(true, StyleType::GREEN); - dumpTable<HfTrackIndexProng3>(true, StyleType::GREEN); - - dumpTable<pidRespTOF>(true, StyleType::GREEN); - dumpTable<pidRespTPC>(true, StyleType::GREEN); - dumpTable<Mults>(true, StyleType::GREEN); - dumpTable<Cents>(true, StyleType::GREEN); - - dumpTable<Jets>(true, StyleType::BLUE); - dumpTable<JetConstituents>(true, StyleType::BLUE); - dumpTable<UnassignedTracks>(); - dumpTable<McCollisions>(true, StyleType::RED); - dumpTable<McTrackLabels>(true, StyleType::RED); - dumpTable<McCaloLabels>(true, StyleType::RED); - dumpTable<McCollisionLabels>(true, StyleType::RED); - dumpTable<McParticles>(true, StyleType::RED); - fmt::printf("%s\n", R"(})"); + + displayEntity<BCs>(); + /// rank trick to avoid BCs moving + nodeEmpty(); + fmt::printf(R"({rank = same; BCs -> root[style=invis];};)"); + nodeNormal(); + + displayEntity<Zdcs>(); + displayEntity<FT0s>(); + displayEntity<FV0s>(); + displayEntity<FDDs>(); + + displayEntities<Collisions, Cents, Mults, Timestamps>(); + displayEntity<McCollisions>(); + displayEntity<McCollisionLabels>(); + + displayEntity<Calos>(); + displayEntity<CaloTriggers>(); + displayEntity<McCaloLabels>(); + + displayEntity<Run2V0s>(); + + displayEntities<Tracks, TracksCov, TracksExtra, TracksExtended, TrackSelection, pidRespTOF, pidRespTPC>(); + displayEntity<UnassignedTracks>(); + + displayEntity<McParticles>(); + displayEntity<McTrackLabels>(); + + displayEntity<HfTrackIndexProng2>(); + displayEntity<HfTrackIndexProng3>(); + + displayEntity<Jets>(); + displayEntity<JetConstituents>(); + + displayEntities<V0s, V0DataFull>(); + displayEntity<V0FinderData>(); + + displayEntities<Cascades, CascDataFull>(); + + displayEntity<Muons>(); + displayEntity<MuonClusters>(); + + graphFooter(); + return 0; } From b122c0f4fb4e8b1e660de0b56d025b6ee51c9a95 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 18 Sep 2020 10:29:24 +0200 Subject: [PATCH 0677/1751] rename aod data model graph creator source file --- Analysis/DataModel/CMakeLists.txt | 2 +- .../DataModel/src/{dumpDataModel.cxx => aodDataModelGraph.cxx} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Analysis/DataModel/src/{dumpDataModel.cxx => aodDataModelGraph.cxx} (100%) diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index df43c7280c5d8..6eb08e7a59853 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -45,7 +45,7 @@ install(FILES include/PID) o2_add_executable(dump-aod-data-model - SOURCES src/dumpDataModel.cxx + SOURCES src/aodDataModelGraph.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel ) diff --git a/Analysis/DataModel/src/dumpDataModel.cxx b/Analysis/DataModel/src/aodDataModelGraph.cxx similarity index 100% rename from Analysis/DataModel/src/dumpDataModel.cxx rename to Analysis/DataModel/src/aodDataModelGraph.cxx From 6826ec1d66984e39c3e15848c943f4d865379260 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 18 Sep 2020 10:29:55 +0200 Subject: [PATCH 0678/1751] rename aod data model graph creator executable --- Analysis/DataModel/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index 6eb08e7a59853..4df9311ced9de 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -44,7 +44,7 @@ install(FILES DESTINATION include/PID) -o2_add_executable(dump-aod-data-model +o2_add_executable(aod-data-model-graph SOURCES src/aodDataModelGraph.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel ) From 5b1f9fa6b78f9ee521794302155b0af7bb2b51a4 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 18 Sep 2020 14:10:53 +0200 Subject: [PATCH 0679/1751] DPL: introduce dangling-outputs-policy (#4381) Default / "file": old behaviour. Messages matching --keep rule will be dumped to a file. "fairmq": a new "output proxy" device is created and all the dangling outputs are bound to, which will then push them to a fairmq channel. --- .../include/Framework/CommonDataProcessors.h | 13 ++++++---- .../include/Framework/runDataProcessing.h | 2 ++ Framework/Core/src/CommonDataProcessors.cxx | 26 +++++++++++++++++++ Framework/Core/src/WorkflowHelpers.cxx | 5 +++- Framework/Core/test/test_WorkflowHelpers.cxx | 1 + 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Framework/Core/include/Framework/CommonDataProcessors.h b/Framework/Core/include/Framework/CommonDataProcessors.h index 19794032575a9..0c8244c572cd0 100644 --- a/Framework/Core/include/Framework/CommonDataProcessors.h +++ b/Framework/Core/include/Framework/CommonDataProcessors.h @@ -17,9 +17,7 @@ #include <vector> -namespace o2 -{ -namespace framework +namespace o2::framework { using outputTasks = std::vector<std::pair<uint32_t, std::string>>; using outputObjects = std::vector<std::pair<uint32_t, std::vector<std::string>>>; @@ -38,6 +36,12 @@ struct CommonDataProcessors { /// not going to be used by the returned DataProcessorSpec. static DataProcessorSpec getGlobalFileSink(std::vector<InputSpec> const& danglingInputs, std::vector<InputSpec>& unmatched); + /// Given the list of @a danglingInputs @return a DataProcessor which + /// exposes them through a FairMQ channel. + /// @fixme: for now we only support shmem and ipc + /// @fixme: for now only the dangling inputs are forwarded. + static DataProcessorSpec getGlobalFairMQSink(std::vector<InputSpec> const& danglingInputs); + /// writes inputs of kind AOD to file static DataProcessorSpec getGlobalAODSink(std::vector<InputSpec> const& OutputInputs, std::vector<bool> const& isdangling); @@ -46,7 +50,6 @@ struct CommonDataProcessors { static DataProcessorSpec getDummySink(std::vector<InputSpec> const& danglingInputs); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif // o2_framework_CommonDataProcessors_H_INCLUDED diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 3bed257a41fe4..c31c061354f16 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -126,6 +126,8 @@ int main(int argc, char** argv) UserCustomizationsHelper::userDefinedCustomization(workflowOptions, 0); workflowOptions.push_back(ConfigParamSpec{"readers", VariantType::Int64, 1ll, {"number of parallel readers to use"}}); workflowOptions.push_back(ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}); + workflowOptions.push_back(ConfigParamSpec{"dangling-outputs-policy", VariantType::String, "file", {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}); + std::vector<ChannelConfigurationPolicy> channelPolicies; UserCustomizationsHelper::userDefinedCustomization(channelPolicies, 0); auto defaultChannelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 9a6bc85c2bbb6..247876809185e 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -29,6 +29,8 @@ #include "Framework/OutputObjHeader.h" #include "Framework/TableTreeHelpers.h" #include "Framework/StringHelpers.h" +#include "Framework/ChannelSpec.h" +#include "Framework/ExternalFairMQDeviceProxy.h" #include "TFile.h" #include "TTree.h" @@ -574,6 +576,30 @@ DataProcessorSpec return spec; } +DataProcessorSpec CommonDataProcessors::getGlobalFairMQSink(std::vector<InputSpec> const& danglingOutputInputs) +{ + + // we build the default channel configuration from the binding of the first input + // in order to have more than one we would need to possibility to have support for + // vectored options + // use the OutputChannelSpec as a tool to create the default configuration for the out-of-band channel + OutputChannelSpec externalChannelSpec; + externalChannelSpec.name = "output_0_0"; + externalChannelSpec.type = ChannelType::Push; + externalChannelSpec.method = ChannelMethod::Bind; + externalChannelSpec.hostname = "localhost"; + externalChannelSpec.port = 0; + externalChannelSpec.listeners = 0; + // in principle, protocol and transport are two different things but fur simplicity + // we use ipc when shared memory is selected and the normal tcp url whith zeromq, + // this is for building the default configuration which can be simply changed from the + // command line + externalChannelSpec.protocol = ChannelProtocol::IPC; + std::string defaultChannelConfig = formatExternalChannelConfiguration(externalChannelSpec); + // at some point the formatting tool might add the transport as well so we have to check + return specifyFairMQDeviceOutputProxy("internal-dpl-output-proxy", danglingOutputInputs, defaultChannelConfig.c_str()); +} + DataProcessorSpec CommonDataProcessors::getDummySink(std::vector<InputSpec> const& danglingOutputInputs) { return DataProcessorSpec{ diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 01f343457ab2c..0678ce75e246c 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -400,11 +400,14 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } std::vector<InputSpec> unmatched; - if (outputsInputsDangling.size() > 0) { + if (outputsInputsDangling.size() > 0 && ctx.options().get<std::string>("dangling-outputs-policy") == "file") { auto fileSink = CommonDataProcessors::getGlobalFileSink(outputsInputsDangling, unmatched); if (unmatched.size() != outputsInputsDangling.size()) { extraSpecs.push_back(fileSink); } + } else if (outputsInputsDangling.size() > 0 && ctx.options().get<std::string>("dangling-outputs-policy") == "fairmq") { + auto fairMQSink = CommonDataProcessors::getGlobalFairMQSink(outputsInputsDangling); + extraSpecs.push_back(fairMQSink); } if (unmatched.size() > 0) { extraSpecs.push_back(CommonDataProcessors::getDummySink(unmatched)); diff --git a/Framework/Core/test/test_WorkflowHelpers.cxx b/Framework/Core/test/test_WorkflowHelpers.cxx index 0bc40a06da78f..27b52cd1667f4 100644 --- a/Framework/Core/test/test_WorkflowHelpers.cxx +++ b/Framework/Core/test/test_WorkflowHelpers.cxx @@ -30,6 +30,7 @@ std::unique_ptr<ConfigContext> makeEmptyConfigContext() // either owns or shares ownership of the registry. std::vector<std::unique_ptr<ParamRetriever>> retrievers; static std::vector<ConfigParamSpec> specs; + specs.push_back(ConfigParamSpec{"dangling-outputs-policy", VariantType::String, "file", {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}); auto store = std::make_unique<ConfigParamStore>(specs, std::move(retrievers)); store->preload(); store->activate(); From a10ae932260458ff5b6ecb0dff61850a2be3688b Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 17 Sep 2020 20:31:56 +0200 Subject: [PATCH 0680/1751] rAns fix: use prefix ++ rather than postfix --- Utilities/rANS/include/rANS/FrequencyTable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/rANS/include/rANS/FrequencyTable.h b/Utilities/rANS/include/rANS/FrequencyTable.h index a3c74072b9550..789a3ab599919 100644 --- a/Utilities/rANS/include/rANS/FrequencyTable.h +++ b/Utilities/rANS/include/rANS/FrequencyTable.h @@ -120,7 +120,7 @@ void FrequencyTable::addSamples(Source_IT begin, Source_IT end, value_t min, val resizeFrequencyTable(min, max); } - for (auto it = begin; it != end; it++) { + for (auto it = begin; it != end; ++it) { assert((*it - mMin) < mFrequencyTable.size()); mFrequencyTable[*it - mMin]++; } From 315179550f8440cdffe2fe1a1b74e8768c8e2ac9 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 17 Sep 2020 20:34:19 +0200 Subject: [PATCH 0681/1751] EncodedBlocks supports encode(.. with any iterator rather than pointer only --- .../EncodedBlocks.h | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index aec0469bf148e..6f8141cb95edc 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -380,9 +380,8 @@ class EncodedBlocks } /// encode vector src to bloc at provided slot - template <typename S, typename VB> - void encode(const S* const srcBegin, const S* const srcEnd, int slot, uint8_t probabilityBits, Metadata::OptStore opt, VB* buffer = nullptr, - const void* encoderExt = nullptr); + template <typename S_IT, typename VB> + void encode(const S_IT srcBegin, const S_IT srcEnd, int slot, uint8_t probabilityBits, Metadata::OptStore opt, VB* buffer = nullptr, const void* encoderExt = nullptr); /// decode block at provided slot to destination vector (will be resized as needed) template <typename VD> @@ -725,21 +724,21 @@ void EncodedBlocks<H, N, W>::decode(D* dest, // destination ///_____________________________________________________________________________ template <typename H, int N, typename W> -template <typename S, typename VB> -void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source message - const S* const srcEnd, // end of source message +template <typename S_IT, typename VB> +void EncodedBlocks<H, N, W>::encode(const S_IT srcBegin, // iterator begin of source message + const S_IT srcEnd, // iterator end of source message int slot, // slot in encoded data to fill uint8_t probabilityBits, // encoding into Metadata::OptStore opt, // option for data compression VB* buffer, // optional buffer (vector) providing memory for encoded blocks const void* encoderExt) // optional external encoder - { // fill a new block assert(slot == mRegistry.nFilledBlocks); mRegistry.nFilledBlocks++; - using stream_t = typename o2::rans::Encoder64<S>::stream_t; - + using STYP = typename std::iterator_traits<S_IT>::value_type; + using stream_t = typename o2::rans::Encoder64<STYP>::stream_t; + ; const size_t messageLength = std::distance(srcBegin, srcEnd); // cover three cases: // * empty source message: no entropy coding @@ -776,29 +775,29 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source // case 3: message where entropy coding should be applied if (opt == Metadata::OptStore::EENCODE) { // build symbol statistics - const o2::rans::LiteralEncoder64<S>* encoder = reinterpret_cast<const o2::rans::LiteralEncoder64<S>*>(encoderExt); - std::unique_ptr<o2::rans::LiteralEncoder64<S>> encoderLoc; + const o2::rans::LiteralEncoder64<STYP>* encoder = reinterpret_cast<const o2::rans::LiteralEncoder64<STYP>*>(encoderExt); + std::unique_ptr<o2::rans::LiteralEncoder64<STYP>> encoderLoc; std::unique_ptr<o2::rans::FrequencyTable> frequencies = nullptr; int dictSize = 0; if (!encoder) { // no external encoder provide, create one on spot frequencies = std::make_unique<o2::rans::FrequencyTable>(); frequencies->addSamples(srcBegin, srcEnd); - encoderLoc = std::make_unique<o2::rans::LiteralEncoder64<S>>(*frequencies, probabilityBits); + encoderLoc = std::make_unique<o2::rans::LiteralEncoder64<STYP>>(*frequencies, probabilityBits); encoder = encoderLoc.get(); dictSize = frequencies->size(); } // estimate size of encode buffer - int dataSize = rans::calculateMaxBufferSize(messageLength, encoder->getAlphabetRangeBits(), sizeof(S)); // size in bytes + int dataSize = rans::calculateMaxBufferSize(messageLength, encoder->getAlphabetRangeBits(), sizeof(STYP)); // size in bytes // preliminary expansion of storage based on dict size + estimated size of encode buffer - dataSize = dataSize / sizeof(W) + (sizeof(S) < sizeof(W)); // size in words of output stream + dataSize = dataSize / sizeof(W) + (sizeof(STYP) < sizeof(W)); // size in words of output stream expandStorage(dictSize + dataSize); //store dictionary first if (dictSize) { bl->storeDict(dictSize, frequencies->data()); } // vector of incompressible literal symbols - std::vector<S> literals; + std::vector<STYP> literals; // directly encode source message into block buffer. const auto encodedMessageEnd = encoder->process(bl->getCreateData(), bl->getCreateData() + dataSize, srcBegin, srcEnd, literals); dataSize = encodedMessageEnd - bl->getData(); @@ -809,7 +808,7 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source int literalSize = 0; if (literals.size()) { - literalSize = (literals.size() * sizeof(S)) / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); + literalSize = (literals.size() * sizeof(STYP)) / sizeof(stream_t) + (sizeof(STYP) < sizeof(stream_t)); expandStorage(literalSize); bl->storeLiterals(literalSize, reinterpret_cast<const stream_t*>(literals.data())); } @@ -817,12 +816,14 @@ void EncodedBlocks<H, N, W>::encode(const S* const srcBegin, // begin of source encoder->getMinSymbol(), encoder->getMaxSymbol(), dictSize, dataSize, literalSize}; } else { // store original data w/o EEncoding - const size_t szb = messageLength * sizeof(S); - const int dataSize = szb / sizeof(stream_t) + (sizeof(S) < sizeof(stream_t)); + const size_t szb = messageLength * sizeof(STYP); + const int dataSize = szb / sizeof(stream_t) + (sizeof(STYP) < sizeof(stream_t)); // no dictionary needed expandStorage(dataSize); *meta = Metadata{messageLength, 0, sizeof(uint64_t), sizeof(stream_t), probabilityBits, opt, 0, 0, 0, dataSize, 0}; - bl->storeData(meta->nDataWords, reinterpret_cast<const W*>(srcBegin)); + // provided iterator is not necessarily pointer, need to use intermediate vector!!! + std::vector<STYP> vtmp(srcBegin, srcEnd); + bl->storeData(meta->nDataWords, reinterpret_cast<const W*>(vtmp.data())); } // resize block if necessary } From 02b2924463d80c58b3284d5d6564e018353206ea Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 17 Sep 2020 20:42:39 +0200 Subject: [PATCH 0682/1751] Definition of MID CTF --- DataFormats/Detectors/MUON/MID/CMakeLists.txt | 11 +++- .../MUON/MID/include/DataFormatsMID/CTF.h | 56 +++++++++++++++++++ DataFormats/Detectors/MUON/MID/src/CTF.cxx | 15 +++++ .../MUON/MID/src/DataFormatsMIDLinkDef.h | 3 + 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 DataFormats/Detectors/MUON/MID/include/DataFormatsMID/CTF.h create mode 100644 DataFormats/Detectors/MUON/MID/src/CTF.cxx diff --git a/DataFormats/Detectors/MUON/MID/CMakeLists.txt b/DataFormats/Detectors/MUON/MID/CMakeLists.txt index e94061f33c1b0..e4379336070f1 100644 --- a/DataFormats/Detectors/MUON/MID/CMakeLists.txt +++ b/DataFormats/Detectors/MUON/MID/CMakeLists.txt @@ -9,8 +9,12 @@ # submit itself to any jurisdiction. o2_add_library(DataFormatsMID - SOURCES src/ColumnData.cxx src/Track.cxx - PUBLIC_LINK_LIBRARIES Boost::serialization O2::MathUtils + SOURCES src/ColumnData.cxx + src/Track.cxx + src/CTF.cxx + PUBLIC_LINK_LIBRARIES Boost::serialization O2::MathUtils + O2::CommonDataFormat + O2::DetectorsCommonDataFormats O2::ReconstructionDataFormats) o2_target_root_dictionary(DataFormatsMID @@ -18,4 +22,5 @@ o2_target_root_dictionary(DataFormatsMID include/DataFormatsMID/Cluster3D.h include/DataFormatsMID/ColumnData.h include/DataFormatsMID/ROFRecord.h - include/DataFormatsMID/Track.h) + include/DataFormatsMID/Track.h + include/DataFormatsMID/CTF.h) diff --git a/DataFormats/Detectors/MUON/MID/include/DataFormatsMID/CTF.h b/DataFormats/Detectors/MUON/MID/include/DataFormatsMID/CTF.h new file mode 100644 index 0000000000000..ed7d4b78ed539 --- /dev/null +++ b/DataFormats/Detectors/MUON/MID/include/DataFormatsMID/CTF.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 CTF.h +/// \author ruben.shahoyan@cern.ch +/// \brief Definitions for MID CTF data + +#ifndef O2_MID_CTF_H +#define O2_MID_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" +#include "DataFormatsMID/ROFRecord.h" +#include "DataFormatsMID/ColumnData.h" + +namespace o2 +{ +namespace mid +{ + +/// Header for a single CTF +struct CTFHeader { + uint32_t nROFs = 0; /// number of ROFrames in TF + uint32_t nColumns = 0; /// number of referred columns in TF + uint32_t firstOrbit = 0; /// 1st orbit of TF + uint16_t firstBC = 0; /// 1st BC of TF + + ClassDefNV(CTFHeader, 1); +}; + +/// wrapper for the Entropy-encoded clusters of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 7, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { BLC_bcIncROF, + BLC_orbitIncROF, + BLC_entriesROF, + BLC_evtypeROF, + BLC_pattern, + BLC_deId, + BLC_colId }; + ClassDefNV(CTF, 1); +}; + +} // namespace mid +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/MUON/MID/src/CTF.cxx b/DataFormats/Detectors/MUON/MID/src/CTF.cxx new file mode 100644 index 0000000000000..9e3bdccc1f992 --- /dev/null +++ b/DataFormats/Detectors/MUON/MID/src/CTF.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 <stdexcept> +#include <cstring> +#include "DataFormatsMID/CTF.h" + +using namespace o2::mid; diff --git a/DataFormats/Detectors/MUON/MID/src/DataFormatsMIDLinkDef.h b/DataFormats/Detectors/MUON/MID/src/DataFormatsMIDLinkDef.h index 14add9a4d87b2..a4986e7abc4c8 100644 --- a/DataFormats/Detectors/MUON/MID/src/DataFormatsMIDLinkDef.h +++ b/DataFormats/Detectors/MUON/MID/src/DataFormatsMIDLinkDef.h @@ -22,4 +22,7 @@ #pragma link C++ class std::vector < o2::mid::ROFRecord > +; #pragma link C++ struct o2::mid::Track + ; +#pragma link C++ struct o2::mid::CTFHeader + ; +#pragma link C++ struct o2::mid::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::mid::CTFHeader, 7, uint32_t> + ; #endif From c5e4a699761195940b669498092cc238749c0c72 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 17 Sep 2020 20:45:24 +0200 Subject: [PATCH 0683/1751] MID CTFcoder + encoder/decocer specs --- Detectors/MUON/MID/CMakeLists.txt | 1 + Detectors/MUON/MID/CTF/CMakeLists.txt | 19 ++ Detectors/MUON/MID/CTF/README.md | 7 + .../MUON/MID/CTF/include/MIDCTF/CTFCoder.h | 153 ++++++++++++++ .../MUON/MID/CTF/include/MIDCTF/CTFHelper.h | 196 ++++++++++++++++++ Detectors/MUON/MID/CTF/src/CTFCoder.cxx | 76 +++++++ Detectors/MUON/MID/CTF/src/CTFHelper.cxx | 15 ++ Detectors/MUON/MID/README.md | 1 + Detectors/MUON/MID/Workflow/CMakeLists.txt | 14 ++ Detectors/MUON/MID/Workflow/README.md | 13 ++ .../include/MIDWorkflow/EntropyDecoderSpec.h | 47 +++++ .../include/MIDWorkflow/EntropyEncoderSpec.h | 48 +++++ .../include/MIDWorkflow/RecoWorkflow.h | 2 +- .../MID/Workflow/src/EntropyDecoderSpec.cxx | 79 +++++++ .../MID/Workflow/src/EntropyEncoderSpec.cxx | 81 ++++++++ .../MUON/MID/Workflow/src/RecoWorkflow.cxx | 8 +- .../Workflow/src/entropy-encoder-workflow.cxx | 39 ++++ .../src/mid-entropy-encoder-workflow.cxx | 45 ++++ .../MID/Workflow/src/mid-reco-workflow.cxx | 8 +- 19 files changed, 846 insertions(+), 6 deletions(-) create mode 100644 Detectors/MUON/MID/CTF/CMakeLists.txt create mode 100644 Detectors/MUON/MID/CTF/README.md create mode 100644 Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h create mode 100644 Detectors/MUON/MID/CTF/include/MIDCTF/CTFHelper.h create mode 100644 Detectors/MUON/MID/CTF/src/CTFCoder.cxx create mode 100644 Detectors/MUON/MID/CTF/src/CTFHelper.cxx create mode 100644 Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyDecoderSpec.h create mode 100644 Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyEncoderSpec.h create mode 100644 Detectors/MUON/MID/Workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/MUON/MID/Workflow/src/EntropyEncoderSpec.cxx create mode 100644 Detectors/MUON/MID/Workflow/src/entropy-encoder-workflow.cxx create mode 100644 Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx diff --git a/Detectors/MUON/MID/CMakeLists.txt b/Detectors/MUON/MID/CMakeLists.txt index f36641cb8592d..f24f88c11354c 100644 --- a/Detectors/MUON/MID/CMakeLists.txt +++ b/Detectors/MUON/MID/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory(Base) add_subdirectory(Clustering) add_subdirectory(QC) add_subdirectory(Raw) +add_subdirectory(CTF) add_subdirectory(Simulation) add_subdirectory(TestingSimTools) add_subdirectory(Tracking) diff --git a/Detectors/MUON/MID/CTF/CMakeLists.txt b/Detectors/MUON/MID/CTF/CMakeLists.txt new file mode 100644 index 0000000000000..2f0fc3b383a68 --- /dev/null +++ b/Detectors/MUON/MID/CTF/CMakeLists.txt @@ -0,0 +1,19 @@ +# 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_library(MIDCTF + SOURCES src/CTFCoder.cxx src/CTFHelper.cxx + PUBLIC_LINK_LIBRARIES O2::DataFormatsMID + O2::DetectorsBase + O2::CommonDataFormat + O2::DetectorsCommonDataFormats + O2::rANS + ms_gsl::ms_gsl) + diff --git a/Detectors/MUON/MID/CTF/README.md b/Detectors/MUON/MID/CTF/README.md new file mode 100644 index 0000000000000..675a20501ac1b --- /dev/null +++ b/Detectors/MUON/MID/CTF/README.md @@ -0,0 +1,7 @@ +<!-- doxy +\page refMUONMIDCTF MID CTF encoding library +/doxy --> + +# MID CTF +This directory contains the classes to handle entropy encoding of MID +ROFRecord and ColumnData data. diff --git a/Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h b/Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h new file mode 100644 index 0000000000000..ed5e5098dffa7 --- /dev/null +++ b/Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h @@ -0,0 +1,153 @@ +// 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 CTFCoder.h +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of MID column data + +#ifndef O2_MID_CTFCODER_H +#define O2_MID_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include <array> +#include "DataFormatsMID/CTF.h" +#include "DataFormatsMID/ROFRecord.h" +#include "DataFormatsMID/ColumnData.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" +#include "rANS/rans.h" +#include "MIDCTF/CTFHelper.h" + +class TTree; + +namespace o2 +{ +namespace mid +{ + +class CTFCoder : public o2::ctf::CTFCoderBase +{ + public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::MID) {} + ~CTFCoder() = default; + + /// entropy-encode data to buffer with CTF + template <typename VEC> + void encode(VEC& buff, const gsl::span<const ROFRecord>& rofData, const gsl::span<const ColumnData>& colData); + + /// entropy decode data from buffer with CTF + template <typename VROF, typename VCOL> + void decode(const CTF::base& ec, VROF& rofVec, VCOL& colVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); + + private: + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<ROFRecord>& rofVec, std::vector<ColumnData>& colVec); +}; + +/// entropy-encode clusters to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const ROFRecord>& rofData, const gsl::span<const ColumnData>& colData) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, // BLC_bcIncROF + MD::EENCODE, // BLC_orbitIncROF + MD::EENCODE, // BLC_entriesROF + MD::EENCODE, // BLC_evtypeROF + MD::EENCODE, // BLC_pattern + MD::EENCODE, // BLC_deId + MD::EENCODE // BLC_colId + }; + CTFHelper helper(rofData, colData); + + // book output size with some margin + auto szIni = sizeof(CTFHeader) + helper.getSize() / 4; // will be autoexpanded if needed + buff.resize(szIni); + + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(helper.createHeader()); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODEMID(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); + // clang-format off + ENCODEMID(helper.begin_bcIncROF(), helper.end_bcIncROF(), CTF::BLC_bcIncROF, 0); + ENCODEMID(helper.begin_orbitIncROF(), helper.end_orbitIncROF(), CTF::BLC_orbitIncROF, 0); + ENCODEMID(helper.begin_entriesROF(), helper.end_entriesROF(), CTF::BLC_entriesROF, 0); + ENCODEMID(helper.begin_evtypeROF(), helper.end_evtypeROF(), CTF::BLC_evtypeROF, 0); + + ENCODEMID(helper.begin_pattern(), helper.end_pattern(), CTF::BLC_pattern, 0); + ENCODEMID(helper.begin_deId(), helper.end_deId(), CTF::BLC_deId, 0); + ENCODEMID(helper.begin_colId(), helper.end_colId(), CTF::BLC_colId, 0); + // clang-format on + CTF::get(buff.data())->print(getPrefix()); +} + +/// decode entropy-encoded clusters to standard compact clusters +template <typename VROF, typename VCOL> +void CTFCoder::decode(const CTF::base& ec, VROF& rofVec, VCOL& colVec) +{ + auto header = ec.getHeader(); + ec.print(getPrefix()); + std::vector<uint16_t> bcInc, entries, pattern; + std::vector<uint32_t> orbitInc; + std::vector<uint8_t> evType, deId, colId; + +#define DECODEFT0(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) + // clang-format off + DECODEFT0(bcInc, CTF::BLC_bcIncROF); + DECODEFT0(orbitInc, CTF::BLC_orbitIncROF); + DECODEFT0(entries, CTF::BLC_entriesROF); + DECODEFT0(evType, CTF::BLC_evtypeROF); + + DECODEFT0(pattern, CTF::BLC_pattern); + DECODEFT0(deId, CTF::BLC_deId); + DECODEFT0(colId, CTF::BLC_colId); + // clang-format on + // + rofVec.clear(); + colVec.clear(); + rofVec.reserve(header.nROFs); + colVec.reserve(header.nColumns); + + uint32_t firstEntry = 0, rofCount = 0, colCount = 0, pCount = 0; + o2::InteractionRecord ir(header.firstBC, header.firstOrbit); + + for (uint32_t irof = 0; irof < header.nROFs; irof++) { + // restore ROFRecord + if (orbitInc[irof]) { // non-0 increment => new orbit + ir.bc = bcInc[irof]; // bcInc has absolute meaning + ir.orbit += orbitInc[irof]; + } else { + ir.bc += bcInc[irof]; + } + + firstEntry = colVec.size(); + for (uint8_t ic = 0; ic < entries[irof]; ic++) { + colVec.emplace_back(ColumnData{deId[colCount], colId[colCount], std::array{pattern[pCount], pattern[pCount + 1], pattern[pCount + 2], pattern[pCount + 3], pattern[pCount + 4]}}); + pCount += 5; + colCount++; + } + rofVec.emplace_back(ROFRecord{ir, EventType(evType[irof]), firstEntry, entries[irof]}); + } + assert(colCount == header.nColumns); +} + +} // namespace mid +} // namespace o2 + +#endif // O2_MID_CTFCODER_H diff --git a/Detectors/MUON/MID/CTF/include/MIDCTF/CTFHelper.h b/Detectors/MUON/MID/CTF/include/MIDCTF/CTFHelper.h new file mode 100644 index 0000000000000..832870fa9f5e5 --- /dev/null +++ b/Detectors/MUON/MID/CTF/include/MIDCTF/CTFHelper.h @@ -0,0 +1,196 @@ +// 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 CTFHelper.h +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for MID CTF creation + +#ifndef O2_MID_CTF_HELPER_H +#define O2_MID_CTF_HELPER_H + +#include "DataFormatsMID/ROFRecord.h" +#include "DataFormatsMID/ColumnData.h" +#include "DataFormatsMID/CTF.h" +#include <gsl/span> + +namespace o2 +{ +namespace mid +{ + +class CTFHelper +{ + + public: + CTFHelper(const gsl::span<const o2::mid::ROFRecord>& rofData, const gsl::span<const o2::mid::ColumnData>& colData) + : mROFData(rofData), mColData(colData) {} + + CTFHeader createHeader() + { + CTFHeader h{uint32_t(mROFData.size()), uint32_t(mColData.size()), 0, 0}; + if (mROFData.size()) { + h.firstOrbit = mROFData[0].interactionRecord.orbit; + h.firstBC = mROFData[0].interactionRecord.bc; + } + return h; + } + + size_t getSize() const { return mROFData.size() * sizeof(o2::mid::ROFRecord) + mColData.size() * sizeof(o2::mid::ColumnData); } + + //>>> =========================== ITERATORS ======================================== + + template <typename I, typename D, typename T, int M = 1> + class _Iter + { + public: + using difference_type = int64_t; + using value_type = T; + using pointer = const T*; + using reference = const T&; + using iterator_category = std::random_access_iterator_tag; + + _Iter(const gsl::span<const D>& data, bool end = false) : mData(data), mIndex(end ? M * data.size() : 0){}; + _Iter() = default; + + const I& operator++() + { + ++mIndex; + return (I&)(*this); + } + + const I& operator--() + { + mIndex--; + return (I&)(*this); + } + + difference_type operator-(const I& other) const { return mIndex - other.mIndex; } + + difference_type operator-(size_t idx) const { return mIndex - idx; } + + const I& operator-(size_t idx) + { + mIndex -= idx; + return (I&)(*this); + } + + bool operator!=(const I& other) const { return mIndex != other.mIndex; } + bool operator==(const I& other) const { return mIndex == other.mIndex; } + bool operator>(const I& other) const { return mIndex > other.mIndex; } + bool operator<(const I& other) const { return mIndex < other.mIndex; } + + protected: + gsl::span<const D> mData{}; + size_t mIndex = 0; + }; + + //_______________________________________________ + // BC difference wrt previous if in the same orbit, otherwise the abs.value. + // For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_bcIncROF : public _Iter<Iter_bcIncROF, ROFRecord, uint16_t> + { + public: + using _Iter<Iter_bcIncROF, ROFRecord, uint16_t>::_Iter; + value_type operator*() const + { + if (mIndex) { + if (mData[mIndex].interactionRecord.orbit == mData[mIndex - 1].interactionRecord.orbit) { + return mData[mIndex].interactionRecord.bc - mData[mIndex - 1].interactionRecord.bc; + } else { + return mData[mIndex].interactionRecord.bc; + } + } + return 0; + } + }; + + //_______________________________________________ + // Orbit difference wrt previous. For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_orbitIncROF : public _Iter<Iter_orbitIncROF, ROFRecord, uint32_t> + { + public: + using _Iter<Iter_orbitIncROF, ROFRecord, uint32_t>::_Iter; + value_type operator*() const { return mIndex ? mData[mIndex].interactionRecord.orbit - mData[mIndex - 1].interactionRecord.orbit : 0; } + }; + + //_______________________________________________ + // Number of entries in the ROF + class Iter_entriesROF : public _Iter<Iter_entriesROF, ROFRecord, uint16_t> + { + public: + using _Iter<Iter_entriesROF, ROFRecord, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].nEntries; } + }; + + //_______________________________________________ + // Event type for the ROF + class Iter_evtypeROF : public _Iter<Iter_evtypeROF, ROFRecord, uint8_t> + { + public: + using _Iter<Iter_evtypeROF, ROFRecord, uint8_t>::_Iter; + value_type operator*() const { return value_type(mData[mIndex].eventType); } + }; + + //_______________________________________________ + class Iter_pattern : public _Iter<Iter_pattern, ColumnData, uint16_t, 5> + { + public: + using _Iter<Iter_pattern, ColumnData, uint16_t, 5>::_Iter; + value_type operator*() const { return mData[mIndex / 5].patterns[mIndex % 5]; } + }; + + //_______________________________________________ + class Iter_deId : public _Iter<Iter_deId, ColumnData, uint8_t> + { + public: + using _Iter<Iter_deId, ColumnData, uint8_t>::_Iter; + value_type operator*() const { return mData[mIndex].deId; } + }; + + //_______________________________________________ + class Iter_colId : public _Iter<Iter_colId, ColumnData, uint8_t> + { + public: + using _Iter<Iter_colId, ColumnData, uint8_t>::_Iter; + value_type operator*() const { return mData[mIndex].columnId; } + }; + + //<<< =========================== ITERATORS ======================================== + + Iter_bcIncROF begin_bcIncROF() const { return Iter_bcIncROF(mROFData, false); } + Iter_bcIncROF end_bcIncROF() const { return Iter_bcIncROF(mROFData, true); } + + Iter_orbitIncROF begin_orbitIncROF() const { return Iter_orbitIncROF(mROFData, false); } + Iter_orbitIncROF end_orbitIncROF() const { return Iter_orbitIncROF(mROFData, true); } + + Iter_entriesROF begin_entriesROF() const { return Iter_entriesROF(mROFData, false); } + Iter_entriesROF end_entriesROF() const { return Iter_entriesROF(mROFData, true); } + + Iter_evtypeROF begin_evtypeROF() const { return Iter_evtypeROF(mROFData, false); } + Iter_evtypeROF end_evtypeROF() const { return Iter_evtypeROF(mROFData, true); } + + Iter_pattern begin_pattern() const { return Iter_pattern(mColData, false); } + Iter_pattern end_pattern() const { return Iter_pattern(mColData, true); } + + Iter_deId begin_deId() const { return Iter_deId(mColData, false); } + Iter_deId end_deId() const { return Iter_deId(mColData, true); } + + Iter_colId begin_colId() const { return Iter_colId(mColData, false); } + Iter_colId end_colId() const { return Iter_colId(mColData, true); } + + private: + const gsl::span<const o2::mid::ROFRecord> mROFData; + const gsl::span<const o2::mid::ColumnData> mColData; +}; + +} // namespace mid +} // namespace o2 + +#endif diff --git a/Detectors/MUON/MID/CTF/src/CTFCoder.cxx b/Detectors/MUON/MID/CTF/src/CTFCoder.cxx new file mode 100644 index 0000000000000..0dc55d6763ae1 --- /dev/null +++ b/Detectors/MUON/MID/CTF/src/CTFCoder.cxx @@ -0,0 +1,76 @@ +// 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 CTFCoder.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of MID data + +#include "MIDCTF/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::mid; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) +{ + ec.appendToTree(tree, mDet.getName()); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, std::vector<ROFRecord>& rofVec, std::vector<ColumnData>& colVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, mDet.getName(), entry); + decode(ec, rofVec, colVec); +} + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + // just to get types + uint16_t bcInc = 0, entries = 0, pattern = 0; + uint32_t orbitInc = 0; + uint8_t evType = 0, deId = 0, colId = 0; +#define MAKECODER(part, slot) createCoder<decltype(part)>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(bcInc, CTF::BLC_bcIncROF); + MAKECODER(orbitInc, CTF::BLC_orbitIncROF); + MAKECODER(entries, CTF::BLC_entriesROF); + MAKECODER(evType, CTF::BLC_evtypeROF); + MAKECODER(pattern, CTF::BLC_pattern); + MAKECODER(deId, CTF::BLC_deId); + MAKECODER(colId, CTF::BLC_colId); + // clang-format on +} diff --git a/Detectors/MUON/MID/CTF/src/CTFHelper.cxx b/Detectors/MUON/MID/CTF/src/CTFHelper.cxx new file mode 100644 index 0000000000000..e512ac535fff4 --- /dev/null +++ b/Detectors/MUON/MID/CTF/src/CTFHelper.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. + +/// \file CTFHelper.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for MID CTF creation + +#include "MIDCTF/CTFHelper.h" diff --git a/Detectors/MUON/MID/README.md b/Detectors/MUON/MID/README.md index 1ac569734d269..af0b8e510c19d 100644 --- a/Detectors/MUON/MID/README.md +++ b/Detectors/MUON/MID/README.md @@ -13,4 +13,5 @@ This is a top page for the MID detector documentation. * \subpage refMUONMIDRawExe * \subpage refMUONMIDTracking * \subpage refMUONMIDWorkflow +* \subpage refMUONMIDCTF /doxy --> diff --git a/Detectors/MUON/MID/Workflow/CMakeLists.txt b/Detectors/MUON/MID/Workflow/CMakeLists.txt index 239e8d98caa8f..6a8be67985f22 100644 --- a/Detectors/MUON/MID/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MID/Workflow/CMakeLists.txt @@ -23,6 +23,8 @@ o2_add_library(MIDWorkflow src/DigitReaderSpec.cxx src/DigitsToRawWorkflow.cxx src/RawWriterSpec.cxx + src/EntropyDecoderSpec.cxx + src/EntropyEncoderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::SimConfig @@ -35,6 +37,7 @@ o2_add_library(MIDWorkflow O2::MIDClustering O2::MIDTracking O2::MIDRaw + O2::MIDCTF ) o2_add_executable( @@ -69,3 +72,14 @@ o2_add_executable( target_include_directories( ${exenameraw} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) + +o2_add_executable( + entropy-encoder-workflow + COMPONENT_NAME mid + SOURCES src/entropy-encoder-workflow.cxx + TARGETVARNAME exenameentropy + PUBLIC_LINK_LIBRARIES + O2::MIDWorkflow) + +target_include_directories( + ${exenameentropy} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) diff --git a/Detectors/MUON/MID/Workflow/README.md b/Detectors/MUON/MID/Workflow/README.md index f980e6b61428f..563f23581c553 100644 --- a/Detectors/MUON/MID/Workflow/README.md +++ b/Detectors/MUON/MID/Workflow/README.md @@ -45,3 +45,16 @@ Processing time / 90 ROFs: full: 3.55542 us tracking: 2.02182 us ``` Two timing values are provided: one is for the full execution of the device (including retrieval and sending of the DPL messages) and one which concerns only the execution of the algorithm (the tracking algorithm in the above example) The timing refers to the time needed to process one read-out-frame, i.e. one event. + +## Operations with CTF + +The MID contribution can be added to CTF by attaching the ``o2-mid-entropy-encoder-workflow`` device to reconstruction workflow ending by CTF writer, e.g.: +```bash +o2-raw-file-reader-workflow --input-conf raw/MID/MIDraw.cfg | o2-mid-reco-workflow | o2-mid-entropy-encoder-workflow | o2-ctf-writer-workflow +``` + +The reconstruction staring from CTF can be done as (option ``--input-ctf`` will prevent the ``o2-mid-reco-workflow`` from +adding raw data decoding/aggregation to the workflow): +```bash +o2-ctf-reader-workflow --ctf-input o2_ctf_0000000000.root --onlyDet MID | o2-mid-reco-workflow --input-ctf +``` diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyDecoderSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..97c413ae8b37d --- /dev/null +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyDecoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to MID ROFRecords/ColumnData stream + +#ifndef O2_MID_ENTROPYDECODER_SPEC +#define O2_MID_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "MIDCTF/CTFCoder.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace mid +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::mid::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace mid +} // namespace o2 + +#endif diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyEncoderSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..7dc6a90be029d --- /dev/null +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/EntropyEncoderSpec.h @@ -0,0 +1,48 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert MID data to CTF (EncodedBlocks) +/// @author ruben.shahoyan@cern.ch + +#ifndef O2_MID_ENTROPYENCODER_SPEC +#define O2_MID_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> +#include "MIDCTF/CTFCoder.h" + +namespace o2 +{ +namespace mid +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::mid::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace mid +} // namespace o2 + +#endif diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h index 1be6a027add3a..d35367efa83e3 100644 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h @@ -23,7 +23,7 @@ namespace o2 { namespace mid { -framework::WorkflowSpec getRecoWorkflow(); +framework::WorkflowSpec getRecoWorkflow(bool ctfInput); } } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/EntropyDecoderSpec.cxx b/Detectors/MUON/MID/Workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..ac4f7364faa95 --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "MIDWorkflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace mid +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("mid-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& rofs = pc.outputs().make<std::vector<o2::mid::ROFRecord>>(OutputRef{"rofs"}); + auto& cols = pc.outputs().make<std::vector<o2::mid::ColumnData>>(OutputRef{"cols"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::mid::CTF::getImage(buff.data()); + mCTFCoder.decode(ctfImage, rofs, cols); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << cols.size() << " MID columns in " << rofs.size() << " ROFRecords in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "MID Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"rofs"}, "MID", "DATAROF", 0, Lifetime::Timeframe}, + OutputSpec{{"cols"}, "MID", "DATA", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "mid-entropy-decoder", + Inputs{InputSpec{"ctf", "MID", "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{{"mid-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; +} + +} // namespace mid +} // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/EntropyEncoderSpec.cxx b/Detectors/MUON/MID/Workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..e3aca8c542833 --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,81 @@ +// 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 EntropyEncoderSpec.cxx +/// @brief Convert MID DATA to CTF (EncodedBlocks) +/// @author ruben.shahoyan@cern.ch + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "MIDWorkflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace mid +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("mid-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto rofs = pc.inputs().get<gsl::span<o2::mid::ROFRecord>>("rofs"); + auto cols = pc.inputs().get<gsl::span<o2::mid::ColumnData>>("cols"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"MID", "CTFDATA", 0, Lifetime::Timeframe}); + mCTFCoder.encode(buffer, rofs, cols); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + // eeb->print(); + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for MID in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "MID Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("rofs", "MID", "DATAROF", 0, Lifetime::Timeframe); + inputs.emplace_back("cols", "MID", "DATA", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "mid-entropy-encoder", + inputs, + Outputs{{"MID", "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{{"mid-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; +} + +} // namespace mid +} // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx b/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx index d46f3a4d2d2a7..90ad7f7f21e80 100644 --- a/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx @@ -29,7 +29,7 @@ namespace o2 namespace mid { -of::WorkflowSpec getRecoWorkflow() +of::WorkflowSpec getRecoWorkflow(bool ctf) { auto checkReady = [](o2::framework::DataRef const& ref) { @@ -44,8 +44,10 @@ of::WorkflowSpec getRecoWorkflow() of::WorkflowSpec specs; - specs.emplace_back(getRawDecoderSpec(false)); - specs.emplace_back(getRawAggregatorSpec()); + if (!ctf) { + specs.emplace_back(getRawDecoderSpec(false)); + specs.emplace_back(getRawAggregatorSpec()); + } specs.emplace_back(getClusterizerSpec()); specs.emplace_back(getTrackerSpec()); specs.emplace_back(of::MakeRootTreeWriterSpec("MIDTracksWriter", diff --git a/Detectors/MUON/MID/Workflow/src/entropy-encoder-workflow.cxx b/Detectors/MUON/MID/Workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..171291272c322 --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/entropy-encoder-workflow.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. + +#include "MIDWorkflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::mid::getEntropyEncoderSpec()); + return wf; +} diff --git a/Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx b/Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..b59fc88c58ba3 --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx @@ -0,0 +1,45 @@ +// 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 mid-entropy-encoder-workflow.cxx +/// \brief MID reconstruction workflow +/// \author ruben.shahoyan@cern.ch + +#include <string> +#include <vector> +#include "Framework/Variant.h" +#include "CommonUtils/ConfigurableParam.h" +#include "MIDWorkflow/EntropyEncoderSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::string keyvaluehelp("Semicolon separated key=value strings ..."); + workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); +} + +// ------------------------------------------------------------------ + +#include "Framework/ConfigParamSpec.h" +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); + + WorkflowSpec wf; + wf.emplace_back(o2::mid::getEntropyEncoderSpec()); + return std::move(wf); +} diff --git a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx b/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx index f97d70d667e8f..8f6ca738487d4 100644 --- a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx @@ -26,6 +26,10 @@ using namespace o2::framework; // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { + std::vector<ConfigParamSpec> options{ + {"input-ctf", VariantType::Bool, false, {"Input data comes from CTF"}}}; + std::swap(workflowOptions, options); + std::string keyvaluehelp("Semicolon separated key=value strings ..."); workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); } @@ -41,6 +45,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); // write the configuration used for the digitizer workflow o2::conf::ConfigurableParam::writeINI("o2mid-recoflow_configuration.ini"); - - return std::move(o2::mid::getRecoWorkflow()); + auto ctf = configcontext.options().get<bool>("input-ctf"); + return std::move(o2::mid::getRecoWorkflow(ctf)); } From e09984b31e8902c2edb9cb64cefcb0a6912e8611 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 17 Sep 2020 20:46:18 +0200 Subject: [PATCH 0684/1751] Add MID to CTF reader / writer devices --- Detectors/CTF/CMakeLists.txt | 8 +- Detectors/CTF/test/test_ctf_io_mid.cxx | 130 ++++++++++++++++++ Detectors/CTF/workflow/CMakeLists.txt | 2 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 ++ Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 3 + .../CTF/workflow/src/ctf-reader-workflow.cxx | 9 ++ 6 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 Detectors/CTF/test/test_ctf_io_mid.cxx diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index 89266ddd5fd5e..c0297405a0126 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -7,7 +7,6 @@ # 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. - add_subdirectory(workflow) o2_add_test(itsmft @@ -51,3 +50,10 @@ o2_add_test(tof COMPONENT_NAME ctf LABELS ctf) +o2_add_test(mid + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::DataFormatsMID + O2::MIDCTF + SOURCES test/test_ctf_io_mid.cxx + COMPONENT_NAME ctf + LABELS ctf) diff --git a/Detectors/CTF/test/test_ctf_io_mid.cxx b/Detectors/CTF/test/test_ctf_io_mid.cxx new file mode 100644 index 0000000000000..94f6c67b087a2 --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_mid.cxx @@ -0,0 +1,130 @@ +// 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. + +#define BOOST_TEST_MODULE Test MIDCTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DetectorsCommonDataFormats/NameConf.h" +#include "MIDCTF/CTFCoder.h" +#include "DataFormatsMID/CTF.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <TSystem.h> +#include <cstring> + +using namespace o2::mid; + +BOOST_AUTO_TEST_CASE(CTFTest) +{ + std::vector<ROFRecord> rofs; + std::vector<ColumnData> cols; + // RS: don't understand why, but this library is not loaded automatically, although the dependencies are clearly + // indicated. What it more weird is that for similar tests of other detectors the library is loaded! + // Absence of the library leads to complains about the StreamerInfo and eventually segm.faul when appending the + // CTH to the tree. For this reason I am loading it here manually + gSystem->Load("libO2DetectorsCommonDataFormats.so"); + TStopwatch sw; + sw.Start(); + o2::InteractionRecord ir(0, 0); + std::array<uint16_t, 5> pattern; + for (int irof = 0; irof < 1000; irof++) { + ir += 1 + gRandom->Integer(200); + uint8_t nch = 0, evtyp = gRandom->Integer(3); + while (nch == 0) { + nch = gRandom->Poisson(10); + } + auto start = cols.size(); + for (int ich = 0; ich < nch; ich++) { + uint8_t deId = gRandom->Integer(128); + uint8_t columnId = gRandom->Integer(128); + for (int i = 0; i < 5; i++) { + pattern[i] = gRandom->Integer(0x7fff); + } + cols.emplace_back(ColumnData{deId, columnId, pattern}); + } + rofs.emplace_back(ROFRecord{ir, EventType(evtyp), start, cols.size() - start}); + } + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + { + CTFCoder coder; + coder.encode(vec, rofs, cols); // compress + } + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + auto* ctfImage = o2::mid::CTF::get(vec.data()); + TFile flOut("test_ctf_mid.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "MID"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + { + sw.Start(); + TFile flIn("test_ctf_mid.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + o2::mid::CTF::readFromTree(vec, *(tree.get()), "MID"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<ROFRecord> rofsD; + std::vector<ColumnData> colsD; + + sw.Start(); + const auto ctfImage = o2::mid::CTF::getImage(vec.data()); + { + CTFCoder coder; + coder.decode(ctfImage, rofsD, colsD); // decompress + } + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + BOOST_CHECK(rofsD.size() == rofs.size()); + BOOST_CHECK(colsD.size() == cols.size()); + LOG(INFO) << " BOOST_CHECK rofsD.size() " << rofsD.size() << " rofs.size() " << rofs.size() + << " BOOST_CHECK(colsD.size() " << colsD.size() << " cols.size()) " << cols.size(); + + for (size_t i = 0; i < rofs.size(); i++) { + const auto& dor = rofs[i]; + const auto& ddc = rofsD[i]; + LOG(DEBUG) << " Orig.ROFRecord " << i << " " << dor.interactionRecord << " " << dor.firstEntry << " " << dor.nEntries; + LOG(DEBUG) << " Deco.ROFRecord " << i << " " << ddc.interactionRecord << " " << ddc.firstEntry << " " << ddc.nEntries; + + BOOST_CHECK(dor.interactionRecord == ddc.interactionRecord); + BOOST_CHECK(dor.firstEntry == ddc.firstEntry); + BOOST_CHECK(dor.nEntries == dor.nEntries); + } + + for (size_t i = 0; i < cols.size(); i++) { + const auto& cor = cols[i]; + const auto& cdc = colsD[i]; + BOOST_CHECK(cor.deId == cdc.deId); + BOOST_CHECK(cor.columnId == cdc.columnId); + for (int j = 0; j < 5; j++) { + BOOST_CHECK(cor.patterns[j] == cdc.patterns[j]); + LOG(DEBUG) << "col " << i << " pat " << j << " : " << cor.patterns[j] << " : " << cdc.patterns[j]; + } + } +} diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index 02b5050aaa4f0..b067550797317 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -18,12 +18,14 @@ o2_add_library(CTFWorkflow O2::DataFormatsTOF O2::DataFormatsFT0 O2::DataFormatsFV0 + O2::DataFormatsMID O2::DataFormatsParameters O2::ITSMFTWorkflow O2::TPCWorkflow O2::FT0Workflow O2::FV0Workflow O2::TOFWorkflow + O2::MIDWorkflow O2::Algorithm O2::CommonUtils) diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index db9d2ce38cf76..0ee5a31257e24 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -28,6 +28,7 @@ #include "DataFormatsFT0/CTF.h" #include "DataFormatsFV0/CTF.h" #include "DataFormatsTOF/CTF.h" +#include "DataFormatsMID/CTF.h" #include "Algorithm/RangeTokenizer.h" using namespace o2::framework; @@ -149,6 +150,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::MID; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::mid::CTF)); + o2::mid::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + mTimer.Stop(); LOG(INFO) << "Read CTF " << inputFile << " in " << mTimer.CpuTime() - cput << " s"; diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 209927a42da49..a71affd80a35d 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -25,6 +25,7 @@ #include "DataFormatsFT0/CTF.h" #include "DataFormatsFV0/CTF.h" #include "DataFormatsTOF/CTF.h" +#include "DataFormatsMID/CTF.h" using namespace o2::framework; @@ -96,6 +97,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) processDet<o2::tof::CTF>(pc, DetID::TOF, header, treeOut.get()); processDet<o2::ft0::CTF>(pc, DetID::FT0, header, treeOut.get()); processDet<o2::fv0::CTF>(pc, DetID::FV0, header, treeOut.get()); + processDet<o2::mid::CTF>(pc, DetID::MID, header, treeOut.get()); mTimer.Stop(); @@ -163,6 +165,7 @@ void CTFWriterSpec::storeDictionaries() storeDictionary<o2::tof::CTF>(DetID::TOF, header); storeDictionary<o2::ft0::CTF>(DetID::FT0, header); storeDictionary<o2::fv0::CTF>(DetID::FV0, header); + storeDictionary<o2::mid::CTF>(DetID::MID, header); // close remnants if (mDictTreeOut) { closeDictionaryTreeAndFile(header); diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index 57f90e8d45b24..0aa39b30509f9 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -23,7 +23,9 @@ #include "ITSMFTWorkflow/EntropyDecoderSpec.h" #include "TPCWorkflow/EntropyDecoderSpec.h" #include "FT0Workflow/EntropyDecoderSpec.h" +#include "FV0Workflow/EntropyDecoderSpec.h" #include "TOFWorkflow/EntropyDecoderSpec.h" +#include "MIDWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -80,5 +82,12 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets[DetID::FT0]) { specs.push_back(o2::ft0::getEntropyDecoderSpec()); } + if (dets[DetID::FV0]) { + specs.push_back(o2::fv0::getEntropyDecoderSpec()); + } + if (dets[DetID::MID]) { + specs.push_back(o2::mid::getEntropyDecoderSpec()); + } + return std::move(specs); } From 71dd95b5efdf6ce256d0fd18e9cf12da7c721ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Fri, 18 Sep 2020 15:56:35 +0200 Subject: [PATCH 0685/1751] Add TOF selection in track selection (#4385) --- Analysis/Core/include/Analysis/TrackSelection.h | 3 +++ .../include/Analysis/TrackSelectionTables.h | 4 +++- Analysis/Tasks/trackselection.cxx | 13 ++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/Analysis/TrackSelection.h index 51aad617a560f..769c6f10b84c8 100644 --- a/Analysis/Core/include/Analysis/TrackSelection.h +++ b/Analysis/Core/include/Analysis/TrackSelection.h @@ -42,6 +42,7 @@ class TrackSelection : public TObject (track.tpcChi2NCl() < mMaxChi2PerClusterTPC) && ((mRequireITSRefit) ? (track.flags() & 0x4) : true) && ((mRequireTPCRefit) ? (track.flags() & 0x40) : true) && + ((mRequireTOF) ? ((track.flags() & 0x2000) && (track.flags() & 0x80000000)) : true) && FulfillsITSHitRequirements(track.itsClusterMap()) && abs(track.dcaXY()) < mMaxDcaXY && abs(track.dcaZ()) < mMaxDcaZ) { return true; @@ -63,6 +64,7 @@ class TrackSelection : public TObject { mRequireTPCRefit = requireTPCRefit; } + void SetRequireTOF(bool requireTOF = true) { mRequireTOF = requireTOF; } void SetMinNClustersTPC(int minNClustersTPC) { mMinNClustersTPC = minNClustersTPC; @@ -131,6 +133,7 @@ class TrackSelection : public TObject bool mRequireITSRefit; // require refit in ITS bool mRequireTPCRefit; // require refit in TPC + bool mRequireTOF; // require that track exits the TOF and that it has an associated time measurement (kTIME and kTOFOUT) std::vector<std::pair<int8_t, std::set<uint8_t>>> mRequiredITSHits; // vector of ITS requirements (minNRequiredHits in diff --git a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h index 5a242860ca34e..e2e29ee95ab9d 100644 --- a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h @@ -23,13 +23,15 @@ DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); // Columns to store track filter decisions DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, uint8_t); DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, uint8_t); +DECLARE_SOA_COLUMN(IsGlobalTrackwTOF, isGlobalTrackwTOF, uint8_t); } // namespace track DECLARE_SOA_TABLE(TracksExtended, "AOD", "TRACKEXTENDED", track::DcaXY, track::DcaZ); DECLARE_SOA_TABLE(TrackSelection, "AOD", "TRACKSELECTION", track::IsGlobalTrack, - track::IsGlobalTrackSDD); + track::IsGlobalTrackSDD, + track::IsGlobalTrackwTOF); } // namespace o2::aod #endif // O2_ANALYSIS_TRACKSELECTIONTABLES_H_ diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index 57fb22c81fd4d..2d92ea7669d41 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -67,6 +67,14 @@ TrackSelection getGlobalTrackSelectionSDD() return selectedTracks; } +// Default track selection requiring a cluster matched in TOF +TrackSelection getGlobalTrackSelectionwTOF() +{ + TrackSelection selectedTracks = getGlobalTrackSelection(); + selectedTracks.SetRequireTOF(kTRUE); + return selectedTracks; +} + //**************************************************************************************** /** * Produce the derived track quantities needed for track selection. @@ -111,18 +119,21 @@ struct TrackSelectionTask { TrackSelection globalTracks; TrackSelection globalTracksSDD; + TrackSelection globalTrackswTOF; void init(InitContext&) { globalTracks = getGlobalTrackSelection(); globalTracksSDD = getGlobalTrackSelectionSDD(); + globalTrackswTOF = getGlobalTrackSelectionwTOF(); } void process(soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& track : tracks) { filterTable((uint8_t)globalTracks.IsSelected(track), - (uint8_t)globalTracksSDD.IsSelected(track)); + (uint8_t)globalTracksSDD.IsSelected(track), + (uint8_t)globalTrackswTOF.IsSelected(track)); } } }; From 9a841ed65ab7b180238f485cc1896ab8e7a35bfb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 18 Sep 2020 20:02:12 +0200 Subject: [PATCH 0686/1751] On track operation failure produce WARNING instead of ERROR --- DataFormats/Reconstruction/src/Track.cxx | 12 ++++++------ Detectors/Base/src/Propagator.cxx | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/DataFormats/Reconstruction/src/Track.cxx b/DataFormats/Reconstruction/src/Track.cxx index d83a82913377e..28773a1f53fcc 100644 --- a/DataFormats/Reconstruction/src/Track.cxx +++ b/DataFormats/Reconstruction/src/Track.cxx @@ -358,8 +358,8 @@ bool TrackPar::propagateParamToDCA(const Point3D<float>& vtx, float b, std::arra auto tmpT(*this); // operate on the copy to recover after the failure alp += std::asin(sn); if (!tmpT.rotateParam(alp) || !tmpT.propagateParamTo(xv, b)) { - LOG(ERROR) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " - << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " + << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; tmpT.printParam(); return false; } @@ -826,7 +826,7 @@ bool TrackParCov::rotate(float alpha) { // rotate to alpha frame if (fabs(getSnp()) > Almost1) { - LOGF(ERROR, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); + LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); return false; } // @@ -903,7 +903,7 @@ bool TrackParCov::propagateToDCA(const o2::dataformats::VertexBase& vtx, float b auto tmpT(*this); // operate on the copy to recover after the failure alp += std::asin(sn); if (!tmpT.rotate(alp) || !tmpT.propagateTo(xv, b)) { - LOG(ERROR) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); return false; } @@ -1381,7 +1381,7 @@ float TrackParCov::getPredictedChi2(const TrackParCov& rhs, MatrixDSym5& covToSe } buildCombinedCovMatrix(rhs, covToSet); if (!covToSet.Invert()) { - LOG(ERROR) << "Cov.matrix inversion failed: " << covToSet; + LOG(WARNING) << "Cov.matrix inversion failed: " << covToSet; return 2. * HugeF; } double chi2diag = 0., chi2ndiag = 0., diff[kNParams]; @@ -1471,7 +1471,7 @@ bool TrackParCov::update(const TrackParCov& rhs) MatrixDSym5 covI; // perform matrix operations in double! buildCombinedCovMatrix(rhs, covI); if (!covI.Invert()) { - LOG(ERROR) << "Cov.matrix inversion failed: " << covI; + LOG(WARNING) << "Cov.matrix inversion failed: " << covI; return false; } return update(rhs, covI); diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index db8147e68085d..af890ba9ede7d 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -315,7 +315,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); if (!tmpT.rotate(alp) || !propagateToX(tmpT, xv, bZ, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { - LOG(ERROR) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); return false; } @@ -360,7 +360,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); if (!tmpT.rotate(alp) || !PropagateToXBxByBz(tmpT, xv, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { - LOG(ERROR) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); return false; } @@ -405,8 +405,8 @@ bool Propagator::propagateToDCA(const Point3D<float>& vtx, o2::track::TrackPar& auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); if (!tmpT.rotateParam(alp) || !propagateToX(tmpT, xv, bZ, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { - LOG(ERROR) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " - << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " + << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; tmpT.printParam(); return false; } @@ -449,8 +449,8 @@ bool Propagator::propagateToDCABxByBz(const Point3D<float>& vtx, o2::track::Trac auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); if (!tmpT.rotateParam(alp) || !PropagateToXBxByBz(tmpT, xv, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { - LOG(ERROR) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " - << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " + << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; tmpT.printParam(); return false; } From ca788fe1b687e8713945da66d72b2aa32f11d4ea Mon Sep 17 00:00:00 2001 From: Gian Michele Innocenti <ginnocen@cern.ch> Date: Fri, 18 Sep 2020 15:48:19 +0200 Subject: [PATCH 0687/1751] reject tracks with very large IP from primary at preselection stage --- Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 92945bb64cc23..adfdeb9c48408 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -54,7 +54,7 @@ struct SelectTracks { status = 0; array<float, 2> dca; auto trackparvar0 = getTrackParCov(track); - trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca); // get impact parameters + trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters if (abs(dca[0]) < dcatoprimxymin) status = 0; if (b_dovalplots) { From b9ae7849c59cb4586112cc1d41ad8bd6a222009d Mon Sep 17 00:00:00 2001 From: Gian Michele Innocenti <ginnocen@cern.ch> Date: Fri, 18 Sep 2020 20:40:15 +0200 Subject: [PATCH 0688/1751] Add check on return value of track propagation --- Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index adfdeb9c48408..aa78acf0b45ac 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -54,7 +54,9 @@ struct SelectTracks { status = 0; array<float, 2> dca; auto trackparvar0 = getTrackParCov(track); - trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters + bool isprop = trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters + if(!isprop) + status = 0; if (abs(dca[0]) < dcatoprimxymin) status = 0; if (b_dovalplots) { From cab993bdf40b96fa8d7b036dd83ed3aea059a9ad Mon Sep 17 00:00:00 2001 From: ALICE Action Bot <alibuild@cern.ch> Date: Fri, 18 Sep 2020 18:41:59 +0000 Subject: [PATCH 0689/1751] Please consider the following formatting changes --- Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index aa78acf0b45ac..8905afb53bb37 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -55,7 +55,7 @@ struct SelectTracks { array<float, 2> dca; auto trackparvar0 = getTrackParCov(track); bool isprop = trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters - if(!isprop) + if (!isprop) status = 0; if (abs(dca[0]) < dcatoprimxymin) status = 0; From b1d57733a32cc96f060afa73d2d5968bc316ab7e Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Sat, 19 Sep 2020 14:31:06 +0100 Subject: [PATCH 0690/1751] Correct the typo when looping over goodNegTracks (#4391) The finder was looping twice over goodPosTracks --- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index 9baf319c218e3..387f541695434 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -113,7 +113,7 @@ struct lambdakzerofinder { continue; if (t0.tpcNClsCrossedRows() < 70) continue; - for (auto& t1 : goodPosTracks) { + for (auto& t1 : goodNegTracks) { auto thisdcanegtopv = getdcaXY(t1, pVtx); if (thisdcanegtopv < dcanegtopv) continue; From ac1072d8eac814d3c91f6dd66b862a8f2a9ebe5e Mon Sep 17 00:00:00 2001 From: dsekihat <daiki.sekihata@cern.ch> Date: Sat, 19 Sep 2020 22:33:40 +0900 Subject: [PATCH 0691/1751] remove PID dependency (#4389) --- Analysis/Tasks/PWGDQ/dileptonEE.cxx | 41 ++++++++++++++++++++++++-- Analysis/Tasks/PWGDQ/tableMaker_pp.cxx | 23 ++++++++------- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx index ef6c8082a0bb9..f47bd93c465a9 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -108,8 +108,45 @@ struct BarrelTrackSelection { cut1->AddCut(VarManager::kTrackDCAxy, -1.0, +1.0); cut1->AddCut(VarManager::kTrackDCAz, -3.0, +3.0); - cut1->AddCut(VarManager::kTPCsignal, 70, 100, false); //exclude = false - cut1->AddCut(VarManager::kTOFnSigmaEl, -3, +3, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, 70, 90, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, 75, 90, false, VarManager::kPt, 2.0, 1e+10); //exclude = false + //cut1->AddCut(VarManager::kTOFnSigmaEl, -3, +3, false); //exclude = false + //fTrackCut->AddCut(cut1); + + AnalysisCompositeCut* pidcut = new AnalysisCompositeCut(false); // false : use OR + AnalysisCut* pidcut_high = new AnalysisCut("pidcut_high", "e high"); + pidcut_high->AddCut(VarManager::kTPCsignal, 75, 90, false, VarManager::kPin, 2.0, 1e+10, false); //exclude = false + pidcut_high->AddCut(VarManager::kTPCsignal, 70, 90, false); //exclude = false + + AnalysisCut* pidcut_rejPr = new AnalysisCut("pidcut_rejPr", "proton rejection"); + TF1* f1minPr = new TF1("f1minPr", "[0]+[1]*x", 0, 10); + f1minPr->SetParameters(220, -150); + TF1* f1maxPr = new TF1("f1maxPr", "[0]+[1]*x", 0, 10); + f1maxPr->SetParameters(195, -100); + pidcut_rejPr->AddCut(VarManager::kTPCsignal, f1minPr, f1maxPr, true, VarManager::kPin, 0.8, 1.25, false); //exclude = false + + AnalysisCut* pidcut_rejKa = new AnalysisCut("pidcut_rejKa", "kaon rejection"); + TF1* f1minKa = new TF1("f1minKa", "[0]+[1]*x", 0, 10); + f1minKa->SetParameters(220, -300); + TF1* f1maxKa = new TF1("f1maxKa", "[0]+[1]*x", 0, 10); + f1maxKa->SetParameters(182.5, -150); + pidcut_rejKa->AddCut(VarManager::kTPCsignal, f1minKa, f1maxKa, true, VarManager::kPin, 0.4, 0.8, false); //exclude = false + + AnalysisCut* pidcut_rejPi = new AnalysisCut("pidcut_rejPi", "pion rejection"); + TF1* f1maxPi = new TF1("f1maxPi", "[0]+[1]*x", 0, 10); + f1maxPi->SetParameters(85, -50); + pidcut_rejPi->AddCut(VarManager::kTPCsignal, 70, f1maxPi, true, VarManager::kPin, 0.0, 0.4, false); //exclude = false + + cut1->AddCut(VarManager::kTPCsignal, f1minPr, f1maxPr, true, VarManager::kPin, 0.8, 1.25, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, f1minKa, f1maxKa, true, VarManager::kPin, 0.4, 0.8, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, 70, f1maxPi, true, VarManager::kPin, 0.0, 0.4, false); //exclude = false + + //pidcut->AddCut(pidcut_high); + //pidcut->AddCut(pidcut_rejPr); + //pidcut->AddCut(pidcut_rejKa); + //pidcut->AddCut(pidcut_rejPi); + //fTrackCut->AddCut(pidcut); + fTrackCut->AddCut(cut1); VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill diff --git a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx index 95c4c5ee90d04..e32e8236867b5 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx @@ -68,7 +68,7 @@ struct TableMaker_pp { VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill } - void process(soa::Join<aod::Collisions, aod::EvSels>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracksBarrel) + void process(soa::Join<aod::Collisions, aod::EvSels>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov /*, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta*/> const& tracksBarrel) { uint64_t tag = 0; uint32_t triggerAliases = 0; @@ -114,16 +114,17 @@ struct TableMaker_pp { track.trdChi2(), track.tofChi2(), track.length(), dcaXY, dcaZ); trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); - trackBarrelPID( - track.tpcSignal(), - track.tpcNSigmaEl(), track.tpcNSigmaMu(), - track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), - track.tofSignal(), track.beta(), - track.tofNSigmaEl(), track.tofNSigmaMu(), - track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), - track.trdSignal()); + trackBarrelPID(track.tpcSignal(), + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + //track.tpcNSigmaEl(), track.tpcNSigmaMu(), + //track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + //track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), + //track.tofSignal(), track.beta(), + //track.tofNSigmaEl(), track.tofNSigmaMu(), + //track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + //track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), + //track.trdSignal()); } for (auto& muon : tracksMuon) { From 050f9ed10688087b2e28b8a6722e0ea6530e563d Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Sat, 19 Sep 2020 16:29:16 +0200 Subject: [PATCH 0692/1751] fixing merging (#4386) --- Analysis/Core/src/CorrelationContainer.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 35798f0a7b510..9f6619b858c73 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -490,7 +490,7 @@ Long64_t CorrelationContainer::Merge(TCollection* list) TObject* obj = nullptr; // collections of objects - const UInt_t kMaxLists = 3; + const UInt_t kMaxLists = 4; TList** lists = new TList*[kMaxLists]; for (UInt_t i = 0; i < kMaxLists; i++) @@ -508,6 +508,7 @@ Long64_t CorrelationContainer::Merge(TCollection* list) lists[1]->Add(entry->mTriggerHist); lists[2]->Add(entry->mTrackHistEfficiency); + lists[3]->Add(entry->mEventCount); count++; } From 278fa62d59fe6460f58773bf9d54700c23311438 Mon Sep 17 00:00:00 2001 From: vfeuilla <71069003+vfeuilla@users.noreply.github.com> Date: Sat, 19 Sep 2020 16:29:47 +0200 Subject: [PATCH 0693/1751] Addition of the dimuon analysis task (#4342) --- Analysis/Core/include/Analysis/VarManager.h | 21 +- Analysis/Core/src/VarManager.cxx | 2 + .../include/Analysis/ReducedInfoTables.h | 3 +- Analysis/Tasks/PWGDQ/CMakeLists.txt | 5 + Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 309 ++++++++++++++++++ .../include/Framework/AnalysisDataModel.h | 11 + 6 files changed, 348 insertions(+), 3 deletions(-) create mode 100644 Analysis/Tasks/PWGDQ/dileptonMuMu.cxx diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 6df2ec3d36cc0..c95c307b56c40 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -27,6 +27,7 @@ // TODO: create an array holding these constants for all needed particles or check for a place where these are already defined static const float fgkElectronMass = 0.000511; // GeV +static const float fgkMuonMass = 0.105; // GeV //_________________________________________________________________________ class VarManager : public TObject @@ -126,6 +127,7 @@ class VarManager : public TObject kMuonZMu, kMuonBendingCoor, kMuonNonBendingCoor, + kMuonRAtAbsorberEnd, kMuonChi2, kMuonChi2MatchTrigger, kNMuonTrackVariables, @@ -359,6 +361,7 @@ void VarManager::FillTrack(T const& track, float* values) values[kMuonZMu] = track.zMu(); values[kMuonBendingCoor] = track.bendingCoor(); values[kMuonNonBendingCoor] = track.nonBendingCoor(); + values[kMuonRAtAbsorberEnd] = track.rAtAbsorberEnd(); values[kMuonChi2] = track.chi2(); values[kMuonChi2MatchTrigger] = track.chi2MatchTrigger(); } @@ -376,13 +379,27 @@ void VarManager::FillPair(T const& t1, T const& t2, float* values) if (!values) values = fgValues; - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), fgkElectronMass); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), fgkElectronMass); + float mass1; + float mass2; + + if (t1.filteringFlags() > 0) + mass1 = fgkElectronMass; + else + mass1 = fgkMuonMass; + + if (t1.filteringFlags() > 0) + mass2 = fgkElectronMass; + else + mass2 = fgkMuonMass; + + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), mass1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), mass2); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; values[kMass] = v12.M(); values[kPt] = v12.Pt(); values[kEta] = v12.Eta(); values[kPhi] = v12.Phi(); + values[kRap] = -v12.Rapidity(); } template <typename T1, typename T2> diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 6cbfc7b6eb9a0..008083f729c01 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -209,6 +209,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kMuonBendingCoor] = ""; fgVariableNames[kMuonNonBendingCoor] = "non-bending coor."; fgVariableUnits[kMuonNonBendingCoor] = ""; + fgVariableNames[kMuonRAtAbsorberEnd] = "R at the end of the absorber"; + fgVariableUnits[kMuonRAtAbsorberEnd] = ""; fgVariableNames[kMuonChi2] = "#chi 2"; fgVariableUnits[kMuonChi2] = ""; fgVariableNames[kMuonChi2MatchTrigger] = "#chi 2 trigger match"; diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index f60c22f63a8c1..88bf692dd77f8 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -133,7 +133,8 @@ DECLARE_SOA_TABLE(ReducedMuonsExtended, "AOD", "RTMUONEXTENDED", muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY, muon::ZMu, muon::BendingCoor, muon::NonBendingCoor, - muon::Chi2, muon::Chi2MatchTrigger); + muon::Chi2, muon::Chi2MatchTrigger, + muon::RAtAbsorberEnd<muon::BendingCoor, muon::NonBendingCoor, muon::ThetaX, muon::ThetaY, muon::ZMu>); // iterators using ReducedTrack = ReducedTracks::iterator; diff --git a/Analysis/Tasks/PWGDQ/CMakeLists.txt b/Analysis/Tasks/PWGDQ/CMakeLists.txt index 928dbe3444c82..866d28ff3c8f1 100644 --- a/Analysis/Tasks/PWGDQ/CMakeLists.txt +++ b/Analysis/Tasks/PWGDQ/CMakeLists.txt @@ -13,6 +13,11 @@ o2_add_dpl_workflow(dilepton-ee PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore COMPONENT_NAME Analysis) +o2_add_dpl_workflow(dilepton-mumu + SOURCES dileptonMuMu.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(table-maker-pp SOURCES tableMaker_pp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx new file mode 100644 index 0000000000000..198660d58519a --- /dev/null +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -0,0 +1,309 @@ +// 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 <TH1F.h> +#include <TMath.h> +#include <THashList.h> +#include <TString.h> +#include <iostream> + +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(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(Rap, rap, 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(MuonTrackCuts, "AOD", "MUONTRACKCUTS", reducedtrack::IsMuonSelected); +} // namespace o2::aod + +using MyEvent = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended>::iterator; +using MyEventVtxCov = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator; +using MyMuonTracks = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended>; +using MyMuonTracksSelected = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended, aod::MuonTrackCuts>; + +void DefineHistograms(o2::framework::OutputObj<HistogramManager> 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 fgEventMuonFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; +constexpr static uint32_t fgMuonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackMuon; + +struct MuonTrackSelection { + Produces<aod::MuonTrackCuts> trackSel; + OutputObj<HistogramManager> fHistMan{"output"}; + AnalysisCompositeCut* fMuonCut; + + 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, "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() + { + fMuonCut = new AnalysisCompositeCut(true); + AnalysisCut kineMuonCut; + kineMuonCut.AddCut(VarManager::kPt, 1.0, 20); + kineMuonCut.AddCut(VarManager::kEta, -4.0, -2.5); + kineMuonCut.AddCut(VarManager::kMuonChi2, 0.0, 1e6); + kineMuonCut.AddCut(VarManager::kMuonRAtAbsorberEnd, 17.6, 89.5); + fMuonCut->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; + // fill event information which might be needed in histograms that combine track and event properties + VarManager::FillEvent<fgEventMuonFillMap>(event, fValues); + + for (auto& muon : muons) { + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValues[i] = -9999.0f; + VarManager::FillTrack<fgMuonFillMap>(muon, fValues); + fHistMan->FillHistClass("TrackMuon_BeforeCuts", fValues); + + if (fMuonCut->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); + } else + trackSel(0); + } + } +}; + +struct DileptonMuMu { + OutputObj<HistogramManager> fHistMan{"outputMuons"}; + AnalysisCompositeCut* fEventCut; + AnalysisCompositeCut* fDiMuonCut; + //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition + // NOTE TO THE NOTE: a dimuon cut is needed on the rapidity of the pair. So I added one. Hopefully this works + + Partition<MyMuonTracksSelected> posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; + Partition<MyMuonTracksSelected> 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;PairsMuonULS;PairsMuonLSpp;PairsMuonLSnn;"); // 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); + + fDiMuonCut = new AnalysisCompositeCut(true); + AnalysisCut* diMuonCut = new AnalysisCut(); + diMuonCut->AddCut(VarManager::kRap, 2.5, 4.0); + fDiMuonCut->AddCut(diMuonCut); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEventVtxCov event, MyMuonTracksSelected const& tracks) + { + // Reset the VarManager::fgValues array + // The reset can be done selectively, using arguments in the ResetValues() function + VarManager::ResetValues(); + + VarManager::FillEvent<fgEventMuonFillMap>(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); + + // same event pairing for muons + 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); + if (!fDiMuonCut->IsSelected(VarManager::fgValues)) + return; + fHistMan->FillHistClass("PairsMuonULS", VarManager::fgValues); + } + for (auto tpos2 = tpos + 1; tpos2 != posMuons.end(); ++tpos2) { // ++ pairs + VarManager::FillPair(tpos, tpos2); + if (!fDiMuonCut->IsSelected(VarManager::fgValues)) + return; + fHistMan->FillHistClass("PairsMuonLSpp", VarManager::fgValues); + } + } + for (auto tneg : negMuons) { // -- pairs + for (auto tneg2 = tneg + 1; tneg2 != negMuons.end(); ++tneg2) { + VarManager::FillPair(tneg, tneg2); + if (!fDiMuonCut->IsSelected(VarManager::fgValues)) + return; + fHistMan->FillHistClass("PairsMuonLSnn", VarManager::fgValues); + } + } + } +}; + +void DefineHistograms(o2::framework::OutputObj<HistogramManager> 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, 19, -4.2, -2.3, 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("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); + histMan->AddHistogram(classStr.Data(), "RAtAbsorberEnd", "", false, 140, 10, 150, VarManager::kMuonRAtAbsorberEnd); + } + } + + if (classStr.Contains("Pairs")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Mass", "", false, 100, 2.0, 12, VarManager::kMass); + histMan->AddHistogram(classStr.Data(), "Pt", "", false, 200, 0.0, 20.0, VarManager::kPt); + histMan->AddHistogram(classStr.Data(), "Rapidity", "", false, 19, 2.0, 4.3, VarManager::kRap); + histMan->AddHistogram(classStr.Data(), "Mass_Pt", "mass vs p_{T} distribution", false, 100, 0.0, 20.0, VarManager::kMass, 200, 0.0, 20.0, VarManager::kPt); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "Mass_Y", "mass vs y distribution", false, 100, 0.0, 20.0, VarManager::kMass, 19, 2.0, 4.3, VarManager::kRap); // TH2F histogram + } + } // end loop over histogram classes +} + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), + adaptAnalysisTask<DileptonMuMu>("dilepton-mumu")}; +} diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 8a079417ed680..1c765aad91018 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -337,6 +337,16 @@ DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float thetaX, float thetaY) -> float { constexpr float twopi = 2.0f * static_cast<float>(M_PI); return (phi >= 0.0 ? phi : phi + twopi); }); +DECLARE_SOA_DYNAMIC_COLUMN(RAtAbsorberEnd, rAtAbsorberEnd, [](float bendingCoor, float nonBendingCoor, float zMu, float thetaX, float thetaY) -> float { + // linear extrapolation of the coordinates of the track to the position of the end of the absorber (-505 cm) + float dZ = -505. - zMu; + float NonBendingSlope = std::tan(thetaX); + float BendingSlope = std::tan(thetaY); + float xAbs = nonBendingCoor + NonBendingSlope * dZ; + float yAbs = bendingCoor + BendingSlope * dZ; + float rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); + return rAtAbsorberEnd; +}); DECLARE_SOA_EXPRESSION_COLUMN(Pt, pt, float, nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) * nsqrt(ntan(aod::muon::thetaX) * ntan(aod::muon::thetaX) + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, -1.0f * ntan(aod::muon::thetaX) * nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, -1.0f * ntan(aod::muon::thetaY) * nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); @@ -351,6 +361,7 @@ DECLARE_SOA_TABLE_FULL(StoredMuons, "Muons", "AOD", "MUON", muon::Chi2, muon::Chi2MatchTrigger, muon::Eta<muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY>, muon::Phi<muon::ThetaX, muon::ThetaY>, + muon::RAtAbsorberEnd<muon::BendingCoor, muon::NonBendingCoor, muon::ThetaX, muon::ThetaY, muon::ZMu>, muon::Charge<muon::InverseBendingMomentum>); DECLARE_SOA_EXTENDED_TABLE(Muons, StoredMuons, "MUON", From ea71f25364722d249b2be5f473fc5329708ff7ed Mon Sep 17 00:00:00 2001 From: Gian Michele Innocenti <gminnocen@gmail.com> Date: Sun, 20 Sep 2020 09:54:58 +0200 Subject: [PATCH 0694/1751] Minor changes to debug histograms (#4394) --- Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 6 ------ Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 10 +++++++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index a8116701e9902..aff6ee0ed161d 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -41,9 +41,6 @@ struct HFCandidateCreator2Prong { Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 100, -0.1, 0.1)}; - OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 100, -0.1, 0.1)}; OutputObj<TH1F> hmass2{TH1F("hmass2", "2-track inv mass", 500, 0., 5.0)}; double massPi = RecoDecay::getMassPDG(kPiPlus); @@ -119,9 +116,6 @@ struct HFCandidateCreator2Prong { // fill histograms if (b_dovalplots) { - hvtx_x_out->Fill(secondaryVertex[0]); - hvtx_y_out->Fill(secondaryVertex[1]); - hvtx_z_out->Fill(secondaryVertex[2]); hmass2->Fill(massPiK); hmass2->Fill(massKPi); } diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 8905afb53bb37..9ab180e1b2908 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -85,8 +85,12 @@ struct HFTrackIndexSkimsCreator { Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min mass dplus presel"}; Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; + + OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 1000, -2.0, 2.0)}; + OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 1000, -2.0, 2.0)}; + OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 1000, -10.0, 10.0)}; OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; - OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; + OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 1.6, 2.1)}; Filter filterSelectTracks = aod::seltrack::issel == 1; using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>>; @@ -160,6 +164,7 @@ struct HFTrackIndexSkimsCreator { array<float, 3> pvec1; df.getTrack(0).getPxPyPzGlo(pvec0); df.getTrack(1).getPxPyPzGlo(pvec1); + const auto& secondaryVertex = df.getPCACandidate(); // calculate invariant masses auto arrMom = array{pvec0, pvec1}; @@ -169,6 +174,9 @@ struct HFTrackIndexSkimsCreator { if (b_dovalplots) { hmass2->Fill(mass2PiK); hmass2->Fill(mass2KPi); + hvtx_x_out->Fill(secondaryVertex[0]); + hvtx_y_out->Fill(secondaryVertex[1]); + hvtx_z_out->Fill(secondaryVertex[2]); } // fill table row From 840bbbbd1637cb448087328e4cf54f9f4e560593 Mon Sep 17 00:00:00 2001 From: mfasel <markus.fasel@cern.ch> Date: Fri, 18 Sep 2020 14:57:12 +0200 Subject: [PATCH 0695/1751] [EMCAL-534] Skip SOX raw headers Skip SOX raw headers which do not contain any payload. --- Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx index 418b6261713ae..859b8454d1a1f 100644 --- a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx @@ -92,11 +92,18 @@ void RawReaderMemory::nextPage(bool doResetPayload) try { mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); RDHDecoder::printRDH(mRawHeader); + if (RDHDecoder::getOffsetToNext(mRawHeader) == RDHDecoder::getHeaderSize(mRawHeader)) { + // No Payload - jump to next rawheader + // This will eventually move, depending on whether for events without payload in the SRU we send the RCU trailer + mCurrentPosition += RDHDecoder::getHeaderSize(mRawHeader); + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + RDHDecoder::printRDH(mRawHeader); + } mRawHeaderInitialized = true; } catch (...) { throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_DECODING); } - if (mCurrentPosition + RDHDecoder::getMemorySize(mRawHeader) >= mRawMemoryBuffer.size()) { + if (mCurrentPosition + RDHDecoder::getMemorySize(mRawHeader) > mRawMemoryBuffer.size()) { // Payload incomplete throw RawDecodingError(RawDecodingError::ErrorType_t::PAYLOAD_DECODING); } else { From 19b763dd23774449a449cc9c794cc02ecf66f2d3 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Mon, 21 Sep 2020 09:12:31 +0200 Subject: [PATCH 0696/1751] Streamlining definition and reading of tables (#4369) --- Framework/Core/CMakeLists.txt | 1 + .../include/Framework/AnalysisDataModel.h | 16 +- .../Core/include/Framework/DataAllocator.h | 1 - Framework/Core/src/AODReaderHelpers.cxx | 192 +++--------------- .../Core/src/AnalysisDataModelHelpers.cxx | 70 +++++++ Framework/Core/src/AnalysisDataModelHelpers.h | 21 ++ Framework/Core/src/CommonDataProcessors.cxx | 7 + Framework/Core/src/DataInputDirector.cxx | 9 +- Framework/Core/src/TableTreeHelpers.cxx | 4 +- Framework/Core/src/WorkflowHelpers.cxx | 59 ++++-- 10 files changed, 180 insertions(+), 200 deletions(-) create mode 100644 Framework/Core/src/AnalysisDataModelHelpers.cxx create mode 100644 Framework/Core/src/AnalysisDataModelHelpers.h diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 1e0bbb7fa90bf..d08fae78bf48d 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -28,6 +28,7 @@ o2_add_library(Framework src/ASoA.cxx ${GUI_SOURCES} src/AnalysisHelpers.cxx + src/AnalysisDataModelHelpers.cxx src/BoostOptionsRetriever.cxx src/ChannelConfigurationPolicy.cxx src/ChannelMatching.cxx diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 1c765aad91018..04b60e1b5ee64 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -205,7 +205,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, [](uint8_ }); } // namespace track -DECLARE_SOA_TABLE_FULL(StoredTracks, "Tracks", "AOD", "TRACKPAR", +DECLARE_SOA_TABLE_FULL(StoredTracks, "Tracks", "AOD", "TRACK:PAR", o2::soa::Index<>, track::CollisionId, track::TrackType, track::X, track::Alpha, track::Y, track::Z, track::Snp, track::Tgl, @@ -216,18 +216,18 @@ DECLARE_SOA_TABLE_FULL(StoredTracks, "Tracks", "AOD", "TRACKPAR", track::Pz<track::Signed1Pt, track::Tgl>, track::Charge<track::Signed1Pt>); -DECLARE_SOA_EXTENDED_TABLE(Tracks, StoredTracks, "TRACKPAR", +DECLARE_SOA_EXTENDED_TABLE(Tracks, StoredTracks, "TRACK:PAR", aod::track::Pt, aod::track::P, aod::track::Eta, aod::track::RawPhi); -DECLARE_SOA_TABLE_FULL(StoredTracksCov, "TracksCov", "AOD", "TRACKPARCOV", +DECLARE_SOA_TABLE_FULL(StoredTracksCov, "TracksCov", "AOD", "TRACK:PARCOV", track::SigmaY, track::SigmaZ, track::SigmaSnp, track::SigmaTgl, track::Sigma1Pt, track::RhoZY, track::RhoSnpY, track::RhoSnpZ, track::RhoTglY, track::RhoTglZ, track::RhoTglSnp, track::Rho1PtY, track::Rho1PtZ, track::Rho1PtSnp, track::Rho1PtTgl); -DECLARE_SOA_EXTENDED_TABLE(TracksCov, StoredTracksCov, "TRACKPARCOV", +DECLARE_SOA_EXTENDED_TABLE(TracksCov, StoredTracksCov, "TRACK:PARCOV", aod::track::CYY, aod::track::CZY, aod::track::CZZ, @@ -244,7 +244,7 @@ DECLARE_SOA_EXTENDED_TABLE(TracksCov, StoredTracksCov, "TRACKPARCOV", aod::track::C1PtTgl, aod::track::C1Pt21Pt2); -DECLARE_SOA_TABLE(TracksExtra, "AOD", "TRACKEXTRA", +DECLARE_SOA_TABLE(TracksExtra, "AOD", "TRACK:EXTRA", track::TPCInnerParam, track::Flags, track::ITSClusterMap, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::TRDPattern, track::ITSChi2NCl, @@ -468,7 +468,7 @@ DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, FullTracks, "fNegTrackID" DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace v0 -DECLARE_SOA_TABLE(StoredV0s, "AOD", "O2v0", o2::soa::Index<>, v0::PosTrackId, v0::NegTrackId); +DECLARE_SOA_TABLE(StoredV0s, "AOD", "V0", o2::soa::Index<>, v0::PosTrackId, v0::NegTrackId); DECLARE_SOA_TABLE(TransientV0s, "AOD", "V0INDEX", v0::CollisionId); using V0s = soa::Join<TransientV0s, StoredV0s>; @@ -481,7 +481,7 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Bachelor, bachelor, int, FullTracks, "fTracksID"); DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace cascade -DECLARE_SOA_TABLE(StoredCascades, "AOD", "O2cascade", o2::soa::Index<>, cascade::V0Id, cascade::BachelorId); +DECLARE_SOA_TABLE(StoredCascades, "AOD", "CASCADE", o2::soa::Index<>, cascade::V0Id, cascade::BachelorId); DECLARE_SOA_TABLE(TransientCascades, "AOD", "CASCADEINDEX", cascade::CollisionId); using Cascades = soa::Join<TransientCascades, StoredCascades>; @@ -503,7 +503,7 @@ DECLARE_SOA_COLUMN(BBFlag, bbFlag, uint64_t); DECLARE_SOA_COLUMN(BGFlag, bgFlag, uint64_t); } // namespace run2v0 -DECLARE_SOA_TABLE(Run2V0s, "AOD", "RUN2V0", o2::soa::Index<>, run2v0::BCId, +DECLARE_SOA_TABLE(Run2V0s, "RN2", "V0", o2::soa::Index<>, run2v0::BCId, run2v0::Adc, run2v0::Time, run2v0::Width, run2v0::MultA, run2v0::MultC, run2v0::TimeA, run2v0::TimeC, diff --git a/Framework/Core/include/Framework/DataAllocator.h b/Framework/Core/include/Framework/DataAllocator.h index 4881fc945e84c..ef7b347d0d8b8 100644 --- a/Framework/Core/include/Framework/DataAllocator.h +++ b/Framework/Core/include/Framework/DataAllocator.h @@ -133,7 +133,6 @@ class DataAllocator void* t2tr = nullptr; call_if_defined<struct TreeToTable>([&](auto* p) { auto t2t = new std::decay_t<decltype(*p)>(args...); - t2t->addAllColumns(); adopt(spec, t2t); t2tr = t2t; }); diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 9e41ec0cd72ba..0b8d90977878e 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -10,7 +10,7 @@ #include "Framework/TableTreeHelpers.h" #include "Framework/AODReaderHelpers.h" -#include "Framework/AnalysisDataModel.h" +#include "AnalysisDataModelHelpers.h" #include "DataProcessingHelpers.h" #include "ExpressionHelpers.h" #include "Framework/RootTableBuilderHelpers.h" @@ -41,105 +41,6 @@ namespace o2::framework::readers { -enum AODTypeMask : uint64_t { - None = 0, - Track = 1 << 0, - TrackCov = 1 << 1, - TrackExtra = 1 << 2, - Calo = 1 << 3, - CaloTrigger = 1 << 4, - Muon = 1 << 5, - MuonCluster = 1 << 6, - Zdc = 1 << 7, - BC = 1 << 8, - Collision = 1 << 9, - FT0 = 1 << 10, - FV0 = 1 << 11, - FDD = 1 << 12, - UnassignedTrack = 1 << 13, - Run2V0 = 1 << 14, - McCollision = 1 << 15, - McTrackLabel = 1 << 16, - McCaloLabel = 1 << 17, - McCollisionLabel = 1 << 18, - McParticle = 1 << 19, - Unknown = 1 << 20 -}; - -uint64_t getMask(header::DataDescription description) -{ - - if (description == header::DataDescription{"TRACKPAR"}) { - return AODTypeMask::Track; - } else if (description == header::DataDescription{"TRACKPARCOV"}) { - return AODTypeMask::TrackCov; - } else if (description == header::DataDescription{"TRACKEXTRA"}) { - return AODTypeMask::TrackExtra; - } else if (description == header::DataDescription{"CALO"}) { - return AODTypeMask::Calo; - } else if (description == header::DataDescription{"CALOTRIGGER"}) { - return AODTypeMask::CaloTrigger; - } else if (description == header::DataDescription{"MUON"}) { - return AODTypeMask::Muon; - } else if (description == header::DataDescription{"MUONCLUSTER"}) { - return AODTypeMask::MuonCluster; - } else if (description == header::DataDescription{"ZDC"}) { - return AODTypeMask::Zdc; - } else if (description == header::DataDescription{"BC"}) { - return AODTypeMask::BC; - } else if (description == header::DataDescription{"COLLISION"}) { - return AODTypeMask::Collision; - } else if (description == header::DataDescription{"FT0"}) { - return AODTypeMask::FT0; - } else if (description == header::DataDescription{"FV0"}) { - return AODTypeMask::FV0; - } else if (description == header::DataDescription{"FDD"}) { - return AODTypeMask::FDD; - } else if (description == header::DataDescription{"UNASSIGNEDTRACK"}) { - return AODTypeMask::UnassignedTrack; - } else if (description == header::DataDescription{"RUN2V0"}) { - return AODTypeMask::Run2V0; - } else if (description == header::DataDescription{"MCCOLLISION"}) { - return AODTypeMask::McCollision; - } else if (description == header::DataDescription{"MCTRACKLABEL"}) { - return AODTypeMask::McTrackLabel; - } else if (description == header::DataDescription{"MCCALOLABEL"}) { - return AODTypeMask::McCaloLabel; - } else if (description == header::DataDescription{"MCCOLLISLABEL"}) { - return AODTypeMask::McCollisionLabel; - } else if (description == header::DataDescription{"MCPARTICLE"}) { - return AODTypeMask::McParticle; - } else { - LOG(DEBUG) << "This is a tree of unknown type! " << description.str; - return AODTypeMask::Unknown; - } -} - -uint64_t calculateReadMask(std::vector<OutputRoute> const& routes, header::DataOrigin const&) -{ - uint64_t readMask = None; - for (auto& route : routes) { - auto concrete = DataSpecUtils::asConcreteDataTypeMatcher(route.matcher); - auto description = concrete.description; - - readMask |= getMask(description); - } - return readMask; -} - -std::vector<OutputRoute> getListOfUnknown(std::vector<OutputRoute> const& routes) -{ - - std::vector<OutputRoute> unknows; - for (auto& route : routes) { - auto concrete = DataSpecUtils::asConcreteDataTypeMatcher(route.matcher); - - if (getMask(concrete.description) == AODTypeMask::Unknown) - unknows.push_back(route); - } - return unknows; -} - AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> requested) { return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { @@ -174,9 +75,9 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> reques return o2::soa::spawner(expressions{}, original_table.get()); }; - if (description == header::DataDescription{"TRACKPAR"}) { + if (description == header::DataDescription{"TRACK:PAR"}) { outputs.adopt(Output{origin, description}, maker(o2::aod::TracksExtensionMetadata{})); - } else if (description == header::DataDescription{"TRACKPARCOV"}) { + } else if (description == header::DataDescription{"TRACK:PARCOV"}) { outputs.adopt(Output{origin, description}, maker(o2::aod::TracksCovExtensionMetadata{})); } else if (description == header::DataDescription{"MUON"}) { outputs.adopt(Output{origin, description}, maker(o2::aod::MuonsExtensionMetadata{})); @@ -206,16 +107,11 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() // get the run time watchdog auto* watchdog = new RuntimeWatchdog(options.get<int64_t>("time-limit")); - // analyze type of requested tables - uint64_t readMask = calculateReadMask(spec.outputs, header::DataOrigin{"AOD"}); - std::vector<OutputRoute> unknowns; - if (readMask & AODTypeMask::Unknown) { - unknowns = getListOfUnknown(spec.outputs); - } + // create list of requested tables + std::vector<OutputRoute> requestedTables(spec.outputs); auto counter = std::make_shared<int>(0); - return adaptStateless([readMask, - unknowns, + return adaptStateless([requestedTables, watchdog, didir](DataAllocator& outputs, ControlService& control, DeviceSpec const& device) { // check if RuntimeLimit is reached @@ -242,66 +138,36 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() return; } - auto tableMaker = [&readMask, &outputs, fi, didir](auto metadata, AODTypeMask mask, char const* treeName) { - if (readMask & mask) { + // loop over requested tables + for (auto route : requestedTables) { - auto dh = header::DataHeader(decltype(metadata)::description(), decltype(metadata)::origin(), 0); - auto reader = didir->getTreeReader(dh, fi, treeName); + // create a TreeToTable object + auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); + auto dh = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); - using table_t = typename decltype(metadata)::table_t; - if (!reader || (reader->IsInvalid())) { - LOGP(ERROR, "Requested \"{}\" tree not found in input file \"{}\"", treeName, didir->getInputFilename(dh, fi)); - } else { - auto& builder = outputs.make<TableBuilder>(Output{decltype(metadata)::origin(), decltype(metadata)::description()}); - RootTableBuilderHelpers::convertASoA<table_t>(builder, *reader); - } + auto tr = didir->getDataTree(dh, fi); + if (!tr) { + char* table; + sprintf(table, "%s/%s/%" PRIu32, concrete.origin.str, concrete.description.str, concrete.subSpec); + LOGP(ERROR, "Error while retrieving the tree for \"{}\"!", table); + return; } - }; - tableMaker(o2::aod::CollisionsMetadata{}, AODTypeMask::Collision, "O2collision"); - tableMaker(o2::aod::StoredTracksMetadata{}, AODTypeMask::Track, "O2track"); - tableMaker(o2::aod::StoredTracksCovMetadata{}, AODTypeMask::TrackCov, "O2track"); - tableMaker(o2::aod::TracksExtraMetadata{}, AODTypeMask::TrackExtra, "O2track"); - tableMaker(o2::aod::CalosMetadata{}, AODTypeMask::Calo, "O2calo"); - tableMaker(o2::aod::CaloTriggersMetadata{}, AODTypeMask::CaloTrigger, "O2calotrigger"); - tableMaker(o2::aod::StoredMuonsMetadata{}, AODTypeMask::Muon, "O2muon"); - tableMaker(o2::aod::MuonClustersMetadata{}, AODTypeMask::Muon, "O2muoncluster"); - tableMaker(o2::aod::ZdcsMetadata{}, AODTypeMask::Zdc, "O2zdc"); - tableMaker(o2::aod::BCsMetadata{}, AODTypeMask::BC, "O2bc"); - tableMaker(o2::aod::FT0sMetadata{}, AODTypeMask::FT0, "O2ft0"); - tableMaker(o2::aod::FV0sMetadata{}, AODTypeMask::FV0, "O2fv0"); - tableMaker(o2::aod::FDDsMetadata{}, AODTypeMask::FDD, "O2fdd"); - tableMaker(o2::aod::UnassignedTracksMetadata{}, AODTypeMask::UnassignedTrack, "O2unassignedtrack"); - tableMaker(o2::aod::Run2V0sMetadata{}, AODTypeMask::Run2V0, "Run2v0"); - tableMaker(o2::aod::McCollisionsMetadata{}, AODTypeMask::McCollision, "O2mccollision"); - tableMaker(o2::aod::McTrackLabelsMetadata{}, AODTypeMask::McTrackLabel, "O2mctracklabel"); - tableMaker(o2::aod::McCaloLabelsMetadata{}, AODTypeMask::McCaloLabel, "O2mccalolabel"); - tableMaker(o2::aod::McCollisionLabelsMetadata{}, AODTypeMask::McCollisionLabel, "O2mccollisionlabel"); - tableMaker(o2::aod::McParticlesMetadata{}, AODTypeMask::McParticle, "O2mcparticle"); - - // tables not included in the DataModel - if (readMask & AODTypeMask::Unknown) { - // loop over unknowns - for (auto route : unknowns) { + auto o = Output(dh); + auto& t2t = outputs.make<TreeToTable>(o, tr); - // create a TreeToTable object - auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); - auto dh = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); - - auto tr = didir->getDataTree(dh, fi); - if (!tr) { - char* table; - sprintf(table, "%s/%s/%" PRIu32, concrete.origin.str, concrete.description.str, concrete.subSpec); - LOGP(ERROR, "Error while retrieving the tree for \"{}\"!", table); - return; + // add branches to read + auto colnames = aod::datamodel::getColumnNames(dh); + if (colnames.size() == 0) { + t2t.addAllColumns(); + } else { + for (auto colname : colnames) { + t2t.addColumn(colname.c_str()); } - - auto o = Output(dh); - auto& t2t = outputs.make<TreeToTable>(o, tr); - - // fill the table - t2t.fill(); } + + // fill the table + t2t.fill(); } }); })}; diff --git a/Framework/Core/src/AnalysisDataModelHelpers.cxx b/Framework/Core/src/AnalysisDataModelHelpers.cxx new file mode 100644 index 0000000000000..b089ebe8f68d0 --- /dev/null +++ b/Framework/Core/src/AnalysisDataModelHelpers.cxx @@ -0,0 +1,70 @@ +// 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 "AnalysisDataModelHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/StringHelpers.h" +#include "Framework/Logger.h" +#include <boost/algorithm/string.hpp> + +namespace o2::aod::datamodel +{ +std::string getTreeName(header::DataHeader dh) +{ + std::string description = std::string(dh.dataDescription.str); + std::string origin = std::string(dh.dataOrigin.str); + + // lower case of first part of description + auto found = description.find_first_of(":"); + std::string treeName = boost::algorithm::to_lower_copy(description).substr(0, found); + + // add prefix according to origin + if (origin == "AOD") { + treeName = "O2" + treeName; + } else if (origin == "RN2") { + treeName = "Run2" + treeName; + } + + // exceptions from this + if (origin == "AOD" && description == "MCCOLLISLABEL") { + treeName = "O2mccollisionlabel"; + } + + return treeName; +} + +template <typename... C> +static constexpr auto columnNamesTrait(framework::pack<C...>) +{ + return std::vector<std::string>{C::columnLabel()...}; +} + +std::vector<std::string> getColumnNames(header::DataHeader dh) +{ + auto description = std::string(dh.dataDescription.str); + auto origin = std::string(dh.dataOrigin.str); + + // get column names + // AOD / RN2 + if (origin == "AOD") { + if (description == "TRACK:PAR") { + return columnNamesTrait(typename StoredTracksMetadata::table_t::persistent_columns_t{}); + } else if (description == "TRACK:PARCOV") { + return columnNamesTrait(typename StoredTracksCovMetadata::table_t::persistent_columns_t{}); + } else if (description == "TRACK:EXTRA") { + return columnNamesTrait(typename TracksExtraMetadata::table_t::persistent_columns_t{}); + } + } + + // default: column names = {} + return std::vector<std::string>({}); +} + +} // namespace o2::aod::datamodel diff --git a/Framework/Core/src/AnalysisDataModelHelpers.h b/Framework/Core/src/AnalysisDataModelHelpers.h new file mode 100644 index 0000000000000..59f69782c845c --- /dev/null +++ b/Framework/Core/src/AnalysisDataModelHelpers.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 O2_FRAMEWORK_ANALYSISDATAMODELHELPERS_H_ +#define O2_FRAMEWORK_ANALYSISDATAMODELHELPERS_H_ + +#include "Framework/AnalysisDataModel.h" +#include "Headers/DataHeader.h" + +namespace o2::aod::datamodel +{ +std::string getTreeName(header::DataHeader dh); +std::vector<std::string> getColumnNames(header::DataHeader dh); +} // namespace o2::aod::datamodel +#endif // O2_FRAMEWORK_ANALYSISDATAMODELHELPERS_H_ diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 247876809185e..a18d49c07f7eb 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -460,6 +460,13 @@ DataProcessorSpec // get the TableConsumer and corresponding arrow table auto s = pc.inputs().get<TableConsumer>(ref.spec->binding); auto table = s->asArrowTable(); + if (!table->Validate().ok()) { + LOGP(ERROR, "The table \"{}\" is not valid and will not be saved!", dh->description.str); + continue; + } else if (table->num_rows() <= 0) { + LOGP(WARNING, "The table \"{}\" is empty and will not be saved!", dh->description.str); + continue; + } // loop over all DataOutputDescriptors // a table can be saved in multiple ways diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 49eb16cea57b5..520ecaf6a132f 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -10,6 +10,7 @@ #include "Framework/DataInputDirector.h" #include "Framework/DataDescriptorQueryBuilder.h" #include "Framework/Logger.h" +#include "AnalysisDataModelHelpers.h" #include "rapidjson/document.h" #include "rapidjson/prettywriter.h" @@ -457,24 +458,24 @@ std::string DataInputDirector::getInputFilename(header::DataHeader dh, int count TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter) { - const char* treename; + std::string treename; TTree* tree = nullptr; auto didesc = getDataInputDescriptor(dh); if (didesc) { // if match then use filename and treename from DataInputDescriptor - treename = didesc->treename.c_str(); + treename = didesc->treename; } else { // if NOT match then use // . filename from defaultDataInputDescriptor // . treename from DataHeader didesc = mdefaultDataInputDescriptor; - treename = dh.dataDescription.str; + treename = aod::datamodel::getTreeName(dh); } auto file = didesc->getInputFile(counter); if (file) { - tree = (TTree*)file->Get(treename); + tree = (TTree*)file->Get(treename.c_str()); if (!tree) { throw std::runtime_error(fmt::format(R"(Couldn't get TTree "{}" from "{}")", treename, file->GetName())); } diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 76776141befac..9e185d787957e 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -379,10 +379,10 @@ ColumnIterator::ColumnIterator(TTreeReader* reader, const char* colname) LOGP(FATAL, "Can not locate tree!"); return; } - //tree->Print(); + auto br = tree->GetBranch(colname); if (!br) { - LOGP(FATAL, "Can not locate branch {}", colname); + LOGP(WARNING, "Can not locate branch {}", colname); return; } mColumnName = colname; diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 0678ce75e246c..9f35f1bd7a7e3 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -128,8 +128,6 @@ void addMissingOutputsToReader(std::vector<OutputSpec> const& providedOutputs, return DataSpecUtils::match(requested, provided); }; }; - auto last = std::unique(requestedInputs.begin(), requestedInputs.end()); - requestedInputs.erase(last, requestedInputs.end()); for (InputSpec const& requested : requestedInputs) { auto provided = std::find_if(providedOutputs.begin(), providedOutputs.end(), @@ -138,6 +136,14 @@ void addMissingOutputsToReader(std::vector<OutputSpec> const& providedOutputs, if (provided != providedOutputs.end()) { continue; } + + auto inList = std::find_if(publisher.outputs.begin(), + publisher.outputs.end(), + matchingOutputFor(requested)); + if (inList != publisher.outputs.end()) { + continue; + } + auto concrete = DataSpecUtils::asConcreteDataMatcher(requested); publisher.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec}); } @@ -267,6 +273,9 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext if (DataSpecUtils::partialMatch(input, header::DataOrigin{"AOD"})) { requestedAODs.emplace_back(input); } + if (DataSpecUtils::partialMatch(input, header::DataOrigin{"RN2"})) { + requestedAODs.emplace_back(input); + } if (DataSpecUtils::partialMatch(input, header::DataOrigin{"DYN"})) { if (std::find_if(requestedDYNs.begin(), requestedDYNs.end(), [&](InputSpec const& spec) { return input.binding == spec.binding; }) == requestedDYNs.end()) { requestedDYNs.emplace_back(input); @@ -279,6 +288,8 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext auto& output = processor.outputs[oi]; if (DataSpecUtils::partialMatch(output, header::DataOrigin{"AOD"})) { providedAODs.emplace_back(output); + } else if (DataSpecUtils::partialMatch(output, header::DataOrigin{"RN2"})) { + providedAODs.emplace_back(output); } else if (DataSpecUtils::partialMatch(output, header::DataOrigin{"ATSK"})) { providedOutputObj.emplace_back(output); auto it = std::find_if(outObjMap.begin(), outObjMap.end(), [&](auto&& x) { return x.first == hash; }); @@ -362,8 +373,8 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext /// . dangling, not AOD - getGlobalFileSink /// // First analyze all ouputs - // outputtypes = isAOD*2 + isdangling*1 + 0 - auto [outputsInputs, outputtypes] = analyzeOutputs(workflow); + // outputTypes = isAOD*2 + isdangling*1 + 0 + auto [OutputsInputs, outputTypes] = analyzeOutputs(workflow); // file sink for any AOD output extraSpecs.clear(); @@ -371,13 +382,13 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select outputs of type AOD std::vector<InputSpec> outputsInputsAOD; std::vector<bool> isdangling; - for (auto ii = 0u; ii < outputsInputs.size(); ii++) { - if ((outputtypes[ii] & 2) == 2) { + for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { + if ((outputTypes[ii] & 2) == 2) { // temporarily also request to be dangling - if ((outputtypes[ii] & 1) == 1) { - outputsInputsAOD.emplace_back(outputsInputs[ii]); - isdangling.emplace_back((outputtypes[ii] & 1) == 1); + if ((outputTypes[ii] & 1) == 1) { + outputsInputsAOD.emplace_back(OutputsInputs[ii]); + isdangling.emplace_back((outputTypes[ii] & 1) == 1); } } } @@ -394,9 +405,9 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select dangling outputs which are not of type AOD std::vector<InputSpec> outputsInputsDangling; - for (auto ii = 0u; ii < outputsInputs.size(); ii++) { - if ((outputtypes[ii] & 1) == 1 && (outputtypes[ii] & 2) == 0) - outputsInputsDangling.emplace_back(outputsInputs[ii]); + for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { + if ((outputTypes[ii] & 1) == 1 && (outputTypes[ii] & 2) == 0) + outputsInputsDangling.emplace_back(OutputsInputs[ii]); } std::vector<InputSpec> unmatched; @@ -733,9 +744,9 @@ std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers:: outputs.reserve(totalOutputs); std::vector<InputSpec> results; - std::vector<unsigned char> outputtypes; + std::vector<unsigned char> outputTypes; results.reserve(totalOutputs); - outputtypes.reserve(totalOutputs); + outputTypes.reserve(totalOutputs); /// Prepare an index to do the iterations quickly. for (size_t wi = 0, we = workflow.size(); wi != we; ++wi) { @@ -753,11 +764,15 @@ std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers:: auto& outputSpec = workflow[output.workflowId].outputs[output.id]; // compute output type - unsigned char outputtype = 0; + unsigned char outputType = 0; // is AOD? if (DataSpecUtils::partialMatch(outputSpec, header::DataOrigin("AOD"))) { - outputtype += 2; + outputType += 2; + } + // is RN2? + if (DataSpecUtils::partialMatch(outputSpec, header::DataOrigin("RN2"))) { + outputType += 2; } // is dangling output? @@ -775,10 +790,10 @@ std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers:: } } if (!matched) { - outputtype += 1; + outputType += 1; } - // update results and outputtypes + // update results and outputTypes auto input = DataSpecUtils::matchingInput(outputSpec); char buf[64]; input.binding = (snprintf(buf, 63, "output_%zu_%zu", output.workflowId, output.id), buf); @@ -786,23 +801,23 @@ std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers:: // make sure that entries are unique if (std::find(results.begin(), results.end(), input) == results.end()) { results.emplace_back(input); - outputtypes.emplace_back(outputtype); + outputTypes.emplace_back(outputType); } } // make sure that results is unique - return std::make_tuple(results, outputtypes); + return std::make_tuple(results, outputTypes); } std::vector<InputSpec> WorkflowHelpers::computeDanglingOutputs(WorkflowSpec const& workflow) { - auto [OutputsInputs, outputtypes] = analyzeOutputs(workflow); + auto [OutputsInputs, outputTypes] = analyzeOutputs(workflow); std::vector<InputSpec> results; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { - if ((outputtypes[ii] & 1) == 1) { + if ((outputTypes[ii] & 1) == 1) { results.emplace_back(OutputsInputs[ii]); } } From 8ecd30fc27befd796dc5add56a2b303fe38a6f83 Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Mon, 21 Sep 2020 09:54:54 +0200 Subject: [PATCH 0697/1751] [QC-403] Protect pendingInfoRegions from concurrent access (#4371) --- Framework/Core/include/Framework/DataProcessingDevice.h | 2 ++ Framework/Core/src/DataProcessingDevice.cxx | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index 84cd9f31b9077..cdb755327d540 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -28,6 +28,7 @@ #include <fairmq/FairMQParts.h> #include <memory> +#include <mutex> namespace o2::framework { @@ -129,6 +130,7 @@ class DataProcessingDevice : public FairMQDevice uint64_t mBeginIterationTimestamp = 0; /// The timestamp of when the current ConditionalRun was started DataProcessingStats mStats; /// Stats about the actual data processing. std::vector<FairMQRegionInfo> mPendingRegionInfos; /// A list of the region infos not yet notified. + std::mutex mRegionInfoMutex; enum TerminationPolicy mErrorPolicy = TerminationPolicy::WAIT; /// What to do when an error arises bool mWasActive = false; /// Whether or not the device was active at last iteration. }; diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index e555786bee572..0d7f06d3b561f 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -274,7 +274,8 @@ void on_signal_callback(uv_signal_t* handle, int signum) void DataProcessingDevice::InitTask() { for (auto& channel : fChannels) { - channel.second.at(0).Transport()->SubscribeToRegionEvents([& pendingRegionInfos = mPendingRegionInfos](FairMQRegionInfo info) { + channel.second.at(0).Transport()->SubscribeToRegionEvents([& pendingRegionInfos = mPendingRegionInfos, ®ionInfoMutex = mRegionInfoMutex](FairMQRegionInfo info) { + std::lock_guard<std::mutex> lock(regionInfoMutex); LOG(debug) << ">>> Region info event" << info.event; LOG(debug) << "id: " << info.id; LOG(debug) << "ptr: " << info.ptr; From 60f34a58f9183cf9c846fad91d2abc35bbb8247c Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 21 Sep 2020 11:24:46 +0200 Subject: [PATCH 0698/1751] fixing merging for good (#4400) --- Analysis/Core/src/CorrelationContainer.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 9f6619b858c73..18e679e37c015 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -517,6 +517,7 @@ Long64_t CorrelationContainer::Merge(TCollection* list) mTriggerHist->Merge(lists[1]); mTrackHistEfficiency->Merge(lists[2]); + mEventCount->Merge(lists[3]); for (UInt_t i = 0; i < kMaxLists; i++) delete lists[i]; From 0b0313fb2c39dad6e2c36555068daceb0edcb422 Mon Sep 17 00:00:00 2001 From: dsekihat <daiki.sekihata@cern.ch> Date: Mon, 21 Sep 2020 18:41:27 +0900 Subject: [PATCH 0699/1751] PWGDQ: quick fix filter bit for e/mu (#4396) --- Analysis/Core/include/Analysis/VarManager.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index c95c307b56c40..9e4342e62b98c 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -379,18 +379,21 @@ void VarManager::FillPair(T const& t1, T const& t2, float* values) if (!values) values = fgValues; - float mass1; - float mass2; + float mass1 = fgkElectronMass; + float mass2 = fgkElectronMass; - if (t1.filteringFlags() > 0) - mass1 = fgkElectronMass; - else - mass1 = fgkMuonMass; + bool isMuon1 = t1.filteringFlags() & (1 << 0); + bool isMuon2 = t2.filteringFlags() & (1 << 0); - if (t1.filteringFlags() > 0) - mass2 = fgkElectronMass; + if (isMuon1) + mass1 = fgkMuonMass; else + mass1 = fgkElectronMass; + + if (isMuon2) mass2 = fgkMuonMass; + else + mass2 = fgkElectronMass; ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), mass1); ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), mass2); From a3816d0e46ad739cb4cd42b9f2813b59f6b4d50b Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 21 Sep 2020 12:40:07 +0200 Subject: [PATCH 0700/1751] fixed bug with filter/grouping interaction (#4399) --- Analysis/Tutorials/src/associatedExample.cxx | 3 ++- Framework/Core/include/Framework/AnalysisTask.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Analysis/Tutorials/src/associatedExample.cxx b/Analysis/Tutorials/src/associatedExample.cxx index cbb44589fc32e..6ac8e1225467c 100644 --- a/Analysis/Tutorials/src/associatedExample.cxx +++ b/Analysis/Tutorials/src/associatedExample.cxx @@ -74,7 +74,8 @@ struct BTask { struct TTask { using myCol = soa::Join<aod::Collisions, aod::CollisionsExtra>; - void process(soa::Join<aod::Collisions, aod::CollisionsExtra>::iterator const& col, aod::Tracks const& tracks) + expressions::Filter multfilter = aod::collision::mult > 10; + void process(soa::Filtered<soa::Join<aod::Collisions, aod::CollisionsExtra>>::iterator const& col, aod::Tracks const& tracks) { LOGF(INFO, "[direct] ID: %d; %d == %d", col.globalIndex(), col.mult(), tracks.size()); if (tracks.size() > 0) { diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 762a97c00cb91..67bc87a3bc4f2 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -240,7 +240,7 @@ struct AnalysisDataProcessorBuilder { if (hasIndexTo<std::decay_t<G>>(typename xt::persistent_columns_t{})) { auto result = o2::framework::sliceByColumn(indexColumnName.c_str(), x.asArrowTable(), - static_cast<int32_t>(gt.size()), + static_cast<int32_t>(gt.tableSize()), &groups[index], &offsets[index]); if (result.ok() == false) { From 287bc531f264ed82780db458eea590507a1ec49f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 20 Sep 2020 02:09:04 +0200 Subject: [PATCH 0701/1751] Major change in ITS/MFT raw data encoding/decoding acc. DataFormat 6.09 * Fix cables mapping and lane patterns * Account for modidied header and trailed words * Add diagnostic word after RDH with stop (its absence tolerated by decoding) --- .../ITSMFT/ITS/simulation/src/digi2raw.cxx | 4 +- .../ITSMFTReconstruction/ChipMappingITS.h | 9 +- .../ITSMFTReconstruction/DecodingStat.h | 6 +- .../include/ITSMFTReconstruction/GBTLink.h | 72 +++++++++++----- .../include/ITSMFTReconstruction/GBTWord.h | 85 ++++++++++++++----- .../ITSMFTReconstruction/RawPixelReader.h | 6 +- .../reconstruction/src/ChipMappingITS.cxx | 14 ++- .../common/reconstruction/src/GBTLink.cxx | 64 ++++++++++++-- .../src/ITSMFTReconstructionLinkDef.h | 3 + .../include/ITSMFTSimulation/MC2RawEncoder.h | 6 +- .../common/simulation/src/MC2RawEncoder.cxx | 49 ++++++++--- Detectors/Raw/README.md | 8 +- .../Raw/include/DetectorsRaw/RawFileWriter.h | 28 +++++- Detectors/Raw/src/RawFileWriter.cxx | 40 +++++++-- 14 files changed, 306 insertions(+), 88 deletions(-) diff --git a/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx b/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx index 4514ba3e2c4c7..539165a1db713 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx @@ -250,10 +250,10 @@ void setupLinks(o2::itsmft::MC2RawEncoder<MAP>& m2r, std::string_view outDir, st if (acceptRU && lnkAs[il]) { nLinks++; auto& ru = *m2r.getRUDecode(ruID); - uint32_t lanes = mp.getCablesOnRUType(ru.ruInfo->ruType); // lanes patter of this RU + uint32_t lanes = mp.getCablesOnRUType(ru.ruInfo->ruType); // lanes pattern of this RU ru.links[il] = m2r.addGBTLink(); auto link = m2r.getGBTLink(ru.links[il]); - link->lanes = lanes & ((0x1 << lnkAs[il]) - 1) << (accL); + link->lanes = lanes & (((0x1 << lnkAs[il]) - 1) << (accL)); // RS FIXME link->idInCRU = linkID; link->cruID = cruID; link->feeID = mp.RUSW2FEEId(ruID, il); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h index 1956756505de2..b7ff106324f3d 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h @@ -166,7 +166,7 @@ class ChipMappingITS int getNCablesOnRUType(int ruType) const { return NCablesPerStaveSB[ruType]; } ///< get pattern of lanes on the RU served by a given RU type - int getCablesOnRUType(int ruType) const { return CablesOnStaveSB[ruType]; } + int getCablesOnRUType(int ruType) const { return mCablesOnStaveSB[ruType]; } ///< get number of chips served by RU of given type (i.e. RU type for ITS) int getNChipsOnRUType(int ruType) const { return NChipsPerStaveSB[ruType]; } @@ -252,11 +252,6 @@ class ChipMappingITS NCablesPerModule[MB] * NModulesPerStaveSB[MB], NCablesPerModule[OB] * NModulesPerStaveSB[OB]}; - ///< pattern of cables per stave of sub-barrel - static constexpr std::array<int, NSubB> CablesOnStaveSB = {(0x1 << NCablesPerModule[IB] * NModulesPerStaveSB[IB]) - 1, - (0x1 << NCablesPerModule[MB] * NModulesPerStaveSB[MB]) - 1, - (0x1 << NCablesPerModule[OB] * NModulesPerStaveSB[OB]) - 1}; - ///< number of chips per sub-barrel static constexpr std::array<int, NSubB> NChipsSB = {NChipsPerStaveSB[IB] * NStavesSB[IB], NChipsPerStaveSB[MB] * NStavesSB[MB], @@ -288,6 +283,8 @@ class ChipMappingITS std::vector<uint8_t> mCableHW2Pos[NSubB]; ///< table of cables positions in the ActiveLanes mask for each RU type std::vector<uint8_t> mCableHWFirstChip[NSubB]; ///< 1st chip of module (relative to the 1st chip of the stave) served by each cable + std::array<int, NSubB> mCablesOnStaveSB = {0}; ///< pattern of cables per stave of sub-barrel + ClassDefNV(ChipMappingITS, 1); }; } // namespace itsmft diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h index c6f5cebb672a8..4c759ee6dce4d 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h @@ -109,12 +109,13 @@ struct GBTLinkDecodingStat { ErrInvalidActiveLanes, // active lanes pattern conflicts with expected for given RU type ErrPacketCounterJump, // jump in RDH.packetCounter ErrPacketDoneMissing, // packet done is missing in the trailer while CRU page is not over + ErrMissingDiagnosticWord, // missing diagnostic word after RDH with stop NErrorsDefined }; static constexpr std::array<std::string_view, NErrorsDefined> ErrNames = { "Page data not start with expected RDH", // ErrNoRDHAtStart "New HB/trigger page started w/o stopping previous one", // ErrPageNotStopped - "Page with RDH.stop is not empty", // ErrStopPageNotEmpty + "Page with RDH.stop does not contain diagnostic word only", // ErrStopPageNotEmpty "RDH page counters for the same RU/trigger are not continuous", // ErrPageCounterDiscontinuity "RDH and GBT header page counters are not consistent", // ErrRDHvsGBTHPageCnt "GBT trigger word was expected but not found", // ErrMissingGBTTrigger @@ -128,7 +129,8 @@ struct GBTLinkDecodingStat { "Cable data does not start with chip header or empty chip", // ErrCableDataHeadWrong "Active lanes pattern conflicts with expected for given RU type", // ErrInvalidActiveLanes "Jump in RDH_packetCounter", // ErrPacketCounterJump - "Packet done is missing in the trailer while CRU page is not over" // ErrPacketDoneMissing + "Packet done is missing in the trailer while CRU page is not over", // ErrPacketDoneMissing + "Missing diagnostic GBT word after RDH with stop" // ErrMissingDiagnosticWord }; uint32_t ruLinkID = 0; // Link ID within RU diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h index 85e05b6db5227..cc2b0f915f28f 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h @@ -123,7 +123,9 @@ struct GBTLink { void discardData() { rawData.setDone(); } void printTrigger(const GBTTrigger* gbtTrg); void printHeader(const GBTDataHeader* gbtH); + void printHeader(const GBTDataHeaderL* gbtH); void printTrailer(const GBTDataTrailer* gbtT); + void printDiagnostic(const GBTDiagnostic* gbtD); bool nextCRUPage(); #ifndef _RAW_READER_ERROR_CHECKS_ // define dummy inline check methods, will be compiled out @@ -135,22 +137,26 @@ struct GBTLink { ErrorType checkErrorsRDHStopPageEmpty(const RDH& rdh) const { return NoError; } ErrorType checkErrorsTriggerWord(const GBTTrigger* gbtTrg) const { return NoError; } ErrorType checkErrorsHeaderWord(const GBTDataHeader* gbtH) const { return NoError; } + ErrorType checkErrorsHeaderWord(const GBTDataHeaderL* gbtH) const { return NoError; } ErrorType checkErrorsActiveLanes(int cables) const { return NoError; } ErrorType checkErrorsGBTData(int cablePos) const { return NoError; } ErrorType checkErrorsTrailerWord(const GBTDataTrailer* gbtT) const { return NoError; } ErrorType checkErrorsPacketDoneMissing(const GBTDataTrailer* gbtT, bool notEnd) const { return NoError; } ErrorType checkErrorsLanesStops() const { return NoError; } + ErrorType checkErrorsDiagnosticWord(const GBTDiagnostic* gbtD) const { return NoError; } #else ErrorType checkErrorsRDH(const RDH& rdh); ErrorType checkErrorsRDHStop(const RDH& rdh); ErrorType checkErrorsRDHStopPageEmpty(const RDH& rdh); ErrorType checkErrorsTriggerWord(const GBTTrigger* gbtTrg); ErrorType checkErrorsHeaderWord(const GBTDataHeader* gbtH); + ErrorType checkErrorsHeaderWord(const GBTDataHeaderL* gbtH); ErrorType checkErrorsActiveLanes(int cables); ErrorType checkErrorsGBTData(int cablePos); ErrorType checkErrorsTrailerWord(const GBTDataTrailer* gbtT); ErrorType checkErrorsPacketDoneMissing(const GBTDataTrailer* gbtT, bool notEnd); ErrorType checkErrorsLanesStops(); + ErrorType checkErrorsDiagnosticWord(const GBTDiagnostic* gbtD); #endif ClassDefNV(GBTLink, 1); @@ -179,16 +185,51 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) } GBTLINK_DECODE_ERRORCHECK(checkErrorsRDH(*rdh)); // make sure we are dealing with RDH GBTLINK_DECODE_ERRORCHECK(checkErrorsRDHStop(*rdh)); // if new HB starts, the lastRDH must have stop - GBTLINK_DECODE_ERRORCHECK(checkErrorsRDHStopPageEmpty(*rdh)); // end of HBF should be an empty page with stop + // GBTLINK_DECODE_ERRORCHECK(checkErrorsRDHStopPageEmpty(*rdh)); // end of HBF should be an empty page with stop lastRDH = rdh; statistics.nPackets++; + dataOffset += sizeof(RDH); + auto psz = RDHUtils::getMemorySize(*rdh); + if (psz == sizeof(RDH)) { + continue; // filter out empty page + } + if (format == NewFormat && RDHUtils::getStop(*rdh)) { // only diagnostic word can be present after the stop + auto gbtDiag = reinterpret_cast<const GBTDiagnostic*>(&currRawPiece->data[dataOffset]); + if (verbosity >= VerboseHeaders) { + printDiagnostic(gbtDiag); + } + GBTLINK_DECODE_ERRORCHECK(checkErrorsDiagnosticWord(gbtDiag)); + dataOffset += RDHUtils::getOffsetToNext(*rdh) - sizeof(RDH); + continue; + } + + // data must start with the GBTHeader + auto gbtH = reinterpret_cast<const GBTDataHeader*>(&currRawPiece->data[dataOffset]); // process GBT header + dataOffset += GBTPaddedWordLength; + if (verbosity >= VerboseHeaders) { + printHeader(gbtH); + } + if (format == OldFormat) { + GBTLINK_DECODE_ERRORCHECK(checkErrorsHeaderWord(reinterpret_cast<const GBTDataHeaderL*>(gbtH))); + lanesActive = reinterpret_cast<const GBTDataHeaderL*>(gbtH)->activeLanesL; // TODO do we need to update this for every page? + } else { + GBTLINK_DECODE_ERRORCHECK(checkErrorsHeaderWord(gbtH)); + lanesActive = gbtH->activeLanes; // TODO do we need to update this for every page? + } + + GBTLINK_DECODE_ERRORCHECK(checkErrorsActiveLanes(chmap.getCablesOnRUType(ruPtr->ruInfo->ruType))); + if (format == OldFormat && reinterpret_cast<const GBTDataHeaderL*>(gbtH)->packetIdx == 0) { // reset flags in case of 1st page of new ROF (old format: judge by RDH) + lanesStop = 0; + lanesWithData = 0; + } + continue; } ruPtr->nCables = ruPtr->ruInfo->nCables; // RSTODO is this needed? TOREMOVE - // data must start with GBT trigger word (unless we work with old format) + // then we expect GBT trigger word (unless we work with old format) const GBTTrigger* gbtTrg = nullptr; if (format == NewFormat) { gbtTrg = reinterpret_cast<const GBTTrigger*>(&currRawPiece->data[dataOffset]); // process GBT trigger @@ -197,24 +238,13 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) printTrigger(gbtTrg); } GBTLINK_DECODE_ERRORCHECK(checkErrorsTriggerWord(gbtTrg)); - } - - // next the GBTHeader must come - auto gbtH = reinterpret_cast<const GBTDataHeader*>(&currRawPiece->data[dataOffset]); // process GBT header - dataOffset += GBTPaddedWordLength; - if (verbosity >= VerboseHeaders) { - printHeader(gbtH); - } - GBTLINK_DECODE_ERRORCHECK(checkErrorsHeaderWord(gbtH)); - lanesActive = gbtH->activeLanes; // TODO do we need to update this for every page? - GBTLINK_DECODE_ERRORCHECK(checkErrorsActiveLanes(chmap.getCablesOnRUType(ruPtr->ruInfo->ruType))); - if (format == OldFormat && RDHUtils::getPageCounter(*lastRDH)) { // RSTODO reset flags in case of 1st page of new ROF (old format: judge by RDH) - lanesStop = 0; - lanesWithData = 0; - } else if (gbtH->packetIdx == 0) { // reset flags in case of 1st page of new ROF (new format: judge by header) + if (gbtTrg->noData) { // emtpy trigger + return status; + } lanesStop = 0; lanesWithData = 0; } + auto gbtD = reinterpret_cast<const o2::itsmft::GBTData*>(&currRawPiece->data[dataOffset]); while (!gbtD->isDataTrailer()) { // start reading real payload nw++; @@ -242,7 +272,9 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) GBTLINK_DECODE_ERRORCHECK(checkErrorsPacketDoneMissing(gbtT, dataOffset < currRawPiece->size)); continue; // keep reading next CRU page } - GBTLINK_DECODE_ERRORCHECK(checkErrorsLanesStops()); + if (format == OldFormat) { + GBTLINK_DECODE_ERRORCHECK(checkErrorsLanesStops()); + } // accumulate packet states statistics.packetStates[gbtT->getPacketState()]++; // before quitting, store the trigger and IR @@ -251,8 +283,8 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) ir.orbit = gbtTrg->orbit; trigger = gbtTrg->triggerType; } else { - ir = RDHUtils::getTriggerIR(lastRDH); - trigger = RDHUtils::getTriggerType(lastRDH); + ir = RDHUtils::getTriggerIR(*lastRDH); + trigger = RDHUtils::getTriggerType(*lastRDH); } return (status = DataSeen); } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h index bc0d61c93ab95..39ea345666eb8 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h @@ -29,7 +29,9 @@ constexpr uint8_t GBTFlagDataHeader = 0xe0; /// GBT payload trailer flag constexpr uint8_t GBTFlagDataTrailer = 0xf0; /// GBT trigger status word flag -constexpr uint8_t GBTFlagTrigger = 0xc0; +constexpr uint8_t GBTFlagTrigger = 0xe8; +/// GBT diagnostic status word flag +constexpr uint8_t GBTFlagDiagnostic = 0xe4; // GBT header flag in the RDH constexpr uint8_t GBTFlagRDH = 0x00; @@ -44,18 +46,24 @@ constexpr int GBTPaddedWordLength = 16; // lentgh in bytes with padding struct GBTWord { /// GBT word of 80 bits, bits 72:79 are reserver for GBT Header flag, the rest depends on specifications union { - struct { - uint64_t packetIdx : 16; /// 0:15 Index of Data Packet within trigger - uint64_t activeLanes : 28; /// 16:43 Bit map of lanes active and eligible for readout - uint64_t na0h : 20; /// 44:71 reserved - uint64_t na1h : 8; /// 44:71 reserved + // RS: packing will be needed only if some of the members cross 64 bit boundary + struct /*__attribute__((packed))*/ { + uint64_t activeLanes : 28; /// 0:27 Bit map of lanes active and eligible for readout + uint64_t na0hn : 36; /// 28:71 reserved + uint64_t na1hn : 8; /// 28:71 reserved uint64_t id : 8; /// 72:79 0xe0; Header Status Word (HSW) identifier - }; // HEADER - struct { - uint64_t lanesStops : 28; /// 0:27 Bit map of “Valid Lane stops received”, 1 bit per lane - uint64_t na0t : 4; /// 28:32 reserved - uint64_t lanesTimeout : 28; /// 32:59 Bit map of “Lane timeouts received”, 1 bit per lane - uint64_t na1t : 4; /// 60:63 reserved + }; // HEADER NEW + struct /*__attribute__((packed))*/ { + uint64_t packetIdx : 16; /// 0:15 Index of Data Packet within trigger + uint64_t activeLanesL : 28; /// 16:43 Bit map of lanes active and eligible for readout + uint64_t na0h : 20; /// 44:64 reserved + uint64_t na1h : 8; /// 64:71 reserved + // uint64_t id : 8; /// 72:79 0xe0; Header Status Word (HSW) identifier + }; // HEADER Legacy + struct /*__attribute__((packed))*/ { + uint64_t lanesStops : 28; /// 0:27 Bit map of “Valid Lane stops received”, 1 bit per lane, NOT USED + uint64_t lanesTimeout : 28; /// 28:55 Bit map of “Lane timeouts received”, 1 bit per lane, NOT USED + uint64_t na1t : 8; /// 56:63 reserved uint64_t packetDone : 1; /// 64 = 1 when current trigger packets transmission done uint64_t transmissionTimeout : 1; /// 65 = 1 if timeout while waiting for data on lanes uint64_t packetOverflow : 1; /// 66 = 1 if max number of packets reached @@ -64,7 +72,7 @@ struct GBTWord { uint64_t na2t : 3; /// 69:71 reserved // uint8_t id : 8; /// = 0xf0; Trailer Status Word (TSW) identifier }; // TRAILER - struct { + struct /*__attribute__((packed))*/ { uint64_t triggerType : 12; /// 0:11 12 lowest bits of trigger type received from CTP uint64_t internal : 1; /// 12 Used in Continuous Mode for internally generated trigger uint64_t noData : 1; /// 13 No data expected (too close to previous trigger or error) @@ -76,6 +84,10 @@ struct GBTWord { uint64_t na3tr : 6; /// 64:71 reserved // uint8_t id : 8; /// = 0xc0; Trigger Status Word (TSW) identifier }; // TRIGGER + struct /*__attribute__((packed))*/ { + uint64_t na0diag : 64; /// + // uint64_t id : 8; /// 72:79 0xe4; diagnostic word identifier + }; // HEADER Legacy uint8_t data8[16]; // 80 bits GBT word + optional padding to 128 bits uint64_t data64[2] = {0}; @@ -92,6 +104,9 @@ struct GBTWord { /// check if the GBT Header corresponds to GBT trigger word bool isTriggerWord() const { return id == GBTFlagTrigger; } + /// check if the GBT Header corresponds to Diagnostic data + bool isDiagnosticWord() const { return id == GBTFlagDiagnostic; } + /// check if the GBT Header corresponds to ITS IB data (header is combined with lanes info) bool isDataIB() const { return (id & 0xe0) == GBTFlagDataIB; } @@ -110,6 +125,23 @@ struct GBTWord { }; struct GBTDataHeader : public GBTWord { + /// Definition of ITS/MFT GBT Header: 80 bits long word + /// In CRU data it must be the 1st word of the payload + /// + /// bits 0 : 27, Active lanes pattern + /// bits 28 : 71, not used + /// bits 72 : 79, header/trailer indicator + + GBTDataHeader() { id = GBTFlagDataHeader; } + GBTDataHeader(uint32_t lanes) + { + id = GBTFlagDataHeader; + activeLanes = lanes; + } + ClassDefNV(GBTDataHeader, 1); +}; + +struct GBTDataHeaderL : public GBTWord { // legacy version /// Definition of ITS/MFT GBT Header: 80 bits long word /// In CRU data it must be the 1st word of the payload /// @@ -118,24 +150,23 @@ struct GBTDataHeader : public GBTWord { /// bits 44 : 71, not used /// bits 72 : 79, header/trailer indicator - GBTDataHeader() { id = GBTFlagDataHeader; } - GBTDataHeader(int packetID, uint32_t lanes) + GBTDataHeaderL() { id = GBTFlagDataHeader; } + GBTDataHeaderL(int packetID, uint32_t lanes) { id = GBTFlagDataHeader; - activeLanes = lanes; + activeLanesL = lanes; packetIdx = packetID; } - ClassDefNV(GBTDataHeader, 1); + ClassDefNV(GBTDataHeaderL, 1); }; struct GBTDataTrailer : public GBTWord { /// Definition of ITS/MFT GBT trailer: 80 bits long word /// In CRU data it must be the last word of the payload /// - /// bits 0 : 27, Lanes stops received - /// bits 28 : 31, not used - /// bits 32 : 59, Lane timeouts received - /// bits 60 : 63, not used + /// bits 0 : 27, Lanes stops received // not used at the moment + /// bits 28 : 55, Lane timeouts received // not used at the moment + /// bits 56 : 63, not used /// bits 64 : 71, State of GBT_Packet: /// 4: lane_timeouts, if at least 1 lane timed out /// 3: lane_starts_violation, if at least 1 lane had a start violation @@ -219,6 +250,18 @@ struct GBTData : public GBTWord { ClassDefNV(GBTData, 1); }; + +struct GBTDiagnostic : public GBTWord { + /// Definition of GBT diagnostic word + /// In CRU data it must be the only word after the RDH with stop + /// + /// bits 0 : 71, reserved + /// bits 72 : 79, diagnostic flag + + GBTDiagnostic() { id = GBTFlagDiagnostic; } + ClassDefNV(GBTDiagnostic, 1); +}; + } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h index aa7840e0ab061..c09bf6d5bac89 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h @@ -371,7 +371,7 @@ class RawPixelReader : public PixelReader link->data.ensureFreeCapacity(MaxGBTPacketBytes); link->data.addFast(reinterpret_cast<uint8_t*>(&rdh), RDHUtils::getHeaderSize(rdh)); // write RDH for current packet link->nTriggers++; // acknowledge the page, note: here we count pages, not triggers - o2::itsmft::GBTDataHeader gbtHeader(0, link->lanes); + o2::itsmft::GBTDataHeaderL gbtHeader(0, link->lanes); o2::itsmft::GBTDataTrailer gbtTrailer; // lanes will be set on closing the last page gbtHeader.packetIdx = RDHUtils::getPageCounter(rdh); @@ -780,7 +780,7 @@ class RawPixelReader : public PixelReader mDecodingStat.nPagesProcessed++; raw += RDHUtils::getHeaderSize(rdh); int nGBTWords = (RDHUtils::getMemorySize(rdh) - RDHUtils::getHeaderSize(rdh)) / mGBTWordSize - 2; // number of GBT words excluding header/trailer - auto gbtH = reinterpret_cast<const o2::itsmft::GBTDataHeader*>(raw); // process GBT header + auto gbtH = reinterpret_cast<const o2::itsmft::GBTDataHeaderL*>(raw); // process GBT header #ifdef _RAW_READER_ERROR_CHECKS_ if (mVerbose) { @@ -1049,7 +1049,7 @@ class RawPixelReader : public PixelReader raw += RDHUtils::getHeaderSize(rdh); // number of 128 b GBT words excluding header/trailer int nGBTWords = (RDHUtils::getMemorySize(rdh) - RDHUtils::getHeaderSize(rdh)) / o2::itsmft::GBTPaddedWordLength - 2; - auto gbtH = reinterpret_cast<const o2::itsmft::GBTDataHeader*>(raw); // process GBT header + auto gbtH = reinterpret_cast<const o2::itsmft::GBTDataHeaderL*>(raw); // process GBT header #ifdef _RAW_READER_ERROR_CHECKS_ if (mVerbose) { diff --git a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx index 6302f9d9b3f7c..4e78c426392ff 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx @@ -24,7 +24,6 @@ constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NModulesAlongSt constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NChipsPerModuleSB; constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NModulesPerStaveSB; constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NCablesPerStaveSB; -constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::CablesOnStaveSB; constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NStavesSB; constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NChipsPerStaveSB; @@ -88,9 +87,13 @@ ChipMappingITS::ChipMappingITS() cInfo.chipOnCable = 0; // every chip is master mCableHW2SW[IB][cInfo.cableHW] = cInfo.cableSW; mCableHW2Pos[IB][cInfo.cableHW] = cInfo.cableHWPos; + mCablesOnStaveSB[IB] |= 0x1 << cInfo.cableHWPos; // account in lanes pattern mCableHWFirstChip[IB][i] = 0; // stave and module are the same } + // [i][j] gives lane id for lowest(i=0) and highest(i=1) 7 chips of HW module (j+1) (1-4 for ML, 1-7 for OL) + const int LANEID[2][7] = {{6, 5, 4, 3, 2, 1, 0}, {0, 1, 2, 3, 4, 5, 6}}; + const int maxModulesPerStave = NModulesPerStaveSB[OB]; const int chipsOnCable = 7; for (int bid = MB; bid <= OB; bid++) { // MB and OB staves have similar layout mChipInfoEntrySB[bid] = ctrChip; @@ -108,10 +111,13 @@ ChipMappingITS::ChipMappingITS() cInfo.chipOnModuleSW = i % NChipsPerModuleSB[bid]; cInfo.chipOnModuleHW = ChipOBModSW2HW[cInfo.chipOnModuleSW]; - uint8_t connector = (hstave << 1) + (cInfo.chipOnModuleSW < (NChipsPerModuleSB[bid] / 2) ? 0 : 1); - cInfo.cableHW = (connector << 3) + (cInfo.moduleHW - 1); + bool upper7 = cInfo.chipOnModuleSW >= (NChipsPerModuleSB[bid] / 2); + + uint8_t connector = 2 * hstave + upper7; + cInfo.cableHW = (connector << 3) + LANEID[upper7][cInfo.moduleHW - 1]; cInfo.cableSW = i / chipsOnCable; - cInfo.cableHWPos = (cInfo.moduleHW - 1) + connector * (NModulesPerStaveSB[bid] / 2); + cInfo.cableHWPos = LANEID[upper7][cInfo.moduleHW - 1] + connector * maxModulesPerStave / 2; + mCablesOnStaveSB[bid] |= 0x1 << cInfo.cableHWPos; // account in lanes pattern cInfo.chipOnCable = cInfo.chipOnModuleSW % (NChipsPerModuleSB[bid] / 2); // each cable serves half module mCableHW2SW[bid][cInfo.cableHW] = cInfo.cableSW; mCableHW2Pos[bid][cInfo.cableHW] = cInfo.cableHWPos; diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index 18eee05516f20..665a68e361c34 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -82,6 +82,14 @@ void GBTLink::printHeader(const GBTDataHeader* gbtH) LOG(INFO) << "Header : Active Lanes " << LA; } +///_________________________________________________________________ +void GBTLink::printHeader(const GBTDataHeaderL* gbtH) +{ + gbtH->printX(); + std::bitset<28> LA(gbtH->activeLanesL); + LOG(INFO) << "HeaderL : Active Lanes " << LA; +} + ///_________________________________________________________________ void GBTLink::printTrailer(const GBTDataTrailer* gbtT) { @@ -90,6 +98,13 @@ void GBTLink::printTrailer(const GBTDataTrailer* gbtT) LOG(INFO) << "Trailer: Done=" << gbtT->packetDone << " Lanes TO: " << LT << " | Lanes ST: " << LS; } +///_________________________________________________________________ +void GBTLink::printDiagnostic(const GBTDiagnostic* gbtD) +{ + gbtD->printX(); + LOG(INFO) << "Diagnostic word"; +} + ///==================================================================== #ifdef _RAW_READER_ERROR_CHECKS_ @@ -98,20 +113,23 @@ void GBTLink::printTrailer(const GBTDataTrailer* gbtT) /// Check RDH correctness GBTLink::ErrorType GBTLink::checkErrorsRDH(const RDH& rdh) { + ErrorType err = NoError; if (!RDHUtils::checkRDH(rdh, true)) { statistics.errorCounts[GBTLinkDecodingStat::ErrNoRDHAtStart]++; if (verbosity >= VerboseErrors) { LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrNoRDHAtStart]; } errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrNoRDHAtStart); - return Abort; // fatal error + err = Abort; + return err; // fatal error } if (format == OldFormat && RDHUtils::getVersion(rdh) > 4) { if (verbosity >= VerboseErrors) { LOG(ERROR) << "Requested old format requires data with RDH version 3 or 4, RDH version " << RDHUtils::getVersion(rdh) << " is found"; } - return Abort; + err = Abort; + return err; } if ((RDHUtils::getPacketCounter(rdh) > packetCounter + 1) && packetCounter >= 0) { statistics.errorCounts[GBTLinkDecodingStat::ErrPacketCounterJump]++; @@ -120,10 +138,10 @@ GBTLink::ErrorType GBTLink::checkErrorsRDH(const RDH& rdh) << " : jump from " << int(packetCounter) << " to " << int(RDHUtils::getPacketCounter(rdh)); } errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrPacketCounterJump); - return Warning; + err = Warning; } packetCounter = RDHUtils::getPacketCounter(rdh); - return NoError; + return err; } ///_________________________________________________________________ @@ -148,7 +166,7 @@ GBTLink::ErrorType GBTLink::checkErrorsRDHStop(const RDH& rdh) /// Check if the RDH Stop page is empty GBTLink::ErrorType GBTLink::checkErrorsRDHStopPageEmpty(const RDH& rdh) { - if (format == NewFormat && RDHUtils::getStop(rdh) && RDHUtils::getMemorySize(rdh) != sizeof(RDH)) { + if (format == NewFormat && RDHUtils::getStop(rdh) && RDHUtils::getMemorySize(rdh) != sizeof(RDH) + sizeof(GBTDiagnostic)) { statistics.errorCounts[GBTLinkDecodingStat::ErrStopPageNotEmpty]++; if (verbosity >= VerboseErrors) { LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrStopPageNotEmpty]; @@ -179,6 +197,22 @@ GBTLink::ErrorType GBTLink::checkErrorsTriggerWord(const GBTTrigger* gbtTrg) ///_________________________________________________________________ /// Check the GBT Header word correctness GBTLink::ErrorType GBTLink::checkErrorsHeaderWord(const GBTDataHeader* gbtH) +{ + if (!gbtH->isDataHeader()) { // check header word + statistics.errorCounts[GBTLinkDecodingStat::ErrMissingGBTHeader]++; + gbtH->printX(); + if (verbosity >= VerboseErrors) { + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrMissingGBTHeader]; + } + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrMissingGBTHeader); + return Abort; + } + return NoError; +} + +///_________________________________________________________________ +/// Check the GBT Header word correctness +GBTLink::ErrorType GBTLink::checkErrorsHeaderWord(const GBTDataHeaderL* gbtH) { if (!gbtH->isDataHeader()) { // check header word statistics.errorCounts[GBTLinkDecodingStat::ErrMissingGBTHeader]++; @@ -191,7 +225,7 @@ GBTLink::ErrorType GBTLink::checkErrorsHeaderWord(const GBTDataHeader* gbtH) } int cnt = RDHUtils::getPageCounter(*lastRDH); // RSTODO: this makes sense only for old format, where every trigger has its RDH - if (format == OldFormat && gbtH->packetIdx != cnt) { + if (gbtH->packetIdx != cnt) { statistics.errorCounts[GBTLinkDecodingStat::ErrRDHvsGBTHPageCnt]++; if (verbosity >= VerboseErrors) { LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrRDHvsGBTHPageCnt] << ": diff in GBT header " @@ -224,7 +258,7 @@ GBTLink::ErrorType GBTLink::checkErrorsActiveLanes(int cbl) statistics.errorCounts[GBTLinkDecodingStat::ErrInvalidActiveLanes]++; std::bitset<32> expectL(cbl), gotL(lanesActive); if (verbosity >= VerboseErrors) { - LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrInvalidActiveLanes] + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrInvalidActiveLanes] << ' ' << gotL << " vs " << expectL << " skip page"; } errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrInvalidActiveLanes); @@ -316,4 +350,20 @@ GBTLink::ErrorType GBTLink::checkErrorsLanesStops() return err; } +///_________________________________________________________________ +/// Check diagnostic word +GBTLink::ErrorType GBTLink::checkErrorsDiagnosticWord(const GBTDiagnostic* gbtD) +{ + if (RDHUtils::getMemorySize(lastRDH) != sizeof(RDH) + sizeof(GBTDiagnostic) || !gbtD->isDiagnosticWord()) { // + statistics.errorCounts[GBTLinkDecodingStat::ErrMissingDiagnosticWord]++; + gbtD->printX(); + if (verbosity >= VerboseErrors) { + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrMissingDiagnosticWord]; + } + errorBits |= 0x1 << int(GBTLinkDecodingStat::ErrMissingDiagnosticWord); + return Abort; + } + return NoError; +} + #endif diff --git a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h index 4c84473abfcaa..c105c30d481cd 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h +++ b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h @@ -33,7 +33,10 @@ #pragma link C++ class o2::itsmft::AlpideCoder + ; #pragma link C++ class o2::itsmft::GBTWord + ; #pragma link C++ class o2::itsmft::GBTDataHeader + ; +#pragma link C++ class o2::itsmft::GBTDataHeaderL + ; #pragma link C++ class o2::itsmft::GBTDataTrailer + ; +#pragma link C++ class o2::itsmft::GBTTrigger + ; +#pragma link C++ class o2::itsmft::GBTDiagnostic + ; #pragma link C++ class o2::itsmft::GBTData + ; #pragma link C++ class o2::itsmft::PayLoadCont + ; #pragma link C++ class o2::itsmft::PayLoadSG + ; diff --git a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/MC2RawEncoder.h b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/MC2RawEncoder.h index a62e482b58066..d91b677989c79 100644 --- a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/MC2RawEncoder.h +++ b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/MC2RawEncoder.h @@ -22,6 +22,7 @@ #include "ITSMFTReconstruction/RUDecodeData.h" #include "DetectorsRaw/RawFileWriter.h" #include "DetectorsRaw/RDHUtils.h" +#include <unordered_map> namespace o2 { @@ -87,6 +88,8 @@ class MC2RawEncoder int carryOverMethod(const o2::header::RDHAny* rdh, const gsl::span<char> data, const char* ptr, int maxSize, int splitID, std::vector<char>& trailer, std::vector<char>& header) const; + void newRDHMethod(const header::RDHAny* rdh, bool empty, std::vector<char>& toAdd) const; + // create new gbt link int addGBTLink() { @@ -120,7 +123,8 @@ class MC2RawEncoder std::array<RUDecodeData, Mapping::getNRUs()> mRUDecodeVec; /// decoding buffers for all active RUs std::array<int, Mapping::getNRUs()> mRUEntry; /// entry of the RU with given SW ID in the mRUDecodeVec std::vector<GBTLink> mGBTLinks; - + std::unordered_map<uint16_t, const GBTLink*> mFEEId2Link; + std::unordered_map<uint16_t, GBTDataHeader> mFEEId2GBTHeader; ClassDefNV(MC2RawEncoder, 1); }; diff --git a/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx b/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx index cb61faa5fc3cc..adee01a9a9c34 100644 --- a/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx +++ b/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx @@ -23,6 +23,7 @@ void MC2RawEncoder<Mapping>::init() { assert(mWriter.isReadOutModeSet()); mWriter.setCarryOverCallBack(this); + mWriter.setNewRDHCallBack(this); // limit RUs to convert to existing ones mRUSWMax = (mRUSWMax < uint8_t(mMAP.getNRUs())) ? mRUSWMax : mMAP.getNRUs() - 1; @@ -34,7 +35,7 @@ void MC2RawEncoder<Mapping>::init() for (int il = 0; il < RUDecodeData::MaxLinksPerRU; il++) { auto* link = getGBTLink(ruData.links[il]); if (link) { - auto subspec = o2::raw::RDHUtils::getSubSpec(link->cruID, link->idInCRU, link->endPointID, link->feeID); + auto subspec = RDHUtils::getSubSpec(link->cruID, link->idInCRU, link->endPointID, link->feeID); if (!mWriter.isLinkRegistered(subspec)) { LOGF(INFO, "RU%3d FEEId 0x%04x Link %02d of CRU=0x%94x will be writing to default sink %s", int(ru), link->feeID, link->idInCRU, link->cruID, mDefaultSinkName); @@ -64,8 +65,13 @@ void MC2RawEncoder<Mapping>::init() mNLinks++; } } - assert(mNLinks > 0); + // create mapping from feeID to links for fast access + for (int i = 0; i < mNLinks; i++) { + const auto* lnk = getGBTLink(i); + mFEEId2Link[lnk->feeID] = lnk; + mFEEId2GBTHeader[lnk->feeID].activeLanes = lnk->lanes; + } } ///______________________________________________________________________ @@ -181,12 +187,8 @@ void MC2RawEncoder<Mapping>::fillGBTLinks(RUDecodeData& ru) } // reserve space for payload + trigger + header + trailer link->data.ensureFreeCapacity((3 + nPayLoadWordsNeeded) * GBTPaddedWordLength); - link->data.addFast(gbtTrigger.getW8(), GBTPaddedWordLength); // write GBT trigger in the beginning of the buffer - GBTDataHeader gbtHeader; - gbtHeader.packetIdx = 0; - gbtHeader.activeLanes = link->lanes; - link->data.addFast(gbtHeader.getW8(), GBTPaddedWordLength); // write GBT header + link->data.addFast(gbtTrigger.getW8(), GBTPaddedWordLength); // write GBT trigger // now loop over the lanes served by this link, writing each time at most 9 bytes, untill all lanes are copied bool hasData = true; @@ -214,8 +216,8 @@ void MC2RawEncoder<Mapping>::fillGBTLinks(RUDecodeData& ru) // all payload was dumped, write final trailer GBTDataTrailer gbtTrailer; // lanes will be set on closing the trigger - gbtTrailer.lanesStops = link->lanes; - gbtTrailer.packetDone = true; + // gbtTrailer.lanesStops = link->lanes; // RS CURRENTLY NOT USED + gbtTrailer.packetDone = true; // RS CURRENTLY NOT USED link->data.addFast(gbtTrailer.getW8(), GBTPaddedWordLength); // write GBT trailer for the last packet LOGF(DEBUG, "Filled %s with %d GBT words", link->describe(), nPayLoadWordsNeeded + 3); @@ -280,8 +282,10 @@ int MC2RawEncoder<Mapping>::carryOverMethod(const header::RDHAny* rdh, const gsl // In case returned actualSize == 0, current CRU page will be closed w/o adding anything, and new // query of this method will be done on the new CRU page - constexpr int TrigHeadSize = sizeof(GBTTrigger) + sizeof(GBTDataHeader); - constexpr int TotServiceSize = sizeof(GBTTrigger) + sizeof(GBTDataHeader) + sizeof(GBTDataTrailer); + // During the carry-over ITS needs to repeat the GBTTrigger and GBTDataTrailer words. + // Also the GBTDataHeader needs to be repeated right after continuation RDH, but it will be provided in the newRDHMethod + constexpr int TrigHeadSize = sizeof(GBTTrigger); + constexpr int TotServiceSize = sizeof(GBTTrigger) + sizeof(GBTDataTrailer); int offs = ptr - &data[0]; // offset wrt the head of the payload // make sure ptr and end of the suggested block are within the payload @@ -304,18 +308,35 @@ int MC2RawEncoder<Mapping>::carryOverMethod(const header::RDHAny* rdh, const gsl // copy the GBTTrigger and GBTHeader from the head of the payload header.resize(TrigHeadSize); memcpy(header.data(), &data[0], TrigHeadSize); - GBTDataHeader& gbtHeader = *reinterpret_cast<GBTDataHeader*>(&header[sizeof(GBTTrigger)]); // 1st trigger then header are written - gbtHeader.packetIdx = splitID + 1; // update the ITS specific packets counter // copy the GBTTrailer from the end of the payload trailer.resize(sizeof(GBTDataTrailer)); memcpy(trailer.data(), trailPtr, sizeof(GBTDataTrailer)); GBTDataTrailer& gbtTrailer = *reinterpret_cast<GBTDataTrailer*>(&trailer[0]); gbtTrailer.packetDone = false; // intermediate trailers should not have done=true - gbtTrailer.lanesStops = 0; // intermediate trailers should not have lanes closed + // gbtTrailer.lanesStops = 0; // intermediate trailers should not have lanes closed // RS CURRENTLY NOT USED return actualSize; } +///______________________________________________________________________ +template <class Mapping> +void MC2RawEncoder<Mapping>::newRDHMethod(const header::RDHAny* rdh, bool empty, std::vector<char>& toAdd) const +{ + // these method is called by the writer when it opens a new RDH page to fill some data. + // empty tells if the previous RDH page had some payload (to differentiate between automatic open/close of empty RDH pages, handled by + // the emptyHBFFunc and read data filling + if (RDHUtils::getStop(rdh)) { // the RDH was added to close previous HBF, do we want to add diagnostic data? + if (!empty) { + GBTDiagnostic diag; + toAdd.resize(GBTPaddedWordLength); + memcpy(toAdd.data(), diag.getW8(), GBTPaddedWordLength); + } + } else { // we need to add GBTDataHeader + toAdd.resize(GBTPaddedWordLength); + memcpy(toAdd.data(), mFEEId2GBTHeader.find(RDHUtils::getFEEID(rdh))->second.getW8(), GBTPaddedWordLength); + } +} + template class o2::itsmft::MC2RawEncoder<o2::itsmft::ChipMappingITS>; template class o2::itsmft::MC2RawEncoder<o2::itsmft::ChipMappingMFT>; diff --git a/Detectors/Raw/README.md b/Detectors/Raw/README.md index a364302317016..13b744a92dc78 100644 --- a/Detectors/Raw/README.md +++ b/Detectors/Raw/README.md @@ -149,10 +149,16 @@ empty HBF the writer will call it with rdh : RDH of the CRU page opening empty RDH toAdd : a vector (supplied empty) to be filled to a size multipe of 16 bytes ``` +The data `toAdd` will be inserted between the star/stop RDHs of the empty HBF. Adding empty HBF pages for HB's w/o data can be avoided by setting `writer.setDontFillEmptyHBF(true)` before starting conversion. Note that the empty HBFs still will be added for HBs which are supposed to open a new TF. -The data `toAdd` will be inserted between the star/stop RDHs of the empty HBF. +Some detectors (ITS/MFT) write a special header word after the RDH of every new CRU page (actually, different GBT words for pages w/o and with ``RDH.stop``) in non-empty HBFs. This can be achieved by +another call back method +```cpp +void newRDHMethod(const RDHAny* rdh, bool prevEmpty, std::vector<char>& toAdd) const; +``` +It proveds the ``RDH`` of the page for which it is called, information if the previous had some payload and buffer to be filled by the used algorithm. The behaviour described above can be modified by providing an extra argument in the `addData` method ```cpp diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h b/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h index ee895a5a3d599..89de7974f4b6f 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h @@ -48,6 +48,7 @@ class RawFileWriter const char* ptr, int size, int splitID, std::vector<char>& trailer, std::vector<char>& header)>; using EmptyPageCallBack = std::function<void(const RDHAny* rdh, std::vector<char>& emptyHBF)>; + using NewRDHCallBack = std::function<void(const RDHAny* rdh, bool prevEmpty, std::vector<char>& filler)>; ///===================================================================================== /// output file handler with its own lock @@ -76,7 +77,7 @@ class RawFileWriter ///===================================================================================== /// Single GBT link helper struct LinkData { - static constexpr int MarginToFlush = 2 * sizeof(RDHAny); // flush superpage if free space left <= this margin + static constexpr int MarginToFlush = 10 * sizeof(RDHAny); // flush superpage if free space left <= this margin RDHAny rdhCopy; // RDH with the running info of the last RDH seen IR updateIR; // IR at which new HBF needs to be created int lastRDHoffset = -1; // position of last RDH in the link buffer @@ -107,6 +108,9 @@ class RawFileWriter void print() const; void addData(const IR& ir, const gsl::span<char> data, bool preformatted = false, uint32_t trigger = 0); RDHAny* getLastRDH() { return lastRDHoffset < 0 ? nullptr : reinterpret_cast<RDHAny*>(&buffer[lastRDHoffset]); } + int getCurrentPageSize() const { return lastRDHoffset < 0 ? -1 : int(buffer.size()) - lastRDHoffset; } + // check if we are at the beginning of new page + bool isNewPage() const { return getCurrentPageSize() == sizeof(RDHAny); } std::string describe() const; protected: @@ -261,6 +265,14 @@ class RawFileWriter }; } + template <class T> + void setNewRDHCallBack(const T* t) + { + newRDHFunc = [=](const RDHAny* rdh, bool prevEmpty, std::vector<char>& toAdd) { + t->newRDHMethod(rdh, prevEmpty, toAdd); + }; + } + // This is a placeholder for the function responsible to split large payload to pieces // fitting 8kB CRU pages. // The RawFileWriter receives from the encoder the payload to format according to the CRU format @@ -313,6 +325,18 @@ class RawFileWriter { } + // This is a placeholder for the optional callback function to provide a detector-specific filler to be added right + // after the page starting by RDH (might be with RDH.stop=1 !) for the normal data filling (!! not automatic open/close RDHs for empty pages) + // + // It provides to the newRDHMethod method the following info: + // rdh : RDH of the CRU page to be opened + // prevEmpty : true is previous RDH page did not receive any data + // toAdd : a vector (supplied empty) to be filled to a size multipe of 16 bytes + // + void newRDHMethod(const RDHAny* rdh, bool prevEmpty, std::vector<char>& toAdd) const + { + } + int getUsedRDHVersion() const { return mUseRDHVersion; } void useRDHVersion(int v) { @@ -361,7 +385,7 @@ class RawFileWriter CarryOverCallBack carryOverFunc = nullptr; // default call back for large payload splitting (does nothing) EmptyPageCallBack emptyHBFFunc = nullptr; // default call back for empty HBF (does nothing) - + NewRDHCallBack newRDHFunc = nullptr; // default call back for new page opening (does nothing) // options int mVerbosity = 0; o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; diff --git a/Detectors/Raw/src/RawFileWriter.cxx b/Detectors/Raw/src/RawFileWriter.cxx index d17d6858a447a..b8a60d55ab682 100644 --- a/Detectors/Raw/src/RawFileWriter.cxx +++ b/Detectors/Raw/src/RawFileWriter.cxx @@ -304,6 +304,14 @@ void RawFileWriter::LinkData::addData(const IR& ir, const gsl::span<char> data, addPreformattedCRUPage(data); return; } + + // if we are at the beginning of the page, detector may want to add some header + if (isNewPage() && writer->newRDHFunc) { + std::vector<char> newPageHeader; + writer->newRDHFunc(getLastRDH(), false, newPageHeader); + pushBack(newPageHeader.data(), newPageHeader.size()); + } + const char* ptr = &data[0]; // in case particular detector CRU pages need to be self-consistent, when carrying-over // large payload to new CRU page we may need to write optional trailer and header before @@ -312,8 +320,15 @@ void RawFileWriter::LinkData::addData(const IR& ir, const gsl::span<char> data, int splitID = 0; std::vector<char> carryOverHeader; while (dataSize > 0) { + if (carryOver) { // check if there is carry-over header to write in the buffer addHBFPage(); // start new CRU page, if needed, the completed superpage is flushed + if (writer->newRDHFunc) { + std::vector<char> newPageHeader; + writer->newRDHFunc(getLastRDH(), false, newPageHeader); + pushBack(newPageHeader.data(), newPageHeader.size()); + } + // for sure after the carryOver we have space on the CRU page, no need to check LOG(DEBUG) << "Adding carryOverHeader " << carryOverHeader.size() << " bytes in IR " << ir << " to " << describe(); @@ -326,6 +341,11 @@ void RawFileWriter::LinkData::addData(const IR& ir, const gsl::span<char> data, int sizeLeft = sizeLeftCRUPage < sizeLeftSupPage ? sizeLeftCRUPage : sizeLeftSupPage; if (!sizeLeft) { // this page is just over, open a new one addHBFPage(); // start new CRU page, if needed, the completed superpage is flushed + if (writer->newRDHFunc) { + std::vector<char> newPageHeader; + writer->newRDHFunc(getLastRDH(), false, newPageHeader); + pushBack(newPageHeader.data(), newPageHeader.size()); + } continue; } @@ -404,9 +424,10 @@ void RawFileWriter::LinkData::addHBFPage(bool stop) } // finalize last RDH auto& lastRDH = *getLastRDH(); - int psize = buffer.size() - lastRDHoffset; // set the size for the previous header RDH - if (stop && psize == sizeof(RDHAny) && writer->emptyHBFFunc) { // we are closing an empty page, does detector want to add something? - std::vector<char> emtyHBFFiller; // working space for optional empty HBF filler + int psize = getCurrentPageSize(); // set the size for the previous header RDH + bool emptyPage = psize == sizeof(RDHAny); + if (stop && emptyPage && writer->emptyHBFFunc) { // we are closing an empty page, does detector want to add something? + std::vector<char> emtyHBFFiller; // working space for optional empty HBF filler writer->emptyHBFFunc(&lastRDH, emtyHBFFiller); if (emtyHBFFiller.size()) { LOG(DEBUG) << "Adding empty HBF filler of size " << emtyHBFFiller.size() << " for " << describe(); @@ -437,9 +458,18 @@ void RawFileWriter::LinkData::addHBFPage(bool stop) RDHUtils::setPacketCounter(rdhCopy, packetCounter++); RDHUtils::setPageCounter(rdhCopy, pageCnt++); RDHUtils::setStop(rdhCopy, stop); - RDHUtils::setOffsetToNext(rdhCopy, sizeof(RDHAny)); - RDHUtils::setMemorySize(rdhCopy, sizeof(RDHAny)); + std::vector<char> userData; + int sz = sizeof(RDHAny); + if (stop && writer->newRDHFunc) { // detector may want to write something in closing page + writer->newRDHFunc(&rdhCopy, emptyPage, userData); + sz += userData.size(); + } + RDHUtils::setOffsetToNext(rdhCopy, sz); + RDHUtils::setMemorySize(rdhCopy, sz); lastRDHoffset = pushBack(rdhCopy); // entry of the new RDH + if (!userData.empty()) { + pushBack(userData.data(), userData.size()); + } } if (stop) { if (RDHUtils::getTriggerType(rdhCopy) & o2::trigger::TF) { From 19831fc54d869493e3b7cee6c889dfaed36c6ae6 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 20 Sep 2020 20:20:51 +0200 Subject: [PATCH 0702/1751] Uniform naming of EMCALCluster*/EMCALCell* brunches (avoid mix of EMC.. and EMCAL..) --- .../reconstruction/src/ClusterizerTask.cxx | 6 +-- Detectors/EMCAL/workflow/src/RecoWorkflow.cxx | 44 ++++++++++++------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Detectors/EMCAL/reconstruction/src/ClusterizerTask.cxx b/Detectors/EMCAL/reconstruction/src/ClusterizerTask.cxx index ef63f5bca6bce..6b5e8e2c56d7e 100644 --- a/Detectors/EMCAL/reconstruction/src/ClusterizerTask.cxx +++ b/Detectors/EMCAL/reconstruction/src/ClusterizerTask.cxx @@ -83,9 +83,9 @@ void ClusterizerTask<InputType>::process(const std::string inputFileName, const // Create output tree std::unique_ptr<TTree> outTree = std::make_unique<TTree>("o2sim", "EMCAL clusters"); - outTree->Branch("EMCCluster", &mClustersArray); - outTree->Branch("EMCClusterInputIndex", &mClustersInputIndices); - outTree->Branch("EMCClusterTRGR", &mClusterTriggerRecordsClusters); + outTree->Branch("EMCALCluster", &mClustersArray); + outTree->Branch("EMCALClusterInputIndex", &mClustersInputIndices); + outTree->Branch("EMCALClusterTRGR", &mClusterTriggerRecordsClusters); outTree->Branch("EMCIndicesTRGR", &mClusterTriggerRecordsIndices); mClustersArray->clear(); diff --git a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx index e0cbadeacf783..1d8489f7a55e8 100644 --- a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx +++ b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx @@ -235,22 +235,34 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, "digitmc-branch-name"})()); } - if (isEnabled(OutputType::Cells) && inputType == InputType::Digits) { - using DigitOutputType = std::vector<o2::emcal::Cell>; - using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; - specs.push_back(makeWriterSpec("emcal-cells-writer", - inputType == InputType::Cells ? "emc-filtered-cells.root" : "emccells.root", - "o2sim", - BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "EMC", "CELLS", 0}, - "EMCCell", - "cell-branch-name"}, - BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"trigger", "EMC", "CELLSTRGR", 0}, - "EMCACellTRGR", - "celltrigger-branch-name"}, - BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "EMC", "CELLSMCTR", 0}, - "EMCCellMCTruth", - "cellmc-branch-name"})()); + if (isEnabled(OutputType::Cells) && !disableRootOutput) { + if (inputType == InputType::Digits) { + using DigitOutputType = std::vector<o2::emcal::Cell>; + using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; + using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + specs.push_back(makeWriterSpec("emcal-cells-writer", "emccells.root", "o2sim", + BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "EMC", "CELLS", 0}, + "EMCALCell", + "cell-branch-name"}, + BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"trigger", "EMC", "CELLSTRGR", 0}, + "EMCALCellTRGR", + "celltrigger-branch-name"}, + BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "EMC", "CELLSMCTR", 0}, + "EMCALCellMCTruth", + "cellmc-branch-name"})()); + } else { + using CellsDataType = std::vector<o2::emcal::Cell>; + using TriggerRecordDataType = std::vector<o2::emcal::TriggerRecord>; + specs.push_back(makeWriterSpec_CellsTR("emcal-cells-writer", + "emccells.root", + "o2sim", + BranchDefinition<CellsDataType>{o2::framework::InputSpec{"data", "EMC", "CELLS", 0}, + "EMCALCell", + "cell-branch-name"}, + BranchDefinition<TriggerRecordDataType>{o2::framework::InputSpec{"trigger", "EMC", "CELLSTRGR", 0}, + "EMCALCellTRGR", + "celltrigger-branch-name"})()); + } } if (isEnabled(OutputType::Clusters)) { From e64d267745cc374499efd50b7a02888606887720 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 20 Sep 2020 20:21:14 +0200 Subject: [PATCH 0703/1751] Improve logics of EMCAL workflow --- .../include/EMCALWorkflow/RecoWorkflow.h | 16 +- Detectors/EMCAL/workflow/src/RecoWorkflow.cxx | 181 ++++++++++-------- .../EMCAL/workflow/src/emc-reco-workflow.cxx | 7 +- 3 files changed, 110 insertions(+), 94 deletions(-) diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h index 0d296cb0e159f..f001e24ae88d2 100644 --- a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h @@ -27,11 +27,10 @@ namespace reco_workflow /// \enum InputType /// \brief Input types of the workflow /// \ingroup EMCALworkflow -enum struct InputType { Digitizer, ///< directly read digits from channel {TPC:DIGITS) - Digits, ///< read digits from file - Cells, ///< read compressed cells from file - Raw, ///< read data in raw page format from file - Clusters ///< read native clusters from file +enum struct InputType { Digits, ///< read digits from file + Cells, ///< read compressed cells from file + Raw, ///< read data in raw page format from file + Clusters ///< read native clusters from file }; /// \enum OutputType @@ -53,9 +52,10 @@ enum struct OutputType { Digits, ///< EMCAL digits /// \ingroup EMCALwokflow framework::WorkflowSpec getWorkflow(bool propagateMC = true, bool enableDigitsPrinter = false, - std::string const& cfgInput = "digits", // - std::string const& cfgOutput = "clusters" // -); + std::string const& cfgInput = "digits", // + std::string const& cfgOutput = "clusters", // + bool disableRootInput = false, + bool disableRootOutput = false); } // namespace reco_workflow } // namespace emcal diff --git a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx index 1d8489f7a55e8..08dfa607cb6d1 100644 --- a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx +++ b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx @@ -43,26 +43,33 @@ namespace emcal namespace reco_workflow { -const std::unordered_map<std::string, InputType> InputMap{ - {"digitizer", InputType::Digitizer}, - {"digits", InputType::Digits}, - {"cells", InputType::Cells}, - {"raw", InputType::Raw}, - {"clusters", InputType::Clusters}, -}; - -const std::unordered_map<std::string, OutputType> OutputMap{ - {"digits", OutputType::Digits}, - {"cells", OutputType::Cells}, - {"raw", OutputType::Raw}, - {"clusters", OutputType::Clusters}, - {"analysisclusters", OutputType::AnalysisClusters}}; - o2::framework::WorkflowSpec getWorkflow(bool propagateMC, bool enableDigitsPrinter, std::string const& cfgInput, - std::string const& cfgOutput) + std::string const& cfgOutput, + bool disableRootInput, + bool disableRootOutput) { + + const std::unordered_map<std::string, InputType> InputMap{ + {"digits", InputType::Digits}, + {"cells", InputType::Cells}, + {"raw", InputType::Raw}, + {"clusters", InputType::Clusters}, + }; + + const std::unordered_map<std::string, OutputType> OutputMap{ + {"digits", OutputType::Digits}, + {"cells", OutputType::Cells}, + {"raw", OutputType::Raw}, + {"clusters", OutputType::Clusters}, + {"analysisclusters", OutputType::AnalysisClusters}}; + + std::unordered_map<InputType, std::vector<OutputType>> allowedIO; + allowedIO[InputType::Digits] = std::vector<OutputType>{OutputType::Cells, OutputType::Clusters, OutputType::AnalysisClusters}; + allowedIO[InputType::Cells] = std::vector<OutputType>{OutputType::Clusters, OutputType::AnalysisClusters}; + allowedIO[InputType::Raw] = std::vector<OutputType>{OutputType::Cells}; + InputType inputType; try { @@ -72,7 +79,7 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, } std::vector<OutputType> outputTypes; try { - outputTypes = RangeTokenizer::tokenize<OutputType>(cfgOutput, [](std::string const& token) { return OutputMap.at(token); }); + outputTypes = RangeTokenizer::tokenize<OutputType>(cfgOutput, [&](std::string const& token) { return OutputMap.at(token); }); } catch (std::out_of_range&) { throw std::invalid_argument(std::string("invalid output type: ") + cfgOutput); } @@ -80,20 +87,48 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, return std::find(outputTypes.begin(), outputTypes.end(), type) != outputTypes.end(); }; + auto isAllowedIOCombination = [&allowedIO](InputType inp, OutputType out) { + const auto& vout = allowedIO[inp]; + return std::find(vout.begin(), vout.end(), out) != vout.end(); + }; + + auto getOutputTypeName = [&OutputMap](OutputType out) { + std::string str; + for (const auto& o : OutputMap) { + if (o.second == out) { + str = std::string(o.first); + } + } + return str; + }; + + // make sure inputs/outputs combinatios are enabled + for (const auto outType : outputTypes) { + if (!isAllowedIOCombination(inputType, outType)) { + throw std::runtime_error(fmt::format("Input {:s} is not allowed with output {:s}", cfgInput, getOutputTypeName(outType))); + } + } + + if (inputType == InputType::Raw) { + propagateMC = false; + } + o2::framework::WorkflowSpec specs; if (inputType == InputType::Digits) { using digitInputType = std::vector<o2::emcal::Digit>; - specs.emplace_back(o2::emcal::getPublisherSpec<digitInputType>(PublisherConf{ - "emcal-digit-reader", - "o2sim", - {"digitbranch", "EMCALDigit", "Digit branch"}, - {"digittriggerbranch", "EMCALDigitTRGR", "Trigger record branch"}, - {"mcbranch", "EMCALDigitMCTruth", "MC label branch"}, - o2::framework::OutputSpec{"EMC", "DIGITS"}, - o2::framework::OutputSpec{"EMC", "DIGITSTRGR"}, - o2::framework::OutputSpec{"EMC", "DIGITSMCTR"}}, - propagateMC)); + if (!disableRootInput) { + specs.emplace_back(o2::emcal::getPublisherSpec<digitInputType>(PublisherConf{ + "emcal-digit-reader", + "o2sim", + {"digitbranch", "EMCALDigit", "Digit branch"}, + {"digittriggerbranch", "EMCALDigitTRGR", "Trigger record branch"}, + {"mcbranch", "EMCALDigitMCTruth", "MC label branch"}, + o2::framework::OutputSpec{"EMC", "DIGITS"}, + o2::framework::OutputSpec{"EMC", "DIGITSTRGR"}, + o2::framework::OutputSpec{"EMC", "DIGITSMCTR"}}, + propagateMC)); + } if (enableDigitsPrinter) { try { @@ -102,32 +137,20 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, LOG(ERROR) << "Cannot create digits printer spec: " << e.what(); } } - - if (isEnabled(OutputType::Cells)) { - // add converter for cells - specs.emplace_back(o2::emcal::reco_workflow::getCellConverterSpec(propagateMC)); - } - - if (isEnabled(OutputType::Clusters)) { - // add clusterizer - specs.emplace_back(o2::emcal::reco_workflow::getClusterizerSpec(true)); - } - if (isEnabled(OutputType::AnalysisClusters)) { - // add clusters from cells - specs.emplace_back(o2::emcal::reco_workflow::getAnalysisClusterSpec(true)); - } } else if (inputType == InputType::Cells) { using cellInputType = std::vector<o2::emcal::Cell>; - specs.emplace_back(o2::emcal::getPublisherSpec<cellInputType>(PublisherConf{ - "emcal-cell-reader", - "o2sim", - {"cellbranch", "EMCALCell", "Cell branch"}, - {"celltriggerbranch", "EMCALCellTRGR", "Trigger record branch"}, - {"mcbranch", "EMCALCellMCTruth", "MC label branch"}, - o2::framework::OutputSpec{"EMC", "CELLS"}, - o2::framework::OutputSpec{"EMC", "CELLSTRGR"}, - o2::framework::OutputSpec{"EMC", "CELLSMCTR"}}, - propagateMC)); + if (!disableRootInput) { + specs.emplace_back(o2::emcal::getPublisherSpec<cellInputType>(PublisherConf{ + "emcal-cell-reader", + "o2sim", + {"cellbranch", "EMCALCell", "Cell branch"}, + {"celltriggerbranch", "EMCALCellTRGR", "Trigger record branch"}, + {"mcbranch", "EMCALCellMCTruth", "MC label branch"}, + o2::framework::OutputSpec{"EMC", "CELLS"}, + o2::framework::OutputSpec{"EMC", "CELLSTRGR"}, + o2::framework::OutputSpec{"EMC", "CELLSMCTR"}}, + propagateMC)); + } if (enableDigitsPrinter) { try { specs.emplace_back(o2::emcal::reco_workflow::getEmcalDigitsPrinterSpec("cells")); @@ -135,24 +158,28 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, LOG(ERROR) << "Cannot create digits printer spec: " << e.what(); } } + } - if (isEnabled(OutputType::Clusters)) { - // add clusterizer from cells - specs.emplace_back(o2::emcal::reco_workflow::getClusterizerSpec(false)); - } - if (isEnabled(OutputType::AnalysisClusters)) { - // add clusters from cells - specs.emplace_back(o2::emcal::reco_workflow::getAnalysisClusterSpec(false)); - } - } else if (inputType == InputType::Raw) { - - //Subcscribe to Readout data using o2-readout-proxy - if (isEnabled(OutputType::Cells)) { - // add converter for cells + if (isEnabled(OutputType::Cells)) { + // add converter for cells + if (inputType == InputType::Digits) { + specs.emplace_back(o2::emcal::reco_workflow::getCellConverterSpec(propagateMC)); + } else { + // raw data will come from upstream specs.emplace_back(o2::emcal::reco_workflow::getRawToCellConverterSpec()); } } + if (isEnabled(OutputType::Clusters)) { + // add clusterizer + specs.emplace_back(o2::emcal::reco_workflow::getClusterizerSpec(inputType == InputType::Digits)); + } + + if (isEnabled(OutputType::AnalysisClusters)) { + // add clusters from cells + specs.emplace_back(o2::emcal::reco_workflow::getAnalysisClusterSpec(inputType == InputType::Digits)); + } + // check if the process is ready to quit // this is decided upon the meta information in the EMCAL block header, the operation is set // value kNoPayload in case of no data or no operation @@ -217,7 +244,7 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, std::move(TriggerRecordBranch))); }; - if (isEnabled(OutputType::Digits)) { + if (isEnabled(OutputType::Digits) && !disableRootOutput) { using DigitOutputType = std::vector<o2::emcal::Digit>; using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; @@ -265,7 +292,7 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, } } - if (isEnabled(OutputType::Clusters)) { + if (isEnabled(OutputType::Clusters) && !disableRootOutput) { using ClusterOutputType = std::vector<o2::emcal::Cluster>; using ClusterIndicesOutputType = std::vector<o2::emcal::ClusterIndex>; using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; @@ -274,20 +301,20 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, "emcclusters.root", "o2sim", BranchDefinition<ClusterOutputType>{o2::framework::InputSpec{"clusters", "EMC", "CLUSTERS", 0}, - "EMCCluster", + "EMCALCluster", "cluster-branch-name"}, BranchDefinition<ClusterIndicesOutputType>{o2::framework::InputSpec{"clusterindices", "EMC", "INDICES", 0}, - "EMCClusterInputIndex", + "EMCALClusterInputIndex", "clusterdigitindices-branch-name"}, BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"clusterTRGR", "EMC", "CLUSTERSTRGR", 0}, - "EMCClusterTRGR", + "EMCALClusterTRGR", "clustertrigger-branch-name"}, BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"indicesTRGR", "EMC", "INDICESTRGR", 0}, "EMCIndicesTRGR", "indicestrigger-branch-name"})()); } - if (isEnabled(OutputType::AnalysisClusters)) { + if (isEnabled(OutputType::AnalysisClusters) && !disableRootOutput) { using AnalysisClusterOutputType = std::vector<o2::emcal::AnalysisCluster>; specs.push_back(makeWriterSpec_AnalysisCluster("emcal-analysis-clusters-writer", @@ -298,20 +325,6 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, "cluster-branch-name"})()); } - if (isEnabled(OutputType::Cells) && inputType == InputType::Raw) { - using CellsDataType = std::vector<o2::emcal::Cell>; - using TriggerRecordDataType = std::vector<o2::emcal::TriggerRecord>; - specs.push_back(makeWriterSpec_CellsTR("emcal-cells-writer", - "emccells.root", - "o2sim", - BranchDefinition<CellsDataType>{o2::framework::InputSpec{"data", "EMC", "CELLS", 0}, - "EMCCell", - "cell-branch-name"}, - BranchDefinition<TriggerRecordDataType>{o2::framework::InputSpec{"trigger", "EMC", "CELLSTRGR", 0}, - "EMCACellTRGR", - "celltrigger-branch-name"})()); - } - return std::move(specs); } diff --git a/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx b/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx index 7ac241a1afffe..53159b3345365 100644 --- a/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx +++ b/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx @@ -30,6 +30,8 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) {"input-type", o2::framework::VariantType::String, "digits", {"digitizer, digits, raw, clusters"}}, {"output-type", o2::framework::VariantType::String, "digits", {"digits, raw, clusters"}}, {"enable-digits-printer", o2::framework::VariantType::Bool, false, {"enable digits printer component"}}, + {"disable-root-input", o2::framework::VariantType::Bool, false, {"do not initialize root files readers"}}, + {"disable-root-output", o2::framework::VariantType::Bool, false, {"do not initialize root file writers"}}, {"disable-mc", o2::framework::VariantType::Bool, false, {"disable sending of MC information"}}, }; std::swap(workflowOptions, options); @@ -55,6 +57,7 @@ o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext co return o2::emcal::reco_workflow::getWorkflow(not cfgc.options().get<bool>("disable-mc"), // cfgc.options().get<bool>("enable-digits-printer"), // cfgc.options().get<std::string>("input-type"), // - cfgc.options().get<std::string>("output-type") // - ); + cfgc.options().get<std::string>("output-type"), // + cfgc.options().get<bool>("disable-root-input"), + cfgc.options().get<bool>("disable-root-output")); } From a00aeb4defce4f5eb85df5e7b9702b3fed35f1ff Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 20 Sep 2020 22:38:42 +0200 Subject: [PATCH 0704/1751] Make EMCAL clusterizer to process empty input data --- .../include/EMCALReconstruction/Clusterizer.h | 5 +++++ Detectors/EMCAL/reconstruction/src/Clusterizer.cxx | 3 +-- Detectors/EMCAL/workflow/src/ClusterizerSpec.cxx | 8 +++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/Clusterizer.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/Clusterizer.h index a719932567609..bc057b0a3b4a9 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/Clusterizer.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/Clusterizer.h @@ -67,6 +67,11 @@ class Clusterizer Clusterizer(); ~Clusterizer() = default; + void clear() + { + mFoundClusters.clear(); + mInputIndices.clear(); + } void initialize(double timeCut, double timeMin, double timeMax, double gradientCut, bool doEnergyGradientCut, double thresholdSeedE, double thresholdCellE); void findClusters(const gsl::span<InputType const>& inputArray); const std::vector<Cluster>* getFoundClusters() const { return &mFoundClusters; } diff --git a/Detectors/EMCAL/reconstruction/src/Clusterizer.cxx b/Detectors/EMCAL/reconstruction/src/Clusterizer.cxx index 9adcc506dbd26..3a4d33d10555d 100644 --- a/Detectors/EMCAL/reconstruction/src/Clusterizer.cxx +++ b/Detectors/EMCAL/reconstruction/src/Clusterizer.cxx @@ -124,8 +124,7 @@ void Clusterizer<InputType>::getTopologicalRowColumn(const InputType& input, int template <class InputType> void Clusterizer<InputType>::findClusters(const gsl::span<InputType const>& inputArray) { - mFoundClusters.clear(); - mInputIndices.clear(); + clear(); // Algorithm // - Fill cells/digits in 2D topological map diff --git a/Detectors/EMCAL/workflow/src/ClusterizerSpec.cxx b/Detectors/EMCAL/workflow/src/ClusterizerSpec.cxx index d3ec00ddac607..8c4284945cb21 100644 --- a/Detectors/EMCAL/workflow/src/ClusterizerSpec.cxx +++ b/Detectors/EMCAL/workflow/src/ClusterizerSpec.cxx @@ -78,9 +78,11 @@ void ClusterizerSpec<InputType>::run(framework::ProcessingContext& ctx) int currentStartClusters = mOutputClusters->size(); int currentStartIndices = mOutputCellDigitIndices->size(); for (auto iTrgRcrd : InputTriggerRecord) { - - mClusterizer.findClusters(gsl::span<const InputType>(&Inputs[iTrgRcrd.getFirstEntry()], iTrgRcrd.getNumberOfObjects())); // Find clusters on cells/digits (pass by ref) - + if (Inputs.size() && iTrgRcrd.getNumberOfObjects()) { + mClusterizer.findClusters(gsl::span<const InputType>(&Inputs[iTrgRcrd.getFirstEntry()], iTrgRcrd.getNumberOfObjects())); // Find clusters on cells/digits (pass by ref) + } else { + mClusterizer.clear(); + } // Get found clusters + cell/digit indices for output // * A cluster contains a range that correspond to the vector of cell/digit indices // * The cell/digit index vector contains the indices of the clusterized cells/digits wrt to the original cell/digit array From cff85114b218b81fb4bbe0c867e5d45ea8090aeb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 20 Sep 2020 22:40:24 +0200 Subject: [PATCH 0705/1751] Consistently use o2::emcal::MCLabel rather than o2::MCCompLabel --- Detectors/EMCAL/workflow/src/CellConverterSpec.cxx | 4 ++-- Detectors/EMCAL/workflow/src/RecoWorkflow.cxx | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx index c3a65960dc82e..dbaefad219773 100644 --- a/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx @@ -14,7 +14,7 @@ #include "DataFormatsEMCAL/EMCALBlockHeader.h" #include "EMCALWorkflow/CellConverterSpec.h" #include "Framework/ControlService.h" -#include "SimulationDataFormat/MCCompLabel.h" +#include "DataFormatsEMCAL/MCLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" using namespace o2::emcal::reco_workflow; @@ -62,7 +62,7 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) if (mPropagateMC) { // copy mc truth container without modification // as indexing doesn't change - auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("digitsmctr"); + auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>*>("digitsmctr"); ctx.outputs().snapshot(o2::framework::Output{"EMC", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe}, *truthcont); } } diff --git a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx index 08dfa607cb6d1..697002b08c7e4 100644 --- a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx +++ b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx @@ -28,7 +28,7 @@ #include "EMCALWorkflow/PublisherSpec.h" #include "EMCALWorkflow/RawToCellConverterSpec.h" #include "Framework/DataSpecUtils.h" -#include "SimulationDataFormat/MCCompLabel.h" +#include "DataFormatsEMCAL/MCLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" namespace o2 @@ -243,11 +243,12 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, std::move(CellsBranch), std::move(TriggerRecordBranch))); }; - + /* + // RS getting input digits and outputing them under the same outputspec will create dependency loop when piping the workflows if (isEnabled(OutputType::Digits) && !disableRootOutput) { using DigitOutputType = std::vector<o2::emcal::Digit>; using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>; specs.push_back(makeWriterSpec("emcal-digits-writer", inputType == InputType::Digits ? "emc-filtered-digits.root" : "emcdigits.root", "o2sim", @@ -261,12 +262,12 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, "EMCDigitMCTruth", "digitmc-branch-name"})()); } - + */ if (isEnabled(OutputType::Cells) && !disableRootOutput) { if (inputType == InputType::Digits) { using DigitOutputType = std::vector<o2::emcal::Cell>; using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>; specs.push_back(makeWriterSpec("emcal-cells-writer", "emccells.root", "o2sim", BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "EMC", "CELLS", 0}, "EMCALCell", From bea1e90ceead54412dc57ab363e8cdeb00e03445 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 21 Sep 2020 15:56:17 +0200 Subject: [PATCH 0706/1751] aligning sign of eta with AliRoot (#4401) --- Framework/Core/include/Framework/AnalysisDataModel.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 04b60e1b5ee64..729e273243241 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -93,8 +93,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(NormalizedPhi, phi, [](float phi) -> float { phi -= twopi; return phi; }); -// FIXME: have float constants like pi defined somewhere -DECLARE_SOA_EXPRESSION_COLUMN(Eta, eta, float, nlog(ntan(0.25f * static_cast<float>(M_PI) - 0.5f * natan(aod::track::tgl)))); +DECLARE_SOA_EXPRESSION_COLUMN(Eta, eta, float, -1.f * nlog(ntan(0.25f * static_cast<float>(M_PI) - 0.5f * natan(aod::track::tgl)))); DECLARE_SOA_EXPRESSION_COLUMN(Pt, pt, float, nabs(1.f / aod::track::signed1Pt)); DECLARE_SOA_DYNAMIC_COLUMN(Charge, charge, [](float signed1Pt) -> short { return (signed1Pt > 0) ? 1 : -1; }); From b32abe2ca0890c0cd33d07d23117e4b3d4ae3c11 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 21 Sep 2020 18:48:20 +0200 Subject: [PATCH 0707/1751] Corr update (#4403) * adding equidistant binning support for StepTHn * adding control histograms --- .../include/Analysis/CorrelationContainer.h | 2 +- Analysis/Core/include/Analysis/StepTHn.h | 6 +- Analysis/Core/src/CorrelationContainer.cxx | 79 ++++++++----------- Analysis/Core/src/StepTHn.cxx | 49 +++++++----- Analysis/Tasks/PWGCF/correlations.cxx | 26 ++++-- 5 files changed, 88 insertions(+), 74 deletions(-) diff --git a/Analysis/Core/include/Analysis/CorrelationContainer.h b/Analysis/Core/include/Analysis/CorrelationContainer.h index b644434a13d55..4e1ba81cad44e 100644 --- a/Analysis/Core/include/Analysis/CorrelationContainer.h +++ b/Analysis/Core/include/Analysis/CorrelationContainer.h @@ -145,7 +145,7 @@ class CorrelationContainer : public TNamed static TString combineBinning(TString defaultBinning, TString customBinning); protected: - Double_t* getBinning(const char* configuration, const char* tag, Int_t& nBins); + std::vector<Double_t> getBinning(const char* configuration, const char* tag, Int_t& nBins); void weightHistogram(TH3* hist1, TH1* hist2); void multiplyHistograms(THnBase* grid, THnBase* target, TH1* histogram, Int_t var1, Int_t var2); diff --git a/Analysis/Core/include/Analysis/StepTHn.h b/Analysis/Core/include/Analysis/StepTHn.h index f57f22f380a81..87e152f9a8d3f 100644 --- a/Analysis/Core/include/Analysis/StepTHn.h +++ b/Analysis/Core/include/Analysis/StepTHn.h @@ -26,7 +26,7 @@ class StepTHnBase : public TNamed { public: StepTHnBase() : TNamed() {} - StepTHnBase(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, Double_t** binLimits, const char** axisTitles) : TNamed(name, title) {} + StepTHnBase(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binLimits[], const char** axisTitles) : TNamed(name, title) {} virtual void Fill(const Double_t* var, Int_t istep, Double_t weight = 1.) = 0; @@ -44,14 +44,12 @@ class StepTHnBase : public TNamed ClassDef(StepTHnBase, 1) // StepTHn base class }; -// TODO equidistant binning for THn - template <class TemplateArray, typename TemplateType> class StepTHn : public StepTHnBase { public: StepTHn(); - StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, Double_t** binLimits, const char** axisTitles); + StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binLimits[], const char** axisTitles); ~StepTHn() override; void Fill(const Double_t* var, Int_t istep, Double_t weight = 1.) override; diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 18e679e37c015..8d7236f7f0efc 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -86,6 +86,8 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl { // Constructor + using BinList = std::vector<Double_t>; + if (strlen(reqHist) == 0) return; @@ -96,12 +98,12 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl // track level Int_t nTrackVars = 4; // eta vs pT vs pT,lead (vs delta phi) vs multiplicity Int_t iTrackBin[7]; - Double_t* trackBins[7]; + BinList trackBins[7]; const char* trackAxisTitle[7]; // eta Int_t nEtaBins = -1; - Double_t* etaBins = getBinning(binning, "eta", nEtaBins); + BinList etaBins = getBinning(binning, "eta", nEtaBins); const char* etaTitle = "#eta"; iTrackBin[0] = nEtaBins; @@ -110,7 +112,7 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl // delta eta Int_t nDeltaEtaBins = -1; - Double_t* deltaEtaBins = getBinning(binning, "delta_eta", nDeltaEtaBins); + BinList deltaEtaBins = getBinning(binning, "delta_eta", nDeltaEtaBins); // pT trackBins[1] = getBinning(binning, "p_t_assoc", iTrackBin[1]); @@ -118,33 +120,33 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl // pT, fine Int_t npTBinsFine = -1; - Double_t* pTBinsFine = getBinning(binning, "p_t_eff", npTBinsFine); + BinList pTBinsFine = getBinning(binning, "p_t_eff", npTBinsFine); // pT,lead binning 1 Int_t nLeadingpTBins = -1; - Double_t* leadingpTBins = getBinning(binning, "p_t_leading", nLeadingpTBins); + BinList leadingpTBins = getBinning(binning, "p_t_leading", nLeadingpTBins); // pT,lead binning 2 Int_t nLeadingpTBins2 = -1; - Double_t* leadingpTBins2 = getBinning(binning, "p_t_leading_course", nLeadingpTBins2); + BinList leadingpTBins2 = getBinning(binning, "p_t_leading_course", nLeadingpTBins2); // phi,lead Int_t nLeadingPhiBins = -1; - Double_t* leadingPhiBins = getBinning(binning, "delta_phi", nLeadingPhiBins); + BinList leadingPhiBins = getBinning(binning, "delta_phi", nLeadingPhiBins); trackBins[3] = getBinning(binning, "multiplicity", iTrackBin[3]); trackAxisTitle[3] = "multiplicity"; // particle species const Int_t kNSpeciesBins = 4; // pi, K, p, rest - Double_t speciesBins[] = {-0.5, 0.5, 1.5, 2.5, 3.5}; + BinList speciesBins = {-0.5, 0.5, 1.5, 2.5, 3.5}; // vtx-z axis const char* vertexTitle = "z-vtx (cm)"; Int_t nVertexBins = -1; - Double_t* vertexBins = getBinning(binning, "vertex", nVertexBins); + BinList vertexBins = getBinning(binning, "vertex", nVertexBins); Int_t nVertexBinsEff = -1; - Double_t* vertexBinsEff = getBinning(binning, "vertex_eff", nVertexBinsEff); + BinList vertexBinsEff = getBinning(binning, "vertex_eff", nVertexBinsEff); Int_t useVtxAxis = 0; Int_t useAliTHn = 1; // 0 = don't use | 1 = with float | 2 = with double @@ -258,7 +260,7 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl // event level Int_t nEventVars = 2; Int_t iEventBin[4] = {0}; - Double_t* eventBins[4] = {nullptr}; + BinList eventBins[4]; const char* eventAxisTitle[4] = {nullptr}; // track 3rd and 4th axis --> event 1st and 2nd axis @@ -305,15 +307,7 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl mTrackHistEfficiency = new StepTHnD("mTrackHistEfficiency", "Tracking efficiency", 6, 5, iTrackBin, trackBins, trackAxisTitle); - mEventCount = new TH2F("mEventCount", ";step;centrality;count", fgkCFSteps + 2, -2.5, -0.5 + fgkCFSteps, iEventBin[1], eventBins[1]); - - delete[] deltaEtaBins; - delete[] pTBinsFine; - delete[] leadingpTBins; - delete[] leadingpTBins2; - delete[] leadingPhiBins; - delete[] vertexBins; - delete[] vertexBinsEff; + mEventCount = new TH2F("mEventCount", ";step;centrality;count", fgkCFSteps + 2, -2.5, -0.5 + fgkCFSteps, iEventBin[1], &(eventBins[1])[0]); } TString CorrelationContainer::combineBinning(TString defaultBinning, TString customBinning) @@ -338,15 +332,18 @@ TString CorrelationContainer::combineBinning(TString defaultBinning, TString cus return binningStr; } -Double_t* CorrelationContainer::getBinning(const char* configuration, const char* tag, Int_t& nBins) +std::vector<Double_t> CorrelationContainer::getBinning(const char* configuration, const char* tag, Int_t& nBins) { // takes the binning from <configuration> identified by <tag> // configuration syntax example: - // eta: 2.4, -2.3, -2.2, -2.1, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 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, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4 - // phi: ..... + // equidistant binning: + // eta: 48 | -2.4, 2.4 + // variable-width binning: + // eta: -2.4, -2.3, -2.2, -2.1, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 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, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4 // // returns bin edges which have to be deleted by the caller + std::vector<Double_t> bins; TString config(configuration); TObjArray* lines = config.Tokenize("\n"); for (Int_t i = 0; i < lines->GetEntriesFast(); i++) { @@ -354,13 +351,19 @@ Double_t* CorrelationContainer::getBinning(const char* configuration, const char if (line.BeginsWith(TString(tag) + ":")) { line.Remove(0, strlen(tag) + 1); line.ReplaceAll(" ", ""); + if (line.Contains("|")) { + // equidistant binning + nBins = TString(line(0, line.Index("|"))).Atoi(); + line.Remove(0, line.Index("|") + 1); + } else { + // variable-width binning + nBins = line.CountChar(','); + } TObjArray* binning = line.Tokenize(","); - Double_t* bins = new Double_t[binning->GetEntriesFast()]; - for (Int_t j = 0; j < binning->GetEntriesFast(); j++) - bins[j] = TString(binning->At(j)->GetName()).Atof(); - - nBins = binning->GetEntriesFast() - 1; - + //Double_t* bins = new Double_t[binning->GetEntriesFast()]; + for (Int_t j = 0; j < binning->GetEntriesFast(); j++) { + bins.push_back(TString(binning->At(j)->GetName()).Atof()); + } delete binning; delete lines; return bins; @@ -369,7 +372,7 @@ Double_t* CorrelationContainer::getBinning(const char* configuration, const char delete lines; LOGF(fatal, "Tag %s not found in %s", tag, configuration); - return nullptr; + return bins; } //_____________________________________________________________________________ @@ -1906,21 +1909,7 @@ THnBase* CorrelationContainer::changeToThn(THnBase* sparse) { // change the object to THn for faster processing - // convert to THn (SEGV's for some strange reason...) - // x = THn::CreateHn("a", "a", sparse); - - // own implementation - Int_t nBins[10]; - for (Int_t i = 0; i < sparse->GetNdimensions(); i++) - nBins[i] = sparse->GetAxis(i)->GetNbins(); - THn* tmpTHn = new THnF(Form("%s_thn", sparse->GetName()), sparse->GetTitle(), sparse->GetNdimensions(), nBins, nullptr, nullptr); - for (Int_t i = 0; i < sparse->GetNdimensions(); i++) { - tmpTHn->SetBinEdges(i, sparse->GetAxis(i)->GetXbins()->GetArray()); - tmpTHn->GetAxis(i)->SetTitle(sparse->GetAxis(i)->GetTitle()); - } - tmpTHn->RebinnedAdd(sparse); - - return tmpTHn; + return THn::CreateHn(Form("%s_thn", sparse->GetName()), sparse->GetTitle(), sparse); } void CorrelationContainer::fillEvent(Float_t centrality, CFStep step) diff --git a/Analysis/Core/src/StepTHn.cxx b/Analysis/Core/src/StepTHn.cxx index 9bc7a11815537..ef7f6902af19b 100644 --- a/Analysis/Core/src/StepTHn.cxx +++ b/Analysis/Core/src/StepTHn.cxx @@ -44,37 +44,50 @@ templateClassImp(StepTHn) mLastBins(nullptr), mPrototype(nullptr) { - // Constructor + // Default constructor (for streaming) } template <class TemplateArray, typename TemplateType> -StepTHn<TemplateArray, TemplateType>::StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, Double_t** binEdges, const char** axisTitles) : StepTHnBase(name, title, nSteps, nAxis, nBins, binEdges, axisTitles), - mNBins(0), - mNVars(nAxis), - mNSteps(nSteps), - mValues(nullptr), - mSumw2(nullptr), - mTarget(nullptr), - mAxisCache(nullptr), - mNbinsCache(nullptr), - mLastVars(nullptr), - mLastBins(nullptr), - mPrototype(nullptr) +StepTHn<TemplateArray, TemplateType>::StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binEdges[], const char** axisTitles) : StepTHnBase(name, title, nSteps, nAxis, nBins, binEdges, axisTitles), + mNBins(0), + mNVars(nAxis), + mNSteps(nSteps), + mValues(nullptr), + mSumw2(nullptr), + mTarget(nullptr), + mAxisCache(nullptr), + mNbinsCache(nullptr), + mLastVars(nullptr), + mLastBins(nullptr), + mPrototype(nullptr) { // Constructor + // + // This will create a container for <nSteps> steps. The memory for such a step is only allocated once the first value is filled. + // Therefore you can easily create many steps which are only filled under certain analysis settings. + // For each step a <nAxis> dimensional histogram is created. + // The axis have <nBins[i]> bins. The bin edges are given in <binEdges[i]>. If there are only two bin edges, equidistant binning is set. mNBins = 1; for (Int_t i = 0; i < mNVars; i++) mNBins *= nBins[i]; - // TODO this should be double for StepTHnD - - mPrototype = new THnSparseF(Form("%s_sparse", name), title, nAxis, nBins); + if constexpr (std::is_same_v<TemplateType, Double_t>) { + mPrototype = new THnSparseD(Form("%s_sparse", name), title, nAxis, nBins); + } else { + mPrototype = new THnSparseF(Form("%s_sparse", name), title, nAxis, nBins); + } for (Int_t i = 0; i < mNVars; i++) { - mPrototype->SetBinEdges(i, binEdges[i]); + if (nBins[i] + 1 == binEdges[i].size()) { // variable-width binning + mPrototype->GetAxis(i)->Set(nBins[i], &(binEdges[i])[0]); + } else if (binEdges[i].size() == 2) { // equidistant binning + mPrototype->GetAxis(i)->Set(nBins[i], binEdges[i][0], binEdges[i][1]); + } else { + LOGF(fatal, "Invalid binning information for axis %d with %d bins and %d entries for bin edges", i, nBins[i], binEdges[i].size()); + } + LOGF(debug, "Histogram %s Axis %d created with %d bins and %d edges", name, i, nBins[i], binEdges[i].size()); mPrototype->GetAxis(i)->SetTitle(axisTitles[i]); } - init(); } diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index 161c33cbd09b9..2e0401bb92763 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -75,21 +75,29 @@ struct CorrelationTask { TH2F* mControlConvResoncances = nullptr; // control histograms for cuts on conversions and resonances } qa; + // HistogramRegistry registry{"qa", true, { + // {"yields", "centrality vs pT vs eta", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"} }}}, + // {"etaphi", "centrality vs eta vs phi", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {100, -2, 2, "#eta"}, {200, 0, 2 * M_PI, "#varphi"} }}} + // }}; + + OutputObj<TH3F> yields{TH3F("yields", "centrality vs pT vs eta", 100, 0, 100, 40, 0, 20, 100, -2, 2)}; + OutputObj<TH3F> etaphi{TH3F("etaphi", "centrality vs eta vs phi", 100, 0, 100, 100, -2, 2, 200, 0, 2 * M_PI)}; + void init(o2::framework::InitContext&) { // --- CONFIGURATION --- const char* binning = - "vertex: -7, -5, -3, -1, 1, 3, 5, 7\n" - "delta_phi: -1.570796, -1.483530, -1.396263, -1.308997, -1.221730, -1.134464, -1.047198, -0.959931, -0.872665, -0.785398, -0.698132, -0.610865, -0.523599, -0.436332, -0.349066, -0.261799, -0.174533, -0.087266, 0.0, 0.087266, 0.174533, 0.261799, 0.349066, 0.436332, 0.523599, 0.610865, 0.698132, 0.785398, 0.872665, 0.959931, 1.047198, 1.134464, 1.221730, 1.308997, 1.396263, 1.483530, 1.570796, 1.658063, 1.745329, 1.832596, 1.919862, 2.007129, 2.094395, 2.181662, 2.268928, 2.356194, 2.443461, 2.530727, 2.617994, 2.705260, 2.792527, 2.879793, 2.967060, 3.054326, 3.141593, 3.228859, 3.316126, 3.403392, 3.490659, 3.577925, 3.665191, 3.752458, 3.839724, 3.926991, 4.014257, 4.101524, 4.188790, 4.276057, 4.363323, 4.450590, 4.537856, 4.625123, 4.712389\n" - "delta_eta: -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 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, 1.6, 1.7, 1.8, 1.9, 2.0\n" + "vertex: 7 | -7, 7\n" + "delta_phi: 72 | -1.570796, 4.712389\n" + "delta_eta: 40 | -2.0, 2.0\n" "p_t_assoc: 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0\n" "p_t_trigger: 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0\n" "multiplicity: 0, 5, 10, 20, 30, 40, 50, 100.1\n" - "eta: -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0\n" - "p_t_leading: 0.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, 8.5, 9.0, 9.5, 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5, 20.0, 20.5, 21.0, 21.5, 22.0, 22.5, 23.0, 23.5, 24.0, 24.5, 25.0, 25.5, 26.0, 26.5, 27.0, 27.5, 28.0, 28.5, 29.0, 29.5, 30.0, 30.5, 31.0, 31.5, 32.0, 32.5, 33.0, 33.5, 34.0, 34.5, 35.0, 35.5, 36.0, 36.5, 37.0, 37.5, 38.0, 38.5, 39.0, 39.5, 40.0, 40.5, 41.0, 41.5, 42.0, 42.5, 43.0, 43.5, 44.0, 44.5, 45.0, 45.5, 46.0, 46.5, 47.0, 47.5, 48.0, 48.5, 49.0, 49.5, 50.0\n" + "eta: 20 | -1.0, 1.0\n" + "p_t_leading: 100 | 0.0, 50.0\n" "p_t_leading_course: 0.5, 1.0, 2.0, 3.0, 4.0, 6.0, 8.0\n" "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" - "vertex_eff: -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10\n"; + "vertex_eff: 10 | -10, 10\n"; if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) cfg.mPairCuts = true; @@ -137,6 +145,12 @@ struct CorrelationTask { // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); + // control histograms + // ((TH3*) (registry.get("yields").get()))->Fill(centrality, track1.pt(), track1.eta()); + // ((TH3*) (registry.get("etaphi").get()))->Fill(centrality, track1.eta(), track1.phi()); + yields->Fill(centrality, track1.pt(), track1.eta()); + etaphi->Fill(centrality, track1.eta(), track1.phi()); + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) continue; From c8fe54ad7ff6839b8af54082c6fc992a9ac86b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Mon, 21 Sep 2020 18:51:00 +0200 Subject: [PATCH 0708/1751] Move TOF/TPC tasks to dedicated directory (#4404) --- Analysis/Tasks/CMakeLists.txt | 10 ---------- Analysis/Tasks/PWGLF/CMakeLists.txt | 12 +++++++++++- Analysis/Tasks/{ => PWGLF}/spectraTOF.cxx | 0 Analysis/Tasks/{ => PWGLF}/spectraTPC.cxx | 0 4 files changed, 11 insertions(+), 11 deletions(-) rename Analysis/Tasks/{ => PWGLF}/spectraTOF.cxx (100%) rename Analysis/Tasks/{ => PWGLF}/spectraTPC.cxx (100%) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 8c9db9ab64be2..1b8ac438c0eac 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -24,16 +24,6 @@ o2_add_dpl_workflow(qatask PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) -o2_add_dpl_workflow(spectra-tof - SOURCES spectraTOF.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(spectra-tpc - SOURCES spectraTPC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel - COMPONENT_NAME Analysis) - o2_add_dpl_workflow(pid-tof SOURCES pidTOF.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt index 76b96f23e02d1..58e47f6d30780 100644 --- a/Analysis/Tasks/PWGLF/CMakeLists.txt +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -8,6 +8,16 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +o2_add_dpl_workflow(spectra-tof + SOURCES spectraTOF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(spectra-tpc + SOURCES spectraTPC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(nuclei-spectra SOURCES NucleiSpectraTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel @@ -36,4 +46,4 @@ o2_add_dpl_workflow(cascadeproducer o2_add_dpl_workflow(cascadeconsumer SOURCES cascadeconsumer PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/spectraTOF.cxx b/Analysis/Tasks/PWGLF/spectraTOF.cxx similarity index 100% rename from Analysis/Tasks/spectraTOF.cxx rename to Analysis/Tasks/PWGLF/spectraTOF.cxx diff --git a/Analysis/Tasks/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx similarity index 100% rename from Analysis/Tasks/spectraTPC.cxx rename to Analysis/Tasks/PWGLF/spectraTPC.cxx From f4dc8e76e478719a5d838ae1a55f108a63cfa00c Mon Sep 17 00:00:00 2001 From: nzardosh <nima.zardoshti@cern.ch> Date: Tue, 22 Sep 2020 02:33:16 +0200 Subject: [PATCH 0709/1751] correcting D0 cuts (#4406) --- Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index 8061d4538fe78..684512487b612 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -152,7 +152,7 @@ struct HFD0CandidateSelector { return false; } if (hfCandProng2.decayLengthNormalised() * hfCandProng2.decayLengthNormalised() < 1.0) { - return false; + //return false; //add back when getter fixed } return true; } @@ -182,7 +182,7 @@ struct HFD0CandidateSelector { } } - if (TMath::Abs(trackPion.signed1Pt()) < TMath::Abs(cuts[pTBin][4]) || TMath::Abs(trackKaon.signed1Pt()) < TMath::Abs(cuts[pTBin][3])) { + if (TMath::Abs(trackPion.pt()) < TMath::Abs(cuts[pTBin][4]) || TMath::Abs(trackKaon.pt()) < 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]) { @@ -209,7 +209,7 @@ struct HFD0CandidateSelector { template <typename T> bool validTPCPID(const T& track) { - if (TMath::Abs(track.signed1Pt()) < d_pidTPCMinpT || TMath::Abs(track.signed1Pt()) >= d_pidTPCMaxpT) { + if (TMath::Abs(track.pt()) < d_pidTPCMinpT || TMath::Abs(track.pt()) >= d_pidTPCMaxpT) { return false; } //if (track.TPCNClsFindable() < d_TPCNClsFindablePIDCut) return false; @@ -223,7 +223,7 @@ struct HFD0CandidateSelector { template <typename T> bool validTOFPID(const T& track) { - if (TMath::Abs(track.signed1Pt()) < d_pidTOFMinpT || TMath::Abs(track.signed1Pt()) >= d_pidTOFMaxpT) { + if (TMath::Abs(track.pt()) < d_pidTOFMinpT || TMath::Abs(track.pt()) >= d_pidTOFMaxpT) { return false; } return true; From 69837998586d860fed00f884e69743030d4b4588 Mon Sep 17 00:00:00 2001 From: Gian Michele Innocenti <gminnocen@gmail.com> Date: Tue, 22 Sep 2020 09:02:41 +0200 Subject: [PATCH 0710/1751] Add 3 prong secondary vertex histograms + fix histogram ranges (#4405) --- Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 9 ++++++++- Analysis/Tasks/PWGHF/taskD0.cxx | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 9ab180e1b2908..ba0988ab0882d 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -88,9 +88,12 @@ struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 1000, -2.0, 2.0)}; - OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 1000, -10.0, 10.0)}; + OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 1000, -20.0, 20.0)}; OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 1.6, 2.1)}; + OutputObj<TH1F> hvtx3_x_out{TH1F("hvtx3_x", "3-track vtx", 1000, -2.0, 2.0)}; + OutputObj<TH1F> hvtx3_y_out{TH1F("hvtx3_y", "3-track vtx", 1000, -2.0, 2.0)}; + OutputObj<TH1F> hvtx3_z_out{TH1F("hvtx3_z", "3-track vtx", 1000, -20.0, 20.0)}; Filter filterSelectTracks = aod::seltrack::issel == 1; using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>>; @@ -218,6 +221,7 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(0).getPxPyPzGlo(pvec0); df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); + const auto& secondaryVertex3 = df3.getPCACandidate(); // calculate invariant mass arr3Mom = array{pvec0, pvec1, pvec2}; @@ -225,6 +229,9 @@ struct HFTrackIndexSkimsCreator { if (b_dovalplots) { hmass3->Fill(mass3PiKPi); + hvtx3_x_out->Fill(secondaryVertex3[0]); + hvtx3_y_out->Fill(secondaryVertex3[1]); + hvtx3_z_out->Fill(secondaryVertex3[2]); } // fill table row diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index 8372ffa1c9d10..ac64e41ef3e6d 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -39,10 +39,10 @@ struct TaskD0 { OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0, 10.0)}; OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0, 10.0)}; OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0, 10.0)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 100, 0., 1.0)}; - OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 100, 0., 1.0)}; + OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.0)}; + OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.0)}; OutputObj<TH1F> hd0{TH1F("hd0", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; - OutputObj<TH1F> hd0d0{TH1F("hd0d0", "product of dca xy to prim. vertex (cm^{2})", 100, -1.0, 1.0)}; + OutputObj<TH1F> hd0d0{TH1F("hd0d0", "product of dca xy to prim. vertex (cm^{2})", 500, -1.0, 1.0)}; OutputObj<TH1F> hCTS{TH1F("hCTS", "cos #it{#theta}*", 120, -1.1, 1.1)}; OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; From e75f5475f51a5a3468b458cac9addf277a4e0e98 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 22 Sep 2020 09:20:00 +0200 Subject: [PATCH 0711/1751] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd39cc5b037dc..bd3afeb09f947 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: run: | set -x git fetch origin - git checkout -B ${{ steps.decide_release_branch.outputs.branch }} origin/${{ steps.decide_release_branch.outputs.branch }} + git checkout -B ${{ steps.decide_release_branch.outputs.branch }} git config --global user.email "alibuild@cern.ch" git config --global user.name "ALICE Action Bot" git tag ${{ github.event.inputs.tag }} From 8bf87249590db916ab9deb8a77b2bcab36245c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Tue, 22 Sep 2020 14:03:10 +0200 Subject: [PATCH 0712/1751] Update timestamp task (#4409) - add explicit error when requesting a run which is not in the SOR orbit converter --- Analysis/Tasks/timestamp.cxx | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/Analysis/Tasks/timestamp.cxx b/Analysis/Tasks/timestamp.cxx index 79d823ed5e21b..f13501cbdca7b 100644 --- a/Analysis/Tasks/timestamp.cxx +++ b/Analysis/Tasks/timestamp.cxx @@ -28,26 +28,29 @@ using namespace o2; struct TimestampTask { Produces<aod::Timestamps> ts_table; /// Table with SOR timestamps produced by the task Service<o2::ccdb::BasicCCDBManager> ccdb; /// Object manager in CCDB - o2::ccdb::CcdbApi api; /// API to access CCDB + o2::ccdb::CcdbApi ccdb_api; /// API to access CCDB std::map<int, int>* mapStartOrbit = nullptr; /// Map of the starting orbit for the run std::pair<int, long> lastCall; /// Last run number processed and its timestamp, needed for caching std::map<int, long> mapRunToTimestamp; /// Cache of processed run numbers // Configurables Configurable<bool> verbose{"verbose", false, "verbose mode"}; - Configurable<std::string> path{"ccdb-path", "RCT/RunInformation/", "path to the ccdb object"}; + Configurable<std::string> rct_path{"rct-path", "RCT/RunInformation/", "path to the ccdb RCT objects for the SOR timestamps"}; + Configurable<std::string> start_orbit_path{"start-orbit-path", "Trigger/StartOrbit", "path to the ccdb SOR orbit objects"}; Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "URL of the CCDB database"}; Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; void init(o2::framework::InitContext&) { LOGF(info, "Initializing TimestampTask"); - mapStartOrbit = ccdb->get<std::map<int, int>>("Trigger/StartOrbit"); + ccdb->setURL(url.value); // Setting URL of CCDB manager from configuration + LOGF(debug, "Getting SOR orbit map from CCDB url '%s' path '%s'", url.value, start_orbit_path.value); + mapStartOrbit = ccdb->get<std::map<int, int>>(start_orbit_path.value); if (!mapStartOrbit) { - LOGF(fatal, "Cannot find map of SOR orbits in CCDB in path Trigger/StartOrbit"); + LOGF(fatal, "Cannot find map of SOR orbits in CCDB in path %s", start_orbit_path.value.data()); } - api.init(url.value); - if (!api.isHostReachable()) { + ccdb_api.init(url.value); + if (!ccdb_api.isHostReachable()) { LOGF(fatal, "CCDB host %s is not reacheable, cannot go forward", url.value.data()); } } @@ -64,8 +67,8 @@ struct TimestampTask { } else { // The run was not requested before: need to acccess CCDB! LOGF(debug, "Getting timestamp from CCDB"); std::map<std::string, std::string> metadata, headers; - const std::string run_path = Form("%s/%i", path.value.data(), bc.runNumber()); - headers = api.retrieveHeaders(run_path, metadata, -1); + const std::string run_path = Form("%s/%i", rct_path.value.data(), bc.runNumber()); + headers = ccdb_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()); } @@ -86,12 +89,15 @@ struct TimestampTask { 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); + const uint16_t initialBC = 0; // exact bc number not relevant due to ms precision of timestamps + if (!mapStartOrbit->count(bc.runNumber())) { + LOGF(fatal, "Cannot find run %i in mapStartOrbit map", bc.runNumber()); + } + const uint32_t initialOrbit = mapStartOrbit->at(bc.runNumber()); + const uint16_t currentBC = isMC ? initialBC : bc.globalBC() % o2::constants::lhc::LHCMaxBunches; + const uint32_t currentOrbit = isMC ? initialOrbit : bc.globalBC() / o2::constants::lhc::LHCMaxBunches; + const InteractionRecord current(currentBC, currentOrbit); + const InteractionRecord initial(initialBC, initialOrbit); ts += (current - initial).bc2ns() / 1000000; ts_table(ts); } From d7cdab62440cf6c8c0252825dae2b50af1bc7367 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 22 Sep 2020 12:16:36 +0200 Subject: [PATCH 0713/1751] A view/adopted version of ConstMCTruthContainer New class ConstMCTruthContainerView. Same functionality as ConstMCTruthContainer but can simply adopt an existing buffer in form of a gsl::span. Useful to adopt labels that have been sent with DPL in shared memory. (This may finally be the only useful version.) --- .../ConstMCTruthContainer.h | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h index da263e5da9c1c..e9bfd6d42be47 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -115,4 +115,85 @@ struct is_specialization<o2::dataformats::ConstMCTruthContainer<T>, std::vector> }; } // namespace o2::framework +namespace o2 +{ +namespace dataformats +{ + +// A "view" label container without owning the storage (similar to gsl::span) +template <typename TruthElement> +class ConstMCTruthContainerView +{ + public: + ConstMCTruthContainerView(gsl::span<const char> const bufferview) : mStorage(bufferview){}; + + // 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<const TruthElement> getLabels(uint32_t dataindex) const + { + if (dataindex >= getIndexedSize()) { + return gsl::span<const TruthElement>(); + } + const auto start = getMCTruthHeader(dataindex).index; + const auto labelsptr = getLabelStart(); + return gsl::span<const TruthElement>(&labelsptr[start], getSize(dataindex)); + } + + // return the number of original data indexed here + size_t getIndexedSize() const { return mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofHeaderElements : 0; } + + // return the number of labels managed in this container + size_t getNElements() const { return mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofTruthElements : 0; } + + private: + gsl::span<const char> mStorage; + + using FlatHeader = typename MCTruthContainer<TruthElement>::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 = &(mStorage)[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 = &(mStorage)[0]; + const auto& flatheader = *reinterpret_cast<FlatHeader const*>(source); + return flatheader; + } + + MCTruthHeaderElement const* const getHeaderStart() const + { + auto* source = &(mStorage)[0]; + source += sizeof(FlatHeader); + return (MCTruthHeaderElement const* const)source; + } +}; + +} // namespace dataformats +} // namespace o2 + #endif //O2_CONSTMCTRUTHCONTAINER_H From 7936fc6a94c143451f4f2044091c70e6e5a16102 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 22 Sep 2020 12:20:09 +0200 Subject: [PATCH 0714/1751] MCTruthContainer: Function to clear + dealloc memory --- .../include/SimulationDataFormat/MCTruthContainer.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h index 801276ecad36b..65d3ba4876121 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h @@ -165,6 +165,16 @@ class MCTruthContainer mTruthArray.clear(); } + // clear and force freeing the memory + void clear_andfreememory() + { + clear(); + // this forces the desctructor being called on existing buffers + mHeaderArray = std::vector<MCTruthHeaderElement>(); + mTruthArray = std::vector<TruthElement>(); + mStreamerData = std::vector<char>(); + } + // add element for a particular dataindex // at the moment only strictly consecutive modes are supported void addElement(uint32_t dataindex, TruthElement const& element) From 6252f4d148a770b00df3f88735075277fd825377 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 22 Sep 2020 12:22:11 +0200 Subject: [PATCH 0715/1751] New adopt function in IOMCTruthContainerView Allow adoption of gsl::span in addition to std::vector. --- .../include/SimulationDataFormat/IOMCTruthContainerView.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h index 15e88dc77a1aa..66c743feb834a 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h +++ b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h @@ -40,12 +40,17 @@ class IOMCTruthContainerView /// 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<char> const& input) + { + adopt(gsl::span<const char>(&(input[0]), input.size())); + } + + IOMCTruthContainerView(gsl::span<const char> const input) { adopt(input); } /// "adopt" (without taking ownership) from an existing buffer - void adopt(std::vector<char> const& input) + void adopt(gsl::span<const char> const input) { const auto delta = input.size() / N; N2 = input.size() - (N - 1) * delta; From 8e95835b49f0c69bedc1a1336c4bc90c4048f655 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 22 Sep 2020 17:11:58 +0200 Subject: [PATCH 0716/1751] DPL: speedup generic table reading (#4413) --- .../Core/include/Framework/TableTreeHelpers.h | 6 ++ Framework/Core/src/TableTreeHelpers.cxx | 76 ++++++++++++++++--- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/Framework/Core/include/Framework/TableTreeHelpers.h b/Framework/Core/include/Framework/TableTreeHelpers.h index 2be51630f6a5a..91adac34bae3a 100644 --- a/Framework/Core/include/Framework/TableTreeHelpers.h +++ b/Framework/Core/include/Framework/TableTreeHelpers.h @@ -192,6 +192,9 @@ class ColumnIterator // copy the TTreeReaderValue to the arrow::TBuilder void push(); + // reserve enough space to push s elements without reallocating + void reserve(size_t s); + std::shared_ptr<arrow::Array> getArray() { return mArray; } std::shared_ptr<arrow::Field> getSchema() { return mField; } @@ -225,6 +228,9 @@ class TreeToTable // add all columns bool addAllColumns(); + // reserve enough space to push s rows without reallocating + void reserve(size_t s); + // do the looping with the TTreeReader void fill(); diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 9e185d787957e..ea8699e490d3c 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -545,6 +545,50 @@ bool ColumnIterator::getStatus() return mStatus; } +void ColumnIterator::reserve(size_t s) +{ + arrow::Status stat; + + switch (mElementType) { + case EDataType::kBool_t: + stat = mTableBuilder_o->Reserve(s * mNumberElements); + break; + case EDataType::kUChar_t: + stat = mTableBuilder_ub->Reserve(s * mNumberElements); + break; + case EDataType::kUShort_t: + stat = mTableBuilder_us->Reserve(s * mNumberElements); + break; + case EDataType::kUInt_t: + stat = mTableBuilder_ui->Reserve(s * mNumberElements); + break; + case EDataType::kULong64_t: + stat = mTableBuilder_ul->Reserve(s * mNumberElements); + break; + case EDataType::kChar_t: + stat = mTableBuilder_b->Reserve(s * mNumberElements); + break; + case EDataType::kShort_t: + stat = mTableBuilder_s->Reserve(s * mNumberElements); + break; + case EDataType::kInt_t: + stat = mTableBuilder_i->Reserve(s * mNumberElements); + break; + case EDataType::kLong64_t: + stat = mTableBuilder_l->Reserve(s * mNumberElements); + break; + case EDataType::kFloat_t: + stat = mTableBuilder_f->Reserve(s * mNumberElements); + break; + case EDataType::kDouble_t: + stat = mTableBuilder_d->Reserve(s * mNumberElements); + break; + default: + LOGP(FATAL, "Type {} not handled!", mElementType); + break; + } +} + void ColumnIterator::push() { arrow::Status stat; @@ -553,37 +597,37 @@ void ColumnIterator::push() if (mNumberElements == 1) { switch (mElementType) { case EDataType::kBool_t: - stat = mTableBuilder_o->Append((bool)**mReaderValue_o); + mTableBuilder_o->UnsafeAppend((bool)**mReaderValue_o); break; case EDataType::kUChar_t: - stat = mTableBuilder_ub->Append(**mReaderValue_ub); + mTableBuilder_ub->UnsafeAppend(**mReaderValue_ub); break; case EDataType::kUShort_t: - stat = mTableBuilder_us->Append(**mReaderValue_us); + mTableBuilder_us->UnsafeAppend(**mReaderValue_us); break; case EDataType::kUInt_t: - stat = mTableBuilder_ui->Append(**mReaderValue_ui); + mTableBuilder_ui->UnsafeAppend(**mReaderValue_ui); break; case EDataType::kULong64_t: - stat = mTableBuilder_ul->Append(**mReaderValue_ul); + mTableBuilder_ul->UnsafeAppend(**mReaderValue_ul); break; case EDataType::kChar_t: - stat = mTableBuilder_b->Append(**mReaderValue_b); + mTableBuilder_b->UnsafeAppend(**mReaderValue_b); break; case EDataType::kShort_t: - stat = mTableBuilder_s->Append(**mReaderValue_s); + mTableBuilder_s->UnsafeAppend(**mReaderValue_s); break; case EDataType::kInt_t: - stat = mTableBuilder_i->Append(**mReaderValue_i); + mTableBuilder_i->UnsafeAppend(**mReaderValue_i); break; case EDataType::kLong64_t: - stat = mTableBuilder_l->Append(**mReaderValue_l); + mTableBuilder_l->UnsafeAppend(**mReaderValue_l); break; case EDataType::kFloat_t: - stat = mTableBuilder_f->Append(**mReaderValue_f); + mTableBuilder_f->UnsafeAppend(**mReaderValue_f); break; case EDataType::kDouble_t: - stat = mTableBuilder_d->Append(**mReaderValue_d); + mTableBuilder_d->UnsafeAppend(**mReaderValue_d); break; default: LOGP(FATAL, "Type {} not handled!", mElementType); @@ -737,8 +781,18 @@ void TreeToTable::push() } } +void TreeToTable::reserve(size_t s) +{ + for (auto column : mColumnIterators) { + column->reserve(s); + } +} + void TreeToTable::fill() { + auto numEntries = mTreeReader->GetEntries(true); + + this->reserve(numEntries); // copy all values from the tree to the table builders mTreeReader->Restart(); while (mTreeReader->Next()) { From a0cc223562f2b5a171c81437e7925a0abe52d173 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Tue, 22 Sep 2020 19:39:46 +0200 Subject: [PATCH 0717/1751] TrackSelection: add pt dependent dca cut (#4372) Co-authored-by: Mario Kruger <mario.kruger@cern.ch> --- .../Core/include/Analysis/TrackSelection.h | 88 ++++++------ Analysis/Core/src/TrackSelection.cxx | 7 +- Analysis/Tasks/trackselection.cxx | 130 +++++++++--------- 3 files changed, 111 insertions(+), 114 deletions(-) diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/Analysis/TrackSelection.h index 769c6f10b84c8..6715ae769a60a 100644 --- a/Analysis/Core/include/Analysis/TrackSelection.h +++ b/Analysis/Core/include/Analysis/TrackSelection.h @@ -17,14 +17,13 @@ #include "Framework/Logger.h" #include "Framework/DataTypes.h" -#include "TObject.h" #include <set> +#include "TObject.h" class TrackSelection : public TObject { - public: - TrackSelection(); + TrackSelection() = default; // Temporary function to check if track passes selection criteria. To be // replaced by framework filters @@ -32,19 +31,20 @@ class TrackSelection : public TObject bool IsSelected(T const& track) { if (track.trackType() == mTrackType && - track.pt() >= mMinPt && track.pt() < mMaxPt && track.eta() >= mMinEta && - track.eta() < mMaxEta && track.tpcNClsFound() >= mMinNClustersTPC && + track.pt() >= mMinPt && track.pt() <= mMaxPt && track.eta() >= mMinEta && + track.eta() <= mMaxEta && track.tpcNClsFound() >= mMinNClustersTPC && track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC && track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC && (track.itsNCls() >= mMinNClustersITS) && - (track.itsChi2NCl() < mMaxChi2PerClusterITS) && - (track.tpcChi2NCl() < mMaxChi2PerClusterTPC) && + (track.itsChi2NCl() <= mMaxChi2PerClusterITS) && + (track.tpcChi2NCl() <= mMaxChi2PerClusterTPC) && ((mRequireITSRefit) ? (track.flags() & 0x4) : true) && ((mRequireTPCRefit) ? (track.flags() & 0x40) : true) && ((mRequireTOF) ? ((track.flags() & 0x2000) && (track.flags() & 0x80000000)) : true) && FulfillsITSHitRequirements(track.itsClusterMap()) && - abs(track.dcaXY()) < mMaxDcaXY && abs(track.dcaZ()) < mMaxDcaZ) { + abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY) && + abs(track.dcaZ()) < mMaxDcaZ) { return true; } else { return false; @@ -52,10 +52,16 @@ class TrackSelection : public TObject } void SetTrackType(o2::aod::track::TrackTypeEnum trackType) { mTrackType = trackType; } - void SetMinPt(float minPt) { mMinPt = minPt; } - void SetMaxPt(float maxPt) { mMaxPt = maxPt; } - void SetMinEta(float minEta) { mMinEta = minEta; } - void SetMaxEta(float maxEta) { mMaxEta = maxEta; } + void SetPtRange(float minPt = 0.f, float maxPt = 1e10f) + { + mMinPt = minPt; + mMaxPt = maxPt; + } + void SetEtaRange(float minEta = -1e10f, float maxEta = 1e10f) + { + mMinEta = minEta; + mMaxEta = maxEta; + } void SetRequireITSRefit(bool requireITSRefit = true) { mRequireITSRefit = requireITSRefit; @@ -76,8 +82,7 @@ class TrackSelection : public TObject void SetMinNCrossedRowsOverFindableClustersTPC( float minNCrossedRowsOverFindableClustersTPC) { - mMinNCrossedRowsOverFindableClustersTPC = - minNCrossedRowsOverFindableClustersTPC; + mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; } void SetMinNClustersITS(int minNClustersITS) { @@ -93,15 +98,18 @@ class TrackSelection : public TObject } void SetMaxDcaXY(float maxDcaXY) { mMaxDcaXY = maxDcaXY; } void SetMaxDcaZ(float maxDcaZ) { mMaxDcaZ = maxDcaZ; } - void SetRequireHitsInITSLayers(int8_t minNRequiredHits, - std::set<uint8_t> requiredLayers) + + void SetMaxDcaXYPtDep(std::function<float(float)> ptDepCut) + { + mMaxDcaXYPtDep = ptDepCut; + } + void SetRequireHitsInITSLayers(int8_t minNRequiredHits, std::set<uint8_t> requiredLayers) { // layer 0 corresponds to the the innermost ITS layer if (minNRequiredHits > requiredLayers.size()) { LOGF(FATAL, "More ITS hits required than layers specified."); } else { - mRequiredITSHits.push_back( - std::make_pair(minNRequiredHits, requiredLayers)); + mRequiredITSHits.push_back(std::make_pair(minNRequiredHits, requiredLayers)); } }; void SetRequireNoHitsInITSLayers(std::set<uint8_t> excludedLayers) @@ -113,32 +121,32 @@ class TrackSelection : public TObject private: bool FulfillsITSHitRequirements(uint8_t itsClusterMap); - o2::aod::track::TrackTypeEnum mTrackType; + o2::aod::track::TrackTypeEnum mTrackType{o2::aod::track::TrackTypeEnum::GlobalTrack}; // kinematic cuts - float mMinPt, mMaxPt; // range in pT - float mMinEta, mMaxEta; // range in eta + float mMinPt{0.f}, mMaxPt{1e10f}; // range in pT + float mMinEta{-1e10f}, mMaxEta{1e10f}; // range in eta // track quality cuts - int mMinNClustersTPC; // min number of TPC clusters - int mMinNCrossedRowsTPC; // min number of crossed rows in TPC - int mMinNClustersITS; // min number of ITS clusters - float mMaxChi2PerClusterTPC; // max tpc fit chi2 per TPC cluster - float mMaxChi2PerClusterITS; // max its fit chi2 per ITS cluster - float mMinNCrossedRowsOverFindableClustersTPC; // min ratio crossed rows / - // findable clusters - - float mMaxDcaXY; - float mMaxDcaZ; - - bool mRequireITSRefit; // require refit in ITS - bool mRequireTPCRefit; // require refit in TPC - bool mRequireTOF; // require that track exits the TOF and that it has an associated time measurement (kTIME and kTOFOUT) - - std::vector<std::pair<int8_t, std::set<uint8_t>>> - mRequiredITSHits; // vector of ITS requirements (minNRequiredHits in - // specific requiredLayers) - ClassDef(TrackSelection, 1) + int mMinNClustersTPC{0}; // min number of TPC clusters + int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC + int mMinNClustersITS{0}; // min number of ITS clusters + float mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster + float mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster + float mMinNCrossedRowsOverFindableClustersTPC{0}; // min ratio crossed rows / findable clusters + + float mMaxDcaXY{1e10f}; + float mMaxDcaZ{1e10f}; + std::function<float(float)> mMaxDcaXYPtDep{}; + + bool mRequireITSRefit{false}; // require refit in ITS + bool mRequireTPCRefit{false}; // require refit in TPC + bool mRequireTOF{false}; // require that track exits the TOF and that it has an associated time measurement (kTIME and kTOFOUT) + + // vector of ITS requirements (minNRequiredHits in specific requiredLayers) + std::vector<std::pair<int8_t, std::set<uint8_t>>> mRequiredITSHits{}; + + ClassDef(TrackSelection, 1); }; #endif diff --git a/Analysis/Core/src/TrackSelection.cxx b/Analysis/Core/src/TrackSelection.cxx index a663acbfa5ad2..665d0efbd3b8b 100644 --- a/Analysis/Core/src/TrackSelection.cxx +++ b/Analysis/Core/src/TrackSelection.cxx @@ -15,12 +15,7 @@ #include "Analysis/TrackSelection.h" #include <TH1F.h> -ClassImp(TrackSelection) - - TrackSelection::TrackSelection() - : TObject(), mTrackType{o2::aod::track::TrackTypeEnum::GlobalTrack}, mMinPt{0.}, mMaxPt{1e10}, mMinEta{-1e10}, mMaxEta{1e10}, mMinNClustersTPC{0}, mMinNCrossedRowsTPC{0}, mMinNClustersITS{0}, mMaxChi2PerClusterTPC{1e10}, mMaxChi2PerClusterITS{1e10}, mMinNCrossedRowsOverFindableClustersTPC{0}, mMaxDcaXY{1e10}, mMaxDcaZ{1e10}, mRequireITSRefit{false}, mRequireTPCRefit{false}, mRequiredITSHits{} -{ -} +ClassImp(TrackSelection); bool TrackSelection::FulfillsITSHitRequirements(uint8_t itsClusterMap) { diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index 2d92ea7669d41..23e7e1ca98796 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -38,32 +38,28 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) TrackSelection getGlobalTrackSelection() { TrackSelection selectedTracks; - selectedTracks.SetMinPt(0.1f); - selectedTracks.SetMaxPt(1e10f); - selectedTracks.SetMinEta(-0.8f); - selectedTracks.SetMaxEta(0.8f); + selectedTracks.SetPtRange(0.1f, 1e10f); + selectedTracks.SetEtaRange(-0.8f, 0.8f); selectedTracks.SetRequireITSRefit(true); selectedTracks.SetRequireTPCRefit(true); selectedTracks.SetMinNCrossedRowsTPC(70); selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); selectedTracks.SetMaxChi2PerClusterTPC(4.f); + selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer selectedTracks.SetMaxChi2PerClusterITS(36.f); - selectedTracks.SetRequireHitsInITSLayers(1, - {0, 1}); // one hit in any SPD layer - selectedTracks.SetMaxDcaXY(2.4f); + selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); selectedTracks.SetMaxDcaZ(2.f); return selectedTracks; } // Default track selection requiring no hit in the SPD and one in the innermost -// SDD +// SDD -> complementary tracks to global selection TrackSelection getGlobalTrackSelectionSDD() { TrackSelection selectedTracks = getGlobalTrackSelection(); selectedTracks.ResetITSRequirements(); selectedTracks.SetRequireNoHitsInITSLayers({0, 1}); // no hit in SPD layers - selectedTracks.SetRequireHitsInITSLayers(1, - {2}); // one hit in first SDD layer + selectedTracks.SetRequireHitsInITSLayers(1, {2}); // one hit in first SDD layer return selectedTracks; } @@ -71,7 +67,7 @@ TrackSelection getGlobalTrackSelectionSDD() TrackSelection getGlobalTrackSelectionwTOF() { TrackSelection selectedTracks = getGlobalTrackSelection(); - selectedTracks.SetRequireTOF(kTRUE); + selectedTracks.SetRequireTOF(true); return selectedTracks; } @@ -146,85 +142,84 @@ struct TrackSelectionTask { struct TrackQATask { Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; - //Filter trackFilter = ((selectedTracks == 1) && (aod::track::isGlobalTrack == true)) || ((selectedTracks == 2) && (aod::track::isGlobalTrackSDD == true)); + + OutputObj<TH2F> dcaxyVsPt{ + TH2F("track-dcaXYvsPt", "DCA xy vs pT;dca-xy [cm];p_{T};p_{T} [GeV/c]", 200, -3., 3., 100, 0., 50.), + OutputObjHandlingPolicy::QAObject}; // track parameters - OutputObj<TH1F> x{TH1F( - "trackpar-x", "track x position at dca in local coordinate system;x [cm]", - 200, -0.4, 0.4), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> x{ + TH1F("trackpar-x", "track x position at dca in local coordinate system;x [cm]", 200, -0.4, 0.4), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> y{TH1F( - "trackpar-y", "track y position at dca in local coordinate system;y [cm]", - 100, -4., 4.), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> y{ + TH1F("trackpar-y", "track y position at dca in local coordinate system;y [cm]", 100, -4., 4.), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> z{TH1F( - "trackpar-z", "track z position at dca in local coordinate system;z [cm]", - 100, -20., 20.), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> z{ + TH1F("trackpar-z", "track z position at dca in local coordinate system;z [cm]", 100, -20., 20.), + OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> alpha{ - TH1F("trackpar-alpha", - "rotation angle of local wrt. global coordinate system;#alpha [rad]", - 100, -(M_PI + 0.01), (M_PI + 0.01)), + TH1F("trackpar-alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 100, -(M_PI + 0.01), (M_PI + 0.01)), OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> signed1Pt{TH1F("trackpar-signed1Pt", - "track signed 1/p_{T};q/p_{T}", 200, - -8, 8), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> signed1Pt{ + TH1F("trackpar-signed1Pt", "track signed 1/p_{T};q/p_{T}", 200, -8, 8), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> snp{TH1F( - "trackpar-snp", "sinus of track momentum azimuthal angle;snp", - 100, -1., 1.), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> snp{ + TH1F("trackpar-snp", "sinus of track momentum azimuthal angle;snp", 100, -1., 1.), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> tgl{TH1F( - "trackpar-tgl", "tangent of the track momentum dip angle;tgl;", - 1000, -2, 2), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> tgl{ + TH1F("trackpar-tgl", "tangent of the track momentum dip angle;tgl;", 1000, -2, 2), + OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> dcaxy{ - TH1F("track-dcaXY", - "distance of closest approach in xy plane;dca-xy [cm];", 200, - -3., 3.), + TH1F("track-dcaXY", "distance of closest approach in xy plane;dca-xy [cm];", 200, -3., 3.), OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> dcaz{TH1F( - "track-dcaZ", "distance of closest approach in z;dca-z [cm];", - 200, -3., 3.), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> dcaz{ + TH1F("track-dcaZ", "distance of closest approach in z;dca-z [cm];", 200, -3., 3.), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> flag{TH1F("track-flags", "track flag;flag bit", 64, -0.5, 63.5), OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> flag{TH1F("track-flags", "track flag;flag bit", 64, -0.5, 63.5), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> pt{TH1F("track-pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.), OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> pt{TH1F("track-pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> eta{TH1F("track-eta", "#eta;#eta", 101, -1.0, 1.0), OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> eta{TH1F("track-eta", "#eta;#eta", 101, -1.0, 1.0), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> phi{TH1F("track-phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI), OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> phi{TH1F("track-phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI), + OutputObjHandlingPolicy::QAObject}; // ITS related quantities OutputObj<TH1F> itsFoundClusters{ - TH1F("its-foundClusters", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5), OutputObjHandlingPolicy::QAObject}; + TH1F("its-foundClusters", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> itsChi2PerCluster{TH1F( - "its-chi2PerCluster", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> itsChi2PerCluster{ + TH1F("its-chi2PerCluster", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> itsHits{TH1F("its-hits", "hitmap ITS;layer ITS", 7, -0.5, 6.5), OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> itsHits{ + TH1F("its-hits", "hitmap ITS;layer ITS", 7, -0.5, 6.5), + OutputObjHandlingPolicy::QAObject}; // TPC related quantities - OutputObj<TH1F> tpcFindableClusters{TH1F( - "tpc-findableClusters", "number of findable TPC clusters;# clusters TPC", 165, -0.5, 164.5), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> tpcFindableClusters{ + TH1F("tpc-findableClusters", "number of findable TPC clusters;# clusters TPC", 165, -0.5, 164.5), + OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcFoundClusters{ TH1F("tpc-foundClusters", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5), OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> tpcSharedClusters{TH1F( - "tpc-sharedClusters", "number of shared TPC clusters;;# shared clusters TPC", 165, -0.5, 164.5), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> tpcSharedClusters{ + TH1F("tpc-sharedClusters", "number of shared TPC clusters;;# shared clusters TPC", 165, -0.5, 164.5), + OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcFractionSharedClusters{ TH1F("tpc-fractionSharedClusters", @@ -232,22 +227,20 @@ struct TrackQATask { OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcCrossedRows{ - TH1F("tpc-crossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5), OutputObjHandlingPolicy::QAObject}; + TH1F("tpc-crossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5), + OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcCrossedRowsOverFindableClusters{ - TH1F("tpc-crossedRowsOverFindableClusters", - "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 110, 0.0, 1.1), + TH1F("tpc-crossedRowsOverFindableClusters", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 110, 0.0, 1.1), OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcChi2PerCluster{ - TH1F("tpc-chi2PerCluster", "chi2 per cluster in TPC;chi2 / cluster TPC", - 100, 0, 10), + TH1F("tpc-chi2PerCluster", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10), OutputObjHandlingPolicy::QAObject}; // collision related quantities OutputObj<TH2F> collisionPos{ - TH2F("collision-xy", "Position of collision;x [cm];y [cm]", 100, - -0.5, 0.5, 100, -0.5, 0.5), + TH2F("collision-xy", "Position of collision;x [cm];y [cm]", 100, -0.5, 0.5, 100, -0.5, 0.5), OutputObjHandlingPolicy::QAObject}; void init(o2::framework::InitContext&) {} @@ -292,6 +285,7 @@ struct TrackQATask { dcaxy->Fill(track.dcaXY()); dcaz->Fill(track.dcaZ()); + dcaxyVsPt->Fill(track.dcaXY(), track.pt()); signed1Pt->Fill(track.signed1Pt()); snp->Fill(track.snp()); From 774d15909eaf3de80fa9ee21b76ad1d3d13b16f8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 22 Sep 2020 22:11:54 +0200 Subject: [PATCH 0718/1751] DPL: drop debug statements (#4408) --- Framework/Core/src/DataAllocator.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index f1885b7c898f3..3dba019767e77 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -181,9 +181,6 @@ void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) std::shared_ptr<TreeToTable> p(t2t); auto finalizer = [payload = p](std::shared_ptr<FairMQResizableBuffer> b) -> void { auto table = payload->finalize(); - LOG(INFO) << "DataAllocator Table created!"; - LOG(INFO) << "Number of columns " << table->num_columns(); - LOG(INFO) << "Number of rows " << table->num_rows(); auto stream = std::make_shared<arrow::io::BufferOutputStream>(b); std::shared_ptr<arrow::ipc::RecordBatchWriter> writer; From 000c5833b196db42c57dd57bce088871bb7e8bd2 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 23 Sep 2020 09:55:27 +0200 Subject: [PATCH 0719/1751] TrackSelection: drop TObject inheritance (#4414) Co-authored-by: Mario Kruger <mario.kruger@cern.ch> --- .../Core/include/Analysis/TrackSelection.h | 47 +++++++++---------- Analysis/Core/src/TrackSelection.cxx | 3 -- Analysis/Tasks/trackselection.cxx | 26 +++++----- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/Analysis/TrackSelection.h index 6715ae769a60a..1ad02643500c7 100644 --- a/Analysis/Core/include/Analysis/TrackSelection.h +++ b/Analysis/Core/include/Analysis/TrackSelection.h @@ -18,24 +18,24 @@ #include "Framework/Logger.h" #include "Framework/DataTypes.h" #include <set> -#include "TObject.h" +#include <vector> +#include "Rtypes.h" -class TrackSelection : public TObject +class TrackSelection { public: TrackSelection() = default; - // Temporary function to check if track passes selection criteria. To be - // replaced by framework filters + // Temporary function to check if track passes selection criteria. To be replaced by framework filters. template <typename T> bool IsSelected(T const& track) { if (track.trackType() == mTrackType && - track.pt() >= mMinPt && track.pt() <= mMaxPt && track.eta() >= mMinEta && - track.eta() <= mMaxEta && track.tpcNClsFound() >= mMinNClustersTPC && + track.pt() >= mMinPt && track.pt() <= mMaxPt && + track.eta() >= mMinEta && track.eta() <= mMaxEta && + track.tpcNClsFound() >= mMinNClustersTPC && track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC && - track.tpcCrossedRowsOverFindableCls() >= - mMinNCrossedRowsOverFindableClustersTPC && + track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC && (track.itsNCls() >= mMinNClustersITS) && (track.itsChi2NCl() <= mMaxChi2PerClusterITS) && (track.tpcChi2NCl() <= mMaxChi2PerClusterTPC) && @@ -44,7 +44,7 @@ class TrackSelection : public TObject ((mRequireTOF) ? ((track.flags() & 0x2000) && (track.flags() & 0x80000000)) : true) && FulfillsITSHitRequirements(track.itsClusterMap()) && abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY) && - abs(track.dcaZ()) < mMaxDcaZ) { + abs(track.dcaZ()) <= mMaxDcaZ) { return true; } else { return false; @@ -79,8 +79,7 @@ class TrackSelection : public TObject { mMinNCrossedRowsTPC = minNCrossedRowsTPC; } - void SetMinNCrossedRowsOverFindableClustersTPC( - float minNCrossedRowsOverFindableClustersTPC) + void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC) { mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; } @@ -111,12 +110,12 @@ class TrackSelection : public TObject } else { mRequiredITSHits.push_back(std::make_pair(minNRequiredHits, requiredLayers)); } - }; + } void SetRequireNoHitsInITSLayers(std::set<uint8_t> excludedLayers) { mRequiredITSHits.push_back(std::make_pair(-1, excludedLayers)); - }; - void ResetITSRequirements() { mRequiredITSHits.clear(); }; + } + void ResetITSRequirements() { mRequiredITSHits.clear(); } private: bool FulfillsITSHitRequirements(uint8_t itsClusterMap); @@ -128,16 +127,16 @@ class TrackSelection : public TObject float mMinEta{-1e10f}, mMaxEta{1e10f}; // range in eta // track quality cuts - int mMinNClustersTPC{0}; // min number of TPC clusters - int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC - int mMinNClustersITS{0}; // min number of ITS clusters - float mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster - float mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster - float mMinNCrossedRowsOverFindableClustersTPC{0}; // min ratio crossed rows / findable clusters - - float mMaxDcaXY{1e10f}; - float mMaxDcaZ{1e10f}; - std::function<float(float)> mMaxDcaXYPtDep{}; + int mMinNClustersTPC{0}; // min number of TPC clusters + int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC + int mMinNClustersITS{0}; // min number of ITS clusters + float mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster + float mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster + float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + + float mMaxDcaXY{1e10f}; // max dca in xy plane + float mMaxDcaZ{1e10f}; // max dca in z direction + std::function<float(float)> mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mRequireITSRefit{false}; // require refit in ITS bool mRequireTPCRefit{false}; // require refit in TPC diff --git a/Analysis/Core/src/TrackSelection.cxx b/Analysis/Core/src/TrackSelection.cxx index 665d0efbd3b8b..15773743f0eb7 100644 --- a/Analysis/Core/src/TrackSelection.cxx +++ b/Analysis/Core/src/TrackSelection.cxx @@ -13,9 +13,6 @@ // #include "Analysis/TrackSelection.h" -#include <TH1F.h> - -ClassImp(TrackSelection); bool TrackSelection::FulfillsITSHitRequirements(uint8_t itsClusterMap) { diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index 23e7e1ca98796..8750936b84fb8 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -184,17 +184,21 @@ struct TrackQATask { TH1F("track-dcaZ", "distance of closest approach in z;dca-z [cm];", 200, -3., 3.), OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> flag{TH1F("track-flags", "track flag;flag bit", 64, -0.5, 63.5), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> flag{ + TH1F("track-flags", "track flag;flag bit", 64, -0.5, 63.5), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> pt{TH1F("track-pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> pt{ + TH1F("track-pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> eta{TH1F("track-eta", "#eta;#eta", 101, -1.0, 1.0), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> eta{ + TH1F("track-eta", "#eta;#eta", 101, -1.0, 1.0), + OutputObjHandlingPolicy::QAObject}; - OutputObj<TH1F> phi{TH1F("track-phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI), - OutputObjHandlingPolicy::QAObject}; + OutputObj<TH1F> phi{ + TH1F("track-phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI), + OutputObjHandlingPolicy::QAObject}; // ITS related quantities OutputObj<TH1F> itsFoundClusters{ @@ -215,15 +219,15 @@ struct TrackQATask { OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcFoundClusters{ - TH1F("tpc-foundClusters", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5), OutputObjHandlingPolicy::QAObject}; + TH1F("tpc-foundClusters", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5), + OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcSharedClusters{ TH1F("tpc-sharedClusters", "number of shared TPC clusters;;# shared clusters TPC", 165, -0.5, 164.5), OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcFractionSharedClusters{ - TH1F("tpc-fractionSharedClusters", - "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.), + TH1F("tpc-fractionSharedClusters", "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.), OutputObjHandlingPolicy::QAObject}; OutputObj<TH1F> tpcCrossedRows{ From 8427e9f2f54184c628769ec5360251c7d556aecb Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez@cern.ch> Date: Wed, 23 Sep 2020 14:40:54 +0200 Subject: [PATCH 0720/1751] Correct track selection according to FB96 (#4415) Also - removed the phi limits from the configuration. Full azimuthal range covered --- .../Tasks/PWGCF/AnalysisConfigurableCuts.h | 24 +++++++++---------- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 23 ++++++------------ 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h b/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h index d60324960c3d6..9c916039f9542 100644 --- a/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h +++ b/Analysis/Tasks/PWGCF/AnalysisConfigurableCuts.h @@ -40,19 +40,17 @@ class EventSelectionCuts class DptDptBinningCuts { public: - int mZVtxbins = 28; ///< the number of z_vtx bins default 28 - float mZVtxmin = -7.0; ///< the minimum z_vtx value, default -7.0 cm - float mZVtxmax = 7.0; ///< the maximum z_vtx value, default 7.0 cm - int mPTbins = 18; ///< the number of pT bins, default 18 - float mPTmin = 0.2; ///< the minimum pT value, default 0.2 GeV - float mPTmax = 2.0; ///< the maximum pT value, default 2.0 GeV - int mEtabins = 16; ///< the number of eta bins default 16 - float mEtamin = -0.8; ///< the minimum eta value, default -0.8 - float mEtamax = 0.8; ///< the maximum eta value, default 0.8 - int mPhibins = 72; ///< the number of phi bins, default 72 - float mPhimin = 0.0; ///< the minimum phi value, default 0.0 - float mPhimax = TMath::TwoPi(); ///< the maximum phi value, default 2*pi - float mPhibinshift = 0.5; ///< the shift in the azimuthal origen, defoult 0.5, i.e half a bin + int mZVtxbins = 28; ///< the number of z_vtx bins default 28 + float mZVtxmin = -7.0; ///< the minimum z_vtx value, default -7.0 cm + float mZVtxmax = 7.0; ///< the maximum z_vtx value, default 7.0 cm + int mPTbins = 18; ///< the number of pT bins, default 18 + float mPTmin = 0.2; ///< the minimum pT value, default 0.2 GeV + float mPTmax = 2.0; ///< the maximum pT value, default 2.0 GeV + int mEtabins = 16; ///< the number of eta bins default 16 + float mEtamin = -0.8; ///< the minimum eta value, default -0.8 + float mEtamax = 0.8; ///< the maximum eta value, default 0.8 + int mPhibins = 72; ///< the number of phi bins, default 72 + float mPhibinshift = 0.5; ///< the shift in the azimuthal origen, defoult 0.5, i.e half a bin private: ClassDefNV(DptDptBinningCuts, 1); diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index f228e03a8d1f5..5678fc3cf3d83 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -34,9 +34,6 @@ using namespace o2::framework::expressions; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { - // std::vector<ConfigParamSpec> options{ - // {"centralities", VariantType::String, "0-5,5-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", {"Centrality/multiplicity ranges in min-max separated by commas"}}}; - // std::swap(workflowOptions, options); ConfigParamSpec centspec = {"centralities", VariantType::String, "0-5,5-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", @@ -221,13 +218,7 @@ bool matchTrackType(aod::TrackData const& track) { switch (tracktype) { case 1: - if (track.isGlobalTrack() != 0) - return true; - else - return false; - break; - case 2: - if (track.isGlobalTrackSDD() != 0) + if (track.isGlobalTrack() != 0 || track.isGlobalTrackSDD() != 0) return true; else return false; @@ -284,14 +275,14 @@ using namespace dptdptcorrelations; struct DptDptCorrelationsFilterAnalysisTask { - Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks loose DCA, 2 = global SDD tracks"}; + Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks FB96"}; Configurable<int> cfgTrackOneCharge{"trk1charge", -1, "Trakc one charge: 1 = positive, -1 = negative"}; Configurable<int> cfgTrackTwoCharge{"trk2charge", -1, "Trakc two charge: 1 = positive, -1 = negative"}; Configurable<bool> cfgProcessPairs{"processpairs", true, "Process pairs: false = no, just singles, true = yes, process pairs"}; Configurable<std::string> cfgCentMultEstimator{"centmultestimator", "V0M", "Centrality/multiplicity estimator detector: default V0M"}; Configurable<o2::analysis::DptDptBinningCuts> cfgBinning{"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.0, TMath::TwoPi()}, + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; @@ -453,7 +444,7 @@ struct DptDptCorrelationsTask { Configurable<bool> cfgProcessPairs{"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}; Configurable<o2::analysis::DptDptBinningCuts> cfgBinning{"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.0, TMath::TwoPi()}, + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}; @@ -468,7 +459,7 @@ struct DptDptCorrelationsTask { float cmmax, Configurable<bool> _cfgProcessPairs = {"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}, Configurable<o2::analysis::DptDptBinningCuts> _cfgBinning = {"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.0, TMath::TwoPi()}, + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}, OutputObj<TList> _fOutput = {"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}, Filter _onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE), @@ -502,8 +493,8 @@ struct DptDptCorrelationsTask { zvtxlow = cfgBinning->mZVtxmin; zvtxup = cfgBinning->mZVtxmax; phibins = cfgBinning->mPhibins; - philow = cfgBinning->mPhimin; - phiup = cfgBinning->mPhimax; + philow = 0.0f; + phiup = TMath::TwoPi(); phibinshift = cfgBinning->mPhibinshift; processpairs = cfgProcessPairs.value; /* update the potential binning change */ From 72afef724e19a2bb6232c3dcbed24febcdd10278 Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Wed, 23 Sep 2020 17:45:10 +0200 Subject: [PATCH 0721/1751] Make histogram registry declaration more readable (#4422) --- Analysis/Tutorials/src/histogramRegistry.cxx | 9 ++++++++- Framework/Core/test/test_HistogramRegistry.cxx | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index 12fe4dd68ee9f..f2ee48279b2d0 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -23,7 +23,14 @@ using namespace o2::framework; // we need GCC 7.4+ for that struct ATask { /// Construct a registry object with direct declaration - HistogramRegistry registry{"registry", true, {{"eta", "#eta", {HistogramType::kTH1F, {{102, -2.01, 2.01}}}}, {"phi", "#varphi", {HistogramType::kTH1F, {{100, 0., 2. * M_PI}}}}}}; + HistogramRegistry registry{ + "registry", + true, + { + {"eta", "#eta", {HistogramType::kTH1F, {{102, -2.01, 2.01}}}}, // + {"phi", "#varphi", {HistogramType::kTH1F, {{100, 0., 2. * M_PI}}}} // + } // + }; void process(aod::Tracks const& tracks) { diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 040f1191a624b..53d4bb0b59900 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -25,7 +25,12 @@ HistogramRegistry foo() BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) { /// Construct a registry object with direct declaration - HistogramRegistry registry{"registry", true, {{"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}}}}; + HistogramRegistry registry{"registry", true, { + {"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, // + {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, // + {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, // + {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // + }}; /// Get histograms by name BOOST_REQUIRE_EQUAL(registry.get("eta")->GetNbinsX(), 100); From fdd4548c7fc90ad7480d5e9cd7c4ec10d7931c1d Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 23 Sep 2020 17:45:56 +0200 Subject: [PATCH 0722/1751] HistHelpers: add some more features (#4421) * HistHelpers: support TFolder based collections * HistHelpers: make ROOT container inheritance private * OutputObj: allow to directly digest shared_ptrs * HistHelpers: example how to use Hist<> object to generate standalone histogram Co-authored-by: Mario Kruger <mario.kruger@cern.ch> --- Analysis/Core/include/Analysis/HistHelpers.h | 18 ++++++++------- Analysis/Tutorials/src/histHelpersTest.cxx | 22 +++++++++++++++---- .../Core/include/Framework/AnalysisHelpers.h | 6 +++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/Analysis/HistHelpers.h index 63b3d2513090a..133578d500bb0 100644 --- a/Analysis/Core/include/Analysis/HistHelpers.h +++ b/Analysis/Core/include/Analysis/HistHelpers.h @@ -25,9 +25,9 @@ #include <TProfile2D.h> #include <TProfile3D.h> +#include <TFolder.h> #include <TObjArray.h> #include <TList.h> -//#include <TDirectory.h> #include "Framework/Logger.h" @@ -48,11 +48,11 @@ struct is_shared_ptr<std::shared_ptr<T>> : std::true_type { //************************************************************************************************** /** * Container class for storing and saving root histograms of any type. - * RootContainer (TObjArray or TList) inheritance is required to interface with O2 file writing functionality. + * RootContainer (TObjArray, TList or TFolder) inheritance is used to interface with O2 file writing functionality. */ //************************************************************************************************** template <class RootContainer> -class HistContainer : public RootContainer +class HistContainer : private RootContainer { public: HistContainer(const std::string& name) : RootContainer() @@ -122,12 +122,14 @@ class HistContainer : public RootContainer Fill<true>(histID, std::forward<Ts>(positionAndWeight)...); } + // make accessible only the RootContainer functions needed for writing to file + using RootContainer::Class; + using RootContainer::GetName; + private: + // FIXME: map is most likely not the fastest -> array? std::map<uint8_t, HistType> mHistos; - // disallow user to call RootContainer::Add() to avoid memory leaks - using RootContainer::Add; - template <bool fillWeight = false, typename T, typename... Ts> void GenericFill(std::shared_ptr<T> hist, const Ts&... position) { @@ -154,7 +156,7 @@ class HistContainer : public RootContainer else hist->Fill(tempArray); } - }; + } template <typename T> std::optional<HistType> GetHistVariant(std::shared_ptr<TObject> obj) @@ -183,9 +185,9 @@ class HistContainer : public RootContainer }; //************************************************************************************************** +using HistFolder = HistContainer<TFolder>; using HistArray = HistContainer<TObjArray>; using HistList = HistContainer<TList>; -//using HistDirectory = HistContainer<TDirectory>; //************************************************************************************************** //************************************************************************************************** diff --git a/Analysis/Tutorials/src/histHelpersTest.cxx b/Analysis/Tutorials/src/histHelpersTest.cxx index aaddbd758abb2..c604bd25bbeef 100644 --- a/Analysis/Tutorials/src/histHelpersTest.cxx +++ b/Analysis/Tutorials/src/histHelpersTest.cxx @@ -55,9 +55,11 @@ struct HistHelpersTest { OutputObj<HistArray> test{HistArray("Test"), OutputObjHandlingPolicy::QAObject}; OutputObj<HistArray> kine{HistArray("Kine"), OutputObjHandlingPolicy::QAObject}; - OutputObj<HistArray> tpc{HistArray("TPC"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistFolder> tpc{HistFolder("TPC"), OutputObjHandlingPolicy::QAObject}; OutputObj<HistList> its{HistList("ITS"), OutputObjHandlingPolicy::QAObject}; + OutputObj<THnF> standaloneHist{"standaloneHist", OutputObjHandlingPolicy::QAObject}; + void init(o2::framework::InitContext&) { // add some plain and simple histograms @@ -157,6 +159,13 @@ struct HistHelpersTest { thirdHist.AddAxes(baseDimensions); thirdHist.AddAxis("myLastDimension", "a (m/(s*s))", 10, -1, 1); its->Add(Hist_test_8d_THnC_third, thirdHist.Create("thirdHist")); + + // we can also use the Hist heleper tool independent of the HistCollections: + Hist<THnF> myHist; + myHist.AddAxis(ptAxis); + myHist.AddAxis(etaAxis); + myHist.AddAxis(phiAxis); + standaloneHist.setObject(myHist.Create("standaloneHist")); } void process(soa::Join<aod::Tracks, aod::TracksExtra>::iterator const& track) @@ -189,12 +198,17 @@ struct HistHelpersTest { tpc->Fill(Hist_Chi2PerClTPC, track.itsChi2NCl()); its->Fill(Hist_Chi2PerClITS, track.tpcChi2NCl()); + + double dummyArray[] = {track.pt(), track.eta(), track.phi()}; + standaloneHist->Fill(dummyArray); } }; -//-------------------------------------------------------------------- -// Workflow definition -//-------------------------------------------------------------------- +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 8b1e5ca59026b..5907634f8873c 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -400,6 +400,12 @@ struct OutputObj { object->SetName(label.c_str()); } + void setObject(std::shared_ptr<T> t) + { + object = t; + object->SetName(label.c_str()); + } + void setHash(uint32_t hash) { mTaskHash = hash; From 5262393300a3a67d1bcca5fd6b111a9ad6d26d60 Mon Sep 17 00:00:00 2001 From: dsekihat <daiki.sekihata@cern.ch> Date: Thu, 24 Sep 2020 00:46:12 +0900 Subject: [PATCH 0723/1751] PWGDQ: update track selection for dileptonEE (#4420) --- Analysis/Tasks/PWGDQ/dileptonEE.cxx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx index f47bd93c465a9..d047085e6e5c9 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -108,8 +108,8 @@ struct BarrelTrackSelection { cut1->AddCut(VarManager::kTrackDCAxy, -1.0, +1.0); cut1->AddCut(VarManager::kTrackDCAz, -3.0, +3.0); - cut1->AddCut(VarManager::kTPCsignal, 70, 90, false); //exclude = false - cut1->AddCut(VarManager::kTPCsignal, 75, 90, false, VarManager::kPt, 2.0, 1e+10); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, 70, 90, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, 75, 90, false, VarManager::kPin, 2.0, 1e+10); //exclude = false //cut1->AddCut(VarManager::kTOFnSigmaEl, -3, +3, false); //exclude = false //fTrackCut->AddCut(cut1); @@ -120,10 +120,10 @@ struct BarrelTrackSelection { AnalysisCut* pidcut_rejPr = new AnalysisCut("pidcut_rejPr", "proton rejection"); TF1* f1minPr = new TF1("f1minPr", "[0]+[1]*x", 0, 10); - f1minPr->SetParameters(220, -150); + f1minPr->SetParameters(170, -100); TF1* f1maxPr = new TF1("f1maxPr", "[0]+[1]*x", 0, 10); - f1maxPr->SetParameters(195, -100); - pidcut_rejPr->AddCut(VarManager::kTPCsignal, f1minPr, f1maxPr, true, VarManager::kPin, 0.8, 1.25, false); //exclude = false + f1maxPr->SetParameters(175, -75); + pidcut_rejPr->AddCut(VarManager::kTPCsignal, f1minPr, f1maxPr, true, VarManager::kPin, 0.8, 1.4, false); //exclude = false AnalysisCut* pidcut_rejKa = new AnalysisCut("pidcut_rejKa", "kaon rejection"); TF1* f1minKa = new TF1("f1minKa", "[0]+[1]*x", 0, 10); @@ -137,9 +137,9 @@ struct BarrelTrackSelection { f1maxPi->SetParameters(85, -50); pidcut_rejPi->AddCut(VarManager::kTPCsignal, 70, f1maxPi, true, VarManager::kPin, 0.0, 0.4, false); //exclude = false - cut1->AddCut(VarManager::kTPCsignal, f1minPr, f1maxPr, true, VarManager::kPin, 0.8, 1.25, false); //exclude = false - cut1->AddCut(VarManager::kTPCsignal, f1minKa, f1maxKa, true, VarManager::kPin, 0.4, 0.8, false); //exclude = false - cut1->AddCut(VarManager::kTPCsignal, 70, f1maxPi, true, VarManager::kPin, 0.0, 0.4, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, f1minPr, f1maxPr, true, VarManager::kPin, 0.8, 1.4, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, f1minKa, f1maxKa, true, VarManager::kPin, 0.4, 0.8, false); //exclude = false + cut1->AddCut(VarManager::kTPCsignal, 70, f1maxPi, true, VarManager::kPin, 0.0, 0.4, false); //exclude = false //pidcut->AddCut(pidcut_high); //pidcut->AddCut(pidcut_rejPr); @@ -165,7 +165,11 @@ struct BarrelTrackSelection { VarManager::FillTrack<fgTrackFillMap>(track, fValues); fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); - if (fTrackCut->IsSelected(fValues)) { + if (fTrackCut->IsSelected(fValues) && + (track.flags() & (uint64_t(1) << 2)) && // kITSrefit + (track.flags() & (uint64_t(1) << 6)) && // kTPCrefit + ((track.itsClusterMap() & (uint8_t(1) << 0))) // SPD first + ) { trackSel(1); fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); } else From cc915d7358fe166fd590ed548f587c4c7f23f0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Wed, 23 Sep 2020 17:46:35 +0200 Subject: [PATCH 0724/1751] Add mc validation task (#4419) - Using central isphysicalprimary --- Analysis/Tasks/PWGLF/CMakeLists.txt | 5 + Analysis/Tasks/PWGLF/mcspectraefficiency.cxx | 157 +++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 Analysis/Tasks/PWGLF/mcspectraefficiency.cxx diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt index 58e47f6d30780..3eb3ece255b9a 100644 --- a/Analysis/Tasks/PWGLF/CMakeLists.txt +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -8,6 +8,11 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +o2_add_dpl_workflow(mc-spectra-efficiency + SOURCES mcspectraefficiency.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(spectra-tof SOURCES spectraTOF.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel diff --git a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx new file mode 100644 index 0000000000000..ab613d09bf884 --- /dev/null +++ b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx @@ -0,0 +1,157 @@ +// 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 includes +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Analysis/MC.h" +#include "Framework/ASoAHelpers.h" +#include "Analysis/TrackSelectionTables.h" + +// ROOT includes +#include <TH1F.h> +#include "TPDGCode.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace MC; + +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"add-vertex", VariantType::Int, 1, {"Vertex plots"}}, + {"add-gen", VariantType::Int, 1, {"Generated plots"}}, + {"add-reco", VariantType::Int, 1, {"Reconstructed plots"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +#define PDGBINNING 100, 0, 100 + +// Simple access to collision +struct VertexTask { + OutputObj<TH1F> vertex{TH1F("vertex", "vertex", 100, -10, 10)}; + + void process(aod::McCollision const& mcCollision) + { + LOGF(info, "MC. vtx-z = %f", mcCollision.posZ()); + vertex->Fill(mcCollision.posZ()); + } +}; + +// Grouping between MC particles and collisions +struct GeneratedTask { + OutputObj<TH2F> phiH{TH2F("phi", "phi;#phi;PDG code", 100, 0., 2. * M_PI, PDGBINNING)}; + OutputObj<TH2F> etaH{TH2F("eta", "eta;#eta;PDG code", 102, -2.01, 2.01, PDGBINNING)}; + OutputObj<TH2F> ptH{TH2F("pt", "pt;#it{p}_{T} (GeV/#it{c});PDG code", 500, 0, 20, PDGBINNING)}; + OutputObj<TH2F> pH{TH2F("p", "p;#it{p} (GeV/#it{c});PDG code", 500, 0, 20, PDGBINNING)}; + OutputObj<TH1F> pdgH{TH1F("pdg", "pdg;PDG code", PDGBINNING)}; + + int events = 0; + int particles = 0; + int primaryparticles = 0; + + void process(aod::McCollision const& mcCollision, aod::McParticles& mcParticles) + { + LOGF(info, "MC. vtx-z = %f", mcCollision.posZ()); + for (auto& mcParticle : mcParticles) { + if (abs(mcParticle.eta()) > 0.8) + continue; + if (isPhysicalPrimary(mcParticles, mcParticle)) { + const auto pdg = Form("%i", mcParticle.pdgCode()); + pdgH->Fill(pdg, 1); + const float pdgbin = pdgH->GetXaxis()->GetBinCenter(pdgH->GetXaxis()->FindBin(pdg)); + phiH->Fill(mcParticle.phi(), pdgbin); + etaH->Fill(mcParticle.eta(), pdgbin); + pH->Fill(sqrt(mcParticle.px() * mcParticle.px() + mcParticle.py() * mcParticle.py() + mcParticle.pz() * mcParticle.pz()), pdgbin); + ptH->Fill(mcParticle.pt(), pdgbin); + primaryparticles++; + } + particles++; + } + LOGF(info, "Events %i", events++ + 1); + LOGF(info, "Particles %i", particles); + LOGF(info, "Primaries %i", primaryparticles); + } +}; + +// Access from tracks to MC particle +struct ReconstructedTask { + OutputObj<TH2F> phiH{TH2F("phi", "phi;#phi;PDG code", 100, 0., 2. * M_PI, PDGBINNING)}; + OutputObj<TH2F> etaH{TH2F("eta", "eta;#eta;PDG code", 102, -2.01, 2.01, PDGBINNING)}; + OutputObj<TH2F> ptH{TH2F("pt", "pt;#it{p}_{T} (GeV/#it{c})", 500, 0, 20, PDGBINNING)}; + OutputObj<TH2F> pH{TH2F("p", "p;#it{p} (GeV/#it{c})", 500, 0, 20, PDGBINNING)}; + OutputObj<TH2F> dcaxyH{TH2F("dcaxy", "dcaxy;DCA_{xy} (cm)", 500, -10, 10, PDGBINNING)}; + OutputObj<TH2F> dcazH{TH2F("dcaz", "dcaz;DCA_{z} (cm)", 500, -10, 10, PDGBINNING)}; + OutputObj<TH1F> pdgH{TH1F("pdg", "pdg;PDG code", PDGBINNING)}; + OutputObj<TH2F> dcaxysecH{TH2F("dcaxysec", "dcaxysec;DCA_{xy} (cm)", 500, -10, 10, PDGBINNING)}; + OutputObj<TH2F> dcazsecH{TH2F("dcazsec", "dcazsec;DCA_{z} (cm)", 500, -10, 10, PDGBINNING)}; + OutputObj<TH1F> pdgsecH{TH1F("pdgsec", "pdgsec;PDG code", PDGBINNING)}; + + OutputObj<TH2F> phiDiff{TH2F("phiDiff", ";phi_{MC} - phi_{Rec}", 100, -M_PI, M_PI, PDGBINNING)}; + OutputObj<TH2F> etaDiff{TH2F("etaDiff", ";eta_{MC} - eta_{Rec}", 100, -2, 2, PDGBINNING)}; + OutputObj<TH2F> ptDiff{TH2F("ptDiff", "ptDiff;#it{p}_{T}_{MC} #it{p}_{T}_{Rec} (GeV/#it{c})", 500, -2, 2, PDGBINNING)}; + OutputObj<TH2F> pDiff{TH2F("pDiff", "pDiff;#it{p}_{MC} #it{p}_{Rec} (GeV/#it{c})", 500, -2, 2, PDGBINNING)}; + + Filter trackAcceptance = (nabs(aod::track::eta) < (float)(0.8f)); + Filter trackCuts = ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + + void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const& collision, + soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::McTrackLabels, aod::TrackSelection>> const& tracks, + aod::McParticles& mcParticles, aod::McCollisions const& mcCollisions) + { + LOGF(info, "vtx-z (data) = %f | vtx-z (MC) = %f", collision.posZ(), collision.label().posZ()); + for (auto& track : tracks) { + const auto pdg = Form("%i", track.label().pdgCode()); + if (!isPhysicalPrimary(mcParticles, track.label())) { + pdgsecH->Fill(pdg, 1); + const float pdgbinsec = pdgH->GetXaxis()->GetBinCenter(pdgsecH->GetXaxis()->FindBin(pdg)); + dcaxysecH->Fill(track.dcaXY(), pdgbinsec); + dcazsecH->Fill(track.dcaZ(), pdgbinsec); + continue; + } + pdgH->Fill(pdg, 1); // Filling the first bin and check its bin + const float pdgbin = pdgH->GetXaxis()->GetBinCenter(pdgH->GetXaxis()->FindBin(pdg)); + phiH->Fill(track.phi(), pdgbin); + etaH->Fill(track.eta(), pdgbin); + pH->Fill(track.p(), pdgbin); + ptH->Fill(track.pt(), pdgbin); + dcaxyH->Fill(track.dcaXY(), pdgbin); + dcazH->Fill(track.dcaZ(), pdgbin); + + etaDiff->Fill(track.label().eta() - track.eta(), pdgbin); + auto delta = track.label().phi() - track.phi(); + if (delta > M_PI) + delta -= 2 * M_PI; + if (delta < -M_PI) + delta += 2 * M_PI; + phiDiff->Fill(delta, pdgbin); + pDiff->Fill(sqrt(track.label().px() * track.label().px() + track.label().py() * track.label().py() + track.label().pz() * track.label().pz()) - track.p(), pdgbin); + ptDiff->Fill(track.label().pt() - track.pt(), pdgbin); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + const bool vertex = cfgc.options().get<int>("add-vertex"); + const bool gen = cfgc.options().get<int>("add-gen"); + const bool reco = cfgc.options().get<int>("add-reco"); + WorkflowSpec workflow{}; + if (vertex) + workflow.push_back(adaptAnalysisTask<VertexTask>("vertex-histogram")); + if (gen) + workflow.push_back(adaptAnalysisTask<GeneratedTask>("generator-histogram")); + if (reco) + workflow.push_back(adaptAnalysisTask<ReconstructedTask>("reconstructed-histogram")); + return workflow; +} From 734ae2f2bdb43feddbe3d3a1a96841344d5656b2 Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Wed, 23 Sep 2020 18:54:02 +0200 Subject: [PATCH 0725/1751] added task for analysis challege: used for TPC trk efficiency of primary el,pi,ka,p and DCAxy distributions of primaries, secondaries --- Analysis/Tasks/CMakeLists.txt | 7 + Analysis/Tasks/trackchecks.cxx | 225 +++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 Analysis/Tasks/trackchecks.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 1b8ac438c0eac..d796e1445ebeb 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -14,6 +14,7 @@ add_subdirectory(PWGHF) add_subdirectory(PWGLF) add_subdirectory(PWGUD) + o2_add_dpl_workflow(trackselection SOURCES trackselection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore @@ -96,3 +97,9 @@ o2_add_dpl_workflow(run3-matcher SOURCES run3Matcher.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) + + +o2_add_dpl_workflow(track-checks + SOURCES trackchecks.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx new file mode 100644 index 0000000000000..c5b18f86340ad --- /dev/null +++ b/Analysis/Tasks/trackchecks.cxx @@ -0,0 +1,225 @@ +// 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 "Analysis/EventSelection.h" +#include "Analysis/MC.h" +#include "Analysis/HistHelpers.h" + +#include <cmath> +#include <array> +#include <utility> + +#include <TH1.h> +#include <TH2.h> +#include <TF1.h> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::experimental::histhelpers; +using namespace std; + +#define NPTBINS 53 +#define NPARTICLES 5 +const double pt_bins[NPTBINS + 1] = {0.0, 0.05, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, + 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, + 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 10.0, 20.0}; +const double mass[NPARTICLES] = {0.000510999, 0.139570, 0.493677, 0.938272, 1.87561}; +enum PType { kEl, + kPi, + kKa, + kPr, + kDe }; + +#define TRACKSELECTION \ + UChar_t clustermap = track.itsClusterMap(); \ + bool issel = (abs(track.eta()) < 0.8) && (track.tpcNClsFindable() > 70) && (track.tpcChi2NCl() < 4.) && (track.tpcCrossedRowsOverFindableCls() > 0.8) && (track.flags() & 0x4) && (track.itsChi2NCl() < 36) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); \ + issel = issel && (track.flags() & (uint64_t(1) << 2)); /*ITS refit*/ \ + issel = issel && (track.flags() & (uint64_t(1) << 6)); /*TPC refit*/ \ + if (!issel) \ + continue; + +struct TrackCheckTask1 { + + Configurable<bool> isMC{"isMC", false, "option to flag mc"}; + OutputObj<TH1F> hTrkPrimReco{TH1F("hTrkPrimReco", "Reco Prim tracks (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + OutputObj<TH1F> hTrkPrimAftEvSel{TH1F("hTrkPrimAftEvSel", "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + OutputObj<HistArray> hTrkPrimReco_truepid{HistArray("hTrkPrimReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<HistArray> hTrkPrimAftEvSel_truepid{HistArray("hTrkPrimAftEvSel_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<HistArray> hDCAxyReco_truepid{HistArray("hDCAxyReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<HistArray> hDCAxyPrim_truepid{HistArray("hDCAxyPrim_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<HistArray> hDCAxySeco_truepid{HistArray("hDCAxySeco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + TF1* fCutDCAxy; + + void init(InitContext&) + { + hTrkPrimReco_truepid->Add(0, TH1F("hTrkPrimReco_truepid_el", "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add(1, TH1F("hTrkPrimReco_truepid_pi", "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add(2, TH1F("hTrkPrimReco_truepid_ka", "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add(3, TH1F("hTrkPrimReco_truepid_pr", "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add(4, TH1F("hTrkPrimReco_truepid_de", "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + + hTrkPrimAftEvSel_truepid->Add(0, TH1F("hTrkPrimAftEvSel_truepid_el", "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add(1, TH1F("hTrkPrimAftEvSel_truepid_pi", "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add(2, TH1F("hTrkPrimAftEvSel_truepid_ka", "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add(3, TH1F("hTrkPrimAftEvSel_truepid_pr", "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add(4, TH1F("hTrkPrimAftEvSel_truepid_de", "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + + hDCAxyReco_truepid->Add(0, TH2F("hDCAxyReco_truepid_el", "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add(1, TH2F("hDCAxyReco_truepid_pi", "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add(2, TH2F("hDCAxyReco_truepid_ka", "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add(3, TH2F("hDCAxyReco_truepid_pr", "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add(4, TH2F("hDCAxyReco_truepid_de", "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + hDCAxyPrim_truepid->Add(0, TH2F("hDCAxyPrim_truepid_el", "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add(1, TH2F("hDCAxyPrim_truepid_pi", "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add(2, TH2F("hDCAxyPrim_truepid_ka", "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add(3, TH2F("hDCAxyPrim_truepid_pr", "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add(4, TH2F("hDCAxyPrim_truepid_de", "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + hDCAxySeco_truepid->Add(0, TH2F("hDCAxySeco_truepid_el", "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add(1, TH2F("hDCAxySeco_truepid_pi", "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add(2, TH2F("hDCAxySeco_truepid_ka", "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add(3, TH2F("hDCAxySeco_truepid_pr", "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add(4, TH2F("hDCAxySeco_truepid_de", "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + fCutDCAxy = new TF1("fMaxDCAxy", "[0]+[1]/(x^[2])", 0, 1e10); //from TPC analysis task (Run2) + fCutDCAxy->SetParameter(0, 0.0105); + fCutDCAxy->SetParameter(1, 0.0350); + fCutDCAxy->SetParameter(2, 1.1); + } //init + + void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) + { + + if (isMC) { + LOGF(info, "isMC=%d - Running on MC", isMC.value); + } else { + LOGF(info, "isMC=%d - Running on DATA", isMC.value); + } + + //event selection + if (!isMC && !col.alias()[kINT7]) // trigger (should be skipped in MC) + return; + if (!col.sel7()) //additional cuts + return; + if (abs(col.posZ()) > 10.) // |v_z|<10cm + return; + + //Loop on tracks + for (auto& track : tracks) { + double y = -999.; + int pdgcode = -999; + int ptype = -999; + bool isPrimary = false; + + if (isMC) { //determine particle species base on MC truth and if it is primary or not + pdgcode = track.label().pdgCode(); + if (pdgcode == 11) + ptype = kEl; + else if (pdgcode == 211) + ptype = kPi; + else if (pdgcode == 321) + ptype = kKa; + else if (pdgcode == 2212) + ptype = kPr; + else if (pdgcode == 1000010020) + ptype = kDe; + + if (MC::isPhysicalPrimary(mcParticles, track.label())) { //is primary? + isPrimary = true; + } + } + + if (isMC) { + //calculate rapidity + y = eta2y(track.pt(), mass[ptype], track.eta()); + + if (isPrimary && abs(y) < 0.5) { + //histograms with generated distribution (after event selection) + hTrkPrimAftEvSel_truepid->Fill(ptype, track.pt()); + hTrkPrimAftEvSel->Fill(track.pt()); //charged particles + } + } + + //track selection - DCAxy and DCAz cut done later - other cuts?? + TRACKSELECTION; + + //DCAxy distributions for reco, primary, secondaries (= not primary) + //calculate dcaxy and dcaz + std::pair<float, float> dcas = getdcaxyz(track, col); + if (isMC) { + if (abs(y) < 0.5) { + hDCAxyReco_truepid->Fill(ptype, track.pt(), dcas.first); + if (isPrimary) + hDCAxyPrim_truepid->Fill(ptype, track.pt(), dcas.first); + else + hDCAxySeco_truepid->Fill(ptype, track.pt(), dcas.first); + } + } + + //Additional CUTS + //apply cut on DCAz + if (abs(dcas.second) > 2.0) + continue; + //apply pt-dependent cut on dcaxy + if (abs(dcas.first) > fCutDCAxy->Eval(track.pt())) + continue; + + //fill reco histos + if (isMC) { + if (isPrimary && abs(y) < 0.5) { + hTrkPrimReco_truepid->Fill(ptype, track.pt()); + hTrkPrimReco->Fill(track.pt()); //charged particles + } + } + } // end loop on tracks + } + + //convert eta to y + double eta2y(double pt, double m, double eta) const + { + // convert eta to y + double mt = sqrt(m * m + pt * pt); + return asinh(pt / mt * sinh(eta)); + } + + //calculated DCAxy and DCAz + template <typename T, typename C> + std::pair<float, float> getdcaxyz(T& track, C const& collision) + { + float sinAlpha = 0.f; + float cosAlpha = 0.f; + float globalX = 0.f; + float globalY = 0.f; + float dcaXY = 0.f; + float dcaZ = 0.f; + + sinAlpha = sin(track.alpha()); + cosAlpha = cos(track.alpha()); + globalX = track.x() * cosAlpha - track.y() * sinAlpha; + globalY = track.x() * sinAlpha + track.y() * cosAlpha; + + dcaXY = track.charge() * sqrt(pow((globalX - collision.posX()), 2) + + pow((globalY - collision.posY()), 2)); + dcaZ = track.charge() * sqrt(pow(track.z() - collision.posZ(), 2)); + + return std::make_pair(dcaXY, dcaZ); + } + +}; // struct TrackCheckTask1 + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<TrackCheckTask1>("track-histos")}; +} From 3660f01774e3ab31f38a3f40160cdf6c83a9c3b7 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 23 Sep 2020 11:28:20 +0200 Subject: [PATCH 0726/1751] Memory improvements in TPC digitizer workflow * create digit accumulator as DPL owned resource, avoiding one data copy * in the ROOT writer callback: free memory taken by branches early by calling DropBaskets("all") For a 100PbPb digitization (8 lanes) I see memory spikes going from ~21GB to ~16GB (with --disable-mc). --- .../src/TPCDigitRootWriterSpec.cxx | 4 ++++ .../src/TPCDigitizerSpec.cxx | 24 +++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx index 88ce2d479ebc1..c3f1ee00b2258 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx @@ -172,6 +172,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur branch.SetAddress(&ptr); branch.Fill(); branch.ResetAddress(); + branch.DropBaskets("all"); } else { // triggered mode (>1 entries will be written) std::vector<o2::tpc::Digit> digGroup; // group of digits related to single trigger auto ptr = &digGroup; @@ -184,6 +185,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur branch.Fill(); } branch.ResetAddress(); + branch.DropBaskets("all"); } } } @@ -215,6 +217,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur branch.SetAddress(&ptr); branch.Fill(); branch.ResetAddress(); + branch.DropBaskets("all"); } else { o2::dataformats::MCTruthContainer<o2::MCCompLabel> lblGroup; // labels for group of digits related to single trigger auto ptr = &lblGroup; @@ -228,6 +231,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur branch.Fill(); } branch.ResetAddress(); + branch.DropBaskets("all"); } } } diff --git a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx index 9c7a63a01af53..701fc6c83fa3c 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx @@ -199,14 +199,12 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer uint64_t activeSectors = 0; activeSectors = sectorHeader->activeSectors; - // lambda that snapshots digits to be sent out; prepares and attaches header with sector information - auto snapshotDigits = [this, sector, &pc, activeSectors, &dh](std::vector<o2::tpc::Digit> const& digits) { + // lambda that creates a DPL owned buffer to accumulate the digits (in shared memory) + auto makeDigitBuffer = [this, sector, &pc, activeSectors, &dh]() { o2::tpc::TPCSectorHeader header{sector}; header.activeSectors = activeSectors; - // note that snapshoting only works with non-const references (to be fixed?) - pc.outputs().snapshot(Output{"TPC", "DIGITS", static_cast<SubSpecificationType>(dh->subSpecification), Lifetime::Timeframe, - header}, - const_cast<std::vector<o2::tpc::Digit>&>(digits)); + return &pc.outputs().make<std::vector<o2::tpc::Digit>>(Output{"TPC", "DIGITS", static_cast<SubSpecificationType>(dh->subSpecification), Lifetime::Timeframe, + header}); }; // lambda that snapshots the common mode vector to be sent out; prepares and attaches header with sector information auto snapshotCommonMode = [this, sector, &pc, activeSectors, &dh](std::vector<o2::tpc::CommonMode> const& commonMode) { @@ -237,7 +235,7 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer const_cast<std::vector<DigiGroupRef>&>(events)); }; - std::vector<o2::tpc::Digit> digitsAccum; // accumulator for digits + auto digitsAccum = makeDigitBuffer(); // accumulator for digits o2::dataformats::MCTruthContainer<o2::MCCompLabel> labelAccum; // timeframe accumulator for labels std::vector<CommonMode> commonModeAccum; std::vector<DigiGroupRef> eventAccum; @@ -260,14 +258,14 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer auto& eventParts = context->getEventParts(); - auto flushDigitsAndLabels = [this, &digitsAccum, &labelAccum, &commonModeAccum](bool finalFlush = false) { + auto flushDigitsAndLabels = [this, digitsAccum, &labelAccum, &commonModeAccum](bool finalFlush = false) { // flush previous buffer mDigits.clear(); mLabels.clear(); mCommonMode.clear(); mDigitizer.flush(mDigits, mLabels, mCommonMode, finalFlush); LOG(INFO) << "TPC: Flushed " << mDigits.size() << " digits, " << mLabels.getNElements() << " labels and " << mCommonMode.size() << " common mode entries"; - std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(digitsAccum)); + std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(*digitsAccum)); if (mWithMCTruth) { labelAccum.mergeAtBack(mLabels); } @@ -289,7 +287,7 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer if (!isContinuous) { mDigitizer.setStartTime(sampaProcessing.getTimeBinFromTime(eventTime)); } - int startSize = digitsAccum.size(); + int startSize = digitsAccum->size(); // for each collision, loop over the constituents event and source IDs // (background signal merging is basically taking place here) @@ -310,7 +308,7 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer flushDigitsAndLabels(); if (!isContinuous) { - eventAccum.emplace_back(startSize, digitsAccum.size() - startSize); + eventAccum.emplace_back(startSize, digitsAccum->size() - startSize); } } } @@ -319,12 +317,12 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer if (isContinuous) { LOG(INFO) << "TPC: Final flush"; flushDigitsAndLabels(true); - eventAccum.emplace_back(0, digitsAccum.size()); // all digits are grouped to 1 super-event pseudo-triggered mode + eventAccum.emplace_back(0, digitsAccum->size()); // all digits are grouped to 1 super-event pseudo-triggered mode } // send out to next stage snapshotEvents(eventAccum); - snapshotDigits(digitsAccum); + // snapshotDigits(digitsAccum); --> done automatically snapshotCommonMode(commonModeAccum); snapshotLabels(labelAccum); From 5604c11e1b73d3264ccdb94b96a9833ad51d6b07 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Mon, 21 Sep 2020 16:17:15 +0300 Subject: [PATCH 0727/1751] Fix namespace naming --- .../include/Analysis/ReducedInfoTables.h | 14 ++++---- Analysis/DataModel/include/PID/PIDResponse.h | 18 +++++----- .../Base/GPUReconstructionKernels.h | 2 +- .../GPUTPCCompressionKernels.cxx | 10 +++--- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 +-- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMMerger.h | 10 +++--- GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h | 2 +- GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h | 4 +-- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 4 +-- GPU/GPUTracking/Merger/GPUTPCGMPropagator.h | 6 ++-- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 6 ++-- .../Standalone/display/GPUDisplay.cxx | 8 ++--- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 34 +++++++++---------- GPU/GPUTracking/Standalone/standalone.cxx | 2 +- GPU/GPUTracking/TPCClusterFinder/CfConsts.h | 4 +-- GPU/GPUTracking/TPCClusterFinder/CfUtils.h | 4 +-- .../TPCClusterFinder/GPUTPCCFClusterizer.cxx | 10 +++--- .../GPUTPCCFDeconvolution.cxx | 4 +-- .../GPUTPCCFNoiseSuppression.cxx | 16 ++++----- .../TPCClusterFinder/GPUTPCCFPeakFinder.cxx | 2 +- 23 files changed, 85 insertions(+), 85 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 88bf692dd77f8..5f8935372bcca 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -96,13 +96,13 @@ DECLARE_SOA_TABLE(ReducedTracksBarrelCov, "AOD", "RTBARRELCOV", // barrel PID information DECLARE_SOA_TABLE(ReducedTracksBarrelPID, "AOD", "RTBARRELPID", track::TPCSignal, - pidTPC::TPCNSigmaEl, pidTPC::TPCNSigmaMu, - pidTPC::TPCNSigmaPi, pidTPC::TPCNSigmaKa, pidTPC::TPCNSigmaPr, - pidTPC::TPCNSigmaDe, pidTPC::TPCNSigmaTr, pidTPC::TPCNSigmaHe, pidTPC::TPCNSigmaAl, - track::TOFSignal, pidTOFbeta::Beta, - pidTOF::TOFNSigmaEl, pidTOF::TOFNSigmaMu, - pidTOF::TOFNSigmaPi, pidTOF::TOFNSigmaKa, pidTOF::TOFNSigmaPr, - pidTOF::TOFNSigmaDe, pidTOF::TOFNSigmaTr, pidTOF::TOFNSigmaHe, pidTOF::TOFNSigmaAl, + pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, + pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtpc::TPCNSigmaDe, pidtpc::TPCNSigmaTr, pidtpc::TPCNSigmaHe, pidtpc::TPCNSigmaAl, + track::TOFSignal, pidtofbeta::Beta, + pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, + pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, + pidtof::TOFNSigmaDe, pidtof::TOFNSigmaTr, pidtof::TOFNSigmaHe, pidtof::TOFNSigmaAl, track::TRDSignal); // muon quantities diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/PID/PIDResponse.h index 96f8dd79821e8..bf9862c30091d 100644 --- a/Analysis/DataModel/include/PID/PIDResponse.h +++ b/Analysis/DataModel/include/PID/PIDResponse.h @@ -30,7 +30,7 @@ namespace o2::aod { -namespace pidTOFbeta +namespace pidtofbeta { DECLARE_SOA_COLUMN(Beta, beta, float); DECLARE_SOA_COLUMN(BetaError, betaerror, float); @@ -40,9 +40,9 @@ DECLARE_SOA_COLUMN(ExpBetaElError, expbetaelerror, float); // DECLARE_SOA_COLUMN(SeparationBetaEl, separationbetael, float); DECLARE_SOA_DYNAMIC_COLUMN(DiffBetaEl, diffbetael, [](float beta, float expbetael) -> float { return beta - expbetael; }); -} // namespace pidTOFbeta +} // namespace pidtofbeta -namespace pidTOF +namespace pidtof { // Expected times DECLARE_SOA_COLUMN(TOFExpSignalEl, tofExpSignalEl, float); @@ -74,21 +74,21 @@ DECLARE_SOA_COLUMN(TOFNSigmaDe, tofNSigmaDe, float); DECLARE_SOA_COLUMN(TOFNSigmaTr, tofNSigmaTr, float); DECLARE_SOA_COLUMN(TOFNSigmaHe, tofNSigmaHe, float); DECLARE_SOA_COLUMN(TOFNSigmaAl, tofNSigmaAl, float); -} // namespace pidTOF +} // namespace pidtof -using namespace pidTOFbeta; +using namespace pidtofbeta; DECLARE_SOA_TABLE(pidRespTOFbeta, "AOD", "pidRespTOFbeta", Beta, BetaError, ExpBetaEl, ExpBetaElError, SeparationBetaEl, DiffBetaEl<Beta, ExpBetaEl>); -using namespace pidTOF; +using namespace pidtof; DECLARE_SOA_TABLE(pidRespTOF, "AOD", "pidRespTOF", TOFExpSignalEl, TOFExpSignalMu, TOFExpSignalPi, TOFExpSignalKa, TOFExpSignalPr, TOFExpSignalDe, TOFExpSignalTr, TOFExpSignalHe, TOFExpSignalAl, TOFExpSigmaEl, TOFExpSigmaMu, TOFExpSigmaPi, TOFExpSigmaKa, TOFExpSigmaPr, TOFExpSigmaDe, TOFExpSigmaTr, TOFExpSigmaHe, TOFExpSigmaAl, TOFNSigmaEl, TOFNSigmaMu, TOFNSigmaPi, TOFNSigmaKa, TOFNSigmaPr, TOFNSigmaDe, TOFNSigmaTr, TOFNSigmaHe, TOFNSigmaAl); -namespace pidTPC +namespace pidtpc { // Expected signals DECLARE_SOA_COLUMN(TPCExpSignalEl, tpcExpSignalEl, float); @@ -120,9 +120,9 @@ DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNSigmaDe, float); DECLARE_SOA_COLUMN(TPCNSigmaTr, tpcNSigmaTr, float); DECLARE_SOA_COLUMN(TPCNSigmaHe, tpcNSigmaHe, float); DECLARE_SOA_COLUMN(TPCNSigmaAl, tpcNSigmaAl, float); -} // namespace pidTPC +} // namespace pidtpc -using namespace pidTPC; +using namespace pidtpc; DECLARE_SOA_TABLE(pidRespTPC, "AOD", "pidRespTPC", TPCExpSignalEl, TPCExpSignalMu, TPCExpSignalPi, TPCExpSignalKa, TPCExpSignalPr, TPCExpSignalDe, TPCExpSignalTr, TPCExpSignalHe, TPCExpSignalAl, TPCExpSigmaEl, TPCExpSigmaMu, TPCExpSigmaPi, TPCExpSigmaKa, TPCExpSigmaPr, TPCExpSigmaDe, TPCExpSigmaTr, TPCExpSigmaHe, TPCExpSigmaAl, diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index ad8c00cb68c9e..aa3e11400159b 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -44,7 +44,7 @@ GPUCA_KRNL_LB((GPUTPCGMMergerMergeSlicesPrepare ), (simple), (, int GPUCA_KRNL_LB((GPUTPCGMMergerMergeBorders, step0 ), (simple), (, int iSlice, char withinSlice, char mergeMode), (, iSlice, withinSlice, mergeMode)) GPUCA_KRNL(( GPUTPCGMMergerMergeBorders, step1 ), (simple), (, int iSlice, char withinSlice, char mergeMode), (, iSlice, withinSlice, mergeMode)) GPUCA_KRNL_LB((GPUTPCGMMergerMergeBorders, step2 ), (simple), (, int iSlice, char withinSlice, char mergeMode), (, iSlice, withinSlice, mergeMode)) -GPUCA_KRNL(( GPUTPCGMMergerMergeBorders, variant ), (simple), (, GPUPtr1(GPUTPCGMMergerTypes::GPUTPCGMBorderRange*, range), int N, int cmpMax), (, GPUPtr2(GPUTPCGMMergerTypes::GPUTPCGMBorderRange*, range), N, cmpMax)) +GPUCA_KRNL(( GPUTPCGMMergerMergeBorders, variant ), (simple), (, GPUPtr1(gputpcgmmergertypes::GPUTPCGMBorderRange*, range), int N, int cmpMax), (, GPUPtr2(gputpcgmmergertypes::GPUTPCGMBorderRange*, range), N, cmpMax)) GPUCA_KRNL_LB((GPUTPCGMMergerMergeCE ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCGMMergerLinkGlobalTracks ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCGMMergerCollect ), (simple), (), ()) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index f183f8957872e..36696abf96714 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -53,10 +53,10 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at int hitId = hit.num; int attach = merger.ClusterAttachment()[hitId]; - if ((attach & GPUTPCGMMergerTypes::attachTrackMask) != i) { + if ((attach & gputpcgmmergertypes::attachTrackMask) != i) { continue; // Main attachment to different track } - bool rejectCluster = processors.param.rec.tpcRejectionMode && (rejectTrk || ((attach & GPUTPCGMMergerTypes::attachGoodLeg) == 0) || (attach & GPUTPCGMMergerTypes::attachHighIncl)); + bool rejectCluster = processors.param.rec.tpcRejectionMode && (rejectTrk || ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) || (attach & gputpcgmmergertypes::attachHighIncl)); if (rejectCluster) { compressor.mClusterStatus[hitId] = 1; // Cluster rejected, do not store continue; @@ -214,13 +214,13 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un break; } } else if (processors.param.rec.tpcRejectionMode >= GPUSettings::RejectionStrategyA) { - if ((attach & GPUTPCGMMergerTypes::attachGoodLeg) == 0) { + if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { break; } - if (attach & GPUTPCGMMergerTypes::attachHighIncl) { + if (attach & gputpcgmmergertypes::attachHighIncl) { break; } - int id = attach & GPUTPCGMMergerTypes::attachTrackMask; + int id = attach & gputpcgmmergertypes::attachTrackMask; if (CAMath::Abs(merger.OutputTracks()[id].GetParam().GetQPt()) > processors.param.rec.tpcRejectQPt) { break; } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 89643bf0044a5..04d58685999c6 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1817,8 +1817,8 @@ void GPUChainTracking::RunTPCTrackingMerger_MergeBorderTracks(char withinSlice, GPUTPCGMBorderTrack *b1, *b2; int jSlice; Merger.MergeBorderTracksSetup(n1, n2, b1, b2, jSlice, i, withinSlice, mergeMode); - GPUTPCGMMergerTypes::GPUTPCGMBorderRange* range1 = MergerShadow.BorderRange(i); - GPUTPCGMMergerTypes::GPUTPCGMBorderRange* range2 = MergerShadow.BorderRange(jSlice) + *processors()->tpcTrackers[jSlice].NTracks(); + gputpcgmmergertypes::GPUTPCGMBorderRange* range1 = MergerShadow.BorderRange(i); + gputpcgmmergertypes::GPUTPCGMBorderRange* range2 = MergerShadow.BorderRange(jSlice) + *processors()->tpcTrackers[jSlice].NTracks(); runKernel<GPUTPCGMMergerMergeBorders, 3>({1, -WarpSize(), stream, deviceType}, krnlRunRangeNone, krnlEventNone, range1, n1, 0); runKernel<GPUTPCGMMergerMergeBorders, 3>({1, -WarpSize(), stream, deviceType}, krnlRunRangeNone, krnlEventNone, range2, n2, 1); deviceEvent** e = nullptr; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 69817111e7309..6bbe9ffc40a48 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -47,7 +47,7 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; -using namespace GPUTPCGMMergerTypes; +using namespace gputpcgmmergertypes; static constexpr int kMaxParts = 400; static constexpr int kMaxClusters = GPUCA_MERGER_MAX_TRACK_CLUSTERS; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h index 7015ddf5e2b44..77bc80545f480 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h @@ -114,7 +114,7 @@ class GPUTPCGMMerger : public GPUProcessor GPUhdi() memory* Memory() const { return mMemory; } GPUhdi() GPUAtomic(unsigned int) * TmpCounter() { return mMemory->tmpCounter; } GPUhdi() uint4* TmpMem() { return mTmpMem; } - GPUhdi() GPUTPCGMMergerTypes::GPUTPCGMBorderRange* BorderRange(int i) { return mBorderRange[i]; } + GPUhdi() gputpcgmmergertypes::GPUTPCGMBorderRange* BorderRange(int i) { return mBorderRange[i]; } GPUd() unsigned short MemoryResMemory() { return mMemoryResMemory; } GPUd() unsigned short MemoryResOutput() const { return mMemoryResOutput; } @@ -135,7 +135,7 @@ class GPUTPCGMMerger : public GPUProcessor GPUd() void MergeBorderTracks(int nBlocks, int nThreads, int iBlock, int iThread, int iSlice, char withinSlice, char mergeMode); GPUd() void MergeBorderTracksSetup(int& n1, int& n2, GPUTPCGMBorderTrack*& b1, GPUTPCGMBorderTrack*& b2, int& jSlice, int iSlice, char withinSlice, char mergeMode); template <int I> - GPUd() void MergeBorderTracks(int nBlocks, int nThreads, int iBlock, int iThread, GPUTPCGMMergerTypes::GPUTPCGMBorderRange* range, int N, int cmpMax); + GPUd() void MergeBorderTracks(int nBlocks, int nThreads, int iBlock, int iThread, gputpcgmmergertypes::GPUTPCGMBorderRange* range, int N, int cmpMax); GPUd() void SortTracks(int nBlocks, int nThreads, int iBlock, int iThread); GPUd() void SortTracksQPt(int nBlocks, int nThreads, int iBlock, int iThread); GPUd() void SortTracksPrepare(int nBlocks, int nThreads, int iBlock, int iThread); @@ -151,7 +151,7 @@ class GPUTPCGMMerger : public GPUProcessor GPUd() void ResolveFindConnectedComponentsHookNeighbors(int nBlocks, int nThreads, int iBlock, int iThread); GPUd() void ResolveFindConnectedComponentsHookLinks(int nBlocks, int nThreads, int iBlock, int iThread); GPUd() void ResolveFindConnectedComponentsMultiJump(int nBlocks, int nThreads, int iBlock, int iThread); - GPUd() void ResolveMergeSlices(GPUTPCGMMergerTypes::GPUResolveSharedMemory& smem, int nBlocks, int nThreads, int iBlock, int iThread, char useOrigTrackParam, char mergeAll); + GPUd() void ResolveMergeSlices(gputpcgmmergertypes::GPUResolveSharedMemory& smem, int nBlocks, int nThreads, int iBlock, int iThread, char useOrigTrackParam, char mergeAll); #ifndef GPUCA_GPUCODE void DumpSliceTracks(std::ostream& out); @@ -221,8 +221,8 @@ class GPUTPCGMMerger : public GPUProcessor uint4* mTmpMem; GPUTPCGMBorderTrack* mBorderMemory; // memory for border tracks GPUTPCGMBorderTrack* mBorder[2 * NSLICES]; - GPUTPCGMMergerTypes::GPUTPCGMBorderRange* mBorderRangeMemory; // memory for border tracks - GPUTPCGMMergerTypes::GPUTPCGMBorderRange* mBorderRange[NSLICES]; // memory for border tracks + gputpcgmmergertypes::GPUTPCGMBorderRange* mBorderRangeMemory; // memory for border tracks + gputpcgmmergertypes::GPUTPCGMBorderRange* mBorderRange[NSLICES]; // memory for border tracks memory* mMemory; unsigned int* mRetryRefitIds; GPUTPCGMLoopData* mLoopData; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx index 21d79de6cc2a7..d9c9e0c5cec23 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx @@ -33,7 +33,7 @@ #include "GPUReconstruction.h" using namespace GPUCA_NAMESPACE::gpu; -using namespace GPUTPCGMMergerTypes; +using namespace gputpcgmmergertypes; static std::vector<int> trackOrder, trackOrderReverse; static int getTrackOrderReverse(int i) { return i == -1 ? -1 : trackOrderReverse[i]; } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx index 70a3f0f8a4a12..b268e15e1ca35 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx @@ -120,7 +120,7 @@ GPUdii() void GPUTPCGMMergerMergeBorders::Thread(int nBlocks, int nThreads, int } template GPUd() void GPUTPCGMMergerMergeBorders::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, int iSlice, char withinSlice, char mergeMode); template GPUd() void GPUTPCGMMergerMergeBorders::Thread<2>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, int iSlice, char withinSlice, char mergeMode); -template GPUd() void GPUTPCGMMergerMergeBorders::Thread<3>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, GPUTPCGMMergerTypes::GPUTPCGMBorderRange* range, int N, int cmpMax); +template GPUd() void GPUTPCGMMergerMergeBorders::Thread<3>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, gputpcgmmergertypes::GPUTPCGMBorderRange* range, int N, int cmpMax); template <> GPUdii() void GPUTPCGMMergerMergeBorders::Thread<1>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger, int iSlice, char withinSlice, char mergeMode) { diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h index c93099151eccc..0614f82926b1e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h @@ -92,7 +92,7 @@ class GPUTPCGMMergerUnpackResetIds : public GPUTPCGMMergerGeneral class GPUTPCGMMergerResolve : public GPUTPCGMMergerGeneral { public: - struct GPUSharedMemory : public GPUTPCGMMergerTypes::GPUResolveSharedMemory { + struct GPUSharedMemory : public gputpcgmmergertypes::GPUResolveSharedMemory { }; #if !defined(GPUCA_ALIROOT_LIB) || !defined(GPUCA_GPUCODE) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h b/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h index bac688e79884b..a40e29c181c2f 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h @@ -21,7 +21,7 @@ namespace GPUCA_NAMESPACE { namespace gpu { -namespace GPUTPCGMMergerTypes +namespace gputpcgmmergertypes { enum attachTypes { attachAttached = 0x40000000, @@ -53,7 +53,7 @@ struct GPUTPCGMBorderRange { float fMin, fMax; }; -} // namespace GPUTPCGMMergerTypes +} // namespace gputpcgmmergertypes } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index bf31f6efb47ad..0703dadaa500d 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -627,7 +627,7 @@ GPUd() float GPUTPCGMPropagator::PredictChi2(float posY, float posZ, float err2Y } } -GPUd() int GPUTPCGMPropagator::Update(float posY, float posZ, int iRow, const GPUParam& GPUrestrict() param, short clusterState, char rejectChi2, GPUTPCGMMergerTypes::InterpolationErrorHit* inter, bool refit) +GPUd() int GPUTPCGMPropagator::Update(float posY, float posZ, int iRow, const GPUParam& GPUrestrict() param, short clusterState, char rejectChi2, gputpcgmmergertypes::InterpolationErrorHit* inter, bool refit) { float err2Y, err2Z; GetErr2(err2Y, err2Z, param, posZ, iRow, clusterState); @@ -663,7 +663,7 @@ GPUd() int GPUTPCGMPropagator::Update(float posY, float posZ, int iRow, const GP return Update(posY, posZ, clusterState, rejectChi2 == 1, err2Y, err2Z); } -GPUd() int GPUTPCGMPropagator::InterpolateReject(float posY, float posZ, short clusterState, char rejectChi2, GPUTPCGMMergerTypes::InterpolationErrorHit* inter, float err2Y, float err2Z) +GPUd() int GPUTPCGMPropagator::InterpolateReject(float posY, float posZ, short clusterState, char rejectChi2, gputpcgmmergertypes::InterpolationErrorHit* inter, float err2Y, float err2Z) { float* GPUrestrict() mC = mT->Cov(); float* GPUrestrict() mP = mT->Par(); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h index 4e7f01e976391..4d12b1d289da7 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h @@ -35,7 +35,7 @@ namespace gpu { class GPUTPCGMTrackParam; struct GPUParam; -namespace GPUTPCGMMergerTypes +namespace gputpcgmmergertypes { struct InterpolationErrorHit; } @@ -98,9 +98,9 @@ class GPUTPCGMPropagator GPUd() int PropagateToXAlphaBz(float posX, float posAlpha, bool inFlyDirection); - GPUd() int Update(float posY, float posZ, int iRow, const GPUParam& param, short clusterState, char rejectChi2, GPUTPCGMMergerTypes::InterpolationErrorHit* inter, bool refit); + GPUd() int Update(float posY, float posZ, int iRow, const GPUParam& param, short clusterState, char rejectChi2, gputpcgmmergertypes::InterpolationErrorHit* inter, bool refit); GPUd() int Update(float posY, float posZ, short clusterState, bool rejectChi2, float err2Y, float err2Z); - GPUd() int InterpolateReject(float posY, float posZ, short clusterState, char rejectChi2, GPUTPCGMMergerTypes::InterpolationErrorHit* inter, float err2Y, float err2Z); + GPUd() int InterpolateReject(float posY, float posZ, short clusterState, char rejectChi2, gputpcgmmergertypes::InterpolationErrorHit* inter, float err2Y, float err2Z); GPUd() float PredictChi2(float posY, float posZ, int iRow, const GPUParam& param, short clusterState) const; GPUd() float PredictChi2(float posY, float posZ, float err2Y, float err2Z) const; GPUd() int RejectCluster(float chiY, float chiZ, unsigned char clusterState) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index d5dcb2936d9e6..70eae65b3754e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -61,7 +61,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, GPUdEdx dEdx; GPUTPCGMPropagator prop; - GPUTPCGMMergerTypes::InterpolationErrors interpolation; + gputpcgmmergertypes::InterpolationErrors interpolation; prop.SetMaterialTPC(); prop.SetPolynomialField(&merger->Param().polynomialField); prop.SetMaxSinPhi(maxSinPhi); @@ -505,10 +505,10 @@ GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict const int nBinsY = row.Grid().Ny(); const int idOffset = tracker.Data().ClusterIdOffset(); const int* ids = &(tracker.Data().ClusterDataIndex()[row.HitNumberOffset()]); - unsigned int myWeight = Merger->TrackOrderAttach()[iTrack] | GPUTPCGMMergerTypes::attachAttached | GPUTPCGMMergerTypes::attachTube; + unsigned int myWeight = Merger->TrackOrderAttach()[iTrack] | gputpcgmmergertypes::attachAttached | gputpcgmmergertypes::attachTube; GPUAtomic(unsigned int)* const weights = Merger->ClusterAttachment(); if (goodLeg) { - myWeight |= GPUTPCGMMergerTypes::attachGoodLeg; + myWeight |= gputpcgmmergertypes::attachGoodLeg; } for (int k = 0; k <= nz; k++) { const int mybin = bin + k * nBinsY; diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 33ad8f525c4d3..79b6179793bfc 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -716,14 +716,14 @@ GPUDisplay::vboList GPUDisplay::DrawClusters(const GPUTPCTracker& tracker, int s if (mQA && mQA->clusterRemovable(cid, mMarkAdjacentClusters == 17)) { draw = select == tMARKED; } - } else if ((mMarkAdjacentClusters & 2) && (attach & GPUTPCGMMergerTypes::attachTube)) { + } else if ((mMarkAdjacentClusters & 2) && (attach & gputpcgmmergertypes::attachTube)) { draw = select == tMARKED; - } else if ((mMarkAdjacentClusters & 1) && (attach & (GPUTPCGMMergerTypes::attachGood | GPUTPCGMMergerTypes::attachTube)) == 0) { + } else if ((mMarkAdjacentClusters & 1) && (attach & (gputpcgmmergertypes::attachGood | gputpcgmmergertypes::attachTube)) == 0) { draw = select == tMARKED; - } else if ((mMarkAdjacentClusters & 4) && (attach & GPUTPCGMMergerTypes::attachGoodLeg) == 0) { + } else if ((mMarkAdjacentClusters & 4) && (attach & gputpcgmmergertypes::attachGoodLeg) == 0) { draw = select == tMARKED; } else if (mMarkAdjacentClusters & 8) { - if (fabsf(tracker.GetConstantMem()->ioPtrs.mergedTracks[attach & GPUTPCGMMergerTypes::attachTrackMask].GetParam().GetQPt()) > 20.f) { + if (fabsf(tracker.GetConstantMem()->ioPtrs.mergedTracks[attach & gputpcgmmergertypes::attachTrackMask].GetParam().GetQPt()) > 20.f) { draw = select == tMARKED; } } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 1f99d2305fe9d..1a836b55e1bc3 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -68,7 +68,7 @@ using namespace GPUCA_NAMESPACE::gpu; if (!unattached && mTrackMCLabels[id].isValid()) { \ int mcLabel = mTrackMCLabels[id].getTrackID()); \ if (mTrackMCLabelsReverse[mcLabel] != id) { \ - attach &= (~GPUTPCGMMergerTypes::attachGoodLeg); \ + attach &= (~gputpcgmmergertypes::attachGoodLeg); \ } \ } #else @@ -80,7 +80,7 @@ using namespace GPUCA_NAMESPACE::gpu; float qpt = 0; \ bool lowPt = false; \ bool mev200 = false; \ - int id = attach & GPUTPCGMMergerTypes::attachTrackMask; \ + int id = attach & gputpcgmmergertypes::attachTrackMask; \ if (!unattached) { \ qpt = fabsf(merger.OutputTracks()[id].GetParam().GetQPt()); \ lowPt = qpt > 20; \ @@ -96,16 +96,16 @@ using namespace GPUCA_NAMESPACE::gpu; if (unattached) { \ } else if (lowPt) { \ mNRecClustersLowPt++; \ - } else if ((attach & GPUTPCGMMergerTypes::attachGoodLeg) == 0) { \ + } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { \ mNRecClustersLoopers++; \ - } else if ((attach & GPUTPCGMMergerTypes::attachTube) && mev200) { \ + } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ mNRecClustersTube200++; \ - } else if (attach & GPUTPCGMMergerTypes::attachHighIncl) { \ + } else if (attach & gputpcgmmergertypes::attachHighIncl) { \ mNRecClustersHighIncl++; \ - } else if (attach & GPUTPCGMMergerTypes::attachTube) { \ + } else if (attach & gputpcgmmergertypes::attachTube) { \ protect = true; \ mNRecClustersTube++; \ - } else if ((attach & GPUTPCGMMergerTypes::attachGood) == 0) { \ + } else if ((attach & gputpcgmmergertypes::attachGood) == 0) { \ protect = true; \ mNRecClustersRejected++; \ } else { \ @@ -115,12 +115,12 @@ using namespace GPUCA_NAMESPACE::gpu; #define CHECK_CLUSTER_STATE_CHK_NOCOUNT() \ if (unattached) { \ } else if (lowPt) { \ - } else if ((attach & GPUTPCGMMergerTypes::attachGoodLeg) == 0) { \ - } else if ((attach & GPUTPCGMMergerTypes::attachTube) && mev200) { \ - } else if (attach & GPUTPCGMMergerTypes::attachHighIncl) { \ - } else if (attach & GPUTPCGMMergerTypes::attachTube) { \ + } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { \ + } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ + } else if (attach & gputpcgmmergertypes::attachHighIncl) { \ + } else if (attach & gputpcgmmergertypes::attachTube) { \ protect = true; \ - } else if ((attach & GPUTPCGMMergerTypes::attachGood) == 0) { \ + } else if ((attach & gputpcgmmergertypes::attachGood) == 0) { \ protect = true; \ } else { \ physics = true; \ @@ -729,8 +729,8 @@ GPUCA_OPENMP(parallel for) for (unsigned int i = 0; i < GetNMCLabels(); i++) { if (mClusterParam[i].attached == 0 && mClusterParam[i].fakeAttached == 0) { int attach = merger.ClusterAttachment()[i]; - if (attach & GPUTPCGMMergerTypes::attachFlagMask) { - int track = attach & GPUTPCGMMergerTypes::attachTrackMask; + if (attach & gputpcgmmergertypes::attachFlagMask) { + int track = attach & gputpcgmmergertypes::attachTrackMask; mcLabelI_t trackL = mTrackMCLabels[track]; bool fake = true; for (int j = 0; j < GetMCLabelNID(i); j++) { @@ -1164,7 +1164,7 @@ GPUCA_OPENMP(parallel for) int attach = merger.ClusterAttachment()[i]; CHECK_CLUSTER_STATE_NOCOUNT(); if (mClusterParam[i].adjacent) { - int label = merger.ClusterAttachment()[i] & GPUTPCGMMergerTypes::attachTrackMask; + int label = merger.ClusterAttachment()[i] & gputpcgmmergertypes::attachTrackMask; if (!mTrackMCLabels[label].isValid()) { float totalWeight = 0.; for (int j = 0; j < GetMCLabelNID(i); j++) { @@ -1321,8 +1321,8 @@ GPUCA_OPENMP(parallel for) mNRecClustersFullFakeRemove400++; } /*printf("Fake removal (%d): Hit %7d, attached %d lowPt %d looper %d tube200 %d highIncl %d tube %d bad %d recPt %7.2f recLabel %6d", totalFake, i, (int) (mClusterParam[i].attached || mClusterParam[i].fakeAttached), - (int) lowPt, (int) ((attach & GPUTPCGMMergerTypes::attachGoodLeg) == 0), (int) ((attach & GPUTPCGMMergerTypes::attachTube) && mev200), - (int) ((attach & GPUTPCGMMergerTypes::attachHighIncl) != 0), (int) ((attach & GPUTPCGMMergerTypes::attachTube) != 0), (int) ((attach & GPUTPCGMMergerTypes::attachGood) == 0), + (int) lowPt, (int) ((attach & gputpcgmmergertypes::attachGoodLeg) == 0), (int) ((attach & gputpcgmmergertypes::attachTube) && mev200), + (int) ((attach & gputpcgmmergertypes::attachHighIncl) != 0), (int) ((attach & gputpcgmmergertypes::attachTube) != 0), (int) ((attach & gputpcgmmergertypes::attachGood) == 0), fabsf(qpt) > 0 ? 1.f / qpt : 0.f, id); for (int j = 0;j < GetMCLabelNID(i);j++) { diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index f0b3e67f6896e..a11a34990650f 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -553,7 +553,7 @@ void OutputStat(GPUChainTracking* t, long long int* nTracksTotal = nullptr, long unsigned int nCls = configStandalone.proc.doublePipeline ? t->mIOPtrs.clustersNative->nClustersTotal : t->GetTPCMerger().NMaxClusters(); for (unsigned int k = 0; k < nCls; k++) { int attach = t->mIOPtrs.mergedTrackHitAttachment[k]; - if (attach & GPUTPCGMMergerTypes::attachFlagMask) { + if (attach & gputpcgmmergertypes::attachFlagMask) { nAdjacentClusters++; } } diff --git a/GPU/GPUTracking/TPCClusterFinder/CfConsts.h b/GPU/GPUTracking/TPCClusterFinder/CfConsts.h index 8edb84dbbb9fb..62a53afa45efb 100644 --- a/GPU/GPUTracking/TPCClusterFinder/CfConsts.h +++ b/GPU/GPUTracking/TPCClusterFinder/CfConsts.h @@ -20,7 +20,7 @@ namespace GPUCA_NAMESPACE { namespace gpu { -namespace CfConsts +namespace cfconsts { GPUconstexpr() tpccf::Delta2 InnerNeighbors[8] = @@ -189,7 +189,7 @@ GPUconstexpr() uint NoiseSuppressionMinima[NOISE_SUPPRESSION_NEIGHBOR_NUM] = (1 << 24), (1 << 24) | (1 << 25)}; -} // namespace CfConsts +} // namespace cfconsts } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/TPCClusterFinder/CfUtils.h b/GPU/GPUTracking/TPCClusterFinder/CfUtils.h index b3cd7ab7eb059..e16353acf6cc3 100644 --- a/GPU/GPUTracking/TPCClusterFinder/CfUtils.h +++ b/GPU/GPUTracking/TPCClusterFinder/CfUtils.h @@ -34,12 +34,12 @@ class CfUtils static GPUdi() bool innerAboveThreshold(uchar aboveThreshold, ushort outerIdx) { - return aboveThreshold & (1 << CfConsts::OuterToInner[outerIdx]); + return aboveThreshold & (1 << cfconsts::OuterToInner[outerIdx]); } static GPUdi() bool innerAboveThresholdInv(uchar aboveThreshold, ushort outerIdx) { - return aboveThreshold & (1 << CfConsts::OuterToInnerInv[outerIdx]); + return aboveThreshold & (1 << cfconsts::OuterToInnerInv[outerIdx]); } static GPUdi() bool isPeak(uchar peak) { return peak & 0x01; } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx index 213c111310fb7..c3002db1c717e 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx @@ -118,7 +118,7 @@ GPUdii() void GPUTPCCFClusterizer::updateClusterInner( GPUCA_UNROLL(U(), U()) for (ushort i = 0; i < N; i++) { - Delta2 d = CfConsts::InnerNeighbors[i]; + Delta2 d = cfconsts::InnerNeighbors[i]; PackedCharge p = buf[N * lid + i]; @@ -149,7 +149,7 @@ GPUdii() void GPUTPCCFClusterizer::updateClusterOuter( for (ushort i = offset; i < M + offset; i++) { PackedCharge p = buf[N * lid + i]; - Delta2 d = CfConsts::OuterNeighbors[i]; + Delta2 d = cfconsts::OuterNeighbors[i]; Charge q = cluster->updateOuter(p, d); static_cast<void>(q); // Avoid unused varible warning on GPU. @@ -180,7 +180,7 @@ GPUdii() void GPUTPCCFClusterizer::buildCluster( ll, 0, 8, - CfConsts::InnerNeighbors, + cfconsts::InnerNeighbors, posBcast, buf); updateClusterInner( @@ -205,7 +205,7 @@ GPUdii() void GPUTPCCFClusterizer::buildCluster( ll, 0, 16, - CfConsts::OuterNeighbors, + cfconsts::OuterNeighbors, posBcast, innerAboveThreshold, buf); @@ -230,7 +230,7 @@ GPUdii() void GPUTPCCFClusterizer::buildCluster( ll, 0, 16, - CfConsts::OuterNeighbors, + cfconsts::OuterNeighbors, posBcast + wgSizeHalf, innerAboveThreshold + wgSizeHalf, buf); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx index dcbc92d3248d6..26f4dceeb96f6 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx @@ -63,7 +63,7 @@ GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int nBlocks, int nThreads ll, 0, 8, - CfConsts::InnerNeighbors, + cfconsts::InnerNeighbors, smem.posBcast1, smem.buf); @@ -88,7 +88,7 @@ GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int nBlocks, int nThreads ll, 0, 16, - CfConsts::OuterNeighbors, + cfconsts::OuterNeighbors, smem.posBcast1, smem.aboveThresholdBcast, smem.buf); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx index 41ed6a79e1e7c..d2fe88b7e8857 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx @@ -150,7 +150,7 @@ GPUdi() bool GPUTPCCFNoiseSuppression::keepPeak( GPUCA_UNROLL(U(), U()) for (int i = 0; i < NOISE_SUPPRESSION_NEIGHBOR_NUM; i++) { bool otherPeak = (peaks & (ulong(1) << i)); - bool minimaBetween = (minima & CfConsts::NoiseSuppressionMinima[i]); + bool minimaBetween = (minima & cfconsts::NoiseSuppressionMinima[i]); keepMe &= (!otherPeak || minimaBetween); } @@ -194,7 +194,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( ll, 16, 2, - CfConsts::NoiseSuppressionNeighbors, + cfconsts::NoiseSuppressionNeighbors, posBcast, buf); @@ -215,7 +215,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( ll, 0, 16, - CfConsts::NoiseSuppressionNeighbors, + cfconsts::NoiseSuppressionNeighbors, posBcast, buf); @@ -238,7 +238,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( ll, 18, 16, - CfConsts::NoiseSuppressionNeighbors, + cfconsts::NoiseSuppressionNeighbors, posBcast, buf); @@ -262,7 +262,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( ll, 0, 16, - CfConsts::NoiseSuppressionNeighbors, + cfconsts::NoiseSuppressionNeighbors, posBcast + wgSizeHalf, buf); @@ -285,7 +285,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( ll, 18, 16, - CfConsts::NoiseSuppressionNeighbors, + cfconsts::NoiseSuppressionNeighbors, posBcast + wgSizeHalf, buf); @@ -315,7 +315,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( ll, 0, 16, - CfConsts::NoiseSuppressionNeighbors, + cfconsts::NoiseSuppressionNeighbors, posBcast, bufp); @@ -333,7 +333,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( ll, 18, 16, - CfConsts::NoiseSuppressionNeighbors, + cfconsts::NoiseSuppressionNeighbors, posBcast, bufp); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx index 328e901576d41..bdfb8518c8828 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx @@ -61,7 +61,7 @@ GPUdii() bool GPUTPCCFPeakFinder::isPeak( ll, 0, N, - CfConsts::InnerNeighbors, + cfconsts::InnerNeighbors, posBcast, buf); From 92c36d3beaa86835115aba7d8fe5ff0c57366711 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 23 Sep 2020 22:53:13 +0200 Subject: [PATCH 0728/1751] Tolerate missing TFs for particular links when reading raw data In case particular link had some TF absent (may happen in the end of short digitized data) just log the error message and skip this link --- Detectors/Raw/include/DetectorsRaw/RawFileReader.h | 2 +- Detectors/Raw/src/RawFileReader.cxx | 6 ++++-- Detectors/Raw/src/RawFileReaderWorkflow.cxx | 7 +++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index 643834c485d37..8bc080bf5111e 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -178,7 +178,7 @@ class RawFileReader size_t skipNextHBF(); size_t skipNextTF(); - void rewindToTF(uint32_t tf); + bool rewindToTF(uint32_t tf); void print(bool verbose = false, const std::string& pref = "") const; std::string describe() const; diff --git a/Detectors/Raw/src/RawFileReader.cxx b/Detectors/Raw/src/RawFileReader.cxx index 635ff5927e9ae..c2d6889771fa2 100644 --- a/Detectors/Raw/src/RawFileReader.cxx +++ b/Detectors/Raw/src/RawFileReader.cxx @@ -227,15 +227,17 @@ size_t RawFileReader::LinkData::skipNextTF() } //_____________________________________________________________________ -void RawFileReader::LinkData::rewindToTF(uint32_t tf) +bool RawFileReader::LinkData::rewindToTF(uint32_t tf) { // go to given TF if (tf < tfStartBlock.size()) { nextBlock2Read = tfStartBlock[tf].first; } else { - LOG(WARNING) << "No TF " << tf << " for link " << describe(); + LOG(WARNING) << "No TF " << tf << " for " << describe(); nextBlock2Read = -1; + return false; } + return true; } //____________________________________________ diff --git a/Detectors/Raw/src/RawFileReaderWorkflow.cxx b/Detectors/Raw/src/RawFileReaderWorkflow.cxx index a10f5fff61cf9..8fc58670ae1a2 100644 --- a/Detectors/Raw/src/RawFileReaderWorkflow.cxx +++ b/Detectors/Raw/src/RawFileReaderWorkflow.cxx @@ -133,9 +133,6 @@ class RawReaderSpecs : public o2f::Task tfID = mMinTFID; } mReader->setNextTFToRead(tfID); - for (int il = 0; il < nlinks; il++) { - mReader->getLink(il).rewindToTF(tfID); - } std::vector<RawFileReader::PartStat> partsSP; const auto& hbfU = HBFUtils::Instance(); @@ -147,7 +144,9 @@ class RawReaderSpecs : public o2f::Task for (int il = 0; il < nlinks; il++) { auto& link = mReader->getLink(il); - + if (!link.rewindToTF(tfID)) { + continue; // this link has no data for wanted TF + } if (!findOutputChannel(link, mTFCounter)) { // no output channel continue; } From d5790c7c45521bac1cd9f184ee9d474a336e9bec Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 23 Sep 2020 22:24:44 +0200 Subject: [PATCH 0729/1751] Acknowledge ITS GBT Calibration status word At the moment simply jump over --- .../include/ITSMFTReconstruction/GBTLink.h | 14 ++++++++++- .../include/ITSMFTReconstruction/GBTWord.h | 25 +++++++++++++++++++ .../common/reconstruction/src/GBTLink.cxx | 15 +++++++++++ .../src/ITSMFTReconstructionLinkDef.h | 1 + 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h index cc2b0f915f28f..027f7dfb955d3 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h @@ -126,6 +126,7 @@ struct GBTLink { void printHeader(const GBTDataHeaderL* gbtH); void printTrailer(const GBTDataTrailer* gbtT); void printDiagnostic(const GBTDiagnostic* gbtD); + void printCalibrationWord(const GBTCalibration* gbtCal); bool nextCRUPage(); #ifndef _RAW_READER_ERROR_CHECKS_ // define dummy inline check methods, will be compiled out @@ -144,6 +145,7 @@ struct GBTLink { ErrorType checkErrorsPacketDoneMissing(const GBTDataTrailer* gbtT, bool notEnd) const { return NoError; } ErrorType checkErrorsLanesStops() const { return NoError; } ErrorType checkErrorsDiagnosticWord(const GBTDiagnostic* gbtD) const { return NoError; } + ErrorType checkErrorsCalibrationWord(const GBTCalibration* gbtCal) const { return NoError; } #else ErrorType checkErrorsRDH(const RDH& rdh); ErrorType checkErrorsRDHStop(const RDH& rdh); @@ -157,6 +159,7 @@ struct GBTLink { ErrorType checkErrorsPacketDoneMissing(const GBTDataTrailer* gbtT, bool notEnd); ErrorType checkErrorsLanesStops(); ErrorType checkErrorsDiagnosticWord(const GBTDiagnostic* gbtD); + ErrorType checkErrorsCalibrationWord(const GBTCalibration* gbtCal); #endif ClassDefNV(GBTLink, 1); @@ -244,8 +247,17 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) lanesStop = 0; lanesWithData = 0; } - + if (format == NewFormat) { // at the moment just check if calibration word is there + auto gbtC = reinterpret_cast<const o2::itsmft::GBTCalibration*>(&currRawPiece->data[dataOffset]); + if (gbtC->isCalibrationWord()) { + if (verbosity >= VerboseHeaders) { + printCalibrationWord(gbtC); + } + dataOffset += GBTPaddedWordLength; + } + } auto gbtD = reinterpret_cast<const o2::itsmft::GBTData*>(&currRawPiece->data[dataOffset]); + while (!gbtD->isDataTrailer()) { // start reading real payload nw++; int cableHW = gbtD->getCableID(), cableSW = chmap.cableHW2SW(ruPtr->ruInfo->ruType, cableHW); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h index 39ea345666eb8..1f7310fa0dd6b 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h @@ -32,6 +32,8 @@ constexpr uint8_t GBTFlagDataTrailer = 0xf0; constexpr uint8_t GBTFlagTrigger = 0xe8; /// GBT diagnostic status word flag constexpr uint8_t GBTFlagDiagnostic = 0xe4; +/// GBT calibration status word flag +constexpr uint8_t GBTFlagCalibration = 0xf8; // GBT header flag in the RDH constexpr uint8_t GBTFlagRDH = 0x00; @@ -88,6 +90,11 @@ struct GBTWord { uint64_t na0diag : 64; /// // uint64_t id : 8; /// 72:79 0xe4; diagnostic word identifier }; // HEADER Legacy + struct __attribute__((packed)) { + uint64_t calibUserField : 48; /// 0:47 user field + uint64_t calibCounter : 24; /// 48:71 elf-incrementing counter of + // uint64_t id : 8; /// 72:79 0xf8; Calibration Status Word (HSW) identifier + }; /// Calibration Data Word uint8_t data8[16]; // 80 bits GBT word + optional padding to 128 bits uint64_t data64[2] = {0}; @@ -107,6 +114,9 @@ struct GBTWord { /// check if the GBT Header corresponds to Diagnostic data bool isDiagnosticWord() const { return id == GBTFlagDiagnostic; } + /// check if the GBT Header corresponds to Calibration word + bool isCalibrationWord() const { return id == GBTFlagCalibration; } + /// check if the GBT Header corresponds to ITS IB data (header is combined with lanes info) bool isDataIB() const { return (id & 0xe0) == GBTFlagDataIB; } @@ -262,6 +272,21 @@ struct GBTDiagnostic : public GBTWord { ClassDefNV(GBTDiagnostic, 1); }; +struct GBTCalibration : public GBTWord { // calibration data word + /// bits 0 : 47, user-written tagging fields + /// bits 48 : 71, self-incrementing counter of CDW words + /// bits 72 : 79, calibration indicator + + GBTCalibration() { id = GBTFlagCalibration; } + GBTCalibration(uint64_t userData, uint16_t counter = 0) + { + id = GBTFlagCalibration; + calibUserField = userData & ((0x1UL << 48) - 1); + calibCounter = counter & ((0x1 << 24) - 1); + } + ClassDefNV(GBTCalibration, 1); +}; + } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index 665a68e361c34..60e1f5e76d133 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -74,6 +74,13 @@ void GBTLink::printTrigger(const GBTTrigger* gbtTrg) LOG(INFO) << "Trigger : Orbit " << gbtTrg->orbit << " BC: " << gbtTrg->bc; } +///_________________________________________________________________ +void GBTLink::printCalibrationWord(const GBTCalibration* gbtCal) +{ + gbtCal->printX(); + LOGF(INFO, "Calibration word %5d | user_data 0x%012lx", gbtCal->calibCounter, gbtCal->bc); +} + ///_________________________________________________________________ void GBTLink::printHeader(const GBTDataHeader* gbtH) { @@ -194,6 +201,14 @@ GBTLink::ErrorType GBTLink::checkErrorsTriggerWord(const GBTTrigger* gbtTrg) return NoError; } +///_________________________________________________________________ +/// Check the GBT Calibration word correctness +GBTLink::ErrorType GBTLink::checkErrorsCalibrationWord(const GBTCalibration* gbtCal) +{ + // at the moment do nothing + return NoError; +} + ///_________________________________________________________________ /// Check the GBT Header word correctness GBTLink::ErrorType GBTLink::checkErrorsHeaderWord(const GBTDataHeader* gbtH) diff --git a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h index c105c30d481cd..9362d1c1bca81 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h +++ b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h @@ -37,6 +37,7 @@ #pragma link C++ class o2::itsmft::GBTDataTrailer + ; #pragma link C++ class o2::itsmft::GBTTrigger + ; #pragma link C++ class o2::itsmft::GBTDiagnostic + ; +#pragma link C++ class o2::itsmft::GBTCalibration + ; #pragma link C++ class o2::itsmft::GBTData + ; #pragma link C++ class o2::itsmft::PayLoadCont + ; #pragma link C++ class o2::itsmft::PayLoadSG + ; From 03c2255d40770b56876aecd0dd8591d7e62d3e49 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 24 Sep 2020 00:35:44 +0200 Subject: [PATCH 0730/1751] Acknowledge ITS GBT Diagnostic and Status words At the moment just print and jump over. Not sure the Status word description is correct --- .../include/ITSMFTReconstruction/GBTLink.h | 7 +++ .../include/ITSMFTReconstruction/GBTWord.h | 55 +++++++++++++++++++ .../common/reconstruction/src/GBTLink.cxx | 29 ++++++++++ .../src/ITSMFTReconstructionLinkDef.h | 2 + 4 files changed, 93 insertions(+) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h index 027f7dfb955d3..7d29794b71308 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h @@ -33,6 +33,8 @@ if ((what) == Abort) { \ discardData(); \ return AbortedOnError; \ + } else if ((what) == Skip) { \ + continue; \ } namespace o2 @@ -59,6 +61,7 @@ struct GBTLink { enum ErrorType : int8_t { NoError, Warning, + Skip, Abort }; enum Verbosity : int8_t { Silent = -1, @@ -126,7 +129,9 @@ struct GBTLink { void printHeader(const GBTDataHeaderL* gbtH); void printTrailer(const GBTDataTrailer* gbtT); void printDiagnostic(const GBTDiagnostic* gbtD); + void printCableDiagnostic(const GBTCableDiagnostic* gbtD); void printCalibrationWord(const GBTCalibration* gbtCal); + void printCableStatus(const GBTCableStatus* gbtS); bool nextCRUPage(); #ifndef _RAW_READER_ERROR_CHECKS_ // define dummy inline check methods, will be compiled out @@ -161,6 +166,7 @@ struct GBTLink { ErrorType checkErrorsDiagnosticWord(const GBTDiagnostic* gbtD); ErrorType checkErrorsCalibrationWord(const GBTCalibration* gbtCal); #endif + ErrorType checkErrorsGBTDataID(const GBTData* dbtD); ClassDefNV(GBTLink, 1); }; @@ -260,6 +266,7 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) while (!gbtD->isDataTrailer()) { // start reading real payload nw++; + GBTLINK_DECODE_ERRORCHECK(checkErrorsGBTDataID(gbtD)); int cableHW = gbtD->getCableID(), cableSW = chmap.cableHW2SW(ruPtr->ruInfo->ruType, cableHW); if (verbosity >= VerboseData) { gbtD->printX(); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h index 1f7310fa0dd6b..7a3bf776c0a05 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h @@ -41,6 +41,13 @@ constexpr uint8_t GBTFlagRDH = 0x00; constexpr uint8_t GBTFlagDataIB = 0x20; // GBT header flag for the ITS OB: 010 bb ccc with bb -> Connector Number (00,01,10,11), ccc -> Lane Number (0-6) constexpr uint8_t GBTFlagDataOB = 0x40; +// GBT header flag for the ITS IB idagnostic : 101 bbbbb with bbbbb -> Lane Number (0-8) +constexpr uint8_t GBTFlagDiagnosticIB = 0xa0; +// GBT header flag for the ITS OB diagnostic word: 110 bb ccc with bb -> Connector Number (00,01,10,11), ccc -> Lane Number (0-6) +constexpr uint8_t GBTFlagDiagnosticOB = 0x60; + +// GBT header flag for the ITS Status word : 111 bbbbb with bbbbb -> Lane Number +constexpr uint8_t GBTFlagStatus = 0xe0; constexpr int GBTWordLength = 10; // lentgh in bytes constexpr int GBTPaddedWordLength = 16; // lentgh in bytes with padding @@ -55,6 +62,7 @@ struct GBTWord { uint64_t na1hn : 8; /// 28:71 reserved uint64_t id : 8; /// 72:79 0xe0; Header Status Word (HSW) identifier }; // HEADER NEW + struct /*__attribute__((packed))*/ { uint64_t packetIdx : 16; /// 0:15 Index of Data Packet within trigger uint64_t activeLanesL : 28; /// 16:43 Bit map of lanes active and eligible for readout @@ -62,6 +70,7 @@ struct GBTWord { uint64_t na1h : 8; /// 64:71 reserved // uint64_t id : 8; /// 72:79 0xe0; Header Status Word (HSW) identifier }; // HEADER Legacy + struct /*__attribute__((packed))*/ { uint64_t lanesStops : 28; /// 0:27 Bit map of “Valid Lane stops received”, 1 bit per lane, NOT USED uint64_t lanesTimeout : 28; /// 28:55 Bit map of “Lane timeouts received”, 1 bit per lane, NOT USED @@ -74,6 +83,7 @@ struct GBTWord { uint64_t na2t : 3; /// 69:71 reserved // uint8_t id : 8; /// = 0xf0; Trailer Status Word (TSW) identifier }; // TRAILER + struct /*__attribute__((packed))*/ { uint64_t triggerType : 12; /// 0:11 12 lowest bits of trigger type received from CTP uint64_t internal : 1; /// 12 Used in Continuous Mode for internally generated trigger @@ -86,16 +96,24 @@ struct GBTWord { uint64_t na3tr : 6; /// 64:71 reserved // uint8_t id : 8; /// = 0xc0; Trigger Status Word (TSW) identifier }; // TRIGGER + struct /*__attribute__((packed))*/ { uint64_t na0diag : 64; /// // uint64_t id : 8; /// 72:79 0xe4; diagnostic word identifier }; // HEADER Legacy + struct __attribute__((packed)) { uint64_t calibUserField : 48; /// 0:47 user field uint64_t calibCounter : 24; /// 48:71 elf-incrementing counter of // uint64_t id : 8; /// 72:79 0xf8; Calibration Status Word (HSW) identifier }; /// Calibration Data Word + struct { + uint64_t diagnosticData : 64; /// 0:63 Error specific diagnostic data + uint64_t laneErrorID : 8; /// 64:71 Identifier of the specific error condition + // uint64_t id : 8; /// 72:79 0xe0; Status Word (HSW) identifier + }; // HEADER Legacy + uint8_t data8[16]; // 80 bits GBT word + optional padding to 128 bits uint64_t data64[2] = {0}; }; @@ -120,9 +138,22 @@ struct GBTWord { /// check if the GBT Header corresponds to ITS IB data (header is combined with lanes info) bool isDataIB() const { return (id & 0xe0) == GBTFlagDataIB; } + /// check if the GBT Header corresponds to ITS IB diagnostics data (header is combined with lanes info) + bool isCableDiagnosticIB() const { return (id & 0xe0) == GBTFlagDiagnosticIB; } + /// check if the GBT Header corresponds to ITS OB data (header is combined with lanes/connector info) bool isDataOB() const { return (id & 0xe0) == GBTFlagDataOB; } + /// check if the GBT Header corresponds to ITS OB diagnostics data (header is combined with lanes info) + bool isCableDiagnosticOB() const { return (id & 0xe0) == GBTFlagDiagnosticIB; } + + /// check if the GBT Header corresponds to ITS IB or OB data (header is combined with lanes/connector info) + bool isData() const { return isDataIB() || isDataOB(); } + + bool isCableDiagnostic() const { return isCableDiagnosticIB() || isCableDiagnosticIB(); } + + bool isStatus() const { return (id & 0xe0) == GBTFlagStatus; } + const uint64_t* getW64() const { return data64; } const uint8_t* getW8() const { return data8; } @@ -272,6 +303,30 @@ struct GBTDiagnostic : public GBTWord { ClassDefNV(GBTDiagnostic, 1); }; +struct GBTCableDiagnostic : public GBTWord { + /// Definition of cable diagnostic word + /// + /// bits 0 : 64, Error specific diagnostic data + /// bits 63 : 71, Identifier of the specific error condition + /// bits 72 : 79, IB or OB diagnostic flag + cable id + + GBTCableDiagnostic(bool ib = true, int lane = 0) { id = (ib ? GBTFlagDiagnosticIB : GBTFlagDiagnosticOB) | (lane & 0x1f); } + int getCableID() const { return id & 0x1f; } // combined connector and lane + bool isIB() const { return (id & 0xe0) == GBTFlagDiagnosticIB; } + bool isOB() const { return (id & 0xe0) == GBTFlagDiagnosticOB; } + ClassDefNV(GBTCableDiagnostic, 1); +}; + +struct GBTCableStatus : public GBTWord { // not sure this is correct, FIXME + /// Definition of cable status word + /// + /// bits 72 : 79, Status flag + cable id + + GBTCableStatus(int lane = 0) { id = GBTFlagStatus | (lane & 0x1f); } + int getCableID() const { return id & 0x1f; } // combined connector and lane + ClassDefNV(GBTCableStatus, 1); +}; + struct GBTCalibration : public GBTWord { // calibration data word /// bits 0 : 47, user-written tagging fields /// bits 48 : 71, self-incrementing counter of CDW words diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index 60e1f5e76d133..f661fb84e1385 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -112,6 +112,20 @@ void GBTLink::printDiagnostic(const GBTDiagnostic* gbtD) LOG(INFO) << "Diagnostic word"; } +///_________________________________________________________________ +void GBTLink::printCableDiagnostic(const GBTCableDiagnostic* gbtD) +{ + gbtD->printX(); + LOGF(INFO, "Diagnostic for %s Lane %d | errorID: %d data 0x%016lx", gbtD->isIB() ? "IB" : "OB", gbtD->getCableID(), gbtD->laneErrorID, gbtD->diagnosticData); +} + +///_________________________________________________________________ +void GBTLink::printCableStatus(const GBTCableStatus* gbtS) +{ + gbtS->printX(); + LOGF(INFO, "Status data, not processed at the moment"); +} + ///==================================================================== #ifdef _RAW_READER_ERROR_CHECKS_ @@ -300,6 +314,21 @@ GBTLink::ErrorType GBTLink::checkErrorsGBTData(int cablePos) return NoError; } +///_________________________________________________________________ +/// Check GBT Data word ID: it might be diagnostic or status data +GBTLink::ErrorType GBTLink::checkErrorsGBTDataID(const GBTData* gbtD) +{ + if (gbtD->isData()) { + return NoError; + } + if (gbtD->isCableDiagnostic()) { + printCableDiagnostic((GBTCableDiagnostic*)gbtD); + } else if (gbtD->isStatus()) { + printCableStatus((GBTCableStatus*)gbtD); + } + return Skip; +} + ///_________________________________________________________________ /// Check the GBT Trailer word correctness GBTLink::ErrorType GBTLink::checkErrorsTrailerWord(const GBTDataTrailer* gbtT) diff --git a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h index 9362d1c1bca81..168ba17660404 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h +++ b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h @@ -37,6 +37,8 @@ #pragma link C++ class o2::itsmft::GBTDataTrailer + ; #pragma link C++ class o2::itsmft::GBTTrigger + ; #pragma link C++ class o2::itsmft::GBTDiagnostic + ; +#pragma link C++ class o2::itsmft::GBTCableDiagnostic + ; +#pragma link C++ class o2::itsmft::GBTCableStatus + ; #pragma link C++ class o2::itsmft::GBTCalibration + ; #pragma link C++ class o2::itsmft::GBTData + ; #pragma link C++ class o2::itsmft::PayLoadCont + ; From d9808a2772fe23b2369a1ec7b104b6c789ba48b8 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 24 Sep 2020 08:58:46 +0200 Subject: [PATCH 0731/1751] RootTreeWriter: Zero copy treatment of trivially messageable vectors (#4417) This commit provides a zero copy treatment for writing std::vector messages to a TTree. Instead of copying the data once more, the new approach fakes a std::vector appearance of the incoming (shared) data (which was read as a gsl::span). In result, this commit leads to memory improvements for workflows such as digitization where the RootTreeWriter is used. --- .../Utils/include/DPLUtils/RootTreeWriter.h | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/Framework/Utils/include/DPLUtils/RootTreeWriter.h b/Framework/Utils/include/DPLUtils/RootTreeWriter.h index 9722f8e0b918e..bd8188947f6db 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeWriter.h +++ b/Framework/Utils/include/DPLUtils/RootTreeWriter.h @@ -603,19 +603,49 @@ class RootTreeWriter template <typename S, typename std::enable_if_t<std::is_same<S, MessageableVectorSpecialization>::value, int> = 0> void fillData(InputContext& context, DataRef const& ref, TBranch* branch, size_t branchIdx) { - using ValueType = typename value_type::value_type; - static_assert(is_messageable<ValueType>::value, "logical error: should be correctly selected by StructureElementTypeTrait"); + using ElementType = typename value_type::value_type; + static_assert(is_messageable<ElementType>::value, "logical error: should be correctly selected by StructureElementTypeTrait"); + + // A helper struct mimicking data layout of std::vector containers + // We assume a standard layout of begin, end, end_capacity + struct VecBase { + const ElementType* start; + const ElementType* end; + const ElementType* cap; + }; + + // a low level hack to make a gsl::span appear as a std::vector so that ROOT serializes the correct type + // but without the need for an extra copy + auto adopt = [](auto const& data, value_type& v) { + static_assert(sizeof(v) == 24); + if (data.size() == 0) { + return; + } + VecBase impl; + impl.start = &(data[0]); + impl.end = &(data[data.size() - 1]) + 1; // end pointer (beyond last element) + impl.cap = impl.end; + std::memcpy(&v, &impl, sizeof(VecBase)); + }; + // if the value type is messagable and has a ROOT dictionary, two serialization methods are possible // for the moment, the InputRecord API can not handle both with the same call try { // try extracting from message with serialization method NONE, throw runtime error // if message is serialized - auto data = context.get<gsl::span<ValueType>>(ref); - value_type clone(data.begin(), data.end()); - if (!runCallback(branch, clone, ref)) { - mStore[branchIdx] = &clone; + auto data = context.get<gsl::span<ElementType>>(ref); + // take an ordinary std::vector "view" on the data + auto* dataview = new value_type; + adopt(data, *dataview); + if (!runCallback(branch, *dataview, ref)) { + mStore[branchIdx] = dataview; branch->Fill(); } + // we delete JUST the view without deleting the data (which is handled by DPL) + auto ptr = (VecBase*)dataview; + if (ptr) { + delete ptr; + } } catch (const std::runtime_error& e) { if constexpr (has_root_dictionary<value_type>::value == true) { // try extracting from message with serialization method ROOT From feff8c626009764b247838b96788099ab59bd8bc Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Thu, 24 Sep 2020 08:00:04 +0100 Subject: [PATCH 0732/1751] Fix links to CMakeInstructions.md in the README of /Examples subfolders (#4392) --- Examples/Ex2/README.md | 2 +- Examples/Ex3/README.md | 2 +- Examples/Ex4/README.md | 2 +- Examples/Ex5/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/Ex2/README.md b/Examples/Ex2/README.md index 3c96cc3e7193e..3f1b9d734ff97 100644 --- a/Examples/Ex2/README.md +++ b/Examples/Ex2/README.md @@ -4,4 +4,4 @@ ## Ex2 A basic library with a Root dictionary -See [CMakeInstructions](../doc/CMakeInstructions.md) for an explanation about this directory. +See [CMakeInstructions](/doc/CMakeInstructions.md) for an explanation about this directory. diff --git a/Examples/Ex3/README.md b/Examples/Ex3/README.md index 879ff48227de8..e0a1a35c1051c 100644 --- a/Examples/Ex3/README.md +++ b/Examples/Ex3/README.md @@ -4,4 +4,4 @@ ## Ex3 Adding an executable -See [CMakeInstructions](../doc/CMakeInstructions.md) for an explanation about this directory. +See [CMakeInstructions](/doc/CMakeInstructions.md) for an explanation about this directory. diff --git a/Examples/Ex4/README.md b/Examples/Ex4/README.md index 9e526d06a4636..6743ca4fc2705 100644 --- a/Examples/Ex4/README.md +++ b/Examples/Ex4/README.md @@ -4,4 +4,4 @@ ## Ex4 Adding tests -See [CMakeInstructions](../doc/CMakeInstructions.md) for an explanation about this directory. +See [CMakeInstructions](/doc/CMakeInstructions.md) for an explanation about this directory. diff --git a/Examples/Ex5/README.md b/Examples/Ex5/README.md index ebc693bb0c68a..6e309644afd4f 100644 --- a/Examples/Ex5/README.md +++ b/Examples/Ex5/README.md @@ -4,4 +4,4 @@ ## Ex5 Adding a man page -See [CMakeInstructions](../doc/CMakeInstructions.md) for an explanation about this directory. +See [CMakeInstructions](/doc/CMakeInstructions.md) for an explanation about this directory. From 8ea50c36f826bac8d689c673051cc935b8c9d448 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 24 Sep 2020 11:36:30 +0200 Subject: [PATCH 0733/1751] DPL: improve InputRecord::size() documentation (#4427) --- Framework/Core/include/Framework/InputRecord.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Framework/Core/include/Framework/InputRecord.h b/Framework/Core/include/Framework/InputRecord.h index b41614bd8f58d..b1fd7d0dc8e9f 100644 --- a/Framework/Core/include/Framework/InputRecord.h +++ b/Framework/Core/include/Framework/InputRecord.h @@ -452,6 +452,9 @@ class InputRecord bool isValid(char const* s) const; bool isValid(int pos) const; + /// Return the total number of inputs in the InputRecord. Notice that these will include + /// both valid and invalid inputs (i.e. inputs which have not arrived yet), depending + /// on the ChannelPolicy you have (using the default policy all inputs will be valid). size_t size() const { return mSpan.size(); From a25ac0c53b78e5dfda235edfb87e0717aa49634e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 24 Sep 2020 13:12:41 +0200 Subject: [PATCH 0734/1751] DPL: hide column types from TableBuilder lambdas (#4425) --- Framework/Core/include/Framework/TableBuilder.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index 3d8d3cdc1209c..835ed75e40445 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -435,8 +435,8 @@ class TableBuilder template <typename... ARGS> auto makeFinalizer() { - mFinalizer = [schema = mSchema, &arrays = mArrays, builders = (BuildersTuple<ARGS...>*)mBuilders]() -> std::shared_ptr<arrow::Table> { - auto status = TableBuilderHelpers::finalize(arrays, *builders, std::make_index_sequence<sizeof...(ARGS)>{}); + mFinalizer = [schema = mSchema, &arrays = mArrays, builders = mBuilders]() -> std::shared_ptr<arrow::Table> { + auto status = TableBuilderHelpers::finalize(arrays, *(BuildersTuple<ARGS...>*)builders, std::make_index_sequence<sizeof...(ARGS)>{}); if (status == false) { throw std::runtime_error("Unable to finalize"); } @@ -498,8 +498,8 @@ class TableBuilder // Callback used to fill the builders using FillTuple = std::tuple<typename BuilderMaker<ARGS>::FillType...>; - return [builders = (BuildersTuple<ARGS...>*)mBuilders](unsigned int slot, FillTuple const& t) -> void { - auto status = TableBuilderHelpers::append(*builders, std::index_sequence_for<ARGS...>{}, t); + return [builders = mBuilders](unsigned int slot, FillTuple const& t) -> void { + auto status = TableBuilderHelpers::append(*(BuildersTuple<ARGS...>*)builders, std::index_sequence_for<ARGS...>{}, t); if (status == false) { throw std::runtime_error("Unable to append"); } @@ -534,8 +534,8 @@ class TableBuilder makeFinalizer<ARGS...>(); // Callback used to fill the builders - return [builders = (BuildersTuple<ARGS...>*)mBuilders](unsigned int slot, typename BuilderMaker<ARGS>::FillType... args) -> void { - TableBuilderHelpers::unsafeAppend(*builders, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); + return [builders = mBuilders](unsigned int slot, typename BuilderMaker<ARGS>::FillType... args) -> void { + TableBuilderHelpers::unsafeAppend(*(BuildersTuple<ARGS...>*)builders, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); }; } @@ -548,8 +548,8 @@ class TableBuilder makeBuilders<ARGS...>(columnNames, nRows); makeFinalizer<ARGS...>(); - return [builders = (BuildersTuple<ARGS...>*)mBuilders](unsigned int slot, size_t batchSize, typename BuilderMaker<ARGS>::FillType const*... args) -> void { - TableBuilderHelpers::bulkAppend(*builders, batchSize, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); + return [builders = mBuilders](unsigned int slot, size_t batchSize, typename BuilderMaker<ARGS>::FillType const*... args) -> void { + TableBuilderHelpers::bulkAppend(*(BuildersTuple<ARGS...>*)builders, batchSize, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); }; } From 4d19a867e310170747923c206d13ede3464e11a9 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 24 Sep 2020 13:59:45 +0200 Subject: [PATCH 0735/1751] DPL: introduce InputRecord::countValidInputs() (O2-1720) (#4428) --- Framework/Core/include/Framework/InputRecord.h | 9 +++++++-- Framework/Core/src/InputRecord.cxx | 16 +++++++++++----- Framework/Core/test/test_InputRecord.cxx | 2 ++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Framework/Core/include/Framework/InputRecord.h b/Framework/Core/include/Framework/InputRecord.h index b1fd7d0dc8e9f..0a70f9dc41eaa 100644 --- a/Framework/Core/include/Framework/InputRecord.h +++ b/Framework/Core/include/Framework/InputRecord.h @@ -452,14 +452,19 @@ class InputRecord bool isValid(char const* s) const; bool isValid(int pos) const; - /// Return the total number of inputs in the InputRecord. Notice that these will include + /// @return the total number of inputs in the InputRecord. Notice that these will include /// both valid and invalid inputs (i.e. inputs which have not arrived yet), depending - /// on the ChannelPolicy you have (using the default policy all inputs will be valid). + /// on the CompletionPolicy you have (using the default policy all inputs will be valid). size_t size() const { return mSpan.size(); } + /// @return the total number of valid inputs in the InputRecord. + /// Invalid inputs might happen if the CompletionPolicy allows + /// incomplete records to be consumed or processed. + size_t countValidInputs() const; + template <typename T> using IteratorBase = std::iterator<std::forward_iterator_tag, T>; diff --git a/Framework/Core/src/InputRecord.cxx b/Framework/Core/src/InputRecord.cxx index 70505dca6646d..48ff01ddda2f5 100644 --- a/Framework/Core/src/InputRecord.cxx +++ b/Framework/Core/src/InputRecord.cxx @@ -26,9 +26,7 @@ #pragma GCC diagnostic pop #endif -namespace o2 -{ -namespace framework +namespace o2::framework { InputRecord::InputRecord(std::vector<InputRoute> const& inputsSchema, @@ -80,5 +78,13 @@ bool InputRecord::isValid(int s) const return true; } -} // namespace framework -} // namespace o2 +size_t InputRecord::countValidInputs() const +{ + size_t count = 0; + for (auto&& _ : *this) { + ++count; + } + return count; +} + +} // namespace o2::framework diff --git a/Framework/Core/test/test_InputRecord.cxx b/Framework/Core/test/test_InputRecord.cxx index 0fa93731c0572..539b8063e1199 100644 --- a/Framework/Core/test/test_InputRecord.cxx +++ b/Framework/Core/test/test_InputRecord.cxx @@ -114,6 +114,8 @@ BOOST_AUTO_TEST_CASE(TestInputRecord) BOOST_CHECK_EQUAL(record.isValid("x"), true); BOOST_CHECK_EQUAL(record.isValid("y"), true); BOOST_CHECK_EQUAL(record.isValid("z"), false); + BOOST_CHECK_EQUAL(record.size(), 3); + BOOST_CHECK_EQUAL(record.countValidInputs(), 2); BOOST_CHECK_EQUAL(record.isValid(0), true); BOOST_CHECK_EQUAL(record.isValid(1), true); From e3e527a6bfdd82383bb23cb3e7a2d60988d6b0ea Mon Sep 17 00:00:00 2001 From: anerokhi <44967087+anerokhi@users.noreply.github.com> Date: Thu, 24 Sep 2020 13:23:00 +0300 Subject: [PATCH 0736/1751] Replace boost::bind with lambda Makes the modernize-avoid-bind check happy --- Utilities/aliceHLTwrapper/src/EventSampler.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/aliceHLTwrapper/src/EventSampler.cxx b/Utilities/aliceHLTwrapper/src/EventSampler.cxx index 1c3009401375a..1bc9d827468c1 100644 --- a/Utilities/aliceHLTwrapper/src/EventSampler.cxx +++ b/Utilities/aliceHLTwrapper/src/EventSampler.cxx @@ -115,7 +115,7 @@ void EventSampler::Run() /// inherited from FairMQDevice int iResult=0; - boost::thread samplerThread(boost::bind(&EventSampler::samplerLoop, this)); + boost::thread samplerThread([this] { EventSampler::samplerLoop(); }); unique_ptr<FairMQPoller> poller(fTransportFactory->CreatePoller(fChannels["data-in"])); From cc195872d7b81eddce4f3c548b1551740d9a8b0e Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 24 Sep 2020 14:16:33 +0200 Subject: [PATCH 0737/1751] PrimaryGenerator that can propagate mother/daughter indices (#4361) * PrimaryGenerator that can propagate mother/daughter indices * Pass mother2 as secondparent when pushing track to stack --- .../include/Generators/PrimaryGenerator.h | 14 +++----- Generators/src/Generator.cxx | 34 ++++++++++++------- Generators/src/PrimaryGenerator.cxx | 24 +++++++++---- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/Generators/include/Generators/PrimaryGenerator.h b/Generators/include/Generators/PrimaryGenerator.h index 484db8b0c2a70..9c576118fcbca 100644 --- a/Generators/include/Generators/PrimaryGenerator.h +++ b/Generators/include/Generators/PrimaryGenerator.h @@ -55,18 +55,14 @@ class PrimaryGenerator : public FairPrimaryGenerator **/ Bool_t GenerateEvent(FairGenericStack* pStack) override; - /** Public method AddTrack - Adding a track to the MC stack. To be called within the ReadEvent - methods of the registered generators. - *@param pdgid Particle ID (PDG code) - *@param px,py,pz Momentum coordinates [GeV] - *@param vx,vy,vz Track origin relative to event vertex - **/ + /** ALICE-o2 AddTrack with mother/daughter indices **/ void AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t pz, Double_t vx, Double_t vy, Double_t vz, - Int_t parent = -1, Bool_t wanttracking = true, + Int_t mother1 = -1, Int_t mother2 = -1, + Int_t daughter1 = -1, Int_t daughter2 = -1, + Bool_t wanttracking = true, Double_t e = -9e9, Double_t tof = 0., - Double_t weight = 0., TMCProcess proc = kPPrimary) override; + Double_t weight = 0., TMCProcess proc = kPPrimary); /** initialize the generator **/ Bool_t Init() override; diff --git a/Generators/src/Generator.cxx b/Generators/src/Generator.cxx index 2507773da3566..48333a2f3a056 100644 --- a/Generators/src/Generator.cxx +++ b/Generators/src/Generator.cxx @@ -12,6 +12,7 @@ #include "Generators/Generator.h" #include "Generators/Trigger.h" +#include "Generators/PrimaryGenerator.h" #include "FairPrimaryGenerator.h" #include "FairLogger.h" #include <cmath> @@ -97,20 +98,29 @@ Bool_t { /** add tracks **/ + auto o2primGen = dynamic_cast<PrimaryGenerator*>(primGen); + if (!o2primGen) { + LOG(FATAL) << "PrimaryGenerator is not a o2::eventgen::PrimaryGenerator"; + return kFALSE; + } + /** loop over particles **/ for (const auto& particle : mParticles) { - primGen->AddTrack(particle.GetPdgCode(), - particle.Px() * mMomentumUnit, - particle.Py() * mMomentumUnit, - particle.Pz() * mMomentumUnit, - particle.Vx() * mPositionUnit, - particle.Vy() * mPositionUnit, - particle.Vz() * mPositionUnit, - particle.GetMother(0), - particle.GetStatusCode() == 1, - particle.Energy() * mEnergyUnit, - particle.T() * mTimeUnit, - particle.GetWeight()); + o2primGen->AddTrack(particle.GetPdgCode(), + particle.Px() * mMomentumUnit, + particle.Py() * mMomentumUnit, + particle.Pz() * mMomentumUnit, + particle.Vx() * mPositionUnit, + particle.Vy() * mPositionUnit, + particle.Vz() * mPositionUnit, + particle.GetMother(0), + particle.GetMother(1), + particle.GetDaughter(0), + particle.GetDaughter(1), + particle.GetStatusCode() == 1, + particle.Energy() * mEnergyUnit, + particle.T() * mTimeUnit, + particle.GetWeight()); } /** success **/ diff --git a/Generators/src/PrimaryGenerator.cxx b/Generators/src/PrimaryGenerator.cxx index cb372a102f19d..fed6ffb4c1b92 100644 --- a/Generators/src/PrimaryGenerator.cxx +++ b/Generators/src/PrimaryGenerator.cxx @@ -116,7 +116,9 @@ Bool_t PrimaryGenerator::GenerateEvent(FairGenericStack* pStack) void PrimaryGenerator::AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t pz, Double_t vx, Double_t vy, Double_t vz, - Int_t parent, Bool_t wanttracking, + Int_t mother1, Int_t mother2, + Int_t daughter1, Int_t daughter2, + Bool_t wanttracking, Double_t e, Double_t tof, Double_t weight, TMCProcess proc) { @@ -146,9 +148,19 @@ void PrimaryGenerator::AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t Int_t ntr = 0; // Track number; to be filled by the stack Int_t status = 0; // Generation status - if (parent != -1) { - parent += fMCIndexOffset; - } // correct for tracks which are in list before generator is called + // correct for tracks which are in list before generator is called + if (mother1 != -1) { + mother1 += fMCIndexOffset; + } + if (mother2 != -1) { + mother2 += fMCIndexOffset; + } + if (daughter1 != -1) { + daughter1 += fMCIndexOffset; + } + if (daughter2 != -1) { + daughter2 += fMCIndexOffset; + } /** if it is a K0/antiK0 to be tracked, convert it into K0s/K0L. @@ -170,9 +182,9 @@ void PrimaryGenerator::AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t } /** add track to stack **/ - fStack->PushTrack(doTracking, parent, pdgid, px, py, pz, + fStack->PushTrack(doTracking, mother1, pdgid, px, py, pz, e, vx, vy, vz, tof, polx, poly, polz, proc, ntr, - weight, status, parent); + weight, status, mother2); fNTracks++; } From b44870e4f75af89db6010178a12df80f1dd21fc5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 24 Sep 2020 15:56:36 +0200 Subject: [PATCH 0738/1751] DPL: support multiplexing of dangling outputs (#4426) --- Framework/Core/src/CommonDataProcessors.cxx | 2 +- .../Core/src/ExternalFairMQDeviceProxy.cxx | 26 ++++++++++++++----- .../test_ExternalFairMQDeviceWorkflow.cxx | 4 +-- Framework/Utils/src/dpl-output-proxy.cxx | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index a18d49c07f7eb..7734aacb68334 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -591,7 +591,7 @@ DataProcessorSpec CommonDataProcessors::getGlobalFairMQSink(std::vector<InputSpe // vectored options // use the OutputChannelSpec as a tool to create the default configuration for the out-of-band channel OutputChannelSpec externalChannelSpec; - externalChannelSpec.name = "output_0_0"; + externalChannelSpec.name = "downstream"; externalChannelSpec.type = ChannelType::Push; externalChannelSpec.method = ChannelMethod::Bind; externalChannelSpec.hostname = "localhost"; diff --git a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx index 7320ba3eda9b6..176d50c3b0284 100644 --- a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx +++ b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx @@ -395,6 +395,15 @@ DataProcessorSpec specifyExternalFairMQDeviceProxy(char const* name, return spec; } +namespace +{ +// Decide where to sent the output. Everything to "downstream" for now +std::string decideChannel(InputSpec const&) +{ + return "downstream"; +} +} // namespace + DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, Inputs const& inputSpecs, const char* defaultChannelConfig) @@ -411,8 +420,9 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, auto channelConfigurationChecker = [inputSpecs = std::move(inputSpecs), device]() { LOG(INFO) << "checking channel configuration"; for (auto const& spec : inputSpecs) { - if (device->fChannels.count(spec.binding) == 0) { - throw std::runtime_error("no corresponding output channel found for input '" + spec.binding + "'"); + auto channel = decideChannel(spec); + if (device->fChannels.count(channel) == 0) { + throw std::runtime_error("no corresponding output channel found for input '" + channel + "'"); } } }; @@ -443,12 +453,13 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, } size_t payloadMsgSize = dh->payloadSize; - auto headerMessage = device.NewMessageFor(first.spec->binding, index, headerMsgSize); + auto channel = decideChannel(*first.spec); + auto headerMessage = device.NewMessageFor(channel, index, headerMsgSize); memcpy(headerMessage->GetData(), part.header, headerMsgSize); - auto payloadMessage = device.NewMessageFor(first.spec->binding, index, payloadMsgSize); + auto payloadMessage = device.NewMessageFor(channel, index, payloadMsgSize); memcpy(payloadMessage->GetData(), part.payload, payloadMsgSize); - outputs[first.spec->binding].AddPart(std::move(headerMessage)); - outputs[first.spec->binding].AddPart(std::move(payloadMessage)); + outputs[channel].AddPart(std::move(headerMessage)); + outputs[channel].AddPart(std::move(payloadMessage)); } } for (auto& [channelName, channelParts] : outputs) { @@ -461,7 +472,8 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, }); const char* d = strdup(((std::string(defaultChannelConfig).find("name=") == std::string::npos ? (std::string("name=") + name + ",") : "") + std::string(defaultChannelConfig)).c_str()); spec.options = { - ConfigParamSpec{"channel-config", VariantType::String, d, {"Out-of-band channel config"}}}; + ConfigParamSpec{"channel-config", VariantType::String, d, {"Out-of-band channel config"}}, + }; return spec; } diff --git a/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx b/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx index 71b080c669d75..9adab2a7236a1 100644 --- a/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx +++ b/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx @@ -75,8 +75,8 @@ std::vector<DataProcessorSpec> defineDataProcessing(ConfigContext const& config) // use the OutputChannelSpec as a tool to create the default configuration for the out-of-band channel OutputChannelSpec externalChannelSpec; - // Note: the name has to match the binding of the input spec - externalChannelSpec.name = "external"; + // Note: the name is hardcoded for now + externalChannelSpec.name = "downstream"; externalChannelSpec.type = ChannelType::Push; externalChannelSpec.method = ChannelMethod::Bind; externalChannelSpec.hostname = "localhost"; diff --git a/Framework/Utils/src/dpl-output-proxy.cxx b/Framework/Utils/src/dpl-output-proxy.cxx index 700f81c380efb..d7941cc520778 100644 --- a/Framework/Utils/src/dpl-output-proxy.cxx +++ b/Framework/Utils/src/dpl-output-proxy.cxx @@ -63,7 +63,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) // vectored options // use the OutputChannelSpec as a tool to create the default configuration for the out-of-band channel OutputChannelSpec externalChannelSpec; - externalChannelSpec.name = inputs[0].binding; + externalChannelSpec.name = "downstream"; externalChannelSpec.type = ChannelType::Push; externalChannelSpec.method = ChannelMethod::Bind; externalChannelSpec.hostname = "localhost"; From 7a2b7949c4682d072e26f474176ab25f80abf423 Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Thu, 24 Sep 2020 20:43:41 +0200 Subject: [PATCH 0739/1751] DPL Analysis: Filling histograms in registry with expressions (#4433) --- Analysis/Tutorials/src/histogramRegistry.cxx | 21 ++++++- .../Core/include/Framework/AnalysisHelpers.h | 34 +++++++----- .../include/Framework/HistogramRegistry.h | 52 +++++++++++++++++- .../Core/test/test_HistogramRegistry.cxx | 55 +++++++++++++++++-- 4 files changed, 140 insertions(+), 22 deletions(-) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index f2ee48279b2d0..6a14f665de918 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -41,8 +41,27 @@ struct ATask { } }; +struct BTask { + /// Construct a registry object with direct declaration + HistogramRegistry registry{ + "registry", + true, + { + {"eta", "#eta", {HistogramType::kTH1F, {{102, -2.01, 2.01}}}}, // + {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // + } // + }; + + void process(aod::Tracks const& tracks) + { + registry.fill<aod::track::Eta>("eta", tracks, aod::track::eta > 0.0f); + registry.fill<aod::track::Pt, aod::track::Pt>("ptToPt", tracks, aod::track::pt < 5.0f); + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<ATask>("eta-and-phi-histograms")}; + adaptAnalysisTask<ATask>("eta-and-phi-histograms"), + adaptAnalysisTask<BTask>("filtered-histograms")}; } diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 5907634f8873c..046e0f2ea600f 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -460,6 +460,25 @@ struct Service { } }; +template <typename T> +o2::soa::Filtered<T>* getTableFromFilter(const T& table, const expressions::Filter& filter) +{ + auto schema = table.asArrowTable()->schema(); + expressions::Operations ops = createOperations(filter); + gandiva::NodePtr tree = nullptr; + if (isSchemaCompatible(schema, ops)) { + tree = createExpressionTree(ops, schema); + } else { + throw std::runtime_error("Partition filter does not match declared table type"); + } + + if constexpr (soa::is_soa_filtered_t<std::decay_t<T>>::value) { + return new o2::soa::Filtered<T>{{table}, tree}; + } else { + return new o2::soa::Filtered<T>{{table.asArrowTable()}, tree}; + } +} + template <typename T> struct Partition { Partition(expressions::Node&& filter_) : filter{std::move(filter_)} @@ -468,19 +487,7 @@ struct Partition { void setTable(const T& table) { - auto schema = table.asArrowTable()->schema(); - expressions::Operations ops = createOperations(filter); - if (isSchemaCompatible(schema, ops)) { - mTree = createExpressionTree(ops, schema); - } else { - throw std::runtime_error("Partition filter does not match declared table type"); - } - - if constexpr (soa::is_soa_filtered_t<std::decay_t<T>>::value) { - mFiltered.reset(new o2::soa::Filtered<T>{{table}, mTree}); - } else { - mFiltered.reset(new o2::soa::Filtered<T>{{table.asArrowTable()}, mTree}); - } + mFiltered.reset(getTableFromFilter(table, filter)); } template <typename... Ts> @@ -505,7 +512,6 @@ struct Partition { } expressions::Filter filter; - gandiva::NodePtr mTree = nullptr; std::unique_ptr<o2::soa::Filtered<T>> mFiltered = nullptr; using filtered_iterator = typename o2::soa::Filtered<T>::iterator; diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index fdaf9f982a712..bd7871e22f9e4 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -161,6 +161,34 @@ std::unique_ptr<TH3> createTH3FromSpec(HistogramSpec const& spec) return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data(), spec.config.axes[2].nBins, spec.config.axes[2].bins.data()); } +/// Helper functions to fill histograms with expressions +template <typename C1, typename C2, typename C3, typename T> +void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter) +{ + auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; + for (auto& t : filtered) { + hist->Fill(*(static_cast<C1>(t).getIterator()), *(static_cast<C2>(t).getIterator()), *(static_cast<C3>(t).getIterator())); + } +} + +template <typename C1, typename C2, typename T> +void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter) +{ + auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; + for (auto& t : filtered) { + hist->Fill(*(static_cast<C1>(t).getIterator()), *(static_cast<C2>(t).getIterator())); + } +} + +template <typename C, typename T> +void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter) +{ + auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; + for (auto& t : filtered) { + hist->Fill(*(static_cast<C>(t).getIterator())); + } +} + using HistogramCreationCallback = std::function<std::unique_ptr<TH1>(HistogramSpec const& spec)>; // Wrapper to avoid multiple function definitinions error @@ -278,7 +306,7 @@ class HistogramRegistry return get(name); } - // @return the associated OutputSpec + /// @return the associated OutputSpec OutputSpec const spec() { ConcreteDataMatcher matcher{"HIST", "\0", 0}; @@ -308,6 +336,28 @@ class HistogramRegistry return folder; } + /// fill the histogram with an expression + template <typename C1, typename C2, typename C3, typename T> + void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + { + TH1* hist = get(name).get(); + framework::fill<C1, C2, C3>(hist, table, filter); + } + + template <typename C1, typename C2, typename T> + void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + { + TH1* hist = get(name).get(); + framework::fill<C1, C2>(hist, table, filter); + } + + template <typename C, typename T> + void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + { + TH1* hist = get(name).get(); + framework::fill<C>(hist, table, filter); + } + /// lookup distance counter for benchmarking mutable uint32_t lookup = 0; diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 53d4bb0b59900..0ecb7c367f16f 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -17,6 +17,12 @@ using namespace o2; using namespace o2::framework; +namespace test +{ +DECLARE_SOA_COLUMN_FULL(X, x, float, "x"); +DECLARE_SOA_COLUMN_FULL(Y, y, float, "y"); +} // namespace test + HistogramRegistry foo() { return {"r", true, {{"histo", "histo", {HistogramType::kTH1F, {{100, 0, 1}}}}}}; @@ -25,12 +31,14 @@ HistogramRegistry foo() BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) { /// Construct a registry object with direct declaration - HistogramRegistry registry{"registry", true, { - {"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, // - {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, // - {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, // - {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // - }}; + HistogramRegistry registry{ + "registry", true, { + {"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, // + {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, // + {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, // + {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // + } // + }; /// Get histograms by name BOOST_REQUIRE_EQUAL(registry.get("eta")->GetNbinsX(), 100); @@ -48,3 +56,38 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) auto histo2 = r.get("histo").get(); BOOST_REQUIRE_EQUAL(histo2->GetNbinsX(), 100); } + +BOOST_AUTO_TEST_CASE(HistogramRegistryExpressionFill) +{ + TableBuilder builderA; + auto rowWriterA = builderA.persist<float, float>({"x", "y"}); + rowWriterA(0, 0.0f, -2.0f); + rowWriterA(0, 1.0f, -4.0f); + rowWriterA(0, 2.0f, -1.0f); + rowWriterA(0, 3.0f, -5.0f); + rowWriterA(0, 4.0f, 0.0f); + rowWriterA(0, 5.0f, -9.0f); + rowWriterA(0, 6.0f, -7.0f); + rowWriterA(0, 7.0f, -4.0f); + auto tableA = builderA.finalize(); + BOOST_REQUIRE_EQUAL(tableA->num_rows(), 8); + using TestA = o2::soa::Table<o2::soa::Index<>, test::X, test::Y>; + TestA tests{tableA}; + BOOST_REQUIRE_EQUAL(8, tests.size()); + + /// Construct a registry object with direct declaration + HistogramRegistry registry{ + "registry", true, { + {"x", "test x", {HistogramType::kTH1F, {{100, 0.0f, 10.0f}}}}, // + {"xy", "test xy", {HistogramType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}} // + } // + }; + + /// Fill histogram with expression and table + registry.fill<test::X>("x", tests, test::x > 3.0f); + BOOST_CHECK_EQUAL(registry.get("x")->GetEntries(), 4); + + /// Fill histogram with expression and table + registry.fill<test::X, test::Y>("xy", tests, test::x > 3.0f && test::y > -5.0f); + BOOST_CHECK_EQUAL(registry.get("xy")->GetEntries(), 2); +} From 743c1a4ba0e64b4a81d1b2bdb4f58fde7539cc14 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Fri, 25 Sep 2020 08:46:26 +0200 Subject: [PATCH 0740/1751] TrackSelection: move QA histograms to separate task (#4435) --- Analysis/Tasks/CMakeLists.txt | 5 + Analysis/Tasks/trackqa.cxx | 217 ++++++++++++++++++++++++++++++ Analysis/Tasks/trackselection.cxx | 188 +------------------------- 3 files changed, 224 insertions(+), 186 deletions(-) create mode 100644 Analysis/Tasks/trackqa.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 1b8ac438c0eac..db35ed2080e91 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -19,6 +19,11 @@ o2_add_dpl_workflow(trackselection PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) +o2_add_dpl_workflow(trackqa + SOURCES trackqa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(qatask SOURCES qaTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx new file mode 100644 index 0000000000000..291176a32d94c --- /dev/null +++ b/Analysis/Tasks/trackqa.cxx @@ -0,0 +1,217 @@ +// 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. + +// +// Task producing basic tracking qa histograms +// + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Analysis/MC.h" +#include "Analysis/HistHelpers.h" + +#include <cmath> + +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::experimental::histhelpers; + +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"mc", VariantType::Bool, false, {"Add MC QA histograms."}}}; + std::swap(workflowOptions, options); +} +#include "Framework/runDataProcessing.h" + +//**************************************************************************************** +/** + * QA histograms for track quantities. + */ +//**************************************************************************************** +struct TrackQATask { + + // unique identifiers for each variable + enum Quantities : uint8_t { + // kine + pt = 0, + eta, + phi, + // track + x, + y, + z, + alpha, + signed1Pt, + snp, + tgl, + dcaXY, + dcaZ, + flags, + // its + itsNCls, + itsChi2NCl, + itsHits, + // tpc + tpcNClsFindable, + tpcNClsFound, + tpcNClsShared, + tpcNClsCrossedRows, + tpcCrossedRowsOverFindableCls, + tpcFractionSharedCls, + tpcChi2NCl, + // trd + // tof + // emcal + }; + + OutputObj<HistFolder> kine{HistFolder("Kine"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistFolder> trackpar{HistFolder("TrackPar"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistFolder> its{HistFolder("ITS"), OutputObjHandlingPolicy::QAObject}; + OutputObj<HistFolder> tpc{HistFolder("TPC"), OutputObjHandlingPolicy::QAObject}; + //OutputObj<HistFolder> trd{HistFolder("TRD"), OutputObjHandlingPolicy::QAObject}; + //OutputObj<HistFolder> tof{HistFolder("TOF"), OutputObjHandlingPolicy::QAObject}; + //OutputObj<HistFolder> emcal{HistFolder("EMCAL"), OutputObjHandlingPolicy::QAObject}; + + Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD, 3 = globalTrackswTOF"}; + + Filter trackFilter = aod::track::isGlobalTrack == (uint8_t)1; + /* + //Function float castFLOAT4(uint8) not supported yet + Filter trackFilter = ((0 * aod::track::isGlobalTrack == (float)selectedTracks) || + (1 * aod::track::isGlobalTrack == (float)selectedTracks) || + (2 * aod::track::isGlobalTrackSDD == (float)selectedTracks) || + (3 * aod::track::isGlobalTrackwTOF == (float)selectedTracks)); + */ + + void init(o2::framework::InitContext&) + { + // kine histograms + kine->Add(pt, new TH1D("pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.)); + kine->Add(eta, new TH1D("eta", "#eta;#eta", 101, -1.0, 1.0)); + kine->Add(phi, new TH1D("phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI)); + + // track histograms + trackpar->Add(x, new TH1D("x", "track x position at dca in local coordinate system;x [cm]", 200, -0.4, 0.4)); + trackpar->Add(y, new TH1D("y", "track y position at dca in local coordinate system;y [cm]", 100, -4., 4.)); + trackpar->Add(z, new TH1D("z", "track z position at dca in local coordinate system;z [cm]", 100, -20., 20.)); + trackpar->Add(alpha, new TH1D("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 100, -(M_PI + 0.01), (M_PI + 0.01))); + trackpar->Add(signed1Pt, new TH1D("signed1Pt", "track signed 1/p_{T};q/p_{T}", 200, -8, 8)); + trackpar->Add(snp, new TH1D("snp", "sinus of track momentum azimuthal angle;snp", 100, -1., 1.)); + trackpar->Add(tgl, new TH1D("tgl", "tangent of the track momentum dip angle;tgl;", 1000, -2, 2)); + trackpar->Add(flags, new TH1D("flags", "track flag;flag bit", 64, -0.5, 63.5)); + trackpar->Add(dcaXY, new TH1D("dcaXY", "distance of closest approach in xy plane;dca-xy [cm];", 200, -3., 3.)); + trackpar->Add(dcaZ, new TH1D("dcaZ", "distance of closest approach in z;dca-z [cm];", 200, -3., 3.)); + + // its histograms + its->Add(itsNCls, new TH1D("itsNCls", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5)); + its->Add(itsChi2NCl, new TH1D("itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40)); + its->Add(itsHits, new TH1D("itsHits", "hitmap ITS;layer ITS", 7, -0.5, 6.5)); + + // tpc histograms + tpc->Add(tpcNClsFindable, new TH1D("tpcNClsFindable", "number of findable TPC clusters;# clusters TPC", 165, -0.5, 164.5)); + tpc->Add(tpcNClsFound, new TH1D("tpcNClsFound", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5)); + tpc->Add(tpcNClsShared, new TH1D("tpcNClsShared", "number of shared TPC clusters;;# shared clusters TPC", 165, -0.5, 164.5)); + tpc->Add(tpcNClsCrossedRows, new TH1D("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5)); + tpc->Add(tpcFractionSharedCls, new TH1D("tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.)); + tpc->Add(tpcCrossedRowsOverFindableCls, new TH1D("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 110, 0.0, 1.1)); + tpc->Add(tpcChi2NCl, new TH1D("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10)); + } + + void process(soa::Filtered<soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection>>::iterator const& track) + { + // fill kinematic variables + kine->Fill(pt, track.pt()); + kine->Fill(eta, track.eta()); + kine->Fill(phi, track.phi()); + + // fill track parameters + trackpar->Fill(alpha, track.alpha()); + trackpar->Fill(x, track.x()); + trackpar->Fill(y, track.y()); + trackpar->Fill(z, track.z()); + trackpar->Fill(signed1Pt, track.signed1Pt()); + trackpar->Fill(snp, track.snp()); + trackpar->Fill(tgl, track.tgl()); + for (unsigned int i = 0; i < 64; i++) { + if (track.flags() & (1 << i)) + trackpar->Fill(flags, i); + } + trackpar->Fill(dcaXY, track.dcaXY()); + trackpar->Fill(dcaZ, track.dcaZ()); + + // fill ITS variables + its->Fill(itsNCls, track.itsNCls()); + its->Fill(itsChi2NCl, track.itsChi2NCl()); + for (unsigned int i = 0; i < 7; i++) { + if (track.itsClusterMap() & (1 << i)) + its->Fill(itsHits, i); + } + + // fill TPC variables + tpc->Fill(tpcNClsFindable, track.tpcNClsFindable()); + tpc->Fill(tpcNClsFound, track.tpcNClsFound()); + tpc->Fill(tpcNClsShared, track.tpcNClsShared()); + tpc->Fill(tpcNClsCrossedRows, track.tpcNClsCrossedRows()); + tpc->Fill(tpcCrossedRowsOverFindableCls, track.tpcCrossedRowsOverFindableCls()); + tpc->Fill(tpcFractionSharedCls, track.tpcFractionSharedCls()); + tpc->Fill(tpcChi2NCl, track.tpcChi2NCl()); + + // fill TRD variables + + // fill TOF variables + + // fill EMCAL variables + } +}; + +//**************************************************************************************** +/** + * QA task including MC truth info. + */ +//**************************************************************************************** +struct TrackQATaskMC { + + OutputObj<HistFolder> resolution{HistFolder("Resolution"), OutputObjHandlingPolicy::QAObject}; + + // unique identifiers for each variable + enum QuantitiesMC : uint8_t { + + }; + + void init(o2::framework::InitContext&){ + + }; + + void process(soa::Join<aod::FullTracks, aod::McTrackLabels>::iterator const& track){ + + }; +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + bool isMC = cfgc.options().get<bool>("mc"); + + WorkflowSpec workflow; + workflow.push_back(adaptAnalysisTask<TrackQATask>("track-qa-histograms")); + if (isMC) { + workflow.push_back(adaptAnalysisTask<TrackQATaskMC>("track-qa-histograms-mc")); + } + return workflow; +} diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index 8750936b84fb8..82e15526e4084 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. // -// Task performing basic track selection +// Task performing basic track selection. // #include "Framework/AnalysisDataModel.h" @@ -20,20 +20,12 @@ #include "Analysis/TrackSelection.h" #include "Analysis/TrackSelectionTables.h" +#include "Framework/runDataProcessing.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) -{ - std::vector<ConfigParamSpec> options{ - {"qa-histos", VariantType::Bool, false, {"Generate QA histograms"}}}; - std::swap(workflowOptions, options); -} - -#include "Framework/runDataProcessing.h" - // Default track selection requiring one hit in the SPD TrackSelection getGlobalTrackSelection() { @@ -134,179 +126,6 @@ struct TrackSelectionTask { } }; -//**************************************************************************************** -/** - * Generate QA histograms for track selection. - */ -//**************************************************************************************** -struct TrackQATask { - - Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; - - OutputObj<TH2F> dcaxyVsPt{ - TH2F("track-dcaXYvsPt", "DCA xy vs pT;dca-xy [cm];p_{T};p_{T} [GeV/c]", 200, -3., 3., 100, 0., 50.), - OutputObjHandlingPolicy::QAObject}; - - // track parameters - OutputObj<TH1F> x{ - TH1F("trackpar-x", "track x position at dca in local coordinate system;x [cm]", 200, -0.4, 0.4), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> y{ - TH1F("trackpar-y", "track y position at dca in local coordinate system;y [cm]", 100, -4., 4.), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> z{ - TH1F("trackpar-z", "track z position at dca in local coordinate system;z [cm]", 100, -20., 20.), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> alpha{ - TH1F("trackpar-alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 100, -(M_PI + 0.01), (M_PI + 0.01)), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> signed1Pt{ - TH1F("trackpar-signed1Pt", "track signed 1/p_{T};q/p_{T}", 200, -8, 8), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> snp{ - TH1F("trackpar-snp", "sinus of track momentum azimuthal angle;snp", 100, -1., 1.), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> tgl{ - TH1F("trackpar-tgl", "tangent of the track momentum dip angle;tgl;", 1000, -2, 2), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> dcaxy{ - TH1F("track-dcaXY", "distance of closest approach in xy plane;dca-xy [cm];", 200, -3., 3.), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> dcaz{ - TH1F("track-dcaZ", "distance of closest approach in z;dca-z [cm];", 200, -3., 3.), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> flag{ - TH1F("track-flags", "track flag;flag bit", 64, -0.5, 63.5), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> pt{ - TH1F("track-pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> eta{ - TH1F("track-eta", "#eta;#eta", 101, -1.0, 1.0), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> phi{ - TH1F("track-phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI), - OutputObjHandlingPolicy::QAObject}; - - // ITS related quantities - OutputObj<TH1F> itsFoundClusters{ - TH1F("its-foundClusters", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> itsChi2PerCluster{ - TH1F("its-chi2PerCluster", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> itsHits{ - TH1F("its-hits", "hitmap ITS;layer ITS", 7, -0.5, 6.5), - OutputObjHandlingPolicy::QAObject}; - - // TPC related quantities - OutputObj<TH1F> tpcFindableClusters{ - TH1F("tpc-findableClusters", "number of findable TPC clusters;# clusters TPC", 165, -0.5, 164.5), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> tpcFoundClusters{ - TH1F("tpc-foundClusters", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> tpcSharedClusters{ - TH1F("tpc-sharedClusters", "number of shared TPC clusters;;# shared clusters TPC", 165, -0.5, 164.5), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> tpcFractionSharedClusters{ - TH1F("tpc-fractionSharedClusters", "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> tpcCrossedRows{ - TH1F("tpc-crossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> tpcCrossedRowsOverFindableClusters{ - TH1F("tpc-crossedRowsOverFindableClusters", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 110, 0.0, 1.1), - OutputObjHandlingPolicy::QAObject}; - - OutputObj<TH1F> tpcChi2PerCluster{ - TH1F("tpc-chi2PerCluster", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10), - OutputObjHandlingPolicy::QAObject}; - - // collision related quantities - OutputObj<TH2F> collisionPos{ - TH2F("collision-xy", "Position of collision;x [cm];y [cm]", 100, -0.5, 0.5, 100, -0.5, 0.5), - OutputObjHandlingPolicy::QAObject}; - - void init(o2::framework::InitContext&) {} - - void process(aod::Collision const& collision, soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection> const& tracks) - { - - collisionPos->Fill(collision.posX(), collision.posY()); - - for (auto& track : tracks) { - - if (selectedTracks == 1 && !track.isGlobalTrack()) - continue; // FIXME: this should be replaced by framework filter - else if (selectedTracks == 2 && !track.isGlobalTrackSDD()) - continue; - - // TPC - tpcFindableClusters->Fill(track.tpcNClsFindable()); - tpcFoundClusters->Fill(track.tpcNClsFound()); - tpcSharedClusters->Fill(track.tpcNClsShared()); - tpcCrossedRows->Fill(track.tpcNClsCrossedRows()); - - tpcCrossedRowsOverFindableClusters->Fill( - track.tpcCrossedRowsOverFindableCls()); - tpcFractionSharedClusters->Fill(track.tpcFractionSharedCls()); - tpcChi2PerCluster->Fill( - track.tpcChi2NCl()); - - // ITS - itsFoundClusters->Fill(track.itsNCls()); - itsChi2PerCluster->Fill(track.itsChi2NCl()); - for (unsigned int i = 0; i < 7; i++) { - if (track.itsClusterMap() & (1 << i)) - itsHits->Fill(i); - } - - // Tracks - alpha->Fill(track.alpha()); - x->Fill(track.x()); - y->Fill(track.y()); - z->Fill(track.z()); - - dcaxy->Fill(track.dcaXY()); - dcaz->Fill(track.dcaZ()); - dcaxyVsPt->Fill(track.dcaXY(), track.pt()); - - signed1Pt->Fill(track.signed1Pt()); - snp->Fill(track.snp()); - tgl->Fill(track.tgl()); - - for (unsigned int i = 0; i < 64; i++) { - if (track.flags() & (1 << i)) - flag->Fill(i); - } - - pt->Fill(track.pt()); - eta->Fill(track.eta()); - phi->Fill(track.phi()); - } - } -}; - //**************************************************************************************** /** * Workflow definition. @@ -314,11 +133,8 @@ struct TrackQATask { //**************************************************************************************** WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - bool createQAplots = cfgc.options().get<bool>("qa-histos"); WorkflowSpec workflow{ adaptAnalysisTask<TrackExtensionTask>("track-extension"), adaptAnalysisTask<TrackSelectionTask>("track-selection")}; - if (createQAplots) - workflow.push_back(adaptAnalysisTask<TrackQATask>("track-qa-histograms")); return workflow; } From cb3e9cb6a59d728e937b55c9a6389572b72d6ea9 Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Fri, 25 Sep 2020 03:47:01 -0300 Subject: [PATCH 0741/1751] V0 finder now with better filtering, preparing test (#4436) --- .../include/Analysis/StrangenessTables.h | 6 ++- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 49 ++++++------------- 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/StrangenessTables.h b/Analysis/DataModel/include/Analysis/StrangenessTables.h index eb7997bed47a5..77fb0b413f46d 100644 --- a/Analysis/DataModel/include/Analysis/StrangenessTables.h +++ b/Analysis/DataModel/include/Analysis/StrangenessTables.h @@ -91,9 +91,11 @@ using V0DataFull = V0DataExt; namespace v0finderdata { +DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, FullTracks, "fPosTrackID"); +DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, FullTracks, "fNegTrackID"); DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} -DECLARE_SOA_TABLE(V0FinderData, "AOD", "V0FINDERDATA", o2::soa::Index<>, v0finderdata::CollisionId); +} // namespace v0finderdata +DECLARE_SOA_TABLE(V0FinderData, "AOD", "V0FINDERDATA", o2::soa::Index<>, v0finderdata::PosTrackId, v0finderdata::NegTrackId, v0finderdata::CollisionId); namespace cascdata { diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index 387f541695434..df5ed68c14f95 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -50,14 +50,6 @@ struct lambdakzerofinder { OutputObj<TH1F> hCandPerEvent{TH1F("hCandPerEvent", "", 1000, 0, 1000)}; - OutputObj<TH1F> hV0PosCrossedRows{TH1F("hV0PosCrossedRows", "", 160, 0, 160)}; - OutputObj<TH1F> hV0NegCrossedRows{TH1F("hV0NegCrossedRows", "", 160, 0, 160)}; - OutputObj<TH1F> hV0CosPA{TH1F("hV0CosPA", "", 2000, 0.9, 1)}; - OutputObj<TH1F> hV0Radius{TH1F("hV0Radius", "", 2000, 0, 200)}; - OutputObj<TH1F> hV0DCADaughters{TH1F("hV0DCADaughters", "", 200, 0, 2)}; - OutputObj<TH1F> hV0PosDCAxy{TH1F("hV0PosDCAxy", "", 200, 0, 5)}; - OutputObj<TH1F> hV0NegDCAxy{TH1F("hV0NegDCAxy", "", 200, 0, 5)}; - //Configurables Configurable<double> d_bz{"d_bz", +5.0, "bz field"}; Configurable<double> d_UseAbsDCA{"d_UseAbsDCA", kTRUE, "Use Abs DCAs"}; @@ -72,8 +64,8 @@ struct lambdakzerofinder { //using myTracks = soa::Filtered<aod::Tracks>; //using myTracks = soa::Filtered<aod::fullTracks>; - Partition<aod::FullTracks> goodPosTracks = aod::track::signed1Pt > 0.0f; - Partition<aod::FullTracks> goodNegTracks = aod::track::signed1Pt < 0.0f; + Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodPosTracks = aod::track::signed1Pt > 0.0f && aod::track::dcaXY > dcapostopv; + Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodNegTracks = aod::track::signed1Pt < 0.0f && aod::track::dcaXY < -dcanegtopv; /// Extracts dca in the XY plane /// \return dcaXY @@ -90,7 +82,7 @@ struct lambdakzerofinder { } void process(aod::Collision const& collision, - aod::FullTracks const& tracks) + soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { //Define o2 fitter, 2-prong o2::vertexing::DCAFitterN<2> fitter; @@ -107,18 +99,12 @@ struct lambdakzerofinder { std::array<float, 3> pVtx = {collision.posX(), collision.posY(), collision.posZ()}; - for (auto& t0 : goodPosTracks) { - auto thisdcapostopv = getdcaXY(t0, pVtx); - if (thisdcapostopv < dcapostopv) - continue; + for (auto& t0 : goodPosTracks) { //FIXME: turn into combination(...) if (t0.tpcNClsCrossedRows() < 70) - continue; + continue; //FIXME: turn into extra filter for (auto& t1 : goodNegTracks) { - auto thisdcanegtopv = getdcaXY(t1, pVtx); - if (thisdcanegtopv < dcanegtopv) - continue; if (t1.tpcNClsCrossedRows() < 70) - continue; + continue; //FIXME: turn into extra filter auto Track1 = getTrackParCov(t0); auto Track2 = getTrackParCov(t1); @@ -152,22 +138,13 @@ struct lambdakzerofinder { if (thisv0cospa < v0cospa) continue; - hV0PosCrossedRows->Fill(t0.tpcNClsCrossedRows()); - hV0NegCrossedRows->Fill(t1.tpcNClsCrossedRows()); - hV0PosDCAxy->Fill(thisdcapostopv); - hV0NegDCAxy->Fill(thisdcanegtopv); - hV0CosPA->Fill(thisv0cospa); - hV0Radius->Fill(thisv0radius); - hV0DCADaughters->Fill(thisdcav0dau); - lNCand++; - v0finderdata(t0.collisionId()); + v0finderdata(t0.globalIndex(), t1.globalIndex(), t0.collisionId()); v0data(pos[0], pos[1], pos[2], pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], fitter.getChi2AtPCACandidate(), - getdcaXY(t0, pVtx), - getdcaXY(t1, pVtx)); + t0.dcaXY(), -t1.dcaXY()); } } hCandPerEvent->Fill(lNCand); @@ -195,11 +172,13 @@ struct lambdakzerofinderQA { OutputObj<TH3F> h3dMassLambda{TH3F("h3dMassLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; OutputObj<TH3F> h3dMassAntiLambda{TH3F("h3dMassAntiLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; + OutputObj<TH1F> hTest{TH1F("hTest", "", 1000, 0, 1000)}; + Filter preFilterV0 = aod::v0data::dcapostopv > dcapostopv&& aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; ///Connect to V0FinderData: newly indexed, note: V0DataExt table incompatible with standard V0 table! - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, aod::FullTracks const& tracks, soa::Filtered<soa::Join<aod::V0FinderData, aod::V0DataExt>> const& fullV0s) { if (!collision.alias()[kINT7]) @@ -216,6 +195,8 @@ struct lambdakzerofinderQA { hDCANegToPV->Fill(v0.dcanegtopv()); hDCAV0Dau->Fill(v0.dcaV0daughters()); + hTest->Fill(v0.posTrack().pt()); + if (TMath::Abs(v0.yLambda()) < 0.5) { h3dMassLambda->Fill(collision.centV0M(), v0.pt(), v0.mLambda()); h3dMassAntiLambda->Fill(collision.centV0M(), v0.pt(), v0.mAntiLambda()); @@ -239,6 +220,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<lambdakzerofinder>("lf-lambdakzerofinder"), - adaptAnalysisTask<lambdakzerofinderQA>("lf-lambdakzerofinderQA"), - adaptAnalysisTask<lambdakzeroinitializer>("lf-lambdakzeroinitializer")}; + adaptAnalysisTask<lambdakzeroinitializer>("lf-lambdakzeroinitializer"), + adaptAnalysisTask<lambdakzerofinderQA>("lf-lambdakzerofinderQA")}; } From 239c57673522ee38a64d25a504f260e505273545 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 24 Sep 2020 15:51:48 +0200 Subject: [PATCH 0742/1751] Rename configurable param Pythia8 -> GeneratorPythia8 --- Generators/include/Generators/GeneratorPythia8Param.h | 2 +- Generators/share/egconfig/pythia8_userhooks_charm.C | 2 +- doc/DetectorSimulation.md | 2 +- .../HF_Embedding_Pythia8/o2sim_configuration_sgn.ini | 2 +- run/SimExamples/HF_Embedding_Pythia8/run.sh | 6 +++--- .../Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro | 2 +- run/SimExamples/Jet_Embedding_Pythia8/run.sh | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Generators/include/Generators/GeneratorPythia8Param.h b/Generators/include/Generators/GeneratorPythia8Param.h index e4c3b77a163ca..e9133da76e6f0 100644 --- a/Generators/include/Generators/GeneratorPythia8Param.h +++ b/Generators/include/Generators/GeneratorPythia8Param.h @@ -32,7 +32,7 @@ struct GeneratorPythia8Param : public o2::conf::ConfigurableParamHelper<Generato std::string config = ""; std::string hooksFileName = ""; std::string hooksFuncName = ""; - O2ParamDef(GeneratorPythia8Param, "Pythia8"); + O2ParamDef(GeneratorPythia8Param, "GeneratorPythia8"); }; } // end namespace eventgen diff --git a/Generators/share/egconfig/pythia8_userhooks_charm.C b/Generators/share/egconfig/pythia8_userhooks_charm.C index de3ef244cce5b..19004c3f4a9f2 100644 --- a/Generators/share/egconfig/pythia8_userhooks_charm.C +++ b/Generators/share/egconfig/pythia8_userhooks_charm.C @@ -1,6 +1,6 @@ // Pythia8 UserHooks // -// usage: o2sim -g pythia8 --configKeyValues "Pythia8.hooksFileName=pythia8_userhooks_charm.C" +// usage: o2sim -g pythia8 --configKeyValues "GeneratorPythia8.hooksFileName=pythia8_userhooks_charm.C" // /// \author R+Preghenella - February 2020 diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index 08946ecf0aae8..de89e32b973e4 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -258,7 +258,7 @@ This functionality might be of use for users who want to be able to steer the ev An example of a configuration macro is this one ``` -// usage: o2sim -g pythia8 --configKeyValues "Pythia8.hooksFileName=pythia8_userhooks_charm.C" +// usage: o2sim -g pythia8 --configKeyValues "GeneratorPythia8.hooksFileName=pythia8_userhooks_charm.C" #include "Generators/Trigger.h" #include "Pythia8/Pythia.h" diff --git a/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini b/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini index e4c4d58ed8659..d0f74533c1386 100644 --- a/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini +++ b/run/SimExamples/HF_Embedding_Pythia8/o2sim_configuration_sgn.ini @@ -1,4 +1,4 @@ -[Pythia8] +[GeneratorPythia8] config = pythia8.cfg hooksFileName = pythia8_userhooks_ccbar.macro hooksFuncName = pythia8_userhooks_ccbar(1.5) diff --git a/run/SimExamples/HF_Embedding_Pythia8/run.sh b/run/SimExamples/HF_Embedding_Pythia8/run.sh index 11d0332775ec4..1ff92a4e5d08c 100755 --- a/run/SimExamples/HF_Embedding_Pythia8/run.sh +++ b/run/SimExamples/HF_Embedding_Pythia8/run.sh @@ -13,12 +13,12 @@ # `GeneratorExternal.fileName=GeneratorHF.macro` by running the code defined in the function `GeneratorExternal.funcName="GeneratorHF()"`. # Special configuration parameters are loaded from the INI file `--configFile o2sim_configuration_sgn.ini`. # -# Pythia8.config defines the Pythia8 configuration file name. +# GeneratorPythia8.config defines the Pythia8 configuration file name. # # We configured to bias towards c-cbar processes where we can select them baed on pt-hat bins. # -# Pythia8.hooksFileName defines the file name where to load the custom Pythia8 hooks -# Pythia8.hooskFuncName defines the function call to be run to retrieve the custom Pythia8 hools. +# GeneratorPythia8.hooksFileName defines the file name where to load the custom Pythia8 hooks +# GeneratorPythia8.hooskFuncName defines the function call to be run to retrieve the custom Pythia8 hools. # # Hooks are used in this example to speedup the event generation. Event generation is paused at parton level. # We check if there are the partons of our interest, if not we veto the event. This saves time because we diff --git a/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro b/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro index 9cd5249f89f98..9986f65e3e5df 100644 --- a/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro +++ b/run/SimExamples/Jet_Embedding_Pythia8/pythia8_userhooks_jets.macro @@ -1,6 +1,6 @@ // Pythia8 UserHooks // -// usage: o2sim -g pythia8 --configKeyValues "Pythia8.hooksFileName=pythia8_userhooks_jets.C" +// usage: o2sim -g pythia8 --configKeyValues "GeneratorPythia8.hooksFileName=pythia8_userhooks_jets.C" // /// \author R+Preghenella - April 2020 diff --git a/run/SimExamples/Jet_Embedding_Pythia8/run.sh b/run/SimExamples/Jet_Embedding_Pythia8/run.sh index e27ccf6e88a22..e063ee2a1b872 100755 --- a/run/SimExamples/Jet_Embedding_Pythia8/run.sh +++ b/run/SimExamples/Jet_Embedding_Pythia8/run.sh @@ -19,7 +19,7 @@ o2-sim -j 20 -n ${NBGR} -g pythia8hi -m PIPE ITS TPC -o bkg --configKeyValues \ # produce hard jets using a pythia8 configuration given in a file 'pythia8_hard.cfg'; event selection is done by a user hook specified # in file 'pythia8_userhooks_jets.macro' and using same vertex setting as background events (via --embedInto) NSGN=10 -o2-sim -j 20 -n ${NSGN} -g pythia8 -m PIPE ITS TPC --configKeyValues "Pythia8.config=pythia8_hard.cfg;Pythia8.hooksFileName=pythia8_userhooks_jets.macro" --embedIntoFile bkg_Kine.root -o sgn > logsgn 2>&1 +o2-sim -j 20 -n ${NSGN} -g pythia8 -m PIPE ITS TPC --configKeyValues "GeneratorPythia8.config=pythia8_hard.cfg;GeneratorPythia8.hooksFileName=pythia8_userhooks_jets.macro" --embedIntoFile bkg_Kine.root -o sgn > logsgn 2>&1 # PART c) # digitization with summation of signal on top of background events From 5e0e726097c668871fd2c555a7e65b792f2c6c3d Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 24 Sep 2020 10:36:06 +0200 Subject: [PATCH 0743/1751] TRD: use new zero copy IO of RootTreeWriter Also remove manipulation of branch lists, somehow the written TTrees segfault when read back. So for the moment we have to live with ughly "tmp" branches. --- .../TRD/workflow/src/TRDDigitWriterSpec.cxx | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx index 829e587cac140..c53c7dcbb4eaa 100644 --- a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx @@ -53,29 +53,23 @@ o2::framework::DataProcessorSpec getTRDDigitWriterSpec(bool mctruth) // custom handler for labels: // essentially transform the input container (as registered in the branch definition) to the special output format for labels - auto customlabelhandler = [](TBranch& branch, o2::dataformats::ConstMCTruthContainer<o2::trd::MCLabel> const& labeldata, DataRef const& ref) { + auto customlabelhandler = [](TBranch& branch, std::vector<char> const& labeldata, DataRef const& ref) { // make the actual output object by adopting/casting the buffer // into a split format o2::dataformats::IOMCTruthContainerView outputcontainer(labeldata); auto tree = branch.GetTree(); - auto name = branch.GetName(); - // we need to make something ugly since the original branch is already registered with a different type - // (communicated by Philippe Canal / ROOT team) - branch.DeleteBaskets("all"); - // remove the existing branch and make a new one with the correct type - tree->GetListOfBranches()->Remove(&branch); - auto br = tree->Branch(name, &outputcontainer); + auto br = tree->Branch("TRDMCLabels", &outputcontainer); br->Fill(); br->ResetAddress(); }; - auto labelsdef = BranchDefinition<o2::dataformats::ConstMCTruthContainer<o2::trd::MCLabel>>{InputSpec{"labelinput", "TRD", "LABELS"}, - "TRDMCLabels", "labels-branch-name", - // this branch definition is disabled if MC labels are not processed - (mctruth ? 1 : 0), - customlabelhandler, - getIndex, - getName}; + auto labelsdef = BranchDefinition<std::vector<char>>{InputSpec{"labelinput", "TRD", "LABELS"}, + "TRDMCLabels_TMP", "labels-branch-name", + // this branch definition is disabled if MC labels are not processed + (mctruth ? 1 : 0), + customlabelhandler, + getIndex, + getName}; return MakeRootTreeWriterSpec("TRDDigitWriter", "trddigits.root", From f3908597ea5ffdd3faa24941c6e8712a07cd8cd6 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 24 Sep 2020 10:37:21 +0200 Subject: [PATCH 0744/1751] New digit MC label handling in ITSMFT digit + reco --- .../ITSMFT/ITS/workflow/src/ClustererSpec.cxx | 9 +- .../ITS/workflow/src/DigitReaderSpec.cxx | 12 +- .../ITSMFT/MFT/workflow/src/ClustererSpec.cxx | 8 +- .../include/ITSMFTReconstruction/Clusterer.h | 11 +- .../ITSMFTReconstruction/DigitPixelReader.h | 10 +- .../ITSMFTReconstruction/PixelReader.h | 4 +- .../common/reconstruction/src/Clusterer.cxx | 8 +- .../common/workflow/src/DigitWriterSpec.cxx | 125 +++++++++++++++++- .../src/ITSMFTDigitizerSpec.cxx | 8 +- macro/readITSDigits.C | 24 +++- 10 files changed, 186 insertions(+), 33 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx index c5af41e8a4575..44eb438772380 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx @@ -20,6 +20,7 @@ #include "ITSMFTReconstruction/ClustererParam.h" #include "DataFormatsITSMFT/CompCluster.h" #include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsParameters/GRPObject.h" @@ -79,22 +80,24 @@ void ClustererDPL::run(ProcessingContext& pc) auto digits = pc.inputs().get<gsl::span<o2::itsmft::Digit>>("digits"); auto rofs = pc.inputs().get<gsl::span<o2::itsmft::ROFRecord>>("ROframes"); - std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>> labels; gsl::span<const o2::itsmft::MC2ROFRecord> mc2rofs; + gsl::span<const char> labelbuffer; if (mUseMC) { - labels = pc.inputs().get<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("labels"); + labelbuffer = pc.inputs().get<gsl::span<char>>("labels"); mc2rofs = pc.inputs().get<gsl::span<o2::itsmft::MC2ROFRecord>>("MC2ROframes"); } + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> labels(labelbuffer); LOG(INFO) << "ITSClusterer pulled " << digits.size() << " digits, in " << rofs.size() << " RO frames"; + LOG(INFO) << "ITSClusterer pulled " << labels.getNElements() << " labels "; o2::itsmft::DigitPixelReader reader; reader.setDigits(digits); reader.setROFRecords(rofs); if (mUseMC) { reader.setMC2ROFRecords(mc2rofs); - reader.setDigitsMCTruth(labels.get()); + reader.setDigitsMCTruth(labels.getIndexedSize() > 0 ? &labels : nullptr); } reader.init(); auto orig = o2::header::gDataOriginITS; diff --git a/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx index befc48e62071a..6b916a7c994a5 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx @@ -11,6 +11,7 @@ /// @file DigitReaderSpec.cxx #include <vector> +#include <SimulationDataFormat/ConstMCTruthContainer.h> #include "TTree.h" @@ -20,8 +21,10 @@ #include "ITSWorkflow/DigitReaderSpec.h" #include "DataFormatsITSMFT/Digit.h" #include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include "DataFormatsITSMFT/ROFRecord.h" +#include <cmath> using namespace o2::framework; using namespace o2::itsmft; @@ -59,7 +62,8 @@ void DigitReader::run(ProcessingContext& pc) std::vector<ROFRecord> rofs, *profs = &rofs; treeDig->SetBranchAddress("ITSDigitROF", &profs); - o2::dataformats::MCTruthContainer<o2::MCCompLabel> labels, *plabels = &labels; + o2::dataformats::IOMCTruthContainerView* plabels = nullptr; + std::vector<MC2ROFRecord> mc2rofs, *pmc2rofs = &mc2rofs; if (mUseMC) { treeDig->SetBranchAddress("ITSDigitMCTruth", &plabels); @@ -73,7 +77,9 @@ void DigitReader::run(ProcessingContext& pc) pc.outputs().snapshot(Output{"ITS", "DIGITS", 0, Lifetime::Timeframe}, digits); pc.outputs().snapshot(Output{"ITS", "DIGITSROF", 0, Lifetime::Timeframe}, *profs); if (mUseMC) { - pc.outputs().snapshot(Output{"ITS", "DIGITSMCTR", 0, Lifetime::Timeframe}, labels); + auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{"ITS", "DIGITSMCTR", 0, Lifetime::Timeframe}); + plabels->copyandflatten(sharedlabels); + delete plabels; pc.outputs().snapshot(Output{"ITS", "DIGITSMC2ROF", 0, Lifetime::Timeframe}, *pmc2rofs); } } else { diff --git a/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx index 26e90db4cd58e..8b305e9679152 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx @@ -20,6 +20,7 @@ #include "DataFormatsITSMFT/CompCluster.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsParameters/GRPObject.h" #include "ITSMFTReconstruction/DigitPixelReader.h" @@ -85,12 +86,13 @@ void ClustererDPL::run(ProcessingContext& pc) auto digits = pc.inputs().get<gsl::span<o2::itsmft::Digit>>("digits"); auto rofs = pc.inputs().get<gsl::span<o2::itsmft::ROFRecord>>("ROframes"); - std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>> labels; gsl::span<const o2::itsmft::MC2ROFRecord> mc2rofs; + gsl::span<const char> labelbuffer; if (mUseMC) { - labels = pc.inputs().get<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("labels"); + labelbuffer = pc.inputs().get<gsl::span<char>>("labels"); mc2rofs = pc.inputs().get<gsl::span<o2::itsmft::MC2ROFRecord>>("MC2ROframes"); } + const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> labels(labelbuffer); LOG(INFO) << "MFTClusterer pulled " << digits.size() << " digits, in " << rofs.size() << " RO frames"; @@ -100,7 +102,7 @@ void ClustererDPL::run(ProcessingContext& pc) reader.setROFRecords(rofs); if (mUseMC) { reader.setMC2ROFRecords(mc2rofs); - reader.setDigitsMCTruth(labels.get()); + reader.setDigitsMCTruth(labels.getIndexedSize() > 0 ? &labels : nullptr); } reader.init(); auto orig = o2::header::gDataOriginMFT; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h index c94fb25d8705b..c2c9a3333cb07 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h @@ -42,6 +42,8 @@ class MCCompLabel; namespace dataformats { template <typename T> +class ConstMCTruthContainerView; +template <typename T> class MCTruthContainer; } @@ -63,6 +65,7 @@ class Clusterer using CompClusterExt = o2::itsmft::CompClusterExt; using Label = o2::MCCompLabel; using MCTruth = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using ConstMCTruth = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; public: static constexpr int MaxLabels = 10; @@ -134,15 +137,15 @@ class Clusterer CompClusCont* compClusPtr, PatternCont* patternsPtr, MCTruth* labelsClusPtr, int nlab, bool isHuge = false); - void fetchMCLabels(int digID, const MCTruth* labelsDig, int& nfilled); + void fetchMCLabels(int digID, const ConstMCTruth* labelsDig, int& nfilled); void initChip(const ChipPixelData* curChipData, uint32_t first); void updateChip(const ChipPixelData* curChipData, uint32_t ip); void finishChip(ChipPixelData* curChipData, CompClusCont* compClus, PatternCont* patterns, - const MCTruth* labelsDig, MCTruth* labelsClus); + const ConstMCTruth* labelsDig, MCTruth* labelsClus); void finishChipSingleHitFast(uint32_t hit, ChipPixelData* curChipData, CompClusCont* compClusPtr, - PatternCont* patternsPtr, const MCTruth* labelsDigPtr, MCTruth* labelsClusPTr); + PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPTr); void process(uint16_t chip, uint16_t nChips, CompClusCont* compClusPtr, PatternCont* patternsPtr, - const MCTruth* labelsDigPtr, MCTruth* labelsClPtr, const ROFRecord& rofPtr); + const ConstMCTruth* labelsDigPtr, MCTruth* labelsClPtr, const ROFRecord& rofPtr); ClustererThread(Clusterer* par = nullptr) : parent(par), curr(column2 + 1), prev(column1 + 1) { diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DigitPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DigitPixelReader.h index 2b45facce2e53..165d149810ed3 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DigitPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DigitPixelReader.h @@ -19,7 +19,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITSMFT/Digit.h" #include "DetectorsCommonDataFormats/DetID.h" -#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <TTree.h> #include <vector> @@ -59,12 +59,12 @@ class DigitPixelReader : public PixelReader mIdDig = 0; } - void setDigitsMCTruth(const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* m) + void setDigitsMCTruth(const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* m) { mDigitsMCTruth = m; } - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* getDigitsMCTruth() const override + const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* getDigitsMCTruth() const override { return mDigitsMCTruth; } @@ -99,13 +99,13 @@ class DigitPixelReader : public PixelReader std::vector<o2::itsmft::Digit>* mDigitsSelf = nullptr; std::vector<o2::itsmft::ROFRecord>* mROFRecVecSelf = nullptr; std::vector<o2::itsmft::MC2ROFRecord>* mMC2ROFRecVecSelf = nullptr; - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mDigitsMCTruthSelf = nullptr; + const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* mDigitsMCTruthSelf = nullptr; gsl::span<const o2::itsmft::Digit> mDigits; gsl::span<const o2::itsmft::ROFRecord> mROFRecVec; gsl::span<const o2::itsmft::MC2ROFRecord> mMC2ROFRecVec; - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mDigitsMCTruth = nullptr; + const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* mDigitsMCTruth = nullptr; Int_t mIdDig = 0; // Digits slot read within ROF Int_t mIdROF = 0; // ROFRecord being red diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h index 7017cc55e2e7d..6a34bd5d1b08a 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h @@ -17,7 +17,7 @@ #include <Rtypes.h> #include "ITSMFTReconstruction/PixelData.h" #include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "CommonDataFormat/InteractionRecord.h" #include <vector> @@ -45,7 +45,7 @@ class PixelReader // prepare data of next trigger, return number of non-empty links or chips virtual int decodeNextTrigger() = 0; - virtual const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* getDigitsMCTruth() const + virtual const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* getDigitsMCTruth() const { return nullptr; } diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index ecb21366e0822..3def2b727f23a 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -156,7 +156,7 @@ void Clusterer::process(int nThreads, PixelReader& reader, CompClusCont* compClu //__________________________________________________ void Clusterer::ClustererThread::process(uint16_t chip, uint16_t nChips, CompClusCont* compClusPtr, PatternCont* patternsPtr, - const MCTruth* labelsDigPtr, MCTruth* labelsClPtr, const ROFRecord& rofPtr) + const ConstMCTruth* labelsDigPtr, MCTruth* labelsClPtr, const ROFRecord& rofPtr) { if (stats.empty() || stats.back().firstChip + stats.back().nChips < chip) { // there is a jump, register new block stats.emplace_back(ThreadStat{chip, 0, uint32_t(compClusPtr->size()), patternsPtr ? uint32_t(patternsPtr->size()) : 0, 0, 0}); @@ -199,7 +199,7 @@ void Clusterer::ClustererThread::process(uint16_t chip, uint16_t nChips, CompClu //__________________________________________________ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClusCont* compClusPtr, - PatternCont* patternsPtr, const MCTruth* labelsDigPtr, MCTruth* labelsClusPtr) + PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPtr) { auto clustersCount = compClusPtr->size(); const auto& pixData = curChipData->getData(); @@ -325,7 +325,7 @@ void Clusterer::ClustererThread::streamCluster(const std::vector<PixelData>& pix //__________________________________________________ void Clusterer::ClustererThread::finishChipSingleHitFast(uint32_t hit, ChipPixelData* curChipData, CompClusCont* compClusPtr, - PatternCont* patternsPtr, const MCTruth* labelsDigPtr, MCTruth* labelsClusPtr) + PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPtr) { auto clustersCount = compClusPtr->size(); auto pix = curChipData->getData()[hit]; @@ -435,7 +435,7 @@ void Clusterer::ClustererThread::updateChip(const ChipPixelData* curChipData, ui } //__________________________________________________ -void Clusterer::ClustererThread::fetchMCLabels(int digID, const MCTruth* labelsDig, int& nfilled) +void Clusterer::ClustererThread::fetchMCLabels(int digID, const ConstMCTruth* labelsDig, int& nfilled) { // transfer MC labels to cluster if (nfilled >= MaxLabels) { diff --git a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx index e8bc9f3f70e31..49d36c33dd3ea 100644 --- a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx @@ -16,11 +16,16 @@ #include "Headers/DataHeader.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DataFormatsITSMFT/ROFRecord.h" -#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include "SimulationDataFormat/MCCompLabel.h" #include <vector> #include <string> #include <algorithm> +#ifdef NDEBUG +#undef NDEBUG +#include <cassert> +#endif using namespace o2::framework; using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; @@ -32,7 +37,33 @@ namespace itsmft template <typename T> using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; -using MCCont = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; +using MCCont = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; + +// #define CUSTOM 1 +// make a std::vec use a gsl::span as internal buffer without copy +template <typename T> +void adopt(gsl::span<const T> const& data, std::vector<T>& v) +{ + static_assert(sizeof(v) == 24); + if (data.size() == 0) { + return; + } + // we assume a standard layout of begin, end, end_capacity and overwrite the internal members of the vector + struct Impl { + const T* start; + const T* end; + const T* cap; + }; + + Impl impl; + impl.start = &(data[0]); + impl.end = &(data[data.size() - 1]) + 1; // end pointer (beyond last element) + impl.cap = impl.end; + std::memcpy(&v, &impl, sizeof(Impl)); + assert(data.size() == v.size()); + assert(v.capacity() == v.size()); + assert((void*)&data[0] == (void*)&v[0]); +} /// create the processor spec /// describing a processor receiving digits for ITS/MFT and writing them to file @@ -41,15 +72,98 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOri std::string detStr = o2::detectors::DetID::getName(detId); std::string detStrL = detStr; std::transform(detStrL.begin(), detStrL.end(), detStrL.begin(), ::tolower); +#ifdef CUSTOM + std::vector<o2::framework::InputSpec> inputs; + if (mctruth) { + inputs.emplace_back(InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}); + inputs.emplace_back(InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}); + } + inputs.emplace_back(InputSpec{"digits", detOrig, "DIGITS", 0}); + inputs.emplace_back(InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}); + + return {(detStr + "DigitWriter").c_str(), + inputs, + {}, + AlgorithmSpec{ + [detStrL, detStr, mctruth](ProcessingContext& ctx) { + static bool mFinished = false; + if (mFinished) { + return; + } + + TFile f((detStrL + "digits.root").c_str(), "RECREATE"); + TTree t("o2sim", "o2sim"); + // define data + auto digits = new std::vector<itsmft::Digit>; // needs to be a pointer since the message memory is managed by DPL and we have to avoid double deletes + auto rof = new std::vector<itsmft::ROFRecord>; + auto mc2rofrecords = new std::vector<itsmft::MC2ROFRecord>; + o2::dataformats::IOMCTruthContainerView labelview; + + auto fillBranch = [](TBranch* br) { + br->Fill(); + br->ResetAddress(); + br->DropBaskets("all"); + }; + // get the data as gsl::span so that ideally no copy is made + // but immediately adopt the views in standard std::vectors *** THIS IS AN INTERNAL HACK *** + if (mctruth) { + labelview.adopt(ctx.inputs().get<gsl::span<char>>("digitsMCTR")); + fillBranch(t.Branch((detStr + "DigitMCTruth").c_str(), &labelview)); + adopt(ctx.inputs().get<gsl::span<itsmft::MC2ROFRecord>>("digitsMC2ROF"), *mc2rofrecords); + fillBranch(t.Branch((detStr + "DigitMC2ROF").c_str(), &mc2rofrecords)); + } + adopt(ctx.inputs().get<gsl::span<itsmft::Digit>>("digits"), *digits); + fillBranch(t.Branch((detStr + "Digits").c_str(), &digits)); + adopt(ctx.inputs().get<gsl::span<itsmft::ROFRecord>>("digitsROF"), *rof); + fillBranch(t.Branch((detStr + "DigitROF").c_str(), &rof)); + t.SetEntries(1); + f.Write(); + f.Close(); + ctx.services().get<ControlService>().readyToQuit(QuitRequest::Me); + mFinished = true; + }}}; +#else auto logger = [](std::vector<o2::itsmft::Digit> const& inDigits) { LOG(INFO) << "RECEIVED DIGITS SIZE " << inDigits.size(); }; + + // the callback to be set as hook for custom action when the writer is closed + auto finishWriting = [](TFile* outputfile, TTree* outputtree) { + outputtree->SetEntries(1); + outputtree->Write("", TObject::kOverwrite); + outputfile->Close(); + }; + + // handler for labels + // This is necessary since we can't store the original label buffer in a ROOT entry -- as is -- if it exceeds a certain size. + // We therefore convert it to a special split class. + auto fillLabels = [detStr](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& /*ref*/) { + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> labels(labelbuffer); + LOG(INFO) << "WRITING " << labels.getNElements() << " LABELS "; + + o2::dataformats::IOMCTruthContainerView outputcontainer; + // first of all redefine the output format (special to labels) + auto tree = branch.GetTree(); + + std::stringstream str; + str << detStr + "DigitMCTruth"; + auto br = tree->Branch(str.str().c_str(), &outputcontainer); + outputcontainer.adopt(labelbuffer); + br->Fill(); + br->ResetAddress(); + const int entries = 1; + tree->SetEntries(entries); + tree->Write("", TObject::kOverwrite); + }; + return MakeRootTreeWriterSpec((detStr + "DigitWriter").c_str(), (detStrL + "digits.root").c_str(), MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Digits tree"}, - BranchDefinition<MCCont>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, - (detStr + "DigitMCTruth").c_str(), - (mctruth ? 1 : 0)}, + MakeRootTreeWriterSpec::CustomClose(finishWriting), + // in case of labels we first read them as std::vector<char> and process them correctly in the fillLabels hook + BranchDefinition<std::vector<char>>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, + (detStr + "DigitMCTruth_TMP").c_str(), + (mctruth ? 1 : 0), fillLabels}, BranchDefinition<std::vector<itsmft::MC2ROFRecord>>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, (detStr + "DigitMC2ROF").c_str(), (mctruth ? 1 : 0)}, @@ -58,6 +172,7 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOri logger}, BranchDefinition<std::vector<itsmft::ROFRecord>>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, (detStr + "DigitROF").c_str()})(); +#endif } DataProcessorSpec getITSDigitWriterSpec(bool mctruth) diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx index 76b76824dc546..75c2e8b9ad9ea 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx @@ -19,6 +19,7 @@ #include "Steer/HitProcessingManager.h" // for DigitizationContext #include "DataFormatsITSMFT/Digit.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "DetectorsBase/BaseDPLDigitizer.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsCommonDataFormats/SimTraits.h" @@ -129,10 +130,15 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer // here we have all digits and labels and we can send them to consumer (aka snapshot it onto output) pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0, Lifetime::Timeframe}, mDigitsAccum); + mDigitsAccum = std::vector<itsmft::Digit>(); // free mem immediately pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0, Lifetime::Timeframe}, mROFRecordsAccum); if (mWithMCTruth) { pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0, Lifetime::Timeframe}, mMC2ROFRecordsAccum); - pc.outputs().snapshot(Output{mOrigin, "DIGITSMCTR", 0, Lifetime::Timeframe}, mLabelsAccum); + auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{mOrigin, "DIGITSMCTR", 0, Lifetime::Timeframe}); + mLabelsAccum.flatten_to(sharedlabels); + // free space of existing label containers + mLabels.clear_andfreememory(); + mLabelsAccum.clear_andfreememory(); } LOG(INFO) << mID.getName() << ": Sending ROMode= " << mROMode << " to GRPUpdater"; pc.outputs().snapshot(Output{mOrigin, "ROMode", 0, Lifetime::Timeframe}, mROMode); diff --git a/macro/readITSDigits.C b/macro/readITSDigits.C index 0958ca9f5312f..33257a1493fb7 100644 --- a/macro/readITSDigits.C +++ b/macro/readITSDigits.C @@ -10,6 +10,8 @@ #include "DataFormatsITSMFT/Digit.h" #include "SimulationDataFormat/DigitizationContext.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include "SimulationDataFormat/MCCompLabel.h" /// Example of accessing the digits of MCEvent digitized with continous readout @@ -42,7 +44,20 @@ void readITSDigits(std::string path = "./", std::vector<o2::itsmft::Digit>* dv = nullptr; digiTree->SetBranchAddress("ITSDigit", &dv); o2::dataformats::MCTruthContainer<o2::MCCompLabel>* labels = nullptr; - digiTree->SetBranchAddress("ITSDigitMCTruth", &labels); + o2::dataformats::IOMCTruthContainerView* labelROOTbuffer = nullptr; + o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel> constlabels; + + // for backward compatibility we check what is stored in the file + auto labelClass = digiTree->GetBranch("ITSDigitMCTruth")->GetClassName(); + bool oldlabelformat = false; + if (TString(labelClass).Contains("IOMCTruth")) { + // new format + digiTree->SetBranchAddress("ITSDigitMCTruth", &labelROOTbuffer); + } else { + // old format + digiTree->SetBranchAddress("ITSDigitMCTruth", &labels); + oldlabelformat = true; + } // ROF record entries in the digit tree std::vector<o2::itsmft::ROFRecord>* rofRecVec = nullptr; @@ -53,6 +68,9 @@ void readITSDigits(std::string path = "./", digiTree->SetBranchAddress("ITSDigitMC2ROF", &mc2rofVec); digiTree->GetEntry(0); + if (!oldlabelformat) { + labelROOTbuffer->copyandflatten(constlabels); + } // MC collisions record auto runContext = reinterpret_cast<o2::steer::DigitizationContext*>(rcFile->GetObjectChecked("DigitizationContext", "o2::steer::DigitizationContext")); @@ -89,7 +107,7 @@ void readITSDigits(std::string path = "./", int dgid = rofrec.getFirstEntry(); const auto& digit0 = (*dv)[dgid]; - const auto& labs0 = labels->getLabels(dgid); + const auto& labs0 = oldlabelformat ? labels->getLabels(dgid) : constlabels.getLabels(dgid); printf("1st digit of this ROF (Entry: %6d) :", dgid); digit0.print(std::cout); printf(" MCinfo: "); @@ -97,7 +115,7 @@ void readITSDigits(std::string path = "./", dgid = rofrec.getFirstEntry() + rofrec.getNEntries() - 1; const auto& digit1 = (*dv)[dgid]; - const auto& labs1 = labels->getLabels(dgid); + const auto& labs1 = oldlabelformat ? labels->getLabels(dgid) : constlabels.getLabels(dgid); printf("1st digit of this ROF (Entry: %6d) :", dgid); digit1.print(std::cout); printf(" MCinfo: "); From 31aef58ced4c8dd6258ac3438f2827154087e64f Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 24 Sep 2020 10:56:43 +0200 Subject: [PATCH 0745/1751] ITSMFT: Zero copy - accumulate digits direcly in DPL resource --- .../src/ITSMFTDigitizerSpec.cxx | 91 ++++++++++--------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx index 75c2e8b9ad9ea..4606304f0268c 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx @@ -101,6 +101,51 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer mDigitizer.setROFRecords(&mROFRecords); mDigitizer.setMCLabels(&mLabels); + // digits are directly put into DPL owned resource + auto digitsAccum = pc.outputs().make<std::vector<itsmft::Digit>>(Output{mOrigin, "DIGITS", 0, Lifetime::Timeframe}); + + auto accumulate = [this, &digitsAccum]() { + // accumulate result of single event processing, called after processing every event supplied + // AND after the final flushing via digitizer::fillOutputContainer + if (!mDigits.size()) { + return; // no digits were flushed, nothing to accumulate + } + static int fixMC2ROF = 0; // 1st entry in mc2rofRecordsAccum to be fixed for ROFRecordID + auto ndigAcc = digitsAccum.size(); + std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(digitsAccum)); + + // fix ROFrecords references on ROF entries + auto nROFRecsOld = mROFRecordsAccum.size(); + + for (int i = 0; i < mROFRecords.size(); i++) { + auto& rof = mROFRecords[i]; + rof.setFirstEntry(ndigAcc + rof.getFirstEntry()); + rof.print(); + + if (mFixMC2ROF < mMC2ROFRecordsAccum.size()) { // fix ROFRecord entry in MC2ROF records + for (int m2rid = mFixMC2ROF; m2rid < mMC2ROFRecordsAccum.size(); m2rid++) { + // need to register the ROFRecors entry for MC event starting from this entry + auto& mc2rof = mMC2ROFRecordsAccum[m2rid]; + if (rof.getROFrame() == mc2rof.minROF) { + mFixMC2ROF++; + mc2rof.rofRecordID = nROFRecsOld + i; + mc2rof.print(); + } + } + } + } + + std::copy(mROFRecords.begin(), mROFRecords.end(), std::back_inserter(mROFRecordsAccum)); + if (mWithMCTruth) { + mLabelsAccum.mergeAtBack(mLabels); + } + LOG(INFO) << "Added " << mDigits.size() << " digits "; + // clean containers from already accumulated stuff + mLabels.clear(); + mDigits.clear(); + mROFRecords.clear(); + }; // and accumulate lambda + auto& eventParts = context->getEventParts(withQED); // loop over all composite collisions given from context (aka loop over all the interaction records) for (int collID = 0; collID < timesview.size(); ++collID) { @@ -129,8 +174,7 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer accumulate(); // here we have all digits and labels and we can send them to consumer (aka snapshot it onto output) - pc.outputs().snapshot(Output{mOrigin, "DIGITS", 0, Lifetime::Timeframe}, mDigitsAccum); - mDigitsAccum = std::vector<itsmft::Digit>(); // free mem immediately + pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0, Lifetime::Timeframe}, mROFRecordsAccum); if (mWithMCTruth) { pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0, Lifetime::Timeframe}, mMC2ROFRecordsAccum); @@ -155,48 +199,6 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer protected: ITSMFTDPLDigitizerTask(bool mctruth = true) : BaseDPLDigitizer(InitServices::FIELD | InitServices::GEOM), mWithMCTruth(mctruth) {} - void accumulate() - { - // accumulate result of single event processing, called after processing every event supplied - // AND after the final flushing via digitizer::fillOutputContainer - if (!mDigits.size()) { - return; // no digits were flushed, nothing to accumulate - } - static int fixMC2ROF = 0; // 1st entry in mc2rofRecordsAccum to be fixed for ROFRecordID - auto ndigAcc = mDigitsAccum.size(); - std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(mDigitsAccum)); - - // fix ROFrecords references on ROF entries - auto nROFRecsOld = mROFRecordsAccum.size(); - - for (int i = 0; i < mROFRecords.size(); i++) { - auto& rof = mROFRecords[i]; - rof.setFirstEntry(ndigAcc + rof.getFirstEntry()); - rof.print(); - - if (mFixMC2ROF < mMC2ROFRecordsAccum.size()) { // fix ROFRecord entry in MC2ROF records - for (int m2rid = mFixMC2ROF; m2rid < mMC2ROFRecordsAccum.size(); m2rid++) { - // need to register the ROFRecors entry for MC event starting from this entry - auto& mc2rof = mMC2ROFRecordsAccum[m2rid]; - if (rof.getROFrame() == mc2rof.minROF) { - mFixMC2ROF++; - mc2rof.rofRecordID = nROFRecsOld + i; - mc2rof.print(); - } - } - } - } - std::copy(mROFRecords.begin(), mROFRecords.end(), std::back_inserter(mROFRecordsAccum)); - if (mWithMCTruth) { - mLabelsAccum.mergeAtBack(mLabels); - } - LOG(INFO) << "Added " << mDigits.size() << " digits "; - // clean containers from already accumulated stuff - mLabels.clear(); - mDigits.clear(); - mROFRecords.clear(); - } - bool mWithMCTruth = true; bool mFinished = false; bool mDisableQED = false; @@ -204,7 +206,6 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; o2::itsmft::Digitizer mDigitizer; std::vector<o2::itsmft::Digit> mDigits; - std::vector<o2::itsmft::Digit> mDigitsAccum; std::vector<o2::itsmft::ROFRecord> mROFRecords; std::vector<o2::itsmft::ROFRecord> mROFRecordsAccum; std::vector<o2::itsmft::Hit> mHits; From 907f2befe5b46fa48c4758dc5961d68aab7d03e9 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 24 Sep 2020 15:13:37 +0200 Subject: [PATCH 0746/1751] Add abs.charge data member to TrackPar This is needed for uniform treatment of tracks with non-standard charge: 0 (for V0s) and e.g. 2 for hypernuclei. In the aliroot AliExternalTrackParam this was treated by derived classes using virtual methods, which we don't use in O2. The meaning of mP[kQ2Pt] remains exactly the same, except for q=0 case: in this case the mP[kQ2Pt] is just an alias to 1/pT, regardless of its sign, and the getCurvature() will 0 (because mAbsCharge is 0). The methods returning lab momentum or its combination account for eventual q>1. --- .../include/ReconstructionDataFormats/Track.h | 55 ++++++++++++++----- DataFormats/Reconstruction/src/Track.cxx | 48 ++++++++-------- 2 files changed, 64 insertions(+), 39 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h index e30d2cc090135..0e31b83b6f902 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h @@ -12,6 +12,15 @@ /// \brief Base track model for the Barrel, params only, w/o covariance /// \author ruben.shahoyan@cern.ch +/* + 24/09/2020: Added new data member for abs. charge. This is needed for uniform treatment of tracks with non-standard + charge: 0 (for V0s) and e.g. 2 for hypernuclei. + In the aliroot AliExternalTrackParam this was treated by derived classes using virtual methods, which we don't use in O2. + The meaning of mP[kQ2Pt] remains exactly the same, except for q=0 case: in this case the mP[kQ2Pt] is just an alias to + 1/pT, regardless of its sign, and the getCurvature() will 0 (because mAbsCharge is 0). + The methods returning lab momentum or its combination account for eventual q>1. + */ + #ifndef ALICEO2_BASE_TRACK #define ALICEO2_BASE_TRACK @@ -128,8 +137,8 @@ class TrackPar { // track parameterization, kinematics only. public: TrackPar() = default; - TrackPar(float x, float alpha, const std::array<float, kNParams>& par); - TrackPar(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, int sign, bool sectorAlpha = true); + TrackPar(float x, float alpha, const std::array<float, kNParams>& par, int charge = 1); + TrackPar(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, int charge, bool sectorAlpha = true); TrackPar(const TrackPar&) = default; TrackPar& operator=(const TrackPar& src) = default; ~TrackPar() = default; @@ -143,6 +152,7 @@ class TrackPar float getSnp() const { return mP[kSnp]; } float getTgl() const { return mP[kTgl]; } float getQ2Pt() const { return mP[kQ2Pt]; } + float getCharge2Pt() const { return mAbsCharge ? mP[kQ2Pt] : 0.; } /// calculate cos^2 and cos of track direction in rphi-tracking float getCsp2() const @@ -160,17 +170,21 @@ class TrackPar void setSnp(float v) { mP[kSnp] = v; } void setTgl(float v) { mP[kTgl] = v; } void setQ2Pt(float v) { mP[kQ2Pt] = v; } + void setAbsCharge(int q) { mAbsCharge = std::abs(q); } // derived getters bool getXatLabR(float r, float& x, float bz, DirType dir = DirAuto) const; void getCircleParamsLoc(float bz, o2::utils::CircleXY& circle) const; void getCircleParams(float bz, o2::utils::CircleXY& circle, float& sna, float& csa) const; void getLineParams(o2::utils::IntervalXY& line, float& sna, float& csa) const; - float getCurvature(float b) const { return mP[kQ2Pt] * b * o2::constants::math::B2C; } - float getSign() const { return mP[kQ2Pt] > 0 ? 1.f : -1.f; } + float getCurvature(float b) const { return mAbsCharge ? mP[kQ2Pt] * b * o2::constants::math::B2C : 0.; } + int getAbsCharge() const { return mAbsCharge; } + int getCharge() const { return getSign() > 0 ? mAbsCharge : -mAbsCharge; } + int getSign() const { return mAbsCharge ? (mP[kQ2Pt] > 0.f ? 1 : -1) : 0; } float getPhi() const; float getPhiPos() const; + float getPtInv() const; float getP2Inv() const; float getP2() const; float getPInv() const; @@ -224,8 +238,9 @@ class TrackPar 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 + char mAbsCharge = 1; /// Extra info about the abs charge, to be taken into account only if not 1 - ClassDefNV(TrackPar, 1); + ClassDefNV(TrackPar, 2); }; class TrackParCov : public TrackPar @@ -235,7 +250,7 @@ class TrackParCov : public TrackPar public: TrackParCov() : TrackPar{} {} - TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, const std::array<float, kCovMatSize>& cov); + TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, const std::array<float, kCovMatSize>& cov, int charge = 1); TrackParCov(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, const std::array<float, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); TrackParCov(const TrackParCov& src) = default; @@ -319,11 +334,12 @@ class TrackParCov : public TrackPar protected: float mC[kCovMatSize] = {0.f}; // 15 covariance matrix elements - ClassDefNV(TrackParCov, 1); + ClassDefNV(TrackParCov, 2); }; //____________________________________________________________ -inline TrackPar::TrackPar(float x, float alpha, const std::array<float, kNParams>& par) : mX{x}, mAlpha{alpha} +inline TrackPar::TrackPar(float x, float alpha, const std::array<float, kNParams>& par, int charge) + : mX{x}, mAlpha{alpha}, mAbsCharge{char(std::abs(charge))} { // explicit constructor std::copy(par.begin(), par.end(), mP); @@ -420,14 +436,24 @@ inline float TrackPar::getPhiPos() const inline float TrackPar::getP2Inv() const { // return the inverted track momentum^2 - return getQ2Pt() * getQ2Pt() / (1.f + getTgl() * getTgl()); + auto p2 = mP[kQ2Pt] * mP[kQ2Pt] / (1.f + getTgl() * getTgl()); + return (mAbsCharge > 1) ? p2 * mAbsCharge * mAbsCharge : p2; +} + +//____________________________________________________________ +inline float TrackPar::getPtInv() const +{ + // return the inverted track pT + auto ptInv = fabs(mP[kQ2Pt]); + return (mAbsCharge > 1) ? ptInv / mAbsCharge : ptInv; } //____________________________________________________________ inline float TrackPar::getPInv() const { // return the inverted track momentum^2 - return fabs(getQ2Pt()) / sqrtf(1.f + getTgl() * getTgl()); + auto pInv = fabs(mP[kQ2Pt]) / sqrtf(1.f + getTgl() * getTgl()); + return (mAbsCharge > 1) ? pInv / mAbsCharge : pInv; } //____________________________________________________________ @@ -450,7 +476,10 @@ inline float TrackPar::getP() const inline float TrackPar::getPt() const { // return the track transverse momentum - float ptI = fabs(getQ2Pt()); + float ptI = fabs(mP[kQ2Pt]); + if (mAbsCharge > 1) { + ptI /= mAbsCharge; + } return (ptI > o2::constants::math::Almost0) ? 1.f / ptI : o2::constants::math::VeryBig; } @@ -458,8 +487,8 @@ inline float TrackPar::getPt() const //____________________________________________________________ inline TrackParCov::TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, - const std::array<float, kCovMatSize>& cov) - : TrackPar{x, alpha, par} + const std::array<float, kCovMatSize>& cov, int charge) + : TrackPar{x, alpha, par, charge} { // explicit constructor std::copy(cov.begin(), cov.end(), mC); diff --git a/DataFormats/Reconstruction/src/Track.cxx b/DataFormats/Reconstruction/src/Track.cxx index 28773a1f53fcc..211b01a5a8021 100644 --- a/DataFormats/Reconstruction/src/Track.cxx +++ b/DataFormats/Reconstruction/src/Track.cxx @@ -79,7 +79,8 @@ TrackPar::TrackPar(const array<float, 3>& xyz, const array<float, 3>& pxpypz, in mP[kZ] = ver[2]; mP[kSnp] = mom[1] * ptI; mP[kTgl] = mom[2] * ptI; - mP[kQ2Pt] = ptI * charge; + mAbsCharge = std::abs(charge); + mP[kQ2Pt] = charge ? ptI * charge : ptI; // if (fabs(1 - getSnp()) < kSafe) { mP[kSnp] = 1. - kSafe; // Protection @@ -96,7 +97,7 @@ bool TrackPar::getPxPyPzGlo(array<float, 3>& pxyz) const if (fabs(getQ2Pt()) < Almost0 || fabs(getSnp()) > Almost1) { return false; } - float cs, sn, pt = fabs(1.f / getQ2Pt()); + float cs, sn, pt = getPt(); float r = std::sqrt((1.f - getSnp()) * (1.f + getSnp())); utils::sincos(getAlpha(), sn, cs); pxyz[0] = pt * (r * cs - getSnp() * sn); @@ -183,7 +184,7 @@ bool TrackPar::propagateParamTo(float xk, const array<float, 3>& b) // print(); return false; } - float crv = (fabs(b[2]) < Almost0) ? 0.f : getCurvature(b[2]); + float crv = getCurvature(b[2]); float x2r = crv * dx; float f1 = getSnp(), f2 = f1 + x2r; if (fabs(f1) > Almost1 || fabs(f2) > Almost1) { @@ -231,8 +232,8 @@ bool TrackPar::propagateParamTo(float xk, const array<float, 3>& b) vecLab[6]}; // Do the helix step - float sgn = getSign(); - g3helx3(sgn * bb, step, vect); + float q = getCharge(); + g3helx3(q * bb, step, vect); // rotate back to the Global System vecLab[0] = cosphi * costet * vect[0] - sinphi * vect[1] + cosphi * sintet * vect[2]; @@ -271,7 +272,7 @@ bool TrackPar::propagateParamTo(float xk, const array<float, 3>& b) mP[kZ] = z; mP[kSnp] = vecLab[4] * t; mP[kTgl] = vecLab[5] * t; - mP[kQ2Pt] = sgn * t / vecLab[6]; + mP[kQ2Pt] = q * t / vecLab[6]; return true; } @@ -381,15 +382,12 @@ bool TrackPar::getYZAt(float xk, float b, float& y, float& z) const if (fabs(dx) < Almost0) { return true; } - float crv = (fabs(b) < Almost0) ? 0.f : getCurvature(b); + float crv = getCurvature(b); float x2r = crv * dx; float f1 = getSnp(), f2 = f1 + x2r; if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { return false; } - if (fabs(getQ2Pt()) < Almost0) { - return false; - } float r1 = std::sqrt((1.f - f1) * (1.f + f1)); if (fabs(r1) < Almost0) { return false; @@ -460,7 +458,7 @@ float TrackPar::getYAt(float xk, float b) const std::string TrackPar::asString() const { // print parameters as string - return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e}", getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt()); + return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d}", getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge()); } //______________________________________________________________ @@ -655,7 +653,7 @@ bool TrackPar::correctForELoss(float xrho, float mass, bool anglecorr, float ded // "xrho" - is the product length*density (g/cm^2). // It should be passed as negative when propagating tracks // from the intreaction point to the outside of the central barrel. - // "mass" - the mass of this particle (GeV/c^2). Negative mass means charge=2 particle + // "mass" - the mass of this particle (GeV/c^2). // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly // "anglecorr" - switch for the angular correction //------------------------------------------------------------------ @@ -682,8 +680,8 @@ bool TrackPar::correctForELoss(float xrho, float mass, bool anglecorr, float ded if ((xrho != 0.f) && (beta2 < 1.f)) { if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly dedx = BetheBlochSolid(p / fabs(mass)); - if (mass < 0) { - dedx *= 4.f; // z=2 particle + if (mAbsCharge != 1) { + dedx *= mAbsCharge * mAbsCharge; } } @@ -727,7 +725,7 @@ bool TrackParCov::propagateTo(float xk, float b) if (fabs(dx) < Almost0) { return true; } - float crv = (fabs(b) < Almost0) ? 0.f : getCurvature(b); + float crv = getCurvature(b); float x2r = crv * dx; float f1 = getSnp(), f2 = f1 + x2r; if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { @@ -974,7 +972,8 @@ TrackParCov::TrackParCov(const array<float, 3>& xyz, const array<float, 3>& pxpy setZ(ver[2]); setSnp(mom[1] * ptI); // cos(phi) setTgl(mom[2] * ptI); // tg(lambda) - setQ2Pt(ptI * charge); + setAbsCharge(std::abs(charge)); + setQ2Pt(charge ? ptI * charge : ptI); // if (fabs(1.f - getSnp()) < kSafe) { setSnp(1.f - kSafe); // Protection @@ -1556,7 +1555,7 @@ bool TrackParCov::correctForMaterial(float x2x0, float xrho, float mass, bool an // "xrho" - is the product length*density (g/cm^2). // It should be passed as negative when propagating tracks // from the intreaction point to the outside of the central barrel. - // "mass" - the mass of this particle (GeV/c^2). Negative mass means charge=2 particle + // "mass" - the mass of this particle (GeV/c^2). // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly // "anglecorr" - switch for the angular correction //------------------------------------------------------------------ @@ -1579,9 +1578,6 @@ bool TrackParCov::correctForMaterial(float x2x0, float xrho, float mass, bool an } float p = getP(); - if (mass < 0) { - p += p; // q=2 particle - } float p2 = p * p, mass2 = mass * mass; float e2 = p2 + mass2; float beta2 = p2 / e2; @@ -1590,13 +1586,13 @@ bool TrackParCov::correctForMaterial(float x2x0, float xrho, float mass, bool an float cC22(0.f), cC33(0.f), cC43(0.f), cC44(0.f); if (x2x0 != 0.f) { float theta2 = kMSConst2 / (beta2 * p2) * fabs(x2x0); - if (mass < 0) { - theta2 *= 4.f; // q=2 particle + if (getAbsCharge() != 1) { + theta2 *= getAbsCharge() * getAbsCharge(); } if (theta2 > PI * PI) { return false; } - float fp34 = getTgl() * getQ2Pt(); + float fp34 = getTgl() * getCharge2Pt(); float t2c2I = theta2 * cst2I; cC22 = t2c2I * csp2; cC33 = t2c2I * cst2I; @@ -1614,8 +1610,8 @@ bool TrackParCov::correctForMaterial(float x2x0, float xrho, float mass, bool an if ((xrho != 0.f) && (beta2 < 1.f)) { if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly dedx = BetheBlochSolid(p / fabs(mass)); - if (mass < 0) { - dedx *= 4.f; // z=2 particle + if (getAbsCharge() != 1) { + dedx *= getAbsCharge() * getAbsCharge(); } } @@ -1633,7 +1629,7 @@ bool TrackParCov::correctForMaterial(float x2x0, float xrho, float mass, bool an // // Approximate energy loss fluctuation (M.Ivanov) constexpr float knst = 0.07f; // To be tuned. - float sigmadE = knst * std::sqrt(fabs(dE)) * e / p2 * getQ2Pt(); + float sigmadE = knst * std::sqrt(fabs(dE)) * e / p2 * getCharge2Pt(); cC44 += sigmadE * sigmadE; } From 7ef905583c50c420b2fcb2f6629596ea5c012c69 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 24 Sep 2020 22:52:43 +0200 Subject: [PATCH 0747/1751] Extend track::PID list and add PID data member to TrackPar * PID list extended by derived particles (V0 and cascade candidates), changed to uint8_t base. * TrackPar will have mPID data member --- .../CommonConstants/PhysicsConstants.h | 3 ++ .../ITS/include/DataFormatsITS/TrackITS.h | 6 +-- .../include/ReconstructionDataFormats/PID.h | 46 +++++++++++++------ .../include/ReconstructionDataFormats/Track.h | 10 +++- DataFormats/Reconstruction/src/PID.cxx | 10 ++-- DataFormats/Reconstruction/src/Track.cxx | 3 +- 6 files changed, 52 insertions(+), 26 deletions(-) diff --git a/Common/Constants/include/CommonConstants/PhysicsConstants.h b/Common/Constants/include/CommonConstants/PhysicsConstants.h index 9f62599916a3f..1e2fe24e1dab9 100644 --- a/Common/Constants/include/CommonConstants/PhysicsConstants.h +++ b/Common/Constants/include/CommonConstants/PhysicsConstants.h @@ -22,6 +22,7 @@ namespace constants namespace physics { // particles masses +constexpr float MassPhoton = 0.0; constexpr float MassElectron = 0.000511; constexpr float MassMuon = 0.105658; constexpr float MassPionCharged = 0.139570; @@ -29,10 +30,12 @@ constexpr float MassPionNeutral = 0.134976; constexpr float MassKaonCharged = 0.493677; constexpr float MassKaonNeutral = 0.497648; constexpr float MassProton = 0.938272; +constexpr float MassLambda = 1.115683; constexpr float MassDeuteron = 1.875613; constexpr float MassTriton = 2.809250; constexpr float MassHelium3 = 2.809230; constexpr float MassAlpha = 3.727379; +constexpr float MassHyperTriton = 2.992; constexpr float LightSpeedCm2S = 299792458.e2; // C in cm/s constexpr float LightSpeedCm2NS = LightSpeedCm2S * 1e-9; // C in cm/ns diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index 4799d43fa7d2d..a9a1769a6cba1 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -87,9 +87,6 @@ class TrackITS : public o2::track::TrackParCov o2::track::TrackParCov& getParamOut() { return mParamOut; } const o2::track::TrackParCov& getParamOut() const { return mParamOut; } - void setPID(uint8_t p) { mPID = p; } - int getPID() const { return mPID; } - void setPattern(uint8_t p) { mPattern = p; } int getPattern() const { return mPattern; } bool hasHitOnLayer(int i) { return mPattern & (0x1 << i); } @@ -98,7 +95,6 @@ class TrackITS : public o2::track::TrackParCov o2::track::TrackParCov mParamOut; ///< parameter at largest radius ClusRefs mClusRef; ///< references on clusters float mChi2 = 0.; ///< Chi2 for this track - uint8_t mPID = 0; ///< pid info (at the moment not used) uint8_t mPattern = 0; ///< layers pattern ClassDefNV(TrackITS, 4); @@ -137,7 +133,7 @@ class TrackITSExt : public TrackITS private: std::array<int, MaxClusters> mIndex = {-1}; ///< Indices of associated clusters - ClassDefNV(TrackITSExt, 1); + ClassDefNV(TrackITSExt, 2); }; } // namespace its } // namespace o2 diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h index 6e3df2f92cd7a..9f1b6b12477aa 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h @@ -15,7 +15,7 @@ #ifndef ALICEO2_track_PID_H_ #define ALICEO2_track_PID_H_ -#include <Rtypes.h> +#include "GPUCommonRtypes.h" #include "CommonConstants/PhysicsConstants.h" namespace o2 @@ -26,7 +26,7 @@ class PID { public: // particle identifiers, continuos starting from 0 - typedef std::int32_t ID; + typedef uint8_t ID; static constexpr ID Electron = 0; static constexpr ID Muon = 1; @@ -40,7 +40,17 @@ class PID static constexpr ID First = Electron; static constexpr ID Last = Alpha; ///< if extra IDs added, update this !!! - static constexpr int NIDs = Last + 1; ///< number of defined IDs + static constexpr ID NIDs = Last + 1; ///< number of defined IDs + + // PID for derived particles + static constexpr ID PI0 = 9; + static constexpr ID Photon = 10; + static constexpr ID K0 = 11; + static constexpr ID Lambda = 12; + static constexpr ID HyperTriton = 13; + static constexpr ID FirstExt = PI0; + static constexpr ID LastExt = HyperTriton; + static constexpr ID NIDsTot = LastExt + 1; ///< total number of defined IDs PID() = default; PID(ID id) : mID(id) {} @@ -49,6 +59,7 @@ class PID PID& operator=(const PID& src) = default; ID getID() const { return mID; } + operator ID() const { return getID(); } float getMass() const { return getMass(mID); } float getMass2Z() const { return getMass2Z(mID); } @@ -69,32 +80,39 @@ class PID return !*x && !*y ? true : /* default */ (*x == *y && sameStr(x + 1, y + 1)); } - inline static constexpr int nameToID(char const* name, int id) + inline static constexpr ID nameToID(char const* name, ID id) { - return id > Last ? id : sameStr(name, sNames[id]) ? id : nameToID(name, id + 1); + return id > LastExt ? id : sameStr(name, sNames[id]) ? id : nameToID(name, id + 1); } - static constexpr const char* sNames[NIDs + 1] = ///< defined particle names - {"Electron", "Muon", "Pion", "Kaon", "Proton", "Deuteron", "Triton", "He3", "Alpha", nullptr}; + static constexpr const char* sNames[NIDsTot + 1] = ///< defined particle names + {"Electron", "Muon", "Pion", "Kaon", "Proton", "Deuteron", "Triton", "He3", "Alpha", + "Pion0", "Photon", "K0", "Lambda", "HyperTriton", + nullptr}; - static constexpr const float sMasses[NIDs] = ///< defined particle masses + static constexpr const float sMasses[NIDsTot] = ///< defined particle masses {o2::constants::physics::MassElectron, o2::constants::physics::MassMuon, o2::constants::physics::MassPionCharged, o2::constants::physics::MassKaonCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron, o2::constants::physics::MassTriton, o2::constants::physics::MassHelium3, - o2::constants::physics::MassAlpha}; + o2::constants::physics::MassAlpha, + o2::constants::physics::MassPionNeutral, o2::constants::physics::MassPhoton, + o2::constants::physics::MassKaonNeutral, o2::constants::physics::MassLambda, + o2::constants::physics::MassHyperTriton}; - static constexpr const float sMasses2Z[NIDs] = ///< defined particle masses / Z + static constexpr const float sMasses2Z[NIDsTot] = ///< defined particle masses / Z {o2::constants::physics::MassElectron, o2::constants::physics::MassMuon, o2::constants::physics::MassPionCharged, o2::constants::physics::MassKaonCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron, o2::constants::physics::MassTriton, o2::constants::physics::MassHelium3 / 2., - o2::constants::physics::MassAlpha / 2.}; + o2::constants::physics::MassAlpha / 2., + 0, 0, 0, 0, o2::constants::physics::MassHyperTriton}; - static constexpr const int sCharges[NIDs] = ///< defined particle charges - {1, 1, 1, 1, 1, 1, 1, 2, 2}; + static constexpr const int sCharges[NIDsTot] = ///< defined particle charges + {1, 1, 1, 1, 1, 1, 1, 2, 2, + 0, 0, 0, 0, 1}; - ClassDefNV(PID, 1); + ClassDefNV(PID, 2); }; } // namespace track } // namespace o2 diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h index 0e31b83b6f902..553258b407138 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h @@ -43,6 +43,7 @@ #include "CommonConstants/MathConstants.h" #include "MathUtils/Utils.h" #include "MathUtils/Primitive2D.h" +#include "ReconstructionDataFormats/PID.h" //Forward declarations, since we cannot include the headers if we eventually want to use track.h on GPU namespace ROOT @@ -153,6 +154,13 @@ class TrackPar float getTgl() const { return mP[kTgl]; } float getQ2Pt() const { return mP[kQ2Pt]; } float getCharge2Pt() const { return mAbsCharge ? mP[kQ2Pt] : 0.; } + int getAbsCharge() const { return mAbsCharge; } + PID getPID() const { return mPID; } + void setPID(const PID pid) + { + mPID = pid; + setAbsCharge(pid.getCharge()); + } /// calculate cos^2 and cos of track direction in rphi-tracking float getCsp2() const @@ -178,7 +186,6 @@ class TrackPar void getCircleParams(float bz, o2::utils::CircleXY& circle, float& sna, float& csa) const; void getLineParams(o2::utils::IntervalXY& line, float& sna, float& csa) const; float getCurvature(float b) const { return mAbsCharge ? mP[kQ2Pt] * b * o2::constants::math::B2C : 0.; } - int getAbsCharge() const { return mAbsCharge; } int getCharge() const { return getSign() > 0 ? mAbsCharge : -mAbsCharge; } int getSign() const { return mAbsCharge ? (mP[kQ2Pt] > 0.f ? 1 : -1) : 0; } float getPhi() const; @@ -239,6 +246,7 @@ class TrackPar float mAlpha = 0.f; /// track frame angle float mP[kNParams] = {0.f}; /// 5 parameters: Y,Z,sin(phi),tg(lambda),q/pT char mAbsCharge = 1; /// Extra info about the abs charge, to be taken into account only if not 1 + PID mPID{}; /// 8 bit PID ClassDefNV(TrackPar, 2); }; diff --git a/DataFormats/Reconstruction/src/PID.cxx b/DataFormats/Reconstruction/src/PID.cxx index 1af3ae35cb695..6b3986de9c7ab 100644 --- a/DataFormats/Reconstruction/src/PID.cxx +++ b/DataFormats/Reconstruction/src/PID.cxx @@ -18,14 +18,14 @@ using namespace o2::track; -constexpr const char* PID::sNames[NIDs + 1]; -constexpr const float PID::sMasses[NIDs]; -constexpr const float PID::sMasses2Z[NIDs]; -constexpr const int PID::sCharges[NIDs]; +constexpr const char* PID::sNames[NIDsTot + 1]; +constexpr const float PID::sMasses[NIDsTot]; +constexpr const float PID::sMasses2Z[NIDsTot]; +constexpr const int PID::sCharges[NIDsTot]; //_______________________________ PID::PID(const char* name) : mID(nameToID(name, First)) { // construct from the name - assert(mID < NIDs); + assert(mID < NIDsTot); } diff --git a/DataFormats/Reconstruction/src/Track.cxx b/DataFormats/Reconstruction/src/Track.cxx index 211b01a5a8021..f83c53f4d2c56 100644 --- a/DataFormats/Reconstruction/src/Track.cxx +++ b/DataFormats/Reconstruction/src/Track.cxx @@ -458,7 +458,8 @@ float TrackPar::getYAt(float xk, float b) const std::string TrackPar::asString() const { // print parameters as string - return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d}", getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge()); + return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d} {:s}", + getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName()); } //______________________________________________________________ From 31e0243de3a6b731f5be77a888e2ccf8e4491a4e Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Fri, 25 Sep 2020 11:40:36 +0200 Subject: [PATCH 0748/1751] Proper protection in case BUILD_SIMULATION=OFF --- macro/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index ae1650bb84db2..f487ab470611e 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -187,7 +187,7 @@ o2_add_test_root_macro( O2::CPVSimulation O2::ZDCSimulation) -if(Geant4_FOUND) +if(Geant4_FOUND AND BUILD_SIMULATION) o2_add_test_root_macro(o2sim.C PUBLIC_LINK_LIBRARIES O2::Generators O2::DetectorsPassive From 90136388521527437982c1bdafd30fd8a179fae9 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 24 Sep 2020 11:23:30 +0200 Subject: [PATCH 0749/1751] RootTreeReader: Allow to specialize data publishing via new callback --- .../Utils/include/DPLUtils/RootTreeReader.h | 83 +++++++++++++------ 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/Framework/Utils/include/DPLUtils/RootTreeReader.h b/Framework/Utils/include/DPLUtils/RootTreeReader.h index 3e60052df8b30..ba2624a88bfaf 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeReader.h +++ b/Framework/Utils/include/DPLUtils/RootTreeReader.h @@ -154,6 +154,20 @@ class GenericRootTreeReader /// start over at entry 0 Loop, }; + + /// A struct holding a callback to specialize publishing based on branch name. This might be useful + /// when the read data needs to be transformed before publishing. + /// The hook gets the following input: + /// name: name of branch (may be used for selecting filtering) + /// context: The processing context (so that we can snapshot or publish) + /// Output: The DPL output channel on which to publish + /// data: pointer to the data object read by the TreeReader + /// The hook should return true when publishing succeeded and false when the ordinary publishing procedure + /// should proceed. + struct SpecialPublishHook { + std::function<bool(std::string_view name, ProcessingContext& context, Output const&, char* data)> hook; + }; + // the key must not be of type const char* to make sure that the variable argument // list of the constructor can be parsed static_assert(std::is_same<KeyType, const char*>::value == false, "the key type must not be const char*"); @@ -189,7 +203,7 @@ class GenericRootTreeReader virtual ~BranchConfigurationInterface() = default; /// Setup the branch configuration, namely get the branch and class information from the tree - virtual void setup(TTree&) {} + virtual void setup(TTree&, SpecialPublishHook* h = nullptr) {} /// Run the reader process /// This will recursively run every level of the the branch configuration and fetch the object /// at position \a entry. The object is published via the DPL ProcessingContext. A creator callback @@ -226,20 +240,21 @@ class GenericRootTreeReader /// Setup branch configuration /// This is the virtal overload entry point to the upper most stage of the branch configuration - void setup(TTree& tree) override + void setup(TTree& tree, SpecialPublishHook* publishhook = nullptr) override { - setupInstance(tree); + setupInstance(tree, publishhook); } /// Run the setup, first recursively for all lower stages, and then the current stage /// This fetches the branch corresponding to the configured name - void setupInstance(TTree& tree) + void setupInstance(TTree& tree, SpecialPublishHook* publishhook = nullptr) { // recursing through the tree structure by simply using method of the previous type, // i.e. the base class method. if constexpr (STAGE > 1) { - PrevT::setupInstance(tree); + PrevT::setupInstance(tree, publishhook); } + mPublishHook = publishhook; // right now we allow the same key to appear for multiple branches mBranch = tree.GetBranch(mName.c_str()); @@ -292,30 +307,39 @@ class GenericRootTreeReader char* data = nullptr; mBranch->SetAddress(&data); mBranch->GetEntry(entry); - if (mSizeBranch != nullptr) { - size_t datasize = 0; - mSizeBranch->SetAddress(&datasize); - mSizeBranch->GetEntry(entry); - auto* buffer = reinterpret_cast<BinaryDataStoreType*>(data); - if (buffer->size() == datasize) { - LOG(INFO) << "branch " << mName << ": publishing binary chunk of " << datasize << " bytes(s)"; - snapshot(mKey, std::move(*buffer)); - } else { - LOG(ERROR) << "branch " << mName << ": inconsitent size of binary chunk " - << buffer->size() << " vs " << datasize; - BinaryDataStoreType empty; - snapshot(mKey, empty); - } - } else { - if constexpr (std::is_void<value_type>::value == true) { - // the default branch configuration publishes the object ROOT serialized - snapshot(mKey, std::move(ROOTSerializedByClass(*data, mClassInfo))); + + // execute hook if it was registered; if this return true do not proceed further + if (mPublishHook != nullptr && (*mPublishHook).hook(mName, context, Output{mKey.origin, mKey.description, mKey.subSpec, mKey.lifetime, std::move(stackcreator())}, data)) { + + } + // try to figureout when we need to do something special + else { + if (mSizeBranch != nullptr) { + size_t datasize = 0; + mSizeBranch->SetAddress(&datasize); + mSizeBranch->GetEntry(entry); + auto* buffer = reinterpret_cast<BinaryDataStoreType*>(data); + if (buffer->size() == datasize) { + LOG(INFO) << "branch " << mName << ": publishing binary chunk of " << datasize << " bytes(s)"; + snapshot(mKey, std::move(*buffer)); + } else { + LOG(ERROR) << "branch " << mName << ": inconsitent size of binary chunk " + << buffer->size() << " vs " << datasize; + BinaryDataStoreType empty; + snapshot(mKey, empty); + } } else { - // if type is specified in the branch configuration, the allocator API decides - // upon serialization - snapshot(mKey, *reinterpret_cast<value_type*>(data)); + if constexpr (std::is_void<value_type>::value == true) { + // the default branch configuration publishes the object ROOT serialized + snapshot(mKey, std::move(ROOTSerializedByClass(*data, mClassInfo))); + } else { + // if type is specified in the branch configuration, the allocator API decides + // upon serialization + snapshot(mKey, *reinterpret_cast<value_type*>(data)); + } } } + // cleanup the memory auto* delfunc = mClassInfo->GetDelete(); if (delfunc) { (*delfunc)(data); @@ -329,6 +353,7 @@ class GenericRootTreeReader TBranch* mBranch = nullptr; TBranch* mSizeBranch = nullptr; TClass* mClassInfo = nullptr; + SpecialPublishHook* mPublishHook = nullptr; }; /// branch definition structure @@ -372,7 +397,7 @@ class GenericRootTreeReader { mInput.SetCacheSize(0); parseConstructorArgs<0>(std::forward<Args>(args)...); - mBranchConfiguration->setup(mInput); + mBranchConfiguration->setup(mInput, mPublishHook); } /// add a file as source for the tree @@ -481,6 +506,8 @@ class GenericRootTreeReader mMaxEntries = def; } else if constexpr (std::is_same<U, PublishingMode>::value) { mPublishingMode = def; + } else if constexpr (std::is_same<U, SpecialPublishHook*>::value) { + mPublishHook = def; } else if constexpr (is_specialization<U, BranchDefinition>::value) { cargs.emplace_back(key_type(def.key), def.name); using type = BranchConfigurationElement<typename U::type, BASE>; @@ -522,6 +549,8 @@ class GenericRootTreeReader int mMaxEntries = -1; /// publishing mode PublishingMode mPublishingMode = PublishingMode::Single; + /// special user hook + SpecialPublishHook* mPublishHook = nullptr; }; using RootTreeReader = GenericRootTreeReader<rtr::DefaultKey>; From c28bef85b5d407d39c592b6b505d07f0c41c1b68 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 24 Sep 2020 12:04:35 +0200 Subject: [PATCH 0750/1751] TPC: new const labels in digitizer workflow Labels are now transported in shared memory as const flat buffer and written to ROOT file without copy. With this we are now able to digitize a full timeframe including labels. The RootTreeReader is given a new hook to specialize publishing data. This is applied to the conversion of flat labels to MCTruthContainer which is still expected by the TPC reco workflow. Next tasks will be the conversion of all read-only MCTruthContainer containers to ConstMCTruthContainer in the remaining workflow. --- .../IOMCTruthContainerView.h | 20 +++++ .../include/TPCWorkflow/PublisherSpec.h | 12 ++- Detectors/TPC/workflow/src/PublisherSpec.cxx | 4 +- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 23 ++++- .../src/TPCDigitRootWriterSpec.cxx | 85 +++++++++++++------ .../src/TPCDigitizerSpec.cxx | 6 +- 6 files changed, 112 insertions(+), 38 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h index 66c743feb834a..590524cd61e8f 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h +++ b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h @@ -49,9 +49,26 @@ class IOMCTruthContainerView adopt(input); } + ~IOMCTruthContainerView() + { + if (!mIsView) { + delete[] part1; + delete[] part2; + delete[] part3; + delete[] part4; + delete[] part5; + delete[] part6; + delete[] part7; + delete[] part8; + delete[] part9; + delete[] part10; + } + } + /// "adopt" (without taking ownership) from an existing buffer void adopt(gsl::span<const char> const input) { + mIsView = true; const auto delta = input.size() / N; N2 = input.size() - (N - 1) * delta; N1 = delta; @@ -104,6 +121,9 @@ class IOMCTruthContainerView const char* part9 = nullptr; //[N1] const char* part10 = nullptr; //[N2] + bool mIsView = false; //! if this was merely adopted from an existing container or actually owns the memory + // we need to know this for the destructor + template <typename Alloc> void copyhelper(const char* input, int size, std::vector<char, Alloc>& output) const { diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/PublisherSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/PublisherSpec.h index e2385e4f1c726..8a1673977d7f9 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/PublisherSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/PublisherSpec.h @@ -28,6 +28,7 @@ namespace tpc { using OutputSpec = framework::OutputSpec; +using Reader = o2::framework::RootTreeReader; struct PublisherConf { struct BranchOptionConfig { @@ -44,6 +45,7 @@ struct PublisherConf { OutputSpec mcoutput; std::vector<int> tpcSectors; std::vector<int> outputIds; + Reader::SpecialPublishHook* hook = nullptr; }; /// create a processor spec @@ -57,7 +59,7 @@ framework::DataProcessorSpec getPublisherSpec(PublisherConf const& config, bool auto mco = o2::framework::DataSpecUtils::asConcreteDataTypeMatcher(config.mcoutput); // a creator callback for the actual reader instance - auto creator = [dto, mco, propagateMC](const char* treename, const char* filename, int nofEvents, Reader::PublishingMode publishingMode, o2::header::DataHeader::SubSpecificationType subSpec, const char* branchname, const char* mcbranchname) { + auto creator = [dto, mco, propagateMC](const char* treename, const char* filename, int nofEvents, Reader::PublishingMode publishingMode, o2::header::DataHeader::SubSpecificationType subSpec, const char* branchname, const char* mcbranchname, Reader::SpecialPublishHook* publishhook = nullptr) { constexpr auto persistency = o2::framework::Lifetime::Timeframe; if (propagateMC) { return std::make_shared<Reader>(treename, @@ -66,13 +68,15 @@ framework::DataProcessorSpec getPublisherSpec(PublisherConf const& config, bool publishingMode, Output{mco.origin, mco.description, subSpec, persistency}, mcbranchname, - Reader::BranchDefinition<T>{Output{dto.origin, dto.description, subSpec, persistency}, branchname}); + Reader::BranchDefinition<T>{Output{dto.origin, dto.description, subSpec, persistency}, branchname}, + publishhook); } else { return std::make_shared<Reader>(treename, filename, nofEvents, publishingMode, - Reader::BranchDefinition<T>{Output{dto.origin, dto.description, subSpec, persistency}, branchname}); + Reader::BranchDefinition<T>{Output{dto.origin, dto.description, subSpec, persistency}, branchname}, + publishhook); } }; @@ -82,7 +86,7 @@ framework::DataProcessorSpec getPublisherSpec(PublisherConf const& config, bool namespace workflow_reader { using Reader = o2::framework::RootTreeReader; -using Creator = std::function<std::shared_ptr<Reader>(const char*, const char*, int, Reader::PublishingMode, o2::header::DataHeader::SubSpecificationType, const char*, const char*)>; +using Creator = std::function<std::shared_ptr<Reader>(const char*, const char*, int, Reader::PublishingMode, o2::header::DataHeader::SubSpecificationType, const char*, const char*, Reader::SpecialPublishHook*)>; } // namespace workflow_reader framework::DataProcessorSpec createPublisherSpec(PublisherConf const& config, bool propagateMC, workflow_reader::Creator creator); diff --git a/Detectors/TPC/workflow/src/PublisherSpec.cxx b/Detectors/TPC/workflow/src/PublisherSpec.cxx index 962e5ad028589..d6c787a37f024 100644 --- a/Detectors/TPC/workflow/src/PublisherSpec.cxx +++ b/Detectors/TPC/workflow/src/PublisherSpec.cxx @@ -138,8 +138,8 @@ DataProcessorSpec createPublisherSpec(PublisherConf const& config, bool propagat publishingMode, subSpec, clusterbranchname.c_str(), // name of data branch - mcbranchname.c_str() // name of mc label branch - ); + mcbranchname.c_str(), // name of mc label branch + config.hook); if (sectorMode == SectorMode::Full) { break; } diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 0d6d5c7eda855..80dc3e2f4c515 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -33,6 +33,8 @@ #include "DataFormatsTPC/CompressedClusters.h" #include "DataFormatsTPC/ZeroSuppression.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "DataFormatsTPC/Helpers.h" #include "DataFormatsTPC/ZeroSuppression.h" @@ -143,6 +145,25 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec // also the dispatch trigger needs to be updated. if (inputType == InputType::Digits) { using Type = std::vector<o2::tpc::Digit>; + + // We provide a special publishing method for labels which have been stored in a split format and need + // to be transformed into a contiguous shareable container before publishing. For other branches/types this returns + // false and the generic RootTreeWriter publishing proceeds + static Reader::SpecialPublishHook hook{[](std::string_view name, ProcessingContext& context, o2::framework::Output const& output, char* data) -> bool { + if (TString(name.data()).Contains("TPCDigitMCTruth")) { + auto storedlabels = reinterpret_cast<o2::dataformats::IOMCTruthContainerView const*>(data); + o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel> flatlabels; + storedlabels->copyandflatten(flatlabels); + LOG(INFO) << "PUBLISHING CONST LABELS " << flatlabels.getNElements(); + // for the moment make real MCTruthContainer since this is still expected by reconstruction + o2::dataformats::MCTruthContainer<o2::MCCompLabel> labels; + labels.restore_from(flatlabels.data(), flatlabels.size()); + context.outputs().snapshot(output, labels); + return true; + } + return false; + }}; + specs.emplace_back(o2::tpc::getPublisherSpec<Type>(PublisherConf{ "tpc-digit-reader", "o2sim", @@ -152,7 +173,7 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec OutputSpec{"TPC", "DIGITSMCTR"}, tpcSectors, laneConfiguration, - }, + &hook}, propagateMC)); } else if (inputType == InputType::ClustersHardware) { specs.emplace_back(o2::tpc::getPublisherSpec(PublisherConf{ diff --git a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx index c3f1ee00b2258..c0d48544cf16d 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx @@ -24,7 +24,8 @@ #include "DataFormatsTPC/Digit.h" #include "TPCSimulation/CommonMode.h" #include <SimulationDataFormat/MCCompLabel.h> -#include <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> +#include <SimulationDataFormat/IOMCTruthContainerView.h> #include <TFile.h> #include <TTree.h> #include <TBranch.h> @@ -55,31 +56,41 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur // the callback to be set as hook for custom action when the writer is closed auto finishWriting = [](TFile* outputfile, TTree* outputtree) { // check/verify number of entries (it should be same in all branches) + auto leavelist = outputtree->GetListOfLeaves(); + for (auto entry : *leavelist) { + if (TString(entry->GetName()).Contains("_TMP")) { + leavelist->Remove(entry); + } + } // will return a TObjArray const auto brlist = outputtree->GetListOfBranches(); int entries = -1; // init to -1 (as unitialized) for (TObject* entry : *brlist) { auto br = static_cast<TBranch*>(entry); + if (TString(entry->GetName()).Contains("_TMP")) { + br->DeleteBaskets("all"); + brlist->Remove(br); + continue; + } + int brentries = br->GetEntries(); - if (entries == -1) { - entries = brentries; - } else { - if (brentries != entries && !TString(br->GetName()).Contains("CommonMode")) { - LOG(WARNING) << "INCONSISTENT NUMBER OF ENTRIES IN BRANCH " << br->GetName() << ": " << entries << " vs " << brentries; - } + entries = std::max(entries, brentries); + if (brentries != entries && !TString(br->GetName()).Contains("CommonMode")) { + LOG(WARNING) << "INCONSISTENT NUMBER OF ENTRIES IN BRANCH " << br->GetName() << ": " << entries << " vs " << brentries; } } if (entries > 0) { + LOG(INFO) << "Setting entries to " << entries; outputtree->SetEntries(entries); + // outputtree->Write("", TObject::kOverwrite); + outputfile->Close(); } - outputtree->Write(); - outputfile->Close(); }; //branch definitions for RootTreeWriter spec using DigitsOutputType = std::vector<o2::tpc::Digit>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; using CommonModeOutputType = std::vector<o2::tpc::CommonMode>; // extracts the sector from header of an input @@ -156,6 +167,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur if (sector >= 0) { LOG(INFO) << "DIGIT SIZE " << digiData.size(); const auto& trigS = (*trigP2Sect.get())[sector]; + int entries = 0; if (!trigS.size()) { std::runtime_error("Digits for sector " + std::to_string(sector) + " are received w/o info on grouping in triggers"); } else { // check consistency of Ndigits with that of expected from the trigger @@ -171,6 +183,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur auto ptr = &digiData; branch.SetAddress(&ptr); branch.Fill(); + entries++; branch.ResetAddress(); branch.DropBaskets("all"); } else { // triggered mode (>1 entries will be written) @@ -183,20 +196,33 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur digGroup.emplace_back(digiData[group.getFirstEntry() + i]); // fetch digits of given trigger } branch.Fill(); + entries++; } branch.ResetAddress(); branch.DropBaskets("all"); } } + auto tree = branch.GetTree(); + tree->SetEntries(entries); + tree->Write("", TObject::kOverwrite); } }; // handler for labels // TODO: this is almost a copy of the above, reduce to a single methods with amends - auto fillLabels = [extractSector, trigP2Sect](TBranch& branch, MCLabelContainer const& labeldata, DataRef const& ref) { + auto fillLabels = [extractSector, trigP2Sect](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& ref) { + o2::dataformats::IOMCTruthContainerView outputcontainer; + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> labeldata(labelbuffer); + // first of all redefine the output format (special to labels) + auto tree = branch.GetTree(); auto sector = extractSector(ref); + std::stringstream str; + str << "TPCDigitMCTruth_" << sector; + auto br = tree->Branch(str.str().c_str(), &outputcontainer); + auto const* dh = DataRefUtils::getHeader<DataHeader*>(ref); LOG(INFO) << "HAVE LABEL DATA FOR SECTOR " << sector << " ON CHANNEL " << dh->subSpecification; + int entries = 0; if (sector >= 0) { LOG(INFO) << "MCTRUTH ELEMENTS " << labeldata.getIndexedSize() << " WITH " << labeldata.getNElements() << " LABELS"; @@ -213,27 +239,30 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur } { if (trigS.size() == 1) { // just 1 entry (continous mode?), use labels directly - auto ptr = &labeldata; - branch.SetAddress(&ptr); - branch.Fill(); - branch.ResetAddress(); - branch.DropBaskets("all"); + outputcontainer.adopt(labelbuffer); + br->Fill(); + br->ResetAddress(); + entries = 1; } else { o2::dataformats::MCTruthContainer<o2::MCCompLabel> lblGroup; // labels for group of digits related to single trigger - auto ptr = &lblGroup; - branch.SetAddress(&ptr); for (auto const& group : trigS) { lblGroup.clear(); for (int i = 0; i < group.getEntries(); i++) { auto lbls = labeldata.getLabels(group.getFirstEntry() + i); lblGroup.addElements(i, lbls); } - branch.Fill(); + // init the output container + std::vector<char> flatbuffer; + lblGroup.flatten_to(flatbuffer); + outputcontainer.adopt(flatbuffer); + br->Fill(); + entries++; } - branch.ResetAddress(); - branch.DropBaskets("all"); + br->ResetAddress(); } } + tree->SetEntries(entries); + tree->Write("", TObject::kOverwrite); } }; @@ -252,13 +281,13 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur getIndex, getName}; - auto labelsdef = BranchDefinition<MCLabelContainer>{InputSpec{"labelinput", ConcreteDataTypeMatcher{"TPC", "DIGITSMCTR"}}, - "TPCDigitMCTruth", "labels-branch-name", - // this branch definition is disabled if MC labels are not processed - (mctruth ? laneConfiguration.size() : 0), - fillLabels, - getIndex, - getName}; + auto labelsdef = BranchDefinition<std::vector<char>>{InputSpec{"labelinput", ConcreteDataTypeMatcher{"TPC", "DIGITSMCTR"}}, + "TPCDigitMCTruth_TMP", "labels-branch-name", + // this branch definition is disabled if MC labels are not processed + (mctruth ? laneConfiguration.size() : 0), + fillLabels, + getIndex, + getName}; auto commddef = BranchDefinition<CommonModeOutputType>{InputSpec{"commonmode", ConcreteDataTypeMatcher{"TPC", "COMMONMODE"}}, "TPCCommonMode", "common-mode-branch-name", diff --git a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx index 701fc6c83fa3c..e5e4308e2f4a8 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx @@ -23,6 +23,7 @@ #include "TSystem.h" #include <SimulationDataFormat/MCCompLabel.h> #include <SimulationDataFormat/MCTruthContainer.h> +#include <SimulationDataFormat/ConstMCTruthContainer.h> #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsTPC/TPCSectorHeader.h" @@ -220,9 +221,8 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer o2::tpc::TPCSectorHeader header{sector}; header.activeSectors = activeSectors; if (mWithMCTruth) { - pc.outputs().snapshot(Output{"TPC", "DIGITSMCTR", static_cast<SubSpecificationType>(dh->subSpecification), - Lifetime::Timeframe, header}, - const_cast<o2::dataformats::MCTruthContainer<o2::MCCompLabel>&>(labels)); + auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{"TPC", "DIGITSMCTR", static_cast<SubSpecificationType>(dh->subSpecification), Lifetime::Timeframe, header}); + labels.flatten_to(sharedlabels); } }; // lambda that snapshots digits grouping (triggers) to be sent out; prepares and attaches header with sector information From ba34ab4608d5079eeb1e8b31365eca38afebaab3 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Thu, 3 Sep 2020 09:33:14 +0200 Subject: [PATCH 0751/1751] TPCClusterFinder: Add gain calibration. --- Detectors/TPC/base/include/TPCBase/Mapper.h | 1 + .../reconstruction/test/testGPUCATracking.cxx | 3 + Detectors/TPC/workflow/src/CATrackerSpec.cxx | 16 +++ GPU/Common/GPUCommonMath.h | 5 + GPU/GPUTracking/Base/GPUConstantMem.h | 7 + GPU/GPUTracking/Base/GPUDataTypes.h | 2 + GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/CMakeLists.txt | 1 + GPU/GPUTracking/Global/GPUChainTracking.cxx | 6 + GPU/GPUTracking/Global/GPUChainTracking.h | 3 + GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 10 +- GPU/GPUTracking/Interface/GPUO2Interface.cxx | 1 + .../TPCClusterFinder/GPUTPCCFDecodeZS.cxx | 8 +- .../TPCClusterFinder/GPUTPCClusterFinder.h | 3 + .../TPCClusterFinder/TPCCFCalibration.cxx | 39 ++++++ .../TPCClusterFinder/TPCCFCalibration.h | 131 ++++++++++++++++++ .../TPCClusterFinder/clusterFinderDefs.h | 1 + 17 files changed, 235 insertions(+), 3 deletions(-) create mode 100644 GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.cxx create mode 100644 GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h diff --git a/Detectors/TPC/base/include/TPCBase/Mapper.h b/Detectors/TPC/base/include/TPCBase/Mapper.h index f7905e0d32982..c810ac1e6ee5a 100644 --- a/Detectors/TPC/base/include/TPCBase/Mapper.h +++ b/Detectors/TPC/base/include/TPCBase/Mapper.h @@ -315,6 +315,7 @@ class Mapper } int getNumberOfPadsInRowSector(int row) const { return mMapNumberOfPadsPerRow[row]; } + int getPadOffsetInRowSector(int row) const { return mMapPadOffsetPerRow[row]; } int getNumberOfPadsInRowROC(int roc, int row) const { return mMapNumberOfPadsPerRow[row + (roc % 72 >= getNumberOfIROCs()) * mNumberOfPadRowsIROC]; diff --git a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx index 162d94d7de3e6..46a6c19a0bcf0 100644 --- a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx @@ -27,6 +27,7 @@ #include "TPCFastTransform.h" #include "TPCdEdxCalibrationSplines.h" #include "GPUO2InterfaceConfiguration.h" +#include "TPCCFCalibration.h" using namespace o2::gpu; @@ -76,6 +77,8 @@ BOOST_AUTO_TEST_CASE(CATracking_test1) config.configCalib.fastTransform = fastTransform.get(); std::unique_ptr<o2::gpu::TPCdEdxCalibrationSplines> dEdxSplines(new TPCdEdxCalibrationSplines); config.configCalib.dEdxSplines = dEdxSplines.get(); + std::unique_ptr<TPCCFCalibration> tpcCalibration(new TPCCFCalibration{}); + config.configCalib.tpcCalibration = tpcCalibration.get(); tracker.initialize(config); std::vector<ClusterNativeContainer> cont(constants::MAXGLOBALPADROW); diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index a56aa3246254a..a238248aa9d77 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -42,15 +42,18 @@ #include "DetectorsRaw/HBFUtils.h" #include "TPCBase/RDHUtils.h" #include "GPUO2InterfaceConfiguration.h" +#include "TPCCFCalibration.h" #include "GPUDisplayBackend.h" #ifdef GPUCA_BUILD_EVENT_DISPLAY #include "GPUDisplayBackendGlfw.h" #endif #include "DataFormatsParameters/GRPObject.h" #include "TPCBase/Sector.h" +#include "TPCBase/Utils.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "Algorithm/Parser.h" +#include <boost/filesystem.hpp> #include <memory> // for make_shared #include <vector> #include <iomanip> @@ -89,6 +92,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int std::unique_ptr<GPUDisplayBackend> displayBackend; std::unique_ptr<TPCFastTransform> fastTransform; std::unique_ptr<TPCdEdxCalibrationSplines> dEdxSplines; + std::unique_ptr<TPCCFCalibration> tpcCalibration; int verbosity = 1; std::vector<int> clusterOutputIds; bool readyToQuit = false; @@ -195,6 +199,18 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int config.configCalib.dEdxSplines = processAttributes->dEdxSplines.get(); + if (boost::filesystem::exists(confParam.gainCalibFile)) { + LOG(INFO) << "Loading tpc gain correction from file " << confParam.gainCalibFile; + const auto* gainMap = o2::tpc::utils::readCalPads(confParam.gainCalibFile, "GainMap")[0]; + processAttributes->tpcCalibration.reset(new TPCCFCalibration{*gainMap}); + } else { + if (not confParam.gainCalibFile.empty()) { + LOG(WARN) << "Couldn't find tpc gain correction file " << confParam.gainCalibFile << ". Not applying any gain correction."; + } + processAttributes->tpcCalibration.reset(new TPCCFCalibration{}); + } + config.configCalib.tpcCalibration = processAttributes->tpcCalibration.get(); + // Sample code what needs to be done for the TRD Geometry, when we extend this to TRD tracking. /*o2::base::GeometryManager::loadGeometry(); o2::trd::TRDGeometry gm; diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 71fc0517c2afd..2720a741c021a 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -47,6 +47,11 @@ class GPUCommonMath GPUd() static T MaxWithRef(T x, T y, S refX, S refY, R& r); template <class T, class S, class R> GPUd() static T MaxWithRef(T x, T y, T z, T w, S refX, S refY, S refZ, S refW, R& r); + template <class T> + GPUdi() static T Clamp(const T v, const T lo, const T hi) + { + return Max(lo, Min(v, hi)); + } GPUhdni() static float Sqrt(float x); GPUd() static float FastInvSqrt(float x); template <class T> diff --git a/GPU/GPUTracking/Base/GPUConstantMem.h b/GPU/GPUTracking/Base/GPUConstantMem.h index 2fecd58fd725b..115e957ee08b1 100644 --- a/GPU/GPUTracking/Base/GPUConstantMem.h +++ b/GPU/GPUTracking/Base/GPUConstantMem.h @@ -133,6 +133,13 @@ GPUdi() void GPUProcessor::raiseError(unsigned int code, unsigned int param1, un GetConstantMem()->errorCodes.raiseError(code, param1, param2, param3); } +#if defined(GPUCA_NOCOMPAT_ALLCINT) && (!defined(GPUCA_GPULIBRARY) || !defined(GPUCA_ALIROOT_LIB)) && defined(HAVE_O2HEADERS) +GPUd() float GPUTPCClusterFinder::getGainCorrection(tpccf::Row row, tpccf::Pad pad) const +{ + return GetConstantMem()->calibObjects.tpcCalibration->getGainCorrection(mISlice, row, pad); +} +#endif + } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index bea67a6f06113..c3b5919206a41 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -67,6 +67,7 @@ namespace gpu { class TPCFastTransform; class TPCdEdxCalibrationSplines; +class TPCCFCalibration; } // namespace gpu } // namespace GPUCA_NAMESPACE @@ -171,6 +172,7 @@ struct GPUCalibObjectsTemplate { typename S<o2::base::MatLayerCylSet>::type* matLUT = nullptr; typename S<o2::trd::TRDGeometryFlat>::type* trdGeometry = nullptr; typename S<TPCdEdxCalibrationSplines>::type* dEdxSplines = nullptr; + typename S<TPCCFCalibration>::type* tpcCalibration = nullptr; }; typedef GPUCalibObjectsTemplate<DefaultPtr> GPUCalibObjects; typedef GPUCalibObjectsTemplate<ConstPtr> GPUCalibObjectsConst; diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index a7e91bd89d488..e64746adcbbae 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -259,6 +259,7 @@ AddOption(runDisplay, bool, false, "", 0, "Run event visualization after process AddOption(dEdxFile, std::string, "", "", 0, "File name of dEdx Splines file") AddOption(transformationFile, std::string, "", "", 0, "File name of TPC fast transformation map") AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") +AddOption(gainCalibFile, std::string, "", "", 0, "File name of TPC pad gain calibration") AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") AddOption(outputBufferSize, unsigned long, 200000000ul, "", 0, "Size of the output buffers to be allocated") AddOption(synchronousProcessing, bool, false, "", 0, "Apply performance shortcuts for synchronous processing, disable unneeded steps") diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index cd942a7adfd04..9d4cb8125c237 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -170,6 +170,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx TPCClusterFinder/GPUTPCCFDecodeZS.cxx TPCClusterFinder/GPUTPCCFGather.cxx + TPCClusterFinder/TPCCFCalibration.cxx dEdx/TPCdEdxCalibrationSplines.cxx) set(SRCS_NO_H ${SRCS_NO_H} diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 04d58685999c6..e09ab06e63751 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -374,6 +374,9 @@ int GPUChainTracking::Init() memcpy((void*)mFlatObjectsShadow.mCalibObjects.trdGeometry, (const void*)processors()->calibObjects.trdGeometry, sizeof(*processors()->calibObjects.trdGeometry)); mFlatObjectsShadow.mCalibObjects.trdGeometry->clearInternalBufferPtr(); } + if (processors()->calibObjects.tpcCalibration) { + memcpy((void*)mFlatObjectsShadow.mCalibObjects.tpcCalibration, (const void*)processors()->calibObjects.tpcCalibration, sizeof(*processors()->calibObjects.tpcCalibration)); + } #endif TransferMemoryResourceLinkToGPU(RecoStep::NoRecoStep, mFlatObjectsShadow.mMemoryResFlat); WriteToConstantMemory(RecoStep::NoRecoStep, (char*)&processors()->calibObjects - (char*)processors(), &mFlatObjectsDevice.mCalibObjects, sizeof(mFlatObjectsDevice.mCalibObjects), -1); // First initialization, for users not using RunChain @@ -427,6 +430,9 @@ void* GPUChainTracking::GPUTrackingFlatObjects::SetPointersFlatObjects(void* mem computePointerWithAlignment(mem, mCalibObjects.fastTransform, 1); computePointerWithAlignment(mem, mTpcTransformBuffer, mChainTracking->GetTPCTransform()->getFlatBufferSize()); } + if (mChainTracking->GetTPCCalibration()) { + computePointerWithAlignment(mem, mCalibObjects.tpcCalibration, 1); + } #ifdef HAVE_O2HEADERS if (mChainTracking->GetdEdxSplines()) { computePointerWithAlignment(mem, mCalibObjects.dEdxSplines, 1); diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index b296c16136ae2..70ec3d49cee99 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -151,6 +151,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega // Getters / setters for parameters const TPCFastTransform* GetTPCTransform() const { return processors()->calibObjects.fastTransform; } + const TPCCFCalibration* GetTPCCalibration() const { return processors()->calibObjects.tpcCalibration; } const TPCdEdxCalibrationSplines* GetdEdxSplines() const { return processors()->calibObjects.dEdxSplines; } const o2::base::MatLayerCylSet* GetMatLUT() const { return processors()->calibObjects.matLUT; } const GPUTRDGeometry* GetTRDGeometry() const { return (GPUTRDGeometry*)processors()->calibObjects.trdGeometry; } @@ -159,6 +160,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void SetMatLUT(std::unique_ptr<o2::base::MatLayerCylSet>&& lut); void SetTRDGeometry(std::unique_ptr<o2::trd::TRDGeometryFlat>&& geo); void SetTPCFastTransform(const TPCFastTransform* tpcFastTransform) { processors()->calibObjects.fastTransform = tpcFastTransform; } + void SetTPCCFCalibration(const TPCCFCalibration* tpcCalibration) { processors()->calibObjects.tpcCalibration = tpcCalibration; } void SetdEdxSplines(const TPCdEdxCalibrationSplines* dEdxSplines) { processors()->calibObjects.dEdxSplines = dEdxSplines; } void SetMatLUT(const o2::base::MatLayerCylSet* lut) { processors()->calibObjects.matLUT = lut; } void SetTRDGeometry(const o2::trd::TRDGeometryFlat* geo) { processors()->calibObjects.trdGeometry = geo; } @@ -226,6 +228,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega // Ptr to detector / calibration objects std::unique_ptr<TPCFastTransform> mTPCFastTransformU; // Global TPC fast transformation object + std::unique_ptr<TPCCFCalibration> mTPCCalibrationU; // TPC gain calibration and cluster finder parameters std::unique_ptr<TPCdEdxCalibrationSplines> mdEdxSplinesU; // TPC dEdx calibration splines std::unique_ptr<o2::base::MatLayerCylSet> mMatLUTU; // Material Lookup Table std::unique_ptr<o2::trd::TRDGeometryFlat> mTRDGeometryU; // TRD Geometry diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index 2e327e8e5e29f..9a918c3ceed36 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -224,7 +224,11 @@ void GPUChainTracking::DumpSettings(const char* dir) f += "tpctransform.dump"; DumpFlatObjectToFile(processors()->calibObjects.fastTransform, f.c_str()); } - + if (processors()->calibObjects.tpcCalibration != nullptr) { + f = dir; + f += "tpccalibration.dump"; + DumpStructToFile(processors()->calibObjects.tpcCalibration, f.c_str()); + } #ifdef HAVE_O2HEADERS if (processors()->calibObjects.dEdxSplines != nullptr) { f = dir; @@ -252,6 +256,10 @@ void GPUChainTracking::ReadSettings(const char* dir) f += "tpctransform.dump"; mTPCFastTransformU = ReadFlatObjectFromFile<TPCFastTransform>(f.c_str()); processors()->calibObjects.fastTransform = mTPCFastTransformU.get(); + f = dir; + f += "tpccalibration.dump"; + mTPCCalibrationU = ReadStructFromFile<TPCCFCalibration>(f.c_str()); + processors()->calibObjects.tpcCalibration = mTPCCalibrationU.get(); #ifdef HAVE_O2HEADERS f = dir; f += "dedxsplines.dump"; diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 629c2de0fd830..3fc2220dd146d 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -52,6 +52,7 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) } mRec->SetSettings(&mConfig->configEvent, &mConfig->configReconstruction, &mConfig->configProcessing, &mConfig->configWorkflow); mChain->SetTPCFastTransform(mConfig->configCalib.fastTransform); + mChain->SetTPCCFCalibration(mConfig->configCalib.tpcCalibration); mChain->SetdEdxSplines(mConfig->configCalib.dEdxSplines); mChain->SetMatLUT(mConfig->configCalib.matLUT); mChain->SetTRDGeometry(mConfig->configCalib.trdGeometry); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx index 6314fff368122..1b17d0a8d0ffa 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx @@ -165,11 +165,15 @@ GPUdii() void GPUTPCCFDecodeZS::decode(GPUTPCClusterFinder& clusterer, GPUShared const CfFragment& fragment = clusterer.mPmemory->fragment; TPCTime globalTime = timeBin + l; bool inFragment = fragment.contains(globalTime); - ChargePos pos(Row(rowOffset + m), Pad(pad++), inFragment ? fragment.toLocal(globalTime) : INVALID_TIME_BIN); + Row row = rowOffset + m; + ChargePos pos(row, Pad(pad), inFragment ? fragment.toLocal(globalTime) : INVALID_TIME_BIN); positions[nDigitsTmp++] = pos; if (inFragment) { - chargeMap[pos] = PackedCharge(float(byte & mask) * decodeBitsFactor); + float q = float(byte & mask) * decodeBitsFactor; + q *= clusterer.getGainCorrection(row, pad); + chargeMap[pos] = PackedCharge(q); } + pad++; byte = byte >> decodeBits; bits -= decodeBits; seqLen--; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index c29aff7887392..b9677e9357970 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -18,6 +18,7 @@ #include "GPUProcessor.h" #include "GPUDataTypes.h" #include "CfFragment.h" +#include "TPCCFCalibration.h" namespace o2 { @@ -131,6 +132,8 @@ class GPUTPCClusterFinder : public GPUProcessor short mZSOffsetId = -1; short mOutputId = -1; + GPUdi() float getGainCorrection(tpccf::Row, tpccf::Pad) const; + #ifndef GPUCA_GPUCODE void DumpDigits(std::ostream& out); void DumpChargeMap(std::ostream& out, std::string_view); diff --git a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.cxx b/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.cxx new file mode 100644 index 0000000000000..0f260cb76ee5b --- /dev/null +++ b/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.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 TPCCFCalibration.cxx +/// \author Felix Weiglhofer + +#include "TPCCFCalibration.h" + +#include "GPUTPCGeometry.h" +#include "DataFormatsTPC/Constants.h" +#include "TPCBase/CalDet.h" + +using namespace GPUCA_NAMESPACE::gpu; + +TPCCFCalibration::TPCCFCalibration() +{ + GPUTPCGeometry geo{}; + int offset = 0; + for (int r = 0; r < TPC_NUM_OF_ROWS; r++) { + mPadOffsetPerRow[r] = offset; + offset += geo.NPads(r); + } +} + +TPCCFCalibration::TPCCFCalibration(const o2::tpc::CalDet<float>& gainMap) : TPCCFCalibration() +{ + for (int sector = 0; sector < o2::tpc::constants::MAXSECTOR; sector++) { + for (int p = 0; p < TPC_PADS_IN_SECTOR; p++) { + mGainCorrection[sector].set(p, gainMap.getValue(sector, p)); + } + } +} diff --git a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h b/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h new file mode 100644 index 0000000000000..b634b714efc4d --- /dev/null +++ b/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h @@ -0,0 +1,131 @@ +// 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 TPCCFCalibration.h +/// \author Felix Weiglhofer + +#ifndef O2_GPU_TPC_CF_CALIBRATION_H +#define O2_GPU_TPC_CF_CALIBRATION_H + +#include "clusterFinderDefs.h" +#include "GPUCommonMath.h" + +namespace o2::tpc +{ +template <class T> +class CalDet; +} // namespace o2::tpc + +namespace GPUCA_NAMESPACE::gpu +{ + +template <typename T> +struct TPCPadGainCorrectionStepNum { +}; + +template <> +struct TPCPadGainCorrectionStepNum<unsigned char> { + static constexpr int value = 254; +}; + +template <> +struct TPCPadGainCorrectionStepNum<unsigned short> { + static constexpr int value = 65534; +}; + +struct TPCCFCalibration { + public: +#ifndef GPUCA_GPUCODE + TPCCFCalibration(); + TPCCFCalibration(const o2::tpc::CalDet<float>&); +#endif + + GPUdi() void setGainCorrection(int sector, tpccf::Row row, tpccf::Pad pad, float c) + { + mGainCorrection[sector].set(globalPad(row, pad), c); + } + + GPUdi() float getGainCorrection(int sector, tpccf::Row row, tpccf::Pad pad) const + { + return mGainCorrection[sector].get(globalPad(row, pad)); + } + + private: + template <typename T = unsigned short> + class PadGainCorrection + { + + public: + constexpr static float MinCorrectionFactor = 0.f; + constexpr static float MaxCorrectionFactor = 2.f; + constexpr static int NumOfSteps = TPCPadGainCorrectionStepNum<T>::value; + + GPUdi() PadGainCorrection() + { + reset(); + } + + GPUdi() void set(unsigned short globalPad, float c) + { + at(globalPad) = pack(c); + } + + GPUdi() float get(unsigned short globalPad) const + { + return unpack(at(globalPad)); + } + + GPUd() void reset() + { + for (unsigned short p = 0; p < TPC_PADS_IN_SECTOR; p++) { + set(p, 1.0f); + } + } + + private: + GPUd() static T pack(float f) + { + f = CAMath::Clamp(f, MinCorrectionFactor, MaxCorrectionFactor); + f -= MinCorrectionFactor; + f *= float(NumOfSteps); + f /= (MaxCorrectionFactor - MinCorrectionFactor); + return CAMath::Nint(f); + } + + GPUd() static float unpack(T c) + { + return MinCorrectionFactor + (MaxCorrectionFactor - MinCorrectionFactor) * float(c) / float(NumOfSteps); + } + + T mGainCorrection[TPC_PADS_IN_SECTOR]; + + GPUdi() T& at(unsigned short globalPad) + { + return mGainCorrection[globalPad]; + } + + GPUdi() const T& at(unsigned short globalPad) const + { + return mGainCorrection[globalPad]; + } + }; + + unsigned short mPadOffsetPerRow[TPC_NUM_OF_ROWS]; + PadGainCorrection<unsigned short> mGainCorrection[TPC_SECTORS]; + + GPUdi() unsigned short globalPad(tpccf::Row row, tpccf::Pad pad) const + { + return mPadOffsetPerRow[row] + pad; + } +}; + +} // namespace GPUCA_NAMESPACE::gpu + +#endif diff --git a/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h b/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h index 6c3a78128c296..2b18d7e243b70 100644 --- a/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h +++ b/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h @@ -50,6 +50,7 @@ using ulong = unsigned long; #define TPC_PADS_PER_ROW 138 #define TPC_PADS_PER_ROW_PADDED (TPC_PADS_PER_ROW + PADDING_PAD) #define TPC_NUM_OF_PADS (TPC_NUM_OF_ROWS * TPC_PADS_PER_ROW_PADDED + PADDING_PAD) +#define TPC_PADS_IN_SECTOR 14560 #define TPC_MAX_FRAGMENT_LEN 4000 #define TPC_MAX_FRAGMENT_LEN_PADDED (TPC_MAX_FRAGMENT_LEN + 2 * PADDING_TIME) From 955409d384704b621b82d84bc32302efe62a293b Mon Sep 17 00:00:00 2001 From: Sean Murray <hamiltonthomas@gmail.com> Date: Thu, 10 Sep 2020 15:40:18 +0200 Subject: [PATCH 0752/1751] fix default trapconfig and outputs --- .../include/TRDSimulation/TrapConfig.h | 3 + Detectors/TRD/simulation/src/TrapConfig.cxx | 46 ++++++++++++- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 69 +++---------------- 3 files changed, 58 insertions(+), 60 deletions(-) diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h index c4ea97ce69fbb..926997cad942d 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h @@ -675,6 +675,9 @@ class TrapConfig const std::array<int, 3> mgkRegisterAddressBlockSize = {0x0400, 0x0200, 0x0004}; std::string mTrapConfigName; std::string mTrapConfigVersion; + void PrintDmemValue3(TrapConfig::TrapDmemWord* trapval, std::ofstream& output); + void PrintRegisterValue3(TrapConfig::TrapRegister* trapval, std::ofstream& output); + void DumpTrapConfig2File(std::string filename); private: // TrapConfig& operator=(const TrapConfig& rhs); // not implemented diff --git a/Detectors/TRD/simulation/src/TrapConfig.cxx b/Detectors/TRD/simulation/src/TrapConfig.cxx index f9fbf83b15774..58da7f1398b3a 100644 --- a/Detectors/TRD/simulation/src/TrapConfig.cxx +++ b/Detectors/TRD/simulation/src/TrapConfig.cxx @@ -12,8 +12,8 @@ // // // TRAP config // // // -// Author: J. Klein (Jochen.Klein@cern.ch) // -// Lots of mods by S. Murray (murrays@cern.ch) // +// Author: J. Klein (Jochen.Klein@cern.ch) (run2 version // +// S. Murray (murrays@cern.ch) // //////////////////////////////////////////////////////////////////////////// #include "TRDBase/TRDGeometry.h" @@ -997,6 +997,48 @@ void TrapConfig::TrapRegister::initfromrun2(const char* name, int addr, int nBit //LOG(fatal) << "Re-initialising an existing TRAP register"; } +void TrapConfig::PrintDmemValue3(TrapConfig::TrapDmemWord* trapval, std::ofstream& output) +{ + output << "\t AllocationMode : " << trapval->getAllocMode() << std::endl; + output << "\t Array size : " << trapval->getDataSize() << std::endl; + for (int dataarray = 0; dataarray < trapval->getDataSize(); dataarray++) { + output << "\t " << trapval->getDataRaw(dataarray) << " : valid : " << trapval->getValidRaw(dataarray) << std::endl; + } +} + +void TrapConfig::PrintRegisterValue3(TrapConfig::TrapRegister* trapval, std::ofstream& output) +{ + output << "\t AllocationMode : " << trapval->getAllocMode() << std::endl; + output << "\t Array size : " << trapval->getDataSize() << std::endl; + for (int dataarray = 0; dataarray < trapval->getDataSize(); dataarray++) { + output << "\t " << trapval->getDataRaw(dataarray) << " : valid : " << trapval->getValidRaw(dataarray) << std::endl; + } +} + +void TrapConfig::DumpTrapConfig2File(std::string filename) +{ + std::ofstream outfile(filename); + outfile << "Trap Registers : " << std::endl; + for (int regvalue = 0; regvalue < TrapConfig::kLastReg; regvalue++) { + outfile << " Trap : " << mRegisterValue[regvalue].getName() + << " at : 0x " << std::hex << mRegisterValue[regvalue].getAddr() << std::dec + << " with nbits : " << mRegisterValue[regvalue].getNbits() + << " and reset value of : " << mRegisterValue[regvalue].getResetValue() << std::endl; + // now for the inherited AliTRDtrapValue members; + PrintRegisterValue3(&mRegisterValue[regvalue], outfile); + } + + // outfile << "done with regiser values now for dmemwords" << std::endl; + outfile << "DMEM Words : " << std::endl; + for (int dmemwords = 0; dmemwords < TrapConfig::mgkDmemWords; dmemwords++) { + // copy fName, fAddr + // inherited from trapvalue : fAllocMode, fSize fData and fValid + // trapconfig->mDmem[dmemwords].mName= run2config->fDmem[dmemwords].fName; // this gets set on setting the address + outfile << "Name : " << mDmem[dmemwords].getName() << " :address : " << mDmem[dmemwords].getAddress() << std::endl; + PrintDmemValue3(&mDmem[dmemwords], outfile); + } +} + void TrapConfig::configureOnlineGains() { // we dont want to do this anymore .... but here for future reference. diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index a7ec13c7a3e98..1e3676e69212c 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -156,45 +156,6 @@ TrapConfig* TRDDPLTrapSimulatorTask::getTrapConfig() } // end of else from if mTrapConfig } -void PrintDmemValue3(TrapConfig::TrapDmemWord* trapval, std::ofstream& output) -{ - output << "\t AllocationMode : " << trapval->getAllocMode() << std::endl; - output << "\t Array size : " << trapval->getDataSize() << std::endl; - for (int dataarray = 0; dataarray < trapval->getDataSize(); dataarray++) { - output << "\t " << trapval->getDataRaw(dataarray) << " : valid : " << trapval->getValidRaw(dataarray) << std::endl; - } -} -void PrintRegisterValue3(TrapConfig::TrapRegister* trapval, std::ofstream& output) -{ - output << "\t AllocationMode : " << trapval->getAllocMode() << std::endl; - output << "\t Array size : " << trapval->getDataSize() << std::endl; - for (int dataarray = 0; dataarray < trapval->getDataSize(); dataarray++) { - output << "\t " << trapval->getDataRaw(dataarray) << " : valid : " << trapval->getValidRaw(dataarray) << std::endl; - } -} -void PrintTrapConfigAsStored3(TrapConfig* trapconfig) -{ - std::ofstream run3config("run3trapconfig-AsStored-insidedpl.txt"); - run3config << "Trap Registers : " << std::endl; - for (int regvalue = 0; regvalue < TrapConfig::kLastReg; regvalue++) { - run3config << " Trap : " << trapconfig->mRegisterValue[regvalue].getName() - << " at : 0x " << std::hex << trapconfig->mRegisterValue[regvalue].getAddr() << std::dec - << " with nbits : " << trapconfig->mRegisterValue[regvalue].getNbits() - << " and reset value of : " << trapconfig->mRegisterValue[regvalue].getResetValue() << std::endl; - // now for the inherited AliTRDtrapValue members; - PrintRegisterValue3(&trapconfig->mRegisterValue[regvalue], run3config); - } - - // run3config << "done with regiser values now for dmemwords" << std::endl; - run3config << "DMEM Words : " << std::endl; - for (int dmemwords = 0; dmemwords < TrapConfig::mgkDmemWords; dmemwords++) { - // copy fName, fAddr - // inherited from trapvalue : fAllocMode, fSize fData and fValid - // trapconfig->mDmem[dmemwords].mName= run2config->fDmem[dmemwords].fName; // this gets set on setting the address - run3config << "Name : " << trapconfig->mDmem[dmemwords].getName() << " :address : " << trapconfig->mDmem[dmemwords].getAddress() << std::endl; - PrintDmemValue3(&trapconfig->mDmem[dmemwords], run3config); - } -} void TRDDPLTrapSimulatorTask::loadTrapConfig() { @@ -204,9 +165,9 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() auto& ccdbmgr = o2::ccdb::BasicCCDBManager::instance(); ccdbmgr.setTimestamp(mRunNumber); - //default is : mTrapConfigName="cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"; + //default is : mTrapConfigName="dcf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"; mTrapConfigName = "c"; - mTrapConfig = ccdbmgr.get<o2::trd::TrapConfig>("TRD_test/TrapConfig2020/c"); + mTrapConfig = ccdbmgr.get<o2::trd::TrapConfig>("TRD_test/TrapConfig2020/" + mTrapConfigName); if (mTrapConfig == nullptr) { //failed to find or open or connect or something to get the trapconfig from the ccdb. //first check the directory listing. @@ -214,7 +175,7 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() } else { //TODO figure out how to get the debug level from logger and only do this for debug option to --severity debug (or what ever the command actualy is) if (mEnableTrapConfigDump) - PrintTrapConfigAsStored3(mTrapConfig); + mTrapConfig->DumpTrapConfig2File("run3trapconfig_dump"); } } @@ -272,7 +233,6 @@ void TRDDPLTrapSimulatorTask::init(o2::framework::InitContext& ic) mDrawTrackletOptions = ic.options().get<int>("trd-drawtracklets"); mShowTrackletStats = ic.options().get<int>("show-trd-trackletstats"); mTrapConfigName = ic.options().get<std::string>("trd-trapconfig"); - mPrintOutTrapConfig = ic.options().get<bool>("trd-printtrapconfig"); mDebugRejectedTracklets = ic.options().get<bool>("trd-debugrejectedtracklets"); mEnableOnlineGainCorrection = ic.options().get<bool>("trd-onlinegaincorrection"); mOnlineGainTableName = ic.options().get<std::string>("trd-onlinegaintable"); @@ -502,10 +462,6 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) << " LinkId:" << LinkRecord::getHalfChamberLinkId(detector, rob) << "\t\t SM:stack:layer:side " << detector / 30 << ":" << trdstack << ":" << trdlayer << ":" << fibreside << " with ORI : " << mFeeParam->getORI(detector, rob) << " and within supermodule ori index:" << mFeeParam->getORIinSM(detector, rob); LOG(debug) << "digit time : " << digittime; - if (row == 4 && pad == 17 && rob == 2 & mcm == 0) { - // here for debugging. - b = sin(30); - } if (digititerator == msgDigits.begin()) { // first time in loop oldrow = row; olddetector = detector; @@ -587,16 +543,15 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // mTrapSimulator[trapcounter].zeroSupressionMapping(); - // if (mDrawTrackletOptions != 0) - // mTrapSimulator[trapcounter].draw(mDrawTrackletOptions, loopindex); + if (mDrawTrackletOptions != 0) + mTrapSimulator[trapcounter].draw(mDrawTrackletOptions, loopindex); if (mDebugRejectedTracklets) { //&& trapTracklets.size()==0) { mTrapSimulator[trapcounter].draw(7, loopindex); //draw adc when no tracklets are found.A LOG(debug) << "loop index : " << loopindex; mTrapSimulator[trapcounter].print(1); - // if(loopindex==320) LOG(fatal) <<"exiting at trap loop count 320"; } - // if (mPrintTrackletOptions != 0) - // mTrapSimulator[trapcounter].print(mPrintTrackletOptions); + if (mPrintTrackletOptions != 0) + mTrapSimulator[trapcounter].print(mPrintTrackletOptions); loopindex++; //set this trap sim object to have not data (effectively) reset. @@ -723,16 +678,14 @@ o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec() AlgorithmSpec{adaptFromTask<TRDDPLTrapSimulatorTask>()}, Options{ {"show-trd-trackletstats", VariantType::Int, 25000, {"Display the accumulated size and capacity at number of track intervals"}}, - {"trd-trapconfig", VariantType::String, "default", {"Name of the trap config from the CCDB"}}, - {"trd-printtrapconfig", VariantType::Bool, false, {"Name of the trap config from the CCDB"}}, - {"trd-drawtracklets", VariantType::Int, 0, {"Bitpattern of input to TrapSimulator Draw method (be very careful) one file per track"}}, - {"trd-printtracklets", VariantType::Int, 0, {"Bitpattern of input to TrapSimulator print method"}}, + {"trd-trapconfig", VariantType::String, "cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549", {"Name of the trap config from the CCDB default:cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"}}, + {"trd-drawtracklets", VariantType::Int, 0, {"Bitpattern of input to TrapSimulator Draw method one histogram per chip not per tracklet, 1=raw,2=hits,4=tracklets, 7 for all"}}, + {"trd-printtracklets", VariantType::Int, 0, {"Bitpattern of input to TrapSimulator print method, "}}, {"trd-fixtriggerrecord", VariantType::Bool, false, {"Fix trigger record alignment, temporary, hence false by default"}}, {"trd-onlinegaincorrection", VariantType::Bool, false, {"Apply online gain calibrations, mostly for back checking to run2 by setting FGBY to 0"}}, {"trd-onlinegaintable", VariantType::String, "Krypton_2015-02", {"Online gain table to be use, names found in CCDB, obviously trd-onlinegaincorrection must be set as well."}}, {"trd-debugrejectedtracklets", VariantType::Bool, false, {"Output all MCM where tracklets were not identified"}}, - {"trd-dumptrapconfig", VariantType::Bool, false, {"Dump the trapconfig at loading"}}, - {"trd-dataformat", VariantType::Int, 1, {"Raw dataformat 1. 4x32bit words 2. 1 with triggerrecords."}}, + {"trd-dumptrapconfig", VariantType::Bool, false, {"Dump the selected trap configuration at loading time, to text file"}}, {"trd-runnum", VariantType::Int, 297595, {"Run number to use to anchor simulation to, defaults to 297595"}}}}; }; From ac3a75aa7fd31579384480f224bf6df8a478c652 Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Fri, 25 Sep 2020 15:50:31 +0200 Subject: [PATCH 0753/1751] added filter for vertex z-position --- Analysis/Tasks/CMakeLists.txt | 2 +- Analysis/Tasks/trackchecks.cxx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index d796e1445ebeb..5958b687457a8 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -97,7 +97,7 @@ o2_add_dpl_workflow(run3-matcher SOURCES run3Matcher.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) - + o2_add_dpl_workflow(track-checks SOURCES trackchecks.cxx diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index c5b18f86340ad..1b93c80483f01 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -13,6 +13,8 @@ #include "Analysis/EventSelection.h" #include "Analysis/MC.h" #include "Analysis/HistHelpers.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" #include <cmath> #include <array> @@ -98,7 +100,9 @@ struct TrackCheckTask1 { fCutDCAxy->SetParameter(2, 1.1); } //init - void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) + //Filters + Filter collfilter = nabs(aod::collision::posZ) < (float)10.; + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) { if (isMC) { @@ -112,8 +116,6 @@ struct TrackCheckTask1 { return; if (!col.sel7()) //additional cuts return; - if (abs(col.posZ()) > 10.) // |v_z|<10cm - return; //Loop on tracks for (auto& track : tracks) { From 6d2921c22407cdd8cd0cf867ad16de8167a2a628 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 25 Sep 2020 10:41:50 +0200 Subject: [PATCH 0754/1751] RootTreeWrite: Utility to allow remaping a branch to different type --- .../Utils/include/DPLUtils/RootTreeWriter.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Framework/Utils/include/DPLUtils/RootTreeWriter.h b/Framework/Utils/include/DPLUtils/RootTreeWriter.h index bd8188947f6db..abb47d0981f20 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeWriter.h +++ b/Framework/Utils/include/DPLUtils/RootTreeWriter.h @@ -340,6 +340,31 @@ class RootTreeWriter return (mTreeStructure != nullptr ? mTreeStructure->size() : 0); } + /// A static helper function to change the type of a (yet unused) branch. + /// Removes the old branch from the TTree system and creates a new branch. + /// The function is useful for situations in which we want to transform data after + /// the RootTreeWriter was created and change the type of the branch - such as in user callbacks. + /// The function needs to be used with care. The user should ensure that "branch" is no longer used + /// after a call to this function. + template <typename T> + static TBranch* remapBranch(TBranch& branch, T* newdata) + { + auto name = branch.GetName(); + auto branchleaves = branch.GetListOfLeaves(); + auto tree = branch.GetTree(); + branch.DropBaskets("all"); + branch.DeleteBaskets("all"); + tree->GetListOfBranches()->Remove(&branch); + for (auto entry : *branchleaves) { + tree->GetListOfLeaves()->Remove(entry); + } + // ROOT leaves holes in the arrays so we need to compress as well + tree->GetListOfBranches()->Compress(); + tree->GetListOfLeaves()->Compress(); + // create a new branch with the same original name but attached to the new data + return tree->Branch(name, newdata); + } + private: /// internal input and branch properties struct BranchSpec { From f5b6070589cfe246e09eebc7bf82838f3b481564 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 25 Sep 2020 10:43:23 +0200 Subject: [PATCH 0755/1751] TRD digitizer: Cleanup of writer; avoid TMP branch --- .../TRD/workflow/src/TRDDigitWriterSpec.cxx | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx index c53c7dcbb4eaa..951a189e5c07c 100644 --- a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx @@ -35,15 +35,6 @@ o2::framework::DataProcessorSpec getTRDDigitWriterSpec(bool mctruth) using MakeRootTreeWriterSpec = framework::MakeRootTreeWriterSpec; using DataRef = framework::DataRef; - auto getIndex = [](o2::framework::DataRef const& ref) -> size_t { - return 0; - }; - - // callback to create branch name - auto getName = [](std::string base, size_t index) -> std::string { - return base; - }; - // the callback to be set as hook for custom action when the writer is closed auto finishWriting = [](TFile* outputfile, TTree* outputtree) { outputtree->SetEntries(1); @@ -52,24 +43,21 @@ o2::framework::DataProcessorSpec getTRDDigitWriterSpec(bool mctruth) }; // custom handler for labels: - // essentially transform the input container (as registered in the branch definition) to the special output format for labels + // essentially transform the input container (as registered in the original branch definition) to the special output format for labels auto customlabelhandler = [](TBranch& branch, std::vector<char> const& labeldata, DataRef const& ref) { // make the actual output object by adopting/casting the buffer // into a split format o2::dataformats::IOMCTruthContainerView outputcontainer(labeldata); - auto tree = branch.GetTree(); - auto br = tree->Branch("TRDMCLabels", &outputcontainer); + auto br = framework::RootTreeWriter::remapBranch(branch, &outputcontainer); br->Fill(); br->ResetAddress(); }; auto labelsdef = BranchDefinition<std::vector<char>>{InputSpec{"labelinput", "TRD", "LABELS"}, - "TRDMCLabels_TMP", "labels-branch-name", + "TRDMCLabels", "labels-branch-name", // this branch definition is disabled if MC labels are not processed (mctruth ? 1 : 0), - customlabelhandler, - getIndex, - getName}; + customlabelhandler}; return MakeRootTreeWriterSpec("TRDDigitWriter", "trddigits.root", From e29346a2923d94bd39e5edaeb760c73c38b41a4e Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 25 Sep 2020 10:46:35 +0200 Subject: [PATCH 0756/1751] ITSMFT: Cleanup of digit writer; avoid TMP branches --- .../common/workflow/src/DigitWriterSpec.cxx | 96 +------------------ 1 file changed, 3 insertions(+), 93 deletions(-) diff --git a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx index 49d36c33dd3ea..8cda4bebe917b 100644 --- a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx @@ -22,10 +22,6 @@ #include <vector> #include <string> #include <algorithm> -#ifdef NDEBUG -#undef NDEBUG -#include <cassert> -#endif using namespace o2::framework; using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; @@ -39,32 +35,6 @@ template <typename T> using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; using MCCont = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; -// #define CUSTOM 1 -// make a std::vec use a gsl::span as internal buffer without copy -template <typename T> -void adopt(gsl::span<const T> const& data, std::vector<T>& v) -{ - static_assert(sizeof(v) == 24); - if (data.size() == 0) { - return; - } - // we assume a standard layout of begin, end, end_capacity and overwrite the internal members of the vector - struct Impl { - const T* start; - const T* end; - const T* cap; - }; - - Impl impl; - impl.start = &(data[0]); - impl.end = &(data[data.size() - 1]) + 1; // end pointer (beyond last element) - impl.cap = impl.end; - std::memcpy(&v, &impl, sizeof(Impl)); - assert(data.size() == v.size()); - assert(v.capacity() == v.size()); - assert((void*)&data[0] == (void*)&v[0]); -} - /// create the processor spec /// describing a processor receiving digits for ITS/MFT and writing them to file DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOrig, o2::detectors::DetID detId) @@ -72,57 +42,6 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOri std::string detStr = o2::detectors::DetID::getName(detId); std::string detStrL = detStr; std::transform(detStrL.begin(), detStrL.end(), detStrL.begin(), ::tolower); -#ifdef CUSTOM - std::vector<o2::framework::InputSpec> inputs; - if (mctruth) { - inputs.emplace_back(InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}); - inputs.emplace_back(InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}); - } - inputs.emplace_back(InputSpec{"digits", detOrig, "DIGITS", 0}); - inputs.emplace_back(InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}); - - return {(detStr + "DigitWriter").c_str(), - inputs, - {}, - AlgorithmSpec{ - [detStrL, detStr, mctruth](ProcessingContext& ctx) { - static bool mFinished = false; - if (mFinished) { - return; - } - - TFile f((detStrL + "digits.root").c_str(), "RECREATE"); - TTree t("o2sim", "o2sim"); - // define data - auto digits = new std::vector<itsmft::Digit>; // needs to be a pointer since the message memory is managed by DPL and we have to avoid double deletes - auto rof = new std::vector<itsmft::ROFRecord>; - auto mc2rofrecords = new std::vector<itsmft::MC2ROFRecord>; - o2::dataformats::IOMCTruthContainerView labelview; - - auto fillBranch = [](TBranch* br) { - br->Fill(); - br->ResetAddress(); - br->DropBaskets("all"); - }; - // get the data as gsl::span so that ideally no copy is made - // but immediately adopt the views in standard std::vectors *** THIS IS AN INTERNAL HACK *** - if (mctruth) { - labelview.adopt(ctx.inputs().get<gsl::span<char>>("digitsMCTR")); - fillBranch(t.Branch((detStr + "DigitMCTruth").c_str(), &labelview)); - adopt(ctx.inputs().get<gsl::span<itsmft::MC2ROFRecord>>("digitsMC2ROF"), *mc2rofrecords); - fillBranch(t.Branch((detStr + "DigitMC2ROF").c_str(), &mc2rofrecords)); - } - adopt(ctx.inputs().get<gsl::span<itsmft::Digit>>("digits"), *digits); - fillBranch(t.Branch((detStr + "Digits").c_str(), &digits)); - adopt(ctx.inputs().get<gsl::span<itsmft::ROFRecord>>("digitsROF"), *rof); - fillBranch(t.Branch((detStr + "DigitROF").c_str(), &rof)); - t.SetEntries(1); - f.Write(); - f.Close(); - ctx.services().get<ControlService>().readyToQuit(QuitRequest::Me); - mFinished = true; - }}}; -#else auto logger = [](std::vector<o2::itsmft::Digit> const& inDigits) { LOG(INFO) << "RECEIVED DIGITS SIZE " << inDigits.size(); }; @@ -137,23 +56,15 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOri // handler for labels // This is necessary since we can't store the original label buffer in a ROOT entry -- as is -- if it exceeds a certain size. // We therefore convert it to a special split class. - auto fillLabels = [detStr](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& /*ref*/) { + auto fillLabels = [](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& /*ref*/) { o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> labels(labelbuffer); LOG(INFO) << "WRITING " << labels.getNElements() << " LABELS "; o2::dataformats::IOMCTruthContainerView outputcontainer; - // first of all redefine the output format (special to labels) - auto tree = branch.GetTree(); - - std::stringstream str; - str << detStr + "DigitMCTruth"; - auto br = tree->Branch(str.str().c_str(), &outputcontainer); + auto br = framework::RootTreeWriter::remapBranch(branch, &outputcontainer); outputcontainer.adopt(labelbuffer); br->Fill(); br->ResetAddress(); - const int entries = 1; - tree->SetEntries(entries); - tree->Write("", TObject::kOverwrite); }; return MakeRootTreeWriterSpec((detStr + "DigitWriter").c_str(), @@ -162,7 +73,7 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOri MakeRootTreeWriterSpec::CustomClose(finishWriting), // in case of labels we first read them as std::vector<char> and process them correctly in the fillLabels hook BranchDefinition<std::vector<char>>{InputSpec{"digitsMCTR", detOrig, "DIGITSMCTR", 0}, - (detStr + "DigitMCTruth_TMP").c_str(), + (detStr + "DigitMCTruth").c_str(), (mctruth ? 1 : 0), fillLabels}, BranchDefinition<std::vector<itsmft::MC2ROFRecord>>{InputSpec{"digitsMC2ROF", detOrig, "DIGITSMC2ROF", 0}, (detStr + "DigitMC2ROF").c_str(), @@ -172,7 +83,6 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOri logger}, BranchDefinition<std::vector<itsmft::ROFRecord>>{InputSpec{"digitsROF", detOrig, "DIGITSROF", 0}, (detStr + "DigitROF").c_str()})(); -#endif } DataProcessorSpec getITSDigitWriterSpec(bool mctruth) From 2a35b5f916412b772715da6f7b05a3a318ec2538 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 25 Sep 2020 13:14:20 +0200 Subject: [PATCH 0757/1751] FDD: mc label migration for digitization Also declare variables more locally so that they can deallocate earlier. --- .../include/FDDWorkflow/DigitReaderSpec.h | 5 --- .../FIT/FDD/workflow/src/DigitReaderSpec.cxx | 26 +++++++++++---- .../src/FDDDigitWriterSpec.h | 32 +++++++++++++++++-- .../src/FDDDigitizerSpec.cxx | 11 ++++--- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/Detectors/FIT/FDD/workflow/include/FDDWorkflow/DigitReaderSpec.h b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/DigitReaderSpec.h index 7127408e717a2..aad71d0e33ce3 100644 --- a/Detectors/FIT/FDD/workflow/include/FDDWorkflow/DigitReaderSpec.h +++ b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/DigitReaderSpec.h @@ -20,7 +20,6 @@ #include "DataFormatsFDD/Digit.h" #include "DataFormatsFDD/ChannelData.h" #include "DataFormatsFDD/MCLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" using namespace o2::framework; @@ -42,10 +41,6 @@ class DigitReader : public Task bool mUseMC = true; // use MC truth o2::header::DataOrigin mOrigin = o2::header::gDataOriginFDD; - std::vector<o2::fdd::Digit>* mDigitsBC = nullptr; - std::vector<o2::fdd::ChannelData>* mDigitsCh = nullptr; - o2::dataformats::MCTruthContainer<o2::fdd::MCLabel>* mMCTruth = nullptr; - std::string mInputFileName = ""; std::string mDigitTreeName = "o2sim"; std::string mDigitBCBranchName = "FDDDigit"; diff --git a/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx b/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx index 819673b77a37e..dbbcbe1c6c164 100644 --- a/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx @@ -18,6 +18,9 @@ #include "Framework/ControlService.h" #include "Framework/Logger.h" #include "FDDWorkflow/DigitReaderSpec.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include <vector> using namespace o2::framework; using namespace o2::fdd; @@ -43,6 +46,10 @@ void DigitReader::run(ProcessingContext& pc) return; } + std::vector<o2::fdd::Digit>* digitsBC = nullptr; + std::vector<o2::fdd::ChannelData>* digitsCh = nullptr; + o2::dataformats::IOMCTruthContainerView* mcTruthRootBuffer = nullptr; + { // load data from files TFile digFile(mInputFileName.c_str(), "read"); if (digFile.IsZombie()) { @@ -54,11 +61,11 @@ void DigitReader::run(ProcessingContext& pc) } LOG(INFO) << "Loaded FDD digits tree " << mDigitTreeName << " from " << mInputFileName; - digTree->SetBranchAddress(mDigitBCBranchName.c_str(), &mDigitsBC); - digTree->SetBranchAddress(mDigitChBranchName.c_str(), &mDigitsCh); + digTree->SetBranchAddress(mDigitBCBranchName.c_str(), &digitsBC); + digTree->SetBranchAddress(mDigitChBranchName.c_str(), &digitsCh); if (mUseMC) { if (digTree->GetBranch(mDigitMCTruthBranchName.c_str())) { - digTree->SetBranchAddress(mDigitMCTruthBranchName.c_str(), &mMCTruth); + digTree->SetBranchAddress(mDigitMCTruthBranchName.c_str(), &mcTruthRootBuffer); LOG(INFO) << "Will use MC-truth from " << mDigitMCTruthBranchName; } else { LOG(INFO) << "MC-truth is missing"; @@ -70,11 +77,16 @@ void DigitReader::run(ProcessingContext& pc) digFile.Close(); } - LOG(INFO) << "FDD DigitReader pushes " << mDigitsBC->size() << " digits"; - pc.outputs().snapshot(Output{mOrigin, "DIGITSBC", 0, Lifetime::Timeframe}, *mDigitsBC); - pc.outputs().snapshot(Output{mOrigin, "DIGITSCH", 0, Lifetime::Timeframe}, *mDigitsCh); + LOG(INFO) << "FDD DigitReader pushes " << digitsBC->size() << " digits"; + pc.outputs().snapshot(Output{mOrigin, "DIGITSBC", 0, Lifetime::Timeframe}, *digitsBC); + pc.outputs().snapshot(Output{mOrigin, "DIGITSCH", 0, Lifetime::Timeframe}, *digitsCh); if (mUseMC) { - pc.outputs().snapshot(Output{mOrigin, "DIGITLBL", 0, Lifetime::Timeframe}, *mMCTruth); + // TODO: To be replaced with sending ConstMCTruthContainer as soon as reco workflow supports it + std::vector<char> flatbuffer; + mcTruthRootBuffer->copyandflatten(flatbuffer); + o2::dataformats::MCTruthContainer<o2::fdd::MCLabel> mcTruth; + mcTruth.restore_from(flatbuffer.data(), flatbuffer.size()); + pc.outputs().snapshot(Output{mOrigin, "DIGITLBL", 0, Lifetime::Timeframe}, mcTruth); } mFinished = true; diff --git a/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h b/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h index 7a007ad136bb6..577c2a1df4b4b 100644 --- a/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h +++ b/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h @@ -16,7 +16,8 @@ #include "Framework/InputSpec.h" #include "DataFormatsFDD/Digit.h" #include "DataFormatsFDD/MCLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" namespace o2 @@ -31,13 +32,40 @@ o2::framework::DataProcessorSpec getFDDDigitWriterSpec(bool mctruth = true) { using InputSpec = framework::InputSpec; using MakeRootTreeWriterSpec = framework::MakeRootTreeWriterSpec; + + // the callback to be set as hook for custom action when the writer is closed + auto finishWriting = [](TFile* outputfile, TTree* outputtree) { + outputtree->SetEntries(1); + outputtree->Write(); + outputfile->Close(); + }; + + // custom handler for labels: + // essentially transform the input container (as registered in the original branch definition) to the special output format for labels + auto customlabelhandler = [](TBranch& branch, std::vector<char> const& labeldata, framework::DataRef const& ref) { + o2::dataformats::ConstMCTruthContainerView<o2::fdd::MCLabel> labels(labeldata); + // make the actual output object by adopting/casting the buffer + // into a split format + o2::dataformats::IOMCTruthContainerView outputcontainer(labeldata); + auto br = framework::RootTreeWriter::remapBranch(branch, &outputcontainer); + br->Fill(); + br->ResetAddress(); + }; + + auto labelsdef = BranchDefinition<std::vector<char>>{InputSpec{"labelinput", "FDD", "DIGITLBL"}, + "FDDDigitLabels", "labels-branch-name", + // this branch definition is disabled if MC labels are not processed + (mctruth ? 1 : 0), + customlabelhandler}; + return MakeRootTreeWriterSpec("FDDDigitWriter", "fdddigits.root", "o2sim", 1, + MakeRootTreeWriterSpec::CustomClose(finishWriting), BranchDefinition<std::vector<o2::fdd::Digit>>{InputSpec{"digitBCinput", "FDD", "DIGITSBC"}, "FDDDigit"}, BranchDefinition<std::vector<o2::fdd::ChannelData>>{InputSpec{"digitChinput", "FDD", "DIGITSCH"}, "FDDDigitCh"}, - BranchDefinition<o2::dataformats::MCTruthContainer<o2::fdd::MCLabel>>{InputSpec{"labelinput", "FDD", "DIGITLBL"}, "FDDDigitLabels", mctruth ? 1 : 0})(); + std::move(labelsdef))(); } } // end namespace fdd diff --git a/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx index 51f08f5ab1205..6ee391f2a8475 100644 --- a/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx @@ -19,6 +19,7 @@ #include "Steer/HitProcessingManager.h" // for DigitizationContext #include "DetectorsBase/BaseDPLDigitizer.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" #include "FDDSimulation/Digitizer.h" @@ -75,6 +76,7 @@ class FDDDPLDigitizerTask : public o2::base::BaseDPLDigitizer // loop over all composite collisions given from context // (aka loop over all the interaction records) std::vector<o2::fdd::Hit> hits; + o2::dataformats::MCTruthContainer<o2::fdd::MCLabel> labels; for (int collID = 0; collID < irecords.size(); ++collID) { @@ -90,20 +92,22 @@ class FDDDPLDigitizerTask : public o2::base::BaseDPLDigitizer mDigitizer.setEventID(part.entryID); mDigitizer.setSrcID(part.sourceID); - mDigitizer.process(hits, mDigitsBC, mDigitsCh, mLabels); + mDigitizer.process(hits, mDigitsBC, mDigitsCh, labels); } } o2::InteractionTimeRecord terminateIR; terminateIR.orbit = 0xffffffff; // supply IR in the infinite future to flush all cached BC mDigitizer.setInteractionRecord(terminateIR); - mDigitizer.flush(mDigitsBC, mDigitsCh, mLabels); + mDigitizer.flush(mDigitsBC, mDigitsCh, labels); // send out to next stage pc.outputs().snapshot(Output{"FDD", "DIGITSBC", 0, Lifetime::Timeframe}, mDigitsBC); pc.outputs().snapshot(Output{"FDD", "DIGITSCH", 0, Lifetime::Timeframe}, mDigitsCh); if (pc.outputs().isAllowed({"FDD", "DIGITLBL", 0})) { - pc.outputs().snapshot(Output{"FDD", "DIGITLBL", 0, Lifetime::Timeframe}, mLabels); + auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::fdd::MCLabel>>(Output{"FDD", "DIGITLBL", 0, Lifetime::Timeframe}); + labels.flatten_to(sharedlabels); + labels.clear_andfreememory(); } LOG(INFO) << "FDD: Sending ROMode= " << mROMode << " to GRPUpdater"; @@ -120,7 +124,6 @@ class FDDDPLDigitizerTask : public o2::base::BaseDPLDigitizer std::vector<TChain*> mSimChains; std::vector<o2::fdd::ChannelData> mDigitsCh; std::vector<o2::fdd::Digit> mDigitsBC; - o2::dataformats::MCTruthContainer<o2::fdd::MCLabel> mLabels; // labels which get filled // RS: at the moment using hardcoded flag for continuous readout o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::CONTINUOUS; // readout mode From 547f2ded9752ed6a5cb96976408290ba9d9c79bf Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 25 Sep 2020 13:31:38 +0200 Subject: [PATCH 0758/1751] TPC: avoid TMP branches in digit writer --- .../src/TPCDigitRootWriterSpec.cxx | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx index c0d48544cf16d..cfaff58868aec 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx @@ -56,24 +56,12 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur // the callback to be set as hook for custom action when the writer is closed auto finishWriting = [](TFile* outputfile, TTree* outputtree) { // check/verify number of entries (it should be same in all branches) - auto leavelist = outputtree->GetListOfLeaves(); - for (auto entry : *leavelist) { - if (TString(entry->GetName()).Contains("_TMP")) { - leavelist->Remove(entry); - } - } // will return a TObjArray const auto brlist = outputtree->GetListOfBranches(); int entries = -1; // init to -1 (as unitialized) for (TObject* entry : *brlist) { auto br = static_cast<TBranch*>(entry); - if (TString(entry->GetName()).Contains("_TMP")) { - br->DeleteBaskets("all"); - brlist->Remove(br); - continue; - } - int brentries = br->GetEntries(); entries = std::max(entries, brentries); if (brentries != entries && !TString(br->GetName()).Contains("CommonMode")) { @@ -216,9 +204,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur // first of all redefine the output format (special to labels) auto tree = branch.GetTree(); auto sector = extractSector(ref); - std::stringstream str; - str << "TPCDigitMCTruth_" << sector; - auto br = tree->Branch(str.str().c_str(), &outputcontainer); + auto br = framework::RootTreeWriter::remapBranch(branch, &outputcontainer); auto const* dh = DataRefUtils::getHeader<DataHeader*>(ref); LOG(INFO) << "HAVE LABEL DATA FOR SECTOR " << sector << " ON CHANNEL " << dh->subSpecification; @@ -242,6 +228,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur outputcontainer.adopt(labelbuffer); br->Fill(); br->ResetAddress(); + br->DropBaskets("all"); entries = 1; } else { o2::dataformats::MCTruthContainer<o2::MCCompLabel> lblGroup; // labels for group of digits related to single trigger @@ -256,6 +243,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur lblGroup.flatten_to(flatbuffer); outputcontainer.adopt(flatbuffer); br->Fill(); + br->DropBaskets("all"); entries++; } br->ResetAddress(); @@ -282,7 +270,7 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur getName}; auto labelsdef = BranchDefinition<std::vector<char>>{InputSpec{"labelinput", ConcreteDataTypeMatcher{"TPC", "DIGITSMCTR"}}, - "TPCDigitMCTruth_TMP", "labels-branch-name", + "TPCDigitMCTruth", "labels-branch-name", // this branch definition is disabled if MC labels are not processed (mctruth ? laneConfiguration.size() : 0), fillLabels, From 4db203c5fb26f4e247e94068c71e74c176bb6daa Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Fri, 15 May 2020 11:32:31 +0200 Subject: [PATCH 0759/1751] Improve treatment of triggered events --- .../MID/Raw/include/MIDRaw/GBTOutputHandler.h | 13 +- .../MUON/MID/Raw/src/GBTOutputHandler.cxx | 146 +++++++++--------- 2 files changed, 81 insertions(+), 78 deletions(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h index 9aa02fb34ce42..5557e56c9522e 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h @@ -54,16 +54,15 @@ class GBTOutputHandler std::vector<ROFRecord> mROFRecords{}; /// List of ROF records uint16_t mFeeId{0}; /// FEE ID InteractionRecord mIRFirstPage{}; /// Interaction record of the first page + uint16_t mReceivedCalibration{0}; /// Flag to test if a calibration trigger was received - std::array<InteractionRecord, crateparams::sNELinksPerGBT> mIRs{}; /// Interaction records per link - std::array<uint16_t, crateparams::sNELinksPerGBT> mCalibClocks{}; /// Calibration clock - std::array<uint16_t, crateparams::sNELinksPerGBT> mLastClock{}; /// Last clock per link + std::array<InteractionRecord, crateparams::sNELinksPerGBT> mIRs{}; /// Interaction records per link + std::array<uint16_t, crateparams::sNELinksPerGBT> mExpectedFETClock{}; /// Expected FET clock + std::array<uint16_t, crateparams::sNELinksPerGBT> mLastClock{}; /// Last clock per link - void addBoard(size_t ilink, const ELinkDecoder& decoder); - void addLoc(size_t ilink, const ELinkDecoder& decoder); + void addLoc(size_t ilink, const ELinkDecoder& decoder, EventType eventType, uint16_t correctedClock); bool checkLoc(size_t ilink, const ELinkDecoder& decoder); - bool updateIR(size_t ilink, const ELinkDecoder& decoder); - bool invertPattern(LocalBoardRO& loc); + bool processTrigger(size_t ilink, const ELinkDecoder& decoder, EventType& eventType, uint16_t& correctedClock); }; } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx index 8b8a57c15c7e4..b77d5b94c807a 100644 --- a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx @@ -37,12 +37,7 @@ void GBTOutputHandler::setIR(uint16_t bc, uint32_t orbit, int pageCnt) ir.bc = bc; ir.orbit = orbit; } - for (auto& clock : mLastClock) { - clock = constants::lhc::LHCMaxBunches; - } - for (auto& clock : mCalibClocks) { - clock = constants::lhc::LHCMaxBunches; - } + mLastClock.fill(constants::lhc::LHCMaxBunches); } if (pageCnt == 0) { @@ -62,112 +57,121 @@ bool GBTOutputHandler::checkLoc(size_t ilink, const ELinkDecoder& decoder) return (ilink == decoder.getId() % 8); } -void GBTOutputHandler::addBoard(size_t ilink, const ELinkDecoder& decoder) +bool GBTOutputHandler::processTrigger(size_t ilink, const ELinkDecoder& decoder, EventType& eventType, uint16_t& correctedClock) { - /// Adds the local or regional board to the output data vector - uint16_t localClock = decoder.getCounter(); - EventType eventType = EventType::Standard; + /// Processes the trigger information + /// Returns true if the event should be further processed, + /// returns false otherwise. + uint16_t linkMask = 1 << ilink; + eventType = EventType::Standard; + + if (decoder.getTriggerWord() == 0) { + // This is a self-triggered event + auto localClock = decoder.getCounter(); + if ((mReceivedCalibration & linkMask) && (localClock == mExpectedFETClock[ilink])) { + mReceivedCalibration &= ~linkMask; + eventType = EventType::Dead; + } + correctedClock = localClock - sDelayBCToLocal; + return true; + } + + // From here we treat triggered events + bool goOn = false; + correctedClock = decoder.getCounter(); if (decoder.getTriggerWord() & raw::sCALIBRATE) { - mCalibClocks[ilink] = localClock; + mExpectedFETClock[ilink] = correctedClock + sDelayCalibToFET; + mReceivedCalibration |= linkMask; eventType = EventType::Noise; - } else if (localClock == mCalibClocks[ilink] + sDelayCalibToFET) { - eventType = EventType::Dead; + goOn = true; } - auto firstEntry = mData.size(); - mData.push_back({decoder.getStatusWord(), decoder.getTriggerWord(), crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), decoder.getId()), decoder.getInputs()}); - InteractionRecord intRec(mIRs[ilink].bc + localClock - sDelayBCToLocal, mIRs[ilink].orbit); - mROFRecords.emplace_back(intRec, eventType, firstEntry, 1); + + if (decoder.getTriggerWord() & raw::sORB) { + // This is the answer to an orbit trigger + // The local clock is reset: we are now in synch with the new HB + // ++mIRs[ilink].orbit; + mIRs[ilink] = mIRFirstPage; // TODO: CHECK + if ((decoder.getTriggerWord() & raw::sSOX) == 0) { + mLastClock[ilink] = correctedClock; + } + // The orbit trigger resets the clock. + // If we received a calibration trigger, we need to change the value of the expected clock accordingly + if (mReceivedCalibration & linkMask) { + mExpectedFETClock[ilink] -= (correctedClock + 1); + } + } + + return goOn; } -void GBTOutputHandler::addLoc(size_t ilink, const ELinkDecoder& decoder) +void GBTOutputHandler::addLoc(size_t ilink, const ELinkDecoder& decoder, EventType eventType, uint16_t correctedClock) { /// Adds the local board to the output data vector - addBoard(ilink, decoder); + auto firstEntry = mData.size(); + mData.push_back({decoder.getStatusWord(), decoder.getTriggerWord(), crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), decoder.getId()), decoder.getInputs()}); + InteractionRecord intRec(mIRs[ilink].bc + correctedClock, mIRs[ilink].orbit); + mROFRecords.emplace_back(intRec, eventType, firstEntry, 1); for (int ich = 0; ich < 4; ++ich) { if ((mData.back().firedChambers & (1 << ich))) { mData.back().patternsBP[ich] = decoder.getPattern(0, ich); mData.back().patternsNBP[ich] = decoder.getPattern(1, ich); } } - if (mROFRecords.back().eventType == EventType::Dead) { - if (invertPattern(mData.back())) { - mData.pop_back(); - mROFRecords.pop_back(); - } - } -} - -bool GBTOutputHandler::updateIR(size_t ilink, const ELinkDecoder& decoder) -{ - /// Updates the interaction record for the link - if (decoder.getTriggerWord() & raw::sORB) { - // This is the answer to an orbit trigger - // The local clock is reset: we are now in synch with the new HB - mIRs[ilink] = mIRFirstPage; - if (!(decoder.getTriggerWord() & (raw::sSOX | raw::sEOX))) { - mLastClock[ilink] = decoder.getCounter(); - } - return true; - } - return false; } void GBTOutputHandler::onDoneLoc(size_t ilink, const ELinkDecoder& decoder) { /// Performs action on decoded local board - if (updateIR(ilink, decoder)) { - return; - } - if (checkLoc(ilink, decoder)) { - addLoc(ilink, decoder); + EventType eventType; + uint16_t correctedClock; + if (processTrigger(ilink, decoder, eventType, correctedClock) && checkLoc(ilink, decoder)) { + addLoc(ilink, decoder, eventType, correctedClock); } } void GBTOutputHandler::onDoneLocDebug(size_t ilink, const ELinkDecoder& decoder) { - /// This always adds the local board to the output, without performing tests - updateIR(ilink, decoder); - addLoc(ilink, decoder); + EventType eventType; + uint16_t correctedClock; + processTrigger(ilink, decoder, eventType, correctedClock); + addLoc(ilink, decoder, eventType, correctedClock); + if (decoder.getTriggerWord() & raw::sORB) { + // The local clock is increased when receiving an orbit trigger, + // but the local counter returned in answering the trigger + // belongs to the previous orbit + --mROFRecords.back().interactionRecord.orbit; + } } void GBTOutputHandler::onDoneRegDebug(size_t ilink, const ELinkDecoder& decoder) { /// Performs action on decoded regional board in debug mode. - updateIR(ilink, decoder); - addBoard(ilink, decoder); - // The board creation is optimized for the local boards, not the regional - // (which are transmitted only in debug mode). - // So, at this point, for the regional board, the local Id is actually the crate ID. + EventType eventType; + uint16_t correctedClock; + processTrigger(ilink, decoder, eventType, correctedClock); // If we want to distinguish the two regional e-links, we can use the link ID instead - mData.back().boardId = crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), ilink + 8 * (crateparams::getGBTIdInCrate(mFeeId) - 1)); - if (mData.back().triggerWord == 0) { - if (mROFRecords.back().interactionRecord.bc < sDelayRegToLocal) { + auto firstEntry = mData.size(); + mData.push_back({decoder.getStatusWord(), decoder.getTriggerWord(), crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), ilink + 8 * (crateparams::getGBTIdInCrate(mFeeId) - 1)), decoder.getInputs()}); + + auto orbit = (decoder.getTriggerWord() & raw::sORB) ? mIRs[ilink].orbit - 1 : mIRs[ilink].orbit; + + InteractionRecord intRec(mIRs[ilink].bc + correctedClock, orbit); + if (decoder.getTriggerWord() == 0) { + if (intRec.bc < sDelayRegToLocal) { // In the tests, the HB does not really correspond to a change of orbit // So we need to keep track of the last clock at which the HB was received // and come back to that value // FIXME: Remove this part as well as mLastClock when tests are no more needed - mROFRecords.back().interactionRecord -= (constants::lhc::LHCMaxBunches - mLastClock[ilink] - 1); + intRec -= (constants::lhc::LHCMaxBunches - mLastClock[ilink] - 1); } // This is a self-triggered event. // In this case the regional card needs to wait to receive the tracklet decision of each local // which result in a delay that needs to be subtracted if we want to be able to synchronize // local and regional cards for the checks - mROFRecords.back().interactionRecord -= sDelayRegToLocal; + intRec -= sDelayRegToLocal; } -} - -bool GBTOutputHandler::invertPattern(LocalBoardRO& loc) -{ - /// Gets the proper pattern - for (int ich = 0; ich < 4; ++ich) { - loc.patternsBP[ich] = ~loc.patternsBP[ich]; - loc.patternsNBP[ich] = ~loc.patternsNBP[ich]; - if (loc.patternsBP[ich] == 0 && loc.patternsNBP[ich] == 0) { - loc.firedChambers &= ~(1 << ich); - } - } - return (loc.firedChambers == 0); + mROFRecords.emplace_back(intRec, eventType, firstEntry, 1); } } // namespace mid From 0db06cf3495edcbe731c512908dc8d7d40576862 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Thu, 17 Sep 2020 10:10:20 +0200 Subject: [PATCH 0760/1751] Improve data member description --- Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h index 5557e56c9522e..04e384449df92 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h @@ -54,7 +54,7 @@ class GBTOutputHandler std::vector<ROFRecord> mROFRecords{}; /// List of ROF records uint16_t mFeeId{0}; /// FEE ID InteractionRecord mIRFirstPage{}; /// Interaction record of the first page - uint16_t mReceivedCalibration{0}; /// Flag to test if a calibration trigger was received + uint16_t mReceivedCalibration{0}; /// Word with one bit per e-link indicating if the calibration trigger was received by the e-link std::array<InteractionRecord, crateparams::sNELinksPerGBT> mIRs{}; /// Interaction records per link std::array<uint16_t, crateparams::sNELinksPerGBT> mExpectedFETClock{}; /// Expected FET clock From 0f840fd5c8ba2e37c14004b515a5d58435f31943 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Thu, 17 Sep 2020 16:50:54 +0200 Subject: [PATCH 0761/1751] Use per trigger functions inside processTrigger --- .../MID/Raw/include/MIDRaw/GBTOutputHandler.h | 3 + .../MUON/MID/Raw/src/GBTOutputHandler.cxx | 79 +++++++++++++------ 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h index 04e384449df92..56d32fce3919b 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h @@ -62,6 +62,9 @@ class GBTOutputHandler void addLoc(size_t ilink, const ELinkDecoder& decoder, EventType eventType, uint16_t correctedClock); bool checkLoc(size_t ilink, const ELinkDecoder& decoder); + EventType processCalibrationTrigger(size_t ilink, uint16_t localClock); + void processOrbitTrigger(size_t ilink, uint16_t localClock, uint8_t triggerWord); + EventType processSelfTriggered(size_t ilink, uint16_t localClock, uint16_t& correctedClock); bool processTrigger(size_t ilink, const ELinkDecoder& decoder, EventType& eventType, uint16_t& correctedClock); }; } // namespace mid diff --git a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx index b77d5b94c807a..5006514c5dcfe 100644 --- a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx @@ -35,7 +35,11 @@ void GBTOutputHandler::setIR(uint16_t bc, uint32_t orbit, int pageCnt) if (mIRs[0].isDummy()) { for (auto& ir : mIRs) { ir.bc = bc; - ir.orbit = orbit; + // The reset changes depending on the way we synch with the orbit + // (see processOrbitTrigger for details) + // FIXME: pick one of the two + ir.orbit = orbit - 1; // with orbit increase + // ir.orbit = orbit; // with reset to RDH } mLastClock.fill(constants::lhc::LHCMaxBunches); } @@ -57,48 +61,77 @@ bool GBTOutputHandler::checkLoc(size_t ilink, const ELinkDecoder& decoder) return (ilink == decoder.getId() % 8); } +EventType GBTOutputHandler::processSelfTriggered(size_t ilink, uint16_t localClock, uint16_t& correctedClock) +{ + /// Processes the self-triggered event + correctedClock = localClock - sDelayBCToLocal; + uint16_t linkMask = 1 << ilink; + if ((mReceivedCalibration & linkMask) && (localClock == mExpectedFETClock[ilink])) { + // Reset the calibration flag for this e-link + mReceivedCalibration &= ~linkMask; + return EventType::Dead; + } + return EventType::Standard; +} + +EventType GBTOutputHandler::processCalibrationTrigger(size_t ilink, uint16_t localClock) +{ + /// Processes the calibration event + mExpectedFETClock[ilink] = localClock + sDelayCalibToFET; + mReceivedCalibration |= (1 << ilink); + return EventType::Noise; +} + +void GBTOutputHandler::processOrbitTrigger(size_t ilink, uint16_t localClock, uint8_t triggerWord) +{ + /// Processes the orbit trigger event + + // The local clock is reset: we are now in synch with the new HB + // We have to way to account for the orbit change: + // - increase the orbit counter by 1 for this e-link + // (CAVEAT: synch is lost if we lose some orbit) + // - set the orbit to the one found in RDH + // (CAVEAT: synch is lost if we have lot of data, spanning over two orbits) + // FIXME: pick one of the two + ++mIRs[ilink].orbit; // orbit increase + // mIRs[ilink] = mIRFirstPage; // reset to RDH + if ((triggerWord & raw::sSOX) == 0) { + mLastClock[ilink] = localClock; + } + // The orbit trigger resets the clock. + // If we received a calibration trigger, we need to change the value of the expected clock accordingly + if (mReceivedCalibration & (1 << ilink)) { + mExpectedFETClock[ilink] -= (localClock + 1); + } +} + bool GBTOutputHandler::processTrigger(size_t ilink, const ELinkDecoder& decoder, EventType& eventType, uint16_t& correctedClock) { /// Processes the trigger information /// Returns true if the event should be further processed, /// returns false otherwise. uint16_t linkMask = 1 << ilink; - eventType = EventType::Standard; + auto localClock = decoder.getCounter(); if (decoder.getTriggerWord() == 0) { // This is a self-triggered event - auto localClock = decoder.getCounter(); - if ((mReceivedCalibration & linkMask) && (localClock == mExpectedFETClock[ilink])) { - mReceivedCalibration &= ~linkMask; - eventType = EventType::Dead; - } - correctedClock = localClock - sDelayBCToLocal; + eventType = processSelfTriggered(ilink, localClock, correctedClock); return true; } // From here we treat triggered events bool goOn = false; - correctedClock = decoder.getCounter(); + correctedClock = localClock; if (decoder.getTriggerWord() & raw::sCALIBRATE) { - mExpectedFETClock[ilink] = correctedClock + sDelayCalibToFET; - mReceivedCalibration |= linkMask; - eventType = EventType::Noise; + // This is an answer to a calibration trigger + eventType = processCalibrationTrigger(ilink, localClock); goOn = true; } if (decoder.getTriggerWord() & raw::sORB) { // This is the answer to an orbit trigger - // The local clock is reset: we are now in synch with the new HB - // ++mIRs[ilink].orbit; - mIRs[ilink] = mIRFirstPage; // TODO: CHECK - if ((decoder.getTriggerWord() & raw::sSOX) == 0) { - mLastClock[ilink] = correctedClock; - } - // The orbit trigger resets the clock. - // If we received a calibration trigger, we need to change the value of the expected clock accordingly - if (mReceivedCalibration & linkMask) { - mExpectedFETClock[ilink] -= (correctedClock + 1); - } + processOrbitTrigger(ilink, localClock, decoder.getTriggerWord()); + eventType = EventType::Standard; } return goOn; From 5a9da410f4e4a6e97d87d9927259cac4f5629518 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 11 Jun 2020 11:24:53 +0200 Subject: [PATCH 0762/1751] Slow reset of TRD tracker not required anymore --- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 20 +------------------ GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 2 +- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index 9b06a3267d662..d7979cea1f8f2 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -191,31 +191,13 @@ void GPUTRDTracker_t<TRDTRK, PROP>::InitializeProcessor() } template <class TRDTRK, class PROP> -void GPUTRDTracker_t<TRDTRK, PROP>::Reset(bool fast) +void GPUTRDTracker_t<TRDTRK, PROP>::Reset() { //-------------------------------------------------------------------- // Reset tracker //-------------------------------------------------------------------- mNTracklets = 0; mNTracks = 0; - if (fast) { - return; - } - for (int i = 0; i < mNMaxSpacePoints; ++i) { - mTracklets[i] = 0x0; - mSpacePoints[i].mR = 0.f; - mSpacePoints[i].mX[0] = 0.f; - mSpacePoints[i].mX[1] = 0.f; - mSpacePoints[i].mCov[0] = 0.f; - mSpacePoints[i].mCov[1] = 0.f; - mSpacePoints[i].mCov[2] = 0.f; - mSpacePoints[i].mDy = 0.f; - mSpacePoints[i].mId = 0; - mSpacePoints[i].mLabel[0] = -1; - mSpacePoints[i].mLabel[1] = -1; - mSpacePoints[i].mLabel[2] = -1; - mSpacePoints[i].mVolumeId = 0; - } } template <class TRDTRK, class PROP> diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 51134e321fbbb..9fbbffd870026 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -107,7 +107,7 @@ class GPUTRDTracker_t : public GPUProcessor short MemoryTracks() const { return mMemoryTracks; } GPUhd() void OverrideGPUGeometry(TRD_GEOMETRY_CONST GPUTRDGeometry* geo) { mGeo = geo; } - void Reset(bool fast = false); + void Reset(); GPUd() int LoadTracklet(const GPUTRDTrackletWord& tracklet, const int* labels = nullptr); //template <class T> GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1) From 4a6252295da1ad94352321a859ffeebd9c1906e8 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Wed, 17 Jun 2020 09:05:53 +0200 Subject: [PATCH 0763/1751] Add TF support to TRD tracker --- .../TRDTracking/GPUTRDInterfaces.h | 10 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 99 ++++++++++++------- GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 18 +++- .../TRDTracking/macros/run_trd_tracker.C | 55 ++++++++--- 4 files changed, 130 insertions(+), 52 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h index e7800219b3e87..42d762b8480bd 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h @@ -80,6 +80,7 @@ class trackInterface<AliExternalTrackParam> : public AliExternalTrackParam const My_Float* getPar() const { return GetParameter(); } const My_Float* getCov() const { return GetCovariance(); } + float getTime() const { return -1.f; } bool CheckNumericalQuality() const { return true; } // parameter manipulation @@ -179,11 +180,16 @@ class trackInterface<o2::dataformats::TrackTPCITS> : public o2::dataformats::Tra } } - const float* getPar() { return getParams(); } + const float* getPar() const { return getParams(); } + float getTime() const { return mTime; } + void setTime(float t) { mTime = t; } bool CheckNumericalQuality() const { return true; } typedef o2::dataformats::TrackTPCITS baseClass; + + private: + float mTime; }; template <> @@ -294,6 +300,7 @@ class trackInterface<GPUTPCGMTrackParam> : public GPUTPCGMTrackParam GPUd() const float* getPar() const { return GetPar(); } GPUd() const float* getCov() const { return GetCov(); } + GPUd() float getTime() const { return -1.f; } GPUd() void setAlpha(float alpha) { mAlpha = alpha; } GPUd() void set(float x, float alpha, const float param[5], const float cov[15]) @@ -338,7 +345,6 @@ class propagatorInterface<GPUTPCGMPropagator> : public GPUTPCGMPropagator { //bool ok = PropagateToXAlpha(x, GetAlpha(), true) == 0 ? true : false; int retVal = PropagateToXAlpha(x, GetAlpha(), true); - printf("Return value of PropagateToXAlpha: %i\n", retVal); bool ok = (retVal == 0) ? true : false; ok = mTrack->CheckNumericalQuality(); return ok; diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index d7979cea1f8f2..5f3c7814bf63b 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -75,7 +75,7 @@ void* GPUTRDTracker_t<TRDTRK, PROP>::SetPointersBase(void* base) //-------------------------------------------------------------------- mMaxThreads = mRec->GetMaxThreads(); computePointerWithAlignment(base, mR, kNChambers); - computePointerWithAlignment(base, mTrackletIndexArray, kNChambers + 1); + computePointerWithAlignment(base, mTrackletIndexArray, (kNChambers + 1) * mNMaxCollisions); computePointerWithAlignment(base, mHypothesis, mNCandidates * mMaxThreads); computePointerWithAlignment(base, mCandidates, mNCandidates * 2 * mMaxThreads); return base; @@ -88,9 +88,9 @@ void* GPUTRDTracker_t<TRDTRK, PROP>::SetPointersTracklets(void* base) // Allocate memory for tracklets and space points // (size might change for different events) //-------------------------------------------------------------------- - computePointerWithAlignment(base, mTracklets, mNMaxSpacePoints); - computePointerWithAlignment(base, mSpacePoints, mNMaxSpacePoints); - computePointerWithAlignment(base, mTrackletLabels, 3 * mNMaxSpacePoints); + computePointerWithAlignment(base, mTracklets, mNMaxSpacePoints * mNMaxCollisions); + computePointerWithAlignment(base, mSpacePoints, mNMaxSpacePoints * mNMaxCollisions); + computePointerWithAlignment(base, mTrackletLabels, 3 * mNMaxSpacePoints * mNMaxCollisions); return base; } @@ -105,7 +105,7 @@ void* GPUTRDTracker_t<TRDTRK, PROP>::SetPointersTracks(void* base) } template <class TRDTRK, class PROP> -GPUTRDTracker_t<TRDTRK, PROP>::GPUTRDTracker_t() : mR(nullptr), mIsInitialized(false), mMemoryPermanent(-1), mMemoryTracklets(-1), mMemoryTracks(-1), mNMaxTracks(0), mNMaxSpacePoints(0), mTracks(nullptr), mNCandidates(1), mNTracks(0), mNEvents(0), mTracklets(nullptr), mMaxThreads(100), mNTracklets(0), mTrackletIndexArray(nullptr), mHypothesis(nullptr), mCandidates(nullptr), mSpacePoints(nullptr), mTrackletLabels(nullptr), mGeo(nullptr), mRPhiA2(0), mRPhiB(0), mRPhiC2(0), mDyA2(0), mDyB(0), mDyC2(0), mAngleToDyA(0), mAngleToDyB(0), mAngleToDyC(0), mDebugOutput(false), mRadialOffset(-0.1), mMinPt(2.f), mMaxEta(0.84f), mExtraRoadY(2.f), mRoadZ(18.f), mMaxChi2(15.0f), mMaxMissingLy(6), mChi2Penalty(12.0f), mZCorrCoefNRC(1.4f), mMCEvent(nullptr), mDebug(new GPUTRDTrackerDebug<TRDTRK>()) +GPUTRDTracker_t<TRDTRK, PROP>::GPUTRDTracker_t() : mR(nullptr), mIsInitialized(false), mProcessPerTimeFrame(false), mMemoryPermanent(-1), mMemoryTracklets(-1), mMemoryTracks(-1), mNMaxCollisions(1), mNMaxTracks(0), mNMaxSpacePoints(0), mTracks(nullptr), mNCandidates(1), mNCollisions(1), mNTracks(0), mNEvents(0), mTriggerRecordIndices(nullptr), mTriggerRecordTimes(nullptr), mTracklets(nullptr), mMaxThreads(100), mNTracklets(0), mTrackletIndexArray(nullptr), mHypothesis(nullptr), mCandidates(nullptr), mSpacePoints(nullptr), mTrackletLabels(nullptr), mGeo(nullptr), mRPhiA2(0), mRPhiB(0), mRPhiC2(0), mDyA2(0), mDyB(0), mDyC2(0), mAngleToDyA(0), mAngleToDyB(0), mAngleToDyC(0), mDebugOutput(false), mTimeWindow(.1f), mRadialOffset(-0.1), mMinPt(2.f), mMaxEta(0.84f), mExtraRoadY(2.f), mRoadZ(18.f), mMaxChi2(15.0f), mMaxMissingLy(6), mChi2Penalty(12.0f), mZCorrCoefNRC(1.4f), mMCEvent(nullptr), mDebug(new GPUTRDTrackerDebug<TRDTRK>()) { //-------------------------------------------------------------------- // Default constructor @@ -208,28 +208,38 @@ void GPUTRDTracker_t<TRDTRK, PROP>::DoTracking(GPUChainTracking* chainTracking) //-------------------------------------------------------------------- // sort tracklets and fill index array - CAAlgo::sort(mTracklets, mTracklets + mNTracklets); // tracklets are sorted by HCId - int* trkltIndexArray = &mTrackletIndexArray[1]; - trkltIndexArray[-1] = 0; - int currDet = 0; - int nextDet = 0; - int trkltCounter = 0; - for (int iTrklt = 0; iTrklt < mNTracklets; ++iTrklt) { - if (mTracklets[iTrklt].GetDetector() > currDet) { - nextDet = mTracklets[iTrklt].GetDetector(); - for (int iDet = currDet; iDet < nextDet; ++iDet) { - trkltIndexArray[iDet] = trkltCounter; + for (int iColl = 0; iColl < mNCollisions; ++iColl) { + int nTrklts = 0; + if (mProcessPerTimeFrame) { + // FIXME maybe two nested if statements are not so good in terms of performance? + nTrklts = (iColl < mNCollisions - 1) ? mTriggerRecordIndices[iColl + 1] - mTriggerRecordIndices[iColl] : mNTracklets - mTriggerRecordIndices[iColl]; + } else { + nTrklts = mNTracklets; + } + GPUTRDTrackletWord* tracklets = (mProcessPerTimeFrame) ? &(mTracklets[mTriggerRecordIndices[iColl]]) : mTracklets; + CAAlgo::sort(tracklets, tracklets + nTrklts); // tracklets are sorted by HCId + int* trkltIndexArray = &mTrackletIndexArray[iColl * (kNChambers + 1) + 1]; + trkltIndexArray[-1] = 0; + int currDet = 0; + int nextDet = 0; + int trkltCounter = 0; + for (int iTrklt = 0; iTrklt < nTrklts; ++iTrklt) { + if (tracklets[iTrklt].GetDetector() > currDet) { + nextDet = tracklets[iTrklt].GetDetector(); + for (int iDet = currDet; iDet < nextDet; ++iDet) { + trkltIndexArray[iDet] = trkltCounter; + } + currDet = nextDet; } - currDet = nextDet; + ++trkltCounter; + } + for (int iDet = currDet; iDet <= kNChambers; ++iDet) { + trkltIndexArray[iDet] = trkltCounter; } - ++trkltCounter; - } - for (int iDet = currDet; iDet <= kNChambers; ++iDet) { - trkltIndexArray[iDet] = trkltCounter; - } - if (!CalculateSpacePoints()) { - Error("DoTracking", "Space points for at least one chamber could not be calculated"); + if (!CalculateSpacePoints(iColl)) { + GPUError("Space points for at least one chamber could not be calculated"); + } } auto timeStart = std::chrono::high_resolution_clock::now(); @@ -241,7 +251,7 @@ void GPUTRDTracker_t<TRDTRK, PROP>::DoTracking(GPUChainTracking* chainTracking) #pragma omp parallel for for (int iTrk = 0; iTrk < mNTracks; ++iTrk) { if (omp_get_num_threads() > mMaxThreads) { - Error("DoTracking", "number of parallel threads too high, aborting tracking"); + GPUError("Number of parallel threads too high, aborting tracking"); // break statement not possible in OpenMP for loop iTrk = mNTracks; continue; @@ -422,7 +432,7 @@ GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTracklet(const GPUTRDTrackletWord& //-------------------------------------------------------------------- // Add single tracklet to tracker //-------------------------------------------------------------------- - if (mNTracklets >= mNMaxSpacePoints) { + if (mNTracklets >= mNMaxSpacePoints * mNMaxCollisions) { Error("LoadTracklet", "Running out of memory for tracklets, skipping tracklet(s). This should actually never happen."); return 1; } @@ -448,22 +458,43 @@ GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::DumpTracks() } } +template <class TRDTRK, class PROP> +GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::GetCollisionID(float trkTime) const +{ + for (int iColl = 0; iColl < mNCollisions; ++iColl) { + if (CAMath::Abs(trkTime - mTriggerRecordTimes[iColl]) < mTimeWindow) { + GPUInfo("TRD info found from interaction %i at %f for track with time %f", iColl, mTriggerRecordTimes[iColl], trkTime); + return iColl; + } + } + return -1; +} + template <class TRDTRK, class PROP> GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::DoTrackingThread(int iTrk, int threadId) { //-------------------------------------------------------------------- // perform the tracking for one track (must be threadsafe) //-------------------------------------------------------------------- + int collisionId = 0; + if (mProcessPerTimeFrame) { + collisionId = GetCollisionID(mTracks[iTrk].getTime()); + if (collisionId < 0) { + GPUInfo("Did not find TRD data for track with t=%f", mTracks[iTrk].getTime()); + // no TRD data available for the bunch crossing this track originates from + return; + } + } PROP prop(&Param().polynomialField); auto trkCopy = mTracks[iTrk]; prop.setTrack(&trkCopy); prop.setFitInProjections(true); - FollowProlongation(&prop, &trkCopy, threadId); + FollowProlongation(&prop, &trkCopy, threadId, collisionId); mTracks[iTrk] = trkCopy; // copy back the resulting track } template <class TRDTRK, class PROP> -GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CalculateSpacePoints() +GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CalculateSpacePoints(int iCollision) { //-------------------------------------------------------------------- // Calculates TRD space points in sector tracking coordinates @@ -471,10 +502,11 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CalculateSpacePoints() //-------------------------------------------------------------------- bool result = true; + int idxOffset = iCollision * (kNChambers + 1); for (int iDet = 0; iDet < kNChambers; ++iDet) { - int nTracklets = mTrackletIndexArray[iDet + 1] - mTrackletIndexArray[iDet]; + int nTracklets = mTrackletIndexArray[idxOffset + iDet + 1] - mTrackletIndexArray[idxOffset + iDet]; if (nTracklets == 0) { continue; } @@ -491,7 +523,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CalculateSpacePoints() float c2 = 1.f / (1.f + t2); // cos^2 (tilt) float sy2 = 0.1f * 0.1f; // sigma_rphi^2, currently assume sigma_rphi = 1 mm - for (int trkltIdx = mTrackletIndexArray[iDet]; trkltIdx < mTrackletIndexArray[iDet + 1]; ++trkltIdx) { + for (int trkltIdx = mTrackletIndexArray[idxOffset + iDet]; trkltIdx < mTrackletIndexArray[idxOffset + iDet + 1]; ++trkltIdx) { int trkltZbin = mTracklets[trkltIdx].GetZbin(); float sz2 = pp->GetRowSize(trkltZbin) * pp->GetRowSize(trkltZbin) / 12.f; // sigma_z = l_pad/sqrt(12) TODO try a larger z error My_Float xTrkltDet[3] = {0.f}; // trklt position in chamber coordinates @@ -523,7 +555,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CalculateSpacePoints() } template <class TRDTRK, class PROP> -GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK* t, int threadId) +GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK* t, int threadId, int collisionId) { //-------------------------------------------------------------------- // Propagate TPC track layerwise through TRD and pick up closest @@ -556,6 +588,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK int candidateIdxOffset = threadId * 2 * mNCandidates; int hypothesisIdxOffset = threadId * mNCandidates; + int trkltIdxOffset = collisionId * (kNChambers + 1); auto trkWork = t; if (mNCandidates > 1) { @@ -671,7 +704,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK } } // first propagate track to x of tracklet - for (int trkltIdx = mTrackletIndexArray[currDet]; trkltIdx < mTrackletIndexArray[currDet + 1]; ++trkltIdx) { + for (int trkltIdx = mTrackletIndexArray[trkltIdxOffset + currDet]; trkltIdx < mTrackletIndexArray[trkltIdxOffset + currDet + 1]; ++trkltIdx) { if (CAMath::Abs(trkWork->getY() - mSpacePoints[trkltIdx].mX[0]) > roadY || CAMath::Abs(trkWork->getZ() - mSpacePoints[trkltIdx].mX[1]) > roadZ) { // skip tracklets which are too far away // although the radii of space points and tracks may differ by ~ few mm the roads are large enough to allow no efficiency loss by this cut @@ -712,7 +745,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK } // end candidate loop #ifdef ENABLE_GPUMC - // in case matching tracklet exists in this layer -> store position information for debugging + // in case matching tracklet exists in this layer -> store position information for debugging FIXME: does not yet work for time frames in o2, but here we anyway do not yet have MC labels... if (matchAvailableAll[iLayer].size() > 0 && mDebugOutput) { mDebug->SetNmatchAvail(matchAvailableAll[iLayer].size(), iLayer); int realTrkltId = matchAvailableAll[iLayer].at(0); diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 9fbbffd870026..0b79fa6bad325 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -145,9 +145,10 @@ class GPUTRDTracker_t : public GPUProcessor mNTracks++; return (0); } + GPUd() int GetCollisionID(float trkTime) const; GPUd() void DoTrackingThread(int iTrk, int threadId = 0); - GPUd() bool CalculateSpacePoints(); - GPUd() bool FollowProlongation(PROP* prop, TRDTRK* t, int threadId); + GPUd() bool CalculateSpacePoints(int iCollision = 0); + GPUd() bool FollowProlongation(PROP* prop, TRDTRK* t, int threadId, int collisionId); GPUd() float GetPredictedChi2(const My_Float* pTRD, const My_Float* covTRD, const My_Float* pTrk, const My_Float* covTrk) const; GPUd() int GetDetectorNumber(const float zPos, const float alpha, const int layer) const; GPUd() bool AdjustSector(PROP* prop, TRDTRK* t, const int layer) const; @@ -166,7 +167,14 @@ class GPUTRDTracker_t : public GPUProcessor GPUd() void Quicksort(const int left, const int right, const int size); GPUd() void InsertHypothesis(Hypothesis hypo, int& nCurrHypothesis, int idxOffset); + // input from TRD trigger record + GPUd() void SetNMaxCollisions(int nColl) { mNMaxCollisions = nColl; } // can this be fixed to a sufficiently large value? + GPUd() void SetNCollisions(int nColl) { mNCollisions = nColl; } + GPUd() void SetTriggerRecordIndices(int* indices) { mTriggerRecordIndices = indices; } + GPUd() void SetTriggerRecordTimes(float* times) { mTriggerRecordTimes = times; } + // settings + GPUd() void SetProcessPerTimeFrame() { mProcessPerTimeFrame = true; } GPUd() void SetMCEvent(AliMCEvent* mc) { mMCEvent = mc; } GPUd() void EnableDebugOutput() { mDebugOutput = true; } GPUd() void SetPtThreshold(float minPt) { mMinPt = minPt; } @@ -199,15 +207,20 @@ class GPUTRDTracker_t : public GPUProcessor protected: float* mR; // radial position of each TRD chamber, alignment taken into account, radial spread within chambers < 7mm bool mIsInitialized; // flag is set upon initialization + bool mProcessPerTimeFrame; // if true, tracking is done per time frame instead of on a single events basis //FIXME is this needed?? short mMemoryPermanent; // size of permanent memory for the tracker short mMemoryTracklets; // size of memory for TRD tracklets short mMemoryTracks; // size of memory for tracks (used for i/o) + int mNMaxCollisions; // max number of collisions to process (per time frame) int mNMaxTracks; // max number of tracks the tracker can handle (per event) int mNMaxSpacePoints; // max number of space points hold by the tracker (per event) TRDTRK* mTracks; // array of trd-updated tracks int mNCandidates; // max. track hypothesis per layer + int mNCollisions; // number of collisions with TRD tracklet data int mNTracks; // number of TPC tracks to be matched int mNEvents; // number of processed events + int* mTriggerRecordIndices; // index of first tracklet for each collision + float* mTriggerRecordTimes; // time in us for each collision GPUTRDTrackletWord* mTracklets; // array of all tracklets, later sorted by HCId int mMaxThreads; // maximum number of supported threads int mNTracklets; // total number of tracklets in event @@ -229,6 +242,7 @@ class GPUTRDTracker_t : public GPUProcessor float mAngleToDyC; // parameterization for conversion track angle -> tracklet deflection /// ---- end error parametrization ---- bool mDebugOutput; // store debug output + float mTimeWindow; // max. deviation of the ITS-TPC track time w.r.t. TRD trigger record time stamp (in us, default is 100 ns) float mRadialOffset; // due to mis-calibration of t0 float mMinPt; // min pt of TPC tracks for tracking float mMaxEta; // TPC tracks with higher eta are ignored diff --git a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C index c7fc292457c82..198c13fcb243c 100644 --- a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C +++ b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C @@ -15,24 +15,29 @@ #include "GPUTRDGeometry.h" // O2 header +#include "DetectorsCommonDataFormats/NameConf.h" +#include "CommonConstants/LHCConstants.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "TRDBase/Tracklet.h" +#include "DataFormatsTRD/TriggerRecord.h" #endif using namespace GPUCA_NAMESPACE::gpu; void run_trd_tracker(std::string path = "./", - std::string inputGRP = "o2sim_grp.root", std::string inputTracks = "o2match_itstpc.root", std::string inputTracklets = "trdtracklets.root") { + //-------- debug time information from tracks and tracklets + std::vector<float> trdTriggerTimes; + std::vector<int> trdTriggerIndices; //-------- init geometry and field --------// - o2::base::GeometryManager::loadGeometry(path); - o2::base::Propagator::initFieldFromGRP(path + inputGRP); + o2::base::GeometryManager::loadGeometry(); + o2::base::Propagator::initFieldFromGRP(o2::base::NameConf::getGRPFileName()); auto geo = o2::trd::TRDGeometry::instance(); geo->createPadPlaneArray(); @@ -43,9 +48,11 @@ void run_trd_tracker(std::string path = "./", GPUSettingsEvent cfgEvent; // defaults should be ok GPUSettingsRec cfgRec; // don't care for now, NWaysOuter is set in here for instance GPUSettingsProcessing cfgDeviceProcessing; // also keep defaults here, or adjust debug level - cfgDeviceProcessing.debugLevel = 10; + cfgDeviceProcessing.debugLevel = 5; GPURecoStepConfiguration cfgRecoStep; cfgRecoStep.steps = GPUDataTypes::RecoStep::NoRecoStep; + cfgRecoStep.inputs.clear(); + cfgRecoStep.outputs.clear(); auto rec = GPUReconstruction::CreateInstance("CPU", true); rec->SetSettings(&cfgEvent, &cfgRec, &cfgDeviceProcessing, &cfgRecoStep); @@ -53,12 +60,14 @@ void run_trd_tracker(std::string path = "./", auto tracker = new GPUTRDTracker(); tracker->SetNCandidates(1); // must be set before initialization + tracker->SetProcessPerTimeFrame(); + tracker->SetNMaxCollisions(100); rec->RegisterGPUProcessor(tracker, false); chainTracking->SetTRDGeometry(&geoFlat); - tracker->SetTrackingChain(chainTracking); - rec->Init(); - rec->AllocateRegisteredMemory(nullptr); + if (rec->Init()) { + printf("ERROR: GPUReconstruction not initialized\n"); + } // configure the tracker //tracker->EnableDebugOutput(); @@ -85,23 +94,34 @@ void run_trd_tracker(std::string path = "./", TChain trdTracklets("o2sim"); trdTracklets.AddFile((path + inputTracklets).c_str()); + std::vector<o2::trd::TriggerRecord>* triggerRecordsInArrayPtr = nullptr; + trdTracklets.SetBranchAddress("TrackTrg", &triggerRecordsInArrayPtr); std::vector<o2::trd::Tracklet>* trackletsInArrayPtr = nullptr; trdTracklets.SetBranchAddress("Tracklet", &trackletsInArrayPtr); trdTracklets.GetEntry(0); + int nCollisions = triggerRecordsInArrayPtr->size(); int nTracklets = trackletsInArrayPtr->size(); - printf("There are %i tracklets in total\n", nTracklets); - - auto pp = geo->getPadPlane(0, 0); - printf("Tilt=%f\n", pp->getTiltingAngle()); + printf("There are %i tracklets in total from %i trigger records\n", nTracklets, nCollisions); + + for (int iEv = 0; iEv < nCollisions; ++iEv) { + o2::trd::TriggerRecord& trg = triggerRecordsInArrayPtr->at(iEv); + int nTrackletsCurrent = trg.getNumberOfObjects(); + int iFirstTracklet = trg.getFirstEntry(); + int64_t evTime = trg.getBCData().toLong() * o2::constants::lhc::LHCBunchSpacingNS; // event time in ns + trdTriggerTimes.push_back(evTime / 1000.); + trdTriggerIndices.push_back(iFirstTracklet); + printf("Event %i: Occured at %li us after SOR, contains %i tracklets, index of first tracklet is %i\n", iEv, evTime / 1000, nTrackletsCurrent, iFirstTracklet); + } - tracker->Reset(true); + tracker->Reset(); chainTracking->mIOPtrs.nMergedTracks = nTracks; chainTracking->mIOPtrs.nTRDTracklets = nTracklets; chainTracking->AllocateIOMemory(); rec->PrepareEvent(); - rec->AllocateRegisteredMemory(tracker->MemoryTracks()); + rec->SetupGPUProcessor(tracker, true); + printf("Start loading input into TRD tracker\n"); // load everything into the tracker for (int iTrk = 0; iTrk < nTracks; ++iTrk) { auto trk = tracksInArrayPtr->at(iTrk); @@ -114,8 +134,11 @@ void run_trd_tracker(std::string path = "./", for (int i = 0; i < 15; ++i) { trkLoad.setCov(trk.getCov()[i], i); } + trkLoad.setTime(trk.getTimeMUS().getTimeStamp()); tracker->LoadTrack(trkLoad); + printf("Loaded track %i with time %f\n", iTrk, trkLoad.getTime()); } + for (int iTrklt = 0; iTrklt < nTracklets; ++iTrklt) { auto trklt = trackletsInArrayPtr->at(iTrklt); unsigned int trkltWord = trklt.getTrackletWord(); @@ -127,9 +150,11 @@ void run_trd_tracker(std::string path = "./", printf("Could not load tracklet %i\n", iTrklt); } } + tracker->SetTriggerRecordTimes(&(trdTriggerTimes[0])); + tracker->SetTriggerRecordIndices(&(trdTriggerIndices[0])); + tracker->SetNCollisions(nCollisions); tracker->DumpTracks(); - tracker->DoTracking(); + tracker->DoTracking(chainTracking); tracker->DumpTracks(); - printf("Done\n"); } From 96b986f16860d814544f8acca11429d33d6eb802 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Mon, 7 Sep 2020 14:27:24 +0200 Subject: [PATCH 0764/1751] Remove erroneous chi2 calculation causing FPEs --- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 38 +------------------ GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 4 +- .../TRDTracking/GPUTRDTrackerDebug.h | 11 ------ 3 files changed, 2 insertions(+), 51 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index 5f3c7814bf63b..d9a54dfa2391c 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -731,7 +731,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK float chi2 = prop->getPredictedChi2(trkltPosTmpYZ, trkltCovTmp); // GPUInfo("layer %i: chi2 = %f", iLayer, chi2); if (chi2 < mMaxChi2 && CAMath::Abs(GetAngularPull(mSpacePoints[trkltIdx].mDy, trkWork->getSnp())) < 4) { - Hypothesis hypo(trkWork->GetNlayers(), iCandidate, trkltIdx, trkWork->GetChi2() + chi2, GetPredictedChi2(trkltPosTmpYZ, trkltCovTmp, trkWork->getPar(), trkWork->getCov())); + Hypothesis hypo(trkWork->GetNlayers(), iCandidate, trkltIdx, trkWork->GetChi2() + chi2); InsertHypothesis(hypo, nCurrHypothesis, hypothesisIdxOffset); } // end tracklet chi2 < mMaxChi2 } // end tracklet in window @@ -769,7 +769,6 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK My_Float covReal[3] = {0.}; RecalcTrkltCov(tilt, trkWork->getSnp(), pad->GetRowSize(mTracklets[realTrkltId].GetZbin()), covReal); mDebug->SetChi2Real(prop->getPredictedChi2(yzPosReal, covReal), iLayer); - mDebug->SetChi2YZPhiReal(GetPredictedChi2(yzPosReal, covReal, trkWork->getPar(), trkWork->getCov()), iLayer); mDebug->SetRawTrackletPositionReal(mSpacePoints[realTrkltId].mR, mSpacePoints[realTrkltId].mX, iLayer); mDebug->SetCorrectedTrackletPositionReal(yzPosReal, iLayer); mDebug->SetTrackletPropertiesReal(mTracklets[realTrkltId].GetDetector(), iLayer); @@ -778,7 +777,6 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK #endif // mDebug->SetChi2Update(mHypothesis[0 + hypothesisIdxOffset].mChi2 - t->GetChi2(), iLayer); // only meaningful for ONE candidate!!! - mDebug->SetChi2YZPhiUpdate(mHypothesis[0 + hypothesisIdxOffset].mChi2YZPhi, iLayer); // only meaningful for ONE candidate!!! mDebug->SetRoad(roadY, roadZ, iLayer); // only meaningful for ONE candidate bool wasTrackStored = false; // -------------------------------------------------------------------------------- @@ -989,40 +987,6 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK return true; } -template <class TRDTRK, class PROP> -GPUd() float GPUTRDTracker_t<TRDTRK, PROP>::GetPredictedChi2(const My_Float* pTRD, const My_Float* covTRD, const My_Float* pTrk, const My_Float* covTrk) const -{ - // FIXME: This function cannot yet be used in production (maybe it is not necessary at all?) - // conversion from tracklet deflection to sin(phi) needs to be parametrized - // predict chi2 for update of track with pTrk and covTrk with TRD space point with pTRD and covTRD - // taking into account y, z and azimuthal angle of the track and tracklet - float deltaY = pTrk[0] - pTRD[0]; - float deltaZ = pTrk[1] - pTRD[1]; - float deltaS = pTrk[2] - pTRD[2]; // FIXME: pTRD[2] is not defined, needs conversion dy -> sin(phi) - - // add errors for track and space point, assume no correlation in y-sin(phi) and z-sin(phi) for space point - float sigmaZ2 = covTrk[2] + covTRD[2]; - float sigmaS2 = covTrk[5] + GetAngularResolution(pTrk[2]); // FIXME: convert angular resolution from dy to sin(phi) for the TRD space point - float sigmaY2 = covTrk[0] + covTRD[0]; - float sigmaZS = covTrk[4]; - float sigmaYS = covTrk[3]; - float sigmaYZ = covTrk[1] + covTRD[1]; - // inverse of the covariance matrix - float c11 = sigmaZ2 * sigmaS2 - sigmaZS * sigmaZS; - float c21 = sigmaZS * sigmaYS - sigmaYZ * sigmaS2; - float c22 = sigmaY2 * sigmaS2 - sigmaYS * sigmaYS; - float c31 = sigmaYZ * sigmaZS - sigmaZ2 * sigmaYS; - float c32 = sigmaYZ * sigmaYS - sigmaY2 * sigmaZS; - float c33 = sigmaY2 * sigmaZ2 - sigmaYZ * sigmaYZ; - // determinant - float det = sigmaY2 * sigmaZ2 * sigmaS2 + 2 * sigmaYZ * sigmaZS * sigmaYS - sigmaYS * sigmaYS * sigmaZ2 - sigmaZS * sigmaZS * sigmaY2 - sigmaS2 * sigmaYZ * sigmaYZ; - if (CAMath::Abs(det) < 1.e-10f) { - printf("Determinant too small: %f\n", det); - det = 1.e-10f; - } - det = 1.f / det; - return (c11 * deltaY * deltaY + 2.f * c21 * deltaY * deltaZ + 2.f * c31 * deltaY * deltaS + c22 * deltaZ * deltaZ + 2.f * c32 * deltaZ * deltaS + c33 * deltaS * deltaS) * det; -} template <class TRDTRK, class PROP> GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::InsertHypothesis(Hypothesis hypo, int& nCurrHypothesis, int idxOffset) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 0b79fa6bad325..62f2193f023c4 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -95,11 +95,10 @@ class GPUTRDTracker_t : public GPUProcessor int mCandidateId; // to which track candidate the hypothesis belongs int mTrackletId; // tracklet index to be used for update float mChi2; // predicted chi2 for given space point - float mChi2YZPhi; // not yet ready (see GetPredictedChi2 method in cxx file) GPUd() float GetReducedChi2() { return mLayers > 0 ? mChi2 / mLayers : mChi2; } GPUd() Hypothesis() : mLayers(0), mCandidateId(-1), mTrackletId(-1), mChi2(9999.f) {} - GPUd() Hypothesis(int layers, int candidateId, int trackletId, float chi2, float chi2YZPhi = -1.f) : mLayers(layers), mCandidateId(candidateId), mTrackletId(trackletId), mChi2(chi2), mChi2YZPhi(chi2YZPhi) {} + GPUd() Hypothesis(int layers, int candidateId, int trackletId, float chi2, float chi2YZPhi = -1.f) : mLayers(layers), mCandidateId(candidateId), mTrackletId(trackletId), mChi2(chi2) {} }; short MemoryPermanent() const { return mMemoryPermanent; } @@ -149,7 +148,6 @@ class GPUTRDTracker_t : public GPUProcessor GPUd() void DoTrackingThread(int iTrk, int threadId = 0); GPUd() bool CalculateSpacePoints(int iCollision = 0); GPUd() bool FollowProlongation(PROP* prop, TRDTRK* t, int threadId, int collisionId); - GPUd() float GetPredictedChi2(const My_Float* pTRD, const My_Float* covTRD, const My_Float* pTrk, const My_Float* covTrk) const; GPUd() int GetDetectorNumber(const float zPos, const float alpha, const int layer) const; GPUd() bool AdjustSector(PROP* prop, TRDTRK* t, const int layer) const; GPUd() int GetSector(float alpha) const; diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerDebug.h b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerDebug.h index 209dfdfc807f3..08b453d4f2345 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerDebug.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerDebug.h @@ -95,9 +95,7 @@ class GPUTRDTrackerDebug fTrackYReal.ResizeTo(6); fTrackZReal.ResizeTo(6); fTrackSecReal.ResizeTo(6); - fChi2YZPhiUpdate.ResizeTo(6); fChi2Update.ResizeTo(6); - fChi2YZPhiReal.ResizeTo(6); fChi2Real.ResizeTo(6); fNmatchesAvail.ResizeTo(6); fFindable.ResizeTo(6); @@ -151,9 +149,7 @@ class GPUTRDTrackerDebug fTrackYReal.Zero(); fTrackZReal.Zero(); fTrackSecReal.Zero(); - fChi2YZPhiUpdate.Zero(); fChi2Update.Zero(); - fChi2YZPhiReal.Zero(); fChi2Real.Zero(); fNmatchesAvail.Zero(); fFindable.Zero(); @@ -290,8 +286,6 @@ class GPUTRDTrackerDebug // update information void SetChi2Update(float chi2, int ly) { fChi2Update(ly) = chi2; } void SetChi2Real(float chi2, int ly) { fChi2Real(ly) = chi2; } - void SetChi2YZPhiUpdate(float chi2, int ly) { fChi2YZPhiUpdate(ly) = chi2; } - void SetChi2YZPhiReal(float chi2, int ly) { fChi2YZPhiReal(ly) = chi2; } // other infos void SetRoad(float roadY, float roadZ, int ly) @@ -370,8 +364,6 @@ class GPUTRDTrackerDebug "trackletDetReal.=" << &fTrackletDetReal << // detector number for matching or related tracklet if available, otherwise -1 "chi2Update.=" << &fChi2Update << // chi2 for update "chi2Real.=" << &fChi2Real << // chi2 for first tracklet w/ matching MC label - "chi2YZPhiUpdate.=" << &fChi2YZPhiUpdate << // chi2 for update taking into account full tracklet information (y, z, dY aka sin(phi)) - "chi2YZPhiReal.=" << &fChi2YZPhiReal << // chi2 for first tracklet w/ matching MC label taking into account full tracklet information (y, z, dY aka sin(phi)) "chi2Total=" << fChi2 << // total chi2 for track "nLayers=" << fNlayers << // number of layers in which track was findable "nTracklets=" << fNtrklts << // number of attached tracklets @@ -456,8 +448,6 @@ class GPUTRDTrackerDebug TVectorF fTrackletDetReal; TVectorF fChi2Update; TVectorF fChi2Real; - TVectorF fChi2YZPhiUpdate; - TVectorF fChi2YZPhiReal; TVectorF fRoadY; TVectorF fRoadZ; TVectorF fFindable; @@ -512,7 +502,6 @@ class GPUTRDTrackerDebug GPUd() void SetChi2Update(float chi2, int ly) {} GPUd() void SetChi2Real(float chi2, int ly) {} GPUd() void SetChi2YZPhiUpdate(float chi2, int ly) {} - GPUd() void SetChi2YZPhiReal(float chi2, int ly) {} // other infos GPUd() void SetRoad(float roadY, float roadZ, int ly) {} From 772c2205959bf188fd3b389ccebde3e7b06af3b8 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 15 Sep 2020 15:59:22 +0200 Subject: [PATCH 0765/1751] Adapt TRD tracker steering macro to new data type --- .../TRDTracking/macros/run_trd_tracker.C | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C index 198c13fcb243c..9d5212704ef4e 100644 --- a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C +++ b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C @@ -19,14 +19,25 @@ #include "CommonConstants/LHCConstants.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" +#include "TRDBase/TRDGeometry.h" #include "ReconstructionDataFormats/TrackTPCITS.h" -#include "TRDBase/Tracklet.h" +#include "DataFormatsTRD/Tracklet64.h" #include "DataFormatsTRD/TriggerRecord.h" #endif using namespace GPUCA_NAMESPACE::gpu; +unsigned int convertTrkltWordToRun2Format(uint64_t trkltWordRun3) +{ + // FIXME: this is currently a dummy function + // need proper functionality to convert the new tracklet data format to + // something compatible with the TRD tracker, but this macro is probably + // not the right place for this + unsigned int trkltWord = 0; + return trkltWord; +} + void run_trd_tracker(std::string path = "./", std::string inputTracks = "o2match_itstpc.root", std::string inputTracklets = "trdtracklets.root") @@ -96,7 +107,7 @@ void run_trd_tracker(std::string path = "./", std::vector<o2::trd::TriggerRecord>* triggerRecordsInArrayPtr = nullptr; trdTracklets.SetBranchAddress("TrackTrg", &triggerRecordsInArrayPtr); - std::vector<o2::trd::Tracklet>* trackletsInArrayPtr = nullptr; + std::vector<o2::trd::Tracklet64>* trackletsInArrayPtr = nullptr; trdTracklets.SetBranchAddress("Tracklet", &trackletsInArrayPtr); trdTracklets.GetEntry(0); int nCollisions = triggerRecordsInArrayPtr->size(); @@ -141,10 +152,10 @@ void run_trd_tracker(std::string path = "./", for (int iTrklt = 0; iTrklt < nTracklets; ++iTrklt) { auto trklt = trackletsInArrayPtr->at(iTrklt); - unsigned int trkltWord = trklt.getTrackletWord(); + unsigned int trkltWord = convertTrkltWordToRun2Format(trklt.getTrackletWord()); GPUTRDTrackletWord trkltLoad; trkltLoad.SetId(iTrklt); - trkltLoad.SetHCId(trklt.getHCId()); + trkltLoad.SetHCId(trklt.getHCID()); trkltLoad.SetTrackletWord(trkltWord); if (tracker->LoadTracklet(trkltLoad) > 0) { printf("Could not load tracklet %i\n", iTrklt); From 63a056d2d1663fd84cafd39684c801ca94e48879 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Wed, 16 Sep 2020 09:00:12 +0200 Subject: [PATCH 0766/1751] Add missing LinkDef for Tracklet64 class --- DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h | 1 + 1 file changed, 1 insertion(+) diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index f4e87501d4f9f..4fe89c45df5ff 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -21,6 +21,7 @@ #pragma link C++ struct o2::trd::TrackletMCMHeader + ; #pragma link C++ struct o2::trd::TrackletMCMData + ; #pragma link C++ class o2::trd::Tracklet64 + ; +#pragma link C++ class std::vector < o2::trd::Tracklet64> + ; #pragma link C++ class std::vector < o2::trd::TriggerRecord > +; #pragma link C++ class std::vector < o2::trd::LinkRecord > +; From 6b0837d69ba97b2effbc45a92d1fdc6406aa20bc Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Fri, 25 Sep 2020 09:46:26 +0200 Subject: [PATCH 0767/1751] Disable material correction for O2 tracking --- GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h index 42d762b8480bd..990b9aa318c51 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h @@ -200,7 +200,7 @@ class propagatorInterface<o2::base::Propagator> propagatorInterface<o2::base::Propagator>(const propagatorInterface<o2::base::Propagator>&) = delete; propagatorInterface<o2::base::Propagator>& operator=(const propagatorInterface<o2::base::Propagator>&) = delete; - bool propagateToX(float x, float maxSnp, float maxStep) { return mProp->PropagateToXBxByBz(*mParam, x, 0.13957, maxSnp, maxStep); } + bool propagateToX(float x, float maxSnp, float maxStep) { return mProp->PropagateToXBxByBz(*mParam, x, 0.13957, maxSnp, maxStep, o2::base::Propagator::MatCorrType::USEMatCorrNONE); } int getPropagatedYZ(My_Float x, My_Float& projY, My_Float& projZ) { return static_cast<int>(mParam->getYZAt(x, mProp->getNominalBz(), projY, projZ)); } void setTrack(trackInterface<o2::dataformats::TrackTPCITS>* trk) { mParam = trk; } From 2c70ff95f23981ef8836010886521179e599b9f5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 13:41:14 +0200 Subject: [PATCH 0768/1751] GPU: Compilation fixes towards CUDA RTC --- .../cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h | 2 ++ Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu | 3 ++- Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu | 2 ++ Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu | 3 +++ GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h | 1 + 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h index 5d2d7a9d8cd78..6bf180fcb93ad 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h @@ -16,7 +16,9 @@ #ifndef O2_ITS_TRACKING_DEVICE_STORE_VERTEXER_GPU_H_ #define O2_ITS_TRACKING_DEVICE_STORE_VERTEXER_GPU_H_ +#ifndef GPUCA_GPUCODE_GENRTC #include <cub/cub.cuh> +#endif #include "ITStracking/Cluster.h" #include "ITStracking/Constants.h" diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu index 6155a94cc5d83..186f0b25ead9a 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu @@ -18,9 +18,10 @@ #include <sstream> #include <iostream> +#ifndef GPUCA_GPUCODE_GENRTC #include <cooperative_groups.h> - #include "cub/cub.cuh" +#endif #include "ITStracking/Constants.h" #include "ITStracking/Configuration.h" diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu index 5ab543d03c20e..5dbe67abe9e51 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu @@ -17,8 +17,10 @@ #include <sstream> #include <stdexcept> +#ifndef GPUCA_GPUCODE_GENRTC #include <cuda_profiler_api.h> #include <cooperative_groups.h> +#endif #include "ITStrackingCUDA/Context.h" diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu index 033dd69e2d526..790a7b9f5b3bb 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu @@ -16,7 +16,10 @@ #include <sstream> #include <array> #include <assert.h> + +#ifndef GPUCA_GPUCODE_GENRTC #include <cub/cub.cuh> +#endif #include "ITStracking/MathUtils.h" #include "ITStracking/Configuration.h" diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h index fff90de9349f8..449a4d889585f 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h @@ -17,6 +17,7 @@ #include <stdint.h> #include <cuda_runtime.h> #include <cuda.h> +#include <cooperative_groups.h> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #include <cub/cub.cuh> From 001dbb2ba844d8f6d848478450d25db7ea3ba6de Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 14:05:07 +0200 Subject: [PATCH 0769/1751] Fix compiler warning on unused variable --- Detectors/TPC/base/include/TPCBase/Mapper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/base/include/TPCBase/Mapper.h b/Detectors/TPC/base/include/TPCBase/Mapper.h index c810ac1e6ee5a..c6c722fe8b06f 100644 --- a/Detectors/TPC/base/include/TPCBase/Mapper.h +++ b/Detectors/TPC/base/include/TPCBase/Mapper.h @@ -593,7 +593,7 @@ inline const DigitPos Mapper::findDigitPosFromGlobalPosition(const GlobalPositio if (phi < 0.) phi += TWOPI; const unsigned char secNum = std::floor(phi / SECPHIWIDTH); - const float secPhi = secNum * SECPHIWIDTH + SECPHIWIDTH / 2.; + // const float secPhi = secNum * SECPHIWIDTH + SECPHIWIDTH / 2.; Sector sec(secNum + (pos.Z() < 0) * SECTORSPERSIDE); // ===| rotated position |==================================================== From 2b89a7f82a589a09c0c5a429c0cf0143dd349a2f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 14:06:10 +0200 Subject: [PATCH 0770/1751] Don do using namespace in header --- Detectors/TPC/base/include/TPCBase/CalArray.h | 6 +++--- Detectors/TPC/base/include/TPCBase/CalDet.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/CalArray.h b/Detectors/TPC/base/include/TPCBase/CalArray.h index 839df16c2b4e5..e043670a4ab16 100644 --- a/Detectors/TPC/base/include/TPCBase/CalArray.h +++ b/Detectors/TPC/base/include/TPCBase/CalArray.h @@ -156,21 +156,21 @@ void CalArray<T>::initData() case PadSubset::ROC: { mData.resize(ROC(mPadSubsetNumber).rocType() == RocType::IROC ? mapper.getPadsInIROC() : mapper.getPadsInOROC()); if (mName.empty()) { - setName(boost::str(format("ROC_%1$02d") % mPadSubsetNumber)); + setName(boost::str(boost::format("ROC_%1$02d") % mPadSubsetNumber)); } break; } case PadSubset::Partition: { mData.resize(mapper.getPartitionInfo(mPadSubsetNumber % mapper.getNumberOfPartitions()).getNumberOfPads()); if (mName.empty()) { - setName(boost::str(format("Partition_%1$03d") % mPadSubsetNumber)); + setName(boost::str(boost::format("Partition_%1$03d") % mPadSubsetNumber)); } break; } case PadSubset::Region: { mData.resize(mapper.getPadRegionInfo(mPadSubsetNumber % mapper.getNumberOfPadRegions()).getNumberOfPads()); if (mName.empty()) { - setName(boost::str(format("Region_%1$03d") % mPadSubsetNumber)); + setName(boost::str(boost::format("Region_%1$03d") % mPadSubsetNumber)); } break; } diff --git a/Detectors/TPC/base/include/TPCBase/CalDet.h b/Detectors/TPC/base/include/TPCBase/CalDet.h index bfc68b5eb5855..7329f95a418c7 100644 --- a/Detectors/TPC/base/include/TPCBase/CalDet.h +++ b/Detectors/TPC/base/include/TPCBase/CalDet.h @@ -336,7 +336,7 @@ void CalDet<T>::initData() for (size_t i = 0; i < size; ++i) { mData.push_back(CalType(mPadSubset, i)); - mData.back().setName(boost::str(format(frmt) % mName % i)); + mData.back().setName(boost::str(boost::format(frmt) % mName % i)); } } From 80931726ea892fcd20f764e8019a031c7fbcfdf2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 14:06:25 +0200 Subject: [PATCH 0771/1751] GPU: Hide some code from GPU standalone compilation --- Detectors/TPC/base/include/TPCBase/CalArray.h | 13 +++++++++---- Detectors/TPC/base/include/TPCBase/CalDet.h | 14 +++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/CalArray.h b/Detectors/TPC/base/include/TPCBase/CalArray.h index e043670a4ab16..6cab619159606 100644 --- a/Detectors/TPC/base/include/TPCBase/CalArray.h +++ b/Detectors/TPC/base/include/TPCBase/CalArray.h @@ -17,13 +17,13 @@ #include <string> #include <numeric> #include <type_traits> -#include <boost/format.hpp> - -#include "FairLogger.h" #include "TPCBase/Mapper.h" -using boost::format; +#ifndef GPUCA_ALIGPUCODE +#include "FairLogger.h" +#include <boost/format.hpp> +#endif namespace o2 { @@ -146,6 +146,8 @@ class CalArray void initData(); }; +#ifndef GPUCA_ALIGPUCODE + // ===| pad region etc. initialisation |======================================== template <class T> void CalArray<T>::initData() @@ -298,6 +300,9 @@ inline const CalArray<T>& CalArray<T>::operator/=(const T& val) } using CalROC = CalArray<float>; + +#endif // GPUCA_ALIGPUCODE + } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/base/include/TPCBase/CalDet.h b/Detectors/TPC/base/include/TPCBase/CalDet.h index 7329f95a418c7..f00794beb08a7 100644 --- a/Detectors/TPC/base/include/TPCBase/CalDet.h +++ b/Detectors/TPC/base/include/TPCBase/CalDet.h @@ -14,19 +14,19 @@ #include <memory> #include <vector> #include <string> -#include <boost/format.hpp> -#include <boost/range/combine.hpp> #include <cassert> -#include <FairLogger.h> - #include "DataFormatsTPC/Defs.h" #include "TPCBase/Mapper.h" #include "TPCBase/ROC.h" #include "TPCBase/Sector.h" #include "TPCBase/CalArray.h" -using boost::format; +#ifndef GPUCA_ALIGPUCODE +#include <Framework/Logger.h> +#include <boost/format.hpp> +#include <boost/range/combine.hpp> +#endif namespace o2 { @@ -182,6 +182,8 @@ inline const T CalDet<T>::getValue(const CRU cru, const size_t row, const size_t return T{}; } +#ifndef GPUCA_ALIGPUCODE // hide from GPU standalone compilation + //______________________________________________________________________________ template <class T> inline const CalDet<T>& CalDet<T>::operator+=(const CalDet& other) @@ -340,6 +342,8 @@ void CalDet<T>::initData() } } +#endif // GPUCA_ALIGPUCODE + using CalPad = CalDet<float>; } // namespace tpc } // namespace o2 From 13216b751da5e6826f00cd583bfc8b4615232922 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 15:25:55 +0200 Subject: [PATCH 0772/1751] GPU: remove debug code --- GPU/GPUTracking/Base/opencl-common/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/opencl-common/CMakeLists.txt b/GPU/GPUTracking/Base/opencl-common/CMakeLists.txt index 6e81224ecb7d1..f2f39ae5f040e 100644 --- a/GPU/GPUTracking/Base/opencl-common/CMakeLists.txt +++ b/GPU/GPUTracking/Base/opencl-common/CMakeLists.txt @@ -55,6 +55,6 @@ if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") add_definitions(-DGPUCA_GPULIBRARY=OCL) add_library(${MODULE} SHARED ${SRCS}) target_link_libraries(${MODULE} GPUTracking OpenCL) - target_include_directories(${MODULE} PUBLIC foo ${CMAKE_CURRENT_LIST_DIR}) + target_include_directories(${MODULE} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) install(TARGETS ${MODULE}) endif() From 9fd3b0ec4348dee72725b9a77aeb4e78b02bad02 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 19:22:03 +0200 Subject: [PATCH 0773/1751] GPU: Fix GPU compilation without O2 headers after TPCPadGainCalib changes --- GPU/GPUTracking/Base/GPUO2FakeClasses.h | 3 +++ GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/GPU/GPUTracking/Base/GPUO2FakeClasses.h b/GPU/GPUTracking/Base/GPUO2FakeClasses.h index c4e49ca52d612..49431fe94427d 100644 --- a/GPU/GPUTracking/Base/GPUO2FakeClasses.h +++ b/GPU/GPUTracking/Base/GPUO2FakeClasses.h @@ -79,6 +79,9 @@ namespace GPUCA_NAMESPACE { namespace gpu { +class TPCCFCalibration +{ +}; class TPCdEdxCalibrationSplines { }; diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index e09ab06e63751..f71b3b77a7a84 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -254,6 +254,10 @@ bool GPUChainTracking::ValidateSteps() GPUError("Cannot run dE/dx without calibration splines"); return false; } + if ((GetRecoSteps() & GPUDataTypes::RecoStep::TPCClusterFinding) && processors()->calibObjects.tpcCalibration == nullptr) { + GPUError("Cannot run gain calibration without calibration object"); + return false; + } return true; } From 5691fdbc076f384ddcbb8a6ac294b8a4c4e88fd2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 19:22:27 +0200 Subject: [PATCH 0774/1751] GPU: Fix initialization of AliRoot HLT TRD tracking --- GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx index 0eaa192f37778..9dd31acd90b2a 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx @@ -191,7 +191,7 @@ int GPUTRDTrackerComponent::DoInit(int argc, const char** argv) cfgRecoStep.inputs.clear(); cfgRecoStep.outputs.clear(); fRec = GPUReconstruction::CreateInstance("CPU", true); - fRec->SetSettings(GetBz()); + fRec->SetSettings(&cfgEvent, &cfgRec, &cfgDeviceProcessing, &cfgRecoStep); fChain = fRec->AddChain<GPUChainTracking>(); fGeo = new GPUTRDGeometry(); From ebea649c4fa6fcaf2e53307292c55ef9af2cc695 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 19:34:32 +0200 Subject: [PATCH 0775/1751] GPU: Fix debug output reporting number of TRD tracks --- GPU/GPUTracking/Standalone/standalone.cxx | 8 +++++--- GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index a11a34990650f..8ea432889625d 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -565,12 +565,14 @@ void OutputStat(GPUChainTracking* t, long long int* nTracksTotal = nullptr, long char trdText[1024] = ""; if (t->GetRecoSteps() & GPUDataTypes::RecoStep::TRDTracking) { - int nTracklets = 0; + int nTRDTracks = 0; + int nTRDTracklets = 0; for (unsigned int k = 0; k < t->mIOPtrs.nTRDTracks; k++) { auto& trk = t->mIOPtrs.trdTracks[k]; - nTracklets += trk.GetNtracklets(); + nTRDTracklets += trk.GetNtracklets(); + nTRDTracks += trk.GetNtracklets() != 0; } - snprintf(trdText, 1024, " - TRD Tracker reconstructed %d tracks (%d tracklets)", t->mIOPtrs.nTRDTracks, nTracklets); + snprintf(trdText, 1024, " - TRD Tracker reconstructed %d tracks (%d tracklets)", nTRDTracks, nTRDTracklets); } printf("Output Tracks: %d (%d / %d / %d / %d clusters (fitted / attached / adjacent / total))%s\n", nTracks, nAttachedClustersFitted, nAttachedClusters, nAdjacentClusters, nCls, trdText); } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx index 9dd31acd90b2a..2a78449830a96 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx @@ -408,12 +408,14 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con GPUTRDTrackData* outTracks = (GPUTRDTrackData*)(outputPtr); outTracks->fCount = 0; + int assignedTracklets = 0; for (int iTrk = 0; iTrk < nTracks; ++iTrk) { GPUTRDTrack& t = trackArray[iTrk]; if (t.GetNtracklets() == 0) { continue; } + assignedTracklets += t.GetNtracklets(); GPUTRDTrackDataRecord& currOutTrack = outTracks->fTracks[outTracks->fCount]; t.ConvertTo(currOutTrack); outTracks->fCount++; @@ -477,7 +479,7 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con size += blockSize; outputPtr += resultDataSP.fSize; - HLTInfo("TRD tracker: output %d tracks and %d track points", outTracks->fCount, outTrackPoints->fCount); + HLTInfo("TRD tracker: output %d tracks (%d assigned tracklets) and %d track points", outTracks->fCount, assignedTracklets, outTrackPoints->fCount); } fBenchmark.Stop(0); From dfa78de76ca11254bcc5ecda116e99527fac085f Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Sat, 26 Sep 2020 08:13:10 +0200 Subject: [PATCH 0776/1751] No using namespace in include (#4438) --- Analysis/Core/include/Analysis/HistogramManager.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Analysis/Core/include/Analysis/HistogramManager.h b/Analysis/Core/include/Analysis/HistogramManager.h index dd916d870be34..9da34415a6bff 100644 --- a/Analysis/Core/include/Analysis/HistogramManager.h +++ b/Analysis/Core/include/Analysis/HistogramManager.h @@ -28,8 +28,6 @@ #include <vector> #include <list> -using namespace std; - class HistogramManager : public TNamed { @@ -96,8 +94,8 @@ class HistogramManager : public TNamed void Print(Option_t*) const override; private: - THashList* fMainList; // master histogram list - int fNVars; // number of variables handled (tipically from the Variable Manager) + THashList* fMainList; // master histogram list + int fNVars; // number of variables handled (tipically from the Variable Manager) bool* fUsedVars; //! flags of used variables std::map<std::string, std::list<std::vector<int>>> fVariablesMap; //! map holding identifiers for all variables needed by histograms From 5a29b5a918f4c2ac25e23980e98a7fc8c4c90662 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 25 Sep 2020 20:13:00 +0200 Subject: [PATCH 0777/1751] Update ITSMFTDigitizerSpec.cxx We have to use `auto&` for DPL owned resources otherwise we fill a copy... --- Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx index 4606304f0268c..5f96a58e235ee 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx @@ -102,7 +102,7 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer mDigitizer.setMCLabels(&mLabels); // digits are directly put into DPL owned resource - auto digitsAccum = pc.outputs().make<std::vector<itsmft::Digit>>(Output{mOrigin, "DIGITS", 0, Lifetime::Timeframe}); + auto& digitsAccum = pc.outputs().make<std::vector<itsmft::Digit>>(Output{mOrigin, "DIGITS", 0, Lifetime::Timeframe}); auto accumulate = [this, &digitsAccum]() { // accumulate result of single event processing, called after processing every event supplied From 6383682472dfebb46bc74a0bb4ad21e1a5cc0e7c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 25 Sep 2020 21:42:43 +0200 Subject: [PATCH 0778/1751] Fix: default init. of some ClusterNativeAccess members --- .../Detectors/TPC/include/DataFormatsTPC/ClusterNative.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h index 4dcabd1913159..6f9ce3afbb8fd 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h @@ -155,13 +155,13 @@ struct ClusterNative { // This is an index struct to access TPC clusters inside sectors and rows. It shall not own the data, but just point to // the data inside a buffer. struct ClusterNativeAccess { - const ClusterNative* clustersLinear; + const ClusterNative* clustersLinear = nullptr; const ClusterNative* clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clustersMCTruth; + const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clustersMCTruth = nullptr; unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; unsigned int nClustersSector[constants::MAXSECTOR]; unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; - unsigned int nClustersTotal; + unsigned int nClustersTotal = 0; void setOffsetPtrs(); }; From 5c546646b7a615e2a5613ff746180d33477659a5 Mon Sep 17 00:00:00 2001 From: cortesep <57937610+cortesep@users.noreply.github.com> Date: Sat, 26 Sep 2020 09:13:14 +0200 Subject: [PATCH 0779/1751] Introduction of fired channels in ZDC digitization (#4326) * Adding more lineshapes * Autotrigger bits are now for all channels. Rename to Hits * Discriminator are enabled on all channels * New data member for discriminated channels that are actually used for triggering * Move AllChannelsMask to highest bit * Enable hits on non triggering channels * Introduce hits besides triggers * Allow triggering on all channels --- DataFormats/Detectors/ZDC/src/BCData.cxx | 2 +- .../ZDC/base/include/ZDCBase/Constants.h | 4 +- Detectors/ZDC/base/src/ModuleConfig.cxx | 11 +++-- Detectors/ZDC/macro/CreateModuleConfig.C | 46 ++++++++++--------- Detectors/ZDC/macro/CreateSimCondition.C | 18 ++++++-- .../include/ZDCSimulation/Digitizer.h | 5 +- Detectors/ZDC/simulation/src/Digitizer.cxx | 22 +++++---- 7 files changed, 65 insertions(+), 43 deletions(-) diff --git a/DataFormats/Detectors/ZDC/src/BCData.cxx b/DataFormats/Detectors/ZDC/src/BCData.cxx index bed2a3576d373..38cf592475b99 100644 --- a/DataFormats/Detectors/ZDC/src/BCData.cxx +++ b/DataFormats/Detectors/ZDC/src/BCData.cxx @@ -24,7 +24,7 @@ void BCData::print() const printf("%s ", channelName(ic)); } } - printf("] Triggered: ["); + printf("] Hits: ["); for (int ic = 0; ic < NChannels; ic++) { if (triggers & (0x1 << ic)) { printf("%s ", channelName(ic)); diff --git a/Detectors/ZDC/base/include/ZDCBase/Constants.h b/Detectors/ZDC/base/include/ZDCBase/Constants.h index 56f3ff185e48a..904567296acf4 100644 --- a/Detectors/ZDC/base/include/ZDCBase/Constants.h +++ b/Detectors/ZDC/base/include/ZDCBase/Constants.h @@ -54,7 +54,9 @@ constexpr int NChannels = 2 * (NChannelsZN + NChannelsZP) + NChannelsZEM; constexpr uint32_t AllChannelsMask = (0x1 << NChannels) - 1; constexpr int NModules = 8; -constexpr int MaxTriggerChannels = 10; +constexpr int NChPerModule = 4; +constexpr int NWPerBc = 3; +constexpr int MaxTriggerChannels = NChannels; constexpr int MaxTDCValues = 5; // max number of TDC values to store in reconstructed event constexpr int NTDCChannels = 10; // max number of TDC values to store in reconstructed event diff --git a/Detectors/ZDC/base/src/ModuleConfig.cxx b/Detectors/ZDC/base/src/ModuleConfig.cxx index ecb7b28766b85..35c24d08a8abd 100644 --- a/Detectors/ZDC/base/src/ModuleConfig.cxx +++ b/Detectors/ZDC/base/src/ModuleConfig.cxx @@ -23,9 +23,11 @@ void Module::print() const printf("\n"); printf("Trigger conf: "); for (int ic = 0; ic < MaxChannels; ic++) { + const auto& cnf = trigChannelConf[ic]; if (trigChannel[ic]) { - const auto& cnf = trigChannelConf[ic]; - printf("[%s: F:%2d L:%2d S:%2d T:%2d] ", channelName(channelID[ic]), cnf.first, cnf.last, cnf.shift, cnf.threshold); + printf("[TRIG %s: F:%2d L:%2d S:%2d T:%2d] ", channelName(channelID[ic]), cnf.first, cnf.last, cnf.shift, cnf.threshold); + } else if (cnf.shift > 0 && cnf.threshold > 0) { + printf("[DISC %s: F:%2d L:%2d S:%2d T:%2d] ", channelName(channelID[ic]), cnf.first, cnf.last, cnf.shift, cnf.threshold); } } printf("\n"); @@ -70,8 +72,11 @@ void Module::setChannel(int slot, int8_t chID, int16_t lID, bool read, bool trig linkID[slot] = lID; channelID[slot] = chID; readChannel[slot] = read; + // In the 2020 firmware implementation, autotrigger bits are computed for each channel + // Therefore we put the trig flag just for the triggering channels + // Discriminator parameters are stored for all modules trigChannel[slot] = trig; - if (trig) { + if (tS > 0 && tT > 0) { if (tL + tS + 1 >= NTimeBinsPerBC) { LOG(FATAL) << "Sum of Last and Shift trigger parameters exceed allowed range"; } diff --git a/Detectors/ZDC/macro/CreateModuleConfig.C b/Detectors/ZDC/macro/CreateModuleConfig.C index a06b585b494a4..82c63e91cebac 100644 --- a/Detectors/ZDC/macro/CreateModuleConfig.C +++ b/Detectors/ZDC/macro/CreateModuleConfig.C @@ -32,14 +32,16 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, int modID; //------------------------------------------- + // Up to 8 modules with four channels + // setChannel(int slot, int8_t chID, int16_t lID, bool read, bool trig = false, int tF = 0, int tL = 0, int tS = 0, int tT = 0) { modID = 0; auto& module = conf.modules[modID]; module.id = modID; module.setChannel(0, IdZNAC, 0, true, true, -5, 6, 4, 12); - module.setChannel(1, IdZNASum, 1, false, false); - module.setChannel(2, IdZNA1, 2, true, false); - module.setChannel(3, IdZNA2, 3, true, false); + module.setChannel(1, IdZNASum, 1, false, false, -5, 6, 4, 12); + module.setChannel(2, IdZNA1, 2, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNA2, 3, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -48,9 +50,9 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, auto& module = conf.modules[modID]; module.id = modID; module.setChannel(0, IdZNAC, 4, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZNASum, 5, true, false); - module.setChannel(2, IdZNA1, 6, true, false); - module.setChannel(3, IdZNA2, 7, true, false); + module.setChannel(1, IdZNASum, 5, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZNA3, 6, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNA4, 7, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -59,9 +61,9 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, auto& module = conf.modules[modID]; module.id = modID; module.setChannel(0, IdZNCC, 8, true, true, -5, 6, 4, 12); - module.setChannel(1, IdZNCSum, 9, false, false); - module.setChannel(2, IdZNC1, 10, true, false); - module.setChannel(3, IdZNC2, 11, true, false); + module.setChannel(1, IdZNCSum, 9, false, false, -5, 6, 4, 12); + module.setChannel(2, IdZNC1, 10, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNC2, 11, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -70,9 +72,9 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, auto& module = conf.modules[modID]; module.id = modID; module.setChannel(0, IdZNCC, 12, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZNCSum, 13, true, false); - module.setChannel(2, IdZNC3, 14, true, false); - module.setChannel(3, IdZNC4, 15, true, false); + module.setChannel(1, IdZNCSum, 13, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZNC3, 14, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNC4, 15, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -82,8 +84,8 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, module.id = modID; module.setChannel(0, IdZPAC, 16, true, true, -5, 6, 4, 12); module.setChannel(1, IdZEM1, 16, true, true, -5, 6, 4, 12); - module.setChannel(2, IdZPA1, 17, true, false); - module.setChannel(3, IdZPA2, 17, true, false); + module.setChannel(2, IdZPA1, 17, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPA2, 17, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -92,9 +94,9 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, auto& module = conf.modules[modID]; module.id = modID; module.setChannel(0, IdZPAC, 18, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZPASum, 18, true, false); - module.setChannel(2, IdZPA1, 19, true, false); - module.setChannel(3, IdZPA2, 19, true, false); + module.setChannel(1, IdZPASum, 18, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZPA3, 19, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPA4, 19, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -104,8 +106,8 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, module.id = modID; module.setChannel(0, IdZPCC, 16, true, true, -5, 6, 4, 12); module.setChannel(1, IdZEM2, 16, true, true, -5, 6, 4, 12); - module.setChannel(2, IdZPC1, 17, true, false); - module.setChannel(3, IdZPC2, 17, true, false); + module.setChannel(2, IdZPC1, 17, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPC2, 17, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -114,9 +116,9 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, auto& module = conf.modules[modID]; module.id = modID; module.setChannel(0, IdZPCC, 18, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZPCSum, 18, true, false); - module.setChannel(2, IdZPC3, 19, true, false); - module.setChannel(3, IdZPC4, 19, true, false); + module.setChannel(1, IdZPCSum, 18, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZPC3, 19, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPC4, 19, true, false, -5, 6, 4, 12); // } conf.check(); diff --git a/Detectors/ZDC/macro/CreateSimCondition.C b/Detectors/ZDC/macro/CreateSimCondition.C index 38f80a5e1c844..e93b14e883a28 100644 --- a/Detectors/ZDC/macro/CreateSimCondition.C +++ b/Detectors/ZDC/macro/CreateSimCondition.C @@ -35,6 +35,16 @@ void CreateSimCondition(std::string sourceDataPath = "signal_shapes.root", const float Gains[5] = {15.e-3, 30.e-3, 100.e-3, 15.e-3, 30.e-3}; // gain (response per photoelectron) const float fudgeFactor = 2.7; // ad hoc factor to tune the gain in the MC + // Source of line shapes, pedestal and noise for each channel + // Missing histos for: towers 1-4 of all calorimeters, zem1, all towers of zpc + std::string ShapeName[o2::zdc::NChannels] = { + "znatc", "znatc", "znatc", "znatc", "znatc", "znatc", // ZNAC, ZNA1, ZNA2, ZNA3, ZNA4, ZNAS (shape not used) + "zpatc", "zpatc", "zpatc", "zpatc", "zpatc", "zpatc", // ZPAC, ZPA1, ZPA2, ZPA3, ZPA4, ZPAS (shape not used) + "zem2", "zem2", // ZEM1, ZEM2 + "znctc", "znctc", "znctc", "znctc", "znctc", "znctc", // ZNCC, ZNC1, ZNC2, ZNC3, ZNC4, ZNCS (shape not used) + "zpatc", "zpatc", "zpatc", "zpatc", "zpatc", "zpatc" // ZPCC, ZPC1, ZPC2, ZPC3, ZPC4, ZPCS (shape not used) + }; + for (int ic = 0; ic < o2::zdc::NChannels; ic++) { auto& channel = conf.channels[ic]; @@ -43,9 +53,7 @@ void CreateSimCondition(std::string sourceDataPath = "signal_shapes.root", // channel.gain = (tower != o2::zdc::Sum) ? fudgeFactor * Gains[det - 1] : 1.0; // - // at the moment we use wf_znatc histo for all channels, to be fixed when - // more histos are created. So, we read in the loop the same histo - std::string histoShapeName = "hw_znatc"; + std::string histoShapeName = "hw_" + ShapeName[ic]; TH1* histoShape = (TH1*)sourceData.GetObjectUnchecked(histoShapeName.c_str()); if (!histoShape) { LOG(FATAL) << "Failed to extract the shape histogram " << histoShapeName; @@ -72,14 +80,14 @@ void CreateSimCondition(std::string sourceDataPath = "signal_shapes.root", // channel.pedestal = gRandom->Gaus(1800., 30.); // - std::string histoPedNoiseName = "hb_znatc"; // same comment here (at the moment the same histo used) + std::string histoPedNoiseName = "hb_" + ShapeName[ic]; TH1* histoPedNoise = (TH1*)sourceData.GetObjectUnchecked(histoPedNoiseName.c_str()); if (!histoPedNoise) { LOG(FATAL) << "Failed to extract the pedestal noise histogram " << histoPedNoise; } channel.pedestalNoise = histoPedNoise->GetRMS(); // - std::string histoPedFluctName = "hp_znatc"; // same comment here (at the moment the same histo used) + std::string histoPedFluctName = "hp_" + ShapeName[ic]; TH1* histoPedFluct = (TH1*)sourceData.GetObjectUnchecked(histoPedFluctName.c_str()); if (!histoPedFluct) { LOG(FATAL) << "Failed to extract the pedestal fluctuation histogram " << histoPedFluct; diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h index e8423b59a4a6d..5a477720dd887 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h @@ -41,7 +41,7 @@ class Digitizer bool digitized = false; bool triggerChecked = false; uint32_t trigChanMask = 0; // mask of triggered channels IDs - static constexpr uint32_t AllChannelsMask = 0x1 << NChannels; + static constexpr uint32_t AllChannelsMask = 0x80000000; BCCache(); @@ -133,7 +133,7 @@ class Digitizer o2::InteractionTimeRecord mIR; std::deque<o2::InteractionRecord> mIRExternalTrigger; // IRs of externally provided triggered (at the moment MC sampled interactions) - std::deque<BCCache> mCache; // cached BCs data + std::deque<BCCache> mCache; // cached BCs data std::array<std::vector<int16_t>, NChannels> mTrigChannelsData; // buffer for fast access to triggered channels data int mTrigBinMin = 0xffff; // prefetched min and max int mTrigBinMax = -0xffff; // bins to be checked for trigger @@ -143,6 +143,7 @@ class Digitizer const SimCondition* mSimCondition = nullptr; ///< externally set SimCondition const ModuleConfig* mModuleConfig = nullptr; ///< externally set ModuleConfig std::vector<TriggerChannelConfig> mTriggerConfig; ///< triggering channels + uint32_t mTriggerableChanMask = 0; ///< mask of digital discriminators that can actually trigger a module std::vector<ModuleConfAux> mModConfAux; ///< module check helper std::vector<BCCache*> mFastCache; ///< for the fast iteration over cached BCs + dummy std::vector<uint32_t> mStoreChanMask; ///< pattern of channels to store diff --git a/Detectors/ZDC/simulation/src/Digitizer.cxx b/Detectors/ZDC/simulation/src/Digitizer.cxx index 36c84ae72ea56..c40d026b2fa04 100644 --- a/Detectors/ZDC/simulation/src/Digitizer.cxx +++ b/Detectors/ZDC/simulation/src/Digitizer.cxx @@ -181,7 +181,7 @@ void Digitizer::digitizeBC(BCCache& bc) auto& bcdata = bc.data; // apply gain for (int idet : {ZNA, ZPA, ZNC, ZPC}) { - for (int ic : {Ch1, Ch2, Ch3, Ch4}) { + for (int ic : {Common, Ch1, Ch2, Ch3, Ch4}) { int chan = toChannel(idet, ic); auto gain = mSimCondition->channels[chan].gain; for (int ib = NTimeBinsPerBC; ib--;) { @@ -226,7 +226,7 @@ bool Digitizer::triggerBC(int ibc) for (int ic = mTriggerConfig.size(); ic--;) { const auto& trigCh = mTriggerConfig[ic]; bool okPrev = false; - int last1 = trigCh.last + 2; + int last1 = trigCh.last + 2; // To be modified. The new requirement is 3 consecutive samples // look for 2 consecutive bins (the 1st one spanning trigCh.first : trigCh.last range) so that // signal[bin]-signal[bin+trigCh.shift] > trigCh.threshold for (int ib = trigCh.first; ib < last1; ib++) { // ib may be negative, so we shift by offs and look in the ADC cache @@ -237,7 +237,7 @@ bool Digitizer::triggerBC(int ibc) bool ok = bcF.data[trigCh.id][binF] - bcL.data[trigCh.id][binL] > trigCh.threshold; if (ok && okPrev) { // trigger ok! bcCached.trigChanMask |= 0x1 << trigCh.id; // register trigger mask - LOG(DEBUG) << " triggering channel " << int(trigCh.id) << " => " << bcCached.trigChanMask; + LOG(DEBUG) << " triggering channel " << int(trigCh.id) << "(" << ChannelNames[trigCh.id] << ") => " << bcCached.trigChanMask; break; } okPrev = ok; @@ -251,7 +251,7 @@ bool Digitizer::triggerBC(int ibc) } } - if (bcCached.trigChanMask) { // there are triggered channels, flag modules/channels to read + if (bcCached.trigChanMask & mTriggerableChanMask) { // there are triggered channels, flag modules/channels to read for (int ibcr = ibc - mNBCAHead; ibcr <= ibc; ibcr++) { auto& bcr = mStoreChanMask[ibcr + mNBCAHead]; for (const auto& mdh : mModConfAux) { @@ -314,7 +314,7 @@ void Digitizer::phe2Sample(int nphe, int parID, double timeHit, std::array<o2::I break; } if (sample >= 0) { - auto signal = chanConfig.shape[sample] * nphe; // signal accounting for the gain + auto signal = chanConfig.shape[sample] * nphe; // signal not accounting for the gain (*bcCache).data[channel][ib] += signal; added = true; } @@ -398,11 +398,10 @@ void Digitizer::refreshCCDB() for (const auto& md : mModuleConfig->modules) { if (md.id >= 0) { mModConfAux.emplace_back(md); - // for (int ic = Module::MaxChannels; ic--;) { - if (md.trigChannel[ic]) { // check if this triggering channel was already registered + if (md.trigChannel[ic] || (md.trigChannelConf[ic].shift > 0 && md.trigChannelConf[ic].threshold > 0)) { bool skip = false; - for (int is = mTriggerConfig.size(); is--;) { + for (int is = mTriggerConfig.size(); is--;) { // check if this triggering channel was already registered if (mTriggerConfig[is].id == md.channelID[ic]) { skip = true; break; @@ -414,7 +413,12 @@ void Digitizer::refreshCCDB() LOG(FATAL) << "Wrong trigger settings"; } mTriggerConfig.emplace_back(trgChanConf); - LOG(INFO) << "Adding channel " << int(trgChanConf.id) << '(' << channelName(trgChanConf.id) << ") as triggering one"; + if (md.trigChannel[ic]) { + LOG(INFO) << "Adding channel " << int(trgChanConf.id) << '(' << channelName(trgChanConf.id) << ") as triggering one"; + mTriggerableChanMask |= 0x1 << trgChanConf.id; + } else { + LOG(INFO) << "Adding channel " << int(trgChanConf.id) << '(' << channelName(trgChanConf.id) << ") as discriminator"; + } if (trgChanConf.first < mTrigBinMin) { mTrigBinMin = trgChanConf.first; } From 0389abec609cc8fd291fe3e56d8e13a0f9404bac Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Sat, 26 Sep 2020 11:49:52 +0200 Subject: [PATCH 0780/1751] [MCH] added DPL message with orbits information (#4285) The additional message provides the list of processed orbits (using a new OrbitInfo struct) for each CRU link in the input raw buffer. Useful for example to estimate the detector occupancy in continuous readout mode. --- Detectors/MUON/MCH/Base/CMakeLists.txt | 4 +- Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt | 2 +- .../Decoder/include/MCHRawDecoder/OrbitInfo.h | 57 +++++++++++++++++++ .../MUON/MCH/Raw/Decoder/src/OrbitInfo.cxx | 42 ++++++++++++++ Detectors/MUON/MCH/Workflow/CMakeLists.txt | 2 +- .../MUON/MCH/Workflow/src/DataDecoderSpec.cxx | 51 ++++++++++++++--- .../MCH/Workflow/src/digits-sink-workflow.cxx | 9 ++- 7 files changed, 154 insertions(+), 13 deletions(-) create mode 100644 Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/OrbitInfo.h create mode 100644 Detectors/MUON/MCH/Raw/Decoder/src/OrbitInfo.cxx diff --git a/Detectors/MUON/MCH/Base/CMakeLists.txt b/Detectors/MUON/MCH/Base/CMakeLists.txt index 4d0bd10526828..c586850ba1c9f 100644 --- a/Detectors/MUON/MCH/Base/CMakeLists.txt +++ b/Detectors/MUON/MCH/Base/CMakeLists.txt @@ -12,8 +12,8 @@ o2_add_library(MCHBase SOURCES src/ClusterBlock.cxx src/Digit.cxx - src/PreCluster.cxx - src/TrackBlock.cxx + src/PreCluster.cxx + src/TrackBlock.cxx PUBLIC_LINK_LIBRARIES ROOT::Core FairRoot::Base FairMQ::FairMQ ms_gsl::ms_gsl) o2_target_root_dictionary(MCHBase diff --git a/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt b/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt index a0759f2cb6505..1c56998c73e51 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt +++ b/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt @@ -9,7 +9,7 @@ # submit itself to any jurisdiction. o2_add_library(MCHRawDecoder - SOURCES src/PageDecoder.cxx src/RDHManip.cxx + SOURCES src/PageDecoder.cxx src/RDHManip.cxx src/OrbitInfo.cxx PUBLIC_LINK_LIBRARIES O2::MCHRawCommon O2::MCHRawElecMap O2::DetectorsRaw PRIVATE_LINK_LIBRARIES O2::MCHRawImplHelpers) diff --git a/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/OrbitInfo.h b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/OrbitInfo.h new file mode 100644 index 0000000000000..87f0944456ae7 --- /dev/null +++ b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/OrbitInfo.h @@ -0,0 +1,57 @@ +// 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 OrbitInfo.h + * C++ Muon MCH class that holds information about processed orbits + * @author Andrea Ferrero + */ + +#ifndef ALICEO2_MCH_BASE_ORBITINFO_H_ +#define ALICEO2_MCH_BASE_ORBITINFO_H_ + +#include <gsl/span> + +#include "Rtypes.h" + +namespace o2 +{ +namespace mch +{ + +// \class OrbitInfo +/// \brief MCH orbit info implementation +class OrbitInfo +{ + public: + OrbitInfo() = default; + + OrbitInfo(gsl::span<const std::byte> rdhBuffer); + ~OrbitInfo() = default; + + uint64_t get() const { return mOrbitInfo; } + uint32_t getOrbit() const { return (mOrbitInfo & 0xFFFFFFFF); } + uint8_t getLinkID() const { return ((mOrbitInfo >> 32) & 0xFF); } + uint16_t getFeeID() const { return ((mOrbitInfo >> 40) & 0xFF); } + + friend bool operator==(const OrbitInfo& o1, const OrbitInfo& o2); + friend bool operator!=(const OrbitInfo& o1, const OrbitInfo& o2); + + private: + uint64_t mOrbitInfo = {0}; + + ClassDefNV(OrbitInfo, 1); +}; //class OrbitInfo + +bool operator==(const OrbitInfo& o1, const OrbitInfo& o2); +bool operator!=(const OrbitInfo& o1, const OrbitInfo& o2); + +} //namespace mch +} //namespace o2 +#endif // ALICEO2_MCH_BASE_ORBITINFO_H_ diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/OrbitInfo.cxx b/Detectors/MUON/MCH/Raw/Decoder/src/OrbitInfo.cxx new file mode 100644 index 0000000000000..df9f12de6d43d --- /dev/null +++ b/Detectors/MUON/MCH/Raw/Decoder/src/OrbitInfo.cxx @@ -0,0 +1,42 @@ +// 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 "Headers/RAWDataHeader.h" +#include "DetectorsRaw/RDHUtils.h" +#include "MCHRawDecoder/OrbitInfo.h" + +namespace o2::mch +{ + +using RDH = o2::header::RDHAny; + +OrbitInfo::OrbitInfo(gsl::span<const std::byte> rdhBuffer) +{ + auto& rdhAny = *reinterpret_cast<RDH*>(const_cast<std::byte*>(&(rdhBuffer[0]))); + auto orbit = o2::raw::RDHUtils::getHeartBeatOrbit(rdhAny); + auto linkId = o2::raw::RDHUtils::getLinkID(rdhAny); + auto feeId = o2::raw::RDHUtils::getFEEID(rdhAny); + + mOrbitInfo = orbit; + mOrbitInfo += ((static_cast<uint64_t>(linkId) << 32) & 0xFF00000000); + mOrbitInfo += ((static_cast<uint64_t>(feeId) << 40) & 0xFF0000000000); +} + +bool operator==(const OrbitInfo& o1, const OrbitInfo& o2) +{ + return (o1.mOrbitInfo == o2.mOrbitInfo); +} + +bool operator!=(const OrbitInfo& o1, const OrbitInfo& o2) +{ + return !(o1 == o2); +} + +} // namespace o2::mch diff --git a/Detectors/MUON/MCH/Workflow/CMakeLists.txt b/Detectors/MUON/MCH/Workflow/CMakeLists.txt index d3d2366f7c4b6..f9fb3cf4548a6 100644 --- a/Detectors/MUON/MCH/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MCH/Workflow/CMakeLists.txt @@ -33,7 +33,7 @@ o2_add_executable( digits-sink-workflow SOURCES src/digits-sink-workflow.cxx COMPONENT_NAME mch - PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils Boost::program_options O2::MCHBase) + PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils Boost::program_options O2::MCHBase O2::MCHRawDecoder) o2_add_executable( raw-to-digits-workflow diff --git a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx index eb2ad9abad33a..40386ffe06010 100644 --- a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx @@ -20,6 +20,9 @@ #include <iostream> #include <fstream> #include <stdexcept> +#include <array> +#include <functional> + #include "Framework/CallbackService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" @@ -33,11 +36,11 @@ #include "MCHBase/Digit.h" #include "Headers/RAWDataHeader.h" #include "MCHRawCommon/DataFormats.h" +#include "MCHRawDecoder/OrbitInfo.h" #include "MCHRawDecoder/PageDecoder.h" #include "MCHRawElecMap/Mapper.h" #include "MCHMappingInterface/Segmentation.h" #include "MCHWorkflow/DataDecoderSpec.h" -#include <array> #include "DetectorsRaw/RDHUtils.h" namespace o2::header @@ -74,6 +77,14 @@ int ds2manu(int i) return refDs2manu_st345[i]; } +// custom hash can be a standalone function object: +struct OrbitInfoHash { + std::size_t operator()(OrbitInfo const& info) const noexcept + { + return std::hash<uint64_t>{}(info.get()); + } +}; + //======================= // Data decoder class DataDecoderTask @@ -137,8 +148,9 @@ class DataDecoderTask digits.emplace_back(o2::mch::Digit(deId, padId, digitadc, time, sc.nofSamples())); - if (mPrint) + if (mPrint) { std::cout << "DIGIT STORED:\nADC " << digits.back().getADC() << " DE# " << digits.back().getDetID() << " PadId " << digits.back().getPadID() << " time " << digits.back().getTime().sampaTime << std::endl; + } ++ndigits; }; @@ -149,6 +161,7 @@ class DataDecoderTask auto flags = o2::raw::RDHUtils::getCRUID(rdhAny) & 0xFF00; auto endpoint = o2::raw::RDHUtils::getEndPointID(rdhAny); auto feeId = cruId * 2 + endpoint + flags; + auto linkId = o2::raw::RDHUtils::getLinkID(rdhAny); o2::raw::RDHUtils::setFEEID(rdhAny, feeId); orbit = o2::raw::RDHUtils::getHeartBeatOrbit(rdhAny); if (mPrint) { @@ -159,6 +172,9 @@ class DataDecoderTask patchPage(page); + // add orbit to vector if not present yet + mOrbits.emplace(page); + if (!mDecoder) { mDecoder = mFee2Solar ? o2::mch::raw::createPageDecoder(page, channelHandler, mFee2Solar) : o2::mch::raw::createPageDecoder(page, channelHandler); @@ -285,6 +301,8 @@ class DataDecoderTask { std::vector<o2::mch::Digit> digits; + mOrbits.clear(); + decodeTF(pc, digits); for (auto&& input : pc.inputs()) { if (input.spec->binding == "readout") @@ -297,16 +315,32 @@ class DataDecoderTask } } - const size_t OUT_SIZE = sizeof(o2::mch::Digit) * digits.size(); + auto createBuffer = [&](auto& vec, size_t& size) { + size = vec.empty() ? 0 : sizeof(*(vec.begin())) * vec.size(); + char* buf = nullptr; + if (size > 0) { + buf = (char*)malloc(size); + if (buf) { + char* p = buf; + size_t sizeofElement = sizeof(*(vec.begin())); + for (auto& element : vec) { + memcpy(p, &element, sizeofElement); + p += sizeofElement; + } + } + } + return buf; + }; // send the output buffer via DPL - char* outbuffer = nullptr; - outbuffer = (char*)realloc(outbuffer, OUT_SIZE); - memcpy(outbuffer, digits.data(), OUT_SIZE); + size_t digitsSize, orbitsSize; + char* digitsBuffer = createBuffer(digits, digitsSize); + char* orbitsBuffer = createBuffer(mOrbits, orbitsSize); // create the output message auto freefct = [](void* data, void*) { free(data); }; - pc.outputs().adoptChunk(Output{"MCH", "DIGITS", 0}, outbuffer, OUT_SIZE, freefct, nullptr); + pc.outputs().adoptChunk(Output{"MCH", "DIGITS", 0}, digitsBuffer, digitsSize, freefct, nullptr); + pc.outputs().adoptChunk(Output{"MCH", "ORBITS", 0}, orbitsBuffer, orbitsSize, freefct, nullptr); } private: @@ -314,6 +348,7 @@ class DataDecoderTask FeeLink2SolarMapper mFee2Solar{nullptr}; o2::mch::raw::PageDecoder mDecoder; size_t mNrdhs{0}; + std::unordered_set<OrbitInfo, OrbitInfoHash> mOrbits; ///< list of orbits in the processed buffer std::ifstream mInputFile{}; ///< input file bool mDs2manu = false; ///< print convert channel numbering from Run3 to Run1-2 order @@ -327,7 +362,7 @@ o2::framework::DataProcessorSpec getDecodingSpec() "DataDecoder", //o2::framework::select("TF:MCH/RAWDATA, re:ROUT/RAWDATA"), o2::framework::select("readout:ROUT/RAWDATA"), - Outputs{OutputSpec{"MCH", "DIGITS", 0, Lifetime::Timeframe}}, + Outputs{OutputSpec{"MCH", "DIGITS", 0, Lifetime::Timeframe}, OutputSpec{"MCH", "ORBITS", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<DataDecoderTask>()}, Options{{"print", VariantType::Bool, false, {"print digits"}}, {"cru-map", VariantType::String, "", {"custom CRU mapping"}}, diff --git a/Detectors/MUON/MCH/Workflow/src/digits-sink-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/digits-sink-workflow.cxx index a73d8776d7e7b..9fcd58628ce44 100644 --- a/Detectors/MUON/MCH/Workflow/src/digits-sink-workflow.cxx +++ b/Detectors/MUON/MCH/Workflow/src/digits-sink-workflow.cxx @@ -38,6 +38,7 @@ #include "DPLUtils/DPLRawParser.h" #include "MCHBase/Digit.h" +#include "MCHRawDecoder/OrbitInfo.h" using namespace o2; using namespace o2::framework; @@ -82,8 +83,14 @@ class DigitsSinkTask { // get the input digits auto digits = pc.inputs().get<gsl::span<Digit>>("digits"); + auto orbits = pc.inputs().get<gsl::span<OrbitInfo>>("orbits"); if (mText) { + for (auto o : orbits) { + mOutputFile << std::endl + << " FEEID " << o.getFeeID() << " LINK " << (int)o.getLinkID() << " ORBIT " << o.getOrbit() << std::endl; + } + mOutputFile << "---------------" << std::endl; for (auto d : digits) { mOutputFile << " DE# " << d.getDetID() << " PadId " << d.getPadID() << " ADC " << d.getADC() << " time " << d.getTime().sampaTime << std::endl; } @@ -111,7 +118,7 @@ WorkflowSpec defineDataProcessing(const ConfigContext&) // The producer to generate some data in the workflow DataProcessorSpec producer{ "DigitsSink", - Inputs{InputSpec{"digits", "MCH", "DIGITS", 0, Lifetime::Timeframe}}, + Inputs{InputSpec{"digits", "MCH", "DIGITS", 0, Lifetime::Timeframe}, InputSpec{"orbits", "MCH", "ORBITS", 0, Lifetime::Timeframe}}, Outputs{}, AlgorithmSpec{adaptFromTask<o2::mch::raw::DigitsSinkTask>()}, Options{ { "outfile", VariantType::String, "digits.out", { "output file name" } }, From 46140fc74a02b2aa03986eaf81266b15aa8fc768 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 25 Sep 2020 21:40:24 +0200 Subject: [PATCH 0781/1751] Guard invasive operations on gGeoManager by mutex --- Detectors/Base/include/DetectorsBase/GeometryManager.h | 4 ++-- Detectors/Base/src/GeometryManager.cxx | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/GeometryManager.h b/Detectors/Base/include/DetectorsBase/GeometryManager.h index f29e795664d3d..bc7fcdd353b1d 100644 --- a/Detectors/Base/include/DetectorsBase/GeometryManager.h +++ b/Detectors/Base/include/DetectorsBase/GeometryManager.h @@ -25,7 +25,7 @@ #include "FairLogger.h" // for LOG #include "MathUtils/Cartesian3D.h" #include "DetectorsBase/MatCell.h" - +#include <mutex> class TGeoHMatrix; // lines 11-11 class TGeoManager; // lines 9-9 @@ -126,7 +126,6 @@ class GeometryManager : public TObject /// detector geometry. The output global matrix is stored in 'm'. /// Returns kFALSE in case TGeo has not been initialized or the volume path is not valid. static Bool_t getOriginalMatrixFromPath(const char* path, TGeoHMatrix& m); - private: /// sensitive volume identifier composed from (det_mask<<sDetOffset)|(sensid&sSensorMask) #ifdef ENABLE_UPGRADES @@ -136,6 +135,7 @@ class GeometryManager : public TObject #endif static constexpr UInt_t sSensorMask = (0x1 << sDetOffset) - 1; /// mask=max sensitive volumes allowed per detector (0xffff) + static std::mutex sTGMutex; ClassDefOverride(GeometryManager, 0); // Manager of geometry information for alignment }; diff --git a/Detectors/Base/src/GeometryManager.cxx b/Detectors/Base/src/GeometryManager.cxx index 646b70cacec6e..5a153a0fd9943 100644 --- a/Detectors/Base/src/GeometryManager.cxx +++ b/Detectors/Base/src/GeometryManager.cxx @@ -33,6 +33,7 @@ using namespace o2::base; /// Implementation of GeometryManager, the geometry manager class which interfaces to TGeo and /// the look-up table mapping unique volume indices to symbolic volume names. For that, it /// collects several static methods +std::mutex GeometryManager::sTGMutex; //______________________________________________________________________ GeometryManager::GeometryManager() @@ -48,13 +49,12 @@ GeometryManager::GeometryManager() Bool_t GeometryManager::getOriginalMatrix(const char* symname, TGeoHMatrix& m) { m.Clear(); - if (!gGeoManager || !gGeoManager->IsClosed()) { LOG(ERROR) << "No active geometry or geometry not yet closed!"; ; return kFALSE; } - + std::lock_guard<std::mutex> guard(sTGMutex); if (!gGeoManager->GetListOfPhysicalNodes()) { LOG(WARNING) << "gGeoManager doesn't contain any aligned nodes!"; @@ -91,7 +91,7 @@ Bool_t GeometryManager::getOriginalMatrixFromPath(const char* path, TGeoHMatrix& LOG(ERROR) << "Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!"; return kFALSE; } - + std::lock_guard<std::mutex> guard(sTGMutex); if (!gGeoManager->CheckPath(path)) { LOG(ERROR) << "Volume path " << path << " not valid!"; return kFALSE; @@ -288,7 +288,7 @@ GeometryManager::MatBudgetExt GeometryManager::meanMaterialBudgetExt(float x0, f for (int i = 3; i--;) { dir[i] *= invlen; } - + std::lock_guard<std::mutex> guard(sTGMutex); // Initialize start point and direction TGeoNode* currentnode = gGeoManager->InitTrack(startD, dir); if (!currentnode) { @@ -380,7 +380,7 @@ o2::base::MatBudget GeometryManager::meanMaterialBudget(float x0, float y0, floa for (int i = 3; i--;) { dir[i] *= invlen; } - + std::lock_guard<std::mutex> guard(sTGMutex); // Initialize start point and direction TGeoNode* currentnode = gGeoManager->InitTrack(startD, dir); if (!currentnode) { From b562b28e511b24ac7a31033590e8947bccfad9c1 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 25 Sep 2020 21:41:41 +0200 Subject: [PATCH 0782/1751] Enable material corrections in TRD tracking --- GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h index 990b9aa318c51..42d762b8480bd 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h @@ -200,7 +200,7 @@ class propagatorInterface<o2::base::Propagator> propagatorInterface<o2::base::Propagator>(const propagatorInterface<o2::base::Propagator>&) = delete; propagatorInterface<o2::base::Propagator>& operator=(const propagatorInterface<o2::base::Propagator>&) = delete; - bool propagateToX(float x, float maxSnp, float maxStep) { return mProp->PropagateToXBxByBz(*mParam, x, 0.13957, maxSnp, maxStep, o2::base::Propagator::MatCorrType::USEMatCorrNONE); } + bool propagateToX(float x, float maxSnp, float maxStep) { return mProp->PropagateToXBxByBz(*mParam, x, 0.13957, maxSnp, maxStep); } int getPropagatedYZ(My_Float x, My_Float& projY, My_Float& projZ) { return static_cast<int>(mParam->getYZAt(x, mProp->getNominalBz(), projY, projZ)); } void setTrack(trackInterface<o2::dataformats::TrackTPCITS>* trk) { mParam = trk; } From 11ce85de7af1a36c5359c5054c4312225c0cdab5 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 25 Sep 2020 23:06:01 +0200 Subject: [PATCH 0783/1751] use ITS-TPC outer param to seed TRD matching --- GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C index 9d5212704ef4e..44dc93012e573 100644 --- a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C +++ b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C @@ -135,7 +135,8 @@ void run_trd_tracker(std::string path = "./", printf("Start loading input into TRD tracker\n"); // load everything into the tracker for (int iTrk = 0; iTrk < nTracks; ++iTrk) { - auto trk = tracksInArrayPtr->at(iTrk); + const auto& match = (*tracksInArrayPtr)[iTrk]; + const auto& trk = match.getParamOut(); GPUTRDTrack trkLoad; trkLoad.setX(trk.getX()); trkLoad.setAlpha(trk.getAlpha()); @@ -145,7 +146,7 @@ void run_trd_tracker(std::string path = "./", for (int i = 0; i < 15; ++i) { trkLoad.setCov(trk.getCov()[i], i); } - trkLoad.setTime(trk.getTimeMUS().getTimeStamp()); + trkLoad.setTime(match.getTimeMUS().getTimeStamp()); tracker->LoadTrack(trkLoad); printf("Loaded track %i with time %f\n", iTrk, trkLoad.getTime()); } From 7b403378ae1c0aa45833adf4c1ec1587b397bf89 Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez@cern.ch> Date: Sun, 27 Sep 2020 08:52:18 +0200 Subject: [PATCH 0784/1751] Fix for the phi bin zero issue in the singles distribution (#4453) At the end was a matter of the azimuthal origin shift for the singles distribution but caused also wrong G2 and R2 Also incorporated - rationalization in the centrality ranges names - fix: wrong automatic histogram which caused merging errors - fix: the not use of sumw2 was not set at histogram creation - optimization: AddBinContent is used instead of Fill for the flattened histograms --- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 53 ++++++++++++++------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index 5678fc3cf3d83..58aa9fbb72b4e 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -36,7 +36,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { ConfigParamSpec centspec = {"centralities", VariantType::String, - "0-5,5-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", + "00-05,05-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", {"Centrality/multiplicity ranges in min-max separated by commas"}}; workflowOptions.push_back(centspec); } @@ -247,6 +247,17 @@ inline void AcceptTrack(aod::TrackData const& track, uint8_t& asone, uint8_t& as } } +/// \brief Returns the potentially phi origin shifted phi +/// \param phi the track azimuthal angle +/// \return the track phi origin shifted azimuthal angle +inline float GetShiftedPhi(float phi) +{ + if (not(phi < phiup)) + return phi - TMath::TwoPi(); + else + return phi; +} + /// \brief Returns the zero based bin index of the eta phi passed track /// \param t the intended track /// \return the zero based bin index @@ -255,13 +266,15 @@ inline void AcceptTrack(aod::TrackData const& track, uint8_t& asone, uint8_t& as /// a zero based bin index and similarlly for the track phi /// The returned index is the composition of both considering eta as /// the first index component +/// WARNING: for performance reasons no checks are done about the consistency +/// of track's eta and phin with the corresponding ranges so, it is suppossed +/// the track has been accepted and it is within that ranges +/// IF THAT IS NOT THE CASE THE ROUTINE WILL PRODUCE NONSENSE RESULTS inline int GetEtaPhiIndex(aod::FilteredTrackData const& t) { int etaix = int((t.eta() - etalow) / etabinwidth); /* consider a potential phi origin shift */ - float phi = t.phi(); - if (not(phi < phiup)) - phi = phi - 2 * TMath::Pi(); + float phi = GetShiftedPhi(t.phi()); int phiix = int((phi - philow) / phibinwidth); return etaix * phibins + phiix; } @@ -282,7 +295,7 @@ struct DptDptCorrelationsFilterAnalysisTask { Configurable<std::string> cfgCentMultEstimator{"centmultestimator", "V0M", "Centrality/multiplicity estimator detector: default V0M"}; Configurable<o2::analysis::DptDptBinningCuts> cfgBinning{"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72}, + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; @@ -348,7 +361,7 @@ struct DptDptCorrelationsFilterAnalysisTask { fhPtPosA = new TH1F("fHistPtPosA", "P_{T} distribution for reconstructed (#{+});P_{T} (GeV/c);dN/dP_{T} (c/GeV)", ptbins, ptlow, ptup); fhPtNegB = new TH1F("fHistPtNegB", "P_{T} distribution for reconstructed (#{-}) before;P_{T} (GeV/c);dN/dP_{T} (c/GeV)", 100, 0.0, 15.0); fhPtNegA = new TH1F("fHistPtNegA", "P_{T} distribution for reconstructed (#{-});P_{T} (GeV/c);dN/dP_{T} (c/GeV)", ptbins, ptlow, ptup); - fhEtaB = new TH1F("fHistEtaB", "#eta distribution for reconstructed before;#eta;counts", 40, 2.0, 2.0); + fhEtaB = new TH1F("fHistEtaB", "#eta distribution for reconstructed before;#eta;counts", 40, -2.0, 2.0); fhEtaA = new TH1F("fHistEtaA", "#eta distribution for reconstructed;#eta;counts", etabins, etalow, etaup); fhPhiB = new TH1F("fHistPhiB", "#phi distribution for reconstructed before;#phi;counts", 360, 0.0, 2 * M_PI); fhPhiA = new TH1F("fHistPhiA", "#phi distribution for reconstructed;#phi;counts", 360, 0.0, 2 * M_PI); @@ -444,7 +457,7 @@ struct DptDptCorrelationsTask { Configurable<bool> cfgProcessPairs{"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}; Configurable<o2::analysis::DptDptBinningCuts> cfgBinning{"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72}, + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}; @@ -459,7 +472,7 @@ struct DptDptCorrelationsTask { float cmmax, Configurable<bool> _cfgProcessPairs = {"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}, Configurable<o2::analysis::DptDptBinningCuts> _cfgBinning = {"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72}, + {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}, OutputObj<TList> _fOutput = {"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}, Filter _onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE), @@ -534,6 +547,7 @@ struct DptDptCorrelationsTask { fhN1_2_vsPt = new TH1F("n1_2_vsPt", "#LT n_{1} #GT;p_{t,2} (GeV/c);#LT n_{1} #GT", ptbins, ptlow, ptup); /* we don't want the Sumw2 structure being created here */ bool defSumw2 = TH1::GetDefaultSumw2(); + TH1::SetDefaultSumw2(false); fhN1_1_vsZEtaPhiPt = new TH3F("n1_1_vsZ_vsEtaPhi_vsPt", "#LT n_{1} #GT;vtx_{z};#eta_{1}#times#varphi_{1};p_{t,1} (GeV/c)", zvtxbins, zvtxlow, zvtxup, etabins * phibins, 0.0, double(etabins * phibins), ptbins, ptlow, ptup); @@ -573,6 +587,7 @@ struct DptDptCorrelationsTask { /* we don't want the Sumw2 structure being created here */ bool defSumw2 = TH1::GetDefaultSumw2(); + TH1::SetDefaultSumw2(false); fhN2_12_vsEtaPhi = new TH1F("n2_12_vsEtaPhi", "#LT n_{2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT n_{2} #GT", etabins * phibins * etabins * phibins, 0., double(etabins * phibins * etabins * phibins)); fhSum2PtPt_12_vsEtaPhi = new TH1F("sumPtPt_12_vsEtaPhi", "#LT #Sigma p_{t,1}p_{t,2} #GT;#eta_{1}#times#varphi_{1}#times#eta_{2}#times#varphi_{2};#LT #Sigma p_{t,1}p_{t,2} #GT (GeV)^{2}", @@ -667,8 +682,8 @@ struct DptDptCorrelationsTask { n1nw_1 += 1; sum1Ptnw_1 += track1.pt(); - fhN1_1_vsEtaPhi->Fill(track1.eta(), track1.phi(), corr); - fhSum1Pt_1_vsEtaPhi->Fill(track1.eta(), track1.phi(), track1.pt() * corr); + fhN1_1_vsEtaPhi->Fill(track1.eta(), GetShiftedPhi(track1.phi()), corr); + fhSum1Pt_1_vsEtaPhi->Fill(track1.eta(), GetShiftedPhi(track1.phi()), track1.pt() * corr); } /* TODO: the centrality should be chosen non detector dependent */ fhN1_1_vsC->Fill(collision.centmult(), n1_1); @@ -689,8 +704,8 @@ struct DptDptCorrelationsTask { n1nw_2 += 1; sum1Ptnw_2 += track2.pt(); - fhN1_2_vsEtaPhi->Fill(track2.eta(), track2.phi(), corr); - fhSum1Pt_2_vsEtaPhi->Fill(track2.eta(), track2.phi(), track2.pt() * corr); + fhN1_2_vsEtaPhi->Fill(track2.eta(), GetShiftedPhi(track2.phi()), corr); + fhSum1Pt_2_vsEtaPhi->Fill(track2.eta(), GetShiftedPhi(track2.phi()), track2.pt() * corr); } /* TODO: the centrality should be chosen non detector dependent */ fhN1_2_vsC->Fill(collision.centmult(), n1_2); @@ -728,10 +743,11 @@ struct DptDptCorrelationsTask { sum2PtPtnw_12 += track1.pt() * track2.pt(); sum2NPtnw_12 += track2.pt(); sum2PtNnw_12 += track1.pt(); - fhN2_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, corr); - fhSum2NPt_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, corr * track2.pt()); - fhSum2PtN_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, track1.pt() * corr); - fhSum2PtPt_12_vsEtaPhi->Fill(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 0.5, track1.pt() * track2.pt() * corr); + /* we already know the bin in the flattened histograms, let's use it to update them */ + fhN2_12_vsEtaPhi->AddBinContent(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 1, corr); + fhSum2NPt_12_vsEtaPhi->AddBinContent(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 1, corr * track2.pt()); + fhSum2PtN_12_vsEtaPhi->AddBinContent(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 1, track1.pt() * corr); + fhSum2PtPt_12_vsEtaPhi->AddBinContent(GetEtaPhiIndex(track1) * etabins * phibins + GetEtaPhiIndex(track2) + 1, track1.pt() * track2.pt() * corr); fhN2_12_vsPtPt->Fill(track1.pt(), track2.pt(), corr); } } @@ -744,6 +760,11 @@ struct DptDptCorrelationsTask { fhSum2PtPtnw_12_vsC->Fill(collision.centmult(), sum2PtPtnw_12); fhSum2PtNnw_12_vsC->Fill(collision.centmult(), sum2PtNnw_12); fhSum2NPtnw_12_vsC->Fill(collision.centmult(), sum2NPtnw_12); + /* let's also update the number of entries in the flattened histograms */ + fhN2_12_vsEtaPhi->SetEntries(fhN2_12_vsEtaPhi->GetEntries() + n2nw_12); + fhSum2NPt_12_vsEtaPhi->SetEntries(fhSum2NPt_12_vsEtaPhi->GetEntries() + n2nw_12); + fhSum2PtN_12_vsEtaPhi->SetEntries(fhSum2PtN_12_vsEtaPhi->GetEntries() + n2nw_12); + fhSum2PtPt_12_vsEtaPhi->SetEntries(fhSum2PtPt_12_vsEtaPhi->GetEntries() + n2nw_12); } } }; From 1375126fbcfe7e872fc218a64aaa522e803a78b6 Mon Sep 17 00:00:00 2001 From: yelmard <38725488+yelmard@users.noreply.github.com> Date: Sun, 27 Sep 2020 08:53:13 +0200 Subject: [PATCH 0785/1751] Initial commit for Raa analysis of charged particles * Add copyright notice Co-authored-by: yelmard <youssef.el.mard.bouziani@cern.ch> --- Analysis/Tasks/PWGLF/CMakeLists.txt | 5 + Analysis/Tasks/PWGLF/raacharged.cxx | 207 ++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 Analysis/Tasks/PWGLF/raacharged.cxx diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt index 3eb3ece255b9a..53a997febd482 100644 --- a/Analysis/Tasks/PWGLF/CMakeLists.txt +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -52,3 +52,8 @@ o2_add_dpl_workflow(cascadeconsumer SOURCES cascadeconsumer PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(raacharged + SOURCES raacharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGLF/raacharged.cxx b/Analysis/Tasks/PWGLF/raacharged.cxx new file mode 100644 index 0000000000000..a1c6d9f6902b7 --- /dev/null +++ b/Analysis/Tasks/PWGLF/raacharged.cxx @@ -0,0 +1,207 @@ +// 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 "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/MC.h" +#include <TH1F.h> +#include <TParticlePDG.h> +#include <TDatabasePDG.h> +#include <cmath> + +using namespace o2; +using namespace o2::framework; + +struct raacharged { + // data members + OutputObj<THnF> fHistTrack{"fHistTrack"}; + OutputObj<THnF> fHistEvent{"fHistEvent"}; + OutputObj<THnF> fHistMC{"fHistMC"}; + Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; + // member functions + void init(InitContext const&) + { + constexpr Int_t nbinsMultCent = 11; + constexpr Int_t nnAcc = 54; + constexpr Int_t nbinspT = 82; + constexpr Int_t nChargeBins = 7; + + Double_t MultCent[] = {0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100}; + Double_t nAccbins[55]; //mult6kcoarse option in AlidNdPtTools + nAccbins[0] = -0.5; + int i = 0; + for (; i <= 10; i++) { + nAccbins[i + 1] = nAccbins[i] + 1; + } + for (; i <= 10 + 9; i++) { + nAccbins[i + 1] = nAccbins[i] + 10; + } + for (; i <= 10 + 9 + 9; i++) { + nAccbins[i + 1] = nAccbins[i] + 100; + } + for (; i <= 10 + 9 + 9 + 25; i++) { + nAccbins[i + 1] = nAccbins[i] + 200; + } + Double_t pTBins[] = {0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0, 32.0, 34.0, 36.0, 40.0, 45.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 130.0, 140.0, 150.0, 160.0, 180.0, 200.0}; + Double_t ChargeBins[] = {-2.5, -1.5, -0.5, 0., 0.5, 1.5, 2.5}; + + Int_t nBinsTrack[4] = {nbinsMultCent - 1, nnAcc - 1, nbinspT - 1, nChargeBins - 1}; + Double_t minTrack[4] = {MultCent[0], nAccbins[0], pTBins[0], ChargeBins[0]}; + Double_t maxTrack[4] = {MultCent[nbinsMultCent - 1], nAccbins[nnAcc - 1], pTBins[nbinspT - 1], ChargeBins[nChargeBins - 1]}; + + fHistTrack.setObject(new THnF("fHistTrack", "Hist. for tracks", 4, nBinsTrack, minTrack, maxTrack)); + fHistTrack->SetBinEdges(0, MultCent); + fHistTrack->SetBinEdges(1, nAccbins); + fHistTrack->SetBinEdges(2, pTBins); + fHistTrack->SetBinEdges(3, ChargeBins); + fHistTrack->GetAxis(0)->SetTitle("cent"); + fHistTrack->GetAxis(1)->SetTitle("nAcc"); + fHistTrack->GetAxis(2)->SetTitle("p_{T} (GeV/c)"); + fHistTrack->GetAxis(3)->SetTitle("Q"); + + constexpr Int_t nbinszV = 13; + Double_t ZvBins[] = {-30., -25., -20., -15., -10., -5., 0., 5., 10., 15., 20., 25., 30.}; + + Int_t nBinsEvent[3] = {nbinsMultCent - 1, nnAcc - 1, nbinszV - 1}; + Double_t minEvent[3] = {MultCent[0], nAccbins[0], ZvBins[0]}; + Double_t maxEvent[3] = {MultCent[nbinsMultCent - 1], nAccbins[nnAcc - 1], ZvBins[nbinszV - 1]}; + + fHistEvent.setObject(new THnF("fHistEvent", "Histogram for Events", 3, nBinsEvent, minEvent, maxEvent)); + fHistEvent->SetBinEdges(0, MultCent); + fHistEvent->SetBinEdges(1, nAccbins); + fHistEvent->SetBinEdges(2, ZvBins); + fHistEvent->GetAxis(0)->SetTitle("cent"); + fHistEvent->GetAxis(1)->SetTitle("nAcc"); + fHistEvent->GetAxis(2)->SetTitle("Zv (cm)"); + + constexpr Int_t nParTypeBins = 11; + constexpr Int_t nMCinfo = 4; + + Double_t ParTypeBins[11] = {-0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5}; // 0=e, 1=mu, 2=pi, 3=K, 4=p, 6=sigmaP, 7=sigmaM, 8=xi, 9=omega, 5=other + Double_t MCinfoBins[4] = {-0.5, 0.5, 1.5, 2.5}; // 0=prim, 1=sec.(decays) 2=genprim , sec. from material not considered + + Int_t nBinsMC[5] = {nbinspT - 1, nParTypeBins - 1, nMCinfo - 1, nChargeBins - 1}; + Double_t minMC[5] = {pTBins[0], ParTypeBins[0], MCinfoBins[0], ChargeBins[0]}; + Double_t maxMC[5] = {pTBins[nbinspT - 1], ParTypeBins[nParTypeBins - 1], MCinfoBins[nMCinfo - 1], ChargeBins[nChargeBins - 1]}; + + fHistMC.setObject(new THnF("fHistMC", "Hist. for MC Info", 4, nBinsMC, minMC, maxMC)); + fHistMC->SetBinEdges(0, pTBins); + fHistMC->SetBinEdges(1, ParTypeBins); + fHistMC->SetBinEdges(2, MCinfoBins); + fHistMC->SetBinEdges(3, ChargeBins); + fHistMC->GetAxis(0)->SetTitle("MCp_{T} (GeV/c)"); + fHistMC->GetAxis(1)->SetTitle("Particle Type"); + fHistMC->GetAxis(2)->SetTitle("MCinfo"); + fHistMC->GetAxis(3)->SetTitle("Q"); + } + + Int_t WhichParticle(Int_t pdgCode) + { //see in AlidNdPtTools + if (pdgCode == 0) + return -1; + if (pdgCode == std::abs(211)) + return 0; //pi+, pi- + if (pdgCode == std::abs(321)) + return 1; //K+, K- + if (pdgCode == std::abs(2212)) + return 2; //p, pbar + if (pdgCode == 3222 || pdgCode == -3112) + return 3; //sigmaPlus, SigmaBarMinus + if (pdgCode == 3112 || pdgCode == -3222) + return 4; //sigmaMinus, SigmaBarPlus + if (pdgCode == std::abs(11)) + return 5; //e-, e+ + if (pdgCode == std::abs(3312)) + return 6; //XiP, XiM + if (pdgCode == std::abs(13)) + return 7; //mu,antimu + if (pdgCode == std::abs(3334)) + return 8; //OmegaP, OmegaM + + return 9; //other + } + Double_t MCCharge(Int_t pdgCode) + { + TParticlePDG* par = TDatabasePDG::Instance()->GetParticle(pdgCode); + Double_t charge = par->Charge() / 3.0; + return charge; + } + + Configurable<bool> isMC{"isMC", 1, "0 - data, 1 - MC"}; + + void process(soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels, aod::Cents>::iterator const& collision, soa::Join<aod::Tracks, aod::McTrackLabels, aod::TrackSelection> const& tracks, aod::McParticles& mcParticles) + { + if (!collision.alias()[kINT7]) + return; + if (!collision.sel7()) + return; + + Double_t eventValues[3] = {0.0, 0.0, collision.posZ()}; + fHistEvent->Fill(eventValues); + + for (auto& track : tracks) { + if (selectedTracks == 1 && !track.isGlobalTrack()) + continue; + else if (selectedTracks == 2 && !track.isGlobalTrackSDD()) + continue; + + Double_t trackValues[4] = {0.0, 0.0, track.pt(), (Double_t)track.charge()}; + fHistTrack->Fill(trackValues); + + Double_t mcInfoVal; + if (!isMC) + continue; + if (MC::isPhysicalPrimary(mcParticles, track.label())) + mcInfoVal = 0.0; + else + mcInfoVal = 1.0; + + Double_t MCpt = track.label().pt(); + Double_t parType = (Double_t)WhichParticle(track.label().pdgCode()); + Double_t MCcharge = (Double_t)track.charge(); + Double_t MCvalues[4] = {MCpt, parType, mcInfoVal, MCcharge}; + + fHistMC->Fill(MCvalues); + } + if (isMC) { + for (auto& mcParticle : mcParticles) { + + if (abs(mcParticle.eta()) > 0.8) + continue; + if (!MC::isPhysicalPrimary(mcParticles, mcParticle)) + continue; + + Double_t MCpt = mcParticle.pt(); + Double_t parType = (Double_t)WhichParticle(mcParticle.pdgCode()); + Int_t pdg = (Int_t)mcParticle.pdgCode(); + Double_t MCcharge = MCCharge(pdg); + + if (MCcharge == 0.0) + continue; + Double_t MCvalues[4] = {MCpt, parType, 2.0, MCcharge}; + fHistMC->Fill(MCvalues); + } + } + } +}; + +//-------------------------------------------------------------------- +// Workflow definition +//-------------------------------------------------------------------- +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<raacharged>("raa-charged")}; +} From 90c2feb32f758560725077cb7e9514807ff5e78c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 28 Sep 2020 01:19:01 +0200 Subject: [PATCH 0786/1751] Revert "Fix: default init. of some ClusterNativeAccess members" This reverts commit 6383682472dfebb46bc74a0bb4ad21e1a5cc0e7c. --- .../Detectors/TPC/include/DataFormatsTPC/ClusterNative.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h index 6f9ce3afbb8fd..4dcabd1913159 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h @@ -155,13 +155,13 @@ struct ClusterNative { // This is an index struct to access TPC clusters inside sectors and rows. It shall not own the data, but just point to // the data inside a buffer. struct ClusterNativeAccess { - const ClusterNative* clustersLinear = nullptr; + const ClusterNative* clustersLinear; const ClusterNative* clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clustersMCTruth = nullptr; + const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clustersMCTruth; unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; unsigned int nClustersSector[constants::MAXSECTOR]; unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; - unsigned int nClustersTotal = 0; + unsigned int nClustersTotal; void setOffsetPtrs(); }; From 3013e8d79b6df4ff4a61702f687aa5542421f354 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 28 Sep 2020 01:32:59 +0200 Subject: [PATCH 0787/1751] reset ClusterNativeAccess before using it --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index f71b3b77a7a84..8eaa623058f67 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -470,6 +470,7 @@ void GPUChainTracking::AllocateIOMemory() AllocateIOMemoryHelper(mIOPtrs.nSliceClusters[i], mIOPtrs.sliceClusters[i], mIOMem.sliceClusters[i]); } mIOMem.clusterNativeAccess.reset(new ClusterNativeAccess); + std::memset(mIOMem.clusterNativeAccess.get(), 0, sizeof(ClusterNativeAccess)); // ClusterNativeAccess has no its own constructor AllocateIOMemoryHelper(mIOMem.clusterNativeAccess->nClustersTotal, mIOMem.clusterNativeAccess->clustersLinear, mIOMem.clustersNative); mIOPtrs.clustersNative = mIOMem.clusterNativeAccess->nClustersTotal ? mIOMem.clusterNativeAccess.get() : nullptr; AllocateIOMemoryHelper(mIOPtrs.nMCLabelsTPC, mIOPtrs.mcLabelsTPC, mIOMem.mcLabelsTPC); From 11d8d3a7692031121bd303e0d235b577f1fa8f50 Mon Sep 17 00:00:00 2001 From: hristov <Peter.Hristov@cern.ch> Date: Sun, 27 Sep 2020 21:21:07 +0200 Subject: [PATCH 0788/1751] Fixes for Root 6-22-02 --- .../include/PIDBase/DetectorResponse.h | 2 ++ .../SimulationDataFormat/LabelContainer.h | 20 +++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Analysis/DataModel/include/PIDBase/DetectorResponse.h b/Analysis/DataModel/include/PIDBase/DetectorResponse.h index 856c6e2231ba5..a7d4d779b59d5 100644 --- a/Analysis/DataModel/include/PIDBase/DetectorResponse.h +++ b/Analysis/DataModel/include/PIDBase/DetectorResponse.h @@ -19,6 +19,8 @@ #ifndef O2_ANALYSIS_PID_DETECTORRESPONSE_H_ #define O2_ANALYSIS_PID_DETECTORRESPONSE_H_ +#include <array> +#include <vector> // ROOT includes #include "Rtypes.h" #include "TMath.h" diff --git a/DataFormats/simulation/include/SimulationDataFormat/LabelContainer.h b/DataFormats/simulation/include/SimulationDataFormat/LabelContainer.h index e13b1e5dafa23..656f4c2ed18d4 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/LabelContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/LabelContainer.h @@ -38,18 +38,18 @@ class LabelContainer public: struct HeaderElementContinuous { HeaderElementContinuous() = default; // for ROOT IO - HeaderElementContinuous(ushort s, uint i) : size(s), index(i) {} - uint index = 0; // index of first label in the actual label storage - ushort size = 0; // total number of labels + HeaderElementContinuous(unsigned short s, unsigned int i) : size(s), index(i) {} + unsigned int index = 0; // index of first label in the actual label storage + unsigned short size = 0; // total number of labels ClassDefNV(HeaderElementContinuous, 1); }; struct HeaderElementLinked { HeaderElementLinked() = default; // for ROOT IO - HeaderElementLinked(uint i, int l, ushort s) : index(i), lastindex(l), size(s) {} - uint index = 0; // index of first label in the actual label storage - uint lastindex = 0; // index of last label in the actual label storage - ushort size = 0; // total number of labels + HeaderElementLinked(unsigned int i, int l, unsigned short s) : index(i), lastindex(l), size(s) {} + unsigned int index = 0; // index of first label in the actual label storage + unsigned int lastindex = 0; // index of last label in the actual label storage + unsigned short size = 0; // total number of labels ClassDefNV(HeaderElementLinked, 1); }; @@ -57,11 +57,11 @@ class LabelContainer using StoredLabelType = typename std::conditional<isContiguousStorage, LabelType, std::pair<LabelType, int>>::type; // internal functions allowing the iterator implementation to be completely generic - static uint getNextIndex(uint index, std::vector<LabelType> const& /*labels*/) + static unsigned int getNextIndex(unsigned int index, std::vector<LabelType> const& /*labels*/) { return index + 1; } - static uint getNextIndex(uint index, std::vector<std::pair<LabelType, int>> const& labels) + static unsigned int getNextIndex(unsigned int index, std::vector<std::pair<LabelType, int>> const& labels) { return labels[index].second; } @@ -202,7 +202,7 @@ class LabelContainer } /// add a label for a dataindex - void addLabel(uint dataindex, LabelType const& label) + void addLabel(unsigned int dataindex, LabelType const& label) { // refer to concrete specialized implementation addLabelImpl(dataindex, mHeaderArray, mLabelArray, label); From 1c7d18972da3c21eb497e46e2669e383a70989e6 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 27 Sep 2020 18:56:02 +0200 Subject: [PATCH 0789/1751] Temporary hack to redefine staveID to staveID_from_FEEID%NStavesOnLr Since the ITS test data contain staveIDs exceeding real number of staves on the layer, with _OVERRIDE_RUID_HACK_ defined the staveID seen in the RDH.FEEID will be redefined to %NStavesOnLr --- .../include/ITSMFTReconstruction/ChipMappingITS.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h index b7ff106324f3d..ae278d79e3e0b 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h @@ -28,6 +28,8 @@ namespace o2 namespace itsmft { +#define _OVERRIDE_RUID_HACK_ + class ChipMappingITS { public: @@ -67,6 +69,9 @@ class ChipMappingITS lr = feeID >> 12; ruOnLr = feeID & 0x3f; link = (feeID >> 8) & 0x3; +#ifdef _OVERRIDE_RUID_HACK_ + ruOnLr %= NStavesOnLr[lr]; +#endif } ///< impose user defined FEEId -> ruSW (staveID) conversion, to be used only for forced decoding of corrupted data @@ -129,7 +134,15 @@ class ChipMappingITS } ///< get SW id of the RU from RU HW id - uint8_t FEEId2RUSW(uint16_t hw) const { return mFEEId2RUSW[hw]; } + uint8_t FEEId2RUSW(uint16_t hw) const + { +#ifdef _OVERRIDE_RUID_HACK_ + uint16_t lr, ruOnLr, link; + expandFEEId(hw, lr, ruOnLr, link); + hw = composeFEEId(lr, ruOnLr, link); +#endif + return mFEEId2RUSW[hw]; + } ///< get FEEId of the RU (software id of the RU), read via given link uint16_t RUSW2FEEId(uint16_t sw, uint16_t linkID = 0) const From 653c7f8df09164b1dcecaa9796d058fe083b2f44 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 27 Sep 2020 18:24:31 +0200 Subject: [PATCH 0790/1751] Fix processing of TDH.noData flag in ITS raw data The behaviour of RawPixelDecoded was to proceed to the next TF if decodeNextTrigger did not find any link with data: the absence of data was interpteted as reaching the end of TF data for all links. With introduction of TDH.noData one can have triggers w/o data: decoder will explicitly count number of links exhausted their data and will proceed to next TF only once this counter is equal to total number of links (or if there was an abort signal due to the error in decoding). --- .../include/ITSMFTReconstruction/GBTLink.h | 1 + .../ITSMFTReconstruction/RawPixelDecoder.h | 1 + .../common/reconstruction/src/GBTLink.cxx | 3 +- .../reconstruction/src/RawPixelDecoder.cxx | 53 +++++++++++-------- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h index 7d29794b71308..29c987611cd62 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h @@ -32,6 +32,7 @@ #define GBTLINK_DECODE_ERRORCHECK(what) \ if ((what) == Abort) { \ discardData(); \ + LOG(ERROR) << "Aborting decoding"; \ return AbortedOnError; \ } else if ((what) == Skip) { \ continue; \ diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 1eb3c7b2057c5..c98a367254743 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -117,6 +117,7 @@ class RawPixelDecoder final : public PixelReader o2::itsmft::ROFRecord::ROFtype mROFCounter = 0; // RSTODO is this needed? eliminate from ROFRecord ? uint32_t mNChipsFiredROF = 0; // counter within the ROF uint32_t mNPixelsFiredROF = 0; // counter within the ROF + uint32_t mNLinksDone = 0; // number of links reached end of data size_t mNChipsFired = 0; // global counter size_t mNPixelsFired = 0; // global counter TStopwatch mTimerTFStart; diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index f661fb84e1385..4b1219e988500 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -71,7 +71,8 @@ void GBTLink::clear(bool resetStat, bool resetTFRaw) void GBTLink::printTrigger(const GBTTrigger* gbtTrg) { gbtTrg->printX(); - LOG(INFO) << "Trigger : Orbit " << gbtTrg->orbit << " BC: " << gbtTrg->bc; + std::bitset<12> trb(gbtTrg->triggerType); + LOG(INFO) << "Trigger : Orbit " << gbtTrg->orbit << " BC: " << gbtTrg->bc << " Trigger: " << trb << " noData:" << gbtTrg->noData << " internal:" << gbtTrg->internal; } ///_________________________________________________________________ diff --git a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx index f84c11ceb2bc0..3ebd568baa5ad 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx @@ -78,37 +78,41 @@ int RawPixelDecoder<Mapping>::decodeNextTrigger() mNPixelsFiredROF = 0; mInteractionRecord.clear(); int nLinksWithData = 0, nru = mRUDecodeVec.size(); + do { #ifdef WITH_OPENMP - omp_set_num_threads(mNThreads); + omp_set_num_threads(mNThreads); #pragma omp parallel for schedule(dynamic) reduction(+ \ : nLinksWithData, mNChipsFiredROF, mNPixelsFiredROF) #endif - for (int iru = 0; iru < nru; iru++) { - nLinksWithData += decodeNextTrigger(iru); - mNChipsFiredROF += mRUDecodeVec[iru].nChipsFired; - int npix = 0; - for (int ic = mRUDecodeVec[iru].nChipsFired; ic--;) { - npix += mRUDecodeVec[iru].chipsData[ic].getData().size(); + for (int iru = 0; iru < nru; iru++) { + nLinksWithData += decodeNextTrigger(iru); + mNChipsFiredROF += mRUDecodeVec[iru].nChipsFired; + int npix = 0; + for (int ic = mRUDecodeVec[iru].nChipsFired; ic--;) { + npix += mRUDecodeVec[iru].chipsData[ic].getData().size(); + } + mNPixelsFiredROF += npix; } - mNPixelsFiredROF += npix; - } - if (nLinksWithData) { // fill some statistics - mROFCounter++; - mNChipsFired += mNChipsFiredROF; - mNPixelsFired += mNPixelsFiredROF; - mCurRUDecodeID = 0; // getNextChipData will start from here - mLastReadChipID = -1; - // set IR and trigger from the 1st non empty link - for (const auto& link : mGBTLinks) { - if (link.status == GBTLink::DataSeen) { - mInteractionRecord = link.ir; - mInteractionRecordHB = o2::raw::RDHUtils::getHeartBeatIR(*link.lastRDH); - mTrigger = link.trigger; - break; + if (nLinksWithData) { // fill some statistics + mROFCounter++; + mNChipsFired += mNChipsFiredROF; + mNPixelsFired += mNPixelsFiredROF; + mCurRUDecodeID = 0; // getNextChipData will start from here + mLastReadChipID = -1; + // set IR and trigger from the 1st non empty link + for (const auto& link : mGBTLinks) { + if (link.status == GBTLink::DataSeen) { + mInteractionRecord = link.ir; + mInteractionRecordHB = o2::raw::RDHUtils::getHeartBeatIR(*link.lastRDH); + mTrigger = link.trigger; + break; + } } + break; } - } + + } while (mNLinksDone < mGBTLinks.size()); mTimerDecode.Stop(); // LOG(INFO) << "Chips Fired: " << mNChipsFiredROF << " NPixels: " << mNPixelsFiredROF << " at IR " << mInteractionRecord << " of HBF " << mInteractionRecordHB; return nLinksWithData; @@ -128,6 +132,7 @@ void RawPixelDecoder<Mapping>::startNewTF(InputRecord& inputs) ru.clear(); } setupLinks(inputs); + mNLinksDone = 0; mTimerTFStart.Stop(); } @@ -145,6 +150,8 @@ int RawPixelDecoder<Mapping>::decodeNextTrigger(int iru) auto res = link->collectROFCableData(mMAP); if (res == GBTLink::DataSeen) { // at the moment process only DataSeen ndec++; + } else if (res == GBTLink::StoppedOnEndOfData || res == GBTLink::AbortedOnError) { // this link has exhausted its data or it has to be discarded due to the error + mNLinksDone++; } } } From 611ba2c753e33171dcef726662ea63e38501e3ec Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Sun, 27 Sep 2020 17:11:03 +0200 Subject: [PATCH 0791/1751] Adjust MFT digit reader Needed adjustment due to new IO label format. --- Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx index 31fdeb964b5d8..e185fc6bcd69d 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx @@ -20,7 +20,8 @@ #include "Framework/Logger.h" #include "DataFormatsITSMFT/Digit.h" #include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include "DataFormatsITSMFT/ROFRecord.h" using namespace o2::framework; @@ -58,7 +59,7 @@ void DigitReader::run(ProcessingContext& pc) std::vector<ROFRecord> rofs, *profs = &rofs; treeDig->SetBranchAddress("MFTDigitROF", &profs); - o2::dataformats::MCTruthContainer<o2::MCCompLabel> labels, *plabels = &labels; + o2::dataformats::IOMCTruthContainerView* plabels = nullptr; std::vector<MC2ROFRecord> mc2rofs, *pmc2rofs = &mc2rofs; if (mUseMC) { treeDig->SetBranchAddress("MFTDigitMCTruth", &plabels); @@ -72,7 +73,9 @@ void DigitReader::run(ProcessingContext& pc) pc.outputs().snapshot(Output{"MFT", "DIGITS", 0, Lifetime::Timeframe}, digits); pc.outputs().snapshot(Output{"MFT", "DIGITSROF", 0, Lifetime::Timeframe}, *profs); if (mUseMC) { - pc.outputs().snapshot(Output{"MFT", "DIGITSMCTR", 0, Lifetime::Timeframe}, labels); + auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{"MFT", "DIGITSMCTR", 0, Lifetime::Timeframe}); + plabels->copyandflatten(sharedlabels); + delete plabels; pc.outputs().snapshot(Output{"MFT", "DIGITSMC2ROF", 0, Lifetime::Timeframe}, *pmc2rofs); } } else { From 5a581963a59404f97ccac3fbfa086d64b92c88a9 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 23 Jul 2020 15:34:35 +0200 Subject: [PATCH 0792/1751] Fix memory leak in o2-sim --noemptyevents --- run/O2HitMerger.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 90d0fe0e8d8e8..7c108fc2e105e 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -309,6 +309,16 @@ class O2HitMerger : public FairMQDevice return expectmore; } + void cleanEvent(int eventID) + { + // remove tree for that eventID + delete mEventToTTreeMap[eventID]; + mEventToTTreeMap.erase(eventID); + // remove memfile + delete mEventToTMemFileMap[eventID]; + mEventToTMemFileMap.erase(eventID); + } + template <typename T> void backInsert(T const& from, T& to) { @@ -569,7 +579,7 @@ class O2HitMerger : public FairMQDevice if (confref.isFilterOutNoHitEvents()) { if (eventheader && eventheader->getMCEventStats().getNHits() == 0) { LOG(INFO) << " Taking out event " << eventID << " due to no hits "; - + cleanEvent(eventID); return false; } } @@ -618,12 +628,7 @@ class O2HitMerger : public FairMQDevice LOG(INFO) << "outtree has file " << mOutTree->GetDirectory()->GetFile()->GetName(); mOutFile->Write("", TObject::kOverwrite); - // remove tree for that eventID - delete mEventToTTreeMap[eventID]; - mEventToTTreeMap.erase(eventID); - // remove memfile - delete mEventToTMemFileMap[eventID]; - mEventToTMemFileMap.erase(eventID); + cleanEvent(eventID); LOG(INFO) << "MERGING HITS TOOK " << timer.RealTime(); return true; From f206cf5b216eafdda06ecd9d304c0a58ee74d967 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 23 Jul 2020 22:45:33 +0200 Subject: [PATCH 0793/1751] Fix race condition in HitMerger lock regions where mEventToTTreeMap and mEventToTMemFileMap are modified --- run/O2HitMerger.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 7c108fc2e105e..386558fc404ba 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -61,6 +61,7 @@ #include <map> #include <vector> #include <csignal> +#include <mutex> #ifdef ENABLE_UPGRADES #include <ITS3Simulation/Detector.h> @@ -192,7 +193,7 @@ class O2HitMerger : public FairMQDevice void fillBranch(int eventID, std::string const& name, T* ptr) { // fetch tree into which to fill - + const std::lock_guard<std::mutex> lock(mMapsMtx); auto iter = mEventToTTreeMap.find(eventID); if (iter == mEventToTTreeMap.end()) { { @@ -312,11 +313,11 @@ class O2HitMerger : public FairMQDevice void cleanEvent(int eventID) { // remove tree for that eventID + const std::lock_guard<std::mutex> lock(mMapsMtx); delete mEventToTTreeMap[eventID]; - mEventToTTreeMap.erase(eventID); - // remove memfile delete mEventToTMemFileMap[eventID]; - mEventToTMemFileMap.erase(eventID); + mEventToTTreeMap.erase(eventID); + mEventToTMemFileMap.erase(eventID); // remove memfile } template <typename T> @@ -648,7 +649,7 @@ class O2HitMerger : public FairMQDevice std::unordered_map<int, TTree*> mEventToTTreeMap; //! in memory trees to collect / presort incoming data per event std::unordered_map<int, TMemFile*> mEventToTMemFileMap; //! files associated to the TTrees std::thread mMergerIOThread; //! a thread used to do hit merging and IO flushing asynchronously - + std::mutex mMapsMtx; //! int mEntries = 0; //! counts the number of entries in the branches int mEventChecksum = 0; //! checksum for events int mNExpectedEvents = 0; //! number of events that we expect to receive From 7fbb397b971a0aca1c42bc8511e87cd08de91f28 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 28 Sep 2020 09:29:22 +0200 Subject: [PATCH 0794/1751] Update sim_challenge.sh correct name of ft0 workflow (o2-fit-reco-workflow does not exist) --- prodtests/sim_challenge.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 2474bda21a336..e85908952a86e 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -222,10 +222,10 @@ if [ "$doreco" == "1" ]; then taskwrapper mftreco.log o2-mft-reco-workflow $gloOpt echo "Return status of mftreco: $?" - echo "Running FIT(FT0) reco flow" - #needs FIT digitized data - taskwrapper fitreco.log o2-fit-reco-workflow $gloOpt - echo "Return status of fitreco: $?" + echo "Running FT0 reco flow" + #needs FT0 digitized data + taskwrapper ft0reco.log o2-ft0-reco-workflow $gloOpt + echo "Return status of ft0reco: $?" echo "Running ITS-TPC macthing flow" #needs results of o2-tpc-reco-workflow, o2-its-reco-workflow and o2-fit-reco-workflow From 8af9b02cc93876f901ea056fcd479cbd6e4f12a2 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 28 Sep 2020 13:07:45 +0200 Subject: [PATCH 0795/1751] DPL Analysis: stop reader and let other tasks finish by end of stream (#4458) --- Framework/Core/src/AODReaderHelpers.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 0b8d90977878e..85d11bc12aefc 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -120,7 +120,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() LOGP(INFO, "Stopping after time frame {}.", watchdog->numberTimeFrames - 1); didir->closeInputFiles(); control.endOfStream(); - control.readyToQuit(QuitRequest::All); + control.readyToQuit(QuitRequest::Me); return; } From 322d34cb30c266538b9764b47b29ce9682d5706a Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Mon, 28 Sep 2020 19:30:28 +0200 Subject: [PATCH 0796/1751] TrackSelection: fix wrong calculation of dca (#4450) * TrackSelection: fix wrong calculation of dca * remove most of broken tracks * add getTrackPar to trackUtilities * remove tracks with large x Co-authored-by: Mario Kruger <mario.kruger@cern.ch> --- .../include/Analysis/trackUtilities.h | 10 ++++++ Analysis/Tasks/trackselection.cxx | 33 +++++++++---------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/trackUtilities.h b/Analysis/DataModel/include/Analysis/trackUtilities.h index 4941a4eb268a2..f9c909fc868dd 100644 --- a/Analysis/DataModel/include/Analysis/trackUtilities.h +++ b/Analysis/DataModel/include/Analysis/trackUtilities.h @@ -22,6 +22,16 @@ #include "ReconstructionDataFormats/Vertex.h" #include "Analysis/RecoDecay.h" +/// Extracts track parameters from a track. +/// \return o2::track::TrackPar +template <typename T> +auto getTrackPar(const T& track) +{ + std::array<float, 5> arraypar = {track.y(), track.z(), track.snp(), + track.tgl(), track.signed1Pt()}; + return o2::track::TrackPar(track.x(), track.alpha(), std::move(arraypar)); +} + /// Extracts track parameters and covariance matrix from a track. /// \return o2::track::TrackParCov template <typename T> diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index 82e15526e4084..b1faf009f8d2d 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -21,6 +21,7 @@ #include "Analysis/TrackSelection.h" #include "Analysis/TrackSelectionTables.h" #include "Framework/runDataProcessing.h" +#include "Analysis/trackUtilities.h" using namespace o2; using namespace o2::framework; @@ -65,7 +66,9 @@ TrackSelection getGlobalTrackSelectionwTOF() //**************************************************************************************** /** - * Produce the derived track quantities needed for track selection. + * Produce the more complicated derived track quantities needed for track selection. + * FIXME: we shall run this only if all other selections are passed to avoid + * FIXME: computing overhead and errors in calculations */ //**************************************************************************************** struct TrackExtensionTask { @@ -74,25 +77,19 @@ struct TrackExtensionTask { void process(aod::Collision const& collision, aod::FullTracks const& tracks) { - float sinAlpha = 0.f; - float cosAlpha = 0.f; - float globalX = 0.f; - float globalY = 0.f; - float dcaXY = 0.f; - float dcaZ = 0.f; - for (auto& track : tracks) { - sinAlpha = sin(track.alpha()); - cosAlpha = cos(track.alpha()); - globalX = track.x() * cosAlpha - track.y() * sinAlpha; - globalY = track.x() * sinAlpha + track.y() * cosAlpha; - - dcaXY = track.charge() * sqrt(pow((globalX - collision.posX()), 2) + - pow((globalY - collision.posY()), 2)); - dcaZ = track.charge() * sqrt(pow(track.z() - collision.posZ(), 2)); - - extendedTrackQuantities(dcaXY, dcaZ); + std::array<float, 2> dca{1e10f, 1e10f}; + // FIXME: temporary solution to remove tracks that should not be there after conversion + if (track.trackType() == o2::aod::track::TrackTypeEnum::GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && track.x() < 150.f) { + float magField = 5.0; // in kG (FIXME: get this from CCDB) + auto trackPar = getTrackPar(track); + trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, magField, &dca); + } + extendedTrackQuantities(dca[0], dca[1]); + + // TODO: add realtive pt resolution sigma(pt)/pt \approx pt * sigma(1/pt) + // TODO: add geometrical length / fiducial volume } } }; From ec7f38d41657bdb4321bd445bbde3776cecc96ce Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Mon, 28 Sep 2020 17:16:51 -0300 Subject: [PATCH 0797/1751] Finder tuned: prefiltering for performance (#4452) --- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 108 +++++++++++++-------- 1 file changed, 66 insertions(+), 42 deletions(-) diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index df5ed68c14f95..1e72a6f25ef20 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -44,6 +44,55 @@ using namespace o2::framework::expressions; using std::array; using namespace ROOT::Math; +namespace o2::aod +{ +namespace v0goodpostracks +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, FullTracks, "fGoodTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +} // namespace v0goodpostracks +DECLARE_SOA_TABLE(V0GoodPosTracks, "AOD", "V0GOODPOSTRACKS", o2::soa::Index<>, v0goodpostracks::GoodTrackId, v0goodpostracks::CollisionId, v0goodpostracks::DCAXY); +namespace v0goodnegtracks +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, FullTracks, "fGoodTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +} // namespace v0goodnegtracks +DECLARE_SOA_TABLE(V0GoodNegTracks, "AOD", "V0GOODNEGTRACKS", o2::soa::Index<>, v0goodnegtracks::GoodTrackId, v0goodnegtracks::CollisionId, v0goodnegtracks::DCAXY); +} // namespace o2::aod + +struct lambdakzeroprefilter { + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<int> mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + + Produces<aod::V0GoodPosTracks> v0GoodPosTracks; + Produces<aod::V0GoodNegTracks> v0GoodNegTracks; + + Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodPosTracks = aod::track::signed1Pt > 0.0f && aod::track::dcaXY > dcapostopv; + Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodNegTracks = aod::track::signed1Pt < 0.0f && aod::track::dcaXY < -dcanegtopv; + + void process(aod::Collision const& collision, + soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) + { + for (auto& t0 : goodPosTracks) { + if (!(t0.flags() & 0x40)) + continue; //TPC refit + if (t0.tpcNClsCrossedRows() < mincrossedrows) + continue; + v0GoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); + } + for (auto& t0 : goodNegTracks) { + if (!(t0.flags() & 0x40)) + continue; //TPC refit + if (t0.tpcNClsCrossedRows() < mincrossedrows) + continue; + v0GoodNegTracks(t0.globalIndex(), t0.collisionId(), -t0.dcaXY()); + } + } +}; + struct lambdakzerofinder { Produces<aod::V0Data> v0data; Produces<aod::V0FinderData> v0finderdata; @@ -57,32 +106,10 @@ struct lambdakzerofinder { //Selection criteria Configurable<double> v0cospa{"v0cospa", 0.995, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) Configurable<float> dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; - Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; - Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; Configurable<float> v0radius{"v0radius", 5.0, "v0radius"}; - //using myTracks = soa::Filtered<aod::Tracks>; - //using myTracks = soa::Filtered<aod::fullTracks>; - - Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodPosTracks = aod::track::signed1Pt > 0.0f && aod::track::dcaXY > dcapostopv; - Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodNegTracks = aod::track::signed1Pt < 0.0f && aod::track::dcaXY < -dcanegtopv; - - /// Extracts dca in the XY plane - /// \return dcaXY - template <typename T, typename U> - auto getdcaXY(const T& track, const U& coll) - { - //Calculate DCAs - auto sinAlpha = sin(track.alpha()); - auto cosAlpha = cos(track.alpha()); - auto globalX = track.x() * cosAlpha - track.y() * sinAlpha; - auto globalY = track.x() * sinAlpha + track.y() * cosAlpha; - return sqrt(pow((globalX - coll[0]), 2) + - pow((globalY - coll[1]), 2)); - } - - void process(aod::Collision const& collision, - soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) + void process(aod::Collision const& collision, aod::FullTracks const& tracks, + aod::V0GoodPosTracks const& ptracks, aod::V0GoodNegTracks const& ntracks) { //Define o2 fitter, 2-prong o2::vertexing::DCAFitterN<2> fitter; @@ -99,14 +126,11 @@ struct lambdakzerofinder { std::array<float, 3> pVtx = {collision.posX(), collision.posY(), collision.posZ()}; - for (auto& t0 : goodPosTracks) { //FIXME: turn into combination(...) - if (t0.tpcNClsCrossedRows() < 70) - continue; //FIXME: turn into extra filter - for (auto& t1 : goodNegTracks) { - if (t1.tpcNClsCrossedRows() < 70) - continue; //FIXME: turn into extra filter - - auto Track1 = getTrackParCov(t0); + for (auto& t0id : ptracks) { //FIXME: turn into combination(...) + auto t0 = t0id.goodTrack(); + auto Track1 = getTrackParCov(t0); + for (auto& t1id : ntracks) { + auto t1 = t1id.goodTrack(); auto Track2 = getTrackParCov(t1); //Try to progate to dca @@ -144,7 +168,7 @@ struct lambdakzerofinder { pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], fitter.getChi2AtPCACandidate(), - t0.dcaXY(), -t1.dcaXY()); + t0id.dcaXY(), t1id.dcaXY()); } } hCandPerEvent->Fill(lNCand); @@ -172,14 +196,15 @@ struct lambdakzerofinderQA { OutputObj<TH3F> h3dMassLambda{TH3F("h3dMassLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; OutputObj<TH3F> h3dMassAntiLambda{TH3F("h3dMassAntiLambda", "", 20, 0, 100, 200, 0, 10, 200, 1.115 - 0.100, 1.115 + 0.100)}; - OutputObj<TH1F> hTest{TH1F("hTest", "", 1000, 0, 1000)}; - - Filter preFilterV0 = aod::v0data::dcapostopv > dcapostopv&& - aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + //FIXME: figure out why this does not work? + //Filter preFilter1 = aod::v0data::dcapostopv > dcapostopv; + //Filter preFilter2 = aod::v0data::dcanegtopv > dcanegtopv; + //Filter preFilter3 = aod::v0data::dcaV0daughters < dcav0dau; ///Connect to V0FinderData: newly indexed, note: V0DataExt table incompatible with standard V0 table! - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, aod::FullTracks const& tracks, - soa::Filtered<soa::Join<aod::V0FinderData, aod::V0DataExt>> const& fullV0s) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, + // soa::Filtered<soa::Join<aod::V0FinderData, aod::V0DataExt>> const& fullV0s) + soa::Join<aod::V0FinderData, aod::V0DataExt> const& fullV0s) { if (!collision.alias()[kINT7]) return; @@ -188,15 +213,13 @@ struct lambdakzerofinderQA { Long_t lNCand = 0; for (auto& v0 : fullV0s) { - if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa) { + if (v0.v0radius() > v0radius && v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && v0.dcapostopv() > dcapostopv && v0.dcanegtopv() > dcanegtopv && v0.dcaV0daughters() > dcav0dau) { hV0Radius->Fill(v0.v0radius()); hV0CosPA->Fill(v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); hDCAPosToPV->Fill(v0.dcapostopv()); hDCANegToPV->Fill(v0.dcanegtopv()); hDCAV0Dau->Fill(v0.dcaV0daughters()); - hTest->Fill(v0.posTrack().pt()); - if (TMath::Abs(v0.yLambda()) < 0.5) { h3dMassLambda->Fill(collision.centV0M(), v0.pt(), v0.mLambda()); h3dMassAntiLambda->Fill(collision.centV0M(), v0.pt(), v0.mAntiLambda()); @@ -219,6 +242,7 @@ struct lambdakzeroinitializer { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ + adaptAnalysisTask<lambdakzeroprefilter>("lf-lambdakzeroprefilter"), adaptAnalysisTask<lambdakzerofinder>("lf-lambdakzerofinder"), adaptAnalysisTask<lambdakzeroinitializer>("lf-lambdakzeroinitializer"), adaptAnalysisTask<lambdakzerofinderQA>("lf-lambdakzerofinderQA")}; From ff5925abed623125fd6fbb719bab9e9a7b56a7cb Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 29 Sep 2020 10:47:56 +0200 Subject: [PATCH 0798/1751] DPL: added table builder warning for empty tables (#4439) --- Framework/Core/include/Framework/TableBuilder.h | 3 +-- Framework/Core/src/DataAllocator.cxx | 3 +++ Framework/Core/src/TableBuilder.cxx | 9 ++------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index 835ed75e40445..350c7b183712f 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -435,12 +435,11 @@ class TableBuilder template <typename... ARGS> auto makeFinalizer() { - mFinalizer = [schema = mSchema, &arrays = mArrays, builders = mBuilders]() -> std::shared_ptr<arrow::Table> { + mFinalizer = [schema = mSchema, &arrays = mArrays, builders = mBuilders]() -> void { auto status = TableBuilderHelpers::finalize(arrays, *(BuildersTuple<ARGS...>*)builders, std::make_index_sequence<sizeof...(ARGS)>{}); if (status == false) { throw std::runtime_error("Unable to finalize"); } - return arrow::Table::Make(schema, arrays); }; } diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index 3dba019767e77..d39ccd2ceeeb9 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -150,6 +150,9 @@ void DataAllocator::adopt(const Output& spec, TableBuilder* tb) std::shared_ptr<TableBuilder> p(tb); auto finalizer = [payload = p](std::shared_ptr<FairMQResizableBuffer> b) -> void { auto table = payload->finalize(); + if (O2_BUILTIN_UNLIKELY(table->num_rows() == 0)) { + LOG(WARN) << "Empty table was produced: " << table->ToString(); + } auto stream = std::make_shared<arrow::io::BufferOutputStream>(b); auto outBatch = arrow::ipc::NewStreamWriter(stream.get(), table->schema()); diff --git a/Framework/Core/src/TableBuilder.cxx b/Framework/Core/src/TableBuilder.cxx index 6c88e0477c97c..f05604c365f38 100644 --- a/Framework/Core/src/TableBuilder.cxx +++ b/Framework/Core/src/TableBuilder.cxx @@ -51,13 +51,8 @@ std::shared_ptr<arrow::Table> TableBuilder::finalize() { mFinalizer(); - std::vector<std::shared_ptr<arrow::ChunkedArray>> columns; - columns.reserve(mArrays.size()); - for (auto i = 0; i < mSchema->num_fields(); ++i) { - auto column = std::make_shared<arrow::ChunkedArray>(mArrays[i]); - columns.emplace_back(column); - } - return arrow::Table::Make(mSchema, columns); + assert(mSchema->num_fields() > 0 && "Schema needs to be non-empty"); + return arrow::Table::Make(mSchema, mArrays); } } // namespace o2::framework From dd0f93add7deb8c51a8a09efd6f2522729a98e4f Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 29 Sep 2020 13:43:56 +0200 Subject: [PATCH 0799/1751] data model changes: track type and flags, add golden chi2 cut (#4459) --- Analysis/Core/include/Analysis/TrackSelection.h | 17 ++++++++++------- .../include/Analysis/TrackSelectionTables.h | 4 +--- Analysis/Tasks/trackqa.cxx | 2 +- Analysis/Tasks/trackselection.cxx | 17 ++++------------- .../Core/include/Framework/AnalysisDataModel.h | 2 +- Framework/Core/include/Framework/DataTypes.h | 8 +++++++- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/Analysis/TrackSelection.h index 1ad02643500c7..d67702fcdbbb7 100644 --- a/Analysis/Core/include/Analysis/TrackSelection.h +++ b/Analysis/Core/include/Analysis/TrackSelection.h @@ -39,9 +39,9 @@ class TrackSelection (track.itsNCls() >= mMinNClustersITS) && (track.itsChi2NCl() <= mMaxChi2PerClusterITS) && (track.tpcChi2NCl() <= mMaxChi2PerClusterTPC) && - ((mRequireITSRefit) ? (track.flags() & 0x4) : true) && - ((mRequireTPCRefit) ? (track.flags() & 0x40) : true) && - ((mRequireTOF) ? ((track.flags() & 0x2000) && (track.flags() & 0x80000000)) : true) && + ((mRequireITSRefit) ? (track.flags() & o2::aod::track::ITSrefit) : true) && + ((mRequireTPCRefit) ? (track.flags() & o2::aod::track::TPCrefit) : true) && + ((mRequireGoldenChi2) ? (track.flags() & o2::aod::track::GoldenChi2) : true) && FulfillsITSHitRequirements(track.itsClusterMap()) && abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY) && abs(track.dcaZ()) <= mMaxDcaZ) { @@ -70,7 +70,10 @@ class TrackSelection { mRequireTPCRefit = requireTPCRefit; } - void SetRequireTOF(bool requireTOF = true) { mRequireTOF = requireTOF; } + void SetRequireGoldenChi2(bool requireGoldenChi2 = true) + { + mRequireGoldenChi2 = requireGoldenChi2; + } void SetMinNClustersTPC(int minNClustersTPC) { mMinNClustersTPC = minNClustersTPC; @@ -138,9 +141,9 @@ class TrackSelection float mMaxDcaZ{1e10f}; // max dca in z direction std::function<float(float)> mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT - bool mRequireITSRefit{false}; // require refit in ITS - bool mRequireTPCRefit{false}; // require refit in TPC - bool mRequireTOF{false}; // require that track exits the TOF and that it has an associated time measurement (kTIME and kTOFOUT) + bool mRequireITSRefit{false}; // require refit in ITS + bool mRequireTPCRefit{false}; // require refit in TPC + bool mRequireGoldenChi2{false}; // require golden chi2 cut (Run 2 only) // vector of ITS requirements (minNRequiredHits in specific requiredLayers) std::vector<std::pair<int8_t, std::set<uint8_t>>> mRequiredITSHits{}; diff --git a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h index e2e29ee95ab9d..5a242860ca34e 100644 --- a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h @@ -23,15 +23,13 @@ DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); // Columns to store track filter decisions DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, uint8_t); DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, uint8_t); -DECLARE_SOA_COLUMN(IsGlobalTrackwTOF, isGlobalTrackwTOF, uint8_t); } // namespace track DECLARE_SOA_TABLE(TracksExtended, "AOD", "TRACKEXTENDED", track::DcaXY, track::DcaZ); DECLARE_SOA_TABLE(TrackSelection, "AOD", "TRACKSELECTION", track::IsGlobalTrack, - track::IsGlobalTrackSDD, - track::IsGlobalTrackwTOF); + track::IsGlobalTrackSDD); } // namespace o2::aod #endif // O2_ANALYSIS_TRACKSELECTIONTABLES_H_ diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 291176a32d94c..60c951086e63b 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -84,7 +84,7 @@ struct TrackQATask { //OutputObj<HistFolder> tof{HistFolder("TOF"), OutputObjHandlingPolicy::QAObject}; //OutputObj<HistFolder> emcal{HistFolder("EMCAL"), OutputObjHandlingPolicy::QAObject}; - Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD, 3 = globalTrackswTOF"}; + Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; Filter trackFilter = aod::track::isGlobalTrack == (uint8_t)1; /* diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index b1faf009f8d2d..d557067d063af 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -31,10 +31,12 @@ using namespace o2::framework::expressions; TrackSelection getGlobalTrackSelection() { TrackSelection selectedTracks; + selectedTracks.SetTrackType(aod::track::Run2GlobalTrack); selectedTracks.SetPtRange(0.1f, 1e10f); selectedTracks.SetEtaRange(-0.8f, 0.8f); selectedTracks.SetRequireITSRefit(true); selectedTracks.SetRequireTPCRefit(true); + selectedTracks.SetRequireGoldenChi2(true); selectedTracks.SetMinNCrossedRowsTPC(70); selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); selectedTracks.SetMaxChi2PerClusterTPC(4.f); @@ -56,14 +58,6 @@ TrackSelection getGlobalTrackSelectionSDD() return selectedTracks; } -// Default track selection requiring a cluster matched in TOF -TrackSelection getGlobalTrackSelectionwTOF() -{ - TrackSelection selectedTracks = getGlobalTrackSelection(); - selectedTracks.SetRequireTOF(true); - return selectedTracks; -} - //**************************************************************************************** /** * Produce the more complicated derived track quantities needed for track selection. @@ -81,7 +75,7 @@ struct TrackExtensionTask { std::array<float, 2> dca{1e10f, 1e10f}; // FIXME: temporary solution to remove tracks that should not be there after conversion - if (track.trackType() == o2::aod::track::TrackTypeEnum::GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && track.x() < 150.f) { + if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && track.x() < 150.f) { float magField = 5.0; // in kG (FIXME: get this from CCDB) auto trackPar = getTrackPar(track); trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, magField, &dca); @@ -104,21 +98,18 @@ struct TrackSelectionTask { TrackSelection globalTracks; TrackSelection globalTracksSDD; - TrackSelection globalTrackswTOF; void init(InitContext&) { globalTracks = getGlobalTrackSelection(); globalTracksSDD = getGlobalTrackSelectionSDD(); - globalTrackswTOF = getGlobalTrackSelectionwTOF(); } void process(soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& track : tracks) { filterTable((uint8_t)globalTracks.IsSelected(track), - (uint8_t)globalTracksSDD.IsSelected(track), - (uint8_t)globalTrackswTOF.IsSelected(track)); + (uint8_t)globalTracksSDD.IsSelected(track)); } } }; diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 729e273243241..728e5b00e0482 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -153,7 +153,7 @@ DECLARE_SOA_EXPRESSION_COLUMN(C1Pt21Pt2, c1Pt21Pt2, float, aod::track::sigma1Pt* // TRACKEXTRA TABLE definition DECLARE_SOA_COLUMN(TPCInnerParam, tpcInnerParam, float); -DECLARE_SOA_COLUMN(Flags, flags, uint64_t); +DECLARE_SOA_COLUMN(Flags, flags, uint32_t); DECLARE_SOA_COLUMN(ITSClusterMap, itsClusterMap, uint8_t); DECLARE_SOA_COLUMN(TPCNClsFindable, tpcNClsFindable, uint8_t); DECLARE_SOA_COLUMN(TPCNClsFindableMinusFound, tpcNClsFindableMinusFound, int8_t); diff --git a/Framework/Core/include/Framework/DataTypes.h b/Framework/Core/include/Framework/DataTypes.h index 12abe74a7cce7..9ea0d1f9fb4c3 100644 --- a/Framework/Core/include/Framework/DataTypes.h +++ b/Framework/Core/include/Framework/DataTypes.h @@ -18,7 +18,13 @@ enum TrackTypeEnum : uint8_t { GlobalTrack = 0, ITSStandalone, MFTStandalone, - Run2Tracklet + Run2GlobalTrack = 254, + Run2Tracklet = 255 +}; +enum TrackFlagsRun2Enum { + ITSrefit = 0x1, + TPCrefit = 0x2, + GoldenChi2 = 0x4 }; } // namespace o2::aod::track From 1f4a06239bf7f89859a381312aa2750b56dfa094 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 29 Sep 2020 13:33:52 +0200 Subject: [PATCH 0800/1751] Extract common job utility functions Refactoring of some job scripts. Provide the taskwrapper as a reusable function across scripts. --- Utilities/Tools/CMakeLists.txt | 1 + Utilities/Tools/jobutils.sh | 152 +++++++++++++++++++++++++++++++++ Utilities/Tools/monitor-mem.sh | 3 +- prodtests/sim_challenge.sh | 105 +---------------------- 4 files changed, 158 insertions(+), 103 deletions(-) create mode 100644 Utilities/Tools/jobutils.sh diff --git a/Utilities/Tools/CMakeLists.txt b/Utilities/Tools/CMakeLists.txt index 3fbf468c4ad7c..f8459d0cf14ea 100644 --- a/Utilities/Tools/CMakeLists.txt +++ b/Utilities/Tools/CMakeLists.txt @@ -10,3 +10,4 @@ install(PROGRAMS monitor-mem.sh DESTINATION share/scripts/) +install(PROGRAMS jobutils.sh DESTINATION share/scripts/) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh new file mode 100644 index 0000000000000..aa123454bb7ee --- /dev/null +++ b/Utilities/Tools/jobutils.sh @@ -0,0 +1,152 @@ +# 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: Sandro Wenzel + +# This file contains a couple of utility functions for reuse +# in shell job scripts (such as on the GRID). +# In order to use these functions in scripts, this file needs to be +# simply sourced into the target script. + + +# Function to find out all the (recursive) child processes starting from a parent PID. +# The output includes includes the parent +# output is saved in child_pid_list +childprocs() { + local parent=$1 + if [ "$parent" ] ; then + child_pid_list="$child_pid_list $parent" + for childpid in $(pgrep -P ${parent}); do + childprocs $childpid "nottoplevel" + done; + fi + # return via a string list (only if toplevel) + if [ ! "$2" ]; then + echo "${child_pid_list}" + fi +} + +# Function wrapping some process and asyncronously supervises and controls it. +# Main features provided at the moment are: +# - optional recording of walltime and memory consumption (time evolution) +# - optional recording of CPU utilization +# - Some job control and error detection (in particular for DPL workflows). +# If exceptions are found, all participating processes will be sent a termination signal. +# The rational behind this function is to be able to determine failing +# conditions early and prevent longtime hanging executables +# (until DPL offers signal handling and automatic shutdown) +# - possibility to provide user hooks for "start" and "failure" +taskwrapper() { + local logfile=$1 + shift 1 + local command="$*" + + # launch the actual command in the background + echo "Launching task: ${command} &> $logfile &" + + # this gives some possibility to customize the wrapper + # and do some special task at the start. The hook takes 2 arguments: + # The original command and the logfile + if [ "${JOBUTILS_JOB_STARTHOOK}" ]; then + hook="${JOBUTILS_JOB_STARTHOOK} '$command' $logfile" + eval "${hook}" + fi + + # with or without memory monitoring ? + finalcommand="TIME=\"#walltime %e\" /usr/bin/time --output=${logfile}_time ${command}" + if [ "${JOBUTILS_MONITORMEM}" ]; then + finalcommand="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh /usr/bin/time --output=${logfile}_time '${command}'" + fi + eval ${finalcommand} &> $logfile & + + # THE NEXT PART IS THE SUPERVISION PART + # get the PID + PID=$! + + cpucounter=1 + + while [ 1 ]; do + # We don't like to see critical problems in the log file. + + # We need to grep on multitude of things: + # - all sorts of exceptions (may need to fine-tune) + # - segmentation violation + # - there was a crash + # - bus error (often occuring with shared mem) + pattern="-e \"xception\" \ + -e \"segmentation violation\" \ + -e \"error while setting up workflow\" \ + -e \"bus error\" \ + -e \"There was a crash.\"" + + grepcommand="grep -H ${pattern} $logfile >> encountered_exceptions_list 2>/dev/null" + eval ${grepcommand} + + grepcommand="grep -h --count ${pattern} $logfile 2>/dev/null" + # using eval here since otherwise the pattern is translated to a + # a weirdly quoted stringlist + RC=$(eval ${grepcommand}) + + # if we see an exception we will bring down the DPL workflow + # after having given it some chance to shut-down itself + # basically --> send kill to all children + if [ "$RC" != "" -a "$RC" != "0" ]; then + echo "Detected critical problem in logfile $logfile" + + # this gives some possibility to customize the wrapper + # and do some special task at the start. The hook takes 2 arguments: + # The original command and the logfile + if [ "${JOBUTILS_JOB_FAILUREHOOK}" ]; then + hook="${JOBUTILS_JOB_FAILUREHOOK} '$command' $logfile" + eval "${hook}" + fi + + sleep 2 + + # query processes still alive + for p in $(childprocs ${PID}); do + echo "killing child $p" + kill $p 2> /dev/null + done + + RC_ACUM=$((RC_ACUM+1)) + return 1 + fi + + # check if command returned which may bring us out of the loop + ps -p $PID > /dev/null + [ $? == 1 ] && break + + if [ "${JOBUTILS_MONITORCPU}" ]; then + # get some CPU usage statistics per process --> actual usage can be calculated thereafter + for p in $(childprocs ${PID}); do + total=`awk 'BEGIN{s=0}/cpu /{for (i=1;i<=NF;i++) s+=$i;} END {print s}' /proc/stat` + utime=`awk '//{print $14}' /proc/${p}/stat 2> /dev/null` + stime=`awk '//{print $15}' /proc/${p}/stat 2> /dev/null` + name=`awk '//{print $2}' /proc/${p}/stat 2> /dev/null` + echo "${cpucounter} ${p} ${total} ${utime} ${stime} ${name}" >> ${logfile}_cpuusage + done + let cpucounter=cpucounter+1 + fi + + # sleep for some time (can be customized for power user) + sleep ${JOBUTILS_WRAPPER_SLEEP:-5} + done + + # wait for PID and fetch return code + # ?? should directly exit here? + wait $PID + # return code + RC=$? + RC_ACUM=$((RC_ACUM+RC)) + [ ! "${RC} -eq 0" ] && echo "command ${command} had nonzero exit code ${RC}" + + return ${RC} +} diff --git a/Utilities/Tools/monitor-mem.sh b/Utilities/Tools/monitor-mem.sh index ff416d87e0686..d4acdfa80a89b 100755 --- a/Utilities/Tools/monitor-mem.sh +++ b/Utilities/Tools/monitor-mem.sh @@ -39,7 +39,8 @@ while [ 1 ] ; do ps -p $PID > /dev/null [ $? == 1 ] && echo "Job finished; Exiting " && break - sleep 0.005 + # take a measurement at some defined rate (can be customized) + sleep ${JOBUTILS_MONITORMEM_SLEEP:-0.005} done diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index e85908952a86e..2ab6d92993f2f 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -3,106 +3,9 @@ # chain of algorithms from MC and reco -# ----------- START WITH UTILITY FUNCTIONS ---------------------------- - -child_pid_list= -# finds out all the (recursive) child process starting from a parent -# output includes the parent -# output is saved in child_pid_list -childprocs() { - local parent=$1 - if [ "$parent" ] ; then - child_pid_list="$child_pid_list $parent" - for childpid in $(pgrep -P ${parent}); do - childprocs $childpid - done; - fi -} - -# accumulate return codes -RC_ACUM=0 - -taskwrapper() { - # A simple task wrapper launching a DPL workflow in the background - # and checking the output for exceptions. If exceptions are found, - # all participating processes will be sent a termination signal. - # The rational behind this function is to be able to determine failing - # conditions early and prevent longtime hanging executables - # (until DPL offers signal handling and automatic shutdown) - - local logfile=$1 - shift 1 - local command="$*" - - # launch the actual command in the background - echo "Launching task: ${command} &> $logfile &" - command="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh /usr/bin/time --output=${logfile}_time '${command}'" - eval ${command} &> $logfile & - - # THE NEXT PART IS THE SUPERVISION PART - # get the PID - PID=$! - - while [ 1 ]; do - # We don't like to see critical problems in the log file. - - # We need to grep on multitude of things: - # - all sorts of exceptions (may need to fine-tune) - # - segmentation violation - # - there was a crash - pattern="-e \"xception\" \ - -e \"segmentation violation\" \ - -e \"error while setting up workflow\" \ - -e \"bus error\" \ - -e \"There was a crash.\"" - - grepcommand="grep -H ${pattern} $logfile >> encountered_exceptions_list 2>/dev/null" - eval ${grepcommand} - - grepcommand="grep -h --count ${pattern} $logfile 2>/dev/null" - # using eval here since otherwise the pattern is translated to a - # a weirdly quoted stringlist - RC=$(eval ${grepcommand}) - - # if we see an exception we will bring down the DPL workflow - # after having given it some chance to shut-down itself - # basically --> send kill to all children - if [ "$RC" != "" -a "$RC" != "0" ]; then - echo "Detected critical problem in logfile $logfile" - sleep 2 - - # query processes still alive - child_pid_list= - childprocs ${PID} - for p in $child_pid_list; do - echo "killing child $p" - kill $p - done - - RC_ACUM=$((RC_ACUM+1)) - return 1 - fi - - # check if command returned which may bring us out of the loop - ps -p $PID > /dev/null - [ $? == 1 ] && break - - # sleep for some time - sleep 5 - done - - # wait for PID and fetch return code - # ?? should directly exit here? - wait $PID - # return code - RC=$? - RC_ACUM=$((RC_ACUM+RC)) - [ ! "${RC} -eq 0" ] && echo "command ${command} had nonzero exit code ${RC}" - - return ${RC} -} - -# ----------- START WITH ACTUAL SCRIPT ---------------------------- +# ------------ LOAD UTILITY FUNCTIONS ---------------------------- +. ${O2_ROOT}/share/scripts/jobutils.sh +# ----------- START WITH ACTUAL SCRIPT --------------------------- # default number of events @@ -242,5 +145,3 @@ if [ "$doreco" == "1" ]; then root -b -q -l $O2_ROOT/share/macro/checkTOFMatching.C 1>tofmatch_qa.log 2>&1 echo "Return status of TOF matching qa: $?" fi - -exit ${RC_ACUM} From 6b517d112d5d0d8e095bb2958a7f6c1f70f0e317 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 29 Sep 2020 16:41:24 +0200 Subject: [PATCH 0801/1751] DPL: avoid copying shared pointers while reading (#4462) --- Framework/Core/include/Framework/TableTreeHelpers.h | 2 +- Framework/Core/src/TableTreeHelpers.cxx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Framework/Core/include/Framework/TableTreeHelpers.h b/Framework/Core/include/Framework/TableTreeHelpers.h index 91adac34bae3a..9a9bcd9200255 100644 --- a/Framework/Core/include/Framework/TableTreeHelpers.h +++ b/Framework/Core/include/Framework/TableTreeHelpers.h @@ -212,7 +212,7 @@ class TreeToTable TTreeReader* mTreeReader; // a list of ColumnIterator* - std::vector<std::shared_ptr<ColumnIterator>> mColumnIterators; + std::vector<std::unique_ptr<ColumnIterator>> mColumnIterators; // Append next set of branch values to the // corresponding table columns diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index ea8699e490d3c..b7de8bf802aad 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -738,7 +738,7 @@ TreeToTable::~TreeToTable() bool TreeToTable::addColumn(const char* colname) { - auto colit = std::make_shared<ColumnIterator>(mTreeReader, colname); + auto colit = std::make_unique<ColumnIterator>(mTreeReader, colname); auto stat = colit->getStatus(); if (stat) { mColumnIterators.push_back(std::move(colit)); @@ -763,7 +763,7 @@ bool TreeToTable::addAllColumns() auto br = (TBranch*)branchList->At(ii); // IMPROVE: make sure that a column is not added more than one time - auto colit = std::make_shared<ColumnIterator>(mTreeReader, br->GetName()); + auto colit = std::make_unique<ColumnIterator>(mTreeReader, br->GetName()); if (colit->getStatus()) { mColumnIterators.push_back(std::move(colit)); } else { @@ -776,14 +776,14 @@ bool TreeToTable::addAllColumns() void TreeToTable::push() { - for (auto colit : mColumnIterators) { + for (auto&& colit : mColumnIterators) { colit->push(); } } void TreeToTable::reserve(size_t s) { - for (auto column : mColumnIterators) { + for (auto&& column : mColumnIterators) { column->reserve(s); } } @@ -805,7 +805,7 @@ std::shared_ptr<arrow::Table> TreeToTable::finalize() // prepare the elements needed to create the final table std::vector<std::shared_ptr<arrow::Array>> array_vector; std::vector<std::shared_ptr<arrow::Field>> schema_vector; - for (auto colit : mColumnIterators) { + for (auto&& colit : mColumnIterators) { colit->finish(); array_vector.push_back(colit->getArray()); schema_vector.push_back(colit->getSchema()); From b179a16d767ae038d6dcbe05db8f00a08a48fac1 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 29 Sep 2020 21:14:07 +0200 Subject: [PATCH 0802/1751] fix in per trigger yield calculation (#4463) --- Analysis/Core/src/CorrelationContainer.cxx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 8d7236f7f0efc..10e8f9443d098 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -748,14 +748,23 @@ TH2* CorrelationContainer::getPerTriggerYield(CorrelationContainer::CFStep step, multBinBegin = multAxis->FindBin(mCentralityMin + 1e-4); multBinEnd = multAxis->FindBin(mCentralityMax - 1e-4); LOGF(info, "Using multiplicity range %d --> %d", multBinBegin, multBinEnd); - } - if (mCentralityMin < mCentralityMax) { trackSameAll->GetAxis(3)->SetRange(multBinBegin, multBinEnd); } + TAxis* vertexAxis = trackSameAll->GetAxis(2); + int vertexBinBegin = 1; + int vertexBinEnd = vertexAxis->GetNbins(); + if (mZVtxMax > mZVtxMin) { + vertexBinBegin = vertexAxis->FindBin(mZVtxMin); + vertexBinEnd = vertexAxis->FindBin(mZVtxMax); + LOGF(info, "Using vertex range %d --> %d", vertexBinBegin, vertexBinEnd); + + trackSameAll->GetAxis(2)->SetRange(vertexBinBegin, vertexBinEnd); + } + TH2* yield = trackSameAll->Projection(1, 0, "E"); - Float_t triggers = eventSameAll->Integral(1, eventSameAll->GetXaxis()->GetNbins(), multBinBegin, multBinEnd); + Float_t triggers = eventSameAll->Integral(multBinBegin, multBinEnd, vertexBinBegin, vertexBinEnd); if (normalizePerTrigger) { LOGF(info, "Dividing %f tracks by %f triggers", yield->Integral(), triggers); From 73a1e9eda99b8e60312cbd1f1a5bec2d0510be3d Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Tue, 29 Sep 2020 16:14:20 -0300 Subject: [PATCH 0803/1751] Cascade finding now available (#4468) --- .../include/Analysis/StrangenessTables.h | 10 + Analysis/Tasks/PWGLF/CMakeLists.txt | 6 + Analysis/Tasks/PWGLF/cascadefinder.cxx | 397 ++++++++++++++++++ 3 files changed, 413 insertions(+) create mode 100644 Analysis/Tasks/PWGLF/cascadefinder.cxx diff --git a/Analysis/DataModel/include/Analysis/StrangenessTables.h b/Analysis/DataModel/include/Analysis/StrangenessTables.h index 77fb0b413f46d..c5983b6fbe335 100644 --- a/Analysis/DataModel/include/Analysis/StrangenessTables.h +++ b/Analysis/DataModel/include/Analysis/StrangenessTables.h @@ -42,6 +42,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, [](float x, float y) { return Rec //CosPA DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { return RecoDecay::CPA(array{pvX, pvY, pvZ}, array{X, Y, Z}, array{Px, Py, Pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(DCAV0ToPV, dcav0topv, [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { return TMath::Sqrt((TMath::Power((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + TMath::Power((pvX - X) * Pz - (pvZ - Z) * Px, 2) + TMath::Power((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); //Calculated on the fly with mass assumption + dynamic tables DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { return RecoDecay::M(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kPiPlus)}); }); @@ -70,6 +71,7 @@ DECLARE_SOA_TABLE(V0Data, "AOD", "V0DATA", v0data::Pt<v0data::PxPos, v0data::PyPos, v0data::PxNeg, v0data::PyNeg>, v0data::V0Radius<v0data::X, v0data::Y>, v0data::V0CosPA<v0data::X, v0data::Y, v0data::Z, v0dataext::Px, v0dataext::Py, v0dataext::Pz>, + v0data::DCAV0ToPV<v0data::X, v0data::Y, v0data::Z, v0dataext::Px, v0dataext::Py, v0dataext::Pz>, //Invariant masses v0data::MLambda<v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg>, @@ -196,6 +198,14 @@ DECLARE_SOA_EXTENDED_TABLE_USER(CascDataExt, CascDataOrigin, "CascDATAEXT", cascdataext::Px, cascdataext::Py, cascdataext::Pz); using CascDataFull = CascDataExt; + +namespace cascfinderdata +{ +DECLARE_SOA_INDEX_COLUMN_FULL(V0, v0, int, V0FinderData, "fV0ID"); +DECLARE_SOA_INDEX_COLUMN_FULL(BachTrack, bachTrack, int, FullTracks, "fBachTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +} // namespace cascfinderdata +DECLARE_SOA_TABLE(CascFinderData, "AOD", "CASCFINDERDATA", o2::soa::Index<>, cascfinderdata::V0Id, cascfinderdata::BachTrackId, cascfinderdata::CollisionId); } // namespace o2::aod #endif // O2_ANALYSIS_STRANGENESSTABLES_H_ diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt index 53a997febd482..7ac04b413f504 100644 --- a/Analysis/Tasks/PWGLF/CMakeLists.txt +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -53,7 +53,13 @@ o2_add_dpl_workflow(cascadeconsumer PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) +o2_add_dpl_workflow(cascadefinder + SOURCES cascadefinder + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(raacharged SOURCES raacharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) + diff --git a/Analysis/Tasks/PWGLF/cascadefinder.cxx b/Analysis/Tasks/PWGLF/cascadefinder.cxx new file mode 100644 index 0000000000000..00ea444406a00 --- /dev/null +++ b/Analysis/Tasks/PWGLF/cascadefinder.cxx @@ -0,0 +1,397 @@ +// 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. +// +// This task re-reconstructs the V0s and cascades + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Analysis/SecondaryVertexHF.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Analysis/RecoDecay.h" +#include "Analysis/trackUtilities.h" +#include "PID/PIDResponse.h" +#include "Analysis/StrangenessTables.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" + +#include <TFile.h> +#include <TLorentzVector.h> +#include <TH1F.h> +#include <TH2F.h> +#include <TProfile.h> +#include <Math/Vector4D.h> +#include <TPDGCode.h> +#include <TDatabasePDG.h> +#include <cmath> +#include <array> +#include <cstdlib> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using namespace ROOT::Math; + +namespace o2::aod +{ + +using V0FinderFull = soa::Join<aod::V0FinderData, aod::V0DataExt>; + +namespace cascgoodpostracks +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodPosTrack, goodPosTrack, int, FullTracks, "fGoodPosTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +} // namespace cascgoodpostracks +DECLARE_SOA_TABLE(CascGoodPosTracks, "AOD", "CASCGOODPTRACKS", o2::soa::Index<>, cascgoodpostracks::GoodPosTrackId, cascgoodpostracks::CollisionId, cascgoodpostracks::DCAXY); +namespace cascgoodnegtracks +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodNegTrack, goodNegTrack, int, FullTracks, "fGoodNegTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +} // namespace cascgoodnegtracks +DECLARE_SOA_TABLE(CascGoodNegTracks, "AOD", "CASCGOODNTRACKS", o2::soa::Index<>, cascgoodnegtracks::GoodNegTrackId, cascgoodnegtracks::CollisionId, cascgoodnegtracks::DCAXY); +namespace cascgoodlambdas +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodLambda, goodLambda, int, V0FinderFull, "fGoodLambdaId"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +} // namespace cascgoodlambdas +DECLARE_SOA_TABLE(CascGoodLambdas, "AOD", "CASCGOODLAM", o2::soa::Index<>, cascgoodlambdas::GoodLambdaId, cascgoodlambdas::CollisionId); +namespace cascgoodantilambdas +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodAntiLambda, goodAntiLambda, int, V0FinderFull, "fGoodAntiLambdaId"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +} // namespace cascgoodantilambdas +DECLARE_SOA_TABLE(CascGoodAntiLambdas, "AOD", "CASCGOODALAM", o2::soa::Index<>, cascgoodantilambdas::GoodAntiLambdaId, cascgoodantilambdas::CollisionId); +} // namespace o2::aod + +struct cascadeprefilter { + Configurable<float> dcabachtopv{"dcabachtopv", .1, "DCA Bach To PV"}; + Configurable<int> mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + Configurable<float> dcav0topv{"dcav0topv", .1, "DCA V0 To PV"}; + Configurable<double> cospaV0{"cospaV0", .98, "CosPA V0"}; + Configurable<float> lambdamasswindow{"lambdamasswindow", .006, "Distance from Lambda mass"}; + Configurable<float> dcav0dau{"dcav0dau", .6, "DCA V0 Daughters"}; + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + + Produces<aod::CascGoodLambdas> cascGoodLambdas; + Produces<aod::CascGoodAntiLambdas> cascGoodAntiLambdas; + Produces<aod::CascGoodPosTracks> cascGoodPosTracks; + Produces<aod::CascGoodNegTracks> cascGoodNegTracks; + + Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodPosTracks = aod::track::signed1Pt > 0.0f && aod::track::dcaXY > dcabachtopv; + Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodNegTracks = aod::track::signed1Pt < 0.0f && aod::track::dcaXY < -dcabachtopv; + + Partition<soa::Join<aod::V0FinderData, aod::V0DataExt>> goodV0s = aod::v0data::dcapostopv > dcapostopv&& aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + + void process(aod::Collision const& collision, + soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks, + soa::Join<aod::V0FinderData, aod::V0DataExt> const& V0s) + { + for (auto& t0 : goodPosTracks) { + if (!(t0.flags() & 0x40)) + continue; //TPC refit + if (t0.tpcNClsCrossedRows() < mincrossedrows) + continue; + cascGoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); + } + for (auto& t0 : goodNegTracks) { + if (!(t0.flags() & 0x40)) + continue; //TPC refit + if (t0.tpcNClsCrossedRows() < mincrossedrows) + continue; + cascGoodNegTracks(t0.globalIndex(), t0.collisionId(), -t0.dcaXY()); + } + for (auto& v0 : goodV0s) { + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cospaV0) + continue; + if (v0.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < dcav0topv) + continue; + + if (fabs(v0.mLambda() - 1.116) < lambdamasswindow) + cascGoodLambdas(v0.globalIndex(), v0.collisionId()); + if (fabs(v0.mAntiLambda() - 1.116) < lambdamasswindow) + cascGoodAntiLambdas(v0.globalIndex(), v0.collisionId()); + } + } +}; + +struct cascadefinder { + Produces<aod::CascData> cascdata; + Produces<aod::CascFinderData> cascfinderdata; + + OutputObj<TH1F> hCandPerEvent{TH1F("hCandPerEvent", "", 100, 0, 100)}; + + //Configurables + Configurable<double> d_bz{"d_bz", +5.0, "bz field"}; + Configurable<double> d_UseAbsDCA{"d_UseAbsDCA", kTRUE, "Use Abs DCAs"}; + + //Selection criteria + Configurable<double> v0cospa{"casccospa", 0.998, "Casc CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<float> dcav0dau{"dcacascdau", 1.0, "DCA Casc Daughters"}; + Configurable<float> v0radius{"cascradius", 1.0, "cascradius"}; + + //Process: subscribes to a lot of things! + void process(aod::Collision const& collision, + aod::FullTracks const& tracks, + soa::Join<aod::V0FinderData, aod::V0DataExt> const& V0s, + aod::CascGoodLambdas const& lambdas, + aod::CascGoodAntiLambdas const& antiLambdas, + aod::CascGoodPosTracks const& pBachtracks, + aod::CascGoodNegTracks const& nBachtracks) + { + //Define o2 fitter, 2-prong + o2::vertexing::DCAFitterN<2> fitterV0, fitterCasc; + fitterV0.setBz(d_bz); + fitterV0.setPropagateToPCA(true); + fitterV0.setMaxR(200.); + fitterV0.setMinParamChange(1e-3); + fitterV0.setMinRelChi2Change(0.9); + fitterV0.setMaxDZIni(1e9); + fitterV0.setMaxChi2(1e9); + fitterV0.setUseAbsDCA(d_UseAbsDCA); + + fitterCasc.setBz(d_bz); + fitterCasc.setPropagateToPCA(true); + fitterCasc.setMaxR(200.); + fitterCasc.setMinParamChange(1e-3); + fitterCasc.setMinRelChi2Change(0.9); + fitterCasc.setMaxDZIni(1e9); + fitterCasc.setMaxChi2(1e9); + fitterCasc.setUseAbsDCA(d_UseAbsDCA); + + Long_t lNCand = 0; + + std::array<float, 3> pVtx = {collision.posX(), collision.posY(), collision.posZ()}; + std::array<float, 3> pos = {0.}; + std::array<float, 3> posXi = {0.}; + std::array<float, 3> pvecpos = {0.}; + std::array<float, 3> pvecneg = {0.}; + std::array<float, 3> pvecbach = {0.}; + + //Cascades first + for (auto& v0id : lambdas) { + //required: de-reference the tracks for cascade building + auto v0 = v0id.goodLambda(); + auto pTrack = getTrackParCov(v0.posTrack()); + auto nTrack = getTrackParCov(v0.negTrack()); + //Let's do the slow part first: the V0 recalculation from scratch + int nCand = fitterV0.process(pTrack, nTrack); + if (nCand != 0) { + fitterV0.propagateTracksToVertex(); + const auto& v0vtx = fitterV0.getPCACandidate(); + for (int i = 0; i < 3; i++) + pos[i] = v0vtx[i]; + + std::array<float, 21> cov0 = {0}; + std::array<float, 21> cov1 = {0}; + std::array<float, 21> covV0 = {0}; + + //Covariance matrix calculation + const int momInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + fitterV0.getTrack(0).getPxPyPzGlo(pvecpos); + fitterV0.getTrack(1).getPxPyPzGlo(pvecneg); + fitterV0.getTrack(0).getCovXYZPxPyPzGlo(cov0); + fitterV0.getTrack(1).getCovXYZPxPyPzGlo(cov1); + for (int i = 0; i < 6; i++) { + int j = momInd[i]; + covV0[j] = cov0[j] + cov1[j]; + } + auto covVtxV0 = fitterV0.calcPCACovMatrix(); + covV0[0] = covVtxV0(0, 0); + covV0[1] = covVtxV0(1, 0); + covV0[2] = covVtxV0(1, 1); + covV0[3] = covVtxV0(2, 0); + covV0[4] = covVtxV0(2, 1); + covV0[5] = covVtxV0(2, 2); + + const std::array<float, 3> vertex = {(float)v0vtx[0], (float)v0vtx[1], (float)v0vtx[2]}; + const std::array<float, 3> momentum = {pvecpos[0] + pvecneg[0], pvecpos[1] + pvecneg[1], pvecpos[2] + pvecneg[2]}; + + auto tV0 = o2::track::TrackParCov(vertex, momentum, covV0, 0); + tV0.setQ2Pt(0); //No bending, please + + for (auto& t0id : nBachtracks) { + auto t0 = t0id.goodNegTrack(); + auto bTrack = getTrackParCov(t0); + + int nCand2 = fitterCasc.process(tV0, bTrack); + if (nCand2 != 0) { + fitterCasc.propagateTracksToVertex(); + const auto& cascvtx = fitterCasc.getPCACandidate(); + for (int i = 0; i < 3; i++) + posXi[i] = cascvtx[i]; + fitterCasc.getTrack(1).getPxPyPzGlo(pvecbach); + + lNCand++; + //If we got here, it means this is a good candidate! + cascfinderdata(v0.globalIndex(), t0.globalIndex(), t0.collisionId()); + cascdata(-1, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], + pvecpos[0], pvecpos[1], pvecpos[2], + pvecneg[0], pvecneg[1], pvecneg[2], + pvecbach[0], pvecbach[1], pvecbach[2], + fitterV0.getChi2AtPCACandidate(), fitterCasc.getChi2AtPCACandidate(), + v0.dcapostopv(), + v0.dcanegtopv(), + t0id.dcaXY()); + } //end if cascade recoed + } //end loop over bachelor + } //end if v0 recoed + } //end loop over cascades + + //Anticascades + for (auto& v0id : antiLambdas) { + //required: de-reference the tracks for cascade building + auto v0 = v0id.goodAntiLambda(); + auto pTrack = getTrackParCov(v0.posTrack()); + auto nTrack = getTrackParCov(v0.negTrack()); + //Let's do the slow part first: the V0 recalculation from scratch + int nCand = fitterV0.process(pTrack, nTrack); + if (nCand != 0) { + fitterV0.propagateTracksToVertex(); + const auto& v0vtx = fitterV0.getPCACandidate(); + for (int i = 0; i < 3; i++) + pos[i] = v0vtx[i]; + + std::array<float, 21> cov0 = {0}; + std::array<float, 21> cov1 = {0}; + std::array<float, 21> covV0 = {0}; + + //Covariance matrix calculation + const int momInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + fitterV0.getTrack(0).getPxPyPzGlo(pvecpos); + fitterV0.getTrack(1).getPxPyPzGlo(pvecneg); + fitterV0.getTrack(0).getCovXYZPxPyPzGlo(cov0); + fitterV0.getTrack(1).getCovXYZPxPyPzGlo(cov1); + for (int i = 0; i < 6; i++) { + int j = momInd[i]; + covV0[j] = cov0[j] + cov1[j]; + } + auto covVtxV0 = fitterV0.calcPCACovMatrix(); + covV0[0] = covVtxV0(0, 0); + covV0[1] = covVtxV0(1, 0); + covV0[2] = covVtxV0(1, 1); + covV0[3] = covVtxV0(2, 0); + covV0[4] = covVtxV0(2, 1); + covV0[5] = covVtxV0(2, 2); + + const std::array<float, 3> vertex = {(float)v0vtx[0], (float)v0vtx[1], (float)v0vtx[2]}; + const std::array<float, 3> momentum = {pvecpos[0] + pvecneg[0], pvecpos[1] + pvecneg[1], pvecpos[2] + pvecneg[2]}; + + auto tV0 = o2::track::TrackParCov(vertex, momentum, covV0, 0); + tV0.setQ2Pt(0); //No bending, please + + for (auto& t0id : pBachtracks) { + auto t0 = t0id.goodPosTrack(); + auto bTrack = getTrackParCov(t0); + + int nCand2 = fitterCasc.process(tV0, bTrack); + if (nCand2 != 0) { + fitterCasc.propagateTracksToVertex(); + const auto& cascvtx = fitterCasc.getPCACandidate(); + for (int i = 0; i < 3; i++) + posXi[i] = cascvtx[i]; + fitterCasc.getTrack(1).getPxPyPzGlo(pvecbach); + + lNCand++; + //If we got here, it means this is a good candidate! + cascfinderdata(v0.globalIndex(), t0.globalIndex(), t0.collisionId()); + cascdata(+1, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], + pvecpos[0], pvecpos[1], pvecpos[2], + pvecneg[0], pvecneg[1], pvecneg[2], + pvecbach[0], pvecbach[1], pvecbach[2], + fitterV0.getChi2AtPCACandidate(), fitterCasc.getChi2AtPCACandidate(), + v0.dcapostopv(), + v0.dcanegtopv(), + t0id.dcaXY()); + } //end if cascade recoed + } //end loop over bachelor + } //end if v0 recoed + } //end loop over anticascades + + hCandPerEvent->Fill(lNCand); + } +}; + +struct cascadefinderQA { + //Basic checks + OutputObj<TH3F> h3dMassXiMinus{TH3F("h3dMassXiMinus", "", 20, 0, 100, 200, 0, 10, 200, 1.322 - 0.100, 1.322 + 0.100)}; + OutputObj<TH3F> h3dMassXiPlus{TH3F("h3dMassXiPlus", "", 20, 0, 100, 200, 0, 10, 200, 1.322 - 0.100, 1.322 + 0.100)}; + OutputObj<TH3F> h3dMassOmegaMinus{TH3F("h3dMassOmegaMinus", "", 20, 0, 100, 200, 0, 10, 200, 1.672 - 0.100, 1.672 + 0.100)}; + OutputObj<TH3F> h3dMassOmegaPlus{TH3F("h3dMassOmegaPlus", "", 20, 0, 100, 200, 0, 10, 200, 1.672 - 0.100, 1.672 + 0.100)}; + + //Selection criteria + Configurable<double> v0cospa{"v0cospa", 0.999, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<double> casccospa{"casccospa", 0.999, "Casc CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<float> dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + Configurable<float> dcacascdau{"dcacascdau", .3, "DCA Casc Daughters"}; + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<float> dcabachtopv{"dcabachtopv", .1, "DCA Bach To PV"}; + Configurable<float> dcav0topv{"dcav0topv", .1, "DCA V0 To PV"}; + Configurable<float> v0radius{"v0radius", 2.0, "v0radius"}; + Configurable<float> cascradius{"cascradius", 1.0, "cascradius"}; + Configurable<float> v0masswindow{"v0masswindow", 0.008, "v0masswindow"}; + + Filter preFilterV0 = + aod::cascdata::dcapostopv > dcapostopv&& aod::cascdata::dcanegtopv > dcanegtopv&& + aod::cascdata::dcabachtopv > dcabachtopv&& + aod::cascdata::dcaV0daughters < dcav0dau&& aod::cascdata::dcacascdaughters < dcacascdau; + + ///Connect to CascFinderData: newly indexed, note: CascDataExt table incompatible with standard V0 table! + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::CascFinderData, aod::CascDataExt>> const& Cascades) + { + if (!collision.alias()[kINT7]) + return; + if (!collision.sel7()) + return; + for (auto& casc : Cascades) { + //FIXME: dynamic columns cannot be filtered on? + if (casc.v0radius() > v0radius && + casc.cascradius() > cascradius && + casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && + casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospa && + casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) { + if (casc.charge() < 0) { //FIXME: could be done better... + if (TMath::Abs(casc.yXi()) < 0.5) + h3dMassXiMinus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); + if (TMath::Abs(casc.yOmega()) < 0.5) + h3dMassOmegaMinus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } else { + if (TMath::Abs(casc.yXi()) < 0.5) + h3dMassXiPlus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); + if (TMath::Abs(casc.yOmega()) < 0.5) + h3dMassOmegaPlus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } + } + } + } +}; + +/// Extends the v0data table with expression columns +struct cascadeinitializer { + Spawns<aod::CascDataExt> cascdataext; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<cascadeprefilter>("lf-cascadeprefilter"), + adaptAnalysisTask<cascadefinder>("lf-cascadefinder"), + adaptAnalysisTask<cascadeinitializer>("lf-cascadeinitializer"), + adaptAnalysisTask<cascadefinderQA>("lf-cascadefinderQA")}; +} From fd9d1de958cb72f761548af47a3621255b58f87d Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 30 Sep 2020 07:27:00 +0200 Subject: [PATCH 0804/1751] DPL Analysis: test for array and boolean column slicing (#4464) --- Framework/Core/test/test_GroupSlicer.cxx | 74 ++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/Framework/Core/test/test_GroupSlicer.cxx b/Framework/Core/test/test_GroupSlicer.cxx index 0c3dfcb7711c7..db7fe5933c0c9 100644 --- a/Framework/Core/test/test_GroupSlicer.cxx +++ b/Framework/Core/test/test_GroupSlicer.cxx @@ -23,12 +23,14 @@ namespace o2::aod { namespace test { +DECLARE_SOA_COLUMN(ID, id, int); DECLARE_SOA_COLUMN(Foo, foo, float); DECLARE_SOA_COLUMN(Bar, bar, float); DECLARE_SOA_COLUMN(EventProperty, eventProperty, float); } // namespace test DECLARE_SOA_TABLE(Events, "AOD", "EVTS", o2::soa::Index<>, + test::ID, test::EventProperty, test::Foo, test::Bar); @@ -56,13 +58,22 @@ DECLARE_SOA_TABLE(TrksU, "AOD", "TRKSU", test::X, test::Y, test::Z); + +namespace test +{ +DECLARE_SOA_COLUMN(Arr, arr, float[3]); +DECLARE_SOA_COLUMN(Boo, boo, bool); +} // namespace test + +DECLARE_SOA_TABLE(EventExtra, "AOD", "EVTSXTRA", test::Arr, test::Boo); + } // namespace o2::aod BOOST_AUTO_TEST_CASE(GroupSlicerOneAssociated) { TableBuilder builderE; auto evtsWriter = builderE.cursor<aod::Events>(); for (auto i = 0; i < 20; ++i) { - evtsWriter(0, 0.5f * i, 2.f * i, 3.f * i); + evtsWriter(0, i, 0.5f * i, 2.f * i, 3.f * i); } auto evtTable = builderE.finalize(); @@ -101,7 +112,7 @@ BOOST_AUTO_TEST_CASE(GroupSlicerSeveralAssociated) TableBuilder builderE; auto evtsWriter = builderE.cursor<aod::Events>(); for (auto i = 0; i < 20; ++i) { - evtsWriter(0, 0.5f * i, 2.f * i, 3.f * i); + evtsWriter(0, i, 0.5f * i, 2.f * i, 3.f * i); } auto evtTable = builderE.finalize(); @@ -189,7 +200,7 @@ BOOST_AUTO_TEST_CASE(GroupSlicerMismatchedGroups) TableBuilder builderE; auto evtsWriter = builderE.cursor<aod::Events>(); for (auto i = 0; i < 20; ++i) { - evtsWriter(0, 0.5f * i, 2.f * i, 3.f * i); + evtsWriter(0, i, 0.5f * i, 2.f * i, 3.f * i); } auto evtTable = builderE.finalize(); @@ -235,7 +246,7 @@ BOOST_AUTO_TEST_CASE(GroupSlicerMismatchedFilteredGroups) TableBuilder builderE; auto evtsWriter = builderE.cursor<aod::Events>(); for (auto i = 0; i < 20; ++i) { - evtsWriter(0, 0.5f * i, 2.f * i, 3.f * i); + evtsWriter(0, i, 0.5f * i, 2.f * i, 3.f * i); } auto evtTable = builderE.finalize(); @@ -278,3 +289,58 @@ BOOST_AUTO_TEST_CASE(GroupSlicerMismatchedFilteredGroups) ++count; } } + +BOOST_AUTO_TEST_CASE(ArrowDirectSlicing) +{ + int counts[] = {5, 5, 5, 4, 1}; + int offsets[] = {0, 5, 10, 15, 19, 20}; + int ids[] = {0, 1, 2, 3, 4}; + + using BigE = soa::Join<aod::Events, aod::EventExtra>; + + TableBuilder builderE; + auto evtsWriter = builderE.cursor<aod::Events>(); + auto step = 0; + for (auto i = 0; i < 20; ++i) { + if (i >= offsets[step + 1]) + ++step; + evtsWriter(0, ids[step], 0.5f * i, 2.f * i, 3.f * i); + } + auto evtTable = builderE.finalize(); + + TableBuilder builderEE; + auto evtsEWriter = builderEE.cursor<aod::EventExtra>(); + for (auto i = 0; i < 20; ++i) { + float arr[3] = {0.1f * i, 0.2f * i, 0.3f * i}; + evtsEWriter(0, arr, i % 2 == 0); + } + auto evtETable = builderEE.finalize(); + + aod::Events e{evtTable}; + aod::EventExtra ee{evtETable}; + BigE b_e{{evtTable, evtETable}}; + + std::vector<std::shared_ptr<arrow::ChunkedArray>> slices_array; + std::vector<std::shared_ptr<arrow::ChunkedArray>> slices_bool; + auto offset = 0; + for (auto i = 0u; i < 5; ++i) { + slices_array.emplace_back(evtETable->column(0)->Slice(offset, counts[i])); + slices_bool.emplace_back(evtETable->column(1)->Slice(offset, counts[i])); + offset += counts[i]; + BOOST_REQUIRE_EQUAL(slices_array[i]->length(), counts[i]); + BOOST_REQUIRE_EQUAL(slices_bool[i]->length(), counts[i]); + } + + std::vector<arrow::Datum> slices; + std::vector<uint64_t> offsts; + auto status = sliceByColumn("fID", b_e.asArrowTable(), 20, &slices, &offsts); + for (auto i = 0u; i < 5; ++i) { + auto tbl = arrow::util::get<std::shared_ptr<arrow::Table>>(slices[i].value); + auto ca = tbl->GetColumnByName("fArr"); + auto cb = tbl->GetColumnByName("fBoo"); + BOOST_REQUIRE_EQUAL(ca->length(), counts[i]); + BOOST_REQUIRE_EQUAL(cb->length(), counts[i]); + BOOST_CHECK(ca->Equals(slices_array[i])); + BOOST_CHECK(cb->Equals(slices_bool[i])); + } +} From 6284f7af079adf59112891834a2716aea448db62 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 30 Sep 2020 08:37:53 +0200 Subject: [PATCH 0805/1751] TrackSelection: move back to boolean columns (#4470) --- .../include/Analysis/TrackSelectionTables.h | 4 +- Analysis/Tasks/PWGCF/correlations.cxx | 2 +- Analysis/Tasks/PWGLF/mcspectraefficiency.cxx | 4 +- Analysis/Tasks/PWGLF/spectraTPC.cxx | 6 +-- Analysis/Tasks/trackqa.cxx | 51 +++++++++---------- Analysis/Tasks/trackselection.cxx | 4 +- 6 files changed, 34 insertions(+), 37 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h index 5a242860ca34e..7b9e95162fa10 100644 --- a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h @@ -21,8 +21,8 @@ DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); // Columns to store track filter decisions -DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, uint8_t); -DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, uint8_t); +DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, bool); +DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, bool); } // namespace track DECLARE_SOA_TABLE(TracksExtended, "AOD", "TRACKEXTENDED", track::DcaXY, diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index 2e0401bb92763..1e6cae9672d54 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -51,7 +51,7 @@ struct CorrelationTask { // 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) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); using myTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection>>; // Output definitions diff --git a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx index ab613d09bf884..20636b4160630 100644 --- a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx +++ b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx @@ -102,8 +102,8 @@ struct ReconstructedTask { OutputObj<TH2F> ptDiff{TH2F("ptDiff", "ptDiff;#it{p}_{T}_{MC} #it{p}_{T}_{Rec} (GeV/#it{c})", 500, -2, 2, PDGBINNING)}; OutputObj<TH2F> pDiff{TH2F("pDiff", "pDiff;#it{p}_{MC} #it{p}_{Rec} (GeV/#it{c})", 500, -2, 2, PDGBINNING)}; - Filter trackAcceptance = (nabs(aod::track::eta) < (float)(0.8f)); - Filter trackCuts = ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + Filter trackAcceptance = (nabs(aod::track::eta) < 0.8f); + Filter trackCuts = ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::McTrackLabels, aod::TrackSelection>> const& tracks, diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index 0a7a746155b05..bbdc39ff8afe4 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -91,7 +91,7 @@ struct TPCPIDQAExpSignalTask { // Filters Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>> const& tracks) { for (auto const& i : tracks) { @@ -147,7 +147,7 @@ struct TPCPIDQANSigmaTask { // Filters Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>> const& tracks) { @@ -200,7 +200,7 @@ struct TPCPIDQASignalwTOFTask { // Filters Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == (uint8_t)1) || (aod::track::isGlobalTrackSDD == (uint8_t)1)); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>> const& tracks) { diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 60c951086e63b..aa42b05b95424 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -19,7 +19,6 @@ #include <cmath> -#include "Analysis/TrackSelection.h" #include "Analysis/TrackSelectionTables.h" using namespace o2; @@ -42,13 +41,12 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) //**************************************************************************************** struct TrackQATask { - // unique identifiers for each variable - enum Quantities : uint8_t { - // kine - pt = 0, + enum HistosKine : uint8_t { + pt, eta, phi, - // track + }; + enum HistosTrackPar : uint8_t { x, y, z, @@ -59,11 +57,13 @@ struct TrackQATask { dcaXY, dcaZ, flags, - // its + }; + enum HistosITS : uint8_t { itsNCls, itsChi2NCl, itsHits, - // tpc + }; + enum HistosTPC : uint8_t { tpcNClsFindable, tpcNClsFound, tpcNClsShared, @@ -71,9 +71,6 @@ struct TrackQATask { tpcCrossedRowsOverFindableCls, tpcFractionSharedCls, tpcChi2NCl, - // trd - // tof - // emcal }; OutputObj<HistFolder> kine{HistFolder("Kine"), OutputObjHandlingPolicy::QAObject}; @@ -86,7 +83,7 @@ struct TrackQATask { Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; - Filter trackFilter = aod::track::isGlobalTrack == (uint8_t)1; + Filter trackFilter = aod::track::isGlobalTrack == true; /* //Function float castFLOAT4(uint8) not supported yet Filter trackFilter = ((0 * aod::track::isGlobalTrack == (float)selectedTracks) || @@ -98,21 +95,21 @@ struct TrackQATask { void init(o2::framework::InitContext&) { // kine histograms - kine->Add(pt, new TH1D("pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.)); - kine->Add(eta, new TH1D("eta", "#eta;#eta", 101, -1.0, 1.0)); - kine->Add(phi, new TH1D("phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI)); + kine->Add(pt, new TH1D("pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", 200, 0., 5.)); + kine->Add(eta, new TH1D("eta", "#eta;#eta", 180, -0.9, 0.9)); + kine->Add(phi, new TH1D("phi", "#phi;#phi [rad]", 180, 0., 2 * M_PI)); // track histograms - trackpar->Add(x, new TH1D("x", "track x position at dca in local coordinate system;x [cm]", 200, -0.4, 0.4)); - trackpar->Add(y, new TH1D("y", "track y position at dca in local coordinate system;y [cm]", 100, -4., 4.)); - trackpar->Add(z, new TH1D("z", "track z position at dca in local coordinate system;z [cm]", 100, -20., 20.)); - trackpar->Add(alpha, new TH1D("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 100, -(M_PI + 0.01), (M_PI + 0.01))); - trackpar->Add(signed1Pt, new TH1D("signed1Pt", "track signed 1/p_{T};q/p_{T}", 200, -8, 8)); - trackpar->Add(snp, new TH1D("snp", "sinus of track momentum azimuthal angle;snp", 100, -1., 1.)); - trackpar->Add(tgl, new TH1D("tgl", "tangent of the track momentum dip angle;tgl;", 1000, -2, 2)); + trackpar->Add(x, new TH1D("x", "track #it{x} position at dca in local coordinate system;#it{x} [cm]", 200, -0.36, 0.36)); + trackpar->Add(y, new TH1D("y", "track #it{y} position at dca in local coordinate system;#it{y} [cm]", 200, -0.5, 0.5)); + trackpar->Add(z, new TH1D("z", "track #it{z} position at dca in local coordinate system;#it{z} [cm]", 200, -11., 11.)); + trackpar->Add(alpha, new TH1D("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 36, -M_PI, M_PI)); + trackpar->Add(signed1Pt, new TH1D("signed1Pt", "track signed 1/#it{p}_{T};#it{q}/#it{p}_{T}", 200, -8, 8)); + trackpar->Add(snp, new TH1D("snp", "sinus of track momentum azimuthal angle;snp", 11, -0.1, 0.1)); + trackpar->Add(tgl, new TH1D("tgl", "tangent of the track momentum dip angle;tgl;", 200, -1., 1.)); trackpar->Add(flags, new TH1D("flags", "track flag;flag bit", 64, -0.5, 63.5)); - trackpar->Add(dcaXY, new TH1D("dcaXY", "distance of closest approach in xy plane;dca-xy [cm];", 200, -3., 3.)); - trackpar->Add(dcaZ, new TH1D("dcaZ", "distance of closest approach in z;dca-z [cm];", 200, -3., 3.)); + trackpar->Add(dcaXY, new TH1D("dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", 200, -0.15, 0.15)); + trackpar->Add(dcaZ, new TH1D("dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", 200, -0.15, 0.15)); // its histograms its->Add(itsNCls, new TH1D("itsNCls", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5)); @@ -120,12 +117,12 @@ struct TrackQATask { its->Add(itsHits, new TH1D("itsHits", "hitmap ITS;layer ITS", 7, -0.5, 6.5)); // tpc histograms - tpc->Add(tpcNClsFindable, new TH1D("tpcNClsFindable", "number of findable TPC clusters;# clusters TPC", 165, -0.5, 164.5)); + tpc->Add(tpcNClsFindable, new TH1D("tpcNClsFindable", "number of findable TPC clusters;# findable clusters TPC", 165, -0.5, 164.5)); tpc->Add(tpcNClsFound, new TH1D("tpcNClsFound", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5)); - tpc->Add(tpcNClsShared, new TH1D("tpcNClsShared", "number of shared TPC clusters;;# shared clusters TPC", 165, -0.5, 164.5)); + tpc->Add(tpcNClsShared, new TH1D("tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", 165, -0.5, 164.5)); tpc->Add(tpcNClsCrossedRows, new TH1D("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5)); tpc->Add(tpcFractionSharedCls, new TH1D("tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.)); - tpc->Add(tpcCrossedRowsOverFindableCls, new TH1D("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 110, 0.0, 1.1)); + tpc->Add(tpcCrossedRowsOverFindableCls, new TH1D("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 120, 0.0, 1.2)); tpc->Add(tpcChi2NCl, new TH1D("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10)); } diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index d557067d063af..66ff376b334eb 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -108,8 +108,8 @@ struct TrackSelectionTask { void process(soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& track : tracks) { - filterTable((uint8_t)globalTracks.IsSelected(track), - (uint8_t)globalTracksSDD.IsSelected(track)); + filterTable(globalTracks.IsSelected(track), + globalTracksSDD.IsSelected(track)); } } }; From 3eb20247f3f86487c4a11f669cdcad9efb47e2a1 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 30 Sep 2020 11:05:13 +0200 Subject: [PATCH 0806/1751] Add primary vertexing to sim_challenge --- prodtests/sim_challenge.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 2ab6d92993f2f..9365a66abacb5 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -113,7 +113,7 @@ if [ "$doreco" == "1" ]; then echo "Return status of tpcreco: $?" echo "Running ITS reco flow" - taskwrapper itsreco.log o2-its-reco-workflow $gloOpt + taskwrapper itsreco.log o2-its-reco-workflow --trackerCA --async-phase $gloOpt echo "Return status of itsreco: $?" # existing checks @@ -140,6 +140,11 @@ if [ "$doreco" == "1" ]; then taskwrapper tofMatch.log o2-tof-reco-workflow $gloOpt echo "Return status of its-tpc-tof match: $?" + echo "Running primary vertex finding flow" + #needs results of TPC-ITS matching and FIT workflows + taskwrapper pvfinder.log o2-primary-vertexing-workflow $gloOpt + echo "Return status of primary vertexing: $?" + echo "Running TOF matching QA" #need results of ITSTPC-TOF matching (+ TOF clusters and ITS-TPC tracks) root -b -q -l $O2_ROOT/share/macro/checkTOFMatching.C 1>tofmatch_qa.log 2>&1 From dbdc0198fdcc268969ecc5feeb729ffb20740eef Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 30 Sep 2020 10:32:32 +0200 Subject: [PATCH 0807/1751] GPU: Manually add some header dependencies to ensure corect creation of rootmap --- GPU/GPUTracking/Base/GPUSettingsList.h | 2 ++ GPU/GPUTracking/CMakeLists.txt | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index e64746adcbbae..bd5820e0f9cca 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -26,6 +26,7 @@ #ifdef QCONFIG_INSTANCE using namespace GPUCA_NAMESPACE::gpu; #endif +#ifdef BeginNamespace // File should not be included without defining the macros, but rootcling will do for dictionary generation BeginNamespace(GPUCA_NAMESPACE) BeginNamespace(gpu) @@ -271,4 +272,5 @@ EndConfig() EndNamespace() // gpu EndNamespace() // GPUCA_NAMESPACE +#endif // clang-format on diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 9d4cb8125c237..bde21257e06a0 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -137,6 +137,7 @@ set(HDRS_INSTALL if(ALIGPU_BUILD_TYPE STREQUAL "O2") set(SRCS ${SRCS} Interface/GPUO2Interface.cxx Interface/GPUO2InterfaceConfigurableParam.cxx) set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h Interface/GPUO2InterfaceConfigurableParam.h dEdx/TPCdEdxCalibrationSplines.h) + set(HDRS_CINT_O2_ADDITIONAL Base/GPUSettings.h Base/GPUSettingsList.h) # Manual depencies for ROOT dictionary generation endif() # Sources for O2 and for Standalone if requested in config file @@ -279,7 +280,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") PRIVATE $<TARGET_PROPERTY:O2::Framework,INTERFACE_INCLUDE_DIRECTORIES>) o2_target_root_dictionary(${MODULE} - HEADERS ${HDRS_CINT_O2} + HEADERS ${HDRS_CINT_O2} ${HDRS_CINT_O2_ADDITIONAL} LINKDEF GPUTrackingLinkDef_O2.h) target_compile_definitions(${targetName} PRIVATE GPUCA_O2_LIB From 89ef69691826f3467938ae13fadc400510f3759c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 30 Sep 2020 19:45:30 +0200 Subject: [PATCH 0808/1751] DPL Analysis: fix leak in TreeToTable (#4475) --- .../Core/include/Framework/TableTreeHelpers.h | 2 +- Framework/Core/src/DataAllocator.cxx | 4 +-- Framework/Core/src/TableTreeHelpers.cxx | 30 ++++++++++++++----- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Framework/Core/include/Framework/TableTreeHelpers.h b/Framework/Core/include/Framework/TableTreeHelpers.h index 9a9bcd9200255..c58484631f914 100644 --- a/Framework/Core/include/Framework/TableTreeHelpers.h +++ b/Framework/Core/include/Framework/TableTreeHelpers.h @@ -160,7 +160,7 @@ class ColumnIterator TTreeReaderArray<double>* mReaderArray_d = nullptr; // all the possible arrow::TBuilder types - std::shared_ptr<arrow::FixedSizeListBuilder> mTableBuilder_list; + arrow::FixedSizeListBuilder* mTableBuilder_list = nullptr; arrow::BooleanBuilder* mTableBuilder_o = nullptr; arrow::UInt8Builder* mTableBuilder_ub = nullptr; diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index d39ccd2ceeeb9..58c821a4290b5 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -181,8 +181,7 @@ void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) /// To finalise this we write the table to the buffer. /// FIXME: most likely not a great idea. We should probably write to the buffer /// directly in the TableBuilder, incrementally. - std::shared_ptr<TreeToTable> p(t2t); - auto finalizer = [payload = p](std::shared_ptr<FairMQResizableBuffer> b) -> void { + auto finalizer = [payload = t2t](std::shared_ptr<FairMQResizableBuffer> b) -> void { auto table = payload->finalize(); auto stream = std::make_shared<arrow::io::BufferOutputStream>(b); @@ -192,6 +191,7 @@ void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) if (outStatus.ok() == false) { throw std::runtime_error("Unable to Write table"); } + delete payload; }; context.addBuffer(std::move(header), buffer, std::move(finalizer), channel); diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index b7de8bf802aad..6e1857b32d817 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -341,13 +341,13 @@ TTree* TableToTree::process() } // ----------------------------------------------------------------------------- -#define MAKE_LIST_BUILDER(ElementType, NumElements) \ - std::unique_ptr<arrow::ArrayBuilder> ValueBuilder; \ - arrow::MemoryPool* MemoryPool = arrow::default_memory_pool(); \ - auto stat = MakeBuilder(MemoryPool, ElementType, &ValueBuilder); \ - mTableBuilder_list = std::make_shared<arrow::FixedSizeListBuilder>( \ - MemoryPool, \ - std::move(ValueBuilder), \ +#define MAKE_LIST_BUILDER(ElementType, NumElements) \ + std::unique_ptr<arrow::ArrayBuilder> ValueBuilder; \ + arrow::MemoryPool* MemoryPool = arrow::default_memory_pool(); \ + auto stat = MakeBuilder(MemoryPool, ElementType, &ValueBuilder); \ + mTableBuilder_list = new arrow::FixedSizeListBuilder( \ + MemoryPool, \ + std::move(ValueBuilder), \ NumElements); #define MAKE_FIELD(ElementType, NumElements) \ @@ -538,6 +538,22 @@ ColumnIterator::~ColumnIterator() delete mReaderArray_l; delete mReaderArray_f; delete mReaderArray_d; + + if (mTableBuilder_list) { + delete mTableBuilder_list; + } else { + delete mTableBuilder_o; + delete mTableBuilder_ub; + delete mTableBuilder_us; + delete mTableBuilder_ui; + delete mTableBuilder_ul; + delete mTableBuilder_b; + delete mTableBuilder_s; + delete mTableBuilder_i; + delete mTableBuilder_l; + delete mTableBuilder_f; + delete mTableBuilder_d; + } }; bool ColumnIterator::getStatus() From 77182fbbc19940dc8e446b4247735e8ad2527752 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 30 Sep 2020 13:38:56 +0200 Subject: [PATCH 0809/1751] Clear CMake list of non-tested macros when rerunning --- CMakeLists.txt | 2 +- cmake/O2ReportNonTestedMacros.cmake | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 891b0567293fe..fead88a8a1126 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,7 @@ include(O2AddHeaderOnlyLibrary) include(O2AddLibrary) include(O2AddTest) include(O2AddTestRootMacro) +include(O2ReportNonTestedMacros) include(O2TargetRootDictionary) include(O2DataFile) include(O2TargetManPage) @@ -108,7 +109,6 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif() if(BUILD_TEST_ROOT_MACROS) add_subdirectory(macro) - include(O2ReportNonTestedMacros) o2_report_non_tested_macros() endif() add_subdirectory(packaging) diff --git a/cmake/O2ReportNonTestedMacros.cmake b/cmake/O2ReportNonTestedMacros.cmake index 6a204039bff38..4a2b80d398682 100644 --- a/cmake/O2ReportNonTestedMacros.cmake +++ b/cmake/O2ReportNonTestedMacros.cmake @@ -10,9 +10,11 @@ include_guard() -include(O2RootMacroExclusionList) include(O2GetListOfMacros) +set(LIST_OF_ROOT_MACRO_TESTS "" CACHE INTERNAL "List of macros to test for loading") +set(LIST_OF_ROOT_MACRO_TESTS_COMPILED "" CACHE INTERNAL "List of macros to test for compilation") + # # Loop over the Root macros that exists in the repository and check whether # there is one (or two) test for that macro (i.e. the o2_add_test_root_macro @@ -24,6 +26,7 @@ include(O2GetListOfMacros) # simply reported). # function(o2_report_non_tested_macros) + include(O2RootMacroExclusionList) cmake_parse_arguments(PARSE_ARGV 0 From 944643b3e97a38c1e773143bdfd38fc03a2f77a5 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Thu, 1 Oct 2020 09:38:41 +0200 Subject: [PATCH 0810/1751] HistHelpers: make histID template argument (#4478) --- Analysis/Core/include/Analysis/HistHelpers.h | 32 ++-- Analysis/Tasks/trackqa.cxx | 92 +++++------ Analysis/Tutorials/src/histHelpersTest.cxx | 155 ++++++++++--------- 3 files changed, 140 insertions(+), 139 deletions(-) diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/Analysis/HistHelpers.h index 133578d500bb0..6684b93f78390 100644 --- a/Analysis/Core/include/Analysis/HistHelpers.h +++ b/Analysis/Core/include/Analysis/HistHelpers.h @@ -31,11 +31,7 @@ #include "Framework/Logger.h" -namespace o2 -{ -namespace experimental -{ -namespace histhelpers +namespace o2::experimental::histhelpers { template <typename T> @@ -62,18 +58,16 @@ class HistContainer : private RootContainer } HistContainer(const HistContainer& other) { - // pseudo copy ctor to move around empty collection on construction (no real copy constructor!) - // this is needed to be able to put this in OutputObj - // Memo: default copy ctor does not work for TList based collections since - // their copy constructor is implicitly deleted as opposed to TObjArrays + // pseudo copy ctor to move around empty collection on construction (e.g. when put in OutputObj) + // this is needed to make HistContainer also work with TLists since these dont have a copy constructor (as opposed to TObjArrays) RootContainer::SetOwner(false); RootContainer::SetName(other.GetName()); } using HistType = std::variant<std::shared_ptr<THn>, std::shared_ptr<THnSparse>, std::shared_ptr<TH3>, std::shared_ptr<TH2>, std::shared_ptr<TH1>, std::shared_ptr<TProfile3D>, std::shared_ptr<TProfile2D>, std::shared_ptr<TProfile>>; - template <typename T> - void Add(uint8_t histID, T&& hist) + template <uint8_t histID, typename T> + void Add(T&& hist) { if (mHistos.find(histID) != mHistos.end()) { LOGF(WARNING, "HistContainer %s already holds a histogram at histID = %d. Overriding it now...", RootContainer::GetName(), histID); @@ -111,15 +105,15 @@ class HistContainer : private RootContainer } // fill histogram or profile with arguments x,y,z,... and weight if requested - template <bool fillWeight = false, typename... Ts> - void Fill(uint8_t histID, Ts&&... position) + template <uint8_t histID, bool fillWeight = false, typename... Ts> + void Fill(Ts&&... position) { std::visit([this, &position...](auto&& hist) { GenericFill<fillWeight>(hist, std::forward<Ts>(position)...); }, mHistos[histID]); } - template <typename... Ts> - void FillWeight(uint8_t histID, Ts&&... positionAndWeight) + template <uint8_t histID, typename... Ts> + void FillWeight(Ts&&... positionAndWeight) { - Fill<true>(histID, std::forward<Ts>(positionAndWeight)...); + Fill<histID, true>(std::forward<Ts>(positionAndWeight)...); } // make accessible only the RootContainer functions needed for writing to file @@ -176,8 +170,8 @@ class HistContainer : private RootContainer } std::optional<HistType> GetHistVariant(std::shared_ptr<TObject> obj) { - // Remember: TProfile3D is TH3, TProfile2D is TH2, TH3 is TH1, TH2 is TH1, TProfile is TH1 if (obj) { + // TProfile3D is TH3, TProfile2D is TH2, TH3 is TH1, TH2 is TH1, TProfile is TH1 return GetHistVariant<THn, THnSparse, TProfile3D, TH3, TProfile2D, TH2, TProfile, TH1>(obj); } return std::nullopt; @@ -337,8 +331,6 @@ class Hist } }; -} // namespace histhelpers -} // namespace experimental -} // namespace o2 +} // namespace o2::experimental::histhelpers #endif diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index aa42b05b95424..63431b6280f66 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -95,75 +95,75 @@ struct TrackQATask { void init(o2::framework::InitContext&) { // kine histograms - kine->Add(pt, new TH1D("pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", 200, 0., 5.)); - kine->Add(eta, new TH1D("eta", "#eta;#eta", 180, -0.9, 0.9)); - kine->Add(phi, new TH1D("phi", "#phi;#phi [rad]", 180, 0., 2 * M_PI)); + kine->Add<pt>(new TH1D("pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", 200, 0., 5.)); + kine->Add<eta>(new TH1D("eta", "#eta;#eta", 180, -0.9, 0.9)); + kine->Add<phi>(new TH1D("phi", "#phi;#phi [rad]", 180, 0., 2 * M_PI)); // track histograms - trackpar->Add(x, new TH1D("x", "track #it{x} position at dca in local coordinate system;#it{x} [cm]", 200, -0.36, 0.36)); - trackpar->Add(y, new TH1D("y", "track #it{y} position at dca in local coordinate system;#it{y} [cm]", 200, -0.5, 0.5)); - trackpar->Add(z, new TH1D("z", "track #it{z} position at dca in local coordinate system;#it{z} [cm]", 200, -11., 11.)); - trackpar->Add(alpha, new TH1D("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 36, -M_PI, M_PI)); - trackpar->Add(signed1Pt, new TH1D("signed1Pt", "track signed 1/#it{p}_{T};#it{q}/#it{p}_{T}", 200, -8, 8)); - trackpar->Add(snp, new TH1D("snp", "sinus of track momentum azimuthal angle;snp", 11, -0.1, 0.1)); - trackpar->Add(tgl, new TH1D("tgl", "tangent of the track momentum dip angle;tgl;", 200, -1., 1.)); - trackpar->Add(flags, new TH1D("flags", "track flag;flag bit", 64, -0.5, 63.5)); - trackpar->Add(dcaXY, new TH1D("dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", 200, -0.15, 0.15)); - trackpar->Add(dcaZ, new TH1D("dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", 200, -0.15, 0.15)); + trackpar->Add<x>(new TH1D("x", "track #it{x} position at dca in local coordinate system;#it{x} [cm]", 200, -0.36, 0.36)); + trackpar->Add<y>(new TH1D("y", "track #it{y} position at dca in local coordinate system;#it{y} [cm]", 200, -0.5, 0.5)); + trackpar->Add<z>(new TH1D("z", "track #it{z} position at dca in local coordinate system;#it{z} [cm]", 200, -11., 11.)); + trackpar->Add<alpha>(new TH1D("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 36, -M_PI, M_PI)); + trackpar->Add<signed1Pt>(new TH1D("signed1Pt", "track signed 1/#it{p}_{T};#it{q}/#it{p}_{T}", 200, -8, 8)); + trackpar->Add<snp>(new TH1D("snp", "sinus of track momentum azimuthal angle;snp", 11, -0.1, 0.1)); + trackpar->Add<tgl>(new TH1D("tgl", "tangent of the track momentum dip angle;tgl;", 200, -1., 1.)); + trackpar->Add<flags>(new TH1D("flags", "track flag;flag bit", 64, -0.5, 63.5)); + trackpar->Add<dcaXY>(new TH1D("dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", 200, -0.15, 0.15)); + trackpar->Add<dcaZ>(new TH1D("dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", 200, -0.15, 0.15)); // its histograms - its->Add(itsNCls, new TH1D("itsNCls", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5)); - its->Add(itsChi2NCl, new TH1D("itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40)); - its->Add(itsHits, new TH1D("itsHits", "hitmap ITS;layer ITS", 7, -0.5, 6.5)); + its->Add<itsNCls>(new TH1D("itsNCls", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5)); + its->Add<itsChi2NCl>(new TH1D("itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40)); + its->Add<itsHits>(new TH1D("itsHits", "hitmap ITS;layer ITS", 7, -0.5, 6.5)); // tpc histograms - tpc->Add(tpcNClsFindable, new TH1D("tpcNClsFindable", "number of findable TPC clusters;# findable clusters TPC", 165, -0.5, 164.5)); - tpc->Add(tpcNClsFound, new TH1D("tpcNClsFound", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5)); - tpc->Add(tpcNClsShared, new TH1D("tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", 165, -0.5, 164.5)); - tpc->Add(tpcNClsCrossedRows, new TH1D("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5)); - tpc->Add(tpcFractionSharedCls, new TH1D("tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.)); - tpc->Add(tpcCrossedRowsOverFindableCls, new TH1D("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 120, 0.0, 1.2)); - tpc->Add(tpcChi2NCl, new TH1D("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10)); + tpc->Add<tpcNClsFindable>(new TH1D("tpcNClsFindable", "number of findable TPC clusters;# findable clusters TPC", 165, -0.5, 164.5)); + tpc->Add<tpcNClsFound>(new TH1D("tpcNClsFound", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5)); + tpc->Add<tpcNClsShared>(new TH1D("tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", 165, -0.5, 164.5)); + tpc->Add<tpcNClsCrossedRows>(new TH1D("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5)); + tpc->Add<tpcFractionSharedCls>(new TH1D("tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.)); + tpc->Add<tpcCrossedRowsOverFindableCls>(new TH1D("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 120, 0.0, 1.2)); + tpc->Add<tpcChi2NCl>(new TH1D("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10)); } void process(soa::Filtered<soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection>>::iterator const& track) { // fill kinematic variables - kine->Fill(pt, track.pt()); - kine->Fill(eta, track.eta()); - kine->Fill(phi, track.phi()); + kine->Fill<pt>(track.pt()); + kine->Fill<eta>(track.eta()); + kine->Fill<phi>(track.phi()); // fill track parameters - trackpar->Fill(alpha, track.alpha()); - trackpar->Fill(x, track.x()); - trackpar->Fill(y, track.y()); - trackpar->Fill(z, track.z()); - trackpar->Fill(signed1Pt, track.signed1Pt()); - trackpar->Fill(snp, track.snp()); - trackpar->Fill(tgl, track.tgl()); + trackpar->Fill<alpha>(track.alpha()); + trackpar->Fill<x>(track.x()); + trackpar->Fill<y>(track.y()); + trackpar->Fill<z>(track.z()); + trackpar->Fill<signed1Pt>(track.signed1Pt()); + trackpar->Fill<snp>(track.snp()); + trackpar->Fill<tgl>(track.tgl()); for (unsigned int i = 0; i < 64; i++) { if (track.flags() & (1 << i)) - trackpar->Fill(flags, i); + trackpar->Fill<flags>(i); } - trackpar->Fill(dcaXY, track.dcaXY()); - trackpar->Fill(dcaZ, track.dcaZ()); + trackpar->Fill<dcaXY>(track.dcaXY()); + trackpar->Fill<dcaZ>(track.dcaZ()); // fill ITS variables - its->Fill(itsNCls, track.itsNCls()); - its->Fill(itsChi2NCl, track.itsChi2NCl()); + its->Fill<itsNCls>(track.itsNCls()); + its->Fill<itsChi2NCl>(track.itsChi2NCl()); for (unsigned int i = 0; i < 7; i++) { if (track.itsClusterMap() & (1 << i)) - its->Fill(itsHits, i); + its->Fill<itsHits>(i); } // fill TPC variables - tpc->Fill(tpcNClsFindable, track.tpcNClsFindable()); - tpc->Fill(tpcNClsFound, track.tpcNClsFound()); - tpc->Fill(tpcNClsShared, track.tpcNClsShared()); - tpc->Fill(tpcNClsCrossedRows, track.tpcNClsCrossedRows()); - tpc->Fill(tpcCrossedRowsOverFindableCls, track.tpcCrossedRowsOverFindableCls()); - tpc->Fill(tpcFractionSharedCls, track.tpcFractionSharedCls()); - tpc->Fill(tpcChi2NCl, track.tpcChi2NCl()); + tpc->Fill<tpcNClsFindable>(track.tpcNClsFindable()); + tpc->Fill<tpcNClsFound>(track.tpcNClsFound()); + tpc->Fill<tpcNClsShared>(track.tpcNClsShared()); + tpc->Fill<tpcNClsCrossedRows>(track.tpcNClsCrossedRows()); + tpc->Fill<tpcCrossedRowsOverFindableCls>(track.tpcCrossedRowsOverFindableCls()); + tpc->Fill<tpcFractionSharedCls>(track.tpcFractionSharedCls()); + tpc->Fill<tpcChi2NCl>(track.tpcChi2NCl()); // fill TRD variables diff --git a/Analysis/Tutorials/src/histHelpersTest.cxx b/Analysis/Tutorials/src/histHelpersTest.cxx index c604bd25bbeef..0a974f7eea8f3 100644 --- a/Analysis/Tutorials/src/histHelpersTest.cxx +++ b/Analysis/Tutorials/src/histHelpersTest.cxx @@ -23,34 +23,37 @@ 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, - - Hist_test_1d_TProfile, - Hist_test_2d_TProfile2D, - Hist_test_3d_TProfile3D, - - Hist_test_7d_THnF_first, - Hist_test_7d_THnF_second, - Hist_test_8d_THnC_third, - LAST, + enum HistNamesTest : uint8_t { + test_1d_TH1D, + test_2d_TH2F, + test_3d_TH3I, + test_1d_TH1D_Weight, + test_2d_TH2F_VarBinningY, + + test_3d_THnI, + test_5d_THnSparseI, + + test_1d_TProfile, + test_1d_TProfile_Weight, + test_2d_TProfile2D, + test_3d_TProfile3D, + + test_7d_THnF_first, + test_7d_THnF_second, + test_8d_THnC_third, + }; + enum HistNamesKine : uint8_t { + pt, + eta, + phi, + }; + enum HistNamesTPC : uint8_t { + tpcNClsFound, + tpcNClsCrossedRows, + tpcChi2NCl, + }; + enum HistNamesITS : uint8_t { + itsChi2NCl, }; OutputObj<HistArray> test{HistArray("Test"), OutputObjHandlingPolicy::QAObject}; @@ -63,23 +66,23 @@ struct HistHelpersTest { 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, new 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.)); + test->Add<test_1d_TH1D>(new TH1D("test_1d_TH1D", ";x", 100, 0., 50.)); + test->Add<test_2d_TH2F>(new TH2F("test_2d_TH2F", ";x;y", 100, -0.5, 0.5, 100, -0.5, 0.5)); + test->Add<test_3d_TH3I>(new TH3I("test_3d_TH3I", ";x;y;z", 100, 0., 20., 100, 0., 20., 100, 0., 20.)); // alternatively use Hist to generate the histogram and add it to container afterwards Hist<TH1D> sameAsBefore; sameAsBefore.AddAxis("x", "x", 100, 0., 50.); // via Hist::Create() we can generate the actual root histogram with the requested axes // Parameters: the name and optionally the decision wether to call SumW2 in case we want to fill this histogram with weights - test->Add(Hist_test_1d_TH1D_Builder, sameAsBefore.Create("testHist_TH1_Builder", true)); + test->Add<test_1d_TH1D_Weight>(sameAsBefore.Create("test_1d_TH1D_Weight", true)); // this helper enables us to have combinations of flexible + fixed binning in 2d or 3d histograms // (which are not available via default root constructors) Hist<TH2F> sameButDifferent; sameButDifferent.AddAxis("x", "x", 100, -0.5, 0.5); 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.Create("testHist_TH2_Builder")); + test->Add<test_2d_TH2F_VarBinningY>(sameButDifferent.Create("test_2d_TH2F_VarBinningY")); // also for n dimensional histograms things become much simpler: std::vector<double> ptBins = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, @@ -99,42 +102,34 @@ struct HistHelpersTest { myHistogram.AddAxis(ptAxis); myHistogram.AddAxis(etaAxis); myHistogram.AddAxis("signed1Pt", "q/p_{T}", 200, -8, 8); - test->Add(Hist_test_3d_THnI, myHistogram.Create("testHist_THn")); + test->Add<test_3d_THnI>(myHistogram.Create("test_3d_THnI")); - Hist<THnSparseC> testSparseHist; + Hist<THnSparseI> testSparseHist; testSparseHist.AddAxis(ptAxis); testSparseHist.AddAxis(etaAxis); testSparseHist.AddAxis(phiAxis); testSparseHist.AddAxis(centAxis); testSparseHist.AddAxis(cutAxis); - test->Add(Hist_test_5d_THnSparseI, testSparseHist.Create("testHist_THnSparse")); + test->Add<test_5d_THnSparseI>(testSparseHist.Create("test_5d_THnSparseI")); Hist<TProfile> testProfile; testProfile.AddAxis(ptAxis); - test->Add(Hist_test_1d_TProfile, testProfile.Create("testProfile_TProfile")); - test->Get<TProfile>(Hist_test_1d_TProfile)->GetYaxis()->SetTitle("eta profile"); + test->Add<test_1d_TProfile>(testProfile.Create("test_1d_TProfile")); + test->Get<TProfile>(test_1d_TProfile)->GetYaxis()->SetTitle("eta profile"); + + // now add same histogram but intended for weighted filling + test->Add<test_1d_TProfile_Weight>(testProfile.Create("test_1d_TProfile_Weight", true)); Hist<TProfile2D> testProfile2d; testProfile2d.AddAxis(ptAxis); testProfile2d.AddAxis(etaAxis); - test->Add(Hist_test_2d_TProfile2D, testProfile2d.Create("testProfile_TProfile2D")); + test->Add<test_2d_TProfile2D>(testProfile2d.Create("test_2d_TProfile2D")); Hist<TProfile3D> testProfile3d; testProfile3d.AddAxis(ptAxis); testProfile3d.AddAxis(etaAxis); testProfile3d.AddAxis(phiAxis); - test->Add(Hist_test_3d_TProfile3D, testProfile3d.Create("testProfile_TProfile3D")); - - // 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)); + test->Add<test_3d_TProfile3D>(testProfile3d.Create("test_3d_TProfile3D")); // we can also re-use axis definitions in case they are similar in many histograms: Hist<THnF> baseDimensions; @@ -147,57 +142,71 @@ struct HistHelpersTest { Hist<THnF> firstHist = baseDimensions; firstHist.AddAxis("something", "v (m/s)", 10, -1, 1); - its->Add(Hist_test_7d_THnF_first, firstHist.Create("firstHist")); + test->Add<test_7d_THnF_first>(firstHist.Create("test_7d_THnF_first")); Hist<THnF> secondHist = baseDimensions; secondHist.AddAxis("somethingElse", "a (m/(s*s))", 10, -1, 1); - its->Add(Hist_test_7d_THnF_second, secondHist.Create("secondHist")); + test->Add<test_7d_THnF_second>(secondHist.Create("test_7d_THnF_second")); // or if we want to have the baseDimensions somewhere in between: Hist<THnC> thirdHist; thirdHist.AddAxis("myFirstDimension", "a (m/(s*s))", 10, -1, 1); thirdHist.AddAxes(baseDimensions); thirdHist.AddAxis("myLastDimension", "a (m/(s*s))", 10, -1, 1); - its->Add(Hist_test_8d_THnC_third, thirdHist.Create("thirdHist")); + test->Add<test_8d_THnC_third>(thirdHist.Create("test_8d_THnC_third")); - // we can also use the Hist heleper tool independent of the HistCollections: + // we can also use the Hist helper tool independent of the HistCollections: Hist<THnF> myHist; myHist.AddAxis(ptAxis); myHist.AddAxis(etaAxis); myHist.AddAxis(phiAxis); standaloneHist.setObject(myHist.Create("standaloneHist")); + + // now add some more useful histograms + kine->Add<pt>(new TH1F("pt", "p_{T};p_{T} [GeV/c]", 100, 0., 5.)); + kine->Add<eta>(new TH1F("eta", "#eta;#eta", 101, -1.0, 1.0)); + kine->Add<phi>(new TH1F("phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI)); + + tpc->Add<tpcNClsFound>(new TH1F("tpcNClsFound", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5)); + tpc->Add<tpcNClsCrossedRows>(new TH1F("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5)); + tpc->Add<tpcChi2NCl>(new TH1F("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10)); + + its->Add<itsChi2NCl>(new TH1F("itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40)); } void process(soa::Join<aod::Tracks, aod::TracksExtra>::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<test_1d_TH1D>(20.); + test->Fill<test_2d_TH2F>(0.1, 0.3); + test->Fill<test_3d_TH3I>(10, 10, 15.5); // this time fill the 1d histogram with weight of 10: - test->FillWeight(Hist_test_1d_TH1D_Builder, 1., 10.); - test->Fill(Hist_test_2d_TH2F_Builder, 0.1, 0.3); + test->FillWeight<test_1d_TH1D_Weight>(20., 10.); + + test->Fill<test_2d_TH2F_VarBinningY>(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); + test->Fill<test_3d_THnI>(1., 0., 1.5); + test->Fill<test_5d_THnSparseI>(1., 0., 1.5, 30, 1); // we can also directly access to the underlying histogram // for this the correct type has to be known (TH1, TH2, TH3, THn, THnSparse, TProfile, TProfile2D or TProfile3D) - test->Get<TH2>(Hist_test_2d_TH2F)->Fill(0.2, 0.2); + test->Get<TH2>(test_2d_TH2F)->Fill(0.2, 0.2); - test->Fill(Hist_test_1d_TProfile, track.pt(), track.eta()); - test->Fill(Hist_test_2d_TProfile2D, track.pt(), track.eta(), track.phi()); - test->Fill(Hist_test_3d_TProfile3D, track.pt(), track.eta(), track.phi(), track.tpcNClsFound()); + test->Fill<test_1d_TProfile>(track.pt(), track.eta()); + // now fill same histogram, but with random weight + test->FillWeight<test_1d_TProfile_Weight>(track.pt(), track.eta(), std::rand()); + test->Fill<test_2d_TProfile2D>(track.pt(), track.eta(), track.phi()); + test->Fill<test_3d_TProfile3D>(track.pt(), track.eta(), track.phi(), track.tpcNClsFound()); - kine->Fill(Hist_pt, track.pt()); - kine->Fill(Hist_eta, track.eta()); - kine->Fill(Hist_phi, track.phi()); + kine->Fill<pt>(track.pt()); + kine->Fill<eta>(track.eta()); + kine->Fill<phi>(track.phi()); - tpc->Fill(Hist_nClsTPC, track.tpcNClsFound()); - tpc->Fill(Hist_nCrossedRowsTPC, track.tpcNClsCrossedRows()); - tpc->Fill(Hist_Chi2PerClTPC, track.itsChi2NCl()); + tpc->Fill<tpcNClsFound>(track.tpcNClsFound()); + tpc->Fill<tpcNClsCrossedRows>(track.tpcNClsCrossedRows()); + tpc->Fill<tpcChi2NCl>(track.tpcChi2NCl()); - its->Fill(Hist_Chi2PerClITS, track.tpcChi2NCl()); + its->Fill<itsChi2NCl>(track.itsChi2NCl()); double dummyArray[] = {track.pt(), track.eta(), track.phi()}; standaloneHist->Fill(dummyArray); From d3b8d8b83b0951ef1b8764e18eeafa0253fc57fe Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 30 Sep 2020 14:30:07 +0200 Subject: [PATCH 0811/1751] Add ROOT PCM file dependncies to ensure correct incremental rebuild of ROOT maps --- CMakeLists.txt | 4 ++- cmake/AddRootDictionary.cmake | 7 +++-- cmake/O2SetROOTPCMDependencies.cmake | 42 ++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 cmake/O2SetROOTPCMDependencies.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index fead88a8a1126..f989fdf44cb9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ include(O2TargetRootDictionary) include(O2DataFile) include(O2TargetManPage) include(O2AddWorkflow) +include(O2SetROOTPCMDependencies) # Main targets of the project in various subdirectories. Order matters. add_subdirectory(Common) @@ -112,5 +113,6 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) o2_report_non_tested_macros() endif() add_subdirectory(packaging) - endif() + +set_root_pcm_dependencies() diff --git a/cmake/AddRootDictionary.cmake b/cmake/AddRootDictionary.cmake index 7de4ee0809e42..8adbbb8aab4d5 100644 --- a/cmake/AddRootDictionary.cmake +++ b/cmake/AddRootDictionary.cmake @@ -111,8 +111,11 @@ function(add_root_dictionary target) set(pcmBase ${dictionary}_rdict.pcm) set(pcmFile ${lib_output_dir}/${pcmBase}) set(rootmapFile ${lib_output_dir}/lib${basename}.rootmap) + + set(O2_TARGETPCMMAP_TARGET "${O2_TARGETPCMMAP_TARGET};${target}" CACHE INTERNAL "target/PCM map (target)") + set(O2_TARGETPCMMAP_PCM "${O2_TARGETPCMMAP_PCM};${pcmFile}" CACHE INTERNAL "target/PCM map (pcm)") - # get the list of compile_definitions + # get the list of compile_definitions set(prop $<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>) # Build the LD_LIBRARY_PATH required to get rootcling running fine @@ -144,7 +147,7 @@ function(add_root_dictionary target) --headers "${headers}" COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/${pcmBase} ${pcmFile} - DEPENDS ${headers}) + DEPENDS ${headers} "$<REMOVE_DUPLICATES:${list_pcm_deps_${target}}>") # cmake-format: on # add dictionary source to the target sources diff --git a/cmake/O2SetROOTPCMDependencies.cmake b/cmake/O2SetROOTPCMDependencies.cmake new file mode 100644 index 0000000000000..915cc7858234d --- /dev/null +++ b/cmake/O2SetROOTPCMDependencies.cmake @@ -0,0 +1,42 @@ +# 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_guard() + +set(O2_TARGETPCMMAP_TARGET "" CACHE INTERNAL "target/PCM map (target)") +set(O2_TARGETPCMMAP_PCM "" CACHE INTERNAL "target/PCM map (pcm)") + +function(set_root_pcm_dependencies) + foreach(target pcm IN ZIP_LISTS O2_TARGETPCMMAP_TARGET O2_TARGETPCMMAP_PCM) + if (NOT pcm STREQUAL "") + #message(STATUS "target ${target} has pcm ${pcm}") + list(APPEND target_pcms_${target} ${pcm}) + endif() + endforeach() + + foreach(target pcm IN ZIP_LISTS O2_TARGETPCMMAP_TARGET O2_TARGETPCMMAP_PCM) + if (NOT pcm STREQUAL "") + unset(pcm_dep_list) + get_target_property(dep_targets ${target} LINK_LIBRARIES) + foreach(dep_target IN LISTS dep_targets) + if (dep_target MATCHES "^O2::") + string(REPLACE "O2::" "" dep_target ${dep_target}) + o2_name_target(${dep_target} NAME dep_target) + #message(STATUS "target ${target} depends on ${dep_target}") + foreach(dep_pcm IN LISTS target_pcms_${dep_target}) + #message(STATUS "${pcm} depends on ${dep_pcm}") + list(APPEND pcm_dep_list ${dep_pcm}) + endforeach() + endif() + endforeach() + set(list_pcm_deps_${target} "${pcm_dep_list}" CACHE INTERNAL "List of pcm dependencies for ${target}") + endif() + endforeach() +endfunction() From d4567f712701846e72e2198b5615b043cf55bdde Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 30 Sep 2020 20:33:30 +0200 Subject: [PATCH 0812/1751] Use rootcling -m option to avoid duplicates in dictionaries --- cmake/AddRootDictionary.cmake | 1 + cmake/rootcling_wrapper.sh.in | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cmake/AddRootDictionary.cmake b/cmake/AddRootDictionary.cmake index 8adbbb8aab4d5..8f627247c9183 100644 --- a/cmake/AddRootDictionary.cmake +++ b/cmake/AddRootDictionary.cmake @@ -144,6 +144,7 @@ function(add_root_dictionary target) --include_dirs -I$<JOIN:${includeDirs},$<SEMICOLON>-I> $<$<BOOL:${prop}>:--compile_defs> $<$<BOOL:${prop}>:-D$<JOIN:${prop},$<SEMICOLON>-D>> + --pcmdeps "$<REMOVE_DUPLICATES:${list_pcm_deps_${target}}>" --headers "${headers}" COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/${pcmBase} ${pcmFile} diff --git a/cmake/rootcling_wrapper.sh.in b/cmake/rootcling_wrapper.sh.in index 1a53153cd0374..3d926190b212d 100755 --- a/cmake/rootcling_wrapper.sh.in +++ b/cmake/rootcling_wrapper.sh.in @@ -37,6 +37,10 @@ while [[ $# -gt 0 ]]; do ROOTMAP_FILE="$2" shift 2 ;; + --pcmdeps) + PCMDEPS="$2" + shift 2 + ;; *) if [[ -z "$1" ]]; then shift @@ -77,7 +81,14 @@ LOGFILE=${DICTIONARY_FILE}.log -rml ${ROOTMAP_LIBRARY_NAME} \ ${INCLUDE_DIRS//;/ } \ ${COMPILE_DEFINITIONS//;/ } \ - ${HEADERS//;/ } > ${LOGFILE} 2>&1 || cat ${LOGFILE} >&2 + ${PCMDEPS:+-m }${PCMDEPS//;/ -m } \ + ${HEADERS//;/ } \ + > ${LOGFILE} 2>&1 || cat ${LOGFILE} >&2 + +if [[ $? != "0" ]]; then + rm $DICTIONARY_FILE + exit 1 +fi MSG="Warning: Unused class rule" if [[ -s ${LOGFILE} ]]; then From 4b6f03b8d733b95d19164f4bbee531e45d2c17a5 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Thu, 1 Oct 2020 10:28:18 +0200 Subject: [PATCH 0813/1751] TrackSelection: skip dca calculation for more tracks (#4472) --- Analysis/Tasks/trackselection.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index 66ff376b334eb..f2067e796d5fe 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -75,7 +75,7 @@ struct TrackExtensionTask { std::array<float, 2> dca{1e10f, 1e10f}; // FIXME: temporary solution to remove tracks that should not be there after conversion - if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && track.x() < 150.f) { + if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && std::abs(track.x()) < 10.f) { float magField = 5.0; // in kG (FIXME: get this from CCDB) auto trackPar = getTrackPar(track); trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, magField, &dca); From dc5076b55a8a04f733d80b0d2608921bb7248a30 Mon Sep 17 00:00:00 2001 From: Andreas Morsch <andreas.morsch@cern.ch> Date: Tue, 29 Sep 2020 16:18:40 +0200 Subject: [PATCH 0814/1751] pass second mother ID to MCTrack + corresponding setters and getters --- .../include/SimulationDataFormat/MCTrack.h | 14 ++++++++++---- .../include/SimulationDataFormat/Stack.h | 7 +++---- DataFormats/simulation/src/Stack.cxx | 6 +++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h index 2f35edcbaa71e..29add2b3cfcdd 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h @@ -40,7 +40,7 @@ class MCTrackT MCTrackT(); /// Standard constructor - MCTrackT(Int_t pdgCode, Int_t motherID, Int_t firstDaighterID, Int_t lastDaughterID, + MCTrackT(Int_t pdgCode, Int_t motherID, Int_t secondMotherID, Int_t firstDaughterID, Int_t lastDaughterID, Double_t px, Double_t py, Double_t pz, Double_t x, Double_t y, Double_t z, Double_t t, Int_t nPoints); @@ -59,6 +59,7 @@ class MCTrackT /// Accessors Int_t GetPdgCode() const { return mPdgCode; } Int_t getMotherTrackId() const { return mMotherTrackId; } + Int_t getSecondMotherTrackId() const { return mSecondMotherTrackId; } bool isSecondary() const { return mMotherTrackId != -1; } Int_t getFirstDaughterTrackId() const { return mFirstDaughterTrackId; } Int_t getLastDaughterTrackId() const { return mLastDaughterTrackId; } @@ -133,6 +134,7 @@ class MCTrackT void setHitMask(Int_t m) { ((PropEncoding)mProp).hitmask = m; } /// Modifiers void SetMotherTrackId(Int_t id) { mMotherTrackId = id; } + void SetSecondMotherTrackId(Int_t id) { mSecondMotherTrackId = id; } void SetFirstDaughterTrackId(Int_t id) { mFirstDaughterTrackId = id; } void SetLastDaughterTrackId(Int_t id) { mLastDaughterTrackId = id; } // set bit indicating that this track @@ -193,8 +195,9 @@ class MCTrackT /// PDG particle code Int_t mPdgCode; - /// Index of mother track. + /// Index of mother tracks Int_t mMotherTrackId; + Int_t mSecondMotherTrackId; Int_t mFirstDaughterTrackId; Int_t mLastDaughterTrackId; @@ -215,7 +218,7 @@ class MCTrackT }; }; - ClassDefNV(MCTrackT, 2); + ClassDefNV(MCTrackT, 3); }; template <typename T> @@ -248,6 +251,7 @@ template <typename T> inline MCTrackT<T>::MCTrackT() : mPdgCode(0), mMotherTrackId(-1), + mSecondMotherTrackId(-1), mFirstDaughterTrackId(-1), mLastDaughterTrackId(-1), mStartVertexMomentumX(0.), @@ -262,11 +266,12 @@ inline MCTrackT<T>::MCTrackT() } template <typename T> -inline MCTrackT<T>::MCTrackT(Int_t pdgCode, Int_t motherId, Int_t firstDaughterId, Int_t lastDaughterId, +inline MCTrackT<T>::MCTrackT(Int_t pdgCode, Int_t motherId, Int_t secondMotherId, Int_t firstDaughterId, Int_t lastDaughterId, Double_t px, Double_t py, Double_t pz, Double_t x, Double_t y, Double_t z, Double_t t, Int_t mask) : mPdgCode(pdgCode), mMotherTrackId(motherId), + mSecondMotherTrackId(secondMotherId), mFirstDaughterTrackId(firstDaughterId), mLastDaughterTrackId(lastDaughterId), mStartVertexMomentumX(px), @@ -284,6 +289,7 @@ template <typename T> inline MCTrackT<T>::MCTrackT(const TParticle& part) : mPdgCode(part.GetPdgCode()), mMotherTrackId(part.GetMother(0)), + mSecondMotherTrackId(part.GetMother(1)), mFirstDaughterTrackId(part.GetFirstDaughter()), mLastDaughterTrackId(part.GetLastDaughter()), mStartVertexMomentumX(part.Px()), diff --git a/DataFormats/simulation/include/SimulationDataFormat/Stack.h b/DataFormats/simulation/include/SimulationDataFormat/Stack.h index 87e78a8411017..3bb5cda6ff82e 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/Stack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/Stack.h @@ -177,7 +177,6 @@ class Stack : public FairGenericStack /// Clone for worker (used in MT mode only) FairGenericStack* CloneStack() const override; - // methods concerning track references void addTrackReference(const o2::TrackReference& p); @@ -232,9 +231,9 @@ class Stack : public FairGenericStack /// Array of TParticles (contains all TParticles put into or created /// by the transport) - std::vector<o2::MCTrack> mParticles; //! - std::vector<int> mTransportedIDs; //! prim + sec trackIDs transported for "current" primary - std::vector<int> mIndexOfPrimaries; //! index of primaries in mParticles + std::vector<o2::MCTrack> mParticles; //! + std::vector<int> mTransportedIDs; //! prim + sec trackIDs transported for "current" primary + std::vector<int> mIndexOfPrimaries; //! index of primaries in mParticles std::vector<int> mTrackIDtoParticlesEntry; //! an O(1) mapping of trackID to the entry of mParticles // the current TParticle object TParticle mCurrentParticle; diff --git a/DataFormats/simulation/src/Stack.cxx b/DataFormats/simulation/src/Stack.cxx index b4c9db1970e45..95dafc74f5398 100644 --- a/DataFormats/simulation/src/Stack.cxx +++ b/DataFormats/simulation/src/Stack.cxx @@ -148,7 +148,7 @@ void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e, Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz, - TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondparentID) + TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondparentId) { // printf("Pushing %s toBeDone %5d parentId %5d pdgCode %5d is %5d entries %5d \n", // proc == kPPrimary ? "Primary: " : "Secondary: ", @@ -167,11 +167,10 @@ void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px Int_t trackId = mNumberOfEntriesInParticles; // Set track variable ntr = trackId; - Int_t nPoints = 0; Int_t daughter1Id = -1; Int_t daughter2Id = -1; Int_t iStatus = (proc == kPPrimary) ? is : trackId; - TParticle p(pdgCode, iStatus, parentId, nPoints, daughter1Id, daughter2Id, px, py, pz, e, vx, vy, vz, time); + TParticle p(pdgCode, iStatus, parentId, secondparentId, daughter1Id, daughter2Id, px, py, pz, e, vx, vy, vz, time); p.SetPolarisation(polx, poly, polz); p.SetWeight(weight); p.SetUniqueID(proc); // using the unique ID to transfer process ID @@ -535,6 +534,7 @@ void Stack::UpdateTrackIndex(TRefArray* detList) void Stack::Reset() { + mIndexOfCurrentTrack = -1; mNumberOfPrimaryParticles = mNumberOfEntriesInParticles = mNumberOfEntriesInTracks = 0; while (!mStack.empty()) { From eb686b0df3f669bb26ea98cf48ce9c99cedc3fb6 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 1 Oct 2020 13:53:45 +0200 Subject: [PATCH 0815/1751] DPL: avoid busy looping when in Idle state (#4481) Under certain conditions (most notably when an enumeration was provided and the device switched to "Idle" state) the libuv integration mistaken ly considered as activity any further enumeration, resulting in a busy loop. This makes sure we always UV_ONCE (i.e. wait for an external event) when in StreamingState::Idle. --- Framework/Core/src/DataProcessingDevice.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 0d7f06d3b561f..13c70ddf03fde 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -427,7 +427,7 @@ bool DataProcessingDevice::ConditionalRun() if (mState.loop) { ZoneScopedN("uv idle"); TracyPlot("past activity", (int64_t)mWasActive); - uv_run(mState.loop, mWasActive ? UV_RUN_NOWAIT : UV_RUN_ONCE); + uv_run(mState.loop, mWasActive && (mDataProcessorContexes.at(0).state->streaming != StreamingState::Idle) ? UV_RUN_NOWAIT : UV_RUN_ONCE); } // Notify on the main thread the new region callbacks, making sure From e9ca9b968fbbd8411244b36305467ea399811a68 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 1 Oct 2020 01:12:38 +0200 Subject: [PATCH 0816/1751] Use as UserField 2 bytes of TrackPar lost for alignment padding --- .../include/ReconstructionDataFormats/Track.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h index 553258b407138..305aab0e4fda3 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h @@ -161,6 +161,8 @@ class TrackPar mPID = pid; setAbsCharge(pid.getCharge()); } + uint16_t getUserField() const { return mUserField; } + void setUserField(uint16_t v) { mUserField = v; } /// calculate cos^2 and cos of track direction in rphi-tracking float getCsp2() const @@ -247,8 +249,8 @@ class TrackPar float mP[kNParams] = {0.f}; /// 5 parameters: Y,Z,sin(phi),tg(lambda),q/pT char mAbsCharge = 1; /// Extra info about the abs charge, to be taken into account only if not 1 PID mPID{}; /// 8 bit PID - - ClassDefNV(TrackPar, 2); + uint16_t mUserField = 0; /// field provided to user + ClassDefNV(TrackPar, 3); }; class TrackParCov : public TrackPar From ca6f37e6b97805c4d3fcf8877867f5c9fd5a186d Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Thu, 1 Oct 2020 14:50:39 +0200 Subject: [PATCH 0817/1751] adding ionut to analysis codeowners (#4480) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 8e61625d42258..ea94454bfdb50 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -12,7 +12,7 @@ /Algorithm @matthiasrichter -/Analysis @jgrosseo +/Analysis @jgrosseo @iarsene /Analysis/Tasks/hf* @ginnocen /CCDB @costing @Barthelemy @sawenzel @AliceO2Group/framework-admins From 998bce647c0feb8fb7c080c094e10f328acd7f7b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 1 Oct 2020 17:42:03 +0200 Subject: [PATCH 0818/1751] GPU: sort comparison function must return 0 for equals --- Detectors/TPC/workflow/src/ZSSpec.cxx | 7 ++----- GPU/GPUTracking/Base/GPUReconstructionConvert.cxx | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Detectors/TPC/workflow/src/ZSSpec.cxx b/Detectors/TPC/workflow/src/ZSSpec.cxx index c0bf8db513211..4ad3dd477b543 100644 --- a/Detectors/TPC/workflow/src/ZSSpec.cxx +++ b/Detectors/TPC/workflow/src/ZSSpec.cxx @@ -65,7 +65,6 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi struct ProcessAttributes { std::unique_ptr<unsigned long long int[]> zsoutput; std::vector<unsigned int> sizes; - std::unique_ptr<o2::gpu::GPUReconstructionConvert> zsEncoder; std::vector<int> inputIds; bool verify = false; int verbosity = 1; @@ -74,7 +73,6 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi auto initFunction = [inputIds, zs10bit, threshold, outRaw](InitContext& ic) { auto processAttributes = std::make_shared<ProcessAttributes>(); - auto& zsEncoder = processAttributes->zsEncoder; auto& zsoutput = processAttributes->zsoutput; processAttributes->inputIds = inputIds; auto& verify = processAttributes->verify; @@ -87,7 +85,6 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi return; } - auto& zsEncoder = processAttributes->zsEncoder; auto& zsoutput = processAttributes->zsoutput; auto& verify = processAttributes->verify; auto& sizes = processAttributes->sizes; @@ -130,7 +127,7 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi sizes.resize(NSectors * NEndpoints); bool zs12bit = !zs10bit; o2::InteractionRecord ir = o2::raw::HBFUtils::Instance().getFirstIR(); - zsEncoder->RunZSEncoder<o2::tpc::Digit, DigitArray>(inputDigits, &zsoutput, sizes.data(), nullptr, &ir, _GPUParam, zs12bit, verify, threshold); + o2::gpu::GPUReconstructionConvert::RunZSEncoder<o2::tpc::Digit, DigitArray>(inputDigits, &zsoutput, sizes.data(), nullptr, &ir, _GPUParam, zs12bit, verify, threshold); ZeroSuppressedContainer8kb* page = reinterpret_cast<ZeroSuppressedContainer8kb*>(zsoutput.get()); unsigned int offset = 0; for (unsigned int i = 0; i < NSectors; i++) { @@ -181,7 +178,7 @@ DataProcessorSpec getZSEncoderSpec(std::vector<int> const& inputIds, bool zs10bi if (useGrouping != LinksGrouping::Link) { writer.useCaching(); } - zsEncoder->RunZSEncoder<o2::tpc::Digit>(inputDigits, nullptr, nullptr, &writer, &ir, _GPUParam, zs12bit, false, threshold); + o2::gpu::GPUReconstructionConvert::RunZSEncoder<o2::tpc::Digit>(inputDigits, nullptr, nullptr, &writer, &ir, _GPUParam, zs12bit, false, threshold); writer.writeConfFile("TPC", "RAWDATA", fmt::format("{}tpcraw.cfg", outDir)); } zsoutput.reset(nullptr); diff --git a/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx b/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx index 316da974137b0..8bbb555ad4afa 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionConvert.cxx @@ -274,7 +274,7 @@ void GPUReconstructionConvert::RunZSEncoder(const S& in, std::unique_ptr<unsigne if (ZSEncoderGetRow(a) != ZSEncoderGetRow(b)) { return ZSEncoderGetRow(a) <= ZSEncoderGetRow(b); } - return ZSEncoderGetPad(a) <= ZSEncoderGetPad(b); + return ZSEncoderGetPad(a) < ZSEncoderGetPad(b); }); int lastEndpoint = -1, lastRow = GPUCA_ROW_COUNT, lastTime = -1; long hbf = -1, nexthbf = 0; From b0d4ee01b1247f53ce04d34d7812b01ff16539d5 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 1 Oct 2020 16:07:49 +0200 Subject: [PATCH 0819/1751] Bugfix in chamber search for TRD tracking --- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index d9a54dfa2391c..e549211e85039 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -1161,7 +1161,7 @@ GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::FindChambersInRoad(const TRDTRK* t, c const GPUTRDpadPlane* pp = mGeo->GetPadPlane(iLayer, currStack); int lastPadRow = mGeo->GetRowMax(iLayer, currStack, 0); float zCenter = pp->GetRowPos(lastPadRow / 2); - if ((t->getZ() + roadZ) > pp->GetRowPos(0) || (t->getZ() - roadZ) < pp->GetRowPos(lastPadRow)) { + if ((t->getZ() + roadZ) > pp->GetRow0() || (t->getZ() - roadZ) < pp->GetRowEnd()) { int addStack = t->getZ() > zCenter ? currStack - 1 : currStack + 1; if (addStack < kNStacks && addStack > -1) { det[nDets++] = mGeo->GetDetector(iLayer, addStack, currSec); From 3196d38db9a63439dd75d15a7b74061263eefcf1 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 2 Oct 2020 10:42:58 +0200 Subject: [PATCH 0820/1751] SimChallenge: MacOS stability fixes Make the test production scripts work on MacOS. --- Utilities/Tools/jobutils.sh | 17 +++++++++++++---- prodtests/sim_challenge.sh | 6 ++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index aa123454bb7ee..dfab53e385043 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -59,12 +59,21 @@ taskwrapper() { eval "${hook}" fi + # the time command is non-standard on MacOS + if [ "$(uname)" == "Darwin" ]; then + GTIME=$(which gtime) + TIMECOMMAND=${GTIME:+"${GTIME} --output=${logfile}_time"} + else + TIMECOMMAND="/usr/bin/time --output=${logfile}_time" + fi + # with or without memory monitoring ? - finalcommand="TIME=\"#walltime %e\" /usr/bin/time --output=${logfile}_time ${command}" - if [ "${JOBUTILS_MONITORMEM}" ]; then - finalcommand="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh /usr/bin/time --output=${logfile}_time '${command}'" + finalcommand="TIME=\"#walltime %e\" ${TIMECOMMAND} ${command}" + if [[ "$(uname)" != "Darwin" && "${JOBUTILS_MONITORMEM}" ]]; then + finalcommand="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh ${TIMECOMMAND} '${command}'" fi - eval ${finalcommand} &> $logfile & + echo "Running: ${finalcommand}" > ${logfile} + eval ${finalcommand} >> ${logfile} 2>&1 & # THE NEXT PART IS THE SUPERVISION PART # get the PID diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 9365a66abacb5..6b3ecce876e62 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -55,7 +55,8 @@ while [ $# -gt 0 ] ; do esac done -collSyst="${collSyst,,}" # convert to lower case +# convert to lower case (the bash construct ${collSyst,,} is less portable) +collSyst=`echo "$collSyst" | awk '{print tolower($0)}'` if [ "$collSyst" == "pp" ]; then gener="$generPP" [[ "nev" -lt "1" ]] && nev="$nevPP" @@ -72,7 +73,8 @@ fi dosim="0" dodigi="0" doreco="0" -fromstage="${fromstage,,}" +# convert to lowercase +fromstage=`echo "$fromstage" | awk '{print tolower($0)}'` if [ "$fromstage" == "sim" ]; then dosim="1" dodigi="1" From 9a545d2894931446b39cf45f08c33ebe75957acf Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 1 Oct 2020 14:11:13 +0200 Subject: [PATCH 0821/1751] Don't use ROOTCLING -m on MacOS --- cmake/rootcling_wrapper.sh.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/rootcling_wrapper.sh.in b/cmake/rootcling_wrapper.sh.in index 3d926190b212d..5a6d8e7bc398b 100755 --- a/cmake/rootcling_wrapper.sh.in +++ b/cmake/rootcling_wrapper.sh.in @@ -72,6 +72,14 @@ if [[ ! $ROOTMAP_FILE ]]; then exit 1 fi +case $OSTYPE in + darwin*) + unset PCMDEPS + ;; + *) + ;; +esac + LOGFILE=${DICTIONARY_FILE}.log @CMAKE_COMMAND@ -E env LD_LIBRARY_PATH=${LD_LIBRARY_PATH} @ROOT_rootcling_CMD@ \ From 37d55dedb6fa6b940299c8a49c6e1c442b58f06b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 1 Oct 2020 21:14:56 +0200 Subject: [PATCH 0822/1751] GPU: Workaround for random crashes on AMD GPUs --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 8eaa623058f67..bffd6fa3b47d9 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1491,6 +1491,9 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() bool error = false; GPUCA_OPENMP(parallel for if(!(doGPU || GetProcessingSettings().ompKernels)) num_threads(GetProcessingSettings().ompThreads)) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { + if (mRec->GetDeviceType() == GPUReconstruction::DeviceType::HIP) { + SynchronizeGPU(); // BUG: Workaround for probable bug in AMD runtime, crashes randomly if not synchronized here + } GPUTPCTracker& trk = processors()->tpcTrackers[iSlice]; GPUTPCTracker& trkShadow = doGPU ? processorsShadow()->tpcTrackers[iSlice] : trk; int useStream = (iSlice % mRec->NStreams()); From 7c8f2c848f24c1b816c7c7c0c2f5c194ae60e694 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sat, 3 Oct 2020 07:54:28 +0200 Subject: [PATCH 0823/1751] DPL Analysis: protect grouping from empty tables (#4489) --- .../Core/include/Framework/AnalysisTask.h | 4 +-- Framework/Core/src/DataAllocator.cxx | 32 +++++++++++++------ Framework/Core/test/test_GroupSlicer.cxx | 32 +++++++++++++++++++ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 67bc87a3bc4f2..59dc5a3cce729 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -237,7 +237,7 @@ struct AnalysisDataProcessorBuilder { auto splitter = [&](auto&& x) { using xt = std::decay_t<decltype(x)>; constexpr auto index = framework::has_type_at_v<std::decay_t<decltype(x)>>(associated_pack_t{}); - if (hasIndexTo<std::decay_t<G>>(typename xt::persistent_columns_t{})) { + if (x.size() != 0 && hasIndexTo<std::decay_t<G>>(typename xt::persistent_columns_t{})) { auto result = o2::framework::sliceByColumn(indexColumnName.c_str(), x.asArrowTable(), static_cast<int32_t>(gt.tableSize()), @@ -342,7 +342,7 @@ struct AnalysisDataProcessorBuilder { auto prepareArgument() { constexpr auto index = framework::has_type_at_v<A1>(associated_pack_t{}); - if (hasIndexTo<G>(typename std::decay_t<A1>::persistent_columns_t{})) { + if (std::get<A1>(*mAt).size() != 0 && hasIndexTo<G>(typename std::decay_t<A1>::persistent_columns_t{})) { uint64_t pos; if constexpr (soa::is_soa_filtered_t<std::decay_t<G>>::value) { pos = (*groupSelection)[position]; diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index 58c821a4290b5..ff48caee0c328 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -151,14 +151,18 @@ void DataAllocator::adopt(const Output& spec, TableBuilder* tb) auto finalizer = [payload = p](std::shared_ptr<FairMQResizableBuffer> b) -> void { auto table = payload->finalize(); if (O2_BUILTIN_UNLIKELY(table->num_rows() == 0)) { - LOG(WARN) << "Empty table was produced: " << table->ToString(); + LOG(DEBUG) << "Empty table was produced: " << table->ToString(); } auto stream = std::make_shared<arrow::io::BufferOutputStream>(b); auto outBatch = arrow::ipc::NewStreamWriter(stream.get(), table->schema()); - auto outStatus = outBatch.ValueOrDie()->WriteTable(*table); - if (outStatus.ok() == false) { - throw std::runtime_error("Unable to Write table"); + if (outBatch.ok() == true) { + auto outStatus = outBatch.ValueOrDie()->WriteTable(*table); + if (outStatus.ok() == false) { + throw std::runtime_error("Unable to Write table"); + } + } else { + throw ::std::runtime_error("Unable to create batch writer"); } }; @@ -187,9 +191,13 @@ void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) auto stream = std::make_shared<arrow::io::BufferOutputStream>(b); std::shared_ptr<arrow::ipc::RecordBatchWriter> writer; auto outBatch = arrow::ipc::NewStreamWriter(stream.get(), table->schema()); - auto outStatus = outBatch.ValueOrDie()->WriteTable(*table); - if (outStatus.ok() == false) { - throw std::runtime_error("Unable to Write table"); + if (outBatch.ok() == true) { + auto outStatus = outBatch.ValueOrDie()->WriteTable(*table); + if (outStatus.ok() == false) { + throw std::runtime_error("Unable to Write table"); + } + } else { + throw ::std::runtime_error("Unable to create batch writer"); } delete payload; }; @@ -211,9 +219,13 @@ void DataAllocator::adopt(const Output& spec, std::shared_ptr<arrow::Table> ptr) auto writer = [table = ptr](std::shared_ptr<FairMQResizableBuffer> b) -> void { auto stream = std::make_shared<arrow::io::BufferOutputStream>(b); auto outBatch = arrow::ipc::NewStreamWriter(stream.get(), table->schema()); - auto outStatus = outBatch.ValueOrDie()->WriteTable(*table); - if (outStatus.ok() == false) { - throw std::runtime_error("Unable to Write table"); + if (outBatch.ok() == true) { + auto outStatus = outBatch.ValueOrDie()->WriteTable(*table); + if (outStatus.ok() == false) { + throw std::runtime_error("Unable to Write table"); + } + } else { + throw ::std::runtime_error("Unable to create batch writer"); } }; diff --git a/Framework/Core/test/test_GroupSlicer.cxx b/Framework/Core/test/test_GroupSlicer.cxx index db7fe5933c0c9..85eaa9bea87e7 100644 --- a/Framework/Core/test/test_GroupSlicer.cxx +++ b/Framework/Core/test/test_GroupSlicer.cxx @@ -290,6 +290,38 @@ BOOST_AUTO_TEST_CASE(GroupSlicerMismatchedFilteredGroups) } } +BOOST_AUTO_TEST_CASE(EmptySliceables) +{ + TableBuilder builderE; + auto evtsWriter = builderE.cursor<aod::Events>(); + for (auto i = 0; i < 20; ++i) { + evtsWriter(0, i, 0.5f * i, 2.f * i, 3.f * i); + } + auto evtTable = builderE.finalize(); + + TableBuilder builderT; + auto trksWriter = builderT.cursor<aod::TrksX>(); + auto trkTable = builderT.finalize(); + + aod::Events e{evtTable}; + aod::TrksX t{trkTable}; + BOOST_CHECK_EQUAL(e.size(), 20); + BOOST_CHECK_EQUAL(t.size(), 0); + + auto tt = std::make_tuple(t); + o2::framework::AnalysisDataProcessorBuilder::GroupSlicer g(e, tt); + + unsigned int count = 0; + for (auto& slice : g) { + auto as = slice.associatedTables(); + auto gg = slice.groupingElement(); + auto trks = std::get<aod::TrksX>(as); + BOOST_CHECK_EQUAL(gg.globalIndex(), count); + BOOST_CHECK_EQUAL(trks.size(), 0); + ++count; + } +} + BOOST_AUTO_TEST_CASE(ArrowDirectSlicing) { int counts[] = {5, 5, 5, 4, 1}; From f6d6b1123d68d06932606c88b9343ee7bd089d8e Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sat, 3 Oct 2020 08:34:24 +0200 Subject: [PATCH 0824/1751] DPL Analysis: use arrow::Table::Slice directly (#4490) --- Framework/Core/include/Framework/Kernels.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Framework/Core/include/Framework/Kernels.h b/Framework/Core/include/Framework/Kernels.h index 00fac405fc8ed..75dc919c9fd75 100644 --- a/Framework/Core/include/Framework/Kernels.h +++ b/Framework/Core/include/Framework/Kernels.h @@ -49,43 +49,37 @@ auto sliceByColumn(char const* key, auto count = 0; auto size = values.length(); - std::shared_ptr<arrow::Schema> schema(input->schema()); - std::vector<std::shared_ptr<arrow::ChunkedArray>> sliceArray; - auto injectSlice = [&](T count) { - for (auto ci = 0; ci < schema->num_fields(); ++ci) { - sliceArray.emplace_back(input->column(ci)->Slice(offset, count)); - } - slices->emplace_back(arrow::Datum(arrow::Table::Make(schema, sliceArray))); + auto makeSlice = [&](T count) { + slices->emplace_back(arrow::Datum{input->Slice(offset, count)}); if (offsets) { offsets->emplace_back(offset); } - sliceArray.clear(); }; auto current = 0; auto v = values.Value(0); while (v - current >= 1) { - injectSlice(0); + makeSlice(0); ++current; } for (auto r = 0; r < size - 1; ++r) { count = counts.Value(r); - injectSlice(count); + makeSlice(count); offset += count; auto nextValue = values.Value(r + 1); auto value = values.Value(r); while (nextValue - value > 1) { - injectSlice(0); + makeSlice(0); ++value; } } - injectSlice(counts.Value(size - 1)); + makeSlice(counts.Value(size - 1)); if (values.Value(size - 1) < fullSize - 1) { for (auto v = values.Value(size - 1) + 1; v < fullSize; ++v) { - injectSlice(0); + makeSlice(0); } } From 8b8e7c7bf1f22fb5ffa77ea0e0e18b8dd3face32 Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Sat, 3 Oct 2020 15:03:06 +0200 Subject: [PATCH 0825/1751] splitting 2 and 3 prong track preselection cuts (#4497) --- .../include/Analysis/SecondaryVertexHF.h | 5 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 69 ++++++++++++++----- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index e21df4947782c..3cd1cbff8ea26 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -25,11 +25,12 @@ namespace o2::aod { namespace seltrack { -DECLARE_SOA_COLUMN(IsSel, issel, int); +DECLARE_SOA_COLUMN(IsSel_2prong, issel_2prong, int); +DECLARE_SOA_COLUMN(IsSel_3prong, issel_3prong, 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, +DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", seltrack::IsSel_2prong, seltrack::IsSel_3prong, seltrack::DCAPrim0, seltrack::DCAPrim1); using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, SelTrack, pidRespTPC, pidRespTOF>; diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index ba0988ab0882d..3cf38eacc3b4f 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -28,44 +28,69 @@ using std::array; /// Track selection struct SelectTracks { Produces<aod::SelTrack> rowSelectedTrack; - Configurable<double> ptmintrack{"ptmintrack", -1, "ptmin single track"}; - Configurable<double> dcatoprimxymin{"dcatoprimxymin", 0, "dca xy to prim vtx min"}; + Configurable<double> ptmintrack_2prong{"ptmintrack_2prong", -1, "ptmin single track"}; + Configurable<double> dcatoprimxymin_2prong{"dcatoprimxymin_2prong", 0, "dca xy to prim vtx min"}; + Configurable<double> etamax_2prong{"etamax_2prong", 999, "maximum pseudorapidity value"}; + Configurable<double> ptmintrack_3prong{"ptmintrack_3prong", -1, "ptmin single track"}; + Configurable<double> dcatoprimxymin_3prong{"dcatoprimxymin_3prong", 0, "dca xy to prim vtx min"}; + Configurable<double> etamax_3prong{"etamax_3prong", 999, "maximum pseudorapidity value"}; Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min number of tpc cls >="}; Configurable<double> d_bz{"d_bz", 5.0, "bz field"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "pt tracks (#GeV)", 100, 0., 10.)}; - OutputObj<TH1F> hpt_cuts{TH1F("hpt_cuts", "pt tracks (#GeV)", 100, 0., 10.)}; - OutputObj<TH1F> hdcatoprimxy_cuts{TH1F("hdcatoprimxy_cuts", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; + OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "pt tracks (#GeV)", 100, 0., 10.)}; + OutputObj<TH1F> hdcatoprimxy_cuts_2prong{TH1F("hdcatoprimxy_cuts_2prong", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; + OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "pt tracks (#GeV)", 100, 0., 10.)}; + OutputObj<TH1F> hdcatoprimxy_cuts_3prong{TH1F("hdcatoprimxy_cuts_3prong", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; + OutputObj<TH1F> heta_cuts_2prong{TH1F("heta_cuts_2prong", "pseudorapidity", 100, -1.0, 1.0)}; + OutputObj<TH1F> heta_cuts_3prong{TH1F("heta_cuts_3prong", "pseudorapidity", 100, -1.0, 1.0)}; void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) { Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); for (auto& track : tracks) { - int status = 1; // selection flag + int status_2prong = 1; // selection flag + int status_3prong = 1; // selection flag if (b_dovalplots) hpt_nocuts->Fill(track.pt()); - if (track.pt() < ptmintrack) - status = 0; + if (track.pt() < ptmintrack_2prong) + status_2prong = 0; + if (track.pt() < ptmintrack_3prong) + status_3prong = 0; + if (abs(track.eta()) > etamax_2prong) + status_2prong = 0; + if (abs(track.eta()) > etamax_3prong) + status_3prong = 0; UChar_t clustermap_0 = track.itsClusterMap(); bool isselected_0 = track.tpcNClsFound() >= d_tpcnclsfound && track.flags() & 0x4; isselected_0 = isselected_0 && (TESTBIT(clustermap_0, 0) || TESTBIT(clustermap_0, 1)); - if (!isselected_0) - status = 0; + if (!isselected_0) { + status_2prong = 0; + status_3prong = 0; + } array<float, 2> dca; auto trackparvar0 = getTrackParCov(track); bool isprop = trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters - if (!isprop) - status = 0; - if (abs(dca[0]) < dcatoprimxymin) - status = 0; + if (!isprop) { + status_2prong = 0; + status_3prong = 0; + } + if (abs(dca[0]) < dcatoprimxymin_2prong) + status_2prong = 0; + if (abs(dca[0]) < dcatoprimxymin_3prong) + status_3prong = 0; if (b_dovalplots) { - if (status == 1) { - hpt_cuts->Fill(track.pt()); - hdcatoprimxy_cuts->Fill(dca[0]); + if (status_2prong == 1) { + hpt_cuts_2prong->Fill(track.pt()); + hdcatoprimxy_cuts_2prong->Fill(dca[0]); + } + if (status_3prong == 1) { + hpt_cuts_3prong->Fill(track.pt()); + hdcatoprimxy_cuts_3prong->Fill(dca[0]); } } - rowSelectedTrack(status, dca[0], dca[1]); + rowSelectedTrack(status_2prong, status_3prong, dca[0], dca[1]); } } }; @@ -95,7 +120,7 @@ struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hvtx3_y_out{TH1F("hvtx3_y", "3-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx3_z_out{TH1F("hvtx3_z", "3-track vtx", 1000, -20.0, 20.0)}; - Filter filterSelectTracks = aod::seltrack::issel == 1; + Filter filterSelectTracks = aod::seltrack::issel_2prong == 1; using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>>; // FIXME //Partition<SelectedTracks> tracksPos = aod::track::signed1Pt > 0.f; @@ -191,9 +216,15 @@ struct HFTrackIndexSkimsCreator { if (do3prong == 1) { // second loop over positive tracks //for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracksPos.end(); ++trackPos2) { + if (trackPos1.issel_3prong() == 0) + continue; + if (trackNeg1.issel_3prong() == 0) + continue; for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracks.end(); ++trackPos2) { if (trackPos2.signed1Pt() < 0) continue; + if (trackPos2.issel_3prong() == 0) + continue; // calculate invariant mass auto arr3Mom = array{ @@ -245,6 +276,8 @@ struct HFTrackIndexSkimsCreator { for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracks.end(); ++trackNeg2) { if (trackNeg2.signed1Pt() > 0) continue; + if (trackNeg2.issel_3prong() == 0) + continue; // calculate invariant mass auto arr3Mom = array{ From 2d18def9313d90650be42a546669b8a74a844b0e Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Thu, 17 Sep 2020 11:44:30 +0200 Subject: [PATCH 0826/1751] add tof device for matching with global and tpc tracks --- .../include/GlobalTracking/MatchTOF.h | 23 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 699 ++++++++++++++++-- .../tofworkflow/CMakeLists.txt | 14 +- .../TOFWorkflow/RecoWorkflowWithTPCSpec.h | 27 + .../include/TOFWorkflow/TOFCalibWriterSpec.h | 2 +- .../TOFWorkflow/TOFMatchedWriterSpec.h | 2 +- .../src/RecoWorkflowWithTPCSpec.cxx | 166 +++++ .../tofworkflow/src/TOFCalibWriterSpec.cxx | 4 +- .../tofworkflow/src/TOFMatchedWriterSpec.cxx | 4 +- .../tofworkflow/src/tof-matcher-global.cxx | 165 +++++ .../tofworkflow/src/tof-matcher-tpc.cxx | 170 +++++ .../calibration/src/TOFChannelCalibrator.cxx | 16 +- 12 files changed, 1195 insertions(+), 97 deletions(-) create mode 100644 Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/RecoWorkflowWithTPCSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowWithTPCSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 225f26075edc6..5319b0574a0db 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -73,6 +73,8 @@ class MatchTOF using Geo = o2::tof::Geo; using Cluster = o2::tof::Cluster; using evIdx = o2::dataformats::EvIndex<int, int>; + using timeEst = o2::dataformats::TimeStampWithError<float, float>; + using matchTrack = std::pair<o2::track::TrackParCov, timeEst>; public: ///< perform matching for provided input @@ -83,9 +85,11 @@ class MatchTOF ///< perform all initializations void init(); + void initTPConly(); ///< attach DPL data and run void run(const gsl::span<const o2::dataformats::TrackTPCITS>& trackArray, const gsl::span<const Cluster>& clusterArray, const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& toflab, const gsl::span<const o2::MCCompLabel>& itslab, const gsl::span<const o2::MCCompLabel>& tpclab); + void run(const gsl::span<const o2::tpc::TrackTPC>& trackArray, const gsl::span<const Cluster>& clusterArray, const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& toflab, const gsl::span<const o2::MCCompLabel>& tpclab); ///< set tree/chain containing tracks void setInputTreeTracks(TTree* tree) { mInputTreeTracks = tree; } @@ -169,8 +173,8 @@ class MatchTOF const std::string& getDebugTreeFileName() const { return mDebugTreeFileName; } ///< fill matching debug tree - void fillTOFmatchTree(const char* tname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, o2::dataformats::TrackTPCITS& trk, float intLength, float intTimePion, float timeTOF); - void fillTOFmatchTreeWithLabels(const char* tname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, o2::dataformats::TrackTPCITS& trk, int TPClabelTrackID, int TPClabelEventID, int TPClabelSourceID, int ITSlabelTrackID, int ITSlabelEventID, int ITSlabelSourceID, int TOFlabelTrackID0, int TOFlabelEventID0, int TOFlabelSourceID0, int TOFlabelTrackID1, int TOFlabelEventID1, int TOFlabelSourceID1, int TOFlabelTrackID2, int TOFlabelEventID2, int TOFlabelSourceID2, float intLength, float intTimePion, float timeTOF); + void fillTOFmatchTree(const char* tname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, matchTrack& trk, float intLength, float intTimePion, float timeTOF); + void fillTOFmatchTreeWithLabels(const char* tname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, matchTrack& trk, int TPClabelTrackID, int TPClabelEventID, int TPClabelSourceID, int ITSlabelTrackID, int ITSlabelEventID, int ITSlabelSourceID, int TOFlabelTrackID0, int TOFlabelEventID0, int TOFlabelSourceID0, int TOFlabelTrackID1, int TOFlabelEventID1, int TOFlabelSourceID1, int TOFlabelTrackID2, int TOFlabelEventID2, int TOFlabelSourceID2, float intLength, float intTimePion, float timeTOF); void dumpWinnerMatches(); std::vector<o2::dataformats::MatchInfoTOF>& getMatchedTrackVector() { return mMatchedTracks; } @@ -197,12 +201,16 @@ class MatchTOF private: void attachInputTrees(); + void attachInputTreesTPConly(); bool prepareTracks(); + bool prepareTPCTracks(); bool prepareTOFClusters(); bool loadTracksNextChunk(); + bool loadTPCTracksNextChunk(); bool loadTOFClustersNextChunk(); void doMatching(int sec); + void doMatchingForTPC(int sec); void selectBestMatches(); bool propagateToRefX(o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, o2::track::TrackLTIntegral& intLT); bool propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, float bz); @@ -233,6 +241,8 @@ class MatchTOF TTree* mTreeTPCTracks = nullptr; ///< input tree for TPC tracks TTree* mTreeTOFClusters = nullptr; ///< input tree for TOF clusters + bool mIsITSused = true; + TTree* mOutputTree = nullptr; ///< output tree for matched tracks TTree* mOutputTreeCalib = nullptr; ///< output tree for calibration infos @@ -241,7 +251,8 @@ class MatchTOF // since this info is provided by external device gsl::span<const o2::dataformats::TrackTPCITS> mTracksArrayInp; ///< input tracks std::vector<o2::dataformats::TrackTPCITS>* mTracksArrayInpVect; ///< input tracks (vector to read from tree) - std::vector<o2::tpc::TrackTPC> mTPCTracksArrayInp; ///< input TPC tracks + gsl::span<const o2::tpc::TrackTPC> mTPCTracksArrayInp; ///< input TPC tracks + std::vector<o2::tpc::TrackTPC>* mTPCTracksArrayInpVect; ///< input tracks (vector to read from tree) gsl::span<const Cluster> mTOFClustersArrayInp; ///< input TOF clusters std::vector<Cluster>* mTOFClustersArrayInpVect; ///< input TOF clusters (vector to read from tree) @@ -259,11 +270,14 @@ class MatchTOF /// <<<----- ///<working copy of the input tracks - std::vector<o2::dataformats::TrackTPCITS> mTracksWork; ///<track params prepared for matching + std::vector<matchTrack> mTracksWork; ///<track params prepared for matching + time value + std::vector<o2::track::TrackLTIntegral> mLTinfos; ///<expected times and others std::vector<Cluster> mTOFClusWork; ///<track params prepared for matching ///< per sector indices of track entry in mTracksWork std::array<std::vector<int>, o2::constants::math::NSectors> mTracksSectIndexCache; + ///< per sector indices of track entry in mTPCTracksWork + std::array<std::vector<int>, o2::constants::math::NSectors> mTPCTracksSectIndexCache; ///< per sector indices of TOF cluster entry in mTOFClusWork std::array<std::vector<int>, o2::constants::math::NSectors> mTOFClusSectIndexCache; @@ -296,6 +310,7 @@ class MatchTOF std::string mOutTOFMCTruthBranchName = "MatchTOFMCTruth"; ///< name of branch containing TOF labels for output matched tracks std::string mOutTPCMCTruthBranchName = "MatchTPCMCTruth"; ///< name of branch containing TOF labels for output matched tracks std::string mOutITSMCTruthBranchName = "MatchITSMCTruth"; ///< name of branch containing TOF labels for output matched tracks + std::string mOutTPCTrackMCTruthBranchName = "TracksMCTruth"; ///< name of branch containing TPC labels for input TPC tracks std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut; UInt_t mDBGFlags = 0; diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 0afa155d8f395..785cc53968909 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -36,8 +36,10 @@ #include "GlobalTracking/MatchTOF.h" #include "GlobalTracking/MatchTPCITS.h" +#include "TPCBase/ParameterGas.h" +#include "TPCBase/ParameterElectronics.h" + using namespace o2::globaltracking; -using timeEst = o2::dataformats::TimeStampWithError<float, float>; using evIdx = o2::dataformats::EvIndex<int, int>; ClassImp(MatchTOF); @@ -62,11 +64,16 @@ void MatchTOF::run() if (mIsworkflowON) { LOG(DEBUG) << "Number of entries in track tree = " << mCurrTracksTreeEntry; + + if (mIsITSused) + prepareTracks(); + else + prepareTPCTracks(); + mMatchedTracks.clear(); mOutTOFLabels.clear(); mOutTPCLabels.clear(); mOutITSLabels.clear(); - prepareTracks(); mTimerTot.Stop(); LOGF(INFO, "Timing prepare tracks: Cpu: %.3e s Real: %.3e s in %d slots", mTimerTot.CpuTime(), mTimerTot.RealTime(), mTimerTot.Counter() - 1); @@ -74,61 +81,47 @@ void MatchTOF::run() for (int sec = o2::constants::math::NSectors; sec--;) { LOG(INFO) << "Doing matching for sector " << sec << "..."; - doMatching(sec); + if (mIsITSused) + doMatching(sec); + else + doMatchingForTPC(sec); LOG(INFO) << "...done. Now check the best matches"; selectBestMatches(); } - if (0) { // enabling this creates very verbose output - mTimerTot.Stop(); - printCandidatesTOF(); - mTimerTot.Start(false); - } } // we do the matching per entry of the TPCITS matched tracks tree while (!mIsworkflowON && mCurrTracksTreeEntry + 1 < mInputTreeTracks->GetEntries()) { // we add "+1" because mCurrTracksTreeEntry starts from -1, and it is incremented in loadTracksNextChunk which is called by prepareTracks LOG(DEBUG) << "Number of entries in track tree = " << mCurrTracksTreeEntry; + + if (mIsITSused) + prepareTracks(); + else + prepareTPCTracks(); + mMatchedTracks.clear(); mOutTOFLabels.clear(); mOutTPCLabels.clear(); mOutITSLabels.clear(); - prepareTracks(); mTimerTot.Stop(); LOGF(INFO, "Timing prepare tracks: Cpu: %.3e s Real: %.3e s in %d slots", mTimerTot.CpuTime(), mTimerTot.RealTime(), mTimerTot.Counter() - 1); mTimerTot.Start(); - /* Uncomment for local debug - Printf("*************** Printing the tracks before starting the matching"); - - // printing the tracks - std::array<float, 3> globalPosTmp; - int totTracks = 0; - - for (int sec = o2::constants::math::NSectors; sec--;) { - Printf("\nsector %d", sec); - auto& cacheTrkTmp = mTracksSectIndexCache[sec]; // array of cached tracks indices for this sector; reminder: they are ordered in time! - for (int itrk = 0; itrk < cacheTrkTmp.size(); itrk++){ - auto& trc = mTracksWork[cacheTrkTmp[itrk]]; - trc.getXYZGlo(globalPosTmp); - LOG(INFO) << "Track" << totTracks << " [in this sector it is the " << itrk << "]: Global coordinates After propagating to 371 cm: globalPos[0] = " << globalPosTmp[0] << ", globalPos[1] = " << globalPosTmp[1] << ", globalPos[2] = " << globalPosTmp[2]; - LOG(INFO) << "The phi angle is " << TMath::ATan2(globalPosTmp[1], globalPosTmp[0]); - totTracks++; - } - } - */ - for (int sec = o2::constants::math::NSectors; sec--;) { LOG(INFO) << "Doing matching for sector " << sec << "..."; - doMatching(sec); + if (mIsITSused) + doMatching(sec); + else + doMatchingForTPC(sec); LOG(INFO) << "...done. Now check the best matches"; selectBestMatches(); } - if (0) { // enabling this creates very verbose output - mTimerTot.Stop(); - printCandidatesTOF(); - mTimerTot.Start(false); - } + + mTimerTot.Stop(); + LOGF(INFO, "Timing Do Matching: Cpu: %.3e s Real: %.3e s in %d slots", mTimerTot.CpuTime(), mTimerTot.RealTime(), mTimerTot.Counter() - 1); + mTimerTot.Start(); + fill(); } @@ -154,6 +147,7 @@ void MatchTOF::fill() //______________________________________________ void MatchTOF::run(const gsl::span<const o2::dataformats::TrackTPCITS>& trackArray, const gsl::span<const Cluster>& clusterArray, const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& toflab, const gsl::span<const o2::MCCompLabel>& itslab, const gsl::span<const o2::MCCompLabel>& tpclab) { + mIsITSused = true; mTracksArrayInp = trackArray; mTOFClustersArrayInp = clusterArray; mIsworkflowON = kTRUE; @@ -166,11 +160,27 @@ void MatchTOF::run(const gsl::span<const o2::dataformats::TrackTPCITS>& trackArr mSAInitDone = true; run(); } +//______________________________________________ +void MatchTOF::run(const gsl::span<const o2::tpc::TrackTPC>& trackArray, const gsl::span<const Cluster>& clusterArray, const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& toflab, const gsl::span<const o2::MCCompLabel>& tpclab) +{ + mIsITSused = false; + mTPCTracksArrayInp = trackArray; + mTOFClustersArrayInp = clusterArray; + mIsworkflowON = kTRUE; + mTOFClusLabels = toflab; + mTPCLabels = tpclab; + mMCTruthON = (mTOFClusLabels.getNElements() && mTPCLabels.size()); + mWFInputAttached = true; + mSAInitDone = true; + + run(); +} //______________________________________________ void MatchTOF::init() { ///< initizalizations + mIsITSused = true; if (mSAInitDone) { LOG(ERROR) << "Initialization was already done"; @@ -184,16 +194,70 @@ void MatchTOF::init() LOG(INFO) << "Matched tracks will be stored in " << mOutTracksBranchName << " branch of tree " << mOutputTree->GetName(); if (mMCTruthON) { - mOutputTree->Branch(mOutTPCMCTruthBranchName.data(), &mOutTPCLabels); - LOG(INFO) << "ITS Tracks Labels branch: " << mOutITSMCTruthBranchName; mOutputTree->Branch(mOutITSMCTruthBranchName.data(), &mOutITSLabels); + LOG(INFO) << "ITS Tracks Labels branch: " << mOutITSMCTruthBranchName; + mOutputTree->Branch(mOutTPCMCTruthBranchName.data(), &mOutTPCLabels); + LOG(INFO) << "TPC Tracks Labels branch: " << mOutTPCMCTruthBranchName; + mOutputTree->Branch(mOutTOFMCTruthBranchName.data(), &mOutTOFLabels); + LOG(INFO) << "TOF Tracks Labels branch: " << mOutTOFMCTruthBranchName; + } + + } else { + LOG(INFO) << "Output tree is not attached, matched tracks will not be stored"; + } + + // create output branch for calibration info + if (mOutputTreeCalib) { + mOutputTreeCalib->Branch(mOutCalibBranchName.data(), &mCalibInfoTOF); + LOG(INFO) << "Calib infos will be stored in " << mOutCalibBranchName << " branch of tree " + << mOutputTreeCalib->GetName(); + } else { + LOG(INFO) << "Calib Output tree is not attached, calib infos will not be stored"; + } + +#ifdef _ALLOW_TOF_DEBUG_ + // debug streamer + if (mDBGFlags) { + mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugTreeFileName.data(), "recreate"); + } +#endif + + mSAInitDone = true; + + { + mTimerTot.Stop(); + mTimerTot.Reset(); + } + + print(); +} +//______________________________________________ +void MatchTOF::initTPConly() +{ + ///< initizalizations + + mIsITSused = false; + + if (mSAInitDone) { + LOG(ERROR) << "Initialization was already done"; + return; + } + attachInputTreesTPConly(); + + // create output branch with track-tof matching + if (mOutputTree) { + mOutputTree->Branch(mOutTracksBranchName.data(), &mMatchedTracks); + LOG(INFO) << "Matched tracks will be stored in " << mOutTracksBranchName << " branch of tree " + << mOutputTree->GetName(); + if (mMCTruthON) { + mOutputTree->Branch(mOutTPCMCTruthBranchName.data(), &mOutTPCLabels); LOG(INFO) << "TPC Tracks Labels branch: " << mOutTPCMCTruthBranchName; mOutputTree->Branch(mOutTOFMCTruthBranchName.data(), &mOutTOFLabels); LOG(INFO) << "TOF Tracks Labels branch: " << mOutTOFMCTruthBranchName; } } else { - LOG(ERROR) << "Output tree is not attached, matched tracks will not be stored"; + LOG(INFO) << "Output tree is not attached, matched tracks will not be stored"; } // create output branch for calibration info @@ -252,15 +316,11 @@ void MatchTOF::attachInputTrees() LOG(FATAL) << "Input tree with tracks is not set"; } - if (!mTreeTPCTracks) { - LOG(FATAL) << "TPC tracks data input tree is not set"; - } - if (!mTreeTOFClusters) { LOG(FATAL) << "TOF clusters data input tree is not set"; } - // input tracks (this is the pais of ITS-TPC matches) + // input tracks (this is the pairs of ITS-TPC matches) if (!mInputTreeTracks->GetBranch(mTracksBranchName.data())) { LOG(FATAL) << "Did not find tracks branch " << mTracksBranchName << " in the input tree"; @@ -299,6 +359,54 @@ void MatchTOF::attachInputTrees() mCurrTracksTreeEntry = -1; mCurrTOFClustersTreeEntry = -1; } +//______________________________________________ +void MatchTOF::attachInputTreesTPConly() +{ + ///< attaching the input tree + LOG(DEBUG) << "attachInputTrees"; + + if (!mTreeTPCTracks) { + LOG(FATAL) << "TPC tracks data input tree is not set"; + } + + if (!mTreeTOFClusters) { + LOG(FATAL) << "TOF clusters data input tree is not set"; + } + + // input tracks (this is the TPC tracks) + + if (!mTreeTPCTracks->GetBranch(mTPCTracksBranchName.data())) { + LOG(FATAL) << "Did not find tracks branch " << mTPCTracksBranchName << " in the input tree"; + } + mTreeTPCTracks->SetBranchAddress(mTPCTracksBranchName.data(), &mTPCTracksArrayInpVect); + LOG(INFO) << "Attached tracks " << mTPCTracksBranchName << " branch with " << mTreeTPCTracks->GetEntries() + << " entries"; + + // input TOF clusters + + if (!mTreeTOFClusters->GetBranch(mTOFClusterBranchName.data())) { + LOG(FATAL) << "Did not find TOF clusters branch " << mTOFClusterBranchName << " in the input tree"; + } + mTreeTOFClusters->SetBranchAddress(mTOFClusterBranchName.data(), &mTOFClustersArrayInpVect); + LOG(INFO) << "Attached TOF clusters " << mTOFClusterBranchName << " branch with " << mTreeTOFClusters->GetEntries() + << " entries"; + // is there MC info available ? + mMCTruthON = true; + if (mTreeTOFClusters->GetBranch(mTOFMCTruthBranchName.data())) { + mTOFClusLabelsPtr = &mTOFClusLabels; + mTreeTOFClusters->SetBranchAddress(mTOFMCTruthBranchName.data(), &mTOFClusLabelsPtr); + LOG(INFO) << "Found TOF Clusters MCLabels branch " << mTOFMCTruthBranchName; + } else + mMCTruthON = false; + if (mTreeTPCTracks->GetBranch(mOutTPCTrackMCTruthBranchName.data())) { + mTreeTPCTracks->SetBranchAddress(mOutTPCTrackMCTruthBranchName.data(), &mTPCLabelsVect); + LOG(INFO) << "Found TPC tracks MCLabels branch " << mOutTPCTrackMCTruthBranchName; + } else + mMCTruthON = false; + + mCurrTracksTreeEntry = -1; + mCurrTOFClustersTreeEntry = -1; +} //______________________________________________ bool MatchTOF::prepareTracks() @@ -317,7 +425,9 @@ bool MatchTOF::prepareTracks() // copy the track params, propagate to reference X and build sector tables mTracksWork.clear(); + mLTinfos.clear(); mTracksWork.reserve(mNumOfTracks); + mLTinfos.reserve(mNumOfTracks); if (mMCTruthON) { mTracksLblWork.clear(); mTracksLblWork.reserve(mNumOfTracks); @@ -330,6 +440,7 @@ bool MatchTOF::prepareTracks() // getting Bz (mag field) auto o2field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); float bzField = o2field->solenoidField(); // magnetic field in kGauss + float maxInvPt = abs(bzField) > 0.1 ? 1. / (abs(bzField) * 0.05) : 999.; LOG(DEBUG) << "\n\nWe have %d tracks to try to match to TOF: " << mNumOfTracks; int nNotPropagatedToTOF = 0; @@ -338,12 +449,13 @@ bool MatchTOF::prepareTracks() std::array<float, 3> globalPos; // create working copy of track param - mTracksWork.emplace_back(trcOrig); //, mCurrTracksTreeEntry, it); + mTracksWork.emplace_back(std::make_pair(trcOrig.getParamOut(), trcOrig.getTimeMUS())); //, mCurrTracksTreeEntry, it); + mLTinfos.emplace_back(trcOrig.getLTIntegralOut()); // make a copy of the TPC track that we have to propagate //o2::tpc::TrackTPC* trc = new o2::tpc::TrackTPC(trcTPCOrig); // this would take the TPCout track //auto& trc = mTracksWork.back(); // with this we take the TPCITS track propagated to the vertex - auto& trc = mTracksWork.back().getParamOut(); // with this we take the TPCITS track propagated to the vertex - auto& intLT = mTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation + auto& trc = mTracksWork.back().first; // with this we take the TPCITS track propagated to the vertex + auto& intLT = mLTinfos.back(); // we get the integrated length from TPC-ITC outward propagation if (trc.getX() < o2::globaltracking::MatchTPCITS::XTPCOuterRef - 1.) { // tpc-its track outward propagation did not reach outer ref.radius, skip this track nNotPropagatedToTOF++; @@ -386,9 +498,146 @@ bool MatchTOF::prepareTracks() if (!indexCache.size()) continue; std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { - auto& trcA = mTracksWork[a]; - auto& trcB = mTracksWork[b]; - return ((trcA.getTimeMUS().getTimeStamp() - mSigmaTimeCut * trcA.getTimeMUS().getTimeStampError()) - (trcB.getTimeMUS().getTimeStamp() - mSigmaTimeCut * trcB.getTimeMUS().getTimeStampError()) < 0.); + auto& trcA = mTracksWork[a].second; + auto& trcB = mTracksWork[b].second; + return ((trcA.getTimeStamp() - mSigmaTimeCut * trcA.getTimeStampError()) - (trcB.getTimeStamp() - mSigmaTimeCut * trcB.getTimeStampError()) < 0.); + }); + } // loop over tracks of single sector + + // Uncomment for local debug + /* + // printing the tracks + std::array<float, 3> globalPos; + int itmp = 0; + for (int sec = o2::constants::math::NSectors; sec--;) { + Printf("sector %d", sec); + auto& cacheTrk = mTracksSectIndexCache[sec]; // array of cached tracks indices for this sector; reminder: they are ordered in time! + for (int itrk = 0; itrk < cacheTrk.size(); itrk++){ + itmp++; + auto& trc = mTracksWork[cacheTrk[itrk]]; + trc.getXYZGlo(globalPos); + printf("Track %d: Global coordinates After propagating to 371 cm: globalPos[0] = %f, globalPos[1] = %f, globalPos[2] = %f\n", itrk, globalPos[0], globalPos[1], globalPos[2]); + // Printf("The phi angle is %f", TMath::ATan2(globalPos[1], globalPos[0])); + } + } + Printf("we have %d tracks",itmp); + */ + + return true; +} +//______________________________________________ +bool MatchTOF::prepareTPCTracks() +{ + ///< prepare the tracks that we want to match to TOF + + if (!mIsworkflowON && !loadTPCTracksNextChunk()) { + return false; + } + + mNumOfTracks = mTPCTracksArrayInp.size(); + if (mNumOfTracks == 0) + return false; // no tracks to be matched + mMatchedTracksIndex.resize(mNumOfTracks); + std::fill(mMatchedTracksIndex.begin(), mMatchedTracksIndex.end(), -1); // initializing all to -1 + + // copy the track params, propagate to reference X and build sector tables + mTracksWork.clear(); + mTracksWork.reserve(mNumOfTracks); + + for (int sec = o2::constants::math::NSectors; sec--;) { + mTPCTracksSectIndexCache[sec].clear(); + mTPCTracksSectIndexCache[sec].reserve(100 + 1.2 * mNumOfTracks / o2::constants::math::NSectors); + } + + // getting Bz (mag field) + auto o2field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); + float bzField = o2field->solenoidField(); // magnetic field in kGauss + float maxInvPt = abs(bzField) > 0.1 ? 1. / (abs(bzField) * 0.05) : 999.; + int nclustersMin = 0; + LOG(INFO) << "Max track Inv pT allowed = " << maxInvPt; + LOG(INFO) << "Min track Nclusters allowed = " << nclustersMin; + + LOG(DEBUG) << "\n\nWe have %d tracks to try to match to TOF: " << mNumOfTracks; + int nNotPropagatedToTOF = 0; + for (int it = 0; it < mNumOfTracks; it++) { + const o2::tpc::TrackTPC& trcOrig = mTPCTracksArrayInp[it]; // TODO: check if we cannot directly use the o2::track::TrackParCov class instead of o2::dataformats::TrackTPCITS, and then avoid the casting below; this is the track at the vertex + std::array<float, 3> globalPos; + + // create working copy of track param + timeEst timeInfo; + // set + timeInfo.setTimeStamp(trcOrig.getTime0() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); + timeInfo.setTimeStampError(trcOrig.getDeltaTBwd() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); + o2::track::TrackLTIntegral intLT0; //mTPCTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation + // make a copy of the TPC track that we have to propagate + //o2::tpc::TrackTPC* trc = new o2::tpc::TrackTPC(trcTPCOrig); // this would take the TPCout track + mTracksWork.emplace_back(std::make_pair(trcOrig.getOuterParam(), timeInfo)); + auto& trc = mTracksWork.back().first; + auto& intLT = mLTinfos.emplace_back(intLT0); + + if (trcOrig.getNClusters() < nclustersMin) { + nNotPropagatedToTOF++; + continue; + } + + if (std::abs(trc.getQ2Pt()) > maxInvPt) { // tpc-its track outward propagation did not reach outer ref.radius, skip this track + nNotPropagatedToTOF++; + continue; + } + + // printf("N clusters = %d\n",trcOrig.getNClusters()); + +#ifdef _ALLOW_TOF_DEBUG_ + // propagate to matching Xref + trc.getXYZGlo(globalPos); + LOG(INFO) << "Global coordinates Before propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; + LOG(INFO) << "Radius xy Before propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); + LOG(INFO) << "Radius xyz Before propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); + // the "very rough" propagation worked; now we can propagate considering also the cov matrix +#endif + + if (!propagateToRefXWithoutCov(trc, mXRef, 10, bzField)) { // we first propagate to 371 cm without considering the covariance matrix + nNotPropagatedToTOF++; + continue; + } + + if (trc.getX() < o2::globaltracking::MatchTPCITS::XTPCOuterRef - 1.) + if (!propagateToRefX(trc, o2::globaltracking::MatchTPCITS::XTPCOuterRef, 10, intLT) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happen that it does not if the propagation without the errors succeeded? + nNotPropagatedToTOF++; + continue; + } + + // the "rough" propagation worked; now we can propagate considering also the cov matrix + if (!propagateToRefX(trc, mXRef, 2, intLT) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happen that it does not if the propagation without the errors succeeded? + nNotPropagatedToTOF++; + continue; + } + + trc.getXYZGlo(globalPos); + +#ifdef _ALLOW_TOF_DEBUG_ + LOG(INFO) << "Global coordinates After propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; + LOG(INFO) << "Radius xy After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); + LOG(INFO) << "Radius xyz After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); + LOG(INFO) << "The track will go to sector " << o2::utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); +#endif + + mTracksSectIndexCache[o2::utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); + //delete trc; // Check: is this needed? + } + + LOG(INFO) << "Total number of tracks = " << mNumOfTracks << ", Number of tracks that failed to be propagated to TOF = " << nNotPropagatedToTOF; + + // sort tracks in each sector according to their time (increasing in time) + for (int sec = o2::constants::math::NSectors; sec--;) { + auto& indexCache = mTracksSectIndexCache[sec]; + LOG(INFO) << "Sorting sector" << sec << " | " << indexCache.size() << " tracks"; + if (!indexCache.size()) + continue; + std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { + auto& trcA = mTracksWork[a].second; + auto& trcB = mTracksWork[b].second; + return ((trcA.getTimeStamp() - trcA.getTimeStampError()) - (trcB.getTimeStamp() - trcB.getTimeStampError()) < 0.); }); } // loop over tracks of single sector @@ -504,6 +753,23 @@ bool MatchTOF::loadTracksNextChunk() --mCurrTracksTreeEntry; return false; } +//_____________________________________________________ +bool MatchTOF::loadTPCTracksNextChunk() +{ + ///< load next chunk of tracks to be matched to TOF + while (++mCurrTracksTreeEntry < mTreeTPCTracks->GetEntries()) { + mTreeTPCTracks->GetEntry(mCurrTracksTreeEntry); + mTPCTracksArrayInp = gsl::span<const o2::tpc::TrackTPC>{*mTPCTracksArrayInpVect}; + LOG(INFO) << "Loading TPC tracks entry " << mCurrTracksTreeEntry << " -> " << mTPCTracksArrayInp.size() + << " tracks"; + if (!mTPCTracksArrayInp.size()) { + continue; + } + return true; + } + --mCurrTracksTreeEntry; + return false; +} //______________________________________________ bool MatchTOF::loadTOFClustersNextChunk() { @@ -528,22 +794,10 @@ bool MatchTOF::loadTOFClustersNextChunk() //______________________________________________ void MatchTOF::doMatching(int sec) { + ///< do the real matching per sector mMatchedTracksPairs.clear(); // new sector - //uncomment for local debug - /* - // printing the tracks - std::array<float, 3> globalPosTmp; - Printf("sector %d", sec); - auto& cacheTrkTmp = mTracksSectIndexCache[sec]; // array of cached tracks indices for this sector; reminder: they are ordered in time! - for (int itrk = 0; itrk < cacheTrkTmp.size(); itrk++){ - auto& trc = mTracksWork[cacheTrkTmp[itrk]]; - trc.getXYZGlo(globalPosTmp); - printf("Track %d: Global coordinates After propagating to 371 cm: globalPos[0] = %f, globalPos[1] = %f, globalPos[2] = %f\n", itrk, globalPosTmp[0], globalPosTmp[1], globalPosTmp[2]); - Printf("The phi angle is %f", TMath::ATan2(globalPosTmp[1], globalPosTmp[0])); - } - */ auto& cacheTOF = mTOFClusSectIndexCache[sec]; // array of cached TOF cluster indices for this sector; reminder: they are ordered in time! auto& cacheTrk = mTracksSectIndexCache[sec]; // array of cached tracks indices for this sector; reminder: they are ordered in time! int nTracks = cacheTrk.size(), nTOFCls = cacheTOF.size(); @@ -561,6 +815,8 @@ void MatchTOF::doMatching(int sec) std::array<float, 3> posBeforeProp; float posFloat[3]; + // prematching for TPC only tracks (identify BC candidate to correct z for TPC track accordingly to v_drift) + LOG(DEBUG) << "Trying to match %d tracks" << cacheTrk.size(); for (int itrk = 0; itrk < cacheTrk.size(); itrk++) { for (int ii = 0; ii < 2; ii++) { @@ -569,11 +825,12 @@ void MatchTOF::doMatching(int sec) } int nStripsCrossedInPropagation = 0; // how many strips were hit during the propagation auto& trackWork = mTracksWork[cacheTrk[itrk]]; - auto& trefTrk = trackWork.getParamOut(); - auto& intLT = trackWork.getLTIntegralOut(); + auto& trefTrk = trackWork.first; + auto& intLT = mLTinfos[cacheTrk[itrk]]; + // Printf("intLT (before doing anything): length = %f, time (Pion) = %f", intLT.getL(), intLT.getTOF(o2::track::PID::Pion)); - float minTrkTime = (trackWork.getTimeMUS().getTimeStamp() - mSigmaTimeCut * trackWork.getTimeMUS().getTimeStampError()) * 1.E6; // minimum time in ps - float maxTrkTime = (trackWork.getTimeMUS().getTimeStamp() + mSigmaTimeCut * trackWork.getTimeMUS().getTimeStampError()) * 1.E6; // maximum time in ps + float minTrkTime = (trackWork.second.getTimeStamp() - mSigmaTimeCut * trackWork.second.getTimeStampError()) * 1.E6; // minimum time in ps + float maxTrkTime = (trackWork.second.getTimeStamp() + mSigmaTimeCut * trackWork.second.getTimeStampError()) * 1.E6; // maximum time in ps int istep = 1; // number of steps float step = 1.0; // step size in cm //uncomment for local debug @@ -756,10 +1013,11 @@ void MatchTOF::doMatching(int sec) if (trefTOF.isBitSet(Cluster::kDownRight)) posCorr[0] -= Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; + float ndifInv = 1. / ndigits; if (ndigits > 1) { - posCorr[0] /= ndigits; - posCorr[1] /= ndigits; - posCorr[2] /= ndigits; + posCorr[0] *= ndifInv; + posCorr[1] *= ndifInv; + posCorr[2] *= ndifInv; } int trackIdTOF; @@ -838,6 +1096,290 @@ void MatchTOF::doMatching(int sec) return; } //______________________________________________ +void MatchTOF::doMatchingForTPC(int sec) +{ + + auto& gasParam = o2::tpc::ParameterGas::Instance(); + float vdrift = gasParam.DriftV; + + ///< do the real matching per sector + mMatchedTracksPairs.clear(); // new sector + + auto& cacheTOF = mTOFClusSectIndexCache[sec]; // array of cached TOF cluster indices for this sector; reminder: they are ordered in time! + auto& cacheTrk = mTracksSectIndexCache[sec]; // array of cached tracks indices for this sector; reminder: they are ordered in time! + int nTracks = cacheTrk.size(), nTOFCls = cacheTOF.size(); + LOG(INFO) << "Matching sector " << sec << ": number of tracks: " << nTracks << ", number of TOF clusters: " << nTOFCls; + if (!nTracks || !nTOFCls) { + return; + } + int itof0 = 0; // starting index in TOF clusters for matching of the track + int detId[2][5]; // at maximum one track can fall in 2 strips during the propagation; the second dimention of the array is the TOF det index + float deltaPos[2][3]; // at maximum one track can fall in 2 strips during the propagation; the second dimention of the array is the residuals + o2::track::TrackLTIntegral trkLTInt[2]; // Here we store the integrated track length and time for the (max 2) matched strips + int nStepsInsideSameStrip[2] = {0, 0}; // number of propagation steps in the same strip (since we have maximum 2 strips, it has dimention = 2) + float deltaPosTemp[3]; + std::array<float, 3> pos; + std::array<float, 3> posBeforeProp; + float posFloat[3]; + + // prematching for TPC only tracks (identify BC candidate to correct z for TPC track accordingly to v_drift) + + std::vector<ulong> BCcand; + + LOG(DEBUG) << "Trying to match %d tracks" << cacheTrk.size(); + for (int itrk = 0; itrk < cacheTrk.size(); itrk++) { + int nStripsCrossedInPropagation = 0; // how many strips were hit during the propagation + auto& trackWork = mTracksWork[cacheTrk[itrk]]; + auto& trefTrk = trackWork.first; + auto& intLT = mLTinfos[cacheTrk[itrk]]; + + int nBCcand = 1; + BCcand.clear(); + BCcand.reserve(nBCcand); + + int side = (trefTrk.getZ() > 0) ? 1 : -1; + + // look at BC candidates for the track + itof0 = 0; + double minTrkTime = (trackWork.second.getTimeStamp() - trackWork.second.getTimeStampError()) * 1.E6; // minimum time in ps + double maxTrkTime = (trackWork.second.getTimeStamp() + trackWork.second.getTimeStampError()) * 1.E6; // maximum time in ps + for (auto itof = itof0; itof < nTOFCls; itof++) { + auto& trefTOF = mTOFClusWork[cacheTOF[itof]]; + + if (trefTOF.getTime() < minTrkTime) { // this cluster has a time that is too small for the current track, we will get to the next one + itof0 = itof + 1; + continue; + } + + if (trefTOF.getTime() > maxTrkTime) { // this cluster has a time that is too large for the current track, close loop + break; + } + + if (trefTOF.getZ() * side < 0) + continue; + + long bc = long(trefTOF.getTime() * Geo::BC_TIME_INPS_INV); + + bool isalreadyin = false; + + for (int k = 0; k < BCcand.size(); k++) + if (bc == BCcand[k]) + isalreadyin = true; + + if (!isalreadyin) + BCcand.emplace_back(bc); + } + + for (int ii = 0; ii < 2; ii++) { + detId[ii][2] = -1; // before trying to match, we need to inizialize the detId corresponding to the strip number to -1; this is the array that we will use to save the det id of the maximum 2 strips matched + nStepsInsideSameStrip[ii] = 0; + } + + // printf("%d) ts_error = %f -- z_error = %f\n", itrk, trackWork.second.getTimeStampError(), trackWork.second.getTimeStampError() * vdrift); + + // Printf("intLT (before doing anything): length = %f, time (Pion) = %f", intLT.getL(), intLT.getTOF(o2::track::PID::Pion)); + int istep = 1; // number of steps + float step = 1.0; // step size in cm + //uncomment for local debug + /* + //trefTrk.getXYZGlo(posBeforeProp); + //float posBeforeProp[3] = {trefTrk.getX(), trefTrk.getY(), trefTrk.getZ()}; // in local ref system + //printf("Global coordinates: posBeforeProp[0] = %f, posBeforeProp[1] = %f, posBeforeProp[2] = %f\n", posBeforeProp[0], posBeforeProp[1], posBeforeProp[2]); + //Printf("Radius xy = %f", TMath::Sqrt(posBeforeProp[0]*posBeforeProp[0] + posBeforeProp[1]*posBeforeProp[1])); + //Printf("Radius xyz = %f", TMath::Sqrt(posBeforeProp[0]*posBeforeProp[0] + posBeforeProp[1]*posBeforeProp[1] + posBeforeProp[2]*posBeforeProp[2])); + */ + +#ifdef _ALLOW_TOF_DEBUG_ + if (mDBGFlags) { + (*mDBGOut) << "propOK" + << "track=" << trefTrk << "\n"; + } +#endif + + // initializing + for (int ii = 0; ii < 2; ii++) { + for (int iii = 0; iii < 5; iii++) { + detId[ii][iii] = -1; + } + } + + int detIdTemp[5] = {-1, -1, -1, -1, -1}; // TOF detector id at the current propagation point + + double reachedPoint = mXRef + istep * step; + + while (propagateToRefX(trefTrk, reachedPoint, step, intLT) && nStripsCrossedInPropagation <= 2 && reachedPoint < Geo::RMAX) { + // while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trefTrk, mXRef + istep * step, o2::constants::physics::MassPionCharged, MAXSNP, step, 1, &intLT) && nStripsCrossedInPropagation <= 2 && mXRef + istep * step < Geo::RMAX) { + + trefTrk.getXYZGlo(pos); + for (int ii = 0; ii < 3; ii++) { // we need to change the type... + posFloat[ii] = pos[ii]; + } + // uncomment below only for local debug; this will produce A LOT of output - one print per propagation step + /* + Printf("posFloat[0] = %f, posFloat[1] = %f, posFloat[2] = %f", posFloat[0], posFloat[1], posFloat[2]); + Printf("radius xy = %f", TMath::Sqrt(posFloat[0]*posFloat[0] + posFloat[1]*posFloat[1])); + Printf("radius xyz = %f", TMath::Sqrt(posFloat[0]*posFloat[0] + posFloat[1]*posFloat[1] + posFloat[2]*posFloat[2])); + */ + + for (int idet = 0; idet < 5; idet++) + detIdTemp[idet] = -1; + + Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp); + + if (detIdTemp[2] == -1) { + reachedPoint += step; + continue; + } + + if (nStripsCrossedInPropagation == 0 || // we are crossing a strip for the first time... + (nStripsCrossedInPropagation >= 1 && (detId[nStripsCrossedInPropagation - 1][0] != detIdTemp[0] || detId[nStripsCrossedInPropagation - 1][1] != detIdTemp[1] || detId[nStripsCrossedInPropagation - 1][2] != detIdTemp[2]))) { // ...or we are crossing a new strip + if (nStripsCrossedInPropagation == 0) + // LOG(DEBUG) << "We cross a strip for the first time"; + if (nStripsCrossedInPropagation == 2) { + break; // we have already matched 2 strips, we cannot match more + } + nStripsCrossedInPropagation++; + } + //Printf("nStepsInsideSameStrip[nStripsCrossedInPropagation-1] = %d", nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]); + if (nStepsInsideSameStrip[nStripsCrossedInPropagation - 1] == 0) { + detId[nStripsCrossedInPropagation - 1][0] = detIdTemp[0]; + detId[nStripsCrossedInPropagation - 1][1] = detIdTemp[1]; + detId[nStripsCrossedInPropagation - 1][2] = detIdTemp[2]; + detId[nStripsCrossedInPropagation - 1][3] = detIdTemp[3]; + detId[nStripsCrossedInPropagation - 1][4] = detIdTemp[4]; + deltaPos[nStripsCrossedInPropagation - 1][0] = deltaPosTemp[0]; + deltaPos[nStripsCrossedInPropagation - 1][1] = deltaPosTemp[1]; + deltaPos[nStripsCrossedInPropagation - 1][2] = deltaPosTemp[2]; + trkLTInt[nStripsCrossedInPropagation - 1] = intLT; + // Printf("intLT (after matching to strip %d): length = %f, time (Pion) = %f", nStripsCrossedInPropagation - 1, trkLTInt[nStripsCrossedInPropagation - 1].getL(), trkLTInt[nStripsCrossedInPropagation - 1].getTOF(o2::track::PID::Pion)); + nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]++; + } else { // a further propagation step in the same strip -> update info (we sum up on all matching with strip - we will divide for the number of steps a bit below) + // N.B. the integrated length and time are taken (at least for now) from the first time we crossed the strip, so here we do nothing with those + deltaPos[nStripsCrossedInPropagation - 1][0] += deltaPosTemp[0] + (detIdTemp[4] - detId[nStripsCrossedInPropagation - 1][4]) * Geo::XPAD; // residual in x + deltaPos[nStripsCrossedInPropagation - 1][1] += deltaPosTemp[1]; // residual in y + deltaPos[nStripsCrossedInPropagation - 1][2] += deltaPosTemp[2] + (detIdTemp[3] - detId[nStripsCrossedInPropagation - 1][3]) * Geo::ZPAD; // residual in z + nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]++; + } + } + + for (Int_t imatch = 0; imatch < nStripsCrossedInPropagation; imatch++) { + // we take as residual the average of the residuals along the propagation in the same strip + deltaPos[imatch][0] /= nStepsInsideSameStrip[imatch]; + deltaPos[imatch][1] /= nStepsInsideSameStrip[imatch]; + deltaPos[imatch][2] /= nStepsInsideSameStrip[imatch]; + // LOG(DEBUG) << "matched strip " << imatch << ": deltaPos[0] = " << deltaPos[imatch][0] << ", deltaPos[1] = " << deltaPos[imatch][1] << ", deltaPos[2] = " << deltaPos[imatch][2] << ", residual (x, z) = " << TMath::Sqrt(deltaPos[imatch][0] * deltaPos[imatch][0] + deltaPos[imatch][2] * deltaPos[imatch][2]); + } + + if (nStripsCrossedInPropagation == 0) { + continue; // the track never hit a TOF strip during the propagation + } + bool foundCluster = false; + itof0 = 0; + for (auto itof = itof0; itof < nTOFCls; itof++) { + // printf("itof = %d\n", itof); + auto& trefTOF = mTOFClusWork[cacheTOF[itof]]; + // compare the times of the track and the TOF clusters - remember that they both are ordered in time! + //Printf("trefTOF.getTime() = %f, maxTrkTime = %f, minTrkTime = %f", trefTOF.getTime(), maxTrkTime, minTrkTime); + + if (trefTOF.getTime() < minTrkTime) { // this cluster has a time that is too small for the current track, we will get to the next one + //Printf("In trefTOF.getTime() < minTrkTime"); + itof0 = itof + 1; // but for the next track that we will check, we will ignore this cluster (the time is anyway too small) + continue; + } + if (trefTOF.getTime() > maxTrkTime) { // no more TOF clusters can be matched to this track + break; + } + + int mainChannel = trefTOF.getMainContributingChannel(); + int indices[5]; + Geo::getVolumeIndices(mainChannel, indices); + + // compute fine correction using cluster position instead of pad center + // this because in case of multiple-hit cluster position is averaged on all pads contributing to the cluster (then error position matrix can be used for Chi2 if nedeed) + int ndigits = 1; + float posCorr[3] = {0, 0, 0}; + + if (trefTOF.isBitSet(Cluster::kLeft)) + posCorr[0] += Geo::XPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kUpLeft)) + posCorr[0] += Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kDownLeft)) + posCorr[0] += Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kUp)) + posCorr[2] -= Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kDown)) + posCorr[2] += Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kRight)) + posCorr[0] -= Geo::XPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kUpRight)) + posCorr[0] -= Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kDownRight)) + posCorr[0] -= Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; + + float ndifInv = 1. / ndigits; + if (ndigits > 1) { + posCorr[0] *= ndifInv; + posCorr[1] *= ndifInv; + posCorr[2] *= ndifInv; + } + + int trackIdTOF; + int eventIdTOF; + int sourceIdTOF; + for (auto iPropagation = 0; iPropagation < nStripsCrossedInPropagation; iPropagation++) { + LOG(DEBUG) << "TOF Cluster [" << itof << ", " << cacheTOF[itof] << "]: indices = " << indices[0] << ", " << indices[1] << ", " << indices[2] << ", " << indices[3] << ", " << indices[4]; + LOG(DEBUG) << "Propagated Track [" << itrk << ", " << cacheTrk[itrk] << "]: detId[" << iPropagation << "] = " << detId[iPropagation][0] << ", " << detId[iPropagation][1] << ", " << detId[iPropagation][2] << ", " << detId[iPropagation][3] << ", " << detId[iPropagation][4]; + float resX = deltaPos[iPropagation][0] - (indices[4] - detId[iPropagation][4]) * Geo::XPAD + posCorr[0]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster + float resZ = deltaPos[iPropagation][2] - (indices[3] - detId[iPropagation][3]) * Geo::ZPAD + posCorr[2]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster + float res = TMath::Sqrt(resX * resX + resZ * resZ); + + LOG(DEBUG) << "resX = " << resX << ", resZ = " << resZ << ", res = " << res; +#ifdef _ALLOW_TOF_DEBUG_ + fillTOFmatchTree("match0", cacheTOF[itof], indices[0], indices[1], indices[2], indices[3], indices[4], cacheTrk[itrk], iPropagation, detId[iPropagation][0], detId[iPropagation][1], detId[iPropagation][2], detId[iPropagation][3], detId[iPropagation][4], resX, resZ, res, trackWork, trkLTInt[iPropagation].getL(), trkLTInt[iPropagation].getTOF(o2::track::PID::Pion), trefTOF.getTime()); + int tofLabelTrackID[3] = {-1, -1, -1}; + int tofLabelEventID[3] = {-1, -1, -1}; + int tofLabelSourceID[3] = {-1, -1, -1}; + if (mMCTruthON) { + const auto& labelsTOF = mTOFClusLabels.getLabels(mTOFClusSectIndexCache[indices[0]][itof]); + int lsize = labelsTOF.size(); + if (lsize >= 3) + lsize = 3; + for (int ilabel = 0; ilabel < lsize; ilabel++) { + tofLabelTrackID[ilabel] = labelsTOF[ilabel].getTrackID(); + tofLabelEventID[ilabel] = labelsTOF[ilabel].getEventID(); + tofLabelSourceID[ilabel] = labelsTOF[ilabel].getSourceID(); + } + auto& labelTPC = mTPCLabels[mTracksSectIndexCache[sec][itrk]]; + auto& labelITS = mTPCLabels[mTracksSectIndexCache[sec][itrk]]; + fillTOFmatchTreeWithLabels("matchPossibleWithLabels", cacheTOF[itof], indices[0], indices[1], indices[2], indices[3], indices[4], cacheTrk[itrk], iPropagation, detId[iPropagation][0], detId[iPropagation][1], detId[iPropagation][2], detId[iPropagation][3], detId[iPropagation][4], resX, resZ, res, trackWork, labelTPC.getTrackID(), labelTPC.getEventID(), labelTPC.getSourceID(), labelITS.getTrackID(), labelITS.getEventID(), labelITS.getSourceID(), tofLabelTrackID[0], tofLabelEventID[0], tofLabelSourceID[0], tofLabelTrackID[1], tofLabelEventID[1], tofLabelSourceID[1], tofLabelTrackID[2], tofLabelEventID[2], tofLabelSourceID[2], trkLTInt[iPropagation].getL(), trkLTInt[iPropagation].getTOF(o2::track::PID::Pion), trefTOF.getTime()); + } +#endif + if (indices[0] != detId[iPropagation][0]) + continue; + if (indices[1] != detId[iPropagation][1]) + continue; + if (indices[2] != detId[iPropagation][2]) + continue; + float chi2 = res; // TODO: take into account also the time! + + if (res < mSpaceTolerance) { // matching ok! + LOG(DEBUG) << "MATCHING FOUND: We have a match! between track " << mTracksSectIndexCache[indices[0]][itrk] << " and TOF cluster " << mTOFClusSectIndexCache[indices[0]][itof]; + foundCluster = true; + // set event indexes (to be checked) + evIdx eventIndexTOFCluster(trefTOF.getEntryInTree(), mTOFClusSectIndexCache[indices[0]][itof]); + evIdx eventIndexTracks(mCurrTracksTreeEntry, mTracksSectIndexCache[indices[0]][itrk]); + mMatchedTracksPairs.emplace_back(o2::dataformats::MatchInfoTOF(eventIndexTOFCluster, chi2, trkLTInt[iPropagation], eventIndexTracks)); // TODO: check if this is correct! + } + } + } + if (!foundCluster && mMCTruthON) { + const auto& labelTPC = mTPCLabels[mTracksSectIndexCache[sec][itrk]]; + LOG(DEBUG) << "We did not find any TOF cluster for track " << cacheTrk[itrk] << " (label = " << labelTPC << ", pt = " << trefTrk.getPt(); + } + } + return; +} +//______________________________________________ int MatchTOF::findFITIndex(int bc) { if (mFITRecPoints.size() == 0) { @@ -898,17 +1440,15 @@ void MatchTOF::selectBestMatches() // add also calibration infos mCalibInfoTOF.emplace_back(mTOFClusWork[matchingPair.getTOFClIndex()].getMainContributingChannel(), int(mTOFClusWork[matchingPair.getTOFClIndex()].getTimeRaw() * 1E12), // add time stamp - mTOFClusWork[matchingPair.getTOFClIndex()].getTimeRaw() - matchingPair.getLTIntegralOut().getTOF(o2::track::PID::Pion) - t0info, + mTOFClusWork[matchingPair.getTOFClIndex()].getTimeRaw() - mLTinfos[matchingPair.getTrackIndex()].getTOF(o2::track::PID::Pion) - t0info, mTOFClusWork[matchingPair.getTOFClIndex()].getTot()); if (mMCTruthON) { const auto& labelsTOF = mTOFClusLabels.getLabels(matchingPair.getTOFClIndex()); const auto& labelTPC = mTPCLabels[matchingPair.getTrackIndex()]; - const auto& labelITS = mITSLabels[matchingPair.getTrackIndex()]; // we want to store positive labels independently of how they are flagged from TPC,ITS people // o2::MCCompLabel labelTPC(abs(labelTPCor.getTrackID()), labelTPCor.getEventID(), labelTPCor.getSourceID()); // o2::MCCompLabel labelITS(abs(labelITSor.getTrackID()), labelITSor.getEventID(), labelITSor.getSourceID()); LOG(DEBUG) << "TPC label" << labelTPC; - LOG(DEBUG) << "ITS label" << labelITS; bool labelOk = false; // whether we have found or not the same TPC label of the track among the labels of the TOF cluster for (int ilabel = 0; ilabel < labelsTOF.size(); ilabel++) { @@ -926,12 +1466,15 @@ void MatchTOF::selectBestMatches() mOutTOFLabels.emplace_back(labelsTOF[0].getTrackID(), labelsTOF[0].getEventID(), labelsTOF[0].getSourceID(), true); } mOutTPCLabels.push_back(labelTPC); - mOutITSLabels.push_back(labelITS); + if (mIsITSused) { + const auto& labelITS = mITSLabels[matchingPair.getTrackIndex()]; + LOG(DEBUG) << "ITS label" << labelITS; + mOutITSLabels.push_back(labelITS); + } } i++; } } - //______________________________________________ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float stepInCm, o2::track::TrackLTIntegral& intLT) { @@ -1019,7 +1562,7 @@ void MatchTOF::setDebugFlag(UInt_t flag, bool on) } //_________________________________________________________ -void MatchTOF::fillTOFmatchTree(const char* trname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, o2::dataformats::TrackTPCITS& trk, float intLength, float intTimePion, float timeTOF) +void MatchTOF::fillTOFmatchTree(const char* trname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, matchTrack& trk, float intLength, float intTimePion, float timeTOF) { ///< fill debug tree for TOF tracks matching check @@ -1031,13 +1574,13 @@ void MatchTOF::fillTOFmatchTree(const char* trname, int cacheTOF, int sectTOF, i (*mDBGOut) << trname << "clusterTOF=" << cacheTOF << "sectTOF=" << sectTOF << "plateTOF=" << plateTOF << "stripTOF=" << stripTOF << "padXTOF=" << padXTOF << "padZTOF=" << padZTOF << "crossedStrip=" << crossedStrip << "sectPropagation=" << sectPropagation << "platePropagation=" << platePropagation << "stripPropagation=" << stripPropagation << "padXPropagation=" << padXPropagation - << "resX=" << resX << "resZ=" << resZ << "res=" << res << "track=" << trk << "intLength=" << intLength << "intTimePion=" << intTimePion << "timeTOF=" << timeTOF << "\n"; + << "resX=" << resX << "resZ=" << resZ << "res=" << res << "track=" << trk.first << "intLength=" << intLength << "intTimePion=" << intTimePion << "timeTOF=" << timeTOF << "\n"; } mTimerDBG.Stop(); } //_________________________________________________________ -void MatchTOF::fillTOFmatchTreeWithLabels(const char* trname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, o2::dataformats::TrackTPCITS& trk, int TPClabelTrackID, int TPClabelEventID, int TPClabelSourceID, int ITSlabelTrackID, int ITSlabelEventID, int ITSlabelSourceID, int TOFlabelTrackID0, int TOFlabelEventID0, int TOFlabelSourceID0, int TOFlabelTrackID1, int TOFlabelEventID1, int TOFlabelSourceID1, int TOFlabelTrackID2, int TOFlabelEventID2, int TOFlabelSourceID2, float intLength, float intTimePion, float timeTOF) +void MatchTOF::fillTOFmatchTreeWithLabels(const char* trname, int cacheTOF, int sectTOF, int plateTOF, int stripTOF, int padXTOF, int padZTOF, int cacheeTrk, int crossedStrip, int sectPropagation, int platePropagation, int stripPropagation, int padXPropagation, int padZPropagation, float resX, float resZ, float res, matchTrack& trk, int TPClabelTrackID, int TPClabelEventID, int TPClabelSourceID, int ITSlabelTrackID, int ITSlabelEventID, int ITSlabelSourceID, int TOFlabelTrackID0, int TOFlabelEventID0, int TOFlabelSourceID0, int TOFlabelTrackID1, int TOFlabelEventID1, int TOFlabelSourceID1, int TOFlabelTrackID2, int TOFlabelEventID2, int TOFlabelSourceID2, float intLength, float intTimePion, float timeTOF) { ///< fill debug tree for TOF tracks matching check @@ -1047,7 +1590,7 @@ void MatchTOF::fillTOFmatchTreeWithLabels(const char* trname, int cacheTOF, int (*mDBGOut) << trname << "clusterTOF=" << cacheTOF << "sectTOF=" << sectTOF << "plateTOF=" << plateTOF << "stripTOF=" << stripTOF << "padXTOF=" << padXTOF << "padZTOF=" << padZTOF << "crossedStrip=" << crossedStrip << "sectPropagation=" << sectPropagation << "platePropagation=" << platePropagation << "stripPropagation=" << stripPropagation << "padXPropagation=" << padXPropagation - << "resX=" << resX << "resZ=" << resZ << "res=" << res << "track=" << trk + << "resX=" << resX << "resZ=" << resZ << "res=" << res << "track=" << trk.first << "TPClabelTrackID=" << TPClabelTrackID << "TPClabelEventID=" << TPClabelEventID << "TPClabelSourceID=" << TPClabelSourceID << "ITSlabelTrackID=" << ITSlabelTrackID << "ITSlabelEventID=" << ITSlabelEventID << "ITSlabelSourceID=" << ITSlabelSourceID << "TOFlabelTrackID0=" << TOFlabelTrackID0 << "TOFlabelEventID0=" << TOFlabelEventID0 << "TOFlabelSourceID0=" << TOFlabelSourceID0 diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt index 5e52105e0ff0f..22e5e927b488d 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/CMakeLists.txt @@ -10,19 +10,31 @@ o2_add_library(TOFWorkflow SOURCES src/RecoWorkflowSpec.cxx + src/RecoWorkflowWithTPCSpec.cxx src/TOFMatchedWriterSpec.cxx src/TOFCalibWriterSpec.cxx src/TOFMatchedReaderSpec.cxx src/CalibInfoReaderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction O2::GlobalTracking O2::GlobalTrackingWorkflow O2::TOFWorkflowUtils - O2::TOFCalibration O2::DataFormatsFT0 O2::FT0Reconstruction O2::FT0Workflow) + O2::TOFCalibration O2::DataFormatsFT0 O2::FT0Reconstruction O2::FT0Workflow + O2::TPCWorkflow) o2_add_executable(reco-workflow COMPONENT_NAME tof SOURCES src/tof-reco-workflow.cxx PUBLIC_LINK_LIBRARIES O2::TOFWorkflow) +o2_add_executable(matcher-global + COMPONENT_NAME tof + SOURCES src/tof-matcher-global.cxx + PUBLIC_LINK_LIBRARIES O2::TOFWorkflow) + +o2_add_executable(matcher-tpc + COMPONENT_NAME tof + SOURCES src/tof-matcher-tpc.cxx + PUBLIC_LINK_LIBRARIES O2::TOFWorkflow) + o2_add_executable(calib-reader COMPONENT_NAME tof SOURCES src/tof-calibinfo-reader.cxx diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/RecoWorkflowWithTPCSpec.h b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/RecoWorkflowWithTPCSpec.h new file mode 100644 index 0000000000000..9f5d5b49dc50b --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/RecoWorkflowWithTPCSpec.h @@ -0,0 +1,27 @@ +// 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 TOF_RECOWORKFLOWWITHTPC_H_ +#define TOF_RECOWORKFLOWWITHTPC_H_ + +#include "Framework/DataProcessorSpec.h" +#include "ReconstructionDataFormats/MatchInfoTOF.h" + +namespace o2 +{ +namespace tof +{ + +o2::framework::DataProcessorSpec getTOFRecoWorkflowWithTPCSpec(bool useMC, bool useFIT); + +} // end namespace tof +} // end namespace o2 + +#endif /* TOF_RECOWORKFLOWWITHTPC_H_ */ diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFCalibWriterSpec.h b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFCalibWriterSpec.h index 9a804b031da48..82d696bcf0383 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFCalibWriterSpec.h +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFCalibWriterSpec.h @@ -24,7 +24,7 @@ namespace tof /// create a processor spec /// write TOF calbi info in a root file -o2::framework::DataProcessorSpec getTOFCalibWriterSpec(); +o2::framework::DataProcessorSpec getTOFCalibWriterSpec(const char* outdef = "o2calib_tof.root"); } // namespace tof } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFMatchedWriterSpec.h b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFMatchedWriterSpec.h index 9c6fe7995ba9f..bb9899addd94c 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFMatchedWriterSpec.h +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFMatchedWriterSpec.h @@ -24,7 +24,7 @@ namespace tof /// create a processor spec /// write TOF matching info in a root file -o2::framework::DataProcessorSpec getTOFMatchedWriterSpec(bool useMC); +o2::framework::DataProcessorSpec getTOFMatchedWriterSpec(bool useMC, const char* outdef = "o2match_tof.root"); } // namespace tof } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowWithTPCSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowWithTPCSpec.cxx new file mode 100644 index 0000000000000..aefc81024073e --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowWithTPCSpec.cxx @@ -0,0 +1,166 @@ +// 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 "TOFWorkflow/RecoWorkflowWithTPCSpec.h" +#include "Framework/ControlService.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataRefUtils.h" +#include "Framework/Lifetime.h" +#include "Framework/Task.h" +#include "Framework/SerializationMethods.h" +#include "Headers/DataHeader.h" +#include "DataFormatsTOF/Cluster.h" +#include "GlobalTracking/MatchTOF.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include <gsl/span> +#include "TStopwatch.h" + +// from FIT +#include "DataFormatsFT0/RecPoints.h" + +#include <memory> // for make_shared, make_unique, unique_ptr +#include <vector> + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +// use the tasking system of DPL +// just need to implement 2 special methods init + run (there is no need to inherit from anything) +class TOFDPLRecoWorkflowWithTPCTask +{ + using evIdx = o2::dataformats::EvIndex<int, int>; + using MatchOutputType = std::vector<o2::dataformats::MatchInfoTOF>; + + bool mUseMC = true; + bool mUseFIT = false; + + public: + explicit TOFDPLRecoWorkflowWithTPCTask(bool useMC, bool useFIT) : mUseMC(useMC), mUseFIT(useFIT) {} + + void init(framework::InitContext& ic) + { + // nothing special to be set up + o2::base::GeometryManager::loadGeometry(); + o2::base::Propagator::initFieldFromGRP("o2sim_grp.root"); + mTimer.Stop(); + mTimer.Reset(); + } + + void run(framework::ProcessingContext& pc) + { + mTimer.Start(false); + //>>>---------- attach input data --------------->>> + const auto clustersRO = pc.inputs().get<gsl::span<o2::tof::Cluster>>("tofcluster"); + const auto tracksRO = pc.inputs().get<gsl::span<o2::tpc::TrackTPC>>("tracks"); + + if (mUseFIT) { + // Note: the particular variable will go out of scope, but the span is passed by copy to the + // worker and the underlying memory is valid throughout the whole computation + auto recPoints = std::move(pc.inputs().get<gsl::span<o2::ft0::RecPoints>>("fitrecpoints")); + mMatcher.setFITRecPoints(recPoints); + LOG(INFO) << "TOF Reco WorkflowWithTPC pulled " << recPoints.size() << " FIT RecPoints"; + } + + //-------- init geometry and field --------// + // std::string path = "./"; + // std::string inputGeom = "O2geometry.root"; + // std::string inputGRP = "o2sim_grp.root"; + + // o2::base::GeometryManager::loadGeometry(path); + // o2::base::Propagator::initFieldFromGRP(path + inputGRP); + + // call actual matching info routine + //#ifdef _ALLOW_DEBUG_TREES_ + // mMatcher.setDebugTreeFileName(path + mMatcher.getDebugTreeFileName()); + // mMatcher.setDebugFlag(o2::globaltracking::MatchTOF::MatchTreeAll); + //#endif + + // we do a copy of the input but we are looking for a way to avoid it (current problem in conversion form unique_ptr to *) + + o2::dataformats::MCTruthContainer<o2::MCCompLabel> toflab; + gsl::span<const o2::MCCompLabel> tpclab; + printf("get MC\n"); + if (mUseMC) { + const auto toflabel = pc.inputs().get<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("tofclusterlabel"); + tpclab = pc.inputs().get<gsl::span<o2::MCCompLabel>>("tpctracklabel"); + toflab = std::move(*toflabel); + } + printf("GOT!\n"); + + mMatcher.run(tracksRO, clustersRO, toflab, tpclab); + + printf("run done\n"); + // in run_match_tof aggiugnere esplicitamente la chiamata a fill del tree (nella classe MatchTOF) e il metodo per leggere i vettori di output + + //... + // LOG(INFO) << "TOF CLUSTERER : TRANSFORMED " << digits->size() + // << " DIGITS TO " << mClustersArray.size() << " CLUSTERS"; + + // send matching-info + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "MATCHINFOS", 0, Lifetime::Timeframe}, mMatcher.getMatchedTrackVector()); + if (mUseMC) { + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "MATCHTOFINFOSMC", 0, Lifetime::Timeframe}, mMatcher.getMatchedTOFLabelsVector()); + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "MATCHTPCINFOSMC", 0, Lifetime::Timeframe}, mMatcher.getMatchedTPCLabelsVector()); + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "MATCHITSINFOSMC", 0, Lifetime::Timeframe}, mMatcher.getMatchedITSLabelsVector()); + } + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CALIBDATA", 0, Lifetime::Timeframe}, mMatcher.getCalibVector()); + mTimer.Stop(); + } + + void endOfStream(EndOfStreamContext& ec) + { + LOGF(INFO, "TOF Matching total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); + } + + private: + o2::globaltracking::MatchTOF mMatcher; ///< Cluster finder + TStopwatch mTimer; +}; + +o2::framework::DataProcessorSpec getTOFRecoWorkflowWithTPCSpec(bool useMC, bool useFIT) +{ + std::vector<InputSpec> inputs; + std::vector<OutputSpec> outputs; + inputs.emplace_back("tofcluster", o2::header::gDataOriginTOF, "CLUSTERS", 0, Lifetime::Timeframe); + inputs.emplace_back("tracks", o2::header::gDataOriginTPC, "TRACKS", 0, Lifetime::Timeframe); + if (useMC) { + inputs.emplace_back("tofclusterlabel", o2::header::gDataOriginTOF, "CLUSTERSMCTR", 0, Lifetime::Timeframe); + inputs.emplace_back("tpctracklabel", o2::header::gDataOriginTPC, "TRACKSMCLBL", 0, Lifetime::Timeframe); + } + + if (useFIT) { + inputs.emplace_back("fitrecpoints", o2::header::gDataOriginFT0, "RECPOINTS", 0, Lifetime::Timeframe); + } + + outputs.emplace_back(o2::header::gDataOriginTOF, "MATCHINFOS", 0, Lifetime::Timeframe); + if (useMC) { + outputs.emplace_back(o2::header::gDataOriginTOF, "MATCHTOFINFOSMC", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTOF, "MATCHTPCINFOSMC", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTOF, "MATCHITSINFOSMC", 0, Lifetime::Timeframe); + } + outputs.emplace_back(o2::header::gDataOriginTOF, "CALIBDATA", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "TOFRecoWorkflowWithTPC", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<TOFDPLRecoWorkflowWithTPCTask>(useMC, useFIT)}, + Options{/* for the moment no options */}}; +} + +} // end namespace tof +} // end namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx index 384d6df8b7f78..e3d0ab0690259 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFCalibWriterSpec.cxx @@ -34,14 +34,14 @@ namespace tof template <typename T> using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; using CalibInfosType = std::vector<o2::dataformats::CalibInfoTOF>; -DataProcessorSpec getTOFCalibWriterSpec() +DataProcessorSpec getTOFCalibWriterSpec(const char* outdef) { // A spectator for logging auto logger = [](CalibInfosType const& indata) { LOG(INFO) << "RECEIVED MATCHED SIZE " << indata.size(); }; return MakeRootTreeWriterSpec("TOFCalibWriter", - "o2calib_tof.root", + outdef, "calibTOF", BranchDefinition<CalibInfosType>{InputSpec{"input", o2::header::gDataOriginTOF, "CALIBDATA", 0}, "TOFCalibInfo", diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFMatchedWriterSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFMatchedWriterSpec.cxx index be790e70d425f..6e8ad5dccd840 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFMatchedWriterSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/TOFMatchedWriterSpec.cxx @@ -35,7 +35,7 @@ using OutputType = std::vector<o2::dataformats::MatchInfoTOF>; using LabelsType = std::vector<o2::MCCompLabel>; using namespace o2::header; -DataProcessorSpec getTOFMatchedWriterSpec(bool useMC) +DataProcessorSpec getTOFMatchedWriterSpec(bool useMC, const char* outdef) { // spectators for logging auto loggerMatched = [](OutputType const& indata) { @@ -54,7 +54,7 @@ DataProcessorSpec getTOFMatchedWriterSpec(bool useMC) // RS why do we need to repead ITS/TPC labels ? // They can be extracted from TPC-ITS matches return MakeRootTreeWriterSpec("TOFMatchedWriter", - "o2match_tof.root", + outdef, "matchTOF", BranchDefinition<OutputType>{InputSpec{"tofmatching", gDataOriginTOF, "MATCHINFOS", 0}, "TOFMatchInfo", diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx new file mode 100644 index 0000000000000..4ded6d1b60acb --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx @@ -0,0 +1,165 @@ +// 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 tof-reco-workflow.cxx +/// @author Francesco Noferini +/// @since 2019-05-22 +/// @brief Basic DPL workflow for TOF reconstruction starting from digits + +#include "DetectorsBase/Propagator.h" +#include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" +#include "TOFWorkflow/ClusterReaderSpec.h" +#include "TOFWorkflow/TOFMatchedWriterSpec.h" +#include "TOFWorkflow/TOFCalibWriterSpec.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/ConfigParamSpec.h" +#include "TOFWorkflow/RecoWorkflowSpec.h" +#include "Algorithm/RangeTokenizer.h" +#include "FairLogger.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" + +// GRP +#include "DataFormatsParameters/GRPObject.h" + +// FIT +#include "FT0Workflow/RecPointReaderSpec.h" + +#include <string> +#include <stdexcept> +#include <unordered_map> + +// add workflow options, note that customization needs to be declared before +// including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{"input-type", o2::framework::VariantType::String, "clusters,tracks", {"clusters, tracks, fit"}}); + workflowOptions.push_back(ConfigParamSpec{"output-type", o2::framework::VariantType::String, "matching-info,calib-info", {"matching-info, calib-info"}}); + workflowOptions.push_back(ConfigParamSpec{"disable-mc", o2::framework::VariantType::Bool, false, {"disable sending of MC information, TBI"}}); + workflowOptions.push_back(ConfigParamSpec{"tof-sectors", o2::framework::VariantType::String, "0-17", {"TOF sector range, e.g. 5-7,8,9 ,TBI"}}); + workflowOptions.push_back(ConfigParamSpec{"tof-lanes", o2::framework::VariantType::Int, 1, {"number of parallel lanes up to the matcher, TBI"}}); + workflowOptions.push_back(ConfigParamSpec{"use-ccdb", o2::framework::VariantType::Bool, false, {"enable access to ccdb tof calibration objects"}}); + workflowOptions.push_back(ConfigParamSpec{"use-fit", o2::framework::VariantType::Bool, false, {"enable access to fit info for calibration"}}); + workflowOptions.push_back(ConfigParamSpec{"input-desc", o2::framework::VariantType::String, "CRAWDATA", {"Input specs description string"}}); + workflowOptions.push_back(ConfigParamSpec{"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input readers"}}); + workflowOptions.push_back(ConfigParamSpec{"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writers"}}); + workflowOptions.push_back(ConfigParamSpec{"configKeyValues", o2::framework::VariantType::String, "", {"Semicolon separated key=value strings ..."}}); +} + +#include "Framework/runDataProcessing.h" // the main driver + +using namespace o2::framework; + +/// The workflow executable for the stand alone TOF reconstruction workflow +/// The basic workflow for TOF reconstruction is defined in RecoWorkflow.cxx +/// and contains the following default processors +/// - digit reader +/// - clusterer +/// - cluster raw decoder +/// - track-TOF matcher +/// +/// The default workflow can be customized by specifying input and output types +/// e.g. digits, raw, clusters. +/// +/// MC info is processed by default, disabled by using command line option `--disable-mc` +/// +/// This function hooks up the the workflow specifications into the DPL driver. +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec specs; + + if (!cfgc.helpOnCommandLine()) { + std::string inputGRP = o2::base::NameConf::getGRPFileName(); + o2::base::Propagator::initFieldFromGRP(inputGRP); + const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP); + if (!grp) { + LOG(ERROR) << "This workflow needs a valid GRP file to start"; + return specs; + } + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + // o2::conf::ConfigurableParam::writeINI("o2tofrecoflow_configuration.ini"); + } + // the lane configuration defines the subspecification ids to be distributed among the lanes. + // auto tofSectors = o2::RangeTokenizer::tokenize<int>(cfgc.options().get<std::string>("tof-sectors")); + // std::vector<int> laneConfiguration = tofSectors; + auto nLanes = cfgc.options().get<int>("tof-lanes"); + auto inputType = cfgc.options().get<std::string>("input-type"); + auto outputType = cfgc.options().get<std::string>("output-type"); + + bool writematching = 0; + bool writecalib = 0; + + if (outputType.rfind("matching-info") < outputType.size()) + writematching = 1; + if (outputType.rfind("calib-info") < outputType.size()) + writecalib = 1; + + bool clusterinput = 0; + bool trackinput = 0; + bool fitinput = 0; + + if (inputType.rfind("clusters") < inputType.size()) { + clusterinput = 1; + } + if (inputType.rfind("tracks") < inputType.size()) { + trackinput = 1; + } + auto useMC = !cfgc.options().get<bool>("disable-mc"); + auto useCCDB = cfgc.options().get<bool>("use-ccdb"); + auto useFIT = cfgc.options().get<bool>("use-fit"); + bool disableRootInput = cfgc.options().get<bool>("disable-root-input"); + bool disableRootOutput = cfgc.options().get<bool>("disable-root-output"); + + if (inputType.rfind("fit") < inputType.size()) { + fitinput = 1; + useFIT = 1; + } + + LOG(INFO) << "TOF RECO WORKFLOW configuration"; + LOG(INFO) << "TOF input = " << cfgc.options().get<std::string>("input-type"); + LOG(INFO) << "TOF output = " << cfgc.options().get<std::string>("output-type"); + LOG(INFO) << "TOF sectors = " << cfgc.options().get<std::string>("tof-sectors"); + LOG(INFO) << "TOF disable-mc = " << cfgc.options().get<std::string>("disable-mc"); + LOG(INFO) << "TOF lanes = " << cfgc.options().get<std::string>("tof-lanes"); + LOG(INFO) << "TOF use-ccdb = " << cfgc.options().get<std::string>("use-ccdb"); + LOG(INFO) << "TOF use-fit = " << cfgc.options().get<std::string>("use-fit"); + LOG(INFO) << "TOF disable-root-input = " << disableRootInput; + LOG(INFO) << "TOF disable-root-output = " << disableRootOutput; + + if (clusterinput) { + LOG(INFO) << "Insert TOF Cluster Reader"; + specs.emplace_back(o2::tof::getClusterReaderSpec(useMC)); + } + if (trackinput) { + LOG(INFO) << "Insert ITS-TPC Track Reader"; + specs.emplace_back(o2::globaltracking::getTrackTPCITSReaderSpec(useMC)); + } + + if (fitinput) { + LOG(INFO) << "Insert FIT RecPoint Reader"; + specs.emplace_back(o2::ft0::getRecPointReaderSpec(useMC)); + } + + LOG(INFO) << "Insert TOF Matching"; + specs.emplace_back(o2::tof::getTOFRecoWorkflowSpec(useMC, useFIT)); + + if (writematching && !disableRootOutput) { + LOG(INFO) << "Insert TOF Matched Info Writer"; + specs.emplace_back(o2::tof::getTOFMatchedWriterSpec(useMC)); + } + if (writecalib) { + LOG(INFO) << "Insert TOF Calib Info Writer"; + specs.emplace_back(o2::tof::getTOFCalibWriterSpec()); + } + + LOG(INFO) << "Number of active devices = " << specs.size(); + + return std::move(specs); +} diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx new file mode 100644 index 0000000000000..5c92aa58f9a85 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx @@ -0,0 +1,170 @@ +// 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 tof-reco-workflow.cxx +/// @author Francesco Noferini +/// @since 2019-05-22 +/// @brief Basic DPL workflow for TOF reconstruction starting from digits + +#include "DetectorsBase/Propagator.h" +#include "TOFWorkflow/ClusterReaderSpec.h" +#include "TOFWorkflow/TOFMatchedWriterSpec.h" +#include "TOFWorkflow/TOFCalibWriterSpec.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/ConfigParamSpec.h" +#include "TOFWorkflow/RecoWorkflowWithTPCSpec.h" +#include "Algorithm/RangeTokenizer.h" +#include "FairLogger.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "TPCWorkflow/TrackReaderSpec.h" + +// GRP +#include "DataFormatsParameters/GRPObject.h" + +// FIT +#include "FT0Workflow/RecPointReaderSpec.h" + +#include <string> +#include <stdexcept> +#include <unordered_map> + +// add workflow options, note that customization needs to be declared before +// including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{"input-type", o2::framework::VariantType::String, "clusters,tracks", {"clusters, tracks, fit"}}); + workflowOptions.push_back(ConfigParamSpec{"output-type", o2::framework::VariantType::String, "matching-info", {"matching-info, calib-info"}}); + workflowOptions.push_back(ConfigParamSpec{"disable-mc", o2::framework::VariantType::Bool, false, {"disable sending of MC information, TBI"}}); + workflowOptions.push_back(ConfigParamSpec{"tof-sectors", o2::framework::VariantType::String, "0-17", {"TOF sector range, e.g. 5-7,8,9 ,TBI"}}); + workflowOptions.push_back(ConfigParamSpec{"tof-lanes", o2::framework::VariantType::Int, 1, {"number of parallel lanes up to the matcher, TBI"}}); + workflowOptions.push_back(ConfigParamSpec{"use-ccdb", o2::framework::VariantType::Bool, false, {"enable access to ccdb tof calibration objects"}}); + workflowOptions.push_back(ConfigParamSpec{"use-fit", o2::framework::VariantType::Bool, false, {"enable access to fit info for calibration"}}); + workflowOptions.push_back(ConfigParamSpec{"input-desc", o2::framework::VariantType::String, "CRAWDATA", {"Input specs description string"}}); + workflowOptions.push_back(ConfigParamSpec{"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input readers"}}); + workflowOptions.push_back(ConfigParamSpec{"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writers"}}); + workflowOptions.push_back(ConfigParamSpec{"configKeyValues", o2::framework::VariantType::String, "", {"Semicolon separated key=value strings ..."}}); +} + +#include "Framework/runDataProcessing.h" // the main driver + +using namespace o2::framework; + +/// The workflow executable for the stand alone TOF reconstruction workflow +/// The basic workflow for TOF reconstruction is defined in RecoWorkflow.cxx +/// and contains the following default processors +/// - digit reader +/// - clusterer +/// - cluster raw decoder +/// - track-TOF matcher +/// +/// The default workflow can be customized by specifying input and output types +/// e.g. digits, raw, clusters. +/// +/// MC info is processed by default, disabled by using command line option `--disable-mc` +/// +/// This function hooks up the the workflow specifications into the DPL driver. +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec specs; + + if (!cfgc.helpOnCommandLine()) { + std::string inputGRP = o2::base::NameConf::getGRPFileName(); + o2::base::Propagator::initFieldFromGRP(inputGRP); + const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP); + if (!grp) { + LOG(ERROR) << "This workflow needs a valid GRP file to start"; + return specs; + } + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + // o2::conf::ConfigurableParam::writeINI("o2tofrecoflow_configuration.ini"); + } + // the lane configuration defines the subspecification ids to be distributed among the lanes. + // auto tofSectors = o2::RangeTokenizer::tokenize<int>(cfgc.options().get<std::string>("tof-sectors")); + // std::vector<int> laneConfiguration = tofSectors; + auto nLanes = cfgc.options().get<int>("tof-lanes"); + auto inputType = cfgc.options().get<std::string>("input-type"); + auto outputType = cfgc.options().get<std::string>("output-type"); + + bool writematching = 0; + bool writecalib = 0; + + if (outputType.rfind("matching-info") < outputType.size()) + writematching = 1; + if (outputType.rfind("calib-info") < outputType.size()) + writecalib = 1; + + bool clusterinput = 0; + bool trackinput = 0; + bool fitinput = 0; + + if (inputType.rfind("clusters") < inputType.size()) { + clusterinput = 1; + } + if (inputType.rfind("tracks") < inputType.size()) { + trackinput = 1; + } + auto useMC = !cfgc.options().get<bool>("disable-mc"); + auto useCCDB = cfgc.options().get<bool>("use-ccdb"); + auto useFIT = cfgc.options().get<bool>("use-fit"); + bool disableRootInput = cfgc.options().get<bool>("disable-root-input"); + bool disableRootOutput = cfgc.options().get<bool>("disable-root-output"); + + if (inputType.rfind("fit") < inputType.size()) { + fitinput = 1; + useFIT = 1; + } + + LOG(INFO) << "TOF RECO WORKFLOW configuration"; + LOG(INFO) << "TOF input = " << cfgc.options().get<std::string>("input-type"); + LOG(INFO) << "TOF output = " << cfgc.options().get<std::string>("output-type"); + LOG(INFO) << "TOF sectors = " << cfgc.options().get<std::string>("tof-sectors"); + LOG(INFO) << "TOF disable-mc = " << cfgc.options().get<std::string>("disable-mc"); + LOG(INFO) << "TOF lanes = " << cfgc.options().get<std::string>("tof-lanes"); + LOG(INFO) << "TOF use-ccdb = " << cfgc.options().get<std::string>("use-ccdb"); + LOG(INFO) << "TOF use-fit = " << cfgc.options().get<std::string>("use-fit"); + LOG(INFO) << "TOF disable-root-input = " << disableRootInput; + LOG(INFO) << "TOF disable-root-output = " << disableRootOutput; + + // useMC = false; + // LOG(INFO) << "TOF disable MC forced"; + // writecalib = false; + // LOG(INFO) << "TOF CalibInfo disabled (forced)"; + + if (clusterinput) { + LOG(INFO) << "Insert TOF Cluster Reader"; + specs.emplace_back(o2::tof::getClusterReaderSpec(useMC)); + } + if (trackinput) { + LOG(INFO) << "Insert TPC Track Reader"; + specs.emplace_back(o2::tpc::getTPCTrackReaderSpec(useMC)); + } + + if (fitinput) { + LOG(INFO) << "Insert FIT RecPoint Reader"; + specs.emplace_back(o2::ft0::getRecPointReaderSpec(useMC)); + } + + LOG(INFO) << "Insert TOF Matching"; + specs.emplace_back(o2::tof::getTOFRecoWorkflowWithTPCSpec(useMC, useFIT)); + + if (writematching && !disableRootOutput) { + LOG(INFO) << "Insert TOF Matched Info Writer"; + specs.emplace_back(o2::tof::getTOFMatchedWriterSpec(useMC, "o2match_toftpc.root")); + } + if (writecalib) { + LOG(INFO) << "Insert TOF Calib Info Writer"; + specs.emplace_back(o2::tof::getTOFCalibWriterSpec("o2calib_toftpc.root")); + } + + LOG(INFO) << "Number of active devices = " << specs.size(); + + return std::move(specs); +} diff --git a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx index 19dc2766a8ca7..9e5ea78f1df8e 100644 --- a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx +++ b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx @@ -176,21 +176,21 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) int chinsectormax = chmax % o2::tof::Geo::NPADSXSECTOR; float res2 = 0; - TStopwatch t3; + //TStopwatch t3; int ind = -1; int binxmin = findBin(binmin); int binxmax = findBin(binmax); LOG(DEBUG) << "binxmin = " << binxmin << ", binxmax = " << binxmax; - t3.Start(); + //t3.Start(); for (unsigned j = chinsectormin; j <= chinsectormax; ++j) { for (unsigned i = binxmin; i <= binxmax; ++i) { const auto& v = mHisto[sector].at(i, j); res2 += v; } } - t3.Stop(); + //t3.Stop(); LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; - t3.Print(); + //t3.Print(); return res2; @@ -299,17 +299,17 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c int chinsectormax = chmax % o2::tof::Geo::NPADSXSECTOR; float res2 = 0; - TStopwatch t3; - t3.Start(); + //TStopwatch t3; + //t3.Start(); for (unsigned j = chinsectormin; j <= chinsectormax; ++j) { for (unsigned i = binxmin; i <= binxmax; ++i) { const auto& v = mHisto[sector].at(i, j); res2 += v; } } - t3.Stop(); + //t3.Stop(); LOG(DEBUG) << "Time for integral looping over axis (result = " << res2 << "):"; - t3.Print(); + //t3.Print(); return res2; /* // all that is below is alternative methods, all proved to be slower From e0cda270cef33cdf372b7414e19d5738610ae8b6 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Wed, 30 Sep 2020 12:11:07 +0200 Subject: [PATCH 0827/1751] rename tofworkflowutil dir --- .../CTF/workflow/src/ctf-reader-workflow.cxx | 2 +- .../tofworkflow/src/tof-matcher-global.cxx | 2 +- .../tofworkflow/src/tof-matcher-tpc.cxx | 2 +- .../tofworkflow/src/tof-reco-workflow.cxx | 18 +++++++++--------- .../src/TrackInterpolationWorkflow.cxx | 2 +- .../src/tof-compressed-analysis.cxx | 2 +- .../src/tof-compressed-inspector.cxx | 2 +- Detectors/TOF/workflow/CMakeLists.txt | 2 +- .../ClusterReaderSpec.h | 0 .../CompressedAnalysis.h | 0 .../CompressedAnalysisTask.h | 2 +- .../CompressedDecodingTask.h | 0 .../CompressedInspectorTask.h | 0 .../DigitReaderSpec.h | 0 .../EntropyDecoderSpec.h | 0 .../EntropyEncoderSpec.h | 0 .../TOFClusterWriterSpec.h | 0 .../TOFClusterizerSpec.h | 0 .../TOFDigitWriterSpec.h | 0 .../TOFRawWriterSpec.h | 0 .../TOF/workflow/src/ClusterReaderSpec.cxx | 2 +- .../workflow/src/CompressedAnalysisTask.cxx | 2 +- .../workflow/src/CompressedDecodingTask.cxx | 2 +- .../workflow/src/CompressedInspectorTask.cxx | 2 +- Detectors/TOF/workflow/src/DigitReaderSpec.cxx | 2 +- .../TOF/workflow/src/EntropyDecoderSpec.cxx | 2 +- .../TOF/workflow/src/EntropyEncoderSpec.cxx | 2 +- .../TOF/workflow/src/TOFClusterWriterSpec.cxx | 2 +- .../TOF/workflow/src/TOFClusterizerSpec.cxx | 2 +- .../TOF/workflow/src/TOFDigitWriterSpec.cxx | 2 +- .../TOF/workflow/src/TOFRawWriterSpec.cxx | 2 +- .../workflow/src/entropy-encoder-workflow.cxx | 2 +- .../src/SimpleDigitizerWorkflow.cxx | 2 +- 33 files changed, 30 insertions(+), 30 deletions(-) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/ClusterReaderSpec.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/CompressedAnalysis.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/CompressedAnalysisTask.h (98%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/CompressedDecodingTask.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/CompressedInspectorTask.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/DigitReaderSpec.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/EntropyDecoderSpec.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/EntropyEncoderSpec.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/TOFClusterWriterSpec.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/TOFClusterizerSpec.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/TOFDigitWriterSpec.h (100%) rename Detectors/TOF/workflow/include/{TOFWorkflow => TOFWorkflowUtils}/TOFRawWriterSpec.h (100%) diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index 0aa39b30509f9..ab255537b9dc7 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -24,7 +24,7 @@ #include "TPCWorkflow/EntropyDecoderSpec.h" #include "FT0Workflow/EntropyDecoderSpec.h" #include "FV0Workflow/EntropyDecoderSpec.h" -#include "TOFWorkflow/EntropyDecoderSpec.h" +#include "TOFWorkflowUtils/EntropyDecoderSpec.h" #include "MIDWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx index 4ded6d1b60acb..cde47586ff985 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx @@ -15,7 +15,7 @@ #include "DetectorsBase/Propagator.h" #include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" -#include "TOFWorkflow/ClusterReaderSpec.h" +#include "TOFWorkflowUtils/ClusterReaderSpec.h" #include "TOFWorkflow/TOFMatchedWriterSpec.h" #include "TOFWorkflow/TOFCalibWriterSpec.h" #include "Framework/WorkflowSpec.h" diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx index 5c92aa58f9a85..2dbea93775e0f 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx @@ -14,7 +14,7 @@ /// @brief Basic DPL workflow for TOF reconstruction starting from digits #include "DetectorsBase/Propagator.h" -#include "TOFWorkflow/ClusterReaderSpec.h" +#include "TOFWorkflowUtils/ClusterReaderSpec.h" #include "TOFWorkflow/TOFMatchedWriterSpec.h" #include "TOFWorkflow/TOFCalibWriterSpec.h" #include "Framework/WorkflowSpec.h" diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 9e7dc66a2d20a..51dcba8bb5fed 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -15,17 +15,17 @@ #include "DetectorsBase/Propagator.h" #include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" -#include "TOFWorkflow/DigitReaderSpec.h" -#include "TOFWorkflow/TOFDigitWriterSpec.h" -#include "TOFWorkflow/ClusterReaderSpec.h" -#include "TOFWorkflow/TOFClusterizerSpec.h" -#include "TOFWorkflow/TOFClusterWriterSpec.h" +#include "TOFWorkflowUtils/DigitReaderSpec.h" +#include "TOFWorkflowUtils/TOFDigitWriterSpec.h" +#include "TOFWorkflowUtils/ClusterReaderSpec.h" +#include "TOFWorkflowUtils/TOFClusterizerSpec.h" +#include "TOFWorkflowUtils/TOFClusterWriterSpec.h" #include "TOFWorkflow/TOFMatchedWriterSpec.h" #include "TOFWorkflow/TOFCalibWriterSpec.h" -#include "TOFWorkflow/TOFRawWriterSpec.h" -#include "TOFWorkflow/CompressedDecodingTask.h" -#include "TOFWorkflow/EntropyEncoderSpec.h" -#include "TOFWorkflow/EntropyDecoderSpec.h" +#include "TOFWorkflowUtils/TOFRawWriterSpec.h" +#include "TOFWorkflowUtils/CompressedDecodingTask.h" +#include "TOFWorkflowUtils/EntropyEncoderSpec.h" +#include "TOFWorkflowUtils/EntropyDecoderSpec.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigParamSpec.h" #include "TOFWorkflow/RecoWorkflowSpec.h" diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TrackInterpolationWorkflow.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TrackInterpolationWorkflow.cxx index b51dbfc9e5667..4793d8b86ea2a 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TrackInterpolationWorkflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TrackInterpolationWorkflow.cxx @@ -16,7 +16,7 @@ #include "TPCWorkflow/TrackReaderSpec.h" #include "TPCWorkflow/PublisherSpec.h" #include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" -#include "TOFWorkflow/ClusterReaderSpec.h" +#include "TOFWorkflowUtils/ClusterReaderSpec.h" #include "TOFWorkflow/TOFMatchedReaderSpec.h" #include "Algorithm/RangeTokenizer.h" #include "TPCInterpolationWorkflow/TPCResidualWriterSpec.h" diff --git a/Detectors/TOF/compression/src/tof-compressed-analysis.cxx b/Detectors/TOF/compression/src/tof-compressed-analysis.cxx index 0e610b60b4e41..4f194448841dc 100644 --- a/Detectors/TOF/compression/src/tof-compressed-analysis.cxx +++ b/Detectors/TOF/compression/src/tof-compressed-analysis.cxx @@ -13,7 +13,7 @@ /// @since 2019-12-18 /// @brief Basic DPL workflow for TOF raw data compression -#include "TOFWorkflow/CompressedAnalysisTask.h" +#include "TOFWorkflowUtils/CompressedAnalysisTask.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigParamSpec.h" #include "FairLogger.h" diff --git a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx index e039cd7e8d335..b177a8eca25b1 100644 --- a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx +++ b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx @@ -13,7 +13,7 @@ /// @since 2019-12-18 /// @brief Basic DPL workflow for TOF raw data compression -#include "TOFWorkflow/CompressedInspectorTask.h" +#include "TOFWorkflowUtils/CompressedInspectorTask.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigParamSpec.h" #include "FairLogger.h" diff --git a/Detectors/TOF/workflow/CMakeLists.txt b/Detectors/TOF/workflow/CMakeLists.txt index d75c55259ff79..418837f9c01ce 100644 --- a/Detectors/TOF/workflow/CMakeLists.txt +++ b/Detectors/TOF/workflow/CMakeLists.txt @@ -25,5 +25,5 @@ o2_add_library(TOFWorkflowUtils o2_add_executable(entropy-encoder-workflow SOURCES src/entropy-encoder-workflow.cxx COMPONENT_NAME tof - PUBLIC_LINK_LIBRARIES O2::TOFWorkflow) + PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils) diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/ClusterReaderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/ClusterReaderSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/ClusterReaderSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/ClusterReaderSpec.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysis.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedAnalysis.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysis.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedAnalysis.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysisTask.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedAnalysisTask.h similarity index 98% rename from Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysisTask.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedAnalysisTask.h index 638030454b38d..367ba19b2aa43 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedAnalysisTask.h +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedAnalysisTask.h @@ -17,7 +17,7 @@ #define O2_TOF_COMPRESSEDANALYSISTASK #include "Framework/Task.h" -#include "TOFWorkflow/CompressedAnalysis.h" +#include "TOFWorkflowUtils/CompressedAnalysis.h" #include "TROOT.h" #include "TSystem.h" diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedDecodingTask.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedDecodingTask.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedInspectorTask.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedInspectorTask.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/DigitReaderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/DigitReaderSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/DigitReaderSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/DigitReaderSpec.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/EntropyDecoderSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/EntropyDecoderSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/EntropyDecoderSpec.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/EntropyEncoderSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/EntropyEncoderSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/EntropyEncoderSpec.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/TOFClusterWriterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterWriterSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/TOFClusterWriterSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterWriterSpec.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/TOFClusterizerSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterizerSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/TOFClusterizerSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterizerSpec.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/TOFDigitWriterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/TOFDigitWriterSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSpec.h diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/TOFRawWriterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFRawWriterSpec.h similarity index 100% rename from Detectors/TOF/workflow/include/TOFWorkflow/TOFRawWriterSpec.h rename to Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFRawWriterSpec.h diff --git a/Detectors/TOF/workflow/src/ClusterReaderSpec.cxx b/Detectors/TOF/workflow/src/ClusterReaderSpec.cxx index 87949525d8146..f9c422307bab3 100644 --- a/Detectors/TOF/workflow/src/ClusterReaderSpec.cxx +++ b/Detectors/TOF/workflow/src/ClusterReaderSpec.cxx @@ -14,7 +14,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" -#include "TOFWorkflow/ClusterReaderSpec.h" +#include "TOFWorkflowUtils/ClusterReaderSpec.h" #include "DataFormatsParameters/GRPObject.h" using namespace o2::framework; diff --git a/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx index 4f6037852f186..a329a7a750e95 100644 --- a/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx @@ -13,7 +13,7 @@ /// @since 2020-09-04 /// @brief TOF compressed data analysis task -#include "TOFWorkflow/CompressedAnalysisTask.h" +#include "TOFWorkflowUtils/CompressedAnalysisTask.h" #include "Framework/Task.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index fd2e4a4733112..03ecd071c1a33 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -13,7 +13,7 @@ /// @since 2020-02-25 /// @brief TOF compressed data decoding task -#include "TOFWorkflow/CompressedDecodingTask.h" +#include "TOFWorkflowUtils/CompressedDecodingTask.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" diff --git a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx index 5753434153b2a..07b23eb2131ae 100644 --- a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx @@ -13,7 +13,7 @@ /// @since 2020-01-25 /// @brief TOF compressed data inspector task -#include "TOFWorkflow/CompressedInspectorTask.h" +#include "TOFWorkflowUtils/CompressedInspectorTask.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/Logger.h" diff --git a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx index bfee442814a24..6684255d03898 100644 --- a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx @@ -17,7 +17,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/Logger.h" -#include "TOFWorkflow/DigitReaderSpec.h" +#include "TOFWorkflowUtils/DigitReaderSpec.h" #include "DataFormatsParameters/GRPObject.h" using namespace o2::framework; diff --git a/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx index 7fa7ba15069ae..db048a4e59850 100644 --- a/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx @@ -14,7 +14,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" -#include "TOFWorkflow/EntropyDecoderSpec.h" +#include "TOFWorkflowUtils/EntropyDecoderSpec.h" using namespace o2::framework; diff --git a/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx index e151def630a2d..7af45cc28c8b2 100644 --- a/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/TOF/workflow/src/EntropyEncoderSpec.cxx @@ -15,7 +15,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "TOFBase/Digit.h" -#include "TOFWorkflow/EntropyEncoderSpec.h" +#include "TOFWorkflowUtils/EntropyEncoderSpec.h" using namespace o2::framework; diff --git a/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx index 4d3aa0bacbd9a..9141c68c7ee59 100644 --- a/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx @@ -10,7 +10,7 @@ /// @file TODClusterWriterSpec.cxx -#include "TOFWorkflow/TOFClusterWriterSpec.h" +#include "TOFWorkflowUtils/TOFClusterWriterSpec.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx index c1d6b5bc28415..d842a59781ef3 100644 --- a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "TOFWorkflow/TOFClusterizerSpec.h" +#include "TOFWorkflowUtils/TOFClusterizerSpec.h" #include "Framework/ControlService.h" #include "Framework/DataProcessorSpec.h" #include "Framework/DataRefUtils.h" diff --git a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx index bd4d664bf7c5f..0667003043115 100644 --- a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx @@ -10,7 +10,7 @@ /// @brief Processor spec for a ROOT file writer for TOF digits -#include "TOFWorkflow/TOFDigitWriterSpec.h" +#include "TOFWorkflowUtils/TOFDigitWriterSpec.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx index 858b71717bbc5..6a503127fd47c 100644 --- a/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx @@ -10,7 +10,7 @@ /// @file TODRawWriterSpec.cxx -#include "TOFWorkflow/TOFRawWriterSpec.h" +#include "TOFWorkflowUtils/TOFRawWriterSpec.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/Logger.h" diff --git a/Detectors/TOF/workflow/src/entropy-encoder-workflow.cxx b/Detectors/TOF/workflow/src/entropy-encoder-workflow.cxx index acf2045d728e8..aaa303de91e00 100644 --- a/Detectors/TOF/workflow/src/entropy-encoder-workflow.cxx +++ b/Detectors/TOF/workflow/src/entropy-encoder-workflow.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "TOFWorkflow/EntropyEncoderSpec.h" +#include "TOFWorkflowUtils/EntropyEncoderSpec.h" #include "CommonUtils/ConfigurableParam.h" #include "Framework/ConfigParamSpec.h" diff --git a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx index 3b61c66e454e4..4bde26c686859 100644 --- a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx +++ b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx @@ -37,7 +37,7 @@ // for TOF #include "TOFDigitizerSpec.h" -#include "TOFWorkflow/TOFDigitWriterSpec.h" +#include "TOFWorkflowUtils/TOFDigitWriterSpec.h" // for FT0 #include "FT0DigitizerSpec.h" From a47eda6873b1eadbc990cd1a1a9bddd6b62a8791 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Wed, 30 Sep 2020 12:24:33 +0200 Subject: [PATCH 0828/1751] Fix retrieval of CompressedAnalysis object --- Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx index a329a7a750e95..967353089b65d 100644 --- a/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx @@ -49,7 +49,7 @@ void CompressedAnalysisTask::init(InitContext& ic) return; } - mAnalysis = GetFromMacro<CompressedAnalysis*>(filename, function, "CompressedAnalysis*", "compressed_analysis"); + mAnalysis = GetFromMacro<CompressedAnalysis*>(filename, function, "o2::tof::CompressedAnalysis*", "compressed_analysis"); if (!mAnalysis) { LOG(ERROR) << "Could not retrieve analysis from file: " << filename; mStatus = true; From 3cd9ec07ab31669d971d0320d604e5b02bb05537 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Wed, 30 Sep 2020 17:26:15 +0200 Subject: [PATCH 0829/1751] add vdrift effect using TOF time for TOF-TPC matching --- Detectors/GlobalTracking/src/MatchTOF.cxx | 338 +++++++++++----------- 1 file changed, 171 insertions(+), 167 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 785cc53968909..832f3cc64993b 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -879,8 +879,9 @@ void MatchTOF::doMatching(int sec) Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp); + reachedPoint += step; + if (detIdTemp[2] == -1) { - reachedPoint += step; continue; } @@ -918,10 +919,10 @@ void MatchTOF::doMatching(int sec) if (nStripsCrossedInPropagation == 0 || // we are crossing a strip for the first time... (nStripsCrossedInPropagation >= 1 && (detId[nStripsCrossedInPropagation - 1][0] != detIdTemp[0] || detId[nStripsCrossedInPropagation - 1][1] != detIdTemp[1] || detId[nStripsCrossedInPropagation - 1][2] != detIdTemp[2]))) { // ...or we are crossing a new strip if (nStripsCrossedInPropagation == 0) - // LOG(DEBUG) << "We cross a strip for the first time"; - if (nStripsCrossedInPropagation == 2) { - break; // we have already matched 2 strips, we cannot match more - } + LOG(DEBUG) << "We cross a strip for the first time"; + if (nStripsCrossedInPropagation == 2) { + break; // we have already matched 2 strips, we cannot match more + } nStripsCrossedInPropagation++; } //Printf("nStepsInsideSameStrip[nStripsCrossedInPropagation-1] = %d", nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]); @@ -1098,7 +1099,7 @@ void MatchTOF::doMatching(int sec) //______________________________________________ void MatchTOF::doMatchingForTPC(int sec) { - + printf("here, DoMatch\n"); auto& gasParam = o2::tpc::ParameterGas::Instance(); float vdrift = gasParam.DriftV; @@ -1112,11 +1113,7 @@ void MatchTOF::doMatchingForTPC(int sec) if (!nTracks || !nTOFCls) { return; } - int itof0 = 0; // starting index in TOF clusters for matching of the track - int detId[2][5]; // at maximum one track can fall in 2 strips during the propagation; the second dimention of the array is the TOF det index - float deltaPos[2][3]; // at maximum one track can fall in 2 strips during the propagation; the second dimention of the array is the residuals - o2::track::TrackLTIntegral trkLTInt[2]; // Here we store the integrated track length and time for the (max 2) matched strips - int nStepsInsideSameStrip[2] = {0, 0}; // number of propagation steps in the same strip (since we have maximum 2 strips, it has dimention = 2) + int itof0 = 0; // starting index in TOF clusters for matching of the track float deltaPosTemp[3]; std::array<float, 3> pos; std::array<float, 3> posBeforeProp; @@ -1124,18 +1121,23 @@ void MatchTOF::doMatchingForTPC(int sec) // prematching for TPC only tracks (identify BC candidate to correct z for TPC track accordingly to v_drift) - std::vector<ulong> BCcand; + std::vector<unsigned long> BCcand; + + std::vector<int> nStripsCrossedInPropagation; + std::vector<std::array<std::array<int, 5>, 2>> detId; + std::vector<std::array<o2::track::TrackLTIntegral, 2>> trkLTInt; + std::vector<std::array<std::array<float, 3>, 2>> deltaPos; + std::vector<std::array<int, 2>> nStepsInsideSameStrip; LOG(DEBUG) << "Trying to match %d tracks" << cacheTrk.size(); for (int itrk = 0; itrk < cacheTrk.size(); itrk++) { - int nStripsCrossedInPropagation = 0; // how many strips were hit during the propagation auto& trackWork = mTracksWork[cacheTrk[itrk]]; auto& trefTrk = trackWork.first; auto& intLT = mLTinfos[cacheTrk[itrk]]; int nBCcand = 1; BCcand.clear(); - BCcand.reserve(nBCcand); + nStripsCrossedInPropagation.clear(); int side = (trefTrk.getZ() > 0) ? 1 : -1; @@ -1143,6 +1145,7 @@ void MatchTOF::doMatchingForTPC(int sec) itof0 = 0; double minTrkTime = (trackWork.second.getTimeStamp() - trackWork.second.getTimeStampError()) * 1.E6; // minimum time in ps double maxTrkTime = (trackWork.second.getTimeStamp() + trackWork.second.getTimeStampError()) * 1.E6; // maximum time in ps + for (auto itof = itof0; itof < nTOFCls; itof++) { auto& trefTOF = mTOFClusWork[cacheTOF[itof]]; @@ -1158,7 +1161,7 @@ void MatchTOF::doMatchingForTPC(int sec) if (trefTOF.getZ() * side < 0) continue; - long bc = long(trefTOF.getTime() * Geo::BC_TIME_INPS_INV); + unsigned long bc = (unsigned long)(trefTOF.getTime() * Geo::BC_TIME_INPS_INV); bool isalreadyin = false; @@ -1166,14 +1169,19 @@ void MatchTOF::doMatchingForTPC(int sec) if (bc == BCcand[k]) isalreadyin = true; - if (!isalreadyin) + if (!isalreadyin) { BCcand.emplace_back(bc); + nStripsCrossedInPropagation.emplace_back(0); + } } - - for (int ii = 0; ii < 2; ii++) { - detId[ii][2] = -1; // before trying to match, we need to inizialize the detId corresponding to the strip number to -1; this is the array that we will use to save the det id of the maximum 2 strips matched - nStepsInsideSameStrip[ii] = 0; - } + detId.clear(); + detId.reserve(BCcand.size()); + trkLTInt.clear(); + trkLTInt.reserve(BCcand.size()); + deltaPos.clear(); + deltaPos.reserve(BCcand.size()); + nStepsInsideSameStrip.clear(); + nStepsInsideSameStrip.reserve(BCcand.size()); // printf("%d) ts_error = %f -- z_error = %f\n", itrk, trackWork.second.getTimeStampError(), trackWork.second.getTimeStampError() * vdrift); @@ -1196,18 +1204,20 @@ void MatchTOF::doMatchingForTPC(int sec) } #endif - // initializing - for (int ii = 0; ii < 2; ii++) { - for (int iii = 0; iii < 5; iii++) { - detId[ii][iii] = -1; - } - } - int detIdTemp[5] = {-1, -1, -1, -1, -1}; // TOF detector id at the current propagation point double reachedPoint = mXRef + istep * step; - while (propagateToRefX(trefTrk, reachedPoint, step, intLT) && nStripsCrossedInPropagation <= 2 && reachedPoint < Geo::RMAX) { + // initializing + for (int ibc = 0; ibc < BCcand.size(); ibc++) { + for (int ii = 0; ii < 2; ii++) { + nStepsInsideSameStrip[ibc][ii] = 0; + for (int iii = 0; iii < 5; iii++) { + detId[ibc][ii][iii] = -1; + } + } + } + while (propagateToRefX(trefTrk, reachedPoint, step, intLT) && reachedPoint < Geo::RMAX) { // while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trefTrk, mXRef + istep * step, o2::constants::physics::MassPionCharged, MAXSNP, step, 1, &intLT) && nStripsCrossedInPropagation <= 2 && mXRef + istep * step < Geo::RMAX) { trefTrk.getXYZGlo(pos); @@ -1221,160 +1231,154 @@ void MatchTOF::doMatchingForTPC(int sec) Printf("radius xyz = %f", TMath::Sqrt(posFloat[0]*posFloat[0] + posFloat[1]*posFloat[1] + posFloat[2]*posFloat[2])); */ - for (int idet = 0; idet < 5; idet++) - detIdTemp[idet] = -1; + reachedPoint += step; - Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp); + // check if you fall in a strip + for (int ibc = 0; ibc < BCcand.size(); ibc++) { + for (int idet = 0; idet < 5; idet++) + detIdTemp[idet] = -1; - if (detIdTemp[2] == -1) { - reachedPoint += step; - continue; - } + if (side > 0) + posFloat[2] = pos[2] - vdrift * (trackWork.second.getTimeStamp() - BCcand[ibc] * Geo::BC_TIME_INPS * 1E-6); + else + posFloat[2] = pos[2] + vdrift * (trackWork.second.getTimeStamp() - BCcand[ibc] * Geo::BC_TIME_INPS * 1E-6); - if (nStripsCrossedInPropagation == 0 || // we are crossing a strip for the first time... - (nStripsCrossedInPropagation >= 1 && (detId[nStripsCrossedInPropagation - 1][0] != detIdTemp[0] || detId[nStripsCrossedInPropagation - 1][1] != detIdTemp[1] || detId[nStripsCrossedInPropagation - 1][2] != detIdTemp[2]))) { // ...or we are crossing a new strip - if (nStripsCrossedInPropagation == 0) - // LOG(DEBUG) << "We cross a strip for the first time"; - if (nStripsCrossedInPropagation == 2) { - break; // we have already matched 2 strips, we cannot match more - } - nStripsCrossedInPropagation++; - } - //Printf("nStepsInsideSameStrip[nStripsCrossedInPropagation-1] = %d", nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]); - if (nStepsInsideSameStrip[nStripsCrossedInPropagation - 1] == 0) { - detId[nStripsCrossedInPropagation - 1][0] = detIdTemp[0]; - detId[nStripsCrossedInPropagation - 1][1] = detIdTemp[1]; - detId[nStripsCrossedInPropagation - 1][2] = detIdTemp[2]; - detId[nStripsCrossedInPropagation - 1][3] = detIdTemp[3]; - detId[nStripsCrossedInPropagation - 1][4] = detIdTemp[4]; - deltaPos[nStripsCrossedInPropagation - 1][0] = deltaPosTemp[0]; - deltaPos[nStripsCrossedInPropagation - 1][1] = deltaPosTemp[1]; - deltaPos[nStripsCrossedInPropagation - 1][2] = deltaPosTemp[2]; - trkLTInt[nStripsCrossedInPropagation - 1] = intLT; - // Printf("intLT (after matching to strip %d): length = %f, time (Pion) = %f", nStripsCrossedInPropagation - 1, trkLTInt[nStripsCrossedInPropagation - 1].getL(), trkLTInt[nStripsCrossedInPropagation - 1].getTOF(o2::track::PID::Pion)); - nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]++; - } else { // a further propagation step in the same strip -> update info (we sum up on all matching with strip - we will divide for the number of steps a bit below) - // N.B. the integrated length and time are taken (at least for now) from the first time we crossed the strip, so here we do nothing with those - deltaPos[nStripsCrossedInPropagation - 1][0] += deltaPosTemp[0] + (detIdTemp[4] - detId[nStripsCrossedInPropagation - 1][4]) * Geo::XPAD; // residual in x - deltaPos[nStripsCrossedInPropagation - 1][1] += deltaPosTemp[1]; // residual in y - deltaPos[nStripsCrossedInPropagation - 1][2] += deltaPosTemp[2] + (detIdTemp[3] - detId[nStripsCrossedInPropagation - 1][3]) * Geo::ZPAD; // residual in z - nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]++; - } - } + Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp); - for (Int_t imatch = 0; imatch < nStripsCrossedInPropagation; imatch++) { - // we take as residual the average of the residuals along the propagation in the same strip - deltaPos[imatch][0] /= nStepsInsideSameStrip[imatch]; - deltaPos[imatch][1] /= nStepsInsideSameStrip[imatch]; - deltaPos[imatch][2] /= nStepsInsideSameStrip[imatch]; - // LOG(DEBUG) << "matched strip " << imatch << ": deltaPos[0] = " << deltaPos[imatch][0] << ", deltaPos[1] = " << deltaPos[imatch][1] << ", deltaPos[2] = " << deltaPos[imatch][2] << ", residual (x, z) = " << TMath::Sqrt(deltaPos[imatch][0] * deltaPos[imatch][0] + deltaPos[imatch][2] * deltaPos[imatch][2]); - } + if (detIdTemp[2] == -1) { + continue; + } - if (nStripsCrossedInPropagation == 0) { - continue; // the track never hit a TOF strip during the propagation - } - bool foundCluster = false; - itof0 = 0; - for (auto itof = itof0; itof < nTOFCls; itof++) { - // printf("itof = %d\n", itof); - auto& trefTOF = mTOFClusWork[cacheTOF[itof]]; - // compare the times of the track and the TOF clusters - remember that they both are ordered in time! - //Printf("trefTOF.getTime() = %f, maxTrkTime = %f, minTrkTime = %f", trefTOF.getTime(), maxTrkTime, minTrkTime); + if (nStripsCrossedInPropagation[ibc] == 0 || // we are crossing a strip for the first time... + (nStripsCrossedInPropagation[ibc] >= 1 && (detId[ibc][nStripsCrossedInPropagation[ibc] - 1][0] != detIdTemp[0] || detId[ibc][nStripsCrossedInPropagation[ibc] - 1][1] != detIdTemp[1] || detId[ibc][nStripsCrossedInPropagation[ibc] - 1][2] != detIdTemp[2]))) { // ...or we are crossing a new strip + if (nStripsCrossedInPropagation[ibc] == 0) + LOG(DEBUG) << "We cross a strip for the first time"; + if (nStripsCrossedInPropagation[ibc] == 2) { + continue; // we have already matched 2 strips, we cannot match more + } + nStripsCrossedInPropagation[ibc]++; + } - if (trefTOF.getTime() < minTrkTime) { // this cluster has a time that is too small for the current track, we will get to the next one - //Printf("In trefTOF.getTime() < minTrkTime"); - itof0 = itof + 1; // but for the next track that we will check, we will ignore this cluster (the time is anyway too small) - continue; + //Printf("nStepsInsideSameStrip[nStripsCrossedInPropagation-1] = %d", nStepsInsideSameStrip[nStripsCrossedInPropagation - 1]); + if (nStepsInsideSameStrip[ibc][nStripsCrossedInPropagation[ibc] - 1] == 0) { + detId[ibc][nStripsCrossedInPropagation[ibc] - 1][0] = detIdTemp[0]; + detId[ibc][nStripsCrossedInPropagation[ibc] - 1][1] = detIdTemp[1]; + detId[ibc][nStripsCrossedInPropagation[ibc] - 1][2] = detIdTemp[2]; + detId[ibc][nStripsCrossedInPropagation[ibc] - 1][3] = detIdTemp[3]; + detId[ibc][nStripsCrossedInPropagation[ibc] - 1][4] = detIdTemp[4]; + deltaPos[ibc][nStripsCrossedInPropagation[ibc] - 1][0] = deltaPosTemp[0]; + deltaPos[ibc][nStripsCrossedInPropagation[ibc] - 1][1] = deltaPosTemp[1]; + deltaPos[ibc][nStripsCrossedInPropagation[ibc] - 1][2] = deltaPosTemp[2]; + + trkLTInt[ibc][nStripsCrossedInPropagation[ibc] - 1] = intLT; + // Printf("intLT (after matching to strip %d): length = %f, time (Pion) = %f", nStripsCrossedInPropagation - 1, trkLTInt[nStripsCrossedInPropagation - 1].getL(), trkLTInt[nStripsCrossedInPropagation - 1].getTOF(o2::track::PID::Pion)); + nStepsInsideSameStrip[ibc][nStripsCrossedInPropagation[ibc] - 1]++; + } else { // a further propagation step in the same strip -> update info (we sum up on all matching with strip - we will divide for the number of steps a bit below) + // N.B. the integrated length and time are taken (at least for now) from the first time we crossed the strip, so here we do nothing with those + deltaPos[ibc][nStripsCrossedInPropagation[ibc] - 1][0] += deltaPosTemp[0] + (detIdTemp[4] - detId[ibc][nStripsCrossedInPropagation[ibc] - 1][4]) * Geo::XPAD; // residual in x + deltaPos[ibc][nStripsCrossedInPropagation[ibc] - 1][1] += deltaPosTemp[1]; // residual in y + deltaPos[ibc][nStripsCrossedInPropagation[ibc] - 1][2] += deltaPosTemp[2] + (detIdTemp[3] - detId[ibc][nStripsCrossedInPropagation[ibc] - 1][3]) * Geo::ZPAD; // residual in z + nStepsInsideSameStrip[ibc][nStripsCrossedInPropagation[ibc] - 1]++; + } } - if (trefTOF.getTime() > maxTrkTime) { // no more TOF clusters can be matched to this track - break; + } + for (int ibc = 0; ibc < BCcand.size(); ibc++) { + float minTime = (BCcand[ibc] - 1) * Geo::BC_TIME_INPS; + float maxTime = (BCcand[ibc] + 1) * Geo::BC_TIME_INPS; + for (Int_t imatch = 0; imatch < nStripsCrossedInPropagation[ibc]; imatch++) { + // we take as residual the average of the residuals along the propagation in the same strip + deltaPos[ibc][imatch][0] /= nStepsInsideSameStrip[ibc][imatch]; + deltaPos[ibc][imatch][1] /= nStepsInsideSameStrip[ibc][imatch]; + deltaPos[ibc][imatch][2] /= nStepsInsideSameStrip[ibc][imatch]; + // LOG(DEBUG) << "matched strip " << imatch << ": deltaPos[0] = " << deltaPos[imatch][0] << ", deltaPos[1] = " << deltaPos[imatch][1] << ", deltaPos[2] = " << deltaPos[imatch][2] << ", residual (x, z) = " << TMath::Sqrt(deltaPos[imatch][0] * deltaPos[imatch][0] + deltaPos[imatch][2] * deltaPos[imatch][2]); } - int mainChannel = trefTOF.getMainContributingChannel(); - int indices[5]; - Geo::getVolumeIndices(mainChannel, indices); - - // compute fine correction using cluster position instead of pad center - // this because in case of multiple-hit cluster position is averaged on all pads contributing to the cluster (then error position matrix can be used for Chi2 if nedeed) - int ndigits = 1; - float posCorr[3] = {0, 0, 0}; - - if (trefTOF.isBitSet(Cluster::kLeft)) - posCorr[0] += Geo::XPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUpLeft)) - posCorr[0] += Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDownLeft)) - posCorr[0] += Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUp)) - posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDown)) - posCorr[2] += Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kRight)) - posCorr[0] -= Geo::XPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUpRight)) - posCorr[0] -= Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDownRight)) - posCorr[0] -= Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; - - float ndifInv = 1. / ndigits; - if (ndigits > 1) { - posCorr[0] *= ndifInv; - posCorr[1] *= ndifInv; - posCorr[2] *= ndifInv; + if (nStripsCrossedInPropagation[ibc] == 0) { + continue; // the track never hit a TOF strip during the propagation } - int trackIdTOF; - int eventIdTOF; - int sourceIdTOF; - for (auto iPropagation = 0; iPropagation < nStripsCrossedInPropagation; iPropagation++) { - LOG(DEBUG) << "TOF Cluster [" << itof << ", " << cacheTOF[itof] << "]: indices = " << indices[0] << ", " << indices[1] << ", " << indices[2] << ", " << indices[3] << ", " << indices[4]; - LOG(DEBUG) << "Propagated Track [" << itrk << ", " << cacheTrk[itrk] << "]: detId[" << iPropagation << "] = " << detId[iPropagation][0] << ", " << detId[iPropagation][1] << ", " << detId[iPropagation][2] << ", " << detId[iPropagation][3] << ", " << detId[iPropagation][4]; - float resX = deltaPos[iPropagation][0] - (indices[4] - detId[iPropagation][4]) * Geo::XPAD + posCorr[0]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster - float resZ = deltaPos[iPropagation][2] - (indices[3] - detId[iPropagation][3]) * Geo::ZPAD + posCorr[2]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster - float res = TMath::Sqrt(resX * resX + resZ * resZ); + bool foundCluster = false; + itof0 = 0; + for (auto itof = itof0; itof < nTOFCls; itof++) { + // printf("itof = %d\n", itof); + auto& trefTOF = mTOFClusWork[cacheTOF[itof]]; + // compare the times of the track and the TOF clusters - remember that they both are ordered in time! + //Printf("trefTOF.getTime() = %f, maxTrkTime = %f, minTrkTime = %f", trefTOF.getTime(), maxTrkTime, minTrkTime); + + if (trefTOF.getTime() < minTime) { // this cluster has a time that is too small for the current track, we will get to the next one + //Printf("In trefTOF.getTime() < minTrkTime"); + itof0 = itof + 1; // but for the next track that we will check, we will ignore this cluster (the time is anyway too small) + continue; + } + if (trefTOF.getTime() > maxTime) { // no more TOF clusters can be matched to this track + break; + } - LOG(DEBUG) << "resX = " << resX << ", resZ = " << resZ << ", res = " << res; -#ifdef _ALLOW_TOF_DEBUG_ - fillTOFmatchTree("match0", cacheTOF[itof], indices[0], indices[1], indices[2], indices[3], indices[4], cacheTrk[itrk], iPropagation, detId[iPropagation][0], detId[iPropagation][1], detId[iPropagation][2], detId[iPropagation][3], detId[iPropagation][4], resX, resZ, res, trackWork, trkLTInt[iPropagation].getL(), trkLTInt[iPropagation].getTOF(o2::track::PID::Pion), trefTOF.getTime()); - int tofLabelTrackID[3] = {-1, -1, -1}; - int tofLabelEventID[3] = {-1, -1, -1}; - int tofLabelSourceID[3] = {-1, -1, -1}; - if (mMCTruthON) { - const auto& labelsTOF = mTOFClusLabels.getLabels(mTOFClusSectIndexCache[indices[0]][itof]); - int lsize = labelsTOF.size(); - if (lsize >= 3) - lsize = 3; - for (int ilabel = 0; ilabel < lsize; ilabel++) { - tofLabelTrackID[ilabel] = labelsTOF[ilabel].getTrackID(); - tofLabelEventID[ilabel] = labelsTOF[ilabel].getEventID(); - tofLabelSourceID[ilabel] = labelsTOF[ilabel].getSourceID(); - } - auto& labelTPC = mTPCLabels[mTracksSectIndexCache[sec][itrk]]; - auto& labelITS = mTPCLabels[mTracksSectIndexCache[sec][itrk]]; - fillTOFmatchTreeWithLabels("matchPossibleWithLabels", cacheTOF[itof], indices[0], indices[1], indices[2], indices[3], indices[4], cacheTrk[itrk], iPropagation, detId[iPropagation][0], detId[iPropagation][1], detId[iPropagation][2], detId[iPropagation][3], detId[iPropagation][4], resX, resZ, res, trackWork, labelTPC.getTrackID(), labelTPC.getEventID(), labelTPC.getSourceID(), labelITS.getTrackID(), labelITS.getEventID(), labelITS.getSourceID(), tofLabelTrackID[0], tofLabelEventID[0], tofLabelSourceID[0], tofLabelTrackID[1], tofLabelEventID[1], tofLabelSourceID[1], tofLabelTrackID[2], tofLabelEventID[2], tofLabelSourceID[2], trkLTInt[iPropagation].getL(), trkLTInt[iPropagation].getTOF(o2::track::PID::Pion), trefTOF.getTime()); + int mainChannel = trefTOF.getMainContributingChannel(); + int indices[5]; + Geo::getVolumeIndices(mainChannel, indices); + + // compute fine correction using cluster position instead of pad center + // this because in case of multiple-hit cluster position is averaged on all pads contributing to the cluster (then error position matrix can be used for Chi2 if nedeed) + int ndigits = 1; + float posCorr[3] = {0, 0, 0}; + + if (trefTOF.isBitSet(Cluster::kLeft)) + posCorr[0] += Geo::XPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kUpLeft)) + posCorr[0] += Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kDownLeft)) + posCorr[0] += Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kUp)) + posCorr[2] -= Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kDown)) + posCorr[2] += Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kRight)) + posCorr[0] -= Geo::XPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kUpRight)) + posCorr[0] -= Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; + if (trefTOF.isBitSet(Cluster::kDownRight)) + posCorr[0] -= Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; + + float ndifInv = 1. / ndigits; + if (ndigits > 1) { + posCorr[0] *= ndifInv; + posCorr[1] *= ndifInv; + posCorr[2] *= ndifInv; } -#endif - if (indices[0] != detId[iPropagation][0]) - continue; - if (indices[1] != detId[iPropagation][1]) - continue; - if (indices[2] != detId[iPropagation][2]) - continue; - float chi2 = res; // TODO: take into account also the time! - if (res < mSpaceTolerance) { // matching ok! - LOG(DEBUG) << "MATCHING FOUND: We have a match! between track " << mTracksSectIndexCache[indices[0]][itrk] << " and TOF cluster " << mTOFClusSectIndexCache[indices[0]][itof]; - foundCluster = true; - // set event indexes (to be checked) - evIdx eventIndexTOFCluster(trefTOF.getEntryInTree(), mTOFClusSectIndexCache[indices[0]][itof]); - evIdx eventIndexTracks(mCurrTracksTreeEntry, mTracksSectIndexCache[indices[0]][itrk]); - mMatchedTracksPairs.emplace_back(o2::dataformats::MatchInfoTOF(eventIndexTOFCluster, chi2, trkLTInt[iPropagation], eventIndexTracks)); // TODO: check if this is correct! + int trackIdTOF; + int eventIdTOF; + int sourceIdTOF; + for (auto iPropagation = 0; iPropagation < nStripsCrossedInPropagation[ibc]; iPropagation++) { + LOG(DEBUG) << "TOF Cluster [" << itof << ", " << cacheTOF[itof] << "]: indices = " << indices[0] << ", " << indices[1] << ", " << indices[2] << ", " << indices[3] << ", " << indices[4]; + LOG(DEBUG) << "Propagated Track [" << itrk << ", " << cacheTrk[itrk] << "]: detId[" << iPropagation << "] = " << detId[ibc][iPropagation][0] << ", " << detId[ibc][iPropagation][1] << ", " << detId[ibc][iPropagation][2] << ", " << detId[ibc][iPropagation][3] << ", " << detId[ibc][iPropagation][4]; + float resX = deltaPos[ibc][iPropagation][0] - (indices[4] - detId[ibc][iPropagation][4]) * Geo::XPAD + posCorr[0]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster + float resZ = deltaPos[ibc][iPropagation][2] - (indices[3] - detId[ibc][iPropagation][3]) * Geo::ZPAD + posCorr[2]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster + float res = TMath::Sqrt(resX * resX + resZ * resZ); + if (indices[0] != detId[ibc][iPropagation][0]) + continue; + if (indices[1] != detId[ibc][iPropagation][1]) + continue; + if (indices[2] != detId[ibc][iPropagation][2]) + continue; + LOG(DEBUG) << "resX = " << resX << ", resZ = " << resZ << ", res = " << res; + float chi2 = res; // TODO: take into account also the time! + + if (res < mSpaceTolerance) { // matching ok! + LOG(DEBUG) << "MATCHING FOUND: We have a match! between track " << mTracksSectIndexCache[indices[0]][itrk] << " and TOF cluster " << mTOFClusSectIndexCache[indices[0]][itof]; + foundCluster = true; + // set event indexes (to be checked) + evIdx eventIndexTOFCluster(trefTOF.getEntryInTree(), mTOFClusSectIndexCache[indices[0]][itof]); + evIdx eventIndexTracks(mCurrTracksTreeEntry, mTracksSectIndexCache[indices[0]][itrk]); + mMatchedTracksPairs.emplace_back(o2::dataformats::MatchInfoTOF(eventIndexTOFCluster, chi2, trkLTInt[ibc][iPropagation], eventIndexTracks)); // TODO: check if this is correct! + } } } - } - if (!foundCluster && mMCTruthON) { - const auto& labelTPC = mTPCLabels[mTracksSectIndexCache[sec][itrk]]; - LOG(DEBUG) << "We did not find any TOF cluster for track " << cacheTrk[itrk] << " (label = " << labelTPC << ", pt = " << trefTrk.getPt(); + if (!foundCluster && mMCTruthON) { + const auto& labelTPC = mTPCLabels[mTracksSectIndexCache[sec][itrk]]; + LOG(DEBUG) << "We did not find any TOF cluster for track " << cacheTrk[itrk] << " (label = " << labelTPC << ", pt = " << trefTrk.getPt(); + } } } return; From 7c2eab4d9d238511cc7959db0419cf03f6731afc Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Thu, 1 Oct 2020 10:43:24 +0200 Subject: [PATCH 0830/1751] fix for TOF-TPC matching --- .../include/GlobalTracking/MatchTOF.h | 2 ++ Detectors/GlobalTracking/src/MatchTOF.cxx | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 5319b0574a0db..94ddd7dc4b4ad 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -271,8 +271,10 @@ class MatchTOF ///<working copy of the input tracks std::vector<matchTrack> mTracksWork; ///<track params prepared for matching + time value + std::vector<float> mExtraTPCFwdTime; ///<track extra params for TPC tracks: Fws Max time std::vector<o2::track::TrackLTIntegral> mLTinfos; ///<expected times and others std::vector<Cluster> mTOFClusWork; ///<track params prepared for matching + std::vector<int> mSideTPC; ///<track side for TPC tracks ///< per sector indices of track entry in mTracksWork std::array<std::vector<int>, o2::constants::math::NSectors> mTracksSectIndexCache; diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 832f3cc64993b..45917703f3723 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -543,6 +543,10 @@ bool MatchTOF::prepareTPCTracks() // copy the track params, propagate to reference X and build sector tables mTracksWork.clear(); mTracksWork.reserve(mNumOfTracks); + mSideTPC.clear(); + mSideTPC.reserve(mNumOfTracks); + mExtraTPCFwdTime.clear(); + mExtraTPCFwdTime.reserve(mNumOfTracks); for (int sec = o2::constants::math::NSectors; sec--;) { mTPCTracksSectIndexCache[sec].clear(); @@ -568,6 +572,9 @@ bool MatchTOF::prepareTPCTracks() // set timeInfo.setTimeStamp(trcOrig.getTime0() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); timeInfo.setTimeStampError(trcOrig.getDeltaTBwd() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); + mSideTPC.push_back(trcOrig.hasASideClustersOnly() ? 1 : (trcOrig.hasCSideClustersOnly() ? -1 : 0)); + mExtraTPCFwdTime.push_back(trcOrig.getDeltaTFwd() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); + o2::track::TrackLTIntegral intLT0; //mTPCTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation // make a copy of the TPC track that we have to propagate //o2::tpc::TrackTPC* trc = new o2::tpc::TrackTPC(trcTPCOrig); // this would take the TPCout track @@ -1139,12 +1146,12 @@ void MatchTOF::doMatchingForTPC(int sec) BCcand.clear(); nStripsCrossedInPropagation.clear(); - int side = (trefTrk.getZ() > 0) ? 1 : -1; + int side = mSideTPC[cacheTrk[itrk]]; // look at BC candidates for the track itof0 = 0; double minTrkTime = (trackWork.second.getTimeStamp() - trackWork.second.getTimeStampError()) * 1.E6; // minimum time in ps - double maxTrkTime = (trackWork.second.getTimeStamp() + trackWork.second.getTimeStampError()) * 1.E6; // maximum time in ps + double maxTrkTime = (trackWork.second.getTimeStamp() + mExtraTPCFwdTime[cacheTrk[itrk]]) * 1.E6; // maximum time in ps for (auto itof = itof0; itof < nTOFCls; itof++) { auto& trefTOF = mTOFClusWork[cacheTOF[itof]]; @@ -1240,8 +1247,10 @@ void MatchTOF::doMatchingForTPC(int sec) if (side > 0) posFloat[2] = pos[2] - vdrift * (trackWork.second.getTimeStamp() - BCcand[ibc] * Geo::BC_TIME_INPS * 1E-6); - else + else if (side < 0) posFloat[2] = pos[2] + vdrift * (trackWork.second.getTimeStamp() - BCcand[ibc] * Geo::BC_TIME_INPS * 1E-6); + else + posFloat[2] = pos[2]; Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp); From 3dbf839dbfbb0d6024ac872e76601f8ec8f10d98 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Fri, 2 Oct 2020 11:17:11 +0200 Subject: [PATCH 0831/1751] add some margins in TOF-TPC matching --- Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h | 2 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 94ddd7dc4b4ad..44427c9b324a9 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -274,7 +274,7 @@ class MatchTOF std::vector<float> mExtraTPCFwdTime; ///<track extra params for TPC tracks: Fws Max time std::vector<o2::track::TrackLTIntegral> mLTinfos; ///<expected times and others std::vector<Cluster> mTOFClusWork; ///<track params prepared for matching - std::vector<int> mSideTPC; ///<track side for TPC tracks + std::vector<int8_t> mSideTPC; ///<track side for TPC tracks ///< per sector indices of track entry in mTracksWork std::array<std::vector<int>, o2::constants::math::NSectors> mTracksSectIndexCache; diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 45917703f3723..ec58d5f1adc94 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -571,9 +571,9 @@ bool MatchTOF::prepareTPCTracks() timeEst timeInfo; // set timeInfo.setTimeStamp(trcOrig.getTime0() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); - timeInfo.setTimeStampError(trcOrig.getDeltaTBwd() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); + timeInfo.setTimeStampError((trcOrig.getDeltaTBwd() + 5) * o2::tpc::ParameterElectronics::Instance().ZbinWidth); mSideTPC.push_back(trcOrig.hasASideClustersOnly() ? 1 : (trcOrig.hasCSideClustersOnly() ? -1 : 0)); - mExtraTPCFwdTime.push_back(trcOrig.getDeltaTFwd() * o2::tpc::ParameterElectronics::Instance().ZbinWidth); + mExtraTPCFwdTime.push_back((trcOrig.getDeltaTFwd() + 5) * o2::tpc::ParameterElectronics::Instance().ZbinWidth); o2::track::TrackLTIntegral intLT0; //mTPCTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation // make a copy of the TPC track that we have to propagate @@ -1165,8 +1165,9 @@ void MatchTOF::doMatchingForTPC(int sec) break; } - if (trefTOF.getZ() * side < 0) + if ((trefTOF.getZ() * side < 0) && ((side > 0) != (trackWork.first.getTgl() > 0))) { continue; + } unsigned long bc = (unsigned long)(trefTOF.getTime() * Geo::BC_TIME_INPS_INV); From 5ef5ee48157483946a1a693c609d2f5ffe2bb8d3 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Sun, 4 Oct 2020 20:57:19 +0200 Subject: [PATCH 0832/1751] HistHelpers: abstract histogram definition does not need to know actual root hist type (#4501) --- Analysis/Core/include/Analysis/HistHelpers.h | 13 +++--- Analysis/Tutorials/src/histHelpersTest.cxx | 48 ++++++++++---------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/Analysis/HistHelpers.h index 6684b93f78390..49e7a5b8934d1 100644 --- a/Analysis/Core/include/Analysis/HistHelpers.h +++ b/Analysis/Core/include/Analysis/HistHelpers.h @@ -197,7 +197,6 @@ struct Axis { std::optional<int> nBins{}; }; -template <typename RootHistType> class Hist { public: @@ -226,8 +225,7 @@ class Hist } // add axes defined in other Hist object - template <typename T> - void AddAxes(const Hist<T>& other) + void AddAxes(const Hist& other) { mAxes.insert(mAxes.end(), other.GetAxes().begin(), other.GetAxes().end()); } @@ -238,6 +236,7 @@ class Hist } // create histogram with the defined axes + template <typename RootHistType> std::shared_ptr<RootHistType> Create(const std::string& name, bool useWeights = false) { const std::size_t MAX_DIM{10}; @@ -246,8 +245,8 @@ class Hist return nullptr; int nBins[MAX_DIM]{0}; - double lowerBounds[MAX_DIM]{0.0}; - double upperBounds[MAX_DIM]{0.0}; + double lowerBounds[MAX_DIM]{0.}; + double upperBounds[MAX_DIM]{0.}; // first figure out number of bins and dimensions std::string title = "[ "; @@ -263,7 +262,7 @@ class Hist } // create histogram - std::shared_ptr<RootHistType> hist(HistFactory(name, title, nAxes, nBins, lowerBounds, upperBounds)); + std::shared_ptr<RootHistType> hist(HistFactory<RootHistType>(name, title, nAxes, nBins, lowerBounds, upperBounds)); if (!hist) { LOGF(FATAL, "The number of specified dimensions does not match the type."); @@ -298,6 +297,7 @@ class Hist private: std::vector<Axis> mAxes; + template <typename RootHistType> RootHistType* HistFactory(const std::string& name, const std::string& title, const std::size_t nDim, const int nBins[], const double lowerBounds[], const double upperBounds[]) { @@ -320,6 +320,7 @@ class Hist return nullptr; } + template <typename RootHistType> TAxis* GetAxis(const int i, std::shared_ptr<RootHistType> hist) { if constexpr (std::is_base_of_v<THnBase, RootHistType>) { diff --git a/Analysis/Tutorials/src/histHelpersTest.cxx b/Analysis/Tutorials/src/histHelpersTest.cxx index 0a974f7eea8f3..9f3042cd5e3d6 100644 --- a/Analysis/Tutorials/src/histHelpersTest.cxx +++ b/Analysis/Tutorials/src/histHelpersTest.cxx @@ -71,18 +71,18 @@ struct HistHelpersTest { test->Add<test_3d_TH3I>(new TH3I("test_3d_TH3I", ";x;y;z", 100, 0., 20., 100, 0., 20., 100, 0., 20.)); // alternatively use Hist to generate the histogram and add it to container afterwards - Hist<TH1D> sameAsBefore; + Hist sameAsBefore; sameAsBefore.AddAxis("x", "x", 100, 0., 50.); // via Hist::Create() we can generate the actual root histogram with the requested axes // Parameters: the name and optionally the decision wether to call SumW2 in case we want to fill this histogram with weights - test->Add<test_1d_TH1D_Weight>(sameAsBefore.Create("test_1d_TH1D_Weight", true)); + test->Add<test_1d_TH1D_Weight>(sameAsBefore.Create<TH1D>("test_1d_TH1D_Weight", true)); // this helper enables us to have combinations of flexible + fixed binning in 2d or 3d histograms // (which are not available via default root constructors) - Hist<TH2F> sameButDifferent; + Hist sameButDifferent; sameButDifferent.AddAxis("x", "x", 100, -0.5, 0.5); sameButDifferent.AddAxis("y", "y", {-0.5, -0.48, -0.3, 0.4, 0.5}); // use variable binning for y axsis this time - test->Add<test_2d_TH2F_VarBinningY>(sameButDifferent.Create("test_2d_TH2F_VarBinningY")); + test->Add<test_2d_TH2F_VarBinningY>(sameButDifferent.Create<TH2F>("test_2d_TH2F_VarBinningY")); // also for n dimensional histograms things become much simpler: std::vector<double> ptBins = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, @@ -98,41 +98,41 @@ struct HistHelpersTest { const int nCuts = 5; Axis cutAxis = {"cut", "cut setting", {-0.5, nCuts - 0.5}, nCuts}; - Hist<THnI> myHistogram; + Hist myHistogram; myHistogram.AddAxis(ptAxis); myHistogram.AddAxis(etaAxis); myHistogram.AddAxis("signed1Pt", "q/p_{T}", 200, -8, 8); - test->Add<test_3d_THnI>(myHistogram.Create("test_3d_THnI")); + test->Add<test_3d_THnI>(myHistogram.Create<THnI>("test_3d_THnI")); - Hist<THnSparseI> testSparseHist; + Hist testSparseHist; testSparseHist.AddAxis(ptAxis); testSparseHist.AddAxis(etaAxis); testSparseHist.AddAxis(phiAxis); testSparseHist.AddAxis(centAxis); testSparseHist.AddAxis(cutAxis); - test->Add<test_5d_THnSparseI>(testSparseHist.Create("test_5d_THnSparseI")); + test->Add<test_5d_THnSparseI>(testSparseHist.Create<THnSparseI>("test_5d_THnSparseI")); - Hist<TProfile> testProfile; + Hist testProfile; testProfile.AddAxis(ptAxis); - test->Add<test_1d_TProfile>(testProfile.Create("test_1d_TProfile")); + test->Add<test_1d_TProfile>(testProfile.Create<TProfile>("test_1d_TProfile")); test->Get<TProfile>(test_1d_TProfile)->GetYaxis()->SetTitle("eta profile"); // now add same histogram but intended for weighted filling - test->Add<test_1d_TProfile_Weight>(testProfile.Create("test_1d_TProfile_Weight", true)); + test->Add<test_1d_TProfile_Weight>(testProfile.Create<TProfile>("test_1d_TProfile_Weight", true)); - Hist<TProfile2D> testProfile2d; + Hist testProfile2d; testProfile2d.AddAxis(ptAxis); testProfile2d.AddAxis(etaAxis); - test->Add<test_2d_TProfile2D>(testProfile2d.Create("test_2d_TProfile2D")); + test->Add<test_2d_TProfile2D>(testProfile2d.Create<TProfile2D>("test_2d_TProfile2D")); - Hist<TProfile3D> testProfile3d; + Hist testProfile3d; testProfile3d.AddAxis(ptAxis); testProfile3d.AddAxis(etaAxis); testProfile3d.AddAxis(phiAxis); - test->Add<test_3d_TProfile3D>(testProfile3d.Create("test_3d_TProfile3D")); + test->Add<test_3d_TProfile3D>(testProfile3d.Create<TProfile3D>("test_3d_TProfile3D")); // we can also re-use axis definitions in case they are similar in many histograms: - Hist<THnF> baseDimensions; + Hist baseDimensions; baseDimensions.AddAxis(ptAxis); baseDimensions.AddAxis(etaAxis); baseDimensions.AddAxis(phiAxis); @@ -140,27 +140,27 @@ struct HistHelpersTest { baseDimensions.AddAxis(cutAxis); baseDimensions.AddAxis(centAxis); - Hist<THnF> firstHist = baseDimensions; + Hist firstHist = baseDimensions; firstHist.AddAxis("something", "v (m/s)", 10, -1, 1); - test->Add<test_7d_THnF_first>(firstHist.Create("test_7d_THnF_first")); + test->Add<test_7d_THnF_first>(firstHist.Create<THnF>("test_7d_THnF_first")); - Hist<THnF> secondHist = baseDimensions; + Hist secondHist = baseDimensions; secondHist.AddAxis("somethingElse", "a (m/(s*s))", 10, -1, 1); - test->Add<test_7d_THnF_second>(secondHist.Create("test_7d_THnF_second")); + test->Add<test_7d_THnF_second>(secondHist.Create<THnF>("test_7d_THnF_second")); // or if we want to have the baseDimensions somewhere in between: - Hist<THnC> thirdHist; + Hist thirdHist; thirdHist.AddAxis("myFirstDimension", "a (m/(s*s))", 10, -1, 1); thirdHist.AddAxes(baseDimensions); thirdHist.AddAxis("myLastDimension", "a (m/(s*s))", 10, -1, 1); - test->Add<test_8d_THnC_third>(thirdHist.Create("test_8d_THnC_third")); + test->Add<test_8d_THnC_third>(thirdHist.Create<THnC>("test_8d_THnC_third")); // we can also use the Hist helper tool independent of the HistCollections: - Hist<THnF> myHist; + Hist myHist; myHist.AddAxis(ptAxis); myHist.AddAxis(etaAxis); myHist.AddAxis(phiAxis); - standaloneHist.setObject(myHist.Create("standaloneHist")); + standaloneHist.setObject(myHist.Create<THnF>("standaloneHist")); // now add some more useful histograms kine->Add<pt>(new TH1F("pt", "p_{T};p_{T} [GeV/c]", 100, 0., 5.)); From a6caa7590a56dda601f03a95c7d6552798f1f0e8 Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Mon, 5 Oct 2020 09:10:37 +0200 Subject: [PATCH 0833/1751] MCH: various fixes to MCH workflows (#4493) [MCH] Various fixes to raw workflows - removed references to specific RDH versions - removed obsolete file-to-digits workflow - added cru-page-to-digits workflow, taking the output of the cru-page-reader workflow - input spec of raw-to-digits workflow set to "TF:MCH/RAWDATA" --- Detectors/MUON/MCH/Workflow/CMakeLists.txt | 16 +- .../include/MCHWorkflow/DataDecoderSpec.h | 2 +- .../MUON/MCH/Workflow/src/DataDecoderSpec.cxx | 18 +- .../Workflow/src/cru-page-reader-workflow.cxx | 1 - .../src/cru-page-to-digits-workflow.cxx | 40 +++ .../Workflow/src/file-to-digits-workflow.cxx | 324 ------------------ .../Workflow/src/raw-to-digits-workflow.cxx | 1 + 7 files changed, 53 insertions(+), 349 deletions(-) create mode 100644 Detectors/MUON/MCH/Workflow/src/cru-page-to-digits-workflow.cxx delete mode 100644 Detectors/MUON/MCH/Workflow/src/file-to-digits-workflow.cxx diff --git a/Detectors/MUON/MCH/Workflow/CMakeLists.txt b/Detectors/MUON/MCH/Workflow/CMakeLists.txt index f9fb3cf4548a6..45483c603ba46 100644 --- a/Detectors/MUON/MCH/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MCH/Workflow/CMakeLists.txt @@ -13,15 +13,7 @@ o2_add_library(MCHWorkflow TARGETVARNAME targetName PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::MCHRawDecoder Boost::program_options O2::MCHRawImplHelpers RapidJSON::RapidJSON O2::MCHMappingInterface O2::MCHPreClustering - O2::MCHMappingImpl3 O2::MCHRawElecMap O2::MCHBase O2::MCHClustering) - -o2_add_executable( - file-to-digits-workflow - SOURCES src/file-to-digits-workflow.cxx - COMPONENT_NAME mch - PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::MCHRawDecoder Boost::program_options - O2::MCHRawImplHelpers O2::MCHMappingInterface - O2::MCHMappingImpl3 O2::MCHRawElecMap O2::MCHBase) + O2::MCHMappingImpl4 O2::MCHRawElecMap O2::MCHBase O2::MCHClustering) o2_add_executable( cru-page-reader-workflow @@ -41,6 +33,12 @@ o2_add_executable( COMPONENT_NAME mch PUBLIC_LINK_LIBRARIES O2::MCHWorkflow) +o2_add_executable( + cru-page-to-digits-workflow + SOURCES src/cru-page-to-digits-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::MCHWorkflow) + o2_add_executable( digits-to-preclusters-workflow SOURCES src/digits-to-preclusters-workflow.cxx diff --git a/Detectors/MUON/MCH/Workflow/include/MCHWorkflow/DataDecoderSpec.h b/Detectors/MUON/MCH/Workflow/include/MCHWorkflow/DataDecoderSpec.h index f8bc1c21582a4..57820cd722f47 100644 --- a/Detectors/MUON/MCH/Workflow/include/MCHWorkflow/DataDecoderSpec.h +++ b/Detectors/MUON/MCH/Workflow/include/MCHWorkflow/DataDecoderSpec.h @@ -27,7 +27,7 @@ namespace mch namespace raw { -o2::framework::DataProcessorSpec getDecodingSpec(); +o2::framework::DataProcessorSpec getDecodingSpec(std::string inputSpec = "TF:MCH/RAWDATA"); } // end namespace raw } // end namespace mch diff --git a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx index 40386ffe06010..ce7dc048bf95b 100644 --- a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx @@ -43,11 +43,6 @@ #include "MCHWorkflow/DataDecoderSpec.h" #include "DetectorsRaw/RDHUtils.h" -namespace o2::header -{ -extern std::ostream& operator<<(std::ostream&, const o2::header::RAWDataHeaderV4&); -} - namespace o2 { namespace mch @@ -250,18 +245,14 @@ class DataDecoderTask DPLRawParser parser(inputs, o2::framework::select("TF:MCH/RAWDATA")); for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { - // retrieving RDH v4 - auto const* rdh = it.get_if<o2::header::RAWDataHeaderV4>(); - // retrieving the raw pointer of the page + auto const* rdh = it.get_if<RDH>(); auto const* raw = it.raw(); - // size of payload size_t payloadSize = it.size(); - if (payloadSize == 0) { continue; } - gsl::span<const std::byte> buffer(reinterpret_cast<const std::byte*>(raw), sizeof(o2::header::RAWDataHeaderV4) + payloadSize); + gsl::span<const std::byte> buffer(reinterpret_cast<const std::byte*>(raw), sizeof(RDH) + payloadSize); decodeBuffer(buffer, digits); } } @@ -356,12 +347,11 @@ class DataDecoderTask }; // namespace raw //_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getDecodingSpec() +o2::framework::DataProcessorSpec getDecodingSpec(std::string inputSpec) { return DataProcessorSpec{ "DataDecoder", - //o2::framework::select("TF:MCH/RAWDATA, re:ROUT/RAWDATA"), - o2::framework::select("readout:ROUT/RAWDATA"), + o2::framework::select(inputSpec.c_str()), Outputs{OutputSpec{"MCH", "DIGITS", 0, Lifetime::Timeframe}, OutputSpec{"MCH", "ORBITS", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<DataDecoderTask>()}, Options{{"print", VariantType::Bool, false, {"print digits"}}, diff --git a/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx index 3ce5b2ac6cb49..ab31062abb47b 100644 --- a/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx +++ b/Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx @@ -8,7 +8,6 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// /// /// \file cru-page-reader-workflow.cxx /// \author Andrea Ferrero diff --git a/Detectors/MUON/MCH/Workflow/src/cru-page-to-digits-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/cru-page-to-digits-workflow.cxx new file mode 100644 index 0000000000000..2c73d33108a41 --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/cru-page-to-digits-workflow.cxx @@ -0,0 +1,40 @@ +// 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 cru-page-to-digits-workflow.cxx +/// \author Andrea Ferrero +/// +/// \brief This is an executable that runs the decoding via DPL. +/// +/// This is an executable that takes a raw buffer from the Data Processing Layer, runs the decoding and sends the digits via the Data Processing Layer. +/// The decoder expects an input buffer in the format generated by o2-mch-cru-page-reader-workflow +/// + +#include "Framework/WorkflowSpec.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/CallbackService.h" +#include "Framework/ControlService.h" +#include "Framework/Task.h" +#include "Framework/runDataProcessing.h" +#include "MCHWorkflow/DataDecoderSpec.h" + +using namespace o2; +using namespace o2::framework; + +WorkflowSpec defineDataProcessing(const ConfigContext&) +{ + WorkflowSpec specs; + + DataProcessorSpec producer = o2::mch::raw::getDecodingSpec("readout:ROUT/RAWDATA"); + specs.push_back(producer); + + return specs; +} diff --git a/Detectors/MUON/MCH/Workflow/src/file-to-digits-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/file-to-digits-workflow.cxx deleted file mode 100644 index 4406ddb7ca3a6..0000000000000 --- a/Detectors/MUON/MCH/Workflow/src/file-to-digits-workflow.cxx +++ /dev/null @@ -1,324 +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. - -/// -/// \file runFileReader.cxx -/// \author Andrea Ferrero -/// -/// \brief This is an executable that reads a data file from disk and sends the data to QC via DPL. -/// -/// This is an executable that reads a data file from disk and sends the data to QC via the Data Processing Layer. -/// It can be used as a data source for QC development. For example, one can do: -/// \code{.sh} -/// o2-qc-run-file-reader --infile=some_data_file | o2-qc --config json://${QUALITYCONTROL_ROOT}/etc/your_config.json -/// \endcode -/// - -#include <random> -#include <iostream> -#include <fstream> -#include <stdexcept> -#include "Framework/CallbackService.h" -#include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/Lifetime.h" -#include "Framework/Output.h" -#include "Framework/Task.h" -#include "Framework/WorkflowSpec.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/runDataProcessing.h" - -#include "DPLUtils/DPLRawParser.h" -#include "MCHBase/Digit.h" -#include "Headers/RAWDataHeader.h" -#include "MCHRawCommon/DataFormats.h" -#include "MCHRawDecoder/PageDecoder.h" -#include "MCHRawElecMap/Mapper.h" -#include "MCHMappingInterface/Segmentation.h" -#include "DetectorsRaw/RDHUtils.h" - -using namespace o2; -using namespace o2::framework; - -struct CRUheader { - uint8_t header_version; - uint8_t header_size; - uint16_t block_length; - uint16_t fee_id; - uint8_t priority_bit; - uint8_t reserved_1; - uint16_t next_packet_offset; - uint16_t memory_size; - uint8_t link_id; - uint8_t packet_counter; - uint16_t cru_id : 12; - uint8_t dpw_id : 4; - uint32_t hb_orbit; - //uint16_t cru_id; - //uint8_t dummy1; - //uint64_t dummy2; -}; - -namespace o2::header -{ -extern std::ostream& operator<<(std::ostream&, const o2::header::RAWDataHeaderV4&); -} - -namespace o2 -{ -namespace mch -{ -namespace raw -{ - -using namespace o2; -using namespace o2::framework; -using namespace o2::mch::mapping; -using RDHv4 = o2::header::RAWDataHeaderV4; - -std::array<int, 64> refManu2ds_st345 = { - 63, 62, 61, 60, 59, 57, 56, 53, 51, 50, 47, 45, 44, 41, 38, 35, - 36, 33, 34, 37, 32, 39, 40, 42, 43, 46, 48, 49, 52, 54, 55, 58, - 7, 8, 5, 2, 6, 1, 3, 0, 4, 9, 10, 15, 17, 18, 22, 25, - 31, 30, 29, 28, 27, 26, 24, 23, 20, 21, 16, 19, 12, 14, 11, 13}; -std::array<int, 64> refDs2manu_st345; - -int manu2ds(int i) -{ - return refManu2ds_st345[i]; -} - -int ds2manu(int i) -{ - return refDs2manu_st345[i]; -} - -class FileReaderTask -{ - void decodeBuffer(gsl::span<const std::byte> page, std::vector<o2::mch::Digit>& digits) - { - size_t ndigits{0}; - - auto channelHandler = [&](DsElecId dsElecId, uint8_t channel, o2::mch::raw::SampaCluster sc) { - auto s = asString(dsElecId); - channel = ds2manu(int(channel)); - if (mPrint) { - auto ch = fmt::format("{}-CH{} samples={}", s, channel, sc.samples.size()); - std::cout << ch << std::endl; - } - double digitadc(0); - //for (auto d = 0; d < sc.nofSamples(); d++) { - for (auto d = 0; d < sc.samples.size(); d++) { - digitadc += sc.samples[d]; - } - - int deId = -1; - int dsIddet = -1; - if (auto opt = Elec2Det(dsElecId); opt.has_value()) { - DsDetId dsDetId = opt.value(); - dsIddet = dsDetId.dsId(); - deId = dsDetId.deId(); - } - if (dsIddet < 0 || deId < 0) { - std::cout << "SOLAR " << (int)dsElecId.solarId() - << " DS " << (int)dsElecId.elinkId() << " (" << (int)dsElecId.elinkGroupId() << "," << (int)dsElecId.elinkIndexInGroup() << ")" - << " CHIP " << ((int)channel) / 32 << " CH " << ((int)channel) % 32 << " ADC " << digitadc << " DE# " << deId << " DSid " << dsIddet << std::endl; - return; - } - - int padId = -1; - try { - const Segmentation& segment = segmentation(deId); - //Segmentation segment(deId); - - padId = segment.findPadByFEE(dsIddet, int(channel)); - if (mPrint) - std::cout << "DS " << (int)dsElecId.elinkId() << " CHIP " << ((int)channel) / 32 << " CH " << ((int)channel) % 32 << " ADC " << digitadc << " DE# " << deId << " DSid " << dsIddet << " PadId " << padId << std::endl; - } catch (const std::exception& e) { - return; - } - - o2::mch::Digit::Time time; - - digits.emplace_back(o2::mch::Digit(deId, padId, digitadc, time, sc.nofSamples())); - //o2::mch::Digit& mchdigit = digits.back(); - //mchdigit.setDetID(deId); - //mchdigit.setPadID(padId); - //mchdigit.setADC(digitadc); - //mchdigit.setTimeStamp(time); - - if (mPrint) - std::cout << "DIGIT STORED:\nADC " << digits.back().getADC() << " DE# " << digits.back().getDetID() << " PadId " << digits.back().getPadID() << " time " << digits.back().getTime().sampaTime << std::endl; - ++ndigits; - }; - - const auto patchPage = [&](gsl::span<const std::byte> rdhBuffer) { - auto rdhPtr = const_cast<void*>(reinterpret_cast<const void*>(rdhBuffer.data())); - nrdhs++; - auto cruId = o2::raw::RDHUtils::getCRUID(rdhPtr); - auto endpoint = o2::raw::RDHUtils::getEndPointID(rdhPtr); - o2::raw::RDHUtils::setFEEID(rdhPtr, cruId * 2 + endpoint); - if (mPrint) { - std::cout << nrdhs << "--\n"; - o2::raw::RDHUtils::printRDH(rdhPtr); - } - }; - - patchPage(page); - if (!decoder.has_value()) - decoder = o2::mch::raw::createPageDecoder(page, channelHandler); - decoder.value()(page); - } - - public: - //_________________________________________________________________________________________________ - void init(framework::InitContext& ic) - { - /// Get the input file and other options from the context - LOG(INFO) << "initializing file reader"; - - for (int i = 0; i < 64; i++) { - for (int j = 0; j < 64; j++) { - if (refManu2ds_st345[j] != i) - continue; - refDs2manu_st345[i] = j; - break; - } - } - - Elec2Det = createElec2DetMapper<ElectronicMapperGenerated>(); - fee2Solar = o2::mch::raw::createFeeLink2SolarMapper<ElectronicMapperGenerated>(); - nrdhs = 0; - - mFrameMax = ic.options().get<int>("frames"); - mPrint = ic.options().get<bool>("print"); - - auto inputFileName = ic.options().get<std::string>("infile"); - mInputFile.open(inputFileName, std::ios::binary); - if (!mInputFile.is_open()) { - throw std::invalid_argument("Cannot open input file \"" + inputFileName + "\""); - } - - auto stop = [this]() { - /// close the input file - LOG(INFO) << "stop file reader"; - this->mInputFile.close(); - }; - ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); - } - - //_________________________________________________________________________________________________ - void run(framework::ProcessingContext& pc) - { - std::vector<o2::mch::Digit> digits; - - uint32_t CRUbuf[4 * 4]; - CRUheader CRUh; - /// send one RDH block via DPL - - int RDH_BLOCK_SIZE = 8192; - - if (mFrameMax == 0) - return; - //printf("mFrameMax: %d\n", mFrameMax); - if (mFrameMax > 0) - mFrameMax -= 1; - - mInputFile.read((char*)(&CRUbuf), sizeof(CRUbuf)); - memcpy(&CRUh, CRUbuf, sizeof(CRUheader)); - if (CRUh.header_version != 4 || CRUh.header_size != 64) - return; - - RDH_BLOCK_SIZE = CRUh.next_packet_offset; - - char* buf = (char*)malloc(RDH_BLOCK_SIZE); - memcpy(buf, CRUbuf, CRUh.header_size); - - mInputFile.read(buf + CRUh.header_size, RDH_BLOCK_SIZE - CRUh.header_size); - if (mInputFile.fail()) { - if (mPrint) { - LOG(INFO) << "end of file reached"; - } - free(buf); - pc.services().get<ControlService>().endOfStream(); - return; // probably reached eof - } - - gsl::span<const std::byte> buffer(reinterpret_cast<const std::byte*>(buf), RDH_BLOCK_SIZE); - decodeBuffer(buffer, digits); - - if (mPrint) { - for (auto d : digits) { - std::cout << " DE# " << d.getDetID() << " PadId " << d.getPadID() << " ADC " << d.getADC() << " time " << d.getTime().sampaTime << std::endl; - } - } - - const size_t OUT_SIZE = sizeof(o2::mch::Digit) * digits.size(); - - /// send the output buffer via DPL - char* outbuffer = nullptr; - outbuffer = (char*)realloc(outbuffer, OUT_SIZE); - memcpy(outbuffer, digits.data(), OUT_SIZE); - - // create the output message - auto freefct = [](void* data, void*) { free(data); }; - pc.outputs().adoptChunk(Output{"MCH", "DIGITS", 0}, outbuffer, OUT_SIZE, freefct, nullptr); - } - - private: - std::function<std::optional<DsDetId>(DsElecId)> Elec2Det; - std::function<std::optional<uint16_t>(FeeLinkId id)> fee2Solar; - std::optional<o2::mch::raw::PageDecoder> decoder; - size_t nrdhs{0}; - - std::ifstream mInputFile{}; ///< input file - int mFrameMax; ///< number of frames to process - bool mPrint = false; ///< print digits -}; - -//_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getFileReaderSpec() -{ - return DataProcessorSpec{ - "FileReader", - Inputs{}, - Outputs{OutputSpec{"MCH", "DIGITS", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask<FileReaderTask>()}, - Options{{"infile", VariantType::String, "data.raw", {"input file name"}}}}; -} - -} // end namespace raw -} // end namespace mch -} // end namespace o2 - -using namespace o2; -using namespace o2::framework; - -// clang-format off -WorkflowSpec defineDataProcessing(const ConfigContext&) -{ - WorkflowSpec specs; - - // The producer to generate some data in the workflow - DataProcessorSpec producer{ - "FileReader", - Inputs{}, - Outputs{OutputSpec{"MCH", "DIGITS", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask<o2::mch::raw::FileReaderTask>()}, - Options{ { "infile", VariantType::String, "", { "input file name" } }, - {"print", VariantType::Bool, false, {"print digits"}}, - { "frames", VariantType::Int, -1, { "number of frames to process" } }} - }; - specs.push_back(producer); - - return specs; -} -// clang-format on diff --git a/Detectors/MUON/MCH/Workflow/src/raw-to-digits-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/raw-to-digits-workflow.cxx index efbf0357c50c6..2cad8309540fd 100644 --- a/Detectors/MUON/MCH/Workflow/src/raw-to-digits-workflow.cxx +++ b/Detectors/MUON/MCH/Workflow/src/raw-to-digits-workflow.cxx @@ -15,6 +15,7 @@ /// \brief This is an executable that runs the decoding via DPL. /// /// This is an executable that takes a raw buffer from the Data Processing Layer, runs the decoding and sends the digits via the Data Processing Layer. +/// The decoder expects an input buffer in the format generated by o2-raw-file-reader-workflow /// #include "Framework/WorkflowSpec.h" From 4e0010f379b5ea8bf2a9c2da644ac90dbd596889 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Thu, 27 Aug 2020 15:36:22 +0200 Subject: [PATCH 0834/1751] TPCClusterFinder: Enable calibrating parameters. --- GPU/GPUTracking/Base/GPUSettingsList.h | 5 +++++ .../TPCClusterFinder/ClusterAccumulator.cxx | 7 ++++--- .../TPCClusterFinder/ClusterAccumulator.h | 2 +- .../TPCClusterFinder/GPUTPCCFClusterizer.cxx | 17 +++++++++-------- .../TPCClusterFinder/GPUTPCCFClusterizer.h | 6 +++--- .../GPUTPCCFNoiseSuppression.cxx | 15 +++++++++------ .../GPUTPCCFNoiseSuppression.h | 4 ++-- .../TPCClusterFinder/GPUTPCCFPeakFinder.cxx | 11 +++++++---- .../TPCClusterFinder/GPUTPCCFPeakFinder.h | 4 ++-- .../TPCClusterFinder/GPUTPCClusterFinder.h | 1 + .../TPCClusterFinder/TPCCFCalibration.h | 1 + .../TPCClusterFinder/clusterFinderDefs.h | 18 ++---------------- 12 files changed, 46 insertions(+), 45 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index bd5820e0f9cca..bc7e4e95f277b 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -43,6 +43,11 @@ AddOption(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required AddOption(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") AddOption(TrackReferenceX, float, 1000.f, "", 0, "Transport all tracks to this X after tracking (disabled if > 500, auto = 1000)") AddOption(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") +AddOption(tpcCFqmaxCutoff, unsigned char, 3, "", 0, "Cluster Finder rejects cluster with qmax below this threshold") +AddOption(tpcCFqtotCutoff, unsigned char, 0, "", 0, "Cluster Finder rejects cluster with qtot below this threshold") +AddOption(tpcCFinnerThreshold, unsigned char, 0, "", 0, "Cluster Finder extends cluster if inner charge above this threshold") +AddOption(tpcCFminSplitNum, unsigned char, 1, "", 0, "Minimum number of split charges in a cluster for the cluster to be marked as split") +AddOption(tpcCFnoiseSuppressionEpsilon, unsigned char, 10, "", 0, "Cluster Finder: Difference between peak and charge for the charge to count as a minima during noise suppression") AddOption(NWays, char, 3, "", 0, "Do N fit passes in final fit of merger") AddOption(NWaysOuter, char, 0, "", 0, "Store outer param") AddOption(RejectMode, char, 5, "", 0, "0: no limit on rejection or missed hits, >0: break after n rejected hits, <0: reject at max -n hits") diff --git a/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx b/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx index 0283f062e7c2f..5405a720abc94 100644 --- a/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx @@ -17,16 +17,17 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace GPUCA_NAMESPACE::gpu::tpccf; -GPUd() void ClusterAccumulator::toNative(const ChargePos& pos, Charge q, tpc::ClusterNative& cn) const +GPUd() void ClusterAccumulator::toNative(const ChargePos& pos, Charge q, int minSplitNum, tpc::ClusterNative& cn) const { bool isEdgeCluster = CfUtils::isAtEdge(pos); - bool wasSplitInTime = mSplitInTime >= MIN_SPLIT_NUM; - bool wasSplitInPad = mSplitInPad >= MIN_SPLIT_NUM; + bool wasSplitInTime = mSplitInTime >= minSplitNum; + bool wasSplitInPad = mSplitInPad >= minSplitNum; uchar flags = 0; flags |= (isEdgeCluster) ? tpc::ClusterNative::flagEdge : 0; flags |= (wasSplitInTime) ? tpc::ClusterNative::flagSplitTime : 0; flags |= (wasSplitInPad) ? tpc::ClusterNative::flagSplitPad : 0; + // TODO: set single flag! cn.qMax = q; cn.qTot = mQtot; diff --git a/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.h b/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.h index 7711868041901..d39a4ed10496e 100644 --- a/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.h +++ b/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.h @@ -38,7 +38,7 @@ class ClusterAccumulator GPUd() tpccf::Charge updateOuter(PackedCharge, tpccf::Delta2); GPUd() void finalize(const ChargePos&, tpccf::Charge, tpccf::TPCTime); - GPUd() void toNative(const ChargePos&, tpccf::Charge, tpc::ClusterNative&) const; + GPUd() void toNative(const ChargePos&, tpccf::Charge, int, tpc::ClusterNative&) const; private: float mQtot = 0; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx index c3002db1c717e..36f0e1f0d6c92 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.cxx @@ -33,7 +33,7 @@ GPUdii() void GPUTPCCFClusterizer::Thread<0>(int nBlocks, int nThreads, int iBlo tpc::ClusterNative* clusterOut = (onlyMC) ? nullptr : clusterer.mPclusterByRow; - GPUTPCCFClusterizer::computeClustersImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), clusterer.mPmemory->fragment, smem, chargeMap, clusterer.mPfilteredPeakPositions, CPU_PTR(&labelAcc), clusterer.mPmemory->counters.nClusters, clusterer.mNMaxClusterPerRow, clusterer.mPclusterInRow, clusterOut, clusterer.mPclusterPosInRow); + GPUTPCCFClusterizer::computeClustersImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), clusterer.mPmemory->fragment, smem, chargeMap, clusterer.mPfilteredPeakPositions, clusterer.Param().rec, CPU_PTR(&labelAcc), clusterer.mPmemory->counters.nClusters, clusterer.mNMaxClusterPerRow, clusterer.mPclusterInRow, clusterOut, clusterer.mPclusterPosInRow); } GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads, int iBlock, int iThread, @@ -41,6 +41,7 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads GPUSharedMemory& smem, const Array2D<PackedCharge>& chargeMap, const ChargePos* filteredPeakPositions, + const GPUSettingsRec& calib, MCLabelAccumulator* labelAcc, uint clusternum, uint maxClusterPerRow, @@ -60,6 +61,7 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads CPU_ONLY(labelAcc->collect(pos, charge)); buildCluster( + calib, chargeMap, pos, smem.posBcast, @@ -74,13 +76,9 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads pc.finalize(pos, charge, fragment.start); tpc::ClusterNative myCluster; - pc.toNative(pos, charge, myCluster); + pc.toNative(pos, charge, calib.tpcCFminSplitNum, myCluster); -#if defined(CUT_QTOT) - bool aboveQTotCutoff = (pc.Q > QTOT_CUTOFF); -#else - bool aboveQTotCutoff = true; -#endif + bool aboveQTotCutoff = (myCluster.qTot > calib.tpcCFqtotCutoff); if (!aboveQTotCutoff) { clusterPosInRow[idx] = maxClusterPerRow; @@ -106,6 +104,7 @@ GPUdii() void GPUTPCCFClusterizer::computeClustersImpl(int nBlocks, int nThreads } GPUdii() void GPUTPCCFClusterizer::updateClusterInner( + const GPUSettingsRec& calib, ushort lid, ushort N, const PackedCharge* buf, @@ -127,7 +126,7 @@ GPUdii() void GPUTPCCFClusterizer::updateClusterInner( CPU_ONLY( labelAcc->collect(pos.delta(d), q)); - aboveThreshold |= (uchar(q > CHARGE_THRESHOLD) << i); + aboveThreshold |= (uchar(q > calib.tpcCFinnerThreshold) << i); } innerAboveThreshold[lid] = aboveThreshold; @@ -160,6 +159,7 @@ GPUdii() void GPUTPCCFClusterizer::updateClusterOuter( } GPUdii() void GPUTPCCFClusterizer::buildCluster( + const GPUSettingsRec& calib, const Array2D<PackedCharge>& chargeMap, ChargePos pos, ChargePos* posBcast, @@ -184,6 +184,7 @@ GPUdii() void GPUTPCCFClusterizer::buildCluster( posBcast, buf); updateClusterInner( + calib, ll, 8, buf, diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h index f47278a54038c..fab830119aa0a 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFClusterizer.h @@ -58,14 +58,14 @@ class GPUTPCCFClusterizer : public GPUKernelTemplate template <int iKernel = defaultKernel> GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, char); - static GPUd() void computeClustersImpl(int, int, int, int, const CfFragment&, GPUSharedMemory&, const Array2D<PackedCharge>&, const ChargePos*, MCLabelAccumulator*, uint, uint, uint*, tpc::ClusterNative*, uint*); + static GPUd() void computeClustersImpl(int, int, int, int, const CfFragment&, GPUSharedMemory&, const Array2D<PackedCharge>&, const ChargePos*, const GPUSettingsRec&, MCLabelAccumulator*, uint, uint, uint*, tpc::ClusterNative*, uint*); private: - static GPUd() void updateClusterInner(ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*, uchar*); + static GPUd() void updateClusterInner(const GPUSettingsRec&, ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*, uchar*); static GPUd() void updateClusterOuter(ushort, ushort, ushort, ushort, const PackedCharge*, const ChargePos&, ClusterAccumulator*, MCLabelAccumulator*); - static GPUd() void buildCluster(const Array2D<PackedCharge>&, ChargePos, ChargePos*, PackedCharge*, uchar*, ClusterAccumulator*, MCLabelAccumulator*); + static GPUd() void buildCluster(const GPUSettingsRec&, const Array2D<PackedCharge>&, ChargePos, ChargePos*, PackedCharge*, uchar*, ClusterAccumulator*, MCLabelAccumulator*); static GPUd() uint sortIntoBuckets(const tpc::ClusterNative&, uint, uint, uint*, tpc::ClusterNative*); }; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx index d2fe88b7e8857..b80258e8d2de2 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.cxx @@ -25,7 +25,7 @@ GPUdii() void GPUTPCCFNoiseSuppression::Thread<GPUTPCCFNoiseSuppression::noiseSu { Array2D<PackedCharge> chargeMap(reinterpret_cast<PackedCharge*>(clusterer.mPchargeMap)); Array2D<uchar> isPeakMap(clusterer.mPpeakMap); - noiseSuppressionImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, chargeMap, isPeakMap, clusterer.mPpeakPositions, clusterer.mPmemory->counters.nPeaks, clusterer.mPisPeak); + noiseSuppressionImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, clusterer.Param().rec, chargeMap, isPeakMap, clusterer.mPpeakPositions, clusterer.mPmemory->counters.nPeaks, clusterer.mPisPeak); } template <> @@ -36,6 +36,7 @@ GPUdii() void GPUTPCCFNoiseSuppression::Thread<GPUTPCCFNoiseSuppression::updateP } GPUdii() void GPUTPCCFNoiseSuppression::noiseSuppressionImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, + const GPUSettingsRec& calibration, const Array2D<PackedCharge>& chargeMap, const Array2D<uchar>& peakMap, const ChargePos* peakPositions, @@ -51,6 +52,7 @@ GPUdii() void GPUTPCCFNoiseSuppression::noiseSuppressionImpl(int nBlocks, int nT findMinimaAndPeaks( chargeMap, peakMap, + calibration, charge, pos, smem.posBcast, @@ -161,6 +163,7 @@ GPUdi() bool GPUTPCCFNoiseSuppression::keepPeak( GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( const Array2D<PackedCharge>& chargeMap, const Array2D<uchar>& peakMap, + const GPUSettingsRec& calibration, float q, const ChargePos& pos, ChargePos* posBcast, @@ -204,7 +207,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( 2, 16, q, - NOISE_SUPPRESSION_MINIMA_EPSILON, + calibration.tpcCFnoiseSuppressionEpsilon, minimas, bigger); @@ -226,7 +229,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( 16, 0, q, - NOISE_SUPPRESSION_MINIMA_EPSILON, + calibration.tpcCFnoiseSuppressionEpsilon, minimas, bigger); } @@ -249,7 +252,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( 16, 18, q, - NOISE_SUPPRESSION_MINIMA_EPSILON, + calibration.tpcCFnoiseSuppressionEpsilon, minimas, bigger); } @@ -273,7 +276,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( 16, 0, q, - NOISE_SUPPRESSION_MINIMA_EPSILON, + calibration.tpcCFnoiseSuppressionEpsilon, minimas, bigger); } @@ -296,7 +299,7 @@ GPUd() void GPUTPCCFNoiseSuppression::findMinimaAndPeaks( 16, 18, q, - NOISE_SUPPRESSION_MINIMA_EPSILON, + calibration.tpcCFnoiseSuppressionEpsilon, minimas, bigger); } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h index a9a385203be20..4cb04bacb4a90 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFNoiseSuppression.h @@ -57,7 +57,7 @@ class GPUTPCCFNoiseSuppression : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUd() void noiseSuppressionImpl(int, int, int, int, GPUSharedMemory&, const Array2D<PackedCharge>&, const Array2D<uchar>&, const ChargePos*, const uint, uchar*); + static GPUd() void noiseSuppressionImpl(int, int, int, int, GPUSharedMemory&, const GPUSettingsRec&, const Array2D<PackedCharge>&, const Array2D<uchar>&, const ChargePos*, const uint, uchar*); static GPUd() void updatePeaksImpl(int, int, int, int, const ChargePos*, const uchar*, const uint, Array2D<uchar>&); @@ -69,7 +69,7 @@ class GPUTPCCFNoiseSuppression : public GPUKernelTemplate static GPUdi() bool keepPeak(ulong, ulong); - static GPUd() void findMinimaAndPeaks(const Array2D<PackedCharge>&, const Array2D<uchar>&, float, const ChargePos&, ChargePos*, PackedCharge*, ulong*, ulong*, ulong*); + static GPUd() void findMinimaAndPeaks(const Array2D<PackedCharge>&, const Array2D<uchar>&, const GPUSettingsRec&, float, const ChargePos&, ChargePos*, PackedCharge*, ulong*, ulong*, ulong*); }; } // namespace GPUCA_NAMESPACE::gpu diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx index bdfb8518c8828..0f22cd47aca72 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx @@ -16,6 +16,7 @@ #include "Array2D.h" #include "CfUtils.h" #include "PackedCharge.h" +#include "TPCCFCalibration.h" using namespace GPUCA_NAMESPACE::gpu; using namespace GPUCA_NAMESPACE::gpu::tpccf; @@ -25,7 +26,7 @@ GPUdii() void GPUTPCCFPeakFinder::Thread<0>(int nBlocks, int nThreads, int iBloc { Array2D<PackedCharge> chargeMap(reinterpret_cast<PackedCharge*>(clusterer.mPchargeMap)); Array2D<uchar> isPeakMap(clusterer.mPpeakMap); - findPeaksImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions, clusterer.mPisPeak, isPeakMap); + findPeaksImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions, clusterer.Param().rec, clusterer.mPisPeak, isPeakMap); } GPUdii() bool GPUTPCCFPeakFinder::isPeak( @@ -34,12 +35,13 @@ GPUdii() bool GPUTPCCFPeakFinder::isPeak( const ChargePos& pos, ushort N, const Array2D<PackedCharge>& chargeMap, + const GPUSettingsRec& calib, ChargePos* posBcast, PackedCharge* buf) { ushort ll = get_local_id(0); - bool belowThreshold = (q <= QMAX_CUTOFF); + bool belowThreshold = (q <= calib.tpcCFqmaxCutoff); ushort lookForPeaks; ushort partId = CfUtils::partition( @@ -91,6 +93,7 @@ GPUd() void GPUTPCCFPeakFinder::findPeaksImpl(int nBlocks, int nThreads, int iBl const Array2D<PackedCharge>& chargeMap, const ChargePos* positions, SizeT digitnum, + const GPUSettingsRec& calib, uchar* isPeakPredicate, Array2D<uchar>& peakMap) { @@ -103,7 +106,7 @@ GPUd() void GPUTPCCFPeakFinder::findPeaksImpl(int nBlocks, int nThreads, int iBl Charge charge = pos.valid() ? chargeMap[pos].unpack() : Charge(0); uchar peak; - peak = isPeak(smem, charge, pos, SCRATCH_PAD_SEARCH_N, chargeMap, smem.posBcast, smem.buf); + peak = isPeak(smem, charge, pos, SCRATCH_PAD_SEARCH_N, chargeMap, calib, smem.posBcast, smem.buf); // Exit early if dummy. See comment above. bool iamDummy = (idx >= digitnum); @@ -113,5 +116,5 @@ GPUd() void GPUTPCCFPeakFinder::findPeaksImpl(int nBlocks, int nThreads, int iBl isPeakPredicate[idx] = peak; - peakMap[pos] = (uchar(charge > CHARGE_THRESHOLD) << 1) | peak; + peakMap[pos] = (uchar(charge > calib.tpcCFinnerThreshold) << 1) | peak; } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h index f78945a43132b..54d878d012562 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h @@ -52,9 +52,9 @@ class GPUTPCCFPeakFinder : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUd() void findPeaksImpl(int, int, int, int, GPUSharedMemory&, const Array2D<PackedCharge>&, const ChargePos*, tpccf::SizeT, uchar*, Array2D<uchar>&); + static GPUd() void findPeaksImpl(int, int, int, int, GPUSharedMemory&, const Array2D<PackedCharge>&, const ChargePos*, tpccf::SizeT, const GPUSettingsRec&, uchar*, Array2D<uchar>&); - static GPUd() bool isPeak(GPUSharedMemory&, tpccf::Charge, const ChargePos&, ushort, const Array2D<o2::gpu::PackedCharge>&, ChargePos*, PackedCharge*); + static GPUd() bool isPeak(GPUSharedMemory&, tpccf::Charge, const ChargePos&, ushort, const Array2D<PackedCharge>&, const GPUSettingsRec&, ChargePos*, PackedCharge*); }; } // namespace GPUCA_NAMESPACE::gpu diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index b9677e9357970..26f3c99b2b68c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -42,6 +42,7 @@ class Digit; namespace GPUCA_NAMESPACE::gpu { struct GPUTPCClusterMCInterim; +struct TPCCFCalibration; struct ChargePos; diff --git a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h b/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h index b634b714efc4d..71ffd48e93f27 100644 --- a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h +++ b/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h @@ -47,6 +47,7 @@ struct TPCCFCalibration { TPCCFCalibration(const o2::tpc::CalDet<float>&); #endif + // Deal with pad gain correction from here on GPUdi() void setGainCorrection(int sector, tpccf::Row row, tpccf::Pad pad, float c) { mGainCorrection[sector].set(globalPad(row, pad), c); diff --git a/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h b/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h index 2b18d7e243b70..8ace539cd7e8c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h +++ b/GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h @@ -23,9 +23,6 @@ using uchar = unsigned char; using ulong = unsigned long; #endif -#define QMAX_CUTOFF 3 -#define QTOT_CUTOFF 0 -#define NOISE_SUPPRESSION_MINIMA_EPSILON 10 #define SCRATCH_PAD_WORK_GROUP_SIZE GPUCA_GET_THREAD_COUNT(GPUCA_LB_CLUSTER_FINDER) /* #define CHARGEMAP_TIME_MAJOR_LAYOUT */ @@ -68,11 +65,7 @@ using ulong = unsigned long; #define CPU_PTR(x) x #endif -namespace GPUCA_NAMESPACE -{ -namespace gpu -{ -namespace tpccf +namespace GPUCA_NAMESPACE::gpu::tpccf { using SizeT = size_t; @@ -90,13 +83,6 @@ using Delta2 = short2; using local_id = short2; -GPUconstexpr() float CHARGE_THRESHOLD = 0.f; -GPUconstexpr() float OUTER_CHARGE_THRESHOLD = 0.f; -GPUconstexpr() float QTOT_THRESHOLD = 500.f; -GPUconstexpr() int MIN_SPLIT_NUM = 1; - -} // namespace tpccf -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace GPUCA_NAMESPACE::gpu::tpccf #endif From 1a8e52d55e780e294391ac28bad6a55f1afe67b2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 2 Oct 2020 16:36:42 +0200 Subject: [PATCH 0835/1751] Add some constructors to ConstMCTruthContainerView --- .../include/SimulationDataFormat/ConstMCTruthContainer.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h index e9bfd6d42be47..a6853364feddd 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -59,7 +59,7 @@ class ConstMCTruthContainer : public std::vector<char> // 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 + // return the number of labels managed in this container size_t getNElements() const { return size() >= sizeof(FlatHeader) ? getHeader().nofTruthElements : 0; } private: @@ -126,6 +126,9 @@ class ConstMCTruthContainerView { public: ConstMCTruthContainerView(gsl::span<const char> const bufferview) : mStorage(bufferview){}; + ConstMCTruthContainerView(ConstMCTruthContainer<TruthElement> const& cont) : mStorage(gsl::span<const char>(cont)){}; + ConstMCTruthContainerView() = default; + ConstMCTruthContainerView(const ConstMCTruthContainerView&) = default; // const data access // get individual const "view" container for a given data index From a3a22f520999a711bf2197ea957267d19c88c4ae Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 2 Oct 2020 13:01:10 +0200 Subject: [PATCH 0836/1751] TPC workflow: Invert options for ca-clusterer and tpc-zs-on-the-fly since they default to true now --- .../TPC/workflow/src/tpc-reco-workflow.cxx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index 7fd422e354095..f8795b9f213d2 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -44,14 +44,14 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) std::vector<ConfigParamSpec> options{ {"input-type", VariantType::String, "digits", {"digitizer, digits, zsraw, clustershw, clustersnative, compressed-clusters, compressed-clusters-ctf"}}, {"output-type", VariantType::String, "tracks", {"digits, zsraw, clustershw, clustersnative, tracks, compressed-clusters, encoded-clusters, disable-writer"}}, - {"ca-clusterer", VariantType::Bool, true, {"Use clusterer of GPUCATracking"}}, + {"no-ca-clusterer", VariantType::Bool, false, {"Use HardwareClusterer instead of clusterer of GPUCATracking"}}, {"disable-mc", VariantType::Bool, false, {"disable sending of MC information"}}, {"tpc-sectors", VariantType::String, "0-35", {"TPC sector range, e.g. 5-7,8,9"}}, {"tpc-lanes", VariantType::Int, 1, {"number of parallel lanes up to the tracker"}}, {"dispatching-mode", VariantType::String, "prompt", {"determines when to dispatch: prompt, complete"}}, - {"tpc-zs-on-the-fly", VariantType::Bool, true, {"use TPC zero suppression on the fly, true/false"}}, + {"no-tpc-zs-on-the-fly", VariantType::Bool, false, {"Do not use TPC zero suppression on the fly"}}, {"zs-threshold", VariantType::Float, 2.0f, {"zero suppression threshold"}}, - {"zs-10bit", VariantType::Bool, false, {"use 10 bit ADCs for TPC zero suppression, true/false, default/false = 12 bit ADC"}}, + {"zs-10bit", VariantType::Bool, false, {"use 10 bit ADCs for TPC zero suppression, default = 12 bit ADC"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings (e.g.: 'TPCHwClusterer.peakChargeThreshold=4;...')"}}, {"configFile", VariantType::String, "", {"configuration file for configurable parameters"}}}; @@ -139,15 +139,15 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) o2::conf::ConfigurableParam::writeINI("o2tpcrecoworkflow_configuration.ini"); bool doMC = not cfgc.options().get<bool>("disable-mc"); - return o2::tpc::reco_workflow::getWorkflow(tpcSectors, // sector configuration - laneConfiguration, // lane configuration - doMC, // - nLanes, // - inputType, // - cfgc.options().get<std::string>("output-type"), // - cfgc.options().get<bool>("ca-clusterer"), // - cfgc.options().get<bool>("tpc-zs-on-the-fly"), // - cfgc.options().get<bool>("zs-10bit"), // - cfgc.options().get<float>("zs-threshold") // + return o2::tpc::reco_workflow::getWorkflow(tpcSectors, // sector configuration + laneConfiguration, // lane configuration + doMC, // + nLanes, // + inputType, // + cfgc.options().get<std::string>("output-type"), // + !cfgc.options().get<bool>("no-ca-clusterer"), // + !cfgc.options().get<bool>("no-tpc-zs-on-the-fly"), // + cfgc.options().get<bool>("zs-10bit"), // + cfgc.options().get<float>("zs-threshold") // ); } From 3cce466cd2b75088cf7596a865219cb95d14e7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 1 Sep 2020 17:01:42 +0200 Subject: [PATCH 0837/1751] PWGHF: Maintenance. Fix file names in documentation and variables names. Remove unnecessary includes. Fix typos. --- .../Analysis/CandidateSelectionTables.h | 4 +--- .../include/Analysis/SecondaryVertexHF.h | 13 ++++++----- .../include/Analysis/trackUtilities.h | 2 -- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 8 +------ .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 22 +++++-------------- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 19 ++++++++-------- Analysis/Tasks/PWGHF/taskD0.cxx | 11 +--------- 7 files changed, 26 insertions(+), 53 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h b/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h index aa7028fa27e72..9bc168244a7b9 100644 --- a/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h @@ -7,12 +7,10 @@ // 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 diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index 3cd1cbff8ea26..cd1970eb31f9b 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -25,12 +25,15 @@ namespace o2::aod { namespace seltrack { -DECLARE_SOA_COLUMN(IsSel_2prong, issel_2prong, int); -DECLARE_SOA_COLUMN(IsSel_3prong, issel_3prong, int); -DECLARE_SOA_COLUMN(DCAPrim0, dcaprim0, float); -DECLARE_SOA_COLUMN(DCAPrim1, dcaprim1, float); +DECLARE_SOA_COLUMN(IsSel2Prong, isSel2Prong, int); +DECLARE_SOA_COLUMN(IsSel3Prong, isSel3Prong, int); +DECLARE_SOA_COLUMN(DCAPrim0, dcaPrim0, float); +DECLARE_SOA_COLUMN(DCAPrim1, dcaPrim1, float); } // namespace seltrack -DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", seltrack::IsSel_2prong, seltrack::IsSel_3prong, seltrack::DCAPrim0, +DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", + seltrack::IsSel2Prong, + seltrack::IsSel3Prong, + seltrack::DCAPrim0, seltrack::DCAPrim1); using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, SelTrack, pidRespTPC, pidRespTOF>; diff --git a/Analysis/DataModel/include/Analysis/trackUtilities.h b/Analysis/DataModel/include/Analysis/trackUtilities.h index f9c909fc868dd..5bb0c7ab8f1c4 100644 --- a/Analysis/DataModel/include/Analysis/trackUtilities.h +++ b/Analysis/DataModel/include/Analysis/trackUtilities.h @@ -16,8 +16,6 @@ #ifndef O2_ANALYSIS_TRACKUTILITIES_H_ #define O2_ANALYSIS_TRACKUTILITIES_H_ -#include <cmath> - #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/Vertex.h" #include "Analysis/RecoDecay.h" diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index aff6ee0ed161d..9a50994a66d84 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file hfcandidatecreator2prong.cxx +/// \file HFCandidateCreator2Prong.cxx /// \brief Reconstruction of heavy-flavour 2-prong decay candidates /// /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN @@ -20,15 +20,9 @@ #include "Analysis/SecondaryVertexHF.h" #include "Analysis/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" -#include "Analysis/RecoDecay.h" -#include "PID/PIDResponse.h" -#include <cmath> -#include <array> -#include <cstdlib> using namespace o2; using namespace o2::framework; -using std::array; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HFCandidateCreator2Prong { diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index 684512487b612..3aa45deeba0ac 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -15,22 +15,12 @@ #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 <cmath> -#include <array> -#include <cstdlib> 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; @@ -114,7 +104,7 @@ struct HFD0CandidateSelector { } /// Conjugate independent toplogical cuts - /// \param hfcandprong2 is candidate + /// \param hfCandProng2 is candidate /// \return true if candidate passes all cuts template <typename T> bool selectionTopol(const T& hfCandProng2) @@ -185,7 +175,7 @@ struct HFD0CandidateSelector { if (TMath::Abs(trackPion.pt()) < TMath::Abs(cuts[pTBin][4]) || TMath::Abs(trackKaon.pt()) < 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]) { + 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 } @@ -231,7 +221,7 @@ struct HFD0CandidateSelector { /// 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 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 @@ -256,7 +246,7 @@ struct HFD0CandidateSelector { /// 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 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 @@ -279,9 +269,9 @@ struct HFD0CandidateSelector { /// PID selection on daughter track /// \param track is the daughter track - /// \param nPDG is the pdg code of the flavour hypothesis + /// \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 + /// \return 1 if successful PID match, 0 if successful PID rejection, -1 if no PID info template <typename T> int selectionPID(const T& track, int nPDG) { diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 3cf38eacc3b4f..e0d1b8d238b84 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file hftrackindexskimscreator.cxx +/// \file HFTrackIndexSkimsCreator.cxx /// \brief Pre-selection of 2-prong and 3-prong secondary vertices of heavy-flavour decay candidates /// /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN @@ -23,7 +23,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; /// Track selection struct SelectTracks { @@ -37,10 +36,10 @@ struct SelectTracks { Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min number of tpc cls >="}; Configurable<double> d_bz{"d_bz", 5.0, "bz field"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "pt tracks (#GeV)", 100, 0., 10.)}; - OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "pt tracks (#GeV)", 100, 0., 10.)}; + OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "pt tracks (GeV/#it{c})", 100, 0., 10.)}; + OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "pt tracks (GeV/#it{c})", 100, 0., 10.)}; OutputObj<TH1F> hdcatoprimxy_cuts_2prong{TH1F("hdcatoprimxy_cuts_2prong", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; - OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "pt tracks (#GeV)", 100, 0., 10.)}; + OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "pt tracks (GeV/#it{c})", 100, 0., 10.)}; OutputObj<TH1F> hdcatoprimxy_cuts_3prong{TH1F("hdcatoprimxy_cuts_3prong", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; OutputObj<TH1F> heta_cuts_2prong{TH1F("heta_cuts_2prong", "pseudorapidity", 100, -1.0, 1.0)}; OutputObj<TH1F> heta_cuts_3prong{TH1F("heta_cuts_3prong", "pseudorapidity", 100, -1.0, 1.0)}; @@ -120,7 +119,7 @@ struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hvtx3_y_out{TH1F("hvtx3_y", "3-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx3_z_out{TH1F("hvtx3_z", "3-track vtx", 1000, -20.0, 20.0)}; - Filter filterSelectTracks = aod::seltrack::issel_2prong == 1; + Filter filterSelectTracks = aod::seltrack::isSel2Prong == 1; using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>>; // FIXME //Partition<SelectedTracks> tracksPos = aod::track::signed1Pt > 0.f; @@ -216,14 +215,14 @@ struct HFTrackIndexSkimsCreator { if (do3prong == 1) { // second loop over positive tracks //for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracksPos.end(); ++trackPos2) { - if (trackPos1.issel_3prong() == 0) + if (trackPos1.isSel3Prong() == 0) continue; - if (trackNeg1.issel_3prong() == 0) + if (trackNeg1.isSel3Prong() == 0) continue; for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracks.end(); ++trackPos2) { if (trackPos2.signed1Pt() < 0) continue; - if (trackPos2.issel_3prong() == 0) + if (trackPos2.isSel3Prong() == 0) continue; // calculate invariant mass @@ -276,7 +275,7 @@ struct HFTrackIndexSkimsCreator { for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracks.end(); ++trackNeg2) { if (trackNeg2.signed1Pt() > 0) continue; - if (trackNeg2.issel_3prong() == 0) + if (trackNeg2.isSel3Prong() == 0) continue; // calculate invariant mass diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index ac64e41ef3e6d..ef449e8097f40 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file taskdzero.h +/// \file taskD0.cxx /// \brief D0 analysis task /// /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN @@ -17,21 +17,12 @@ #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 <TFile.h> -#include <TH1F.h> -#include <cmath> -#include <array> -#include <cstdlib> - 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 struct TaskD0 { From dc8e0f521f15479308b9af5f56a378802509822f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 1 Sep 2020 17:38:12 +0200 Subject: [PATCH 0838/1751] RecoDecay: Add explicit return types. --- .../DataModel/include/Analysis/RecoDecay.h | 58 +++++++++---------- .../include/Analysis/trackUtilities.h | 6 +- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index c4cbbfc0e7db3..babc7e6fab606 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -56,7 +56,7 @@ class RecoDecay /// \param num a number of arbitrary type /// \return number squared template <typename T> - static auto sq(T num) + static double sq(T num) { return (double)num * (double)num; } @@ -66,7 +66,7 @@ class RecoDecay /// \param args arbitrary number of numbers of arbitrary types /// \return sum of squares of numbers template <typename... T> - static auto sumOfSquares(const T&... args) + static double sumOfSquares(const T&... args) { return (((double)args * (double)args) + ...); } @@ -75,7 +75,7 @@ class RecoDecay /// \param args arbitrary number of numbers of arbitrary types /// \return square root of sum of squares of numbers template <typename... T> - static auto sqrtSumOfSquares(const T&... args) + static double sqrtSumOfSquares(const T&... args) { return std::sqrt(sumOfSquares(args...)); } @@ -105,7 +105,7 @@ class RecoDecay /// \param vec1,vec2 vectors /// \return scalar product template <std::size_t N, typename T, typename U> - static auto dotProd(const array<T, N>& vec1, const array<U, N>& vec2) + static double dotProd(const array<T, N>& vec1, const array<U, N>& vec2) { double res{0}; for (auto iDim = 0; iDim < N; ++iDim) { @@ -119,7 +119,7 @@ class RecoDecay /// \param vec vector /// \return magnitude squared template <std::size_t N, typename T> - static auto mag2(const array<T, N>& vec) + static double mag2(const array<T, N>& vec) { return dotProd(vec, vec); } @@ -128,7 +128,7 @@ class RecoDecay /// \param point1,point2 {x, y, z} coordinates of points /// \return 3D distance between two points template <typename T, typename U> - static auto distance(const T& point1, const U& point2) + static double distance(const T& point1, const U& point2) { return sqrtSumOfSquares(point1[0] - point2[0], point1[1] - point2[1], point1[2] - point2[2]); } @@ -137,7 +137,7 @@ class RecoDecay /// \param point1,point2 {x, y, z} or {x, y} coordinates of points /// \return 2D {x, y} distance between two points template <typename T, typename U> - static auto distanceXY(const T& point1, const U& point2) + static double distanceXY(const T& point1, const U& point2) { return sqrtSumOfSquares(point1[0] - point2[0], point1[1] - point2[1]); } @@ -148,7 +148,7 @@ class RecoDecay /// \param mom 3-momentum array /// \return pseudorapidity template <typename T> - static auto Eta(const array<T, 3>& mom) + static double Eta(const array<T, 3>& mom) { // eta = arctanh(pz/p) if (std::abs(mom[0]) < Almost0 && std::abs(mom[1]) < Almost0) { // very small px and py @@ -162,7 +162,7 @@ class RecoDecay /// \param mass mass /// \return rapidity template <typename T, typename U> - static auto Y(const array<T, 3>& mom, U mass) + static double Y(const array<T, 3>& mom, U mass) { // y = arctanh(pz/E) return std::atanh(mom[2] / E(mom, mass)); @@ -174,7 +174,7 @@ class RecoDecay /// \param mom 3-momentum array /// \return cosine of pointing angle template <typename T, typename U, typename V> - static auto CPA(const array<T, 3>& posPV, const array<U, 3>& posSV, const array<V, 3>& mom) + static double CPA(const array<T, 3>& posPV, const array<U, 3>& posSV, const array<V, 3>& mom) { // CPA = (l . p)/(|l| |p|) auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1], posSV[2] - posPV[2]}; @@ -194,7 +194,7 @@ class RecoDecay /// \param mom {x, y, z} or {x, y} momentum array /// \return cosine of pointing angle in {x, y} template <std::size_t N, std::size_t O, std::size_t P, typename T, typename U, typename V> - static auto CPAXY(const array<T, N>& posPV, const array<U, O>& posSV, const array<V, P>& mom) + static double CPAXY(const array<T, N>& posPV, const array<U, O>& posSV, const array<V, P>& mom) { // CPAXY = (r . pT)/(|r| |pT|) auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1]}; @@ -216,7 +216,7 @@ class RecoDecay /// \param length decay length /// \return proper lifetime times c template <typename T, typename U, typename V> - static auto Ct(const array<T, 3>& mom, U length, V mass) + static double Ct(const array<T, 3>& mom, U length, V mass) { // c t = l m c^2/(p c) return (double)length * (double)mass / P(mom); @@ -230,7 +230,7 @@ class RecoDecay /// \param iProng index of the prong /// \return cosine of θ* of the i-th prong template <typename T, typename U> - static auto CosThetaStarM(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) + static double CosThetaStarM(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) { auto eProng = E(arrMom[iProng], arrMass[iProng]); // energy of the prong auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the 2-prong system @@ -256,7 +256,7 @@ class RecoDecay /// \param iProng index of the prong /// \return cosine of θ* of the i-th prong template <typename T, typename U> - static auto CosThetaStarD(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) + static double CosThetaStarD(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) { auto eProng = E(arrMom[iProng], arrMass[iProng]); // energy of the prong auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the 2-prong system @@ -283,7 +283,7 @@ class RecoDecay /// \param iProng index of the prong /// \return cosine of θ* of the i-th prong under the assumption of the invariant mass template <typename T, typename U, typename V> - static auto CosThetaStarA(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, V mTot, int iProng) + static double CosThetaStarA(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, V mTot, int iProng) { auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the mother particle auto pTot = P(pVecTot); // magnitude of the momentum of the mother particle @@ -311,7 +311,7 @@ class RecoDecay /// Calculates momentum squared from momentum components. /// \param px,py,pz {x, y, z} momentum components /// \return momentum squared - static auto P2(double px, double py, double pz) + static double P2(double px, double py, double pz) { return sumOfSquares(px, py, pz); } @@ -320,7 +320,7 @@ class RecoDecay /// \param args pack of 3-momentum arrays /// \return total momentum squared template <typename... T> - static auto P2(const array<T, 3>&... args) + static double P2(const array<T, 3>&... args) { return sumOfSquares(getElement(0, args...), getElement(1, args...), getElement(2, args...)); } @@ -329,7 +329,7 @@ class RecoDecay /// \param args {x, y, z} momentum components or pack of 3-momentum arrays /// \return (total) momentum magnitude template <typename... T> - static auto P(const T&... args) + static double P(const T&... args) { return std::sqrt(P2(args...)); } @@ -337,7 +337,7 @@ class RecoDecay /// Calculates transverse momentum squared from momentum components. /// \param px,py {x, y} momentum components /// \return transverse momentum squared - static auto Pt2(double px, double py) + static double Pt2(double px, double py) { return sumOfSquares(px, py); } @@ -346,7 +346,7 @@ class RecoDecay /// \param args pack of 3-(or 2-)momentum arrays /// \return total transverse momentum squared template <std::size_t N, typename... T> - static auto Pt2(const array<T, N>&... args) + static double Pt2(const array<T, N>&... args) { return sumOfSquares(getElement(0, args...), getElement(1, args...)); } @@ -355,7 +355,7 @@ class RecoDecay /// \param args {x, y} momentum components or pack of 3-momentum arrays /// \return (total) transverse momentum template <typename... T> - static auto Pt(const T&... args) + static double Pt(const T&... args) { return std::sqrt(Pt2(args...)); } @@ -365,7 +365,7 @@ class RecoDecay /// \param args {x, y, z} momentum components, mass /// \return energy squared template <typename... T> - static auto E2(T... args) + static double E2(T... args) { return sumOfSquares(args...); } @@ -375,7 +375,7 @@ class RecoDecay /// \param mass mass /// \return energy squared template <typename T, typename U> - static auto E2(const array<T, 3>& mom, U mass) + static double E2(const array<T, 3>& mom, U mass) { return E2(mom[0], mom[1], mom[2], mass); } @@ -386,7 +386,7 @@ class RecoDecay /// \param args 3-momentum array, mass /// \return energy template <typename... T> - static auto E(const T&... args) + static double E(const T&... args) { return std::sqrt(E2(args...)); } @@ -395,7 +395,7 @@ class RecoDecay /// \param mom momentum magnitude /// \param energy energy /// \return invariant mass squared - static auto M2(double mom, double energy) + static double M2(double mom, double energy) { return energy * energy - mom * mom; } @@ -405,7 +405,7 @@ class RecoDecay /// \param energy energy /// \return invariant mass squared template <typename T> - static auto M2(const array<T, 3>& mom, double energy) + static double M2(const array<T, 3>& mom, double energy) { return energy * energy - P2(mom); } @@ -416,7 +416,7 @@ class RecoDecay /// \param arrMass array of N masses (in the same order as arrMom) /// \return invariant mass squared template <std::size_t N, typename T, typename U> - static auto M2(const array<array<T, 3>, N>& arrMom, const array<U, N>& arrMass) + static double M2(const array<array<T, 3>, N>& arrMom, const array<U, N>& arrMass) { array<double, 3> momTotal{0., 0., 0.}; // candidate momentum vector double energyTot{0.}; // candidate energy @@ -435,7 +435,7 @@ class RecoDecay /// \param args array of momenta, array of masses /// \return invariant mass template <typename... T> - static auto M(const T&... args) + static double M(const T&... args) { return std::sqrt(M2(args...)); } @@ -443,7 +443,7 @@ class RecoDecay /// Returns particle mass based on PDG code. /// \param pdg PDG code /// \return particle mass - static auto getMassPDG(int pdg) + static double getMassPDG(int pdg) { // Try to get the particle mass from the list first. for (const auto& particle : mListMass) { diff --git a/Analysis/DataModel/include/Analysis/trackUtilities.h b/Analysis/DataModel/include/Analysis/trackUtilities.h index 5bb0c7ab8f1c4..ec32f5210e11f 100644 --- a/Analysis/DataModel/include/Analysis/trackUtilities.h +++ b/Analysis/DataModel/include/Analysis/trackUtilities.h @@ -31,9 +31,8 @@ auto getTrackPar(const T& track) } /// Extracts track parameters and covariance matrix from a track. -/// \return o2::track::TrackParCov template <typename T> -auto getTrackParCov(const T& track) +o2::track::TrackParCov getTrackParCov(const T& track) { std::array<float, 5> arraypar = {track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt()}; @@ -47,9 +46,8 @@ auto getTrackParCov(const T& track) } /// Extracts primary vertex position and covariance matrix from a collision. -/// \return o2::dataformats::VertexBase template <typename T> -auto getPrimaryVertex(const T& collision) +o2::dataformats::VertexBase getPrimaryVertex(const T& collision) { Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); std::array<float, 6> vtxCov{collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}; From 7dfb171c84357cc2aa493a39444bad1b0e9d8085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Sat, 5 Sep 2020 17:10:29 +0200 Subject: [PATCH 0839/1751] RecoDecay: Keep only the AliRoot version of CosThetaStar. --- .../DataModel/include/Analysis/RecoDecay.h | 55 +------------------ .../include/Analysis/SecondaryVertexHF.h | 2 +- 2 files changed, 2 insertions(+), 55 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/DataModel/include/Analysis/RecoDecay.h index babc7e6fab606..5747e4415edad 100644 --- a/Analysis/DataModel/include/Analysis/RecoDecay.h +++ b/Analysis/DataModel/include/Analysis/RecoDecay.h @@ -224,66 +224,13 @@ class RecoDecay /// Calculates cosine of θ* (theta star). /// \note Implemented for 2 prongs only. - /// \note "Multiply by gamma" version - /// \param arrMom array of two 3-momentum arrays - /// \param arrMass array of two masses (in the same order as arrMom) - /// \param iProng index of the prong - /// \return cosine of θ* of the i-th prong - template <typename T, typename U> - static double CosThetaStarM(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) - { - auto eProng = E(arrMom[iProng], arrMass[iProng]); // energy of the prong - auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the 2-prong system - auto pTot = P(pVecTot); // magnitude of the momentum of the 2-prong system - auto mTot = M(arrMom, arrMass); // invariant mass of the 2-prong system - auto eTot = eProng + E(arrMom[1 - iProng], arrMass[1 - iProng]); // energy of the 2-prong system - auto gamma = eTot / mTot; // γ, Lorentz gamma factor of the 2-prong system - auto beta = pTot / eTot; // β, velocity of the 2-prong system - auto pStar = std::sqrt(sq(sq(mTot) - sq(arrMass[0]) - sq(arrMass[1])) - sq(2 * arrMass[0] * arrMass[1])) / (2 * mTot); // p*, prong momentum in the rest frame of the 2-prong system - // p* = √[(M^2 - m1^2 - m2^2)^2 - 4 m1^2 m2^2]/2M - // Lorentz transformation of the longitudinal momentum of the prong into the rest frame of the 2-prong system: - // p*_L,i = γ (p_L,i - β E_i) - // p*_L,i = p* cos(θ*_i) - // cos(θ*_i) = γ (p_L,i - β E_i)/p* - return gamma * (dotProd(arrMom[iProng], pVecTot) / pTot - beta * eProng) / pStar; - } - - /// Calculates cosine of θ* (theta star). - /// \note Implemented for 2 prongs only. - /// \note "Divide by gamma" version - /// \param arrMom array of two 3-momentum arrays - /// \param arrMass array of two masses (in the same order as arrMom) - /// \param iProng index of the prong - /// \return cosine of θ* of the i-th prong - template <typename T, typename U> - static double CosThetaStarD(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, int iProng) - { - auto eProng = E(arrMom[iProng], arrMass[iProng]); // energy of the prong - auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the 2-prong system - auto pTot = P(pVecTot); // magnitude of the momentum of the 2-prong system - auto mTot = M(arrMom, arrMass); // invariant mass of the 2-prong system - auto eTot = eProng + E(arrMom[1 - iProng], arrMass[1 - iProng]); // energy of the 2-prong system - auto gamma = eTot / mTot; // γ, Lorentz gamma factor of the 2-prong system - auto beta = pTot / eTot; // β, velocity of the 2-prong system - auto pStar = std::sqrt(sq(sq(mTot) - sq(arrMass[0]) - sq(arrMass[1])) - sq(2 * arrMass[0] * arrMass[1])) / (2 * mTot); // p*, prong momentum in the rest frame of the 2-prong system - // p* = √[(M^2 - m1^2 - m2^2)^2 - 4 m1^2 m2^2]/2M - // Lorentz transformation of the longitudinal momentum of the prong into the detector frame: - // p_L,i = γ (p*_L,i + β E*_i) - // p*_L,i = p_L,i/γ - β E*_i (less sensitive too incorrect masses?) - // cos(θ*_i) = (p_L,i/γ - β E*_i)/p* - return (dotProd(arrMom[iProng], pVecTot) / (pTot * gamma) - beta * E(pStar, arrMass[iProng])) / pStar; - } - - /// Calculates cosine of θ* (theta star). - /// \note Implemented for 2 prongs only. - /// \note AliRoot version /// \param arrMom array of two 3-momentum arrays /// \param arrMass array of two masses (in the same order as arrMom) /// \param mTot assumed mass of mother particle /// \param iProng index of the prong /// \return cosine of θ* of the i-th prong under the assumption of the invariant mass template <typename T, typename U, typename V> - static double CosThetaStarA(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, V mTot, int iProng) + static double CosThetaStar(const array<array<T, 3>, 2>& arrMom, const array<U, 2>& arrMass, V mTot, int iProng) { auto pVecTot = PVec(arrMom[0], arrMom[1]); // momentum of the mother particle auto pTot = P(pVecTot); // magnitude of the momentum of the mother particle diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index cd1970eb31f9b..96bbde88a2a07 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -130,7 +130,7 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::hf_cand::pzProng0 + 1.f DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, [](float dca1, float dca2) { return dca1 * dca2; }); DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); -DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m, double mTot, int iProng) { return RecoDecay::CosThetaStarA(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); +DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m, double mTot, int iProng) { return RecoDecay::CosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); // functions for specific particles From ac422d887540ac4b84a926be9dd753ac0e34d933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 22 Sep 2020 05:44:17 +0200 Subject: [PATCH 0840/1751] RecoDecay: Move to AnalysisCore. --- Analysis/{DataModel => Core}/include/Analysis/RecoDecay.h | 0 Analysis/DataModel/CMakeLists.txt | 2 +- Analysis/Tasks/PWGHF/CMakeLists.txt | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename Analysis/{DataModel => Core}/include/Analysis/RecoDecay.h (100%) diff --git a/Analysis/DataModel/include/Analysis/RecoDecay.h b/Analysis/Core/include/Analysis/RecoDecay.h similarity index 100% rename from Analysis/DataModel/include/Analysis/RecoDecay.h rename to Analysis/Core/include/Analysis/RecoDecay.h diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index 4df9311ced9de..ef447cc6246f0 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -46,7 +46,7 @@ install(FILES o2_add_executable(aod-data-model-graph SOURCES src/aodDataModelGraph.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore ) o2_add_executable(pidparam-tpc-bethe-bloch diff --git a/Analysis/Tasks/PWGHF/CMakeLists.txt b/Analysis/Tasks/PWGHF/CMakeLists.txt index 1c0a8e222c81a..1430c8765b705 100644 --- a/Analysis/Tasks/PWGHF/CMakeLists.txt +++ b/Analysis/Tasks/PWGHF/CMakeLists.txt @@ -25,5 +25,5 @@ o2_add_dpl_workflow(hf-d0-candidate-selector o2_add_dpl_workflow(hf-task-d0 SOURCES taskD0.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) From 52374d29d7731c7194d60e645b1869b58efa6aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 22 Sep 2020 15:28:52 +0200 Subject: [PATCH 0841/1751] PWGHF: Add more histograms. --- Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 4 ++++ Analysis/Tasks/PWGHF/taskD0.cxx | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 9a50994a66d84..93c0f2e980fc0 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -36,6 +36,8 @@ struct HFCandidateCreator2Prong { Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; OutputObj<TH1F> hmass2{TH1F("hmass2", "2-track inv mass", 500, 0., 5.0)}; + OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.0e-4)}; + OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "XX element of SV cov. matrix", 100, 0., 0.2)}; double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); @@ -67,6 +69,7 @@ struct HFCandidateCreator2Prong { const auto& secondaryVertex = df.getPCACandidate(); auto chi2PCA = df.getChi2AtPCACandidate(); auto covMatrixPCA = df.calcPCACovMatrix().Array(); + hCovSVXX->Fill(covMatrixPCA[0]); // FIXME: Calculation of errorDecayLength(XY) gives wrong values without this line. auto trackParVar0 = df.getTrack(0); auto trackParVar1 = df.getTrack(1); @@ -85,6 +88,7 @@ struct HFCandidateCreator2Prong { // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); auto covMatrixPV = primaryVertex.getCov(); + hCovPVXX->Fill(covMatrixPV[0]); o2::dataformats::DCA impactParameter0; o2::dataformats::DCA impactParameter1; trackParVar0.propagateToDCA(primaryVertex, magneticField, &impactParameter0); diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index ef449e8097f40..71224825e08c2 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -38,6 +38,9 @@ struct TaskD0 { OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; + OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1.0, 1.0)}; + OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.0)}; + OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.0)}; Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; @@ -65,6 +68,10 @@ struct TaskD0 { hCt->Fill(CtD0(candidate)); hEta->Fill(candidate.eta()); hselectionstatus->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); + hImpParErr->Fill(candidate.errorImpactParameter0()); + hImpParErr->Fill(candidate.errorImpactParameter1()); + hDecLenErr->Fill(candidate.errorDecayLength()); + hDecLenXYErr->Fill(candidate.errorDecayLengthXY()); } } }; From 130719f24f6355626170f686adc71816d520237f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Sat, 3 Oct 2020 14:16:21 +0200 Subject: [PATCH 0842/1751] PWGHF: Fix track selection. --- Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index e0d1b8d238b84..679fb5d767bc1 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -61,10 +61,11 @@ struct SelectTracks { status_2prong = 0; if (abs(track.eta()) > etamax_3prong) status_3prong = 0; - UChar_t clustermap_0 = track.itsClusterMap(); - bool isselected_0 = track.tpcNClsFound() >= d_tpcnclsfound && track.flags() & 0x4; - isselected_0 = isselected_0 && (TESTBIT(clustermap_0, 0) || TESTBIT(clustermap_0, 1)); - if (!isselected_0) { + UChar_t clustermap = track.itsClusterMap(); + bool isselected = track.tpcNClsFound() >= d_tpcnclsfound && + track.flags() & o2::aod::track::ITSrefit && + (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); + if (!isselected) { status_2prong = 0; status_3prong = 0; } From 4eaca66a6f87c6d1f202e7dc3ce3f343ff171f46 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Fri, 2 Oct 2020 17:35:07 +0200 Subject: [PATCH 0843/1751] Adjust handling of decoding in CONET mode --- .../compression/include/TOFCompression/Compressor.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Detectors/TOF/compression/include/TOFCompression/Compressor.h b/Detectors/TOF/compression/include/TOFCompression/Compressor.h index cc86d4f12a89f..e52cc7f1ecca3 100644 --- a/Detectors/TOF/compression/include/TOFCompression/Compressor.h +++ b/Detectors/TOF/compression/include/TOFCompression/Compressor.h @@ -41,7 +41,15 @@ class Compressor rewind(); if (mDecoderCONET) { mDecoderPointerMax = reinterpret_cast<const uint32_t*>(mDecoderBuffer + mDecoderBufferSize); - return processDRM(); + while (mDecoderPointer < mDecoderPointerMax) { + mEventCounter++; + processDRM(); + if (mDecoderFatal) + mFatalCounter++; + if (mDecoderError) + mErrorCounter++; + } + return false; } while (!processHBF()) ; From 1bff2cdc687557c616a88bbaf5de6056c70b07dd Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Sun, 4 Oct 2020 13:15:14 +0200 Subject: [PATCH 0844/1751] Adjust handling of decoding in CONET mode --- .../reconstruction/include/TOFReconstruction/DecoderBase.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h index 54e9d3031ebf3..85ca5dea0aff5 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h @@ -43,7 +43,10 @@ class DecoderBaseT rewind(); if (mDecoderCONET) { mDecoderPointerMax = reinterpret_cast<const uint32_t*>(mDecoderBuffer + mDecoderBufferSize); - return processDRM(); + while (mDecoderPointer < mDecoderPointerMax) { + processDRM(); + } + return false; } while (!processHBF()) ; From 11069664d72b1962e761dbbe5dbf1adb3217f8c3 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 1 Oct 2020 13:57:49 +0200 Subject: [PATCH 0845/1751] Getting started with AOD from Reco This commit provides a rudimentary executable producing AOD from reconstructed objects, serving as a first demonstrator to be expanded on. For the moment collisions and tracks (ITS, TPC, ITSTPC) are handled, as well as the McCollision table showing how to interface MC kinematics. The executable is added to the sim challenge. The commit contains adjustments to MCKinematicsReader to allow fetching the MCEventHeaders. --- Detectors/AOD/CMakeLists.txt | 34 +++ Detectors/AOD/src/StandaloneAODProducer.cxx | 225 ++++++++++++++++++++ Detectors/CMakeLists.txt | 1 + Steer/include/Steer/MCKinematicsReader.h | 20 ++ Steer/src/MCKinematicsReader.cxx | 23 ++ prodtests/sim_challenge.sh | 4 + 6 files changed, 307 insertions(+) create mode 100644 Detectors/AOD/CMakeLists.txt create mode 100644 Detectors/AOD/src/StandaloneAODProducer.cxx diff --git a/Detectors/AOD/CMakeLists.txt b/Detectors/AOD/CMakeLists.txt new file mode 100644 index 0000000000000..626fcd8ef7258 --- /dev/null +++ b/Detectors/AOD/CMakeLists.txt @@ -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. + +o2_add_executable( + standalone-aod-producer + COMPONENT_NAME reco + SOURCES src/StandaloneAODProducer.cxx + PUBLIC_LINK_LIBRARIES + O2::DataFormatsTPC + O2::DataFormatsITSMFT + O2::DataFormatsITS + O2::DataFormatsFT0 + O2::DataFormatsTOF + O2::ITSReconstruction + O2::FT0Reconstruction + O2::TPCFastTransformation + O2::GPUTracking + O2::TPCBase + O2::TPCReconstruction + O2::TOFBase + O2::TOFCalibration + O2::SimConfig + O2::DataFormatsFT0 + O2::AnalysisDataModel + O2::Steer +) + diff --git a/Detectors/AOD/src/StandaloneAODProducer.cxx b/Detectors/AOD/src/StandaloneAODProducer.cxx new file mode 100644 index 0000000000000..7c5aceb68bc36 --- /dev/null +++ b/Detectors/AOD/src/StandaloneAODProducer.cxx @@ -0,0 +1,225 @@ +// 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. + +/// \brief Produce AOD from reconstructed objects + +/// This is a standalone demonstrator producer of the AOD format +/// from MC-RECO. For the moment not a DPL device but in future this +/// promotion is targeted. The executable produces the aod.root file which +/// can be fed into analysis workflows. + +#include "Framework/AnalysisDataModel.h" +#include "Framework/TableBuilder.h" +#include "Framework/TableTreeHelpers.h" +#include "Framework/Logger.h" +#include "TFile.h" + +#include "ReconstructionDataFormats/PrimaryVertex.h" +#include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/VtxTrackRef.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "DataFormatsITS/TrackITS.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "Steer/MCKinematicsReader.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "SimulationDataFormat/DigitizationContext.h" + +#include <vector> + +using namespace o2; +using namespace o2::framework; + +using GIndex = o2::dataformats::VtxTrackIndex; + +template <typename TrackT> +std::vector<TrackT>* fetchTracks(const char* filename, const char* treename, const char* branchname) +{ + TFile file(filename, "OPEN"); + auto tree = (TTree*)file.Get(treename); + auto br = tree->GetBranch(branchname); + std::vector<TrackT>* tracks = nullptr; + br->SetAddress(&tracks); + br->GetEntry(0); + return tracks; +} + +// fills the table of Monte Carlo collisions +// these are the ones references in the digitizer context +void fillMCollisionTable(o2::steer::MCKinematicsReader const& mcreader) +{ + + auto digitizationContext = mcreader.getDigitizationContext(); + const auto& records = digitizationContext->getEventRecords(); + const auto& parts = digitizationContext->getEventParts(); + + TableBuilder mcCollBuilder; + auto mcCollCursor = mcCollBuilder.cursor<o2::aod::McCollisions>(); + + // QUESTIONS: + // Well defined enumeration for Generator type? + // What to do with pile-up/embedded collision - which generator type? + // In the data model: What are "null / invalid" values or default values + // In the data model: What are the units? + + // iterating over records gives us the time information + int index = 0; + for (auto& rec : records) { + // concrete header information is available via the parts and MCKineReader + auto time = rec.getTimeNS(); + auto& colparts = parts[index]; + // get event ID(s) and source ID(s) + // if there are more than one sources --> the generator might differ but vertex etc should be same + auto eventID = colparts[0].entryID; + auto sourceID = colparts[0].sourceID; + + auto& header = mcreader.getMCEventHeader(eventID, sourceID); + //DECLARE_SOA_TABLE(McCollisions, "AOD", "MCCOLLISION", o2::soa::Index<>, mccollision::BCId, + // mccollision::GeneratorsID, + // mccollision::PosX, mccollision::PosY, mccollision::PosZ, mccollision::T, mccollision::Weight, + // mccollision::ImpactParameter); + + mcCollCursor(0, 0 /*bcID*/, 0 /*genID*/, header.GetX(), header.GetY(), header.GetZ(), time, 1. /*weight*/, header.GetB()); + + index++; + } + auto mccoltable = mcCollBuilder.finalize(); + + TFile outfile("aod.root", "UPDATE"); + { + TableToTree t2t(mccoltable, &outfile, aod::MetadataTrait<o2::aod::McCollisions>::metadata::tableLabel()); + t2t.addAllBranches(); + t2t.process(); + } +} + +// add vertices/collisions +void fillCollisionAndTrackTable() +{ + // open the file for vertices + TFile f("o2_primary_vertex.root", "OPEN"); + auto t = (TTree*)f.Get("o2sim"); + + // fetch the tracks (these names are not following any convention!!) + auto tpctracks = fetchTracks<o2::tpc::TrackTPC>("tpctracks.root", "events", "Tracks"); + auto itstracks = fetchTracks<o2::its::TrackITS>("o2trac_its.root", "o2sim", "ITSTrack"); + auto itstpctracks = fetchTracks<o2::dataformats::TrackTPCITS>("o2match_itstpc.root", "matchTPCITS", "TPCITS"); + LOG(INFO) << "FOUND " << tpctracks->size() << " TPC tracks"; + LOG(INFO) << "FOUND " << itstracks->size() << " ITS tracks"; + LOG(INFO) << "FOUND " << itstpctracks->size() << " ITCTPC tracks"; + + if (t) { + auto br = t->GetBranch("PrimaryVertex"); + std::vector<o2::dataformats::PrimaryVertex>* vertices = nullptr; + br->SetAddress(&vertices); + br->GetEntry(0); + + // this referes to actual tracks + auto indexbr = t->GetBranch("PVTrackIndices"); + std::vector<GIndex>* vertexTrackIDs = nullptr; + indexbr->SetAddress(&vertexTrackIDs); + indexbr->GetEntry(0); + + // this makes the connection of vertex to track indices + auto v2totrackrefbr = t->GetBranch("PV2TrackRefs"); + std::vector<o2::dataformats::VtxTrackRef>* v2trackref = nullptr; + v2totrackrefbr->SetAddress(&v2trackref); + v2totrackrefbr->GetEntry(0); + + if (vertices && vertexTrackIDs) { + TableBuilder collBuilder; + auto collCursor = collBuilder.cursor<o2::aod::Collisions>(); + + TableBuilder trackBuilder; + auto trackCursor = trackBuilder.cursor<o2::aod::Tracks>(); + + int index = 0; + for (auto& v : *vertices) { + //DECLARE_SOA_TABLE(Collisions, "AOD", "COLLISION", o2::soa::Index<>, + // collision::BCId, collision::PosX, collision::PosY, collision::PosZ, + // collision::CovXX, collision::CovXY, collision::CovXZ, collision::CovYY, collision::CovYZ, collision::CovZZ, + // collision::Chi2, collision::NumContrib, collision::CollisionTime, collision::CollisionTimeRes, collision::CollisionTimeMask); + int BCid = 0; + auto& cov = v.getCov(); + auto& ts = v.getTimeStamp(); + + // TODO: figure out BC + CollisionTimeMask + collCursor(0, BCid, v.getX(), v.getY(), v.getZ(), + cov[0], cov[1], cov[2], cov[3], cov[4], cov[6], + v.getChi2(), v.getNContributors(), ts.getTimeStamp(), ts.getTimeStampError(), 1); + + // get the track for each vertex and fill the tracks table + // now go over tracks via the indices + auto& trackref = (*v2trackref)[index]; + int start = trackref.getFirstEntryOfSource(0); + int ntracks = trackref.getEntriesOfSource(0); + for (int ti = 0; ti < ntracks; ++ti) { + auto trackindex = (*vertexTrackIDs)[start + ti]; + + // now we need to fetch the actual track and fill the table + const auto source = trackindex.getSource(); + o2::track::TrackParCov* track = nullptr; + if (source == o2::dataformats::VtxTrackIndex::Source::TPC) { + track = &((*tpctracks)[trackindex.getIndex()]); + } else if (source == o2::dataformats::VtxTrackIndex::Source::ITS) { + track = &((*itstracks)[trackindex.getIndex()]); + } else if (source == o2::dataformats::VtxTrackIndex::Source::TPCITS) { + track = &((*itstpctracks)[trackindex.getIndex()]); + } else { + LOG(WARNING) << "Unsupported track source"; + } + + //DECLARE_SOA_TABLE_FULL(StoredTracks, "Tracks", "AOD", "TRACK:PAR", + // o2::soa::Index<>, track::CollisionId, track::TrackType, + // track::X, track::Alpha, + // track::Y, track::Z, track::Snp, track::Tgl, + // track::Signed1Pt, + // track::NormalizedPhi<track::RawPhi>, + // track::Px<track::Signed1Pt, track::Snp, track::Alpha>, + // track::Py<track::Signed1Pt, track::Snp, track::Alpha>, + // track::Pz<track::Signed1Pt, track::Tgl>, + // track::Charge<track::Signed1Pt>); + + std::array<float, 3> pxpypz; + track->getPxPyPzGlo(pxpypz); + trackCursor(0, index, 0 /* CORRECT THIS */, track->getX(), track->getAlpha(), track->getY(), track->getZ(), track->getSnp(), track->getTgl(), + track->getPt() /*CHECK!!*/, track->getPhi(), pxpypz[0], pxpypz[1], pxpypz[2]); + } + index++; + } + auto colltable = collBuilder.finalize(); + auto tracktable = trackBuilder.finalize(); + + f.Close(); + TFile outfile("aod.root", "RECREATE"); + { + TableToTree t2t(colltable, &outfile, aod::MetadataTrait<o2::aod::Collisions>::metadata::tableLabel()); + t2t.addAllBranches(); + t2t.process(); + } + { + TableToTree t2t(tracktable, &outfile, "Tracks" /* aod::MetadataTrait<o2::aod::Tracks>::metadata::tableLabel() */); + t2t.addAllBranches(); + t2t.process(); + } + } + } +} + +// TODO: add MCparticles + +int main() +{ + fillCollisionAndTrackTable(); + + o2::steer::MCKinematicsReader mcreader("collisioncontext.root"); + fillMCollisionTable(mcreader); + + return 0; +} diff --git a/Detectors/CMakeLists.txt b/Detectors/CMakeLists.txt index 774b14856f6f9..e15b6fefa0c04 100644 --- a/Detectors/CMakeLists.txt +++ b/Detectors/CMakeLists.txt @@ -32,6 +32,7 @@ add_subdirectory(TPC) add_subdirectory(GlobalTracking) add_subdirectory(GlobalTrackingWorkflow) add_subdirectory(Vertexing) +add_subdirectory(AOD) add_subdirectory(Calibration) add_subdirectory(DCS) diff --git a/Steer/include/Steer/MCKinematicsReader.h b/Steer/include/Steer/MCKinematicsReader.h index e031a251c7e65..f73497fbff6f6 100644 --- a/Steer/include/Steer/MCKinematicsReader.h +++ b/Steer/include/Steer/MCKinematicsReader.h @@ -11,12 +11,14 @@ #include "SimulationDataFormat/DigitizationContext.h" #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCEventHeader.h" #include <vector> class TChain; namespace o2 { + namespace steer { @@ -77,8 +79,17 @@ class MCKinematicsReader /// get all mothers/daughters of the given label + /// retrieves the MCEventHeader for a given eventID and sourceID + o2::dataformats::MCEventHeader const& getMCEventHeader(int source, int event) const; + + DigitizationContext const* getDigitizationContext() const + { + return mDigitizationContext; + } + private: void loadTracksForSource(int source) const; + void loadHeadersForSource(int source) const; DigitizationContext const* mDigitizationContext = nullptr; @@ -87,6 +98,7 @@ class MCKinematicsReader // a vector of tracks foreach source and each collision mutable std::vector<std::vector<std::vector<o2::MCTrack>>> mTracks; // the in-memory track container + mutable std::vector<std::vector<o2::dataformats::MCEventHeader>> mHeaders; // the in-memory header container bool mInitialized = false; // whether initialized }; @@ -125,5 +137,13 @@ inline std::vector<MCTrack> const& MCKinematicsReader::getTracks(int event) cons return getTracks(0, event); } +inline o2::dataformats::MCEventHeader const& MCKinematicsReader::getMCEventHeader(int source, int event) const +{ + if (mHeaders.at(source).size() == 0) { + loadHeadersForSource(source); + } + return mHeaders.at(source)[event]; +} + } // namespace steer } // namespace o2 diff --git a/Steer/src/MCKinematicsReader.cxx b/Steer/src/MCKinematicsReader.cxx index ec16b76570038..a77089db29172 100644 --- a/Steer/src/MCKinematicsReader.cxx +++ b/Steer/src/MCKinematicsReader.cxx @@ -10,6 +10,7 @@ #include "DetectorsCommonDataFormats/NameConf.h" #include "Steer/MCKinematicsReader.h" +#include "SimulationDataFormat/MCEventHeader.h" #include <TChain.h> #include <vector> #include "FairLogger.h" @@ -35,6 +36,26 @@ void MCKinematicsReader::loadTracksForSource(int source) const } } +void MCKinematicsReader::loadHeadersForSource(int source) const +{ + auto chain = mInputChains[source]; + if (chain) { + // todo: get name from NameConfig + auto br = chain->GetBranch("MCEventHeader."); + if (br) { + o2::dataformats::MCEventHeader* header = nullptr; + br->SetAddress(&header); + mHeaders[source].resize(br->GetEntries()); + for (int event = 0; event < br->GetEntries(); ++event) { + br->GetEntry(event); + mHeaders[source][event] = *header; + } + } else { + LOG(WARN) << "MCHeader branch not found"; + } + } +} + bool MCKinematicsReader::initFromDigitContext(std::string_view name) { if (mInitialized) { @@ -54,6 +75,7 @@ bool MCKinematicsReader::initFromDigitContext(std::string_view name) // load the kinematics information mTracks.resize(mInputChains.size()); + mHeaders.resize(mInputChains.size()); // actual loading will be done only if someone asks // the first time for a particular source ... @@ -70,6 +92,7 @@ bool MCKinematicsReader::initFromKinematics(std::string_view name) mInputChains.emplace_back(new TChain("o2sim")); mInputChains.back()->AddFile(o2::base::NameConf::getMCKinematicsFileName(name.data()).c_str()); mTracks.resize(1); + mHeaders.resize(1); mInitialized = true; return true; diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index 6b3ecce876e62..e7d582f799be7 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -151,4 +151,8 @@ if [ "$doreco" == "1" ]; then #need results of ITSTPC-TOF matching (+ TOF clusters and ITS-TPC tracks) root -b -q -l $O2_ROOT/share/macro/checkTOFMatching.C 1>tofmatch_qa.log 2>&1 echo "Return status of TOF matching qa: $?" + + echo "Producing AOD" + taskwrapper aod.log o2-reco-standalone-aod-producer + echo "Return status of AOD production: $?" fi From 72a53b968eb403915c5a95e38af5b719b481959a Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Mon, 5 Oct 2020 16:33:17 +0200 Subject: [PATCH 0846/1751] Add knopers8 and Barthelemy as code owners of Data Sampling (#4507) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index ea94454bfdb50..6a230634f7d43 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -114,10 +114,10 @@ /Utilities @AliceO2Group/framework-admins /Utilities/Mergers @Barthelemy @knopers8 +/Utilities/DataSampling @Barthelemy @knopers8 #/Utilities/DataCompression #/Utilities/DataFlow #/Utilities/MCStepLogger -#/Utilities/Mergers #/Utilities/O2Device #/Utilities/O2MessageMonitor #/Utilities/PCG From 4383a11ffe9d620cc4b6f40e0088d2f19635d22b Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Fri, 2 Oct 2020 14:44:15 +0200 Subject: [PATCH 0847/1751] Keep tracking frame rotation angle between -pi and +pi --- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index e549211e85039..ff50aa3eff96c 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -685,8 +685,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK } int currSec = mGeo->GetSector(currDet); if (currSec != GetSector(prop->getAlpha())) { - float currAlpha = GetAlphaOfSector(currSec); - if (!prop->rotate(currAlpha)) { + if (!prop->rotate(GetAlphaOfSector(currSec))) { if (ENABLE_WARNING) { Warning("FollowProlongation", "Track could not be rotated in tracklet coordinate system"); } @@ -1075,7 +1074,13 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::AdjustSector(PROP* prop, TRDTRK* t, c return false; } int sign = (y > 0) ? 1 : -1; - if (!prop->rotate(alphaCurr + alpha * sign)) { + float alphaNew = alphaCurr + alpha * sign; + if (alphaNew > M_PI) { + alphaNew -= 2 * M_PI; + } else if (alphaNew < -M_PI) { + alphaNew += 2 * M_PI; + } + if (!prop->rotate(alphaNew)) { return false; } if (!prop->propagateToX(xTmp, .8f, 2.f)) { @@ -1107,7 +1112,11 @@ GPUd() float GPUTRDTracker_t<TRDTRK, PROP>::GetAlphaOfSector(const int sec) cons //-------------------------------------------------------------------- // rotation angle for TRD sector sec //-------------------------------------------------------------------- - return (2.0f * M_PI / (float)kNSectors * ((float)sec + 0.5f)); + float alpha = 2.0f * M_PI / (float)kNSectors * ((float)sec + 0.5f); + if (alpha > M_PI) { + alpha -= 2 * M_PI; + } + return alpha; } template <class TRDTRK, class PROP> From 665c82339f52c32abebaf17c60cb4003ecbb70c1 Mon Sep 17 00:00:00 2001 From: Jan Fiete Grosse-Oetringhaus <jgrosseo@cern.ch> Date: Mon, 5 Oct 2020 16:14:34 +0200 Subject: [PATCH 0848/1751] adding histogram task which reads full tracks --- Analysis/Tutorials/CMakeLists.txt | 5 +++ .../src/collisionTracksIteration.cxx | 6 +-- .../Tutorials/src/histogramsFullTracks.cxx | 37 +++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 Analysis/Tutorials/src/histogramsFullTracks.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index 98ae8843a15f8..f7d61f1d8818f 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -57,6 +57,11 @@ o2_add_dpl_workflow(histograms PUBLIC_LINK_LIBRARIES O2::Framework COMPONENT_NAME AnalysisTutorial) +o2_add_dpl_workflow(histograms-full-tracks + SOURCES src/histogramsFullTracks.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + COMPONENT_NAME AnalysisTutorial) + o2_add_dpl_workflow(filters SOURCES src/filters.cxx PUBLIC_LINK_LIBRARIES O2::Framework diff --git a/Analysis/Tutorials/src/collisionTracksIteration.cxx b/Analysis/Tutorials/src/collisionTracksIteration.cxx index 8bf3b940309e8..e2d1f8a07efe3 100644 --- a/Analysis/Tutorials/src/collisionTracksIteration.cxx +++ b/Analysis/Tutorials/src/collisionTracksIteration.cxx @@ -23,10 +23,10 @@ using namespace o2::framework; struct ATask { void process(aod::Collision const&, aod::Tracks const& tracks) { - // FIXME: to see some output, we create the histogram - // for every timeframe. In general this is not the way it - // should be done. LOGF(info, "Tracks for collision: %d", tracks.size()); + for (auto& track : tracks) { + LOGF(info, "This track has pT = %f GeV/c", track.pt()); + } } }; diff --git a/Analysis/Tutorials/src/histogramsFullTracks.cxx b/Analysis/Tutorials/src/histogramsFullTracks.cxx new file mode 100644 index 0000000000000..3dab7398facdf --- /dev/null +++ b/Analysis/Tutorials/src/histogramsFullTracks.cxx @@ -0,0 +1,37 @@ +// 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 <TH2F.h> + +#include <cmath> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct ATask { + OutputObj<TH2F> etaClsH{TH2F("eta_vs_cls", "eta_vs_cls", 102, -2.01, 2.01, 160, -0.5, 159.5)}; + + void process(aod::FullTracks const& tracks) + { + for (auto& track : tracks) { + etaClsH->Fill(track.eta(), track.tpcNClsFindable()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<ATask>("eta-and-cls-histograms"), + }; +} From 0c67316ed363a0ef4fbc6a655e90008282752133 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 5 Oct 2020 23:56:10 +0200 Subject: [PATCH 0849/1751] DPL Analysis: more protections for empty tables (#4503) * Added protection to spawner() * Moved protection from Extend() to joinTables * Join now checks consistent row numbers and works with empty tables --- Framework/Core/include/Framework/ASoA.h | 18 +++++++++++------- Framework/Core/src/ASoA.cxx | 20 +++++++++++++++----- Framework/Core/test/test_ASoA.cxx | 23 +++++++++++++++++++++++ 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 9cc1e14f3f57c..6c95679f6dfd6 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1757,12 +1757,20 @@ auto filter(T&& t, framework::expressions::Filter const& expr) template <typename... C> auto spawner(framework::pack<C...> columns, arrow::Table* atable) { + static auto new_schema = o2::soa::createSchemaFromColumns(columns); + static auto projectors = framework::expressions::createProjectors(columns, atable->schema()); + + std::vector<std::shared_ptr<arrow::ChunkedArray>> arrays; + + if (atable->num_rows() == 0) { + return arrow::Table::Make(new_schema, arrays); + } + arrow::TableBatchReader reader(*atable); std::shared_ptr<arrow::RecordBatch> batch; arrow::ArrayVector v; std::array<arrow::ArrayVector, sizeof...(C)> chunks; - static auto projectors = framework::expressions::createProjectors(columns, atable->schema()); while (true) { auto s = reader.ReadNext(&batch); if (!s.ok()) { @@ -1779,11 +1787,10 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) chunks[i].emplace_back(v.at(i)); } } - std::vector<std::shared_ptr<arrow::ChunkedArray>> arrays; + for (auto i = 0u; i < sizeof...(C); ++i) { arrays.push_back(std::make_shared<arrow::ChunkedArray>(chunks[i])); } - static auto new_schema = o2::soa::createSchemaFromColumns(columns); return arrow::Table::Make(new_schema, arrays); } @@ -1822,10 +1829,7 @@ auto Extend(T const& table) { static_assert((soa::is_type_spawnable_v<Cs> && ...), "You can only extend a table with expression columns"); using output_t = Join<T, soa::Table<Cs...>>; - if (table.tableSize() > 0) { - return output_t{{spawner(framework::pack<Cs...>{}, table.asArrowTable().get()), table.asArrowTable()}, 0}; - } - return output_t{{nullptr}, 0}; + return output_t{{spawner(framework::pack<Cs...>{}, table.asArrowTable().get()), table.asArrowTable()}, 0}; } /// Template function to attach dynamic columns on-the-fly (e.g. inside diff --git a/Framework/Core/src/ASoA.cxx b/Framework/Core/src/ASoA.cxx index 2508ee2f905c6..256fafc438c2e 100644 --- a/Framework/Core/src/ASoA.cxx +++ b/Framework/Core/src/ASoA.cxx @@ -19,16 +19,26 @@ std::shared_ptr<arrow::Table> ArrowHelpers::joinTables(std::vector<std::shared_p if (tables.size() == 1) { return tables[0]; } - std::vector<std::shared_ptr<arrow::ChunkedArray>> columns; + for (auto i = 0u; i < tables.size() - 1; ++i) { + assert(tables[i]->num_rows() == tables[i + 1]->num_rows()); + } std::vector<std::shared_ptr<arrow::Field>> fields; + std::vector<std::shared_ptr<arrow::ChunkedArray>> columns; for (auto& t : tables) { - for (auto i = 0; i < t->num_columns(); ++i) { - columns.push_back(t->column(i)); - fields.push_back(t->schema()->field(i)); + auto tf = t->fields(); + std::copy(tf.begin(), tf.end(), std::back_inserter(fields)); + } + + auto schema = std::make_shared<arrow::Schema>(fields); + + if (tables[0]->num_rows() != 0) { + for (auto& t : tables) { + auto tc = t->columns(); + std::copy(tc.begin(), tc.end(), std::back_inserter(columns)); } } - return arrow::Table::Make(std::make_shared<arrow::Schema>(fields), columns); + return arrow::Table::Make(schema, columns); } std::shared_ptr<arrow::Table> ArrowHelpers::concatTables(std::vector<std::shared_ptr<arrow::Table>>&& tables) diff --git a/Framework/Core/test/test_ASoA.cxx b/Framework/Core/test/test_ASoA.cxx index b276f86c95552..cb7bca0c9d301 100644 --- a/Framework/Core/test/test_ASoA.cxx +++ b/Framework/Core/test/test_ASoA.cxx @@ -14,6 +14,8 @@ #include "Framework/ASoA.h" #include "Framework/ASoAHelpers.h" +#include "Framework/Expressions.h" +#include "../src/ExpressionHelpers.h" #include "gandiva/tree_expr_builder.h" #include "arrow/status.h" #include "gandiva/filter.h" @@ -30,6 +32,7 @@ DECLARE_SOA_COLUMN_FULL(X, x, int32_t, "x"); DECLARE_SOA_COLUMN_FULL(Y, y, int32_t, "y"); DECLARE_SOA_COLUMN_FULL(Z, z, int32_t, "z"); DECLARE_SOA_DYNAMIC_COLUMN(Sum, sum, [](int32_t x, int32_t y) { return x + y; }); +DECLARE_SOA_EXPRESSION_COLUMN(ESum, esum, int32_t, 1 * test::x + test::y); } // namespace test DECLARE_SOA_TABLE(Points, "TST", "POINTS", test::X, test::Y); @@ -622,3 +625,23 @@ BOOST_AUTO_TEST_CASE(TestNestedFiltering) } BOOST_CHECK_EQUAL(i, 1); } + +BOOST_AUTO_TEST_CASE(TestEmptyTables) +{ + TableBuilder bPoints; + auto pwriter = bPoints.cursor<Points>(); + auto pempty = bPoints.finalize(); + + TableBuilder bInfos; + auto iwriter = bInfos.cursor<Infos>(); + auto iempty = bInfos.finalize(); + + Points p{pempty}; + Infos i{iempty}; + + using PI = Join<Points, Infos>; + PI pi{0, pempty, iempty}; + BOOST_CHECK_EQUAL(pi.size(), 0); + auto spawned = Extend<Points, test::ESum>(p); + BOOST_CHECK_EQUAL(spawned.size(), 0); +} From b7ec63980c5d77a6ff5198a444e8d67d4deca7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Tue, 6 Oct 2020 08:58:06 +0200 Subject: [PATCH 0850/1751] =?UTF-8?q?PWGHF:=20Add=203-prong=20table,=20can?= =?UTF-8?q?didate=20creator,=20and=20D=C2=B1=20task.=20(#4510)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../include/Analysis/SecondaryVertexHF.h | 98 +++++++++++- Analysis/Tasks/PWGHF/CMakeLists.txt | 10 ++ .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 139 ++++++++++++++++++ .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 10 +- Analysis/Tasks/PWGHF/taskDPlus.cxx | 78 ++++++++++ 5 files changed, 329 insertions(+), 6 deletions(-) create mode 100644 Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx create mode 100644 Analysis/Tasks/PWGHF/taskDPlus.cxx diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index 96bbde88a2a07..38717adba46c0 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -204,8 +204,7 @@ 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, + hf_track_index::Index0Id, hf_track_index::Index1Id, /* dynamic columns */ hf_cand_prong2::ImpactParameterProduct<hf_cand::ImpactParameter0, hf_cand::ImpactParameter1>, hf_cand_prong2::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, @@ -234,6 +233,101 @@ DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng2Ext, HfCandProng2Origin, "HFCANDPRG2 using HfCandProng2 = HfCandProng2Ext; +// specific 3-prong decay properties +namespace hf_cand_prong3 +{ +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, 1.f * aod::hf_cand::pxProng0 + 1.f * aod::hf_cand::pxProng1 + 1.f * aod::hf_cand::pxProng2); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, 1.f * aod::hf_cand::pyProng0 + 1.f * aod::hf_cand::pyProng1 + 1.f * aod::hf_cand::pyProng2); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1 + 1.f * aod::hf_cand::pzProng2); +DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); + +// functions for specific particles + +// D± → π± K∓ π± + +template <typename T> +auto CtDPlus(const T& candidate) +{ + return candidate.ct(RecoDecay::getMassPDG(411)); +} + +template <typename T> +auto YDPlus(const T& candidate) +{ + return candidate.y(RecoDecay::getMassPDG(411)); +} + +template <typename T> +auto EDPlus(const T& candidate) +{ + return candidate.e(RecoDecay::getMassPDG(411)); +} + +template <typename T> +auto InvMassDPlus(const T& candidate) +{ + return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); +} +} // namespace hf_cand_prong3 + +DECLARE_SOA_TABLE(HfCandBase3, "AOD", "HFCANDBASE3", + collision::PosX, collision::PosY, collision::PosZ, + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, + /* dynamic columns */ + hf_cand::RSecondaryVertex<hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, + hf_cand::ImpactParameterNormalised0<hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0>, + hf_cand::ImpactParameterNormalised1<hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter1>, + hf_cand::PtProng0<hf_cand::PxProng0, hf_cand::PyProng0>, + hf_cand::Pt2Prong0<hf_cand::PxProng0, hf_cand::PyProng0>, + hf_cand::PVectorProng0<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0>, + hf_cand::PtProng1<hf_cand::PxProng1, hf_cand::PyProng1>, + hf_cand::Pt2Prong1<hf_cand::PxProng1, hf_cand::PyProng1>, + hf_cand::PVectorProng1<hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, + hf_cand::DecayLength<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex>, + hf_cand::DecayLengthXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, + hf_cand::DecayLengthNormalised<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand::ErrorDecayLength>, + hf_cand::DecayLengthXYNormalised<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ErrorDecayLengthXY>, //); + + //DECLARE_SOA_TABLE(HfCandProng3Base, "AOD", "HFCANDPRG3BASE", // TODO split table + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, + hf_track_index::Index0Id, hf_track_index::Index1Id, hf_track_index::Index2Id, + /* dynamic columns */ + hf_cand_prong3::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, + hf_cand_prong3::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, + hf_cand::ImpactParameterNormalised2<hf_cand::ImpactParameter2, hf_cand::ErrorImpactParameter2>, + hf_cand::PtProng2<hf_cand::PxProng2, hf_cand::PyProng2>, + hf_cand::Pt2Prong2<hf_cand::PxProng2, hf_cand::PyProng2>, + hf_cand::PVectorProng2<hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt<hf_cand_prong3::Px, hf_cand_prong3::Py>, + hf_cand::Pt2<hf_cand_prong3::Px, hf_cand_prong3::Py>, + hf_cand::P<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::P2<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::PVector<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::CPA<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::CPAXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py>, + hf_cand::Ct<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::Eta<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::Y<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::E<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::E2<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>); + +//using HfCandProng3Origin = soa::Join<HfCandBase3, HfCandProng3Base>; // TODO split table +using HfCandProng3Origin = HfCandBase3; + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng3Ext, HfCandProng3Origin, "HFCANDPRG3EXT", + hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz); + +using HfCandProng3 = HfCandProng3Ext; + } // namespace o2::aod #endif // O2_ANALYSIS_SECONDARYVERTEXHF_H_ diff --git a/Analysis/Tasks/PWGHF/CMakeLists.txt b/Analysis/Tasks/PWGHF/CMakeLists.txt index 1430c8765b705..f37b15d1ad06a 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-candidate-creator-3prong + SOURCES HFCandidateCreator3Prong.cxx + 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 @@ -27,3 +32,8 @@ o2_add_dpl_workflow(hf-task-d0 SOURCES taskD0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(hf-task-dplus + SOURCES taskDPlus.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx new file mode 100644 index 0000000000000..36304ae40e4b4 --- /dev/null +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -0,0 +1,139 @@ +// 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 HFCandidateCreator3Prong.cxx +/// \brief Reconstruction of heavy-flavour 3-prong decay candidates +/// \note Extended from HFCandidateCreator2Prong +/// +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" + +using namespace o2; +using namespace o2::framework; + +/// Reconstruction of heavy-flavour 3-prong decay candidates +struct HFCandidateCreator3Prong { + Produces<aod::HfCandBase3> rowCandidateBase; + //Produces<aod::HfCandProng3Base> rowCandidateProng3Base; // TODO split table + Configurable<double> magneticField{"d_bz", 5.0, "magnetic field"}; + Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; + Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; + Configurable<double> d_maxdzini{"d_maxdzini", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; + Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; + Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; + OutputObj<TH1F> hmass3{TH1F("hmass3", "3-track inv mass", 500, 1.6, 2.1)}; + OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.0e-4)}; + OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "XX element of SV cov. matrix", 100, 0., 0.2)}; + + double massPi = RecoDecay::getMassPDG(kPiPlus); + double massK = RecoDecay::getMassPDG(kKPlus); + double massPiKPi{0}; + + void process(aod::Collision const& collision, + aod::HfTrackIndexProng3 const& rowsTrackIndexProng3, + aod::BigTracks const& tracks) + { + // 3-prong vertex fitter + o2::vertexing::DCAFitterN<3> df; + df.setBz(magneticField); + df.setPropagateToPCA(b_propdca); + df.setMaxR(d_maxr); + df.setMaxDZIni(d_maxdzini); + df.setMinParamChange(d_minparamchange); + df.setMinRelChi2Change(d_minrelchi2change); + df.setUseAbsDCA(true); + + // loop over pairs of track indeces + for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) { + auto trackParVar0 = getTrackParCov(rowTrackIndexProng3.index0()); + auto trackParVar1 = getTrackParCov(rowTrackIndexProng3.index1()); + auto trackParVar2 = getTrackParCov(rowTrackIndexProng3.index2()); + + // reconstruct the 3-prong secondary vertex + if (df.process(trackParVar0, trackParVar1, trackParVar2) == 0) + continue; + const auto& secondaryVertex = df.getPCACandidate(); + auto chi2PCA = df.getChi2AtPCACandidate(); + auto covMatrixPCA = df.calcPCACovMatrix().Array(); + hCovSVXX->Fill(covMatrixPCA[0]); // FIXME: Calculation of errorDecayLength(XY) gives wrong values without this line. + trackParVar0 = df.getTrack(0); + trackParVar1 = df.getTrack(1); + trackParVar2 = df.getTrack(2); + + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; + trackParVar0.getPxPyPzGlo(pvec0); + trackParVar1.getPxPyPzGlo(pvec1); + trackParVar2.getPxPyPzGlo(pvec2); + + // calculate invariant mass + auto arrayMomenta = array{pvec0, pvec1, pvec2}; + massPiKPi = RecoDecay::M(arrayMomenta, array{massPi, massK, massPi}); + + // get track impact parameters + // This modifies track momenta! + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + hCovPVXX->Fill(covMatrixPV[0]); + o2::dataformats::DCA impactParameter0; + o2::dataformats::DCA impactParameter1; + o2::dataformats::DCA impactParameter2; + trackParVar0.propagateToDCA(primaryVertex, magneticField, &impactParameter0); + trackParVar1.propagateToDCA(primaryVertex, magneticField, &impactParameter1); + trackParVar2.propagateToDCA(primaryVertex, magneticField, &impactParameter2); + + // get uncertainty of the decay length + double phi, theta; + getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + // fill candidate table rows + rowCandidateBase(collision.posX(), collision.posY(), collision.posZ(), + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, //); + //rowCandidateProng3Base( // TODO split table + pvec0[0], pvec0[1], pvec0[2], + pvec1[0], pvec1[1], pvec1[2], + pvec2[0], pvec2[1], pvec2[2], + impactParameter0.getY(), impactParameter1.getY(), impactParameter2.getY(), + std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), std::sqrt(impactParameter2.getSigmaY2()), + rowTrackIndexProng3.index0Id(), rowTrackIndexProng3.index1Id(), rowTrackIndexProng3.index2Id()); + + // fill histograms + if (b_dovalplots) { + hmass3->Fill(massPiKPi); + } + } + } +}; + +/// Extends the base table with expression columns. +struct HFCandidateCreator3ProngExpressions { + Spawns<aod::HfCandProng3Ext> rowCandidateProng3; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<HFCandidateCreator3Prong>("hf-cand-creator-3prong"), + adaptAnalysisTask<HFCandidateCreator3ProngExpressions>("hf-cand-creator-3prong-expressions")}; +} diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 679fb5d767bc1..31c624311949a 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -114,8 +114,8 @@ struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 1000, -20.0, 20.0)}; - OutputObj<TH1F> hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; - OutputObj<TH1F> hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 1.6, 2.1)}; + OutputObj<TH1F> hmass2{TH1F("hmass2", ";Inv Mass (GeV/#it{c}^{2})", 500, 0, 5.0)}; + OutputObj<TH1F> hmass3{TH1F("hmass3", ";Inv Mass (GeV/#it{c}^{2})", 500, 1.6, 2.1)}; OutputObj<TH1F> hvtx3_x_out{TH1F("hvtx3_x", "3-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx3_y_out{TH1F("hvtx3_y", "3-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx3_z_out{TH1F("hvtx3_z", "3-track vtx", 1000, -20.0, 20.0)}; @@ -214,12 +214,13 @@ struct HFTrackIndexSkimsCreator { // 3-prong vertex reconstruction if (do3prong == 1) { - // second loop over positive tracks - //for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracksPos.end(); ++trackPos2) { if (trackPos1.isSel3Prong() == 0) continue; if (trackNeg1.isSel3Prong() == 0) continue; + + // second loop over positive tracks + //for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracksPos.end(); ++trackPos2) { for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracks.end(); ++trackPos2) { if (trackPos2.signed1Pt() < 0) continue; @@ -271,6 +272,7 @@ struct HFTrackIndexSkimsCreator { trackNeg1.globalIndex(), trackPos2.globalIndex(), 2); } + // second loop over negative tracks //for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracksNeg.end(); ++trackNeg2) { for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracks.end(); ++trackNeg2) { diff --git a/Analysis/Tasks/PWGHF/taskDPlus.cxx b/Analysis/Tasks/PWGHF/taskDPlus.cxx new file mode 100644 index 0000000000000..01c30df080ebe --- /dev/null +++ b/Analysis/Tasks/PWGHF/taskDPlus.cxx @@ -0,0 +1,78 @@ +// 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 taskDPlus.cxx +/// \brief D± analysis task +/// \note Extended from taskD0 +/// +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::hf_cand_prong3; +//using namespace o2::framework::expressions; + +/// D± analysis task +struct TaskDPlus { + OutputObj<TH1F> hmass{TH1F("hmass", "3-track inv mass", 500, 1.6, 2.1)}; + OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0, 10.0)}; + OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0, 10.0)}; + OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0, 10.0)}; + OutputObj<TH1F> hptprong2{TH1F("hptprong2", "pt prong2", 100, 0, 10.0)}; + OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.0)}; + OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.0)}; + OutputObj<TH1F> hd0{TH1F("hd0", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; + OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; + OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; + //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; + OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1.0, 1.0)}; + OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.0)}; + OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.0)}; + + Configurable<int> d_selectionFlagDPlus{"d_selectionFlagDPlus", 1, "Selection Flag for DPlus"}; + + //Filter seltrack = (aod::hfselcandidate::isSelDPlus >= d_selectionFlagDPlus); + + //void process(soa::Filtered<soa::Join<aod::HfCandProng3, aod::HFSelDPlusCandidate>> const& candidates) + void process(aod::HfCandProng3 const& candidates) + { + for (auto& candidate : candidates) { + hmass->Fill(InvMassDPlus(candidate)); + hptcand->Fill(candidate.pt()); + hptprong0->Fill(candidate.ptProng0()); + hptprong1->Fill(candidate.ptProng1()); + hptprong2->Fill(candidate.ptProng2()); + hdeclength->Fill(candidate.decayLength()); + hdeclengthxy->Fill(candidate.decayLengthXY()); + hd0->Fill(candidate.impactParameter0()); + hd0->Fill(candidate.impactParameter1()); + hd0->Fill(candidate.impactParameter2()); + hCt->Fill(CtDPlus(candidate)); + hEta->Fill(candidate.eta()); + //hselectionstatus->Fill(candidate.isSelDPlus()); + hImpParErr->Fill(candidate.errorImpactParameter0()); + hImpParErr->Fill(candidate.errorImpactParameter1()); + hImpParErr->Fill(candidate.errorImpactParameter2()); + hDecLenErr->Fill(candidate.errorDecayLength()); + hDecLenXYErr->Fill(candidate.errorDecayLengthXY()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<TaskDPlus>("hf-task-dplus")}; +} From 26f0ec96aaeaddd074a67731413e9d3171b1033c Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Tue, 6 Oct 2020 08:58:45 +0200 Subject: [PATCH 0851/1751] adding preselection cut on the candidate minimum pt for the two and the 3 prong (#4509) --- Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 31c624311949a..53b179eaeb853 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -110,6 +110,8 @@ struct HFTrackIndexSkimsCreator { Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min mass dplus presel"}; Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; + Configurable<double> ptmincand_2prong{"ptmincand_2prong", -1, "ptmin 2prong candidate"}; + Configurable<double> ptmincand_3prong{"ptmincand_3prong", -1, "ptmin 3prong candidate"}; OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 1000, -2.0, 2.0)}; @@ -131,6 +133,8 @@ struct HFTrackIndexSkimsCreator { double mass2PiK{0}; double mass2KPi{0}; double mass3PiKPi{0}; + double ptcand_2prong{0}; + double ptcand_3prong{0}; void process(aod::Collision const& collision, aod::BCs const& bcs, @@ -198,7 +202,10 @@ struct HFTrackIndexSkimsCreator { auto arrMom = array{pvec0, pvec1}; mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); + ptcand_2prong = RecoDecay::Pt(pvec0, pvec1); + if (ptcand_2prong < ptmincand_2prong) + continue; if (b_dovalplots) { hmass2->Fill(mass2PiK); hmass2->Fill(mass2KPi); @@ -258,7 +265,10 @@ struct HFTrackIndexSkimsCreator { // calculate invariant mass arr3Mom = array{pvec0, pvec1, pvec2}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + ptcand_3prong = RecoDecay::Pt(pvec0, pvec1, pvec2); + if (ptcand_3prong < ptmincand_3prong) + continue; if (b_dovalplots) { hmass3->Fill(mass3PiKPi); hvtx3_x_out->Fill(secondaryVertex3[0]); @@ -311,7 +321,10 @@ struct HFTrackIndexSkimsCreator { // calculate invariant mass arr3Mom = array{pvec0, pvec1, pvec2}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + ptcand_3prong = RecoDecay::Pt(pvec0, pvec1, pvec2); + if (ptcand_3prong < ptmincand_3prong) + continue; if (b_dovalplots) { hmass3->Fill(mass3PiKPi); } From dc3c75e50ff373e4a3a7b7da9d56ee778354f7aa Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Fri, 2 Oct 2020 17:30:00 +0200 Subject: [PATCH 0852/1751] Update documentation on external generator --- Generators/share/external/GenCosmics.C | 2 +- Generators/share/external/GenCosmicsLoader.C | 2 +- Generators/share/external/README.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generators/share/external/GenCosmics.C b/Generators/share/external/GenCosmics.C index 493bfcf6c1311..f8757c2b51a89 100644 --- a/Generators/share/external/GenCosmics.C +++ b/Generators/share/external/GenCosmics.C @@ -9,7 +9,7 @@ // 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 +//< o2-sim -n10000 -m PIPE ITS TPC -g extgen --configKeyValues "GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/GenCosmicsLoader.C" R__LOAD_LIBRARY(libGeneratorCosmics.so) diff --git a/Generators/share/external/GenCosmicsLoader.C b/Generators/share/external/GenCosmicsLoader.C index fa646743e674e..3ed746b30ac59 100644 --- a/Generators/share/external/GenCosmicsLoader.C +++ b/Generators/share/external/GenCosmicsLoader.C @@ -9,7 +9,7 @@ // 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 +//< o2-sim -n10000 -m PIPE ITS TPC -g extgen --configKeyValues "GeneratorExternal.fileName=$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 diff --git a/Generators/share/external/README.md b/Generators/share/external/README.md index 9a52ce1c01f33..6eab4521b7faa 100644 --- a/Generators/share/external/README.md +++ b/Generators/share/external/README.md @@ -21,12 +21,12 @@ The x-section of the process depends on the applied cuts, it is calculated on th - 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`` +``o2-sim -n1000 -m PIPE ITS TPC -g extgen --configKeyValues "GeneratorExternal.fileName=$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`` +``o2-sim -n100 -m PIPE ITS TPC -g extgen --configKeyValues "cosmics.maxAngle=40.;cosmics.accept=ITS0;cosmics.origin=500;GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/GenCosmicsLoader.C"`` See GenCosmicsParam class for available options. ------------ From 756f2c745bb2d7a75bf5611fe15ef9b5d572142d Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 6 Oct 2020 11:46:36 +0200 Subject: [PATCH 0853/1751] Fixing timestamp lookup (#4515) --- Analysis/Tasks/centralityTable.cxx | 10 +++++----- Analysis/Tasks/eventSelection.cxx | 13 ++++++------- .../Core/include/Framework/AnalysisDataModel.h | 2 ++ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Analysis/Tasks/centralityTable.cxx b/Analysis/Tasks/centralityTable.cxx index ffa4337255db5..19dac63be3746 100644 --- a/Analysis/Tasks/centralityTable.cxx +++ b/Analysis/Tasks/centralityTable.cxx @@ -29,13 +29,13 @@ struct CentralityTableTask { ccdb->setLocalObjectValidityChecking(); } - void process(soa::Join<aod::Collisions, aod::Mults>::iterator const& collision, aod::Timestamps& timestamps, aod::BCs const& bcs) + void process(soa::Join<aod::Collisions, aod::Mults>::iterator const& collision, aod::BCsWithTimestamps const&) { - auto ts = timestamps.iteratorAt(collision.bcId()); - LOGF(debug, "timestamp=%llu", ts.timestamp()); - TH1F* hCumMultV0M = ccdb->getForTimeStamp<TH1F>("Multiplicity/CumMultV0M", ts.timestamp()); + auto bc = collision.bc_as<aod::BCsWithTimestamps>(); + LOGF(debug, "timestamp=%llu", bc.timestamp()); + TH1F* hCumMultV0M = ccdb->getForTimeStamp<TH1F>("Multiplicity/CumMultV0M", bc.timestamp()); if (!hCumMultV0M) { - LOGF(fatal, "V0M centrality calibration is not available in CCDB for run=%d at timestamp=%llu", collision.bc().runNumber(), ts.timestamp()); + LOGF(fatal, "V0M centrality calibration is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } float centV0M = hCumMultV0M->GetBinContent(hCumMultV0M->FindFixBin(collision.multV0M())); diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index 15ccf4cf87bcb..a8e2590f2f516 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -13,7 +13,6 @@ #include "Analysis/EventSelection.h" #include "Analysis/TriggerAliases.h" #include <CCDB/BasicCCDBManager.h> -#include <map> using namespace o2; using namespace o2::framework; @@ -93,15 +92,15 @@ struct EventSelectionTask { ccdb->setLocalObjectValidityChecking(); } - void process(aod::Collision const& collision, aod::BCs const& bcs, aod::Timestamps& timestamps, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs const& fdds) + void process(aod::Collision const& collision, aod::BCsWithTimestamps const&, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs const& fdds) { - auto ts = timestamps.iteratorAt(collision.bcId()); - LOGF(debug, "timestamp=%llu", ts.timestamp()); - TriggerAliases* aliases = ccdb->getForTimeStamp<TriggerAliases>("Trigger/TriggerAliases", ts.timestamp()); + auto bc = collision.bc_as<aod::BCsWithTimestamps>(); + LOGF(debug, "timestamp=%llu", bc.timestamp()); + TriggerAliases* aliases = ccdb->getForTimeStamp<TriggerAliases>("Trigger/TriggerAliases", bc.timestamp()); if (!aliases) { - LOGF(fatal, "Trigger aliases are not available in CCDB for run=%d at timestamp=%llu", collision.bc().runNumber(), ts.timestamp()); + LOGF(fatal, "Trigger aliases are not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } - uint64_t triggerMask = collision.bc().triggerMask(); + uint64_t triggerMask = bc.triggerMask(); LOGF(debug, "triggerMask=%llu", triggerMask); // fill fired aliases diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 728e5b00e0482..69b20c7259b95 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -42,6 +42,8 @@ DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); DECLARE_SOA_TABLE(Timestamps, "AOD", "TIMESTAMPS", timestamp::Timestamp); +using BCsWithTimestamps = soa::Join<aod::BCs, aod::Timestamps>; + namespace collision { DECLARE_SOA_INDEX_COLUMN(BC, bc); From ad7196f2df77fe68b21346f1120c23542d0e0817 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 6 Oct 2020 12:13:38 +0200 Subject: [PATCH 0854/1751] More isolation for simulation tests perform simulation tests in a dedicated working dir have log files prefixed with the proper simulation prefix --- run/CMakeLists.txt | 17 +++++++++++------ run/o2sim_parallel.cxx | 42 +++++++++++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index 3dc66a1d5f853..96c68ffd81dde 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -103,11 +103,16 @@ o2_data_file(COPY o2simtopology.json DESTINATION config) # perform # * # some checks on kinematics and track references + +# make workspace for simulation tests +set(SIMTESTDIR ${CMAKE_BINARY_DIR}/o2sim_tests) +file(MAKE_DIRECTORY ${SIMTESTDIR}) + o2_name_target(sim NAME o2simExecutable IS_EXE) o2_name_target(sim-serial NAME o2simSerialExecutable IS_EXE) o2_add_test_wrapper(NAME o2sim_G4 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${SIMTESTDIR} DONT_FAIL_ON_TIMEOUT MAX_ATTEMPTS 2 TIMEOUT 400 @@ -134,7 +139,7 @@ set_property(TEST o2sim_G4 APPEND PROPERTY ENVIRONMENT ${G4ENV}) # # note that the MT is currently only supported in the non FairMQ version o2_add_test_wrapper(NAME o2sim_G4_mt - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${SIMTESTDIR} DONT_FAIL_ON_TIMEOUT MAX_ATTEMPTS 2 TIMEOUT 400 @@ -160,7 +165,7 @@ set_property(TEST o2sim_G4_mt APPEND PROPERTY ENVIRONMENT ${G4ENV}) o2_add_test(CheckStackG4 SOURCES checkStack.cxx NAME o2sim_checksimkinematics_G4 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${SIMTESTDIR} COMMAND_LINE_ARGS o2simG4 PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat NO_BOOST_TEST @@ -170,7 +175,7 @@ set_tests_properties(o2sim_checksimkinematics_G4 PROPERTIES FIXTURES_REQUIRED G4) o2_add_test_wrapper(NAME o2sim_G3 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${SIMTESTDIR} DONT_FAIL_ON_TIMEOUT MAX_ATTEMPTS 3 COMMAND $<TARGET_FILE:${o2simExecutable}> @@ -199,7 +204,7 @@ set_property(TEST o2sim_G3 APPEND PROPERTY ENVIRONMENT "ALICE_O2SIM_DUMPLOG=ON") o2_add_test(CheckStackG3 SOURCES checkStack.cxx NAME o2sim_checksimkinematics_G3 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${SIMTESTDIR} COMMAND_LINE_ARGS o2simG3 PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat NO_BOOST_TEST @@ -210,7 +215,7 @@ set_tests_properties(o2sim_checksimkinematics_G3 PROPERTIES FIXTURES_REQUIRED G3) o2_add_test_wrapper(NAME o2sim_hepmc - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${SIMTESTDIR} DONT_FAIL_ON_TIMEOUT MAX_ATTEMPTS 2 TIMEOUT 400 diff --git a/run/o2sim_parallel.cxx b/run/o2sim_parallel.cxx index 18cb9dfa38446..91b9a02affade 100644 --- a/run/o2sim_parallel.cxx +++ b/run/o2sim_parallel.cxx @@ -36,9 +36,29 @@ #include "rapidjson/filereadstream.h" #include "rapidjson/filewritestream.h" -static const char* serverlogname = "serverlog"; -static const char* workerlogname = "workerlog"; -static const char* mergerlogname = "mergerlog"; +std::string getServerLogName() +{ + auto& conf = o2::conf::SimConfig::Instance(); + std::stringstream str; + str << conf.getOutPrefix() << "_serverlog"; + return str.str(); +} + +std::string getWorkerLogName() +{ + auto& conf = o2::conf::SimConfig::Instance(); + std::stringstream str; + str << conf.getOutPrefix() << "_workerlog"; + return str.str(); +} + +std::string getMergerLogName() +{ + auto& conf = o2::conf::SimConfig::Instance(); + std::stringstream str; + str << conf.getOutPrefix() << "_mergerlog"; + return str.str(); +} void cleanup() { @@ -49,21 +69,21 @@ void cleanup() if (getenv("ALICE_O2SIM_DUMPLOG")) { std::cerr << "------------- START OF EVENTSERVER LOG ----------" << std::endl; std::stringstream catcommand1; - catcommand1 << "cat " << serverlogname << ";"; + catcommand1 << "cat " << getServerLogName() << ";"; if (system(catcommand1.str().c_str()) != 0) { LOG(WARN) << "error executing system call"; } std::cerr << "------------- START OF SIM WORKER(S) LOG --------" << std::endl; std::stringstream catcommand2; - catcommand2 << "cat " << workerlogname << "*;"; + catcommand2 << "cat " << getWorkerLogName() << "*;"; if (system(catcommand2.str().c_str()) != 0) { LOG(WARN) << "error executing system call"; } std::cerr << "------------- START OF MERGER LOG ---------------" << std::endl; std::stringstream catcommand3; - catcommand3 << "cat " << mergerlogname << ";"; + catcommand3 << "cat " << getMergerLogName() << ";"; if (system(catcommand3.str().c_str()) != 0) { LOG(WARN) << "error executing system call"; } @@ -281,7 +301,7 @@ int main(int argc, char* argv[]) // the server int pid = fork(); if (pid == 0) { - int fd = open(serverlogname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + int fd = open(getServerLogName().c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); setenv("ALICE_O2SIMSERVERTODRIVER_PIPE", std::to_string(pipe_serverdriver_fd[1]).c_str(), 1); dup2(fd, 1); // make stdout go to file @@ -324,7 +344,7 @@ int main(int argc, char* argv[]) } else { childpids.push_back(pid); close(pipe_serverdriver_fd[1]); - std::cout << "Spawning particle server on PID " << pid << "; Redirect output to " << serverlogname << "\n"; + std::cout << "Spawning particle server on PID " << pid << "; Redirect output to " << getServerLogName() << "\n"; launchThreadMonitoringEvents(pipe_serverdriver_fd[0], "DISTRIBUTING EVENT : "); } @@ -336,7 +356,7 @@ int main(int argc, char* argv[]) for (int id = 0; id < nworkers; ++id) { // the workers std::stringstream workerlogss; - workerlogss << workerlogname << id; + workerlogss << getWorkerLogName() << id; // the workers std::stringstream workerss; @@ -370,7 +390,7 @@ int main(int argc, char* argv[]) pid = fork(); if (pid == 0) { - int fd = open(mergerlogname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + int fd = open(getMergerLogName().c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); dup2(fd, 1); // make stdout go to file dup2(fd, 2); // make stderr go to file - you may choose to not do this // or perhaps send stderr to another file @@ -384,7 +404,7 @@ int main(int argc, char* argv[]) (char*)nullptr); return 0; } else { - std::cout << "Spawning hit merger on PID " << pid << "; Redirect output to " << mergerlogname << "\n"; + std::cout << "Spawning hit merger on PID " << pid << "; Redirect output to " << getMergerLogName() << "\n"; childpids.push_back(pid); close(pipe_mergerdriver_fd[1]); launchThreadMonitoringEvents(pipe_mergerdriver_fd[0], "EVENT FINISHED : "); From efde4e384ccda43df7b783d120c8ab128cfb92ec Mon Sep 17 00:00:00 2001 From: arvindkhuntia <31609955+arvindkhuntia@users.noreply.github.com> Date: Tue, 6 Oct 2020 16:48:57 +0200 Subject: [PATCH 0855/1751] [FV0] pile-up simulation (#4500) * [FV0] pile-up simulation --- .../include/FV0Simulation/Digitizer.h | 56 ++++- .../include/FV0Simulation/FV0DigParam.h | 24 +- .../FIT/FV0/simulation/src/Digitizer.cxx | 236 +++++++++++++----- .../src/FV0DigitizerSpec.cxx | 8 +- 4 files changed, 237 insertions(+), 87 deletions(-) diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h index e4f9fa53d4a38..c03614b0d5ecd 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h @@ -35,7 +35,7 @@ class Digitizer public: Digitizer() - : mTimeStamp(0), mIntRecord(), mEventId(-1), mSrcId(-1), mMCLabels(), mPmtChargeVsTime(), mNBins(), mPmtResponseGlobal(), mPmtResponseTemp() + : mTimeStamp(0), mIntRecord(), mEventId(-1), mSrcId(-1), mMCLabels(), mCache(), mPmtChargeVsTime(), mNBins(), mNTimeBinsPerBC(), mPmtResponseGlobal(), mPmtResponseTemp() { } @@ -53,25 +53,61 @@ class Digitizer void setSrcId(Int_t id) { mSrcId = id; } void setInteractionRecord(const InteractionTimeRecord& ir) { mIntRecord = ir; } - void process(const std::vector<o2::fv0::Hit>& hits); - void analyseWaveformsAndStore(std::vector<fv0::BCData>& digitsBC, - std::vector<fv0::ChannelData>& digitsCh, - dataformats::MCTruthContainer<fv0::MCLabel>& labels); + void process(const std::vector<o2::fv0::Hit>& hits, std::vector<o2::fv0::BCData>& digitsBC, + std::vector<o2::fv0::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels); + + void flush(std::vector<o2::fv0::BCData>& digitsBC, + std::vector<o2::fv0::ChannelData>& digitsCh, + o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels); const InteractionRecord& getInteractionRecord() const { return mIntRecord; } InteractionRecord& getInteractionRecord(InteractionRecord& src) { return mIntRecord; } uint32_t getOrbit() const { return mIntRecord.orbit; } uint16_t getBC() const { return mIntRecord.bc; } + using ChannelBCDataF = std::vector<float>; + + struct BCCache : public o2::InteractionRecord { + std::vector<o2::fv0::MCLabel> labels; + std::array<ChannelBCDataF, Constants::nFv0Channels> mPmtChargeVsTime = {}; + + void clear() + { + for (auto& channel : mPmtChargeVsTime) { + std::fill(channel.begin(), channel.end(), 0.); + } + labels.clear(); + } + + BCCache& operator=(const o2::InteractionRecord& ir) + { + o2::InteractionRecord::operator=(ir); + return *this; + } + void print() const; + }; + private: + static constexpr int BCCacheMin = 0, BCCacheMax = 7, NBC2Cache = 1 + BCCacheMax - BCCacheMin; + void createPulse(float mipFraction, int parID, const double hitTime, std::array<o2::InteractionRecord, NBC2Cache> const& cachedIR, + int nCachedIR, const int detID); + long mTimeStamp; // TF (run) timestamp - InteractionRecord mIntRecord; // Interaction record (orbit, bc) -> InteractionTimeRecord + InteractionTimeRecord mIntRecord; // Interaction record (orbit, bc) -> InteractionTimeRecord Int_t mEventId; // ID of the current event Int_t mSrcId; // signal, background or QED - std::vector<fv0::MCLabel> mMCLabels; + std::deque<fv0::MCLabel> mMCLabels; + std::deque<BCCache> mCache; + + BCCache& setBCCache(const o2::InteractionRecord& ir); + BCCache* getBCCache(const o2::InteractionRecord& ir); + + void storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv0::ChannelData>& digitsCh, + o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels); std::array<std::vector<Float_t>, Constants::nFv0Channels> mPmtChargeVsTime; // Charge time series aka analogue signal pulse from PM - UInt_t mNBins; // Number of bins in pulse series + UInt_t mNBins; // + UInt_t mNTimeBinsPerBC; Float_t mBinSize; // Time width of the pulse bin - HPTDC resolution /// vectors to store the PMT signal from cosmic muons @@ -80,7 +116,9 @@ class Digitizer /// Internal helper methods related to conversion of energy-deposition into el. signal Int_t SimulateLightYield(Int_t pmt, Int_t nPhot) const; - Float_t SimulateTimeCfd(Int_t channel) const; + Float_t SimulateTimeCfd(const ChannelBCDataF& pulse) const; + Float_t IntegrateCharge(const ChannelBCDataF& pulse) const; + // Float_t SimulateTimeCfd(Int_t channel, Int_t iCache) const; /// Functions related to splitting ring-5 cell signal to two readout channels static float getDistFromCellCenter(UInt_t cellId, double hitx, double hity); diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h index c70c4464ccf6a..0901ff3c1b0ee 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h @@ -13,13 +13,13 @@ #include "CommonUtils/ConfigurableParam.h" #include "CommonUtils/ConfigurableParamHelper.h" +#include "CommonConstants/PhysicsConstants.h" namespace o2 { namespace fv0 { // parameters of FV0 digitization / transport simulation - struct FV0DigParam : public o2::conf::ConfigurableParamHelper<FV0DigParam> { float intrinsicTimeRes = 0.91; // time resolution float photoCathodeEfficiency = 0.23; // quantum efficiency = nOfPhotoE_emitted_by_photocathode / nIncidentPhotons @@ -28,23 +28,23 @@ struct FV0DigParam : public o2::conf::ConfigurableParamHelper<FV0DigParam> { float pmtTransitTime = 9.5; // PMT response time (corresponds to 1.9 ns rise time) float pmtTransparency = 0.25; // Transparency of the first dynode of the PMT float shapeConst = 1.18059e-14; // Crystal ball const parameter - float shapeMean = 1.70518e+01; // Crystal ball mean parameter + float shapeMean = 9.5; // Crystal ball mean parameter float shapeAlpha = -6.56586e-01; // Crystal ball alpha parameter float shapeN = 2.36408e+00; // Crystal ball N parameter float shapeSigma = 3.55445; // Crystal ball sigma parameter - float timeShiftCfd = 3.3; // TODO: adjust after PM design for FV0 is fixed + //float timeShiftCfd = 3.3; // From the cosmic measurements of FV0 [keep it for reference] + float timeShiftCfd = 5.3; // TODO: adjust after FV0 with FEE measurements are done float singleMipThreshold = 3.0; // in [MeV] of deposited energy + float singleHitTimeThreshold = 120.0; // in [ns] to skip very slow particles float waveformNbins = 10000; // number of bins for the analog pulse waveform float waveformBinWidth = 0.01302; // number of bins for the analog - float timeCompensate = 23.25; // in ns - float chargeIntBinMin = (timeCompensate - 6.0) / waveformBinWidth; //Charge integration offset (cfd mean time - 6 ns) - float chargeIntBinMax = (timeCompensate + 14.0) / waveformBinWidth; //Charge integration offset (cfd mean time + 14 ns) - bool isIntegrateFull = false; - float cfdCheckWindow = 2.5; // in ns - int avgPhElectron = 201; - - //Optimization-related, derived constants - float oneOverPmtTransitTime2 = 1.0 / (pmtTransitTime * pmtTransitTime); + float avgCfdTimeForMip = 8.63; // in ns to shift the CFD time to zero TODO do ring wise + int chargeIntBinMin = (avgCfdTimeForMip - 6.0) / waveformBinWidth; //Charge integration offset (cfd mean time - 6 ns) + int chargeIntBinMax = (avgCfdTimeForMip + 14.0) / waveformBinWidth; //Charge integration offset (cfd mean time + 14 ns) + bool isIntegrateFull = false; // Full charge integration widow in 25 ns + float cfdCheckWindow = 2.5; // time window for the cfd in ns to trigger the charge integration + int avgNumberPhElectronPerMip = 201; // avg number of photo-electrons per MIP + float globalTimeOfFlight = 315.0 / o2::constants::physics::LightSpeedCm2NS; //TODO check the correct value for distance of FV0 to IP O2ParamDef(FV0DigParam, "FV0DigParam"); }; diff --git a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx index 2cc2bafbf07d2..3ce0a80e69022 100644 --- a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx @@ -37,6 +37,8 @@ void Digitizer::init() mNBins = FV0DigParam::Instance().waveformNbins; //Will be computed using detector set-up from CDB mBinSize = FV0DigParam::Instance().waveformBinWidth; //Will be set-up from CDB + mNTimeBinsPerBC = int(o2::constants::lhc::LHCBunchSpacingNS / mBinSize); + for (Int_t detID = 0; detID < Constants::nFv0Channels; detID++) { mPmtChargeVsTime[detID].resize(mNBins); } @@ -50,7 +52,7 @@ void Digitizer::init() FV0DigParam::Instance().shapeN); // PMT response per hit [Global] - float x = mBinSize; + float x = mBinSize / 2.0; /// Calculate at BinCenter mPmtResponseGlobal.resize(mNBins); for (Int_t j = 0; j < mPmtResponseGlobal.size(); ++j) { mPmtResponseGlobal[j] = signalShapeFn.Eval(x); @@ -61,26 +63,27 @@ void Digitizer::init() LOG(INFO) << "V0Digitizer::init -> finished"; } -void Digitizer::process(const std::vector<o2::fv0::Hit>& hits) +void Digitizer::process(const std::vector<o2::fv0::Hit>& hits, std::vector<o2::fv0::BCData>& digitsBC, + std::vector<o2::fv0::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels) { LOG(INFO) << "[FV0] Digitizer::process(): begin with " << hits.size() << " hits"; + flush(digitsBC, digitsCh, labels); // flush cached signal which cannot be affect by new event std::vector<int> hitIdx(hits.size()); std::iota(std::begin(hitIdx), std::end(hitIdx), 0); - std::sort(std::begin(hitIdx), std::end(hitIdx), [&hits](int a, int b) { return hits[a].GetTrackID() < hits[b].GetTrackID(); }); - + std::sort(std::begin(hitIdx), std::end(hitIdx), + [&hits](int a, int b) { return hits[a].GetTrackID() < hits[b].GetTrackID(); }); Int_t parentIdPrev = -10; // use ordered hits for (auto ids : hitIdx) { const auto& hit = hits[ids]; Int_t detId = hit.GetDetectorID(); Double_t hitEdep = hit.GetHitValue() * 1e3; //convert to MeV - + Float_t const hitTime = hit.GetTime() * 1e9; // TODO: check how big is inaccuracy if more than 1 'below-threshold' particles hit the same detector cell - if (hitEdep < FV0DigParam::Instance().singleMipThreshold) { + if (hitEdep < FV0DigParam::Instance().singleMipThreshold || hitTime > FV0DigParam::Instance().singleHitTimeThreshold) { continue; } - float distanceFromXc = 0; if (Geometry::instance()->isRing5(detId)) { distanceFromXc = getDistFromCellCenter(detId, hit.GetX(), hit.GetY()); @@ -90,14 +93,13 @@ void Digitizer::process(const std::vector<o2::fv0::Hit>& hits) while (iChannelPerCell < 2) { // loop over 2 channels, into which signal from each cell in ring 5 is split if (Geometry::instance()->isRing5(detId)) { // The first channel number is located counter-clockwise from the cell center - // and remains identical to the detector number, the second one is clockwise and incremented by 8 + // and remains identical to the detector number, the second one is clockwise and incremented by 8 if (iChannelPerCell == 1) { detId += 8; } - // Split signal magnitude to fractions depending on the distance of the hit from the cell center hitEdep = (hit.GetHitValue() * 1e3) * getSignalFraction(distanceFromXc, iChannelPerCell == 0); - //LOG(INFO) << " detId: " << detId << "-" << iChannelPerCell << " hitEdep: " << hitEdep << " distanceFromXc: " << distanceFromXc; + // LOG(INFO) << " detId: " << detId << "-" << iChannelPerCell << " hitEdep: " << hitEdep << " distanceFromXc: " << distanceFromXc; ++iChannelPerCell; } else { iChannelPerCell = 2; // not a ring 5 cell -> don't repeat the loop @@ -105,64 +107,112 @@ void Digitizer::process(const std::vector<o2::fv0::Hit>& hits) Double_t const nPhotons = hitEdep * DP::N_PHOTONS_PER_MEV; float const nPhE = SimulateLightYield(detId, nPhotons); - float avgMip = float(nPhE / FV0DigParam::Instance().avgPhElectron); - Float_t const hitTime = hit.GetTime() * 1e9; - //------------------------------------------------------------------------------ - mPmtResponseTemp = mPmtResponseGlobal; - Size_t NBinShift = std::lround(hitTime / FV0DigParam::Instance().waveformBinWidth); - for (int m = 0; m < NBinShift; m++) - mPmtResponseTemp.push_back(0); - // rotate the vector element to shift all the elements by hit time - std::rotate(mPmtResponseTemp.rbegin(), mPmtResponseTemp.rbegin() + NBinShift, mPmtResponseTemp.rend()); - mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins); - - for (int mm = 0; mm < mPmtResponseTemp.size(); mm++) { - mPmtChargeVsTime[detId][mm] += (mPmtResponseTemp[mm] * avgMip); - } - // Charged particles in MCLabel - Int_t const parentId = hit.GetTrackID(); - if (parentId != parentIdPrev) { - mMCLabels.emplace_back(parentId, mEventId, mSrcId, detId); - parentIdPrev = parentId; - } + float mipFraction = float(nPhE / FV0DigParam::Instance().avgNumberPhElectronPerMip); + Float_t timeHit = hitTime; + timeHit += mIntRecord.getTimeNS(); + o2::InteractionTimeRecord irHit(timeHit); + std::array<o2::InteractionRecord, NBC2Cache> cachedIR; + int nCachedIR = 0; + + for (int i = BCCacheMin; i < BCCacheMax + 1; i++) { + double tNS = timeHit + o2::constants::lhc::LHCBunchSpacingNS * i; + cachedIR[nCachedIR].setFromNS(tNS); + if (tNS < 0 && cachedIR[nCachedIR] > irHit) { + continue; // don't go to negative BC/orbit (it will wrap) + } + setBCCache(cachedIR[nCachedIR++]); // ensure existence of cached container + } //BCCache loop + createPulse(mipFraction, hit.GetTrackID(), hitTime, cachedIR, nCachedIR, detId); + + } //while loop + } //hitloop +} + +void Digitizer::createPulse(float mipFraction, int parID, const double hitTime, + std::array<o2::InteractionRecord, NBC2Cache> const& cachedIR, int nCachedIR, const int detId) +{ + + bool added[nCachedIR]; + for (int ir = 0; ir < nCachedIR; ir++) { + added[ir] = false; + } + + for (int ir = 0; ir < NBC2Cache; ir++) { + auto bcCache = getBCCache(cachedIR[ir]); + for (int ich = 0; ich < Constants::nFv0Channels; ich++) { + (*bcCache).mPmtChargeVsTime[ich].resize(mNTimeBinsPerBC); + } + } + + ///Time of flight subtracted from Hit time //TODO have different TOF according to thr ring number + Size_t NBinShift = std::lround((hitTime - FV0DigParam::Instance().globalTimeOfFlight) / FV0DigParam::Instance().waveformBinWidth); + mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins, 0.); + std::memcpy(&mPmtResponseTemp[NBinShift], &mPmtResponseGlobal[0], sizeof(double) * (FV0DigParam::Instance().waveformNbins - NBinShift)); + + for (int ir = 0; ir < int(mPmtResponseTemp.size() / mNTimeBinsPerBC); ir++) { + auto bcCache = getBCCache(cachedIR[ir]); + + for (int iBin = 0; iBin < mNTimeBinsPerBC; iBin++) { + (*bcCache).mPmtChargeVsTime[detId][iBin] += (mPmtResponseTemp[ir * mNTimeBinsPerBC + iBin] * mipFraction); } - } //hit loop + added[ir] = true; + } + ///Add MC labels to BCs for those contributed to the PMT signal + for (int ir = 0; ir < nCachedIR; ir++) { + if (added[ir]) { + auto bcCache = getBCCache(cachedIR[ir]); + (*bcCache).labels.emplace_back(parID, mEventId, mSrcId, detId); + } + } } -void Digitizer::analyseWaveformsAndStore(std::vector<fv0::BCData>& digitsBC, - std::vector<fv0::ChannelData>& digitsCh, - dataformats::MCTruthContainer<fv0::MCLabel>& labels) +void Digitizer::flush(std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv0::ChannelData>& digitsCh, + o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels) { - // Sum charge of all time bins to get total charge collected for a given channel - size_t const first = digitsCh.size(); + int nCached = mCache.size(); + if (nCached < 1) { + return; + } + for (auto bc : mCache) { + if (mIntRecord.differenceInBC(bc) > NBC2Cache) { // Build events those are separated by NBC2Cache BCs from current BC + storeBC(bc, digitsBC, digitsCh, labels); + mCache.pop_front(); + } else { + return; + } + } +} + +void Digitizer::storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv0::ChannelData>& digitsCh, + o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels) + +{ + int first = digitsCh.size(); size_t nStored = 0; - for (Int_t ipmt = 0; ipmt < Constants::nFv0Channels; ++ipmt) { - float time = SimulateTimeCfd(ipmt) - FV0DigParam::Instance().timeCompensate; - if (time < -FV0DigParam::Instance().cfdCheckWindow || time > FV0DigParam::Instance().cfdCheckWindow) - continue; - Float_t totalCharge = 0.0f; - auto const& analogSignal = mPmtChargeVsTime[ipmt]; + double totalCharge = 0; + for (int iPmt = 0; iPmt < Constants::nFv0Channels; iPmt++) { + double cfdWithOffset = SimulateTimeCfd(bc.mPmtChargeVsTime[iPmt]); + double cfdZero = cfdWithOffset - FV0DigParam::Instance().avgCfdTimeForMip; - int chargeIntMin = FV0DigParam::Instance().isIntegrateFull ? 0 : FV0DigParam::Instance().chargeIntBinMin; - int chargeIntMax = FV0DigParam::Instance().isIntegrateFull ? FV0DigParam::Instance().waveformNbins : FV0DigParam::Instance().chargeIntBinMax; + if (cfdZero < -FV0DigParam::Instance().cfdCheckWindow || cfdZero > FV0DigParam::Instance().cfdCheckWindow) + continue; - for (Int_t iTimeBin = chargeIntMin; iTimeBin < chargeIntMax; ++iTimeBin) { - Float_t const timeBinCharge = mPmtChargeVsTime[ipmt][iTimeBin]; - totalCharge += timeBinCharge; - } + //LOG(INFO) << "time inside analyse and store =========> " << cfdZero <<" detid "<<iPmt; + float charge = IntegrateCharge(bc.mPmtChargeVsTime[iPmt]); + totalCharge += charge; totalCharge *= DP::INV_CHARGE_PER_ADC; - time *= DP::INV_TIME_PER_TDCCHANNEL; - digitsCh.emplace_back(ipmt, static_cast<short int>(std::round(time)), static_cast<short int>(std::round(totalCharge))); + cfdZero *= DP::INV_TIME_PER_TDCCHANNEL; + + digitsCh.emplace_back(iPmt, static_cast<short int>(std::round(cfdZero)), + static_cast<short int>(std::round(totalCharge))); + totalCharge = 0; ++nStored; } - - // Send MClabels and digitsBC to storage - size_t const nBC = digitsBC.size(); - digitsBC.emplace_back(first, nStored, mIntRecord); - for (auto const& lbl : mMCLabels) { + int nBC = digitsBC.size(); + digitsBC.emplace_back(first, nStored, bc); + for (const auto& lbl : bc.labels) { labels.addElement(nBC, lbl); } - mMCLabels.clear(); } // ------------------------------------------------------------------------------- @@ -181,16 +231,35 @@ Int_t Digitizer::SimulateLightYield(Int_t pmt, Int_t nPhot) const : gRandom->Gaus((p * nPhot) + 0.5, TMath::Sqrt(p * (1. - p) * nPhot))); return n; } +//--------------------------------------------------------------------------- +Float_t Digitizer::IntegrateCharge(const ChannelBCDataF& pulse) const +{ + int chargeIntMin = FV0DigParam::Instance().isIntegrateFull ? 0 : FV0DigParam::Instance().chargeIntBinMin; + int chargeIntMax = FV0DigParam::Instance().isIntegrateFull ? mNTimeBinsPerBC : FV0DigParam::Instance().chargeIntBinMax; -Float_t Digitizer::SimulateTimeCfd(Int_t channel) const + Float_t totalCharge = 0.0f; + for (int iTimeBin = chargeIntMin; iTimeBin < chargeIntMax; iTimeBin++) { + Float_t const timeBinCharge = pulse[iTimeBin]; + //LOG(INFO)<<iTimeBin*0.013<<" "<<timeBinCharge; + totalCharge += timeBinCharge; + } + return totalCharge; +} +//--------------------------------------------------------------------------- +Float_t Digitizer::SimulateTimeCfd(/*Int_t channel, */ const ChannelBCDataF& pulse) const { Float_t timeCfd = -1024.0f; + + //auto& bc= mCache[iCache]; + + if (pulse.empty()) { + return timeCfd; + } + Int_t const binShift = TMath::Nint(FV0DigParam::Instance().timeShiftCfd / mBinSize); - Float_t sigPrev = -mPmtChargeVsTime[channel][0]; - for (Int_t iTimeBin = 1; iTimeBin < mNBins; ++iTimeBin) { - Float_t const sigCurrent = (iTimeBin >= binShift - ? 5.0f * mPmtChargeVsTime[channel][iTimeBin - binShift] - mPmtChargeVsTime[channel][iTimeBin] - : -mPmtChargeVsTime[channel][iTimeBin]); + Float_t sigPrev = -pulse[0]; //[0]; + for (Int_t iTimeBin = 1; iTimeBin < mNTimeBinsPerBC; ++iTimeBin) { + Float_t const sigCurrent = (iTimeBin >= binShift ? 5.0f * pulse[iTimeBin - binShift] - pulse[iTimeBin] : -pulse[iTimeBin]); if (sigPrev < 0.0f && sigCurrent >= 0.0f) { timeCfd = Float_t(iTimeBin) * mBinSize; break; @@ -200,7 +269,6 @@ Float_t Digitizer::SimulateTimeCfd(Int_t channel) const return timeCfd; } -// The Distance is positive for top half-sectors (when the hit position is above the cell center (has higher y)) float Digitizer::getDistFromCellCenter(UInt_t cellId, double hitx, double hity) { Geometry* geo = Geometry::instance(); @@ -212,7 +280,7 @@ float Digitizer::getDistFromCellCenter(UInt_t cellId, double hitx, double hity) double a = -(y0 - pCell->y) / (x0 - pCell->x); double b = 1; double c = -(y0 - a * x0); - // Return the distance from hit to this line + //Return the distance from hit to this line return (a * hitx + b * hity + c) / TMath::Sqrt(a * a + b * b); } @@ -225,3 +293,43 @@ float Digitizer::getSignalFraction(float distanceFromXc, bool isFirstChannel) return isFirstChannel ? (1. - fraction) : fraction; } } + +//_____________________________________________________________________________ +o2::fv0::Digitizer::BCCache& Digitizer::setBCCache(const o2::InteractionRecord& ir) +{ + if (mCache.empty() || mCache.back() < ir) { + mCache.emplace_back(); + auto& cb = mCache.back(); + cb = ir; + return cb; + } + if (mCache.front() > ir) { + mCache.emplace_front(); + auto& cb = mCache.front(); + cb = ir; + return cb; + } + + for (auto cb = mCache.begin(); cb != mCache.end(); cb++) { + if ((*cb) == ir) { + return *cb; + } + if (ir < (*cb)) { + auto cbnew = mCache.emplace(cb); // insert new element before cb + (*cbnew) = ir; + return (*cbnew); + } + } + return mCache.front(); +} +//_____________________________________________________________________________ +o2::fv0::Digitizer::BCCache* Digitizer::getBCCache(const o2::InteractionRecord& ir) +{ + // get pointer on existing cache + for (auto cb = mCache.begin(); cb != mCache.end(); cb++) { + if ((*cb) == ir) { + return &(*cb); + } + } + return nullptr; +} \ No newline at end of file diff --git a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx index 4de8f3c51d9e5..7e501e6f2ed81 100644 --- a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx @@ -85,12 +85,16 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer // call actual digitization procedure mDigitizer.setEventId(part.entryID); mDigitizer.setSrcId(part.sourceID); - mDigitizer.process(hits); + mDigitizer.process(hits, mDigitsBC, mDigitsCh, mLabels); } - mDigitizer.analyseWaveformsAndStore(mDigitsBC, mDigitsCh, mLabels); LOG(INFO) << "[FV0] Has " << mDigitsBC.size() << " BC elements, " << mDigitsCh.size() << " mDigitsCh elements"; } + o2::InteractionTimeRecord terminateIR; + terminateIR.orbit = 0xffffffff; // supply IR in the infinite future to flush all cached BC + mDigitizer.setInteractionRecord(terminateIR); + mDigitizer.flush(mDigitsBC, mDigitsCh, mLabels); + // here we have all digits and we can send them to consumer (aka snapshot it onto output) LOG(INFO) << "FV0: Sending " << mDigitsBC.size() << " digitsBC and " << mDigitsCh.size() << " digitsCh."; From e82e301a2fa94621e9b82fd93f4df9249fc68b74 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 6 Oct 2020 16:34:07 +0200 Subject: [PATCH 0856/1751] Disable o2sim_hepmc Disable test temporarily until problem with CI test fixed. --- run/CMakeLists.txt | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index 96c68ffd81dde..18baf220c4dce 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -214,25 +214,26 @@ o2_add_test(CheckStackG3 set_tests_properties(o2sim_checksimkinematics_G3 PROPERTIES FIXTURES_REQUIRED G3) -o2_add_test_wrapper(NAME o2sim_hepmc - WORKING_DIRECTORY ${SIMTESTDIR} - DONT_FAIL_ON_TIMEOUT - MAX_ATTEMPTS 2 - TIMEOUT 400 - COMMAND $<TARGET_FILE:${o2simExecutable}> - COMMAND_LINE_ARGS -n - 2 - -j - 2 - -g - hepmc - --configKeyValues - "HepMC.fileName=${CMAKE_SOURCE_DIR}/Generators/share/data/pythia.hepmc;HepMC.version=2" - -o - o2simhepmc - LABELS long sim hepmc3 - ENVIRONMENT "O2_ROOT=${CMAKE_BINARY_DIR}/stage;VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/share") -set_tests_properties(o2sim_hepmc - PROPERTIES PASS_REGULAR_EXPRESSION - "SIMULATION RETURNED SUCCESFULLY") +#o2_add_test_wrapper(NAME o2sim_hepmc +# WORKING_DIRECTORY ${SIMTESTDIR} +# DONT_FAIL_ON_TIMEOUT +# MAX_ATTEMPTS 2 +# TIMEOUT 400 +# COMMAND $<TARGET_FILE:${o2simExecutable}> +# COMMAND_LINE_ARGS -n +# 2 +# -j +# 2 +# -g +# hepmc +# --configKeyValues +# "HepMC.fileName=${CMAKE_SOURCE_DIR}/Generators/share/data/pythia.hepmc;HepMC.version=2" +# -o +# o2simhepmc +# LABELS long sim hepmc3 +# ENVIRONMENT "O2_ROOT=${CMAKE_BINARY_DIR}/stage;VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/share") +# +#set_tests_properties(o2sim_hepmc +# PROPERTIES PASS_REGULAR_EXPRESSION +# "SIMULATION RETURNED SUCCESFULLY") From fb2a0d894c0cc22b4126b43c0cac29747d01b261 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 6 Oct 2020 21:19:41 +0200 Subject: [PATCH 0857/1751] Update DataAllocator.cxx (#4513) --- Framework/Core/src/DataAllocator.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index ff48caee0c328..38bf5c04f190c 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -172,7 +172,6 @@ void DataAllocator::adopt(const Output& spec, TableBuilder* tb) void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) { std::string const& channel = matchDataHeader(spec, mTimingInfo->timeslice); - LOG(INFO) << "DataAllocator::adopt channel " << channel.c_str(); auto header = headerMessageFromOutput(spec, channel, o2::header::gSerializationMethodArrow, 0); auto& context = mRegistry->get<ArrowContext>(); From 7df478dbe95ac41196a9df4e290047f2c3e0fa53 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 6 Oct 2020 23:14:54 +0200 Subject: [PATCH 0858/1751] first version of reduced table for CF (#4520) --- .../DataModel/include/Analysis/CFDerived.h | 38 ++ Analysis/Tasks/PWGCF/CMakeLists.txt | 10 + Analysis/Tasks/PWGCF/correlations.cxx | 2 +- Analysis/Tasks/PWGCF/correlationsFiltered.cxx | 432 ++++++++++++++++++ Analysis/Tasks/PWGCF/filterCF.cxx | 82 ++++ 5 files changed, 563 insertions(+), 1 deletion(-) create mode 100644 Analysis/DataModel/include/Analysis/CFDerived.h create mode 100644 Analysis/Tasks/PWGCF/correlationsFiltered.cxx create mode 100644 Analysis/Tasks/PWGCF/filterCF.cxx diff --git a/Analysis/DataModel/include/Analysis/CFDerived.h b/Analysis/DataModel/include/Analysis/CFDerived.h new file mode 100644 index 0000000000000..78fdcdfee505c --- /dev/null +++ b/Analysis/DataModel/include/Analysis/CFDerived.h @@ -0,0 +1,38 @@ +// 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_CFDERIVED_H +#define O2_ANALYSIS_CFDERIVED_H + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Analysis/Centrality.h" + +namespace o2::aod +{ +DECLARE_SOA_TABLE(CFCollisions, "AOD", "CFCOLLISION", o2::soa::Index<>, + o2::aod::bc::RunNumber, o2::aod::collision::PosZ, o2::aod::cent::CentV0M); +using CFCollision = CFCollisions::iterator; + +namespace cftrack +{ +DECLARE_SOA_INDEX_COLUMN(CFCollision, cfCollision); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Charge, charge, int8_t); +} // namespace cftrack +DECLARE_SOA_TABLE(CFTracks, "AOD", "CFTRACK", o2::soa::Index<>, + cftrack::CFCollisionId, + cftrack::Pt, cftrack::Eta, cftrack::Phi, + cftrack::Charge, track::TrackType); +using CFTrack = CFTracks::iterator; +} // namespace o2::aod + +#endif // O2_ANALYSIS_CFDERIVED_H diff --git a/Analysis/Tasks/PWGCF/CMakeLists.txt b/Analysis/Tasks/PWGCF/CMakeLists.txt index 29309d8cab809..e7eb33cb131ab 100644 --- a/Analysis/Tasks/PWGCF/CMakeLists.txt +++ b/Analysis/Tasks/PWGCF/CMakeLists.txt @@ -31,3 +31,13 @@ o2_add_dpl_workflow(correlations-mixed PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore COMPONENT_NAME Analysis) +o2_add_dpl_workflow(filter-cf + SOURCES filterCF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(correlations-filtered + SOURCES correlationsFiltered.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index 1e6cae9672d54..de1566e3b419a 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -121,7 +121,7 @@ struct CorrelationTask { } // Version with explicit nested loop - void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents>>::iterator const& collision, aod::BCs const& bcs, aod::Run2V0s const& vzeros, myTracks const& tracks) + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents>>::iterator const& collision, myTracks const& tracks) { LOGF(info, "Tracks for collision: %d | Vertex: %.1f | INT7: %d | V0M: %.1f", tracks.size(), collision.posZ(), collision.sel7(), collision.centV0M()); diff --git a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx new file mode 100644 index 0000000000000..48c50c903ed9d --- /dev/null +++ b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx @@ -0,0 +1,432 @@ +// 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/EventSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/Centrality.h" +#include "Analysis/StepTHn.h" +#include "Analysis/CorrelationContainer.h" +#include "Analysis/CFDerived.h" + +#include <TH1F.h> +#include <cmath> +#include <TDirectory.h> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP}; + +struct CorrelationTask { + + // 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(cfgPtOrder, int, 1, "Only consider pairs for which pT,1 < pT,2 (0 = OFF, 1 = ON)"); + 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"); + + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value"); + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); + + O2_DEFINE_CONFIGURABLE(cfgPairCutPhoton, float, -1, "Pair cut on photons: -1 = off; >0 otherwise distance value (suggested: 0.004)") + O2_DEFINE_CONFIGURABLE(cfgPairCutK0, float, -1, "Pair cut on K0s: -1 = off; >0 otherwise distance value (suggested: 0.005)") + O2_DEFINE_CONFIGURABLE(cfgPairCutLambda, float, -1, "Pair cut on Lambda: -1 = off; >0 otherwise distance value (suggested: 0.005)") + 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::cftrack::eta) < cfgCutEta) && (aod::cftrack::pt > cfgCutPt); + + // Output definitions + OutputObj<CorrelationContainer> same{"sameEvent"}; + OutputObj<CorrelationContainer> mixed{"mixedEvent"}; + //OutputObj<TDirectory> qaOutput{"qa"}; + + enum PairCuts { Photon = 0, + K0, + Lambda, + Phi, + Rho }; + struct Config { + bool mPairCuts = false; + //THn* mEfficiencyTrigger = nullptr; + //THn* mEfficiencyAssociated = nullptr; + } cfg; + + struct QA { + TH3F* mTwoTrackDistancePt[2] = {nullptr}; // control histograms for two-track efficiency study: dphi*_min vs deta (0 = before cut, 1 = after cut) + TH2F* mControlConvResoncances = nullptr; // control histograms for cuts on conversions and resonances + } qa; + + // HistogramRegistry registry{"qa", true, { + // {"yields", "centrality vs pT vs eta", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"} }}}, + // {"etaphi", "centrality vs eta vs phi", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {100, -2, 2, "#eta"}, {200, 0, 2 * M_PI, "#varphi"} }}} + // }}; + + OutputObj<TH3F> yields{TH3F("yields", "centrality vs pT vs eta", 100, 0, 100, 40, 0, 20, 100, -2, 2)}; + OutputObj<TH3F> etaphi{TH3F("etaphi", "centrality vs eta vs phi", 100, 0, 100, 100, -2, 2, 200, 0, 2 * M_PI)}; + + void init(o2::framework::InitContext&) + { + // --- CONFIGURATION --- + const char* binning = + "vertex: 7 | -7, 7\n" + "delta_phi: 72 | -1.570796, 4.712389\n" + "delta_eta: 40 | -2.0, 2.0\n" + "p_t_assoc: 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0\n" + "p_t_trigger: 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0\n" + "multiplicity: 0, 5, 10, 20, 30, 40, 50, 100.1\n" + "eta: 20 | -1.0, 1.0\n" + "p_t_leading: 100 | 0.0, 50.0\n" + "p_t_leading_course: 0.5, 1.0, 2.0, 3.0, 4.0, 6.0, 8.0\n" + "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" + "vertex_eff: 10 | -10, 10\n"; + + if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) + cfg.mPairCuts = true; + + // --- OBJECT INIT --- + same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentralityVtx", binning)); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentralityVtx", binning)); + //qaOutput.setObject(new TDirectory("qa", "qa")); + + if (cfgTwoTrackCut > 0) { + qa.mTwoTrackDistancePt[0] = new TH3F("TwoTrackDistancePt[0]", ";#Delta#eta;#Delta#varphi^{*}_{min};#Delta p_{T}", 100, -0.15, 0.15, 100, -0.05, 0.05, 20, 0, 10); + qa.mTwoTrackDistancePt[1] = (TH3F*)qa.mTwoTrackDistancePt[0]->Clone("TwoTrackDistancePt[1]"); + //qaOutput->Add(qa.mTwoTrackDistancePt[0]); + //qaOutput->Add(qa.mTwoTrackDistancePt[1]); + } + + if (cfg.mPairCuts) { + qa.mControlConvResoncances = new TH2F("ControlConvResoncances", ";id;delta mass", 6, -0.5, 5.5, 500, -0.5, 0.5); + //qaOutput->Add(qa.mControlConvResoncances); + } + } + + // Version with explicit nested loop + void process(soa::Filtered<aod::CFCollisions>::iterator const& collision, soa::Filtered<aod::CFTracks> const& tracks) + { + LOGF(info, "Tracks for collision: %d | Vertex: %.1f | V0M: %.1f", tracks.size(), collision.posZ(), collision.centV0M()); + + const auto centrality = collision.centV0M(); + + same->fillEvent(centrality, CorrelationContainer::kCFStepReconstructed); + + int bSign = 1; // TODO magnetic field from CCDB + + for (auto& track1 : tracks) { + + // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); + + // control histograms + // ((TH3*) (registry.get("yields").get()))->Fill(centrality, track1.pt(), track1.eta()); + // ((TH3*) (registry.get("etaphi").get()))->Fill(centrality, track1.eta(), track1.phi()); + yields->Fill(centrality, track1.pt(), track1.eta()); + etaphi->Fill(centrality, track1.eta(), track1.phi()); + + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + continue; + + double eventValues[3]; + eventValues[0] = track1.pt(); + eventValues[1] = centrality; + eventValues[2] = collision.posZ(); + + same->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + + for (auto& track2 : tracks) { + if (track1 == track2) + continue; + + if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) + continue; + + if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) + continue; + if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) + continue; + + if (cfg.mPairCuts && conversionCuts(track1, track2)) + continue; + + if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) + continue; + + double values[6] = {0}; + + values[0] = track1.eta() - track2.eta(); + values[1] = track2.pt(); + values[2] = track1.pt(); + values[3] = centrality; + + values[4] = track1.phi() - track2.phi(); + if (values[4] > 1.5 * TMath::Pi()) + values[4] -= TMath::TwoPi(); + if (values[4] < -0.5 * TMath::Pi()) + values[4] += TMath::TwoPi(); + + values[5] = collision.posZ(); + + same->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + //mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + } + } + } + + template <typename T> + bool conversionCuts(T const& track1, T const& track2) + { + // skip if like sign + if (track1.charge() * track2.charge() > 0) + return false; + + bool decision = false; + + if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) + decision = true; + if (conversionCut(track1, track2, K0, cfgPairCutK0)) + decision = true; + if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) + decision = true; + if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) + decision = true; + if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) + decision = true; + if (conversionCut(track1, track2, Rho, cfgPairCutRho)) + decision = true; + + return decision; + } + + template <typename T> + bool conversionCut(T const& track1, T const& track2, PairCuts conv, double cut) + { + //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); + + if (cut < 0) + return false; + + double massD1, massD2, massM; + + switch (conv) { + case Photon: + massD1 = 0.51e-3; + massD2 = 0.51e-3; + massM = 0; + break; + case K0: + massD1 = 0.1396; + massD2 = 0.1396; + massM = 0.4976; + break; + case Lambda: + massD1 = 0.9383; + massD2 = 0.1396; + massM = 1.115; + break; + case Phi: + massD1 = 0.4937; + massD2 = 0.4937; + massM = 1.019; + break; + case Rho: + massD1 = 0.1396; + massD2 = 0.1396; + massM = 0.770; + break; + } + + auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); + + if (TMath::Abs(massC - massM * massM) > cut * 5) + return false; + + massC = getInvMassSquared(track1, massD1, track2, massD2); + qa.mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) + return true; + + return false; + } + + template <typename T> + double getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2) + { + // calculate inv mass squared + // same can be achieved, but with more computing time with + /*TLorentzVector photon, p1, p2; + p1.SetPtEtaPhiM(triggerParticle->Pt(), triggerEta, triggerParticle->Phi(), 0.510e-3); + p2.SetPtEtaPhiM(particle->Pt(), eta[j], particle->Phi(), 0.510e-3); + photon = p1+p2; + photon.M()*/ + + float tantheta1 = 1e10; + + if (track1.eta() < -1e-10 || track1.eta() > 1e-10) { + float expTmp = TMath::Exp(-track1.eta()); + tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float tantheta2 = 1e10; + if (track2.eta() < -1e-10 || track2.eta() > 1e-10) { + float expTmp = TMath::Exp(-track2.eta()); + tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); + + float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (TMath::Cos(track1.phi() - track2.phi()) + 1.0 / tantheta1 / tantheta2))); + + // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); + + return mass2; + } + + template <typename T> + double getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2) + { + // calculate inv mass squared approximately + + const float eta1 = track1.eta(); + const float eta2 = track2.eta(); + const float phi1 = track1.phi(); + const float phi2 = track2.phi(); + const float pt1 = track1.pt(); + const float pt2 = track2.pt(); + + float tantheta1 = 1e10; + + if (eta1 < -1e-10 || eta1 > 1e-10) { + float expTmp = 1.0 - eta1 + eta1 * eta1 / 2 - eta1 * eta1 * eta1 / 6 + eta1 * eta1 * eta1 * eta1 / 24; + tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float tantheta2 = 1e10; + if (eta2 < -1e-10 || eta2 > 1e-10) { + float expTmp = 1.0 - eta2 + eta2 * eta2 / 2 - eta2 * eta2 * eta2 / 6 + eta2 * eta2 * eta2 * eta2 / 24; + tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + pt1 * pt1 * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + pt2 * pt2 * (1.0 + 1.0 / tantheta2 / tantheta2); + + // fold onto 0...pi + float deltaPhi = TMath::Abs(phi1 - phi2); + while (deltaPhi > TMath::TwoPi()) + deltaPhi -= TMath::TwoPi(); + if (deltaPhi > TMath::Pi()) + deltaPhi = TMath::TwoPi() - deltaPhi; + + float cosDeltaPhi = 0; + if (deltaPhi < TMath::Pi() / 3) + cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; + else if (deltaPhi < 2 * TMath::Pi() / 3) + cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); + else + cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); + + double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); + + // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); + + return mass2; + } + + template <typename T> + bool twoTrackCut(T const& track1, T const& track2, int bSign) + { + // the variables & cuthave been developed by the HBT group + // see e.g. https://indico.cern.ch/materialDisplay.py?contribId=36&sessionId=6&materialId=slides&confId=142700 + + auto deta = track1.eta() - track2.eta(); + + // optimization + if (TMath::Abs(deta) < cfgTwoTrackCut * 2.5 * 3) { + // check first boundaries to see if is worth to loop and find the minimum + float dphistar1 = getDPhiStar(track1, track2, cfgTwoTrackCutMinRadius, bSign); + float dphistar2 = getDPhiStar(track1, track2, 2.5, bSign); + + const float kLimit = cfgTwoTrackCut * 3; + + if (TMath::Abs(dphistar1) < kLimit || TMath::Abs(dphistar2) < kLimit || dphistar1 * dphistar2 < 0) { + float dphistarminabs = 1e5; + float dphistarmin = 1e5; + for (Double_t rad = cfgTwoTrackCutMinRadius; rad < 2.51; rad += 0.01) { + float dphistar = getDPhiStar(track1, track2, rad, bSign); + + float dphistarabs = TMath::Abs(dphistar); + + if (dphistarabs < dphistarminabs) { + dphistarmin = dphistar; + dphistarminabs = dphistarabs; + } + } + + qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + + if (dphistarminabs < cfgTwoTrackCut && TMath::Abs(deta) < cfgTwoTrackCut) { + //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.charge(), track2.phi2(), track2.pt(), track2.charge(), bSign); + return true; + } + + qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + } + } + + return false; + } + + template <typename T> + float getDPhiStar(T const& track1, T const& track2, float radius, float bSign) + { + // + // calculates dphistar + // + + auto phi1 = track1.phi(); + auto pt1 = track1.pt(); + auto charge1 = track1.charge(); + + auto phi2 = track2.phi(); + auto pt2 = track2.pt(); + auto charge2 = track2.charge(); + + float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); + + static const Double_t kPi = TMath::Pi(); + + if (dphistar > kPi) + dphistar = kPi * 2 - dphistar; + if (dphistar < -kPi) + dphistar = -kPi * 2 - dphistar; + if (dphistar > kPi) // might look funny but is needed + dphistar = kPi * 2 - dphistar; + + return dphistar; + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<CorrelationTask>("correlation-task")}; +} diff --git a/Analysis/Tasks/PWGCF/filterCF.cxx b/Analysis/Tasks/PWGCF/filterCF.cxx new file mode 100644 index 0000000000000..98ed5274de027 --- /dev/null +++ b/Analysis/Tasks/PWGCF/filterCF.cxx @@ -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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "Analysis/CFDerived.h" +#include "Analysis/EventSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/Centrality.h" + +#include <TH3F.h> + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP}; + +struct FilterCF { + + // 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") + + // Filters and input definitions + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex && aod::cent::centV0M <= 80.0f; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); + + OutputObj<TH3F> yields{TH3F("yields", "centrality vs pT vs eta", 100, 0, 100, 40, 0, 20, 100, -2, 2)}; + OutputObj<TH3F> etaphi{TH3F("etaphi", "centrality vs eta vs phi", 100, 0, 100, 100, -2, 2, 200, 0, 2 * M_PI)}; + + Produces<aod::CFCollisions> outputCollisions; + Produces<aod::CFTracks> outputTracks; + + uint64_t eventCounter = 0; + + void init(o2::framework::InitContext&) + { + } + + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents>>::iterator const& collision, aod::BCs const&, soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection>> const& tracks) + { + LOGF(info, "Tracks for collision: %d | Vertex: %.1f | INT7: %d | V0M: %.1f", tracks.size(), collision.posZ(), collision.sel7(), collision.centV0M()); + + if (!collision.sel7()) + return; + + outputCollisions(collision.bc().runNumber(), collision.posZ(), collision.centV0M()); + + for (auto& track : tracks) { + uint8_t trackType = 0; + if (track.isGlobalTrack()) + trackType = 1; + else if (track.isGlobalTrackSDD()) + trackType = 2; + + // TODO can we get the eventCounter from the previous filling to collisions(...)? + outputTracks(eventCounter, track.pt(), track.eta(), track.phi(), track.charge(), trackType); + + yields->Fill(collision.centV0M(), track.pt(), track.eta()); + etaphi->Fill(collision.centV0M(), track.eta(), track.phi()); + } + + eventCounter++; + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<FilterCF>("filter-cf")}; +} From 8054558d84de7625f9966e4fe1ece3ce37b64d00 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Fri, 2 Oct 2020 11:08:26 +0200 Subject: [PATCH 0859/1751] fix in TOF digitizer to allow very large time --- Detectors/TOF/base/include/TOFBase/WindowFiller.h | 6 +++--- .../TOF/calibration/include/TOFCalibration/CalibTOFapi.h | 4 ++-- Detectors/TOF/calibration/src/CalibTOF.cxx | 4 ++-- Detectors/TOF/calibration/src/CalibTOFapi.cxx | 4 ++-- .../TOF/simulation/include/TOFSimulation/Digitizer.h | 2 +- Detectors/TOF/simulation/src/Digitizer.cxx | 9 ++++----- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index dacecadc26340..2b049ae5c90b7 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -33,8 +33,8 @@ class WindowFiller void reset(); - Int_t getCurrentReadoutWindow() const { return mReadoutWindowCurrent; } - void setCurrentReadoutWindow(Double_t value) { mReadoutWindowCurrent = value; } + uint64_t getCurrentReadoutWindow() const { return mReadoutWindowCurrent; } + void setCurrentReadoutWindow(uint64_t value) { mReadoutWindowCurrent = value; } void setEventTime(InteractionTimeRecord value) { mEventTime = value; @@ -54,7 +54,7 @@ class WindowFiller protected: // info TOF timewindow - Int_t mReadoutWindowCurrent = 0; + uint64_t mReadoutWindowCurrent = 0; InteractionRecord mFirstIR{0, 0}; // reference IR (1st IR of the timeframe) InteractionTimeRecord mEventTime; diff --git a/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h b/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h index 854edca6f4849..564d7590feb0a 100644 --- a/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h +++ b/Detectors/TOF/calibration/include/TOFCalibration/CalibTOFapi.h @@ -49,8 +49,8 @@ class CalibTOFapi } void readLHCphase(); void readTimeSlewingParam(); - void writeLHCphase(LhcPhase* phase, std::map<std::string, std::string> metadataLHCphase, unsigned long minTimeSTamp, unsigned long maxTimeStamp); - void writeTimeSlewingParam(SlewParam* param, std::map<std::string, std::string> metadataChannelCalib, unsigned long minTimeSTamp, unsigned long maxTimeStamp = 0); + void writeLHCphase(LhcPhase* phase, std::map<std::string, std::string> metadataLHCphase, uint64_t minTimeSTamp, uint64_t maxTimeStamp); + void writeTimeSlewingParam(SlewParam* param, std::map<std::string, std::string> metadataChannelCalib, uint64_t minTimeSTamp, uint64_t maxTimeStamp = 0); float getTimeCalibration(int ich, float tot); float getTimeDecalibration(int ich, float tot); bool isProblematic(int ich); diff --git a/Detectors/TOF/calibration/src/CalibTOF.cxx b/Detectors/TOF/calibration/src/CalibTOF.cxx index c37f5808c27c6..ffe8fde0c929e 100644 --- a/Detectors/TOF/calibration/src/CalibTOF.cxx +++ b/Detectors/TOF/calibration/src/CalibTOF.cxx @@ -269,11 +269,11 @@ void CalibTOF::fillOutput(int flag) if (mFillCCDB) { if (flag & kLHCphase) { std::map<std::string, std::string> metadataLHCphase; // can be empty - mCalibTOFapi.writeLHCphase(mLHCphaseObj, metadataLHCphase, (unsigned long)mMinTimestamp * 1000, (unsigned long)mMaxTimestamp * 1000); // we use as validity the timestamps that we got from the input for the calibration; but we need to convert to ms for the CCDB (at least for now that we use an integer for the timestamp) + mCalibTOFapi.writeLHCphase(mLHCphaseObj, metadataLHCphase, (uint64_t)mMinTimestamp * 1000, (uint64_t)mMaxTimestamp * 1000); // we use as validity the timestamps that we got from the input for the calibration; but we need to convert to ms for the CCDB (at least for now that we use an integer for the timestamp) } if (flag & kChannelOffset || flag & kChannelTimeSlewing) { std::map<std::string, std::string> metadataChannelCalib; // can be empty - mCalibTOFapi.writeTimeSlewingParam(mTimeSlewingObj, metadataChannelCalib, (unsigned long)mMinTimestamp * 1000); // contains both offset and time slewing; we use as validity the START ONLY timestamp that we got from the input for the calibration; but we need to convert to ms for the CCDB (at least for now that we use an integer for the timestamp), END is default + mCalibTOFapi.writeTimeSlewingParam(mTimeSlewingObj, metadataChannelCalib, (uint64_t)mMinTimestamp * 1000); // contains both offset and time slewing; we use as validity the START ONLY timestamp that we got from the input for the calibration; but we need to convert to ms for the CCDB (at least for now that we use an integer for the timestamp), END is default } } } diff --git a/Detectors/TOF/calibration/src/CalibTOFapi.cxx b/Detectors/TOF/calibration/src/CalibTOFapi.cxx index 7689412e2428f..b8f1a54156ed7 100644 --- a/Detectors/TOF/calibration/src/CalibTOFapi.cxx +++ b/Detectors/TOF/calibration/src/CalibTOFapi.cxx @@ -48,7 +48,7 @@ void CalibTOFapi::readTimeSlewingParam() //______________________________________________________________________ -void CalibTOFapi::writeLHCphase(LhcPhase* phase, std::map<std::string, std::string> metadataLHCphase, unsigned long minTimeStamp, unsigned long maxTimeStamp) +void CalibTOFapi::writeLHCphase(LhcPhase* phase, std::map<std::string, std::string> metadataLHCphase, uint64_t minTimeStamp, uint64_t maxTimeStamp) { // write LHCphase object to CCDB @@ -61,7 +61,7 @@ void CalibTOFapi::writeLHCphase(LhcPhase* phase, std::map<std::string, std::stri //______________________________________________________________________ -void CalibTOFapi::writeTimeSlewingParam(SlewParam* param, std::map<std::string, std::string> metadataChannelCalib, unsigned long minTimeStamp, unsigned long maxTimeStamp) +void CalibTOFapi::writeTimeSlewingParam(SlewParam* param, std::map<std::string, std::string> metadataChannelCalib, uint64_t minTimeStamp, uint64_t maxTimeStamp) { // write TiemSlewing object to CCDB (it includes offset + problematic) diff --git a/Detectors/TOF/simulation/include/TOFSimulation/Digitizer.h b/Detectors/TOF/simulation/include/TOFSimulation/Digitizer.h index 1dd93d9ee2090..453475bd775ee 100644 --- a/Detectors/TOF/simulation/include/TOFSimulation/Digitizer.h +++ b/Detectors/TOF/simulation/include/TOFSimulation/Digitizer.h @@ -114,7 +114,7 @@ class Digitizer : public WindowFiller CalibApi* mCalibApi = nullptr; //! calib api to handle the TOF calibration - void fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID); + void fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID); Int_t processHit(const HitType& hit, Double_t event_time); void addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, Float_t z, Float_t charge, Int_t iX, Int_t iZ, Int_t padZfired, diff --git a/Detectors/TOF/simulation/src/Digitizer.cxx b/Detectors/TOF/simulation/src/Digitizer.cxx index a778f27b6d4c5..2b27665a75b52 100644 --- a/Detectors/TOF/simulation/src/Digitizer.cxx +++ b/Detectors/TOF/simulation/src/Digitizer.cxx @@ -277,7 +277,7 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, // let's move from time to bc, tdc - Int_t nbc = Int_t(time * Geo::BC_TIME_INPS_INV); // time elapsed in number of bunch crossing + uint64_t nbc = (uint64_t)(time * Geo::BC_TIME_INPS_INV); // time elapsed in number of bunch crossing //Digit newdigit(time, channel, (time - Geo::BC_TIME_INPS * nbc) * Geo::NTDCBIN_PER_PS, tot * Geo::NTOTBIN_PER_NS, nbc); int tdc = int((time - Geo::BC_TIME_INPS * nbc) * Geo::NTDCBIN_PER_PS); @@ -368,7 +368,7 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, } } //______________________________________________________________________ -void Digitizer::fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID) +void Digitizer::fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID) { int lblCurrent; if (mcTruthContainer) { @@ -856,13 +856,12 @@ void Digitizer::flushOutputContainer(std::vector<Digit>& digits) //______________________________________________________________________ void Digitizer::checkIfReuseFutureDigits() { + uint64_t bclimit = 999999999999999999; + // check if digits stored very far in future match the new readout windows currently available int idigit = mFutureDigits.size() - 1; - int bclimit = 999999; // if bc is larger than this value stop the search in the next loop since bc are ordered in descending order - for (std::vector<Digit>::reverse_iterator digit = mFutureDigits.rbegin(); digit != mFutureDigits.rend(); ++digit) { - if (digit->getBC() > bclimit) break; From d39deb018a6f3d00c611ee7309211eefe99af8f6 Mon Sep 17 00:00:00 2001 From: Piotr Konopka <piotr.jan.konopka@cern.ch> Date: Mon, 5 Oct 2020 16:24:06 +0200 Subject: [PATCH 0860/1751] [QC-437] Do not throw if no DataSamplingPolicies are specified --- Utilities/DataSampling/CMakeLists.txt | 2 +- Utilities/DataSampling/src/DataSampling.cxx | 4 ++++ Utilities/DataSampling/test/test_DataSampling.cxx | 8 ++++++++ Utilities/DataSampling/test/test_DataSamplingEmpty.json | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Utilities/DataSampling/test/test_DataSamplingEmpty.json diff --git a/Utilities/DataSampling/CMakeLists.txt b/Utilities/DataSampling/CMakeLists.txt index d580da86be76f..588631fc47cb3 100644 --- a/Utilities/DataSampling/CMakeLists.txt +++ b/Utilities/DataSampling/CMakeLists.txt @@ -34,7 +34,7 @@ o2_add_library(DataSampling # tests with input data -o2_data_file(COPY test/test_DataSampling.json DESTINATION tests) +o2_data_file(COPY test/test_DataSampling.json test/test_DataSamplingEmpty.json DESTINATION tests) o2_add_test(DataSampling NAME test_DataSampling_test_DataSampling SOURCES test/test_DataSampling.cxx diff --git a/Utilities/DataSampling/src/DataSampling.cxx b/Utilities/DataSampling/src/DataSampling.cxx index 13ce66fc3d0ca..abf7ff6164852 100644 --- a/Utilities/DataSampling/src/DataSampling.cxx +++ b/Utilities/DataSampling/src/DataSampling.cxx @@ -38,6 +38,10 @@ std::string DataSampling::createDispatcherName() void DataSampling::GenerateInfrastructure(WorkflowSpec& workflow, const std::string& policiesSource, size_t threads) { std::unique_ptr<ConfigurationInterface> cfg = ConfigurationFactory::getConfiguration(policiesSource); + if (cfg->getRecursive("").count("dataSamplingPolicies") == 0) { + LOG(WARN) << "No \"dataSamplingPolicies\" structure found in the config file. If no Data Sampling is expected, then it is completely fine."; + return; + } auto policiesTree = cfg->getRecursive("dataSamplingPolicies"); Dispatcher dispatcher(createDispatcherName(), policiesSource); DataSampling::DoGenerateInfrastructure(dispatcher, workflow, policiesTree, threads); diff --git a/Utilities/DataSampling/test/test_DataSampling.cxx b/Utilities/DataSampling/test/test_DataSampling.cxx index 7d667768f6647..12b72aba0809c 100644 --- a/Utilities/DataSampling/test/test_DataSampling.cxx +++ b/Utilities/DataSampling/test/test_DataSampling.cxx @@ -216,3 +216,11 @@ BOOST_AUTO_TEST_CASE(InputSpecsForPolicy) BOOST_CHECK_EQUAL(inputs.size(), 2); } + +BOOST_AUTO_TEST_CASE(DataSamplingEmptyConfig) +{ + std::string configFilePath = "json:/" + std::string(getenv("O2_ROOT")) + "/share/tests/test_DataSamplingEmpty.json"; + + WorkflowSpec workflow; + BOOST_CHECK_NO_THROW(DataSampling::GenerateInfrastructure(workflow, configFilePath)); +} \ No newline at end of file diff --git a/Utilities/DataSampling/test/test_DataSamplingEmpty.json b/Utilities/DataSampling/test/test_DataSamplingEmpty.json new file mode 100644 index 0000000000000..7a73a41bfdf76 --- /dev/null +++ b/Utilities/DataSampling/test/test_DataSamplingEmpty.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file From 1ce6c2abb8c246754eb637ce8f57ac9af1eab05b Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Wed, 7 Oct 2020 16:06:02 +0200 Subject: [PATCH 0861/1751] moving pair cuts to separate file (#4524) --- Analysis/Core/include/Analysis/PairCuts.h | 315 ++++++++++++++++++++++ Analysis/Tasks/PWGCF/correlations.cxx | 280 ++----------------- 2 files changed, 334 insertions(+), 261 deletions(-) create mode 100644 Analysis/Core/include/Analysis/PairCuts.h diff --git a/Analysis/Core/include/Analysis/PairCuts.h b/Analysis/Core/include/Analysis/PairCuts.h new file mode 100644 index 0000000000000..975ee271df9b8 --- /dev/null +++ b/Analysis/Core/include/Analysis/PairCuts.h @@ -0,0 +1,315 @@ +// 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_PAIRCUTS_H +#define O2_ANALYSIS_PAIRCUTS_H + +#include <cmath> +#include <TH2F.h> +#include <TH3F.h> + +// Functions which cut on particle pairs (decays, conversions, two-track cuts) +// +// Author: Jan Fiete Grosse-Oetringhaus + +class PairCuts +{ + public: + enum Particle { Photon = 0, + K0, + Lambda, + Phi, + Rho, + ParticlesLastEntry }; + + void SetPairCut(Particle particle, float cut) + { + mCuts[particle] = cut; + if (mControlConvResoncances == nullptr) { + mControlConvResoncances = new TH2F("ControlConvResoncances", ";id;delta mass", 6, -0.5, 5.5, 500, -0.5, 0.5); + } + } + + void SetTwoTrackCuts(float distance = 0.02f, float radius = 0.8f) + { + mTwoTrackDistance = distance; + mTwoTrackRadius = radius; + + if (mTwoTrackDistancePt[0] == nullptr) { + mTwoTrackDistancePt[0] = new TH3F("TwoTrackDistancePt[0]", ";#Delta#eta;#Delta#varphi^{*}_{min};#Delta p_{T}", 100, -0.15, 0.15, 100, -0.05, 0.05, 20, 0, 10); + mTwoTrackDistancePt[1] = (TH3F*)mTwoTrackDistancePt[0]->Clone("TwoTrackDistancePt[1]"); + } + } + + template <typename T> + bool conversionCuts(T const& track1, T const& track2); + + template <typename T> + bool twoTrackCut(T const& track1, T const& track2, int bSign); + + protected: + float mCuts[ParticlesLastEntry] = {-1}; + float mTwoTrackDistance = -1; // distance below which the pair is flagged as to be removed + float mTwoTrackRadius = 0.8f; // radius at which the two track cuts are applied + + TH2F* mControlConvResoncances = nullptr; // control histograms for cuts on conversions and resonances + TH3F* mTwoTrackDistancePt[2] = {nullptr}; // control histograms for two-track efficiency study: dphi*_min vs deta (0 = before cut, 1 = after cut) + + template <typename T> + bool conversionCut(T const& track1, T const& track2, Particle conv, double cut); + + template <typename T> + double getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2); + + template <typename T> + double getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2); + + template <typename T> + float getDPhiStar(T const& track1, T const& track2, float radius, float bSign); +}; + +template <typename T> +bool PairCuts::conversionCuts(T const& track1, T const& track2) +{ + // skip if like sign + if (track1.charge() * track2.charge() > 0) { + return false; + } + + for (int i = 0; i < static_cast<int>(ParticlesLastEntry); i++) { + Particle particle = static_cast<Particle>(i); + if (mCuts[i] > 0) { + if (conversionCut(track1, track2, particle, mCuts[i])) { + return true; + } + if (particle == Lambda) { + if (conversionCut(track2, track1, particle, mCuts[i])) { + return true; + } + } + } + } + + return false; +} + +template <typename T> +bool PairCuts::twoTrackCut(T const& track1, T const& track2, int bSign) +{ + // the variables & cut have been developed in Run 1 by the CF - HBT group + // + // Parameters: + // bSign: sign of B field + + auto deta = track1.eta() - track2.eta(); + + // optimization + if (TMath::Abs(deta) < mTwoTrackDistance * 2.5 * 3) { + // check first boundaries to see if is worth to loop and find the minimum + float dphistar1 = getDPhiStar(track1, track2, mTwoTrackRadius, bSign); + float dphistar2 = getDPhiStar(track1, track2, 2.5, bSign); + + const float kLimit = mTwoTrackDistance * 3; + + if (TMath::Abs(dphistar1) < kLimit || TMath::Abs(dphistar2) < kLimit || dphistar1 * dphistar2 < 0) { + float dphistarminabs = 1e5; + float dphistarmin = 1e5; + for (Double_t rad = mTwoTrackRadius; rad < 2.51; rad += 0.01) { + float dphistar = getDPhiStar(track1, track2, rad, bSign); + + float dphistarabs = TMath::Abs(dphistar); + + if (dphistarabs < dphistarminabs) { + dphistarmin = dphistar; + dphistarminabs = dphistarabs; + } + } + + mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + + if (dphistarminabs < mTwoTrackDistance && TMath::Abs(deta) < mTwoTrackDistance) { + //LOGF(debug, "Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.charge(), track2.phi2(), track2.pt(), track2.charge(), bSign); + return true; + } + + mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + } + } + + return false; +} + +template <typename T> +bool PairCuts::conversionCut(T const& track1, T const& track2, Particle conv, double cut) +{ + //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); + + if (cut < 0) + return false; + + double massD1, massD2, massM; + + switch (conv) { + case Photon: + massD1 = 0.51e-3; + massD2 = 0.51e-3; + massM = 0; + break; + case K0: + massD1 = 0.1396; + massD2 = 0.1396; + massM = 0.4976; + break; + case Lambda: + massD1 = 0.9383; + massD2 = 0.1396; + massM = 1.115; + break; + case Phi: + massD1 = 0.4937; + massD2 = 0.4937; + massM = 1.019; + break; + case Rho: + massD1 = 0.1396; + massD2 = 0.1396; + massM = 0.770; + break; + default: + LOGF(fatal, "Particle now known"); + return false; + break; + } + + auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); + + if (TMath::Abs(massC - massM * massM) > cut * 5) + return false; + + massC = getInvMassSquared(track1, massD1, track2, massD2); + mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) + return true; + + return false; +} + +template <typename T> +double PairCuts::getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2) +{ + // calculate inv mass squared + // same can be achieved, but with more computing time with + /*TLorentzVector photon, p1, p2; + p1.SetPtEtaPhiM(triggerParticle->Pt(), triggerEta, triggerParticle->Phi(), 0.510e-3); + p2.SetPtEtaPhiM(particle->Pt(), eta[j], particle->Phi(), 0.510e-3); + photon = p1+p2; + photon.M()*/ + + float tantheta1 = 1e10; + + if (track1.eta() < -1e-10 || track1.eta() > 1e-10) { + float expTmp = TMath::Exp(-track1.eta()); + tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float tantheta2 = 1e10; + if (track2.eta() < -1e-10 || track2.eta() > 1e-10) { + float expTmp = TMath::Exp(-track2.eta()); + tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); + + float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (TMath::Cos(track1.phi() - track2.phi()) + 1.0 / tantheta1 / tantheta2))); + + // LOGF(debug, "%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2); + + return mass2; +} + +template <typename T> +double PairCuts::getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2) +{ + // calculate inv mass squared approximately + + const float eta1 = track1.eta(); + const float eta2 = track2.eta(); + const float phi1 = track1.phi(); + const float phi2 = track2.phi(); + const float pt1 = track1.pt(); + const float pt2 = track2.pt(); + + float tantheta1 = 1e10; + + if (eta1 < -1e-10 || eta1 > 1e-10) { + float expTmp = 1.0 - eta1 + eta1 * eta1 / 2 - eta1 * eta1 * eta1 / 6 + eta1 * eta1 * eta1 * eta1 / 24; + tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float tantheta2 = 1e10; + if (eta2 < -1e-10 || eta2 > 1e-10) { + float expTmp = 1.0 - eta2 + eta2 * eta2 / 2 - eta2 * eta2 * eta2 / 6 + eta2 * eta2 * eta2 * eta2 / 24; + tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + pt1 * pt1 * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + pt2 * pt2 * (1.0 + 1.0 / tantheta2 / tantheta2); + + // fold onto 0...pi + float deltaPhi = TMath::Abs(phi1 - phi2); + while (deltaPhi > TMath::TwoPi()) + deltaPhi -= TMath::TwoPi(); + if (deltaPhi > TMath::Pi()) + deltaPhi = TMath::TwoPi() - deltaPhi; + + float cosDeltaPhi = 0; + if (deltaPhi < TMath::Pi() / 3) + cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; + else if (deltaPhi < 2 * TMath::Pi() / 3) + cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); + else + cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); + + double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); + + //LOGF(debug, "%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2); + + return mass2; +} + +template <typename T> +float PairCuts::getDPhiStar(T const& track1, T const& track2, float radius, float bSign) +{ + // + // calculates dphistar + // + + auto phi1 = track1.phi(); + auto pt1 = track1.pt(); + auto charge1 = track1.charge(); + + auto phi2 = track2.phi(); + auto pt2 = track2.pt(); + auto charge2 = track2.charge(); + + float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); + + if (dphistar > M_PI) + dphistar = M_PI * 2 - dphistar; + if (dphistar < -M_PI) + dphistar = -M_PI * 2 - dphistar; + if (dphistar > M_PI) // might look funny but is needed + dphistar = M_PI * 2 - dphistar; + + return dphistar; +} + +#endif diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index de1566e3b419a..425a7d9a3fd9a 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -17,6 +17,7 @@ #include "Analysis/Centrality.h" #include "Analysis/StepTHn.h" #include "Analysis/CorrelationContainer.h" +#include "Analysis/PairCuts.h" #include <TH1F.h> #include <cmath> @@ -40,7 +41,7 @@ struct CorrelationTask { 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"); - O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value"); + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value (suggested: 0.02)"); O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); O2_DEFINE_CONFIGURABLE(cfgPairCutPhoton, float, -1, "Pair cut on photons: -1 = off; >0 otherwise distance value (suggested: 0.004)") @@ -59,22 +60,12 @@ struct CorrelationTask { OutputObj<CorrelationContainer> mixed{"mixedEvent"}; //OutputObj<TDirectory> qaOutput{"qa"}; - enum PairCuts { Photon = 0, - K0, - Lambda, - Phi, - Rho }; struct Config { bool mPairCuts = false; //THn* mEfficiencyTrigger = nullptr; //THn* mEfficiencyAssociated = nullptr; } cfg; - struct QA { - TH3F* mTwoTrackDistancePt[2] = {nullptr}; // control histograms for two-track efficiency study: dphi*_min vs deta (0 = before cut, 1 = after cut) - TH2F* mControlConvResoncances = nullptr; // control histograms for cuts on conversions and resonances - } qa; - // HistogramRegistry registry{"qa", true, { // {"yields", "centrality vs pT vs eta", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"} }}}, // {"etaphi", "centrality vs eta vs phi", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {100, -2, 2, "#eta"}, {200, 0, 2 * M_PI, "#varphi"} }}} @@ -83,6 +74,8 @@ struct CorrelationTask { OutputObj<TH3F> yields{TH3F("yields", "centrality vs pT vs eta", 100, 0, 100, 40, 0, 20, 100, -2, 2)}; OutputObj<TH3F> etaphi{TH3F("etaphi", "centrality vs eta vs phi", 100, 0, 100, 100, -2, 2, 200, 0, 2 * M_PI)}; + PairCuts mPairCuts; + void init(o2::framework::InitContext&) { // --- CONFIGURATION --- @@ -99,25 +92,23 @@ struct CorrelationTask { "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" "vertex_eff: 10 | -10, 10\n"; - if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) + if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) { + mPairCuts.SetPairCut(PairCuts::Photon, cfgPairCutPhoton); + mPairCuts.SetPairCut(PairCuts::K0, cfgPairCutK0); + mPairCuts.SetPairCut(PairCuts::Lambda, cfgPairCutLambda); + mPairCuts.SetPairCut(PairCuts::Phi, cfgPairCutPhi); + mPairCuts.SetPairCut(PairCuts::Rho, cfgPairCutRho); cfg.mPairCuts = true; + } + + if (cfgTwoTrackCut > 0) { + mPairCuts.SetTwoTrackCuts(cfgTwoTrackCut, cfgTwoTrackCutMinRadius); + } // --- OBJECT INIT --- same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentralityVtx", binning)); mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentralityVtx", binning)); //qaOutput.setObject(new TDirectory("qa", "qa")); - - if (cfgTwoTrackCut > 0) { - qa.mTwoTrackDistancePt[0] = new TH3F("TwoTrackDistancePt[0]", ";#Delta#eta;#Delta#varphi^{*}_{min};#Delta p_{T}", 100, -0.15, 0.15, 100, -0.05, 0.05, 20, 0, 10); - qa.mTwoTrackDistancePt[1] = (TH3F*)qa.mTwoTrackDistancePt[0]->Clone("TwoTrackDistancePt[1]"); - //qaOutput->Add(qa.mTwoTrackDistancePt[0]); - //qaOutput->Add(qa.mTwoTrackDistancePt[1]); - } - - if (cfg.mPairCuts) { - qa.mControlConvResoncances = new TH2F("ControlConvResoncances", ";id;delta mass", 6, -0.5, 5.5, 500, -0.5, 0.5); - //qaOutput->Add(qa.mControlConvResoncances); - } } // Version with explicit nested loop @@ -174,10 +165,10 @@ struct CorrelationTask { if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) continue; - if (cfg.mPairCuts && conversionCuts(track1, track2)) + if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) continue; - if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) + if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, bSign)) continue; double values[6] = {0}; @@ -234,10 +225,10 @@ struct CorrelationTask { if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) continue; - if (cfg.mPairCuts && conversionCuts(track1, track2)) + if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) continue; - if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) + if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, bSign)) continue; double values[6] = {0}; @@ -259,239 +250,6 @@ struct CorrelationTask { //mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); } } - - template <typename T> - bool conversionCuts(T const& track1, T const& track2) - { - // skip if like sign - if (track1.charge() * track2.charge() > 0) - return false; - - bool decision = false; - - if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) - decision = true; - if (conversionCut(track1, track2, K0, cfgPairCutK0)) - decision = true; - if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) - decision = true; - if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) - decision = true; - if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) - decision = true; - if (conversionCut(track1, track2, Rho, cfgPairCutRho)) - decision = true; - - return decision; - } - - template <typename T> - bool conversionCut(T const& track1, T const& track2, PairCuts conv, double cut) - { - //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); - - if (cut < 0) - return false; - - double massD1, massD2, massM; - - switch (conv) { - case Photon: - massD1 = 0.51e-3; - massD2 = 0.51e-3; - massM = 0; - break; - case K0: - massD1 = 0.1396; - massD2 = 0.1396; - massM = 0.4976; - break; - case Lambda: - massD1 = 0.9383; - massD2 = 0.1396; - massM = 1.115; - break; - case Phi: - massD1 = 0.4937; - massD2 = 0.4937; - massM = 1.019; - break; - case Rho: - massD1 = 0.1396; - massD2 = 0.1396; - massM = 0.770; - break; - } - - auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); - - if (TMath::Abs(massC - massM * massM) > cut * 5) - return false; - - massC = getInvMassSquared(track1, massD1, track2, massD2); - qa.mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); - if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) - return true; - - return false; - } - - template <typename T> - double getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2) - { - // calculate inv mass squared - // same can be achieved, but with more computing time with - /*TLorentzVector photon, p1, p2; - p1.SetPtEtaPhiM(triggerParticle->Pt(), triggerEta, triggerParticle->Phi(), 0.510e-3); - p2.SetPtEtaPhiM(particle->Pt(), eta[j], particle->Phi(), 0.510e-3); - photon = p1+p2; - photon.M()*/ - - float tantheta1 = 1e10; - - if (track1.eta() < -1e-10 || track1.eta() > 1e-10) { - float expTmp = TMath::Exp(-track1.eta()); - tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float tantheta2 = 1e10; - if (track2.eta() < -1e-10 || track2.eta() > 1e-10) { - float expTmp = TMath::Exp(-track2.eta()); - tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); - float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); - - float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (TMath::Cos(track1.phi() - track2.phi()) + 1.0 / tantheta1 / tantheta2))); - - // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); - - return mass2; - } - - template <typename T> - double getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2) - { - // calculate inv mass squared approximately - - const float eta1 = track1.eta(); - const float eta2 = track2.eta(); - const float phi1 = track1.phi(); - const float phi2 = track2.phi(); - const float pt1 = track1.pt(); - const float pt2 = track2.pt(); - - float tantheta1 = 1e10; - - if (eta1 < -1e-10 || eta1 > 1e-10) { - float expTmp = 1.0 - eta1 + eta1 * eta1 / 2 - eta1 * eta1 * eta1 / 6 + eta1 * eta1 * eta1 * eta1 / 24; - tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float tantheta2 = 1e10; - if (eta2 < -1e-10 || eta2 > 1e-10) { - float expTmp = 1.0 - eta2 + eta2 * eta2 / 2 - eta2 * eta2 * eta2 / 6 + eta2 * eta2 * eta2 * eta2 / 24; - tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); - } - - float e1squ = m0_1 * m0_1 + pt1 * pt1 * (1.0 + 1.0 / tantheta1 / tantheta1); - float e2squ = m0_2 * m0_2 + pt2 * pt2 * (1.0 + 1.0 / tantheta2 / tantheta2); - - // fold onto 0...pi - float deltaPhi = TMath::Abs(phi1 - phi2); - while (deltaPhi > TMath::TwoPi()) - deltaPhi -= TMath::TwoPi(); - if (deltaPhi > TMath::Pi()) - deltaPhi = TMath::TwoPi() - deltaPhi; - - float cosDeltaPhi = 0; - if (deltaPhi < TMath::Pi() / 3) - cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; - else if (deltaPhi < 2 * TMath::Pi() / 3) - cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); - else - cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); - - double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); - - // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); - - return mass2; - } - - template <typename T> - bool twoTrackCut(T const& track1, T const& track2, int bSign) - { - // the variables & cuthave been developed by the HBT group - // see e.g. https://indico.cern.ch/materialDisplay.py?contribId=36&sessionId=6&materialId=slides&confId=142700 - - auto deta = track1.eta() - track2.eta(); - - // optimization - if (TMath::Abs(deta) < cfgTwoTrackCut * 2.5 * 3) { - // check first boundaries to see if is worth to loop and find the minimum - float dphistar1 = getDPhiStar(track1, track2, cfgTwoTrackCutMinRadius, bSign); - float dphistar2 = getDPhiStar(track1, track2, 2.5, bSign); - - const float kLimit = cfgTwoTrackCut * 3; - - if (TMath::Abs(dphistar1) < kLimit || TMath::Abs(dphistar2) < kLimit || dphistar1 * dphistar2 < 0) { - float dphistarminabs = 1e5; - float dphistarmin = 1e5; - for (Double_t rad = cfgTwoTrackCutMinRadius; rad < 2.51; rad += 0.01) { - float dphistar = getDPhiStar(track1, track2, rad, bSign); - - float dphistarabs = TMath::Abs(dphistar); - - if (dphistarabs < dphistarminabs) { - dphistarmin = dphistar; - dphistarminabs = dphistarabs; - } - } - - qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); - - if (dphistarminabs < cfgTwoTrackCut && TMath::Abs(deta) < cfgTwoTrackCut) { - //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.charge(), track2.phi2(), track2.pt(), track2.charge(), bSign); - return true; - } - - qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); - } - } - - return false; - } - - template <typename T> - float getDPhiStar(T const& track1, T const& track2, float radius, float bSign) - { - // - // calculates dphistar - // - - auto phi1 = track1.phi(); - auto pt1 = track1.pt(); - auto charge1 = track1.charge(); - - auto phi2 = track2.phi(); - auto pt2 = track2.pt(); - auto charge2 = track2.charge(); - - float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); - - static const Double_t kPi = TMath::Pi(); - - if (dphistar > kPi) - dphistar = kPi * 2 - dphistar; - if (dphistar < -kPi) - dphistar = -kPi * 2 - dphistar; - if (dphistar > kPi) // might look funny but is needed - dphistar = kPi * 2 - dphistar; - - return dphistar; - } }; WorkflowSpec defineDataProcessing(ConfigContext const&) From 3826aacba907e29a38d5889b7fe359db19a13e5e Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Thu, 1 Oct 2020 11:40:47 +0200 Subject: [PATCH 0862/1751] [Align] TrackPar and TrackParCov as template Converts TrackPar and TrackParCov classes into template classes to allow for a single and double precision floating point version. No changes in program semantics. --- .../ITS/include/DataFormatsITS/TrackITS.h | 2 +- .../TPC/include/DataFormatsTPC/LaserTrack.h | 2 +- DataFormats/Reconstruction/CMakeLists.txt | 3 +- .../include/ReconstructionDataFormats/Track.h | 488 +---- .../TrackLTIntegral.h | 2 - .../TrackParametrization.h | 664 ++++++ .../TrackParametrizationWithError.h | 293 +++ .../ReconstructionDataFormats/TrackUtils.h | 143 ++ .../src/ReconstructionDataFormatsLinkDef.h | 4 + DataFormats/Reconstruction/src/Track.cxx | 1830 ----------------- .../src/TrackParametrization.cxx | 742 +++++++ .../src/TrackParametrizationWithError.cxx | 1096 ++++++++++ Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 2 +- 13 files changed, 2952 insertions(+), 2319 deletions(-) create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h delete mode 100644 DataFormats/Reconstruction/src/Track.cxx create mode 100644 DataFormats/Reconstruction/src/TrackParametrization.cxx create mode 100644 DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index a9a1769a6cba1..a178a662b8796 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -41,7 +41,7 @@ class TrackITS : public o2::track::TrackParCov TrackITS() = default; TrackITS(const TrackITS& t) = default; - TrackITS(const o2::track::TrackParCov& parcov) : TrackParCov{parcov} {} + TrackITS(const o2::track::TrackParCov& parcov) : o2::track::TrackParCov{parcov} {} TrackITS(const o2::track::TrackParCov& parCov, float chi2, const o2::track::TrackParCov& outer) : o2::track::TrackParCov{parCov}, mParamOut{outer}, mChi2{chi2} {} TrackITS& operator=(const TrackITS& tr) = default; diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/LaserTrack.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/LaserTrack.h index 7f9bbf388dc5a..6397086e10e48 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/LaserTrack.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/LaserTrack.h @@ -32,7 +32,7 @@ class LaserTrack : public o2::track::TrackPar static constexpr int TracksPerBundle = 7; ///< number of micro-mirrors per bundle LaserTrack() = default; - LaserTrack(int id, float x, float alpha, const std::array<float, o2::track::kNParams>& par) : mID(id), TrackPar(x, alpha, par) { ; } + LaserTrack(int id, float x, float alpha, const std::array<float, o2::track::kNParams>& par) : mID(id), o2::track::TrackPar(x, alpha, par) { ; } LaserTrack(LaserTrack const&) = default; /// set laser track ID diff --git a/DataFormats/Reconstruction/CMakeLists.txt b/DataFormats/Reconstruction/CMakeLists.txt index f09bf663ae41b..bef53810a63a2 100644 --- a/DataFormats/Reconstruction/CMakeLists.txt +++ b/DataFormats/Reconstruction/CMakeLists.txt @@ -9,7 +9,8 @@ # submit itself to any jurisdiction. o2_add_library(ReconstructionDataFormats - SOURCES src/Track.cxx + SOURCES src/TrackParametrization.cxx + src/TrackParametrizationWithError.cxx src/TrackFwd.cxx src/BaseCluster.cxx src/TrackTPCITS.cxx diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h index 305aab0e4fda3..2a4a57753a580 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h @@ -10,499 +10,21 @@ /// \file Track.h /// \brief Base track model for the Barrel, params only, w/o covariance -/// \author ruben.shahoyan@cern.ch - -/* - 24/09/2020: Added new data member for abs. charge. This is needed for uniform treatment of tracks with non-standard - charge: 0 (for V0s) and e.g. 2 for hypernuclei. - In the aliroot AliExternalTrackParam this was treated by derived classes using virtual methods, which we don't use in O2. - The meaning of mP[kQ2Pt] remains exactly the same, except for q=0 case: in this case the mP[kQ2Pt] is just an alias to - 1/pT, regardless of its sign, and the getCurvature() will 0 (because mAbsCharge is 0). - The methods returning lab momentum or its combination account for eventual q>1. - */ +/// \author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch #ifndef ALICEO2_BASE_TRACK #define ALICEO2_BASE_TRACK -#include "GPUCommonRtypes.h" - -#ifndef __OPENCL__ -#include <algorithm> -#include <array> -#include <cfloat> -#include <cmath> -#include <cstring> -#include <iosfwd> -#endif - -#ifndef GPUCA_ALIGPUCODE //Used only by functions that are hidden on the GPU -#include "ReconstructionDataFormats/BaseCluster.h" -#include <string> -#endif - -#include "CommonConstants/MathConstants.h" -#include "MathUtils/Utils.h" -#include "MathUtils/Primitive2D.h" -#include "ReconstructionDataFormats/PID.h" - -//Forward declarations, since we cannot include the headers if we eventually want to use track.h on GPU -namespace ROOT -{ -namespace Math -{ -template <class T, unsigned int D1, unsigned int D2, class R> -class SMatrix; -template <class T, unsigned int D> -class MatRepSym; -template <class T, unsigned int D1, unsigned int D2> -class MatRepStd; -template <class CoordSystem, class Tag> -class PositionVector3D; -template <class T> -class Cartesian3D; -class DefaultCoordinateSystemTag; -} // namespace Math -} // namespace ROOT -template <typename T> -using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +#include "ReconstructionDataFormats/TrackParametrization.h" +#include "ReconstructionDataFormats/TrackParametrizationWithError.h" namespace o2 { -template <typename T> -class BaseCluster; - -namespace dataformats -{ -class VertexBase; -class DCA; -} // namespace dataformats - namespace track { -// aliases for track elements -enum ParLabels : int { kY, - kZ, - kSnp, - kTgl, - kQ2Pt }; -enum CovLabels : int { - kSigY2, - kSigZY, - kSigZ2, - kSigSnpY, - kSigSnpZ, - kSigSnp2, - kSigTglY, - kSigTglZ, - kSigTglSnp, - kSigTgl2, - kSigQ2PtY, - kSigQ2PtZ, - kSigQ2PtSnp, - kSigQ2PtTgl, - kSigQ2Pt2 -}; - -enum DirType : int { DirInward = -1, - DirAuto = 0, - DirOutward = 1 }; - -constexpr int kNParams = 5, kCovMatSize = 15, kLabCovMatSize = 21; - -constexpr float kCY2max = 100 * 100, // SigmaY<=100cm - kCZ2max = 100 * 100, // SigmaZ<=100cm - kCSnp2max = 1 * 1, // SigmaSin<=1 - kCTgl2max = 1 * 1, // SigmaTan<=1 - kC1Pt2max = 100 * 100, // Sigma1/Pt<=100 1/GeV - kMostProbablePt = 0.6, // Most Probable Pt (GeV), for running with Bz=0 - kCalcdEdxAuto = -999.f; // value indicating request for dedx calculation - -// access to covariance matrix by row and column -constexpr int CovarMap[kNParams][kNParams] = {{0, 1, 3, 6, 10}, - {1, 2, 4, 7, 11}, - {3, 4, 5, 8, 12}, - {6, 7, 8, 9, 13}, - {10, 11, 12, 13, 14}}; - -// access to covariance matrix diagonal elements -constexpr int DiagMap[kNParams] = {0, 2, 5, 9, 14}; - -constexpr float HugeF = o2::constants::math::VeryBig; - -// helper function -float BetheBlochSolid(float bg, float rho = 2.33f, float kp1 = 0.20f, float kp2 = 3.00f, float meanI = 173e-9f, - float meanZA = 0.49848f); -void g3helx3(float qfield, float step, std::array<float, 7>& vect); - -class TrackPar -{ // track parameterization, kinematics only. - public: - TrackPar() = default; - TrackPar(float x, float alpha, const std::array<float, kNParams>& par, int charge = 1); - TrackPar(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, int charge, bool sectorAlpha = true); - TrackPar(const TrackPar&) = default; - TrackPar& operator=(const TrackPar& src) = default; - ~TrackPar() = default; - - const float* getParams() const { return mP; } - float getParam(int i) const { return mP[i]; } - float getX() const { return mX; } - float getAlpha() const { return mAlpha; } - float getY() const { return mP[kY]; } - float getZ() const { return mP[kZ]; } - float getSnp() const { return mP[kSnp]; } - float getTgl() const { return mP[kTgl]; } - float getQ2Pt() const { return mP[kQ2Pt]; } - float getCharge2Pt() const { return mAbsCharge ? mP[kQ2Pt] : 0.; } - int getAbsCharge() const { return mAbsCharge; } - PID getPID() const { return mPID; } - void setPID(const PID pid) - { - mPID = pid; - setAbsCharge(pid.getCharge()); - } - uint16_t getUserField() const { return mUserField; } - void setUserField(uint16_t v) { mUserField = v; } - - /// calculate cos^2 and cos of track direction in rphi-tracking - float getCsp2() const - { - float csp2 = (1. - mP[kSnp]) * (1. + mP[kSnp]); - return csp2 > o2::constants::math::Almost0 ? csp2 : o2::constants::math::Almost0; - } - float getCsp() const { return sqrtf(getCsp2()); } - - void setX(float v) { mX = v; } - void setParam(float v, int i) { mP[i] = v; } - void setAlpha(float v) { mAlpha = v; } - void setY(float v) { mP[kY] = v; } - void setZ(float v) { mP[kZ] = v; } - void setSnp(float v) { mP[kSnp] = v; } - void setTgl(float v) { mP[kTgl] = v; } - void setQ2Pt(float v) { mP[kQ2Pt] = v; } - void setAbsCharge(int q) { mAbsCharge = std::abs(q); } - - // derived getters - bool getXatLabR(float r, float& x, float bz, DirType dir = DirAuto) const; - void getCircleParamsLoc(float bz, o2::utils::CircleXY& circle) const; - void getCircleParams(float bz, o2::utils::CircleXY& circle, float& sna, float& csa) const; - void getLineParams(o2::utils::IntervalXY& line, float& sna, float& csa) const; - float getCurvature(float b) const { return mAbsCharge ? mP[kQ2Pt] * b * o2::constants::math::B2C : 0.; } - int getCharge() const { return getSign() > 0 ? mAbsCharge : -mAbsCharge; } - int getSign() const { return mAbsCharge ? (mP[kQ2Pt] > 0.f ? 1 : -1) : 0; } - float getPhi() const; - float getPhiPos() const; - - float getPtInv() const; - float getP2Inv() const; - float getP2() const; - float getPInv() const; - float getP() const; - float getPt() const; - - float getTheta() const { return constants::math::PIHalf - std::atan(mP[3]); } - float getEta() const { return -std::log(std::tan(0.5 * getTheta())); } - Point3D<float> getXYZGlo() const; - void getXYZGlo(std::array<float, 3>& xyz) const; - bool getPxPyPzGlo(std::array<float, 3>& pxyz) const; - bool getPosDirGlo(std::array<float, 9>& posdirp) const; - - // methods for track params estimate at other point - bool getYZAt(float xk, float b, float& y, float& z) const; - float getZAt(float xk, float b) const; - float getYAt(float xk, float b) const; - Point3D<float> getXYZGloAt(float xk, float b, bool& ok) const; - - // parameters manipulation - bool correctForELoss(float xrho, float mass, bool anglecorr = false, float dedx = kCalcdEdxAuto); - bool rotateParam(float alpha); - bool propagateParamTo(float xk, float b); - bool propagateParamTo(float xk, const std::array<float, 3>& b); - - bool propagateParamToDCA(const Point3D<float>& vtx, float b, std::array<float, 2>* dca = nullptr, float maxD = 999.f); - - void invertParam(); - - bool isValid() const { return mX != InvalidX; } - void invalidate() { mX = InvalidX; } - -#ifndef GPUCA_ALIGPUCODE - void printParam() const; - std::string asString() const; -#endif - - protected: - void updateParam(float delta, int i) { mP[i] += delta; } - void updateParams(const float delta[kNParams]) - { - for (int i = kNParams; i--;) { - mP[i] += delta[i]; - } - } - // derived getters - - 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 - char mAbsCharge = 1; /// Extra info about the abs charge, to be taken into account only if not 1 - PID mPID{}; /// 8 bit PID - uint16_t mUserField = 0; /// field provided to user - ClassDefNV(TrackPar, 3); -}; - -class TrackParCov : public TrackPar -{ // track+error parameterization - using MatrixDSym5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepSym<double, kNParams>>; - using MatrixD5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepStd<double, kNParams, kNParams>>; - - public: - TrackParCov() : TrackPar{} {} - TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, const std::array<float, kCovMatSize>& cov, int charge = 1); - TrackParCov(const std::array<float, 3>& xyz, const std::array<float, 3>& pxpypz, - const std::array<float, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); - TrackParCov(const TrackParCov& src) = default; - TrackParCov& operator=(const TrackParCov& src) = default; - ~TrackParCov() = default; - - const float* getCov() const { return mC; } - float getSigmaY2() const { return mC[kSigY2]; } - float getSigmaZY() const { return mC[kSigZY]; } - float getSigmaZ2() const { return mC[kSigZ2]; } - float getSigmaSnpY() const { return mC[kSigSnpY]; } - float getSigmaSnpZ() const { return mC[kSigSnpZ]; } - float getSigmaSnp2() const { return mC[kSigSnp2]; } - float getSigmaTglY() const { return mC[kSigTglY]; } - float getSigmaTglZ() const { return mC[kSigTglZ]; } - float getSigmaTglSnp() const { return mC[kSigTglSnp]; } - float getSigmaTgl2() const { return mC[kSigTgl2]; } - float getSigma1PtY() const { return mC[kSigQ2PtY]; } - float getSigma1PtZ() const { return mC[kSigQ2PtZ]; } - float getSigma1PtSnp() const { return mC[kSigQ2PtSnp]; } - float getSigma1PtTgl() const { return mC[kSigQ2PtTgl]; } - float getSigma1Pt2() const { return mC[kSigQ2Pt2]; } - float getCovarElem(int i, int j) const { return mC[CovarMap[i][j]]; } - float getDiagError2(int i) const { return mC[DiagMap[i]]; } - - bool getCovXYZPxPyPzGlo(std::array<float, 21>& c) const; - -#ifndef GPUCA_ALIGPUCODE - void print() const; - std::string asString() const; -#endif - - // parameters + covmat manipulation - bool rotate(float alpha); - bool propagateTo(float xk, float b); - bool propagateTo(float xk, const std::array<float, 3>& b); - bool propagateToDCA(const o2::dataformats::VertexBase& vtx, float b, o2::dataformats::DCA* dca = nullptr, float maxD = 999.f); - void invert(); - - float getPredictedChi2(const std::array<float, 2>& p, const std::array<float, 3>& cov) const; - - template <typename T> - float getPredictedChi2(const BaseCluster<T>& p) const - { - const std::array<float, 2> pyz = {p.getY(), p.getZ()}; - const std::array<float, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; - return getPredictedChi2(pyz, cov); - } - float getPredictedChi2(const TrackParCov& rhs) const; - - void buildCombinedCovMatrix(const TrackParCov& rhs, MatrixDSym5& cov) const; - float getPredictedChi2(const TrackParCov& rhs, MatrixDSym5& covToSet) const; - bool update(const TrackParCov& rhs, const MatrixDSym5& covInv); - - bool update(const std::array<float, 2>& p, const std::array<float, 3>& cov); - - template <typename T> - bool update(const BaseCluster<T>& p) - { - const std::array<float, 2> pyz = {p.getY(), p.getZ()}; - const std::array<float, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; - return update(pyz, cov); - } - - bool update(const TrackParCov& rhs); - - bool correctForMaterial(float x2x0, float xrho, float mass, bool anglecorr = false, float dedx = kCalcdEdxAuto); - - void resetCovariance(float s2 = 0); - void checkCovariance(); - void setCov(float v, int i) { mC[i] = v; } - - protected: - void updateCov(const float delta[kCovMatSize]) - { - for (int i = kCovMatSize; i--;) - mC[i] += delta[i]; - } - - protected: - float mC[kCovMatSize] = {0.f}; // 15 covariance matrix elements - - ClassDefNV(TrackParCov, 2); -}; - -//____________________________________________________________ -inline TrackPar::TrackPar(float x, float alpha, const std::array<float, kNParams>& par, int charge) - : mX{x}, mAlpha{alpha}, mAbsCharge{char(std::abs(charge))} -{ - // explicit constructor - std::copy(par.begin(), par.end(), mP); -} - -//_______________________________________________________ -inline void TrackPar::getLineParams(o2::utils::IntervalXY& ln, float& sna, float& csa) const -{ - // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } - o2::utils::sincos(getAlpha(), sna, csa); - o2::utils::rotateZ(getX(), getY(), ln.xP, ln.yP, sna, csa); // reference point in global frame - float snp = getSnp(), csp = sqrtf((1.f - snp) * (1.f + snp)); - ln.dxP = csp * csa - snp * sna; - ln.dyP = snp * csa + csp * sna; -} - -//_______________________________________________________ -inline void TrackPar::getCircleParams(float bz, o2::utils::CircleXY& c, float& sna, float& csa) const -{ - // get circle params in loc and lab frame, for straight line just set to global coordinates - getCircleParamsLoc(bz, c); - o2::utils::sincos(getAlpha(), sna, csa); - o2::utils::rotateZ(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame -} - -//_______________________________________________________ -inline void TrackPar::getCircleParamsLoc(float bz, o2::utils::CircleXY& c) const -{ - // get circle params in track local frame, for straight line just set to local coordinates - c.rC = getCurvature(bz); - // treat as straight track if sagitta between the vertex and middle of TPC is below 0.01 cm - constexpr float MinSagitta = 0.01, TPCMidR = 160., MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR); - if (std::abs(c.rC) > MinCurv) { - c.rC = 1.f / getCurvature(bz); - float sn = getSnp(), cs = sqrtf((1. - sn) * (1. + sn)); - c.xC = getX() - sn * c.rC; // center in tracking - c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!! - c.rC = fabs(c.rC); - } else { - c.rC = 0.f; // signal straight line - c.xC = getX(); - c.yC = getY(); - } -} - -//_______________________________________________________ -inline void TrackPar::getXYZGlo(std::array<float, 3>& xyz) const -{ - // track coordinates in lab frame - xyz[0] = getX(); - xyz[1] = getY(); - xyz[2] = getZ(); - utils::RotateZ(xyz, getAlpha()); -} - -//_______________________________________________________ -inline float TrackPar::getPhi() const -{ - // track pt direction phi (in 0:2pi range) - float phi = asinf(getSnp()) + getAlpha(); - utils::BringTo02Pi(phi); - return phi; -} - -#ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden -//_______________________________________________________ -inline Point3D<float> TrackPar::getXYZGlo() const -{ - return Rotation2D(getAlpha())(Point3D<float>(getX(), getY(), getZ())); -} - -//_______________________________________________________ -inline Point3D<float> TrackPar::getXYZGloAt(float xk, float b, bool& ok) const -{ - //---------------------------------------------------------------- - // estimate global X,Y,Z in global frame at given X - //---------------------------------------------------------------- - float y = 0.f, z = 0.f; - ok = getYZAt(xk, b, y, z); - return ok ? Rotation2D(getAlpha())(Point3D<float>(xk, y, z)) : Point3D<float>(); -} -#endif - -//_______________________________________________________ -inline float TrackPar::getPhiPos() const -{ - // angle of track position (in -pi:pi range) - float phi = atan2f(getY(), getX()) + getAlpha(); - utils::BringTo02Pi(phi); - return phi; -} - -//____________________________________________________________ -inline float TrackPar::getP2Inv() const -{ - // return the inverted track momentum^2 - auto p2 = mP[kQ2Pt] * mP[kQ2Pt] / (1.f + getTgl() * getTgl()); - return (mAbsCharge > 1) ? p2 * mAbsCharge * mAbsCharge : p2; -} - -//____________________________________________________________ -inline float TrackPar::getPtInv() const -{ - // return the inverted track pT - auto ptInv = fabs(mP[kQ2Pt]); - return (mAbsCharge > 1) ? ptInv / mAbsCharge : ptInv; -} - -//____________________________________________________________ -inline float TrackPar::getPInv() const -{ - // return the inverted track momentum^2 - auto pInv = fabs(mP[kQ2Pt]) / sqrtf(1.f + getTgl() * getTgl()); - return (mAbsCharge > 1) ? pInv / mAbsCharge : pInv; -} - -//____________________________________________________________ -inline float TrackPar::getP2() const -{ - // return the track momentum^2 - auto p2inv = getP2Inv(); - return (p2inv > o2::constants::math::Almost0) ? 1. / p2inv : o2::constants::math::VeryBig; -} - -//____________________________________________________________ -inline float TrackPar::getP() const -{ - // return the track momentum - float pInv = getPInv(); - return (pInv > o2::constants::math::Almost0) ? 1. / pInv : o2::constants::math::VeryBig; -} - -//____________________________________________________________ -inline float TrackPar::getPt() const -{ - // return the track transverse momentum - float ptI = fabs(mP[kQ2Pt]); - if (mAbsCharge > 1) { - ptI /= mAbsCharge; - } - return (ptI > o2::constants::math::Almost0) ? 1.f / ptI : o2::constants::math::VeryBig; -} - -//============================================================ - -//____________________________________________________________ -inline TrackParCov::TrackParCov(float x, float alpha, const std::array<float, kNParams>& par, - const std::array<float, kCovMatSize>& cov, int charge) - : TrackPar{x, alpha, par, charge} -{ - // explicit constructor - std::copy(cov.begin(), cov.end(), mC); -} +using TrackPar = TrackParametrization<float>; +using TrackParCov = TrackParametrizationWithError<float>; } // namespace track } // namespace o2 diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h index 4122c38be2c19..75efa94113ed1 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h @@ -24,8 +24,6 @@ namespace o2 namespace track { -class TrackPar; - class TrackLTIntegral { public: diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h new file mode 100644 index 0000000000000..cd9c8d675c9de --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -0,0 +1,664 @@ +// 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 TrackParametrization.h +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since Oct 1, 2020 +/// @brief + +/* + 24/09/2020: Added new data member for abs. charge. This is needed for uniform treatment of tracks with non-standard + charge: 0 (for V0s) and e.g. 2 for hypernuclei. + In the aliroot AliExternalTrackParam this was treated by derived classes using virtual methods, which we don't use in O2. + The meaning of mP[kQ2Pt] remains exactly the same, except for q=0 case: in this case the mP[kQ2Pt] is just an alias to + 1/pT, regardless of its sign, and the getCurvature() will 0 (because mAbsCharge is 0). + The methods returning lab momentum or its combination account for eventual q>1. + */ + +#ifndef INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATION_H_ +#define INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATION_H_ + +#include "GPUCommonRtypes.h" + +#ifndef __OPENCL__ +#include <algorithm> +#include <array> +#include <cfloat> +#include <cmath> +#include <cstring> +#include <iosfwd> +#endif + +#ifndef GPUCA_ALIGPUCODE //Used only by functions that are hidden on the GPU +#include "ReconstructionDataFormats/BaseCluster.h" +#include <string> +#endif + +#include "CommonConstants/MathConstants.h" +#include "MathUtils/Utils.h" +#include "MathUtils/Primitive2D.h" +#include "ReconstructionDataFormats/PID.h" + +#include "ReconstructionDataFormats/TrackUtils.h" + +//Forward declarations, since we cannot include the headers if we eventually want to use track.h on GPU +namespace ROOT +{ +namespace Math +{ +template <class T, unsigned int D1, unsigned int D2, class R> +class SMatrix; +template <class T, unsigned int D> +class MatRepSym; +template <class T, unsigned int D1, unsigned int D2> +class MatRepStd; +template <class CoordSystem, class Tag> +class PositionVector3D; +template <class T> +class Cartesian3D; +class DefaultCoordinateSystemTag; +} // namespace Math +} // namespace ROOT +template <typename T> +using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; + +namespace o2 +{ +template <typename T> +class BaseCluster; + +namespace dataformats +{ +class VertexBase; +class DCA; +} // namespace dataformats + +namespace track +{ +// aliases for track elements +enum ParLabels : int { kY, + kZ, + kSnp, + kTgl, + kQ2Pt }; +enum CovLabels : int { + kSigY2, + kSigZY, + kSigZ2, + kSigSnpY, + kSigSnpZ, + kSigSnp2, + kSigTglY, + kSigTglZ, + kSigTglSnp, + kSigTgl2, + kSigQ2PtY, + kSigQ2PtZ, + kSigQ2PtSnp, + kSigQ2PtTgl, + kSigQ2Pt2 +}; + +enum DirType : int { DirInward = -1, + DirAuto = 0, + DirOutward = 1 }; + +constexpr int kNParams = 5, kCovMatSize = 15, kLabCovMatSize = 21; + +constexpr float kCY2max = 100 * 100, // SigmaY<=100cm + kCZ2max = 100 * 100, // SigmaZ<=100cm + kCSnp2max = 1 * 1, // SigmaSin<=1 + kCTgl2max = 1 * 1, // SigmaTan<=1 + kC1Pt2max = 100 * 100, // Sigma1/Pt<=100 1/GeV + kMostProbablePt = 0.6, // Most Probable Pt (GeV), for running with Bz=0 + kCalcdEdxAuto = -999.f; // value indicating request for dedx calculation + +// access to covariance matrix by row and column +constexpr int CovarMap[kNParams][kNParams] = {{0, 1, 3, 6, 10}, + {1, 2, 4, 7, 11}, + {3, 4, 5, 8, 12}, + {6, 7, 8, 9, 13}, + {10, 11, 12, 13, 14}}; + +// access to covariance matrix diagonal elements +constexpr int DiagMap[kNParams] = {0, 2, 5, 9, 14}; + +constexpr float HugeF = o2::constants::math::VeryBig; + +template <typename value_T = float> +class TrackParametrization +{ // track parameterization, kinematics only. + + public: + using value_t = value_T; + using dim3v_t = std::array<value_t, 3>; + + static_assert(std::is_floating_point_v<value_t>); + + TrackParametrization() = default; + TrackParametrization(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, int charge = 1); + TrackParametrization(const std::array<value_t, 3>& xyz, const std::array<value_t, 3>& pxpypz, int charge, bool sectorAlpha = true); + TrackParametrization(const TrackParametrization&) = default; + TrackParametrization(TrackParametrization&&) = default; + TrackParametrization& operator=(const TrackParametrization& src) = default; + TrackParametrization& operator=(TrackParametrization&& src) = default; + ~TrackParametrization() = default; + + const value_t* getParams() const; + value_t getParam(int i) const; + value_t getX() const; + value_t getAlpha() const; + value_t getY() const; + value_t getZ() const; + value_t getSnp() const; + value_t getTgl() const; + value_t getQ2Pt() const; + value_t getCharge2Pt() const; + int getAbsCharge() const; + PID getPID() const; + void setPID(const PID pid); + + /// calculate cos^2 and cos of track direction in rphi-tracking + value_t getCsp2() const; + value_t getCsp() const; + + void setX(value_t v); + void setParam(value_t v, int i); + void setAlpha(value_t v); + void setY(value_t v); + void setZ(value_t v); + void setSnp(value_t v); + void setTgl(value_t v); + void setQ2Pt(value_t v); + void setAbsCharge(int q); + + // derived getters + bool getXatLabR(value_t r, value_t& x, value_t bz, DirType dir = DirAuto) const; + void getCircleParamsLoc(value_t bz, o2::utils::CircleXY& circle) const; + void getCircleParams(value_t bz, o2::utils::CircleXY& circle, value_t& sna, value_t& csa) const; + void getLineParams(o2::utils::IntervalXY& line, value_t& sna, value_t& csa) const; + value_t getCurvature(value_t b) const; + int getCharge() const; + int getSign() const; + value_t getPhi() const; + value_t getPhiPos() const; + + value_t getPtInv() const; + value_t getP2Inv() const; + value_t getP2() const; + value_t getPInv() const; + value_t getP() const; + value_t getPt() const; + + value_t getTheta() const; + value_t getEta() const; + Point3D<value_t> getXYZGlo() const; + void getXYZGlo(std::array<value_t, 3>& xyz) const; + bool getPxPyPzGlo(std::array<value_t, 3>& pxyz) const; + bool getPosDirGlo(std::array<value_t, 9>& posdirp) const; + + // methods for track params estimate at other point + bool getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const; + value_t getZAt(value_t xk, value_t b) const; + value_t getYAt(value_t xk, value_t b) const; + Point3D<value_t> getXYZGloAt(value_t xk, value_t b, bool& ok) const; + + // parameters manipulation + bool correctForELoss(value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); + bool rotateParam(value_t alpha); + bool propagateParamTo(value_t xk, value_t b); + bool propagateParamTo(value_t xk, const std::array<value_t, 3>& b); + + bool propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, std::array<value_t, 2>* dca = nullptr, value_t maxD = 999.f); + + void invertParam(); + + bool isValid() const; + void invalidate(); + + uint16_t getUserField() const; + void setUserField(uint16_t v); + +#ifndef GPUCA_ALIGPUCODE + void printParam() const; + std::string asString() const; +#endif + + protected: + void updateParam(value_t delta, int i); + void updateParams(const value_t delta[kNParams]); + + private: + // + static constexpr value_t InvalidX = -99999.; + value_t mX = 0.f; /// X of track evaluation + value_t mAlpha = 0.f; /// track frame angle + value_t mP[kNParams] = {0.f}; /// 5 parameters: Y,Z,sin(phi),tg(lambda),q/pT + char mAbsCharge = 1; /// Extra info about the abs charge, to be taken into account only if not 1 + PID mPID{}; /// 8 bit PID + uint16_t mUserField = 0; /// field provided to user + + ClassDefNV(TrackParametrization, 3); +}; + +//____________________________________________________________ +template <typename value_T> +inline TrackParametrization<value_T>::TrackParametrization(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, int charge) + : mX{x}, mAlpha{alpha}, mAbsCharge{char(std::abs(charge))} +{ + // explicit constructor + std::copy(par.begin(), par.end(), mP); +} + +//____________________________________________________________ +template <typename value_T> +inline const typename TrackParametrization<value_T>::value_t* TrackParametrization<value_T>::getParams() const +{ + return mP; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getParam(int i) const +{ + return mP[i]; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getX() const +{ + return mX; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getAlpha() const +{ + return mAlpha; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getY() const +{ + return mP[kY]; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getZ() const +{ + return mP[kZ]; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getSnp() const +{ + return mP[kSnp]; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getTgl() const +{ + return mP[kTgl]; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getQ2Pt() const +{ + return mP[kQ2Pt]; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCharge2Pt() const +{ + return mAbsCharge ? mP[kQ2Pt] : 0.; +} + +//____________________________________________________________ +template <typename value_T> +inline int TrackParametrization<value_T>::getAbsCharge() const +{ + return mAbsCharge; +} + +//____________________________________________________________ +template <typename value_T> +inline PID TrackParametrization<value_T>::getPID() const +{ + return mPID; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setPID(const PID pid) +{ + mPID = pid; + setAbsCharge(pid.getCharge()); +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp2() const +{ + value_t csp2 = (1. - mP[kSnp]) * (1. + mP[kSnp]); + return csp2 > o2::constants::math::Almost0 ? csp2 : o2::constants::math::Almost0; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp() const +{ + return sqrtf(getCsp2()); +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setX(value_t v) +{ + mX = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setParam(value_t v, int i) +{ + mP[i] = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setAlpha(value_t v) +{ + mAlpha = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setY(value_t v) +{ + mP[kY] = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setZ(value_t v) +{ + mP[kZ] = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setSnp(value_t v) +{ + mP[kSnp] = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setTgl(value_t v) +{ + mP[kTgl] = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setQ2Pt(value_t v) +{ + mP[kQ2Pt] = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::setAbsCharge(int q) +{ + mAbsCharge = std::abs(q); +} + +//_______________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::utils::CircleXY& c) const +{ + // get circle params in track local frame, for straight line just set to local coordinates + c.rC = getCurvature(bz); + // treat as straight track if sagitta between the vertex and middle of TPC is below 0.01 cm + constexpr value_t MinSagitta = 0.01, TPCMidR = 160., MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR); + if (std::abs(c.rC) > MinCurv) { + c.rC = 1.f / getCurvature(bz); + value_t sn = getSnp(), cs = sqrtf((1. - sn) * (1. + sn)); + c.xC = getX() - sn * c.rC; // center in tracking + c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!! + c.rC = fabs(c.rC); + } else { + c.rC = 0.f; // signal straight line + c.xC = getX(); + c.yC = getY(); + } +} + +//_______________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::utils::CircleXY& c, value_t& sna, value_t& csa) const +{ + // get circle params in loc and lab frame, for straight line just set to global coordinates + getCircleParamsLoc(bz, c); + o2::utils::sincos(getAlpha(), sna, csa); + o2::utils::rotateZ(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame +} + +//_______________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::getLineParams(o2::utils::IntervalXY& ln, value_t& sna, value_t& csa) const +{ + // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } + o2::utils::sincos(getAlpha(), sna, csa); + o2::utils::rotateZ(getX(), getY(), ln.xP, ln.yP, sna, csa); // reference point in global frame + value_t snp = getSnp(), csp = sqrtf((1.f - snp) * (1.f + snp)); + ln.dxP = csp * csa - snp * sna; + ln.dyP = snp * csa + csp * sna; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCurvature(value_t b) const +{ + return mAbsCharge ? mP[kQ2Pt] * b * o2::constants::math::B2C : 0.; +} + +//____________________________________________________________ +template <typename value_T> +inline int TrackParametrization<value_T>::getCharge() const +{ + return getSign() > 0 ? mAbsCharge : -mAbsCharge; +} + +//____________________________________________________________ +template <typename value_T> +inline int TrackParametrization<value_T>::getSign() const +{ + return mAbsCharge ? (mP[kQ2Pt] > 0.f ? 1 : -1) : 0; +} + +//_______________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhi() const +{ + // track pt direction phi (in 0:2pi range) + value_t phi = asinf(getSnp()) + getAlpha(); + utils::BringTo02Pi(phi); + return phi; +} + +//_______________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhiPos() const +{ + // angle of track position (in -pi:pi range) + value_t phi = atan2f(getY(), getX()) + getAlpha(); + utils::BringTo02Pi(phi); + return phi; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPtInv() const +{ + // return the inverted track pT + auto ptInv = fabs(mP[kQ2Pt]); + return (mAbsCharge > 1) ? ptInv / mAbsCharge : ptInv; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2Inv() const +{ + // return the inverted track momentum^2 + auto p2 = mP[kQ2Pt] * mP[kQ2Pt] / (1.f + getTgl() * getTgl()); + return (mAbsCharge > 1) ? p2 * mAbsCharge * mAbsCharge : p2; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2() const +{ + // return the track momentum^2 + auto p2inv = getP2Inv(); + return (p2inv > o2::constants::math::Almost0) ? 1. / p2inv : o2::constants::math::VeryBig; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPInv() const +{ + // return the inverted track momentum^2 + auto pInv = fabs(mP[kQ2Pt]) / sqrtf(1.f + getTgl() * getTgl()); + return (mAbsCharge > 1) ? pInv / mAbsCharge : pInv; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP() const +{ + // return the track momentum + value_t pInv = getPInv(); + return (pInv > o2::constants::math::Almost0) ? 1. / pInv : o2::constants::math::VeryBig; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPt() const +{ + // return the track transverse momentum + value_t ptI = fabs(mP[kQ2Pt]); + if (mAbsCharge > 1) { + ptI /= mAbsCharge; + } + return (ptI > o2::constants::math::Almost0) ? 1.f / ptI : o2::constants::math::VeryBig; +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getTheta() const +{ + return constants::math::PIHalf - std::atan(mP[3]); +} + +//____________________________________________________________ +template <typename value_T> +inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getEta() const +{ + return -std::log(std::tan(0.5 * getTheta())); +} + +#ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden +//_______________________________________________________ +template <typename value_T> +inline Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGlo() const +{ + return Rotation2D(getAlpha())(Point3D<value_t>(getX(), getY(), getZ())); +} +#endif + +//_______________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::getXYZGlo(std::array<value_t, 3>& xyz) const +{ + // track coordinates in lab frame + xyz[0] = getX(); + xyz[1] = getY(); + xyz[2] = getZ(); + utils::RotateZ(xyz, getAlpha()); +} + +#ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden +//_______________________________________________________ +template <typename value_T> +inline Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGloAt(value_t xk, value_t b, bool& ok) const +{ + //---------------------------------------------------------------- + // estimate global X,Y,Z in global frame at given X + //---------------------------------------------------------------- + value_t y = 0.f, z = 0.f; + ok = getYZAt(xk, b, y, z); + return ok ? Rotation2D(getAlpha())(Point3D<value_t>(xk, y, z)) : Point3D<value_t>(); +} +#endif + +//____________________________________________________________ +template <typename value_T> +inline bool TrackParametrization<value_T>::isValid() const +{ + return mX != InvalidX; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::invalidate() +{ + mX = InvalidX; +} + +template <typename value_T> +inline uint16_t TrackParametrization<value_T>::getUserField() const +{ + return mUserField; +} + +template <typename value_T> +inline void TrackParametrization<value_T>::setUserField(uint16_t v) +{ + mUserField = v; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::updateParam(value_t delta, int i) +{ + mP[i] += delta; +} + +//____________________________________________________________ +template <typename value_T> +inline void TrackParametrization<value_T>::updateParams(const value_t delta[kNParams]) +{ + for (int i = kNParams; i--;) { + mP[i] += delta[i]; + } +} + +} // namespace track +} // namespace o2 + +#endif /* INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATION_H_ */ diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h new file mode 100644 index 0000000000000..4418bef53acaa --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -0,0 +1,293 @@ +// 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 TrackParametrizationWithError.h +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since Oct 1, 2020 +/// @brief + +#ifndef INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATIONWITHERROR_H_ +#define INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATIONWITHERROR_H_ + +#include "ReconstructionDataFormats/TrackParametrization.h" + +namespace o2 +{ +namespace track +{ + +template <typename value_T = float> +class TrackParametrizationWithError : public TrackParametrization<value_T> +{ // track+error parameterization + using MatrixDSym5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepSym<double, kNParams>>; + using MatrixD5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepStd<double, kNParams, kNParams>>; + + using typename TrackParametrization<value_T>::value_t; + + static_assert(std::is_floating_point_v<value_t>); + + public: + TrackParametrizationWithError(); + TrackParametrizationWithError(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, const std::array<value_t, kCovMatSize>& cov, int charge = 1); + TrackParametrizationWithError(const std::array<value_t, 3>& xyz, const std::array<value_t, 3>& pxpypz, + const std::array<value_t, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); + + TrackParametrizationWithError(const TrackParametrizationWithError& src) = default; + TrackParametrizationWithError(TrackParametrizationWithError&& src) = default; + TrackParametrizationWithError& operator=(const TrackParametrizationWithError& src) = default; + TrackParametrizationWithError& operator=(TrackParametrizationWithError&& src) = default; + ~TrackParametrizationWithError() = default; + + const value_t* getCov() const; + value_t getSigmaY2() const; + value_t getSigmaZY() const; + value_t getSigmaZ2() const; + value_t getSigmaSnpY() const; + value_t getSigmaSnpZ() const; + value_t getSigmaSnp2() const; + value_t getSigmaTglY() const; + value_t getSigmaTglZ() const; + value_t getSigmaTglSnp() const; + value_t getSigmaTgl2() const; + value_t getSigma1PtY() const; + value_t getSigma1PtZ() const; + value_t getSigma1PtSnp() const; + value_t getSigma1PtTgl() const; + value_t getSigma1Pt2() const; + value_t getCovarElem(int i, int j) const; + value_t getDiagError2(int i) const; + + bool getCovXYZPxPyPzGlo(std::array<value_t, 21>& c) const; + +#ifndef GPUCA_ALIGPUCODE + void print() const; + std::string asString() const; +#endif + + // parameters + covmat manipulation + bool rotate(value_t alpha); + bool propagateTo(value_t xk, value_t b); + bool propagateTo(value_t xk, const std::array<value_t, 3>& b); + bool propagateToDCA(const o2::dataformats::VertexBase& vtx, value_t b, o2::dataformats::DCA* dca = nullptr, value_t maxD = 999.f); + void invert(); + + value_t getPredictedChi2(const std::array<value_t, 2>& p, const std::array<value_t, 3>& cov) const; + + template <typename T> + value_t getPredictedChi2(const BaseCluster<T>& p) const; + + value_t getPredictedChi2(const TrackParametrizationWithError& rhs) const; + + void buildCombinedCovMatrix(const TrackParametrizationWithError& rhs, MatrixDSym5& cov) const; + value_t getPredictedChi2(const TrackParametrizationWithError& rhs, MatrixDSym5& covToSet) const; + bool update(const TrackParametrizationWithError& rhs, const MatrixDSym5& covInv); + + bool update(const std::array<value_t, 2>& p, const std::array<value_t, 3>& cov); + + template <typename T> + bool update(const BaseCluster<T>& p); + + bool update(const TrackParametrizationWithError& rhs); + + bool correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); + + void resetCovariance(value_t s2 = 0); + void checkCovariance(); + void setCov(value_t v, int i); + + protected: + void updateCov(const value_t delta[kCovMatSize]); + + protected: + value_t mC[kCovMatSize] = {0.f}; // 15 covariance matrix elements + + ClassDefNV(TrackParametrizationWithError, 2); +}; + +//__________________________________________________________________________ +template <typename value_T> +inline TrackParametrizationWithError<value_T>::TrackParametrizationWithError() : TrackParametrization<value_T>{} +{ +} + +//__________________________________________________________________________ +template <typename value_T> +inline TrackParametrizationWithError<value_T>::TrackParametrizationWithError(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, + const std::array<value_t, kCovMatSize>& cov, int charge) + : TrackParametrization<value_T>{x, alpha, par, charge} +{ + // explicit constructor + std::copy(cov.begin(), cov.end(), mC); +} + +//__________________________________________________________________________ +template <typename value_T> +inline const typename TrackParametrizationWithError<value_T>::value_t* TrackParametrizationWithError<value_T>::getCov() const +{ + return mC; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaY2() const +{ + return mC[kSigY2]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaZY() const +{ + return mC[kSigZY]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaZ2() const +{ + return mC[kSigZ2]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnpY() const +{ + return mC[kSigSnpY]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnpZ() const +{ + return mC[kSigSnpZ]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnp2() const +{ + return mC[kSigSnp2]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglY() const +{ + return mC[kSigTglY]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglZ() const +{ + return mC[kSigTglZ]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglSnp() const +{ + return mC[kSigTglSnp]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTgl2() const +{ + return mC[kSigTgl2]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtY() const +{ + return mC[kSigQ2PtY]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtZ() const +{ + return mC[kSigQ2PtZ]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtSnp() const +{ + return mC[kSigQ2PtSnp]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtTgl() const +{ + return mC[kSigQ2PtTgl]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1Pt2() const +{ + return mC[kSigQ2Pt2]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getCovarElem(int i, int j) const +{ + return mC[CovarMap[i][j]]; +} + +//__________________________________________________________________________ +template <typename value_T> +inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getDiagError2(int i) const +{ + return mC[DiagMap[i]]; +} + +//__________________________________________________________________________ +template <typename value_T> +template <typename T> +typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const BaseCluster<T>& p) const +{ + const std::array<value_t, 2> pyz = {p.getY(), p.getZ()}; + const std::array<value_t, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; + return getPredictedChi2(pyz, cov); +} + +//__________________________________________________________________________ +template <typename value_T> +template <typename T> +bool TrackParametrizationWithError<value_T>::update(const BaseCluster<T>& p) +{ + const std::array<value_t, 2> pyz = {p.getY(), p.getZ()}; + const std::array<value_t, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; + return update(pyz, cov); +} + +//__________________________________________________________________________ +template <typename value_T> +inline void TrackParametrizationWithError<value_T>::setCov(value_t v, int i) +{ + mC[i] = v; +} + +//__________________________________________________________________________ +template <typename value_T> +inline void TrackParametrizationWithError<value_T>::updateCov(const value_t delta[kCovMatSize]) +{ + for (int i = kCovMatSize; i--;) + mC[i] += delta[i]; +} + +} // namespace track +} // namespace o2 +#endif /* INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATIONWITHERROR_H_ */ diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h new file mode 100644 index 0000000000000..529b82afc0880 --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h @@ -0,0 +1,143 @@ +// 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 TrackParametrizationHelpers.h +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since Oct 1, 2020 +/// @brief Helper functions for track manipulation + +#ifndef INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKUTILS_H_ +#define INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKUTILS_H_ + +#include "GPUCommonRtypes.h" + +#ifndef __OPENCL__ +#include <array> +#include <cmath> +#endif + +#include "MathUtils/Utils.h" +#include "CommonConstants/MathConstants.h" + +namespace o2 +{ +namespace track +{ +// helper function +template <typename value_T = float> +value_T BetheBlochSolid(value_T bg, value_T rho = 2.33, value_T kp1 = 0.20, value_T kp2 = 3.00, value_T meanI = 173e-9, + value_T meanZA = 0.49848); +template <typename value_T = float> +void g3helx3(value_T qfield, value_T step, std::array<value_T, 7>& vect); + +//____________________________________________________ +template <typename value_T> +void g3helx3(value_T qfield, value_T step, std::array<value_T, 7>& vect) +{ + /****************************************************************** + * * + * GEANT3 tracking routine in a constant field oriented * + * along axis 3 * + * Tracking is performed with a conventional * + * helix step method * + * * + * Authors R.Brun, M.Hansroul ********* * + * Rewritten V.Perevoztchikov * + * * + * Rewritten in C++ by I.Belikov * + * * + * qfield (kG) - particle charge times magnetic field * + * step (cm) - step length along the helix * + * vect[7](cm,GeV/c) - input/output x, y, z, px/p, py/p ,pz/p, p * + * * + ******************************************************************/ + + static_assert(std::is_floating_point_v<value_T>); + + const int ix = 0, iy = 1, iz = 2, ipx = 3, ipy = 4, ipz = 5, ipp = 6; + constexpr value_T kOvSqSix = 0.408248f; // std::sqrt(1./6.); + + value_T cosx = vect[ipx], cosy = vect[ipy], cosz = vect[ipz]; + + value_T rho = qfield * constants::math::B2C / vect[ipp]; + value_T tet = rho * step; + + value_T tsint, sintt, sint, cos1t; + if (fabs(tet) > 0.03f) { + sint = sinf(tet); + sintt = sint / tet; + tsint = (tet - sint) / tet; + value_T t = sinf(0.5f * tet); + cos1t = 2 * t * t / tet; + } else { + tsint = tet * tet / 6.f; + sintt = (1.f - tet * kOvSqSix) * (1.f + tet * kOvSqSix); // 1.- tsint; + sint = tet * sintt; + cos1t = 0.5f * tet; + } + + value_T f1 = step * sintt; + value_T f2 = step * cos1t; + value_T f3 = step * tsint * cosz; + value_T f4 = -tet * cos1t; + value_T f5 = sint; + + vect[ix] += f1 * cosx - f2 * cosy; + vect[iy] += f1 * cosy + f2 * cosx; + vect[iz] += f1 * cosz + f3; + + vect[ipx] += f4 * cosx - f5 * cosy; + vect[ipy] += f4 * cosy + f5 * cosx; +} + +//____________________________________________________ +template <typename value_T> +value_T BetheBlochSolid(value_T bg, value_T rho, value_T kp1, value_T kp2, value_T meanI, + value_T meanZA) +{ + // + // This is the parameterization of the Bethe-Bloch formula inspired by Geant. + // + // bg - beta*gamma + // rho - density [g/cm^3] + // kp1 - density effect first junction point + // kp2 - density effect second junction point + // meanI - mean excitation energy [GeV] + // meanZA - mean Z/A + // + // The default values for the kp* parameters are for silicon. + // The returned value is in [GeV/(g/cm^2)]. + // + static_assert(std::is_floating_point_v<value_T>); + + constexpr value_T mK = 0.307075e-3f; // [GeV*cm^2/g] + constexpr value_T me = 0.511e-3f; // [GeV/c^2] + kp1 *= 2.303f; + kp2 *= 2.303f; + value_T bg2 = bg * bg; + value_T maxT = 2.f * me * bg2; // neglecting the electron mass + + //*** Density effect + value_T d2 = 0.; + const value_T x = log(bg); + const value_T lhwI = log(28.816 * 1e-9 * std::sqrt(rho * meanZA) / meanI); + if (x > kp2) { + d2 = lhwI + x - 0.5; + } else if (x > kp1) { + double r = (kp2 - x) / (kp2 - kp1); + d2 = lhwI + x - 0.5 + (0.5 - lhwI - kp1) * r * r * r; + } + return mK * meanZA * (1 + bg2) / bg2 * (0.5 * log(2 * me * bg2 * maxT / (meanI * meanI)) - bg2 / (1 + bg2) - d2); +} + +} // namespace track +} // namespace o2 + +#endif /* INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKUTILS_H_ */ diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index ea8000cdc3292..c0063614bb1c8 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -15,7 +15,11 @@ #pragma link off all functions; #pragma link C++ class o2::track::TrackPar + ; +#pragma link C++ class o2::track::TrackParametrization < float> + ; +//#pragma link C++ class o2::track::TrackParametrization < double> + ; #pragma link C++ class o2::track::TrackParCov + ; +#pragma link C++ class o2::track::TrackParametrizationWithError < float> + ; +//#pragma link C++ class o2::track::TrackParametrizationWithError < double> + ; #pragma link C++ class o2::track::TrackParFwd + ; #pragma link C++ class o2::track::TrackParCovFwd + ; #pragma link C++ class o2::track::PID + ; diff --git a/DataFormats/Reconstruction/src/Track.cxx b/DataFormats/Reconstruction/src/Track.cxx deleted file mode 100644 index f83c53f4d2c56..0000000000000 --- a/DataFormats/Reconstruction/src/Track.cxx +++ /dev/null @@ -1,1830 +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. - -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/Vertex.h" -#include "ReconstructionDataFormats/DCA.h" -#include <FairLogger.h> -#include <iostream> -#include "Math/SMatrix.h" -#include <fmt/printf.h> -#include "Framework/Logger.h" - -using o2::track::TrackPar; -using o2::track::TrackParCov; -using std::array; -using namespace o2::constants::math; - -//______________________________________________________________ -TrackPar::TrackPar(const array<float, 3>& xyz, const array<float, 3>& pxpypz, int charge, bool sectorAlpha) - : mX{0.f}, mAlpha{0.f}, mP{0.f} -{ - // construct track param from kinematics - - // Alpha of the frame is defined as: - // sectorAlpha == false : -> angle of pt direction - // sectorAlpha == true : -> angle of the sector from X,Y coordinate for r>1 - // angle of pt direction for r==0 - // - // - constexpr float kSafe = 1e-5f; - float radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; - float alp = 0; - if (sectorAlpha || radPos2 < 1) { - alp = atan2f(pxpypz[1], pxpypz[0]); - } else { - alp = atan2f(xyz[1], xyz[0]); - } - if (sectorAlpha) { - alp = utils::Angle2Alpha(alp); - } - // - float sn, cs; - utils::sincos(alp, sn, cs); - // protection: avoid alpha being too close to 0 or +-pi/2 - if (fabs(sn) < 2 * kSafe) { - if (alp > 0) { - alp += alp < PIHalf ? 2 * kSafe : -2 * kSafe; - } else { - alp += alp > -PIHalf ? -2 * kSafe : 2 * kSafe; - } - utils::sincos(alp, sn, cs); - } else if (fabs(cs) < 2 * kSafe) { - if (alp > 0) { - alp += alp > PIHalf ? 2 * kSafe : -2 * kSafe; - } else { - alp += alp > -PIHalf ? 2 * kSafe : -2 * kSafe; - } - utils::sincos(alp, sn, cs); - } - // get the vertex of origin and the momentum - array<float, 3> ver{xyz[0], xyz[1], xyz[2]}; - array<float, 3> mom{pxpypz[0], pxpypz[1], pxpypz[2]}; - // - // Rotate to the local coordinate system - utils::RotateZ(ver, -alp); - utils::RotateZ(mom, -alp); - // - float ptI = 1.f / sqrt(mom[0] * mom[0] + mom[1] * mom[1]); - mX = ver[0]; - mAlpha = alp; - mP[kY] = ver[1]; - mP[kZ] = ver[2]; - mP[kSnp] = mom[1] * ptI; - mP[kTgl] = mom[2] * ptI; - mAbsCharge = std::abs(charge); - mP[kQ2Pt] = charge ? ptI * charge : ptI; - // - if (fabs(1 - getSnp()) < kSafe) { - mP[kSnp] = 1. - kSafe; // Protection - } else if (fabs(-1 - getSnp()) < kSafe) { - mP[kSnp] = -1. + kSafe; // Protection - } - // -} - -//_______________________________________________________ -bool TrackPar::getPxPyPzGlo(array<float, 3>& pxyz) const -{ - // track momentum - if (fabs(getQ2Pt()) < Almost0 || fabs(getSnp()) > Almost1) { - return false; - } - float cs, sn, pt = getPt(); - float r = std::sqrt((1.f - getSnp()) * (1.f + getSnp())); - utils::sincos(getAlpha(), sn, cs); - pxyz[0] = pt * (r * cs - getSnp() * sn); - pxyz[1] = pt * (getSnp() * cs + r * sn); - pxyz[2] = pt * getTgl(); - return true; -} - -//____________________________________________________ -bool TrackPar::getPosDirGlo(array<float, 9>& posdirp) const -{ - // fill vector with lab x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha - float ptI = fabs(getQ2Pt()); - float snp = getSnp(); - if (ptI < Almost0 || fabs(snp) > Almost1) { - return false; - } - float &sn = posdirp[7], &cs = posdirp[8]; - float csp = std::sqrt((1.f - snp) * (1.f + snp)); - float cstht = std::sqrt(1.f + getTgl() * getTgl()); - float csthti = 1.f / cstht; - utils::sincos(getAlpha(), sn, cs); - posdirp[0] = getX() * cs - getY() * sn; - posdirp[1] = getX() * sn + getY() * cs; - posdirp[2] = getZ(); - posdirp[3] = (csp * cs - snp * sn) * csthti; // px/p - posdirp[4] = (snp * cs + csp * sn) * csthti; // py/p - posdirp[5] = getTgl() * csthti; // pz/p - posdirp[6] = cstht / ptI; // p - return true; -} - -//______________________________________________________________ -bool TrackPar::rotateParam(float alpha) -{ - // rotate to alpha frame - if (fabs(getSnp()) > Almost1) { - LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); - return false; - } - // - utils::BringToPMPi(alpha); - // - float ca = 0, sa = 0; - utils::sincos(alpha - getAlpha(), sa, ca); - float snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision - // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle - // direction in local frame is along the X axis - if ((csp * ca + snp * sa) < 0) { - //LOGF(WARNING,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa); - return false; - } - // - float tmp = snp * ca - csp * sa; - if (fabs(tmp) > Almost1) { - LOGF(WARNING, "Rotation failed: new snp {:.2f}", tmp); - return false; - } - float xold = getX(), yold = getY(); - mAlpha = alpha; - mX = xold * ca + yold * sa; - mP[kY] = -xold * sa + yold * ca; - mP[kSnp] = tmp; - return true; -} - -//____________________________________________________________ -bool TrackPar::propagateParamTo(float xk, const array<float, 3>& b) -{ - //---------------------------------------------------------------- - // Extrapolate this track params (w/o cov matrix) to the plane X=xk in the field b[]. - // - // X [cm] is in the "tracking coordinate system" of this track. - // b[]={Bx,By,Bz} [kG] is in the Global coordidate system. - //---------------------------------------------------------------- - - float dx = xk - getX(); - if (fabs(dx) < Almost0) { - return true; - } - // Do not propagate tracks outside the ALICE detector - if (fabs(dx) > 1e5 || fabs(getY()) > 1e5 || fabs(getZ()) > 1e5) { - LOGF(WARNING, "Anomalous track, target X:{:f}", xk); - // print(); - return false; - } - float crv = getCurvature(b[2]); - float x2r = crv * dx; - float f1 = getSnp(), f2 = f1 + x2r; - if (fabs(f1) > Almost1 || fabs(f2) > Almost1) { - return false; - } - float r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { - return false; - } - float r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { - return false; - } - float dy2dx = (f1 + f2) / (r1 + r2); - float step = (fabs(x2r) < 0.05f) ? dx * fabs(r2 + f2 * dy2dx) // chord - : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc - step *= std::sqrt(1.f + getTgl() * getTgl()); - // - // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System - array<float, 9> vecLab{0.f}; - if (!getPosDirGlo(vecLab)) { - return false; - } - - // rotate to the system where Bx=By=0. - float bxy2 = b[0] * b[0] + b[1] * b[1]; - float bt = std::sqrt(bxy2); - float cosphi = 1.f, sinphi = 0.f; - if (bt > Almost0) { - cosphi = b[0] / bt; - sinphi = b[1] / bt; - } - float bb = std::sqrt(bxy2 + b[2] * b[2]); - float costet = 1., sintet = 0.; - if (bb > Almost0) { - costet = b[2] / bb; - sintet = bt / bb; - } - array<float, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], - -sinphi * vecLab[0] + cosphi * vecLab[1], - sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], - costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], - -sinphi * vecLab[3] + cosphi * vecLab[4], - sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], - vecLab[6]}; - - // Do the helix step - float q = getCharge(); - g3helx3(q * bb, step, vect); - - // rotate back to the Global System - vecLab[0] = cosphi * costet * vect[0] - sinphi * vect[1] + cosphi * sintet * vect[2]; - vecLab[1] = sinphi * costet * vect[0] + cosphi * vect[1] + sinphi * sintet * vect[2]; - vecLab[2] = -sintet * vect[0] + costet * vect[2]; - - vecLab[3] = cosphi * costet * vect[3] - sinphi * vect[4] + cosphi * sintet * vect[5]; - vecLab[4] = sinphi * costet * vect[3] + cosphi * vect[4] + sinphi * sintet * vect[5]; - vecLab[5] = -sintet * vect[3] + costet * vect[5]; - - // rotate back to the Tracking System - float sinalp = -vecLab[7], cosalp = vecLab[8]; - float t = cosalp * vecLab[0] - sinalp * vecLab[1]; - vecLab[1] = sinalp * vecLab[0] + cosalp * vecLab[1]; - vecLab[0] = t; - t = cosalp * vecLab[3] - sinalp * vecLab[4]; - vecLab[4] = sinalp * vecLab[3] + cosalp * vecLab[4]; - vecLab[3] = t; - - // Do the final correcting step to the target plane (linear approximation) - float x = vecLab[0], y = vecLab[1], z = vecLab[2]; - if (fabs(dx) > Almost0) { - if (fabs(vecLab[3]) < Almost0) { - return false; - } - dx = xk - vecLab[0]; - x += dx; - y += vecLab[4] / vecLab[3] * dx; - z += vecLab[5] / vecLab[3] * dx; - } - - // Calculate the track parameters - t = 1.f / std::sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); - mX = x; - mP[kY] = y; - mP[kZ] = z; - mP[kSnp] = vecLab[4] * t; - mP[kTgl] = vecLab[5] * t; - mP[kQ2Pt] = q * t / vecLab[6]; - - return true; -} - -//____________________________________________________________ -bool TrackPar::propagateParamTo(float xk, float b) -{ - //---------------------------------------------------------------- - // propagate this track to the plane X=xk (cm) in the field "b" (kG) - // Only parameters are propagated, not the matrix. To be used for small - // distances only (<mm, i.e. misalignment) - //---------------------------------------------------------------- - float dx = xk - getX(); - if (fabs(dx) < Almost0) { - return true; - } - float crv = (fabs(b) < Almost0) ? 0.f : getCurvature(b); - float x2r = crv * dx; - float f1 = getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { - return false; - } - float r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { - return false; - } - float r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { - return false; - } - mX = xk; - double dy2dx = (f1 + f2) / (r1 + r2); - mP[kY] += dx * dy2dx; - mP[kSnp] += x2r; - if (fabs(x2r) < 0.05f) { - mP[kZ] += dx * (r2 + f2 * dy2dx) * getTgl(); - } else { - // for small dx/R the linear apporximation of the arc by the segment is OK, - // but at large dx/R the error is very large and leads to incorrect Z propagation - // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi - // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2) - // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one - // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center - // track1 += rot/crv*track3; - // - float rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. - if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles - if (f2 > 0.f) { - rot = PI - rot; // - } else { - rot = -PI - rot; - } - } - mP[kZ] += getTgl() / crv * rot; - } - return true; -} - -//_______________________________________________________________________ -bool TrackPar::propagateParamToDCA(const Point3D<float>& vtx, float b, std::array<float, 2>* dca, float maxD) -{ - // propagate track to DCA to the vertex - float sn, cs, alp = getAlpha(); - o2::utils::sincos(alp, sn, cs); - float x = getX(), y = getY(), snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); - float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); - x -= xv; - y -= yv; - //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); - if (d > maxD) { - return false; - } - float crv = getCurvature(b); - float tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > Almost0) ? sn / tgfv : Almost1; - - x = xv * cs + yv * sn; - yv = -xv * sn + yv * cs; - xv = x; - - auto tmpT(*this); // operate on the copy to recover after the failure - alp += std::asin(sn); - if (!tmpT.rotateParam(alp) || !tmpT.propagateParamTo(xv, b)) { - LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " - << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; - tmpT.printParam(); - return false; - } - *this = tmpT; - if (dca) { - (*dca)[0] = getY() - yv; - (*dca)[1] = getZ() - zv; - } - return true; -} - -//____________________________________________________________ -bool TrackPar::getYZAt(float xk, float b, float& y, float& z) const -{ - //---------------------------------------------------------------- - // estimate Y,Z in tracking frame at given X - //---------------------------------------------------------------- - float dx = xk - getX(); - if (fabs(dx) < Almost0) { - return true; - } - float crv = getCurvature(b); - float x2r = crv * dx; - float f1 = getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { - return false; - } - float r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { - return false; - } - float r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { - return false; - } - double dy2dx = (f1 + f2) / (r1 + r2); - y = mP[kY] + dx * dy2dx; - z = mP[kZ]; - if (fabs(x2r) < 0.05f) { - z += dx * (r2 + f2 * dy2dx) * getTgl(); - } else { - // for small dx/R the linear apporximation of the arc by the segment is OK, - // but at large dx/R the error is very large and leads to incorrect Z propagation - // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi - // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2) - // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one - // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center - // track1 += rot/crv*track3; - // - float rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. - if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles - if (f2 > 0.f) { - rot = PI - rot; // - } else { - rot = -PI - rot; - } - } - z += getTgl() / crv * rot; - } - return true; -} - -//______________________________________________________________ -void TrackPar::invertParam() -{ - // Transform this track to the local coord. system rotated by 180 deg. - mX = -mX; - mAlpha += PI; - utils::BringToPMPi(mAlpha); - // - mP[0] = -mP[0]; - mP[3] = -mP[3]; - mP[4] = -mP[4]; - // -} - -//______________________________________________________________ -float TrackPar::getZAt(float xk, float b) const -{ - ///< this method is just an alias for obtaining Z @ X in the tree->Draw() - float y, z; - return getYZAt(xk, b, y, z) ? z : -9999.; -} - -//______________________________________________________________ -float TrackPar::getYAt(float xk, float b) const -{ - ///< this method is just an alias for obtaining Z @ X in the tree->Draw() - float y, z; - return getYZAt(xk, b, y, z) ? y : -9999.; -} - -#ifndef GPUCA_ALIGPUCODE -//______________________________________________________________ -std::string TrackPar::asString() const -{ - // print parameters as string - return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d} {:s}", - getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName()); -} - -//______________________________________________________________ -void TrackPar::printParam() const -{ - // print parameters - printf("%s\n", asString().c_str()); -} -#endif - -//______________________________________________________________ -bool TrackPar::getXatLabR(float r, float& x, float bz, o2::track::DirType dir) const -{ - // Get local X of the track position estimated at the radius lab radius r. - // The track curvature is accounted exactly - // - // The flag "dir" can be used to remove the ambiguity of which intersection to take (out of 2 possible) - // DirAuto (==0) - take the intersection closest to the current track position - // DirOutward (==1) - go along the track (increasing mX) - // DirInward (==-1) - go backward (decreasing mX) - // - const auto fy = mP[0], sn = mP[2]; - const float kEps = 1.e-6; - // - auto crv = getCurvature(bz); - if (fabs(crv) > o2::constants::math::Almost0) { // helix - // get center of the track circle - o2::utils::CircleXY circle; - getCircleParamsLoc(bz, circle); - auto r0 = std::sqrt(circle.getCenterD2()); - if (r0 <= o2::constants::math::Almost0) { - return false; // the track is concentric to circle - } - float tR2r0 = 1., g = 0., tmp = 0.; - if (fabs(circle.rC - r0) > kEps) { - tR2r0 = circle.rC / r0; - g = 0.5 * (r * r / (r0 * circle.rC) - tR2r0 - 1. / tR2r0); - tmp = 1. + g * tR2r0; - } else { - tR2r0 = 1.0; - g = 0.5 * r * r / (r0 * circle.rC) - 1.; - tmp = 0.5 * r * r / (r0 * r0); - } - auto det = (1. - g) * (1. + g); - if (det < 0.) { - return false; // does not reach raduis r - } - det = std::sqrt(det); - // - // the intersection happens in 2 points: {circle.xC+tR*C,circle.yC+tR*S} - // with C=f*c0+-|s0|*det and S=f*s0-+c0 sign(s0)*det - // where s0 and c0 make direction for the circle center (=circle.xC/r0 and circle.yC/r0) - // - x = circle.xC * tmp; - auto y = circle.yC * tmp; - if (fabs(circle.yC) > o2::constants::math::Almost0) { // when circle.yC==0 the x,y is unique - auto dfx = tR2r0 * fabs(circle.yC) * det; - auto dfy = tR2r0 * circle.xC * (circle.yC > 0. ? det : -det); - if (dir == DirAuto) { // chose the one which corresponds to smallest step - auto delta = (x - mX) * dfx - (y - fy) * dfy; // the choice of + in C will lead to smaller step if delta<0 - x += delta < 0. ? dfx : -dfx; - } else if (dir == DirOutward) { // along track direction: x must be > mX - x -= dfx; // try the smallest step (dfx is positive) - auto dfeps = mX - x; // handle special case of very small step - if (dfeps < -kEps) { - return true; - } - if (fabs(dfeps) < kEps && fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? - return mX; - } - x += dfx + dfx; - auto dxm = x - mX; - if (dxm > 0.) { - return true; - } else if (dxm < -kEps) { - return false; - } - x = mX; // don't move - } else { // backward: x must be < mX - x += dfx; // try the smallest step (dfx is positive) - auto dfeps = x - mX; // handle special case of very small step - if (dfeps < -kEps) { - return true; - } - if (fabs(dfeps) < kEps && fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? - return mX; - } - x -= dfx + dfx; - auto dxm = x - mX; - if (dxm < 0.) { - return true; - } - if (dxm > kEps) { - return false; - } - x = mX; // don't move - } - } else { // special case: track touching the circle just in 1 point - if ((dir == DirOutward && x < mX) || (dir == DirInward && x > mX)) { - return false; - } - } - } else { // this is a straight track - if (fabs(sn) >= o2::constants::math::Almost1) { // || to Y axis - auto det = (r - mX) * (r + mX); - if (det < 0.) { - return false; // does not reach raduis r - } - x = mX; - if (dir == DirAuto) { - return true; - } - det = std::sqrt(det); - if (dir == DirOutward) { // along the track direction - if (sn > 0.) { - if (fy > det) { - return false; // track is along Y axis and above the circle - } - } else { - if (fy < -det) { - return false; // track is against Y axis amd belo the circle - } - } - } else if (dir == DirInward) { // against track direction - if (sn > 0.) { - if (fy < -det) { - return false; // track is along Y axis - } - } else if (fy > det) { - return false; // track is against Y axis - } - } - } else if (fabs(sn) <= o2::constants::math::Almost0) { // || to X axis - auto det = (r - fy) * (r + fy); - if (det < 0.) { - return false; // does not reach raduis r - } - det = std::sqrt(det); - if (dir == DirAuto) { - x = mX > 0. ? det : -det; // choose the solution requiring the smalest step - return true; - } else if (dir == DirOutward) { // along the track direction - if (mX > det) { - return false; // current point is in on the right from the circle - } else { - x = (mX < -det) ? -det : det; // on the left : within the circle - } - } else { // against the track direction - if (mX < -det) { - return false; - } else { - x = mX > det ? det : -det; - } - } - } else { // general case of straight line - auto cs = std::sqrt((1 - sn) * (1 + sn)); - auto xsyc = mX * sn - fy * cs; - auto det = (r - xsyc) * (r + xsyc); - if (det < 0.) { - return false; // does not reach raduis r - } - det = std::sqrt(det); - auto xcys = mX * cs + fy * sn; - auto t = -xcys; - if (dir == DirAuto) { - t += t > 0. ? -det : det; // chose the solution requiring the smalest step - } else if (dir > 0) { // go in increasing mX direction. ( t+-det > 0) - if (t >= -det) { - t += -det; // take minimal step giving t>0 - } else { - return false; // both solutions have negative t - } - } else { // go in increasing mX direction. (t+-det < 0) - if (t < det) { - t -= det; // take minimal step giving t<0 - } else { - return false; // both solutions have positive t - } - } - x = mX + cs * t; - } - } - // - return true; -} - -//______________________________________________ -bool TrackPar::correctForELoss(float xrho, float mass, bool anglecorr, float dedx) -{ - //------------------------------------------------------------------ - // This function corrects the track parameters for the energy loss in crossed material. - // "xrho" - is the product length*density (g/cm^2). - // It should be passed as negative when propagating tracks - // from the intreaction point to the outside of the central barrel. - // "mass" - the mass of this particle (GeV/c^2). - // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly - // "anglecorr" - switch for the angular correction - //------------------------------------------------------------------ - constexpr float kMaxELossFrac = 0.3f; // max allowed fractional eloss - constexpr float kMinP = 0.01f; // kill below this momentum - - // Apply angle correction, if requested - if (anglecorr) { - float csp2 = (1.f - getSnp()) * (1.f + getSnp()); // cos(phi)^2 - float cst2I = (1.f + getTgl() * getTgl()); // 1/cos(lambda)^2 - float angle = std::sqrt(cst2I / (csp2)); - xrho *= angle; - } - - float p = getP(); - if (mass < 0) { - p += p; // q=2 particle - } - float p2 = p * p, mass2 = mass * mass; - float e2 = p2 + mass2; - float beta2 = p2 / e2; - - // Calculating the energy loss corrections************************ - if ((xrho != 0.f) && (beta2 < 1.f)) { - if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / fabs(mass)); - if (mAbsCharge != 1) { - dedx *= mAbsCharge * mAbsCharge; - } - } - - float dE = dedx * xrho; - float e = std::sqrt(e2); - if (fabs(dE) > kMaxELossFrac * e) { - return false; // 30% energy loss is too much! - } - float eupd = e + dE; - float pupd2 = eupd * eupd - mass2; - if (pupd2 < kMinP * kMinP) { - return false; - } - setQ2Pt(getQ2Pt() * p / std::sqrt(pupd2)); - } - - return true; -} - -//______________________________________________________________ -void TrackParCov::invert() -{ - // Transform this track to the local coord. system rotated by 180 deg. - invertParam(); - // since the fP1 and fP2 are not inverted, their covariances with others change sign - mC[kSigZY] = -mC[kSigZY]; - mC[kSigSnpY] = -mC[kSigSnpY]; - mC[kSigTglZ] = -mC[kSigTglZ]; - mC[kSigTglSnp] = -mC[kSigTglSnp]; - mC[kSigQ2PtZ] = -mC[kSigQ2PtZ]; - mC[kSigQ2PtSnp] = -mC[kSigQ2PtSnp]; -} - -//______________________________________________________________ -bool TrackParCov::propagateTo(float xk, float b) -{ - //---------------------------------------------------------------- - // propagate this track to the plane X=xk (cm) in the field "b" (kG) - //---------------------------------------------------------------- - float dx = xk - getX(); - if (fabs(dx) < Almost0) { - return true; - } - float crv = getCurvature(b); - float x2r = crv * dx; - float f1 = getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { - return false; - } - float r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { - return false; - } - float r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { - return false; - } - setX(xk); - double dy2dx = (f1 + f2) / (r1 + r2); - float dP[kNParams] = {0.f}; - dP[kY] = dx * dy2dx; - dP[kSnp] = x2r; - if (fabs(x2r) < 0.05f) { - dP[kZ] = dx * (r2 + f2 * dy2dx) * getTgl(); - } else { - // for small dx/R the linear apporximation of the arc by the segment is OK, - // but at large dx/R the error is very large and leads to incorrect Z propagation - // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi - // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2) - // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one - // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center - // mP1 += rot/crv*mP3; - // - float rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. - if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles - if (f2 > 0.f) { - rot = PI - rot; // - } else { - rot = -PI - rot; - } - } - dP[kZ] = getTgl() / crv * rot; - } - - updateParams(dP); // apply corrections - - float &c00 = mC[kSigY2], &c10 = mC[kSigZY], &c11 = mC[kSigZ2], &c20 = mC[kSigSnpY], &c21 = mC[kSigSnpZ], - &c22 = mC[kSigSnp2], &c30 = mC[kSigTglY], &c31 = mC[kSigTglZ], &c32 = mC[kSigTglSnp], &c33 = mC[kSigTgl2], - &c40 = mC[kSigQ2PtY], &c41 = mC[kSigQ2PtZ], &c42 = mC[kSigQ2PtSnp], &c43 = mC[kSigQ2PtTgl], - &c44 = mC[kSigQ2Pt2]; - - // evaluate matrix in double prec. - double rinv = 1. / r1; - double r3inv = rinv * rinv * rinv; - double f24 = dx * b * B2C; // x2r/mP[kQ2Pt]; - double f02 = dx * r3inv; - double f04 = 0.5 * f24 * f02; - double f12 = f02 * getTgl() * f1; - double f14 = 0.5 * f24 * f12; // 0.5*f24*f02*getTgl()*f1; - double f13 = dx * rinv; - - // b = C*ft - double b00 = f02 * c20 + f04 * c40, b01 = f12 * c20 + f14 * c40 + f13 * c30; - double b02 = f24 * c40; - double b10 = f02 * c21 + f04 * c41, b11 = f12 * c21 + f14 * c41 + f13 * c31; - double b12 = f24 * c41; - double b20 = f02 * c22 + f04 * c42, b21 = f12 * c22 + f14 * c42 + f13 * c32; - double b22 = f24 * c42; - double b40 = f02 * c42 + f04 * c44, b41 = f12 * c42 + f14 * c44 + f13 * c43; - double b42 = f24 * c44; - double b30 = f02 * c32 + f04 * c43, b31 = f12 * c32 + f14 * c43 + f13 * c33; - double b32 = f24 * c43; - - // a = f*b = f*C*ft - double a00 = f02 * b20 + f04 * b40, a01 = f02 * b21 + f04 * b41, a02 = f02 * b22 + f04 * b42; - double a11 = f12 * b21 + f14 * b41 + f13 * b31, a12 = f12 * b22 + f14 * b42 + f13 * b32; - double a22 = f24 * b42; - - // F*C*Ft = C + (b + bt + a) - c00 += b00 + b00 + a00; - c10 += b10 + b01 + a01; - c20 += b20 + b02 + a02; - c30 += b30; - c40 += b40; - c11 += b11 + b11 + a11; - c21 += b21 + b12 + a12; - c31 += b31; - c41 += b41; - c22 += b22 + b22 + a22; - c32 += b32; - c42 += b42; - - checkCovariance(); - - return true; -} - -//______________________________________________________________ -bool TrackParCov::rotate(float alpha) -{ - // rotate to alpha frame - if (fabs(getSnp()) > Almost1) { - LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); - return false; - } - // - utils::BringToPMPi(alpha); - // - float ca = 0, sa = 0; - utils::sincos(alpha - getAlpha(), sa, ca); - float snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision - // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle - // direction in local frame is along the X axis - if ((csp * ca + snp * sa) < 0) { - //LOGF(WARNING,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa); - return false; - } - // - - float updSnp = snp * ca - csp * sa; - if (fabs(updSnp) > Almost1) { - LOGF(WARNING, "Rotation failed: new snp {:.2f}", updSnp); - return false; - } - float xold = getX(), yold = getY(); - setAlpha(alpha); - setX(xold * ca + yold * sa); - setY(-xold * sa + yold * ca); - setSnp(updSnp); - - if (fabs(csp) < Almost0) { - LOGF(WARNING, "Too small cosine value {:f}", csp); - csp = Almost0; - } - - float rr = (ca + snp / csp * sa); - - mC[kSigY2] *= (ca * ca); - mC[kSigZY] *= ca; - mC[kSigSnpY] *= ca * rr; - mC[kSigSnpZ] *= rr; - mC[kSigSnp2] *= rr * rr; - mC[kSigTglY] *= ca; - mC[kSigTglSnp] *= rr; - mC[kSigQ2PtY] *= ca; - mC[kSigQ2PtSnp] *= rr; - - checkCovariance(); - return true; -} - -//_______________________________________________________________________ -bool TrackParCov::propagateToDCA(const o2::dataformats::VertexBase& vtx, float b, o2::dataformats::DCA* dca, float maxD) -{ - // propagate track to DCA to the vertex - float sn, cs, alp = getAlpha(); - o2::utils::sincos(alp, sn, cs); - float x = getX(), y = getY(), snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); - float xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); - x -= xv; - y -= yv; - //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); - if (d > maxD) { - return false; - } - float crv = getCurvature(b); - float tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > Almost0) ? sn / tgfv : Almost1; - - x = xv * cs + yv * sn; - yv = -xv * sn + yv * cs; - xv = x; - - auto tmpT(*this); // operate on the copy to recover after the failure - alp += std::asin(sn); - if (!tmpT.rotate(alp) || !tmpT.propagateTo(xv, b)) { - LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; - tmpT.print(); - return false; - } - *this = tmpT; - if (dca) { - o2::utils::sincos(alp, sn, cs); - auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; - dca->set(getY() - yv, getZ() - zv, getSigmaY2() + s2ylocvtx, getSigmaZY(), getSigmaZ2() + vtx.getSigmaZ2()); - } - return true; -} - -//______________________________________________________________ -TrackParCov::TrackParCov(const array<float, 3>& xyz, const array<float, 3>& pxpypz, - const array<float, kLabCovMatSize>& cv, int charge, bool sectorAlpha) -{ - // construct track param and covariance from kinematics and lab errors - - // Alpha of the frame is defined as: - // sectorAlpha == false : -> angle of pt direction - // sectorAlpha == true : -> angle of the sector from X,Y coordinate for r>1 - // angle of pt direction for r==0 - // - // - constexpr float kSafe = 1e-5f; - float radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; - float alp = 0; - if (sectorAlpha || radPos2 < 1) { - alp = atan2f(pxpypz[1], pxpypz[0]); - } else { - alp = atan2f(xyz[1], xyz[0]); - } - if (sectorAlpha) { - alp = utils::Angle2Alpha(alp); - } - // - float sn, cs; - utils::sincos(alp, sn, cs); - // protection: avoid alpha being too close to 0 or +-pi/2 - if (fabs(sn) < 2.f * kSafe) { - if (alp > 0) { - alp += alp < PIHalf ? 2.f * kSafe : -2.f * kSafe; - } else { - alp += alp > -PIHalf ? -2.f * kSafe : 2.f * kSafe; - } - utils::sincos(alp, sn, cs); - } else if (fabs(cs) < 2.f * kSafe) { - if (alp > 0) { - alp += alp > PIHalf ? 2.f * kSafe : -2.f * kSafe; - } else { - alp += alp > -PIHalf ? 2.f * kSafe : -2.f * kSafe; - } - utils::sincos(alp, sn, cs); - } - // get the vertex of origin and the momentum - array<float, 3> ver{xyz[0], xyz[1], xyz[2]}; - array<float, 3> mom{pxpypz[0], pxpypz[1], pxpypz[2]}; - // - // Rotate to the local coordinate system - utils::RotateZ(ver, -alp); - utils::RotateZ(mom, -alp); - // - float pt = sqrt(mom[0] * mom[0] + mom[1] * mom[1]); - float ptI = 1.f / pt; - setX(ver[0]); - setAlpha(alp); - setY(ver[1]); - setZ(ver[2]); - setSnp(mom[1] * ptI); // cos(phi) - setTgl(mom[2] * ptI); // tg(lambda) - setAbsCharge(std::abs(charge)); - setQ2Pt(charge ? ptI * charge : ptI); - // - if (fabs(1.f - getSnp()) < kSafe) { - setSnp(1.f - kSafe); // Protection - } else if (fabs(-1.f - getSnp()) < kSafe) { - setSnp(-1.f + kSafe); // Protection - } - // - // Covariance matrix (formulas to be simplified) - float r = mom[0] * ptI; // cos(phi) - float cv34 = std::sqrt(cv[3] * cv[3] + cv[4] * cv[4]); - // - int special = 0; - float sgcheck = r * sn + getSnp() * cs; - if (fabs(sgcheck) > 1 - kSafe) { // special case: lab phi is +-pi/2 - special = 1; - sgcheck = sgcheck < 0 ? -1.f : 1.f; - } else if (fabs(sgcheck) < kSafe) { - sgcheck = cs < 0 ? -1.0f : 1.0f; - special = 2; // special case: lab phi is 0 - } - // - mC[kSigY2] = cv[0] + cv[2]; - mC[kSigZY] = (-cv[3] * sn) < 0 ? -cv34 : cv34; - mC[kSigZ2] = cv[5]; - // - float ptI2 = ptI * ptI; - float tgl2 = getTgl() * getTgl(); - if (special == 1) { - mC[kSigSnpY] = cv[6] * ptI; - mC[kSigSnpZ] = -sgcheck * cv[8] * r * ptI; - mC[kSigSnp2] = fabs(cv[9] * r * r * ptI2); - mC[kSigTglY] = (cv[10] * getTgl() - sgcheck * cv[15]) * ptI / r; - mC[kSigTglZ] = (cv[17] - sgcheck * cv[12] * getTgl()) * ptI; - mC[kSigTglSnp] = (-sgcheck * cv[18] + cv[13] * getTgl()) * r * ptI2; - mC[kSigTgl2] = fabs(cv[20] - 2 * sgcheck * cv[19] * mC[4] + cv[14] * tgl2) * ptI2; - mC[kSigQ2PtY] = cv[10] * ptI2 / r * charge; - mC[kSigQ2PtZ] = -sgcheck * cv[12] * ptI2 * charge; - mC[kSigQ2PtSnp] = cv[13] * r * ptI * ptI2 * charge; - mC[kSigQ2PtTgl] = (-sgcheck * cv[19] + cv[14] * getTgl()) * r * ptI2 * ptI; - mC[kSigQ2Pt2] = fabs(cv[14] * ptI2 * ptI2); - } else if (special == 2) { - mC[kSigSnpY] = -cv[10] * ptI * cs / sn; - mC[kSigSnpZ] = cv[12] * cs * ptI; - mC[kSigSnp2] = fabs(cv[14] * cs * cs * ptI2); - mC[kSigTglY] = (sgcheck * cv[6] * getTgl() - cv[15]) * ptI / sn; - mC[kSigTglZ] = (cv[17] - sgcheck * cv[8] * getTgl()) * ptI; - mC[kSigTglSnp] = (cv[19] - sgcheck * cv[13] * getTgl()) * cs * ptI2; - mC[kSigTgl2] = fabs(cv[20] - 2 * sgcheck * cv[18] * getTgl() + cv[9] * tgl2) * ptI2; - mC[kSigQ2PtY] = sgcheck * cv[6] * ptI2 / sn * charge; - mC[kSigQ2PtZ] = -sgcheck * cv[8] * ptI2 * charge; - mC[kSigQ2PtSnp] = -sgcheck * cv[13] * cs * ptI * ptI2 * charge; - mC[kSigQ2PtTgl] = (-sgcheck * cv[18] + cv[9] * getTgl()) * ptI2 * ptI * charge; - mC[kSigQ2Pt2] = fabs(cv[9] * ptI2 * ptI2); - } else { - double m00 = -sn; // m10=cs; - double m23 = -pt * (sn + getSnp() * cs / r), m43 = -pt * pt * (r * cs - getSnp() * sn); - double m24 = pt * (cs - getSnp() * sn / r), m44 = -pt * pt * (r * sn + getSnp() * cs); - double m35 = pt, m45 = -pt * pt * getTgl(); - // - m43 *= charge; - m44 *= charge; - m45 *= charge; - // - double a1 = cv[13] - cv[9] * (m23 * m44 + m43 * m24) / m23 / m43; - double a2 = m23 * m24 - m23 * (m23 * m44 + m43 * m24) / m43; - double a3 = m43 * m44 - m43 * (m23 * m44 + m43 * m24) / m23; - double a4 = cv[14] + 2. * cv[9]; - double a5 = m24 * m24 - 2. * m24 * m44 * m23 / m43; - double a6 = m44 * m44 - 2. * m24 * m44 * m43 / m23; - // - mC[kSigSnpY] = (cv[10] * m43 - cv[6] * m44) / (m24 * m43 - m23 * m44) / m00; - mC[kSigQ2PtY] = (cv[6] / m00 - mC[kSigSnpY] * m23) / m43; - mC[kSigTglY] = (cv[15] / m00 - mC[kSigQ2PtY] * m45) / m35; - mC[kSigSnpZ] = (cv[12] * m43 - cv[8] * m44) / (m24 * m43 - m23 * m44); - mC[kSigQ2PtZ] = (cv[8] - mC[kSigSnpZ] * m23) / m43; - mC[kSigTglZ] = cv[17] / m35 - mC[kSigQ2PtZ] * m45 / m35; - mC[kSigSnp2] = fabs((a4 * a3 - a6 * a1) / (a5 * a3 - a6 * a2)); - mC[kSigQ2Pt2] = fabs((a1 - a2 * mC[kSigSnp2]) / a3); - mC[kSigQ2PtSnp] = (cv[9] - mC[kSigSnp2] * m23 * m23 - mC[kSigQ2Pt2] * m43 * m43) / m23 / m43; - double b1 = cv[18] - mC[kSigQ2PtSnp] * m23 * m45 - mC[kSigQ2Pt2] * m43 * m45; - double b2 = m23 * m35; - double b3 = m43 * m35; - double b4 = cv[19] - mC[kSigQ2PtSnp] * m24 * m45 - mC[kSigQ2Pt2] * m44 * m45; - double b5 = m24 * m35; - double b6 = m44 * m35; - mC[kSigTglSnp] = (b4 - b6 * b1 / b3) / (b5 - b6 * b2 / b3); - mC[kSigQ2PtTgl] = b1 / b3 - b2 * mC[kSigTglSnp] / b3; - mC[kSigTgl2] = fabs((cv[20] - mC[kSigQ2Pt2] * (m45 * m45) - mC[kSigQ2PtTgl] * 2. * m35 * m45) / (m35 * m35)); - } - checkCovariance(); -} - -//____________________________________________________________ -bool TrackParCov::propagateTo(float xk, const array<float, 3>& b) -{ - //---------------------------------------------------------------- - // Extrapolate this track to the plane X=xk in the field b[]. - // - // X [cm] is in the "tracking coordinate system" of this track. - // b[]={Bx,By,Bz} [kG] is in the Global coordidate system. - //---------------------------------------------------------------- - - float dx = xk - getX(); - if (fabs(dx) < Almost0) { - return true; - } - // Do not propagate tracks outside the ALICE detector - if (fabs(dx) > 1e5 || fabs(getY()) > 1e5 || fabs(getZ()) > 1e5) { - LOGF(WARNING, "Anomalous track, target X:{:f}", xk); - // print(); - return false; - } - float crv = (fabs(b[2]) < Almost0) ? 0.f : getCurvature(b[2]); - float x2r = crv * dx; - float f1 = getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { - return false; - } - float r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { - return false; - } - float r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { - return false; - } - - float dy2dx = (f1 + f2) / (r1 + r2); - float step = (fabs(x2r) < 0.05f) ? dx * fabs(r2 + f2 * dy2dx) // chord - : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc - step *= std::sqrt(1.f + getTgl() * getTgl()); - // - // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System - array<float, 9> vecLab{0.f}; - if (!getPosDirGlo(vecLab)) { - return false; - } - // - // matrix transformed with Bz component only - float &c00 = mC[kSigY2], &c10 = mC[kSigZY], &c11 = mC[kSigZ2], &c20 = mC[kSigSnpY], &c21 = mC[kSigSnpZ], - &c22 = mC[kSigSnp2], &c30 = mC[kSigTglY], &c31 = mC[kSigTglZ], &c32 = mC[kSigTglSnp], &c33 = mC[kSigTgl2], - &c40 = mC[kSigQ2PtY], &c41 = mC[kSigQ2PtZ], &c42 = mC[kSigQ2PtSnp], &c43 = mC[kSigQ2PtTgl], - &c44 = mC[kSigQ2Pt2]; - // evaluate matrix in double prec. - double rinv = 1. / r1; - double r3inv = rinv * rinv * rinv; - double f24 = dx * b[2] * B2C; // x2r/track[kQ2Pt]; - double f02 = dx * r3inv; - double f04 = 0.5 * f24 * f02; - double f12 = f02 * getTgl() * f1; - double f14 = 0.5 * f24 * f12; // 0.5*f24*f02*getTgl()*f1; - double f13 = dx * rinv; - - // b = C*ft - double b00 = f02 * c20 + f04 * c40, b01 = f12 * c20 + f14 * c40 + f13 * c30; - double b02 = f24 * c40; - double b10 = f02 * c21 + f04 * c41, b11 = f12 * c21 + f14 * c41 + f13 * c31; - double b12 = f24 * c41; - double b20 = f02 * c22 + f04 * c42, b21 = f12 * c22 + f14 * c42 + f13 * c32; - double b22 = f24 * c42; - double b40 = f02 * c42 + f04 * c44, b41 = f12 * c42 + f14 * c44 + f13 * c43; - double b42 = f24 * c44; - double b30 = f02 * c32 + f04 * c43, b31 = f12 * c32 + f14 * c43 + f13 * c33; - double b32 = f24 * c43; - - // a = f*b = f*C*ft - double a00 = f02 * b20 + f04 * b40, a01 = f02 * b21 + f04 * b41, a02 = f02 * b22 + f04 * b42; - double a11 = f12 * b21 + f14 * b41 + f13 * b31, a12 = f12 * b22 + f14 * b42 + f13 * b32; - double a22 = f24 * b42; - - // F*C*Ft = C + (b + bt + a) - c00 += b00 + b00 + a00; - c10 += b10 + b01 + a01; - c20 += b20 + b02 + a02; - c30 += b30; - c40 += b40; - c11 += b11 + b11 + a11; - c21 += b21 + b12 + a12; - c31 += b31; - c41 += b41; - c22 += b22 + b22 + a22; - c32 += b32; - c42 += b42; - - checkCovariance(); - - // Rotate to the system where Bx=By=0. - float bxy2 = b[0] * b[0] + b[1] * b[1]; - float bt = std::sqrt(bxy2); - float cosphi = 1.f, sinphi = 0.f; - if (bt > Almost0) { - cosphi = b[0] / bt; - sinphi = b[1] / bt; - } - float bb = std::sqrt(bxy2 + b[2] * b[2]); - float costet = 1., sintet = 0.; - if (bb > Almost0) { - costet = b[2] / bb; - sintet = bt / bb; - } - array<float, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], - -sinphi * vecLab[0] + cosphi * vecLab[1], - sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], - costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], - -sinphi * vecLab[3] + cosphi * vecLab[4], - sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], - vecLab[6]}; - - // Do the helix step - float sgn = getSign(); - g3helx3(sgn * bb, step, vect); - - // Rotate back to the Global System - vecLab[0] = cosphi * costet * vect[0] - sinphi * vect[1] + cosphi * sintet * vect[2]; - vecLab[1] = sinphi * costet * vect[0] + cosphi * vect[1] + sinphi * sintet * vect[2]; - vecLab[2] = -sintet * vect[0] + costet * vect[2]; - - vecLab[3] = cosphi * costet * vect[3] - sinphi * vect[4] + cosphi * sintet * vect[5]; - vecLab[4] = sinphi * costet * vect[3] + cosphi * vect[4] + sinphi * sintet * vect[5]; - vecLab[5] = -sintet * vect[3] + costet * vect[5]; - - // Rotate back to the Tracking System - float sinalp = -vecLab[7], cosalp = vecLab[8]; - float t = cosalp * vecLab[0] - sinalp * vecLab[1]; - vecLab[1] = sinalp * vecLab[0] + cosalp * vecLab[1]; - vecLab[0] = t; - t = cosalp * vecLab[3] - sinalp * vecLab[4]; - vecLab[4] = sinalp * vecLab[3] + cosalp * vecLab[4]; - vecLab[3] = t; - - // Do the final correcting step to the target plane (linear approximation) - float x = vecLab[0], y = vecLab[1], z = vecLab[2]; - if (fabs(dx) > Almost0) { - if (fabs(vecLab[3]) < Almost0) { - return false; - } - dx = xk - vecLab[0]; - x += dx; - y += vecLab[4] / vecLab[3] * dx; - z += vecLab[5] / vecLab[3] * dx; - } - - // Calculate the track parameters - t = 1.f / std::sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); - setX(x); - setY(y); - setZ(z); - setSnp(vecLab[4] * t); - setTgl(vecLab[5] * t); - setQ2Pt(sgn * t / vecLab[6]); - - return true; -} - -//______________________________________________ -void TrackParCov::checkCovariance() -{ - // This function forces the diagonal elements of the covariance matrix to be positive. - // In case the diagonal element is bigger than the maximal allowed value, it is set to - // the limit and the off-diagonal elements that correspond to it are set to zero. - - mC[kSigY2] = fabs(mC[kSigY2]); - if (mC[kSigY2] > kCY2max) { - float scl = std::sqrt(kCY2max / mC[kSigY2]); - mC[kSigY2] = kCY2max; - mC[kSigZY] *= scl; - mC[kSigSnpY] *= scl; - mC[kSigTglY] *= scl; - mC[kSigQ2PtY] *= scl; - } - mC[kSigZ2] = fabs(mC[kSigZ2]); - if (mC[kSigZ2] > kCZ2max) { - float scl = std::sqrt(kCZ2max / mC[kSigZ2]); - mC[kSigZ2] = kCZ2max; - mC[kSigZY] *= scl; - mC[kSigSnpZ] *= scl; - mC[kSigTglZ] *= scl; - mC[kSigQ2PtZ] *= scl; - } - mC[kSigSnp2] = fabs(mC[kSigSnp2]); - if (mC[kSigSnp2] > kCSnp2max) { - float scl = std::sqrt(kCSnp2max / mC[kSigSnp2]); - mC[kSigSnp2] = kCSnp2max; - mC[kSigSnpY] *= scl; - mC[kSigSnpZ] *= scl; - mC[kSigTglSnp] *= scl; - mC[kSigQ2PtSnp] *= scl; - } - mC[kSigTgl2] = fabs(mC[kSigTgl2]); - if (mC[kSigTgl2] > kCTgl2max) { - float scl = std::sqrt(kCTgl2max / mC[kSigTgl2]); - mC[kSigTgl2] = kCTgl2max; - mC[kSigTglY] *= scl; - mC[kSigTglZ] *= scl; - mC[kSigTglSnp] *= scl; - mC[kSigQ2PtTgl] *= scl; - } - mC[kSigQ2Pt2] = fabs(mC[kSigQ2Pt2]); - if (mC[kSigQ2Pt2] > kC1Pt2max) { - float scl = std::sqrt(kC1Pt2max / mC[kSigQ2Pt2]); - mC[kSigQ2Pt2] = kC1Pt2max; - mC[kSigQ2PtY] *= scl; - mC[kSigQ2PtZ] *= scl; - mC[kSigQ2PtSnp] *= scl; - mC[kSigQ2PtTgl] *= scl; - } -} - -//______________________________________________ -void TrackParCov::resetCovariance(float s2) -{ - // Reset the covarince matrix to "something big" - double d0(kCY2max), d1(kCZ2max), d2(kCSnp2max), d3(kCTgl2max), d4(kC1Pt2max); - if (s2 > Almost0) { - d0 = getSigmaY2() * s2; - d1 = getSigmaZ2() * s2; - d2 = getSigmaSnp2() * s2; - d3 = getSigmaTgl2() * s2; - d4 = getSigma1Pt2() * s2; - if (d0 > kCY2max) { - d0 = kCY2max; - } - if (d1 > kCZ2max) { - d1 = kCZ2max; - } - if (d2 > kCSnp2max) { - d2 = kCSnp2max; - } - if (d3 > kCTgl2max) { - d3 = kCTgl2max; - } - if (d4 > kC1Pt2max) { - d4 = kC1Pt2max; - } - } - memset(mC, 0, kCovMatSize * sizeof(float)); - mC[kSigY2] = d0; - mC[kSigZ2] = d1; - mC[kSigSnp2] = d2; - mC[kSigTgl2] = d3; - mC[kSigQ2Pt2] = d4; -} - -//______________________________________________ -float TrackParCov::getPredictedChi2(const array<float, 2>& p, const array<float, 3>& cov) const -{ - // Estimate the chi2 of the space point "p" with the cov. matrix "cov" - auto sdd = static_cast<double>(getSigmaY2()) + static_cast<double>(cov[0]); - auto sdz = static_cast<double>(getSigmaZY()) + static_cast<double>(cov[1]); - auto szz = static_cast<double>(getSigmaZ2()) + static_cast<double>(cov[2]); - auto det = sdd * szz - sdz * sdz; - - if (fabs(det) < Almost0) { - return VeryBig; - } - - float d = getY() - p[0]; - float z = getZ() - p[1]; - - return (d * (szz * d - sdz * z) + z * (sdd * z - d * sdz)) / det; -} - -//______________________________________________ -void TrackParCov::buildCombinedCovMatrix(const TrackParCov& rhs, MatrixDSym5& cov) const -{ - // fill combined cov.matrix (NOT inverted) - cov(kY, kY) = static_cast<double>(getSigmaY2()) + static_cast<double>(rhs.getSigmaY2()); - cov(kZ, kY) = static_cast<double>(getSigmaZY()) + static_cast<double>(rhs.getSigmaZY()); - cov(kZ, kZ) = static_cast<double>(getSigmaZ2()) + static_cast<double>(rhs.getSigmaZ2()); - cov(kSnp, kY) = static_cast<double>(getSigmaSnpY()) + static_cast<double>(rhs.getSigmaSnpY()); - cov(kSnp, kZ) = static_cast<double>(getSigmaSnpZ()) + static_cast<double>(rhs.getSigmaSnpZ()); - cov(kSnp, kSnp) = static_cast<double>(getSigmaSnp2()) + static_cast<double>(rhs.getSigmaSnp2()); - cov(kTgl, kY) = static_cast<double>(getSigmaTglY()) + static_cast<double>(rhs.getSigmaTglY()); - cov(kTgl, kZ) = static_cast<double>(getSigmaTglZ()) + static_cast<double>(rhs.getSigmaTglZ()); - cov(kTgl, kSnp) = static_cast<double>(getSigmaTglSnp()) + static_cast<double>(rhs.getSigmaTglSnp()); - cov(kTgl, kTgl) = static_cast<double>(getSigmaTgl2()) + static_cast<double>(rhs.getSigmaTgl2()); - cov(kQ2Pt, kY) = static_cast<double>(getSigma1PtY()) + static_cast<double>(rhs.getSigma1PtY()); - cov(kQ2Pt, kZ) = static_cast<double>(getSigma1PtZ()) + static_cast<double>(rhs.getSigma1PtZ()); - cov(kQ2Pt, kSnp) = static_cast<double>(getSigma1PtSnp()) + static_cast<double>(rhs.getSigma1PtSnp()); - cov(kQ2Pt, kTgl) = static_cast<double>(getSigma1PtTgl()) + static_cast<double>(rhs.getSigma1PtTgl()); - cov(kQ2Pt, kQ2Pt) = static_cast<double>(getSigma1Pt2()) + static_cast<double>(rhs.getSigma1Pt2()); -} - -//______________________________________________ -float TrackParCov::getPredictedChi2(const TrackParCov& rhs) const -{ - MatrixDSym5 cov; // perform matrix operations in double! - return getPredictedChi2(rhs, cov); -} - -//______________________________________________ -float TrackParCov::getPredictedChi2(const TrackParCov& rhs, MatrixDSym5& covToSet) const -{ - // get chi2 wrt other track, which must be defined at the same parameters X,alpha - // Supplied non-initialized covToSet matrix is filled by inverse combined matrix for further use - - if (std::abs(getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { - LOG(ERROR) << "The reference Alpha of the tracks differ: " << getAlpha() << " : " << rhs.getAlpha(); - return 2. * HugeF; - } - if (std::abs(getX() - rhs.getX()) > FLT_EPSILON) { - LOG(ERROR) << "The reference X of the tracks differ: " << getX() << " : " << rhs.getX(); - return 2. * HugeF; - } - buildCombinedCovMatrix(rhs, covToSet); - if (!covToSet.Invert()) { - LOG(WARNING) << "Cov.matrix inversion failed: " << covToSet; - return 2. * HugeF; - } - double chi2diag = 0., chi2ndiag = 0., diff[kNParams]; - for (int i = kNParams; i--;) { - diff[i] = getParam(i) - rhs.getParam(i); - chi2diag += diff[i] * diff[i] * covToSet(i, i); - } - for (int i = kNParams; i--;) { - for (int j = i; j--;) { - chi2ndiag += diff[i] * diff[j] * covToSet(i, j); - } - } - return chi2diag + 2. * chi2ndiag; -} - -//______________________________________________ -bool TrackParCov::update(const TrackParCov& rhs, const MatrixDSym5& covInv) -{ - // update track with other track, the inverted combined cov matrix should be supplied - - // consider skipping this check, since it is usually already done upstream - if (std::abs(getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { - LOG(ERROR) << "The reference Alpha of the tracks differ: " << getAlpha() << " : " << rhs.getAlpha(); - return false; - } - if (std::abs(getX() - rhs.getX()) > FLT_EPSILON) { - LOG(ERROR) << "The reference X of the tracks differ: " << getX() << " : " << rhs.getX(); - return false; - } - - // gain matrix K = Cov0*H*(Cov0+Cov0)^-1 (for measurement matrix H=I) - MatrixDSym5 matC0; - matC0(kY, kY) = getSigmaY2(); - matC0(kZ, kY) = getSigmaZY(); - matC0(kZ, kZ) = getSigmaZ2(); - matC0(kSnp, kY) = getSigmaSnpY(); - matC0(kSnp, kZ) = getSigmaSnpZ(); - matC0(kSnp, kSnp) = getSigmaSnp2(); - matC0(kTgl, kY) = getSigmaTglY(); - matC0(kTgl, kZ) = getSigmaTglZ(); - matC0(kTgl, kSnp) = getSigmaTglSnp(); - matC0(kTgl, kTgl) = getSigmaTgl2(); - matC0(kQ2Pt, kY) = getSigma1PtY(); - matC0(kQ2Pt, kZ) = getSigma1PtZ(); - matC0(kQ2Pt, kSnp) = getSigma1PtSnp(); - matC0(kQ2Pt, kTgl) = getSigma1PtTgl(); - matC0(kQ2Pt, kQ2Pt) = getSigma1Pt2(); - MatrixD5 matK = matC0 * covInv; - - // updated state vector: x = K*(x1-x0) - // RS: why SMatix, SVector does not provide multiplication operators ??? - double diff[kNParams]; - for (int i = kNParams; i--;) { - diff[i] = rhs.getParam(i) - getParam(i); - } - for (int i = kNParams; i--;) { - for (int j = kNParams; j--;) { - updateParam(matK(i, j) * diff[j], i); - } - } - - // updated covariance: Cov0 = Cov0 - K*Cov0 - matK *= ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepStd<double, kNParams>>(matC0); - mC[kSigY2] -= matK(kY, kY); - mC[kSigZY] -= matK(kZ, kY); - mC[kSigZ2] -= matK(kZ, kZ); - mC[kSigSnpY] -= matK(kSnp, kY); - mC[kSigSnpZ] -= matK(kSnp, kZ); - mC[kSigSnp2] -= matK(kSnp, kSnp); - mC[kSigTglY] -= matK(kTgl, kY); - mC[kSigTglZ] -= matK(kTgl, kZ); - mC[kSigTglSnp] -= matK(kTgl, kSnp); - mC[kSigTgl2] -= matK(kTgl, kTgl); - mC[kSigQ2PtY] -= matK(kQ2Pt, kY); - mC[kSigQ2PtZ] -= matK(kQ2Pt, kZ); - mC[kSigQ2PtSnp] -= matK(kQ2Pt, kSnp); - mC[kSigQ2PtTgl] -= matK(kQ2Pt, kTgl); - mC[kSigQ2Pt2] -= matK(kQ2Pt, kQ2Pt); - - return true; -} - -//______________________________________________ -bool TrackParCov::update(const TrackParCov& rhs) -{ - // update track with other track - MatrixDSym5 covI; // perform matrix operations in double! - buildCombinedCovMatrix(rhs, covI); - if (!covI.Invert()) { - LOG(WARNING) << "Cov.matrix inversion failed: " << covI; - return false; - } - return update(rhs, covI); -} - -//______________________________________________ -bool TrackParCov::update(const array<float, 2>& p, const array<float, 3>& cov) -{ - // Update the track parameters with the space point "p" having - // the covariance matrix "cov" - - float &cm00 = mC[kSigY2], &cm10 = mC[kSigZY], &cm11 = mC[kSigZ2], &cm20 = mC[kSigSnpY], &cm21 = mC[kSigSnpZ], - &cm22 = mC[kSigSnp2], &cm30 = mC[kSigTglY], &cm31 = mC[kSigTglZ], &cm32 = mC[kSigTglSnp], &cm33 = mC[kSigTgl2], - &cm40 = mC[kSigQ2PtY], &cm41 = mC[kSigQ2PtZ], &cm42 = mC[kSigQ2PtSnp], &cm43 = mC[kSigQ2PtTgl], - &cm44 = mC[kSigQ2Pt2]; - - // use double precision? - double r00 = static_cast<double>(cov[0]) + static_cast<double>(cm00); - double r01 = static_cast<double>(cov[1]) + static_cast<double>(cm10); - double r11 = static_cast<double>(cov[2]) + static_cast<double>(cm11); - double det = r00 * r11 - r01 * r01; - - if (fabs(det) < Almost0) { - return false; - } - double detI = 1. / det; - double tmp = r00; - r00 = r11 * detI; - r11 = tmp * detI; - r01 = -r01 * detI; - - double k00 = cm00 * r00 + cm10 * r01, k01 = cm00 * r01 + cm10 * r11; - double k10 = cm10 * r00 + cm11 * r01, k11 = cm10 * r01 + cm11 * r11; - double k20 = cm20 * r00 + cm21 * r01, k21 = cm20 * r01 + cm21 * r11; - double k30 = cm30 * r00 + cm31 * r01, k31 = cm30 * r01 + cm31 * r11; - double k40 = cm40 * r00 + cm41 * r01, k41 = cm40 * r01 + cm41 * r11; - - float dy = p[kY] - getY(), dz = p[kZ] - getZ(); - float dsnp = k20 * dy + k21 * dz; - if (fabs(getSnp() + dsnp) > Almost1) { - return false; - } - - float dP[kNParams] = {float(k00 * dy + k01 * dz), float(k10 * dy + k11 * dz), dsnp, float(k30 * dy + k31 * dz), - float(k40 * dy + k41 * dz)}; - updateParams(dP); - - double c01 = cm10, c02 = cm20, c03 = cm30, c04 = cm40; - double c12 = cm21, c13 = cm31, c14 = cm41; - - cm00 -= k00 * cm00 + k01 * cm10; - cm10 -= k00 * c01 + k01 * cm11; - cm20 -= k00 * c02 + k01 * c12; - cm30 -= k00 * c03 + k01 * c13; - cm40 -= k00 * c04 + k01 * c14; - - cm11 -= k10 * c01 + k11 * cm11; - cm21 -= k10 * c02 + k11 * c12; - cm31 -= k10 * c03 + k11 * c13; - cm41 -= k10 * c04 + k11 * c14; - - cm22 -= k20 * c02 + k21 * c12; - cm32 -= k20 * c03 + k21 * c13; - cm42 -= k20 * c04 + k21 * c14; - - cm33 -= k30 * c03 + k31 * c13; - cm43 -= k30 * c04 + k31 * c14; - - cm44 -= k40 * c04 + k41 * c14; - - checkCovariance(); - - return true; -} - -//______________________________________________ -bool TrackParCov::correctForMaterial(float x2x0, float xrho, float mass, bool anglecorr, float dedx) -{ - //------------------------------------------------------------------ - // This function corrects the track parameters for the crossed material. - // "x2x0" - X/X0, the thickness in units of the radiation length. - // "xrho" - is the product length*density (g/cm^2). - // It should be passed as negative when propagating tracks - // from the intreaction point to the outside of the central barrel. - // "mass" - the mass of this particle (GeV/c^2). - // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly - // "anglecorr" - switch for the angular correction - //------------------------------------------------------------------ - constexpr float kMSConst2 = 0.0136f * 0.0136f; - constexpr float kMaxELossFrac = 0.3f; // max allowed fractional eloss - constexpr float kMinP = 0.01f; // kill below this momentum - - float& fC22 = mC[kSigSnp2]; - float& fC33 = mC[kSigTgl2]; - float& fC43 = mC[kSigQ2PtTgl]; - float& fC44 = mC[kSigQ2Pt2]; - // - float csp2 = (1.f - getSnp()) * (1.f + getSnp()); // cos(phi)^2 - float cst2I = (1.f + getTgl() * getTgl()); // 1/cos(lambda)^2 - // Apply angle correction, if requested - if (anglecorr) { - float angle = std::sqrt(cst2I / (csp2)); - x2x0 *= angle; - xrho *= angle; - } - - float p = getP(); - float p2 = p * p, mass2 = mass * mass; - float e2 = p2 + mass2; - float beta2 = p2 / e2; - - // Calculating the multiple scattering corrections****************** - float cC22(0.f), cC33(0.f), cC43(0.f), cC44(0.f); - if (x2x0 != 0.f) { - float theta2 = kMSConst2 / (beta2 * p2) * fabs(x2x0); - if (getAbsCharge() != 1) { - theta2 *= getAbsCharge() * getAbsCharge(); - } - if (theta2 > PI * PI) { - return false; - } - float fp34 = getTgl() * getCharge2Pt(); - float t2c2I = theta2 * cst2I; - cC22 = t2c2I * csp2; - cC33 = t2c2I * cst2I; - cC43 = t2c2I * fp34; - cC44 = theta2 * fp34 * fp34; - // optimes this - // cC22 = theta2*((1.-getSnp())*(1.+getSnp()))*(1. + getTgl()*getTgl()); - // cC33 = theta2*(1. + getTgl()*getTgl())*(1. + getTgl()*getTgl()); - // cC43 = theta2*getTgl()*getQ2Pt()*(1. + getTgl()*getTgl()); - // cC44 = theta2*getTgl()*getQ2Pt()*getTgl()*getQ2Pt(); - } - - // Calculating the energy loss corrections************************ - float cP4 = 1.f; - if ((xrho != 0.f) && (beta2 < 1.f)) { - if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / fabs(mass)); - if (getAbsCharge() != 1) { - dedx *= getAbsCharge() * getAbsCharge(); - } - } - - float dE = dedx * xrho; - float e = std::sqrt(e2); - if (fabs(dE) > kMaxELossFrac * e) { - return false; // 30% energy loss is too much! - } - float eupd = e + dE; - float pupd2 = eupd * eupd - mass2; - if (pupd2 < kMinP * kMinP) { - return false; - } - cP4 = p / std::sqrt(pupd2); - // - // Approximate energy loss fluctuation (M.Ivanov) - constexpr float knst = 0.07f; // To be tuned. - float sigmadE = knst * std::sqrt(fabs(dE)) * e / p2 * getCharge2Pt(); - cC44 += sigmadE * sigmadE; - } - - // Applying the corrections***************************** - fC22 += cC22; - fC33 += cC33; - fC43 += cC43; - fC44 += cC44; - setQ2Pt(getQ2Pt() * cP4); - - checkCovariance(); - - return true; -} - -//______________________________________________________________ -bool TrackParCov::getCovXYZPxPyPzGlo(std::array<float, 21>& cv) const -{ - //--------------------------------------------------------------------- - // This function returns the global covariance matrix of the track params - // - // Cov(x,x) ... : cv[0] - // Cov(y,x) ... : cv[1] cv[2] - // Cov(z,x) ... : cv[3] cv[4] cv[5] - // Cov(px,x)... : cv[6] cv[7] cv[8] cv[9] - // Cov(py,x)... : cv[10] cv[11] cv[12] cv[13] cv[14] - // Cov(pz,x)... : cv[15] cv[16] cv[17] cv[18] cv[19] cv[20] - // - // Results for (nearly) straight tracks are meaningless ! - //--------------------------------------------------------------------- - if (std::abs(getQ2Pt()) <= Almost0 || std::abs(getSnp()) > Almost1) { - for (int i = 0; i < 21; i++) { - cv[i] = 0.; - } - return false; - } - - auto pt = getPt(); - float sn, cs; - o2::utils::sincos(getAlpha(), sn, cs); - auto r = std::sqrt((1. - getSnp()) * (1. + getSnp())); - auto m00 = -sn, m10 = cs; - auto m23 = -pt * (sn + getSnp() * cs / r), m43 = -pt * pt * (r * cs - getSnp() * sn); - auto m24 = pt * (cs - getSnp() * sn / r), m44 = -pt * pt * (r * sn + getSnp() * cs); - auto m35 = pt, m45 = -pt * pt * getTgl(); - - if (getSign() < 0) { - m43 = -m43; - m44 = -m44; - m45 = -m45; - } - - cv[0] = mC[0] * m00 * m00; - cv[1] = mC[0] * m00 * m10; - cv[2] = mC[0] * m10 * m10; - cv[3] = mC[1] * m00; - cv[4] = mC[1] * m10; - cv[5] = mC[2]; - cv[6] = m00 * (mC[3] * m23 + mC[10] * m43); - cv[7] = m10 * (mC[3] * m23 + mC[10] * m43); - cv[8] = mC[4] * m23 + mC[11] * m43; - cv[9] = m23 * (mC[5] * m23 + mC[12] * m43) + m43 * (mC[12] * m23 + mC[14] * m43); - cv[10] = m00 * (mC[3] * m24 + mC[10] * m44); - cv[11] = m10 * (mC[3] * m24 + mC[10] * m44); - cv[12] = mC[4] * m24 + mC[11] * m44; - cv[13] = m23 * (mC[5] * m24 + mC[12] * m44) + m43 * (mC[12] * m24 + mC[14] * m44); - cv[14] = m24 * (mC[5] * m24 + mC[12] * m44) + m44 * (mC[12] * m24 + mC[14] * m44); - cv[15] = m00 * (mC[6] * m35 + mC[10] * m45); - cv[16] = m10 * (mC[6] * m35 + mC[10] * m45); - cv[17] = mC[7] * m35 + mC[11] * m45; - cv[18] = m23 * (mC[8] * m35 + mC[12] * m45) + m43 * (mC[13] * m35 + mC[14] * m45); - cv[19] = m24 * (mC[8] * m35 + mC[12] * m45) + m44 * (mC[13] * m35 + mC[14] * m45); - cv[20] = m35 * (mC[9] * m35 + mC[13] * m45) + m45 * (mC[13] * m35 + mC[14] * m45); - - return true; -} - -#ifndef GPUCA_ALIGPUCODE -//______________________________________________________________ -std::string TrackParCov::asString() const -{ - return TrackPar::asString() + - fmt::format( - "\n{:7s} {:+.3e}\n" - "{:7s} {:+.3e} {:+.3e}\n" - "{:7s} {:+.3e} {:+.3e} {:+.3e}\n" - "{:7s} {:+.3e} {:+.3e} {:+.3e} {:+.3e}\n" - "{:7s} {:+.3e} {:+.3e} {:+.3e} {:+.3e} {:+.3e}", - "CovMat:", mC[kSigY2], "", mC[kSigZY], mC[kSigZ2], "", mC[kSigSnpY], mC[kSigSnpZ], mC[kSigSnp2], "", mC[kSigTglY], - mC[kSigTglZ], mC[kSigTglSnp], mC[kSigTgl2], "", mC[kSigQ2PtY], mC[kSigQ2PtZ], mC[kSigQ2PtSnp], mC[kSigQ2PtTgl], - mC[kSigQ2Pt2]); -} - -//______________________________________________________________ -void TrackParCov::print() const -{ - // print parameters - printf("%s\n", asString().c_str()); -} -#endif - -//================================================= -// -// Aux. methods for tracks manipulation -// -//================================================= - -void o2::track::g3helx3(float qfield, float step, array<float, 7>& vect) -{ - /****************************************************************** - * * - * GEANT3 tracking routine in a constant field oriented * - * along axis 3 * - * Tracking is performed with a conventional * - * helix step method * - * * - * Authors R.Brun, M.Hansroul ********* * - * Rewritten V.Perevoztchikov * - * * - * Rewritten in C++ by I.Belikov * - * * - * qfield (kG) - particle charge times magnetic field * - * step (cm) - step length along the helix * - * vect[7](cm,GeV/c) - input/output x, y, z, px/p, py/p ,pz/p, p * - * * - ******************************************************************/ - const int ix = 0, iy = 1, iz = 2, ipx = 3, ipy = 4, ipz = 5, ipp = 6; - constexpr float kOvSqSix = 0.408248f; // std::sqrt(1./6.); - - float cosx = vect[ipx], cosy = vect[ipy], cosz = vect[ipz]; - - float rho = qfield * B2C / vect[ipp]; - float tet = rho * step; - - float tsint, sintt, sint, cos1t; - if (fabs(tet) > 0.03f) { - sint = sinf(tet); - sintt = sint / tet; - tsint = (tet - sint) / tet; - float t = sinf(0.5f * tet); - cos1t = 2 * t * t / tet; - } else { - tsint = tet * tet / 6.f; - sintt = (1.f - tet * kOvSqSix) * (1.f + tet * kOvSqSix); // 1.- tsint; - sint = tet * sintt; - cos1t = 0.5f * tet; - } - - float f1 = step * sintt; - float f2 = step * cos1t; - float f3 = step * tsint * cosz; - float f4 = -tet * cos1t; - float f5 = sint; - - vect[ix] += f1 * cosx - f2 * cosy; - vect[iy] += f1 * cosy + f2 * cosx; - vect[iz] += f1 * cosz + f3; - - vect[ipx] += f4 * cosx - f5 * cosy; - vect[ipy] += f4 * cosy + f5 * cosx; -} - -//____________________________________________________ -float o2::track::BetheBlochSolid(float bg, float rho, float kp1, float kp2, float meanI, float meanZA) -{ - // - // This is the parameterization of the Bethe-Bloch formula inspired by Geant. - // - // bg - beta*gamma - // rho - density [g/cm^3] - // kp1 - density effect first junction point - // kp2 - density effect second junction point - // meanI - mean excitation energy [GeV] - // meanZA - mean Z/A - // - // The default values for the kp* parameters are for silicon. - // The returned value is in [GeV/(g/cm^2)]. - // - constexpr float mK = 0.307075e-3f; // [GeV*cm^2/g] - constexpr float me = 0.511e-3f; // [GeV/c^2] - kp1 *= 2.303f; - kp2 *= 2.303f; - float bg2 = bg * bg; - float maxT = 2.f * me * bg2; // neglecting the electron mass - - //*** Density effect - float d2 = 0.; - const float x = log(bg); - const float lhwI = log(28.816 * 1e-9 * std::sqrt(rho * meanZA) / meanI); - if (x > kp2) { - d2 = lhwI + x - 0.5; - } else if (x > kp1) { - double r = (kp2 - x) / (kp2 - kp1); - d2 = lhwI + x - 0.5 + (0.5 - lhwI - kp1) * r * r * r; - } - return mK * meanZA * (1 + bg2) / bg2 * (0.5 * log(2 * me * bg2 * maxT / (meanI * meanI)) - bg2 / (1 + bg2) - d2); -} diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx new file mode 100644 index 0000000000000..b84a65b506d35 --- /dev/null +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -0,0 +1,742 @@ +// 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 TrackParametrization.cxx +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since Oct 1, 2020 +/// @brief + +// 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 "ReconstructionDataFormats/TrackParametrization.h" +#include "ReconstructionDataFormats/Vertex.h" +#include "ReconstructionDataFormats/DCA.h" +#include <FairLogger.h> +#include <iostream> +#include "Math/SMatrix.h" +#include <fmt/printf.h> +#include "Framework/Logger.h" + +using std::array; +using namespace o2::constants::math; + +namespace o2 +{ +namespace track +{ + +//______________________________________________________________ +template <typename value_T> +TrackParametrization<value_T>::TrackParametrization(const array<value_t, 3>& xyz, const array<value_t, 3>& pxpypz, int charge, bool sectorAlpha) + : mX{0.f}, mAlpha{0.f}, mP{0.f} +{ + // construct track param from kinematics + + // Alpha of the frame is defined as: + // sectorAlpha == false : -> angle of pt direction + // sectorAlpha == true : -> angle of the sector from X,Y coordinate for r>1 + // angle of pt direction for r==0 + // + // + constexpr value_t kSafe = 1e-5f; + value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; + value_t alp = 0; + if (sectorAlpha || radPos2 < 1) { + alp = atan2f(pxpypz[1], pxpypz[0]); + } else { + alp = atan2f(xyz[1], xyz[0]); + } + if (sectorAlpha) { + alp = utils::Angle2Alpha(alp); + } + // + value_t sn, cs; + utils::sincos(alp, sn, cs); + // protection: avoid alpha being too close to 0 or +-pi/2 + if (fabs(sn) < 2 * kSafe) { + if (alp > 0) { + alp += alp < PIHalf ? 2 * kSafe : -2 * kSafe; + } else { + alp += alp > -PIHalf ? -2 * kSafe : 2 * kSafe; + } + utils::sincos(alp, sn, cs); + } else if (fabs(cs) < 2 * kSafe) { + if (alp > 0) { + alp += alp > PIHalf ? 2 * kSafe : -2 * kSafe; + } else { + alp += alp > -PIHalf ? 2 * kSafe : -2 * kSafe; + } + utils::sincos(alp, sn, cs); + } + // get the vertex of origin and the momentum + array<value_t, 3> ver{xyz[0], xyz[1], xyz[2]}; + array<value_t, 3> mom{pxpypz[0], pxpypz[1], pxpypz[2]}; + // + // Rotate to the local coordinate system + utils::RotateZ(ver, -alp); + utils::RotateZ(mom, -alp); + // + value_t ptI = 1.f / sqrt(mom[0] * mom[0] + mom[1] * mom[1]); + mX = ver[0]; + mAlpha = alp; + mP[kY] = ver[1]; + mP[kZ] = ver[2]; + mP[kSnp] = mom[1] * ptI; + mP[kTgl] = mom[2] * ptI; + mAbsCharge = std::abs(charge); + mP[kQ2Pt] = charge ? ptI * charge : ptI; + // + if (fabs(1 - getSnp()) < kSafe) { + mP[kSnp] = 1. - kSafe; // Protection + } else if (fabs(-1 - getSnp()) < kSafe) { + mP[kSnp] = -1. + kSafe; // Protection + } + // +} + +//_______________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::getPxPyPzGlo(array<value_t, 3>& pxyz) const +{ + // track momentum + if (fabs(getQ2Pt()) < Almost0 || fabs(getSnp()) > Almost1) { + return false; + } + value_t cs, sn, pt = getPt(); + value_t r = std::sqrt((1.f - getSnp()) * (1.f + getSnp())); + utils::sincos(getAlpha(), sn, cs); + pxyz[0] = pt * (r * cs - getSnp() * sn); + pxyz[1] = pt * (getSnp() * cs + r * sn); + pxyz[2] = pt * getTgl(); + return true; +} + +//____________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::getPosDirGlo(array<value_t, 9>& posdirp) const +{ + // fill vector with lab x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha + value_t ptI = fabs(getQ2Pt()); + value_t snp = getSnp(); + if (ptI < Almost0 || fabs(snp) > Almost1) { + return false; + } + value_t &sn = posdirp[7], &cs = posdirp[8]; + value_t csp = std::sqrt((1.f - snp) * (1.f + snp)); + value_t cstht = std::sqrt(1.f + getTgl() * getTgl()); + value_t csthti = 1.f / cstht; + utils::sincos(getAlpha(), sn, cs); + posdirp[0] = getX() * cs - getY() * sn; + posdirp[1] = getX() * sn + getY() * cs; + posdirp[2] = getZ(); + posdirp[3] = (csp * cs - snp * sn) * csthti; // px/p + posdirp[4] = (snp * cs + csp * sn) * csthti; // py/p + posdirp[5] = getTgl() * csthti; // pz/p + posdirp[6] = cstht / ptI; // p + return true; +} + +//______________________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::rotateParam(value_t alpha) +{ + // rotate to alpha frame + if (fabs(getSnp()) > Almost1) { + LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); + return false; + } + // + utils::BringToPMPi(alpha); + // + value_t ca = 0, sa = 0; + utils::sincos(alpha - getAlpha(), sa, ca); + value_t snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision + // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle + // direction in local frame is along the X axis + if ((csp * ca + snp * sa) < 0) { + //LOGF(WARNING,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa); + return false; + } + // + value_t tmp = snp * ca - csp * sa; + if (fabs(tmp) > Almost1) { + LOGF(WARNING, "Rotation failed: new snp {:.2f}", tmp); + return false; + } + value_t xold = getX(), yold = getY(); + mAlpha = alpha; + mX = xold * ca + yold * sa; + mP[kY] = -xold * sa + yold * ca; + mP[kSnp] = tmp; + return true; +} + +//____________________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const array<value_t, 3>& b) +{ + //---------------------------------------------------------------- + // Extrapolate this track params (w/o cov matrix) to the plane X=xk in the field b[]. + // + // X [cm] is in the "tracking coordinate system" of this track. + // b[]={Bx,By,Bz} [kG] is in the Global coordidate system. + //---------------------------------------------------------------- + + value_t dx = xk - getX(); + if (fabs(dx) < Almost0) { + return true; + } + // Do not propagate tracks outside the ALICE detector + if (fabs(dx) > 1e5 || fabs(getY()) > 1e5 || fabs(getZ()) > 1e5) { + LOGF(WARNING, "Anomalous track, target X:{:f}", xk); + // print(); + return false; + } + value_t crv = getCurvature(b[2]); + value_t x2r = crv * dx; + value_t f1 = getSnp(), f2 = f1 + x2r; + if (fabs(f1) > Almost1 || fabs(f2) > Almost1) { + return false; + } + value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); + if (fabs(r1) < Almost0) { + return false; + } + value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); + if (fabs(r2) < Almost0) { + return false; + } + value_t dy2dx = (f1 + f2) / (r1 + r2); + value_t step = (fabs(x2r) < 0.05f) ? dx * fabs(r2 + f2 * dy2dx) // chord + : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc + step *= std::sqrt(1.f + getTgl() * getTgl()); + // + // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System + array<value_t, 9> vecLab{0.f}; + if (!getPosDirGlo(vecLab)) { + return false; + } + + // rotate to the system where Bx=By=0. + value_t bxy2 = b[0] * b[0] + b[1] * b[1]; + value_t bt = std::sqrt(bxy2); + value_t cosphi = 1.f, sinphi = 0.f; + if (bt > Almost0) { + cosphi = b[0] / bt; + sinphi = b[1] / bt; + } + value_t bb = std::sqrt(bxy2 + b[2] * b[2]); + value_t costet = 1., sintet = 0.; + if (bb > Almost0) { + costet = b[2] / bb; + sintet = bt / bb; + } + array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], + -sinphi * vecLab[0] + cosphi * vecLab[1], + sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], + costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], + -sinphi * vecLab[3] + cosphi * vecLab[4], + sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], + vecLab[6]}; + + // Do the helix step + value_t q = getCharge(); + g3helx3(q * bb, step, vect); + + // rotate back to the Global System + vecLab[0] = cosphi * costet * vect[0] - sinphi * vect[1] + cosphi * sintet * vect[2]; + vecLab[1] = sinphi * costet * vect[0] + cosphi * vect[1] + sinphi * sintet * vect[2]; + vecLab[2] = -sintet * vect[0] + costet * vect[2]; + + vecLab[3] = cosphi * costet * vect[3] - sinphi * vect[4] + cosphi * sintet * vect[5]; + vecLab[4] = sinphi * costet * vect[3] + cosphi * vect[4] + sinphi * sintet * vect[5]; + vecLab[5] = -sintet * vect[3] + costet * vect[5]; + + // rotate back to the Tracking System + value_t sinalp = -vecLab[7], cosalp = vecLab[8]; + value_t t = cosalp * vecLab[0] - sinalp * vecLab[1]; + vecLab[1] = sinalp * vecLab[0] + cosalp * vecLab[1]; + vecLab[0] = t; + t = cosalp * vecLab[3] - sinalp * vecLab[4]; + vecLab[4] = sinalp * vecLab[3] + cosalp * vecLab[4]; + vecLab[3] = t; + + // Do the final correcting step to the target plane (linear approximation) + value_t x = vecLab[0], y = vecLab[1], z = vecLab[2]; + if (fabs(dx) > Almost0) { + if (fabs(vecLab[3]) < Almost0) { + return false; + } + dx = xk - vecLab[0]; + x += dx; + y += vecLab[4] / vecLab[3] * dx; + z += vecLab[5] / vecLab[3] * dx; + } + + // Calculate the track parameters + t = 1.f / std::sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); + mX = x; + mP[kY] = y; + mP[kZ] = z; + mP[kSnp] = vecLab[4] * t; + mP[kTgl] = vecLab[5] * t; + mP[kQ2Pt] = q * t / vecLab[6]; + + return true; +} + +//____________________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) +{ + //---------------------------------------------------------------- + // propagate this track to the plane X=xk (cm) in the field "b" (kG) + // Only parameters are propagated, not the matrix. To be used for small + // distances only (<mm, i.e. misalignment) + //---------------------------------------------------------------- + value_t dx = xk - getX(); + if (fabs(dx) < Almost0) { + return true; + } + value_t crv = (fabs(b) < Almost0) ? 0.f : getCurvature(b); + value_t x2r = crv * dx; + value_t f1 = getSnp(), f2 = f1 + x2r; + if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + return false; + } + value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); + if (fabs(r1) < Almost0) { + return false; + } + value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); + if (fabs(r2) < Almost0) { + return false; + } + mX = xk; + double dy2dx = (f1 + f2) / (r1 + r2); + mP[kY] += dx * dy2dx; + mP[kSnp] += x2r; + if (fabs(x2r) < 0.05f) { + mP[kZ] += dx * (r2 + f2 * dy2dx) * getTgl(); + } else { + // for small dx/R the linear apporximation of the arc by the segment is OK, + // but at large dx/R the error is very large and leads to incorrect Z propagation + // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi + // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2) + // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one + // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center + // track1 += rot/crv*track3; + // + value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. + if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles + if (f2 > 0.f) { + rot = PI - rot; // + } else { + rot = -PI - rot; + } + } + mP[kZ] += getTgl() / crv * rot; + } + return true; +} + +//_______________________________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, std::array<value_t, 2>* dca, value_t maxD) +{ + // propagate track to DCA to the vertex + value_t sn, cs, alp = getAlpha(); + o2::utils::sincos(alp, sn, cs); + value_t x = getX(), y = getY(), snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + value_t xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); + x -= xv; + y -= yv; + //Estimate the impact parameter neglecting the track curvature + Double_t d = std::abs(x * snp - y * csp); + if (d > maxD) { + return false; + } + value_t crv = getCurvature(b); + value_t tgfv = -(crv * x - snp) / (crv * y + csp); + sn = tgfv / std::sqrt(1.f + tgfv * tgfv); + cs = std::sqrt((1. - sn) * (1. + sn)); + cs = (std::abs(tgfv) > Almost0) ? sn / tgfv : Almost1; + + x = xv * cs + yv * sn; + yv = -xv * sn + yv * cs; + xv = x; + + auto tmpT(*this); // operate on the copy to recover after the failure + alp += std::asin(sn); + if (!tmpT.rotateParam(alp) || !tmpT.propagateParamTo(xv, b)) { + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " + << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; + tmpT.printParam(); + return false; + } + *this = tmpT; + if (dca) { + (*dca)[0] = getY() - yv; + (*dca)[1] = getZ() - zv; + } + return true; +} + +//____________________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const +{ + //---------------------------------------------------------------- + // estimate Y,Z in tracking frame at given X + //---------------------------------------------------------------- + value_t dx = xk - getX(); + if (fabs(dx) < Almost0) { + return true; + } + value_t crv = getCurvature(b); + value_t x2r = crv * dx; + value_t f1 = getSnp(), f2 = f1 + x2r; + if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + return false; + } + value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); + if (fabs(r1) < Almost0) { + return false; + } + value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); + if (fabs(r2) < Almost0) { + return false; + } + double dy2dx = (f1 + f2) / (r1 + r2); + y = mP[kY] + dx * dy2dx; + z = mP[kZ]; + if (fabs(x2r) < 0.05f) { + z += dx * (r2 + f2 * dy2dx) * getTgl(); + } else { + // for small dx/R the linear apporximation of the arc by the segment is OK, + // but at large dx/R the error is very large and leads to incorrect Z propagation + // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi + // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2) + // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one + // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center + // track1 += rot/crv*track3; + // + value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. + if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles + if (f2 > 0.f) { + rot = PI - rot; // + } else { + rot = -PI - rot; + } + } + z += getTgl() / crv * rot; + } + return true; +} + +//______________________________________________________________ +template <typename value_T> +void TrackParametrization<value_T>::invertParam() +{ + // Transform this track to the local coord. system rotated by 180 deg. + mX = -mX; + mAlpha += PI; + utils::BringToPMPi(mAlpha); + // + mP[0] = -mP[0]; + mP[3] = -mP[3]; + mP[4] = -mP[4]; + // +} + +//______________________________________________________________ +template <typename value_T> +typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getZAt(value_t xk, value_t b) const +{ + ///< this method is just an alias for obtaining Z @ X in the tree->Draw() + value_t y, z; + return getYZAt(xk, b, y, z) ? z : -9999.; +} + +//______________________________________________________________ +template <typename value_T> +typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getYAt(value_t xk, value_t b) const +{ + ///< this method is just an alias for obtaining Z @ X in the tree->Draw() + value_t y, z; + return getYZAt(xk, b, y, z) ? y : -9999.; +} + +#ifndef GPUCA_ALIGPUCODE +//_____________________________________________________________ +template <typename value_T> +std::string TrackParametrization<value_T>::asString() const +{ + // print parameters as string + return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d} {:s}", + getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName()); +} + +//______________________________________________________________ +template <typename value_T> +void TrackParametrization<value_T>::printParam() const +{ + // print parameters + printf("%s\n", asString().c_str()); +} +#endif + +//______________________________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz, o2::track::DirType dir) const +{ + // Get local X of the track position estimated at the radius lab radius r. + // The track curvature is accounted exactly + // + // The flag "dir" can be used to remove the ambiguity of which intersection to take (out of 2 possible) + // DirAuto (==0) - take the intersection closest to the current track position + // DirOutward (==1) - go along the track (increasing mX) + // DirInward (==-1) - go backward (decreasing mX) + // + const auto fy = mP[0], sn = mP[2]; + const value_t kEps = 1.e-6; + // + auto crv = getCurvature(bz); + if (fabs(crv) > o2::constants::math::Almost0) { // helix + // get center of the track circle + o2::utils::CircleXY circle; + getCircleParamsLoc(bz, circle); + auto r0 = std::sqrt(circle.getCenterD2()); + if (r0 <= o2::constants::math::Almost0) { + return false; // the track is concentric to circle + } + value_t tR2r0 = 1., g = 0., tmp = 0.; + if (fabs(circle.rC - r0) > kEps) { + tR2r0 = circle.rC / r0; + g = 0.5 * (r * r / (r0 * circle.rC) - tR2r0 - 1. / tR2r0); + tmp = 1. + g * tR2r0; + } else { + tR2r0 = 1.0; + g = 0.5 * r * r / (r0 * circle.rC) - 1.; + tmp = 0.5 * r * r / (r0 * r0); + } + auto det = (1. - g) * (1. + g); + if (det < 0.) { + return false; // does not reach raduis r + } + det = std::sqrt(det); + // + // the intersection happens in 2 points: {circle.xC+tR*C,circle.yC+tR*S} + // with C=f*c0+-|s0|*det and S=f*s0-+c0 sign(s0)*det + // where s0 and c0 make direction for the circle center (=circle.xC/r0 and circle.yC/r0) + // + x = circle.xC * tmp; + auto y = circle.yC * tmp; + if (fabs(circle.yC) > o2::constants::math::Almost0) { // when circle.yC==0 the x,y is unique + auto dfx = tR2r0 * fabs(circle.yC) * det; + auto dfy = tR2r0 * circle.xC * (circle.yC > 0. ? det : -det); + if (dir == DirAuto) { // chose the one which corresponds to smallest step + auto delta = (x - mX) * dfx - (y - fy) * dfy; // the choice of + in C will lead to smaller step if delta<0 + x += delta < 0. ? dfx : -dfx; + } else if (dir == DirOutward) { // along track direction: x must be > mX + x -= dfx; // try the smallest step (dfx is positive) + auto dfeps = mX - x; // handle special case of very small step + if (dfeps < -kEps) { + return true; + } + if (fabs(dfeps) < kEps && fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? + return mX; + } + x += dfx + dfx; + auto dxm = x - mX; + if (dxm > 0.) { + return true; + } else if (dxm < -kEps) { + return false; + } + x = mX; // don't move + } else { // backward: x must be < mX + x += dfx; // try the smallest step (dfx is positive) + auto dfeps = x - mX; // handle special case of very small step + if (dfeps < -kEps) { + return true; + } + if (fabs(dfeps) < kEps && fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? + return mX; + } + x -= dfx + dfx; + auto dxm = x - mX; + if (dxm < 0.) { + return true; + } + if (dxm > kEps) { + return false; + } + x = mX; // don't move + } + } else { // special case: track touching the circle just in 1 point + if ((dir == DirOutward && x < mX) || (dir == DirInward && x > mX)) { + return false; + } + } + } else { // this is a straight track + if (fabs(sn) >= o2::constants::math::Almost1) { // || to Y axis + auto det = (r - mX) * (r + mX); + if (det < 0.) { + return false; // does not reach raduis r + } + x = mX; + if (dir == DirAuto) { + return true; + } + det = std::sqrt(det); + if (dir == DirOutward) { // along the track direction + if (sn > 0.) { + if (fy > det) { + return false; // track is along Y axis and above the circle + } + } else { + if (fy < -det) { + return false; // track is against Y axis amd belo the circle + } + } + } else if (dir == DirInward) { // against track direction + if (sn > 0.) { + if (fy < -det) { + return false; // track is along Y axis + } + } else if (fy > det) { + return false; // track is against Y axis + } + } + } else if (fabs(sn) <= o2::constants::math::Almost0) { // || to X axis + auto det = (r - fy) * (r + fy); + if (det < 0.) { + return false; // does not reach raduis r + } + det = std::sqrt(det); + if (dir == DirAuto) { + x = mX > 0. ? det : -det; // choose the solution requiring the smalest step + return true; + } else if (dir == DirOutward) { // along the track direction + if (mX > det) { + return false; // current point is in on the right from the circle + } else { + x = (mX < -det) ? -det : det; // on the left : within the circle + } + } else { // against the track direction + if (mX < -det) { + return false; + } else { + x = mX > det ? det : -det; + } + } + } else { // general case of straight line + auto cs = std::sqrt((1 - sn) * (1 + sn)); + auto xsyc = mX * sn - fy * cs; + auto det = (r - xsyc) * (r + xsyc); + if (det < 0.) { + return false; // does not reach raduis r + } + det = std::sqrt(det); + auto xcys = mX * cs + fy * sn; + auto t = -xcys; + if (dir == DirAuto) { + t += t > 0. ? -det : det; // chose the solution requiring the smalest step + } else if (dir > 0) { // go in increasing mX direction. ( t+-det > 0) + if (t >= -det) { + t += -det; // take minimal step giving t>0 + } else { + return false; // both solutions have negative t + } + } else { // go in increasing mX direction. (t+-det < 0) + if (t < det) { + t -= det; // take minimal step giving t<0 + } else { + return false; // both solutions have positive t + } + } + x = mX + cs * t; + } + } + // + return true; +} + +//______________________________________________ +template <typename value_T> +bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, bool anglecorr, value_t dedx) +{ + //------------------------------------------------------------------ + // This function corrects the track parameters for the energy loss in crossed material. + // "xrho" - is the product length*density (g/cm^2). + // It should be passed as negative when propagating tracks + // from the intreaction point to the outside of the central barrel. + // "mass" - the mass of this particle (GeV/c^2). + // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly + // "anglecorr" - switch for the angular correction + //------------------------------------------------------------------ + constexpr value_t kMaxELossFrac = 0.3f; // max allowed fractional eloss + constexpr value_t kMinP = 0.01f; // kill below this momentum + + // Apply angle correction, if requested + if (anglecorr) { + value_t csp2 = (1.f - getSnp()) * (1.f + getSnp()); // cos(phi)^2 + value_t cst2I = (1.f + getTgl() * getTgl()); // 1/cos(lambda)^2 + value_t angle = std::sqrt(cst2I / (csp2)); + xrho *= angle; + } + + value_t p = getP(); + if (mass < 0) { + p += p; // q=2 particle + } + value_t p2 = p * p, mass2 = mass * mass; + value_t e2 = p2 + mass2; + value_t beta2 = p2 / e2; + + // Calculating the energy loss corrections************************ + if ((xrho != 0.f) && (beta2 < 1.f)) { + if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly + dedx = BetheBlochSolid(p / fabs(mass)); + if (mAbsCharge != 1) { + dedx *= mAbsCharge * mAbsCharge; + } + } + + value_t dE = dedx * xrho; + value_t e = std::sqrt(e2); + if (fabs(dE) > kMaxELossFrac * e) { + return false; // 30% energy loss is too much! + } + value_t eupd = e + dE; + value_t pupd2 = eupd * eupd - mass2; + if (pupd2 < kMinP * kMinP) { + return false; + } + setQ2Pt(getQ2Pt() * p / std::sqrt(pupd2)); + } + + return true; +} + +template class TrackParametrization<float>; +//template class TrackParametrization<double>; + +} // namespace track +} // namespace o2 diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx new file mode 100644 index 0000000000000..8573411777aed --- /dev/null +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -0,0 +1,1096 @@ +// 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 TrackparametrizationWithError.cxx +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since Oct 1, 2020 +/// @brief + +// 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 "ReconstructionDataFormats/TrackParametrizationWithError.h" +#include "ReconstructionDataFormats/Vertex.h" +#include "ReconstructionDataFormats/DCA.h" +#include <FairLogger.h> +#include <iostream> +#include "Math/SMatrix.h" +#include <fmt/printf.h> +#include "Framework/Logger.h" + +using std::array; +using namespace o2::constants::math; + +namespace o2 +{ +namespace track +{ + +//______________________________________________________________ +template <typename value_T> +void TrackParametrizationWithError<value_T>::invert() +{ + // Transform this track to the local coord. system rotated by 180 deg. + this->invertParam(); + // since the fP1 and fP2 are not inverted, their covariances with others change sign + mC[kSigZY] = -mC[kSigZY]; + mC[kSigSnpY] = -mC[kSigSnpY]; + mC[kSigTglZ] = -mC[kSigTglZ]; + mC[kSigTglSnp] = -mC[kSigTglSnp]; + mC[kSigQ2PtZ] = -mC[kSigQ2PtZ]; + mC[kSigQ2PtSnp] = -mC[kSigQ2PtSnp]; +} + +//______________________________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) +{ + //---------------------------------------------------------------- + // propagate this track to the plane X=xk (cm) in the field "b" (kG) + //---------------------------------------------------------------- + value_t dx = xk - this->getX(); + if (fabs(dx) < Almost0) { + return true; + } + value_t crv = this->getCurvature(b); + value_t x2r = crv * dx; + value_t f1 = this->getSnp(), f2 = f1 + x2r; + if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + return false; + } + value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); + if (fabs(r1) < Almost0) { + return false; + } + value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); + if (fabs(r2) < Almost0) { + return false; + } + this->setX(xk); + double dy2dx = (f1 + f2) / (r1 + r2); + value_t dP[kNParams] = {0.f}; + dP[kY] = dx * dy2dx; + dP[kSnp] = x2r; + if (fabs(x2r) < 0.05f) { + dP[kZ] = dx * (r2 + f2 * dy2dx) * this->getTgl(); + } else { + // for small dx/R the linear apporximation of the arc by the segment is OK, + // but at large dx/R the error is very large and leads to incorrect Z propagation + // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi + // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2) + // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one + // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center + // mP1 += rot/crv*mP3; + // + value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. + if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles + if (f2 > 0.f) { + rot = PI - rot; // + } else { + rot = -PI - rot; + } + } + dP[kZ] = this->getTgl() / crv * rot; + } + + this->updateParams(dP); // apply corrections + + value_t &c00 = mC[kSigY2], &c10 = mC[kSigZY], &c11 = mC[kSigZ2], &c20 = mC[kSigSnpY], &c21 = mC[kSigSnpZ], + &c22 = mC[kSigSnp2], &c30 = mC[kSigTglY], &c31 = mC[kSigTglZ], &c32 = mC[kSigTglSnp], &c33 = mC[kSigTgl2], + &c40 = mC[kSigQ2PtY], &c41 = mC[kSigQ2PtZ], &c42 = mC[kSigQ2PtSnp], &c43 = mC[kSigQ2PtTgl], + &c44 = mC[kSigQ2Pt2]; + + // evaluate matrix in double prec. + double rinv = 1. / r1; + double r3inv = rinv * rinv * rinv; + double f24 = dx * b * B2C; // x2r/mP[kQ2Pt]; + double f02 = dx * r3inv; + double f04 = 0.5 * f24 * f02; + double f12 = f02 * this->getTgl() * f1; + double f14 = 0.5 * f24 * f12; // 0.5*f24*f02*getTgl()*f1; + double f13 = dx * rinv; + + // b = C*ft + double b00 = f02 * c20 + f04 * c40, b01 = f12 * c20 + f14 * c40 + f13 * c30; + double b02 = f24 * c40; + double b10 = f02 * c21 + f04 * c41, b11 = f12 * c21 + f14 * c41 + f13 * c31; + double b12 = f24 * c41; + double b20 = f02 * c22 + f04 * c42, b21 = f12 * c22 + f14 * c42 + f13 * c32; + double b22 = f24 * c42; + double b40 = f02 * c42 + f04 * c44, b41 = f12 * c42 + f14 * c44 + f13 * c43; + double b42 = f24 * c44; + double b30 = f02 * c32 + f04 * c43, b31 = f12 * c32 + f14 * c43 + f13 * c33; + double b32 = f24 * c43; + + // a = f*b = f*C*ft + double a00 = f02 * b20 + f04 * b40, a01 = f02 * b21 + f04 * b41, a02 = f02 * b22 + f04 * b42; + double a11 = f12 * b21 + f14 * b41 + f13 * b31, a12 = f12 * b22 + f14 * b42 + f13 * b32; + double a22 = f24 * b42; + + // F*C*Ft = C + (b + bt + a) + c00 += b00 + b00 + a00; + c10 += b10 + b01 + a01; + c20 += b20 + b02 + a02; + c30 += b30; + c40 += b40; + c11 += b11 + b11 + a11; + c21 += b21 + b12 + a12; + c31 += b31; + c41 += b41; + c22 += b22 + b22 + a22; + c32 += b32; + c42 += b42; + + checkCovariance(); + + return true; +} + +//______________________________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) +{ + // rotate to alpha frame + if (fabs(this->getSnp()) > Almost1) { + LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", this->getSnp()); + return false; + } + // + utils::BringToPMPi(alpha); + // + value_t ca = 0, sa = 0; + utils::sincos(alpha - this->getAlpha(), sa, ca); + value_t snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision + // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle + // direction in local frame is along the X axis + if ((csp * ca + snp * sa) < 0) { + //LOGF(WARNING,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa); + return false; + } + // + + value_t updSnp = snp * ca - csp * sa; + if (fabs(updSnp) > Almost1) { + LOGF(WARNING, "Rotation failed: new snp {:.2f}", updSnp); + return false; + } + value_t xold = this->getX(), yold = this->getY(); + this->setAlpha(alpha); + this->setX(xold * ca + yold * sa); + this->setY(-xold * sa + yold * ca); + this->setSnp(updSnp); + + if (fabs(csp) < Almost0) { + LOGF(WARNING, "Too small cosine value {:f}", csp); + csp = Almost0; + } + + value_t rr = (ca + snp / csp * sa); + + mC[kSigY2] *= (ca * ca); + mC[kSigZY] *= ca; + mC[kSigSnpY] *= ca * rr; + mC[kSigSnpZ] *= rr; + mC[kSigSnp2] *= rr * rr; + mC[kSigTglY] *= ca; + mC[kSigTglSnp] *= rr; + mC[kSigQ2PtY] *= ca; + mC[kSigQ2PtSnp] *= rr; + + checkCovariance(); + return true; +} + +//_______________________________________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformats::VertexBase& vtx, value_t b, o2::dataformats::DCA* dca, value_t maxD) +{ + // propagate track to DCA to the vertex + value_t sn, cs, alp = this->getAlpha(); + o2::utils::sincos(alp, sn, cs); + value_t x = this->getX(), y = this->getY(), snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + value_t xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); + x -= xv; + y -= yv; + //Estimate the impact parameter neglecting the track curvature + Double_t d = std::abs(x * snp - y * csp); + if (d > maxD) { + return false; + } + value_t crv = this->getCurvature(b); + value_t tgfv = -(crv * x - snp) / (crv * y + csp); + sn = tgfv / std::sqrt(1.f + tgfv * tgfv); + cs = std::sqrt((1. - sn) * (1. + sn)); + cs = (std::abs(tgfv) > Almost0) ? sn / tgfv : Almost1; + + x = xv * cs + yv * sn; + yv = -xv * sn + yv * cs; + xv = x; + + auto tmpT(*this); // operate on the copy to recover after the failure + alp += std::asin(sn); + if (!tmpT.rotate(alp) || !tmpT.propagateTo(xv, b)) { + LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; + tmpT.print(); + return false; + } + *this = tmpT; + if (dca) { + o2::utils::sincos(alp, sn, cs); + auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; + dca->set(this->getY() - yv, this->getZ() - zv, getSigmaY2() + s2ylocvtx, getSigmaZY(), getSigmaZ2() + vtx.getSigmaZ2()); + } + return true; +} + +//______________________________________________________________ +template <typename value_T> +TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const array<value_t, 3>& xyz, const array<value_t, 3>& pxpypz, + const array<value_t, kLabCovMatSize>& cv, int charge, bool sectorAlpha) +{ + // construct track param and covariance from kinematics and lab errors + + // Alpha of the frame is defined as: + // sectorAlpha == false : -> angle of pt direction + // sectorAlpha == true : -> angle of the sector from X,Y coordinate for r>1 + // angle of pt direction for r==0 + // + // + constexpr value_t kSafe = 1e-5f; + value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; + value_t alp = 0; + if (sectorAlpha || radPos2 < 1) { + alp = atan2f(pxpypz[1], pxpypz[0]); + } else { + alp = atan2f(xyz[1], xyz[0]); + } + if (sectorAlpha) { + alp = utils::Angle2Alpha(alp); + } + // + value_t sn, cs; + utils::sincos(alp, sn, cs); + // protection: avoid alpha being too close to 0 or +-pi/2 + if (fabs(sn) < 2.f * kSafe) { + if (alp > 0) { + alp += alp < PIHalf ? 2.f * kSafe : -2.f * kSafe; + } else { + alp += alp > -PIHalf ? -2.f * kSafe : 2.f * kSafe; + } + utils::sincos(alp, sn, cs); + } else if (fabs(cs) < 2.f * kSafe) { + if (alp > 0) { + alp += alp > PIHalf ? 2.f * kSafe : -2.f * kSafe; + } else { + alp += alp > -PIHalf ? 2.f * kSafe : -2.f * kSafe; + } + utils::sincos(alp, sn, cs); + } + // get the vertex of origin and the momentum + array<value_t, 3> ver{xyz[0], xyz[1], xyz[2]}; + array<value_t, 3> mom{pxpypz[0], pxpypz[1], pxpypz[2]}; + // + // Rotate to the local coordinate system + utils::RotateZ(ver, -alp); + utils::RotateZ(mom, -alp); + // + value_t pt = sqrt(mom[0] * mom[0] + mom[1] * mom[1]); + value_t ptI = 1.f / pt; + this->setX(ver[0]); + this->setAlpha(alp); + this->setY(ver[1]); + this->setZ(ver[2]); + this->setSnp(mom[1] * ptI); // cos(phi) + this->setTgl(mom[2] * ptI); // tg(lambda) + this->setAbsCharge(std::abs(charge)); + this->setQ2Pt(charge ? ptI * charge : ptI); + // + if (fabs(1.f - this->getSnp()) < kSafe) { + this->setSnp(1.f - kSafe); // Protection + } else if (fabs(-1.f - this->getSnp()) < kSafe) { + this->setSnp(-1.f + kSafe); // Protection + } + // + // Covariance matrix (formulas to be simplified) + value_t r = mom[0] * ptI; // cos(phi) + value_t cv34 = std::sqrt(cv[3] * cv[3] + cv[4] * cv[4]); + // + int special = 0; + value_t sgcheck = r * sn + this->getSnp() * cs; + if (fabs(sgcheck) > 1 - kSafe) { // special case: lab phi is +-pi/2 + special = 1; + sgcheck = sgcheck < 0 ? -1.f : 1.f; + } else if (fabs(sgcheck) < kSafe) { + sgcheck = cs < 0 ? -1.0f : 1.0f; + special = 2; // special case: lab phi is 0 + } + // + mC[kSigY2] = cv[0] + cv[2]; + mC[kSigZY] = (-cv[3] * sn) < 0 ? -cv34 : cv34; + mC[kSigZ2] = cv[5]; + // + value_t ptI2 = ptI * ptI; + value_t tgl2 = this->getTgl() * this->getTgl(); + if (special == 1) { + mC[kSigSnpY] = cv[6] * ptI; + mC[kSigSnpZ] = -sgcheck * cv[8] * r * ptI; + mC[kSigSnp2] = fabs(cv[9] * r * r * ptI2); + mC[kSigTglY] = (cv[10] * this->getTgl() - sgcheck * cv[15]) * ptI / r; + mC[kSigTglZ] = (cv[17] - sgcheck * cv[12] * this->getTgl()) * ptI; + mC[kSigTglSnp] = (-sgcheck * cv[18] + cv[13] * this->getTgl()) * r * ptI2; + mC[kSigTgl2] = fabs(cv[20] - 2 * sgcheck * cv[19] * mC[4] + cv[14] * tgl2) * ptI2; + mC[kSigQ2PtY] = cv[10] * ptI2 / r * charge; + mC[kSigQ2PtZ] = -sgcheck * cv[12] * ptI2 * charge; + mC[kSigQ2PtSnp] = cv[13] * r * ptI * ptI2 * charge; + mC[kSigQ2PtTgl] = (-sgcheck * cv[19] + cv[14] * this->getTgl()) * r * ptI2 * ptI; + mC[kSigQ2Pt2] = fabs(cv[14] * ptI2 * ptI2); + } else if (special == 2) { + mC[kSigSnpY] = -cv[10] * ptI * cs / sn; + mC[kSigSnpZ] = cv[12] * cs * ptI; + mC[kSigSnp2] = fabs(cv[14] * cs * cs * ptI2); + mC[kSigTglY] = (sgcheck * cv[6] * this->getTgl() - cv[15]) * ptI / sn; + mC[kSigTglZ] = (cv[17] - sgcheck * cv[8] * this->getTgl()) * ptI; + mC[kSigTglSnp] = (cv[19] - sgcheck * cv[13] * this->getTgl()) * cs * ptI2; + mC[kSigTgl2] = fabs(cv[20] - 2 * sgcheck * cv[18] * this->getTgl() + cv[9] * tgl2) * ptI2; + mC[kSigQ2PtY] = sgcheck * cv[6] * ptI2 / sn * charge; + mC[kSigQ2PtZ] = -sgcheck * cv[8] * ptI2 * charge; + mC[kSigQ2PtSnp] = -sgcheck * cv[13] * cs * ptI * ptI2 * charge; + mC[kSigQ2PtTgl] = (-sgcheck * cv[18] + cv[9] * this->getTgl()) * ptI2 * ptI * charge; + mC[kSigQ2Pt2] = fabs(cv[9] * ptI2 * ptI2); + } else { + double m00 = -sn; // m10=cs; + double m23 = -pt * (sn + this->getSnp() * cs / r), m43 = -pt * pt * (r * cs - this->getSnp() * sn); + double m24 = pt * (cs - this->getSnp() * sn / r), m44 = -pt * pt * (r * sn + this->getSnp() * cs); + double m35 = pt, m45 = -pt * pt * this->getTgl(); + // + m43 *= charge; + m44 *= charge; + m45 *= charge; + // + double a1 = cv[13] - cv[9] * (m23 * m44 + m43 * m24) / m23 / m43; + double a2 = m23 * m24 - m23 * (m23 * m44 + m43 * m24) / m43; + double a3 = m43 * m44 - m43 * (m23 * m44 + m43 * m24) / m23; + double a4 = cv[14] + 2. * cv[9]; + double a5 = m24 * m24 - 2. * m24 * m44 * m23 / m43; + double a6 = m44 * m44 - 2. * m24 * m44 * m43 / m23; + // + mC[kSigSnpY] = (cv[10] * m43 - cv[6] * m44) / (m24 * m43 - m23 * m44) / m00; + mC[kSigQ2PtY] = (cv[6] / m00 - mC[kSigSnpY] * m23) / m43; + mC[kSigTglY] = (cv[15] / m00 - mC[kSigQ2PtY] * m45) / m35; + mC[kSigSnpZ] = (cv[12] * m43 - cv[8] * m44) / (m24 * m43 - m23 * m44); + mC[kSigQ2PtZ] = (cv[8] - mC[kSigSnpZ] * m23) / m43; + mC[kSigTglZ] = cv[17] / m35 - mC[kSigQ2PtZ] * m45 / m35; + mC[kSigSnp2] = fabs((a4 * a3 - a6 * a1) / (a5 * a3 - a6 * a2)); + mC[kSigQ2Pt2] = fabs((a1 - a2 * mC[kSigSnp2]) / a3); + mC[kSigQ2PtSnp] = (cv[9] - mC[kSigSnp2] * m23 * m23 - mC[kSigQ2Pt2] * m43 * m43) / m23 / m43; + double b1 = cv[18] - mC[kSigQ2PtSnp] * m23 * m45 - mC[kSigQ2Pt2] * m43 * m45; + double b2 = m23 * m35; + double b3 = m43 * m35; + double b4 = cv[19] - mC[kSigQ2PtSnp] * m24 * m45 - mC[kSigQ2Pt2] * m44 * m45; + double b5 = m24 * m35; + double b6 = m44 * m35; + mC[kSigTglSnp] = (b4 - b6 * b1 / b3) / (b5 - b6 * b2 / b3); + mC[kSigQ2PtTgl] = b1 / b3 - b2 * mC[kSigTglSnp] / b3; + mC[kSigTgl2] = fabs((cv[20] - mC[kSigQ2Pt2] * (m45 * m45) - mC[kSigQ2PtTgl] * 2. * m35 * m45) / (m35 * m35)); + } + checkCovariance(); +} + +//____________________________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const array<value_t, 3>& b) +{ + //---------------------------------------------------------------- + // Extrapolate this track to the plane X=xk in the field b[]. + // + // X [cm] is in the "tracking coordinate system" of this track. + // b[]={Bx,By,Bz} [kG] is in the Global coordidate system. + //---------------------------------------------------------------- + + value_t dx = xk - this->getX(); + if (fabs(dx) < Almost0) { + return true; + } + // Do not propagate tracks outside the ALICE detector + if (fabs(dx) > 1e5 || fabs(this->getY()) > 1e5 || fabs(this->getZ()) > 1e5) { + LOGF(WARNING, "Anomalous track, target X:{:f}", xk); + // print(); + return false; + } + value_t crv = (fabs(b[2]) < Almost0) ? 0.f : this->getCurvature(b[2]); + value_t x2r = crv * dx; + value_t f1 = this->getSnp(), f2 = f1 + x2r; + if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + return false; + } + value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); + if (fabs(r1) < Almost0) { + return false; + } + value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); + if (fabs(r2) < Almost0) { + return false; + } + + value_t dy2dx = (f1 + f2) / (r1 + r2); + value_t step = (fabs(x2r) < 0.05f) ? dx * fabs(r2 + f2 * dy2dx) // chord + : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc + step *= std::sqrt(1.f + this->getTgl() * this->getTgl()); + // + // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System + array<value_t, 9> vecLab{0.f}; + if (!this->getPosDirGlo(vecLab)) { + return false; + } + // + // matrix transformed with Bz component only + value_t &c00 = mC[kSigY2], &c10 = mC[kSigZY], &c11 = mC[kSigZ2], &c20 = mC[kSigSnpY], &c21 = mC[kSigSnpZ], + &c22 = mC[kSigSnp2], &c30 = mC[kSigTglY], &c31 = mC[kSigTglZ], &c32 = mC[kSigTglSnp], &c33 = mC[kSigTgl2], + &c40 = mC[kSigQ2PtY], &c41 = mC[kSigQ2PtZ], &c42 = mC[kSigQ2PtSnp], &c43 = mC[kSigQ2PtTgl], + &c44 = mC[kSigQ2Pt2]; + // evaluate matrix in double prec. + double rinv = 1. / r1; + double r3inv = rinv * rinv * rinv; + double f24 = dx * b[2] * B2C; // x2r/track[kQ2Pt]; + double f02 = dx * r3inv; + double f04 = 0.5 * f24 * f02; + double f12 = f02 * this->getTgl() * f1; + double f14 = 0.5 * f24 * f12; // 0.5*f24*f02*getTgl()*f1; + double f13 = dx * rinv; + + // b = C*ft + double b00 = f02 * c20 + f04 * c40, b01 = f12 * c20 + f14 * c40 + f13 * c30; + double b02 = f24 * c40; + double b10 = f02 * c21 + f04 * c41, b11 = f12 * c21 + f14 * c41 + f13 * c31; + double b12 = f24 * c41; + double b20 = f02 * c22 + f04 * c42, b21 = f12 * c22 + f14 * c42 + f13 * c32; + double b22 = f24 * c42; + double b40 = f02 * c42 + f04 * c44, b41 = f12 * c42 + f14 * c44 + f13 * c43; + double b42 = f24 * c44; + double b30 = f02 * c32 + f04 * c43, b31 = f12 * c32 + f14 * c43 + f13 * c33; + double b32 = f24 * c43; + + // a = f*b = f*C*ft + double a00 = f02 * b20 + f04 * b40, a01 = f02 * b21 + f04 * b41, a02 = f02 * b22 + f04 * b42; + double a11 = f12 * b21 + f14 * b41 + f13 * b31, a12 = f12 * b22 + f14 * b42 + f13 * b32; + double a22 = f24 * b42; + + // F*C*Ft = C + (b + bt + a) + c00 += b00 + b00 + a00; + c10 += b10 + b01 + a01; + c20 += b20 + b02 + a02; + c30 += b30; + c40 += b40; + c11 += b11 + b11 + a11; + c21 += b21 + b12 + a12; + c31 += b31; + c41 += b41; + c22 += b22 + b22 + a22; + c32 += b32; + c42 += b42; + + checkCovariance(); + + // Rotate to the system where Bx=By=0. + value_t bxy2 = b[0] * b[0] + b[1] * b[1]; + value_t bt = std::sqrt(bxy2); + value_t cosphi = 1.f, sinphi = 0.f; + if (bt > Almost0) { + cosphi = b[0] / bt; + sinphi = b[1] / bt; + } + value_t bb = std::sqrt(bxy2 + b[2] * b[2]); + value_t costet = 1., sintet = 0.; + if (bb > Almost0) { + costet = b[2] / bb; + sintet = bt / bb; + } + array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], + -sinphi * vecLab[0] + cosphi * vecLab[1], + sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], + costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], + -sinphi * vecLab[3] + cosphi * vecLab[4], + sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], + vecLab[6]}; + + // Do the helix step + value_t sgn = this->getSign(); + g3helx3(sgn * bb, step, vect); + + // Rotate back to the Global System + vecLab[0] = cosphi * costet * vect[0] - sinphi * vect[1] + cosphi * sintet * vect[2]; + vecLab[1] = sinphi * costet * vect[0] + cosphi * vect[1] + sinphi * sintet * vect[2]; + vecLab[2] = -sintet * vect[0] + costet * vect[2]; + + vecLab[3] = cosphi * costet * vect[3] - sinphi * vect[4] + cosphi * sintet * vect[5]; + vecLab[4] = sinphi * costet * vect[3] + cosphi * vect[4] + sinphi * sintet * vect[5]; + vecLab[5] = -sintet * vect[3] + costet * vect[5]; + + // Rotate back to the Tracking System + value_t sinalp = -vecLab[7], cosalp = vecLab[8]; + value_t t = cosalp * vecLab[0] - sinalp * vecLab[1]; + vecLab[1] = sinalp * vecLab[0] + cosalp * vecLab[1]; + vecLab[0] = t; + t = cosalp * vecLab[3] - sinalp * vecLab[4]; + vecLab[4] = sinalp * vecLab[3] + cosalp * vecLab[4]; + vecLab[3] = t; + + // Do the final correcting step to the target plane (linear approximation) + value_t x = vecLab[0], y = vecLab[1], z = vecLab[2]; + if (fabs(dx) > Almost0) { + if (fabs(vecLab[3]) < Almost0) { + return false; + } + dx = xk - vecLab[0]; + x += dx; + y += vecLab[4] / vecLab[3] * dx; + z += vecLab[5] / vecLab[3] * dx; + } + + // Calculate the track parameters + t = 1.f / std::sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); + this->setX(x); + this->setY(y); + this->setZ(z); + this->setSnp(vecLab[4] * t); + this->setTgl(vecLab[5] * t); + this->setQ2Pt(sgn * t / vecLab[6]); + + return true; +} + +//______________________________________________ +template <typename value_T> +void TrackParametrizationWithError<value_T>::checkCovariance() +{ + // This function forces the diagonal elements of the covariance matrix to be positive. + // In case the diagonal element is bigger than the maximal allowed value, it is set to + // the limit and the off-diagonal elements that correspond to it are set to zero. + + mC[kSigY2] = fabs(mC[kSigY2]); + if (mC[kSigY2] > kCY2max) { + value_t scl = std::sqrt(kCY2max / mC[kSigY2]); + mC[kSigY2] = kCY2max; + mC[kSigZY] *= scl; + mC[kSigSnpY] *= scl; + mC[kSigTglY] *= scl; + mC[kSigQ2PtY] *= scl; + } + mC[kSigZ2] = fabs(mC[kSigZ2]); + if (mC[kSigZ2] > kCZ2max) { + value_t scl = std::sqrt(kCZ2max / mC[kSigZ2]); + mC[kSigZ2] = kCZ2max; + mC[kSigZY] *= scl; + mC[kSigSnpZ] *= scl; + mC[kSigTglZ] *= scl; + mC[kSigQ2PtZ] *= scl; + } + mC[kSigSnp2] = fabs(mC[kSigSnp2]); + if (mC[kSigSnp2] > kCSnp2max) { + value_t scl = std::sqrt(kCSnp2max / mC[kSigSnp2]); + mC[kSigSnp2] = kCSnp2max; + mC[kSigSnpY] *= scl; + mC[kSigSnpZ] *= scl; + mC[kSigTglSnp] *= scl; + mC[kSigQ2PtSnp] *= scl; + } + mC[kSigTgl2] = fabs(mC[kSigTgl2]); + if (mC[kSigTgl2] > kCTgl2max) { + value_t scl = std::sqrt(kCTgl2max / mC[kSigTgl2]); + mC[kSigTgl2] = kCTgl2max; + mC[kSigTglY] *= scl; + mC[kSigTglZ] *= scl; + mC[kSigTglSnp] *= scl; + mC[kSigQ2PtTgl] *= scl; + } + mC[kSigQ2Pt2] = fabs(mC[kSigQ2Pt2]); + if (mC[kSigQ2Pt2] > kC1Pt2max) { + value_t scl = std::sqrt(kC1Pt2max / mC[kSigQ2Pt2]); + mC[kSigQ2Pt2] = kC1Pt2max; + mC[kSigQ2PtY] *= scl; + mC[kSigQ2PtZ] *= scl; + mC[kSigQ2PtSnp] *= scl; + mC[kSigQ2PtTgl] *= scl; + } +} + +//______________________________________________ +template <typename value_T> +void TrackParametrizationWithError<value_T>::resetCovariance(value_t s2) +{ + // Reset the covarince matrix to "something big" + double d0(kCY2max), d1(kCZ2max), d2(kCSnp2max), d3(kCTgl2max), d4(kC1Pt2max); + if (s2 > Almost0) { + d0 = getSigmaY2() * s2; + d1 = getSigmaZ2() * s2; + d2 = getSigmaSnp2() * s2; + d3 = getSigmaTgl2() * s2; + d4 = getSigma1Pt2() * s2; + if (d0 > kCY2max) { + d0 = kCY2max; + } + if (d1 > kCZ2max) { + d1 = kCZ2max; + } + if (d2 > kCSnp2max) { + d2 = kCSnp2max; + } + if (d3 > kCTgl2max) { + d3 = kCTgl2max; + } + if (d4 > kC1Pt2max) { + d4 = kC1Pt2max; + } + } + memset(mC, 0, kCovMatSize * sizeof(value_t)); + mC[kSigY2] = d0; + mC[kSigZ2] = d1; + mC[kSigSnp2] = d2; + mC[kSigTgl2] = d3; + mC[kSigQ2Pt2] = d4; +} + +//______________________________________________ +template <typename value_T> +typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const array<value_t, 2>& p, const array<value_t, 3>& cov) const +{ + // Estimate the chi2 of the space point "p" with the cov. matrix "cov" + auto sdd = static_cast<double>(getSigmaY2()) + static_cast<double>(cov[0]); + auto sdz = static_cast<double>(getSigmaZY()) + static_cast<double>(cov[1]); + auto szz = static_cast<double>(getSigmaZ2()) + static_cast<double>(cov[2]); + auto det = sdd * szz - sdz * sdz; + + if (fabs(det) < Almost0) { + return VeryBig; + } + + value_t d = this->getY() - p[0]; + value_t z = this->getZ() - p[1]; + + return (d * (szz * d - sdz * z) + z * (sdd * z - d * sdz)) / det; +} + +//______________________________________________ +template <typename value_T> +void TrackParametrizationWithError<value_T>::buildCombinedCovMatrix(const TrackParametrizationWithError<value_T>& rhs, MatrixDSym5& cov) const +{ + // fill combined cov.matrix (NOT inverted) + cov(kY, kY) = static_cast<double>(getSigmaY2()) + static_cast<double>(rhs.getSigmaY2()); + cov(kZ, kY) = static_cast<double>(getSigmaZY()) + static_cast<double>(rhs.getSigmaZY()); + cov(kZ, kZ) = static_cast<double>(getSigmaZ2()) + static_cast<double>(rhs.getSigmaZ2()); + cov(kSnp, kY) = static_cast<double>(getSigmaSnpY()) + static_cast<double>(rhs.getSigmaSnpY()); + cov(kSnp, kZ) = static_cast<double>(getSigmaSnpZ()) + static_cast<double>(rhs.getSigmaSnpZ()); + cov(kSnp, kSnp) = static_cast<double>(getSigmaSnp2()) + static_cast<double>(rhs.getSigmaSnp2()); + cov(kTgl, kY) = static_cast<double>(getSigmaTglY()) + static_cast<double>(rhs.getSigmaTglY()); + cov(kTgl, kZ) = static_cast<double>(getSigmaTglZ()) + static_cast<double>(rhs.getSigmaTglZ()); + cov(kTgl, kSnp) = static_cast<double>(getSigmaTglSnp()) + static_cast<double>(rhs.getSigmaTglSnp()); + cov(kTgl, kTgl) = static_cast<double>(getSigmaTgl2()) + static_cast<double>(rhs.getSigmaTgl2()); + cov(kQ2Pt, kY) = static_cast<double>(getSigma1PtY()) + static_cast<double>(rhs.getSigma1PtY()); + cov(kQ2Pt, kZ) = static_cast<double>(getSigma1PtZ()) + static_cast<double>(rhs.getSigma1PtZ()); + cov(kQ2Pt, kSnp) = static_cast<double>(getSigma1PtSnp()) + static_cast<double>(rhs.getSigma1PtSnp()); + cov(kQ2Pt, kTgl) = static_cast<double>(getSigma1PtTgl()) + static_cast<double>(rhs.getSigma1PtTgl()); + cov(kQ2Pt, kQ2Pt) = static_cast<double>(getSigma1Pt2()) + static_cast<double>(rhs.getSigma1Pt2()); +} + +//______________________________________________ +template <typename value_T> +typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const TrackParametrizationWithError<value_T>& rhs) const +{ + MatrixDSym5 cov; // perform matrix operations in double! + return getPredictedChi2(rhs, cov); +} + +//______________________________________________ +template <typename value_T> +typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const TrackParametrizationWithError<value_T>& rhs, MatrixDSym5& covToSet) const +{ + // get chi2 wrt other track, which must be defined at the same parameters X,alpha + // Supplied non-initialized covToSet matrix is filled by inverse combined matrix for further use + + if (std::abs(this->getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { + LOG(ERROR) << "The reference Alpha of the tracks differ: " << this->getAlpha() << " : " << rhs.getAlpha(); + return 2. * HugeF; + } + if (std::abs(this->getX() - rhs.getX()) > FLT_EPSILON) { + LOG(ERROR) << "The reference X of the tracks differ: " << this->getX() << " : " << rhs.getX(); + return 2. * HugeF; + } + buildCombinedCovMatrix(rhs, covToSet); + if (!covToSet.Invert()) { + LOG(WARNING) << "Cov.matrix inversion failed: " << covToSet; + return 2. * HugeF; + } + double chi2diag = 0., chi2ndiag = 0., diff[kNParams]; + for (int i = kNParams; i--;) { + diff[i] = this->getParam(i) - rhs.getParam(i); + chi2diag += diff[i] * diff[i] * covToSet(i, i); + } + for (int i = kNParams; i--;) { + for (int j = i; j--;) { + chi2ndiag += diff[i] * diff[j] * covToSet(i, j); + } + } + return chi2diag + 2. * chi2ndiag; +} + +//______________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::update(const TrackParametrizationWithError<value_T>& rhs, const MatrixDSym5& covInv) +{ + // update track with other track, the inverted combined cov matrix should be supplied + + // consider skipping this check, since it is usually already done upstream + if (std::abs(this->getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { + LOG(ERROR) << "The reference Alpha of the tracks differ: " << this->getAlpha() << " : " << rhs.getAlpha(); + return false; + } + if (std::abs(this->getX() - rhs.getX()) > FLT_EPSILON) { + LOG(ERROR) << "The reference X of the tracks differ: " << this->getX() << " : " << rhs.getX(); + return false; + } + + // gain matrix K = Cov0*H*(Cov0+Cov0)^-1 (for measurement matrix H=I) + MatrixDSym5 matC0; + matC0(kY, kY) = getSigmaY2(); + matC0(kZ, kY) = getSigmaZY(); + matC0(kZ, kZ) = getSigmaZ2(); + matC0(kSnp, kY) = getSigmaSnpY(); + matC0(kSnp, kZ) = getSigmaSnpZ(); + matC0(kSnp, kSnp) = getSigmaSnp2(); + matC0(kTgl, kY) = getSigmaTglY(); + matC0(kTgl, kZ) = getSigmaTglZ(); + matC0(kTgl, kSnp) = getSigmaTglSnp(); + matC0(kTgl, kTgl) = getSigmaTgl2(); + matC0(kQ2Pt, kY) = getSigma1PtY(); + matC0(kQ2Pt, kZ) = getSigma1PtZ(); + matC0(kQ2Pt, kSnp) = getSigma1PtSnp(); + matC0(kQ2Pt, kTgl) = getSigma1PtTgl(); + matC0(kQ2Pt, kQ2Pt) = getSigma1Pt2(); + MatrixD5 matK = matC0 * covInv; + + // updated state vector: x = K*(x1-x0) + // RS: why SMatix, SVector does not provide multiplication operators ??? + double diff[kNParams]; + for (int i = kNParams; i--;) { + diff[i] = rhs.getParam(i) - this->getParam(i); + } + for (int i = kNParams; i--;) { + for (int j = kNParams; j--;) { + this->updateParam(matK(i, j) * diff[j], i); + } + } + + // updated covariance: Cov0 = Cov0 - K*Cov0 + matK *= ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepStd<double, kNParams>>(matC0); + mC[kSigY2] -= matK(kY, kY); + mC[kSigZY] -= matK(kZ, kY); + mC[kSigZ2] -= matK(kZ, kZ); + mC[kSigSnpY] -= matK(kSnp, kY); + mC[kSigSnpZ] -= matK(kSnp, kZ); + mC[kSigSnp2] -= matK(kSnp, kSnp); + mC[kSigTglY] -= matK(kTgl, kY); + mC[kSigTglZ] -= matK(kTgl, kZ); + mC[kSigTglSnp] -= matK(kTgl, kSnp); + mC[kSigTgl2] -= matK(kTgl, kTgl); + mC[kSigQ2PtY] -= matK(kQ2Pt, kY); + mC[kSigQ2PtZ] -= matK(kQ2Pt, kZ); + mC[kSigQ2PtSnp] -= matK(kQ2Pt, kSnp); + mC[kSigQ2PtTgl] -= matK(kQ2Pt, kTgl); + mC[kSigQ2Pt2] -= matK(kQ2Pt, kQ2Pt); + + return true; +} + +//______________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::update(const TrackParametrizationWithError<value_T>& rhs) +{ + // update track with other track + MatrixDSym5 covI; // perform matrix operations in double! + buildCombinedCovMatrix(rhs, covI); + if (!covI.Invert()) { + LOG(WARNING) << "Cov.matrix inversion failed: " << covI; + return false; + } + return update(rhs, covI); +} + +//______________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::update(const array<value_t, 2>& p, const array<value_t, 3>& cov) +{ + // Update the track parameters with the space point "p" having + // the covariance matrix "cov" + + value_t &cm00 = mC[kSigY2], &cm10 = mC[kSigZY], &cm11 = mC[kSigZ2], &cm20 = mC[kSigSnpY], &cm21 = mC[kSigSnpZ], + &cm22 = mC[kSigSnp2], &cm30 = mC[kSigTglY], &cm31 = mC[kSigTglZ], &cm32 = mC[kSigTglSnp], &cm33 = mC[kSigTgl2], + &cm40 = mC[kSigQ2PtY], &cm41 = mC[kSigQ2PtZ], &cm42 = mC[kSigQ2PtSnp], &cm43 = mC[kSigQ2PtTgl], + &cm44 = mC[kSigQ2Pt2]; + + // use double precision? + double r00 = static_cast<double>(cov[0]) + static_cast<double>(cm00); + double r01 = static_cast<double>(cov[1]) + static_cast<double>(cm10); + double r11 = static_cast<double>(cov[2]) + static_cast<double>(cm11); + double det = r00 * r11 - r01 * r01; + + if (fabs(det) < Almost0) { + return false; + } + double detI = 1. / det; + double tmp = r00; + r00 = r11 * detI; + r11 = tmp * detI; + r01 = -r01 * detI; + + double k00 = cm00 * r00 + cm10 * r01, k01 = cm00 * r01 + cm10 * r11; + double k10 = cm10 * r00 + cm11 * r01, k11 = cm10 * r01 + cm11 * r11; + double k20 = cm20 * r00 + cm21 * r01, k21 = cm20 * r01 + cm21 * r11; + double k30 = cm30 * r00 + cm31 * r01, k31 = cm30 * r01 + cm31 * r11; + double k40 = cm40 * r00 + cm41 * r01, k41 = cm40 * r01 + cm41 * r11; + + value_t dy = p[kY] - this->getY(), dz = p[kZ] - this->getZ(); + value_t dsnp = k20 * dy + k21 * dz; + if (fabs(this->getSnp() + dsnp) > Almost1) { + return false; + } + + value_t dP[kNParams] = {value_t(k00 * dy + k01 * dz), value_t(k10 * dy + k11 * dz), dsnp, value_t(k30 * dy + k31 * dz), + value_t(k40 * dy + k41 * dz)}; + this->updateParams(dP); + + double c01 = cm10, c02 = cm20, c03 = cm30, c04 = cm40; + double c12 = cm21, c13 = cm31, c14 = cm41; + + cm00 -= k00 * cm00 + k01 * cm10; + cm10 -= k00 * c01 + k01 * cm11; + cm20 -= k00 * c02 + k01 * c12; + cm30 -= k00 * c03 + k01 * c13; + cm40 -= k00 * c04 + k01 * c14; + + cm11 -= k10 * c01 + k11 * cm11; + cm21 -= k10 * c02 + k11 * c12; + cm31 -= k10 * c03 + k11 * c13; + cm41 -= k10 * c04 + k11 * c14; + + cm22 -= k20 * c02 + k21 * c12; + cm32 -= k20 * c03 + k21 * c13; + cm42 -= k20 * c04 + k21 * c14; + + cm33 -= k30 * c03 + k31 * c13; + cm43 -= k30 * c04 + k31 * c14; + + cm44 -= k40 * c04 + k41 * c14; + + checkCovariance(); + + return true; +} + +//______________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr, value_t dedx) +{ + //------------------------------------------------------------------ + // This function corrects the track parameters for the crossed material. + // "x2x0" - X/X0, the thickness in units of the radiation length. + // "xrho" - is the product length*density (g/cm^2). + // It should be passed as negative when propagating tracks + // from the intreaction point to the outside of the central barrel. + // "mass" - the mass of this particle (GeV/c^2). + // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly + // "anglecorr" - switch for the angular correction + //------------------------------------------------------------------ + constexpr value_t kMSConst2 = 0.0136f * 0.0136f; + constexpr value_t kMaxELossFrac = 0.3f; // max allowed fractional eloss + constexpr value_t kMinP = 0.01f; // kill below this momentum + + value_t& fC22 = mC[kSigSnp2]; + value_t& fC33 = mC[kSigTgl2]; + value_t& fC43 = mC[kSigQ2PtTgl]; + value_t& fC44 = mC[kSigQ2Pt2]; + // + value_t csp2 = (1.f - this->getSnp()) * (1.f + this->getSnp()); // cos(phi)^2 + value_t cst2I = (1.f + this->getTgl() * this->getTgl()); // 1/cos(lambda)^2 + // Apply angle correction, if requested + if (anglecorr) { + value_t angle = std::sqrt(cst2I / (csp2)); + x2x0 *= angle; + xrho *= angle; + } + + value_t p = this->getP(); + value_t p2 = p * p, mass2 = mass * mass; + value_t e2 = p2 + mass2; + value_t beta2 = p2 / e2; + + // Calculating the multiple scattering corrections****************** + value_t cC22(0.f), cC33(0.f), cC43(0.f), cC44(0.f); + if (x2x0 != 0.f) { + value_t theta2 = kMSConst2 / (beta2 * p2) * fabs(x2x0); + if (this->getAbsCharge() != 1) { + theta2 *= this->getAbsCharge() * this->getAbsCharge(); + } + if (theta2 > PI * PI) { + return false; + } + value_t fp34 = this->getTgl() * this->getCharge2Pt(); + value_t t2c2I = theta2 * cst2I; + cC22 = t2c2I * csp2; + cC33 = t2c2I * cst2I; + cC43 = t2c2I * fp34; + cC44 = theta2 * fp34 * fp34; + // optimes this + // cC22 = theta2*((1.-getSnp())*(1.+getSnp()))*(1. + this->getTgl()*getTgl()); + // cC33 = theta2*(1. + this->getTgl()*getTgl())*(1. + this->getTgl()*getTgl()); + // cC43 = theta2*getTgl()*this->getQ2Pt()*(1. + this->getTgl()*getTgl()); + // cC44 = theta2*getTgl()*this->getQ2Pt()*getTgl()*this->getQ2Pt(); + } + + // Calculating the energy loss corrections************************ + value_t cP4 = 1.f; + if ((xrho != 0.f) && (beta2 < 1.f)) { + if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly + dedx = BetheBlochSolid(p / fabs(mass)); + if (this->getAbsCharge() != 1) { + dedx *= this->getAbsCharge() * this->getAbsCharge(); + } + } + + value_t dE = dedx * xrho; + value_t e = std::sqrt(e2); + if (fabs(dE) > kMaxELossFrac * e) { + return false; // 30% energy loss is too much! + } + value_t eupd = e + dE; + value_t pupd2 = eupd * eupd - mass2; + if (pupd2 < kMinP * kMinP) { + return false; + } + cP4 = p / std::sqrt(pupd2); + // + // Approximate energy loss fluctuation (M.Ivanov) + constexpr value_t knst = 0.07f; // To be tuned. + value_t sigmadE = knst * std::sqrt(fabs(dE)) * e / p2 * this->getCharge2Pt(); + cC44 += sigmadE * sigmadE; + } + + // Applying the corrections***************************** + fC22 += cC22; + fC33 += cC33; + fC43 += cC43; + fC44 += cC44; + this->setQ2Pt(this->getQ2Pt() * cP4); + + checkCovariance(); + + return true; +} + +//______________________________________________________________ +template <typename value_T> +bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(std::array<value_t, 21>& cv) const +{ + //--------------------------------------------------------------------- + // This function returns the global covariance matrix of the track params + // + // Cov(x,x) ... : cv[0] + // Cov(y,x) ... : cv[1] cv[2] + // Cov(z,x) ... : cv[3] cv[4] cv[5] + // Cov(px,x)... : cv[6] cv[7] cv[8] cv[9] + // Cov(py,x)... : cv[10] cv[11] cv[12] cv[13] cv[14] + // Cov(pz,x)... : cv[15] cv[16] cv[17] cv[18] cv[19] cv[20] + // + // Results for (nearly) straight tracks are meaningless ! + //--------------------------------------------------------------------- + if (std::abs(this->getQ2Pt()) <= Almost0 || std::abs(this->getSnp()) > Almost1) { + for (int i = 0; i < 21; i++) { + cv[i] = 0.; + } + return false; + } + + auto pt = this->getPt(); + value_t sn, cs; + o2::utils::sincos(this->getAlpha(), sn, cs); + auto r = std::sqrt((1. - this->getSnp()) * (1. + this->getSnp())); + auto m00 = -sn, m10 = cs; + auto m23 = -pt * (sn + this->getSnp() * cs / r), m43 = -pt * pt * (r * cs - this->getSnp() * sn); + auto m24 = pt * (cs - this->getSnp() * sn / r), m44 = -pt * pt * (r * sn + this->getSnp() * cs); + auto m35 = pt, m45 = -pt * pt * this->getTgl(); + + if (this->getSign() < 0) { + m43 = -m43; + m44 = -m44; + m45 = -m45; + } + + cv[0] = mC[0] * m00 * m00; + cv[1] = mC[0] * m00 * m10; + cv[2] = mC[0] * m10 * m10; + cv[3] = mC[1] * m00; + cv[4] = mC[1] * m10; + cv[5] = mC[2]; + cv[6] = m00 * (mC[3] * m23 + mC[10] * m43); + cv[7] = m10 * (mC[3] * m23 + mC[10] * m43); + cv[8] = mC[4] * m23 + mC[11] * m43; + cv[9] = m23 * (mC[5] * m23 + mC[12] * m43) + m43 * (mC[12] * m23 + mC[14] * m43); + cv[10] = m00 * (mC[3] * m24 + mC[10] * m44); + cv[11] = m10 * (mC[3] * m24 + mC[10] * m44); + cv[12] = mC[4] * m24 + mC[11] * m44; + cv[13] = m23 * (mC[5] * m24 + mC[12] * m44) + m43 * (mC[12] * m24 + mC[14] * m44); + cv[14] = m24 * (mC[5] * m24 + mC[12] * m44) + m44 * (mC[12] * m24 + mC[14] * m44); + cv[15] = m00 * (mC[6] * m35 + mC[10] * m45); + cv[16] = m10 * (mC[6] * m35 + mC[10] * m45); + cv[17] = mC[7] * m35 + mC[11] * m45; + cv[18] = m23 * (mC[8] * m35 + mC[12] * m45) + m43 * (mC[13] * m35 + mC[14] * m45); + cv[19] = m24 * (mC[8] * m35 + mC[12] * m45) + m44 * (mC[13] * m35 + mC[14] * m45); + cv[20] = m35 * (mC[9] * m35 + mC[13] * m45) + m45 * (mC[13] * m35 + mC[14] * m45); + + return true; +} + +#ifndef GPUCA_ALIGPUCODE +//______________________________________________________________ +template <typename value_T> +std::string TrackParametrizationWithError<value_T>::asString() const +{ + return TrackParametrization<value_t>::asString() + + fmt::format( + "\n{:7s} {:+.3e}\n" + "{:7s} {:+.3e} {:+.3e}\n" + "{:7s} {:+.3e} {:+.3e} {:+.3e}\n" + "{:7s} {:+.3e} {:+.3e} {:+.3e} {:+.3e}\n" + "{:7s} {:+.3e} {:+.3e} {:+.3e} {:+.3e} {:+.3e}", + "CovMat:", mC[kSigY2], "", mC[kSigZY], mC[kSigZ2], "", mC[kSigSnpY], mC[kSigSnpZ], mC[kSigSnp2], "", mC[kSigTglY], + mC[kSigTglZ], mC[kSigTglSnp], mC[kSigTgl2], "", mC[kSigQ2PtY], mC[kSigQ2PtZ], mC[kSigQ2PtSnp], mC[kSigQ2PtTgl], + mC[kSigQ2Pt2]); +} + +//______________________________________________________________ +template <typename value_T> +void TrackParametrizationWithError<value_T>::print() const +{ + // print parameters + printf("%s\n", asString().c_str()); +} + +template class TrackParametrizationWithError<float>; +//template class TrackParametrizationWithError<double>; + +} // namespace track +} // namespace o2 +#endif diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index e58317517a189..57a0168f29bdf 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -401,7 +401,7 @@ bool Tracker::fitTrack(const ROframe& event, TrackITSExt& track, int start, int track.setChi2(track.getChi2() + track.getPredictedChi2(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)); - if (!track.TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) + if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) return false; const float xx0 = (iLayer > 2) ? 0.008f : 0.003f; // Rough layer thickness From b899de32c27bbced540aff635f1dd17c8020d5a9 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Mon, 5 Oct 2020 17:40:44 +0200 Subject: [PATCH 0863/1751] [Align] Remove implicit conversions in TrackParam Removes undesired implicite conversions from float->double->float and calling of more costly double versions of functions. --- .../TrackParametrization.h | 48 ++-- .../TrackParametrizationWithError.h | 27 +- .../ReconstructionDataFormats/TrackUtils.h | 16 +- .../src/TrackParametrization.cxx | 235 +++++++++--------- .../src/TrackParametrizationWithError.cxx | 175 +++++++------ 5 files changed, 251 insertions(+), 250 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index cd9c8d675c9de..6f8f51103aa20 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -117,7 +117,7 @@ constexpr float kCY2max = 100 * 100, // SigmaY<=100cm kCSnp2max = 1 * 1, // SigmaSin<=1 kCTgl2max = 1 * 1, // SigmaTan<=1 kC1Pt2max = 100 * 100, // Sigma1/Pt<=100 1/GeV - kMostProbablePt = 0.6, // Most Probable Pt (GeV), for running with Bz=0 + kMostProbablePt = 0.6f, // Most Probable Pt (GeV), for running with Bz=0 kCalcdEdxAuto = -999.f; // value indicating request for dedx calculation // access to covariance matrix by row and column @@ -138,13 +138,15 @@ class TrackParametrization public: using value_t = value_T; - using dim3v_t = std::array<value_t, 3>; + using dim2_t = std::array<value_t, 2>; + using dim3_t = std::array<value_t, 3>; + using params_t = std::array<value_t, kNParams>; static_assert(std::is_floating_point_v<value_t>); TrackParametrization() = default; - TrackParametrization(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, int charge = 1); - TrackParametrization(const std::array<value_t, 3>& xyz, const std::array<value_t, 3>& pxpypz, int charge, bool sectorAlpha = true); + TrackParametrization(value_t x, value_t alpha, const params_t& par, int charge = 1); + TrackParametrization(const dim3_t& xyz, const dim3_t& pxpypz, int charge, bool sectorAlpha = true); TrackParametrization(const TrackParametrization&) = default; TrackParametrization(TrackParametrization&&) = default; TrackParametrization& operator=(const TrackParametrization& src) = default; @@ -200,8 +202,8 @@ class TrackParametrization value_t getTheta() const; value_t getEta() const; Point3D<value_t> getXYZGlo() const; - void getXYZGlo(std::array<value_t, 3>& xyz) const; - bool getPxPyPzGlo(std::array<value_t, 3>& pxyz) const; + void getXYZGlo(dim3_t& xyz) const; + bool getPxPyPzGlo(dim3_t& pxyz) const; bool getPosDirGlo(std::array<value_t, 9>& posdirp) const; // methods for track params estimate at other point @@ -214,9 +216,9 @@ class TrackParametrization bool correctForELoss(value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); bool rotateParam(value_t alpha); bool propagateParamTo(value_t xk, value_t b); - bool propagateParamTo(value_t xk, const std::array<value_t, 3>& b); + bool propagateParamTo(value_t xk, const dim3_t& b); - bool propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, std::array<value_t, 2>* dca = nullptr, value_t maxD = 999.f); + bool propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, dim2_t* dca = nullptr, value_t maxD = 999.f); void invertParam(); @@ -237,7 +239,7 @@ class TrackParametrization private: // - static constexpr value_t InvalidX = -99999.; + static constexpr value_t InvalidX = -99999.f; value_t mX = 0.f; /// X of track evaluation value_t mAlpha = 0.f; /// track frame angle value_t mP[kNParams] = {0.f}; /// 5 parameters: Y,Z,sin(phi),tg(lambda),q/pT @@ -250,7 +252,7 @@ class TrackParametrization //____________________________________________________________ template <typename value_T> -inline TrackParametrization<value_T>::TrackParametrization(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, int charge) +inline TrackParametrization<value_T>::TrackParametrization(value_t x, value_t alpha, const params_t& par, int charge) : mX{x}, mAlpha{alpha}, mAbsCharge{char(std::abs(charge))} { // explicit constructor @@ -324,7 +326,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCharge2Pt() const { - return mAbsCharge ? mP[kQ2Pt] : 0.; + return mAbsCharge ? mP[kQ2Pt] : 0.f; } //____________________________________________________________ @@ -353,7 +355,7 @@ inline void TrackParametrization<value_T>::setPID(const PID pid) template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp2() const { - value_t csp2 = (1. - mP[kSnp]) * (1. + mP[kSnp]); + value_t csp2 = (1.f - mP[kSnp]) * (1.f + mP[kSnp]); return csp2 > o2::constants::math::Almost0 ? csp2 : o2::constants::math::Almost0; } @@ -434,10 +436,10 @@ inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::ut // get circle params in track local frame, for straight line just set to local coordinates c.rC = getCurvature(bz); // treat as straight track if sagitta between the vertex and middle of TPC is below 0.01 cm - constexpr value_t MinSagitta = 0.01, TPCMidR = 160., MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR); + constexpr value_t MinSagitta = 0.01f, TPCMidR = 160.f, MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR); if (std::abs(c.rC) > MinCurv) { c.rC = 1.f / getCurvature(bz); - value_t sn = getSnp(), cs = sqrtf((1. - sn) * (1. + sn)); + value_t sn = getSnp(), cs = sqrtf((1.f - sn) * (1.f + sn)); c.xC = getX() - sn * c.rC; // center in tracking c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!! c.rC = fabs(c.rC); @@ -516,7 +518,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPtInv() const { // return the inverted track pT - auto ptInv = fabs(mP[kQ2Pt]); + const value_t ptInv = fabs(mP[kQ2Pt]); return (mAbsCharge > 1) ? ptInv / mAbsCharge : ptInv; } @@ -525,7 +527,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2Inv() const { // return the inverted track momentum^2 - auto p2 = mP[kQ2Pt] * mP[kQ2Pt] / (1.f + getTgl() * getTgl()); + const value_t p2 = mP[kQ2Pt] * mP[kQ2Pt] / (1.f + getTgl() * getTgl()); return (mAbsCharge > 1) ? p2 * mAbsCharge * mAbsCharge : p2; } @@ -534,8 +536,8 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2() const { // return the track momentum^2 - auto p2inv = getP2Inv(); - return (p2inv > o2::constants::math::Almost0) ? 1. / p2inv : o2::constants::math::VeryBig; + const value_t p2inv = getP2Inv(); + return (p2inv > o2::constants::math::Almost0) ? 1.f / p2inv : o2::constants::math::VeryBig; } //____________________________________________________________ @@ -543,7 +545,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPInv() const { // return the inverted track momentum^2 - auto pInv = fabs(mP[kQ2Pt]) / sqrtf(1.f + getTgl() * getTgl()); + const value_t pInv = fabs(mP[kQ2Pt]) / sqrtf(1.f + getTgl() * getTgl()); return (mAbsCharge > 1) ? pInv / mAbsCharge : pInv; } @@ -552,8 +554,8 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP() const { // return the track momentum - value_t pInv = getPInv(); - return (pInv > o2::constants::math::Almost0) ? 1. / pInv : o2::constants::math::VeryBig; + const value_t pInv = getPInv(); + return (pInv > o2::constants::math::Almost0) ? 1.f / pInv : o2::constants::math::VeryBig; } //____________________________________________________________ @@ -579,7 +581,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getEta() const { - return -std::log(std::tan(0.5 * getTheta())); + return -std::log(std::tan(0.5f * getTheta())); } #ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden @@ -593,7 +595,7 @@ inline Point3D<typename TrackParametrization<value_T>::value_t> TrackParametriza //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getXYZGlo(std::array<value_t, 3>& xyz) const +inline void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const { // track coordinates in lab frame xyz[0] = getX(); diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index 4418bef53acaa..f88fcc8ecff53 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -30,13 +30,18 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> using MatrixD5 = ROOT::Math::SMatrix<double, kNParams, kNParams, ROOT::Math::MatRepStd<double, kNParams, kNParams>>; using typename TrackParametrization<value_T>::value_t; + using typename TrackParametrization<value_T>::dim3_t; + using typename TrackParametrization<value_T>::dim2_t; + using typename TrackParametrization<value_T>::params_t; static_assert(std::is_floating_point_v<value_t>); public: + using covMat_t = std::array<value_t, kCovMatSize>; + TrackParametrizationWithError(); - TrackParametrizationWithError(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, const std::array<value_t, kCovMatSize>& cov, int charge = 1); - TrackParametrizationWithError(const std::array<value_t, 3>& xyz, const std::array<value_t, 3>& pxpypz, + TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, const std::array<value_t, kCovMatSize>& cov, int charge = 1); + TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, const std::array<value_t, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); TrackParametrizationWithError(const TrackParametrizationWithError& src) = default; @@ -64,7 +69,7 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> value_t getCovarElem(int i, int j) const; value_t getDiagError2(int i) const; - bool getCovXYZPxPyPzGlo(std::array<value_t, 21>& c) const; + bool getCovXYZPxPyPzGlo(std::array<value_t, kLabCovMatSize>& c) const; #ifndef GPUCA_ALIGPUCODE void print() const; @@ -74,11 +79,11 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> // parameters + covmat manipulation bool rotate(value_t alpha); bool propagateTo(value_t xk, value_t b); - bool propagateTo(value_t xk, const std::array<value_t, 3>& b); + bool propagateTo(value_t xk, const dim3_t& b); bool propagateToDCA(const o2::dataformats::VertexBase& vtx, value_t b, o2::dataformats::DCA* dca = nullptr, value_t maxD = 999.f); void invert(); - value_t getPredictedChi2(const std::array<value_t, 2>& p, const std::array<value_t, 3>& cov) const; + value_t getPredictedChi2(const dim2_t& p, const dim3_t& cov) const; template <typename T> value_t getPredictedChi2(const BaseCluster<T>& p) const; @@ -89,7 +94,7 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> value_t getPredictedChi2(const TrackParametrizationWithError& rhs, MatrixDSym5& covToSet) const; bool update(const TrackParametrizationWithError& rhs, const MatrixDSym5& covInv); - bool update(const std::array<value_t, 2>& p, const std::array<value_t, 3>& cov); + bool update(const dim2_t& p, const dim3_t& cov); template <typename T> bool update(const BaseCluster<T>& p); @@ -119,7 +124,7 @@ inline TrackParametrizationWithError<value_T>::TrackParametrizationWithError() : //__________________________________________________________________________ template <typename value_T> -inline TrackParametrizationWithError<value_T>::TrackParametrizationWithError(value_t x, value_t alpha, const std::array<value_t, kNParams>& par, +inline TrackParametrizationWithError<value_T>::TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, const std::array<value_t, kCovMatSize>& cov, int charge) : TrackParametrization<value_T>{x, alpha, par, charge} { @@ -258,8 +263,8 @@ template <typename value_T> template <typename T> typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const BaseCluster<T>& p) const { - const std::array<value_t, 2> pyz = {p.getY(), p.getZ()}; - const std::array<value_t, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; + const dim2_t pyz = {p.getY(), p.getZ()}; + const dim3_t cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; return getPredictedChi2(pyz, cov); } @@ -268,8 +273,8 @@ template <typename value_T> template <typename T> bool TrackParametrizationWithError<value_T>::update(const BaseCluster<T>& p) { - const std::array<value_t, 2> pyz = {p.getY(), p.getZ()}; - const std::array<value_t, 3> cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; + const dim2_t pyz = {p.getY(), p.getZ()}; + const dim3_t cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; return update(pyz, cov); } diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h index 529b82afc0880..1ff1f87489aac 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h @@ -70,11 +70,11 @@ void g3helx3(value_T qfield, value_T step, std::array<value_T, 7>& vect) value_T tet = rho * step; value_T tsint, sintt, sint, cos1t; - if (fabs(tet) > 0.03f) { - sint = sinf(tet); + if (std::fabs(tet) > 0.03f) { + sint = std::sin(tet); sintt = sint / tet; tsint = (tet - sint) / tet; - value_T t = sinf(0.5f * tet); + value_T t = std::sin(0.5f * tet); cos1t = 2 * t * t / tet; } else { tsint = tet * tet / 6.f; @@ -126,15 +126,15 @@ value_T BetheBlochSolid(value_T bg, value_T rho, value_T kp1, value_T kp2, value //*** Density effect value_T d2 = 0.; - const value_T x = log(bg); - const value_T lhwI = log(28.816 * 1e-9 * std::sqrt(rho * meanZA) / meanI); + const value_T x = std::log(bg); + const value_T lhwI = std::log(28.816f * 1e-9f * std::sqrt(rho * meanZA) / meanI); if (x > kp2) { - d2 = lhwI + x - 0.5; + d2 = lhwI + x - 0.5f; } else if (x > kp1) { double r = (kp2 - x) / (kp2 - kp1); - d2 = lhwI + x - 0.5 + (0.5 - lhwI - kp1) * r * r * r; + d2 = lhwI + x - 0.5f + (0.5f - lhwI - kp1) * r * r * r; } - return mK * meanZA * (1 + bg2) / bg2 * (0.5 * log(2 * me * bg2 * maxT / (meanI * meanI)) - bg2 / (1 + bg2) - d2); + return mK * meanZA * (1 + bg2) / bg2 * (0.5f * std::log(2 * me * bg2 * maxT / (meanI * meanI)) - bg2 / (1 + bg2) - d2); } } // namespace track diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index b84a65b506d35..555dfcc0d70b7 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -32,9 +32,6 @@ #include <fmt/printf.h> #include "Framework/Logger.h" -using std::array; -using namespace o2::constants::math; - namespace o2 { namespace track @@ -42,7 +39,7 @@ namespace track //______________________________________________________________ template <typename value_T> -TrackParametrization<value_T>::TrackParametrization(const array<value_t, 3>& xyz, const array<value_t, 3>& pxpypz, int charge, bool sectorAlpha) +TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim3_t& pxpypz, int charge, bool sectorAlpha) : mX{0.f}, mAlpha{0.f}, mP{0.f} { // construct track param from kinematics @@ -53,7 +50,7 @@ TrackParametrization<value_T>::TrackParametrization(const array<value_t, 3>& xyz // angle of pt direction for r==0 // // - constexpr value_t kSafe = 1e-5f; + constexpr value_t kSafe = 1e-5; value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; value_t alp = 0; if (sectorAlpha || radPos2 < 1) { @@ -68,24 +65,24 @@ TrackParametrization<value_T>::TrackParametrization(const array<value_t, 3>& xyz value_t sn, cs; utils::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 - if (fabs(sn) < 2 * kSafe) { + if (std::fabs(sn) < 2 * kSafe) { if (alp > 0) { - alp += alp < PIHalf ? 2 * kSafe : -2 * kSafe; + alp += alp < constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } else { - alp += alp > -PIHalf ? -2 * kSafe : 2 * kSafe; + alp += alp > -constants::math::PIHalf ? -2 * kSafe : 2 * kSafe; } utils::sincos(alp, sn, cs); - } else if (fabs(cs) < 2 * kSafe) { + } else if (std::fabs(cs) < 2 * kSafe) { if (alp > 0) { - alp += alp > PIHalf ? 2 * kSafe : -2 * kSafe; + alp += alp > constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } else { - alp += alp > -PIHalf ? 2 * kSafe : -2 * kSafe; + alp += alp > -constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } utils::sincos(alp, sn, cs); } // get the vertex of origin and the momentum - array<value_t, 3> ver{xyz[0], xyz[1], xyz[2]}; - array<value_t, 3> mom{pxpypz[0], pxpypz[1], pxpypz[2]}; + dim3_t ver{xyz[0], xyz[1], xyz[2]}; + dim3_t mom{pxpypz[0], pxpypz[1], pxpypz[2]}; // // Rotate to the local coordinate system utils::RotateZ(ver, -alp); @@ -101,20 +98,20 @@ TrackParametrization<value_T>::TrackParametrization(const array<value_t, 3>& xyz mAbsCharge = std::abs(charge); mP[kQ2Pt] = charge ? ptI * charge : ptI; // - if (fabs(1 - getSnp()) < kSafe) { - mP[kSnp] = 1. - kSafe; // Protection - } else if (fabs(-1 - getSnp()) < kSafe) { - mP[kSnp] = -1. + kSafe; // Protection + if (std::fabs(1 - getSnp()) < kSafe) { + mP[kSnp] = 1.f - kSafe; // Protection + } else if (std::fabs(-1 - getSnp()) < kSafe) { + mP[kSnp] = -1.f + kSafe; // Protection } // } //_______________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getPxPyPzGlo(array<value_t, 3>& pxyz) const +bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const { // track momentum - if (fabs(getQ2Pt()) < Almost0 || fabs(getSnp()) > Almost1) { + if (std::fabs(getQ2Pt()) < constants::math::Almost0 || std::fabs(getSnp()) > constants::math::Almost1) { return false; } value_t cs, sn, pt = getPt(); @@ -128,12 +125,12 @@ bool TrackParametrization<value_T>::getPxPyPzGlo(array<value_t, 3>& pxyz) const //____________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getPosDirGlo(array<value_t, 9>& posdirp) const +bool TrackParametrization<value_T>::getPosDirGlo(std::array<value_t, 9>& posdirp) const { // fill vector with lab x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha - value_t ptI = fabs(getQ2Pt()); + value_t ptI = std::fabs(getQ2Pt()); value_t snp = getSnp(); - if (ptI < Almost0 || fabs(snp) > Almost1) { + if (ptI < constants::math::Almost0 || std::fabs(snp) > constants::math::Almost1) { return false; } value_t &sn = posdirp[7], &cs = posdirp[8]; @@ -156,7 +153,7 @@ template <typename value_T> bool TrackParametrization<value_T>::rotateParam(value_t alpha) { // rotate to alpha frame - if (fabs(getSnp()) > Almost1) { + if (std::fabs(getSnp()) > constants::math::Almost1) { LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); return false; } @@ -174,7 +171,7 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) } // value_t tmp = snp * ca - csp * sa; - if (fabs(tmp) > Almost1) { + if (std::fabs(tmp) > constants::math::Almost1) { LOGF(WARNING, "Rotation failed: new snp {:.2f}", tmp); return false; } @@ -188,7 +185,7 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) //____________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const array<value_t, 3>& b) +bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b) { //---------------------------------------------------------------- // Extrapolate this track params (w/o cov matrix) to the plane X=xk in the field b[]. @@ -198,11 +195,11 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const array<val //---------------------------------------------------------------- value_t dx = xk - getX(); - if (fabs(dx) < Almost0) { + if (std::fabs(dx) < constants::math::Almost0) { return true; } // Do not propagate tracks outside the ALICE detector - if (fabs(dx) > 1e5 || fabs(getY()) > 1e5 || fabs(getZ()) > 1e5) { + if (std::fabs(dx) > 1e5 || std::fabs(getY()) > 1e5 || std::fabs(getZ()) > 1e5) { LOGF(WARNING, "Anomalous track, target X:{:f}", xk); // print(); return false; @@ -210,24 +207,24 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const array<val value_t crv = getCurvature(b[2]); value_t x2r = crv * dx; value_t f1 = getSnp(), f2 = f1 + x2r; - if (fabs(f1) > Almost1 || fabs(f2) > Almost1) { + if (std::fabs(f1) > constants::math::Almost1 || std::fabs(f2) > constants::math::Almost1) { return false; } value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { + if (std::fabs(r1) < constants::math::Almost0) { return false; } value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { + if (std::fabs(r2) < constants::math::Almost0) { return false; } value_t dy2dx = (f1 + f2) / (r1 + r2); - value_t step = (fabs(x2r) < 0.05f) ? dx * fabs(r2 + f2 * dy2dx) // chord - : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc + value_t step = (std::fabs(x2r) < 0.05f) ? dx * std::fabs(r2 + f2 * dy2dx) // chord + : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc step *= std::sqrt(1.f + getTgl() * getTgl()); // // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System - array<value_t, 9> vecLab{0.f}; + std::array<value_t, 9> vecLab{0.f}; if (!getPosDirGlo(vecLab)) { return false; } @@ -236,23 +233,23 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const array<val value_t bxy2 = b[0] * b[0] + b[1] * b[1]; value_t bt = std::sqrt(bxy2); value_t cosphi = 1.f, sinphi = 0.f; - if (bt > Almost0) { + if (bt > constants::math::Almost0) { cosphi = b[0] / bt; sinphi = b[1] / bt; } value_t bb = std::sqrt(bxy2 + b[2] * b[2]); - value_t costet = 1., sintet = 0.; - if (bb > Almost0) { + value_t costet = 1.f, sintet = 0.f; + if (bb > constants::math::Almost0) { costet = b[2] / bb; sintet = bt / bb; } - array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], - -sinphi * vecLab[0] + cosphi * vecLab[1], - sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], - costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], - -sinphi * vecLab[3] + cosphi * vecLab[4], - sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], - vecLab[6]}; + std::array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], + -sinphi * vecLab[0] + cosphi * vecLab[1], + sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], + costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], + -sinphi * vecLab[3] + cosphi * vecLab[4], + sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], + vecLab[6]}; // Do the helix step value_t q = getCharge(); @@ -278,8 +275,8 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const array<val // Do the final correcting step to the target plane (linear approximation) value_t x = vecLab[0], y = vecLab[1], z = vecLab[2]; - if (fabs(dx) > Almost0) { - if (fabs(vecLab[3]) < Almost0) { + if (std::fabs(dx) > constants::math::Almost0) { + if (std::fabs(vecLab[3]) < constants::math::Almost0) { return false; } dx = xk - vecLab[0]; @@ -310,28 +307,28 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) // distances only (<mm, i.e. misalignment) //---------------------------------------------------------------- value_t dx = xk - getX(); - if (fabs(dx) < Almost0) { + if (std::fabs(dx) < constants::math::Almost0) { return true; } - value_t crv = (fabs(b) < Almost0) ? 0.f : getCurvature(b); + value_t crv = (std::fabs(b) < constants::math::Almost0) ? 0.f : getCurvature(b); value_t x2r = crv * dx; value_t f1 = getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { return false; } value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { + if (std::fabs(r1) < constants::math::Almost0) { return false; } value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { + if (std::fabs(r2) < constants::math::Almost0) { return false; } mX = xk; double dy2dx = (f1 + f2) / (r1 + r2); mP[kY] += dx * dy2dx; mP[kSnp] += x2r; - if (fabs(x2r) < 0.05f) { + if (std::fabs(x2r) < 0.05f) { mP[kZ] += dx * (r2 + f2 * dy2dx) * getTgl(); } else { // for small dx/R the linear apporximation of the arc by the segment is OK, @@ -345,9 +342,9 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles if (f2 > 0.f) { - rot = PI - rot; // + rot = constants::math::PI - rot; // } else { - rot = -PI - rot; + rot = -constants::math::PI - rot; } } mP[kZ] += getTgl() / crv * rot; @@ -357,11 +354,11 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) //_______________________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, std::array<value_t, 2>* dca, value_t maxD) +bool TrackParametrization<value_T>::propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, dim2_t* dca, value_t maxD) { // propagate track to DCA to the vertex value_t sn, cs, alp = getAlpha(); - o2::utils::sincos(alp, sn, cs); + utils::sincos(alp, sn, cs); value_t x = getX(), y = getY(), snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); value_t xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; @@ -374,8 +371,8 @@ bool TrackParametrization<value_T>::propagateParamToDCA(const Point3D<value_t>& value_t crv = getCurvature(b); value_t tgfv = -(crv * x - snp) / (crv * y + csp); sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > Almost0) ? sn / tgfv : Almost1; + cs = std::sqrt((1.f - sn) * (1.f + sn)); + cs = (std::abs(tgfv) > constants::math::Almost0) ? sn / tgfv : constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; @@ -405,27 +402,27 @@ bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, v // estimate Y,Z in tracking frame at given X //---------------------------------------------------------------- value_t dx = xk - getX(); - if (fabs(dx) < Almost0) { + if (std::fabs(dx) < constants::math::Almost0) { return true; } value_t crv = getCurvature(b); value_t x2r = crv * dx; value_t f1 = getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { return false; } value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { + if (std::fabs(r1) < constants::math::Almost0) { return false; } value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { + if (std::fabs(r2) < constants::math::Almost0) { return false; } double dy2dx = (f1 + f2) / (r1 + r2); y = mP[kY] + dx * dy2dx; z = mP[kZ]; - if (fabs(x2r) < 0.05f) { + if (std::fabs(x2r) < 0.05f) { z += dx * (r2 + f2 * dy2dx) * getTgl(); } else { // for small dx/R the linear apporximation of the arc by the segment is OK, @@ -439,9 +436,9 @@ bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, v value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles if (f2 > 0.f) { - rot = PI - rot; // + rot = constants::math::PI - rot; // } else { - rot = -PI - rot; + rot = -constants::math::PI - rot; } } z += getTgl() / crv * rot; @@ -455,7 +452,7 @@ void TrackParametrization<value_T>::invertParam() { // Transform this track to the local coord. system rotated by 180 deg. mX = -mX; - mAlpha += PI; + mAlpha += constants::math::PI; utils::BringToPMPi(mAlpha); // mP[0] = -mP[0]; @@ -470,7 +467,7 @@ typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::g { ///< this method is just an alias for obtaining Z @ X in the tree->Draw() value_t y, z; - return getYZAt(xk, b, y, z) ? z : -9999.; + return getYZAt(xk, b, y, z) ? z : -9999.f; } //______________________________________________________________ @@ -479,7 +476,7 @@ typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::g { ///< this method is just an alias for obtaining Z @ X in the tree->Draw() value_t y, z; - return getYZAt(xk, b, y, z) ? y : -9999.; + return getYZAt(xk, b, y, z) ? y : -9999.f; } #ifndef GPUCA_ALIGPUCODE @@ -503,7 +500,7 @@ void TrackParametrization<value_T>::printParam() const //______________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz, o2::track::DirType dir) const +bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz, track::DirType dir) const { // Get local X of the track position estimated at the radius lab radius r. // The track curvature is accounted exactly @@ -517,26 +514,26 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz const value_t kEps = 1.e-6; // auto crv = getCurvature(bz); - if (fabs(crv) > o2::constants::math::Almost0) { // helix + if (std::fabs(crv) > constants::math::Almost0) { // helix // get center of the track circle - o2::utils::CircleXY circle; + utils::CircleXY circle; getCircleParamsLoc(bz, circle); - auto r0 = std::sqrt(circle.getCenterD2()); - if (r0 <= o2::constants::math::Almost0) { + value_t r0 = std::sqrt(circle.getCenterD2()); + if (r0 <= constants::math::Almost0) { return false; // the track is concentric to circle } - value_t tR2r0 = 1., g = 0., tmp = 0.; - if (fabs(circle.rC - r0) > kEps) { + value_t tR2r0 = 1.f, g = 0.f, tmp = 0.f; + if (std::fabs(circle.rC - r0) > kEps) { tR2r0 = circle.rC / r0; - g = 0.5 * (r * r / (r0 * circle.rC) - tR2r0 - 1. / tR2r0); - tmp = 1. + g * tR2r0; + g = 0.5f * (r * r / (r0 * circle.rC) - tR2r0 - 1.f / tR2r0); + tmp = 1.f + g * tR2r0; } else { tR2r0 = 1.0; - g = 0.5 * r * r / (r0 * circle.rC) - 1.; - tmp = 0.5 * r * r / (r0 * r0); + g = 0.5f * r * r / (r0 * circle.rC) - 1.f; + tmp = 0.5f * r * r / (r0 * r0); } - auto det = (1. - g) * (1. + g); - if (det < 0.) { + value_t det = (1.f - g) * (1.f + g); + if (det < 0.f) { return false; // does not reach raduis r } det = std::sqrt(det); @@ -546,42 +543,42 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz // where s0 and c0 make direction for the circle center (=circle.xC/r0 and circle.yC/r0) // x = circle.xC * tmp; - auto y = circle.yC * tmp; - if (fabs(circle.yC) > o2::constants::math::Almost0) { // when circle.yC==0 the x,y is unique - auto dfx = tR2r0 * fabs(circle.yC) * det; - auto dfy = tR2r0 * circle.xC * (circle.yC > 0. ? det : -det); - if (dir == DirAuto) { // chose the one which corresponds to smallest step - auto delta = (x - mX) * dfx - (y - fy) * dfy; // the choice of + in C will lead to smaller step if delta<0 - x += delta < 0. ? dfx : -dfx; + value_t y = circle.yC * tmp; + if (std::fabs(circle.yC) > constants::math::Almost0) { // when circle.yC==0 the x,y is unique + value_t dfx = tR2r0 * std::fabs(circle.yC) * det; + value_t dfy = tR2r0 * circle.xC * (circle.yC > 0.f ? det : -det); + if (dir == DirAuto) { // chose the one which corresponds to smallest step + value_t delta = (x - mX) * dfx - (y - fy) * dfy; // the choice of + in C will lead to smaller step if delta<0 + x += delta < 0.f ? dfx : -dfx; } else if (dir == DirOutward) { // along track direction: x must be > mX x -= dfx; // try the smallest step (dfx is positive) - auto dfeps = mX - x; // handle special case of very small step + value_t dfeps = mX - x; // handle special case of very small step if (dfeps < -kEps) { return true; } - if (fabs(dfeps) < kEps && fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? + if (std::fabs(dfeps) < kEps && std::fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? return mX; } x += dfx + dfx; - auto dxm = x - mX; - if (dxm > 0.) { + value_t dxm = x - mX; + if (dxm > 0.f) { return true; } else if (dxm < -kEps) { return false; } - x = mX; // don't move - } else { // backward: x must be < mX - x += dfx; // try the smallest step (dfx is positive) - auto dfeps = x - mX; // handle special case of very small step + x = mX; // don't move + } else { // backward: x must be < mX + x += dfx; // try the smallest step (dfx is positive) + value_t dfeps = x - mX; // handle special case of very small step if (dfeps < -kEps) { return true; } - if (fabs(dfeps) < kEps && fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? + if (std::fabs(dfeps) < kEps && std::fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? return mX; } x -= dfx + dfx; - auto dxm = x - mX; - if (dxm < 0.) { + value_t dxm = x - mX; + if (dxm < 0.f) { return true; } if (dxm > kEps) { @@ -594,10 +591,10 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz return false; } } - } else { // this is a straight track - if (fabs(sn) >= o2::constants::math::Almost1) { // || to Y axis - auto det = (r - mX) * (r + mX); - if (det < 0.) { + } else { // this is a straight track + if (std::fabs(sn) >= constants::math::Almost1) { // || to Y axis + value_t det = (r - mX) * (r + mX); + if (det < 0.f) { return false; // does not reach raduis r } x = mX; @@ -606,7 +603,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz } det = std::sqrt(det); if (dir == DirOutward) { // along the track direction - if (sn > 0.) { + if (sn > 0.f) { if (fy > det) { return false; // track is along Y axis and above the circle } @@ -616,7 +613,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz } } } else if (dir == DirInward) { // against track direction - if (sn > 0.) { + if (sn > 0.f) { if (fy < -det) { return false; // track is along Y axis } @@ -624,14 +621,14 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz return false; // track is against Y axis } } - } else if (fabs(sn) <= o2::constants::math::Almost0) { // || to X axis - auto det = (r - fy) * (r + fy); - if (det < 0.) { + } else if (std::fabs(sn) <= constants::math::Almost0) { // || to X axis + value_t det = (r - fy) * (r + fy); + if (det < 0.f) { return false; // does not reach raduis r } det = std::sqrt(det); if (dir == DirAuto) { - x = mX > 0. ? det : -det; // choose the solution requiring the smalest step + x = mX > 0.f ? det : -det; // choose the solution requiring the smalest step return true; } else if (dir == DirOutward) { // along the track direction if (mX > det) { @@ -647,18 +644,18 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz } } } else { // general case of straight line - auto cs = std::sqrt((1 - sn) * (1 + sn)); - auto xsyc = mX * sn - fy * cs; - auto det = (r - xsyc) * (r + xsyc); - if (det < 0.) { + value_t cs = std::sqrt((1.f - sn) * (1.f + sn)); + value_t xsyc = mX * sn - fy * cs; + value_t det = (r - xsyc) * (r + xsyc); + if (det < 0.f) { return false; // does not reach raduis r } det = std::sqrt(det); - auto xcys = mX * cs + fy * sn; - auto t = -xcys; + value_t xcys = mX * cs + fy * sn; + value_t t = -xcys; if (dir == DirAuto) { - t += t > 0. ? -det : det; // chose the solution requiring the smalest step - } else if (dir > 0) { // go in increasing mX direction. ( t+-det > 0) + t += t > 0.f ? -det : det; // chose the solution requiring the smalest step + } else if (dir > 0) { // go in increasing mX direction. ( t+-det > 0) if (t >= -det) { t += -det; // take minimal step giving t>0 } else { @@ -712,8 +709,8 @@ bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, // Calculating the energy loss corrections************************ if ((xrho != 0.f) && (beta2 < 1.f)) { - if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / fabs(mass)); + if (dedx < kCalcdEdxAuto + constants::math::Almost1) { // request to calculate dedx on the fly + dedx = BetheBlochSolid(p / std::fabs(mass)); if (mAbsCharge != 1) { dedx *= mAbsCharge * mAbsCharge; } @@ -721,7 +718,7 @@ bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, value_t dE = dedx * xrho; value_t e = std::sqrt(e2); - if (fabs(dE) > kMaxELossFrac * e) { + if (std::fabs(dE) > kMaxELossFrac * e) { return false; // 30% energy loss is too much! } value_t eupd = e + dE; diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index 8573411777aed..43334c905d6c2 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -32,9 +32,6 @@ #include <fmt/printf.h> #include "Framework/Logger.h" -using std::array; -using namespace o2::constants::math; - namespace o2 { namespace track @@ -63,21 +60,21 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) // propagate this track to the plane X=xk (cm) in the field "b" (kG) //---------------------------------------------------------------- value_t dx = xk - this->getX(); - if (fabs(dx) < Almost0) { + if (std::fabs(dx) < constants::math::Almost0) { return true; } value_t crv = this->getCurvature(b); value_t x2r = crv * dx; value_t f1 = this->getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { return false; } value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { + if (std::fabs(r1) < constants::math::Almost0) { return false; } value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { + if (std::fabs(r2) < constants::math::Almost0) { return false; } this->setX(xk); @@ -85,7 +82,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) value_t dP[kNParams] = {0.f}; dP[kY] = dx * dy2dx; dP[kSnp] = x2r; - if (fabs(x2r) < 0.05f) { + if (std::fabs(x2r) < 0.05f) { dP[kZ] = dx * (r2 + f2 * dy2dx) * this->getTgl(); } else { // for small dx/R the linear apporximation of the arc by the segment is OK, @@ -96,12 +93,12 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center // mP1 += rot/crv*mP3; // - value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. + value_t rot = std::asin(r1 * f2 - r2 * f1); // more economic version from Yura. if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles if (f2 > 0.f) { - rot = PI - rot; // + rot = constants::math::PI - rot; // } else { - rot = -PI - rot; + rot = -constants::math::PI - rot; } } dP[kZ] = this->getTgl() / crv * rot; @@ -117,7 +114,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) // evaluate matrix in double prec. double rinv = 1. / r1; double r3inv = rinv * rinv * rinv; - double f24 = dx * b * B2C; // x2r/mP[kQ2Pt]; + double f24 = dx * b * constants::math::B2C; // x2r/mP[kQ2Pt]; double f02 = dx * r3inv; double f04 = 0.5 * f24 * f02; double f12 = f02 * this->getTgl() * f1; @@ -165,7 +162,7 @@ template <typename value_T> bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) { // rotate to alpha frame - if (fabs(this->getSnp()) > Almost1) { + if (std::fabs(this->getSnp()) > constants::math::Almost1) { LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", this->getSnp()); return false; } @@ -184,7 +181,7 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) // value_t updSnp = snp * ca - csp * sa; - if (fabs(updSnp) > Almost1) { + if (std::fabs(updSnp) > constants::math::Almost1) { LOGF(WARNING, "Rotation failed: new snp {:.2f}", updSnp); return false; } @@ -194,9 +191,9 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) this->setY(-xold * sa + yold * ca); this->setSnp(updSnp); - if (fabs(csp) < Almost0) { + if (std::fabs(csp) < constants::math::Almost0) { LOGF(WARNING, "Too small cosine value {:f}", csp); - csp = Almost0; + csp = constants::math::Almost0; } value_t rr = (ca + snp / csp * sa); @@ -234,8 +231,8 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat value_t crv = this->getCurvature(b); value_t tgfv = -(crv * x - snp) / (crv * y + csp); sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > Almost0) ? sn / tgfv : Almost1; + cs = std::sqrt((1.f - sn) * (1.f + sn)); + cs = (std::abs(tgfv) > constants::math::Almost0) ? sn / tgfv : constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; @@ -259,8 +256,8 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat //______________________________________________________________ template <typename value_T> -TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const array<value_t, 3>& xyz, const array<value_t, 3>& pxpypz, - const array<value_t, kLabCovMatSize>& cv, int charge, bool sectorAlpha) +TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, + const std::array<value_t, kLabCovMatSize>& cv, int charge, bool sectorAlpha) { // construct track param and covariance from kinematics and lab errors @@ -274,9 +271,9 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const arra value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; value_t alp = 0; if (sectorAlpha || radPos2 < 1) { - alp = atan2f(pxpypz[1], pxpypz[0]); + alp = std::atan2(pxpypz[1], pxpypz[0]); } else { - alp = atan2f(xyz[1], xyz[0]); + alp = std::atan2(xyz[1], xyz[0]); } if (sectorAlpha) { alp = utils::Angle2Alpha(alp); @@ -285,24 +282,24 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const arra value_t sn, cs; utils::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 - if (fabs(sn) < 2.f * kSafe) { + if (std::fabs(sn) < 2.f * kSafe) { if (alp > 0) { - alp += alp < PIHalf ? 2.f * kSafe : -2.f * kSafe; + alp += alp < constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } else { - alp += alp > -PIHalf ? -2.f * kSafe : 2.f * kSafe; + alp += alp > -constants::math::PIHalf ? -2.f * kSafe : 2.f * kSafe; } utils::sincos(alp, sn, cs); - } else if (fabs(cs) < 2.f * kSafe) { + } else if (std::fabs(cs) < 2.f * kSafe) { if (alp > 0) { - alp += alp > PIHalf ? 2.f * kSafe : -2.f * kSafe; + alp += alp > constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } else { - alp += alp > -PIHalf ? 2.f * kSafe : -2.f * kSafe; + alp += alp > -constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } utils::sincos(alp, sn, cs); } // get the vertex of origin and the momentum - array<value_t, 3> ver{xyz[0], xyz[1], xyz[2]}; - array<value_t, 3> mom{pxpypz[0], pxpypz[1], pxpypz[2]}; + dim3_t ver{xyz[0], xyz[1], xyz[2]}; + dim3_t mom{pxpypz[0], pxpypz[1], pxpypz[2]}; // // Rotate to the local coordinate system utils::RotateZ(ver, -alp); @@ -319,9 +316,9 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const arra this->setAbsCharge(std::abs(charge)); this->setQ2Pt(charge ? ptI * charge : ptI); // - if (fabs(1.f - this->getSnp()) < kSafe) { + if (std::fabs(1.f - this->getSnp()) < kSafe) { this->setSnp(1.f - kSafe); // Protection - } else if (fabs(-1.f - this->getSnp()) < kSafe) { + } else if (std::fabs(-1.f - this->getSnp()) < kSafe) { this->setSnp(-1.f + kSafe); // Protection } // @@ -331,10 +328,10 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const arra // int special = 0; value_t sgcheck = r * sn + this->getSnp() * cs; - if (fabs(sgcheck) > 1 - kSafe) { // special case: lab phi is +-pi/2 + if (std::fabs(sgcheck) > 1 - kSafe) { // special case: lab phi is +-pi/2 special = 1; sgcheck = sgcheck < 0 ? -1.f : 1.f; - } else if (fabs(sgcheck) < kSafe) { + } else if (std::fabs(sgcheck) < kSafe) { sgcheck = cs < 0 ? -1.0f : 1.0f; special = 2; // special case: lab phi is 0 } @@ -348,29 +345,29 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const arra if (special == 1) { mC[kSigSnpY] = cv[6] * ptI; mC[kSigSnpZ] = -sgcheck * cv[8] * r * ptI; - mC[kSigSnp2] = fabs(cv[9] * r * r * ptI2); + mC[kSigSnp2] = std::fabs(cv[9] * r * r * ptI2); mC[kSigTglY] = (cv[10] * this->getTgl() - sgcheck * cv[15]) * ptI / r; mC[kSigTglZ] = (cv[17] - sgcheck * cv[12] * this->getTgl()) * ptI; mC[kSigTglSnp] = (-sgcheck * cv[18] + cv[13] * this->getTgl()) * r * ptI2; - mC[kSigTgl2] = fabs(cv[20] - 2 * sgcheck * cv[19] * mC[4] + cv[14] * tgl2) * ptI2; + mC[kSigTgl2] = std::fabs(cv[20] - 2 * sgcheck * cv[19] * mC[4] + cv[14] * tgl2) * ptI2; mC[kSigQ2PtY] = cv[10] * ptI2 / r * charge; mC[kSigQ2PtZ] = -sgcheck * cv[12] * ptI2 * charge; mC[kSigQ2PtSnp] = cv[13] * r * ptI * ptI2 * charge; mC[kSigQ2PtTgl] = (-sgcheck * cv[19] + cv[14] * this->getTgl()) * r * ptI2 * ptI; - mC[kSigQ2Pt2] = fabs(cv[14] * ptI2 * ptI2); + mC[kSigQ2Pt2] = std::fabs(cv[14] * ptI2 * ptI2); } else if (special == 2) { mC[kSigSnpY] = -cv[10] * ptI * cs / sn; mC[kSigSnpZ] = cv[12] * cs * ptI; - mC[kSigSnp2] = fabs(cv[14] * cs * cs * ptI2); + mC[kSigSnp2] = std::fabs(cv[14] * cs * cs * ptI2); mC[kSigTglY] = (sgcheck * cv[6] * this->getTgl() - cv[15]) * ptI / sn; mC[kSigTglZ] = (cv[17] - sgcheck * cv[8] * this->getTgl()) * ptI; mC[kSigTglSnp] = (cv[19] - sgcheck * cv[13] * this->getTgl()) * cs * ptI2; - mC[kSigTgl2] = fabs(cv[20] - 2 * sgcheck * cv[18] * this->getTgl() + cv[9] * tgl2) * ptI2; + mC[kSigTgl2] = std::fabs(cv[20] - 2 * sgcheck * cv[18] * this->getTgl() + cv[9] * tgl2) * ptI2; mC[kSigQ2PtY] = sgcheck * cv[6] * ptI2 / sn * charge; mC[kSigQ2PtZ] = -sgcheck * cv[8] * ptI2 * charge; mC[kSigQ2PtSnp] = -sgcheck * cv[13] * cs * ptI * ptI2 * charge; mC[kSigQ2PtTgl] = (-sgcheck * cv[18] + cv[9] * this->getTgl()) * ptI2 * ptI * charge; - mC[kSigQ2Pt2] = fabs(cv[9] * ptI2 * ptI2); + mC[kSigQ2Pt2] = std::fabs(cv[9] * ptI2 * ptI2); } else { double m00 = -sn; // m10=cs; double m23 = -pt * (sn + this->getSnp() * cs / r), m43 = -pt * pt * (r * cs - this->getSnp() * sn); @@ -394,8 +391,8 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const arra mC[kSigSnpZ] = (cv[12] * m43 - cv[8] * m44) / (m24 * m43 - m23 * m44); mC[kSigQ2PtZ] = (cv[8] - mC[kSigSnpZ] * m23) / m43; mC[kSigTglZ] = cv[17] / m35 - mC[kSigQ2PtZ] * m45 / m35; - mC[kSigSnp2] = fabs((a4 * a3 - a6 * a1) / (a5 * a3 - a6 * a2)); - mC[kSigQ2Pt2] = fabs((a1 - a2 * mC[kSigSnp2]) / a3); + mC[kSigSnp2] = std::fabs((a4 * a3 - a6 * a1) / (a5 * a3 - a6 * a2)); + mC[kSigQ2Pt2] = std::fabs((a1 - a2 * mC[kSigSnp2]) / a3); mC[kSigQ2PtSnp] = (cv[9] - mC[kSigSnp2] * m23 * m23 - mC[kSigQ2Pt2] * m43 * m43) / m23 / m43; double b1 = cv[18] - mC[kSigQ2PtSnp] * m23 * m45 - mC[kSigQ2Pt2] * m43 * m45; double b2 = m23 * m35; @@ -405,14 +402,14 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const arra double b6 = m44 * m35; mC[kSigTglSnp] = (b4 - b6 * b1 / b3) / (b5 - b6 * b2 / b3); mC[kSigQ2PtTgl] = b1 / b3 - b2 * mC[kSigTglSnp] / b3; - mC[kSigTgl2] = fabs((cv[20] - mC[kSigQ2Pt2] * (m45 * m45) - mC[kSigQ2PtTgl] * 2. * m35 * m45) / (m35 * m35)); + mC[kSigTgl2] = std::fabs((cv[20] - mC[kSigQ2Pt2] * (m45 * m45) - mC[kSigQ2PtTgl] * 2.f * m35 * m45) / (m35 * m35)); } checkCovariance(); } //____________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const array<value_t, 3>& b) +bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_t& b) { //---------------------------------------------------------------- // Extrapolate this track to the plane X=xk in the field b[]. @@ -422,37 +419,37 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const array //---------------------------------------------------------------- value_t dx = xk - this->getX(); - if (fabs(dx) < Almost0) { + if (std::fabs(dx) < constants::math::Almost0) { return true; } // Do not propagate tracks outside the ALICE detector - if (fabs(dx) > 1e5 || fabs(this->getY()) > 1e5 || fabs(this->getZ()) > 1e5) { + if (std::fabs(dx) > 1e5 || std::fabs(this->getY()) > 1e5 || std::fabs(this->getZ()) > 1e5) { LOGF(WARNING, "Anomalous track, target X:{:f}", xk); // print(); return false; } - value_t crv = (fabs(b[2]) < Almost0) ? 0.f : this->getCurvature(b[2]); + value_t crv = (std::fabs(b[2]) < constants::math::Almost0) ? 0.f : this->getCurvature(b[2]); value_t x2r = crv * dx; value_t f1 = this->getSnp(), f2 = f1 + x2r; - if ((fabs(f1) > Almost1) || (fabs(f2) > Almost1)) { + if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { return false; } value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (fabs(r1) < Almost0) { + if (std::fabs(r1) < constants::math::Almost0) { return false; } value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (fabs(r2) < Almost0) { + if (std::fabs(r2) < constants::math::Almost0) { return false; } value_t dy2dx = (f1 + f2) / (r1 + r2); - value_t step = (fabs(x2r) < 0.05f) ? dx * fabs(r2 + f2 * dy2dx) // chord - : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc + value_t step = (std::fabs(x2r) < 0.05f) ? dx * std::fabs(r2 + f2 * dy2dx) // chord + : 2.f * std::asin(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc step *= std::sqrt(1.f + this->getTgl() * this->getTgl()); // // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System - array<value_t, 9> vecLab{0.f}; + std::array<value_t, 9> vecLab{0.f}; if (!this->getPosDirGlo(vecLab)) { return false; } @@ -465,7 +462,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const array // evaluate matrix in double prec. double rinv = 1. / r1; double r3inv = rinv * rinv * rinv; - double f24 = dx * b[2] * B2C; // x2r/track[kQ2Pt]; + double f24 = dx * b[2] * constants::math::B2C; // x2r/track[kQ2Pt]; double f02 = dx * r3inv; double f04 = 0.5 * f24 * f02; double f12 = f02 * this->getTgl() * f1; @@ -509,23 +506,23 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const array value_t bxy2 = b[0] * b[0] + b[1] * b[1]; value_t bt = std::sqrt(bxy2); value_t cosphi = 1.f, sinphi = 0.f; - if (bt > Almost0) { + if (bt > constants::math::Almost0) { cosphi = b[0] / bt; sinphi = b[1] / bt; } value_t bb = std::sqrt(bxy2 + b[2] * b[2]); value_t costet = 1., sintet = 0.; - if (bb > Almost0) { + if (bb > constants::math::Almost0) { costet = b[2] / bb; sintet = bt / bb; } - array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], - -sinphi * vecLab[0] + cosphi * vecLab[1], - sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], - costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], - -sinphi * vecLab[3] + cosphi * vecLab[4], - sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], - vecLab[6]}; + std::array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], + -sinphi * vecLab[0] + cosphi * vecLab[1], + sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], + costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], + -sinphi * vecLab[3] + cosphi * vecLab[4], + sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], + vecLab[6]}; // Do the helix step value_t sgn = this->getSign(); @@ -551,8 +548,8 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const array // Do the final correcting step to the target plane (linear approximation) value_t x = vecLab[0], y = vecLab[1], z = vecLab[2]; - if (fabs(dx) > Almost0) { - if (fabs(vecLab[3]) < Almost0) { + if (std::fabs(dx) > constants::math::Almost0) { + if (std::fabs(vecLab[3]) < constants::math::Almost0) { return false; } dx = xk - vecLab[0]; @@ -581,7 +578,7 @@ void TrackParametrizationWithError<value_T>::checkCovariance() // In case the diagonal element is bigger than the maximal allowed value, it is set to // the limit and the off-diagonal elements that correspond to it are set to zero. - mC[kSigY2] = fabs(mC[kSigY2]); + mC[kSigY2] = std::fabs(mC[kSigY2]); if (mC[kSigY2] > kCY2max) { value_t scl = std::sqrt(kCY2max / mC[kSigY2]); mC[kSigY2] = kCY2max; @@ -590,7 +587,7 @@ void TrackParametrizationWithError<value_T>::checkCovariance() mC[kSigTglY] *= scl; mC[kSigQ2PtY] *= scl; } - mC[kSigZ2] = fabs(mC[kSigZ2]); + mC[kSigZ2] = std::fabs(mC[kSigZ2]); if (mC[kSigZ2] > kCZ2max) { value_t scl = std::sqrt(kCZ2max / mC[kSigZ2]); mC[kSigZ2] = kCZ2max; @@ -599,7 +596,7 @@ void TrackParametrizationWithError<value_T>::checkCovariance() mC[kSigTglZ] *= scl; mC[kSigQ2PtZ] *= scl; } - mC[kSigSnp2] = fabs(mC[kSigSnp2]); + mC[kSigSnp2] = std::fabs(mC[kSigSnp2]); if (mC[kSigSnp2] > kCSnp2max) { value_t scl = std::sqrt(kCSnp2max / mC[kSigSnp2]); mC[kSigSnp2] = kCSnp2max; @@ -608,7 +605,7 @@ void TrackParametrizationWithError<value_T>::checkCovariance() mC[kSigTglSnp] *= scl; mC[kSigQ2PtSnp] *= scl; } - mC[kSigTgl2] = fabs(mC[kSigTgl2]); + mC[kSigTgl2] = std::fabs(mC[kSigTgl2]); if (mC[kSigTgl2] > kCTgl2max) { value_t scl = std::sqrt(kCTgl2max / mC[kSigTgl2]); mC[kSigTgl2] = kCTgl2max; @@ -617,7 +614,7 @@ void TrackParametrizationWithError<value_T>::checkCovariance() mC[kSigTglSnp] *= scl; mC[kSigQ2PtTgl] *= scl; } - mC[kSigQ2Pt2] = fabs(mC[kSigQ2Pt2]); + mC[kSigQ2Pt2] = std::fabs(mC[kSigQ2Pt2]); if (mC[kSigQ2Pt2] > kC1Pt2max) { value_t scl = std::sqrt(kC1Pt2max / mC[kSigQ2Pt2]); mC[kSigQ2Pt2] = kC1Pt2max; @@ -634,7 +631,7 @@ void TrackParametrizationWithError<value_T>::resetCovariance(value_t s2) { // Reset the covarince matrix to "something big" double d0(kCY2max), d1(kCZ2max), d2(kCSnp2max), d3(kCTgl2max), d4(kC1Pt2max); - if (s2 > Almost0) { + if (s2 > constants::math::Almost0) { d0 = getSigmaY2() * s2; d1 = getSigmaZ2() * s2; d2 = getSigmaSnp2() * s2; @@ -666,7 +663,7 @@ void TrackParametrizationWithError<value_T>::resetCovariance(value_t s2) //______________________________________________ template <typename value_T> -typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const array<value_t, 2>& p, const array<value_t, 3>& cov) const +typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const dim2_t& p, const dim3_t& cov) const { // Estimate the chi2 of the space point "p" with the cov. matrix "cov" auto sdd = static_cast<double>(getSigmaY2()) + static_cast<double>(cov[0]); @@ -674,8 +671,8 @@ typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWit auto szz = static_cast<double>(getSigmaZ2()) + static_cast<double>(cov[2]); auto det = sdd * szz - sdz * sdz; - if (fabs(det) < Almost0) { - return VeryBig; + if (std::fabs(det) < constants::math::Almost0) { + return constants::math::VeryBig; } value_t d = this->getY() - p[0]; @@ -723,16 +720,16 @@ typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWit if (std::abs(this->getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { LOG(ERROR) << "The reference Alpha of the tracks differ: " << this->getAlpha() << " : " << rhs.getAlpha(); - return 2. * HugeF; + return 2.f * HugeF; } if (std::abs(this->getX() - rhs.getX()) > FLT_EPSILON) { LOG(ERROR) << "The reference X of the tracks differ: " << this->getX() << " : " << rhs.getX(); - return 2. * HugeF; + return 2.f * HugeF; } buildCombinedCovMatrix(rhs, covToSet); if (!covToSet.Invert()) { LOG(WARNING) << "Cov.matrix inversion failed: " << covToSet; - return 2. * HugeF; + return 2.f * HugeF; } double chi2diag = 0., chi2ndiag = 0., diff[kNParams]; for (int i = kNParams; i--;) { @@ -831,7 +828,7 @@ bool TrackParametrizationWithError<value_T>::update(const TrackParametrizationWi //______________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::update(const array<value_t, 2>& p, const array<value_t, 3>& cov) +bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, const dim3_t& cov) { // Update the track parameters with the space point "p" having // the covariance matrix "cov" @@ -847,7 +844,7 @@ bool TrackParametrizationWithError<value_T>::update(const array<value_t, 2>& p, double r11 = static_cast<double>(cov[2]) + static_cast<double>(cm11); double det = r00 * r11 - r01 * r01; - if (fabs(det) < Almost0) { + if (std::fabs(det) < constants::math::Almost0) { return false; } double detI = 1. / det; @@ -864,7 +861,7 @@ bool TrackParametrizationWithError<value_T>::update(const array<value_t, 2>& p, value_t dy = p[kY] - this->getY(), dz = p[kZ] - this->getZ(); value_t dsnp = k20 * dy + k21 * dz; - if (fabs(this->getSnp() + dsnp) > Almost1) { + if (std::fabs(this->getSnp() + dsnp) > constants::math::Almost1) { return false; } @@ -927,7 +924,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va value_t cst2I = (1.f + this->getTgl() * this->getTgl()); // 1/cos(lambda)^2 // Apply angle correction, if requested if (anglecorr) { - value_t angle = std::sqrt(cst2I / (csp2)); + value_t angle = std::sqrt(cst2I / csp2); x2x0 *= angle; xrho *= angle; } @@ -940,11 +937,11 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va // Calculating the multiple scattering corrections****************** value_t cC22(0.f), cC33(0.f), cC43(0.f), cC44(0.f); if (x2x0 != 0.f) { - value_t theta2 = kMSConst2 / (beta2 * p2) * fabs(x2x0); + value_t theta2 = kMSConst2 / (beta2 * p2) * std::fabs(x2x0); if (this->getAbsCharge() != 1) { theta2 *= this->getAbsCharge() * this->getAbsCharge(); } - if (theta2 > PI * PI) { + if (theta2 > constants::math::PI * constants::math::PI) { return false; } value_t fp34 = this->getTgl() * this->getCharge2Pt(); @@ -963,8 +960,8 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va // Calculating the energy loss corrections************************ value_t cP4 = 1.f; if ((xrho != 0.f) && (beta2 < 1.f)) { - if (dedx < kCalcdEdxAuto + Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / fabs(mass)); + if (dedx < kCalcdEdxAuto + constants::math::Almost1) { // request to calculate dedx on the fly + dedx = BetheBlochSolid(p / std::fabs(mass)); if (this->getAbsCharge() != 1) { dedx *= this->getAbsCharge() * this->getAbsCharge(); } @@ -972,7 +969,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va value_t dE = dedx * xrho; value_t e = std::sqrt(e2); - if (fabs(dE) > kMaxELossFrac * e) { + if (std::fabs(dE) > kMaxELossFrac * e) { return false; // 30% energy loss is too much! } value_t eupd = e + dE; @@ -984,7 +981,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va // // Approximate energy loss fluctuation (M.Ivanov) constexpr value_t knst = 0.07f; // To be tuned. - value_t sigmadE = knst * std::sqrt(fabs(dE)) * e / p2 * this->getCharge2Pt(); + value_t sigmadE = knst * std::sqrt(std::fabs(dE)) * e / p2 * this->getCharge2Pt(); cC44 += sigmadE * sigmadE; } @@ -1002,7 +999,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va //______________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(std::array<value_t, 21>& cv) const +bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(std::array<value_t, kLabCovMatSize>& cv) const { //--------------------------------------------------------------------- // This function returns the global covariance matrix of the track params @@ -1016,7 +1013,7 @@ bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(std::array<value // // Results for (nearly) straight tracks are meaningless ! //--------------------------------------------------------------------- - if (std::abs(this->getQ2Pt()) <= Almost0 || std::abs(this->getSnp()) > Almost1) { + if (std::abs(this->getQ2Pt()) <= constants::math::Almost0 || std::abs(this->getSnp()) > constants::math::Almost1) { for (int i = 0; i < 21; i++) { cv[i] = 0.; } From 7f49667025e8fe6bded0dfee2635591b0ea4b2d2 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Wed, 7 Oct 2020 19:54:52 +0200 Subject: [PATCH 0864/1751] changing default table name to O2<TREE> convention (#4525) --- Framework/Core/src/DataOutputDirector.cxx | 6 ++++-- Framework/Core/test/test_DataOutputDirector.cxx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index af9bcbee17fc7..00b2c55509b26 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -56,8 +56,10 @@ DataOutputDescriptor::DataOutputDescriptor(std::string inString) } // get the tree name - // defaul tree name is the table name + // default tree name is the O2 + table name (lower case) treename = tablename; + std::transform(treename.begin(), treename.end(), treename.begin(), [](unsigned char c) { return std::tolower(c); }); + treename = std::string("O2") + treename; ++iter1; if (iter1 == end) { return; @@ -500,7 +502,7 @@ void DataOutputDirector::setFilenameBase(std::string dfn) auto it = std::unique(mtreeFilenames.begin(), mtreeFilenames.end()); if (it != mtreeFilenames.end()) { printOut(); - LOG(FATAL) << "Dublicate tree names in a file!"; + LOG(FATAL) << "Duplicate tree names in a file!"; } // make unique/sorted list of filenameBases diff --git a/Framework/Core/test/test_DataOutputDirector.cxx b/Framework/Core/test/test_DataOutputDirector.cxx index e6f198197618e..f9f2becd04044 100644 --- a/Framework/Core/test/test_DataOutputDirector.cxx +++ b/Framework/Core/test/test_DataOutputDirector.cxx @@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE(TestDataOutputDirector) BOOST_CHECK_EQUAL(ds[0]->getFilenameBase(), std::string("fn1")); BOOST_CHECK_EQUAL(ds[1]->tablename, std::string("UNO")); - BOOST_CHECK_EQUAL(ds[1]->treename, std::string("UNO")); + BOOST_CHECK_EQUAL(ds[1]->treename, std::string("O2uno")); BOOST_CHECK_EQUAL(ds[1]->colnames.size(), 1); BOOST_CHECK_EQUAL(ds[1]->getFilenameBase(), std::string("myresultfile")); From 5d8dac97bf263e50fc9ff3ab1c60a99d02f3d08f Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Wed, 7 Oct 2020 19:55:27 +0200 Subject: [PATCH 0865/1751] use correct counters (#4531) --- Analysis/Tasks/PWGCF/filterCF.cxx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Analysis/Tasks/PWGCF/filterCF.cxx b/Analysis/Tasks/PWGCF/filterCF.cxx index 98ed5274de027..3956924ae44c4 100644 --- a/Analysis/Tasks/PWGCF/filterCF.cxx +++ b/Analysis/Tasks/PWGCF/filterCF.cxx @@ -42,8 +42,6 @@ struct FilterCF { Produces<aod::CFCollisions> outputCollisions; Produces<aod::CFTracks> outputTracks; - uint64_t eventCounter = 0; - void init(o2::framework::InitContext&) { } @@ -64,14 +62,11 @@ struct FilterCF { else if (track.isGlobalTrackSDD()) trackType = 2; - // TODO can we get the eventCounter from the previous filling to collisions(...)? - outputTracks(eventCounter, track.pt(), track.eta(), track.phi(), track.charge(), trackType); + outputTracks(outputCollisions.lastIndex(), track.pt(), track.eta(), track.phi(), track.charge(), trackType); yields->Fill(collision.centV0M(), track.pt(), track.eta()); etaphi->Fill(collision.centV0M(), track.eta(), track.phi()); } - - eventCounter++; } }; From cd1eef32c05cc88372f136a3fb79c20325c81bf4 Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Wed, 7 Oct 2020 22:52:00 +0200 Subject: [PATCH 0866/1751] fix the 3 prong preselection on min pt of the candidate (#4534) --- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 53b179eaeb853..17a0746d0ed73 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -204,21 +204,19 @@ struct HFTrackIndexSkimsCreator { mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); ptcand_2prong = RecoDecay::Pt(pvec0, pvec1); - if (ptcand_2prong < ptmincand_2prong) - continue; - if (b_dovalplots) { - hmass2->Fill(mass2PiK); - hmass2->Fill(mass2KPi); - hvtx_x_out->Fill(secondaryVertex[0]); - hvtx_y_out->Fill(secondaryVertex[1]); - hvtx_z_out->Fill(secondaryVertex[2]); + if (ptcand_2prong >= ptmincand_2prong) { + if (b_dovalplots) { + hmass2->Fill(mass2PiK); + hmass2->Fill(mass2KPi); + hvtx_x_out->Fill(secondaryVertex[0]); + hvtx_y_out->Fill(secondaryVertex[1]); + hvtx_z_out->Fill(secondaryVertex[2]); + } + // fill table row + rowTrackIndexProng2(trackPos1.collisionId(), + trackPos1.globalIndex(), + trackNeg1.globalIndex(), 1); } - - // fill table row - rowTrackIndexProng2(trackPos1.collisionId(), - trackPos1.globalIndex(), - trackNeg1.globalIndex(), 1); - // 3-prong vertex reconstruction if (do3prong == 1) { if (trackPos1.isSel3Prong() == 0) From 99373ff7ee184a3ed316cc2040448ef3fc5f6f03 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Thu, 8 Oct 2020 00:43:46 +0200 Subject: [PATCH 0867/1751] DPL Analysis: workaround for arrow not serializing empty tables (#4528) --- Framework/Core/include/Framework/ASoA.h | 61 ------------------- .../Core/include/Framework/AnalysisHelpers.h | 23 +++++++ .../Core/include/Framework/TableBuilder.h | 49 +++++++++++++++ Framework/Core/src/AODReaderHelpers.cxx | 2 +- Framework/Core/src/AnalysisManagers.h | 7 ++- Framework/Core/src/DataAllocator.cxx | 1 - Framework/Core/test/test_ASoA.cxx | 1 + 7 files changed, 80 insertions(+), 64 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 6c95679f6dfd6..d95ca28ba1e87 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1753,47 +1753,6 @@ auto filter(T&& t, framework::expressions::Filter const& expr) return Filtered<T>(t.asArrowTable(), expr); } -/// Expression-based column generator to materialize columns -template <typename... C> -auto spawner(framework::pack<C...> columns, arrow::Table* atable) -{ - static auto new_schema = o2::soa::createSchemaFromColumns(columns); - static auto projectors = framework::expressions::createProjectors(columns, atable->schema()); - - std::vector<std::shared_ptr<arrow::ChunkedArray>> arrays; - - if (atable->num_rows() == 0) { - return arrow::Table::Make(new_schema, arrays); - } - - arrow::TableBatchReader reader(*atable); - std::shared_ptr<arrow::RecordBatch> batch; - arrow::ArrayVector v; - std::array<arrow::ArrayVector, sizeof...(C)> chunks; - - while (true) { - auto s = reader.ReadNext(&batch); - if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot read batches from table: {}", s.ToString())); - } - if (batch == nullptr) { - break; - } - s = projectors->Evaluate(*batch, arrow::default_memory_pool(), &v); - if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot apply projector: {}", s.ToString())); - } - for (auto i = 0u; i < sizeof...(C); ++i) { - chunks[i].emplace_back(v.at(i)); - } - } - - for (auto i = 0u; i < sizeof...(C); ++i) { - arrays.push_back(std::make_shared<arrow::ChunkedArray>(chunks[i])); - } - return arrow::Table::Make(new_schema, arrays); -} - /// Template for building an index table to access matching rows from non- /// joinable, but compatible tables, e.g. Collisions and ZDCs. /// First argument is the key table (BCs for the Collisions+ZDCs case), the rest @@ -1822,26 +1781,6 @@ struct IndexTable : Table<soa::Index<>, H, Ts...> { template <typename T> using is_soa_index_table_t = typename framework::is_base_of_template<soa::IndexTable, T>; - -/// On-the-fly adding of expression columns -template <typename T, typename... Cs> -auto Extend(T const& table) -{ - static_assert((soa::is_type_spawnable_v<Cs> && ...), "You can only extend a table with expression columns"); - using output_t = Join<T, soa::Table<Cs...>>; - return output_t{{spawner(framework::pack<Cs...>{}, table.asArrowTable().get()), table.asArrowTable()}, 0}; -} - -/// Template function to attach dynamic columns on-the-fly (e.g. inside -/// process() function). Dynamic columns need to be compatible with the table. -template <typename T, typename... Cs> -auto Attach(T const& table) -{ - static_assert((framework::is_base_of_template<o2::soa::DynamicColumn, Cs>::value && ...), "You can only attach dynamic columns"); - using output_t = Join<T, o2::soa::Table<Cs...>>; - return output_t{{table.asArrowTable()}, table.offset()}; -} - } // namespace o2::soa #endif // O2_FRAMEWORK_ASOA_H_ diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 046e0f2ea600f..50101722cdddb 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -169,6 +169,7 @@ struct TableTransform { template <typename T> struct Spawns : TableTransform<typename aod::MetadataTrait<framework::pack_head_t<typename T::originals>>::metadata> { using extension_t = framework::pack_head_t<typename T::originals>; + using base_table_t = typename aod::MetadataTrait<extension_t>::metadata::base_table_t; using expression_pack_t = typename aod::MetadataTrait<extension_t>::metadata::expression_pack_t; constexpr auto pack() @@ -541,4 +542,26 @@ struct Partition { } // namespace o2::framework +namespace o2::soa +{ +/// On-the-fly adding of expression columns +template <typename T, typename... Cs> +auto Extend(T const& table) +{ + static_assert((soa::is_type_spawnable_v<Cs> && ...), "You can only extend a table with expression columns"); + using output_t = Join<T, soa::Table<Cs...>>; + return output_t{{o2::framework::spawner(framework::pack<Cs...>{}, table.asArrowTable().get()), table.asArrowTable()}, 0}; +} + +/// Template function to attach dynamic columns on-the-fly (e.g. inside +/// process() function). Dynamic columns need to be compatible with the table. +template <typename T, typename... Cs> +auto Attach(T const& table) +{ + static_assert((framework::is_base_of_template<o2::soa::DynamicColumn, Cs>::value && ...), "You can only attach dynamic columns"); + using output_t = Join<T, o2::soa::Table<Cs...>>; + return output_t{{table.asArrowTable()}, table.offset()}; +} +} // namespace o2::soa + #endif // o2_framework_AnalysisHelpers_H_DEFINED diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index 350c7b183712f..e1e1b0576060f 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -597,6 +597,55 @@ class TableBuilder std::vector<std::shared_ptr<arrow::Array>> mArrays; }; +template <typename T> +auto makeEmptyTable() +{ + TableBuilder b; + auto writer = b.cursor<T>(); + return b.finalize(); +} + +/// Expression-based column generator to materialize columns +template <typename... C> +auto spawner(framework::pack<C...> columns, arrow::Table* atable) +{ + static auto new_schema = o2::soa::createSchemaFromColumns(columns); + static auto projectors = framework::expressions::createProjectors(columns, atable->schema()); + + if (atable->num_rows() == 0) { + return makeEmptyTable<soa::Table<C...>>(); + } + + arrow::TableBatchReader reader(*atable); + std::shared_ptr<arrow::RecordBatch> batch; + arrow::ArrayVector v; + std::array<arrow::ArrayVector, sizeof...(C)> chunks; + std::vector<std::shared_ptr<arrow::ChunkedArray>> arrays; + + while (true) { + auto s = reader.ReadNext(&batch); + if (!s.ok()) { + throw std::runtime_error(fmt::format("Cannot read batches from table: {}", s.ToString())); + } + if (batch == nullptr) { + break; + } + s = projectors->Evaluate(*batch, arrow::default_memory_pool(), &v); + if (!s.ok()) { + throw std::runtime_error(fmt::format("Cannot apply projector: {}", s.ToString())); + } + for (auto i = 0u; i < sizeof...(C); ++i) { + chunks[i].emplace_back(v.at(i)); + } + } + + for (auto i = 0u; i < sizeof...(C); ++i) { + arrays.push_back(std::make_shared<arrow::ChunkedArray>(chunks[i])); + } + + return arrow::Table::Make(new_schema, arrays); +} + /// Helper to get a tuple tail template <typename Head, typename... Tail> std::tuple<Tail...> tuple_tail(std::tuple<Head, Tail...>& t) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 85d11bc12aefc..59908ad33e9ac 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -72,7 +72,7 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> reques using metadata_t = decltype(metadata); using expressions = typename metadata_t::expression_pack_t; auto original_table = pc.inputs().get<TableConsumer>(input.binding)->asArrowTable(); - return o2::soa::spawner(expressions{}, original_table.get()); + return o2::framework::spawner(expressions{}, original_table.get()); }; if (description == header::DataDescription{"TRACK:PAR"}) { diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index 9154fa7c77ef6..bba95b523034e 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -236,7 +236,12 @@ struct OutputManager<Spawns<T>> { static bool prepare(ProcessingContext& pc, Spawns<T>& what) { auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(what.sources_pack(), pc)); - what.extension = std::make_shared<typename Spawns<T>::extension_t>(o2::soa::spawner(what.pack(), original_table.get())); + if (original_table->schema()->fields().empty() == true) { + using base_table_t = typename Spawns<T>::base_table_t; + original_table = makeEmptyTable<base_table_t>(); + } + + what.extension = std::make_shared<typename Spawns<T>::extension_t>(o2::framework::spawner(what.pack(), original_table.get())); what.table = std::make_shared<typename T::table_t>(soa::ArrowHelpers::joinTables({what.extension->asArrowTable(), original_table})); return true; } diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index 38bf5c04f190c..aa3ea7043c560 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -188,7 +188,6 @@ void DataAllocator::adopt(const Output& spec, TreeToTable* t2t) auto table = payload->finalize(); auto stream = std::make_shared<arrow::io::BufferOutputStream>(b); - std::shared_ptr<arrow::ipc::RecordBatchWriter> writer; auto outBatch = arrow::ipc::NewStreamWriter(stream.get(), table->schema()); if (outBatch.ok() == true) { auto outStatus = outBatch.ValueOrDie()->WriteTable(*table); diff --git a/Framework/Core/test/test_ASoA.cxx b/Framework/Core/test/test_ASoA.cxx index cb7bca0c9d301..74dc0e7706262 100644 --- a/Framework/Core/test/test_ASoA.cxx +++ b/Framework/Core/test/test_ASoA.cxx @@ -15,6 +15,7 @@ #include "Framework/ASoA.h" #include "Framework/ASoAHelpers.h" #include "Framework/Expressions.h" +#include "Framework/AnalysisHelpers.h" #include "../src/ExpressionHelpers.h" #include "gandiva/tree_expr_builder.h" #include "arrow/status.h" From c6900c13a253afd850e95d29ad8fb77ef8d0ca30 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 8 Oct 2020 00:56:49 +0200 Subject: [PATCH 0868/1751] DPL Analysis: do poor man bulk reading (#4407) * Accumulate values read from ROOT before pushing them to arrow. * Do not use the learning phase, we know what to read. * Do not use default cache size. We know how big our tables are. --- .../Framework/RootTableBuilderHelpers.h | 144 ++++++++++++------ .../Core/include/Framework/TableBuilder.h | 63 +++++++- Framework/Core/test/test_Root2ArrowTable.cxx | 2 + 3 files changed, 158 insertions(+), 51 deletions(-) diff --git a/Framework/Core/include/Framework/RootTableBuilderHelpers.h b/Framework/Core/include/Framework/RootTableBuilderHelpers.h index eb1074385dd98..5ead9d8e69412 100644 --- a/Framework/Core/include/Framework/RootTableBuilderHelpers.h +++ b/Framework/Core/include/Framework/RootTableBuilderHelpers.h @@ -14,6 +14,7 @@ #include "Framework/TableBuilder.h" #include "Framework/Logger.h" +#include <Rtypes.h> #include <arrow/stl.h> #include <arrow/type_traits.h> #include <arrow/table.h> @@ -22,6 +23,8 @@ #include <TTreeReader.h> #include <TTreeReaderValue.h> #include <TTreeReaderArray.h> +#include <TBuffer.h> +#include <TBufferFile.h> #include <vector> #include <string> @@ -53,45 +56,7 @@ struct TreeReaderValueTraits<TTreeReaderArray<VALUE>> { using ArrowType = arrow::ListType; }; -template <typename T> -struct ReaderHolder { - using Reader = TTreeReaderValue<T>; - using Type = T; - std::unique_ptr<Reader> reader; -}; - -template <typename T, int N> -struct ReaderHolder<T[N]> { - using Reader = TTreeReaderArray<T>; - using Type = T (&)[N]; - std::unique_ptr<Reader> reader; -}; - -struct ValueExtractor { - template <typename T> - static T deref(TTreeReaderValue<T>& rv) - { - return *rv; - } - - template <typename T> - static std::pair<typename TTreeReaderArray<T>::iterator, typename TTreeReaderArray<T>::iterator> deref(TTreeReaderArray<T>& rv) - { - return std::make_pair(rv.begin(), rv.end()); - } - - template <typename T> - static T deref(ReaderHolder<T>& holder) - { - return **holder.reader; - } - - template <typename T, int N> - static T* deref(ReaderHolder<T[N]>& holder) - { - return &((*holder.reader)[0]); - } -}; +static constexpr int PREBUFFER_SIZE = 32 * 1024; // When reading from a ROOT file special care must happen // because uint64_t is platform specific while ULong64_t is @@ -126,12 +91,92 @@ struct Remap64Bit<uint64_t[N]> { template <typename T> using Remap64Bit_t = typename Remap64Bit<T>::type; +template <typename T> +struct ReaderHolder { + using Reader = TTreeReaderValue<T>; + using Type = T; + + ReaderHolder(TBranch* branch, std::unique_ptr<Reader> reader_) + : reader{std::move(reader_)} + { + } + + ReaderHolder(ReaderHolder&& other) + : reader{std::move(other.reader)}, + pos{other.pos} + { + } + + ReaderHolder& operator=(ReaderHolder&& other) = delete; + + std::unique_ptr<Reader> reader; + int pos = 0; + Remap64Bit_t<T> buffer[PREBUFFER_SIZE]; + int itemSize = sizeof(T); +}; + +template <typename T, int N> +struct ReaderHolder<T[N]> { + using Reader = TTreeReaderArray<T>; + using Type = T (&)[N]; + + ReaderHolder(TBranch* branch, std::unique_ptr<Reader> reader_) + : reader{std::move(reader_)} + { + } + + ReaderHolder(ReaderHolder&& other) + : reader{std::move(other.reader)}, + pos{other.pos} + { + } + + ReaderHolder& operator=(ReaderHolder&& other) = delete; + + std::unique_ptr<Reader> reader; + int pos = 0; + Remap64Bit_t<T> buffer[PREBUFFER_SIZE * N]; + int itemSize = sizeof(T) * N; +}; + +struct BulkExtractor { + template <typename T> + static auto deref(ReaderHolder<T>& holder, size_t maxSize) + { + holder.buffer[holder.pos % PREBUFFER_SIZE] = **holder.reader; + holder.pos++; + if (holder.pos == maxSize) { + return BulkInfo<Remap64Bit_t<T> const*>{holder.buffer, maxSize % PREBUFFER_SIZE}; + } + // We flush only after PREBUFFER_SIZE items have been inserted + if ((holder.pos % PREBUFFER_SIZE) != 0) { + return BulkInfo<Remap64Bit_t<T> const*>{nullptr, 0}; + } + return BulkInfo<Remap64Bit_t<T> const*>{holder.buffer, PREBUFFER_SIZE}; + } + + template <typename T, int N> + static auto deref(ReaderHolder<T[N]>& holder, size_t maxSize) + { + memcpy(&holder.buffer[(holder.pos % PREBUFFER_SIZE) * N], &((*holder.reader)[0]), N * sizeof(T)); + holder.pos++; + if (holder.pos == maxSize) { + return BulkInfo<Remap64Bit_t<T> const*>{holder.buffer, maxSize % PREBUFFER_SIZE}; + } + // We flush only after PREBUFFER_SIZE items have been inserted + if ((holder.pos % PREBUFFER_SIZE) != 0) { + return BulkInfo<Remap64Bit_t<T> const*>{nullptr, 0}; + } + return BulkInfo<Remap64Bit_t<T> const*>{reinterpret_cast<T const*>(holder.buffer), PREBUFFER_SIZE}; + } +}; + template <typename T> struct HolderMaker { static auto make(TTreeReader& reader, char const* branchName) { using Reader = TTreeReaderValue<T>; - return std::move(ReaderHolder<T>{std::move(std::make_unique<Reader>(reader, branchName))}); + return ReaderHolder<T>{reader.GetTree()->GetBranch(branchName), std::move(std::make_unique<Reader>(reader, branchName))}; } }; @@ -140,7 +185,7 @@ struct HolderMaker<T[N]> { static auto make(TTreeReader& reader, char const* branchName) { using Reader = TTreeReaderArray<T>; - return std::move(ReaderHolder<T[N]>{std::move(std::make_unique<Reader>(reader, branchName))}); + return ReaderHolder<T[N]>{reader.GetTree()->GetBranch(branchName), std::move(std::make_unique<Reader>(reader, branchName))}; } }; @@ -148,22 +193,27 @@ template <typename C> struct ColumnReaderTrait { static auto createReader(TTreeReader& reader) { - return std::move(HolderMaker<Remap64Bit_t<typename C::type>>::make(reader, C::base::columnLabel())); + return HolderMaker<Remap64Bit_t<typename C::type>>::make(reader, C::base::columnLabel()); } }; struct RootTableBuilderHelpers { - template <typename... TTREEREADERVALUE> + /// Use bulk insertion when TTreeReaderValue everywhere + template <typename... T> static void convertTTree(TableBuilder& builder, TTreeReader& reader, - ReaderHolder<TTREEREADERVALUE>... holders) + ReaderHolder<T>... holders) { std::vector<std::string> branchNames = {holders.reader->GetBranchName()...}; + TTree* tree = reader.GetTree(); + size_t maxExtries = reader.GetEntries(true); + tree->SetCacheSize(maxExtries * (holders.itemSize + ...)); + (tree->AddBranchToCache(tree->GetBranch(holders.reader->GetBranchName()), true), ...); + tree->StopCacheLearningPhase(); - auto filler = builder.preallocatedPersist<typename std::decay_t<decltype(holders)>::Type...>(branchNames, reader.GetEntries(true)); - reader.Restart(); + auto filler = builder.bulkPersistChunked<Remap64Bit_t<typename std::decay_t<decltype(holders)>::Type>...>(branchNames, maxExtries); while (reader.Next()) { - filler(0, ValueExtractor::deref(holders)...); + filler(0, BulkExtractor::deref(holders, maxExtries)...); } } diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index e1e1b0576060f..deeb8e494631c 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -20,12 +20,14 @@ // Apparently needs to be on top of the arrow includes. #include <sstream> +#include <arrow/status.h> #include <arrow/stl.h> #include <arrow/type_traits.h> #include <arrow/table.h> #include <arrow/builder.h> #include <functional> +#include <stdexcept> #include <vector> #include <string> #include <memory> @@ -38,6 +40,12 @@ class Table; class Array; } // namespace arrow +template <typename T> +struct BulkInfo { + const T ptr; + size_t size; +}; + namespace o2::framework { namespace detail @@ -87,15 +95,15 @@ O2_ARROW_STL_CONVERSION(std::string, StringType) struct BuilderUtils { template <typename T> - static arrow::Status appendToList(std::unique_ptr<arrow::FixedSizeListBuilder>& builder, T* data) + static arrow::Status appendToList(std::unique_ptr<arrow::FixedSizeListBuilder>& builder, T* data, int size = 1) { - using ArrowType = typename detail::ConversionTraits<T>::ArrowType; + using ArrowType = typename detail::ConversionTraits<std::decay_t<T>>::ArrowType; using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType; size_t numElements = static_cast<const arrow::FixedSizeListType*>(builder->type().get())->list_size(); - auto status = builder->AppendValues(1); + auto status = builder->AppendValues(size); auto ValueBuilder = static_cast<BuilderType*>(builder->value_builder()); - status &= ValueBuilder->AppendValues(data, numElements, nullptr); + status &= ValueBuilder->AppendValues(data, numElements * size, nullptr); return status; } @@ -154,6 +162,28 @@ struct BuilderUtils { return builder->AppendValues(ptr, bulkSize, nullptr); } + template <typename BuilderType, typename PTR> + static arrow::Status bulkAppendChunked(BuilderType& builder, BulkInfo<PTR> info) + { + // Appending nullptr is a no-op. + if (info.ptr == nullptr) { + return arrow::Status::OK(); + } + if constexpr (std::is_same_v<BuilderType, std::unique_ptr<arrow::FixedSizeListBuilder>>) { + if (appendToList<std::remove_pointer_t<decltype(info.ptr)>>(builder, info.ptr, info.size).ok() == false) { + throw std::runtime_error("Unable to append to column"); + } else { + return arrow::Status::OK(); + } + } else { + if (builder->AppendValues(info.ptr, info.size, nullptr).ok() == false) { + throw std::runtime_error("Unable to append to column"); + } else { + return arrow::Status::OK(); + } + } + } + template <typename BuilderType, typename ITERATOR> static arrow::Status append(BuilderType& builder, std::pair<ITERATOR, ITERATOR> ip) { @@ -185,6 +215,7 @@ struct BuilderUtils { template <typename T> struct BuilderMaker { using FillType = T; + using STLValueType = T; using ArrowType = typename detail::ConversionTraits<T>::ArrowType; using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType; @@ -213,6 +244,7 @@ struct BuilderMaker { template <> struct BuilderMaker<bool> { using FillType = bool; + using STLValueType = bool; using ArrowType = typename detail::ConversionTraits<bool>::ArrowType; using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType; @@ -235,6 +267,7 @@ struct BuilderMaker<bool> { template <typename ITERATOR> struct BuilderMaker<std::pair<ITERATOR, ITERATOR>> { using FillType = std::pair<ITERATOR, ITERATOR>; + using STLValueType = typename ITERATOR::value_type; using ArrowType = arrow::ListType; using ValueType = typename detail::ConversionTraits<typename ITERATOR::value_type>::ArrowType; using BuilderType = arrow::ListBuilder; @@ -255,6 +288,7 @@ struct BuilderMaker<std::pair<ITERATOR, ITERATOR>> { template <typename T, int N> struct BuilderMaker<T (&)[N]> { using FillType = T*; + using STLValueType = T; using BuilderType = arrow::FixedSizeListBuilder; using ArrowType = arrow::FixedSizeListType; using ElementType = typename detail::ConversionTraits<T>::ArrowType; @@ -356,6 +390,13 @@ struct TableBuilderHelpers { return (BuilderUtils::bulkAppend(std::get<Is>(builders), bulkSize, std::get<Is>(ptrs)).ok() && ...); } + /// Return true if all columns are done. + template <std::size_t... Is, typename BUILDERS, typename INFOS> + static bool bulkAppendChunked(BUILDERS& builders, std::index_sequence<Is...>, INFOS infos) + { + return (BuilderUtils::bulkAppendChunked(std::get<Is>(builders), std::get<Is>(infos)).ok() && ...); + } + /// Invokes the append method for each entry in the tuple template <typename BUILDERS, std::size_t... Is> static bool finalize(std::vector<std::shared_ptr<arrow::Array>>& arrays, BUILDERS& builders, std::index_sequence<Is...> seq) @@ -552,6 +593,20 @@ class TableBuilder }; } + template <typename... ARGS> + auto bulkPersistChunked(std::vector<std::string> const& columnNames, size_t nRows) + { + constexpr int nColumns = sizeof...(ARGS); + validate<ARGS...>(columnNames); + mArrays.resize(nColumns); + makeBuilders<ARGS...>(columnNames, nRows); + makeFinalizer<ARGS...>(); + + return [builders = mBuilders](unsigned int slot, BulkInfo<typename BuilderMaker<ARGS>::STLValueType const*>... args) -> bool { + return TableBuilderHelpers::bulkAppendChunked(*(BuildersTuple<ARGS...>*)builders, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); + }; + } + /// Reserve method to expand the columns as needed. template <typename... ARGS> auto reserve(o2::framework::pack<ARGS...> pack, int s) diff --git a/Framework/Core/test/test_Root2ArrowTable.cxx b/Framework/Core/test/test_Root2ArrowTable.cxx index fc338031dbdf8..346790dc76388 100644 --- a/Framework/Core/test/test_Root2ArrowTable.cxx +++ b/Framework/Core/test/test_Root2ArrowTable.cxx @@ -91,6 +91,8 @@ BOOST_AUTO_TEST_CASE(RootTree2Table) auto chunkToUse = table->column(0)->chunk(0); chunkToUse = std::dynamic_pointer_cast<arrow::FixedSizeListArray>(chunkToUse)->values(); auto array = std::static_pointer_cast<arrow::FloatArray>(chunkToUse); + // array of 3 floats, time 1000. + BOOST_REQUIRE_EQUAL(array->length(), 3000); const float* c = reinterpret_cast<float const*>(array->values()->data()); //auto array = std::static_pointer_cast<arrow::FixedSizeBinaryArray>(table->column(0)->chunk(0)); From 42ec3365c8e8768128111e96ad03a49dba8b67fb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 7 Oct 2020 15:36:51 +0200 Subject: [PATCH 0869/1751] Revert to 15 bits used for sensID in GeometryManager --- Detectors/Base/include/DetectorsBase/GeometryManager.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/GeometryManager.h b/Detectors/Base/include/DetectorsBase/GeometryManager.h index bc7fcdd353b1d..8e8941e68a2e6 100644 --- a/Detectors/Base/include/DetectorsBase/GeometryManager.h +++ b/Detectors/Base/include/DetectorsBase/GeometryManager.h @@ -128,11 +128,7 @@ class GeometryManager : public TObject static Bool_t getOriginalMatrixFromPath(const char* path, TGeoHMatrix& m); private: /// sensitive volume identifier composed from (det_mask<<sDetOffset)|(sensid&sSensorMask) -#ifdef ENABLE_UPGRADES - static constexpr UInt_t sDetOffset = 13; /// detector identifier will start from this bit -#else static constexpr UInt_t sDetOffset = 15; /// detector identifier will start from this bit -#endif static constexpr UInt_t sSensorMask = (0x1 << sDetOffset) - 1; /// mask=max sensitive volumes allowed per detector (0xffff) static std::mutex sTGMutex; From f6f468409d6107b0146bc315d2f5d8a9a8bf4c9b Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 7 Oct 2020 16:08:27 +0200 Subject: [PATCH 0870/1751] Use DetID instead its mask in GeometryManager sensID --- Detectors/Base/include/DetectorsBase/GeometryManager.h | 6 +++--- Detectors/Base/src/GeometryManager.cxx | 10 ---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/GeometryManager.h b/Detectors/Base/include/DetectorsBase/GeometryManager.h index 8e8941e68a2e6..8b5354f208002 100644 --- a/Detectors/Base/include/DetectorsBase/GeometryManager.h +++ b/Detectors/Base/include/DetectorsBase/GeometryManager.h @@ -64,7 +64,7 @@ class GeometryManager : public TObject static int getSensID(o2::detectors::DetID detid, int sensid) { /// compose combined detector+sensor ID for sensitive volumes - return (detid.getMask().to_ulong() << sDetOffset) | (sensid & sSensorMask); + return (detid << sDetOffset) | (sensid & sSensorMask); } /// Default destructor @@ -113,7 +113,7 @@ class GeometryManager : public TObject private: /// Default constructor - GeometryManager(); + GeometryManager() = default; static void accountMaterial(const TGeoMaterial* material, MatBudgetExt& bd); static void accountMaterial(const TGeoMaterial* material, o2::base::MatBudget& bd) @@ -127,7 +127,7 @@ class GeometryManager : public TObject /// Returns kFALSE in case TGeo has not been initialized or the volume path is not valid. static Bool_t getOriginalMatrixFromPath(const char* path, TGeoHMatrix& m); private: -/// sensitive volume identifier composed from (det_mask<<sDetOffset)|(sensid&sSensorMask) + /// sensitive volume identifier composed from (det_ID<<sDetOffset)|(sensid&sSensorMask) static constexpr UInt_t sDetOffset = 15; /// detector identifier will start from this bit static constexpr UInt_t sSensorMask = (0x1 << sDetOffset) - 1; /// mask=max sensitive volumes allowed per detector (0xffff) diff --git a/Detectors/Base/src/GeometryManager.cxx b/Detectors/Base/src/GeometryManager.cxx index 5a153a0fd9943..b97c6c65c2f11 100644 --- a/Detectors/Base/src/GeometryManager.cxx +++ b/Detectors/Base/src/GeometryManager.cxx @@ -35,16 +35,6 @@ using namespace o2::base; /// collects several static methods std::mutex GeometryManager::sTGMutex; -//______________________________________________________________________ -GeometryManager::GeometryManager() -{ - /// default constructor - - /// make sure detectors masks can be encoded in the combined det+sensor id - static_assert(sizeof(Int_t) * 8 - sDetOffset > DetID::getNDetectors(), - "N detectors exceeds available N bits for their encoding"); -} - //______________________________________________________________________ Bool_t GeometryManager::getOriginalMatrix(const char* symname, TGeoHMatrix& m) { From 6e27712cd72bb7c5b10d6364d1ea4c48f8907040 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 6 Oct 2020 14:26:41 +0200 Subject: [PATCH 0871/1751] Some cleanup --- .../TRD/base/include/TRDBase/TRDGeometryBase.h | 1 - .../TRD/base/include/TRDBase/TRDGeometryFlat.h | 2 +- Detectors/TRD/base/src/TRDGeometry.cxx | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 14 ++++++++------ GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h b/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h index 8a345d5c62e7f..eb06c9ae1c263 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h +++ b/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h @@ -25,7 +25,6 @@ class TRDGeometryBase public: ~TRDGeometryBase() = default; - static constexpr int MAXMATRICES = 521; GPUd() int isVersion() { return 1; } GPUd() bool isHole(int la, int st, int se) const { return (((se == 13) || (se == 14) || (se == 15)) && (st == 2)); } diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h index 5324faac97e22..54b82c5757815 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h +++ b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h @@ -58,7 +58,7 @@ class TRDGeometryFlat : public o2::gpu::FlatObject, public TRDGeometryBase } private: - o2::gpu::Transform3D mMatrixCache[MAXMATRICES]; + o2::gpu::Transform3D mMatrixCache[constants::NCHAMBER]; short mMatrixIndirection[constants::MAXCHAMBER]; }; diff --git a/Detectors/TRD/base/src/TRDGeometry.cxx b/Detectors/TRD/base/src/TRDGeometry.cxx index 560b7a1dfe0eb..7e6a75fe6da6a 100644 --- a/Detectors/TRD/base/src/TRDGeometry.cxx +++ b/Detectors/TRD/base/src/TRDGeometry.cxx @@ -2751,7 +2751,7 @@ bool TRDGeometry::createClusterMatrixArray() return true; // already initialized } - setSize(MAXMATRICES, MAXCHAMBER); //Only MAXMATRICES=521 of MAXCHAMBER matrices are filled + setSize(NCHAMBER, MAXCHAMBER); //Only NCHAMBER=521 of MAXCHAMBER matrices are filled fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L) | o2::utils::bit2Mask(o2::TransformType::L2G) | o2::utils::bit2Mask(o2::TransformType::T2G) | o2::utils::bit2Mask(o2::TransformType::T2GRot)); return true; diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index ff50aa3eff96c..646d68528092a 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -505,15 +505,17 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CalculateSpacePoints(int iCollision) int idxOffset = iCollision * (kNChambers + 1); for (int iDet = 0; iDet < kNChambers; ++iDet) { - int nTracklets = mTrackletIndexArray[idxOffset + iDet + 1] - mTrackletIndexArray[idxOffset + iDet]; if (nTracklets == 0) { continue; } - + if (!mGeo->ChamberInGeometry(iDet)) { + GPUError("Found TRD tracklets in chamber %i which is not included in the geometry", iDet); + return false; + } auto* matrix = mGeo->GetClusterMatrix(iDet); if (!matrix) { - Error("CalculateSpacePoints", "Invalid TRD cluster matrix, skipping detector %i", iDet); + GPUError("No cluster matrix available for chamber %i. Skipping it...", iDet); result = false; continue; } @@ -645,7 +647,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK } // rotate track in new sector in case of sector crossing - if (!AdjustSector(prop, trkWork, iLayer)) { + if (!AdjustSector(prop, trkWork)) { if (ENABLE_INFO) { GPUInfo("FollowProlongation: Adjusting sector failed for track %i candidate %i in layer %i", iTrack, iCandidate, iLayer); } @@ -1048,11 +1050,11 @@ GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::GetDetectorNumber(const float zPos, co } template <class TRDTRK, class PROP> -GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::AdjustSector(PROP* prop, TRDTRK* t, const int layer) const +GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::AdjustSector(PROP* prop, TRDTRK* t) const { //-------------------------------------------------------------------- // rotate track in new sector if necessary and - // propagate to correct x of layer + // propagate to previous x afterwards // cancel if track crosses two sector boundaries //-------------------------------------------------------------------- float alpha = mGeo->GetAlpha(); diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 62f2193f023c4..6345c799daad3 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -149,7 +149,7 @@ class GPUTRDTracker_t : public GPUProcessor GPUd() bool CalculateSpacePoints(int iCollision = 0); GPUd() bool FollowProlongation(PROP* prop, TRDTRK* t, int threadId, int collisionId); GPUd() int GetDetectorNumber(const float zPos, const float alpha, const int layer) const; - GPUd() bool AdjustSector(PROP* prop, TRDTRK* t, const int layer) const; + GPUd() bool AdjustSector(PROP* prop, TRDTRK* t) const; GPUd() int GetSector(float alpha) const; GPUd() float GetAlphaOfSector(const int sec) const; GPUd() float GetRPhiRes(float snp) const { return (mRPhiA2 + mRPhiC2 * (snp - mRPhiB) * (snp - mRPhiB)); } // parametrization obtained from track-tracklet residuals: From 8d72475f6d05343ddfedd696cc19610af3b6d127 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 6 Oct 2020 14:33:31 +0200 Subject: [PATCH 0872/1751] Use GPUTPCGM* classes as base for GPUTRDTrackerComponent --- GPU/GPUTracking/TRDTracking/GPUTRDDef.h | 10 ++++------ GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h | 4 ++-- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 7 +++---- .../TRDTracking/GPUTRDTrackerComponent.cxx | 18 +++++++++--------- .../TRDTracking/GPUTRDTrackerComponent.h | 2 +- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDDef.h b/GPU/GPUTracking/TRDTracking/GPUTRDDef.h index ff03fc8af18ca..54f2f7110e581 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDDef.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDDef.h @@ -52,9 +52,8 @@ typedef float My_Float; #if defined(TRD_TRACK_TYPE_ALIROOT) typedef AliExternalTrackParam TRDBaseTrack; -typedef AliExternalTrackParam TRDBaseTrackGPU; -// class GPUTPCGMTrackParam; -// typedef GPUTPCGMTrackParam TRDBaseTrack; +class GPUTPCGMTrackParam; +typedef GPUTPCGMTrackParam TRDBaseTrackGPU; #elif defined(TRD_TRACK_TYPE_O2) typedef o2::dataformats::TrackTPCITS TRDBaseTrack; class GPUTPCGMTrackParam; @@ -63,9 +62,8 @@ typedef GPUTPCGMTrackParam TRDBaseTrackGPU; #ifdef GPUCA_ALIROOT_LIB typedef AliTrackerBase TRDBasePropagator; -typedef AliTrackerBase TRDBasePropagatorGPU; -// class GPUTPCGMPropagator; -// typedef GPUTPCGMPropagator TRDBasePropagator; +class GPUTPCGMPropagator; +typedef GPUTPCGMPropagator TRDBasePropagatorGPU; #else typedef o2::base::Propagator TRDBasePropagator; class GPUTPCGMPropagator; diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h index 42d762b8480bd..0f40cd142d060 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h @@ -103,7 +103,7 @@ class propagatorInterface<AliTrackerBase> : public AliTrackerBase propagatorInterface<AliTrackerBase>& operator=(const propagatorInterface<AliTrackerBase>&) CON_DELETE; bool propagateToX(float x, float maxSnp, float maxStep) { return PropagateTrackToBxByBz(mParam, x, 0.13957, maxStep, false, maxSnp); } - int getPropagatedYZ(My_Float x, My_Float& projY, My_Float& projZ) + int getPropagatedYZ(float x, float& projY, float& projZ) { Double_t yz[2] = {0.}; mParam->GetYZAt(x, GetBz(), yz); @@ -201,7 +201,7 @@ class propagatorInterface<o2::base::Propagator> propagatorInterface<o2::base::Propagator>& operator=(const propagatorInterface<o2::base::Propagator>&) = delete; bool propagateToX(float x, float maxSnp, float maxStep) { return mProp->PropagateToXBxByBz(*mParam, x, 0.13957, maxSnp, maxStep); } - int getPropagatedYZ(My_Float x, My_Float& projY, My_Float& projZ) { return static_cast<int>(mParam->getYZAt(x, mProp->getNominalBz(), projY, projZ)); } + int getPropagatedYZ(float x, float& projY, float& projZ) { return static_cast<int>(mParam->getYZAt(x, mProp->getNominalBz(), projY, projZ)); } void setTrack(trackInterface<o2::dataformats::TrackTPCITS>* trk) { mParam = trk; } void setFitInProjections(bool flag) {} diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index 646d68528092a..31c06f20ef778 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -711,7 +711,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK // although the radii of space points and tracks may differ by ~ few mm the roads are large enough to allow no efficiency loss by this cut continue; } - My_Float projY, projZ; + float projY, projZ; prop->getPropagatedYZ(mSpacePoints[trkltIdx].mR, projY, projZ); // correction for tilted pads (only applied if deltaZ < l_pad && track z err << l_pad) float tiltCorr = tilt * (mSpacePoints[trkltIdx].mX[1] - projZ); @@ -1268,13 +1268,12 @@ namespace GPUCA_NAMESPACE { namespace gpu { -// instatiate the tracker for both for GPU data types and for AliRoot/O2 data types #if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE) +// instantiate version for non-GPU data types template class GPUTRDTracker_t<GPUTRDTrack, GPUTRDPropagator>; #endif -#ifndef GPUCA_ALIROOT_LIB +// always instantiate version for GPU data types template class GPUTRDTracker_t<GPUTRDTrackGPU, GPUTRDPropagatorGPU>; -#endif } // namespace gpu } // namespace GPUCA_NAMESPACE #endif diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx index 2a78449830a96..becb53949aa38 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx @@ -130,7 +130,7 @@ int GPUTRDTrackerComponent::ReadConfigurationString(const char* arguments) if (argument.CompareTo("-debugOutput") == 0) { fDebugTrackOutput = true; fVerboseDebugOutput = true; - HLTInfo("Tracks are dumped in the GPUTRDTrack format"); + HLTInfo("Tracks are dumped in the GPUTRDTrackGPU format"); continue; } @@ -202,7 +202,7 @@ int GPUTRDTrackerComponent::DoInit(int argc, const char** argv) HLTError("TRD geometry not available"); return -EINVAL; } - fTracker = new GPUTRDTracker(); + fTracker = new GPUTRDTrackerGPU(); if (!fTracker) { return -ENOMEM; } @@ -252,7 +252,7 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con int iResult = 0; if (fTrackList->GetEntries() != 0) { - fTrackList->Clear(); // tracks are owned by GPUTRDTracker + fTrackList->Clear(); // tracks are owned by GPUTRDTrackerGPU } int nBlocks = evtData.fBlockCnt; @@ -261,7 +261,7 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con AliHLTTracksData* itsData = nullptr; AliHLTTrackMCData* tpcDataMC = nullptr; - std::vector<GPUTRDTrack> tracksTPC; + std::vector<GPUTRDTrackGPU> tracksTPC; std::vector<int> tracksTPCLab; std::vector<int> tracksTPCId; @@ -338,7 +338,7 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con if (itsData != nullptr && !itsAvail.at(currOutTrackTPC->fTrackID)) { continue; } - GPUTRDTrack t(*currOutTrackTPC); + GPUTRDTrackGPU t(*currOutTrackTPC); int mcLabel = -1; if (tpcDataMC) { if (mcLabels.find(currOutTrackTPC->fTrackID) != mcLabels.end()) { @@ -384,9 +384,9 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con fTracker->DoTracking(NULL); fBenchmark.Stop(1); - GPUTRDTrack* trackArray = fTracker->Tracks(); + GPUTRDTrackGPU* trackArray = fTracker->Tracks(); int nTracks = fTracker->NTracks(); - GPUTRDTracker::GPUTRDSpacePointInternal* spacePoints = fTracker->SpacePoints(); + GPUTRDTrackerGPU::GPUTRDSpacePointInternal* spacePoints = fTracker->SpacePoints(); // TODO delete fTrackList since it only works for TObjects (or use compiler flag after tests with GPU track type) // for (int iTrack=0; iTrack<nTracks; ++iTrack) { @@ -411,7 +411,7 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con int assignedTracklets = 0; for (int iTrk = 0; iTrk < nTracks; ++iTrk) { - GPUTRDTrack& t = trackArray[iTrk]; + GPUTRDTrackGPU& t = trackArray[iTrk]; if (t.GetNtracklets() == 0) { continue; } @@ -458,7 +458,7 @@ int GPUTRDTrackerComponent::DoEvent(const AliHLTComponentEventData& evtData, con } for (int i = 0; i < nTrackletsTotal; ++i) { - const GPUTRDTracker::GPUTRDSpacePointInternal& sp = spacePoints[i]; + const GPUTRDTrackerGPU::GPUTRDSpacePointInternal& sp = spacePoints[i]; int id = sp.mId; if (id < 0 || id >= nTrackletsTotal) { HLTError("Internal error: wrong space point index %d", id); diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.h b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.h index 9be4c4de9eff0..6adc8704e7e79 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.h @@ -131,7 +131,7 @@ class GPUTRDTrackerComponent : public AliHLTProcessor * Members - private * --------------------------------------------------------------------------------- */ - GPUCA_NAMESPACE::gpu::GPUTRDTracker* fTracker; // the tracker itself + GPUCA_NAMESPACE::gpu::GPUTRDTrackerGPU* fTracker; // the tracker itself GPUCA_NAMESPACE::gpu::GPUTRDGeometry* fGeo; // TRD geometry needed by the tracker GPUCA_NAMESPACE::gpu::GPUReconstruction* fRec; // GPU Reconstruction object GPUCA_NAMESPACE::gpu::GPUChainTracking* fChain; // Tracking Chain Object From 1c2c1d401c1c00f6b00594e96eb2d8646c3caa8d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 7 Oct 2020 16:02:00 +0200 Subject: [PATCH 0873/1751] GPU: Truncate invalid AliRoot cluster charges before dumping --- GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx index 5a7406188f9e6..6447ac7070202 100644 --- a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx +++ b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx @@ -252,8 +252,21 @@ int AliHLTGPUDumpComponent::DoEvent(const AliHLTComponentEventData& evtData, con #endif AliHLTTPCRawCluster tmp = cRaw; tmp.fPadRow += firstRow; + if ((unsigned int)cluster.amp >= 25 * 1024) { + GPUError("Invalid cluster charge, truncating (%d >= %d)", (int)cluster.amp, 25 * 1024); + cluster.amp = 25 * 1024 - 1; + } + if ((unsigned int)tmp.GetCharge() >= 25 * 1024) { + GPUError("Invalid raw cluster charge, truncating (%d >= %d)", (int)tmp.GetCharge(), 25 * 1024); + tmp.SetCharge(25 * 1024 - 1); + } + if ((unsigned int)tmp.GetQMax() >= 1024) { + GPUError("Invalid raw cluster charge max, truncating (%d >= %d)", (int)tmp.GetQMax(), 1024); + tmp.SetQMax(1024 - 1); + } clusterData[slice].emplace_back(cluster); rawClusters[slice].emplace_back(tmp); + nClustersTotal++; } } From 2e4dd12b23f857c8956154088f92adb3a379518e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 7 Oct 2020 16:44:04 +0200 Subject: [PATCH 0874/1751] GPU: Fix printout of tracking settings in standalone benchmark --- GPU/GPUTracking/Base/GPUSettingsList.h | 1 - GPU/GPUTracking/Standalone/utils/qconfig.cxx | 27 ++++++++++++ GPU/GPUTracking/Standalone/utils/qconfig.h | 44 +++++++++++--------- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index bc7e4e95f277b..0b5688dee2f2d 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -214,7 +214,6 @@ AddOption(runsInit, int, 1, "", 0, "Number of initial iterations excluded from a AddOption(EventsDir, const char*, "pp", "events", 'e', "Directory with events to process", message("Reading events from Directory events/%s")) AddOption(eventDisplay, int, 0, "display", 'd', "Show standalone event display", def(1)) //1: default display (Windows / X11), 2: glut, 3: glfw AddOption(eventGenerator, bool, false, "", 0, "Run event generator") -AddOption(nways7, bool, false, "", 0, "Create OuterParam") AddOption(cont, bool, false, "", 0, "Process continuous timeframe data") AddOption(outputcontrolmem, unsigned long, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ul), message("Using %lld bytes as output memory")) AddOption(inputcontrolmem, unsigned long, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ul), message("Using %lld bytes as input memory")) diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index 79dd8cffbe68b..bc918419f3958 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -21,6 +21,7 @@ #include <tuple> #include <vector> #include <string> +#include <sstream> #include "qconfig.h" // Create config instances @@ -500,8 +501,34 @@ static inline int qConfigParse(int argc, const char** argv, const char* /*filena int qConfigParse(int argc, const char** argv, const char* filename) { return (qConfig::qConfigParse(argc, argv, filename)); } // Print current config settings +namespace +{ +template <class T> +std::string print_type(T val) +{ + std::ostringstream s; + s << val; + return s.str(); +}; +template <> +std::string print_type<char>(char val) +{ + return std::to_string(val); +}; +template <> +std::string print_type<unsigned char>(unsigned char val) +{ + return std::to_string(val); +}; +template <> +std::string print_type<bool>(bool val) +{ + return val ? "true" : "false"; +}; +} // namespace void qConfigPrint() { + std::string blockName; #define QCONFIG_PRINT #include "qconfig.h" #undef QCONFIG_PRINT diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index 688ea042eae4e..4b931f97136b1 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -156,35 +156,39 @@ // End QCONFIG_HELP #elif defined(QCONFIG_PRINT) -#define AddOption(name, type, default, optname, optnameshort, ...) std::cout << "\t" << qon_mxstr(name) << ": " << tmp.name << "\n"; -#define AddVariable(name, type, default) std::cout << "\t" << qon_mxstr(name) << ": " << tmp.name << "\n"; +#define AddOption(name, type, default, optname, optnameshort, ...) std::cout << "\t" << blockName << qon_mxstr(name) << ": " << print_type(tmp.name) << "\n"; +#define AddVariable(name, type, default) std::cout << "\t" << blockName << qon_mxstr(name) << ": " << print_type(tmp.name) << "\n"; #define AddOptionSet(name, type, value, optname, optnameshort, ...) -#define AddOptionVec(name, type, optname, optnameshort, ...) \ - { \ - std::cout << "\t" << qon_mxstr(name) << "[]: "; \ - for (unsigned int i = 0; i < tmp.name.size(); i++) { \ - if (i) { \ - std::cout << ", "; \ - } /*std::cout << tmp.name[i];*/ \ - } \ - std::cout << "\n"; \ +#define AddOptionVec(name, type, optname, optnameshort, ...) \ + { \ + std::cout << "\t" << blockName << qon_mxstr(name) << "[]: "; \ + for (unsigned int i = 0; i < tmp.name.size(); i++) { \ + if (i) { \ + std::cout << ", "; \ + } \ + std::cout << print_type(tmp.name[i]); \ + } \ + std::cout << "\n"; \ } -#define AddOptionArray(name, type, count, default, optname, optnameshort, ...) \ - { \ - std::cout << "\t" << qon_mxstr(name) << "[" << count << "]: " << tmp.name[0]; \ - for (int i = 1; i < count; i++) { \ - std::cout << ", " << tmp.name[i]; \ - } \ - std::cout << "\n"; \ +#define AddOptionArray(name, type, count, default, optname, optnameshort, ...) \ + { \ + std::cout << "\t" << blockName << qon_mxstr(name) << "[" << count << "]: " << print_type(tmp.name[0]); \ + for (int i = 1; i < count; i++) { \ + std::cout << ", " << print_type(tmp.name[i]); \ + } \ + std::cout << "\n"; \ } #define AddSubConfig(name, instance) #define AddHelpText(text) printf(" " text ":\n"); #define BeginConfig(name, instance) \ { \ - name& tmp = instance; + name& tmp = instance; \ + blockName = ""; #define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ { \ - name& tmp = parent.instance; + name& tmp = parent.instance; \ + blockName = std::string("\t") + qon_mxstr(name) + "."; \ + std::cout << "\t" << qon_mxstr(name) << "\n"; #define EndConfig() } // End QCONFIG_PRINT From 92d4a42dc53cdcb571c208d1a1e47a8cd2781b25 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 7 Oct 2020 18:17:49 +0200 Subject: [PATCH 0875/1751] GPU: Add option to dump AliRoot TPC transformation map with timestamp from SOR --- GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx | 5 +++-- GPU/GPUTracking/Global/AliHLTGPUDumpComponent.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx index 6447ac7070202..d88ae53768a2a 100644 --- a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx +++ b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx @@ -54,7 +54,7 @@ using namespace GPUCA_NAMESPACE::gpu; -AliHLTGPUDumpComponent::AliHLTGPUDumpComponent() : fSolenoidBz(0.f), fRec(nullptr), fChain(nullptr), fFastTransformManager(new TPCFastTransformManager), fCalib(nullptr), fRecParam(nullptr), fOfflineRecoParam(), fOrigTransform(nullptr), fIsMC(false) +AliHLTGPUDumpComponent::AliHLTGPUDumpComponent() : fSolenoidBz(0.f), fRec(nullptr), fChain(nullptr), fFastTransformManager(new TPCFastTransformManager), fCalib(nullptr), fRecParam(nullptr), fOfflineRecoParam(), fOrigTransform(nullptr), fIsMC(false), fInitTimestamp(0.) { fRec = GPUReconstruction::CreateInstance(); fChain = fRec->AddChain<GPUChainTracking>(); @@ -150,6 +150,7 @@ int AliHLTGPUDumpComponent::DoInit(int argc, const char** argv) HLTFatal("No TPC Reco Param entry found for the given event specification"); } fCalib->GetTransform()->SetCurrentRecoParam(fRecParam); + fInitTimestamp = GetTimeStamp(); return 0; } @@ -460,7 +461,7 @@ int AliHLTGPUDumpComponent::DoEvent(const AliHLTComponentEventData& evtData, con if (nEvent == 0) { std::unique_ptr<TPCFastTransform> fFastTransformIRS(new TPCFastTransform); - long TimeStamp = GetTimeStamp(); + long TimeStamp = (getenv("DUMP_TIMESTAMP_SOR") && atoi(getenv("DUMP_TIMESTAMP_SOR"))) ? fInitTimestamp : GetTimeStamp(); if (fIsMC && !fRecParam->GetUseCorrectionMap()) { TimeStamp = 0; } diff --git a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.h b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.h index c1514e41bcfa3..c30d31de544b4 100644 --- a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.h +++ b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.h @@ -68,6 +68,7 @@ class AliHLTGPUDumpComponent : public AliHLTProcessor AliRecoParam fOfflineRecoParam; AliTPCTransform* fOrigTransform; bool fIsMC; + long fInitTimestamp; }; #endif From f95b54dc745879224fec30e26dc34bad3192c2b8 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 7 Oct 2020 20:40:21 +0200 Subject: [PATCH 0876/1751] GPU: Remove bogus initialization for cluster error correction in AliRoot --- GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx b/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx index a9c24968bbb37..773f66f3dd20b 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGlobalMergerComponent.cxx @@ -120,7 +120,7 @@ void GPUTPCGlobalMergerComponent::SetDefaultConfiguration() fSolenoidBz = -5.00668; fClusterErrorCorrectionY = 0; - fClusterErrorCorrectionZ = 1.1; + fClusterErrorCorrectionZ = 0; fNWays = 1; fNWaysOuter = 0; fNoClear = false; From 2a6805b8c632cd56efc9480afca4aa229afeb692 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 7 Oct 2020 20:40:33 +0200 Subject: [PATCH 0877/1751] GPU: Improve debug messages --- GPU/GPUTracking/Base/GPUParam.cxx | 5 ++--- GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 066392f0e7794..d3037cd8ef14e 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -35,7 +35,7 @@ void GPUParam::SetDefaults(float solenoidBz) new (&rec) GPUSettingsRec; // clang-format off - float const kParamS0Par[2][3][6] = + const float kParamS0Par[2][3][6] = { { { 6.45913474727e-04, 2.51547407970e-05, 1.57551113516e-02, 1.99872811635e-08, -5.86769729853e-03, 9.16301505640e-05 }, { 9.71546804067e-04, 1.70938055817e-05, 2.17084009200e-02, 3.90275758377e-08, -1.68631039560e-03, 8.40498323669e-05 }, @@ -45,8 +45,7 @@ void GPUParam::SetDefaults(float solenoidBz) { 1.15970033221e-03, 1.30452335725e-05, 1.87015570700e-02, 5.39766737973e-08, 1.64790824056e-02, 1.44115634612e-04 }, { 6.27940462437e-04, 1.78520094778e-05, 2.83537860960e-02, 1.16867742150e-08, 5.02607785165e-02, 1.88510020962e-04 } } }; - - float const kParamRMS0[2][3][4] = + const float kParamRMS0[2][3][4] = { { { 4.17516864836e-02, 1.87623649254e-04, 5.63788712025e-02, 5.38373768330e-01, }, { 8.29434990883e-02, 2.03291710932e-04, 6.81538805366e-02, 9.70965325832e-01, }, diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx index d29e041f122de..1c605118d6e2b 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx @@ -84,7 +84,7 @@ GPUd() void GPUTPCTrackletConstructor::StoreTracklet(int /*nBlocks*/, int /*nThr GPUglobalref() MEM_GLOBAL(GPUTPCTracklet) & GPUrestrict() tracklet = tracker.Tracklets()[itrout]; tracklet.SetNHits(r.mNHits); - CADEBUG(GPUInfo(" DONE %d hits", r.mNHits)); + CADEBUG(printf(" DONE %d hits\n", r.mNHits)); tracklet.SetFirstRow(r.mFirstRow); tracklet.SetLastRow(r.mLastRow); @@ -191,7 +191,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int break; } CADEBUG( - printf("%15s hits %3d: FIT PROP ROW %3d X %8.3f -", "", r.mNHits, iRow, tParam.X()); for (int i = 0; i < 5; i++) { printf(" %8.3f", tParam.Par()[i]); } printf(" -"); for (int i = 0; i < 15; i++) { printf(" %8.3f", tParam.Cov()[i]); } printf("\n")); + printf("%5s hits %3d: FIT PROP ROW %3d X %8.3f -", "", r.mNHits, iRow, tParam.X()); for (int i = 0; i < 5; i++) { printf(" %8.3f", tParam.Par()[i]); } printf(" -"); for (int i = 0; i < 15; i++) { printf(" %8.3f", tParam.Cov()[i]); } printf("\n")); tracker.GetErrors2Seeding(iRow, tParam.GetZ(), sinPhi, tParam.GetDzDs(), err2Y, err2Z); if (r.mNHits >= 10) { @@ -332,7 +332,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int float y = y0 + hh.x * stepY; float z = z0 + hh.y * stepZ; - CADEBUG(GPUInfo("%14s: SEA Hit %5d, Res %f %f", "", best, tParam.Y() - y, tParam.Z() - z)); + CADEBUG(printf("%14s: SEA Hit %5d (%8.3f %8.3f), Res %f %f\n", "", best, y, z, tParam.Y() - y, tParam.Z() - z)); calink oldHit = (r.mStage == 2 && iRow >= r.mStartRow) ? rowHit : CALINK_INVAL; if (oldHit != best && !tParam.Filter(y, z, err2Y, err2Z, GPUCA_MAX_SIN_PHI_LOW, oldHit != CALINK_INVAL)) { From 0a20bdc86b4386a07775a1ad5173cd7b1b041359 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 8 Oct 2020 14:57:36 +0200 Subject: [PATCH 0878/1751] DPL Analysis: fix WritingCursor::reserve() (#4536) --- Framework/Core/include/Framework/ASoA.h | 1 + Framework/Core/include/Framework/AnalysisHelpers.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index d95ca28ba1e87..76a4b1566f056 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -813,6 +813,7 @@ class Table public: using table_t = Table<C...>; using columns = framework::pack<C...>; + using column_types = framework::pack<typename C::type...>; using persistent_columns_t = framework::selected_pack<is_persistent_t, C...>; template <typename IP, typename Parent, typename... T> diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 50101722cdddb..0745170ebf804 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -64,7 +64,7 @@ struct WritingCursor<soa::Table<PC...>> { /// spend time reallocating the buffers. void reserve(int64_t size) { - mBuilder->reserve(typename persistent_table_t::columns{}, size); + mBuilder->reserve(typename persistent_table_t::column_types{}, size); } decltype(FFL(std::declval<cursor_t>())) cursor; From 0a1965c0d6d005d6fe71586e69c97fd130b0127c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 8 Oct 2020 16:31:24 +0200 Subject: [PATCH 0879/1751] GPU: Fix TPC-TRD track relation for non-consecutive TPC track ids --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index bffd6fa3b47d9..ca064bdc642e0 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2283,7 +2283,7 @@ int GPUChainTracking::RunTRDTracking() } for (unsigned int iTrack = 0; iTrack < tracksTPC.size(); ++iTrack) { - if (Tracker.LoadTrack(tracksTPC[iTrack], tracksTPCLab[iTrack])) { + if (Tracker.LoadTrack(tracksTPC[iTrack], tracksTPCLab[iTrack], nullptr, -1, tracksTPC[iTrack].GetTPCtrackId())) { return 1; } } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 6345c799daad3..c04a0aa52827c 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -109,7 +109,7 @@ class GPUTRDTracker_t : public GPUProcessor void Reset(); GPUd() int LoadTracklet(const GPUTRDTrackletWord& tracklet, const int* labels = nullptr); //template <class T> - GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1) + GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1, int tpcTrackId = -1) { if (mNTracks >= mNMaxTracks) { #ifndef GPUCA_GPUCODE @@ -131,7 +131,7 @@ class GPUTRDTracker_t : public GPUProcessor #else mTracks[mNTracks] = trk; #endif - mTracks[mNTracks].SetTPCtrackId(mNTracks); + mTracks[mNTracks].SetTPCtrackId(tpcTrackId >= 0 ? tpcTrackId : mNTracks); if (label >= 0) { mTracks[mNTracks].SetLabel(label); } From a74561119f9109e9d0b41f0e426779198bba1c75 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 8 Oct 2020 19:41:16 +0200 Subject: [PATCH 0880/1751] DPL Analysis: speedup insertion in basic columns (#4541) --- .../Core/include/Framework/TableBuilder.h | 267 +++++++++++++----- 1 file changed, 193 insertions(+), 74 deletions(-) diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index deeb8e494631c..37f84648651da 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -21,6 +21,7 @@ #include <sstream> #include <arrow/status.h> +#include <arrow/memory_pool.h> #include <arrow/stl.h> #include <arrow/type_traits.h> #include <arrow/table.h> @@ -32,6 +33,7 @@ #include <string> #include <memory> #include <tuple> +#include <type_traits> namespace arrow { @@ -108,75 +110,81 @@ struct BuilderUtils { return status; } - template <typename BuilderType, typename T> - static arrow::Status append(BuilderType& builder, T value) + template <typename HolderType, typename T> + static arrow::Status append(HolderType& holder, T value) { - return builder->Append(value); + return static_cast<typename HolderType::Policy&>(holder).append(holder.builder, value); + } + + template <typename HolderType> + static arrow::Status flush(HolderType& holder) + { + return static_cast<typename HolderType::Policy&>(holder).flush(holder.builder); } /// Appender for the pointer case. /// Assumes that the pointer actually points to a buffer /// which contains the correct number of elements. - template <typename BuilderType, typename T> - static arrow::Status append(BuilderType& builder, T* data) + template <typename HolderType, typename T> + static arrow::Status append(HolderType& holder, T* data) { - if constexpr (std::is_same_v<BuilderType, std::unique_ptr<arrow::FixedSizeListBuilder>>) { - return appendToList<T>(builder, data); + if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) { + return appendToList<T>(holder.builder, data); } else { - return builder->Append(reinterpret_cast<const uint8_t*>(data)); + return holder.builder->Append(reinterpret_cast<const uint8_t*>(data)); } } /// Appender for the array case. - template <typename BuilderType, typename T, int N> - static arrow::Status append(BuilderType& builder, T (&data)[N]) + template <typename HolderType, typename T, int N> + static arrow::Status append(HolderType& holder, T (&data)[N]) { - return builder->Append(reinterpret_cast<const uint8_t*>(data)); + return holder.builder->Append(reinterpret_cast<const uint8_t*>(data)); } /// Appender for the array case. - template <typename BuilderType, typename T, int N> - static arrow::Status append(BuilderType& builder, std::array<T, N> const& data) + template <typename HolderType, typename T, int N> + static arrow::Status append(HolderType& holder, std::array<T, N> const& data) { - return builder->Append(reinterpret_cast<const uint8_t*>(data.data())); + return holder.builder->Append(reinterpret_cast<const uint8_t*>(data.data())); } - template <typename BuilderType, typename T> - static void unsafeAppend(BuilderType& builder, T value) + template <typename HolderType, typename T> + static void unsafeAppend(HolderType& holder, T value) { - return builder->UnsafeAppend(value); + return holder.builder->UnsafeAppend(value); } - template <typename BuilderType, typename T> - static void unsafeAppend(BuilderType& builder, T* value) + template <typename HolderType, typename T> + static void unsafeAppend(HolderType& holder, T* value) { - if constexpr (std::is_same_v<BuilderType, std::unique_ptr<arrow::FixedSizeListBuilder>>) { - auto status = appendToList<T>(builder, value); + if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) { + auto status = appendToList<T>(holder.builder, value); } else { - return builder->UnsafeAppend(reinterpret_cast<const uint8_t*>(value)); + return holder.builder->UnsafeAppend(reinterpret_cast<const uint8_t*>(value)); } } - template <typename BuilderType, typename PTR> - static arrow::Status bulkAppend(BuilderType& builder, size_t bulkSize, const PTR ptr) + template <typename HolderType, typename PTR> + static arrow::Status bulkAppend(HolderType& holder, size_t bulkSize, const PTR ptr) { - return builder->AppendValues(ptr, bulkSize, nullptr); + return holder.builder->AppendValues(ptr, bulkSize, nullptr); } - template <typename BuilderType, typename PTR> - static arrow::Status bulkAppendChunked(BuilderType& builder, BulkInfo<PTR> info) + template <typename HolderType, typename PTR> + static arrow::Status bulkAppendChunked(HolderType& holder, BulkInfo<PTR> info) { // Appending nullptr is a no-op. if (info.ptr == nullptr) { return arrow::Status::OK(); } - if constexpr (std::is_same_v<BuilderType, std::unique_ptr<arrow::FixedSizeListBuilder>>) { - if (appendToList<std::remove_pointer_t<decltype(info.ptr)>>(builder, info.ptr, info.size).ok() == false) { + if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) { + if (appendToList<std::remove_pointer_t<decltype(info.ptr)>>(holder.builder, info.ptr, info.size).ok() == false) { throw std::runtime_error("Unable to append to column"); } else { return arrow::Status::OK(); } } else { - if (builder->AppendValues(info.ptr, info.size, nullptr).ok() == false) { + if (holder.builder->AppendValues(info.ptr, info.size, nullptr).ok() == false) { throw std::runtime_error("Unable to append to column"); } else { return arrow::Status::OK(); @@ -184,26 +192,26 @@ struct BuilderUtils { } } - template <typename BuilderType, typename ITERATOR> - static arrow::Status append(BuilderType& builder, std::pair<ITERATOR, ITERATOR> ip) + template <typename HolderType, typename ITERATOR> + static arrow::Status append(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip) { using ArrowType = typename detail::ConversionTraits<typename ITERATOR::value_type>::ArrowType; using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType; // FIXME: for the moment we do not fill things. - auto status = builder->Append(); - auto valueBuilder = reinterpret_cast<ValueBuilderType*>(builder->value_builder()); + auto status = holder.builder->Append(); + auto valueBuilder = reinterpret_cast<ValueBuilderType*>(holder.builder->value_builder()); return status & valueBuilder->AppendValues(&*ip.first, std::distance(ip.first, ip.second)); } // Lists do not have UnsafeAppend so we need to use the slow path in any case. - template <typename BuilderType, typename ITERATOR> - static void unsafeAppend(BuilderType& builder, std::pair<ITERATOR, ITERATOR> ip) + template <typename HolderType, typename ITERATOR> + static void unsafeAppend(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip) { using ArrowType = typename detail::ConversionTraits<typename ITERATOR::value_type>::ArrowType; using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType; // FIXME: for the moment we do not fill things. - auto status = builder->Append(); - auto valueBuilder = reinterpret_cast<ValueBuilderType*>(builder->value_builder()); + auto status = holder.builder->Append(); + auto valueBuilder = reinterpret_cast<ValueBuilderType*>(holder.builder->value_builder()); status &= valueBuilder->AppendValues(&*ip.first, std::distance(ip.first, ip.second)); if (!status.ok()) { throw std::runtime_error("Unable to append values to valueBuilder!"); @@ -327,7 +335,6 @@ struct BuilderMaker<T[N]> { return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N); } }; - template <typename... ARGS> auto make_builders() { @@ -356,6 +363,62 @@ struct BuilderTraits<T[N]> { using BuilderType = arrow::FixedSizeListBuilder; }; +template <typename T> +struct DirectInsertion { + template <typename BUILDER> + arrow::Status append(BUILDER& builder, T value) + { + return builder->Append(value); + } + + template <typename BUILDER> + arrow::Status flush(BUILDER&) + { + return arrow::Status::OK(); + } +}; + +template <typename T> +struct CachedInsertion { + static constexpr int CHUNK_SIZE = 256; + + template <typename BUILDER> + arrow::Status append(BUILDER& builder, T value) + { + cache[pos % CHUNK_SIZE] = value; + ++pos; + if (pos % CHUNK_SIZE == 0) { + return builder->AppendValues(cache, CHUNK_SIZE, nullptr); + } + return arrow::Status::OK(); + } + + template <typename BUILDER> + arrow::Status flush(BUILDER& builder) + { + if (pos % CHUNK_SIZE != 0) { + return builder->AppendValues(cache, pos % CHUNK_SIZE, nullptr); + } + return arrow::Status::OK(); + } + T cache[CHUNK_SIZE]; + int pos = 0; +}; + +template <typename T, template <typename U> typename InsertionPolicy> +struct BuilderHolder : InsertionPolicy<T> { + using Policy = InsertionPolicy<T>; + using ArrowType = typename detail::ConversionTraits<T>::ArrowType; + using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType; + + BuilderHolder(arrow::MemoryPool* pool) + : builder{BuilderMaker<T>::make(pool)} + { + } + + std::unique_ptr<BuilderType> builder; +}; + struct TableBuilderHelpers { template <typename... ARGS> static auto makeFields(std::vector<std::string> const& names) @@ -369,25 +432,25 @@ struct TableBuilderHelpers { } /// Invokes the append method for each entry in the tuple - template <std::size_t... Is, typename BUILDERS, typename VALUES> - static bool append(BUILDERS& builders, std::index_sequence<Is...>, VALUES&& values) + template <std::size_t... Is, typename HOLDERS, typename VALUES> + static bool append(HOLDERS& holders, std::index_sequence<Is...>, VALUES&& values) { - return (BuilderUtils::append(std::get<Is>(builders), std::get<Is>(values)).ok() && ...); + return (BuilderUtils::append(std::get<Is>(holders), std::get<Is>(values)).ok() && ...); } /// Invokes the UnsafeAppend method for each entry in the tuple /// For this to be used, one should make sure the number of entries /// is known a-priori. - template <std::size_t... Is, typename BUILDERS, typename VALUES> - static void unsafeAppend(BUILDERS& builders, std::index_sequence<Is...>, VALUES&& values) + template <std::size_t... Is, typename HOLDERS, typename VALUES> + static void unsafeAppend(HOLDERS& holders, std::index_sequence<Is...>, VALUES&& values) { - (BuilderUtils::unsafeAppend(std::get<Is>(builders), std::get<Is>(values)), ...); + (BuilderUtils::unsafeAppend(std::get<Is>(holders), std::get<Is>(values)), ...); } - template <std::size_t... Is, typename BUILDERS, typename PTRS> - static bool bulkAppend(BUILDERS& builders, size_t bulkSize, std::index_sequence<Is...>, PTRS ptrs) + template <std::size_t... Is, typename HOLDERS, typename PTRS> + static bool bulkAppend(HOLDERS& holders, size_t bulkSize, std::index_sequence<Is...>, PTRS ptrs) { - return (BuilderUtils::bulkAppend(std::get<Is>(builders), bulkSize, std::get<Is>(ptrs)).ok() && ...); + return (BuilderUtils::bulkAppend(std::get<Is>(holders), bulkSize, std::get<Is>(ptrs)).ok() && ...); } /// Return true if all columns are done. @@ -398,16 +461,17 @@ struct TableBuilderHelpers { } /// Invokes the append method for each entry in the tuple - template <typename BUILDERS, std::size_t... Is> - static bool finalize(std::vector<std::shared_ptr<arrow::Array>>& arrays, BUILDERS& builders, std::index_sequence<Is...> seq) + template <typename HOLDERS, std::size_t... Is> + static bool finalize(std::vector<std::shared_ptr<arrow::Array>>& arrays, HOLDERS& holders, std::index_sequence<Is...> seq) { - return (std::get<Is>(builders)->Finish(&arrays[Is]).ok() && ...); + bool ok = (BuilderUtils::flush(std::get<Is>(holders)).ok() && ...); + return ok && (std::get<Is>(holders).builder->Finish(&arrays[Is]).ok() && ...); } - template <typename BUILDERS, std::size_t... Is> - static bool reserveAll(BUILDERS& builders, size_t s, std::index_sequence<Is...>) + template <typename HOLDERS, std::size_t... Is> + static bool reserveAll(HOLDERS& holders, size_t s, std::index_sequence<Is...>) { - return (std::get<Is>(builders)->Reserve(s).ok() && ...); + return (std::get<Is>(holders).builder->Reserve(s).ok() && ...); } }; @@ -432,20 +496,75 @@ template <class T, std::size_t N> struct is_bounded_array<std::array<T, N>> : std::true_type { }; +template <typename T> +struct HolderTrait { + using Holder = BuilderHolder<T, DirectInsertion>; +}; + +template <> +struct HolderTrait<int8_t> { + using Holder = BuilderHolder<int8_t, CachedInsertion>; +}; + +template <> +struct HolderTrait<uint8_t> { + using Holder = BuilderHolder<uint8_t, CachedInsertion>; +}; + +template <> +struct HolderTrait<uint16_t> { + using Holder = BuilderHolder<uint16_t, CachedInsertion>; +}; + +template <> +struct HolderTrait<int16_t> { + using Holder = BuilderHolder<int16_t, CachedInsertion>; +}; + +template <> +struct HolderTrait<int> { + using Holder = BuilderHolder<int, CachedInsertion>; +}; + +template <> +struct HolderTrait<float> { + using Holder = BuilderHolder<float, CachedInsertion>; +}; + +template <> +struct HolderTrait<double> { + using Holder = BuilderHolder<double, CachedInsertion>; +}; + +template <> +struct HolderTrait<unsigned int> { + using Holder = BuilderHolder<unsigned int, CachedInsertion>; +}; + +template <> +struct HolderTrait<uint64_t> { + using Holder = BuilderHolder<uint64_t, CachedInsertion>; +}; + +template <> +struct HolderTrait<int64_t> { + using Holder = BuilderHolder<int64_t, CachedInsertion>; +}; + /// Helper class which creates a lambda suitable for building /// an arrow table from a tuple. This can be used, for example /// to build an arrow::Table from a TDataFrame. class TableBuilder { template <typename... ARGS> - using BuildersTuple = typename std::tuple<std::unique_ptr<typename BuilderTraits<ARGS>::BuilderType>...>; + using HoldersTuple = typename std::tuple<typename HolderTrait<ARGS>::Holder...>; /// Get the builders, assumning they were created with a given pack /// of basic types template <typename... ARGS> auto getBuilders(o2::framework::pack<ARGS...> pack) { - return (BuildersTuple<ARGS...>*)mBuilders; + return (HoldersTuple<ARGS...>*)mHolders; } template <typename... ARGS> @@ -455,7 +574,7 @@ class TableBuilder if (nColumns != columnNames.size()) { throw std::runtime_error("Mismatching number of column types and names"); } - if (mBuilders != nullptr) { + if (mHolders != nullptr) { throw std::runtime_error("TableBuilder::persist can only be invoked once per instance"); } } @@ -465,19 +584,19 @@ class TableBuilder { mSchema = std::make_shared<arrow::Schema>(TableBuilderHelpers::makeFields<ARGS...>(columnNames)); - auto builders = new BuildersTuple<ARGS...>(BuilderMaker<ARGS>::make(mMemoryPool)...); + auto holders = new HoldersTuple<ARGS...>(typename HolderTrait<ARGS>::Holder(mMemoryPool)...); if (nRows != -1) { auto seq = std::make_index_sequence<sizeof...(ARGS)>{}; - TableBuilderHelpers::reserveAll(*builders, nRows, seq); + TableBuilderHelpers::reserveAll(*holders, nRows, seq); } - mBuilders = builders; // We store the builders + mHolders = holders; // We store the builders } template <typename... ARGS> auto makeFinalizer() { - mFinalizer = [schema = mSchema, &arrays = mArrays, builders = mBuilders]() -> void { - auto status = TableBuilderHelpers::finalize(arrays, *(BuildersTuple<ARGS...>*)builders, std::make_index_sequence<sizeof...(ARGS)>{}); + mFinalizer = [schema = mSchema, &arrays = mArrays, holders = mHolders]() -> void { + auto status = TableBuilderHelpers::finalize(arrays, *(HoldersTuple<ARGS...>*)holders, std::make_index_sequence<sizeof...(ARGS)>{}); if (status == false) { throw std::runtime_error("Unable to finalize"); } @@ -486,7 +605,7 @@ class TableBuilder public: TableBuilder(arrow::MemoryPool* pool = arrow::default_memory_pool()) - : mBuilders{nullptr}, + : mHolders{nullptr}, mMemoryPool{pool} { } @@ -538,8 +657,8 @@ class TableBuilder // Callback used to fill the builders using FillTuple = std::tuple<typename BuilderMaker<ARGS>::FillType...>; - return [builders = mBuilders](unsigned int slot, FillTuple const& t) -> void { - auto status = TableBuilderHelpers::append(*(BuildersTuple<ARGS...>*)builders, std::index_sequence_for<ARGS...>{}, t); + return [holders = mHolders](unsigned int slot, FillTuple const& t) -> void { + auto status = TableBuilderHelpers::append(*(HoldersTuple<ARGS...>*)holders, std::index_sequence_for<ARGS...>{}, t); if (status == false) { throw std::runtime_error("Unable to append"); } @@ -574,8 +693,8 @@ class TableBuilder makeFinalizer<ARGS...>(); // Callback used to fill the builders - return [builders = mBuilders](unsigned int slot, typename BuilderMaker<ARGS>::FillType... args) -> void { - TableBuilderHelpers::unsafeAppend(*(BuildersTuple<ARGS...>*)builders, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); + return [holders = mHolders](unsigned int slot, typename BuilderMaker<ARGS>::FillType... args) -> void { + TableBuilderHelpers::unsafeAppend(*(HoldersTuple<ARGS...>*)holders, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); }; } @@ -588,8 +707,8 @@ class TableBuilder makeBuilders<ARGS...>(columnNames, nRows); makeFinalizer<ARGS...>(); - return [builders = mBuilders](unsigned int slot, size_t batchSize, typename BuilderMaker<ARGS>::FillType const*... args) -> void { - TableBuilderHelpers::bulkAppend(*(BuildersTuple<ARGS...>*)builders, batchSize, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); + return [holders = mHolders](unsigned int slot, size_t batchSize, typename BuilderMaker<ARGS>::FillType const*... args) -> void { + TableBuilderHelpers::bulkAppend(*(HoldersTuple<ARGS...>*)holders, batchSize, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); }; } @@ -602,8 +721,8 @@ class TableBuilder makeBuilders<ARGS...>(columnNames, nRows); makeFinalizer<ARGS...>(); - return [builders = mBuilders](unsigned int slot, BulkInfo<typename BuilderMaker<ARGS>::STLValueType const*>... args) -> bool { - return TableBuilderHelpers::bulkAppendChunked(*(BuildersTuple<ARGS...>*)builders, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); + return [holders = mHolders](unsigned int slot, BulkInfo<typename BuilderMaker<ARGS>::STLValueType const*>... args) -> bool { + return TableBuilderHelpers::bulkAppendChunked(*(HoldersTuple<ARGS...>*)holders, std::index_sequence_for<ARGS...>{}, std::forward_as_tuple(args...)); }; } @@ -611,7 +730,7 @@ class TableBuilder template <typename... ARGS> auto reserve(o2::framework::pack<ARGS...> pack, int s) { - visitBuilders(pack, [s](auto& builder) { return builder.Reserve(s).ok(); }); + visitBuilders(pack, [s](auto& holder) { return holder.builder->Reserve(s).ok(); }); } /// Invoke the appropriate visitor on the various builders @@ -620,7 +739,7 @@ class TableBuilder { auto builders = getBuilders(pack); return std::apply(overloaded{ - [visitor](std::unique_ptr<typename BuilderTraits<ARGS>::BuilderType>&... args) { (visitor(*args), ...); }}, + [visitor](typename HolderTrait<ARGS>::Holder&... args) { (visitor(args), ...); }}, *builders); } @@ -646,7 +765,7 @@ class TableBuilder } std::function<void(void)> mFinalizer; - void* mBuilders; + void* mHolders; arrow::MemoryPool* mMemoryPool; std::shared_ptr<arrow::Schema> mSchema; std::vector<std::shared_ptr<arrow::Array>> mArrays; From 708b06e15bd7fecbd3433d49e3eb0b23034cc3b8 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 8 Oct 2020 16:14:16 +0200 Subject: [PATCH 0881/1751] Add macro to dump TRD transf matrices from AliRoot --- GPU/GPUTracking/Standalone/tools/createGeo.C | 1 + .../Standalone/tools/dumpTRDClusterMatrices.C | 83 +++++++++++++++++++ cmake/O2RootMacroExclusionList.cmake | 1 + 3 files changed, 85 insertions(+) create mode 100644 GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C diff --git a/GPU/GPUTracking/Standalone/tools/createGeo.C b/GPU/GPUTracking/Standalone/tools/createGeo.C index e084cd7cae9ad..bd8d1443768d7 100644 --- a/GPU/GPUTracking/Standalone/tools/createGeo.C +++ b/GPU/GPUTracking/Standalone/tools/createGeo.C @@ -16,6 +16,7 @@ void createGeo() gm->createPadPlaneArray(); gm->createClusterMatrixArray(); o2::trd::TRDGeometryFlat gf(*gm); + //if (!gf.readMatricesFromFile()) return; // uncomment this line when the matrices dumped from AliRoot should be used gSystem->Load("libO2GPUTracking.so"); GPUReconstruction* rec = GPUReconstruction::CreateInstance(GPUReconstruction::DeviceType::CPU); GPUChainTracking* chain = rec->AddChain<GPUChainTracking>(); diff --git a/GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C b/GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C new file mode 100644 index 0000000000000..362e4cdc6287c --- /dev/null +++ b/GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C @@ -0,0 +1,83 @@ +#include "AliCDBManager.h" +#include "AliGeomManager.h" +#include "AliTRDgeometry.h" + +#include "TGeoMatrix.h" + +#include <iostream> +#include <fstream> + +/* + This macro loads the TRD geometry taking into account the alignment from Run 2 + and dumps the inverse of all cluster matrices to a file. + To load the matrices add the following include and method to + TRDGeometryFlat.h: + +#include <fstream> + + GPUd() bool readMatricesFromFile() + { + std::ifstream fIn("matrices.dat", std::ios::in | std::ios::binary); + if (!fIn) { + printf("Cannot read file\n"); + return false; + } + for (int iDet = 0; iDet < constants::NCHAMBER; ++iDet) { + float m[12]; + for (int j=0; j<12; ++j) { + fIn.read((char*) &m[j], sizeof(float)); + } + mMatrixCache[iDet] = o2::gpu::Transform3D(m); + } + return true; + } + + Don't forget to uncomment the line in createGeo.C which calls this method. + + Note that only 521 chambers are installed. + +*/ + +void dumpTRDClusterMatrices() +{ + auto man = AliCDBManager::Instance(); + if (!man->IsDefaultStorageSet()) { + man->SetDefaultStorage("local:///cvmfs/alice-ocdb.cern.ch/calibration/data/2015/OCDB"); + man->SetRun(244340); + } + AliGeomManager::LoadGeometry(); + AliGeomManager::ApplyAlignObjsFromCDB("ITS TPC TRD TOF"); + + auto geo = new AliTRDgeometry(); + + std::ofstream fOut("matrices.dat", std::ios::out | std::ios::binary); + if (!fOut) { + printf("Cannot open file\n"); + return; + } + + int nMatrices = 0; + + for (int i = 0; i < 540; ++i) { + // dump all available matrices to a file + auto matrix = geo->GetClusterMatrix(i); + if (!matrix) { + printf("No matrix for chamber %i\n", i); + continue; + } + ++nMatrices; + auto matrixO2 = matrix->Inverse(); + + auto tr = matrixO2.GetTranslation(); + auto rot = matrixO2.GetRotationMatrix(); + + float m[12] = {static_cast<float>(rot[0]), static_cast<float>(rot[1]), static_cast<float>(rot[2]), static_cast<float>(tr[0]), static_cast<float>(rot[3]), static_cast<float>(rot[4]), static_cast<float>(rot[5]), static_cast<float>(tr[1]), static_cast<float>(rot[6]), static_cast<float>(rot[7]), static_cast<float>(rot[8]), static_cast<float>(tr[2])}; + + for (int j = 0; j < 12; ++j) { + fOut.write((char*)&m[j], sizeof(float)); + } + } + + fOut.close(); + printf("Dumped %i matrices\n", nMatrices); +} diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 2842c256a7b08..a002cf240b1bb 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -36,6 +36,7 @@ list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST GPU/GPUTracking/Merger/macros/fitPolynomialFieldTpc.C # Needs AliRoot AliMagF GPU/GPUTracking/Merger/macros/fitPolynomialFieldTrd.C # Needs AliRoot AliMagF GPU/GPUTracking/Standalone/tools/dump.C # Needs AliRoot ALiHLTSystem + GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C # Needs AliRoot AliCDBManager, AliGeomManager and AliTRDgeometry GPU/GPUTracking/TRDTracking/macros/checkDbgOutput.C # Needs AliRoot TStatToolkit GPU/TPCFastTransformation/alirootMacro/createTPCFastTransform.C # Needs AliTPCCalibDB GPU/TPCFastTransformation/alirootMacro/generateTPCDistortionNTupleAliRoot.C # Needs AliTPCCalibDB From 64a56b909ceefc59f754bc756bb5d1cf0028e724 Mon Sep 17 00:00:00 2001 From: Jorge Lopez <jorgext@gmail.com> Date: Tue, 6 Oct 2020 23:04:31 -0300 Subject: [PATCH 0882/1751] remove labels that do not have a digit --- .../simulation/include/TRDSimulation/Digitizer.h | 13 +++++++------ Detectors/TRD/simulation/src/Digitizer.cxx | 13 ++++++++----- Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx | 3 +++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h index 984a8d593bdef..4b6106a313564 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h @@ -40,10 +40,11 @@ class TRDArraySignal; class PadResponse; struct SignalArray { - double firstTBtime; // first TB time + double firstTBtime; // first TB time std::array<float, constants::TIMEBINS> signals{}; // signals - std::unordered_map<int, int> trackIds; // tracks Ids associated to the signal - std::vector<MCLabel> labels; // labels associated to the signal + std::unordered_map<int, int> trackIds; // tracks Ids associated to the signal + std::vector<MCLabel> labels; // labels associated to the signal + bool isDigit = false; // flag a signal converted to a digit }; using DigitContainer = std::vector<Digit>; @@ -114,8 +115,8 @@ class Digitizer int mMaxTimeBinsTRAP = 30; // Maximum number of time bins for processing adcs; should be read from the CCDB or the TRAP config // Digitization containers - std::vector<HitType> mHitContainer; // the container of hits in a given detector - std::vector<MCLabel> mMergedLabels; // temporary label container + std::vector<HitType> mHitContainer; // the container of hits in a given detector + std::vector<MCLabel> mMergedLabels; // temporary label container std::array<SignalContainer, constants::MAXCHAMBER> mSignalsMapCollection; // container for caching signals over a timeframe std::deque<std::array<SignalContainer, constants::MAXCHAMBER>> mPileupSignals; // container for piled up signals @@ -128,7 +129,7 @@ class Digitizer SignalContainer addSignalsFromPileup(); void clearContainers(); bool convertHits(const int, const std::vector<HitType>&, SignalContainer&, int thread = 0); // True if hit-to-signal conversion is successful - bool convertSignalsToADC(const SignalContainer&, DigitContainer&, int thread = 0); // True if signal-to-ADC conversion is successful + bool convertSignalsToADC(SignalContainer&, DigitContainer&, int thread = 0); // True if signal-to-ADC conversion is successful void addLabel(const o2::trd::HitType& hit, std::vector<o2::trd::MCLabel>&, std::unordered_map<int, int>&); bool diffusion(float, float, float, float, float, float, double&, double&, double&, int thread = 0); // True if diffusion is applied successfully diff --git a/Detectors/TRD/simulation/src/Digitizer.cxx b/Detectors/TRD/simulation/src/Digitizer.cxx index e3c770b655271..efcc78e90545a 100644 --- a/Detectors/TRD/simulation/src/Digitizer.cxx +++ b/Detectors/TRD/simulation/src/Digitizer.cxx @@ -96,19 +96,21 @@ void Digitizer::flush(DigitContainer& digits, o2::dataformats::MCTruthContainer< LOG(WARN) << "TRD conversion of signals to digits failed"; } for (const auto& iter : smc) { - labels.addElements(labels.getIndexedSize(), iter.second.labels); + if (iter.second.isDigit) + labels.addElements(labels.getIndexedSize(), iter.second.labels); } } } else { // since we don't have any pileup signals just flush the signals for each chamber // we avoid flattening the array<map, ndets> to a single map - for (const auto& smc : mSignalsMapCollection) { + for (auto& smc : mSignalsMapCollection) { bool status = convertSignalsToADC(smc, digits); if (!status) { LOG(WARN) << "TRD conversion of signals to digits failed"; } for (const auto& iter : smc) { - labels.addElements(labels.getIndexedSize(), iter.second.labels); + if (iter.second.isDigit) + labels.addElements(labels.getIndexedSize(), iter.second.labels); } } } @@ -482,7 +484,7 @@ float drawGaus(o2::math_utils::RandomRing<>& normaldistRing, float mu, float sig return mu + sigma * normaldistRing.getNextValue(); } -bool Digitizer::convertSignalsToADC(const SignalContainer& signalMapCont, DigitContainer& digits, int thread) +bool Digitizer::convertSignalsToADC(SignalContainer& signalMapCont, DigitContainer& digits, int thread) { // // Converts the sampled electron signals to ADC values for a given chamber @@ -495,7 +497,7 @@ bool Digitizer::convertSignalsToADC(const SignalContainer& signalMapCont, DigitC double baseline = mSimParam->GetADCbaseline() / adcConvert; // The electronics baseline in mV double baselineEl = baseline / convert; // The electronics baseline in electrons - for (const auto& signalMapIter : signalMapCont) { + for (auto& signalMapIter : signalMapCont) { const auto key = signalMapIter.first; const int det = getDetectorFromKey(key); const int row = getRowFromKey(key); @@ -522,6 +524,7 @@ bool Digitizer::convertSignalsToADC(const SignalContainer& signalMapCont, DigitC LOG(FATAL) << "Not a valid gain " << padgain << ", " << det << ", " << col << ", " << row; } + signalMapIter.second.isDigit = true; // flag the signal as digit // Loop over the all timebins in the ADC array const auto& signalArray = signalMapIter.second.signals; ArrayADC adcs{}; diff --git a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx index 3fe597f5e627f..2f464bb9aa724 100644 --- a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx @@ -100,6 +100,7 @@ class TRDDPLDigitizerTask : public o2::base::BaseDPLDigitizer LOG(INFO) << "For collision " << collID << " eventID " << part.entryID << " found TRD " << hits.size() << " hits "; mDigitizer.process(hits, digits, labels); + assert(digits.size() == labels.getIndexedSize()); // Add trigger record triggers.emplace_back(irecords[collID], digitsAccum.size(), digits.size()); @@ -114,6 +115,8 @@ class TRDDPLDigitizerTask : public o2::base::BaseDPLDigitizer } // Force flush of the digits that remain in the digitizer cache mDigitizer.flush(digits, labels); + assert(digits.size() == labels.getIndexedSize()); + triggers.emplace_back(irecords[irecords.size() - 1], digitsAccum.size(), digits.size()); std::copy(digits.begin(), digits.end(), std::back_inserter(digitsAccum)); if (mctruth) { From 555a727367e6613114f93f748e7da4186a75eb29 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 8 Oct 2020 20:29:02 +0200 Subject: [PATCH 0883/1751] Fix compiler warning --- Framework/Utils/include/DPLUtils/RootTreeWriter.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Framework/Utils/include/DPLUtils/RootTreeWriter.h b/Framework/Utils/include/DPLUtils/RootTreeWriter.h index abb47d0981f20..87f47893c31ef 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeWriter.h +++ b/Framework/Utils/include/DPLUtils/RootTreeWriter.h @@ -634,9 +634,10 @@ class RootTreeWriter // A helper struct mimicking data layout of std::vector containers // We assume a standard layout of begin, end, end_capacity struct VecBase { - const ElementType* start; - const ElementType* end; - const ElementType* cap; + VecBase() = default; + const ElementType* start = nullptr; + const ElementType* end = nullptr; + const ElementType* cap = nullptr; }; // a low level hack to make a gsl::span appear as a std::vector so that ROOT serializes the correct type From cfe970b6ab6c5e1951d532ffb5fad868e13b10ed Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Fri, 9 Oct 2020 08:36:08 +0200 Subject: [PATCH 0884/1751] Applying the min pt candidate prefiltering cut before the 2 vertex reconstruction (#4547) --- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 169 +++++++++--------- 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 17a0746d0ed73..8a6d6908f9786 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -183,28 +183,27 @@ struct HFTrackIndexSkimsCreator { continue; auto trackParVarNeg1 = getTrackParCov(trackNeg1); + Double_t px_Cand = trackPos1.px() + trackNeg1.px(); + Double_t py_Cand = trackPos1.py() + trackNeg1.py(); + Double_t pt_Cand_before2vertex = TMath::Sqrt(px_Cand * px_Cand + py_Cand * py_Cand); - // reconstruct the 2-prong secondary vertex - if (df.process(trackParVarPos1, trackParVarNeg1) == 0) - continue; - - // get vertex - //const auto& vtx = df.getPCACandidate(); + if (pt_Cand_before2vertex >= ptmincand_2prong) { + // reconstruct the 2-prong secondary vertex + if (df.process(trackParVarPos1, trackParVarNeg1) == 0) + continue; - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - df.getTrack(0).getPxPyPzGlo(pvec0); - df.getTrack(1).getPxPyPzGlo(pvec1); - const auto& secondaryVertex = df.getPCACandidate(); + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + df.getTrack(0).getPxPyPzGlo(pvec0); + df.getTrack(1).getPxPyPzGlo(pvec1); + const auto& secondaryVertex = df.getPCACandidate(); - // calculate invariant masses - auto arrMom = array{pvec0, pvec1}; - mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); - mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); - ptcand_2prong = RecoDecay::Pt(pvec0, pvec1); + // calculate invariant masses + auto arrMom = array{pvec0, pvec1}; + mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); + mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); - if (ptcand_2prong >= ptmincand_2prong) { if (b_dovalplots) { hmass2->Fill(mass2PiK); hmass2->Fill(mass2KPi); @@ -217,6 +216,7 @@ struct HFTrackIndexSkimsCreator { trackPos1.globalIndex(), trackNeg1.globalIndex(), 1); } + // 3-prong vertex reconstruction if (do3prong == 1) { if (trackPos1.isSel3Prong() == 0) @@ -243,42 +243,41 @@ struct HFTrackIndexSkimsCreator { continue; auto trackParVarPos2 = getTrackParCov(trackPos2); - - // reconstruct the 3-prong secondary vertex - if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) - continue; - - // get vertex - //const auto& vtx3 = df3.getPCACandidate(); - - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - array<float, 3> pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); - const auto& secondaryVertex3 = df3.getPCACandidate(); - - // calculate invariant mass - arr3Mom = array{pvec0, pvec1, pvec2}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - ptcand_3prong = RecoDecay::Pt(pvec0, pvec1, pvec2); - - if (ptcand_3prong < ptmincand_3prong) - continue; - if (b_dovalplots) { - hmass3->Fill(mass3PiKPi); - hvtx3_x_out->Fill(secondaryVertex3[0]); - hvtx3_y_out->Fill(secondaryVertex3[1]); - hvtx3_z_out->Fill(secondaryVertex3[2]); + Double_t px_Cand3 = trackPos1.px() + trackNeg1.px() + trackPos2.px(); + Double_t py_Cand3 = trackPos1.py() + trackNeg1.py() + trackPos2.py(); + Double_t pt_Cand3_before2vertex = TMath::Sqrt(px_Cand * px_Cand + py_Cand * py_Cand); + + if (pt_Cand3_before2vertex >= ptmincand_3prong) { + // reconstruct the 3-prong secondary vertex + if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) + continue; + + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); + const auto& secondaryVertex3 = df3.getPCACandidate(); + + // calculate invariant mass + arr3Mom = array{pvec0, pvec1, pvec2}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + + if (b_dovalplots) { + hmass3->Fill(mass3PiKPi); + hvtx3_x_out->Fill(secondaryVertex3[0]); + hvtx3_y_out->Fill(secondaryVertex3[1]); + hvtx3_z_out->Fill(secondaryVertex3[2]); + } + + // fill table row + rowTrackIndexProng3(trackPos1.collisionId(), + trackPos1.globalIndex(), + trackNeg1.globalIndex(), + trackPos2.globalIndex(), 2); } - - // fill table row - rowTrackIndexProng3(trackPos1.collisionId(), - trackPos1.globalIndex(), - trackNeg1.globalIndex(), - trackPos2.globalIndex(), 2); } // second loop over negative tracks @@ -300,38 +299,40 @@ struct HFTrackIndexSkimsCreator { continue; auto trackParVarNeg2 = getTrackParCov(trackNeg2); - - // reconstruct the 3-prong secondary vertex - if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) - continue; - - // get vertex - //const auto& vtx3 = df3.getPCACandidate(); - - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - array<float, 3> pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); - - // calculate invariant mass - arr3Mom = array{pvec0, pvec1, pvec2}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - ptcand_3prong = RecoDecay::Pt(pvec0, pvec1, pvec2); - - if (ptcand_3prong < ptmincand_3prong) - continue; - if (b_dovalplots) { - hmass3->Fill(mass3PiKPi); + Double_t px_Cand3 = trackPos1.px() + trackNeg1.px() + trackNeg2.px(); + Double_t py_Cand3 = trackPos1.py() + trackNeg1.py() + trackNeg2.py(); + Double_t pt_Cand3_before2vertex = TMath::Sqrt(px_Cand3 * px_Cand3 + py_Cand3 * py_Cand3); + + if (pt_Cand3_before2vertex >= ptmincand_3prong) { + // reconstruct the 3-prong secondary vertex + if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) + continue; + + // get vertex + //const auto& vtx3 = df3.getPCACandidate(); + + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); + + // calculate invariant mass + arr3Mom = array{pvec0, pvec1, pvec2}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + + if (b_dovalplots) { + hmass3->Fill(mass3PiKPi); + } + + // fill table row + rowTrackIndexProng3(trackNeg1.collisionId(), + trackNeg1.globalIndex(), + trackPos1.globalIndex(), + trackNeg2.globalIndex(), 2); } - - // fill table row - rowTrackIndexProng3(trackNeg1.collisionId(), - trackNeg1.globalIndex(), - trackPos1.globalIndex(), - trackNeg2.globalIndex(), 2); } } } From 7817030a805158415fdb322933a2c7c0320b2343 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Fri, 9 Oct 2020 08:46:41 +0200 Subject: [PATCH 0885/1751] DQ Skimming Update * removed tof and tpc pid response from table maker * Several changes. More variables added in VarManager; TableMaker applies tighter selection track cuts; Output object for histograms changed to take the HistogramManager master histogram list instead of the manager itself. * fixup! Several changes. More variables added in VarManager; TableMaker applies tighter selection track cuts; Output object for histograms changed to take the HistogramManager master histogram list instead of the manager itself. * removed temporarily the dilepton-hadron analysis task from workflow --- Analysis/Core/include/Analysis/AnalysisCut.h | 50 +++++- Analysis/Core/include/Analysis/VarManager.h | 132 ++++++++++------ Analysis/Core/src/AnalysisCut.cxx | 56 ------- .../include/Analysis/ReducedInfoTables.h | 1 + Analysis/Tasks/PWGDQ/tableMaker.cxx | 149 +++++++++++++----- Analysis/Tasks/PWGDQ/tableReader.cxx | 94 ++++++----- 6 files changed, 293 insertions(+), 189 deletions(-) diff --git a/Analysis/Core/include/Analysis/AnalysisCut.h b/Analysis/Core/include/Analysis/AnalysisCut.h index 2a9bc68822a7b..4aaf6980b0831 100644 --- a/Analysis/Core/include/Analysis/AnalysisCut.h +++ b/Analysis/Core/include/Analysis/AnalysisCut.h @@ -23,9 +23,9 @@ class AnalysisCut : public TNamed { public: - AnalysisCut(); + AnalysisCut() = default; AnalysisCut(const char* name, const char* title); - AnalysisCut(const AnalysisCut& c); + AnalysisCut(const AnalysisCut& c) = default; AnalysisCut& operator=(const AnalysisCut& c); ~AnalysisCut() override; @@ -37,8 +37,6 @@ class AnalysisCut : public TNamed int dependentVar = -1, float depCutLow = 0., float depCutHigh = 0., bool depCutExclude = false, int dependentVar2 = -1, float depCut2Low = 0., float depCut2High = 0., bool depCut2Exclude = false); - // TODO: implement also IsSelected() functions which take as argument the object to be selected - // But this would require to have access to the VarManager for extracting variables virtual bool IsSelected(float* values); static std::vector<int> fgUsedVars; //! vector of used variables @@ -119,4 +117,48 @@ void AnalysisCut::AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude, fCuts.push_back(cut); } +//____________________________________________________________________________ +inline bool AnalysisCut::IsSelected(float* values) +{ + // + // apply the configured cuts + // + // iterate over cuts + for (std::vector<CutContainer>::iterator it = fCuts.begin(); it != fCuts.end(); ++it) { + // check whether a dependent variables were enabled and if they are in the requested range + if ((*it).fDepVar != -1) { + bool inRange = (values[(*it).fDepVar] > (*it).fDepLow && values[(*it).fDepVar] <= (*it).fDepHigh); + if (!inRange && !((*it).fDepExclude)) + continue; + if (inRange && (*it).fDepExclude) + continue; + } + if ((*it).fDepVar2 != -1) { + bool inRange = (values[(*it).fDepVar2] > (*it).fDep2Low && values[(*it).fDepVar2] <= (*it).fDep2High); + if (!inRange && !((*it).fDep2Exclude)) + continue; + if (inRange && (*it).fDep2Exclude) + continue; + } + // obtain the low and high cut values (either directly as a value or from a function) + float cutLow, cutHigh; + if ((*it).fFuncLow) + cutLow = ((*it).fFuncLow)->Eval(values[(*it).fDepVar]); + else + cutLow = ((*it).fLow); + if ((*it).fFuncHigh) + cutHigh = ((*it).fFuncHigh)->Eval(values[(*it).fDepVar]); + else + cutHigh = ((*it).fHigh); + // apply the cut and return the decision + bool inRange = (values[(*it).fVar] >= cutLow && values[(*it).fVar] <= cutHigh); + if (!inRange && !((*it).fExclude)) + return false; + if (inRange && ((*it).fExclude)) + return false; + } + + return true; +} + #endif diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 9e4342e62b98c..e83e3887f5203 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -25,6 +25,9 @@ #include <map> #include <cmath> +#include "Framework/DataTypes.h" +#include "Analysis/TriggerAliases.h" + // TODO: create an array holding these constants for all needed particles or check for a place where these are already defined static const float fgkElectronMass = 0.000511; // GeV static const float fgkMuonMass = 0.105; // GeV @@ -36,18 +39,21 @@ class VarManager : public TObject enum ObjTypes { BC = BIT(0), Collision = BIT(1), - ReducedEvent = BIT(2), - ReducedEventExtended = BIT(3), - ReducedEventVtxCov = BIT(4), + CollisionCent = BIT(2), + ReducedEvent = BIT(3), + ReducedEventExtended = BIT(4), + ReducedEventVtxCov = BIT(5), Track = BIT(0), TrackCov = BIT(1), TrackExtra = BIT(2), - ReducedTrack = BIT(3), - ReducedTrackBarrel = BIT(4), - ReducedTrackBarrelCov = BIT(5), - ReducedTrackBarrelPID = BIT(6), - ReducedTrackMuon = BIT(7), - Pair = BIT(8) + TrackPID = BIT(3), + // TODO: Central model MUON variables to be added + ReducedTrack = BIT(4), + ReducedTrackBarrel = BIT(5), + ReducedTrackBarrelCov = BIT(6), + ReducedTrackBarrelPID = BIT(7), + ReducedTrackMuon = BIT(8), + Pair = BIT(9) }; public: @@ -62,6 +68,12 @@ class VarManager : public TObject kCollisionTime, kBC, kIsPhysicsSelection, + kIsINT7, + kIsEMC7, + kIsINT7inMUON, + kIsMuonSingleLowPt7, + kIsMuonUnlikeLowPt7, + kIsMuonLikeLowPt7, kVtxX, kVtxY, kVtxZ, @@ -91,9 +103,14 @@ class VarManager : public TObject // Barrel track variables kPin, + kIsITSrefit, + kIsSPDany, + kIsSPDfirst, + kIsSPDboth, kITSncls, kITSchi2, kITSlayerHit, + kIsTPCrefit, kTPCncls, kTPCchi2, kTPCsignal, @@ -226,6 +243,18 @@ void VarManager::FillEvent(T const& event, float* values) } if constexpr ((fillMap & Collision) > 0) { + if (fgUsedVars[kIsINT7]) + values[kIsINT7] = (event.alias()[kINT7] > 0); + if (fgUsedVars[kIsEMC7]) + values[kIsEMC7] = (event.alias()[kEMC7] > 0); + if (fgUsedVars[kIsINT7inMUON]) + values[kIsINT7inMUON] = (event.alias()[kINT7inMUON] > 0); + if (fgUsedVars[kIsMuonSingleLowPt7]) + values[kIsMuonSingleLowPt7] = (event.alias()[kMuonSingleLowPt7] > 0); + if (fgUsedVars[kIsMuonUnlikeLowPt7]) + values[kIsMuonUnlikeLowPt7] = (event.alias()[kMuonUnlikeLowPt7] > 0); + if (fgUsedVars[kIsMuonLikeLowPt7]) + values[kIsMuonLikeLowPt7] = (event.alias()[kMuonLikeLowPt7] > 0); values[kVtxX] = event.posX(); values[kVtxY] = event.posY(); values[kVtxZ] = event.posZ(); @@ -240,6 +269,10 @@ void VarManager::FillEvent(T const& event, float* values) values[kVtxChi2] = event.chi2(); } + if constexpr ((fillMap & CollisionCent) > 0) { + values[kCentVZERO] = event.centV0M(); + } + // TODO: need to add EvSels and Cents tables, etc. in case of the central data model if constexpr ((fillMap & ReducedEvent) > 0) { @@ -253,6 +286,18 @@ void VarManager::FillEvent(T const& event, float* values) if constexpr ((fillMap & ReducedEventExtended) > 0) { values[kBC] = event.globalBC(); values[kCentVZERO] = event.centV0M(); + if (fgUsedVars[kIsINT7]) + values[kIsINT7] = event.triggerAlias() & (uint32_t(1) << kINT7); + if (fgUsedVars[kIsEMC7]) + values[kIsEMC7] = event.triggerAlias() & (uint32_t(1) << kEMC7); + if (fgUsedVars[kIsINT7inMUON]) + values[kIsINT7inMUON] = event.triggerAlias() & (uint32_t(1) << kINT7inMUON); + if (fgUsedVars[kIsMuonSingleLowPt7]) + values[kIsMuonSingleLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonSingleLowPt7); + if (fgUsedVars[kIsMuonUnlikeLowPt7]) + values[kIsMuonUnlikeLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonUnlikeLowPt7); + if (fgUsedVars[kIsMuonLikeLowPt7]) + values[kIsMuonLikeLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonLikeLowPt7); } if constexpr ((fillMap & ReducedEventVtxCov) > 0) { @@ -274,34 +319,7 @@ void VarManager::FillTrack(T const& track, float* values) if (!values) values = fgValues; - if constexpr ((fillMap & Track) > 0) { - values[kPt] = track.pt(); - values[kEta] = track.eta(); - values[kPhi] = track.phi(); - values[kCharge] = track.charge(); - } - - if constexpr ((fillMap & TrackExtra) > 0) { - values[kPin] = track.tpcInnerParam(); - if (fgUsedVars[kITSncls]) - values[kITSncls] = track.itsNCls(); // dynamic column - values[kITSchi2] = track.itsChi2NCl(); - values[kTPCncls] = track.tpcNClsFound(); - values[kTPCchi2] = track.tpcChi2NCl(); - values[kTrackLength] = track.length(); - values[kTrackDCAxy] = track.dcaXY(); - values[kTrackDCAz] = track.dcaZ(); - } - - if constexpr ((fillMap & TrackCov) > 0) { - values[kTrackCYY] = track.cYY(); - values[kTrackCZZ] = track.cZZ(); - values[kTrackCSnpSnp] = track.cSnpSnp(); - values[kTrackCTglTgl] = track.cTglTgl(); - values[kTrackC1Pt21Pt2] = track.c1Pt21Pt2(); - } - - if constexpr ((fillMap & ReducedTrack) > 0) { + if constexpr ((fillMap & Track) > 0 || (fillMap & ReducedTrack) > 0) { values[kPt] = track.pt(); if (fgUsedVars[kPx]) values[kPx] = track.px(); @@ -314,22 +332,42 @@ void VarManager::FillTrack(T const& track, float* values) values[kCharge] = track.charge(); } - if constexpr ((fillMap & ReducedTrackBarrel) > 0) { + if constexpr ((fillMap & TrackExtra) > 0 || (fillMap & ReducedTrackBarrel) > 0) { values[kPin] = track.tpcInnerParam(); - if (fgUsedVars[kITSncls]) { // TODO: add the central data model dynamic column to the reduced table - values[kITSncls] = 0.0; - for (int i = 0; i < 6; ++i) - values[kITSncls] += ((track.itsClusterMap() & (1 << i)) ? 1 : 0); - } + if (fgUsedVars[kIsITSrefit]) + values[kIsITSrefit] = track.flags() & (uint64_t(1) << 2); // TODO: the flag mapping needs to be updated + if (fgUsedVars[kIsTPCrefit]) + values[kIsTPCrefit] = track.flags() & (uint64_t(1) << 6); // TODO: the flag mapping needs to be updated + if (fgUsedVars[kIsSPDfirst]) + values[kIsSPDfirst] = track.itsClusterMap() & uint8_t(1); + if (fgUsedVars[kIsSPDboth]) + values[kIsSPDboth] = track.itsClusterMap() & uint8_t(3); + if (fgUsedVars[kIsSPDany]) + values[kIsSPDfirst] = (track.itsClusterMap() & uint8_t(1)) || (track.itsClusterMap() & uint8_t(2)); values[kITSchi2] = track.itsChi2NCl(); values[kTPCncls] = track.tpcNClsFound(); values[kTPCchi2] = track.tpcChi2NCl(); values[kTrackLength] = track.length(); - values[kTrackDCAxy] = track.dcaXY(); - values[kTrackDCAz] = track.dcaZ(); + + if constexpr ((fillMap & TrackExtra) > 0) { + if (fgUsedVars[kITSncls]) + values[kITSncls] = track.itsNCls(); // dynamic column + // TODO: DCA calculation for central data model tracks to be added here + values[kTrackDCAxy] = -9999.; + values[kTrackDCAz] = -9999.; + } + if constexpr ((fillMap & ReducedTrackBarrel) > 0) { + if (fgUsedVars[kITSncls]) { + values[kITSncls] = 0.0; + for (int i = 0; i < 6; ++i) + values[kITSncls] += ((track.itsClusterMap() & (1 << i)) ? 1 : 0); + } + values[kTrackDCAxy] = track.dcaXY(); + values[kTrackDCAz] = track.dcaZ(); + } } - if constexpr ((fillMap & ReducedTrackBarrelCov) > 0) { + if constexpr ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0) { values[kTrackCYY] = track.cYY(); values[kTrackCZZ] = track.cZZ(); values[kTrackCSnpSnp] = track.cSnpSnp(); @@ -337,7 +375,7 @@ void VarManager::FillTrack(T const& track, float* values) values[kTrackC1Pt21Pt2] = track.c1Pt21Pt2(); } - if constexpr ((fillMap & ReducedTrackBarrelPID) > 0) { + if constexpr ((fillMap & TrackPID) > 0 || (fillMap & ReducedTrackBarrelPID) > 0) { values[kTPCnSigmaEl] = track.tpcNSigmaEl(); values[kTPCnSigmaMu] = track.tpcNSigmaMu(); values[kTPCnSigmaPi] = track.tpcNSigmaPi(); diff --git a/Analysis/Core/src/AnalysisCut.cxx b/Analysis/Core/src/AnalysisCut.cxx index 64dc65874cefb..659b9e6c4c7dd 100644 --- a/Analysis/Core/src/AnalysisCut.cxx +++ b/Analysis/Core/src/AnalysisCut.cxx @@ -18,15 +18,6 @@ ClassImp(AnalysisCut); std::vector<int> AnalysisCut::fgUsedVars = {}; -//____________________________________________________________________________ -AnalysisCut::AnalysisCut() : TNamed(), - fCuts() -{ - // - // default constructor - // -} - //____________________________________________________________________________ AnalysisCut::AnalysisCut(const char* name, const char* title) : TNamed(name, title), fCuts() @@ -36,9 +27,6 @@ AnalysisCut::AnalysisCut(const char* name, const char* title) : TNamed(name, tit // } -//____________________________________________________________________________ -AnalysisCut::AnalysisCut(const AnalysisCut& c) = default; - //____________________________________________________________________________ AnalysisCut& AnalysisCut::operator=(const AnalysisCut& c) { @@ -54,47 +42,3 @@ AnalysisCut& AnalysisCut::operator=(const AnalysisCut& c) //____________________________________________________________________________ AnalysisCut::~AnalysisCut() = default; - -//____________________________________________________________________________ -bool AnalysisCut::IsSelected(float* values) -{ - // - // apply the configured cuts - // - // iterate over cuts - for (std::vector<CutContainer>::iterator it = fCuts.begin(); it != fCuts.end(); ++it) { - // check whether a dependent variables were enabled and if they are in the requested range - if ((*it).fDepVar != -1) { - bool inRange = (values[(*it).fDepVar] > (*it).fDepLow && values[(*it).fDepVar] <= (*it).fDepHigh); - if (!inRange && !((*it).fDepExclude)) - continue; - if (inRange && (*it).fDepExclude) - continue; - } - if ((*it).fDepVar2 != -1) { - bool inRange = (values[(*it).fDepVar2] > (*it).fDep2Low && values[(*it).fDepVar2] <= (*it).fDep2High); - if (!inRange && !((*it).fDep2Exclude)) - continue; - if (inRange && (*it).fDep2Exclude) - continue; - } - // obtain the low and high cut values (either directly as a value or from a function) - float cutLow, cutHigh; - if ((*it).fFuncLow) - cutLow = ((*it).fFuncLow)->Eval(values[(*it).fDepVar]); - else - cutLow = ((*it).fLow); - if ((*it).fFuncHigh) - cutHigh = ((*it).fFuncHigh)->Eval(values[(*it).fDepVar]); - else - cutHigh = ((*it).fHigh); - // apply the cut and return the decision - bool inRange = (values[(*it).fVar] >= cutLow && values[(*it).fVar] <= cutHigh); - if (!inRange && !((*it).fExclude)) - return false; - if (inRange && ((*it).fExclude)) - return false; - } - - return true; -} diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 5f8935372bcca..66f047ea2a8bc 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -17,6 +17,7 @@ #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Analysis/Centrality.h" +#include "Analysis/EventSelection.h" #include "PID/PIDResponse.h" #include "MathUtils/Utils.h" #include <cmath> diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index 56a2b7b5aea71..9d9841d89e544 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -21,6 +21,8 @@ #include "Analysis/ReducedInfoTables.h" #include "Analysis/VarManager.h" #include "Analysis/HistogramManager.h" +#include "Analysis/AnalysisCut.h" +#include "Analysis/AnalysisCompositeCut.h" #include "PID/PIDResponse.h" #include <iostream> @@ -32,6 +34,19 @@ using namespace o2::framework; //using namespace o2::framework::expressions; using namespace o2::aod; +using MyEvents = soa::Join<aod::Collisions, aod::EvSels, aod::Cents>; +using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta>; + +// 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 gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent; +constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; + struct TableMaker { Produces<ReducedEvents> event; @@ -44,31 +59,63 @@ struct TableMaker { Produces<ReducedMuons> muonBasic; Produces<ReducedMuonsExtended> muonExtended; - OutputObj<HistogramManager> fHistMan{"output"}; + float* fValues; - // 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::BC | VarManager::ObjTypes::Collision; - constexpr static uint32_t fgTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackCov; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; + + // TODO: Filters should be used to make lowest level selection. The additional more restrictive cuts should be defined via the AnalysisCuts + // TODO: Multiple event selections can be applied and decisions stored in the reducedevent::tag + AnalysisCompositeCut* fEventCut; + // TODO: Multiple track selections can be applied and decisions stored in the reducedtrack::filteringFlags + // Cuts should be defined using Configurables (prepare cut libraries, as discussed in O2 DQ meetings) + AnalysisCompositeCut* fTrackCut; void init(o2::framework::InitContext&) { + fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); - + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); - DefineHistograms("Event;"); // define all histograms + DefineHistograms("Event_BeforeCuts;Event_AfterCuts;TrackBarrel_BeforeCuts;TrackBarrel_AfterCuts"); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + DefineCuts(); + } + + void DefineCuts() + { + fEventCut = new AnalysisCompositeCut(true); + AnalysisCut* eventVarCut = new AnalysisCut(); + eventVarCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + eventVarCut->AddCut(VarManager::kIsINT7, 0.5, 1.5); // require kINT7 + fEventCut->AddCut(eventVarCut); + + fTrackCut = new AnalysisCompositeCut(true); + AnalysisCut* trackVarCut = new AnalysisCut(); + trackVarCut->AddCut(VarManager::kPt, 1.0, 1000.0); + trackVarCut->AddCut(VarManager::kEta, -0.9, 0.9); + trackVarCut->AddCut(VarManager::kTPCsignal, 70.0, 100.0); + //trackVarCut->AddCut(VarManager::kIsITSrefit, 0.5, 1.5); + //trackVarCut->AddCut(VarManager::kIsTPCrefit, 0.5, 1.5); + trackVarCut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + trackVarCut->AddCut(VarManager::kITSchi2, 0.1, 36.0); + trackVarCut->AddCut(VarManager::kTPCncls, 100.0, 161.); + + AnalysisCut* pidCut1 = new AnalysisCut(); + TF1* cutLow1 = new TF1("cutLow1", "pol1", 0., 10.); + cutLow1->SetParameters(130., -40.0); + pidCut1->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + + fTrackCut->AddCut(trackVarCut); + fTrackCut->AddCut(pidCut1); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov /*, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta*/> const& tracksBarrel) + void process(MyEvents::iterator const& collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, MyBarrelTracks const& tracksBarrel) { uint64_t tag = 0; uint32_t triggerAliases = 0; @@ -76,9 +123,14 @@ struct TableMaker { if (collision.alias()[i] > 0) triggerAliases |= (uint32_t(1) << i); - VarManager::ResetValues(); - VarManager::FillEvent<fgEventFillMap>(collision); // extract event information and place it in the fgValues array - fHistMan->FillHistClass("Event", VarManager::fgValues); // automatically fill all the histograms in the class Event + VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); + VarManager::FillEvent<gkEventFillMap>(collision, fValues); // extract event information and place it in the fgValues array + fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event + + if (!fEventCut->IsSelected(fValues)) + return; + + fHistMan->FillHistClass("Event_AfterCuts", fValues); event(tag, collision.bc().runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib()); eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), triggerAliases, collision.centV0M()); @@ -93,11 +145,14 @@ struct TableMaker { float dcaZ = 0.f; for (auto& track : tracksBarrel) { - if (track.pt() < 0.15) - continue; - if (TMath::Abs(track.eta()) > 0.9) + VarManager::FillTrack<gkTrackFillMap>(track, fValues); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + if (!fTrackCut->IsSelected(fValues)) continue; + fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); + // TODO: update the DCA calculation (use the values computed in the trackSelection workflow or use the propagateToDCA function from there) + // TODO: Move the DCA calculation in the VarManager, so the DCA is available for cuts and histograms sinAlpha = sin(track.alpha()); cosAlpha = cos(track.alpha()); globalX = track.x() * cosAlpha - track.y() * sinAlpha; @@ -107,7 +162,7 @@ struct TableMaker { pow((globalY - collision.posY()), 2)); dcaZ = sqrt(pow(track.z() - collision.posZ(), 2)); - trackBasic(collision, track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); + trackBasic(event.lastIndex(), track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), @@ -115,24 +170,25 @@ struct TableMaker { track.length(), dcaXY, dcaZ); trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); trackBarrelPID(track.tpcSignal(), - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - /* track.tpcNSigmaEl(), track.tpcNSigmaMu(), - track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), - track.tofSignal(), track.beta(), - track.tofNSigmaEl(), track.tofNSigmaMu(), - track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), - track.trdSignal());*/ + /*0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);*/ + track.tpcNSigmaEl(), track.tpcNSigmaMu(), + track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), + track.tofSignal(), track.beta(), + track.tofNSigmaEl(), track.tofNSigmaMu(), + track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), + track.trdSignal()); } for (auto& muon : tracksMuon) { // TODO: add proper information for muon tracks if (muon.bc() != collision.bc()) continue; + // TODO: the trackFilteringFlag will not be needed to encode whether the track is a muon since there is a dedicated table for muons trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track - muonBasic(collision, trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); + muonBasic(event.lastIndex(), trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); } } @@ -154,14 +210,27 @@ struct TableMaker { 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 + kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, 60, -15.0, 15.0, VarManager::kVtxZ, 10, 0., 0., VarManager::kNothing, runsStr.Data()); + fHistMan->AddHistogram(classStr.Data(), "CentVZERO", "Centrality VZERO", false, 100, 0.0, 100.0, VarManager::kCentVZERO); // TH1F histogram + } + + 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 + + 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(), "TPCncls_Run", "Number of cluster in TPC", true, kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, + 10, -0.5, 159.5, VarManager::kTPCncls, 10, 0., 1., VarManager::kNothing, runsStr.Data()); // 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(), "DCAxy", "DCAxy", false, 100, -3.0, 3.0, VarManager::kTrackDCAxy); // TH1F histogram + //fHistMan->AddHistogram(classStr.Data(), "DCAz", "DCAz", false, 100, -5.0, 5.0, VarManager::kTrackDCAz); // TH1F histogram + } } } // end loop over histogram classes } diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index 1e566fbc791c7..cd2912812b926 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -69,7 +69,7 @@ DECLARE_SOA_TABLE(EventCuts, "AOD", "EVENTCUTS", reducedevent::IsEventSelected); DECLARE_SOA_TABLE(EventCategories, "AOD", "EVENTCATEGORIES", reducedevent::Category); 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::FilterMap, +DECLARE_SOA_TABLE(Dileptons, "AOD", "DILEPTON", reducedpair::ReducedEventId, reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Charge, reducedpair::FilterMap, reducedpair::Px<reducedpair::Pt, reducedpair::Phi>, reducedpair::Py<reducedpair::Pt, reducedpair::Phi>, reducedpair::Pz<reducedpair::Pt, reducedpair::Eta>, reducedpair::Pmom<reducedpair::Pt, reducedpair::Eta>); using Dilepton = Dileptons::iterator; @@ -84,7 +84,7 @@ using MyBarrelTracksSelected = soa::Join<aod::ReducedTracks, aod::ReducedTracksB using MyMuonTracks = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended>; using MyMuonTracksSelected = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended, aod::MuonTrackCuts>; -void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TString histClasses); +void DefineHistograms(HistogramManager* 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 @@ -93,15 +93,16 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin // 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; +constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; +constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; +constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackMuon; int gNTrackCuts = 2; struct EventSelection { Produces<aod::EventCuts> eventSel; - OutputObj<HistogramManager> fHistMan{"output"}; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; AnalysisCompositeCut* fEventCut; float* fValues; @@ -110,12 +111,13 @@ struct EventSelection { { fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;"); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); DefineCuts(); } @@ -126,6 +128,8 @@ struct EventSelection { AnalysisCut* varCut = new AnalysisCut(); varCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + varCut->AddCut(VarManager::kIsINT7, 0.5, 1.5); + varCut->AddCut(VarManager::kCentVZERO, 0.0, 10.0); fEventCut->AddCut(varCut); // TODO: Add more cuts, also enable cuts which are not easily possible via the VarManager (e.g. trigger selections) @@ -138,7 +142,7 @@ struct EventSelection { // Reset the fValues array VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); - VarManager::FillEvent<fgEventFillMap>(event, fValues); + VarManager::FillEvent<gkEventFillMap>(event, fValues); fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event if (fEventCut->IsSelected(fValues)) { fHistMan->FillHistClass("Event_AfterCuts", fValues); @@ -150,7 +154,8 @@ struct EventSelection { struct BarrelTrackSelection { Produces<aod::BarrelTrackCuts> trackSel; - OutputObj<HistogramManager> fHistMan{"output"}; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; std::vector<AnalysisCompositeCut> fTrackCuts; float* fValues; // array to be used by the VarManager @@ -161,7 +166,7 @@ struct BarrelTrackSelection { fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); @@ -171,6 +176,7 @@ struct BarrelTrackSelection { DefineHistograms(fHistMan, cutNames.Data()); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); } void DefineCuts() @@ -179,6 +185,9 @@ struct BarrelTrackSelection { commonCuts->AddCut(VarManager::kPt, 1.0, 20.0); commonCuts->AddCut(VarManager::kTPCsignal, 70.0, 100.0); commonCuts->AddCut(VarManager::kEta, -0.9, 0.9); + commonCuts->AddCut(VarManager::kIsSPDany, 0.5, 1.5); + commonCuts->AddCut(VarManager::kIsITSrefit, 0.5, 1.5); + commonCuts->AddCut(VarManager::kIsTPCrefit, 0.5, 1.5); commonCuts->AddCut(VarManager::kTPCchi2, 0.0, 4.0); commonCuts->AddCut(VarManager::kITSchi2, 0.1, 36.0); commonCuts->AddCut(VarManager::kTPCncls, 100.0, 161.); @@ -213,26 +222,21 @@ struct BarrelTrackSelection { { VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables, fValues); // fill event information which might be needed in histograms that combine track and event properties - VarManager::FillEvent<fgEventFillMap>(event, fValues); + VarManager::FillEvent<gkEventFillMap>(event, fValues); uint8_t filterMap = uint8_t(0); for (auto& track : tracks) { filterMap = uint8_t(0); - VarManager::FillTrack<fgTrackFillMap>(track, fValues); + VarManager::FillTrack<gkTrackFillMap>(track, fValues); if (event.isEventSelected()) fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); - if ((track.flags() & (uint64_t(1) << 2)) && // kITSrefit - (track.flags() & (uint64_t(1) << 6)) && // kTPCrefit - ((track.itsClusterMap() & (uint8_t(1) << 0)) || (track.itsClusterMap() & (uint8_t(1) << 1)))) //SPD any - { - int i = 0; - for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { - if ((*cut).IsSelected(fValues)) { - filterMap |= (uint8_t(1) << i); - fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut).GetName()), fValues); - } + int i = 0; + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { + if ((*cut).IsSelected(fValues)) { + filterMap |= (uint8_t(1) << i); + fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut).GetName()), fValues); } } trackSel(filterMap); @@ -242,7 +246,8 @@ struct BarrelTrackSelection { struct MuonTrackSelection { Produces<aod::MuonTrackCuts> trackSel; - OutputObj<HistogramManager> fHistMan{"output"}; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; AnalysisCompositeCut* fTrackCut; float* fValues; @@ -251,12 +256,13 @@ struct MuonTrackSelection { { fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan = 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 + fOutputList.setObject(fHistMan->GetMainHistogramList()); DefineCuts(); } @@ -274,11 +280,11 @@ struct MuonTrackSelection { void process(MyEventsSelected::iterator const& event, MyMuonTracks const& muons) { VarManager::ResetValues(0, VarManager::kNMuonTrackVariables, fValues); - VarManager::FillEvent<fgEventFillMap>(event, fValues); + VarManager::FillEvent<gkEventFillMap>(event, fValues); for (auto& muon : muons) { //VarManager::ResetValues(VarManager::kNBarrelTrackVariables, VarManager::kNMuonTrackVariables, fValues); - VarManager::FillTrack<fgMuonFillMap>(muon, fValues); + VarManager::FillTrack<gkMuonFillMap>(muon, fValues); //if(event.isEventSelected()) fHistMan->FillHistClass("TrackMuon_BeforeCuts", fValues); @@ -294,21 +300,22 @@ struct MuonTrackSelection { struct TableReader { Produces<aod::Dileptons> dileptonList; - OutputObj<HistogramManager> fHistMan{"output"}; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition float* fValues; Partition<MyBarrelTracksSelected> posTracks = aod::reducedtrack::charge > 0 && aod::reducedtrack::isBarrelSelected > uint8_t(0); Partition<MyBarrelTracksSelected> negTracks = aod::reducedtrack::charge < 0 && aod::reducedtrack::isBarrelSelected > uint8_t(0); - //Partition<MyMuonTracksSelected> posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; - //Partition<MyMuonTracksSelected> negMuons = aod::reducedtrack::charge < 0 && aod::reducedtrack::isMuonSelected == 1; + Partition<MyMuonTracksSelected> posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; + Partition<MyMuonTracksSelected> negMuons = aod::reducedtrack::charge < 0 && aod::reducedtrack::isMuonSelected == 1; void init(o2::framework::InitContext&) { fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); @@ -318,17 +325,18 @@ struct TableReader { DefineHistograms(fHistMan, histNames.Data()); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); } //void process(soa::Filtered<MyEventsVtxCovSelected>::iterator const& event, MyBarrelTracksSelected const& tracks, MyMuonTracksSelected const& muons) - void process(MyEventsVtxCovSelected::iterator const& event, MyBarrelTracksSelected const& tracks /*, MyMuonTracksSelected const& muons*/) + void process(MyEventsVtxCovSelected::iterator const& event, MyBarrelTracksSelected const& tracks, MyMuonTracksSelected const& muons) { if (!event.isEventSelected()) return; // Reset the fValues array VarManager::ResetValues(0, VarManager::kNVars, fValues); - VarManager::FillEvent<fgEventFillMap>(event, fValues); + VarManager::FillEvent<gkEventFillMap>(event, fValues); // Run the same event pairing for barrel tracks // TODO: Use combinations() when this will work for Partitions @@ -378,13 +386,13 @@ struct TableReader { } // same event pairing for muons - /*for (auto& tpos : posMuons) { + 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, fValues); fHistMan->FillHistClass("PairsMuon", fValues); } - }*/ + } } }; @@ -395,7 +403,8 @@ struct DileptonHadronAnalysis { // or in dilepton + hadron correlations, etc. // It requires the TableReader task to be in the workflow and produce the dilepton table // - OutputObj<HistogramManager> fHistMan{"output"}; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; AnalysisCompositeCut* fHadronCut; // TODO: this cut will be moved into the barrel/muon track selection task //NOTE: no cut has been included for dileptons because that can be controlled via the TableReader task and the partition below @@ -414,12 +423,13 @@ struct DileptonHadronAnalysis { fValuesDilepton = new float[VarManager::kNVars]; fValuesHadron = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan = 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 + VarManager::SetUseVars(fHistMan->GetUsedVars()); + fOutputList.setObject(fHistMan->GetMainHistogramList()); DefineCuts(); } @@ -444,8 +454,8 @@ struct DileptonHadronAnalysis { VarManager::ResetValues(0, VarManager::kNVars, fValuesHadron); VarManager::ResetValues(0, VarManager::kNVars, fValuesDilepton); // fill event information which might be needed in histograms that combine track/pair and event properties - VarManager::FillEvent<fgEventFillMap>(event, fValuesHadron); - VarManager::FillEvent<fgEventFillMap>(event, fValuesDilepton); // TODO: check if needed (just for dilepton QA which might be depending on event wise variables) + VarManager::FillEvent<gkEventFillMap>(event, fValuesHadron); + VarManager::FillEvent<gkEventFillMap>(event, fValuesDilepton); // TODO: check if needed (just for dilepton QA which might be depending on event wise variables) // loop once over dileptons for QA purposes for (auto dilepton : selDileptons) { @@ -455,7 +465,7 @@ struct DileptonHadronAnalysis { // loop over hadrons for (auto& hadron : hadrons) { - VarManager::FillTrack<fgTrackFillMap>(hadron, fValuesHadron); + VarManager::FillTrack<gkTrackFillMap>(hadron, fValuesHadron); if (!fHadronCut->IsSelected(fValuesHadron)) // TODO: this will be moved to a partition when the selection will be done in the barrel/muon track selection continue; @@ -476,13 +486,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) return WorkflowSpec{ adaptAnalysisTask<EventSelection>("my-event-selection"), adaptAnalysisTask<BarrelTrackSelection>("barrel-track-selection"), - //adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), + adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), adaptAnalysisTask<TableReader>("table-reader") //adaptAnalysisTask<DileptonHadronAnalysis>("dilepton-hadron") }; } -void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TString histClasses) +void DefineHistograms(HistogramManager* histMan, TString histClasses) { // // Define here the histograms for all the classes required in analysis. From 20c9a95a2a2acd3bfa966e82b8fae1c69d4f6335 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Fri, 9 Oct 2020 08:47:30 +0200 Subject: [PATCH 0886/1751] Update WorkflowHelpers.cxx (#4538) Allow non-dangling outputs to be saved to file --- Framework/Core/src/WorkflowHelpers.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 9f35f1bd7a7e3..edf90efde5bce 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -384,10 +384,10 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext std::vector<bool> isdangling; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { if ((outputTypes[ii] & 2) == 2) { + outputsInputsAOD.emplace_back(OutputsInputs[ii]); - // temporarily also request to be dangling + // is this dangling if ((outputTypes[ii] & 1) == 1) { - outputsInputsAOD.emplace_back(OutputsInputs[ii]); isdangling.emplace_back((outputTypes[ii] & 1) == 1); } } From a2f9cc7aac807f9ca1e92057be21e2991e968e12 Mon Sep 17 00:00:00 2001 From: anerokhi <44967087+anerokhi@users.noreply.github.com> Date: Fri, 9 Oct 2020 10:42:07 +0300 Subject: [PATCH 0887/1751] Utilities: add braces to single statements (#4530) --- .../include/DataCompression/HuffmanCodec.h | 6 +- Utilities/DataFlow/src/EPNReceiverDevice.cxx | 3 +- Utilities/DataFlow/src/FLPSenderDevice.cxx | 3 +- .../DataFlow/src/FakeTimeframeBuilder.cxx | 23 +++--- .../DataFlow/src/SubframeBuilderDevice.cxx | 3 +- .../DataFlow/src/TimeframeValidationTool.cxx | 5 +- .../DataFlow/src/TimeframeValidatorDevice.cxx | 3 +- .../DataFlow/src/TimeframeWriterDevice.cxx | 3 +- .../O2MessageMonitor/src/O2MessageMonitor.cxx | 3 +- Utilities/PCG/include/PCG/pcg_extras.hpp | 32 +++++--- Utilities/PCG/include/PCG/pcg_random.hpp | 38 +++++---- .../Publishers/src/DataPublisherDevice.cxx | 6 +- .../include/aliceHLTwrapper/AliHLTDataTypes.h | 33 +++++--- .../include/aliceHLTwrapper/AliHLTHOMERData.h | 78 ++++++++++++------- Utilities/aliceHLTwrapper/src/Component.cxx | 39 +++++++--- .../aliceHLTwrapper/src/EventSampler.cxx | 11 ++- .../aliceHLTwrapper/src/HOMERFactory.cxx | 24 ++++-- .../aliceHLTwrapper/src/MessageFormat.cxx | 43 ++++++---- .../aliceHLTwrapper/src/SystemInterface.cxx | 27 ++++--- .../aliceHLTwrapper/src/WrapperDevice.cxx | 15 ++-- .../aliceHLTwrapper/src/runComponent.cxx | 11 ++- .../test/testMessageFormat.cxx | 15 ++-- .../include/rANS/internal/EncoderSymbol.h | 3 +- Utilities/rANS/src/SymbolStatistics.cxx | 5 +- 24 files changed, 288 insertions(+), 144 deletions(-) diff --git a/Utilities/DataCompression/include/DataCompression/HuffmanCodec.h b/Utilities/DataCompression/include/DataCompression/HuffmanCodec.h index 2e07e0b5a31dc..5b6cda6bac249 100644 --- a/Utilities/DataCompression/include/DataCompression/HuffmanCodec.h +++ b/Utilities/DataCompression/include/DataCompression/HuffmanCodec.h @@ -436,8 +436,9 @@ class HuffmanModel : public _BASE } node->getLeftChild()->setBinaryCode(codelen + 1, c); int branchlen = assignCode(node->getLeftChild()); - if (retcodelen < branchlen) + if (retcodelen < branchlen) { retcodelen = branchlen; + } } if (node->getRightChild()) { // bit '0' branch code_type c = node->getBinaryCode(); @@ -449,8 +450,9 @@ class HuffmanModel : public _BASE } node->getRightChild()->setBinaryCode(codelen + 1, c); int branchlen = assignCode(node->getRightChild()); - if (retcodelen < branchlen) + if (retcodelen < branchlen) { retcodelen = branchlen; + } } return retcodelen; } diff --git a/Utilities/DataFlow/src/EPNReceiverDevice.cxx b/Utilities/DataFlow/src/EPNReceiverDevice.cxx index 8c5649680e31d..9424bd58d9f25 100644 --- a/Utilities/DataFlow/src/EPNReceiverDevice.cxx +++ b/Utilities/DataFlow/src/EPNReceiverDevice.cxx @@ -94,8 +94,9 @@ void EPNReceiverDevice::Run() while (compatibility::FairMQ13<FairMQDevice>::IsRunning(this)) { FairMQParts subtimeframeParts; - if (Receive(subtimeframeParts, mInChannelName, 0, 100) <= 0) + if (Receive(subtimeframeParts, mInChannelName, 0, 100) <= 0) { continue; + } assert(subtimeframeParts.Size() >= 2); diff --git a/Utilities/DataFlow/src/FLPSenderDevice.cxx b/Utilities/DataFlow/src/FLPSenderDevice.cxx index 1cecd8ed3d62a..cc37be574bb6d 100644 --- a/Utilities/DataFlow/src/FLPSenderDevice.cxx +++ b/Utilities/DataFlow/src/FLPSenderDevice.cxx @@ -50,8 +50,9 @@ void FLPSenderDevice::Run() // - Add the current FLP id to the SubtimeframeMetadata // - Forward to the EPN the whole subtimeframe FairMQParts subtimeframeParts; - if (Receive(subtimeframeParts, mInChannelName, 0, 100) <= 0) + if (Receive(subtimeframeParts, mInChannelName, 0, 100) <= 0) { continue; + } assert(subtimeframeParts.Size() != 0); assert(subtimeframeParts.Size() >= 2); diff --git a/Utilities/DataFlow/src/FakeTimeframeBuilder.cxx b/Utilities/DataFlow/src/FakeTimeframeBuilder.cxx index 432ea03e95be7..66bcc4fbcea08 100644 --- a/Utilities/DataFlow/src/FakeTimeframeBuilder.cxx +++ b/Utilities/DataFlow/src/FakeTimeframeBuilder.cxx @@ -25,29 +25,34 @@ namespace { o2::header::DataDescription lookupDataDescription(const char* key) { - if (strcmp(key, "RAWDATA") == 0) + if (strcmp(key, "RAWDATA") == 0) { return o2::header::gDataDescriptionRawData; - else if (strcmp(key, "CLUSTERS") == 0) + } else if (strcmp(key, "CLUSTERS") == 0) { return o2::header::gDataDescriptionClusters; - else if (strcmp(key, "TRACKS") == 0) + } else if (strcmp(key, "TRACKS") == 0) { return o2::header::gDataDescriptionTracks; - else if (strcmp(key, "CONFIG") == 0) + } else if (strcmp(key, "CONFIG") == 0) { return o2::header::gDataDescriptionConfig; - else if (strcmp(key, "INFO") == 0) + } else if (strcmp(key, "INFO") == 0) { return o2::header::gDataDescriptionInfo; + } return o2::header::gDataDescriptionInvalid; } o2::header::DataOrigin lookupDataOrigin(const char* key) { - if (strcmp(key, "TPC") == 0) + if (strcmp(key, "TPC") == 0) { return o2::header::gDataOriginTPC; - if (strcmp(key, "TRD") == 0) + } + if (strcmp(key, "TRD") == 0) { return o2::header::gDataOriginTRD; - if (strcmp(key, "TOF") == 0) + } + if (strcmp(key, "TOF") == 0) { return o2::header::gDataOriginTOF; - if (strcmp(key, "ITS") == 0) + } + if (strcmp(key, "ITS") == 0) { return o2::header::gDataOriginITS; + } return o2::header::gDataOriginInvalid; } diff --git a/Utilities/DataFlow/src/SubframeBuilderDevice.cxx b/Utilities/DataFlow/src/SubframeBuilderDevice.cxx index 9047f74a207d4..adad827e04a1f 100644 --- a/Utilities/DataFlow/src/SubframeBuilderDevice.cxx +++ b/Utilities/DataFlow/src/SubframeBuilderDevice.cxx @@ -86,8 +86,9 @@ bool o2::data_flow::SubframeBuilderDevice::BuildAndSendFrame(FairMQParts& inPart size_t outSize = mMerger->finalise(outBuffer, id); // In this case we do not have enough subtimeframes for id, // so we simply return. - if (outSize == 0) + if (outSize == 0) { return true; + } // If we reach here, it means we do have enough subtimeframes. // top level subframe header, the DataHeader is going to be used with diff --git a/Utilities/DataFlow/src/TimeframeValidationTool.cxx b/Utilities/DataFlow/src/TimeframeValidationTool.cxx index 81ff1038ff78a..b3f1168006fc6 100644 --- a/Utilities/DataFlow/src/TimeframeValidationTool.cxx +++ b/Utilities/DataFlow/src/TimeframeValidationTool.cxx @@ -28,12 +28,13 @@ int main(int argc, char** argv) while ((c = getopt(argc, argv, "")) != -1) { switch (c) { case '?': - if (isprint(optopt)) + if (isprint(optopt)) { fprintf(stderr, "Unknown option `-%c'.\n", optopt); - else + } else { fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); + } return 1; default: abort(); diff --git a/Utilities/DataFlow/src/TimeframeValidatorDevice.cxx b/Utilities/DataFlow/src/TimeframeValidatorDevice.cxx index f1468e8e7527e..4f62bc621ef46 100644 --- a/Utilities/DataFlow/src/TimeframeValidatorDevice.cxx +++ b/Utilities/DataFlow/src/TimeframeValidatorDevice.cxx @@ -43,8 +43,9 @@ void o2::data_flow::TimeframeValidatorDevice::Run() { while (compatibility::FairMQ13<FairMQDevice>::IsRunning(this)) { FairMQParts timeframeParts; - if (Receive(timeframeParts, mInChannelName, 0, 100) <= 0) + if (Receive(timeframeParts, mInChannelName, 0, 100) <= 0) { continue; + } if (timeframeParts.Size() < 2) { LOG(ERROR) << "Expecting at least 2 parts\n"; diff --git a/Utilities/DataFlow/src/TimeframeWriterDevice.cxx b/Utilities/DataFlow/src/TimeframeWriterDevice.cxx index 84b41bf2efe11..151ac59424880 100644 --- a/Utilities/DataFlow/src/TimeframeWriterDevice.cxx +++ b/Utilities/DataFlow/src/TimeframeWriterDevice.cxx @@ -70,8 +70,9 @@ void TimeframeWriterDevice::Run() } FairMQParts timeframeParts; - if (Receive(timeframeParts, mInChannelName, 0, 100) <= 0) + if (Receive(timeframeParts, mInChannelName, 0, 100) <= 0) { continue; + } streamTimeframe(mFile, timeframeParts); if ((mFile.tellp() > mMaxFileSize) || (streamedTimeframes++ > mMaxTimeframes)) { diff --git a/Utilities/O2MessageMonitor/src/O2MessageMonitor.cxx b/Utilities/O2MessageMonitor/src/O2MessageMonitor.cxx index 9181b194e35d0..1d2dc6f8dfa0b 100644 --- a/Utilities/O2MessageMonitor/src/O2MessageMonitor.cxx +++ b/Utilities/O2MessageMonitor/src/O2MessageMonitor.cxx @@ -45,8 +45,9 @@ void O2MessageMonitor::InitTask() mIterations = GetConfig()->GetValue<int>("n"); mPayload = GetConfig()->GetValue<std::string>("payload"); std::string tmp = GetConfig()->GetValue<std::string>("name"); - if (!tmp.empty()) + if (!tmp.empty()) { mName = tmp; + } mLimitOutputCharacters = GetConfig()->GetValue<int>("limit"); } diff --git a/Utilities/PCG/include/PCG/pcg_extras.hpp b/Utilities/PCG/include/PCG/pcg_extras.hpp index 9a612a2cbdee2..cb40f933426b1 100644 --- a/Utilities/PCG/include/PCG/pcg_extras.hpp +++ b/Utilities/PCG/include/PCG/pcg_extras.hpp @@ -132,8 +132,9 @@ std::basic_ostream<CharT, Traits>& if (desired_width > 16) { out.width(desired_width - 16); } - if (highpart != 0 || desired_width > 16) + if (highpart != 0 || desired_width > 16) { out << highpart; + } CharT oldfill = '\0'; if (highpart != 0) { out.width(16); @@ -168,8 +169,9 @@ std::basic_istream<CharT, Traits>& { typename std::basic_istream<CharT, Traits>::sentry s(in); - if (!s) + if (!s) { return in; + } constexpr auto BASE = pcg128_t(10ULL); pcg128_t current(0ULL); @@ -177,8 +179,9 @@ std::basic_istream<CharT, Traits>& bool overflow = false; for (;;) { CharT wide_ch = in.get(); - if (!in.good()) + if (!in.good()) { break; + } auto ch = in.narrow(wide_ch, '\0'); if (ch < '0' || ch > '9') { in.unget(); @@ -194,8 +197,9 @@ std::basic_istream<CharT, Traits>& if (did_nothing || overflow) { in.setstate(std::ios::failbit); - if (overflow) + if (overflow) { current = ~pcg128_t(0ULL); + } } value = current; @@ -223,8 +227,9 @@ std::basic_istream<CharT, Traits>& { uint32_t value = 0xdecea5edU; in >> value; - if (!in && value == 0xdecea5edU) + if (!in && value == 0xdecea5edU) { return in; + } if (value > uint8_t(~0)) { in.setstate(std::ios::failbit); value = ~0U; @@ -425,10 +430,11 @@ SrcIter uneven_copy_impl( src_t value = 0; while (dest_first != dest_last) { - if ((count++ % SCALE) == 0) + if ((count++ % SCALE) == 0) { value = *src_first++; // Get more bits - else + } else { value >>= DEST_BITS; // Move down bits + } *dest_first++ = dest_t(value); // Truncates, ignores high bits. } @@ -549,8 +555,9 @@ auto bounded_rand(RngType& rng, typename RngType::result_type upper_bound) rtype threshold = (RngType::max() - RngType::min() + rtype(1) - upper_bound) % upper_bound; for (;;) { rtype r = rng() - RngType::min(); - if (r >= threshold) + if (r >= threshold) { return r % upper_bound; + } } } @@ -599,8 +606,9 @@ class seed_seq_from template <typename Iter> void generate(Iter start, Iter finish) { - for (auto i = start; i != finish; ++i) + for (auto i = start; i != finish; ++i) { *i = result_type(rng_()); + } } constexpr size_t size() const @@ -654,11 +662,13 @@ std::ostream& operator<<(std::ostream& out, printable_typename<T>) int status; char* pretty_name = abi::__cxa_demangle(implementation_typename, nullptr, nullptr, &status); - if (status == 0) + if (status == 0) { out << pretty_name; + } free(static_cast<void*>(pretty_name)); - if (status == 0) + if (status == 0) { return out; + } #endif out << implementation_typename; return out; diff --git a/Utilities/PCG/include/PCG/pcg_random.hpp b/Utilities/PCG/include/PCG/pcg_random.hpp index f98b863c1cffb..467167e9ff361 100644 --- a/Utilities/PCG/include/PCG/pcg_random.hpp +++ b/Utilities/PCG/include/PCG/pcg_random.hpp @@ -419,10 +419,11 @@ class engine : protected output_mixin, public: result_type operator()() { - if (output_previous) + if (output_previous) { return this->output(base_generate0()); - else + } else { return this->output(base_generate()); + } } result_type operator()(result_type upper_bound) @@ -1155,8 +1156,9 @@ struct inside_out : private baseclass { bool crosses_zero = forwards ? dist_to_zero <= delta : (-dist_to_zero) <= delta; - if (!forwards) + if (!forwards) { delta = -delta; + } state = baseclass::advance(state, delta, mult, inc); randval = baseclass::output(state); return crosses_zero; @@ -1212,13 +1214,15 @@ class extended : public baseclass if (may_tick) { bool tick = kdd ? (state & tick_mask) == state_type(0u) : (state >> tick_shift) == state_type(0u); - if (tick) + if (tick) { advance_table(); + } } if (may_tock) { bool tock = state == state_type(0u); - if (tock) + if (tock) { advance_table(); + } } return data_[index]; } @@ -1348,8 +1352,9 @@ template <bitcount_t table_pow2, bitcount_t advance_pow2, void extended<table_pow2, advance_pow2, baseclass, extvalclass, kdd>::datainit( const result_type* data) { - for (size_t i = 0; i < table_size; ++i) + for (size_t i = 0; i < table_size; ++i) { data_[i] = data[i]; + } } template <bitcount_t table_pow2, bitcount_t advance_pow2, @@ -1414,8 +1419,9 @@ std::basic_ostream<CharT, Traits>& << rng.increment() << space << rng.state_; - for (const auto& datum : rng.data_) + for (const auto& datum : rng.data_) { out << space << datum; + } out.flags(orig_flags); out.fill(orig_fill); @@ -1434,15 +1440,17 @@ std::basic_istream<CharT, Traits>& auto& base_rng = static_cast<baseclass&>(new_rng); in >> base_rng; - if (in.fail()) + if (in.fail()) { return in; + } auto orig_flags = in.flags(std::ios_base::dec | std::ios_base::skipws); for (auto& datum : new_rng.data_) { in >> datum; - if (in.fail()) + if (in.fail()) { goto bail; + } } rng = new_rng; @@ -1509,21 +1517,25 @@ void extended<table_pow2, advance_pow2, baseclass, extvalclass, kdd>::advance( state_type adv_mask = baseclass::is_mcg ? tick_mask << 2 : tick_mask; state_type next_advance_distance = this->distance(zero, adv_mask); - if (!forwards) + if (!forwards) { next_advance_distance = (-next_advance_distance) & tick_mask; + } if (next_advance_distance < (distance & tick_mask)) { ++ticks; } - if (ticks) + if (ticks) { advance_table(ticks, forwards); + } } if (forwards) { - if (may_tock && this->distance(zero) <= distance) + if (may_tock && this->distance(zero) <= distance) { advance_table(); + } baseclass::advance(distance); } else { - if (may_tock && -(this->distance(zero)) <= distance) + if (may_tock && -(this->distance(zero)) <= distance) { advance_table(state_type(1U), false); + } baseclass::advance(-distance); } } diff --git a/Utilities/Publishers/src/DataPublisherDevice.cxx b/Utilities/Publishers/src/DataPublisherDevice.cxx index 0e3a6b1e9c727..598ac8c5413e7 100644 --- a/Utilities/Publishers/src/DataPublisherDevice.cxx +++ b/Utilities/Publishers/src/DataPublisherDevice.cxx @@ -126,8 +126,9 @@ bool DataPublisherDevice::HandleO2LogicalBlock(const byte* headerBuffer, // not handled in O2Device::ForEach at the moment // indicate that the block has not been processed by a 'false' if (!dataHeader || - (dataHeader->dataDescription) != o2::header::gDataDescriptionHeartbeatFrame) + (dataHeader->dataDescription) != o2::header::gDataDescriptionHeartbeatFrame) { return false; + } if (!hbfEnvelope) { LOG(ERROR) << "no heartbeat frame envelope header found"; @@ -190,8 +191,9 @@ bool DataPublisherDevice::AppendFile(const char* name, std::vector<o2::byte>& bu { bool result = true; std::ifstream ifile(name, std::ifstream::binary); - if (ifile.bad()) + if (ifile.bad()) { return false; + } // get length of file: ifile.seekg(0, ifile.end); diff --git a/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTDataTypes.h b/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTDataTypes.h index f9bf1ce387c22..f618d117c388c 100644 --- a/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTDataTypes.h +++ b/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTDataTypes.h @@ -1579,12 +1579,16 @@ namespace std */ inline bool MatchExactly(const AliHLTComponentDataType& dt1, const AliHLTComponentDataType& dt2) { - for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++) - if (dt1.fID[i] != dt2.fID[i]) + for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++) { + if (dt1.fID[i] != dt2.fID[i]) { return false; - for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++) - if (dt1.fOrigin[i] != dt2.fOrigin[i]) + } + } + for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++) { + if (dt1.fOrigin[i] != dt2.fOrigin[i]) { return false; + } + } return true; } @@ -1595,10 +1599,12 @@ inline bool MatchExactly(const AliHLTComponentDataType& dt1, const AliHLTCompone */ inline bool operator==(const AliHLTComponentDataType& dt1, const AliHLTComponentDataType& dt2) { - if (MatchExactly(dt1, kAliHLTAllDataTypes)) + if (MatchExactly(dt1, kAliHLTAllDataTypes)) { return true; - if (MatchExactly(dt2, kAliHLTAllDataTypes)) + } + if (MatchExactly(dt2, kAliHLTAllDataTypes)) { return true; + } bool any1 = true, any2 = true, void1 = true, void2 = true, match = true; for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++) { @@ -1607,8 +1613,9 @@ inline bool operator==(const AliHLTComponentDataType& dt1, const AliHLTComponent void1 &= (dt1.fOrigin[i] == kAliHLTDataOriginVoid[i]); void2 &= (dt2.fOrigin[i] == kAliHLTDataOriginVoid[i]); match &= dt1.fOrigin[i] == dt2.fOrigin[i]; - if (!(match || (any2 && !void1) || (any1 && !void2))) + if (!(match || (any2 && !void1) || (any1 && !void2))) { return false; + } } any1 = true, any2 = true, match = true; @@ -1618,8 +1625,9 @@ inline bool operator==(const AliHLTComponentDataType& dt1, const AliHLTComponent void1 &= (dt1.fID[i] == kAliHLTVoidDataTypeID[i]); void2 &= (dt2.fID[i] == kAliHLTVoidDataTypeID[i]); match &= dt1.fID[i] == dt2.fID[i]; - if (!(match || (any2 && !void1) || (any1 && !void2))) + if (!(match || (any2 && !void1) || (any1 && !void2))) { return false; + } } return true; } @@ -1639,8 +1647,9 @@ inline bool operator!=(const AliHLTComponentDataType& dt1, const AliHLTComponent inline AliHLTComponentDataType operator|(const AliHLTComponentDataType srcdt, const char origin[kAliHLTComponentDataTypefOriginSize]) { AliHLTComponentDataType dt = srcdt; - for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++) + for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++) { dt.fOrigin[i] = origin[i]; + } return dt; } @@ -1653,10 +1662,12 @@ inline AliHLTComponentDataType AliHLTComponentDataTypeInitializer(const char id[ { AliHLTComponentDataType dt = kAliHLTVoidDataType; int i = 0; - for (i = 0; i < kAliHLTComponentDataTypefIDsize && id[i] != 0; i++) + for (i = 0; i < kAliHLTComponentDataTypefIDsize && id[i] != 0; i++) { dt.fID[i] = id[i]; - for (i = 0; i < kAliHLTComponentDataTypefOriginSize && origin[i] != 0; i++) + } + for (i = 0; i < kAliHLTComponentDataTypefOriginSize && origin[i] != 0; i++) { dt.fOrigin[i] = origin[i]; + } return dt; } diff --git a/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTHOMERData.h b/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTHOMERData.h index 8d408e5c4e2eb..59c0ab41f93e3 100644 --- a/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTHOMERData.h +++ b/Utilities/aliceHLTwrapper/include/aliceHLTwrapper/AliHLTHOMERData.h @@ -220,8 +220,9 @@ class AliHLTHOMERBlockDescriptor void Initialize() { if (fHeader) { - for (unsigned ii = 0; ii < kCount_64b_Words; ii++) + for (unsigned ii = 0; ii < kCount_64b_Words; ii++) { ((homer_uint64*)fHeader)[ii] = (homer_uint64)0; + } ((homer_uint64*)fHeader)[kID_64b_Offset] = HOMER_BLOCK_DESCRIPTOR_TYPEID; ((homer_uint64*)fHeader)[kLength_64b_Offset] = GetHOMERBlockDescriptorSize(); ((homer_uint8*)fHeader)[kByteOrderAttribute_8b_Offset] = kHOMERNativeByteOrder; @@ -231,132 +232,157 @@ class AliHLTHOMERBlockDescriptor void SetByteOrder(homer_uint8 bo) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kByteOrderAttribute_8b_Offset] = bo; + } } homer_uint8 GetByteOrder() const { - if (fHeader) + if (fHeader) { return ((homer_uint8*)fHeader)[kByteOrderAttribute_8b_Offset]; + } return 0xFF; } void SetVersion(homer_uint8 v) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kVersionAttribute_8b_Offset] = v; + } } void SetID(homer_uint64 id) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kID_64b_Offset] = id; + } } void SetHeaderLength(homer_uint64 l) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kLength_64b_Offset] = l; + } } homer_uint64 GetHeaderLength() const { - if (fHeader) + if (fHeader) { return ((homer_uint64*)fHeader)[kLength_64b_Offset]; + } return 0; } void SetAlignment(homer_uint8 type, homer_uint8 align) const { - if (fHeader && type < 6) + if (fHeader && type < 6) { ((homer_uint8*)fHeader)[kAlignment_8b_StartOffset + type] = align; + } } void SetUInt64Alignment(homer_uint8 align) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kUInt64Alignment_8b_Offset] = align; + } } void SetUInt32Alignment(homer_uint8 align) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kUInt32Alignment_8b_Offset] = align; + } } void SetUInt16Alignment(homer_uint8 align) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kUInt16Alignment_8b_Offset] = align; + } } void SetUInt8Alignment(homer_uint8 align) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kUInt8Alignment_8b_Offset] = align; + } } void SetDoubleAlignment(homer_uint8 align) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kDoubleAlignment_8b_Offset] = align; + } } void SetFloatAlignment(homer_uint8 align) const { - if (fHeader) + if (fHeader) { ((homer_uint8*)fHeader)[kFloatAlignment_8b_Offset] = align; + } } void SetType(homer_uint64 t) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kType_64b_Offset] = t; + } } void SetSubType1(homer_uint64 st1) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kSubType1_64b_Offset] = st1; + } } void SetSubType2(homer_uint64 st2) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kSubType2_64b_Offset] = st2; + } } void SetBirth_s(homer_uint64 bs) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kBirth_s_64b_Offset] = bs; + } } void SetBirth_us(homer_uint64 bus) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kBirth_us_64b_Offset] = bus; + } } void SetProducerNode(homer_uint64 pn) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kProducerNode_64b_Offset] = pn; + } } void SetBlockOffset(homer_uint64 bo) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kOffset_64b_Offset] = bo; + } } homer_uint64 GetBlockOffset() const { - if (fHeader) + if (fHeader) { return ((homer_uint64*)fHeader)[kOffset_64b_Offset]; + } return 0; } void SetBlockSize(homer_uint64 bs) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kSize_64b_Offset] = bs; + } } homer_uint64 GetBlockSize() const { - if (fHeader) + if (fHeader) { return ((homer_uint64*)fHeader)[kSize_64b_Offset]; + } return 0; } void SetStatusFlags(homer_uint64 bs) const { - if (fHeader) + if (fHeader) { ((homer_uint64*)fHeader)[kStatusFlags_64b_Offset] = bs; + } } homer_uint64 GetStatusFlags() const { - if (fHeader) + if (fHeader) { return ((homer_uint64*)fHeader)[kStatusFlags_64b_Offset]; + } return 0; } diff --git a/Utilities/aliceHLTwrapper/src/Component.cxx b/Utilities/aliceHLTwrapper/src/Component.cxx index 41b8a6eaaf9b8..115faa1b3f765 100644 --- a/Utilities/aliceHLTwrapper/src/Component.cxx +++ b/Utilities/aliceHLTwrapper/src/Component.cxx @@ -120,7 +120,9 @@ int Component::init(int argc, char** argv) bpo::store(bpo::parse_command_line(argc, argv, od), varmap); for (int option = 0; option < OptionKeyLast; ++option) { - if (varmap.count(OptionKeys[option]) == 0) continue; + if (varmap.count(OptionKeys[option]) == 0) { + continue; + } switch (option) { case OptionKeyLibrary: break; case OptionKeyComponent: break; @@ -186,8 +188,9 @@ int Component::init(int argc, char** argv) mpSystem = iface.release(); // load the component library - if ((iResult = mpSystem->loadLibrary(varmap[OptionKeys[OptionKeyLibrary]].as<string>().c_str())) != 0) + if ((iResult = mpSystem->loadLibrary(varmap[OptionKeys[OptionKeyLibrary]].as<string>().c_str())) != 0) { return iResult > 0 ? -iResult : iResult; + } // chop the parameter string in order to provide parameters in the argc/argv format vector<const char*> parameters; @@ -198,9 +201,13 @@ int Component::init(int argc, char** argv) char* iterator = parameterBuffer.get(); parameters.emplace_back(iterator); for (; *iterator != 0; iterator++) { - if (*iterator != ' ') continue; + if (*iterator != ' ') { + continue; + } *iterator = 0; // separate strings - if (*(iterator + 1) != ' ' && *(iterator + 1) != 0) parameters.emplace_back(iterator + 1); + if (*(iterator + 1) != ' ' && *(iterator + 1) != 0) { + parameters.emplace_back(iterator + 1); + } } } @@ -222,7 +229,9 @@ int Component::init(int argc, char** argv) int Component::process(vector<MessageFormat::BufferDesc_t>& dataArray, cballoc_signal_t* cbAllocate) { - if (!mpSystem) return -ENOSYS; + if (!mpSystem) { + return -ENOSYS; + } int iResult = 0; unsigned outputBufferSize = 0; @@ -294,9 +303,13 @@ int Component::process(vector<MessageFormat::BufferDesc_t>& dataArray, outputBlockCnt = 0; // TODO: check if that is working with the corresponding allocation method of the // component environment - if (pOutputBlocks) delete[] pOutputBlocks; + if (pOutputBlocks) { + delete[] pOutputBlocks; + } pOutputBlocks = nullptr; - if (pEventDoneData) delete pEventDoneData; + if (pEventDoneData) { + delete pEventDoneData; + } pEventDoneData = nullptr; iResult = mpSystem->processEvent(mProcessor, &evtData, &inputBlocks[0], &trigData, @@ -336,7 +349,9 @@ int Component::process(vector<MessageFormat::BufferDesc_t>& dataArray, AliHLTComponentBlockData* pFiltered = pOutputBlocks; for (unsigned blockIndex = 0; blockIndex < outputBlockCnt; blockIndex++, pOutputBlock++) { // filter special data blocks - if (pOutputBlock->fDataType == kDataTypeEvent) continue; + if (pOutputBlock->fDataType == kDataTypeEvent) { + continue; + } // block descriptors without any attached payload are propagated bool bValid = pOutputBlock->fSize == 0; @@ -387,9 +402,13 @@ int Component::process(vector<MessageFormat::BufferDesc_t>& dataArray, // until released. inputBlocks.clear(); outputBlockCnt = 0; - if (pOutputBlocks) delete[] pOutputBlocks; + if (pOutputBlocks) { + delete[] pOutputBlocks; + } pOutputBlocks = nullptr; - if (pEventDoneData) delete pEventDoneData; + if (pEventDoneData) { + delete pEventDoneData; + } pEventDoneData = nullptr; return -iResult; diff --git a/Utilities/aliceHLTwrapper/src/EventSampler.cxx b/Utilities/aliceHLTwrapper/src/EventSampler.cxx index 1bc9d827468c1..46a4b7f601a79 100644 --- a/Utilities/aliceHLTwrapper/src/EventSampler.cxx +++ b/Utilities/aliceHLTwrapper/src/EventSampler.cxx @@ -216,7 +216,9 @@ void EventSampler::samplerLoop() unsigned initialDelayInSeconds=mInitialDelay/1000; unsigned initialDelayInUSeconds=mInitialDelay%1000; unsigned eventPeriodInSeconds=mEventPeriod/1000000; - if (initialDelayInSeconds>0) sleep(initialDelayInSeconds); + if (initialDelayInSeconds > 0) { + sleep(initialDelayInSeconds); + } usleep(initialDelayInUSeconds); unique_ptr<FairMQMessage> msg(fTransportFactory->CreateMessage()); @@ -253,7 +255,10 @@ void EventSampler::samplerLoop() } mNEvents++; - if (eventPeriodInSeconds>0) sleep(eventPeriodInSeconds); - else usleep(mEventPeriod); + if (eventPeriodInSeconds > 0) { + sleep(eventPeriodInSeconds); + } else { + usleep(mEventPeriod); + } } } diff --git a/Utilities/aliceHLTwrapper/src/HOMERFactory.cxx b/Utilities/aliceHLTwrapper/src/HOMERFactory.cxx index 9b75e367754af..f9c70a1da1ad6 100644 --- a/Utilities/aliceHLTwrapper/src/HOMERFactory.cxx +++ b/Utilities/aliceHLTwrapper/src/HOMERFactory.cxx @@ -88,8 +88,9 @@ HOMERFactory::~HOMERFactory() = default; AliHLTHOMERReader* HOMERFactory::OpenReader(const char* hostname, unsigned short port) { // Open Reader instance for host - if (sLibraryStatus < 0) + if (sLibraryStatus < 0) { return nullptr; + } sLibraryStatus = LoadHOMERLibrary(); if (sLibraryStatus <= 0) { @@ -107,8 +108,9 @@ AliHLTHOMERReader* HOMERFactory::OpenReader(const char* hostname, unsigned short AliHLTHOMERReader* HOMERFactory::OpenReader(unsigned int tcpCnt, const char** hostnames, unsigned short* ports) { // Open Reader instance for a list of hosts - if (sLibraryStatus < 0) + if (sLibraryStatus < 0) { return nullptr; + } sLibraryStatus = LoadHOMERLibrary(); if (sLibraryStatus <= 0) { @@ -127,8 +129,9 @@ AliHLTHOMERReader* HOMERFactory::OpenReader(unsigned int tcpCnt, const char** ho AliHLTHOMERReader* HOMERFactory::OpenReaderBuffer(const AliHLTUInt8_t* pBuffer, int size) { // Open Reader instance for a data buffer - if (sLibraryStatus < 0) + if (sLibraryStatus < 0) { return nullptr; + } sLibraryStatus = LoadHOMERLibrary(); if (sLibraryStatus <= 0) { @@ -148,8 +151,9 @@ int HOMERFactory::DeleteReader(AliHLTHOMERReader* pReader) // delete a reader // the actual deletion function is inside the HOMER library - if (sLibraryStatus < 0) + if (sLibraryStatus < 0) { return sLibraryStatus; + } sLibraryStatus = LoadHOMERLibrary(); if (sLibraryStatus <= 0) { @@ -166,8 +170,9 @@ int HOMERFactory::DeleteReader(AliHLTHOMERReader* pReader) AliHLTHOMERWriter* HOMERFactory::OpenWriter() { // open a Writer instance - if (sLibraryStatus < 0) + if (sLibraryStatus < 0) { return nullptr; + } sLibraryStatus = LoadHOMERLibrary(); if (sLibraryStatus <= 0) { @@ -185,8 +190,9 @@ AliHLTHOMERWriter* HOMERFactory::OpenWriter() int HOMERFactory::DeleteWriter(AliHLTHOMERWriter* pWriter) { // see header file for class documentation - if (sLibraryStatus < 0) + if (sLibraryStatus < 0) { return sLibraryStatus; + } sLibraryStatus = LoadHOMERLibrary(); if (sLibraryStatus <= 0) { @@ -262,15 +268,17 @@ int HOMERFactory::UnloadHOMERLibrary() const char** library = &sLibraries[0]; int* refcount = &sLibRefCount[0]; while (*library != nullptr) { - if (strcmp(*library, mLoadedLib) == 0) + if (strcmp(*library, mLoadedLib) == 0) { break; + } ++library; ++refcount; } // Decrease the reference count and remove the library if it is zero. - if (*refcount >= 0) + if (*refcount >= 0) { --(*refcount); + } if (*refcount == 0) { /* Matthias 2014-05-08 that part of the code has been disabled for the ROOT-independent version. TODO: dlopen is maintaining an internal reference count, which also makes the diff --git a/Utilities/aliceHLTwrapper/src/MessageFormat.cxx b/Utilities/aliceHLTwrapper/src/MessageFormat.cxx index ca6ef9c62589f..6d383f068ae9f 100644 --- a/Utilities/aliceHLTwrapper/src/MessageFormat.cxx +++ b/Utilities/aliceHLTwrapper/src/MessageFormat.cxx @@ -58,8 +58,9 @@ MessageFormat::MessageFormat() MessageFormat::~MessageFormat() { - if (mpFactory) + if (mpFactory) { delete mpFactory; + } mpFactory = nullptr; } @@ -144,9 +145,9 @@ int MessageFormat::addMessages(const std::vector<BufferDesc_t>& list) if (data.mSize > 0) { unsigned nofEventHeaders = mListEvtData.size(); int result = addMessage(data.mP, data.mSize); - if (result >= 0) + if (result >= 0) { totalCount += result; - else { + } else { cerr << "warning: no valid data blocks in message " << i << endl; } } else { @@ -161,8 +162,9 @@ int MessageFormat::readBlockSequence(uint8_t* buffer, unsigned size, { // read a sequence of blocks consisting of AliHLTComponentBlockData followed by payload // from a buffer - if (buffer == nullptr) + if (buffer == nullptr) { return 0; + } unsigned position = 0; std::vector<BlockDescriptor> input; while (position + sizeof(AliHLTComponentBlockData) < size) { @@ -197,13 +199,16 @@ int MessageFormat::readHOMERFormat(uint8_t* buffer, unsigned size, std::vector<BlockDescriptor>& descriptorList) const { // read message payload in HOMER format - if (mpFactory == nullptr) + if (mpFactory == nullptr) { const_cast<MessageFormat*>(this)->mpFactory = new o2::alice_hlt::HOMERFactory; - if (buffer == nullptr || mpFactory == nullptr) + } + if (buffer == nullptr || mpFactory == nullptr) { return -EINVAL; + } unique_ptr<AliHLTHOMERReader> reader(mpFactory->OpenReaderBuffer(buffer, size)); - if (reader.get() == nullptr) + if (reader.get() == nullptr) { return -ENOMEM; + } unsigned nofBlocks = 0; if (reader->ReadNextEvent() == 0) { @@ -377,14 +382,16 @@ std::vector<MessageFormat::BufferDesc_t> MessageFormat::createMessages(const Ali pTarget = MakeTarget(msgSize, position, cbAllocate); memcpy(pTarget, headerMessage.data(), msgSize); mMessages.emplace_back(pTarget, msgSize); - if (cbAllocate == nullptr) + if (cbAllocate == nullptr) { position += msgSize; + } msgSize = dh.payloadSize; pTarget = MakeTarget(msgSize, position, cbAllocate); memcpy(pTarget, &hbfPayload, msgSize); mMessages.emplace_back(pTarget, msgSize); - if (cbAllocate == nullptr) + if (cbAllocate == nullptr) { position += msgSize; + } } unsigned msgSize = 0; do { @@ -442,8 +449,9 @@ std::vector<MessageFormat::BufferDesc_t> MessageFormat::createMessages(const Ali if (mOutputMode == kOutputModeMultiPart) { // send one descriptor per block back to device mMessages.emplace_back(pTarget, offset); - if (cbAllocate == nullptr) + if (cbAllocate == nullptr) { position += offset; + } offset = 0; } else if (mOutputMode == kOutputModeO2) { o2::header::DataHeader dh; @@ -454,8 +462,9 @@ std::vector<MessageFormat::BufferDesc_t> MessageFormat::createMessages(const Ali memcpy(pTarget, &dh, sizeof(o2::header::DataHeader)); offset += sizeof(o2::header::DataHeader); mMessages.emplace_back(pTarget, offset); - if (cbAllocate == nullptr) + if (cbAllocate == nullptr) { position += offset; + } offset = 0; if (mHeartbeatHeader.headerWord == 0) { // no heartbeat information availalbe, send the buffer @@ -472,8 +481,9 @@ std::vector<MessageFormat::BufferDesc_t> MessageFormat::createMessages(const Ali memcpy(pTarget + offset, &mHeartbeatTrailer, sizeof(mHeartbeatTrailer)); offset += sizeof(mHeartbeatTrailer); mMessages.emplace_back(pTarget, offset); - if (cbAllocate == nullptr) + if (cbAllocate == nullptr) { position += offset; + } offset = 0; } } @@ -518,13 +528,16 @@ AliHLTHOMERWriter* MessageFormat::createHOMERFormat(const AliHLTComponentBlockDa { // send data blocks in HOMER format in one message int iResult = 0; - if (mpFactory == nullptr) + if (mpFactory == nullptr) { const_cast<MessageFormat*>(this)->mpFactory = new o2::alice_hlt::HOMERFactory; - if (!mpFactory) + } + if (!mpFactory) { return nullptr; + } unique_ptr<AliHLTHOMERWriter> writer(mpFactory->OpenWriter()); - if (writer.get() == nullptr) + if (writer.get() == nullptr) { return nullptr; + } homer_uint64 homerHeader[kCount_64b_Words]; HOMERBlockDescriptor homerDescriptor(homerHeader); diff --git a/Utilities/aliceHLTwrapper/src/SystemInterface.cxx b/Utilities/aliceHLTwrapper/src/SystemInterface.cxx index da2a99e531f58..4026f55be909d 100644 --- a/Utilities/aliceHLTwrapper/src/SystemInterface.cxx +++ b/Utilities/aliceHLTwrapper/src/SystemInterface.cxx @@ -169,23 +169,26 @@ int SystemInterface::releaseSystem() bookkeeping of loaded libraries and unloading them before releasing the system? */ int iResult = 0; - if (mpAliHLTExtFctDeinitSystem) + if (mpAliHLTExtFctDeinitSystem) { iResult = (*mpAliHLTExtFctDeinitSystem)(); + } clear(); return iResult; } int SystemInterface::loadLibrary(const char* libname) { - if (!mpAliHLTExtFctLoadLibrary) + if (!mpAliHLTExtFctLoadLibrary) { return -ENOSYS; + } return (*mpAliHLTExtFctLoadLibrary)(libname); } int SystemInterface::unloadLibrary(const char* libname) { - if (!mpAliHLTExtFctUnloadLibrary) + if (!mpAliHLTExtFctUnloadLibrary) { return -ENOSYS; + } return (*mpAliHLTExtFctUnloadLibrary)(libname); } @@ -196,15 +199,17 @@ int SystemInterface::createComponent(const char* componentId, AliHLTComponentHandle* handle, const char* description) { - if (!mpAliHLTExtFctCreateComponent) + if (!mpAliHLTExtFctCreateComponent) { return -ENOSYS; + } return (*mpAliHLTExtFctCreateComponent)(componentId, environParam, argc, argv, handle, description); } int SystemInterface::destroyComponent(AliHLTComponentHandle handle) { - if (!mpAliHLTExtFctDestroyComponent) + if (!mpAliHLTExtFctDestroyComponent) { return -ENOSYS; + } return (*mpAliHLTExtFctDestroyComponent)(handle); } @@ -215,24 +220,27 @@ int SystemInterface::processEvent(AliHLTComponentHandle handle, AliHLTUInt32_t* outputBlockCnt, AliHLTComponentBlockData** outputBlocks, AliHLTComponentEventDoneData** edd) { - if (!mpAliHLTExtFctProcessEvent) + if (!mpAliHLTExtFctProcessEvent) { return -ENOSYS; + } return (*mpAliHLTExtFctProcessEvent)(handle, evtData, blocks, trigData, outputPtr, size, outputBlockCnt, outputBlocks, edd); } int SystemInterface::getOutputDataType(AliHLTComponentHandle handle, AliHLTComponentDataType* dataType) { - if (!mpAliHLTExtFctGetOutputDataType) + if (!mpAliHLTExtFctGetOutputDataType) { return -ENOSYS; + } return (*mpAliHLTExtFctGetOutputDataType)(handle, dataType); } int SystemInterface::getOutputSize(AliHLTComponentHandle handle, unsigned long* constEventBase, unsigned long* constBlockBase, double* inputBlockMultiplier) { - if (!mpAliHLTExtFctGetOutputSize) + if (!mpAliHLTExtFctGetOutputSize) { return -ENOSYS; + } return (*mpAliHLTExtFctGetOutputSize)(handle, constEventBase, constEventBase, inputBlockMultiplier); } @@ -264,7 +272,8 @@ void* SystemInterface::alloc(void* /*param*/, unsigned long size) void SystemInterface::dealloc(void* buffer, unsigned long /*size*/) { // deallocate memory - if (buffer == nullptr) + if (buffer == nullptr) { return; + } free(buffer); } diff --git a/Utilities/aliceHLTwrapper/src/WrapperDevice.cxx b/Utilities/aliceHLTwrapper/src/WrapperDevice.cxx index 6ad1f5155bee5..7ba026f7ba714 100644 --- a/Utilities/aliceHLTwrapper/src/WrapperDevice.cxx +++ b/Utilities/aliceHLTwrapper/src/WrapperDevice.cxx @@ -80,8 +80,9 @@ void WrapperDevice::InitTask() int iResult = 0; std::unique_ptr<Component> component(new o2::alice_hlt::Component); - if (!component.get()) + if (!component.get()) { return /*-ENOMEM*/; + } // loop over program options, check if the option was used and // add it together with the parameter to the argument vector. @@ -192,15 +193,17 @@ void WrapperDevice::Run() } } } - if (receivedAtLeastOneMessage) + if (receivedAtLeastOneMessage) { nReadCycles++; + } if (inputsReceived < numInputs) { continue; } mNSamples++; mTotalReadCycles += nReadCycles; - if (mMaxReadCycles < 0 || mMaxReadCycles < nReadCycles) + if (mMaxReadCycles < 0 || mMaxReadCycles < nReadCycles) { mMaxReadCycles = nReadCycles; + } // if (nReadCycles>1) { // LOG(INFO) << "------ recieved complete Msg from " << numInputs << " input(s) after " << nReadCycles << " read cycles" ; // } @@ -210,10 +213,12 @@ void WrapperDevice::Run() if (mLastSampleTime >= 0) { int sampleTimeDiff = duration.count() - mLastSampleTime; - if (mMinTimeBetweenSample < 0 || sampleTimeDiff < mMinTimeBetweenSample) + if (mMinTimeBetweenSample < 0 || sampleTimeDiff < mMinTimeBetweenSample) { mMinTimeBetweenSample = sampleTimeDiff; - if (mMaxTimeBetweenSample < 0 || sampleTimeDiff > mMaxTimeBetweenSample) + } + if (mMaxTimeBetweenSample < 0 || sampleTimeDiff > mMaxTimeBetweenSample) { mMaxTimeBetweenSample = sampleTimeDiff; + } } mLastSampleTime = duration.count(); if (duration.count() - mLastCalcTime > 1000) { diff --git a/Utilities/aliceHLTwrapper/src/runComponent.cxx b/Utilities/aliceHLTwrapper/src/runComponent.cxx index 4ed7636cab512..17d07cc37d61f 100644 --- a/Utilities/aliceHLTwrapper/src/runComponent.cxx +++ b/Utilities/aliceHLTwrapper/src/runComponent.cxx @@ -59,10 +59,11 @@ int main(int argc, char** argv) if (arg[1] == 'i' || arg[1] == 'o') { if (i + 1 >= argc) { cerr << "missing file name for option " << arg << endl; - } else if (arg[1] == 'i') + } else if (arg[1] == 'i') { inputFileName = argv[i + 1]; - else + } else { outputFileName = argv[i + 1]; + } break; } } @@ -101,11 +102,13 @@ int main(int argc, char** argv) if ((iResult = component.process(blockData)) < 0) { cerr << "error: init failed with " << iResult << endl; } - if (inputBuffer) + if (inputBuffer) { delete[] inputBuffer; + } inputBuffer = nullptr; - if (iResult < 0) + if (iResult < 0) { return -iResult; + } // for now, only the first buffer is written if (blockData.size() > 0) { diff --git a/Utilities/aliceHLTwrapper/test/testMessageFormat.cxx b/Utilities/aliceHLTwrapper/test/testMessageFormat.cxx index b28091e839e35..83681cbc2d117 100644 --- a/Utilities/aliceHLTwrapper/test/testMessageFormat.cxx +++ b/Utilities/aliceHLTwrapper/test/testMessageFormat.cxx @@ -50,8 +50,9 @@ BOOST_AUTO_TEST_CASE(test_createMessagesModeMultiPart) for (auto& desc : dataDescriptors) { totalPayloadSize += desc.fSize; hexDump("HLT data descriptor", &desc, sizeof(desc)); - if (!desc.fPtr) + if (!desc.fPtr) { continue; + } hexDump(" data payload", (char*)desc.fPtr + desc.fOffset, desc.fSize); } @@ -100,8 +101,9 @@ BOOST_AUTO_TEST_CASE(test_createMessagesModeSequence) for (auto& desc : dataDescriptors) { totalPayloadSize += desc.fSize; hexDump("HLT data descriptor", &desc, sizeof(desc)); - if (!desc.fPtr) + if (!desc.fPtr) { continue; + } hexDump(" data payload", (char*)desc.fPtr + desc.fOffset, desc.fSize); } @@ -142,8 +144,9 @@ BOOST_AUTO_TEST_CASE(test_createMessagesModeO2) for (auto& desc : dataDescriptors) { totalPayloadSize += desc.fSize; hexDump("HLT data descriptor", &desc, sizeof(desc)); - if (!desc.fPtr) + if (!desc.fPtr) { continue; + } hexDump(" data payload", (char*)desc.fPtr + desc.fOffset, desc.fSize); } @@ -173,8 +176,9 @@ BOOST_AUTO_TEST_CASE(test_createMessagesModeO2) dataidx = 0; for (auto& desc : descriptors) { hexDump("Readback: HLT data descriptor", &desc, sizeof(desc)); - if (!desc.fPtr) + if (!desc.fPtr) { continue; + } const char* data = (char*)desc.fPtr + desc.fOffset; hexDump(" data payload", data, desc.fSize); BOOST_CHECK(dataFields[dataidx++] == data); @@ -226,8 +230,9 @@ BOOST_AUTO_TEST_CASE(test_createHeartbeatFrame) for (auto& desc : dataDescriptors) { totalPayloadSize += desc.fSize; hexDump("HLT data descriptor", &desc, sizeof(desc)); - if (!desc.fPtr) + if (!desc.fPtr) { continue; + } hexDump(" data payload", (char*)desc.fPtr + desc.fOffset, desc.fSize); } diff --git a/Utilities/rANS/include/rANS/internal/EncoderSymbol.h b/Utilities/rANS/include/rANS/internal/EncoderSymbol.h index 133a97f10bae5..08fccf7fff284 100644 --- a/Utilities/rANS/include/rANS/internal/EncoderSymbol.h +++ b/Utilities/rANS/include/rANS/internal/EncoderSymbol.h @@ -92,8 +92,9 @@ struct EncoderSymbol { // Alverson, "Integer Division using reciprocals" // shift=ceil(log2(freq)) uint32_t shift = 0; - while (freq > (1u << shift)) + while (freq > (1u << shift)) { shift++; + } if constexpr (needs64Bit<T>()) { uint64_t x0, x1, t0, t1; diff --git a/Utilities/rANS/src/SymbolStatistics.cxx b/Utilities/rANS/src/SymbolStatistics.cxx index 2b6a82793ad59..ca9934b236443 100644 --- a/Utilities/rANS/src/SymbolStatistics.cxx +++ b/Utilities/rANS/src/SymbolStatistics.cxx @@ -82,10 +82,11 @@ void SymbolStatistics::rescale() mCumulativeFrequencyTable.back() == newCumulatedFrequency); for (size_t i = 0; i < mFrequencyTable.size(); i++) { - if (mFrequencyTable[i] == 0) + if (mFrequencyTable[i] == 0) { assert(mCumulativeFrequencyTable[i + 1] == mCumulativeFrequencyTable[i]); - else + } else { assert(mCumulativeFrequencyTable[i + 1] > mCumulativeFrequencyTable[i]); + } // calc updated freq mFrequencyTable[i] = getFrequency(i); From e5485b3a9f11659f911fddc145d1329508eaf994 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 5 Oct 2020 13:14:29 +0200 Subject: [PATCH 0888/1751] Use ConstMCTruthContainer in TPC workflow --- .../include/DataFormatsTPC/ClusterNative.h | 13 +++- .../DataFormatsTPC/ClusterNativeHelper.h | 46 ++++++++------ .../Detectors/TPC/src/ClusterNativeHelper.cxx | 8 +-- .../ConstMCTruthContainer.h | 7 ++- .../src/TPCITSMatchingSpec.cxx | 4 +- .../src/TPCInterpolationSpec.cxx | 4 +- .../TPC/calibration/macro/extractGainMap.C | 2 +- Detectors/TPC/qc/macro/runClusters.C | 2 +- .../include/TPCReconstruction/Clusterer.h | 7 ++- .../include/TPCReconstruction/ClustererTask.h | 5 +- .../HardwareClusterDecoder.h | 4 +- .../include/TPCReconstruction/HwClusterer.h | 15 +++-- .../TPC/reconstruction/src/ClustererTask.cxx | 8 +-- .../TPC/reconstruction/src/GPUCATracking.cxx | 7 ++- .../src/HardwareClusterDecoder.cxx | 4 +- .../TPC/reconstruction/src/HwClusterer.cxx | 10 ++-- .../test/testTPCHwClusterer.cxx | 30 ++++++---- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 28 ++++++--- .../workflow/src/ClusterDecoderRawSpec.cxx | 36 +++++++---- Detectors/TPC/workflow/src/ClustererSpec.cxx | 19 +++--- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 60 ++++++++++--------- .../Detectors/src/DataInterpreterTPC.cxx | 2 +- GPU/GPUTracking/Base/GPUDataTypes.h | 2 + GPU/GPUTracking/Base/GPUHostDataTypes.h | 3 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 21 +++++-- GPU/GPUTracking/Global/GPUChainTracking.h | 2 + GPU/GPUTracking/Interface/GPUO2Interface.cxx | 11 ++++ GPU/GPUTracking/Interface/GPUO2Interface.h | 1 + .../Interface/GPUO2InterfaceConfiguration.h | 3 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 + .../TPCClusterFinder/GPUTPCClusterFinder.h | 4 +- .../TPCClusterFinder/MCLabelAccumulator.cxx | 2 +- .../TPCClusterFinder/MCLabelAccumulator.h | 4 +- 33 files changed, 244 insertions(+), 132 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h index 4dcabd1913159..70124c72d62c9 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNative.h @@ -16,6 +16,7 @@ #ifndef GPUCA_GPUCODE_DEVICE #include <cstdint> #include <cstddef> // for size_t +#include <utility> #endif #include "DataFormatsTPC/Constants.h" #include "GPUCommonDef.h" @@ -26,7 +27,9 @@ class MCCompLabel; namespace dataformats { template <class T> -class MCTruthContainer; +class ConstMCTruthContainer; +template <class T> +class ConstMCTruthContainerView; } } // namespace o2 @@ -157,13 +160,19 @@ struct ClusterNative { struct ClusterNativeAccess { const ClusterNative* clustersLinear; const ClusterNative* clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* clustersMCTruth; + const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* clustersMCTruth; unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; unsigned int nClustersSector[constants::MAXSECTOR]; unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]; unsigned int nClustersTotal; void setOffsetPtrs(); + +#ifndef GPUCA_GPUCODE + using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; + using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; + using ConstMCLabelContainerViewWithBuffer = std::pair<ConstMCLabelContainer, ConstMCLabelContainerView>; +#endif }; inline void ClusterNativeAccess::setOffsetPtrs() diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h index 830830eab211a..9370132e74eab 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h @@ -19,6 +19,7 @@ #include "DataFormatsTPC/ClusterGroupAttribute.h" #include "DataFormatsTPC/Constants.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <gsl/gsl> #include <TFile.h> @@ -33,7 +34,6 @@ namespace o2 { namespace tpc { -using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; /// @struct ClusterNativeContainer /// A container class for a collection of ClusterNative object @@ -132,6 +132,11 @@ struct alignas(64) ClusterIndexBuffer { class ClusterNativeHelper { public: + using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using ConstMCLabelContainer = ClusterNativeAccess::ConstMCLabelContainer; + using ConstMCLabelContainerView = ClusterNativeAccess::ConstMCLabelContainerView; + using ConstMCLabelContainerViewWithBuffer = ClusterNativeAccess::ConstMCLabelContainerViewWithBuffer; + ClusterNativeHelper() = default; ~ClusterNativeHelper() = default; @@ -187,7 +192,7 @@ class ClusterNativeHelper // Fill the ClusterNative access structure from data and corresponding mc label arrays // from the internal data structures of the reader. int fillIndex(ClusterNativeAccess& clusterIndex, std::unique_ptr<ClusterNative[]>& clusterBuffer, - MCLabelContainer& mcBuffer); + ConstMCLabelContainerViewWithBuffer& mcBuffer); // Fill the ClusterNative access structure from data and corresponding mc label arrays. // Both cluster data input and mc containers are provided as a collection with one entry per @@ -211,10 +216,10 @@ class ClusterNativeHelper // @param inputs data arrays, fixed array, one per sector // @param mcinputs vectors mc truth container, fixed array, one per sector // @param checkFct check whether a sector index is valid - template <typename DataArrayType, typename MCArrayType, typename CheckFct> + template <typename DataArrayType, typename MCArrayType, typename CheckFct = std::function<bool(size_t&)>> static int fillIndex( ClusterNativeAccess& clusterIndex, std::unique_ptr<ClusterNative[]>& clusterBuffer, - MCLabelContainer& mcBuffer, DataArrayType& inputs, MCArrayType const& mcinputs, + ConstMCLabelContainerViewWithBuffer& mcBuffer, DataArrayType& inputs, MCArrayType const& mcinputs, CheckFct checkFct = [](auto const&) { return true; }); template <typename DataArrayType, typename CheckFct = std::function<bool(size_t&)>> @@ -226,7 +231,7 @@ class ClusterNativeHelper // TODO: maybe do in one function with conditional template parameter std::vector<std::unique_ptr<MCLabelContainer>> dummy; // another default, nothing will be added to the container - MCLabelContainer mcBuffer; + ConstMCLabelContainerViewWithBuffer mcBuffer; return fillIndex(clusterIndex, clusterBuffer, mcBuffer, inputs, dummy, checkFct); } @@ -234,17 +239,17 @@ class ClusterNativeHelper // This function does not copy any data but sets the corresponding poiters in the index. // Cluster data are provided as a raw buffer of consecutive ClusterNative arrays preceded by ClusterGroupHeader // MC labels are provided as a span of MCLabelContainers, one per sector. - static int parseSector(const char* buffer, size_t size, gsl::span<MCLabelContainer const> const& mcinput, // - ClusterNativeAccess& clusterIndex, // - const MCLabelContainer* (&clustersMCTruth)[NSectors]); // + static int parseSector(const char* buffer, size_t size, gsl::span<ConstMCLabelContainerView const> const& mcinput, // + ClusterNativeAccess& clusterIndex, // + const ConstMCLabelContainerView* (&clustersMCTruth)[NSectors]); // // Process data for one sector // Helper method receiving raw buffer provided as container // This function does not copy any data but sets the corresponding poiters in the index. template <typename ContainerT> - static int parseSector(ContainerT const cont, gsl::span<MCLabelContainer const> const& mcinput, // - ClusterNativeAccess& clusterIndex, // - const MCLabelContainer* (&clustersMCTruth)[NSectors]) // + static int parseSector(ContainerT const cont, gsl::span<ConstMCLabelContainerView const> const& mcinput, // + ClusterNativeAccess& clusterIndex, // + const ConstMCLabelContainerView* (&clustersMCTruth)[NSectors]) // { using T = typename std::remove_pointer<ContainerT>::type; static_assert(sizeof(typename T::value_type) == 1, "raw container must be byte-type"); @@ -346,7 +351,7 @@ class ClusterNativeHelper template <typename DataArrayType, typename MCArrayType, typename CheckFct> int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, - std::unique_ptr<ClusterNative[]>& clusterBuffer, MCLabelContainer& mcBuffer, + std::unique_ptr<ClusterNative[]>& clusterBuffer, ConstMCLabelContainerViewWithBuffer& mcBuffer, DataArrayType& inputs, MCArrayType const& mcinputs, CheckFct checkFct) { if (mcinputs.size() > 0 && mcinputs.size() != inputs.size()) { @@ -361,7 +366,7 @@ int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, clusterIndex.clustersLinear = reinterpret_cast<const ClusterNative*>(inputs[0].data() + sizeof(*hdr)); clusterIndex.setOffsetPtrs(); if (mcinputs.size() > 0) { - clusterIndex.clustersMCTruth = mcinputs[0].get(); + clusterIndex.clustersMCTruth = &mcinputs[0]; } } if (sizeof(ClusterCountIndex) + clusterIndex.nClustersTotal * sizeof(ClusterNative) > inputs[0].size()) { @@ -371,16 +376,16 @@ int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, } // multiple data blocks need to be merged into the single block - const MCLabelContainer* clustersMCTruth[NSectors] = {nullptr}; + const ConstMCLabelContainerView* clustersMCTruth[NSectors] = {nullptr}; int result = 0; for (size_t index = 0, end = inputs.size(); index < end; index++) { if (!checkFct(index)) { continue; } - MCLabelContainer const* labelsptr = nullptr; + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> const* labelsptr = nullptr; int extent = 0; if (index < mcinputs.size()) { - labelsptr = mcinputs[index].get(); + labelsptr = &mcinputs[index]; extent = 1; } int locres = parseSector(inputs[index], {labelsptr, extent}, clusterIndex, clustersMCTruth); @@ -393,7 +398,8 @@ int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, // Now move all data to a new consecutive buffer ClusterNativeAccess old = clusterIndex; clusterBuffer.reset(new ClusterNative[result]); - mcBuffer.clear(); + MCLabelContainer tmpMCBuffer; + tmpMCBuffer.clear(); bool mcPresent = false; clusterIndex.clustersLinear = clusterBuffer.get(); clusterIndex.setOffsetPtrs(); @@ -405,14 +411,16 @@ int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, mcPresent = true; for (unsigned int k = 0; k < old.nClusters[i][j]; k++, sectorLabelId++) { for (auto const& label : clustersMCTruth[i]->getLabels(sectorLabelId)) { - mcBuffer.addElement(clusterIndex.clusterOffset[i][j] + k, label); + tmpMCBuffer.addElement(clusterIndex.clusterOffset[i][j] + k, label); } } } } } if (mcPresent) { - clusterIndex.clustersMCTruth = &mcBuffer; + tmpMCBuffer.flatten_to(mcBuffer.first); + mcBuffer.second = mcBuffer.first; + clusterIndex.clustersMCTruth = &mcBuffer.second; } return result; diff --git a/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx b/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx index ee0c0a5b12907..0d30744b3ee83 100644 --- a/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx +++ b/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx @@ -31,7 +31,7 @@ void ClusterNativeHelper::convert(const char* fromFile, const char* toFile, cons size_t nEntries = reader.getTreeSize(); ClusterNativeAccess clusterIndex; std::unique_ptr<ClusterNative[]> clusterBuffer; - MCLabelContainer mcBuffer; + ConstMCLabelContainerViewWithBuffer mcBuffer; int result = 0; int nClusters = 0; @@ -161,7 +161,7 @@ void ClusterNativeHelper::Reader::clear() } int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, std::unique_ptr<ClusterNative[]>& clusterBuffer, - MCLabelContainer& mcBuffer) + ConstMCLabelContainerViewWithBuffer& mcBuffer) { for (size_t index = 0; index < mSectorRaw.size(); ++index) { if (mSectorRaw[index] && mSectorRaw[index]->size() != mSectorRawSize[index]) { @@ -177,8 +177,8 @@ int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, st return 0; } -int ClusterNativeHelper::Reader::parseSector(const char* buffer, size_t size, gsl::span<MCLabelContainer const> const& mcinput, ClusterNativeAccess& clusterIndex, - const MCLabelContainer* (&clustersMCTruth)[MAXSECTOR]) +int ClusterNativeHelper::Reader::parseSector(const char* buffer, size_t size, gsl::span<ConstMCLabelContainerView const> const& mcinput, ClusterNativeAccess& clusterIndex, + const ConstMCLabelContainerView* (&clustersMCTruth)[MAXSECTOR]) { if (!buffer || size < sizeof(ClusterCountIndex)) { return 0; diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h index a6853364feddd..30473cd598a9b 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -127,7 +127,7 @@ class ConstMCTruthContainerView public: ConstMCTruthContainerView(gsl::span<const char> const bufferview) : mStorage(bufferview){}; ConstMCTruthContainerView(ConstMCTruthContainer<TruthElement> const& cont) : mStorage(gsl::span<const char>(cont)){}; - ConstMCTruthContainerView() = default; + ConstMCTruthContainerView() : mStorage(nullptr, (gsl::span<const char>::index_type)0){}; // be explicit that we want nullptr / 0 for an uninitialized container ConstMCTruthContainerView(const ConstMCTruthContainerView&) = default; // const data access @@ -151,9 +151,12 @@ class ConstMCTruthContainerView // return the number of original data indexed here size_t getIndexedSize() const { return mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofHeaderElements : 0; } - // return the number of labels managed in this container + // return the number of labels managed in this container size_t getNElements() const { return mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofTruthElements : 0; } + // return underlying buffer + const gsl::span<const char>& getBuffer() const { return mStorage; } + private: gsl::span<const char> mStorage; diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index b974b562f55f4..b96e965ea34b9 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -202,7 +202,9 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) o2::tpc::ClusterNativeAccess clusterIndex; std::unique_ptr<o2::tpc::ClusterNative[]> clusterBuffer; memset(&clusterIndex, 0, sizeof(clusterIndex)); - o2::tpc::ClusterNativeHelper::Reader::fillIndex(clusterIndex, clusterBuffer, clustersTPC); + o2::tpc::ClusterNativeHelper::ConstMCLabelContainerViewWithBuffer dummyMCOutput; + std::vector<o2::tpc::ClusterNativeHelper::ConstMCLabelContainerView> dummyMCInput; + o2::tpc::ClusterNativeHelper::Reader::fillIndex(clusterIndex, clusterBuffer, dummyMCOutput, clustersTPC, dummyMCInput); //----------------------------<< TPC Clusters loading <<------------------------------------------ // diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx index 8ac3dc05d7fc5..cf8a9a3e48e76 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx @@ -145,7 +145,9 @@ void TPCInterpolationDPL::run(ProcessingContext& pc) o2::tpc::ClusterNativeAccess clusterIndex; std::unique_ptr<o2::tpc::ClusterNative[]> clusterBuffer; memset(&clusterIndex, 0, sizeof(clusterIndex)); - o2::tpc::ClusterNativeHelper::Reader::fillIndex(clusterIndex, clusterBuffer, clustersTPC); + o2::tpc::ClusterNativeHelper::ConstMCLabelContainerViewWithBuffer dummyMCOutput; + std::vector<o2::tpc::ClusterNativeHelper::ConstMCLabelContainerView> dummyMCInput; + o2::tpc::ClusterNativeHelper::Reader::fillIndex(clusterIndex, clusterBuffer, dummyMCOutput, clustersTPC, dummyMCInput); //----------------------------<< TPC Clusters loading <<------------------------------------------ // pass input data to TrackInterpolation object diff --git a/Detectors/TPC/calibration/macro/extractGainMap.C b/Detectors/TPC/calibration/macro/extractGainMap.C index 7476bd0f0846d..35ea78192e8df 100644 --- a/Detectors/TPC/calibration/macro/extractGainMap.C +++ b/Detectors/TPC/calibration/macro/extractGainMap.C @@ -107,7 +107,7 @@ void calibGainMacroTrk(const float momMin, const float momMax, const std::string ClusterNativeAccess clusterIndex{}; std::unique_ptr<ClusterNative[]> clusterBuffer{}; - MCLabelContainer clusterMCBuffer; + o2::tpc::ClusterNativeHelper::ConstMCLabelContainerViewWithBuffer clusterMCBuffer; memset(&clusterIndex, 0, sizeof(clusterIndex)); CalibPadGainTracks cGain{}; diff --git a/Detectors/TPC/qc/macro/runClusters.C b/Detectors/TPC/qc/macro/runClusters.C index 62c3df227c4af..bed9cbb409d15 100644 --- a/Detectors/TPC/qc/macro/runClusters.C +++ b/Detectors/TPC/qc/macro/runClusters.C @@ -29,7 +29,7 @@ void runClusters(std::string_view outputFile = "ClusterQC.root", std::string_vie ClusterNativeAccess clusterIndex; std::unique_ptr<ClusterNative[]> clusterBuffer; memset(&clusterIndex, 0, sizeof(clusterIndex)); - MCLabelContainer clusterMCBuffer; + o2::tpc::ClusterNativeHelper::ConstMCLabelContainerViewWithBuffer clusterMCBuffer; qc::Clusters clusters; diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h index 881d71e504080..7bcf1a2427782 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h @@ -18,6 +18,7 @@ #include <memory> #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "TPCBase/CalDet.h" @@ -34,7 +35,7 @@ class Digit; class Clusterer { protected: - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; public: /// Default Constructor @@ -49,8 +50,8 @@ class Clusterer /// Processing all digits /// \param digits Container with TPC digits /// \param mcDigitTruth MC Digit Truth container - virtual void process(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth) = 0; - virtual void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth) = 0; + virtual void process(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) = 0; + virtual void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) = 0; /// Setter for noise object, noise will be added before cluster finding /// \param noiseObject CalDet object, containing noise simulation diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h index f745ae1fedf3d..d2919848df2e9 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h @@ -21,6 +21,7 @@ #include "DataFormatsTPC/Digit.h" #include "TPCReconstruction/HwClusterer.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "DataFormatsTPC/Helpers.h" #include "DataFormatsTPC/ClusterHardware.h" @@ -36,6 +37,8 @@ class ClustererTask : public FairTask { using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; + using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; using OutputType = ClusterHardwareContainer8kb; public: @@ -68,7 +71,7 @@ class ClustererTask : public FairTask // Digit arrays std::unique_ptr<const std::vector<Digit>> mDigitsArray; ///< Array of TPC digits - std::unique_ptr<const MCLabelContainer> mDigitMCTruthArray; ///< Array for MCTruth information associated to digits in mDigitsArrray + std::unique_ptr<const ConstMCLabelContainerView> mDigitMCTruthArray; ///< Array for MCTruth information associated to digits in mDigitsArrray // Cluster arrays std::unique_ptr<std::vector<OutputType>> mHwClustersArray; ///< Array of clusters found by Hw Clusterfinder diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/HardwareClusterDecoder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/HardwareClusterDecoder.h index e84532380152d..84d1b2b5ed643 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/HardwareClusterDecoder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/HardwareClusterDecoder.h @@ -30,6 +30,8 @@ namespace dataformats { template <typename TruthElement> class MCTruthContainer; +template <typename TruthElement> +class ConstMCTruthContainerView; } /// @class HardwareClusterDecoder @@ -76,7 +78,7 @@ class HardwareClusterDecoder /// @param outMCLabels optional pointer to MC output container int decodeClusters(std::vector<std::pair<const o2::tpc::ClusterHardwareContainer*, std::size_t>>& inputClusters, OutputAllocator outputAllocator, - const std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>* inMCLabels = nullptr, + const std::vector<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>>* inMCLabels = nullptr, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* outMCLabels = nullptr); /// @brief Sort clusters and MC labels in place diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h index 58d9c80b82942..2068ca4360fc3 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h @@ -21,6 +21,7 @@ #include "DataFormatsTPC/Helpers.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <vector> @@ -42,6 +43,8 @@ class HwClusterer : public Clusterer private: using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; + using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; /// Main Constructor HwClusterer( @@ -71,15 +74,15 @@ class HwClusterer : public Clusterer /// \param digits Container with TPC digits /// \param mcDigitTruth MC Digit Truth container /// \param clearContainerFirst Clears the outpcontainer for clusters and MC labels first, before processing - void process(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth) override; - void process(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth, bool clearContainerFirst); + void process(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) override; + void process(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth, bool clearContainerFirst); /// Finish processing digits /// \param digits Container with TPC digits /// \param mcDigitTruth MC Digit Truth container /// \param clearContainerFirst Clears the outpcontainer for clusters and MC labels first, before processing - void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth) override; - void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth, bool clearContainerFirst); + void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) override; + void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth, bool clearContainerFirst); /// Switch for triggered / continuous readout /// \param isContinuous - false for triggered readout, true for continuous readout @@ -218,12 +221,12 @@ class HwClusterer : public Clusterer MCLabelContainer* mClusterMcLabelArray; ///< Pointer to MC Label container }; -inline void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, o2::dataformats::MCTruthContainer<o2::MCCompLabel> const* mcDigitTruth) +inline void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) { process(digits, mcDigitTruth, true); } -inline void HwClusterer::finishProcess(gsl::span<o2::tpc::Digit const> const& digits, o2::dataformats::MCTruthContainer<o2::MCCompLabel> const* mcDigitTruth) +inline void HwClusterer::finishProcess(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) { finishProcess(digits, mcDigitTruth, true); } diff --git a/Detectors/TPC/reconstruction/src/ClustererTask.cxx b/Detectors/TPC/reconstruction/src/ClustererTask.cxx index 634afbc6a1c65..503a7f4e3201a 100644 --- a/Detectors/TPC/reconstruction/src/ClustererTask.cxx +++ b/Detectors/TPC/reconstruction/src/ClustererTask.cxx @@ -62,8 +62,8 @@ InitStatus ClustererTask::Init() } std::stringstream mcsectornamestr; mcsectornamestr << "TPCDigitMCTruth" << mClusterSector; - mDigitMCTruthArray = std::unique_ptr<const MCLabelContainer>( - mgr->InitObjectAs<const MCLabelContainer*>(mcsectornamestr.str().c_str())); + mDigitMCTruthArray = std::unique_ptr<const ConstMCLabelContainerView>( + mgr->InitObjectAs<const ConstMCLabelContainerView*>(mcsectornamestr.str().c_str())); if (!mDigitMCTruthArray) { LOG(ERROR) << "TPC MC Truth not registered in the FairRootManager. Exiting ..."; return kERROR; @@ -102,7 +102,7 @@ void ClustererTask::Exec(Option_t* option) if (mHwClustersMCTruthArray) mHwClustersMCTruthArray->clear(); - mHwClusterer->process(gsl::span<o2::tpc::Digit const>(mDigitsArray->data(), mDigitsArray->size()), mDigitMCTruthArray.get()); + mHwClusterer->process(gsl::span<o2::tpc::Digit const>(mDigitsArray->data(), mDigitsArray->size()), *mDigitMCTruthArray.get()); LOG(DEBUG) << "Hw clusterer delivered " << mHwClustersArray->size() << " cluster container"; ++mEventCount; @@ -118,7 +118,7 @@ void ClustererTask::FinishTask() if (mHwClustersMCTruthArray) mHwClustersMCTruthArray->clear(); - mHwClusterer->finishProcess(*mDigitsArray.get(), mDigitMCTruthArray.get()); + mHwClusterer->finishProcess(*mDigitsArray.get(), *mDigitMCTruthArray.get()); LOG(DEBUG) << "Hw clusterer delivered " << mHwClustersArray->size() << " cluster container"; ++mEventCount; diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index e894824d51742..1e26fc0bd4d03 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -17,6 +17,7 @@ #include "ReconstructionDataFormats/Track.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "TChain.h" #include "TClonesArray.h" #include "TPCBase/Mapper.h" @@ -26,6 +27,7 @@ #include "TPCBase/ParameterGas.h" #include "TPCBase/Sector.h" #include "DataFormatsTPC/Digit.h" +#include "DataFormatsTPC/ClusterNativeHelper.h" #include "DetectorsRaw/HBFUtils.h" #include "GPUO2Interface.h" @@ -87,6 +89,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* std::vector<o2::tpc::Digit> gpuDigits[Sector::MAXSECTOR]; o2::dataformats::MCTruthContainer<o2::MCCompLabel> gpuDigitsMC[Sector::MAXSECTOR]; + ClusterNativeAccess::ConstMCLabelContainerViewWithBuffer gpuDigitsMCConst[Sector::MAXSECTOR]; GPUTrackingInOutDigits gpuDigitsMap; GPUTPCDigitsMCInput gpuDigitsMapMC; @@ -121,7 +124,9 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* gpuDigitsMap.tpcDigits[i] = gpuDigits[i].data(); gpuDigitsMap.nTPCDigits[i] = gpuDigits[i].size(); if (data->o2DigitsMC) { - gpuDigitsMapMC.v[i] = &gpuDigitsMC[i]; + gpuDigitsMC[i].flatten_to(gpuDigitsMCConst[i].first); + gpuDigitsMCConst[i].second = gpuDigitsMCConst[i].first; + gpuDigitsMapMC.v[i] = &gpuDigitsMCConst[i].second; } } else { gpuDigitsMap.tpcDigits[i] = (*(data->o2Digits))[i].data(); diff --git a/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx b/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx index cf3a326e29eab..67537a7d4b34f 100644 --- a/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx +++ b/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx @@ -34,7 +34,7 @@ using namespace o2::dataformats; int HardwareClusterDecoder::decodeClusters(std::vector<std::pair<const ClusterHardwareContainer*, std::size_t>>& inputClusters, HardwareClusterDecoder::OutputAllocator outputAllocator, - const std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>* inMCLabels, + const std::vector<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>>* inMCLabels, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* outMCLabels) { if (mIntegrator == nullptr) @@ -176,7 +176,7 @@ void HardwareClusterDecoder::sortClustersAndMC(ClusterNative* clusters, size_t n return clusters[a] < clusters[b]; }); std::vector<ClusterNative> buffer(clusters, clusters + nClusters); - MCLabelContainer tmpMC = std::move(mcTruth); + ClusterNativeHelper::MCLabelContainer tmpMC = std::move(mcTruth); assert(mcTruth.getIndexedSize() == 0); for (int i = 0; i < nClusters; i++) { clusters[i] = buffer[indizes[i]]; diff --git a/Detectors/TPC/reconstruction/src/HwClusterer.cxx b/Detectors/TPC/reconstruction/src/HwClusterer.cxx index de41dcc290eba..15da2996b7e02 100644 --- a/Detectors/TPC/reconstruction/src/HwClusterer.cxx +++ b/Detectors/TPC/reconstruction/src/HwClusterer.cxx @@ -129,7 +129,7 @@ void HwClusterer::init() } //______________________________________________________________________________ -void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth, bool clearContainerFirst) +void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth, bool clearContainerFirst) { if (clearContainerFirst) { if (mClusterArray) @@ -226,9 +226,11 @@ void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, MCLabel // we have to copy the MC truth container because we need the information // maybe only in the next events (we store permanently 5 timebins), where // the original pointer could already point to the next container. - if (mcDigitTruth) { + if (mcDigitTruth.getBuffer().size()) { if (mCurrentMcContainerInBuffer == 0) { - mMCtruth[mapTimeInRange(timeBin)] = std::make_shared<MCLabelContainer const>(*mcDigitTruth); + auto tmp = std::make_shared<MCLabelContainer>(); + tmp->restore_from(mcDigitTruth.getBuffer().data(), mcDigitTruth.getBuffer().size()); + mMCtruth[mapTimeInRange(timeBin)] = tmp; } else { mMCtruth[mapTimeInRange(timeBin)] = std::shared_ptr<MCLabelContainer const>(mMCtruth[getFirstSetBitOfField()]); } @@ -272,7 +274,7 @@ void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, MCLabel } //______________________________________________________________________________ -void HwClusterer::finishProcess(gsl::span<o2::tpc::Digit const> const& digits, MCLabelContainer const* mcDigitTruth, bool clearContainerFirst) +void HwClusterer::finishProcess(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth, bool clearContainerFirst) { // Process the last digits (if there are any) process(digits, mcDigitTruth, clearContainerFirst); diff --git a/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx b/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx index d0f7d82b4fc14..d647cc5d9f295 100644 --- a/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx +++ b/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx @@ -22,6 +22,7 @@ #include "TPCReconstruction/HwClusterer.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <vector> @@ -156,8 +157,10 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test1) auto digits = std::make_unique<const std::vector<Digit>>(digitVec); auto mcDigitTruth = std::make_unique<const MCLabelContainer>(labelContainer); + o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel> flatLabels; + mcDigitTruth->flatten_to(flatLabels); - clusterer.process(*digits.get(), mcDigitTruth.get()); + clusterer.process(*digits.get(), flatLabels); // check if clusters were found BOOST_CHECK_EQUAL(clusterArray->size(), 1); @@ -216,7 +219,8 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test2) std::sort(digits->begin(), digits->end(), sortTime()); // Search clusters - clusterer.process(*digits.get(), nullptr); + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> flatLabelsViewEmpty; + clusterer.process(*digits.get(), flatLabelsViewEmpty); // Check result BOOST_CHECK_EQUAL(clusterArray->size(), 47); @@ -314,7 +318,8 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test3) std::sort(digits->begin(), digits->end(), sortTime()); // Search clusters - clusterer.process(*digits.get(), nullptr); + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> flatLabelsViewEmpty; + clusterer.process(*digits.get(), flatLabelsViewEmpty); // Check outcome BOOST_CHECK_EQUAL(clusterArray->size(), 1); @@ -416,7 +421,8 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test4) std::cout << "testing without thresholds..." << std::endl; clusterer.setRejectSinglePadClusters(false); clusterer.setRejectSingleTimeClusters(false); - clusterer.process(*digits.get(), nullptr); + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> flatLabelsViewEmpty; + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); auto clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 4); @@ -456,7 +462,7 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test4) std::cout << "testing with pad threshold..." << std::endl; clusterer.setRejectSinglePadClusters(true); clusterer.setRejectSingleTimeClusters(false); - clusterer.process(*digits.get(), nullptr); + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 2); @@ -496,7 +502,7 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test4) std::cout << "testing with time threshold..." << std::endl; clusterer.setRejectSinglePadClusters(false); clusterer.setRejectSingleTimeClusters(true); - clusterer.process(*digits.get(), nullptr); + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 2); @@ -536,7 +542,7 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test4) std::cout << "testing both thresholds..." << std::endl; clusterer.setRejectSinglePadClusters(true); clusterer.setRejectSingleTimeClusters(true); - clusterer.process(*digits.get(), nullptr); + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 1); @@ -620,7 +626,8 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test5) // Search clusters without rejection, all 4 clusters shoud be found std::cout << "testing without rejection..." << std::endl; clusterer.setRejectLaterTimebin(false); - clusterer.process(*digits.get(), nullptr); + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> flatLabelsViewEmpty; + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); auto clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 4); @@ -632,7 +639,7 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test5) // Search clusters with rejection, cluster with peak charge 13 should be surpressed std::cout << "testing with with rejection..." << std::endl; clusterer.setRejectLaterTimebin(true); - clusterer.process(*digits.get(), nullptr); + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 3); @@ -904,7 +911,8 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test6) clustersToCompare.emplace_back(); clustersToCompare.back().setCluster(2, 7 + 100, p_pre_fp(clustersMode0[10]), t_pre_fp(clustersMode0[10]), sigma_p_pre_fp(clustersMode0[10]), sigma_t_pre_fp(clustersMode0[10]), (clustersMode0[10][12] * 2), (std::accumulate(clustersMode0[10].begin(), clustersMode0[10].end(), 0.0) * 16), 0, 0); clusterer.setSplittingMode(0); - clusterer.process(*digits.get(), nullptr); + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> flatLabelsViewEmpty; + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); auto clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 11); @@ -962,7 +970,7 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test6) clustersToCompare.emplace_back(); clustersToCompare.back().setCluster(2, 7 + 100, p_pre_fp(clustersMode1[10]), t_pre_fp(clustersMode1[10]), sigma_p_pre_fp(clustersMode1[10]), sigma_t_pre_fp(clustersMode1[10]), (clustersMode1[10][12] * 2), (std::accumulate(clustersMode1[10].begin(), clustersMode1[10].end(), 0.0) * 16), 0, 0); clusterer.setSplittingMode(1); - clusterer.process(*digits.get(), nullptr); + clusterer.process(*digits.get(), flatLabelsViewEmpty); BOOST_CHECK_EQUAL(clusterArray->size(), 1); clusterContainer = (*clusterArray)[0].getContainer(); BOOST_CHECK_EQUAL(clusterContainer->numberOfClusters, 11); diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index a238248aa9d77..92dc7c39b9dcf 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -51,6 +51,7 @@ #include "TPCBase/Sector.h" #include "TPCBase/Utils.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "Algorithm/Parser.h" #include <boost/filesystem.hpp> @@ -70,6 +71,9 @@ using namespace o2::header; using namespace o2::gpu; using namespace o2::base; +using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; +using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; + namespace o2 { namespace tpc @@ -263,8 +267,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int auto& verbosity = processAttributes->verbosity; // FIXME cleanup almost duplicated code auto& validMcInputs = processAttributes->validMcInputs; - using CachedMCLabelContainer = decltype(std::declval<InputRecord>().get<MCLabelContainer*>(DataRef{nullptr, nullptr, nullptr})); - std::vector<CachedMCLabelContainer> mcInputs; + std::vector<ConstMCLabelContainerView> mcInputs; std::vector<gsl::span<const char>> inputs; struct InputRef { DataRef data; @@ -281,8 +284,9 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int const void** tpcZSmetaPointers2[GPUTrackingInOutZS::NSLICES][GPUTrackingInOutZS::NENDPOINTS]; const unsigned int* tpcZSmetaSizes2[GPUTrackingInOutZS::NSLICES][GPUTrackingInOutZS::NENDPOINTS]; std::array<gsl::span<const o2::tpc::Digit>, NSectors> inputDigits; - std::vector<CachedMCLabelContainer> inputDigitsMC; - std::array<const MCLabelContainer*, constants::MAXSECTOR> inputDigitsMCPtrs; + std::vector<ConstMCLabelContainerView> inputDigitsMC; + std::array<int, constants::MAXSECTOR> inputDigitsMCIndex; + std::array<const ConstMCLabelContainerView*, constants::MAXSECTOR> inputDigitsMCPtrs; std::array<unsigned int, NEndpoints * NSectors> tpcZSonTheFlySizes; gsl::span<const ZeroSuppressedContainer8kb> inputZS; @@ -312,8 +316,8 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } inputrefs[sector].labels = ref; if (specconfig.caClusterer) { - inputDigitsMC.emplace_back(pc.inputs().get<const MCLabelContainer*>(ref)); - inputDigitsMCPtrs[sector] = inputDigitsMC.back().get(); + inputDigitsMCIndex[sector] = inputDigitsMC.size(); + inputDigitsMC.emplace_back(ConstMCLabelContainerView(pc.inputs().get<gsl::span<char>>(ref))); } validMcInputs |= sectorMask; activeSectors |= sectorHeader->activeSectors; @@ -326,6 +330,9 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int << " active sectors: " << std::bitset<NSectors>(activeSectors); // } } + for (unsigned int i = 0; i < NSectors; i++) { + inputDigitsMCPtrs[i] = &inputDigitsMC[inputDigitsMCIndex[i]]; + } } auto& validInputs = processAttributes->validInputs; @@ -509,7 +516,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int continue; } if (refentry.second.labels.header != nullptr && refentry.second.labels.payload != nullptr) { - mcInputs.emplace_back(pc.inputs().get<const MCLabelContainer*>(refentry.second.labels)); + mcInputs.emplace_back(ConstMCLabelContainerView(pc.inputs().get<gsl::span<char>>(refentry.second.labels))); } inputs.emplace_back(gsl::span(ref.payload, DataRefUtils::getPayloadSize(ref))); printInputLog(ref, "received", sector); @@ -559,7 +566,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int GPUO2InterfaceIOPtrs ptrs; ClusterNativeAccess clusterIndex; std::unique_ptr<ClusterNative[]> clusterBuffer; - MCLabelContainer clustersMCBuffer; + ClusterNativeHelper::ConstMCLabelContainerViewWithBuffer clustersMCBuffer; void* ptrEp[NSectors * NEndpoints] = {}; ptrs.outputTracks = &tracks; ptrs.outputClusRefs = &clusRefs; @@ -639,6 +646,9 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int outputRegions.tpcTracks.ptr = bufferTPCTracksChar = bufferTPCTracks->get().data(); outputRegions.tpcTracks.size = bufferTPCTracks->get().size(); } + if (specconfig.processMC) { + outputRegions.clusterLabels.allocator = [&clustersMCBuffer](size_t size) -> void* { return &clustersMCBuffer; }; + } int retVal = tracker->runTracking(&ptrs, &outputRegions); if (processAttributes->suppressOutput) { @@ -696,7 +706,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int static_assert(sizeof(ClusterCountIndex) == sizeof(accessIndex.nClusters)); memcpy(outIndex, &accessIndex.nClusters[0][0], sizeof(ClusterCountIndex)); if (specconfig.processMC && accessIndex.clustersMCTruth) { - pc.outputs().snapshot({gDataOriginTPC, "CLNATIVEMCLBL", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}, *accessIndex.clustersMCTruth); + pc.outputs().snapshot({gDataOriginTPC, "CLNATIVEMCLBL", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}, clustersMCBuffer.first); } } diff --git a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx index f43fad7a07bcf..0816b5650760f 100644 --- a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx @@ -23,6 +23,7 @@ #include "DataFormatsTPC/Helpers.h" #include "TPCReconstruction/HardwareClusterDecoder.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <FairMQLogger.h> #include <memory> // for make_shared @@ -42,6 +43,8 @@ namespace tpc { using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; +using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; +using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; /// create the processor spec for TPC raw cluster decoder converting TPC raw to native clusters /// Input: raw pages of TPC raw clusters @@ -115,13 +118,15 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) // MC labels are received as one container of labels in the sequence matching clusters // in the raw pages - std::vector<MCLabelContainer> mcinCopies; - std::unique_ptr<const MCLabelContainer> mcin; + std::vector<ConstMCLabelContainer> mcinCopiesFlat; + std::vector<ConstMCLabelContainerView> mcinCopiesFlatView; + ConstMCLabelContainerView mcin; if (DataRefUtils::isValid(mclabelref)) { - mcin = std::move(pc.inputs().get<MCLabelContainer*>(mclabelref)); - mcinCopies.resize(nPages); + mcin = pc.inputs().get<gsl::span<char>>(mclabelref); + mcinCopiesFlat.resize(nPages); + mcinCopiesFlatView.reserve(nPages); if (verbosity > 0) { - LOG(INFO) << "Decoder input: " << size << ", " << nPages << " pages, " << mcin->getIndexedSize() << " MC label sets for sector " << sectorHeader->sector(); + LOG(INFO) << "Decoder input: " << size << ", " << nPages << " pages, " << mcin.getIndexedSize() << " MC label sets for sector " << sectorHeader->sector(); } } @@ -133,6 +138,7 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) size_t mcinPos = 0; size_t totalNumberOfClusters = 0; for (size_t page = 0; page < nPages; page++) { + MCLabelContainer mcinCopy; inputList.emplace_back(reinterpret_cast<const ClusterHardwareContainer*>(ref.payload + page * 8192), 1); const ClusterHardwareContainer& container = *(inputList.back().first); if (verbosity > 1) { @@ -141,22 +147,24 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) << std::setw(3) << container.numberOfClusters << " cluster(s)"; // } totalNumberOfClusters += container.numberOfClusters; - if (mcin) { + if (mcin.getBuffer().size()) { for (size_t mccopyPos = 0; - mccopyPos < container.numberOfClusters && mcinPos < mcin->getIndexedSize(); + mccopyPos < container.numberOfClusters && mcinPos < mcin.getIndexedSize(); mccopyPos++, mcinPos++) { - for (auto const& label : mcin->getLabels(mcinPos)) { - mcinCopies[page].addElement(mccopyPos, label); + for (auto const& label : mcin.getLabels(mcinPos)) { + mcinCopy.addElement(mccopyPos, label); } } } + mcinCopy.flatten_to(mcinCopiesFlat[page]); + mcinCopiesFlatView.emplace_back(mcinCopiesFlat[page]); } // FIXME: introduce error handling policy: throw, ignore, warn //assert(!mcin || mcinPos == mcin->getIndexedSize()); - if (mcin && mcinPos != totalNumberOfClusters) { + if (mcin.getBuffer().size() && mcinPos != totalNumberOfClusters) { LOG(ERROR) << "inconsistent number of MC label objects processed" << ", expecting MC label objects for " << totalNumberOfClusters << " cluster(s)" - << ", got " << mcin->getIndexedSize(); + << ", got " << mcin.getIndexedSize(); } // output of the decoder is sorted in (sector,globalPadRow) coordinates, individual // containers are created for clusters and MC labels per (sector,globalPadRow) address @@ -166,7 +174,7 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) return outputBuffer; }; MCLabelContainer mcout; - decoder->decodeClusters(inputList, outputAllocator, (mcin ? &mcinCopies : nullptr), &mcout); + decoder->decodeClusters(inputList, outputAllocator, (mcin.getBuffer().size() ? &mcinCopiesFlatView : nullptr), &mcout); // TODO: reestablish the logging messages on the raw buffer // if (verbosity > 1) { @@ -181,7 +189,9 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) << " label object(s)" << std::endl; } // serialize the complete list of MC label containers - pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLNATIVEMCLBL"), fanSpec, Lifetime::Timeframe, std::move(mcHeaderStack)}, mcout); + ConstMCLabelContainer labelsFlat; + mcout.flatten_to(labelsFlat); + pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLNATIVEMCLBL"), fanSpec, Lifetime::Timeframe, std::move(mcHeaderStack)}, labelsFlat); } }; diff --git a/Detectors/TPC/workflow/src/ClustererSpec.cxx b/Detectors/TPC/workflow/src/ClustererSpec.cxx index ee0220cafe689..36d76de3d81a3 100644 --- a/Detectors/TPC/workflow/src/ClustererSpec.cxx +++ b/Detectors/TPC/workflow/src/ClustererSpec.cxx @@ -39,6 +39,8 @@ namespace tpc { using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; +using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; +using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; /// create a processor spec /// runs the TPC HwClusterer in a DPL process with digits and mc as input @@ -87,14 +89,14 @@ DataProcessorSpec getClustererSpec(bool sendMC) } return; } - std::unique_ptr<const MCLabelContainer> inMCLabels; + ConstMCLabelContainerView inMCLabels; if (DataRefUtils::isValid(mclabelref)) { - inMCLabels = std::move(pc.inputs().get<const MCLabelContainer*>(mclabelref)); + inMCLabels = pc.inputs().get<gsl::span<char>>(mclabelref); } auto inDigits = pc.inputs().get<gsl::span<o2::tpc::Digit>>(dataref); - if (verbosity > 0 && inMCLabels) { + if (verbosity > 0 && inMCLabels.getBuffer().size()) { LOG(INFO) << "received " << inDigits.size() << " digits, " - << inMCLabels->getIndexedSize() << " MC label objects" + << inMCLabels.getIndexedSize() << " MC label objects" << " input MC label size " << DataRefUtils::getPayloadSize(mclabelref); } if (!clusterers[sector]) { @@ -115,9 +117,10 @@ DataProcessorSpec getClustererSpec(bool sendMC) // are cleared but also the cluster counter. Clearing the containers externally leaves the // cluster counter unchanged and leads to an inconsistency between cluster container and // MC label container (the latter just grows with every call). - clusterer->process(inDigits, inMCLabels.get(), true /* clear output containers and cluster counter */); + clusterer->process(inDigits, inMCLabels, true /* clear output containers and cluster counter */); const std::vector<o2::tpc::Digit> emptyDigits; - clusterer->finishProcess(emptyDigits, nullptr, false); // keep here the false, otherwise the clusters are lost of they are not stored in the meantime + ConstMCLabelContainerView emptyLabels; + clusterer->finishProcess(emptyDigits, emptyLabels, false); // keep here the false, otherwise the clusters are lost of they are not stored in the meantime if (verbosity > 0) { LOG(INFO) << "clusterer produced " << std::accumulate(clusterArray.begin(), clusterArray.end(), size_t(0), [](size_t l, auto const& r) { return l + r.getContainer()->numberOfClusters; }) @@ -133,7 +136,9 @@ DataProcessorSpec getClustererSpec(bool sendMC) auto outputPages = pc.outputs().make<ClusterHardwareContainer8kb>(Output{gDataOriginTPC, "CLUSTERHW", fanSpec, Lifetime::Timeframe, {*sectorHeader}}, clusterArray.size()); std::copy(clusterArray.begin(), clusterArray.end(), outputPages.begin()); if (DataRefUtils::isValid(mclabelref)) { - pc.outputs().snapshot(Output{gDataOriginTPC, "CLUSTERHWMCLBL", fanSpec, Lifetime::Timeframe, {*sectorHeader}}, mctruthArray); + ConstMCLabelContainer mcflat; + mctruthArray.flatten_to(mcflat); + pc.outputs().snapshot(Output{gDataOriginTPC, "CLUSTERHWMCLBL", fanSpec, Lifetime::Timeframe, {*sectorHeader}}, mcflat); } }; diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 80dc3e2f4c515..8a5360216ba21 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -139,6 +139,21 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec WorkflowSpec specs; + // We provide a special publishing method for labels which have been stored in a split format and need + // to be transformed into a contiguous shareable container before publishing. For other branches/types this returns + // false and the generic RootTreeWriter publishing proceeds + static Reader::SpecialPublishHook hook{[](std::string_view name, ProcessingContext& context, o2::framework::Output const& output, char* data) -> bool { + if (TString(name.data()).Contains("TPCDigitMCTruth") || TString(name.data()).Contains("TPCClusterHwMCTruth") || TString(name.data()).Contains("TPCClusterNativeMCTruth")) { + auto storedlabels = reinterpret_cast<o2::dataformats::IOMCTruthContainerView const*>(data); + o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel> flatlabels; + storedlabels->copyandflatten(flatlabels); + LOG(INFO) << "PUBLISHING CONST LABELS " << flatlabels.getNElements(); + context.outputs().snapshot(output, flatlabels); + return true; + } + return false; + }}; + // The OutputSpec of the PublisherSpec is configured depending on the input // type. Note that the configuration of the dispatch trigger in the main file // needs to be done in accordance. This means, if a new input option is added @@ -146,24 +161,6 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec if (inputType == InputType::Digits) { using Type = std::vector<o2::tpc::Digit>; - // We provide a special publishing method for labels which have been stored in a split format and need - // to be transformed into a contiguous shareable container before publishing. For other branches/types this returns - // false and the generic RootTreeWriter publishing proceeds - static Reader::SpecialPublishHook hook{[](std::string_view name, ProcessingContext& context, o2::framework::Output const& output, char* data) -> bool { - if (TString(name.data()).Contains("TPCDigitMCTruth")) { - auto storedlabels = reinterpret_cast<o2::dataformats::IOMCTruthContainerView const*>(data); - o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel> flatlabels; - storedlabels->copyandflatten(flatlabels); - LOG(INFO) << "PUBLISHING CONST LABELS " << flatlabels.getNElements(); - // for the moment make real MCTruthContainer since this is still expected by reconstruction - o2::dataformats::MCTruthContainer<o2::MCCompLabel> labels; - labels.restore_from(flatlabels.data(), flatlabels.size()); - context.outputs().snapshot(output, labels); - return true; - } - return false; - }}; - specs.emplace_back(o2::tpc::getPublisherSpec<Type>(PublisherConf{ "tpc-digit-reader", "o2sim", @@ -185,7 +182,7 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec OutputSpec{"TPC", "CLUSTERHWMCLBL"}, tpcSectors, laneConfiguration, - }, + &hook}, propagateMC)); } else if (inputType == InputType::Clusters) { specs.emplace_back(o2::tpc::getPublisherSpec(PublisherConf{ @@ -197,7 +194,7 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec OutputSpec{"TPC", "CLNATIVEMCLBL"}, tpcSectors, laneConfiguration, - }, + &hook}, propagateMC)); } else if (inputType == InputType::CompClusters) { // TODO: need to check if we want to store the MC labels alongside with compressed clusters @@ -210,10 +207,10 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec {"clusterbranch", "TPCCompClusters", "Branch with TPC compressed clusters"}, {"clustermcbranch", "TPCClusterNativeMCTruth", "MC label branch"}, OutputSpec{"TPC", "COMPCLUSTERS"}, - OutputSpec{"TPC", "CLNATIVEMCLBL"}, + OutputSpec{"TPC", "CLNATIVEMCLBL"}, // This does not work with labels! std::vector<int>(1, 0), std::vector<int>(1, 0), - }, + &hook}, false)); } else if (inputType == InputType::EncodedClusters) { // TODO: need to check if we want to store the MC labels alongside with encoded clusters @@ -224,10 +221,10 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec {"clusterbranch", "TPCEncodedClusters", "Branch with TPC encoded clusters"}, {"clustermcbranch", "TPCClusterNativeMCTruth", "MC label branch"}, OutputSpec{"TPC", "ENCCLUSTERS"}, - OutputSpec{"TPC", "CLNATIVEMCLBL"}, + OutputSpec{"TPC", "CLNATIVEMCLBL"}, // This does not work with labels! std::vector<int>(1, 0), std::vector<int>(1, 0), - }, + &hook}, false)); } @@ -318,6 +315,15 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec // ------------------------------------------------------------------------------------------- // helper to create writer specs for different types of output + auto fillLabels = [](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& /*ref*/) { + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> labels(labelbuffer); + o2::dataformats::IOMCTruthContainerView outputcontainer; + auto br = framework::RootTreeWriter::remapBranch(branch, &outputcontainer); + outputcontainer.adopt(labelbuffer); + br->Fill(); + br->ResetAddress(); + }; + auto makeWriterSpec = [tpcSectors, laneConfiguration, propagateMC, getIndex, getName](const char* processName, const char* defaultFileName, const char* defaultTreeName, @@ -403,9 +409,9 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec BranchDefinition<const char*>{InputSpec{"data", ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}}, "TPCClusterNative", "databranch"}, - BranchDefinition<MCLabelContainer>{InputSpec{"mc", ConcreteDataTypeMatcher{"TPC", "CLNATIVEMCLBL"}}, - "TPCClusterNativeMCTruth", - "mcbranch"}, + BranchDefinition<std::vector<char>>{InputSpec{"mc", ConcreteDataTypeMatcher{"TPC", "CLNATIVEMCLBL"}}, + "TPCClusterNativeMCTruth", + "mcbranch", fillLabels}, caClusterer || decompressTPC)); } diff --git a/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx b/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx index c09db2c6395dd..9e78c98c2e40b 100644 --- a/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx +++ b/EventVisualisation/Detectors/src/DataInterpreterTPC.cxx @@ -60,7 +60,7 @@ std::unique_ptr<VisualisationEvent> DataInterpreterTPC::interpretDataForType(TOb auto access = std::make_unique<o2::tpc::ClusterNativeAccess>(); std::unique_ptr<tpc::ClusterNative[]> clusterBuffer; - tpc::MCLabelContainer clusterMCBuffer; + tpc::ClusterNativeHelper::ConstMCLabelContainerViewWithBuffer clusterMCBuffer; reader->fillIndex(*access, clusterBuffer, clusterMCBuffer); diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index c3b5919206a41..e04ee771ef7ac 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -58,6 +58,8 @@ namespace dataformats { template <class T> class MCTruthContainer; +template <class T> +class ConstMCTruthContainerView; } // namespace dataformats } // namespace o2 diff --git a/GPU/GPUTracking/Base/GPUHostDataTypes.h b/GPU/GPUTracking/Base/GPUHostDataTypes.h index f87f49f251e0a..ac8e29b54ef1b 100644 --- a/GPU/GPUTracking/Base/GPUHostDataTypes.h +++ b/GPU/GPUTracking/Base/GPUHostDataTypes.h @@ -28,6 +28,7 @@ #include <array> #include "DataFormatsTPC/Constants.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" namespace GPUCA_NAMESPACE @@ -36,7 +37,7 @@ namespace gpu { struct GPUTPCDigitsMCInput { - std::array<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*, o2::tpc::constants::MAXSECTOR> v; + std::array<const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>*, o2::tpc::constants::MAXSECTOR> v; }; struct GPUTPCClusterMCInterim { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index ca064bdc642e0..7974a0cc39dc4 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1328,12 +1328,23 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } } - static o2::dataformats::MCTruthContainer<o2::MCCompLabel> mcLabels; + ClusterNativeAccess::ConstMCLabelContainerView* mcLabelsConstView = nullptr; + if (propagateMCLabels) { + // TODO: write to buffer directly + o2::dataformats::MCTruthContainer<o2::MCCompLabel> mcLabels; + if (mOutputClusterLabels == nullptr || !mOutputClusterLabels->OutputAllocator) { + throw std::runtime_error("Cluster MC Label buffer missing"); + } + ClusterNativeAccess::ConstMCLabelContainerViewWithBuffer* container = reinterpret_cast<ClusterNativeAccess::ConstMCLabelContainerViewWithBuffer*>(mOutputClusterLabels->OutputAllocator(0)); - assert(propagateMCLabels ? mcLinearLabels.header.size() == nClsTotal : true); - assert(propagateMCLabels ? mcLinearLabels.data.size() >= nClsTotal : true); + assert(propagateMCLabels ? mcLinearLabels.header.size() == nClsTotal : true); + assert(propagateMCLabels ? mcLinearLabels.data.size() >= nClsTotal : true); - mcLabels.setFrom(mcLinearLabels.header, mcLinearLabels.data); + mcLabels.setFrom(mcLinearLabels.header, mcLinearLabels.data); + mcLabels.flatten_to(container->first); + container->second = container->first; + mcLabelsConstView = &container->second; + } if (buildNativeHost && buildNativeGPU && GetProcessingSettings().delayedOutput) { mInputsHost->mNClusterNative = mInputsShadow->mNClusterNative = nClsTotal; @@ -1345,7 +1356,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (buildNativeHost) { tmpNative->clustersLinear = mInputsHost->mPclusterNativeOutput; - tmpNative->clustersMCTruth = propagateMCLabels ? &mcLabels : nullptr; + tmpNative->clustersMCTruth = mcLabelsConstView; tmpNative->setOffsetPtrs(); mIOPtrs.clustersNative = tmpNative; } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 70ec3d49cee99..2854672ee304c 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -168,6 +168,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void SetOutputControlCompressedClusters(GPUOutputControl* v) { mOutputCompressedClusters = v; } void SetOutputControlClustersNative(GPUOutputControl* v) { mOutputClustersNative = v; } void SetOutputControlTPCTracks(GPUOutputControl* v) { mOutputTPCTracks = v; } + void SetOutputControlClusterLabels(GPUOutputControl* v) { mOutputClusterLabels = v; } const void* mConfigDisplay = nullptr; // Abstract pointer to Standalone Display Configuration Structure const void* mConfigQA = nullptr; // Abstract pointer to Standalone QA Configuration Structure @@ -238,6 +239,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega GPUOutputControl* mOutputCompressedClusters = nullptr; GPUOutputControl* mOutputClustersNative = nullptr; GPUOutputControl* mOutputTPCTracks = nullptr; + GPUOutputControl* mOutputClusterLabels = nullptr; std::unique_ptr<GPUTPCCFChainContext> mCFContext; diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 3fc2220dd146d..6d040e667b6e7 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -64,6 +64,10 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) mOutputTPCTracks.reset(new GPUOutputControl); mChain->SetOutputControlTPCTracks(mOutputTPCTracks.get()); } + if (mConfig->configProcessing.runMC) { + mOutputTPCClusterLabels.reset(new GPUOutputControl); + mChain->SetOutputControlClusterLabels(mOutputTPCClusterLabels.get()); + } if (mRec->Init()) { return (1); @@ -131,6 +135,13 @@ int GPUTPCO2Interface::RunTracking(GPUTrackingInOutPointers* data, GPUInterfaceO mOutputTPCTracks->reset(); } } + if (mConfig->configProcessing.runMC) { + if (outputs->clusterLabels.allocator) { + mOutputTPCClusterLabels->set(outputs->clusterLabels.allocator); + } else { + mOutputTPCClusterLabels->reset(); + } + } int retVal = mRec->RunChains(); if (retVal == 2) { retVal = 0; // 2 signals end of event display, ignore diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.h b/GPU/GPUTracking/Interface/GPUO2Interface.h index af22dfd7ced58..6fdf163d9b84c 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.h +++ b/GPU/GPUTracking/Interface/GPUO2Interface.h @@ -75,6 +75,7 @@ class GPUTPCO2Interface std::unique_ptr<GPUOutputControl> mOutputCompressedClusters; std::unique_ptr<GPUOutputControl> mOutputClustersNative; std::unique_ptr<GPUOutputControl> mOutputTPCTracks; + std::unique_ptr<GPUOutputControl> mOutputTPCClusterLabels; }; } // namespace o2::gpu diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index b7dda0118f17f..8f47fbdb304af 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -63,6 +63,7 @@ struct GPUInterfaceOutputs { GPUInterfaceOutputRegion compressedClusters; GPUInterfaceOutputRegion clustersNative; GPUInterfaceOutputRegion tpcTracks; + GPUInterfaceOutputRegion clusterLabels; }; // Full configuration structure with all available settings of GPU... @@ -108,7 +109,7 @@ struct GPUO2InterfaceIOPtrs { // Input: TPC clusters in cluster native format, or digits, or list of ZS pages - const as it can only be input const o2::tpc::ClusterNativeAccess* clusters = nullptr; const std::array<gsl::span<const o2::tpc::Digit>, o2::tpc::constants::MAXSECTOR>* o2Digits = nullptr; - std::array<const o2::dataformats::MCTruthContainer<o2::MCCompLabel>*, o2::tpc::constants::MAXSECTOR>* o2DigitsMC = nullptr; + std::array<const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>*, o2::tpc::constants::MAXSECTOR>* o2DigitsMC = nullptr; const o2::gpu::GPUTrackingInOutZS* tpcZS = nullptr; // Input / Output for Merged TPC tracks, two ptrs, for the tracks themselves, and for the MC labels. diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 1a836b55e1bc3..202166a46a28e 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -43,6 +43,7 @@ #include "GPUParam.inc" #ifdef GPUCA_O2_LIB #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/TrackReference.h" @@ -160,6 +161,7 @@ static const GPUQA::configQA& GPUQA_GetConfig(GPUChainTracking* rec) #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" inline unsigned int GPUQA::GetNMCCollissions() { diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index 26f3c99b2b68c..abec35440f3a5 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -29,6 +29,8 @@ namespace dataformats { template <typename TruthElement> class MCTruthContainer; +template <typename TruthElement> +class ConstMCTruthContainerView; } // namespace dataformats namespace tpc @@ -111,7 +113,7 @@ class GPUTPCClusterFinder : public GPUProcessor int* mPbuf = nullptr; Memory* mPmemory = nullptr; - o2::dataformats::MCTruthContainer<o2::MCCompLabel> const* mPinputLabels = nullptr; + o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel> const* mPinputLabels = nullptr; uint* mPlabelsInRow = nullptr; uint mPlabelsHeaderGlobalOffset = 0; uint mPlabelsDataGlobalOffset = 0; diff --git a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx index a408b2763ff4d..96300ad3883a3 100644 --- a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.cxx @@ -33,7 +33,7 @@ void MCLabelAccumulator::collect(const ChargePos& pos, Charge q) uint index = mIndexMap[pos]; - auto labels = mLabels->getLabels(index); + const auto& labels = mLabels->getLabels(index); for (const auto& label : labels) { int h = label.getRawValue() % mMaybeHasLabel.size(); diff --git a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h index ca52c15c69900..a81f0e940d21b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h +++ b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h @@ -23,7 +23,7 @@ namespace o2::dataformats { template <typename T> -class MCTruthContainer; +class ConstMCTruthContainerView; } // namespace o2::dataformats namespace GPUCA_NAMESPACE::gpu @@ -45,7 +45,7 @@ class MCLabelAccumulator void commit(tpccf::Row, uint, uint); private: - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabelContainer = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; Array2D<const uint> mIndexMap; const MCLabelContainer* mLabels = nullptr; From d3f19981146a27d7138286d5410fbc1d1e9b3973 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 7 Oct 2020 14:58:46 +0200 Subject: [PATCH 0889/1751] Don't try to run the ca-clusterer on the cluster-input --- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 8a5360216ba21..d7e3f72fdfdca 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -117,6 +117,9 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec zsOnTheFly = false; propagateMC = false; } + if (inputType == InputType::ClustersHardware || inputType == InputType::Clusters) { + caClusterer = false; + } if (!caClusterer) { zsOnTheFly = false; } From 40ca036cfbefb4d25a4cf24e68b4ce04504bca97 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 7 Oct 2020 15:43:07 +0200 Subject: [PATCH 0890/1751] Remove unnecessary includes and fix compiler warnings --- .../include/DataFormatsTPC/ClusterNativeHelper.h | 1 - .../SimulationDataFormat/ConstMCTruthContainer.h | 16 ++++++++++------ .../simulation/test/testMCTruthContainer.cxx | 1 - .../ITSMFT/ITS/workflow/src/ClustererSpec.cxx | 1 - .../ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx | 1 - .../ITSMFT/MFT/workflow/src/ClustererSpec.cxx | 1 - .../include/TPCReconstruction/Clusterer.h | 1 - .../include/TPCReconstruction/ClustererTask.h | 1 - .../include/TPCReconstruction/HwClusterer.h | 1 - .../TPC/reconstruction/src/GPUCATracking.cxx | 1 - .../reconstruction/test/testTPCHwClusterer.cxx | 1 - Detectors/TPC/workflow/src/CATrackerSpec.cxx | 1 - .../TPC/workflow/src/ClusterDecoderRawSpec.cxx | 1 - Detectors/TPC/workflow/src/RecoWorkflow.cxx | 1 - Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx | 1 - .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 1 - GPU/GPUTracking/Base/GPUHostDataTypes.h | 1 - GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 -- Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx | 1 - .../src/ITSMFTDigitizerSpec.cxx | 1 - Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h | 1 - .../DigitizerWorkflow/src/MCTruthSourceSpec.cxx | 1 - .../DigitizerWorkflow/src/MCTruthWriterSpec.cxx | 1 - Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx | 1 - macro/readITSDigits.C | 1 - 25 files changed, 10 insertions(+), 31 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h index 9370132e74eab..6834b7b6c9838 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h @@ -18,7 +18,6 @@ #include "DataFormatsTPC/ClusterNative.h" #include "DataFormatsTPC/ClusterGroupAttribute.h" #include "DataFormatsTPC/Constants.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <gsl/gsl> diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h index 30473cd598a9b..7d089a48bc127 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -16,7 +16,9 @@ #define O2_CONSTMCTRUTHCONTAINER_H #include <SimulationDataFormat/MCTruthContainer.h> +#ifndef GPUCA_STANDALONE #include <Framework/Traits.h> +#endif namespace o2 { @@ -77,7 +79,7 @@ class ConstMCTruthContainer : public std::vector<char> /// 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 + TruthElement const* getLabelStart() const { auto* source = &(*this)[0]; auto flatheader = getHeader(); @@ -94,7 +96,7 @@ class ConstMCTruthContainer : public std::vector<char> return flatheader; } - MCTruthHeaderElement const* const getHeaderStart() const + MCTruthHeaderElement const* getHeaderStart() const { auto* source = &(*this)[0]; source += sizeof(FlatHeader); @@ -108,12 +110,14 @@ class ConstMCTruthContainer : public std::vector<char> // In particular in enables // a) --> snapshot without ROOT dictionary (as a flat buffer) // b) --> requesting the resource in shared mem using make<T> +#ifndef GPUCA_STANDALONE namespace o2::framework { template <typename T> struct is_specialization<o2::dataformats::ConstMCTruthContainer<T>, std::vector> : std::true_type { }; } // namespace o2::framework +#endif namespace o2 { @@ -149,10 +153,10 @@ class ConstMCTruthContainerView } // return the number of original data indexed here - size_t getIndexedSize() const { return mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofHeaderElements : 0; } + size_t getIndexedSize() const { return (size_t)mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofHeaderElements : 0; } // return the number of labels managed in this container - size_t getNElements() const { return mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofTruthElements : 0; } + size_t getNElements() const { return (size_t)mStorage.size() >= sizeof(FlatHeader) ? getHeader().nofTruthElements : 0; } // return underlying buffer const gsl::span<const char>& getBuffer() const { return mStorage; } @@ -174,7 +178,7 @@ class ConstMCTruthContainerView /// 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 + TruthElement const* getLabelStart() const { auto* source = &(mStorage)[0]; auto flatheader = getHeader(); @@ -191,7 +195,7 @@ class ConstMCTruthContainerView return flatheader; } - MCTruthHeaderElement const* const getHeaderStart() const + MCTruthHeaderElement const* getHeaderStart() const { auto* source = &(mStorage)[0]; source += sizeof(FlatHeader); diff --git a/DataFormats/simulation/test/testMCTruthContainer.cxx b/DataFormats/simulation/test/testMCTruthContainer.cxx index 725e0eb9015cb..8e5b66ba826d6 100644 --- a/DataFormats/simulation/test/testMCTruthContainer.cxx +++ b/DataFormats/simulation/test/testMCTruthContainer.cxx @@ -12,7 +12,6 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include <boost/test/unit_test.hpp> -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/LabelContainer.h" diff --git a/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx index 44eb438772380..094b60ec5370d 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/ClustererSpec.cxx @@ -21,7 +21,6 @@ #include "DataFormatsITSMFT/CompCluster.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsParameters/GRPObject.h" #include "ITSMFTReconstruction/DigitPixelReader.h" diff --git a/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx index 6b916a7c994a5..c5c4d7f77170f 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/DigitReaderSpec.cxx @@ -11,7 +11,6 @@ /// @file DigitReaderSpec.cxx #include <vector> -#include <SimulationDataFormat/ConstMCTruthContainer.h> #include "TTree.h" diff --git a/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx index 8b305e9679152..388f18514b414 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/ClustererSpec.cxx @@ -19,7 +19,6 @@ #include "ITSMFTReconstruction/ChipMappingMFT.h" #include "DataFormatsITSMFT/CompCluster.h" #include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsParameters/GRPObject.h" diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h index 7bcf1a2427782..44ea93474d709 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h @@ -17,7 +17,6 @@ #include <vector> #include <memory> -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h index d2919848df2e9..b06b425b1be19 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h @@ -20,7 +20,6 @@ #include "DataFormatsTPC/Digit.h" #include "TPCReconstruction/HwClusterer.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "DataFormatsTPC/Helpers.h" diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h index 2068ca4360fc3..6e9eb0a3043d3 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h @@ -20,7 +20,6 @@ #include "TPCReconstruction/Clusterer.h" #include "DataFormatsTPC/Helpers.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 1e26fc0bd4d03..14bc0cdbe3488 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -16,7 +16,6 @@ #include "FairLogger.h" #include "ReconstructionDataFormats/Track.h" #include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "TChain.h" #include "TClonesArray.h" diff --git a/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx b/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx index d647cc5d9f295..894be89b72b00 100644 --- a/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx +++ b/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx @@ -21,7 +21,6 @@ #include "TPCBase/Mapper.h" #include "TPCReconstruction/HwClusterer.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 92dc7c39b9dcf..e0c900626474e 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -50,7 +50,6 @@ #include "DataFormatsParameters/GRPObject.h" #include "TPCBase/Sector.h" #include "TPCBase/Utils.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "Algorithm/Parser.h" diff --git a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx index 0816b5650760f..594220d68dee4 100644 --- a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx @@ -22,7 +22,6 @@ #include "DataFormatsTPC/ClusterHardware.h" #include "DataFormatsTPC/Helpers.h" #include "TPCReconstruction/HardwareClusterDecoder.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <FairMQLogger.h> diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index d7e3f72fdfdca..466a92968d074 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -32,7 +32,6 @@ #include "DataFormatsTPC/TPCSectorHeader.h" #include "DataFormatsTPC/CompressedClusters.h" #include "DataFormatsTPC/ZeroSuppression.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/IOMCTruthContainerView.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx index 2f464bb9aa724..7093d336e369a 100644 --- a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx @@ -19,7 +19,6 @@ #include "Steer/HitProcessingManager.h" // for DigitizationContext #include "TChain.h" #include <SimulationDataFormat/MCCompLabel.h> -#include <SimulationDataFormat/MCTruthContainer.h> #include <SimulationDataFormat/ConstMCTruthContainer.h> #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 1e3676e69212c..37d5ae14deff7 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -35,7 +35,6 @@ #include "Steer/HitProcessingManager.h" // for DigitizationContext #include "TChain.h" #include <SimulationDataFormat/MCCompLabel.h> -#include <SimulationDataFormat/MCTruthContainer.h> #include <SimulationDataFormat/ConstMCTruthContainer.h> #include "fairlogger/Logger.h" #include "CCDB/BasicCCDBManager.h" diff --git a/GPU/GPUTracking/Base/GPUHostDataTypes.h b/GPU/GPUTracking/Base/GPUHostDataTypes.h index ac8e29b54ef1b..d46826d283768 100644 --- a/GPU/GPUTracking/Base/GPUHostDataTypes.h +++ b/GPU/GPUTracking/Base/GPUHostDataTypes.h @@ -27,7 +27,6 @@ #include <vector> #include <array> #include "DataFormatsTPC/Constants.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 202166a46a28e..6c25f4f666389 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -42,7 +42,6 @@ #include "GPUO2DataTypes.h" #include "GPUParam.inc" #ifdef GPUCA_O2_LIB -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTrack.h" @@ -160,7 +159,6 @@ static const GPUQA::configQA& GPUQA_GetConfig(GPUChainTracking* rec) #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" inline unsigned int GPUQA::GetNMCCollissions() diff --git a/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx index 6ee391f2a8475..4b72eeb32dbaa 100644 --- a/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/FDDDigitizerSpec.cxx @@ -18,7 +18,6 @@ #include "Headers/DataHeader.h" #include "Steer/HitProcessingManager.h" // for DigitizationContext #include "DetectorsBase/BaseDPLDigitizer.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx index 5f96a58e235ee..e8e5f66cd2b57 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx @@ -18,7 +18,6 @@ #include "Headers/DataHeader.h" #include "Steer/HitProcessingManager.h" // for DigitizationContext #include "DataFormatsITSMFT/Digit.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "DetectorsBase/BaseDPLDigitizer.h" #include "DetectorsCommonDataFormats/DetID.h" diff --git a/Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h b/Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h index 1be0084edd2ce..eb507f4d4afe1 100644 --- a/Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h +++ b/Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h @@ -16,7 +16,6 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/DataRefUtils.h" #include "Framework/Lifetime.h" -#include <SimulationDataFormat/MCTruthContainer.h> #include <SimulationDataFormat/ConstMCTruthContainer.h> #include <SimulationDataFormat/MCCompLabel.h> #include "SimulationDataFormat/IOMCTruthContainerView.h" diff --git a/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx b/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx index 759c5edfffacd..c80ae833cb31b 100644 --- a/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx +++ b/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx @@ -13,7 +13,6 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/DataRefUtils.h" #include "Framework/Lifetime.h" -#include <SimulationDataFormat/MCTruthContainer.h> #include <SimulationDataFormat/ConstMCTruthContainer.h> #include <SimulationDataFormat/MCCompLabel.h> #include "Framework/Task.h" diff --git a/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx b/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx index 96dc0628d5ceb..b35db1ad01954 100644 --- a/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx +++ b/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx @@ -13,7 +13,6 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/DataRefUtils.h" #include "Framework/Lifetime.h" -#include <SimulationDataFormat/MCTruthContainer.h> #include <SimulationDataFormat/ConstMCTruthContainer.h> #include <SimulationDataFormat/MCCompLabel.h> #include "SimulationDataFormat/IOMCTruthContainerView.h" diff --git a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx index e5e4308e2f4a8..f35c3b30856d4 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx @@ -22,7 +22,6 @@ #include "TChain.h" #include "TSystem.h" #include <SimulationDataFormat/MCCompLabel.h> -#include <SimulationDataFormat/MCTruthContainer.h> #include <SimulationDataFormat/ConstMCTruthContainer.h> #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" diff --git a/macro/readITSDigits.C b/macro/readITSDigits.C index 33257a1493fb7..2fef209670934 100644 --- a/macro/readITSDigits.C +++ b/macro/readITSDigits.C @@ -9,7 +9,6 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITSMFT/Digit.h" #include "SimulationDataFormat/DigitizationContext.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/IOMCTruthContainerView.h" #include "SimulationDataFormat/MCCompLabel.h" From 13c008b4576e60b3e7ed5d5a955365c4e529cf34 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 8 Oct 2020 20:01:43 +0200 Subject: [PATCH 0891/1751] Unify redundant definitions of MCLabelContainer and clean up conflicting definitions --- .../DataFormatsTPC/ClusterNativeHelper.h | 5 ++-- .../ConstMCTruthContainer.h | 3 +++ .../SimulationDataFormat/MCTruthContainer.h | 4 +++ Detectors/CPV/workflow/src/RecoWorkflow.cxx | 4 +-- Detectors/EMCAL/workflow/src/RecoWorkflow.cxx | 10 +++---- Detectors/PHOS/workflow/src/RecoWorkflow.cxx | 17 +++++------- .../include/TOFReconstruction/Clusterer.h | 2 +- .../include/TOFReconstruction/ClustererTask.h | 9 +++---- .../TOF/workflow/src/TOFClusterizerSpec.cxx | 2 +- .../include/TPCReconstruction/Clusterer.h | 7 ++--- .../include/TPCReconstruction/ClustererTask.h | 8 ++---- .../include/TPCReconstruction/HwClusterer.h | 7 ++--- .../TPC/reconstruction/macro/readClusters.C | 2 +- .../TPC/reconstruction/src/ClustererTask.cxx | 1 + .../TPC/reconstruction/src/GPUCATracking.cxx | 2 -- .../test/testTPCHwClusterer.cxx | 8 ++---- .../simulation/run/convertDigitsToRawZS.cxx | 2 +- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 4 +-- .../workflow/src/ClusterDecoderRawSpec.cxx | 6 +---- Detectors/TPC/workflow/src/ClustererSpec.cxx | 5 +--- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 27 +++++++++---------- .../TPC/workflow/test/test_TPCWorkflow.cxx | 4 +-- .../TPCClusterFinder/MCLabelAccumulator.h | 15 ++++++----- .../src/TPCDigitRootWriterSpec.cxx | 1 - macro/runCATrackingClusterNative.C | 2 -- 25 files changed, 64 insertions(+), 93 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h index 6834b7b6c9838..bfe9bad7a5458 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h @@ -131,9 +131,8 @@ struct alignas(64) ClusterIndexBuffer { class ClusterNativeHelper { public: - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; - using ConstMCLabelContainer = ClusterNativeAccess::ConstMCLabelContainer; - using ConstMCLabelContainerView = ClusterNativeAccess::ConstMCLabelContainerView; + using MCLabelContainer = o2::dataformats::MCLabelContainer; + using ConstMCLabelContainerView = o2::dataformats::ConstMCLabelContainerView; using ConstMCLabelContainerViewWithBuffer = ClusterNativeAccess::ConstMCLabelContainerViewWithBuffer; ClusterNativeHelper() = default; diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h index 7d089a48bc127..6e0d30f593956 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -203,6 +203,9 @@ class ConstMCTruthContainerView } }; +using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; +using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; + } // namespace dataformats } // namespace o2 diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h index 65d3ba4876121..ed5391da4f803 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h @@ -30,8 +30,10 @@ namespace o2 { +class MCCompLabel; namespace dataformats { + /// @struct MCTruthHeaderElement /// @brief Simple struct having information about truth elements for particular indices: /// how many associations we have and where they start in the storage @@ -415,6 +417,8 @@ class MCTruthContainer ClassDefNV(MCTruthContainer, 2); }; // end class +using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + } // namespace dataformats } // namespace o2 diff --git a/Detectors/CPV/workflow/src/RecoWorkflow.cxx b/Detectors/CPV/workflow/src/RecoWorkflow.cxx index 0f73562af8901..50d860a856c25 100644 --- a/Detectors/CPV/workflow/src/RecoWorkflow.cxx +++ b/Detectors/CPV/workflow/src/RecoWorkflow.cxx @@ -30,6 +30,8 @@ #include "Framework/DataSpecUtils.h" #include "SimulationDataFormat/MCTruthContainer.h" +using namespace o2::dataformats; + namespace o2 { @@ -163,7 +165,6 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, // if (isEnabled(OutputType::Raw)) { // using RawOutputType = std::vector<o2::cpv::Raw>; - // using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; // specs.push_back(makeWriterSpec("cpv-raw-writer", // inputType == InputType::Digits ? "cpv-raw.root" : "cpvrawcells.root", // "o2sim", @@ -178,7 +179,6 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, if (isEnabled(OutputType::Digits)) { using DigitOutputType = std::vector<o2::cpv::Digit>; using DTROutputType = std::vector<o2::cpv::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("cpv-digits-writer", "cpvdigits.root", "o2sim", -1, diff --git a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx index 697002b08c7e4..d7c7fb7f03446 100644 --- a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx +++ b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx @@ -248,7 +248,6 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, if (isEnabled(OutputType::Digits) && !disableRootOutput) { using DigitOutputType = std::vector<o2::emcal::Digit>; using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>; specs.push_back(makeWriterSpec("emcal-digits-writer", inputType == InputType::Digits ? "emc-filtered-digits.root" : "emcdigits.root", "o2sim", @@ -258,7 +257,7 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"trigger", "EMC", "DIGITSTRGR", 0}, "EMCALDigitTRGR", "digittrigger-branch-name"}, - BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "EMC", "DIGITSMCTR", 0}, + BranchDefinition<o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>>{o2::framework::InputSpec{"mc", "EMC", "DIGITSMCTR", 0}, "EMCDigitMCTruth", "digitmc-branch-name"})()); } @@ -267,7 +266,6 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, if (inputType == InputType::Digits) { using DigitOutputType = std::vector<o2::emcal::Cell>; using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>; specs.push_back(makeWriterSpec("emcal-cells-writer", "emccells.root", "o2sim", BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "EMC", "CELLS", 0}, "EMCALCell", @@ -275,9 +273,9 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"trigger", "EMC", "CELLSTRGR", 0}, "EMCALCellTRGR", "celltrigger-branch-name"}, - BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "EMC", "CELLSMCTR", 0}, - "EMCALCellMCTruth", - "cellmc-branch-name"})()); + BranchDefinition<o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>>{o2::framework::InputSpec{"mc", "EMC", "CELLSMCTR", 0}, + "EMCALCellMCTruth", + "cellmc-branch-name"})()); } else { using CellsDataType = std::vector<o2::emcal::Cell>; using TriggerRecordDataType = std::vector<o2::emcal::TriggerRecord>; diff --git a/Detectors/PHOS/workflow/src/RecoWorkflow.cxx b/Detectors/PHOS/workflow/src/RecoWorkflow.cxx index 0f337b0d95a93..2d144debf5662 100644 --- a/Detectors/PHOS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/PHOS/workflow/src/RecoWorkflow.cxx @@ -192,14 +192,13 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, // if (isEnabled(OutputType::Raw)) { // using RawOutputType = std::vector<o2::phos::Raw>; - // using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::phos::MCLabel>; // specs.push_back(makeWriterSpec("phos-raw-writer", // inputType == InputType::Digits ? "phos-raw.root" : "phosrawcells.root", // "o2sim", // BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "PHS", "RAW", 0}, // "PHSRaw", // "raw-branch-name"}, - // BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "PHS", "RAWMCTR", 0}, + // BranchDefinition<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>>{o2::framework::InputSpec{"mc", "PHS", "RAWMCTR", 0}, // "PHSRawMCTruth", // "rawmc-branch-name"})()); // } @@ -207,7 +206,6 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, if (isEnabled(OutputType::Digits)) { using DigitOutputType = std::vector<o2::phos::Digit>; using DTROutputType = std::vector<o2::phos::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::phos::MCLabel>; specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("phos-digits-writer", "phosdigits.root", "o2sim", -1, @@ -218,15 +216,14 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, BranchDefinition<DTROutputType>{o2::framework::InputSpec{"data", "PHS", "DIGITTRIGREC", 0}, "PHSDigTR", "digittr-branch-name"}, - BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "PHS", "DIGITSMCTR", 0}, - "PHSDigitMCTruth", - "digitmc-branch-name"})()); + BranchDefinition<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>>{o2::framework::InputSpec{"mc", "PHS", "DIGITSMCTR", 0}, + "PHSDigitMCTruth", + "digitmc-branch-name"})()); } if (isEnabled(OutputType::Cells)) { using CellOutputType = std::vector<o2::phos::Cell>; using CTROutputType = std::vector<o2::phos::TriggerRecord>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::phos::MCLabel>; specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("phos-cells-writer", "phoscells.root", "o2sim", -1, o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, BranchDefinition<CellOutputType>{o2::framework::InputSpec{"data", "PHS", "CELLS", 0}, @@ -235,9 +232,9 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, BranchDefinition<CTROutputType>{o2::framework::InputSpec{"data", "PHS", "CELLTRIGREC", 0}, "PHSCellTR", "celltr-branch-name"}, - BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "PHS", "CELLSMCTR", 0}, - "PHSCellMCTruth", - "cellmc-branch-name"}, + BranchDefinition<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>>{o2::framework::InputSpec{"mc", "PHS", "CELLSMCTR", 0}, + "PHSCellMCTruth", + "cellmc-branch-name"}, BranchDefinition<std::vector<uint>>{o2::framework::InputSpec{"mcmap", "PHS", "CELLSMCMAP", 0}, "PHSCellMCMAP", "cellmcmap-branch-name"})()); diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h index 11dad2d0dfa19..3049a955c8e26 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h @@ -29,7 +29,7 @@ namespace tof { class Clusterer { - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabelContainer = o2::dataformats::MCLabelContainer; using Cluster = o2::tof::Cluster; using StripData = o2::tof::DataReader::StripData; using Digit = o2::tof::Digit; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/ClustererTask.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/ClustererTask.h index 0e3b2423adeb1..45b0caffa4a24 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/ClustererTask.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/ClustererTask.h @@ -32,9 +32,6 @@ namespace tof class ClustererTask : public FairTask { - - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; - public: ClustererTask(Bool_t useMCTruth = kTRUE); ~ClustererTask() override; @@ -46,9 +43,9 @@ class ClustererTask : public FairTask DigitDataReader mReader; ///< Digit reader Clusterer mClusterer; ///< Cluster finder - std::vector<Cluster>* mClustersArray = nullptr; ///< Array of clusters - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mClsLabels = nullptr; ///< MC labels for output - MCLabelContainer const* mDigitMCTruth; ///< Array for MCTruth information associated to digits + std::vector<Cluster>* mClustersArray = nullptr; ///< Array of clusters + o2::dataformats::MCLabelContainer* mClsLabels = nullptr; ///< MC labels for output + o2::dataformats::MCLabelContainer const* mDigitMCTruth; ///< Array for MCTruth information associated to digits ClassDefOverride(ClustererTask, 1); }; diff --git a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx index d842a59781ef3..eb1149d23fe85 100644 --- a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx @@ -32,6 +32,7 @@ #include "DetectorsRaw/HBFUtils.h" using namespace o2::framework; +using namespace o2::dataformats; namespace o2 { @@ -42,7 +43,6 @@ namespace tof // just need to implement 2 special methods init + run (there is no need to inherit from anything) class TOFDPLClustererTask { - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; bool mUseMC = true; bool mUseCCDB = false; diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h index 44ea93474d709..34405c1de783f 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/Clusterer.h @@ -33,9 +33,6 @@ class Digit; /// \brief Base Class for TPC clusterer class Clusterer { - protected: - using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; - public: /// Default Constructor Clusterer() = default; @@ -49,8 +46,8 @@ class Clusterer /// Processing all digits /// \param digits Container with TPC digits /// \param mcDigitTruth MC Digit Truth container - virtual void process(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) = 0; - virtual void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth) = 0; + virtual void process(gsl::span<o2::tpc::Digit const> const& digits, o2::dataformats::ConstMCLabelContainerView const& mcDigitTruth) = 0; + virtual void finishProcess(gsl::span<o2::tpc::Digit const> const& digits, o2::dataformats::ConstMCLabelContainerView const& mcDigitTruth) = 0; /// Setter for noise object, noise will be added before cluster finding /// \param noiseObject CalDet object, containing noise simulation diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h index b06b425b1be19..071ded988bdf7 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/ClustererTask.h @@ -34,10 +34,6 @@ namespace tpc class ClustererTask : public FairTask { - - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; - using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; - using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; using OutputType = ClusterHardwareContainer8kb; public: @@ -70,11 +66,11 @@ class ClustererTask : public FairTask // Digit arrays std::unique_ptr<const std::vector<Digit>> mDigitsArray; ///< Array of TPC digits - std::unique_ptr<const ConstMCLabelContainerView> mDigitMCTruthArray; ///< Array for MCTruth information associated to digits in mDigitsArrray + std::unique_ptr<const o2::dataformats::ConstMCLabelContainerView> mDigitMCTruthArray; ///< Array for MCTruth information associated to digits in mDigitsArrray // Cluster arrays std::unique_ptr<std::vector<OutputType>> mHwClustersArray; ///< Array of clusters found by Hw Clusterfinder - std::unique_ptr<MCLabelContainer> mHwClustersMCTruthArray; ///< Array for MCTruth information associated to cluster in mHwClustersArrays + std::unique_ptr<o2::dataformats::MCLabelContainer> mHwClustersMCTruthArray; ///< Array for MCTruth information associated to cluster in mHwClustersArrays ClassDefOverride(ClustererTask, 1); }; diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h index 6e9eb0a3043d3..b57d06b8dcd85 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h @@ -39,12 +39,9 @@ class ClusterHardware; /// \brief Class for TPC HW cluster finding class HwClusterer : public Clusterer { - private: - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; - using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; - using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; - + using MCLabelContainer = o2::dataformats::MCLabelContainer; + using ConstMCLabelContainerView = o2::dataformats::ConstMCLabelContainerView; /// Main Constructor HwClusterer( std::vector<ClusterHardwareContainer8kb>* clusterOutputContainer, diff --git a/Detectors/TPC/reconstruction/macro/readClusters.C b/Detectors/TPC/reconstruction/macro/readClusters.C index a969940fb369f..b92021aba8dc3 100644 --- a/Detectors/TPC/reconstruction/macro/readClusters.C +++ b/Detectors/TPC/reconstruction/macro/readClusters.C @@ -47,7 +47,7 @@ void readClusters(std::string clusterFilename, std::string digitFilename, int se std::vector<o2::tpc::Digit>* digits = nullptr; digitBranch->SetAddress(&digits); - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + using MCLabelContainer = o2::dataformats::MCLabelContainer; MCLabelContainer* mcClusterTruth = nullptr; clusterTree->SetBranchAddress(Form("TPCClusterHWMCTruth%i", sectorid), &mcClusterTruth); MCLabelContainer* mcDigitTruth = nullptr; diff --git a/Detectors/TPC/reconstruction/src/ClustererTask.cxx b/Detectors/TPC/reconstruction/src/ClustererTask.cxx index 503a7f4e3201a..831078120784a 100644 --- a/Detectors/TPC/reconstruction/src/ClustererTask.cxx +++ b/Detectors/TPC/reconstruction/src/ClustererTask.cxx @@ -19,6 +19,7 @@ ClassImp(o2::tpc::ClustererTask); using namespace o2::tpc; +using namespace o2::dataformats; //_____________________________________________________________________ ClustererTask::ClustererTask(int sectorid) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 14bc0cdbe3488..63908b70927db 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -45,8 +45,6 @@ using namespace o2::tpc; using namespace o2; using namespace o2::dataformats; -using MCLabelContainer = MCTruthContainer<MCCompLabel>; - GPUCATracking::GPUCATracking() = default; GPUCATracking::~GPUCATracking() { deinitialize(); } diff --git a/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx b/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx index 894be89b72b00..d6edfe6507f42 100644 --- a/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx +++ b/Detectors/TPC/reconstruction/test/testTPCHwClusterer.cxx @@ -28,6 +28,8 @@ #include <memory> #include <iostream> +using MCLabelContainer = o2::dataformats::MCLabelContainer; + namespace o2 { namespace tpc @@ -133,7 +135,6 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test1) { std::cout << "##" << std::endl; std::cout << "## Starting test 1, basic class tests." << std::endl; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; auto clusterArray = std::make_unique<std::vector<ClusterHardwareContainer8kb>>(); auto labelArray = std::make_unique<MCLabelContainer>(); @@ -188,7 +189,6 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test2) { std::cout << "##" << std::endl; std::cout << "## Starting test 2, finding single pad clusters." << std::endl; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; auto clusterArray = std::make_unique<std::vector<o2::tpc::ClusterHardwareContainer8kb>>(); auto labelArray = std::make_unique<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>(); @@ -263,7 +263,6 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test3) { std::cout << "##" << std::endl; std::cout << "## Starting test 3, computing cluster properties." << std::endl; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; auto clusterArray = std::make_unique<std::vector<o2::tpc::ClusterHardwareContainer8kb>>(); auto labelArray = std::make_unique<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>(); @@ -367,7 +366,6 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test4) { std::cout << "##" << std::endl; std::cout << "## Starting test 4, rejecting single pad clusters." << std::endl; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; auto clusterArray = std::make_unique<std::vector<o2::tpc::ClusterHardwareContainer8kb>>(); auto labelArray = std::make_unique<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>(); @@ -587,7 +585,6 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test5) { std::cout << "##" << std::endl; std::cout << "## Starting test 5, rejecting peaks in subsequent." << std::endl; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; auto clusterArray = std::make_unique<std::vector<o2::tpc::ClusterHardwareContainer8kb>>(); auto labelArray = std::make_unique<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>(); @@ -656,7 +653,6 @@ BOOST_AUTO_TEST_CASE(HwClusterer_test6) { std::cout << "##" << std::endl; std::cout << "## Starting test 6, split charge among nearby clusters." << std::endl; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; auto clusterArray = std::make_unique<std::vector<o2::tpc::ClusterHardwareContainer8kb>>(); auto labelArray = std::make_unique<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>(); diff --git a/Detectors/TPC/simulation/run/convertDigitsToRawZS.cxx b/Detectors/TPC/simulation/run/convertDigitsToRawZS.cxx index b8a749b921a8c..fcc06bd746218 100644 --- a/Detectors/TPC/simulation/run/convertDigitsToRawZS.cxx +++ b/Detectors/TPC/simulation/run/convertDigitsToRawZS.cxx @@ -48,12 +48,12 @@ namespace bpo = boost::program_options; using namespace o2::tpc; using namespace o2::gpu; +using namespace o2::dataformats; using o2::MCCompLabel; constexpr static size_t NSectors = o2::tpc::Sector::MAXSECTOR; constexpr static size_t NEndpoints = o2::gpu::GPUTrackingInOutZS::NENDPOINTS; using DigitArray = std::array<gsl::span<const o2::tpc::Digit>, Sector::MAXSECTOR>; -using MCLabelContainer = o2::dataformats::MCTruthContainer<MCCompLabel>; struct ProcessAttributes { std::unique_ptr<unsigned long long int[]> zsoutput; diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index e0c900626474e..4d87a4a5ea17a 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -69,9 +69,7 @@ using namespace o2::framework; using namespace o2::header; using namespace o2::gpu; using namespace o2::base; - -using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; -using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; +using namespace o2::dataformats; namespace o2 { diff --git a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx index 594220d68dee4..66d9b25966598 100644 --- a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx @@ -35,16 +35,12 @@ using namespace o2::framework; using namespace o2::header; +using namespace o2::dataformats; namespace o2 { namespace tpc { - -using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; -using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; -using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; - /// create the processor spec for TPC raw cluster decoder converting TPC raw to native clusters /// Input: raw pages of TPC raw clusters /// Output: vector of containers with clusters in ClusterNative format, one container per diff --git a/Detectors/TPC/workflow/src/ClustererSpec.cxx b/Detectors/TPC/workflow/src/ClustererSpec.cxx index 36d76de3d81a3..59b3336a840cf 100644 --- a/Detectors/TPC/workflow/src/ClustererSpec.cxx +++ b/Detectors/TPC/workflow/src/ClustererSpec.cxx @@ -32,16 +32,13 @@ using namespace o2::framework; using namespace o2::header; +using namespace o2::dataformats; namespace o2 { namespace tpc { -using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; -using ConstMCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; -using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; - /// create a processor spec /// runs the TPC HwClusterer in a DPL process with digits and mc as input DataProcessorSpec getClustererSpec(bool sendMC) diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 466a92968d074..3fac36e48e065 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -50,6 +50,8 @@ #include <array> #include <gsl/span> +using namespace o2::dataformats; + namespace o2 { namespace tpc @@ -366,7 +368,6 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec // selected by output type 'difits' if (isEnabled(OutputType::Digits) && !isEnabled(OutputType::DisableWriter)) { using DigitOutputType = std::vector<o2::tpc::Digit>; - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; specs.push_back(makeWriterSpec("tpc-digits-writer", inputType == InputType::ZSRaw ? "tpc-zs-digits.root" : inputType == InputType::Digits ? "tpc-filtered-digits.root" : "tpcdigits.root", "o2sim", @@ -384,7 +385,6 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec // // selected by output type 'clustershardware' if (isEnabled(OutputType::ClustersHardware) && !isEnabled(OutputType::DisableWriter)) { - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; specs.push_back(makeWriterSpec("tpc-clusterhardware-writer", inputType == InputType::ClustersHardware ? "tpc-filtered-clustershardware.root" : "tpc-clustershardware.root", "tpcclustershardware", @@ -402,7 +402,6 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec // // selected by output type 'clusters' if (isEnabled(OutputType::Clusters) && !isEnabled(OutputType::DisableWriter)) { - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; // if the caClusterer is enabled, only one data set with the full TPC is produced, and the writer // is configured to write one single branch specs.push_back(makeWriterSpec("tpc-native-cluster-writer", @@ -472,23 +471,21 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec using TrackOutputType = std::vector<o2::tpc::TrackTPC>; using ClusRefsOutputType = std::vector<o2::tpc::TPCClRefElem>; - - using MCLabelContainer = std::vector<o2::MCCompLabel>; // a spectator callback which will be invoked by the tree writer with the extracted object // we are using it for printing a log message auto logger = BranchDefinition<TrackOutputType>::Spectator([](TrackOutputType const& tracks) { LOG(INFO) << "writing " << tracks.size() << " track(s)"; }); - auto tracksdef = BranchDefinition<TrackOutputType>{InputSpec{"inputTracks", "TPC", "TRACKS", 0}, // - "TPCTracks", "track-branch-name", // - 1, // - logger}; // - auto clrefdef = BranchDefinition<ClusRefsOutputType>{InputSpec{"inputClusRef", "TPC", "CLUSREFS", 0}, // - "ClusRefs", "trackclusref-branch-name"}; // - auto mcdef = BranchDefinition<MCLabelContainer>{InputSpec{"mcinput", "TPC", "TRACKSMCLBL", 0}, // - "TPCTracksMCTruth", // - (propagateMC ? 1 : 0), // - "trackmc-branch-name"}; // + auto tracksdef = BranchDefinition<TrackOutputType>{InputSpec{"inputTracks", "TPC", "TRACKS", 0}, // + "TPCTracks", "track-branch-name", // + 1, // + logger}; // + auto clrefdef = BranchDefinition<ClusRefsOutputType>{InputSpec{"inputClusRef", "TPC", "CLUSREFS", 0}, // + "ClusRefs", "trackclusref-branch-name"}; // + auto mcdef = BranchDefinition<std::vector<o2::MCCompLabel>>{InputSpec{"mcinput", "TPC", "TRACKSMCLBL", 0}, // + "TPCTracksMCTruth", // + (propagateMC ? 1 : 0), // + "trackmc-branch-name"}; // // depending on the MC propagation flag, branch definition for MC labels is disabled specs.push_back(MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, diff --git a/Detectors/TPC/workflow/test/test_TPCWorkflow.cxx b/Detectors/TPC/workflow/test/test_TPCWorkflow.cxx index e5d3154bfa69f..83c156851f91b 100644 --- a/Detectors/TPC/workflow/test/test_TPCWorkflow.cxx +++ b/Detectors/TPC/workflow/test/test_TPCWorkflow.cxx @@ -21,6 +21,7 @@ #include <TTree.h> using namespace o2; +using namespace o2::dataformats; BOOST_AUTO_TEST_CASE(TPCWorkflow_types) { @@ -30,8 +31,7 @@ BOOST_AUTO_TEST_CASE(TPCWorkflow_types) // even though std::vector < o2::dataformats::MCTruthContainer < o2::MCCompLabel >> // has not been specified in the LinkDef file. But it can only e serialized to a // tree branch if it has been defined. - using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::MCCompLabel>; - MCLabelContainer labels; + dataformats::MCLabelContainer labels; std::vector<MCLabelContainer> containers; const char* filename = "testTPCWorkflowTypes.root"; const char* treename = "testtree"; diff --git a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h index a81f0e940d21b..f839402ba310b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h +++ b/GPU/GPUTracking/TPCClusterFinder/MCLabelAccumulator.h @@ -16,15 +16,20 @@ #include "clusterFinderDefs.h" #include "Array2D.h" -#include "SimulationDataFormat/MCCompLabel.h" #include <bitset> #include <vector> -namespace o2::dataformats +namespace o2 { +class MCCompLabel; +namespace dataformats +{ +class MCCompLabel; template <typename T> class ConstMCTruthContainerView; -} // namespace o2::dataformats +using ConstMCLabelContainerView = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; +} // namespace dataformats +} // namespace o2 namespace GPUCA_NAMESPACE::gpu { @@ -45,10 +50,8 @@ class MCLabelAccumulator void commit(tpccf::Row, uint, uint); private: - using MCLabelContainer = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>; - Array2D<const uint> mIndexMap; - const MCLabelContainer* mLabels = nullptr; + const o2::dataformats::ConstMCLabelContainerView* mLabels = nullptr; GPUTPCClusterMCInterim* mOutput = nullptr; std::bitset<64> mMaybeHasLabel; diff --git a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx index cfaff58868aec..53ca18ec2a4c8 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx @@ -78,7 +78,6 @@ DataProcessorSpec getTPCDigitRootWriterSpec(std::vector<int> const& laneConfigur //branch definitions for RootTreeWriter spec using DigitsOutputType = std::vector<o2::tpc::Digit>; - using MCLabelContainer = o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>; using CommonModeOutputType = std::vector<o2::tpc::CommonMode>; // extracts the sector from header of an input diff --git a/macro/runCATrackingClusterNative.C b/macro/runCATrackingClusterNative.C index 07921750eecb9..95d1f215fbeb9 100644 --- a/macro/runCATrackingClusterNative.C +++ b/macro/runCATrackingClusterNative.C @@ -40,8 +40,6 @@ using namespace o2::tpc; using namespace o2::dataformats; using namespace std; -using MCLabelContainer = MCTruthContainer<o2::MCCompLabel>; - #if !defined(__CLING__) || defined(__ROOTCLING__) // Disable in interpreted mode due to missing rootmaps // This is a prototype of a macro to test running the HLT O2 CA Tracking library on a root input file containg From 0437c3b81597de684557f2fc5002d13b1a59b3c7 Mon Sep 17 00:00:00 2001 From: Timo Wilken <timo.21.wilken@gmail.com> Date: Fri, 9 Oct 2020 09:29:14 +0000 Subject: [PATCH 0892/1751] Fix code-formatting workflow (#4553) * code-formatting workflow: get the correct commit to compare against * code-formatting workflow: adapt line-length detection "git diff $x" doesn't do anything as there are no unstaged changes. We need to tell it what to compare against. The header is also 4 or 5 lines long, depending on whether a file is completely new or not. If we chop 5 lines off, it'll always catch the +++ line and may chop the first @@ line too, which we don't care about. --- .github/workflows/code-formatting.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index d6c21c589e3c0..42145d62efe4c 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -26,7 +26,11 @@ jobs: 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 }} + # github.event.pull_request.base.sha is the latest commit on the branch + # the PR will be merged into, NOT the commit this PR derives from! For + # that, we need to find the latest common ancestor between the PR and + # the branch we are merging into. + BASE_COMMIT=$(git merge-base HEAD ${{ 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)" @@ -41,7 +45,7 @@ jobs: # 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 ;; + git diff $BASE_COMMIT $x | tail -n +6 | 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 From baab712404b44f32718cfd1555851ab685cfbfe9 Mon Sep 17 00:00:00 2001 From: Timo Wilken <timo.21.wilken@gmail.com> Date: Fri, 9 Oct 2020 12:29:17 +0000 Subject: [PATCH 0893/1751] code-formatting workflow: fetch all history (#4559) We don't know how far back the last common ancestor commit between dev and the PR is, so fetch everything. Co-authored-by: ALICE Action Bot <alibuild@cern.ch> --- .github/workflows/code-formatting.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 42145d62efe4c..dbea9bdc2b1f0 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -11,6 +11,10 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false + # We need the history of the dev branch all the way back to where the PR + # diverged. We're fetching everything here, as we don't know how many + # commits back that point is. + fetch-depth: 0 - name: Run clang format id: clang_format env: From 66561d9b5870f72b339028644695aca6cce39561 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Fri, 9 Oct 2020 17:35:17 +0200 Subject: [PATCH 0894/1751] support adding also lvalue shared_ptrs (#4539) --- Analysis/Core/include/Analysis/HistHelpers.h | 3 +- Analysis/Tutorials/src/histHelpersTest.cxx | 29 +++++--------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/Analysis/HistHelpers.h index 49e7a5b8934d1..55fd75b5c4f88 100644 --- a/Analysis/Core/include/Analysis/HistHelpers.h +++ b/Analysis/Core/include/Analysis/HistHelpers.h @@ -78,7 +78,7 @@ class HistContainer : private RootContainer // if shared pointers or rvalue raw pointers are provided as argument, the existing object is used // otherwise the existing object is copied std::optional<HistType> histVariant{}; - if constexpr (is_shared_ptr<T>::value) + if constexpr (is_shared_ptr<typename std::remove_reference<T>::type>::value) histVariant = GetHistVariant(hist); else if constexpr (std::is_pointer_v<T> && std::is_rvalue_reference_v<decltype(std::forward<T>(hist))>) histVariant = GetHistVariant(std::shared_ptr<std::remove_pointer_t<T>>(hist)); @@ -201,6 +201,7 @@ class Hist { public: Hist() : mAxes{} {} + Hist(const std::vector<Axis>& axes) : mAxes{axes} {} void AddAxis(const Axis& axis) { diff --git a/Analysis/Tutorials/src/histHelpersTest.cxx b/Analysis/Tutorials/src/histHelpersTest.cxx index 9f3042cd5e3d6..8037582e52ccc 100644 --- a/Analysis/Tutorials/src/histHelpersTest.cxx +++ b/Analysis/Tutorials/src/histHelpersTest.cxx @@ -98,22 +98,13 @@ struct HistHelpersTest { const int nCuts = 5; Axis cutAxis = {"cut", "cut setting", {-0.5, nCuts - 0.5}, nCuts}; - Hist myHistogram; - myHistogram.AddAxis(ptAxis); - myHistogram.AddAxis(etaAxis); - myHistogram.AddAxis("signed1Pt", "q/p_{T}", 200, -8, 8); + Hist myHistogram({ptAxis, etaAxis, {"signed1Pt", "q/p_{T}", {-8, 8}, 200}}); test->Add<test_3d_THnI>(myHistogram.Create<THnI>("test_3d_THnI")); - Hist testSparseHist; - testSparseHist.AddAxis(ptAxis); - testSparseHist.AddAxis(etaAxis); - testSparseHist.AddAxis(phiAxis); - testSparseHist.AddAxis(centAxis); - testSparseHist.AddAxis(cutAxis); + Hist testSparseHist({ptAxis, etaAxis, phiAxis, centAxis, cutAxis}); test->Add<test_5d_THnSparseI>(testSparseHist.Create<THnSparseI>("test_5d_THnSparseI")); - Hist testProfile; - testProfile.AddAxis(ptAxis); + Hist testProfile({ptAxis}); test->Add<test_1d_TProfile>(testProfile.Create<TProfile>("test_1d_TProfile")); test->Get<TProfile>(test_1d_TProfile)->GetYaxis()->SetTitle("eta profile"); @@ -132,19 +123,13 @@ struct HistHelpersTest { test->Add<test_3d_TProfile3D>(testProfile3d.Create<TProfile3D>("test_3d_TProfile3D")); // we can also re-use axis definitions in case they are similar in many histograms: - Hist baseDimensions; - baseDimensions.AddAxis(ptAxis); - baseDimensions.AddAxis(etaAxis); - baseDimensions.AddAxis(phiAxis); - baseDimensions.AddAxis(centAxis); - baseDimensions.AddAxis(cutAxis); - baseDimensions.AddAxis(centAxis); - - Hist firstHist = baseDimensions; + Hist baseDimensions({ptAxis, etaAxis, phiAxis, centAxis, cutAxis, centAxis}); + + Hist firstHist{baseDimensions}; firstHist.AddAxis("something", "v (m/s)", 10, -1, 1); test->Add<test_7d_THnF_first>(firstHist.Create<THnF>("test_7d_THnF_first")); - Hist secondHist = baseDimensions; + Hist secondHist{baseDimensions}; secondHist.AddAxis("somethingElse", "a (m/(s*s))", 10, -1, 1); test->Add<test_7d_THnF_second>(secondHist.Create<THnF>("test_7d_THnF_second")); From 899ce7c74ebc927ccf1fc698336a290578564987 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 8 Oct 2020 14:43:53 +0200 Subject: [PATCH 0895/1751] Reenable sim test; Add additional checks also refactored environment handling for sim tests --- run/CMakeLists.txt | 85 +++++++++++++++++++++++++++++----------------- run/simlogcheck.sh | 28 +++++++++++++++ 2 files changed, 82 insertions(+), 31 deletions(-) create mode 100755 run/simlogcheck.sh diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index 18baf220c4dce..5ad1e169afb20 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -108,6 +108,11 @@ o2_data_file(COPY o2simtopology.json DESTINATION config) set(SIMTESTDIR ${CMAKE_BINARY_DIR}/o2sim_tests) file(MAKE_DIRECTORY ${SIMTESTDIR}) +# define environment needed for simulation tests (during build phase) +# needed because the build environment is different to runtime environment +set(SIMENV "ALICE_O2SIM_DUMPLOG=ON;O2_ROOT=${CMAKE_BINARY_DIR}/stage;VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/share;ROOT_INCLUDE_PATH=$ENV{ROOT_INCLUDE_PATH}:$ENV{HEPMC3_ROOT}/include;ROOT_DYN_PATH=$ENV{ROOTSYS}/lib") +message(STATUS "SIMENV = ${SIMENV}") + o2_name_target(sim NAME o2simExecutable IS_EXE) o2_name_target(sim-serial NAME o2simSerialExecutable IS_EXE) @@ -125,16 +130,13 @@ o2_add_test_wrapper(NAME o2sim_G4 TGeant4 -o o2simG4 + ENVIRONMENT "${SIMENV}" LABELS "g4;sim;long") set_tests_properties(o2sim_G4 PROPERTIES PASS_REGULAR_EXPRESSION "SIMULATION RETURNED SUCCESFULLY" FIXTURES_SETUP G4) -set_property(TEST o2sim_G4 APPEND PROPERTY ENVIRONMENT - ALICE_O2SIM_DUMPLOG=ON - O2_ROOT=${CMAKE_BINARY_DIR}/stage - VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/share) set_property(TEST o2sim_G4 APPEND PROPERTY ENVIRONMENT ${G4ENV}) # # note that the MT is currently only supported in the non FairMQ version @@ -152,13 +154,11 @@ o2_add_test_wrapper(NAME o2sim_G4_mt on -o o2simG4MT + ENVIRONMENT "${SIMENV}" LABELS "g4;sim;long") set_tests_properties(o2sim_G4_mt PROPERTIES PASS_REGULAR_EXPRESSION "Macro finished succesfully") -set_property(TEST o2sim_G4_mt APPEND PROPERTY ENVIRONMENT - O2_ROOT=${CMAKE_BINARY_DIR}/stage - VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/share) set_property(TEST o2sim_G4_mt APPEND PROPERTY ENVIRONMENT ${G4ENV}) @@ -188,7 +188,8 @@ o2_add_test_wrapper(NAME o2sim_G3 -o o2simG3 LABELS g3 sim long - ENVIRONMENT "O2_ROOT=${CMAKE_BINARY_DIR}/stage;VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/share") + ENVIRONMENT "${SIMENV}" +) # set properties for G3 ... we use fixtures to force execution after G4 (since # they require multiple CPUs) @@ -199,7 +200,6 @@ set_tests_properties(o2sim_G3 G4 FIXTURES_SETUP G3) -set_property(TEST o2sim_G3 APPEND PROPERTY ENVIRONMENT "ALICE_O2SIM_DUMPLOG=ON") o2_add_test(CheckStackG3 SOURCES checkStack.cxx @@ -215,25 +215,48 @@ set_tests_properties(o2sim_checksimkinematics_G3 PROPERTIES FIXTURES_REQUIRED G3) -#o2_add_test_wrapper(NAME o2sim_hepmc -# WORKING_DIRECTORY ${SIMTESTDIR} -# DONT_FAIL_ON_TIMEOUT -# MAX_ATTEMPTS 2 -# TIMEOUT 400 -# COMMAND $<TARGET_FILE:${o2simExecutable}> -# COMMAND_LINE_ARGS -n -# 2 -# -j -# 2 -# -g -# hepmc -# --configKeyValues -# "HepMC.fileName=${CMAKE_SOURCE_DIR}/Generators/share/data/pythia.hepmc;HepMC.version=2" -# -o -# o2simhepmc -# LABELS long sim hepmc3 -# ENVIRONMENT "O2_ROOT=${CMAKE_BINARY_DIR}/stage;VMCWORKDIR=${CMAKE_BINARY_DIR}/stage/share") -# -#set_tests_properties(o2sim_hepmc -# PROPERTIES PASS_REGULAR_EXPRESSION -# "SIMULATION RETURNED SUCCESFULLY") +o2_add_test_wrapper(NAME o2sim_hepmc + WORKING_DIRECTORY ${SIMTESTDIR} + DONT_FAIL_ON_TIMEOUT + MAX_ATTEMPTS 2 + TIMEOUT 400 + COMMAND $<TARGET_FILE:${o2simExecutable}> + COMMAND_LINE_ARGS -n + 2 + -j + 2 + -g + hepmc + --configKeyValues + "HepMC.fileName=${CMAKE_SOURCE_DIR}/Generators/share/data/pythia.hepmc;HepMC.version=2" + -o + o2simhepmc + LABELS long sim hepmc3 + ENVIRONMENT "${SIMENV}") + +set_tests_properties(o2sim_hepmc + PROPERTIES PASS_REGULAR_EXPRESSION + "SIMULATION RETURNED SUCCESFULLY") + +# somewhat analyse the logfiles as another means to detect problems +o2_add_test_wrapper(NAME o2sim_G3_checklogs + WORKING_DIRECTORY ${SIMTESTDIR} + DONT_FAIL_ON_TIMEOUT + COMMAND ${CMAKE_SOURCE_DIR}/run/simlogcheck.sh + COMMAND_LINE_ARGS o2simG3_serverlog o2simG3_mergerlog o2simG3_workerlog0 + LABELS long sim hepmc3) + +set_tests_properties(o2sim_G3_checklogs + PROPERTIES FIXTURES_REQUIRED G3) + +# somewhat analyse the logfiles as another means to detect problems +o2_add_test_wrapper(NAME o2sim_G4_checklogs + WORKING_DIRECTORY ${SIMTESTDIR} + DONT_FAIL_ON_TIMEOUT + COMMAND ${CMAKE_SOURCE_DIR}/run/simlogcheck.sh + COMMAND_LINE_ARGS o2simG4_serverlog o2simG4_mergerlog o2simG4_workerlog0 + LABELS long sim +) + +set_tests_properties(o2sim_G3_checklogs + PROPERTIES FIXTURES_REQUIRED G4) diff --git a/run/simlogcheck.sh b/run/simlogcheck.sh new file mode 100755 index 0000000000000..ced2cd01294c0 --- /dev/null +++ b/run/simlogcheck.sh @@ -0,0 +1,28 @@ +#!/bin/bash -l +set -x + +# a script checking logfiles for signs of error +# can be used to detect most common errors automatically +# returns/exits with 0 if no problem + +error=0 + +for file in "$@"; do + echo "looking into ${file}" + + # We don't want to see "Error" or "ERROR" messages + value=$(grep "Error" ${file}) + if [ -n "${value}" ]; then + echo "check for Error failed" + let error=error+1 + fi + + value=$(grep "ERROR" ${file}) + if [ -n "${value}" ]; then + echo "check for ERROR failed" + let error=error+1 + fi + +done + +exit ${error} From b16f8b1ad3570863dcfb8f76be6f21e2405acee6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 9 Oct 2020 14:01:16 +0200 Subject: [PATCH 0896/1751] TPC Workflow: Don't supporrt specifying tpc sectors, doesn't work anyway with tpc tracking, could be fixed at some point later --- Detectors/TPC/workflow/src/tpc-reco-workflow.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index f8795b9f213d2..cf5164964e970 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -46,7 +46,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) {"output-type", VariantType::String, "tracks", {"digits, zsraw, clustershw, clustersnative, tracks, compressed-clusters, encoded-clusters, disable-writer"}}, {"no-ca-clusterer", VariantType::Bool, false, {"Use HardwareClusterer instead of clusterer of GPUCATracking"}}, {"disable-mc", VariantType::Bool, false, {"disable sending of MC information"}}, - {"tpc-sectors", VariantType::String, "0-35", {"TPC sector range, e.g. 5-7,8,9"}}, + //{"tpc-sectors", VariantType::String, "0-35", {"TPC sector range, e.g. 5-7,8,9"}}, {"tpc-lanes", VariantType::Int, 1, {"number of parallel lanes up to the tracker"}}, {"dispatching-mode", VariantType::String, "prompt", {"determines when to dispatch: prompt, complete"}}, {"no-tpc-zs-on-the-fly", VariantType::Bool, false, {"Do not use TPC zero suppression on the fly"}}, @@ -110,7 +110,9 @@ using namespace o2::framework; /// This function hooks up the the workflow specifications into the DPL driver. WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - auto tpcSectors = o2::RangeTokenizer::tokenize<int>(cfgc.options().get<std::string>("tpc-sectors")); + //auto tpcSectors = o2::RangeTokenizer::tokenize<int>(cfgc.options().get<std::string>("tpc-sectors")); + std::vector<int> tpcSectors(36); + std::iota(tpcSectors.begin(), tpcSectors.end(), 0); // the lane configuration defines the subspecification ids to be distributed among the lanes. std::vector<int> laneConfiguration; auto nLanes = cfgc.options().get<int>("tpc-lanes"); From 4a04ec60eef2db08cbcaf31ff3b3ae54f982a1f6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 9 Oct 2020 16:16:19 +0200 Subject: [PATCH 0897/1751] TPC Workflow: Fix check that data is received for all sectors exactly once + cleanup --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 210 ++++++------------ Detectors/TPC/workflow/src/RecoWorkflow.cxx | 6 +- .../TPC/workflow/src/tpc-reco-workflow.cxx | 3 +- 3 files changed, 75 insertions(+), 144 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 4d87a4a5ea17a..d0dd25ca0a316 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -86,23 +86,25 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int constexpr static size_t NEndpoints = 20; //TODO: get from mapper? using ClusterGroupParser = o2::algorithm::ForwardParser<ClusterGroupHeader>; struct ProcessAttributes { - std::bitset<NSectors> validInputs = 0; - std::bitset<NSectors> validMcInputs = 0; std::unique_ptr<ClusterGroupParser> parser; std::unique_ptr<GPUCATracking> tracker; std::unique_ptr<GPUDisplayBackend> displayBackend; std::unique_ptr<TPCFastTransform> fastTransform; std::unique_ptr<TPCdEdxCalibrationSplines> dEdxSplines; std::unique_ptr<TPCCFCalibration> tpcCalibration; - int verbosity = 1; std::vector<int> clusterOutputIds; + unsigned long outputBufferSize = 0; + unsigned long tpcSectorMask = 0; + int verbosity = 1; bool readyToQuit = false; bool allocateOutputOnTheFly = false; - unsigned long outputBufferSize = 0; bool suppressOutput = false; }; auto processAttributes = std::make_shared<ProcessAttributes>(); + for (auto s : tpcsectors) { + processAttributes->tpcSectorMask |= (1ul << s); + } auto initFunction = [processAttributes, specconfig](InitContext& ic) { GPUO2InterfaceConfiguration config; GPUSettingsO2 confParam; @@ -224,8 +226,6 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int if (tracker->initialize(config) != 0) { throw std::invalid_argument("GPUCATracking initialization failed"); } - processAttributes->validInputs.reset(); - processAttributes->validMcInputs.reset(); } auto& callbacks = ic.services().get<CallbackService>(); @@ -260,10 +260,8 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int } auto& parser = processAttributes->parser; auto& tracker = processAttributes->tracker; - uint64_t activeSectors = 0; auto& verbosity = processAttributes->verbosity; // FIXME cleanup almost duplicated code - auto& validMcInputs = processAttributes->validMcInputs; std::vector<ConstMCLabelContainerView> mcInputs; std::vector<gsl::span<const char>> inputs; struct InputRef { @@ -293,6 +291,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int {"check", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITSMCTR"}, Lifetime::Timeframe}, {"check", ConcreteDataTypeMatcher{gDataOriginTPC, "CLNATIVEMCLBL"}, Lifetime::Timeframe}, }; + unsigned long recvMask = 0; for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) { auto const* sectorHeader = DataRefUtils::getHeader<TPCSectorHeader*>(ref); if (sectorHeader == nullptr) { @@ -304,81 +303,80 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int if (sector < 0) { continue; } - std::bitset<NSectors> sectorMask(sectorHeader->sectorBits); - if ((validMcInputs & sectorMask).any()) { - // have already data for this sector, this should not happen in the current - // sequential implementation, for parallel path merged at the tracker stage - // multiple buffers need to be handled + if (recvMask & sectorHeader->sectorBits) { throw std::runtime_error("can only have one MC data set per sector"); } + recvMask |= sectorHeader->sectorBits; inputrefs[sector].labels = ref; if (specconfig.caClusterer) { inputDigitsMCIndex[sector] = inputDigitsMC.size(); inputDigitsMC.emplace_back(ConstMCLabelContainerView(pc.inputs().get<gsl::span<char>>(ref))); } - validMcInputs |= sectorMask; - activeSectors |= sectorHeader->activeSectors; - if (verbosity > 1) { - LOG(INFO) << "received " << *(ref.spec) << " MC label containers" - << " for sectors " << sectorMask // - << std::endl // - << " mc input status: " << validMcInputs // - << std::endl // - << " active sectors: " << std::bitset<NSectors>(activeSectors); // - } } - for (unsigned int i = 0; i < NSectors; i++) { - inputDigitsMCPtrs[i] = &inputDigitsMC[inputDigitsMCIndex[i]]; + if (recvMask != processAttributes->tpcSectorMask) { + throw std::runtime_error("Incomplete set of MC labels received"); + } + if (specconfig.caClusterer) { + for (unsigned int i = 0; i < NSectors; i++) { + LOG(INFO) << "GOT MC LABELS FOR SECTOR " << i << " -> " << inputDigitsMC[inputDigitsMCIndex[i]].getNElements(); + inputDigitsMCPtrs[i] = &inputDigitsMC[inputDigitsMCIndex[i]]; + } } } - auto& validInputs = processAttributes->validInputs; - int operation = 0; - std::vector<InputSpec> filter = { - {"check", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe}, - {"check", ConcreteDataTypeMatcher{gDataOriginTPC, "CLUSTERNATIVE"}, Lifetime::Timeframe}, - }; - - for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) { - auto const* sectorHeader = DataRefUtils::getHeader<TPCSectorHeader*>(ref); - if (sectorHeader == nullptr) { - throw std::runtime_error("sector header missing on header stack"); - } - const int sector = sectorHeader->sector(); - if (sector < 0) { - continue; - } - std::bitset<NSectors> sectorMask(sectorHeader->sectorBits); - if ((validInputs & sectorMask).any()) { - // have already data for this sector, this should not happen in the current - // sequential implementation, for parallel path merged at the tracker stage - // multiple buffers need to be handled - throw std::runtime_error("can only have one cluster data set per sector"); + if (!specconfig.decompressTPC && (!specconfig.caClusterer || ((!specconfig.zsOnTheFly || specconfig.processMC) && !specconfig.zsDecoder))) { + std::vector<InputSpec> filter = { + {"check", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe}, + {"check", ConcreteDataTypeMatcher{gDataOriginTPC, "CLUSTERNATIVE"}, Lifetime::Timeframe}, + }; + unsigned long recvMask = 0; + for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) { + auto const* sectorHeader = DataRefUtils::getHeader<TPCSectorHeader*>(ref); + if (sectorHeader == nullptr) { + throw std::runtime_error("sector header missing on header stack"); + } + const int sector = sectorHeader->sector(); + if (sector < 0) { + continue; + } + if (recvMask & sectorHeader->sectorBits) { + throw std::runtime_error("can only have one cluster data set per sector"); + } + recvMask |= sectorHeader->sectorBits; + inputrefs[sector].data = ref; + if (specconfig.caClusterer && (!specconfig.zsOnTheFly || specconfig.processMC)) { + inputDigits[sector] = pc.inputs().get<gsl::span<o2::tpc::Digit>>(ref); + LOG(INFO) << "GOT DIGITS SPAN FOR SECTOR " << sector << " -> " << inputDigits[sector].size(); + } } - activeSectors |= sectorHeader->activeSectors; - validInputs |= sectorMask; - inputrefs[sector].data = ref; - if (specconfig.caClusterer && (!specconfig.zsOnTheFly || specconfig.processMC)) { - inputDigits[sector] = pc.inputs().get<gsl::span<o2::tpc::Digit>>(ref); - LOG(INFO) << "GOT DIGITS SPAN FOR SECTOR " << sector << " -> " << inputDigits[sector].size(); + if (recvMask != processAttributes->tpcSectorMask) { + throw std::runtime_error("Incomplete set of clusters/digits received"); } } + if (specconfig.zsOnTheFly) { tpcZSonTheFlySizes = {0}; // tpcZSonTheFlySizes: #zs pages per endpoint: std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{gDataOriginTPC, "ZSSIZES"}, Lifetime::Timeframe}}; + bool recv = false, recvsizes = false; for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) { + if (recvsizes) { + throw std::runtime_error("Received multiple ZSSIZES data"); + } tpcZSonTheFlySizes = pc.inputs().get<std::array<unsigned int, NEndpoints * NSectors>>(ref); + recvsizes = true; } // zs pages std::vector<InputSpec> filter2 = {{"check", ConcreteDataTypeMatcher{gDataOriginTPC, "TPCZS"}, Lifetime::Timeframe}}; for (auto const& ref : InputRecordWalker(pc.inputs(), filter2)) { + if (recv) { + throw std::runtime_error("Received multiple TPCZS data"); + } inputZS = pc.inputs().get<gsl::span<ZeroSuppressedContainer8kb>>(ref); + recv = true; } - //set all sectors as active and as valid inputs - for (int s = 0; s < NSectors; s++) { - activeSectors |= 1 << s; - validInputs.set(s); + if (!recv || !recvsizes) { + throw std::runtime_error("TPC ZS data not received"); } for (unsigned int i = 0; i < GPUTrackingInOutZS::NSLICES; i++) { for (unsigned int j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) { @@ -482,78 +480,25 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int pCompClustersFlat = pc.inputs().get<CompressedClustersFlat*>("input").get(); } } else if (!specconfig.zsOnTheFly) { - // This code path should run optionally also for the zs decoder version - auto printInputLog = [&verbosity, &validInputs, &activeSectors](auto& r, const char* comment, auto& s) { - if (verbosity > 1) { - LOG(INFO) << comment << " " << *(r.spec) << ", size " << DataRefUtils::getPayloadSize(r) // - << " for sector " << s // - << std::endl // - << " input status: " << validInputs // - << std::endl // - << " active sectors: " << std::bitset<NSectors>(activeSectors); // - } - }; - // for digits and clusters we always have the sector information, activeSectors being zero - // is thus an error condition. The completion policy makes sure that the data set is complete - if (activeSectors == 0 || (activeSectors & validInputs.to_ulong()) != activeSectors) { - throw std::runtime_error("Incomplete input data, expecting complete data set, buffering has been removed "); - } - // MC label blocks must be in the same multimessage with the corresponding data, the completion - // policy does not check for the MC labels and expects them to be present and thus complete if - // the data is complete - if (specconfig.processMC && (activeSectors & validMcInputs.to_ulong()) != activeSectors) { - throw std::runtime_error("Incomplete mc label input, expecting complete data set, buffering has been removed"); - } - assert(specconfig.processMC == false || validMcInputs == validInputs); for (auto const& refentry : inputrefs) { auto& sector = refentry.first; auto& ref = refentry.second.data; - if (ref.payload == nullptr) { - // skip zero-length message - continue; - } - if (refentry.second.labels.header != nullptr && refentry.second.labels.payload != nullptr) { - mcInputs.emplace_back(ConstMCLabelContainerView(pc.inputs().get<gsl::span<char>>(refentry.second.labels))); - } - inputs.emplace_back(gsl::span(ref.payload, DataRefUtils::getPayloadSize(ref))); - printInputLog(ref, "received", sector); - } - assert(mcInputs.size() == 0 || mcInputs.size() == inputs.size()); - if (verbosity > 0) { - // make human readable information from the bitfield - std::string bitInfo; - auto nActiveBits = validInputs.count(); - if (((uint64_t)0x1 << nActiveBits) == validInputs.to_ulong() + 1) { - // sectors 0 to some upper bound are active - bitInfo = "0-" + std::to_string(nActiveBits - 1); - } else { - int rangeStart = -1; - int rangeEnd = -1; - for (size_t sector = 0; sector < validInputs.size(); sector++) { - if (validInputs.test(sector)) { - if (rangeStart < 0) { - if (rangeEnd >= 0) { - bitInfo += ","; - } - bitInfo += std::to_string(sector); - if (nActiveBits == 1) { - break; - } - rangeStart = sector; - } - rangeEnd = sector; - } else { - if (rangeStart >= 0 && rangeEnd > rangeStart) { - bitInfo += "-" + std::to_string(rangeEnd); - } - rangeStart = -1; - } + if (!specconfig.caClusterer) { + if (ref.payload == nullptr) { + // skip zero-length message + continue; } - if (rangeStart >= 0 && rangeEnd > rangeStart) { - bitInfo += "-" + std::to_string(rangeEnd); + if (refentry.second.labels.header != nullptr && refentry.second.labels.payload != nullptr) { + mcInputs.emplace_back(ConstMCLabelContainerView(pc.inputs().get<gsl::span<char>>(refentry.second.labels))); } + inputs.emplace_back(gsl::span(ref.payload, DataRefUtils::getPayloadSize(ref))); } - LOG(INFO) << "running tracking for sector(s) " << bitInfo; + if (verbosity > 1) { + LOG(INFO) << "received " << *(ref.spec) << ", size " << DataRefUtils::getPayloadSize(ref) << " for sector " << sector; + } + } + if (verbosity) { + LOGF(INFO, "running tracking for sector(s) 0x%09x", processAttributes->tpcSectorMask); } } @@ -592,7 +537,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int ptrs.compressedClusters = pCompClustersFlat; } else { memset(&clusterIndex, 0, sizeof(clusterIndex)); - ClusterNativeHelper::Reader::fillIndex(clusterIndex, clusterBuffer, clustersMCBuffer, inputs, mcInputs, [&validInputs](auto& index) { return validInputs.test(index); }); + ClusterNativeHelper::Reader::fillIndex(clusterIndex, clusterBuffer, clustersMCBuffer, inputs, mcInputs, [&processAttributes](auto& index) { return processAttributes->tpcSectorMask & (1ul << index); }); ptrs.clusters = &clusterIndex; } // a byte size resizable vector object, the DataAllocator returns reference to internal object @@ -600,18 +545,10 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int using O2CharVectorOutputType = std::decay_t<decltype(pc.outputs().make<std::vector<char>>(Output{"", "", 0}))>; TPCSectorHeader clusterOutputSectorHeader{0}; if (processAttributes->clusterOutputIds.size() > 0) { - if (activeSectors == 0) { - // there is no sector header shipped with the ZS raw data and thus we do not have - // a valid activeSector variable, though it will be needed downstream - // FIXME: check if this can be provided upstream - for (auto const& sector : processAttributes->clusterOutputIds) { - activeSectors |= 0x1 << sector; - } - } - clusterOutputSectorHeader.sectorBits = activeSectors; + clusterOutputSectorHeader.sectorBits = processAttributes->tpcSectorMask; // subspecs [0, NSectors - 1] are used to identify sector data, we use NSectors // to indicate the full TPC - clusterOutputSectorHeader.activeSectors = activeSectors; + clusterOutputSectorHeader.activeSectors = processAttributes->tpcSectorMask; } GPUInterfaceOutputs outputRegions; @@ -706,11 +643,6 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int pc.outputs().snapshot({gDataOriginTPC, "CLNATIVEMCLBL", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}, clustersMCBuffer.first); } } - - validInputs.reset(); - if (specconfig.processMC) { - validMcInputs.reset(); - } }; return processingFct; diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 3fac36e48e065..c02c0863318d7 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -417,11 +417,11 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec } if (zsOnTheFly) { - specs.emplace_back(o2::tpc::getZSEncoderSpec(laneConfiguration, zs10bit, zsThreshold, outRaw)); + specs.emplace_back(o2::tpc::getZSEncoderSpec(tpcSectors, zs10bit, zsThreshold, outRaw)); } if (zsToDigit) { - specs.emplace_back(o2::tpc::getZStoDigitsSpec(laneConfiguration)); + specs.emplace_back(o2::tpc::getZStoDigitsSpec(tpcSectors)); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -442,7 +442,7 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec runClusterEncoder ? ca::Operation::OutputCompClustersFlat : ca::Operation::Noop, isEnabled(OutputType::Clusters) && (caClusterer || decompressTPC) ? ca::Operation::OutputCAClusters : ca::Operation::Noop, }, - laneConfiguration)); + tpcSectors)); } ////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index cf5164964e970..40b2ce0ad13e8 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -114,10 +114,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) std::vector<int> tpcSectors(36); std::iota(tpcSectors.begin(), tpcSectors.end(), 0); // the lane configuration defines the subspecification ids to be distributed among the lanes. - std::vector<int> laneConfiguration; + std::vector<int> laneConfiguration = tpcSectors; // Currently just a copy of the tpcSectors, why? auto nLanes = cfgc.options().get<int>("tpc-lanes"); auto inputType = cfgc.options().get<std::string>("input-type"); - laneConfiguration = tpcSectors; // depending on whether to dispatch early (prompt) and on the input type, we // set the matcher. Note that this has to be in accordance with the OutputSpecs From e1cae5f07eacb0daca8afe7bff8e79fbd964e061 Mon Sep 17 00:00:00 2001 From: anerokhi <44967087+anerokhi@users.noreply.github.com> Date: Sat, 10 Oct 2020 09:27:08 +0300 Subject: [PATCH 0898/1751] Framework: add braces to single statements (#4566) --- .../include/Framework/AnalysisDataModel.h | 6 +- .../Core/include/Framework/AnalysisTask.h | 6 +- Framework/Core/src/ConfigParamsHelper.cxx | 6 +- .../Core/src/DataDescriptorQueryBuilder.cxx | 3 +- Framework/Core/src/DataInputDirector.cxx | 9 ++- Framework/Core/src/DataOutputDirector.cxx | 12 ++-- Framework/Core/src/DeviceSpec.cxx | 11 ++-- Framework/Core/src/Expressions.cxx | 57 ++++++++++++------- .../Core/src/FrameworkGUIDevicesGraph.cxx | 18 ++++-- Framework/Core/src/WorkflowHelpers.cxx | 6 +- Framework/Core/src/runDataProcessing.cxx | 6 +- Framework/Core/test/benchmark_TreeToTable.cxx | 7 +-- Framework/Core/test/test_GroupSlicer.cxx | 3 +- Framework/Foundation/include/Framework/Pack.h | 16 ++++-- .../test/test_MakeDPLObjects.cxx | 3 +- 15 files changed, 110 insertions(+), 59 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 69b20c7259b95..fc50e4e105fb3 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -178,17 +178,19 @@ DECLARE_SOA_DYNAMIC_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, [](uint8_t tp DECLARE_SOA_DYNAMIC_COLUMN(ITSNCls, itsNCls, [](uint8_t itsClusterMap) -> uint8_t { uint8_t itsNcls = 0; constexpr uint8_t bit = 1; - for (int layer = 0; layer < 7; layer++) + for (int layer = 0; layer < 7; layer++) { if (itsClusterMap & (bit << layer)) itsNcls++; + } return itsNcls; }); DECLARE_SOA_DYNAMIC_COLUMN(ITSNClsInnerBarrel, itsNClsInnerBarrel, [](uint8_t itsClusterMap) -> uint8_t { uint8_t itsNclsInnerBarrel = 0; constexpr uint8_t bit = 1; - for (int layer = 0; layer < 3; layer++) + for (int layer = 0; layer < 3; layer++) { if (itsClusterMap & (bit << layer)) itsNclsInnerBarrel++; + } return itsNclsInnerBarrel; }); diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 59dc5a3cce729..bbcdb028f36b3 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -144,14 +144,16 @@ struct AnalysisDataProcessorBuilder { if constexpr (soa::is_soa_filtered_t<decayed>::value) { for (auto& info : infos) { - if (info.index == at) + if (info.index == at) { return extractFilteredFromRecord<decayed>(record, info, soa::make_originals_from_type<decayed>()); + } } } else if constexpr (soa::is_soa_iterator_t<decayed>::value) { if constexpr (std::is_same_v<typename decayed::policy_t, soa::FilteredIndexPolicy>) { for (auto& info : infos) { - if (info.index == at) + if (info.index == at) { return extractFilteredFromRecord<decayed>(record, info, soa::make_originals_from_type<decayed>()); + } } } else { return extractFromRecord<decayed>(record, soa::make_originals_from_type<decayed>()); diff --git a/Framework/Core/src/ConfigParamsHelper.cxx b/Framework/Core/src/ConfigParamsHelper.cxx index 72b70ea2a36ca..4fa7415b9234e 100644 --- a/Framework/Core/src/ConfigParamsHelper.cxx +++ b/Framework/Core/src/ConfigParamsHelper.cxx @@ -32,8 +32,9 @@ void ConfigParamsHelper::populateBoostProgramOptions( auto proxy = options.add_options(); for (auto& spec : specs) { // skip everything found in the veto definition - if (vetos.find_nothrow(spec.name, false)) + if (vetos.find_nothrow(spec.name, false)) { continue; + } const char* name = spec.name.c_str(); const char* help = spec.help.c_str(); @@ -75,8 +76,9 @@ bool ConfigParamsHelper::dpl2BoostOptions(const std::vector<ConfigParamSpec>& sp for (const auto& configSpec : spec) { // skip everything found in the veto definition try { - if (vetos.find_nothrow(configSpec.name, false)) + if (vetos.find_nothrow(configSpec.name, false)) { continue; + } } catch (boost::program_options::ambiguous_option& e) { for (auto& alternative : e.alternatives()) { std::cerr << alternative << std::endl; diff --git a/Framework/Core/src/DataDescriptorQueryBuilder.cxx b/Framework/Core/src/DataDescriptorQueryBuilder.cxx index 0a3737b2ba971..2edbb4f84be5d 100644 --- a/Framework/Core/src/DataDescriptorQueryBuilder.cxx +++ b/Framework/Core/src/DataDescriptorQueryBuilder.cxx @@ -285,8 +285,9 @@ DataDescriptorQuery DataDescriptorQueryBuilder::buildFromExtendedKeepConfig(std: s.end(), delim2, -1); - if (iter2 == end) + if (iter2 == end) { continue; + } s = iter2->str(); // create the corresponding DataDescriptorMatcher diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 520ecaf6a132f..d7be1fd9763f4 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -138,8 +138,9 @@ void DataInputDescriptor::printOut() LOGP(INFO, " Input files file : {}", getInputfilesFilename()); LOGP(INFO, " File name regex : {}", getFilenamesRegexString()); LOGP(INFO, " Input files : {}", mfilenames.size()); - for (auto fn : mfilenames) + for (auto fn : mfilenames) { LOGP(INFO, " {}", fn); + } } DataInputDirector::DataInputDirector() @@ -519,13 +520,15 @@ void DataInputDirector::printOut() LOGP(INFO, " Default input files file : {}", minputfilesFile); LOGP(INFO, " Default file name regex : {}", mFilenameRegex); LOGP(INFO, " Default file names : {}", mdefaultInputFiles.size()); - for (auto const& fn : mdefaultInputFiles) + for (auto const& fn : mdefaultInputFiles) { LOGP(INFO, " {}", fn); + } LOGP(INFO, " Default DataInputDescriptor:"); mdefaultDataInputDescriptor->printOut(); LOGP(INFO, " DataInputDescriptors : {}", getNumberInputDescriptors()); - for (auto const& didesc : mdataInputDescriptors) + for (auto const& didesc : mdataInputDescriptors) { didesc->printOut(); + } } } // namespace framework diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index 00b2c55509b26..17adfc56e2a10 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -114,8 +114,9 @@ void DataOutputDescriptor::printOut() } else { LOGP(INFO, " Columns : {}", colnames.size()); } - for (auto cn : colnames) + for (auto cn : colnames) { LOGP(INFO, " {}", cn); + } } std::string DataOutputDescriptor::remove_ws(const std::string& s) @@ -459,10 +460,11 @@ TFile* DataOutputDirector::getDataOutputFile(DataOutputDescriptor* dodesc, void DataOutputDirector::closeDataFiles() { - for (auto filePtr : mfilePtrs) + for (auto filePtr : mfilePtrs) { if (filePtr) { filePtr->Close(); } + } } void DataOutputDirector::printOut() @@ -472,12 +474,14 @@ void DataOutputDirector::printOut() LOGP(INFO, " Number of files : {}", mfilenameBases.size()); LOGP(INFO, " DataOutputDescriptors: {}", mDataOutputDescriptors.size()); - for (auto const& ds : mDataOutputDescriptors) + for (auto const& ds : mDataOutputDescriptors) { ds->printOut(); + } LOGP(INFO, " File name bases :"); - for (auto const& fb : mfilenameBases) + for (auto const& fb : mfilenameBases) { LOGP(INFO, fb); + } } void DataOutputDirector::setFilenameBase(std::string dfn) diff --git a/Framework/Core/src/DeviceSpec.cxx b/Framework/Core/src/DeviceSpec.cxx index 0951548d6f95f..06f8f7d561a3f 100644 --- a/Framework/Core/src/DeviceSpec.cxx +++ b/Framework/Core/src/DeviceSpec.cxx @@ -35,16 +35,19 @@ size_t levenshteinDistance(const char* s, int len_s, const char* t, int len_t) size_t cost; /* base case: empty strings */ - if (len_s == 0) + if (len_s == 0) { return len_t; - if (len_t == 0) + } + if (len_t == 0) { return len_s; + } /* test if last characters of the strings match */ - if (s[len_s - 1] == t[len_t - 1]) + if (s[len_s - 1] == t[len_t - 1]) { cost = 0; - else + } else { cost = 1; + } return std::min(std::min(levenshteinDistance(s, len_s - 1, t, len_t) + 1, levenshteinDistance(s, len_s, t, len_t - 1) + 1), diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 2455e897f0b0e..12acc095328a1 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -204,11 +204,13 @@ Operations createOperations(Filter const& expression) } decltype(left) right = nullptr; - if (top.node_ptr->right != nullptr) + if (top.node_ptr->right != nullptr) { right = top.node_ptr->right.get(); + } bool rightLeaf = true; - if (right != nullptr) + if (right != nullptr) { rightLeaf = isLeaf(right); + } size_t ri = 0; auto isUnary = false; if (top.node_ptr->right == nullptr) { @@ -224,10 +226,12 @@ Operations createOperations(Filter const& expression) } OperationSpecs.push_back(std::move(operationSpec)); - if (!leftLeaf) + if (!leftLeaf) { path.emplace(left, li); - if (!isUnary && !rightLeaf) + } + if (!isUnary && !rightLeaf) { path.emplace(right, ri); + } } // at this stage the operations vector is created, but the field types are // only set for the logical operations and leaf nodes @@ -241,18 +245,21 @@ Operations createOperations(Filter const& expression) } // check if the datums are references - if (left.datum.index() == 1) + if (left.datum.index() == 1) { left.type = resultTypes[std::get<size_t>(left.datum)]; + } - if (right.datum.index() == 1) + if (right.datum.index() == 1) { right.type = resultTypes[std::get<size_t>(right.datum)]; + } auto t1 = left.type; auto t2 = right.type; // if the right datum is monostate (unary op) if (right.datum.index() == 0) { - if (t1 == atype::DOUBLE) + if (t1 == atype::DOUBLE) { return atype::DOUBLE; + } return atype::FLOAT; } @@ -261,18 +268,23 @@ Operations createOperations(Filter const& expression) } if (t1 == atype::INT32 || t1 == atype::INT8 || t1 == atype::INT16 || t1 == atype::UINT8) { - if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::UINT8) + if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::UINT8) { return atype::FLOAT; - if (t2 == atype::FLOAT) + } + if (t2 == atype::FLOAT) { return atype::FLOAT; - if (t2 == atype::DOUBLE) + } + if (t2 == atype::DOUBLE) { return atype::DOUBLE; + } } if (t1 == atype::FLOAT) { - if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::UINT8) + if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::UINT8) { return atype::FLOAT; - if (t2 == atype::DOUBLE) + } + if (t2 == atype::DOUBLE) { return atype::DOUBLE; + } } if (t1 == atype::DOUBLE) { return atype::DOUBLE; @@ -423,16 +435,21 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, if (spec.datum.index() == 2) { auto content = std::get<LiteralNode::var_t>(spec.datum); - if (content.index() == 0) + if (content.index() == 0) { return gandiva::TreeExprBuilder::MakeLiteral(static_cast<int32_t>(std::get<int>(content))); - if (content.index() == 1) + } + if (content.index() == 1) { return gandiva::TreeExprBuilder::MakeLiteral(std::get<bool>(content)); - if (content.index() == 2) + } + if (content.index() == 2) { return gandiva::TreeExprBuilder::MakeLiteral(std::get<float>(content)); - if (content.index() == 3) + } + if (content.index() == 3) { return gandiva::TreeExprBuilder::MakeLiteral(std::get<double>(content)); - if (content.index() == 4) + } + if (content.index() == 4) { return gandiva::TreeExprBuilder::MakeLiteral(std::get<uint8_t>(content)); + } throw std::runtime_error("Malformed LiteralNode"); } @@ -508,10 +525,12 @@ bool isSchemaCompatible(gandiva::SchemaPtr const& Schema, Operations const& opSp { std::set<std::string> opFieldNames; for (auto& spec : opSpecs) { - if (spec.left.datum.index() == 3) + if (spec.left.datum.index() == 3) { opFieldNames.insert(std::get<std::string>(spec.left.datum)); - if (spec.right.datum.index() == 3) + } + if (spec.right.datum.index() == 3) { opFieldNames.insert(std::get<std::string>(spec.right.datum)); + } } std::set<std::string> schemaFieldNames; diff --git a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx index c4ee6f5020de4..b42f811155a4f 100644 --- a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx +++ b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx @@ -469,12 +469,15 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, } } bool node_moving_active = ImGui::IsItemActive(); - if (node_widgets_active || node_moving_active) + if (node_widgets_active || node_moving_active) { node_selected = node->ID; - if (node_moving_active && ImGui::IsMouseDragging(0)) + } + if (node_moving_active && ImGui::IsMouseDragging(0)) { pos->pos = pos->pos + ImGui::GetIO().MouseDelta; - if (ImGui::IsWindowHovered() && !node_moving_active && ImGui::IsMouseDragging(0)) + } + if (ImGui::IsWindowHovered() && !node_moving_active && ImGui::IsMouseDragging(0)) { scrolling = scrolling - ImVec2(ImGui::GetIO().MouseDelta.x / 4.f, ImGui::GetIO().MouseDelta.y / 4.f); + } auto nodeBg = decideColorForNode(info); @@ -497,8 +500,9 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, draw_list->AddTriangleFilled(pp1, pp2, pp3, color); draw_list->AddCircleFilled(offset + NodePos::GetInputSlotPos(nodes, positions, node_idx, slot_idx), NODE_SLOT_RADIUS, ImColor(150, 150, 150, 150)); } - for (int slot_idx = 0; slot_idx < node->OutputsCount; slot_idx++) + for (int slot_idx = 0; slot_idx < node->OutputsCount; slot_idx++) { draw_list->AddCircleFilled(offset + NodePos::GetOutputSlotPos(nodes, positions, node_idx, slot_idx), NODE_SLOT_RADIUS, ImColor(150, 150, 150, 150)); + } ImGui::PopID(); } @@ -511,10 +515,12 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, } if (open_context_menu) { ImGui::OpenPopup("context_menu"); - if (node_hovered_in_list != -1) + if (node_hovered_in_list != -1) { node_selected = node_hovered_in_list; - if (node_hovered_in_scene != -1) + } + if (node_hovered_in_scene != -1) { node_selected = node_hovered_in_scene; + } } // Scrolling diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index edf90efde5bce..fc5d06e648eb4 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -406,8 +406,9 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select dangling outputs which are not of type AOD std::vector<InputSpec> outputsInputsDangling; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { - if ((outputTypes[ii] & 1) == 1 && (outputTypes[ii] & 2) == 0) + if ((outputTypes[ii] & 1) == 1 && (outputTypes[ii] & 2) == 0) { outputsInputsDangling.emplace_back(OutputsInputs[ii]); + } } std::vector<InputSpec> unmatched; @@ -695,8 +696,9 @@ void WorkflowHelpers::verifyWorkflow(const o2::framework::WorkflowSpec& workflow std::ostringstream ss; for (auto& spec : workflow) { - if (spec.name.empty()) + if (spec.name.empty()) { throw std::runtime_error("Invalid DataProcessorSpec name"); + } if (validNames.find(spec.name) != validNames.end()) { throw std::runtime_error("Name " + spec.name + " is used twice."); } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 966860f191da1..921a921f08e30 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -162,8 +162,9 @@ std::istream& operator>>(std::istream& in, enum TerminationPolicy& policy) policy = TerminationPolicy::QUIT; } else if (token == "wait") { policy = TerminationPolicy::WAIT; - } else + } else { in.setstate(std::ios_base::failbit); + } return in; } @@ -173,8 +174,9 @@ std::ostream& operator<<(std::ostream& out, const enum TerminationPolicy& policy out << "quit"; } else if (policy == TerminationPolicy::WAIT) { out << "wait"; - } else + } else { out.setstate(std::ios_base::failbit); + } return out; } } // namespace framework diff --git a/Framework/Core/test/benchmark_TreeToTable.cxx b/Framework/Core/test/benchmark_TreeToTable.cxx index 3224d31ccf484..2a590609906b8 100644 --- a/Framework/Core/test/benchmark_TreeToTable.cxx +++ b/Framework/Core/test/benchmark_TreeToTable.cxx @@ -82,11 +82,10 @@ static void BM_TreeToTable(benchmark::State& state) } // clean up - if (tr2ta) - delete tr2ta; + delete tr2ta; + f->Close(); - if (f) - delete f; + delete f; } state.SetBytesProcessed(state.iterations() * state.range(0) * 24); diff --git a/Framework/Core/test/test_GroupSlicer.cxx b/Framework/Core/test/test_GroupSlicer.cxx index 85eaa9bea87e7..4117d629e0eda 100644 --- a/Framework/Core/test/test_GroupSlicer.cxx +++ b/Framework/Core/test/test_GroupSlicer.cxx @@ -334,8 +334,9 @@ BOOST_AUTO_TEST_CASE(ArrowDirectSlicing) auto evtsWriter = builderE.cursor<aod::Events>(); auto step = 0; for (auto i = 0; i < 20; ++i) { - if (i >= offsets[step + 1]) + if (i >= offsets[step + 1]) { ++step; + } evtsWriter(0, ids[step], 0.5f * i, 2.f * i, 3.f * i); } auto evtTable = builderE.finalize(); diff --git a/Framework/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index b357e51af53af..59282108fb434 100644 --- a/Framework/Foundation/include/Framework/Pack.h +++ b/Framework/Foundation/include/Framework/Pack.h @@ -100,10 +100,11 @@ constexpr auto select_pack(Result result, pack<>) template <template <typename> typename Condition, typename Result, typename T, typename... Ts> constexpr auto select_pack(Result result, pack<T, Ts...>) { - if constexpr (Condition<T>()) + if constexpr (Condition<T>()) { return select_pack<Condition>(concatenate_pack(result, pack<T>{}), pack<Ts...>{}); - else + } else { return select_pack<Condition>(result, pack<Ts...>{}); + } } template <template <typename> typename Condition, typename... Types> @@ -119,10 +120,11 @@ constexpr auto filter_pack(Result result, pack<>) template <template <typename> typename Condition, typename Result, typename T, typename... Ts> constexpr auto filter_pack(Result result, pack<T, Ts...>) { - if constexpr (Condition<T>()) + if constexpr (Condition<T>()) { return filter_pack<Condition>(result, pack<Ts...>{}); - else + } else { return filter_pack<Condition>(concatenate_pack(result, pack<T>{}), pack<Ts...>{}); + } } template <typename T> @@ -154,10 +156,12 @@ constexpr size_t has_type_at(pack<> const&) template <typename T, typename T1, typename... Ts> constexpr size_t has_type_at(pack<T1, Ts...> const&) { - if constexpr (std::is_same_v<T, T1>) + if constexpr (std::is_same_v<T, T1>) { return 0; - if constexpr (has_type_v<T, pack<T1, Ts...>>) + } + if constexpr (has_type_v<T, pack<T1, Ts...>>) { return 1 + has_type_at<T>(pack<Ts...>{}); + } return sizeof...(Ts) + 2; } diff --git a/Framework/TestWorkflows/test/test_MakeDPLObjects.cxx b/Framework/TestWorkflows/test/test_MakeDPLObjects.cxx index f39328d7d3a2c..285a0957178b9 100644 --- a/Framework/TestWorkflows/test/test_MakeDPLObjects.cxx +++ b/Framework/TestWorkflows/test/test_MakeDPLObjects.cxx @@ -56,8 +56,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) // simply make a vector of pointers, snapshot will include the latest // change, but not the one which is done after taking the snapshot std::vector<XYZ*> p; - for (auto& i : v) + for (auto& i : v) { p.push_back(&i); + } ctx.outputs().snapshot(Output{"TST", "LINEARIZED"}, p); v[999] = XYZ{3, 4, 5}; From 70322c3c01dcca4bd04652ebb4dd183ad49862ef Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Sat, 10 Oct 2020 08:46:14 +0200 Subject: [PATCH 0899/1751] adding example to iterate over muons (#4561) --- Analysis/Tasks/run2Matcher.cxx | 11 ++++- Analysis/Tasks/run3Matcher.cxx | 2 +- Analysis/Tutorials/CMakeLists.txt | 5 +++ Analysis/Tutorials/src/filters.cxx | 6 ++- Analysis/Tutorials/src/muonIteration.cxx | 42 +++++++++++++++++++ .../include/Framework/AnalysisDataModel.h | 11 +++-- 6 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 Analysis/Tutorials/src/muonIteration.cxx diff --git a/Analysis/Tasks/run2Matcher.cxx b/Analysis/Tasks/run2Matcher.cxx index e5ba8984f44d5..f680559fa121a 100644 --- a/Analysis/Tasks/run2Matcher.cxx +++ b/Analysis/Tasks/run2Matcher.cxx @@ -20,16 +20,25 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct Run2Matcher { - Builds<aod::Run2MatchedExclusive> matched_e; + BuildsExclusive<aod::Run2MatchedExclusive> matched_e; Builds<aod::Run2MatchedSparse> matched_s; void init(o2::framework::InitContext&) { } }; +struct BCMatcher { + BuildsExclusive<aod::BCCollisionsExclusive> matched_e; + Builds<aod::BCCollisionsSparse> matched; + void init(o2::framework::InitContext&) + { + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<Run2Matcher>("produce-run2-bc-matching"), + adaptAnalysisTask<BCMatcher>("bc-matcher"), }; } diff --git a/Analysis/Tasks/run3Matcher.cxx b/Analysis/Tasks/run3Matcher.cxx index f9a798a1bd973..b1877418f572f 100644 --- a/Analysis/Tasks/run3Matcher.cxx +++ b/Analysis/Tasks/run3Matcher.cxx @@ -21,7 +21,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct Run3Matcher { - Builds<aod::Run3MatchedExclusive> matched_e; + BuildsExclusive<aod::Run3MatchedExclusive> matched_e; Builds<aod::Run3MatchedSparse> matched_s; void init(o2::framework::InitContext&) { diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index f7d61f1d8818f..76260b6ce453e 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -134,3 +134,8 @@ o2_add_dpl_workflow(histogram-registry SOURCES src/histogramRegistry.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(muon-iteration + SOURCES src/muonIteration.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/filters.cxx b/Analysis/Tutorials/src/filters.cxx index 122b5c290826e..3df02db0427ae 100644 --- a/Analysis/Tutorials/src/filters.cxx +++ b/Analysis/Tutorials/src/filters.cxx @@ -69,9 +69,11 @@ struct BTask { void process(soa::Filtered<aod::Collisions>::iterator const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TPhi>> const& tracks) { - LOGF(INFO, "Collision: %d [N = %d], -10 < %.3f < 10", collision.globalIndex(), tracks.size(), collision.posZ()); + LOGF(INFO, "Collision: %d [N = %d out of %d], -10 < %.3f < 10", + collision.globalIndex(), tracks.size(), tracks.tableSize(), collision.posZ()); for (auto& track : tracks) { - LOGF(INFO, "id = %d; eta: %.3f < %.3f < %.3f; phi: %.3f < %.3f < %.3f; pt: %.3f < %.3f < %.3f", track.collisionId(), etalow, track.eta(), etaup, philow, track.nphi(), phiup, ptlow, track.pt(), ptup); + LOGF(INFO, "id = %d; eta: %.3f < %.3f < %.3f; phi: %.3f < %.3f < %.3f; pt: %.3f < %.3f < %.3f", + track.collisionId(), etalow, track.eta(), etaup, philow, track.nphi(), phiup, ptlow, track.pt(), ptup); } } }; diff --git a/Analysis/Tutorials/src/muonIteration.cxx b/Analysis/Tutorials/src/muonIteration.cxx new file mode 100644 index 0000000000000..5e3448cda554d --- /dev/null +++ b/Analysis/Tutorials/src/muonIteration.cxx @@ -0,0 +1,42 @@ +// 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" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// This task shows how to access the Muons belong to a collision +// The association is made through the BC column (and in Run 3 may not be unique!) +// To run this workflow, the o2-analysis-run(2,3)-matcher has to be run as well. +// Example: o2-analysis-run2-matcher --aod-file AO2D.root | o2-analysistutorial-muon-iteration +// +// Note that one has to subscribe to aod::Collisions const& to load +// the relevant data even if you access the data itself through m.collision() +// This uses the exclusive matcher, so you only get BCs which have a collision +// If you want also BCs without collision, you should use BCCollisionsSparse and check for m.has_collision() +struct IterateMuons { + void process(aod::BCCollisionsExclusive::iterator const& m, aod::Collisions const&, aod::Muons const& muons) + { + LOGF(INFO, "Vertex = %f has %d muons", m.collision().posZ(), muons.size()); + for (auto& muon : muons) { + LOGF(info, " pT = %.2f", muon.pt()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<IterateMuons>("iterate-muons"), + }; +} diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index fc50e4e105fb3..05c9e7558c4cf 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -622,12 +622,15 @@ DECLARE_SOA_INDEX_COLUMN(Run2V0, run2v0); } // namespace indices #define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::Run2V0Id -DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MATCHED", INDEX_LIST_RUN2); -DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MATCHED", INDEX_LIST_RUN2); +DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); +DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); #define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0Id, indices::FDDId -DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MATCHED", INDEX_LIST_RUN3); -DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MATCHED", INDEX_LIST_RUN3); +DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); +DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MA_RN3_SP", INDEX_LIST_RUN3); + +DECLARE_SOA_INDEX_TABLE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); +DECLARE_SOA_INDEX_TABLE(BCCollisionsSparse, BCs, "MA_BCCOL_SP", indices::BCId, indices::CollisionId); } // namespace aod From dfdb279cb8efcac2177b9fe6fae17c9943dc4500 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 10 Oct 2020 08:50:16 +0200 Subject: [PATCH 0900/1751] Fix missing include (#4550) --- Common/Utils/include/CommonUtils/ShmManager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Common/Utils/include/CommonUtils/ShmManager.h b/Common/Utils/include/CommonUtils/ShmManager.h index b59998c36289f..72308780bff16 100644 --- a/Common/Utils/include/CommonUtils/ShmManager.h +++ b/Common/Utils/include/CommonUtils/ShmManager.h @@ -20,6 +20,7 @@ #include <list> #include <cstddef> +#include <atomic> #include <boost/interprocess/managed_external_buffer.hpp> #include <boost/interprocess/allocators/allocator.hpp> From 8215220c90bac4fe31c88c56476816d70af4f693 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sat, 10 Oct 2020 08:50:56 +0200 Subject: [PATCH 0901/1751] DPL Analysis: move empty table protection from Table constructor to input record extraction (#4549) --- Framework/Core/include/Framework/ASoA.h | 4 ++-- Framework/Core/include/Framework/AnalysisTask.h | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 76a4b1566f056..f184ce55b5124 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -909,10 +909,10 @@ class Table Table(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : mTable(table), - mEnd{table == nullptr ? 0 : static_cast<uint64_t>(table->num_rows())}, + mEnd{static_cast<uint64_t>(table->num_rows())}, mOffset(offset) { - if ((mTable == nullptr) or (mTable->num_rows() == 0)) { + if (mTable->num_rows() == 0) { for (size_t ci = 0; ci < sizeof...(C); ++ci) { mColumnChunks[ci] = nullptr; } diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index bbcdb028f36b3..f0c267f9e9ad7 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -110,7 +110,11 @@ struct AnalysisDataProcessorBuilder { static auto extractTableFromRecord(InputRecord& record) { if constexpr (soa::is_type_with_metadata_v<aod::MetadataTrait<T>>) { - return record.get<TableConsumer>(aod::MetadataTrait<T>::metadata::tableLabel())->asArrowTable(); + auto table = record.get<TableConsumer>(aod::MetadataTrait<T>::metadata::tableLabel())->asArrowTable(); + if (table->num_rows() == 0) { + table = makeEmptyTable<T>(); + } + return table; } else if constexpr (soa::is_type_with_originals_v<T>) { return extractFromRecord<T>(record, typename T::originals{}); } From b4a5cf1c90fd10c5a083427f06898280f466f5e5 Mon Sep 17 00:00:00 2001 From: Matteo Concas <mconcas@cern.ch> Date: Sat, 10 Oct 2020 08:52:14 +0200 Subject: [PATCH 0902/1751] Add READMEs for Upgrade section (#4526) --- Detectors/Upgrades/IT3/README.md | 17 +++++++++++++++++ Detectors/Upgrades/PostLS4/IT4/README.md | 17 +++++++++++++++++ Detectors/Upgrades/README.md | 19 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 Detectors/Upgrades/IT3/README.md create mode 100644 Detectors/Upgrades/PostLS4/IT4/README.md create mode 100644 Detectors/Upgrades/README.md diff --git a/Detectors/Upgrades/IT3/README.md b/Detectors/Upgrades/IT3/README.md new file mode 100644 index 0000000000000..3d57a976c41fa --- /dev/null +++ b/Detectors/Upgrades/IT3/README.md @@ -0,0 +1,17 @@ +# IT3 +Upgraded version of the ITS that includes upgraded truly-cylindrical inner barrel. + +# Run the full simulation +Provided O2 has been compiled with upgrades enabled, it is possible to simulate ITS 3 geometry within the `o2-sim` executable. + +## Simulation +IT3 module is enabled via the `-m IT3` parameter. +In case of `PIPE` to be enabled, the size of the beam pipe is automatically scaled to what is foreseen for the upgrades. + +Typical command to generate MC data: +```bash +o2-sim -m PIPE IT3 [...] +``` + +## Reconstruction +Currently, the reconstruction is driven the `macro/run_trac_alice3.C`, which takes as input the hits generated by simulation. Hits can be smeared upon request (see `kUseSmearing`). \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/README.md b/Detectors/Upgrades/PostLS4/IT4/README.md new file mode 100644 index 0000000000000..672f26326d8e1 --- /dev/null +++ b/Detectors/Upgrades/PostLS4/IT4/README.md @@ -0,0 +1,17 @@ +# IT4 +At the moment the IT4 name is a placeholder for barrel detector. + +# Run the full simulation +Provided O2 has been compiled with upgrades enabled, it is possible to simulate IT4 geometry within the `o2-sim` executable. + +## Simulation +IT4 module is enabled via the `-m IT4` parameter. +In case of `PIPE` to be enabled, the size of the beam pipe is automatically scaled to what is foreseen for the upgrades. + +Typical command to generate MC data: +```bash +o2-sim -m PIPE IT4 [...] +``` + +## Reconstruction +Currently, the reconstruction is driven the `macro/run_trac_alice3.C`, which takes as input the hits generated by simulation. Hits can be smeared upon request (see `kUseSmearing`). \ No newline at end of file diff --git a/Detectors/Upgrades/README.md b/Detectors/Upgrades/README.md new file mode 100644 index 0000000000000..c71db05187e1e --- /dev/null +++ b/Detectors/Upgrades/README.md @@ -0,0 +1,19 @@ +<!-- doxy +\page refDetectorsITSMFT ITSMFT +/doxy --> + +# Upgrades +This is a top page for detectors not included in Run 3 layout. + +# Installation + +To enable the compilation of this section it is required to prepend the `ENABLE_UPGRADES=ON` to the installation command, for instance: + +```bash +ENABLE_UPGRADES=ON aliBuild build O2 --defaults o2 +``` + +<!-- doxy +* \subpage refIT3 +* \subpage refPostLS4 +/doxy --> \ No newline at end of file From 3e02abfc267329ace4d12e650dde1b92616c7c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Sat, 10 Oct 2020 09:42:39 +0200 Subject: [PATCH 0903/1751] PWGHF: Adjust names of HF-related files and variables. Move trackUtilities.h to Analysis/Core. Split histograms. (#4565) * Move trackUtilities.h to Analysis/Core. * PWGHF: Adjust names of HF-related files and variables. * PWGHF: Make an impact parameter histogram for each prong. --- .../include/Analysis/trackUtilities.h | 0 ...nTables.h => HFCandidateSelectionTables.h} | 12 +++++----- ...econdaryVertexHF.h => HFSecondaryVertex.h} | 24 +++++++++---------- Analysis/DataModel/src/aodDataModelGraph.cxx | 2 +- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 2 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 2 +- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 4 ++-- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 8 +++---- Analysis/Tasks/PWGHF/taskD0.cxx | 13 +++++----- Analysis/Tasks/PWGHF/taskDPlus.cxx | 6 ++--- Analysis/Tasks/PWGLF/cascadefinder.cxx | 2 +- Analysis/Tasks/PWGLF/cascadeproducer.cxx | 2 +- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 2 +- Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 2 +- 14 files changed, 41 insertions(+), 40 deletions(-) rename Analysis/{DataModel => Core}/include/Analysis/trackUtilities.h (100%) rename Analysis/DataModel/include/Analysis/{CandidateSelectionTables.h => HFCandidateSelectionTables.h} (65%) rename Analysis/DataModel/include/Analysis/{SecondaryVertexHF.h => HFSecondaryVertex.h} (97%) diff --git a/Analysis/DataModel/include/Analysis/trackUtilities.h b/Analysis/Core/include/Analysis/trackUtilities.h similarity index 100% rename from Analysis/DataModel/include/Analysis/trackUtilities.h rename to Analysis/Core/include/Analysis/trackUtilities.h diff --git a/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h b/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h similarity index 65% rename from Analysis/DataModel/include/Analysis/CandidateSelectionTables.h rename to Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h index 9bc168244a7b9..9507e32113e4b 100644 --- a/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h @@ -8,17 +8,17 @@ // 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_ +#ifndef O2_ANALYSIS_HFCANDIDATESELECTIONTABLES_H_ +#define O2_ANALYSIS_HFCANDIDATESELECTIONTABLES_H_ namespace o2::aod { -namespace hfselcandidate +namespace hf_selcandidate { 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 hf_selcandidate +DECLARE_SOA_TABLE(HFSelD0Candidate, "AOD", "HFSELD0CAND", hf_selcandidate::IsSelD0, hf_selcandidate::IsSelD0bar); } // namespace o2::aod -#endif // O2_ANALYSIS_CANDIDATESELECTIONTABLES_H_ +#endif // O2_ANALYSIS_HFCANDIDATESELECTIONTABLES_H_ diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h similarity index 97% rename from Analysis/DataModel/include/Analysis/SecondaryVertexHF.h rename to Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 38717adba46c0..b24b1ea0f1ff0 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -8,14 +8,14 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file SecondaryVertexHF.h +/// \file HFSecondaryVertex.h /// \brief Definitions of tables of heavy-flavour decay candidates. /// /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN /// \author Vít Kučera <vit.kucera@cern.ch>, CERN -#ifndef O2_ANALYSIS_SECONDARYVERTEXHF_H_ -#define O2_ANALYSIS_SECONDARYVERTEXHF_H_ +#ifndef O2_ANALYSIS_HFSECONDARYVERTEX_H_ +#define O2_ANALYSIS_HFSECONDARYVERTEX_H_ #include "Framework/AnalysisDataModel.h" #include "Analysis/RecoDecay.h" @@ -23,20 +23,20 @@ namespace o2::aod { -namespace seltrack +namespace hf_seltrack { DECLARE_SOA_COLUMN(IsSel2Prong, isSel2Prong, int); DECLARE_SOA_COLUMN(IsSel3Prong, isSel3Prong, int); DECLARE_SOA_COLUMN(DCAPrim0, dcaPrim0, float); DECLARE_SOA_COLUMN(DCAPrim1, dcaPrim1, float); -} // namespace seltrack -DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", - seltrack::IsSel2Prong, - seltrack::IsSel3Prong, - seltrack::DCAPrim0, - seltrack::DCAPrim1); +} // namespace hf_seltrack +DECLARE_SOA_TABLE(HFSelTrack, "AOD", "SELTRACK", + hf_seltrack::IsSel2Prong, + hf_seltrack::IsSel3Prong, + hf_seltrack::DCAPrim0, + hf_seltrack::DCAPrim1); -using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, SelTrack, pidRespTPC, pidRespTOF>; +using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, HFSelTrack, pidRespTPC, pidRespTOF>; // FIXME: this is a workaround until we get the index columns to work with joins. @@ -330,4 +330,4 @@ using HfCandProng3 = HfCandProng3Ext; } // namespace o2::aod -#endif // O2_ANALYSIS_SECONDARYVERTEXHF_H_ +#endif // O2_ANALYSIS_HFSECONDARYVERTEX_H_ diff --git a/Analysis/DataModel/src/aodDataModelGraph.cxx b/Analysis/DataModel/src/aodDataModelGraph.cxx index 4683a45e1f8a2..5b9a60f7e727c 100644 --- a/Analysis/DataModel/src/aodDataModelGraph.cxx +++ b/Analysis/DataModel/src/aodDataModelGraph.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/AnalysisDataModel.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "PID/PIDResponse.h" #include "Analysis/Multiplicity.h" #include "Analysis/Centrality.h" diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 93c0f2e980fc0..455ef64174783 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -17,7 +17,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "Analysis/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 36304ae40e4b4..21d5f02fcaafb 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -17,7 +17,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "Analysis/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index 3aa45deeba0ac..30f88a2e98a38 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -15,8 +15,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/SecondaryVertexHF.h" -#include "Analysis/CandidateSelectionTables.h" +#include "Analysis/HFSecondaryVertex.h" +#include "Analysis/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 8a6d6908f9786..c75ca881942b2 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -17,7 +17,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "Analysis/trackUtilities.h" using namespace o2; @@ -26,7 +26,7 @@ using namespace o2::framework::expressions; /// Track selection struct SelectTracks { - Produces<aod::SelTrack> rowSelectedTrack; + Produces<aod::HFSelTrack> rowSelectedTrack; Configurable<double> ptmintrack_2prong{"ptmintrack_2prong", -1, "ptmin single track"}; Configurable<double> dcatoprimxymin_2prong{"dcatoprimxymin_2prong", 0, "dca xy to prim vtx min"}; Configurable<double> etamax_2prong{"etamax_2prong", 999, "maximum pseudorapidity value"}; @@ -122,8 +122,8 @@ struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hvtx3_y_out{TH1F("hvtx3_y", "3-track vtx", 1000, -2.0, 2.0)}; OutputObj<TH1F> hvtx3_z_out{TH1F("hvtx3_z", "3-track vtx", 1000, -20.0, 20.0)}; - Filter filterSelectTracks = aod::seltrack::isSel2Prong == 1; - using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::SelTrack>>; + Filter filterSelectTracks = aod::hf_seltrack::isSel2Prong == 1; + using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::HFSelTrack>>; // FIXME //Partition<SelectedTracks> tracksPos = aod::track::signed1Pt > 0.f; //Partition<SelectedTracks> tracksNeg = aod::track::signed1Pt < 0.f; diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index 71224825e08c2..194651790902a 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -16,8 +16,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/SecondaryVertexHF.h" -#include "Analysis/CandidateSelectionTables.h" +#include "Analysis/HFSecondaryVertex.h" +#include "Analysis/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; @@ -32,7 +32,8 @@ struct TaskD0 { OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0, 10.0)}; OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.0)}; OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.0)}; - OutputObj<TH1F> hd0{TH1F("hd0", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; + OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "prong 0 dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; + OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "prong 1 dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; OutputObj<TH1F> hd0d0{TH1F("hd0d0", "product of dca xy to prim. vertex (cm^{2})", 500, -1.0, 1.0)}; OutputObj<TH1F> hCTS{TH1F("hCTS", "cos #it{#theta}*", 120, -1.1, 1.1)}; OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; @@ -45,7 +46,7 @@ struct TaskD0 { Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; - Filter seltrack = (aod::hfselcandidate::isSelD0 >= d_selectionFlagD0 || aod::hfselcandidate::isSelD0bar >= d_selectionFlagD0bar); + Filter filterSelectCandidates = (aod::hf_selcandidate::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate::isSelD0bar >= d_selectionFlagD0bar); void process(soa::Filtered<soa::Join<aod::HfCandProng2, aod::HFSelD0Candidate>> const& candidates) { @@ -61,8 +62,8 @@ struct TaskD0 { hptprong1->Fill(candidate.ptProng1()); hdeclength->Fill(candidate.decayLength()); hdeclengthxy->Fill(candidate.decayLengthXY()); - hd0->Fill(candidate.impactParameter0()); - hd0->Fill(candidate.impactParameter1()); + hd0Prong0->Fill(candidate.impactParameter0()); + hd0Prong1->Fill(candidate.impactParameter1()); hd0d0->Fill(candidate.impactParameterProduct()); hCTS->Fill(CosThetaStarD0(candidate)); hCt->Fill(CtD0(candidate)); diff --git a/Analysis/Tasks/PWGHF/taskDPlus.cxx b/Analysis/Tasks/PWGHF/taskDPlus.cxx index 01c30df080ebe..5ea0ca4f1cd98 100644 --- a/Analysis/Tasks/PWGHF/taskDPlus.cxx +++ b/Analysis/Tasks/PWGHF/taskDPlus.cxx @@ -16,8 +16,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/SecondaryVertexHF.h" -#include "Analysis/CandidateSelectionTables.h" +#include "Analysis/HFSecondaryVertex.h" +#include "Analysis/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; @@ -43,7 +43,7 @@ struct TaskDPlus { Configurable<int> d_selectionFlagDPlus{"d_selectionFlagDPlus", 1, "Selection Flag for DPlus"}; - //Filter seltrack = (aod::hfselcandidate::isSelDPlus >= d_selectionFlagDPlus); + //Filter filterSelectCandidates = (aod::hf_selcandidate::isSelDPlus >= d_selectionFlagDPlus); //void process(soa::Filtered<soa::Join<aod::HfCandProng3, aod::HFSelDPlusCandidate>> const& candidates) void process(aod::HfCandProng3 const& candidates) diff --git a/Analysis/Tasks/PWGLF/cascadefinder.cxx b/Analysis/Tasks/PWGLF/cascadefinder.cxx index 00ea444406a00..ab8c4391bfb08 100644 --- a/Analysis/Tasks/PWGLF/cascadefinder.cxx +++ b/Analysis/Tasks/PWGLF/cascadefinder.cxx @@ -14,7 +14,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx index 11cf0abe558d3..64a31f22699c6 100644 --- a/Analysis/Tasks/PWGLF/cascadeproducer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -11,7 +11,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index 1e72a6f25ef20..7605546ba775f 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -14,7 +14,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index a56a3a6f2a31f..69664b67f5e50 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -11,7 +11,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" From 8ad067042f522779fefa5c4adac377b3d1b3994d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Sat, 10 Oct 2020 09:43:10 +0200 Subject: [PATCH 0904/1751] Update tutorial for ccdb/timestamp access (#4563) --- Analysis/Tutorials/src/ccdbaccess.cxx | 31 ++++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Analysis/Tutorials/src/ccdbaccess.cxx b/Analysis/Tutorials/src/ccdbaccess.cxx index 2061a23532a79..0d2718e50eac6 100644 --- a/Analysis/Tutorials/src/ccdbaccess.cxx +++ b/Analysis/Tutorials/src/ccdbaccess.cxx @@ -8,13 +8,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// -// A tutorial task to retrieve objects from CCDB given a run number -// -// Author: Nicolo' Jacazio on 2020-06-22 +/// +/// \brief A tutorial task to retrieve objects from CCDB given a run number. +/// The tutorial shows also how to use timestamps in your analysis. +/// This task requires to access the timestamp table in order to be working. +/// Currently this is done by adding `o2-analysis-timestamp` to the workflow +/// \author Nicolo' Jacazio +/// \since 2020-06-22 +/// #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" #include <CCDB/BasicCCDBManager.h> #include "CommonDataFormat/InteractionRecord.h" @@ -40,16 +45,16 @@ struct TimestampUserTask { ccdb->setCreatedNotAfter(nolaterthan.value); } - void process(soa::Join<aod::BCs, aod::Timestamps> const& iter) + void process(aod::Collision const& collision, aod::BCsWithTimestamps const& /*bc*/) { - for (auto i : iter) { - auto obj = ccdb->getForTimeStamp<TH2F>(path.value, i.timestamp()); - if (obj) { - LOGF(info, "Found object!"); - obj->Print("all"); - } else { - LOGF(warning, "Object not found!"); - } + auto bc = collision.bc_as<aod::BCsWithTimestamps>(); + LOGF(info, "Getting object %s for run number %i from timestamp=%llu", path.value.data(), bc.runNumber(), bc.timestamp()); + auto obj = ccdb->getForTimeStamp<TH2F>(path.value, bc.timestamp()); + if (obj) { + LOGF(info, "Found object!"); + obj->Print("all"); + } else { + LOGF(warning, "Object not found!"); } } }; From e91df90b25fcfe8f2033f34301847ac1e946f977 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sat, 10 Oct 2020 09:43:56 +0200 Subject: [PATCH 0905/1751] Analysis: update multiplicity table producer to use current features (#4554) --- Analysis/Tasks/multiplicityTable.cxx | 52 ++++++++++------------------ 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/Analysis/Tasks/multiplicityTable.cxx b/Analysis/Tasks/multiplicityTable.cxx index ed5187af5ebcd..d02ec15a48b74 100644 --- a/Analysis/Tasks/multiplicityTable.cxx +++ b/Analysis/Tasks/multiplicityTable.cxx @@ -16,43 +16,29 @@ using namespace o2; using namespace o2::framework; -struct MultiplicityTableTask { +struct MultiplicityTableTaskIndexed { Produces<aod::Mults> mult; + Partition<aod::Tracks> tracklets = (aod::track::trackType == static_cast<uint8_t>(o2::aod::track::TrackTypeEnum::Run2Tracklet)); - aod::Run2V0 getVZero(aod::BC const& bc, aod::Run2V0s const& vzeros) + void process(aod::Run2MatchedSparse::iterator const& collision, aod::Tracks const& tracks, aod::BCs const&, aod::Zdcs const&, aod::Run2V0s const&) { - for (auto& vzero : vzeros) - if (vzero.bc() == bc) - return vzero; - aod::Run2V0 dummy; - return dummy; - } - - aod::Zdc getZdc(aod::BC const& bc, aod::Zdcs const& zdcs) - { - for (auto& zdc : zdcs) - if (zdc.bc() == bc) - return zdc; - aod::Zdc dummy; - return dummy; - } - - void process(aod::Collision const& collision, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::Tracks const& tracks) - { - auto zdc = getZdc(collision.bc(), zdcs); - auto vzero = getVZero(collision.bc(), vzeros); - float multV0A = vzero.multA(); - float multV0C = vzero.multC(); - float multZNA = zdc.energyCommonZNA(); - float multZNC = zdc.energyCommonZNC(); - - int multTracklets = 0; - for (auto& tr : tracks) - if (tr.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet) - multTracklets++; + float multV0A = -1.f; + float multV0C = -1.f; + float multZNA = -1.f; + float multZNC = -1.f; + int multTracklets = tracklets.size(); + if (collision.has_run2v0()) { + auto v0 = collision.run2v0(); + multV0A = v0.multA(); + multV0C = v0.multC(); + } + if (collision.has_zdc()) { + auto zdc = collision.zdc(); + multZNA = zdc.energyCommonZNA(); + multZNC = zdc.energyCommonZNC(); + } LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multZNA=%6.0f multZNC=%6.0f multTracklets=%i", multV0A, multV0C, multZNA, multZNC, multTracklets); - // fill multiplicity columns mult(multV0A, multV0C, multZNA, multZNC, multTracklets); } }; @@ -60,5 +46,5 @@ struct MultiplicityTableTask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<MultiplicityTableTask>("multiplicity-table")}; + adaptAnalysisTask<MultiplicityTableTaskIndexed>("multiplicity-table")}; } From 03f9ed032dd11e44ed295f68ab3ae01422a5cb14 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Fri, 9 Oct 2020 14:17:22 +0200 Subject: [PATCH 0906/1751] MFT: add flag for MFT data in GBT data word --- .../include/ITSMFTReconstruction/ChipMappingMFT.h | 2 +- .../reconstruction/include/ITSMFTReconstruction/GBTWord.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h index af425caef1564..242b020b32e07 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h @@ -99,7 +99,7 @@ class ChipMappingMFT ///< get number of chips served by single cable on given RU type uint8_t getGBTHeaderRUType(Int_t ruType, Int_t cableHW) { - return (cableHW & 0x1f); + return ((0x1 << 7) + (cableHW & 0x1f)); } ///< convert HW cable ID to its position on the ActiveLanes word in the GBT.header for given RU type diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h index 7a3bf776c0a05..43b063ed4baef 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTWord.h @@ -41,6 +41,8 @@ constexpr uint8_t GBTFlagRDH = 0x00; constexpr uint8_t GBTFlagDataIB = 0x20; // GBT header flag for the ITS OB: 010 bb ccc with bb -> Connector Number (00,01,10,11), ccc -> Lane Number (0-6) constexpr uint8_t GBTFlagDataOB = 0x40; +// GBT header flag for the MFT +constexpr uint8_t GBTFlagDataMFT = 0x80; // GBT header flag for the ITS IB idagnostic : 101 bbbbb with bbbbb -> Lane Number (0-8) constexpr uint8_t GBTFlagDiagnosticIB = 0xa0; // GBT header flag for the ITS OB diagnostic word: 110 bb ccc with bb -> Connector Number (00,01,10,11), ccc -> Lane Number (0-6) @@ -144,11 +146,14 @@ struct GBTWord { /// check if the GBT Header corresponds to ITS OB data (header is combined with lanes/connector info) bool isDataOB() const { return (id & 0xe0) == GBTFlagDataOB; } + /// check if the GBT Header corresponds to MFT data (header is combined with cable number) + bool isDataMFT() const { return (id & 0xe0) == GBTFlagDataMFT; } + /// check if the GBT Header corresponds to ITS OB diagnostics data (header is combined with lanes info) bool isCableDiagnosticOB() const { return (id & 0xe0) == GBTFlagDiagnosticIB; } /// check if the GBT Header corresponds to ITS IB or OB data (header is combined with lanes/connector info) - bool isData() const { return isDataIB() || isDataOB(); } + bool isData() const { return isDataIB() || isDataOB() || isDataMFT(); } bool isCableDiagnostic() const { return isCableDiagnosticIB() || isCableDiagnosticIB(); } From 246728d318705e04594360801b023696b793aa1f Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Fri, 9 Oct 2020 11:57:09 +0200 Subject: [PATCH 0907/1751] [EMCAL-515] Use signed type for time calib values In run3 we will shift the time already during reconstruction by 600 ns in order to center it around 0, therefore the time calib will need to be done with respect to the shifted time, meaing the time calib params can become negative. Therefore a signed type is mandatory. --- .../calib/include/EMCALCalib/TimeCalibrationParams.h | 8 ++++---- Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Detectors/EMCAL/calib/include/EMCALCalib/TimeCalibrationParams.h b/Detectors/EMCAL/calib/include/EMCALCalib/TimeCalibrationParams.h index e1858c1742c1d..610daefedb264 100644 --- a/Detectors/EMCAL/calib/include/EMCALCalib/TimeCalibrationParams.h +++ b/Detectors/EMCAL/calib/include/EMCALCalib/TimeCalibrationParams.h @@ -62,13 +62,13 @@ class TimeCalibrationParams /// \param cellID Absolute ID of cell /// \param time is the calibration coefficient /// \param isLowGain is flag whether this cell is LG or HG - void addTimeCalibParam(unsigned short cellID, unsigned short time, bool isLowGain); + void addTimeCalibParam(unsigned short cellID, short time, bool isLowGain); /// \brief Get the time calibration coefficient for a certain cell /// \param cellID Absolute ID of cell /// \param isLowGain is flag whether this cell is LG or HG /// \return time calibration coefficient of the cell - unsigned short getTimeCalibParam(unsigned short cellID, bool isLowGain) const; + short getTimeCalibParam(unsigned short cellID, bool isLowGain) const; /// \brief Convert the time calibration coefficient array to a histogram /// \param isLowGain is flag whether to draw for LG or HG @@ -76,8 +76,8 @@ class TimeCalibrationParams TH1* getHistogramRepresentation(bool isLowGain) const; private: - std::array<unsigned short, 17664> mTimeCalibParamsHG; ///< Container for the time calibration coefficient for the High Gain cells - std::array<unsigned short, 17664> mTimeCalibParamsLG; ///< Container for the time calibration coefficient for the Low Gain cells + std::array<short, 17664> mTimeCalibParamsHG; ///< Container for the time calibration coefficient for the High Gain cells + std::array<short, 17664> mTimeCalibParamsLG; ///< Container for the time calibration coefficient for the Low Gain cells ClassDefNV(TimeCalibrationParams, 1); }; diff --git a/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx b/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx index 019624e6a94f6..31624df6761cd 100644 --- a/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx +++ b/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx @@ -18,7 +18,7 @@ using namespace o2::emcal; -void TimeCalibrationParams::addTimeCalibParam(unsigned short cellID, unsigned short time, bool isLowGain) +void TimeCalibrationParams::addTimeCalibParam(unsigned short cellID, short time, bool isLowGain) { if (!isLowGain) mTimeCalibParamsHG[cellID] = time; @@ -26,7 +26,7 @@ void TimeCalibrationParams::addTimeCalibParam(unsigned short cellID, unsigned sh mTimeCalibParamsLG[cellID] = time; } -unsigned short TimeCalibrationParams::getTimeCalibParam(unsigned short cellID, bool isLowGain) const +short TimeCalibrationParams::getTimeCalibParam(unsigned short cellID, bool isLowGain) const { if (isLowGain) return mTimeCalibParamsLG[cellID]; From fa88a0ccfd862a9661d7c970941f3d32641846e8 Mon Sep 17 00:00:00 2001 From: cortesep <57937610+cortesep@users.noreply.github.com> Date: Sat, 10 Oct 2020 16:18:36 +0200 Subject: [PATCH 0908/1751] Dev zdcmap - Geographical mapping of autotrigger bits and correct treatment of noise of duplicate channels (#4558) * Correct typos * Adding more lineshapes * Autotrigger bits are now for all channels. Rename to Hits * Discriminator are enabled on all channels * New data member for discriminated channels that are actually used for triggering * Move AllChannelsMask to highest bit * Correcting mistake * Enable hits on non triggering channels * Introduce hits besides triggers * Allow triggering on all channels * Correct coding conventions * Updated comment * Apply clang-format * Fix link ID * Separate word trigger word for ALICE trigger * Change formatting * Change meaning of autotrigger bits, from logical (signal) to geographical (module,channel). Proper treatment of signal noise for channels that are acquired on two modules (one for trigger and readout and on another for triggering) * Removing comments * correct clang format * Updated comments Co-authored-by: cortese <cortese@fis01.disit.uniupo.it> --- .../ZDC/include/DataFormatsZDC/BCData.h | 8 +- DataFormats/Detectors/ZDC/src/BCData.cxx | 28 ++- DataFormats/Detectors/ZDC/src/ChannelData.cxx | 2 +- .../ZDC/base/include/ZDCBase/Constants.h | 7 +- .../ZDC/base/include/ZDCBase/ModuleConfig.h | 2 + Detectors/ZDC/base/src/ModuleConfig.cxx | 23 ++- Detectors/ZDC/macro/CreateModuleConfig.C | 66 +++---- .../include/ZDCSimulation/Digitizer.h | 4 +- Detectors/ZDC/simulation/src/Digitizer.cxx | 164 ++++++++++-------- 9 files changed, 186 insertions(+), 118 deletions(-) diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/BCData.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/BCData.h index db805b9b2ed52..32213f8ec4d58 100644 --- a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/BCData.h +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/BCData.h @@ -31,17 +31,19 @@ struct BCData { /// we are going to refer to at most 26 channels, so 5 bits for the NChannels and 27 for the reference o2::dataformats::RangeRefComp<5> ref; o2::InteractionRecord ir; - uint32_t channels = 0; // pattern of channels it refers to - uint32_t triggers = 0; // pattern of triggered channels (not necessarily stored) in this BC + uint32_t channels = 0; // pattern of channels it refers to + uint32_t triggers = 0; // pattern of triggered channels (not necessarily stored) in this BC + uint8_t ext_triggers = 0; // pattern of ALICE triggers BCData() = default; - BCData(int first, int ne, o2::InteractionRecord iRec, uint32_t chSto, uint32_t chTrig) + BCData(int first, int ne, o2::InteractionRecord iRec, uint32_t chSto, uint32_t chTrig, uint8_t extTrig) { ref.setFirstEntry(first); ref.setEntries(ne); ir = iRec; channels = chSto; triggers = chTrig; + ext_triggers = extTrig; } gsl::span<const ChannelData> getBunchChannelData(const gsl::span<const ChannelData> tfdata) const; diff --git a/DataFormats/Detectors/ZDC/src/BCData.cxx b/DataFormats/Detectors/ZDC/src/BCData.cxx index 38cf592475b99..3f35c5e441949 100644 --- a/DataFormats/Detectors/ZDC/src/BCData.cxx +++ b/DataFormats/Detectors/ZDC/src/BCData.cxx @@ -18,16 +18,32 @@ void BCData::print() const { ir.print(); printf("%d channels starting from %d\n", ref.getEntries(), ref.getFirstEntry()); - printf("Read : ["); - for (int ic = 0; ic < NChannels; ic++) { + printf("Read:"); + for (int ic = 0; ic < NDigiChannels; ic++) { + if (ic % NChPerModule == 0) { + if (ic == 0) + printf(" %d[", ic / NChPerModule); + else + printf("] %d[", ic / NChPerModule); + } if (channels & (0x1 << ic)) { - printf("%s ", channelName(ic)); + printf("R"); + } else { + printf(" "); } } - printf("] Hits: ["); - for (int ic = 0; ic < NChannels; ic++) { + printf("]\nHits:"); + for (int ic = 0; ic < NDigiChannels; ic++) { + if (ic % NChPerModule == 0) { + if (ic == 0) + printf(" %d[", ic / NChPerModule); + else + printf("] %d[", ic / NChPerModule); + } if (triggers & (0x1 << ic)) { - printf("%s ", channelName(ic)); + printf("H"); + } else { + printf(" "); } } printf("]\n"); diff --git a/DataFormats/Detectors/ZDC/src/ChannelData.cxx b/DataFormats/Detectors/ZDC/src/ChannelData.cxx index c1391cc6f17f6..a29f977762e02 100644 --- a/DataFormats/Detectors/ZDC/src/ChannelData.cxx +++ b/DataFormats/Detectors/ZDC/src/ChannelData.cxx @@ -14,7 +14,7 @@ using namespace o2::zdc; void ChannelData::print() const { - printf("Ch%2d | ", id); + printf("Sig %2d | ", id); for (int i = 0; i < NTimeBinsPerBC; i++) { printf("%+5d ", data[i]); } diff --git a/Detectors/ZDC/base/include/ZDCBase/Constants.h b/Detectors/ZDC/base/include/ZDCBase/Constants.h index 904567296acf4..ce8b42800bb99 100644 --- a/Detectors/ZDC/base/include/ZDCBase/Constants.h +++ b/Detectors/ZDC/base/include/ZDCBase/Constants.h @@ -39,8 +39,8 @@ enum ChannelTypeZNP { Common, enum ChannelTypeZEM { ZEMCh1, ZEMCh2 }; // channel IDs for ZEMs -constexpr int NTimeBinsPerBC = 12; //< number of samples per BC -constexpr int NBCReadOut = 4; // N BCs read out per trigger +constexpr int NTimeBinsPerBC = 12; //< number of samples per BC +constexpr int NBCReadOut = 4; // N BCs read out per trigger constexpr int NTimeBinsReadout = NTimeBinsPerBC * NBCReadOut; constexpr int NChannelsZN = 6; //< number of channels stored per ZN @@ -51,10 +51,11 @@ constexpr float ChannelTimeBinNS = 2.; //< bin length in NS constexpr float SampleLenghtNS = NTimeBinsPerBC * ChannelTimeBinNS; constexpr int NChannels = 2 * (NChannelsZN + NChannelsZP) + NChannelsZEM; -constexpr uint32_t AllChannelsMask = (0x1 << NChannels) - 1; +constexpr uint8_t ALICETriggerMask = 0x1; constexpr int NModules = 8; constexpr int NChPerModule = 4; +constexpr int NDigiChannels = NModules * NChPerModule; constexpr int NWPerBc = 3; constexpr int MaxTriggerChannels = NChannels; diff --git a/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h b/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h index f10a8870ca538..1ffef071f7aa6 100644 --- a/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h +++ b/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h @@ -41,6 +41,8 @@ struct Module { void setChannel(int slot, int8_t chID, int16_t lID, bool read, bool trig = false, int tF = 0, int tL = 0, int tS = 0, int tT = 0); void print() const; + void printCh() const; + void printTrig() const; void check() const; ClassDefNV(Module, 1); }; diff --git a/Detectors/ZDC/base/src/ModuleConfig.cxx b/Detectors/ZDC/base/src/ModuleConfig.cxx index 35c24d08a8abd..ca56b67c426eb 100644 --- a/Detectors/ZDC/base/src/ModuleConfig.cxx +++ b/Detectors/ZDC/base/src/ModuleConfig.cxx @@ -14,14 +14,18 @@ using namespace o2::zdc; -void Module::print() const +void Module::printCh() const { printf("Module %d [ChID/LinkID R:T ]", id); for (int ic = 0; ic < MaxChannels; ic++) { - printf("[%s{%2d}/L%02d %c:%c ]", channelName(channelID[ic]), channelID[ic], linkID[ic], readChannel[ic] ? '+' : '-', trigChannel[ic] ? '+' : '-'); + printf("[%s{%2d}/L%02d %c:%c ]", channelName(channelID[ic]), channelID[ic], linkID[ic], readChannel[ic] ? 'R' : ' ', trigChannel[ic] ? 'T' : ' '); } printf("\n"); - printf("Trigger conf: "); +} + +void Module::printTrig() const +{ + printf("Trigger conf %d: ", id); for (int ic = 0; ic < MaxChannels; ic++) { const auto& cnf = trigChannelConf[ic]; if (trigChannel[ic]) { @@ -33,12 +37,23 @@ void Module::print() const printf("\n"); } +void Module::print() const +{ + printCh(); + printTrig(); +} + void ModuleConfig::print() const { printf("Modules configuration:\n"); for (const auto& md : modules) { if (md.id >= 0) { - md.print(); + md.printCh(); + } + } + for (const auto& md : modules) { + if (md.id >= 0) { + md.printTrig(); } } } diff --git a/Detectors/ZDC/macro/CreateModuleConfig.C b/Detectors/ZDC/macro/CreateModuleConfig.C index 82c63e91cebac..d992c10230f01 100644 --- a/Detectors/ZDC/macro/CreateModuleConfig.C +++ b/Detectors/ZDC/macro/CreateModuleConfig.C @@ -34,14 +34,16 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, //------------------------------------------- // Up to 8 modules with four channels // setChannel(int slot, int8_t chID, int16_t lID, bool read, bool trig = false, int tF = 0, int tL = 0, int tS = 0, int tT = 0) + // module id must be in the range 0-7 + // channel id must be in range 0-3 { modID = 0; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZNAC, 0, true, true, -5, 6, 4, 12); - module.setChannel(1, IdZNASum, 1, false, false, -5, 6, 4, 12); - module.setChannel(2, IdZNA1, 2, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZNA2, 3, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZNAC, 2 * modID, true, true, -5, 6, 4, 12); + module.setChannel(1, IdZNASum, 2 * modID, false, false, -5, 6, 4, 12); + module.setChannel(2, IdZNA1, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNA2, 2 * modID + 1, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -49,10 +51,10 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, modID = 1; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZNAC, 4, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZNASum, 5, true, false, -5, 6, 4, 12); - module.setChannel(2, IdZNA3, 6, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZNA4, 7, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZNAC, 2 * modID, false, true, -5, 6, 4, 12); + module.setChannel(1, IdZNASum, 2 * modID, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZNA3, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNA4, 2 * modID + 1, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -60,10 +62,10 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, modID = 2; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZNCC, 8, true, true, -5, 6, 4, 12); - module.setChannel(1, IdZNCSum, 9, false, false, -5, 6, 4, 12); - module.setChannel(2, IdZNC1, 10, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZNC2, 11, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZNCC, 2 * modID, true, true, -5, 6, 4, 12); + module.setChannel(1, IdZNCSum, 2 * modID, false, false, -5, 6, 4, 12); + module.setChannel(2, IdZNC1, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNC2, 2 * modID + 1, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -71,10 +73,10 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, modID = 3; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZNCC, 12, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZNCSum, 13, true, false, -5, 6, 4, 12); - module.setChannel(2, IdZNC3, 14, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZNC4, 15, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZNCC, 2 * modID, false, true, -5, 6, 4, 12); + module.setChannel(1, IdZNCSum, 2 * modID, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZNC3, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZNC4, 2 * modID + 1, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -82,10 +84,10 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, modID = 4; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZPAC, 16, true, true, -5, 6, 4, 12); - module.setChannel(1, IdZEM1, 16, true, true, -5, 6, 4, 12); - module.setChannel(2, IdZPA1, 17, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZPA2, 17, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZPAC, 2 * modID, true, true, -5, 6, 4, 12); + module.setChannel(1, IdZEM1, 2 * modID, true, true, -5, 6, 4, 12); + module.setChannel(2, IdZPA1, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPA2, 2 * modID + 1, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -93,10 +95,10 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, modID = 5; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZPAC, 18, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZPASum, 18, true, false, -5, 6, 4, 12); - module.setChannel(2, IdZPA3, 19, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZPA4, 19, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZPAC, 2 * modID, false, true, -5, 6, 4, 12); + module.setChannel(1, IdZPASum, 2 * modID, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZPA3, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPA4, 2 * modID + 1, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -104,10 +106,10 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, modID = 6; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZPCC, 16, true, true, -5, 6, 4, 12); - module.setChannel(1, IdZEM2, 16, true, true, -5, 6, 4, 12); - module.setChannel(2, IdZPC1, 17, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZPC2, 17, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZPCC, 2 * modID, true, true, -5, 6, 4, 12); + module.setChannel(1, IdZEM2, 2 * modID, true, true, -5, 6, 4, 12); + module.setChannel(2, IdZPC1, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPC2, 2 * modID + 1, true, false, -5, 6, 4, 12); // } //------------------------------------------- @@ -115,10 +117,10 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, modID = 7; auto& module = conf.modules[modID]; module.id = modID; - module.setChannel(0, IdZPCC, 18, false, true, -5, 6, 4, 12); - module.setChannel(1, IdZPCSum, 18, true, false, -5, 6, 4, 12); - module.setChannel(2, IdZPC3, 19, true, false, -5, 6, 4, 12); - module.setChannel(3, IdZPC4, 19, true, false, -5, 6, 4, 12); + module.setChannel(0, IdZPCC, 2 * modID, false, true, -5, 6, 4, 12); + module.setChannel(1, IdZPCSum, 2 * modID, true, false, -5, 6, 4, 12); + module.setChannel(2, IdZPC3, 2 * modID + 1, true, false, -5, 6, 4, 12); + module.setChannel(3, IdZPC4, 2 * modID + 1, true, false, -5, 6, 4, 12); // } conf.check(); diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h index 5a477720dd887..ce717e5a97593 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h @@ -37,10 +37,12 @@ class Digitizer public: struct BCCache : public o2::InteractionRecord { std::array<ChannelBCDataF, NChannels> data = {}; + std::array<ChannelBCDataF, NDigiChannels> digi = {}; std::vector<o2::zdc::MCLabel> labels; bool digitized = false; bool triggerChecked = false; - uint32_t trigChanMask = 0; // mask of triggered channels IDs + uint32_t trigChanMask = 0; // mask of triggered channels + uint8_t extTrig = 0; // external trigger static constexpr uint32_t AllChannelsMask = 0x80000000; BCCache(); diff --git a/Detectors/ZDC/simulation/src/Digitizer.cxx b/Detectors/ZDC/simulation/src/Digitizer.cxx index c40d026b2fa04..ae03970780442 100644 --- a/Detectors/ZDC/simulation/src/Digitizer.cxx +++ b/Detectors/ZDC/simulation/src/Digitizer.cxx @@ -26,14 +26,17 @@ Digitizer::BCCache::BCCache() Digitizer::ModuleConfAux::ModuleConfAux(const Module& md) : id(md.id) { + if (md.id < 0 || md.id >= NModules) { + LOG(FATAL) << "Module id = " << md.id << " not in allowed range [0:" << NModules << ")"; + } // construct aux helper from full module description for (int ic = Module::MaxChannels; ic--;) { if (md.channelID[ic] >= IdDummy) { if (md.readChannel[ic]) { - readChannels |= 0x1 << md.channelID[ic]; + readChannels |= 0x1 << (NChPerModule * md.id + ic); } if (md.trigChannel[ic]) { - trigChannels |= 0x1 << md.channelID[ic]; + trigChannels |= 0x1 << (NChPerModule * md.id + ic); } } } @@ -179,6 +182,7 @@ void Digitizer::generatePedestal() void Digitizer::digitizeBC(BCCache& bc) { auto& bcdata = bc.data; + auto& bcdigi = bc.digi; // apply gain for (int idet : {ZNA, ZPA, ZNC, ZPC}) { for (int ic : {Common, Ch1, Ch2, Ch3, Ch4}) { @@ -193,7 +197,7 @@ void Digitizer::digitizeBC(BCCache& bc) bcdata[IdZEM1][ib] *= mSimCondition->channels[IdZEM1].gain; bcdata[IdZEM2][ib] *= mSimCondition->channels[IdZEM2].gain; } - // + // Prepare sum of towers before adding noise for (int ib = NTimeBinsPerBC; ib--;) { bcdata[IdZNASum][ib] = mSimCondition->channels[IdZNASum].gain * (bcdata[IdZNA1][ib] + bcdata[IdZNA2][ib] + bcdata[IdZNA3][ib] + bcdata[IdZNA4][ib]); @@ -204,15 +208,29 @@ void Digitizer::digitizeBC(BCCache& bc) bcdata[IdZPCSum][ib] = mSimCondition->channels[IdZPCSum].gain * (bcdata[IdZPC1][ib] + bcdata[IdZPC2][ib] + bcdata[IdZPC3][ib] + bcdata[IdZPC4][ib]); } - for (int chan = NChannels; chan--;) { - const auto& chanConf = mSimCondition->channels[chan]; - auto pedBaseLine = mSimCondition->channels[chan].pedestal; - for (int ib = NTimeBinsPerBC; ib--;) { - bcdata[chan][ib] += gRandom->Gaus(pedBaseLine + mPedestalBLFluct[chan], chanConf.pedestalNoise); - int adc = std::nearbyint(bcdata[chan][ib]); - bcdata[chan][ib] = adc < ADCMax ? (adc > ADCMin ? adc : ADCMin) : ADCMax; + // Digitize the signals connected to each channel of the different modules + for (const auto& md : mModuleConfig->modules) { + if (md.id >= 0 && md.id < NModules) { + for (int ic = Module::MaxChannels; ic--;) { + int id = md.channelID[ic]; + if (id >= 0 && id < NChannels) { + const auto& chanConf = mSimCondition->channels[id]; + auto pedBaseLine = mSimCondition->channels[id].pedestal; + // Geographical position of signal in the setup + auto ipos = NChPerModule * md.id + ic; + for (int ib = NTimeBinsPerBC; ib--;) { + bcdigi[ipos][ib] = bcdata[id][ib] + gRandom->Gaus(pedBaseLine + mPedestalBLFluct[id], chanConf.pedestalNoise); + int adc = std::nearbyint(bcdigi[ipos][ib]); + bcdigi[ipos][ib] = adc < ADCMax ? (adc > ADCMin ? adc : ADCMin) : ADCMax; + } + LOG(DEBUG) << "md " << md.id << " ch " << ic << " sig " << id << " " << ChannelNames[id] + << bcdigi[ipos][0] << " " << bcdigi[ipos][1] << " " << bcdigi[ipos][2] << " " << bcdigi[ipos][3] << " " << bcdigi[ipos][4] << " " << bcdigi[ipos][5] << " " + << bcdigi[ipos][6] << " " << bcdigi[ipos][7] << " " << bcdigi[ipos][8] << " " << bcdigi[ipos][9] << " " << bcdigi[ipos][10] << " " << bcdigi[ipos][11]; + } + } } } + bc.digitized = true; } @@ -222,35 +240,45 @@ bool Digitizer::triggerBC(int ibc) auto& bcCached = *mFastCache[ibc]; LOG(DEBUG) << "CHECK TRIGGER " << ibc << " IR=" << bcCached; - if (mIsContinuous) { - for (int ic = mTriggerConfig.size(); ic--;) { - const auto& trigCh = mTriggerConfig[ic]; - bool okPrev = false; - int last1 = trigCh.last + 2; // To be modified. The new requirement is 3 consecutive samples - // look for 2 consecutive bins (the 1st one spanning trigCh.first : trigCh.last range) so that - // signal[bin]-signal[bin+trigCh.shift] > trigCh.threshold - for (int ib = trigCh.first; ib < last1; ib++) { // ib may be negative, so we shift by offs and look in the ADC cache - int binF, bcFidx = ibc + binHelper(ib, binF); - int binL, bcLidx = ibc + binHelper(ib + trigCh.shift, binL); - const auto& bcF = (bcFidx < 0 || !mFastCache[bcFidx]) ? mDummyBC : *mFastCache[bcFidx]; - const auto& bcL = (bcLidx < 0 || !mFastCache[bcLidx]) ? mDummyBC : *mFastCache[bcLidx]; - bool ok = bcF.data[trigCh.id][binF] - bcL.data[trigCh.id][binL] > trigCh.threshold; - if (ok && okPrev) { // trigger ok! - bcCached.trigChanMask |= 0x1 << trigCh.id; // register trigger mask - LOG(DEBUG) << " triggering channel " << int(trigCh.id) << "(" << ChannelNames[trigCh.id] << ") => " << bcCached.trigChanMask; - break; + + // Check trigger condition regardless of run type, will apply later the trigger mask + for (const auto& md : mModuleConfig->modules) { + if (md.id >= 0 && md.id < NModules) { + for (int ic = Module::MaxChannels; ic--;) { + //int id=md.channelID[ic]; + auto trigCh = md.trigChannelConf[ic]; + int id = trigCh.id; + if (id >= 0 && id < NChannels) { + auto ipos = NChPerModule * md.id + ic; + bool okPrev = false; + int last1 = trigCh.last + 2; // To be modified. The new requirement is 3 consecutive samples + // look for 2 consecutive bins (the 1st one spanning trigCh.first : trigCh.last range) so that + // signal[bin]-signal[bin+trigCh.shift] > trigCh.threshold + for (int ib = trigCh.first; ib < last1; ib++) { // ib may be negative, so we shift by offs and look in the ADC cache + int binF, bcFidx = ibc + binHelper(ib, binF); + int binL, bcLidx = ibc + binHelper(ib + trigCh.shift, binL); + const auto& bcF = (bcFidx < 0 || !mFastCache[bcFidx]) ? mDummyBC : *mFastCache[bcFidx]; + const auto& bcL = (bcLidx < 0 || !mFastCache[bcLidx]) ? mDummyBC : *mFastCache[bcLidx]; + bool ok = bcF.digi[ipos][binF] - bcL.digi[ipos][binL] > trigCh.threshold; + if (ok && okPrev) { // trigger ok! + bcCached.trigChanMask |= 0x1 << (NChPerModule * md.id + ic); // register trigger mask + LOG(DEBUG) << bcF.digi[ipos][binF] << " - " << bcL.digi[ipos][binL] << " = " << bcF.digi[ipos][binF] - bcL.digi[ipos][binL] << " > " << trigCh.threshold; + LOG(DEBUG) << " hit [" << md.id << "," << ic << "] " << int(id) << "(" << ChannelNames[id] << ") => " << bcCached.trigChanMask; + break; + } + okPrev = ok; + } } - okPrev = ok; } - } // loop over trigger channels - } else { - // just check if this BC IR corresponds to externall trigger - if (!mIRExternalTrigger.empty() && mIRExternalTrigger.front() == bcCached) { - bcCached.trigChanMask = AllChannelsMask; - mIRExternalTrigger.pop_front(); // suppress accounted external trigger } } + // just check if this BC IR corresponds to external trigger + if (!mIRExternalTrigger.empty() && mIRExternalTrigger.front() == bcCached) { + bcCached.extTrig = ALICETriggerMask; + mIRExternalTrigger.pop_front(); // suppress accounted external trigger + } + // This works in autotrigger mode, partially for triggered mode if (bcCached.trigChanMask & mTriggerableChanMask) { // there are triggered channels, flag modules/channels to read for (int ibcr = ibc - mNBCAHead; ibcr <= ibc; ibcr++) { auto& bcr = mStoreChanMask[ibcr + mNBCAHead]; @@ -276,14 +304,20 @@ void Digitizer::storeBC(const BCCache& bc, uint32_t chan2Store, LOG(DEBUG) << "Storing ch: " << chanPattern(chan2Store) << " trigger: " << chanPattern(bc.trigChanMask) << " for BC " << bc; int first = digitsCh.size(), nSto = 0; - for (int ic = 0; ic < NChannels; ic++) { - if (chan2Store & (0x1 << ic)) { - digitsCh.emplace_back(ic, bc.data[ic]); - nSto++; + for (const auto& md : mModuleConfig->modules) { + if (md.id >= 0 && md.id < NModules) { + for (int ic = 0; ic < Module::MaxChannels; ic++) { + auto ipos = NChPerModule * md.id + ic; + if (chan2Store & (0x1 << ipos)) { + digitsCh.emplace_back(md.channelID[ic], bc.digi[ipos]); + nSto++; + } + } } } + int nBC = digitsBC.size(); - digitsBC.emplace_back(first, nSto, bc, chan2Store, bc.trigChanMask); + digitsBC.emplace_back(first, nSto, bc, chan2Store, bc.trigChanMask, bc.extTrig); // TODO clarify if we want to store MC labels for all channels or only for stored ones for (const auto& lbl : bc.labels) { if (chan2Store & (0x1 << lbl.getChannel())) { @@ -396,45 +430,39 @@ void Digitizer::refreshCCDB() mTriggerConfig.clear(); mModConfAux.clear(); for (const auto& md : mModuleConfig->modules) { - if (md.id >= 0) { + if (md.id >= 0 && md.id < NModules) { mModConfAux.emplace_back(md); for (int ic = Module::MaxChannels; ic--;) { + // We consider all channels that can produce a hit if (md.trigChannel[ic] || (md.trigChannelConf[ic].shift > 0 && md.trigChannelConf[ic].threshold > 0)) { - bool skip = false; - for (int is = mTriggerConfig.size(); is--;) { // check if this triggering channel was already registered - if (mTriggerConfig[is].id == md.channelID[ic]) { - skip = true; - break; - } + const auto& trgChanConf = md.trigChannelConf[ic]; + if (trgChanConf.last + trgChanConf.shift + 1 >= NTimeBinsPerBC) { + LOG(FATAL) << "Wrong trigger settings"; } - if (!skip) { - const auto& trgChanConf = md.trigChannelConf[ic]; - if (trgChanConf.last + trgChanConf.shift + 1 >= NTimeBinsPerBC) { - LOG(FATAL) << "Wrong trigger settings"; - } - mTriggerConfig.emplace_back(trgChanConf); - if (md.trigChannel[ic]) { - LOG(INFO) << "Adding channel " << int(trgChanConf.id) << '(' << channelName(trgChanConf.id) << ") as triggering one"; - mTriggerableChanMask |= 0x1 << trgChanConf.id; - } else { - LOG(INFO) << "Adding channel " << int(trgChanConf.id) << '(' << channelName(trgChanConf.id) << ") as discriminator"; - } - if (trgChanConf.first < mTrigBinMin) { - mTrigBinMin = trgChanConf.first; - } - if (trgChanConf.last + trgChanConf.shift > mTrigBinMax) { - mTrigBinMax = trgChanConf.last + trgChanConf.shift; - } + mTriggerConfig.emplace_back(trgChanConf); + // We insert in the trigger mask only the channels that are actually triggering + // Trigger mask is geographical, bit position is relative to the module and channel + // where signal is connected + if (md.trigChannel[ic]) { + LOG(INFO) << "Adding channel [" << md.id << "," << ic << "] " << int(trgChanConf.id) << '(' << channelName(trgChanConf.id) << ") as triggering one"; + // TODO insert check if bit is already used. Should never happen + mTriggerableChanMask |= 0x1 << (NChPerModule * md.id + ic); + } else { + LOG(INFO) << "Adding channel [" << md.id << "," << ic << "] " << int(trgChanConf.id) << '(' << channelName(trgChanConf.id) << ") as discriminator"; + } + if (trgChanConf.first < mTrigBinMin) { + mTrigBinMin = trgChanConf.first; + } + if (trgChanConf.last + trgChanConf.shift > mTrigBinMax) { + mTrigBinMax = trgChanConf.last + trgChanConf.shift; } } } + } else { + LOG(FATAL) << "Module id: " << md.id << " is out of range"; } } - if (int(mTriggerConfig.size()) > MaxTriggerChannels) { - LOG(FATAL) << "Too many triggering channels (" << mTriggerConfig.size() << ')'; - } mModuleConfig->print(); - // } if (!mSimCondition) { // load this only once From da867d4de1f63892bb571df2e668b6b5e576b239 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 1 Oct 2020 12:24:04 +0200 Subject: [PATCH 0909/1751] speed up file reading fix variable overflow * Implement event creation only in case hborbit changed * The variable to keep the file size was too small causing lots of problems --- .../include/TPCReconstruction/RawReaderCRU.h | 27 ++++++++++--------- .../TPC/reconstruction/src/RawReaderCRU.cxx | 22 ++++++++++++--- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h index c20017bf7f346..7d619292e3b37 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h @@ -391,13 +391,15 @@ class RawReaderCRUEventSync /// get link information for a specific event and cru LinkInfo& getLinkInfo(const RDH& rdh, DataType dataType) { - // check if event is already registered. If not create a new one. - auto& event = createEvent(rdh, dataType); + if (!mLastEvent) { + createEvent(rdh, dataType); + } const auto dataWrapperID = RDHUtils::getEndPointID(rdh); const auto linkID = RDHUtils::getLinkID(rdh); const auto globalLinkID = linkID + dataWrapperID * 12; - return event.CRUInfoArray[RDHUtils::getCRUID(rdh)].LinkInformation[globalLinkID]; + + return mLastEvent->CRUInfoArray[RDHUtils::getCRUID(rdh)].LinkInformation[globalLinkID]; } /// get array with all link informaiton for a specific event number and cru @@ -465,6 +467,7 @@ class RawReaderCRUEventSync private: EventInfoVector mEventInformation{}; ///< event information + EventInfo* mLastEvent{nullptr}; ///< Last event that was created std::bitset<CRU::MaxCRU> mCRUSeen{}; ///< if cru was seen ClassDefNV(RawReaderCRUEventSync, 0); // event synchronisation for raw reader instances @@ -647,10 +650,10 @@ class RawReaderCRU class PacketDescriptor { public: - PacketDescriptor(uint32_t headOff, uint32_t cruID, uint32_t linkID, uint32_t dataWrapperID, uint16_t memorySize = 7840, uint16_t packetSize = 8192) : mHeaderOffset(headOff), - mFEEID(cruID + (linkID << 9) + (dataWrapperID << 13)), - mMemorySize(memorySize), - mPacketSize(packetSize) + PacketDescriptor(size_t headOff, uint32_t cruID, uint32_t linkID, uint32_t dataWrapperID, uint16_t memorySize = 7840, uint16_t packetSize = 8192) : mHeaderOffset(headOff), + mFEEID(cruID + (linkID << 9) + (dataWrapperID << 13)), + mMemorySize(memorySize), + mPacketSize(packetSize) { } @@ -678,10 +681,10 @@ class RawReaderCRU } private: - uint32_t mHeaderOffset; ///< header offset - uint16_t mMemorySize; ///< payload size - uint16_t mPacketSize; ///< packet size - uint16_t mFEEID; ///< link ID -- BIT 0-8: CRUid -- BIT 9-12: LinkID -- BIT 13: DataWrapperID -- BIT 14,15: unused + size_t mHeaderOffset; ///< header offset + uint16_t mMemorySize; ///< payload size + uint16_t mPacketSize; ///< packet size + uint16_t mFEEID; ///< link ID -- BIT 0-8: CRUid -- BIT 9-12: LinkID -- BIT 13: DataWrapperID -- BIT 14,15: unused }; // =========================================================================== @@ -697,7 +700,7 @@ class RawReaderCRU uint32_t mStream; ///< present stream being processed uint32_t mEventNumber = 0; ///< current event number to process CRU mCRU; ///< CRU - int mFileSize; ///< size of the input file + size_t mFileSize; ///< size of the input file bool mDumpTextFiles = false; ///< dump debugging text files bool mFillADCdataMap = true; ///< fill the ADC data map bool mForceCRU = false; ///< force CRU: overwrite value from RDH diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index b60ffee7c4353..b9fbc677e9e22 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -47,16 +47,25 @@ RawReaderCRUEventSync::EventInfo& RawReaderCRUEventSync::createEvent(const RDH& { const auto heartbeatOrbit = RDHUtils::getHeartBeatOrbit(rdh); + // TODO: might be that reversing the loop below has the same effect as using mLastEvent + if (mLastEvent && mLastEvent->hasHearbeatOrbit(heartbeatOrbit)) { + return *mLastEvent; + } + for (auto& ev : mEventInformation) { const auto hbMatch = ev.hasHearbeatOrbit(heartbeatOrbit); if (hbMatch) { + mLastEvent = &ev; return ev; } else if (ev.HeartbeatOrbits.back() == heartbeatOrbit - 1) { ev.HeartbeatOrbits.emplace_back(heartbeatOrbit); + mLastEvent = &ev; return ev; } } - return mEventInformation.emplace_back(heartbeatOrbit); + auto& ev = mEventInformation.emplace_back(heartbeatOrbit); + mLastEvent = &ev; + return ev; } void RawReaderCRUEventSync::analyse() @@ -211,9 +220,10 @@ int RawReaderCRU::scanFile() // read in the RDH, then jump to the next RDH position RDH rdh; uint32_t currentPacket = 0; + uint32_t lastHeartbeatOrbit = 0; - while (currentPacket < numPackets) { - const uint32_t currentPos = file.tellg(); + while ((currentPacket < numPackets) && !file.eof()) { + const size_t currentPos = file.tellg(); // ===| read in the RawDataHeader at the current position |================= file >> rdh; @@ -256,7 +266,7 @@ int RawReaderCRU::scanFile() } // ===| get relavant data information |===================================== - //const auto heartbeatOrbit = rdh.heartbeatOrbit; + const auto heartbeatOrbit = RDHUtils::getHeartBeatOrbit(rdh); const auto dataWrapperID = RDHUtils::getEndPointID(rdh); const auto linkID = RDHUtils::getLinkID(rdh); const auto globalLinkID = linkID + dataWrapperID * 12; @@ -276,6 +286,10 @@ int RawReaderCRU::scanFile() RawReaderCRUEventSync::LinkInfo* linkInfo = nullptr; if (mManager) { // in case of triggered mode, we use the first heartbeat orbit as event identifier + if ((lastHeartbeatOrbit == 0) || (heartbeatOrbit != lastHeartbeatOrbit)) { + mManager->mEventSync.createEvent(rdh, mManager->getDataType()); + lastHeartbeatOrbit = heartbeatOrbit; + } linkInfo = &mManager->mEventSync.getLinkInfo(rdh, mManager->getDataType()); mManager->mEventSync.setCRUSeen(mCRU); } From 72469903ed4d5e862c802d84c10d67c8f5df751f Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 1 Oct 2020 12:25:51 +0200 Subject: [PATCH 0910/1751] add options to start with valgrind and callgrind --- Detectors/TPC/monitor/macro/startMonitor | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/monitor/macro/startMonitor b/Detectors/TPC/monitor/macro/startMonitor index 2ed32d5aa6fdc..a9adecda17365 100755 --- a/Detectors/TPC/monitor/macro/startMonitor +++ b/Detectors/TPC/monitor/macro/startMonitor @@ -42,9 +42,10 @@ verbosity=0 debugLevel=0 selectedSector=0 showOverview=0 +tool="" # ===| parse command line options |============================================= -OPTIONS=$(getopt -l "fileInfo:,pedestalFile:,firstTimeBin:,lastTimeBin:,timeBins:,verbosity:,debugLevel:,sector:,overview,help" -o "i:p:f:l:t:v:d:s:oh" -n "startMonitor" -- "$@") +OPTIONS=$(getopt -l "fileInfo:,pedestalFile:,firstTimeBin:,lastTimeBin:,timeBins:,verbosity:,debugLevel:,sector:,overview,valgrind,callgrind,help" -o "i:p:f:l:t:v:d:s:oh" -n "startMonitor" -- "$@") if [ $? != 0 ] ; then usageAndExit @@ -64,6 +65,8 @@ while true; do -d|--debugLevel) debugLevel=$2; shift 2;; -s|--sector) selectedSector=$2; shift 2;; -o|--overview) showOverview=1; shift;; + --valgrind) tool="valgrind --log-file=valgrind.log"; shift;; + --callgrind) tool="valgrind --tool=callgrind"; shift;; -h|--help) usageAndExit;; *) echo "Internal error!" ; exit 1 ;; esac @@ -83,8 +86,6 @@ else fi # ===| command building and execution |========================================= - -#cmd="valgrind --log-file=valgrind.log root.exe -l $O2_SRC/Detectors/TPC/reconstruction/macro/addInclude.C $O2_SRC/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C+g'(\"$fileInfo\",\"$pedestalFile\",$timeBins,$verbosity,$debugLevel,$selectedSector,$showOverview)'" -cmd="root.exe -l $O2_SRC/Detectors/TPC/reconstruction/macro/addInclude.C $O2_SRC/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C+g'(\"$fileInfo\", \"$pedestalFile\", $firstTimeBin, $lastTimeBin, $timeBins, $verbosity, $debugLevel, $selectedSector, $showOverview)'" +cmd="$tool root.exe -l $O2_SRC/Detectors/TPC/reconstruction/macro/addInclude.C $O2_SRC/Detectors/TPC/monitor/macro/RunSimpleEventDisplay.C+g'(\"$fileInfo\", \"$pedestalFile\", $firstTimeBin, $lastTimeBin, $timeBins, $verbosity, $debugLevel, $selectedSector, $showOverview)'" echo "running: $cmd" eval $cmd From b60b2ca6a88341281bb2cb970d22ce2733122ee7 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 8 Oct 2020 22:29:06 +0200 Subject: [PATCH 0911/1751] Add possibility to read data from several CRUs per file --- .../include/TPCCalibration/CalibRawBase.h | 90 +------------------ .../include/TPCReconstruction/RawReaderCRU.h | 36 ++++++-- .../TPC/reconstruction/src/RawReaderCRU.cxx | 35 +++++++- 3 files changed, 64 insertions(+), 97 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h index a9ed98f4dbf40..cb607d0563453 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h @@ -422,94 +422,8 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventRawReaderCRU(int ev const bool skipEvent = mSkipIncomplete && !isPresentEventComplete(); if (!skipEvent) { - for (auto& reader_ptr : mRawReaderCRUManager.getReaders()) { - auto reader = reader_ptr.get(); - - LOG(INFO) << "Processing event number " << eventNumber << " (" << mNevents << ") - RawReader#: " << processedReaders << " ptr: " << reader; - - if (eventNumber >= 0) { - mPresentEventNumber = eventNumber; - } else if (eventNumber == -1) { - if (mPresentEventNumber == std::numeric_limits<size_t>::max()) { - mPresentEventNumber = 0; - } else { - mPresentEventNumber = (reader->getEventNumber() + 1) % reader->getNumberOfEvents(); - } - } else if (eventNumber == -2) { - auto readerNumber = reader->getEventNumber(); - if (readerNumber > 0) { - mPresentEventNumber = readerNumber - 1; - } else { - mPresentEventNumber = reader->getNumberOfEvents() - 1; - } - } - reader->setEventNumber(mPresentEventNumber); - - // process data - reader->processLinks(); - hasData = true; - - const auto& cru = reader->getCRU(); - const int roc = cru.roc(); - - // TODO: OROC case needs subtraction of number of pad rows in IROC - const PadRegionInfo& regionInfo = mMapper.getPadRegionInfo(cru.region()); - const PartitionInfo& partInfo = mMapper.getPartitionInfo(cru.partition()); - - //LOG(INFO) << " Found ADC values: " << reader->getADCMap().size(); - // loop over pads - for (const auto& pair : reader->getADCMap()) { - const auto& padPos = pair.first; - const auto& dataVector = pair.second; - - // TODO: fix this? - mProcessedTimeBins = std::max(mProcessedTimeBins, dataVector.size()); - - // row is local in region (CRU) - const int row = padPos.getRow(); - const int pad = padPos.getPad(); - if (row == 255 || pad == 255) - continue; - - int timeBin = 0; - - int rowOffset = 0; - switch (mPadSubset) { - case PadSubset::ROC: { - rowOffset = regionInfo.getGlobalRowOffset(); - rowOffset -= (cru.isOROC()) * nRowIROC; - break; - } - case PadSubset::Region: { - break; - } - case PadSubset::Partition: { - rowOffset = regionInfo.getGlobalRowOffset(); - rowOffset -= partInfo.getGlobalRowOffset(); - break; - } - } - - //const FECInfo& fecInfo = mMapper.getFECInfo(PadROCPos(roc, row, pad)); - - for (const auto& signalI : dataVector) { - // modify row depending on the calibration type used - const float signal = float(signalI); - //printf("Call update: %d, %d (%d), %d, %d, %.3f -- cru: %03d, reg: %02d -- FEC: %02d, Chip: %02d, Chn: %02d\n", roc, row, rowOffset, pad, timeBin, signal, cru.number(), cru.region(), fecInfo.getIndex(), fecInfo.getSampaChip(), fecInfo.getSampaChannel()); - updateCRU(cru, row, pad, timeBin, signal); - updateROC(roc, row + rowOffset, pad, timeBin, signal); - ++timeBin; - hasData = true; - } - } - LOG(INFO) << "Found time bins: " << mProcessedTimeBins << "\n"; - - reader->clearMap(); - - // notify that one raw reader processing finalized for this event - endReader(); - ++processedReaders; - } + hasData = true; + mRawReaderCRUManager.processEvent(mPresentEventNumber, [this]() { endReader(); }); // set status, don't overwrite decision if (!hasData) { return ProcessStatus::NoMoreData; diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h index 7d619292e3b37..5e14e6e23ad41 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h @@ -303,6 +303,9 @@ class RawReaderCRUEventSync using RDH = o2::header::RAWDataHeader; + /// default ctor + RawReaderCRUEventSync() { reset(); } + // --------------------------------------------------------------------------- /// \struct LinkInfo /// \brief helper to store link information in an event @@ -449,13 +452,19 @@ class RawReaderCRUEventSync void setLinksSeen(const CRU cru, const std::bitset<MaxNumberOfLinks>& links); /// set a cru as seen - void setCRUSeen(const CRU cru) { mCRUSeen[cru] = true; } + void setCRUSeen(const CRU cru, const uint16_t reader = 0) { mCRUSeen[cru] = reader; } + + /// return CRU seen information + const auto& getCRUSeen() const { return mCRUSeen; } + + /// get the reader associated to the CRU + uint32_t getReaderNumber(uint32_t cru) { return mCRUSeen[cru]; } /// reset all information void reset() { mEventInformation.clear(); - mCRUSeen.reset(); + mCRUSeen.fill(-1); } /// overloading output stream operator @@ -466,9 +475,9 @@ class RawReaderCRUEventSync } private: - EventInfoVector mEventInformation{}; ///< event information - EventInfo* mLastEvent{nullptr}; ///< Last event that was created - std::bitset<CRU::MaxCRU> mCRUSeen{}; ///< if cru was seen + EventInfoVector mEventInformation{}; ///< event information + EventInfo* mLastEvent{nullptr}; ///< Last event that was created + std::array<int16_t, CRU::MaxCRU> mCRUSeen{}; ///< if cru was seen, number is for which decoder ClassDefNV(RawReaderCRUEventSync, 0); // event synchronisation for raw reader instances }; // class RawReaderCRUEventSync @@ -493,12 +502,14 @@ class RawReaderCRU uint32_t stream = 0, uint32_t debugLevel = 0, uint32_t verbosity = 0, - const std::string_view outputFilePrefix = "") + const std::string_view outputFilePrefix = "", + uint32_t readerNumber = 0) : mDebugLevel(debugLevel), mVerbosity(verbosity), mNumTimeBins(numTimeBins), mLink(link), mStream(stream), + mReaderNumber(readerNumber), mCRU(), mFileSize(-1), mPacketsPerLink(), @@ -544,9 +555,15 @@ class RawReaderCRU /// set event number void setEventNumber(uint32_t eventNumber = 0) { mEventNumber = eventNumber; } + /// set the reader number in the manager + void setReaderNumber(uint32_t readerNumber) { mReaderNumber = readerNumber; } + /// set filling of ADC data map void setFillADCdataMap(bool fill) { mFillADCdataMap = fill; } + /// get filling of ADC data map + bool getFillADCdataMap() const { return mFillADCdataMap; } + /// get event number uint32_t getEventNumber() const { return mEventNumber; } @@ -699,6 +716,7 @@ class RawReaderCRU uint32_t mLink; ///< present link being processed uint32_t mStream; ///< present stream being processed uint32_t mEventNumber = 0; ///< current event number to process + uint32_t mReaderNumber = 0; ///< raw reader number in manager CRU mCRU; ///< CRU size_t mFileSize; ///< size of the input file bool mDumpTextFiles = false; ///< dump debugging text files @@ -851,6 +869,7 @@ class RawReaderCRUManager { public: using ADCDataCallback = std::function<Int_t(const PadROCPos&, const CRU&, const gsl::span<const uint32_t>)>; + using EndReaderCallback = std::function<void()>; /// constructor RawReaderCRUManager() = default; @@ -865,7 +884,7 @@ class RawReaderCRUManager const std::string_view outputFilePrefix = "") //RawReaderCRU& createReader(std::string_view fileName, uint32_t numTimeBins) { - mRawReadersCRU.emplace_back(std::make_unique<RawReaderCRU>(inputFileName, numTimeBins, 0, stream, debugLevel, verbosity, outputFilePrefix)); + mRawReadersCRU.emplace_back(std::make_unique<RawReaderCRU>(inputFileName, numTimeBins, 0, stream, debugLevel, verbosity, outputFilePrefix, mRawReadersCRU.size())); mRawReadersCRU.back()->setManager(this); return *mRawReadersCRU.back().get(); } @@ -948,6 +967,9 @@ class RawReaderCRUManager /// set a callback function void setADCDataCallback(ADCDataCallback function) { mADCDataCallback = function; } + /// process event calling mADCDataCallback to process values + void processEvent(uint32_t eventNumber, EndReaderCallback endReader = nullptr); + private: std::vector<std::unique_ptr<RawReaderCRU>> mRawReadersCRU{}; ///< cru type raw readers RawReaderCRUEventSync mEventSync{}; ///< event synchronisation diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index b9fbc677e9e22..e3f3e9414cdfe 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -80,7 +80,7 @@ void RawReaderCRUEventSync::analyse() for (size_t iCRU = 0; iCRU < event.CRUInfoArray.size(); ++iCRU) { const auto& cruInfo = event.CRUInfoArray[iCRU]; if (!cruInfo.isPresent()) { - if (mCRUSeen[iCRU]) { + if (mCRUSeen[iCRU] >= 0) { event.IsComplete = false; break; } @@ -125,6 +125,14 @@ void RawReaderCRUEventSync::streamTo(std::ostream& output) const const std::string bold("\033[1m"); const std::string clear("\033[0m"); + std::cout << "CRU information"; + for (size_t iCRU = 0; iCRU < mCRUSeen.size(); ++iCRU) { + const auto readerNumber = mCRUSeen[iCRU]; + if (readerNumber >= 0) { + std::cout << fmt::format("CRU {:2} found in reader {}\n", iCRU, readerNumber); + } + } + std::cout << "Detailed event information\n"; // event loop for (int i = 0; i < mEventInformation.size(); ++i) { @@ -291,7 +299,7 @@ int RawReaderCRU::scanFile() lastHeartbeatOrbit = heartbeatOrbit; } linkInfo = &mManager->mEventSync.getLinkInfo(rdh, mManager->getDataType()); - mManager->mEventSync.setCRUSeen(mCRU); + mManager->mEventSync.setCRUSeen(mCRU, mReaderNumber); } //std::cout << "block length: " << blockLength << '\n'; @@ -1021,6 +1029,7 @@ void RawReaderCRUManager::setupReaders(const std::string_view inputFileNames, for (auto file : *arr) { // fix the number of time bins auto& reader = createReader(file->GetName(), numTimeBins); + reader.setReaderNumber(mRawReadersCRU.size() - 1); reader.setVerbosity(verbosity); reader.setDebugLevel(debugLevel); O2INFO("Adding file: %s\n", file->GetName()); @@ -1042,3 +1051,25 @@ void RawReaderCRUManager::copyEvents(const std::string_view inputFileNames, cons manager.setupReaders(inputFileNames); manager.copyEvents(eventNumbers, outputDirectory, mode); } + +void RawReaderCRUManager::processEvent(uint32_t eventNumber, EndReaderCallback endReader) +{ + const auto& cruSeen = mEventSync.getCRUSeen(); + + for (size_t iCRU = 0; iCRU < cruSeen.size(); ++iCRU) { + const auto readerNumber = cruSeen[iCRU]; + if (readerNumber >= 0) { + auto& reader = mRawReadersCRU[readerNumber]; + if (reader->getFillADCdataMap()) { + LOGF(warning, "Filling of ADC data map not supported in RawReaderCRUManager::processEvent, it is disabled now. use ADCDataCallback"); + reader->setFillADCdataMap(false); + } + reader->setEventNumber(eventNumber); + reader->forceCRU(iCRU); + reader->processLinks(); + if (endReader) { + endReader(); + } + } + } +} From 5ba0edd3ab36f8f64526aabb4b4fa5c2c80d51e3 Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Mon, 12 Oct 2020 11:48:49 +0200 Subject: [PATCH 0912/1751] MCH: disable exception when digit array sizes don't match (#4551) [MCH] add option to enable/disable the check of the digits vectors sizes The sizes of the input and output digits arrays do not always match in the case of continuous data, because there could be multiple digits for the same pad in the input buffer. This will (mostly) be fixed by the time-based pre-clustering that will run before the position-based pre-clustering. --- .../MCH/Workflow/src/PreClusterFinderSpec.cxx | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx index 3c50d2d9f2d3c..6e833233243c3 100644 --- a/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/PreClusterFinderSpec.cxx @@ -43,6 +43,12 @@ namespace mch using namespace std; using namespace o2::framework; +enum tCheckNoLeftoverDigits { + CHECK_NO_LEFTOVER_DIGITS_OFF, + CHECK_NO_LEFTOVER_DIGITS_ERROR, + CHECK_NO_LEFTOVER_DIGITS_FATAL +}; + class PreClusterFinderTask { public: @@ -67,6 +73,15 @@ class PreClusterFinderTask << std::chrono::duration<double, std::milli>(tEnd - tStart).count() << " ms"; }; ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); + + auto checkNoLeftoverDigits = ic.options().get<std::string>("check-no-leftover-digits"); + if (checkNoLeftoverDigits == "off") { + mCheckNoLeftoverDigits = CHECK_NO_LEFTOVER_DIGITS_OFF; + } else if (checkNoLeftoverDigits == "error") { + mCheckNoLeftoverDigits = CHECK_NO_LEFTOVER_DIGITS_ERROR; + } else if (checkNoLeftoverDigits == "fatal") { + mCheckNoLeftoverDigits = CHECK_NO_LEFTOVER_DIGITS_FATAL; + } } //_________________________________________________________________________________________________ @@ -102,9 +117,24 @@ class PreClusterFinderTask mPreClusters.reserve(nPreClusters); // to avoid reallocation if mUsedDigits.reserve(digits.size()); // the capacity is exceeded mPreClusterFinder.getPreClusters(mPreClusters, mUsedDigits); - if (mUsedDigits.size() != digits.size()) { - throw runtime_error("some digits have been lost during the preclustering"); - } + + // check sizes of input and output digits vectors + bool digitsSizesDiffer = (mUsedDigits.size() != digits.size()); + switch (mCheckNoLeftoverDigits) { + case CHECK_NO_LEFTOVER_DIGITS_OFF: + break; + case CHECK_NO_LEFTOVER_DIGITS_ERROR: + if (digitsSizesDiffer) { + LOG(ERROR) << "some digits have been lost during the preclustering"; + } + break; + case CHECK_NO_LEFTOVER_DIGITS_FATAL: + if (digitsSizesDiffer) { + throw runtime_error("some digits have been lost during the preclustering"); + } + break; + }; + tEnd = std::chrono::high_resolution_clock::now(); mTimeStorePreClusters += tEnd - tStart; @@ -118,6 +148,8 @@ class PreClusterFinderTask std::vector<PreCluster> mPreClusters{}; ///< vector of preclusters std::vector<Digit> mUsedDigits{}; ///< vector of digits in the preclusters + int mCheckNoLeftoverDigits{CHECK_NO_LEFTOVER_DIGITS_ERROR}; ///< digits vector size check option + std::chrono::duration<double, std::milli> mTimeResetPreClusterFinder{}; ///< timer std::chrono::duration<double, std::milli> mTimeLoadDigits{}; ///< timer std::chrono::duration<double, std::milli> mTimePreClusterFinder{}; ///< timer @@ -127,13 +159,14 @@ class PreClusterFinderTask //_________________________________________________________________________________________________ o2::framework::DataProcessorSpec getPreClusterFinderSpec() { + std::string helpstr = "check that all digits are included in pre-clusters"; return DataProcessorSpec{ "PreClusterFinder", Inputs{InputSpec{"digits", "MCH", "DIGITS", 0, Lifetime::Timeframe}}, Outputs{OutputSpec{"MCH", "PRECLUSTERS", 0, Lifetime::Timeframe}, OutputSpec{"MCH", "PRECLUSTERDIGITS", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<PreClusterFinderTask>()}, - Options{}}; + Options{{"check-no-leftover-digits", VariantType::String, "error", {helpstr}}}}; } } // end namespace mch From 0ae416653c81f594e5c6b8813ec40e2eea9133c0 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 12 Oct 2020 14:11:47 +0200 Subject: [PATCH 0913/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index dbea9bdc2b1f0..0ce1bea4c14ae 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -49,7 +49,8 @@ jobs: # 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 $BASE_COMMIT $x | tail -n +6 | grep -e '^+' | grep '.\{122,\}' && { echo "Line longer than 120 chars in $x." && exit 1; } || true ;; + # Disabled for now, since people don't like the convention. + # git diff $BASE_COMMIT $x | tail -n +6 | 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 From 4f62b15f1f3c695cbfb91f4da5cd06af3260e5a4 Mon Sep 17 00:00:00 2001 From: Jochen Klein <qgp@users.noreply.github.com> Date: Mon, 12 Oct 2020 14:16:36 +0200 Subject: [PATCH 0914/1751] Add cmake targets for FastJet contrib (#4514) --- dependencies/FindFastJet.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dependencies/FindFastJet.cmake b/dependencies/FindFastJet.cmake index 6d6ad46b7e3a9..a61abdf7e7a28 100644 --- a/dependencies/FindFastJet.cmake +++ b/dependencies/FindFastJet.cmake @@ -107,6 +107,13 @@ if(${${PKGNAME}_FOUND}) foreach(incdir ${${PKGNAME}_INCLUDE_DIRS}) target_include_directories(${PKGNAME}::${PKGNAME} INTERFACE ${incdir}) endforeach() + + find_library(lib_contrib NAMES "fastjetcontribfragile" PATHS ${${PKGNAME}_LIB_DIRS} NO_DEFAULT_PATH) + if(lib_contrib) + message(STATUS "adding FastJet contrib") + add_library(${PKGNAME}::Contrib IMPORTED INTERFACE GLOBAL) + target_link_libraries(${PKGNAME}::Contrib INTERFACE ${lib_contrib}) + endif() endif() unset(PKGNAME) From a1fe0fdf90e9b76c9f2dfb9f5cf7c0324375dc38 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 12 Oct 2020 14:26:59 +0200 Subject: [PATCH 0915/1751] Drop clang-format checker from travis. (#4571) We now have a much more powerful alternative in Github actions. --- .travis.yml | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/.travis.yml b/.travis.yml index 102f63acab08f..0616499ab1d76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,52 +7,6 @@ matrix: - os: linux - env: include: - - os: linux - dist: xenial - env: JOB=clang-format - addons: - apt: - sources: - - llvm-toolchain-xenial-8 - packages: - - clang-format-8 - compiler: clang - script: | - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - BASE_COMMIT=$(git rev-parse $TRAVIS_BRANCH) - echo "Running clang-format-8 against branch $TRAVIS_BRANCH, with hash $BASE_COMMIT" - 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)" - - 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." - exit 0 - 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 "$RESULT_OUTPUT" - exit 1 - fi - fi - os: linux dist: bionic env: JOB=doxygen From b5b89ddaecd4441ed80b06f17fc8c50b02bfc64c Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 12 Oct 2020 15:52:23 +0200 Subject: [PATCH 0916/1751] adding example for sparse BC matching (#4569) --- Analysis/Tasks/run2Matcher.cxx | 11 ++--------- Analysis/Tutorials/src/muonIteration.cxx | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Analysis/Tasks/run2Matcher.cxx b/Analysis/Tasks/run2Matcher.cxx index f680559fa121a..53fb49d731c44 100644 --- a/Analysis/Tasks/run2Matcher.cxx +++ b/Analysis/Tasks/run2Matcher.cxx @@ -22,14 +22,8 @@ using namespace o2::framework::expressions; struct Run2Matcher { BuildsExclusive<aod::Run2MatchedExclusive> matched_e; Builds<aod::Run2MatchedSparse> matched_s; - void init(o2::framework::InitContext&) - { - } -}; - -struct BCMatcher { - BuildsExclusive<aod::BCCollisionsExclusive> matched_e; - Builds<aod::BCCollisionsSparse> matched; + BuildsExclusive<aod::BCCollisionsExclusive> bc_e; + Builds<aod::BCCollisionsSparse> bc; void init(o2::framework::InitContext&) { } @@ -39,6 +33,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<Run2Matcher>("produce-run2-bc-matching"), - adaptAnalysisTask<BCMatcher>("bc-matcher"), }; } diff --git a/Analysis/Tutorials/src/muonIteration.cxx b/Analysis/Tutorials/src/muonIteration.cxx index 5e3448cda554d..509fdb88b6ea4 100644 --- a/Analysis/Tutorials/src/muonIteration.cxx +++ b/Analysis/Tutorials/src/muonIteration.cxx @@ -23,7 +23,7 @@ using namespace o2::framework::expressions; // Note that one has to subscribe to aod::Collisions const& to load // the relevant data even if you access the data itself through m.collision() // This uses the exclusive matcher, so you only get BCs which have a collision -// If you want also BCs without collision, you should use BCCollisionsSparse and check for m.has_collision() +// If you want also BCs without collision, see the example IterateMuonsSparse below struct IterateMuons { void process(aod::BCCollisionsExclusive::iterator const& m, aod::Collisions const&, aod::Muons const& muons) { @@ -34,9 +34,26 @@ struct IterateMuons { } }; +// This uses the sparase matcher, so you also get BCs without a collision. +// You need to check with m.has_collision() +struct IterateMuonsSparse { + void process(aod::BCCollisionsSparse::iterator const& m, aod::Collisions const&, aod::Muons const& muons) + { + if (m.has_collision()) { + LOGF(INFO, "Vertex = %f has %d muons", m.collision().posZ(), muons.size()); + } else { + LOGF(INFO, "BC without collision has %d muons", muons.size()); + } + for (auto& muon : muons) { + LOGF(info, " pT = %.2f", muon.pt()); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<IterateMuons>("iterate-muons"), + adaptAnalysisTask<IterateMuonsSparse>("iterate-muons-sparse"), }; } From 0891d058979a9364ff63f7f62302b5be725bbb22 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 12 Oct 2020 19:58:07 +0200 Subject: [PATCH 0917/1751] Update code-formatting.yml --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 0ce1bea4c14ae..aa9d8f2651b78 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -41,7 +41,7 @@ jobs: for x in $COMMIT_FILES; do case $x in - *.h|*.cxx) + # *.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 From d13fe546ce0d82901de0a782c871c8b0078de625 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 12 Oct 2020 19:59:21 +0200 Subject: [PATCH 0918/1751] Analysis: speed up PID (#4576) * Avoiding virtual inheritance to DetectorResponse. * Reserve memory upfront. --- Analysis/DataModel/CMakeLists.txt | 1 - Analysis/DataModel/include/PID/PIDTOF.h | 9 ++- Analysis/DataModel/include/PID/PIDTPC.h | 9 ++- .../include/PIDBase/DetectorResponse.h | 48 +++++++++----- Analysis/DataModel/src/DetectorResponse.cxx | 56 ---------------- Analysis/DataModel/src/PIDTOF.cxx | 4 +- Analysis/DataModel/src/PIDTPC.cxx | 8 +-- Analysis/Tasks/pidTOF.cxx | 47 +++++++------- Analysis/Tasks/pidTPC.cxx | 65 ++++++++++--------- 9 files changed, 103 insertions(+), 144 deletions(-) delete mode 100644 Analysis/DataModel/src/DetectorResponse.cxx diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index ef447cc6246f0..1ddd6f70161db 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -10,7 +10,6 @@ o2_add_library(AnalysisDataModel SOURCES src/ParamBase.cxx - src/DetectorResponse.cxx src/PIDTOF.cxx src/PIDTPC.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src diff --git a/Analysis/DataModel/include/PID/PIDTOF.h b/Analysis/DataModel/include/PID/PIDTOF.h index 3a69ddd5e850c..bee4a52dc58de 100644 --- a/Analysis/DataModel/include/PID/PIDTOF.h +++ b/Analysis/DataModel/include/PID/PIDTOF.h @@ -64,11 +64,10 @@ class EventTime /// \brief Class to handle the the TOF detector response -class Response : public DetectorResponse +class Response { public: Response() = default; - ~Response() override = default; /// Updater for the TOF response to setup the track parameters /// i.e. sets the track of interest @@ -105,14 +104,14 @@ class Response : public DetectorResponse /// Computes the expected time of a track, given it TOF expected momentum static float ComputeExpectedTime(float tofexpmom, float length, float massZ); /// Gets the expected signal of the track of interest under the PID assumption - float GetExpectedSignal(o2::track::PID::ID id) const override { return ComputeExpectedTime(mTOFExpMomentum, mLength, o2::track::PID::getMass2Z(id)); } + float GetExpectedSignal(o2::track::PID::ID id) const { return ComputeExpectedTime(mTOFExpMomentum, mLength, o2::track::PID::getMass2Z(id)); } // Expected resolution /// Gets the expected resolution of the measurement - float GetExpectedSigma(o2::track::PID::ID id) const override; + float GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const; // Nsigma - float GetSeparation(o2::track::PID::ID id) const override { return (mTOFSignal - mEventTime.GetEvTime(mMomentum) - GetExpectedSignal(id)) / GetExpectedSigma(id); } + float GetSeparation(DetectorResponse<Response>& response, o2::track::PID::ID id) const { return (mTOFSignal - mEventTime.GetEvTime(mMomentum) - GetExpectedSignal(id)) / GetExpectedSigma(response, id); } // float GetMismatchProbability(float time, float eta) const; // Utility values diff --git a/Analysis/DataModel/include/PID/PIDTPC.h b/Analysis/DataModel/include/PID/PIDTPC.h index a28954fb9971a..c462d4e0d00d9 100644 --- a/Analysis/DataModel/include/PID/PIDTPC.h +++ b/Analysis/DataModel/include/PID/PIDTPC.h @@ -31,11 +31,10 @@ namespace o2::pid::tpc { /// \brief Class to handle the the TPC detector response -class Response : public DetectorResponse +class Response { public: Response() = default; - ~Response() override = default; /// Updater for the TPC response to setup the track parameters /// i.e. sets the track of interest @@ -43,14 +42,14 @@ class Response : public DetectorResponse // Expected resolution /// Gets the expected resolution of the measurement - float GetExpectedSigma(o2::track::PID::ID id) const override; + float GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const; // Expected signal /// Gets the expected signal of the measurement - float GetExpectedSignal(o2::track::PID::ID id) const override; + float GetExpectedSignal(DetectorResponse<Response>& response, o2::track::PID::ID id) const; // Nsigma - float GetSeparation(o2::track::PID::ID id) const override { return (mTPCSignal - GetExpectedSignal(id)) / GetExpectedSigma(id); } + float GetSeparation(DetectorResponse<Response>& response, o2::track::PID::ID id) const { return (mTPCSignal - GetExpectedSignal(response, id)) / GetExpectedSigma(response, id); } private: // Event of interest information diff --git a/Analysis/DataModel/include/PIDBase/DetectorResponse.h b/Analysis/DataModel/include/PIDBase/DetectorResponse.h index a7d4d779b59d5..88f245af19831 100644 --- a/Analysis/DataModel/include/PIDBase/DetectorResponse.h +++ b/Analysis/DataModel/include/PIDBase/DetectorResponse.h @@ -21,9 +21,11 @@ #include <array> #include <vector> +#include "Framework/Logger.h" // ROOT includes #include "Rtypes.h" #include "TMath.h" +#include "TFile.h" // O2 includes #include "ReconstructionDataFormats/PID.h" @@ -32,7 +34,8 @@ namespace o2::pid { /// \brief Class to handle the general detector response -class DetectorResponse +template <typename DetectorImpl> +class DetectorResponse : public DetectorImpl { public: DetectorResponse() = default; @@ -43,22 +46,7 @@ class DetectorResponse kSigma, kNParams }; - static const std::array<TString, kNParams> ParamName; - - /// Getter for the expected resolution, purely virtual and reimplemented in derived classes - /// @param id particle index to compute the expected sigma - /// @return Returns the expected resolution for the hypothesis id - virtual pidvar_t GetExpectedSigma(o2::track::PID::ID id) const = 0; - - /// Getter for the expected signal, purely virtual and reimplemented in derived classes - /// @param id particle index to compute the expected signal - /// @return Returns the expected signal for the hypothesis id - virtual pidvar_t GetExpectedSignal(o2::track::PID::ID id) const = 0; - - /// Getter for the expected discriminating value, can be Nsigmas, probabilities or whatever, purely virtual and reimplemented in derived classes - /// @param id particle index to compute the separation - /// @return Returns the discriminating value for the hypothesis id - virtual pidvar_t GetSeparation(o2::track::PID::ID id) const = 0; + static constexpr std::array<char const*, kNParams> ParamName = {{"Signal", "Sigma"}}; /// Setter for the parametrization from input TFile /// \param fname File name used for input @@ -89,6 +77,32 @@ class DetectorResponse std::array<Parametrization*, kNParams> mParam; }; +template <typename DetectorImpl> +inline void DetectorResponse<DetectorImpl>::LoadParamFromFile(const TString fname, const TString pname, const Param_t ptype) +{ + TFile f(fname, "READ"); + if (!f.Get(pname)) { + LOG(fatal) << "Did not find parametrization " << pname << " in file " << fname; + } + LOG(info) << "Loading parametrization " << pname << " from TFile " << fname; + f.GetObject(pname, mParam[ptype]); + f.Close(); + mParam[ptype]->Print(); + mParam[ptype]->PrintParametrization(); +} + +template <typename DetectorImpl> +inline void DetectorResponse<DetectorImpl>::SetParameters(const DetectorResponse<DetectorImpl>::Param_t ptype, std::vector<pidvar_t> p) +{ + if (!mParam[ptype]) { + const std::string pname = std::string(ParamName[ptype]) + "_default_param"; + LOG(info) << "Creating new parametrization " << pname << " of size " << p.size(); + mParam[ptype] = new Parametrization(pname, p.size()); + mParam[ptype]->Print(); + } + mParam[ptype]->SetParameters(p); +} + } // namespace o2::pid #endif // O2_ANALYSIS_PID_DETECTORRESPONSE_H_ diff --git a/Analysis/DataModel/src/DetectorResponse.cxx b/Analysis/DataModel/src/DetectorResponse.cxx deleted file mode 100644 index 0ddb305ae65dc..0000000000000 --- a/Analysis/DataModel/src/DetectorResponse.cxx +++ /dev/null @@ -1,56 +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. - -/// -/// \file ParamBase.cxx -/// \author Nicolo' Jacazio -/// \since 07/08/2020 -/// \brief Set of utilities to handle the parametrization of the PID response for each detector -/// These are the basic storage elements to be kept in the CCDB -/// - -// Root includes -#include "TFile.h" - -// O2 includes -#include "PIDBase/ParamBase.h" -#include "PIDBase/DetectorResponse.h" -#include "Framework/Logger.h" - -namespace o2::pid -{ - -const std::array<TString, DetectorResponse::kNParams> DetectorResponse::ParamName = {{"Signal", "Sigma"}}; - -void DetectorResponse::LoadParamFromFile(const TString fname, const TString pname, const Param_t ptype) -{ - TFile f(fname, "READ"); - if (!f.Get(pname)) { - LOG(fatal) << "Did not find parametrization " << pname << " in file " << fname; - } - LOG(info) << "Loading parametrization " << pname << " from TFile " << fname; - f.GetObject(pname, mParam[ptype]); - f.Close(); - mParam[ptype]->Print(); - mParam[ptype]->PrintParametrization(); -} - -void DetectorResponse::SetParameters(const Param_t ptype, std::vector<pidvar_t> p) -{ - if (!mParam[ptype]) { - const TString pname = ParamName[ptype] + "_default_param"; - LOG(info) << "Creating new parametrization " << pname << " of size " << p.size(); - mParam[ptype] = new Parametrization(pname, p.size()); - mParam[ptype]->Print(); - } - mParam[ptype]->SetParameters(p); -} - -} // namespace o2::pid \ No newline at end of file diff --git a/Analysis/DataModel/src/PIDTOF.cxx b/Analysis/DataModel/src/PIDTOF.cxx index a56d4603f7fac..6e36145214b65 100644 --- a/Analysis/DataModel/src/PIDTOF.cxx +++ b/Analysis/DataModel/src/PIDTOF.cxx @@ -54,10 +54,10 @@ float Response::GetExpectedBeta(float mom, float mass) } //_________________________________________________________________________ -float Response::GetExpectedSigma(o2::track::PID::ID id) const +float Response::GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const { const float x[4] = {mMomentum, mTOFSignal, mEventTime.GetEvTimeReso(mMomentum), o2::track::PID::getMass2Z(id)}; - return this->operator()(kSigma, x); + return response(DetectorResponse<Response>::kSigma, x); } } // namespace o2::pid::tof diff --git a/Analysis/DataModel/src/PIDTPC.cxx b/Analysis/DataModel/src/PIDTPC.cxx index f36eebed232c9..2906f3d1c00fc 100644 --- a/Analysis/DataModel/src/PIDTPC.cxx +++ b/Analysis/DataModel/src/PIDTPC.cxx @@ -20,16 +20,16 @@ void Response::UpdateTrack(float mom, float tpcsignal, float tpcpoints) mTPCPoints = tpcpoints; }; -float Response::GetExpectedSignal(o2::track::PID::ID id) const +float Response::GetExpectedSignal(DetectorResponse<Response>& response, o2::track::PID::ID id) const { const float x[2] = {mMomentum / o2::track::PID::getMass(id), (float)o2::track::PID::getCharge(id)}; - return this->operator()(kSignal, x); + return response(DetectorResponse<Response>::kSignal, x); } -float Response::GetExpectedSigma(o2::track::PID::ID id) const +float Response::GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const { const float x[2] = {mTPCSignal, mTPCPoints}; - return this->operator()(kSigma, x); + return response(DetectorResponse<Response>::kSigma, x); } } // namespace o2::pid::tpc diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index d2b4d3b0d6abe..3200b7810f204 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -26,7 +26,7 @@ using namespace o2::track; struct pidTOFTask { Produces<aod::pidRespTOF> tofpid; Produces<aod::pidRespTOFbeta> tofpidbeta; - tof::Response resp = tof::Response(); + DetectorResponse<tof::Response> resp = DetectorResponse<tof::Response>(); Service<o2::ccdb::BasicCCDBManager> ccdb; Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; Configurable<std::string> sigmaname{"param-sigma", "TOFReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"}; @@ -43,13 +43,13 @@ struct pidTOFTask { ccdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()); // const std::vector<float> p = {0.008, 0.008, 0.002, 40.0}; - resp.SetParameters(DetectorResponse::kSigma, p); + resp.SetParameters(DetectorResponse<tof::Response>::kSigma, p); const std::string fname = paramfile.value; if (!fname.empty()) { // Loading the parametrization from file - resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse<tof::Response>::kSigma); } else { // Loading it from CCDB const std::string path = "Analysis/PID/TOF"; - resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); + resp.LoadParam(DetectorResponse<tof::Response>::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); } } @@ -60,6 +60,9 @@ struct pidTOFTask { evt.SetEvTimeReso(0, collision.collisionTimeRes()); evt.SetEvTimeMask(0, collision.collisionTimeMask()); resp.SetEventTime(evt); + + tofpidbeta.reserve(tracks.size()); + tofpid.reserve(tracks.size()); for (auto const& i : tracks) { resp.UpdateTrack(i.p(), i.tofExpMom() / tof::Response::kCSPEED, i.length(), i.tofSignal()); tofpidbeta(resp.GetBeta(), @@ -77,24 +80,24 @@ struct pidTOFTask { resp.GetExpectedSignal(PID::Triton), resp.GetExpectedSignal(PID::Helium3), resp.GetExpectedSignal(PID::Alpha), - resp.GetExpectedSigma(PID::Electron), - resp.GetExpectedSigma(PID::Muon), - resp.GetExpectedSigma(PID::Pion), - resp.GetExpectedSigma(PID::Kaon), - resp.GetExpectedSigma(PID::Proton), - resp.GetExpectedSigma(PID::Deuteron), - resp.GetExpectedSigma(PID::Triton), - resp.GetExpectedSigma(PID::Helium3), - resp.GetExpectedSigma(PID::Alpha), - resp.GetSeparation(PID::Electron), - resp.GetSeparation(PID::Muon), - resp.GetSeparation(PID::Pion), - resp.GetSeparation(PID::Kaon), - resp.GetSeparation(PID::Proton), - resp.GetSeparation(PID::Deuteron), - resp.GetSeparation(PID::Triton), - resp.GetSeparation(PID::Helium3), - resp.GetSeparation(PID::Alpha)); + resp.GetExpectedSigma(resp, PID::Electron), + resp.GetExpectedSigma(resp, PID::Muon), + resp.GetExpectedSigma(resp, PID::Pion), + resp.GetExpectedSigma(resp, PID::Kaon), + resp.GetExpectedSigma(resp, PID::Proton), + resp.GetExpectedSigma(resp, PID::Deuteron), + resp.GetExpectedSigma(resp, PID::Triton), + resp.GetExpectedSigma(resp, PID::Helium3), + resp.GetExpectedSigma(resp, PID::Alpha), + resp.GetSeparation(resp, PID::Electron), + resp.GetSeparation(resp, PID::Muon), + resp.GetSeparation(resp, PID::Pion), + resp.GetSeparation(resp, PID::Kaon), + resp.GetSeparation(resp, PID::Proton), + resp.GetSeparation(resp, PID::Deuteron), + resp.GetSeparation(resp, PID::Triton), + resp.GetSeparation(resp, PID::Helium3), + resp.GetSeparation(resp, PID::Alpha)); } } }; diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index af8baff6349d7..4c127f018971c 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -25,7 +25,7 @@ using namespace o2::track; struct pidTPCTask { Produces<aod::pidRespTPC> tpcpid; - tpc::Response resp = tpc::Response(); + DetectorResponse<tpc::Response> resp = DetectorResponse<tpc::Response>(); Service<o2::ccdb::BasicCCDBManager> ccdb; Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; Configurable<std::string> signalname{"param-signal", "BetheBloch", "Name of the parametrization for the expected signal, used in both file and CCDB mode"}; @@ -44,47 +44,48 @@ struct pidTPCTask { // const std::string fname = paramfile.value; if (!fname.empty()) { // Loading the parametrization from file - resp.LoadParamFromFile(fname.data(), signalname.value, DetectorResponse::kSignal); - resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); + resp.LoadParamFromFile(fname.data(), signalname.value, DetectorResponse<tpc::Response>::kSignal); + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse<tpc::Response>::kSigma); } else { // Loading it from CCDB const std::string path = "Analysis/PID/TPC"; - resp.LoadParam(DetectorResponse::kSignal, ccdb->getForTimeStamp<Parametrization>(path + "/" + signalname.value, timestamp.value)); - resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); + resp.LoadParam(DetectorResponse<tpc::Response>::kSignal, ccdb->getForTimeStamp<Parametrization>(path + "/" + signalname.value, timestamp.value)); + resp.LoadParam(DetectorResponse<tpc::Response>::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); } } void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) { + tpcpid.reserve(tracks.size()); for (auto const& i : tracks) { resp.UpdateTrack(i.tpcInnerParam(), i.tpcSignal(), i.tpcNClsShared()); tpcpid( - resp.GetExpectedSignal(PID::Electron), - resp.GetExpectedSignal(PID::Muon), - resp.GetExpectedSignal(PID::Pion), - resp.GetExpectedSignal(PID::Kaon), - resp.GetExpectedSignal(PID::Proton), - resp.GetExpectedSignal(PID::Deuteron), - resp.GetExpectedSignal(PID::Triton), - resp.GetExpectedSignal(PID::Helium3), - resp.GetExpectedSignal(PID::Alpha), - resp.GetExpectedSigma(PID::Electron), - resp.GetExpectedSigma(PID::Muon), - resp.GetExpectedSigma(PID::Pion), - resp.GetExpectedSigma(PID::Kaon), - resp.GetExpectedSigma(PID::Proton), - resp.GetExpectedSigma(PID::Deuteron), - resp.GetExpectedSigma(PID::Triton), - resp.GetExpectedSigma(PID::Helium3), - resp.GetExpectedSigma(PID::Alpha), - resp.GetSeparation(PID::Electron), - resp.GetSeparation(PID::Muon), - resp.GetSeparation(PID::Pion), - resp.GetSeparation(PID::Kaon), - resp.GetSeparation(PID::Proton), - resp.GetSeparation(PID::Deuteron), - resp.GetSeparation(PID::Triton), - resp.GetSeparation(PID::Helium3), - resp.GetSeparation(PID::Alpha)); + resp.GetExpectedSignal(resp, PID::Electron), + resp.GetExpectedSignal(resp, PID::Muon), + resp.GetExpectedSignal(resp, PID::Pion), + resp.GetExpectedSignal(resp, PID::Kaon), + resp.GetExpectedSignal(resp, PID::Proton), + resp.GetExpectedSignal(resp, PID::Deuteron), + resp.GetExpectedSignal(resp, PID::Triton), + resp.GetExpectedSignal(resp, PID::Helium3), + resp.GetExpectedSignal(resp, PID::Alpha), + resp.GetExpectedSigma(resp, PID::Electron), + resp.GetExpectedSigma(resp, PID::Muon), + resp.GetExpectedSigma(resp, PID::Pion), + resp.GetExpectedSigma(resp, PID::Kaon), + resp.GetExpectedSigma(resp, PID::Proton), + resp.GetExpectedSigma(resp, PID::Deuteron), + resp.GetExpectedSigma(resp, PID::Triton), + resp.GetExpectedSigma(resp, PID::Helium3), + resp.GetExpectedSigma(resp, PID::Alpha), + resp.GetSeparation(resp, PID::Electron), + resp.GetSeparation(resp, PID::Muon), + resp.GetSeparation(resp, PID::Pion), + resp.GetSeparation(resp, PID::Kaon), + resp.GetSeparation(resp, PID::Proton), + resp.GetSeparation(resp, PID::Deuteron), + resp.GetSeparation(resp, PID::Triton), + resp.GetSeparation(resp, PID::Helium3), + resp.GetSeparation(resp, PID::Alpha)); } } }; From 3ab781a87d9440fd7dca654b23fdf581125cf401 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <mpuccio@users.noreply.github.com> Date: Tue, 13 Oct 2020 08:43:38 +0200 Subject: [PATCH 0919/1751] Update nuclei masses to the latest CODATA values (#4578) Using 2018 values summarised in https://physics.nist.gov/cuu/pdf/wall_2018.pdf This is particularly important for He-3, that was off by 0.8 MeV/c^2. See alisw/AliRoot#1245 --- .../Constants/include/CommonConstants/PhysicsConstants.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Common/Constants/include/CommonConstants/PhysicsConstants.h b/Common/Constants/include/CommonConstants/PhysicsConstants.h index 1e2fe24e1dab9..b303ec049f90e 100644 --- a/Common/Constants/include/CommonConstants/PhysicsConstants.h +++ b/Common/Constants/include/CommonConstants/PhysicsConstants.h @@ -31,10 +31,10 @@ constexpr float MassKaonCharged = 0.493677; constexpr float MassKaonNeutral = 0.497648; constexpr float MassProton = 0.938272; constexpr float MassLambda = 1.115683; -constexpr float MassDeuteron = 1.875613; -constexpr float MassTriton = 2.809250; -constexpr float MassHelium3 = 2.809230; -constexpr float MassAlpha = 3.727379; +constexpr float MassDeuteron = 1.8756129; +constexpr float MassTriton = 2.8089211; +constexpr float MassHelium3 = 2.8083916; +constexpr float MassAlpha = 3.7273794; constexpr float MassHyperTriton = 2.992; constexpr float LightSpeedCm2S = 299792458.e2; // C in cm/s From dc4899021b3ba2d2b6b59271df29c515038d2493 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 9 Oct 2020 19:45:29 +0200 Subject: [PATCH 0920/1751] TPC Workflow: Fix TPC Completion Policy --- .../include/TPCWorkflow/CATrackerSpec.h | 3 +- .../include/TPCWorkflow/RecoWorkflow.h | 20 ++++-- .../TPCWorkflow/TPCSectorCompletionPolicy.h | 70 +++++++++++++------ Detectors/TPC/workflow/src/CATrackerSpec.cxx | 15 ++-- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 26 +++---- .../src/tpc-raw-to-digits-workflow.cxx | 2 +- .../TPC/workflow/src/tpc-reco-workflow.cxx | 10 +-- 7 files changed, 98 insertions(+), 48 deletions(-) diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h index b382f71d41a6f..c3b0fde519484 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h @@ -14,6 +14,7 @@ /// @brief Processor spec for running TPC CA tracking #include "Framework/DataProcessorSpec.h" +#include "RecoWorkflow.h" #include <utility> // std::forward namespace o2 @@ -132,7 +133,7 @@ struct Config { /// /// @param specconfig configuration options for the processor spec /// @param tpcsectors list of sector numbers -framework::DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int> const& tpcsectors); +framework::DataProcessorSpec getCATrackerSpec(o2::tpc::reco_workflow::CompletionPolicyData* policyData, ca::Config const& specconfig, std::vector<int> const& tpcsectors); o2::framework::CompletionPolicy getCATrackerCompletionPolicy(); } // end namespace tpc diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h b/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h index 2173e6d3ace15..436f29eb255d5 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h @@ -17,11 +17,16 @@ #include "Framework/WorkflowSpec.h" #include <vector> +#include <array> #include <string> #include <numeric> // std::iota namespace o2 { +namespace framework +{ +struct InputSpec; +} namespace tpc { @@ -56,8 +61,11 @@ enum struct OutputType { Digits, ZSRaw, }; +using CompletionPolicyData = std::vector<framework::InputSpec>; + /// create the workflow for TPC reconstruction -framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, // +framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, // + std::vector<int> const& tpcSectors, // std::vector<int> const& laneConfiguration, // bool propagateMC = true, unsigned nLanes = 1, // std::string const& cfgInput = "digitizer", // @@ -67,7 +75,8 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, int zs10bit = 0, float zsThreshold = 2.0f); -static inline framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, // +static inline framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, // + std::vector<int> const& tpcSectors, // bool propagateMC = true, unsigned nLanes = 1, // std::string const& cfgInput = "digitizer", // std::string const& cfgOutput = "tracks", // @@ -79,10 +88,11 @@ static inline framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSec // create a default lane configuration with ids [0, nLanes-1] std::vector<int> laneConfiguration(nLanes); std::iota(laneConfiguration.begin(), laneConfiguration.end(), 0); - return getWorkflow(tpcSectors, laneConfiguration, propagateMC, nLanes, cfgInput, cfgOutput, caClusterer, zsOnTheFly, zs10bit, zsThreshold); + return getWorkflow(policyData, tpcSectors, laneConfiguration, propagateMC, nLanes, cfgInput, cfgOutput, caClusterer, zsOnTheFly, zs10bit, zsThreshold); } -static inline framework::WorkflowSpec getWorkflow(bool propagateMC = true, unsigned nLanes = 1, // +static inline framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, // + bool propagateMC = true, unsigned nLanes = 1, // std::string const& cfgInput = "digitizer", // std::string const& cfgOutput = "tracks", // int caClusterer = 0, // @@ -93,7 +103,7 @@ static inline framework::WorkflowSpec getWorkflow(bool propagateMC = true, unsig // create a default lane configuration with ids [0, nLanes-1] std::vector<int> laneConfiguration(nLanes); std::iota(laneConfiguration.begin(), laneConfiguration.end(), 0); - return getWorkflow({}, laneConfiguration, propagateMC, nLanes, cfgInput, cfgOutput, caClusterer, zsOnTheFly, zs10bit, zsThreshold); + return getWorkflow(policyData, {}, laneConfiguration, propagateMC, nLanes, cfgInput, cfgOutput, caClusterer, zsOnTheFly, zs10bit, zsThreshold); } } // end namespace reco_workflow diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCSectorCompletionPolicy.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCSectorCompletionPolicy.h index ae394304dd9df..52a38fb2cb2c3 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TPCSectorCompletionPolicy.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCSectorCompletionPolicy.h @@ -28,7 +28,6 @@ namespace o2 { -using namespace framework; namespace tpc { @@ -64,6 +63,8 @@ namespace tpc class TPCSectorCompletionPolicy { public: + using CompletionPolicyData = std::vector<framework::InputSpec>; + enum struct Config { // require data on all other inputs in addition to the ones checked for the sector completion RequireAll, @@ -80,15 +81,15 @@ class TPCSectorCompletionPolicy { constexpr static size_t NSectors = o2::tpc::Sector::MAXSECTOR; - auto matcher = [expression = mProcessorName](DeviceSpec const& device) -> bool { + auto matcher = [expression = mProcessorName](framework::DeviceSpec const& device) -> bool { return std::regex_match(device.name.begin(), device.name.end(), std::regex(expression.c_str())); }; - auto callback = [inputMatchers = mInputMatchers, bRequireAll = this->mRequireAll](CompletionPolicy::InputSet inputs) -> CompletionPolicy::CompletionOp { - auto op = CompletionPolicy::CompletionOp::Wait; + auto callback = [bRequireAll = mRequireAll, inputMatchers = mInputMatchers, externalInputMatchers = mExternalInputMatchers](framework::CompletionPolicy::InputSet inputs) -> framework::CompletionPolicy::CompletionOp { std::bitset<NSectors> validSectors = 0; bool haveMatchedInput = false; uint64_t activeSectors = 0; + std::vector<uint64_t> validSectorsExternal(externalInputMatchers ? externalInputMatchers->size() : 0); size_t nActiveInputRoutes = 0; size_t nMaxPartsPerRoute = 0; int inputType = -1; @@ -96,17 +97,17 @@ class TPCSectorCompletionPolicy nMaxPartsPerRoute = it.size() > nMaxPartsPerRoute ? it.size() : nMaxPartsPerRoute; bool haveActivePart = false; for (auto const& ref : it) { - if (!DataRefUtils::isValid(ref)) { + if (!framework::DataRefUtils::isValid(ref)) { continue; } haveActivePart = true; - auto const* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref); + auto const* dh = framework::DataRefUtils::getHeader<o2::header::DataHeader*>(ref); // check if the O2 message matches on of the input specs to be matched and // if it matches, check for the sector header, retrieve the active sector information - // and mark the sector as valid + // and mark the sector as valid, we require to match exactly one of the inputs in the list for (size_t idx = 0, end = inputMatchers.size(); idx < end; idx++) { auto const& spec = inputMatchers[idx]; - if (DataRefUtils::match(ref, spec)) { + if (framework::DataRefUtils::match(ref, spec)) { haveMatchedInput = true; if (inputType == -1) { // we bind to the index of the first match and require all other inputs to match the same spec @@ -119,34 +120,57 @@ class TPCSectorCompletionPolicy << dh->dataDescription.as<std::string>() + "/" + dh->subSpecification; throw std::runtime_error(error.str()); } - auto const* sectorHeader = DataRefUtils::getHeader<o2::tpc::TPCSectorHeader*>(ref); + auto const* sectorHeader = framework::DataRefUtils::getHeader<o2::tpc::TPCSectorHeader*>(ref); if (sectorHeader == nullptr) { - // FIXME: think about error policy throw std::runtime_error("TPC sector header missing on header stack"); } activeSectors |= sectorHeader->activeSectors; - std::bitset<NSectors> sectorMask(sectorHeader->sectorBits); - validSectors |= sectorMask; + validSectors |= sectorHeader->sectorBits; break; } } + + // We require to match all inputs in the external list + if (externalInputMatchers) { + for (size_t idx = 0, end = externalInputMatchers->size(); idx < end; idx++) { + auto const& spec = (*externalInputMatchers)[idx]; + if (framework::DataRefUtils::match(ref, spec)) { + auto const* sectorHeader = framework::DataRefUtils::getHeader<o2::tpc::TPCSectorHeader*>(ref); + if (sectorHeader == nullptr) { + throw std::runtime_error("TPC sector header missing on header stack"); + } + activeSectors |= sectorHeader->activeSectors; + validSectorsExternal[idx] |= sectorHeader->sectorBits; + break; + } + } + } } if (haveActivePart) { ++nActiveInputRoutes; } } + if (externalInputMatchers) { + // We require all external matchers to have all sectors present, if not we wait + for (size_t idx = 0, end = externalInputMatchers->size(); idx < end; idx++) { + if (validSectorsExternal[idx] == 0 || validSectorsExternal[idx] != activeSectors) { + return framework::CompletionPolicy::CompletionOp::Wait; + } + } + } + // If the flag Config::RequireAll is set in the constructor arguments we require // data from all inputs in addition to the sector matching condition // To be fully correct we would need to require data from all inputs not going // into the TPC policy, but that is not possible for the moment. That's why there is a possibly // unhandled case if multiple TPC input routes are defined but a complete data set is coming over // one of them. Not likely to be a use case, though. - if (haveMatchedInput && activeSectors == validSectors.to_ulong() && + if ((inputMatchers.size() == 0 || (haveMatchedInput && activeSectors == validSectors.to_ulong())) && (!bRequireAll || nActiveInputRoutes == inputs.size())) { // we can process if there is input for all sectors, the required sectors are // transported as part of the sector header - op = CompletionPolicy::CompletionOp::Consume; + return framework::CompletionPolicy::CompletionOp::Consume; } else if (activeSectors == 0 && nActiveInputRoutes == inputs.size()) { // no sector header is transmitted, this is the case for e.g. the ZS raw data // we simply require input on all routes, this is also the default of DPL DataRelayer @@ -158,12 +182,12 @@ class TPCSectorCompletionPolicy //if (nMaxPartsPerRoute > 1) { // LOG(WARNING) << "No sector information is provided with the data, data set is complete with data on all input routes. But there are multiple parts on at least one route and this policy might not be complete, no check possible if other parts on some routes are still missing. It is adviced to add a custom policy."; //} - op = CompletionPolicy::CompletionOp::Consume; + return framework::CompletionPolicy::CompletionOp::Consume; } - return op; + return framework::CompletionPolicy::CompletionOp::Wait; }; - return CompletionPolicy{"TPCSectorCompletionPolicy", matcher, callback}; + return framework::CompletionPolicy{"TPCSectorCompletionPolicy", matcher, callback}; } private: @@ -172,7 +196,7 @@ class TPCSectorCompletionPolicy void init(Arg&& arg, Args&&... args) { using Type = std::decay_t<Arg>; - if constexpr (std::is_same<Type, InputSpec>::value) { + if constexpr (std::is_same<Type, framework::InputSpec>::value) { mInputMatchers.emplace_back(std::move(arg)); } else if constexpr (std::is_same<Type, TPCSectorCompletionPolicy::Config>::value) { switch (arg) { @@ -180,8 +204,10 @@ class TPCSectorCompletionPolicy mRequireAll = true; break; } + } else if constexpr (std::is_same<Type, std::vector<o2::framework::InputSpec>*>::value) { + mExternalInputMatchers = arg; } else { - static_assert(always_static_assert_v<Type>); + static_assert(framework::always_static_assert_v<Type>); } if constexpr (sizeof...(args) > 0) { init(std::forward<Args>(args)...); @@ -189,7 +215,11 @@ class TPCSectorCompletionPolicy } std::string mProcessorName; - std::vector<InputSpec> mInputMatchers; + std::vector<framework::InputSpec> mInputMatchers; + // The external input matchers behave as the internal ones with the following differences: + // - They are controlled externally and the external entity can modify them, e.g. after parsing command line arguments. + // - They are all matched independently, it is not sufficient that one of them is present for all sectors + const std::vector<framework::InputSpec>* mExternalInputMatchers = nullptr; bool mRequireAll = false; }; } // namespace tpc diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index d0dd25ca0a316..26b8ac4ead28c 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -70,13 +70,14 @@ using namespace o2::header; using namespace o2::gpu; using namespace o2::base; using namespace o2::dataformats; +using namespace o2::tpc::reco_workflow; namespace o2 { namespace tpc { -DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int> const& tpcsectors) +DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config const& specconfig, std::vector<int> const& tpcsectors) { if (specconfig.outputCAClusters && !specconfig.caClusterer && !specconfig.decompressTPC) { throw std::runtime_error("inconsistent configuration: cluster output is only possible if CA clusterer is activated"); @@ -652,7 +653,7 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int // changing the binding name of the input in order to identify inputs by unique labels // in the processing. Think about how the processing can be made agnostic of input size, // e.g. by providing a span of inputs under a certain label - auto createInputSpecs = [&tpcsectors, &specconfig]() { + auto createInputSpecs = [&tpcsectors, &specconfig, policyData]() { Inputs inputs; if (specconfig.decompressTPC) { inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, specconfig.decompressTPCFromROOT ? header::DataDescription("COMPCLUSTERS") : header::DataDescription("COMPCLUSTERSFLAT")}, Lifetime::Timeframe}); @@ -660,18 +661,21 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int // We accept digits and MC labels also if we run on ZS Raw data, since they are needed for MC label propagation if ((!specconfig.zsOnTheFly || specconfig.processMC) && !specconfig.zsDecoder) { inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe}); + policyData->emplace_back(o2::framework::InputSpec{"digits", o2::framework::ConcreteDataTypeMatcher{"TPC", "DIGITS"}}); } } else { inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, "CLUSTERNATIVE"}, Lifetime::Timeframe}); + policyData->emplace_back(o2::framework::InputSpec{"clusters", o2::framework::ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}}); } if (specconfig.processMC) { if (specconfig.caClusterer) { - constexpr o2::header::DataDescription datadesc("DIGITSMCTR"); if (!specconfig.zsDecoder) { - inputs.emplace_back(InputSpec{"mclblin", ConcreteDataTypeMatcher{gDataOriginTPC, datadesc}, Lifetime::Timeframe}); + inputs.emplace_back(InputSpec{"mclblin", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITSMCTR"}, Lifetime::Timeframe}); + policyData->emplace_back(o2::framework::InputSpec{"digitsmc", o2::framework::ConcreteDataTypeMatcher{"TPC", "DIGITSMCTR"}}); } } else { inputs.emplace_back(InputSpec{"mclblin", ConcreteDataTypeMatcher{gDataOriginTPC, "CLNATIVEMCLBL"}, Lifetime::Timeframe}); + policyData->emplace_back(o2::framework::InputSpec{"clustersmc", o2::framework::ConcreteDataTypeMatcher{"TPC", "CLNATIVEMCLBL"}}); } } @@ -687,6 +691,9 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int return inputs; }; + //o2::framework::InputSpec{"cluster", o2::framework::ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}}, + // o2::framework::InputSpec{"digits", o2::framework::ConcreteDataTypeMatcher{"TPC", "DIGITS"}})()); + auto createOutputSpecs = [&specconfig, &tpcsectors, &processAttributes]() { std::vector<OutputSpec> outputSpecs{ OutputSpec{{"outTracks"}, gDataOriginTPC, "TRACKS", 0, Lifetime::Timeframe}, diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index c02c0863318d7..7d237d5d213a0 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -86,7 +86,7 @@ const std::unordered_map<std::string, OutputType> OutputMap{ {"zsraw", OutputType::ZSRaw}, }; -framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vector<int> const& laneConfiguration, +framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vector<int> const& tpcSectors, std::vector<int> const& laneConfiguration, bool propagateMC, unsigned nLanes, std::string const& cfgInput, std::string const& cfgOutput, int caClusterer, int zsOnTheFly, int zs10bit, float zsThreshold) { @@ -430,18 +430,18 @@ framework::WorkflowSpec getWorkflow(std::vector<int> const& tpcSectors, std::vec // // selected by output type 'tracks' if (runTracker) { - specs.emplace_back(o2::tpc::getCATrackerSpec(ca::Config{ - propagateMC ? ca::Operation::ProcessMC : ca::Operation::Noop, - decompressTPC ? ca::Operation::DecompressTPC : ca::Operation::Noop, - decompressTPC && inputType == InputType::CompClusters ? ca::Operation::DecompressTPCFromROOT : ca::Operation::Noop, - caClusterer ? ca::Operation::CAClusterer : ca::Operation::Noop, - zsDecoder ? ca::Operation::ZSDecoder : ca::Operation::Noop, - zsOnTheFly ? ca::Operation::ZSOnTheFly : ca::Operation::Noop, - produceTracks ? ca::Operation::OutputTracks : ca::Operation::Noop, - produceCompClusters ? ca::Operation::OutputCompClusters : ca::Operation::Noop, - runClusterEncoder ? ca::Operation::OutputCompClustersFlat : ca::Operation::Noop, - isEnabled(OutputType::Clusters) && (caClusterer || decompressTPC) ? ca::Operation::OutputCAClusters : ca::Operation::Noop, - }, + specs.emplace_back(o2::tpc::getCATrackerSpec(policyData, ca::Config{ + propagateMC ? ca::Operation::ProcessMC : ca::Operation::Noop, + decompressTPC ? ca::Operation::DecompressTPC : ca::Operation::Noop, + decompressTPC && inputType == InputType::CompClusters ? ca::Operation::DecompressTPCFromROOT : ca::Operation::Noop, + caClusterer ? ca::Operation::CAClusterer : ca::Operation::Noop, + zsDecoder ? ca::Operation::ZSDecoder : ca::Operation::Noop, + zsOnTheFly ? ca::Operation::ZSOnTheFly : ca::Operation::Noop, + produceTracks ? ca::Operation::OutputTracks : ca::Operation::Noop, + produceCompClusters ? ca::Operation::OutputCompClusters : ca::Operation::Noop, + runClusterEncoder ? ca::Operation::OutputCompClustersFlat : ca::Operation::Noop, + isEnabled(OutputType::Clusters) && (caClusterer || decompressTPC) ? ca::Operation::OutputCAClusters : ca::Operation::Noop, + }, tpcSectors)); } diff --git a/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx b/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx index 8c245bec30d0c..b282a0a2269ce 100644 --- a/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx @@ -126,7 +126,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) recoOuput = tpcRecoOutputType.c_str(); } - auto tpcRecoWorkflow = o2::tpc::reco_workflow::getWorkflow(tpcSectors, tpcSectors, false, lanes, "digitizer", recoOuput.data()); + auto tpcRecoWorkflow = o2::tpc::reco_workflow::getWorkflow(nullptr, tpcSectors, tpcSectors, false, lanes, "digitizer", recoOuput.data()); specs.insert(specs.end(), tpcRecoWorkflow.begin(), tpcRecoWorkflow.end()); return specs; diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index 40b2ce0ad13e8..c88bdc1caf03f 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -35,6 +35,9 @@ // publisher will trigger on. This is dependent on the input type o2::framework::Output gDispatchTrigger{"", ""}; +// Global variable used to transport data to the completion policy +o2::tpc::reco_workflow::CompletionPolicyData gPolicyData; + // add workflow options, note that customization needs to be declared before // including Framework/runDataProcessing void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) @@ -85,9 +88,7 @@ void customize(std::vector<o2::framework::CompletionPolicy>& policies) policies.push_back(CompletionPolicyHelpers::defineByName("tpc-cluster-decoder.*", CompletionPolicy::CompletionOp::Consume)); policies.push_back(CompletionPolicyHelpers::defineByName("tpc-clusterer.*", CompletionPolicy::CompletionOp::Consume)); // the custom completion policy for the tracker - policies.push_back(o2::tpc::TPCSectorCompletionPolicy("tpc-tracker.*", - o2::framework::InputSpec{"cluster", o2::framework::ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}}, - o2::framework::InputSpec{"digits", o2::framework::ConcreteDataTypeMatcher{"TPC", "DIGITS"}})()); + policies.push_back(o2::tpc::TPCSectorCompletionPolicy("tpc-tracker.*", o2::tpc::TPCSectorCompletionPolicy::Config::RequireAll, &gPolicyData)()); } #include "Framework/runDataProcessing.h" // the main driver @@ -140,7 +141,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) o2::conf::ConfigurableParam::writeINI("o2tpcrecoworkflow_configuration.ini"); bool doMC = not cfgc.options().get<bool>("disable-mc"); - return o2::tpc::reco_workflow::getWorkflow(tpcSectors, // sector configuration + return o2::tpc::reco_workflow::getWorkflow(&gPolicyData, // + tpcSectors, // sector configuration laneConfiguration, // lane configuration doMC, // nLanes, // From ec811f4db00bbebfb920efc416ece4f6b58ae70d Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 13 Oct 2020 13:42:10 +0200 Subject: [PATCH 0921/1751] enabling covariance on muons (#4577) --- Framework/Core/include/Framework/AnalysisDataModel.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 05c9e7558c4cf..14d59145900bc 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -86,7 +86,7 @@ DECLARE_SOA_COLUMN(Snp, snp, float); DECLARE_SOA_COLUMN(Tgl, tgl, float); DECLARE_SOA_COLUMN(Signed1Pt, signed1Pt, float); DECLARE_SOA_EXPRESSION_COLUMN(RawPhi, phiraw, float, nasin(aod::track::snp) + aod::track::alpha); -// FIXME: dynamic column pending inclusion of conditional nodes +// FIXME: make expression column when conditional nodes are supported in Gandiva DECLARE_SOA_DYNAMIC_COLUMN(NormalizedPhi, phi, [](float phi) -> float { constexpr float twopi = 2.0f * static_cast<float>(M_PI); if (phi < 0) @@ -196,13 +196,11 @@ DECLARE_SOA_DYNAMIC_COLUMN(ITSNClsInnerBarrel, itsNClsInnerBarrel, [](uint8_t it DECLARE_SOA_DYNAMIC_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, [](uint8_t tpcNClsFindable, int8_t tpcNClsFindableMinusCrossedRows) -> float { - // FIXME: use int16 tpcNClsCrossedRows from dynamic column as argument int16_t tpcNClsCrossedRows = (int16_t)tpcNClsFindable - tpcNClsFindableMinusCrossedRows; return (float)tpcNClsCrossedRows / (float)tpcNClsFindable; }); DECLARE_SOA_DYNAMIC_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, [](uint8_t tpcNClsShared, uint8_t tpcNClsFindable, int8_t tpcNClsFindableMinusFound) -> float { - // FIXME: use tpcNClsFound from dynamic column as argument int16_t tpcNClsFound = (int16_t)tpcNClsFindable - tpcNClsFindableMinusFound; return (float)tpcNClsShared / (float)tpcNClsFound; }); @@ -321,8 +319,7 @@ DECLARE_SOA_COLUMN(ThetaY, thetaY, float); DECLARE_SOA_COLUMN(ZMu, zMu, float); DECLARE_SOA_COLUMN(BendingCoor, bendingCoor, float); DECLARE_SOA_COLUMN(NonBendingCoor, nonBendingCoor, float); -// FIXME: need to implement array columns... -// DECLARE_SOA_COLUMN(Covariances, covariances, float[], "fCovariances"); +DECLARE_SOA_COLUMN(Covariances, covariances, float[15]); DECLARE_SOA_COLUMN(Chi2, chi2, float); DECLARE_SOA_COLUMN(Chi2MatchTrigger, chi2MatchTrigger, float); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float inverseBendingMomentum, float thetaX, float thetaY) -> float { @@ -361,7 +358,7 @@ DECLARE_SOA_TABLE_FULL(StoredMuons, "Muons", "AOD", "MUON", muon::BCId, muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY, muon::ZMu, muon::BendingCoor, muon::NonBendingCoor, - muon::Chi2, muon::Chi2MatchTrigger, + muon::Covariances, muon::Chi2, muon::Chi2MatchTrigger, muon::Eta<muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY>, muon::Phi<muon::ThetaX, muon::ThetaY>, muon::RAtAbsorberEnd<muon::BendingCoor, muon::NonBendingCoor, muon::ThetaX, muon::ThetaY, muon::ZMu>, From 0c1519f9722a87d7086eca84fce8a5724cb2a082 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 13 Oct 2020 13:55:43 +0200 Subject: [PATCH 0922/1751] DPL Analysis: send prebuilt tables on finalise, not postRun (#4580) --- Framework/Core/src/AnalysisManagers.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index bba95b523034e..57697dfa64226 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -246,14 +246,14 @@ struct OutputManager<Spawns<T>> { return true; } - static bool finalize(ProcessingContext&, Spawns<T>&) + static bool finalize(ProcessingContext& pc, Spawns<T>& what) { + pc.outputs().adopt(what.output(), what.asArrowTable()); return true; } - static bool postRun(EndOfStreamContext& eosc, Spawns<T>& what) + static bool postRun(EndOfStreamContext&, Spawns<T>&) { - eosc.outputs().adopt(what.output(), what.asArrowTable()); return true; } }; @@ -287,14 +287,14 @@ struct OutputManager<Builds<T, P>> { extractOriginalsTuple(what.sources_pack(), pc)); } - static bool finalize(ProcessingContext&, Builds<T, P>&) + static bool finalize(ProcessingContext& pc, Builds<T, P>& what) { + pc.outputs().adopt(what.output(), what.asArrowTable()); return true; } - static bool postRun(EndOfStreamContext& eosc, Builds<T, P>& what) + static bool postRun(EndOfStreamContext&, Builds<T, P>&) { - eosc.outputs().adopt(what.output(), what.asArrowTable()); return true; } }; From 691d14da5564a77d65d2563406aaef9a4df8de24 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 13 Oct 2020 15:14:42 +0200 Subject: [PATCH 0923/1751] Check if digits available before accessing them --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 7974a0cc39dc4..7946a5d14c7d9 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1133,7 +1133,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) assert(clusterer.mPinputLabels->getIndexedSize() >= mIOPtrs.tpcPackedDigits->nTPCDigits[iSlice]); } - { + if (mIOPtrs.tpcPackedDigits) { bool setDigitsOnGPU = doGPU && not mIOPtrs.tpcZS; bool setDigitsOnHost = (not doGPU && not mIOPtrs.tpcZS) || propagateMCLabels; auto* inDigits = mIOPtrs.tpcPackedDigits; From 654e37e3a5ff43febbb9f5e5d0235da142e94da7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 10:53:42 +0200 Subject: [PATCH 0924/1751] GPU: Add track filter to GPU TPC Standalone display --- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 13 +++++++++++-- GPU/GPUTracking/Standalone/display/GPUDisplay.h | 2 ++ .../Standalone/display/GPUDisplayKeys.cxx | 7 ++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 79b6179793bfc..723cc250dfd7e 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -882,7 +882,14 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s size_t startCountInner = mVertexBuffer[iSlice].size(); bool drawing = false; - if (mTRDTrackIds[i]) { + + if (mTrackFilter) { + if (mTrackFilter && mTRDTrackIds[i] == -1) { + break; + } + } + + if (mTRDTrackIds[i] != -1) { auto& trk = trdTracker().Tracks()[mTRDTrackIds[i]]; for (int k = 5; k >= 0; k--) { int cid = trk.GetTrackletIndex(k); @@ -1155,7 +1162,9 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) if ((size_t)mMerger.GetConstantMem()->ioPtrs.nMergedTracks > mTRDTrackIds.size()) { mTRDTrackIds.resize(mMerger.GetConstantMem()->ioPtrs.nMergedTracks); } - memset(mTRDTrackIds.data(), 0, sizeof(mTRDTrackIds[0]) * mMerger.GetConstantMem()->ioPtrs.nMergedTracks); + for (unsigned int i = 0;i < mMerger.GetConstantMem()->ioPtrs.nMergedTracks;i++) { + mTRDTrackIds[i] = -1; + } for (int i = 0; i < trdTracker().NTracks(); i++) { if (trdTracker().Tracks()[i].GetNtracklets()) { mTRDTrackIds[trdTracker().Tracks()[i].GetTPCtrackId()] = i; diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.h b/GPU/GPUTracking/Standalone/display/GPUDisplay.h index 44ada1c12abbf..7852562ea11b8 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.h @@ -238,6 +238,7 @@ class GPUDisplay void SetInfo(Args... args) { snprintf(mInfoText2, 1024, args...); + GPUInfo("%s", mInfoText2); mInfoText2Timer.ResetStart(); } void PrintGLHelpText(float colorValue); @@ -354,6 +355,7 @@ class GPUDisplay int mHideRejectedTracks = 1; int mMarkAdjacentClusters = 0; int mMarkFakeClusters = 0; + int mTrackFilter = 0; vecpod<std::array<int, 37>> mCollisionClusters; int mNCollissions = 1; diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx index b2d3b9cc7fe53..e685c06cabbaa 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx @@ -35,8 +35,9 @@ const char* HelpText[] = { "[L] / [K] Draw single collisions (next / previous)", "[C] Colorcode clusters of different collisions", "[v] Hide rejected clusters from tracks", - "[b] Hide all clusters not belonging or related to matched tracks", + "[b] Hide all clusters not belonging or related to matched tracks in QA", "[j] Show global tracks as additional segments of final tracks", + "[u] Cycle through track filter", "[E] / [G] Extrapolate tracks / loopers", "[t] / [T] Take Screenshot / Record Animation to pictures", "[Z] Change screenshot resolution (scaling factor)", @@ -355,6 +356,10 @@ void GPUDisplay::HandleKeyRelease(unsigned char key) } else { SetInfo("Animation mode %d - Position: %s, Direction: %s", mCfg.animationMode, (mCfg.animationMode & 2) ? "Spherical (spherical rotation)" : (mCfg.animationMode & 4) ? "Spherical (Euler angles)" : "Cartesian", (mCfg.animationMode & 1) ? "Euler angles" : "Quaternion"); } + } else if (key == 'u') { + mTrackFilter = (mTrackFilter + 1) % 2; + mUpdateDLList = true; + SetInfo("Track filter: %s", mTrackFilter ? "TRD Tracks only" : "None"); } else if (key == 'o') { FILE* ftmp = fopen("glpos.tmp", "w+b"); if (ftmp) { From b83e3e3a70d151c3db260da84358215b1fe061df Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 11:06:48 +0200 Subject: [PATCH 0925/1751] GPU: Write all text output of an event before entering visualization --- GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/Global/GPUChainTracking.cxx | 11 +++++-- GPU/GPUTracking/Global/GPUChainTracking.h | 1 + .../GPUChainTrackingDebugAndProfiling.cxx | 32 +++++++++++++++++++ .../Standalone/display/GPUDisplay.cxx | 6 ++-- GPU/GPUTracking/Standalone/standalone.cxx | 27 ++-------------- 6 files changed, 48 insertions(+), 30 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 0b5688dee2f2d..80775a5219f02 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -120,6 +120,7 @@ AddOption(registerStandaloneInputMemory, bool, false, "registerInputMemory", 0, 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") +AddOption(showOutputStat, bool, false, "", 0, "Print some track output statistics") AddVariable(eventDisplay, GPUCA_NAMESPACE::gpu::GPUDisplayBackend*, nullptr) AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 7946a5d14c7d9..56aa8b439ad5a 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2445,6 +2445,14 @@ int GPUChainTracking::RunChainFinalize() mRec->getGeneralStepTimer(GeneralStep::QA).Stop(); } + if (GetProcessingSettings().showOutputStat) { + PrintOutputStat(); + } + + PrintDebugOutput(); + + //PrintMemoryRelations(); + if (GetProcessingSettings().eventDisplay) { if (!mDisplayRunning) { if (mEventDisplay->StartDisplay()) { @@ -2491,9 +2499,6 @@ int GPUChainTracking::RunChainFinalize() mEventDisplay->WaitForNextEvent(); } - PrintDebugOutput(); - - //PrintMemoryRelations(); return 0; } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 2854672ee304c..e148cf6e115d7 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -211,6 +211,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void PrintMemoryStatistics() override; void PrepareDebugOutput(); void PrintDebugOutput(); + void PrintOutputStat(); bool ValidateSteps(); bool ValidateSettings(); diff --git a/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx b/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx index c853a02bc82da..9cd4e25155ee7 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingDebugAndProfiling.cxx @@ -188,3 +188,35 @@ void GPUChainTracking::PrintDebugOutput() processors()->debugOutput.Print(); #endif } + +void GPUChainTracking::PrintOutputStat() +{ + int nTracks = 0, nAttachedClusters = 0, nAttachedClustersFitted = 0, nAdjacentClusters = 0; + for (unsigned int k = 0; k < mIOPtrs.nMergedTracks; k++) { + if (mIOPtrs.mergedTracks[k].OK()) { + nTracks++; + nAttachedClusters += mIOPtrs.mergedTracks[k].NClusters(); + nAttachedClustersFitted += mIOPtrs.mergedTracks[k].NClustersFitted(); + } + } + unsigned int nCls = GetProcessingSettings().doublePipeline ? mIOPtrs.clustersNative->nClustersTotal : GetTPCMerger().NMaxClusters(); + for (unsigned int k = 0; k < nCls; k++) { + int attach = mIOPtrs.mergedTrackHitAttachment[k]; + if (attach & gputpcgmmergertypes::attachFlagMask) { + nAdjacentClusters++; + } + } + + char trdText[1024] = ""; + if (GetRecoSteps() & GPUDataTypes::RecoStep::TRDTracking) { + int nTRDTracks = 0; + int nTRDTracklets = 0; + for (unsigned int k = 0; k < mIOPtrs.nTRDTracks; k++) { + auto& trk = mIOPtrs.trdTracks[k]; + nTRDTracklets += trk.GetNtracklets(); + nTRDTracks += trk.GetNtracklets() != 0; + } + snprintf(trdText, 1024, " - TRD Tracker reconstructed %d tracks (%d tracklets)", nTRDTracks, nTRDTracklets); + } + printf("Output Tracks: %d (%d / %d / %d / %d clusters (fitted / attached / adjacent / total))%s\n", nTracks, nAttachedClustersFitted, nAttachedClusters, nAdjacentClusters, nCls, trdText); +} diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 723cc250dfd7e..f7ec7f69c6bc8 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -882,13 +882,13 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s size_t startCountInner = mVertexBuffer[iSlice].size(); bool drawing = false; - + if (mTrackFilter) { if (mTrackFilter && mTRDTrackIds[i] == -1) { break; } } - + if (mTRDTrackIds[i] != -1) { auto& trk = trdTracker().Tracks()[mTRDTrackIds[i]]; for (int k = 5; k >= 0; k--) { @@ -1162,7 +1162,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) if ((size_t)mMerger.GetConstantMem()->ioPtrs.nMergedTracks > mTRDTrackIds.size()) { mTRDTrackIds.resize(mMerger.GetConstantMem()->ioPtrs.nMergedTracks); } - for (unsigned int i = 0;i < mMerger.GetConstantMem()->ioPtrs.nMergedTracks;i++) { + for (unsigned int i = 0; i < mMerger.GetConstantMem()->ioPtrs.nMergedTracks; i++) { mTRDTrackIds[i] = -1; } for (int i = 0; i < trdTracker().NTracks(); i++) { diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 8ea432889625d..1056734d54caf 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -263,6 +263,8 @@ int ReadConfiguration(int argc, char** argv) return 1; } #endif + + configStandalone.proc.showOutputStat = true; return (0); } @@ -542,39 +544,16 @@ int LoadEvent(int iEvent, int x) void OutputStat(GPUChainTracking* t, long long int* nTracksTotal = nullptr, long long int* nClustersTotal = nullptr) { - int nTracks = 0, nAttachedClusters = 0, nAttachedClustersFitted = 0, nAdjacentClusters = 0; + int nTracks = 0; for (unsigned int k = 0; k < t->mIOPtrs.nMergedTracks; k++) { if (t->mIOPtrs.mergedTracks[k].OK()) { nTracks++; - nAttachedClusters += t->mIOPtrs.mergedTracks[k].NClusters(); - nAttachedClustersFitted += t->mIOPtrs.mergedTracks[k].NClustersFitted(); - } - } - unsigned int nCls = configStandalone.proc.doublePipeline ? t->mIOPtrs.clustersNative->nClustersTotal : t->GetTPCMerger().NMaxClusters(); - for (unsigned int k = 0; k < nCls; k++) { - int attach = t->mIOPtrs.mergedTrackHitAttachment[k]; - if (attach & gputpcgmmergertypes::attachFlagMask) { - nAdjacentClusters++; } } - if (nTracksTotal && nClustersTotal) { *nTracksTotal += nTracks; *nClustersTotal += t->mIOPtrs.nMergedTrackHits; } - - char trdText[1024] = ""; - if (t->GetRecoSteps() & GPUDataTypes::RecoStep::TRDTracking) { - int nTRDTracks = 0; - int nTRDTracklets = 0; - for (unsigned int k = 0; k < t->mIOPtrs.nTRDTracks; k++) { - auto& trk = t->mIOPtrs.trdTracks[k]; - nTRDTracklets += trk.GetNtracklets(); - nTRDTracks += trk.GetNtracklets() != 0; - } - snprintf(trdText, 1024, " - TRD Tracker reconstructed %d tracks (%d tracklets)", nTRDTracks, nTRDTracklets); - } - printf("Output Tracks: %d (%d / %d / %d / %d clusters (fitted / attached / adjacent / total))%s\n", nTracks, nAttachedClustersFitted, nAttachedClusters, nAdjacentClusters, nCls, trdText); } int RunBenchmark(GPUReconstruction* recUse, GPUChainTracking* chainTrackingUse, int runs, int iEvent, long long int* nTracksTotal, long long int* nClustersTotal, int threadId = 0, HighResTimer* timerPipeline = nullptr) From e0845a686c4c4c2b529b3ba77bb0c4223dfae4e2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 11:26:56 +0200 Subject: [PATCH 0926/1751] GPU: Add track filter for TRD candidates to standalone visualization --- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 5 ++++- .../Standalone/display/GPUDisplayKeys.cxx | 4 ++-- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 15 +++++++++++++++ GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 12 +++--------- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index f7ec7f69c6bc8..3e3e18a964283 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -884,7 +884,10 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s bool drawing = false; if (mTrackFilter) { - if (mTrackFilter && mTRDTrackIds[i] == -1) { + if (mTrackFilter == 2 && !trdTracker().CheckTrackTRDCandidate((GPUTRDTrackGPU)*track)) { + break; + } + if (mTrackFilter == 1 && mTRDTrackIds[i] == -1) { break; } } diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx index e685c06cabbaa..3d2ae8be4fcf3 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx @@ -357,9 +357,9 @@ void GPUDisplay::HandleKeyRelease(unsigned char key) SetInfo("Animation mode %d - Position: %s, Direction: %s", mCfg.animationMode, (mCfg.animationMode & 2) ? "Spherical (spherical rotation)" : (mCfg.animationMode & 4) ? "Spherical (Euler angles)" : "Cartesian", (mCfg.animationMode & 1) ? "Euler angles" : "Quaternion"); } } else if (key == 'u') { - mTrackFilter = (mTrackFilter + 1) % 2; + mTrackFilter = (mTrackFilter + 1) % 3; mUpdateDLList = true; - SetInfo("Track filter: %s", mTrackFilter ? "TRD Tracks only" : "None"); + SetInfo("Track filter: %s", mTrackFilter == 2 ? "TRD Track candidates" : mTrackFilter ? "TRD Tracks only" : "None"); } else if (key == 'o') { FILE* ftmp = fopen("glpos.tmp", "w+b"); if (ftmp) { diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index 31c06f20ef778..ca2ddc231517f 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -426,6 +426,21 @@ GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::CheckTrackRefs(const int trackID, boo } #endif //! GPUCA_GPUCODE +template <class TRDTRK, class PROP> +GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CheckTrackTRDCandidate(const TRDTRK& trk) const +{ + if (!trk.CheckNumericalQuality()) { + return false; + } + if (CAMath::Abs(trk.getEta()) > mMaxEta) { + return false; + } + if (trk.getPt() < mMinPt) { + return false; + } + return true; +} + template <class TRDTRK, class PROP> GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTracklet(const GPUTRDTrackletWord& tracklet, const int* labels) { diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index c04a0aa52827c..5d7a320061b4c 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -108,7 +108,7 @@ class GPUTRDTracker_t : public GPUProcessor GPUhd() void OverrideGPUGeometry(TRD_GEOMETRY_CONST GPUTRDGeometry* geo) { mGeo = geo; } void Reset(); GPUd() int LoadTracklet(const GPUTRDTrackletWord& tracklet, const int* labels = nullptr); - //template <class T> + GPUd() bool CheckTrackTRDCandidate(const TRDTRK& trk) const; GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1, int tpcTrackId = -1) { if (mNTracks >= mNMaxTracks) { @@ -117,14 +117,8 @@ class GPUTRDTracker_t : public GPUProcessor #endif return (1); } - if (!trk.CheckNumericalQuality()) { - return (0); - } - if (CAMath::Abs(trk.getEta()) > mMaxEta) { - return (0); - } - if (trk.getPt() < mMinPt) { - return (0); + if (!CheckTrackTRDCandidate(trk)) { + return 0; } #ifdef GPUCA_ALIROOT_LIB new (&mTracks[mNTracks]) TRDTRK(trk); // We need placement new, since the class is virtual From 5037ffd23217ff6c0799c789bdb579f5f08a1e60 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 11:37:05 +0200 Subject: [PATCH 0927/1751] GPU: Move long function LoadTrack into cxx --- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 31 +++++++++++++++++++ GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 31 ++----------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index ca2ddc231517f..d3683ca151529 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -441,6 +441,37 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CheckTrackTRDCandidate(const TRDTRK& return true; } +template <class TRDTRK, class PROP> +GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTrack(const TRDTRK& trk, const int label, const int* nTrkltsOffline, const int labelOffline, int tpcTrackId) +{ + if (mNTracks >= mNMaxTracks) { +#ifndef GPUCA_GPUCODE + GPUError("Error: Track dropped (no memory available) -> must not happen"); +#endif + return (1); + } + if (!CheckTrackTRDCandidate(trk)) { + return 0; + } +#ifdef GPUCA_ALIROOT_LIB + new (&mTracks[mNTracks]) TRDTRK(trk); // We need placement new, since the class is virtual +#else + mTracks[mNTracks] = trk; +#endif + mTracks[mNTracks].SetTPCtrackId(tpcTrackId >= 0 ? tpcTrackId : mNTracks); + if (label >= 0) { + mTracks[mNTracks].SetLabel(label); + } + if (nTrkltsOffline) { + for (int i = 0; i < 4; ++i) { + mTracks[mNTracks].SetNtrackletsOffline(i, nTrkltsOffline[i]); // see GPUTRDTrack.h for information on the index + } + } + mTracks[mNTracks].SetLabelOffline(labelOffline); + mNTracks++; + return (0); +} + template <class TRDTRK, class PROP> GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTracklet(const GPUTRDTrackletWord& tracklet, const int* labels) { diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 5d7a320061b4c..3ccf1af7c26e0 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -109,35 +109,8 @@ class GPUTRDTracker_t : public GPUProcessor void Reset(); GPUd() int LoadTracklet(const GPUTRDTrackletWord& tracklet, const int* labels = nullptr); GPUd() bool CheckTrackTRDCandidate(const TRDTRK& trk) const; - GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1, int tpcTrackId = -1) - { - if (mNTracks >= mNMaxTracks) { -#ifndef GPUCA_GPUCODE - GPUError("Error: Track dropped (no memory available) -> must not happen"); -#endif - return (1); - } - if (!CheckTrackTRDCandidate(trk)) { - return 0; - } -#ifdef GPUCA_ALIROOT_LIB - new (&mTracks[mNTracks]) TRDTRK(trk); // We need placement new, since the class is virtual -#else - mTracks[mNTracks] = trk; -#endif - mTracks[mNTracks].SetTPCtrackId(tpcTrackId >= 0 ? tpcTrackId : mNTracks); - if (label >= 0) { - mTracks[mNTracks].SetLabel(label); - } - if (nTrkltsOffline) { - for (int i = 0; i < 4; ++i) { - mTracks[mNTracks].SetNtrackletsOffline(i, nTrkltsOffline[i]); // see GPUTRDTrack.h for information on the index - } - } - mTracks[mNTracks].SetLabelOffline(labelOffline); - mNTracks++; - return (0); - } + GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1, int tpcTrackId = -1); + GPUd() int GetCollisionID(float trkTime) const; GPUd() void DoTrackingThread(int iTrk, int threadId = 0); GPUd() bool CalculateSpacePoints(int iCollision = 0); From 5ccc97be9d8f96af94e2f83c4e8e7e52b100b8e5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 11:37:24 +0200 Subject: [PATCH 0928/1751] GPU: Simplify TRD track loading in GPU Tracking chain --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 25 +++++++-------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 56aa8b439ad5a..b2e43b1e1d711 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2267,8 +2267,12 @@ int GPUChainTracking::RunTRDTracking() mRec->PushNonPersistentMemory(); SetupGPUProcessor(&Tracker, true); - std::vector<GPUTRDTrackGPU> tracksTPC; - std::vector<int> tracksTPCLab; + + for (unsigned int iTracklet = 0; iTracklet < mIOPtrs.nTRDTracklets; ++iTracklet) { + if (Tracker.LoadTracklet(mIOPtrs.trdTracklets[iTracklet], mIOPtrs.trdTrackletsMC ? mIOPtrs.trdTrackletsMC[iTracklet].mLabel : nullptr)) { + return 1; + } + } for (unsigned int i = 0; i < mIOPtrs.nMergedTracks; i++) { const GPUTPCGMMergedTrack& trk = mIOPtrs.mergedTracks[i]; @@ -2278,23 +2282,10 @@ int GPUChainTracking::RunTRDTracking() if (trk.Looper()) { continue; } - if (param().rec.NWaysOuter) { - tracksTPC.emplace_back(trk.OuterParam()); - } else { - tracksTPC.emplace_back(trk); - } - tracksTPC.back().SetTPCtrackId(i); - tracksTPCLab.push_back(-1); - } - for (unsigned int iTracklet = 0; iTracklet < mIOPtrs.nTRDTracklets; ++iTracklet) { - if (Tracker.LoadTracklet(mIOPtrs.trdTracklets[iTracklet], mIOPtrs.trdTrackletsMC ? mIOPtrs.trdTrackletsMC[iTracklet].mLabel : nullptr)) { - return 1; - } - } + const GPUTRDTrackGPU& trktrd = param().rec.NWaysOuter ? (GPUTRDTrackGPU)trk.OuterParam() : (GPUTRDTrackGPU)trk; - for (unsigned int iTrack = 0; iTrack < tracksTPC.size(); ++iTrack) { - if (Tracker.LoadTrack(tracksTPC[iTrack], tracksTPCLab[iTrack], nullptr, -1, tracksTPC[iTrack].GetTPCtrackId())) { + if (Tracker.LoadTrack(trktrd, -1, nullptr, -1, i)) { return 1; } } From 8341877295d2db6d901b2f17aebd0b72657dc6db Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 13:09:29 +0200 Subject: [PATCH 0929/1751] GPU: Unify checks for TRD track candidates into function inside GPUTRDTracker --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 9 ++++----- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 4 ++-- GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 8 +++++++- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index b2e43b1e1d711..33e4dfc5731ce 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2276,16 +2276,15 @@ int GPUChainTracking::RunTRDTracking() for (unsigned int i = 0; i < mIOPtrs.nMergedTracks; i++) { const GPUTPCGMMergedTrack& trk = mIOPtrs.mergedTracks[i]; - if (!trk.OK()) { + if (!Tracker.PreCheckTrackTRDCandidate(trk)) { continue; } - if (trk.Looper()) { + const GPUTRDTrackGPU& trktrd = param().rec.NWaysOuter ? (GPUTRDTrackGPU)trk.OuterParam() : (GPUTRDTrackGPU)trk; + if (!Tracker.CheckTrackTRDCandidate(trktrd)) { continue; } - const GPUTRDTrackGPU& trktrd = param().rec.NWaysOuter ? (GPUTRDTrackGPU)trk.OuterParam() : (GPUTRDTrackGPU)trk; - - if (Tracker.LoadTrack(trktrd, -1, nullptr, -1, i)) { + if (Tracker.LoadTrack(trktrd, -1, nullptr, -1, i, false)) { return 1; } } diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 3e3e18a964283..fede022945735 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -884,7 +884,7 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s bool drawing = false; if (mTrackFilter) { - if (mTrackFilter == 2 && !trdTracker().CheckTrackTRDCandidate((GPUTRDTrackGPU)*track)) { + if (mTrackFilter == 2 && (!trdTracker().PreCheckTrackTRDCandidate(*track) || !trdTracker().CheckTrackTRDCandidate((GPUTRDTrackGPU)*track))) { break; } if (mTrackFilter == 1 && mTRDTrackIds[i] == -1) { diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index d3683ca151529..10abe93b69454 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -442,7 +442,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CheckTrackTRDCandidate(const TRDTRK& } template <class TRDTRK, class PROP> -GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTrack(const TRDTRK& trk, const int label, const int* nTrkltsOffline, const int labelOffline, int tpcTrackId) +GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTrack(const TRDTRK& trk, const int label, const int* nTrkltsOffline, const int labelOffline, int tpcTrackId, bool checkTrack) { if (mNTracks >= mNMaxTracks) { #ifndef GPUCA_GPUCODE @@ -450,7 +450,7 @@ GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTrack(const TRDTRK& trk, const int #endif return (1); } - if (!CheckTrackTRDCandidate(trk)) { + if (checkTrack && !CheckTrackTRDCandidate(trk)) { return 0; } #ifdef GPUCA_ALIROOT_LIB diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 3ccf1af7c26e0..53cb1c66df1dd 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -108,8 +108,14 @@ class GPUTRDTracker_t : public GPUProcessor GPUhd() void OverrideGPUGeometry(TRD_GEOMETRY_CONST GPUTRDGeometry* geo) { mGeo = geo; } void Reset(); GPUd() int LoadTracklet(const GPUTRDTrackletWord& tracklet, const int* labels = nullptr); + template <class T> + GPUd() bool PreCheckTrackTRDCandidate(const T& trk) const + { + return true; + } + GPUd() bool PreCheckTrackTRDCandidate(const GPUTPCGMMergedTrack& trk) const { return trk.OK() && !trk.Looper(); } GPUd() bool CheckTrackTRDCandidate(const TRDTRK& trk) const; - GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1, int tpcTrackId = -1); + GPUd() int LoadTrack(const TRDTRK& trk, const int label = -1, const int* nTrkltsOffline = nullptr, const int labelOffline = -1, int tpcTrackId = -1, bool checkTrack = true); GPUd() int GetCollisionID(float trkTime) const; GPUd() void DoTrackingThread(int iTrk, int threadId = 0); From a59f1a19a64a5acf5b7633a7401dacf5db117b23 Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Tue, 13 Oct 2020 17:16:18 +0200 Subject: [PATCH 0930/1751] common track selection implemented (from track selection task) + configurable cuts for vertez z position and rapidity --- Analysis/Tasks/CMakeLists.txt | 1 - Analysis/Tasks/trackchecks.cxx | 314 ++++++++++++++++++--------------- 2 files changed, 175 insertions(+), 140 deletions(-) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 7f0de675bf90c..c625a353963bf 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -102,7 +102,6 @@ o2_add_dpl_workflow(run3-matcher SOURCES run3Matcher.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) - o2_add_dpl_workflow(track-checks SOURCES trackchecks.cxx diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index 1b93c80483f01..50cb82853a6c4 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -36,81 +36,61 @@ const double pt_bins[NPTBINS + 1] = {0.0, 0.05, 0.08, 0.1, 0.12, 0.14, 0.16, 0.1 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 10.0, 20.0}; const double mass[NPARTICLES] = {0.000510999, 0.139570, 0.493677, 0.938272, 1.87561}; -enum PType { kEl, - kPi, - kKa, - kPr, - kDe }; - -#define TRACKSELECTION \ - UChar_t clustermap = track.itsClusterMap(); \ - bool issel = (abs(track.eta()) < 0.8) && (track.tpcNClsFindable() > 70) && (track.tpcChi2NCl() < 4.) && (track.tpcCrossedRowsOverFindableCls() > 0.8) && (track.flags() & 0x4) && (track.itsChi2NCl() < 36) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); \ - issel = issel && (track.flags() & (uint64_t(1) << 2)); /*ITS refit*/ \ - issel = issel && (track.flags() & (uint64_t(1) << 6)); /*TPC refit*/ \ - if (!issel) \ - continue; - -struct TrackCheckTask1 { +enum PType : uint8_t { + kEl, + kPi, + kKa, + kPr, + kDe, + kNull +}; + +//function to convert eta to y +double eta2y(double pt, double m, double eta) +{ + double mt = sqrt(m * m + pt * pt); + return asinh(pt / mt * sinh(eta)); +} + +int getparticleint(int pdgcode) +{ + if (pdgcode == 11) + return kEl; + else if (pdgcode == 211) + return kPi; + else if (pdgcode == 321) + return kKa; + else if (pdgcode == 2212) + return kPr; + else if (pdgcode == 1000010020) + return kDe; + else + return kNull; +} + +//No track selection --> only event selection here +struct TrackCheckTaskEvSel { Configurable<bool> isMC{"isMC", false, "option to flag mc"}; - OutputObj<TH1F> hTrkPrimReco{TH1F("hTrkPrimReco", "Reco Prim tracks (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; + Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; OutputObj<TH1F> hTrkPrimAftEvSel{TH1F("hTrkPrimAftEvSel", "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; - OutputObj<HistArray> hTrkPrimReco_truepid{HistArray("hTrkPrimReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hTrkPrimAftEvSel_truepid{HistArray("hTrkPrimAftEvSel_truepid"), OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<HistArray> hDCAxyReco_truepid{HistArray("hDCAxyReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<HistArray> hDCAxyPrim_truepid{HistArray("hDCAxyPrim_truepid"), OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<HistArray> hDCAxySeco_truepid{HistArray("hDCAxySeco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; - TF1* fCutDCAxy; void init(InitContext&) { - hTrkPrimReco_truepid->Add(0, TH1F("hTrkPrimReco_truepid_el", "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add(1, TH1F("hTrkPrimReco_truepid_pi", "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add(2, TH1F("hTrkPrimReco_truepid_ka", "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add(3, TH1F("hTrkPrimReco_truepid_pr", "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add(4, TH1F("hTrkPrimReco_truepid_de", "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - - hTrkPrimAftEvSel_truepid->Add(0, TH1F("hTrkPrimAftEvSel_truepid_el", "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add(1, TH1F("hTrkPrimAftEvSel_truepid_pi", "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add(2, TH1F("hTrkPrimAftEvSel_truepid_ka", "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add(3, TH1F("hTrkPrimAftEvSel_truepid_pr", "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add(4, TH1F("hTrkPrimAftEvSel_truepid_de", "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - - hDCAxyReco_truepid->Add(0, TH2F("hDCAxyReco_truepid_el", "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add(1, TH2F("hDCAxyReco_truepid_pi", "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add(2, TH2F("hDCAxyReco_truepid_ka", "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add(3, TH2F("hDCAxyReco_truepid_pr", "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add(4, TH2F("hDCAxyReco_truepid_de", "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - - hDCAxyPrim_truepid->Add(0, TH2F("hDCAxyPrim_truepid_el", "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add(1, TH2F("hDCAxyPrim_truepid_pi", "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add(2, TH2F("hDCAxyPrim_truepid_ka", "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add(3, TH2F("hDCAxyPrim_truepid_pr", "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add(4, TH2F("hDCAxyPrim_truepid_de", "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - - hDCAxySeco_truepid->Add(0, TH2F("hDCAxySeco_truepid_el", "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add(1, TH2F("hDCAxySeco_truepid_pi", "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add(2, TH2F("hDCAxySeco_truepid_ka", "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add(3, TH2F("hDCAxySeco_truepid_pr", "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add(4, TH2F("hDCAxySeco_truepid_de", "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - - fCutDCAxy = new TF1("fMaxDCAxy", "[0]+[1]/(x^[2])", 0, 1e10); //from TPC analysis task (Run2) - fCutDCAxy->SetParameter(0, 0.0105); - fCutDCAxy->SetParameter(1, 0.0350); - fCutDCAxy->SetParameter(2, 1.1); + hTrkPrimAftEvSel_truepid->Add<kEl>(TH1F("hTrkPrimAftEvSel_truepid_el", "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kPi>(TH1F("hTrkPrimAftEvSel_truepid_pi", "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kKa>(TH1F("hTrkPrimAftEvSel_truepid_ka", "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kPr>(TH1F("hTrkPrimAftEvSel_truepid_pr", "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kDe>(TH1F("hTrkPrimAftEvSel_truepid_de", "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); } //init //Filters - Filter collfilter = nabs(aod::collision::posZ) < (float)10.; + Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) { - if (isMC) { - LOGF(info, "isMC=%d - Running on MC", isMC.value); - } else { - LOGF(info, "isMC=%d - Running on DATA", isMC.value); - } - //event selection if (!isMC && !col.alias()[kINT7]) // trigger (should be skipped in MC) return; @@ -120,108 +100,164 @@ struct TrackCheckTask1 { //Loop on tracks for (auto& track : tracks) { double y = -999.; - int pdgcode = -999; - int ptype = -999; bool isPrimary = false; if (isMC) { //determine particle species base on MC truth and if it is primary or not - pdgcode = track.label().pdgCode(); - if (pdgcode == 11) - ptype = kEl; - else if (pdgcode == 211) - ptype = kPi; - else if (pdgcode == 321) - ptype = kKa; - else if (pdgcode == 2212) - ptype = kPr; - else if (pdgcode == 1000010020) - ptype = kDe; + int pdgcode = track.label().pdgCode(); if (MC::isPhysicalPrimary(mcParticles, track.label())) { //is primary? isPrimary = true; } - } - if (isMC) { //calculate rapidity - y = eta2y(track.pt(), mass[ptype], track.eta()); + int pint = getparticleint(pdgcode); + if (pint == kNull) + y = (double)kNull; + else + y = eta2y(track.pt(), mass[pint], track.eta()); - if (isPrimary && abs(y) < 0.5) { + if (isPrimary && abs(y) < cfgCutY) { //histograms with generated distribution (after event selection) - hTrkPrimAftEvSel_truepid->Fill(ptype, track.pt()); + if (pdgcode == 11) + hTrkPrimAftEvSel_truepid->Fill<kEl>(track.pt()); + else if (pdgcode == 211) + hTrkPrimAftEvSel_truepid->Fill<kPi>(track.pt()); + else if (pdgcode == 321) + hTrkPrimAftEvSel_truepid->Fill<kKa>(track.pt()); + else if (pdgcode == 2212) + hTrkPrimAftEvSel_truepid->Fill<kPr>(track.pt()); + else if (pdgcode == 1000010020) + hTrkPrimAftEvSel_truepid->Fill<kDe>(track.pt()); + hTrkPrimAftEvSel->Fill(track.pt()); //charged particles } } + } // end loop on tracks + } //end of process +}; //end struct TrackCheckTaskEvSel + +//event selection + track selection here +struct TrackCheckTaskEvSelTrackSel { + + Configurable<bool> isMC{"isMC", false, "option to flag mc"}; + Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; + Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; + OutputObj<TH1F> hTrkPrimReco{TH1F("hTrkPrimReco", "Reco Prim tracks (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + OutputObj<HistArray> hTrkPrimReco_truepid{HistArray("hTrkPrimReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<HistArray> hDCAxyReco_truepid{HistArray("hDCAxyReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<HistArray> hDCAxyPrim_truepid{HistArray("hDCAxyPrim_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<HistArray> hDCAxySeco_truepid{HistArray("hDCAxySeco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + hTrkPrimReco_truepid->Add<kEl>(TH1F("hTrkPrimReco_truepid_el", "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kPi>(TH1F("hTrkPrimReco_truepid_pi", "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kKa>(TH1F("hTrkPrimReco_truepid_ka", "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kPr>(TH1F("hTrkPrimReco_truepid_pr", "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kDe>(TH1F("hTrkPrimReco_truepid_de", "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + + hDCAxyReco_truepid->Add<kEl>(TH2F("hDCAxyReco_truepid_el", "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kPi>(TH2F("hDCAxyReco_truepid_pi", "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kKa>(TH2F("hDCAxyReco_truepid_ka", "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kPr>(TH2F("hDCAxyReco_truepid_pr", "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kDe>(TH2F("hDCAxyReco_truepid_de", "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + hDCAxyPrim_truepid->Add<kEl>(TH2F("hDCAxyPrim_truepid_el", "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kPi>(TH2F("hDCAxyPrim_truepid_pi", "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kKa>(TH2F("hDCAxyPrim_truepid_ka", "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kPr>(TH2F("hDCAxyPrim_truepid_pr", "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kDe>(TH2F("hDCAxyPrim_truepid_de", "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + hDCAxySeco_truepid->Add<kEl>(TH2F("hDCAxySeco_truepid_el", "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kPi>(TH2F("hDCAxySeco_truepid_pi", "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kKa>(TH2F("hDCAxySeco_truepid_ka", "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kPr>(TH2F("hDCAxySeco_truepid_pr", "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kDe>(TH2F("hDCAxySeco_truepid_de", "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + } //init - //track selection - DCAxy and DCAz cut done later - other cuts?? - TRACKSELECTION; - - //DCAxy distributions for reco, primary, secondaries (= not primary) - //calculate dcaxy and dcaz - std::pair<float, float> dcas = getdcaxyz(track, col); - if (isMC) { - if (abs(y) < 0.5) { - hDCAxyReco_truepid->Fill(ptype, track.pt(), dcas.first); - if (isPrimary) - hDCAxyPrim_truepid->Fill(ptype, track.pt(), dcas.first); - else - hDCAxySeco_truepid->Fill(ptype, track.pt(), dcas.first); + //Filters + Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; + Filter trackfilter = aod::track::isGlobalTrack == true; + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection, aod::McTrackLabels>>& tracks, aod::McParticles& mcParticles) + { + + //event selection + if (!isMC && !col.alias()[kINT7]) // trigger (should be skipped in MC) + return; + if (!col.sel7()) //additional cuts + return; + + //Loop on tracks + for (auto& track : tracks) { + double y = -999.; + bool isPrimary = false; + + if (isMC) { //determine particle species base on MC truth and if it is primary or not + int pdgcode = track.label().pdgCode(); + + if (MC::isPhysicalPrimary(mcParticles, track.label())) { //is primary? + isPrimary = true; + } + //Calculate y + int pint = getparticleint(pdgcode); + if (pint == kNull) + y = (double)kNull; + else + y = eta2y(track.pt(), mass[pint], track.eta()); + + //DCAxy distributions for reco, primary, secondaries (= not primary) + distributions for reco primaries (MC truth) + if (abs(y) < cfgCutY) { + if (pdgcode == 11) { + hDCAxyReco_truepid->Fill<kEl>(track.pt(), track.dcaXY()); + if (isPrimary) { + hDCAxyPrim_truepid->Fill<kEl>(track.pt(), track.dcaXY()); + hTrkPrimReco_truepid->Fill<kEl>(track.pt()); + } else + hDCAxySeco_truepid->Fill<kEl>(track.pt(), track.dcaXY()); + } else if (pdgcode == 211) { + hDCAxyReco_truepid->Fill<kPi>(track.pt(), track.dcaXY()); + if (isPrimary) { + hDCAxyPrim_truepid->Fill<kPi>(track.pt(), track.dcaXY()); + hTrkPrimReco_truepid->Fill<kPi>(track.pt()); + } else + hDCAxySeco_truepid->Fill<kPi>(track.pt(), track.dcaXY()); + } else if (pdgcode == 321) { + hDCAxyReco_truepid->Fill<kKa>(track.pt(), track.dcaXY()); + if (isPrimary) { + hDCAxyPrim_truepid->Fill<kKa>(track.pt(), track.dcaXY()); + hTrkPrimReco_truepid->Fill<kKa>(track.pt()); + } else + hDCAxySeco_truepid->Fill<kKa>(track.pt(), track.dcaXY()); + } else if (pdgcode == 2212) { + hDCAxyReco_truepid->Fill<kPr>(track.pt(), track.dcaXY()); + if (isPrimary) { + hDCAxyPrim_truepid->Fill<kPr>(track.pt(), track.dcaXY()); + hTrkPrimReco_truepid->Fill<kPr>(track.pt()); + } else + hDCAxySeco_truepid->Fill<kPr>(track.pt(), track.dcaXY()); + } else if (pdgcode == 1000010020) { + hDCAxyReco_truepid->Fill<kDe>(track.pt(), track.dcaXY()); + if (isPrimary) { + hDCAxyPrim_truepid->Fill<kDe>(track.pt(), track.dcaXY()); + hTrkPrimReco_truepid->Fill<kDe>(track.pt()); + } else + hDCAxySeco_truepid->Fill<kDe>(track.pt(), track.dcaXY()); + } } - } - //Additional CUTS - //apply cut on DCAz - if (abs(dcas.second) > 2.0) - continue; - //apply pt-dependent cut on dcaxy - if (abs(dcas.first) > fCutDCAxy->Eval(track.pt())) - continue; - - //fill reco histos - if (isMC) { - if (isPrimary && abs(y) < 0.5) { - hTrkPrimReco_truepid->Fill(ptype, track.pt()); + //reco histos (charged particles) + if (isPrimary && abs(y) < cfgCutY) { hTrkPrimReco->Fill(track.pt()); //charged particles } } } // end loop on tracks } - - //convert eta to y - double eta2y(double pt, double m, double eta) const - { - // convert eta to y - double mt = sqrt(m * m + pt * pt); - return asinh(pt / mt * sinh(eta)); - } - - //calculated DCAxy and DCAz - template <typename T, typename C> - std::pair<float, float> getdcaxyz(T& track, C const& collision) - { - float sinAlpha = 0.f; - float cosAlpha = 0.f; - float globalX = 0.f; - float globalY = 0.f; - float dcaXY = 0.f; - float dcaZ = 0.f; - - sinAlpha = sin(track.alpha()); - cosAlpha = cos(track.alpha()); - globalX = track.x() * cosAlpha - track.y() * sinAlpha; - globalY = track.x() * sinAlpha + track.y() * cosAlpha; - - dcaXY = track.charge() * sqrt(pow((globalX - collision.posX()), 2) + - pow((globalY - collision.posY()), 2)); - dcaZ = track.charge() * sqrt(pow(track.z() - collision.posZ(), 2)); - - return std::make_pair(dcaXY, dcaZ); - } - }; // struct TrackCheckTask1 WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<TrackCheckTask1>("track-histos")}; + adaptAnalysisTask<TrackCheckTaskEvSel>("track-histos-evsel"), + adaptAnalysisTask<TrackCheckTaskEvSelTrackSel>("track-histos-evsel-trksel")}; } From b9b00030dc38a29a62dce830a2537b6873354422 Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Tue, 13 Oct 2020 17:35:39 +0200 Subject: [PATCH 0931/1751] clang format applied for comments in the code --- Analysis/Tasks/trackchecks.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index 50cb82853a6c4..eddaf0634ca26 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -179,7 +179,8 @@ struct TrackCheckTaskEvSelTrackSel { //Filters Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; Filter trackfilter = aod::track::isGlobalTrack == true; - void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection, aod::McTrackLabels>>& tracks, aod::McParticles& mcParticles) + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, + soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection, aod::McTrackLabels>>& tracks, aod::McParticles& mcParticles) { //event selection @@ -206,7 +207,8 @@ struct TrackCheckTaskEvSelTrackSel { else y = eta2y(track.pt(), mass[pint], track.eta()); - //DCAxy distributions for reco, primary, secondaries (= not primary) + distributions for reco primaries (MC truth) + //DCAxy distributions for reco, primary, secondaries (= not primary) + // + distributions for reco primaries (MC truth) if (abs(y) < cfgCutY) { if (pdgcode == 11) { hDCAxyReco_truepid->Fill<kEl>(track.pt(), track.dcaXY()); From 59c6eccb6c2212fe1169b708afb69265dd33c93a Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Tue, 13 Oct 2020 17:54:43 +0200 Subject: [PATCH 0932/1751] retry with clang format --- Analysis/Tasks/trackchecks.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index eddaf0634ca26..65d06e4922818 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -32,9 +32,10 @@ using namespace std; #define NPTBINS 53 #define NPARTICLES 5 -const double pt_bins[NPTBINS + 1] = {0.0, 0.05, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, - 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, - 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 10.0, 20.0}; +const double pt_bins[NPTBINS + 1] = {0.0, 0.05, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, + 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, + 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, + 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 10.0, 20.0}; const double mass[NPARTICLES] = {0.000510999, 0.139570, 0.493677, 0.938272, 1.87561}; enum PType : uint8_t { kEl, @@ -180,7 +181,8 @@ struct TrackCheckTaskEvSelTrackSel { Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; Filter trackfilter = aod::track::isGlobalTrack == true; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, - soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection, aod::McTrackLabels>>& tracks, aod::McParticles& mcParticles) + soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection, aod::McTrackLabels>>& tracks, + aod::McParticles& mcParticles) { //event selection From c6bf08d9648418e69ddf79b82c08a185cf891d3d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 13 Oct 2020 18:03:13 +0200 Subject: [PATCH 0933/1751] Revert "Update WorkflowHelpers.cxx (#4538)" (#4583) This reverts commit 20c9a95a2a2acd3bfa966e82b8fae1c69d4f6335. --- Framework/Core/src/WorkflowHelpers.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index fc5d06e648eb4..a38f0e7946962 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -384,10 +384,10 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext std::vector<bool> isdangling; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { if ((outputTypes[ii] & 2) == 2) { - outputsInputsAOD.emplace_back(OutputsInputs[ii]); - // is this dangling + // temporarily also request to be dangling if ((outputTypes[ii] & 1) == 1) { + outputsInputsAOD.emplace_back(OutputsInputs[ii]); isdangling.emplace_back((outputTypes[ii] & 1) == 1); } } From fbbecd54668d287eff56851954dc95d8913f850a Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Tue, 13 Oct 2020 18:33:04 +0200 Subject: [PATCH 0934/1751] split lines longer than 120 chars, reapplied clang-format --- Analysis/Tasks/trackchecks.cxx | 99 ++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 34 deletions(-) diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index 65d06e4922818..d9c40dc885505 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -75,21 +75,29 @@ struct TrackCheckTaskEvSel { Configurable<bool> isMC{"isMC", false, "option to flag mc"}; Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; - OutputObj<TH1F> hTrkPrimAftEvSel{TH1F("hTrkPrimAftEvSel", "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; - OutputObj<HistArray> hTrkPrimAftEvSel_truepid{HistArray("hTrkPrimAftEvSel_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> hTrkPrimAftEvSel{TH1F("hTrkPrimAftEvSel", + "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + OutputObj<HistArray> hTrkPrimAftEvSel_truepid{HistArray("hTrkPrimAftEvSel_truepid"), + OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { - hTrkPrimAftEvSel_truepid->Add<kEl>(TH1F("hTrkPrimAftEvSel_truepid_el", "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add<kPi>(TH1F("hTrkPrimAftEvSel_truepid_pi", "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add<kKa>(TH1F("hTrkPrimAftEvSel_truepid_ka", "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add<kPr>(TH1F("hTrkPrimAftEvSel_truepid_pr", "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimAftEvSel_truepid->Add<kDe>(TH1F("hTrkPrimAftEvSel_truepid_de", "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kEl>(TH1F("hTrkPrimAftEvSel_truepid_el", + "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kPi>(TH1F("hTrkPrimAftEvSel_truepid_pi", + "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kKa>(TH1F("hTrkPrimAftEvSel_truepid_ka", + "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kPr>(TH1F("hTrkPrimAftEvSel_truepid_pr", + "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimAftEvSel_truepid->Add<kDe>(TH1F("hTrkPrimAftEvSel_truepid_de", + "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); } //init //Filters Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; - void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, + soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) { //event selection @@ -143,37 +151,59 @@ struct TrackCheckTaskEvSelTrackSel { Configurable<bool> isMC{"isMC", false, "option to flag mc"}; Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; - OutputObj<TH1F> hTrkPrimReco{TH1F("hTrkPrimReco", "Reco Prim tracks (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; - OutputObj<HistArray> hTrkPrimReco_truepid{HistArray("hTrkPrimReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TH1F> hTrkPrimReco{TH1F("hTrkPrimReco", "Reco Prim tracks (charged); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)}; + OutputObj<HistArray> hTrkPrimReco_truepid{HistArray("hTrkPrimReco_truepid"), + OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxyReco_truepid{HistArray("hDCAxyReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxyPrim_truepid{HistArray("hDCAxyPrim_truepid"), OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxySeco_truepid{HistArray("hDCAxySeco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { - hTrkPrimReco_truepid->Add<kEl>(TH1F("hTrkPrimReco_truepid_el", "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add<kPi>(TH1F("hTrkPrimReco_truepid_pi", "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add<kKa>(TH1F("hTrkPrimReco_truepid_ka", "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add<kPr>(TH1F("hTrkPrimReco_truepid_pr", "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - hTrkPrimReco_truepid->Add<kDe>(TH1F("hTrkPrimReco_truepid_de", "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); - - hDCAxyReco_truepid->Add<kEl>(TH2F("hDCAxyReco_truepid_el", "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add<kPi>(TH2F("hDCAxyReco_truepid_pi", "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add<kKa>(TH2F("hDCAxyReco_truepid_ka", "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add<kPr>(TH2F("hDCAxyReco_truepid_pr", "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyReco_truepid->Add<kDe>(TH2F("hDCAxyReco_truepid_de", "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - - hDCAxyPrim_truepid->Add<kEl>(TH2F("hDCAxyPrim_truepid_el", "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add<kPi>(TH2F("hDCAxyPrim_truepid_pi", "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add<kKa>(TH2F("hDCAxyPrim_truepid_ka", "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add<kPr>(TH2F("hDCAxyPrim_truepid_pr", "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxyPrim_truepid->Add<kDe>(TH2F("hDCAxyPrim_truepid_de", "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - - hDCAxySeco_truepid->Add<kEl>(TH2F("hDCAxySeco_truepid_el", "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add<kPi>(TH2F("hDCAxySeco_truepid_pi", "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add<kKa>(TH2F("hDCAxySeco_truepid_ka", "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add<kPr>(TH2F("hDCAxySeco_truepid_pr", "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); - hDCAxySeco_truepid->Add<kDe>(TH2F("hDCAxySeco_truepid_de", "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hTrkPrimReco_truepid->Add<kEl>(TH1F("hTrkPrimReco_truepid_el", + "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kPi>(TH1F("hTrkPrimReco_truepid_pi", + "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kKa>(TH1F("hTrkPrimReco_truepid_ka", + "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kPr>(TH1F("hTrkPrimReco_truepid_pr", + "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + hTrkPrimReco_truepid->Add<kDe>(TH1F("hTrkPrimReco_truepid_de", + "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + + hDCAxyReco_truepid->Add<kEl>(TH2F("hDCAxyReco_truepid_el", + "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kPi>(TH2F("hDCAxyReco_truepid_pi", + "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kKa>(TH2F("hDCAxyReco_truepid_ka", + "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kPr>(TH2F("hDCAxyReco_truepid_pr", + "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyReco_truepid->Add<kDe>(TH2F("hDCAxyReco_truepid_de", + "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + hDCAxyPrim_truepid->Add<kEl>(TH2F("hDCAxyPrim_truepid_el", + "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kPi>(TH2F("hDCAxyPrim_truepid_pi", + "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kKa>(TH2F("hDCAxyPrim_truepid_ka", + "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kPr>(TH2F("hDCAxyPrim_truepid_pr", + "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxyPrim_truepid->Add<kDe>(TH2F("hDCAxyPrim_truepid_de", + "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + + hDCAxySeco_truepid->Add<kEl>(TH2F("hDCAxySeco_truepid_el", + "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kPi>(TH2F("hDCAxySeco_truepid_pi", + "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kKa>(TH2F("hDCAxySeco_truepid_ka", + "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kPr>(TH2F("hDCAxySeco_truepid_pr", + "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + hDCAxySeco_truepid->Add<kDe>(TH2F("hDCAxySeco_truepid_de", + "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); } //init @@ -181,7 +211,8 @@ struct TrackCheckTaskEvSelTrackSel { Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; Filter trackfilter = aod::track::isGlobalTrack == true; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, - soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection, aod::McTrackLabels>>& tracks, + soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, + aod::TrackSelection, aod::McTrackLabels>>& tracks, aod::McParticles& mcParticles) { From ad40ff211fa6063317272d50b2ba6f699b0a6ae9 Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Tue, 13 Oct 2020 18:35:56 +0200 Subject: [PATCH 0935/1751] split lines longer than 120 chars, no clang-format command launched --- Analysis/Tasks/trackchecks.cxx | 65 +++++++++++++++++----------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index d9c40dc885505..3b2203db1b3a8 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -76,28 +76,28 @@ struct TrackCheckTaskEvSel { Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; OutputObj<TH1F> hTrkPrimAftEvSel{TH1F("hTrkPrimAftEvSel", - "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; OutputObj<HistArray> hTrkPrimAftEvSel_truepid{HistArray("hTrkPrimAftEvSel_truepid"), - OutputObjHandlingPolicy::AnalysisObject}; + OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { hTrkPrimAftEvSel_truepid->Add<kEl>(TH1F("hTrkPrimAftEvSel_truepid_el", - "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kPi>(TH1F("hTrkPrimAftEvSel_truepid_pi", - "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kKa>(TH1F("hTrkPrimAftEvSel_truepid_ka", - "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kPr>(TH1F("hTrkPrimAftEvSel_truepid_pr", - "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kDe>(TH1F("hTrkPrimAftEvSel_truepid_de", - "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); } //init //Filters Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, - soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) + soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) { //event selection @@ -152,9 +152,9 @@ struct TrackCheckTaskEvSelTrackSel { Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; OutputObj<TH1F> hTrkPrimReco{TH1F("hTrkPrimReco", "Reco Prim tracks (charged); #it{p}_{T} (GeV/#it{c}); Counts", - NPTBINS, pt_bins)}; + NPTBINS, pt_bins)}; OutputObj<HistArray> hTrkPrimReco_truepid{HistArray("hTrkPrimReco_truepid"), - OutputObjHandlingPolicy::AnalysisObject}; + OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxyReco_truepid{HistArray("hDCAxyReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxyPrim_truepid{HistArray("hDCAxyPrim_truepid"), OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxySeco_truepid{HistArray("hDCAxySeco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; @@ -162,48 +162,48 @@ struct TrackCheckTaskEvSelTrackSel { void init(InitContext&) { hTrkPrimReco_truepid->Add<kEl>(TH1F("hTrkPrimReco_truepid_el", - "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kPi>(TH1F("hTrkPrimReco_truepid_pi", - "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kKa>(TH1F("hTrkPrimReco_truepid_ka", - "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kPr>(TH1F("hTrkPrimReco_truepid_pr", - "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kDe>(TH1F("hTrkPrimReco_truepid_de", - "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hDCAxyReco_truepid->Add<kEl>(TH2F("hDCAxyReco_truepid_el", - "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kPi>(TH2F("hDCAxyReco_truepid_pi", - "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kKa>(TH2F("hDCAxyReco_truepid_ka", - "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kPr>(TH2F("hDCAxyReco_truepid_pr", - "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kDe>(TH2F("hDCAxyReco_truepid_de", - "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kEl>(TH2F("hDCAxyPrim_truepid_el", - "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kPi>(TH2F("hDCAxyPrim_truepid_pi", - "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kKa>(TH2F("hDCAxyPrim_truepid_ka", - "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kPr>(TH2F("hDCAxyPrim_truepid_pr", - "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kDe>(TH2F("hDCAxyPrim_truepid_de", - "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kEl>(TH2F("hDCAxySeco_truepid_el", - "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kPi>(TH2F("hDCAxySeco_truepid_pi", - "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kKa>(TH2F("hDCAxySeco_truepid_ka", - "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kPr>(TH2F("hDCAxySeco_truepid_pr", - "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kDe>(TH2F("hDCAxySeco_truepid_de", - "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); } //init @@ -211,9 +211,8 @@ struct TrackCheckTaskEvSelTrackSel { Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; Filter trackfilter = aod::track::isGlobalTrack == true; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, - soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, - aod::TrackSelection, aod::McTrackLabels>>& tracks, - aod::McParticles& mcParticles) + soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, + aod::TrackSelection, aod::McTrackLabels>>& tracks, aod::McParticles& mcParticles) { //event selection From 8526efdf072653051818be37d2c3b1ac1c0170db Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Tue, 13 Oct 2020 20:42:32 +0200 Subject: [PATCH 0936/1751] last time clang-format before notifying experts --- Analysis/Tasks/trackchecks.cxx | 65 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index 3b2203db1b3a8..d9c40dc885505 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -76,28 +76,28 @@ struct TrackCheckTaskEvSel { Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; OutputObj<TH1F> hTrkPrimAftEvSel{TH1F("hTrkPrimAftEvSel", - "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; OutputObj<HistArray> hTrkPrimAftEvSel_truepid{HistArray("hTrkPrimAftEvSel_truepid"), - OutputObjHandlingPolicy::AnalysisObject}; + OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { hTrkPrimAftEvSel_truepid->Add<kEl>(TH1F("hTrkPrimAftEvSel_truepid_el", - "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kPi>(TH1F("hTrkPrimAftEvSel_truepid_pi", - "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kKa>(TH1F("hTrkPrimAftEvSel_truepid_ka", - "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kPr>(TH1F("hTrkPrimAftEvSel_truepid_pr", - "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kDe>(TH1F("hTrkPrimAftEvSel_truepid_de", - "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); } //init //Filters Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, - soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) + soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels>& tracks, aod::McParticles& mcParticles) { //event selection @@ -152,9 +152,9 @@ struct TrackCheckTaskEvSelTrackSel { Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; OutputObj<TH1F> hTrkPrimReco{TH1F("hTrkPrimReco", "Reco Prim tracks (charged); #it{p}_{T} (GeV/#it{c}); Counts", - NPTBINS, pt_bins)}; + NPTBINS, pt_bins)}; OutputObj<HistArray> hTrkPrimReco_truepid{HistArray("hTrkPrimReco_truepid"), - OutputObjHandlingPolicy::AnalysisObject}; + OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxyReco_truepid{HistArray("hDCAxyReco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxyPrim_truepid{HistArray("hDCAxyPrim_truepid"), OutputObjHandlingPolicy::AnalysisObject}; OutputObj<HistArray> hDCAxySeco_truepid{HistArray("hDCAxySeco_truepid"), OutputObjHandlingPolicy::AnalysisObject}; @@ -162,48 +162,48 @@ struct TrackCheckTaskEvSelTrackSel { void init(InitContext&) { hTrkPrimReco_truepid->Add<kEl>(TH1F("hTrkPrimReco_truepid_el", - "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kPi>(TH1F("hTrkPrimReco_truepid_pi", - "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kKa>(TH1F("hTrkPrimReco_truepid_ka", - "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kPr>(TH1F("hTrkPrimReco_truepid_pr", - "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kDe>(TH1F("hTrkPrimReco_truepid_de", - "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); hDCAxyReco_truepid->Add<kEl>(TH2F("hDCAxyReco_truepid_el", - "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kPi>(TH2F("hDCAxyReco_truepid_pi", - "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kKa>(TH2F("hDCAxyReco_truepid_ka", - "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kPr>(TH2F("hDCAxyReco_truepid_pr", - "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kDe>(TH2F("hDCAxyReco_truepid_de", - "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kEl>(TH2F("hDCAxyPrim_truepid_el", - "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kPi>(TH2F("hDCAxyPrim_truepid_pi", - "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kKa>(TH2F("hDCAxyPrim_truepid_ka", - "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kPr>(TH2F("hDCAxyPrim_truepid_pr", - "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kDe>(TH2F("hDCAxyPrim_truepid_de", - "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kEl>(TH2F("hDCAxySeco_truepid_el", - "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kPi>(TH2F("hDCAxySeco_truepid_pi", - "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kKa>(TH2F("hDCAxySeco_truepid_ka", - "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kPr>(TH2F("hDCAxySeco_truepid_pr", - "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kDe>(TH2F("hDCAxySeco_truepid_de", - "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); } //init @@ -211,8 +211,9 @@ struct TrackCheckTaskEvSelTrackSel { Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; Filter trackfilter = aod::track::isGlobalTrack == true; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, - soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, - aod::TrackSelection, aod::McTrackLabels>>& tracks, aod::McParticles& mcParticles) + soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, + aod::TrackSelection, aod::McTrackLabels>>& tracks, + aod::McParticles& mcParticles) { //event selection From bac1d2678245ac965c9e5ef6a07665be92f74ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Tue, 13 Oct 2020 21:27:51 +0200 Subject: [PATCH 0937/1751] Update to TPC spectra task and added PID QA plots to PID tasks (#4587) - Update TPC spectra task - Use common configuration - Use same filtering in all sub tasks - Add histograms for event and unselected tracks - Add QA histograms for TOF PID in TOF PID task - QA histograms are now optionally added - Add QA histograms for TPC PID in TPC PID task - QA histograms are now optionally added --- Analysis/Tasks/CMakeLists.txt | 4 +- Analysis/Tasks/PWGLF/spectraTPC.cxx | 118 ++++++-------- Analysis/Tasks/pidTOF.cxx | 236 +++++++++++++++++++++++++++- Analysis/Tasks/pidTPC.cxx | 164 ++++++++++++++++++- 4 files changed, 446 insertions(+), 76 deletions(-) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index db35ed2080e91..d818f8eb79502 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -31,12 +31,12 @@ o2_add_dpl_workflow(qatask o2_add_dpl_workflow(pid-tof SOURCES pidTOF.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(pid-tpc SOURCES pidTPC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(validation diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index bbdc39ff8afe4..e53228945bc18 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -9,11 +9,11 @@ // or submit itself to any jurisdiction. // O2 includes +#include "ReconstructionDataFormats/Track.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/Track.h" -#include "PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" +#include "PID/PIDResponse.h" #include "Analysis/TrackSelectionTables.h" // ROOT includes @@ -32,12 +32,21 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) #include "Framework/runDataProcessing.h" -#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP}; - #define DOTH1F(OBJ, ...) \ OutputObj<TH1F> OBJ{TH1F(#OBJ, __VA_ARGS__)}; #define DOTH2F(OBJ, ...) \ OutputObj<TH2F> OBJ{TH2F(#OBJ, __VA_ARGS__)}; +#define DOTH3F(OBJ, ...) \ + OutputObj<TH3F> OBJ{TH3F(#OBJ, __VA_ARGS__)}; + +#define CANDIDATE_SELECTION \ + Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; \ + Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; \ + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; \ + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); \ + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>>; \ + using TrackCandidateswTOF = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>>; \ + using CollisionCandidates = soa::Filtered<aod::Collisions>; #define makelogaxis(h) \ { \ @@ -56,11 +65,9 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) struct TPCPIDQAExpSignalTask { // Options - O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") - #define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000 + DOTH1F(hvertexz, ";Vtx_{z} (cm);Entries", 100, -20, 20); DOTH2F(htpcsignal, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); DOTH2F(hexpEl, ";#it{p} (GeV/#it{c});TPC expected signal e;Tracks", BIN_AXIS); DOTH2F(hexpMu, ";#it{p} (GeV/#it{c});TPC expected signal #mu;Tracks", BIN_AXIS); @@ -90,10 +97,11 @@ struct TPCPIDQAExpSignalTask { } // Filters - Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); - void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>> const& tracks) + CANDIDATE_SELECTION + + void process(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) { + hvertexz->Fill(collision.posZ()); for (auto const& i : tracks) { // const float mom = i.p(); const float mom = i.tpcInnerParam(); @@ -113,9 +121,6 @@ struct TPCPIDQAExpSignalTask { struct TPCPIDQANSigmaTask { // Options - O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") - #define BIN_AXIS 1000, 0.001, 20, 1000, -10, 10 // TPC NSigma @@ -146,10 +151,9 @@ struct TPCPIDQANSigmaTask { } // Filters - Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); + CANDIDATE_SELECTION - void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>> const& tracks) + void process(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) { for (auto const& i : tracks) { hnsigmaEl->Fill(i.p(), i.tpcNSigmaEl()); @@ -166,21 +170,18 @@ struct TPCPIDQANSigmaTask { }; struct TPCPIDQASignalwTOFTask { - // Options - O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") -#define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000 +#define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000, 20, -10, 10 - DOTH2F(htpcsignalEl, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalMu, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalPi, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalKa, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalPr, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalDe, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalTr, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalHe, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(htpcsignalAl, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); + DOTH3F(htpcsignalEl, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma e", BIN_AXIS); + DOTH3F(htpcsignalMu, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma #mu", BIN_AXIS); + DOTH3F(htpcsignalPi, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma #pi", BIN_AXIS); + DOTH3F(htpcsignalKa, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma K", BIN_AXIS); + DOTH3F(htpcsignalPr, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma p", BIN_AXIS); + DOTH3F(htpcsignalDe, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma d", BIN_AXIS); + DOTH3F(htpcsignalTr, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma t", BIN_AXIS); + DOTH3F(htpcsignalHe, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma ^{3}He", BIN_AXIS); + DOTH3F(htpcsignalAl, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma #alpha", BIN_AXIS); #undef BIN_AXIS @@ -199,55 +200,34 @@ struct TPCPIDQASignalwTOFTask { } // Filters - Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); + CANDIDATE_SELECTION - void process(aod::Collision const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>> const& tracks) + void process(CollisionCandidates::iterator const& collision, TrackCandidateswTOF const& tracks) { for (auto const& i : tracks) { - // Require kTIME and kTOFout - if (!(i.flags() & 0x2000)) - continue; - if (!(i.flags() & 0x80000000)) - continue; - // - // const float mom = i.p(); const float mom = i.tpcInnerParam(); - if (abs(i.tofNSigmaEl()) < 2) { - htpcsignalEl->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaMu()) < 2) { - htpcsignalMu->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaPi()) < 2) { - htpcsignalPi->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaKa()) < 2) { - htpcsignalKa->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaPr()) < 2) { - htpcsignalPr->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaDe()) < 2) { - htpcsignalDe->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaTr()) < 2) { - htpcsignalTr->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaHe()) < 2) { - htpcsignalHe->Fill(mom, i.tpcSignal()); - } - if (abs(i.tofNSigmaAl()) < 2) { - htpcsignalAl->Fill(mom, i.tpcSignal()); + if (i.tofSignal() < 0) { // Skip tracks without TOF + continue; } + htpcsignalEl->Fill(mom, i.tpcSignal(), i.tofNSigmaEl()); + htpcsignalMu->Fill(mom, i.tpcSignal(), i.tofNSigmaMu()); + htpcsignalPi->Fill(mom, i.tpcSignal(), i.tofNSigmaPi()); + htpcsignalKa->Fill(mom, i.tpcSignal(), i.tofNSigmaKa()); + htpcsignalPr->Fill(mom, i.tpcSignal(), i.tofNSigmaPr()); + htpcsignalDe->Fill(mom, i.tpcSignal(), i.tofNSigmaDe()); + htpcsignalTr->Fill(mom, i.tpcSignal(), i.tofNSigmaTr()); + htpcsignalHe->Fill(mom, i.tpcSignal(), i.tofNSigmaHe()); + htpcsignalAl->Fill(mom, i.tpcSignal(), i.tofNSigmaAl()); } } }; struct TPCSpectraTask { + // Pt #define TIT ";#it{p}_{T} (GeV/#it{c});Tracks" + DOTH1F(hpt, TIT, 100, 0, 20); DOTH1F(hpt_El, TIT, 100, 0, 20); DOTH1F(hpt_Pi, TIT, 100, 0, 20); DOTH1F(hpt_Ka, TIT, 100, 0, 20); @@ -255,15 +235,21 @@ struct TPCSpectraTask { #undef TIT // P #define TIT ";#it{p} (GeV/#it{c});Tracks" + DOTH1F(hp, TIT, 100, 0, 20); DOTH1F(hp_El, TIT, 100, 0, 20); DOTH1F(hp_Pi, TIT, 100, 0, 20); DOTH1F(hp_Ka, TIT, 100, 0, 20); DOTH1F(hp_Pr, TIT, 100, 0, 20); #undef TIT - void process(soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) + //Defining filters and input + CANDIDATE_SELECTION + + void process(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) { for (auto i : tracks) { + hp->Fill(i.p()); + hpt->Fill(i.pt()); if (TMath::Abs(i.tpcNSigmaEl()) < 3) { hp_El->Fill(i.p()); hpt_El->Fill(i.pt()); diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index 3200b7810f204..430468beaf3ee 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -9,13 +9,21 @@ // or submit itself to any jurisdiction. // O2 includes -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" #include "ReconstructionDataFormats/Track.h" #include "PID/PIDResponse.h" -#include "Framework/ASoAHelpers.h" #include <CCDB/BasicCCDBManager.h> +#include "Analysis/HistHelpers.h" + +// #define USE_REGISTRY +#ifdef USE_REGISTRY +#include "Framework/HistogramRegistry.h" +#endif + +// ROOT includes +#include <TH1F.h> using namespace o2; using namespace o2::framework; @@ -23,6 +31,15 @@ using namespace o2::pid; using namespace o2::framework::expressions; using namespace o2::track; +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"add-qa", VariantType::Int, 0, {"Produce TOF PID QA histograms"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + struct pidTOFTask { Produces<aod::pidRespTOF> tofpid; Produces<aod::pidRespTOFbeta> tofpidbeta; @@ -102,7 +119,218 @@ struct pidTOFTask { } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +struct pidTOFTaskQA { + enum event_histo : uint8_t { vertexz, + signal, + tofbeta }; + enum Particle : uint8_t { El, + Mu, + Pi, + Ka, + Pr, + De, + Tr, + He, + Al }; + +#ifdef USE_REGISTRY + // Event + HistogramRegistry event{ + "event", + true, + { + {"hvertexz", ";Vtx_{z} (cm);Entries", {HistogramType::kTH1F, {{100, -20, 20}}}}, + {"htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}} // + {"htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 2}}}} // + } // + }; + // Exp signal + HistogramRegistry expected{ + "expected", + true, + { + {"hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, + {"hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}} // + } // + }; + // T-Texp + HistogramRegistry timediff{ + "timediff", + true, + { + {"htimediffEl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffMu", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffPi", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffKa", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffPr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffDe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp d})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffTr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp t})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffHe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp ^{3}He})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, + {"htimediffAl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #alpha})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}} // + } // + }; + + // NSigma + HistogramRegistry nsigma{ + "nsigma", + true, + { + {"hnsigmaEl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(e)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaMu", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#mu)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaPi", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#pi)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaKa", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(K)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaPr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(p)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaDe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(d)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaTr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(t)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaHe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(^{3}He)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, + {"hnsigmaAl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#alpha)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}} // + } // + }; +#else + // Event + OutputObj<experimental::histhelpers::HistFolder> event{experimental::histhelpers::HistFolder("event"), OutputObjHandlingPolicy::QAObject}; + // Exp signal + OutputObj<experimental::histhelpers::HistFolder> expected{experimental::histhelpers::HistFolder("expected"), OutputObjHandlingPolicy::QAObject}; + // T-Texp + OutputObj<experimental::histhelpers::HistFolder> timediff{experimental::histhelpers::HistFolder("timediff"), OutputObjHandlingPolicy::QAObject}; + // NSigma + OutputObj<experimental::histhelpers::HistFolder> nsigma{experimental::histhelpers::HistFolder("nsigma"), OutputObjHandlingPolicy::QAObject}; +#endif + + void init(o2::framework::InitContext&) + { +#ifndef USE_REGISTRY + event->Add<vertexz>(new TH1F("hvertexz", ";Vtx_{z} (cm);Entries", 100, -20, 20)); + event->Add<signal>(new TH2F("htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", 100, 0, 5, 100, 0, 10000)); + event->Add<tofbeta>(new TH2F("htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", 100, 0, 5, 100, 0, 2)); + // + expected->Add<El>(new TH2F("hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", 100, 0, 5, 100, 0, 10000)); + expected->Add<Mu>(new TH2F("hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", 100, 0, 5, 100, 0, 10000)); + expected->Add<Pi>(new TH2F("hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", 100, 0, 5, 100, 0, 10000)); + expected->Add<Ka>(new TH2F("hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", 100, 0, 5, 100, 0, 10000)); + expected->Add<Pr>(new TH2F("hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", 100, 0, 5, 100, 0, 10000)); + expected->Add<De>(new TH2F("hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", 100, 0, 5, 100, 0, 10000)); + expected->Add<Tr>(new TH2F("hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", 100, 0, 5, 100, 0, 10000)); + expected->Add<He>(new TH2F("hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", 100, 0, 5, 100, 0, 10000)); + expected->Add<Al>(new TH2F("hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", 100, 0, 5, 100, 0, 10000)); + // + timediff->Add<El>(new TH2F("htimediffEl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<Mu>(new TH2F("htimediffMu", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<Pi>(new TH2F("htimediffPi", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<Ka>(new TH2F("htimediffKa", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<Pr>(new TH2F("htimediffPr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<De>(new TH2F("htimediffDe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp d})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<Tr>(new TH2F("htimediffTr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp t})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<He>(new TH2F("htimediffHe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp ^{3}He})", 100, 0, 5, 100, -1000, 1000)); + timediff->Add<Al>(new TH2F("htimediffAl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #alpha})", 100, 0, 5, 100, -1000, 1000)); + // + nsigma->Add<El>(new TH2F("nsigmaEl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(e)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Mu>(new TH2F("nsigmaMu", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#mu)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Pi>(new TH2F("nsigmaPi", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#pi)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Ka>(new TH2F("nsigmaKa", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(K)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Pr>(new TH2F("nsigmaPr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(p)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<De>(new TH2F("nsigmaDe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(d)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Tr>(new TH2F("nsigmaTr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(t)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<He>(new TH2F("nsigmaHe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(^{3}He)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Al>(new TH2F("nsigmaAl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#alpha)", 1000, 0.001, 20, 200, -10, 10)); +#endif + } + + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) + { +#ifdef USE_REGISTRY + event("vertexz")->Fill(collision.posZ()); +#else + event->Fill<vertexz>(collision.posZ()); +#endif + + for (auto i : tracks) { + // + const float tof = i.tofSignal() - collision.collisionTime(); +#ifdef USE_REGISTRY + event("htofsignal")->Fill(i.p(), i.tofSignal()); + event("htofbeta")->Fill(i.p(), i.beta()); + // + expected("hexpectedEl")->Fill(i.p(), i.tofExpSignalEl()); + expected("hexpectedEl")->Fill(i.p(), i.tofExpSignalEl()); + expected("hexpectedMu")->Fill(i.p(), i.tofExpSignalMu()); + expected("hexpectedPi")->Fill(i.p(), i.tofExpSignalPi()); + expected("hexpectedKa")->Fill(i.p(), i.tofExpSignalKa()); + expected("hexpectedPr")->Fill(i.p(), i.tofExpSignalPr()); + expected("hexpectedDe")->Fill(i.p(), i.tofExpSignalDe()); + expected("hexpectedTr")->Fill(i.p(), i.tofExpSignalTr()); + expected("hexpectedHe")->Fill(i.p(), i.tofExpSignalHe()); + expected("hexpectedAl")->Fill(i.p(), i.tofExpSignalAl()); + // + timediff("htimediffEl")->Fill(i.p(), tof - i.tofExpSignalEl()); + timediff("htimediffMu")->Fill(i.p(), tof - i.tofExpSignalMu()); + timediff("htimediffPi")->Fill(i.p(), tof - i.tofExpSignalPi()); + timediff("htimediffKa")->Fill(i.p(), tof - i.tofExpSignalKa()); + timediff("htimediffPr")->Fill(i.p(), tof - i.tofExpSignalPr()); + timediff("htimediffDe")->Fill(i.p(), tof - i.tofExpSignalDe()); + timediff("htimediffTr")->Fill(i.p(), tof - i.tofExpSignalTr()); + timediff("htimediffHe")->Fill(i.p(), tof - i.tofExpSignalHe()); + timediff("htimediffAl")->Fill(i.p(), tof - i.tofExpSignalAl()); + // + nsigma("hnsigmaEl")->Fill(i.p(), i.tofNSigmaEl()); + nsigma("hnsigmaMu")->Fill(i.p(), i.tofNSigmaMu()); + nsigma("hnsigmaPi")->Fill(i.p(), i.tofNSigmaPi()); + nsigma("hnsigmaKa")->Fill(i.p(), i.tofNSigmaKa()); + nsigma("hnsigmaPr")->Fill(i.p(), i.tofNSigmaPr()); + nsigma("hnsigmaDe")->Fill(i.p(), i.tofNSigmaDe()); + nsigma("hnsigmaTr")->Fill(i.p(), i.tofNSigmaTr()); + nsigma("hnsigmaHe")->Fill(i.p(), i.tofNSigmaHe()); + nsigma("hnsigmaAl")->Fill(i.p(), i.tofNSigmaAl()); +#else + event->Fill<signal>(i.p(), i.tofSignal()); + event->Fill<tofbeta>(i.p(), i.beta()); + // + expected->Fill<El>(i.p(), i.tofExpSignalEl()); + expected->Fill<Mu>(i.p(), i.tofExpSignalMu()); + expected->Fill<Pi>(i.p(), i.tofExpSignalPi()); + expected->Fill<Ka>(i.p(), i.tofExpSignalKa()); + expected->Fill<Pr>(i.p(), i.tofExpSignalPr()); + expected->Fill<De>(i.p(), i.tofExpSignalDe()); + expected->Fill<Tr>(i.p(), i.tofExpSignalTr()); + expected->Fill<He>(i.p(), i.tofExpSignalHe()); + expected->Fill<Al>(i.p(), i.tofExpSignalAl()); + // + timediff->Fill<El>(i.p(), tof - i.tofExpSignalEl()); + timediff->Fill<Mu>(i.p(), tof - i.tofExpSignalMu()); + timediff->Fill<Pi>(i.p(), tof - i.tofExpSignalPi()); + timediff->Fill<Ka>(i.p(), tof - i.tofExpSignalKa()); + timediff->Fill<Pr>(i.p(), tof - i.tofExpSignalPr()); + timediff->Fill<De>(i.p(), tof - i.tofExpSignalDe()); + timediff->Fill<Tr>(i.p(), tof - i.tofExpSignalTr()); + timediff->Fill<He>(i.p(), tof - i.tofExpSignalHe()); + timediff->Fill<Al>(i.p(), tof - i.tofExpSignalAl()); + // + nsigma->Fill<El>(i.p(), i.tofNSigmaEl()); + nsigma->Fill<Mu>(i.p(), i.tofNSigmaMu()); + nsigma->Fill<Pi>(i.p(), i.tofNSigmaPi()); + nsigma->Fill<Ka>(i.p(), i.tofNSigmaKa()); + nsigma->Fill<Pr>(i.p(), i.tofNSigmaPr()); + nsigma->Fill<De>(i.p(), i.tofNSigmaDe()); + nsigma->Fill<Tr>(i.p(), i.tofNSigmaTr()); + nsigma->Fill<He>(i.p(), i.tofNSigmaHe()); + nsigma->Fill<Al>(i.p(), i.tofNSigmaAl()); +#endif + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask<pidTOFTask>("pidTOF-task")}; + auto workflow = WorkflowSpec{adaptAnalysisTask<pidTOFTask>("pidTOF-task")}; + if (cfgc.options().get<int>("add-qa")) { + workflow.push_back(adaptAnalysisTask<pidTOFTaskQA>("pidTOFQA-task")); + } + return workflow; } diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index 4c127f018971c..b1fedaa72e64f 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -9,13 +9,13 @@ // or submit itself to any jurisdiction. // O2 includes -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" #include "ReconstructionDataFormats/Track.h" #include "PID/PIDResponse.h" -#include "Framework/ASoAHelpers.h" #include <CCDB/BasicCCDBManager.h> +#include "Analysis/HistHelpers.h" using namespace o2; using namespace o2::framework; @@ -23,6 +23,15 @@ using namespace o2::pid; using namespace o2::framework::expressions; using namespace o2::track; +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"add-qa", VariantType::Int, 0, {"Produce TOF PID QA histograms"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + struct pidTPCTask { Produces<aod::pidRespTPC> tpcpid; DetectorResponse<tpc::Response> resp = DetectorResponse<tpc::Response>(); @@ -90,7 +99,154 @@ struct pidTPCTask { } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +struct pidTPCTaskQA { + enum event_histo : uint8_t { vertexz, + signal }; + enum Particle : uint8_t { El, + Mu, + Pi, + Ka, + Pr, + De, + Tr, + He, + Al + }; + + // Event + OutputObj<experimental::histhelpers::HistFolder> event{experimental::histhelpers::HistFolder("event"), OutputObjHandlingPolicy::QAObject}; + // Exp signal + OutputObj<experimental::histhelpers::HistFolder> expected{experimental::histhelpers::HistFolder("expected"), OutputObjHandlingPolicy::QAObject}; + // Exp signal difference + OutputObj<experimental::histhelpers::HistFolder> expected_diff{experimental::histhelpers::HistFolder("expected_diff"), OutputObjHandlingPolicy::QAObject}; + // NSigma + OutputObj<experimental::histhelpers::HistFolder> nsigma{experimental::histhelpers::HistFolder("nsigma"), OutputObjHandlingPolicy::QAObject}; + void init(o2::framework::InitContext&) + { + +#define makelogaxis(h) \ + { \ + const Int_t nbins = h->GetNbinsX(); \ + double binp[nbins + 1]; \ + double max = h->GetXaxis()->GetBinUpEdge(nbins); \ + double min = h->GetXaxis()->GetBinLowEdge(1); \ + double lmin = TMath::Log10(min); \ + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); \ + for (int i = 0; i < nbins; i++) { \ + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); \ + } \ + binp[nbins] = max + 1; \ + h->GetXaxis()->Set(nbins, binp); \ + } + + event->Add<vertexz>(new TH1F("hvertexz", ";Vtx_{z} (cm);Entries", 100, -20, 20)); + event->Add<signal>(new TH2F("htpcsignal", ";#it{p} (GeV/#it{c});TPC Signal", 1000, 0.001, 20, 1000, 0, 1000)); + makelogaxis(event->Get<TH2>(signal)); + // + expected->Add<El>(new TH2F("hexpectedEl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{e}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<Mu>(new TH2F("hexpectedMu", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{#mu}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<Pi>(new TH2F("hexpectedPi", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{#pi}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<Ka>(new TH2F("hexpectedKa", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{K}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<Pr>(new TH2F("hexpectedPr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{p}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<De>(new TH2F("hexpectedDe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{d}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<Tr>(new TH2F("hexpectedTr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{t}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<He>(new TH2F("hexpectedHe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{^{3}He}", 1000, 0.001, 20, 1000, 0, 1000)); + expected->Add<Al>(new TH2F("hexpectedAl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{#alpha}", 1000, 0.001, 20, 1000, 0, 1000)); + makelogaxis(expected->Get<TH2>(El)); + makelogaxis(expected->Get<TH2>(Mu)); + makelogaxis(expected->Get<TH2>(Pi)); + makelogaxis(expected->Get<TH2>(Ka)); + makelogaxis(expected->Get<TH2>(Pr)); + makelogaxis(expected->Get<TH2>(De)); + makelogaxis(expected->Get<TH2>(Tr)); + makelogaxis(expected->Get<TH2>(He)); + makelogaxis(expected->Get<TH2>(Al)); + // + expected_diff->Add<El>(new TH2F("hexpdiffEl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{e}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<Mu>(new TH2F("hexpdiffMu", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{#mu}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<Pi>(new TH2F("hexpdiffPi", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{#pi}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<Ka>(new TH2F("hexpdiffKa", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{K}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<Pr>(new TH2F("hexpdiffPr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{p}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<De>(new TH2F("hexpdiffDe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{d}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<Tr>(new TH2F("hexpdiffTr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{t}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<He>(new TH2F("hexpdiffHe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{^{3}He}", 1000, 0.001, 20, 1000, -500, 500)); + expected_diff->Add<Al>(new TH2F("hexpdiffAl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{#alpha}", 1000, 0.001, 20, 1000, -500, 500)); + makelogaxis(expected_diff->Get<TH2>(El)); + makelogaxis(expected_diff->Get<TH2>(Mu)); + makelogaxis(expected_diff->Get<TH2>(Pi)); + makelogaxis(expected_diff->Get<TH2>(Ka)); + makelogaxis(expected_diff->Get<TH2>(Pr)); + makelogaxis(expected_diff->Get<TH2>(De)); + makelogaxis(expected_diff->Get<TH2>(Tr)); + makelogaxis(expected_diff->Get<TH2>(He)); + makelogaxis(expected_diff->Get<TH2>(Al)); + // + nsigma->Add<El>(new TH2F("hnsigmaEl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(e)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Mu>(new TH2F("hnsigmaMu", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(#mu)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Pi>(new TH2F("hnsigmaPi", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(#pi)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Ka>(new TH2F("hnsigmaKa", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(K)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Pr>(new TH2F("hnsigmaPr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(p)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<De>(new TH2F("hnsigmaDe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(d)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Tr>(new TH2F("hnsigmaTr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(t)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<He>(new TH2F("hnsigmaHe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(^{3}He)", 1000, 0.001, 20, 200, -10, 10)); + nsigma->Add<Al>(new TH2F("hnsigmaAl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(#alpha)", 1000, 0.001, 20, 200, -10, 10)); + makelogaxis(nsigma->Get<TH2>(El)); + makelogaxis(nsigma->Get<TH2>(Mu)); + makelogaxis(nsigma->Get<TH2>(Pi)); + makelogaxis(nsigma->Get<TH2>(Ka)); + makelogaxis(nsigma->Get<TH2>(Pr)); + makelogaxis(nsigma->Get<TH2>(De)); + makelogaxis(nsigma->Get<TH2>(Tr)); + makelogaxis(nsigma->Get<TH2>(He)); + makelogaxis(nsigma->Get<TH2>(Al)); +#undef makelogaxis + } + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) + { + event->Fill<vertexz>(collision.posZ()); + for (auto i : tracks) { + // const float mom = i.p(); + const float mom = i.tpcInnerParam(); + event->Fill<signal>(mom, i.tpcSignal()); + // + expected->Fill<El>(mom, i.tpcExpSignalEl()); + expected->Fill<Mu>(mom, i.tpcExpSignalMu()); + expected->Fill<Pi>(mom, i.tpcExpSignalPi()); + expected->Fill<Ka>(mom, i.tpcExpSignalKa()); + expected->Fill<Pr>(mom, i.tpcExpSignalPr()); + expected->Fill<De>(mom, i.tpcExpSignalDe()); + expected->Fill<Tr>(mom, i.tpcExpSignalTr()); + expected->Fill<He>(mom, i.tpcExpSignalHe()); + expected->Fill<Al>(mom, i.tpcExpSignalAl()); + // + expected_diff->Fill<El>(mom, i.tpcSignal() - i.tpcExpSignalEl()); + expected_diff->Fill<Mu>(mom, i.tpcSignal() - i.tpcExpSignalMu()); + expected_diff->Fill<Pi>(mom, i.tpcSignal() - i.tpcExpSignalPi()); + expected_diff->Fill<Ka>(mom, i.tpcSignal() - i.tpcExpSignalKa()); + expected_diff->Fill<Pr>(mom, i.tpcSignal() - i.tpcExpSignalPr()); + expected_diff->Fill<De>(mom, i.tpcSignal() - i.tpcExpSignalDe()); + expected_diff->Fill<Tr>(mom, i.tpcSignal() - i.tpcExpSignalTr()); + expected_diff->Fill<He>(mom, i.tpcSignal() - i.tpcExpSignalHe()); + expected_diff->Fill<Al>(mom, i.tpcSignal() - i.tpcExpSignalAl()); + // + nsigma->Fill<El>(mom, i.tpcNSigmaEl()); + nsigma->Fill<Mu>(mom, i.tpcNSigmaMu()); + nsigma->Fill<Pi>(mom, i.tpcNSigmaPi()); + nsigma->Fill<Ka>(mom, i.tpcNSigmaKa()); + nsigma->Fill<Pr>(mom, i.tpcNSigmaPr()); + nsigma->Fill<De>(mom, i.tpcNSigmaDe()); + nsigma->Fill<Tr>(mom, i.tpcNSigmaTr()); + nsigma->Fill<He>(mom, i.tpcNSigmaHe()); + nsigma->Fill<Al>(mom, i.tpcNSigmaAl()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask<pidTPCTask>("pidTPC-task")}; + auto workflow = WorkflowSpec{adaptAnalysisTask<pidTPCTask>("pidTPC-task")}; + if (cfgc.options().get<int>("add-qa")) { + workflow.push_back(adaptAnalysisTask<pidTPCTaskQA>("pidTPCQA-task")); + } + return workflow; } From ab3462e6ed3031db3fc5db563c67b3a5633135b9 Mon Sep 17 00:00:00 2001 From: LucasNL <nunes.lopes@ufrgs.br> Date: Wed, 16 Sep 2020 12:31:52 -0300 Subject: [PATCH 0938/1751] [WIP]Updated Cov. Matriz and sigma_qpt --- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 139 +++++++++++++----- 1 file changed, 105 insertions(+), 34 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 8e6bcc21e64eb..5701d10535594 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -98,12 +98,13 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) auto& mftTrackingParam = MFTTrackingParam::Instance(); // initialize the starting track parameters and cluster + double sigmainvQPtsq; double chi2invqptquad; double invQPtSeed; auto nPoints = track.getNumberOfPoints(); auto k = TMath::Abs(o2::constants::math::B2C * mBZField); auto Hz = std::copysign(1, mBZField); - invQPtSeed = invQPtFromFCF(track, mBZField, chi2invqptquad); + invQPtSeed = invQPtFromFCF(track, mBZField, sigmainvQPtsq); if (mftTrackingParam.verbose) { std::cout << "\n ***************************** Start Fitting new track ***************************** \n"; @@ -169,32 +170,48 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; std::cout << "Track Model: " << model << std::endl; std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + std::cout << " Variances: sigma_x0 = " << TMath::Sqrt(sigmax0sq) << " sigma_y0 = " << TMath::Sqrt(sigmay0sq) << " sigma_q/pt = " << TMath::Sqrt(sigmainvQPtsq) << std::endl; } auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; + + double C1 = track.getInvQPt() * k * deltaR; + double D1 = TMath::Sqrt(C1 * C1 + 1); + double invD1 = 1. / D1; + double D2 = 1. / TMath::Sqrt(D1 + 1); + double E1 = deltaR * D2 * D2 * invD1; + double F1 = Hz * k * D2; + double G1 = deltaZ * k * D2 / D1; + double invDr2 = 1. / (deltaR * deltaR); + double J1 = G1 * invDr2 / (k*deltaR); + double L1 = C1 * C1 - 2 * D1 * (D1 + 1); + double inv2rt2 = 0.25 * TMath::Sqrt(2); + // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) SMatrix55 lastParamCov; - lastParamCov(0, 0) = sigmax0sq; // <X,X> - lastParamCov(0, 1) = 0; // <Y,X> - lastParamCov(0, 2) = sigmaboost * -sigmax0sq * y0 * invr0sq; // <PHI,X> - lastParamCov(0, 3) = sigmaboost * -z0 * sigmax0sq * x0 * invr0cu; // <TANL,X> - lastParamCov(0, 4) = sigmaboost * -x0 * sigmax0sq * invr0cu; // <INVQPT,X> + lastParamCov(0, 0) = sigmax0sq; // <X,X> + lastParamCov(0, 1) = 0; // <Y,X> + lastParamCov(0, 2) = sigmax0sq * invDr2 * (inv2rt2 * track.getInvQPt() * F1 * E1 * L1 * deltaX - deltaY); // <PHI,X> + lastParamCov(0, 3) = sigmax0sq * inv2rt2 * J1 * L1 * deltaX; // <TANL,X> + lastParamCov(0, 4) = 0; // <INVQPT,X> + + lastParamCov(1, 1) = sigmay0sq; // <Y,Y> + lastParamCov(1, 2) = sigmay0sq * invDr2 * (inv2rt2 * track.getInvQPt() * F1 * E1 * L1 * deltaY - deltaX); // <PHI,Y> + lastParamCov(1, 3) = sigmay0sq * inv2rt2 * J1 * L1 * deltaY; // <TANL,Y> + lastParamCov(1, 4) = 0; // <INVQPT,Y> + + lastParamCov(2, 2) = sigmainvQPtsq * 0.125 * E1 * E1 * F1 * F1 * L1 * L1; // <PHI,PHI> - lastParamCov(1, 1) = sigmay0sq; // <Y,Y> - lastParamCov(1, 2) = sigmaboost * sigmay0sq * x0 * invr0sq; // <PHI,Y> - lastParamCov(1, 3) = sigmaboost * -z0 * sigmay0sq * y0 * invr0cu; // <TANL,Y> - lastParamCov(1, 4) = sigmaboost * y0 * sigmay0sq * invr0cu; //1e-2; // <INVQPT,Y> + lastParamCov(2, 3) = sigmainvQPtsq * 0.125 * C1 * E1 * F1 * G1 * L1; // <TANL,PHI> - lastParamCov(2, 2) = sigmaboost * (sigmax0sq * y0 * y0 + sigmay0sq * x0 * x0) * invr0sq * invr0sq; // <PHI,PHI> - lastParamCov(2, 3) = sigmaboost * z0 * x0 * y0 * (sigmax0sq - sigmay0sq) * invr0sq * invr0cu; // <TANL,PHI> - lastParamCov(2, 4) = sigmaboost * y0 * x0 * invr0cu * invr0sq * (sigmax0sq - sigmay0sq); // <INVQPT,PHI> + lastParamCov(2, 4) = sigmainvQPtsq * inv2rt2 * E1 * F1 * L1; // <INVQPT,PHI> - lastParamCov(3, 3) = sigmaboost * z0 * z0 * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0) * invr0cu * invr0cu + sigmaDeltaZsq * invr0sq; // <TANL,TANL> - lastParamCov(3, 4) = sigmaboost * z0 * invr0cu * invr0cu * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0); // <INVQPT,TANL> + lastParamCov(3, 3) = sigmainvQPtsq * 0.125 * C1 * C1 * G1 * G1; // <TANL,TANL> - lastParamCov(4, 4) = sigmaboost * sigmaboost * (sigmax0sq * x0 * x0 + sigmay0sq * y0 * y0) * invr0cu * invr0cu; // <INVQPT,INVQPT> + lastParamCov(3, 4) = sigmainvQPtsq * inv2rt2 * C1 * G1; // <INVQPT,TANL> + lastParamCov(4, 4) = sigmainvQPtsq; // <INVQPT,INVQPT> track.setCovariances(lastParamCov); track.setTrackChi2(0.); @@ -296,7 +313,7 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) } //_________________________________________________________________________________________________ -Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) +Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmainvqptsq) { const std::array<Float_t, constants::mft::LayersNumber>& xPositions = track.getXCoordinates(); @@ -315,7 +332,14 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) Double_t* uVal = new Double_t[nPoints - 1]; Double_t* vVal = new Double_t[nPoints - 1]; Double_t* vErr = new Double_t[nPoints - 1]; - Double_t a, ae, b, be, x2, y2, invx2y2, rx, ry, r; + Double_t* fweight = new Double_t[nPoints - 1]; + Double_t* Rn = new Double_t[nPoints - 1]; + Double_t* Pn = new Double_t[nPoints - 1]; + Double_t A, Aerr, B, Berr, x2, y2, invx2y2, a, b, r, sigmaRsq, u2, sigma; + Double_t F0,F1,F2,F3,F4, SumSRn, SumSPn, SumRn, SumUPn, SumRP; + + SumSRn = SumSPn = SumRn = SumUPn = SumRP = 0.0; + F0 = F1 = F2 = F3 = F4 = 0.0; for (auto np = 0; np < nPoints; np++) { xErr[np] = SigmasX2[np]; @@ -331,27 +355,55 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) } zVal[np] = zPositions[np]; } - for (int i = 0; i < (nPoints - 1); i++) { + for (int i = 0; i < (nPoints - 1); i++) { x2 = xVal[i + 1] * xVal[i + 1]; y2 = yVal[i + 1] * yVal[i + 1]; invx2y2 = 1. / (x2 + y2); uVal[i] = xVal[i + 1] * invx2y2; vVal[i] = yVal[i + 1] * invx2y2; vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2) * (x2 - y2)) * invx2y2 * invx2y2; + u2 = uVal[i] * uVal[i]; + fweight[i] = 1;//. / vErr[i]; + F0 += fweight[i]; // f = fn(Hansroul) que é o peso de cada ponto Vn...inverso da incerteza? + F1 += fweight[i] * uVal[i]; + F2 += fweight[i] * u2; + F3 += fweight[i] * uVal[i] * u2; + F4 += fweight[i] * u2 * u2; } + double Rn_det1 = F2 * F4 - F3 * F3; + double Rn_det2 = F1 * F4 - F2 * F3; + double Rn_det3 = F1 * F3 - F2 * F2; + double Pn_det1 = Rn_det2; + double Pn_det2 = F0 * F4 - F2 * F2; + double Pn_det3 = F0 * F3 - F1 * F2; + + for (int j = 0; j < (nPoints - 1); j++) { + Rn[j] = fweight[j] * (Rn_det1 - uVal[j]*Rn_det2 + uVal[j]*uVal[j]*Rn_det3); + SumSRn += Rn[j] * Rn[j] * vErr[j]; + SumRn += Rn[j]; + + Pn[j] = fweight[j] * (-Pn_det1 + uVal[j]*Pn_det2 - uVal[j]*uVal[j]*Pn_det3); + SumSPn += Pn[j] * Pn[j] * vErr[j]; + SumUPn += uVal[j] * Pn[j]; + + SumRP += Rn[j] * Pn[j] * vErr[j] * vErr[j]; //falta um vErr? + } + Double_t invqpt_fcf; Int_t qfcf; - chi2 = 0.; - if (LinearRegression((nPoints - 1), uVal, vVal, vErr, a, ae, b, be)) { +// chi2 = 0.; + if (LinearRegression((nPoints - 1), uVal, vVal, vErr, B, Berr, A, Aerr)) { // v = a * u + b // circle passing through (0,0): // (x - rx)^2 + (y - ry)^2 = r^2 // ---> a = - rx / ry; // ---> b = 1 / (2 * ry) - ry = 1. / (2. * b); - rx = -a * ry; - r = std::sqrt(rx * rx + ry * ry); + b = 1. / (2. * A); + a = -B * b; + r = std::sqrt(a * a + b * b); + double_t invR = 1./r; + // pt ---> Double_t invpt = 1. / (o2::constants::math::B2C * bFieldZ * r); @@ -363,8 +415,8 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) Double_t slope = TMath::ATan2(y, x); Double_t cosSlope = TMath::Cos(slope); Double_t sinSlope = TMath::Sin(slope); - Double_t rxRot = rx * cosSlope + ry * sinSlope; - Double_t ryRot = rx * sinSlope - ry * cosSlope; + Double_t rxRot = a * cosSlope + b * sinSlope; + Double_t ryRot = a * sinSlope - b * cosSlope; qfcf = (ryRot > 0.) ? -1 : +1; Double_t alpha = 2.0 * std::abs(TMath::ATan2(rxRot, ryRot)); @@ -378,6 +430,24 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) pz = std::sqrt(p * p - pt * pt); invqpt_fcf = qfcf * invpt; + + //error calculations: + double invA2 = 1. / (A * A); + + double sigmaAsq = SumSRn / (SumRn * SumRn); + double sigmaBsq = SumSPn / (SumUPn * SumUPn); + double sigmaAB = SumRP / (SumRn * SumUPn); + + double sigmaasq_FCF = TMath::Abs (0.25 * invA2 * invA2 * (B * B * sigmaAsq + A * A * sigmaBsq - A * B * sigmaAB)); + double sigmabsq_FCF = TMath::Abs (0.25 * invA2 * invA2 * sigmaAsq); + double sigma2R = invR * invR * (b * b * sigmaasq_FCF + a * a * sigmabsq_FCF + 2 * a * b * TMath::Sqrt(sigmaasq_FCF) * TMath::Sqrt(sigmabsq_FCF)); + + sigmainvqptsq = sigma2R * invpt * invpt * invR * invR; + + std::cout << " Sigma^2_A " << sigmaAsq <<" Sigma^2_B " << sigmaBsq <<" Sigma_AB " << sigmaAB << std::endl; + std::cout << " Sigma^2_a " << sigmaasq_FCF <<" Sigma^2_b " << sigmabsq_FCF <<" Sigma^2_R " << sigma2R << std::endl; + + } else { // the linear regression failed... LOG(WARN) << "LinearRegression failed!"; invqpt_fcf = 1. / 100.; @@ -387,9 +457,9 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& chi2) } ////_________________________________________________________________________________________________ -Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yErr, Double_t& a, Double_t& ae, Double_t& b, Double_t& be) +Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yErr, Double_t& B, Double_t& Berr, Double_t& A, Double_t& Aerr) { - // linear regression y = a * x + b + // linear regression y = B * x + A Double_t S1, SXY, SX, SY, SXX, SsXY, SsXX, SsYY, Xm, Ym, s, delta, difx; Double_t invYErr2; @@ -416,8 +486,8 @@ Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yE if (delta == 0.) { return kFALSE; } - a = (SXY * S1 - SX * SY) / delta; - b = (SY * SXX - SX * SXY) / delta; + B = (SXY * S1 - SX * SY) / delta; + A = (SY * SXX - SX * SXY) / delta; Ym /= (Double_t)nVal; Xm /= (Double_t)nVal; @@ -427,14 +497,15 @@ Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yE Double_t eps = 1.E-24; if ((nVal > 2) && (TMath::Abs(difx) > eps) && ((SsYY - (SsXY * SsXY) / SsXX) > 0.)) { s = TMath::Sqrt((SsYY - (SsXY * SsXY) / SsXX) / (nVal - 2)); - be = s * TMath::Sqrt(1. / (Double_t)nVal + (Xm * Xm) / SsXX); - ae = s / TMath::Sqrt(SsXX); + Aerr = s * TMath::Sqrt(1. / (Double_t)nVal + (Xm * Xm) / SsXX); + Berr = s / TMath::Sqrt(SsXX); } else { - be = 0.; - ae = 0.; + Aerr = 0.; + Berr = 0.; } return kTRUE; } + } // namespace mft } // namespace o2 From 46669053eab24b45fcdf1016e6f1adc106454987 Mon Sep 17 00:00:00 2001 From: LucasNL <nunes.lopes@ufrgs.br> Date: Fri, 18 Sep 2020 18:25:56 -0300 Subject: [PATCH 0939/1751] FCF: Fixed sums --- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 5701d10535594..07dc146deea33 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -132,7 +132,7 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) double deltaR = TMath::Sqrt(deltaX * deltaX + deltaY * deltaY); double tanl = 0.5 * TMath::Sqrt(2) * (deltaZ / deltaR) * TMath::Sqrt(TMath::Sqrt((invQPtSeed * deltaR * k) * (invQPtSeed * deltaR * k) + 1) + 1); - double phi0 = TMath::ATan2(y0, x0) + 0.5 * Hz * invQPtSeed * deltaZ * k / tanl; + double phi0 = TMath::ATan2(deltaY, deltaX) - 0.5 * Hz * invQPtSeed * deltaZ * k / tanl; double r0sq = x0 * x0 + y0 * y0; double r0cu = r0sq * TMath::Sqrt(r0sq); double invr0sq = 1.0 / r0sq; @@ -187,27 +187,34 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) double J1 = G1 * invDr2 / (k*deltaR); double L1 = C1 * C1 - 2 * D1 * (D1 + 1); double inv2rt2 = 0.25 * TMath::Sqrt(2); + double Mx = invDr2 * (inv2rt2 * track.getInvQPt() * E1 * F1 * L1 * deltaX - deltaY); + double My = invDr2 * (inv2rt2 * track.getInvQPt() * E1 * F1 * L1 * deltaY + deltaX); + + double sigmax1sq = track.getSigmasX2()[0]; + double sigmay1sq = track.getSigmasY2()[0]; + double sigmaDeltaX = sigmax0sq + sigmax1sq; + double sigmaDeltaY = sigmay0sq + sigmay1sq; // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) SMatrix55 lastParamCov; lastParamCov(0, 0) = sigmax0sq; // <X,X> lastParamCov(0, 1) = 0; // <Y,X> - lastParamCov(0, 2) = sigmax0sq * invDr2 * (inv2rt2 * track.getInvQPt() * F1 * E1 * L1 * deltaX - deltaY); // <PHI,X> + lastParamCov(0, 2) = sigmax0sq * Mx; // <PHI,X> lastParamCov(0, 3) = sigmax0sq * inv2rt2 * J1 * L1 * deltaX; // <TANL,X> lastParamCov(0, 4) = 0; // <INVQPT,X> lastParamCov(1, 1) = sigmay0sq; // <Y,Y> - lastParamCov(1, 2) = sigmay0sq * invDr2 * (inv2rt2 * track.getInvQPt() * F1 * E1 * L1 * deltaY - deltaX); // <PHI,Y> + lastParamCov(1, 2) = sigmay0sq * My; // <PHI,Y> lastParamCov(1, 3) = sigmay0sq * inv2rt2 * J1 * L1 * deltaY; // <TANL,Y> lastParamCov(1, 4) = 0; // <INVQPT,Y> - lastParamCov(2, 2) = sigmainvQPtsq * 0.125 * E1 * E1 * F1 * F1 * L1 * L1; // <PHI,PHI> + lastParamCov(2, 2) = sigmainvQPtsq * 0.125 * E1 * E1 * F1 * F1 * L1 * L1 + sigmaDeltaX * Mx * Mx + sigmaDeltaY * My * My; // <PHI,PHI> - lastParamCov(2, 3) = sigmainvQPtsq * 0.125 * C1 * E1 * F1 * G1 * L1; // <TANL,PHI> + lastParamCov(2, 3) = sigmainvQPtsq * 0.125 * C1 * E1 * F1 * G1 * L1 + inv2rt2 * J1 * L1 * (sigmaDeltaX * Mx + sigmaDeltaY * My); // <TANL,PHI> lastParamCov(2, 4) = sigmainvQPtsq * inv2rt2 * E1 * F1 * L1; // <INVQPT,PHI> - lastParamCov(3, 3) = sigmainvQPtsq * 0.125 * C1 * C1 * G1 * G1; // <TANL,TANL> + lastParamCov(3, 3) = sigmainvQPtsq * 0.125 * C1 * C1 * G1 * G1 + 0.125 * J1 * J1 * L1 * L1 * (sigmaDeltaX * deltaX * deltaX + sigmaDeltaY * deltaY * deltaY); // <TANL,TANL> lastParamCov(3, 4) = sigmainvQPtsq * inv2rt2 * C1 * G1; // <INVQPT,TANL> @@ -363,7 +370,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai vVal[i] = yVal[i + 1] * invx2y2; vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2) * (x2 - y2)) * invx2y2 * invx2y2; u2 = uVal[i] * uVal[i]; - fweight[i] = 1;//. / vErr[i]; + fweight[i] = 1. / vErr[i]; F0 += fweight[i]; // f = fn(Hansroul) que é o peso de cada ponto Vn...inverso da incerteza? F1 += fweight[i] * uVal[i]; F2 += fweight[i] * u2; @@ -380,14 +387,14 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai for (int j = 0; j < (nPoints - 1); j++) { Rn[j] = fweight[j] * (Rn_det1 - uVal[j]*Rn_det2 + uVal[j]*uVal[j]*Rn_det3); - SumSRn += Rn[j] * Rn[j] * vErr[j]; + SumSRn += Rn[j] * Rn[j] * vErr[j] * vErr[j]; SumRn += Rn[j]; Pn[j] = fweight[j] * (-Pn_det1 + uVal[j]*Pn_det2 - uVal[j]*uVal[j]*Pn_det3); - SumSPn += Pn[j] * Pn[j] * vErr[j]; + SumSPn += Pn[j] * Pn[j] * vErr[j] * vErr[j]; SumUPn += uVal[j] * Pn[j]; - SumRP += Rn[j] * Pn[j] * vErr[j] * vErr[j]; //falta um vErr? + SumRP += Rn[j] * Pn[j] * vErr[j] * vErr[j] * vErr[j]; } Double_t invqpt_fcf; From e2089a2f580f2ca1d8293c3658c27ff770d2d16c Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Thu, 1 Oct 2020 13:42:28 +0000 Subject: [PATCH 0940/1751] Refactored MFT track seed covariances matrix for low Pt Tracks --- DataFormats/Reconstruction/src/TrackFwd.cxx | 2 +- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 222 +++++++++--------- 2 files changed, 109 insertions(+), 115 deletions(-) diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 9741168a72863..29949f8dd6446 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -325,7 +325,7 @@ void TrackParCovFwd::addMCSEffect(double dZ, double x_over_X0) auto pathLengthOverX0 = x_over_X0 * csclambda; // // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory - auto sigmathetasq = 0.0136 * getInverseMomentum() * (1 + 0.038 * TMath::Log(pathLengthOverX0)); + auto sigmathetasq = 0.0136 * getInverseMomentum(); sigmathetasq *= sigmathetasq * pathLengthOverX0; // Get covariance matrix diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 07dc146deea33..4c9bf4853a6bb 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -98,127 +98,123 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) auto& mftTrackingParam = MFTTrackingParam::Instance(); // initialize the starting track parameters and cluster - double sigmainvQPtsq; + double sigmainvQPtsq; double chi2invqptquad; - double invQPtSeed; + auto invQPt0 = invQPtFromFCF(track, mBZField, sigmainvQPtsq); auto nPoints = track.getNumberOfPoints(); auto k = TMath::Abs(o2::constants::math::B2C * mBZField); auto Hz = std::copysign(1, mBZField); - invQPtSeed = invQPtFromFCF(track, mBZField, sigmainvQPtsq); if (mftTrackingParam.verbose) { std::cout << "\n ***************************** Start Fitting new track ***************************** \n"; std::cout << "N Clusters = " << nPoints << std::endl; } - track.setInvQPtSeed(invQPtSeed); + track.setInvQPtSeed(invQPt0); track.setChi2QPtSeed(chi2invqptquad); - track.setInvQPt(invQPtSeed); + track.setInvQPt(invQPt0); /// Compute the initial track parameters to seed the Kalman filter - int start; // Start fitting by the first or the last cluster - if (outward) - start = 0; - else - start = nPoints - 1; - - double x0 = track.getXCoordinates()[start]; - double y0 = track.getYCoordinates()[start]; - double z0 = track.getZCoordinates()[start]; - double deltaX = track.getXCoordinates()[nPoints - 1] - track.getXCoordinates()[0]; - double deltaY = track.getYCoordinates()[nPoints - 1] - track.getYCoordinates()[0]; - double deltaZ = track.getZCoordinates()[nPoints - 1] - track.getZCoordinates()[0]; - double deltaR = TMath::Sqrt(deltaX * deltaX + deltaY * deltaY); - double tanl = 0.5 * TMath::Sqrt(2) * (deltaZ / deltaR) * - TMath::Sqrt(TMath::Sqrt((invQPtSeed * deltaR * k) * (invQPtSeed * deltaR * k) + 1) + 1); - double phi0 = TMath::ATan2(deltaY, deltaX) - 0.5 * Hz * invQPtSeed * deltaZ * k / tanl; - double r0sq = x0 * x0 + y0 * y0; - double r0cu = r0sq * TMath::Sqrt(r0sq); - double invr0sq = 1.0 / r0sq; - double invr0cu = 1.0 / r0cu; - double sigmax0sq = track.getSigmasX2()[start]; - double sigmay0sq = track.getSigmasY2()[start]; - double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond - double sigmaboost = mftTrackingParam.sigmaboost; // Boost q/pt seed covariances - double seedH_k = mftTrackingParam.seedH_k; // SeedH constant + int first_cls, last_cls; + if (outward) { // MCH matching + first_cls = 0; + last_cls = nPoints - 1; + } else { // Vertexing + first_cls = nPoints - 1; + last_cls = 0; + } + + auto x0 = track.getXCoordinates()[first_cls]; + auto y0 = track.getYCoordinates()[first_cls]; + auto z0 = track.getZCoordinates()[first_cls]; + + auto deltaX = track.getXCoordinates()[nPoints - 1] - track.getXCoordinates()[0]; + auto deltaY = track.getYCoordinates()[nPoints - 1] - track.getYCoordinates()[0]; + auto deltaZ = track.getZCoordinates()[nPoints - 1] - track.getZCoordinates()[0]; + auto deltaR = TMath::Sqrt(deltaX * deltaX + deltaY * deltaY); + auto tanl0 = 0.5 * TMath::Sqrt2() * (deltaZ / deltaR) * + TMath::Sqrt(TMath::Sqrt((invQPt0 * deltaR * k) * (invQPt0 * deltaR * k) + 1) + 1); + auto phi0 = TMath::ATan2(deltaY, deltaX) - 0.5 * Hz * invQPt0 * deltaZ * k / tanl0; + auto sigmax0sq = track.getSigmasX2()[first_cls]; + auto sigmay0sq = track.getSigmasY2()[first_cls]; + auto sigmax1sq = track.getSigmasX2()[last_cls]; + auto sigmay1sq = track.getSigmasY2()[last_cls]; + auto sigmaDeltaXsq = sigmax0sq + sigmax1sq; + auto sigmaDeltaYsq = sigmay0sq + sigmay1sq; track.setX(x0); track.setY(y0); track.setZ(z0); track.setPhi(phi0); - track.setTanl(tanl); - - // Configure the track seed - switch (mftTrackingParam.seed) { - case AB: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed A / B; sigmaboost = " << sigmaboost << (track.isCA() ? " CA Track " : " LTF Track") << std::endl; - track.setInvQPt(1.0 / TMath::Sqrt(x0 * x0 + y0 * y0)); // Seeds A & B - break; - case DH: - if (mftTrackingParam.verbose) - std::cout << " Init track with Seed H; (k = " << seedH_k << "); sigmaboost = " << sigmaboost << (track.isCA() ? " CA Track " : " LTF Track") << std::endl; - track.setInvQPt(track.getInvQPt() / seedH_k); // SeedH - break; - default: - LOG(ERROR) << "Invalid MFT tracking seed"; - return false; - break; - } + track.setTanl(tanl0); + if (mftTrackingParam.verbose) { + std::cout << " Init " << (track.isCA() ? "CA Track " : "LTF Track") << std::endl; auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; std::cout << "Track Model: " << model << std::endl; - std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; - std::cout << " Variances: sigma_x0 = " << TMath::Sqrt(sigmax0sq) << " sigma_y0 = " << TMath::Sqrt(sigmay0sq) << " sigma_q/pt = " << TMath::Sqrt(sigmainvQPtsq) << std::endl; + std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << tanl0 << " Phi = " << phi0 << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + std::cout << " Variances: sigma2_x0 = " << TMath::Sqrt(sigmax0sq) << " sigma2_y0 = " << TMath::Sqrt(sigmay0sq) << " sigma2_q/pt = " << TMath::Sqrt(sigmainvQPtsq) << std::endl; } - auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear"; - - - double C1 = track.getInvQPt() * k * deltaR; - double D1 = TMath::Sqrt(C1 * C1 + 1); - double invD1 = 1. / D1; - double D2 = 1. / TMath::Sqrt(D1 + 1); - double E1 = deltaR * D2 * D2 * invD1; - double F1 = Hz * k * D2; - double G1 = deltaZ * k * D2 / D1; - double invDr2 = 1. / (deltaR * deltaR); - double J1 = G1 * invDr2 / (k*deltaR); - double L1 = C1 * C1 - 2 * D1 * (D1 + 1); - double inv2rt2 = 0.25 * TMath::Sqrt(2); - double Mx = invDr2 * (inv2rt2 * track.getInvQPt() * E1 * F1 * L1 * deltaX - deltaY); - double My = invDr2 * (inv2rt2 * track.getInvQPt() * E1 * F1 * L1 * deltaY + deltaX); - - double sigmax1sq = track.getSigmasX2()[0]; - double sigmay1sq = track.getSigmasY2()[0]; - double sigmaDeltaX = sigmax0sq + sigmax1sq; - double sigmaDeltaY = sigmay0sq + sigmay1sq; - - // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) - SMatrix55 lastParamCov; - lastParamCov(0, 0) = sigmax0sq; // <X,X> - lastParamCov(0, 1) = 0; // <Y,X> - lastParamCov(0, 2) = sigmax0sq * Mx; // <PHI,X> - lastParamCov(0, 3) = sigmax0sq * inv2rt2 * J1 * L1 * deltaX; // <TANL,X> - lastParamCov(0, 4) = 0; // <INVQPT,X> - - lastParamCov(1, 1) = sigmay0sq; // <Y,Y> - lastParamCov(1, 2) = sigmay0sq * My; // <PHI,Y> - lastParamCov(1, 3) = sigmay0sq * inv2rt2 * J1 * L1 * deltaY; // <TANL,Y> - lastParamCov(1, 4) = 0; // <INVQPT,Y> + auto deltaR2 = deltaR * deltaR; + auto deltaR3 = deltaR2 * deltaR; + auto deltaR4 = deltaR2 * deltaR2; + auto k2 = k * k; + auto A = TMath::Sqrt(track.getInvQPt() * track.getInvQPt() * deltaR2 * k2 + 1); + auto A2 = A * A; + auto B = A + 1.0; + auto B2 = B * B; + auto B3 = B * B * B; + auto B12 = TMath::Sqrt(B); + auto B32 = B * B12; + auto B52 = B * B32; + auto C = invQPt0 * k; + auto C2 = C * C; + auto C3 = C * C2; + auto D = 1.0 / (A2 * B2 * B2 * deltaR4); + auto E = D * deltaZ / (B * deltaR); + auto F = deltaR * deltaX * C3 * Hz / (A * B32); + auto G = 0.5 * TMath::Sqrt2() * A * B32 * C * Hz * deltaR; + auto Gx = G * deltaX; + auto Gy = G * deltaY; + auto H = -0.25 * TMath::Sqrt2() * B12 * C3 * Hz * deltaR3; + auto Hx = H * deltaX; + auto Hy = H * deltaY; + auto I = A * B2; + auto Ix = I * deltaX; + auto Iy = I * deltaY; + auto J = 2 * B * deltaR3 * deltaR3 * k2; + auto K = 0.5 * A * B - 0.25 * C2 * deltaR2; + auto L0 = Gx + Hx + Iy; + auto M0 = -Gy - Hy + Ix; + auto N = -0.5 * B3 * C * Hz * deltaR3 * deltaR4 * k2; + auto O = 0.125 * C2 * deltaR4 * deltaR4 * k2; + auto P = -K * k * Hz * deltaR / A; + auto Q = deltaZ * deltaZ / (A2 * B * deltaR3 * deltaR3); + auto R = 0.25 * C * deltaZ * TMath::Sqrt2() * deltaR * k / (A * B12); - lastParamCov(2, 2) = sigmainvQPtsq * 0.125 * E1 * E1 * F1 * F1 * L1 * L1 + sigmaDeltaX * Mx * Mx + sigmaDeltaY * My * My; // <PHI,PHI> - - lastParamCov(2, 3) = sigmainvQPtsq * 0.125 * C1 * E1 * F1 * G1 * L1 + inv2rt2 * J1 * L1 * (sigmaDeltaX * Mx + sigmaDeltaY * My); // <TANL,PHI> + SMatrix55 lastParamCov; + lastParamCov(0, 0) = sigmax0sq; // <X,X> + lastParamCov(0, 1) = 0; // <Y,X> + lastParamCov(0, 2) = 0; // <PHI,X> + lastParamCov(0, 3) = 0; // <TANL,X> + lastParamCov(0, 4) = 0; // <INVQPT,X> - lastParamCov(2, 4) = sigmainvQPtsq * inv2rt2 * E1 * F1 * L1; // <INVQPT,PHI> + lastParamCov(1, 1) = sigmay0sq; // <Y,Y> + lastParamCov(1, 2) = 0; // <PHI,Y> + lastParamCov(1, 3) = 0; // <TANL,Y> + lastParamCov(1, 4) = 0; // <INVQPT,Y> - lastParamCov(3, 3) = sigmainvQPtsq * 0.125 * C1 * C1 * G1 * G1 + 0.125 * J1 * J1 * L1 * L1 * (sigmaDeltaX * deltaX * deltaX + sigmaDeltaY * deltaY * deltaY); // <TANL,TANL> + lastParamCov(2, 2) = D * (J * K * K * sigmainvQPtsq + L0 * L0 * sigmaDeltaXsq + M0 * M0 * sigmaDeltaYsq); // <PHI,PHI> + lastParamCov(2, 3) = E * K * (TMath::Sqrt2() * B52 * (L0 * deltaX * sigmaDeltaXsq - deltaY * sigmaDeltaYsq * M0) + N * sigmainvQPtsq); // <TANL,PHI> + lastParamCov(2, 4) = P * sigmainvQPtsq * TMath::Sqrt2() / B32; // <INVQPT,PHI> - lastParamCov(3, 4) = sigmainvQPtsq * inv2rt2 * C1 * G1; // <INVQPT,TANL> + lastParamCov(3, 3) = Q * (2 * K * K * (deltaX * deltaX * sigmaDeltaXsq + deltaY * deltaY * sigmaDeltaYsq) + O * sigmainvQPtsq); // <TANL,TANL> + lastParamCov(3, 4) = R * sigmainvQPtsq; // <INVQPT,TANL> lastParamCov(4, 4) = sigmainvQPtsq; // <INVQPT,INVQPT> + track.setCovariances(lastParamCov); track.setTrackChi2(0.); @@ -252,7 +248,7 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) using o2::mft::constants::LayerZPosition; int startingLayerID, newLayerID; - double dZ = clz - track.getZ(); + auto dZ = clz - track.getZ(); //LayerID of each cluster from ZPosition // TODO: Use ChipMapping for (auto layer = 10; layer--;) if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3) @@ -267,7 +263,7 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) else NDisksMS = (startingLayerID % 2 == 0) ? (newLayerID - startingLayerID + 1) / 2 : (newLayerID - startingLayerID) / 2; - double MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0; + auto MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0; if (mftTrackingParam.verbose) { std::cout << "startingLayerID = " << startingLayerID << " ; " << "newLayerID = " << newLayerID << " ; "; @@ -343,9 +339,9 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai Double_t* Rn = new Double_t[nPoints - 1]; Double_t* Pn = new Double_t[nPoints - 1]; Double_t A, Aerr, B, Berr, x2, y2, invx2y2, a, b, r, sigmaRsq, u2, sigma; - Double_t F0,F1,F2,F3,F4, SumSRn, SumSPn, SumRn, SumUPn, SumRP; + Double_t F0, F1, F2, F3, F4, SumSRn, SumSPn, SumRn, SumUPn, SumRP; - SumSRn = SumSPn = SumRn = SumUPn = SumRP = 0.0; + SumSRn = SumSPn = SumRn = SumUPn = SumRP = 0.0; F0 = F1 = F2 = F3 = F4 = 0.0; for (auto np = 0; np < nPoints; np++) { @@ -362,7 +358,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai } zVal[np] = zPositions[np]; } - for (int i = 0; i < (nPoints - 1); i++) { + for (int i = 0; i < (nPoints - 1); i++) { x2 = xVal[i + 1] * xVal[i + 1]; y2 = yVal[i + 1] * yVal[i + 1]; invx2y2 = 1. / (x2 + y2); @@ -370,46 +366,46 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai vVal[i] = yVal[i + 1] * invx2y2; vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2) * (x2 - y2)) * invx2y2 * invx2y2; u2 = uVal[i] * uVal[i]; - fweight[i] = 1. / vErr[i]; - F0 += fweight[i]; // f = fn(Hansroul) que é o peso de cada ponto Vn...inverso da incerteza? + fweight[i] = 1. / vErr[i]; + F0 += fweight[i]; // f = fn(Hansroul) que é o peso de cada ponto Vn...inverso da incerteza? F1 += fweight[i] * uVal[i]; F2 += fweight[i] * u2; F3 += fweight[i] * uVal[i] * u2; F4 += fweight[i] * u2 * u2; } - double Rn_det1 = F2 * F4 - F3 * F3; + double Rn_det1 = F2 * F4 - F3 * F3; double Rn_det2 = F1 * F4 - F2 * F3; double Rn_det3 = F1 * F3 - F2 * F2; double Pn_det1 = Rn_det2; double Pn_det2 = F0 * F4 - F2 * F2; double Pn_det3 = F0 * F3 - F1 * F2; - for (int j = 0; j < (nPoints - 1); j++) { - Rn[j] = fweight[j] * (Rn_det1 - uVal[j]*Rn_det2 + uVal[j]*uVal[j]*Rn_det3); + for (int j = 0; j < (nPoints - 1); j++) { + Rn[j] = fweight[j] * (Rn_det1 - uVal[j] * Rn_det2 + uVal[j] * uVal[j] * Rn_det3); SumSRn += Rn[j] * Rn[j] * vErr[j] * vErr[j]; SumRn += Rn[j]; - Pn[j] = fweight[j] * (-Pn_det1 + uVal[j]*Pn_det2 - uVal[j]*uVal[j]*Pn_det3); + Pn[j] = fweight[j] * (-Pn_det1 + uVal[j] * Pn_det2 - uVal[j] * uVal[j] * Pn_det3); SumSPn += Pn[j] * Pn[j] * vErr[j] * vErr[j]; SumUPn += uVal[j] * Pn[j]; - + SumRP += Rn[j] * Pn[j] * vErr[j] * vErr[j] * vErr[j]; } - + Double_t invqpt_fcf; Int_t qfcf; -// chi2 = 0.; + // chi2 = 0.; if (LinearRegression((nPoints - 1), uVal, vVal, vErr, B, Berr, A, Aerr)) { // v = a * u + b // circle passing through (0,0): // (x - rx)^2 + (y - ry)^2 = r^2 // ---> a = - rx / ry; // ---> b = 1 / (2 * ry) - b = 1. / (2. * A); + b = 1. / (2. * A); a = -B * b; r = std::sqrt(a * a + b * b); - double_t invR = 1./r; + double_t invR = 1. / r; // pt ---> Double_t invpt = 1. / (o2::constants::math::B2C * bFieldZ * r); @@ -445,15 +441,14 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai double sigmaBsq = SumSPn / (SumUPn * SumUPn); double sigmaAB = SumRP / (SumRn * SumUPn); - double sigmaasq_FCF = TMath::Abs (0.25 * invA2 * invA2 * (B * B * sigmaAsq + A * A * sigmaBsq - A * B * sigmaAB)); - double sigmabsq_FCF = TMath::Abs (0.25 * invA2 * invA2 * sigmaAsq); + double sigmaasq_FCF = TMath::Abs(0.25 * invA2 * invA2 * (B * B * sigmaAsq + A * A * sigmaBsq - A * B * sigmaAB)); + double sigmabsq_FCF = TMath::Abs(0.25 * invA2 * invA2 * sigmaAsq); double sigma2R = invR * invR * (b * b * sigmaasq_FCF + a * a * sigmabsq_FCF + 2 * a * b * TMath::Sqrt(sigmaasq_FCF) * TMath::Sqrt(sigmabsq_FCF)); - sigmainvqptsq = sigma2R * invpt * invpt * invR * invR; + sigmainvqptsq = sigma2R * invpt * invpt * invR * invR; - std::cout << " Sigma^2_A " << sigmaAsq <<" Sigma^2_B " << sigmaBsq <<" Sigma_AB " << sigmaAB << std::endl; - std::cout << " Sigma^2_a " << sigmaasq_FCF <<" Sigma^2_b " << sigmabsq_FCF <<" Sigma^2_R " << sigma2R << std::endl; - + std::cout << " Sigma^2_A " << sigmaAsq << " Sigma^2_B " << sigmaBsq << " Sigma_AB " << sigmaAB << std::endl; + std::cout << " Sigma^2_a " << sigmaasq_FCF << " Sigma^2_b " << sigmabsq_FCF << " Sigma^2_R " << sigma2R << std::endl; } else { // the linear regression failed... LOG(WARN) << "LinearRegression failed!"; @@ -513,6 +508,5 @@ Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yE return kTRUE; } - } // namespace mft } // namespace o2 From 5fd4c480e2e334f65348327c044caf1994558875 Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Thu, 1 Oct 2020 13:34:22 -0300 Subject: [PATCH 0941/1751] Remove obsolete MFT tracking options --- .../tracking/include/MFTTracking/MFTTrackingParam.h | 10 +--------- Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx | 13 +++++-------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h index 6735b02ca1765..c28807bdc959b 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h @@ -21,11 +21,6 @@ namespace o2 namespace mft { -enum MFTTrackingSeed { - AB, // - DH -}; - enum MFTTrackModel { Helix, Quadratic, @@ -36,11 +31,8 @@ enum MFTTrackModel { // ** Parameters for MFT tracking configuration // ** struct MFTTrackingParam : public o2::conf::ConfigurableParamHelper<MFTTrackingParam> { - Int_t seed = MFTTrackingSeed::DH; Int_t trackmodel = MFTTrackModel::Helix; - double sigmaboost = 1e3; - double seedH_k = 1.0; - double MFTRadLenghts = 0.041; // MFT average material budget within acceptance + double MFTRadLength = 1.0; // MFT average material budget within acceptance. Should be 0.041 bool verbose = false; O2ParamDef(MFTTrackingParam, "MFTTracking"); diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index 4c9bf4853a6bb..c8775497b051d 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -206,12 +206,12 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward) lastParamCov(1, 3) = 0; // <TANL,Y> lastParamCov(1, 4) = 0; // <INVQPT,Y> - lastParamCov(2, 2) = D * (J * K * K * sigmainvQPtsq + L0 * L0 * sigmaDeltaXsq + M0 * M0 * sigmaDeltaYsq); // <PHI,PHI> + lastParamCov(2, 2) = D * (J * K * K * sigmainvQPtsq + L0 * L0 * sigmaDeltaXsq + M0 * M0 * sigmaDeltaYsq); // <PHI,PHI> lastParamCov(2, 3) = E * K * (TMath::Sqrt2() * B52 * (L0 * deltaX * sigmaDeltaXsq - deltaY * sigmaDeltaYsq * M0) + N * sigmainvQPtsq); // <TANL,PHI> - lastParamCov(2, 4) = P * sigmainvQPtsq * TMath::Sqrt2() / B32; // <INVQPT,PHI> + lastParamCov(2, 4) = P * sigmainvQPtsq * TMath::Sqrt2() / B32; // <INVQPT,PHI> lastParamCov(3, 3) = Q * (2 * K * K * (deltaX * deltaX * sigmaDeltaXsq + deltaY * deltaY * sigmaDeltaYsq) + O * sigmainvQPtsq); // <TANL,TANL> - lastParamCov(3, 4) = R * sigmainvQPtsq; // <INVQPT,TANL> + lastParamCov(3, 4) = R * sigmainvQPtsq; // <INVQPT,TANL> lastParamCov(4, 4) = sigmainvQPtsq; // <INVQPT,INVQPT> @@ -263,7 +263,7 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) else NDisksMS = (startingLayerID % 2 == 0) ? (newLayerID - startingLayerID + 1) / 2 : (newLayerID - startingLayerID) / 2; - auto MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0; + auto MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLength / 5.0; if (mftTrackingParam.verbose) { std::cout << "startingLayerID = " << startingLayerID << " ; " << "newLayerID = " << newLayerID << " ; "; @@ -367,7 +367,7 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2) * (x2 - y2)) * invx2y2 * invx2y2; u2 = uVal[i] * uVal[i]; fweight[i] = 1. / vErr[i]; - F0 += fweight[i]; // f = fn(Hansroul) que é o peso de cada ponto Vn...inverso da incerteza? + F0 += fweight[i]; F1 += fweight[i] * uVal[i]; F2 += fweight[i] * u2; F3 += fweight[i] * uVal[i] * u2; @@ -447,9 +447,6 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai sigmainvqptsq = sigma2R * invpt * invpt * invR * invR; - std::cout << " Sigma^2_A " << sigmaAsq << " Sigma^2_B " << sigmaBsq << " Sigma_AB " << sigmaAB << std::endl; - std::cout << " Sigma^2_a " << sigmaasq_FCF << " Sigma^2_b " << sigmabsq_FCF << " Sigma^2_R " << sigma2R << std::endl; - } else { // the linear regression failed... LOG(WARN) << "LinearRegression failed!"; invqpt_fcf = 1. / 100.; From 23bcf94501cd62bf96bf4462eb41d5f4cc24148a Mon Sep 17 00:00:00 2001 From: Rafael Pezzi <rafael.pezzi@cern.ch> Date: Tue, 6 Oct 2020 12:14:40 -0300 Subject: [PATCH 0942/1751] Adding default constructor for mft::Cluster --- Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index 5dc5e4a16740d..851151caa71a2 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -26,6 +26,7 @@ namespace mft { struct Cluster : public o2::BaseCluster<float> { + Cluster() = default; Cluster(const Float_t x, const Float_t y, const Float_t z, const Float_t phi, const Float_t r, const Int_t id, const Int_t bin, const Float_t sigX2, const Float_t sigY2, const Int_t sensorID) : BaseCluster(sensorID, x, y, z), phiCoordinate{phi}, From ca788e1b7cc3e2001a3edf42de03fea00b615813 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen <evgeny.kryshen@cern.ch> Date: Wed, 14 Oct 2020 00:10:54 +0300 Subject: [PATCH 0943/1751] Run2V0 replaced with FV0A and FV0C (#4570) --- Analysis/DataModel/src/aodDataModelGraph.cxx | 4 +- Analysis/Tasks/eventSelection.cxx | 47 ++--------- Analysis/Tasks/eventSelectionQa.cxx | 26 ++++-- Analysis/Tasks/multiplicityTable.cxx | 17 ++-- Analysis/Tutorials/src/ZDCVZeroIteration.cxx | 58 ++++++------- .../include/Framework/AnalysisDataModel.h | 83 ++++++++----------- 6 files changed, 104 insertions(+), 131 deletions(-) diff --git a/Analysis/DataModel/src/aodDataModelGraph.cxx b/Analysis/DataModel/src/aodDataModelGraph.cxx index 5b9a60f7e727c..6653ddce6c9d3 100644 --- a/Analysis/DataModel/src/aodDataModelGraph.cxx +++ b/Analysis/DataModel/src/aodDataModelGraph.cxx @@ -234,7 +234,7 @@ int main(int, char**) displayEntity<Zdcs>(); displayEntity<FT0s>(); - displayEntity<FV0s>(); + displayEntity<FV0As>(); displayEntity<FDDs>(); displayEntities<Collisions, Cents, Mults, Timestamps>(); @@ -245,7 +245,7 @@ int main(int, char**) displayEntity<CaloTriggers>(); displayEntity<McCaloLabels>(); - displayEntity<Run2V0s>(); + displayEntity<FV0Cs>(); displayEntities<Tracks, TracksCov, TracksExtra, TracksExtended, TrackSelection, pidRespTOF, pidRespTPC>(); displayEntity<UnassignedTracks>(); diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index a8e2590f2f516..d29c768b9b557 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -58,33 +58,6 @@ struct EventSelectionTask { EvSelParameters par; - aod::Run2V0 getVZero(aod::BC const& bc, aod::Run2V0s const& vzeros) - { - for (auto& vzero : vzeros) - if (vzero.bc() == bc) - return vzero; - aod::Run2V0 dummy; - return dummy; - } - - aod::Zdc getZdc(aod::BC const& bc, aod::Zdcs const& zdcs) - { - for (auto& zdc : zdcs) - if (zdc.bc() == bc) - return zdc; - aod::Zdc dummy; - return dummy; - } - - aod::FDD getFDD(aod::BC const& bc, aod::FDDs const& fdds) - { - for (auto& fdd : fdds) - if (fdd.bc() == bc) - return fdd; - aod::FDD dummy; - return dummy; - } - void init(InitContext&) { ccdb->setURL("http://ccdb-test.cern.ch:8080"); @@ -92,7 +65,7 @@ struct EventSelectionTask { ccdb->setLocalObjectValidityChecking(); } - void process(aod::Collision const& collision, aod::BCsWithTimestamps const&, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs const& fdds) + void process(aod::Run2MatchedSparse::iterator const& collision, aod::BCsWithTimestamps const&, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FDDs const& fdds) { auto bc = collision.bc_as<aod::BCsWithTimestamps>(); LOGF(debug, "timestamp=%llu", bc.timestamp()); @@ -111,18 +84,12 @@ struct EventSelectionTask { } } - // ZDC info - auto zdc = getZdc(collision.bc(), zdcs); - float timeZNA = zdc.timeZNA(); - float timeZNC = zdc.timeZNC(); - // VZERO info - auto vzero = getVZero(collision.bc(), vzeros); - float timeV0A = vzero.timeA(); - float timeV0C = vzero.timeC(); - // FDD info - auto fdd = getFDD(collision.bc(), fdds); - float timeFDA = fdd.timeA(); - float timeFDC = fdd.timeC(); + float timeZNA = collision.has_zdc() ? collision.zdc().timeZNA() : -999.f; + float timeZNC = collision.has_zdc() ? collision.zdc().timeZNC() : -999.f; + float timeV0A = collision.has_fv0a() ? collision.fv0a().time() : -999.f; + float timeV0C = collision.has_fv0c() ? collision.fv0c().time() : -999.f; + float timeFDA = collision.has_fdd() ? collision.fdd().timeA() : -999.f; + float timeFDC = collision.has_fdd() ? collision.fdd().timeC() : -999.f; LOGF(debug, "timeZNA=%f timeZNC=%f", timeZNA, timeZNC); LOGF(debug, "timeV0A=%f timeV0C=%f", timeV0A, timeV0C); diff --git a/Analysis/Tasks/eventSelectionQa.cxx b/Analysis/Tasks/eventSelectionQa.cxx index fdbb8eaef6459..ec82a9dab9213 100644 --- a/Analysis/Tasks/eventSelectionQa.cxx +++ b/Analysis/Tasks/eventSelectionQa.cxx @@ -16,12 +16,21 @@ using namespace o2; using namespace o2::framework; struct EventSelectionTask { - aod::Run2V0 getVZero(aod::BC const& bc, aod::Run2V0s const& vzeros) + aod::FV0A getVZeroA(aod::BC const& bc, aod::FV0As const& vzeros) { for (auto& vzero : vzeros) if (vzero.bc() == bc) return vzero; - aod::Run2V0 dummy; + aod::FV0A dummy; + return dummy; + } + + aod::FV0C getVZeroC(aod::BC const& bc, aod::FV0Cs const& vzeros) + { + for (auto& vzero : vzeros) + if (vzero.bc() == bc) + return vzero; + aod::FV0C dummy; return dummy; } @@ -58,14 +67,15 @@ struct EventSelectionTask { Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; - void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs fdds) + void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FDDs fdds) { if (!isMC && !col.alias()[kINT7]) return; - auto vzero = getVZero(col.bc(), vzeros); - hTimeV0Aall->Fill(vzero.timeA()); - hTimeV0Call->Fill(vzero.timeC()); + auto fv0a = getVZeroA(col.bc(), fv0as); + auto fv0c = getVZeroC(col.bc(), fv0cs); + hTimeV0Aall->Fill(fv0a.time()); + hTimeV0Call->Fill(fv0c.time()); auto zdc = getZdc(col.bc(), zdcs); hTimeZNAall->Fill(zdc.timeZNA()); @@ -78,8 +88,8 @@ struct EventSelectionTask { if (!col.sel7()) return; - hTimeV0Aacc->Fill(vzero.timeA()); - hTimeV0Cacc->Fill(vzero.timeC()); + hTimeV0Aacc->Fill(fv0a.time()); + hTimeV0Cacc->Fill(fv0c.time()); hTimeZNAacc->Fill(zdc.timeZNA()); hTimeZNCacc->Fill(zdc.timeZNC()); hTimeFDAacc->Fill(fdd.timeA()); diff --git a/Analysis/Tasks/multiplicityTable.cxx b/Analysis/Tasks/multiplicityTable.cxx index d02ec15a48b74..f9bd0adeaabad 100644 --- a/Analysis/Tasks/multiplicityTable.cxx +++ b/Analysis/Tasks/multiplicityTable.cxx @@ -20,7 +20,7 @@ struct MultiplicityTableTaskIndexed { Produces<aod::Mults> mult; Partition<aod::Tracks> tracklets = (aod::track::trackType == static_cast<uint8_t>(o2::aod::track::TrackTypeEnum::Run2Tracklet)); - void process(aod::Run2MatchedSparse::iterator const& collision, aod::Tracks const& tracks, aod::BCs const&, aod::Zdcs const&, aod::Run2V0s const&) + void process(aod::Run2MatchedSparse::iterator const& collision, aod::Tracks const& tracks, aod::BCs const&, aod::Zdcs const&, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs) { float multV0A = -1.f; float multV0C = -1.f; @@ -28,10 +28,17 @@ struct MultiplicityTableTaskIndexed { float multZNC = -1.f; int multTracklets = tracklets.size(); - if (collision.has_run2v0()) { - auto v0 = collision.run2v0(); - multV0A = v0.multA(); - multV0C = v0.multC(); + if (collision.has_fv0a()) { + auto v0a = collision.fv0a(); + for (int i = 0; i < 48; i++) { + multV0A += v0a.amplitude()[i]; + } + } + if (collision.has_fv0c()) { + auto v0c = collision.fv0c(); + for (int i = 0; i < 32; i++) { + multV0C += v0c.amplitude()[i]; + } } if (collision.has_zdc()) { auto zdc = collision.zdc(); diff --git a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx index 7c762f53888fe..2cebd397f4c36 100644 --- a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx +++ b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx @@ -15,25 +15,25 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// This task shows how to access the ZDC and the Run2 V0 information which belongs to a collision +// This task shows how to access the ZDC and FV0A information which belongs to a collision // The association is made through the BC column (and in Run 3 may not be unique!) // To run this workflow, the o2-analysis-run2-matcher has to be run as well. // Example: o2-analysis-run2-matcher --aod-file AO2D.root | o2-analysistutorial-zdc-vzero-iteration -// This example access the collisions and the related Run2V0 information. -// Note that one has to subscribe to aod::Collisions const& and aod::Run2V0s const& to load -// the relevant data even if you access the data itself through m.collision() and m.run2v0() -// Here the "sparse" matcher is used which means, there can be collisions without Run2V0 information -// To find out, m.has_run2v0() has to be called. Otherwise m.run2v0() will fail. +// This example access the collisions and the related FV0A information. +// Note that one has to subscribe to aod::Collisions const& and aod::FV0As const& to load +// the relevant data even if you access the data itself through m.collision() and m.fv0a() +// Here the "sparse" matcher is used which means, there can be collisions without FV0A information +// To find out, m.has_fv0a() has to be called. Otherwise m.fv0a() will fail. struct IterateV0 { - void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::Run2V0s const&) + void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::FV0As const&) { LOGF(INFO, "Vertex = %f", m.collision().posZ()); - if (m.has_run2v0()) { - auto v0 = m.run2v0(); - LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + if (m.has_fv0a()) { + auto v0a = m.fv0a(); + LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); } else { - LOGF(INFO, "No V0 info"); + LOGF(INFO, "No V0A info"); } } }; @@ -42,25 +42,25 @@ struct IterateV0 { // of the tables asked for in Run2MatchedExclusive (see AnalysisDataModel.h) are missing are not listed. // Only to be used if one is sure that all your events have the desired information struct IterateV0Exclusive { - void process(aod::Run2MatchedExclusive::iterator const& m, aod::Collisions const&, aod::Run2V0s const&) + void process(aod::Run2MatchedExclusive::iterator const& m, aod::Collisions const&, aod::FV0As const&) { LOGF(INFO, "Vertex = %f", m.collision().posZ()); - auto v0 = m.run2v0(); - LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + auto v0a = m.fv0a(); + LOGF(info, "V0: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); } }; // This example builds on IterateV0 and in addition accesses also the tracks grouped to the specific collision. // The tracks are directly access through its pointer. struct IterateV0Tracks { - void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::Run2V0s const&, aod::Tracks const& tracks) + void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::FV0As const&, aod::Tracks const& tracks) { LOGF(INFO, "Vertex = %f. %d tracks", m.collision().posZ(), tracks.size()); - if (m.has_run2v0()) { - auto v0 = m.run2v0(); - LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + if (m.has_fv0a()) { + auto v0a = m.fv0a(); + LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); } else { - LOGF(INFO, "No V0 info"); + LOGF(INFO, "No V0A info"); } } }; @@ -68,29 +68,29 @@ struct IterateV0Tracks { // IterateV0Tracks with join. Desired version for good readability // using CollisionMatchedRun2Sparse = soa::Join<aod::Run2MatchedSparse, aod::Collisions>::iterator; // struct IterateV0Tracks2 { -// void process(CollisionMatchedRun2Sparse const& m, aod::Run2V0s const&, aod::Tracks const& tracks) +// void process(CollisionMatchedRun2Sparse const& m, aod::FV0As const&, aod::Tracks const& tracks) // { // LOGF(INFO, "Vertex = %f. %d tracks", m.posZ(), tracks.size()); // LOGF(INFO, "Vertex = %f. %d tracks", m.collision().posZ(), tracks.size()); -// if (m.has_run2v0()) { -// auto v0 = m.run2v0(); -// LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); +// if (m.has_fv0a()) { +// auto v0a = m.fv0a(); +// LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); // } else { -// LOGF(INFO, "No V0 info"); +// LOGF(INFO, "No V0A info"); // } // } // }; // This example accesses V0 and ZDC information struct IterateV0ZDC { - void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::Run2V0s const&, aod::Zdcs const&) + void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::FV0As const&, aod::Zdcs const&) { LOGF(INFO, "Vertex = %f", m.collision().posZ()); - if (m.has_run2v0()) { - auto v0 = m.run2v0(); - LOGF(info, "V0: %f %f", v0.adc()[0], v0.adc()[1]); + if (m.has_fv0a()) { + auto v0a = m.fv0a(); + LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); } else { - LOGF(INFO, "No V0 info"); + LOGF(INFO, "No V0A info"); } if (m.has_zdc()) { LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", m.zdc().energyZEM1(), m.zdc().energyZEM2()); diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 14d59145900bc..321c0c293f337 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -421,44 +421,56 @@ DECLARE_SOA_TABLE(Zdcs, "AOD", "ZDC", o2::soa::Index<>, zdc::BCId, zdc::EnergyZE zdc::TimeZEM1, zdc::TimeZEM2, zdc::TimeZNA, zdc::TimeZNC, zdc::TimeZPA, zdc::TimeZPC); using Zdc = Zdcs::iterator; +namespace fv0a +{ +DECLARE_SOA_INDEX_COLUMN(BC, bc); +DECLARE_SOA_COLUMN(Amplitude, amplitude, float[48]); +DECLARE_SOA_COLUMN(Time, time, float); +DECLARE_SOA_COLUMN(TriggerMask, triggerMask, uint8_t); +} // namespace fv0a + +DECLARE_SOA_TABLE(FV0As, "AOD", "FV0A", o2::soa::Index<>, fv0a::BCId, fv0a::Amplitude, fv0a::Time, fv0a::TriggerMask); +using FV0A = FV0As::iterator; + +// V0C table for Run2 only +namespace fv0c +{ +DECLARE_SOA_INDEX_COLUMN(BC, bc); +DECLARE_SOA_COLUMN(Amplitude, amplitude, float[32]); +DECLARE_SOA_COLUMN(Time, time, float); +} // namespace fv0c + +DECLARE_SOA_TABLE(FV0Cs, "AOD", "FV0C", o2::soa::Index<>, fv0c::BCId, fv0c::Amplitude, fv0c::Time); +using FV0C = FV0Cs::iterator; + namespace ft0 { DECLARE_SOA_INDEX_COLUMN(BC, bc); -DECLARE_SOA_COLUMN(Amplitude, amplitude, float[208]); +DECLARE_SOA_COLUMN(AmplitudeA, amplitudeA, float[96]); +DECLARE_SOA_COLUMN(AmplitudeC, amplitudeC, float[112]); DECLARE_SOA_COLUMN(TimeA, timeA, float); DECLARE_SOA_COLUMN(TimeC, timeC, float); -DECLARE_SOA_COLUMN(BCSignal, triggerSignal, uint8_t); +DECLARE_SOA_COLUMN(TriggerMask, triggerMask, uint8_t); } // namespace ft0 DECLARE_SOA_TABLE(FT0s, "AOD", "FT0", o2::soa::Index<>, ft0::BCId, - ft0::Amplitude, ft0::TimeA, ft0::TimeC, - ft0::BCSignal); + ft0::AmplitudeA, ft0::AmplitudeC, ft0::TimeA, ft0::TimeC, + ft0::TriggerMask); using FT0 = FT0s::iterator; -namespace fv0 -{ -DECLARE_SOA_INDEX_COLUMN(BC, bc); -DECLARE_SOA_COLUMN(Amplitude, amplitude, float[48]); -DECLARE_SOA_COLUMN(TimeA, timeA, float); -DECLARE_SOA_COLUMN(BCSignal, triggerSignal, uint8_t); -} // namespace fv0 - -DECLARE_SOA_TABLE(FV0s, "AOD", "FV0", o2::soa::Index<>, fv0::BCId, - fv0::Amplitude, fv0::TimeA, fv0::BCSignal); -using FV0 = FV0s::iterator; - namespace fdd { DECLARE_SOA_INDEX_COLUMN(BC, bc); -DECLARE_SOA_COLUMN(Amplitude, amplitude, float[8]); +DECLARE_SOA_COLUMN(AmplitudeA, amplitudeA, float[4]); +DECLARE_SOA_COLUMN(AmplitudeC, amplitudeC, float[4]); DECLARE_SOA_COLUMN(TimeA, timeA, float); DECLARE_SOA_COLUMN(TimeC, timeC, float); -DECLARE_SOA_COLUMN(BCSignal, triggerSignal, uint8_t); +DECLARE_SOA_COLUMN(TriggerMask, triggerMask, uint8_t); } // namespace fdd DECLARE_SOA_TABLE(FDDs, "AOD", "FDD", o2::soa::Index<>, fdd::BCId, - fdd::Amplitude, fdd::TimeA, fdd::TimeC, - fdd::BCSignal); + fdd::AmplitudeA, fdd::AmplitudeC, fdd::TimeA, fdd::TimeC, + fdd::TriggerMask); using FDD = FDDs::iterator; namespace v0 @@ -487,29 +499,6 @@ DECLARE_SOA_TABLE(TransientCascades, "AOD", "CASCADEINDEX", cascade::CollisionId using Cascades = soa::Join<TransientCascades, StoredCascades>; using Cascade = Cascades::iterator; -// ---- LEGACY tables ---- - -namespace run2v0 -{ -DECLARE_SOA_INDEX_COLUMN(BC, bc); -DECLARE_SOA_COLUMN(Adc, adc, float[64]); -DECLARE_SOA_COLUMN(Time, time, float[64]); -DECLARE_SOA_COLUMN(Width, width, float[64]); -DECLARE_SOA_COLUMN(MultA, multA, float); -DECLARE_SOA_COLUMN(MultC, multC, float); -DECLARE_SOA_COLUMN(TimeA, timeA, float); -DECLARE_SOA_COLUMN(TimeC, timeC, float); -DECLARE_SOA_COLUMN(BBFlag, bbFlag, uint64_t); -DECLARE_SOA_COLUMN(BGFlag, bgFlag, uint64_t); -} // namespace run2v0 - -DECLARE_SOA_TABLE(Run2V0s, "RN2", "V0", o2::soa::Index<>, run2v0::BCId, - run2v0::Adc, run2v0::Time, run2v0::Width, - run2v0::MultA, run2v0::MultC, - run2v0::TimeA, run2v0::TimeC, - run2v0::BBFlag, run2v0::BGFlag); -using Run2V0 = Run2V0s::iterator; - // ---- MC tables ---- namespace mccollision @@ -612,17 +601,17 @@ namespace indices DECLARE_SOA_INDEX_COLUMN(Collision, collision); DECLARE_SOA_INDEX_COLUMN(BC, bc); DECLARE_SOA_INDEX_COLUMN(Zdc, zdc); +DECLARE_SOA_INDEX_COLUMN(FV0A, fv0a); +DECLARE_SOA_INDEX_COLUMN(FV0C, fv0c); DECLARE_SOA_INDEX_COLUMN(FT0, ft0); -DECLARE_SOA_INDEX_COLUMN(FV0, fv0); DECLARE_SOA_INDEX_COLUMN(FDD, fdd); -DECLARE_SOA_INDEX_COLUMN(Run2V0, run2v0); } // namespace indices -#define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::Run2V0Id +#define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FV0CId, indices::FDDId DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); -#define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0Id, indices::FDDId +#define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FV0CId, indices::FDDId DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MA_RN3_SP", INDEX_LIST_RUN3); From b33c799ea067a6644576eff3c6731323ba10bb8b Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Tue, 13 Oct 2020 23:13:47 +0200 Subject: [PATCH 0944/1751] Adapt DataInputDirector to the new AO2D file format, which includes a subdirectory TF_%d per time frame (#4573) * This allows to save table data of several Time Frames (TF) in one file. Each TF is saved in a sub folder TF_%d. Each subfolder contains the same trees. --- .../include/Framework/DataInputDirector.h | 26 ++-- Framework/Core/src/DataInputDirector.cxx | 136 +++++++++++------- Framework/Core/src/WorkflowHelpers.cxx | 2 +- .../Core/test/test_DataInputDirector.cxx | 9 +- 4 files changed, 109 insertions(+), 64 deletions(-) diff --git a/Framework/Core/include/Framework/DataInputDirector.h b/Framework/Core/include/Framework/DataInputDirector.h index 33e8b1bf4e9da..880495d4e2e2b 100644 --- a/Framework/Core/include/Framework/DataInputDirector.h +++ b/Framework/Core/include/Framework/DataInputDirector.h @@ -24,6 +24,13 @@ namespace framework { using namespace rapidjson; +struct FileNameHolder { + std::string fileName; + int numberOfTimeFrames = 0; + std::vector<std::string> listOfTimeFrameKeys; +}; +FileNameHolder* makeFileNameHolder(std::string fileName); + struct DataInputDescriptor { /// Holds information concerning the reading of an aod table. /// The information includes the table specification, treename, @@ -44,9 +51,9 @@ struct DataInputDescriptor { void setFilenamesRegex(std::string fn) { mFilenameRegex = fn; } void setFilenamesRegex(std::string* fnptr) { mFilenameRegexPtr = fnptr; } - void setDefaultInputfiles(std::vector<std::string>* difnptr) { mdefaultFilenamesPtr = difnptr; } + void setDefaultInputfiles(std::vector<FileNameHolder*>* difnptr) { mdefaultFilenamesPtr = difnptr; } - void addFilename(std::string fn); + void addFileNameHolder(FileNameHolder* fn); int fillInputfiles(); // getters @@ -54,10 +61,11 @@ struct DataInputDescriptor { std::string getFilenamesRegexString(); std::regex getFilenamesRegex(); int getNumberInputfiles() { return mfilenames.size(); } + int getNumberTimeFrames() { return mtotalNumberTimeFrames; } + + std::tuple<TFile*, std::string> getFileFolder(int counter); - TFile* getInputFile(int counter); void closeInputFile(); - std::string getInputFilename(int counter); bool isAlienSupportOn() { return mAlienSupport; } private: @@ -65,10 +73,12 @@ struct DataInputDescriptor { std::string* minputfilesFilePtr = nullptr; std::string mFilenameRegex = ""; std::string* mFilenameRegexPtr = nullptr; - std::vector<std::string> mfilenames; - std::vector<std::string>* mdefaultFilenamesPtr = nullptr; + std::vector<FileNameHolder*> mfilenames; + std::vector<FileNameHolder*>* mdefaultFilenamesPtr = nullptr; TFile* mcurrentFile = nullptr; bool mAlienSupport = false; + + int mtotalNumberTimeFrames = 0; }; struct DataInputDirector { @@ -94,7 +104,7 @@ struct DataInputDirector { // getters DataInputDescriptor* getDataInputDescriptor(header::DataHeader dh); std::unique_ptr<TTreeReader> getTreeReader(header::DataHeader dh, int counter, std::string treeName); - std::string getInputFilename(header::DataHeader dh, int counter); + std::tuple<TFile*, std::string> getFileFolder(header::DataHeader dh, int counter); TTree* getDataTree(header::DataHeader dh, int counter); int getNumberInputDescriptors() { return mdataInputDescriptors.size(); } @@ -104,7 +114,7 @@ struct DataInputDirector { std::string mFilenameRegex; std::string* const mFilenameRegexPtr = &mFilenameRegex; DataInputDescriptor* mdefaultDataInputDescriptor = nullptr; - std::vector<std::string> mdefaultInputFiles; + std::vector<FileNameHolder*> mdefaultInputFiles; std::vector<DataInputDescriptor*> mdataInputDescriptors; bool mDebugMode = false; diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index d7be1fd9763f4..dae6dc8762265 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -24,11 +24,48 @@ namespace framework { using namespace rapidjson; +FileNameHolder* makeFileNameHolder(std::string fileName) +{ + auto fileNameHolder = new FileNameHolder(); + fileNameHolder->fileName = fileName; + + TFile file = TFile(fileName.c_str(), "R"); + if (!file.IsOpen()) { + LOGP(ERROR, "\"{}\" can not be opened.", fileName); + return fileNameHolder; + } + + // find TimeFrame folders + std::regex TFRegex = std::regex("TF_[0-9]+"); + TList* keyList = file.GetListOfKeys(); + for (auto key : *keyList) { + if (std::regex_match(((TObjString*)key)->GetString().Data(), TFRegex)) { + fileNameHolder->listOfTimeFrameKeys.emplace_back(std::string(((TObjString*)key)->GetString().Data())); + } + } + fileNameHolder->numberOfTimeFrames = fileNameHolder->listOfTimeFrameKeys.size(); + + return fileNameHolder; +} + DataInputDescriptor::DataInputDescriptor(bool alienSupport) { mAlienSupport = alienSupport; } +void DataInputDescriptor::printOut() +{ + LOGP(INFO, "DataInputDescriptor"); + LOGP(INFO, " Table name : {}", tablename); + LOGP(INFO, " Tree name : {}", treename); + LOGP(INFO, " Input files file : {}", getInputfilesFilename()); + LOGP(INFO, " File name regex : {}", getFilenamesRegexString()); + LOGP(INFO, " Input files : {}", mfilenames.size()); + for (auto fn : mfilenames) + LOGP(INFO, " {} {}", fn->fileName, fn->numberOfTimeFrames); + LOGP(INFO, " Total number of TF: {}", getNumberTimeFrames()); +} + std::string DataInputDescriptor::getInputfilesFilename() { return (minputfilesFile.empty() && minputfilesFilePtr) ? (std::string)*minputfilesFilePtr : minputfilesFile; @@ -44,35 +81,52 @@ std::regex DataInputDescriptor::getFilenamesRegex() return std::regex(getFilenamesRegexString()); } -void DataInputDescriptor::addFilename(std::string fn) +void DataInputDescriptor::addFileNameHolder(FileNameHolder* fn) { - if (!mAlienSupport && fn.rfind("alien://", 0) == 0) { + if (!mAlienSupport && fn->fileName.rfind("alien://", 0) == 0) { LOG(debug) << "AliEn file requested. Enabling support."; TGrid::Connect("alien://"); mAlienSupport = true; } + + mtotalNumberTimeFrames += fn->numberOfTimeFrames; mfilenames.emplace_back(fn); } -TFile* DataInputDescriptor::getInputFile(int counter) +std::tuple<TFile*, std::string> DataInputDescriptor::getFileFolder(int counter) { - if (counter < getNumberInputfiles()) { + std::string filename(""); + std::string directoryName(""); + + int cnt = mfilenames[0]->numberOfTimeFrames; + if (counter >= 0 && counter < getNumberTimeFrames()) { + for (int ii = 0; ii < getNumberInputfiles(); ii++) { + if (counter < cnt) { + filename = mfilenames[ii]->fileName; + cnt -= mfilenames[ii]->numberOfTimeFrames; + directoryName = (mfilenames[ii]->listOfTimeFrameKeys)[counter - cnt]; + break; + } else { + cnt += mfilenames[ii + 1]->numberOfTimeFrames; + } + } + if (mcurrentFile) { - if (mcurrentFile->GetName() != mfilenames[counter]) { + if (mcurrentFile->GetName() != filename) { closeInputFile(); - mcurrentFile = TFile::Open(mfilenames[counter].c_str()); + mcurrentFile = TFile::Open(filename.c_str()); } } else { - mcurrentFile = TFile::Open(mfilenames[counter].c_str()); + mcurrentFile = TFile::Open(filename.c_str()); } if (!mcurrentFile) { - throw std::runtime_error(fmt::format("Couldn't open file \"{}\"!", mfilenames[counter])); + throw std::runtime_error(fmt::format("Couldn't open file \"{}\"!", filename)); } } else { closeInputFile(); } - return mcurrentFile; + return std::make_tuple(mcurrentFile, directoryName); } void DataInputDescriptor::closeInputFile() @@ -98,7 +152,7 @@ int DataInputDescriptor::fillInputfiles() while (std::getline(filelist, fileName)) { if (getFilenamesRegexString().empty() || std::regex_match(fileName, getFilenamesRegex())) { - addFilename(fileName); + addFileNameHolder(makeFileNameHolder(fileName)); } } } catch (...) { @@ -108,10 +162,10 @@ int DataInputDescriptor::fillInputfiles() } else { // 3. getFilenamesRegex() @ mdefaultFilenamesPtr if (mdefaultFilenamesPtr) { - for (auto fileName : *mdefaultFilenamesPtr) { + for (auto fileNameHolder : *mdefaultFilenamesPtr) { if (getFilenamesRegexString().empty() || - std::regex_match(fileName, getFilenamesRegex())) { - addFilename(fileName); + std::regex_match(fileNameHolder->fileName, getFilenamesRegex())) { + addFileNameHolder(fileNameHolder); } } } @@ -120,29 +174,6 @@ int DataInputDescriptor::fillInputfiles() return getNumberInputfiles(); } -std::string DataInputDescriptor::getInputFilename(int counter) -{ - std::string filename(""); - if (counter >= 0 && counter < getNumberInputfiles()) { - filename = mfilenames[counter]; - } - - return filename; -} - -void DataInputDescriptor::printOut() -{ - LOGP(INFO, "DataInputDescriptor"); - LOGP(INFO, " Table name : {}", tablename); - LOGP(INFO, " Tree name : {}", treename); - LOGP(INFO, " Input files file : {}", getInputfilesFilename()); - LOGP(INFO, " File name regex : {}", getFilenamesRegexString()); - LOGP(INFO, " Input files : {}", mfilenames.size()); - for (auto fn : mfilenames) { - LOGP(INFO, " {}", fn); - } -} - DataInputDirector::DataInputDirector() { createDefaultDataInputDescriptor(); @@ -154,7 +185,7 @@ DataInputDirector::DataInputDirector(std::string inputFile) inputFile.erase(0, 1); setInputfilesFile(inputFile); } else { - mdefaultInputFiles.emplace_back(inputFile); + mdefaultInputFiles.emplace_back(makeFileNameHolder(inputFile)); } createDefaultDataInputDescriptor(); @@ -163,7 +194,7 @@ DataInputDirector::DataInputDirector(std::string inputFile) DataInputDirector::DataInputDirector(std::vector<std::string> inputFiles) { for (auto inputFile : inputFiles) { - mdefaultInputFiles.emplace_back(inputFile); + mdefaultInputFiles.emplace_back(makeFileNameHolder(inputFile)); } createDefaultDataInputDescriptor(); @@ -278,13 +309,13 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) setInputfilesFile(fileName); } else { setInputfilesFile(""); - mdefaultInputFiles.emplace_back(fileName); + mdefaultInputFiles.emplace_back(makeFileNameHolder(fileName)); } } else if (didirItem[itemName].IsArray()) { setInputfilesFile(""); auto fns = didirItem[itemName].GetArray(); for (auto& fn : fns) { - mdefaultInputFiles.emplace_back(fn.GetString()); + mdefaultInputFiles.emplace_back(makeFileNameHolder(fn.GetString())); } } else { LOGP(ERROR, "Check the JSON document! Item \"{}\" must be a string or an array!", itemName); @@ -361,7 +392,7 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) } else { if (didesc->getFilenamesRegexString().empty() || std::regex_match(fileName, didesc->getFilenamesRegex())) { - didesc->addFilename(fileName); + didesc->addFileNameHolder(makeFileNameHolder(fileName)); } } } else if (didescItem[itemName].IsArray()) { @@ -369,7 +400,7 @@ bool DataInputDirector::readJsonDocument(Document* jsonDoc) for (auto& fn : fns) { if (didesc->getFilenamesRegexString().empty() || std::regex_match(fn.GetString(), didesc->getFilenamesRegex())) { - didesc->addFilename(fn.GetString()); + didesc->addFileNameHolder(makeFileNameHolder(fn.GetString())); } } } else { @@ -434,8 +465,9 @@ std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader didesc = mdefaultDataInputDescriptor; } - auto file = didesc->getInputFile(counter); + auto [file, directory] = didesc->getFileFolder(counter); if (file) { + treename = directory + "/" + treename; reader = std::make_unique<TTreeReader>(treename.c_str(), file); if (!reader) { throw std::runtime_error(fmt::format(R"(Couldn't create TTreeReader for tree "{}" in file "{}")", treename, file->GetName())); @@ -445,16 +477,16 @@ std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader return reader; } -std::string DataInputDirector::getInputFilename(header::DataHeader dh, int counter) +std::tuple<TFile*, std::string> DataInputDirector::getFileFolder(header::DataHeader dh, int counter) { auto didesc = getDataInputDescriptor(dh); // if NOT match then use defaultDataInputDescriptor if (!didesc) { didesc = mdefaultDataInputDescriptor; } - auto filename = didesc->getInputFilename(counter); + auto [file, directory] = didesc->getFileFolder(counter); - return filename; + return std::make_tuple(file, directory); } TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter) @@ -474,8 +506,9 @@ TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter) treename = aod::datamodel::getTreeName(dh); } - auto file = didesc->getInputFile(counter); + auto [file, directory] = didesc->getFileFolder(counter); if (file) { + treename = directory + "/" + treename; tree = (TTree*)file->Get(treename.c_str()); if (!tree) { throw std::runtime_error(fmt::format(R"(Couldn't get TTree "{}" from "{}")", treename, file->GetName())); @@ -506,9 +539,9 @@ bool DataInputDirector::isValid() bool DataInputDirector::atEnd(int counter) { - bool status = mdefaultDataInputDescriptor->getNumberInputfiles() <= counter; + bool status = mdefaultDataInputDescriptor->getNumberTimeFrames() <= counter; for (auto didesc : mdataInputDescriptors) { - status &= (didesc->getNumberInputfiles() <= counter); + status &= (didesc->getNumberTimeFrames() <= counter); } return status; @@ -520,9 +553,8 @@ void DataInputDirector::printOut() LOGP(INFO, " Default input files file : {}", minputfilesFile); LOGP(INFO, " Default file name regex : {}", mFilenameRegex); LOGP(INFO, " Default file names : {}", mdefaultInputFiles.size()); - for (auto const& fn : mdefaultInputFiles) { - LOGP(INFO, " {}", fn); - } + for (auto const& fn : mdefaultInputFiles) + LOGP(INFO, " {} {}", fn->fileName, fn->numberOfTimeFrames); LOGP(INFO, " Default DataInputDescriptor:"); mdefaultDataInputDescriptor->printOut(); LOGP(INFO, " DataInputDescriptors : {}", getNumberInputDescriptors()); diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index a38f0e7946962..8d7ea47d1bb1b 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -385,7 +385,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { if ((outputTypes[ii] & 2) == 2) { - // temporarily also request to be dangling + // is this dangling ? if ((outputTypes[ii] & 1) == 1) { outputsInputsAOD.emplace_back(OutputsInputs[ii]); isdangling.emplace_back((outputTypes[ii] & 1) == 1); diff --git a/Framework/Core/test/test_DataInputDirector.cxx b/Framework/Core/test/test_DataInputDirector.cxx index c1d38d56a270e..f5a6ed352213a 100644 --- a/Framework/Core/test/test_DataInputDirector.cxx +++ b/Framework/Core/test/test_DataInputDirector.cxx @@ -50,14 +50,15 @@ BOOST_AUTO_TEST_CASE(TestDatainputDirector) DataInputDirector didir1; BOOST_CHECK(didir1.readJson(jsonFile)); - //didir1.printOut(); printf("\n\n"); + didir1.printOut(); printf("\n\n"); BOOST_CHECK_EQUAL(didir1.getNumberInputDescriptors(), 2); auto dh = DataHeader(DataDescription{"DUE"}, DataOrigin{"AOD"}, DataHeader::SubSpecificationType{0}); - BOOST_CHECK_EQUAL(didir1.getInputFilename(dh, 1), "Bresults_1.root"); + auto [file1, directory1] = didir1.getFileFolder(dh, 1); + //BOOST_CHECK_EQUAL(file1->GetName(), "Bresults_1.root"); auto didesc = didir1.getDataInputDescriptor(dh); BOOST_CHECK(didesc); @@ -93,9 +94,11 @@ BOOST_AUTO_TEST_CASE(TestDatainputDirector) "Bresults_1.root", "Bresults_2.root"}; DataInputDirector didir2(inputFiles); + didir2.printOut(); printf("\n\n"); BOOST_CHECK(didir2.readJson(jsonFile)); - BOOST_CHECK_EQUAL(didir2.getInputFilename(dh, 1), "Bresults_1.root"); + auto [file2, directory2] = didir2.getFileFolder(dh, 1); + //BOOST_CHECK_EQUAL(file2->GetName(), "Bresults_1.root"); didesc = didir2.getDataInputDescriptor(dh); BOOST_CHECK(didesc); From 341158b6c0fa1ce6def1069887f77a6be87486a1 Mon Sep 17 00:00:00 2001 From: nzardosh <nima.zardoshti@cern.ch> Date: Tue, 13 Oct 2020 23:14:22 +0200 Subject: [PATCH 0945/1751] restructuring PWGJE (#4512) --- Analysis/Core/CMakeLists.txt | 10 + Analysis/Core/include/Analysis/JetFinder.h | 182 ++++++++++++++++++ Analysis/Core/src/AnalysisCoreLinkDef.h | 2 + Analysis/Core/src/AnalysisJetsLinkDef.h | 15 ++ Analysis/Core/src/JetFinder.cxx | 90 +++++++++ Analysis/DataModel/include/Analysis/Jet.h | 56 +++++- Analysis/Tasks/CMakeLists.txt | 9 +- Analysis/Tasks/PWGJE/CMakeLists.txt | 38 ++++ Analysis/Tasks/PWGJE/jetfinder.cxx | 102 ++++++++++ .../Tasks/PWGJE/jetfinderhadronrecoil.cxx | 126 ++++++++++++ Analysis/Tasks/PWGJE/jetfinderhf.cxx | 113 +++++++++++ Analysis/Tasks/PWGJE/jetskimming.cxx | 69 +++++++ Analysis/Tasks/PWGJE/jetsubstructure.cxx | 124 ++++++++++++ Analysis/Tasks/jetfinder.cxx | 125 ------------ 14 files changed, 921 insertions(+), 140 deletions(-) create mode 100644 Analysis/Core/include/Analysis/JetFinder.h create mode 100644 Analysis/Core/src/AnalysisJetsLinkDef.h create mode 100644 Analysis/Core/src/JetFinder.cxx create mode 100644 Analysis/Tasks/PWGJE/CMakeLists.txt create mode 100644 Analysis/Tasks/PWGJE/jetfinder.cxx create mode 100644 Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx create mode 100644 Analysis/Tasks/PWGJE/jetfinderhf.cxx create mode 100644 Analysis/Tasks/PWGJE/jetskimming.cxx create mode 100644 Analysis/Tasks/PWGJE/jetsubstructure.cxx delete mode 100644 Analysis/Tasks/jetfinder.cxx diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index 03b0393c6029e..145b41d3ed9ce 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -30,3 +30,13 @@ o2_target_root_dictionary(AnalysisCore include/Analysis/TriggerAliases.h include/Analysis/MC.h LINKDEF src/AnalysisCoreLinkDef.h) + +if(FastJet_FOUND) +o2_add_library(AnalysisJets + SOURCES src/JetFinder.cxx + PUBLIC_LINK_LIBRARIES O2::AnalysisCore FastJet::FastJet FastJet::Contrib) + +o2_target_root_dictionary(AnalysisJets + HEADERS include/Analysis/JetFinder.h + LINKDEF src/AnalysisJetsLinkDef.h) +endif() diff --git a/Analysis/Core/include/Analysis/JetFinder.h b/Analysis/Core/include/Analysis/JetFinder.h new file mode 100644 index 0000000000000..486d11daedf5e --- /dev/null +++ b/Analysis/Core/include/Analysis/JetFinder.h @@ -0,0 +1,182 @@ +// 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. + +// jet finder task +// +// Authors: Nima Zardoshti, Jochen Klein + +#ifndef O2_ANALYSIS_JETFINDER_H +#define O2_ANALYSIS_JETFINDER_H + +#include <TDatabasePDG.h> +#include <TPDGCode.h> +#include <TMath.h> + +#include "fastjet/PseudoJet.hh" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/AreaDefinition.hh" +#include "fastjet/JetDefinition.hh" +#include "fastjet/tools/JetMedianBackgroundEstimator.hh" +#include "fastjet/tools/Subtractor.hh" +#include "fastjet/contrib/ConstituentSubtractor.hh" + +#include <vector> + +class JetFinder +{ + + public: + enum class BkgSubMode { none, + rhoAreaSub, + constSub }; + BkgSubMode bkgSubMode; + + void setBkgSubMode(BkgSubMode bSM) { bkgSubMode = bSM; } + + /// Performs jet finding + /// \note the input particle and jet lists are passed by reference + /// \param inputParticles vector of input particles/tracks + /// \param jets veector of jets to be filled + /// \return ClusterSequenceArea object needed to access constituents + // fastjet::ClusterSequenceArea findJets(std::vector<fastjet::PseudoJet> &inputParticles, std::vector<fastjet::PseudoJet> &jets); + + static constexpr float mPion = 0.139; // TDatabasePDG::Instance()->GetParticle(211)->Mass(); //can be removed when pion mass becomes default for unidentified tracks + + float phiMin; + float phiMax; + float etaMin; + float etaMax; + + float jetR; + float jetPtMin; + float jetPtMax; + float jetPhiMin; + float jetPhiMax; + float jetEtaMin; + float jetEtaMax; + + float ghostEtaMin; + float ghostEtaMax; + float ghostArea; + int ghostRepeatN; + double ghostktMean; + float gridScatter; + float ktScatter; + + float jetBkgR; + float bkgPhiMin; + float bkgPhiMax; + float bkgEtaMin; + float bkgEtaMax; + + float constSubAlpha; + float constSubRMax; + + bool isReclustering; + + fastjet::JetAlgorithm algorithm; + fastjet::RecombinationScheme recombScheme; + fastjet::Strategy strategy; + fastjet::AreaType areaType; + fastjet::GhostedAreaSpec ghostAreaSpec; + fastjet::JetDefinition jetDef; + fastjet::AreaDefinition areaDef; + fastjet::Selector selJets; + fastjet::Selector selGhosts; + + fastjet::JetAlgorithm algorithmBkg; + fastjet::RecombinationScheme recombSchemeBkg; + fastjet::Strategy strategyBkg; + fastjet::AreaType areaTypeBkg; + fastjet::JetDefinition jetDefBkg; + fastjet::AreaDefinition areaDefBkg; + fastjet::Selector selRho; + + /// Default constructor + JetFinder(float eta_Min = -0.9, float eta_Max = 0.9, float phi_Min = 0.0, float phi_Max = 2 * TMath::Pi()) : phiMin(phi_Min), + phiMax(phi_Max), + etaMin(eta_Min), + etaMax(eta_Max), + jetR(0.4), + jetPtMin(0.0), + jetPtMax(1000.0), + jetPhiMin(phi_Min), + jetPhiMax(phi_Max), + jetEtaMin(eta_Min), + jetEtaMax(eta_Max), + ghostEtaMin(eta_Min), + ghostEtaMax(eta_Max), + ghostArea(0.005), + ghostRepeatN(1), + ghostktMean(1e-100), //is float precise enough? + gridScatter(1.0), + ktScatter(0.1), + jetBkgR(0.2), + bkgPhiMin(phi_Min), + bkgPhiMax(phi_Max), + bkgEtaMin(eta_Min), + bkgEtaMax(eta_Max), + algorithm(fastjet::antikt_algorithm), + recombScheme(fastjet::E_scheme), + strategy(fastjet::Best), + areaType(fastjet::active_area), + algorithmBkg(fastjet::JetAlgorithm(fastjet::kt_algorithm)), + recombSchemeBkg(fastjet::RecombinationScheme(fastjet::E_scheme)), + strategyBkg(fastjet::Best), + areaTypeBkg(fastjet::active_area), + bkgSubMode(BkgSubMode::none), + constSubAlpha(1.0), + constSubRMax(0.6), + isReclustering(false) + + { + + //default constructor + } + + /// Default destructor + ~JetFinder() = default; + + /// Sets the jet finding parameters + void setParams(); + + /// Sets the background subtraction estimater pointer + void setBkgE(); + + /// Sets the background subtraction pointer + void setSub(); + + /// Performs jet finding + /// \note the input particle and jet lists are passed by reference + /// \param inputParticles vector of input particles/tracks + /// \param jets veector of jets to be filled + /// \return ClusterSequenceArea object needed to access constituents + fastjet::ClusterSequenceArea findJets(std::vector<fastjet::PseudoJet>& inputParticles, std::vector<fastjet::PseudoJet>& jets); //ideally find a way of passing the cluster sequence as a reeference + + private: + //void setParams(); + //void setBkgSub(); + std::unique_ptr<fastjet::BackgroundEstimatorBase> bkgE; + std::unique_ptr<fastjet::Subtractor> sub; + std::unique_ptr<fastjet::contrib::ConstituentSubtractor> constituentSub; + + ClassDef(JetFinder, 1); +}; + +//does this belong here? +template <typename T> +void fillConstituents(const T& constituent, std::vector<fastjet::PseudoJet>& constituents) +{ + + auto energy = std::sqrt(constituent.p() * constituent.p() + JetFinder::mPion * JetFinder::mPion); + constituents.emplace_back(constituent.px(), constituent.py(), constituent.pz(), energy); +} + +#endif diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index 5eac2f6879fa5..bc79d27b607be 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -26,3 +26,5 @@ #pragma link C++ class HistogramManager + ; #pragma link C++ class AnalysisCut + ; #pragma link C++ class AnalysisCompositeCut + ; + +// #pragma link C++ class JetFinder+; diff --git a/Analysis/Core/src/AnalysisJetsLinkDef.h b/Analysis/Core/src/AnalysisJetsLinkDef.h new file mode 100644 index 0000000000000..8de8bce16da64 --- /dev/null +++ b/Analysis/Core/src/AnalysisJetsLinkDef.h @@ -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. + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class JetFinder + ; diff --git a/Analysis/Core/src/JetFinder.cxx b/Analysis/Core/src/JetFinder.cxx new file mode 100644 index 0000000000000..fb1498d911e80 --- /dev/null +++ b/Analysis/Core/src/JetFinder.cxx @@ -0,0 +1,90 @@ +// 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. + +// jet finder task +// +// Author: Jochen Klein, Nima Zardoshti +#include "Analysis/JetFinder.h" +#include "Framework/AnalysisTask.h" + +/// Sets the jet finding parameters +void JetFinder::setParams() +{ + + if (!isReclustering) { + jetEtaMin = etaMin + jetR; //in aliphysics this was (-etaMax + 0.95*jetR) + jetEtaMax = etaMax - jetR; + } + + //selGhosts =fastjet::SelectorRapRange(ghostEtaMin,ghostEtaMax) && fastjet::SelectorPhiRange(phiMin,phiMax); + //ghostAreaSpec=fastjet::GhostedAreaSpec(selGhosts,ghostRepeatN,ghostArea,gridScatter,ktScatter,ghostktMean); + ghostAreaSpec = fastjet::GhostedAreaSpec(ghostEtaMax, ghostRepeatN, ghostArea, gridScatter, ktScatter, ghostktMean); //the first argument is rapidity not pseudorapidity, to be checked + jetDef = fastjet::JetDefinition(algorithm, jetR, recombScheme, strategy); + areaDef = fastjet::AreaDefinition(areaType, ghostAreaSpec); + selJets = fastjet::SelectorPtRange(jetPtMin, jetPtMax) && fastjet::SelectorEtaRange(jetEtaMin, jetEtaMax) && fastjet::SelectorPhiRange(jetPhiMin, jetPhiMax); + jetDefBkg = fastjet::JetDefinition(algorithmBkg, jetBkgR, recombSchemeBkg, strategyBkg); + areaDefBkg = fastjet::AreaDefinition(areaTypeBkg, ghostAreaSpec); + selRho = fastjet::SelectorRapRange(bkgEtaMin, bkgEtaMax) && fastjet::SelectorPhiRange(bkgPhiMin, bkgPhiMax); //&& !fastjet::SelectorNHardest(2) //here we have to put rap range, to be checked! +} + +/// Sets the background subtraction estimater pointer +void JetFinder::setBkgE() +{ + if (bkgSubMode == BkgSubMode::rhoAreaSub || bkgSubMode == BkgSubMode::constSub) { + bkgE = decltype(bkgE)(new fastjet::JetMedianBackgroundEstimator(selRho, jetDefBkg, areaDefBkg)); + } else { + if (bkgSubMode != BkgSubMode::none) + LOGF(ERROR, "requested subtraction mode not implemented!"); + } +} + +/// Sets the background subtraction pointer +void JetFinder::setSub() +{ + //if rho < 1e-6 it is set to 1e-6 in AliPhysics + if (bkgSubMode == BkgSubMode::rhoAreaSub) { + sub = decltype(sub){new fastjet::Subtractor{bkgE.get()}}; + } else if (bkgSubMode == BkgSubMode::constSub) { //event or jetwise + constituentSub = decltype(constituentSub){new fastjet::contrib::ConstituentSubtractor{bkgE.get()}}; + constituentSub->set_distance_type(fastjet::contrib::ConstituentSubtractor::deltaR); + constituentSub->set_max_distance(constSubRMax); + constituentSub->set_alpha(constSubAlpha); + constituentSub->set_ghost_area(ghostArea); + constituentSub->set_max_eta(bkgEtaMax); + constituentSub->set_background_estimator(bkgE.get()); //what about rho_m + } else { + if (bkgSubMode != BkgSubMode::none) + LOGF(ERROR, "requested subtraction mode not implemented!"); + } +} + +/// Performs jet finding +/// \note the input particle and jet lists are passed by reference +/// \param inputParticles vector of input particles/tracks +/// \param jets veector of jets to be filled +/// \return ClusterSequenceArea object needed to access constituents +fastjet::ClusterSequenceArea JetFinder::findJets(std::vector<fastjet::PseudoJet>& inputParticles, std::vector<fastjet::PseudoJet>& jets) //ideally find a way of passing the cluster sequence as a reeference +{ + setParams(); + setBkgE(); + jets.clear(); + + if (bkgE) { + bkgE->set_particles(inputParticles); + setSub(); + } + if (constituentSub) { + inputParticles = constituentSub->subtract_event(inputParticles); + } + fastjet::ClusterSequenceArea clusterSeq(inputParticles, jetDef, areaDef); + jets = sub ? (*sub)(clusterSeq.inclusive_jets()) : clusterSeq.inclusive_jets(); + jets = selJets(jets); + return clusterSeq; +} diff --git a/Analysis/DataModel/include/Analysis/Jet.h b/Analysis/DataModel/include/Analysis/Jet.h index 0d08276852a7d..6f36198fb58af 100644 --- a/Analysis/DataModel/include/Analysis/Jet.h +++ b/Analysis/DataModel/include/Analysis/Jet.h @@ -10,7 +10,7 @@ // table definitions for jets // -// Author: Jochen Klein +// Author: Jochen Klein, Nima Zardoshti #pragma once @@ -21,17 +21,31 @@ namespace o2::aod namespace jet { DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(Area, area, float); DECLARE_SOA_COLUMN(Energy, energy, float); DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(Area, area, float); +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) { return pt * TMath::Cos(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) { return pt * TMath::Sin(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) { return pt * TMath::SinH(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) { return pt * TMath::CosH(eta); }); //absolute p } // namespace jet DECLARE_SOA_TABLE(Jets, "AOD", "JET", - o2::soa::Index<>, jet::CollisionId, - jet::Eta, jet::Phi, jet::Pt, jet::Area, jet::Energy, jet::Mass); + o2::soa::Index<>, + jet::CollisionId, + jet::Pt, + jet::Eta, + jet::Phi, + jet::Energy, + jet::Mass, + jet::Area, + jet::Px<jet::Pt, jet::Phi>, + jet::Py<jet::Pt, jet::Phi>, + jet::Pz<jet::Pt, jet::Eta>, + jet::P<jet::Pt, jet::Eta>); using Jet = Jets::iterator; @@ -43,8 +57,36 @@ DECLARE_SOA_INDEX_COLUMN(Jet, jet); DECLARE_SOA_INDEX_COLUMN(Track, track); } // namespace constituents -DECLARE_SOA_TABLE(JetConstituents, "AOD", "JETCONSTITUENTS", - constituents::JetId, constituents::TrackId); +DECLARE_SOA_TABLE(JetConstituents, "AOD", "CONSTITUENTS", + constituents::JetId, + constituents::TrackId); using JetConstituent = JetConstituents::iterator; + +namespace constituentssub +{ +DECLARE_SOA_INDEX_COLUMN(Jet, jet); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) { return pt * TMath::Cos(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) { return pt * TMath::Sin(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) { return pt * TMath::SinH(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) { return pt * TMath::CosH(eta); }); //absolute p +} //namespace constituentssub +DECLARE_SOA_TABLE(JetConstituentsSub, "AOD", "CONSTITUENTSSUB", + constituentssub::JetId, + constituentssub::Pt, + constituentssub::Eta, + constituentssub::Phi, + constituentssub::Energy, + constituentssub::Mass, + constituentssub::Px<constituentssub::Pt, constituentssub::Phi>, + constituentssub::Py<constituentssub::Pt, constituentssub::Phi>, + constituentssub::Pz<constituentssub::Pt, constituentssub::Eta>, + constituentssub::P<constituentssub::Pt, constituentssub::Eta>); +using JetConstituentSub = JetConstituentsSub::iterator; + } // namespace o2::aod diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index d818f8eb79502..9723fd82fa5c5 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(PWGJE) add_subdirectory(PWGLF) add_subdirectory(PWGUD) @@ -44,14 +45,6 @@ o2_add_dpl_workflow(validation PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase COMPONENT_NAME Analysis) -if(FastJet_FOUND) -o2_add_dpl_workflow(jetfinder - SOURCES jetfinder.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel - FastJet::FastJet - COMPONENT_NAME Analysis) -endif() - o2_add_dpl_workflow(event-selection SOURCES eventSelection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB diff --git a/Analysis/Tasks/PWGJE/CMakeLists.txt b/Analysis/Tasks/PWGJE/CMakeLists.txt new file mode 100644 index 0000000000000..d0afc844d3375 --- /dev/null +++ b/Analysis/Tasks/PWGJE/CMakeLists.txt @@ -0,0 +1,38 @@ +# 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. + + +if(FastJet_FOUND) +o2_add_dpl_workflow(jet-finder + SOURCES jetfinder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisJets O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(jet-finder-hf + SOURCES jetfinderhf.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisJets O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(jet-finder-hadron-recoil + SOURCES jetfinderhadronrecoil.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisJets O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(jet-substructure + SOURCES jetsubstructure.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisJets O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(jet-skimmer + SOURCES jetskimming.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisJets O2::AnalysisDataModel + COMPONENT_NAME Analysis) +endif() + diff --git a/Analysis/Tasks/PWGJE/jetfinder.cxx b/Analysis/Tasks/PWGJE/jetfinder.cxx new file mode 100644 index 0000000000000..187b130a961e6 --- /dev/null +++ b/Analysis/Tasks/PWGJE/jetfinder.cxx @@ -0,0 +1,102 @@ +// 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. + +// jet finder task +// +// Author: Jochen Klein, Nima Zardoshti + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" + +#include "fastjet/PseudoJet.hh" +#include "fastjet/ClusterSequenceArea.hh" + +#include "Analysis/Jet.h" +#include "Analysis/JetFinder.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct JetFinderTask { + Produces<o2::aod::Jets> jetsTable; + Produces<o2::aod::JetConstituents> constituentsTable; + Produces<o2::aod::JetConstituentsSub> constituentsSubTable; + OutputObj<TH1F> hJetPt{"h_jet_pt"}; + OutputObj<TH1F> hJetPhi{"h_jet_phi"}; + OutputObj<TH1F> hJetEta{"h_jet_eta"}; + OutputObj<TH1F> hJetN{"h_jet_n"}; + + Configurable<bool> b_DoRhoAreaSub{"b_DoRhoAreaSub", false, "do rho area subtraction"}; + Configurable<bool> b_DoConstSub{"b_DoConstSub", false, "do constituent subtraction"}; + + Filter trackCuts = aod::track::pt >= 0.15f && aod::track::eta >= -0.9f && aod::track::eta <= 0.9f; + + std::vector<fastjet::PseudoJet> jets; + std::vector<fastjet::PseudoJet> inputParticles; + JetFinder jetFinder; + + void init(InitContext const&) + { + hJetPt.setObject(new TH1F("h_jet_pt", "jet p_{T};p_{T} (GeV/#it{c})", + 100, 0., 100.)); + hJetPhi.setObject(new TH1F("h_jet_phi", "jet #phi;#phi", + 80, -1., 7.)); + hJetEta.setObject(new TH1F("h_jet_eta", "jet #eta;#eta", + 70, -0.7, 0.7)); + hJetN.setObject(new TH1F("h_jet_n", "jet n;n constituents", + 30, 0., 30.)); + if (b_DoRhoAreaSub) + jetFinder.setBkgSubMode(JetFinder::BkgSubMode::rhoAreaSub); + if (b_DoConstSub) + jetFinder.setBkgSubMode(JetFinder::BkgSubMode::constSub); + } + + void process(aod::Collision const& collision, + soa::Filtered<aod::Tracks> const& tracks) + { + + jets.clear(); + inputParticles.clear(); + + for (auto& track : tracks) { + /* auto energy = std::sqrt(track.p() * track.p() + mPion*mPion); + inputParticles.emplace_back(track.px(), track.py(), track.pz(), energy); + inputParticles.back().set_user_index(track.globalIndex());*/ + fillConstituents(track, inputParticles); + inputParticles.back().set_user_index(track.globalIndex()); + } + + fastjet::ClusterSequenceArea clusterSeq(jetFinder.findJets(inputParticles, jets)); + + for (const auto& jet : jets) { + jetsTable(collision, jet.pt(), jet.eta(), jet.phi(), + jet.E(), jet.m(), jet.area()); + hJetPt->Fill(jet.pt()); + hJetPhi->Fill(jet.phi()); + hJetEta->Fill(jet.eta()); + hJetN->Fill(jet.constituents().size()); + for (const auto& constituent : jet.constituents()) { //event or jetwise + if (b_DoConstSub) + constituentsSubTable(jetsTable.lastIndex(), constituent.pt(), constituent.eta(), constituent.phi(), + constituent.E(), constituent.m()); + constituentsTable(jetsTable.lastIndex(), constituent.user_index()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<JetFinderTask>("jet-finder")}; +} diff --git a/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx b/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx new file mode 100644 index 0000000000000..d5eda89cbca71 --- /dev/null +++ b/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx @@ -0,0 +1,126 @@ +// 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. + +// jet finder task +// +// Author: Nima Zardoshti + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" + +#include "fastjet/PseudoJet.hh" +#include "fastjet/ClusterSequenceArea.hh" + +#include "Analysis/Jet.h" +#include "Analysis/JetFinder.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct JetFinderHadronRecoilTask { + OutputObj<TH1F> hJetPt{"h_jet_pt"}; + OutputObj<TH1F> hHadronPt{"h_hadron_pt"}; + OutputObj<TH1F> hJetHadronDeltaPhi{"h_jet_hadron_deltaphi"}; + + Configurable<float> f_trackTTMin{"f_trackTTMin", 8.0, "TT hadron min pT"}; + Configurable<float> f_trackTTMax{"f_trackTTMax", 9.0, "TT hadron max pT"}; + Configurable<float> f_recoilWindow{"f_recoilWindow", 0.6, "jet finding phi window reecoilling from hadron"}; + + Filter trackCuts = aod::track::pt >= 0.15f && aod::track::eta > -0.9f && aod::track::eta < 0.9f; + int collisionSplit = 0; //can we partition the collisions? + //can we also directly filter the collision based on the max track::pt? + + std::vector<float> trackTTPt; + std::vector<fastjet::PseudoJet> jets; + std::vector<fastjet::PseudoJet> inputParticles; + JetFinder jetFinder; + + template <typename T> + T relativePhi(T phi1, T phi2) + { + if (phi1 < -TMath::Pi()) { + phi1 += (2 * TMath::Pi()); + } else if (phi1 > TMath::Pi()) { + phi1 -= (2 * TMath::Pi()); + } + if (phi2 < -TMath::Pi()) { + phi2 += (2 * TMath::Pi()); + } else if (phi2 > TMath::Pi()) { + phi2 -= (2 * TMath::Pi()); + } + T deltaPhi = phi2 - phi1; + if (deltaPhi < -TMath::Pi()) { + deltaPhi += (2 * TMath::Pi()); + } else if (deltaPhi > TMath::Pi()) { + deltaPhi -= (2 * TMath::Pi()); + } + return deltaPhi; + } + + void init(InitContext const&) + { + hJetPt.setObject(new TH1F("h_jet_pt", "jet p_{T};jet p_{T} (GeV/#it{c})", + 100, 0., 100.)); + hHadronPt.setObject(new TH1F("h_hadron_pt", "hadron p_{T};hadron p_{T} (GeV/#it{c})", + 120, 0., 60.)); + hJetHadronDeltaPhi.setObject(new TH1F("h_jet_hadron_deltaphi", "jet #eta;#eta", + 40, 0.0, 4.)); + } + + void process(aod::Collision const& collision, + soa::Filtered<aod::Tracks> const& tracks) + { + + jets.clear(); + inputParticles.clear(); + auto trackTTPhi = 0.0; + auto trackTTPt = 0.0; + auto comparisonPt = 0.0; + bool isTT = false; + for (auto& track : tracks) { + if (track.pt() >= f_trackTTMin && track.pt() < f_trackTTMax) { //can this also go into a partition? + isTT = true; + if (track.pt() >= comparisonPt) { //currently take highest pT but later to randomise + comparisonPt = track.pt(); + trackTTPt = track.pt(); + trackTTPhi = track.phi(); + } + } + auto energy = std::sqrt(track.p() * track.p() + JetFinder::mPion * JetFinder::mPion); + inputParticles.emplace_back(track.px(), track.py(), track.pz(), energy); + inputParticles.back().set_user_index(track.globalIndex()); + } + if (!isTT) + return; + hHadronPt->Fill(trackTTPt); + + // you can set phi selector here for jets + fastjet::ClusterSequenceArea clusterSeq(jetFinder.findJets(inputParticles, jets)); + + for (const auto& jet : jets) { + auto deltaPhi = TMath::Abs(relativePhi(jet.phi(), trackTTPhi)); + if (deltaPhi >= (TMath::Pi() - f_recoilWindow)) { + hJetPt->Fill(jet.pt()); + } + if (deltaPhi >= TMath::Pi() / 2.0 && deltaPhi <= TMath::Pi()) { + hJetHadronDeltaPhi->Fill(deltaPhi); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<JetFinderHadronRecoilTask>("jet-finder-hadron-recoil")}; +} diff --git a/Analysis/Tasks/PWGJE/jetfinderhf.cxx b/Analysis/Tasks/PWGJE/jetfinderhf.cxx new file mode 100644 index 0000000000000..d32a7018e94b4 --- /dev/null +++ b/Analysis/Tasks/PWGJE/jetfinderhf.cxx @@ -0,0 +1,113 @@ +// 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. + +// jet finder task +// +// Author: Nima Zardoshti + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" + +#include "Analysis/HFSecondaryVertex.h" +#include "Analysis/HFCandidateSelectionTables.h" + +#include "fastjet/PseudoJet.hh" +#include "fastjet/ClusterSequenceArea.hh" + +#include "Analysis/Jet.h" +#include "Analysis/JetFinder.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct JetFinderHFTask { + Produces<o2::aod::Jets> jetsTable; + Produces<o2::aod::JetConstituents> constituents; + OutputObj<TH1F> hJetPt{"h_jet_pt"}; + OutputObj<TH1F> hD0Pt{"h_D0_pt"}; + + std::vector<fastjet::PseudoJet> jets; + std::vector<fastjet::PseudoJet> inputParticles; + JetFinder jetFinder; + + void init(InitContext const&) + { + hJetPt.setObject(new TH1F("h_jet_pt", "jet p_{T};p_{T} (GeV/#it{c})", + 100, 0., 100.)); + hD0Pt.setObject(new TH1F("h_D0_pt", "jet p_{T,D};p_{T,D} (GeV/#it{c})", + 60, 0., 60.)); + } + + Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; + Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + + //need enum as configurable + enum pdgCode { pdgD0 = 421 }; + + Filter trackCuts = (aod::track::pt > 0.15f && aod::track::eta > -0.9f && aod::track::eta < 0.9f); + Filter seltrack = (aod::hf_selcandidate::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate::isSelD0bar >= d_selectionFlagD0bar); + + void process(aod::Collision const& collision, + soa::Filtered<aod::Tracks> const& tracks, + soa::Filtered<soa::Join<aod::HfCandProng2, aod::HFSelD0Candidate>> const& candidates) + { + std::cout << "Per Event" << std::endl; + // TODO: retrieve pion mass from somewhere + bool isHFJet; + + //this loop should be made more efficient + for (auto& candidate : candidates) { + jets.clear(); + inputParticles.clear(); + for (auto& track : tracks) { + auto energy = std::sqrt(track.p() * track.p() + JetFinder::mPion * JetFinder::mPion); + if (candidate.index0().globalIndex() == track.globalIndex() || candidate.index1().globalIndex() == track.globalIndex()) { //is it global index? + continue; + } + inputParticles.emplace_back(track.px(), track.py(), track.pz(), energy); + inputParticles.back().set_user_index(track.globalIndex()); + } + inputParticles.emplace_back(candidate.px(), candidate.py(), candidate.pz(), candidate.e(RecoDecay::getMassPDG(pdgD0))); + inputParticles.back().set_user_index(1); + + fastjet::ClusterSequenceArea clusterSeq(jetFinder.findJets(inputParticles, jets)); + + for (const auto& jet : jets) { + isHFJet = false; + for (const auto& constituent : jet.constituents()) { + if (constituent.user_index() == 1 && (candidate.isSelD0() == 1 || candidate.isSelD0bar() == 1)) { + isHFJet = true; + break; + } + } + if (isHFJet) { + jetsTable(collision, jet.eta(), jet.phi(), jet.pt(), + jet.area(), jet.E(), jet.m()); + for (const auto& constituent : jet.constituents()) { + constituents(jetsTable.lastIndex(), constituent.user_index()); + } + hJetPt->Fill(jet.pt()); + std::cout << "Filling" << std::endl; + hD0Pt->Fill(candidate.pt()); + break; + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<JetFinderHFTask>("jet-finder-hf")}; +} diff --git a/Analysis/Tasks/PWGJE/jetskimming.cxx b/Analysis/Tasks/PWGJE/jetskimming.cxx new file mode 100644 index 0000000000000..490ce1e284e3b --- /dev/null +++ b/Analysis/Tasks/PWGJE/jetskimming.cxx @@ -0,0 +1,69 @@ +// 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. + +// 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. + +// jet skimming task +// +// Author: Nima Zardoshti + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace jetskim +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Energy, energy, float); +} // namespace jetskim +DECLARE_SOA_TABLE(JetSkim, "AOD", "JETSKIM1", + jetskim::CollisionId, + jetskim::Pt, jetskim::Eta, jetskim::Phi, jetskim::Energy); +} // namespace o2::aod + +struct JetSkimmingTask1 { + Produces<o2::aod::JetSkim> skim; + + Filter trackCuts = aod::track::pt > 0.15f; + float mPionSquared = 0.139 * 0.139; + + void process(aod::Collision const& collision, + soa::Filtered<aod::Tracks> const& tracks) + { + for (auto& track : tracks) { + float energy = std::sqrt(track.p() * track.p() + mPionSquared); + skim(collision, track.pt(), track.eta(), track.phi(), energy); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<JetSkimmingTask1>("jet-skimmer")}; +} diff --git a/Analysis/Tasks/PWGJE/jetsubstructure.cxx b/Analysis/Tasks/PWGJE/jetsubstructure.cxx new file mode 100644 index 0000000000000..5a51b6e739e03 --- /dev/null +++ b/Analysis/Tasks/PWGJE/jetsubstructure.cxx @@ -0,0 +1,124 @@ +// 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. + +// jet analysis tasks (subscribing to jet finder task) +// +// Author: Nima Zardoshti +// + +#include "TH1F.h" +#include "TTree.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" + +#include "Analysis/Jet.h" +#include "Analysis/JetFinder.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace jetsubstructure +{ +DECLARE_SOA_COLUMN(Zg, zg, float); +DECLARE_SOA_COLUMN(Rg, rg, float); +DECLARE_SOA_COLUMN(Nsd, nsd, float); +} // namespace jetsubstructure +DECLARE_SOA_TABLE(JetSubtructure, "AOD", "JETSUBSTRUCTURE", jetsubstructure::Zg, jetsubstructure::Rg, jetsubstructure::Nsd); +} // namespace o2::aod + +struct JetSubstructure { + Produces<aod::JetSubtructure> jetSubstructure; + OutputObj<TH1F> hZg{"h_jet_zg"}; + OutputObj<TH1F> hRg{"h_jet_rg"}; + OutputObj<TH1F> hNsd{"h_jet_nsd"}; + + Configurable<float> f_jetPtMin{"f_jetPtMin", 0.0, "minimum jet pT cut"}; + Configurable<float> f_zCut{"f_zCut", 0.1, "soft drop z cut"}; + Configurable<float> f_beta{"f_beta", 0.0, "soft drop beta"}; + Configurable<float> f_jetR{"f_jetR", 0.4, "jer resolution parameter"}; //possible to get configurable from another task? jetR + Configurable<bool> b_DoConstSub{"b_DoConstSub", false, "do constituent subtraction"}; + + std::vector<fastjet::PseudoJet> jetConstituents; + std::vector<fastjet::PseudoJet> jetReclustered; + JetFinder jetReclusterer; + + void init(InitContext const&) + { + hZg.setObject(new TH1F("h_jet_zg", "zg ;zg", + 10, 0.0, 0.5)); + hRg.setObject(new TH1F("h_jet_rg", "rg ;rg", + 10, 0.0, 0.5)); + hNsd.setObject(new TH1F("h_jet_nsd", "nsd ;nsd", + 7, -0.5, 6.5)); + jetReclusterer.isReclustering = true; + jetReclusterer.algorithm = fastjet::JetAlgorithm::cambridge_algorithm; + jetReclusterer.jetR = f_jetR * 2.5; + } + + //Filter jetCuts = aod::jet::pt > f_jetPtMin; //how does this work? + + void process(aod::Jet const& jet, + aod::Tracks const& tracks, + aod::JetConstituents const& constituents, + aod::JetConstituentsSub const& constituentsSub) + { + jetConstituents.clear(); + jetReclustered.clear(); + if (b_DoConstSub) { + for (const auto constituent : constituentsSub) { + fillConstituents(constituent, jetConstituents); + } + } else { + for (const auto constituentIndex : constituents) { + auto constituent = constituentIndex.track(); + fillConstituents(constituent, jetConstituents); + } + } + fastjet::ClusterSequenceArea clusterSeq(jetReclusterer.findJets(jetConstituents, jetReclustered)); + jetReclustered = sorted_by_pt(jetReclustered); + fastjet::PseudoJet daughterSubJet = jetReclustered[0]; + fastjet::PseudoJet parentSubJet1; + fastjet::PseudoJet parentSubJet2; + bool softDropped = false; + int nsd = 0.0; + auto zg = -1.0; + auto rg = -1.0; + while (daughterSubJet.has_parents(parentSubJet1, parentSubJet2)) { + if (parentSubJet1.perp() < parentSubJet2.perp()) + std::swap(parentSubJet1, parentSubJet2); + auto z = parentSubJet2.perp() / (parentSubJet1.perp() + parentSubJet2.perp()); + auto r = parentSubJet1.delta_R(parentSubJet2); + if (z >= f_zCut * TMath::Power(r / f_jetR, f_beta)) { + if (!softDropped) { + zg = z; + rg = r; + hZg->Fill(zg); + hRg->Fill(rg); + softDropped = true; + } + nsd++; + } + daughterSubJet = parentSubJet1; + } + hNsd->Fill(nsd); + jetSubstructure(zg, rg, nsd); + } +}; +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<JetSubstructure>("jet-substructure")}; +} diff --git a/Analysis/Tasks/jetfinder.cxx b/Analysis/Tasks/jetfinder.cxx deleted file mode 100644 index 7145cd58541c0..0000000000000 --- a/Analysis/Tasks/jetfinder.cxx +++ /dev/null @@ -1,125 +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. - -// jet finder task -// -// Author: Jochen Klein - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/AreaDefinition.hh" -#include "fastjet/JetDefinition.hh" -#include "fastjet/tools/JetMedianBackgroundEstimator.hh" -#include "fastjet/tools/Subtractor.hh" - -#include "Analysis/Jet.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -struct JetFinderTask { - Produces<o2::aod::Jets> jets; - Produces<o2::aod::JetConstituents> constituents; - - // options for jet finding - Configurable<float> rParam{"rParam", 0.4, "jet radius"}; - Configurable<float> ghostEtamax{"ghostEtamax", 1.0, "eta max for ghosts"}; - Configurable<float> minJetPt{"minJetPt", 0., "minimum jet pt"}; - // TODO: initialize with 0.9 - rParam (requires lazy evaluation) - Configurable<float> maxJetEta{"maxJetEta", 0.5, "eta range for jets"}; - // TODO: use configurables also for enums - fastjet::JetAlgorithm algorithm{fastjet::antikt_algorithm}; - fastjet::RecombinationScheme recombScheme{fastjet::E_scheme}; - fastjet::Strategy strategy{fastjet::Best}; - fastjet::AreaType areaType{fastjet::passive_area}; - fastjet::GhostedAreaSpec ghostSpec{ghostEtamax}; - fastjet::AreaDefinition areaDef{areaType, ghostSpec}; - fastjet::JetDefinition jetDef{algorithm, rParam, recombScheme, strategy}; - fastjet::Selector selJet = fastjet::SelectorPtMin(minJetPt) && - fastjet::SelectorAbsRapMax(maxJetEta); - - // options for background subtraction - enum class BkgMode { none, - rhoArea }; - BkgMode bkgMode = BkgMode::none; - Configurable<double> rParamBkg{"rParamBkg", 0.2, "jet radius for background"}; - Configurable<double> rapBkg{"rapBkg", .9, "rapidity range for background"}; - // TODO: use configurables also for enums - fastjet::JetAlgorithm algorithmBkg{fastjet::kt_algorithm}; - fastjet::RecombinationScheme recombSchemeBkg{fastjet::E_scheme}; - fastjet::JetDefinition jetDefBkg{algorithmBkg, rParamBkg, recombSchemeBkg, strategy}; - fastjet::AreaDefinition areaDefBkg{areaType, ghostSpec}; - fastjet::Selector selBkg = fastjet::SelectorAbsRapMax(rapBkg); - - // TODO: use values from configurables - // TODO: add eta cuts - Filter trackCuts = aod::track::pt > 0.1f; - - std::unique_ptr<fastjet::BackgroundEstimatorBase> bge; - std::unique_ptr<fastjet::Subtractor> sub; - - std::vector<fastjet::PseudoJet> pJets; - - void init(InitContext const&) - { - if (bkgMode == BkgMode::none) { - } else if (bkgMode == BkgMode::rhoArea) { - bge = decltype(bge)(new fastjet::JetMedianBackgroundEstimator(selBkg, jetDefBkg, areaDefBkg)); - sub = decltype(sub){new fastjet::Subtractor{bge.get()}}; - } else { - LOGF(ERROR, "requested subtraction mode not implemented!"); - } - } - - void process(aod::Collision const& collision, - soa::Filtered<aod::Tracks> const& fullTracks) - { - // TODO: retrieve pion mass from somewhere - const float mPionSquared = 0.139 * 0.139; - - pJets.clear(); - - std::vector<fastjet::PseudoJet> inputParticles; - for (auto& track : fullTracks) { - auto energy = std::sqrt(track.p() * track.p() + mPionSquared); - inputParticles.emplace_back(track.px(), track.py(), track.pz(), energy); - inputParticles.back().set_user_index(track.globalIndex()); - } - - fastjet::ClusterSequenceArea clust_seq(inputParticles, jetDef, areaDef); - if (bge) - bge->set_particles(inputParticles); - pJets = sub ? (*sub)(clust_seq.inclusive_jets()) : clust_seq.inclusive_jets(); - - pJets = selJet(pJets); - - for (const auto& pjet : pJets) { - jets(collision, pjet.eta(), pjet.phi(), pjet.pt(), - pjet.area(), pjet.Et(), pjet.m()); - for (const auto& track : pjet.constituents()) { - LOGF(DEBUG, "jet %d constituent %d: %f %f %f", jets.lastIndex(), - track.user_index(), track.eta(), track.phi(), track.pt()); - constituents(jets.lastIndex(), track.user_index()); - } - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<JetFinderTask>("jet-finder")}; -} From 1856793e505d9a38c20573dc44cb7e1e1c6d49da Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Wed, 14 Oct 2020 09:35:28 +0200 Subject: [PATCH 0946/1751] cut lines manually for clang-format --- Analysis/Tasks/trackchecks.cxx | 78 ++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/trackchecks.cxx index d9c40dc885505..e8d994ae15f1a 100644 --- a/Analysis/Tasks/trackchecks.cxx +++ b/Analysis/Tasks/trackchecks.cxx @@ -76,22 +76,28 @@ struct TrackCheckTaskEvSel { Configurable<double> cfgCutY{"cfgCutY", 0.5, "option to configure rapidity cut"}; Configurable<float> cfgCutVZ{"cfgCutVZ", 10.f, "option to configure z-vertex cut"}; OutputObj<TH1F> hTrkPrimAftEvSel{TH1F("hTrkPrimAftEvSel", - "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)}; + "Reco Prim tracks AftEvSel (charged); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)}; OutputObj<HistArray> hTrkPrimAftEvSel_truepid{HistArray("hTrkPrimAftEvSel_truepid"), OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { hTrkPrimAftEvSel_truepid->Add<kEl>(TH1F("hTrkPrimAftEvSel_truepid_el", - "Generated tracks after event selection (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Gen tracks aft. ev. sel. (true El); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kPi>(TH1F("hTrkPrimAftEvSel_truepid_pi", - "Generated tracks after event selection (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Gen tracks aft. ev. sel. (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kKa>(TH1F("hTrkPrimAftEvSel_truepid_ka", - "Generated tracks after event selection (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Gen. tracks aft. ev. sel. (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kPr>(TH1F("hTrkPrimAftEvSel_truepid_pr", - "Generated tracks after event selection (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Gen tracks aft. ev. sel. (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimAftEvSel_truepid->Add<kDe>(TH1F("hTrkPrimAftEvSel_truepid_de", - "Generated tracks after event selection (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Gen tracks aft. ev. sel. (true De); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); } //init //Filters @@ -162,48 +168,68 @@ struct TrackCheckTaskEvSelTrackSel { void init(InitContext&) { hTrkPrimReco_truepid->Add<kEl>(TH1F("hTrkPrimReco_truepid_el", - "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true El); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kPi>(TH1F("hTrkPrimReco_truepid_pi", - "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Pi); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kKa>(TH1F("hTrkPrimReco_truepid_ka", - "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Ka); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kPr>(TH1F("hTrkPrimReco_truepid_pr", - "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true Pr); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hTrkPrimReco_truepid->Add<kDe>(TH1F("hTrkPrimReco_truepid_de", - "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", NPTBINS, pt_bins)); + "Primary Reco tracks (true De); #it{p}_{T} (GeV/#it{c}); Counts", + NPTBINS, pt_bins)); hDCAxyReco_truepid->Add<kEl>(TH2F("hDCAxyReco_truepid_el", - "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kPi>(TH2F("hDCAxyReco_truepid_pi", - "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kKa>(TH2F("hDCAxyReco_truepid_ka", - "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kPr>(TH2F("hDCAxyReco_truepid_pr", - "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyReco_truepid->Add<kDe>(TH2F("hDCAxyReco_truepid_de", - "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy reco (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kEl>(TH2F("hDCAxyPrim_truepid_el", - "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kPi>(TH2F("hDCAxyPrim_truepid_pi", - "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kKa>(TH2F("hDCAxyPrim_truepid_ka", - "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kPr>(TH2F("hDCAxyPrim_truepid_pr", - "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxyPrim_truepid->Add<kDe>(TH2F("hDCAxyPrim_truepid_de", - "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy primaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kEl>(TH2F("hDCAxySeco_truepid_el", - "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true El); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kPi>(TH2F("hDCAxySeco_truepid_pi", - "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Pi); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kKa>(TH2F("hDCAxySeco_truepid_ka", - "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Ka); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kPr>(TH2F("hDCAxySeco_truepid_pr", - "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true Pr); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); hDCAxySeco_truepid->Add<kDe>(TH2F("hDCAxySeco_truepid_de", - "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", NPTBINS, pt_bins, 800, -4., 4.)); + "DCAxy secondaries (true De); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", + NPTBINS, pt_bins, 800, -4., 4.)); } //init From 959e32de0f54c490211a4b53fcc800736e6d9a4d Mon Sep 17 00:00:00 2001 From: Iouri Belikov <iouri.belikov@cern.ch> Date: Tue, 6 Oct 2020 18:16:00 +0200 Subject: [PATCH 0947/1751] A workflow to write clusters to a file --- Detectors/ITSMFT/ITS/workflow/CMakeLists.txt | 6 ++++ .../ITSWorkflow/ClusterWriterWorkflow.h | 30 ++++++++++++++++ .../workflow/src/ClusterWriterWorkflow.cxx | 35 +++++++++++++++++++ .../src/its-cluster-writer-workflow.cxx | 33 +++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h create mode 100644 Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx create mode 100644 Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx diff --git a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt index 790d7390334f0..60788887fd94f 100644 --- a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt @@ -10,6 +10,7 @@ o2_add_library(ITSWorkflow SOURCES src/RecoWorkflow.cxx + src/ClusterWriterWorkflow.cxx src/DigitReaderSpec.cxx src/ClustererSpec.cxx src/ClusterWriterSpec.cxx @@ -33,3 +34,8 @@ o2_add_executable(reco-workflow COMPONENT_NAME its PUBLIC_LINK_LIBRARIES O2::ITSWorkflow) +o2_add_executable(cluster-writer-workflow + SOURCES src/its-cluster-writer-workflow.cxx + COMPONENT_NAME its + PUBLIC_LINK_LIBRARIES O2::ITSWorkflow) + diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h new file mode 100644 index 0000000000000..3ac0c47d5e9c9 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h @@ -0,0 +1,30 @@ +// 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_ITS_CLUSTER_WRITER_WORKFLOW_H +#define O2_ITS_CLUSTER_WRITER_WORKFLOW_H + +/// @file ClusterWriterWorkflow.h + +#include "Framework/WorkflowSpec.h" + +namespace o2 +{ +namespace its +{ + +namespace cluster_writer_workflow +{ +framework::WorkflowSpec getWorkflow(bool useMC); +} + +} // namespace its +} // namespace o2 +#endif diff --git a/Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx new file mode 100644 index 0000000000000..1330f30f7e42c --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx @@ -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. + +/// @file ClusterWriterWorkflow.cxx + +#include "ITSWorkflow/ClusterWriterWorkflow.h" +#include "ITSWorkflow/ClusterWriterSpec.h" + +namespace o2 +{ +namespace its +{ + +namespace cluster_writer_workflow +{ + +framework::WorkflowSpec getWorkflow(bool useMC) +{ + framework::WorkflowSpec specs; + + specs.emplace_back(o2::its::getClusterWriterSpec(useMC)); + + return specs; +} + +} // namespace cluster_writer_workflow +} // namespace its +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx new file mode 100644 index 0000000000000..92c538b24283a --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx @@ -0,0 +1,33 @@ +// 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 "ITSWorkflow/ClusterWriterWorkflow.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back( + ConfigParamSpec{ + "disable-mc", + o2::framework::VariantType::Bool, + false, + {"disable MC propagation even if available"}}); +} + +#include "Framework/runDataProcessing.h" +#include "Framework/Logger.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + auto useMC = !configcontext.options().get<bool>("disable-mc"); + return std::move(o2::its::cluster_writer_workflow::getWorkflow(useMC)); +} From 5e5d1b17d8c05fd5b17750fb67181eb3debde607 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen <evgeny.kryshen@cern.ch> Date: Wed, 14 Oct 2020 14:46:42 +0300 Subject: [PATCH 0948/1751] Added T0 timing and multiplicity (#4588) * Resolve conflicts * Updated access to V0,ZDC and FDD * Added T0 timing and multiplicity --- .../include/Analysis/EventSelection.h | 4 ++++ .../DataModel/include/Analysis/Multiplicity.h | 5 ++++- Analysis/Tasks/eventSelection.cxx | 15 +++++++++++-- Analysis/Tasks/eventSelectionQa.cxx | 21 ++++++++++++++++++- Analysis/Tasks/multiplicityQa.cxx | 7 ++++++- Analysis/Tasks/multiplicityTable.cxx | 17 ++++++++++++--- 6 files changed, 61 insertions(+), 8 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/EventSelection.h b/Analysis/DataModel/include/Analysis/EventSelection.h index aacb72c017688..198db13e00b7a 100644 --- a/Analysis/DataModel/include/Analysis/EventSelection.h +++ b/Analysis/DataModel/include/Analysis/EventSelection.h @@ -19,6 +19,8 @@ namespace evsel { // TODO bool arrays are not supported? Storing in int32 for the moment DECLARE_SOA_COLUMN(Alias, alias, int32_t[kNaliases]); +DECLARE_SOA_COLUMN(BBT0A, bbT0A, bool); // beam-beam time in T0A +DECLARE_SOA_COLUMN(BBT0C, bbT0C, bool); // beam-beam time in T0C DECLARE_SOA_COLUMN(BBV0A, bbV0A, bool); // beam-beam time in V0A DECLARE_SOA_COLUMN(BBV0C, bbV0C, bool); // beam-beam time in V0C DECLARE_SOA_COLUMN(BGV0A, bgV0A, bool); // beam-gas time in V0A @@ -30,9 +32,11 @@ DECLARE_SOA_COLUMN(BBFDC, bbFDC, bool); // beam-beam time in FDC DECLARE_SOA_COLUMN(BGFDA, bgFDA, bool); // beam-gas time in FDA DECLARE_SOA_COLUMN(BGFDC, bgFDC, bool); // beam-gas time in FDC DECLARE_SOA_DYNAMIC_COLUMN(SEL7, sel7, [](bool bbV0A, bool bbV0C, bool bbZNA, bool bbZNC) -> bool { return bbV0A && bbV0C && bbZNA && bbZNC; }); +DECLARE_SOA_DYNAMIC_COLUMN(SEL8, sel8, [](bool bbT0A, bool bbT0C, bool bbZNA, bool bbZNC) -> bool { return bbT0A && bbT0C && bbZNA && bbZNC; }); } // namespace evsel DECLARE_SOA_TABLE(EvSels, "AOD", "EVSEL", evsel::Alias, + evsel::BBT0A, evsel::BBT0C, evsel::BBV0A, evsel::BBV0C, evsel::BGV0A, evsel::BGV0C, evsel::BBZNA, evsel::BBZNC, evsel::BBFDA, evsel::BBFDC, evsel::BGFDA, evsel::BGFDC, evsel::SEL7<evsel::BBV0A, evsel::BBV0C, evsel::BBZNA, evsel::BBZNC>); diff --git a/Analysis/DataModel/include/Analysis/Multiplicity.h b/Analysis/DataModel/include/Analysis/Multiplicity.h index 004ad2c8e2976..bb4b4aadccf51 100644 --- a/Analysis/DataModel/include/Analysis/Multiplicity.h +++ b/Analysis/DataModel/include/Analysis/Multiplicity.h @@ -18,13 +18,16 @@ namespace mult { DECLARE_SOA_COLUMN(MultV0A, multV0A, float); DECLARE_SOA_COLUMN(MultV0C, multV0C, float); +DECLARE_SOA_COLUMN(MultT0A, multT0A, float); +DECLARE_SOA_COLUMN(MultT0C, multT0C, float); DECLARE_SOA_COLUMN(MultZNA, multZNA, float); DECLARE_SOA_COLUMN(MultZNC, multZNC, float); DECLARE_SOA_DYNAMIC_COLUMN(MultV0M, multV0M, [](float multV0A, float multV0C) -> float { return multV0A + multV0C; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultT0M, multT0M, [](float multT0A, float multT0C) -> float { return multT0A + multT0C; }); DECLARE_SOA_COLUMN(MultTracklets, multTracklets, int); } // namespace mult -DECLARE_SOA_TABLE(Mults, "AOD", "MULT", mult::MultV0A, mult::MultV0C, mult::MultZNA, mult::MultZNC, mult::MultV0M<mult::MultV0A, mult::MultV0C>, mult::MultTracklets); +DECLARE_SOA_TABLE(Mults, "AOD", "MULT", mult::MultV0A, mult::MultV0C, mult::MultT0A, mult::MultT0C, mult::MultZNA, mult::MultZNC, mult::MultV0M<mult::MultV0A, mult::MultV0C>, mult::MultT0M<mult::MultT0A, mult::MultT0C>, mult::MultTracklets); using Mult = Mults::iterator; } // namespace o2::aod diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index d29c768b9b557..084ec4dc02404 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -49,6 +49,12 @@ struct EvSelParameters { float fZNABBupper = 2.0; // ns float fZNCBBlower = -2.0; // ns float fZNCBBupper = 2.0; // ns + + // TODO rough cuts to be adjusted + float fT0ABBlower = -2.0; // ns + float fT0ABBupper = 2.0; // ns + float fT0CBBlower = -2.0; // ns + float fT0CBBupper = 2.0; // ns }; struct EventSelectionTask { @@ -65,7 +71,7 @@ struct EventSelectionTask { ccdb->setLocalObjectValidityChecking(); } - void process(aod::Run2MatchedSparse::iterator const& collision, aod::BCsWithTimestamps const&, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FDDs const& fdds) + void process(aod::Run2MatchedSparse::iterator const& collision, aod::BCsWithTimestamps const&, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FT0s const& ft0s, aod::FDDs const& fdds) { auto bc = collision.bc_as<aod::BCsWithTimestamps>(); LOGF(debug, "timestamp=%llu", bc.timestamp()); @@ -88,12 +94,15 @@ struct EventSelectionTask { float timeZNC = collision.has_zdc() ? collision.zdc().timeZNC() : -999.f; float timeV0A = collision.has_fv0a() ? collision.fv0a().time() : -999.f; float timeV0C = collision.has_fv0c() ? collision.fv0c().time() : -999.f; + float timeT0A = collision.has_ft0() ? collision.ft0().timeA() : -999.f; + float timeT0C = collision.has_ft0() ? collision.ft0().timeC() : -999.f; float timeFDA = collision.has_fdd() ? collision.fdd().timeA() : -999.f; float timeFDC = collision.has_fdd() ? collision.fdd().timeC() : -999.f; LOGF(debug, "timeZNA=%f timeZNC=%f", timeZNA, timeZNC); LOGF(debug, "timeV0A=%f timeV0C=%f", timeV0A, timeV0C); LOGF(debug, "timeFDA=%f timeFDC=%f", timeFDA, timeFDC); + LOGF(debug, "timeT0A=%f timeT0C=%f", timeT0A, timeT0C); bool bbZNA = timeZNA > par.fZNABBlower && timeZNA < par.fZNABBupper; bool bbZNC = timeZNC > par.fZNCBBlower && timeZNC < par.fZNCBBupper; @@ -105,6 +114,8 @@ struct EventSelectionTask { bool bbFDC = timeFDC > par.fFDCBBlower && timeFDC < par.fFDCBBupper; bool bgFDA = timeFDA > par.fFDABGlower && timeFDA < par.fFDABGupper; bool bgFDC = timeFDC > par.fFDCBGlower && timeFDC < par.fFDCBGupper; + bool bbT0A = timeT0A > par.fT0ABBlower && timeT0A < par.fT0ABBupper; + bool bbT0C = timeT0C > par.fT0CBBlower && timeT0C < par.fT0CBBupper; if (isMC) { bbZNA = 1; @@ -112,7 +123,7 @@ struct EventSelectionTask { } // Fill event selection columns - evsel(alias, bbV0A, bbV0C, bgV0A, bgV0C, bbZNA, bbZNC, bbFDA, bbFDC, bgFDA, bgFDC); + evsel(alias, bbT0A, bbT0C, bbV0A, bbV0C, bgV0A, bgV0C, bbZNA, bbZNC, bbFDA, bbFDC, bgFDA, bgFDC); } }; diff --git a/Analysis/Tasks/eventSelectionQa.cxx b/Analysis/Tasks/eventSelectionQa.cxx index ec82a9dab9213..84810129d813f 100644 --- a/Analysis/Tasks/eventSelectionQa.cxx +++ b/Analysis/Tasks/eventSelectionQa.cxx @@ -43,6 +43,15 @@ struct EventSelectionTask { return dummy; } + aod::FT0 getFT0(aod::BC const& bc, aod::FT0s const& ft0s) + { + for (auto& ft0 : ft0s) + if (ft0.bc() == bc) + return ft0; + aod::FT0 dummy; + return dummy; + } + aod::FDD getFDD(aod::BC const& bc, aod::FDDs const& fdds) { for (auto& fdd : fdds) @@ -56,18 +65,22 @@ struct EventSelectionTask { OutputObj<TH1F> hTimeV0Call{TH1F("hTimeV0Call", "", 200, -50., 50.)}; OutputObj<TH1F> hTimeZNAall{TH1F("hTimeZNAall", "", 250, -25., 25.)}; OutputObj<TH1F> hTimeZNCall{TH1F("hTimeZNCall", "", 250, -25., 25.)}; + OutputObj<TH1F> hTimeT0Aall{TH1F("hTimeT0Aall", "", 200, -10., 10.)}; + OutputObj<TH1F> hTimeT0Call{TH1F("hTimeT0Call", "", 200, -10., 10.)}; OutputObj<TH1F> hTimeFDAall{TH1F("hTimeFDAall", "", 1000, -100., 100.)}; OutputObj<TH1F> hTimeFDCall{TH1F("hTimeFDCall", "", 1000, -100., 100.)}; OutputObj<TH1F> hTimeV0Aacc{TH1F("hTimeV0Aacc", "", 200, -50., 50.)}; OutputObj<TH1F> hTimeV0Cacc{TH1F("hTimeV0Cacc", "", 200, -50., 50.)}; OutputObj<TH1F> hTimeZNAacc{TH1F("hTimeZNAacc", "", 250, -25., 25.)}; OutputObj<TH1F> hTimeZNCacc{TH1F("hTimeZNCacc", "", 250, -25., 25.)}; + OutputObj<TH1F> hTimeT0Aacc{TH1F("hTimeT0Aacc", "", 200, -10., 10.)}; + OutputObj<TH1F> hTimeT0Cacc{TH1F("hTimeT0Cacc", "", 200, -10., 10.)}; OutputObj<TH1F> hTimeFDAacc{TH1F("hTimeFDAacc", "", 1000, -100., 100.)}; OutputObj<TH1F> hTimeFDCacc{TH1F("hTimeFDCacc", "", 1000, -100., 100.)}; Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; - void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FDDs fdds) + void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FT0s ft0s, aod::FDDs fdds) { if (!isMC && !col.alias()[kINT7]) return; @@ -81,6 +94,10 @@ struct EventSelectionTask { hTimeZNAall->Fill(zdc.timeZNA()); hTimeZNCall->Fill(zdc.timeZNC()); + auto ft0 = getFT0(col.bc(), ft0s); + hTimeT0Aall->Fill(ft0.timeA()); + hTimeT0Call->Fill(ft0.timeC()); + auto fdd = getFDD(col.bc(), fdds); hTimeFDAall->Fill(fdd.timeA()); hTimeFDCall->Fill(fdd.timeC()); @@ -92,6 +109,8 @@ struct EventSelectionTask { hTimeV0Cacc->Fill(fv0c.time()); hTimeZNAacc->Fill(zdc.timeZNA()); hTimeZNCacc->Fill(zdc.timeZNC()); + hTimeT0Aacc->Fill(ft0.timeA()); + hTimeT0Cacc->Fill(ft0.timeC()); hTimeFDAacc->Fill(fdd.timeA()); hTimeFDCacc->Fill(fdd.timeC()); } diff --git a/Analysis/Tasks/multiplicityQa.cxx b/Analysis/Tasks/multiplicityQa.cxx index 0159a6e9e7e17..a4ab0cc1bd7fc 100644 --- a/Analysis/Tasks/multiplicityQa.cxx +++ b/Analysis/Tasks/multiplicityQa.cxx @@ -13,14 +13,17 @@ #include "Analysis/Multiplicity.h" #include "Analysis/EventSelection.h" #include "TH1F.h" +#include "TH2F.h" using namespace o2; using namespace o2::framework; struct MultiplicityQaTask { OutputObj<TH1F> hMultV0M{TH1F("hMultV0M", "", 50000, 0., 50000.)}; + OutputObj<TH1F> hMultT0M{TH1F("hMultT0M", "", 10000, 0., 200000.)}; OutputObj<TH1F> hMultZNA{TH1F("hMultZNA", "", 600, 0., 240000.)}; OutputObj<TH1F> hMultZNC{TH1F("hMultZNC", "", 600, 0., 240000.)}; + OutputObj<TH2F> hMultV0MvsT0M{TH2F("hMultV0MvsT0M", ";V0M;T0M", 200, 0., 50000., 200, 0., 200000.)}; OutputObj<TProfile> hMultNtrackletsVsV0M{TProfile("hMultNtrackletsVsV0M", "", 50000, 0., 50000.)}; @@ -31,11 +34,13 @@ struct MultiplicityQaTask { if (!col.sel7()) return; - LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multV0M=%5.0f", col.multV0A(), col.multV0C(), col.multV0M()); + LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multV0M=%5.0f multT0A=%5.0f multT0C=%5.0f multT0M=%5.0f", col.multV0A(), col.multV0C(), col.multV0M(), col.multT0A(), col.multT0C(), col.multT0M()); // fill calibration histos hMultV0M->Fill(col.multV0M()); + hMultT0M->Fill(col.multT0M()); hMultZNA->Fill(col.multZNA()); hMultZNC->Fill(col.multZNC()); + hMultV0MvsT0M->Fill(col.multV0M(), col.multT0M()); hMultNtrackletsVsV0M->Fill(col.multV0M(), col.multTracklets()); } }; diff --git a/Analysis/Tasks/multiplicityTable.cxx b/Analysis/Tasks/multiplicityTable.cxx index f9bd0adeaabad..e79d2f70e21a6 100644 --- a/Analysis/Tasks/multiplicityTable.cxx +++ b/Analysis/Tasks/multiplicityTable.cxx @@ -20,10 +20,12 @@ struct MultiplicityTableTaskIndexed { Produces<aod::Mults> mult; Partition<aod::Tracks> tracklets = (aod::track::trackType == static_cast<uint8_t>(o2::aod::track::TrackTypeEnum::Run2Tracklet)); - void process(aod::Run2MatchedSparse::iterator const& collision, aod::Tracks const& tracks, aod::BCs const&, aod::Zdcs const&, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs) + void process(aod::Run2MatchedSparse::iterator const& collision, aod::Tracks const& tracks, aod::BCs const&, aod::Zdcs const&, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FT0s const& ft0s) { float multV0A = -1.f; float multV0C = -1.f; + float multT0A = -1.f; + float multT0C = -1.f; float multZNA = -1.f; float multZNC = -1.f; int multTracklets = tracklets.size(); @@ -40,13 +42,22 @@ struct MultiplicityTableTaskIndexed { multV0C += v0c.amplitude()[i]; } } + if (collision.has_ft0()) { + auto ft0 = collision.ft0(); + for (int i = 0; i < 96; i++) { + multT0A += ft0.amplitudeA()[i]; + } + for (int i = 0; i < 112; i++) { + multT0C += ft0.amplitudeC()[i]; + } + } if (collision.has_zdc()) { auto zdc = collision.zdc(); multZNA = zdc.energyCommonZNA(); multZNC = zdc.energyCommonZNC(); } - LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multZNA=%6.0f multZNC=%6.0f multTracklets=%i", multV0A, multV0C, multZNA, multZNC, multTracklets); - mult(multV0A, multV0C, multZNA, multZNC, multTracklets); + LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multT0A=%5.0f multT0C=%5.0f multZNA=%6.0f multZNC=%6.0f multTracklets=%i", multV0A, multV0C, multT0A, multT0C, multZNA, multZNC, multTracklets); + mult(multV0A, multV0C, multT0A, multT0C, multZNA, multZNC, multTracklets); } }; From 4e0e6b2951f941aad1901070ce692ed7410204a7 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Wed, 14 Oct 2020 15:08:31 +0200 Subject: [PATCH 0949/1751] fix alien reading (#4590) --- Framework/Core/src/DataInputDirector.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index dae6dc8762265..7fc76f451f84a 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -29,21 +29,23 @@ FileNameHolder* makeFileNameHolder(std::string fileName) auto fileNameHolder = new FileNameHolder(); fileNameHolder->fileName = fileName; - TFile file = TFile(fileName.c_str(), "R"); - if (!file.IsOpen()) { + TFile* file = TFile::Open(fileName.c_str(), "R"); + if (!file || !file->IsOpen()) { LOGP(ERROR, "\"{}\" can not be opened.", fileName); + delete file; return fileNameHolder; } // find TimeFrame folders std::regex TFRegex = std::regex("TF_[0-9]+"); - TList* keyList = file.GetListOfKeys(); + TList* keyList = file->GetListOfKeys(); for (auto key : *keyList) { if (std::regex_match(((TObjString*)key)->GetString().Data(), TFRegex)) { fileNameHolder->listOfTimeFrameKeys.emplace_back(std::string(((TObjString*)key)->GetString().Data())); } } fileNameHolder->numberOfTimeFrames = fileNameHolder->listOfTimeFrameKeys.size(); + delete file; return fileNameHolder; } From 3041283817220778a75ca11063908097f38704f0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 14 Oct 2020 15:59:48 +0200 Subject: [PATCH 0950/1751] Add missing include for ROOT 6.22 (#4593) --- Framework/Core/src/DataInputDirector.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 7fc76f451f84a..2713b0e61c5c8 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -17,6 +17,7 @@ #include "rapidjson/filereadstream.h" #include "TGrid.h" +#include "TObjString.h" namespace o2 { From 79548105a12e1d88fa5a11d47bb4d3e3f4d41046 Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Wed, 14 Oct 2020 16:04:09 +0200 Subject: [PATCH 0951/1751] A method to check if one InputSpec includes other (#4586) --- .../Core/include/Framework/DataSpecUtils.h | 3 +++ Framework/Core/src/DataSpecUtils.cxx | 27 +++++++++++++++++++ .../Core/test/unittest_DataSpecUtils.cxx | 24 +++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/Framework/Core/include/Framework/DataSpecUtils.h b/Framework/Core/include/Framework/DataSpecUtils.h index 6e35feed4c214..8af549a8f6642 100644 --- a/Framework/Core/include/Framework/DataSpecUtils.h +++ b/Framework/Core/include/Framework/DataSpecUtils.h @@ -188,6 +188,9 @@ struct DataSpecUtils { /// Build a DataDescriptMatcher which does not care about the subSpec and origin. static data_matcher::DataDescriptorMatcher dataDescriptorMatcherFrom(header::DataDescription const& origin); + + /// Checks if left includes right (or is equal to) + static bool includes(const InputSpec& left, const InputSpec& right); }; } // namespace framework diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index 9614c3cbc1163..f7b69e0d43cfa 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -561,4 +561,31 @@ std::optional<header::DataHeader::SubSpecificationType> DataSpecUtils::getOption spec.matcher); } +bool DataSpecUtils::includes(const InputSpec& left, const InputSpec& right) +{ + return std::visit( + overloaded{ + [&left](ConcreteDataMatcher const& rightMatcher) { + return match(left, rightMatcher); + }, + [&left](DataDescriptorMatcher const& rightMatcher) { + auto rightInfo = extractMatcherInfo(rightMatcher); + return std::visit( + overloaded{ + [&rightInfo](ConcreteDataMatcher const& leftMatcher) { + return rightInfo.hasUniqueOrigin && rightInfo.origin == leftMatcher.origin && + rightInfo.hasUniqueDescription && rightInfo.description == leftMatcher.description && + rightInfo.hasUniqueSubSpec && rightInfo.subSpec == leftMatcher.subSpec; + }, + [&rightInfo](DataDescriptorMatcher const& leftMatcher) { + auto leftInfo = extractMatcherInfo(leftMatcher); + return (!leftInfo.hasOrigin || (rightInfo.hasOrigin && leftInfo.origin == rightInfo.origin)) && + (!leftInfo.hasDescription || (rightInfo.hasDescription && leftInfo.description == rightInfo.description)) && + (!leftInfo.hasSubSpec || (rightInfo.hasSubSpec && leftInfo.subSpec == rightInfo.hasSubSpec)); + }}, + left.matcher); + }}, + right.matcher); +} + } // namespace o2::framework diff --git a/Framework/Core/test/unittest_DataSpecUtils.cxx b/Framework/Core/test/unittest_DataSpecUtils.cxx index 45c3c077ef80f..1327de30ebe0b 100644 --- a/Framework/Core/test/unittest_DataSpecUtils.cxx +++ b/Framework/Core/test/unittest_DataSpecUtils.cxx @@ -303,4 +303,28 @@ BOOST_AUTO_TEST_CASE(GettingConcreteMembers) BOOST_REQUIRE_EQUAL(justOriginInputSpec.size(), 1); BOOST_CHECK_EQUAL(DataSpecUtils::asConcreteOrigin(justOriginInputSpec.at(0)).as<std::string>(), "TST"); BOOST_CHECK_THROW(DataSpecUtils::asConcreteDataDescription(justOriginInputSpec.at(0)).as<std::string>(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(Includes) +{ + InputSpec concreteInput1{"binding", "TSET", "FOOO", 1, Lifetime::Timeframe}; + InputSpec concreteInput2{"binding", "TSET", "BAAAR", 1, Lifetime::Timeframe}; + InputSpec wildcardInput1{"binding", {"TSET", "FOOO"}, Lifetime::Timeframe}; + InputSpec wildcardInput2{"binding", {"TSET", "BAAAR"}, Lifetime::Timeframe}; + + // wildcard and concrete + BOOST_CHECK(DataSpecUtils::includes(wildcardInput1, concreteInput1)); + BOOST_CHECK(!DataSpecUtils::includes(wildcardInput1, concreteInput2)); + BOOST_CHECK(!DataSpecUtils::includes(concreteInput1, wildcardInput1)); + BOOST_CHECK(!DataSpecUtils::includes(concreteInput2, wildcardInput1)); + + // concrete and concrete + BOOST_CHECK(DataSpecUtils::includes(concreteInput1, concreteInput1)); + BOOST_CHECK(!DataSpecUtils::includes(concreteInput1, concreteInput2)); + BOOST_CHECK(!DataSpecUtils::includes(concreteInput2, concreteInput1)); + + // wildcard and wildcard + BOOST_CHECK(DataSpecUtils::includes(wildcardInput1, wildcardInput1)); + BOOST_CHECK(!DataSpecUtils::includes(wildcardInput1, wildcardInput2)); + BOOST_CHECK(!DataSpecUtils::includes(wildcardInput2, wildcardInput1)); } \ No newline at end of file From aaf8bd39a0e15690eef64e67bf8de78fd7d0da34 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 14 Oct 2020 16:42:04 +0200 Subject: [PATCH 0952/1751] DPL Analysis: tutorial task demonstrating configurable-wrapped class (#4537) --- Analysis/Tutorials/CMakeLists.txt | 13 +++++ .../include/Analysis/configurableCut.h | 42 ++++++++++++++ .../Tutorials/src/ConfigurableCutLinkDef.h | 15 +++++ Analysis/Tutorials/src/configurableCut.cxx | 43 ++++++++++++++ Analysis/Tutorials/src/configurableCut.json | 21 +++++++ .../Tutorials/src/configurableObjects.cxx | 58 +++++++++++++++++++ .../Core/include/Framework/Configurable.h | 52 ++++++++++++++--- Framework/Core/src/AnalysisManagers.h | 8 +-- 8 files changed, 240 insertions(+), 12 deletions(-) create mode 100644 Analysis/Tutorials/include/Analysis/configurableCut.h create mode 100644 Analysis/Tutorials/src/ConfigurableCutLinkDef.h create mode 100644 Analysis/Tutorials/src/configurableCut.cxx create mode 100644 Analysis/Tutorials/src/configurableCut.json create mode 100644 Analysis/Tutorials/src/configurableObjects.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index 76260b6ce453e..33fa1fe87785e 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -135,6 +135,19 @@ o2_add_dpl_workflow(histogram-registry PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) +o2_add_library(ConfigurableCut + SOURCES src/configurableCut.cxx + PUBLIC_LINK_LIBRARIES O2::AnalysisCore) + +o2_target_root_dictionary(ConfigurableCut + HEADERS include/Analysis/configurableCut.h + LINKDEF src/ConfigurableCutLinkDef.h) + +o2_add_dpl_workflow(configurable-objects + SOURCES src/configurableObjects.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::ConfigurableCut + COMPONENT_NAME AnalysisTutorial) + o2_add_dpl_workflow(muon-iteration SOURCES src/muonIteration.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h new file mode 100644 index 0000000000000..84737a67fb2dc --- /dev/null +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -0,0 +1,42 @@ +// 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 CONFIGURABLECUT_H +#define CONFIGURABLECUT_H + +#include <iosfwd> +#include <TMath.h> + +class configurableCut +{ + public: + configurableCut(float cut_ = 2., int state_ = 1) + : cut{cut_}, state{state_} + { + } + + bool method(float arg) const; + + void setCut(float cut_); + float getCut() const; + + void setState(int state_); + int getState() const; + + private: + float cut; + int state; + + ClassDef(configurableCut, 2); +}; + +std::ostream& operator<<(std::ostream& os, configurableCut const& c); + +#endif // CONFIGURABLECUT_H diff --git a/Analysis/Tutorials/src/ConfigurableCutLinkDef.h b/Analysis/Tutorials/src/ConfigurableCutLinkDef.h new file mode 100644 index 0000000000000..0760e732fb45f --- /dev/null +++ b/Analysis/Tutorials/src/ConfigurableCutLinkDef.h @@ -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. + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class configurableCut + ; diff --git a/Analysis/Tutorials/src/configurableCut.cxx b/Analysis/Tutorials/src/configurableCut.cxx new file mode 100644 index 0000000000000..fabca8db4b8cf --- /dev/null +++ b/Analysis/Tutorials/src/configurableCut.cxx @@ -0,0 +1,43 @@ +// 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 "Analysis/configurableCut.h" +#include <iostream> + +bool configurableCut::method(float arg) const +{ + return arg > cut; +} + +void configurableCut::setCut(float cut_) +{ + cut = cut_; +} + +float configurableCut::getCut() const +{ + return cut; +} + +std::ostream& operator<<(std::ostream& os, configurableCut const& c) +{ + os << "Cut value: " << c.getCut() << "; state: " << c.getState(); + return os; +} + +void configurableCut::setState(int state_) +{ + state = state_; +} + +int configurableCut::getState() const +{ + return state; +} diff --git a/Analysis/Tutorials/src/configurableCut.json b/Analysis/Tutorials/src/configurableCut.json new file mode 100644 index 0000000000000..33d4294b13286 --- /dev/null +++ b/Analysis/Tutorials/src/configurableCut.json @@ -0,0 +1,21 @@ +{ + "internal-dpl-clock": "", + "internal-dpl-aod-reader": { + "aod-file": "aod.root", + "time-limit": "0", + "start-value-enumeration": "0", + "end-value-enumeration": "-1", + "step-value-enumeration": "1" + }, + "internal-dpl-aod-spawner": "", + "configurable-demo": { + "cut": { + "cut": "0.1", + "state": "1" + }, + "mutable_cut": { + "cut": "0.2", + "state": "-1" + } + } +} diff --git a/Analysis/Tutorials/src/configurableObjects.cxx b/Analysis/Tutorials/src/configurableObjects.cxx new file mode 100644 index 0000000000000..5ae293436f981 --- /dev/null +++ b/Analysis/Tutorials/src/configurableObjects.cxx @@ -0,0 +1,58 @@ +// 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 "Analysis/configurableCut.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// This task demonstrates how to use configurable to wrap classes +/// use it with supplied configuration: "configurableObject.json" + +struct ConfigurableObjectDemo { + Configurable<configurableCut> cut{"cut", {0.5, 1}, "generic cut"}; + MutableConfigurable<configurableCut> mutable_cut{"mutable_cut", {1., 2}, "generic cut"}; + void init(InitContext const&){}; + void process(aod::Collision const&, aod::Tracks const& tracks) + { + LOGF(INFO, "Cut1: %.3f; Cut2: %.3f", cut, mutable_cut); + for (auto& track : tracks) { + if (track.globalIndex() % 500 == 0) { + std::string decision1; + std::string decision2; + if (cut->method(std::abs(track.eta()))) { + decision1 = "true"; + } else { + decision1 = "false"; + } + if (mutable_cut->method(std::abs(track.eta()))) { + decision2 = "true"; + } else { + decision2 = "false"; + } + LOGF(INFO, "Cut1: %s; Cut2: %s", decision1, decision2); + if (decision2 == "false") { + mutable_cut->setState(-1); + } else { + mutable_cut->setState(1); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<ConfigurableObjectDemo>("configurable-demo")}; +} diff --git a/Framework/Core/include/Framework/Configurable.h b/Framework/Core/include/Framework/Configurable.h index 8e6917cc596dd..118e7afa99d93 100644 --- a/Framework/Core/include/Framework/Configurable.h +++ b/Framework/Core/include/Framework/Configurable.h @@ -12,29 +12,65 @@ #include <string> namespace o2::framework { -/// This helper allows you to create a configurable option associated to a task. -/// Internally it will be bound to a ConfigParamSpec. template <typename T> -struct Configurable { - Configurable(std::string const& name, T defaultValue, std::string const& help) - : name(name), value(defaultValue), help(help) +struct ConfigurableBase { + ConfigurableBase(std::string const& name, T&& defaultValue, std::string const& help) + : name(name), value{std::move(defaultValue)}, help(help) { } using type = T; std::string name; T value; std::string help; +}; + +template <typename T> +struct ConfigurablePolicyConst : ConfigurableBase<T> { + ConfigurablePolicyConst(std::string const& name, T&& defaultValue, std::string const& help) + : ConfigurableBase<T>{name, std::forward<T>(defaultValue), help} + { + } operator T() { - return value; + return this->value; } T const* operator->() const { - return &value; + return &this->value; + } +}; + +template <typename T> +struct ConfigurablePolicyMutable : ConfigurableBase<T> { + ConfigurablePolicyMutable(std::string const& name, T&& defaultValue, std::string const& help) + : ConfigurableBase<T>{name, std::forward<T>(defaultValue), help} + { + } + operator T() + { + return this->value; + } + T* operator->() + { + return &this->value; + } +}; + +/// This helper allows you to create a configurable option associated to a task. +/// Internally it will be bound to a ConfigParamSpec. +template <typename T, typename IP = ConfigurablePolicyConst<T>> +struct Configurable : IP { + Configurable(std::string const& name, T&& defaultValue, std::string const& help) + : IP{name, std::forward<T>(defaultValue), help} + { } }; + template <typename T> -std::ostream& operator<<(std::ostream& os, Configurable<T> const& c) +using MutableConfigurable = Configurable<T, ConfigurablePolicyMutable<T>>; + +template <typename T, typename IP> +std::ostream& operator<<(std::ostream& os, Configurable<T, IP> const& c) { os << c.value; return os; diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index 57697dfa64226..33340b70640e9 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -355,9 +355,9 @@ struct OptionManager { } }; -template <typename T> -struct OptionManager<Configurable<T>> { - static bool appendOption(std::vector<ConfigParamSpec>& options, Configurable<T>& what) +template <typename T, typename IP> +struct OptionManager<Configurable<T, IP>> { + static bool appendOption(std::vector<ConfigParamSpec>& options, Configurable<T, IP>& what) { if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { options.emplace_back(ConfigParamSpec{what.name, variant_trait_v<typename std::decay<T>::type>, what.value, {what.help}}); @@ -368,7 +368,7 @@ struct OptionManager<Configurable<T>> { return true; } - static bool prepare(InitContext& context, Configurable<T>& what) + static bool prepare(InitContext& context, Configurable<T, IP>& what) { if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { what.value = context.options().get<T>(what.name.c_str()); From 7e2e655df91babea35d864049dd557043645210a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 14 Oct 2020 20:57:28 +0200 Subject: [PATCH 0953/1751] DPL Foundation: add own runtime_error. (#4594) A few features: * No need to include <stdexcept> hopefully reducing bload. * No allocation on throw. * Includes backtrace. We should use this to remove all the runtime_error from at least the framework. --- Framework/Foundation/CMakeLists.txt | 11 ++- .../include/Framework/RuntimeError.h | 35 ++++++++ Framework/Foundation/src/RuntimeError.cxx | 80 +++++++++++++++++++ .../Foundation/test/test_RuntimeError.cxx | 40 ++++++++++ 4 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 Framework/Foundation/include/Framework/RuntimeError.h create mode 100644 Framework/Foundation/src/RuntimeError.cxx create mode 100644 Framework/Foundation/test/test_RuntimeError.cxx diff --git a/Framework/Foundation/CMakeLists.txt b/Framework/Foundation/CMakeLists.txt index 907b9f5991736..5760a2ff00d15 100644 --- a/Framework/Foundation/CMakeLists.txt +++ b/Framework/Foundation/CMakeLists.txt @@ -8,7 +8,11 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_header_only_library(FrameworkFoundation) +install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/Framework + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +o2_add_library(FrameworkFoundation + SOURCES src/RuntimeError.cxx) o2_add_test(test_FunctionalHelpers NAME test_FrameworkFoundation_test_FunctionalHelpers COMPONENT_NAME FrameworkFoundation @@ -34,3 +38,8 @@ o2_add_test(test_Signpost NAME test_FrameworkFoundation_Signpost COMPONENT_NAME FrameworkFoundation SOURCES test/test_Signpost.cxx PUBLIC_LINK_LIBRARIES O2::FrameworkFoundation) + +o2_add_test(test_RuntimeError NAME test_FrameworkFoundation_RuntimeError + COMPONENT_NAME FrameworkFoundation + SOURCES test/test_RuntimeError.cxx + PUBLIC_LINK_LIBRARIES O2::FrameworkFoundation) diff --git a/Framework/Foundation/include/Framework/RuntimeError.h b/Framework/Foundation/include/Framework/RuntimeError.h new file mode 100644 index 0000000000000..05692690d1bc7 --- /dev/null +++ b/Framework/Foundation/include/Framework/RuntimeError.h @@ -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. +#ifndef O2_FRAMEWORK_RUNTIMEERROR_H_ +#define O2_FRAMEWORK_RUNTIMEERROR_H_ + +namespace o2::framework +{ + +struct RuntimeError { + static constexpr unsigned int MAX_RUNTIME_ERRORS = 64; + static constexpr unsigned int MAX_RUNTIME_ERROR_SIZE = 1024; + static constexpr unsigned int MAX_BACKTRACE_SIZE = 100; + char what[MAX_RUNTIME_ERROR_SIZE]; + void* backtrace[MAX_BACKTRACE_SIZE]; + int maxBacktrace = 0; +}; + +struct RuntimeErrorRef { + int index = 0; +}; + +RuntimeErrorRef runtime_error(const char*); +RuntimeErrorRef runtime_error_f(const char*, ...); +RuntimeError& error_from_ref(RuntimeErrorRef); + +} // namespace o2::framework + +#endif // O2_FRAMEWORK_RUNTIMEERROR_H_ diff --git a/Framework/Foundation/src/RuntimeError.cxx b/Framework/Foundation/src/RuntimeError.cxx new file mode 100644 index 0000000000000..0bb39a70601a7 --- /dev/null +++ b/Framework/Foundation/src/RuntimeError.cxx @@ -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. + +#include "Framework/RuntimeError.h" + +#include <cstdio> +#include <atomic> +#include <cstdarg> +#include <execinfo.h> +#include <cstring> + +namespace o2::framework +{ + +namespace +{ +static RuntimeError gError[RuntimeError::MAX_RUNTIME_ERRORS]; +static std::atomic<bool> gErrorBooking[RuntimeError::MAX_RUNTIME_ERRORS]; + +bool canDumpBacktrace() +{ +#ifdef DPL_ENABLE_BACKTRACE + return true; +#else + return false; +#endif +} +} // namespace + +void clean_all_runtime_errors() +{ + for (size_t i = 0; i < RuntimeError::MAX_RUNTIME_ERRORS; ++i) { + gErrorBooking[i].store(false); + } +} + +void clean_runtime_error(int i) +{ + gErrorBooking[i].store(false); +} + +RuntimeError& error_from_ref(RuntimeErrorRef ref) +{ + return gError[ref.index]; +} + +RuntimeErrorRef runtime_error_f(const char* format, ...) +{ + int i = 0; + bool expected = false; + while (gErrorBooking[i].compare_exchange_strong(expected, true) == false) { + ++i; + } + va_list args; + va_start(args, format); + vsnprintf(gError[i].what, RuntimeError::MAX_RUNTIME_ERROR_SIZE, format, args); + gError[i].maxBacktrace = canDumpBacktrace() ? backtrace(gError[i].backtrace, RuntimeError::MAX_BACKTRACE_SIZE) : 0; + return RuntimeErrorRef{i}; +} + +RuntimeErrorRef runtime_error(const char* s) +{ + int i = 0; + bool expected = false; + while (gErrorBooking[i].compare_exchange_strong(expected, true) == false) { + ++i; + } + strncpy(gError[i].what, s, RuntimeError::MAX_RUNTIME_ERROR_SIZE); + gError[i].maxBacktrace = canDumpBacktrace() ? backtrace(gError[i].backtrace, RuntimeError::MAX_BACKTRACE_SIZE) : 0; + return RuntimeErrorRef{i}; +} + +} // namespace o2::framework diff --git a/Framework/Foundation/test/test_RuntimeError.cxx b/Framework/Foundation/test/test_RuntimeError.cxx new file mode 100644 index 0000000000000..44867d627f5df --- /dev/null +++ b/Framework/Foundation/test/test_RuntimeError.cxx @@ -0,0 +1,40 @@ +// 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. + +#define BOOST_TEST_MODULE Test Framework RuntimeError +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> +#include "Framework/RuntimeError.h" +#include <execinfo.h> + +BOOST_AUTO_TEST_CASE(TestRuntimeError) +{ + try { + throw o2::framework::runtime_error("foo"); + } catch (o2::framework::RuntimeErrorRef ref) { + auto& err = o2::framework::error_from_ref(ref); + BOOST_CHECK_EQUAL(strncmp(err.what, "foo", 3), 0); +#ifdef DPL_ENABLE_BACKTRACE + backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); +#endif + } + + try { + throw o2::framework::runtime_error_f("foo %d", 1); + } catch (o2::framework::RuntimeErrorRef ref) { + auto& err = o2::framework::error_from_ref(ref); + BOOST_CHECK_EQUAL(strncmp(err.what, "foo", 3), 0); +#ifdef DPL_ENABLE_BACKTRACE + backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); +#endif + } +} From da92c1b145b599076601ee112668713bc1c49dad Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 14 Oct 2020 15:16:47 +0200 Subject: [PATCH 0954/1751] Allow user-provided DataDescription in RawPixelDecoder --- .../include/ITSMFTReconstruction/RawPixelDecoder.h | 4 ++++ .../ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index c98a367254743..0b6467b84b6a7 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -70,6 +70,9 @@ class RawPixelDecoder final : public PixelReader auto getUserDataOrigin() const { return mUserDataOrigin; } void setUserDataOrigin(header::DataOrigin orig) { mUserDataOrigin = orig; } + auto getUserDataDescription() const { return mUserDataDescription; } + void setUserDataDescription(header::DataDescription desc) { mUserDataDescription = desc; } + void setNThreads(int n); int getNThreads() const { return mNThreads; } @@ -107,6 +110,7 @@ class RawPixelDecoder final : public PixelReader std::array<short, Mapping::getNRUs()> mRUEntry; // entry of the RU with given SW ID in the mRUDecodeVec std::string mSelfName; // self name header::DataOrigin mUserDataOrigin = o2::header::gDataOriginInvalid; // alternative user-provided data origin to pick + header::DataDescription mUserDataDescription = o2::header::gDataDescriptionInvalid; // alternative user-provided description to pick uint16_t mCurRUDecodeID = NORUDECODED; // index of currently processed RUDecode container int mLastReadChipID = -1; // chip ID returned by previous getNextChipData call, used for ordering checks Mapping mMAP; // chip mapping diff --git a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx index 3ebd568baa5ad..24710c25b7209 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx @@ -169,7 +169,8 @@ void RawPixelDecoder<Mapping>::setupLinks(InputRecord& inputs) mCurRUDecodeID = NORUDECODED; auto nLinks = mGBTLinks.size(); auto origin = (mUserDataOrigin == o2::header::gDataOriginInvalid) ? mMAP.getOrigin() : mUserDataOrigin; - std::vector<InputSpec> filter{InputSpec{"filter", ConcreteDataTypeMatcher{origin, "RAWDATA"}, Lifetime::Timeframe}}; + auto datadesc = (mUserDataDescription == o2::header::gDataDescriptionInvalid) ? o2::header::gDataDescriptionRawData : mUserDataDescription; + std::vector<InputSpec> filter{InputSpec{"filter", ConcreteDataTypeMatcher{origin, datadesc}, Lifetime::Timeframe}}; DPLRawParser parser(inputs, filter); uint32_t currSSpec = 0xffffffff; // dummy starting subspec int linksAdded = 0; From 685d88779ffd8148b4f49e697e3cc5ac4f175b23 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 15:53:27 +0200 Subject: [PATCH 0955/1751] TPC Workflow: Add option to split clusters per sector when writing to ROOT file --- .../include/TPCWorkflow/CATrackerSpec.h | 5 ++ .../include/TPCWorkflow/RecoWorkflow.h | 1 + Detectors/TPC/workflow/src/CATrackerSpec.cxx | 64 +++++++++++++++---- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 4 +- .../TPC/workflow/src/tpc-reco-workflow.cxx | 2 +- 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h index c3b0fde519484..0be54aaf59818 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h @@ -42,6 +42,7 @@ enum struct Operation { OutputCompClusters, // publish CompClusters container OutputCompClustersFlat, // publish CompClusters container ProcessMC, // process MC labels + SendClustersPerSector, // Send clusters and clusters mc labels per sector Noop, // skip argument on the constructor }; @@ -90,6 +91,9 @@ struct Config { case Operation::ProcessMC: processMC = true; break; + case Operation::SendClustersPerSector: + sendClustersPerSector = true; + break; case Operation::Noop: break; default: @@ -113,6 +117,7 @@ struct Config { bool outputCompClustersFlat = false; bool outputCAClusters = false; bool processMC = false; + bool sendClustersPerSector = false; }; } // namespace ca diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h b/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h index 436f29eb255d5..100a35e82c0bc 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h @@ -58,6 +58,7 @@ enum struct OutputType { Digits, CompClusters, EncodedClusters, DisableWriter, + SendClustersPerSector, ZSRaw, }; diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 26b8ac4ead28c..e4dabd39d4287 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -565,10 +565,11 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } } if (processAttributes->clusterOutputIds.size() > 0) { + const o2::header::DataDescription outputLabel = specconfig.sendClustersPerSector ? (o2::header::DataDescription) "CLUSTERNATIVETMP" : (o2::header::DataDescription) "CLUSTERNATIVE"; if (processAttributes->allocateOutputOnTheFly) { - outputRegions.clustersNative.allocator = [&clusterOutputChar, &pc, clusterOutputSectorHeader](size_t size) -> void* {clusterOutputChar = pc.outputs().make<char>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, size + sizeof(ClusterCountIndex)).data(); return clusterOutputChar + sizeof(ClusterCountIndex); }; + outputRegions.clustersNative.allocator = [&clusterOutputChar, &pc, clusterOutputSectorHeader, outputLabel](size_t size) -> void* {clusterOutputChar = pc.outputs().make<char>({gDataOriginTPC, outputLabel, NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, size + sizeof(ClusterCountIndex)).data(); return clusterOutputChar + sizeof(ClusterCountIndex); }; } else { - clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, processAttributes->outputBufferSize)); + clusterOutput.emplace(pc.outputs().make<std::vector<char>>({gDataOriginTPC, outputLabel, NSectors, Lifetime::Timeframe, {clusterOutputSectorHeader}}, processAttributes->outputBufferSize)); clusterOutputChar = clusterOutput->get().data(); outputRegions.clustersNative.ptr = clusterOutputChar + sizeof(ClusterCountIndex); outputRegions.clustersNative.size = clusterOutput->get().size() - sizeof(ClusterCountIndex); @@ -634,14 +635,41 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config throw std::runtime_error("cluster native output ptrs out of sync"); // sanity check } - o2::header::DataHeader::SubSpecificationType subspec = NSectors; - // doing a copy for now, in the future the tracker uses the output buffer directly ClusterNativeAccess const& accessIndex = *ptrs.clusters; - ClusterCountIndex* outIndex = reinterpret_cast<ClusterCountIndex*>(clusterOutputChar); - static_assert(sizeof(ClusterCountIndex) == sizeof(accessIndex.nClusters)); - memcpy(outIndex, &accessIndex.nClusters[0][0], sizeof(ClusterCountIndex)); - if (specconfig.processMC && accessIndex.clustersMCTruth) { - pc.outputs().snapshot({gDataOriginTPC, "CLNATIVEMCLBL", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}, clustersMCBuffer.first); + if (specconfig.sendClustersPerSector) { + for (int i = 0; i < NSectors; i++) { + if (processAttributes->tpcSectorMask & (1ul << i)) { + o2::header::DataHeader::SubSpecificationType subspec = i; + clusterOutputSectorHeader.sectorBits = (1ul << i); + char* buffer = pc.outputs().make<char>({gDataOriginTPC, "CLUSTERNATIVE", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}, accessIndex.nClustersSector[i] * sizeof(*accessIndex.clustersLinear) + sizeof(ClusterCountIndex)).data(); + ClusterCountIndex* outIndex = reinterpret_cast<ClusterCountIndex*>(buffer); + memset(outIndex, 0, sizeof(*outIndex)); + for (int j = 0; j < constants::MAXGLOBALPADROW; j++) { + outIndex->nClusters[i][j] = accessIndex.nClusters[i][j]; + } + memcpy(buffer + sizeof(*outIndex), accessIndex.clusters[i][0], accessIndex.nClustersSector[i] * sizeof(*accessIndex.clustersLinear)); + if (specconfig.processMC && accessIndex.clustersMCTruth) { + MCLabelContainer cont; + for (int j = 0; j < accessIndex.nClustersSector[i]; j++) { + const auto& labels = accessIndex.clustersMCTruth->getLabels(accessIndex.clusterOffset[i][0] + j); + for (const auto& label : labels) { + cont.addElement(j, label); + } + } + ConstMCLabelContainer contflat; + cont.flatten_to(contflat); + pc.outputs().snapshot({gDataOriginTPC, "CLNATIVEMCLBL", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}, contflat); + } + } + } + } else { + o2::header::DataHeader::SubSpecificationType subspec = NSectors; + ClusterCountIndex* outIndex = reinterpret_cast<ClusterCountIndex*>(clusterOutputChar); + static_assert(sizeof(ClusterCountIndex) == sizeof(accessIndex.nClusters)); + memcpy(outIndex, &accessIndex.nClusters[0][0], sizeof(ClusterCountIndex)); + if (specconfig.processMC && accessIndex.clustersMCTruth) { + pc.outputs().snapshot({gDataOriginTPC, "CLNATIVEMCLBL", subspec, Lifetime::Timeframe, {clusterOutputSectorHeader}}, clustersMCBuffer.first); + } } } }; @@ -723,9 +751,23 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config for (auto const& sector : tpcsectors) { processAttributes->clusterOutputIds.emplace_back(sector); } - outputSpecs.emplace_back(gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe); + outputSpecs.emplace_back(gDataOriginTPC, "CLUSTERNATIVE", specconfig.sendClustersPerSector ? 0 : NSectors, Lifetime::Timeframe); + if (specconfig.sendClustersPerSector) { + outputSpecs.emplace_back(gDataOriginTPC, "CLUSTERNATIVETMP", NSectors, Lifetime::Timeframe); // Dummy buffer the TPC tracker writes the inital linear clusters to + for (const auto sector : tpcsectors) { + outputSpecs.emplace_back(gDataOriginTPC, "CLUSTERNATIVE", sector, Lifetime::Timeframe); + } + } else { + outputSpecs.emplace_back(gDataOriginTPC, "CLUSTERNATIVE", NSectors, Lifetime::Timeframe); + } if (specconfig.processMC) { - outputSpecs.emplace_back(OutputSpec{gDataOriginTPC, "CLNATIVEMCLBL", NSectors, Lifetime::Timeframe}); + if (specconfig.sendClustersPerSector) { + for (const auto sector : tpcsectors) { + outputSpecs.emplace_back(gDataOriginTPC, "CLNATIVEMCLBL", sector, Lifetime::Timeframe); + } + } else { + outputSpecs.emplace_back(gDataOriginTPC, "CLNATIVEMCLBL", NSectors, Lifetime::Timeframe); + } } } return std::move(outputSpecs); diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 7d237d5d213a0..195079d0149e3 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -83,6 +83,7 @@ const std::unordered_map<std::string, OutputType> OutputMap{ {"compressed-clusters", OutputType::CompClusters}, {"encoded-clusters", OutputType::EncodedClusters}, {"disable-writer", OutputType::DisableWriter}, + {"send-clusters-per-sector", OutputType::SendClustersPerSector}, {"zsraw", OutputType::ZSRaw}, }; @@ -413,7 +414,7 @@ framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vecto BranchDefinition<std::vector<char>>{InputSpec{"mc", ConcreteDataTypeMatcher{"TPC", "CLNATIVEMCLBL"}}, "TPCClusterNativeMCTruth", "mcbranch", fillLabels}, - caClusterer || decompressTPC)); + (caClusterer || decompressTPC) && !isEnabled(OutputType::SendClustersPerSector))); } if (zsOnTheFly) { @@ -440,6 +441,7 @@ framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vecto produceTracks ? ca::Operation::OutputTracks : ca::Operation::Noop, produceCompClusters ? ca::Operation::OutputCompClusters : ca::Operation::Noop, runClusterEncoder ? ca::Operation::OutputCompClustersFlat : ca::Operation::Noop, + isEnabled(OutputType::SendClustersPerSector) ? ca::Operation::SendClustersPerSector : ca::Operation::Noop, isEnabled(OutputType::Clusters) && (caClusterer || decompressTPC) ? ca::Operation::OutputCAClusters : ca::Operation::Noop, }, tpcSectors)); diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index c88bdc1caf03f..4f084afa6f527 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -46,7 +46,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) std::vector<ConfigParamSpec> options{ {"input-type", VariantType::String, "digits", {"digitizer, digits, zsraw, clustershw, clustersnative, compressed-clusters, compressed-clusters-ctf"}}, - {"output-type", VariantType::String, "tracks", {"digits, zsraw, clustershw, clustersnative, tracks, compressed-clusters, encoded-clusters, disable-writer"}}, + {"output-type", VariantType::String, "tracks", {"digits, zsraw, clustershw, clustersnative, tracks, compressed-clusters, encoded-clusters, disable-writer, send-clusters-per-sector"}}, {"no-ca-clusterer", VariantType::Bool, false, {"Use HardwareClusterer instead of clusterer of GPUCATracking"}}, {"disable-mc", VariantType::Bool, false, {"disable sending of MC information"}}, //{"tpc-sectors", VariantType::String, "0-35", {"TPC sector range, e.g. 5-7,8,9"}}, From fec7a0179c7f9a8263b8c6b683d8163dd4b7cc18 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 14 Oct 2020 15:22:49 +0200 Subject: [PATCH 0956/1751] GPU: Add header file with some ROOT forward declarations to enable GPU compilation of some classes --- .../TPC/include/DataFormatsTPC/Defs.h | 5 ++ .../TPC/include/DataFormatsTPC/TrackTPC.h | 1 - .../TrackParametrization.h | 20 +------- Detectors/TPC/base/include/TPCBase/Mapper.h | 3 ++ .../SpacePoints/src/TrackInterpolation.cxx | 1 + GPU/Common/CMakeLists.txt | 3 +- GPU/Common/GPUROOTCartesianFwd.h | 46 +++++++++++++++++++ 7 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 GPU/Common/GPUROOTCartesianFwd.h diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h index 5e75d2b708bb0..f9a4b8967e2d4 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h @@ -18,10 +18,15 @@ #ifndef AliceO2_TPC_Defs_H #define AliceO2_TPC_Defs_H +#ifndef GPUCA_GPUCODE_DEVICE #include <cmath> +#endif +#include "GPUROOTCartesianFwd.h" +#ifndef GPUCA_ALIGPUCODE #include "MathUtils/Cartesian2D.h" #include "MathUtils/Cartesian3D.h" +#endif namespace o2 { diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h index e0e734e552587..e021d9db7388f 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h @@ -14,7 +14,6 @@ #include "ReconstructionDataFormats/Track.h" #include "CommonDataFormat/RangeReference.h" #include "DataFormatsTPC/ClusterNative.h" -#include "DataFormatsTPC/Defs.h" #include "DataFormatsTPC/dEdxInfo.h" #include <gsl/span> diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 6f8f51103aa20..698c90de64b61 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -49,25 +49,7 @@ #include "ReconstructionDataFormats/TrackUtils.h" //Forward declarations, since we cannot include the headers if we eventually want to use track.h on GPU -namespace ROOT -{ -namespace Math -{ -template <class T, unsigned int D1, unsigned int D2, class R> -class SMatrix; -template <class T, unsigned int D> -class MatRepSym; -template <class T, unsigned int D1, unsigned int D2> -class MatRepStd; -template <class CoordSystem, class Tag> -class PositionVector3D; -template <class T> -class Cartesian3D; -class DefaultCoordinateSystemTag; -} // namespace Math -} // namespace ROOT -template <typename T> -using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +#include "GPUROOTCartesianFwd.h" namespace o2 { diff --git a/Detectors/TPC/base/include/TPCBase/Mapper.h b/Detectors/TPC/base/include/TPCBase/Mapper.h index c6c722fe8b06f..21267afc949fa 100644 --- a/Detectors/TPC/base/include/TPCBase/Mapper.h +++ b/Detectors/TPC/base/include/TPCBase/Mapper.h @@ -27,6 +27,9 @@ #include "TPCBase/PartitionInfo.h" #include "TPCBase/Sector.h" +#include "MathUtils/Cartesian2D.h" +#include "MathUtils/Cartesian3D.h" + // using o2::tpc::PadRegionInfo; // using o2::tpc::PartitionInfo; diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index d017015a4cfb9..6300b33ac2a1a 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -17,6 +17,7 @@ #include "SpacePoints/TrackInterpolation.h" #include "TPCBase/ParameterElectronics.h" #include "DataFormatsTPC/TrackTPC.h" +#include "DataFormatsTPC/Defs.h" #include <fairlogger/Logger.h> #include <set> diff --git a/GPU/Common/CMakeLists.txt b/GPU/Common/CMakeLists.txt index 744365ac798e5..f3a8502796a19 100644 --- a/GPU/Common/CMakeLists.txt +++ b/GPU/Common/CMakeLists.txt @@ -24,7 +24,8 @@ set(HDRS_INSTALL GPUDefGPUParameters.h GPUDefOpenCL12Templates.h GPULogging.h - GPUDefMacros.h) + GPUDefMacros.h + GPUROOTCartesianFwd.h) if(ALIGPU_BUILD_TYPE STREQUAL "O2") o2_add_library(${MODULE} diff --git a/GPU/Common/GPUROOTCartesianFwd.h b/GPU/Common/GPUROOTCartesianFwd.h new file mode 100644 index 0000000000000..6df0fa43b0f4c --- /dev/null +++ b/GPU/Common/GPUROOTCartesianFwd.h @@ -0,0 +1,46 @@ +// 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 GPUROOTCartesianFwd.h +/// \author David Rohr + +#ifndef GPUROOTCARTESIANFWD_H +#define GPUROOTCARTESIANFWD_H + +// Standalone forward declarations for Cartesian2D / Cartesian3D / Point2D / Point3D etc. +// To be used on GPU where ROOT is not available. + +namespace ROOT +{ +namespace Math +{ +template <class T, unsigned int D1, unsigned int D2, class R> +class SMatrix; +template <class T, unsigned int D> +class MatRepSym; +template <class T, unsigned int D1, unsigned int D2> +class MatRepStd; +template <class CoordSystem, class Tag> +class PositionVector2D; +template <class CoordSystem, class Tag> +class PositionVector3D; +template <class T> +class Cartesian2D; +template <class T> +class Cartesian3D; +class DefaultCoordinateSystemTag; +} // namespace Math +} // namespace ROOT +template <typename T> +using Point2D = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +template <typename T> +using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; + +#endif From 5db42d362006fa35a10be7f81d29e4ec5d2cc5ad Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 14 Oct 2020 15:31:52 +0200 Subject: [PATCH 0957/1751] TPC: Accept also std::vector or plain ptr as the reference info --- .../Detectors/TPC/include/DataFormatsTPC/TrackTPC.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h index e021d9db7388f..2369b2e76cad8 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h @@ -15,7 +15,6 @@ #include "CommonDataFormat/RangeReference.h" #include "DataFormatsTPC/ClusterNative.h" #include "DataFormatsTPC/dEdxInfo.h" -#include <gsl/span> namespace o2 { @@ -74,7 +73,8 @@ class TrackTPC : public o2::track::TrackParCov int getNClusterReferences() const { return getNClusters(); } void setClusterRef(uint32_t entry, uint16_t ncl) { mClustersReference.set(entry, ncl); } - void getClusterReference(gsl::span<const o2::tpc::TPCClRefElem> clinfo, int nCluster, + template <class T> + void getClusterReference(T& clinfo, int nCluster, uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex) const { // data for given tracks starts at clinfo[ mClustersReference.getFirstEntry() ], @@ -89,7 +89,8 @@ class TrackTPC : public o2::track::TrackParCov rowIndex = srIndexArr[nCluster + mClustersReference.getEntries()]; } - const o2::tpc::ClusterNative& getCluster(gsl::span<const o2::tpc::TPCClRefElem> clinfo, int nCluster, + template <class T> + const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex) const { uint32_t clusterIndex; @@ -97,7 +98,8 @@ class TrackTPC : public o2::track::TrackParCov return (clusters.clusters[sectorIndex][rowIndex][clusterIndex]); } - const o2::tpc::ClusterNative& getCluster(gsl::span<const o2::tpc::TPCClRefElem> clinfo, int nCluster, + template <class T> + const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, const o2::tpc::ClusterNativeAccess& clusters) const { uint8_t sectorIndex, rowIndex; From d6707f35901f56c1ebc1d533f54abddad6166b70 Mon Sep 17 00:00:00 2001 From: Nicolo' Jacazio <nicolo.jacazio@cern.ch> Date: Wed, 14 Oct 2020 21:04:37 +0200 Subject: [PATCH 0958/1751] Update TOF and TPC PID workflow * Set DetectorResponse as container for parametrization - de-templatized DetectorResponse * Update TOF PID - Split Nsigma and Beta tasks - Use constexpr for TOF response - templatized TOF response * Update TPC PID - Use constexpr for TPC response - templatized TPC response --- Analysis/DataModel/CMakeLists.txt | 2 - Analysis/DataModel/include/PID/PIDResponse.h | 2 - Analysis/DataModel/include/PID/PIDTOF.h | 168 +++++++++-------- Analysis/DataModel/include/PID/PIDTPC.h | 41 ++-- .../include/PIDBase/DetectorResponse.h | 9 +- Analysis/DataModel/src/PIDTOF.cxx | 63 ------- Analysis/DataModel/src/PIDTPC.cxx | 35 ---- Analysis/Tasks/pidTOF.cxx | 176 +++++++++++------- Analysis/Tasks/pidTPC.cxx | 82 ++++---- 9 files changed, 265 insertions(+), 313 deletions(-) delete mode 100644 Analysis/DataModel/src/PIDTOF.cxx delete mode 100644 Analysis/DataModel/src/PIDTPC.cxx diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index 1ddd6f70161db..bf3f50c8a30a6 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -10,8 +10,6 @@ o2_add_library(AnalysisDataModel SOURCES src/ParamBase.cxx - src/PIDTOF.cxx - src/PIDTPC.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats O2::TPCSimulation ) diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/PID/PIDResponse.h index bf9862c30091d..aaf6143cc35b7 100644 --- a/Analysis/DataModel/include/PID/PIDResponse.h +++ b/Analysis/DataModel/include/PID/PIDResponse.h @@ -24,8 +24,6 @@ #include "Framework/AnalysisDataModel.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/PID.h" -#include "PID/PIDTOF.h" -#include "PID/PIDTPC.h" namespace o2::aod { diff --git a/Analysis/DataModel/include/PID/PIDTOF.h b/Analysis/DataModel/include/PID/PIDTOF.h index bee4a52dc58de..59a007641476c 100644 --- a/Analysis/DataModel/include/PID/PIDTOF.h +++ b/Analysis/DataModel/include/PID/PIDTOF.h @@ -30,102 +30,112 @@ namespace o2::pid::tof { -/// \brief Class to handle the event times available for PID -class EventTime -{ - public: - EventTime() = default; - ~EventTime() = default; - - /// Setter for the event time in momentum bin i - void SetEvTime(int i, float evtime) { mEvTime[i] = evtime; } - /// Setter for the event time resolution in momentum bin i - void SetEvTimeReso(int i, float evtimereso) { mEvTimeReso[i] = evtimereso; } - /// Setter for the event time mask in momentum bin i - void SetEvTimeMask(int i, int mask) { mEvTimeMask[i] = mask; } - /// Getter for the event time in momentum bin i - float GetEvTime(int i) const { return mEvTime[i]; } - /// Getter for the event time resolution in momentum bin i - float GetEvTimeReso(int i) const { return mEvTimeReso[i]; } - /// Getter for the momentum bin index - uint GetMomBin(float mom) const; - /// Getter for the event time for the momentum requested - float GetEvTime(float mom) const { return mEvTime[GetMomBin(mom)]; } - /// Getter for the event time resolution for the momentum requested - float GetEvTimeReso(float mom) const { return mEvTimeReso[GetMomBin(mom)]; } - - private: - static const unsigned int mNmomBins = 1; /// Number of momentum bin - static constexpr std::array<float, mNmomBins + 1> mMomBins = {0, 100}; /// Momentum bins - std::array<float, mNmomBins> mEvTime; /// Evtime (best, T0, T0-TOF, ...) of the event as a function of p - std::array<float, mNmomBins> mEvTimeReso; /// Evtime (best, T0, T0-TOF, ...) resolution as a function of p - std::array<int, mNmomBins> mEvTimeMask; /// Mask withthe T0 used (0x1=T0-TOF,0x2=T0A,0x3=TOC) for p bins -}; - +// Utility values +static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; /// Speed of light in TOF units (cm/ps) -/// \brief Class to handle the the TOF detector response -class Response +/// \brief Class to handle the the TOF detector response for the TOF beta measurement +template <typename Coll, typename Trck, o2::track::PID::ID id> +class Beta { public: - Response() = default; - - /// Updater for the TOF response to setup the track parameters - /// i.e. sets the track of interest - void UpdateTrack(float mom, float tofexpmom, float length, float tofsignal) - { - mMomentum = mom; - mTOFExpMomentum = tofexpmom; - mLength = length; - mTOFSignal = tofsignal; - }; - - /// Setter for the event time information in the parametrization - void SetEventTime(EventTime& evtime) { mEventTime = evtime; }; - /// Getter for the event time information in the parametrization - EventTime GetEventTime() const { return mEventTime; }; - - // TOF beta + Beta() = default; + ~Beta() = default; + /// Computes the beta of a track given a length, a time measurement and an event time - static float GetBeta(float length, float time, float evtime); + static float GetBeta(const float length, const float tofSignal, const float collisionTime); + /// Gets the beta for the track of interest - float GetBeta() const { return GetBeta(mLength, mTOFSignal, mEventTime.GetEvTime(mMomentum)); } + float GetBeta(const Coll& col, const Trck& trk) const { return GetBeta(trk.length(), trk.tofSignal(), col.collisionTime()); } + /// Computes the expected uncertainty on the beta measurement - static float GetBetaExpectedSigma(float length, float time, float evtime, float sigmat = 80); + static float GetExpectedSigma(const float& length, const float& tofSignal, const float& collisionTime, const float& time_reso); + /// Gets the expected uncertainty on the beta measurement of the track of interest - float GetBetaExpectedSigma(float sigmat = 80) const { return GetBetaExpectedSigma(mLength, mTOFSignal, mEventTime.GetEvTime(mMomentum), sigmat); } + float GetExpectedSigma(const Coll& col, const Trck& trk) const { return GetExpectedSigma(trk.length(), trk.tofSignal(), col.collisionTime(), mExpectedResolution); } + /// Gets the expected beta for a given mass hypothesis (no energy loss taken into account) - static float GetExpectedBeta(float mom, float mass); + static float GetExpectedSignal(const float& mom, const float& mass); + /// Gets the expected beta given the particle index (no energy loss taken into account) - float GetExpectedBeta(o2::track::PID::ID id) const { return GetExpectedBeta(mMomentum, o2::track::PID::getMass2Z(id)); } + float GetExpectedSignal(const Coll& col, const Trck& trk) const { return GetExpectedSignal(trk.p(), o2::track::PID::getMass2Z(id)); } + /// Gets the number of sigmas with respect the approximate beta (no energy loss taken into account) - float GetBetaNumberOfSigmas(o2::track::PID::ID id, float sigmat = 80) { return (GetBeta() - GetExpectedBeta(id)) / GetBetaExpectedSigma(sigmat); } + float GetSeparation(const Coll& col, const Trck& trk) const { return (GetBeta(col, trk) - GetExpectedSignal(col, trk)) / GetExpectedSigma(col, trk); } + + float mExpectedResolution = 80; /// Expected time resolution +}; + +//_________________________________________________________________________ +template <typename Coll, typename Trck, o2::track::PID::ID id> +float Beta<Coll, Trck, id>::GetBeta(const float length, const float tofSignal, const float collisionTime) +{ + if (tofSignal <= 0) { + return -999.f; + } + return length / (tofSignal - collisionTime) / kCSPEED; +} + +//_________________________________________________________________________ +template <typename Coll, typename Trck, o2::track::PID::ID id> +float Beta<Coll, Trck, id>::GetExpectedSigma(const float& length, const float& tofSignal, const float& collisionTime, const float& time_reso) +{ + if (tofSignal <= 0) { + return -999.f; + } + return GetBeta(length, tofSignal, collisionTime) / (tofSignal - collisionTime) * time_reso; +} + +//_________________________________________________________________________ +template <typename Coll, typename Trck, o2::track::PID::ID id> +float Beta<Coll, Trck, id>::GetExpectedSignal(const float& mom, const float& mass) +{ + if (mom > 0) { + return mom / TMath::Sqrt(mom * mom + mass * mass); + } + return 0; +} + +/// \brief Class to handle the the TOF detector response for the expected time +template <typename Coll, typename Trck, o2::track::PID::ID id> +class ExpTimes +{ + public: + ExpTimes() = default; + ~ExpTimes() = default; - // TOF expected times /// Computes the expected time of a track, given it TOF expected momentum - static float ComputeExpectedTime(float tofexpmom, float length, float massZ); + static float ComputeExpectedTime(const float& tofExpMom, const float& length, const float& massZ); + /// Gets the expected signal of the track of interest under the PID assumption - float GetExpectedSignal(o2::track::PID::ID id) const { return ComputeExpectedTime(mTOFExpMomentum, mLength, o2::track::PID::getMass2Z(id)); } + float GetExpectedSignal(const Coll& col, const Trck& trk) const { return ComputeExpectedTime(trk.tofExpMom() / kCSPEED, trk.length(), o2::track::PID::getMass2Z(id)); } - // Expected resolution /// Gets the expected resolution of the measurement - float GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const; - - // Nsigma - float GetSeparation(DetectorResponse<Response>& response, o2::track::PID::ID id) const { return (mTOFSignal - mEventTime.GetEvTime(mMomentum) - GetExpectedSignal(id)) / GetExpectedSigma(response, id); } - - // float GetMismatchProbability(float time, float eta) const; - // Utility values - static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; /// Speed of light in TOF units (cm/ps) - private: - // Event of interest information - EventTime mEventTime; /// Event time object - // Track of interest information - float mMomentum; /// Momentum of the track of interest - float mTOFExpMomentum; /// TOF expected momentum of the track of interest - float mLength; /// Track of interest integrated length - float mTOFSignal; /// Track of interest integrated length + float GetExpectedSigma(const DetectorResponse& response, const Coll& col, const Trck& trk) const; + + /// Gets the number of sigmas with respect the expected time + float GetSeparation(const DetectorResponse& response, const Coll& col, const Trck& trk) const { return (trk.tofSignal() - col.collisionTime() - GetExpectedSignal(col, trk)) / GetExpectedSigma(response, col, trk); } }; +//_________________________________________________________________________ +template <typename Coll, typename Trck, o2::track::PID::ID id> +float ExpTimes<Coll, Trck, id>::ComputeExpectedTime(const float& tofExpMom, const float& length, const float& massZ) +{ + const float energy = sqrt((massZ * massZ) + (tofExpMom * tofExpMom)); + return length * energy / (kCSPEED * tofExpMom); +} + +//_________________________________________________________________________ +template <typename Coll, typename Trck, o2::track::PID::ID id> +float ExpTimes<Coll, Trck, id>::GetExpectedSigma(const DetectorResponse& response, const Coll& col, const Trck& trk) const +{ + if (trk.tofSignal() <= 0) { + return -999.f; + } + const float x[4] = {trk.p(), trk.tofSignal(), col.collisionTimeRes(), o2::track::PID::getMass2Z(id)}; + return response(response.kSigma, x); + // return response(response.kSigma, const Coll& col, const Trck& trk, id); +} + } // namespace o2::pid::tof #endif // O2_FRAMEWORK_PIDTOF_H_ diff --git a/Analysis/DataModel/include/PID/PIDTPC.h b/Analysis/DataModel/include/PID/PIDTPC.h index c462d4e0d00d9..bee121f4bc9d7 100644 --- a/Analysis/DataModel/include/PID/PIDTPC.h +++ b/Analysis/DataModel/include/PID/PIDTPC.h @@ -31,33 +31,36 @@ namespace o2::pid::tpc { /// \brief Class to handle the the TPC detector response -class Response +template <typename Coll, typename Trck, o2::track::PID::ID id> +class ELoss { public: - Response() = default; + ELoss() = default; + ~ELoss() = default; - /// Updater for the TPC response to setup the track parameters - /// i.e. sets the track of interest - void UpdateTrack(float mom, float tpcsignal, float tpcpoints); + /// Gets the expected signal of the measurement + float GetExpectedSignal(DetectorResponse& response, const Coll& col, const Trck& trk) const; - // Expected resolution /// Gets the expected resolution of the measurement - float GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const; + float GetExpectedSigma(DetectorResponse& response, const Coll& col, const Trck& trk) const; - // Expected signal - /// Gets the expected signal of the measurement - float GetExpectedSignal(DetectorResponse<Response>& response, o2::track::PID::ID id) const; + /// Gets the number of sigmas with respect the expected value + float GetSeparation(DetectorResponse& response, const Coll& col, const Trck& trk) const { return (trk.tpcSignal() - GetExpectedSignal(response, col, trk)) / GetExpectedSigma(response, col, trk); } +}; - // Nsigma - float GetSeparation(DetectorResponse<Response>& response, o2::track::PID::ID id) const { return (mTPCSignal - GetExpectedSignal(response, id)) / GetExpectedSigma(response, id); } +template <typename Coll, typename Trck, o2::track::PID::ID id> +float ELoss<Coll, Trck, id>::GetExpectedSignal(DetectorResponse& response, const Coll& col, const Trck& trk) const +{ + const float x[2] = {trk.tpcInnerParam() / o2::track::PID::getMass(id), (float)o2::track::PID::getCharge(id)}; + return response(DetectorResponse::kSignal, x); +} - private: - // Event of interest information - // Track of interest information - float mMomentum; /// Momentum - float mTPCSignal; /// TPC signal - float mTPCPoints; /// Number of TPC points for TPC signal -}; +template <typename Coll, typename Trck, o2::track::PID::ID id> +float ELoss<Coll, Trck, id>::GetExpectedSigma(DetectorResponse& response, const Coll& col, const Trck& trk) const +{ + const float x[2] = {trk.tpcSignal(), (float)trk.tpcNClsFound()}; + return response(DetectorResponse::kSigma, x); +} } // namespace o2::pid::tpc diff --git a/Analysis/DataModel/include/PIDBase/DetectorResponse.h b/Analysis/DataModel/include/PIDBase/DetectorResponse.h index 88f245af19831..b5f3fb3a55a00 100644 --- a/Analysis/DataModel/include/PIDBase/DetectorResponse.h +++ b/Analysis/DataModel/include/PIDBase/DetectorResponse.h @@ -34,8 +34,7 @@ namespace o2::pid { /// \brief Class to handle the general detector response -template <typename DetectorImpl> -class DetectorResponse : public DetectorImpl +class DetectorResponse { public: DetectorResponse() = default; @@ -77,8 +76,7 @@ class DetectorResponse : public DetectorImpl std::array<Parametrization*, kNParams> mParam; }; -template <typename DetectorImpl> -inline void DetectorResponse<DetectorImpl>::LoadParamFromFile(const TString fname, const TString pname, const Param_t ptype) +inline void DetectorResponse::LoadParamFromFile(const TString fname, const TString pname, const Param_t ptype) { TFile f(fname, "READ"); if (!f.Get(pname)) { @@ -91,8 +89,7 @@ inline void DetectorResponse<DetectorImpl>::LoadParamFromFile(const TString fnam mParam[ptype]->PrintParametrization(); } -template <typename DetectorImpl> -inline void DetectorResponse<DetectorImpl>::SetParameters(const DetectorResponse<DetectorImpl>::Param_t ptype, std::vector<pidvar_t> p) +inline void DetectorResponse::SetParameters(const DetectorResponse::Param_t ptype, std::vector<pidvar_t> p) { if (!mParam[ptype]) { const std::string pname = std::string(ParamName[ptype]) + "_default_param"; diff --git a/Analysis/DataModel/src/PIDTOF.cxx b/Analysis/DataModel/src/PIDTOF.cxx deleted file mode 100644 index 6e36145214b65..0000000000000 --- a/Analysis/DataModel/src/PIDTOF.cxx +++ /dev/null @@ -1,63 +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. - -#include "PID/PIDTOF.h" - -namespace o2::pid::tof -{ - -//_________________________________________________________________________ -uint EventTime::GetMomBin(float mom) const -{ - for (int i = 0; i < mNmomBins; i++) - if (abs(mom) < mMomBins[i + 1]) - return i; - return mNmomBins - 1; -} - -//_________________________________________________________________________ -float Response::ComputeExpectedTime(float tofexpmom, float length, float massZ) -{ - const float energy = sqrt((massZ * massZ) + (tofexpmom * tofexpmom)); - return length * energy / (kCSPEED * tofexpmom); -} - -//_________________________________________________________________________ -float Response::GetBeta(float length, float time, float evtime) -{ - if (time <= 0) - return -999.f; - return length / (time - evtime) / kCSPEED; -} - -//_________________________________________________________________________ -float Response::GetBetaExpectedSigma(float length, float time, float evtime, float sigmat) -{ - if (time <= 0) - return -999.f; - return GetBeta(length, time, evtime) / (time - evtime) * sigmat; -} - -//_________________________________________________________________________ -float Response::GetExpectedBeta(float mom, float mass) -{ - if (mom > 0) - return mom / TMath::Sqrt(mom * mom + mass * mass); - return 0; -} - -//_________________________________________________________________________ -float Response::GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const -{ - const float x[4] = {mMomentum, mTOFSignal, mEventTime.GetEvTimeReso(mMomentum), o2::track::PID::getMass2Z(id)}; - return response(DetectorResponse<Response>::kSigma, x); -} - -} // namespace o2::pid::tof diff --git a/Analysis/DataModel/src/PIDTPC.cxx b/Analysis/DataModel/src/PIDTPC.cxx deleted file mode 100644 index 2906f3d1c00fc..0000000000000 --- a/Analysis/DataModel/src/PIDTPC.cxx +++ /dev/null @@ -1,35 +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. - -#include "PID/PIDTPC.h" - -namespace o2::pid::tpc -{ - -void Response::UpdateTrack(float mom, float tpcsignal, float tpcpoints) -{ - mMomentum = mom; - mTPCSignal = tpcsignal; - mTPCPoints = tpcpoints; -}; - -float Response::GetExpectedSignal(DetectorResponse<Response>& response, o2::track::PID::ID id) const -{ - const float x[2] = {mMomentum / o2::track::PID::getMass(id), (float)o2::track::PID::getCharge(id)}; - return response(DetectorResponse<Response>::kSignal, x); -} - -float Response::GetExpectedSigma(DetectorResponse<Response>& response, o2::track::PID::ID id) const -{ - const float x[2] = {mTPCSignal, mTPCPoints}; - return response(DetectorResponse<Response>::kSigma, x); -} - -} // namespace o2::pid::tpc diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index 430468beaf3ee..af985a6cf9464 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -16,6 +16,7 @@ #include "PID/PIDResponse.h" #include <CCDB/BasicCCDBManager.h> #include "Analysis/HistHelpers.h" +#include "PID/PIDTOF.h" // #define USE_REGISTRY #ifdef USE_REGISTRY @@ -34,16 +35,18 @@ using namespace o2::track; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { std::vector<ConfigParamSpec> options{ - {"add-qa", VariantType::Int, 0, {"Produce TOF PID QA histograms"}}}; + {"add-qa", VariantType::Int, 0, {"Produce TOF PID QA histograms"}}, + {"add-beta", VariantType::Int, 0, {"Produce TOF Beta table"}}}; std::swap(workflowOptions, options); } #include "Framework/runDataProcessing.h" struct pidTOFTask { + using Trks = soa::Join<aod::Tracks, aod::TracksExtra>; + using Coll = aod::Collision; Produces<aod::pidRespTOF> tofpid; - Produces<aod::pidRespTOFbeta> tofpidbeta; - DetectorResponse<tof::Response> resp = DetectorResponse<tof::Response>(); + DetectorResponse resp; Service<o2::ccdb::BasicCCDBManager> ccdb; Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; Configurable<std::string> sigmaname{"param-sigma", "TOFReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"}; @@ -60,61 +63,82 @@ struct pidTOFTask { ccdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()); // const std::vector<float> p = {0.008, 0.008, 0.002, 40.0}; - resp.SetParameters(DetectorResponse<tof::Response>::kSigma, p); + resp.SetParameters(DetectorResponse::kSigma, p); const std::string fname = paramfile.value; if (!fname.empty()) { // Loading the parametrization from file - resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse<tof::Response>::kSigma); + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); } else { // Loading it from CCDB const std::string path = "Analysis/PID/TOF"; - resp.LoadParam(DetectorResponse<tof::Response>::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); + resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); } } - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) + void process(Coll const& collision, Trks const& tracks) { - tof::EventTime evt = tof::EventTime(); - evt.SetEvTime(0, collision.collisionTime()); - evt.SetEvTimeReso(0, collision.collisionTimeRes()); - evt.SetEvTimeMask(0, collision.collisionTimeMask()); - resp.SetEventTime(evt); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Electron> resp_Electron = tof::ExpTimes<Coll, Trks::iterator, PID::Electron>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Muon> resp_Muon = tof::ExpTimes<Coll, Trks::iterator, PID::Muon>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Pion> resp_Pion = tof::ExpTimes<Coll, Trks::iterator, PID::Pion>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Kaon> resp_Kaon = tof::ExpTimes<Coll, Trks::iterator, PID::Kaon>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Proton> resp_Proton = tof::ExpTimes<Coll, Trks::iterator, PID::Proton>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Deuteron> resp_Deuteron = tof::ExpTimes<Coll, Trks::iterator, PID::Deuteron>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Triton> resp_Triton = tof::ExpTimes<Coll, Trks::iterator, PID::Triton>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Helium3> resp_Helium3 = tof::ExpTimes<Coll, Trks::iterator, PID::Helium3>(); + constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Alpha> resp_Alpha = tof::ExpTimes<Coll, Trks::iterator, PID::Alpha>(); - tofpidbeta.reserve(tracks.size()); tofpid.reserve(tracks.size()); - for (auto const& i : tracks) { - resp.UpdateTrack(i.p(), i.tofExpMom() / tof::Response::kCSPEED, i.length(), i.tofSignal()); - tofpidbeta(resp.GetBeta(), - resp.GetBetaExpectedSigma(), - resp.GetExpectedBeta(PID::Electron), - resp.GetBetaExpectedSigma(), - resp.GetBetaNumberOfSigmas(PID::Electron)); - tofpid( - resp.GetExpectedSignal(PID::Electron), - resp.GetExpectedSignal(PID::Muon), - resp.GetExpectedSignal(PID::Pion), - resp.GetExpectedSignal(PID::Kaon), - resp.GetExpectedSignal(PID::Proton), - resp.GetExpectedSignal(PID::Deuteron), - resp.GetExpectedSignal(PID::Triton), - resp.GetExpectedSignal(PID::Helium3), - resp.GetExpectedSignal(PID::Alpha), - resp.GetExpectedSigma(resp, PID::Electron), - resp.GetExpectedSigma(resp, PID::Muon), - resp.GetExpectedSigma(resp, PID::Pion), - resp.GetExpectedSigma(resp, PID::Kaon), - resp.GetExpectedSigma(resp, PID::Proton), - resp.GetExpectedSigma(resp, PID::Deuteron), - resp.GetExpectedSigma(resp, PID::Triton), - resp.GetExpectedSigma(resp, PID::Helium3), - resp.GetExpectedSigma(resp, PID::Alpha), - resp.GetSeparation(resp, PID::Electron), - resp.GetSeparation(resp, PID::Muon), - resp.GetSeparation(resp, PID::Pion), - resp.GetSeparation(resp, PID::Kaon), - resp.GetSeparation(resp, PID::Proton), - resp.GetSeparation(resp, PID::Deuteron), - resp.GetSeparation(resp, PID::Triton), - resp.GetSeparation(resp, PID::Helium3), - resp.GetSeparation(resp, PID::Alpha)); + for (auto const& trk : tracks) { + tofpid(resp_Electron.GetExpectedSignal(collision, trk), + resp_Muon.GetExpectedSignal(collision, trk), + resp_Pion.GetExpectedSignal(collision, trk), + resp_Kaon.GetExpectedSignal(collision, trk), + resp_Proton.GetExpectedSignal(collision, trk), + resp_Deuteron.GetExpectedSignal(collision, trk), + resp_Triton.GetExpectedSignal(collision, trk), + resp_Helium3.GetExpectedSignal(collision, trk), + resp_Alpha.GetExpectedSignal(collision, trk), + resp_Electron.GetExpectedSigma(resp, collision, trk), + resp_Muon.GetExpectedSigma(resp, collision, trk), + resp_Pion.GetExpectedSigma(resp, collision, trk), + resp_Kaon.GetExpectedSigma(resp, collision, trk), + resp_Proton.GetExpectedSigma(resp, collision, trk), + resp_Deuteron.GetExpectedSigma(resp, collision, trk), + resp_Triton.GetExpectedSigma(resp, collision, trk), + resp_Helium3.GetExpectedSigma(resp, collision, trk), + resp_Alpha.GetExpectedSigma(resp, collision, trk), + resp_Electron.GetSeparation(resp, collision, trk), + resp_Muon.GetSeparation(resp, collision, trk), + resp_Pion.GetSeparation(resp, collision, trk), + resp_Kaon.GetSeparation(resp, collision, trk), + resp_Proton.GetSeparation(resp, collision, trk), + resp_Deuteron.GetSeparation(resp, collision, trk), + resp_Triton.GetSeparation(resp, collision, trk), + resp_Helium3.GetSeparation(resp, collision, trk), + resp_Alpha.GetSeparation(resp, collision, trk)); + } + } +}; + +struct pidTOFTaskBeta { + using Trks = soa::Join<aod::Tracks, aod::TracksExtra>; + using Coll = aod::Collision; + Produces<aod::pidRespTOFbeta> tofpidbeta; + tof::Beta<Coll, Trks::iterator, PID::Electron> resp_Electron; + Configurable<float> expreso{"tof-expreso", 80, "Expected resolution for the computation of the expected beta"}; + + void init(o2::framework::InitContext&) + { + resp_Electron.mExpectedResolution = expreso.value; + } + + void process(Coll const& collision, Trks const& tracks) + { + tofpidbeta.reserve(tracks.size()); + for (auto const& trk : tracks) { + tofpidbeta(resp_Electron.GetBeta(collision, trk), + resp_Electron.GetExpectedSigma(collision, trk), + resp_Electron.GetExpectedSignal(collision, trk), + resp_Electron.GetExpectedSigma(collision, trk), + resp_Electron.GetSeparation(collision, trk)); } } }; @@ -140,25 +164,25 @@ struct pidTOFTaskQA { true, { {"hvertexz", ";Vtx_{z} (cm);Entries", {HistogramType::kTH1F, {{100, -20, 20}}}}, - {"htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}} // - {"htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 2}}}} // - } // + {"htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}} // + {"htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 2}}}} // + } // }; // Exp signal HistogramRegistry expected{ "expected", true, { - {"hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}}, - {"hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 10000}}}} // - } // + {"hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, + {"hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}} // + } // }; // T-Texp HistogramRegistry timediff{ @@ -208,18 +232,18 @@ struct pidTOFTaskQA { { #ifndef USE_REGISTRY event->Add<vertexz>(new TH1F("hvertexz", ";Vtx_{z} (cm);Entries", 100, -20, 20)); - event->Add<signal>(new TH2F("htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", 100, 0, 5, 100, 0, 10000)); + event->Add<signal>(new TH2F("htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", 100, 0, 5, 1000, 0, 2e6)); event->Add<tofbeta>(new TH2F("htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", 100, 0, 5, 100, 0, 2)); // - expected->Add<El>(new TH2F("hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", 100, 0, 5, 100, 0, 10000)); - expected->Add<Mu>(new TH2F("hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", 100, 0, 5, 100, 0, 10000)); - expected->Add<Pi>(new TH2F("hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", 100, 0, 5, 100, 0, 10000)); - expected->Add<Ka>(new TH2F("hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", 100, 0, 5, 100, 0, 10000)); - expected->Add<Pr>(new TH2F("hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", 100, 0, 5, 100, 0, 10000)); - expected->Add<De>(new TH2F("hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", 100, 0, 5, 100, 0, 10000)); - expected->Add<Tr>(new TH2F("hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", 100, 0, 5, 100, 0, 10000)); - expected->Add<He>(new TH2F("hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", 100, 0, 5, 100, 0, 10000)); - expected->Add<Al>(new TH2F("hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", 100, 0, 5, 100, 0, 10000)); + expected->Add<El>(new TH2F("hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<Mu>(new TH2F("hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<Pi>(new TH2F("hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<Ka>(new TH2F("hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<Pr>(new TH2F("hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<De>(new TH2F("hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<Tr>(new TH2F("hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<He>(new TH2F("hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", 100, 0, 5, 1000, 0, 2e6)); + expected->Add<Al>(new TH2F("hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", 100, 0, 5, 1000, 0, 2e6)); // timediff->Add<El>(new TH2F("htimediffEl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e})", 100, 0, 5, 100, -1000, 1000)); timediff->Add<Mu>(new TH2F("htimediffMu", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu})", 100, 0, 5, 100, -1000, 1000)); @@ -253,6 +277,9 @@ struct pidTOFTaskQA { for (auto i : tracks) { // + if (i.tofSignal() < 0) { // Skipping tracks without TOF + continue; + } const float tof = i.tofSignal() - collision.collisionTime(); #ifdef USE_REGISTRY event("htofsignal")->Fill(i.p(), i.tofSignal()); @@ -329,7 +356,12 @@ struct pidTOFTaskQA { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { auto workflow = WorkflowSpec{adaptAnalysisTask<pidTOFTask>("pidTOF-task")}; - if (cfgc.options().get<int>("add-qa")) { + const int add_beta = cfgc.options().get<int>("add-beta"); + const int add_qa = cfgc.options().get<int>("add-qa"); + if (add_beta || add_qa) { + workflow.push_back(adaptAnalysisTask<pidTOFTaskBeta>("pidTOFBeta-task")); + } + if (add_qa) { workflow.push_back(adaptAnalysisTask<pidTOFTaskQA>("pidTOFQA-task")); } return workflow; diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index b1fedaa72e64f..190b0e642e658 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -16,6 +16,7 @@ #include "PID/PIDResponse.h" #include <CCDB/BasicCCDBManager.h> #include "Analysis/HistHelpers.h" +#include "PID/PIDTPC.h" using namespace o2; using namespace o2::framework; @@ -33,8 +34,10 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) #include "Framework/runDataProcessing.h" struct pidTPCTask { + using Trks = soa::Join<aod::Tracks, aod::TracksExtra>; + using Coll = aod::Collision; Produces<aod::pidRespTPC> tpcpid; - DetectorResponse<tpc::Response> resp = DetectorResponse<tpc::Response>(); + DetectorResponse resp; Service<o2::ccdb::BasicCCDBManager> ccdb; Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; Configurable<std::string> signalname{"param-signal", "BetheBloch", "Name of the parametrization for the expected signal, used in both file and CCDB mode"}; @@ -53,48 +56,57 @@ struct pidTPCTask { // const std::string fname = paramfile.value; if (!fname.empty()) { // Loading the parametrization from file - resp.LoadParamFromFile(fname.data(), signalname.value, DetectorResponse<tpc::Response>::kSignal); - resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse<tpc::Response>::kSigma); + resp.LoadParamFromFile(fname.data(), signalname.value, DetectorResponse::kSignal); + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); } else { // Loading it from CCDB const std::string path = "Analysis/PID/TPC"; - resp.LoadParam(DetectorResponse<tpc::Response>::kSignal, ccdb->getForTimeStamp<Parametrization>(path + "/" + signalname.value, timestamp.value)); - resp.LoadParam(DetectorResponse<tpc::Response>::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); + resp.LoadParam(DetectorResponse::kSignal, ccdb->getForTimeStamp<Parametrization>(path + "/" + signalname.value, timestamp.value)); + resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value)); } } - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra> const& tracks) + void process(Coll const& collision, Trks const& tracks) { + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Electron> resp_Electron = tpc::ELoss<Coll, Trks::iterator, PID::Electron>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Muon> resp_Muon = tpc::ELoss<Coll, Trks::iterator, PID::Muon>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Pion> resp_Pion = tpc::ELoss<Coll, Trks::iterator, PID::Pion>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Kaon> resp_Kaon = tpc::ELoss<Coll, Trks::iterator, PID::Kaon>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Proton> resp_Proton = tpc::ELoss<Coll, Trks::iterator, PID::Proton>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Deuteron> resp_Deuteron = tpc::ELoss<Coll, Trks::iterator, PID::Deuteron>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Triton> resp_Triton = tpc::ELoss<Coll, Trks::iterator, PID::Triton>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Helium3> resp_Helium3 = tpc::ELoss<Coll, Trks::iterator, PID::Helium3>(); + constexpr tpc::ELoss<Coll, Trks::iterator, PID::Alpha> resp_Alpha = tpc::ELoss<Coll, Trks::iterator, PID::Alpha>(); + tpcpid.reserve(tracks.size()); - for (auto const& i : tracks) { - resp.UpdateTrack(i.tpcInnerParam(), i.tpcSignal(), i.tpcNClsShared()); + for (auto const& trk : tracks) { tpcpid( - resp.GetExpectedSignal(resp, PID::Electron), - resp.GetExpectedSignal(resp, PID::Muon), - resp.GetExpectedSignal(resp, PID::Pion), - resp.GetExpectedSignal(resp, PID::Kaon), - resp.GetExpectedSignal(resp, PID::Proton), - resp.GetExpectedSignal(resp, PID::Deuteron), - resp.GetExpectedSignal(resp, PID::Triton), - resp.GetExpectedSignal(resp, PID::Helium3), - resp.GetExpectedSignal(resp, PID::Alpha), - resp.GetExpectedSigma(resp, PID::Electron), - resp.GetExpectedSigma(resp, PID::Muon), - resp.GetExpectedSigma(resp, PID::Pion), - resp.GetExpectedSigma(resp, PID::Kaon), - resp.GetExpectedSigma(resp, PID::Proton), - resp.GetExpectedSigma(resp, PID::Deuteron), - resp.GetExpectedSigma(resp, PID::Triton), - resp.GetExpectedSigma(resp, PID::Helium3), - resp.GetExpectedSigma(resp, PID::Alpha), - resp.GetSeparation(resp, PID::Electron), - resp.GetSeparation(resp, PID::Muon), - resp.GetSeparation(resp, PID::Pion), - resp.GetSeparation(resp, PID::Kaon), - resp.GetSeparation(resp, PID::Proton), - resp.GetSeparation(resp, PID::Deuteron), - resp.GetSeparation(resp, PID::Triton), - resp.GetSeparation(resp, PID::Helium3), - resp.GetSeparation(resp, PID::Alpha)); + resp_Electron.GetExpectedSignal(resp, collision, trk), + resp_Muon.GetExpectedSignal(resp, collision, trk), + resp_Pion.GetExpectedSignal(resp, collision, trk), + resp_Kaon.GetExpectedSignal(resp, collision, trk), + resp_Proton.GetExpectedSignal(resp, collision, trk), + resp_Deuteron.GetExpectedSignal(resp, collision, trk), + resp_Triton.GetExpectedSignal(resp, collision, trk), + resp_Helium3.GetExpectedSignal(resp, collision, trk), + resp_Alpha.GetExpectedSignal(resp, collision, trk), + resp_Electron.GetExpectedSigma(resp, collision, trk), + resp_Muon.GetExpectedSigma(resp, collision, trk), + resp_Pion.GetExpectedSigma(resp, collision, trk), + resp_Kaon.GetExpectedSigma(resp, collision, trk), + resp_Proton.GetExpectedSigma(resp, collision, trk), + resp_Deuteron.GetExpectedSigma(resp, collision, trk), + resp_Triton.GetExpectedSigma(resp, collision, trk), + resp_Helium3.GetExpectedSigma(resp, collision, trk), + resp_Alpha.GetExpectedSigma(resp, collision, trk), + resp_Electron.GetSeparation(resp, collision, trk), + resp_Muon.GetSeparation(resp, collision, trk), + resp_Pion.GetSeparation(resp, collision, trk), + resp_Kaon.GetSeparation(resp, collision, trk), + resp_Proton.GetSeparation(resp, collision, trk), + resp_Deuteron.GetSeparation(resp, collision, trk), + resp_Triton.GetSeparation(resp, collision, trk), + resp_Helium3.GetSeparation(resp, collision, trk), + resp_Alpha.GetSeparation(resp, collision, trk)); } } }; From a740637a016f2f2f93fd73cc454dc8647bd70d06 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Wed, 14 Oct 2020 16:41:07 +0200 Subject: [PATCH 0959/1751] adapt file reading part to new data structures for clusters and MC --- .../DataFormatsTPC/ClusterNativeHelper.h | 6 +-- .../Detectors/TPC/src/ClusterNativeHelper.cxx | 40 +++++++++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h index bfe9bad7a5458..7c316f3deba9c 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h @@ -18,6 +18,7 @@ #include "DataFormatsTPC/ClusterNative.h" #include "DataFormatsTPC/ClusterGroupAttribute.h" #include "DataFormatsTPC/Constants.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include <gsl/gsl> @@ -132,6 +133,7 @@ class ClusterNativeHelper { public: using MCLabelContainer = o2::dataformats::MCLabelContainer; + using ConstMCLabelContainer = o2::dataformats::ConstMCLabelContainer; using ConstMCLabelContainerView = o2::dataformats::ConstMCLabelContainerView; using ConstMCLabelContainerViewWithBuffer = ClusterNativeAccess::ConstMCLabelContainerViewWithBuffer; @@ -279,10 +281,8 @@ class ClusterNativeHelper std::array<std::vector<char>*, NSectors> mSectorRaw = {nullptr}; /// the array of raw buffers std::array<size_t, NSectors> mSectorRawSize = {0}; - /// the array of MC label containers - std::array<std::vector<MCLabelContainer>, NSectors> mSectorMC; /// pointers on the elements of array of MC label containers - std::array<std::vector<MCLabelContainer>*, NSectors> mSectorMCPtr = {nullptr}; + std::array<dataformats::IOMCTruthContainerView*, NSectors> mSectorMCPtr{}; }; /// @class TreeWriter diff --git a/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx b/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx index 0d30744b3ee83..10c38de78b7de 100644 --- a/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx +++ b/DataFormats/Detectors/TPC/src/ClusterNativeHelper.cxx @@ -114,10 +114,13 @@ void ClusterNativeHelper::Reader::init(const char* filename, const char* treenam LOG(ERROR) << "can not find tree " << mTreeName << " in file " << filename; return; } + + const bool singleBranch = mTree->GetBranch(mDataBranchName.data()); + size_t nofDataBranches = 0; size_t nofMCBranches = 0; for (size_t sector = 0; sector < NSectors; ++sector) { - auto branchname = mDataBranchName + "_" + std::to_string(sector); + auto branchname = singleBranch ? mDataBranchName : mDataBranchName + "_" + std::to_string(sector); TBranch* branch = mTree->GetBranch(branchname.c_str()); if (branch) { TBranch* sizebranch = mTree->GetBranch((branchname + "Size").c_str()); @@ -129,13 +132,16 @@ void ClusterNativeHelper::Reader::init(const char* filename, const char* treenam LOG(ERROR) << "can not find corresponding 'Size' branch for data branch " << branchname << ", skipping it"; } } - branchname = mMCBranchName + "_" + std::to_string(sector); + branchname = singleBranch ? mMCBranchName : mMCBranchName + "_" + std::to_string(sector); branch = mTree->GetBranch(branchname.c_str()); if (branch) { - mSectorMCPtr[sector] = &mSectorMC[sector]; branch->SetAddress(&mSectorMCPtr[sector]); ++nofMCBranches; } + + if (singleBranch) { + break; + } } LOG(INFO) << "reading " << nofDataBranches << " data branch(es) and " << nofMCBranches << " mc branch(es)"; } @@ -163,18 +169,28 @@ void ClusterNativeHelper::Reader::clear() int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, std::unique_ptr<ClusterNative[]>& clusterBuffer, ConstMCLabelContainerViewWithBuffer& mcBuffer) { + std::vector<gsl::span<const char>> clustersTPC; + std::vector<ConstMCLabelContainer> constMCLabelContainers; + std::vector<ConstMCLabelContainerView> constMCLabelContainerViews; + for (size_t index = 0; index < mSectorRaw.size(); ++index) { - if (mSectorRaw[index] && mSectorRaw[index]->size() != mSectorRawSize[index]) { - LOG(ERROR) << "inconsistent raw size for sector " << index << ": " << mSectorRaw[index]->size() << " v.s. " << mSectorRawSize[index]; - mSectorRaw[index]->clear(); + if (mSectorRaw[index]) { + if (mSectorRaw[index]->size() != mSectorRawSize[index]) { + LOG(ERROR) << "inconsistent raw size for sector " << index << ": " << mSectorRaw[index]->size() << " v.s. " << mSectorRawSize[index]; + mSectorRaw[index]->clear(); + } else { + clustersTPC.emplace_back(mSectorRaw[index]->data(), mSectorRawSize[index]); + } + } + if (mSectorMCPtr[index]) { + auto& view = constMCLabelContainers.emplace_back(); + mSectorMCPtr[index]->copyandflatten(view); + constMCLabelContainerViews.emplace_back(view); } } - // after changing this ClusterNative transport format, this functionality needs - // to be adapted - throw std::runtime_error("code path currently not supported"); - //int result = fillIndex(clusterIndex, clusterBuffer, mcBuffer, mSectorRaw, mSectorMC, [](auto&) { return true; }); - //return result; - return 0; + + int result = fillIndex(clusterIndex, clusterBuffer, mcBuffer, clustersTPC, constMCLabelContainerViews, [](auto&) { return true; }); + return result; } int ClusterNativeHelper::Reader::parseSector(const char* buffer, size_t size, gsl::span<ConstMCLabelContainerView const> const& mcinput, ClusterNativeAccess& clusterIndex, From b71fd81a6a79e54a96ebdd2b304eda283defcfac Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 15 Oct 2020 11:54:00 +0200 Subject: [PATCH 0960/1751] DPL: add metadata to InputSpec (#4598) This will be useful for things like enumerations and CCDB access. --- Framework/Core/include/Framework/InputSpec.h | 40 +++++++++--- Framework/Core/src/InputSpec.cxx | 43 ++++++++++--- .../Core/src/WorkflowSerializationHelpers.cxx | 62 ++++++++++++++----- .../Core/test/test_WorkflowSerialization.cxx | 2 +- .../TestWorkflows/src/o2DiamondWorkflow.cxx | 2 +- 5 files changed, 113 insertions(+), 36 deletions(-) diff --git a/Framework/Core/include/Framework/InputSpec.h b/Framework/Core/include/Framework/InputSpec.h index 87dbed0af3246..d9e3f3201d66d 100644 --- a/Framework/Core/include/Framework/InputSpec.h +++ b/Framework/Core/include/Framework/InputSpec.h @@ -13,14 +13,13 @@ #include "Framework/Lifetime.h" #include "Framework/ConcreteDataMatcher.h" #include "Framework/DataDescriptorMatcher.h" +#include "Framework/ConfigParamSpec.h" #include <string> #include <ostream> #include <variant> -namespace o2 -{ -namespace framework +namespace o2::framework { /// A selector for some kind of data being processed, either in @@ -28,23 +27,46 @@ namespace framework /// specific payloads in a timeframe. struct InputSpec { /// Create a fully qualified InputSpec - InputSpec(std::string binding_, header::DataOrigin origin_, header::DataDescription description_, header::DataHeader::SubSpecificationType subSpec_, enum Lifetime lifetime_ = Lifetime::Timeframe); + InputSpec(std::string binding_, + header::DataOrigin origin_, + header::DataDescription description_, + header::DataHeader::SubSpecificationType subSpec_, + enum Lifetime lifetime_ = Lifetime::Timeframe, + std::vector<ConfigParamSpec> const& metadata_ = {}); /// Create a fully qualified InputSpec (alternative syntax) - InputSpec(std::string binding_, ConcreteDataMatcher const& dataType, enum Lifetime lifetime_ = Lifetime::Timeframe); + InputSpec(std::string binding_, + ConcreteDataMatcher const& dataType, + enum Lifetime lifetime_ = Lifetime::Timeframe, + std::vector<ConfigParamSpec> const& metadata_ = {}); /// Create a fully qualified InputSpec where the subSpec is 0 - InputSpec(std::string binding_, header::DataOrigin origin_, header::DataDescription description_, enum Lifetime lifetime_ = Lifetime::Timeframe); + InputSpec(std::string binding_, + header::DataOrigin origin_, + header::DataDescription description_, + enum Lifetime lifetime_ = Lifetime::Timeframe, + std::vector<ConfigParamSpec> const& metadata_ = {}); /// Create an InputSpec which does not check for the subSpec. - InputSpec(std::string binding_, ConcreteDataTypeMatcher const& dataType, enum Lifetime lifetime_ = Lifetime::Timeframe); - InputSpec(std::string binding, data_matcher::DataDescriptorMatcher&& matcher); + InputSpec(std::string binding_, + ConcreteDataTypeMatcher const& dataType, + enum Lifetime lifetime_ = Lifetime::Timeframe, + std::vector<ConfigParamSpec> const& metadata_ = {}); + InputSpec(std::string binding, + data_matcher::DataDescriptorMatcher&& matcher, + std::vector<ConfigParamSpec> const& metadata_ = {}); + /// A mnemonic name for the input spec. std::string binding; + + /// The actual matcher for the input spec. std::variant<ConcreteDataMatcher, data_matcher::DataDescriptorMatcher> matcher; + enum Lifetime lifetime; + /// A set of configurables which can be used to customise the InputSpec. + std::vector<ConfigParamSpec> metadata; + friend std::ostream& operator<<(std::ostream& stream, InputSpec const& arg); bool operator==(InputSpec const& that) const; }; -} // namespace framework } // namespace o2 #endif diff --git a/Framework/Core/src/InputSpec.cxx b/Framework/Core/src/InputSpec.cxx index f67d8bb047da3..d52adfc24564c 100644 --- a/Framework/Core/src/InputSpec.cxx +++ b/Framework/Core/src/InputSpec.cxx @@ -12,44 +12,67 @@ #include "Framework/DataSpecUtils.h" #include <variant> +#include <vector> namespace o2 { namespace framework { -InputSpec::InputSpec(std::string binding_, ConcreteDataMatcher const& concrete, enum Lifetime lifetime_) +InputSpec::InputSpec(std::string binding_, + ConcreteDataMatcher const& concrete, + enum Lifetime lifetime_, + std::vector<ConfigParamSpec> const& metadata_) : binding{binding_}, matcher{concrete}, - lifetime{lifetime_} + lifetime{lifetime_}, + metadata{metadata_} { } -InputSpec::InputSpec(std::string binding_, header::DataOrigin origin_, header::DataDescription description_, header::DataHeader::SubSpecificationType subSpec_, enum Lifetime lifetime_) +InputSpec::InputSpec(std::string binding_, + header::DataOrigin origin_, + header::DataDescription description_, + header::DataHeader::SubSpecificationType subSpec_, + enum Lifetime lifetime_, + std::vector<ConfigParamSpec> const& metadata_) : binding{binding_}, matcher{ConcreteDataMatcher{origin_, description_, subSpec_}}, - lifetime{lifetime_} + lifetime{lifetime_}, + metadata{metadata_} { } -InputSpec::InputSpec(std::string binding_, header::DataOrigin origin_, header::DataDescription description_, enum Lifetime lifetime_) +InputSpec::InputSpec(std::string binding_, + header::DataOrigin origin_, + header::DataDescription description_, + enum Lifetime lifetime_, + std::vector<ConfigParamSpec> const& metadata_) : binding{binding_}, matcher{ConcreteDataMatcher{origin_, description_, 0}}, - lifetime{lifetime_} + lifetime{lifetime_}, + metadata{metadata_} { } -InputSpec::InputSpec(std::string binding_, ConcreteDataTypeMatcher const& dataType, enum Lifetime lifetime_) +InputSpec::InputSpec(std::string binding_, + ConcreteDataTypeMatcher const& dataType, + enum Lifetime lifetime_, + std::vector<ConfigParamSpec> const& metadata_) : binding{binding_}, matcher{DataSpecUtils::dataDescriptorMatcherFrom(dataType)}, - lifetime{lifetime_} + lifetime{lifetime_}, + metadata{metadata_} { } -InputSpec::InputSpec(std::string binding_, data_matcher::DataDescriptorMatcher&& matcher_) +InputSpec::InputSpec(std::string binding_, + data_matcher::DataDescriptorMatcher&& matcher_, + std::vector<ConfigParamSpec> const& metadata_) : binding{binding_}, matcher{matcher_}, - lifetime{Lifetime::Timeframe} + lifetime{Lifetime::Timeframe}, + metadata{metadata_} { } diff --git a/Framework/Core/src/WorkflowSerializationHelpers.cxx b/Framework/Core/src/WorkflowSerializationHelpers.cxx index 22e13c0275948..1b892d19405c5 100644 --- a/Framework/Core/src/WorkflowSerializationHelpers.cxx +++ b/Framework/Core/src/WorkflowSerializationHelpers.cxx @@ -51,6 +51,7 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, IN_INPUT_DESCRIPTION, IN_INPUT_SUBSPEC, IN_INPUT_LIFETIME, + IN_INPUT_OPTIONS, IN_OUTPUT, IN_OUTPUT_BINDING, IN_OUTPUT_ORIGIN, @@ -135,6 +136,9 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, case State::IN_INPUT_LIFETIME: s << "IN_INPUT_LIFETIME"; break; + case State::IN_INPUT_OPTIONS: + s << "IN_INPUT_OPTIONS"; + break; case State::IN_OUTPUT: s << "IN_OUTPUT"; break; @@ -202,7 +206,7 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, WorkflowImporter(std::vector<DataProcessorSpec>& o, std::vector<DataProcessorInfo>& m) : states{}, - output{o}, + dataProcessors{o}, metadata{m} { push(State::IN_START); @@ -215,9 +219,9 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, push(State::IN_EXECUTION); } else if (in(State::IN_DATAPROCESSORS)) { push(State::IN_DATAPROCESSOR); - output.push_back(DataProcessorSpec{}); + dataProcessors.push_back(DataProcessorSpec{}); } else if (in(State::IN_DATAPROCESSOR)) { - output.push_back(DataProcessorSpec{}); + dataProcessors.push_back(DataProcessorSpec{}); } else if (in(State::IN_INPUTS)) { push(State::IN_INPUT); inputHasSubSpec = false; @@ -242,16 +246,17 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, enter("END_OBJECT"); if (in(State::IN_INPUT)) { if (inputHasSubSpec) { - output.back().inputs.push_back(InputSpec(binding, origin, description, subspec, lifetime)); + dataProcessors.back().inputs.push_back(InputSpec(binding, origin, description, subspec, lifetime, inputOptions)); } else { - output.back().inputs.push_back(InputSpec(binding, {origin, description}, lifetime)); + dataProcessors.back().inputs.push_back(InputSpec(binding, {origin, description}, lifetime, inputOptions)); } + inputOptions.clear(); inputHasSubSpec = false; } else if (in(State::IN_OUTPUT)) { if (outputHasSubSpec) { - output.back().outputs.push_back(OutputSpec({binding}, origin, description, subspec, lifetime)); + dataProcessors.back().outputs.push_back(OutputSpec({binding}, origin, description, subspec, lifetime)); } else { - output.back().outputs.push_back(OutputSpec({binding}, {origin, description}, lifetime)); + dataProcessors.back().outputs.push_back(OutputSpec({binding}, {origin, description}, lifetime)); } outputHasSubSpec = false; } else if (in(State::IN_OPTION)) { @@ -282,9 +287,11 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, } // Depending on the previous state, push options to the right place. if (previousIs(State::IN_OPTIONS)) { - output.back().options.push_back(*opt); + dataProcessors.back().options.push_back(*opt); } else if (previousIs(State::IN_WORKFLOW_OPTIONS)) { metadata.back().workflowOptions.push_back(*opt); + } else if (previousIs(State::IN_INPUT_OPTIONS)) { + inputOptions.push_back(*opt); } else { assert(false); } @@ -301,6 +308,8 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, } else if (in(State::IN_INPUTS)) { push(State::IN_INPUT); inputHasSubSpec = false; + } else if (in(State::IN_INPUT_OPTIONS)) { + push(State::IN_OPTION); } else if (in(State::IN_OUTPUTS)) { push(State::IN_OUTPUT); outputHasSubSpec = false; @@ -345,6 +354,8 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, inputHasSubSpec = true; } else if (in(State::IN_INPUT) && strncmp(str, "lifetime", length) == 0) { push(State::IN_INPUT_LIFETIME); + } else if (in(State::IN_INPUT) && strncmp(str, "metadata", length) == 0) { + push(State::IN_INPUT_OPTIONS); } else if (in(State::IN_OUTPUT) && strncmp(str, "binding", length) == 0) { push(State::IN_OUTPUT_BINDING); } else if (in(State::IN_OUTPUT) && strncmp(str, "origin", length) == 0) { @@ -404,8 +415,8 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, enter(str); auto s = std::string(str, length); if (in(State::IN_DATAPROCESSOR_NAME)) { - assert(output.size()); - output.back().name = s; + assert(dataProcessors.size()); + dataProcessors.back().name = s; } else if (in(State::IN_METADATUM_NAME)) { assert(metadata.size()); metadata.back().name = s; @@ -459,13 +470,13 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, } else if (in(State::IN_OUTPUT_LIFETIME)) { lifetime = (Lifetime)i; } else if (in(State::IN_DATAPROCESSOR_RANK)) { - output.back().rank = i; + dataProcessors.back().rank = i; } else if (in(State::IN_DATAPROCESSOR_N_SLOTS)) { - output.back().nSlots = i; + dataProcessors.back().nSlots = i; } else if (in(State::IN_DATAPROCESSOR_TIMESLICE_ID)) { - output.back().inputTimeSliceId = i; + dataProcessors.back().inputTimeSliceId = i; } else if (in(State::IN_DATAPROCESSOR_MAX_TIMESLICES)) { - output.back().maxInputTimeslices = i; + dataProcessors.back().maxInputTimeslices = i; } pop(); return true; @@ -526,8 +537,9 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, std::ostringstream debug; std::vector<State> states; std::string spec; - std::vector<DataProcessorSpec>& output; + std::vector<DataProcessorSpec>& dataProcessors; std::vector<DataProcessorInfo>& metadata; + std::vector<ConfigParamSpec> inputOptions; std::string binding; header::DataOrigin origin; header::DataDescription description; @@ -612,6 +624,26 @@ void WorkflowSerializationHelpers::dump(std::ostream& out, } w.Key("lifetime"); w.Uint((int)input.lifetime); + if (input.metadata.empty() == false) { + w.Key("metadata"); + w.StartArray(); + for (auto& metadata : input.metadata) { + w.StartObject(); + w.Key("name"); + w.String(metadata.name.c_str()); + auto s = std::to_string(int(metadata.type)); + w.Key("type"); + w.String(s.c_str()); + std::ostringstream oss; + oss << metadata.defaultValue; + w.Key("defaultValue"); + w.String(oss.str().c_str()); + w.Key("help"); + w.String(metadata.help.c_str()); + w.EndObject(); + } + w.EndArray(); + } w.EndObject(); } w.EndArray(); diff --git a/Framework/Core/test/test_WorkflowSerialization.cxx b/Framework/Core/test/test_WorkflowSerialization.cxx index d9868e9bcccde..511d4ccca5307 100644 --- a/Framework/Core/test/test_WorkflowSerialization.cxx +++ b/Framework/Core/test/test_WorkflowSerialization.cxx @@ -22,7 +22,7 @@ BOOST_AUTO_TEST_CASE(TestVerifyWorkflow) using namespace o2::framework; WorkflowSpec w0{ DataProcessorSpec{"A", - {InputSpec{"foo", "A", "COLLISIONCONTEXT", 1, Lifetime::Condition}}, + {InputSpec{"foo", "A", "COLLISIONCONTEXT", 1, Lifetime::Condition, {ConfigParamSpec{"aUrl", VariantType::String, "foo/bar", {"A InputSpec option"}}}}}, {OutputSpec{{"bar"}, "C", "D", 2, Lifetime::Timeframe}}, AlgorithmSpec{[](ProcessingContext& ctx) {}}, {ConfigParamSpec{"aInt", VariantType::Int, 0, {"An Int"}}, diff --git a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx index c280248e2496b..eb1099cdbb7a9 100644 --- a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx +++ b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx @@ -65,7 +65,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& specs) })}, {ConfigParamSpec{"some-device-param", VariantType::Int, 1, {"Some device parameter"}}}}, {"B", - {InputSpec{"x", "TST", "A1"}}, + {InputSpec{"x", "TST", "A1", Lifetime::Timeframe, {ConfigParamSpec{"somestring", VariantType::String, "", {"Some input param"}}}}}, {OutputSpec{{"b1"}, "TST", "B1"}}, simplePipe("b1", 0)}, {"C", From 122d3c8bc94322ce74863049126cb58e6285abeb Mon Sep 17 00:00:00 2001 From: Timo Wilken <timo.wilken@cern.ch> Date: Thu, 15 Oct 2020 11:05:15 +0000 Subject: [PATCH 0961/1751] Don't git fetch --unshallow, as we've already got a full clone (#4603) --- .github/workflows/code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index aa9d8f2651b78..d663eac1a2fae 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -72,7 +72,7 @@ jobs: echo "Opening a PR to your branch with the fixes" git commit -m "Please consider the following formatting changes" -a git show | cat - git fetch --unshallow https://github.com/AliceO2Group/AliceO2.git pull/${{ github.event.pull_request.number }}/head + git fetch https://github.com/AliceO2Group/AliceO2.git pull/${{ github.event.pull_request.number }}/head git push --set-upstream https://alibuild:$ALIBUILD_GITHUB_TOKEN@github.com/alibuild/AliceO2.git HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f echo ::set-output name=clean::false fi From c587deb022c9cc76dcc3d9ca84e4d8c0dab38a64 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 15 Oct 2020 14:46:28 +0200 Subject: [PATCH 0962/1751] DPL Analysis: rework TableToTree (#4589) * Hide internal details of the conversion. * Attempt at freeing the memory as soon as possible. --- .../Core/include/Framework/TableTreeHelpers.h | 128 +--------- Framework/Core/src/AODReaderHelpers.cxx | 6 +- Framework/Core/src/TableTreeHelpers.cxx | 240 +++++++++++------- Framework/Core/test/benchmark_TreeToTable.cxx | 7 +- Framework/Core/test/test_TreeToTable.cxx | 8 +- 5 files changed, 169 insertions(+), 220 deletions(-) diff --git a/Framework/Core/include/Framework/TableTreeHelpers.h b/Framework/Core/include/Framework/TableTreeHelpers.h index c58484631f914..519c2aa418878 100644 --- a/Framework/Core/include/Framework/TableTreeHelpers.h +++ b/Framework/Core/include/Framework/TableTreeHelpers.h @@ -7,8 +7,8 @@ // 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_TABLETREE_H -#define FRAMEWORK_TABLETREE_H +#ifndef O2_FRAMEWORK_TABLETREEHELPERS_H_ +#define O2_FRAMEWORK_TABLETREEHELPERS_H_ #include "TFile.h" #include "TTreeReader.h" @@ -17,9 +17,7 @@ #include "TableBuilder.h" // ============================================================================= -namespace o2 -{ -namespace framework +namespace o2::framework { // ----------------------------------------------------------------------------- @@ -117,133 +115,29 @@ class TableToTree TTree* process(); }; -// ----------------------------------------------------------------------------- -// TreeToTable allows to fill the contents of a given TTree to an arrow::Table -// ColumnIterator is used by TreeToTable -// -// To copy the contents of a tree tr to a table ta do: -// . TreeToTable t2t(tr); -// . t2t.addColumn(columnname1); t2t.addColumn(columnname2); ... -// OR -// t2t.addAllColumns(); -// . auto ta = t2t.process(); -// -// ............................................................................. -class ColumnIterator -{ - - private: - // all the possible TTreeReaderValue<T> types - TTreeReaderValue<bool>* mReaderValue_o = nullptr; - TTreeReaderValue<uint8_t>* mReaderValue_ub = nullptr; - TTreeReaderValue<uint16_t>* mReaderValue_us = nullptr; - TTreeReaderValue<uint32_t>* mReaderValue_ui = nullptr; - TTreeReaderValue<ULong64_t>* mReaderValue_ul = nullptr; - TTreeReaderValue<int8_t>* mReaderValue_b = nullptr; - TTreeReaderValue<int16_t>* mReaderValue_s = nullptr; - TTreeReaderValue<int32_t>* mReaderValue_i = nullptr; - TTreeReaderValue<int64_t>* mReaderValue_l = nullptr; - TTreeReaderValue<float>* mReaderValue_f = nullptr; - TTreeReaderValue<double>* mReaderValue_d = nullptr; - - // all the possible TTreeReaderArray<T> types - TTreeReaderArray<bool>* mReaderArray_o = nullptr; - TTreeReaderArray<uint8_t>* mReaderArray_ub = nullptr; - TTreeReaderArray<uint16_t>* mReaderArray_us = nullptr; - TTreeReaderArray<uint32_t>* mReaderArray_ui = nullptr; - TTreeReaderArray<uint64_t>* mReaderArray_ul = nullptr; - TTreeReaderArray<int8_t>* mReaderArray_b = nullptr; - TTreeReaderArray<int16_t>* mReaderArray_s = nullptr; - TTreeReaderArray<int32_t>* mReaderArray_i = nullptr; - TTreeReaderArray<int64_t>* mReaderArray_l = nullptr; - TTreeReaderArray<float>* mReaderArray_f = nullptr; - TTreeReaderArray<double>* mReaderArray_d = nullptr; - - // all the possible arrow::TBuilder types - arrow::FixedSizeListBuilder* mTableBuilder_list = nullptr; - - arrow::BooleanBuilder* mTableBuilder_o = nullptr; - arrow::UInt8Builder* mTableBuilder_ub = nullptr; - arrow::UInt16Builder* mTableBuilder_us = nullptr; - arrow::UInt32Builder* mTableBuilder_ui = nullptr; - arrow::UInt64Builder* mTableBuilder_ul = nullptr; - arrow::Int8Builder* mTableBuilder_b = nullptr; - arrow::Int16Builder* mTableBuilder_s = nullptr; - arrow::Int32Builder* mTableBuilder_i = nullptr; - arrow::Int64Builder* mTableBuilder_l = nullptr; - arrow::FloatBuilder* mTableBuilder_f = nullptr; - arrow::DoubleBuilder* mTableBuilder_d = nullptr; - - bool mStatus = false; - EDataType mElementType; - int64_t mNumberElements; - const char* mColumnName; - - std::shared_ptr<arrow::Field> mField; - std::shared_ptr<arrow::Array> mArray; - - public: - ColumnIterator(TTreeReader* reader, const char* colname); - ~ColumnIterator(); - - // has the iterator been properly initialized - bool getStatus(); - - // copy the TTreeReaderValue to the arrow::TBuilder - void push(); - - // reserve enough space to push s elements without reallocating - void reserve(size_t s); - - std::shared_ptr<arrow::Array> getArray() { return mArray; } - std::shared_ptr<arrow::Field> getSchema() { return mField; } - - // finish the arrow::TBuilder - // with this mArray is prepared to be used in arrow::Table::Make - void finish(); -}; - class TreeToTable { private: - // the TTreeReader allows to efficiently loop over - // the rows of a TTree - TTreeReader* mTreeReader; - - // a list of ColumnIterator* - std::vector<std::unique_ptr<ColumnIterator>> mColumnIterators; - - // Append next set of branch values to the - // corresponding table columns - void push(); + std::shared_ptr<arrow::Table> mTable; + std::vector<std::string> mColumnNames; public: - TreeToTable(TTree* tree); - ~TreeToTable(); - // add a column to be included in the arrow::table - bool addColumn(const char* colname); - - // add all columns - bool addAllColumns(); + void addColumn(const char* colname); - // reserve enough space to push s rows without reallocating - void reserve(size_t s); + // add all branches in @a tree as columns + bool addAllColumns(TTree* tree); // do the looping with the TTreeReader - void fill(); + void fill(TTree* tree); // create the table std::shared_ptr<arrow::Table> finalize(); - - // do the looping with the TTreeReader and create the table - std::shared_ptr<arrow::Table> process(); }; // ----------------------------------------------------------------------------- -} // namespace framework -} // namespace o2 +} // namespace o2::framework // ============================================================================= -#endif // FRAMEWORK_TABLETREE_H +#endif // O2_FRAMEWORK_TABLETREEHELPERS_H_ diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 59908ad33e9ac..93809cb19096c 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -154,12 +154,12 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() } auto o = Output(dh); - auto& t2t = outputs.make<TreeToTable>(o, tr); + auto& t2t = outputs.make<TreeToTable>(o); // add branches to read auto colnames = aod::datamodel::getColumnNames(dh); if (colnames.size() == 0) { - t2t.addAllColumns(); + t2t.addAllColumns(tr); } else { for (auto colname : colnames) { t2t.addColumn(colname.c_str()); @@ -167,7 +167,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() } // fill the table - t2t.fill(); + t2t.fill(tr); } }); })}; diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 6e1857b32d817..6137d0c38e281 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -8,15 +8,103 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/TableTreeHelpers.h" +#include <stdexcept> #include "Framework/Logger.h" #include "arrow/type_traits.h" -namespace o2 +namespace o2::framework { -namespace framework + +namespace +{ +// ----------------------------------------------------------------------------- +// TreeToTable allows to fill the contents of a given TTree to an arrow::Table +// ColumnIterator is used by TreeToTable +// +// To copy the contents of a tree tr to a table ta do: +// . TreeToTable t2t(tr); +// . t2t.addColumn(columnname1); t2t.addColumn(columnname2); ... +// OR +// t2t.addAllColumns(); +// . auto ta = t2t.process(); +// +// ............................................................................. +class ColumnIterator { + private: + // all the possible TTreeReaderValue<T> types + TTreeReaderValue<bool>* mReaderValue_o = nullptr; + TTreeReaderValue<uint8_t>* mReaderValue_ub = nullptr; + TTreeReaderValue<uint16_t>* mReaderValue_us = nullptr; + TTreeReaderValue<uint32_t>* mReaderValue_ui = nullptr; + TTreeReaderValue<ULong64_t>* mReaderValue_ul = nullptr; + TTreeReaderValue<int8_t>* mReaderValue_b = nullptr; + TTreeReaderValue<int16_t>* mReaderValue_s = nullptr; + TTreeReaderValue<int32_t>* mReaderValue_i = nullptr; + TTreeReaderValue<int64_t>* mReaderValue_l = nullptr; + TTreeReaderValue<float>* mReaderValue_f = nullptr; + TTreeReaderValue<double>* mReaderValue_d = nullptr; + + // all the possible TTreeReaderArray<T> types + TTreeReaderArray<bool>* mReaderArray_o = nullptr; + TTreeReaderArray<uint8_t>* mReaderArray_ub = nullptr; + TTreeReaderArray<uint16_t>* mReaderArray_us = nullptr; + TTreeReaderArray<uint32_t>* mReaderArray_ui = nullptr; + TTreeReaderArray<uint64_t>* mReaderArray_ul = nullptr; + TTreeReaderArray<int8_t>* mReaderArray_b = nullptr; + TTreeReaderArray<int16_t>* mReaderArray_s = nullptr; + TTreeReaderArray<int32_t>* mReaderArray_i = nullptr; + TTreeReaderArray<int64_t>* mReaderArray_l = nullptr; + TTreeReaderArray<float>* mReaderArray_f = nullptr; + TTreeReaderArray<double>* mReaderArray_d = nullptr; + + // all the possible arrow::TBuilder types + arrow::FixedSizeListBuilder* mTableBuilder_list = nullptr; + + arrow::BooleanBuilder* mTableBuilder_o = nullptr; + arrow::UInt8Builder* mTableBuilder_ub = nullptr; + arrow::UInt16Builder* mTableBuilder_us = nullptr; + arrow::UInt32Builder* mTableBuilder_ui = nullptr; + arrow::UInt64Builder* mTableBuilder_ul = nullptr; + arrow::Int8Builder* mTableBuilder_b = nullptr; + arrow::Int16Builder* mTableBuilder_s = nullptr; + arrow::Int32Builder* mTableBuilder_i = nullptr; + arrow::Int64Builder* mTableBuilder_l = nullptr; + arrow::FloatBuilder* mTableBuilder_f = nullptr; + arrow::DoubleBuilder* mTableBuilder_d = nullptr; + + bool mStatus = false; + EDataType mElementType; + int64_t mNumberElements; + const char* mColumnName; + + std::shared_ptr<arrow::Field> mField; + std::shared_ptr<arrow::Array> mArray; + + public: + ColumnIterator(TTreeReader& reader, const char* colname); + ~ColumnIterator(); + + // has the iterator been properly initialized + bool getStatus(); + + // copy the TTreeReaderValue to the arrow::TBuilder + void push(); + + // reserve enough space to push s elements without reallocating + void reserve(size_t s); + + std::shared_ptr<arrow::Array> getArray() { return mArray; } + std::shared_ptr<arrow::Field> getSchema() { return mField; } + + // finish the arrow::TBuilder + // with this mArray is prepared to be used in arrow::Table::Make + void finish(); +}; +} // namespace + // is used in TableToTree BranchIterator::BranchIterator(TTree* tree, std::shared_ptr<arrow::ChunkedArray> col, std::shared_ptr<arrow::Field> field) { @@ -370,11 +458,11 @@ TTree* TableToTree::process() } // is used in TreeToTable -ColumnIterator::ColumnIterator(TTreeReader* reader, const char* colname) +ColumnIterator::ColumnIterator(TTreeReader& reader, const char* colname) { // find branch - auto tree = reader->GetTree(); + auto tree = reader.GetTree(); if (!tree) { LOGP(FATAL, "Can not locate tree!"); return; @@ -412,47 +500,47 @@ ColumnIterator::ColumnIterator(TTreeReader* reader, const char* colname) if (mNumberElements == 1) { switch (mElementType) { case EDataType::kBool_t: - mReaderValue_o = new TTreeReaderValue<bool>(*reader, mColumnName); + mReaderValue_o = new TTreeReaderValue<bool>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(bool, 1, mTableBuilder_o); break; case EDataType::kUChar_t: - mReaderValue_ub = new TTreeReaderValue<uint8_t>(*reader, mColumnName); + mReaderValue_ub = new TTreeReaderValue<uint8_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint8_t, 1, mTableBuilder_ub); break; case EDataType::kUShort_t: - mReaderValue_us = new TTreeReaderValue<uint16_t>(*reader, mColumnName); + mReaderValue_us = new TTreeReaderValue<uint16_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint16_t, 1, mTableBuilder_us); break; case EDataType::kUInt_t: - mReaderValue_ui = new TTreeReaderValue<uint32_t>(*reader, mColumnName); + mReaderValue_ui = new TTreeReaderValue<uint32_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint32_t, 1, mTableBuilder_ui); break; case EDataType::kULong64_t: - mReaderValue_ul = new TTreeReaderValue<ULong64_t>(*reader, mColumnName); + mReaderValue_ul = new TTreeReaderValue<ULong64_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint64_t, 1, mTableBuilder_ul); break; case EDataType::kChar_t: - mReaderValue_b = new TTreeReaderValue<int8_t>(*reader, mColumnName); + mReaderValue_b = new TTreeReaderValue<int8_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int8_t, 1, mTableBuilder_b); break; case EDataType::kShort_t: - mReaderValue_s = new TTreeReaderValue<int16_t>(*reader, mColumnName); + mReaderValue_s = new TTreeReaderValue<int16_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int16_t, 1, mTableBuilder_s); break; case EDataType::kInt_t: - mReaderValue_i = new TTreeReaderValue<int32_t>(*reader, mColumnName); + mReaderValue_i = new TTreeReaderValue<int32_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int32_t, 1, mTableBuilder_i); break; case EDataType::kLong64_t: - mReaderValue_l = new TTreeReaderValue<int64_t>(*reader, mColumnName); + mReaderValue_l = new TTreeReaderValue<int64_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int64_t, 1, mTableBuilder_l); break; case EDataType::kFloat_t: - mReaderValue_f = new TTreeReaderValue<float>(*reader, mColumnName); + mReaderValue_f = new TTreeReaderValue<float>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(float, 1, mTableBuilder_f); break; case EDataType::kDouble_t: - mReaderValue_d = new TTreeReaderValue<double>(*reader, mColumnName); + mReaderValue_d = new TTreeReaderValue<double>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(double, 1, mTableBuilder_d); break; default: @@ -462,47 +550,47 @@ ColumnIterator::ColumnIterator(TTreeReader* reader, const char* colname) } else { switch (mElementType) { case EDataType::kBool_t: - mReaderArray_o = new TTreeReaderArray<bool>(*reader, mColumnName); + mReaderArray_o = new TTreeReaderArray<bool>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(bool, mNumberElements, mTableBuilder_o); break; case EDataType::kUChar_t: - mReaderArray_ub = new TTreeReaderArray<uint8_t>(*reader, mColumnName); + mReaderArray_ub = new TTreeReaderArray<uint8_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint8_t, mNumberElements, mTableBuilder_ub); break; case EDataType::kUShort_t: - mReaderArray_us = new TTreeReaderArray<uint16_t>(*reader, mColumnName); + mReaderArray_us = new TTreeReaderArray<uint16_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint16_t, mNumberElements, mTableBuilder_us); break; case EDataType::kUInt_t: - mReaderArray_ui = new TTreeReaderArray<uint32_t>(*reader, mColumnName); + mReaderArray_ui = new TTreeReaderArray<uint32_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint32_t, mNumberElements, mTableBuilder_ui); break; case EDataType::kULong64_t: - mReaderArray_ul = new TTreeReaderArray<uint64_t>(*reader, mColumnName); + mReaderArray_ul = new TTreeReaderArray<uint64_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(uint64_t, mNumberElements, mTableBuilder_ul); break; case EDataType::kChar_t: - mReaderArray_b = new TTreeReaderArray<int8_t>(*reader, mColumnName); + mReaderArray_b = new TTreeReaderArray<int8_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int8_t, mNumberElements, mTableBuilder_b); break; case EDataType::kShort_t: - mReaderArray_s = new TTreeReaderArray<int16_t>(*reader, mColumnName); + mReaderArray_s = new TTreeReaderArray<int16_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int16_t, mNumberElements, mTableBuilder_s); break; case EDataType::kInt_t: - mReaderArray_i = new TTreeReaderArray<int32_t>(*reader, mColumnName); + mReaderArray_i = new TTreeReaderArray<int32_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int32_t, mNumberElements, mTableBuilder_i); break; case EDataType::kLong64_t: - mReaderArray_l = new TTreeReaderArray<int64_t>(*reader, mColumnName); + mReaderArray_l = new TTreeReaderArray<int64_t>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(int64_t, mNumberElements, mTableBuilder_l); break; case EDataType::kFloat_t: - mReaderArray_f = new TTreeReaderArray<float>(*reader, mColumnName); + mReaderArray_f = new TTreeReaderArray<float>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(float, mNumberElements, mTableBuilder_f); break; case EDataType::kDouble_t: - mReaderArray_d = new TTreeReaderArray<double>(*reader, mColumnName); + mReaderArray_d = new TTreeReaderArray<double>(reader, mColumnName); MAKE_FIELD_AND_BUILDER(double, mNumberElements, mTableBuilder_d); break; default: @@ -741,87 +829,58 @@ void ColumnIterator::finish() } } -TreeToTable::TreeToTable(TTree* tree) -{ - // initialize the TTreeReader - mTreeReader = new TTreeReader(tree); -} - -TreeToTable::~TreeToTable() +void TreeToTable::addColumn(const char* colname) { - delete mTreeReader; -}; - -bool TreeToTable::addColumn(const char* colname) -{ - auto colit = std::make_unique<ColumnIterator>(mTreeReader, colname); - auto stat = colit->getStatus(); - if (stat) { - mColumnIterators.push_back(std::move(colit)); - } - - return stat; + mColumnNames.push_back(colname); } -bool TreeToTable::addAllColumns() +bool TreeToTable::addAllColumns(TTree* tree) { - // get a list of column names - auto tree = mTreeReader->GetTree(); - if (!tree) { - LOGP(FATAL, "Tree not found!"); - return false; - } auto branchList = tree->GetListOfBranches(); // loop over branches - bool status = !branchList->IsEmpty(); + if (branchList->IsEmpty()) { + return false; + } for (Int_t ii = 0; ii < branchList->GetEntries(); ii++) { auto br = (TBranch*)branchList->At(ii); // IMPROVE: make sure that a column is not added more than one time - auto colit = std::make_unique<ColumnIterator>(mTreeReader, br->GetName()); - if (colit->getStatus()) { - mColumnIterators.push_back(std::move(colit)); - } else { - status = false; - } + mColumnNames.push_back(br->GetName()); } - - return status; + return true; } -void TreeToTable::push() +void TreeToTable::fill(TTree* tree) { - for (auto&& colit : mColumnIterators) { - colit->push(); + std::vector<std::unique_ptr<ColumnIterator>> columnIterators; + TTreeReader treeReader{tree}; + + for (auto&& columnName : mColumnNames) { + auto colit = std::make_unique<ColumnIterator>(treeReader, columnName.c_str()); + auto stat = colit->getStatus(); + if (!stat) { + throw std::runtime_error("Unable to convert column " + columnName); + } + columnIterators.push_back(std::move(colit)); } -} + auto numEntries = treeReader.GetEntries(true); -void TreeToTable::reserve(size_t s) -{ - for (auto&& column : mColumnIterators) { - column->reserve(s); + for (auto&& column : columnIterators) { + column->reserve(numEntries); } -} - -void TreeToTable::fill() -{ - auto numEntries = mTreeReader->GetEntries(true); - - this->reserve(numEntries); // copy all values from the tree to the table builders - mTreeReader->Restart(); - while (mTreeReader->Next()) { - push(); + treeReader.Restart(); + while (treeReader.Next()) { + for (auto&& column : columnIterators) { + column->push(); + } } -} -std::shared_ptr<arrow::Table> TreeToTable::finalize() -{ // prepare the elements needed to create the final table std::vector<std::shared_ptr<arrow::Array>> array_vector; std::vector<std::shared_ptr<arrow::Field>> schema_vector; - for (auto&& colit : mColumnIterators) { + for (auto&& colit : columnIterators) { colit->finish(); array_vector.push_back(colit->getArray()); schema_vector.push_back(colit->getSchema()); @@ -830,19 +889,12 @@ std::shared_ptr<arrow::Table> TreeToTable::finalize() // create the final table // ta is of type std::shared_ptr<arrow::Table> - auto table = (arrow::Table::Make(fields, array_vector)); - - return table; + mTable = (arrow::Table::Make(fields, array_vector)); } -std::shared_ptr<arrow::Table> TreeToTable::process() +std::shared_ptr<arrow::Table> TreeToTable::finalize() { - // do the looping with the TTreeReader - fill(); - - // create the table - return finalize(); + return mTable; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/test/benchmark_TreeToTable.cxx b/Framework/Core/test/benchmark_TreeToTable.cxx index 2a590609906b8..381b8c09bad4a 100644 --- a/Framework/Core/test/benchmark_TreeToTable.cxx +++ b/Framework/Core/test/benchmark_TreeToTable.cxx @@ -72,9 +72,10 @@ static void BM_TreeToTable(benchmark::State& state) // benchmark TreeToTable if (tr) { - tr2ta = new TreeToTable(tr); - if (tr2ta->addAllColumns()) { - auto ta = tr2ta->process(); + tr2ta = new TreeToTable; + if (tr2ta->addAllColumns(tr)) { + tr2ta->fill(tr); + auto ta = tr2ta->finalize(); } } else { diff --git a/Framework/Core/test/test_TreeToTable.cxx b/Framework/Core/test/test_TreeToTable.cxx index 7961ef6ba7acf..de5eb1048eba4 100644 --- a/Framework/Core/test/test_TreeToTable.cxx +++ b/Framework/Core/test/test_TreeToTable.cxx @@ -74,13 +74,15 @@ BOOST_AUTO_TEST_CASE(TreeToTableConversion) t1.Write(); // Create an arrow table from this. - TreeToTable tr2ta(&t1); - auto stat = tr2ta.addAllColumns(); + TreeToTable tr2ta; + auto stat = tr2ta.addAllColumns(&t1); if (!stat) { LOG(ERROR) << "Table was not created!"; return; } - auto table = tr2ta.process(); + + tr2ta.fill(&t1); + auto table = tr2ta.finalize(); f1.Close(); // test result From e5c4bc3d371b65019c284c4cfbe5be0ac5f1edee Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 15 Oct 2020 16:30:11 +0200 Subject: [PATCH 0963/1751] DPL: exit only the relevant devices when writing is complete. (#4604) --- Framework/Core/src/CommonDataProcessors.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 7734aacb68334..e3212dbe458a9 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -82,7 +82,7 @@ DataProcessorSpec CommonDataProcessors::getHistogramRegistrySink(outputObjects c LOG(DEBUG) << "Writing merged histograms to file"; if (inputObjects->empty()) { LOG(ERROR) << "Output object map is empty!"; - context.services().get<ControlService>().readyToQuit(QuitRequest::All); + context.services().get<ControlService>().readyToQuit(QuitRequest::Me); return; } std::string currentDirectory = ""; @@ -115,7 +115,7 @@ DataProcessorSpec CommonDataProcessors::getHistogramRegistrySink(outputObjects c } } LOG(INFO) << "All outputs merged in their respective target files"; - context.services().get<ControlService>().readyToQuit(QuitRequest::All); + context.services().get<ControlService>().readyToQuit(QuitRequest::Me); }; callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); @@ -211,7 +211,7 @@ DataProcessorSpec CommonDataProcessors::getOutputObjSink(outputObjects const& ob LOG(DEBUG) << "Writing merged objects to file"; if (inputObjects->empty()) { LOG(ERROR) << "Output object map is empty!"; - context.services().get<ControlService>().readyToQuit(QuitRequest::All); + context.services().get<ControlService>().readyToQuit(QuitRequest::Me); return; } std::string currentDirectory = ""; @@ -244,7 +244,7 @@ DataProcessorSpec CommonDataProcessors::getOutputObjSink(outputObjects const& ob } } LOG(DEBUG) << "All outputs merged in their respective target files"; - context.services().get<ControlService>().readyToQuit(QuitRequest::All); + context.services().get<ControlService>().readyToQuit(QuitRequest::Me); }; callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); @@ -426,7 +426,7 @@ DataProcessorSpec auto endofdatacb = [dod](EndOfStreamContext& context) { dod->closeDataFiles(); - context.services().get<ControlService>().readyToQuit(QuitRequest::All); + context.services().get<ControlService>().readyToQuit(QuitRequest::Me); }; auto& callbacks = ic.services().get<CallbackService>(); From 6e72c6bc48b86ab9a8f38f105126d75f4964d196 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 16 Oct 2020 07:23:36 +0200 Subject: [PATCH 0964/1751] DPL: use Framework/RuntimeError helpers throughout the framework (#4600) --- .../MUON/MCH/Tracking/src/TrackFitterSpec.cxx | 2 +- Framework/Core/include/Framework/ASoA.h | 6 ++- .../Core/include/Framework/ASoAHelpers.h | 3 +- .../Core/include/Framework/AnalysisTask.h | 5 +- .../Core/include/Framework/CallbackRegistry.h | 4 +- .../Core/include/Framework/DataAllocator.h | 9 ++-- .../include/Framework/DataDescriptorMatcher.h | 1 + .../Framework/DataDescriptorMatcher.inc | 4 +- .../include/Framework/DataProcessingDevice.h | 4 +- .../Core/include/Framework/DataRefUtils.h | 39 +++++----------- .../Core/include/Framework/ErrorContext.h | 25 +++++----- .../Core/include/Framework/Expressions.h | 4 +- .../include/Framework/HistogramRegistry.h | 11 +++-- .../Core/include/Framework/InputRecord.h | 42 +++++++++-------- .../Core/include/Framework/MessageContext.h | 9 ++-- .../Framework/RootConfigParamHelpers.h | 3 +- .../Core/include/Framework/ServiceRegistry.h | 8 ++-- .../Framework/ServiceRegistryHelpers.h | 2 - .../include/Framework/TMessageSerializer.h | 17 +++---- .../Core/include/Framework/TableBuilder.h | 20 ++++---- Framework/Core/include/Framework/Variant.h | 5 +- Framework/Core/src/AODReaderHelpers.cxx | 2 +- Framework/Core/src/ChannelSpecHelpers.cxx | 6 +-- Framework/Core/src/CommonDataProcessors.cxx | 4 +- Framework/Core/src/DataAllocator.cxx | 16 +++---- Framework/Core/src/DataDescriptorMatcher.cxx | 21 +++++---- Framework/Core/src/DataProcessingDevice.cxx | 26 ++++++++--- Framework/Core/src/DataSpecUtils.cxx | 22 +++++---- Framework/Core/src/DeviceSpecHelpers.cxx | 11 +++-- Framework/Core/src/Expressions.cxx | 46 +++++++++---------- Framework/Core/src/LifetimeHelpers.cxx | 12 ++--- Framework/Core/src/runDataProcessing.cxx | 10 +++- Framework/Core/test/test_InputRecord.cxx | 18 ++++---- Framework/Core/test/test_Services.cxx | 6 +-- .../Core/test/test_TMessageSerializer.cxx | 45 +++++++++--------- Framework/Core/test/test_Variants.cxx | 8 ++-- .../Core/test/unittest_DataSpecUtils.cxx | 4 +- Framework/Foundation/CMakeLists.txt | 8 +++- .../TestWorkflows/src/o2DiamondWorkflow.cxx | 1 + .../Utils/include/DPLUtils/RootTreeWriter.h | 2 +- 40 files changed, 254 insertions(+), 237 deletions(-) diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx index 8a9fb1bb0080a..bcaedac5499d8 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx @@ -94,7 +94,7 @@ class TrackFitterTask try { mTrackFitter.fit(track); } catch (exception const& e) { - throw runtime_error(std::string("Track fit failed: ") + e.what()); + throw std::runtime_error(std::string("Track fit failed: ") + e.what()); } // write the refitted track to the ouput message diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index f184ce55b5124..1f726cbd9ca62 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -18,13 +18,15 @@ #include "Framework/Traits.h" #include "Framework/Expressions.h" #include "Framework/ArrowTypes.h" +#include "Framework/RuntimeError.h" #include <arrow/table.h> #include <arrow/array.h> #include <arrow/util/variant.h> #include <arrow/compute/kernel.h> #include <gandiva/selection_vector.h> #include <cassert> -#include <fmt/format.h> + +using o2::framework::runtime_error_f; namespace o2::soa { @@ -1005,7 +1007,7 @@ class Table auto label = T::columnLabel(); auto index = mTable->schema()->GetFieldIndex(label); if (index == -1) { - throw std::runtime_error(std::string("Unable to find column with label ") + label); + throw runtime_error_f("Unable to find column with label %s", label); } return mTable->column(index).get(); } else { diff --git a/Framework/Core/include/Framework/ASoAHelpers.h b/Framework/Core/include/Framework/ASoAHelpers.h index bf1d992688540..f82b58da8242f 100644 --- a/Framework/Core/include/Framework/ASoAHelpers.h +++ b/Framework/Core/include/Framework/ASoAHelpers.h @@ -13,6 +13,7 @@ #include "Framework/ASoA.h" #include "Framework/Kernels.h" +#include "Framework/RuntimeError.h" #include <arrow/table.h> #include <iterator> @@ -122,7 +123,7 @@ auto groupTable(const T& table, const std::string& categoryColumnName, int minCa return doGroupTable<float, arrow::FloatArray>(arrowTable, categoryColumnName, minCatSize, outsider); } // FIXME: Should we support other types as well? - throw std::runtime_error("Combinations: category column must be of integral type"); + throw o2::framework::runtime_error("Combinations: category column must be of integral type"); } // Synchronize categories so as groupedIndices contain elements only of categories common to all tables diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index f0c267f9e9ad7..eacdd9704566c 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -24,6 +24,7 @@ #include "Framework/FunctionalHelpers.h" #include "Framework/Traits.h" #include "Framework/VariantHelpers.h" +#include "Framework/RuntimeError.h" #include <arrow/compute/kernel.h> #include <arrow/table.h> @@ -250,10 +251,10 @@ struct AnalysisDataProcessorBuilder { &groups[index], &offsets[index]); if (result.ok() == false) { - throw std::runtime_error("Cannot split collection"); + throw runtime_error("Cannot split collection"); } if (groups[index].size() != gt.tableSize()) { - throw std::runtime_error(fmt::format("Splitting collection resulted in different group number ({}) than there is rows in the grouping table ({}).", groups[index].size(), gt.tableSize())); + throw runtime_error_f("Splitting collection resulted in different group number (%d) than there is rows in the grouping table (%d).", groups[index].size(), gt.tableSize()); }; } }; diff --git a/Framework/Core/include/Framework/CallbackRegistry.h b/Framework/Core/include/Framework/CallbackRegistry.h index 76a79e78dc3de..1b72025d9a5f2 100644 --- a/Framework/Core/include/Framework/CallbackRegistry.h +++ b/Framework/Core/include/Framework/CallbackRegistry.h @@ -16,8 +16,8 @@ /// @brief A generic registry for callbacks #include "Framework/TypeTraits.h" +#include "Framework/RuntimeError.h" #include <tuple> -#include <stdexcept> // runtime_error #include <utility> // declval namespace o2 @@ -101,7 +101,7 @@ class CallbackRegistry template <std::size_t pos, typename U, typename F> typename std::enable_if<has_matching_callback<U, F>::value == false>::type setAt(F&& cb) { - throw std::runtime_error("mismatch in function substitution at position " + std::to_string(pos)); + throw runtime_error_f("mismatch in function substitution at position %d", pos); } // exec callback of specified id diff --git a/Framework/Core/include/Framework/DataAllocator.h b/Framework/Core/include/Framework/DataAllocator.h index ef7b347d0d8b8..22f08b1f1ed9b 100644 --- a/Framework/Core/include/Framework/DataAllocator.h +++ b/Framework/Core/include/Framework/DataAllocator.h @@ -25,6 +25,7 @@ #include "Framework/SerializationMethods.h" #include "Framework/CheckTypes.h" #include "Framework/ServiceRegistry.h" +#include "Framework/RuntimeError.h" #include "Headers/DataHeader.h" #include <TClass.h> @@ -326,13 +327,13 @@ class DataAllocator cl = TClass::GetClass(reinterpret_cast<const char*>(object.getHint())); } if (has_root_dictionary<WrappedType>::value == false && cl == nullptr) { - std::string msg("ROOT serialization not supported, dictionary not found for type "); if (std::is_same<typename T::hint_type, const char>::value) { - msg += reinterpret_cast<const char*>(object.getHint()); + throw runtime_error_f("ROOT serialization not supported, dictionary not found for type %s", + reinterpret_cast<const char*>(object.getHint())); } else { - msg += typeid(WrappedType).name(); + throw runtime_error_f("ROOT serialization not supported, dictionary not found for type %s", + typeid(WrappedType).name()); } - throw std::runtime_error(msg); } TMessageSerializer().Serialize(*payloadMessage, &object(), cl); } else { diff --git a/Framework/Core/include/Framework/DataDescriptorMatcher.h b/Framework/Core/include/Framework/DataDescriptorMatcher.h index 524ea084e60e5..fc72f5d2f0d8c 100644 --- a/Framework/Core/include/Framework/DataDescriptorMatcher.h +++ b/Framework/Core/include/Framework/DataDescriptorMatcher.h @@ -12,6 +12,7 @@ #include "Framework/ConcreteDataMatcher.h" #include "Framework/DataProcessingHeader.h" +#include "Framework/RuntimeError.h" #include "Headers/DataHeader.h" #include "Headers/Stack.h" diff --git a/Framework/Core/include/Framework/DataDescriptorMatcher.inc b/Framework/Core/include/Framework/DataDescriptorMatcher.inc index bcd4f5630bd8d..8e1b86d45d585 100644 --- a/Framework/Core/include/Framework/DataDescriptorMatcher.inc +++ b/Framework/Core/include/Framework/DataDescriptorMatcher.inc @@ -81,7 +81,7 @@ inline OriginValueMatcher::OriginValueMatcher(std::string const& s) : ValueHolder{s} { if (s.size() > header::gSizeDataOriginString) { - throw std::runtime_error("Header DataDescription too long"); + throw runtime_error("Header DataDescription too long"); } } @@ -100,7 +100,7 @@ inline DescriptionValueMatcher::DescriptionValueMatcher(std::string const& s) : ValueHolder{s} { if (s.size() > header::gSizeDataDescriptionString) { - throw std::runtime_error("Header DataDescription too long"); + throw runtime_error("Header DataDescription too long"); } } diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index cdb755327d540..89d8dd90d9f20 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -73,7 +73,7 @@ struct DataProcessorContext { AlgorithmSpec::ProcessCallback* statelessProcess = nullptr; AlgorithmSpec::ErrorCallback* error = nullptr; - std::function<void(std::exception& e, InputRecord& record)>* errorHandling = nullptr; + std::function<void(o2::framework::RuntimeErrorRef e, InputRecord& record)>* errorHandling = nullptr; int* errorCount = nullptr; }; @@ -113,7 +113,7 @@ class DataProcessingDevice : public FairMQDevice AlgorithmSpec::ProcessCallback mStatefulProcess; AlgorithmSpec::ProcessCallback mStatelessProcess; AlgorithmSpec::ErrorCallback mError; - std::function<void(std::exception& e, InputRecord& record)> mErrorHandling; + std::function<void(RuntimeErrorRef e, InputRecord& record)> mErrorHandling; std::unique_ptr<ConfigParamRegistry> mConfigRegistry; ServiceRegistry& mServiceRegistry; TimingInfo mTimingInfo; diff --git a/Framework/Core/include/Framework/DataRefUtils.h b/Framework/Core/include/Framework/DataRefUtils.h index f6fd9a1bfa4e9..962f85b20faac 100644 --- a/Framework/Core/include/Framework/DataRefUtils.h +++ b/Framework/Core/include/Framework/DataRefUtils.h @@ -17,11 +17,10 @@ #include "Framework/TypeTraits.h" #include "Headers/DataHeader.h" #include "Framework/CheckTypes.h" +#include "Framework/RuntimeError.h" #include <gsl/gsl> -#include <stdexcept> -#include <sstream> #include <type_traits> namespace o2::framework @@ -40,10 +39,10 @@ struct DataRefUtils { using DataHeader = o2::header::DataHeader; auto header = o2::header::get<const DataHeader*>(ref.header); if (header->payloadSerializationMethod != o2::header::gSerializationMethodNone) { - throw std::runtime_error("Attempt to extract a POD from a wrong message kind"); + throw runtime_error("Attempt to extract a POD from a wrong message kind"); } if ((header->payloadSize % sizeof(T)) != 0) { - throw std::runtime_error("Cannot extract POD from message as size do not match"); + throw runtime_error("Cannot extract POD from message as size do not match"); } //FIXME: provide a const collection return gsl::span<T>(reinterpret_cast<T*>(const_cast<char*>(ref.payload)), header->payloadSize / sizeof(T)); @@ -61,7 +60,7 @@ struct DataRefUtils { using DataHeader = o2::header::DataHeader; auto header = o2::header::get<const DataHeader*>(ref.header); if (header->payloadSerializationMethod != o2::header::gSerializationMethodROOT) { - throw std::runtime_error("Attempt to extract a TMessage from non-ROOT serialised message"); + throw runtime_error("Attempt to extract a TMessage from non-ROOT serialised message"); } typename RSS::FairTMessage ftm(const_cast<char*>(ref.payload), header->payloadSize); @@ -72,11 +71,8 @@ struct DataRefUtils { auto* object = ftm.ReadObjectAny(storedClass); if (object == nullptr) { - std::ostringstream ss; - ss << "Failed to read object with name " - << (storedClass != nullptr ? storedClass->GetName() : "<unknown>") - << " from message using ROOT serialization."; - throw std::runtime_error(ss.str()); + throw runtime_error_f("Failed to read object with name %s from message using ROOT serialization.", + (storedClass != nullptr ? storedClass->GetName() : "<unknown>")); } if constexpr (std::is_base_of<typename RSS::TObject, T>::value) { // compile time switch @@ -106,13 +102,9 @@ struct DataRefUtils { (*delfunc)(object); } - std::ostringstream ss; - ss << "Attempting to extract a " - << (requestedClass != nullptr ? requestedClass->GetName() : "<unknown>") - << " but a " - << (storedClass != nullptr ? storedClass->GetName() : "<unknown>") - << " is actually stored which cannot be casted to the requested one."; - throw std::runtime_error(ss.str()); + throw runtime_error_f("Attempting to extract a %s but a %s is actually stored which cannot be casted to the requested one.", + (requestedClass != nullptr ? requestedClass->GetName() : "<unknown>"), + (storedClass != nullptr ? storedClass->GetName() : "<unknown>")); } // collections in ROOT can be non-owning or owning and the proper cleanup depends on // this flag. Be it a bug or a feature in ROOT, but the owning flag of the extracted @@ -139,24 +131,17 @@ struct DataRefUtils { auto header = o2::header::get<const DataHeader*>(ref.header); if (header->payloadSerializationMethod != o2::header::gSerializationMethodROOT) { - throw std::runtime_error("Attempt to extract a TMessage from non-ROOT serialised message"); + throw runtime_error("Attempt to extract a TMessage from non-ROOT serialised message"); } auto* cl = RSS::TClass::GetClass(typeid(wrapped)); if (has_root_dictionary<wrapped>::value == false && cl == nullptr) { - throw std::runtime_error("ROOT serialization not supported, dictionary not found for data type"); + throw runtime_error("ROOT serialization not supported, dictionary not found for data type"); } typename RSS::FairTMessage ftm(const_cast<char*>(ref.payload), header->payloadSize); result.reset(static_cast<wrapped*>(ftm.ReadObjectAny(cl))); if (result.get() == nullptr) { - std::ostringstream ss; - ss << "Unable to extract class "; - if (cl == nullptr) { - ss << "<name not available>"; - } else { - ss << cl->GetName(); - } - throw std::runtime_error(ss.str()); + throw runtime_error_f("Unable to extract class %s", cl == nullptr ? "<name not available>" : cl->GetName()); } // workaround for ROOT feature, see above if constexpr (has_root_setowner<T>::value) { diff --git a/Framework/Core/include/Framework/ErrorContext.h b/Framework/Core/include/Framework/ErrorContext.h index fd151d83b504d..96528afa69c49 100644 --- a/Framework/Core/include/Framework/ErrorContext.h +++ b/Framework/Core/include/Framework/ErrorContext.h @@ -7,17 +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_ERROR_CONTEXT_H -#define FRAMEWORK_ERROR_CONTEXT_H +#ifndef O2_FRAMEWORK_ERROR_CONTEXT_H_ +#define O2_FRAMEWORK_ERROR_CONTEXT_H_ #include "Framework/InputRecord.h" #include "Framework/ServiceRegistry.h" +#include "Framework/RuntimeError.h" -#include <exception> - -namespace o2 -{ -namespace framework +namespace o2::framework { // This is a utility class to reduce the amount of boilerplate when defining @@ -25,23 +22,23 @@ namespace framework class ErrorContext { public: - ErrorContext(InputRecord& inputs, ServiceRegistry& services, std::exception& e) + ErrorContext(InputRecord& inputs, ServiceRegistry& services, RuntimeErrorRef e) : mInputs{inputs}, mServices{services}, - mException{e} + mExceptionRef{e} { } InputRecord const& inputs() { return mInputs; } ServiceRegistry const& services() { return mServices; } - std::exception const& exception() { return mException; } + RuntimeErrorRef exception() { return mExceptionRef; } + private: InputRecord& mInputs; ServiceRegistry& mServices; - std::exception& mException; + RuntimeErrorRef mExceptionRef; }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif +#endif // o2::framework diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index c96cf3ef58a79..743ae75ba974a 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -19,6 +19,7 @@ #include "Framework/InitContext.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/RootConfigParamHelpers.h" +#include "Framework/RuntimeError.h" #include <arrow/type_fwd.h> #include <gandiva/gandiva_aliases.h> #include <arrow/type.h> @@ -29,7 +30,6 @@ #include <gandiva/node.h> #include <gandiva/filter.h> #include <gandiva/projector.h> -#include <fmt/format.h> #else namespace gandiva { @@ -573,7 +573,7 @@ std::shared_ptr<gandiva::Projector> createProjectors(framework::pack<C...>, gand if (s.ok()) { return projector; } else { - throw std::runtime_error(fmt::format("Failed to create projector: {}", s.ToString())); + throw o2::framework::runtime_error_f("Failed to create projector: %s", s.ToString().c_str()); } } } // namespace o2::framework::expressions diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index bd7871e22f9e4..93f21ec50479d 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -20,6 +20,7 @@ #include "Framework/SerializationMethods.h" #include "Framework/StringHelpers.h" #include "Framework/TableBuilder.h" +#include "Framework/RuntimeError.h" #include "TClass.h" #include "TH1.h" @@ -129,7 +130,7 @@ template <typename T> std::unique_ptr<TH1> createTH1FromSpec(HistogramSpec const& spec) { if (spec.config.axes.size() == 0) { - throw std::runtime_error("No arguments available in spec to create a histogram"); + throw runtime_error("No arguments available in spec to create a histogram"); } if (spec.config.binsEqual) { return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1]); @@ -141,7 +142,7 @@ template <typename T> std::unique_ptr<TH2> createTH2FromSpec(HistogramSpec const& spec) { if (spec.config.axes.size() == 0) { - throw std::runtime_error("No arguments available in spec to create a histogram"); + throw runtime_error("No arguments available in spec to create a histogram"); } if (spec.config.binsEqual) { return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1]); @@ -153,7 +154,7 @@ template <typename T> std::unique_ptr<TH3> createTH3FromSpec(HistogramSpec const& spec) { if (spec.config.axes.size() == 0) { - throw std::runtime_error("No arguments available in spec to create a histogram"); + throw runtime_error("No arguments available in spec to create a histogram"); } if (spec.config.binsEqual) { return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1], spec.config.axes[2].nBins, spec.config.axes[2].bins[0], spec.config.axes[2].bins[1]); @@ -297,7 +298,7 @@ class HistogramRegistry return mRegistryValue[imask(j + i)]; } } - throw std::runtime_error("No match found!"); + throw runtime_error("No match found!"); } /// @return the histogram registered with name @a name @@ -373,7 +374,7 @@ class HistogramRegistry return; } } - throw std::runtime_error("Internal array is full."); + throw runtime_error("Internal array is full."); } inline constexpr uint32_t imask(uint32_t i) const diff --git a/Framework/Core/include/Framework/InputRecord.h b/Framework/Core/include/Framework/InputRecord.h index 0a70f9dc41eaa..47813bdb89757 100644 --- a/Framework/Core/include/Framework/InputRecord.h +++ b/Framework/Core/include/Framework/InputRecord.h @@ -17,6 +17,7 @@ #include "Framework/InputSpan.h" #include "Framework/TableConsumer.h" #include "Framework/Traits.h" +#include "Framework/RuntimeError.h" #include "MemoryResources/Types.h" #include "Headers/DataHeader.h" @@ -29,7 +30,6 @@ #include <vector> #include <cstring> #include <cassert> -#include <exception> #include <memory> #include <type_traits> @@ -139,7 +139,7 @@ class InputRecord if (mProperty == OwnershipProperty::Unknown) { mProperty = other.mProperty; } else if (mProperty != other.mProperty) { - throw std::runtime_error("Attemp to change resource control"); + throw runtime_error("Attemp to change resource control"); } } @@ -156,7 +156,7 @@ class InputRecord if (mProperty == OwnershipProperty::Unknown) { mProperty = other.mProperty; } else if (mProperty != other.mProperty) { - throw std::runtime_error("Attemp to change resource control"); + throw runtime_error("Attemp to change resource control"); } return *this; } @@ -180,13 +180,13 @@ class InputRecord DataRef getByPos(int pos, int part = 0) const { if (pos >= mSpan.size() || pos < 0) { - throw std::runtime_error("Unknown message requested at position " + std::to_string(pos)); + throw runtime_error_f("Unknown message requested at position %d", pos); } if (part > 0 && part >= getNofParts(pos)) { - throw std::runtime_error("Invalid message part index at " + std::to_string(pos) + ":" + std::to_string(part)); + throw runtime_error_f("Invalid message part index at %d:%d", pos, part); } if (pos >= mInputsSchema.size()) { - throw std::runtime_error("Unknown schema at position" + std::to_string(pos)); + throw runtime_error_f("Unknown schema at position %d", pos); } auto ref = mSpan.get(pos, part); ref.spec = &mInputsSchema[pos].matcher; @@ -232,8 +232,11 @@ class InputRecord } ref = this->getByPos(pos, part); } catch (const std::exception& e) { - throw std::runtime_error("Unknown argument requested " + std::string(binding) + - " - " + e.what()); + if constexpr (std::is_same_v<std::decay_t<R>, std::string>) { + throw runtime_error_f("Unknown argument requested %s - %s", binding.c_str(), e.what()); + } else { + throw runtime_error_f("Unknown argument requested %s - %s", binding, e.what()); + } } } else if constexpr (std::is_same_v<std::decay_t<R>, DataRef>) { ref = binding; @@ -296,13 +299,14 @@ class InputRecord auto header = header::get<const header::DataHeader*>(ref.header); assert(header); if (sizeof(typename T::value_type) > 1 && header->payloadSerializationMethod != o2::header::gSerializationMethodNone) { - throw std::runtime_error("Inconsistent serialization method for extracting span"); + throw runtime_error("Inconsistent serialization method for extracting span"); } using ValueT = typename T::value_type; if (header->payloadSize % sizeof(ValueT)) { - throw std::runtime_error("Inconsistent type and payload size at " + std::string(ref.spec->binding) + "(" + DataSpecUtils::describe(*ref.spec) + ")" + - ": type size " + std::to_string(sizeof(ValueT)) + - " payload size " + std::to_string(header->payloadSize)); + throw runtime_error(("Inconsistent type and payload size at " + std::string(ref.spec->binding) + "(" + DataSpecUtils::describe(*ref.spec) + ")" + + ": type size " + std::to_string(sizeof(ValueT)) + + " payload size " + std::to_string(header->payloadSize)) + .c_str()); } return gsl::span<ValueT const>(reinterpret_cast<ValueT const*>(ref.payload), header->payloadSize / sizeof(ValueT)); @@ -336,10 +340,10 @@ class InputRecord std::swap(const_cast<NonConstT&>(container), *object); return container; } else { - throw std::runtime_error("No supported conversion function for ROOT serialized message"); + throw runtime_error("No supported conversion function for ROOT serialized message"); } } else { - throw std::runtime_error("Attempt to extract object from message with unsupported serialization type"); + throw runtime_error("Attempt to extract object from message with unsupported serialization type"); } } else { static_assert(always_static_assert_v<T>, "unsupported code path"); @@ -358,7 +362,7 @@ class InputRecord if (method != o2::header::gSerializationMethodNone) { // FIXME: we could in principle support serialized content here as well if we // store all extracted objects internally and provide cleanup - throw std::runtime_error("Can not extract a plain object from serialized message"); + throw runtime_error("Can not extract a plain object from serialized message"); } return *reinterpret_cast<T const*>(ref.payload); @@ -387,7 +391,7 @@ class InputRecord std::unique_ptr<ValueT const, Deleter<ValueT const>> result(container.release(), Deleter<ValueT const>(true)); return result; } - throw std::runtime_error("unsupported code path"); + throw runtime_error("unsupported code path"); } else if (method == o2::header::gSerializationMethodROOT) { // This supports the common case of retrieving a root object and getting pointer. // Notice that this will return a copy of the actual contents of the buffer, because @@ -400,7 +404,7 @@ class InputRecord std::unique_ptr<ValueT const, Deleter<ValueT const>> result(DataRefUtils::as<ROOTSerialized<ValueT>>(ref).release()); return result; } else { - throw std::runtime_error("Attempt to extract object from message with unsupported serialization type"); + throw runtime_error("Attempt to extract object from message with unsupported serialization type"); } } else if constexpr (has_root_dictionary<T>::value) { // retrieving ROOT objects follows the pointer approach, i.e. T* has to be specified @@ -416,7 +420,7 @@ class InputRecord auto method = header->payloadSerializationMethod; if (method == o2::header::gSerializationMethodNone) { // this code path is only selected if the type is non-messageable - throw std::runtime_error( + throw runtime_error( "Type mismatch: attempt to extract a non-messagable object " "from message with unserialized data"); } else if (method == o2::header::gSerializationMethodROOT) { @@ -426,7 +430,7 @@ class InputRecord std::unique_ptr<T const, Deleter<T const>> result(DataRefUtils::as<ROOTSerialized<T>>(ref).release()); return result; } else { - throw std::runtime_error("Attempt to extract object from message with unsupported serialization type"); + throw runtime_error("Attempt to extract object from message with unsupported serialization type"); } } } diff --git a/Framework/Core/include/Framework/MessageContext.h b/Framework/Core/include/Framework/MessageContext.h index b5b9718a70be3..fca8d7069ea32 100644 --- a/Framework/Core/include/Framework/MessageContext.h +++ b/Framework/Core/include/Framework/MessageContext.h @@ -12,8 +12,10 @@ #include "Framework/DispatchControl.h" #include "Framework/FairMQDeviceProxy.h" +#include "Framework/RuntimeError.h" #include "Framework/TMessageSerializer.h" #include "Framework/TypeTraits.h" + #include "Headers/DataHeader.h" #include "MemoryResources/MemoryResources.h" @@ -22,7 +24,6 @@ #include <cassert> #include <functional> -#include <stdexcept> #include <string> #include <type_traits> #include <unordered_map> @@ -233,10 +234,10 @@ class MessageContext // FIXME: drop this repeated check and make sure at initial setup of devices that everything is fine // introduce error policy if (mFactory == nullptr) { - throw std::runtime_error(std::string("failed to get transport factory for channel ") + bindingChannel); + throw runtime_error_f("failed to get transport factory for channel %s", bindingChannel.c_str()); } if (mResource.isValid() == false) { - throw std::runtime_error(std::string("no memory resource for channel ") + bindingChannel); + throw runtime_error_f("no memory resource for channel %s", bindingChannel.c_str()); } } ~ContainerRefObject() override = default; @@ -406,7 +407,7 @@ class MessageContext // TODO: decide whether this is an error or not // can also check if the standard constructor can be dropped to make sure that // the ScopeHook is always set up with a context - throw std::runtime_error("No context available to schedule the context object"); + throw runtime_error("No context available to schedule the context object"); return base::operator()(ptr); } // keep the object alive and add to message list of the context diff --git a/Framework/Core/include/Framework/RootConfigParamHelpers.h b/Framework/Core/include/Framework/RootConfigParamHelpers.h index bd91e969d4dc5..31e1c35712f37 100644 --- a/Framework/Core/include/Framework/RootConfigParamHelpers.h +++ b/Framework/Core/include/Framework/RootConfigParamHelpers.h @@ -11,6 +11,7 @@ #define O2_FRAMEWORK_ROOTCONFIGPARAMHELPERS_H_ #include "Framework/ConfigParamSpec.h" +#include "Framework/RuntimeError.h" #include <TClass.h> #include <boost/property_tree/ptree_fwd.hpp> #include <type_traits> @@ -34,7 +35,7 @@ struct RootConfigParamHelpers { { auto cl = TClass::GetClass<T>(); if (!cl) { - throw std::runtime_error(std::string("Unable to convert object ") + typeid(T).name()); + throw runtime_error_f("Unable to convert object %s", typeid(T).name()); } return asConfigParamSpecsImpl(mainKey, cl, reinterpret_cast<void*>(const_cast<T*>(&proto))); diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index ab6d1362bd74e..8e2f96363d3ec 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -15,15 +15,14 @@ #include "Framework/ServiceRegistryHelpers.h" #include "Framework/CompilerBuiltins.h" #include "Framework/TypeIdHelpers.h" +#include "Framework/RuntimeError.h" #include <algorithm> #include <array> -#include <exception> #include <functional> #include <string> #include <type_traits> #include <typeinfo> -#include <stdexcept> #include <thread> #include <atomic> #include <mutex> @@ -281,9 +280,8 @@ struct ServiceRegistry { return *reinterpret_cast<T*>(ptr); } } - throw std::runtime_error(std::string("Unable to find service of kind ") + - typeid(T).name() + - ". Make sure you use const / non-const correctly."); + throw runtime_error_f("Unable to find service of kind %s. Make sure you use const / non-const correctly.", + typeid(T).name()); } }; diff --git a/Framework/Core/include/Framework/ServiceRegistryHelpers.h b/Framework/Core/include/Framework/ServiceRegistryHelpers.h index 86781a79c5ece..f738517c4a254 100644 --- a/Framework/Core/include/Framework/ServiceRegistryHelpers.h +++ b/Framework/Core/include/Framework/ServiceRegistryHelpers.h @@ -15,12 +15,10 @@ #include <algorithm> #include <array> -#include <exception> #include <functional> #include <string> #include <type_traits> #include <typeinfo> -#include <stdexcept> #include <thread> namespace o2::framework diff --git a/Framework/Core/include/Framework/TMessageSerializer.h b/Framework/Core/include/Framework/TMessageSerializer.h index dc12130e380da..b041125800396 100644 --- a/Framework/Core/include/Framework/TMessageSerializer.h +++ b/Framework/Core/include/Framework/TMessageSerializer.h @@ -12,6 +12,8 @@ #include <fairmq/FairMQMessage.h> +#include "Framework/RuntimeError.h" + #include <TList.h> #include <TMessage.h> #include <TObjArray.h> @@ -137,9 +139,7 @@ inline std::unique_ptr<T> TMessageSerializer::deserialize(gsl::span<o2::byte> bu { TClass* tgtClass = TClass::GetClass(typeid(T)); if (tgtClass == nullptr) { - std::string error("class is not ROOT-serializable: "); - error += typeid(T).name(); - throw std::runtime_error(error); + throw runtime_error_f("class is not ROOT-serializable: %s", typeid(T).name()); } // FIXME: we need to add consistency check for buffer data to be serialized // at the moment, TMessage might simply crash if an invalid or inconsistent @@ -147,15 +147,12 @@ inline std::unique_ptr<T> TMessageSerializer::deserialize(gsl::span<o2::byte> bu FairTMessage tm(buffer); TClass* serializedClass = tm.GetClass(); if (serializedClass == nullptr) { - std::string error("can not read class info from buffer"); - throw std::runtime_error(error); + throw runtime_error_f("can not read class info from buffer"); } if (tgtClass != serializedClass && serializedClass->GetBaseClass(tgtClass) == nullptr) { - std::string error("can not convert serialized class "); - error += tm.GetClass()->GetName(); - error += " into target class "; - error += tgtClass->GetName(); - throw std::runtime_error(error); + throw runtime_error_f("can not convert serialized class %s into target class %s", + tm.GetClass()->GetName(), + tgtClass->GetName()); } return std::unique_ptr<T>(reinterpret_cast<T*>(tm.ReadObjectAny(serializedClass))); } diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index 37f84648651da..43e45b9d79bb0 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -15,6 +15,7 @@ #include "Framework/StructToTuple.h" #include "Framework/FunctionalHelpers.h" #include "Framework/VariantHelpers.h" +#include "Framework/RuntimeError.h" #include "arrow/type_traits.h" // Apparently needs to be on top of the arrow includes. @@ -28,7 +29,6 @@ #include <arrow/builder.h> #include <functional> -#include <stdexcept> #include <vector> #include <string> #include <memory> @@ -179,13 +179,13 @@ struct BuilderUtils { } if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) { if (appendToList<std::remove_pointer_t<decltype(info.ptr)>>(holder.builder, info.ptr, info.size).ok() == false) { - throw std::runtime_error("Unable to append to column"); + throw runtime_error("Unable to append to column"); } else { return arrow::Status::OK(); } } else { if (holder.builder->AppendValues(info.ptr, info.size, nullptr).ok() == false) { - throw std::runtime_error("Unable to append to column"); + throw runtime_error("Unable to append to column"); } else { return arrow::Status::OK(); } @@ -214,7 +214,7 @@ struct BuilderUtils { auto valueBuilder = reinterpret_cast<ValueBuilderType*>(holder.builder->value_builder()); status &= valueBuilder->AppendValues(&*ip.first, std::distance(ip.first, ip.second)); if (!status.ok()) { - throw std::runtime_error("Unable to append values to valueBuilder!"); + throw runtime_error("Unable to append values to valueBuilder!"); } return; } @@ -572,10 +572,10 @@ class TableBuilder { constexpr int nColumns = sizeof...(ARGS); if (nColumns != columnNames.size()) { - throw std::runtime_error("Mismatching number of column types and names"); + throw runtime_error("Mismatching number of column types and names"); } if (mHolders != nullptr) { - throw std::runtime_error("TableBuilder::persist can only be invoked once per instance"); + throw runtime_error("TableBuilder::persist can only be invoked once per instance"); } } @@ -598,7 +598,7 @@ class TableBuilder mFinalizer = [schema = mSchema, &arrays = mArrays, holders = mHolders]() -> void { auto status = TableBuilderHelpers::finalize(arrays, *(HoldersTuple<ARGS...>*)holders, std::make_index_sequence<sizeof...(ARGS)>{}); if (status == false) { - throw std::runtime_error("Unable to finalize"); + throw runtime_error("Unable to finalize"); } }; } @@ -660,7 +660,7 @@ class TableBuilder return [holders = mHolders](unsigned int slot, FillTuple const& t) -> void { auto status = TableBuilderHelpers::append(*(HoldersTuple<ARGS...>*)holders, std::index_sequence_for<ARGS...>{}, t); if (status == false) { - throw std::runtime_error("Unable to append"); + throw runtime_error("Unable to append"); } }; } @@ -799,14 +799,14 @@ auto spawner(framework::pack<C...> columns, arrow::Table* atable) while (true) { auto s = reader.ReadNext(&batch); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot read batches from table: {}", s.ToString())); + throw runtime_error_f("Cannot read batches from table: %s", s.ToString().c_str()); } if (batch == nullptr) { break; } s = projectors->Evaluate(*batch, arrow::default_memory_pool(), &v); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot apply projector: {}", s.ToString())); + throw runtime_error_f("Cannot apply projector: %s", s.ToString().c_str()); } for (auto i = 0u; i < sizeof...(C); ++i) { chunks[i].emplace_back(v.at(i)); diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index 139eea96a98cb..e2bddf83dba57 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -9,11 +9,12 @@ // or submit itself to any jurisdiction. #ifndef FRAMEWORK_VARIANT_H #define FRAMEWORK_VARIANT_H + +#include "Framework/RuntimeError.h" #include <type_traits> #include <cstring> #include <cstdint> #include <cstdlib> -#include <stdexcept> #include <iosfwd> #include <initializer_list> #include <string_view> @@ -220,7 +221,7 @@ class Variant { auto v = variant_trait_v<T>; if (mType != variant_trait_v<T>) { - throw std::runtime_error("Mismatch between types"); + throw runtime_error("Mismatch between types"); } return variant_helper<storage_t, T>::get(&mStore); } diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 93809cb19096c..b341b4089b47e 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -82,7 +82,7 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> reques } else if (description == header::DataDescription{"MUON"}) { outputs.adopt(Output{origin, description}, maker(o2::aod::MuonsExtensionMetadata{})); } else { - throw std::runtime_error("Not an extended table"); + throw runtime_error("Not an extended table"); } } }; diff --git a/Framework/Core/src/ChannelSpecHelpers.cxx b/Framework/Core/src/ChannelSpecHelpers.cxx index 87b7ff45c0c1c..7c04beecb19ea 100644 --- a/Framework/Core/src/ChannelSpecHelpers.cxx +++ b/Framework/Core/src/ChannelSpecHelpers.cxx @@ -8,10 +8,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "ChannelSpecHelpers.h" +#include "Framework/RuntimeError.h" #include <fmt/format.h> #include <ostream> #include <cassert> -#include <stdexcept> #if 0 #include <filesystem> namespace fs = std::filesystem; @@ -49,7 +49,7 @@ char const* ChannelSpecHelpers::typeAsString(enum ChannelType type) case ChannelType::Pair: return "pair"; } - throw std::runtime_error("Unknown ChannelType"); + throw runtime_error("Unknown ChannelType"); } char const* ChannelSpecHelpers::methodAsString(enum ChannelMethod method) @@ -60,7 +60,7 @@ char const* ChannelSpecHelpers::methodAsString(enum ChannelMethod method) case ChannelMethod::Connect: return "connect"; } - throw std::runtime_error("Unknown ChannelMethod"); + throw runtime_error("Unknown ChannelMethod"); } std::string ChannelSpecHelpers::channelUrl(OutputChannelSpec const& channel) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index e3212dbe458a9..37f1af7c6e32c 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -31,6 +31,7 @@ #include "Framework/StringHelpers.h" #include "Framework/ChannelSpec.h" #include "Framework/ExternalFairMQDeviceProxy.h" +#include "Framework/RuntimeError.h" #include "TFile.h" #include "TTree.h" @@ -40,7 +41,6 @@ #include <ROOT/RArrowDS.hxx> #include <ROOT/RVec.hxx> #include <chrono> -#include <exception> #include <fstream> #include <functional> #include <memory> @@ -518,7 +518,7 @@ DataProcessorSpec auto keepString = ic.options().get<std::string>("keep"); if (filename.empty()) { - throw std::runtime_error("output file missing"); + throw runtime_error("output file missing"); } bool hasOutputsToWrite = false; diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index aa3ea7043c560..48d9eacaf3586 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -50,12 +50,12 @@ std::string const& DataAllocator::matchDataHeader(const Output& spec, size_t tim return output.channel; } } - std::ostringstream str; - str << "Worker is not authorised to create message with " - << "origin(" << spec.origin.as<std::string>() << ")" - << "description(" << spec.description.as<std::string>() << ")" - << "subSpec(" << spec.subSpec << ")"; - throw std::runtime_error(str.str()); + throw runtime_error_f( + "Worker is not authorised to create message with " + "origin(%s) description(%s) subSpec(%d)", + spec.origin.as<std::string>().c_str(), + spec.description.as<std::string>().c_str(), + spec.subSpec); } DataChunk& DataAllocator::newChunk(const Output& spec, size_t size) @@ -243,7 +243,7 @@ void DataAllocator::snapshot(const Output& spec, const char* payload, size_t pay Output DataAllocator::getOutputByBind(OutputRef&& ref) { if (ref.label.empty()) { - throw std::runtime_error("Invalid (empty) OutputRef provided."); + throw runtime_error("Invalid (empty) OutputRef provided."); } for (auto ri = 0ul, re = mAllowedOutputRoutes.size(); ri != re; ++ri) { if (mAllowedOutputRoutes[ri].matcher.binding.value == ref.label) { @@ -252,7 +252,7 @@ Output DataAllocator::getOutputByBind(OutputRef&& ref) return Output{dataType.origin, dataType.description, ref.subSpec, spec.lifetime, std::move(ref.headerStack)}; } } - throw std::runtime_error("Unable to find OutputSpec with label " + ref.label); + throw runtime_error_f("Unable to find OutputSpec with label %s", ref.label.c_str()); O2_BUILTIN_UNREACHABLE(); } diff --git a/Framework/Core/src/DataDescriptorMatcher.cxx b/Framework/Core/src/DataDescriptorMatcher.cxx index 5d38036cb6335..ba08fd67ff50e 100644 --- a/Framework/Core/src/DataDescriptorMatcher.cxx +++ b/Framework/Core/src/DataDescriptorMatcher.cxx @@ -13,6 +13,7 @@ #include "Framework/DataMatcherWalker.h" #include "Framework/DataProcessingHeader.h" #include "Framework/VariantHelpers.h" +#include "Framework/RuntimeError.h" #include <iostream> namespace o2 @@ -63,7 +64,7 @@ bool OriginValueMatcher::match(header::DataHeader const& header, VariableContext } else if (auto s = std::get_if<std::string>(&mValue)) { return strncmp(header.dataOrigin.str, s->c_str(), 4) == 0; } - throw std::runtime_error("Mismatching type for variable"); + throw runtime_error("Mismatching type for variable"); } bool DescriptionValueMatcher::match(header::DataHeader const& header, VariableContext& context) const @@ -79,7 +80,7 @@ bool DescriptionValueMatcher::match(header::DataHeader const& header, VariableCo } else if (auto s = std::get_if<std::string>(&this->mValue)) { return strncmp(header.dataDescription.str, s->c_str(), 16) == 0; } - throw std::runtime_error("Mismatching type for variable"); + throw runtime_error("Mismatching type for variable"); } bool SubSpecificationTypeValueMatcher::match(header::DataHeader const& header, VariableContext& context) const @@ -94,7 +95,7 @@ bool SubSpecificationTypeValueMatcher::match(header::DataHeader const& header, V } else if (auto v = std::get_if<header::DataHeader::SubSpecificationType>(&mValue)) { return header.subSpecification == *v; } - throw std::runtime_error("Mismatching type for variable"); + throw runtime_error("Mismatching type for variable"); } /// This will match the timing information which is currently in @@ -112,7 +113,7 @@ bool StartTimeValueMatcher::match(DataProcessingHeader const& dph, VariableConte } else if (auto v = std::get_if<uint64_t>(&mValue)) { return (dph.startTime / mScale) == *v; } - throw std::runtime_error("Mismatching type for variable"); + throw runtime_error("Mismatching type for variable"); } DataDescriptorMatcher::DataDescriptorMatcher(DataDescriptorMatcher const& other) @@ -241,19 +242,19 @@ bool DataDescriptorMatcher::match(char const* d, VariableContext& context) const if (auto pval0 = std::get_if<OriginValueMatcher>(&mLeft)) { auto dh = o2::header::get<header::DataHeader*>(d); if (dh == nullptr) { - throw std::runtime_error("Cannot find DataHeader"); + throw runtime_error("Cannot find DataHeader"); } leftValue = pval0->match(*dh, context); } else if (auto pval1 = std::get_if<DescriptionValueMatcher>(&mLeft)) { auto dh = o2::header::get<header::DataHeader*>(d); if (dh == nullptr) { - throw std::runtime_error("Cannot find DataHeader"); + throw runtime_error("Cannot find DataHeader"); } leftValue = pval1->match(*dh, context); } else if (auto pval2 = std::get_if<SubSpecificationTypeValueMatcher>(&mLeft)) { auto dh = o2::header::get<header::DataHeader*>(d); if (dh == nullptr) { - throw std::runtime_error("Cannot find DataHeader"); + throw runtime_error("Cannot find DataHeader"); } leftValue = pval2->match(*dh, context); } else if (auto pval3 = std::get_if<std::unique_ptr<DataDescriptorMatcher>>(&mLeft)) { @@ -263,11 +264,11 @@ bool DataDescriptorMatcher::match(char const* d, VariableContext& context) const } else if (auto pval5 = std::get_if<StartTimeValueMatcher>(&mLeft)) { auto dph = o2::header::get<DataProcessingHeader*>(d); if (dph == nullptr) { - throw std::runtime_error("Cannot find DataProcessingHeader"); + throw runtime_error("Cannot find DataProcessingHeader"); } leftValue = pval5->match(*dph, context); } else { - throw std::runtime_error("Bad parsing tree"); + throw runtime_error("Bad parsing tree"); } // Common speedup. if (mOp == Op::And && leftValue == false) { @@ -309,7 +310,7 @@ bool DataDescriptorMatcher::match(char const* d, VariableContext& context) const case Op::Just: return leftValue; } - throw std::runtime_error("Bad parsing tree"); + throw runtime_error("Bad parsing tree"); }; bool DataDescriptorMatcher::operator==(DataDescriptorMatcher const& other) const diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 13c70ddf03fde..19e3058277c32 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -53,6 +53,7 @@ #include <memory> #include <unordered_map> #include <uv.h> +#include <execinfo.h> using namespace o2::framework; using Key = o2::monitoring::tags::Key; @@ -94,19 +95,23 @@ DataProcessingDevice::DataProcessingDevice(DeviceSpec const& spec, ServiceRegist { /// FIXME: move erro handling to a service? if (mError != nullptr) { - mErrorHandling = [& errorCallback = mError, - &serviceRegistry = mServiceRegistry](std::exception& e, InputRecord& record) { + mErrorHandling = [&errorCallback = mError, + &serviceRegistry = mServiceRegistry](RuntimeErrorRef e, InputRecord& record) { ZoneScopedN("Error handling"); - LOG(ERROR) << "Exception caught: " << e.what() << std::endl; + auto& err = error_from_ref(e); + LOGP(ERROR, "Exception caught: {} ", err.what); + backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); serviceRegistry.get<Monitoring>().send({1, "error"}); ErrorContext errorContext{record, serviceRegistry, e}; errorCallback(errorContext); }; } else { - mErrorHandling = [& errorPolicy = mErrorPolicy, - &serviceRegistry = mServiceRegistry](std::exception& e, InputRecord& record) { + mErrorHandling = [&errorPolicy = mErrorPolicy, + &serviceRegistry = mServiceRegistry](RuntimeErrorRef e, InputRecord& record) { ZoneScopedN("Error handling"); - LOG(ERROR) << "Exception caught: " << e.what() << std::endl; + auto& err = error_from_ref(e); + LOGP(ERROR, "Exception caught: {} ", err.what); + backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); serviceRegistry.get<Monitoring>().send({1, "error"}); switch (errorPolicy) { case TerminationPolicy::QUIT: @@ -975,7 +980,14 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, context.registry->postProcessingCallbacks(processContext); } } - } catch (std::exception& e) { + } catch (std::exception& ex) { + ZoneScopedN("error handling"); + /// Convert a standatd exception to a RuntimeErrorRef + /// Notice how this will lose the backtrace information + /// and report the exception coming from here. + auto e = runtime_error(ex.what()); + (*context.errorHandling)(e, record); + } catch (o2::framework::RuntimeErrorRef e) { ZoneScopedN("error handling"); (*context.errorHandling)(e, record); } diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index f7b69e0d43cfa..a56b288fa8212 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -12,6 +12,8 @@ #include "Framework/DataMatcherWalker.h" #include "Framework/VariantHelpers.h" #include "Framework/Logger.h" +#include "Framework/RuntimeError.h" + #include <cstring> #include <cinttypes> @@ -70,7 +72,7 @@ std::string DataSpecUtils::describe(InputSpec const& spec) ss << "<matcher query: " << *matcher << ">"; return ss.str(); } - throw std::runtime_error("Unhandled InputSpec kind."); + throw runtime_error("Unhandled InputSpec kind."); } std::string DataSpecUtils::describe(OutputSpec const& spec) @@ -95,7 +97,7 @@ void DataSpecUtils::describe(char* buffer, size_t size, InputSpec const& spec) ss << "<matcher query: " << *matcher << ">"; strncpy(buffer, ss.str().c_str(), size - 1); } else { - throw std::runtime_error("Unsupported InputSpec"); + throw runtime_error("Unsupported InputSpec"); } } @@ -112,7 +114,7 @@ std::string DataSpecUtils::label(InputSpec const& spec) return result; } - throw std::runtime_error("Unsupported InputSpec"); + throw runtime_error("Unsupported InputSpec"); } std::string DataSpecUtils::label(OutputSpec const& spec) @@ -129,7 +131,7 @@ std::string DataSpecUtils::restEndpoint(InputSpec const& spec) if (auto concrete = std::get_if<ConcreteDataMatcher>(&spec.matcher)) { return std::string("/") + join(*concrete, "/"); } else { - throw std::runtime_error("Unsupported InputSpec kind"); + throw runtime_error("Unsupported InputSpec kind"); } } @@ -215,7 +217,7 @@ bool DataSpecUtils::match(InputSpec const& spec, ConcreteDataMatcher const& targ data_matcher::VariableContext context; return matcher->match(target, context); } else { - throw std::runtime_error("Unsupported InputSpec"); + throw runtime_error("Unsupported InputSpec"); } } @@ -406,7 +408,7 @@ ConcreteDataTypeMatcher DataSpecUtils::asConcreteDataTypeMatcher(InputSpec const if (state.hasUniqueOrigin && state.hasUniqueDescription) { return ConcreteDataTypeMatcher{state.origin, state.description}; } - throw std::runtime_error("Could not extract data type from query"); + throw runtime_error("Could not extract data type from query"); }}, spec.matcher); } @@ -422,7 +424,7 @@ header::DataOrigin DataSpecUtils::asConcreteOrigin(InputSpec const& spec) if (state.hasUniqueOrigin) { return state.origin; } - throw std::runtime_error("Could not extract data type from query"); + throw runtime_error("Could not extract data type from query"); }}, spec.matcher); } @@ -438,7 +440,7 @@ header::DataDescription DataSpecUtils::asConcreteDataDescription(InputSpec const if (state.hasUniqueDescription) { return state.description; } - throw std::runtime_error("Could not extract data type from query"); + throw runtime_error("Could not extract data type from query"); }}, spec.matcher); } @@ -457,7 +459,7 @@ OutputSpec DataSpecUtils::asOutputSpec(InputSpec const& spec) return OutputSpec{{spec.binding}, ConcreteDataTypeMatcher{state.origin, state.description}, spec.lifetime}; } - throw std::runtime_error("Could not extract neither ConcreteDataMatcher nor ConcreteDataTypeMatcher from query" + describe(spec)); + throw runtime_error_f("Could not extract neither ConcreteDataMatcher nor ConcreteDataTypeMatcher from query %s", describe(spec).c_str()); }}, spec.matcher); } @@ -554,7 +556,7 @@ std::optional<header::DataHeader::SubSpecificationType> DataSpecUtils::getOption if (state.hasUniqueSubSpec) { return std::make_optional(state.subSpec); } else if (state.hasError) { - throw std::runtime_error("Could not extract subSpec from query"); + throw runtime_error("Could not extract subSpec from query"); } return {}; }}, diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index a6eef7615cb12..56d9f94d64086 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -30,6 +30,7 @@ #include "Framework/WorkflowSpec.h" #include "Framework/ComputingResource.h" #include "Framework/Logger.h" +#include "Framework/RuntimeError.h" #include "WorkflowHelpers.h" @@ -110,7 +111,7 @@ struct ExpirationHandlerHelpers { /// FIXME: seems convoluted... Maybe there is a way to avoid all this checking??? auto m = std::get_if<ConcreteDataMatcher>(&spec.matcher); if (m == nullptr) { - throw std::runtime_error("InputSpec for Conditions must be fully qualified"); + throw runtime_error("InputSpec for Conditions must be fully qualified"); } return [s = spec, matcher = *m, sourceChannel](DeviceState&, ConfigParamRegistry const& options) { @@ -151,7 +152,7 @@ struct ExpirationHandlerHelpers { { auto m = std::get_if<ConcreteDataMatcher>(&spec.matcher); if (m == nullptr) { - throw std::runtime_error("InputSpec for Timers must be fully qualified"); + throw runtime_error("InputSpec for Timers must be fully qualified"); } // We copy the matcher to avoid lifetime issues. return [matcher = *m, sourceChannel](DeviceState&, ConfigParamRegistry const&) { return LifetimeHelpers::enumerate(matcher, sourceChannel); }; @@ -161,7 +162,7 @@ struct ExpirationHandlerHelpers { { auto m = std::get_if<ConcreteDataMatcher>(&spec.matcher); if (m == nullptr) { - throw std::runtime_error("InputSpec for Enumeration must be fully qualified"); + throw runtime_error("InputSpec for Enumeration must be fully qualified"); } // We copy the matcher to avoid lifetime issues. return [matcher = *m, sourceChannel](DeviceState&, ConfigParamRegistry const&) { @@ -752,7 +753,7 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf } return deviceEdge.deviceIndex; } - throw std::runtime_error("Unable to find device."); + throw runtime_error("Unable to find device."); }; // Optimize the topology when two devices are @@ -789,7 +790,7 @@ void DeviceSpecHelpers::reworkShmSegmentSize(std::vector<DataProcessorInfo>& inf } auto value = it + 1; if (value == info.cmdLineArgs.end()) { - throw std::runtime_error("--shm-segment-size requires an argument"); + throw runtime_error("--shm-segment-size requires an argument"); } char* err = nullptr; int64_t size = strtoll(value->c_str(), &err, 10); diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 12acc095328a1..0284124a406b3 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -11,6 +11,7 @@ #include "../src/ExpressionHelpers.h" #include "Framework/VariantHelpers.h" #include "Framework/Logger.h" +#include "Framework/RuntimeError.h" #include "gandiva/tree_expr_builder.h" #include "arrow/table.h" #include "fmt/format.h" @@ -89,7 +90,7 @@ std::string upcastTo(atype::type f) case atype::DOUBLE: return "castFLOAT8"; default: - throw std::runtime_error(fmt::format("Do not know how to cast to {}", f)); + throw runtime_error_f("Do not know how to cast to %d", f); } } @@ -241,7 +242,7 @@ Operations createOperations(Filter const& expression) auto inferResultType = [&resultTypes](DatumSpec& left, DatumSpec& right) { // if the left datum is monostate (error) if (left.datum.index() == 0) { - throw std::runtime_error("Malformed operation spec: empty left datum"); + throw runtime_error("Malformed operation spec: empty left datum"); } // check if the datums are references @@ -289,7 +290,7 @@ Operations createOperations(Filter const& expression) if (t1 == atype::DOUBLE) { return atype::DOUBLE; } - throw std::runtime_error(fmt::format("Invalid combination of argument types {} and {}", t1, t2)); + throw runtime_error_f("Invalid combination of argument types %d and %d", t1, t2); }; for (auto it = OperationSpecs.rbegin(); it != OperationSpecs.rend(); ++it) { @@ -321,11 +322,10 @@ std::shared_ptr<gandiva::Filter> auto s = gandiva::Filter::Make(Schema, makeCondition(createExpressionTree(opSpecs, Schema)), &filter); - if (s.ok()) { - return filter; - } else { - throw std::runtime_error(fmt::format("Failed to create filter: {}", s.ToString())); + if (!s.ok()) { + throw runtime_error_f("Failed to create filter: %s", s.ToString().c_str()); } + return filter; } std::shared_ptr<gandiva::Filter> @@ -335,11 +335,10 @@ std::shared_ptr<gandiva::Filter> auto s = gandiva::Filter::Make(Schema, condition, &filter); - if (s.ok()) { - return filter; - } else { - throw std::runtime_error(fmt::format("Failed to create filter: {}", s.ToString())); + if (!s.ok()) { + throw runtime_error_f("Failed to create filter: %s", s.ToString().c_str()); } + return filter; } std::shared_ptr<gandiva::Projector> @@ -349,11 +348,10 @@ std::shared_ptr<gandiva::Projector> auto s = gandiva::Projector::Make(Schema, {makeExpression(createExpressionTree(opSpecs, Schema), result)}, &projector); - if (s.ok()) { - return projector; - } else { - throw std::runtime_error(fmt::format("Failed to create projector: {}", s.ToString())); + if (!s.ok()) { + throw runtime_error_f("Failed to create projector: %s", s.ToString().c_str()); } + return projector; } std::shared_ptr<gandiva::Projector> @@ -369,21 +367,21 @@ Selection createSelection(std::shared_ptr<arrow::Table> table, std::shared_ptr<g arrow::default_memory_pool(), &selection); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot allocate selection vector {}", s.ToString())); + throw runtime_error_f("Cannot allocate selection vector %s", s.ToString().c_str()); } arrow::TableBatchReader reader(*table); std::shared_ptr<arrow::RecordBatch> batch; while (true) { s = reader.ReadNext(&batch); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot read batches from table {}", s.ToString())); + throw runtime_error_f("Cannot read batches from table %s", s.ToString().c_str()); } if (batch == nullptr) { break; } s = gfilter->Evaluate(*batch, selection); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot apply filter {}", s.ToString())); + throw runtime_error_f("Cannot apply filter %s", s.ToString().c_str()); } } @@ -404,14 +402,14 @@ auto createProjection(std::shared_ptr<arrow::Table> table, std::shared_ptr<gandi while (true) { auto s = reader.ReadNext(&batch); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot read batches from table {}", s.ToString())); + throw runtime_error_f("Cannot read batches from table %s", s.ToString().c_str()); } if (batch == nullptr) { break; } s = gprojector->Evaluate(*batch, arrow::default_memory_pool(), v.get()); if (!s.ok()) { - throw std::runtime_error(fmt::format("Cannot apply projector {}", s.ToString())); + throw runtime_error_f("Cannot apply projector %s", s.ToString().c_str()); } } return v; @@ -450,7 +448,7 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, if (content.index() == 4) { return gandiva::TreeExprBuilder::MakeLiteral(std::get<uint8_t>(content)); } - throw std::runtime_error("Malformed LiteralNode"); + throw runtime_error("Malformed LiteralNode"); } if (spec.datum.index() == 3) { @@ -461,13 +459,13 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, } auto field = Schema->GetFieldByName(name); if (field == nullptr) { - throw std::runtime_error(fmt::format("Cannot find field \"{}\"", name)); + throw runtime_error_f("Cannot find field \"%s\"", name.c_str()); } auto node = gandiva::TreeExprBuilder::MakeField(field); fieldNodes.insert({name, node}); return node; } - throw std::runtime_error("Malformed DatumSpec"); + throw runtime_error("Malformed DatumSpec"); }; gandiva::NodePtr tree = nullptr; @@ -545,7 +543,7 @@ bool isSchemaCompatible(gandiva::SchemaPtr const& Schema, Operations const& opSp void updateExpressionInfos(expressions::Filter const& filter, std::vector<ExpressionInfo>& eInfos) { if (eInfos.empty()) { - throw std::runtime_error("Empty expression info vector."); + throw runtime_error("Empty expression info vector."); } Operations ops = createOperations(filter); for (auto& info : eInfos) { diff --git a/Framework/Core/src/LifetimeHelpers.cxx b/Framework/Core/src/LifetimeHelpers.cxx index c21214b17e6b1..3bd1b26d390ee 100644 --- a/Framework/Core/src/LifetimeHelpers.cxx +++ b/Framework/Core/src/LifetimeHelpers.cxx @@ -180,7 +180,7 @@ ExpirationHandler::Handler char* err; uint64_t overrideTimestampMilliseconds = strtoll(overrideTimestamp.c_str(), &err, 10); if (*err != 0) { - throw std::runtime_error("fetchFromCCDBCache: Unable to parse forced timestamp for conditions"); + throw runtime_error("fetchFromCCDBCache: Unable to parse forced timestamp for conditions"); } if (overrideTimestampMilliseconds) { LOGP(info, "fetchFromCCDBCache: forcing timestamp for conditions to {} milliseconds from epoch UTC", overrideTimestampMilliseconds); @@ -199,7 +199,7 @@ ExpirationHandler::Handler CURL* curl = curl_easy_init(); if (curl == nullptr) { - throw std::runtime_error("fetchFromCCDBCache: Unable to initialise CURL"); + throw runtime_error("fetchFromCCDBCache: Unable to initialise CURL"); } CURLcode res; if (overrideTimestampMilliseconds) { @@ -216,13 +216,13 @@ ExpirationHandler::Handler res = curl_easy_perform(curl); if (res != CURLE_OK) { - throw std::runtime_error(std::string("fetchFromCCDBCache: Unable to fetch ") + url + " from CCDB"); + throw runtime_error_f("fetchFromCCDBCache: Unable to fetch %s from CCDB", url.c_str()); } long responseCode; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); if (responseCode != 200) { - throw std::runtime_error(std::string("fetchFromCCDBCache: HTTP error ") + std::to_string(responseCode) + " while fetching " + url + " from CCDB"); + throw runtime_error_f("fetchFromCCDBCache: HTTP error %d while fetching %s from CCDB", responseCode, url.c_str()); } curl_easy_cleanup(curl); @@ -254,7 +254,7 @@ ExpirationHandler::Handler ExpirationHandler::Handler LifetimeHelpers::fetchFromQARegistry() { return [](ServiceRegistry&, PartRef& ref, uint64_t) -> void { - throw std::runtime_error("fetchFromQARegistry: Not yet implemented"); + throw runtime_error("fetchFromQARegistry: Not yet implemented"); return; }; } @@ -265,7 +265,7 @@ ExpirationHandler::Handler LifetimeHelpers::fetchFromQARegistry() ExpirationHandler::Handler LifetimeHelpers::fetchFromObjectRegistry() { return [](ServiceRegistry&, PartRef& ref, uint64_t) -> void { - throw std::runtime_error("fetchFromObjectRegistry: Not yet implemented"); + throw runtime_error("fetchFromObjectRegistry: Not yet implemented"); return; }; } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 921a921f08e30..b19aa1815d255 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -107,6 +107,7 @@ #include <sys/un.h> #include <sys/wait.h> #include <unistd.h> +#include <execinfo.h> #if __has_include(<linux/getcpu.h>) #include <linux/getcpu.h> #elif __has_include(<cpuid.h>) @@ -763,11 +764,16 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f runner.AddHook<fair::mq::hooks::InstantiateDevice>(afterConfigParsingCallback); return runner.Run(); } catch (boost::exception& e) { - LOG(ERROR) << "Unhandled exception reached the top of main, device shutting down. Details follow: \n" + LOG(ERROR) << "Unhandled boost::exception reached the top of main, device shutting down. Details follow: \n" << boost::current_exception_diagnostic_information(true); return 1; + } catch (o2::framework::RuntimeErrorRef e) { + LOG(ERROR) << "Unhandled o2::framework::runtime_error reached the top of main, device shutting down. Details follow: \n"; + auto& err = o2::framework::error_from_ref(e); + backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); + return 1; } catch (std::exception& e) { - LOG(ERROR) << "Unhandled exception reached the top of main: " << e.what() << ", device shutting down."; + LOG(ERROR) << "Unhandled std::exception reached the top of main: " << e.what() << ", device shutting down."; return 1; } catch (...) { LOG(ERROR) << "Unknown exception reached the top of main.\n"; diff --git a/Framework/Core/test/test_InputRecord.cxx b/Framework/Core/test/test_InputRecord.cxx index 539b8063e1199..56276be56c1ab 100644 --- a/Framework/Core/test/test_InputRecord.cxx +++ b/Framework/Core/test/test_InputRecord.cxx @@ -22,7 +22,7 @@ using namespace o2::framework; using DataHeader = o2::header::DataHeader; using Stack = o2::header::Stack; -bool any_exception(std::exception const& ex) { return true; } +bool any_exception(RuntimeErrorRef const& ex) { return true; } BOOST_AUTO_TEST_CASE(TestInputRecord) { @@ -48,12 +48,12 @@ BOOST_AUTO_TEST_CASE(TestInputRecord) // bunch of exceptions. InputRecord emptyRecord(schema, {[](size_t) { return DataRef{nullptr, nullptr, nullptr}; }, 0}); - BOOST_CHECK_EXCEPTION(emptyRecord.get("x"), std::exception, any_exception); - BOOST_CHECK_EXCEPTION(emptyRecord.get("y"), std::exception, any_exception); - BOOST_CHECK_EXCEPTION(emptyRecord.get("z"), std::exception, any_exception); - BOOST_CHECK_EXCEPTION(emptyRecord.getByPos(0), std::exception, any_exception); - BOOST_CHECK_EXCEPTION(emptyRecord.getByPos(1), std::exception, any_exception); - BOOST_CHECK_EXCEPTION(emptyRecord.getByPos(2), std::exception, any_exception); + BOOST_CHECK_EXCEPTION(emptyRecord.get("x"), RuntimeErrorRef, any_exception); + BOOST_CHECK_EXCEPTION(emptyRecord.get("y"), RuntimeErrorRef, any_exception); + BOOST_CHECK_EXCEPTION(emptyRecord.get("z"), RuntimeErrorRef, any_exception); + BOOST_CHECK_EXCEPTION(emptyRecord.getByPos(0), RuntimeErrorRef, any_exception); + BOOST_CHECK_EXCEPTION(emptyRecord.getByPos(1), RuntimeErrorRef, any_exception); + BOOST_CHECK_EXCEPTION(emptyRecord.getByPos(2), RuntimeErrorRef, any_exception); // Then we actually check with a real set of inputs. std::vector<void*> inputs; @@ -97,13 +97,13 @@ BOOST_AUTO_TEST_CASE(TestInputRecord) auto ref00 = record.get("x"); auto ref10 = record.get("y"); auto ref20 = record.get("z"); - BOOST_CHECK_EXCEPTION(record.get("err"), std::exception, any_exception); + BOOST_CHECK_EXCEPTION(record.get("err"), RuntimeErrorRef, any_exception); // Or we can get it positionally BOOST_CHECK_NO_THROW(record.get("x")); auto ref01 = record.getByPos(0); auto ref11 = record.getByPos(1); - BOOST_CHECK_EXCEPTION(record.getByPos(10), std::exception, any_exception); + BOOST_CHECK_EXCEPTION(record.getByPos(10), RuntimeErrorRef, any_exception); // This should be exactly the same pointers BOOST_CHECK_EQUAL(ref00.header, ref01.header); diff --git a/Framework/Core/test/test_Services.cxx b/Framework/Core/test/test_Services.cxx index 946e21afd1bb5..ccba588e4c665 100644 --- a/Framework/Core/test/test_Services.cxx +++ b/Framework/Core/test/test_Services.cxx @@ -61,8 +61,8 @@ BOOST_AUTO_TEST_CASE(TestServiceRegistry) BOOST_CHECK(registry.active<InterfaceA>() == true); BOOST_CHECK(registry.active<InterfaceB>() == true); BOOST_CHECK(registry.active<InterfaceC>() == false); - BOOST_CHECK_THROW(registry.get<InterfaceA const>(), std::runtime_error); - BOOST_CHECK_THROW(registry.get<InterfaceC>(), std::runtime_error); + BOOST_CHECK_THROW(registry.get<InterfaceA const>(), RuntimeErrorRef); + BOOST_CHECK_THROW(registry.get<InterfaceC>(), RuntimeErrorRef); } BOOST_AUTO_TEST_CASE(TestCallbackService) @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(TestCallbackService) registry.get<CallbackService>().set(CallbackService::Id::Stop, cb); // check to set with the wrong type - BOOST_CHECK_THROW(registry.get<CallbackService>().set(CallbackService::Id::Stop, [](int) {}), std::runtime_error); + BOOST_CHECK_THROW(registry.get<CallbackService>().set(CallbackService::Id::Stop, [](int) {}), RuntimeErrorRef); // execute and check registry.get<CallbackService>()(CallbackService::Id::Stop); diff --git a/Framework/Core/test/test_TMessageSerializer.cxx b/Framework/Core/test/test_TMessageSerializer.cxx index bf75bb814e9eb..bea66936c3452 100644 --- a/Framework/Core/test/test_TMessageSerializer.cxx +++ b/Framework/Core/test/test_TMessageSerializer.cxx @@ -45,15 +45,22 @@ BOOST_AUTO_TEST_CASE(TestTMessageSerializer) BOOST_CHECK_EQUAL(named->GetTitle(), testtitle); // test deserialization with a wrong target class and check the exception - try { - auto out2 = TMessageSerializer::deserialize<TNamed>(buf); - BOOST_FAIL("here we should never get, the function call must fail with exception"); - } catch (std::exception& e) { - std::string expected("can not convert serialized class TObjArray into target class TNamed"); - BOOST_CHECK_MESSAGE(expected == e.what(), e.what()); - } + BOOST_CHECK_EXCEPTION(TMessageSerializer::deserialize<TNamed>(buf), + RuntimeErrorRef, + [](RuntimeErrorRef const& ref) { + auto& e = error_from_ref(ref); + std::string expected("can not convert serialized class TObjArray into target class TNamed"); + return expected == e.what; + }); } +bool check_expected(RuntimeErrorRef const& ref) +{ + auto& e = error_from_ref(ref); + std::string expected("can not convert serialized class vector<o2::test::Polymorphic> into target class TObject"); + return expected == e.what; +}; + BOOST_AUTO_TEST_CASE(TestTMessageSerializer_NonTObject) { using namespace o2::framework; @@ -73,13 +80,7 @@ BOOST_AUTO_TEST_CASE(TestTMessageSerializer_NonTObject) BOOST_CHECK((*out.get())[1] == o2::test::Polymorphic(0xd00f)); // test deserialization with a wrong target class and check the exception - try { - auto out2 = TMessageSerializer::deserialize(as_span(msg)); - BOOST_FAIL("here we should never get, the function call must fail with exception"); - } catch (std::exception& e) { - std::string expected("can not convert serialized class vector<o2::test::Polymorphic> into target class TObject"); - BOOST_CHECK_MESSAGE(expected == e.what(), e.what()); - } + BOOST_CHECK_EXCEPTION(TMessageSerializer::deserialize(as_span(msg)), RuntimeErrorRef, check_expected); } BOOST_AUTO_TEST_CASE(TestTMessageSerializer_InvalidBuffer) @@ -97,12 +98,12 @@ BOOST_AUTO_TEST_CASE(TestTMessageSerializer_InvalidBuffer) } */ // test deserialization of invalid target class and check the exception - try { - struct Dummy { - }; - auto out = TMessageSerializer::deserialize<Dummy>((o2::byte*)buffer, strlen(buffer)); - BOOST_ERROR("here we should never get, the function call must fail with exception"); - } catch (std::exception& e) { - BOOST_CHECK_MESSAGE(std::string(e.what()).find("class is not ROOT-serializable") == 0, e.what()); - } + struct Dummy { + }; + BOOST_CHECK_EXCEPTION(TMessageSerializer::deserialize<Dummy>((o2::byte*)buffer, strlen(buffer)), + RuntimeErrorRef, + [](RuntimeErrorRef const& ref) { + auto& err = error_from_ref(ref); + return strcmp(err.what, "class is not ROOT-serializable") != 0; + }); } diff --git a/Framework/Core/test/test_Variants.cxx b/Framework/Core/test/test_Variants.cxx index 5950a75b3a299..671b62a6dabfb 100644 --- a/Framework/Core/test/test_Variants.cxx +++ b/Framework/Core/test/test_Variants.cxx @@ -13,15 +13,15 @@ #include <boost/test/unit_test.hpp> #include "Framework/Variant.h" -#include <stdexcept> #include <sstream> #include <cstring> using namespace o2::framework; -bool unknown_type(std::runtime_error const& ex) +bool unknown_type(RuntimeErrorRef const& ref) { - return strcmp(ex.what(), "Mismatch between types") == 0; + auto& err = error_from_ref(ref); + return strcmp(err.what, "Mismatch between types") == 0; } BOOST_AUTO_TEST_CASE(VariantTest) @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(VariantTest) Variant c(10.2); BOOST_CHECK(c.get<double>() == 10.2); ss << c; - BOOST_CHECK_EXCEPTION(a.get<char*>(), std::runtime_error, unknown_type); + BOOST_CHECK_EXCEPTION(a.get<char*>(), RuntimeErrorRef, unknown_type); Variant d("foo"); ss << d; BOOST_CHECK(std::string(d.get<const char*>()) == "foo"); diff --git a/Framework/Core/test/unittest_DataSpecUtils.cxx b/Framework/Core/test/unittest_DataSpecUtils.cxx index 1327de30ebe0b..f35c214a149a1 100644 --- a/Framework/Core/test/unittest_DataSpecUtils.cxx +++ b/Framework/Core/test/unittest_DataSpecUtils.cxx @@ -302,7 +302,7 @@ BOOST_AUTO_TEST_CASE(GettingConcreteMembers) BOOST_REQUIRE_EQUAL(justOriginInputSpec.size(), 1); BOOST_CHECK_EQUAL(DataSpecUtils::asConcreteOrigin(justOriginInputSpec.at(0)).as<std::string>(), "TST"); - BOOST_CHECK_THROW(DataSpecUtils::asConcreteDataDescription(justOriginInputSpec.at(0)).as<std::string>(), std::runtime_error); + BOOST_CHECK_THROW(DataSpecUtils::asConcreteDataDescription(justOriginInputSpec.at(0)).as<std::string>(), RuntimeErrorRef); } BOOST_AUTO_TEST_CASE(Includes) @@ -327,4 +327,4 @@ BOOST_AUTO_TEST_CASE(Includes) BOOST_CHECK(DataSpecUtils::includes(wildcardInput1, wildcardInput1)); BOOST_CHECK(!DataSpecUtils::includes(wildcardInput1, wildcardInput2)); BOOST_CHECK(!DataSpecUtils::includes(wildcardInput2, wildcardInput1)); -} \ No newline at end of file +} diff --git a/Framework/Foundation/CMakeLists.txt b/Framework/Foundation/CMakeLists.txt index 5760a2ff00d15..ab4c3d7c4fe99 100644 --- a/Framework/Foundation/CMakeLists.txt +++ b/Framework/Foundation/CMakeLists.txt @@ -12,7 +12,13 @@ install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/Framework DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) o2_add_library(FrameworkFoundation - SOURCES src/RuntimeError.cxx) + SOURCES src/RuntimeError.cxx + TARGETVARNAME targetName + ) +if (DPL_ENABLE_BACKTRACE) +target_compile_definitions(${targetName} PUBLIC -DDPL_ENABLE_BACKTRACE) +endif() + o2_add_test(test_FunctionalHelpers NAME test_FrameworkFoundation_test_FunctionalHelpers COMPONENT_NAME FrameworkFoundation diff --git a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx index eb1099cdbb7a9..54e973b4c1f8c 100644 --- a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx +++ b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx @@ -42,6 +42,7 @@ AlgorithmSpec simplePipe(std::string const& what, int minDelay) return AlgorithmSpec{adaptStateful([what, minDelay]() { srand(getpid()); return adaptStateless([what, minDelay](DataAllocator& outputs) { + throw runtime_error_f("This is an error %d", 1); std::this_thread::sleep_for(std::chrono::seconds((rand() % 5) + minDelay)); auto& bData = outputs.make<int>(OutputRef{what}, 1); }); diff --git a/Framework/Utils/include/DPLUtils/RootTreeWriter.h b/Framework/Utils/include/DPLUtils/RootTreeWriter.h index 87f47893c31ef..c6291a651ef7e 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeWriter.h +++ b/Framework/Utils/include/DPLUtils/RootTreeWriter.h @@ -672,7 +672,7 @@ class RootTreeWriter if (ptr) { delete ptr; } - } catch (const std::runtime_error& e) { + } catch (RuntimeErrorRef e) { if constexpr (has_root_dictionary<value_type>::value == true) { // try extracting from message with serialization method ROOT auto data = context.get<typename std::add_pointer<value_type>::type>(ref); From c2d2772c3989abde31759449784046b3e36b1594 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 16 Oct 2020 08:41:48 +0200 Subject: [PATCH 0965/1751] DPL Analysis: protect expression application from empty table (#4606) --- Framework/Core/src/Expressions.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 0284124a406b3..94f63dd75353b 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -369,6 +369,9 @@ Selection createSelection(std::shared_ptr<arrow::Table> table, std::shared_ptr<g if (!s.ok()) { throw runtime_error_f("Cannot allocate selection vector %s", s.ToString().c_str()); } + if (table->num_rows() == 0) { + return selection; + } arrow::TableBatchReader reader(*table); std::shared_ptr<arrow::RecordBatch> batch; while (true) { From fd80b2987e216f6bd8c2bef4dc9e95c0b1057635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Fri, 16 Oct 2020 08:42:59 +0200 Subject: [PATCH 0966/1751] PWGHF: Fix histogram filling. Define base candidate columns. (#4608) * PWGHF: Fill 3-prong vertex histograms also for negative candidates. * PWGHF: Define base columns with a macro. --- .../include/Analysis/HFSecondaryVertex.h | 86 ++++++++----------- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 6 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 6 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 7 +- 4 files changed, 43 insertions(+), 62 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index b24b1ea0f1ff0..b8a5caeae6330 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -30,6 +30,7 @@ DECLARE_SOA_COLUMN(IsSel3Prong, isSel3Prong, int); DECLARE_SOA_COLUMN(DCAPrim0, dcaPrim0, float); DECLARE_SOA_COLUMN(DCAPrim1, dcaPrim1, float); } // namespace hf_seltrack + DECLARE_SOA_TABLE(HFSelTrack, "AOD", "SELTRACK", hf_seltrack::IsSel2Prong, hf_seltrack::IsSel3Prong, @@ -179,36 +180,40 @@ auto CosThetaStarD0bar(const T& candidate) } } // namespace hf_cand_prong2 -DECLARE_SOA_TABLE(HfCandBase, "AOD", "HFCANDBASE", - collision::PosX, collision::PosY, collision::PosZ, - hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, - hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, - hf_cand::Chi2PCA, - /* dynamic columns */ - hf_cand::RSecondaryVertex<hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, - hf_cand::ImpactParameterNormalised0<hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0>, - hf_cand::ImpactParameterNormalised1<hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter1>, - hf_cand::PtProng0<hf_cand::PxProng0, hf_cand::PyProng0>, - hf_cand::Pt2Prong0<hf_cand::PxProng0, hf_cand::PyProng0>, - hf_cand::PVectorProng0<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0>, - hf_cand::PtProng1<hf_cand::PxProng1, hf_cand::PyProng1>, - hf_cand::Pt2Prong1<hf_cand::PxProng1, hf_cand::PyProng1>, - hf_cand::PVectorProng1<hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, - hf_cand::DecayLength<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex>, - hf_cand::DecayLengthXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, - hf_cand::DecayLengthNormalised<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand::ErrorDecayLength>, - hf_cand::DecayLengthXYNormalised<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ErrorDecayLengthXY>, //); - - //DECLARE_SOA_TABLE(HfCandProng2Base, "AOD", "HFCANDPRG2BASE", // TODO split table +// general columns +#define HFCAND_COLUMNS \ + collision::PosX, collision::PosY, collision::PosZ, \ + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, \ + hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, \ + hf_cand::Chi2PCA, \ + /* dynamic columns */ hf_cand::RSecondaryVertex<hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, \ + hf_cand::DecayLength<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex>, \ + hf_cand::DecayLengthXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, \ + hf_cand::DecayLengthNormalised<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand::ErrorDecayLength>, \ + hf_cand::DecayLengthXYNormalised<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ErrorDecayLengthXY>, \ + /* prong 0 */ hf_cand::ImpactParameterNormalised0<hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0>, \ + hf_cand::PtProng0<hf_cand::PxProng0, hf_cand::PyProng0>, \ + hf_cand::Pt2Prong0<hf_cand::PxProng0, hf_cand::PyProng0>, \ + hf_cand::PVectorProng0<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0>, \ + /* prong 1 */ hf_cand::ImpactParameterNormalised1<hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter1>, \ + hf_cand::PtProng1<hf_cand::PxProng1, hf_cand::PyProng1>, \ + hf_cand::Pt2Prong1<hf_cand::PxProng1, hf_cand::PyProng1>, \ + hf_cand::PVectorProng1<hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1> + +// 2-prong decay candidate table +DECLARE_SOA_TABLE(HfCandProng2Base, "AOD", "HFCANDP2BASE", + // general columns + HFCAND_COLUMNS, + // 2-prong specific columns hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, 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::ImpactParameter0, hf_cand::ImpactParameter1>, hf_cand_prong2::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, hf_cand_prong2::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, + hf_cand_prong2::ImpactParameterProduct<hf_cand::ImpactParameter0, hf_cand::ImpactParameter1>, hf_cand_prong2::CosThetaStar<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, /* dynamic columns that use candidate momentum components */ hf_cand::Pt<hf_cand_prong2::Px, hf_cand_prong2::Py>, @@ -224,11 +229,8 @@ DECLARE_SOA_TABLE(HfCandBase, "AOD", "HFCANDBASE", hf_cand::E<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, hf_cand::E2<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>); -//using HfCandProng2Origin = soa::Join<HfCandBase, HfCandProng2Base>; // TODO split table -using HfCandProng2Origin = HfCandBase; - // extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng2Ext, HfCandProng2Origin, "HFCANDPRG2EXT", +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng2Ext, HfCandProng2Base, "HFCANDP2EXT", hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz); using HfCandProng2 = HfCandProng2Ext; @@ -271,27 +273,11 @@ auto InvMassDPlus(const T& candidate) } } // namespace hf_cand_prong3 -DECLARE_SOA_TABLE(HfCandBase3, "AOD", "HFCANDBASE3", - collision::PosX, collision::PosY, collision::PosZ, - hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, - hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, - hf_cand::Chi2PCA, - /* dynamic columns */ - hf_cand::RSecondaryVertex<hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, - hf_cand::ImpactParameterNormalised0<hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0>, - hf_cand::ImpactParameterNormalised1<hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter1>, - hf_cand::PtProng0<hf_cand::PxProng0, hf_cand::PyProng0>, - hf_cand::Pt2Prong0<hf_cand::PxProng0, hf_cand::PyProng0>, - hf_cand::PVectorProng0<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0>, - hf_cand::PtProng1<hf_cand::PxProng1, hf_cand::PyProng1>, - hf_cand::Pt2Prong1<hf_cand::PxProng1, hf_cand::PyProng1>, - hf_cand::PVectorProng1<hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, - hf_cand::DecayLength<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex>, - hf_cand::DecayLengthXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex>, - hf_cand::DecayLengthNormalised<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand::ErrorDecayLength>, - hf_cand::DecayLengthXYNormalised<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ErrorDecayLengthXY>, //); - - //DECLARE_SOA_TABLE(HfCandProng3Base, "AOD", "HFCANDPRG3BASE", // TODO split table +// 3-prong decay candidate table +DECLARE_SOA_TABLE(HfCandProng3Base, "AOD", "HFCANDP3BASE", + // general columns + HFCAND_COLUMNS, + // 3-prong specific columns hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, @@ -301,6 +287,7 @@ DECLARE_SOA_TABLE(HfCandBase3, "AOD", "HFCANDBASE3", /* dynamic columns */ hf_cand_prong3::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, hf_cand_prong3::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, + /* prong 2 */ hf_cand::ImpactParameterNormalised2<hf_cand::ImpactParameter2, hf_cand::ErrorImpactParameter2>, hf_cand::PtProng2<hf_cand::PxProng2, hf_cand::PyProng2>, hf_cand::Pt2Prong2<hf_cand::PxProng2, hf_cand::PyProng2>, @@ -319,11 +306,8 @@ DECLARE_SOA_TABLE(HfCandBase3, "AOD", "HFCANDBASE3", hf_cand::E<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, hf_cand::E2<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>); -//using HfCandProng3Origin = soa::Join<HfCandBase3, HfCandProng3Base>; // TODO split table -using HfCandProng3Origin = HfCandBase3; - // extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng3Ext, HfCandProng3Origin, "HFCANDPRG3EXT", +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng3Ext, HfCandProng3Base, "HFCANDP3EXT", hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz); using HfCandProng3 = HfCandProng3Ext; diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 455ef64174783..de3a78a123a10 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -26,8 +26,7 @@ using namespace o2::framework; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HFCandidateCreator2Prong { - Produces<aod::HfCandBase> rowCandidateBase; - //Produces<aod::HfCandProng2Base> rowCandidateProng2Base; // TODO split table + Produces<aod::HfCandProng2Base> rowCandidateBase; Configurable<double> magneticField{"d_bz", 5.0, "magnetic field"}; Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; @@ -104,8 +103,7 @@ struct HFCandidateCreator2Prong { rowCandidateBase(collision.posX(), collision.posY(), collision.posZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], errorDecayLength, errorDecayLengthXY, - chi2PCA, //); - //rowCandidateProng2Base( // TODO split table + chi2PCA, pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], impactParameter0.getY(), impactParameter1.getY(), diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 21d5f02fcaafb..00488d15a7341 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -26,8 +26,7 @@ using namespace o2::framework; /// Reconstruction of heavy-flavour 3-prong decay candidates struct HFCandidateCreator3Prong { - Produces<aod::HfCandBase3> rowCandidateBase; - //Produces<aod::HfCandProng3Base> rowCandidateProng3Base; // TODO split table + Produces<aod::HfCandProng3Base> rowCandidateBase; Configurable<double> magneticField{"d_bz", 5.0, "magnetic field"}; Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; @@ -108,8 +107,7 @@ struct HFCandidateCreator3Prong { rowCandidateBase(collision.posX(), collision.posY(), collision.posZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], errorDecayLength, errorDecayLengthXY, - chi2PCA, //); - //rowCandidateProng3Base( // TODO split table + chi2PCA, pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], pvec2[0], pvec2[1], pvec2[2], diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index c75ca881942b2..3a69c57fbe85d 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -308,9 +308,6 @@ struct HFTrackIndexSkimsCreator { if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) continue; - // get vertex - //const auto& vtx3 = df3.getPCACandidate(); - // get track momenta array<float, 3> pvec0; array<float, 3> pvec1; @@ -318,6 +315,7 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(0).getPxPyPzGlo(pvec0); df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); + const auto& secondaryVertex3 = df3.getPCACandidate(); // calculate invariant mass arr3Mom = array{pvec0, pvec1, pvec2}; @@ -325,6 +323,9 @@ struct HFTrackIndexSkimsCreator { if (b_dovalplots) { hmass3->Fill(mass3PiKPi); + hvtx3_x_out->Fill(secondaryVertex3[0]); + hvtx3_y_out->Fill(secondaryVertex3[1]); + hvtx3_z_out->Fill(secondaryVertex3[2]); } // fill table row From 6e159913ada1f6cc38e717d03b648b232e52046c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 16 Oct 2020 10:42:08 +0200 Subject: [PATCH 0967/1751] DPL Analysis: use "Consume" as a policy for AOD writer (#4612) --- Framework/Core/src/CompletionPolicy.cxx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Framework/Core/src/CompletionPolicy.cxx b/Framework/Core/src/CompletionPolicy.cxx index 83c4334852b3b..f4cc5b26861c8 100644 --- a/Framework/Core/src/CompletionPolicy.cxx +++ b/Framework/Core/src/CompletionPolicy.cxx @@ -14,9 +14,7 @@ #include <functional> #include <iostream> -namespace o2 -{ -namespace framework +namespace o2::framework { /// By default the CompletionPolicy matches any Device and only runs a @@ -24,7 +22,9 @@ namespace framework std::vector<CompletionPolicy> CompletionPolicy::createDefaultPolicies() { - return {CompletionPolicyHelpers::consumeWhenAll()}; + return { + CompletionPolicyHelpers::defineByName("internal-dpl-aod-writer", CompletionOp::Consume), + CompletionPolicyHelpers::consumeWhenAll()}; } std::ostream& operator<<(std::ostream& oss, CompletionPolicy::CompletionOp const& val) @@ -46,5 +46,4 @@ std::ostream& operator<<(std::ostream& oss, CompletionPolicy::CompletionOp const return oss; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework From 60a4968a0ef47e9d056387fc35480a83ef972bf7 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Fri, 16 Oct 2020 10:52:01 +0200 Subject: [PATCH 0968/1751] Writes time frames into directories TF_%d of same file (#4595) --- .../include/Framework/DataOutputDirector.h | 8 ++-- Framework/Core/src/CommonDataProcessors.cxx | 7 ++- Framework/Core/src/DataInputDirector.cxx | 1 + Framework/Core/src/DataOutputDirector.cxx | 43 ++++++++++--------- Framework/Core/src/TableTreeHelpers.cxx | 11 ++++- 5 files changed, 42 insertions(+), 28 deletions(-) diff --git a/Framework/Core/include/Framework/DataOutputDirector.h b/Framework/Core/include/Framework/DataOutputDirector.h index 3d819875d9c38..6a2655316cfb1 100644 --- a/Framework/Core/include/Framework/DataOutputDirector.h +++ b/Framework/Core/include/Framework/DataOutputDirector.h @@ -75,8 +75,10 @@ struct DataOutputDirector { std::vector<DataOutputDescriptor*> getDataOutputDescriptors(InputSpec spec); // get the matching TFile - TFile* getDataOutputFile(DataOutputDescriptor* dod, - int ntf, int ntfmerge, std::string filemode); + std::tuple<TFile*, std::string> getFileFolder(DataOutputDescriptor* dodesc, + int ntf, int ntfmerge, + std::string filemode); + void closeDataFiles(); void setFilenameBase(std::string dfn); @@ -89,7 +91,7 @@ struct DataOutputDirector { std::vector<DataOutputDescriptor*> mDataOutputDescriptors; std::vector<std::string> mtreeFilenames; std::vector<std::string> mfilenameBases; - std::vector<int> mfileCounts; + std::vector<int> mfolderCounts; std::vector<TFile*> mfilePtrs; bool mdebugmode = false; diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 37f1af7c6e32c..e0a4257be1528 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -472,9 +472,12 @@ DataProcessorSpec // a table can be saved in multiple ways // e.g. different selections of columns to different files for (auto d : ds) { + + auto [file, directory] = dod->getFileFolder(d, ntf, ntfmerge, filemode); + auto treename = directory + d->treename; TableToTree ta2tr(table, - dod->getDataOutputFile(d, ntf, ntfmerge, filemode), - d->treename.c_str()); + file, + treename.c_str()); if (d->colnames.size() > 0) { for (auto cn : d->colnames) { diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 2713b0e61c5c8..effa16adf8a54 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -48,6 +48,7 @@ FileNameHolder* makeFileNameHolder(std::string fileName) fileNameHolder->numberOfTimeFrames = fileNameHolder->listOfTimeFrameKeys.size(); delete file; + delete file; return fileNameHolder; } diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index 17adfc56e2a10..99f10171207b8 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -142,7 +142,7 @@ void DataOutputDirector::reset() mtreeFilenames.clear(); closeDataFiles(); mfilePtrs.clear(); - mfileCounts.clear(); + mfolderCounts.clear(); mfilenameBase = std::string(""); }; @@ -184,10 +184,10 @@ void DataOutputDirector::readString(std::string const& keepString) auto last = std::unique(mfilenameBases.begin(), mfilenameBases.end()); mfilenameBases.erase(last, mfilenameBases.end()); - // prepare list mfilePtrs of TFile and mfileCounts + // prepare list mfilePtrs of TFile and mfolderCounts for (auto fn : mfilenameBases) { mfilePtrs.emplace_back(new TFile()); - mfileCounts.emplace_back(-1); + mfolderCounts.emplace_back(-1); } } @@ -428,34 +428,35 @@ std::vector<DataOutputDescriptor*> DataOutputDirector::getDataOutputDescriptors( return result; } -TFile* DataOutputDirector::getDataOutputFile(DataOutputDescriptor* dodesc, - int ntf, int ntfmerge, - std::string filemode) +std::tuple<TFile*, std::string> DataOutputDirector::getFileFolder(DataOutputDescriptor* dodesc, + int ntf, int ntfmerge, + std::string filemode) { // initialisation TFile* filePtr = nullptr; + std::string directoryName(""); // search dodesc->filename in mfilenameBases and return corresponding filePtr auto it = std::find(mfilenameBases.begin(), mfilenameBases.end(), dodesc->getFilenameBase()); if (it != mfilenameBases.end()) { int ind = std::distance(mfilenameBases.begin(), it); - - // check if new version of file needs to be opened - int fcnt = (int)(ntf / ntfmerge); - if ((ntf % ntfmerge) == 0 && fcnt > mfileCounts[ind]) { - if (mfilePtrs[ind]) { - mfilePtrs[ind]->Close(); - } - - mfileCounts[ind] = fcnt; - auto fn = mfilenameBases[ind] + "_" + std::to_string(mfileCounts[ind]) + ".root"; + if (!mfilePtrs[ind]->IsOpen()) { + auto fn = mfilenameBases[ind] + ".root"; mfilePtrs[ind] = new TFile(fn.c_str(), filemode.c_str()); } filePtr = mfilePtrs[ind]; - filePtr->cd(); + + // check if new folder TF_* is needed + int fcnt = (int)(ntf / ntfmerge); + directoryName = "TF_" + std::to_string(fcnt) + "/"; + if ((ntf % ntfmerge) == 0 && fcnt > mfolderCounts[ind]) { + mfolderCounts[ind] = fcnt; + filePtr->mkdir(directoryName.c_str()); + } + filePtr->cd(directoryName.c_str()); } - return filePtr; + return std::make_tuple(filePtr, directoryName); } void DataOutputDirector::closeDataFiles() @@ -493,7 +494,7 @@ void DataOutputDirector::setFilenameBase(std::string dfn) mtreeFilenames.clear(); closeDataFiles(); mfilePtrs.clear(); - mfileCounts.clear(); + mfolderCounts.clear(); // loop over DataOutputDescritors for (auto dodesc : mDataOutputDescriptors) { @@ -514,10 +515,10 @@ void DataOutputDirector::setFilenameBase(std::string dfn) auto last = std::unique(mfilenameBases.begin(), mfilenameBases.end()); mfilenameBases.erase(last, mfilenameBases.end()); - // prepare list mfilePtrs of TFile and mfileCounts + // prepare list mfilePtrs of TFile and mfolderCounts for (auto fn : mfilenameBases) { mfilePtrs.emplace_back(new TFile()); - mfileCounts.emplace_back(-1); + mfolderCounts.emplace_back(-1); } } diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 6137d0c38e281..6f0537fdfdbf1 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -373,7 +373,14 @@ TableToTree::TableToTree(std::shared_ptr<arrow::Table> table, // create the tree if it does not exist already if (!mTreePtr) { - mTreePtr = new TTree(treename, treename); + // does treename containe folder? + std::string treeName(treename); + auto pos = treeName.find_first_of("/"); + if (pos != std::string::npos) { + file->cd(treeName.substr(0, pos).c_str()); + } + treeName = treeName.substr(pos + 1, std::string::npos); + mTreePtr = new TTree(treeName.c_str(), treeName.c_str()); } } @@ -423,7 +430,7 @@ TTree* TableToTree::process() togo &= brit->push(); } } - mTreePtr->Write(); + mTreePtr->Write("", TObject::kOverwrite); return mTreePtr; } From b5be7f5879c7f87290d48878c5c31b9441a40211 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Fri, 16 Oct 2020 13:50:28 +0200 Subject: [PATCH 0969/1751] fixing double delete (#4613) --- Framework/Core/src/DataInputDirector.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index effa16adf8a54..2713b0e61c5c8 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -48,7 +48,6 @@ FileNameHolder* makeFileNameHolder(std::string fileName) fileNameHolder->numberOfTimeFrames = fileNameHolder->listOfTimeFrameKeys.size(); delete file; - delete file; return fileNameHolder; } From a3e41ec99e381b997dad41e7ca08fcbff23e5716 Mon Sep 17 00:00:00 2001 From: iravasen <ivan.ravasenga@cern.ch> Date: Fri, 16 Oct 2020 15:12:56 +0200 Subject: [PATCH 0970/1751] task moved to PWGLF, modification of CMakeList done accordingly --- Analysis/Tasks/CMakeLists.txt | 5 ----- Analysis/Tasks/PWGLF/CMakeLists.txt | 6 ++++++ Analysis/Tasks/{ => PWGLF}/trackchecks.cxx | 0 3 files changed, 6 insertions(+), 5 deletions(-) rename Analysis/Tasks/{ => PWGLF}/trackchecks.cxx (100%) diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index c625a353963bf..3d6c4bad4b8ec 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -102,8 +102,3 @@ o2_add_dpl_workflow(run3-matcher SOURCES run3Matcher.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(track-checks - SOURCES trackchecks.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt index 7ac04b413f504..6b1d703be7636 100644 --- a/Analysis/Tasks/PWGLF/CMakeLists.txt +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -63,3 +63,9 @@ o2_add_dpl_workflow(raacharged PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) +o2_add_dpl_workflow(track-checks + SOURCES trackchecks.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + diff --git a/Analysis/Tasks/trackchecks.cxx b/Analysis/Tasks/PWGLF/trackchecks.cxx similarity index 100% rename from Analysis/Tasks/trackchecks.cxx rename to Analysis/Tasks/PWGLF/trackchecks.cxx From b0e81513e0585d86298a9a4b7a5c913d8fca3961 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Fri, 16 Oct 2020 19:41:26 +0200 Subject: [PATCH 0971/1751] tables for run 3 matcher (#4614) --- Analysis/Tasks/run3Matcher.cxx | 2 ++ Framework/Core/include/Framework/AnalysisDataModel.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Analysis/Tasks/run3Matcher.cxx b/Analysis/Tasks/run3Matcher.cxx index b1877418f572f..10263ca6fa2d3 100644 --- a/Analysis/Tasks/run3Matcher.cxx +++ b/Analysis/Tasks/run3Matcher.cxx @@ -23,6 +23,8 @@ using namespace o2::framework::expressions; struct Run3Matcher { BuildsExclusive<aod::Run3MatchedExclusive> matched_e; Builds<aod::Run3MatchedSparse> matched_s; + BuildsExclusive<aod::BCCollisionsExclusive> bc_e; + Builds<aod::BCCollisionsSparse> bc; void init(o2::framework::InitContext&) { } diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 321c0c293f337..8e92461402b85 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -611,7 +611,7 @@ DECLARE_SOA_INDEX_COLUMN(FDD, fdd); DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); -#define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FV0CId, indices::FDDId +#define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FDDId DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MA_RN3_SP", INDEX_LIST_RUN3); From b0539d3439829b9c81f06c52c3e11f3a373a2961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20von=20Haller?= <barthelemy.von.haller@cern.ch> Date: Sat, 17 Oct 2020 08:43:39 +0200 Subject: [PATCH 0972/1751] Overload InputSpecsForPolicy with shared_ptr (#4610) Add an overloaded version of InputSpecsForPolicy that takes a shared_ptr instead of a raw. The former version is marked as deprecated and should be removed as soon as we switch in QC. --- .../include/DataSampling/DataSampling.h | 3 +++ Utilities/DataSampling/src/DataSampling.cxx | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Utilities/DataSampling/include/DataSampling/DataSampling.h b/Utilities/DataSampling/include/DataSampling/DataSampling.h index 2ca8f02cb15c6..6ef4f9a0ca2d4 100644 --- a/Utilities/DataSampling/include/DataSampling/DataSampling.h +++ b/Utilities/DataSampling/include/DataSampling/DataSampling.h @@ -94,7 +94,10 @@ class DataSampling /// \brief Provides InputSpecs to receive data for given DataSamplingPolicy static std::vector<framework::InputSpec> InputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); /// \brief Provides InputSpecs to receive data for given DataSamplingPolicy + /// @deprecated static std::vector<framework::InputSpec> InputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); + /// \brief Provides InputSpecs to receive data for given DataSamplingPolicy + static std::vector<framework::InputSpec> InputSpecsForPolicy(std::shared_ptr<configuration::ConfigurationInterface> config, const std::string& policyName); /// \brief Provides OutputSpecs of given DataSamplingPolicy static std::vector<framework::OutputSpec> OutputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); /// \brief Provides OutputSpecs of given DataSamplingPolicy diff --git a/Utilities/DataSampling/src/DataSampling.cxx b/Utilities/DataSampling/src/DataSampling.cxx index abf7ff6164852..91d9b60236383 100644 --- a/Utilities/DataSampling/src/DataSampling.cxx +++ b/Utilities/DataSampling/src/DataSampling.cxx @@ -138,6 +138,24 @@ std::vector<InputSpec> DataSampling::InputSpecsForPolicy(ConfigurationInterface* return inputs; } +std::vector<InputSpec> DataSampling::InputSpecsForPolicy(std::shared_ptr<configuration::ConfigurationInterface> config, const std::string& policyName) +{ + std::vector<InputSpec> inputs; + auto policiesTree = config->getRecursive("dataSamplingPolicies"); + + for (auto&& policyConfig : policiesTree) { + if (policyConfig.second.get<std::string>("id") == policyName) { + DataSamplingPolicy policy(policyConfig.second); + for (const auto& path : policy.getPathMap()) { + InputSpec input = DataSpecUtils::matchingInput(path.second); + inputs.push_back(input); + } + break; + } + } + return inputs; +} + std::vector<OutputSpec> DataSampling::OutputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName) { std::unique_ptr<ConfigurationInterface> config = ConfigurationFactory::getConfiguration(policiesSource); From b7bb4e9cc14d856758b62be17f1921aff2360aea Mon Sep 17 00:00:00 2001 From: anerokhi <44967087+anerokhi@users.noreply.github.com> Date: Sat, 17 Oct 2020 09:44:32 +0300 Subject: [PATCH 0973/1751] Algorithm Common: add braces to single statements (#4567) --- Algorithm/include/Algorithm/Parser.h | 37 +++++++++++++------ Algorithm/include/Algorithm/TableView.h | 30 ++++++++++----- Algorithm/test/pageparser.cxx | 3 +- CCDB/include/CCDB/BasicCCDBManager.h | 3 +- Common/Field/src/MagFieldFast.cxx | 25 ++++++++----- Common/Field/src/MagFieldParam.cxx | 30 ++++++++++----- Common/Field/src/MagneticField.cxx | 22 +++++++---- Common/Field/src/MagneticWrapperChebyshev.cxx | 3 +- Common/MathUtils/include/MathUtils/MathBase.h | 24 ++++++++---- Common/MathUtils/src/Chebyshev3D.cxx | 6 ++- Common/MathUtils/test/testUtils.cxx | 3 +- Common/Utils/include/CommonUtils/TreeStream.h | 3 +- Common/Utils/src/TreeStream.cxx | 24 ++++++++---- Common/Utils/src/TreeStreamRedirector.cxx | 15 +++++--- Common/Utils/test/testTreeStream.cxx | 18 ++++++--- run/O2HitMerger.h | 6 ++- 16 files changed, 167 insertions(+), 85 deletions(-) diff --git a/Algorithm/include/Algorithm/Parser.h b/Algorithm/include/Algorithm/Parser.h index 960e9e6a18751..43ec4daa90aec 100644 --- a/Algorithm/include/Algorithm/Parser.h +++ b/Algorithm/include/Algorithm/Parser.h @@ -158,25 +158,30 @@ class ForwardParser { static_assert(sizeof(InputType) == 1, "ForwardParser currently only supports byte type buffer"); - if (buffer == nullptr || bufferSize == 0) + if (buffer == nullptr || bufferSize == 0) { return 0; + } + size_t position = 0; std::vector<FrameInfo> frames; do { FrameInfo entry; // check the header - if (sizeof(HeaderType) + position > bufferSize) + if (sizeof(HeaderType) + position > bufferSize) { break; + } entry.header = reinterpret_cast<const HeaderType*>(buffer + position); - if (!checkHeader(*entry.header)) + if (!checkHeader(*entry.header)) { break; + } // extract frame size from header, this is expected to be the // total frome size including header, payload and optional trailer auto frameSize = getFrameSize(*entry.header); - if (frameSize + position > bufferSize) + if (frameSize + position > bufferSize) { break; + } // payload starts right after the header entry.payload = reinterpret_cast<typename FrameInfo::PtrT>(entry.header + 1); @@ -188,8 +193,9 @@ class ForwardParser } else { auto trailerStart = buffer + position + frameSize - tailOffset; entry.trailer = reinterpret_cast<const TrailerType*>(trailerStart); - if (!CheckTrailer(entry, checkTrailer)) + if (!CheckTrailer(entry, checkTrailer)) { break; + } } // store the extracted frame info and continue with remaining buffer @@ -201,8 +207,9 @@ class ForwardParser // frames found and format consistent, insert entries to target // Note: the complete block must be consistent for (auto entry : frames) { - if (!insert(entry)) + if (!insert(entry)) { break; + } } return frames.size(); } else if (frames.size() == 0) { @@ -332,30 +339,35 @@ class ReverseParser { static_assert(sizeof(InputType) == 1, "ReverseParser currently only supports byte type buffer"); - if (buffer == nullptr || bufferSize == 0) + if (buffer == nullptr || bufferSize == 0) { return 0; + } auto position = bufferSize; std::vector<FrameInfo> frames; do { FrameInfo entry; // start from end, extract and check trailer - if (sizeof(TrailerType) > position) + if (sizeof(TrailerType) > position) { break; + } entry.trailer = reinterpret_cast<const TrailerType*>(buffer + position - sizeof(TrailerType)); - if (!checkTrailer(*entry.trailer)) + if (!checkTrailer(*entry.trailer)) { break; + } // get the total frame size auto frameSize = getFrameSize(*entry.trailer); - if (frameSize > position) + if (frameSize > position) { break; + } // extract and check header auto headerStart = buffer + position - frameSize; entry.header = reinterpret_cast<const HeaderType*>(headerStart); - if (!checkHeader(*entry.header)) + if (!checkHeader(*entry.header)) { break; + } // payload immediately after header entry.payload = reinterpret_cast<typename FrameInfo::PtrT>(entry.header + 1); @@ -367,8 +379,9 @@ class ReverseParser if (position == 0) { // frames found and format consistent, the complete block must be consistent for (auto entry : frames) { - if (!insert(entry)) + if (!insert(entry)) { break; + } } return frames.size(); } else if (frames.size() == 0) { diff --git a/Algorithm/include/Algorithm/TableView.h b/Algorithm/include/Algorithm/TableView.h index 3aa2e5b91dd5f..462a5ef74d74c 100644 --- a/Algorithm/include/Algorithm/TableView.h +++ b/Algorithm/include/Algorithm/TableView.h @@ -67,10 +67,12 @@ class TableView bool operator<(const FrameIndex& rh) const { - if (rh.columnIndex < columnIndex) + if (rh.columnIndex < columnIndex) { return false; - if (columnIndex < rh.columnIndex) + } + if (columnIndex < rh.columnIndex) { return true; + } return row < rh.row; } }; @@ -143,8 +145,9 @@ class TableView /// get row data for a data set const RowDescType& getRowData(size_t row) const { - if (row < mRowData.size()) + if (row < mRowData.size()) { return mRowData[row]; + } // TODO: better to throw exception? static RowDescType dummy; return dummy; @@ -180,22 +183,26 @@ class TableView iterator(IteratorDirections direction, TableView* parent, unsigned row = 0, unsigned column = 0) : mDirection(direction), mRow(row), mColumn(column), mEnd(direction == kAlongRow ? parent->getNColumns() : parent->getNRows()), mParent(parent), mCache(), mIsCached(false) { - while (!isValid() && !isEnd()) + while (!isValid() && !isEnd()) { operator++(); + } } self_type& operator++() { mIsCached = false; if (mDirection == kAlongRow) { - if (mColumn < mEnd) + if (mColumn < mEnd) { mColumn++; + } } else { - if (mRow < mEnd) + if (mRow < mEnd) { mRow++; + } } - while (!isEnd() && !isValid()) + while (!isEnd() && !isValid()) { operator++(); + } return *this; } @@ -265,11 +272,13 @@ class TableView self_type& operator++() { if (base::mDirection == iterator::kAlongRow) { - if (base::mColumn < base::mEnd) + if (base::mColumn < base::mEnd) { base::mColumn++; + } } else { - if (base::mRow < base::mEnd) + if (base::mRow < base::mEnd) { base::mRow++; + } } return *this; } @@ -314,8 +323,9 @@ class TableView /// private access function for the iterators bool get(unsigned row, unsigned column, FrameData& data) { - if (this->mColumns.size() == 0) + if (this->mColumns.size() == 0) { return false; + } auto element = this->mFrames.find(FrameIndex{this->mColumns[column], row}); if (element != this->mFrames.end()) { data = element->second; diff --git a/Algorithm/test/pageparser.cxx b/Algorithm/test/pageparser.cxx index 10a918beb23cf..a7b03ecb36816 100644 --- a/Algorithm/test/pageparser.cxx +++ b/Algorithm/test/pageparser.cxx @@ -78,8 +78,9 @@ std::pair<std::unique_ptr<uint8_t[]>, size_t> MakeBuffer(size_t pagesize, } while (nPages * pagesize < totalSize); } else { auto nRequiredPages = dataset.size() / maxElementsPerPage; - if (dataset.size() % maxElementsPerPage > 0) + if (dataset.size() % maxElementsPerPage > 0) { ++nRequiredPages; + } totalSize = (nRequiredPages > 0 ? nRequiredPages : 1) * pagesize; } diff --git a/CCDB/include/CCDB/BasicCCDBManager.h b/CCDB/include/CCDB/BasicCCDBManager.h index b34cce62fc93a..2a6a85b840981 100644 --- a/CCDB/include/CCDB/BasicCCDBManager.h +++ b/CCDB/include/CCDB/BasicCCDBManager.h @@ -147,8 +147,9 @@ T* BasicCCDBManager::getForTimeStamp(std::string const& path, long timestamp) mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : ""); } auto& cached = mCache[path]; - if (mCheckObjValidityEnabled && cached.isValid(timestamp)) + if (mCheckObjValidityEnabled && cached.isValid(timestamp)) { return reinterpret_cast<T*>(cached.objPtr.get()); + } T* ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, &mHeaders, cached.uuid, mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "", diff --git a/Common/Field/src/MagFieldFast.cxx b/Common/Field/src/MagFieldFast.cxx index 2016012e02b24..aabbb4d016b01 100644 --- a/Common/Field/src/MagFieldFast.cxx +++ b/Common/Field/src/MagFieldFast.cxx @@ -68,22 +68,25 @@ bool MagFieldFast::LoadData(const string inpFName) SolParam* curParam = nullptr; while (std::getline(in, line)) { - if (line.empty() || line[0] == '#') + if (line.empty() || line[0] == '#') { continue; // empy or comment + } std::stringstream ss(line); int cnt = 0; if (component < 0) { - while (cnt < 4 && (ss >> header[cnt++])) + while (cnt < 4 && (ss >> header[cnt++])) { ; + } if (cnt != 4) { LOG(FATAL) << "Wrong header " << line; return false; } curParam = &mSolPar[header[0]][header[1]][header[2]]; } else { - while (cnt < header[3] && (ss >> curParam->parBxyz[component][cnt++])) + while (cnt < header[3] && (ss >> curParam->parBxyz[component][cnt++])) { ; + } if (cnt != header[3]) { LOG(FATAL) << "Wrong data (npar=" << cnt << ") for param " << header[0] << " " << header[1] << " " << header[2] << " " << header[3] << " " << line; @@ -215,20 +218,24 @@ bool MagFieldFast::GetSegment(float x, float y, float z, int& zSeg, int& rSeg, i const float zGridSpaceInv = 1.f / (kSolZMax * 2 / kNSolZRanges); zSeg = -1; if (z < kSolZMax) { - if (z > -kSolZMax) + if (z > -kSolZMax) { zSeg = (z + kSolZMax) * zGridSpaceInv; // solenoid params - else { // need to check dipole params + } else { // need to check dipole params return false; } - } else + } else { return false; + } // R segment float xx = x * x, yy = y * y, rr = xx + yy; - for (rSeg = 0; rSeg < kNSolRRanges; rSeg++) - if (rr < kSolR2Max[rSeg]) + for (rSeg = 0; rSeg < kNSolRRanges; rSeg++) { + if (rr < kSolR2Max[rSeg]) { break; - if (rSeg == kNSolRRanges) + } + } + if (rSeg == kNSolRRanges) { return kFALSE; + } quadrant = GetQuadrant(x, y); return true; } diff --git a/Common/Field/src/MagFieldParam.cxx b/Common/Field/src/MagFieldParam.cxx index 66310ea7b4117..dd7fb68978c7f 100644 --- a/Common/Field/src/MagFieldParam.cxx +++ b/Common/Field/src/MagFieldParam.cxx @@ -48,8 +48,9 @@ void MagFieldParam::SetParam(const MagneticField* field) void MagFieldParam::putParams(FairParamList* list) { /// store parameters in the list - if (!list) + if (!list) { return; + } list->add("Map Type ID", int(mMapType)); list->add("Beam Type ID", int(mBeamType)); list->add("Integral Type", mDefaultIntegration); @@ -65,33 +66,42 @@ Bool_t MagFieldParam::getParams(FairParamList* list) { /// retried parameters int int2enum = 0; - if (!list->fill("Map Type ID", &int2enum)) + if (!list->fill("Map Type ID", &int2enum)) { return kFALSE; + } mMapType = static_cast<BMap_t>(int2enum); - if (!list->fill("Beam Type ID", &int2enum)) + if (!list->fill("Beam Type ID", &int2enum)) { return kFALSE; + } mBeamType = static_cast<BeamType_t>(int2enum); // - if (!list->fill("Integral Type", &mDefaultIntegration)) + if (!list->fill("Integral Type", &mDefaultIntegration)) { return kFALSE; - if (!list->fill("Fact.Solenoid", &mFactorSol)) + } + if (!list->fill("Fact.Solenoid", &mFactorSol)) { return kFALSE; - if (!list->fill("Fact.Dipole ", &mFactorDip)) + } + if (!list->fill("Fact.Dipole ", &mFactorDip)) { return kFALSE; - if (!list->fill("Beam Energy ", &mBeamEnergy)) + } + if (!list->fill("Beam Energy ", &mBeamEnergy)) { return kFALSE; - if (!list->fill("Max. Field ", &mMaxField)) + } + if (!list->fill("Max. Field ", &mMaxField)) { return kFALSE; + } FairParamObj* parpath = list->find("Path to map "); - if (!parpath) + if (!parpath) { return kFALSE; + } int lgt = parpath->getLength(); // RS: is there a bug in FairParamList::fill(const Text_t* name,Text_t* value,const Int_t length)? // I think the "if (l<length-1)" should be "if (l<length)" char cbuff[lgt + 2]; memset(cbuff, 0, sizeof(char) * (lgt + 2)); - if (!list->fill("Path to map ", cbuff, lgt + 2)) + if (!list->fill("Path to map ", cbuff, lgt + 2)) { return kFALSE; + } mMapPath = cbuff; return kTRUE; } diff --git a/Common/Field/src/MagneticField.cxx b/Common/Field/src/MagneticField.cxx index f53ac5a42cfdc..3afabde8a0bbb 100644 --- a/Common/Field/src/MagneticField.cxx +++ b/Common/Field/src/MagneticField.cxx @@ -185,16 +185,18 @@ void MagneticField::CreateField() << "; Helix tracking chosen instead"; mDefaultIntegration = 2; } - if (mDefaultIntegration == 0) + if (mDefaultIntegration == 0) { mPrecisionInteg = 0; + } if (mBeamEnergy <= 0 && mBeamType != MagFieldParam::kNoBeamField) { - if (mBeamType == MagFieldParam::kBeamTypepp) + if (mBeamType == MagFieldParam::kBeamTypepp) { mBeamEnergy = 7000.; // max proton energy - else if (mBeamType == MagFieldParam::kBeamTypeAA) + } else if (mBeamType == MagFieldParam::kBeamTypeAA) { mBeamEnergy = 2760; // max PbPb energy - else if (mBeamType == MagFieldParam::kBeamTypepA || mBeamType == MagFieldParam::kBeamTypeAp) + } else if (mBeamType == MagFieldParam::kBeamTypepA || mBeamType == MagFieldParam::kBeamTypeAp) { mBeamEnergy = 2760; // same rigitiy max PbPb energy + } // LOG(INFO) << "MagneticField::CreateField: Maximim possible beam energy for requested beam is assumed"; } @@ -257,8 +259,9 @@ void MagneticField::Field(const Double_t* __restrict__ xyz, Double_t* __restrict */ // b[0]=b[1]=b[2]=0.0; - if (mFastField && mFastField->Field(xyz, b)) + if (mFastField && mFastField->Field(xyz, b)) { return; + } if (mMeasuredMap && xyz[2] > mMeasuredMap->getMinZ() && xyz[2] < mMeasuredMap->getMaxZ()) { mMeasuredMap->Field(xyz, b); @@ -284,8 +287,9 @@ Double_t MagneticField::getBz(const Double_t* xyz) const if (mFastField) { double bz = 0; - if (mFastField->GetBz(xyz, bz)) + if (mFastField->GetBz(xyz, bz)) { return bz; + } } if (mMeasuredMap && xyz[2] > mMeasuredMap->getMinZ() && xyz[2] < mMeasuredMap->getMaxZ()) { double bz = mMeasuredMap->getBz(xyz); @@ -478,8 +482,9 @@ void MagneticField::setFactorSolenoid(Float_t fc) mMultipicativeFactorSolenoid = fc; break; // case kConvMap2005: mMultipicativeFactorSolenoid = fc; break; } - if (mFastField) + if (mFastField) { mFastField->setFactorSol(getFactorSolenoid()); + } } void MagneticField::setFactorDipole(Float_t fc) @@ -665,8 +670,9 @@ void MagneticField::FillParContainer() void MagneticField::AllowFastField(bool v) { if (v) { - if (!mFastField) + if (!mFastField) { mFastField = std::make_unique<MagFieldFast>(getFactorSolenoid(), mMapType == MagFieldParam::k2kG ? 2 : 5); + } } else { mFastField.reset(nullptr); } diff --git a/Common/Field/src/MagneticWrapperChebyshev.cxx b/Common/Field/src/MagneticWrapperChebyshev.cxx index 10e8d7d8924d1..db73f2bf7ce45 100644 --- a/Common/Field/src/MagneticWrapperChebyshev.cxx +++ b/Common/Field/src/MagneticWrapperChebyshev.cxx @@ -1403,8 +1403,9 @@ void MagneticWrapperChebyshev::saveData(const char* outfile) const // TPCIntegral part fprintf(stream, "START TPCINT\n#Number of pieces\n%d\n", mNumberOfParameterizationTPC); - for (int ip = 0; ip < mNumberOfParameterizationTPC; ip++) + for (int ip = 0; ip < mNumberOfParameterizationTPC; ip++) { getParameterTPCIntegral(ip)->saveData(stream); + } fprintf(stream, "#\nEND TPCINT\n"); // TPCRatIntegral part diff --git a/Common/MathUtils/include/MathUtils/MathBase.h b/Common/MathUtils/include/MathUtils/MathBase.h index f4c26c4a0adfc..16d7d46b2b99c 100644 --- a/Common/MathUtils/include/MathUtils/MathBase.h +++ b/Common/MathUtils/include/MathUtils/MathBase.h @@ -170,18 +170,22 @@ Double_t fitGaus(const size_t nBins, const T* arr, const T xMin, const T xMax, s for (Int_t i = 0; i < nBins; i++) { entries += arr[i]; - if (arr[i] > 0) + if (arr[i] > 0) { nfilled++; + } } // TODO: Check why this is needed - if (max < 4) + if (max < 4) { return -4; - if (entries < 12) + } + if (entries < 12) { return -4; + } - if (rms < kTol) + if (rms < kTol) { return -4; + } param[3] = entries; @@ -224,16 +228,19 @@ Double_t fitGaus(const size_t nBins, const T* arr, const T xMin, const T xMax, s fitter.GetCovarianceMatrix(mat); chi2 = fitter.GetChisquare() / Double_t(npoints); } - if (TMath::Abs(par[1]) < kTol) + if (TMath::Abs(par[1]) < kTol) { return -4; - if (TMath::Abs(par[2]) < kTol) + } + if (TMath::Abs(par[2]) < kTol) { return -4; + } param[1] = T(par[1] / (-2. * par[2])); param[2] = T(1. / TMath::Sqrt(TMath::Abs(-2. * par[2]))); Double_t lnparam0 = par[0] + par[1] * param[1] + par[2] * param[1] * param[1]; - if (lnparam0 > 307) + if (lnparam0 > 307) { return -4; + } param[0] = TMath::Exp(lnparam0); return chi2; @@ -299,8 +306,9 @@ StatisticsData getStatisticsData(const T* arr, const size_t nBins, const double ++npoints; } } - if (sum == 0) + if (sum == 0) { return data; + } mean /= sum; data.mCOG = mean; diff --git a/Common/MathUtils/src/Chebyshev3D.cxx b/Common/MathUtils/src/Chebyshev3D.cxx index 963df5ae1ba60..2fd984640b6af 100644 --- a/Common/MathUtils/src/Chebyshev3D.cxx +++ b/Common/MathUtils/src/Chebyshev3D.cxx @@ -524,8 +524,9 @@ Int_t Chebyshev3D::chebyshevFit(int dmOut) Chebyshev3DCalc* cheb = getChebyshevCalc(dmOut); Float_t prec = cheb->getPrecision(); - if (prec < sMinimumPrecision) + if (prec < sMinimumPrecision) { prec = mPrecision; // no specific precision for this dim. + } Float_t rTiny = 0.1 * prec / Float_t(maxDim); // neglect coefficient below this threshold float ncals2count = mNumberOfPoints[2] * mNumberOfPoints[1] * mNumberOfPoints[0]; @@ -864,8 +865,9 @@ TH1* Chebyshev3D::TestRMS(int idim, int npoints, TH1* histo) } float prc = getChebyshevCalc(idim)->getPrecision(); - if (prc < sMinimumPrecision) + if (prc < sMinimumPrecision) { prc = mPrecision; // no dimension specific precision + } for (int ip = npoints; ip--;) { gRandom->RndmArray(3, (Float_t*)mTemporaryCoefficient); diff --git a/Common/MathUtils/test/testUtils.cxx b/Common/MathUtils/test/testUtils.cxx index 804a246765c8b..caae0e40e55a3 100644 --- a/Common/MathUtils/test/testUtils.cxx +++ b/Common/MathUtils/test/testUtils.cxx @@ -38,8 +38,9 @@ BOOST_AUTO_TEST_CASE(Utils_test) double diff = phi - phi0; p->Fill(phi0, diff); diff = fabs(diff); - if (diff > maxDiff) + if (diff > maxDiff) { maxDiff = diff; + } } //p->Draw(); diff --git a/Common/Utils/include/CommonUtils/TreeStream.h b/Common/Utils/include/CommonUtils/TreeStream.h index 35ed0616302ef..d1df4ca48f600 100644 --- a/Common/Utils/include/CommonUtils/TreeStream.h +++ b/Common/Utils/include/CommonUtils/TreeStream.h @@ -177,8 +177,9 @@ Int_t TreeStream::CheckIn(T* obj) { // check in arbitrary class having dictionary TClass* pClass = nullptr; - if (obj) + if (obj) { pClass = obj->IsA(); + } if (mCurrentIndex >= static_cast<int>(mElements.size())) { mElements.emplace_back(); diff --git a/Common/Utils/src/TreeStream.cxx b/Common/Utils/src/TreeStream.cxx index 664f002423b61..24171ff647ad3 100644 --- a/Common/Utils/src/TreeStream.cxx +++ b/Common/Utils/src/TreeStream.cxx @@ -59,16 +59,18 @@ void TreeStream::BuildTree() // Build the Tree int entriesFilled = mTree.GetEntries(); - if (mBranches.size() < mElements.size()) + if (mBranches.size() < mElements.size()) { mBranches.resize(mElements.size()); + } TString name; TBranch* br = nullptr; for (int i = 0; i < static_cast<int>(mElements.size()); i++) { // auto& element = mElements[i]; - if (mBranches[i]) + if (mBranches[i]) { continue; + } name = element.name.data(); if (name.IsNull()) { name = TString::Format("B%d", i); @@ -111,16 +113,19 @@ void TreeStream::Fill() } for (int i = 0; i < entries; i++) { auto& element = mElements[i]; - if (!element.type) + if (!element.type) { continue; + } auto br = mBranches[i]; if (br) { - if (element.type) + if (element.type) { br->SetAddress(element.ptr); + } } } - if (!mStatus) + if (!mStatus) { mTree.Fill(); // fill only in case of non conflicts + } mStatus = 0; } @@ -129,8 +134,9 @@ TreeStream& TreeStream::Endl() { // Perform pseudo endl operation - if (mTree.GetNbranches() == 0) + if (mTree.GetNbranches() == 0) { BuildTree(); + } Fill(); mStatus = 0; mCurrentIndex = 0; @@ -147,14 +153,16 @@ TreeStream& TreeStream::operator<<(const Char_t* name) } // // if tree was already defined ignore - if (mTree.GetEntries() > 0) + if (mTree.GetEntries() > 0) { return *this; + } // check branch name if tree was not // Int_t last = 0; for (last = 0;; last++) { - if (name[last] == 0) + if (name[last] == 0) { break; + } } if (last > 0 && name[last - 1] == '=') { diff --git a/Common/Utils/src/TreeStreamRedirector.cxx b/Common/Utils/src/TreeStreamRedirector.cxx index 0fa91c7f8d2ad..6218c0998ce3d 100644 --- a/Common/Utils/src/TreeStreamRedirector.cxx +++ b/Common/Utils/src/TreeStreamRedirector.cxx @@ -76,8 +76,9 @@ TreeStream& TreeStreamRedirector::operator<<(Int_t id) mDataLayouts.emplace_back(std::unique_ptr<TreeStream>(new TreeStream(Form("Tree%d", id)))); auto layout = mDataLayouts.back().get(); layout->setID(id); - if (backup) + if (backup) { backup->cd(); + } return *layout; } @@ -88,8 +89,9 @@ TreeStream& TreeStreamRedirector::operator<<(const char* name) // if not existing - creates new for (auto& layout : mDataLayouts) { - if (!std::strcmp(layout->getName(), name)) + if (!std::strcmp(layout->getName(), name)) { return *layout.get(); + } } // create new @@ -98,8 +100,9 @@ TreeStream& TreeStreamRedirector::operator<<(const char* name) mDataLayouts.emplace_back(std::unique_ptr<TreeStream>(new TreeStream(name))); auto layout = mDataLayouts.back().get(); layout->setID(-1); - if (backup) + if (backup) { backup->cd(); + } return *layout; } @@ -114,8 +117,9 @@ void TreeStreamRedirector::Close() layout->getTree().Write(layout->getName()); } mDataLayouts.clear(); - if (backup) + if (backup) { backup->cd(); + } if (mOwnDirectory) { mDirectory->Close(); @@ -143,8 +147,9 @@ void TreeStreamRedirector::FixLeafNameBug(TTree* tree) // After the fix unit test code with pairs of sprse friend trees worked properly // Side effects of fix: // - if (!tree) + if (!tree) { return; + } TObjArray* brArray = tree->GetListOfBranches(); TObjArray* lArray = tree->GetListOfLeaves(); for (int i = 0; i < brArray->GetLast(); i++) { diff --git a/Common/Utils/test/testTreeStream.cxx b/Common/Utils/test/testTreeStream.cxx index a401e2530baa4..d9a857ff091f6 100644 --- a/Common/Utils/test/testTreeStream.cxx +++ b/Common/Utils/test/testTreeStream.cxx @@ -124,16 +124,19 @@ bool UnitTestSparse(Double_t scale, Int_t testEntries) // Input parameter scale => downscaling of sprse element std::string outFName("testTreeStreamSparse.root"); - if (scale <= 0) + if (scale <= 0) { scale = 1; - if (scale > 1) + } + if (scale > 1) { scale = 1; + } TreeStreamRedirector* pcstream = new TreeStreamRedirector(outFName.data(), "recreate"); for (Int_t ientry = 0; ientry < testEntries; ientry++) { TVectorD vecRandom(200); TVectorD vecZerro(200); // zerro vector - for (Int_t j = 0; j < 200; j++) + for (Int_t j = 0; j < 200; j++) { vecRandom[j] = j + ientry + 0.1 * gRandom->Rndm(); + } Bool_t isSelected = (gRandom->Rndm() < scale); TVectorD* pvecFull = &vecRandom; TVectorD* pvecSparse = isSelected ? &vecRandom : nullptr; @@ -192,12 +195,15 @@ bool UnitTestSparse(Double_t scale, Int_t testEntries) treeSparseSkip0->SetBranchAddress("vec.", &pvecRead); Bool_t readOK = kTRUE; for (Int_t ientry = 0; ientry < testEntries; ientry++) { - if (!pvecRead) + if (!pvecRead) { continue; - if (pvecRead->GetNrows() == 0) + } + if (pvecRead->GetNrows() == 0) { continue; - if (TMath::Abs((*pvecRead)[0] - ientry) > 0.5) + } + if (TMath::Abs((*pvecRead)[0] - ientry) > 0.5) { readOK = kFALSE; + } } printf("#UnitTest:\tTestSparse(%f)\tReadOK\t%d\n", scale, readOK); // diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 386558fc404ba..1815fe4ed5eff 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -430,8 +430,9 @@ class O2HitMerger : public FairMQDevice } else { // loop over subevents Int_t nprimTot = 0; - for (auto entry = 0; entry < entries; entry++) + for (auto entry = 0; entry < entries; entry++) { nprimTot += nprimaries[entry]; + } Int_t idelta0 = 0; Int_t idelta1 = nprimTot; for (auto entry = entries - 1; entry >= 0; --entry) { @@ -461,8 +462,9 @@ class O2HitMerger : public FairMQDevice { Int_t cId = track.getMotherTrackId(); Int_t ioffset = (cId < nprim) ? idelta0 : idelta1; - if (cId != -1) + if (cId != -1) { track.SetMotherTrackId(cId + ioffset); + } } void updateTrackIdWithOffset(TrackReference& ref, Int_t nprim, Int_t idelta0, Int_t idelta1) From a986dd4dcc206ddee052ef48875d22369140f8cd Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Sat, 17 Oct 2020 13:30:19 +0200 Subject: [PATCH 0974/1751] HistogramRegistry: add support for all root histogram types (#4616) - store histograms in std::variant to support arbitrary root types - add fill() and fillWeight() functions to the registry - support filling by value and filling from filtered table with variable number of arguments depending on histogram dimensions --- Analysis/Tutorials/src/histogramRegistry.cxx | 137 +++- Framework/Core/CMakeLists.txt | 1 + .../include/Framework/HistogramRegistry.h | 600 +++++++++++------- Framework/Core/src/HistogramRegistry.cxx | 37 ++ .../Core/test/benchmark_HistogramRegistry.cxx | 8 +- .../Core/test/test_HistogramRegistry.cxx | 36 +- 6 files changed, 572 insertions(+), 247 deletions(-) create mode 100644 Framework/Core/src/HistogramRegistry.cxx diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index 6a14f665de918..f7f2d92d37657 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -27,16 +27,16 @@ struct ATask { "registry", true, { - {"eta", "#eta", {HistogramType::kTH1F, {{102, -2.01, 2.01}}}}, // - {"phi", "#varphi", {HistogramType::kTH1F, {{100, 0., 2. * M_PI}}}} // - } // + {"eta", "#eta", {HistType::kTH1F, {{102, -2.01, 2.01}}}}, // + {"phi", "#varphi", {HistType::kTH1F, {{100, 0., 2. * M_PI}}}} // + } // }; void process(aod::Tracks const& tracks) { for (auto& track : tracks) { - registry.get("eta")->Fill(track.eta()); - registry.get("phi")->Fill(track.phi()); + registry.get<TH1>("eta")->Fill(track.eta()); + registry.get<TH1>("phi")->Fill(track.phi()); } } }; @@ -47,9 +47,9 @@ struct BTask { "registry", true, { - {"eta", "#eta", {HistogramType::kTH1F, {{102, -2.01, 2.01}}}}, // - {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // - } // + {"eta", "#eta", {HistType::kTH1F, {{102, -2.01, 2.01}}}}, // + {"ptToPt", "#ptToPt", {HistType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // + } // }; void process(aod::Tracks const& tracks) @@ -59,9 +59,128 @@ struct BTask { } }; +struct CTask { + + HistogramRegistry registry{ + "registry", + true, + { + {"1d", "test 1d", {HistType::kTH1I, {{100, -10.0f, 10.0f}}}}, // + {"2d", "test 2d", {HistType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}}, // + {"3d", "test 3d", {HistType::kTH3D, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}}, // + {"4d", "test 4d", {HistType::kTHnC, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}}, // + {"5d", "test 5d", {HistType::kTHnSparseL, {{10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}}}}, // + } // + }; + + void init(o2::framework::InitContext&) + { + registry.add({"7d", "test 7d", {HistType::kTHnC, {{3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}}}}); + + registry.add({"6d", "test 6d", {HistType::kTHnC, {{3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}}}}); + + registry.add({"1d-profile", "test 1d profile", {HistType::kTProfile, {{20, 0.0f, 10.01f}}}}); + registry.add({"2d-profile", "test 2d profile", {HistType::kTProfile2D, {{20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}}}}); + registry.add({"3d-profile", "test 3d profile", {HistType::kTProfile3D, {{20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}}}}); + + registry.add({"2d-weight", "test 2d weight", {HistType::kTH2C, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true}); + + registry.add({"3d-weight", "test 3d weight", {HistType::kTH3C, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true}); + + registry.add({"4d-weight", "test 4d weight", {HistType::kTHnC, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}, true}); + + registry.add({"1d-profile-weight", "test 1d profile weight", {HistType::kTProfile, {{2, -10.0f, 10.01f}}}, true}); + registry.add({"2d-profile-weight", "test 2d profile weight", {HistType::kTProfile2D, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true}); + } + + void process(aod::Tracks const& tracks) + { + using namespace aod::track; + // does not work with dynamic columns (e.g. Charge, NormalizedPhi) + registry.fill<Eta>("1d", tracks, eta > -0.7f); + registry.fill<Pt, Eta, RawPhi>("3d", tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi, P, X>("5d", tracks, pt > 0.15f); + registry.fill<Pt, Eta, RawPhi, P, X, Y, Z>("7d", tracks, pt > 0.15f); + registry.fill<Pt, Eta, RawPhi>("2d-profile", tracks, eta > -0.5f); + + // fill 4d histogram with weight (column X) + registry.fillWeight<Pt, Eta, RawPhi, Z, X>("4d-weight", tracks, eta > 0.f); + + registry.fillWeight<Pt, Eta, RawPhi>("2d-weight", tracks, eta > 0.f); + + registry.fillWeight<Pt, Eta, RawPhi>("1d-profile-weight", tracks, eta > 0.f); + + for (auto& track : tracks) { + registry.fill("2d", track.eta(), track.pt()); + registry.fill("4d", track.pt(), track.eta(), track.phi(), track.signed1Pt()); + registry.fill("6d", track.pt(), track.eta(), track.phi(), track.snp(), track.tgl(), track.alpha()); + registry.fill("1d-profile", track.pt(), track.eta()); + registry.fill("3d-profile", track.pt(), track.eta(), track.phi(), track.snp()); + + // fill 3d histogram with weight (2.) + registry.fillWeight("3d-weight", track.pt(), track.eta(), track.phi(), 2.); + + registry.fillWeight("2d-profile-weight", track.pt(), track.eta(), track.phi(), 5.); + } + } +}; + +struct DTask { + HistogramRegistry spectra{"spectra", true, {}}; + HistogramRegistry etaStudy{"etaStudy", true, {}}; + + void init(o2::framework::InitContext&) + { + std::vector<double> ptBinning = {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<double> centBinning = {0., 30., 60., 90.}; + + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/c)"}; + AxisSpec centAxis = {centBinning, "centrality"}; + AxisSpec etaAxis = {5, -0.8, 0.8, "#eta"}; + AxisSpec phiAxis = {4, 0., 2. * M_PI, "#phi"}; + const int nCuts = 5; + AxisSpec cutAxis = {nCuts, -0.5, nCuts - 0.5, "cut setting"}; + + HistogramConfigSpec defaultParticleHist({HistType::kTHnF, {ptAxis, etaAxis, centAxis, cutAxis}}); + + spectra.add({"myControlHist", "a", {HistType::kTH2F, {ptAxis, etaAxis}}}); + spectra.get<TH2>("myControlHist")->GetYaxis()->SetTitle("my-y-axis"); + spectra.get<TH2>("myControlHist")->SetTitle("something meaningful"); + + spectra.add({"pions", "Pions", defaultParticleHist}); + spectra.add({"kaons", "Kaons", defaultParticleHist}); + spectra.add({"sigmas", "Sigmas", defaultParticleHist}); + spectra.add({"lambdas", "Lambd", defaultParticleHist}); + + spectra.get<THn>("lambdas")->SetTitle("Lambdas"); + + etaStudy.add({"positive", "A side spectra", {HistType::kTH1I, {ptAxis}}}); + etaStudy.add({"negative", "C side spectra", {HistType::kTH1I, {ptAxis}}}); + } + + void process(aod::Tracks const& tracks) + { + using namespace aod::track; + + etaStudy.fill<Pt>("positive", tracks, eta > 0.f); + etaStudy.fill<Pt>("negative", tracks, eta < 0.f); + + for (auto& track : tracks) { + spectra.fill("myControlHist", track.pt(), track.eta()); + spectra.fill("pions", track.pt(), track.eta(), 50., 0.); + spectra.fill("kaons", track.pt(), track.eta(), 50., 0.); + spectra.fill("sigmas", track.pt(), track.eta(), 50., 0.); + spectra.fill("lambdas", track.pt(), track.eta(), 50., 0.); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<ATask>("eta-and-phi-histograms"), - adaptAnalysisTask<BTask>("filtered-histograms")}; + adaptAnalysisTask<BTask>("filtered-histograms"), + adaptAnalysisTask<CTask>("dimension-test"), + adaptAnalysisTask<DTask>("realistic-example")}; } diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index d08fae78bf48d..badffa9815841 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -103,6 +103,7 @@ o2_add_library(Framework src/WorkflowSpec.cxx src/runDataProcessing.cxx src/ExternalFairMQDeviceProxy.cxx + src/HistogramRegistry.cxx test/TestClasses.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src PUBLIC_LINK_LIBRARIES ${DEBUGGUI_TARGET} diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 93f21ec50479d..b40577ccdf04e 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -23,96 +23,155 @@ #include "Framework/RuntimeError.h" #include "TClass.h" -#include "TH1.h" -#include "TH2.h" -#include "TH3.h" -#include "THn.h" -#include "THnSparse.h" -#include "TFolder.h" + +#include <TH1.h> +#include <TH2.h> +#include <TH3.h> +#include <THn.h> +#include <THnSparse.h> +#include <TProfile.h> +#include <TProfile2D.h> +#include <TProfile3D.h> + +#include <TFolder.h> +//#include <TObjArray.h> +//#include <TList.h> #include <string> #include <variant> -namespace o2 -{ -namespace framework +namespace o2::framework { -// Most common histogram types -enum HistogramType : unsigned int { - kTH1D = 0, - kTH1F = 1, - kTH1I = 2, - kTH2D = 3, - kTH2F = 4, - kTH2I = 5, - kTH3D = 6, - kTH3F = 7, - kTH3I = 8 +// Available root histogram types +enum HistType : unsigned int { + kUndefinedHist = 0, + kTH1D, + kTH1F, + kTH1I, + kTH1C, + kTH1S, + kTH2D, + kTH2F, + kTH2I, + kTH2C, + kTH2S, + kTH3D, + kTH3F, + kTH3I, + kTH3C, + kTH3S, + kTHnD, + kTHnF, + kTHnI, + kTHnC, + kTHnS, + kTHnL, + kTHnSparseD, + kTHnSparseF, + kTHnSparseI, + kTHnSparseC, + kTHnSparseS, + kTHnSparseL, + kTProfile, + kTProfile2D, + kTProfile3D, + kStepTHnF, // FIXME: for these two to work we need to align StepTHn ctors with the root THn ones + kStepTHnD }; -/// Description of a single histogram axis +// variant of all possible root pointers; here we use only the interface types since the underlying data representation (int,float,double,long,char) is irrelevant +using HistPtr = std::variant<std::shared_ptr<THn>, std::shared_ptr<THnSparse>, std::shared_ptr<TH3>, std::shared_ptr<TH2>, std::shared_ptr<TH1>, std::shared_ptr<TProfile3D>, std::shared_ptr<TProfile2D>, std::shared_ptr<TProfile>>; + +//************************************************************************************************** +/** + * Specification of an Axis. + */ +//************************************************************************************************** struct AxisSpec { - AxisSpec(int nBins_, std::vector<double> bins_, std::string label_ = "") - : nBins(nBins_), - bins(bins_), - binsEqual(false), - label(label_) + AxisSpec(std::vector<double> binEdges_, std::string title_ = "", std::optional<std::string> name_ = std::nullopt) + : nBins(std::nullopt), + binEdges(binEdges_), + title(title_), + name(name_) { } - AxisSpec(int nBins_, double binMin_, double binMax_, std::string label_ = "") + AxisSpec(int nBins_, double binMin_, double binMax_, std::string title_ = "", std::optional<std::string> name_ = std::nullopt) : nBins(nBins_), - bins({binMin_, binMax_}), - binsEqual(true), - label(label_) + binEdges({binMin_, binMax_}), + title(title_), + name(name_) { } - AxisSpec() : nBins(1), binsEqual(false), bins(), label("") {} - - int nBins; - std::vector<double> bins; - bool binsEqual; // if true, then bins specify min and max for equidistant binning - std::string label; + std::optional<int> nBins{}; + std::vector<double> binEdges{}; + std::string title{}; + std::optional<std::string> name{}; // optional axis name for ndim histograms }; -/// Data sctructure that will allow to construct a fully qualified TH* histogram +//************************************************************************************************** +/** + * Specification of a histogram configuration. + */ +//************************************************************************************************** struct HistogramConfigSpec { - HistogramConfigSpec(HistogramType type_, std::vector<AxisSpec> axes_) + HistogramConfigSpec(HistType type_, std::vector<AxisSpec> axes_) : type(type_), - axes(axes_), - binsEqual(axes.size() > 0 ? axes[0].binsEqual : false) + axes(axes_) { } + HistogramConfigSpec() = default; + HistogramConfigSpec(HistogramConfigSpec const& other) = default; + HistogramConfigSpec(HistogramConfigSpec&& other) = default; - HistogramConfigSpec() - : type(HistogramType::kTH1F), - axes(), - binsEqual(false) + void addAxis(const AxisSpec& axis) { + axes.push_back(axis); + } + + void addAxis(int nBins_, const double binMin_, const double binMax_, const std::string& title_ = "", const std::optional<std::string>& name_ = std::nullopt) + { + axes.push_back({nBins_, binMin_, binMax_, title_, name_}); + } + + void addAxis(const std::vector<double>& binEdges_, const std::string& title_, const std::string& name_) + { + axes.push_back({binEdges_, title_, name_}); + } + + void addAxes(const std::vector<AxisSpec>& axes_) + { + axes.insert(axes.end(), axes_.begin(), axes_.end()); + } + + // add axes defined in other HistogramConfigSpec object + void addAxes(const HistogramConfigSpec& other) + { + axes.insert(axes.end(), other.axes.begin(), other.axes.end()); } - HistogramConfigSpec(HistogramConfigSpec const& other) = default; - HistogramConfigSpec(HistogramConfigSpec&& other) = default; - HistogramType type; - std::vector<AxisSpec> axes; - bool binsEqual; + HistType type{HistType::kUndefinedHist}; + std::vector<AxisSpec> axes{}; }; -/// Data structure containing histogram specification for the HistogramRegistry -/// Contains hashed name as id for fast lookup +//************************************************************************************************** +/** + * Specification of a histogram. + */ +//************************************************************************************************** struct HistogramSpec { - HistogramSpec(char const* const name_, char const* const readableName_, HistogramConfigSpec config_) + HistogramSpec(char const* const name_, char const* const title_, HistogramConfigSpec config_, bool callSumw2_ = false) : name(name_), - readableName(readableName_), id(compile_time_hash(name_)), - config(config_) + title(title_), + config(config_), + callSumw2(callSumw2_) { } HistogramSpec() : name(""), - readableName(""), id(0), config() { @@ -120,191 +179,265 @@ struct HistogramSpec { HistogramSpec(HistogramSpec const& other) = default; HistogramSpec(HistogramSpec&& other) = default; - std::string name; - std::string readableName; - uint32_t id; - HistogramConfigSpec config; + std::string name{}; + uint32_t id{}; + std::string title{}; + HistogramConfigSpec config{}; + bool callSumw2{}; // wether or not hist needs heavy error structure produced by Sumw2() }; -template <typename T> -std::unique_ptr<TH1> createTH1FromSpec(HistogramSpec const& spec) -{ - if (spec.config.axes.size() == 0) { - throw runtime_error("No arguments available in spec to create a histogram"); - } - if (spec.config.binsEqual) { - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1]); - } - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data()); -} +//************************************************************************************************** +/** + * Static helper class to generate histograms from the specifications. + * Also provides functions to obtain pointer to the created histogram casted to the correct alternative of the std::variant HistPtr that is used in HistogramRegistry. + */ +//************************************************************************************************** +struct HistFactory { + + // create histogram of type T with the axes defined in HistogramConfigSpec + template <typename T> + static std::shared_ptr<T> createHist(const HistogramSpec& histSpec) + { + constexpr std::size_t MAX_DIM{10}; + const std::size_t nAxes{histSpec.config.axes.size()}; + if (nAxes == 0 || nAxes > MAX_DIM) { + LOGF(FATAL, "The histogram specification contains no (or too many) axes."); + return nullptr; + } -template <typename T> -std::unique_ptr<TH2> createTH2FromSpec(HistogramSpec const& spec) -{ - if (spec.config.axes.size() == 0) { - throw runtime_error("No arguments available in spec to create a histogram"); - } - if (spec.config.binsEqual) { - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1]); - } - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data()); -} + int nBins[MAX_DIM]{0}; + double lowerBounds[MAX_DIM]{0.}; + double upperBounds[MAX_DIM]{0.}; -template <typename T> -std::unique_ptr<TH3> createTH3FromSpec(HistogramSpec const& spec) -{ - if (spec.config.axes.size() == 0) { - throw runtime_error("No arguments available in spec to create a histogram"); - } - if (spec.config.binsEqual) { - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins[0], spec.config.axes[0].bins[1], spec.config.axes[1].nBins, spec.config.axes[1].bins[0], spec.config.axes[1].bins[1], spec.config.axes[2].nBins, spec.config.axes[2].bins[0], spec.config.axes[2].bins[1]); - } - return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data(), spec.config.axes[2].nBins, spec.config.axes[2].bins.data()); -} + // first figure out number of bins and dimensions + for (std::size_t i = 0; i < nAxes; i++) { + nBins[i] = (histSpec.config.axes[i].nBins) ? *histSpec.config.axes[i].nBins : histSpec.config.axes[i].binEdges.size() - 1; + lowerBounds[i] = histSpec.config.axes[i].binEdges.front(); + upperBounds[i] = histSpec.config.axes[i].binEdges.back(); + } -/// Helper functions to fill histograms with expressions -template <typename C1, typename C2, typename C3, typename T> -void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter) -{ - auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; - for (auto& t : filtered) { - hist->Fill(*(static_cast<C1>(t).getIterator()), *(static_cast<C2>(t).getIterator()), *(static_cast<C3>(t).getIterator())); - } -} + // create histogram + std::shared_ptr<T> hist{generateHist<T>(histSpec.name, histSpec.title, nAxes, nBins, lowerBounds, upperBounds)}; + if (!hist) { + LOGF(FATAL, "The number of specified dimensions does not match the type."); + return nullptr; + } -template <typename C1, typename C2, typename T> -void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter) -{ - auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; - for (auto& t : filtered) { - hist->Fill(*(static_cast<C1>(t).getIterator()), *(static_cast<C2>(t).getIterator())); - } -} + // set axis properties + for (std::size_t i = 0; i < nAxes; i++) { + TAxis* axis{getAxis(i, hist)}; + if (axis) { + axis->SetTitle(histSpec.config.axes[i].title.data()); + + // this helps to have axes not only called 0,1,2... in ndim histos + if constexpr (std::is_base_of_v<THnBase, T>) { + if (histSpec.config.axes[i].name) + axis->SetName((std::string(axis->GetName()) + "-" + *histSpec.config.axes[i].name).data()); + } + + // move the bin edges in case a variable binning was requested + if (!histSpec.config.axes[i].nBins) { + if (!std::is_sorted(std::begin(histSpec.config.axes[i].binEdges), std::end(histSpec.config.axes[i].binEdges))) { + LOGF(FATAL, "The bin edges specified for axis %s in histogram %s are not in increasing order!", (histSpec.config.axes[i].name) ? *histSpec.config.axes[i].name : histSpec.config.axes[i].title, histSpec.name); + return nullptr; + } + axis->Set(nBins[i], histSpec.config.axes[i].binEdges.data()); + } + } + } + if (histSpec.callSumw2) + hist->Sumw2(); -template <typename C, typename T> -void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter) -{ - auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; - for (auto& t : filtered) { - hist->Fill(*(static_cast<C>(t).getIterator())); + return hist; } -} -using HistogramCreationCallback = std::function<std::unique_ptr<TH1>(HistogramSpec const& spec)>; - -// Wrapper to avoid multiple function definitinions error -struct HistogramCallbacks { - static HistogramCreationCallback createTH1D() + // create histogram and return it casted to the correct alternative held in HistPtr variant + template <typename T> + static HistPtr createHistVariant(HistogramSpec const& histSpec) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH1FromSpec<TH1D>(spec); - }; + if (auto hist = castToVariant(createHist<T>(histSpec))) + return *hist; + else + throw runtime_error("Histogram was not created properly."); } - static HistogramCreationCallback createTH1F() + // runtime version of the above + static HistPtr createHistVariant(HistogramSpec const& histSpec) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH1FromSpec<TH1F>(spec); - }; + if (histSpec.config.type == HistType::kUndefinedHist) + throw runtime_error("Histogram type was not specified."); + else + return HistogramCreationCallbacks.at(histSpec.config.type)(histSpec); } - static HistogramCreationCallback createTH1I() + private: + static const std::map<HistType, std::function<HistPtr(const HistogramSpec&)>> HistogramCreationCallbacks; + + // helper function to generate the actual histograms + template <typename T> + static T* generateHist(const std::string& name, const std::string& title, const std::size_t nDim, + const int nBins[], const double lowerBounds[], const double upperBounds[]) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH1FromSpec<TH1I>(spec); - }; + if constexpr (std::is_base_of_v<THnBase, T>) { + return new T(name.data(), title.data(), nDim, nBins, lowerBounds, upperBounds); + } else if constexpr (std::is_base_of_v<TH3, T>) { + return (nDim != 3) ? nullptr + : new 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<TH2, T>) { + return (nDim != 2) ? nullptr + : new 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<TH1, T>) { + return (nDim != 1) + ? nullptr + : new T(name.data(), title.data(), nBins[0], lowerBounds[0], upperBounds[0]); + } + return nullptr; } - static HistogramCreationCallback createTH2D() + // helper function to get the axis via index for any type of root histogram + template <typename T> + static TAxis* getAxis(const int i, std::shared_ptr<T>& hist) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH2FromSpec<TH2D>(spec); - }; + if constexpr (std::is_base_of_v<THnBase, T>) { + return hist->GetAxis(i); + } else { + return (i == 0) ? hist->GetXaxis() + : (i == 1) ? hist->GetYaxis() : (i == 2) ? hist->GetZaxis() : nullptr; + } } - static HistogramCreationCallback createTH2F() + // helper function to cast the actual histogram type (e.g. TH2F) to the correct interface type (e.g. TH2) that is stored in the HistPtr variant + template <typename T> + static std::optional<HistPtr> castToVariant(std::shared_ptr<TObject> obj) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH2FromSpec<TH2F>(spec); - }; + if (obj->InheritsFrom(T::Class())) { + return std::static_pointer_cast<T>(obj); + } + return std::nullopt; } - - static HistogramCreationCallback createTH2I() + template <typename T, typename Next, typename... Rest> + static std::optional<HistPtr> castToVariant(std::shared_ptr<TObject> obj) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH2FromSpec<TH2I>(spec); - }; + if (auto hist = castToVariant<T>(obj)) { + return hist; + } + return castToVariant<Next, Rest...>(obj); } - - static HistogramCreationCallback createTH3D() + static std::optional<HistPtr> castToVariant(std::shared_ptr<TObject> obj) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH3FromSpec<TH3D>(spec); - }; + if (obj) { + // TProfile3D is TH3, TProfile2D is TH2, TH3 is TH1, TH2 is TH1, TProfile is TH1 + return castToVariant<THn, THnSparse, TProfile3D, TH3, TProfile2D, TH2, TProfile, TH1>(obj); + } + return std::nullopt; } +}; - static HistogramCreationCallback createTH3F() +//************************************************************************************************** +/** + * Static helper class to fill existing root histograms of any type. + * Contains functionality to fill once per call or a whole (filtered) table at once. + */ +//************************************************************************************************** +struct HistFiller { + // fill any type of histogram (if weight was requested it must be the last argument) + template <bool useWeight = false, typename T, typename... Ts> + static void fillHistAny(std::shared_ptr<T>& hist, const Ts&... positionAndWeight) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH3FromSpec<TH3F>(spec); - }; + constexpr int nDim = sizeof...(Ts) - useWeight; + + constexpr bool validTH3 = (std::is_same_v<TH3, T> && nDim == 3); + constexpr bool validTH2 = (std::is_same_v<TH2, T> && nDim == 2); + constexpr bool validTH1 = (std::is_same_v<TH1, T> && nDim == 1); + constexpr bool validTProfile3D = (std::is_same_v<TProfile3D, T> && nDim == 4); + constexpr bool validTProfile2D = (std::is_same_v<TProfile2D, T> && nDim == 3); + constexpr bool validTProfile = (std::is_same_v<TProfile, T> && nDim == 2); + + constexpr bool validSimpleFill = validTH1 || validTH2 || validTH3 || validTProfile || validTProfile2D || validTProfile3D; + // unfortunately we dont know at compile the dimension of THn(Sparse) + constexpr bool validComplexFill = std::is_base_of_v<THnBase, T>; + + if constexpr (validSimpleFill) { + hist->Fill(static_cast<double>(positionAndWeight)...); + } else if constexpr (validComplexFill) { + // savety check for n dimensional histograms (runtime overhead) + if (hist->GetNdimensions() != nDim) + throw runtime_error("The number of position (and weight) arguments does not match the histogram dimensions!"); + + double tempArray[sizeof...(Ts)] = {static_cast<double>(positionAndWeight)...}; + if constexpr (useWeight) + hist->Fill(tempArray, tempArray[sizeof...(Ts) - 1]); + else + hist->Fill(tempArray); + } else { + throw runtime_error("The number of position (and weight) arguments does not match the histogram dimensions!"); + } } - static HistogramCreationCallback createTH3I() + // fill any type of histogram with columns (Cs) of a filtered table (if weight is requested it must reside the last specified column) + template <bool useWeight = false, typename... Cs, typename R, typename T> + static void fillHistAnyTable(std::shared_ptr<R>& hist, const T& table, const o2::framework::expressions::Filter& filter) { - return [](HistogramSpec const& spec) -> std::unique_ptr<TH1> { - return createTH3FromSpec<TH3I>(spec); - }; + auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; + for (auto& t : filtered) { + fillHistAny<useWeight>(hist, (*(static_cast<Cs>(t).getIterator()))...); + } } }; -/// Histogram registry for an analysis task that allows to define needed histograms -/// and serves as the container/wrapper to fill them +//************************************************************************************************** +/** + * Histogram registry that can be used to store and fill histograms of any type. + */ +//************************************************************************************************** class HistogramRegistry { public: - HistogramRegistry(char const* const name_, bool enable, std::vector<HistogramSpec> specs, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) - : name(name_), - policy(policy_), - enabled(enable), - mRegistryKey(), - mRegistryValue(), - mHistogramCreationCallbacks({HistogramCallbacks::createTH1D(), - HistogramCallbacks::createTH1F(), - HistogramCallbacks::createTH1I(), - HistogramCallbacks::createTH2D(), - HistogramCallbacks::createTH2F(), - HistogramCallbacks::createTH2I(), - HistogramCallbacks::createTH3D(), - HistogramCallbacks::createTH3F(), - HistogramCallbacks::createTH3I()}) + HistogramRegistry(char const* const name_, bool enable, std::vector<HistogramSpec> histSpecs_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) : name(name_), + policy(policy_), + enabled(enable), + mRegistryKey(), + mRegistryValue() { mRegistryKey.fill(0u); - for (auto& spec : specs) { - insert(spec); + for (auto& histSpec : histSpecs_) { + insert(histSpec); } } + void add(HistogramSpec&& histSpec_) + { + insert(histSpec_); + } + + // gets the underlying histogram pointer + // we cannot automatically infer type here so it has to be explicitly specified + // -> get<TH1>(), get<TH2>(), get<TH3>(), get<THn>(), get<THnSparse>(), get<TProfile>(), get<TProfile2D>(), get<TProfile3D>() /// @return the histogram registered with name @a name - auto& get(char const* const name) const + template <typename T> + auto& get(char const* const name) { const uint32_t id = compile_time_hash(name); const uint32_t i = imask(id); if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { - return mRegistryValue[i]; + return *std::get_if<std::shared_ptr<T>>(&mRegistryValue[i]); } for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { if (id == mRegistryKey[imask(j + i)]) { - return mRegistryValue[imask(j + i)]; + return *std::get_if<std::shared_ptr<T>>(&mRegistryValue[imask(j + i)]); } } - throw runtime_error("No match found!"); + throw runtime_error("No matching histogram found in HistogramRegistry!"); } /// @return the histogram registered with name @a name - auto& operator()(char const* const name) const + template <typename T> + auto& operator()(char const* const name) { - return get(name); + return get<T>(name); } /// @return the associated OutputSpec @@ -324,79 +457,114 @@ class HistogramRegistry taskHash = hash; } + // TODO: maybe support also TDirectory,TList,TObjArray?, find a way to write to file in 'single key' mode (arg in WriteObjAny) TFolder* operator*() { TFolder* folder = new TFolder(this->name.c_str(), this->name.c_str()); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { - if (mRegistryValue[j].get() != nullptr) { - auto hist = mRegistryValue[j].get(); - folder->Add(hist); + TObject* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[j]); + if (rawPtr) { + folder->Add(rawPtr); } } - folder->SetOwner(); + folder->SetOwner(false); // object deletion will be handled by shared_ptrs return folder; } - /// fill the histogram with an expression - template <typename C1, typename C2, typename C3, typename T> - void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + // fill hist with values + template <bool useWeight = false, typename... Ts> + void fill(char const* const name, Ts&&... positionAndWeight) { - TH1* hist = get(name).get(); - framework::fill<C1, C2, C3>(hist, table, filter); + const uint32_t id = compile_time_hash(name); + const uint32_t i = imask(id); + if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { + std::visit([this, &positionAndWeight...](auto&& hist) { HistFiller::fillHistAny<useWeight>(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[i]); + return; + } + for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { + if (id == mRegistryKey[imask(j + i)]) { + std::visit([this, &positionAndWeight...](auto&& hist) { HistFiller::fillHistAny<useWeight>(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[imask(j + i)]); + return; + } + } + throw runtime_error("No matching histogram found in HistogramRegistry!"); } - template <typename C1, typename C2, typename T> - void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + template <typename... Ts> + void fillWeight(char const* const name, Ts&&... positionAndWeight) { - TH1* hist = get(name).get(); - framework::fill<C1, C2>(hist, table, filter); + fill<true>(name, std::forward<Ts>(positionAndWeight)...); } - template <typename C, typename T> + // fill hist with content of (filtered) table columns + template <typename... Cs, typename T> void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) { - TH1* hist = get(name).get(); - framework::fill<C>(hist, table, filter); + fillTable<false, Cs...>(name, table, filter); + } + template <typename... Cs, typename T> + void fillWeight(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + { + fillTable<true, Cs...>(name, table, filter); + } + + // this is for internal use only because we dont want user to have to specify 'useWeight' argument + template <bool useWeight = false, typename... Cs, typename T> + void fillTable(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + { + const uint32_t id = compile_time_hash(name); + const uint32_t i = imask(id); + if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { + std::visit([this, &table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<useWeight, Cs...>(hist, table, filter); }, mRegistryValue[i]); + return; + } + for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { + if (id == mRegistryKey[imask(j + i)]) { + std::visit([this, &table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<useWeight, Cs...>(hist, table, filter); }, mRegistryValue[imask(j + i)]); + return; + } + } + throw runtime_error("No matching histogram found in HistogramRegistry!"); } /// lookup distance counter for benchmarking mutable uint32_t lookup = 0; private: - void insert(HistogramSpec& spec) + void insert(HistogramSpec& histSpec) { - uint32_t i = imask(spec.id); + uint32_t i = imask(histSpec.id); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { - if (mRegistryValue[imask(j + i)].get() == nullptr) { - mRegistryKey[imask(j + i)] = spec.id; - mRegistryValue[imask(j + i)] = mHistogramCreationCallbacks[spec.config.type](spec); + TObject* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); + if (!rawPtr) { + mRegistryKey[imask(j + i)] = histSpec.id; + mRegistryValue[imask(j + i)] = HistFactory::createHistVariant(histSpec); lookup += j; return; } } - throw runtime_error("Internal array is full."); + throw runtime_error("Internal array of HistogramRegistry is full."); } inline constexpr uint32_t imask(uint32_t i) const { return i & mask; } - std::string name; - bool enabled; - OutputObjHandlingPolicy policy; - uint32_t taskHash; + + std::string name{}; + bool enabled{}; + OutputObjHandlingPolicy policy{}; + uint32_t taskHash{}; /// The maximum number of histograms in buffer is currently set to 512 /// which seems to be both reasonably large and allowing for very fast lookup static constexpr uint32_t mask = 0x1FF; static constexpr uint32_t MAX_REGISTRY_SIZE = mask + 1; - std::array<uint32_t, MAX_REGISTRY_SIZE> mRegistryKey; - std::array<std::unique_ptr<TH1>, MAX_REGISTRY_SIZE> mRegistryValue; - std::vector<HistogramCreationCallback> mHistogramCreationCallbacks; + std::array<uint32_t, MAX_REGISTRY_SIZE> mRegistryKey{}; + std::array<HistPtr, MAX_REGISTRY_SIZE> mRegistryValue{}; }; -} // namespace framework - -} // namespace o2 - +} // namespace o2::framework #endif // FRAMEWORK_HISTOGRAMREGISTRY_H_ diff --git a/Framework/Core/src/HistogramRegistry.cxx b/Framework/Core/src/HistogramRegistry.cxx new file mode 100644 index 0000000000000..ef336c52ce208 --- /dev/null +++ b/Framework/Core/src/HistogramRegistry.cxx @@ -0,0 +1,37 @@ +// 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/HistogramRegistry.h" + +namespace o2::framework +{ + +// define histogram callbacks for runtime histogram creation +#define CALLB(HType) \ + { \ + k##HType, \ + [](HistogramSpec const& histSpec) { \ + return HistFactory::createHistVariant<HType>(histSpec); \ + } \ + } + +const std::map<HistType, std::function<HistPtr(const HistogramSpec&)>> HistFactory::HistogramCreationCallbacks{ + CALLB(TH1D), CALLB(TH1F), CALLB(TH1I), CALLB(TH1C), CALLB(TH1S), + CALLB(TH2D), CALLB(TH2F), CALLB(TH2I), CALLB(TH2C), CALLB(TH2S), + CALLB(TH3D), CALLB(TH3F), CALLB(TH3I), CALLB(TH3C), CALLB(TH3S), + CALLB(THnD), CALLB(THnF), CALLB(THnI), CALLB(THnC), CALLB(THnS), CALLB(THnL), + CALLB(THnSparseD), CALLB(THnSparseF), CALLB(THnSparseI), CALLB(THnSparseC), CALLB(THnSparseS), CALLB(THnSparseL), + CALLB(TProfile), CALLB(TProfile2D), CALLB(TProfile3D), + //CALLB(StepTHnF), CALLB(StepTHnD) +}; + +#undef CALLB + +} // namespace o2::framework diff --git a/Framework/Core/test/benchmark_HistogramRegistry.cxx b/Framework/Core/test/benchmark_HistogramRegistry.cxx index f91436dcc4cdd..05c4d17047ec8 100644 --- a/Framework/Core/test/benchmark_HistogramRegistry.cxx +++ b/Framework/Core/test/benchmark_HistogramRegistry.cxx @@ -28,15 +28,15 @@ static void BM_HashedNameLookup(benchmark::State& state) { for (auto _ : state) { state.PauseTiming(); - std::vector<HistogramSpec> specs; + std::vector<HistogramSpec> histSpecs; for (auto i = 0; i < state.range(0); ++i) { - specs.push_back({fmt::format("histo{}", i + 1).c_str(), fmt::format("Histo {}", i + 1).c_str(), {HistogramType::kTH1F, {{100, 0, 1}}}}); + histSpecs.push_back({fmt::format("histo{}", i + 1).c_str(), fmt::format("Histo {}", i + 1).c_str(), {HistType::kTH1F, {{100, 0, 1}}}}); } - HistogramRegistry registry{"registry", true, specs}; + HistogramRegistry registry{"registry", true, histSpecs}; state.ResumeTiming(); for (auto i = 0; i < nLookups; ++i) { - auto& x = registry.get("histo4"); + auto& x = registry.get<TH1>("histo4"); benchmark::DoNotOptimize(x); } state.counters["Average lookup distance"] = ((double)registry.lookup / (double)(state.range(0))); diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 0ecb7c367f16f..59227a8ba0388 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -25,7 +25,7 @@ DECLARE_SOA_COLUMN_FULL(Y, y, float, "y"); HistogramRegistry foo() { - return {"r", true, {{"histo", "histo", {HistogramType::kTH1F, {{100, 0, 1}}}}}}; + return {"r", true, {{"histo", "histo", {HistType::kTH1F, {{100, 0, 1}}}}}}; } BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) @@ -33,27 +33,27 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) /// Construct a registry object with direct declaration HistogramRegistry registry{ "registry", true, { - {"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, // - {"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, // - {"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, // - {"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // - } // + {"eta", "#Eta", {HistType::kTH1F, {{100, -2.0, 2.0}}}}, // + {"phi", "#Phi", {HistType::kTH1D, {{102, 0, 2 * M_PI}}}}, // + {"pt", "p_{T}", {HistType::kTH1D, {{1002, -0.01, 50.1}}}}, // + {"ptToPt", "#ptToPt", {HistType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // + } // }; /// Get histograms by name - BOOST_REQUIRE_EQUAL(registry.get("eta")->GetNbinsX(), 100); - BOOST_REQUIRE_EQUAL(registry.get("phi")->GetNbinsX(), 102); - BOOST_REQUIRE_EQUAL(registry.get("pt")->GetNbinsX(), 1002); - BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsX(), 100); - BOOST_REQUIRE_EQUAL(registry.get("ptToPt")->GetNbinsY(), 100); + BOOST_REQUIRE_EQUAL(registry.get<TH1>("eta")->GetNbinsX(), 100); + BOOST_REQUIRE_EQUAL(registry.get<TH1>("phi")->GetNbinsX(), 102); + BOOST_REQUIRE_EQUAL(registry.get<TH1>("pt")->GetNbinsX(), 1002); + BOOST_REQUIRE_EQUAL(registry.get<TH2>("ptToPt")->GetNbinsX(), 100); + BOOST_REQUIRE_EQUAL(registry.get<TH2>("ptToPt")->GetNbinsY(), 100); /// Get a pointer to the histogram - auto histo = registry.get("pt").get(); + auto histo = registry.get<TH1>("pt").get(); BOOST_REQUIRE_EQUAL(histo->GetNbinsX(), 1002); /// Get registry object from a function auto r = foo(); - auto histo2 = r.get("histo").get(); + auto histo2 = r.get<TH1>("histo").get(); BOOST_REQUIRE_EQUAL(histo2->GetNbinsX(), 100); } @@ -78,16 +78,16 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryExpressionFill) /// Construct a registry object with direct declaration HistogramRegistry registry{ "registry", true, { - {"x", "test x", {HistogramType::kTH1F, {{100, 0.0f, 10.0f}}}}, // - {"xy", "test xy", {HistogramType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}} // - } // + {"x", "test x", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, // + {"xy", "test xy", {HistType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}} // + } // }; /// Fill histogram with expression and table registry.fill<test::X>("x", tests, test::x > 3.0f); - BOOST_CHECK_EQUAL(registry.get("x")->GetEntries(), 4); + BOOST_CHECK_EQUAL(registry.get<TH1>("x")->GetEntries(), 4); /// Fill histogram with expression and table registry.fill<test::X, test::Y>("xy", tests, test::x > 3.0f && test::y > -5.0f); - BOOST_CHECK_EQUAL(registry.get("xy")->GetEntries(), 2); + BOOST_CHECK_EQUAL(registry.get<TH2>("xy")->GetEntries(), 2); } From a36e009696f2295cd33a6484d0783f4e875be642 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Sat, 17 Oct 2020 15:04:21 +0200 Subject: [PATCH 0975/1751] fix for alien connection (will be updated by new reader) (#4620) --- Framework/Core/src/DataInputDirector.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 2713b0e61c5c8..7995cf82fe19f 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -30,6 +30,13 @@ FileNameHolder* makeFileNameHolder(std::string fileName) auto fileNameHolder = new FileNameHolder(); fileNameHolder->fileName = fileName; + if (fileName.rfind("alien://", 0) == 0) { + if (gGrid == nullptr || gGrid->IsConnected() == false) { + LOG(debug) << "AliEn file requested. Enabling support."; + TGrid::Connect("alien://"); + } + } + TFile* file = TFile::Open(fileName.c_str(), "R"); if (!file || !file->IsOpen()) { LOGP(ERROR, "\"{}\" can not be opened.", fileName); From e7e0ce5dbe05a0c1484ba1ea23db2afbf58ddb68 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 18 Oct 2020 13:08:14 +0200 Subject: [PATCH 0976/1751] DPL: introduce metric observer callback (#4622) Each service can now observe metric processing in the Driver. --- Framework/Core/include/Framework/ServiceSpec.h | 6 ++++++ Framework/Core/src/CommonMessageBackends.cxx | 4 ++++ Framework/Core/src/CommonServices.cxx | 13 +++++++++++++ Framework/Core/src/runDataProcessing.cxx | 16 +++++++++++++++- 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index 14b323c622433..6e1e420a7da25 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -63,6 +63,9 @@ using ServicePostForkChild = std::function<void(ServiceRegistry&)>; /// but before doing exec / starting the device. using ServicePostForkParent = std::function<void(ServiceRegistry&)>; +/// Callback executed in the driver in order to process a metric. +using ServiceMetricHandling = std::function<void(ServiceRegistry&)>; + /// A specification for a Service. /// A Service is a utility class which does not perform /// data processing itself, but it can be used by the data processor @@ -99,6 +102,9 @@ struct ServiceSpec { /// but before doing exec / starting the device. ServicePostForkParent postForkParent = nullptr; + ///Callback executed after each metric is received by the driver. + ServiceMetricHandling metricHandling = nullptr; + /// Kind of service being specified. ServiceKind kind; }; diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index 1b2126c7ff125..100fd8397b6e5 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -90,6 +90,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -127,6 +128,7 @@ o2::framework::ServiceSpec CommonMessageBackends::fairMQBackendSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -144,6 +146,7 @@ o2::framework::ServiceSpec CommonMessageBackends::stringBackendSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -161,6 +164,7 @@ o2::framework::ServiceSpec CommonMessageBackends::rawBufferBackendSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 741f0874036d3..ecea272d900ed 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -70,6 +70,7 @@ o2::framework::ServiceSpec CommonServices::monitoringSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -87,6 +88,7 @@ o2::framework::ServiceSpec CommonServices::infologgerContextSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -172,6 +174,7 @@ o2::framework::ServiceSpec CommonServices::infologgerSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -197,6 +200,7 @@ o2::framework::ServiceSpec CommonServices::configurationSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Global}; } @@ -218,6 +222,7 @@ o2::framework::ServiceSpec CommonServices::controlSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -236,6 +241,7 @@ o2::framework::ServiceSpec CommonServices::rootFileSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -258,6 +264,7 @@ o2::framework::ServiceSpec CommonServices::parallelSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -276,6 +283,7 @@ o2::framework::ServiceSpec CommonServices::timesliceIndex() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -294,6 +302,7 @@ o2::framework::ServiceSpec CommonServices::callbacksSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -319,6 +328,7 @@ o2::framework::ServiceSpec CommonServices::dataRelayer() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -349,6 +359,7 @@ o2::framework::ServiceSpec CommonServices::tracingSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -382,6 +393,7 @@ o2::framework::ServiceSpec CommonServices::threadPool(int numWorkers) setenv("UV_THREADPOOL_SIZE", numWorkersS.c_str(), 0); }, nullptr, + nullptr, ServiceKind::Serial}; } @@ -481,6 +493,7 @@ o2::framework::ServiceSpec CommonServices::dataProcessingStats() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index b19aa1815d255..37eedf985070b 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -883,6 +883,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, // We initialise this in the driver, because different drivers might have // different versions of the service ServiceRegistry serviceRegistry; + std::vector<ServiceMetricHandling> metricProcessingCallbacks; while (true) { // If control forced some transition on us, we push it to the queue. @@ -986,7 +987,14 @@ int runStateMachine(DataProcessorSpecs const& workflow, driverInfo.uniqueWorkflowId, !varmap["no-IPC"].as<bool>(), driverInfo.resourcesMonitoringInterval); - + metricProcessingCallbacks.clear(); + for (auto& device : deviceSpecs) { + for (auto& service : device.services) { + if (service.metricHandling) { + metricProcessingCallbacks.push_back(service.metricHandling); + } + } + } // This should expand nodes so that we can build a consistent DAG. } catch (std::runtime_error& e) { std::cerr << "Invalid workflow: " << e.what() << std::endl; @@ -1114,6 +1122,9 @@ int runStateMachine(DataProcessorSpecs const& workflow, uint64_t inputProcessingStart = uv_hrtime(); auto inputProcessingLatency = inputProcessingStart - inputProcessingLast; processChildrenOutput(driverInfo, infos, deviceSpecs, controls, metricsInfos); + for (auto& callback : metricProcessingCallbacks) { + callback(serviceRegistry); + } auto inputProcessingEnd = uv_hrtime(); driverInfo.inputProcessingCost = (inputProcessingEnd - inputProcessingStart) / 1000000; driverInfo.inputProcessingLatency = (inputProcessingLatency) / 1000000; @@ -1152,6 +1163,9 @@ int runStateMachine(DataProcessorSpecs const& workflow, sigchld_requested = false; driverInfo.sigchldRequested = false; processChildrenOutput(driverInfo, infos, deviceSpecs, controls, metricsInfos); + for (auto& callback : metricProcessingCallbacks) { + callback(serviceRegistry); + } hasError = processSigChild(infos); if (areAllChildrenGone(infos) == true && (guiQuitRequested || (checkIfCanExit(infos) == true) || graceful_exit)) { From 077efcb778e27a0ffbd79975fcd6f6c0834f43b6 Mon Sep 17 00:00:00 2001 From: Matteo Concas <mconcas@cern.ch> Date: Sun, 18 Oct 2020 16:06:45 +0200 Subject: [PATCH 0977/1751] [ALICE-3] Update barrel geometry definition (#4502) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update definition of Layers, length is automatically computed requiring |η| < 1.44. Thanks @preghenella for the hints. --- .../PostLS4/IT4/simulation/src/Detector.cxx | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx index 68ae078f94f37..909259e2459a8 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx @@ -53,6 +53,11 @@ using o2::itsmft::Hit; using Segmentation = o2::itsmft::SegmentationAlpide; using namespace o2::its4; +float getDetLengthFromEta(const float eta, const float radius) +{ + return 2. * (10. + radius * std::cos(2 * std::atan(std::exp(-eta)))); +} + Detector::Detector() : o2::base::DetImpl<Detector>("IT4", kTRUE), mTrackData(), @@ -140,24 +145,24 @@ void Detector::configITS(Detector* its) // From Mario Sitta's hack std::vector<std::array<double, 2>> tdr5data; - tdr5data.emplace_back(std::array<double, 2>{1.8f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{2.4f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{3.0f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{4.0f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{5.0f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{6.0f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{7.0f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{8.0f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{9.0f, 27.15}); - tdr5data.emplace_back(std::array<double, 2>{10.0f, 27.15}); - - static constexpr float SensorLayerThickness = 30.e-4; + tdr5data.emplace_back(std::array<double, 2>{1.8f, getDetLengthFromEta(1.44f, 1.8f)}); + tdr5data.emplace_back(std::array<double, 2>{2.8f, getDetLengthFromEta(1.44f, 2.8f)}); + tdr5data.emplace_back(std::array<double, 2>{3.8f, getDetLengthFromEta(1.44f, 3.8f)}); + tdr5data.emplace_back(std::array<double, 2>{8.0f, getDetLengthFromEta(1.44f, 8.0f)}); + tdr5data.emplace_back(std::array<double, 2>{20.0f, getDetLengthFromEta(1.44f, 20.0f)}); + tdr5data.emplace_back(std::array<double, 2>{25.0f, getDetLengthFromEta(1.44f, 25.0f)}); + tdr5data.emplace_back(std::array<double, 2>{40.0f, getDetLengthFromEta(1.44f, 40.0f)}); + tdr5data.emplace_back(std::array<double, 2>{55.f, getDetLengthFromEta(1.44f, 55.f)}); + tdr5data.emplace_back(std::array<double, 2>{80.0f, getDetLengthFromEta(1.44f, 80.0f)}); + tdr5data.emplace_back(std::array<double, 2>{100.f, getDetLengthFromEta(1.44f, 100.f)}); + + std::array<float, 10> sensorThicknesses = {50.e-4, 50.e-4, 50.e-4, 50.e-3, 50.e-3, 50.e-3, 50.e-3, 50.e-3, 50.e-3, 50.e-3}; its->setStaveModelOB(o2::its4::Detector::kOBModel2); // its->createOuterBarrel(false); auto idLayer{0}; for (auto& layerData : tdr5data) { - its->defineInnerLayerITS4(idLayer, layerData[0], layerData[1], SensorLayerThickness, 0, 0); + its->defineInnerLayerITS4(idLayer, layerData[0], layerData[1], sensorThicknesses[idLayer], 0, 0); ++idLayer; } its->createOuterBarrel(false); From 33097b7a336f2141c24a17b746fc9972b16ade6a Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Sun, 18 Oct 2020 19:00:21 +0200 Subject: [PATCH 0978/1751] TrackQA: use HistogramRegistry (#4623) - put more user-friendly add() functions in registry - made axis title std::optional (-> axis titles contained in semicolon separated title-string that can be put in root histogram constructors will not be overridden by empty string anymore) - add throw exception if user specifies wrong histogram type in get<>() - use HistogramRegistry in trackqa task --- Analysis/Tasks/trackqa.cxx | 150 +++++++----------- .../include/Framework/HistogramRegistry.h | 53 ++++--- 2 files changed, 92 insertions(+), 111 deletions(-) diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 63431b6280f66..438ec2399123c 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -15,7 +15,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Analysis/MC.h" -#include "Analysis/HistHelpers.h" +#include "Framework/HistogramRegistry.h" #include <cmath> @@ -24,7 +24,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::experimental::histhelpers; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { @@ -41,45 +40,14 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) //**************************************************************************************** struct TrackQATask { - enum HistosKine : uint8_t { - pt, - eta, - phi, - }; - enum HistosTrackPar : uint8_t { - x, - y, - z, - alpha, - signed1Pt, - snp, - tgl, - dcaXY, - dcaZ, - flags, - }; - enum HistosITS : uint8_t { - itsNCls, - itsChi2NCl, - itsHits, - }; - enum HistosTPC : uint8_t { - tpcNClsFindable, - tpcNClsFound, - tpcNClsShared, - tpcNClsCrossedRows, - tpcCrossedRowsOverFindableCls, - tpcFractionSharedCls, - tpcChi2NCl, - }; + HistogramRegistry kine{"Kine", true, {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry trackpar{"TrackPar", true, {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry its{"ITS", true, {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry tpc{"TPC", true, {}, OutputObjHandlingPolicy::QAObject}; - OutputObj<HistFolder> kine{HistFolder("Kine"), OutputObjHandlingPolicy::QAObject}; - OutputObj<HistFolder> trackpar{HistFolder("TrackPar"), OutputObjHandlingPolicy::QAObject}; - OutputObj<HistFolder> its{HistFolder("ITS"), OutputObjHandlingPolicy::QAObject}; - OutputObj<HistFolder> tpc{HistFolder("TPC"), OutputObjHandlingPolicy::QAObject}; - //OutputObj<HistFolder> trd{HistFolder("TRD"), OutputObjHandlingPolicy::QAObject}; - //OutputObj<HistFolder> tof{HistFolder("TOF"), OutputObjHandlingPolicy::QAObject}; - //OutputObj<HistFolder> emcal{HistFolder("EMCAL"), OutputObjHandlingPolicy::QAObject}; + //HistogramRegistry trd{"TRD", true, {}, OutputObjHandlingPolicy::QAObject}; + //HistogramRegistry tof{"TOF", true, {}, OutputObjHandlingPolicy::QAObject}; + //HistogramRegistry emcal{"EMCAL", true, {}, OutputObjHandlingPolicy::QAObject}; Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; @@ -94,76 +62,79 @@ struct TrackQATask { void init(o2::framework::InitContext&) { + std::vector<double> ptBinning = {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}; + // kine histograms - kine->Add<pt>(new TH1D("pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", 200, 0., 5.)); - kine->Add<eta>(new TH1D("eta", "#eta;#eta", 180, -0.9, 0.9)); - kine->Add<phi>(new TH1D("phi", "#phi;#phi [rad]", 180, 0., 2 * M_PI)); + kine.add("pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", kTH1D, {{ptBinning}}); + kine.add("eta", "#eta;#eta", kTH1D, {{180, -0.9, 0.9}}); + kine.add("phi", "#phi;#phi [rad]", kTH1D, {{180, 0., 2 * M_PI}}); // track histograms - trackpar->Add<x>(new TH1D("x", "track #it{x} position at dca in local coordinate system;#it{x} [cm]", 200, -0.36, 0.36)); - trackpar->Add<y>(new TH1D("y", "track #it{y} position at dca in local coordinate system;#it{y} [cm]", 200, -0.5, 0.5)); - trackpar->Add<z>(new TH1D("z", "track #it{z} position at dca in local coordinate system;#it{z} [cm]", 200, -11., 11.)); - trackpar->Add<alpha>(new TH1D("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", 36, -M_PI, M_PI)); - trackpar->Add<signed1Pt>(new TH1D("signed1Pt", "track signed 1/#it{p}_{T};#it{q}/#it{p}_{T}", 200, -8, 8)); - trackpar->Add<snp>(new TH1D("snp", "sinus of track momentum azimuthal angle;snp", 11, -0.1, 0.1)); - trackpar->Add<tgl>(new TH1D("tgl", "tangent of the track momentum dip angle;tgl;", 200, -1., 1.)); - trackpar->Add<flags>(new TH1D("flags", "track flag;flag bit", 64, -0.5, 63.5)); - trackpar->Add<dcaXY>(new TH1D("dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", 200, -0.15, 0.15)); - trackpar->Add<dcaZ>(new TH1D("dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", 200, -0.15, 0.15)); + trackpar.add("x", "track #it{x} position at dca in local coordinate system;#it{x} [cm]", kTH1D, {{200, -0.36, 0.36}}); + trackpar.add("y", "track #it{y} position at dca in local coordinate system;#it{y} [cm]", kTH1D, {{200, -0.5, 0.5}}); + trackpar.add("z", "track #it{z} position at dca in local coordinate system;#it{z} [cm]", kTH1D, {{200, -11., 11.}}); + trackpar.add("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", kTH1D, {{36, -M_PI, M_PI}}); + trackpar.add("signed1Pt", "track signed 1/#it{p}_{T};#it{q}/#it{p}_{T}", kTH1D, {{200, -8, 8}}); + trackpar.add("snp", "sinus of track momentum azimuthal angle;snp", kTH1D, {{11, -0.1, 0.1}}); + trackpar.add("tgl", "tangent of the track momentum dip angle;tgl;", kTH1D, {{200, -1., 1.}}); + trackpar.add("flags", "track flag;flag bit", kTH1D, {{64, -0.5, 63.5}}); + trackpar.add("dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", kTH1D, {{200, -0.15, 0.15}}); + trackpar.add("dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", kTH1D, {{200, -0.15, 0.15}}); // its histograms - its->Add<itsNCls>(new TH1D("itsNCls", "number of found ITS clusters;# clusters ITS", 8, -0.5, 7.5)); - its->Add<itsChi2NCl>(new TH1D("itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40)); - its->Add<itsHits>(new TH1D("itsHits", "hitmap ITS;layer ITS", 7, -0.5, 6.5)); + its.add("itsNCls", "number of found ITS clusters;# clusters ITS", kTH1D, {{8, -0.5, 7.5}}); + its.add("itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", kTH1D, {{100, 0, 40}}); + its.add("itsHits", "hitmap ITS;layer ITS", kTH1D, {{7, -0.5, 6.5}}); // tpc histograms - tpc->Add<tpcNClsFindable>(new TH1D("tpcNClsFindable", "number of findable TPC clusters;# findable clusters TPC", 165, -0.5, 164.5)); - tpc->Add<tpcNClsFound>(new TH1D("tpcNClsFound", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5)); - tpc->Add<tpcNClsShared>(new TH1D("tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", 165, -0.5, 164.5)); - tpc->Add<tpcNClsCrossedRows>(new TH1D("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5)); - tpc->Add<tpcFractionSharedCls>(new TH1D("tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", 100, 0., 1.)); - tpc->Add<tpcCrossedRowsOverFindableCls>(new TH1D("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", 120, 0.0, 1.2)); - tpc->Add<tpcChi2NCl>(new TH1D("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10)); + tpc.add("tpcNClsFindable", "number of findable TPC clusters;# findable clusters TPC", kTH1D, {{165, -0.5, 164.5}}); + tpc.add("tpcNClsFound", "number of found TPC clusters;# clusters TPC", kTH1D, {{165, -0.5, 164.5}}); + tpc.add("tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", kTH1D, {{165, -0.5, 164.5}}); + tpc.add("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", kTH1D, {{165, -0.5, 164.5}}); + tpc.add("tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", kTH1D, {{100, 0., 1.}}); + tpc.add("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {{120, 0.0, 1.2}}); + tpc.add("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {{100, 0, 10}}); } void process(soa::Filtered<soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection>>::iterator const& track) { // fill kinematic variables - kine->Fill<pt>(track.pt()); - kine->Fill<eta>(track.eta()); - kine->Fill<phi>(track.phi()); + kine.fill("pt", track.pt()); + kine.fill("eta", track.eta()); + kine.fill("phi", track.phi()); // fill track parameters - trackpar->Fill<alpha>(track.alpha()); - trackpar->Fill<x>(track.x()); - trackpar->Fill<y>(track.y()); - trackpar->Fill<z>(track.z()); - trackpar->Fill<signed1Pt>(track.signed1Pt()); - trackpar->Fill<snp>(track.snp()); - trackpar->Fill<tgl>(track.tgl()); + trackpar.fill("alpha", track.alpha()); + trackpar.fill("x", track.x()); + trackpar.fill("y", track.y()); + trackpar.fill("z", track.z()); + trackpar.fill("signed1Pt", track.signed1Pt()); + trackpar.fill("snp", track.snp()); + trackpar.fill("tgl", track.tgl()); for (unsigned int i = 0; i < 64; i++) { if (track.flags() & (1 << i)) - trackpar->Fill<flags>(i); + trackpar.fill("flags", i); } - trackpar->Fill<dcaXY>(track.dcaXY()); - trackpar->Fill<dcaZ>(track.dcaZ()); + trackpar.fill("dcaXY", track.dcaXY()); + trackpar.fill("dcaZ", track.dcaZ()); // fill ITS variables - its->Fill<itsNCls>(track.itsNCls()); - its->Fill<itsChi2NCl>(track.itsChi2NCl()); + its.fill("itsNCls", track.itsNCls()); + its.fill("itsChi2NCl", track.itsChi2NCl()); for (unsigned int i = 0; i < 7; i++) { if (track.itsClusterMap() & (1 << i)) - its->Fill<itsHits>(i); + its.fill("itsHits", i); } // fill TPC variables - tpc->Fill<tpcNClsFindable>(track.tpcNClsFindable()); - tpc->Fill<tpcNClsFound>(track.tpcNClsFound()); - tpc->Fill<tpcNClsShared>(track.tpcNClsShared()); - tpc->Fill<tpcNClsCrossedRows>(track.tpcNClsCrossedRows()); - tpc->Fill<tpcCrossedRowsOverFindableCls>(track.tpcCrossedRowsOverFindableCls()); - tpc->Fill<tpcFractionSharedCls>(track.tpcFractionSharedCls()); - tpc->Fill<tpcChi2NCl>(track.tpcChi2NCl()); + tpc.fill("tpcNClsFindable", track.tpcNClsFindable()); + tpc.fill("tpcNClsFound", track.tpcNClsFound()); + tpc.fill("tpcNClsShared", track.tpcNClsShared()); + tpc.fill("tpcNClsCrossedRows", track.tpcNClsCrossedRows()); + tpc.fill("tpcCrossedRowsOverFindableCls", track.tpcCrossedRowsOverFindableCls()); + tpc.fill("tpcFractionSharedCls", track.tpcFractionSharedCls()); + tpc.fill("tpcChi2NCl", track.tpcChi2NCl()); // fill TRD variables @@ -180,12 +151,7 @@ struct TrackQATask { //**************************************************************************************** struct TrackQATaskMC { - OutputObj<HistFolder> resolution{HistFolder("Resolution"), OutputObjHandlingPolicy::QAObject}; - - // unique identifiers for each variable - enum QuantitiesMC : uint8_t { - - }; + HistogramRegistry resolution{"Resolution", true, {}, OutputObjHandlingPolicy::QAObject}; void init(o2::framework::InitContext&){ diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index b40577ccdf04e..24f466e7e2d04 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -22,8 +22,6 @@ #include "Framework/TableBuilder.h" #include "Framework/RuntimeError.h" -#include "TClass.h" - #include <TH1.h> #include <TH2.h> #include <TH3.h> @@ -88,7 +86,7 @@ using HistPtr = std::variant<std::shared_ptr<THn>, std::shared_ptr<THnSparse>, s */ //************************************************************************************************** struct AxisSpec { - AxisSpec(std::vector<double> binEdges_, std::string title_ = "", std::optional<std::string> name_ = std::nullopt) + AxisSpec(std::vector<double> binEdges_, std::optional<std::string> title_ = std::nullopt, std::optional<std::string> name_ = std::nullopt) : nBins(std::nullopt), binEdges(binEdges_), title(title_), @@ -96,7 +94,7 @@ struct AxisSpec { { } - AxisSpec(int nBins_, double binMin_, double binMax_, std::string title_ = "", std::optional<std::string> name_ = std::nullopt) + AxisSpec(int nBins_, double binMin_, double binMax_, std::optional<std::string> title_ = std::nullopt, std::optional<std::string> name_ = std::nullopt) : nBins(nBins_), binEdges({binMin_, binMax_}), title(title_), @@ -106,7 +104,7 @@ struct AxisSpec { std::optional<int> nBins{}; std::vector<double> binEdges{}; - std::string title{}; + std::optional<std::string> title{}; std::optional<std::string> name{}; // optional axis name for ndim histograms }; @@ -130,17 +128,17 @@ struct HistogramConfigSpec { axes.push_back(axis); } - void addAxis(int nBins_, const double binMin_, const double binMax_, const std::string& title_ = "", const std::optional<std::string>& name_ = std::nullopt) + void addAxis(int nBins_, double binMin_, double binMax_, std::optional<std::string> title_ = std::nullopt, std::optional<std::string> name_ = std::nullopt) { axes.push_back({nBins_, binMin_, binMax_, title_, name_}); } - void addAxis(const std::vector<double>& binEdges_, const std::string& title_, const std::string& name_) + void addAxis(std::vector<double> binEdges_, std::optional<std::string> title_ = std::nullopt, std::optional<std::string> name_ = std::nullopt) { axes.push_back({binEdges_, title_, name_}); } - void addAxes(const std::vector<AxisSpec>& axes_) + void addAxes(std::vector<AxisSpec> axes_) { axes.insert(axes.end(), axes_.begin(), axes_.end()); } @@ -194,7 +192,7 @@ struct HistogramSpec { //************************************************************************************************** struct HistFactory { - // create histogram of type T with the axes defined in HistogramConfigSpec + // create histogram of type T with the axes defined in HistogramSpec template <typename T> static std::shared_ptr<T> createHist(const HistogramSpec& histSpec) { @@ -227,7 +225,8 @@ struct HistFactory { for (std::size_t i = 0; i < nAxes; i++) { TAxis* axis{getAxis(i, hist)}; if (axis) { - axis->SetTitle(histSpec.config.axes[i].title.data()); + if (histSpec.config.axes[i].title) + axis->SetTitle((*histSpec.config.axes[i].title).data()); // this helps to have axes not only called 0,1,2... in ndim histos if constexpr (std::is_base_of_v<THnBase, T>) { @@ -238,7 +237,7 @@ struct HistFactory { // move the bin edges in case a variable binning was requested if (!histSpec.config.axes[i].nBins) { if (!std::is_sorted(std::begin(histSpec.config.axes[i].binEdges), std::end(histSpec.config.axes[i].binEdges))) { - LOGF(FATAL, "The bin edges specified for axis %s in histogram %s are not in increasing order!", (histSpec.config.axes[i].name) ? *histSpec.config.axes[i].name : histSpec.config.axes[i].title, histSpec.name); + LOGF(FATAL, "The bin edges in histogram %s are not in increasing order!", histSpec.name); return nullptr; } axis->Set(nBins[i], histSpec.config.axes[i].binEdges.data()); @@ -253,7 +252,7 @@ struct HistFactory { // create histogram and return it casted to the correct alternative held in HistPtr variant template <typename T> - static HistPtr createHistVariant(HistogramSpec const& histSpec) + static HistPtr createHistVariant(const HistogramSpec& histSpec) { if (auto hist = castToVariant(createHist<T>(histSpec))) return *hist; @@ -262,7 +261,7 @@ struct HistFactory { } // runtime version of the above - static HistPtr createHistVariant(HistogramSpec const& histSpec) + static HistPtr createHistVariant(const HistogramSpec& histSpec) { if (histSpec.config.type == HistType::kUndefinedHist) throw runtime_error("Histogram type was not specified."); @@ -365,7 +364,7 @@ struct HistFiller { } else if constexpr (validComplexFill) { // savety check for n dimensional histograms (runtime overhead) if (hist->GetNdimensions() != nDim) - throw runtime_error("The number of position (and weight) arguments does not match the histogram dimensions!"); + throw runtime_error("The number of position (and weight) arguments in fill() does not match the histogram dimensions!"); double tempArray[sizeof...(Ts)] = {static_cast<double>(positionAndWeight)...}; if constexpr (useWeight) @@ -373,7 +372,7 @@ struct HistFiller { else hist->Fill(tempArray); } else { - throw runtime_error("The number of position (and weight) arguments does not match the histogram dimensions!"); + throw runtime_error("The number of position (and weight) arguments in fill() does not match the histogram dimensions!"); } } @@ -408,11 +407,21 @@ class HistogramRegistry } } - void add(HistogramSpec&& histSpec_) + void add(const HistogramSpec& histSpec_) { insert(histSpec_); } + void add(char const* const name_, char const* const title_, const HistogramConfigSpec& histConfigSpec_, bool callSumw2_ = false) + { + insert({name_, title_, histConfigSpec_, callSumw2_}); + } + + void add(char const* const name_, char const* const title_, HistType histType_, std::vector<AxisSpec> axes_, bool callSumw2_ = false) + { + insert({name_, title_, {histType_, axes_}, callSumw2_}); + } + // gets the underlying histogram pointer // we cannot automatically infer type here so it has to be explicitly specified // -> get<TH1>(), get<TH2>(), get<TH3>(), get<THn>(), get<THnSparse>(), get<TProfile>(), get<TProfile2D>(), get<TProfile3D>() @@ -423,11 +432,17 @@ class HistogramRegistry const uint32_t id = compile_time_hash(name); const uint32_t i = imask(id); if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { - return *std::get_if<std::shared_ptr<T>>(&mRegistryValue[i]); + if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[i])) + return *histPtr; + else + throw runtime_error("Histogram type specified in get() does not match actual histogram type!"); } for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { if (id == mRegistryKey[imask(j + i)]) { - return *std::get_if<std::shared_ptr<T>>(&mRegistryValue[imask(j + i)]); + if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[imask(j + i)])) + return *histPtr; + else + throw runtime_error("Histogram type specified in get() does not match actual histogram type!"); } } throw runtime_error("No matching histogram found in HistogramRegistry!"); @@ -532,7 +547,7 @@ class HistogramRegistry mutable uint32_t lookup = 0; private: - void insert(HistogramSpec& histSpec) + void insert(const HistogramSpec& histSpec) { uint32_t i = imask(histSpec.id); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { From 4549222159d6eaf8dc5184fd8f8c896449aa16ee Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 19 Oct 2020 07:29:02 +0200 Subject: [PATCH 0979/1751] DPL: add tracking of AOD messages created / destroyed. (#4624) --- .../Core/include/Framework/ArrowContext.h | 57 ++++++++++++++++--- .../Core/include/Framework/DataProcessor.h | 22 ++++--- .../Core/include/Framework/ServiceRegistry.h | 6 ++ .../Core/include/Framework/ServiceSpec.h | 12 ++++ Framework/Core/src/CommonMessageBackends.cxx | 35 +++++++++++- Framework/Core/src/CommonServices.cxx | 13 +++++ Framework/Core/src/DataProcessingDevice.cxx | 2 + Framework/Core/src/DataProcessor.cxx | 28 +++++---- Framework/Core/src/ServiceRegistry.cxx | 11 ++++ 9 files changed, 154 insertions(+), 32 deletions(-) diff --git a/Framework/Core/include/Framework/ArrowContext.h b/Framework/Core/include/Framework/ArrowContext.h index 4601ded5b457b..0c9d4e5cdce43 100644 --- a/Framework/Core/include/Framework/ArrowContext.h +++ b/Framework/Core/include/Framework/ArrowContext.h @@ -7,8 +7,8 @@ // 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_ARROWCONTEXT_H -#define FRAMEWORK_ARROWCONTEXT_H +#ifndef O2_FRAMEWORK_ARROWCONTEXT_H_ +#define O2_FRAMEWORK_ARROWCONTEXT_H_ #include "Framework/FairMQDeviceProxy.h" #include <cassert> @@ -19,9 +19,7 @@ class FairMQMessage; -namespace o2 -{ -namespace framework +namespace o2::framework { class FairMQResizableBuffer; @@ -92,11 +90,54 @@ class ArrowContext return mProxy; } + void updateBytesSent(size_t value) + { + mBytesSent += value; + } + + void updateBytesDestroyed(size_t value) + { + mBytesDestroyed += value; + } + + void updateMessagesSent(size_t value) + { + mMessagesCreated += value; + } + + void updateMessagesDestroyed(size_t value) + { + mMessagesDestroyed += value; + } + + size_t bytesSent() + { + return mBytesSent; + } + + size_t bytesDestroyed() + { + return mBytesDestroyed; + } + + size_t messagesCreated() + { + return mMessagesCreated; + } + + size_t messagesDestroyed() + { + return mMessagesDestroyed; + } + private: FairMQDeviceProxy mProxy; Messages mMessages; + size_t mBytesSent = 0; + size_t mBytesDestroyed = 0; + size_t mMessagesCreated = 0; + size_t mMessagesDestroyed = 0; }; -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_ARROWCONTEXT_H +} // namespace o2::framework +#endif // O2_FRAMEWORK_ARROWCONTEXT_H_ diff --git a/Framework/Core/include/Framework/DataProcessor.h b/Framework/Core/include/Framework/DataProcessor.h index e4147aaef6c52..8aa83108c5851 100644 --- a/Framework/Core/include/Framework/DataProcessor.h +++ b/Framework/Core/include/Framework/DataProcessor.h @@ -7,33 +7,31 @@ // 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_DATAPROCESSOR_H -#define FRAMEWORK_DATAPROCESSOR_H +#ifndef O2_FRAMEWORK_DATAPROCESSOR_H_ +#define O2_FRAMEWORK_DATAPROCESSOR_H_ class FairMQDevice; class FairMQParts; -namespace o2 -{ -namespace framework +namespace o2::framework { class MessageContext; class StringContext; class ArrowContext; class RawBufferContext; +class ServiceRegistry; /// Helper class to send messages from a contex at the end /// of a computation. struct DataProcessor { - static void doSend(FairMQDevice&, MessageContext&); - static void doSend(FairMQDevice&, StringContext&); - static void doSend(FairMQDevice&, ArrowContext&); - static void doSend(FairMQDevice&, RawBufferContext&); + static void doSend(FairMQDevice&, MessageContext&, ServiceRegistry&); + static void doSend(FairMQDevice&, StringContext&, ServiceRegistry&); + static void doSend(FairMQDevice&, ArrowContext&, ServiceRegistry&); + static void doSend(FairMQDevice&, RawBufferContext&, ServiceRegistry&); static void doSend(FairMQDevice&, FairMQParts&&, const char*, unsigned int); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif // FRAMEWORK_DATAPROCESSOR_H +#endif // O2_FRAMEWORK_DATAPROCESSOR_H_ diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index 8e2f96363d3ec..5490a1bbc32f2 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -92,6 +92,8 @@ struct ServiceRegistry { std::vector<ServiceEOSHandle> mPreEOSHandles; /// Callbacks for services to be executed after every EOS user callback invokation std::vector<ServiceEOSHandle> mPostEOSHandles; + /// Callbacks for services to be executed after every dispatching + std::vector<ServiceDispatchingHandle> mPostDispatchingHandles; public: using hash_type = decltype(TypeIdHelpers::uniqueId<void>()); @@ -130,6 +132,10 @@ struct ServiceRegistry { void preEOSCallbacks(EndOfStreamContext&); /// Invoke callbacks to be executed after every EOS user callback invokation void postEOSCallbacks(EndOfStreamContext&); + /// Invoke callbacks to monitor inputs after dispatching, regardless of them + /// being discarded, consumed or processed. + void postDispatchingCallbacks(ProcessingContext&); + /// Declare a service by its ServiceSpec. If of type Global /// / Serial it will be immediately registered for tid 0, /// so that subsequent gets will ultimately use it. diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index 6e1e420a7da25..e7dce7623f2d3 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -66,6 +66,9 @@ using ServicePostForkParent = std::function<void(ServiceRegistry&)>; /// Callback executed in the driver in order to process a metric. using ServiceMetricHandling = std::function<void(ServiceRegistry&)>; +/// Callback executed in the child after dispatching happened. +using ServicePostDispatching = std::function<void(ProcessingContext&, void*)>; + /// A specification for a Service. /// A Service is a utility class which does not perform /// data processing itself, but it can be used by the data processor @@ -105,6 +108,10 @@ struct ServiceSpec { ///Callback executed after each metric is received by the driver. ServiceMetricHandling metricHandling = nullptr; + /// Callback executed after a given input record has been successfully + /// dispatched. + ServicePostDispatching postDispatching = nullptr; + /// Kind of service being specified. ServiceKind kind; }; @@ -129,6 +136,11 @@ struct ServiceEOSHandle { void* service; }; +struct ServiceDispatchingHandle { + ServicePostDispatching callback; + void* service; +}; + } // namespace o2::framework #endif // O2_FRAMEWORK_SERVICESPEC_H_ diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index 100fd8397b6e5..4a1056c50900f 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -19,6 +19,9 @@ #include "Framework/EndOfStreamContext.h" #include "Framework/Tracing.h" +#include <Monitoring/Monitoring.h> +#include <Headers/DataHeader.h> + #include <options/FairMQProgOptions.h> namespace o2::framework @@ -45,7 +48,7 @@ struct CommonMessageBackendsHelpers { ZoneScopedN("send message callback"); T* context = reinterpret_cast<T*>(service); auto& device = ctx.services().get<RawDeviceService>(); - DataProcessor::doSend(*device.device(), *context); + DataProcessor::doSend(*device.device(), *context, ctx.services()); }; } @@ -70,7 +73,7 @@ struct CommonMessageBackendsHelpers { return [](EndOfStreamContext& ctx, void* service) { T* context = reinterpret_cast<T*>(service); auto& device = ctx.services().get<RawDeviceService>(); - DataProcessor::doSend(*device.device(), *context); + DataProcessor::doSend(*device.device(), *context, ctx.services()); }; } }; @@ -78,6 +81,11 @@ struct CommonMessageBackendsHelpers { o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() { + using o2::monitoring::Metric; + using o2::monitoring::Monitoring; + using o2::monitoring::tags::Key; + using o2::monitoring::tags::Value; + return ServiceSpec{"arrow-backend", CommonMessageBackendsHelpers<ArrowContext>::createCallback(), CommonServices::noConfiguration(), @@ -91,6 +99,26 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() nullptr, nullptr, nullptr, + [](ProcessingContext& ctx, void* service) { + using DataHeader = o2::header::DataHeader; + ArrowContext* arrow = reinterpret_cast<ArrowContext*>(service); + for (auto& input : ctx.inputs()) { + if (input.header == nullptr) { + continue; + } + auto dh = o2::header::get<DataHeader*>(input.header); + auto dph = o2::header::get<DataProcessingHeader*>(input.header); + for (auto const& forward : ctx.services().get<DeviceSpec const>().forwards) { + if (DataSpecUtils::match(forward.matcher, dh->dataOrigin, dh->dataDescription, dh->subSpecification) == true && (dph->startTime % forward.maxTimeslices) == forward.timeslice) { + continue; + } + arrow->updateBytesDestroyed(dh->payloadSize); + arrow->updateMessagesDestroyed(1); + } + } + ctx.services().get<Monitoring>().send(Metric{(uint64_t)arrow->bytesDestroyed(), "arrow-bytes-destroyed"}.addTag(Key::Subsystem, Value::DPL)); + ctx.services().get<Monitoring>().send(Metric{(uint64_t)arrow->messagesDestroyed(), "arrow-messages-destroyed"}.addTag(Key::Subsystem, Value::DPL)); + }, ServiceKind::Serial}; } @@ -129,6 +157,7 @@ o2::framework::ServiceSpec CommonMessageBackends::fairMQBackendSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -147,6 +176,7 @@ o2::framework::ServiceSpec CommonMessageBackends::stringBackendSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -165,6 +195,7 @@ o2::framework::ServiceSpec CommonMessageBackends::rawBufferBackendSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index ecea272d900ed..cac9a6fdfeb91 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -71,6 +71,7 @@ o2::framework::ServiceSpec CommonServices::monitoringSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -89,6 +90,7 @@ o2::framework::ServiceSpec CommonServices::infologgerContextSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -175,6 +177,7 @@ o2::framework::ServiceSpec CommonServices::infologgerSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -201,6 +204,7 @@ o2::framework::ServiceSpec CommonServices::configurationSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Global}; } @@ -223,6 +227,7 @@ o2::framework::ServiceSpec CommonServices::controlSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -242,6 +247,7 @@ o2::framework::ServiceSpec CommonServices::rootFileSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -265,6 +271,7 @@ o2::framework::ServiceSpec CommonServices::parallelSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -284,6 +291,7 @@ o2::framework::ServiceSpec CommonServices::timesliceIndex() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -303,6 +311,7 @@ o2::framework::ServiceSpec CommonServices::callbacksSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -329,6 +338,7 @@ o2::framework::ServiceSpec CommonServices::dataRelayer() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -360,6 +370,7 @@ o2::framework::ServiceSpec CommonServices::tracingSpec() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } @@ -388,6 +399,7 @@ o2::framework::ServiceSpec CommonServices::threadPool(int numWorkers) nullptr, nullptr, nullptr, + nullptr, [numWorkers](ServiceRegistry& service) -> void { auto numWorkersS = std::to_string(numWorkers); setenv("UV_THREADPOOL_SIZE", numWorkersS.c_str(), 0); @@ -494,6 +506,7 @@ o2::framework::ServiceSpec CommonServices::dataProcessingStats() nullptr, nullptr, nullptr, + nullptr, ServiceKind::Serial}; } diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 19e3058277c32..dd2e35c36ec5c 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -956,6 +956,7 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, } if (action.op == CompletionPolicy::CompletionOp::Discard) { if (context.spec->forwards.empty() == false) { + context.registry->postDispatchingCallbacks(processContext); forwardInputs(action.slot, record); continue; } @@ -996,6 +997,7 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, // We forward inputs only when we consume them. If we simply Process them, // we keep them for next message arriving. if (action.op == CompletionPolicy::CompletionOp::Consume) { + context.registry->postDispatchingCallbacks(processContext); if (context.spec->forwards.empty() == false) { forwardInputs(action.slot, record); } diff --git a/Framework/Core/src/DataProcessor.cxx b/Framework/Core/src/DataProcessor.cxx index f68c60d2de870..1265717c45bd7 100644 --- a/Framework/Core/src/DataProcessor.cxx +++ b/Framework/Core/src/DataProcessor.cxx @@ -13,9 +13,12 @@ #include "Framework/ArrowContext.h" #include "Framework/RawBufferContext.h" #include "Framework/TMessageSerializer.h" +#include "Framework/ServiceRegistry.h" #include "FairMQResizableBuffer.h" #include "CommonUtils/BoostSerializer.h" #include "Headers/DataHeader.h" + +#include <Monitoring/Monitoring.h> #include <fairmq/FairMQParts.h> #include <fairmq/FairMQDevice.h> #include <arrow/io/memory.h> @@ -26,9 +29,7 @@ using namespace o2::framework; using DataHeader = o2::header::DataHeader; -namespace o2 -{ -namespace framework +namespace o2::framework { void DataProcessor::doSend(FairMQDevice& device, FairMQParts&& parts, const char* channel, unsigned int index) @@ -36,7 +37,7 @@ void DataProcessor::doSend(FairMQDevice& device, FairMQParts&& parts, const char device.Send(parts, channel, index); } -void DataProcessor::doSend(FairMQDevice& device, MessageContext& context) +void DataProcessor::doSend(FairMQDevice& device, MessageContext& context, ServiceRegistry&) { std::unordered_map<std::string const*, FairMQParts> outputs; auto contextMessages = context.getMessagesForSending(); @@ -54,7 +55,7 @@ void DataProcessor::doSend(FairMQDevice& device, MessageContext& context) } } -void DataProcessor::doSend(FairMQDevice& device, StringContext& context) +void DataProcessor::doSend(FairMQDevice& device, StringContext& context, ServiceRegistry&) { for (auto& messageRef : context) { FairMQParts parts; @@ -73,9 +74,13 @@ void DataProcessor::doSend(FairMQDevice& device, StringContext& context) } } -// FIXME: for the moment we simply send empty messages. -void DataProcessor::doSend(FairMQDevice& device, ArrowContext& context) +void DataProcessor::doSend(FairMQDevice& device, ArrowContext& context, ServiceRegistry& registry) { + using o2::monitoring::Metric; + using o2::monitoring::Monitoring; + using o2::monitoring::tags::Key; + using o2::monitoring::tags::Value; + for (auto& messageRef : context) { FairMQParts parts; // Depending on how the arrow table is constructed, we finalize @@ -89,13 +94,17 @@ void DataProcessor::doSend(FairMQDevice& device, ArrowContext& context) // exposing it to the user in the first place. DataHeader* dh = const_cast<DataHeader*>(cdh); dh->payloadSize = payload->GetSize(); + context.updateBytesSent(payload->GetSize()); + context.updateMessagesSent(1); + registry.get<Monitoring>().send(Metric{(uint64_t)context.bytesSent(), "arrow-bytes-created"}.addTag(Key::Subsystem, Value::DPL)); + registry.get<Monitoring>().send(Metric{(uint64_t)context.messagesCreated(), "arrow-messages-created"}.addTag(Key::Subsystem, Value::DPL)); parts.AddPart(std::move(messageRef.header)); parts.AddPart(std::move(payload)); device.Send(parts, messageRef.channel, 0); } } -void DataProcessor::doSend(FairMQDevice& device, RawBufferContext& context) +void DataProcessor::doSend(FairMQDevice& device, RawBufferContext& context, ServiceRegistry& registry) { for (auto& messageRef : context) { FairMQParts parts; @@ -116,5 +125,4 @@ void DataProcessor::doSend(FairMQDevice& device, RawBufferContext& context) } } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/src/ServiceRegistry.cxx b/Framework/Core/src/ServiceRegistry.cxx index 1890483b69724..55d25a6abd67d 100644 --- a/Framework/Core/src/ServiceRegistry.cxx +++ b/Framework/Core/src/ServiceRegistry.cxx @@ -93,6 +93,9 @@ void ServiceRegistry::bindService(ServiceSpec const& spec, void* service) if (spec.postEOS) { mPostEOSHandles.push_back(ServiceEOSHandle{spec.postEOS, service}); } + if (spec.postDispatching) { + mPostDispatchingHandles.push_back(ServiceDispatchingHandle{spec.postDispatching, service}); + } } /// Invoke callbacks to be executed before every process method invokation @@ -141,4 +144,12 @@ void ServiceRegistry::postEOSCallbacks(EndOfStreamContext& eosContext) } } +/// Invoke callbacks to be executed after every data Dispatching +void ServiceRegistry::postDispatchingCallbacks(ProcessingContext& processContext) +{ + for (auto& dispatchingHandle : mPostDispatchingHandles) { + dispatchingHandle.callback(processContext, dispatchingHandle.service); + } +} + } // namespace o2::framework From 7a4812bee28ff657b0afb329fc41fb6e3e024fd9 Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Mon, 19 Oct 2020 11:10:40 +0200 Subject: [PATCH 0980/1751] [QC-428] Standalone Data Sampling executable (#4574) --- Utilities/DataSampling/CMakeLists.txt | 5 +++ Utilities/DataSampling/README.md | 6 ++- .../src/dataSamplingStandalone.cxx | 45 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 Utilities/DataSampling/src/dataSamplingStandalone.cxx diff --git a/Utilities/DataSampling/CMakeLists.txt b/Utilities/DataSampling/CMakeLists.txt index 588631fc47cb3..549f87122175f 100644 --- a/Utilities/DataSampling/CMakeLists.txt +++ b/Utilities/DataSampling/CMakeLists.txt @@ -61,6 +61,11 @@ endforeach() o2_data_file(COPY etc/exampleDataSamplingConfig.json DESTINATION etc) +o2_add_dpl_workflow(standalone + SOURCES src/dataSamplingStandalone.cxx + COMPONENT_NAME DataSampling + PUBLIC_LINK_LIBRARIES O2::DataSampling) + o2_add_dpl_workflow(datasampling-pod-and-root SOURCES test/dataSamplingPodAndRoot.cxx COMPONENT_NAME DataSampling diff --git a/Utilities/DataSampling/README.md b/Utilities/DataSampling/README.md index 68281ac7de8b5..0f74547dab51b 100644 --- a/Utilities/DataSampling/README.md +++ b/Utilities/DataSampling/README.md @@ -24,7 +24,11 @@ Data Sampling provides possibility to sample data in DPL workflows, basing on ce ### Usage -To use Data Sampling in a DPL workflow insert following lines to your code: +One can use Data Sampling either by merging the standalone Data Sampling workflow with other DPL workflows: +```bash +o2-workflow-abc | o2-datasampling-standalone --config json://path/to/config.json | o2-workflow-xyz +``` +...or by incorporating the code below into a DPL workflow which needs sampling: ```cpp #include "DataSampling/DataSampling.h" using namespace o2::framework; diff --git a/Utilities/DataSampling/src/dataSamplingStandalone.cxx b/Utilities/DataSampling/src/dataSamplingStandalone.cxx new file mode 100644 index 0000000000000..e6fb96fbdbdd5 --- /dev/null +++ b/Utilities/DataSampling/src/dataSamplingStandalone.cxx @@ -0,0 +1,45 @@ +// 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/ConfigParamSpec.h" +#include "DataSampling/DataSampling.h" +#include "Framework/CompletionPolicyHelpers.h" +#include <vector> + +using namespace o2::framework; +using namespace o2::utilities; + +void customize(std::vector<CompletionPolicy>& policies) +{ + DataSampling::CustomizeInfrastructure(policies); +} + +void customize(std::vector<ChannelConfigurationPolicy>& policies) +{ + DataSampling::CustomizeInfrastructure(policies); +} + +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{"config", VariantType::String, "", {"path to the Data Sampling configuration file"}}); + workflowOptions.push_back(ConfigParamSpec{"dispatchers", VariantType::Int, 1, {"amount of parallel Dispatchers"}}); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& config) +{ + auto configurationPath = config.options().get<std::string>("config"); + auto numberOfDispatchers = config.options().get<int>("dispatchers"); + + WorkflowSpec specs; + DataSampling::GenerateInfrastructure(specs, configurationPath, numberOfDispatchers); + return specs; +} \ No newline at end of file From bcd4e0513058c809ede3e463afbad2a8b77d0d5d Mon Sep 17 00:00:00 2001 From: Piotr Konopka <piotr.jan.konopka@cern.ch> Date: Thu, 15 Oct 2020 13:39:28 +0200 Subject: [PATCH 0981/1751] [QC-338] Facilitate creating a Dispatcher without configuration files --- .../DataSampling/DataSamplingCondition.h | 2 +- .../include/DataSampling/DataSamplingPolicy.h | 28 ++++-- .../include/DataSampling/Dispatcher.h | 8 +- Utilities/DataSampling/src/DataSampling.cxx | 21 ++--- .../DataSampling/src/DataSamplingPolicy.cxx | 50 ++++++----- Utilities/DataSampling/src/Dispatcher.cxx | 85 +++++++++++++----- .../DataSampling/test/test_DataSampling.cxx | 79 ++++++++++++++++- .../test/test_DataSamplingPolicy.cxx | 86 +++++++++++-------- 8 files changed, 249 insertions(+), 110 deletions(-) diff --git a/Utilities/DataSampling/include/DataSampling/DataSamplingCondition.h b/Utilities/DataSampling/include/DataSampling/DataSamplingCondition.h index 98a02978e92b4..754f9049a1561 100644 --- a/Utilities/DataSampling/include/DataSampling/DataSamplingCondition.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingCondition.h @@ -24,7 +24,7 @@ namespace o2::utilities { -/// A standarised data sampling condition, to decide if given data sample should be passed forward. +/// A standardised data sampling condition, to decide if given data sample should be passed forward. class DataSamplingCondition { public: diff --git a/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h b/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h index 6a82ac5f1c0b1..3330aea33686b 100644 --- a/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h @@ -39,8 +39,8 @@ class DataSamplingPolicy class PathMap : public PathVectorBase { public: - ~PathMap() = default; PathMap() = default; + ~PathMap() = default; const PathVectorBase::const_iterator find(const framework::ConcreteDataMatcher& input) const { return std::find_if(begin(), end(), [input](const auto& el) { @@ -50,21 +50,33 @@ class DataSamplingPolicy }; public: + /// \brief Configures a policy using structured configuration entry. + static DataSamplingPolicy fromConfiguration(const boost::property_tree::ptree&); + /// \brief Constructor. - DataSamplingPolicy(); - /// \brief Constructor. - DataSamplingPolicy(const boost::property_tree::ptree&); + DataSamplingPolicy(std::string name); /// \brief Destructor - ~DataSamplingPolicy(); + ~DataSamplingPolicy() = default; + /// \brief Move constructor + DataSamplingPolicy(DataSamplingPolicy&&) = default; + /// \brief Move assignment + DataSamplingPolicy& operator=(DataSamplingPolicy&&) = default; + + /// \brief Adds a new association between inputs and outputs. + void registerPath(const framework::InputSpec&, const framework::OutputSpec&); + /// \brief Adds a new association between inputs and outputs. + // void registerPolicy(framework::InputSpec&&, framework::OutputSpec&&); + /// \brief Adds a new sampling condition. + void registerCondition(std::unique_ptr<DataSamplingCondition>&&); + /// \brief Sets a raw FairMQChannel. Deprecated, do not use. + void setFairMQOutputChannel(std::string); - /// \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 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 framework::Output prepareOutput(const framework::ConcreteDataMatcher& input, framework::Lifetime lifetime = framework::Lifetime::Timeframe) const; + framework::Output prepareOutput(const framework::ConcreteDataMatcher& input, framework::Lifetime lifetime = framework::Lifetime::Timeframe) const; const std::string& getName() const; const PathMap& getPathMap() const; diff --git a/Utilities/DataSampling/include/DataSampling/Dispatcher.h b/Utilities/DataSampling/include/DataSampling/Dispatcher.h index 565de10bb35f7..3e2c078d788e6 100644 --- a/Utilities/DataSampling/include/DataSampling/Dispatcher.h +++ b/Utilities/DataSampling/include/DataSampling/Dispatcher.h @@ -50,12 +50,14 @@ class Dispatcher : public framework::Task /// \brief Dispatcher process callback 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<framework::InputSpec, framework::OutputSpec>&); + /// \brief Register a Data Sampling Policy + void registerPolicy(std::unique_ptr<DataSamplingPolicy>&&); const std::string& getName(); + /// \brief Assembles InputSpecs of all registered policies in a single vector, removing overlapping entries. framework::Inputs getInputSpecs(); framework::Outputs getOutputSpecs(); + framework::Options getOptions(); private: DataSamplingHeader prepareDataSamplingHeader(const DataSamplingPolicy& policy, const framework::DeviceSpec& spec); @@ -67,8 +69,6 @@ class Dispatcher : public framework::Task std::string mName; std::string mReconfigurationSource; - framework::Inputs inputs; - framework::Outputs outputs; // policies should be shared between all pipeline threads std::vector<std::shared_ptr<DataSamplingPolicy>> mPolicies; }; diff --git a/Utilities/DataSampling/src/DataSampling.cxx b/Utilities/DataSampling/src/DataSampling.cxx index 91d9b60236383..73988d2afb58b 100644 --- a/Utilities/DataSampling/src/DataSampling.cxx +++ b/Utilities/DataSampling/src/DataSampling.cxx @@ -56,7 +56,6 @@ void DataSampling::GenerateInfrastructure(WorkflowSpec& workflow, const boost::p void DataSampling::DoGenerateInfrastructure(Dispatcher& dispatcher, WorkflowSpec& workflow, const boost::property_tree::ptree& policiesTree, size_t threads) { LOG(DEBUG) << "Generating Data Sampling infrastructure..."; - Options options; for (auto&& policyConfig : policiesTree) { @@ -64,7 +63,7 @@ void DataSampling::DoGenerateInfrastructure(Dispatcher& dispatcher, WorkflowSpec // We don't want the Dispatcher to exit due to one faulty Policy try { - policy = std::make_unique<DataSamplingPolicy>(policyConfig.second); + dispatcher.registerPolicy(std::make_unique<DataSamplingPolicy>(DataSamplingPolicy::fromConfiguration(policyConfig.second))); } catch (const std::exception& ex) { LOG(WARN) << "Could not load the Data Sampling Policy '" << policyConfig.second.get_optional<std::string>("id").value_or("") << "', because: " << ex.what(); @@ -74,27 +73,17 @@ void DataSampling::DoGenerateInfrastructure(Dispatcher& dispatcher, WorkflowSpec << policyConfig.second.get_optional<std::string>("id").value_or("") << "'"; continue; } - - for (const auto& path : policy->getPathMap()) { - dispatcher.registerPath({path.first, path.second}); - } - - if (!policy->getFairMQOutputChannel().empty()) { - options.push_back({"channel-config", VariantType::String, policy->getFairMQOutputChannel().c_str(), {"Out-of-band channel config"}}); - LOG(DEBUG) << " - registering output FairMQ channel '" << policy->getFairMQOutputChannel() << "'"; - } } - options.push_back({"period-timer-stats", framework::VariantType::Int, 10 * 1000000, {"Dispatcher's stats timer period"}}); if (dispatcher.getInputSpecs().size() > 0) { DataProcessorSpec spec; spec.name = dispatcher.getName(); spec.inputs = dispatcher.getInputSpecs(); spec.outputs = dispatcher.getOutputSpecs(); - spec.algorithm = adaptFromTask<Dispatcher>(std::move(dispatcher)); spec.maxInputTimeslices = threads; spec.labels = {{"DataSampling"}, {"Dispatcher"}}; - spec.options = options; + spec.options = dispatcher.getOptions(); + spec.algorithm = adaptFromTask<Dispatcher>(std::move(dispatcher)); workflow.emplace_back(std::move(spec)); } else { @@ -127,7 +116,7 @@ std::vector<InputSpec> DataSampling::InputSpecsForPolicy(ConfigurationInterface* for (auto&& policyConfig : policiesTree) { if (policyConfig.second.get<std::string>("id") == policyName) { - DataSamplingPolicy policy(policyConfig.second); + auto policy = DataSamplingPolicy::fromConfiguration(policyConfig.second); for (const auto& path : policy.getPathMap()) { InputSpec input = DataSpecUtils::matchingInput(path.second); inputs.push_back(input); @@ -169,7 +158,7 @@ std::vector<OutputSpec> DataSampling::OutputSpecsForPolicy(ConfigurationInterfac for (auto&& policyConfig : policiesTree) { if (policyConfig.second.get<std::string>("id") == policyName) { - DataSamplingPolicy policy(policyConfig.second); + auto policy = DataSamplingPolicy::fromConfiguration(policyConfig.second); for (const auto& path : policy.getPathMap()) { outputs.push_back(path.second); } diff --git a/Utilities/DataSampling/src/DataSamplingPolicy.cxx b/Utilities/DataSampling/src/DataSamplingPolicy.cxx index a68fb6394f1af..61b66defd783f 100644 --- a/Utilities/DataSampling/src/DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/src/DataSamplingPolicy.cxx @@ -29,28 +29,30 @@ namespace o2::utilities using boost::property_tree::ptree; -DataSamplingPolicy::DataSamplingPolicy() = default; +DataSamplingPolicy::DataSamplingPolicy(std::string name) : mName(std::move(name)) +{ +} -DataSamplingPolicy::DataSamplingPolicy(const ptree& config) +void DataSamplingPolicy::registerPath(const InputSpec& inputSpec, const OutputSpec& outputSpec) { - configure(config); + mPaths.emplace_back(inputSpec, outputSpec); } -DataSamplingPolicy::~DataSamplingPolicy() = default; +void DataSamplingPolicy::registerCondition(std::unique_ptr<DataSamplingCondition>&& condition) +{ + mConditions.emplace_back(std::move(condition)); +} -void DataSamplingPolicy::configure(const ptree& config) +void DataSamplingPolicy::setFairMQOutputChannel(std::string channel) { - mName = config.get<std::string>("id"); - if (mName.size() > 14) { - LOG(WARNING) << "DataSamplingPolicy name '" << mName << "' is longer than 14 characters, we have to trim it. " - << "Use a shorter policy name to avoid potential output name conflicts."; - mName.resize(14); - } + mFairMQOutputChannel = std::move(channel); +} - auto subSpecString = config.get_optional<std::string>("subSpec").value_or("*"); - auto subSpec = subSpecString.find_first_of("-*") != std::string::npos ? -1 : std::strtoull(subSpecString.c_str(), nullptr, 10); +DataSamplingPolicy DataSamplingPolicy::fromConfiguration(const ptree& config) +{ + auto name = config.get<std::string>("id"); + DataSamplingPolicy policy(name); - mPaths.clear(); size_t outputId = 0; std::vector<InputSpec> inputSpecs = DataDescriptorQueryBuilder::parse(config.get<std::string>("query").c_str()); @@ -60,29 +62,31 @@ void DataSamplingPolicy::configure(const ptree& config) OutputSpec outputSpec{ {inputSpec.binding}, createPolicyDataOrigin(), - createPolicyDataDescription(mName, outputId++), + createPolicyDataDescription(name, outputId++), DataSpecUtils::getOptionalSubSpec(inputSpec).value(), inputSpec.lifetime}; - mPaths.push_back({inputSpec, outputSpec}); + policy.registerPath(inputSpec, outputSpec); } else { OutputSpec outputSpec{ {inputSpec.binding}, - {createPolicyDataOrigin(), createPolicyDataDescription(mName, outputId++)}, + {createPolicyDataOrigin(), createPolicyDataDescription(name, outputId++)}, inputSpec.lifetime}; - mPaths.push_back({inputSpec, outputSpec}); + policy.registerPath(inputSpec, outputSpec); } } - mConditions.clear(); for (const auto& conditionConfig : config.get_child("samplingConditions")) { - mConditions.push_back(DataSamplingConditionFactory::create(conditionConfig.second.get<std::string>("condition"))); - mConditions.back()->configure(conditionConfig.second); + auto condition = DataSamplingConditionFactory::create(conditionConfig.second.get<std::string>("condition")); + condition->configure(conditionConfig.second); + policy.registerCondition(std::move(condition)); } - mFairMQOutputChannel = config.get_optional<std::string>("fairMQOutput").value_or(""); + policy.setFairMQOutputChannel(config.get_optional<std::string>("fairMQOutput").value_or("")); + + return policy; } bool DataSamplingPolicy::match(const ConcreteDataMatcher& input) const @@ -103,7 +107,7 @@ bool DataSamplingPolicy::decide(const o2::framework::DataRef& dataRef) return decision; } -const Output DataSamplingPolicy::prepareOutput(const ConcreteDataMatcher& input, Lifetime lifetime) const +Output DataSamplingPolicy::prepareOutput(const ConcreteDataMatcher& input, Lifetime lifetime) const { auto result = mPaths.find(input); if (result != mPaths.end()) { diff --git a/Utilities/DataSampling/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx index 9f517d207ff72..f5e753de1e9d5 100644 --- a/Utilities/DataSampling/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -38,9 +38,6 @@ namespace o2::utilities Dispatcher::Dispatcher(std::string name, const std::string reconfigurationSource) : mName(name), mReconfigurationSource(reconfigurationSource) { - header::DataDescription timerDescription; - timerDescription.runtimeInit(("TIMER-" + name).substr(0, 16).c_str()); - inputs.emplace_back(InputSpec{"timer-stats", "DS", timerDescription, 0, Lifetime::Timer}); } Dispatcher::~Dispatcher() = default; @@ -55,15 +52,16 @@ void Dispatcher::init(InitContext& ctx) std::unique_ptr<ConfigurationInterface> cfg = ConfigurationFactory::getConfiguration(mReconfigurationSource); policiesTree = cfg->getRecursive("dataSamplingPolicies"); mPolicies.clear(); - } else { + } else if (ctx.options().isSet("sampling-config-ptree")) { policiesTree = ctx.options().get<boost::property_tree::ptree>("sampling-config-ptree"); mPolicies.clear(); - } + } else + ; // we use policies declared during workflow init. for (auto&& policyConfig : policiesTree) { // we don't want the Dispatcher to exit due to one faulty Policy try { - mPolicies.emplace_back(std::make_shared<DataSamplingPolicy>(policyConfig.second)); + mPolicies.emplace_back(std::make_shared<DataSamplingPolicy>(DataSamplingPolicy::fromConfiguration(policyConfig.second))); } catch (std::exception& ex) { LOG(WARN) << "Could not load the Data Sampling Policy '" << policyConfig.second.get_optional<std::string>("id").value_or("") << "', because: " << ex.what(); @@ -188,22 +186,9 @@ void Dispatcher::sendFairMQ(FairMQDevice* device, const DataRef& inputData, cons int64_t bytesSent = device->Send(message, fairMQChannel); } -void Dispatcher::registerPath(const std::pair<InputSpec, OutputSpec>& path) +void Dispatcher::registerPolicy(std::unique_ptr<DataSamplingPolicy>&& policy) { - //todo: take care of inputs inclusive in others, when subSpec matchers are supported - auto cmp = [a = path.first](const InputSpec b) { - return a.matcher == b.matcher && a.lifetime == b.lifetime; - }; - - if (std::find_if(inputs.begin(), inputs.end(), cmp) == inputs.end()) { - inputs.push_back(path.first); - LOG(DEBUG) << "Registering input " << DataSpecUtils::describe(path.first); - } else { - LOG(DEBUG) << "Input " << DataSpecUtils::describe(path.first) - << " already registered"; - } - - outputs.push_back(path.second); + mPolicies.emplace_back(std::move(policy)); } const std::string& Dispatcher::getName() @@ -213,12 +198,66 @@ const std::string& Dispatcher::getName() Inputs Dispatcher::getInputSpecs() { - return inputs; + Inputs declaredInputs; + + // Add data inputs. Avoid duplicates and inputs which include others (e.g. "TST/DATA" includes "TST/DATA/1". + for (const auto& policy : mPolicies) { + for (const auto& [potentiallyNewInput, _policyOutput] : policy->getPathMap()) { + (void)_policyOutput; + + // The idea is that we remove all existing inputs which are covered by the potentially new input. + // If there are none which are broader than the new one, then we add it. + // I hope this is enough for all corner cases, but I am not 100% sure. + auto newInputIsBroader = [&potentiallyNewInput](const InputSpec& other) { + return DataSpecUtils::includes(potentiallyNewInput, other); + }; + declaredInputs.erase(std::remove_if(declaredInputs.begin(), declaredInputs.end(), newInputIsBroader), declaredInputs.end()); + + auto declaredInputIsBroader = [&potentiallyNewInput](const InputSpec& other) { + return DataSpecUtils::includes(other, potentiallyNewInput); + }; + if (std::none_of(declaredInputs.begin(), declaredInputs.end(), declaredInputIsBroader)) { + declaredInputs.push_back(potentiallyNewInput); + } + } + } + + // add timer input + header::DataDescription timerDescription; + timerDescription.runtimeInit(("TIMER-" + mName).substr(0, 16).c_str()); + declaredInputs.emplace_back(InputSpec{"timer-stats", "DS", timerDescription, 0, Lifetime::Timer}); + + return declaredInputs; } Outputs Dispatcher::getOutputSpecs() { - return outputs; + Outputs declaredOutputs; + for (const auto& policy : mPolicies) { + for (const auto& [_policyInput, policyOutput] : policy->getPathMap()) { + (void)_policyInput; + // In principle Data Sampling Policies should have different outputs. + // We may add a check to be very gentle with users. + declaredOutputs.push_back(policyOutput); + } + } + return declaredOutputs; +} +framework::Options Dispatcher::getOptions() +{ + o2::framework::Options options; + for (const auto& policy : mPolicies) { + if (!policy->getFairMQOutputChannel().empty()) { + if (!options.empty()) { + throw std::runtime_error("Maximum one policy with raw FairMQ channel is allowed, more have been declared."); + } + options.push_back({"channel-config", VariantType::String, policy->getFairMQOutputChannel().c_str(), {"Out-of-band channel config"}}); + LOG(DEBUG) << " - registering output FairMQ channel '" << policy->getFairMQOutputChannel() << "'"; + } + } + options.push_back({"period-timer-stats", framework::VariantType::Int, 10 * 1000000, {"Dispatcher's stats timer period"}}); + + return options; } } // namespace o2::utilities diff --git a/Utilities/DataSampling/test/test_DataSampling.cxx b/Utilities/DataSampling/test/test_DataSampling.cxx index 12b72aba0809c..e3eff2d236310 100644 --- a/Utilities/DataSampling/test/test_DataSampling.cxx +++ b/Utilities/DataSampling/test/test_DataSampling.cxx @@ -14,6 +14,8 @@ #include <boost/test/unit_test.hpp> #include "DataSampling/DataSampling.h" +#include "DataSampling/Dispatcher.h" +#include "DataSampling/DataSamplingPolicy.h" #include "Framework/DataProcessingHeader.h" #include "Framework/ExternalFairMQDeviceProxy.h" #include "DataSampling/DataSamplingReadoutAdapter.h" @@ -223,4 +225,79 @@ BOOST_AUTO_TEST_CASE(DataSamplingEmptyConfig) WorkflowSpec workflow; BOOST_CHECK_NO_THROW(DataSampling::GenerateInfrastructure(workflow, configFilePath)); -} \ No newline at end of file +} + +BOOST_AUTO_TEST_CASE(DataSamplingOverlappingInputs) +{ + { + // policy3 includes 1 and 2, so we should have only one inputspec for data, one for timer + Dispatcher dispatcher("dispatcher", ""); + auto policy1 = std::make_unique<DataSamplingPolicy>("policy1"); + policy1->registerPath({"vcxz", "TST", "AAAA", 0}, {{"erwv"}, "DS", "AAAA"}); + + auto policy2 = std::make_unique<DataSamplingPolicy>("policy2"); + policy2->registerPath({"fdsa", "TST", "AAAA", 0}, {{"fdsf"}, "DS", "BBBB"}); + + auto policy3 = std::make_unique<DataSamplingPolicy>("policy3"); + policy3->registerPath({"asdf", {"TST", "AAAA"}}, {{"erwv"}, "DS", "CCCC"}); + + dispatcher.registerPolicy(std::move(policy1)); + dispatcher.registerPolicy(std::move(policy2)); + dispatcher.registerPolicy(std::move(policy3)); + + auto inputs = dispatcher.getInputSpecs(); + + BOOST_REQUIRE_EQUAL(inputs.size(), 2); + BOOST_CHECK_EQUAL(inputs[0], (InputSpec{"asdf", {"TST", "AAAA"}})); + BOOST_CHECK_EQUAL(inputs[1], (InputSpec{"timer-stats", "DS", "TIMER-dispatcher", 0, Lifetime::Timer})); + } + + { + // policy3 includes 1 and 2, so we should have only one inputspec for data, one for timer + // same as before, but different order of registration + Dispatcher dispatcher("dispatcher", ""); + auto policy1 = std::make_unique<DataSamplingPolicy>("policy1"); + policy1->registerPath({"vcxz", "TST", "AAAA", 0}, {{"erwv"}, "DS", "AAAA"}); + + auto policy2 = std::make_unique<DataSamplingPolicy>("policy2"); + policy2->registerPath({"fdsa", "TST", "AAAA", 0}, {{"fdsf"}, "DS", "BBBB"}); + + auto policy3 = std::make_unique<DataSamplingPolicy>("policy3"); + policy3->registerPath({"asdf", {"TST", "AAAA"}}, {{"erwv"}, "DS", "CCCC"}); + + dispatcher.registerPolicy(std::move(policy3)); + dispatcher.registerPolicy(std::move(policy1)); + dispatcher.registerPolicy(std::move(policy2)); + + auto inputs = dispatcher.getInputSpecs(); + + BOOST_REQUIRE_EQUAL(inputs.size(), 2); + BOOST_CHECK_EQUAL(inputs[0], (InputSpec{"asdf", {"TST", "AAAA"}})); + BOOST_CHECK_EQUAL(inputs[1], (InputSpec{"timer-stats", "DS", "TIMER-dispatcher", 0, Lifetime::Timer})); + } + + { + // three different inputs + timer + Dispatcher dispatcher("dispatcher", ""); + auto policy1 = std::make_unique<DataSamplingPolicy>("policy1"); + policy1->registerPath({"vcxz", "TST", "AAAA", 0}, {{"erwv"}, "DS", "AAAA"}); + + auto policy2 = std::make_unique<DataSamplingPolicy>("policy2"); + policy2->registerPath({"sfsd", "TST", "BBBB", 0}, {{"fdsf"}, "DS", "BBBB"}); + + auto policy3 = std::make_unique<DataSamplingPolicy>("policy3"); + policy3->registerPath({"asdf", {"TST", "CCCC"}}, {{"erwv"}, "DS", "CCCC"}); + + dispatcher.registerPolicy(std::move(policy1)); + dispatcher.registerPolicy(std::move(policy2)); + dispatcher.registerPolicy(std::move(policy3)); + + auto inputs = dispatcher.getInputSpecs(); + + BOOST_REQUIRE_EQUAL(inputs.size(), 4); + BOOST_CHECK_EQUAL(inputs[0], (InputSpec{"vcxz", "TST", "AAAA"})); + BOOST_CHECK_EQUAL(inputs[1], (InputSpec{"sfsd", "TST", "BBBB"})); + BOOST_CHECK_EQUAL(inputs[2], (InputSpec{"asdf", {"TST", "CCCC"}})); + BOOST_CHECK_EQUAL(inputs[3], (InputSpec{"timer-stats", "DS", "TIMER-dispatcher", 0, Lifetime::Timer})); + } +} diff --git a/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx b/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx index 4e81c58868aa0..5f65e5be3e67b 100644 --- a/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx @@ -14,12 +14,14 @@ #include <boost/test/unit_test.hpp> #include <boost/property_tree/ptree.hpp> +#include "DataSampling/DataSamplingConditionFactory.h" #include "DataSampling/DataSamplingPolicy.h" #include "Framework/DataRef.h" #include "Framework/DataProcessingHeader.h" using namespace o2::framework; using namespace o2::utilities; +using namespace o2::header; // an example of DataSamplingPolicy JSON object // { @@ -29,19 +31,7 @@ using namespace o2::utilities; // "aidlalala1", // "aidlalala2" // ] -// "dataHeaders" : [ -// { -// "binding" : "clusters", -// "dataOrigin" : "TPC", -// "dataDescription" : "CLUSTERS" -// }, -// { -// "binding" : "tracks", -// "dataOrigin" : "TPC", -// "dataDescription" : "TRACKS" -// } -// ], -// "subSpec" : "*", +// "query" : "c:TST/CHLEB/33;m:TST/MLEKO/33", // "samplingConditions" : [ // { // "condition" : "random", @@ -52,10 +42,9 @@ using namespace o2::utilities; // "blocking" : "false" // } -BOOST_AUTO_TEST_CASE(DataSamplingPolicyConfiguration) +BOOST_AUTO_TEST_CASE(DataSamplingPolicyFromConfiguration) { using boost::property_tree::ptree; - DataSamplingPolicy policy; ptree config; config.put("id", "my_policy"); @@ -70,28 +59,57 @@ BOOST_AUTO_TEST_CASE(DataSamplingPolicyConfiguration) config.add_child("samplingConditions", samplingConditions); config.put("blocking", "false"); - policy.configure(config); + { + auto policy = std::move(DataSamplingPolicy::fromConfiguration(config)); - BOOST_CHECK_EQUAL(policy.getName(), "my_policy"); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "my_policy0", 33})); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "my_policy1", 33})); - const auto& map = policy.getPathMap(); - BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "CHLEB", 33})).second == (OutputSpec{"DS", "my_policy0", 33})); - BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "MLEKO", 33})).second == (OutputSpec{"DS", "my_policy1", 33})); - BOOST_CHECK_EQUAL(map.size(), 2); + BOOST_CHECK_EQUAL(policy.getName(), "my_policy"); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "my_policy0", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "my_policy1", 33})); + const auto& map = policy.getPathMap(); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "CHLEB", 33})).second == (OutputSpec{"DS", "my_policy0", 33})); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "MLEKO", 33})).second == (OutputSpec{"DS", "my_policy1", 33})); + BOOST_CHECK_EQUAL(map.size(), 2); - BOOST_CHECK(policy.match(ConcreteDataMatcher{"TST", "CHLEB", 33})); - BOOST_CHECK(!policy.match(ConcreteDataMatcher{"TST", "SZYNKA", 33})); + BOOST_CHECK(policy.match(ConcreteDataMatcher{"TST", "CHLEB", 33})); + BOOST_CHECK(!policy.match(ConcreteDataMatcher{"TST", "SZYNKA", 33})); - DataProcessingHeader dph{555, 0}; - o2::header::Stack headerStack{dph}; - DataRef dr{nullptr, reinterpret_cast<const char*>(headerStack.data()), nullptr}; - policy.decide(dr); // just make sure it does not crash + DataProcessingHeader dph{555, 0}; + o2::header::Stack headerStack{dph}; + DataRef dr{nullptr, reinterpret_cast<const char*>(headerStack.data()), nullptr}; + policy.decide(dr); // just make sure it does not crash + } config.put("id", "too-long-policy-name"); - policy.configure(config); - BOOST_CHECK_EQUAL(policy.getName(), "too-long-polic"); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "too-long-polic0", 33})); - BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "too-long-polic1", 33})); - BOOST_CHECK_EQUAL(policy.getPathMap().size(), 2); // previous paths should be cleared + + { + auto policy = std::move(DataSamplingPolicy::fromConfiguration(config)); + BOOST_CHECK_EQUAL(policy.getName(), "too-long-policy-name"); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "too-long-polic0", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "too-long-polic1", 33})); + } } + +BOOST_AUTO_TEST_CASE(DataSamplingPolicyFromMethods) +{ + DataSamplingPolicy policy("my_policy"); + auto conditionNConsecutive = DataSamplingConditionFactory::create("nConsecutive"); + BOOST_REQUIRE(conditionNConsecutive); + + boost::property_tree::ptree config; + config.put("samplesNumber", 3); + config.put("cycleSize", 10); + conditionNConsecutive->configure(config); + + policy.registerCondition(std::move(conditionNConsecutive)); + + policy.registerPath({"tststs", {"TST", "CHLEB"}}, {{"asdf"}, "AA", "BBBB"}); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"AA", "BBBB", 33})); +} + +BOOST_AUTO_TEST_CASE(DataSamplingPolicyStaticMethods) +{ + BOOST_CHECK(DataSamplingPolicy::createPolicyDataOrigin() == DataOrigin("DS")); + BOOST_CHECK(DataSamplingPolicy::createPolicyDataDescription("asdf", 0) == DataDescription("asdf0")); + BOOST_CHECK(DataSamplingPolicy::createPolicyDataDescription("asdfasdfasdfasdf", 0) == DataDescription("asdfasdfasdfas0")); + BOOST_CHECK(DataSamplingPolicy::createPolicyDataDescription("asdfasdfasdfasdf", 10) == DataDescription("asdfasdfasdfas10")); +} \ No newline at end of file From 60ee0bf8b63048efe8d1ac5899755b5380ec5f52 Mon Sep 17 00:00:00 2001 From: Piotr Konopka <piotr.jan.konopka@cern.ch> Date: Thu, 15 Oct 2020 15:37:24 +0200 Subject: [PATCH 0982/1751] Try to avoid macOS build complaints --- Utilities/DataSampling/src/Dispatcher.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Utilities/DataSampling/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx index f5e753de1e9d5..4859d29b0fbc9 100644 --- a/Utilities/DataSampling/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -202,12 +202,11 @@ Inputs Dispatcher::getInputSpecs() // Add data inputs. Avoid duplicates and inputs which include others (e.g. "TST/DATA" includes "TST/DATA/1". for (const auto& policy : mPolicies) { - for (const auto& [potentiallyNewInput, _policyOutput] : policy->getPathMap()) { - (void)_policyOutput; + for (const auto& path : policy->getPathMap()) { + auto& potentiallyNewInput = path.first; // The idea is that we remove all existing inputs which are covered by the potentially new input. // If there are none which are broader than the new one, then we add it. - // I hope this is enough for all corner cases, but I am not 100% sure. auto newInputIsBroader = [&potentiallyNewInput](const InputSpec& other) { return DataSpecUtils::includes(potentiallyNewInput, other); }; From 1f6c294b9fe53063d9c9e07444c80314300bbdf5 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 27 Jul 2020 19:02:03 +0200 Subject: [PATCH 0983/1751] Add electronics delay parameters --- Detectors/MUON/MID/Raw/CMakeLists.txt | 1 + .../MID/Raw/include/MIDRaw/ElectronicsDelay.h | 40 ++++++++++++ .../MUON/MID/Raw/src/ElectronicsDelay.cxx | 65 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 Detectors/MUON/MID/Raw/include/MIDRaw/ElectronicsDelay.h create mode 100644 Detectors/MUON/MID/Raw/src/ElectronicsDelay.cxx diff --git a/Detectors/MUON/MID/Raw/CMakeLists.txt b/Detectors/MUON/MID/Raw/CMakeLists.txt index 8c63889365a96..714fda4cd856c 100644 --- a/Detectors/MUON/MID/Raw/CMakeLists.txt +++ b/Detectors/MUON/MID/Raw/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library( src/CrateMapper.cxx src/CrateMasks.cxx src/Decoder.cxx + src/ElectronicsDelay.cxx src/ELinkDecoder.cxx src/Encoder.cxx src/FEEIdConfig.cxx diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/ElectronicsDelay.h b/Detectors/MUON/MID/Raw/include/MIDRaw/ElectronicsDelay.h new file mode 100644 index 0000000000000..a689ed2a6d033 --- /dev/null +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/ElectronicsDelay.h @@ -0,0 +1,40 @@ +// 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 MIDRaw/ElectronicsDelay.h +/// \brief Delay parameters for MID electronics +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 27 July 2020 +#ifndef O2_MID_ELECTRONICSDELAY_H +#define O2_MID_ELECTRONICSDELAY_H + +#include <cstdint> +#include <iostream> + +namespace o2 +{ +namespace mid +{ + +struct ElectronicsDelay { + // The delays are in local clocks, and correspond to the LHC clocks (aka BCs) + uint16_t calibToFET{9}; + uint16_t BCToLocal{0}; + uint16_t regToLocal{6}; +}; + +std::ostream& operator<<(std::ostream& os, const ElectronicsDelay& delay); + +ElectronicsDelay readElectronicsDelay(const char* filename); + +} // namespace mid +} // namespace o2 + +#endif /* O2_MID_ELECTRONICSDELAY_H */ diff --git a/Detectors/MUON/MID/Raw/src/ElectronicsDelay.cxx b/Detectors/MUON/MID/Raw/src/ElectronicsDelay.cxx new file mode 100644 index 0000000000000..48a7955e2ef5d --- /dev/null +++ b/Detectors/MUON/MID/Raw/src/ElectronicsDelay.cxx @@ -0,0 +1,65 @@ +// 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 MIDRaw/ElectronicsDelay.cxx +/// \brief Delay parameters for MID electronics +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 27 July 2020 + +#include "MIDRaw/ElectronicsDelay.h" + +#include <algorithm> +#include <fstream> +#include <string> + +namespace o2 +{ +namespace mid +{ + +std::ostream& operator<<(std::ostream& os, const ElectronicsDelay& delay) +{ + /// Output streamer for ElectronicsDelay + os << "calibToFET: " << delay.calibToFET << "\n"; + os << "BCToLocal: " << delay.BCToLocal << "\n"; + os << "regToLocal: " << delay.regToLocal << "\n"; + return os; +} + +ElectronicsDelay readElectronicsDelay(const char* filename) +{ + /// Reads the electronic delays from file + ElectronicsDelay electronicsDelay; + std::ifstream inFile(filename); + if (inFile.is_open()) { + std::string line; + while (std::getline(inFile, line)) { + line.erase(std::remove_if(line.begin(), line.end(), [](unsigned char x) { return std::isspace(x); }), line.end()); + auto pos = line.find(":"); + if (pos != std::string::npos) { + std::string key = line.substr(0, pos); + uint16_t val = std::atoi(line.substr(pos + 1).c_str()); + if (key == "calibToFET") { + electronicsDelay.calibToFET = val; + } else if (key == "BCToLocal") { + electronicsDelay.BCToLocal = val; + } else if (key == "regToLocal") { + electronicsDelay.regToLocal = val; + } + } + } + } else { + std::cout << "Error: cannot open file " << filename << std::endl; + } + return electronicsDelay; +} + +} // namespace mid +} // namespace o2 From ed61ebd66c534c1245e02eaac75dc3383df03856 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 27 Jul 2020 19:04:34 +0200 Subject: [PATCH 0984/1751] Use configurable electronics delay in MID raw decoder/encoder --- Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h | 7 +++++++ .../MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h | 4 ++++ .../MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h | 5 +++++ .../MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h | 4 ++++ .../MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h | 12 ++++++++---- Detectors/MUON/MID/Raw/src/Decoder.cxx | 3 ++- Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx | 10 ++++------ Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx | 7 +++---- 8 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h index b872acaa9be81..e3312a6c5aab1 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h @@ -20,8 +20,10 @@ #include <array> #include <gsl/gsl> #include "DataFormatsMID/ROFRecord.h" +#include "DetectorsRaw/RDHUtils.h" #include "MIDRaw/CrateMasks.h" #include "MIDRaw/CrateParameters.h" +#include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/FEEIdConfig.h" #include "MIDRaw/GBTBareDecoder.h" #include "MIDRaw/GBTUserLogicDecoder.h" @@ -38,8 +40,12 @@ class Decoder public: Decoder(); ~Decoder() = default; + /// Sets the FEE ID config file void setFeeIdConfig(const FEEIdConfig& feeIdConfig) { mFEEIdConfig = feeIdConfig; } + /// Sets the crate masks void setCrateMasks(const CrateMasks& masks) { mMasks = masks; } + /// Sets the electronics delays + void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } void init(bool isDebugMode = false); void process(gsl::span<const uint8_t> bytes); template <typename RDH = o2::header::RAWDataHeader> @@ -67,6 +73,7 @@ class Decoder std::array<GBTDECODER, crateparams::sNGBTs> mGBTDecoders{}; /// GBT decoders FEEIdConfig mFEEIdConfig{}; /// Crate FEEID mapper CrateMasks mMasks{}; /// Crate masks + ElectronicsDelay mElectronicsDelay{}; /// Delay in the electronics }; } // namespace mid diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h index db5289ef12287..b53a2701a091e 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h @@ -21,6 +21,7 @@ #include <gsl/gsl> #include "DataFormatsMID/ROFRecord.h" #include "MIDRaw/CrateParameters.h" +#include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/ELinkDecoder.h" #include "MIDRaw/GBTOutputHandler.h" #include "MIDRaw/LocalBoardRO.h" @@ -45,6 +46,9 @@ class GBTBareDecoder /// Clears the decoded data void clear() { mOutputHandler.clear(); } + /// Sets the delay in the electronics + void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mOutputHandler.setElectronicsDelay(electronicsDelay); } + private: GBTOutputHandler mOutputHandler{}; /// GBT output handler uint8_t mMask{0xFF}; /// GBT mask diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h index 56d32fce3919b..e153da3e91536 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h @@ -21,6 +21,7 @@ #include "CommonDataFormat/InteractionRecord.h" #include "DataFormatsMID/ROFRecord.h" #include "MIDRaw/CrateParameters.h" +#include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/ELinkDecoder.h" #include "MIDRaw/LocalBoardRO.h" @@ -41,6 +42,9 @@ class GBTOutputHandler void onDoneReg(size_t, const ELinkDecoder&){}; /// Dummy function void onDoneRegDebug(size_t ilink, const ELinkDecoder& decoder); + /// Sets the delay in the electronics + void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } + /// Gets the vector of data const std::vector<LocalBoardRO>& getData() const { return mData; } @@ -55,6 +59,7 @@ class GBTOutputHandler uint16_t mFeeId{0}; /// FEE ID InteractionRecord mIRFirstPage{}; /// Interaction record of the first page uint16_t mReceivedCalibration{0}; /// Word with one bit per e-link indicating if the calibration trigger was received by the e-link + ElectronicsDelay mElectronicsDelay{}; /// Delays in the electronics std::array<InteractionRecord, crateparams::sNELinksPerGBT> mIRs{}; /// Interaction records per link std::array<uint16_t, crateparams::sNELinksPerGBT> mExpectedFETClock{}; /// Expected FET clock diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h index 42bb55a156698..8899c0176600d 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h @@ -20,6 +20,7 @@ #include <gsl/gsl> #include "DetectorsRaw/RDHUtils.h" #include "DataFormatsMID/ROFRecord.h" +#include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/ELinkDecoder.h" #include "MIDRaw/GBTOutputHandler.h" #include "MIDRaw/LocalBoardRO.h" @@ -50,6 +51,9 @@ class GBTUserLogicDecoder /// Clears the decoded data void clear() { mOutputHandler.clear(); } + /// Sets the delay in the electronics + void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mOutputHandler.setElectronicsDelay(electronicsDelay); } + private: GBTOutputHandler mOutputHandler{}; /// GBT output handler diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h index 9e5c78872e919..e853b759428ec 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h @@ -18,8 +18,8 @@ #include <cstdint> #include <vector> #include <gsl/gsl> -#include "Headers/RAWDataHeader.h" #include "DataFormatsMID/ROFRecord.h" +#include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/LocalBoardRO.h" namespace o2 @@ -47,6 +47,9 @@ class GBTUserLogicEncoder /// Clears the buffer void clear() { mBytes.clear(); } + /// Sets the delay in the electronics + void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } + private: /// Adds the board id and the fired chambers inline void addIdAndChambers(uint8_t id, uint8_t firedChambers) { mBytes.emplace_back((id << 4) | firedChambers); } @@ -57,9 +60,10 @@ class GBTUserLogicEncoder void addShort(uint16_t shortWord); bool checkAndAdd(gsl::span<const LocalBoardRO> data, uint16_t bc, uint8_t triggerWord); - std::vector<uint8_t> mBytes{}; /// Vector with encoded information - uint16_t mFeeId{0}; /// FEE ID - uint8_t mMask{0xFF}; /// GBT mask + std::vector<uint8_t> mBytes{}; /// Vector with encoded information + uint16_t mFeeId{0}; /// FEE ID + uint8_t mMask{0xFF}; /// GBT mask + ElectronicsDelay mElectronicsDelay; /// Delays in the electronics }; } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/Decoder.cxx b/Detectors/MUON/MID/Raw/src/Decoder.cxx index 5cd6b8491e98e..9f71c784047ca 100644 --- a/Detectors/MUON/MID/Raw/src/Decoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Decoder.cxx @@ -15,7 +15,7 @@ #include "MIDRaw/Decoder.h" -#include "Headers/RAWDataHeader.h" +#include "Headers/RDHAny.h" #include "DPLUtils/RawParser.h" namespace o2 @@ -48,6 +48,7 @@ void Decoder<GBTDECODER>::init(bool isDebugMode) } else { mGBTDecoders[igbt].init(igbt, isDebugMode); } + mGBTDecoders[igbt].setElectronicsDelay(mElectronicsDelay); } } diff --git a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx index 5006514c5dcfe..b65d4b2934061 100644 --- a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx @@ -15,8 +15,6 @@ #include "MIDRaw/GBTOutputHandler.h" -#include "RawInfo.h" - namespace o2 { namespace mid @@ -64,7 +62,7 @@ bool GBTOutputHandler::checkLoc(size_t ilink, const ELinkDecoder& decoder) EventType GBTOutputHandler::processSelfTriggered(size_t ilink, uint16_t localClock, uint16_t& correctedClock) { /// Processes the self-triggered event - correctedClock = localClock - sDelayBCToLocal; + correctedClock = localClock - mElectronicsDelay.BCToLocal; uint16_t linkMask = 1 << ilink; if ((mReceivedCalibration & linkMask) && (localClock == mExpectedFETClock[ilink])) { // Reset the calibration flag for this e-link @@ -77,7 +75,7 @@ EventType GBTOutputHandler::processSelfTriggered(size_t ilink, uint16_t localClo EventType GBTOutputHandler::processCalibrationTrigger(size_t ilink, uint16_t localClock) { /// Processes the calibration event - mExpectedFETClock[ilink] = localClock + sDelayCalibToFET; + mExpectedFETClock[ilink] = localClock + mElectronicsDelay.calibToFET; mReceivedCalibration |= (1 << ilink); return EventType::Noise; } @@ -191,7 +189,7 @@ void GBTOutputHandler::onDoneRegDebug(size_t ilink, const ELinkDecoder& decoder) InteractionRecord intRec(mIRs[ilink].bc + correctedClock, orbit); if (decoder.getTriggerWord() == 0) { - if (intRec.bc < sDelayRegToLocal) { + if (intRec.bc < mElectronicsDelay.regToLocal) { // In the tests, the HB does not really correspond to a change of orbit // So we need to keep track of the last clock at which the HB was received // and come back to that value @@ -202,7 +200,7 @@ void GBTOutputHandler::onDoneRegDebug(size_t ilink, const ELinkDecoder& decoder) // In this case the regional card needs to wait to receive the tracklet decision of each local // which result in a delay that needs to be subtracted if we want to be able to synchronize // local and regional cards for the checks - intRec -= sDelayRegToLocal; + intRec -= mElectronicsDelay.regToLocal; } mROFRecords.emplace_back(intRec, eventType, firstEntry, 1); } diff --git a/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx b/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx index ff3dd4541f18a..8e7259764d32a 100644 --- a/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx @@ -16,7 +16,6 @@ #include "MIDRaw/GBTUserLogicEncoder.h" #include "MIDRaw/CrateParameters.h" -#include "RawInfo.h" namespace o2 { @@ -93,7 +92,7 @@ void GBTUserLogicEncoder::addReg(uint16_t bc, uint8_t triggerWord, uint8_t id, u mBytes.emplace_back(triggerWord); uint16_t localClock = bc; if (triggerWord == 0) { - localClock += sDelayBCToLocal + sDelayRegToLocal; + localClock += mElectronicsDelay.BCToLocal + mElectronicsDelay.regToLocal; } addShort(localClock); addIdAndChambers(id + 8 * crateparams::getGBTIdInCrate(mFeeId), firedChambers); @@ -108,7 +107,7 @@ void GBTUserLogicEncoder::addLoc(const LocalBoardRO& loc, uint16_t bc, uint8_t t uint16_t localClock = bc; if (loc.triggerWord == 0) { - localClock += sDelayBCToLocal; + localClock += mElectronicsDelay.BCToLocal; } addShort(localClock); @@ -130,7 +129,7 @@ void GBTUserLogicEncoder::process(gsl::span<const LocalBoardRO> data, const uint checkAndAdd(data, bc, triggerWord); if (triggerWord == raw::sCALIBRATE) { // Add FET - checkAndAdd(data, bc + sDelayCalibToFET, 0); + checkAndAdd(data, bc + mElectronicsDelay.calibToFET, 0); } } From 18df31c7e6b571ad65f3b0345afe32af1c1174e4 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 27 Jul 2020 19:06:43 +0200 Subject: [PATCH 0985/1751] Use configurable electronic delays in GBT raw data checker --- Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h | 6 +++++- Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h | 5 +++++ Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx | 4 ++-- Detectors/MUON/MID/QC/src/RawDataChecker.cxx | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h b/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h index 6e25d85d787f6..38b85395510a8 100644 --- a/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h +++ b/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h @@ -18,11 +18,11 @@ #include <cstdint> #include <map> #include <string> -#include <tuple> #include <vector> #include <unordered_map> #include <gsl/gsl> #include "DataFormatsMID/ROFRecord.h" +#include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/LocalBoardRO.h" namespace o2 @@ -44,6 +44,9 @@ class GBTRawDataChecker std::string getDebugMessage() const { return mDebugMsg; } void clear(); + /// Sets the delay in the electronics + void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } + private: struct Mask { std::array<uint16_t, 4> patternsBP{}; /// Bending plane mask @@ -84,6 +87,7 @@ class GBTRawDataChecker uint8_t mCrateMask{0xFF}; /// Crate mask uint16_t mFeeId{0}; /// FeeId uint16_t mResetVal{0}; /// Reset value + ElectronicsDelay mElectronicsDelay{}; /// Delays in the electronics std::map<o2::InteractionRecord, uint16_t> mTrigEvents{}; ///! Index of triggered events diff --git a/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h b/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h index 79e86091aecbc..d761bde848ee9 100644 --- a/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h +++ b/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h @@ -20,6 +20,7 @@ #include <gsl/gsl> #include "DataFormatsMID/ROFRecord.h" #include "MIDRaw/CrateMasks.h" +#include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/LocalBoardRO.h" #include "MIDQC/GBTRawDataChecker.h" @@ -42,9 +43,13 @@ class RawDataChecker std::string getDebugMessage() const { return mDebugMsg; } void clear(); + /// Sets the delay in the electronics + void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } + private: std::array<GBTRawDataChecker, crateparams::sNGBTs> mCheckers{}; /// GBT raw data checker std::string mDebugMsg{}; /// Debug message + ElectronicsDelay mElectronicsDelay{}; /// Delays in the electronics }; } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx b/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx index 5aa54a8f25309..d1def0c8d06de 100644 --- a/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx +++ b/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx @@ -392,7 +392,7 @@ bool GBTRawDataChecker::checkEvents(bool isTriggered) ++mStatistics[0]; if (!checkEvent(isTriggered, gbtEvent.regs, gbtEvent.locs)) { std::stringstream ss; - ss << std::hex << std::showbase << evtIdxItem.first; + ss << fmt::format("BCid: 0x{:x} Orbit: 0x{:x}", evtIdxItem.first.bc, evtIdxItem.first.orbit); if (!gbtEvent.pages.empty()) { ss << " [in"; for (auto& page : gbtEvent.pages) { @@ -446,7 +446,7 @@ bool GBTRawDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl:: board.triggerWord = 0; auto ir = rofIt->interactionRecord; if (id >= crateparams::sMaxNBoardsInLink) { - uint16_t delayRegLocal = 6; + uint16_t delayRegLocal = mElectronicsDelay.regToLocal; if (rofIt->interactionRecord.bc < delayRegLocal) { ir -= (constants::lhc::LHCMaxBunches - mResetVal - 1); } diff --git a/Detectors/MUON/MID/QC/src/RawDataChecker.cxx b/Detectors/MUON/MID/QC/src/RawDataChecker.cxx index 9f622534d2a1e..c8e97e10ad6e4 100644 --- a/Detectors/MUON/MID/QC/src/RawDataChecker.cxx +++ b/Detectors/MUON/MID/QC/src/RawDataChecker.cxx @@ -27,6 +27,7 @@ void RawDataChecker::init(const CrateMasks& crateMasks) { /// Initializes the checkers for (uint16_t igbt = 0; igbt < crateparams::sNGBTs; ++igbt) { + mCheckers[igbt].setElectronicsDelay(mElectronicsDelay); mCheckers[igbt].init(igbt, crateMasks.getMask(igbt)); } } From 274ecb2e4c2839e05ab7434451f309dc4d9358a3 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 27 Jul 2020 19:28:21 +0200 Subject: [PATCH 0986/1751] Use configurable electronic delays in raw-checker --- Detectors/MUON/MID/QC/exe/raw-checker.cxx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Detectors/MUON/MID/QC/exe/raw-checker.cxx b/Detectors/MUON/MID/QC/exe/raw-checker.cxx index 575f6a27c9504..733d8310bafd0 100644 --- a/Detectors/MUON/MID/QC/exe/raw-checker.cxx +++ b/Detectors/MUON/MID/QC/exe/raw-checker.cxx @@ -16,8 +16,9 @@ #include <iostream> #include <fstream> #include "boost/program_options.hpp" -#include "MIDRaw/FEEIdConfig.h" #include "MIDRaw/CrateMasks.h" +#include "MIDRaw/ElectronicsDelay.h" +#include "MIDRaw/FEEIdConfig.h" #include "MIDRaw/Decoder.h" #include "MIDRaw/RawFileReader.h" #include "MIDQC/RawDataChecker.h" @@ -58,6 +59,13 @@ int process(po::variables_map& vm) o2::mid::FEEIdConfig feeIdConfig(vm["feeId-config-file"].as<std::string>().c_str()); decoder.setFeeIdConfig(feeIdConfig); } + o2::mid::ElectronicsDelay electronicsDelay; + if (vm.count("electronics-delay-file")) { + o2::mid::ElectronicsDelay electronicsDelay = o2::mid::readElectronicsDelay(vm["electronics-delay-file"].as<std::string>().c_str()); + decoder.setElectronicsDelay(electronicsDelay); + checker.setElectronicsDelay(electronicsDelay); + } + if (vm.count("crate-masks-file")) { o2::mid::CrateMasks crateMasks(vm["crate-masks-file"].as<std::string>().c_str()); decoder.setCrateMasks(crateMasks); @@ -155,6 +163,7 @@ int main(int argc, char* argv[]) ("max-errors", po::value<unsigned long int>()->default_value(10000),"Maximum number of errors before aborting") ("feeId-config-file", po::value<std::string>(),"Filename with crate FEE ID correspondence") ("crate-masks-file", po::value<std::string>(),"Filename with crate masks") + ("electronics-delay-file", po::value<std::string>(),"Filename with electronics delay") ("output-dir", po::value<std::string>()->default_value(""),"Output directory") ("bare", po::value<bool>()->implicit_value(true),"Use bare decoder"); From 55ff104766f680e92644195e3369efb3a7392176 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 24 Feb 2020 13:50:44 +0100 Subject: [PATCH 0987/1751] Remove obsolete MID RawInfo.h --- Detectors/MUON/MID/Raw/src/RawInfo.h | 34 ---------------------------- 1 file changed, 34 deletions(-) delete mode 100644 Detectors/MUON/MID/Raw/src/RawInfo.h diff --git a/Detectors/MUON/MID/Raw/src/RawInfo.h b/Detectors/MUON/MID/Raw/src/RawInfo.h deleted file mode 100644 index 83b5505210650..0000000000000 --- a/Detectors/MUON/MID/Raw/src/RawInfo.h +++ /dev/null @@ -1,34 +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. - -/// \file MID/Raw/src/RawInfo.h -/// \brief Raw data format MID -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 30 September 2019 -#ifndef O2_MID_RAWINFO_H -#define O2_MID_RAWINFO_H - -#include <cstdint> - -namespace o2 -{ -namespace mid -{ - -/// Parameters for local board encoding/decoding -// The delays are in local clocks, and correspond to the LHC clocks (aka BCs) -static constexpr uint16_t sDelayCalibToFET = 10; -static constexpr uint16_t sDelayBCToLocal = 0; -static constexpr uint16_t sDelayRegToLocal = 3; - -} // namespace mid -} // namespace o2 - -#endif /* O2_MID_RAWINFO_H */ From e5431e477439a150941f2ecbab980d5709d1177c Mon Sep 17 00:00:00 2001 From: Piotr Konopka <piotr.jan.konopka@cern.ch> Date: Mon, 19 Oct 2020 12:24:35 +0200 Subject: [PATCH 0988/1751] adapt to the recent changes in dev --- Utilities/DataSampling/src/DataSampling.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/DataSampling/src/DataSampling.cxx b/Utilities/DataSampling/src/DataSampling.cxx index 73988d2afb58b..f0bc702703793 100644 --- a/Utilities/DataSampling/src/DataSampling.cxx +++ b/Utilities/DataSampling/src/DataSampling.cxx @@ -134,7 +134,7 @@ std::vector<InputSpec> DataSampling::InputSpecsForPolicy(std::shared_ptr<configu for (auto&& policyConfig : policiesTree) { if (policyConfig.second.get<std::string>("id") == policyName) { - DataSamplingPolicy policy(policyConfig.second); + auto policy = DataSamplingPolicy::fromConfiguration(policyConfig.second); for (const auto& path : policy.getPathMap()) { InputSpec input = DataSpecUtils::matchingInput(path.second); inputs.push_back(input); From e55ff3d9ccc9835caaaa805845f2997104a55a7e Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 19 Oct 2020 14:13:36 +0200 Subject: [PATCH 0989/1751] adding example of schema evolution (#4581) --- Analysis/Tutorials/CMakeLists.txt | 5 ++ Analysis/Tutorials/src/schemaEvolution.cxx | 89 ++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 Analysis/Tutorials/src/schemaEvolution.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index 33fa1fe87785e..c10c44a391a04 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -152,3 +152,8 @@ o2_add_dpl_workflow(muon-iteration SOURCES src/muonIteration.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(schema-evolution + SOURCES src/schemaEvolution.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/schemaEvolution.cxx b/Analysis/Tutorials/src/schemaEvolution.cxx new file mode 100644 index 0000000000000..8d126b86f34cb --- /dev/null +++ b/Analysis/Tutorials/src/schemaEvolution.cxx @@ -0,0 +1,89 @@ +// 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" + +// This example shows how schema evolution of tables can be implemented +// Here two tables are defined, EtaPhiV2 has an additional member compared to EtaPhiV1 +// It is shown how an example task can use a template, and can be instantiated to work +// on both. + +namespace o2::aod +{ +namespace etaphi +{ +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(AbsEta, absEta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +} // namespace etaphi +DECLARE_SOA_TABLE(EtaPhiV1, "AOD", "ETAPHI", etaphi::Eta, etaphi::Phi); +DECLARE_SOA_TABLE(EtaPhiV2, "AOD", "ETAPHIV2", etaphi::Eta, etaphi::AbsEta, etaphi::Phi); +} // namespace o2::aod + +using namespace o2; +using namespace o2::framework; + +// Producer of EtaPhiV1 +struct ATask { + Produces<aod::EtaPhiV1> etaphi; + + void process(aod::Tracks const& tracks) + { + for (auto& track : tracks) { + float phi = asin(track.snp()) + track.alpha() + static_cast<float>(M_PI); + float eta = log(tan(0.25f * static_cast<float>(M_PI) - 0.5f * atan(track.tgl()))); + + etaphi(eta, phi); + } + } +}; + +// Producer of EtaPhiV2 +struct BTask { + Produces<aod::EtaPhiV2> etaphi; + + void process(aod::Tracks const& tracks) + { + for (auto& track : tracks) { + float phi = asin(track.snp()) + track.alpha() + static_cast<float>(M_PI); + float eta = log(tan(0.25f * static_cast<float>(M_PI) - 0.5f * atan(track.tgl()))); + + etaphi(eta, std::abs(eta), phi); + } + } +}; + +// Consumper of both EtaPhiV1 and EtaPhiV2 +// InputTable is a template which is then specified below when the workflow is defined +template <typename InputTable> +struct CTask { + void process(InputTable const& etaPhis) + { + constexpr bool isV2 = std::is_same<InputTable, aod::EtaPhiV2>::value; + for (auto& etaPhi : etaPhis) { + LOGF(info, "(%f, %f)", etaPhi.eta(), etaPhi.phi()); + if constexpr (isV2) { + // This line is only compiled if this is templated with EtaPhiV2 + LOGF(info, "We have the new data model (%f)", etaPhi.absEta()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<ATask>("produce-etaphi-v1"), + adaptAnalysisTask<BTask>("produce-etaphi-v2"), + adaptAnalysisTask<CTask<aod::EtaPhiV1>>("consume-etaphi-v1"), // here CTask is added with EtaPhiV1 input + adaptAnalysisTask<CTask<aod::EtaPhiV2>>("consume-etaphi-v2"), // here CTask is added with EtaPhiV2 input + }; +} From 0a85af2064af114ee28abd2fd0a483da68df890e Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Mon, 5 Oct 2020 12:12:56 +0000 Subject: [PATCH 0990/1751] TPCClusterFinder: Set single-flag on created clusters to indicate single-pad or single-timebin cluster. --- GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx b/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx index 5405a720abc94..547301ae80a0c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/ClusterAccumulator.cxx @@ -22,12 +22,13 @@ GPUd() void ClusterAccumulator::toNative(const ChargePos& pos, Charge q, int min bool isEdgeCluster = CfUtils::isAtEdge(pos); bool wasSplitInTime = mSplitInTime >= minSplitNum; bool wasSplitInPad = mSplitInPad >= minSplitNum; + bool isSingleCluster = (mPadSigma == 0) || (mTimeSigma == 0); uchar flags = 0; flags |= (isEdgeCluster) ? tpc::ClusterNative::flagEdge : 0; flags |= (wasSplitInTime) ? tpc::ClusterNative::flagSplitTime : 0; flags |= (wasSplitInPad) ? tpc::ClusterNative::flagSplitPad : 0; - // TODO: set single flag! + flags |= (isSingleCluster) ? tpc::ClusterNative::flagSingle : 0; cn.qMax = q; cn.qTot = mQtot; From c1ea6a74954b91e4496176c664aa1cc59ac894eb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 19 Oct 2020 16:41:54 +0200 Subject: [PATCH 0991/1751] DPL: improve metrics for arrow messages (#4626) * Correctly account for the case in which there are no forwards. * Only count Arrow serialized messages. --- Framework/Core/src/CommonMessageBackends.cxx | 7 +++++-- Framework/Core/src/DataProcessingDevice.cxx | 2 +- Framework/Core/src/DataProcessor.cxx | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index 4a1056c50900f..968facc299a5a 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -107,14 +107,17 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() continue; } auto dh = o2::header::get<DataHeader*>(input.header); + if (dh->serialization != o2::header::gSerializationMethodArrow) { + continue; + } auto dph = o2::header::get<DataProcessingHeader*>(input.header); for (auto const& forward : ctx.services().get<DeviceSpec const>().forwards) { if (DataSpecUtils::match(forward.matcher, dh->dataOrigin, dh->dataDescription, dh->subSpecification) == true && (dph->startTime % forward.maxTimeslices) == forward.timeslice) { continue; } - arrow->updateBytesDestroyed(dh->payloadSize); - arrow->updateMessagesDestroyed(1); } + arrow->updateBytesDestroyed(dh->payloadSize); + arrow->updateMessagesDestroyed(1); } ctx.services().get<Monitoring>().send(Metric{(uint64_t)arrow->bytesDestroyed(), "arrow-bytes-destroyed"}.addTag(Key::Subsystem, Value::DPL)); ctx.services().get<Monitoring>().send(Metric{(uint64_t)arrow->messagesDestroyed(), "arrow-messages-destroyed"}.addTag(Key::Subsystem, Value::DPL)); diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index dd2e35c36ec5c..47735d9f6a51e 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -955,8 +955,8 @@ bool DataProcessingDevice::tryDispatchComputation(DataProcessorContext& context, context.registry->preProcessingCallbacks(processContext); } if (action.op == CompletionPolicy::CompletionOp::Discard) { + context.registry->postDispatchingCallbacks(processContext); if (context.spec->forwards.empty() == false) { - context.registry->postDispatchingCallbacks(processContext); forwardInputs(action.slot, record); continue; } diff --git a/Framework/Core/src/DataProcessor.cxx b/Framework/Core/src/DataProcessor.cxx index 1265717c45bd7..c26e5e89251f7 100644 --- a/Framework/Core/src/DataProcessor.cxx +++ b/Framework/Core/src/DataProcessor.cxx @@ -94,6 +94,7 @@ void DataProcessor::doSend(FairMQDevice& device, ArrowContext& context, ServiceR // exposing it to the user in the first place. DataHeader* dh = const_cast<DataHeader*>(cdh); dh->payloadSize = payload->GetSize(); + dh->serialization = o2::header::gSerializationMethodArrow; context.updateBytesSent(payload->GetSize()); context.updateMessagesSent(1); registry.get<Monitoring>().send(Metric{(uint64_t)context.bytesSent(), "arrow-bytes-created"}.addTag(Key::Subsystem, Value::DPL)); From ade60fa111d69d41d29b393dbb63f858ea1a1653 Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Tue, 20 Oct 2020 09:06:55 +0200 Subject: [PATCH 0992/1751] [QC-450] Allow for output proxy channels which aren't "downstream" (#4631) --- Framework/Core/src/ExternalFairMQDeviceProxy.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx index 176d50c3b0284..105b3b3acbc57 100644 --- a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx +++ b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx @@ -397,10 +397,10 @@ DataProcessorSpec specifyExternalFairMQDeviceProxy(char const* name, namespace { -// Decide where to sent the output. Everything to "downstream" for now -std::string decideChannel(InputSpec const&) +// Decide where to sent the output. Everything to "downstream" if there is such a channel. +std::string decideChannel(InputSpec const& input, const std::unordered_map<std::string, std::vector<FairMQChannel>>& channels) { - return "downstream"; + return channels.count("downstream") ? "downstream" : input.binding; } } // namespace @@ -420,7 +420,7 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, auto channelConfigurationChecker = [inputSpecs = std::move(inputSpecs), device]() { LOG(INFO) << "checking channel configuration"; for (auto const& spec : inputSpecs) { - auto channel = decideChannel(spec); + auto channel = decideChannel(spec, device->fChannels); if (device->fChannels.count(channel) == 0) { throw std::runtime_error("no corresponding output channel found for input '" + channel + "'"); } @@ -453,7 +453,7 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, } size_t payloadMsgSize = dh->payloadSize; - auto channel = decideChannel(*first.spec); + auto channel = decideChannel(*first.spec, device.fChannels); auto headerMessage = device.NewMessageFor(channel, index, headerMsgSize); memcpy(headerMessage->GetData(), part.header, headerMsgSize); auto payloadMessage = device.NewMessageFor(channel, index, payloadMsgSize); From 9b7f1f77a9132449d25ff3f78b8adcdfb8a6d4da Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 20 Oct 2020 10:37:05 +0200 Subject: [PATCH 0993/1751] DPL: add Lifetime::Signal to trigger processing on a signal (#4633) --- .../include/Framework/DataProcessingDevice.h | 1 + .../Core/include/Framework/DeviceState.h | 3 ++ Framework/Core/include/Framework/Lifetime.h | 16 ++++----- Framework/Core/src/DataProcessingDevice.cxx | 7 ++-- Framework/Core/src/DeviceSpecHelpers.cxx | 33 +++++++++++++++++++ Framework/Core/src/WorkflowHelpers.cxx | 4 +++ 6 files changed, 52 insertions(+), 12 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index 89d8dd90d9f20..4eccdc78fc676 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -133,6 +133,7 @@ class DataProcessingDevice : public FairMQDevice std::mutex mRegionInfoMutex; enum TerminationPolicy mErrorPolicy = TerminationPolicy::WAIT; /// What to do when an error arises bool mWasActive = false; /// Whether or not the device was active at last iteration. + bool mFirst = true; /// Whether or not this was the first iteration }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/DeviceState.h b/Framework/Core/include/Framework/DeviceState.h index a156f4553b6e9..b16d07e94dd4e 100644 --- a/Framework/Core/include/Framework/DeviceState.h +++ b/Framework/Core/include/Framework/DeviceState.h @@ -19,6 +19,7 @@ typedef struct uv_loop_s uv_loop_t; typedef struct uv_timer_s uv_timer_t; typedef struct uv_poll_s uv_poll_t; +typedef struct uv_signal_s uv_signal_t; namespace o2::framework { @@ -47,6 +48,8 @@ struct DeviceState { std::vector<uv_poll_t*> activeInputPollers; // The list of pollers for active output channels std::vector<uv_poll_t*> activeOutputPollers; + /// The list of active signal handlers + std::vector<uv_signal_t*> activeSignals; }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/Lifetime.h b/Framework/Core/include/Framework/Lifetime.h index 3c142d0afa081..6bad4de842d5e 100644 --- a/Framework/Core/include/Framework/Lifetime.h +++ b/Framework/Core/include/Framework/Lifetime.h @@ -7,12 +7,10 @@ // 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_LIFETIME_H -#define FRAMEWORK_LIFETIME_H +#ifndef O2_FRAMEWORK_LIFETIME_H_ +#define O2_FRAMEWORK_LIFETIME_H_ -namespace o2 -{ -namespace framework +namespace o2::framework { /// Possible Lifetime of objects being exchanged by the DPL. @@ -23,9 +21,9 @@ enum struct Lifetime { QA, Transient, Timer, - Enumeration + Enumeration, + Signal }; -} // namespace framework -} // namespace o2 -#endif +} // namespace o2::framework +#endif // O2_FRAMEWORK_LIFETIME_H_ diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 47735d9f6a51e..fe4e17d00a155 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -338,9 +338,9 @@ void DataProcessingDevice::InitTask() mState.activeInputPollers.push_back(poller); } // In case we do not have any input channel and we do not have - // any timers, we still wake up whenever we can send data to downstream + // any timers or signal watchers we still wake up whenever we can send data to downstream // devices to allow for enumerations. - if (mState.activeInputPollers.empty() && mState.activeTimers.empty()) { + if (mState.activeInputPollers.empty() && mState.activeTimers.empty() && mState.activeSignals.empty()) { for (auto& x : fChannels) { if (x.first.rfind("from_internal-dpl", 0) == 0) { LOG(debug) << x.first << " is an internal channel. Not polling." << std::endl; @@ -432,7 +432,8 @@ bool DataProcessingDevice::ConditionalRun() if (mState.loop) { ZoneScopedN("uv idle"); TracyPlot("past activity", (int64_t)mWasActive); - uv_run(mState.loop, mWasActive && (mDataProcessorContexes.at(0).state->streaming != StreamingState::Idle) ? UV_RUN_NOWAIT : UV_RUN_ONCE); + uv_run(mState.loop, (mFirst == true) || (mWasActive && (mDataProcessorContexes.at(0).state->streaming != StreamingState::Idle) && (mState.activeSignals.empty())) ? UV_RUN_NOWAIT : UV_RUN_ONCE); + mFirst = false; } // Notify on the main thread the new region callbacks, making sure diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 56d9f94d64086..f6513e2b01984 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -39,6 +39,7 @@ #include <sys/time.h> #include <sys/resource.h> +#include <csignal> namespace bpo = boost::program_options; @@ -53,6 +54,11 @@ void timer_callback(uv_timer_t*) { // We simply wake up the event loop. Nothing to be done here. } + +void signal_callback(uv_signal_t*, int) +{ + // We simply wake up the event loop. Nothing to be done here. +} } // namespace detail struct ExpirationHandlerHelpers { @@ -78,6 +84,27 @@ struct ExpirationHandlerHelpers { }; } + static RouteConfigurator::CreationConfigurator signalDrivenConfigurator(InputSpec const& matcher, size_t inputTimeslice, size_t maxInputTimeslices) + { + return [matcher, inputTimeslice, maxInputTimeslices](DeviceState& state, ConfigParamRegistry const& options) { + std::string startName = std::string{"start-value-"} + matcher.binding; + std::string endName = std::string{"end-value-"} + matcher.binding; + std::string stepName = std::string{"step-value-"} + matcher.binding; + auto start = options.get<int64_t>(startName.c_str()); + auto stop = options.get<int64_t>(endName.c_str()); + auto step = options.get<int64_t>(stepName.c_str()); + // We create a timer to wake us up. Notice the actual + // timeslot creation and record expiration still happens + // in a synchronous way. + uv_signal_t* sh = (uv_signal_t*)(malloc(sizeof(uv_signal_t))); + uv_signal_init(state.loop, sh); + uv_signal_start(sh, detail::signal_callback, SIGUSR1); + state.activeSignals.push_back(sh); + + return LifetimeHelpers::enumDrivenCreation(start, stop, step, inputTimeslice, maxInputTimeslices); + }; + } + static RouteConfigurator::CreationConfigurator enumDrivenConfigurator(InputSpec const& matcher, size_t inputTimeslice, size_t maxInputTimeslices) { return [matcher, inputTimeslice, maxInputTimeslices](DeviceState&, ConfigParamRegistry const& options) { @@ -591,6 +618,12 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices, ExpirationHandlerHelpers::danglingEnumerationConfigurator(inputSpec), ExpirationHandlerHelpers::expiringEnumerationConfigurator(inputSpec, sourceChannel)}; break; + case Lifetime::Signal: + route.configurator = { + ExpirationHandlerHelpers::signalDrivenConfigurator(inputSpec, consumerDevice.inputTimesliceId, consumerDevice.maxInputTimeslices), + ExpirationHandlerHelpers::danglingEnumerationConfigurator(inputSpec), + ExpirationHandlerHelpers::expiringEnumerationConfigurator(inputSpec, sourceChannel)}; + break; case Lifetime::Transient: route.configurator = { ExpirationHandlerHelpers::dataDrivenConfigurator(), diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 8d7ea47d1bb1b..702b7514b139c 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -253,6 +253,10 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } timer.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec, Lifetime::Timer}); } break; + case Lifetime::Signal: { + auto concrete = DataSpecUtils::asConcreteDataMatcher(input); + timer.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec, Lifetime::Signal}); + } break; case Lifetime::Enumeration: { auto concrete = DataSpecUtils::asConcreteDataMatcher(input); timer.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec, Lifetime::Enumeration}); From cd287724c3098c7a1edf6f38a3c5dde25dfcd65f Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Tue, 20 Oct 2020 12:52:50 +0200 Subject: [PATCH 0994/1751] DPL Analysis: use index-builder similar to aod-spawner for predefined index tables (#4630) --- .../Core/include/Framework/AODReaderHelpers.h | 1 + Framework/Core/include/Framework/ASoA.h | 17 +++- .../include/Framework/AnalysisDataModel.h | 6 +- .../Core/include/Framework/AnalysisTask.h | 31 ++++++- Framework/Core/src/AODReaderHelpers.cxx | 91 +++++++++++++++++-- Framework/Core/src/AnalysisManagers.h | 4 +- Framework/Core/src/WorkflowHelpers.cxx | 57 ++++++++++++ 7 files changed, 191 insertions(+), 16 deletions(-) diff --git a/Framework/Core/include/Framework/AODReaderHelpers.h b/Framework/Core/include/Framework/AODReaderHelpers.h index 3016f07200fb2..f428f46bce6f5 100644 --- a/Framework/Core/include/Framework/AODReaderHelpers.h +++ b/Framework/Core/include/Framework/AODReaderHelpers.h @@ -65,6 +65,7 @@ struct RuntimeWatchdog { struct AODReaderHelpers { static AlgorithmSpec rootFileReaderCallback(); static AlgorithmSpec aodSpawnerCallback(std::vector<InputSpec> requested); + static AlgorithmSpec indexBuilderCallback(std::vector<InputSpec> requested); }; } // namespace o2::framework::readers diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 1f726cbd9ca62..41f98f2f7d304 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -25,6 +25,7 @@ #include <arrow/compute/kernel.h> #include <gandiva/selection_vector.h> #include <cassert> +#include <fmt/format.h> using o2::framework::runtime_error_f; @@ -1050,6 +1051,7 @@ class TableMetadata static constexpr char const* tableLabel() { return INHERIT::mLabel; } static constexpr char const (&origin())[4] { return INHERIT::mOrigin; } static constexpr char const (&description())[16] { return INHERIT::mDescription; } + static std::string sourceSpec() { return fmt::format("{}/{}/{}", INHERIT::mLabel, INHERIT::mOrigin, INHERIT::mDescription); }; }; template <typename... C1, typename... C2> @@ -1377,7 +1379,7 @@ constexpr auto is_binding_compatible_v() #define DECLARE_SOA_EXTENDED_TABLE_USER(_Name_, _Table_, _Description_, ...) \ DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "AOD", _Description_, __VA_ARGS__) -#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, ...) \ +#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, _Exclusive_, ...) \ struct _Name_ : o2::soa::IndexTable<_Key_, __VA_ARGS__> { \ _Name_(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : o2::soa::IndexTable<_Key_, __VA_ARGS__>(table, offset){}; \ _Name_(_Name_ const&) = default; \ @@ -1393,6 +1395,7 @@ constexpr auto is_binding_compatible_v() static constexpr char const* mLabel = #_Name_; \ static constexpr char const mOrigin[4] = _Origin_; \ static constexpr char const mDescription[16] = _Description_; \ + static constexpr bool exclusive = _Exclusive_; \ }; \ \ template <> \ @@ -1406,7 +1409,16 @@ constexpr auto is_binding_compatible_v() }; #define DECLARE_SOA_INDEX_TABLE(_Name_, _Key_, _Description_, ...) \ - DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, __VA_ARGS__) + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "IDX", _Description_, false, __VA_ARGS__) + +#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(_Name_, _Key_, _Description_, ...) \ + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "IDX", _Description_, true, __VA_ARGS__) + +#define DECLARE_SOA_INDEX_TABLE_USER(_Name_, _Key_, _Description_, ...) \ + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, false, __VA_ARGS__) + +#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE_USER(_Name_, _Key_, _Description_, ...) \ + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, true, __VA_ARGS__) namespace o2::soa { @@ -1767,6 +1779,7 @@ struct IndexTable : Table<soa::Index<>, H, Ts...> { using indexing_t = Key; using first_t = typename H::binding_t; using rest_t = framework::pack<typename Ts::binding_t...>; + using sources_t = framework::pack<Key, typename H::binding_t, typename Ts::binding_t...>; IndexTable(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : base_t{table, offset} diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 8e92461402b85..25d68cbd64766 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -608,14 +608,14 @@ DECLARE_SOA_INDEX_COLUMN(FDD, fdd); } // namespace indices #define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FV0CId, indices::FDDId -DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); #define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FDDId -DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MA_RN3_SP", INDEX_LIST_RUN3); -DECLARE_SOA_INDEX_TABLE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); DECLARE_SOA_INDEX_TABLE(BCCollisionsSparse, BCs, "MA_BCCOL_SP", indices::BCId, indices::CollisionId); } // namespace aod diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index eacdd9704566c..ca966d48cc726 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -53,13 +53,42 @@ struct AnalysisTask { // the contents of an AnalysisTask... struct AnalysisDataProcessorBuilder { + template <typename T> + static ConfigParamSpec getSpec() + { + if constexpr (soa::is_type_with_metadata_v<aod::MetadataTrait<T>>) { + return ConfigParamSpec{"input", VariantType::String, aod::MetadataTrait<T>::metadata::sourceSpec(), {"\"\""}}; + } else { + using O1 = framework::pack_element_t<0, typename T::originals>; + return ConfigParamSpec{"input", VariantType::String, aod::MetadataTrait<O1>::metadata::sourceSpec(), {"\"\""}}; + } + } + + template <typename... T> + static std::vector<ConfigParamSpec> getInputSpecs(framework::pack<T...>) + { + return std::vector{getSpec<T>()...}; + } + + template <typename T> + static std::vector<ConfigParamSpec> getIndexSources() + { + static_assert(soa::is_soa_index_table_t<T>::value, "Can only be used with IndexTable"); + return getInputSpecs(typename T::sources_t{}); + } + template <typename Arg> static void doAppendInputWithMetadata(std::vector<InputSpec>& inputs) { using metadata = typename aod::MetadataTrait<std::decay_t<Arg>>::metadata; static_assert(std::is_same_v<metadata, void> == false, "Could not find metadata. Did you register your type?"); - inputs.push_back({metadata::tableLabel(), metadata::origin(), metadata::description()}); + if constexpr (soa::is_soa_index_table_t<std::decay_t<Arg>>::value) { + auto inputSources = getIndexSources<std::decay_t<Arg>>(); + inputs.push_back(InputSpec{metadata::tableLabel(), metadata::origin(), metadata::description(), Lifetime::Timeframe, inputSources}); + } else { + inputs.push_back({metadata::tableLabel(), metadata::origin(), metadata::description()}); + } } template <typename... Args> diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index b341b4089b47e..6dc4350a0d8cb 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -8,8 +8,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/TableTreeHelpers.h" #include "Framework/AODReaderHelpers.h" +#include "Framework/TableTreeHelpers.h" +#include "Framework/AnalysisHelpers.h" #include "AnalysisDataModelHelpers.h" #include "DataProcessingHelpers.h" #include "ExpressionHelpers.h" @@ -41,16 +42,90 @@ namespace o2::framework::readers { -AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> requested) +auto setEOSCallback(InitContext& ic) +{ + ic.services().get<CallbackService>().set(CallbackService::Id::EndOfStream, + [](EndOfStreamContext& eosc) { + auto& control = eosc.services().get<ControlService>(); + control.endOfStream(); + control.readyToQuit(QuitRequest::Me); + }); +} + +template <typename O> +static inline auto extractTypedOriginal(ProcessingContext& pc) +{ + ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables + return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; +} + +template <typename... Os> +static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +{ + return std::make_tuple(extractTypedOriginal<Os>(pc)...); +} + +AlgorithmSpec AODReaderHelpers::indexBuilderCallback(std::vector<InputSpec> requested) { return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { - auto& callbacks = ic.services().get<CallbackService>(); - auto endofdatacb = [](EndOfStreamContext& eosc) { - auto& control = eosc.services().get<ControlService>(); - control.endOfStream(); - control.readyToQuit(QuitRequest::Me); + setEOSCallback(ic); + + return [requested](ProcessingContext& pc) { + auto outputs = pc.outputs(); + // spawn tables + for (auto& input : requested) { + auto description = std::visit( + overloaded{ + [](ConcreteDataMatcher const& matcher) { return matcher.description; }, + [](auto&&) { return header::DataDescription{""}; }}, + input.matcher); + + auto origin = std::visit( + overloaded{ + [](ConcreteDataMatcher const& matcher) { return matcher.origin; }, + [](auto&&) { return header::DataOrigin{""}; }}, + input.matcher); + + auto maker = [&](auto metadata) { + using metadata_t = decltype(metadata); + using Key = typename metadata_t::Key; + using index_pack_t = typename metadata_t::index_pack_t; + using sources = typename metadata_t::originals; + if constexpr (metadata_t::exclusive == true) { + return o2::framework::IndexExclusive::indexBuilder(index_pack_t{}, + extractTypedOriginal<Key>(pc), + extractOriginalsTuple(sources{}, pc)); + } else { + return o2::framework::IndexSparse::indexBuilder(index_pack_t{}, + extractTypedOriginal<Key>(pc), + extractOriginalsTuple(sources{}, pc)); + } + }; + + if (description == header::DataDescription{"MA_RN2_EX"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run2MatchedExclusiveMetadata{})); + } else if (description == header::DataDescription{"MA_RN2_SP"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run2MatchedSparseMetadata{})); + } else if (description == header::DataDescription{"MA_RN3_EX"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedExclusiveMetadata{})); + } else if (description == header::DataDescription{"MA_RN3_SP"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedSparseMetadata{})); + } else if (description == header::DataDescription{"MA_BCCOL_EX"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsExclusiveMetadata{})); + } else if (description == header::DataDescription{"MA_BCCOL_SP"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsSparseMetadata{})); + } else { + throw std::runtime_error("Not an index table"); + } + } }; - callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); + }}; +} + +AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> requested) +{ + return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { + setEOSCallback(ic); return [requested](ProcessingContext& pc) { auto outputs = pc.outputs(); diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index 33340b70640e9..c59225b8364d0 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -260,14 +260,14 @@ struct OutputManager<Spawns<T>> { /// Builds specialization template <typename O> -static auto extractTypedOriginal(ProcessingContext& pc) +static inline auto extractTypedOriginal(ProcessingContext& pc) { ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; } template <typename... Os> -static auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) { return std::make_tuple(extractTypedOriginal<Os>(pc)...); } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 702b7514b139c..631a972d7630b 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -161,6 +161,41 @@ void addMissingOutputsToSpawner(std::vector<InputSpec>&& requestedDYNs, } } +void addMissingOutputsToBuilder(std::vector<InputSpec>&& requestedIDXs, + std::vector<InputSpec>& requestedAODs, + DataProcessorSpec& publisher) +{ + auto inputSpecFromString = [](std::string s) { + std::regex word_regex("(\\w+)"); + auto words = std::sregex_iterator(s.begin(), s.end(), word_regex); + if (std::distance(words, std::sregex_iterator()) != 3) { + throw runtime_error_f("Malformed spec: %s", s.c_str()); + } + std::vector<std::string> data; + for (auto i = words; i != std::sregex_iterator(); ++i) { + data.emplace_back(i->str()); + } + char origin[4]; + char description[16]; + std::memcpy(&origin, data[1].c_str(), 4); + std::memcpy(&description, data[2].c_str(), 16); + return InputSpec{data[0], header::DataOrigin{origin}, header::DataDescription{description}}; + }; + + for (auto& input : requestedIDXs) { + auto concrete = DataSpecUtils::asConcreteDataMatcher(input); + publisher.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec}); + for (auto& i : input.metadata) { + auto spec = inputSpecFromString(i.defaultValue.get<std::string>()); + auto j = std::find_if(publisher.inputs.begin(), publisher.inputs.end(), [&](auto x) { return x.binding == spec.binding; }); + if (j == publisher.inputs.end()) { + publisher.inputs.push_back(spec); + } + requestedAODs.push_back(spec); + } + } +} + void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext const& ctx) { auto fakeCallback = AlgorithmSpec{[](InitContext& ic) { @@ -218,6 +253,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext std::vector<InputSpec> requestedAODs; std::vector<OutputSpec> providedAODs; std::vector<InputSpec> requestedDYNs; + std::vector<InputSpec> requestedIDXs; std::vector<InputSpec> requestedCCDBs; std::vector<OutputSpec> providedCCDBs; @@ -285,6 +321,11 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext requestedDYNs.emplace_back(input); } } + if (DataSpecUtils::partialMatch(input, header::DataOrigin{"IDX"})) { + if (std::find_if(requestedIDXs.begin(), requestedIDXs.end(), [&](InputSpec const& spec) { return input.binding == spec.binding; }) == requestedIDXs.end()) { + requestedIDXs.emplace_back(input); + } + } } std::stable_sort(timer.outputs.begin(), timer.outputs.end(), [](OutputSpec const& a, OutputSpec const& b) { return *DataSpecUtils::getOptionalSubSpec(a) < *DataSpecUtils::getOptionalSubSpec(b); }); @@ -320,6 +361,9 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext auto last = std::unique(requestedDYNs.begin(), requestedDYNs.end()); requestedDYNs.erase(last, requestedDYNs.end()); + last = std::unique(requestedIDXs.begin(), requestedIDXs.end()); + requestedIDXs.erase(last, requestedIDXs.end()); + DataProcessorSpec aodSpawner{ "internal-dpl-aod-spawner", {}, @@ -327,7 +371,16 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext readers::AODReaderHelpers::aodSpawnerCallback(requestedDYNs), {}}; + DataProcessorSpec indexBuilder{ + "internal-dpl-index-builder", + {}, + {}, + readers::AODReaderHelpers::indexBuilderCallback(requestedIDXs), + {}}; + addMissingOutputsToSpawner(std::move(requestedDYNs), requestedAODs, aodSpawner); + addMissingOutputsToBuilder(std::move(requestedIDXs), requestedAODs, indexBuilder); + addMissingOutputsToReader(providedAODs, requestedAODs, aodReader); addMissingOutputsToReader(providedCCDBs, requestedCCDBs, ccdbBackend); @@ -347,6 +400,10 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext extraSpecs.push_back(aodSpawner); } + if (indexBuilder.outputs.empty() == false) { + extraSpecs.push_back(indexBuilder); + } + if (aodReader.outputs.empty() == false) { extraSpecs.push_back(timePipeline(aodReader, ctx.options().get<int64_t>("readers"))); auto concrete = DataSpecUtils::asConcreteDataMatcher(aodReader.inputs[0]); From 162dc929c4a7690d4bdfaff116d6acf051fd1d6a Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Tue, 20 Oct 2020 14:41:43 +0200 Subject: [PATCH 0995/1751] Must reset TRM TDC error counter in case header/trailer is not detected (#4523) * Must reset TRM TDC error counter in case header/trailer is not detected * Stop decoding if error is found in CONET mode * Increase size of buffers and alloc them dynamically * Make sure we reset counters and flags in the most extreme error case * Add labels for the Diagnostic bits * Add DRM and TRM_DECODE_ERROR diagnostic check and bit --- .../DataFormatsTOF/CompressedDataFormat.h | 70 ++++++++++++++++++- .../include/TOFCompression/Compressor.h | 11 +-- .../include/TOFCompression/CompressorTask.h | 7 +- Detectors/TOF/compression/src/Compressor.cxx | 38 ++++++++++ .../TOF/compression/src/CompressorTask.cxx | 7 +- .../include/TOFReconstruction/DecoderBase.h | 3 +- 6 files changed, 123 insertions(+), 13 deletions(-) diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CompressedDataFormat.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CompressedDataFormat.h index d95372a05d318..ad00322500e81 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CompressedDataFormat.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CompressedDataFormat.h @@ -110,17 +110,48 @@ enum EDRMDiagnostic_t { DRM_FAULTSLOTMASK_NOTZERO = 1 << 11, DRM_READOUTTIMEOUT_NOTZERO = 1 << 12, DRM_EVENTWORDS_MISMATCH = 1 << 13, + DRM_DIAGNOSTIC_SPARE1 = 1 << 14, + DRM_DECODE_ERROR = 1 << 15, DRM_MAXDIAGNOSTIC_BIT = 1 << 16 // end before BIT(16) }; +static const char* DRMDiagnosticName[32] = { + "DRM_HAS_DATA", + "", + "", + "", + "DRM_HEADER_MISSING", + "DRM_TRAILER_MISSING", + "DRM_FEEID_MISMATCH", + "DRM_ORBIT_MISMATCH", + "DRM_CRC_MISMATCH", + "DRM_ENAPARTMASK_DIFFER", + "DRM_CLOCKSTATUS_WRONG", + "DRM_FAULTSLOTMASK_NOTZERO", + "DRM_READOUTTIMEOUT_NOTZERO", + "DRM_EVENTWORDS_MISMATCH", + "DRM_DIAGNOSTIC_SPARE1", + "DRM_DECODE_ERROR"}; + /** LTM diagnostic bits **/ enum ELTMDiagnostic_t { LTM_HEADER_MISSING = 1 << 4, // start from BIT(4) LTM_TRAILER_MISSING = 1 << 5, + LTM_DIAGNOSTIC_SPARE1 = 1 << 6, LTM_HEADER_UNEXPECTED = 1 << 7, LTM_MAXDIAGNOSTIC_BIT = 1 << 16 // end before BIT(16) }; +static const char* LTMDiagnosticName[32] = { + "LTM_HAS_DATA", + "", + "", + "", + "LTM_HEADER_MISSING", + "LTM_TRAILER_MISSING", + "LTM_DIAGNOSTIC_SPARE1", + "LTM_HEADER_UNEXPECTED"}; + /** TRM diagnostic bits, 12 bits [4-15] **/ enum ETRMDiagnostic_t { TRM_HEADER_MISSING = 1 << 4, // start from BIT(4) @@ -134,8 +165,9 @@ enum ETRMDiagnostic_t { TRM_EVENTWORDS_MISMATCH = 1 << 12, TRM_DIAGNOSTIC_SPARE1 = 1 << 13, TRM_DIAGNOSTIC_SPARE2 = 1 << 14, - TRM_DIAGNOSTIC_SPARE3 = 1 << 15, - TRM_MAXDIAGNOSTIC_BIT = 1 << 16 // end before BIT(16) + TRM_DECODE_ERROR = 1 << 15, + TRM_DIAGNOSTIC_SPARE3 = TRM_DECODE_ERROR, // backward compatibility + TRM_MAXDIAGNOSTIC_BIT = 1 << 16 // end before BIT(16) }; /** TRM Chain diagnostic bits, 8 bits [16-23] chainA [24-31] chainB **/ @@ -151,6 +183,40 @@ enum ETRMChainDiagnostic_t { TRMCHAIN_MAXDIAGNOSTIC_BIT = 1 << 24 // end before BIT(23), BIT(32) }; +static const char* TRMDiagnosticName[32] = { + "TRM_HAS_DATA", + "", + "", + "", + "TRM_HEADER_MISSING", + "TRM_TRAILER_MISSING", + "TRM_CRC_MISMATCH", + "TRM_HEADER_UNEXPECTED", + "TRM_EVENTCNT_MISMATCH", + "TRM_EMPTYBIT_NOTZERO", + "TRM_LBIT_NOTZERO", + "TRM_FAULTSLOTBIT_NOTZERO", + "TRM_EVENTWORDS_MISMATCH", + "TRM_DIAGNOSTIC_SPARE1", + "TRM_DIAGNOSTIC_SPARE2", + "TRM_DECODE_ERROR", + "TRM_CHAIN_A_HEADER_MISSING", + "TRM_CHAIN_A_TRAILER_MISSING", + "TRM_CHAIN_A_STATUS_NOTZERO", + "TRM_CHAIN_A_EVENTCNT_MISMATCH", + "TRM_CHAIN_A_TDCERROR_DETECTED", + "TRM_CHAIN_A_BUNCHCNT_MISMATCH", + "TRM_CHAIN_A_DIAGNOSTIC_SPARE1", + "TRM_CHAIN_A_DIAGNOSTIC_SPARE2", + "TRM_CHAIN_B_HEADER_MISSING", + "TRM_CHAIN_B_TRAILER_MISSING", + "TRM_CHAIN_B_STATUS_NOTZERO", + "TRM_CHAIN_B_EVENTCNT_MISMATCH", + "TRM_CHAIN_B_TDCERROR_DETECTED", + "TRM_CHAIN_B_BUNCHCNT_MISMATCH", + "TRM_CHAIN_B_DIAGNOSTIC_SPARE1", + "TRM_CHAIN_B_DIAGNOSTIC_SPARE2"}; + } // namespace diagnostic } // namespace tof diff --git a/Detectors/TOF/compression/include/TOFCompression/Compressor.h b/Detectors/TOF/compression/include/TOFCompression/Compressor.h index e52cc7f1ecca3..e88e6341dfd03 100644 --- a/Detectors/TOF/compression/include/TOFCompression/Compressor.h +++ b/Detectors/TOF/compression/include/TOFCompression/Compressor.h @@ -33,8 +33,8 @@ class Compressor { public: - Compressor() = default; - ~Compressor() = default; + Compressor() { mDecoderSaveBuffer = new char[mDecoderSaveBufferSize]; }; + ~Compressor() { delete[] mDecoderSaveBuffer; }; inline bool run() { @@ -121,7 +121,8 @@ class Compressor bool mDecoderVerbose = false; bool mDecoderError = false; bool mDecoderFatal = false; - char mDecoderSaveBuffer[1048576]; + char* mDecoderSaveBuffer = nullptr; + const int mDecoderSaveBufferSize = 33554432; uint32_t mDecoderSaveBufferDataSize = 0; uint32_t mDecoderSaveBufferDataLeft = 0; @@ -199,7 +200,9 @@ class Compressor uint8_t trmErrors[10][2]; bool hasHits[10][2]; bool hasErrors[10][2]; - bool decodeError; + bool drmDecodeError; + bool ltmDecodeError; + bool trmDecodeError[10]; } mDecoderSummary = {nullptr}; struct SpiderSummary_t { diff --git a/Detectors/TOF/compression/include/TOFCompression/CompressorTask.h b/Detectors/TOF/compression/include/TOFCompression/CompressorTask.h index 84245091dd6ad..0bd9adb6b0e0b 100644 --- a/Detectors/TOF/compression/include/TOFCompression/CompressorTask.h +++ b/Detectors/TOF/compression/include/TOFCompression/CompressorTask.h @@ -32,13 +32,16 @@ template <typename RDH, bool verbose> class CompressorTask : public Task { public: - CompressorTask() = default; - ~CompressorTask() override = default; + CompressorTask() { mBufferOut = new char[mBufferOutSize]; }; + ~CompressorTask() override { delete[] mBufferOut; }; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; private: Compressor<RDH, verbose> mCompressor; + + char* mBufferOut = nullptr; + const int mBufferOutSize = 33554432; }; } // namespace tof diff --git a/Detectors/TOF/compression/src/Compressor.cxx b/Detectors/TOF/compression/src/Compressor.cxx index 4408867c98972..318aa7867bd78 100644 --- a/Detectors/TOF/compression/src/Compressor.cxx +++ b/Detectors/TOF/compression/src/Compressor.cxx @@ -476,6 +476,7 @@ bool Compressor<RDH, verbose>::processDRM() /** decode error **/ mDecoderError = true; + mDecoderSummary.drmDecodeError = true; if (verbose && mDecoderVerbose) { printf("%s %08x [ERROR] trying to recover DRM decode stream %s \n", colorRed, *mDecoderPointer, colorReset); @@ -617,6 +618,7 @@ bool Compressor<RDH, verbose>::processTRM() /** decode error **/ mDecoderError = true; + mDecoderSummary.trmDecodeError[itrm] = true; if (verbose && mDecoderVerbose) { printf("%s %08x [ERROR] breaking TRM decode stream %s \n", colorRed, *mDecoderPointer, colorReset); } @@ -714,6 +716,7 @@ bool Compressor<RDH, verbose>::processTRMchain(int itrm, int ichain) /** decode error **/ mDecoderError = true; + mDecoderSummary.trmDecodeError[itrm] = true; if (verbose && mDecoderVerbose) { printf("%s %08x [ERROR] breaking TRM Chain-%c decode stream %s \n", colorRed, *mDecoderPointer, ichain == 0 ? 'A' : 'B', colorReset); } @@ -883,9 +886,28 @@ bool Compressor<RDH, verbose>::checkerCheck() } mDecoderSummary = {nullptr}; mCheckerSummary.nDiagnosticWords++; + for (int itrm = 0; itrm < 10; ++itrm) { + mDecoderSummary.trmDataHeader[itrm] = nullptr; + mDecoderSummary.trmDataTrailer[itrm] = nullptr; + for (int ichain = 0; ichain < 2; ++ichain) { + mDecoderSummary.trmChainHeader[itrm][ichain] = nullptr; + mDecoderSummary.trmChainTrailer[itrm][ichain] = nullptr; + mDecoderSummary.trmErrors[itrm][ichain] = 0; + mDecoderSummary.trmErrors[itrm][ichain] = 0; + } + } return true; } + /** check DRM decode error **/ + if (mDecoderSummary.drmDecodeError) { + mCheckerSummary.DiagnosticWord[0] |= diagnostic::DRM_DECODE_ERROR; + if (verbose && mCheckerVerbose) { + printf(" DRM decode error \n"); + } + mDecoderSummary.drmDecodeError = false; + } + /** check DRM Data Trailer **/ if (verbose && mCheckerVerbose) { printf(" --- Checking DRM Data Trailer: %p \n", mDecoderSummary.drmDataTrailer); @@ -897,6 +919,7 @@ bool Compressor<RDH, verbose>::checkerCheck() } mDecoderSummary = {nullptr}; mCheckerSummary.nDiagnosticWords++; + return true; } @@ -1053,9 +1076,20 @@ bool Compressor<RDH, verbose>::checkerCheck() if (verbose && mCheckerVerbose) { printf(" Missing TRM Data Header (slotId=%u) \n", slotId); } + mDecoderSummary.trmErrors[itrm][0] = 0; + mDecoderSummary.trmErrors[itrm][1] = 0; continue; } + /** check TRM decode error **/ + if (mDecoderSummary.trmDecodeError[itrm]) { + mCheckerSummary.DiagnosticWord[iword] |= diagnostic::TRM_DECODE_ERROR; + if (verbose && mCheckerVerbose) { + printf(" Decode error in TRM (slotId=%u) \n", slotId); + } + mDecoderSummary.trmDecodeError[itrm] = false; + } + /** check TRM Data Trailer **/ if (!mDecoderSummary.trmDataTrailer[itrm]) { mCheckerSummary.DiagnosticWord[iword] |= diagnostic::TRM_TRAILER_MISSING; @@ -1063,6 +1097,8 @@ bool Compressor<RDH, verbose>::checkerCheck() printf(" Missing TRM Trailer (slotId=%u) \n", slotId); } mDecoderSummary.trmDataHeader[itrm] = nullptr; + mDecoderSummary.trmErrors[itrm][0] = 0; + mDecoderSummary.trmErrors[itrm][1] = 0; continue; } @@ -1123,6 +1159,7 @@ bool Compressor<RDH, verbose>::checkerCheck() if (verbose && mCheckerVerbose) { printf(" Missing TRM Chain Header (slotId=%u, chain=%d) \n", slotId, ichain); } + mDecoderSummary.trmErrors[itrm][ichain] = 0; continue; } @@ -1133,6 +1170,7 @@ bool Compressor<RDH, verbose>::checkerCheck() printf(" Missing TRM Chain Trailer (slotId=%u, chain=%d) \n", slotId, ichain); } mDecoderSummary.trmChainHeader[itrm][ichain] = nullptr; + mDecoderSummary.trmErrors[itrm][ichain] = 0; continue; } diff --git a/Detectors/TOF/compression/src/CompressorTask.cxx b/Detectors/TOF/compression/src/CompressorTask.cxx index 8b9143f45f7a7..de3a490ec05dd 100644 --- a/Detectors/TOF/compression/src/CompressorTask.cxx +++ b/Detectors/TOF/compression/src/CompressorTask.cxx @@ -57,9 +57,8 @@ void CompressorTask<RDH, verbose>::run(ProcessingContext& pc) LOG(DEBUG) << "Compressor run"; /** set encoder output buffer **/ - char bufferOut[1048576]; - mCompressor.setEncoderBuffer(bufferOut); - mCompressor.setEncoderBufferSize(1048576); + mCompressor.setEncoderBuffer(mBufferOut); + mCompressor.setEncoderBufferSize(mBufferOutSize); auto device = pc.services().get<o2::framework::RawDeviceService>().device(); auto outputRoutes = pc.services().get<o2::framework::RawDeviceService>().spec().outputs; @@ -87,7 +86,7 @@ void CompressorTask<RDH, verbose>::run(ProcessingContext& pc) mCompressor.run(); auto payloadOutSize = mCompressor.getEncoderByteCounter(); auto payloadMessage = device->NewMessage(payloadOutSize); - std::memcpy(payloadMessage->GetData(), bufferOut, payloadOutSize); + std::memcpy(payloadMessage->GetData(), mBufferOut, payloadOutSize); /** output **/ auto headerOut = *headerIn; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h index 85ca5dea0aff5..fa6ea9e670384 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h @@ -44,7 +44,8 @@ class DecoderBaseT if (mDecoderCONET) { mDecoderPointerMax = reinterpret_cast<const uint32_t*>(mDecoderBuffer + mDecoderBufferSize); while (mDecoderPointer < mDecoderPointerMax) { - processDRM(); + if (processDRM()) + return false; } return false; } From fcc70ee069d30b4422077a3a1cba36f90c7ea07e Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 20 Oct 2020 16:56:21 +0200 Subject: [PATCH 0996/1751] Revert "DPL Analysis: use index-builder similar to aod-spawner for predefined index tables (#4630)" (#4639) This reverts commit cd287724c3098c7a1edf6f38a3c5dde25dfcd65f. --- .../Core/include/Framework/AODReaderHelpers.h | 1 - Framework/Core/include/Framework/ASoA.h | 17 +--- .../include/Framework/AnalysisDataModel.h | 6 +- .../Core/include/Framework/AnalysisTask.h | 31 +------ Framework/Core/src/AODReaderHelpers.cxx | 91 ++----------------- Framework/Core/src/AnalysisManagers.h | 4 +- Framework/Core/src/WorkflowHelpers.cxx | 57 ------------ 7 files changed, 16 insertions(+), 191 deletions(-) diff --git a/Framework/Core/include/Framework/AODReaderHelpers.h b/Framework/Core/include/Framework/AODReaderHelpers.h index f428f46bce6f5..3016f07200fb2 100644 --- a/Framework/Core/include/Framework/AODReaderHelpers.h +++ b/Framework/Core/include/Framework/AODReaderHelpers.h @@ -65,7 +65,6 @@ struct RuntimeWatchdog { struct AODReaderHelpers { static AlgorithmSpec rootFileReaderCallback(); static AlgorithmSpec aodSpawnerCallback(std::vector<InputSpec> requested); - static AlgorithmSpec indexBuilderCallback(std::vector<InputSpec> requested); }; } // namespace o2::framework::readers diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 41f98f2f7d304..1f726cbd9ca62 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -25,7 +25,6 @@ #include <arrow/compute/kernel.h> #include <gandiva/selection_vector.h> #include <cassert> -#include <fmt/format.h> using o2::framework::runtime_error_f; @@ -1051,7 +1050,6 @@ class TableMetadata static constexpr char const* tableLabel() { return INHERIT::mLabel; } static constexpr char const (&origin())[4] { return INHERIT::mOrigin; } static constexpr char const (&description())[16] { return INHERIT::mDescription; } - static std::string sourceSpec() { return fmt::format("{}/{}/{}", INHERIT::mLabel, INHERIT::mOrigin, INHERIT::mDescription); }; }; template <typename... C1, typename... C2> @@ -1379,7 +1377,7 @@ constexpr auto is_binding_compatible_v() #define DECLARE_SOA_EXTENDED_TABLE_USER(_Name_, _Table_, _Description_, ...) \ DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "AOD", _Description_, __VA_ARGS__) -#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, _Exclusive_, ...) \ +#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, ...) \ struct _Name_ : o2::soa::IndexTable<_Key_, __VA_ARGS__> { \ _Name_(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : o2::soa::IndexTable<_Key_, __VA_ARGS__>(table, offset){}; \ _Name_(_Name_ const&) = default; \ @@ -1395,7 +1393,6 @@ constexpr auto is_binding_compatible_v() static constexpr char const* mLabel = #_Name_; \ static constexpr char const mOrigin[4] = _Origin_; \ static constexpr char const mDescription[16] = _Description_; \ - static constexpr bool exclusive = _Exclusive_; \ }; \ \ template <> \ @@ -1409,16 +1406,7 @@ constexpr auto is_binding_compatible_v() }; #define DECLARE_SOA_INDEX_TABLE(_Name_, _Key_, _Description_, ...) \ - DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "IDX", _Description_, false, __VA_ARGS__) - -#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(_Name_, _Key_, _Description_, ...) \ - DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "IDX", _Description_, true, __VA_ARGS__) - -#define DECLARE_SOA_INDEX_TABLE_USER(_Name_, _Key_, _Description_, ...) \ - DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, false, __VA_ARGS__) - -#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE_USER(_Name_, _Key_, _Description_, ...) \ - DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, true, __VA_ARGS__) + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, __VA_ARGS__) namespace o2::soa { @@ -1779,7 +1767,6 @@ struct IndexTable : Table<soa::Index<>, H, Ts...> { using indexing_t = Key; using first_t = typename H::binding_t; using rest_t = framework::pack<typename Ts::binding_t...>; - using sources_t = framework::pack<Key, typename H::binding_t, typename Ts::binding_t...>; IndexTable(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : base_t{table, offset} diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 25d68cbd64766..8e92461402b85 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -608,14 +608,14 @@ DECLARE_SOA_INDEX_COLUMN(FDD, fdd); } // namespace indices #define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FV0CId, indices::FDDId -DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); +DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); #define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FDDId -DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); +DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MA_RN3_SP", INDEX_LIST_RUN3); -DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); +DECLARE_SOA_INDEX_TABLE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); DECLARE_SOA_INDEX_TABLE(BCCollisionsSparse, BCs, "MA_BCCOL_SP", indices::BCId, indices::CollisionId); } // namespace aod diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index ca966d48cc726..eacdd9704566c 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -53,42 +53,13 @@ struct AnalysisTask { // the contents of an AnalysisTask... struct AnalysisDataProcessorBuilder { - template <typename T> - static ConfigParamSpec getSpec() - { - if constexpr (soa::is_type_with_metadata_v<aod::MetadataTrait<T>>) { - return ConfigParamSpec{"input", VariantType::String, aod::MetadataTrait<T>::metadata::sourceSpec(), {"\"\""}}; - } else { - using O1 = framework::pack_element_t<0, typename T::originals>; - return ConfigParamSpec{"input", VariantType::String, aod::MetadataTrait<O1>::metadata::sourceSpec(), {"\"\""}}; - } - } - - template <typename... T> - static std::vector<ConfigParamSpec> getInputSpecs(framework::pack<T...>) - { - return std::vector{getSpec<T>()...}; - } - - template <typename T> - static std::vector<ConfigParamSpec> getIndexSources() - { - static_assert(soa::is_soa_index_table_t<T>::value, "Can only be used with IndexTable"); - return getInputSpecs(typename T::sources_t{}); - } - template <typename Arg> static void doAppendInputWithMetadata(std::vector<InputSpec>& inputs) { using metadata = typename aod::MetadataTrait<std::decay_t<Arg>>::metadata; static_assert(std::is_same_v<metadata, void> == false, "Could not find metadata. Did you register your type?"); - if constexpr (soa::is_soa_index_table_t<std::decay_t<Arg>>::value) { - auto inputSources = getIndexSources<std::decay_t<Arg>>(); - inputs.push_back(InputSpec{metadata::tableLabel(), metadata::origin(), metadata::description(), Lifetime::Timeframe, inputSources}); - } else { - inputs.push_back({metadata::tableLabel(), metadata::origin(), metadata::description()}); - } + inputs.push_back({metadata::tableLabel(), metadata::origin(), metadata::description()}); } template <typename... Args> diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 6dc4350a0d8cb..b341b4089b47e 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -8,9 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/AODReaderHelpers.h" #include "Framework/TableTreeHelpers.h" -#include "Framework/AnalysisHelpers.h" +#include "Framework/AODReaderHelpers.h" #include "AnalysisDataModelHelpers.h" #include "DataProcessingHelpers.h" #include "ExpressionHelpers.h" @@ -42,90 +41,16 @@ namespace o2::framework::readers { -auto setEOSCallback(InitContext& ic) -{ - ic.services().get<CallbackService>().set(CallbackService::Id::EndOfStream, - [](EndOfStreamContext& eosc) { - auto& control = eosc.services().get<ControlService>(); - control.endOfStream(); - control.readyToQuit(QuitRequest::Me); - }); -} - -template <typename O> -static inline auto extractTypedOriginal(ProcessingContext& pc) -{ - ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables - return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; -} - -template <typename... Os> -static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) -{ - return std::make_tuple(extractTypedOriginal<Os>(pc)...); -} - -AlgorithmSpec AODReaderHelpers::indexBuilderCallback(std::vector<InputSpec> requested) -{ - return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { - setEOSCallback(ic); - - return [requested](ProcessingContext& pc) { - auto outputs = pc.outputs(); - // spawn tables - for (auto& input : requested) { - auto description = std::visit( - overloaded{ - [](ConcreteDataMatcher const& matcher) { return matcher.description; }, - [](auto&&) { return header::DataDescription{""}; }}, - input.matcher); - - auto origin = std::visit( - overloaded{ - [](ConcreteDataMatcher const& matcher) { return matcher.origin; }, - [](auto&&) { return header::DataOrigin{""}; }}, - input.matcher); - - auto maker = [&](auto metadata) { - using metadata_t = decltype(metadata); - using Key = typename metadata_t::Key; - using index_pack_t = typename metadata_t::index_pack_t; - using sources = typename metadata_t::originals; - if constexpr (metadata_t::exclusive == true) { - return o2::framework::IndexExclusive::indexBuilder(index_pack_t{}, - extractTypedOriginal<Key>(pc), - extractOriginalsTuple(sources{}, pc)); - } else { - return o2::framework::IndexSparse::indexBuilder(index_pack_t{}, - extractTypedOriginal<Key>(pc), - extractOriginalsTuple(sources{}, pc)); - } - }; - - if (description == header::DataDescription{"MA_RN2_EX"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::Run2MatchedExclusiveMetadata{})); - } else if (description == header::DataDescription{"MA_RN2_SP"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::Run2MatchedSparseMetadata{})); - } else if (description == header::DataDescription{"MA_RN3_EX"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedExclusiveMetadata{})); - } else if (description == header::DataDescription{"MA_RN3_SP"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedSparseMetadata{})); - } else if (description == header::DataDescription{"MA_BCCOL_EX"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsExclusiveMetadata{})); - } else if (description == header::DataDescription{"MA_BCCOL_SP"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsSparseMetadata{})); - } else { - throw std::runtime_error("Not an index table"); - } - } - }; - }}; -} - AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> requested) { return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { - setEOSCallback(ic); + auto& callbacks = ic.services().get<CallbackService>(); + auto endofdatacb = [](EndOfStreamContext& eosc) { + auto& control = eosc.services().get<ControlService>(); + control.endOfStream(); + control.readyToQuit(QuitRequest::Me); + }; + callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); return [requested](ProcessingContext& pc) { auto outputs = pc.outputs(); diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index c59225b8364d0..33340b70640e9 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -260,14 +260,14 @@ struct OutputManager<Spawns<T>> { /// Builds specialization template <typename O> -static inline auto extractTypedOriginal(ProcessingContext& pc) +static auto extractTypedOriginal(ProcessingContext& pc) { ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; } template <typename... Os> -static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +static auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) { return std::make_tuple(extractTypedOriginal<Os>(pc)...); } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 631a972d7630b..702b7514b139c 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -161,41 +161,6 @@ void addMissingOutputsToSpawner(std::vector<InputSpec>&& requestedDYNs, } } -void addMissingOutputsToBuilder(std::vector<InputSpec>&& requestedIDXs, - std::vector<InputSpec>& requestedAODs, - DataProcessorSpec& publisher) -{ - auto inputSpecFromString = [](std::string s) { - std::regex word_regex("(\\w+)"); - auto words = std::sregex_iterator(s.begin(), s.end(), word_regex); - if (std::distance(words, std::sregex_iterator()) != 3) { - throw runtime_error_f("Malformed spec: %s", s.c_str()); - } - std::vector<std::string> data; - for (auto i = words; i != std::sregex_iterator(); ++i) { - data.emplace_back(i->str()); - } - char origin[4]; - char description[16]; - std::memcpy(&origin, data[1].c_str(), 4); - std::memcpy(&description, data[2].c_str(), 16); - return InputSpec{data[0], header::DataOrigin{origin}, header::DataDescription{description}}; - }; - - for (auto& input : requestedIDXs) { - auto concrete = DataSpecUtils::asConcreteDataMatcher(input); - publisher.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec}); - for (auto& i : input.metadata) { - auto spec = inputSpecFromString(i.defaultValue.get<std::string>()); - auto j = std::find_if(publisher.inputs.begin(), publisher.inputs.end(), [&](auto x) { return x.binding == spec.binding; }); - if (j == publisher.inputs.end()) { - publisher.inputs.push_back(spec); - } - requestedAODs.push_back(spec); - } - } -} - void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext const& ctx) { auto fakeCallback = AlgorithmSpec{[](InitContext& ic) { @@ -253,7 +218,6 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext std::vector<InputSpec> requestedAODs; std::vector<OutputSpec> providedAODs; std::vector<InputSpec> requestedDYNs; - std::vector<InputSpec> requestedIDXs; std::vector<InputSpec> requestedCCDBs; std::vector<OutputSpec> providedCCDBs; @@ -321,11 +285,6 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext requestedDYNs.emplace_back(input); } } - if (DataSpecUtils::partialMatch(input, header::DataOrigin{"IDX"})) { - if (std::find_if(requestedIDXs.begin(), requestedIDXs.end(), [&](InputSpec const& spec) { return input.binding == spec.binding; }) == requestedIDXs.end()) { - requestedIDXs.emplace_back(input); - } - } } std::stable_sort(timer.outputs.begin(), timer.outputs.end(), [](OutputSpec const& a, OutputSpec const& b) { return *DataSpecUtils::getOptionalSubSpec(a) < *DataSpecUtils::getOptionalSubSpec(b); }); @@ -361,9 +320,6 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext auto last = std::unique(requestedDYNs.begin(), requestedDYNs.end()); requestedDYNs.erase(last, requestedDYNs.end()); - last = std::unique(requestedIDXs.begin(), requestedIDXs.end()); - requestedIDXs.erase(last, requestedIDXs.end()); - DataProcessorSpec aodSpawner{ "internal-dpl-aod-spawner", {}, @@ -371,16 +327,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext readers::AODReaderHelpers::aodSpawnerCallback(requestedDYNs), {}}; - DataProcessorSpec indexBuilder{ - "internal-dpl-index-builder", - {}, - {}, - readers::AODReaderHelpers::indexBuilderCallback(requestedIDXs), - {}}; - addMissingOutputsToSpawner(std::move(requestedDYNs), requestedAODs, aodSpawner); - addMissingOutputsToBuilder(std::move(requestedIDXs), requestedAODs, indexBuilder); - addMissingOutputsToReader(providedAODs, requestedAODs, aodReader); addMissingOutputsToReader(providedCCDBs, requestedCCDBs, ccdbBackend); @@ -400,10 +347,6 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext extraSpecs.push_back(aodSpawner); } - if (indexBuilder.outputs.empty() == false) { - extraSpecs.push_back(indexBuilder); - } - if (aodReader.outputs.empty() == false) { extraSpecs.push_back(timePipeline(aodReader, ctx.options().get<int64_t>("readers"))); auto concrete = DataSpecUtils::asConcreteDataMatcher(aodReader.inputs[0]); From b6743a24f2e5b771f8fd1df2c28f305331282d8e Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Tue, 22 Sep 2020 15:00:11 +0200 Subject: [PATCH 0997/1751] DCSProcessor DCS processor example example macro Update. Fixes + check on entries in map Using unordered_map find, adding other types. Not yet complete. Fix for string type (thanks to Ruben!) and adding binary type. Implementing reading of flags plus other changes. * new Init taking full map; * function to check presence of alias. Removing commented out line Fix indentation For the sake of clang happiness. Following comments by Ruben. Some fixes for comments - but does not compile Fixing specialized templates. Clang-format. Changing layout of templated functions + making some functions virtual clang-format --- Detectors/DCS/CMakeLists.txt | 9 +- .../DCS/include/DetectorsDCS/DCSProcessor.h | 176 +++++++ Detectors/DCS/src/DCSProcessor.cxx | 487 ++++++++++++++++++ Detectors/DCS/src/DetectorsDCSLinkDef.h | 1 + Detectors/DCS/test/processor_dpcom_o2.C | 115 +++++ cmake/O2RootMacroExclusionList.cmake | 3 +- 6 files changed, 788 insertions(+), 3 deletions(-) create mode 100644 Detectors/DCS/include/DetectorsDCS/DCSProcessor.h create mode 100644 Detectors/DCS/src/DCSProcessor.cxx create mode 100644 Detectors/DCS/test/processor_dpcom_o2.C diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt index 436b018b1b3fb..31417c37d55c9 100644 --- a/Detectors/DCS/CMakeLists.txt +++ b/Detectors/DCS/CMakeLists.txt @@ -16,11 +16,16 @@ o2_add_library(DetectorsDCS src/DataPointValue.cxx src/DeliveryType.cxx src/GenericFunctions.cxx - src/StringUtils.cxx) + src/StringUtils.cxx + src/DCSProcessor.cxx + PUBLIC_LINK_LIBRARIES O2::Headers + O2::CommonUtils + ms_gsl::ms_gsl) o2_target_root_dictionary(DetectorsDCS HEADERS include/DetectorsDCS/DataPointCompositeObject.h include/DetectorsDCS/DataPointIdentifier.h - include/DetectorsDCS/DataPointValue.h) + include/DetectorsDCS/DataPointValue.h + include/DetectorsDCS/DCSProcessor.h) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h new file mode 100644 index 0000000000000..c3802b5d72996 --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -0,0 +1,176 @@ +// 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 DETECTOR_DCS_DCSPROCESSOR_H_ +#define DETECTOR_DCS_DCSPROCESSOR_H_ + +#include <memory> +#include <Rtypes.h> +#include <unordered_map> +#include <deque> +#include "Framework/Logger.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DeliveryType.h" + +/// @brief Class to process DCS data points + +namespace o2 +{ +namespace dcs +{ + +class DCSProcessor +{ + + public: + using Ints = std::vector<int>; + using Chars = std::vector<char>; + using Doubles = std::vector<double>; + using Binaries = std::array<uint64_t, 7>; + using Strings = std::array<char, 56>; + + using DQChars = std::deque<char>; + using DQInts = std::deque<int>; + using DQDoubles = std::deque<double>; + using DQUInts = std::deque<uint32_t>; + using DQBools = std::deque<bool>; + using DQStrings = std::deque<Strings>; + using DQTimes = std::deque<uint32_t>; + using DQBinaries = std::deque<Binaries>; + + using DPID = o2::dcs::DataPointIdentifier; + using DPVAL = o2::dcs::DataPointValue; + using DPCOM = o2::dcs::DataPointCompositeObject; + + DCSProcessor() = default; + ~DCSProcessor() = default; + + void init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, + const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, + const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, + const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries); + + void init(const std::vector<DPID>& aliases); + + int process(const std::unordered_map<DPID, DPVAL>& map); + + std::unordered_map<DPID, DPVAL>::const_iterator processAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map); + + template <typename T> + int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap); + + virtual void processChars(); + virtual void processInts(); + virtual void processDoubles(); + virtual void processUInts(); + virtual void processBools(); + virtual void processStrings(); + virtual void processTimes(); + virtual void processBinaries(); + virtual uint64_t processFlag(uint64_t flag, const char* alias); + + void doSimpleMovingAverage(int nelements, std::deque<int>& vect, float& avg, bool& isSMA); + + DQChars& getVectorForAliasChar(const DPID& id) { return mDpscharsmap[id]; } + DQInts& getVectorForAliasInt(const DPID& id) { return mDpsintsmap[id]; } + DQDoubles& getVectorForAliasDouble(const DPID& id) { return mDpsdoublesmap[id]; } + DQUInts& getVectorForAliasUInt(const DPID& id) { return mDpsUintsmap[id]; } + DQBools& getVectorForAliasBool(const DPID& id) { return mDpsboolsmap[id]; } + DQStrings& getVectorForAliasString(const DPID& id) { return mDpsstringsmap[id]; } + DQTimes& getVectorForAliasTime(const DPID& id) { return mDpstimesmap[id]; } + DQBinaries& getVectorForAliasBinary(const DPID& id) { return mDpsbinariesmap[id]; } + + private: + float mAvgTestInt0 = 0; // moving average for DP named TestInt0 + std::unordered_map<DPID, DQChars> mDpscharsmap; + std::unordered_map<DPID, DQInts> mDpsintsmap; + std::unordered_map<DPID, DQDoubles> mDpsdoublesmap; + std::unordered_map<DPID, DQUInts> mDpsUintsmap; + std::unordered_map<DPID, DQBools> mDpsboolsmap; + std::unordered_map<DPID, DQStrings> mDpsstringsmap; + std::unordered_map<DPID, DQTimes> mDpstimesmap; + std::unordered_map<DPID, DQBinaries> mDpsbinariesmap; + std::vector<DPID> mAliaseschars; + std::vector<DPID> mAliasesints; + std::vector<DPID> mAliasesdoubles; + std::vector<DPID> mAliasesUints; + std::vector<DPID> mAliasesbools; + std::vector<DPID> mAliasesstrings; + std::vector<DPID> mAliasestimes; + std::vector<DPID> mAliasesbinaries; + std::vector<uint64_t> mLatestTimestampchars; + std::vector<uint64_t> mLatestTimestampints; + std::vector<uint64_t> mLatestTimestampdoubles; + std::vector<uint64_t> mLatestTimestampUints; + std::vector<uint64_t> mLatestTimestampbools; + std::vector<uint64_t> mLatestTimestampstrings; + std::vector<uint64_t> mLatestTimestamptimes; + std::vector<uint64_t> mLatestTimestampbinaries; + + ClassDefNV(DCSProcessor, 0); +}; + +using Ints = std::vector<int>; +using Chars = std::vector<char>; +using Doubles = std::vector<double>; +using Binaries = std::array<uint64_t, 7>; +using Strings = std::array<char, 56>; + +using DQStrings = std::deque<Strings>; +using DQBinaries = std::deque<Binaries>; + +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; + +template <typename T> +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap) +{ + + // processing the array of type T + + int found = 0; + auto s = array.size(); + if (s > 0) { + for (size_t i = 0; i != s; ++i) { + auto it = processAlias(array[i], type, map); + if (it == map.end()) { + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + continue; + } + found++; + auto& val = it->second; + auto flags = val.get_flags(); + if (processFlag(flags, array[i].get_alias()) == 0) { + auto etime = val.get_epoch_time(); + // fill only if new value has a timestamp different from the timestamp of the previous one + LOG(INFO) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); + if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { + LOG(INFO) << "adding new value"; + destmap[array[i]].push_back(val.payload_pt1); + latestTimeStamp[i] = etime; + } + } + } + } + return found; +} + +template <> +int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQStrings>& destmap); + +template <> +int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQBinaries>& destmap); + +} // namespace dcs +} // namespace o2 + +#endif diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx new file mode 100644 index 0000000000000..35fcea1e579ba --- /dev/null +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -0,0 +1,487 @@ +// 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 <DetectorsDCS/DCSProcessor.h> +#include "Rtypes.h" +#include <deque> +#include <string.h> + +using namespace o2::dcs; + +using DeliveryType = o2::dcs::DeliveryType; +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; + +//ClassImp(o2::dcs::DCSProcessor); + +void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, const std::vector<DPID>& aliasesdoubles, + const std::vector<DPID>& aliasesUints, const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, + const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries) +{ + + // init from separate vectors of aliases (one per data point type) + + // chars + for (auto it = std::begin(aliaseschars); it != std::end(aliaseschars); ++it) { + if ((*it).get_type() != DeliveryType::RAW_CHAR) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a char"; + } + mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + } + + // ints + for (auto it = std::begin(aliasesints); it != std::end(aliasesints); ++it) { + if ((*it).get_type() != DeliveryType::RAW_INT) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a int"; + } + mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + } + + // doubles + for (auto it = std::begin(aliasesdoubles); it != std::end(aliasesdoubles); ++it) { + if ((*it).get_type() != DeliveryType::RAW_DOUBLE) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a double"; + } + mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + } + + // uints + for (auto it = std::begin(aliasesUints); it != std::end(aliasesUints); ++it) { + if ((*it).get_type() != DeliveryType::RAW_UINT) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a uint"; + } + mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + } + + // bools + for (auto it = std::begin(aliasesbools); it != std::end(aliasesbools); ++it) { + if ((*it).get_type() != DeliveryType::RAW_BOOL) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a bool"; + } + mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + } + + // strings + for (auto it = std::begin(aliasesstrings); it != std::end(aliasesstrings); ++it) { + if ((*it).get_type() != DeliveryType::RAW_STRING) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a string"; + } + mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + } + + // times + for (auto it = std::begin(aliasestimes); it != std::end(aliasestimes); ++it) { + if ((*it).get_type() != DeliveryType::RAW_TIME) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a time"; + } + mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + } + + // binaries + for (auto it = std::begin(aliasesbinaries); it != std::end(aliasesbinaries); ++it) { + if ((*it).get_type() != DeliveryType::RAW_BINARY) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a binary"; + } + mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); + } + + mLatestTimestampchars.resize(aliaseschars.size(), 0); + mLatestTimestampints.resize(aliasesints.size(), 0); + mLatestTimestampdoubles.resize(aliasesdoubles.size(), 0); + mLatestTimestampUints.resize(aliasesUints.size(), 0); + mLatestTimestampbools.resize(aliasesbools.size(), 0); + mLatestTimestampstrings.resize(aliasesstrings.size(), 0); + mLatestTimestamptimes.resize(aliasestimes.size(), 0); + mLatestTimestampbinaries.resize(aliasesbinaries.size(), 0); +} + +//______________________________________________________________________ + +void DCSProcessor::init(const std::vector<DPID>& aliases) +{ + + int nchars = 0, nints = 0, ndoubles = 0, nUints = 0, + nbools = 0, nstrings = 0, ntimes = 0, nbinaries = 0; + for (auto it = std::begin(aliases); it != std::end(aliases); ++it) { + if ((*it).get_type() == DeliveryType::RAW_CHAR) { + mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + nchars++; + } + if ((*it).get_type() == DeliveryType::RAW_INT) { + mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + nints++; + } + if ((*it).get_type() == DeliveryType::RAW_DOUBLE) { + mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + ndoubles++; + } + if ((*it).get_type() == DeliveryType::RAW_UINT) { + mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + nUints++; + } + if ((*it).get_type() == DeliveryType::RAW_BOOL) { + mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + nbools++; + } + if ((*it).get_type() == DeliveryType::RAW_STRING) { + mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + nstrings++; + } + if ((*it).get_type() == DeliveryType::RAW_TIME) { + mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + ntimes++; + } + if ((*it).get_type() == DeliveryType::RAW_BINARY) { + mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); + nbinaries++; + } + } + + mLatestTimestampchars.resize(nchars, 0); + mLatestTimestampints.resize(nints, 0); + mLatestTimestampdoubles.resize(ndoubles, 0); + mLatestTimestampUints.resize(nUints, 0); + mLatestTimestampbools.resize(nbools, 0); + mLatestTimestampstrings.resize(nstrings, 0); + mLatestTimestamptimes.resize(ntimes, 0); + mLatestTimestampbinaries.resize(nbinaries, 0); +} + +//__________________________________________________________________ + +int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map) +{ + + // process function to do "something" with the DCS map that is passed + + // first, we need to check if there are the Data Points that we need + + int foundChars = 0, foundInts = 0, foundDoubles = 0, foundUInts = 0, + foundBools = 0, foundStrings = 0, foundTimes = 0, foundBinaries = 0; + + // char type + foundChars = processArrayType(mAliaseschars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); + if (foundChars > 0) + processChars(); + + // int type + foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); + if (foundInts > 0) + processInts(); + + // double type + foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, mDpsdoublesmap); + if (foundDoubles > 0) + processDoubles(); + + // UInt type + foundUInts = processArrayType(mAliasesUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); + if (foundUInts > 0) + processUInts(); + + // Bool type + foundBools = processArrayType(mAliasesbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); + if (foundBools > 0) + processBools(); + + // String type + foundStrings = processArrayType(mAliasesstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, mDpsstringsmap); + if (foundStrings > 0) + processStrings(); + + // Time type + foundTimes = processArrayType(mAliasestimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); + if (foundTimes > 0) + processTimes(); + + // Binary type + foundBinaries = processArrayType(mAliasesbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, mDpsbinariesmap); + if (foundBinaries > 0) + processBinaries(); + + if (foundChars != mAliaseschars.size()) + LOG(INFO) << "Not all expected char-typed DPs found!"; + if (foundInts != mAliasesints.size()) + LOG(INFO) << "Not all expected int-typed DPs found!"; + if (foundDoubles != mAliasesdoubles.size()) + LOG(INFO) << "Not all expected double-typed DPs found!"; + if (foundUInts != mAliasesUints.size()) + LOG(INFO) << "Not all expected uint-typed DPs found!"; + if (foundBools != mAliasesbools.size()) + LOG(INFO) << "Not all expected bool-typed DPs found!"; + if (foundStrings != mAliasesstrings.size()) + LOG(INFO) << "Not all expected string-typed DPs found!"; + if (foundTimes != mAliasestimes.size()) + LOG(INFO) << "Not all expected time-typed DPs found!"; + if (foundBinaries != mAliasesbinaries.size()) + LOG(INFO) << "Not all expected binary-typed DPs found!"; + + return 0; +} + +//______________________________________________________________________ + +template <> +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, DQStrings>& destmap) +{ + + // processing the array of type T + + int found = 0; + auto s = array.size(); + if (s > 0) { + for (size_t i = 0; i != s; ++i) { + auto it = processAlias(array[i], type, map); + if (it == map.end()) { + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + continue; + } + found++; + auto& val = it->second; + auto flags = val.get_flags(); + if (processFlag(flags, array[i].get_alias()) == 0) { + auto etime = val.get_epoch_time(); + // fill only if new value has a timestamp different from the timestamp of the previous one + LOG(INFO) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); + if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { + auto& tmp = destmap[array[i]].emplace_back(); + std::strncpy(tmp.data(), (char*)&(val.payload_pt1), 56); + latestTimeStamp[i] = etime; + } + } + } + } + return found; +} + +//______________________________________________________________________ + +template <> +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, DQBinaries>& destmap) +{ + + // processing the array of type T + + int found = 0; + auto s = array.size(); + if (s > 0) { + for (size_t i = 0; i != s; ++i) { + auto it = processAlias(array[i], type, map); + if (it == map.end()) { + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + continue; + } + found++; + auto& val = it->second; + auto flags = val.get_flags(); + if (processFlag(flags, array[i].get_alias()) == 0) { + auto etime = val.get_epoch_time(); + // fill only if new value has a timestamp different from the timestamp of the previous one + LOG(INFO) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); + if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { + auto& tmp = destmap[array[i]].emplace_back(); + memcpy(tmp.data(), &(val.payload_pt1), 7); + latestTimeStamp[i] = etime; + } + } + } + } + return found; +} + +//______________________________________________________________________ + +std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::processAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map) +{ + + // processing basic checks for map: all needed aliases must be present + + LOG(INFO) << "Processing " << alias; + auto it = map.find(alias); + DeliveryType tt = alias.get_type(); + if (tt != type) { + LOG(FATAL) << "Delivery Type of alias " << alias.get_alias() << " does not match definition in DCSProcessor (" << type << ")! Please fix"; + } + return it; +} + +//______________________________________________________________________ + +void DCSProcessor::processChars() +{ + + // function to process aliases of Char type; it will just print them + + for (size_t i = 0; i != mAliaseschars.size(); ++i) { + LOG(INFO) << "processChars: mAliaseschars[" << i << "] = " << mAliaseschars[i]; + auto& id = mAliaseschars[i]; + auto& vchar = getVectorForAliasChar(id); + LOG(INFO) << "vchar size = " << vchar.size(); + for (size_t j = 0; j < vchar.size(); j++) { + LOG(INFO) << "DP = " << mAliaseschars[i] << " , value[" << j << "] = " << vchar[j]; + } + } +} + +//______________________________________________________________________ + +void DCSProcessor::processInts() +{ + + // function to process aliases of Int type + + for (size_t i = 0; i != mAliasesints.size(); ++i) { + LOG(INFO) << "processInts: mAliasesints[" << i << "] = " << mAliasesints[i]; + auto& id = mAliasesints[i]; + auto& vint = getVectorForAliasInt(id); + LOG(INFO) << "vint size = " << vint.size(); + for (size_t j = 0; j < vint.size(); j++) { + LOG(INFO) << "DP = " << mAliasesints[i] << " , value[" << j << "] = " << vint[j]; + } + bool isSMA = false; + LOG(INFO) << "get alias = " << id.get_alias(); + if (strcmp(id.get_alias(), "TestInt0") == 0) { + doSimpleMovingAverage(2, vint, mAvgTestInt0, isSMA); + LOG(INFO) << "Moving average = " << mAvgTestInt0; + if (isSMA) { + // populate CCDB + } + } + } +} + +//______________________________________________________________________ + +void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<int>& vect, float& avg, bool& isSMA) +{ + + // Do simple moving average on vector of ints + if (vect.size() < nelements) { + avg += vect[vect.size() - 1]; + return; + } + if (vect.size() == nelements) { + avg += vect[vect.size() - 1]; + avg /= nelements; + isSMA = true; + return; + } + avg += (vect[vect.size() - 1] - vect[0]) / nelements; + vect.pop_front(); + isSMA = true; +} + +//______________________________________________________________________ + +void DCSProcessor::processDoubles() +{ + + // function to process aliases of Double type +} + +//______________________________________________________________________ + +void DCSProcessor::processUInts() +{ + + // function to process aliases of UInt type +} + +//______________________________________________________________________ + +void DCSProcessor::processBools() +{ + + // function to process aliases of Bool type +} + +//______________________________________________________________________ + +void DCSProcessor::processStrings() +{ + + // function to process aliases of String type +} + +//______________________________________________________________________ + +void DCSProcessor::processTimes() +{ + + // function to process aliases of Time type +} + +//______________________________________________________________________ + +void DCSProcessor::processBinaries() +{ + + // function to process aliases of Time binary +} + +//______________________________________________________________________ + +uint64_t DCSProcessor::processFlag(const uint64_t flags, const char* alias) +{ + + // function to process the flag. the return code zero means that all is fine. + // anything else means that there was an issue + + if (flags & DataPointValue::KEEP_ALIVE_FLAG) { + LOG(INFO) << "KEEP_ALIVE_FLAG active for DP " << alias; + } + if (flags & DataPointValue::END_FLAG) { + LOG(INFO) << "END_FLAG active for DP " << alias; + } + if (flags & DataPointValue::FBI_FLAG) { + LOG(INFO) << "FBI_FLAG active for DP " << alias; + } + if (flags & DataPointValue::NEW_FLAG) { + LOG(INFO) << "NEW_FLAG active for DP " << alias; + } + if (flags & DataPointValue::DIRTY_FLAG) { + LOG(INFO) << "DIRTY_FLAG active for DP " << alias; + } + if (flags & DataPointValue::TURN_FLAG) { + LOG(INFO) << "TURN_FLAG active for DP " << alias; + } + if (flags & DataPointValue::WRITE_FLAG) { + LOG(INFO) << "WRITE_FLAG active for DP " << alias; + } + if (flags & DataPointValue::READ_FLAG) { + LOG(INFO) << "READ_FLAG active for DP " << alias; + } + if (flags & DataPointValue::OVERWRITE_FLAG) { + LOG(INFO) << "OVERWRITE_FLAG active for DP " << alias; + } + if (flags & DataPointValue::VICTIM_FLAG) { + LOG(INFO) << "VICTIM_FLAG active for DP " << alias; + } + if (flags & DataPointValue::DIM_ERROR_FLAG) { + LOG(INFO) << "DIM_ERROR_FLAG active for DP " << alias; + } + if (flags & DataPointValue::BAD_DPID_FLAG) { + LOG(INFO) << "BAD_DPID_FLAG active for DP " << alias; + } + if (flags & DataPointValue::BAD_FLAGS_FLAG) { + LOG(INFO) << "BAD_FLAGS_FLAG active for DP " << alias; + } + if (flags & DataPointValue::BAD_TIMESTAMP_FLAG) { + LOG(INFO) << "BAD_TIMESTAMP_FLAG active for DP " << alias; + } + if (flags & DataPointValue::BAD_PAYLOAD_FLAG) { + LOG(INFO) << "BAD_PAYLOAD_FLAG active for DP " << alias; + } + if (flags & DataPointValue::BAD_FBI_FLAG) { + LOG(INFO) << "BAD_FBI_FLAG active for DP " << alias; + } + + return 0; +} diff --git a/Detectors/DCS/src/DetectorsDCSLinkDef.h b/Detectors/DCS/src/DetectorsDCSLinkDef.h index 78b3c58223100..cd41cf35959f8 100644 --- a/Detectors/DCS/src/DetectorsDCSLinkDef.h +++ b/Detectors/DCS/src/DetectorsDCSLinkDef.h @@ -17,5 +17,6 @@ #pragma link C++ struct o2::dcs::DataPointCompositeObject + ; #pragma link C++ class o2::dcs::DataPointIdentifier + ; #pragma link C++ struct o2::dcs::DataPointValue + ; +#pragma link C++ class o2::dcs::DCSProcessor + ; #endif diff --git a/Detectors/DCS/test/processor_dpcom_o2.C b/Detectors/DCS/test/processor_dpcom_o2.C new file mode 100644 index 0000000000000..4d1171205055c --- /dev/null +++ b/Detectors/DCS/test/processor_dpcom_o2.C @@ -0,0 +1,115 @@ +using namespace o2::dcs; +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; +using DPCOM = o2::dcs::DataPointCompositeObject; + +int processor_dpcom_o2() +{ + + std::unordered_map<DPID, DPVAL> dpmap; + + o2::dcs::DCSProcessor dcsproc; + std::vector<DPID> aliasChars; + std::vector<DPID> aliasInts; + std::vector<DPID> aliasDoubles; + std::vector<DPID> aliasUInts; + std::vector<DPID> aliasBools; + std::vector<DPID> aliasStrings; + std::vector<DPID> aliasTimes; + std::vector<DPID> aliasBinaries; + + DeliveryType typechar = RAW_CHAR; + std::string dpAliaschar = "TestChar0"; + DPID charVar(dpAliaschar, typechar); + aliasChars.push_back(charVar); + + DeliveryType typeint = RAW_INT; + std::string dpAliasint0 = "TestInt0"; + DPID intVar0(dpAliasint0, typeint); + aliasInts.push_back(intVar0); + + std::string dpAliasint1 = "TestInt1"; + DPID intVar1(dpAliasint1, typeint); + aliasInts.push_back(intVar1); + + std::string dpAliasint2 = "TestInt2"; + DPID intVar2(dpAliasint2, typeint); + aliasInts.push_back(intVar2); + + DeliveryType typedouble = RAW_DOUBLE; + std::string dpAliasdouble0 = "TestDouble0"; + DPID doubleVar0(dpAliasdouble0, typedouble); + aliasDoubles.push_back(doubleVar0); + + std::string dpAliasdouble1 = "TestDouble1"; + DPID doubleVar1(dpAliasdouble1, typedouble); + aliasDoubles.push_back(doubleVar1); + + std::string dpAliasdouble2 = "TestDouble2"; + DPID doubleVar2(dpAliasdouble2, typedouble); + aliasDoubles.push_back(doubleVar2); + + std::string dpAliasdouble3 = "TestDouble3"; + DPID doubleVar3(dpAliasdouble3, typedouble); + aliasDoubles.push_back(doubleVar3); + + DeliveryType typestring = RAW_STRING; + std::string dpAliasstring0 = "TestString0"; + DPID stringVar0(dpAliasstring0, typestring); + aliasStrings.push_back(stringVar0); + + dcsproc.init(aliasChars, aliasInts, aliasDoubles, aliasUInts, aliasBools, aliasStrings, aliasTimes, aliasBinaries); + + uint16_t flags = 0; + uint16_t milliseconds = 0; + TDatime currentTime; + uint32_t seconds = currentTime.Get(); + uint64_t* payload = new uint64_t[7]; + + // loop that emulates the number of times the DCS DataPoints are sent + for (auto k = 0; k < 4; k++) { + payload[0] = (uint64_t)k + 33; // adding 33 to have visible chars and strings + + DPVAL valchar(flags, milliseconds + k * 10, seconds + k, payload, typechar); + DPVAL valint(flags, milliseconds + k * 10, seconds + k, payload, typeint); + DPVAL valdouble(flags, milliseconds + k * 10, seconds + k, payload, typedouble); + DPVAL valstring(flags, milliseconds + k * 10, seconds + k, payload, typestring); + + dpmap[charVar] = valchar; + dpmap[intVar0] = valint; + dpmap[intVar1] = valint; + dpmap[intVar2] = valint; + dpmap[doubleVar0] = valdouble; + dpmap[doubleVar1] = valdouble; + dpmap[doubleVar2] = valdouble; + dpmap[stringVar0] = valstring; + if (k != 3) + dpmap[doubleVar3] = valdouble; // to test the case when a DP is not updated + std::cout << "index = " << k << std::endl; + std::cout << charVar << std::endl + << valchar << " --> " << (char)valchar.payload_pt1 << std::endl; + std::cout << intVar0 << std::endl + << valint << " --> " << (int)valchar.payload_pt1 << std::endl; + std::cout << intVar1 << std::endl + << valint << " --> " << (int)valchar.payload_pt1 << std::endl; + std::cout << intVar2 << std::endl + << valint << " --> " << (int)valchar.payload_pt1 << std::endl; + std::cout << doubleVar0 << std::endl + << valdouble << " --> " << (double)valchar.payload_pt1 << std::endl; + std::cout << doubleVar1 << std::endl + << valdouble << " --> " << (double)valchar.payload_pt1 << std::endl; + std::cout << doubleVar2 << std::endl + << valdouble << " --> " << (double)valchar.payload_pt1 << std::endl; + std::cout << doubleVar3 << std::endl + << valdouble << " --> " << (double)valchar.payload_pt1 << std::endl; + char tt[56]; + memcpy(&tt[0], &valstring.payload_pt1, 56); + printf("tt = %s\n", tt); + std::cout << stringVar0 << std::endl + << valstring << " --> " << tt << std::endl; + + dcsproc.process(dpmap); + } + std::cout << "The map has " << dpmap.size() << " entries" << std::endl; + return 0; +} diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index a002cf240b1bb..933546715c67d 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -52,7 +52,8 @@ list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST macro/loadExtDepLib.C macro/load_all_libs.C macro/putCondition.C - macro/rootlogon.C) + macro/rootlogon.C + Detectors/DCS/test/processor_dpcom_o2.C) if(NOT BUILD_SIMULATION) # some complete sub_directories are not added to the build when not building From c916cb5b4bfb1c1492a54abd13c657878da1ab24 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Sat, 3 Oct 2020 00:35:26 +0200 Subject: [PATCH 0998/1751] Adding workflow for DCS processing Fixing workflow. INFO --> DEBUG clang... beautification Forgot to delete pointer Fixing compilation --- Detectors/DCS/CMakeLists.txt | 6 +- .../DCS/include/DetectorsDCS/DataPointValue.h | 8 +- Detectors/DCS/src/DCSProcessor.cxx | 2 +- Detectors/DCS/src/DetectorsDCSLinkDef.h | 1 + .../DCS/testWorkflow/DCSDataGeneratorSpec.h | 166 ++++++++++++++++++ .../DCS/testWorkflow/DCSDataProcessorSpec.h | 113 ++++++++++++ .../DCS/testWorkflow/dcs-data-workflow.cxx | 43 +++++ 7 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h create mode 100644 Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h create mode 100644 Detectors/DCS/testWorkflow/dcs-data-workflow.cxx diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt index 31417c37d55c9..a6bec21667f42 100644 --- a/Detectors/DCS/CMakeLists.txt +++ b/Detectors/DCS/CMakeLists.txt @@ -28,4 +28,8 @@ o2_target_root_dictionary(DetectorsDCS include/DetectorsDCS/DataPointValue.h include/DetectorsDCS/DCSProcessor.h) - +o2_add_executable(dcs-data-workflow + COMPONENT_NAME dcs + SOURCES testWorkflow/dcs-data-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DetectorsDCS) diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointValue.h b/Detectors/DCS/include/DetectorsDCS/DataPointValue.h index 0887cf0d28c5d..c32c4e04128b8 100644 --- a/Detectors/DCS/include/DetectorsDCS/DataPointValue.h +++ b/Detectors/DCS/include/DetectorsDCS/DataPointValue.h @@ -408,7 +408,13 @@ struct alignas(64) DataPointValue final { break; case RAW_STRING: case DPVAL_STRING: - std::strncpy((char*)&payload_pt1, (char*)data, 56); + std::strncpy((char*)&payload_pt1, (char*)data, 8); + std::strncpy((char*)&payload_pt2, (char*)data + 8, 8); + std::strncpy((char*)&payload_pt3, (char*)data + 16, 8); + std::strncpy((char*)&payload_pt4, (char*)data + 24, 8); + std::strncpy((char*)&payload_pt5, (char*)data + 32, 8); + std::strncpy((char*)&payload_pt6, (char*)data + 40, 8); + std::strncpy((char*)&payload_pt7, (char*)data + 48, 8); break; case RAW_BINARY: case DPVAL_BINARY: diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 35fcea1e579ba..d30ca945ed900 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -11,7 +11,7 @@ #include <DetectorsDCS/DCSProcessor.h> #include "Rtypes.h" #include <deque> -#include <string.h> +#include <string> using namespace o2::dcs; diff --git a/Detectors/DCS/src/DetectorsDCSLinkDef.h b/Detectors/DCS/src/DetectorsDCSLinkDef.h index cd41cf35959f8..5f53e7757a349 100644 --- a/Detectors/DCS/src/DetectorsDCSLinkDef.h +++ b/Detectors/DCS/src/DetectorsDCSLinkDef.h @@ -18,5 +18,6 @@ #pragma link C++ class o2::dcs::DataPointIdentifier + ; #pragma link C++ struct o2::dcs::DataPointValue + ; #pragma link C++ class o2::dcs::DCSProcessor + ; +#pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue> + ; #endif diff --git a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h new file mode 100644 index 0000000000000..d078614108122 --- /dev/null +++ b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h @@ -0,0 +1,166 @@ +// 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_DCS_DATAGENERATOR_H +#define O2_DCS_DATAGENERATOR_H + +/// @file DataGeneratorSpec.h +/// @brief Dummy data generator +#include <unistd.h> +#include <TRandom.h> +#include <TDatime.h> +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DeliveryType.h" +#include "Framework/DeviceSpec.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" + +namespace o2 +{ +namespace dcs +{ +class DCSDataGenerator : public o2::framework::Task +{ + + using DPID = o2::dcs::DataPointIdentifier; + using DPVAL = o2::dcs::DataPointValue; + + public: + void init(o2::framework::InitContext& ic) final + { + mMaxTF = ic.options().get<int64_t>("max-timeframes"); + + LOG(INFO) << "mMaxTF = " << mMaxTF; + std::string dpAliaschar = "TestChar0"; + DPID::FILL(mcharVar, dpAliaschar, mtypechar); + + std::string dpAliasint0 = "TestInt0"; + DPID::FILL(mintVar0, dpAliasint0, mtypeint); + std::string dpAliasint1 = "TestInt1"; + DPID::FILL(mintVar1, dpAliasint1, mtypeint); + std::string dpAliasint2 = "TestInt2"; + DPID::FILL(mintVar2, dpAliasint2, mtypeint); + + std::string dpAliasdouble0 = "TestDouble0"; + DPID::FILL(mdoubleVar0, dpAliasdouble0, mtypedouble); + std::string dpAliasdouble1 = "TestDouble1"; + DPID::FILL(mdoubleVar1, dpAliasdouble1, mtypedouble); + std::string dpAliasdouble2 = "TestDouble2"; + DPID::FILL(mdoubleVar2, dpAliasdouble2, mtypedouble); + std::string dpAliasdouble3 = "TestDouble3"; + DPID::FILL(mdoubleVar3, dpAliasdouble3, mtypedouble); + + std::string dpAliasstring0 = "TestString0"; + DPID::FILL(mstringVar0, dpAliasstring0, mtypestring); + } + + void run(o2::framework::ProcessingContext& pc) final + { + + uint64_t tfid; + for (auto& input : pc.inputs()) { + tfid = header::get<o2::framework::DataProcessingHeader*>(input.header)->startTime; + LOG(INFO) << "tfid = " << tfid; + if (tfid >= mMaxTF) { + LOG(INFO) << "Data generator reached TF " << tfid << ", stopping"; + pc.services().get<o2::framework::ControlService>().endOfStream(); + pc.services().get<o2::framework::ControlService>().readyToQuit(o2::framework::QuitRequest::Me); + break; + } + } + + uint16_t flags = 0; + uint16_t milliseconds = 0; + TDatime currentTime; + uint32_t seconds = currentTime.Get(); + uint64_t* payload = new uint64_t[7]; + memset(payload, 0, sizeof(uint64_t) * 7); + + payload[0] = (uint64_t)tfid + 33; // adding 33 to have visible chars and strings + + DPVAL valchar(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypechar); + DPVAL valint(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypeint); + DPVAL valdouble(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypedouble); + DPVAL valstring(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypestring); + + LOG(DEBUG) << mcharVar; + LOG(DEBUG) << valchar << " --> " << (char)valchar.payload_pt1; + LOG(DEBUG) << mintVar0; + LOG(DEBUG) << valint << " --> " << (int)valint.payload_pt1; + LOG(DEBUG) << mintVar1; + LOG(DEBUG) << valint << " --> " << (int)valint.payload_pt1; + LOG(DEBUG) << mintVar2; + LOG(DEBUG) << valint << " --> " << (int)valint.payload_pt1; + LOG(DEBUG) << mdoubleVar0; + LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; + LOG(DEBUG) << mdoubleVar1; + LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; + LOG(DEBUG) << mdoubleVar2; + LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; + LOG(DEBUG) << mdoubleVar3; + LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; + char tt[56]; + memcpy(&tt[0], &valstring.payload_pt1, 56); + LOG(DEBUG) << mstringVar0; + LOG(DEBUG) << valstring << " --> " << tt; + auto& tmpDPmap = pc.outputs().make<std::unordered_map<DPID, DPVAL>>(o2::framework::OutputRef{"output", 0}); + tmpDPmap[mcharVar] = valchar; + tmpDPmap[mintVar0] = valint; + tmpDPmap[mintVar1] = valint; + tmpDPmap[mintVar2] = valint; + tmpDPmap[mdoubleVar0] = valdouble; + tmpDPmap[mdoubleVar1] = valdouble; + tmpDPmap[mdoubleVar2] = valdouble; + if (tfid % 3 == 0) + tmpDPmap[mdoubleVar3] = valdouble; // to test the case when a DP is not updated, we skip some updates + tmpDPmap[mstringVar0] = valstring; + delete payload; + } + + private: + uint64_t mMaxTF = 1; + o2::dcs::DataPointIdentifier mcharVar; + DPID mintVar0; + DPID mintVar1; + DPID mintVar2; + DPID mdoubleVar0; + DPID mdoubleVar1; + DPID mdoubleVar2; + DPID mdoubleVar3; + DPID mstringVar0; + DeliveryType mtypechar = RAW_CHAR; + DeliveryType mtypeint = RAW_INT; + DeliveryType mtypedouble = RAW_DOUBLE; + DeliveryType mtypestring = RAW_STRING; +}; + +} // namespace dcs + +namespace framework +{ + +DataProcessorSpec getDCSDataGeneratorSpec() +{ + return DataProcessorSpec{ + "dcs-data-generator", + Inputs{}, + Outputs{{{"output"}, "DCS", "DATAPOINTS"}}, + AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataGenerator>()}, + Options{{"max-timeframes", VariantType::Int64, 99999999999ll, {"max TimeFrames to generate"}}}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h new file mode 100644 index 0000000000000..e374a74577728 --- /dev/null +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -0,0 +1,113 @@ +// 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_DCS_DATAPROCESSOR_H +#define O2_DCS_DATAPROCESSOR_H + +/// @file DataGeneratorSpec.h +/// @brief Dummy data generator + +#include <unistd.h> +#include <TRandom.h> +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DeliveryType.h" +#include "DetectorsDCS/DCSProcessor.h" +#include "Framework/DeviceSpec.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" + +namespace o2 +{ +namespace dcs +{ + +using namespace o2::dcs; +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; + +class DCSDataProcessor : public o2::framework::Task +{ + public: + void init(o2::framework::InitContext& ic) final + { + std::vector<DPID> aliasVect; + + DeliveryType typechar = RAW_CHAR; + std::string dpAliaschar = "TestChar0"; + DPID charVar(dpAliaschar, typechar); + aliasVect.push_back(charVar); + + DeliveryType typeint = RAW_INT; + std::string dpAliasint0 = "TestInt0"; + DPID intVar0(dpAliasint0, typeint); + aliasVect.push_back(intVar0); + std::string dpAliasint1 = "TestInt1"; + DPID intVar1(dpAliasint1, typeint); + aliasVect.push_back(intVar1); + std::string dpAliasint2 = "TestInt2"; + DPID intVar2(dpAliasint2, typeint); + aliasVect.push_back(intVar2); + + DeliveryType typedouble = RAW_DOUBLE; + std::string dpAliasdouble0 = "TestDouble0"; + DPID doubleVar0(dpAliasdouble0, typedouble); + aliasVect.push_back(doubleVar0); + std::string dpAliasdouble1 = "TestDouble1"; + DPID doubleVar1(dpAliasdouble1, typedouble); + aliasVect.push_back(doubleVar1); + std::string dpAliasdouble2 = "TestDouble2"; + DPID doubleVar2(dpAliasdouble2, typedouble); + aliasVect.push_back(doubleVar2); + std::string dpAliasdouble3 = "TestDouble3"; + DPID doubleVar3(dpAliasdouble3, typedouble); + aliasVect.push_back(doubleVar3); + + DeliveryType typestring = RAW_STRING; + std::string dpAliasstring0 = "TestString0"; + DPID stringVar0(dpAliasstring0, typestring); + aliasVect.push_back(stringVar0); + + mDCSproc.init(aliasVect); + } + + void run(o2::framework::ProcessingContext& pc) final + { + auto tfcounter = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; + auto dcsmap = pc.inputs().get<std::unordered_map<DPID, DPVAL>*>("input"); + mDCSproc.process(*dcsmap); + } + + private: + o2::dcs::DCSProcessor mDCSproc; +}; + +} // namespace dcs + +namespace framework +{ + +DataProcessorSpec getDCSDataProcessorSpec() +{ + return DataProcessorSpec{ + "dcs-data-processor", + Inputs{{"input", "DCS", "DATAPOINTS"}}, + Outputs{{}}, + AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataProcessor>()}, + Options{}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/DCS/testWorkflow/dcs-data-workflow.cxx b/Detectors/DCS/testWorkflow/dcs-data-workflow.cxx new file mode 100644 index 0000000000000..9c4d84482489d --- /dev/null +++ b/Detectors/DCS/testWorkflow/dcs-data-workflow.cxx @@ -0,0 +1,43 @@ +// 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 "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "Framework/TypeTraits.h" +namespace o2::framework +{ +template <> +struct has_root_dictionary<std::unordered_map<o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue>, void> : std::true_type { +}; +} // namespace o2::framework +#include <unordered_map> +#include "Framework/DataProcessorSpec.h" +#include "DCSDataGeneratorSpec.h" +#include "DCSDataProcessorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getDCSDataGeneratorSpec()); + specs.emplace_back(getDCSDataProcessorSpec()); + return specs; +} From f4dc57b20e4d979e3e0c71f2c536193113e4af48 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Tue, 6 Oct 2020 23:39:11 +0200 Subject: [PATCH 0999/1751] Sending binary buffer. The unorderd_map is created in the processor part. bug fix clang... --- Detectors/DCS/src/DCSProcessor.cxx | 2 +- .../DCS/testWorkflow/DCSDataGeneratorSpec.h | 138 ++++++++++++------ .../DCS/testWorkflow/DCSDataProcessorSpec.h | 62 ++++---- 3 files changed, 130 insertions(+), 72 deletions(-) diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index d30ca945ed900..4d633b77459dd 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -347,7 +347,7 @@ void DCSProcessor::processInts() } bool isSMA = false; LOG(INFO) << "get alias = " << id.get_alias(); - if (strcmp(id.get_alias(), "TestInt0") == 0) { + if (strcmp(id.get_alias(), "TestInt_0") == 0) { doSimpleMovingAverage(2, vint, mAvgTestInt0, isSMA); LOG(INFO) << "Moving average = " << mAvgTestInt0; if (isSMA) { diff --git a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h index d078614108122..2ecea9a2c48aa 100644 --- a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h @@ -18,6 +18,7 @@ #include <TDatime.h> #include "DetectorsDCS/DataPointIdentifier.h" #include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DataPointCompositeObject.h" #include "DetectorsDCS/DeliveryType.h" #include "Framework/DeviceSpec.h" #include "Framework/ConfigParamRegistry.h" @@ -26,6 +27,8 @@ #include "Framework/Task.h" #include "Framework/Logger.h" +using namespace o2::framework; + namespace o2 { namespace dcs @@ -35,6 +38,7 @@ class DCSDataGenerator : public o2::framework::Task using DPID = o2::dcs::DataPointIdentifier; using DPVAL = o2::dcs::DataPointValue; + using DPCOM = o2::dcs::DataPointCompositeObject; public: void init(o2::framework::InitContext& ic) final @@ -42,27 +46,42 @@ class DCSDataGenerator : public o2::framework::Task mMaxTF = ic.options().get<int64_t>("max-timeframes"); LOG(INFO) << "mMaxTF = " << mMaxTF; - std::string dpAliaschar = "TestChar0"; - DPID::FILL(mcharVar, dpAliaschar, mtypechar); - - std::string dpAliasint0 = "TestInt0"; - DPID::FILL(mintVar0, dpAliasint0, mtypeint); - std::string dpAliasint1 = "TestInt1"; - DPID::FILL(mintVar1, dpAliasint1, mtypeint); - std::string dpAliasint2 = "TestInt2"; - DPID::FILL(mintVar2, dpAliasint2, mtypeint); - - std::string dpAliasdouble0 = "TestDouble0"; - DPID::FILL(mdoubleVar0, dpAliasdouble0, mtypedouble); - std::string dpAliasdouble1 = "TestDouble1"; - DPID::FILL(mdoubleVar1, dpAliasdouble1, mtypedouble); - std::string dpAliasdouble2 = "TestDouble2"; - DPID::FILL(mdoubleVar2, dpAliasdouble2, mtypedouble); - std::string dpAliasdouble3 = "TestDouble3"; - DPID::FILL(mdoubleVar3, dpAliasdouble3, mtypedouble); - - std::string dpAliasstring0 = "TestString0"; - DPID::FILL(mstringVar0, dpAliasstring0, mtypestring); + + DPID dpidtmp; + + // chars + std::string dpAliaschar = "TestChar_0"; + DPID::FILL(dpidtmp, dpAliaschar, mtypechar); + mDPIDvect.push_back(dpidtmp); + mNumDPs++; + mNumDPschar++; + + // ints + for (int i = 0; i < 3; i++) { + std::string dpAliasint = "TestInt_" + std::to_string(i); + DPID::FILL(dpidtmp, dpAliasint, mtypeint); + mDPIDvect.push_back(dpidtmp); + mNumDPs++; + mNumDPsint++; + } + + // doubles + for (int i = 0; i < 4; i++) { + std::string dpAliasdouble = "TestDouble_" + std::to_string(i); + DPID::FILL(dpidtmp, dpAliasdouble, mtypedouble); + mDPIDvect.push_back(dpidtmp); + mNumDPs++; + mNumDPsdouble++; + } + + // strings + std::string dpAliasstring0 = "TestString_0"; + DPID::FILL(dpidtmp, dpAliasstring0, mtypestring); + mDPIDvect.push_back(dpidtmp); + mNumDPs++; + mNumDPsstring++; + + LOG(INFO) << "Number of DCS data points = " << mNumDPs; } void run(o2::framework::ProcessingContext& pc) final @@ -76,8 +95,8 @@ class DCSDataGenerator : public o2::framework::Task LOG(INFO) << "Data generator reached TF " << tfid << ", stopping"; pc.services().get<o2::framework::ControlService>().endOfStream(); pc.services().get<o2::framework::ControlService>().readyToQuit(o2::framework::QuitRequest::Me); - break; } + break; // we break because one input is enough to get the TF ID } uint16_t flags = 0; @@ -94,26 +113,52 @@ class DCSDataGenerator : public o2::framework::Task DPVAL valdouble(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypedouble); DPVAL valstring(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypestring); - LOG(DEBUG) << mcharVar; - LOG(DEBUG) << valchar << " --> " << (char)valchar.payload_pt1; - LOG(DEBUG) << mintVar0; - LOG(DEBUG) << valint << " --> " << (int)valint.payload_pt1; - LOG(DEBUG) << mintVar1; - LOG(DEBUG) << valint << " --> " << (int)valint.payload_pt1; - LOG(DEBUG) << mintVar2; - LOG(DEBUG) << valint << " --> " << (int)valint.payload_pt1; - LOG(DEBUG) << mdoubleVar0; - LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; - LOG(DEBUG) << mdoubleVar1; - LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; - LOG(DEBUG) << mdoubleVar2; - LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; - LOG(DEBUG) << mdoubleVar3; - LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; + LOG(INFO) << "Value used for char DPs:"; + LOG(INFO) << valchar << " --> " << (char)valchar.payload_pt1; + LOG(INFO) << "Value used for int DPs:"; + LOG(INFO) << valint << " --> " << (int)valint.payload_pt1; + LOG(INFO) << "Value used for double DPs:"; + LOG(INFO) << valdouble << " --> " << (double)valdouble.payload_pt1; char tt[56]; memcpy(&tt[0], &valstring.payload_pt1, 56); - LOG(DEBUG) << mstringVar0; - LOG(DEBUG) << valstring << " --> " << tt; + LOG(INFO) << "Value used for string DPs:"; + LOG(INFO) << valstring << " --> " << tt; + + std::vector<DPCOM> dpcomVect; + for (int i = 0; i < mNumDPschar; i++) { + dpcomVect.emplace_back(mDPIDvect[i], valchar); + } + for (int i = 0; i < mNumDPsint; i++) { + dpcomVect.emplace_back(mDPIDvect[mNumDPschar + i], valint); + } + for (int i = 0; i < mNumDPsdouble; i++) { + dpcomVect.emplace_back(mDPIDvect[mNumDPschar + mNumDPsint + i], valdouble); + } + for (int i = 0; i < mNumDPsstring; i++) { + dpcomVect.emplace_back(mDPIDvect[mNumDPschar + mNumDPsint + mNumDPsdouble + i], valstring); + } + + auto svect = dpcomVect.size(); + LOG(INFO) << "dpcomVect has size " << svect; + for (int i = 0; i < svect; i++) { + LOG(INFO) << "i = " << i << ", DPCOM = " << dpcomVect[i]; + } + std::vector<char> buff(mNumDPs * sizeof(DPCOM)); + char* dptr = buff.data(); + for (int i = 0; i < svect; i++) { + memcpy(dptr + i * sizeof(DPCOM), &dpcomVect[i], sizeof(DPCOM)); + } + auto sbuff = buff.size(); + LOG(INFO) << "size of output buffer = " << sbuff; + pc.outputs().snapshot(Output{"DCS", "DATAPOINTS", 0, Lifetime::Timeframe}, buff.data(), sbuff); + + LOG(INFO) << "Reading back"; + DPCOM dptmp; + for (int i = 0; i < svect; i++) { + memcpy(&dptmp, dptr + i * sizeof(DPCOM), sizeof(DPCOM)); + LOG(INFO) << "Check: Reading from generator: i = " << i << ", DPCOM = " << dptmp; + } + /* auto& tmpDPmap = pc.outputs().make<std::unordered_map<DPID, DPVAL>>(o2::framework::OutputRef{"output", 0}); tmpDPmap[mcharVar] = valchar; tmpDPmap[mintVar0] = valint; @@ -125,12 +170,19 @@ class DCSDataGenerator : public o2::framework::Task if (tfid % 3 == 0) tmpDPmap[mdoubleVar3] = valdouble; // to test the case when a DP is not updated, we skip some updates tmpDPmap[mstringVar0] = valstring; + */ delete payload; } private: uint64_t mMaxTF = 1; - o2::dcs::DataPointIdentifier mcharVar; + uint64_t mNumDPs = 0; + uint64_t mNumDPschar = 0; + uint64_t mNumDPsint = 0; + uint64_t mNumDPsdouble = 0; + uint64_t mNumDPsstring = 0; + /* + DPID mcharVar; DPID mintVar0; DPID mintVar1; DPID mintVar2; @@ -139,6 +191,8 @@ class DCSDataGenerator : public o2::framework::Task DPID mdoubleVar2; DPID mdoubleVar3; DPID mstringVar0; + */ + std::vector<DPID> mDPIDvect; DeliveryType mtypechar = RAW_CHAR; DeliveryType mtypeint = RAW_INT; DeliveryType mtypedouble = RAW_DOUBLE; @@ -155,7 +209,7 @@ DataProcessorSpec getDCSDataGeneratorSpec() return DataProcessorSpec{ "dcs-data-generator", Inputs{}, - Outputs{{{"output"}, "DCS", "DATAPOINTS"}}, + Outputs{{{"outputDCS"}, "DCS", "DATAPOINTS"}}, AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataGenerator>()}, Options{{"max-timeframes", VariantType::Int64, 99999999999ll, {"max TimeFrames to generate"}}}}; } diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index e374a74577728..2e1c2d179a689 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -18,6 +18,7 @@ #include <TRandom.h> #include "DetectorsDCS/DataPointIdentifier.h" #include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DataPointCompositeObject.h" #include "DetectorsDCS/DeliveryType.h" #include "DetectorsDCS/DCSProcessor.h" #include "Framework/DeviceSpec.h" @@ -35,6 +36,7 @@ namespace dcs using namespace o2::dcs; using DPID = o2::dcs::DataPointIdentifier; using DPVAL = o2::dcs::DataPointValue; +using DPCOM = o2::dcs::DataPointCompositeObject; class DCSDataProcessor : public o2::framework::Task { @@ -43,40 +45,30 @@ class DCSDataProcessor : public o2::framework::Task { std::vector<DPID> aliasVect; + DPID dpidtmp; DeliveryType typechar = RAW_CHAR; - std::string dpAliaschar = "TestChar0"; - DPID charVar(dpAliaschar, typechar); - aliasVect.push_back(charVar); + std::string dpAliaschar = "TestChar_0"; + DPID::FILL(dpidtmp, dpAliaschar, typechar); + aliasVect.push_back(dpidtmp); DeliveryType typeint = RAW_INT; - std::string dpAliasint0 = "TestInt0"; - DPID intVar0(dpAliasint0, typeint); - aliasVect.push_back(intVar0); - std::string dpAliasint1 = "TestInt1"; - DPID intVar1(dpAliasint1, typeint); - aliasVect.push_back(intVar1); - std::string dpAliasint2 = "TestInt2"; - DPID intVar2(dpAliasint2, typeint); - aliasVect.push_back(intVar2); + for (int i = 0; i < 3; i++) { + std::string dpAliasint = "TestInt_" + std::to_string(i); + DPID::FILL(dpidtmp, dpAliasint, typeint); + aliasVect.push_back(dpidtmp); + } DeliveryType typedouble = RAW_DOUBLE; - std::string dpAliasdouble0 = "TestDouble0"; - DPID doubleVar0(dpAliasdouble0, typedouble); - aliasVect.push_back(doubleVar0); - std::string dpAliasdouble1 = "TestDouble1"; - DPID doubleVar1(dpAliasdouble1, typedouble); - aliasVect.push_back(doubleVar1); - std::string dpAliasdouble2 = "TestDouble2"; - DPID doubleVar2(dpAliasdouble2, typedouble); - aliasVect.push_back(doubleVar2); - std::string dpAliasdouble3 = "TestDouble3"; - DPID doubleVar3(dpAliasdouble3, typedouble); - aliasVect.push_back(doubleVar3); + for (int i = 0; i < 4; i++) { + std::string dpAliasdouble = "TestDouble_" + std::to_string(i); + DPID::FILL(dpidtmp, dpAliasdouble, typedouble); + aliasVect.push_back(dpidtmp); + } DeliveryType typestring = RAW_STRING; - std::string dpAliasstring0 = "TestString0"; - DPID stringVar0(dpAliasstring0, typestring); - aliasVect.push_back(stringVar0); + std::string dpAliasstring0 = "TestString_0"; + DPID::FILL(dpidtmp, dpAliasstring0, typestring); + aliasVect.push_back(dpidtmp); mDCSproc.init(aliasVect); } @@ -84,8 +76,20 @@ class DCSDataProcessor : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final { auto tfcounter = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; - auto dcsmap = pc.inputs().get<std::unordered_map<DPID, DPVAL>*>("input"); - mDCSproc.process(*dcsmap); + auto rawchar = pc.inputs().get<const char*>("input"); + const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("input").header); + auto sz = dh->payloadSize; + int nDPs = sz / sizeof(DPCOM); + LOG(INFO) << "Number of DPs received = " << nDPs; + std::unordered_map<DPID, DPVAL> dcsmap; + DPCOM dptmp; + for (int i = 0; i < nDPs; i++) { + memcpy(&dptmp, rawchar + i * sizeof(DPCOM), sizeof(DPCOM)); + dcsmap[dptmp.id] = dptmp.data; + LOG(INFO) << "Reading from generator: i = " << i << ", DPCOM = " << dptmp; + LOG(INFO) << "Reading from generator: i = " << i << ", DPID = " << dptmp.id; + } + mDCSproc.process(dcsmap); } private: From 3c20540cfa3f3a21a0a71c6905dbff9f79a99789 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Wed, 7 Oct 2020 23:15:39 +0200 Subject: [PATCH 1000/1751] Stressing the simulation using 50K points --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 6 ++-- Detectors/DCS/src/DCSProcessor.cxx | 32 +++++++++---------- .../DCS/testWorkflow/DCSDataGeneratorSpec.h | 10 +++--- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 6 ++-- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index c3802b5d72996..786b471c6d47c 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -90,7 +90,7 @@ class DCSProcessor DQBinaries& getVectorForAliasBinary(const DPID& id) { return mDpsbinariesmap[id]; } private: - float mAvgTestInt0 = 0; // moving average for DP named TestInt0 + std::vector<float> mAvgTestInt; // moving average for DP named TestInt0 std::unordered_map<DPID, DQChars> mDpscharsmap; std::unordered_map<DPID, DQInts> mDpsintsmap; std::unordered_map<DPID, DQDoubles> mDpsdoublesmap; @@ -152,9 +152,9 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType if (processFlag(flags, array[i].get_alias()) == 0) { auto etime = val.get_epoch_time(); // fill only if new value has a timestamp different from the timestamp of the previous one - LOG(INFO) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); + LOG(DEBUG) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { - LOG(INFO) << "adding new value"; + LOG(DEBUG) << "adding new value"; destmap[array[i]].push_back(val.payload_pt1); latestTimeStamp[i] = etime; } diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 4d633b77459dd..ee238c854d397 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -100,6 +100,7 @@ void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector mLatestTimestampstrings.resize(aliasesstrings.size(), 0); mLatestTimestamptimes.resize(aliasestimes.size(), 0); mLatestTimestampbinaries.resize(aliasesbinaries.size(), 0); + mAvgTestInt.resize(aliasesints.size(), 0); } //______________________________________________________________________ @@ -152,6 +153,7 @@ void DCSProcessor::init(const std::vector<DPID>& aliases) mLatestTimestampstrings.resize(nstrings, 0); mLatestTimestamptimes.resize(ntimes, 0); mLatestTimestampbinaries.resize(nbinaries, 0); + mAvgTestInt.resize(nints, 0); } //__________________________________________________________________ @@ -249,7 +251,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType if (processFlag(flags, array[i].get_alias()) == 0) { auto etime = val.get_epoch_time(); // fill only if new value has a timestamp different from the timestamp of the previous one - LOG(INFO) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); + LOG(DEBUG) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { auto& tmp = destmap[array[i]].emplace_back(); std::strncpy(tmp.data(), (char*)&(val.payload_pt1), 56); @@ -284,7 +286,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType if (processFlag(flags, array[i].get_alias()) == 0) { auto etime = val.get_epoch_time(); // fill only if new value has a timestamp different from the timestamp of the previous one - LOG(INFO) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); + LOG(DEBUG) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { auto& tmp = destmap[array[i]].emplace_back(); memcpy(tmp.data(), &(val.payload_pt1), 7); @@ -303,7 +305,7 @@ std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::processAlias(const // processing basic checks for map: all needed aliases must be present - LOG(INFO) << "Processing " << alias; + LOG(DEBUG) << "Processing " << alias; auto it = map.find(alias); DeliveryType tt = alias.get_type(); if (tt != type) { @@ -320,12 +322,12 @@ void DCSProcessor::processChars() // function to process aliases of Char type; it will just print them for (size_t i = 0; i != mAliaseschars.size(); ++i) { - LOG(INFO) << "processChars: mAliaseschars[" << i << "] = " << mAliaseschars[i]; + LOG(DEBUG) << "processChars: mAliaseschars[" << i << "] = " << mAliaseschars[i]; auto& id = mAliaseschars[i]; auto& vchar = getVectorForAliasChar(id); - LOG(INFO) << "vchar size = " << vchar.size(); + LOG(DEBUG) << "vchar size = " << vchar.size(); for (size_t j = 0; j < vchar.size(); j++) { - LOG(INFO) << "DP = " << mAliaseschars[i] << " , value[" << j << "] = " << vchar[j]; + LOG(DEBUG) << "DP = " << mAliaseschars[i] << " , value[" << j << "] = " << vchar[j]; } } } @@ -338,21 +340,19 @@ void DCSProcessor::processInts() // function to process aliases of Int type for (size_t i = 0; i != mAliasesints.size(); ++i) { - LOG(INFO) << "processInts: mAliasesints[" << i << "] = " << mAliasesints[i]; + LOG(DEBUG) << "processInts: mAliasesints[" << i << "] = " << mAliasesints[i]; auto& id = mAliasesints[i]; auto& vint = getVectorForAliasInt(id); - LOG(INFO) << "vint size = " << vint.size(); + LOG(DEBUG) << "vint size = " << vint.size(); for (size_t j = 0; j < vint.size(); j++) { - LOG(INFO) << "DP = " << mAliasesints[i] << " , value[" << j << "] = " << vint[j]; + LOG(DEBUG) << "DP = " << mAliasesints[i] << " , value[" << j << "] = " << vint[j]; } bool isSMA = false; - LOG(INFO) << "get alias = " << id.get_alias(); - if (strcmp(id.get_alias(), "TestInt_0") == 0) { - doSimpleMovingAverage(2, vint, mAvgTestInt0, isSMA); - LOG(INFO) << "Moving average = " << mAvgTestInt0; - if (isSMA) { - // populate CCDB - } + LOG(DEBUG) << "get alias = " << id.get_alias(); + doSimpleMovingAverage(2, vint, mAvgTestInt[i], isSMA); + LOG(DEBUG) << "Moving average = " << mAvgTestInt[i]; + if (isSMA) { + // populate CCDB } } } diff --git a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h index 2ecea9a2c48aa..1f86407d98476 100644 --- a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h @@ -57,7 +57,7 @@ class DCSDataGenerator : public o2::framework::Task mNumDPschar++; // ints - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasint, mtypeint); mDPIDvect.push_back(dpidtmp); @@ -141,7 +141,7 @@ class DCSDataGenerator : public o2::framework::Task auto svect = dpcomVect.size(); LOG(INFO) << "dpcomVect has size " << svect; for (int i = 0; i < svect; i++) { - LOG(INFO) << "i = " << i << ", DPCOM = " << dpcomVect[i]; + LOG(DEBUG) << "i = " << i << ", DPCOM = " << dpcomVect[i]; } std::vector<char> buff(mNumDPs * sizeof(DPCOM)); char* dptr = buff.data(); @@ -149,15 +149,17 @@ class DCSDataGenerator : public o2::framework::Task memcpy(dptr + i * sizeof(DPCOM), &dpcomVect[i], sizeof(DPCOM)); } auto sbuff = buff.size(); - LOG(INFO) << "size of output buffer = " << sbuff; + LOG(DEBUG) << "size of output buffer = " << sbuff; pc.outputs().snapshot(Output{"DCS", "DATAPOINTS", 0, Lifetime::Timeframe}, buff.data(), sbuff); + /* LOG(INFO) << "Reading back"; DPCOM dptmp; for (int i = 0; i < svect; i++) { memcpy(&dptmp, dptr + i * sizeof(DPCOM), sizeof(DPCOM)); - LOG(INFO) << "Check: Reading from generator: i = " << i << ", DPCOM = " << dptmp; + LOG(DEBUG) << "Check: Reading from generator: i = " << i << ", DPCOM = " << dptmp; } + */ /* auto& tmpDPmap = pc.outputs().make<std::unordered_map<DPID, DPVAL>>(o2::framework::OutputRef{"output", 0}); tmpDPmap[mcharVar] = valchar; diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index 2e1c2d179a689..e6b65f39b936f 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -52,7 +52,7 @@ class DCSDataProcessor : public o2::framework::Task aliasVect.push_back(dpidtmp); DeliveryType typeint = RAW_INT; - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasint, typeint); aliasVect.push_back(dpidtmp); @@ -86,8 +86,8 @@ class DCSDataProcessor : public o2::framework::Task for (int i = 0; i < nDPs; i++) { memcpy(&dptmp, rawchar + i * sizeof(DPCOM), sizeof(DPCOM)); dcsmap[dptmp.id] = dptmp.data; - LOG(INFO) << "Reading from generator: i = " << i << ", DPCOM = " << dptmp; - LOG(INFO) << "Reading from generator: i = " << i << ", DPID = " << dptmp.id; + LOG(DEBUG) << "Reading from generator: i = " << i << ", DPCOM = " << dptmp; + LOG(DEBUG) << "Reading from generator: i = " << i << ", DPID = " << dptmp.id; } mDCSproc.process(dcsmap); } From 6e56e494265a77c8733a10c5fa74c2f7a30721f6 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Fri, 9 Oct 2020 00:12:10 +0200 Subject: [PATCH 1001/1751] Template of simple moving average. --- Detectors/DCS/CMakeLists.txt | 7 ++- .../DCS/include/DetectorsDCS/DCSProcessor.h | 44 ++++++++++++++++--- Detectors/DCS/src/DCSProcessor.cxx | 19 +++++++- .../DCS/testWorkflow/DCSDataGeneratorSpec.h | 30 ++++++++----- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 16 ++++++- 5 files changed, 97 insertions(+), 19 deletions(-) diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt index a6bec21667f42..d5b1c5a3dc440 100644 --- a/Detectors/DCS/CMakeLists.txt +++ b/Detectors/DCS/CMakeLists.txt @@ -8,8 +8,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. - o2_add_library(DetectorsDCS + TARGETVARNAME targetName SOURCES src/Clock.cxx src/DataPointCompositeObject.cxx src/DataPointIdentifier.cxx @@ -33,3 +33,8 @@ o2_add_executable(dcs-data-workflow SOURCES testWorkflow/dcs-data-workflow.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) + +if (OpenMP_CXX_FOUND) + target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) + target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) +endif() diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index 786b471c6d47c..e93fa870ee218 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -21,6 +21,10 @@ #include "DetectorsDCS/DataPointValue.h" #include "DetectorsDCS/DeliveryType.h" +//#ifdef WITH_OPENMP +//#include <omp.h> +//#endif + /// @brief Class to process DCS data points namespace o2 @@ -68,6 +72,9 @@ class DCSProcessor template <typename T> int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap); + template <typename T> + void doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA); + virtual void processChars(); virtual void processInts(); virtual void processDoubles(); @@ -78,8 +85,6 @@ class DCSProcessor virtual void processBinaries(); virtual uint64_t processFlag(uint64_t flag, const char* alias); - void doSimpleMovingAverage(int nelements, std::deque<int>& vect, float& avg, bool& isSMA); - DQChars& getVectorForAliasChar(const DPID& id) { return mDpscharsmap[id]; } DQInts& getVectorForAliasInt(const DPID& id) { return mDpsintsmap[id]; } DQDoubles& getVectorForAliasDouble(const DPID& id) { return mDpsdoublesmap[id]; } @@ -88,9 +93,13 @@ class DCSProcessor DQStrings& getVectorForAliasString(const DPID& id) { return mDpsstringsmap[id]; } DQTimes& getVectorForAliasTime(const DPID& id) { return mDpstimesmap[id]; } DQBinaries& getVectorForAliasBinary(const DPID& id) { return mDpsbinariesmap[id]; } - + + void setNThreads(int n); + int getNThreads() const { return mNThreads; } + private: - std::vector<float> mAvgTestInt; // moving average for DP named TestInt0 + std::vector<float> mAvgTestInt; // moving average for int DPs + std::vector<float> mAvgTestDouble; // moving average for double DPs std::unordered_map<DPID, DQChars> mDpscharsmap; std::unordered_map<DPID, DQInts> mDpsintsmap; std::unordered_map<DPID, DQDoubles> mDpsdoublesmap; @@ -115,7 +124,8 @@ class DCSProcessor std::vector<uint64_t> mLatestTimestampstrings; std::vector<uint64_t> mLatestTimestamptimes; std::vector<uint64_t> mLatestTimestampbinaries; - + int mNThreads = 1; // number of threads + ClassDefNV(DCSProcessor, 0); }; @@ -140,6 +150,10 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType int found = 0; auto s = array.size(); if (s > 0) { + //#ifdef WITH_OPENMP + //omp_set_num_threads(mNThreads); + //#pragma omp parallel for schedule(dynamic) + //#endif for (size_t i = 0; i != s; ++i) { auto it = processAlias(array[i], type, map); if (it == map.end()) { @@ -170,6 +184,26 @@ int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, template <> int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQBinaries>& destmap); +template <typename T> +void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA) { + + // Do simple moving average on vector of type T + + if (vect.size() < nelements) { + avg += vect[vect.size() - 1]; + return; + } + if (vect.size() == nelements) { + avg += vect[vect.size() - 1]; + avg /= nelements; + isSMA = true; + return; + } + avg += (vect[vect.size() - 1] - vect[0]) / nelements; + vect.pop_front(); + isSMA = true; +} + } // namespace dcs } // namespace o2 diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index ee238c854d397..489ba3b041f15 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -349,6 +349,7 @@ void DCSProcessor::processInts() } bool isSMA = false; LOG(DEBUG) << "get alias = " << id.get_alias(); + // I do the moving average always of the last 2 points, no matter if it was updated or not doSimpleMovingAverage(2, vint, mAvgTestInt[i], isSMA); LOG(DEBUG) << "Moving average = " << mAvgTestInt[i]; if (isSMA) { @@ -358,7 +359,7 @@ void DCSProcessor::processInts() } //______________________________________________________________________ - +/* void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<int>& vect, float& avg, bool& isSMA) { @@ -377,7 +378,7 @@ void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<int>& vect, f vect.pop_front(); isSMA = true; } - +*/ //______________________________________________________________________ void DCSProcessor::processDoubles() @@ -485,3 +486,17 @@ uint64_t DCSProcessor::processFlag(const uint64_t flags, const char* alias) return 0; } + +//______________________________________________________________________ + +void DCSProcessor::setNThreads(int n) { + + // to set number of threads used to process the DPs + +#ifdef WITH_OPENMP + mNThreads = n > 0 ? n : 1; +#else + LOG(WARNING) << " Multithreading is not supported, imposing single thread"; + mNThreads = 1; +#endif +} diff --git a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h index 1f86407d98476..8819225ec4dab 100644 --- a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h @@ -16,6 +16,7 @@ #include <unistd.h> #include <TRandom.h> #include <TDatime.h> +#include <TStopwatch.h> #include "DetectorsDCS/DataPointIdentifier.h" #include "DetectorsDCS/DataPointValue.h" #include "DetectorsDCS/DataPointCompositeObject.h" @@ -87,10 +88,11 @@ class DCSDataGenerator : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final { + TStopwatch s; uint64_t tfid; for (auto& input : pc.inputs()) { tfid = header::get<o2::framework::DataProcessingHeader*>(input.header)->startTime; - LOG(INFO) << "tfid = " << tfid; + LOG(DEBUG) << "tfid = " << tfid; if (tfid >= mMaxTF) { LOG(INFO) << "Data generator reached TF " << tfid << ", stopping"; pc.services().get<o2::framework::ControlService>().endOfStream(); @@ -99,6 +101,8 @@ class DCSDataGenerator : public o2::framework::Task break; // we break because one input is enough to get the TF ID } + LOG(INFO) << "TF: " << tfid << " --> building binary blob..."; + s.Start(); uint16_t flags = 0; uint16_t milliseconds = 0; TDatime currentTime; @@ -113,16 +117,16 @@ class DCSDataGenerator : public o2::framework::Task DPVAL valdouble(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypedouble); DPVAL valstring(flags, milliseconds + tfid * 10, seconds + tfid, payload, mtypestring); - LOG(INFO) << "Value used for char DPs:"; - LOG(INFO) << valchar << " --> " << (char)valchar.payload_pt1; - LOG(INFO) << "Value used for int DPs:"; - LOG(INFO) << valint << " --> " << (int)valint.payload_pt1; - LOG(INFO) << "Value used for double DPs:"; - LOG(INFO) << valdouble << " --> " << (double)valdouble.payload_pt1; + LOG(DEBUG) << "Value used for char DPs:"; + LOG(DEBUG) << valchar << " --> " << (char)valchar.payload_pt1; + LOG(DEBUG) << "Value used for int DPs:"; + LOG(DEBUG) << valint << " --> " << (int)valint.payload_pt1; + LOG(DEBUG) << "Value used for double DPs:"; + LOG(DEBUG) << valdouble << " --> " << (double)valdouble.payload_pt1; char tt[56]; memcpy(&tt[0], &valstring.payload_pt1, 56); - LOG(INFO) << "Value used for string DPs:"; - LOG(INFO) << valstring << " --> " << tt; + LOG(DEBUG) << "Value used for string DPs:"; + LOG(DEBUG) << valstring << " --> " << tt; std::vector<DPCOM> dpcomVect; for (int i = 0; i < mNumDPschar; i++) { @@ -139,7 +143,7 @@ class DCSDataGenerator : public o2::framework::Task } auto svect = dpcomVect.size(); - LOG(INFO) << "dpcomVect has size " << svect; + LOG(DEBUG) << "dpcomVect has size " << svect; for (int i = 0; i < svect; i++) { LOG(DEBUG) << "i = " << i << ", DPCOM = " << dpcomVect[i]; } @@ -150,7 +154,13 @@ class DCSDataGenerator : public o2::framework::Task } auto sbuff = buff.size(); LOG(DEBUG) << "size of output buffer = " << sbuff; + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...binary blob prepared: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + LOG(INFO) << "TF: " << tfid << " --> sending snapshot..."; + s.Start(); pc.outputs().snapshot(Output{"DCS", "DATAPOINTS", 0, Lifetime::Timeframe}, buff.data(), sbuff); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...snapshot sent: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); /* LOG(INFO) << "Reading back"; diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index e6b65f39b936f..4160421b17dc4 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -16,6 +16,7 @@ #include <unistd.h> #include <TRandom.h> +#include <TStopwatch.h> #include "DetectorsDCS/DataPointIdentifier.h" #include "DetectorsDCS/DataPointValue.h" #include "DetectorsDCS/DataPointCompositeObject.h" @@ -75,21 +76,34 @@ class DCSDataProcessor : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final { - auto tfcounter = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; + auto tfid = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; + TStopwatch s; + LOG(INFO) << "TF: " << tfid << " --> receiving binary data..."; + s.Start(); auto rawchar = pc.inputs().get<const char*>("input"); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...binary data received: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("input").header); auto sz = dh->payloadSize; int nDPs = sz / sizeof(DPCOM); LOG(INFO) << "Number of DPs received = " << nDPs; std::unordered_map<DPID, DPVAL> dcsmap; DPCOM dptmp; + LOG(INFO) << "TF: " << tfid << " --> building unordered_map..."; + s.Start(); for (int i = 0; i < nDPs; i++) { memcpy(&dptmp, rawchar + i * sizeof(DPCOM), sizeof(DPCOM)); dcsmap[dptmp.id] = dptmp.data; LOG(DEBUG) << "Reading from generator: i = " << i << ", DPCOM = " << dptmp; LOG(DEBUG) << "Reading from generator: i = " << i << ", DPID = " << dptmp.id; } + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...unordered_map built = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + LOG(INFO) << "TF: " << tfid << " --> starting processing..."; + s.Start(); mDCSproc.process(dcsmap); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); } private: From 327a1b7819b5628fcce6e46012c0ec54036348bb Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Fri, 9 Oct 2020 23:28:59 +0200 Subject: [PATCH 1002/1751] Adding publishing in CCDB part e.g.: o2-dcs-dcs-data-workflow --max-timeframes 100 -b | o2-calibration-ccdb-populator-workflow --ccdb-path localhost:8080 -b clang-format Setting TF Clang-format Generating and receiving also a delta map (Not yet processed) Clang... Fix to stupid mistake --- Detectors/DCS/CMakeLists.txt | 2 + .../DCS/include/DetectorsDCS/DCSProcessor.h | 44 ++++++- Detectors/DCS/src/DCSProcessor.cxx | 36 ++--- .../DCS/testWorkflow/DCSDataGeneratorSpec.h | 124 ++++++++++++------ .../DCS/testWorkflow/DCSDataProcessorSpec.h | 60 ++++++++- 5 files changed, 194 insertions(+), 72 deletions(-) diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt index d5b1c5a3dc440..1d037f297f6da 100644 --- a/Detectors/DCS/CMakeLists.txt +++ b/Detectors/DCS/CMakeLists.txt @@ -20,6 +20,8 @@ o2_add_library(DetectorsDCS src/DCSProcessor.cxx PUBLIC_LINK_LIBRARIES O2::Headers O2::CommonUtils + O2::CCDB + O2::DetectorsCalibration ms_gsl::ms_gsl) o2_target_root_dictionary(DetectorsDCS diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index e93fa870ee218..d204e606cdaaf 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -20,6 +20,9 @@ #include "DetectorsDCS/DataPointIdentifier.h" #include "DetectorsDCS/DataPointValue.h" #include "DetectorsDCS/DeliveryType.h" +#include "CCDB/CcdbObjectInfo.h" +#include "CommonUtils/MemFileHelper.h" +#include "CCDB/CcdbApi.h" //#ifdef WITH_OPENMP //#include <omp.h> @@ -55,6 +58,9 @@ class DCSProcessor using DPVAL = o2::dcs::DataPointValue; using DPCOM = o2::dcs::DataPointCompositeObject; + using TFType = uint64_t; + using CcdbObjectInfo = o2::ccdb::CcdbObjectInfo; + DCSProcessor() = default; ~DCSProcessor() = default; @@ -93,12 +99,20 @@ class DCSProcessor DQStrings& getVectorForAliasString(const DPID& id) { return mDpsstringsmap[id]; } DQTimes& getVectorForAliasTime(const DPID& id) { return mDpstimesmap[id]; } DQBinaries& getVectorForAliasBinary(const DPID& id) { return mDpsbinariesmap[id]; } - + void setNThreads(int n); int getNThreads() const { return mNThreads; } - + const std::unordered_map<std::string, float>& getCCDBint() const { return mccdbInt; } + const CcdbObjectInfo& getCCDBintInfo() const { return mccdbIntInfo; } + CcdbObjectInfo& getCCDBintInfo() { return mccdbIntInfo; } + + void setTF(TFType tf) { mTF = tf; } + + template <typename T> + void prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md); + private: - std::vector<float> mAvgTestInt; // moving average for int DPs + std::vector<float> mAvgTestInt; // moving average for int DPs std::vector<float> mAvgTestDouble; // moving average for double DPs std::unordered_map<DPID, DQChars> mDpscharsmap; std::unordered_map<DPID, DQInts> mDpsintsmap; @@ -124,8 +138,11 @@ class DCSProcessor std::vector<uint64_t> mLatestTimestampstrings; std::vector<uint64_t> mLatestTimestamptimes; std::vector<uint64_t> mLatestTimestampbinaries; - int mNThreads = 1; // number of threads - + int mNThreads = 1; // number of threads + std::unordered_map<std::string, float> mccdbInt; // unordered map in which to store the CCDB entry + CcdbObjectInfo mccdbIntInfo; // info to store the output of teh calibration on int values + TFType mTF = 0; // TF index for processing, used to store CCDB object + ClassDefNV(DCSProcessor, 0); }; @@ -185,7 +202,8 @@ template <> int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQBinaries>& destmap); template <typename T> -void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA) { +void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA) +{ // Do simple moving average on vector of type T @@ -204,6 +222,20 @@ void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, flo isSMA = true; } +template <typename T> +void DCSProcessor::prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md) +{ + + // prepare all info to be sent to CCDB for object obj + auto clName = o2::utils::MemFileHelper::getClassName(obj); + auto flName = o2::ccdb::CcdbApi::generateFileName(clName); + info.setPath(path); + info.setObjectType(clName); + info.setFileName(flName); + info.setStartValidityTimestamp(tf); + info.setEndValidityTimestamp(99999999999999); + info.setMetaData(md); +} } // namespace dcs } // namespace o2 diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 489ba3b041f15..70bfaaef1ea27 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -163,7 +163,10 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map) // process function to do "something" with the DCS map that is passed - // first, we need to check if there are the Data Points that we need + // resetting the content of the CCDB object to be sent + mccdbInt.clear(); + + // we need to check if there are the Data Points that we need int foundChars = 0, foundInts = 0, foundDoubles = 0, foundUInts = 0, foundBools = 0, foundStrings = 0, foundTimes = 0, foundBinaries = 0; @@ -353,32 +356,14 @@ void DCSProcessor::processInts() doSimpleMovingAverage(2, vint, mAvgTestInt[i], isSMA); LOG(DEBUG) << "Moving average = " << mAvgTestInt[i]; if (isSMA) { - // populate CCDB + // create CCDB object + mccdbInt[id.get_alias()] = mAvgTestInt[i]; } } + std::map<std::string, std::string> md; + prepareCCDBobject(mccdbInt, mccdbIntInfo, "TestDCS/IntDPs", mTF, md); } -//______________________________________________________________________ -/* -void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<int>& vect, float& avg, bool& isSMA) -{ - - // Do simple moving average on vector of ints - if (vect.size() < nelements) { - avg += vect[vect.size() - 1]; - return; - } - if (vect.size() == nelements) { - avg += vect[vect.size() - 1]; - avg /= nelements; - isSMA = true; - return; - } - avg += (vect[vect.size() - 1] - vect[0]) / nelements; - vect.pop_front(); - isSMA = true; -} -*/ //______________________________________________________________________ void DCSProcessor::processDoubles() @@ -489,10 +474,11 @@ uint64_t DCSProcessor::processFlag(const uint64_t flags, const char* alias) //______________________________________________________________________ -void DCSProcessor::setNThreads(int n) { +void DCSProcessor::setNThreads(int n) +{ // to set number of threads used to process the DPs - + #ifdef WITH_OPENMP mNThreads = n > 0 ? n : 1; #else diff --git a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h index 8819225ec4dab..7168dacbd601b 100644 --- a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h @@ -53,42 +53,47 @@ class DCSDataGenerator : public o2::framework::Task // chars std::string dpAliaschar = "TestChar_0"; DPID::FILL(dpidtmp, dpAliaschar, mtypechar); - mDPIDvect.push_back(dpidtmp); - mNumDPs++; - mNumDPschar++; + mDPIDvectFull.push_back(dpidtmp); + mNumDPsFull++; + mNumDPscharFull++; // ints for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasint, mtypeint); - mDPIDvect.push_back(dpidtmp); - mNumDPs++; - mNumDPsint++; + mDPIDvectFull.push_back(dpidtmp); + mNumDPsFull++; + mNumDPsintFull++; + if (i < 100) { + mDPIDvectDelta.push_back(dpidtmp); + mNumDPsDelta++; + mNumDPsintDelta++; + } } // doubles for (int i = 0; i < 4; i++) { std::string dpAliasdouble = "TestDouble_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasdouble, mtypedouble); - mDPIDvect.push_back(dpidtmp); - mNumDPs++; - mNumDPsdouble++; + mDPIDvectFull.push_back(dpidtmp); + mNumDPsFull++; + mNumDPsdoubleFull++; } // strings std::string dpAliasstring0 = "TestString_0"; DPID::FILL(dpidtmp, dpAliasstring0, mtypestring); - mDPIDvect.push_back(dpidtmp); - mNumDPs++; - mNumDPsstring++; + mDPIDvectFull.push_back(dpidtmp); + mNumDPsFull++; + mNumDPsstringFull++; - LOG(INFO) << "Number of DCS data points = " << mNumDPs; + LOG(INFO) << "Number of DCS data points: " << mNumDPsFull << " (full map); " << mNumDPsDelta << " (delta map)"; } void run(o2::framework::ProcessingContext& pc) final { - TStopwatch s; + TStopwatch s; uint64_t tfid; for (auto& input : pc.inputs()) { tfid = header::get<o2::framework::DataProcessingHeader*>(input.header)->startTime; @@ -107,7 +112,7 @@ class DCSDataGenerator : public o2::framework::Task uint16_t milliseconds = 0; TDatime currentTime; uint32_t seconds = currentTime.Get(); - uint64_t* payload = new uint64_t[7]; + uint64_t payload[7]; memset(payload, 0, sizeof(uint64_t) * 7); payload[0] = (uint64_t)tfid + 33; // adding 33 to have visible chars and strings @@ -128,29 +133,46 @@ class DCSDataGenerator : public o2::framework::Task LOG(DEBUG) << "Value used for string DPs:"; LOG(DEBUG) << valstring << " --> " << tt; - std::vector<DPCOM> dpcomVect; - for (int i = 0; i < mNumDPschar; i++) { - dpcomVect.emplace_back(mDPIDvect[i], valchar); + // full map (all DPs) + std::vector<DPCOM> dpcomVectFull; + for (int i = 0; i < mNumDPscharFull; i++) { + dpcomVectFull.emplace_back(mDPIDvectFull[i], valchar); } - for (int i = 0; i < mNumDPsint; i++) { - dpcomVect.emplace_back(mDPIDvect[mNumDPschar + i], valint); + for (int i = 0; i < mNumDPsintFull; i++) { + dpcomVectFull.emplace_back(mDPIDvectFull[mNumDPscharFull + i], valint); } - for (int i = 0; i < mNumDPsdouble; i++) { - dpcomVect.emplace_back(mDPIDvect[mNumDPschar + mNumDPsint + i], valdouble); + for (int i = 0; i < mNumDPsdoubleFull; i++) { + dpcomVectFull.emplace_back(mDPIDvectFull[mNumDPscharFull + mNumDPsintFull + i], valdouble); } - for (int i = 0; i < mNumDPsstring; i++) { - dpcomVect.emplace_back(mDPIDvect[mNumDPschar + mNumDPsint + mNumDPsdouble + i], valstring); + for (int i = 0; i < mNumDPsstringFull; i++) { + dpcomVectFull.emplace_back(mDPIDvectFull[mNumDPscharFull + mNumDPsintFull + mNumDPsdoubleFull + i], valstring); } - auto svect = dpcomVect.size(); - LOG(DEBUG) << "dpcomVect has size " << svect; + // delta map (only DPs that changed) + std::vector<DPCOM> dpcomVectDelta; + for (int i = 0; i < mNumDPscharDelta; i++) { + dpcomVectDelta.emplace_back(mDPIDvectDelta[i], valchar); + } + for (int i = 0; i < mNumDPsintDelta; i++) { + dpcomVectDelta.emplace_back(mDPIDvectDelta[mNumDPscharDelta + i], valint); + } + for (int i = 0; i < mNumDPsdoubleDelta; i++) { + dpcomVectDelta.emplace_back(mDPIDvectDelta[mNumDPscharDelta + mNumDPsintDelta + i], valdouble); + } + for (int i = 0; i < mNumDPsstringDelta; i++) { + dpcomVectDelta.emplace_back(mDPIDvectDelta[mNumDPscharDelta + mNumDPsintDelta + mNumDPsdoubleDelta + i], valstring); + } + + // Full map + auto svect = dpcomVectFull.size(); + LOG(DEBUG) << "dpcomVectFull has size " << svect; for (int i = 0; i < svect; i++) { - LOG(DEBUG) << "i = " << i << ", DPCOM = " << dpcomVect[i]; + LOG(DEBUG) << "i = " << i << ", DPCOM = " << dpcomVectFull[i]; } - std::vector<char> buff(mNumDPs * sizeof(DPCOM)); + std::vector<char> buff(mNumDPsFull * sizeof(DPCOM)); char* dptr = buff.data(); for (int i = 0; i < svect; i++) { - memcpy(dptr + i * sizeof(DPCOM), &dpcomVect[i], sizeof(DPCOM)); + memcpy(dptr + i * sizeof(DPCOM), &dpcomVectFull[i], sizeof(DPCOM)); } auto sbuff = buff.size(); LOG(DEBUG) << "size of output buffer = " << sbuff; @@ -162,6 +184,27 @@ class DCSDataGenerator : public o2::framework::Task s.Stop(); LOG(INFO) << "TF: " << tfid << " --> ...snapshot sent: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + // Delta map + auto svectDelta = dpcomVectDelta.size(); + LOG(DEBUG) << "dpcomVectDelta has size " << svect; + for (int i = 0; i < svectDelta; i++) { + LOG(DEBUG) << "i = " << i << ", DPCOM = " << dpcomVectDelta[i]; + } + std::vector<char> buffDelta(mNumDPsDelta * sizeof(DPCOM)); + char* dptrDelta = buffDelta.data(); + for (int i = 0; i < svectDelta; i++) { + memcpy(dptrDelta + i * sizeof(DPCOM), &dpcomVectDelta[i], sizeof(DPCOM)); + } + auto sbuffDelta = buffDelta.size(); + LOG(DEBUG) << "size of output (delta) buffer = " << sbuffDelta; + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...binary (delta) blob prepared: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + LOG(INFO) << "TF: " << tfid << " --> sending (delta) snapshot..."; + s.Start(); + pc.outputs().snapshot(Output{"DCS", "DATAPOINTSdelta", 0, Lifetime::Timeframe}, buffDelta.data(), sbuffDelta); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...snapshot (delta) sent: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + /* LOG(INFO) << "Reading back"; DPCOM dptmp; @@ -183,16 +226,22 @@ class DCSDataGenerator : public o2::framework::Task tmpDPmap[mdoubleVar3] = valdouble; // to test the case when a DP is not updated, we skip some updates tmpDPmap[mstringVar0] = valstring; */ - delete payload; } private: uint64_t mMaxTF = 1; - uint64_t mNumDPs = 0; - uint64_t mNumDPschar = 0; - uint64_t mNumDPsint = 0; - uint64_t mNumDPsdouble = 0; - uint64_t mNumDPsstring = 0; + + uint64_t mNumDPsFull = 0; + uint64_t mNumDPscharFull = 0; + uint64_t mNumDPsintFull = 0; + uint64_t mNumDPsdoubleFull = 0; + uint64_t mNumDPsstringFull = 0; + + uint64_t mNumDPsDelta = 0; + uint64_t mNumDPscharDelta = 0; + uint64_t mNumDPsintDelta = 0; + uint64_t mNumDPsdoubleDelta = 0; + uint64_t mNumDPsstringDelta = 0; /* DPID mcharVar; DPID mintVar0; @@ -204,7 +253,8 @@ class DCSDataGenerator : public o2::framework::Task DPID mdoubleVar3; DPID mstringVar0; */ - std::vector<DPID> mDPIDvect; + std::vector<DPID> mDPIDvectFull; // for full map + std::vector<DPID> mDPIDvectDelta; // for delta map (containing only DPs that changed) DeliveryType mtypechar = RAW_CHAR; DeliveryType mtypeint = RAW_INT; DeliveryType mtypedouble = RAW_DOUBLE; @@ -221,7 +271,7 @@ DataProcessorSpec getDCSDataGeneratorSpec() return DataProcessorSpec{ "dcs-data-generator", Inputs{}, - Outputs{{{"outputDCS"}, "DCS", "DATAPOINTS"}}, + Outputs{{{"outputDCS"}, "DCS", "DATAPOINTS"}, {{"outputDCSdelta"}, "DCS", "DATAPOINTSdelta"}}, AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataGenerator>()}, Options{{"max-timeframes", VariantType::Int64, 99999999999ll, {"max TimeFrames to generate"}}}}; } diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index 4160421b17dc4..ebf863299e270 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -22,6 +22,8 @@ #include "DetectorsDCS/DataPointCompositeObject.h" #include "DetectorsDCS/DeliveryType.h" #include "DetectorsDCS/DCSProcessor.h" +#include "DetectorsCalibration/Utils.h" +#include "CCDB/CcdbApi.h" #include "Framework/DeviceSpec.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" @@ -77,12 +79,21 @@ class DCSDataProcessor : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final { auto tfid = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; - TStopwatch s; + mDCSproc.setTF(tfid); + + TStopwatch s; LOG(INFO) << "TF: " << tfid << " --> receiving binary data..."; s.Start(); auto rawchar = pc.inputs().get<const char*>("input"); s.Stop(); LOG(INFO) << "TF: " << tfid << " --> ...binary data received: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + LOG(INFO) << "TF: " << tfid << " --> receiving (delta) binary data..."; + s.Start(); + auto rawcharDelta = pc.inputs().get<const char*>("inputDelta"); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...binary (delta) data received: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + + // full map const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("input").header); auto sz = dh->payloadSize; int nDPs = sz / sizeof(DPCOM); @@ -99,17 +110,51 @@ class DCSDataProcessor : public o2::framework::Task } s.Stop(); LOG(INFO) << "TF: " << tfid << " --> ...unordered_map built = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + + // delta map + const auto* dhDelta = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("inputDelta").header); + auto szDelta = dhDelta->payloadSize; + int nDPsDelta = szDelta / sizeof(DPCOM); + LOG(INFO) << "Number of DPs received (delta map) = " << nDPsDelta; + std::unordered_map<DPID, DPVAL> dcsmapDelta; + LOG(INFO) << "TF: " << tfid << " --> building (delta) unordered_map..."; + s.Start(); + for (int i = 0; i < nDPsDelta; i++) { + memcpy(&dptmp, rawcharDelta + i * sizeof(DPCOM), sizeof(DPCOM)); + dcsmapDelta[dptmp.id] = dptmp.data; + LOG(DEBUG) << "Reading from generator: i = " << i << ", DPCOM = " << dptmp; + LOG(DEBUG) << "Reading from generator: i = " << i << ", DPID = " << dptmp.id; + } + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...unordered_map (delta) built = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + LOG(INFO) << "TF: " << tfid << " --> starting processing..."; s.Start(); mDCSproc.process(dcsmap); s.Stop(); LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + + sendOutput(pc.outputs()); } private: o2::dcs::DCSProcessor mDCSproc; -}; + //________________________________________________________________ + void sendOutput(DataAllocator& output) + { + // extract CCDB infos and calibration objects, convert it to TMemFile and send them to the output + // copied from LHCClockCalibratorSpec.cxx + using clbUtils = o2::calibration::Utils; + const auto& payload = mDCSproc.getCCDBint(); + auto& info = mDCSproc.getCCDBintInfo(); + auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); + LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); // vector<char> + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); + } +}; // end class } // namespace dcs namespace framework @@ -117,10 +162,17 @@ namespace framework DataProcessorSpec getDCSDataProcessorSpec() { + + using clbUtils = o2::calibration::Utils; + + std::vector<OutputSpec> outputs; + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload}); + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); + return DataProcessorSpec{ "dcs-data-processor", - Inputs{{"input", "DCS", "DATAPOINTS"}}, - Outputs{{}}, + Inputs{{"input", "DCS", "DATAPOINTS"}, {"inputDelta", "DCS", "DATAPOINTSdelta"}}, + outputs, AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataProcessor>()}, Options{}}; } From ee77d3676b6023aad61398d346b91a7720175669 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Mon, 12 Oct 2020 16:37:32 +0200 Subject: [PATCH 1003/1751] Including processing of delta map. Clang --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 37 +++++++----- Detectors/DCS/src/DCSProcessor.cxx | 58 ++++++++++++------- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 8 ++- .../DCS/testWorkflow/dcs-data-workflow.cxx | 2 +- 4 files changed, 67 insertions(+), 38 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index d204e606cdaaf..107cac002cf55 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -71,12 +71,12 @@ class DCSProcessor void init(const std::vector<DPID>& aliases); - int process(const std::unordered_map<DPID, DPVAL>& map); + int process(const std::unordered_map<DPID, DPVAL>& map, bool isDelta = false); std::unordered_map<DPID, DPVAL>::const_iterator processAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map); template <typename T> - int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap); + int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap); template <typename T> void doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA); @@ -108,10 +108,15 @@ class DCSProcessor void setTF(TFType tf) { mTF = tf; } + void setIsDelta(bool isDelta) { mIsDelta = isDelta; } + void isDelta() { mIsDelta = true; } + bool getIsDelta() const { return mIsDelta; } + template <typename T> void prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md); private: + bool mIsDelta = false; // set to true in case you are processing delta map (containing only DPs that changed) std::vector<float> mAvgTestInt; // moving average for int DPs std::vector<float> mAvgTestDouble; // moving average for double DPs std::unordered_map<DPID, DQChars> mDpscharsmap; @@ -130,14 +135,14 @@ class DCSProcessor std::vector<DPID> mAliasesstrings; std::vector<DPID> mAliasestimes; std::vector<DPID> mAliasesbinaries; - std::vector<uint64_t> mLatestTimestampchars; - std::vector<uint64_t> mLatestTimestampints; - std::vector<uint64_t> mLatestTimestampdoubles; - std::vector<uint64_t> mLatestTimestampUints; - std::vector<uint64_t> mLatestTimestampbools; - std::vector<uint64_t> mLatestTimestampstrings; - std::vector<uint64_t> mLatestTimestamptimes; - std::vector<uint64_t> mLatestTimestampbinaries; + std::vector<int64_t> mLatestTimestampchars; + std::vector<int64_t> mLatestTimestampints; + std::vector<int64_t> mLatestTimestampdoubles; + std::vector<int64_t> mLatestTimestampUints; + std::vector<int64_t> mLatestTimestampbools; + std::vector<int64_t> mLatestTimestampstrings; + std::vector<int64_t> mLatestTimestamptimes; + std::vector<int64_t> mLatestTimestampbinaries; int mNThreads = 1; // number of threads std::unordered_map<std::string, float> mccdbInt; // unordered map in which to store the CCDB entry CcdbObjectInfo mccdbIntInfo; // info to store the output of teh calibration on int values @@ -159,7 +164,7 @@ using DPID = o2::dcs::DataPointIdentifier; using DPVAL = o2::dcs::DataPointValue; template <typename T> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap) +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap) { // processing the array of type T @@ -174,7 +179,11 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType for (size_t i = 0; i != s; ++i) { auto it = processAlias(array[i], type, map); if (it == map.end()) { - LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + if (!mIsDelta) { + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + } else { + latestTimeStamp[i] = -latestTimeStamp[i]; + } continue; } found++; @@ -196,10 +205,10 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType } template <> -int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQStrings>& destmap); +int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQStrings>& destmap); template <> -int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQBinaries>& destmap); +int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQBinaries>& destmap); template <typename T> void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA) diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 70bfaaef1ea27..ac76b72f12c6e 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -158,13 +158,14 @@ void DCSProcessor::init(const std::vector<DPID>& aliases) //__________________________________________________________________ -int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map) +int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDelta) { // process function to do "something" with the DCS map that is passed // resetting the content of the CCDB object to be sent mccdbInt.clear(); + mIsDelta = isDelta; // we need to check if there are the Data Points that we need @@ -211,22 +212,24 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map) if (foundBinaries > 0) processBinaries(); - if (foundChars != mAliaseschars.size()) - LOG(INFO) << "Not all expected char-typed DPs found!"; - if (foundInts != mAliasesints.size()) - LOG(INFO) << "Not all expected int-typed DPs found!"; - if (foundDoubles != mAliasesdoubles.size()) - LOG(INFO) << "Not all expected double-typed DPs found!"; - if (foundUInts != mAliasesUints.size()) - LOG(INFO) << "Not all expected uint-typed DPs found!"; - if (foundBools != mAliasesbools.size()) - LOG(INFO) << "Not all expected bool-typed DPs found!"; - if (foundStrings != mAliasesstrings.size()) - LOG(INFO) << "Not all expected string-typed DPs found!"; - if (foundTimes != mAliasestimes.size()) - LOG(INFO) << "Not all expected time-typed DPs found!"; - if (foundBinaries != mAliasesbinaries.size()) - LOG(INFO) << "Not all expected binary-typed DPs found!"; + if (!isDelta) { + if (foundChars != mAliaseschars.size()) + LOG(INFO) << "Not all expected char-typed DPs found!"; + if (foundInts != mAliasesints.size()) + LOG(INFO) << "Not all expected int-typed DPs found!"; + if (foundDoubles != mAliasesdoubles.size()) + LOG(INFO) << "Not all expected double-typed DPs found!"; + if (foundUInts != mAliasesUints.size()) + LOG(INFO) << "Not all expected uint-typed DPs found!"; + if (foundBools != mAliasesbools.size()) + LOG(INFO) << "Not all expected bool-typed DPs found!"; + if (foundStrings != mAliasesstrings.size()) + LOG(INFO) << "Not all expected string-typed DPs found!"; + if (foundTimes != mAliasestimes.size()) + LOG(INFO) << "Not all expected time-typed DPs found!"; + if (foundBinaries != mAliasesbinaries.size()) + LOG(INFO) << "Not all expected binary-typed DPs found!"; + } return 0; } @@ -234,7 +237,7 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map) //______________________________________________________________________ template <> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, DQStrings>& destmap) +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, DQStrings>& destmap) { // processing the array of type T @@ -245,7 +248,11 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType for (size_t i = 0; i != s; ++i) { auto it = processAlias(array[i], type, map); if (it == map.end()) { - LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + if (!mIsDelta) { + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + } else { + latestTimeStamp[i] = -std::abs(latestTimeStamp[i]); // we keep it negative, in case it was already negative + } continue; } found++; @@ -255,7 +262,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType auto etime = val.get_epoch_time(); // fill only if new value has a timestamp different from the timestamp of the previous one LOG(DEBUG) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); - if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { + if (destmap[array[i]].size() == 0 || etime != std::abs(latestTimeStamp[i])) { auto& tmp = destmap[array[i]].emplace_back(); std::strncpy(tmp.data(), (char*)&(val.payload_pt1), 56); latestTimeStamp[i] = etime; @@ -269,7 +276,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType //______________________________________________________________________ template <> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, DQBinaries>& destmap) +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, DQBinaries>& destmap) { // processing the array of type T @@ -280,7 +287,11 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType for (size_t i = 0; i != s; ++i) { auto it = processAlias(array[i], type, map); if (it == map.end()) { - LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + if (!mIsDelta) { + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + } else { + latestTimeStamp[i] = -latestTimeStamp[i]; + } continue; } found++; @@ -344,6 +355,9 @@ void DCSProcessor::processInts() for (size_t i = 0; i != mAliasesints.size(); ++i) { LOG(DEBUG) << "processInts: mAliasesints[" << i << "] = " << mAliasesints[i]; + if (mIsDelta && mLatestTimestampints[i] < 0) { // we have received only the delta map, and the alias "i" was not present --> we don't process, but keep the old value in the mAvgTestInt vector + continue; + } auto& id = mAliasesints[i]; auto& vint = getVectorForAliasInt(id); LOG(DEBUG) << "vint size = " << vint.size(); diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index ebf863299e270..11e606a348a3a 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -130,10 +130,16 @@ class DCSDataProcessor : public o2::framework::Task LOG(INFO) << "TF: " << tfid << " --> starting processing..."; s.Start(); - mDCSproc.process(dcsmap); + mDCSproc.process(dcsmap, false); s.Stop(); LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing..."; + s.Start(); + mDCSproc.process(dcsmapDelta, true); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + sendOutput(pc.outputs()); } diff --git a/Detectors/DCS/testWorkflow/dcs-data-workflow.cxx b/Detectors/DCS/testWorkflow/dcs-data-workflow.cxx index 9c4d84482489d..e22ee95a0a76d 100644 --- a/Detectors/DCS/testWorkflow/dcs-data-workflow.cxx +++ b/Detectors/DCS/testWorkflow/dcs-data-workflow.cxx @@ -11,13 +11,13 @@ #include "DetectorsDCS/DataPointIdentifier.h" #include "DetectorsDCS/DataPointValue.h" #include "Framework/TypeTraits.h" +#include <unordered_map> namespace o2::framework { template <> struct has_root_dictionary<std::unordered_map<o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue>, void> : std::true_type { }; } // namespace o2::framework -#include <unordered_map> #include "Framework/DataProcessorSpec.h" #include "DCSDataGeneratorSpec.h" #include "DCSDataProcessorSpec.h" From 5dd83e7c5889c20e18966cd2fa406a7604bacf88 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Tue, 13 Oct 2020 00:41:07 +0200 Subject: [PATCH 1004/1751] Implementing ProcessDP. --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 56 ++++++++++++---- Detectors/DCS/src/DCSProcessor.cxx | 65 +++++++++++++++---- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 59 +++++++++++++---- 3 files changed, 141 insertions(+), 39 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index 107cac002cf55..2e7b0ab9881ad 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -15,6 +15,7 @@ #include <Rtypes.h> #include <unordered_map> #include <deque> +#include <numeric> #include "Framework/Logger.h" #include "DetectorsDCS/DataPointCompositeObject.h" #include "DetectorsDCS/DataPointIdentifier.h" @@ -73,10 +74,13 @@ class DCSProcessor int process(const std::unordered_map<DPID, DPVAL>& map, bool isDelta = false); - std::unordered_map<DPID, DPVAL>::const_iterator processAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map); + std::unordered_map<DPID, DPVAL>::const_iterator findAndCheckAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map); template <typename T> - int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap); + int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); + + template <typename T> + void processDP(const DPID& alias, std::deque<T>& aliasDeque); template <typename T> void doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA); @@ -102,9 +106,9 @@ class DCSProcessor void setNThreads(int n); int getNThreads() const { return mNThreads; } - const std::unordered_map<std::string, float>& getCCDBint() const { return mccdbInt; } - const CcdbObjectInfo& getCCDBintInfo() const { return mccdbIntInfo; } - CcdbObjectInfo& getCCDBintInfo() { return mccdbIntInfo; } + const std::unordered_map<std::string, float>& getCCDBSimpleMovingAverage() const { return mccdbSimpleMovingAverage; } + const CcdbObjectInfo& getCCDBSimpleMovingAverageInfo() const { return mccdbSimpleMovingAverageInfo; } + CcdbObjectInfo& getCCDBSimpleMovingAverageInfo() { return mccdbSimpleMovingAverageInfo; } void setTF(TFType tf) { mTF = tf; } @@ -112,13 +116,20 @@ class DCSProcessor void isDelta() { mIsDelta = true; } bool getIsDelta() const { return mIsDelta; } + void setMaxCyclesNoFullMap(uint64_t maxCycles) { mMaxCyclesNoFullMap = maxCycles; } + uint64_t getMaxCyclesNoFullMap() const { return mMaxCyclesNoFullMap; } + + uint64_t getNCyclesNoFullMap() const { return mNCyclesNoFullMap; } + template <typename T> void prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md); private: + bool mFullMapSent = false; // set to true as soon as a full map was sent. No delta can be received if there was never a full map sent + int64_t mNCyclesNoFullMap = 0; // number of times the delta was sent withoug a full map + int64_t mMaxCyclesNoFullMap = 6000; // max number of times when the delta can be sent between two full maps (assuming DCS sends data every 50 ms, this means a 5 minutes threshold) bool mIsDelta = false; // set to true in case you are processing delta map (containing only DPs that changed) - std::vector<float> mAvgTestInt; // moving average for int DPs - std::vector<float> mAvgTestDouble; // moving average for double DPs + std::unordered_map<DPID, float> mSimpleMovingAverage; // moving average for several DPs std::unordered_map<DPID, DQChars> mDpscharsmap; std::unordered_map<DPID, DQInts> mDpsintsmap; std::unordered_map<DPID, DQDoubles> mDpsdoublesmap; @@ -144,8 +155,8 @@ class DCSProcessor std::vector<int64_t> mLatestTimestamptimes; std::vector<int64_t> mLatestTimestampbinaries; int mNThreads = 1; // number of threads - std::unordered_map<std::string, float> mccdbInt; // unordered map in which to store the CCDB entry - CcdbObjectInfo mccdbIntInfo; // info to store the output of teh calibration on int values + std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry for the DPs for which we calculated the simple moving average + CcdbObjectInfo mccdbSimpleMovingAverageInfo; // info to store the output of the calibration for the DPs for which we calculated the simple moving average TFType mTF = 0; // TF index for processing, used to store CCDB object ClassDefNV(DCSProcessor, 0); @@ -164,20 +175,20 @@ using DPID = o2::dcs::DataPointIdentifier; using DPVAL = o2::dcs::DataPointValue; template <typename T> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, T>& destmap) +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap) { // processing the array of type T int found = 0; auto s = array.size(); - if (s > 0) { + if (s > 0) { // we have at least one DP of type T //#ifdef WITH_OPENMP //omp_set_num_threads(mNThreads); //#pragma omp parallel for schedule(dynamic) //#endif for (size_t i = 0; i != s; ++i) { - auto it = processAlias(array[i], type, map); + auto it = findAndCheckAlias(array[i], type, map); if (it == map.end()) { if (!mIsDelta) { LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; @@ -199,7 +210,9 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType latestTimeStamp[i] = etime; } } - } + processDP(array[i], destmap[array[i]]); + // todo: better to move the "found++" after the process, in case it fails? + } } return found; } @@ -210,6 +223,16 @@ int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, template <> int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQBinaries>& destmap); +template <typename T> +void DCSProcessor::processDP(const DPID& alias, std::deque<T>& aliasdeque) +{ + // processing the single alias + return; +} + +template <> +void DCSProcessor::processDP(const DPID& alias, std::deque<int>& aliasdeque); + template <typename T> void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA) { @@ -226,6 +249,13 @@ void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, flo isSMA = true; return; } + /* +if (vect.size() <= nelements) { + //avg = std::accumulate(vect.begin(), vect.end(), 0.0) / vect.size(); + avg = (avg * (vect.size() - 1) + vect[vect.size() - 1]) / vect.size(); + return; + } + */ avg += (vect[vect.size() - 1] - vect[0]) / nelements; vect.pop_front(); isSMA = true; diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index ac76b72f12c6e..065d72090ddb8 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -100,7 +100,7 @@ void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector mLatestTimestampstrings.resize(aliasesstrings.size(), 0); mLatestTimestamptimes.resize(aliasestimes.size(), 0); mLatestTimestampbinaries.resize(aliasesbinaries.size(), 0); - mAvgTestInt.resize(aliasesints.size(), 0); + // mAvgTestInt.resize(aliasesints.size(), 0); } //______________________________________________________________________ @@ -153,7 +153,7 @@ void DCSProcessor::init(const std::vector<DPID>& aliases) mLatestTimestampstrings.resize(nstrings, 0); mLatestTimestamptimes.resize(ntimes, 0); mLatestTimestampbinaries.resize(nbinaries, 0); - mAvgTestInt.resize(nints, 0); + // mAvgTestInt.resize(nints, 0); } //__________________________________________________________________ @@ -164,7 +164,22 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDel // process function to do "something" with the DCS map that is passed // resetting the content of the CCDB object to be sent - mccdbInt.clear(); + + if (!isDelta) { + // full map sent + mFullMapSent = true; + } + else { + if (!mFullMapSent) { + LOG(ERROR) << "We need first a full map!"; + } + mNCyclesNoFullMap++; + if (mNCyclesNoFullMap > mMaxCyclesNoFullMap) { + LOG(ERROR) << "We expected a full map!"; + } + } + + //mccdbSimpleMovingAverage.clear(); mIsDelta = isDelta; // we need to check if there are the Data Points that we need @@ -179,8 +194,8 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDel // int type foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); - if (foundInts > 0) - processInts(); + // if (foundInts > 0) + // processInts(); // double type foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, mDpsdoublesmap); @@ -231,6 +246,16 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDel LOG(INFO) << "Not all expected binary-typed DPs found!"; } + // filling CCDB info to be sent in output + std::map<std::string, std::string> md; + prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, "TestDCS/SimpleMovingAverageDPs", mTF, md); + + LOG(DEBUG) << "Size of unordered_map for CCDB = " << mccdbSimpleMovingAverage.size(); + LOG(DEBUG) << "CCDB entry for TF " << mTF << " will be:"; + for (const auto& i : mccdbSimpleMovingAverage){ + LOG(DEBUG) << i.first << " --> " << i.second; + } + return 0; } @@ -246,7 +271,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType auto s = array.size(); if (s > 0) { for (size_t i = 0; i != s; ++i) { - auto it = processAlias(array[i], type, map); + auto it = findAndCheckAlias(array[i], type, map); if (it == map.end()) { if (!mIsDelta) { LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; @@ -285,7 +310,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType auto s = array.size(); if (s > 0) { for (size_t i = 0; i != s; ++i) { - auto it = processAlias(array[i], type, map); + auto it = findAndCheckAlias(array[i], type, map); if (it == map.end()) { if (!mIsDelta) { LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; @@ -314,7 +339,23 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType //______________________________________________________________________ -std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::processAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map) +template <> +void DCSProcessor::processDP(const DPID& alias, std::deque<int>& aliasdeque) +{ + // processing the single alias of type int + bool isSMA = false; + doSimpleMovingAverage(2, aliasdeque, mSimpleMovingAverage[alias], isSMA); + LOG(DEBUG) << "Moving average = " << mSimpleMovingAverage[alias]; + // create CCDB object + //if (isSMA) { + mccdbSimpleMovingAverage[alias.get_alias()] = mSimpleMovingAverage[alias]; + //} + return; +} + +//______________________________________________________________________ + +std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map) { // processing basic checks for map: all needed aliases must be present @@ -367,15 +408,15 @@ void DCSProcessor::processInts() bool isSMA = false; LOG(DEBUG) << "get alias = " << id.get_alias(); // I do the moving average always of the last 2 points, no matter if it was updated or not - doSimpleMovingAverage(2, vint, mAvgTestInt[i], isSMA); - LOG(DEBUG) << "Moving average = " << mAvgTestInt[i]; + doSimpleMovingAverage(2, vint, mSimpleMovingAverage[id], isSMA); + LOG(DEBUG) << "Moving average = " << mSimpleMovingAverage[id]; if (isSMA) { // create CCDB object - mccdbInt[id.get_alias()] = mAvgTestInt[i]; + mccdbSimpleMovingAverage[id.get_alias()] = mSimpleMovingAverage[id]; } } std::map<std::string, std::string> md; - prepareCCDBobject(mccdbInt, mccdbIntInfo, "TestDCS/IntDPs", mTF, md); + prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, "TestDCS/IntDPs", mTF, md); } //______________________________________________________________________ diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index 11e606a348a3a..caf06d16ee183 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -44,6 +44,13 @@ using DPCOM = o2::dcs::DataPointCompositeObject; class DCSDataProcessor : public o2::framework::Task { public: + + enum Detectors { + kTest, + kTPC, + kNdetectors + }; + void init(o2::framework::InitContext& ic) final { std::vector<DPID> aliasVect; @@ -54,11 +61,15 @@ class DCSDataProcessor : public o2::framework::Task DPID::FILL(dpidtmp, dpAliaschar, typechar); aliasVect.push_back(dpidtmp); + std::vector<int> vectDet{kTest, kTPC}; + mDetectorAlias[dpidtmp] = vectDet; + DeliveryType typeint = RAW_INT; for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasint, typeint); aliasVect.push_back(dpidtmp); + mDetectorAlias[dpidtmp] = vectDet; } DeliveryType typedouble = RAW_DOUBLE; @@ -66,14 +77,18 @@ class DCSDataProcessor : public o2::framework::Task std::string dpAliasdouble = "TestDouble_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasdouble, typedouble); aliasVect.push_back(dpidtmp); + mDetectorAlias[dpidtmp] = vectDet; } DeliveryType typestring = RAW_STRING; std::string dpAliasstring0 = "TestString_0"; DPID::FILL(dpidtmp, dpAliasstring0, typestring); aliasVect.push_back(dpidtmp); + mDetectorAlias[dpidtmp] = vectDet; mDCSproc.init(aliasVect); + mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); + //mDCSprocVect[kTest] = mDCSproc; } void run(o2::framework::ProcessingContext& pc) final @@ -128,32 +143,48 @@ class DCSDataProcessor : public o2::framework::Task s.Stop(); LOG(INFO) << "TF: " << tfid << " --> ...unordered_map (delta) built = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); - LOG(INFO) << "TF: " << tfid << " --> starting processing..."; - s.Start(); - mDCSproc.process(dcsmap, false); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); - - LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing..."; - s.Start(); - mDCSproc.process(dcsmapDelta, true); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + if (tfid % 6000 == 0) { + LOG(INFO) << "TF: " << tfid << " --> starting processing..."; + s.Start(); + mDCSproc.process(dcsmap, false); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + } + else { + LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing..."; + s.Start(); + mDCSproc.process(dcsmapDelta, true); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + + // processing per DP found in the map, to be done in case of a delta map + + for (const auto& dpid : dcsmapDelta) { + std::vector<int> detVect = mDetectorAlias[dpid.first]; + for (int idet = 0; idet < detVect.size(); idet++) { + } + } + + + } sendOutput(pc.outputs()); } private: + std::unordered_map<DPID, std::vector<int>> mDetectorAlias; + std::array<DCSProcessor, kNdetectors> mDCSprocVect; o2::dcs::DCSProcessor mDCSproc; + //________________________________________________________________ void sendOutput(DataAllocator& output) { // extract CCDB infos and calibration objects, convert it to TMemFile and send them to the output // copied from LHCClockCalibratorSpec.cxx using clbUtils = o2::calibration::Utils; - const auto& payload = mDCSproc.getCCDBint(); - auto& info = mDCSproc.getCCDBintInfo(); + const auto& payload = mDCSproc.getCCDBSimpleMovingAverage(); + auto& info = mDCSproc.getCCDBSimpleMovingAverageInfo(); auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); @@ -180,7 +211,7 @@ DataProcessorSpec getDCSDataProcessorSpec() Inputs{{"input", "DCS", "DATAPOINTS"}, {"inputDelta", "DCS", "DATAPOINTSdelta"}}, outputs, AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataProcessor>()}, - Options{}}; + Options{{"max-cycles-no-full-map", VariantType::Int64, 6000ll, {"max number of cycles between the sending of two full maps"}}}}; } } // namespace framework From 5b069154f233f37966b2aba21801757cbe0b01d8 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Tue, 13 Oct 2020 15:32:02 +0200 Subject: [PATCH 1005/1751] Possibility to process per Data Point only needed detectors. And other changes... Clang --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 99 +++++--- Detectors/DCS/src/DCSProcessor.cxx | 233 +++++++++++------- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 74 +++--- 3 files changed, 246 insertions(+), 160 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index 2e7b0ab9881ad..e65947f902814 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -72,7 +72,9 @@ class DCSProcessor void init(const std::vector<DPID>& aliases); - int process(const std::unordered_map<DPID, DPVAL>& map, bool isDelta = false); + int processMap(const std::unordered_map<DPID, DPVAL>& map, bool isDelta = false); + + int processDP(const std::pair<DPID, DPVAL>& dpcom); std::unordered_map<DPID, DPVAL>::const_iterator findAndCheckAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map); @@ -80,7 +82,10 @@ class DCSProcessor int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); template <typename T> - void processDP(const DPID& alias, std::deque<T>& aliasDeque); + void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, T>& destmap); + + template <typename T> + void process(const DPID& alias, std::deque<T>& aliasDeque); template <typename T> void doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA); @@ -125,11 +130,11 @@ class DCSProcessor void prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md); private: - bool mFullMapSent = false; // set to true as soon as a full map was sent. No delta can be received if there was never a full map sent - int64_t mNCyclesNoFullMap = 0; // number of times the delta was sent withoug a full map - int64_t mMaxCyclesNoFullMap = 6000; // max number of times when the delta can be sent between two full maps (assuming DCS sends data every 50 ms, this means a 5 minutes threshold) - bool mIsDelta = false; // set to true in case you are processing delta map (containing only DPs that changed) - std::unordered_map<DPID, float> mSimpleMovingAverage; // moving average for several DPs + bool mFullMapSent = false; // set to true as soon as a full map was sent. No delta can be received if there was never a full map sent + int64_t mNCyclesNoFullMap = 0; // number of times the delta was sent withoug a full map + int64_t mMaxCyclesNoFullMap = 6000; // max number of times when the delta can be sent between two full maps (assuming DCS sends data every 50 ms, this means a 5 minutes threshold) + bool mIsDelta = false; // set to true in case you are processing delta map (containing only DPs that changed) + std::unordered_map<DPID, float> mSimpleMovingAverage; // moving average for several DPs std::unordered_map<DPID, DQChars> mDpscharsmap; std::unordered_map<DPID, DQInts> mDpsintsmap; std::unordered_map<DPID, DQDoubles> mDpsdoublesmap; @@ -154,10 +159,10 @@ class DCSProcessor std::vector<int64_t> mLatestTimestampstrings; std::vector<int64_t> mLatestTimestamptimes; std::vector<int64_t> mLatestTimestampbinaries; - int mNThreads = 1; // number of threads + int mNThreads = 1; // number of threads std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry for the DPs for which we calculated the simple moving average CcdbObjectInfo mccdbSimpleMovingAverageInfo; // info to store the output of the calibration for the DPs for which we calculated the simple moving average - TFType mTF = 0; // TF index for processing, used to store CCDB object + TFType mTF = 0; // TF index for processing, used to store CCDB object ClassDefNV(DCSProcessor, 0); }; @@ -198,40 +203,63 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType continue; } found++; - auto& val = it->second; - auto flags = val.get_flags(); - if (processFlag(flags, array[i].get_alias()) == 0) { - auto etime = val.get_epoch_time(); - // fill only if new value has a timestamp different from the timestamp of the previous one - LOG(DEBUG) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); - if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { - LOG(DEBUG) << "adding new value"; - destmap[array[i]].push_back(val.payload_pt1); - latestTimeStamp[i] = etime; - } - } - processDP(array[i], destmap[array[i]]); + std::pair<DPID, DPVAL> pairIt = *it; + checkFlagsAndFill(pairIt, latestTimeStamp[i], destmap); + process(array[i], destmap[array[i]]); // todo: better to move the "found++" after the process, in case it fails? - } + } } return found; } +//______________________________________________________________________ + +template <typename T> +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, T>& destmap) +{ + + // check the flags for the upcoming data, and if ok, fill the accumulator + + auto& dpid = dpcom.first; + auto& val = dpcom.second; + auto flags = val.get_flags(); + if (processFlag(flags, dpid.get_alias()) == 0) { + auto etime = val.get_epoch_time(); + // fill only if new value has a timestamp different from the timestamp of the previous one + LOG(DEBUG) << "destmap[pid].size() = " << destmap[dpid].size(); + if (destmap[dpid].size() == 0 || etime != std::abs(latestTimeStamp)) { + LOG(DEBUG) << "adding new value"; + destmap[dpid].push_back(val.payload_pt1); + latestTimeStamp = etime; + } + } +} + +//______________________________________________________________________ + template <> -int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQStrings>& destmap); +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DCSProcessor::DQStrings>& destmap); + +//______________________________________________________________________ template <> -int DCSProcessor::processArrayType(const std::vector<DCSProcessor::DPID>& array, DeliveryType type, const std::unordered_map<DCSProcessor::DPID, DCSProcessor::DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DCSProcessor::DPID, DCSProcessor::DQBinaries>& destmap); +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DCSProcessor::DQBinaries>& destmap); + +//______________________________________________________________________ template <typename T> -void DCSProcessor::processDP(const DPID& alias, std::deque<T>& aliasdeque) +void DCSProcessor::process(const DPID& alias, std::deque<T>& aliasdeque) { // processing the single alias return; } +//______________________________________________________________________ + template <> -void DCSProcessor::processDP(const DPID& alias, std::deque<int>& aliasdeque); +void DCSProcessor::process(const DPID& alias, std::deque<int>& aliasdeque); + +//______________________________________________________________________ template <typename T> void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA) @@ -239,28 +267,19 @@ void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, flo // Do simple moving average on vector of type T - if (vect.size() < nelements) { - avg += vect[vect.size() - 1]; - return; - } - if (vect.size() == nelements) { - avg += vect[vect.size() - 1]; - avg /= nelements; - isSMA = true; - return; - } - /* -if (vect.size() <= nelements) { + if (vect.size() <= nelements) { //avg = std::accumulate(vect.begin(), vect.end(), 0.0) / vect.size(); avg = (avg * (vect.size() - 1) + vect[vect.size() - 1]) / vect.size(); return; } - */ + avg += (vect[vect.size() - 1] - vect[0]) / nelements; vect.pop_front(); isSMA = true; } +//______________________________________________________________________ + template <typename T> void DCSProcessor::prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md) { diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 065d72090ddb8..865b971eb21a5 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -12,6 +12,8 @@ #include "Rtypes.h" #include <deque> #include <string> +#include <algorithm> +#include <iterator> using namespace o2::dcs; @@ -100,7 +102,6 @@ void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector mLatestTimestampstrings.resize(aliasesstrings.size(), 0); mLatestTimestamptimes.resize(aliasestimes.size(), 0); mLatestTimestampbinaries.resize(aliasesbinaries.size(), 0); - // mAvgTestInt.resize(aliasesints.size(), 0); } //______________________________________________________________________ @@ -153,12 +154,11 @@ void DCSProcessor::init(const std::vector<DPID>& aliases) mLatestTimestampstrings.resize(nstrings, 0); mLatestTimestamptimes.resize(ntimes, 0); mLatestTimestampbinaries.resize(nbinaries, 0); - // mAvgTestInt.resize(nints, 0); } //__________________________________________________________________ -int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDelta) +int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool isDelta) { // process function to do "something" with the DCS map that is passed @@ -168,8 +168,7 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDel if (!isDelta) { // full map sent mFullMapSent = true; - } - else { + } else { if (!mFullMapSent) { LOG(ERROR) << "We need first a full map!"; } @@ -178,8 +177,7 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDel LOG(ERROR) << "We expected a full map!"; } } - - //mccdbSimpleMovingAverage.clear(); + mIsDelta = isDelta; // we need to check if there are the Data Points that we need @@ -194,38 +192,24 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDel // int type foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); - // if (foundInts > 0) - // processInts(); // double type foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, mDpsdoublesmap); - if (foundDoubles > 0) - processDoubles(); // UInt type foundUInts = processArrayType(mAliasesUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); - if (foundUInts > 0) - processUInts(); // Bool type foundBools = processArrayType(mAliasesbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); - if (foundBools > 0) - processBools(); // String type foundStrings = processArrayType(mAliasesstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, mDpsstringsmap); - if (foundStrings > 0) - processStrings(); // Time type foundTimes = processArrayType(mAliasestimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); - if (foundTimes > 0) - processTimes(); // Binary type foundBinaries = processArrayType(mAliasesbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, mDpsbinariesmap); - if (foundBinaries > 0) - processBinaries(); if (!isDelta) { if (foundChars != mAliaseschars.size()) @@ -250,97 +234,163 @@ int DCSProcessor::process(const std::unordered_map<DPID, DPVAL>& map, bool isDel std::map<std::string, std::string> md; prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, "TestDCS/SimpleMovingAverageDPs", mTF, md); - LOG(DEBUG) << "Size of unordered_map for CCDB = " << mccdbSimpleMovingAverage.size(); + LOG(DEBUG) << "Size of unordered_map for CCDB = " << mccdbSimpleMovingAverage.size(); LOG(DEBUG) << "CCDB entry for TF " << mTF << " will be:"; - for (const auto& i : mccdbSimpleMovingAverage){ + for (const auto& i : mccdbSimpleMovingAverage) { LOG(DEBUG) << i.first << " --> " << i.second; } - + + return 0; +} + +//__________________________________________________________________ + +int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) +{ + + // processing single DP + + DPID dpid = dpcom.first; + DeliveryType type = dpid.get_type(); + + // first we check if the DP is in the list for the detector + if (type == DeliveryType::RAW_CHAR) { + auto it = std::find(mAliaseschars.begin(), mAliaseschars.end(), dpid); + if (it == mAliaseschars.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliaseschars.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampchars[index], mDpscharsmap); + process(dpid, mDpscharsmap[dpid]); + } + + else if (type == DeliveryType::RAW_INT) { + auto it = std::find(mAliasesints.begin(), mAliasesints.end(), dpid); + if (it == mAliasesints.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliasesints.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampints[index], mDpsintsmap); + process(dpid, mDpsintsmap[dpid]); + } + + else if (type == DeliveryType::RAW_DOUBLE) { + auto it = std::find(mAliasesdoubles.begin(), mAliasesdoubles.end(), dpid); + if (it == mAliasesdoubles.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliasesdoubles.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampdoubles[index], mDpsdoublesmap); + process(dpid, mDpsdoublesmap[dpid]); + } + + else if (type == DeliveryType::RAW_UINT) { + auto it = std::find(mAliasesUints.begin(), mAliasesUints.end(), dpid); + if (it == mAliasesUints.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliasesUints.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampUints[index], mDpsUintsmap); + process(dpid, mDpsUintsmap[dpid]); + } + + else if (type == DeliveryType::RAW_BOOL) { + auto it = std::find(mAliasesbools.begin(), mAliasesbools.end(), dpid); + if (it == mAliasesbools.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliasesbools.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampbools[index], mDpsboolsmap); + process(dpid, mDpsboolsmap[dpid]); + } + + else if (type == DeliveryType::RAW_STRING) { + auto it = std::find(mAliasesstrings.begin(), mAliasesstrings.end(), dpid); + if (it == mAliasesstrings.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliasesstrings.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampstrings[index], mDpsstringsmap); + process(dpid, mDpsstringsmap[dpid]); + } else if (type == DeliveryType::RAW_TIME) { + auto it = std::find(mAliasestimes.begin(), mAliasestimes.end(), dpid); + if (it == mAliasestimes.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliasestimes.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestamptimes[index], mDpstimesmap); + process(dpid, mDpstimesmap[dpid]); + } else if (type == DeliveryType::RAW_BINARY) { + auto it = std::find(mAliasesbinaries.begin(), mAliasesbinaries.end(), dpid); + if (it == mAliasesbinaries.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int index = std::distance(mAliasesbinaries.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampbinaries[index], mDpsbinariesmap); + process(dpid, mDpsbinariesmap[dpid]); + } + return 0; } //______________________________________________________________________ template <> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, DQStrings>& destmap) +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DQStrings>& destmap) { - // processing the array of type T - - int found = 0; - auto s = array.size(); - if (s > 0) { - for (size_t i = 0; i != s; ++i) { - auto it = findAndCheckAlias(array[i], type, map); - if (it == map.end()) { - if (!mIsDelta) { - LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; - } else { - latestTimeStamp[i] = -std::abs(latestTimeStamp[i]); // we keep it negative, in case it was already negative - } - continue; - } - found++; - auto& val = it->second; - auto flags = val.get_flags(); - if (processFlag(flags, array[i].get_alias()) == 0) { - auto etime = val.get_epoch_time(); - // fill only if new value has a timestamp different from the timestamp of the previous one - LOG(DEBUG) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); - if (destmap[array[i]].size() == 0 || etime != std::abs(latestTimeStamp[i])) { - auto& tmp = destmap[array[i]].emplace_back(); - std::strncpy(tmp.data(), (char*)&(val.payload_pt1), 56); - latestTimeStamp[i] = etime; - } - } - } - } - return found; + // check the flags for the upcoming data, and if ok, fill the accumulator + + auto& dpid = dpcom.first; + auto& val = dpcom.second; + auto flags = val.get_flags(); + if (processFlag(flags, dpid.get_alias()) == 0) { + auto etime = val.get_epoch_time(); + // fill only if new value has a timestamp different from the timestamp of the previous one + LOG(DEBUG) << "destmap[pid].size() = " << destmap[dpid].size(); + if (destmap[dpid].size() == 0 || etime != std::abs(latestTimeStamp)) { + auto& tmp = destmap[dpid].emplace_back(); + std::strncpy(tmp.data(), (char*)&(val.payload_pt1), 56); + latestTimeStamp = etime; + } + } } //______________________________________________________________________ template <> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, DQBinaries>& destmap) +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DQBinaries>& destmap) { - // processing the array of type T - - int found = 0; - auto s = array.size(); - if (s > 0) { - for (size_t i = 0; i != s; ++i) { - auto it = findAndCheckAlias(array[i], type, map); - if (it == map.end()) { - if (!mIsDelta) { - LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; - } else { - latestTimeStamp[i] = -latestTimeStamp[i]; - } - continue; - } - found++; - auto& val = it->second; - auto flags = val.get_flags(); - if (processFlag(flags, array[i].get_alias()) == 0) { - auto etime = val.get_epoch_time(); - // fill only if new value has a timestamp different from the timestamp of the previous one - LOG(DEBUG) << "destmap[array[" << i << "]].size() = " << destmap[array[i]].size(); - if (destmap[array[i]].size() == 0 || etime != latestTimeStamp[i]) { - auto& tmp = destmap[array[i]].emplace_back(); - memcpy(tmp.data(), &(val.payload_pt1), 7); - latestTimeStamp[i] = etime; - } - } - } - } - return found; + // check the flags for the upcoming data, and if ok, fill the accumulator + + auto& dpid = dpcom.first; + auto& val = dpcom.second; + auto flags = val.get_flags(); + if (processFlag(flags, dpid.get_alias()) == 0) { + auto etime = val.get_epoch_time(); + // fill only if new value has a timestamp different from the timestamp of the previous one + LOG(DEBUG) << "destmap[pid].size() = " << destmap[dpid].size(); + if (destmap[dpid].size() == 0 || etime != std::abs(latestTimeStamp)) { + auto& tmp = destmap[dpid].emplace_back(); + memcpy(tmp.data(), &(val.payload_pt1), 7); + latestTimeStamp = etime; + } + } } //______________________________________________________________________ template <> -void DCSProcessor::processDP(const DPID& alias, std::deque<int>& aliasdeque) +void DCSProcessor::process(const DPID& alias, std::deque<int>& aliasdeque) { // processing the single alias of type int bool isSMA = false; @@ -348,8 +398,8 @@ void DCSProcessor::processDP(const DPID& alias, std::deque<int>& aliasdeque) LOG(DEBUG) << "Moving average = " << mSimpleMovingAverage[alias]; // create CCDB object //if (isSMA) { - mccdbSimpleMovingAverage[alias.get_alias()] = mSimpleMovingAverage[alias]; - //} + mccdbSimpleMovingAverage[alias.get_alias()] = mSimpleMovingAverage[alias]; + //} return; } @@ -359,6 +409,7 @@ std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias( { // processing basic checks for map: all needed aliases must be present + // finds dp defined by "alias" in received map "map" LOG(DEBUG) << "Processing " << alias; auto it = map.find(alias); diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index caf06d16ee183..48a57d971c60e 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -44,13 +44,12 @@ using DPCOM = o2::dcs::DataPointCompositeObject; class DCSDataProcessor : public o2::framework::Task { public: - enum Detectors { kTest, kTPC, kNdetectors }; - + void init(o2::framework::InitContext& ic) final { std::vector<DPID> aliasVect; @@ -63,7 +62,7 @@ class DCSDataProcessor : public o2::framework::Task std::vector<int> vectDet{kTest, kTPC}; mDetectorAlias[dpidtmp] = vectDet; - + DeliveryType typeint = RAW_INT; for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); @@ -88,7 +87,9 @@ class DCSDataProcessor : public o2::framework::Task mDCSproc.init(aliasVect); mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); - //mDCSprocVect[kTest] = mDCSproc; + mDCSprocVect[kTest].init(aliasVect); + mDCSprocVect[kTest].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); + mProcessFullDeltaMap = ic.options().get<bool>("process-full-delta-map"); } void run(o2::framework::ProcessingContext& pc) final @@ -144,39 +145,52 @@ class DCSDataProcessor : public o2::framework::Task LOG(INFO) << "TF: " << tfid << " --> ...unordered_map (delta) built = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); if (tfid % 6000 == 0) { - LOG(INFO) << "TF: " << tfid << " --> starting processing..."; - s.Start(); - mDCSproc.process(dcsmap, false); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); - } - else { - LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing..."; - s.Start(); - mDCSproc.process(dcsmapDelta, true); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); - - // processing per DP found in the map, to be done in case of a delta map - - for (const auto& dpid : dcsmapDelta) { - std::vector<int> detVect = mDetectorAlias[dpid.first]; - for (int idet = 0; idet < detVect.size(); idet++) { - } + //for (int idet = 0; idet < detVect.size(); idet++) { + for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor + LOG(INFO) << "TF: " << tfid << " --> starting processing..."; + s.Start(); + mDCSprocVect[idet].processMap(dcsmap, false); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + } + } else { + if (mProcessFullDeltaMap) { + //for (int idet = 0; idet < detVect.size(); idet++) { + for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor + LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing..."; + s.Start(); + mDCSprocVect[idet].processMap(dcsmapDelta, true); + s.Stop(); + LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + } + } else { + + // processing per DP found in the map, to be done in case of a delta map + + bool resetStopwatch = true; + LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing for detector..."; + for (const auto& dpcom : dcsmapDelta) { + std::vector<int> detVect = mDetectorAlias[dpcom.first]; + //for (int idet = 0; idet < detVect.size(); idet++) { + for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor + s.Start(resetStopwatch); + mDCSprocVect[idet].processDP(dpcom); + s.Stop(); + resetStopwatch = false; + } + } + LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) in detector loop done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); } - - } - sendOutput(pc.outputs()); } private: - std::unordered_map<DPID, std::vector<int>> mDetectorAlias; + std::unordered_map<DPID, std::vector<int>> mDetectorAlias; std::array<DCSProcessor, kNdetectors> mDCSprocVect; o2::dcs::DCSProcessor mDCSproc; + bool mProcessFullDeltaMap = false; - //________________________________________________________________ void sendOutput(DataAllocator& output) { @@ -211,7 +225,9 @@ DataProcessorSpec getDCSDataProcessorSpec() Inputs{{"input", "DCS", "DATAPOINTS"}, {"inputDelta", "DCS", "DATAPOINTSdelta"}}, outputs, AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataProcessor>()}, - Options{{"max-cycles-no-full-map", VariantType::Int64, 6000ll, {"max number of cycles between the sending of two full maps"}}}}; + Options{ + {"max-cycles-no-full-map", VariantType::Int64, 6000ll, {"max number of cycles between the sending of two full maps"}}, + {"process-full-delta-map", VariantType::Bool, false, {"whether to process the delta map as a whole instead of per data point"}}}}; } } // namespace framework From 90bce5677732b061a764a8372b1bd71e286aa5c2 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Tue, 13 Oct 2020 22:45:51 +0200 Subject: [PATCH 1006/1751] De-templating some functions so that detectors can override them if deriving from DCSProcessor. clang --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 91 ++++++----- Detectors/DCS/src/DCSProcessor.cxx | 149 +++++++----------- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 8 + 3 files changed, 107 insertions(+), 141 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index e65947f902814..e6f3d1dbae606 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -84,22 +84,20 @@ class DCSProcessor template <typename T> void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, T>& destmap); - template <typename T> - void process(const DPID& alias, std::deque<T>& aliasDeque); + virtual void processCharDP(const DPID& alias); + virtual void processIntDP(const DPID& alias); + virtual void processDoubleDP(const DPID& alias); + virtual void processUIntDP(const DPID& alias); + virtual void processBoolDP(const DPID& alias); + virtual void processStringDP(const DPID& alias); + virtual void processTimeDP(const DPID& alias); + virtual void processBinaryDP(const DPID& alias); + + virtual uint64_t processFlag(uint64_t flag, const char* alias); template <typename T> void doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA); - virtual void processChars(); - virtual void processInts(); - virtual void processDoubles(); - virtual void processUInts(); - virtual void processBools(); - virtual void processStrings(); - virtual void processTimes(); - virtual void processBinaries(); - virtual uint64_t processFlag(uint64_t flag, const char* alias); - DQChars& getVectorForAliasChar(const DPID& id) { return mDpscharsmap[id]; } DQInts& getVectorForAliasInt(const DPID& id) { return mDpsintsmap[id]; } DQDoubles& getVectorForAliasDouble(const DPID& id) { return mDpsdoublesmap[id]; } @@ -129,6 +127,9 @@ class DCSProcessor template <typename T> void prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md); + void setName(std::string name) { mName = name; } + const std::string getName() const { return mName; } + private: bool mFullMapSent = false; // set to true as soon as a full map was sent. No delta can be received if there was never a full map sent int64_t mNCyclesNoFullMap = 0; // number of times the delta was sent withoug a full map @@ -163,6 +164,7 @@ class DCSProcessor std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry for the DPs for which we calculated the simple moving average CcdbObjectInfo mccdbSimpleMovingAverageInfo; // info to store the output of the calibration for the DPs for which we calculated the simple moving average TFType mTF = 0; // TF index for processing, used to store CCDB object + std::string mName = ""; // to be used to determine CCDB path ClassDefNV(DCSProcessor, 0); }; @@ -186,28 +188,39 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType // processing the array of type T int found = 0; - auto s = array.size(); - if (s > 0) { // we have at least one DP of type T - //#ifdef WITH_OPENMP - //omp_set_num_threads(mNThreads); - //#pragma omp parallel for schedule(dynamic) - //#endif - for (size_t i = 0; i != s; ++i) { - auto it = findAndCheckAlias(array[i], type, map); - if (it == map.end()) { - if (!mIsDelta) { - LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; - } else { - latestTimeStamp[i] = -latestTimeStamp[i]; - } - continue; + //#ifdef WITH_OPENMP + //omp_set_num_threads(mNThreads); + //#pragma omp parallel for schedule(dynamic) + //#endif + for (size_t i = 0; i != array.size(); ++i) { + auto it = findAndCheckAlias(array[i], type, map); + if (it == map.end()) { + if (!mIsDelta) { + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; } - found++; - std::pair<DPID, DPVAL> pairIt = *it; - checkFlagsAndFill(pairIt, latestTimeStamp[i], destmap); - process(array[i], destmap[array[i]]); - // todo: better to move the "found++" after the process, in case it fails? + continue; + } + found++; + std::pair<DPID, DPVAL> pairIt = *it; + checkFlagsAndFill(pairIt, latestTimeStamp[i], destmap); + if (type == RAW_CHAR) { + processCharDP(array[i]); + } else if (type == RAW_INT) { + processIntDP(array[i]); + } else if (type == RAW_DOUBLE) { + processDoubleDP(array[i]); + } else if (type == RAW_UINT) { + processUIntDP(array[i]); + } else if (type == RAW_BOOL) { + processBoolDP(array[i]); + } else if (type == RAW_STRING) { + processStringDP(array[i]); + } else if (type == RAW_TIME) { + processTimeDP(array[i]); + } else if (type == RAW_BINARY) { + processBinaryDP(array[i]); } + // todo: better to move the "found++" after the process, in case it fails? } return found; } @@ -247,20 +260,6 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ //______________________________________________________________________ -template <typename T> -void DCSProcessor::process(const DPID& alias, std::deque<T>& aliasdeque) -{ - // processing the single alias - return; -} - -//______________________________________________________________________ - -template <> -void DCSProcessor::process(const DPID& alias, std::deque<int>& aliasdeque); - -//______________________________________________________________________ - template <typename T> void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA) { diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 865b971eb21a5..5900699b3816d 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -187,8 +187,6 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is // char type foundChars = processArrayType(mAliaseschars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); - if (foundChars > 0) - processChars(); // int type foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); @@ -232,7 +230,7 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is // filling CCDB info to be sent in output std::map<std::string, std::string> md; - prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, "TestDCS/SimpleMovingAverageDPs", mTF, md); + prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, mName + "/TestDCS/SimpleMovingAverageDPs", mTF, md); LOG(DEBUG) << "Size of unordered_map for CCDB = " << mccdbSimpleMovingAverage.size(); LOG(DEBUG) << "CCDB entry for TF " << mTF << " will be:"; @@ -262,7 +260,7 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliaseschars.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestampchars[index], mDpscharsmap); - process(dpid, mDpscharsmap[dpid]); + processCharDP(dpid); } else if (type == DeliveryType::RAW_INT) { @@ -273,7 +271,7 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliasesints.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestampints[index], mDpsintsmap); - process(dpid, mDpsintsmap[dpid]); + processIntDP(dpid); } else if (type == DeliveryType::RAW_DOUBLE) { @@ -284,7 +282,7 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliasesdoubles.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestampdoubles[index], mDpsdoublesmap); - process(dpid, mDpsdoublesmap[dpid]); + processDoubleDP(dpid); } else if (type == DeliveryType::RAW_UINT) { @@ -295,7 +293,7 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliasesUints.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestampUints[index], mDpsUintsmap); - process(dpid, mDpsUintsmap[dpid]); + processUIntDP(dpid); } else if (type == DeliveryType::RAW_BOOL) { @@ -306,7 +304,7 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliasesbools.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestampbools[index], mDpsboolsmap); - process(dpid, mDpsboolsmap[dpid]); + processBoolDP(dpid); } else if (type == DeliveryType::RAW_STRING) { @@ -317,8 +315,10 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliasesstrings.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestampstrings[index], mDpsstringsmap); - process(dpid, mDpsstringsmap[dpid]); - } else if (type == DeliveryType::RAW_TIME) { + processStringDP(dpid); + } + + else if (type == DeliveryType::RAW_TIME) { auto it = std::find(mAliasestimes.begin(), mAliasestimes.end(), dpid); if (it == mAliasestimes.end()) { LOG(ERROR) << "DP not found for this detector, please check"; @@ -326,8 +326,10 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliasestimes.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestamptimes[index], mDpstimesmap); - process(dpid, mDpstimesmap[dpid]); - } else if (type == DeliveryType::RAW_BINARY) { + processTimeDP(dpid); + } + + else if (type == DeliveryType::RAW_BINARY) { auto it = std::find(mAliasesbinaries.begin(), mAliasesbinaries.end(), dpid); if (it == mAliasesbinaries.end()) { LOG(ERROR) << "DP not found for this detector, please check"; @@ -335,7 +337,7 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) } int index = std::distance(mAliasesbinaries.begin(), it); checkFlagsAndFill(dpcom, mLatestTimestampbinaries[index], mDpsbinariesmap); - process(dpid, mDpsbinariesmap[dpid]); + processBinaryDP(dpid); } return 0; @@ -389,13 +391,20 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ //______________________________________________________________________ -template <> -void DCSProcessor::process(const DPID& alias, std::deque<int>& aliasdeque) +void DCSProcessor::processCharDP(const DPID& alias) +{ + // empty for the example + return; +} + +//______________________________________________________________________ + +void DCSProcessor::processIntDP(const DPID& alias) { // processing the single alias of type int bool isSMA = false; - doSimpleMovingAverage(2, aliasdeque, mSimpleMovingAverage[alias], isSMA); - LOG(DEBUG) << "Moving average = " << mSimpleMovingAverage[alias]; + doSimpleMovingAverage(2, mDpsintsmap[alias], mSimpleMovingAverage[alias], isSMA); + LOG(DEBUG) << "dpid = " << alias << " --> Moving average = " << mSimpleMovingAverage[alias]; // create CCDB object //if (isSMA) { mccdbSimpleMovingAverage[alias.get_alias()] = mSimpleMovingAverage[alias]; @@ -405,117 +414,67 @@ void DCSProcessor::process(const DPID& alias, std::deque<int>& aliasdeque) //______________________________________________________________________ -std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map) -{ - - // processing basic checks for map: all needed aliases must be present - // finds dp defined by "alias" in received map "map" - - LOG(DEBUG) << "Processing " << alias; - auto it = map.find(alias); - DeliveryType tt = alias.get_type(); - if (tt != type) { - LOG(FATAL) << "Delivery Type of alias " << alias.get_alias() << " does not match definition in DCSProcessor (" << type << ")! Please fix"; - } - return it; -} - -//______________________________________________________________________ - -void DCSProcessor::processChars() +void DCSProcessor::processDoubleDP(const DPID& alias) { - - // function to process aliases of Char type; it will just print them - - for (size_t i = 0; i != mAliaseschars.size(); ++i) { - LOG(DEBUG) << "processChars: mAliaseschars[" << i << "] = " << mAliaseschars[i]; - auto& id = mAliaseschars[i]; - auto& vchar = getVectorForAliasChar(id); - LOG(DEBUG) << "vchar size = " << vchar.size(); - for (size_t j = 0; j < vchar.size(); j++) { - LOG(DEBUG) << "DP = " << mAliaseschars[i] << " , value[" << j << "] = " << vchar[j]; - } - } + // empty for the example + return; } //______________________________________________________________________ -void DCSProcessor::processInts() +void DCSProcessor::processUIntDP(const DPID& alias) { - - // function to process aliases of Int type - - for (size_t i = 0; i != mAliasesints.size(); ++i) { - LOG(DEBUG) << "processInts: mAliasesints[" << i << "] = " << mAliasesints[i]; - if (mIsDelta && mLatestTimestampints[i] < 0) { // we have received only the delta map, and the alias "i" was not present --> we don't process, but keep the old value in the mAvgTestInt vector - continue; - } - auto& id = mAliasesints[i]; - auto& vint = getVectorForAliasInt(id); - LOG(DEBUG) << "vint size = " << vint.size(); - for (size_t j = 0; j < vint.size(); j++) { - LOG(DEBUG) << "DP = " << mAliasesints[i] << " , value[" << j << "] = " << vint[j]; - } - bool isSMA = false; - LOG(DEBUG) << "get alias = " << id.get_alias(); - // I do the moving average always of the last 2 points, no matter if it was updated or not - doSimpleMovingAverage(2, vint, mSimpleMovingAverage[id], isSMA); - LOG(DEBUG) << "Moving average = " << mSimpleMovingAverage[id]; - if (isSMA) { - // create CCDB object - mccdbSimpleMovingAverage[id.get_alias()] = mSimpleMovingAverage[id]; - } - } - std::map<std::string, std::string> md; - prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, "TestDCS/IntDPs", mTF, md); + // empty for the example + return; } //______________________________________________________________________ -void DCSProcessor::processDoubles() +void DCSProcessor::processBoolDP(const DPID& alias) { - - // function to process aliases of Double type + // empty for the example + return; } //______________________________________________________________________ -void DCSProcessor::processUInts() +void DCSProcessor::processStringDP(const DPID& alias) { - - // function to process aliases of UInt type + // empty for the example + return; } //______________________________________________________________________ -void DCSProcessor::processBools() +void DCSProcessor::processTimeDP(const DPID& alias) { - - // function to process aliases of Bool type + // empty for the example + return; } //______________________________________________________________________ -void DCSProcessor::processStrings() +void DCSProcessor::processBinaryDP(const DPID& alias) { - - // function to process aliases of String type + // empty for the example + return; } //______________________________________________________________________ -void DCSProcessor::processTimes() +std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map) { - // function to process aliases of Time type -} - -//______________________________________________________________________ - -void DCSProcessor::processBinaries() -{ + // processing basic checks for map: all needed aliases must be present + // finds dp defined by "alias" in received map "map" - // function to process aliases of Time binary + LOG(DEBUG) << "Processing " << alias; + auto it = map.find(alias); + DeliveryType tt = alias.get_type(); + if (tt != type) { + LOG(FATAL) << "Delivery Type of alias " << alias.get_alias() << " does not match definition in DCSProcessor (" << type << ")! Please fix"; + } + return it; } //______________________________________________________________________ diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index 48a57d971c60e..2311d20847761 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -87,8 +87,10 @@ class DCSDataProcessor : public o2::framework::Task mDCSproc.init(aliasVect); mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); + mDCSproc.setName("Test0Det"); mDCSprocVect[kTest].init(aliasVect); mDCSprocVect[kTest].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); + mDCSprocVect[kTest].setName("Test1Det"); mProcessFullDeltaMap = ic.options().get<bool>("process-full-delta-map"); } @@ -180,6 +182,12 @@ class DCSDataProcessor : public o2::framework::Task } } LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) in detector loop done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + // now preparing CCDB object + //for (int idet = 0; idet < detVect.size(); idet++) { + for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor + std::map<std::string, std::string> md; + mDCSprocVect[idet].prepareCCDBobject(mDCSprocVect[idet].getCCDBSimpleMovingAverage(), mDCSprocVect[idet].getCCDBSimpleMovingAverageInfo(), mDCSprocVect[idet].getName() + "/TestDCS/SimpleMovingAverageDPs", tfid, md); + } } } sendOutput(pc.outputs()); From ef8247b20d9cb416d29a0a13e59cf1158f023cb9 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Wed, 14 Oct 2020 22:35:33 +0200 Subject: [PATCH 1007/1751] Improving timing evaluation. clang. clang 2 clang 3 Again clang Clang!!!! Clang!!! Maybe like this clang will be happy --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 52 +++-- Detectors/DCS/src/DCSProcessor.cxx | 31 ++- .../DCS/testWorkflow/DCSDataGeneratorSpec.h | 76 ++++--- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 188 +++++++++++++----- 4 files changed, 244 insertions(+), 103 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index e6f3d1dbae606..8eaa6c8a6be03 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -76,13 +76,16 @@ class DCSProcessor int processDP(const std::pair<DPID, DPVAL>& dpcom); - std::unordered_map<DPID, DPVAL>::const_iterator findAndCheckAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map); + std::unordered_map<DPID, DPVAL>::const_iterator findAndCheckAlias(const DPID& alias, DeliveryType type, + const std::unordered_map<DPID, DPVAL>& map); template <typename T> - int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); + int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, + std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); template <typename T> - void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, T>& destmap); + void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, + std::unordered_map<DPID, T>& destmap); virtual void processCharDP(const DPID& alias); virtual void processIntDP(const DPID& alias); @@ -125,16 +128,21 @@ class DCSProcessor uint64_t getNCyclesNoFullMap() const { return mNCyclesNoFullMap; } template <typename T> - void prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md); + void prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, + const std::map<std::string, std::string>& md); void setName(std::string name) { mName = name; } const std::string getName() const { return mName; } private: - bool mFullMapSent = false; // set to true as soon as a full map was sent. No delta can be received if there was never a full map sent + bool mFullMapSent = false; // set to true as soon as a full map was sent. No delta can + // be received if there was never a full map sent int64_t mNCyclesNoFullMap = 0; // number of times the delta was sent withoug a full map - int64_t mMaxCyclesNoFullMap = 6000; // max number of times when the delta can be sent between two full maps (assuming DCS sends data every 50 ms, this means a 5 minutes threshold) - bool mIsDelta = false; // set to true in case you are processing delta map (containing only DPs that changed) + int64_t mMaxCyclesNoFullMap = 6000; // max number of times when the delta can be sent between + // two full maps (assuming DCS sends data every 50 ms, this + // means a 5 minutes threshold) + bool mIsDelta = false; // set to true in case you are processing delta map + // (containing only DPs that changed) std::unordered_map<DPID, float> mSimpleMovingAverage; // moving average for several DPs std::unordered_map<DPID, DQChars> mDpscharsmap; std::unordered_map<DPID, DQInts> mDpsintsmap; @@ -161,9 +169,14 @@ class DCSProcessor std::vector<int64_t> mLatestTimestamptimes; std::vector<int64_t> mLatestTimestampbinaries; int mNThreads = 1; // number of threads - std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry for the DPs for which we calculated the simple moving average - CcdbObjectInfo mccdbSimpleMovingAverageInfo; // info to store the output of the calibration for the DPs for which we calculated the simple moving average - TFType mTF = 0; // TF index for processing, used to store CCDB object + std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry + // for the DPs for which we calculated the simple + // moving average + CcdbObjectInfo mccdbSimpleMovingAverageInfo; // info to store the output of the calibration for + // the DPs for which we calculated + // the simple moving average + TFType mTF = 0; // TF index for processing, + // used to store CCDB object std::string mName = ""; // to be used to determine CCDB path ClassDefNV(DCSProcessor, 0); @@ -182,7 +195,10 @@ using DPID = o2::dcs::DataPointIdentifier; using DPVAL = o2::dcs::DataPointValue; template <typename T> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap) +int DCSProcessor::processArrayType(const std::vector<DPID>& array, + DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, + std::vector<int64_t>& latestTimeStamp, + std::unordered_map<DPID, std::deque<T>>& destmap) { // processing the array of type T @@ -228,7 +244,8 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType //______________________________________________________________________ template <typename T> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, T>& destmap) +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, + std::unordered_map<DPID, T>& destmap) { // check the flags for the upcoming data, and if ok, fill the accumulator @@ -251,12 +268,14 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DCSProcessor::DQStrings>& destmap); +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, + std::unordered_map<DPID, DCSProcessor::DQStrings>& destmap); //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DCSProcessor::DQBinaries>& destmap); +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, + std::unordered_map<DPID, DCSProcessor::DQBinaries>& destmap); //______________________________________________________________________ @@ -268,7 +287,7 @@ void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, flo if (vect.size() <= nelements) { //avg = std::accumulate(vect.begin(), vect.end(), 0.0) / vect.size(); - avg = (avg * (vect.size() - 1) + vect[vect.size() - 1]) / vect.size(); + avg = (avg * (vect.size() - 1) + vect.back()) / vect.size(); return; } @@ -280,7 +299,8 @@ void DCSProcessor::doSimpleMovingAverage(int nelements, std::deque<T>& vect, flo //______________________________________________________________________ template <typename T> -void DCSProcessor::prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, const std::map<std::string, std::string>& md) +void DCSProcessor::prepareCCDBobject(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, + const std::map<std::string, std::string>& md) { // prepare all info to be sent to CCDB for object obj diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 5900699b3816d..1151a3b8d7d90 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -23,8 +23,9 @@ using DPVAL = o2::dcs::DataPointValue; //ClassImp(o2::dcs::DCSProcessor); -void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, const std::vector<DPID>& aliasesdoubles, - const std::vector<DPID>& aliasesUints, const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, +void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, + const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, + const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries) { @@ -192,7 +193,8 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); // double type - foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, mDpsdoublesmap); + foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, + mDpsdoublesmap); // UInt type foundUInts = processArrayType(mAliasesUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); @@ -201,13 +203,15 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is foundBools = processArrayType(mAliasesbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); // String type - foundStrings = processArrayType(mAliasesstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, mDpsstringsmap); + foundStrings = processArrayType(mAliasesstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, + mDpsstringsmap); // Time type foundTimes = processArrayType(mAliasestimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); // Binary type - foundBinaries = processArrayType(mAliasesbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, mDpsbinariesmap); + foundBinaries = processArrayType(mAliasesbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, + mDpsbinariesmap); if (!isDelta) { if (foundChars != mAliaseschars.size()) @@ -230,7 +234,8 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is // filling CCDB info to be sent in output std::map<std::string, std::string> md; - prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, mName + "/TestDCS/SimpleMovingAverageDPs", mTF, md); + prepareCCDBobject(mccdbSimpleMovingAverage, mccdbSimpleMovingAverageInfo, + mName + "/TestDCS/SimpleMovingAverageDPs", mTF, md); LOG(DEBUG) << "Size of unordered_map for CCDB = " << mccdbSimpleMovingAverage.size(); LOG(DEBUG) << "CCDB entry for TF " << mTF << " will be:"; @@ -346,7 +351,8 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DQStrings>& destmap) +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, + std::unordered_map<DPID, DQStrings>& destmap) { // check the flags for the upcoming data, and if ok, fill the accumulator @@ -369,7 +375,8 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, std::unordered_map<DPID, DQBinaries>& destmap) +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, + std::unordered_map<DPID, DQBinaries>& destmap) { // check the flags for the upcoming data, and if ok, fill the accumulator @@ -462,7 +469,10 @@ void DCSProcessor::processBinaryDP(const DPID& alias) //______________________________________________________________________ -std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias(const DPID& alias, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map) +std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias(const DPID& alias, + DeliveryType type, + const std::unordered_map<DPID, DPVAL>& + map) { // processing basic checks for map: all needed aliases must be present @@ -472,7 +482,8 @@ std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias( auto it = map.find(alias); DeliveryType tt = alias.get_type(); if (tt != type) { - LOG(FATAL) << "Delivery Type of alias " << alias.get_alias() << " does not match definition in DCSProcessor (" << type << ")! Please fix"; + LOG(FATAL) << "Delivery Type of alias " << alias.get_alias() << " does not match definition in DCSProcessor (" + << type << ")! Please fix"; } return it; } diff --git a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h index 7168dacbd601b..27c0bb2977b6d 100644 --- a/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataGeneratorSpec.h @@ -93,7 +93,6 @@ class DCSDataGenerator : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final { - TStopwatch s; uint64_t tfid; for (auto& input : pc.inputs()) { tfid = header::get<o2::framework::DataProcessingHeader*>(input.header)->startTime; @@ -106,8 +105,7 @@ class DCSDataGenerator : public o2::framework::Task break; // we break because one input is enough to get the TF ID } - LOG(INFO) << "TF: " << tfid << " --> building binary blob..."; - s.Start(); + LOG(DEBUG) << "TF: " << tfid << " --> building binary blob..."; uint16_t flags = 0; uint16_t milliseconds = 0; TDatime currentTime; @@ -134,6 +132,7 @@ class DCSDataGenerator : public o2::framework::Task LOG(DEBUG) << valstring << " --> " << tt; // full map (all DPs) + mBuildingBinaryBlock.Start(mFirstTF); std::vector<DPCOM> dpcomVectFull; for (int i = 0; i < mNumDPscharFull; i++) { dpcomVectFull.emplace_back(mDPIDvectFull[i], valchar); @@ -149,6 +148,7 @@ class DCSDataGenerator : public o2::framework::Task } // delta map (only DPs that changed) + mDeltaBuildingBinaryBlock.Start(mFirstTF); std::vector<DPCOM> dpcomVectDelta; for (int i = 0; i < mNumDPscharDelta; i++) { dpcomVectDelta.emplace_back(mDPIDvectDelta[i], valchar); @@ -160,7 +160,8 @@ class DCSDataGenerator : public o2::framework::Task dpcomVectDelta.emplace_back(mDPIDvectDelta[mNumDPscharDelta + mNumDPsintDelta + i], valdouble); } for (int i = 0; i < mNumDPsstringDelta; i++) { - dpcomVectDelta.emplace_back(mDPIDvectDelta[mNumDPscharDelta + mNumDPsintDelta + mNumDPsdoubleDelta + i], valstring); + dpcomVectDelta.emplace_back(mDPIDvectDelta[mNumDPscharDelta + mNumDPsintDelta + mNumDPsdoubleDelta + i], + valstring); } // Full map @@ -176,13 +177,16 @@ class DCSDataGenerator : public o2::framework::Task } auto sbuff = buff.size(); LOG(DEBUG) << "size of output buffer = " << sbuff; - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...binary blob prepared: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); - LOG(INFO) << "TF: " << tfid << " --> sending snapshot..."; - s.Start(); + mBuildingBinaryBlock.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...binary blob prepared: realTime = " + << mBuildingBinaryBlock.RealTime() << ", cpuTime = " + << mBuildingBinaryBlock.CpuTime(); + LOG(DEBUG) << "TF: " << tfid << " --> sending snapshot..."; + mSnapshotSending.Start(mFirstTF); pc.outputs().snapshot(Output{"DCS", "DATAPOINTS", 0, Lifetime::Timeframe}, buff.data(), sbuff); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...snapshot sent: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + mSnapshotSending.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...snapshot sent: realTime = " << mSnapshotSending.RealTime() + << ", cpuTime = " << mSnapshotSending.CpuTime(); // Delta map auto svectDelta = dpcomVectDelta.size(); @@ -197,13 +201,16 @@ class DCSDataGenerator : public o2::framework::Task } auto sbuffDelta = buffDelta.size(); LOG(DEBUG) << "size of output (delta) buffer = " << sbuffDelta; - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...binary (delta) blob prepared: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); - LOG(INFO) << "TF: " << tfid << " --> sending (delta) snapshot..."; - s.Start(); + mDeltaBuildingBinaryBlock.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...binary (delta) blob prepared: realTime = " + << mDeltaBuildingBinaryBlock.RealTime() << ", cpuTime = " << mDeltaBuildingBinaryBlock.CpuTime(); + LOG(DEBUG) << "TF: " << tfid << " --> sending (delta) snapshot..."; + mDeltaSnapshotSending.Start(mFirstTF); pc.outputs().snapshot(Output{"DCS", "DATAPOINTSdelta", 0, Lifetime::Timeframe}, buffDelta.data(), sbuffDelta); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...snapshot (delta) sent: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + mDeltaSnapshotSending.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...snapshot (delta) sent: realTime = " + << mDeltaSnapshotSending.RealTime() << ", cpuTime = " + << mDeltaSnapshotSending.CpuTime(); /* LOG(INFO) << "Reading back"; @@ -226,6 +233,25 @@ class DCSDataGenerator : public o2::framework::Task tmpDPmap[mdoubleVar3] = valdouble; // to test the case when a DP is not updated, we skip some updates tmpDPmap[mstringVar0] = valstring; */ + mFirstTF = false; + mTFs++; + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + LOG(INFO) << "number of processed TF: " << mTFs; + LOG(INFO) << " --> time to prepare binary blob: realTime = " + << mBuildingBinaryBlock.RealTime() / mTFs << ", cpuTime = " + << mBuildingBinaryBlock.CpuTime() / mTFs; + LOG(INFO) << " --> time to send snapshot: realTime = " + << mSnapshotSending.RealTime() / mTFs << ", cpuTime = " + << mSnapshotSending.CpuTime() / mTFs; + LOG(INFO) << " --> time to prepare binary blob: realTime = " + << mDeltaBuildingBinaryBlock.RealTime() / mTFs << ", cpuTime = " + << mDeltaBuildingBinaryBlock.CpuTime() / mTFs; + LOG(INFO) << " --> time to send snapshot: realTime = " + << mDeltaSnapshotSending.RealTime() / mTFs << ", cpuTime = " + << mDeltaSnapshotSending.CpuTime() / mTFs; } private: @@ -242,23 +268,19 @@ class DCSDataGenerator : public o2::framework::Task uint64_t mNumDPsintDelta = 0; uint64_t mNumDPsdoubleDelta = 0; uint64_t mNumDPsstringDelta = 0; - /* - DPID mcharVar; - DPID mintVar0; - DPID mintVar1; - DPID mintVar2; - DPID mdoubleVar0; - DPID mdoubleVar1; - DPID mdoubleVar2; - DPID mdoubleVar3; - DPID mstringVar0; - */ std::vector<DPID> mDPIDvectFull; // for full map std::vector<DPID> mDPIDvectDelta; // for delta map (containing only DPs that changed) DeliveryType mtypechar = RAW_CHAR; DeliveryType mtypeint = RAW_INT; DeliveryType mtypedouble = RAW_DOUBLE; DeliveryType mtypestring = RAW_STRING; + + TStopwatch mBuildingBinaryBlock; + TStopwatch mDeltaBuildingBinaryBlock; + TStopwatch mSnapshotSending; + TStopwatch mDeltaSnapshotSending; + bool mFirstTF = true; + uint64_t mTFs = 0; }; } // namespace dcs diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index 2311d20847761..a0d99f2962c50 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -46,7 +46,7 @@ class DCSDataProcessor : public o2::framework::Task public: enum Detectors { kTest, - kTPC, + // kTPC, // commented out for test, when we use only 1 "Test" detector kNdetectors }; @@ -60,7 +60,8 @@ class DCSDataProcessor : public o2::framework::Task DPID::FILL(dpidtmp, dpAliaschar, typechar); aliasVect.push_back(dpidtmp); - std::vector<int> vectDet{kTest, kTPC}; + //std::vector<int> vectDet{kTest, kTPC}; // only one detector for now + std::vector<int> vectDet{kTest}; mDetectorAlias[dpidtmp] = vectDet; DeliveryType typeint = RAW_INT; @@ -88,9 +89,11 @@ class DCSDataProcessor : public o2::framework::Task mDCSproc.init(aliasVect); mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); mDCSproc.setName("Test0Det"); - mDCSprocVect[kTest].init(aliasVect); - mDCSprocVect[kTest].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); - mDCSprocVect[kTest].setName("Test1Det"); + for (int idet = 0; idet < kNdetectors; idet++) { + mDCSprocVect[idet].init(aliasVect); + mDCSprocVect[idet].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); + mDCSprocVect[idet].setName("Test1Det"); + } mProcessFullDeltaMap = ic.options().get<bool>("process-full-delta-map"); } @@ -98,106 +101,190 @@ class DCSDataProcessor : public o2::framework::Task { auto tfid = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; mDCSproc.setTF(tfid); + for (int idet = 0; idet < kNdetectors; idet++) { + mDCSprocVect[idet].setTF(tfid); + } TStopwatch s; - LOG(INFO) << "TF: " << tfid << " --> receiving binary data..."; - s.Start(); + LOG(DEBUG) << "TF: " << tfid << " --> receiving binary data..."; + mReceiveBinaryData.Start(mFirstTF); auto rawchar = pc.inputs().get<const char*>("input"); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...binary data received: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); - LOG(INFO) << "TF: " << tfid << " --> receiving (delta) binary data..."; - s.Start(); + mReceiveBinaryData.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...binary data received: realTime = " + << mReceiveBinaryData.RealTime() << ", cpuTime = " + << mReceiveBinaryData.CpuTime(); + LOG(DEBUG) << "TF: " << tfid << " --> receiving (delta) binary data..."; + mDeltaReceiveBinaryData.Start(mFirstTF); auto rawcharDelta = pc.inputs().get<const char*>("inputDelta"); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...binary (delta) data received: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + mDeltaReceiveBinaryData.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...binary (delta) data received: realTime = " + << mDeltaReceiveBinaryData.RealTime() + << ", cpuTime = " << mDeltaReceiveBinaryData.CpuTime(); // full map const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("input").header); auto sz = dh->payloadSize; int nDPs = sz / sizeof(DPCOM); - LOG(INFO) << "Number of DPs received = " << nDPs; std::unordered_map<DPID, DPVAL> dcsmap; DPCOM dptmp; - LOG(INFO) << "TF: " << tfid << " --> building unordered_map..."; - s.Start(); + LOG(DEBUG) << "TF: " << tfid << " --> building unordered_map..."; + mBuildingUnorderedMap.Start(mFirstTF); for (int i = 0; i < nDPs; i++) { memcpy(&dptmp, rawchar + i * sizeof(DPCOM), sizeof(DPCOM)); dcsmap[dptmp.id] = dptmp.data; LOG(DEBUG) << "Reading from generator: i = " << i << ", DPCOM = " << dptmp; LOG(DEBUG) << "Reading from generator: i = " << i << ", DPID = " << dptmp.id; } - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...unordered_map built = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + mBuildingUnorderedMap.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...unordered_map built = " + << mBuildingUnorderedMap.RealTime() << ", cpuTime = " << mBuildingUnorderedMap.CpuTime(); // delta map const auto* dhDelta = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("inputDelta").header); auto szDelta = dhDelta->payloadSize; int nDPsDelta = szDelta / sizeof(DPCOM); - LOG(INFO) << "Number of DPs received (delta map) = " << nDPsDelta; std::unordered_map<DPID, DPVAL> dcsmapDelta; - LOG(INFO) << "TF: " << tfid << " --> building (delta) unordered_map..."; - s.Start(); + LOG(DEBUG) << "TF: " << tfid << " --> building (delta) unordered_map..."; + mDeltaBuildingUnorderedMap.Start(mFirstTF); for (int i = 0; i < nDPsDelta; i++) { memcpy(&dptmp, rawcharDelta + i * sizeof(DPCOM), sizeof(DPCOM)); dcsmapDelta[dptmp.id] = dptmp.data; LOG(DEBUG) << "Reading from generator: i = " << i << ", DPCOM = " << dptmp; LOG(DEBUG) << "Reading from generator: i = " << i << ", DPID = " << dptmp.id; } - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...unordered_map (delta) built = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + mDeltaBuildingUnorderedMap.Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...unordered_map (delta) built = " + << mDeltaBuildingUnorderedMap.RealTime() << ", cpuTime = " + << mDeltaBuildingUnorderedMap.CpuTime(); if (tfid % 6000 == 0) { - //for (int idet = 0; idet < detVect.size(); idet++) { - for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor - LOG(INFO) << "TF: " << tfid << " --> starting processing..."; - s.Start(); + LOG(INFO) << "Number of DPs received = " << nDPs; + for (int idet = 0; idet < kNdetectors; idet++) { + LOG(DEBUG) << "TF: " << tfid << " --> starting processing..."; + mProcessing[idet].Start(mResetStopwatchProcessing); mDCSprocVect[idet].processMap(dcsmap, false); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...processing done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + mProcessing[idet].Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...processing done: realTime = " + << mProcessing[idet].RealTime() << ", cpuTime = " + << mProcessing[idet].CpuTime(); } + mResetStopwatchProcessing = false; // from now on, we sum up the processing time + mTFsProcessing++; } else { + LOG(INFO) << "Number of DPs received (delta map) = " << nDPsDelta; if (mProcessFullDeltaMap) { - //for (int idet = 0; idet < detVect.size(); idet++) { - for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor - LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing..."; - s.Start(); + for (int idet = 0; idet < kNdetectors; idet++) { + LOG(DEBUG) << "TF: " << tfid << " --> starting (delta) processing..."; + mDeltaProcessing[idet].Start(mResetStopwatchDeltaProcessing); mDCSprocVect[idet].processMap(dcsmapDelta, true); - s.Stop(); - LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); + mDeltaProcessing[idet].Stop(); + LOG(DEBUG) << "TF: " << tfid << " --> ...processing (delta) done: realTime = " + << mDeltaProcessing[idet].RealTime() + << ", cpuTime = " << mDeltaProcessing[idet].CpuTime(); } + mResetStopwatchDeltaProcessing = false; // from now on, we sum up the processing time + mTFsDeltaProcessing++; } else { // processing per DP found in the map, to be done in case of a delta map - bool resetStopwatch = true; - LOG(INFO) << "TF: " << tfid << " --> starting (delta) processing for detector..."; + LOG(DEBUG) << "TF: " << tfid << " --> starting (delta) processing in detector loop..."; for (const auto& dpcom : dcsmapDelta) { std::vector<int> detVect = mDetectorAlias[dpcom.first]; - //for (int idet = 0; idet < detVect.size(); idet++) { - for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor - s.Start(resetStopwatch); + for (int idet = 0; idet < detVect.size(); idet++) { + mDeltaProcessingDetLoop[idet].Start(mResetStopwatchDeltaProcessingDetLoop); mDCSprocVect[idet].processDP(dpcom); - s.Stop(); - resetStopwatch = false; + mDeltaProcessingDetLoop[idet].Stop(); } + mResetStopwatchDeltaProcessingDetLoop = false; // from now on, we sum up the processing time + } + for (int idet = 0; idet < kNdetectors; idet++) { + LOG(DEBUG) << "TF: " << tfid << " --> ...processing (delta) in detector loop done: realTime = " + << mDeltaProcessingDetLoop[idet].RealTime() << ", cpuTime = " + << mDeltaProcessingDetLoop[idet].CpuTime(); } - LOG(INFO) << "TF: " << tfid << " --> ...processing (delta) in detector loop done: realTime = " << s.RealTime() << ", cpuTime = " << s.CpuTime(); // now preparing CCDB object - //for (int idet = 0; idet < detVect.size(); idet++) { - for (int idet = 0; idet < 1; idet++) { // for now I test only 1 DCS processor + for (int idet = 0; idet < kNdetectors; idet++) { std::map<std::string, std::string> md; - mDCSprocVect[idet].prepareCCDBobject(mDCSprocVect[idet].getCCDBSimpleMovingAverage(), mDCSprocVect[idet].getCCDBSimpleMovingAverageInfo(), mDCSprocVect[idet].getName() + "/TestDCS/SimpleMovingAverageDPs", tfid, md); + mDCSprocVect[idet].prepareCCDBobject(mDCSprocVect[idet].getCCDBSimpleMovingAverage(), + mDCSprocVect[idet].getCCDBSimpleMovingAverageInfo(), + mDCSprocVect[idet].getName() + "/TestDCS/SimpleMovingAverageDPs", + tfid, md); } + mTFsDeltaProcessingDetLoop++; } } sendOutput(pc.outputs()); + mFirstTF = false; + mTFs++; + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + LOG(INFO) << "\n\nTIMING SUMMARY:\n"; + LOG(INFO) << "Number of processed TF: " << mTFs; + LOG(INFO) << "Number of processed TF, processing full map: " << mTFsProcessing; + LOG(INFO) << "Number of processed TF, processing delta map: " << mTFsDeltaProcessing; + LOG(INFO) << "Number of processed TF, processing delta map per DP: " << mTFsDeltaProcessingDetLoop; + LOG(INFO) << "Receiving binary data --> realTime = " + << mReceiveBinaryData.RealTime() / mTFs << ", cpuTime = " + << mReceiveBinaryData.CpuTime() / mTFs; + LOG(INFO) << "Receiving binary data (delta) --> realTime = " + << mDeltaReceiveBinaryData.RealTime() / mTFs << ", cpuTime = " + << mDeltaReceiveBinaryData.CpuTime() / mTFs; + LOG(INFO) << "Building unordered_map --> realTime = " + << mBuildingUnorderedMap.RealTime() / mTFs << ", cpuTime = " + << mBuildingUnorderedMap.CpuTime() / mTFs; + LOG(INFO) << "Building unordered_map (delta) --> realTime = " + << mDeltaBuildingUnorderedMap.RealTime() / mTFs << ", cpuTime = " + << mDeltaBuildingUnorderedMap.CpuTime() / mTFs; + for (int i = 0; i < kNdetectors; i++) { + LOG(INFO) << " --> : Detector " << i; + if (mTFsProcessing != 0) { + LOG(INFO) << "Processing full map (average over " << mTFsProcessing << " TFs) --> realTime = " + << mProcessing[i].RealTime() / mTFsProcessing << ", cpuTime = " + << mProcessing[i].CpuTime() / mTFsProcessing; + } else { + LOG(INFO) << "Full DCS map was never processed"; + } + if (mTFsDeltaProcessing != 0) { + LOG(INFO) << "Processing full delta map (average over " << mTFsDeltaProcessing << " TFs) --> realTime = " + << mDeltaProcessing[i].RealTime() / mTFsDeltaProcessing << ", cpuTime = " + << mDeltaProcessing[i].CpuTime() / mTFsDeltaProcessing; + } else { + LOG(INFO) << "Full delta DCS map was never processed"; + } + if (mTFsDeltaProcessingDetLoop != 0) { + LOG(INFO) << "Processing delta map per DP (average over " << mTFsDeltaProcessingDetLoop + << " TFs) --> realTime = " + << mDeltaProcessingDetLoop[i].RealTime() / mTFsDeltaProcessingDetLoop << ", cpuTime = " + << mDeltaProcessingDetLoop[i].CpuTime() / mTFsDeltaProcessingDetLoop; + } else { + LOG(INFO) << "Delta map was never process DP by DP"; + } + } } private: std::unordered_map<DPID, std::vector<int>> mDetectorAlias; std::array<DCSProcessor, kNdetectors> mDCSprocVect; o2::dcs::DCSProcessor mDCSproc; + TStopwatch mReceiveBinaryData; + TStopwatch mDeltaReceiveBinaryData; + TStopwatch mBuildingUnorderedMap; + TStopwatch mDeltaBuildingUnorderedMap; + TStopwatch mProcessing[kNdetectors]; + TStopwatch mDeltaProcessing[kNdetectors]; + TStopwatch mDeltaProcessingDetLoop[kNdetectors]; bool mProcessFullDeltaMap = false; + bool mFirstTF = true; + uint64_t mTFs = 0; + uint64_t mTFsProcessing = 0; + uint64_t mTFsDeltaProcessing = 0; + uint64_t mTFsDeltaProcessingDetLoop = 0; + bool mResetStopwatchProcessing = true; + bool mResetStopwatchDeltaProcessing = true; + bool mResetStopwatchDeltaProcessingDetLoop = true; //________________________________________________________________ void sendOutput(DataAllocator& output) @@ -208,9 +295,10 @@ class DCSDataProcessor : public o2::framework::Task const auto& payload = mDCSproc.getCCDBSimpleMovingAverage(); auto& info = mDCSproc.getCCDBSimpleMovingAverageInfo(); auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); - LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); - output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); // vector<char> + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); } }; // end class @@ -234,8 +322,8 @@ DataProcessorSpec getDCSDataProcessorSpec() outputs, AlgorithmSpec{adaptFromTask<o2::dcs::DCSDataProcessor>()}, Options{ - {"max-cycles-no-full-map", VariantType::Int64, 6000ll, {"max number of cycles between the sending of two full maps"}}, - {"process-full-delta-map", VariantType::Bool, false, {"whether to process the delta map as a whole instead of per data point"}}}}; + {"max-cycles-no-full-map", VariantType::Int64, 6000ll, {"max num of cycles between the sending of 2 full maps"}}, + {"process-full-delta-map", VariantType::Bool, false, {"to process the delta map as a whole instead of per DP"}}}}; } } // namespace framework From 585d346a33ac3445b89f696c2fd3b35f4f63a0fc Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Mon, 19 Oct 2020 10:57:55 +0200 Subject: [PATCH 1008/1751] Using unordered_map instead of vectors. clang --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 75 ++--- Detectors/DCS/src/DCSProcessor.cxx | 280 ++++++++++-------- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 18 +- 3 files changed, 207 insertions(+), 166 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index 8eaa6c8a6be03..64b37a8583ecc 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -65,12 +65,12 @@ class DCSProcessor DCSProcessor() = default; ~DCSProcessor() = default; - void init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, - const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, - const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, - const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries); + void init(const std::unordered_map<DPID, int>& dpidmapchars, const std::unordered_map<DPID, int>& dpidmapints, + const std::unordered_map<DPID, int>& dpidmapdoubles, const std::unordered_map<DPID, int>& dpidmapUints, + const std::unordered_map<DPID, int>& dpidmapbools, const std::unordered_map<DPID, int>& dpidmapstrings, + const std::unordered_map<DPID, int>& dpidmaptimes, const std::unordered_map<DPID, int>& dpidmapbinaries); - void init(const std::vector<DPID>& aliases); + void init(const std::unordered_map<DPID, int>& dpidmap); int processMap(const std::unordered_map<DPID, DPVAL>& map, bool isDelta = false); @@ -80,8 +80,9 @@ class DCSProcessor const std::unordered_map<DPID, DPVAL>& map); template <typename T> - int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, - std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); + int processArrayType(const std::unordered_map<DPID, int>& array, DeliveryType type, + const std::unordered_map<DPID, DPVAL>& map, + std::unordered_map<DPID, int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); template <typename T> void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, @@ -152,22 +153,22 @@ class DCSProcessor std::unordered_map<DPID, DQStrings> mDpsstringsmap; std::unordered_map<DPID, DQTimes> mDpstimesmap; std::unordered_map<DPID, DQBinaries> mDpsbinariesmap; - std::vector<DPID> mAliaseschars; - std::vector<DPID> mAliasesints; - std::vector<DPID> mAliasesdoubles; - std::vector<DPID> mAliasesUints; - std::vector<DPID> mAliasesbools; - std::vector<DPID> mAliasesstrings; - std::vector<DPID> mAliasestimes; - std::vector<DPID> mAliasesbinaries; - std::vector<int64_t> mLatestTimestampchars; - std::vector<int64_t> mLatestTimestampints; - std::vector<int64_t> mLatestTimestampdoubles; - std::vector<int64_t> mLatestTimestampUints; - std::vector<int64_t> mLatestTimestampbools; - std::vector<int64_t> mLatestTimestampstrings; - std::vector<int64_t> mLatestTimestamptimes; - std::vector<int64_t> mLatestTimestampbinaries; + std::unordered_map<DPID, int> mMapchars; + std::unordered_map<DPID, int> mMapints; + std::unordered_map<DPID, int> mMapdoubles; + std::unordered_map<DPID, int> mMapUints; + std::unordered_map<DPID, int> mMapbools; + std::unordered_map<DPID, int> mMapstrings; + std::unordered_map<DPID, int> mMaptimes; + std::unordered_map<DPID, int> mMapbinaries; + std::unordered_map<DPID, int64_t> mLatestTimestampchars; + std::unordered_map<DPID, int64_t> mLatestTimestampints; + std::unordered_map<DPID, int64_t> mLatestTimestampdoubles; + std::unordered_map<DPID, int64_t> mLatestTimestampUints; + std::unordered_map<DPID, int64_t> mLatestTimestampbools; + std::unordered_map<DPID, int64_t> mLatestTimestampstrings; + std::unordered_map<DPID, int64_t> mLatestTimestamptimes; + std::unordered_map<DPID, int64_t> mLatestTimestampbinaries; int mNThreads = 1; // number of threads std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry // for the DPs for which we calculated the simple @@ -195,9 +196,9 @@ using DPID = o2::dcs::DataPointIdentifier; using DPVAL = o2::dcs::DataPointValue; template <typename T> -int DCSProcessor::processArrayType(const std::vector<DPID>& array, +int DCSProcessor::processArrayType(const std::unordered_map<DPID, int>& mapDPid, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, - std::vector<int64_t>& latestTimeStamp, + std::unordered_map<DPID, int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap) { @@ -208,33 +209,33 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, //omp_set_num_threads(mNThreads); //#pragma omp parallel for schedule(dynamic) //#endif - for (size_t i = 0; i != array.size(); ++i) { - auto it = findAndCheckAlias(array[i], type, map); + for (const auto& el : mapDPid) { + auto it = findAndCheckAlias(el.first, type, map); if (it == map.end()) { if (!mIsDelta) { - LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; + LOG(ERROR) << "Element " << el.first << " not found " << std::endl; } continue; } found++; std::pair<DPID, DPVAL> pairIt = *it; - checkFlagsAndFill(pairIt, latestTimeStamp[i], destmap); + checkFlagsAndFill(pairIt, latestTimeStamp[pairIt.first], destmap); if (type == RAW_CHAR) { - processCharDP(array[i]); + processCharDP(el.first); } else if (type == RAW_INT) { - processIntDP(array[i]); + processIntDP(el.first); } else if (type == RAW_DOUBLE) { - processDoubleDP(array[i]); + processDoubleDP(el.first); } else if (type == RAW_UINT) { - processUIntDP(array[i]); + processUIntDP(el.first); } else if (type == RAW_BOOL) { - processBoolDP(array[i]); + processBoolDP(el.first); } else if (type == RAW_STRING) { - processStringDP(array[i]); + processStringDP(el.first); } else if (type == RAW_TIME) { - processTimeDP(array[i]); + processTimeDP(el.first); } else if (type == RAW_BINARY) { - processBinaryDP(array[i]); + processBinaryDP(el.first); } // todo: better to move the "found++" after the process, in case it fails? } diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 1151a3b8d7d90..ea6c6f94ae749 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -23,138 +23,140 @@ using DPVAL = o2::dcs::DataPointValue; //ClassImp(o2::dcs::DCSProcessor); -void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, - const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, - const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, - const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries) +void DCSProcessor::init(const std::unordered_map<DPID, int>& dpidmapchars, + const std::unordered_map<DPID, int>& dpidmapints, + const std::unordered_map<DPID, int>& dpidmapdoubles, + const std::unordered_map<DPID, int>& dpidmapUints, + const std::unordered_map<DPID, int>& dpidmapbools, + const std::unordered_map<DPID, int>& dpidmapstrings, + const std::unordered_map<DPID, int>& dpidmaptimes, + const std::unordered_map<DPID, int>& dpidmapbinaries) { // init from separate vectors of aliases (one per data point type) // chars - for (auto it = std::begin(aliaseschars); it != std::end(aliaseschars); ++it) { - if ((*it).get_type() != DeliveryType::RAW_CHAR) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a char"; + for (const auto& el : dpidmapchars) { + if ((el.first).get_type() != DeliveryType::RAW_CHAR) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a char"; } - mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + mMapchars[el.first] = el.second; + mLatestTimestampchars[el.first] = 0; } // ints - for (auto it = std::begin(aliasesints); it != std::end(aliasesints); ++it) { - if ((*it).get_type() != DeliveryType::RAW_INT) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a int"; + for (const auto& el : dpidmapints) { + if ((el.first).get_type() != DeliveryType::RAW_INT) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a int"; } - mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + mMapints[el.first] = el.second; + mLatestTimestampints[el.first] = 0; } // doubles - for (auto it = std::begin(aliasesdoubles); it != std::end(aliasesdoubles); ++it) { - if ((*it).get_type() != DeliveryType::RAW_DOUBLE) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a double"; + for (const auto& el : dpidmapdoubles) { + if ((el.first).get_type() != DeliveryType::RAW_DOUBLE) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a double"; } - mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + mMapdoubles[el.first] = el.second; + mLatestTimestampdoubles[el.first] = 0; } // uints - for (auto it = std::begin(aliasesUints); it != std::end(aliasesUints); ++it) { - if ((*it).get_type() != DeliveryType::RAW_UINT) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a uint"; + for (const auto& el : dpidmapUints) { + if ((el.first).get_type() != DeliveryType::RAW_UINT) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a uint"; } - mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + mMapUints[el.first] = el.second; + mLatestTimestampUints[el.first] = 0; } // bools - for (auto it = std::begin(aliasesbools); it != std::end(aliasesbools); ++it) { - if ((*it).get_type() != DeliveryType::RAW_BOOL) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a bool"; + for (const auto& el : dpidmapbools) { + if ((el.first).get_type() != DeliveryType::RAW_BOOL) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a bool"; } - mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + mMapbools[el.first] = el.second; + mLatestTimestampbools[el.first] = 0; } // strings - for (auto it = std::begin(aliasesstrings); it != std::end(aliasesstrings); ++it) { - if ((*it).get_type() != DeliveryType::RAW_STRING) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a string"; + for (const auto& el : dpidmapstrings) { + if ((el.first).get_type() != DeliveryType::RAW_STRING) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a string"; } - mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + mMapstrings[el.first] = el.second; + mLatestTimestampstrings[el.first] = 0; } // times - for (auto it = std::begin(aliasestimes); it != std::end(aliasestimes); ++it) { - if ((*it).get_type() != DeliveryType::RAW_TIME) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a time"; + for (const auto& el : dpidmaptimes) { + if ((el.first).get_type() != DeliveryType::RAW_TIME) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a time"; } - mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + mMaptimes[el.first] = el.second; + mLatestTimestamptimes[el.first] = 0; } // binaries - for (auto it = std::begin(aliasesbinaries); it != std::end(aliasesbinaries); ++it) { - if ((*it).get_type() != DeliveryType::RAW_BINARY) { - LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a binary"; + for (const auto& el : dpidmapbinaries) { + if ((el.first).get_type() != DeliveryType::RAW_BINARY) { + LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a binary"; } - mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); + mMapbinaries[el.first] = el.second; + mLatestTimestampbinaries[el.first] = 0; } - - mLatestTimestampchars.resize(aliaseschars.size(), 0); - mLatestTimestampints.resize(aliasesints.size(), 0); - mLatestTimestampdoubles.resize(aliasesdoubles.size(), 0); - mLatestTimestampUints.resize(aliasesUints.size(), 0); - mLatestTimestampbools.resize(aliasesbools.size(), 0); - mLatestTimestampstrings.resize(aliasesstrings.size(), 0); - mLatestTimestamptimes.resize(aliasestimes.size(), 0); - mLatestTimestampbinaries.resize(aliasesbinaries.size(), 0); } //______________________________________________________________________ -void DCSProcessor::init(const std::vector<DPID>& aliases) +void DCSProcessor::init(const std::unordered_map<DPID, int>& dpidmap) { int nchars = 0, nints = 0, ndoubles = 0, nUints = 0, nbools = 0, nstrings = 0, ntimes = 0, nbinaries = 0; - for (auto it = std::begin(aliases); it != std::end(aliases); ++it) { - if ((*it).get_type() == DeliveryType::RAW_CHAR) { - mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + for (const auto& el : dpidmap) { + if ((el.first).get_type() == DeliveryType::RAW_CHAR) { + mMapchars[el.first] = el.second; + mLatestTimestampchars[el.first] = 0; nchars++; } - if ((*it).get_type() == DeliveryType::RAW_INT) { - mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + if ((el.first).get_type() == DeliveryType::RAW_INT) { + mMapints[el.first] = el.second; + mLatestTimestampints[el.first] = 0; nints++; } - if ((*it).get_type() == DeliveryType::RAW_DOUBLE) { - mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + if ((el.first).get_type() == DeliveryType::RAW_DOUBLE) { + mMapdoubles[el.first] = el.second; + mLatestTimestampdoubles[el.first] = 0; ndoubles++; } - if ((*it).get_type() == DeliveryType::RAW_UINT) { - mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + if ((el.first).get_type() == DeliveryType::RAW_UINT) { + mMapUints[el.first] = el.second; + mLatestTimestampUints[el.first] = 0; nUints++; } - if ((*it).get_type() == DeliveryType::RAW_BOOL) { - mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + if ((el.first).get_type() == DeliveryType::RAW_BOOL) { + mMapbools[el.first] = el.second; + mLatestTimestampbools[el.first] = 0; nbools++; } - if ((*it).get_type() == DeliveryType::RAW_STRING) { - mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + if ((el.first).get_type() == DeliveryType::RAW_STRING) { + mMapstrings[el.first] = el.second; + mLatestTimestampstrings[el.first] = 0; nstrings++; } - if ((*it).get_type() == DeliveryType::RAW_TIME) { - mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + if ((el.first).get_type() == DeliveryType::RAW_TIME) { + mMaptimes[el.first] = el.second; + mLatestTimestamptimes[el.first] = 0; ntimes++; } - if ((*it).get_type() == DeliveryType::RAW_BINARY) { - mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); + if ((el.first).get_type() == DeliveryType::RAW_BINARY) { + mMapbinaries[el.first] = el.second; + mLatestTimestampbinaries[el.first] = 0; nbinaries++; } } - - mLatestTimestampchars.resize(nchars, 0); - mLatestTimestampints.resize(nints, 0); - mLatestTimestampdoubles.resize(ndoubles, 0); - mLatestTimestampUints.resize(nUints, 0); - mLatestTimestampbools.resize(nbools, 0); - mLatestTimestampstrings.resize(nstrings, 0); - mLatestTimestamptimes.resize(ntimes, 0); - mLatestTimestampbinaries.resize(nbinaries, 0); } //__________________________________________________________________ @@ -187,48 +189,48 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is foundBools = 0, foundStrings = 0, foundTimes = 0, foundBinaries = 0; // char type - foundChars = processArrayType(mAliaseschars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); + foundChars = processArrayType(mMapchars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); // int type - foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); + foundInts = processArrayType(mMapints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); // double type - foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, + foundDoubles = processArrayType(mMapdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, mDpsdoublesmap); // UInt type - foundUInts = processArrayType(mAliasesUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); + foundUInts = processArrayType(mMapUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); // Bool type - foundBools = processArrayType(mAliasesbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); + foundBools = processArrayType(mMapbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); // String type - foundStrings = processArrayType(mAliasesstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, + foundStrings = processArrayType(mMapstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, mDpsstringsmap); // Time type - foundTimes = processArrayType(mAliasestimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); + foundTimes = processArrayType(mMaptimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); // Binary type - foundBinaries = processArrayType(mAliasesbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, + foundBinaries = processArrayType(mMapbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, mDpsbinariesmap); if (!isDelta) { - if (foundChars != mAliaseschars.size()) + if (foundChars != mMapchars.size()) LOG(INFO) << "Not all expected char-typed DPs found!"; - if (foundInts != mAliasesints.size()) + if (foundInts != mMapints.size()) LOG(INFO) << "Not all expected int-typed DPs found!"; - if (foundDoubles != mAliasesdoubles.size()) + if (foundDoubles != mMapdoubles.size()) LOG(INFO) << "Not all expected double-typed DPs found!"; - if (foundUInts != mAliasesUints.size()) + if (foundUInts != mMapUints.size()) LOG(INFO) << "Not all expected uint-typed DPs found!"; - if (foundBools != mAliasesbools.size()) + if (foundBools != mMapbools.size()) LOG(INFO) << "Not all expected bool-typed DPs found!"; - if (foundStrings != mAliasesstrings.size()) + if (foundStrings != mMapstrings.size()) LOG(INFO) << "Not all expected string-typed DPs found!"; - if (foundTimes != mAliasestimes.size()) + if (foundTimes != mMaptimes.size()) LOG(INFO) << "Not all expected time-typed DPs found!"; - if (foundBinaries != mAliasesbinaries.size()) + if (foundBinaries != mMapbinaries.size()) LOG(INFO) << "Not all expected binary-typed DPs found!"; } @@ -258,90 +260,128 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) // first we check if the DP is in the list for the detector if (type == DeliveryType::RAW_CHAR) { - auto it = std::find(mAliaseschars.begin(), mAliaseschars.end(), dpid); - if (it == mAliaseschars.end()) { + auto el = mMapchars.find(dpid); + if (el == mMapchars.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliaseschars.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampchars[index], mDpscharsmap); + auto elTime = mLatestTimestampchars.find(dpid); + if (elTime == mLatestTimestampchars.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + checkFlagsAndFill(dpcom, mLatestTimestampchars[dpid], mDpscharsmap); processCharDP(dpid); } else if (type == DeliveryType::RAW_INT) { - auto it = std::find(mAliasesints.begin(), mAliasesints.end(), dpid); - if (it == mAliasesints.end()) { + std::vector<int64_t> tmp; + tmp.resize(100, 0); + auto el = mMapints.find(dpid); + if (el == mMapints.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliasesints.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampints[index], mDpsintsmap); + + auto elTime = mLatestTimestampints.find(dpid); + if (elTime == mLatestTimestampints.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + + checkFlagsAndFill(dpcom, (*elTime).second, mDpsintsmap); + //checkFlagsAndFill(dpcom, tmp[0], mDpsintsmap); + //checkFlagsAndFill(dpcom, mLatestTimestampints[dpid], mDpsintsmap); processIntDP(dpid); } else if (type == DeliveryType::RAW_DOUBLE) { - auto it = std::find(mAliasesdoubles.begin(), mAliasesdoubles.end(), dpid); - if (it == mAliasesdoubles.end()) { + auto el = mMapdoubles.find(dpid); + if (el == mMapdoubles.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliasesdoubles.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampdoubles[index], mDpsdoublesmap); + auto elTime = mLatestTimestampdoubles.find(dpid); + if (elTime == mLatestTimestampdoubles.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + checkFlagsAndFill(dpcom, mLatestTimestampdoubles[dpid], mDpsdoublesmap); processDoubleDP(dpid); } else if (type == DeliveryType::RAW_UINT) { - auto it = std::find(mAliasesUints.begin(), mAliasesUints.end(), dpid); - if (it == mAliasesUints.end()) { + auto el = mMapUints.find(dpid); + if (el == mMapUints.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliasesUints.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampUints[index], mDpsUintsmap); + auto elTime = mLatestTimestampUints.find(dpid); + if (elTime == mLatestTimestampUints.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + checkFlagsAndFill(dpcom, mLatestTimestampUints[dpid], mDpsUintsmap); processUIntDP(dpid); } else if (type == DeliveryType::RAW_BOOL) { - auto it = std::find(mAliasesbools.begin(), mAliasesbools.end(), dpid); - if (it == mAliasesbools.end()) { + auto el = mMapbools.find(dpid); + if (el == mMapbools.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliasesbools.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampbools[index], mDpsboolsmap); + auto elTime = mLatestTimestampbools.find(dpid); + if (elTime == mLatestTimestampbools.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + checkFlagsAndFill(dpcom, mLatestTimestampbools[dpid], mDpsboolsmap); processBoolDP(dpid); } else if (type == DeliveryType::RAW_STRING) { - auto it = std::find(mAliasesstrings.begin(), mAliasesstrings.end(), dpid); - if (it == mAliasesstrings.end()) { + auto el = mMapstrings.find(dpid); + if (el == mMapstrings.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliasesstrings.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampstrings[index], mDpsstringsmap); + auto elTime = mLatestTimestampstrings.find(dpid); + if (elTime == mLatestTimestampstrings.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + checkFlagsAndFill(dpcom, mLatestTimestampstrings[dpid], mDpsstringsmap); processStringDP(dpid); } else if (type == DeliveryType::RAW_TIME) { - auto it = std::find(mAliasestimes.begin(), mAliasestimes.end(), dpid); - if (it == mAliasestimes.end()) { + auto el = mMaptimes.find(dpid); + if (el == mMaptimes.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliasestimes.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestamptimes[index], mDpstimesmap); + auto elTime = mLatestTimestamptimes.find(dpid); + if (elTime == mLatestTimestamptimes.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + checkFlagsAndFill(dpcom, mLatestTimestamptimes[dpid], mDpstimesmap); processTimeDP(dpid); } else if (type == DeliveryType::RAW_BINARY) { - auto it = std::find(mAliasesbinaries.begin(), mAliasesbinaries.end(), dpid); - if (it == mAliasesbinaries.end()) { + auto el = mMapbinaries.find(dpid); + if (el == mMapbinaries.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - int index = std::distance(mAliasesbinaries.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampbinaries[index], mDpsbinariesmap); + auto elTime = mLatestTimestampbinaries.find(dpid); + if (elTime == mLatestTimestampbinaries.end()) { + LOG(ERROR) << "Timestamp not found for this DP, please check"; + return 1; + } + checkFlagsAndFill(dpcom, mLatestTimestampbinaries[dpid], mDpsbinariesmap); processBinaryDP(dpid); } diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index a0d99f2962c50..4a407361bdc9c 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -52,13 +52,13 @@ class DCSDataProcessor : public o2::framework::Task void init(o2::framework::InitContext& ic) final { - std::vector<DPID> aliasVect; + std::unordered_map<DPID, int> dpMap; DPID dpidtmp; DeliveryType typechar = RAW_CHAR; std::string dpAliaschar = "TestChar_0"; DPID::FILL(dpidtmp, dpAliaschar, typechar); - aliasVect.push_back(dpidtmp); + dpMap[dpidtmp] = 1; //std::vector<int> vectDet{kTest, kTPC}; // only one detector for now std::vector<int> vectDet{kTest}; @@ -68,7 +68,7 @@ class DCSDataProcessor : public o2::framework::Task for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasint, typeint); - aliasVect.push_back(dpidtmp); + dpMap[dpidtmp] = 1; mDetectorAlias[dpidtmp] = vectDet; } @@ -76,21 +76,21 @@ class DCSDataProcessor : public o2::framework::Task for (int i = 0; i < 4; i++) { std::string dpAliasdouble = "TestDouble_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasdouble, typedouble); - aliasVect.push_back(dpidtmp); + dpMap[dpidtmp] = 1; mDetectorAlias[dpidtmp] = vectDet; } DeliveryType typestring = RAW_STRING; std::string dpAliasstring0 = "TestString_0"; DPID::FILL(dpidtmp, dpAliasstring0, typestring); - aliasVect.push_back(dpidtmp); + dpMap[dpidtmp] = 1; mDetectorAlias[dpidtmp] = vectDet; - mDCSproc.init(aliasVect); + mDCSproc.init(dpMap); mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); mDCSproc.setName("Test0Det"); for (int idet = 0; idet < kNdetectors; idet++) { - mDCSprocVect[idet].init(aliasVect); + mDCSprocVect[idet].init(dpMap); mDCSprocVect[idet].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); mDCSprocVect[idet].setName("Test1Det"); } @@ -295,8 +295,8 @@ class DCSDataProcessor : public o2::framework::Task const auto& payload = mDCSproc.getCCDBSimpleMovingAverage(); auto& info = mDCSproc.getCCDBSimpleMovingAverageInfo(); auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); - LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() - << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + LOG(DEBUG) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); From 79cb0f25071c0698d3dad73e528a8f2ffbd8ffd9 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Mon, 19 Oct 2020 15:05:25 +0200 Subject: [PATCH 1009/1751] Revert "Using unordered_map instead of vectors." This reverts commit 40ce3e718f268e50d5574e8287c6694b6c26355a. --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 75 +++-- Detectors/DCS/src/DCSProcessor.cxx | 280 ++++++++---------- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 18 +- 3 files changed, 166 insertions(+), 207 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index 64b37a8583ecc..8eaa6c8a6be03 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -65,12 +65,12 @@ class DCSProcessor DCSProcessor() = default; ~DCSProcessor() = default; - void init(const std::unordered_map<DPID, int>& dpidmapchars, const std::unordered_map<DPID, int>& dpidmapints, - const std::unordered_map<DPID, int>& dpidmapdoubles, const std::unordered_map<DPID, int>& dpidmapUints, - const std::unordered_map<DPID, int>& dpidmapbools, const std::unordered_map<DPID, int>& dpidmapstrings, - const std::unordered_map<DPID, int>& dpidmaptimes, const std::unordered_map<DPID, int>& dpidmapbinaries); + void init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, + const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, + const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, + const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries); - void init(const std::unordered_map<DPID, int>& dpidmap); + void init(const std::vector<DPID>& aliases); int processMap(const std::unordered_map<DPID, DPVAL>& map, bool isDelta = false); @@ -80,9 +80,8 @@ class DCSProcessor const std::unordered_map<DPID, DPVAL>& map); template <typename T> - int processArrayType(const std::unordered_map<DPID, int>& array, DeliveryType type, - const std::unordered_map<DPID, DPVAL>& map, - std::unordered_map<DPID, int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); + int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, + std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); template <typename T> void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, @@ -153,22 +152,22 @@ class DCSProcessor std::unordered_map<DPID, DQStrings> mDpsstringsmap; std::unordered_map<DPID, DQTimes> mDpstimesmap; std::unordered_map<DPID, DQBinaries> mDpsbinariesmap; - std::unordered_map<DPID, int> mMapchars; - std::unordered_map<DPID, int> mMapints; - std::unordered_map<DPID, int> mMapdoubles; - std::unordered_map<DPID, int> mMapUints; - std::unordered_map<DPID, int> mMapbools; - std::unordered_map<DPID, int> mMapstrings; - std::unordered_map<DPID, int> mMaptimes; - std::unordered_map<DPID, int> mMapbinaries; - std::unordered_map<DPID, int64_t> mLatestTimestampchars; - std::unordered_map<DPID, int64_t> mLatestTimestampints; - std::unordered_map<DPID, int64_t> mLatestTimestampdoubles; - std::unordered_map<DPID, int64_t> mLatestTimestampUints; - std::unordered_map<DPID, int64_t> mLatestTimestampbools; - std::unordered_map<DPID, int64_t> mLatestTimestampstrings; - std::unordered_map<DPID, int64_t> mLatestTimestamptimes; - std::unordered_map<DPID, int64_t> mLatestTimestampbinaries; + std::vector<DPID> mAliaseschars; + std::vector<DPID> mAliasesints; + std::vector<DPID> mAliasesdoubles; + std::vector<DPID> mAliasesUints; + std::vector<DPID> mAliasesbools; + std::vector<DPID> mAliasesstrings; + std::vector<DPID> mAliasestimes; + std::vector<DPID> mAliasesbinaries; + std::vector<int64_t> mLatestTimestampchars; + std::vector<int64_t> mLatestTimestampints; + std::vector<int64_t> mLatestTimestampdoubles; + std::vector<int64_t> mLatestTimestampUints; + std::vector<int64_t> mLatestTimestampbools; + std::vector<int64_t> mLatestTimestampstrings; + std::vector<int64_t> mLatestTimestamptimes; + std::vector<int64_t> mLatestTimestampbinaries; int mNThreads = 1; // number of threads std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry // for the DPs for which we calculated the simple @@ -196,9 +195,9 @@ using DPID = o2::dcs::DataPointIdentifier; using DPVAL = o2::dcs::DataPointValue; template <typename T> -int DCSProcessor::processArrayType(const std::unordered_map<DPID, int>& mapDPid, +int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, - std::unordered_map<DPID, int64_t>& latestTimeStamp, + std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap) { @@ -209,33 +208,33 @@ int DCSProcessor::processArrayType(const std::unordered_map<DPID, int>& mapDPid, //omp_set_num_threads(mNThreads); //#pragma omp parallel for schedule(dynamic) //#endif - for (const auto& el : mapDPid) { - auto it = findAndCheckAlias(el.first, type, map); + for (size_t i = 0; i != array.size(); ++i) { + auto it = findAndCheckAlias(array[i], type, map); if (it == map.end()) { if (!mIsDelta) { - LOG(ERROR) << "Element " << el.first << " not found " << std::endl; + LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; } continue; } found++; std::pair<DPID, DPVAL> pairIt = *it; - checkFlagsAndFill(pairIt, latestTimeStamp[pairIt.first], destmap); + checkFlagsAndFill(pairIt, latestTimeStamp[i], destmap); if (type == RAW_CHAR) { - processCharDP(el.first); + processCharDP(array[i]); } else if (type == RAW_INT) { - processIntDP(el.first); + processIntDP(array[i]); } else if (type == RAW_DOUBLE) { - processDoubleDP(el.first); + processDoubleDP(array[i]); } else if (type == RAW_UINT) { - processUIntDP(el.first); + processUIntDP(array[i]); } else if (type == RAW_BOOL) { - processBoolDP(el.first); + processBoolDP(array[i]); } else if (type == RAW_STRING) { - processStringDP(el.first); + processStringDP(array[i]); } else if (type == RAW_TIME) { - processTimeDP(el.first); + processTimeDP(array[i]); } else if (type == RAW_BINARY) { - processBinaryDP(el.first); + processBinaryDP(array[i]); } // todo: better to move the "found++" after the process, in case it fails? } diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index ea6c6f94ae749..1151a3b8d7d90 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -23,140 +23,138 @@ using DPVAL = o2::dcs::DataPointValue; //ClassImp(o2::dcs::DCSProcessor); -void DCSProcessor::init(const std::unordered_map<DPID, int>& dpidmapchars, - const std::unordered_map<DPID, int>& dpidmapints, - const std::unordered_map<DPID, int>& dpidmapdoubles, - const std::unordered_map<DPID, int>& dpidmapUints, - const std::unordered_map<DPID, int>& dpidmapbools, - const std::unordered_map<DPID, int>& dpidmapstrings, - const std::unordered_map<DPID, int>& dpidmaptimes, - const std::unordered_map<DPID, int>& dpidmapbinaries) +void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, + const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, + const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, + const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries) { // init from separate vectors of aliases (one per data point type) // chars - for (const auto& el : dpidmapchars) { - if ((el.first).get_type() != DeliveryType::RAW_CHAR) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a char"; + for (auto it = std::begin(aliaseschars); it != std::end(aliaseschars); ++it) { + if ((*it).get_type() != DeliveryType::RAW_CHAR) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a char"; } - mMapchars[el.first] = el.second; - mLatestTimestampchars[el.first] = 0; + mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); } // ints - for (const auto& el : dpidmapints) { - if ((el.first).get_type() != DeliveryType::RAW_INT) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a int"; + for (auto it = std::begin(aliasesints); it != std::end(aliasesints); ++it) { + if ((*it).get_type() != DeliveryType::RAW_INT) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a int"; } - mMapints[el.first] = el.second; - mLatestTimestampints[el.first] = 0; + mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); } // doubles - for (const auto& el : dpidmapdoubles) { - if ((el.first).get_type() != DeliveryType::RAW_DOUBLE) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a double"; + for (auto it = std::begin(aliasesdoubles); it != std::end(aliasesdoubles); ++it) { + if ((*it).get_type() != DeliveryType::RAW_DOUBLE) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a double"; } - mMapdoubles[el.first] = el.second; - mLatestTimestampdoubles[el.first] = 0; + mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); } // uints - for (const auto& el : dpidmapUints) { - if ((el.first).get_type() != DeliveryType::RAW_UINT) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a uint"; + for (auto it = std::begin(aliasesUints); it != std::end(aliasesUints); ++it) { + if ((*it).get_type() != DeliveryType::RAW_UINT) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a uint"; } - mMapUints[el.first] = el.second; - mLatestTimestampUints[el.first] = 0; + mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); } // bools - for (const auto& el : dpidmapbools) { - if ((el.first).get_type() != DeliveryType::RAW_BOOL) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a bool"; + for (auto it = std::begin(aliasesbools); it != std::end(aliasesbools); ++it) { + if ((*it).get_type() != DeliveryType::RAW_BOOL) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a bool"; } - mMapbools[el.first] = el.second; - mLatestTimestampbools[el.first] = 0; + mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); } // strings - for (const auto& el : dpidmapstrings) { - if ((el.first).get_type() != DeliveryType::RAW_STRING) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a string"; + for (auto it = std::begin(aliasesstrings); it != std::end(aliasesstrings); ++it) { + if ((*it).get_type() != DeliveryType::RAW_STRING) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a string"; } - mMapstrings[el.first] = el.second; - mLatestTimestampstrings[el.first] = 0; + mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); } // times - for (const auto& el : dpidmaptimes) { - if ((el.first).get_type() != DeliveryType::RAW_TIME) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a time"; + for (auto it = std::begin(aliasestimes); it != std::end(aliasestimes); ++it) { + if ((*it).get_type() != DeliveryType::RAW_TIME) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a time"; } - mMaptimes[el.first] = el.second; - mLatestTimestamptimes[el.first] = 0; + mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); } // binaries - for (const auto& el : dpidmapbinaries) { - if ((el.first).get_type() != DeliveryType::RAW_BINARY) { - LOG(FATAL) << "Type for data point " << el.first << " does not match with expectations! It should be a binary"; + for (auto it = std::begin(aliasesbinaries); it != std::end(aliasesbinaries); ++it) { + if ((*it).get_type() != DeliveryType::RAW_BINARY) { + LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a binary"; } - mMapbinaries[el.first] = el.second; - mLatestTimestampbinaries[el.first] = 0; + mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); } + + mLatestTimestampchars.resize(aliaseschars.size(), 0); + mLatestTimestampints.resize(aliasesints.size(), 0); + mLatestTimestampdoubles.resize(aliasesdoubles.size(), 0); + mLatestTimestampUints.resize(aliasesUints.size(), 0); + mLatestTimestampbools.resize(aliasesbools.size(), 0); + mLatestTimestampstrings.resize(aliasesstrings.size(), 0); + mLatestTimestamptimes.resize(aliasestimes.size(), 0); + mLatestTimestampbinaries.resize(aliasesbinaries.size(), 0); } //______________________________________________________________________ -void DCSProcessor::init(const std::unordered_map<DPID, int>& dpidmap) +void DCSProcessor::init(const std::vector<DPID>& aliases) { int nchars = 0, nints = 0, ndoubles = 0, nUints = 0, nbools = 0, nstrings = 0, ntimes = 0, nbinaries = 0; - for (const auto& el : dpidmap) { - if ((el.first).get_type() == DeliveryType::RAW_CHAR) { - mMapchars[el.first] = el.second; - mLatestTimestampchars[el.first] = 0; + for (auto it = std::begin(aliases); it != std::end(aliases); ++it) { + if ((*it).get_type() == DeliveryType::RAW_CHAR) { + mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); nchars++; } - if ((el.first).get_type() == DeliveryType::RAW_INT) { - mMapints[el.first] = el.second; - mLatestTimestampints[el.first] = 0; + if ((*it).get_type() == DeliveryType::RAW_INT) { + mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); nints++; } - if ((el.first).get_type() == DeliveryType::RAW_DOUBLE) { - mMapdoubles[el.first] = el.second; - mLatestTimestampdoubles[el.first] = 0; + if ((*it).get_type() == DeliveryType::RAW_DOUBLE) { + mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); ndoubles++; } - if ((el.first).get_type() == DeliveryType::RAW_UINT) { - mMapUints[el.first] = el.second; - mLatestTimestampUints[el.first] = 0; + if ((*it).get_type() == DeliveryType::RAW_UINT) { + mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); nUints++; } - if ((el.first).get_type() == DeliveryType::RAW_BOOL) { - mMapbools[el.first] = el.second; - mLatestTimestampbools[el.first] = 0; + if ((*it).get_type() == DeliveryType::RAW_BOOL) { + mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); nbools++; } - if ((el.first).get_type() == DeliveryType::RAW_STRING) { - mMapstrings[el.first] = el.second; - mLatestTimestampstrings[el.first] = 0; + if ((*it).get_type() == DeliveryType::RAW_STRING) { + mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); nstrings++; } - if ((el.first).get_type() == DeliveryType::RAW_TIME) { - mMaptimes[el.first] = el.second; - mLatestTimestamptimes[el.first] = 0; + if ((*it).get_type() == DeliveryType::RAW_TIME) { + mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); ntimes++; } - if ((el.first).get_type() == DeliveryType::RAW_BINARY) { - mMapbinaries[el.first] = el.second; - mLatestTimestampbinaries[el.first] = 0; + if ((*it).get_type() == DeliveryType::RAW_BINARY) { + mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); nbinaries++; } } + + mLatestTimestampchars.resize(nchars, 0); + mLatestTimestampints.resize(nints, 0); + mLatestTimestampdoubles.resize(ndoubles, 0); + mLatestTimestampUints.resize(nUints, 0); + mLatestTimestampbools.resize(nbools, 0); + mLatestTimestampstrings.resize(nstrings, 0); + mLatestTimestamptimes.resize(ntimes, 0); + mLatestTimestampbinaries.resize(nbinaries, 0); } //__________________________________________________________________ @@ -189,48 +187,48 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is foundBools = 0, foundStrings = 0, foundTimes = 0, foundBinaries = 0; // char type - foundChars = processArrayType(mMapchars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); + foundChars = processArrayType(mAliaseschars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); // int type - foundInts = processArrayType(mMapints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); + foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); // double type - foundDoubles = processArrayType(mMapdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, + foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, mDpsdoublesmap); // UInt type - foundUInts = processArrayType(mMapUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); + foundUInts = processArrayType(mAliasesUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); // Bool type - foundBools = processArrayType(mMapbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); + foundBools = processArrayType(mAliasesbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); // String type - foundStrings = processArrayType(mMapstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, + foundStrings = processArrayType(mAliasesstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, mDpsstringsmap); // Time type - foundTimes = processArrayType(mMaptimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); + foundTimes = processArrayType(mAliasestimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); // Binary type - foundBinaries = processArrayType(mMapbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, + foundBinaries = processArrayType(mAliasesbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, mDpsbinariesmap); if (!isDelta) { - if (foundChars != mMapchars.size()) + if (foundChars != mAliaseschars.size()) LOG(INFO) << "Not all expected char-typed DPs found!"; - if (foundInts != mMapints.size()) + if (foundInts != mAliasesints.size()) LOG(INFO) << "Not all expected int-typed DPs found!"; - if (foundDoubles != mMapdoubles.size()) + if (foundDoubles != mAliasesdoubles.size()) LOG(INFO) << "Not all expected double-typed DPs found!"; - if (foundUInts != mMapUints.size()) + if (foundUInts != mAliasesUints.size()) LOG(INFO) << "Not all expected uint-typed DPs found!"; - if (foundBools != mMapbools.size()) + if (foundBools != mAliasesbools.size()) LOG(INFO) << "Not all expected bool-typed DPs found!"; - if (foundStrings != mMapstrings.size()) + if (foundStrings != mAliasesstrings.size()) LOG(INFO) << "Not all expected string-typed DPs found!"; - if (foundTimes != mMaptimes.size()) + if (foundTimes != mAliasestimes.size()) LOG(INFO) << "Not all expected time-typed DPs found!"; - if (foundBinaries != mMapbinaries.size()) + if (foundBinaries != mAliasesbinaries.size()) LOG(INFO) << "Not all expected binary-typed DPs found!"; } @@ -260,128 +258,90 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) // first we check if the DP is in the list for the detector if (type == DeliveryType::RAW_CHAR) { - auto el = mMapchars.find(dpid); - if (el == mMapchars.end()) { + auto it = std::find(mAliaseschars.begin(), mAliaseschars.end(), dpid); + if (it == mAliaseschars.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - auto elTime = mLatestTimestampchars.find(dpid); - if (elTime == mLatestTimestampchars.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - checkFlagsAndFill(dpcom, mLatestTimestampchars[dpid], mDpscharsmap); + int index = std::distance(mAliaseschars.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampchars[index], mDpscharsmap); processCharDP(dpid); } else if (type == DeliveryType::RAW_INT) { - std::vector<int64_t> tmp; - tmp.resize(100, 0); - auto el = mMapints.find(dpid); - if (el == mMapints.end()) { + auto it = std::find(mAliasesints.begin(), mAliasesints.end(), dpid); + if (it == mAliasesints.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - - auto elTime = mLatestTimestampints.find(dpid); - if (elTime == mLatestTimestampints.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - - checkFlagsAndFill(dpcom, (*elTime).second, mDpsintsmap); - //checkFlagsAndFill(dpcom, tmp[0], mDpsintsmap); - //checkFlagsAndFill(dpcom, mLatestTimestampints[dpid], mDpsintsmap); + int index = std::distance(mAliasesints.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampints[index], mDpsintsmap); processIntDP(dpid); } else if (type == DeliveryType::RAW_DOUBLE) { - auto el = mMapdoubles.find(dpid); - if (el == mMapdoubles.end()) { + auto it = std::find(mAliasesdoubles.begin(), mAliasesdoubles.end(), dpid); + if (it == mAliasesdoubles.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - auto elTime = mLatestTimestampdoubles.find(dpid); - if (elTime == mLatestTimestampdoubles.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - checkFlagsAndFill(dpcom, mLatestTimestampdoubles[dpid], mDpsdoublesmap); + int index = std::distance(mAliasesdoubles.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampdoubles[index], mDpsdoublesmap); processDoubleDP(dpid); } else if (type == DeliveryType::RAW_UINT) { - auto el = mMapUints.find(dpid); - if (el == mMapUints.end()) { + auto it = std::find(mAliasesUints.begin(), mAliasesUints.end(), dpid); + if (it == mAliasesUints.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - auto elTime = mLatestTimestampUints.find(dpid); - if (elTime == mLatestTimestampUints.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - checkFlagsAndFill(dpcom, mLatestTimestampUints[dpid], mDpsUintsmap); + int index = std::distance(mAliasesUints.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampUints[index], mDpsUintsmap); processUIntDP(dpid); } else if (type == DeliveryType::RAW_BOOL) { - auto el = mMapbools.find(dpid); - if (el == mMapbools.end()) { + auto it = std::find(mAliasesbools.begin(), mAliasesbools.end(), dpid); + if (it == mAliasesbools.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - auto elTime = mLatestTimestampbools.find(dpid); - if (elTime == mLatestTimestampbools.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - checkFlagsAndFill(dpcom, mLatestTimestampbools[dpid], mDpsboolsmap); + int index = std::distance(mAliasesbools.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampbools[index], mDpsboolsmap); processBoolDP(dpid); } else if (type == DeliveryType::RAW_STRING) { - auto el = mMapstrings.find(dpid); - if (el == mMapstrings.end()) { + auto it = std::find(mAliasesstrings.begin(), mAliasesstrings.end(), dpid); + if (it == mAliasesstrings.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - auto elTime = mLatestTimestampstrings.find(dpid); - if (elTime == mLatestTimestampstrings.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - checkFlagsAndFill(dpcom, mLatestTimestampstrings[dpid], mDpsstringsmap); + int index = std::distance(mAliasesstrings.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampstrings[index], mDpsstringsmap); processStringDP(dpid); } else if (type == DeliveryType::RAW_TIME) { - auto el = mMaptimes.find(dpid); - if (el == mMaptimes.end()) { + auto it = std::find(mAliasestimes.begin(), mAliasestimes.end(), dpid); + if (it == mAliasestimes.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - auto elTime = mLatestTimestamptimes.find(dpid); - if (elTime == mLatestTimestamptimes.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - checkFlagsAndFill(dpcom, mLatestTimestamptimes[dpid], mDpstimesmap); + int index = std::distance(mAliasestimes.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestamptimes[index], mDpstimesmap); processTimeDP(dpid); } else if (type == DeliveryType::RAW_BINARY) { - auto el = mMapbinaries.find(dpid); - if (el == mMapbinaries.end()) { + auto it = std::find(mAliasesbinaries.begin(), mAliasesbinaries.end(), dpid); + if (it == mAliasesbinaries.end()) { LOG(ERROR) << "DP not found for this detector, please check"; return 1; } - auto elTime = mLatestTimestampbinaries.find(dpid); - if (elTime == mLatestTimestampbinaries.end()) { - LOG(ERROR) << "Timestamp not found for this DP, please check"; - return 1; - } - checkFlagsAndFill(dpcom, mLatestTimestampbinaries[dpid], mDpsbinariesmap); + int index = std::distance(mAliasesbinaries.begin(), it); + checkFlagsAndFill(dpcom, mLatestTimestampbinaries[index], mDpsbinariesmap); processBinaryDP(dpid); } diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index 4a407361bdc9c..a0d99f2962c50 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -52,13 +52,13 @@ class DCSDataProcessor : public o2::framework::Task void init(o2::framework::InitContext& ic) final { - std::unordered_map<DPID, int> dpMap; + std::vector<DPID> aliasVect; DPID dpidtmp; DeliveryType typechar = RAW_CHAR; std::string dpAliaschar = "TestChar_0"; DPID::FILL(dpidtmp, dpAliaschar, typechar); - dpMap[dpidtmp] = 1; + aliasVect.push_back(dpidtmp); //std::vector<int> vectDet{kTest, kTPC}; // only one detector for now std::vector<int> vectDet{kTest}; @@ -68,7 +68,7 @@ class DCSDataProcessor : public o2::framework::Task for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasint, typeint); - dpMap[dpidtmp] = 1; + aliasVect.push_back(dpidtmp); mDetectorAlias[dpidtmp] = vectDet; } @@ -76,21 +76,21 @@ class DCSDataProcessor : public o2::framework::Task for (int i = 0; i < 4; i++) { std::string dpAliasdouble = "TestDouble_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasdouble, typedouble); - dpMap[dpidtmp] = 1; + aliasVect.push_back(dpidtmp); mDetectorAlias[dpidtmp] = vectDet; } DeliveryType typestring = RAW_STRING; std::string dpAliasstring0 = "TestString_0"; DPID::FILL(dpidtmp, dpAliasstring0, typestring); - dpMap[dpidtmp] = 1; + aliasVect.push_back(dpidtmp); mDetectorAlias[dpidtmp] = vectDet; - mDCSproc.init(dpMap); + mDCSproc.init(aliasVect); mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); mDCSproc.setName("Test0Det"); for (int idet = 0; idet < kNdetectors; idet++) { - mDCSprocVect[idet].init(dpMap); + mDCSprocVect[idet].init(aliasVect); mDCSprocVect[idet].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); mDCSprocVect[idet].setName("Test1Det"); } @@ -295,8 +295,8 @@ class DCSDataProcessor : public o2::framework::Task const auto& payload = mDCSproc.getCCDBSimpleMovingAverage(); auto& info = mDCSproc.getCCDBSimpleMovingAverageInfo(); auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); - LOG(DEBUG) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() - << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); From 26da3e941ade5ef8500faea3b4e609bfb59798b9 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Mon, 19 Oct 2020 15:40:01 +0200 Subject: [PATCH 1010/1751] Adding map to keep track of needed aliases, to be used in find. Stopping TStopwatches before starting measuring clang --- .../DCS/include/DetectorsDCS/DCSProcessor.h | 98 +++--- Detectors/DCS/src/DCSProcessor.cxx | 287 ++++++++---------- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 33 +- 3 files changed, 201 insertions(+), 217 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h index 8eaa6c8a6be03..8f19d1eeae923 100644 --- a/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h +++ b/Detectors/DCS/include/DetectorsDCS/DCSProcessor.h @@ -65,50 +65,50 @@ class DCSProcessor DCSProcessor() = default; ~DCSProcessor() = default; - void init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, - const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, - const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, - const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries); + void init(const std::vector<DPID>& pidschars, const std::vector<DPID>& pidsints, + const std::vector<DPID>& pidsdoubles, const std::vector<DPID>& pidsUints, + const std::vector<DPID>& pidsbools, const std::vector<DPID>& pidsstrings, + const std::vector<DPID>& pidstimes, const std::vector<DPID>& pidsbinaries); - void init(const std::vector<DPID>& aliases); + void init(const std::vector<DPID>& pids); int processMap(const std::unordered_map<DPID, DPVAL>& map, bool isDelta = false); int processDP(const std::pair<DPID, DPVAL>& dpcom); - std::unordered_map<DPID, DPVAL>::const_iterator findAndCheckAlias(const DPID& alias, DeliveryType type, - const std::unordered_map<DPID, DPVAL>& map); + std::unordered_map<DPID, DPVAL>::const_iterator findAndCheckPid(const DPID& pid, DeliveryType type, + const std::unordered_map<DPID, DPVAL>& map); template <typename T> int processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, - std::vector<int64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); + std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap); template <typename T> - void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, + void checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, uint64_t& latestTimeStamp, std::unordered_map<DPID, T>& destmap); - virtual void processCharDP(const DPID& alias); - virtual void processIntDP(const DPID& alias); - virtual void processDoubleDP(const DPID& alias); - virtual void processUIntDP(const DPID& alias); - virtual void processBoolDP(const DPID& alias); - virtual void processStringDP(const DPID& alias); - virtual void processTimeDP(const DPID& alias); - virtual void processBinaryDP(const DPID& alias); + virtual void processCharDP(const DPID& pid); + virtual void processIntDP(const DPID& pid); + virtual void processDoubleDP(const DPID& pid); + virtual void processUIntDP(const DPID& pid); + virtual void processBoolDP(const DPID& pid); + virtual void processStringDP(const DPID& pid); + virtual void processTimeDP(const DPID& pid); + virtual void processBinaryDP(const DPID& pid); - virtual uint64_t processFlag(uint64_t flag, const char* alias); + virtual uint64_t processFlag(uint64_t flag, const char* pid); template <typename T> void doSimpleMovingAverage(int nelements, std::deque<T>& vect, float& avg, bool& isSMA); - DQChars& getVectorForAliasChar(const DPID& id) { return mDpscharsmap[id]; } - DQInts& getVectorForAliasInt(const DPID& id) { return mDpsintsmap[id]; } - DQDoubles& getVectorForAliasDouble(const DPID& id) { return mDpsdoublesmap[id]; } - DQUInts& getVectorForAliasUInt(const DPID& id) { return mDpsUintsmap[id]; } - DQBools& getVectorForAliasBool(const DPID& id) { return mDpsboolsmap[id]; } - DQStrings& getVectorForAliasString(const DPID& id) { return mDpsstringsmap[id]; } - DQTimes& getVectorForAliasTime(const DPID& id) { return mDpstimesmap[id]; } - DQBinaries& getVectorForAliasBinary(const DPID& id) { return mDpsbinariesmap[id]; } + DQChars& getVectorForPidChar(const DPID& id) { return mDpscharsmap[id]; } + DQInts& getVectorForPidInt(const DPID& id) { return mDpsintsmap[id]; } + DQDoubles& getVectorForPidDouble(const DPID& id) { return mDpsdoublesmap[id]; } + DQUInts& getVectorForPidUInt(const DPID& id) { return mDpsUintsmap[id]; } + DQBools& getVectorForPidBool(const DPID& id) { return mDpsboolsmap[id]; } + DQStrings& getVectorForPidString(const DPID& id) { return mDpsstringsmap[id]; } + DQTimes& getVectorForPidTime(const DPID& id) { return mDpstimesmap[id]; } + DQBinaries& getVectorForPidBinary(const DPID& id) { return mDpsbinariesmap[id]; } void setNThreads(int n); int getNThreads() const { return mNThreads; } @@ -152,22 +152,24 @@ class DCSProcessor std::unordered_map<DPID, DQStrings> mDpsstringsmap; std::unordered_map<DPID, DQTimes> mDpstimesmap; std::unordered_map<DPID, DQBinaries> mDpsbinariesmap; - std::vector<DPID> mAliaseschars; - std::vector<DPID> mAliasesints; - std::vector<DPID> mAliasesdoubles; - std::vector<DPID> mAliasesUints; - std::vector<DPID> mAliasesbools; - std::vector<DPID> mAliasesstrings; - std::vector<DPID> mAliasestimes; - std::vector<DPID> mAliasesbinaries; - std::vector<int64_t> mLatestTimestampchars; - std::vector<int64_t> mLatestTimestampints; - std::vector<int64_t> mLatestTimestampdoubles; - std::vector<int64_t> mLatestTimestampUints; - std::vector<int64_t> mLatestTimestampbools; - std::vector<int64_t> mLatestTimestampstrings; - std::vector<int64_t> mLatestTimestamptimes; - std::vector<int64_t> mLatestTimestampbinaries; + std::vector<DPID> mPidschars; + std::vector<DPID> mPidsints; + std::vector<DPID> mPidsdoubles; + std::vector<DPID> mPidsUints; + std::vector<DPID> mPidsbools; + std::vector<DPID> mPidsstrings; + std::vector<DPID> mPidstimes; + std::vector<DPID> mPidsbinaries; + std::unordered_map<DPID, int> mPids; // contains all PIDs for the current processor; the value correspond to the index + // in the mPidschars/ints/doubles.. vectors + std::vector<uint64_t> mLatestTimestampchars; + std::vector<uint64_t> mLatestTimestampints; + std::vector<uint64_t> mLatestTimestampdoubles; + std::vector<uint64_t> mLatestTimestampUints; + std::vector<uint64_t> mLatestTimestampbools; + std::vector<uint64_t> mLatestTimestampstrings; + std::vector<uint64_t> mLatestTimestamptimes; + std::vector<uint64_t> mLatestTimestampbinaries; int mNThreads = 1; // number of threads std::unordered_map<std::string, float> mccdbSimpleMovingAverage; // unordered map in which to store the CCDB entry // for the DPs for which we calculated the simple @@ -197,7 +199,7 @@ using DPVAL = o2::dcs::DataPointValue; template <typename T> int DCSProcessor::processArrayType(const std::vector<DPID>& array, DeliveryType type, const std::unordered_map<DPID, DPVAL>& map, - std::vector<int64_t>& latestTimeStamp, + std::vector<uint64_t>& latestTimeStamp, std::unordered_map<DPID, std::deque<T>>& destmap) { @@ -209,7 +211,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, //#pragma omp parallel for schedule(dynamic) //#endif for (size_t i = 0; i != array.size(); ++i) { - auto it = findAndCheckAlias(array[i], type, map); + auto it = findAndCheckPid(array[i], type, map); if (it == map.end()) { if (!mIsDelta) { LOG(ERROR) << "Element " << array[i] << " not found " << std::endl; @@ -244,7 +246,7 @@ int DCSProcessor::processArrayType(const std::vector<DPID>& array, //______________________________________________________________________ template <typename T> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, uint64_t& latestTimeStamp, std::unordered_map<DPID, T>& destmap) { @@ -257,7 +259,7 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ auto etime = val.get_epoch_time(); // fill only if new value has a timestamp different from the timestamp of the previous one LOG(DEBUG) << "destmap[pid].size() = " << destmap[dpid].size(); - if (destmap[dpid].size() == 0 || etime != std::abs(latestTimeStamp)) { + if (destmap[dpid].size() == 0 || etime != latestTimeStamp) { LOG(DEBUG) << "adding new value"; destmap[dpid].push_back(val.payload_pt1); latestTimeStamp = etime; @@ -268,13 +270,13 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, uint64_t& latestTimeStamp, std::unordered_map<DPID, DCSProcessor::DQStrings>& destmap); //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, uint64_t& latestTimeStamp, std::unordered_map<DPID, DCSProcessor::DQBinaries>& destmap); //______________________________________________________________________ diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 1151a3b8d7d90..36756e3656d24 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -23,126 +23,142 @@ using DPVAL = o2::dcs::DataPointValue; //ClassImp(o2::dcs::DCSProcessor); -void DCSProcessor::init(const std::vector<DPID>& aliaseschars, const std::vector<DPID>& aliasesints, - const std::vector<DPID>& aliasesdoubles, const std::vector<DPID>& aliasesUints, - const std::vector<DPID>& aliasesbools, const std::vector<DPID>& aliasesstrings, - const std::vector<DPID>& aliasestimes, const std::vector<DPID>& aliasesbinaries) +void DCSProcessor::init(const std::vector<DPID>& pidschars, const std::vector<DPID>& pidsints, + const std::vector<DPID>& pidsdoubles, const std::vector<DPID>& pidsUints, + const std::vector<DPID>& pidsbools, const std::vector<DPID>& pidsstrings, + const std::vector<DPID>& pidstimes, const std::vector<DPID>& pidsbinaries) { - // init from separate vectors of aliases (one per data point type) + // init from separate vectors of pids (one per data point type) // chars - for (auto it = std::begin(aliaseschars); it != std::end(aliaseschars); ++it) { + for (auto it = std::begin(pidschars); it != std::end(pidschars); ++it) { if ((*it).get_type() != DeliveryType::RAW_CHAR) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a char"; } - mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + mPidschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + mPids[*it] = mPidschars.size() - 1; } // ints - for (auto it = std::begin(aliasesints); it != std::end(aliasesints); ++it) { + for (auto it = std::begin(pidsints); it != std::end(pidsints); ++it) { if ((*it).get_type() != DeliveryType::RAW_INT) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a int"; } - mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + mPidsints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + mPids[*it] = mPidsints.size() - 1; } // doubles - for (auto it = std::begin(aliasesdoubles); it != std::end(aliasesdoubles); ++it) { + for (auto it = std::begin(pidsdoubles); it != std::end(pidsdoubles); ++it) { if ((*it).get_type() != DeliveryType::RAW_DOUBLE) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a double"; } - mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + mPidsdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + mPids[*it] = mPidsdoubles.size() - 1; } // uints - for (auto it = std::begin(aliasesUints); it != std::end(aliasesUints); ++it) { + for (auto it = std::begin(pidsUints); it != std::end(pidsUints); ++it) { if ((*it).get_type() != DeliveryType::RAW_UINT) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a uint"; } - mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + mPidsUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + mPids[*it] = mPidsUints.size() - 1; } // bools - for (auto it = std::begin(aliasesbools); it != std::end(aliasesbools); ++it) { + for (auto it = std::begin(pidsbools); it != std::end(pidsbools); ++it) { if ((*it).get_type() != DeliveryType::RAW_BOOL) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a bool"; } - mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + mPidsbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + mPids[*it] = mPidsbools.size() - 1; } // strings - for (auto it = std::begin(aliasesstrings); it != std::end(aliasesstrings); ++it) { + for (auto it = std::begin(pidsstrings); it != std::end(pidsstrings); ++it) { if ((*it).get_type() != DeliveryType::RAW_STRING) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a string"; } - mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + mPidsstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + mPids[*it] = mPidsstrings.size() - 1; } // times - for (auto it = std::begin(aliasestimes); it != std::end(aliasestimes); ++it) { + for (auto it = std::begin(pidstimes); it != std::end(pidstimes); ++it) { if ((*it).get_type() != DeliveryType::RAW_TIME) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a time"; } - mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + mPidstimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + mPids[*it] = mPidstimes.size() - 1; } // binaries - for (auto it = std::begin(aliasesbinaries); it != std::end(aliasesbinaries); ++it) { + for (auto it = std::begin(pidsbinaries); it != std::end(pidsbinaries); ++it) { if ((*it).get_type() != DeliveryType::RAW_BINARY) { LOG(FATAL) << "Type for data point " << *it << " does not match with expectations! It should be a binary"; } - mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); - } - - mLatestTimestampchars.resize(aliaseschars.size(), 0); - mLatestTimestampints.resize(aliasesints.size(), 0); - mLatestTimestampdoubles.resize(aliasesdoubles.size(), 0); - mLatestTimestampUints.resize(aliasesUints.size(), 0); - mLatestTimestampbools.resize(aliasesbools.size(), 0); - mLatestTimestampstrings.resize(aliasesstrings.size(), 0); - mLatestTimestamptimes.resize(aliasestimes.size(), 0); - mLatestTimestampbinaries.resize(aliasesbinaries.size(), 0); + mPidsbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); + mPids[*it] = mPidsbinaries.size() - 1; + } + + mLatestTimestampchars.resize(pidschars.size(), 0); + mLatestTimestampints.resize(pidsints.size(), 0); + mLatestTimestampdoubles.resize(pidsdoubles.size(), 0); + mLatestTimestampUints.resize(pidsUints.size(), 0); + mLatestTimestampbools.resize(pidsbools.size(), 0); + mLatestTimestampstrings.resize(pidsstrings.size(), 0); + mLatestTimestamptimes.resize(pidstimes.size(), 0); + mLatestTimestampbinaries.resize(pidsbinaries.size(), 0); } //______________________________________________________________________ -void DCSProcessor::init(const std::vector<DPID>& aliases) +void DCSProcessor::init(const std::vector<DPID>& pids) { int nchars = 0, nints = 0, ndoubles = 0, nUints = 0, nbools = 0, nstrings = 0, ntimes = 0, nbinaries = 0; - for (auto it = std::begin(aliases); it != std::end(aliases); ++it) { + for (auto it = std::begin(pids); it != std::end(pids); ++it) { if ((*it).get_type() == DeliveryType::RAW_CHAR) { - mAliaseschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + mPidschars.emplace_back((*it).get_alias(), DeliveryType::RAW_CHAR); + mPids[*it] = nchars; nchars++; } if ((*it).get_type() == DeliveryType::RAW_INT) { - mAliasesints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + mPidsints.emplace_back((*it).get_alias(), DeliveryType::RAW_INT); + mPids[*it] = nints; nints++; } if ((*it).get_type() == DeliveryType::RAW_DOUBLE) { - mAliasesdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + mPidsdoubles.emplace_back((*it).get_alias(), DeliveryType::RAW_DOUBLE); + mPids[*it] = ndoubles; ndoubles++; } if ((*it).get_type() == DeliveryType::RAW_UINT) { - mAliasesUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + mPidsUints.emplace_back((*it).get_alias(), DeliveryType::RAW_UINT); + mPids[*it] = nUints; nUints++; } if ((*it).get_type() == DeliveryType::RAW_BOOL) { - mAliasesbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + mPidsbools.emplace_back((*it).get_alias(), DeliveryType::RAW_BOOL); + mPids[*it] = nbools; nbools++; } if ((*it).get_type() == DeliveryType::RAW_STRING) { - mAliasesstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + mPidsstrings.emplace_back((*it).get_alias(), DeliveryType::RAW_STRING); + mPids[*it] = nstrings; nstrings++; } if ((*it).get_type() == DeliveryType::RAW_TIME) { - mAliasestimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + mPidstimes.emplace_back((*it).get_alias(), DeliveryType::RAW_TIME); + mPids[*it] = ntimes; ntimes++; } if ((*it).get_type() == DeliveryType::RAW_BINARY) { - mAliasesbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); + mPidsbinaries.emplace_back((*it).get_alias(), DeliveryType::RAW_BINARY); + mPids[*it] = nbinaries; nbinaries++; } } @@ -187,48 +203,48 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is foundBools = 0, foundStrings = 0, foundTimes = 0, foundBinaries = 0; // char type - foundChars = processArrayType(mAliaseschars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); + foundChars = processArrayType(mPidschars, DeliveryType::RAW_CHAR, map, mLatestTimestampchars, mDpscharsmap); // int type - foundInts = processArrayType(mAliasesints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); + foundInts = processArrayType(mPidsints, DeliveryType::RAW_INT, map, mLatestTimestampints, mDpsintsmap); // double type - foundDoubles = processArrayType(mAliasesdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, + foundDoubles = processArrayType(mPidsdoubles, DeliveryType::RAW_DOUBLE, map, mLatestTimestampdoubles, mDpsdoublesmap); // UInt type - foundUInts = processArrayType(mAliasesUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); + foundUInts = processArrayType(mPidsUints, DeliveryType::RAW_UINT, map, mLatestTimestampUints, mDpsUintsmap); // Bool type - foundBools = processArrayType(mAliasesbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); + foundBools = processArrayType(mPidsbools, DeliveryType::RAW_BOOL, map, mLatestTimestampbools, mDpsboolsmap); // String type - foundStrings = processArrayType(mAliasesstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, + foundStrings = processArrayType(mPidsstrings, DeliveryType::RAW_STRING, map, mLatestTimestampstrings, mDpsstringsmap); // Time type - foundTimes = processArrayType(mAliasestimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); + foundTimes = processArrayType(mPidstimes, DeliveryType::RAW_TIME, map, mLatestTimestamptimes, mDpstimesmap); // Binary type - foundBinaries = processArrayType(mAliasesbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, + foundBinaries = processArrayType(mPidsbinaries, DeliveryType::RAW_BINARY, map, mLatestTimestampbinaries, mDpsbinariesmap); if (!isDelta) { - if (foundChars != mAliaseschars.size()) + if (foundChars != mPidschars.size()) LOG(INFO) << "Not all expected char-typed DPs found!"; - if (foundInts != mAliasesints.size()) + if (foundInts != mPidsints.size()) LOG(INFO) << "Not all expected int-typed DPs found!"; - if (foundDoubles != mAliasesdoubles.size()) + if (foundDoubles != mPidsdoubles.size()) LOG(INFO) << "Not all expected double-typed DPs found!"; - if (foundUInts != mAliasesUints.size()) + if (foundUInts != mPidsUints.size()) LOG(INFO) << "Not all expected uint-typed DPs found!"; - if (foundBools != mAliasesbools.size()) + if (foundBools != mPidsbools.size()) LOG(INFO) << "Not all expected bool-typed DPs found!"; - if (foundStrings != mAliasesstrings.size()) + if (foundStrings != mPidsstrings.size()) LOG(INFO) << "Not all expected string-typed DPs found!"; - if (foundTimes != mAliasestimes.size()) + if (foundTimes != mPidstimes.size()) LOG(INFO) << "Not all expected time-typed DPs found!"; - if (foundBinaries != mAliasesbinaries.size()) + if (foundBinaries != mPidsbinaries.size()) LOG(INFO) << "Not all expected binary-typed DPs found!"; } @@ -257,91 +273,50 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) DeliveryType type = dpid.get_type(); // first we check if the DP is in the list for the detector + auto el = mPids.find(dpid); + if (el == mPids.end()) { + LOG(ERROR) << "DP not found for this detector, please check"; + return 1; + } + int posInVector = (*el).second; + if (type == DeliveryType::RAW_CHAR) { - auto it = std::find(mAliaseschars.begin(), mAliaseschars.end(), dpid); - if (it == mAliaseschars.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliaseschars.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampchars[index], mDpscharsmap); + checkFlagsAndFill(dpcom, mLatestTimestampchars[posInVector], mDpscharsmap); processCharDP(dpid); } else if (type == DeliveryType::RAW_INT) { - auto it = std::find(mAliasesints.begin(), mAliasesints.end(), dpid); - if (it == mAliasesints.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliasesints.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampints[index], mDpsintsmap); + checkFlagsAndFill(dpcom, mLatestTimestampints[posInVector], mDpsintsmap); processIntDP(dpid); } else if (type == DeliveryType::RAW_DOUBLE) { - auto it = std::find(mAliasesdoubles.begin(), mAliasesdoubles.end(), dpid); - if (it == mAliasesdoubles.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliasesdoubles.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampdoubles[index], mDpsdoublesmap); + checkFlagsAndFill(dpcom, mLatestTimestampdoubles[posInVector], mDpsdoublesmap); processDoubleDP(dpid); } else if (type == DeliveryType::RAW_UINT) { - auto it = std::find(mAliasesUints.begin(), mAliasesUints.end(), dpid); - if (it == mAliasesUints.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliasesUints.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampUints[index], mDpsUintsmap); + checkFlagsAndFill(dpcom, mLatestTimestampUints[posInVector], mDpsUintsmap); processUIntDP(dpid); } else if (type == DeliveryType::RAW_BOOL) { - auto it = std::find(mAliasesbools.begin(), mAliasesbools.end(), dpid); - if (it == mAliasesbools.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliasesbools.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampbools[index], mDpsboolsmap); + checkFlagsAndFill(dpcom, mLatestTimestampbools[posInVector], mDpsboolsmap); processBoolDP(dpid); } else if (type == DeliveryType::RAW_STRING) { - auto it = std::find(mAliasesstrings.begin(), mAliasesstrings.end(), dpid); - if (it == mAliasesstrings.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliasesstrings.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampstrings[index], mDpsstringsmap); + checkFlagsAndFill(dpcom, mLatestTimestampstrings[posInVector], mDpsstringsmap); processStringDP(dpid); } else if (type == DeliveryType::RAW_TIME) { - auto it = std::find(mAliasestimes.begin(), mAliasestimes.end(), dpid); - if (it == mAliasestimes.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliasestimes.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestamptimes[index], mDpstimesmap); + checkFlagsAndFill(dpcom, mLatestTimestamptimes[posInVector], mDpstimesmap); processTimeDP(dpid); } else if (type == DeliveryType::RAW_BINARY) { - auto it = std::find(mAliasesbinaries.begin(), mAliasesbinaries.end(), dpid); - if (it == mAliasesbinaries.end()) { - LOG(ERROR) << "DP not found for this detector, please check"; - return 1; - } - int index = std::distance(mAliasesbinaries.begin(), it); - checkFlagsAndFill(dpcom, mLatestTimestampbinaries[index], mDpsbinariesmap); + checkFlagsAndFill(dpcom, mLatestTimestampbinaries[posInVector], mDpsbinariesmap); processBinaryDP(dpid); } @@ -351,7 +326,7 @@ int DCSProcessor::processDP(const std::pair<DPID, DPVAL>& dpcom) //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, uint64_t& latestTimeStamp, std::unordered_map<DPID, DQStrings>& destmap) { @@ -364,7 +339,7 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ auto etime = val.get_epoch_time(); // fill only if new value has a timestamp different from the timestamp of the previous one LOG(DEBUG) << "destmap[pid].size() = " << destmap[dpid].size(); - if (destmap[dpid].size() == 0 || etime != std::abs(latestTimeStamp)) { + if (destmap[dpid].size() == 0 || etime != latestTimeStamp) { auto& tmp = destmap[dpid].emplace_back(); std::strncpy(tmp.data(), (char*)&(val.payload_pt1), 56); latestTimeStamp = etime; @@ -375,7 +350,7 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ //______________________________________________________________________ template <> -void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_t& latestTimeStamp, +void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, uint64_t& latestTimeStamp, std::unordered_map<DPID, DQBinaries>& destmap) { @@ -388,7 +363,7 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ auto etime = val.get_epoch_time(); // fill only if new value has a timestamp different from the timestamp of the previous one LOG(DEBUG) << "destmap[pid].size() = " << destmap[dpid].size(); - if (destmap[dpid].size() == 0 || etime != std::abs(latestTimeStamp)) { + if (destmap[dpid].size() == 0 || etime != latestTimeStamp) { auto& tmp = destmap[dpid].emplace_back(); memcpy(tmp.data(), &(val.payload_pt1), 7); latestTimeStamp = etime; @@ -398,7 +373,7 @@ void DCSProcessor::checkFlagsAndFill(const std::pair<DPID, DPVAL>& dpcom, int64_ //______________________________________________________________________ -void DCSProcessor::processCharDP(const DPID& alias) +void DCSProcessor::processCharDP(const DPID& pid) { // empty for the example return; @@ -406,22 +381,22 @@ void DCSProcessor::processCharDP(const DPID& alias) //______________________________________________________________________ -void DCSProcessor::processIntDP(const DPID& alias) +void DCSProcessor::processIntDP(const DPID& pid) { - // processing the single alias of type int + // processing the single pid of type int bool isSMA = false; - doSimpleMovingAverage(2, mDpsintsmap[alias], mSimpleMovingAverage[alias], isSMA); - LOG(DEBUG) << "dpid = " << alias << " --> Moving average = " << mSimpleMovingAverage[alias]; + doSimpleMovingAverage(2, mDpsintsmap[pid], mSimpleMovingAverage[pid], isSMA); + LOG(DEBUG) << "dpid = " << pid << " --> Moving average = " << mSimpleMovingAverage[pid]; // create CCDB object //if (isSMA) { - mccdbSimpleMovingAverage[alias.get_alias()] = mSimpleMovingAverage[alias]; + mccdbSimpleMovingAverage[pid.get_alias()] = mSimpleMovingAverage[pid]; //} return; } //______________________________________________________________________ -void DCSProcessor::processDoubleDP(const DPID& alias) +void DCSProcessor::processDoubleDP(const DPID& pid) { // empty for the example return; @@ -429,7 +404,7 @@ void DCSProcessor::processDoubleDP(const DPID& alias) //______________________________________________________________________ -void DCSProcessor::processUIntDP(const DPID& alias) +void DCSProcessor::processUIntDP(const DPID& pid) { // empty for the example return; @@ -437,7 +412,7 @@ void DCSProcessor::processUIntDP(const DPID& alias) //______________________________________________________________________ -void DCSProcessor::processBoolDP(const DPID& alias) +void DCSProcessor::processBoolDP(const DPID& pid) { // empty for the example return; @@ -445,7 +420,7 @@ void DCSProcessor::processBoolDP(const DPID& alias) //______________________________________________________________________ -void DCSProcessor::processStringDP(const DPID& alias) +void DCSProcessor::processStringDP(const DPID& pid) { // empty for the example return; @@ -453,7 +428,7 @@ void DCSProcessor::processStringDP(const DPID& alias) //______________________________________________________________________ -void DCSProcessor::processTimeDP(const DPID& alias) +void DCSProcessor::processTimeDP(const DPID& pid) { // empty for the example return; @@ -461,7 +436,7 @@ void DCSProcessor::processTimeDP(const DPID& alias) //______________________________________________________________________ -void DCSProcessor::processBinaryDP(const DPID& alias) +void DCSProcessor::processBinaryDP(const DPID& pid) { // empty for the example return; @@ -469,20 +444,20 @@ void DCSProcessor::processBinaryDP(const DPID& alias) //______________________________________________________________________ -std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias(const DPID& alias, - DeliveryType type, - const std::unordered_map<DPID, DPVAL>& - map) +std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckPid(const DPID& pid, + DeliveryType type, + const std::unordered_map<DPID, DPVAL>& + map) { - // processing basic checks for map: all needed aliases must be present - // finds dp defined by "alias" in received map "map" + // processing basic checks for map: all needed pids must be present + // finds dp defined by "pid" in received map "map" - LOG(DEBUG) << "Processing " << alias; - auto it = map.find(alias); - DeliveryType tt = alias.get_type(); + LOG(DEBUG) << "Processing " << pid; + auto it = map.find(pid); + DeliveryType tt = pid.get_type(); if (tt != type) { - LOG(FATAL) << "Delivery Type of alias " << alias.get_alias() << " does not match definition in DCSProcessor (" + LOG(FATAL) << "Delivery Type of pid " << pid.get_alias() << " does not match definition in DCSProcessor (" << type << ")! Please fix"; } return it; @@ -490,59 +465,59 @@ std::unordered_map<DPID, DPVAL>::const_iterator DCSProcessor::findAndCheckAlias( //______________________________________________________________________ -uint64_t DCSProcessor::processFlag(const uint64_t flags, const char* alias) +uint64_t DCSProcessor::processFlag(const uint64_t flags, const char* pid) { // function to process the flag. the return code zero means that all is fine. // anything else means that there was an issue if (flags & DataPointValue::KEEP_ALIVE_FLAG) { - LOG(INFO) << "KEEP_ALIVE_FLAG active for DP " << alias; + LOG(INFO) << "KEEP_ALIVE_FLAG active for DP " << pid; } if (flags & DataPointValue::END_FLAG) { - LOG(INFO) << "END_FLAG active for DP " << alias; + LOG(INFO) << "END_FLAG active for DP " << pid; } if (flags & DataPointValue::FBI_FLAG) { - LOG(INFO) << "FBI_FLAG active for DP " << alias; + LOG(INFO) << "FBI_FLAG active for DP " << pid; } if (flags & DataPointValue::NEW_FLAG) { - LOG(INFO) << "NEW_FLAG active for DP " << alias; + LOG(INFO) << "NEW_FLAG active for DP " << pid; } if (flags & DataPointValue::DIRTY_FLAG) { - LOG(INFO) << "DIRTY_FLAG active for DP " << alias; + LOG(INFO) << "DIRTY_FLAG active for DP " << pid; } if (flags & DataPointValue::TURN_FLAG) { - LOG(INFO) << "TURN_FLAG active for DP " << alias; + LOG(INFO) << "TURN_FLAG active for DP " << pid; } if (flags & DataPointValue::WRITE_FLAG) { - LOG(INFO) << "WRITE_FLAG active for DP " << alias; + LOG(INFO) << "WRITE_FLAG active for DP " << pid; } if (flags & DataPointValue::READ_FLAG) { - LOG(INFO) << "READ_FLAG active for DP " << alias; + LOG(INFO) << "READ_FLAG active for DP " << pid; } if (flags & DataPointValue::OVERWRITE_FLAG) { - LOG(INFO) << "OVERWRITE_FLAG active for DP " << alias; + LOG(INFO) << "OVERWRITE_FLAG active for DP " << pid; } if (flags & DataPointValue::VICTIM_FLAG) { - LOG(INFO) << "VICTIM_FLAG active for DP " << alias; + LOG(INFO) << "VICTIM_FLAG active for DP " << pid; } if (flags & DataPointValue::DIM_ERROR_FLAG) { - LOG(INFO) << "DIM_ERROR_FLAG active for DP " << alias; + LOG(INFO) << "DIM_ERROR_FLAG active for DP " << pid; } if (flags & DataPointValue::BAD_DPID_FLAG) { - LOG(INFO) << "BAD_DPID_FLAG active for DP " << alias; + LOG(INFO) << "BAD_DPID_FLAG active for DP " << pid; } if (flags & DataPointValue::BAD_FLAGS_FLAG) { - LOG(INFO) << "BAD_FLAGS_FLAG active for DP " << alias; + LOG(INFO) << "BAD_FLAGS_FLAG active for DP " << pid; } if (flags & DataPointValue::BAD_TIMESTAMP_FLAG) { - LOG(INFO) << "BAD_TIMESTAMP_FLAG active for DP " << alias; + LOG(INFO) << "BAD_TIMESTAMP_FLAG active for DP " << pid; } if (flags & DataPointValue::BAD_PAYLOAD_FLAG) { - LOG(INFO) << "BAD_PAYLOAD_FLAG active for DP " << alias; + LOG(INFO) << "BAD_PAYLOAD_FLAG active for DP " << pid; } if (flags & DataPointValue::BAD_FBI_FLAG) { - LOG(INFO) << "BAD_FBI_FLAG active for DP " << alias; + LOG(INFO) << "BAD_FBI_FLAG active for DP " << pid; } return 0; diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index a0d99f2962c50..2f5569106e77c 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -52,45 +52,52 @@ class DCSDataProcessor : public o2::framework::Task void init(o2::framework::InitContext& ic) final { - std::vector<DPID> aliasVect; + + // stopping all stopwatches, since they start counting from the moment they are created + for (int idet = 0; idet < kNdetectors; idet++) { + mDeltaProcessingDetLoop[idet].Stop(); + mDeltaProcessingDetLoop[idet].Reset(); + } + + std::vector<DPID> pidVect; DPID dpidtmp; DeliveryType typechar = RAW_CHAR; std::string dpAliaschar = "TestChar_0"; DPID::FILL(dpidtmp, dpAliaschar, typechar); - aliasVect.push_back(dpidtmp); + pidVect.push_back(dpidtmp); //std::vector<int> vectDet{kTest, kTPC}; // only one detector for now std::vector<int> vectDet{kTest}; - mDetectorAlias[dpidtmp] = vectDet; + mDetectorPid[dpidtmp] = vectDet; DeliveryType typeint = RAW_INT; for (int i = 0; i < 50000; i++) { std::string dpAliasint = "TestInt_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasint, typeint); - aliasVect.push_back(dpidtmp); - mDetectorAlias[dpidtmp] = vectDet; + pidVect.push_back(dpidtmp); + mDetectorPid[dpidtmp] = vectDet; } DeliveryType typedouble = RAW_DOUBLE; for (int i = 0; i < 4; i++) { std::string dpAliasdouble = "TestDouble_" + std::to_string(i); DPID::FILL(dpidtmp, dpAliasdouble, typedouble); - aliasVect.push_back(dpidtmp); - mDetectorAlias[dpidtmp] = vectDet; + pidVect.push_back(dpidtmp); + mDetectorPid[dpidtmp] = vectDet; } DeliveryType typestring = RAW_STRING; std::string dpAliasstring0 = "TestString_0"; DPID::FILL(dpidtmp, dpAliasstring0, typestring); - aliasVect.push_back(dpidtmp); - mDetectorAlias[dpidtmp] = vectDet; + pidVect.push_back(dpidtmp); + mDetectorPid[dpidtmp] = vectDet; - mDCSproc.init(aliasVect); + mDCSproc.init(pidVect); mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); mDCSproc.setName("Test0Det"); for (int idet = 0; idet < kNdetectors; idet++) { - mDCSprocVect[idet].init(aliasVect); + mDCSprocVect[idet].init(pidVect); mDCSprocVect[idet].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); mDCSprocVect[idet].setName("Test1Det"); } @@ -190,7 +197,7 @@ class DCSDataProcessor : public o2::framework::Task LOG(DEBUG) << "TF: " << tfid << " --> starting (delta) processing in detector loop..."; for (const auto& dpcom : dcsmapDelta) { - std::vector<int> detVect = mDetectorAlias[dpcom.first]; + std::vector<int> detVect = mDetectorPid[dpcom.first]; for (int idet = 0; idet < detVect.size(); idet++) { mDeltaProcessingDetLoop[idet].Start(mResetStopwatchDeltaProcessingDetLoop); mDCSprocVect[idet].processDP(dpcom); @@ -266,7 +273,7 @@ class DCSDataProcessor : public o2::framework::Task } private: - std::unordered_map<DPID, std::vector<int>> mDetectorAlias; + std::unordered_map<DPID, std::vector<int>> mDetectorPid; std::array<DCSProcessor, kNdetectors> mDCSprocVect; o2::dcs::DCSProcessor mDCSproc; TStopwatch mReceiveBinaryData; From 7d78de8506dce9dfef3ea5c2f18cb424f4577d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Wed, 21 Oct 2020 08:36:19 +0200 Subject: [PATCH 1011/1751] Split track extension and selection (#4640) - Create directory for ALICE3 related studies - Add selection task for Run5 - Add method to check single cut - Add task to fill QA info for track cuts - Add header for standard cut object creation --- Analysis/Core/CMakeLists.txt | 1 + .../Core/include/Analysis/TrackSelection.h | 61 ++++++++++++++++ .../include/Analysis/TrackSelectionDefaults.h | 53 ++++++++++++++ Analysis/Core/src/TrackSelection.cxx | 4 +- Analysis/Tasks/ALICE3/CMakeLists.txt | 16 +++++ .../Tasks/ALICE3/alice3-trackselection.cxx | 56 +++++++++++++++ Analysis/Tasks/CMakeLists.txt | 6 ++ Analysis/Tasks/trackextension.cxx | 65 +++++++++++++++++ Analysis/Tasks/trackqa.cxx | 38 ++++++++-- Analysis/Tasks/trackselection.cxx | 72 +------------------ 10 files changed, 296 insertions(+), 76 deletions(-) create mode 100644 Analysis/Core/include/Analysis/TrackSelectionDefaults.h create mode 100644 Analysis/Tasks/ALICE3/CMakeLists.txt create mode 100644 Analysis/Tasks/ALICE3/alice3-trackselection.cxx create mode 100644 Analysis/Tasks/trackextension.cxx diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index 145b41d3ed9ce..d6dca70436d7e 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -23,6 +23,7 @@ o2_target_root_dictionary(AnalysisCore HEADERS include/Analysis/StepTHn.h include/Analysis/CorrelationContainer.h include/Analysis/TrackSelection.h + include/Analysis/TrackSelectionDefaults.h include/Analysis/VarManager.h include/Analysis/HistogramManager.h include/Analysis/AnalysisCut.h diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/Analysis/TrackSelection.h index d67702fcdbbb7..f4e6edf67c985 100644 --- a/Analysis/Core/include/Analysis/TrackSelection.h +++ b/Analysis/Core/include/Analysis/TrackSelection.h @@ -26,6 +26,27 @@ class TrackSelection public: TrackSelection() = default; + enum class TrackCuts : int { + kTrackType = 0, + kPtRange, + kEtaRange, + kTPCNCls, + kTPCCrossedRows, + kTPCCrossedRowsOverNCls, + kTPCChi2NDF, + kTPCRefit, + kITSNCls, + kITSChi2NDF, + kITSRefit, + kITSHits, + kGoldenChi2, + kDCAxy, + kDCAz, + kNCuts + }; + + static const std::string mCutNames[static_cast<int>(TrackCuts::kNCuts)]; + // Temporary function to check if track passes selection criteria. To be replaced by framework filters. template <typename T> bool IsSelected(T const& track) @@ -51,6 +72,46 @@ class TrackSelection } } + // Temporary function to check if track passes a given selection criteria. To be replaced by framework filters. + template <typename T> + bool IsSelected(T const& track, const TrackCuts& cut) + { + switch (cut) { + case TrackCuts::kTrackType: + return track.trackType() == mTrackType; + case TrackCuts::kPtRange: + return track.pt() >= mMinPt && track.pt() <= mMaxPt; + case TrackCuts::kEtaRange: + return track.eta() >= mMinEta && track.eta() <= mMaxEta; + case TrackCuts::kTPCNCls: + return track.tpcNClsFound() >= mMinNClustersTPC; + case TrackCuts::kTPCCrossedRows: + return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; + case TrackCuts::kTPCCrossedRowsOverNCls: + return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + case TrackCuts::kTPCChi2NDF: + return track.itsNCls() >= mMinNClustersITS; + case TrackCuts::kTPCRefit: + return track.itsChi2NCl() <= mMaxChi2PerClusterITS; + case TrackCuts::kITSNCls: + return track.tpcChi2NCl() <= mMaxChi2PerClusterTPC; + case TrackCuts::kITSChi2NDF: + return (mRequireITSRefit) ? (track.flags() & o2::aod::track::ITSrefit) : true; + case TrackCuts::kITSRefit: + return (mRequireTPCRefit) ? (track.flags() & o2::aod::track::TPCrefit) : true; + case TrackCuts::kITSHits: + return (mRequireGoldenChi2) ? (track.flags() & o2::aod::track::GoldenChi2) : true; + case TrackCuts::kGoldenChi2: + return FulfillsITSHitRequirements(track.itsClusterMap()); + case TrackCuts::kDCAxy: + return abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + case TrackCuts::kDCAz: + return abs(track.dcaZ()) <= mMaxDcaZ; + default: + return false; + } + } + void SetTrackType(o2::aod::track::TrackTypeEnum trackType) { mTrackType = trackType; } void SetPtRange(float minPt = 0.f, float maxPt = 1e10f) { diff --git a/Analysis/Core/include/Analysis/TrackSelectionDefaults.h b/Analysis/Core/include/Analysis/TrackSelectionDefaults.h new file mode 100644 index 0000000000000..bddbf5c560141 --- /dev/null +++ b/Analysis/Core/include/Analysis/TrackSelectionDefaults.h @@ -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. + +/// +/// \file TrackSelectionDefaults.h +/// \brief Class for the definition of standard track selection objects +/// \since 20-10-2020 +/// + +#ifndef TrackSelectionDefaults_H +#define TrackSelectionDefaults_H + +#include "Framework/DataTypes.h" + +// Default track selection requiring one hit in the SPD +TrackSelection getGlobalTrackSelection() +{ + TrackSelection selectedTracks; + selectedTracks.SetTrackType(o2::aod::track::Run2GlobalTrack); + selectedTracks.SetPtRange(0.1f, 1e10f); + selectedTracks.SetEtaRange(-0.8f, 0.8f); + selectedTracks.SetRequireITSRefit(true); + selectedTracks.SetRequireTPCRefit(true); + selectedTracks.SetRequireGoldenChi2(true); + selectedTracks.SetMinNCrossedRowsTPC(70); + selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); + selectedTracks.SetMaxChi2PerClusterTPC(4.f); + selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer + selectedTracks.SetMaxChi2PerClusterITS(36.f); + selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + selectedTracks.SetMaxDcaZ(2.f); + return selectedTracks; +} + +// Default track selection requiring no hit in the SPD and one in the innermost +// SDD -> complementary tracks to global selection +TrackSelection getGlobalTrackSelectionSDD() +{ + TrackSelection selectedTracks = getGlobalTrackSelection(); + selectedTracks.ResetITSRequirements(); + selectedTracks.SetRequireNoHitsInITSLayers({0, 1}); // no hit in SPD layers + selectedTracks.SetRequireHitsInITSLayers(1, {2}); // one hit in first SDD layer + return selectedTracks; +} + +#endif diff --git a/Analysis/Core/src/TrackSelection.cxx b/Analysis/Core/src/TrackSelection.cxx index 15773743f0eb7..5e7ff6fa41fd0 100644 --- a/Analysis/Core/src/TrackSelection.cxx +++ b/Analysis/Core/src/TrackSelection.cxx @@ -26,4 +26,6 @@ bool TrackSelection::FulfillsITSHitRequirements(uint8_t itsClusterMap) } } return true; -}; +} + +const std::string TrackSelection::mCutNames[static_cast<int>(TrackSelection::TrackCuts::kNCuts)] = {"TrackType", "PtRange", "EtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCRefit", "ITSNCls", "ITSChi2NDF", "ITSRefit", "ITSHits", "GoldenChi2", "DCAxy", "DCAz"}; diff --git a/Analysis/Tasks/ALICE3/CMakeLists.txt b/Analysis/Tasks/ALICE3/CMakeLists.txt new file mode 100644 index 0000000000000..7734d35e2289b --- /dev/null +++ b/Analysis/Tasks/ALICE3/CMakeLists.txt @@ -0,0 +1,16 @@ +# 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(alice3-trackselection + SOURCES alice3-trackselection.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + + diff --git a/Analysis/Tasks/ALICE3/alice3-trackselection.cxx b/Analysis/Tasks/ALICE3/alice3-trackselection.cxx new file mode 100644 index 0000000000000..53928e1e4523f --- /dev/null +++ b/Analysis/Tasks/ALICE3/alice3-trackselection.cxx @@ -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. + +// +// Task performing basic track selection. +// + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/trackUtilities.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +//**************************************************************************************** +/** + * Produce track filter table. + */ +//**************************************************************************************** +struct TrackSelectionTask { + Produces<aod::TrackSelection> filterTable; + + void init(InitContext&) + { + } + + void process(soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) + { + for (auto& track : tracks) { + filterTable(kTRUE, + kTRUE); + } + } +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask<TrackSelectionTask>("track-selection")}; + return workflow; +} diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 9f5ef647a7c46..e56c4c6476024 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -14,8 +14,14 @@ add_subdirectory(PWGHF) add_subdirectory(PWGJE) add_subdirectory(PWGLF) add_subdirectory(PWGUD) +add_subdirectory(ALICE3) +o2_add_dpl_workflow(trackextension + SOURCES trackextension.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(trackselection SOURCES trackselection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore diff --git a/Analysis/Tasks/trackextension.cxx b/Analysis/Tasks/trackextension.cxx new file mode 100644 index 0000000000000..1be057fff8e3b --- /dev/null +++ b/Analysis/Tasks/trackextension.cxx @@ -0,0 +1,65 @@ +// 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. + +// +// Task performing basic track selection. +// + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/trackUtilities.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +//**************************************************************************************** +/** + * Produce the more complicated derived track quantities needed for track selection. + * FIXME: we shall run this only if all other selections are passed to avoid + * FIXME: computing overhead and errors in calculations + */ +//**************************************************************************************** +struct TrackExtensionTask { + + Produces<aod::TracksExtended> extendedTrackQuantities; + + void process(aod::Collision const& collision, aod::FullTracks const& tracks) + { + for (auto& track : tracks) { + + std::array<float, 2> dca{1e10f, 1e10f}; + // FIXME: temporary solution to remove tracks that should not be there after conversion + if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && std::abs(track.x()) < 10.f) { + float magField = 5.0; // in kG (FIXME: get this from CCDB) + auto trackPar = getTrackPar(track); + trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, magField, &dca); + } + extendedTrackQuantities(dca[0], dca[1]); + + // TODO: add realtive pt resolution sigma(pt)/pt \approx pt * sigma(1/pt) + // TODO: add geometrical length / fiducial volume + } + } +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask<TrackExtensionTask>("track-extension")}; + return workflow; +} diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 438ec2399123c..a5241b677070b 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -14,12 +14,11 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Analysis/MC.h" #include "Framework/HistogramRegistry.h" - -#include <cmath> - +#include "Analysis/MC.h" #include "Analysis/TrackSelectionTables.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionDefaults.h" using namespace o2; using namespace o2::framework; @@ -28,7 +27,8 @@ using namespace o2::framework::expressions; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { std::vector<ConfigParamSpec> options{ - {"mc", VariantType::Bool, false, {"Add MC QA histograms."}}}; + {"mc", VariantType::Bool, false, {"Add MC QA histograms."}}, + {"add-cut-qa", VariantType::Int, 0, {"Add track cut QA histograms."}}}; std::swap(workflowOptions, options); } #include "Framework/runDataProcessing.h" @@ -144,6 +144,28 @@ struct TrackQATask { } }; +struct TrackCutQATask { + HistogramRegistry cuts{"Cuts", true, {}, OutputObjHandlingPolicy::QAObject}; + TrackSelection selectedTracks = getGlobalTrackSelection(); + static constexpr int ncuts = static_cast<int>(TrackSelection::TrackCuts::kNCuts); + void init(InitContext&) + { + cuts.add("single_cut", ";Cut;Tracks", kTH1D, {{ncuts, 0, ncuts}}); + for (int i = 0; i < ncuts; i++) { + cuts.get<TH1>("single_cut")->GetXaxis()->SetBinLabel(1 + i, TrackSelection::mCutNames[i].data()); + } + } + + void process(soa::Join<aod::FullTracks, aod::TracksExtended>::iterator const& track) + { + for (int i = 0; i < ncuts; i++) { + if (selectedTracks.IsSelected(track, static_cast<TrackSelection::TrackCuts>(i))) { + cuts.fill("single_cut", i); + } + } + } +}; + //**************************************************************************************** /** * QA task including MC truth info. @@ -169,10 +191,14 @@ struct TrackQATaskMC { //**************************************************************************************** WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - bool isMC = cfgc.options().get<bool>("mc"); + const bool isMC = cfgc.options().get<bool>("mc"); + const int add_cut_qa = cfgc.options().get<int>("add-cut-qa"); WorkflowSpec workflow; workflow.push_back(adaptAnalysisTask<TrackQATask>("track-qa-histograms")); + if (add_cut_qa) { + workflow.push_back(adaptAnalysisTask<TrackCutQATask>("track-cut-qa-histograms")); + } if (isMC) { workflow.push_back(adaptAnalysisTask<TrackQATaskMC>("track-qa-histograms-mc")); } diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index f2067e796d5fe..a8425576eaaff 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -14,80 +14,16 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include <TH1F.h> - -#include <cmath> - +#include "Framework/runDataProcessing.h" #include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionDefaults.h" #include "Analysis/TrackSelectionTables.h" -#include "Framework/runDataProcessing.h" #include "Analysis/trackUtilities.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// Default track selection requiring one hit in the SPD -TrackSelection getGlobalTrackSelection() -{ - TrackSelection selectedTracks; - selectedTracks.SetTrackType(aod::track::Run2GlobalTrack); - selectedTracks.SetPtRange(0.1f, 1e10f); - selectedTracks.SetEtaRange(-0.8f, 0.8f); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); - selectedTracks.SetRequireGoldenChi2(true); - selectedTracks.SetMinNCrossedRowsTPC(70); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); - selectedTracks.SetMaxChi2PerClusterTPC(4.f); - selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer - selectedTracks.SetMaxChi2PerClusterITS(36.f); - selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(2.f); - return selectedTracks; -} - -// Default track selection requiring no hit in the SPD and one in the innermost -// SDD -> complementary tracks to global selection -TrackSelection getGlobalTrackSelectionSDD() -{ - TrackSelection selectedTracks = getGlobalTrackSelection(); - selectedTracks.ResetITSRequirements(); - selectedTracks.SetRequireNoHitsInITSLayers({0, 1}); // no hit in SPD layers - selectedTracks.SetRequireHitsInITSLayers(1, {2}); // one hit in first SDD layer - return selectedTracks; -} - -//**************************************************************************************** -/** - * Produce the more complicated derived track quantities needed for track selection. - * FIXME: we shall run this only if all other selections are passed to avoid - * FIXME: computing overhead and errors in calculations - */ -//**************************************************************************************** -struct TrackExtensionTask { - - Produces<aod::TracksExtended> extendedTrackQuantities; - - void process(aod::Collision const& collision, aod::FullTracks const& tracks) - { - for (auto& track : tracks) { - - std::array<float, 2> dca{1e10f, 1e10f}; - // FIXME: temporary solution to remove tracks that should not be there after conversion - if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && std::abs(track.x()) < 10.f) { - float magField = 5.0; // in kG (FIXME: get this from CCDB) - auto trackPar = getTrackPar(track); - trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, magField, &dca); - } - extendedTrackQuantities(dca[0], dca[1]); - - // TODO: add realtive pt resolution sigma(pt)/pt \approx pt * sigma(1/pt) - // TODO: add geometrical length / fiducial volume - } - } -}; - //**************************************************************************************** /** * Produce track filter table. @@ -121,8 +57,6 @@ struct TrackSelectionTask { //**************************************************************************************** WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{ - adaptAnalysisTask<TrackExtensionTask>("track-extension"), - adaptAnalysisTask<TrackSelectionTask>("track-selection")}; + WorkflowSpec workflow{adaptAnalysisTask<TrackSelectionTask>("track-selection")}; return workflow; } From 745f533ddee3021968912aa0e72a688c4e604ef8 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Wed, 21 Oct 2020 08:36:35 +0200 Subject: [PATCH 1012/1751] examples for efficiency histograms (#4644) --- Analysis/Tutorials/CMakeLists.txt | 10 +++ Analysis/Tutorials/src/efficiencyGlobal.cxx | 67 +++++++++++++++++++ Analysis/Tutorials/src/efficiencyPerRun.cxx | 71 +++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 Analysis/Tutorials/src/efficiencyGlobal.cxx create mode 100644 Analysis/Tutorials/src/efficiencyPerRun.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index c10c44a391a04..d5689d3068466 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -157,3 +157,13 @@ o2_add_dpl_workflow(schema-evolution SOURCES src/schemaEvolution.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(efficiency-per-run + SOURCES src/efficiencyPerRun.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(efficiency-global + SOURCES src/efficiencyGlobal.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/efficiencyGlobal.cxx b/Analysis/Tutorials/src/efficiencyGlobal.cxx new file mode 100644 index 0000000000000..f2a02d04b25e0 --- /dev/null +++ b/Analysis/Tutorials/src/efficiencyGlobal.cxx @@ -0,0 +1,67 @@ +// 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. + +/// +/// \brief This example demonstrates how the CCDB can be used to store an efficiency object which is valid for a full train run +/// The objects are uploaded with +/// o2-ccdb-upload -p Users/jgrosseo/efficiency/simple -f eff.root -k efficiency --starttimestamp 1 --endtimestamp 16032093350000 +/// A sufficiently large time stamp interval should be given to span all runs under consideration +/// NOTE If an efficiency object per run is needed, please check the example efficiencyPerRun.cxx +/// + +#include <chrono> + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include <CCDB/BasicCCDBManager.h> + +using namespace o2::framework; +using namespace o2; + +struct EfficiencyGlobal { + Service<ccdb::BasicCCDBManager> ccdb; + Configurable<std::string> path{"ccdb-path", "Users/jgrosseo/efficiency/simple", "base path to the ccdb object"}; + Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable<long> nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + + OutputObj<TH1F> pt{TH1F("pt", "pt", 20, 0., 10.)}; + + TH1F* efficiency = nullptr; + + void init(InitContext&) + { + ccdb->setURL(url.value); + // Enabling object caching, otherwise each call goes to the CCDB server + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now, will be replaced by the value of the train creation + // This avoids that users can replace objects **while** a train is running + ccdb->setCreatedNotAfter(nolaterthan.value); + LOGF(info, "Getting object %s", path.value.data()); + efficiency = ccdb->getForTimeStamp<TH1F>(path.value, nolaterthan.value); + if (!efficiency) { + LOGF(fatal, "Efficiency object not found!"); + } + } + + void process(aod::Collision const& collision, aod::Tracks const& tracks) + { + for (auto& track : tracks) { + pt->Fill(track.pt(), efficiency->GetBinContent(efficiency->FindBin(track.pt()))); + //LOGF(info, "Efficiency %f for pt %f", efficiency->GetBinContent(efficiency->FindBin(track.pt())), track.pt()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{adaptAnalysisTask<EfficiencyGlobal>("EfficiencyGlobal")}; +} diff --git a/Analysis/Tutorials/src/efficiencyPerRun.cxx b/Analysis/Tutorials/src/efficiencyPerRun.cxx new file mode 100644 index 0000000000000..2c8abeefc35e5 --- /dev/null +++ b/Analysis/Tutorials/src/efficiencyPerRun.cxx @@ -0,0 +1,71 @@ +// 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. + +/// +/// \brief A tutorial task to retrieve objects from CCDB given a run number. +/// This example demonstrates how the CCDB can be used to store an efficiency object which is valid only for a specific time +/// interval (e.g. for a run) +/// The objects are uploaded with +/// o2-ccdb-upload -p Users/jgrosseo/efficiency/simple -f eff.root -k efficiency --starttimestamp 1 --endtimestamp 16032093350000 +/// Different timestamps intervals can be given. +/// You need to run this with the o2-analysis-timestamps example +/// NOTE If only one efficiency object for all runs is needed, this code is not optimal. In this case please check the example: +/// efficiencyGlobal.cxx +/// + +#include <chrono> + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include <CCDB/BasicCCDBManager.h> + +using namespace o2::framework; +using namespace o2; + +struct EfficiencyPerRun { + Service<ccdb::BasicCCDBManager> ccdb; + Configurable<std::string> path{"ccdb-path", "Users/jgrosseo/efficiency/simple", "base path to the ccdb object"}; + Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable<long> nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + + OutputObj<TH1F> pt{TH1F("pt", "pt", 20, 0., 10.)}; + + void init(InitContext&) + { + ccdb->setURL(url.value); + // Enabling object caching, otherwise each call goes to the CCDB server + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now, will be replaced by the value of the train creation + // This avoids that users can replace objects **while** a train is running + ccdb->setCreatedNotAfter(nolaterthan.value); + } + + void process(aod::Collision const& collision, aod::BCsWithTimestamps const&, aod::Tracks const& tracks) + { + auto bc = collision.bc_as<aod::BCsWithTimestamps>(); + LOGF(info, "Getting object %s for run number %i from timestamp=%llu", path.value.data(), bc.runNumber(), bc.timestamp()); + auto efficiency = ccdb->getForTimeStamp<TH1F>(path.value, bc.timestamp()); + if (!efficiency) { + LOGF(fatal, "Efficiency object not found!"); + } + + for (auto& track : tracks) { + pt->Fill(track.pt(), efficiency->GetBinContent(efficiency->FindBin(track.pt()))); + //LOGF(info, "Efficiency %f for pt %f", efficiency->GetBinContent(efficiency->FindBin(track.pt())), track.pt()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{adaptAnalysisTask<EfficiencyPerRun>("EfficiencyPerRun")}; +} From 0e67aed0c39617e286977258f1682781c7d54077 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 21 Oct 2020 08:38:01 +0200 Subject: [PATCH 1013/1751] HistogramRegistry: allow for grouping of histograms in output file (#4646) * HistogramRegistry: allow for grouping of histograms in output file - move from TFolders to TLists since TFolder is 'non-mergable' - allow sub-grouping of output - TODO: turn lists into directories in file sink * include deque --- Analysis/Tutorials/src/histogramRegistry.cxx | 21 +++--- .../include/Framework/HistogramRegistry.h | 66 +++++++++++++++---- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index f7f2d92d37657..c178e0ad3f084 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -144,19 +144,20 @@ struct DTask { HistogramConfigSpec defaultParticleHist({HistType::kTHnF, {ptAxis, etaAxis, centAxis, cutAxis}}); - spectra.add({"myControlHist", "a", {HistType::kTH2F, {ptAxis, etaAxis}}}); + spectra.add("myControlHist", "a", kTH2F, {ptAxis, etaAxis}); spectra.get<TH2>("myControlHist")->GetYaxis()->SetTitle("my-y-axis"); spectra.get<TH2>("myControlHist")->SetTitle("something meaningful"); - spectra.add({"pions", "Pions", defaultParticleHist}); - spectra.add({"kaons", "Kaons", defaultParticleHist}); - spectra.add({"sigmas", "Sigmas", defaultParticleHist}); - spectra.add({"lambdas", "Lambd", defaultParticleHist}); + spectra.add("charged/pions", "Pions", defaultParticleHist); + spectra.add("neutral/pions", "Pions", defaultParticleHist); + spectra.add("one/two/three/four/kaons", "Kaons", defaultParticleHist); + spectra.add("sigmas", "Sigmas", defaultParticleHist); + spectra.add("lambdas", "Lambd", defaultParticleHist); spectra.get<THn>("lambdas")->SetTitle("Lambdas"); - etaStudy.add({"positive", "A side spectra", {HistType::kTH1I, {ptAxis}}}); - etaStudy.add({"negative", "C side spectra", {HistType::kTH1I, {ptAxis}}}); + etaStudy.add("positive", "A side spectra", kTH1I, {ptAxis}); + etaStudy.add("negative", "C side spectra", kTH1I, {ptAxis}); } void process(aod::Tracks const& tracks) @@ -168,8 +169,10 @@ struct DTask { for (auto& track : tracks) { spectra.fill("myControlHist", track.pt(), track.eta()); - spectra.fill("pions", track.pt(), track.eta(), 50., 0.); - spectra.fill("kaons", track.pt(), track.eta(), 50., 0.); + spectra.fill("charged/pions", track.pt(), track.eta(), 50., 0.); + spectra.fill("charged/pions", track.pt(), track.eta(), 50., 0.); + spectra.fill("neutral/pions", track.pt(), track.eta(), 50., 0.); + spectra.fill("one/two/three/four/kaons", track.pt(), track.eta(), 50., 0.); spectra.fill("sigmas", track.pt(), track.eta(), 50., 0.); spectra.fill("lambdas", track.pt(), track.eta(), 50., 0.); } diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 24f466e7e2d04..8d4e3552b8d9b 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -30,13 +30,11 @@ #include <TProfile.h> #include <TProfile2D.h> #include <TProfile3D.h> - -#include <TFolder.h> -//#include <TObjArray.h> -//#include <TList.h> +#include <TList.h> #include <string> #include <variant> +#include <deque> namespace o2::framework { @@ -472,19 +470,28 @@ class HistogramRegistry taskHash = hash; } - // TODO: maybe support also TDirectory,TList,TObjArray?, find a way to write to file in 'single key' mode (arg in WriteObjAny) - TFolder* operator*() + TList* operator*() { - TFolder* folder = new TFolder(this->name.c_str(), this->name.c_str()); + TList* list = new TList(); + list->SetName(this->name.data()); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { - TObject* rawPtr = nullptr; - std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[j]); + TNamed* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[j]); if (rawPtr) { - folder->Add(rawPtr); + std::deque<std::string> path = splitPath(rawPtr->GetName()); + std::string name = path.back(); + path.pop_back(); + TList* targetList{getSubList(list, path)}; + if (targetList) { + rawPtr->SetName(name.data()); + targetList->Add(rawPtr); + } else { + LOGF(FATAL, "Specified subfolder could not be created."); + } } } - folder->SetOwner(false); // object deletion will be handled by shared_ptrs - return folder; + list->SetOwner(false); // object deletion will be handled by shared_ptrs + return list; } // fill hist with values @@ -547,6 +554,7 @@ class HistogramRegistry mutable uint32_t lookup = 0; private: + // create histogram from specification and insert it into the registry void insert(const HistogramSpec& histSpec) { uint32_t i = imask(histSpec.id); @@ -568,6 +576,40 @@ class HistogramRegistry return i & mask; } + // helper function to create resp. find the subList defined by path + TList* getSubList(TList* list, std::deque<std::string> path) + { + if (path.empty()) + return list; + TList* targetList{nullptr}; + std::string nextList = path[0]; + path.pop_front(); + if (auto subList = (TList*)list->FindObject(nextList.data())) { + if (subList->InheritsFrom(TList::Class())) + targetList = getSubList((TList*)subList, path); + else + return nullptr; + } else { + subList = new TList(); + subList->SetName(nextList.data()); + list->Add(subList); + targetList = getSubList(subList, path); + } + return targetList; + } + + // helper function to split user defined path/to/hist/name string + std::deque<std::string> splitPath(std::string pathAndNameUser) + { + std::istringstream pathAndNameStream(pathAndNameUser); + std::deque<std::string> pathAndName; + std::string curDir; + while (std::getline(pathAndNameStream, curDir, '/')) { + pathAndName.push_back(curDir); + } + return pathAndName; + } + std::string name{}; bool enabled{}; OutputObjHandlingPolicy policy{}; From b66b5e4f22c88ba4f3d55ca723a97c750d110df1 Mon Sep 17 00:00:00 2001 From: Javier Castillo Castellanos <javier.castillo.castellanos@cern.ch> Date: Wed, 14 Oct 2020 17:41:51 +0200 Subject: [PATCH 1014/1751] Fix position of wrings --- Detectors/Passive/src/Shil.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/Passive/src/Shil.cxx b/Detectors/Passive/src/Shil.cxx index d1bd18505cc28..16883dce6f336 100644 --- a/Detectors/Passive/src/Shil.cxx +++ b/Detectors/Passive/src/Shil.cxx @@ -800,10 +800,10 @@ void Shil::ConstructGeometry() dz += saa1Wring2HWidth; dz += saa1DWrings; dz += saa1Wring3HWidth; - asSaa1ExtraShield->AddNode(voSaa1Wring3, 1, new TGeoCombiTrans(0., 0., dz - 0.15, rot090)); - asSaa1ExtraShield->AddNode(voSaa1Wring3, 2, new TGeoCombiTrans(0., 0., dz - 0.15, rot270)); + asSaa1ExtraShield->AddNode(voSaa1Wring3, 1, new TGeoCombiTrans(0., 0., dz, rot090)); + asSaa1ExtraShield->AddNode(voSaa1Wring3, 2, new TGeoCombiTrans(0., 0., dz, rot270)); dz += saa1Wring3HWidth; - asSaa1ExtraShield->AddNode(voSaa1Wring4, 1, new TGeoTranslation(0., 0., dz - 6.)); + asSaa1ExtraShield->AddNode(voSaa1Wring4, 1, new TGeoTranslation(0., 0., dz)); dz += saa1Wring4Width; const Float_t saa1ExtraShieldL = 48; // From 35cf3d8f600a10803be43252536ba2086327e02d Mon Sep 17 00:00:00 2001 From: Javier Castillo Castellanos <javier.castillo.castellanos@cern.ch> Date: Wed, 14 Oct 2020 17:43:04 +0200 Subject: [PATCH 1015/1751] Correct positioning of quadrants in station1 --- Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx b/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx index b067c15772541..426df458f1134 100644 --- a/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx @@ -107,8 +107,8 @@ const float kDeltaQuadLHC = 2.6; // LHC Origin wrt Quadrant Origin const float kFrameOffset = 5.2; // pad plane offsets -const float kPadXOffsetBP = 0.50 - 0.63 / 2; // = 0.185 -const float kPadYOffsetBP = 0.31 + 0.42 / 2; // = 0.52 +const float kPadXOffsetBP = 0.50 - 0.63 / 2; // = 0.185 +const float kPadYOffsetBP = -0.31 - 0.42 / 2; // = -0.52 const int kFoamBoxNameOffset = 200; const int kFR4BoxNameOffset = 400; const int kDaughterCopyNoOffset = 1000; @@ -1539,8 +1539,8 @@ void createStation1Geometry(TGeoVolume& topVolume) std::array<TGeoRotation*, kNQuadrants> rot = {rot0, rot1, rot2, rot3}; // initialize the quadrant positions - float x[kNQuadrants] = {-1, 1, 1, -1}; - float y[kNQuadrants] = {-1, -1, 1, 1}; + float x[kNQuadrants] = {1, -1, -1, 1}; + float y[kNQuadrants] = {1, 1, -1, -1}; for (int i = 0; i < kNQuadrants; i++) { x[i] *= kPadXOffsetBP; @@ -1568,7 +1568,7 @@ void createStation1Geometry(TGeoVolume& topVolume) // compute the detection element ID detElemID = 100 * ich + i; - if (x[i] < 0) { + if (x[i] > 0) { in->AddNode(quadrant, detElemID, new TGeoCombiTrans(x[i], y[i], z, rot[i])); } else out->AddNode(quadrant, detElemID, new TGeoCombiTrans(x[i], y[i], z, rot[i])); From c6646a4159ed2cbd166d397188ca9e084ec84eee Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 15 Oct 2020 12:33:29 +0200 Subject: [PATCH 1016/1751] fix tracklet column --- Detectors/TRD/simulation/src/TrapSimulator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 11ade2970fbcb..dad19d150b310 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -2064,7 +2064,7 @@ void TrapSimulator::fitTracklet() uint32_t format = 0; uint32_t hcid = mDetector * 2 + mRobPos % 2; uint32_t padrow = ((mRobPos >> 1) << 2) | (mMcmPos >> 2); - uint32_t col = 0; + uint32_t col = mFeeParam->getPadColFromADC(mRobPos, mMcmPos, 1); uint32_t position = rawoffset; //uint32_t s mTrackletArray64.emplace_back(format, hcid, padrow, col, position, slope, q2, q1, q0); From a7f1065ac8b405a01f9b8f3ca67388130c854147 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Sat, 10 Oct 2020 04:39:53 +0300 Subject: [PATCH 1017/1751] EMCAL: add braces to single statements --- .../EMCAL/base/include/EMCALBase/Geometry.h | 17 +- .../include/EMCALBase/ShishKebabTrd1Module.h | 16 +- Detectors/EMCAL/base/src/ClusterFactory.cxx | 99 ++++--- Detectors/EMCAL/base/src/Geometry.cxx | 278 +++++++++++------- Detectors/EMCAL/base/src/Hit.cxx | 3 +- Detectors/EMCAL/base/src/Mapper.cxx | 18 +- Detectors/EMCAL/base/src/RCUTrailer.cxx | 15 +- .../EMCAL/base/src/ShishKebabTrd1Module.cxx | 9 +- Detectors/EMCAL/base/test/testMapper.cxx | 3 +- Detectors/EMCAL/calib/src/BadChannelMap.cxx | 35 ++- Detectors/EMCAL/calib/src/CalibDB.cxx | 63 ++-- .../calib/src/GainCalibrationFactors.cxx | 3 +- .../EMCAL/calib/src/TempCalibParamSM.cxx | 3 +- .../EMCAL/calib/src/TempCalibrationParams.cxx | 6 +- .../EMCAL/calib/src/TimeCalibParamL1Phase.cxx | 3 +- .../EMCAL/calib/src/TimeCalibrationParams.cxx | 16 +- Detectors/EMCAL/calib/src/TriggerDCS.cxx | 3 +- .../calib/src/TriggerSTUErrorCounter.cxx | 6 +- .../EMCAL/calib/test/testBadChannelMap.cxx | 30 +- .../EMCAL/calib/test/testGainCalibration.cxx | 12 +- .../EMCAL/calib/test/testTempCalibration.cxx | 9 +- .../calib/test/testTempCalibrationSM.cxx | 12 +- .../EMCAL/calib/test/testTimeCalibration.cxx | 27 +- .../EMCAL/calib/test/testTimeL1PhaseCalib.cxx | 12 +- Detectors/EMCAL/calib/test/testTriggerDCS.cxx | 3 +- .../EMCAL/calib/test/testTriggerSTUDCS.cxx | 3 +- .../EMCAL/calib/test/testTriggerTRUDCS.cxx | 3 +- .../reconstruction/run/rawReaderFile.cxx | 3 +- .../EMCAL/reconstruction/src/AltroDecoder.cxx | 6 +- Detectors/EMCAL/reconstruction/src/Bunch.cxx | 3 +- .../reconstruction/src/CaloRawFitter.cxx | 9 +- .../src/CaloRawFitterGamma2.cxx | 15 +- .../src/CaloRawFitterStandard.cxx | 11 +- .../EMCAL/reconstruction/src/Channel.cxx | 12 +- .../EMCAL/reconstruction/src/RawBuffer.cxx | 6 +- .../EMCAL/reconstruction/src/RawPayload.cxx | 6 +- .../reconstruction/src/RawReaderMemory.cxx | 21 +- Detectors/EMCAL/simulation/src/Detector.cxx | 15 +- Detectors/EMCAL/simulation/src/Digitizer.cxx | 12 +- .../EMCAL/simulation/src/DigitizerTask.cxx | 6 +- Detectors/EMCAL/simulation/src/RawWriter.cxx | 32 +- .../EMCAL/workflow/src/CellConverterSpec.cxx | 9 +- .../EMCAL/workflow/src/DigitsPrinterSpec.cxx | 6 +- .../workflow/src/RawToCellConverterSpec.cxx | 12 +- 44 files changed, 567 insertions(+), 324 deletions(-) diff --git a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h index 9e21cc9422265..74324f6b0f366 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h @@ -239,8 +239,9 @@ class Geometry // EMCALSMType GetSMType(Int_t nSupMod) const { - if (nSupMod >= mNumberOfSuperModules) + if (nSupMod >= mNumberOfSuperModules) { throw SupermoduleIndexException(nSupMod, mNumberOfSuperModules); + } return mEMCSMSystem[nSupMod]; } @@ -455,14 +456,15 @@ class Geometry Int_t GetSuperModuleNumber(Int_t absId) const; Int_t GetNumberOfModuleInPhiDirection(Int_t nSupMod) const { - if (GetSMType(nSupMod) == EMCAL_HALF) + if (GetSMType(nSupMod) == EMCAL_HALF) { return mNPhi / 2; - else if (GetSMType(nSupMod) == EMCAL_THIRD) + } else if (GetSMType(nSupMod) == EMCAL_THIRD) { return mNPhi / 3; - else if (GetSMType(nSupMod) == DCAL_EXT) + } else if (GetSMType(nSupMod) == DCAL_EXT) { return mNPhi / 3; - else + } else { return mNPhi; + } } /// \brief Transition from cell indexes (iphi, ieta) to module indexes (iphim, ietam, nModule) @@ -677,10 +679,11 @@ class Geometry inline Bool_t Geometry::CheckAbsCellId(Int_t absId) const { - if (absId < 0 || absId >= mNCells) + if (absId < 0 || absId >= mNCells) { return kFALSE; - else + } else { return kTRUE; + } } } // namespace emcal } // namespace o2 diff --git a/Detectors/EMCAL/base/include/EMCALBase/ShishKebabTrd1Module.h b/Detectors/EMCAL/base/include/EMCALBase/ShishKebabTrd1Module.h index 4b9162665d92f..4e92dfda6e345 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/ShishKebabTrd1Module.h +++ b/Detectors/EMCAL/base/include/EMCALBase/ShishKebabTrd1Module.h @@ -88,10 +88,11 @@ class ShishKebabTrd1Module // ieta=0 or 1 - Jun 02, 2006 const TVector2& GetCenterOfCellInLocalCoordinateofSM(Int_t ieta) const { - if (ieta <= 0) + if (ieta <= 0) { return mOK2; - else + } else { return mOK1; + } } void GetCenterOfCellInLocalCoordinateofSM(Int_t ieta, Double_t& xr, Double_t& zr) const @@ -109,10 +110,12 @@ class ShishKebabTrd1Module void GetCenterOfCellInLocalCoordinateofSM3X3(Int_t ieta, Double_t& xr, Double_t& zr) const { // 3X3 case - Nov 9,2006 - if (ieta < 0) + if (ieta < 0) { ieta = 0; // ieta = ieta<0? ieta=0 : ieta; // check index - if (ieta > 2) + } + if (ieta > 2) { ieta = 2; // ieta = ieta>2? ieta=2 : ieta; + } xr = mOK3X3[2 - ieta].Y(); zr = mOK3X3[2 - ieta].X(); } @@ -127,10 +130,11 @@ class ShishKebabTrd1Module const TVector2& GetCenterOfModuleFace() const { return mOB; } const TVector2& GetCenterOfModuleFace(Int_t ieta) const { - if (ieta <= 0) + if (ieta <= 0) { return mOB2; - else + } else { return mOB1; + } } // Jul 30, 2007 diff --git a/Detectors/EMCAL/base/src/ClusterFactory.cxx b/Detectors/EMCAL/base/src/ClusterFactory.cxx index 2ab67b1e0b783..54b7942cbde67 100644 --- a/Detectors/EMCAL/base/src/ClusterFactory.cxx +++ b/Detectors/EMCAL/base/src/ClusterFactory.cxx @@ -46,8 +46,9 @@ void ClusterFactory<InputType>::reset() template <class InputType> o2::emcal::AnalysisCluster ClusterFactory<InputType>::buildCluster(int clusterIndex) const { - if (clusterIndex >= mClustersContainer.size()) + if (clusterIndex >= mClustersContainer.size()) { throw ClusterRangeException(clusterIndex, mClustersContainer.size()); + } o2::emcal::AnalysisCluster clusterAnalysis; clusterAnalysis.setID(clusterIndex); @@ -124,8 +125,9 @@ void ClusterFactory<InputType>::evalDispersion(gsl::span<const int> inputsIndice // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2 // C Side impair SM, nSupMod%2=1; A side pair SM nSupMod%2=0 - if (mSharedCluster && nSupMod % 2) + if (mSharedCluster && nSupMod % 2) { ieta += EMCAL_COLS; + } double etai = (double)ieta; double phii = (double)iphi; @@ -142,8 +144,9 @@ void ClusterFactory<InputType>::evalDispersion(gsl::span<const int> inputsIndice if (wtot > 0) { phiMean /= wtot; etaMean /= wtot; - } else + } else { LOG(ERROR) << Form("Wrong weight %f\n", wtot); + } // Calculate dispersion for (auto iInput : inputsIndices) { @@ -154,8 +157,9 @@ void ClusterFactory<InputType>::evalDispersion(gsl::span<const int> inputsIndice // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2 // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0 - if (mSharedCluster && nSupMod % 2) + if (mSharedCluster && nSupMod % 2) { ieta += EMCAL_COLS; + } double etai = (double)ieta; double phii = (double)iphi; @@ -168,10 +172,11 @@ void ClusterFactory<InputType>::evalDispersion(gsl::span<const int> inputsIndice } } - if (wtot > 0 && nstat > 1) + if (wtot > 0 && nstat > 1) { d /= wtot; - else + } else { d = 0.; + } clusterAnalysis.setDispersion(TMath::Sqrt(d)); } @@ -199,13 +204,15 @@ void ClusterFactory<InputType>::evalLocalPosition(gsl::span<const int> inputsInd } //Temporal patch, due to mapping problem, need to swap "y" in one of the 2 SM, although no effect in position calculation. GCB 05/2010 - if (mSharedCluster && mSuperModuleNumber != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) + if (mSharedCluster && mSuperModuleNumber != mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())) { xyzi[1] *= -1; + } - if (mLogWeight > 0.0) + if (mLogWeight > 0.0) { w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E())); - else + } else { w = mInputsContainer[iInput].getEnergy(); // just energy + } if (w > 0.0) { wtot += w; @@ -229,12 +236,14 @@ void ClusterFactory<InputType>::evalLocalPosition(gsl::span<const int> inputsInd clRmsXYZ[i] /= (wtot * wtot); clRmsXYZ[i] = clRmsXYZ[i] - clXYZ[i] * clXYZ[i]; - if (clRmsXYZ[i] > 0.0) + if (clRmsXYZ[i] > 0.0) { clRmsXYZ[i] = TMath::Sqrt(clRmsXYZ[i]); - else + } else { clRmsXYZ[i] = 0; - } else + } + } else { clRmsXYZ[i] = 0; + } } } else { for (int i = 0; i < 3; i++) { @@ -271,10 +280,11 @@ void ClusterFactory<InputType>::evalGlobalPosition(gsl::span<const int> inputsIn // Now get the global coordinate mGeomPtr->GetGlobal(lxyzi, xyzi, mGeomPtr->GetSuperModuleNumber(mInputsContainer[iInput].getTower())); - if (mLogWeight > 0.0) + if (mLogWeight > 0.0) { w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E())); - else + } else { w = mInputsContainer[iInput].getEnergy(); // just energy + } if (w > 0.0) { wtot += w; @@ -298,12 +308,14 @@ void ClusterFactory<InputType>::evalGlobalPosition(gsl::span<const int> inputsIn clRmsXYZ[i] /= (wtot * wtot); clRmsXYZ[i] = clRmsXYZ[i] - clXYZ[i] * clXYZ[i]; - if (clRmsXYZ[i] > 0.0) + if (clRmsXYZ[i] > 0.0) { clRmsXYZ[i] = TMath::Sqrt(clRmsXYZ[i]); - else + } else { clRmsXYZ[i] = 0; - } else + } + } else { clRmsXYZ[i] = 0; + } } } else { for (i = 0; i < 3; i++) { @@ -333,10 +345,11 @@ void ClusterFactory<InputType>::evalLocalPositionFit(double deff, double mLogWei continue; } - if (mLogWeight > 0.0) + if (mLogWeight > 0.0) { w = TMath::Max(0., mLogWeight + TMath::Log(mInputsContainer[iInput].getEnergy() / clusterAnalysis.E())); - else + } else { w = mInputsContainer[iInput].getEnergy(); // just energy + } if (w > 0.0) { wtot += w; @@ -360,12 +373,14 @@ void ClusterFactory<InputType>::evalLocalPositionFit(double deff, double mLogWei clRmsXYZ[i] /= (wtot * wtot); clRmsXYZ[i] = clRmsXYZ[i] - clXYZ[i] * clXYZ[i]; - if (clRmsXYZ[i] > 0.0) + if (clRmsXYZ[i] > 0.0) { clRmsXYZ[i] = TMath::Sqrt(clRmsXYZ[i]); - else + } else { clRmsXYZ[i] = 0; - } else + } + } else { clRmsXYZ[i] = 0; + } } } else { for (i = 0; i < 3; i++) { @@ -421,8 +436,9 @@ void ClusterFactory<InputType>::evalCoreEnergy(gsl::span<const int> inputsIndice float coreEnergy = 0.; - if (!clusterAnalysis.getLocalPosition().Mag2()) + if (!clusterAnalysis.getLocalPosition().Mag2()) { evalLocalPosition(inputsIndices, clusterAnalysis); + } double phiPoint = clusterAnalysis.getLocalPosition().Phi(); double etaPoint = clusterAnalysis.getLocalPosition().Eta(); @@ -433,8 +449,9 @@ void ClusterFactory<InputType>::evalCoreEnergy(gsl::span<const int> inputsIndice double distance = TMath::Sqrt((eta - etaPoint) * (eta - etaPoint) + (phi - phiPoint) * (phi - phiPoint)); - if (distance < mCoreRadius) + if (distance < mCoreRadius) { coreEnergy += mInputsContainer[iInput].getEnergy(); + } } clusterAnalysis.setCoreEnergy(coreEnergy); } @@ -464,8 +481,9 @@ void ClusterFactory<InputType>::evalElipsAxis(gsl::span<const int> inputsIndices // In case of a shared cluster, index of SM in C side, columns start at 48 and ends at 48*2 // C Side impair SM, nSupMod%2=1; A side pair SM, nSupMod%2=0 - if (mSharedCluster && nSupMod % 2) + if (mSharedCluster && nSupMod % 2) { ieta += EMCAL_COLS; + } double etai = (double)ieta; double phii = (double)iphi; @@ -497,17 +515,19 @@ void ClusterFactory<InputType>::evalElipsAxis(gsl::span<const int> inputsIndices lambda[0] = 0.5 * (dxx + dzz) + TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz); - if (lambda[0] > 0) + if (lambda[0] > 0) { lambda[0] = TMath::Sqrt(lambda[0]); - else + } else { lambda[0] = 0; + } lambda[1] = 0.5 * (dxx + dzz) - TMath::Sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz); - if (lambda[1] > 0) //To avoid exception if numerical errors lead to negative lambda. + if (lambda[1] > 0) { //To avoid exception if numerical errors lead to negative lambda. lambda[1] = TMath::Sqrt(lambda[1]); - else + } else { lambda[1] = 0.; + } } else { lambda[0] = 0.; lambda[1] = 0.; @@ -528,8 +548,9 @@ std::tuple<int, float, float> ClusterFactory<InputType>::getMaximalEnergyIndex(g int mid = 0; float cellAmp = 0; for (auto iInput : inputsIndices) { - if (iInput >= mInputsContainer.size()) + if (iInput >= mInputsContainer.size()) { throw CellIndexRangeException(iInput, mInputsContainer.size()); + } cellAmp += mInputsContainer[iInput].getEnergy(); if (mInputsContainer[iInput].getEnergy() > energy) { energy = mInputsContainer[iInput].getEnergy(); @@ -548,8 +569,9 @@ int ClusterFactory<InputType>::getMultiplicityAtLevel(float H, gsl::span<const i { int multipl = 0; for (auto iInput : inputsIndices) { - if (mInputsContainer[iInput].getEnergy() > H * clusterAnalysis.E()) + if (mInputsContainer[iInput].getEnergy() > H * clusterAnalysis.E()) { multipl++; + } } return multipl; @@ -587,10 +609,11 @@ double ClusterFactory<InputType>::tMaxInCm(const double e, const int key) const if (e > 0.1) { tmax = TMath::Log(e) + ca; - if (key == 0) + if (key == 0) { tmax += 0.5; - else + } else { tmax -= 0.5; + } tmax *= x0; // convert to cm } @@ -633,10 +656,11 @@ bool ClusterFactory<InputType>::ClusterIterator::operator==(const ClusterFactory template <class InputType> typename ClusterFactory<InputType>::ClusterIterator& ClusterFactory<InputType>::ClusterIterator::operator++() { - if (mForward) + if (mForward) { mClusterID++; - else + } else { mClusterID--; + } mCurrentCluster = mClusterFactory.buildCluster(mClusterID); return *this; } @@ -652,10 +676,11 @@ typename ClusterFactory<InputType>::ClusterIterator ClusterFactory<InputType>::C template <class InputType> typename ClusterFactory<InputType>::ClusterIterator& ClusterFactory<InputType>::ClusterIterator::operator--() { - if (mForward) + if (mForward) { mClusterID--; - else + } else { mClusterID++; + } mCurrentCluster = mClusterFactory.buildCluster(mClusterID); return *this; } diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index 08688e4a24657..2e3c806252c03 100644 --- a/Detectors/EMCAL/base/src/Geometry.cxx +++ b/Detectors/EMCAL/base/src/Geometry.cxx @@ -180,8 +180,9 @@ Geometry::~Geometry() } for (Int_t smod = 0; smod < mNumberOfSuperModules; smod++) { - if (SMODULEMATRIX[smod]) + if (SMODULEMATRIX[smod]) { delete SMODULEMATRIX[smod]; + } } } @@ -304,17 +305,18 @@ void Geometry::DefineSamplingFraction(const std::string_view mcname, const std:: } Float_t samplingFactorTranportModel = 1.; - if (contains(mcname, "Geant3")) + if (contains(mcname, "Geant3")) { samplingFactorTranportModel = 1.; // 0.988 // Do nothing - else if (contains(mcname, "Fluka")) + } else if (contains(mcname, "Fluka")) { samplingFactorTranportModel = 1.; // To be set - else if (contains(mcname, "Geant4")) { - if (contains(mctitle, "EMV-EMCAL")) + } else if (contains(mcname, "Geant4")) { + if (contains(mctitle, "EMV-EMCAL")) { samplingFactorTranportModel = 0.821; // EMC list but for EMCal, before 0.86 - else if (contains(mctitle, "EMV")) + } else if (contains(mctitle, "EMV")) { samplingFactorTranportModel = 1.096; // 0.906, 0.896 (OPT) - else + } else { samplingFactorTranportModel = 0.821; // 1.15 (CHIPS), 1.149 (BERT), 1.147 (BERT_CHIPS) + } } LOG(INFO) << "MC modeler <" << mcname << ">, Title <" << mctitle << ">: Sampling " << std::setw(2) @@ -340,8 +342,9 @@ void Geometry::DefineEMC(std::string_view mcname, std::string_view mctitle) } } - if (contains(mGeoName, "WSUC")) + if (contains(mGeoName, "WSUC")) { mGeoName = "EMCAL_WSUC"; + } // check that we have a valid geometry name if (!(contains(mGeoName, "EMCAL_PDC06") || contains(mGeoName, "EMCAL_WSUC") || contains(mGeoName, "EMCAL_COMPLETE") || @@ -352,10 +355,12 @@ void Geometry::DefineEMC(std::string_view mcname, std::string_view mctitle) // Option to know whether we have the "half" supermodule(s) or not mKey110DEG = 0; - if (contains(mGeoName, "COMPLETE") || contains(mGeoName, "PDC06") || contains(mGeoName, "12SM")) + if (contains(mGeoName, "COMPLETE") || contains(mGeoName, "PDC06") || contains(mGeoName, "12SM")) { mKey110DEG = 1; // for GetAbsCellId - if (contains(mGeoName, "COMPLETEV1")) + } + if (contains(mGeoName, "COMPLETEV1")) { mKey110DEG = 0; + } mnSupModInDCAL = 0; if (contains(mGeoName, "DCAL_DEV")) { @@ -447,10 +452,11 @@ void Geometry::DefineEMC(std::string_view mcname, std::string_view mctitle) if (contains(mGeoName, "DCAL")) { mNumberOfSuperModules = 12 + mnSupModInDCAL; mArm1PhiMax = 320.0; - if (contains(mGeoName, "DCAL_8SM")) + if (contains(mGeoName, "DCAL_8SM")) { mArm1PhiMax = 340.0; // degrees, End of DCAL Phi position - else if (contains(mGeoName, "DCAL_DEV")) + } else if (contains(mGeoName, "DCAL_DEV")) { mArm1PhiMin = 40.0; // degrees, Starting EMCAL(shifted) Phi position + } mDCALPhiMin = mArm1PhiMax - 10. * mnSupModInDCAL; } } @@ -460,8 +466,9 @@ void Geometry::DefineEMC(std::string_view mcname, std::string_view mctitle) mEMCSMSystem.clear(); mEMCSMSystem.resize(mNumberOfSuperModules); - for (Int_t i = 0; i < mNumberOfSuperModules; i++) + for (Int_t i = 0; i < mNumberOfSuperModules; i++) { mEMCSMSystem[i] = NOT_EXISTENT; + } Int_t iSM = 0; @@ -521,23 +528,25 @@ void Geometry::DefineEMC(std::string_view mcname, std::string_view mctitle) mNCellsInSupMod = mNCellsInModule * mNPhi * mNZ; mNCells = 0; for (int i = 0; i < mNumberOfSuperModules; i++) { - if (GetSMType(i) == EMCAL_STANDARD) + if (GetSMType(i) == EMCAL_STANDARD) { mNCells += mNCellsInSupMod; - else if (GetSMType(i) == EMCAL_HALF) + } else if (GetSMType(i) == EMCAL_HALF) { mNCells += mNCellsInSupMod / 2; - else if (GetSMType(i) == EMCAL_THIRD) + } else if (GetSMType(i) == EMCAL_THIRD) { mNCells += mNCellsInSupMod / 3; - else if (GetSMType(i) == DCAL_STANDARD) + } else if (GetSMType(i) == DCAL_STANDARD) { mNCells += 2 * mNCellsInSupMod / 3; - else if (GetSMType(i) == DCAL_EXT) + } else if (GetSMType(i) == DCAL_EXT) { mNCells += mNCellsInSupMod / 3; - else + } else { LOG(ERROR) << "Uknown SuperModule Type !!\n"; + } } mNPhiSuperModule = mNumberOfSuperModules / 2; - if (mNPhiSuperModule < 1) + if (mNPhiSuperModule < 1) { mNPhiSuperModule = 1; + } mPhiTileSize = mPhiModuleSize / double(mNPHIdiv) - mLateralSteelStrip; // 13-may-05 mEtaTileSize = mEtaModuleSize / double(mNETAdiv) - mLateralSteelStrip; // 13-may-05 @@ -550,8 +559,9 @@ void Geometry::DefineEMC(std::string_view mcname, std::string_view mctitle) } m2Trd1Dx2 = mEtaModuleSize + 2. * mLongModuleSize * TMath::Tan(mTrd1Angle * TMath::DegToRad() / 2.); - if (!contains(mGeoName, "WSUC")) + if (!contains(mGeoName, "WSUC")) { mShellThickness = TMath::Sqrt(mLongModuleSize * mLongModuleSize + m2Trd1Dx2 * m2Trd1Dx2); + } // These parameters are used to create the mother volume to hold the supermodules // 2cm padding added to allow for misalignments - JLK 30-May-2008 @@ -613,19 +623,20 @@ void Geometry::DefineEMC(std::string_view mcname, std::string_view mctitle) mEMCALPhiMax = mArm1PhiMin; mDCALPhiMax = mDCALPhiMin; // DCAl extention will not be included for (Int_t i = 0; i < mNumberOfSuperModules; i += 2) { - if (GetSMType(i) == EMCAL_STANDARD) + if (GetSMType(i) == EMCAL_STANDARD) { mEMCALPhiMax += 20.; - else if (GetSMType(i) == EMCAL_HALF) + } else if (GetSMType(i) == EMCAL_HALF) { mEMCALPhiMax += mPhiSuperModule / 2. + innerExtandedPhi; - else if (GetSMType(i) == EMCAL_THIRD) + } else if (GetSMType(i) == EMCAL_THIRD) { mEMCALPhiMax += mPhiSuperModule / 3. + 4.0 * innerExtandedPhi / 3.0; - else if (GetSMType(i) == DCAL_STANDARD) { + } else if (GetSMType(i) == DCAL_STANDARD) { mDCALPhiMax += 20.; mDCALStandardPhiMax = mDCALPhiMax; - } else if (GetSMType(i) == DCAL_EXT) + } else if (GetSMType(i) == DCAL_EXT) { mDCALPhiMax += mPhiSuperModule / 3. + 4.0 * innerExtandedPhi / 3.0; - else + } else { LOG(ERROR) << "Unkown SM Type!!\n"; + } } // for compatible reason // if(fNumberOfSuperModules == 4) {fEMCALPhiMax = fArm1PhiMax ;} @@ -704,25 +715,27 @@ Int_t Geometry::GetAbsCellId(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nI // 0 <= absid < fNCells Int_t id = 0; // have to change from 0 to fNCells-1 for (int i = 0; i < nSupMod; i++) { - if (GetSMType(i) == EMCAL_STANDARD) + if (GetSMType(i) == EMCAL_STANDARD) { id += mNCellsInSupMod; - else if (GetSMType(i) == EMCAL_HALF) + } else if (GetSMType(i) == EMCAL_HALF) { id += mNCellsInSupMod / 2; - else if (GetSMType(i) == EMCAL_THIRD) + } else if (GetSMType(i) == EMCAL_THIRD) { id += mNCellsInSupMod / 3; - else if (GetSMType(i) == DCAL_STANDARD) + } else if (GetSMType(i) == DCAL_STANDARD) { id += 2 * mNCellsInSupMod / 3; - else if (GetSMType(i) == DCAL_EXT) + } else if (GetSMType(i) == DCAL_EXT) { id += mNCellsInSupMod / 3; - else + } else { throw InvalidSupermoduleTypeException(); + } } id += mNCellsInModule * nModule; id += mNPHIdiv * nIphi; id += nIeta; - if (!CheckAbsCellId(id)) + if (!CheckAbsCellId(id)) { id = -TMath::Abs(id); // if negative something wrong + } return id; } @@ -756,8 +769,9 @@ Int_t Geometry::GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t iet std::tuple<int, int> Geometry::GlobalRowColFromIndex(int cellID) const { - if (cellID >= GetNCells()) + if (cellID >= GetNCells()) { throw InvalidCellIDException(cellID); + } auto [supermodule, module, phiInModule, etaInModule] = GetCellIndex(cellID); auto [row, col] = GetCellPhiEtaIndexInSModule(supermodule, module, phiInModule, etaInModule); // add offsets (row / col per supermodule) @@ -765,8 +779,9 @@ std::tuple<int, int> Geometry::GlobalRowColFromIndex(int cellID) const // DCal odd SMs need shift of the col. index in oder to get the global col. index col += 16; } - if (supermodule % 2) + if (supermodule % 2) { col += mNZ * 2; + } int sector = supermodule / 2; if (sector > 0) { for (int isec = 0; isec < sector; isec++) { @@ -780,8 +795,9 @@ std::tuple<int, int> Geometry::GlobalRowColFromIndex(int cellID) const std::tuple<int, int, int> Geometry::GetPositionInSupermoduleFromGlobalRowCol(int row, int col) const { - if (col < 0 || col >= 4 * GetNEta()) + if (col < 0 || col >= 4 * GetNEta()) { throw RowColException(row, col); + } int side = col < GetNEta() * 2 ? 0 : 1, colSM = col % (GetNEta() * 2); int sector = -1, @@ -789,26 +805,30 @@ std::tuple<int, int, int> Geometry::GetPositionInSupermoduleFromGlobalRowCol(int for (int isec = 0; isec < GetNPhiSuperModule(); isec++) { auto smtype = GetSMType(isec * 2); auto nphism = GetNPhi() * 2; - if (smtype == EMCAL_THIRD || smtype == DCAL_EXT) + if (smtype == EMCAL_THIRD || smtype == DCAL_EXT) { nphism /= 3; + } if (rowSM < nphism) { sector = isec; break; } rowSM -= nphism; } - if (sector < 0) + if (sector < 0) { throw RowColException(row, col); + } int supermodule = sector * 2 + side; if (supermodule == 13 || supermodule == 15 || supermodule == 17) { // DCal odd SMs need shift of the col. index as global col index includes PHOS hole colSM -= 16; - if (colSM < 0) + if (colSM < 0) { throw RowColException(row, col); // Position inside PHOS hole specified + } } if (supermodule == 12 || supermodule == 14 || supermodule == 16) { - if (colSM > 32) + if (colSM > 32) { throw RowColException(row, col); // Position inside PHOS hole specified + } } return std::make_tuple(supermodule, rowSM, colSM); } @@ -842,8 +862,9 @@ int Geometry::GlobalRow(int cellID) const Int_t Geometry::SuperModuleNumberFromEtaPhi(Double_t eta, Double_t phi) const { - if (TMath::Abs(eta) > mEtaMaxOfTRD1) + if (TMath::Abs(eta) > mEtaMaxOfTRD1) { throw InvalidPositionException(eta, phi); + } phi = TVector2::Phi_0_2pi(phi); // move phi to (0,2pi) boundaries Int_t nphism = mNumberOfSuperModules / 2; @@ -852,12 +873,14 @@ Int_t Geometry::SuperModuleNumberFromEtaPhi(Double_t eta, Double_t phi) const LOG(DEBUG) << "Sec " << i << ": Min " << mPhiBoundariesOfSM[2 * i] << ", Max " << mPhiBoundariesOfSM[2 * i + 1]; if (phi >= mPhiBoundariesOfSM[2 * i] && phi <= mPhiBoundariesOfSM[2 * i + 1]) { nSupMod = 2 * i; - if (eta < 0.0) + if (eta < 0.0) { nSupMod++; + } if (GetSMType(nSupMod) == DCAL_STANDARD) { // Gap between DCAL - if (TMath::Abs(eta) < GetNEta() / 3 * mTrd1Angle * TMath::DegToRad()) + if (TMath::Abs(eta) < GetNEta() / 3 * mTrd1Angle * TMath::DegToRad()) { throw InvalidPositionException(eta, phi); + } } LOG(DEBUG) << "eta " << eta << " phi " << phi << " (" << std::setw(5) << std::setprecision(2) @@ -876,12 +899,13 @@ Int_t Geometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi) const phi = TVector2::Phi_0_2pi(phi); Double_t phiLoc = phi - mPhiCentersOfSMSec[nSupMod / 2]; Int_t nphi = mPhiCentersOfCells.size(); - if (GetSMType(nSupMod) == EMCAL_HALF) + if (GetSMType(nSupMod) == EMCAL_HALF) { nphi /= 2; - else if (GetSMType(nSupMod) == EMCAL_THIRD) + } else if (GetSMType(nSupMod) == EMCAL_THIRD) { nphi /= 3; - else if (GetSMType(nSupMod) == DCAL_EXT) + } else if (GetSMType(nSupMod) == DCAL_EXT) { nphi /= 3; + } Double_t dmin = TMath::Abs(mPhiCentersOfCells[0] - phiLoc), d = 0.; @@ -902,8 +926,9 @@ Int_t Geometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi) const Int_t neta = mCentersOfCellsEtaDir.size(), etaShift = iphi * neta, ieta = 0; - if (GetSMType(nSupMod) == DCAL_STANDARD) + if (GetSMType(nSupMod) == DCAL_STANDARD) { ieta += 16; // jump 16 cells for DCSM + } dmin = TMath::Abs(mEtaCentersOfCells[etaShift + ieta] - absEta); for (Int_t i = ieta + 1; i < neta; i++) { d = TMath::Abs(mEtaCentersOfCells[i + etaShift] - absEta); @@ -913,8 +938,9 @@ Int_t Geometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi) const } } - if (GetSMType(nSupMod) == DCAL_STANDARD) + if (GetSMType(nSupMod) == DCAL_STANDARD) { ieta -= 16; // jump 16 cells for DCSM + } LOG(DEBUG2) << " ieta " << ieta << " : dmin " << dmin << " (eta=" << eta << ") : nSupMod " << nSupMod; @@ -922,8 +948,9 @@ Int_t Geometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi) const if (nSupMod % 2 == 0) { // 47 + 16 -ieta for DCSM, 47 - ieta for others, revert the ordering on A side in order to keep convention. ieta = (neta - 1) - ieta; - if (GetSMType(nSupMod) == DCAL_STANDARD) + if (GetSMType(nSupMod) == DCAL_STANDARD) { ieta -= 16; // recover cells for DCSM + } } return GetAbsCellIdFromCellIndexes(nSupMod, iphi, ieta); @@ -931,8 +958,9 @@ Int_t Geometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi) const std::tuple<int, int, int, int> Geometry::CalculateCellIndex(Int_t absId) const { - if (!CheckAbsCellId(absId)) + if (!CheckAbsCellId(absId)) { throw InvalidCellIDException(absId); + } Int_t tmp = absId; Int_t test = absId; @@ -941,17 +969,17 @@ std::tuple<int, int, int, int> Geometry::CalculateCellIndex(Int_t absId) const for (nSupMod = -1; test >= 0;) { nSupMod++; tmp = test; - if (GetSMType(nSupMod) == EMCAL_STANDARD) + if (GetSMType(nSupMod) == EMCAL_STANDARD) { test -= mNCellsInSupMod; - else if (GetSMType(nSupMod) == EMCAL_HALF) + } else if (GetSMType(nSupMod) == EMCAL_HALF) { test -= mNCellsInSupMod / 2; - else if (GetSMType(nSupMod) == EMCAL_THIRD) + } else if (GetSMType(nSupMod) == EMCAL_THIRD) { test -= mNCellsInSupMod / 3; - else if (GetSMType(nSupMod) == DCAL_STANDARD) + } else if (GetSMType(nSupMod) == DCAL_STANDARD) { test -= 2 * mNCellsInSupMod / 3; - else if (GetSMType(nSupMod) == DCAL_EXT) + } else if (GetSMType(nSupMod) == DCAL_EXT) { test -= mNCellsInSupMod / 3; - else { + } else { throw InvalidSupermoduleTypeException(); } } @@ -964,8 +992,9 @@ std::tuple<int, int, int, int> Geometry::CalculateCellIndex(Int_t absId) const std::tuple<int, int, int, int> Geometry::GetCellIndex(Int_t absId) const { - if (!CheckAbsCellId(absId)) + if (!CheckAbsCellId(absId)) { throw InvalidCellIDException(absId); + } return mCellIndexLookup[absId]; } @@ -974,14 +1003,15 @@ Int_t Geometry::GetSuperModuleNumber(Int_t absId) const { return std::get<0>(Get std::tuple<int, int> Geometry::GetModulePhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule) const { Int_t nphi = -1; - if (GetSMType(nSupMod) == EMCAL_HALF) + if (GetSMType(nSupMod) == EMCAL_HALF) { nphi = mNPhi / 2; // halfSM - else if (GetSMType(nSupMod) == EMCAL_THIRD) + } else if (GetSMType(nSupMod) == EMCAL_THIRD) { nphi = mNPhi / 3; // 1/3 SM - else if (GetSMType(nSupMod) == DCAL_EXT) + } else if (GetSMType(nSupMod) == DCAL_EXT) { nphi = mNPhi / 3; // 1/3 SM - else + } else { nphi = mNPhi; // full SM + } return std::make_tuple(int(nModule % nphi), int(nModule / nphi)); } @@ -1036,8 +1066,9 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId) const Double_t zshift = 0.5 * GetDCALInnerEdge(); Double_t xr, yr, zr; - if (!CheckAbsCellId(absId)) + if (!CheckAbsCellId(absId)) { throw InvalidCellIDException(absId); + } auto cellindex = GetCellIndex(absId); Int_t nSupMod = std::get<0>(cellindex), nModule = std::get<1>(cellindex), nIphi = std::get<2>(cellindex), @@ -1047,35 +1078,42 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId) const // Get eta position. Careful with ALICE conventions (increase index decrease eta) Int_t ieta2 = ieta; - if (nSupMod % 2 == 0) + if (nSupMod % 2 == 0) { ieta2 = (mCentersOfCellsEtaDir.size() - 1) - ieta; // 47-ieta, revert the ordering on A side in order to keep convention. + } - if (GetSMType(nSupMod) == DCAL_STANDARD && nSupMod % 2) + if (GetSMType(nSupMod) == DCAL_STANDARD && nSupMod % 2) { ieta2 += 16; // DCAL revert the ordering on C side ... + } zr = mCentersOfCellsEtaDir[ieta2]; - if (GetSMType(nSupMod) == DCAL_STANDARD) + if (GetSMType(nSupMod) == DCAL_STANDARD) { zr -= zshift; // DCAL shift (SMALLER SM) + } xr = mCentersOfCellsXDir[ieta2]; // Get phi position. Careful with ALICE conventions (increase index increase phi) Int_t iphi2 = iphi; if (GetSMType(nSupMod) == DCAL_EXT) { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (phiindex / 3 - 1) - iphi; // 7-iphi [1/3SM], revert the ordering on C side in order to keep convention. + } yr = mCentersOfCellsPhiDir[iphi2 + phiindex / 3]; } else if (GetSMType(nSupMod) == EMCAL_HALF) { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (phiindex / 2 - 1) - iphi; // 11-iphi [1/2SM], revert the ordering on C side in order to keep + } // convention. yr = mCentersOfCellsPhiDir[iphi2 + phiindex / 4]; } else if (GetSMType(nSupMod) == EMCAL_THIRD) { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (phiindex / 3 - 1) - iphi; // 7-iphi [1/3SM], revert the ordering on C side in order to keep convention. + } yr = mCentersOfCellsPhiDir[iphi2 + phiindex / 3]; } else { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (phiindex - 1) - iphi; // 23-iphi, revert the ordering on C side in order to keep conventi + } yr = mCentersOfCellsPhiDir[iphi2]; } @@ -1095,8 +1133,9 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId, Double_t distEff) con Int_t iphim = -1, ietam = -1; TVector2 v; - if (!CheckAbsCellId(absId)) + if (!CheckAbsCellId(absId)) { throw InvalidCellIDException(absId); + } auto cellindex = GetCellIndex(absId); Int_t nSupMod = std::get<0>(cellindex), nModule = std::get<1>(cellindex), nIphi = std::get<2>(cellindex), @@ -1111,39 +1150,46 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId, Double_t distEff) con if (nSupMod % 2 == 0) { ietam = (mCentersOfCellsEtaDir.size() / 2 - 1) - ietam; // 24-ietam, revert the ordering on A side in order to keep convention. - if (nIeta == 0) + if (nIeta == 0) { nIeta = 1; - else + } else { nIeta = 0; + } } - if (GetSMType(nSupMod) == DCAL_STANDARD && nSupMod % 2) + if (GetSMType(nSupMod) == DCAL_STANDARD && nSupMod % 2) { ietam += kDCalshift; // DCAL revert the ordering on C side .... + } const ShishKebabTrd1Module& mod = GetShishKebabModule(ietam); mod.GetPositionAtCenterCellLine(nIeta, distEff, v); xr = v.Y() - mParSM[0]; zr = v.X() - mParSM[2]; - if (GetSMType(nSupMod) == DCAL_STANDARD) + if (GetSMType(nSupMod) == DCAL_STANDARD) { zr -= zshift; // DCAL shift (SMALLER SM) + } // Get phi position. Careful with ALICE conventions (increase index increase phi) Int_t iphi2 = iphi; if (GetSMType(nSupMod) == DCAL_EXT) { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (nphiIndex / 3 - 1) - iphi; // 7-iphi [1/3SM], revert the ordering on C side in order to keep convention. + } yr = mCentersOfCellsPhiDir[iphi2 + nphiIndex / 3]; } else if (GetSMType(nSupMod) == EMCAL_HALF) { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (nphiIndex / 2 - 1) - iphi; // 11-iphi [1/2SM], revert the ordering on C side in order to keep + } // convention. yr = mCentersOfCellsPhiDir[iphi2 + nphiIndex / 2]; } else if (GetSMType(nSupMod) == EMCAL_THIRD) { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (nphiIndex / 3 - 1) - iphi; // 7-iphi [1/3SM], revert the ordering on C side in order to keep convention. + } yr = mCentersOfCellsPhiDir[iphi2 + nphiIndex / 3]; } else { - if (nSupMod % 2 != 0) + if (nSupMod % 2 != 0) { iphi2 = (nphiIndex - 1) - iphi; // 23-iphi, revert the ordering on C side in order to keep convention. + } yr = mCentersOfCellsPhiDir[iphi2]; } @@ -1267,8 +1313,9 @@ void Geometry::CreateListOfTrd1Modules() const ShishKebabTrd1Module& Geometry::GetShishKebabModule(Int_t neta) const { - if (mShishKebabTrd1Modules.size() && neta >= 0 && neta < mShishKebabTrd1Modules.size()) + if (mShishKebabTrd1Modules.size() && neta >= 0 && neta < mShishKebabTrd1Modules.size()) { return mShishKebabTrd1Modules.at(neta); + } throw InvalidModuleException(neta, mShishKebabTrd1Modules.size()); } @@ -1280,8 +1327,9 @@ Bool_t Geometry::Impact(const TParticle* particle) const ImpactOnEmcal({particle->Vx(), particle->Vy(), particle->Vz()}, particle->Theta(), particle->Phi(), absID, vimpact); - if (absID >= 0) + if (absID >= 0) { in = kTRUE; + } return in; } @@ -1292,8 +1340,9 @@ void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_ vimpact.SetXYZ(0, 0, 0); absId = -1; - if (phi == 0 || theta == 0) + if (phi == 0 || theta == 0) { return; + } Vector3D<double> direction; Double_t factor = (mIPDistance - vtx.Y()) / p.Y(); @@ -1320,15 +1369,17 @@ void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_ nIeta = std::get<3>(cellindex); // look at 2 neighbours-s cell using nIphi={0,1} and nIeta={0,1} Int_t nIphi2 = -1, nIeta2 = -1, absId2 = -1, absId3 = -1; - if (nIeta == 0) + if (nIeta == 0) { nIeta2 = 1; - else + } else { nIeta2 = 0; + } absId2 = GetAbsCellId(nSupMod, nModule, nIphi, nIeta2); - if (nIphi == 0) + if (nIphi == 0) { nIphi2 = 1; - else + } else { nIphi2 = 0; + } absId3 = GetAbsCellId(nSupMod, nModule, nIphi2, nIeta); // 2nd point on emcal cell plane @@ -1372,8 +1423,9 @@ void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_ Double_t glob4[3] = {}; Vector3D<double> dir = {a, b, c}; Point3D<double> point = {glob[0], glob[1], glob[2]}; - if (point.Dot(dir) < 0) + if (point.Dot(dir) < 0) { dist *= -1; + } glob4[0] = glob[0] - dist * a / norm; glob4[1] = glob[1] - dist * b / norm; glob4[2] = glob[2] - dist * c / norm; @@ -1400,46 +1452,52 @@ void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_ Bool_t Geometry::IsInEMCAL(const Point3D<double>& pnt) const { - if (IsInEMCALOrDCAL(pnt) == EMCAL_ACCEPTANCE) + if (IsInEMCALOrDCAL(pnt) == EMCAL_ACCEPTANCE) { return kTRUE; - else + } else { return kFALSE; + } } Bool_t Geometry::IsInDCAL(const Point3D<double>& pnt) const { - if (IsInEMCALOrDCAL(pnt) == DCAL_ACCEPTANCE) + if (IsInEMCALOrDCAL(pnt) == DCAL_ACCEPTANCE) { return kTRUE; - else + } else { return kFALSE; + } } o2::emcal::AcceptanceType_t Geometry::IsInEMCALOrDCAL(const Point3D<double>& pnt) const { Double_t r = sqrt(pnt.X() * pnt.X() + pnt.Y() * pnt.Y()); - if (r <= mEnvelop[0]) + if (r <= mEnvelop[0]) { return NON_ACCEPTANCE; - else { + } else { Double_t theta = TMath::ATan2(r, pnt.Z()); Double_t eta; - if (theta == 0) + if (theta == 0) { eta = 9999; - else + } else { eta = -TMath::Log(TMath::Tan(theta / 2.)); - if (eta < mArm1EtaMin || eta > mArm1EtaMax) + } + if (eta < mArm1EtaMin || eta > mArm1EtaMax) { return NON_ACCEPTANCE; + } Double_t phi = TMath::ATan2(pnt.Y(), pnt.X()) * 180. / TMath::Pi(); - if (phi < 0) + if (phi < 0) { phi += 360; // phi should go from 0 to 360 in this case + } - if (phi >= mArm1PhiMin && phi <= mEMCALPhiMax) + if (phi >= mArm1PhiMin && phi <= mEMCALPhiMax) { return EMCAL_ACCEPTANCE; - else if (phi >= mDCALPhiMin && phi <= mDCALStandardPhiMax && TMath::Abs(eta) > mDCALInnerExtandedEta) + } else if (phi >= mDCALPhiMin && phi <= mDCALStandardPhiMax && TMath::Abs(eta) > mDCALInnerExtandedEta) { return DCAL_ACCEPTANCE; - else if (phi > mDCALStandardPhiMax && phi <= mDCALPhiMax) + } else if (phi > mDCALStandardPhiMax && phi <= mDCALPhiMax) { return DCAL_ACCEPTANCE; + } return NON_ACCEPTANCE; } } @@ -1595,11 +1653,12 @@ void Geometry::RecalculateTowerPosition(Float_t drow, Float_t dcol, const Int_t for (int is = 0; is <= istrip; is++) { teta1 = TMath::DegToRad() * (is * 1.5 + 0.75); - if (is == 0) + if (is == 0) { zIs = zIs + 2 * dz * TMath::Cos(teta1); - else + } else { zIs = zIs + 2 * dz * TMath::Cos(teta1) + 2 * dz * TMath::Sin(teta1) * TMath::Tan(teta1 - 0.75 * TMath::DegToRad()); + } } z0 = dz * (dcol - 2 * istrip + 0.5); @@ -1648,8 +1707,9 @@ void Geometry::RecalculateTowerPosition(Float_t drow, Float_t dcol, const Int_t void Geometry::SetMisalMatrix(const TGeoHMatrix* m, Int_t smod) const { if (smod >= 0 && smod < mNumberOfSuperModules) { - if (!SMODULEMATRIX[smod]) + if (!SMODULEMATRIX[smod]) { SMODULEMATRIX[smod] = new TGeoHMatrix(*m); // Set only if not set yet + } } else { LOG(FATAL) << "Wrong supermodule index -> " << smod << std::endl; } @@ -1657,16 +1717,18 @@ void Geometry::SetMisalMatrix(const TGeoHMatrix* m, Int_t smod) const Bool_t Geometry::IsDCALSM(Int_t iSupMod) const { - if (mEMCSMSystem[iSupMod] == DCAL_STANDARD || mEMCSMSystem[iSupMod] == DCAL_EXT) + if (mEMCSMSystem[iSupMod] == DCAL_STANDARD || mEMCSMSystem[iSupMod] == DCAL_EXT) { return kTRUE; + } return kFALSE; } Bool_t Geometry::IsDCALExtSM(Int_t iSupMod) const { - if (mEMCSMSystem[iSupMod] == DCAL_EXT) + if (mEMCSMSystem[iSupMod] == DCAL_EXT) { return kTRUE; + } return kFALSE; } @@ -1686,15 +1748,17 @@ Double_t Geometry::GetPhiCenterOfSM(Int_t nsupmod) const std::tuple<double, double> Geometry::GetPhiBoundariesOfSM(Int_t nSupMod) const { int i; - if (nSupMod < 0 || nSupMod > 12 + mnSupModInDCAL - 1) + if (nSupMod < 0 || nSupMod > 12 + mnSupModInDCAL - 1) { throw InvalidModuleException(nSupMod, 12 + mnSupModInDCAL); + } i = nSupMod / 2; return std::make_tuple((Double_t)mPhiBoundariesOfSM[2 * i], (Double_t)mPhiBoundariesOfSM[2 * i + 1]); } std::tuple<double, double> Geometry::GetPhiBoundariesOfSMGap(Int_t nPhiSec) const { - if (nPhiSec < 0 || nPhiSec > 5 + mnSupModInDCAL / 2 - 1) + if (nPhiSec < 0 || nPhiSec > 5 + mnSupModInDCAL / 2 - 1) { throw InvalidModuleException(nPhiSec, 5 + mnSupModInDCAL / 2); + } return std::make_tuple(mPhiBoundariesOfSM[2 * nPhiSec + 1], mPhiBoundariesOfSM[2 * nPhiSec + 2]); } diff --git a/Detectors/EMCAL/base/src/Hit.cxx b/Detectors/EMCAL/base/src/Hit.cxx index 3b681d19176f1..4a7f97581942b 100644 --- a/Detectors/EMCAL/base/src/Hit.cxx +++ b/Detectors/EMCAL/base/src/Hit.cxx @@ -23,8 +23,9 @@ void Hit::PrintStream(std::ostream& stream) const Bool_t Hit::operator<(const Hit& rhs) const { - if (GetTrackID() != rhs.GetTrackID()) + if (GetTrackID() != rhs.GetTrackID()) { return GetTrackID() < rhs.GetTrackID(); + } return GetDetectorID() < rhs.GetDetectorID(); } diff --git a/Detectors/EMCAL/base/src/Mapper.cxx b/Detectors/EMCAL/base/src/Mapper.cxx index 80eaf25a509f9..a5619a00a877e 100644 --- a/Detectors/EMCAL/base/src/Mapper.cxx +++ b/Detectors/EMCAL/base/src/Mapper.cxx @@ -59,8 +59,9 @@ void Mapper::init(const std::string_view filename) throw FileFormatException(e.what()); } - if (address > maxHardwareAddress) + if (address > maxHardwareAddress) { throw AddressRangeException(address, maxHardwareAddress); + } auto chantype = o2::emcal::intToChannelType(caloflag); @@ -73,22 +74,26 @@ void Mapper::init(const std::string_view filename) Mapper::ChannelID Mapper::getChannelID(int hardawareaddress) const { - if (!mInitStatus) + if (!mInitStatus) { throw InitStatusException(); + } auto res = mMapping.find(hardawareaddress); - if (res == mMapping.end()) + if (res == mMapping.end()) { throw AddressNotFoundException(hardawareaddress); + } return res->second; } int Mapper::getHardwareAddress(int row, int col, ChannelType_t channeltype) const { - if (!mInitStatus) + if (!mInitStatus) { throw InitStatusException(); + } ChannelID channelToFind{uint8_t(row), uint8_t(col), channeltype}; auto found = mInverseMapping.find(channelToFind); - if (found == mInverseMapping.end()) + if (found == mInverseMapping.end()) { throw ChannelNotFoundException(channelToFind); + } return found->second; } @@ -105,8 +110,9 @@ MappingHandler::MappingHandler() Mapper& MappingHandler::getMappingForDDL(int ddl) { - if (ddl > 40) + if (ddl > 40) { throw MappingHandler::DDLInvalid(ddl); + } const int NDDLSM = 2, NSIDES = 2; int ddlInSM = ddl % NDDLSM, sideID = (ddl / NDDLSM) % NSIDES; diff --git a/Detectors/EMCAL/base/src/RCUTrailer.cxx b/Detectors/EMCAL/base/src/RCUTrailer.cxx index 11e3a8313d57d..5e0e0c962a03f 100644 --- a/Detectors/EMCAL/base/src/RCUTrailer.cxx +++ b/Detectors/EMCAL/base/src/RCUTrailer.cxx @@ -38,15 +38,17 @@ void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payload reset(); int index = payloadwords.size(); auto word = payloadwords[--index]; - if ((word >> 30) != 3) + if ((word >> 30) != 3) { throw Error(Error::ErrorType_t::DECODING_INVALID, "Last RCU trailer word not found!"); + } mFirmwareVersion = (word >> 16) & 0xFF; mRCUId = (int)((word >> 7) & 0x1FF); int trailerSize = (word & 0x7F); - if (trailerSize < 2) + if (trailerSize < 2) { throw Error(Error::ErrorType_t::SIZE_INVALID, fmt::format("Invalid trailer size found (%d bytes) !", trailerSize * 4).data()); + } mTrailerSize = trailerSize; trailerSize -= 2; // Cut first and last trailer words as they are handled separately @@ -124,14 +126,15 @@ double RCUTrailer::getTimeSample() const void RCUTrailer::setTimeSample(double timesample) { int fq = 0; - if (std::abs(timesample - 50) < DBL_EPSILON) + if (std::abs(timesample - 50) < DBL_EPSILON) { fq = 0; - else if (std::abs(timesample - 100) < DBL_EPSILON) + } else if (std::abs(timesample - 100) < DBL_EPSILON) { fq = 1; - else if (std::abs(timesample - 200) < DBL_EPSILON) + } else if (std::abs(timesample - 200) < DBL_EPSILON) { fq = 2; - else + } else { throw Error(Error::ErrorType_t::SAMPLINGFREQ_INVALID, fmt::format("invalid time sample: %f", timesample).data()); + } mAltroCFG2 = (mAltroCFG2 & 0x1F) | fq << 5; } diff --git a/Detectors/EMCAL/base/src/ShishKebabTrd1Module.cxx b/Detectors/EMCAL/base/src/ShishKebabTrd1Module.cxx index eb8e254cf4c72..d33c456f0bf0c 100644 --- a/Detectors/EMCAL/base/src/ShishKebabTrd1Module.cxx +++ b/Detectors/EMCAL/base/src/ShishKebabTrd1Module.cxx @@ -39,11 +39,13 @@ ShishKebabTrd1Module::ShishKebabTrd1Module(Double_t theta, Geometry* g) { std::string_view sname = g->GetName(); Int_t key = 0; - if (sname.find("v1") != std::string::npos || sname.find("V1") != std::string::npos) + if (sname.find("v1") != std::string::npos || sname.find("V1") != std::string::npos) { key = 1; // EMCAL_COMPLETEV1 vs EMCAL_COMPLETEv1 (or other) + } - if (SetParameters()) + if (SetParameters()) { DefineFirstModule(key); + } // DefineName(mTheta); LOG(DEBUG4) << "o2::emcal::ShishKebabTrd1Module - first module key=" << key << ": theta " << std::setw(1) @@ -85,8 +87,9 @@ ShishKebabTrd1Module::ShishKebabTrd1Module(const ShishKebabTrd1Module& mod) mORB(mod.mORB), mORT(mod.mORT) { - for (Int_t i = 0; i < 3; i++) + for (Int_t i = 0; i < 3; i++) { mOK3X3[i] = mod.mOK3X3[i]; + } } void ShishKebabTrd1Module::Init(Double_t A, Double_t B) diff --git a/Detectors/EMCAL/base/test/testMapper.cxx b/Detectors/EMCAL/base/test/testMapper.cxx index 16731685057d0..78244510b9f8f 100644 --- a/Detectors/EMCAL/base/test/testMapper.cxx +++ b/Detectors/EMCAL/base/test/testMapper.cxx @@ -33,8 +33,9 @@ BOOST_AUTO_TEST_CASE(Mapper_test) const char* aliceO2env = std::getenv("O2_ROOT"); std::string inputDir = " "; - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/EMC/files/"; std::string mappingfile = inputDir + "RCU0A.data"; diff --git a/Detectors/EMCAL/calib/src/BadChannelMap.cxx b/Detectors/EMCAL/calib/src/BadChannelMap.cxx index 2f75ec34bd810..4fed9e4ec7cd6 100644 --- a/Detectors/EMCAL/calib/src/BadChannelMap.cxx +++ b/Detectors/EMCAL/calib/src/BadChannelMap.cxx @@ -48,12 +48,13 @@ void BadChannelMap::addBadChannel(unsigned short channelID, MaskType_t mask) BadChannelMap::MaskType_t BadChannelMap::getChannelStatus(unsigned short channelID) const { auto status = MaskType_t::GOOD_CELL; - if (mDeadCells.test(channelID)) + if (mDeadCells.test(channelID)) { status = MaskType_t::DEAD_CELL; - else if (mBadCells.test(channelID)) + } else if (mBadCells.test(channelID)) { status = MaskType_t::BAD_CELL; - else if (mWarmCells.test(channelID)) + } else if (mWarmCells.test(channelID)) { status = MaskType_t::WARM_CELL; + } return status; } @@ -71,12 +72,13 @@ TH2* BadChannelMap::getHistogramRepresentation() const for (size_t cellID = 0; cellID < mBadCells.size(); cellID++) { int value(0); - if (mBadCells.test(cellID)) + if (mBadCells.test(cellID)) { value = 1; - else if (mDeadCells.test(cellID)) + } else if (mDeadCells.test(cellID)) { value = 2; - else if (mWarmCells.test(cellID)) + } else if (mWarmCells.test(cellID)) { value = 3; + } if (value) { auto position = geo->GlobalRowColFromIndex(cellID); hist->Fill(std::get<1>(position), std::get<0>(position), value); @@ -90,18 +92,22 @@ BadChannelMap& BadChannelMap::operator+=(const BadChannelMap& rhs) for (size_t cellID = 0; cellID < mDeadCells.size(); cellID++) { if (rhs.mDeadCells.test(cellID)) { mDeadCells.set(cellID); - if (mBadCells.test(cellID)) + if (mBadCells.test(cellID)) { mBadCells.reset(cellID); - if (mWarmCells.test(cellID)) + } + if (mWarmCells.test(cellID)) { mWarmCells.reset(cellID); + } } if (rhs.mBadCells.test(cellID) && !mDeadCells.test(cellID)) { mBadCells.set(cellID); - if (mWarmCells.test(cellID)) + if (mWarmCells.test(cellID)) { mWarmCells.reset(cellID); + } } - if (rhs.mWarmCells.test(cellID) && !(mBadCells.test(cellID) || mDeadCells.test(cellID))) + if (rhs.mWarmCells.test(cellID) && !(mBadCells.test(cellID) || mDeadCells.test(cellID))) { mWarmCells.set(cellID); + } } return *this; } @@ -118,12 +124,15 @@ void BadChannelMap::PrintStream(std::ostream& stream) const stream << "Number of dead cells: " << mDeadCells.count() << "\n"; stream << "Number of warm cells: " << mWarmCells.count() << "\n"; for (size_t cellID = 0; cellID < mBadCells.size(); cellID++) { - if (mBadCells.test(cellID)) + if (mBadCells.test(cellID)) { stream << "Channel " << cellID << ": Bad cell\n"; - if (mDeadCells.test(cellID)) + } + if (mDeadCells.test(cellID)) { stream << "Channel " << cellID << ": Dead cell\n"; - if (mWarmCells.test(cellID)) + } + if (mWarmCells.test(cellID)) { stream << "Channel " << cellID << ": Warm cell\n"; + } } } diff --git a/Detectors/EMCAL/calib/src/CalibDB.cxx b/Detectors/EMCAL/calib/src/CalibDB.cxx index c86607a23c5c0..d845f9e1bcfdc 100644 --- a/Detectors/EMCAL/calib/src/CalibDB.cxx +++ b/Detectors/EMCAL/calib/src/CalibDB.cxx @@ -32,119 +32,140 @@ void CalibDB::init() void CalibDB::storeBadChannelMap(BadChannelMap* bcm, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFileAny(bcm, "EMC/BadChannelMap", metadata, rangestart, rangeend); } void CalibDB::storeTimeCalibParam(TimeCalibrationParams* tcp, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFileAny(tcp, "EMC/TimeCalibParams", metadata, rangestart, rangeend); } void CalibDB::storeTimeCalibParamL1Phase(TimeCalibParamL1Phase* tcp, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFileAny(tcp, "EMC/TimeCalibParamsL1Phase", metadata, rangestart, rangeend); } void CalibDB::storeTempCalibParam(TempCalibrationParams* tcp, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFileAny(tcp, "EMC/TempCalibParams", metadata, rangestart, rangeend); } void CalibDB::storeTempCalibParamSM(TempCalibParamSM* tcp, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFileAny(tcp, "EMC/TempCalibParamsSM", metadata, rangestart, rangeend); } void CalibDB::storeGainCalibFactors(GainCalibrationFactors* gcf, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFileAny(gcf, "EMC/GainCalibFactors", metadata, rangestart, rangeend); } void CalibDB::storeTriggerDCSData(TriggerDCS* dcs, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFileAny(dcs, "EMC/TriggerDCS", metadata, rangestart, rangeend); } BadChannelMap* CalibDB::readBadChannelMap(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } BadChannelMap* result = mCCDBManager.retrieveFromTFileAny<o2::emcal::BadChannelMap>("EMC/BadChannelMap", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "EMC/BadChannelMap", metadata, timestamp); + } return result; } TimeCalibrationParams* CalibDB::readTimeCalibParam(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } TimeCalibrationParams* result = mCCDBManager.retrieveFromTFileAny<o2::emcal::TimeCalibrationParams>("EMC/TimeCalibParams", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "EMC/TimeCalibParams", metadata, timestamp); + } return result; } TimeCalibParamL1Phase* CalibDB::readTimeCalibParamL1Phase(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } TimeCalibParamL1Phase* result = mCCDBManager.retrieveFromTFileAny<o2::emcal::TimeCalibParamL1Phase>("EMC/TimeCalibParamsL1Phase", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "EMC/TimeCalibParamsL1Phase", metadata, timestamp); + } return result; } TempCalibrationParams* CalibDB::readTempCalibParam(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } TempCalibrationParams* result = mCCDBManager.retrieveFromTFileAny<o2::emcal::TempCalibrationParams>("EMC/TempCalibParams", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "EMC/TempCalibParams", metadata, timestamp); + } return result; } TempCalibParamSM* CalibDB::readTempCalibParamSM(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } TempCalibParamSM* result = mCCDBManager.retrieveFromTFileAny<o2::emcal::TempCalibParamSM>("EMC/TempCalibParamsSM", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "EMC/TempCalibParamsSM", metadata, timestamp); + } return result; } GainCalibrationFactors* CalibDB::readGainCalibFactors(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } GainCalibrationFactors* result = mCCDBManager.retrieveFromTFileAny<o2::emcal::GainCalibrationFactors>("EMC/GainCalibFactors", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "EMC/GainCalibFactors", metadata, timestamp); + } return result; } TriggerDCS* CalibDB::readTriggerDCSData(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } TriggerDCS* result = mCCDBManager.retrieveFromTFileAny<o2::emcal::TriggerDCS>("EMC/TriggerDCS", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "EMC/TriggerDCS", metadata, timestamp); + } return result; } diff --git a/Detectors/EMCAL/calib/src/GainCalibrationFactors.cxx b/Detectors/EMCAL/calib/src/GainCalibrationFactors.cxx index 3b313728bb0fa..c80d8d2322909 100644 --- a/Detectors/EMCAL/calib/src/GainCalibrationFactors.cxx +++ b/Detectors/EMCAL/calib/src/GainCalibrationFactors.cxx @@ -33,8 +33,9 @@ TH1* GainCalibrationFactors::getHistogramRepresentation() const auto hist = new TH1F("GainCalibrationFactors", "GainCalibrationFactors", 17664, 0, 17664); hist->SetDirectory(nullptr); - for (std::size_t icell{0}; icell < mGainCalibFactors.size(); ++icell) + for (std::size_t icell{0}; icell < mGainCalibFactors.size(); ++icell) { hist->SetBinContent(icell + 1, mGainCalibFactors[icell]); + } return hist; } diff --git a/Detectors/EMCAL/calib/src/TempCalibParamSM.cxx b/Detectors/EMCAL/calib/src/TempCalibParamSM.cxx index f928ca00bbf2e..efdb51af0f57a 100644 --- a/Detectors/EMCAL/calib/src/TempCalibParamSM.cxx +++ b/Detectors/EMCAL/calib/src/TempCalibParamSM.cxx @@ -33,8 +33,9 @@ TH1* TempCalibParamSM::getHistogramRepresentation() const auto hist = new TH1F("TempCalibParamSM", "Temp Calibration Params per SM", 19, 0, 19); hist->SetDirectory(nullptr); - for (std::size_t iSM{0}; iSM < mTempCalibParamsPerSM.size(); ++iSM) + for (std::size_t iSM{0}; iSM < mTempCalibParamsPerSM.size(); ++iSM) { hist->SetBinContent(iSM + 1, mTempCalibParamsPerSM[iSM]); + } return hist; } diff --git a/Detectors/EMCAL/calib/src/TempCalibrationParams.cxx b/Detectors/EMCAL/calib/src/TempCalibrationParams.cxx index 8eda3530c9de0..6e2d97aace83d 100644 --- a/Detectors/EMCAL/calib/src/TempCalibrationParams.cxx +++ b/Detectors/EMCAL/calib/src/TempCalibrationParams.cxx @@ -40,8 +40,9 @@ TH1* TempCalibrationParams::getHistogramRepresentationSlope() const auto hist = new TH1F("TempCalibrationParamsSlope", "Temp Calibration Params Slope", 17664, 0, 17664); hist->SetDirectory(nullptr); - for (std::size_t icell{0}; icell < mTempCalibParamsSlope.size(); ++icell) + for (std::size_t icell{0}; icell < mTempCalibParamsSlope.size(); ++icell) { hist->SetBinContent(icell + 1, mTempCalibParamsSlope[icell]); + } return hist; } @@ -52,8 +53,9 @@ TH1* TempCalibrationParams::getHistogramRepresentationA0() const auto hist = new TH1F("TempCalibrationParamsA0", "Temp Calibration Params A0", 17664, 0, 17664); hist->SetDirectory(nullptr); - for (std::size_t icell{0}; icell < mTempCalibParamsA0.size(); ++icell) + for (std::size_t icell{0}; icell < mTempCalibParamsA0.size(); ++icell) { hist->SetBinContent(icell + 1, mTempCalibParamsA0[icell]); + } return hist; } diff --git a/Detectors/EMCAL/calib/src/TimeCalibParamL1Phase.cxx b/Detectors/EMCAL/calib/src/TimeCalibParamL1Phase.cxx index ec23a5804709b..27c5ef90629e9 100644 --- a/Detectors/EMCAL/calib/src/TimeCalibParamL1Phase.cxx +++ b/Detectors/EMCAL/calib/src/TimeCalibParamL1Phase.cxx @@ -33,8 +33,9 @@ TH1* TimeCalibParamL1Phase::getHistogramRepresentation() const auto hist = new TH1C("hL1PhaseShift", "L1PhaseShift", 19, 0, 19); hist->SetDirectory(nullptr); - for (std::size_t iSM{0}; iSM < mTimeCalibParamsL1Phase.size(); ++iSM) + for (std::size_t iSM{0}; iSM < mTimeCalibParamsL1Phase.size(); ++iSM) { hist->SetBinContent(iSM + 1, mTimeCalibParamsL1Phase[iSM] - '0'); + } return hist; } diff --git a/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx b/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx index 31624df6761cd..03de70b3c7427 100644 --- a/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx +++ b/Detectors/EMCAL/calib/src/TimeCalibrationParams.cxx @@ -20,18 +20,20 @@ using namespace o2::emcal; void TimeCalibrationParams::addTimeCalibParam(unsigned short cellID, short time, bool isLowGain) { - if (!isLowGain) + if (!isLowGain) { mTimeCalibParamsHG[cellID] = time; - else + } else { mTimeCalibParamsLG[cellID] = time; + } } short TimeCalibrationParams::getTimeCalibParam(unsigned short cellID, bool isLowGain) const { - if (isLowGain) + if (isLowGain) { return mTimeCalibParamsLG[cellID]; - else + } else { return mTimeCalibParamsHG[cellID]; + } } TH1* TimeCalibrationParams::getHistogramRepresentation(bool isLowGain) const @@ -41,16 +43,18 @@ TH1* TimeCalibrationParams::getHistogramRepresentation(bool isLowGain) const auto hist = new TH1S("TimeCalibrationParams", "Time Calibration Params HG", 17664, 0, 17664); hist->SetDirectory(nullptr); - for (std::size_t icell{0}; icell < mTimeCalibParamsHG.size(); ++icell) + for (std::size_t icell{0}; icell < mTimeCalibParamsHG.size(); ++icell) { hist->SetBinContent(icell + 1, mTimeCalibParamsHG[icell]); + } return hist; } else { auto hist = new TH1S("TimeCalibrationParams", "Time Calibration Params LG", 17664, 0, 17664); hist->SetDirectory(nullptr); - for (std::size_t icell{0}; icell < mTimeCalibParamsLG.size(); ++icell) + for (std::size_t icell{0}; icell < mTimeCalibParamsLG.size(); ++icell) { hist->SetBinContent(icell + 1, mTimeCalibParamsLG[icell]); + } return hist; } diff --git a/Detectors/EMCAL/calib/src/TriggerDCS.cxx b/Detectors/EMCAL/calib/src/TriggerDCS.cxx index 0b5074a64911b..57e7dcf302d53 100644 --- a/Detectors/EMCAL/calib/src/TriggerDCS.cxx +++ b/Detectors/EMCAL/calib/src/TriggerDCS.cxx @@ -58,8 +58,9 @@ std::string TriggerDCS::toJSON() const jsonstring << "mTRUArr:["; for (int ien = 0; ien < mTRUArr.size(); ien++) { jsonstring << "{\"TRU" << ien << "\":" << mTRUArr.at(ien).toJSON() << "}"; - if (ien != mTRUArr.size() - 1) + if (ien != mTRUArr.size() - 1) { jsonstring << ","; + } } jsonstring << "]}"; return jsonstring.str(); diff --git a/Detectors/EMCAL/calib/src/TriggerSTUErrorCounter.cxx b/Detectors/EMCAL/calib/src/TriggerSTUErrorCounter.cxx index 75d034ba2f900..38c92c0651eb5 100644 --- a/Detectors/EMCAL/calib/src/TriggerSTUErrorCounter.cxx +++ b/Detectors/EMCAL/calib/src/TriggerSTUErrorCounter.cxx @@ -39,10 +39,12 @@ bool TriggerSTUErrorCounter::isEqual(TriggerSTUErrorCounter& counter) const int TriggerSTUErrorCounter::compare(TriggerSTUErrorCounter& counter) const { - if (mTimeErrorCount.first > counter.mTimeErrorCount.first) + if (mTimeErrorCount.first > counter.mTimeErrorCount.first) { return 1; - if (mTimeErrorCount.first < counter.mTimeErrorCount.first) + } + if (mTimeErrorCount.first < counter.mTimeErrorCount.first) { return -1; + } return 0; } diff --git a/Detectors/EMCAL/calib/test/testBadChannelMap.cxx b/Detectors/EMCAL/calib/test/testBadChannelMap.cxx index 461bf10ac352c..51c896b588c4a 100644 --- a/Detectors/EMCAL/calib/test/testBadChannelMap.cxx +++ b/Detectors/EMCAL/calib/test/testBadChannelMap.cxx @@ -49,12 +49,15 @@ BOOST_AUTO_TEST_CASE(BadChannelMap_test) // the inner function (used in comparisons) a cell ID. auto refChannelCombined = [](const std::vector<unsigned short>& deadcells, const std::vector<unsigned short>& badcells, const std::vector<unsigned short>& warmcells) { return [&deadcells, &badcells, &warmcells](unsigned short cellID) { - if (std::find(deadcells.begin(), deadcells.end(), cellID) != deadcells.end()) + if (std::find(deadcells.begin(), deadcells.end(), cellID) != deadcells.end()) { return BadChannelMap::MaskType_t::DEAD_CELL; - if (std::find(badcells.begin(), badcells.end(), cellID) != badcells.end()) + } + if (std::find(badcells.begin(), badcells.end(), cellID) != badcells.end()) { return BadChannelMap::MaskType_t::BAD_CELL; - if (std::find(warmcells.begin(), warmcells.end(), cellID) != warmcells.end()) + } + if (std::find(warmcells.begin(), warmcells.end(), cellID) != warmcells.end()) { return BadChannelMap::MaskType_t::WARM_CELL; + } return BadChannelMap::MaskType_t::GOOD_CELL; }; }; @@ -115,12 +118,15 @@ BOOST_AUTO_TEST_CASE(BadChannelMap_test) filterBad(combinedWarm, combinedBad); filterBad(combinedWarm, combinedDead); filterBad(combinedBad, combinedDead); - for (auto bc : badLHC17o) + for (auto bc : badLHC17o) { lhc17omap.addBadChannel(bc, BadChannelMap::MaskType_t::BAD_CELL); - for (auto wc : warmLHC7o) + } + for (auto wc : warmLHC7o) { lhc17omap.addBadChannel(wc, BadChannelMap::MaskType_t::WARM_CELL); - for (auto dc : deadLHC17o) + } + for (auto dc : deadLHC17o) { lhc17omap.addBadChannel(dc, BadChannelMap::MaskType_t::DEAD_CELL); + } BadChannelMap summed(lhc17omap); summed += patterntest; auto getRefChannelTypeCombined = refChannelCombined(combinedDead, combinedBad, combinedWarm); @@ -143,12 +149,14 @@ BOOST_AUTO_TEST_CASE(BadChannelMap_test) std::vector<unsigned short> combineMaps(const std::vector<unsigned short>& list1, const std::vector<unsigned short> list2) { std::vector<unsigned short> combined; - for (auto l1 : list1) + for (auto l1 : list1) { combined.emplace_back(l1); + } for (auto l2 : list2) { auto found = std::find(combined.begin(), combined.end(), l2); - if (found == combined.end()) + if (found == combined.end()) { combined.emplace_back(l2); + } } std::sort(combined.begin(), combined.end(), std::less<>()); return combined; @@ -157,9 +165,11 @@ std::vector<unsigned short> combineMaps(const std::vector<unsigned short>& list1 void filterBad(std::vector<unsigned short> warmcells, const std::vector<unsigned short> badcells) { std::vector<unsigned short> todelete; - for (auto wc : warmcells) - if (std::find(badcells.begin(), badcells.end(), wc) != badcells.end()) + for (auto wc : warmcells) { + if (std::find(badcells.begin(), badcells.end(), wc) != badcells.end()) { todelete.emplace_back(wc); + } + } for (auto td : todelete) { auto it = std::find(warmcells.begin(), warmcells.end(), td); warmcells.erase(it); diff --git a/Detectors/EMCAL/calib/test/testGainCalibration.cxx b/Detectors/EMCAL/calib/test/testGainCalibration.cxx index 6a31a685b2c9b..4fcc49fd10ede 100644 --- a/Detectors/EMCAL/calib/test/testGainCalibration.cxx +++ b/Detectors/EMCAL/calib/test/testGainCalibration.cxx @@ -53,14 +53,16 @@ BOOST_AUTO_TEST_CASE(testGainCalibration) const char* aliceO2env = std::getenv("O2_ROOT"); std::string inputDir = " "; - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/EMC/files/"; std::string fileNameGainCalib = inputDir + "GainCalibrationFactors_LHC18q.txt"; std::ifstream fileGainCalib(fileNameGainCalib, std::ifstream::in); - if (!fileGainCalib.is_open()) + if (!fileGainCalib.is_open()) { std::cout << "The file GainCalibrationFactors_LHC18q was not opened\n"; + } float GainCalibFactors[17664]; @@ -78,16 +80,18 @@ BOOST_AUTO_TEST_CASE(testGainCalibration) icell++; } - for (unsigned short icell = 0; icell < 17664; icell++) + for (unsigned short icell = 0; icell < 17664; icell++) { BOOST_CHECK_EQUAL(parameter.getGainCalibFactors(icell), GainCalibFactors[icell]); + } // Writing to the other container which will be used for comparison GainCalibrationFactors parameterLHC15; std::string fileNameGainCalib_LHC15 = inputDir + "GainCalibrationFactors_LHC15.txt"; std::ifstream fileGainCalib_LHC15(fileNameGainCalib_LHC15, std::ifstream::in); - if (!fileGainCalib_LHC15.is_open()) + if (!fileGainCalib_LHC15.is_open()) { std::cout << "The file GainCalibrationFactors_LHC15 was not opened\n"; + } // Write to the container icell = 0; diff --git a/Detectors/EMCAL/calib/test/testTempCalibration.cxx b/Detectors/EMCAL/calib/test/testTempCalibration.cxx index 96800113a30bf..dcd9488510987 100644 --- a/Detectors/EMCAL/calib/test/testTempCalibration.cxx +++ b/Detectors/EMCAL/calib/test/testTempCalibration.cxx @@ -54,14 +54,16 @@ BOOST_AUTO_TEST_CASE(testTempCalibration) const char* aliceO2env = std::getenv("O2_ROOT"); std::string inputDir = " "; - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/EMC/files/"; std::string file = inputDir + "TempCalibCoeff.txt"; std::ifstream fileTemp(file, std::ifstream::in); - if (!fileTemp.is_open()) + if (!fileTemp.is_open()) { std::cout << "The file TempCalibCoeff was not opened\n"; + } float Slope[17664], A0[17664]; @@ -89,8 +91,9 @@ BOOST_AUTO_TEST_CASE(testTempCalibration) std::string fileLHC17 = inputDir + "TempCalibCoeff_LHC17.txt"; std::ifstream fileTempLHC17(fileLHC17, std::ifstream::in); - if (!fileTempLHC17.is_open()) + if (!fileTempLHC17.is_open()) { std::cout << "The file TempCalibCoeff_LHC17 was not opened\n"; + } float Slope_LHC17, A0_LHC17; diff --git a/Detectors/EMCAL/calib/test/testTempCalibrationSM.cxx b/Detectors/EMCAL/calib/test/testTempCalibrationSM.cxx index 06f5b18cf6efc..0f087bf12123d 100644 --- a/Detectors/EMCAL/calib/test/testTempCalibrationSM.cxx +++ b/Detectors/EMCAL/calib/test/testTempCalibrationSM.cxx @@ -49,14 +49,16 @@ BOOST_AUTO_TEST_CASE(testTempCalibrationSM) const char* aliceO2env = std::getenv("O2_ROOT"); std::string inputDir = " "; - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/EMC/files/"; std::string file = inputDir + "TempCalibSM_LHC18k_289166.txt"; std::ifstream fileTempCalibSM(file, std::ifstream::in); - if (!fileTempCalibSM.is_open()) + if (!fileTempCalibSM.is_open()) { std::cout << "The file TempCalibSM_LHC18k_289166.txt was not opened\n"; + } float TempCalibSM[20]; @@ -72,8 +74,9 @@ BOOST_AUTO_TEST_CASE(testTempCalibrationSM) iSM++; } - for (unsigned short ism = 0; ism < 20; ism++) + for (unsigned short ism = 0; ism < 20; ism++) { BOOST_CHECK_EQUAL(parameter.getTempCalibParamPerSM(ism), TempCalibSM[ism]); + } // Comparison test @@ -82,8 +85,9 @@ BOOST_AUTO_TEST_CASE(testTempCalibrationSM) std::string fileLHC18k = inputDir + "TempCalibSM_LHC18k_289201.txt"; std::ifstream fileTempCalibSM_LHC18k(fileLHC18k, std::ifstream::in); - if (!fileTempCalibSM_LHC18k.is_open()) + if (!fileTempCalibSM_LHC18k.is_open()) { std::cout << "The file TempCalibSM_LHC18k_289201.txt was not opened\n"; + } unsigned char TempCalibSM_LHC18k; diff --git a/Detectors/EMCAL/calib/test/testTimeCalibration.cxx b/Detectors/EMCAL/calib/test/testTimeCalibration.cxx index 357dc2f0e34e0..63e5ac314b8db 100644 --- a/Detectors/EMCAL/calib/test/testTimeCalibration.cxx +++ b/Detectors/EMCAL/calib/test/testTimeCalibration.cxx @@ -57,27 +57,31 @@ BOOST_AUTO_TEST_CASE(testTimeCalibration) const char* aliceO2env = std::getenv("O2_ROOT"); std::string inputDir = " "; - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/EMC/files/"; std::string fileHG = inputDir + "TimeCalibCoeffHG.txt"; std::ifstream allTimeAvHG(fileHG, std::ifstream::in); - if (!allTimeAvHG.is_open()) + if (!allTimeAvHG.is_open()) { std::cout << "The file TimeCalibCoeffHG was not opened\n"; + } std::string fileLG = inputDir + "TimeCalibCoeffLG.txt"; std::ifstream allTimeAvLG(fileLG, std::ifstream::in); - if (!allTimeAvLG.is_open()) + if (!allTimeAvLG.is_open()) { std::cout << "The file TimeCalibCoeffLG was not opened\n"; + } unsigned short TimeHG[17664], TimeLG[17664]; unsigned short icell = 0; while (1) { allTimeAvHG >> TimeHG[icell]; - if (!allTimeAvHG.good()) + if (!allTimeAvHG.good()) { break; + } parameter.addTimeCalibParam(icell, TimeHG[icell], 0); //HG icell++; } @@ -85,8 +89,9 @@ BOOST_AUTO_TEST_CASE(testTimeCalibration) icell = 0; while (1) { allTimeAvLG >> TimeLG[icell]; - if (!allTimeAvLG.good()) + if (!allTimeAvLG.good()) { break; + } parameter.addTimeCalibParam(icell, TimeLG[icell], 1); //LG icell++; } @@ -102,21 +107,24 @@ BOOST_AUTO_TEST_CASE(testTimeCalibration) std::string fileHG_LHC17g = inputDir + "TimeCalibCoeffHG_LHC17g.txt"; std::ifstream allTimeAvHG_LHC17g(fileHG_LHC17g, std::ifstream::in); - if (!allTimeAvHG_LHC17g.is_open()) + if (!allTimeAvHG_LHC17g.is_open()) { std::cout << "The file TimeCalibCoeffHG_LHC17g was not opened\n"; + } std::string fileLG_LHC17g = inputDir + "TimeCalibCoeffLG_LHC17g.txt"; std::ifstream allTimeAvLG_LHC17g(fileLG_LHC17g, std::ifstream::in); - if (!allTimeAvLG_LHC17g.is_open()) + if (!allTimeAvLG_LHC17g.is_open()) { std::cout << "The file TimeCalibCoeffLG_LHC17g was not opened\n"; + } unsigned short TimeHG_LHC17g, TimeLG_LHC17g; icell = 0; while (0) { allTimeAvHG_LHC17g >> TimeHG_LHC17g; - if (!allTimeAvHG_LHC17g.good()) + if (!allTimeAvHG_LHC17g.good()) { break; + } parameterLHC17g.addTimeCalibParam(icell, TimeHG_LHC17g, 0); //HG icell++; } @@ -124,8 +132,9 @@ BOOST_AUTO_TEST_CASE(testTimeCalibration) icell = 0; while (0) { allTimeAvLG_LHC17g >> TimeLG_LHC17g; - if (!allTimeAvLG_LHC17g.good()) + if (!allTimeAvLG_LHC17g.good()) { break; + } parameterLHC17g.addTimeCalibParam(icell, TimeLG_LHC17g, 1); //LG icell++; } diff --git a/Detectors/EMCAL/calib/test/testTimeL1PhaseCalib.cxx b/Detectors/EMCAL/calib/test/testTimeL1PhaseCalib.cxx index 5199d8d4e6e9e..cbe13ae87d6b2 100644 --- a/Detectors/EMCAL/calib/test/testTimeL1PhaseCalib.cxx +++ b/Detectors/EMCAL/calib/test/testTimeL1PhaseCalib.cxx @@ -49,14 +49,16 @@ BOOST_AUTO_TEST_CASE(testTimeL1PhaseCalib) const char* aliceO2env = std::getenv("O2_ROOT"); std::string inputDir = " "; - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/EMC/files/"; std::string file = inputDir + "TimeL1Phase_LHC18q_295585.txt"; std::ifstream fileL1Phase(file, std::ifstream::in); - if (!fileL1Phase.is_open()) + if (!fileL1Phase.is_open()) { std::cout << "The file TimeL1Phase_LHC18q_295585 was not opened\n"; + } unsigned char L1Phase[20]; @@ -72,8 +74,9 @@ BOOST_AUTO_TEST_CASE(testTimeL1PhaseCalib) iSM++; } - for (unsigned short iSM = 0; iSM < 20; iSM++) + for (unsigned short iSM = 0; iSM < 20; iSM++) { BOOST_CHECK_EQUAL(parameter.getTimeCalibParamL1Phase(iSM), L1Phase[iSM]); + } // Comparison test @@ -82,8 +85,9 @@ BOOST_AUTO_TEST_CASE(testTimeL1PhaseCalib) std::string fileLHC18q = inputDir + "TimeL1Phase_LHC18q_296623.txt"; std::ifstream fileL1PhaseLHC18q(fileLHC18q, std::ifstream::in); - if (!fileL1PhaseLHC18q.is_open()) + if (!fileL1PhaseLHC18q.is_open()) { std::cout << "The file TimeL1Phase_LHC18q_296623 was not opened\n"; + } unsigned char L1Phase_LHC18q; diff --git a/Detectors/EMCAL/calib/test/testTriggerDCS.cxx b/Detectors/EMCAL/calib/test/testTriggerDCS.cxx index e784b9ab5b6f2..8dee30ac50ef3 100644 --- a/Detectors/EMCAL/calib/test/testTriggerDCS.cxx +++ b/Detectors/EMCAL/calib/test/testTriggerDCS.cxx @@ -62,8 +62,9 @@ void ConfigureReferenceSTU(TriggerSTUDCS& testobject) testobject.setFw(0x2A012); testobject.setMedianMode(0); testobject.setRegion(0xffffffff); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { testobject.setPHOSScale(i, 0); + } } BOOST_AUTO_TEST_CASE(TriggerDCS_test) diff --git a/Detectors/EMCAL/calib/test/testTriggerSTUDCS.cxx b/Detectors/EMCAL/calib/test/testTriggerSTUDCS.cxx index f3b6cba8f09fb..b1c6884cfd1d2 100644 --- a/Detectors/EMCAL/calib/test/testTriggerSTUDCS.cxx +++ b/Detectors/EMCAL/calib/test/testTriggerSTUDCS.cxx @@ -44,8 +44,9 @@ void ConfigureReference(TriggerSTUDCS& testobject) testobject.setFw(0x2A012); testobject.setMedianMode(0); testobject.setRegion(0xffffffff); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { testobject.setPHOSScale(i, 0); + } } BOOST_AUTO_TEST_CASE(TriggerSTUDCS_test) diff --git a/Detectors/EMCAL/calib/test/testTriggerTRUDCS.cxx b/Detectors/EMCAL/calib/test/testTriggerTRUDCS.cxx index db234e69b4952..9c2c3f74027dc 100644 --- a/Detectors/EMCAL/calib/test/testTriggerTRUDCS.cxx +++ b/Detectors/EMCAL/calib/test/testTriggerTRUDCS.cxx @@ -63,8 +63,9 @@ BOOST_AUTO_TEST_CASE(TriggerTRUDCS_test) BOOST_CHECK_EQUAL(testobject.getGTHRL0(), GTHRL0); BOOST_CHECK_EQUAL(testobject.getRLBKSTU(), RLBKSTU); - for (int ireg = 0; ireg < 6; ireg++) + for (int ireg = 0; ireg < 6; ireg++) { BOOST_CHECK_EQUAL(testobject.getMaskReg(ireg), MaskReg[ireg]); + } BOOST_CHECK_EQUAL(testobject.getFw(), Fw); diff --git a/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx b/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx index 69daeafbdf80b..badb7c785292d 100644 --- a/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx +++ b/Detectors/EMCAL/reconstruction/run/rawReaderFile.cxx @@ -94,8 +94,9 @@ int main(int argc, char** argv) while (parser.hasNext()) { parser.next(); // Exclude STU DDLs - if (o2::raw::RDHUtils::getFEEID(parser.getRawHeader()) >= 40) + if (o2::raw::RDHUtils::getFEEID(parser.getRawHeader()) >= 40) { continue; + } o2::emcal::AltroDecoder decoder(parser); decoder.decode(); diff --git a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx index 1d1eca3495ccc..20f8b16b3651d 100644 --- a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx @@ -94,14 +94,16 @@ void AltroDecoder::readChannels() const RCUTrailer& AltroDecoder::getRCUTrailer() const { - if (!mRCUTrailer.isInitialized()) + if (!mRCUTrailer.isInitialized()) { throw AltroDecoderError(AltroDecoderError::ErrorType_t::RCU_TRAILER_ERROR, "RCU trailer was not initialized"); + } return mRCUTrailer; } const std::vector<Channel>& AltroDecoder::getChannels() const { - if (!mChannelsInitialized) + if (!mChannelsInitialized) { throw AltroDecoderError(AltroDecoderError::ErrorType_t::CHANNEL_ERROR, "Channels not initizalized"); + } return mChannels; } \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/src/Bunch.cxx b/Detectors/EMCAL/reconstruction/src/Bunch.cxx index 1211a1852409c..fea2cd3da982c 100644 --- a/Detectors/EMCAL/reconstruction/src/Bunch.cxx +++ b/Detectors/EMCAL/reconstruction/src/Bunch.cxx @@ -13,6 +13,7 @@ using namespace o2::emcal; void Bunch::initFromRange(gsl::span<uint16_t> adcs) { - for (auto adcval : adcs) + for (auto adcval : adcs) { mADC.emplace_back(adcval); + } } \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/src/CaloRawFitter.cxx b/Detectors/EMCAL/reconstruction/src/CaloRawFitter.cxx index 6748b6246ed81..7e14fe7b56eab 100644 --- a/Detectors/EMCAL/reconstruction/src/CaloRawFitter.cxx +++ b/Detectors/EMCAL/reconstruction/src/CaloRawFitter.cxx @@ -90,10 +90,12 @@ std::tuple<int, int> CaloRawFitter::selectSubarray(const gsl::span<double> data, // we keep one pre- or post- sample if we can (as in online) // check though if we ended up on a 'jump', or out of bounds: if so, back up - if (firstJump || tmpfirst < 0) + if (firstJump || tmpfirst < 0) { tmpfirst++; - if (lastJump || tmplast >= data.size()) + } + if (lastJump || tmplast >= data.size()) { tmplast--; + } first = tmpfirst; last = tmplast; @@ -266,8 +268,9 @@ std::tuple<int, int, float, short, short, float, int, int> CaloRawFitter::preFit for (int i = 0; i < length; i++) { mReversed[i] = sig[length - i - 1] - ped; - if (maxf < mReversed[i]) + if (maxf < mReversed[i]) { maxf = mReversed[i]; + } } if (maxf >= acut) // possibly significant signal diff --git a/Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx b/Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx index c587f461bd1a5..9fce37c26a2a6 100755 --- a/Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx +++ b/Detectors/EMCAL/reconstruction/src/CaloRawFitterGamma2.cxx @@ -94,10 +94,12 @@ std::tuple<float, bool> CaloRawFitterGamma2::doFit_1peak(int firstTimeBin, int n float chi2(0.); // fit using gamma-2 function (ORDER =2 assumed) - if (nSamples < 3) + if (nSamples < 3) { return std::make_tuple(chi2, false); - if (mNiter > mNiterationsMax) + } + if (mNiter > mNiterationsMax) { return std::make_tuple(chi2, false); + } double D, dA, dt; double c11 = 0; @@ -112,8 +114,9 @@ std::tuple<float, bool> CaloRawFitterGamma2::doFit_1peak(int firstTimeBin, int n for (int itbin = 0; itbin < nSamples; itbin++) { double ti = (itbin - time) / constants::TAU; - if ((ti + 1) < 0) + if ((ti + 1) < 0) { continue; + } double g_1i = (ti + 1) * TMath::Exp(-2 * ti); double g_i = (ti + 1) * g_1i; @@ -132,8 +135,9 @@ std::tuple<float, bool> CaloRawFitterGamma2::doFit_1peak(int firstTimeBin, int n D = c11 * c22 - c12 * c21; - if (TMath::Abs(D) < DBL_EPSILON) + if (TMath::Abs(D) < DBL_EPSILON) { return std::make_tuple(chi2, false); + } dt = (d1 * c22 - d2 * c12) / D * constants::TAU; dA = (d1 * c21 - d2 * c11) / D; @@ -143,8 +147,9 @@ std::tuple<float, bool> CaloRawFitterGamma2::doFit_1peak(int firstTimeBin, int n bool res = true; - if (TMath::Abs(dA) > 1 || TMath::Abs(dt) > 0.01) + if (TMath::Abs(dA) > 1 || TMath::Abs(dt) > 0.01) { std::tie(chi2, res) = doFit_1peak(firstTimeBin, nSamples, ampl, time); + } return std::make_tuple(chi2, res); } diff --git a/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx b/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx index 8523ad353a87b..102185633b6de 100644 --- a/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx +++ b/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx @@ -40,10 +40,11 @@ double CaloRawFitterStandard::rawResponseFunction(double* x, double* par) double ped = par[4]; double xx = (x[0] - par[1] + tau) / tau; - if (xx <= 0) + if (xx <= 0) { signal = ped; - else + } else { signal = ped + par[0] * TMath::Power(xx, n) * TMath::Exp(n * (1 - xx)); + } return signal; } @@ -105,8 +106,9 @@ std::tuple<float, float, float, bool> CaloRawFitterStandard::fitRaw(int firstTim int nsamples = lastTimeBin - firstTimeBin + 1; fitDone = kFALSE; - if (nsamples < 3) + if (nsamples < 3) { return std::make_tuple(amp, time, chi2, fitDone); + } TGraph gSig(nsamples); @@ -133,8 +135,9 @@ std::tuple<float, float, float, bool> CaloRawFitterStandard::fitRaw(int firstTim time = signalF.GetParameter(1); chi2 = signalF.GetChisquare(); fitDone = kTRUE; - } else + } else { fitDone = kFALSE; + } return std::make_tuple(amp, time, chi2, fitDone); } diff --git a/Detectors/EMCAL/reconstruction/src/Channel.cxx b/Detectors/EMCAL/reconstruction/src/Channel.cxx index 616067bc79558..bdd79ee9d39b5 100644 --- a/Detectors/EMCAL/reconstruction/src/Channel.cxx +++ b/Detectors/EMCAL/reconstruction/src/Channel.cxx @@ -13,29 +13,33 @@ using namespace o2::emcal; int Channel::getBranchIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return ((mHardwareAddress >> 11) & 0x1); } int Channel::getFECIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return ((mHardwareAddress >> 7) & 0xF); } Int_t Channel::getAltroIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return ((mHardwareAddress >> 4) & 0x7); } Int_t Channel::getChannelIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return (mHardwareAddress & 0xF); } diff --git a/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx b/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx index 1da3635891218..fd79bcfe088a4 100644 --- a/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawBuffer.cxx @@ -61,14 +61,16 @@ void RawBuffer::readFromMemoryBuffer(const gsl::span<const char> rawmemory) uint32_t RawBuffer::getWord(int index) const { - if (index >= mNDataWords) + if (index >= mNDataWords) { throw std::runtime_error("Index out of range"); + } return mDataWords[index]; } uint32_t RawBuffer::getNextDataWord() { - if (!hasNext()) + if (!hasNext()) { throw std::runtime_error("No more data words in buffer"); + } return mDataWords[mCurrentDataWord++]; } diff --git a/Detectors/EMCAL/reconstruction/src/RawPayload.cxx b/Detectors/EMCAL/reconstruction/src/RawPayload.cxx index a6bd1801c2561..b28e49bf50bb2 100644 --- a/Detectors/EMCAL/reconstruction/src/RawPayload.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawPayload.cxx @@ -15,14 +15,16 @@ using namespace o2::emcal; RawPayload::RawPayload(gsl::span<const uint32_t> payloadwords, int numpages) : mPayloadWords(payloadwords.size()), mNumberOfPages(numpages) { - for (auto word : payloadwords) + for (auto word : payloadwords) { mPayloadWords.emplace_back(word); + } } void RawPayload::appendPayloadWords(const gsl::span<const uint32_t> payloadwords) { - for (auto word : payloadwords) + for (auto word : payloadwords) { mPayloadWords.emplace_back(word); + } } void RawPayload::reset() diff --git a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx index 859b8454d1a1f..dcce7d20298d0 100644 --- a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx @@ -70,10 +70,12 @@ void RawReaderMemory::next() auto nextpagecounter = RDHDecoder::getPageCounter(nextheader); if (nextpagecounter == 0) { isDataTerminated = true; - } else + } else { isDataTerminated = false; - } else + } + } else { isDataTerminated = true; + } // Check if the data continues } while (!isDataTerminated); // add combined trailer to payload @@ -82,10 +84,12 @@ void RawReaderMemory::next() void RawReaderMemory::nextPage(bool doResetPayload) { - if (!hasNext()) + if (!hasNext()) { throw RawDecodingError(RawDecodingError::ErrorType_t::PAGE_NOTFOUND); - if (doResetPayload) + } + if (doResetPayload) { mRawPayload.reset(); + } mRawHeaderInitialized = false; mPayloadInitialized = false; // Read header @@ -131,8 +135,9 @@ void RawReaderMemory::nextPage(bool doResetPayload) void RawReaderMemory::readPage(int page) { int currentposition = 8192 * page; - if (currentposition >= mRawMemoryBuffer.size()) + if (currentposition >= mRawMemoryBuffer.size()) { throw RawDecodingError(RawDecodingError::ErrorType_t::PAGE_NOTFOUND); + } mRawHeaderInitialized = false; mPayloadInitialized = false; // Read header @@ -152,14 +157,16 @@ void RawReaderMemory::readPage(int page) const o2::header::RDHAny& RawReaderMemory::getRawHeader() const { - if (!mRawHeaderInitialized) + if (!mRawHeaderInitialized) { throw RawDecodingError(RawDecodingError::ErrorType_t::HEADER_INVALID); + } return mRawHeader; } const RawBuffer& RawReaderMemory::getRawBuffer() const { - if (!mPayloadInitialized) + if (!mPayloadInitialized) { throw RawDecodingError(RawDecodingError::ErrorType_t::PAYLOAD_INVALID); + } return mRawBuffer; } diff --git a/Detectors/EMCAL/simulation/src/Detector.cxx b/Detectors/EMCAL/simulation/src/Detector.cxx index 575a5c7670608..b6720fcd34844 100644 --- a/Detectors/EMCAL/simulation/src/Detector.cxx +++ b/Detectors/EMCAL/simulation/src/Detector.cxx @@ -196,8 +196,9 @@ Bool_t Detector::ProcessHits(FairVolume* v) LOG(DEBUG4) << "We are in sensitive volume " << v->GetName() << ": " << fMC->CurrentVolPath() << std::endl; // TODO Implement handling of parents and primary particle Double_t eloss = fMC->Edep(); - if (eloss < DBL_EPSILON) + if (eloss < DBL_EPSILON) { return false; // only process hits which actually deposit some energy in the EMCAL + } Geometry* geom = GetGeometry(); // Obtain detector ID // This is not equal to the volume ID of the fair volume @@ -415,10 +416,11 @@ void Detector::CreateEmcalEnvelope() envelopA[2] = 20; CreateEMCALVolume(geom->GetNameOfEMCALEnvelope(), "BOX", ID_SC, envelopA, 3); - for (Int_t i = 0; i < 3; i++) + for (Int_t i = 0; i < 3; i++) { // Position the EMCAL Mother Volume (XEN1) in WSUC. // Look to AliEMCALWsuCosmicRaySetUp. TVirtualMC::GetMC()->Gspos(geom->GetNameOfEMCALEnvelope(), 1, "WSUC", 0.0, 0.0, +265., rotMatrixID, "ONLY"); + } } else { Double_t envelopA[10]; envelopA[0] = geom->GetArm1PhiMin(); // minimum phi angle @@ -508,8 +510,9 @@ void Detector::CreateShiskebabGeometry() Double_t parSCM0[5] = {0, 0, 0, 0}, *dummy = nullptr, parTRAP[11]; if (!contains(gn, "V1")) { Double_t wallThickness = g->GetPhiModuleSize() / g->GetNPHIdiv() - g->GetPhiTileSize(); - for (Int_t i = 0; i < 3; i++) + for (Int_t i = 0; i < 3; i++) { parSCM0[i] = mParEMOD[i] - wallThickness; + } parSCM0[3] = mParEMOD[3]; CreateEMCALVolume("SCM0", "TRD1", ID_AIR, parSCM0, 4); TVirtualMC::GetMC()->Gspos("SCM0", 1, "EMOD", 0., 0., 0., 0, "ONLY"); @@ -840,8 +843,9 @@ void Detector::CreateSupermoduleGeometry(const std::string_view mother) if (smodnum % 2 == 1) { phiy += 180.; - if (phiy >= 360.) + if (phiy >= 360.) { phiy -= 360.; + } phiz = 180.; zpos *= -1.; } @@ -921,8 +925,9 @@ void Detector::CreateEmcalModuleGeometry(const std::string_view mother, const st } else if (mother == "DCEXT") { iyMax /= 3; } else if (mother == "DCSM") { - if (iz < 8) + if (iz < 8) { continue; //!!!DCSM from 8th to 23th + } zpos = mod.GetPosZ() - mSmodPar2 - g->GetDCALInnerEdge() / 2.; } else if (mother.compare("SMOD")) { LOG(ERROR) << "Unknown super module Type!!"; diff --git a/Detectors/EMCAL/simulation/src/Digitizer.cxx b/Detectors/EMCAL/simulation/src/Digitizer.cxx index 39b548c52e75a..3282094477e97 100644 --- a/Detectors/EMCAL/simulation/src/Digitizer.cxx +++ b/Detectors/EMCAL/simulation/src/Digitizer.cxx @@ -121,8 +121,9 @@ void Digitizer::process(const std::vector<Hit>& hits) } MCLabel label(hit.GetTrackID(), mCurrEvID, mCurrSrcID, false, 1.0); - if (digit.getAmplitude() == 0) + if (digit.getAmplitude() == 0) { label.setAmplitudeFraction(0); + } LabeledDigit d(digit, label); mDigits[id].push_back(d); } @@ -235,12 +236,15 @@ void Digitizer::fillOutputContainer(std::vector<Digit>& digits, o2::dataformats: addNoiseDigits(ld1); } - if (mRemoveDigitsBelowThreshold && (ld1.getAmplitude() < mSimParam->getDigitThreshold() * (constants::EMCAL_ADCENERGY))) + if (mRemoveDigitsBelowThreshold && (ld1.getAmplitude() < mSimParam->getDigitThreshold() * (constants::EMCAL_ADCENERGY))) { continue; - if (ld1.getAmplitude() < 0) + } + if (ld1.getAmplitude() < 0) { continue; - if (ld1.getTimeStamp() >= mSimParam->getLiveTime()) + } + if (ld1.getTimeStamp() >= mSimParam->getLiveTime()) { continue; + } l.push_back(ld1); } diff --git a/Detectors/EMCAL/simulation/src/DigitizerTask.cxx b/Detectors/EMCAL/simulation/src/DigitizerTask.cxx index ae990751ea6bd..94b3e8a58e8eb 100644 --- a/Detectors/EMCAL/simulation/src/DigitizerTask.cxx +++ b/Detectors/EMCAL/simulation/src/DigitizerTask.cxx @@ -72,8 +72,9 @@ void DigitizerTask::Exec(Option_t* option) { FairRootManager* mgr = FairRootManager::Instance(); - if (mDigitsArray) + if (mDigitsArray) { mDigitsArray->clear(); + } mDigitizer.setEventTime(mgr->GetEventTime()); LOG(DEBUG) << "Running digitization on new event " << mEventID << " from source " << mSourceID; @@ -92,8 +93,9 @@ void DigitizerTask::FinishTask() // finalize digitization, if needed, flash remaining digits FairRootManager* mgr = FairRootManager::Instance(); mgr->SetLastFill(kTRUE); /// necessary, otherwise the data is not written out - if (mDigitsArray) + if (mDigitsArray) { mDigitsArray->clear(); + } // mDigitizer.fillOutputContainer(mDigitsArray); mDigitizer.finish(); } diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index b4c6d3b202b4b..674ba68aa408d 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -39,10 +39,11 @@ void RawWriter::init() break; case FileFor_t::kSubDet: { std::string detstring; - if (iddl < 22) + if (iddl < 22) { detstring = "emcal"; - else + } else { detstring = "dcal"; + } rawfilename += fmt::format("/{:s}.raw", detstring.data()); break; }; @@ -52,8 +53,9 @@ void RawWriter::init() mRawWriter->registerLink(iddl, crorc, link, 0, rawfilename.data()); } // initialize mappers - if (!mMappingHandler) + if (!mMappingHandler) { mMappingHandler = std::make_unique<o2::emcal::MappingHandler>(); + } // initialize containers for SRU for (auto isru = 0; isru < 40; isru++) { @@ -73,16 +75,18 @@ void RawWriter::digitsToRaw(gsl::span<o2::emcal::Digit> digitsbranch, gsl::span< bool RawWriter::processTrigger(const o2::emcal::TriggerRecord& trg) { - for (auto srucont : mSRUdata) + for (auto srucont : mSRUdata) { srucont.mChannels.clear(); + } std::vector<o2::emcal::Digit*>* bunchDigits; int lasttower = -1; for (auto& dig : gsl::span(mDigits.data() + trg.getFirstEntry(), trg.getNumberOfObjects())) { auto tower = dig.getTower(); if (tower != lasttower) { lasttower = tower; - if (tower > 20000) + 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); @@ -137,8 +141,9 @@ bool RawWriter::processTrigger(const o2::emcal::TriggerRecord& trg) // Create RCU trailer auto trailerwords = createRCUTrailer(payload.size() / 4, 16, 16, 100., 0.); - for (auto word : trailerwords) + for (auto word : trailerwords) { payload.emplace_back(word); + } // register output data auto ddlid = srucont.mSRUid; @@ -178,8 +183,9 @@ std::vector<AltroBunch> RawWriter::findBunches(const std::vector<o2::emcal::Digi currentBunch->mADCs.emplace_back(adc); } // if we have a last bunch set time start time to the time bin of teh previous digit - if (currentBunch) + if (currentBunch) { currentBunch->mStarttime = itime + 1; + } return result; } @@ -192,16 +198,18 @@ std::tuple<int, int, int> RawWriter::getOnlineID(int towerID) int row = std::get<0>(etaphishift), col = std::get<1>(etaphishift); int ddlInSupermoudel = -1; - if (0 <= row && row < 8) + if (0 <= row && row < 8) { ddlInSupermoudel = 0; // first cable row - else if (8 <= row && row < 16 && 0 <= col && col < 24) + } else if (8 <= row && row < 16 && 0 <= col && col < 24) { ddlInSupermoudel = 0; // first half; - else if (8 <= row && row < 16 && 24 <= col && col < 48) + } else if (8 <= row && row < 16 && 24 <= col && col < 48) { ddlInSupermoudel = 1; // second half; - else if (16 <= row && row < 24) + } else if (16 <= row && row < 24) { ddlInSupermoudel = 1; // third cable row - if (supermoduleID % 2 == 1) + } + if (supermoduleID % 2 == 1) { ddlInSupermoudel = 1 - ddlInSupermoudel; // swap for odd=C side, to allow us to cable both sides the same + } return std::make_tuple(supermoduleID * 2 + ddlInSupermoudel, row, col); } diff --git a/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx index dbaefad219773..b6fbc65ea37dc 100644 --- a/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/CellConverterSpec.cxx @@ -41,14 +41,15 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) gsl::span<const o2::emcal::Digit> digits(digitsAll.data() + trg.getFirstEntry(), trg.getNumberOfObjects()); for (const auto& dig : digits) { ChannelType_t chantype; - if (dig.getHighGain()) + if (dig.getHighGain()) { chantype = ChannelType_t::HIGH_GAIN; - else if (dig.getLowGain()) + } else if (dig.getLowGain()) { chantype = ChannelType_t::LOW_GAIN; - else if (dig.getTRU()) + } else if (dig.getTRU()) { chantype = ChannelType_t::TRU; - else if (dig.getLEDMon()) + } else if (dig.getLEDMon()) { chantype = ChannelType_t::LEDMON; + } mOutputCells.emplace_back(dig.getTower(), dig.getEnergy(), dig.getTimeStamp(), chantype); ncellsTrigger++; } diff --git a/Detectors/EMCAL/workflow/src/DigitsPrinterSpec.cxx b/Detectors/EMCAL/workflow/src/DigitsPrinterSpec.cxx index 1cf7daf767682..df0131cc53e28 100644 --- a/Detectors/EMCAL/workflow/src/DigitsPrinterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/DigitsPrinterSpec.cxx @@ -36,11 +36,11 @@ void DigitsPrinterSpec<InputType>::run(framework::ProcessingContext& pc) // Get the EMCAL block header and check whether it contains digits LOG(DEBUG) << "[EMCALDigitsPrinter - process] called"; std::string objectbranch; - if constexpr (std::is_same<InputType, o2::emcal::Digit>::value) + if constexpr (std::is_same<InputType, o2::emcal::Digit>::value) { objectbranch = "digits"; - else if constexpr (std::is_same<InputType, o2::emcal::Cell>::value) + } else if constexpr (std::is_same<InputType, o2::emcal::Cell>::value) { objectbranch = "cells"; - else { + } else { LOG(ERROR) << "Unsupported input type ... "; return; } diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index 35d40a6ec7f4e..9a4b6b1dea0a2 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -94,8 +94,9 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) currentCellContainer = found->second; } - if (feeID > 40) + if (feeID > 40) { continue; //skip STU ddl + } //std::cout<<rawreader.getRawHeader()<<std::endl; @@ -127,10 +128,12 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) // define the conatiner for the fit results, and perform the raw fitting using the stadnard raw fitter double amp = 0., time = 0.; o2::emcal::CaloFitResults fitResults = mRawFitter->evaluate(chan.getBunches(), 0, 0); - if (fitResults.getAmp() > 0) + if (fitResults.getAmp() > 0) { fitResults.setAmp(0.); - if (fitResults.getTime() < 0) + } + if (fitResults.getTime() < 0) { fitResults.setTime(0.); + } currentCellContainer->emplace_back(CellID, amp, time, chantype); } } @@ -144,8 +147,9 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) if (cells->size()) { // Sort cells according to cell ID std::sort(cells->begin(), cells->end(), [](o2::emcal::Cell& lhs, o2::emcal::Cell& rhs) { return lhs.getTower() < rhs.getTower(); }); - for (auto cell : *cells) + for (auto cell : *cells) { mOutputCells.push_back(cell); + } } } From 976857397056ab1de0f948ae31b1ac2c9987d298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Wed, 21 Oct 2020 11:39:06 +0200 Subject: [PATCH 1018/1751] PWGHF: Extend and improve track index skimming. (#4647) * PWGHF: Adjust value formats. * PWGHF: Speed up track flagging. * PWGHF: Do not use ROOT types and functions. * PWGHF: Calculate stuff only when needed. * PWGHF: Delete redundant variables. * PWGHF: Add more D0 preselection cuts. Add cuts on cosine of pointing angle, invariant mass, imp. par. product. Add missing braces. Make RecoDecay::CPA more general. * PWGHF: Sort task parameters. * PWGHF: Add switch to disable track quality cut. Sort parameters and improve descriptions. --- Analysis/Core/include/Analysis/RecoDecay.h | 6 +- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 21 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 15 +- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 20 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 368 +++++++++++------- Analysis/Tasks/PWGHF/taskD0.cxx | 28 +- Analysis/Tasks/PWGHF/taskDPlus.cxx | 24 +- 7 files changed, 284 insertions(+), 198 deletions(-) diff --git a/Analysis/Core/include/Analysis/RecoDecay.h b/Analysis/Core/include/Analysis/RecoDecay.h index 5747e4415edad..228802391be27 100644 --- a/Analysis/Core/include/Analysis/RecoDecay.h +++ b/Analysis/Core/include/Analysis/RecoDecay.h @@ -174,7 +174,7 @@ class RecoDecay /// \param mom 3-momentum array /// \return cosine of pointing angle template <typename T, typename U, typename V> - static double CPA(const array<T, 3>& posPV, const array<U, 3>& posSV, const array<V, 3>& mom) + static double CPA(const T& posPV, const U& posSV, const array<V, 3>& mom) { // CPA = (l . p)/(|l| |p|) auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1], posSV[2] - posPV[2]}; @@ -193,8 +193,8 @@ class RecoDecay /// \param posSV {x, y, z} or {x, y} position of the secondary vertex /// \param mom {x, y, z} or {x, y} momentum array /// \return cosine of pointing angle in {x, y} - template <std::size_t N, std::size_t O, std::size_t P, typename T, typename U, typename V> - static double CPAXY(const array<T, N>& posPV, const array<U, O>& posSV, const array<V, P>& mom) + template <std::size_t N, typename T, typename U, typename V> + static double CPAXY(const T& posPV, const U& posSV, const array<V, N>& mom) { // CPAXY = (r . pT)/(|r| |pT|) auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1]}; diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index de3a78a123a10..2592e543a7975 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -27,21 +27,23 @@ using namespace o2::framework; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HFCandidateCreator2Prong { Produces<aod::HfCandProng2Base> rowCandidateBase; - Configurable<double> magneticField{"d_bz", 5.0, "magnetic field"}; + + Configurable<double> magneticField{"d_bz", 5., "magnetic field"}; Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; Configurable<double> d_maxdzini{"d_maxdzini", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - OutputObj<TH1F> hmass2{TH1F("hmass2", "2-track inv mass", 500, 0., 5.0)}; - OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.0e-4)}; + + OutputObj<TH1F> hmass2{TH1F("hmass2", "2-track inv mass", 500, 0., 5.)}; + OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.e-4)}; OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "XX element of SV cov. matrix", 100, 0., 0.2)}; double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); - double massPiK{0}; - double massKPi{0}; + double massPiK{0.}; + double massKPi{0.}; void process(aod::Collision const& collision, aod::HfTrackIndexProng2 const& rowsTrackIndexProng2, @@ -78,11 +80,6 @@ struct HFCandidateCreator2Prong { trackParVar0.getPxPyPzGlo(pvec0); trackParVar1.getPxPyPzGlo(pvec1); - // calculate invariant masses - auto arrayMomenta = array{pvec0, pvec1}; - massPiK = RecoDecay::M(arrayMomenta, array{massPi, massK}); - massKPi = RecoDecay::M(arrayMomenta, array{massK, massPi}); - // get track impact parameters // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); @@ -112,6 +109,10 @@ struct HFCandidateCreator2Prong { // fill histograms if (b_dovalplots) { + // calculate invariant masses + auto arrayMomenta = array{pvec0, pvec1}; + massPiK = RecoDecay::M(arrayMomenta, array{massPi, massK}); + massKPi = RecoDecay::M(arrayMomenta, array{massK, massPi}); hmass2->Fill(massPiK); hmass2->Fill(massKPi); } diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 00488d15a7341..4468db49e558e 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -27,20 +27,22 @@ using namespace o2::framework; /// Reconstruction of heavy-flavour 3-prong decay candidates struct HFCandidateCreator3Prong { Produces<aod::HfCandProng3Base> rowCandidateBase; - Configurable<double> magneticField{"d_bz", 5.0, "magnetic field"}; + + Configurable<double> magneticField{"d_bz", 5., "magnetic field"}; Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; Configurable<double> d_maxdzini{"d_maxdzini", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; + OutputObj<TH1F> hmass3{TH1F("hmass3", "3-track inv mass", 500, 1.6, 2.1)}; - OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.0e-4)}; + OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.e-4)}; OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "XX element of SV cov. matrix", 100, 0., 0.2)}; double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); - double massPiKPi{0}; + double massPiKPi{0.}; void process(aod::Collision const& collision, aod::HfTrackIndexProng3 const& rowsTrackIndexProng3, @@ -81,10 +83,6 @@ struct HFCandidateCreator3Prong { trackParVar1.getPxPyPzGlo(pvec1); trackParVar2.getPxPyPzGlo(pvec2); - // calculate invariant mass - auto arrayMomenta = array{pvec0, pvec1, pvec2}; - massPiKPi = RecoDecay::M(arrayMomenta, array{massPi, massK, massPi}); - // get track impact parameters // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); @@ -117,6 +115,9 @@ struct HFCandidateCreator3Prong { // fill histograms if (b_dovalplots) { + // calculate invariant mass + auto arrayMomenta = array{pvec0, pvec1, pvec2}; + massPiKPi = RecoDecay::M(std::move(arrayMomenta), array{massPi, massK, massPi}); hmass3->Fill(massPiKPi); } } diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index 30f88a2e98a38..262d2c07ee0b6 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -58,19 +58,19 @@ struct HFD0CandidateSelector { Produces<aod::HFSelD0Candidate> hfSelD0Candidate; - Configurable<double> d_pTCandMin{"d_pTCandMin", 0.0, "Lower bound of candidate pT"}; - Configurable<double> d_pTCandMax{"d_pTCandMax", 50.0, "Upper bound of candidate pT"}; + Configurable<double> d_pTCandMin{"d_pTCandMin", 0., "Lower bound of candidate pT"}; + Configurable<double> d_pTCandMax{"d_pTCandMax", 50., "Upper bound of candidate pT"}; Configurable<double> d_pidTPCMinpT{"d_pidTPCMinpT", 0.15, "Lower bound of track pT for TPC PID"}; - Configurable<double> d_pidTPCMaxpT{"d_pidTPCMaxpT", 5.0, "Upper bound of track pT for TPC PID"}; + Configurable<double> d_pidTPCMaxpT{"d_pidTPCMaxpT", 5., "Upper bound of track pT for TPC PID"}; Configurable<double> d_pidTOFMinpT{"d_pidTOFMinpT", 0.15, "Lower bound of track pT for TOF PID"}; - Configurable<double> d_pidTOFMaxpT{"d_pidTOFMaxpT", 5.0, "Upper bound of track pT for TOF PID"}; + Configurable<double> d_pidTOFMaxpT{"d_pidTOFMaxpT", 5., "Upper bound of track pT for TOF PID"}; - Configurable<double> d_TPCNClsFindablePIDCut{"d_TPCNClsFindablePIDCut", 50.0, "Lower bound of TPC findable clusters for good PID"}; - Configurable<double> d_nSigmaTPC{"d_nSigmaTPC", 3.0, "Nsigma cut on TPC only"}; - Configurable<double> d_nSigmaTPCCombined{"d_nSigmaTPCCombined", 5.0, "Nsigma cut on TPC combined with TOF"}; - Configurable<double> d_nSigmaTOF{"d_nSigmaTOF", 3.0, "Nsigma cut on TOF only"}; - Configurable<double> d_nSigmaTOFCombined{"d_nSigmaTOFCombined", 5.0, "Nsigma cut on TOF combined with TPC"}; + Configurable<double> d_TPCNClsFindablePIDCut{"d_TPCNClsFindablePIDCut", 50., "Lower bound of TPC findable clusters for good PID"}; + Configurable<double> d_nSigmaTPC{"d_nSigmaTPC", 3., "Nsigma cut on TPC only"}; + Configurable<double> d_nSigmaTPCCombined{"d_nSigmaTPCCombined", 5., "Nsigma cut on TPC combined with TOF"}; + Configurable<double> d_nSigmaTOF{"d_nSigmaTOF", 3., "Nsigma cut on TOF only"}; + Configurable<double> d_nSigmaTOFCombined{"d_nSigmaTOFCombined", 5., "Nsigma cut on TOF combined with TPC"}; /// Gets corresponding pT bin from cut file array /// \param candpT is the pT of the candidate @@ -78,7 +78,7 @@ struct HFD0CandidateSelector { template <typename T> 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}; + double pTBins[npTBins + 1] = {0, 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8., 9., 10., 12., 16., 20., 24., 36., 50., 100.}; for (int i = 0; i < npTBins; i++) { if (candpT >= pTBins[i] && candpT < pTBins[i + 1]) { return i; diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 3a69c57fbe85d..6aa4b1c4647c0 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -27,22 +27,30 @@ using namespace o2::framework::expressions; /// Track selection struct SelectTracks { Produces<aod::HFSelTrack> rowSelectedTrack; - Configurable<double> ptmintrack_2prong{"ptmintrack_2prong", -1, "ptmin single track"}; - Configurable<double> dcatoprimxymin_2prong{"dcatoprimxymin_2prong", 0, "dca xy to prim vtx min"}; - Configurable<double> etamax_2prong{"etamax_2prong", 999, "maximum pseudorapidity value"}; - Configurable<double> ptmintrack_3prong{"ptmintrack_3prong", -1, "ptmin single track"}; - Configurable<double> dcatoprimxymin_3prong{"dcatoprimxymin_3prong", 0, "dca xy to prim vtx min"}; - Configurable<double> etamax_3prong{"etamax_3prong", 999, "maximum pseudorapidity value"}; - Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min number of tpc cls >="}; - Configurable<double> d_bz{"d_bz", 5.0, "bz field"}; - Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "pt tracks (GeV/#it{c})", 100, 0., 10.)}; - OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "pt tracks (GeV/#it{c})", 100, 0., 10.)}; - OutputObj<TH1F> hdcatoprimxy_cuts_2prong{TH1F("hdcatoprimxy_cuts_2prong", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; - OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "pt tracks (GeV/#it{c})", 100, 0., 10.)}; - OutputObj<TH1F> hdcatoprimxy_cuts_3prong{TH1F("hdcatoprimxy_cuts_3prong", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; - OutputObj<TH1F> heta_cuts_2prong{TH1F("heta_cuts_2prong", "pseudorapidity", 100, -1.0, 1.0)}; - OutputObj<TH1F> heta_cuts_3prong{TH1F("heta_cuts_3prong", "pseudorapidity", 100, -1.0, 1.0)}; + + Configurable<bool> b_dovalplots{"b_dovalplots", true, "fill histograms"}; + Configurable<double> d_bz{"d_bz", 5., "bz field"}; + // quality cut + Configurable<bool> doCutQuality{"doCutQuality", true, "apply quality cuts"}; + Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min. number of TPC clusters"}; + // 2-prong cuts + Configurable<double> ptmintrack_2prong{"ptmintrack_2prong", -1., "min. track pT"}; + Configurable<double> dcatoprimxymin_2prong{"dcatoprimxymin_2prong", 0., "min. DCAXY to prim. vtx."}; + Configurable<double> etamax_2prong{"etamax_2prong", 999., "max. pseudorapidity"}; + // 3-prong cuts + Configurable<double> ptmintrack_3prong{"ptmintrack_3prong", -1., "min. track pT"}; + Configurable<double> dcatoprimxymin_3prong{"dcatoprimxymin_3prong", 0., "min. DCAXY to prim. vtx."}; + Configurable<double> etamax_3prong{"etamax_3prong", 999., "max. pseudorapidity"}; + + OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "#it{p}_{T}^{track} (GeV/#it{c})", 100, 0., 10.)}; + // 2-prong histograms + OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "#it{p}_{T}^{track} (GeV/#it{c})", 100, 0., 10.)}; + OutputObj<TH1F> hdcatoprimxy_cuts_2prong{TH1F("hdcatoprimxy_cuts_2prong", "DCAXY to prim. vtx. (cm)", 100, -1., 1.)}; + OutputObj<TH1F> heta_cuts_2prong{TH1F("heta_cuts_2prong", "#it{#eta}", 100, -1., 1.)}; + // 3-prong histograms + OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "#it{p}_{T}^{track} (GeV/#it{c})", 100, 0., 10.)}; + OutputObj<TH1F> hdcatoprimxy_cuts_3prong{TH1F("hdcatoprimxy_cuts_3prong", "DCAXY to prim. vtx. (cm)", 100, -1., 1.)}; + OutputObj<TH1F> heta_cuts_3prong{TH1F("heta_cuts_3prong", "#it{#eta}", 100, -1., 1.)}; void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) @@ -51,35 +59,50 @@ struct SelectTracks { for (auto& track : tracks) { int status_2prong = 1; // selection flag int status_3prong = 1; // selection flag + if (b_dovalplots) hpt_nocuts->Fill(track.pt()); + + // pT cut if (track.pt() < ptmintrack_2prong) status_2prong = 0; if (track.pt() < ptmintrack_3prong) status_3prong = 0; - if (abs(track.eta()) > etamax_2prong) - status_2prong = 0; - if (abs(track.eta()) > etamax_3prong) - status_3prong = 0; - UChar_t clustermap = track.itsClusterMap(); - bool isselected = track.tpcNClsFound() >= d_tpcnclsfound && - track.flags() & o2::aod::track::ITSrefit && - (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); - if (!isselected) { + + // eta cut + if (status_2prong && abs(track.eta()) > etamax_2prong) status_2prong = 0; + if (status_3prong && abs(track.eta()) > etamax_3prong) status_3prong = 0; + + // quality cut + if (doCutQuality && (status_2prong || status_3prong)) { + UChar_t clustermap = track.itsClusterMap(); + bool isselected = track.tpcNClsFound() >= d_tpcnclsfound && + track.flags() & o2::aod::track::ITSrefit && + (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); + if (!isselected) { + status_2prong = 0; + status_3prong = 0; + } } + + // DCA cut array<float, 2> dca; - auto trackparvar0 = getTrackParCov(track); - bool isprop = trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters - if (!isprop) { - status_2prong = 0; - status_3prong = 0; + if (status_2prong || status_3prong) { + auto trackparvar0 = getTrackParCov(track); + bool isprop = trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters + if (!isprop) { + status_2prong = 0; + status_3prong = 0; + } + if (status_2prong && abs(dca[0]) < dcatoprimxymin_2prong) + status_2prong = 0; + if (status_3prong && abs(dca[0]) < dcatoprimxymin_3prong) + status_3prong = 0; } - if (abs(dca[0]) < dcatoprimxymin_2prong) - status_2prong = 0; - if (abs(dca[0]) < dcatoprimxymin_3prong) - status_3prong = 0; + + // fill histograms if (b_dovalplots) { if (status_2prong == 1) { hpt_cuts_2prong->Fill(track.pt()); @@ -90,6 +113,8 @@ struct SelectTracks { hdcatoprimxy_cuts_3prong->Fill(dca[0]); } } + + // fill table row rowSelectedTrack(status_2prong, status_3prong, dca[0], dca[1]); } } @@ -99,30 +124,41 @@ struct SelectTracks { struct HFTrackIndexSkimsCreator { Produces<aod::HfTrackIndexProng2> rowTrackIndexProng2; Produces<aod::HfTrackIndexProng3> rowTrackIndexProng3; - Configurable<int> triggerindex{"triggerindex", -1, "trigger index"}; + + Configurable<bool> b_dovalplots{"b_dovalplots", true, "fill histograms"}; Configurable<int> do3prong{"do3prong", 0, "do 3 prong"}; - Configurable<double> d_bz{"d_bz", 5.0, "bz field"}; + // event selection + Configurable<int> triggerindex{"triggerindex", -1, "trigger index"}; + // vertexing parameters + Configurable<double> d_bz{"d_bz", 5., "magnetic field"}; Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; - Configurable<double> d_maxr{"d_maxr", 200, "reject PCA's above this radius"}; - Configurable<double> d_maxdzini{"d_maxdzini", 4, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; - Configurable<double> d_minparamchange{"d_minparamchange", 1e-3, "stop iterations if largest change of any X is smaller than this"}; - Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; - Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min mass dplus presel"}; - Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "max mass dplus presel"}; - Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - Configurable<double> ptmincand_2prong{"ptmincand_2prong", -1, "ptmin 2prong candidate"}; - Configurable<double> ptmincand_3prong{"ptmincand_3prong", -1, "ptmin 3prong candidate"}; - - OutputObj<TH1F> hvtx_x_out{TH1F("hvtx_x", "2-track vtx", 1000, -2.0, 2.0)}; - OutputObj<TH1F> hvtx_y_out{TH1F("hvtx_y", "2-track vtx", 1000, -2.0, 2.0)}; - OutputObj<TH1F> hvtx_z_out{TH1F("hvtx_z", "2-track vtx", 1000, -20.0, 20.0)}; - OutputObj<TH1F> hmass2{TH1F("hmass2", ";Inv Mass (GeV/#it{c}^{2})", 500, 0, 5.0)}; + Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; + Configurable<double> d_maxdzini{"d_maxdzini", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; + Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations if chi2/chi2old > this"}; + // 2-prong cuts + Configurable<double> ptmincand_2prong{"ptmincand_2prong", -1., "ptmin 2prong candidate"}; + Configurable<double> cutCPAMin{"cutCPAMin", -2., "min. cosine of pointing angle"}; + Configurable<double> cutInvMassD0Min{"cutInvMassD0Min", -1., "min. D0 candidate invariant mass"}; + Configurable<double> cutInvMassD0Max{"cutInvMassD0Max", -1., "max. D0 candidate invariant mass"}; + Configurable<double> cutImpParProductMax{"cutImpParProductMax", 100., "max. product of imp. par. of D0 candidate prongs"}; + // 3-prong cuts + Configurable<double> ptmincand_3prong{"ptmincand_3prong", -1., "ptmin 3prong candidate"}; + Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min. D+ candidate invariant mass"}; + Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "min. D+ candidate invariant mass"}; + + // 2-prong histograms + OutputObj<TH1F> hvtx_x{TH1F("hvtx_x", "2-track vtx", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx_y{TH1F("hvtx_y", "2-track vtx", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx_z{TH1F("hvtx_z", "2-track vtx", 1000, -20., 20.)}; + OutputObj<TH1F> hmass2{TH1F("hmass2", ";Inv Mass (GeV/#it{c}^{2})", 500, 0., 5.)}; + // 3-prong histograms + OutputObj<TH1F> hvtx3_x{TH1F("hvtx3_x", "3-track vtx", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx3_y{TH1F("hvtx3_y", "3-track vtx", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx3_z{TH1F("hvtx3_z", "3-track vtx", 1000, -20., 20.)}; OutputObj<TH1F> hmass3{TH1F("hmass3", ";Inv Mass (GeV/#it{c}^{2})", 500, 1.6, 2.1)}; - OutputObj<TH1F> hvtx3_x_out{TH1F("hvtx3_x", "3-track vtx", 1000, -2.0, 2.0)}; - OutputObj<TH1F> hvtx3_y_out{TH1F("hvtx3_y", "3-track vtx", 1000, -2.0, 2.0)}; - OutputObj<TH1F> hvtx3_z_out{TH1F("hvtx3_z", "3-track vtx", 1000, -20.0, 20.0)}; - Filter filterSelectTracks = aod::hf_seltrack::isSel2Prong == 1; + Filter filterSelectTracks = (aod::hf_seltrack::isSel2Prong == 1); using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::HFSelTrack>>; // FIXME //Partition<SelectedTracks> tracksPos = aod::track::signed1Pt > 0.f; @@ -130,11 +166,9 @@ struct HFTrackIndexSkimsCreator { double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); - double mass2PiK{0}; - double mass2KPi{0}; - double mass3PiKPi{0}; - double ptcand_2prong{0}; - double ptcand_3prong{0}; + double mass2PiK{0.}; + double mass2KPi{0.}; + double mass3PiKPi{0.}; void process(aod::Collision const& collision, aod::BCs const& bcs, @@ -171,66 +205,110 @@ struct HFTrackIndexSkimsCreator { // first loop over positive tracks //for (auto trackPos1 = tracksPos.begin(); trackPos1 != tracksPos.end(); ++trackPos1) { for (auto trackPos1 = tracks.begin(); trackPos1 != tracks.end(); ++trackPos1) { - if (trackPos1.signed1Pt() < 0) + if (trackPos1.signed1Pt() < 0) { continue; + } auto trackParVarPos1 = getTrackParCov(trackPos1); // first loop over negative tracks //for (auto trackNeg1 = tracksNeg.begin(); trackNeg1 != tracksNeg.end(); ++trackNeg1) { for (auto trackNeg1 = tracks.begin(); trackNeg1 != tracks.end(); ++trackNeg1) { - if (trackNeg1.signed1Pt() > 0) + if (trackNeg1.signed1Pt() > 0) { continue; + } auto trackParVarNeg1 = getTrackParCov(trackNeg1); - Double_t px_Cand = trackPos1.px() + trackNeg1.px(); - Double_t py_Cand = trackPos1.py() + trackNeg1.py(); - Double_t pt_Cand_before2vertex = TMath::Sqrt(px_Cand * px_Cand + py_Cand * py_Cand); + auto pVecCand = array{trackPos1.px() + trackNeg1.px(), + trackPos1.py() + trackNeg1.py(), + trackPos1.pz() + trackNeg1.pz()}; + bool isSelectedCandD0 = true; + + // pT cand cut + double pt_Cand_before2vertex = RecoDecay::Pt(pVecCand); + if (pt_Cand_before2vertex < ptmincand_2prong) { + isSelectedCandD0 = false; + } - if (pt_Cand_before2vertex >= ptmincand_2prong) { + if (isSelectedCandD0) { // reconstruct the 2-prong secondary vertex - if (df.process(trackParVarPos1, trackParVarNeg1) == 0) + if (df.process(trackParVarPos1, trackParVarNeg1) == 0) { continue; + } + + // imp. par. product cut + if (isSelectedCandD0 && cutImpParProductMax < 100.) { + if (trackPos1.dcaPrim0() * trackNeg1.dcaPrim0() > cutImpParProductMax) { + isSelectedCandD0 = false; + } + } - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - df.getTrack(0).getPxPyPzGlo(pvec0); - df.getTrack(1).getPxPyPzGlo(pvec1); + // get secondary vertex const auto& secondaryVertex = df.getPCACandidate(); - // calculate invariant masses - auto arrMom = array{pvec0, pvec1}; - mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); - mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); - - if (b_dovalplots) { - hmass2->Fill(mass2PiK); - hmass2->Fill(mass2KPi); - hvtx_x_out->Fill(secondaryVertex[0]); - hvtx_y_out->Fill(secondaryVertex[1]); - hvtx_z_out->Fill(secondaryVertex[2]); + // CPA cut + if (isSelectedCandD0 && cutCPAMin > -2.) { + auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, pVecCand); + if (cpa < cutCPAMin) { + isSelectedCandD0 = false; + } + } + + if (isSelectedCandD0) { + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + df.getTrack(0).getPxPyPzGlo(pvec0); + df.getTrack(1).getPxPyPzGlo(pvec1); + // calculate invariant masses + auto arrMom = array{pvec0, pvec1}; + mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); + mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); + } + + // invariant-mass cut + if (isSelectedCandD0 && cutInvMassD0Min >= 0. && cutInvMassD0Max > 0.) { + if ((mass2PiK < cutInvMassD0Min || mass2PiK > cutInvMassD0Max) && + (mass2KPi < cutInvMassD0Min || mass2KPi > cutInvMassD0Max)) { + isSelectedCandD0 = false; + } + } + + if (isSelectedCandD0) { + // fill table row + rowTrackIndexProng2(trackPos1.collisionId(), + trackPos1.globalIndex(), + trackNeg1.globalIndex(), 1); + + // fill histograms + if (b_dovalplots) { + hvtx_x->Fill(secondaryVertex[0]); + hvtx_y->Fill(secondaryVertex[1]); + hvtx_z->Fill(secondaryVertex[2]); + hmass2->Fill(mass2PiK); + hmass2->Fill(mass2KPi); + } } - // fill table row - rowTrackIndexProng2(trackPos1.collisionId(), - trackPos1.globalIndex(), - trackNeg1.globalIndex(), 1); } // 3-prong vertex reconstruction if (do3prong == 1) { - if (trackPos1.isSel3Prong() == 0) + if (trackPos1.isSel3Prong() == 0) { continue; - if (trackNeg1.isSel3Prong() == 0) + } + if (trackNeg1.isSel3Prong() == 0) { continue; + } // second loop over positive tracks //for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracksPos.end(); ++trackPos2) { for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracks.end(); ++trackPos2) { - if (trackPos2.signed1Pt() < 0) + if (trackPos2.signed1Pt() < 0) { continue; - if (trackPos2.isSel3Prong() == 0) + } + if (trackPos2.isSel3Prong() == 0) { continue; + } // calculate invariant mass auto arr3Mom = array{ @@ -239,37 +317,18 @@ struct HFTrackIndexSkimsCreator { array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) + if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) { continue; + } - auto trackParVarPos2 = getTrackParCov(trackPos2); - Double_t px_Cand3 = trackPos1.px() + trackNeg1.px() + trackPos2.px(); - Double_t py_Cand3 = trackPos1.py() + trackNeg1.py() + trackPos2.py(); - Double_t pt_Cand3_before2vertex = TMath::Sqrt(px_Cand * px_Cand + py_Cand * py_Cand); + double pt_Cand3_before2vertex = RecoDecay::Pt(trackPos1.px() + trackNeg1.px() + trackPos2.px(), + trackPos1.py() + trackNeg1.py() + trackPos2.py()); if (pt_Cand3_before2vertex >= ptmincand_3prong) { // reconstruct the 3-prong secondary vertex - if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) + auto trackParVarPos2 = getTrackParCov(trackPos2); + if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) { continue; - - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - array<float, 3> pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); - const auto& secondaryVertex3 = df3.getPCACandidate(); - - // calculate invariant mass - arr3Mom = array{pvec0, pvec1, pvec2}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - - if (b_dovalplots) { - hmass3->Fill(mass3PiKPi); - hvtx3_x_out->Fill(secondaryVertex3[0]); - hvtx3_y_out->Fill(secondaryVertex3[1]); - hvtx3_z_out->Fill(secondaryVertex3[2]); } // fill table row @@ -277,16 +336,39 @@ struct HFTrackIndexSkimsCreator { trackPos1.globalIndex(), trackNeg1.globalIndex(), trackPos2.globalIndex(), 2); + + // fill histograms + if (b_dovalplots) { + // get secondary vertex + const auto& secondaryVertex3 = df3.getPCACandidate(); + hvtx3_x->Fill(secondaryVertex3[0]); + hvtx3_y->Fill(secondaryVertex3[1]); + hvtx3_z->Fill(secondaryVertex3[2]); + + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); + + // calculate invariant mass + arr3Mom = array{pvec0, pvec1, pvec2}; + hmass3->Fill(RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi})); + } } } // second loop over negative tracks //for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracksNeg.end(); ++trackNeg2) { for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracks.end(); ++trackNeg2) { - if (trackNeg2.signed1Pt() > 0) + if (trackNeg2.signed1Pt() > 0) { continue; - if (trackNeg2.isSel3Prong() == 0) + } + if (trackNeg2.isSel3Prong() == 0) { continue; + } // calculate invariant mass auto arr3Mom = array{ @@ -295,37 +377,18 @@ struct HFTrackIndexSkimsCreator { array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}}; mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) + if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) { continue; + } - auto trackParVarNeg2 = getTrackParCov(trackNeg2); - Double_t px_Cand3 = trackPos1.px() + trackNeg1.px() + trackNeg2.px(); - Double_t py_Cand3 = trackPos1.py() + trackNeg1.py() + trackNeg2.py(); - Double_t pt_Cand3_before2vertex = TMath::Sqrt(px_Cand3 * px_Cand3 + py_Cand3 * py_Cand3); + double pt_Cand3_before2vertex = RecoDecay::Pt(trackPos1.px() + trackNeg1.px() + trackNeg2.px(), + trackPos1.py() + trackNeg1.py() + trackNeg2.py()); if (pt_Cand3_before2vertex >= ptmincand_3prong) { // reconstruct the 3-prong secondary vertex - if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) + auto trackParVarNeg2 = getTrackParCov(trackNeg2); + if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) { continue; - - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - array<float, 3> pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); - const auto& secondaryVertex3 = df3.getPCACandidate(); - - // calculate invariant mass - arr3Mom = array{pvec0, pvec1, pvec2}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - - if (b_dovalplots) { - hmass3->Fill(mass3PiKPi); - hvtx3_x_out->Fill(secondaryVertex3[0]); - hvtx3_y_out->Fill(secondaryVertex3[1]); - hvtx3_z_out->Fill(secondaryVertex3[2]); } // fill table row @@ -333,6 +396,27 @@ struct HFTrackIndexSkimsCreator { trackNeg1.globalIndex(), trackPos1.globalIndex(), trackNeg2.globalIndex(), 2); + + // fill histograms + if (b_dovalplots) { + // get secondary vertex + const auto& secondaryVertex3 = df3.getPCACandidate(); + hvtx3_x->Fill(secondaryVertex3[0]); + hvtx3_y->Fill(secondaryVertex3[1]); + hvtx3_z->Fill(secondaryVertex3[2]); + + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); + + // calculate invariant mass + arr3Mom = array{pvec0, pvec1, pvec2}; + hmass3->Fill(RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi})); + } } } } diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index 194651790902a..c08a4c59fd683 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -26,22 +26,22 @@ using namespace o2::framework::expressions; /// D0 analysis task struct TaskD0 { - OutputObj<TH1F> hmass{TH1F("hmass", "2-track inv mass", 500, 0, 5.0)}; - OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0, 10.0)}; - OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0, 10.0)}; - OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0, 10.0)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.0)}; - OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.0)}; - OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "prong 0 dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; - OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "prong 1 dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; - OutputObj<TH1F> hd0d0{TH1F("hd0d0", "product of dca xy to prim. vertex (cm^{2})", 500, -1.0, 1.0)}; + OutputObj<TH1F> hmass{TH1F("hmass", "2-track inv mass", 500, 0., 5.)}; + OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0., 10.)}; + OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0., 10.)}; + OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0., 10.)}; + OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.)}; + OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.)}; + OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "prong 0 dca xy to prim. vertex (cm)", 100, -1., 1.)}; + OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "prong 1 dca xy to prim. vertex (cm)", 100, -1., 1.)}; + OutputObj<TH1F> hd0d0{TH1F("hd0d0", "product of dca xy to prim. vertex (cm^{2})", 500, -1., 1.)}; OutputObj<TH1F> hCTS{TH1F("hCTS", "cos #it{#theta}*", 120, -1.1, 1.1)}; - OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; - OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; + OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20., 100.)}; + OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2., 2.)}; OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; - OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1.0, 1.0)}; - OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.0)}; - OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.0)}; + OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1., 1.)}; + OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.)}; + OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.)}; Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; diff --git a/Analysis/Tasks/PWGHF/taskDPlus.cxx b/Analysis/Tasks/PWGHF/taskDPlus.cxx index 5ea0ca4f1cd98..1072358098b62 100644 --- a/Analysis/Tasks/PWGHF/taskDPlus.cxx +++ b/Analysis/Tasks/PWGHF/taskDPlus.cxx @@ -27,19 +27,19 @@ using namespace o2::aod::hf_cand_prong3; /// D± analysis task struct TaskDPlus { OutputObj<TH1F> hmass{TH1F("hmass", "3-track inv mass", 500, 1.6, 2.1)}; - OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0, 10.0)}; - OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0, 10.0)}; - OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0, 10.0)}; - OutputObj<TH1F> hptprong2{TH1F("hptprong2", "pt prong2", 100, 0, 10.0)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.0)}; - OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.0)}; - OutputObj<TH1F> hd0{TH1F("hd0", "dca xy to prim. vertex (cm)", 100, -1.0, 1.0)}; - OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; - OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; + OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0., 10.)}; + OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0., 10.)}; + OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0., 10.)}; + OutputObj<TH1F> hptprong2{TH1F("hptprong2", "pt prong2", 100, 0., 10.)}; + OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.)}; + OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.)}; + OutputObj<TH1F> hd0{TH1F("hd0", "dca xy to prim. vertex (cm)", 100, -1., 1.)}; + OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20., 100.)}; + OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2., 2.)}; //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; - OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1.0, 1.0)}; - OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.0)}; - OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.0)}; + OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1., 1.)}; + OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.)}; + OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.)}; Configurable<int> d_selectionFlagDPlus{"d_selectionFlagDPlus", 1, "Selection Flag for DPlus"}; From b65f93e86e2de6b8775b57ff0d9c32fc56af2a04 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 21 Oct 2020 20:29:19 +0200 Subject: [PATCH 1019/1751] HistogramRegistry: write output into (sub-)directories (#4648) --- Framework/Core/src/CommonDataProcessors.cxx | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index e0a4257be1528..c64645c35ba3c 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -106,7 +106,25 @@ DataProcessorSpec CommonDataProcessors::getHistogramRegistrySink(outputObjects c currentDirectory = nextDirectory; currentFile = filename; } - (f[route.policy]->GetDirectory(currentDirectory.c_str()))->WriteObjectAny(entry.obj, entry.kind, entry.name.c_str()); + + // translate the list-structure created by the registry into a directory structure within the file + std::function<void(TList*, TDirectory*)> writeListToFile; + writeListToFile = [&](TList* list, TDirectory* parentDir) { + TIter next(list); + TNamed* object = nullptr; + while ((object = (TNamed*)next())) { + if (object->InheritsFrom(TList::Class())) { + writeListToFile((TList*)object, parentDir->mkdir(object->GetName(), object->GetName(), true)); + } else { + parentDir->WriteObjectAny(object, object->Class(), object->GetName()); + list->Remove(object); + } + } + }; + TList* outputList = (TList*)entry.obj; + writeListToFile(outputList, f[route.policy]->GetDirectory(currentDirectory.c_str())); + outputList->SetOwner(true); + delete outputList; // properly remove the empty list and its sub-lists } } for (auto i = 0u; i < OutputObjHandlingPolicy::numPolicies; ++i) { From 5ae7a0427b41a506566e28197f071116ac27b9e7 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Wed, 21 Oct 2020 23:54:45 +0200 Subject: [PATCH 1020/1751] Update of AOD reader / writer (#4642) * this is to work with files containing folders TF_%d * catch issue with missing command line options in test__WorkflowHelpers.cxx * ignore hite spaces and empty lines in the input file list --- Framework/Core/ANALYSIS.md | 91 +++++++------- .../include/Framework/CommonDataProcessors.h | 5 +- .../include/Framework/DataInputDirector.h | 8 +- .../include/Framework/DataOutputDirector.h | 13 +- .../include/Framework/runDataProcessing.h | 7 ++ Framework/Core/src/AODReaderHelpers.cxx | 66 ++++++---- Framework/Core/src/CommonDataProcessors.cxx | 109 ++++------------- Framework/Core/src/DataInputDirector.cxx | 113 +++++++++--------- Framework/Core/src/DataOutputDirector.cxx | 25 ++-- Framework/Core/src/WorkflowHelpers.cxx | 101 ++++++++++++++-- Framework/Core/src/WorkflowHelpers.h | 3 + .../Core/test/test_DataInputDirector.cxx | 4 +- 12 files changed, 294 insertions(+), 251 deletions(-) diff --git a/Framework/Core/ANALYSIS.md b/Framework/Core/ANALYSIS.md index a4c12f937352c..bb625129078dd 100644 --- a/Framework/Core/ANALYSIS.md +++ b/Framework/Core/ANALYSIS.md @@ -408,17 +408,17 @@ Produced tables can be saved to file as TTrees. This process is customized by va The options to consider are: -* --keep -* --res-file -* --ntfmerge -* --json-file +* --aod-writer-keep +* --aod-writer-resfile +* --aod-writer-ntfmerge +* --aod-writer-json -#### --keep +#### --aod-writer-keep -`keep` is a comma-separated list of `DataOuputDescriptors`. +`aod-writer-keep` is a comma-separated list of `DataOuputDescriptors`. -`keep` +`aod-writer-keep` ```csh DataOuputDescriptor1,DataOuputDescriptor2, ... ``` @@ -429,9 +429,9 @@ Each `DataOuputDescriptor` is a colon-separated list of 4 items ```csh table:tree:columns:file ``` -and instructs the internal-dpl-aod-writer, to save the columns `columns` of table `table` as TTree `tree` into files `file_x.root`, where `x` is an incremental number. The selected columns are saved as separate TBranches of TTree `tree`. +and instructs the internal-dpl-aod-writer, to save the columns `columns` of table `table` as TTree `tree` in folder `TF_x` of file `file.root`. The selected columns are saved as separate TBranches of TTree `tree`. -By default `x` is incremented with every time frame. This behavior can be modified with the command line option `--ntfmerge`. The value of `ntfmerge` specifies the number of time frames to merge into one file. +By default `x` is incremented with every time frame. This behavior can be modified with the command line option `--ntfmerge`. The value of `aod-writer-ntfmerge` specifies the number of time frames to merge into one `TF_x` folder. The first item of a `DataOuputDescriptor` (`table`) is mandatory and needs to be specified, otherwise the `DataOuputDescriptor` is ignored. The other three items are optional and are filled by default values if missing. @@ -443,7 +443,7 @@ AOD/tablename/0 ``` `tablename` is the name of the table as defined in the workflow definition. -The format of `tree` is a simple string which names the TTree the table is saved to. If `tree` is not specified then `tablename` is used as TTree name. +The format of `tree` is a simple string which names the TTree the table is saved to. If `tree` is not specified then `O2tablename` is used as TTree name. `columns` is a slash(/)-separated list of column names., e.g. @@ -453,32 +453,32 @@ col1/col2/col3 ``` The column names are expected to match column names of table `tablename` as defined in the respective workflow. Non-matching columns are ignored. The selected table columns are saved as separate TBranches with the same names as the corresponding table columns. If `columns` is not specified then all table columns are saved. -`file` finally specifies the base name of the files the tables are saved to. The actual file names are composed as `file`_`x`.root, where `x` is an incremental number. If `file` is not specified the default file name is used. The default file name can be set with the command line option `--res-file`. However, if `res-file` is missing then the default file name is set to `AnalysisResults`. +`file` finally specifies the base name of the file the tables are saved to. The actual file name is `file`.root. If `file` is not specified the default file name is used. The default file name can be set with the command line option `--aod-writer-resfile`. However, if `aod-writer-resfile` is missing then the default file name is set to `AnalysisResults_trees`. ##### Dangling outputs -The `keep` option also accepts the string "dangling" (or any leading sub-string of it). In +The `aod-writer-keep` option also accepts the string "dangling" (or any leading sub-string of it). In this case all dangling output tables are saved. For the parameters `tree`, `columns`, and `file` the default values ([see table below](#priorities)) are used. -#### --ntfmerge +#### --aod-writer-ntfmerge -`ntfmerge` specifies the number of time frames which are merged into a given root file. By default this value is set to 1. The actual file names are composed as `file`_`x`.root, where `x` is an incremental number. `x` is incremented by 1 at every `ntfmerge` time frame. +`aod-writer-ntfmerge` specifies the number of time frames which are merged into a given folder `TF_x`. By default this value is set to 1. `x` is incremented by 1 at every `aod-writer-ntfmerge` time frame. -#### --res-file +#### --aod-writer-resfile -`res-file` specifies the default base name of the results files to which tables are saved. If in any of the `DataOutputDescriptors` the `file` value is missing it will be set to this default value. +`aod-writer-resfile` specifies the default base name of the results files to which tables are saved. If in any of the `DataOutputDescriptors` the `file` value is missing it will be set to this default value. -#### --json-file +#### --aod-writer-json -`json-file` specifies the name of a json-file which contains the full information needed to customize the behavior of the internal-dpl-aod-writer. It can replace the other three options completely. Nevertheless, currently all options are supported ([see also discussion below](#redundancy)). +`aod-writer-json` specifies the name of a json-file which contains the full information needed to customize the behavior of the internal-dpl-aod-writer. It can replace the other three options completely. Nevertheless, currently all options are supported ([see also discussion below](#redundancy)). An example file is shown in the highlighted field below. The relevant information is contained in a json object `OutputDirector`. The `OutputDirector` can include three different items: - 1. `resfile` is a string and corresponds to the `res-file` command line option - 2.`ntfmerge` is an integer and corresponds to the `ntfmerge` command line option - 3.`OutputDescriptors` is an array of objects and corresponds to the `keep` command line option. The objects are equivalent to the `DataOuputDescriptors` of the `keep` option and are composed of 4 items which correspond to the 4 items of a `DataOuputDescriptor`. + 1. `resfile` is a string and corresponds to the `aod-writer-resfile` command line option + 2.`aod-writer-ntfmerge` is an integer and corresponds to the `aod-writer-ntfmerge` command line option + 3.`OutputDescriptors` is an array of objects and corresponds to the `aod-writer-keep` command line option. The objects are equivalent to the `DataOuputDescriptors` of the `aod-writer-keep` option and are composed of 4 items which correspond to the 4 items of a `DataOuputDescriptor`. a. `table` is a string b. `treename` is a string @@ -523,10 +523,10 @@ This hierarchy of the options is summarized in the following table. The columns <a name="priorities"></a> -| parameter\option | keep | res-file | ntfmerge | json-file | default | +| parameter\option | aod-writer-keep | aod-writer-resfile | aod-writer-ntfmerge | aod-writer-json | default | |--------------|:----:|:--------:|:--------:|----------:|:-------:| -| `default file name` | - | 1. | - | 2. | 3. (AnalysisResults)| -| `ntfmerge` | - | - | 1. | 2. | 3. (1) | +| `default file name` | - | 1. | - | 2. | 3. (AnalysisResults_trees)| +| `ntfmerge` | - | - | 1. | 2. | 3. (1) | | `tablename` | 1. | - | - | 2. | - | | `tree` | 1. | - | - | 2. | 3. (`tablename`) | | `columns` | 1. | - | - | 2. | 3. (all columns) | @@ -536,18 +536,18 @@ This hierarchy of the options is summarized in the following table. The columns #### Valid example command line options ```csh ---keep AOD/UNO/0 - # save all columns of table 'UNO' to TTree 'UNO' in files 'AnalysisResults'_x.root +--aod-writer-keep AOD/UNO/0 + # save all columns of table 'UNO' to TTree 'O2uno' in file `AnalysisResults_trees.root` ---keep AOD/UNO/0::c2/c4:unoresults - # save columns 'c2' and 'c4' of table 'UNO' to TTree 'UNO' in files 'unoresults'_x.root +--aod-writer-keep AOD/UNO/0::c2/c4:unoresults + # save columns 'c2' and 'c4' of table 'UNO' to TTree 'O2uno' in file 'unoresults.root` ---res-file myskim --ntfmerge 50 --keep AOD/UNO/0:trsel1:c1/c2,AOD/DUE/0:trsel2:c6/c7/c8 - # save columns 'c1' and 'c2' of table 'UNO' to TTree 'trsel1' in files 'myskim'_x.root and - # save columns 'c6', 'c7' and 'c8' of table 'DUE' to TTree 'trsel2' in files 'myskim'_x.root. - # Merge 50 time frames in each file. +--aod-writer-resfile myskim --aod-writer-ntfmerge 50 --aod-writer-keep AOD/UNO/0:trsel1:c1/c2,AOD/DUE/0:trsel2:c6/c7/c8 + # save columns 'c1' and 'c2' of table 'UNO' to TTree 'trsel1' in file 'myskim.root` and + # save columns 'c6', 'c7' and 'c8' of table 'DUE' to TTree 'trsel2' in file 'myskim.root`. + # Merge 50 time frames in each folder `TF_x`. ---json-file myconfig.json +--aod-writer-json myconfig.json # according to the contents of myconfig.json ``` @@ -563,7 +563,7 @@ two trees with equal name to a given file. The internal-dpl-aod-reader reads trees from root files and provides them as arrow tables to the requesting workflows. Its behavior is customized with the following command line options: * --aod-file -* --json-file +* --aod-reader-json #### --aod-file @@ -578,9 +578,9 @@ The internal-dpl-aod-reader reads trees from root files and provides them as arr ``` -#### --json-file +#### --aod-reader-json -'json-file' is a string and specifies a json file, which contains the +'aod-reader-json' is a string and specifies a json file, which contains the customization information for the internal-dpl-aod-reader. An example file is shown in the highlighted field below. The relevant information is contained in a json object `InputDirector`. The `InputDirector` can include the following @@ -595,12 +595,12 @@ three items: c. `resfiles` is either a string or an array of strings. It specifies a list of possible input files (see discussion of `resfiles` above). d. `fileregex` is a regular expression string which is used to select the input files from the file list specified by `resfiles` -The information contained in a `DataInputDescriptor` instructs the internal-dpl-aod-reader to fill table `table` with the values from the tree `treename` in the files which are defined by `resfiles` and which names match the regex `fileregex`. +The information contained in a `DataInputDescriptor` instructs the internal-dpl-aod-reader to fill table `table` with the values from the tree `treename` in folders `TF_x` of the files which are defined by `resfiles` and which names match the regex `fileregex`. Of the four items of a `DataInputDescriptor`, `table` is the only required information. If one of the other items is missing its value will be set as follows: - 1. `treename` is set to `tablename` of the respective `table` item. - 2. `resfiles` is set to `resfiles` of the `InputDirector` (1. item of the `InputDirector`). If that is missing, then the value of the `aod-file` option is used. If that is missing, then `AnalysisResults.root` is used. + 1. `treename` is set to `O2tablename` of the respective `table` item. + 2. `resfiles` is set to `resfiles` of the `InputDirector` (1. item of the `InputDirector`). If that is missing, then the value of the `aod-file` option is used. If that is missing, then `AnalysisResults_trees.root` is used. 3. `fileregex` is set to `fileregex` of the `InputDirector` (2. item of the `InputDirector`). If that is missing, then `.*` is used. @@ -635,17 +635,17 @@ Of the four items of a `DataInputDescriptor`, `table` is the only required infor } ``` -When the internal-dpl-aod-reader receives the request to fill a given table `tablename` it searches in the provided `InputDirector` for the corresponding `InputDescriptor` and proceeds as defined there. However, if there is no corresponding `InputDescriptor` it falls back to the information provided by the `resfiles` and `fileregex` options of the `InputDirector` and uses the `tablename` as `treename`. +When the internal-dpl-aod-reader receives the request to fill a given table `tablename` it searches in the provided `InputDirector` for the corresponding `InputDescriptor` and proceeds as defined there. However, if there is no corresponding `InputDescriptor` it falls back to the information provided by the `resfiles` and `fileregex` options of the `InputDirector` and uses `O2tablename` as `treename`. #### Some practical comments -The `json-file` option allows to setup the reading of tables in a rather +The `aod-reader-json` option allows to setup the reading of tables in a rather flexible way. Here a few presumably practical cases are discussed: 1. Let's assume a case where data from tables `tableA` and `tableB` need to be processed together. Table `tableA` was previously saved as tree `tableA` to -files `tableAResults_x.root`, where `x` is a number and `tableB` was saved as -tree `tableB` to `tableBResults_x.root`. The following json-file could be used +files `tableAResults_n.root`, where `n` is a number and `tableB` was saved as +tree `tableB` to `tableBResults_n.root`. The following json-file could be used to read these tables: ```csh @@ -667,10 +667,10 @@ to read these tables: } ``` - 2. In this case several tables need to be provided. All tables can be read from files `tableResult_x.root`, except for one table, namely `tableA`, which is saved as tree `treeA` in files `tableAResult_x.root`. + 2. In this case several tables need to be provided. All tables can be read from files `tableResult_n.root`, except for one table, namely `tableA`, which is saved as tree `treeA` in files `tableAResult_n.root`. ```csh - # file resfiles.txt lists all tableResults_x.root and tableAResults_x.root files. + # file resfiles.txt lists all tableResults_n.root and tableAResults_n.root files. "InputDirector": { "resfiles": "@resfiles.txt", @@ -684,7 +684,6 @@ to read these tables: ] } ``` - #### Limitations diff --git a/Framework/Core/include/Framework/CommonDataProcessors.h b/Framework/Core/include/Framework/CommonDataProcessors.h index 0c8244c572cd0..8724029468cd6 100644 --- a/Framework/Core/include/Framework/CommonDataProcessors.h +++ b/Framework/Core/include/Framework/CommonDataProcessors.h @@ -43,8 +43,9 @@ struct CommonDataProcessors { static DataProcessorSpec getGlobalFairMQSink(std::vector<InputSpec> const& danglingInputs); /// writes inputs of kind AOD to file - static DataProcessorSpec getGlobalAODSink(std::vector<InputSpec> const& OutputInputs, - std::vector<bool> const& isdangling); + static DataProcessorSpec getGlobalAODSink(std::shared_ptr<DataOutputDirector> dod, + std::vector<InputSpec> const& OutputInputs); + /// @return a dummy DataProcessorSpec which requires all the passed @a InputSpec /// and simply discards them. static DataProcessorSpec getDummySink(std::vector<InputSpec> const& danglingInputs); diff --git a/Framework/Core/include/Framework/DataInputDirector.h b/Framework/Core/include/Framework/DataInputDirector.h index 880495d4e2e2b..952fd08e0f734 100644 --- a/Framework/Core/include/Framework/DataInputDirector.h +++ b/Framework/Core/include/Framework/DataInputDirector.h @@ -63,7 +63,7 @@ struct DataInputDescriptor { int getNumberInputfiles() { return mfilenames.size(); } int getNumberTimeFrames() { return mtotalNumberTimeFrames; } - std::tuple<TFile*, std::string> getFileFolder(int counter); + std::tuple<TFile*, std::string> getFileFolder(int counter, int numTF); void closeInputFile(); bool isAlienSupportOn() { return mAlienSupport; } @@ -103,9 +103,9 @@ struct DataInputDirector { // getters DataInputDescriptor* getDataInputDescriptor(header::DataHeader dh); - std::unique_ptr<TTreeReader> getTreeReader(header::DataHeader dh, int counter, std::string treeName); - std::tuple<TFile*, std::string> getFileFolder(header::DataHeader dh, int counter); - TTree* getDataTree(header::DataHeader dh, int counter); + std::unique_ptr<TTreeReader> getTreeReader(header::DataHeader dh, int counter, int numTF, std::string treeName); + std::tuple<TFile*, std::string> getFileFolder(header::DataHeader dh, int counter, int numTF); + TTree* getDataTree(header::DataHeader dh, int counter, int numTF); int getNumberInputDescriptors() { return mdataInputDescriptors.size(); } private: diff --git a/Framework/Core/include/Framework/DataOutputDirector.h b/Framework/Core/include/Framework/DataOutputDirector.h index 6a2655316cfb1..706a0d7c8cfc0 100644 --- a/Framework/Core/include/Framework/DataOutputDirector.h +++ b/Framework/Core/include/Framework/DataOutputDirector.h @@ -70,14 +70,18 @@ struct DataOutputDirector { std::tuple<std::string, std::string, int> readJson(std::string const& fnjson); std::tuple<std::string, std::string, int> readJsonString(std::string const& stjson); + // read/write private members + int getNumberTimeFramesToMerge() { return mnumberTimeFramesToMerge; } + void setNumberTimeFramesToMerge(int ntfmerge) { mnumberTimeFramesToMerge = ntfmerge; } + std::string getFileMode() { return mfileMode; } + void setFileMode(std::string filemode) { mfileMode = filemode; } + // get matching DataOutputDescriptors std::vector<DataOutputDescriptor*> getDataOutputDescriptors(header::DataHeader dh); std::vector<DataOutputDescriptor*> getDataOutputDescriptors(InputSpec spec); // get the matching TFile - std::tuple<TFile*, std::string> getFileFolder(DataOutputDescriptor* dodesc, - int ntf, int ntfmerge, - std::string filemode); + std::tuple<TFile*, std::string> getFileFolder(DataOutputDescriptor* dodesc, uint64_t folderNumber); void closeDataFiles(); @@ -91,9 +95,10 @@ struct DataOutputDirector { std::vector<DataOutputDescriptor*> mDataOutputDescriptors; std::vector<std::string> mtreeFilenames; std::vector<std::string> mfilenameBases; - std::vector<int> mfolderCounts; std::vector<TFile*> mfilePtrs; bool mdebugmode = false; + int mnumberTimeFramesToMerge = 1; + std::string mfileMode = "RECREATE"; std::tuple<std::string, std::string, int> readJsonDocument(Document* doc); const std::tuple<std::string, std::string, int> memptyanswer = std::make_tuple(std::string(""), std::string(""), -1); diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index c31c061354f16..b2cc4606e6a83 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -128,6 +128,13 @@ int main(int argc, char** argv) workflowOptions.push_back(ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}); workflowOptions.push_back(ConfigParamSpec{"dangling-outputs-policy", VariantType::String, "file", {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}); + // options for AOD writer + workflowOptions.push_back(ConfigParamSpec{"aod-writer-json", VariantType::String, "", {"Name of the json configuration file"}}); + workflowOptions.push_back(ConfigParamSpec{"aod-writer-resfile", VariantType::String, "", {"Default name of the output file"}}); + workflowOptions.push_back(ConfigParamSpec{"aod-writer-resmode", VariantType::String, "", {"Creation mode of the result files: NEW, CREATE, RECREATE, UPDATE"}}); + workflowOptions.push_back(ConfigParamSpec{"aod-writer-ntfmerge", VariantType::Int, -1, {"Number of time frames to merge into one file"}}); + workflowOptions.push_back(ConfigParamSpec{"aod-writer-keep", VariantType::String, "", {"Comma separated list of ORIGIN/DESCRIPTION/SUBSPECIFICATION:treename:col1/col2/..:filename"}}); + std::vector<ChannelConfigurationPolicy> channelPolicies; UserCustomizationsHelper::userDefinedCustomization(channelPolicies, 0); auto defaultChannelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index b341b4089b47e..261b4d84acebc 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -93,12 +93,17 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() { auto callback = AlgorithmSpec{adaptStateful([](ConfigParamRegistry const& options, DeviceSpec const& spec) { + if (!options.isSet("aod-file")) { + LOGP(ERROR, "No input file defined!"); + throw std::runtime_error("Processing is stopped!"); + } + auto filename = options.get<std::string>("aod-file"); // create a DataInputDirector auto didir = std::make_shared<DataInputDirector>(filename); - if (options.isSet("json-file")) { - auto jsonFile = options.get<std::string>("json-file"); + if (options.isSet("aod-reader-json")) { + auto jsonFile = options.get<std::string>("aod-reader-json"); if (!didir->readJson(jsonFile)) { LOGP(ERROR, "Check the JSON document! Can not be properly parsed!"); } @@ -110,48 +115,63 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() // create list of requested tables std::vector<OutputRoute> requestedTables(spec.outputs); - auto counter = std::make_shared<int>(0); + auto fileCounter = std::make_shared<int>(0); + auto numTF = std::make_shared<int>(-1); return adaptStateless([requestedTables, + fileCounter, + numTF, watchdog, didir](DataAllocator& outputs, ControlService& control, DeviceSpec const& device) { // check if RuntimeLimit is reached if (!watchdog->update()) { LOGP(INFO, "Run time exceeds run time limit of {} seconds!", watchdog->runTimeLimit); - LOGP(INFO, "Stopping after time frame {}.", watchdog->numberTimeFrames - 1); + LOGP(INFO, "Stopping reader {} after time frame {}.", device.inputTimesliceId, watchdog->numberTimeFrames - 1); didir->closeInputFiles(); control.endOfStream(); control.readyToQuit(QuitRequest::Me); return; } - // Each parallel reader reads the files whose index is associated to - // their inputTimesliceId + // Each parallel reader device.inputTimesliceId reads the files fileCounter*device.maxInputTimeslices+device.inputTimesliceId + // the TF to read is numTF assert(device.inputTimesliceId < device.maxInputTimeslices); - size_t fi = (watchdog->numberTimeFrames * device.maxInputTimeslices) + device.inputTimesliceId; - - // check if EoF is reached - if (didir->atEnd(fi)) { - LOGP(INFO, "All input files processed"); - didir->closeInputFiles(); - control.endOfStream(); - control.readyToQuit(QuitRequest::Me); - return; - } + int fcnt = (*fileCounter * device.maxInputTimeslices) + device.inputTimesliceId; + int ntf = *numTF + 1; // loop over requested tables + TTree* tr = nullptr; + bool first = true; for (auto route : requestedTables) { // create a TreeToTable object auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); auto dh = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); - auto tr = didir->getDataTree(dh, fi); + tr = didir->getDataTree(dh, fcnt, ntf); if (!tr) { - char* table; - sprintf(table, "%s/%s/%" PRIu32, concrete.origin.str, concrete.description.str, concrete.subSpec); - LOGP(ERROR, "Error while retrieving the tree for \"{}\"!", table); - return; + if (first) { + // check if there is a next file to read + fcnt += device.maxInputTimeslices; + if (didir->atEnd(fcnt)) { + LOGP(INFO, "No input files left to read for reader {}!", device.inputTimesliceId); + didir->closeInputFiles(); + control.endOfStream(); + control.readyToQuit(QuitRequest::Me); + return; + } + // get first folder of next file + ntf = 0; + tr = didir->getDataTree(dh, fcnt, ntf); + if (!tr) { + LOGP(FATAL, "Can not retrieve tree for table {}: fileCounter {}, timeFrame {}", concrete.origin, fcnt, ntf); + throw std::runtime_error("Processing is stopped!"); + } + } else { + LOGP(FATAL, "Can not retrieve tree for table {}: fileCounter {}, timeFrame {}", concrete.origin, fcnt, ntf); + throw std::runtime_error("Processing is stopped!"); + } } + first = false; auto o = Output(dh); auto& t2t = outputs.make<TreeToTable>(o); @@ -169,6 +189,10 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() // fill the table t2t.fill(tr); } + + // save file number and time frame + *fileCounter = (fcnt - device.inputTimesliceId) / device.maxInputTimeslices; + *numTF = ntf; }); })}; diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index c64645c35ba3c..432a1847f6cdb 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -349,75 +349,12 @@ DataProcessorSpec CommonDataProcessors::getOutputObjSink(outputObjects const& ob // add sink for the AODs DataProcessorSpec - CommonDataProcessors::getGlobalAODSink(std::vector<InputSpec> const& OutputInputs, - std::vector<bool> const& isdangling) + CommonDataProcessors::getGlobalAODSink(std::shared_ptr<DataOutputDirector> dod, + std::vector<InputSpec> const& OutputInputs) { - auto writerFunction = [OutputInputs, isdangling](InitContext& ic) -> std::function<void(ProcessingContext&)> { - LOG(DEBUG) << "======== getGlobalAODSink::Init =========="; - - auto dod = std::make_shared<DataOutputDirector>(); - - // analyze ic and take actions accordingly - // default values - std::string fnbase("AnalysisResults"); - std::string filemode("RECREATE"); - int ntfmerge = 1; - - // values from json - if (ic.options().isSet("json-file")) { - auto fnjson = ic.options().get<std::string>("json-file"); - if (!fnjson.empty()) { - auto [fnb, fmo, ntfm] = dod->readJson(fnjson); - if (!fnb.empty()) { - fnbase = fnb; - } - if (!fmo.empty()) { - filemode = fmo; - } - if (ntfm > 0) { - ntfmerge = ntfm; - } - } - } - - // values from command line options, information from json is overwritten - if (ic.options().isSet("res-file")) { - fnbase = ic.options().get<std::string>("res-file"); - } - if (ic.options().isSet("res-mode")) { - filemode = ic.options().get<std::string>("res-mode"); - } - if (ic.options().isSet("ntfmerge")) { - auto ntfm = ic.options().get<int>("ntfmerge"); - if (ntfm > 0) { - ntfmerge = ntfm; - } - } - // parse the keepString - if (ic.options().isSet("keep")) { - dod->reset(); - auto keepString = ic.options().get<std::string>("keep"); - - std::string d("dangling"); - if (d.find(keepString) == 0) { - - // use the dangling outputs - std::vector<InputSpec> danglingOutputs; - for (auto ii = 0; ii < OutputInputs.size(); ii++) { - if (isdangling[ii]) { - danglingOutputs.emplace_back(OutputInputs[ii]); - } - } - dod->readSpecs(danglingOutputs); - - } else { - - // use the keep string - dod->readString(keepString); - } - } - dod->setFilenameBase(fnbase); + auto writerFunction = [dod, OutputInputs](InitContext& ic) -> std::function<void(ProcessingContext&)> { + LOGP(DEBUG, "======== getGlobalAODSink::Init =========="); // find out if any table needs to be saved bool hasOutputsToWrite = false; @@ -430,6 +367,7 @@ DataProcessorSpec } // if nothing needs to be saved then return a trivial functor + // this happens when nothing needs to be saved but there are dangling outputs if (!hasOutputsToWrite) { return [](ProcessingContext&) mutable -> void { static bool once = false; @@ -443,7 +381,6 @@ DataProcessorSpec // end of data functor is called at the end of the data stream auto endofdatacb = [dod](EndOfStreamContext& context) { dod->closeDataFiles(); - context.services().get<ControlService>().readyToQuit(QuitRequest::Me); }; @@ -451,39 +388,39 @@ DataProcessorSpec callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); // this functor is called once per time frame - Int_t ntf = -1; - return std::move([ntf, ntfmerge, filemode, dod](ProcessingContext& pc) mutable -> void { - LOG(DEBUG) << "======== getGlobalAODSink::processing =========="; - LOG(DEBUG) << " processing data set with " << pc.inputs().size() << " entries"; + return std::move([dod](ProcessingContext& pc) mutable -> void { + LOGP(DEBUG, "======== getGlobalAODSink::processing =========="); + LOGP(DEBUG, " processing data set with {} entries", pc.inputs().size()); - // return immediately if pc.inputs() is empty + // return immediately if pc.inputs() is empty. This should never happen! auto ninputs = pc.inputs().size(); if (ninputs == 0) { - LOG(INFO) << "No inputs available!"; + LOGP(INFO, "No inputs available!"); return; } - // increment the time frame counter ntf - ntf++; - // loop over the DataRefs which are contained in pc.inputs() for (const auto& ref : pc.inputs()) { // does this need to be saved? auto dh = DataRefUtils::getHeader<header::DataHeader*>(ref); - auto ds = dod->getDataOutputDescriptors(*dh); + auto dataProcessingHeader = DataRefUtils::getHeader<DataProcessingHeader*>(ref); + + // the startTime contained in the header determines the folder number + uint64_t folderNumber = dataProcessingHeader->startTime; + // get the relevant DataOutputDescriptors + auto ds = dod->getDataOutputDescriptors(*dh); if (ds.size() > 0) { // get the TableConsumer and corresponding arrow table auto s = pc.inputs().get<TableConsumer>(ref.spec->binding); auto table = s->asArrowTable(); if (!table->Validate().ok()) { - LOGP(ERROR, "The table \"{}\" is not valid and will not be saved!", dh->description.str); + LOGP(WARNING, "The table \"{}\" is not valid and will not be saved!", dh->description.str); continue; } else if (table->num_rows() <= 0) { - LOGP(WARNING, "The table \"{}\" is empty and will not be saved!", dh->description.str); - continue; + LOGP(WARNING, "The table \"{}\" is empty but will be saved anyway!", dh->description.str); } // loop over all DataOutputDescriptors @@ -491,7 +428,7 @@ DataProcessorSpec // e.g. different selections of columns to different files for (auto d : ds) { - auto [file, directory] = dod->getFileFolder(d, ntf, ntfmerge, filemode); + auto [file, directory] = dod->getFileFolder(d, folderNumber); auto treename = directory + d->treename; TableToTree ta2tr(table, file, @@ -516,16 +453,14 @@ DataProcessorSpec }); }; // end of writerFunction + // the command line options relevant for the writer are global + // see runDataProcessing.h DataProcessorSpec spec{ "internal-dpl-aod-writer", OutputInputs, Outputs{}, AlgorithmSpec(writerFunction), - {{"json-file", VariantType::String, {"Name of the json configuration file"}}, - {"res-file", VariantType::String, {"Default name of the output file"}}, - {"res-mode", VariantType::String, {"Creation mode of the result files: NEW, CREATE, RECREATE, UPDATE"}}, - {"ntfmerge", VariantType::Int, {"Number of time frames to merge into one file"}}, - {"keep", VariantType::String, {"Comma separated list of ORIGIN/DESCRIPTION/SUBSPECIFICATION:treename:col1/col2/..:filename"}}}}; + {}}; return spec; } diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 7995cf82fe19f..7e5855763f1b6 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -17,7 +17,6 @@ #include "rapidjson/filereadstream.h" #include "TGrid.h" -#include "TObjString.h" namespace o2 { @@ -30,31 +29,6 @@ FileNameHolder* makeFileNameHolder(std::string fileName) auto fileNameHolder = new FileNameHolder(); fileNameHolder->fileName = fileName; - if (fileName.rfind("alien://", 0) == 0) { - if (gGrid == nullptr || gGrid->IsConnected() == false) { - LOG(debug) << "AliEn file requested. Enabling support."; - TGrid::Connect("alien://"); - } - } - - TFile* file = TFile::Open(fileName.c_str(), "R"); - if (!file || !file->IsOpen()) { - LOGP(ERROR, "\"{}\" can not be opened.", fileName); - delete file; - return fileNameHolder; - } - - // find TimeFrame folders - std::regex TFRegex = std::regex("TF_[0-9]+"); - TList* keyList = file->GetListOfKeys(); - for (auto key : *keyList) { - if (std::regex_match(((TObjString*)key)->GetString().Data(), TFRegex)) { - fileNameHolder->listOfTimeFrameKeys.emplace_back(std::string(((TObjString*)key)->GetString().Data())); - } - } - fileNameHolder->numberOfTimeFrames = fileNameHolder->listOfTimeFrameKeys.size(); - delete file; - return fileNameHolder; } @@ -103,38 +77,56 @@ void DataInputDescriptor::addFileNameHolder(FileNameHolder* fn) mfilenames.emplace_back(fn); } -std::tuple<TFile*, std::string> DataInputDescriptor::getFileFolder(int counter) +std::tuple<TFile*, std::string> DataInputDescriptor::getFileFolder(int counter, int numTF) { - std::string filename(""); std::string directoryName(""); - int cnt = mfilenames[0]->numberOfTimeFrames; - if (counter >= 0 && counter < getNumberTimeFrames()) { - for (int ii = 0; ii < getNumberInputfiles(); ii++) { - if (counter < cnt) { - filename = mfilenames[ii]->fileName; - cnt -= mfilenames[ii]->numberOfTimeFrames; - directoryName = (mfilenames[ii]->listOfTimeFrameKeys)[counter - cnt]; - break; - } else { - cnt += mfilenames[ii + 1]->numberOfTimeFrames; - } + // no files left + if (counter >= getNumberInputfiles()) { + return std::make_tuple((TFile*)nullptr, directoryName); + } + + // no TF left + if (mfilenames[counter]->numberOfTimeFrames > 0 && numTF >= mfilenames[counter]->numberOfTimeFrames) { + return std::make_tuple((TFile*)nullptr, directoryName); + } + + // open file + auto filename = mfilenames[counter]->fileName; + if (mcurrentFile) { + if (mcurrentFile->GetName() != filename) { + closeInputFile(); + mcurrentFile = TFile::Open(filename.c_str()); } + } else { + mcurrentFile = TFile::Open(filename.c_str()); + } + if (!mcurrentFile) { + throw std::runtime_error(fmt::format("Couldn't open file \"{}\"!", filename)); + } - if (mcurrentFile) { - if (mcurrentFile->GetName() != filename) { - closeInputFile(); - mcurrentFile = TFile::Open(filename.c_str()); + // get the directory name + if (mfilenames[counter]->numberOfTimeFrames <= 0) { + std::regex TFRegex = std::regex("TF_[0-9]+"); + TList* keyList = mcurrentFile->GetListOfKeys(); + + // extract TF numbers and sort accordingly + std::list<uint64_t> folderNumbers; + for (auto key : *keyList) { + if (std::regex_match(((TObjString*)key)->GetString().Data(), TFRegex)) { + auto folderNumber = std::stoul(std::string(((TObjString*)key)->GetString().Data()).substr(3)); + folderNumbers.emplace_back(folderNumber); } - } else { - mcurrentFile = TFile::Open(filename.c_str()); } - if (!mcurrentFile) { - throw std::runtime_error(fmt::format("Couldn't open file \"{}\"!", filename)); + folderNumbers.sort(); + + for (auto folderNumber : folderNumbers) { + auto folderName = "TF_" + std::to_string(folderNumber); + mfilenames[counter]->listOfTimeFrameKeys.emplace_back(folderName); } - } else { - closeInputFile(); + mfilenames[counter]->numberOfTimeFrames = mfilenames[counter]->listOfTimeFrameKeys.size(); } + directoryName = (mfilenames[counter]->listOfTimeFrameKeys)[numTF]; return std::make_tuple(mcurrentFile, directoryName); } @@ -143,6 +135,7 @@ void DataInputDescriptor::closeInputFile() { if (mcurrentFile) { mcurrentFile->Close(); + mcurrentFile = nullptr; delete mcurrentFile; } } @@ -160,8 +153,10 @@ int DataInputDescriptor::fillInputfiles() try { std::ifstream filelist(fileName); while (std::getline(filelist, fileName)) { - if (getFilenamesRegexString().empty() || - std::regex_match(fileName, getFilenamesRegex())) { + // remove white spaces, empty lines are skipped + fileName.erase(std::remove_if(fileName.begin(), fileName.end(), ::isspace), fileName.end()); + if (!fileName.empty() && (getFilenamesRegexString().empty() || + std::regex_match(fileName, getFilenamesRegex()))) { addFileNameHolder(makeFileNameHolder(fileName)); } } @@ -466,7 +461,7 @@ DataInputDescriptor* DataInputDirector::getDataInputDescriptor(header::DataHeade return result; } -std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader dh, int counter, std::string treename) +std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader dh, int counter, int numTF, std::string treename) { std::unique_ptr<TTreeReader> reader = nullptr; auto didesc = getDataInputDescriptor(dh); @@ -475,7 +470,7 @@ std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader didesc = mdefaultDataInputDescriptor; } - auto [file, directory] = didesc->getFileFolder(counter); + auto [file, directory] = didesc->getFileFolder(counter, numTF); if (file) { treename = directory + "/" + treename; reader = std::make_unique<TTreeReader>(treename.c_str(), file); @@ -487,19 +482,19 @@ std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader return reader; } -std::tuple<TFile*, std::string> DataInputDirector::getFileFolder(header::DataHeader dh, int counter) +std::tuple<TFile*, std::string> DataInputDirector::getFileFolder(header::DataHeader dh, int counter, int numTF) { auto didesc = getDataInputDescriptor(dh); // if NOT match then use defaultDataInputDescriptor if (!didesc) { didesc = mdefaultDataInputDescriptor; } - auto [file, directory] = didesc->getFileFolder(counter); + auto [file, directory] = didesc->getFileFolder(counter, numTF); return std::make_tuple(file, directory); } -TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter) +TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter, int numTF) { std::string treename; TTree* tree = nullptr; @@ -516,7 +511,7 @@ TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter) treename = aod::datamodel::getTreeName(dh); } - auto [file, directory] = didesc->getFileFolder(counter); + auto [file, directory] = didesc->getFileFolder(counter, numTF); if (file) { treename = directory + "/" + treename; tree = (TTree*)file->Get(treename.c_str()); @@ -549,9 +544,9 @@ bool DataInputDirector::isValid() bool DataInputDirector::atEnd(int counter) { - bool status = mdefaultDataInputDescriptor->getNumberTimeFrames() <= counter; + bool status = mdefaultDataInputDescriptor->getNumberInputfiles() <= counter; for (auto didesc : mdataInputDescriptors) { - status &= (didesc->getNumberTimeFrames() <= counter); + status &= (didesc->getNumberInputfiles() <= counter); } return status; diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index 99f10171207b8..f1f8857395457 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -142,7 +142,6 @@ void DataOutputDirector::reset() mtreeFilenames.clear(); closeDataFiles(); mfilePtrs.clear(); - mfolderCounts.clear(); mfilenameBase = std::string(""); }; @@ -184,10 +183,9 @@ void DataOutputDirector::readString(std::string const& keepString) auto last = std::unique(mfilenameBases.begin(), mfilenameBases.end()); mfilenameBases.erase(last, mfilenameBases.end()); - // prepare list mfilePtrs of TFile and mfolderCounts + // prepare list mfilePtrs of TFile for (auto fn : mfilenameBases) { mfilePtrs.emplace_back(new TFile()); - mfolderCounts.emplace_back(-1); } } @@ -308,6 +306,7 @@ std::tuple<std::string, std::string, int> DataOutputDirector::readJsonDocument(D if (dodirItem.HasMember(itemName)) { if (dodirItem[itemName].IsString()) { fmode = dodirItem[itemName].GetString(); + setFileMode(fmode); } else { LOGP(ERROR, "Check the JSON document! Item \"{}\" must be a string!", itemName); return memptyanswer; @@ -318,6 +317,7 @@ std::tuple<std::string, std::string, int> DataOutputDirector::readJsonDocument(D if (dodirItem.HasMember(itemName)) { if (dodirItem[itemName].IsNumber()) { ntfm = dodirItem[itemName].GetInt(); + setNumberTimeFramesToMerge(ntfm); } else { LOGP(ERROR, "Check the JSON document! Item \"{}\" must be a number!", itemName); return memptyanswer; @@ -428,9 +428,7 @@ std::vector<DataOutputDescriptor*> DataOutputDirector::getDataOutputDescriptors( return result; } -std::tuple<TFile*, std::string> DataOutputDirector::getFileFolder(DataOutputDescriptor* dodesc, - int ntf, int ntfmerge, - std::string filemode) +std::tuple<TFile*, std::string> DataOutputDirector::getFileFolder(DataOutputDescriptor* dodesc, uint64_t folderNumber) { // initialisation TFile* filePtr = nullptr; @@ -442,15 +440,14 @@ std::tuple<TFile*, std::string> DataOutputDirector::getFileFolder(DataOutputDesc int ind = std::distance(mfilenameBases.begin(), it); if (!mfilePtrs[ind]->IsOpen()) { auto fn = mfilenameBases[ind] + ".root"; - mfilePtrs[ind] = new TFile(fn.c_str(), filemode.c_str()); + mfilePtrs[ind] = new TFile(fn.c_str(), mfileMode.c_str()); } filePtr = mfilePtrs[ind]; - // check if new folder TF_* is needed - int fcnt = (int)(ntf / ntfmerge); - directoryName = "TF_" + std::to_string(fcnt) + "/"; - if ((ntf % ntfmerge) == 0 && fcnt > mfolderCounts[ind]) { - mfolderCounts[ind] = fcnt; + // check if folder TF_* exists + directoryName = "TF_" + std::to_string(folderNumber) + "/"; + auto key = filePtr->GetKey(directoryName.c_str()); + if (!key) { filePtr->mkdir(directoryName.c_str()); } filePtr->cd(directoryName.c_str()); @@ -494,7 +491,6 @@ void DataOutputDirector::setFilenameBase(std::string dfn) mtreeFilenames.clear(); closeDataFiles(); mfilePtrs.clear(); - mfolderCounts.clear(); // loop over DataOutputDescritors for (auto dodesc : mDataOutputDescriptors) { @@ -515,10 +511,9 @@ void DataOutputDirector::setFilenameBase(std::string dfn) auto last = std::unique(mfilenameBases.begin(), mfilenameBases.end()); mfilenameBases.erase(last, mfilenameBases.end()); - // prepare list mfilePtrs of TFile and mfolderCounts + // prepare list mfilePtrs of TFile for (auto fn : mfilenameBases) { mfilePtrs.emplace_back(new TFile()); - mfolderCounts.emplace_back(-1); } } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 702b7514b139c..7ce8a9ab68a72 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -208,8 +208,8 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext static_cast<DataAllocator::SubSpecificationType>(compile_time_hash("internal-dpl-aod-reader")), Lifetime::Enumeration}}, {}, readers::AODReaderHelpers::rootFileReaderCallback(), - {ConfigParamSpec{"aod-file", VariantType::String, "aod.root", {"Input AOD file"}}, - ConfigParamSpec{"json-file", VariantType::String, {"json configuration file"}}, + {ConfigParamSpec{"aod-file", VariantType::String, {"Input AOD file"}}, + ConfigParamSpec{"aod-reader-json", VariantType::String, {"json configuration file"}}, ConfigParamSpec{"time-limit", VariantType::Int64, 0ll, {"Maximum run time limit in seconds"}}, ConfigParamSpec{"start-value-enumeration", VariantType::Int64, 0ll, {"initial value for the enumeration"}}, ConfigParamSpec{"end-value-enumeration", VariantType::Int64, -1ll, {"final value for the enumeration"}}, @@ -263,7 +263,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } break; case Lifetime::Condition: { if (hasConditionOption == false) { - processor.options.emplace_back(ConfigParamSpec{"condition-backend", VariantType::String, "http://localhost:8080", {"Url for CCDB"}}); + processor.options.emplace_back(ConfigParamSpec{"condition-backend", VariantType::String, "http://localhost:8080", {"URL for CCDB"}}); processor.options.emplace_back(ConfigParamSpec{"condition-timestamp", VariantType::String, "", {"Force timestamp for CCDB lookup"}}); hasConditionOption = true; } @@ -380,26 +380,27 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // outputTypes = isAOD*2 + isdangling*1 + 0 auto [OutputsInputs, outputTypes] = analyzeOutputs(workflow); + // create DataOutputDescriptor + std::shared_ptr<DataOutputDirector> dod = getDataOutputDirector(ctx.options(), OutputsInputs, outputTypes); + // file sink for any AOD output extraSpecs.clear(); - // select outputs of type AOD + // select outputs of type AOD which need to be saved + // ATTENTION: if there are dangling outputs the getGlobalAODSink + // has to be created in any case! std::vector<InputSpec> outputsInputsAOD; - std::vector<bool> isdangling; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { if ((outputTypes[ii] & 2) == 2) { - - // is this dangling ? - if ((outputTypes[ii] & 1) == 1) { + auto ds = dod->getDataOutputDescriptors(OutputsInputs[ii]); + if (ds.size() > 0 || (outputTypes[ii] & 1) == 1) { outputsInputsAOD.emplace_back(OutputsInputs[ii]); - isdangling.emplace_back((outputTypes[ii] & 1) == 1); } } } if (outputsInputsAOD.size() > 0) { - auto fileSink = CommonDataProcessors::getGlobalAODSink(outputsInputsAOD, - isdangling); + auto fileSink = CommonDataProcessors::getGlobalAODSink(dod, outputsInputsAOD); extraSpecs.push_back(fileSink); } workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); @@ -734,6 +735,84 @@ struct DataMatcherId { size_t id; }; +std::shared_ptr<DataOutputDirector> WorkflowHelpers::getDataOutputDirector(ConfigParamRegistry const& options, std::vector<InputSpec> const& OutputsInputs, std::vector<unsigned char> const& outputTypes) +{ + std::shared_ptr<DataOutputDirector> dod = std::make_shared<DataOutputDirector>(); + + // analyze options and take actions accordingly + // default values + std::string fnb, fnbase("AnalysisResults_trees"); + std::string fmo, filemode("RECREATE"); + int ntfm, ntfmerge = 1; + + // values from json + if (options.isSet("aod-writer-json")) { + auto fnjson = options.get<std::string>("aod-writer-json"); + if (!fnjson.empty()) { + std::tie(fnb, fmo, ntfm) = dod->readJson(fnjson); + if (!fnb.empty()) { + fnbase = fnb; + } + if (!fmo.empty()) { + filemode = fmo; + } + if (ntfm > 0) { + ntfmerge = ntfm; + } + } + } + + // values from command line options, information from json is overwritten + if (options.isSet("aod-writer-resfile")) { + fnb = options.get<std::string>("aod-writer-resfile"); + if (!fnb.empty()) { + fnbase = fnb; + } + } + if (options.isSet("aod-writer-resmode")) { + fmo = options.get<std::string>("aod-writer-resmode"); + if (!fmo.empty()) { + filemode = fmo; + } + } + if (options.isSet("aod-writer-ntfmerge")) { + ntfm = options.get<int>("aod-writer-ntfmerge"); + if (ntfm > 0) { + ntfmerge = ntfm; + } + } + // parse the keepString + if (options.isSet("aod-writer-keep")) { + auto keepString = options.get<std::string>("aod-writer-keep"); + if (!keepString.empty()) { + + dod->reset(); + std::string d("dangling"); + if (d.find(keepString) == 0) { + + // use the dangling outputs + std::vector<InputSpec> danglingOutputs; + for (auto ii = 0; ii < OutputsInputs.size(); ii++) { + if ((outputTypes[ii] & 2) == 2 && (outputTypes[ii] & 1) == 1) { + danglingOutputs.emplace_back(OutputsInputs[ii]); + } + } + dod->readSpecs(danglingOutputs); + + } else { + + // use the keep string + dod->readString(keepString); + } + } + } + dod->setFilenameBase(fnbase); + dod->setFileMode(filemode); + dod->setNumberTimeFramesToMerge(ntfmerge); + + return dod; +} + std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers::analyzeOutputs(WorkflowSpec const& workflow) { // compute total number of input/output diff --git a/Framework/Core/src/WorkflowHelpers.h b/Framework/Core/src/WorkflowHelpers.h index 2f740609effcf..3e90491cb751e 100644 --- a/Framework/Core/src/WorkflowHelpers.h +++ b/Framework/Core/src/WorkflowHelpers.h @@ -14,6 +14,7 @@ #include "Framework/OutputSpec.h" #include "Framework/ForwardRoute.h" #include "Framework/WorkflowSpec.h" +#include "Framework/DataOutputDirector.h" #include "DataProcessorInfo.h" #include <cstddef> @@ -173,6 +174,8 @@ struct WorkflowHelpers { const std::vector<DeviceConnectionEdge>& edges, const std::vector<size_t>& index); + static std::shared_ptr<DataOutputDirector> getDataOutputDirector(ConfigParamRegistry const& options, std::vector<InputSpec> const& OutputsInputs, std::vector<unsigned char> const& outputTypes); + /// Given @a workflow it gathers all the OutputSpec and in addition provides /// the information whether and output is dangling and/or of type AOD /// An Output is dangling if it does not have a corresponding InputSpec. diff --git a/Framework/Core/test/test_DataInputDirector.cxx b/Framework/Core/test/test_DataInputDirector.cxx index f5a6ed352213a..ac77c341151ae 100644 --- a/Framework/Core/test/test_DataInputDirector.cxx +++ b/Framework/Core/test/test_DataInputDirector.cxx @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(TestDatainputDirector) auto dh = DataHeader(DataDescription{"DUE"}, DataOrigin{"AOD"}, DataHeader::SubSpecificationType{0}); - auto [file1, directory1] = didir1.getFileFolder(dh, 1); + //auto [file1, directory1] = didir1.getFileFolder(dh, 1, 0); //BOOST_CHECK_EQUAL(file1->GetName(), "Bresults_1.root"); auto didesc = didir1.getDataInputDescriptor(dh); @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(TestDatainputDirector) didir2.printOut(); printf("\n\n"); BOOST_CHECK(didir2.readJson(jsonFile)); - auto [file2, directory2] = didir2.getFileFolder(dh, 1); + //auto [file2, directory2] = didir2.getFileFolder(dh, 1, 0); //BOOST_CHECK_EQUAL(file2->GetName(), "Bresults_1.root"); didesc = didir2.getDataInputDescriptor(dh); From 5682187fd62b8b8951756c9e13c2cfdf262c5e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Thu, 22 Oct 2020 00:12:59 +0200 Subject: [PATCH 1021/1751] PWGHF: Reduce size of track index skim table. (#4651) - Remove collision column. - Reduce size of the flag column type. --- Analysis/DataModel/include/Analysis/HFSecondaryVertex.h | 5 +---- Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 3 ++- Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 3 ++- Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 9 +++------ 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index b8a5caeae6330..67a9303d370cc 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -43,22 +43,19 @@ using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, HFSelTrack, pidRespT namespace hf_track_index { -DECLARE_SOA_INDEX_COLUMN(Collision, collision); DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, BigTracks, "fIndex0"); DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, BigTracks, "fIndex1"); DECLARE_SOA_INDEX_COLUMN_FULL(Index2, index2, int, BigTracks, "fIndex2"); DECLARE_SOA_INDEX_COLUMN_FULL(Index3, index3, int, BigTracks, "fIndex3"); -DECLARE_SOA_COLUMN(HFflag, hfflag, int); +DECLARE_SOA_COLUMN(HFflag, hfflag, uint8_t); } // namespace hf_track_index DECLARE_SOA_TABLE(HfTrackIndexProng2, "AOD", "HFTRACKIDXP2", - hf_track_index::CollisionId, hf_track_index::Index0Id, hf_track_index::Index1Id, hf_track_index::HFflag); DECLARE_SOA_TABLE(HfTrackIndexProng3, "AOD", "HFTRACKIDXP3", - hf_track_index::CollisionId, hf_track_index::Index0Id, hf_track_index::Index1Id, hf_track_index::Index2Id, diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 2592e543a7975..5185085e64c85 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -45,7 +45,7 @@ struct HFCandidateCreator2Prong { double massPiK{0.}; double massKPi{0.}; - void process(aod::Collision const& collision, + void process(aod::Collisions const& collisions, aod::HfTrackIndexProng2 const& rowsTrackIndexProng2, aod::BigTracks const& tracks) { @@ -63,6 +63,7 @@ struct HFCandidateCreator2Prong { for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { auto trackParVarPos1 = getTrackParCov(rowTrackIndexProng2.index0()); auto trackParVarNeg1 = getTrackParCov(rowTrackIndexProng2.index1()); + auto collision = rowTrackIndexProng2.index0().collision(); // reconstruct the 2-prong secondary vertex if (df.process(trackParVarPos1, trackParVarNeg1) == 0) diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 4468db49e558e..07096f904515c 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -44,7 +44,7 @@ struct HFCandidateCreator3Prong { double massK = RecoDecay::getMassPDG(kKPlus); double massPiKPi{0.}; - void process(aod::Collision const& collision, + void process(aod::Collisions const& collisions, aod::HfTrackIndexProng3 const& rowsTrackIndexProng3, aod::BigTracks const& tracks) { @@ -63,6 +63,7 @@ struct HFCandidateCreator3Prong { auto trackParVar0 = getTrackParCov(rowTrackIndexProng3.index0()); auto trackParVar1 = getTrackParCov(rowTrackIndexProng3.index1()); auto trackParVar2 = getTrackParCov(rowTrackIndexProng3.index2()); + auto collision = rowTrackIndexProng3.index0().collision(); // reconstruct the 3-prong secondary vertex if (df.process(trackParVar0, trackParVar1, trackParVar2) == 0) diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 6aa4b1c4647c0..fef7ebac5c865 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -276,8 +276,7 @@ struct HFTrackIndexSkimsCreator { if (isSelectedCandD0) { // fill table row - rowTrackIndexProng2(trackPos1.collisionId(), - trackPos1.globalIndex(), + rowTrackIndexProng2(trackPos1.globalIndex(), trackNeg1.globalIndex(), 1); // fill histograms @@ -332,8 +331,7 @@ struct HFTrackIndexSkimsCreator { } // fill table row - rowTrackIndexProng3(trackPos1.collisionId(), - trackPos1.globalIndex(), + rowTrackIndexProng3(trackPos1.globalIndex(), trackNeg1.globalIndex(), trackPos2.globalIndex(), 2); @@ -392,8 +390,7 @@ struct HFTrackIndexSkimsCreator { } // fill table row - rowTrackIndexProng3(trackNeg1.collisionId(), - trackNeg1.globalIndex(), + rowTrackIndexProng3(trackNeg1.globalIndex(), trackPos1.globalIndex(), trackNeg2.globalIndex(), 2); From f94704bffd6c3e6e58739e212234f97fa691f1ac Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Thu, 22 Oct 2020 09:50:22 +0200 Subject: [PATCH 1022/1751] [QC-447] Allow to specify OutputSpecs of DataSamplingPolicies (#4635) --- Utilities/DataSampling/README.md | 7 ++- .../DataSampling/src/DataSamplingPolicy.cxx | 53 ++++++++++++------- .../test/test_DataSamplingPolicy.cxx | 27 +++++++++- 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/Utilities/DataSampling/README.md b/Utilities/DataSampling/README.md index 0f74547dab51b..ad9abc8ba2ba5 100644 --- a/Utilities/DataSampling/README.md +++ b/Utilities/DataSampling/README.md @@ -1,6 +1,6 @@ ## 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). +Data Sampling provides a possibility to sample data in DPL workflows based on certain conditions ( 5% randomly, when a 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) or by using dedicated interface methods (for advanced use). ``` { "id": "policy_example1", # name of the policy @@ -11,6 +11,9 @@ Data Sampling provides possibility to sample data in DPL workflows, basing on ce ], # list of data that should be sampled, the format is: # binding1:origin1/description1/subSpec1[;binding2:...] "query": "clusters:TPC/CLUSTERS/0;tracks:TPC/TRACKS/0", + # optional list of outputspecs for sampled data, matching the query + # if not present or specified, the default format is used + "outputs": "sampled_clusters:DS/CLUSTERS/0;sampled_tracks:DS/TRACKS/0", "samplingConditions": [ # list of sampling conditions { "condition": "random", # condition type @@ -96,4 +99,4 @@ The following sampling conditions are available. When more than one is used, a p "className": "o2::quality_control_modules::example::ExampleCondition", "customParam": "value" } -``` \ No newline at end of file +``` diff --git a/Utilities/DataSampling/src/DataSamplingPolicy.cxx b/Utilities/DataSampling/src/DataSamplingPolicy.cxx index 61b66defd783f..452f61ab14cfd 100644 --- a/Utilities/DataSampling/src/DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/src/DataSamplingPolicy.cxx @@ -55,27 +55,40 @@ DataSamplingPolicy DataSamplingPolicy::fromConfiguration(const ptree& config) size_t outputId = 0; std::vector<InputSpec> inputSpecs = DataDescriptorQueryBuilder::parse(config.get<std::string>("query").c_str()); - - for (const auto& inputSpec : inputSpecs) { - - if (DataSpecUtils::getOptionalSubSpec(inputSpec).has_value()) { - OutputSpec outputSpec{ - {inputSpec.binding}, - createPolicyDataOrigin(), - createPolicyDataDescription(name, outputId++), - DataSpecUtils::getOptionalSubSpec(inputSpec).value(), - inputSpec.lifetime}; - - policy.registerPath(inputSpec, outputSpec); - - } else { - OutputSpec outputSpec{ - {inputSpec.binding}, - {createPolicyDataOrigin(), createPolicyDataDescription(name, outputId++)}, - inputSpec.lifetime}; - - policy.registerPath(inputSpec, outputSpec); + std::vector<OutputSpec> outputSpecs; + // Optionally user can specify the outputs, + if (auto outputsQuery = config.get<std::string>("outputs", ""); !outputsQuery.empty()) { + std::vector<InputSpec> outputsAsInputSpecs = DataDescriptorQueryBuilder::parse(outputsQuery.c_str()); + if (outputsAsInputSpecs.size() != inputSpecs.size()) { + throw std::runtime_error( + "The number of outputs should match the number of inputs (queries)," + " which is not the case for the policy '" + + name + "'(" + + std::to_string(inputSpecs.size()) + " inputs vs. " + std::to_string(outputsAsInputSpecs.size()) + " outputs)."); + } + for (const auto& outputAsInputSpec : outputsAsInputSpecs) { + outputSpecs.emplace_back(DataSpecUtils::asOutputSpec(outputAsInputSpec)); } + } else { // otherwise default format will be used + for (const auto& inputSpec : inputSpecs) { + if (DataSpecUtils::getOptionalSubSpec(inputSpec).has_value()) { + outputSpecs.emplace_back(OutputSpec{ + {inputSpec.binding}, + createPolicyDataOrigin(), + createPolicyDataDescription(name, outputId++), + DataSpecUtils::getOptionalSubSpec(inputSpec).value(), + inputSpec.lifetime}); + } else { + outputSpecs.emplace_back(OutputSpec{ + {inputSpec.binding}, + {createPolicyDataOrigin(), createPolicyDataDescription(name, outputId++)}, + inputSpec.lifetime}); + } + } + } + assert(inputSpecs.size() == outputSpecs.size()); + for (size_t i = 0; i < inputSpecs.size(); i++) { + policy.registerPath(inputSpecs[i], outputSpecs[i]); } for (const auto& conditionConfig : config.get_child("samplingConditions")) { diff --git a/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx b/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx index 5f65e5be3e67b..1723dc913fe28 100644 --- a/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx @@ -32,6 +32,7 @@ using namespace o2::header; // "aidlalala2" // ] // "query" : "c:TST/CHLEB/33;m:TST/MLEKO/33", +// "outputs" : "cc:TST/CHLEB_S/33;mm:TST/MLEKO_S/33", "": "this is optional, if not specified, default format is used", // "samplingConditions" : [ // { // "condition" : "random", @@ -80,13 +81,37 @@ BOOST_AUTO_TEST_CASE(DataSamplingPolicyFromConfiguration) } config.put("id", "too-long-policy-name"); - { auto policy = std::move(DataSamplingPolicy::fromConfiguration(config)); BOOST_CHECK_EQUAL(policy.getName(), "too-long-policy-name"); BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"DS", "too-long-polic0", 33})); BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"DS", "too-long-polic1", 33})); } + + // with custom outputs + config.put("outputs", "cc:TST/CHLEB_S/33;mm:TST/MLEKO_S/33"); + { + auto policy = std::move(DataSamplingPolicy::fromConfiguration(config)); + + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"TST", "CHLEB_S", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"TST", "MLEKO_S", 33})); + const auto& map = policy.getPathMap(); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "CHLEB", 33})).second == (OutputSpec{"TST", "CHLEB_S", 33})); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "MLEKO", 33})).second == (OutputSpec{"TST", "MLEKO_S", 33})); + BOOST_CHECK_EQUAL(map.size(), 2); + } + // with custom outputs which are wildcards + config.put("outputs", "cc:TST/CHLEB_S;mm:TST/MLEKO_S"); + { + auto policy = std::move(DataSamplingPolicy::fromConfiguration(config)); + + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "CHLEB", 33})) == (Output{"TST", "CHLEB_S", 33})); + BOOST_CHECK((policy.prepareOutput(ConcreteDataMatcher{"TST", "MLEKO", 33})) == (Output{"TST", "MLEKO_S", 33})); + const auto& map = policy.getPathMap(); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "CHLEB", 33})).second == (OutputSpec{{"TST", "CHLEB_S"}})); + BOOST_CHECK((*map.find(ConcreteDataMatcher{"TST", "MLEKO", 33})).second == (OutputSpec{{"TST", "MLEKO_S"}})); + BOOST_CHECK_EQUAL(map.size(), 2); + } } BOOST_AUTO_TEST_CASE(DataSamplingPolicyFromMethods) From 8b31674e2bddddf3949fbb5baf85cb2df7d48f8b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 11:05:27 +0200 Subject: [PATCH 1023/1751] Add missing include again that was removed in 5ae7a0427b41a506566e28197f071116ac27b9e7 --- Framework/Core/src/DataInputDirector.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 7e5855763f1b6..ecaa59ea4a123 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -17,6 +17,7 @@ #include "rapidjson/filereadstream.h" #include "TGrid.h" +#include "TObjString.h" namespace o2 { From 7c57a74a6a0e2f6ed4b10cd89ee6f3427da27855 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Wed, 21 Oct 2020 22:19:20 +0300 Subject: [PATCH 1024/1751] Analysis: make readability-braces-around-statements happy --- Analysis/Core/include/Analysis/AnalysisCut.h | 40 ++- Analysis/Core/include/Analysis/HistHelpers.h | 25 +- .../Core/include/Analysis/HistogramManager.h | 3 +- Analysis/Core/include/Analysis/MC.h | 32 +- Analysis/Core/include/Analysis/PairCuts.h | 31 +- Analysis/Core/include/Analysis/StepTHn.h | 3 +- Analysis/Core/include/Analysis/VarManager.h | 112 ++++--- Analysis/Core/src/AnalysisCompositeCut.cxx | 11 +- Analysis/Core/src/CorrelationContainer.cxx | 217 +++++++++----- Analysis/Core/src/HistogramManager.cxx | 281 ++++++++++++------ Analysis/Core/src/JetFinder.cxx | 6 +- Analysis/Core/src/StepTHn.cxx | 67 +++-- Analysis/Core/src/VarManager.cxx | 15 +- Analysis/DataModel/include/PID/TOFReso.h | 3 +- Analysis/DataModel/src/aodDataModelGraph.cxx | 4 +- Analysis/Tasks/PWGCF/correlations.cxx | 54 ++-- Analysis/Tasks/PWGCF/correlationsFiltered.cxx | 82 +++-- Analysis/Tasks/PWGCF/correlationsMixed.cxx | 82 +++-- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 10 +- Analysis/Tasks/PWGCF/filterCF.cxx | 8 +- Analysis/Tasks/PWGDQ/dileptonEE.cxx | 15 +- Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 24 +- Analysis/Tasks/PWGDQ/tableMaker.cxx | 18 +- Analysis/Tasks/PWGDQ/tableMaker_pp.cxx | 18 +- Analysis/Tasks/PWGDQ/tableReader.cxx | 42 ++- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 3 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 3 +- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 30 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 24 +- Analysis/Tasks/PWGJE/jetfinder.cxx | 9 +- .../Tasks/PWGJE/jetfinderhadronrecoil.cxx | 3 +- Analysis/Tasks/PWGJE/jetsubstructure.cxx | 3 +- Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx | 9 +- Analysis/Tasks/PWGLF/cascadeconsumer.cxx | 18 +- Analysis/Tasks/PWGLF/cascadefinder.cxx | 54 ++-- Analysis/Tasks/PWGLF/cascadeproducer.cxx | 9 +- Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx | 9 +- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 36 ++- Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 3 +- Analysis/Tasks/PWGLF/mcspectraefficiency.cxx | 18 +- Analysis/Tasks/PWGLF/raacharged.cxx | 58 ++-- Analysis/Tasks/PWGLF/spectraTPC.cxx | 3 +- Analysis/Tasks/PWGLF/trackchecks.cxx | 61 ++-- Analysis/Tasks/PWGUD/upcAnalysis.cxx | 24 +- Analysis/Tasks/centralityQa.cxx | 6 +- Analysis/Tasks/eventSelectionQa.cxx | 36 ++- Analysis/Tasks/multiplicityQa.cxx | 6 +- Analysis/Tasks/qaTask.cxx | 6 +- Analysis/Tasks/trackqa.cxx | 6 +- .../Tutorials/src/histogramTrackSelection.cxx | 5 +- Analysis/Tutorials/src/mcHistograms.cxx | 6 +- 51 files changed, 1080 insertions(+), 571 deletions(-) diff --git a/Analysis/Core/include/Analysis/AnalysisCut.h b/Analysis/Core/include/Analysis/AnalysisCut.h index 4aaf6980b0831..d094e0d6cffe8 100644 --- a/Analysis/Core/include/Analysis/AnalysisCut.h +++ b/Analysis/Core/include/Analysis/AnalysisCut.h @@ -79,8 +79,9 @@ void AnalysisCut::AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude, CutContainer cut = {}; if constexpr (std::is_same_v<T1, TF1*>) { - if (dependentVar < 0) + if (dependentVar < 0) { return; + } cut.fFuncLow = cutLow; cut.fLow = -9999.0; } else { @@ -88,8 +89,9 @@ void AnalysisCut::AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude, cut.fLow = cutLow; } if constexpr (std::is_same_v<T2, TF1*>) { - if (dependentVar < 0) + if (dependentVar < 0) { return; + } cut.fFuncHigh = cutHigh; cut.fHigh = -9999.0; } else { @@ -104,15 +106,17 @@ void AnalysisCut::AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude, cut.fDepLow = depCutLow; cut.fDepHigh = depCutHigh; cut.fDepExclude = depCutExclude; - if (dependentVar != -1) + if (dependentVar != -1) { fgUsedVars.push_back(dependentVar); + } cut.fDepVar2 = dependentVar2; cut.fDep2Low = depCut2Low; cut.fDep2High = depCut2High; cut.fDep2Exclude = depCut2Exclude; - if (dependentVar2 != -1) + if (dependentVar2 != -1) { fgUsedVars.push_back(dependentVar2); + } fCuts.push_back(cut); } @@ -128,34 +132,42 @@ inline bool AnalysisCut::IsSelected(float* values) // check whether a dependent variables were enabled and if they are in the requested range if ((*it).fDepVar != -1) { bool inRange = (values[(*it).fDepVar] > (*it).fDepLow && values[(*it).fDepVar] <= (*it).fDepHigh); - if (!inRange && !((*it).fDepExclude)) + if (!inRange && !((*it).fDepExclude)) { continue; - if (inRange && (*it).fDepExclude) + } + if (inRange && (*it).fDepExclude) { continue; + } } if ((*it).fDepVar2 != -1) { bool inRange = (values[(*it).fDepVar2] > (*it).fDep2Low && values[(*it).fDepVar2] <= (*it).fDep2High); - if (!inRange && !((*it).fDep2Exclude)) + if (!inRange && !((*it).fDep2Exclude)) { continue; - if (inRange && (*it).fDep2Exclude) + } + if (inRange && (*it).fDep2Exclude) { continue; + } } // obtain the low and high cut values (either directly as a value or from a function) float cutLow, cutHigh; - if ((*it).fFuncLow) + if ((*it).fFuncLow) { cutLow = ((*it).fFuncLow)->Eval(values[(*it).fDepVar]); - else + } else { cutLow = ((*it).fLow); - if ((*it).fFuncHigh) + } + if ((*it).fFuncHigh) { cutHigh = ((*it).fFuncHigh)->Eval(values[(*it).fDepVar]); - else + } else { cutHigh = ((*it).fHigh); + } // apply the cut and return the decision bool inRange = (values[(*it).fVar] >= cutLow && values[(*it).fVar] <= cutHigh); - if (!inRange && !((*it).fExclude)) + if (!inRange && !((*it).fExclude)) { return false; - if (inRange && ((*it).fExclude)) + } + if (inRange && ((*it).fExclude)) { return false; + } } return true; diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/Analysis/HistHelpers.h index 55fd75b5c4f88..f9481876c3cd7 100644 --- a/Analysis/Core/include/Analysis/HistHelpers.h +++ b/Analysis/Core/include/Analysis/HistHelpers.h @@ -78,11 +78,11 @@ class HistContainer : private RootContainer // if shared pointers or rvalue raw pointers are provided as argument, the existing object is used // otherwise the existing object is copied std::optional<HistType> histVariant{}; - if constexpr (is_shared_ptr<typename std::remove_reference<T>::type>::value) + if constexpr (is_shared_ptr<typename std::remove_reference<T>::type>::value) { histVariant = GetHistVariant(hist); - else if constexpr (std::is_pointer_v<T> && std::is_rvalue_reference_v<decltype(std::forward<T>(hist))>) + } else if constexpr (std::is_pointer_v<T> && std::is_rvalue_reference_v<decltype(std::forward<T>(hist))>) { histVariant = GetHistVariant(std::shared_ptr<std::remove_pointer_t<T>>(hist)); - else { + } else { histVariant = GetHistVariant(std::make_shared<T>(hist)); } if (histVariant) { @@ -145,10 +145,11 @@ class HistContainer : private RootContainer // savety check for n dimensional histograms (runtime overhead) // if (hist->GetNdimensions() != sizeof...(position) - fillWeight) return; double tempArray[] = {static_cast<double>(position)...}; - if constexpr (fillWeight) + if constexpr (fillWeight) { hist->Fill(tempArray, tempArray[sizeof...(Ts) - 1]); - else + } else { hist->Fill(tempArray); + } } } @@ -242,8 +243,9 @@ class Hist { const std::size_t MAX_DIM{10}; const std::size_t nAxes{mAxes.size()}; - if (nAxes == 0 || nAxes > MAX_DIM) + if (nAxes == 0 || nAxes > MAX_DIM) { return nullptr; + } int nBins[MAX_DIM]{0}; double lowerBounds[MAX_DIM]{0.}; @@ -256,10 +258,11 @@ class Hist lowerBounds[i] = mAxes[i].binEdges.front(); upperBounds[i] = mAxes[i].binEdges.back(); title += mAxes[i].name; - if (i < nAxes - 1) + if (i < nAxes - 1) { title += " : "; - else + } else { title += " ]"; + } } // create histogram @@ -275,8 +278,9 @@ class Hist TAxis* axis{GetAxis(i, hist)}; if (axis) { axis->SetTitle(mAxes[i].title.data()); - if constexpr (std::is_base_of_v<THnBase, RootHistType>) + if constexpr (std::is_base_of_v<THnBase, RootHistType>) { axis->SetName((std::to_string(i) + "-" + mAxes[i].name).data()); + } // move the bin edges in case a variable binning was requested if (!mAxes[i].nBins) { @@ -288,8 +292,9 @@ class Hist } } } - if (useWeights) + if (useWeights) { hist->Sumw2(); + } return hist; } diff --git a/Analysis/Core/include/Analysis/HistogramManager.h b/Analysis/Core/include/Analysis/HistogramManager.h index 9da34415a6bff..893b5cc755132 100644 --- a/Analysis/Core/include/Analysis/HistogramManager.h +++ b/Analysis/Core/include/Analysis/HistogramManager.h @@ -42,8 +42,9 @@ class HistogramManager : public TNamed void SetMainHistogramList(THashList* list) { - if (fMainList) + if (fMainList) { delete fMainList; + } fMainList = list; } diff --git a/Analysis/Core/include/Analysis/MC.h b/Analysis/Core/include/Analysis/MC.h index 19895d10c1e3b..aa400966f5d69 100644 --- a/Analysis/Core/include/Analysis/MC.h +++ b/Analysis/Core/include/Analysis/MC.h @@ -75,22 +75,26 @@ bool isPhysicalPrimary(TMCParticles& mcParticles, TMCParticle const& particle) // Initial state particle // Solution for K0L decayed by Pythia6 // -> - if ((ist > 1) && (pdg != 130) && particle.producedByGenerator()) + if ((ist > 1) && (pdg != 130) && particle.producedByGenerator()) { return false; - if ((ist > 1) && !particle.producedByGenerator()) + } + if ((ist > 1) && !particle.producedByGenerator()) { return false; + } // <- - if (!isStable(pdg)) + if (!isStable(pdg)) { return false; + } if (particle.producedByGenerator()) { // Solution for K0L decayed by Pythia6 // -> if (particle.mother0() != -1) { auto mother = mcParticles.iteratorAt(particle.mother0()); - if (std::abs(mother.pdgCode()) == 130) + if (std::abs(mother.pdgCode()) == 130) { return false; + } } // <- // check for direct photon in parton shower @@ -98,8 +102,9 @@ bool isPhysicalPrimary(TMCParticles& mcParticles, TMCParticle const& particle) if (pdg == 22 && particle.daughter0() != -1) { LOGF(debug, "D %d", particle.daughter0()); auto daughter = mcParticles.iteratorAt(particle.daughter0()); - if (daughter.pdgCode() == 22) + if (daughter.pdgCode() == 22) { return false; + } } // <- return true; @@ -112,23 +117,27 @@ bool isPhysicalPrimary(TMCParticles& mcParticles, TMCParticle const& particle) int mpdg = std::abs(mother.pdgCode()); // Check for Sigma0 - if ((mpdg == 3212) && mother.producedByGenerator()) + if ((mpdg == 3212) && mother.producedByGenerator()) { return true; + } // Check if it comes from a pi0 decay - if ((mpdg == kPi0) && mother.producedByGenerator()) + if ((mpdg == kPi0) && mother.producedByGenerator()) { return true; + } // Check if this is a heavy flavor decay product int mfl = int(mpdg / std::pow(10, int(std::log10(mpdg)))); // Light hadron - if (mfl < 4) + if (mfl < 4) { return false; + } // Heavy flavor hadron produced by generator - if (mother.producedByGenerator()) + if (mother.producedByGenerator()) { return true; + } // To be sure that heavy flavor has not been produced in a secondary interaction // Loop back to the generated mother @@ -140,10 +149,11 @@ bool isPhysicalPrimary(TMCParticles& mcParticles, TMCParticle const& particle) mfl = int(mpdg / std::pow(10, int(std::log10(mpdg)))); } - if (mfl < 4) + if (mfl < 4) { return false; - else + } else { return true; + } } }; // namespace MC diff --git a/Analysis/Core/include/Analysis/PairCuts.h b/Analysis/Core/include/Analysis/PairCuts.h index 975ee271df9b8..59f7519d04d91 100644 --- a/Analysis/Core/include/Analysis/PairCuts.h +++ b/Analysis/Core/include/Analysis/PairCuts.h @@ -151,8 +151,9 @@ bool PairCuts::conversionCut(T const& track1, T const& track2, Particle conv, do { //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); - if (cut < 0) + if (cut < 0) { return false; + } double massD1, massD2, massM; @@ -190,13 +191,15 @@ bool PairCuts::conversionCut(T const& track1, T const& track2, Particle conv, do auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); - if (TMath::Abs(massC - massM * massM) > cut * 5) + if (TMath::Abs(massC - massM * massM) > cut * 5) { return false; + } massC = getInvMassSquared(track1, massD1, track2, massD2); mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); - if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) { return true; + } return false; } @@ -265,18 +268,21 @@ double PairCuts::getInvMassSquaredFast(T const& track1, double m0_1, T const& tr // fold onto 0...pi float deltaPhi = TMath::Abs(phi1 - phi2); - while (deltaPhi > TMath::TwoPi()) + while (deltaPhi > TMath::TwoPi()) { deltaPhi -= TMath::TwoPi(); - if (deltaPhi > TMath::Pi()) + } + if (deltaPhi > TMath::Pi()) { deltaPhi = TMath::TwoPi() - deltaPhi; + } float cosDeltaPhi = 0; - if (deltaPhi < TMath::Pi() / 3) + if (deltaPhi < TMath::Pi() / 3) { cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; - else if (deltaPhi < 2 * TMath::Pi() / 3) + } else if (deltaPhi < 2 * TMath::Pi() / 3) { cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); - else + } else { cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); + } double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); @@ -302,12 +308,15 @@ float PairCuts::getDPhiStar(T const& track1, T const& track2, float radius, floa float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); - if (dphistar > M_PI) + if (dphistar > M_PI) { dphistar = M_PI * 2 - dphistar; - if (dphistar < -M_PI) + } + if (dphistar < -M_PI) { dphistar = -M_PI * 2 - dphistar; - if (dphistar > M_PI) // might look funny but is needed + } + if (dphistar > M_PI) { // might look funny but is needed dphistar = M_PI * 2 - dphistar; + } return dphistar; } diff --git a/Analysis/Core/include/Analysis/StepTHn.h b/Analysis/Core/include/Analysis/StepTHn.h index 87e152f9a8d3f..9e3fa76bfcc5a 100644 --- a/Analysis/Core/include/Analysis/StepTHn.h +++ b/Analysis/Core/include/Analysis/StepTHn.h @@ -56,8 +56,9 @@ class StepTHn : public StepTHnBase THnBase* getTHn(Int_t step, Bool_t sparse = kFALSE) override { - if (!mTarget || !mTarget[step]) + if (!mTarget || !mTarget[step]) { createTarget(step, sparse); + } return mTarget[step]; } Int_t getNSteps() override { return mNSteps; } diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index e83e3887f5203..79e9c23448998 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -174,27 +174,31 @@ class VarManager : public TObject static void SetUseVariable(int var) { - if (var >= 0 && var < kNVars) + if (var >= 0 && var < kNVars) { fgUsedVars[var] = kTRUE; + } SetVariableDependencies(); } static void SetUseVars(const bool* usedVars) { for (int i = 0; i < kNVars; ++i) { - if (usedVars[i]) + if (usedVars[i]) { fgUsedVars[i] = true; // overwrite only the variables that are being used since there are more channels to modify the used variables array, independently + } } SetVariableDependencies(); } static void SetUseVars(const std::vector<int> usedVars) { - for (auto& var : usedVars) + for (auto& var : usedVars) { fgUsedVars[var] = true; + } } static bool GetUsedVar(int var) { - if (var >= 0 && var < kNVars) + if (var >= 0 && var < kNVars) { return fgUsedVars[var]; + } return false; } @@ -234,8 +238,9 @@ class VarManager : public TObject template <uint32_t fillMap, typename T> void VarManager::FillEvent(T const& event, float* values) { - if (!values) + if (!values) { values = fgValues; + } if constexpr ((fillMap & BC) > 0) { values[kRunNo] = event.bc().runNumber(); // accessed via Collisions table @@ -243,18 +248,24 @@ void VarManager::FillEvent(T const& event, float* values) } if constexpr ((fillMap & Collision) > 0) { - if (fgUsedVars[kIsINT7]) + if (fgUsedVars[kIsINT7]) { values[kIsINT7] = (event.alias()[kINT7] > 0); - if (fgUsedVars[kIsEMC7]) + } + if (fgUsedVars[kIsEMC7]) { values[kIsEMC7] = (event.alias()[kEMC7] > 0); - if (fgUsedVars[kIsINT7inMUON]) + } + if (fgUsedVars[kIsINT7inMUON]) { values[kIsINT7inMUON] = (event.alias()[kINT7inMUON] > 0); - if (fgUsedVars[kIsMuonSingleLowPt7]) + } + if (fgUsedVars[kIsMuonSingleLowPt7]) { values[kIsMuonSingleLowPt7] = (event.alias()[kMuonSingleLowPt7] > 0); - if (fgUsedVars[kIsMuonUnlikeLowPt7]) + } + if (fgUsedVars[kIsMuonUnlikeLowPt7]) { values[kIsMuonUnlikeLowPt7] = (event.alias()[kMuonUnlikeLowPt7] > 0); - if (fgUsedVars[kIsMuonLikeLowPt7]) + } + if (fgUsedVars[kIsMuonLikeLowPt7]) { values[kIsMuonLikeLowPt7] = (event.alias()[kMuonLikeLowPt7] > 0); + } values[kVtxX] = event.posX(); values[kVtxY] = event.posY(); values[kVtxZ] = event.posZ(); @@ -286,18 +297,24 @@ void VarManager::FillEvent(T const& event, float* values) if constexpr ((fillMap & ReducedEventExtended) > 0) { values[kBC] = event.globalBC(); values[kCentVZERO] = event.centV0M(); - if (fgUsedVars[kIsINT7]) + if (fgUsedVars[kIsINT7]) { values[kIsINT7] = event.triggerAlias() & (uint32_t(1) << kINT7); - if (fgUsedVars[kIsEMC7]) + } + if (fgUsedVars[kIsEMC7]) { values[kIsEMC7] = event.triggerAlias() & (uint32_t(1) << kEMC7); - if (fgUsedVars[kIsINT7inMUON]) + } + if (fgUsedVars[kIsINT7inMUON]) { values[kIsINT7inMUON] = event.triggerAlias() & (uint32_t(1) << kINT7inMUON); - if (fgUsedVars[kIsMuonSingleLowPt7]) + } + if (fgUsedVars[kIsMuonSingleLowPt7]) { values[kIsMuonSingleLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonSingleLowPt7); - if (fgUsedVars[kIsMuonUnlikeLowPt7]) + } + if (fgUsedVars[kIsMuonUnlikeLowPt7]) { values[kIsMuonUnlikeLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonUnlikeLowPt7); - if (fgUsedVars[kIsMuonLikeLowPt7]) + } + if (fgUsedVars[kIsMuonLikeLowPt7]) { values[kIsMuonLikeLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonLikeLowPt7); + } } if constexpr ((fillMap & ReducedEventVtxCov) > 0) { @@ -316,17 +333,21 @@ void VarManager::FillEvent(T const& event, float* values) template <uint32_t fillMap, typename T> void VarManager::FillTrack(T const& track, float* values) { - if (!values) + if (!values) { values = fgValues; + } if constexpr ((fillMap & Track) > 0 || (fillMap & ReducedTrack) > 0) { values[kPt] = track.pt(); - if (fgUsedVars[kPx]) + if (fgUsedVars[kPx]) { values[kPx] = track.px(); - if (fgUsedVars[kPy]) + } + if (fgUsedVars[kPy]) { values[kPy] = track.py(); - if (fgUsedVars[kPz]) + } + if (fgUsedVars[kPz]) { values[kPz] = track.pz(); + } values[kEta] = track.eta(); values[kPhi] = track.phi(); values[kCharge] = track.charge(); @@ -334,24 +355,30 @@ void VarManager::FillTrack(T const& track, float* values) if constexpr ((fillMap & TrackExtra) > 0 || (fillMap & ReducedTrackBarrel) > 0) { values[kPin] = track.tpcInnerParam(); - if (fgUsedVars[kIsITSrefit]) + if (fgUsedVars[kIsITSrefit]) { values[kIsITSrefit] = track.flags() & (uint64_t(1) << 2); // TODO: the flag mapping needs to be updated - if (fgUsedVars[kIsTPCrefit]) + } + if (fgUsedVars[kIsTPCrefit]) { values[kIsTPCrefit] = track.flags() & (uint64_t(1) << 6); // TODO: the flag mapping needs to be updated - if (fgUsedVars[kIsSPDfirst]) + } + if (fgUsedVars[kIsSPDfirst]) { values[kIsSPDfirst] = track.itsClusterMap() & uint8_t(1); - if (fgUsedVars[kIsSPDboth]) + } + if (fgUsedVars[kIsSPDboth]) { values[kIsSPDboth] = track.itsClusterMap() & uint8_t(3); - if (fgUsedVars[kIsSPDany]) + } + if (fgUsedVars[kIsSPDany]) { values[kIsSPDfirst] = (track.itsClusterMap() & uint8_t(1)) || (track.itsClusterMap() & uint8_t(2)); + } values[kITSchi2] = track.itsChi2NCl(); values[kTPCncls] = track.tpcNClsFound(); values[kTPCchi2] = track.tpcChi2NCl(); values[kTrackLength] = track.length(); if constexpr ((fillMap & TrackExtra) > 0) { - if (fgUsedVars[kITSncls]) + if (fgUsedVars[kITSncls]) { values[kITSncls] = track.itsNCls(); // dynamic column + } // TODO: DCA calculation for central data model tracks to be added here values[kTrackDCAxy] = -9999.; values[kTrackDCAz] = -9999.; @@ -359,8 +386,9 @@ void VarManager::FillTrack(T const& track, float* values) if constexpr ((fillMap & ReducedTrackBarrel) > 0) { if (fgUsedVars[kITSncls]) { values[kITSncls] = 0.0; - for (int i = 0; i < 6; ++i) + for (int i = 0; i < 6; ++i) { values[kITSncls] += ((track.itsClusterMap() & (1 << i)) ? 1 : 0); + } } values[kTrackDCAxy] = track.dcaXY(); values[kTrackDCAz] = track.dcaZ(); @@ -414,8 +442,9 @@ void VarManager::FillTrack(T const& track, float* values) template <typename T> void VarManager::FillPair(T const& t1, T const& t2, float* values) { - if (!values) + if (!values) { values = fgValues; + } float mass1 = fgkElectronMass; float mass2 = fgkElectronMass; @@ -423,15 +452,17 @@ void VarManager::FillPair(T const& t1, T const& t2, float* values) bool isMuon1 = t1.filteringFlags() & (1 << 0); bool isMuon2 = t2.filteringFlags() & (1 << 0); - if (isMuon1) + if (isMuon1) { mass1 = fgkMuonMass; - else + } else { mass1 = fgkElectronMass; + } - if (isMuon2) + if (isMuon2) { mass2 = fgkMuonMass; - else + } else { mass2 = fgkElectronMass; + } ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), mass1); ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), mass2); @@ -446,8 +477,9 @@ void VarManager::FillPair(T const& t1, T const& t2, float* values) template <typename T1, typename T2> void VarManager::FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values, float hadronMass) { - if (!values) + 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()); @@ -460,20 +492,24 @@ void VarManager::FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* } if (fgUsedVars[kDeltaPhi]) { double delta = dilepton.phi() - hadron.phi(); - if (delta > 3.0 / 2.0 * TMath::Pi()) + if (delta > 3.0 / 2.0 * TMath::Pi()) { delta -= 2.0 * TMath::Pi(); - if (delta < -0.5 * 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()) + if (delta > TMath::Pi()) { delta = 2 * TMath::Pi() - delta; + } values[kDeltaPhiSym] = delta; } - if (fgUsedVars[kDeltaEta]) + if (fgUsedVars[kDeltaEta]) { values[kDeltaEta] = dilepton.eta() - hadron.eta(); + } } #endif diff --git a/Analysis/Core/src/AnalysisCompositeCut.cxx b/Analysis/Core/src/AnalysisCompositeCut.cxx index fa97af1af2275..9acd248e173af 100644 --- a/Analysis/Core/src/AnalysisCompositeCut.cxx +++ b/Analysis/Core/src/AnalysisCompositeCut.cxx @@ -42,14 +42,17 @@ bool AnalysisCompositeCut::IsSelected(float* values) // apply cuts // for (std::vector<AnalysisCut>::iterator it = fCutList.begin(); it < fCutList.end(); ++it) { - if (fOptionUseAND && !(*it).IsSelected(values)) + if (fOptionUseAND && !(*it).IsSelected(values)) { return false; - if (!fOptionUseAND && (*it).IsSelected(values)) + } + if (!fOptionUseAND && (*it).IsSelected(values)) { return true; + } } - if (fOptionUseAND) + if (fOptionUseAND) { return true; - else + } else { return false; + } } diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 10e8f9443d098..f23f01ecf7ca5 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -88,8 +88,9 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl using BinList = std::vector<Double_t>; - if (strlen(reqHist) == 0) + if (strlen(reqHist) == 0) { return; + } LOGF(info, "Creating CorrelationContainer with %s (binning: %s)", reqHist, binning); @@ -151,10 +152,12 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl Int_t useVtxAxis = 0; Int_t useAliTHn = 1; // 0 = don't use | 1 = with float | 2 = with double - if (TString(reqHist).Contains("Sparse")) + if (TString(reqHist).Contains("Sparse")) { useAliTHn = 0; - if (TString(reqHist).Contains("Double")) + } + if (TString(reqHist).Contains("Double")) { useAliTHn = 2; + } // selection depending on requested histogram Int_t axis = -1; // 0 = pT,lead, 1 = phi,lead @@ -165,8 +168,9 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl axis = 1; title = "d^{2}N_{ch}/d#varphid#eta"; } else if (TString(reqHist).BeginsWith("NumberDensityPhiCentrality")) { - if (TString(reqHist).Contains("Vtx")) + if (TString(reqHist).Contains("Vtx")) { useVtxAxis = 1; + } reqHist = "NumberDensityPhiCentrality"; mHistogramType = reqHist; @@ -182,8 +186,9 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl mHistogramType = reqHist; axis = 3; title = "d^{2}N_{ch}/d#varphid#eta"; - } else + } else { LOGF(fatal, "Invalid histogram requested: %s", reqHist); + } UInt_t nSteps = fgkCFSteps; @@ -252,10 +257,11 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl trackAxisTitle[6] = "Trigger 2 p_{T} (GeV/c)"; } - if (axis >= 2 && useAliTHn == 1) + if (axis >= 2 && useAliTHn == 1) { mPairHist = new StepTHnF("mPairHist", title, nSteps, nTrackVars, iTrackBin, trackBins, trackAxisTitle); - else if (axis >= 2 && useAliTHn == 2) + } else if (axis >= 2 && useAliTHn == 2) { mPairHist = new StepTHnD("mPairHist", title, nSteps, nTrackVars, iTrackBin, trackBins, trackAxisTitle); + } // event level Int_t nEventVars = 2; @@ -321,10 +327,11 @@ TString CorrelationContainer::combineBinning(TString defaultBinning, TString cus for (Int_t i = 0; i < lines->GetEntriesFast(); i++) { TString line(lines->At(i)->GetName()); TString tag = line(0, line.Index(":") + 1); - if (!customBinning.BeginsWith(tag) && !customBinning.Contains(TString("\n") + tag)) + if (!customBinning.BeginsWith(tag) && !customBinning.Contains(TString("\n") + tag)) { binningStr += line + "\n"; - else + } else { LOGF(info, "Using custom binning for %s", tag.Data()); + } } delete lines; binningStr += customBinning; @@ -437,8 +444,9 @@ CorrelationContainer& CorrelationContainer::operator=(const CorrelationContainer { // assigment operator - if (this != &c) + if (this != &c) { ((CorrelationContainer&)c).Copy(*this); + } return *this; } @@ -450,14 +458,17 @@ void CorrelationContainer::Copy(TObject& c) const CorrelationContainer& target = (CorrelationContainer&)c; - if (mPairHist) + if (mPairHist) { target.mPairHist = dynamic_cast<StepTHnBase*>(mPairHist->Clone()); + } - if (mTriggerHist) + if (mTriggerHist) { target.mTriggerHist = dynamic_cast<StepTHnBase*>(mTriggerHist->Clone()); + } - if (mTrackHistEfficiency) + if (mTrackHistEfficiency) { target.mTrackHistEfficiency = dynamic_cast<StepTHnBase*>(mTrackHistEfficiency->Clone()); + } target.mEtaMin = mEtaMin; target.mEtaMax = mEtaMax; @@ -483,11 +494,13 @@ Long64_t CorrelationContainer::Merge(TCollection* list) // PROOF). // Returns the number of merged objects (including this). - if (!list) + if (!list) { return 0; + } - if (list->IsEmpty()) + if (list->IsEmpty()) { return 1; + } TIterator* iter = list->MakeIterator(); TObject* obj = nullptr; @@ -496,18 +509,21 @@ Long64_t CorrelationContainer::Merge(TCollection* list) const UInt_t kMaxLists = 4; TList** lists = new TList*[kMaxLists]; - for (UInt_t i = 0; i < kMaxLists; i++) + for (UInt_t i = 0; i < kMaxLists; i++) { lists[i] = new TList; + } Int_t count = 0; while ((obj = iter->Next())) { CorrelationContainer* entry = dynamic_cast<CorrelationContainer*>(obj); - if (entry == nullptr) + if (entry == nullptr) { continue; + } - if (entry->mPairHist) + if (entry->mPairHist) { lists[0]->Add(entry->mPairHist); + } lists[1]->Add(entry->mTriggerHist); lists[2]->Add(entry->mTrackHistEfficiency); @@ -515,15 +531,17 @@ Long64_t CorrelationContainer::Merge(TCollection* list) count++; } - if (mPairHist) + if (mPairHist) { mPairHist->Merge(lists[0]); + } mTriggerHist->Merge(lists[1]); mTrackHistEfficiency->Merge(lists[2]); mEventCount->Merge(lists[3]); - for (UInt_t i = 0; i < kMaxLists; i++) + for (UInt_t i = 0; i < kMaxLists; i++) { delete lists[i]; + } delete[] lists; @@ -535,14 +553,17 @@ void CorrelationContainer::setBinLimits(THnBase* grid) { // sets the bin limits in eta and pT defined by mEtaMin/Max, mPtMin/Max - if (mEtaMax > mEtaMin) + if (mEtaMax > mEtaMin) { grid->GetAxis(0)->SetRangeUser(mEtaMin, mEtaMax); - if (mPtMax > mPtMin) + } + if (mPtMax > mPtMin) { grid->GetAxis(1)->SetRangeUser(mPtMin, mPtMax); - if (mPt2Min > 0 && mPt2Max > 0) + } + if (mPt2Min > 0 && mPt2Max > 0) { grid->GetAxis(6)->SetRangeUser(mPt2Min, mPt2Max); - else if (mPt2Min > 0) + } else if (mPt2Min > 0) { grid->GetAxis(6)->SetRangeUser(mPt2Min, grid->GetAxis(6)->GetXmax() - 0.01); + } } //____________________________________________________________________ @@ -550,9 +571,11 @@ void CorrelationContainer::resetBinLimits(THnBase* grid) { // resets all bin limits - for (Int_t i = 0; i < grid->GetNdimensions(); i++) - if (grid->GetAxis(i)->TestBit(TAxis::kAxisRange)) + for (Int_t i = 0; i < grid->GetNdimensions(); i++) { + if (grid->GetAxis(i)->TestBit(TAxis::kAxisRange)) { grid->GetAxis(i)->SetRangeUser(0, -1); + } + } } //____________________________________________________________________ @@ -590,8 +613,9 @@ void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Flo Int_t count = 0; Int_t vars[4]; - for (Int_t i = 0; i < 4; i++) + for (Int_t i = 0; i < 4; i++) { vars[i] = binBegin[i]; + } THnBase* grid = mPairHist->getTHn(step); while (1) { @@ -612,8 +636,9 @@ void CorrelationContainer::countEmptyBins(CorrelationContainer::CFStep step, Flo } } - if (vars[0] == binEnd[0] + 1) + if (vars[0] == binEnd[0] + 1) { break; + } total++; } @@ -652,15 +677,17 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F if (mPt2Min > 0) { Int_t firstBinPt2 = sparse->GetAxis(6)->FindBin(mPt2Min); Int_t lastBinPt2 = sparse->GetAxis(6)->GetNbins(); - if (mPt2Max > 0) + if (mPt2Max > 0) { lastBinPt2 = sparse->GetAxis(6)->FindBin(mPt2Max); + } mTriggerHist->getTHn(step)->GetAxis(3)->SetRange(firstBinPt2, lastBinPt2); } Bool_t hasVertex = kTRUE; - if (!mPairHist->getTHn(step)->GetAxis(5)) + if (!mPairHist->getTHn(step)->GetAxis(5)) { hasVertex = kFALSE; + } if (hasVertex) { Int_t dimensions[] = {4, 0, 5, 3}; @@ -681,8 +708,9 @@ void CorrelationContainer::getHistsZVtxMult(CorrelationContainer::CFStep step, F for (int i = 0; i < 3; i++) { int j = i; - if (i == 2) + if (i == 2) { j = 3; + } (*trackHist)->SetBinEdges(j, tmpTrackHist->GetAxis(i)->GetXbins()->GetArray()); (*trackHist)->GetAxis(j)->SetTitle(tmpTrackHist->GetAxis(i)->GetTitle()); @@ -768,8 +796,9 @@ TH2* CorrelationContainer::getPerTriggerYield(CorrelationContainer::CFStep step, if (normalizePerTrigger) { LOGF(info, "Dividing %f tracks by %f triggers", yield->Integral(), triggers); - if (triggers > 0) + if (triggers > 0) { yield->Scale(1.0 / triggers); + } } // normalizate to dphi width @@ -843,8 +872,9 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati for (Int_t multBin = TMath::Max(1, multBinBegin); multBin <= TMath::Min(multAxis->GetNbins(), multBinEnd); multBin++) { trackSameAll->GetAxis(3)->SetRange(multBin, multBin); trackMixedAll->GetAxis(3)->SetRange(multBin, multBin); - if (trackMixedAllStep6) + if (trackMixedAllStep6) { trackMixedAllStep6->GetAxis(3)->SetRange(multBin, multBin); + } Double_t mixedNorm = 1; Double_t mixedNormError = 0; @@ -924,8 +954,9 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati mixedNormError /= triggers; delete tracksMixed; - } else + } else { LOGF(warning, "WARNING: Skipping mixed-event scaling! mSkipScaleMixedEvent IS set!"); + } if (mixedNorm <= 0) { LOGF(error, "ERROR: Skipping multiplicity %d because mixed event is empty at (0,0)", multBin); @@ -966,10 +997,11 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati if (triggers2 <= 0) { LOGF(error, "ERROR: Skipping multiplicity %d vertex bin %d because mixed event is empty", multBin, vertexBin); } else { - if (!mSkipScaleMixedEvent) + if (!mSkipScaleMixedEvent) { tracksMixed->Scale(1.0 / triggers2 / mixedNorm); - else if (tracksMixed->Integral() > 0) + } else if (tracksMixed->Integral() > 0) { tracksMixed->Scale(1.0 / tracksMixed->Integral()); + } // tracksSame->Scale(tracksMixed->Integral() / tracksSame->Integral()); // new TCanvas; tracksSame->DrawClone("SURF1"); @@ -979,25 +1011,29 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati Double_t sums[] = {0, 0, 0}; Double_t errors[] = {0, 0, 0}; - for (Int_t x = 1; x <= tracksSame->GetNbinsX(); x++) + for (Int_t x = 1; x <= tracksSame->GetNbinsX(); x++) { for (Int_t y = 1; y <= tracksSame->GetNbinsY(); y++) { sums[0] += tracksSame->GetBinContent(x, y); errors[0] += tracksSame->GetBinError(x, y); sums[1] += tracksMixed->GetBinContent(x, y); errors[1] += tracksMixed->GetBinError(x, y); } + } tracksSame->Divide(tracksMixed); - for (Int_t x = 1; x <= tracksSame->GetNbinsX(); x++) + for (Int_t x = 1; x <= tracksSame->GetNbinsX(); x++) { for (Int_t y = 1; y <= tracksSame->GetNbinsY(); y++) { sums[2] += tracksSame->GetBinContent(x, y); errors[2] += tracksSame->GetBinError(x, y); } + } - for (Int_t x = 0; x < 3; x++) - if (sums[x] > 0) + for (Int_t x = 0; x < 3; x++) { + if (sums[x] > 0) { errors[x] /= sums[x]; + } + } LOGF(info, "The correlation function %d %d has uncertainties %f %f %f (Ratio S/M %f)", multBin, vertexBin, errors[0], errors[1], errors[2], (errors[1] > 0) ? errors[0] / errors[1] : -1); // code to draw contributions @@ -1008,10 +1044,11 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati proj->DrawCopy((vertexBin > 1) ? "SAME" : ""); */ - if (!totalTracks) + if (!totalTracks) { totalTracks = (TH2*)tracksSame->Clone("totalTracks"); - else + } else { totalTracks->Add(tracksSame); + } totalEvents += eventSameAll->GetBinContent(vertexBin, multBin); @@ -1029,21 +1066,25 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati Double_t sums[] = {0, 0, 0}; Double_t errors[] = {0, 0, 0}; - for (Int_t x = 1; x <= totalTracks->GetNbinsX(); x++) + for (Int_t x = 1; x <= totalTracks->GetNbinsX(); x++) { for (Int_t y = 1; y <= totalTracks->GetNbinsY(); y++) { sums[0] += totalTracks->GetBinContent(x, y); errors[0] += totalTracks->GetBinError(x, y); } - if (sums[0] > 0) + } + if (sums[0] > 0) { errors[0] /= sums[0]; + } if (normalizePerTrigger) { LOGF(info, "Dividing %f tracks by %lld events (%d correlation function(s)) (error %f)", totalTracks->Integral(), totalEvents, nCorrelationFunctions, errors[0]); - if (totalEvents > 0) + if (totalEvents > 0) { totalTracks->Scale(1.0 / totalEvents); + } } - if (trigger != nullptr) + if (trigger != nullptr) { *trigger = (Int_t)totalEvents; + } // normalizate to dphi width Float_t normalization = totalTracks->GetXaxis()->GetBinWidth(1); @@ -1144,8 +1185,9 @@ TH1* CorrelationContainer::getTrackEfficiency(CFStep step1, CFStep step2, Int_t // step offset because we start with kCFStepAnaTopology step1 = (CFStep)((Int_t)step1 - (Int_t)kCFStepAnaTopology); step2 = (CFStep)((Int_t)step2 - (Int_t)kCFStepAnaTopology); - } else + } else { return nullptr; + } // reset all limits and set the right ones except those in axis1, axis2 and axis3 resetBinLimits(sourceContainer->getTHn(step1)); @@ -1238,8 +1280,9 @@ TH1* CorrelationContainer::getTrackEfficiency(CFStep step1, CFStep step2, Int_t Int_t count = 0; Int_t vars[3]; - for (Int_t i = 0; i < 3; i++) + for (Int_t i = 0; i < 3; i++) { vars[i] = binBegin[i]; + } const Int_t limit = 50; while (1) { @@ -1272,8 +1315,9 @@ TH1* CorrelationContainer::getTrackEfficiency(CFStep step1, CFStep step2, Int_t vars[0]++; } - if (vars[0] == binEnd[0] + 1) + if (vars[0] == binEnd[0] + 1) { break; + } total++; } @@ -1289,20 +1333,22 @@ TH1* CorrelationContainer::getTrackEfficiency(CFStep step1, CFStep step2, Int_t TH1* tmp = measured; measured = new TH2D(Form("%s_rebinned", tmp->GetName()), tmp->GetTitle(), axis->GetNbins(), axis->GetXbins()->GetArray(), tmp->GetNbinsY(), tmp->GetYaxis()->GetXbins()->GetArray()); - for (Int_t x = 1; x <= tmp->GetNbinsX(); x++) + for (Int_t x = 1; x <= tmp->GetNbinsX(); x++) { for (Int_t y = 1; y <= tmp->GetNbinsY(); y++) { ((TH2*)measured)->Fill(tmp->GetXaxis()->GetBinCenter(x), tmp->GetYaxis()->GetBinCenter(y), tmp->GetBinContent(x, y)); measured->SetBinError(x, y, 0); // cannot trust bin error, set to 0 } + } delete tmp; tmp = generated; generated = new TH2D(Form("%s_rebinned", tmp->GetName()), tmp->GetTitle(), axis->GetNbins(), axis->GetXbins()->GetArray(), tmp->GetNbinsY(), tmp->GetYaxis()->GetXbins()->GetArray()); - for (Int_t x = 1; x <= tmp->GetNbinsX(); x++) + for (Int_t x = 1; x <= tmp->GetNbinsX(); x++) { for (Int_t y = 1; y <= tmp->GetNbinsY(); y++) { ((TH2*)generated)->Fill(tmp->GetXaxis()->GetBinCenter(x), tmp->GetYaxis()->GetBinCenter(y), tmp->GetBinContent(x, y)); generated->SetBinError(x, y, 0); // cannot trust bin error, set to 0 } + } delete tmp; } else { TH1* tmp = measured; @@ -1451,13 +1497,15 @@ TH1* CorrelationContainer::getBias(CFStep step1, CFStep step2, const char* axis, TH1D* events1 = (TH1D*)mTriggerHist->getTHn(step1)->Projection(0); TH3D* hist1 = (TH3D*)tmp->getTHn(step1)->Projection(0, tmp->getNVar() - 1, 2); - if (weighting == 0) + if (weighting == 0) { weightHistogram(hist1, events1); + } TH1D* events2 = (TH1D*)mTriggerHist->getTHn(step2)->Projection(0); TH3D* hist2 = (TH3D*)tmp->getTHn(step2)->Projection(0, tmp->getNVar() - 1, 2); - if (weighting == 0) + if (weighting == 0) { weightHistogram(hist2, events2); + } TH1* generated = hist1; TH1* measured = hist2; @@ -1681,8 +1729,9 @@ void CorrelationContainer::deepCopy(CorrelationContainer* from) } for (Int_t step = 0; step < TMath::Min(mTrackHistEfficiency->getNSteps(), from->mTrackHistEfficiency->getNSteps()); step++) { - if (!from->mTrackHistEfficiency->getTHn(step)) + if (!from->mTrackHistEfficiency->getTHn(step)) { continue; + } LOGF(info, "Eff: Copying step %d", step); THnBase* target = mTrackHistEfficiency->getTHn(step); @@ -1700,20 +1749,22 @@ void CorrelationContainer::symmetrizepTBins() for (Int_t step = 0; step < mPairHist->getNSteps(); step++) { LOGF(info, "Copying step %d", step); THnBase* target = mPairHist->getTHn(step); - if (target->GetEntries() == 0) + if (target->GetEntries() == 0) { continue; + } // for symmetric bins THnBase* source = (THnBase*)target->Clone(); Int_t zVtxBins = 1; - if (target->GetNdimensions() > 5) + if (target->GetNdimensions() > 5) { zVtxBins = target->GetAxis(5)->GetNbins(); + } // axes: 0 delta eta; 1 pT,a; 2 pT,t; 3 centrality; 4 delta phi; 5 vtx-z - for (Int_t i3 = 1; i3 <= target->GetAxis(3)->GetNbins(); i3++) + for (Int_t i3 = 1; i3 <= target->GetAxis(3)->GetNbins(); i3++) { for (Int_t i5 = 1; i5 <= zVtxBins; i5++) { - for (Int_t i1 = 1; i1 <= target->GetAxis(1)->GetNbins(); i1++) + for (Int_t i1 = 1; i1 <= target->GetAxis(1)->GetNbins(); i1++) { for (Int_t i2 = 1; i2 <= target->GetAxis(2)->GetNbins(); i2++) { // find source bin Int_t binA = target->GetAxis(1)->FindBin(target->GetAxis(2)->GetBinCenter(i2)); @@ -1721,12 +1772,13 @@ void CorrelationContainer::symmetrizepTBins() LOGF(info, "(%d %d) Copying from %d %d to %d %d", i3, i5, binA, binT, i1, i2); - for (Int_t i0 = 1; i0 <= target->GetAxis(0)->GetNbins(); i0++) + for (Int_t i0 = 1; i0 <= target->GetAxis(0)->GetNbins(); i0++) { for (Int_t i4 = 1; i4 <= target->GetAxis(4)->GetNbins(); i4++) { Int_t binEta = target->GetAxis(0)->FindBin(-target->GetAxis(0)->GetBinCenter(i0)); Double_t phi = -target->GetAxis(4)->GetBinCenter(i4); - if (phi < -TMath::Pi() / 2) + if (phi < -TMath::Pi() / 2) { phi += TMath::TwoPi(); + } Int_t binPhi = target->GetAxis(4)->FindBin(phi); Int_t binSource[] = {binEta, binA, binT, i3, binPhi, i5}; @@ -1735,8 +1787,9 @@ void CorrelationContainer::symmetrizepTBins() Double_t value = source->GetBinContent(binSource); Double_t error = source->GetBinError(binSource); - if (error == 0) + if (error == 0) { continue; + } Double_t value2 = target->GetBinContent(binTarget); Double_t error2 = target->GetBinError(binTarget); @@ -1754,8 +1807,11 @@ void CorrelationContainer::symmetrizepTBins() target->SetBinContent(binTarget, sum); target->SetBinError(binTarget, err); } + } } + } } + } delete source; } @@ -1796,8 +1852,8 @@ void CorrelationContainer::extendTrackingEfficiency(Bool_t verbose) LOGF(info, "CorrelationContainer::extendTrackingEfficiency: Fitted efficiency between %f and %f and got %f tracking efficiency and %f tracking contamination correction. Extending from %f onwards (within %f < eta < %f)", fitRangeBegin, fitRangeEnd, trackingEff, trackingCont, extendRangeBegin, mEtaMin, mEtaMax); // extend for full pT range - for (Int_t x = mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMin); x <= mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMax); x++) - for (Int_t y = mTrackHistEfficiency->getTHn(0)->GetAxis(1)->FindBin(extendRangeBegin); y <= mTrackHistEfficiency->getTHn(0)->GetAxis(1)->GetNbins(); y++) + for (Int_t x = mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMin); x <= mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMax); x++) { + for (Int_t y = mTrackHistEfficiency->getTHn(0)->GetAxis(1)->FindBin(extendRangeBegin); y <= mTrackHistEfficiency->getTHn(0)->GetAxis(1)->GetNbins(); y++) { for (Int_t z = 1; z <= mTrackHistEfficiency->getTHn(0)->GetAxis(2)->GetNbins(); z++) // particle type axis { @@ -1810,6 +1866,8 @@ void CorrelationContainer::extendTrackingEfficiency(Bool_t verbose) mTrackHistEfficiency->getTHn(1)->SetBinContent(bins, 100.0 * trackingEff); mTrackHistEfficiency->getTHn(2)->SetBinContent(bins, 100.0 * trackingEff / trackingCont); } + } + } } else if (mTrackHistEfficiency->getNVar() == 4) { // fit in centrality intervals of 20% for efficiency, one bin for contamination Float_t* trackingEff = nullptr; @@ -1834,26 +1892,28 @@ void CorrelationContainer::extendTrackingEfficiency(Bool_t verbose) } for (Int_t i = 0; i < centralityBinsLocal; i++) { - if (centralityBinsLocal == 1) + if (centralityBinsLocal == 1) { setCentralityRange(centralityBins[0] + 0.1, centralityBins[nCentralityBins] - 0.1); - else + } else { setCentralityRange(centralityBins[i] + 0.1, centralityBins[i + 1] - 0.1); + } TH1* proj = (caseNo == 0) ? getTrackingEfficiency(1) : getTrackingContamination(1); if (verbose) { new TCanvas; proj->DrawCopy(); } - if ((Int_t)proj->Fit("pol0", (verbose) ? "+" : "Q0+", "SAME", fitRangeBegin, fitRangeEnd) == 0) + if ((Int_t)proj->Fit("pol0", (verbose) ? "+" : "Q0+", "SAME", fitRangeBegin, fitRangeEnd) == 0) { target[i] = proj->GetFunction("pol0")->GetParameter(0); - else + } else { target[i] = 0; + } LOGF(info, "CorrelationContainer::extendTrackingEfficiency: case %d, centrality %d, eff %f", caseNo, i, target[i]); } } // extend for full pT range - for (Int_t x = mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMin); x <= mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMax); x++) - for (Int_t y = mTrackHistEfficiency->getTHn(0)->GetAxis(1)->FindBin(extendRangeBegin); y <= mTrackHistEfficiency->getTHn(0)->GetAxis(1)->GetNbins(); y++) + for (Int_t x = mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMin); x <= mTrackHistEfficiency->getTHn(0)->GetAxis(0)->FindBin(mEtaMax); x++) { + for (Int_t y = mTrackHistEfficiency->getTHn(0)->GetAxis(1)->FindBin(extendRangeBegin); y <= mTrackHistEfficiency->getTHn(0)->GetAxis(1)->GetNbins(); y++) { for (Int_t z = 1; z <= mTrackHistEfficiency->getTHn(0)->GetAxis(2)->GetNbins(); z++) // particle type axis { for (Int_t z2 = 1; z2 <= mTrackHistEfficiency->getTHn(0)->GetAxis(3)->GetNbins(); z2++) // centrality axis @@ -1866,19 +1926,23 @@ void CorrelationContainer::extendTrackingEfficiency(Bool_t verbose) bins[3] = z2; Int_t z2Bin = 0; - while (centralityBins[z2Bin + 1] < mTrackHistEfficiency->getTHn(0)->GetAxis(3)->GetBinCenter(z2)) + while (centralityBins[z2Bin + 1] < mTrackHistEfficiency->getTHn(0)->GetAxis(3)->GetBinCenter(z2)) { z2Bin++; + } //Printf("%d %d", z2, z2Bin); mTrackHistEfficiency->getTHn(0)->SetBinContent(bins, 100); mTrackHistEfficiency->getTHn(1)->SetBinContent(bins, 100.0 * trackingEff[z2Bin]); - if (trackingCont[0] > 0) + if (trackingCont[0] > 0) { mTrackHistEfficiency->getTHn(2)->SetBinContent(bins, 100.0 * trackingEff[z2Bin] / trackingCont[0]); - else + } else { mTrackHistEfficiency->getTHn(2)->SetBinContent(bins, 0); + } } } + } + } delete[] trackingEff; delete[] trackingCont; @@ -1904,14 +1968,17 @@ void CorrelationContainer::Reset() { // resets all contained histograms - for (Int_t step = 0; step < mPairHist->getNSteps(); step++) + for (Int_t step = 0; step < mPairHist->getNSteps(); step++) { mPairHist->getTHn(step)->Reset(); + } - for (Int_t step = 0; step < mTriggerHist->getNSteps(); step++) + for (Int_t step = 0; step < mTriggerHist->getNSteps(); step++) { mTriggerHist->getTHn(step)->Reset(); + } - for (Int_t step = 0; step < mTrackHistEfficiency->getNSteps(); step++) + for (Int_t step = 0; step < mTrackHistEfficiency->getNSteps(); step++) { mTrackHistEfficiency->getTHn(step)->Reset(); + } } THnBase* CorrelationContainer::changeToThn(THnBase* sparse) diff --git a/Analysis/Core/src/HistogramManager.cxx b/Analysis/Core/src/HistogramManager.cxx index a0315fd34e23c..f92ec71d19c80 100644 --- a/Analysis/Core/src/HistogramManager.cxx +++ b/Analysis/Core/src/HistogramManager.cxx @@ -140,25 +140,32 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co // deduce the dimension of the histogram from parameters // NOTE: in case of profile histograms, one extra variable is needed int dimension = 1; - if (varY > kNothing) + if (varY > kNothing) { dimension = 2; - if (varZ > kNothing) + } + if (varZ > kNothing) { dimension = 3; + } // tokenize the title string; the user may include in it axis titles which will overwrite the defaults TString titleStr(title); TObjArray* arr = titleStr.Tokenize(";"); // mark required variables as being used - if (varX > kNothing) + if (varX > kNothing) { fUsedVars[varX] = kTRUE; - if (varY > kNothing) + } + if (varY > kNothing) { fUsedVars[varY] = kTRUE; - if (varZ > kNothing) + } + if (varZ > kNothing) { fUsedVars[varZ] = kTRUE; - if (varT > kNothing) + } + if (varT > kNothing) { fUsedVars[varT] = kTRUE; - if (varW > kNothing) + } + if (varW > kNothing) { fUsedVars[varW] = kTRUE; + } // encode needed variable identifiers in a vector and push it to the std::list corresponding to the current histogram list std::vector<int> varVector; @@ -183,13 +190,16 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co fBinsAllocated += nXbins + 2; // TODO: possibly make the call of Sumw2() optional for all histograms h->Sumw2(); - if (fVariableNames[varX][0]) + if (fVariableNames[varX][0]) { h->GetXaxis()->SetTitle(Form("%s %s", fVariableNames[varX].Data(), (fVariableUnits[varX][0] ? Form("(%s)", fVariableUnits[varX].Data()) : ""))); - if (arr->At(1)) + } + if (arr->At(1)) { h->GetXaxis()->SetTitle(arr->At(1)->GetName()); - if (xLabels[0] != '\0') + } + if (xLabels[0] != '\0') { MakeAxisLabels(h->GetXaxis(), xLabels); + } hList->Add(h); h->SetDirectory(nullptr); break; @@ -201,31 +211,39 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co h->Sumw2(); // if requested, build the profile using the profile widths instead of stat errors // TODO: make this option more transparent to the user ? - if (titleStr.Contains("--s--")) + if (titleStr.Contains("--s--")) { ((TProfile*)h)->BuildOptions(0., 0., "s"); + } } else { h = new TH2F(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xmin, xmax, nYbins, ymin, ymax); fBinsAllocated += (nXbins + 2) * (nYbins + 2); h->Sumw2(); } - if (fVariableNames[varX][0]) + if (fVariableNames[varX][0]) { h->GetXaxis()->SetTitle(Form("%s %s", fVariableNames[varX].Data(), (fVariableUnits[varX][0] ? Form("(%s)", fVariableUnits[varX].Data()) : ""))); - if (arr->At(1)) + } + if (arr->At(1)) { h->GetXaxis()->SetTitle(arr->At(1)->GetName()); - if (xLabels[0] != '\0') + } + if (xLabels[0] != '\0') { MakeAxisLabels(h->GetXaxis(), xLabels); + } - if (fVariableNames[varY][0]) + if (fVariableNames[varY][0]) { h->GetYaxis()->SetTitle(Form("%s %s", fVariableNames[varY].Data(), (fVariableUnits[varY][0] ? Form("(%s)", fVariableUnits[varY].Data()) : ""))); - if (fVariableNames[varY][0] && isProfile) + } + if (fVariableNames[varY][0] && isProfile) { h->GetYaxis()->SetTitle(Form("<%s> %s", fVariableNames[varY].Data(), (fVariableUnits[varY][0] ? Form("(%s)", fVariableUnits[varY].Data()) : ""))); - if (arr->At(2)) + } + if (arr->At(2)) { h->GetYaxis()->SetTitle(arr->At(2)->GetName()); - if (yLabels[0] != '\0') + } + if (yLabels[0] != '\0') { MakeAxisLabels(h->GetYaxis(), yLabels); + } hList->Add(h); h->SetDirectory(nullptr); break; @@ -236,44 +254,56 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co h = new TProfile3D(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xmin, xmax, nYbins, ymin, ymax, nZbins, zmin, zmax); fBinsAllocated += (nXbins + 2) * (nYbins + 2) * (nZbins + 2); h->Sumw2(); - if (titleStr.Contains("--s--")) + if (titleStr.Contains("--s--")) { ((TProfile3D*)h)->BuildOptions(0., 0., "s"); + } } else { // TProfile2D h = new TProfile2D(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xmin, xmax, nYbins, ymin, ymax); fBinsAllocated += (nXbins + 2) * (nYbins + 2); h->Sumw2(); - if (titleStr.Contains("--s--")) + if (titleStr.Contains("--s--")) { ((TProfile2D*)h)->BuildOptions(0., 0., "s"); + } } } else { // TH3F h = new TH3F(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xmin, xmax, nYbins, ymin, ymax, nZbins, zmin, zmax); fBinsAllocated += (nXbins + 2) * (nYbins + 2) * (nZbins + 2); h->Sumw2(); } - if (fVariableNames[varX][0]) + if (fVariableNames[varX][0]) { h->GetXaxis()->SetTitle(Form("%s %s", fVariableNames[varX].Data(), (fVariableUnits[varX][0] ? Form("(%s)", fVariableUnits[varX].Data()) : ""))); - if (arr->At(1)) + } + if (arr->At(1)) { h->GetXaxis()->SetTitle(arr->At(1)->GetName()); - if (xLabels[0] != '\0') + } + if (xLabels[0] != '\0') { MakeAxisLabels(h->GetXaxis(), xLabels); - if (fVariableNames[varY][0]) + } + if (fVariableNames[varY][0]) { h->GetYaxis()->SetTitle(Form("%s %s", fVariableNames[varY].Data(), (fVariableUnits[varY][0] ? Form("(%s)", fVariableUnits[varY].Data()) : ""))); - if (arr->At(2)) + } + if (arr->At(2)) { h->GetYaxis()->SetTitle(arr->At(2)->GetName()); - if (yLabels[0] != '\0') + } + if (yLabels[0] != '\0') { MakeAxisLabels(h->GetYaxis(), yLabels); - if (fVariableNames[varZ][0]) + } + if (fVariableNames[varZ][0]) { h->GetZaxis()->SetTitle(Form("%s %s", fVariableNames[varZ].Data(), (fVariableUnits[varZ][0] ? Form("(%s)", fVariableUnits[varZ].Data()) : ""))); - if (fVariableNames[varZ][0] && isProfile && varT < 0) // for TProfile2D + } + if (fVariableNames[varZ][0] && isProfile && varT < 0) { // for TProfile2D h->GetZaxis()->SetTitle(Form("<%s> %s", fVariableNames[varZ].Data(), (fVariableUnits[varZ][0] ? Form("(%s)", fVariableUnits[varZ].Data()) : ""))); - if (arr->At(3)) + } + if (arr->At(3)) { h->GetZaxis()->SetTitle(arr->At(3)->GetName()); - if (zLabels[0] != '\0') + } + if (zLabels[0] != '\0') { MakeAxisLabels(h->GetZaxis(), zLabels); + } h->SetDirectory(nullptr); hList->Add(h); break; @@ -308,22 +338,29 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co // deduce the dimension of the histogram from parameters // NOTE: in case of profile histograms, one extra variable is needed int dimension = 1; - if (varY > kNothing) + if (varY > kNothing) { dimension = 2; - if (varZ > kNothing) + } + if (varZ > kNothing) { dimension = 3; + } // mark required variables as being used - if (varX > kNothing) + if (varX > kNothing) { fUsedVars[varX] = kTRUE; - if (varY > kNothing) + } + if (varY > kNothing) { fUsedVars[varY] = kTRUE; - if (varZ > kNothing) + } + if (varZ > kNothing) { fUsedVars[varZ] = kTRUE; - if (varT > kNothing) + } + if (varT > kNothing) { fUsedVars[varT] = kTRUE; - if (varW > kNothing) + } + if (varW > kNothing) { fUsedVars[varW] = kTRUE; + } // tokenize the title string; the user may include in it axis titles which will overwrite the defaults TString titleStr(title); @@ -350,13 +387,16 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co h = new TH1F(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xbins); fBinsAllocated += nXbins + 2; h->Sumw2(); - if (fVariableNames[varX][0]) + if (fVariableNames[varX][0]) { h->GetXaxis()->SetTitle(Form("%s %s", fVariableNames[varX].Data(), (fVariableUnits[varX][0] ? Form("(%s)", fVariableUnits[varX].Data()) : ""))); - if (arr->At(1)) + } + if (arr->At(1)) { h->GetXaxis()->SetTitle(arr->At(1)->GetName()); - if (xLabels[0] != '\0') + } + if (xLabels[0] != '\0') { MakeAxisLabels(h->GetXaxis(), xLabels); + } h->SetDirectory(nullptr); hList->Add(h); break; @@ -366,31 +406,39 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co h = new TProfile(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xbins); fBinsAllocated += nXbins + 2; h->Sumw2(); - if (titleStr.Contains("--s--")) + if (titleStr.Contains("--s--")) { ((TProfile*)h)->BuildOptions(0., 0., "s"); + } } else { h = new TH2F(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xbins, nYbins, ybins); fBinsAllocated += (nXbins + 2) * (nYbins + 2); h->Sumw2(); } - if (fVariableNames[varX][0]) + if (fVariableNames[varX][0]) { h->GetXaxis()->SetTitle(Form("%s (%s)", fVariableNames[varX].Data(), (fVariableUnits[varX][0] ? Form("(%s)", fVariableUnits[varX].Data()) : ""))); - if (arr->At(1)) + } + if (arr->At(1)) { h->GetXaxis()->SetTitle(arr->At(1)->GetName()); - if (xLabels[0] != '\0') + } + if (xLabels[0] != '\0') { MakeAxisLabels(h->GetXaxis(), xLabels); - if (fVariableNames[varY][0]) + } + if (fVariableNames[varY][0]) { h->GetYaxis()->SetTitle(Form("%s (%s)", fVariableNames[varY].Data(), (fVariableUnits[varY][0] ? Form("(%s)", fVariableUnits[varY].Data()) : ""))); - if (fVariableNames[varY][0] && isProfile) + } + if (fVariableNames[varY][0] && isProfile) { h->GetYaxis()->SetTitle(Form("<%s> (%s)", fVariableNames[varY].Data(), (fVariableUnits[varY][0] ? Form("(%s)", fVariableUnits[varY].Data()) : ""))); + } - if (arr->At(2)) + if (arr->At(2)) { h->GetYaxis()->SetTitle(arr->At(2)->GetName()); - if (yLabels[0] != '\0') + } + if (yLabels[0] != '\0') { MakeAxisLabels(h->GetYaxis(), yLabels); + } h->SetDirectory(nullptr); hList->Add(h); break; @@ -401,45 +449,57 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co h = new TProfile3D(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xbins, nYbins, ybins, nZbins, zbins); fBinsAllocated += (nXbins + 2) * (nYbins + 2) * (nZbins + 2); h->Sumw2(); - if (titleStr.Contains("--s--")) + if (titleStr.Contains("--s--")) { ((TProfile3D*)h)->BuildOptions(0., 0., "s"); + } } else { h = new TProfile2D(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xbins, nYbins, ybins); fBinsAllocated += (nXbins + 2) * (nYbins + 2); h->Sumw2(); - if (titleStr.Contains("--s--")) + if (titleStr.Contains("--s--")) { ((TProfile2D*)h)->BuildOptions(0., 0., "s"); + } } } else { h = new TH3F(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nXbins, xbins, nYbins, ybins, nZbins, zbins); fBinsAllocated += (nXbins + 2) * (nYbins + 2) * (nZbins + 2); h->Sumw2(); } - if (fVariableNames[varX][0]) + if (fVariableNames[varX][0]) { h->GetXaxis()->SetTitle(Form("%s %s", fVariableNames[varX].Data(), (fVariableUnits[varX][0] ? Form("(%s)", fVariableUnits[varX].Data()) : ""))); - if (arr->At(1)) + } + if (arr->At(1)) { h->GetXaxis()->SetTitle(arr->At(1)->GetName()); - if (xLabels[0] != '\0') + } + if (xLabels[0] != '\0') { MakeAxisLabels(h->GetXaxis(), xLabels); - if (fVariableNames[varY][0]) + } + if (fVariableNames[varY][0]) { h->GetYaxis()->SetTitle(Form("%s %s", fVariableNames[varY].Data(), (fVariableUnits[varY][0] ? Form("(%s)", fVariableUnits[varY].Data()) : ""))); - if (arr->At(2)) + } + if (arr->At(2)) { h->GetYaxis()->SetTitle(arr->At(2)->GetName()); - if (yLabels[0] != '\0') + } + if (yLabels[0] != '\0') { MakeAxisLabels(h->GetYaxis(), yLabels); - if (fVariableNames[varZ][0]) + } + if (fVariableNames[varZ][0]) { h->GetZaxis()->SetTitle(Form("%s %s", fVariableNames[varZ].Data(), (fVariableUnits[varZ][0] ? Form("(%s)", fVariableUnits[varZ].Data()) : ""))); - if (fVariableNames[varZ][0] && isProfile && varT < 0) // TProfile2D + } + if (fVariableNames[varZ][0] && isProfile && varT < 0) { // TProfile2D h->GetZaxis()->SetTitle(Form("<%s> %s", fVariableNames[varZ].Data(), (fVariableUnits[varZ][0] ? Form("(%s)", fVariableUnits[varZ].Data()) : ""))); + } - if (arr->At(3)) + if (arr->At(3)) { h->GetZaxis()->SetTitle(arr->At(3)->GetName()); - if (zLabels[0] != '\0') + } + if (zLabels[0] != '\0') { MakeAxisLabels(h->GetZaxis(), zLabels); + } hList->Add(h); break; } // end switch(dimension) @@ -471,16 +531,18 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co TString titleStr(title); TObjArray* arr = titleStr.Tokenize(";"); - if (varW > kNothing) + if (varW > kNothing) { fUsedVars[varW] = kTRUE; + } // encode needed variable identifiers in a vector and push it to the std::list corresponding to the current histogram list std::vector<int> varVector; varVector.push_back(0); // whether the histogram is a profile varVector.push_back(nDimensions); // number of dimensions varVector.push_back(varW); // variable used for weighting - for (int idim = 0; idim < nDimensions; ++idim) + for (int idim = 0; idim < nDimensions; ++idim) { varVector.push_back(vars[idim]); // axes variables + } std::list varList = fVariablesMap[histClass]; varList.push_back(varVector); cout << "Adding histogram " << hname << endl; @@ -489,30 +551,35 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co unsigned long int nbins = 1; THnBase* h = nullptr; - if (useSparse) + if (useSparse) { h = new THnSparseF(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nDimensions, nBins, xmin, xmax); - else + } else { h = new THnF(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nDimensions, nBins, xmin, xmax); + } h->Sumw2(); // configure the THn histogram and count the allocated bins for (int idim = 0; idim < nDimensions; ++idim) { nbins *= (nBins[idim] + 2); TAxis* axis = h->GetAxis(idim); - if (fVariableNames[vars[idim]][0]) + if (fVariableNames[vars[idim]][0]) { axis->SetTitle(Form("%s %s", fVariableNames[vars[idim]].Data(), (fVariableUnits[vars[idim]][0] ? Form("(%s)", fVariableUnits[vars[idim]].Data()) : ""))); - if (arr->At(1 + idim)) + } + if (arr->At(1 + idim)) { axis->SetTitle(arr->At(1 + idim)->GetName()); - if (axLabels && !axLabels[idim].IsNull()) + } + if (axLabels && !axLabels[idim].IsNull()) { MakeAxisLabels(axis, axLabels[idim].Data()); + } fUsedVars[vars[idim]] = kTRUE; } - if (useSparse) + if (useSparse) { hList->Add((THnSparseF*)h); - else + } else { hList->Add((THnF*)h); + } fBinsAllocated += nbins; } @@ -543,16 +610,18 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co TString titleStr(title); TObjArray* arr = titleStr.Tokenize(";"); - if (varW > kNothing) + if (varW > kNothing) { fUsedVars[varW] = kTRUE; + } // encode needed variable identifiers in a vector and push it to the std::list corresponding to the current histogram list std::vector<int> varVector; varVector.push_back(0); // whether the histogram is a profile varVector.push_back(nDimensions); // number of dimensions varVector.push_back(varW); // variable used for weighting - for (int idim = 0; idim < nDimensions; ++idim) + for (int idim = 0; idim < nDimensions; ++idim) { varVector.push_back(vars[idim]); // axes variables + } std::list varList = fVariablesMap[histClass]; varList.push_back(varVector); cout << "Adding histogram " << hname << endl; @@ -571,10 +640,11 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co // initialize the THn with equal spaced bins THnBase* h = nullptr; - if (useSparse) + if (useSparse) { h = new THnSparseF(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nDimensions, nBins, xmin, xmax); - else + } else { h = new THnF(hname, (arr->At(0) ? arr->At(0)->GetName() : ""), nDimensions, nBins, xmin, xmax); + } // rebin the axes according to the user requested binning for (int idim = 0; idim < nDimensions; ++idim) { TAxis* axis = h->GetAxis(idim); @@ -586,19 +656,23 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co for (int idim = 0; idim < nDimensions; ++idim) { bins *= (nBins[idim] + 2); TAxis* axis = h->GetAxis(idim); - if (fVariableNames[vars[idim]][0]) + if (fVariableNames[vars[idim]][0]) { axis->SetTitle(Form("%s %s", fVariableNames[vars[idim]].Data(), (fVariableUnits[vars[idim]][0] ? Form("(%s)", fVariableUnits[vars[idim]].Data()) : ""))); - if (arr->At(1 + idim)) + } + if (arr->At(1 + idim)) { axis->SetTitle(arr->At(1 + idim)->GetName()); - if (axLabels && !axLabels[idim].IsNull()) + } + if (axLabels && !axLabels[idim].IsNull()) { MakeAxisLabels(axis, axLabels[idim].Data()); + } fUsedVars[vars[idim]] = kTRUE; } - if (useSparse) + if (useSparse) { hList->Add((THnSparseF*)h); - else + } else { hList->Add((THnF*)h); + } fBinsAllocated += bins; } @@ -641,16 +715,18 @@ void HistogramManager::FillHistClass(const char* className, Float_t* values) // decode information from the vector of indices isProfile = (varIter->at(0) == 1 ? true : false); isTHn = (varIter->at(1) > 0 ? true : false); - if (isTHn) + if (isTHn) { dimension = varIter->at(1); - else + } else { dimension = ((TH1*)h)->GetDimension(); + } // get the various variable indices varW = varIter->at(2); if (isTHn) { - for (int i = 0; i < dimension; i++) + for (int i = 0; i < dimension; i++) { fillValues[i] = values[varIter->at(3 + i)]; + } } else { varX = varIter->at(3); varY = varIter->at(4); @@ -662,41 +738,47 @@ void HistogramManager::FillHistClass(const char* className, Float_t* values) switch (dimension) { case 1: if (isProfile) { - if (varW > kNothing) + if (varW > kNothing) { ((TProfile*)h)->Fill(values[varX], values[varY], values[varW]); - else + } else { ((TProfile*)h)->Fill(values[varX], values[varY]); + } } else { - if (varW > kNothing) + if (varW > kNothing) { ((TH1F*)h)->Fill(values[varX], values[varW]); - else + } else { ((TH1F*)h)->Fill(values[varX]); + } } break; case 2: if (isProfile) { - if (varW > kNothing) + if (varW > kNothing) { ((TProfile2D*)h)->Fill(values[varX], values[varY], values[varZ], values[varW]); - else + } else { ((TProfile2D*)h)->Fill(values[varX], values[varY], values[varZ]); + } } else { - if (varW > kNothing) + if (varW > kNothing) { ((TH2F*)h)->Fill(values[varX], values[varY], values[varW]); - else + } else { ((TH2F*)h)->Fill(values[varX], values[varY]); + } } break; case 3: if (isProfile) { - if (varW > kNothing) + if (varW > kNothing) { ((TProfile3D*)h)->Fill(values[varX], values[varY], values[varZ], values[varT], values[varW]); - else + } else { ((TProfile3D*)h)->Fill(values[varX], values[varY], values[varZ], values[varT]); + } } else { - if (varW > kNothing) + if (varW > kNothing) { ((TH3F*)h)->Fill(values[varX], values[varY], values[varZ], values[varW]); - else + } else { ((TH3F*)h)->Fill(values[varX], values[varY], values[varZ]); + } } break; @@ -706,15 +788,17 @@ void HistogramManager::FillHistClass(const char* className, Float_t* values) } // end if(!isTHn) else { if (varW > kNothing) { - if (isSparse) + if (isSparse) { ((THnSparseF*)h)->Fill(fillValues, values[varW]); - else + } else { ((THnF*)h)->Fill(fillValues, values[varW]); + } } else { - if (isSparse) + if (isSparse) { ((THnSparseF*)h)->Fill(fillValues); - else + } else { ((THnF*)h)->Fill(fillValues); + } } } // end else } // end loop over histograms @@ -729,8 +813,9 @@ void HistogramManager::MakeAxisLabels(TAxis* ax, const char* labels) TString labelsStr(labels); TObjArray* arr = labelsStr.Tokenize(";"); for (int ib = 1; ib <= ax->GetNbins(); ++ib) { - if (ib >= arr->GetEntries() + 1) + if (ib >= arr->GetEntries() + 1) { break; + } ax->SetBinLabel(ib, arr->At(ib - 1)->GetName()); } } diff --git a/Analysis/Core/src/JetFinder.cxx b/Analysis/Core/src/JetFinder.cxx index fb1498d911e80..bb9304213b828 100644 --- a/Analysis/Core/src/JetFinder.cxx +++ b/Analysis/Core/src/JetFinder.cxx @@ -40,8 +40,9 @@ void JetFinder::setBkgE() if (bkgSubMode == BkgSubMode::rhoAreaSub || bkgSubMode == BkgSubMode::constSub) { bkgE = decltype(bkgE)(new fastjet::JetMedianBackgroundEstimator(selRho, jetDefBkg, areaDefBkg)); } else { - if (bkgSubMode != BkgSubMode::none) + if (bkgSubMode != BkgSubMode::none) { LOGF(ERROR, "requested subtraction mode not implemented!"); + } } } @@ -60,8 +61,9 @@ void JetFinder::setSub() constituentSub->set_max_eta(bkgEtaMax); constituentSub->set_background_estimator(bkgE.get()); //what about rho_m } else { - if (bkgSubMode != BkgSubMode::none) + if (bkgSubMode != BkgSubMode::none) { LOGF(ERROR, "requested subtraction mode not implemented!"); + } } } diff --git a/Analysis/Core/src/StepTHn.cxx b/Analysis/Core/src/StepTHn.cxx index ef7f6902af19b..f4ef928f0ca83 100644 --- a/Analysis/Core/src/StepTHn.cxx +++ b/Analysis/Core/src/StepTHn.cxx @@ -69,8 +69,9 @@ StepTHn<TemplateArray, TemplateType>::StepTHn(const Char_t* name, const Char_t* // The axis have <nBins[i]> bins. The bin edges are given in <binEdges[i]>. If there are only two bin edges, equidistant binning is set. mNBins = 1; - for (Int_t i = 0; i < mNVars; i++) + for (Int_t i = 0; i < mNVars; i++) { mNBins *= nBins[i]; + } if constexpr (std::is_same_v<TemplateType, Double_t>) { mPrototype = new THnSparseD(Form("%s_sparse", name), title, nAxis, nBins); @@ -172,8 +173,9 @@ StepTHn<TemplateArray, TemplateType>& StepTHn<TemplateArray, TemplateType>::oper { // assigment operator - if (this != &c) + if (this != &c) { ((StepTHn&)c).Copy(*this); + } return *this; } @@ -195,19 +197,22 @@ void StepTHn<TemplateArray, TemplateType>::Copy(TObject& c) const target.init(); for (Int_t i = 0; i < mNSteps; i++) { - if (mValues[i]) + if (mValues[i]) { target.mValues[i] = new TemplateArray(*(mValues[i])); - else + } else { target.mValues[i] = nullptr; + } - if (mSumw2[i]) + if (mSumw2[i]) { target.mSumw2[i] = new TemplateArray(*(mSumw2[i])); - else + } else { target.mSumw2[i] = nullptr; + } } - if (mPrototype) + if (mPrototype) { target.mPrototype = dynamic_cast<THnSparseF*>(mPrototype->Clone()); + } } //____________________________________________________________________ @@ -218,11 +223,13 @@ Long64_t StepTHn<TemplateArray, TemplateType>::Merge(TCollection* list) // PROOF). // Returns the number of merged objects (including this). - if (!list) + if (!list) { return 0; + } - if (list->IsEmpty()) + if (list->IsEmpty()) { return 1; + } TIterator* iter = list->MakeIterator(); TObject* obj; @@ -231,24 +238,29 @@ Long64_t StepTHn<TemplateArray, TemplateType>::Merge(TCollection* list) while ((obj = iter->Next())) { StepTHn* entry = dynamic_cast<StepTHn*>(obj); - if (entry == nullptr) + if (entry == nullptr) { continue; + } for (Int_t i = 0; i < mNSteps; i++) { if (entry->mValues[i]) { - if (!mValues[i]) + if (!mValues[i]) { mValues[i] = new TemplateArray(mNBins); + } - for (Long64_t l = 0; l < mNBins; l++) + for (Long64_t l = 0; l < mNBins; l++) { mValues[i]->GetArray()[l] += entry->mValues[i]->GetArray()[l]; + } } if (entry->mSumw2[i]) { - if (!mSumw2[i]) + if (!mSumw2[i]) { mSumw2[i] = new TemplateArray(mNBins); + } - for (Long64_t l = 0; l < mNBins; l++) + for (Long64_t l = 0; l < mNBins; l++) { mSumw2[i]->GetArray()[l] += entry->mSumw2[i]->GetArray()[l]; + } } } @@ -288,9 +300,9 @@ void StepTHn<TemplateArray, TemplateType>::Fill(const Double_t* var, Int_t istep bin *= mNbinsCache[i]; Int_t tmpBin = 0; - if (mLastVars[i] == var[i]) + if (mLastVars[i] == var[i]) { tmpBin = mLastBins[i]; - else { + } else { tmpBin = mAxisCache[i]->FindBin(var[i]); mLastBins[i] = tmpBin; mLastVars[i] = var[i]; @@ -298,8 +310,9 @@ void StepTHn<TemplateArray, TemplateType>::Fill(const Double_t* var, Int_t istep //Printf("%d", tmpBin); // under/overflow not supported - if (tmpBin < 1 || tmpBin > mNbinsCache[i]) + if (tmpBin < 1 || tmpBin > mNbinsCache[i]) { return; + } // bins start from 0 here bin += tmpBin - 1; @@ -320,8 +333,9 @@ void StepTHn<TemplateArray, TemplateType>::Fill(const Double_t* var, Int_t istep } mValues[istep]->GetArray()[bin] += weight; - if (mSumw2[istep]) + if (mSumw2[istep]) { mSumw2[istep]->GetArray()[bin] += weight * weight; + } // Printf("%f", mValues[istep][bin]); @@ -357,23 +371,27 @@ void StepTHn<TemplateArray, TemplateType>::createTarget(Int_t step, Bool_t spars if (!mTarget) { mTarget = new THnBase*[mNSteps]; - for (Int_t i = 0; i < mNSteps; i++) + for (Int_t i = 0; i < mNSteps; i++) { mTarget[i] = nullptr; + } } - if (mTarget[step]) + if (mTarget[step]) { return; + } TemplateType* source = mValues[step]->GetArray(); // if mSumw2 is not stored, the sqrt of the number of bin entries in source is filled below; otherwise we use mSumw2 TemplateType* sourceSumw2 = source; - if (mSumw2[step]) + if (mSumw2[step]) { sourceSumw2 = mSumw2[step]->GetArray(); + } - if (sparse) + if (sparse) { mTarget[step] = THnSparse::CreateSparse(Form("%s_%d", GetName(), step), Form("%s_%d", GetTitle(), step), mPrototype); - else + } else { mTarget[step] = THn::CreateHn(Form("%s_%d", GetName(), step), Form("%s_%d", GetTitle(), step), mPrototype); + } THnBase* target = mTarget[step]; @@ -409,8 +427,9 @@ void StepTHn<TemplateArray, TemplateType>::createTarget(Int_t step, Bool_t spars } } - if (binIdx[0] > nBins[0]) + if (binIdx[0] > nBins[0]) { break; + } } LOGF(info, "Step %d: copied %lld entries out of %lld bins", step, count, getGlobalBinIndex(binIdx)); diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 008083f729c01..553555f5060b8 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -50,10 +50,12 @@ void VarManager::ResetValues(int startValue, int endValue, float* values) // // reset all variables to an "innocent" value // NOTE: here we use -9999.0 as a neutral value, but depending on situation, this may not be the case - if (!values) + if (!values) { values = fgValues; - for (Int_t i = startValue; i < endValue; ++i) + } + for (Int_t i = startValue; i < endValue; ++i) { values[i] = -9999.; + } } //__________________________________________________________________ @@ -62,8 +64,9 @@ void VarManager::SetRunNumbers(int n, int* runs) // // maps the list of runs such that one can plot the list of runs nicely in a histogram axis // - for (int i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { fgRunMap[runs[i]] = i + 1; + } } //__________________________________________________________________ @@ -72,8 +75,9 @@ void VarManager::FillEventDerived(float* values) // // Fill event-wise derived quantities (these are all quantities which can be computed just based on the values already filled in the FillEvent() function) // - if (fgUsedVars[kRunId]) + if (fgUsedVars[kRunId]) { values[kRunId] = (fgRunMap.size() > 0 ? fgRunMap[int(values[kRunNo])] : 0); + } } //__________________________________________________________________ @@ -82,8 +86,9 @@ void VarManager::FillTrackDerived(float* values) // // Fill track-wise derived quantities (these are all quantities which can be computed just based on the values already filled in the FillTrack() function) // - if (fgUsedVars[kP]) + if (fgUsedVars[kP]) { values[kP] = values[kPt] * TMath::CosH(values[kEta]); + } } //__________________________________________________________________ diff --git a/Analysis/DataModel/include/PID/TOFReso.h b/Analysis/DataModel/include/PID/TOFReso.h index 6b71105ceccb1..7cb8745c3e7f3 100644 --- a/Analysis/DataModel/include/PID/TOFReso.h +++ b/Analysis/DataModel/include/PID/TOFReso.h @@ -34,8 +34,9 @@ class TOFReso : public Parametrization float operator()(const float* x) const override { const float mom = abs(x[0]); - if (mom <= 0) + if (mom <= 0) { return -999; + } const float time = x[1]; const float evtimereso = x[2]; const float mass = x[3]; diff --git a/Analysis/DataModel/src/aodDataModelGraph.cxx b/Analysis/DataModel/src/aodDataModelGraph.cxx index 6653ddce6c9d3..49454df0cd62a 100644 --- a/Analysis/DataModel/src/aodDataModelGraph.cxx +++ b/Analysis/DataModel/src/aodDataModelGraph.cxx @@ -80,7 +80,9 @@ template <typename T> Style getStyleFor() { auto label = MetadataTrait<T>::metadata::tableLabel(); - auto entry = std::find_if(tableStyles.begin(), tableStyles.end(), [&](auto&& x) { if (std::string(label).find(x.first) != std::string::npos) return true; return false; }); + auto entry = std::find_if(tableStyles.begin(), tableStyles.end(), [&](auto&& x) { if (std::string(label).find(x.first) != std::string::npos) { return true; + +}return false; }); if (entry != tableStyles.end()) { auto value = *entry; return styles[value.second]; diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index 425a7d9a3fd9a..b55bec738780d 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -120,8 +120,9 @@ struct CorrelationTask { same->fillEvent(centrality, CorrelationContainer::kCFStepAll); - if (!collision.sel7()) + if (!collision.sel7()) { return; + } same->fillEvent(centrality, CorrelationContainer::kCFStepTriggered); @@ -142,8 +143,9 @@ struct CorrelationTask { yields->Fill(centrality, track1.pt(), track1.eta()); etaphi->Fill(centrality, track1.eta(), track1.phi()); - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; + } double eventValues[3]; eventValues[0] = track1.pt(); @@ -154,22 +156,28 @@ struct CorrelationTask { //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); for (auto& track2 : tracks) { - if (track1 == track2) + if (track1 == track2) { continue; + } - if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) + if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) { continue; + } - if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) + if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) { continue; - if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) + } + if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) { continue; + } - if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) + if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) { continue; + } - if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, bSign)) + if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, bSign)) { continue; + } double values[6] = {0}; @@ -179,10 +187,12 @@ struct CorrelationTask { values[3] = centrality; values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) + if (values[4] > 1.5 * TMath::Pi()) { values[4] -= TMath::TwoPi(); - if (values[4] < -0.5 * TMath::Pi()) + } + if (values[4] < -0.5 * TMath::Pi()) { values[4] += TMath::TwoPi(); + } values[5] = collision.posZ(); @@ -201,8 +211,9 @@ struct CorrelationTask { for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; + } // LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); @@ -218,18 +229,23 @@ struct CorrelationTask { for (auto& [track1, track2] : combinations(tracks, tracks)) { //LOGF(info, "Combination %d %d", track1.index(), track2.index()); - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; - if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) + } + if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) { continue; - if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) + } + if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) { continue; + } - if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) + if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) { continue; + } - if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, bSign)) + if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, bSign)) { continue; + } double values[6] = {0}; @@ -239,10 +255,12 @@ struct CorrelationTask { values[3] = 0; // collision.v0mult(); values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) + if (values[4] > 1.5 * TMath::Pi()) { values[4] -= TMath::TwoPi(); - if (values[4] < -0.5 * TMath::Pi()) + } + if (values[4] < -0.5 * TMath::Pi()) { values[4] += TMath::TwoPi(); + } values[5] = collision.posZ(); diff --git a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx index 48c50c903ed9d..349329d9a7afa 100644 --- a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx +++ b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx @@ -99,8 +99,9 @@ struct CorrelationTask { "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" "vertex_eff: 10 | -10, 10\n"; - if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) + if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) { cfg.mPairCuts = true; + } // --- OBJECT INIT --- same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentralityVtx", binning)); @@ -141,8 +142,9 @@ struct CorrelationTask { yields->Fill(centrality, track1.pt(), track1.eta()); etaphi->Fill(centrality, track1.eta(), track1.phi()); - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; + } double eventValues[3]; eventValues[0] = track1.pt(); @@ -153,22 +155,28 @@ struct CorrelationTask { //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); for (auto& track2 : tracks) { - if (track1 == track2) + if (track1 == track2) { continue; + } - if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) + if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) { continue; + } - if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) + if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) { continue; - if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) + } + if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) { continue; + } - if (cfg.mPairCuts && conversionCuts(track1, track2)) + if (cfg.mPairCuts && conversionCuts(track1, track2)) { continue; + } - if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) + if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) { continue; + } double values[6] = {0}; @@ -178,10 +186,12 @@ struct CorrelationTask { values[3] = centrality; values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) + if (values[4] > 1.5 * TMath::Pi()) { values[4] -= TMath::TwoPi(); - if (values[4] < -0.5 * TMath::Pi()) + } + if (values[4] < -0.5 * TMath::Pi()) { values[4] += TMath::TwoPi(); + } values[5] = collision.posZ(); @@ -195,23 +205,30 @@ struct CorrelationTask { bool conversionCuts(T const& track1, T const& track2) { // skip if like sign - if (track1.charge() * track2.charge() > 0) + if (track1.charge() * track2.charge() > 0) { return false; + } bool decision = false; - if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) + if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) { decision = true; - if (conversionCut(track1, track2, K0, cfgPairCutK0)) + } + if (conversionCut(track1, track2, K0, cfgPairCutK0)) { decision = true; - if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) + } + if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) { decision = true; - if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) + } + if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) { decision = true; - if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) + } + if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) { decision = true; - if (conversionCut(track1, track2, Rho, cfgPairCutRho)) + } + if (conversionCut(track1, track2, Rho, cfgPairCutRho)) { decision = true; + } return decision; } @@ -221,8 +238,9 @@ struct CorrelationTask { { //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); - if (cut < 0) + if (cut < 0) { return false; + } double massD1, massD2, massM; @@ -256,13 +274,15 @@ struct CorrelationTask { auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); - if (TMath::Abs(massC - massM * massM) > cut * 5) + if (TMath::Abs(massC - massM * massM) > cut * 5) { return false; + } massC = getInvMassSquared(track1, massD1, track2, massD2); qa.mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); - if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) { return true; + } return false; } @@ -331,18 +351,21 @@ struct CorrelationTask { // fold onto 0...pi float deltaPhi = TMath::Abs(phi1 - phi2); - while (deltaPhi > TMath::TwoPi()) + while (deltaPhi > TMath::TwoPi()) { deltaPhi -= TMath::TwoPi(); - if (deltaPhi > TMath::Pi()) + } + if (deltaPhi > TMath::Pi()) { deltaPhi = TMath::TwoPi() - deltaPhi; + } float cosDeltaPhi = 0; - if (deltaPhi < TMath::Pi() / 3) + if (deltaPhi < TMath::Pi() / 3) { cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; - else if (deltaPhi < 2 * TMath::Pi() / 3) + } else if (deltaPhi < 2 * TMath::Pi() / 3) { cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); - else + } else { cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); + } double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); @@ -414,12 +437,15 @@ struct CorrelationTask { static const Double_t kPi = TMath::Pi(); - if (dphistar > kPi) + if (dphistar > kPi) { dphistar = kPi * 2 - dphistar; - if (dphistar < -kPi) + } + if (dphistar < -kPi) { dphistar = -kPi * 2 - dphistar; - if (dphistar > kPi) // might look funny but is needed + } + if (dphistar > kPi) { // might look funny but is needed dphistar = kPi * 2 - dphistar; + } return dphistar; } diff --git a/Analysis/Tasks/PWGCF/correlationsMixed.cxx b/Analysis/Tasks/PWGCF/correlationsMixed.cxx index b07b0051a91fb..a3c1f27c14e9f 100644 --- a/Analysis/Tasks/PWGCF/correlationsMixed.cxx +++ b/Analysis/Tasks/PWGCF/correlationsMixed.cxx @@ -73,10 +73,12 @@ struct HashTask { int getHash(std::vector<float> const& vtxBins, std::vector<float> const& multBins, float vtx, float mult) { // underflow - if (vtx < vtxBins[0]) + if (vtx < vtxBins[0]) { return -1; - if (mult < multBins[0]) + } + if (mult < multBins[0]) { return -1; + } for (int i = 1; i < vtxBins.size(); i++) { if (vtx < vtxBins[i]) { @@ -162,8 +164,9 @@ struct CorrelationTask { "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" "vertex_eff: -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10\n"; - if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) + if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) { cfg.mPairCuts = true; + } // --- OBJECT INIT --- same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentrality", binning)); @@ -221,8 +224,9 @@ struct CorrelationTask { for (auto& track1 : tracks1) { - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; + } //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.etam(), track1.phi(), track1.phim(), track1.pt(), track1.ptm()); @@ -235,16 +239,20 @@ struct CorrelationTask { for (auto& track2 : tracks2) { - if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) + if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.charge() < 0) { continue; - if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) + } + if (cfgPairCharge != 0 && cfgPairCharge * track1.charge() * track2.charge() < 0) { continue; + } - if (cfg.mPairCuts && conversionCuts(track1, track2)) + if (cfg.mPairCuts && conversionCuts(track1, track2)) { continue; + } - if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) + if (cfgTwoTrackCut > 0 && twoTrackCut(track1, track2, bSign)) { continue; + } double values[6] = {0}; @@ -254,10 +262,12 @@ struct CorrelationTask { values[3] = collision1.centV0M(); values[4] = track1.phim() - track2.phim(); - if (values[4] > 1.5 * TMath::Pi()) + if (values[4] > 1.5 * TMath::Pi()) { values[4] -= TMath::TwoPi(); - if (values[4] < -0.5 * TMath::Pi()) + } + if (values[4] < -0.5 * TMath::Pi()) { values[4] += TMath::TwoPi(); + } values[5] = collision1.posZ(); @@ -271,23 +281,30 @@ struct CorrelationTask { bool conversionCuts(T const& track1, T const& track2) { // skip if like sign - if (track1.charge() * track2.charge() > 0) + if (track1.charge() * track2.charge() > 0) { return false; + } bool decision = false; - if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) + if (conversionCut(track1, track2, Photon, cfgPairCutPhoton)) { decision = true; - if (conversionCut(track1, track2, K0, cfgPairCutK0)) + } + if (conversionCut(track1, track2, K0, cfgPairCutK0)) { decision = true; - if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) + } + if (conversionCut(track1, track2, Lambda, cfgPairCutLambda)) { decision = true; - if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) + } + if (conversionCut(track2, track1, Lambda, cfgPairCutLambda)) { decision = true; - if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) + } + if (conversionCut(track1, track2, Phi, cfgPairCutPhi)) { decision = true; - if (conversionCut(track1, track2, Rho, cfgPairCutRho)) + } + if (conversionCut(track1, track2, Rho, cfgPairCutRho)) { decision = true; + } return decision; } @@ -297,8 +314,9 @@ struct CorrelationTask { { //LOGF(info, "pt is %f %f", track1.ptm(), track2.ptm()); - if (cut < 0) + if (cut < 0) { return false; + } double massD1, massD2, massM; @@ -332,13 +350,15 @@ struct CorrelationTask { auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); - if (TMath::Abs(massC - massM * massM) > cut * 5) + if (TMath::Abs(massC - massM * massM) > cut * 5) { return false; + } massC = getInvMassSquared(track1, massD1, track2, massD2); qa.mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); - if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) { return true; + } return false; } @@ -407,18 +427,21 @@ struct CorrelationTask { // fold onto 0...pi float deltaPhi = TMath::Abs(phi1 - phi2); - while (deltaPhi > TMath::TwoPi()) + while (deltaPhi > TMath::TwoPi()) { deltaPhi -= TMath::TwoPi(); - if (deltaPhi > TMath::Pi()) + } + if (deltaPhi > TMath::Pi()) { deltaPhi = TMath::TwoPi() - deltaPhi; + } float cosDeltaPhi = 0; - if (deltaPhi < TMath::Pi() / 3) + if (deltaPhi < TMath::Pi() / 3) { cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; - else if (deltaPhi < 2 * TMath::Pi() / 3) + } else if (deltaPhi < 2 * TMath::Pi() / 3) { cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); - else + } else { cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); + } double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); @@ -490,12 +513,15 @@ struct CorrelationTask { static const Double_t kPi = TMath::Pi(); - if (dphistar > kPi) + if (dphistar > kPi) { dphistar = kPi * 2 - dphistar; - if (dphistar < -kPi) + } + if (dphistar < -kPi) { dphistar = -kPi * 2 - dphistar; - if (dphistar > kPi) // might look funny but is needed + } + if (dphistar > kPi) { // might look funny but is needed dphistar = kPi * 2 - dphistar; + } return dphistar; } diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index 58aa9fbb72b4e..327802d5bdadf 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -218,10 +218,11 @@ bool matchTrackType(aod::TrackData const& track) { switch (tracktype) { case 1: - if (track.isGlobalTrack() != 0 || track.isGlobalTrackSDD() != 0) + if (track.isGlobalTrack() != 0 || track.isGlobalTrackSDD() != 0) { return true; - else + } else { return false; + } break; default: return false; @@ -252,10 +253,11 @@ inline void AcceptTrack(aod::TrackData const& track, uint8_t& asone, uint8_t& as /// \return the track phi origin shifted azimuthal angle inline float GetShiftedPhi(float phi) { - if (not(phi < phiup)) + if (not(phi < phiup)) { return phi - TMath::TwoPi(); - else + } else { return phi; + } } /// \brief Returns the zero based bin index of the eta phi passed track diff --git a/Analysis/Tasks/PWGCF/filterCF.cxx b/Analysis/Tasks/PWGCF/filterCF.cxx index 3956924ae44c4..05ef5f3860c83 100644 --- a/Analysis/Tasks/PWGCF/filterCF.cxx +++ b/Analysis/Tasks/PWGCF/filterCF.cxx @@ -50,17 +50,19 @@ struct FilterCF { { LOGF(info, "Tracks for collision: %d | Vertex: %.1f | INT7: %d | V0M: %.1f", tracks.size(), collision.posZ(), collision.sel7(), collision.centV0M()); - if (!collision.sel7()) + if (!collision.sel7()) { return; + } outputCollisions(collision.bc().runNumber(), collision.posZ(), collision.centV0M()); for (auto& track : tracks) { uint8_t trackType = 0; - if (track.isGlobalTrack()) + if (track.isGlobalTrack()) { trackType = 1; - else if (track.isGlobalTrackSDD()) + } else if (track.isGlobalTrackSDD()) { trackType = 2; + } outputTracks(outputCollisions.lastIndex(), track.pt(), track.eta(), track.phi(), track.charge(), trackType); diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx index d047085e6e5c9..eaeb00d4575c0 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -154,14 +154,16 @@ struct BarrelTrackSelection { void process(MyEvent event, MyBarrelTracks const& tracks) { - for (int i = 0; i < VarManager::kNVars; ++i) + 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<fgEventFillMap>(event, fValues); for (auto& track : tracks) { - for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) { fValues[i] = -9999.0f; + } VarManager::FillTrack<fgTrackFillMap>(track, fValues); fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); @@ -172,8 +174,9 @@ struct BarrelTrackSelection { ) { trackSel(1); fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); - } else + } else { trackSel(0); + } } } }; @@ -219,8 +222,9 @@ struct DileptonEE { VarManager::FillEvent<fgEventFillMap>(event); fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event - if (!fEventCut->IsSelected(VarManager::fgValues)) + if (!fEventCut->IsSelected(VarManager::fgValues)) { return; + } fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); // Run the same event pairing for barrel tracks @@ -268,8 +272,9 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin const int kNRuns = 2; int runs[kNRuns] = {244918, 244919}; TString runsStr; - for (int i = 0; i < kNRuns; i++) + for (int i = 0; i < kNRuns; i++) { runsStr += Form("%d;", runs[i]); + } VarManager::SetRunNumbers(kNRuns, runs); TObjArray* arr = histClasses.Tokenize(";"); diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx index 198660d58519a..c5e366856e8c2 100644 --- a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -111,22 +111,25 @@ struct MuonTrackSelection { void process(MyEvent event, MyMuonTracks const& muons) { - for (int i = 0; i < VarManager::kNVars; ++i) + 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<fgEventMuonFillMap>(event, fValues); for (auto& muon : muons) { - for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) { fValues[i] = -9999.0f; + } VarManager::FillTrack<fgMuonFillMap>(muon, fValues); fHistMan->FillHistClass("TrackMuon_BeforeCuts", fValues); if (fMuonCut->IsSelected(fValues)) { trackSel(1); fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); - } else + } else { trackSel(0); + } } } }; @@ -179,8 +182,9 @@ struct DileptonMuMu { VarManager::FillEvent<fgEventMuonFillMap>(event); fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event - if (!fEventCut->IsSelected(VarManager::fgValues)) + if (!fEventCut->IsSelected(VarManager::fgValues)) { return; + } fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); // same event pairing for muons @@ -188,22 +192,25 @@ struct DileptonMuMu { 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); - if (!fDiMuonCut->IsSelected(VarManager::fgValues)) + if (!fDiMuonCut->IsSelected(VarManager::fgValues)) { return; + } fHistMan->FillHistClass("PairsMuonULS", VarManager::fgValues); } for (auto tpos2 = tpos + 1; tpos2 != posMuons.end(); ++tpos2) { // ++ pairs VarManager::FillPair(tpos, tpos2); - if (!fDiMuonCut->IsSelected(VarManager::fgValues)) + if (!fDiMuonCut->IsSelected(VarManager::fgValues)) { return; + } fHistMan->FillHistClass("PairsMuonLSpp", VarManager::fgValues); } } for (auto tneg : negMuons) { // -- pairs for (auto tneg2 = tneg + 1; tneg2 != negMuons.end(); ++tneg2) { VarManager::FillPair(tneg, tneg2); - if (!fDiMuonCut->IsSelected(VarManager::fgValues)) + if (!fDiMuonCut->IsSelected(VarManager::fgValues)) { return; + } fHistMan->FillHistClass("PairsMuonLSnn", VarManager::fgValues); } } @@ -220,8 +227,9 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin const int kNRuns = 2; int runs[kNRuns] = {244918, 244919}; TString runsStr; - for (int i = 0; i < kNRuns; i++) + for (int i = 0; i < kNRuns; i++) { runsStr += Form("%d;", runs[i]); + } VarManager::SetRunNumbers(kNRuns, runs); TObjArray* arr = histClasses.Tokenize(";"); diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index 9d9841d89e544..d47dd428f249b 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -119,16 +119,19 @@ struct TableMaker { { uint64_t tag = 0; uint32_t triggerAliases = 0; - for (int i = 0; i < kNaliases; i++) - if (collision.alias()[i] > 0) + for (int i = 0; i < kNaliases; i++) { + if (collision.alias()[i] > 0) { triggerAliases |= (uint32_t(1) << i); + } + } VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); VarManager::FillEvent<gkEventFillMap>(collision, fValues); // extract event information and place it in the fgValues array fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event - if (!fEventCut->IsSelected(fValues)) + if (!fEventCut->IsSelected(fValues)) { return; + } fHistMan->FillHistClass("Event_AfterCuts", fValues); @@ -147,8 +150,9 @@ struct TableMaker { VarManager::FillTrack<gkTrackFillMap>(track, fValues); fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); - if (!fTrackCut->IsSelected(fValues)) + if (!fTrackCut->IsSelected(fValues)) { continue; + } fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); // TODO: update the DCA calculation (use the values computed in the trackSelection workflow or use the propagateToDCA function from there) @@ -184,8 +188,9 @@ struct TableMaker { for (auto& muon : tracksMuon) { // TODO: add proper information for muon tracks - if (muon.bc() != collision.bc()) + if (muon.bc() != collision.bc()) { continue; + } // TODO: the trackFilteringFlag will not be needed to encode whether the track is a muon since there is a dedicated table for muons trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track muonBasic(event.lastIndex(), trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); @@ -198,8 +203,9 @@ struct TableMaker { const int kNRuns = 2; int runs[kNRuns] = {244918, 244919}; TString runsStr; - for (int i = 0; i < kNRuns; i++) + for (int i = 0; i < kNRuns; i++) { runsStr += Form("%d;", runs[i]); + } VarManager::SetRunNumbers(kNRuns, runs); TObjArray* arr = histClasses.Tokenize(";"); diff --git a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx index e32e8236867b5..d629257e4f6cf 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx @@ -72,9 +72,11 @@ struct TableMaker_pp { { uint64_t tag = 0; uint32_t triggerAliases = 0; - for (int i = 0; i < kNaliases; i++) - if (collision.alias()[i] > 0) + for (int i = 0; i < kNaliases; i++) { + if (collision.alias()[i] > 0) { triggerAliases |= (uint32_t(1) << i); + } + } VarManager::ResetValues(); VarManager::FillEvent<fgEventFillMap>(collision); // extract event information and place it in the fgValues array @@ -93,10 +95,12 @@ struct TableMaker_pp { float dcaZ = 0.f; for (auto& track : tracksBarrel) { - if (track.pt() < 0.15) + if (track.pt() < 0.15) { continue; - if (TMath::Abs(track.eta()) > 0.9) + } + if (TMath::Abs(track.eta()) > 0.9) { continue; + } sinAlpha = sin(track.alpha()); cosAlpha = cos(track.alpha()); @@ -129,8 +133,9 @@ struct TableMaker_pp { for (auto& muon : tracksMuon) { // TODO: add proper information for muon tracks - if (muon.bc() != collision.bc()) + if (muon.bc() != collision.bc()) { continue; + } trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track muonBasic(collision, trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); @@ -142,8 +147,9 @@ struct TableMaker_pp { const int kNRuns = 2; int runs[kNRuns] = {244918, 244919}; TString runsStr; - for (int i = 0; i < kNRuns; i++) + for (int i = 0; i < kNRuns; i++) { runsStr += Form("%d;", runs[i]); + } VarManager::SetRunNumbers(kNRuns, runs); TObjArray* arr = histClasses.Tokenize(";"); diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index cd2912812b926..b4fc30978d128 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -147,8 +147,9 @@ struct EventSelection { if (fEventCut->IsSelected(fValues)) { fHistMan->FillHistClass("Event_AfterCuts", fValues); eventSel(1); - } else + } else { eventSel(0); + } } }; @@ -171,8 +172,9 @@ struct BarrelTrackSelection { fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); TString cutNames = "TrackBarrel_BeforeCuts;"; - for (int i = 0; i < gNTrackCuts; i++) + for (int i = 0; i < gNTrackCuts; i++) { cutNames += Form("TrackBarrel_%s;", fTrackCuts[i].GetName()); + } DefineHistograms(fHistMan, cutNames.Data()); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill @@ -229,8 +231,9 @@ struct BarrelTrackSelection { for (auto& track : tracks) { filterMap = uint8_t(0); VarManager::FillTrack<gkTrackFillMap>(track, fValues); - if (event.isEventSelected()) + if (event.isEventSelected()) { fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + } int i = 0; for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { @@ -292,8 +295,9 @@ struct MuonTrackSelection { trackSel(1); //if(event.isEventSelected()) fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); - } else + } else { trackSel(0); + } } } }; @@ -320,8 +324,9 @@ struct TableReader { fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); TString histNames = ""; - for (int i = 0; i < gNTrackCuts; i++) + for (int i = 0; i < gNTrackCuts; i++) { histNames += Form("PairsBarrelPM_cut%d;PairsBarrelPP_cut%d;PairsBarrelMM_cut%d;", i + 1, i + 1, i + 1); + } DefineHistograms(fHistMan, histNames.Data()); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill @@ -331,8 +336,9 @@ struct TableReader { //void process(soa::Filtered<MyEventsVtxCovSelected>::iterator const& event, MyBarrelTracksSelected const& tracks, MyMuonTracksSelected const& muons) void process(MyEventsVtxCovSelected::iterator const& event, MyBarrelTracksSelected const& tracks, MyMuonTracksSelected const& muons) { - if (!event.isEventSelected()) + if (!event.isEventSelected()) { return; + } // Reset the fValues array VarManager::ResetValues(0, VarManager::kNVars, fValues); @@ -350,37 +356,43 @@ struct TableReader { for (auto tpos : posTracks) { for (auto tneg : negTracks) { // +- pairs filter = tpos.isBarrelSelected() & tneg.isBarrelSelected(); - if (!filter) // the tracks must have at least one filter bit in common to continue + if (!filter) { // the tracks must have at least one filter bit in common to continue continue; + } VarManager::FillPair(tpos, tneg, fValues); dileptonList(event, fValues[VarManager::kMass], fValues[VarManager::kPt], fValues[VarManager::kEta], fValues[VarManager::kPhi], 0, filter); for (int i = 0; i < gNTrackCuts; ++i) { - if (filter & (uint8_t(1) << i)) + if (filter & (uint8_t(1) << i)) { fHistMan->FillHistClass(Form("PairsBarrelPM_cut%d", i + 1), fValues); + } } } for (auto tpos2 = tpos + 1; tpos2 != posTracks.end(); ++tpos2) { // ++ pairs filter = tpos.isBarrelSelected() & tpos2.isBarrelSelected(); - if (!filter) // the tracks must have at least one filter bit in common to continue + if (!filter) { // the tracks must have at least one filter bit in common to continue continue; + } VarManager::FillPair(tpos, tpos2, fValues); dileptonList(event, fValues[VarManager::kMass], fValues[VarManager::kPt], fValues[VarManager::kEta], fValues[VarManager::kPhi], 2, filter); for (int i = 0; i < gNTrackCuts; ++i) { - if (filter & (uint8_t(1) << i)) + if (filter & (uint8_t(1) << i)) { fHistMan->FillHistClass(Form("PairsBarrelPP_cut%d", i + 1), fValues); + } } } } for (auto tneg : negTracks) { // -- pairs for (auto tneg2 = tneg + 1; tneg2 != negTracks.end(); ++tneg2) { filter = tneg.isBarrelSelected() & tneg2.isBarrelSelected(); - if (!filter) // the tracks must have at least one filter bit in common to continue + if (!filter) { // the tracks must have at least one filter bit in common to continue continue; + } VarManager::FillPair(tneg, tneg2, fValues); dileptonList(event, fValues[VarManager::kMass], fValues[VarManager::kPt], fValues[VarManager::kEta], fValues[VarManager::kPhi], -2, filter); for (int i = 0; i < gNTrackCuts; ++i) { - if (filter & (uint8_t(1) << i)) + if (filter & (uint8_t(1) << i)) { fHistMan->FillHistClass(Form("PairsBarrelMM_cut%d", i + 1), fValues); + } } } } @@ -466,8 +478,9 @@ struct DileptonHadronAnalysis { // loop over hadrons for (auto& hadron : hadrons) { VarManager::FillTrack<gkTrackFillMap>(hadron, fValuesHadron); - if (!fHadronCut->IsSelected(fValuesHadron)) // TODO: this will be moved to a partition when the selection will be done in the barrel/muon track selection + if (!fHadronCut->IsSelected(fValuesHadron)) { // TODO: this will be moved to a partition when the selection will be done in the barrel/muon track selection continue; + } fHistMan->FillHistClass("HadronsSelected", fValuesHadron); @@ -516,8 +529,9 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) 246847, 246851, 246865, 246867, 246870, 246871, 246928, 246945, 246948, 246980, 246982, 246984, 246989, 246991, 246994}; TString runsStr; - for (int i = 0; i < kNRuns; i++) + for (int i = 0; i < kNRuns; i++) { runsStr += Form("%d;", runs[i]); + } VarManager::SetRunNumbers(kNRuns, runs); TObjArray* arr = histClasses.Tokenize(";"); diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 5185085e64c85..46cb0a13a1063 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -66,8 +66,9 @@ struct HFCandidateCreator2Prong { auto collision = rowTrackIndexProng2.index0().collision(); // reconstruct the 2-prong secondary vertex - if (df.process(trackParVarPos1, trackParVarNeg1) == 0) + if (df.process(trackParVarPos1, trackParVarNeg1) == 0) { continue; + } const auto& secondaryVertex = df.getPCACandidate(); auto chi2PCA = df.getChi2AtPCACandidate(); auto covMatrixPCA = df.calcPCACovMatrix().Array(); diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 07096f904515c..a00ae4c8f2bf9 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -66,8 +66,9 @@ struct HFCandidateCreator3Prong { auto collision = rowTrackIndexProng3.index0().collision(); // reconstruct the 3-prong secondary vertex - if (df.process(trackParVar0, trackParVar1, trackParVar2) == 0) + if (df.process(trackParVar0, trackParVar1, trackParVar2) == 0) { continue; + } const auto& secondaryVertex = df.getPCACandidate(); auto chi2PCA = df.getChi2AtPCACandidate(); auto covMatrixPCA = df.calcPCACovMatrix().Array(); diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index 262d2c07ee0b6..b0de359ef6fd6 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -111,8 +111,9 @@ struct HFD0CandidateSelector { { auto candpT = hfCandProng2.pt(); int pTBin = getpTBin(candpT); - if (pTBin == -1) + if (pTBin == -1) { return false; + } if (candpT < d_pTCandMin || candpT >= d_pTCandMax) { return false; //check that the candidate pT is within the analysis range @@ -159,8 +160,9 @@ struct HFD0CandidateSelector { auto candpT = hfCandProng2.pt(); int pTBin = getpTBin(candpT); - if (pTBin == -1) + if (pTBin == -1) { return false; + } if (trackPion.charge() > 0) { //invariant mass cut if (TMath::Abs(InvMassD0(hfCandProng2) - RecoDecay::getMassPDG(421)) > cuts[pTBin][0]) { @@ -255,16 +257,18 @@ struct HFD0CandidateSelector { { double nSigma = 0.0; nPDG = TMath::Abs(nPDG); - if (nPDG == 111) + if (nPDG == 111) { nSigma = track.tofNSigmaPi(); - else if (nPDG == 321) + } else if (nPDG == 321) { nSigma = track.tofNSigmaKa(); - else + } else { return nSigma = 100; //arbitarily large value - if (nSigma < nSigmaCut) + } + if (nSigma < nSigmaCut) { return true; - else + } else { return false; + } } /// PID selection on daughter track @@ -369,14 +373,18 @@ struct HFD0CandidateSelector { piMinus = selectionPID(trackNeg, 211); kPlus = selectionPID(trackPos, 321); - if (piPlus == 0 || kMinus == 0 || piMinus == 1 || kPlus == 1) + if (piPlus == 0 || kMinus == 0 || piMinus == 1 || kPlus == 1) { pidD0 = 0; //exclude D0 - if (piPlus == 1 || kMinus == 1 || piMinus == 0 || kPlus == 0) + } + if (piPlus == 1 || kMinus == 1 || piMinus == 0 || kPlus == 0) { pidD0bar = 0; //exclude D0bar - if (piPlus == 1 && kMinus == 1) + } + if (piPlus == 1 && kMinus == 1) { pidD0 = 1; //accept D0 - if (piMinus == 1 && kPlus == 1) + } + if (piMinus == 1 && kPlus == 1) { pidD0bar = 1; //accept D0bar + } if (pidD0 == 0 && pidD0bar == 0) { hfSelD0Candidate(statusD0, statusD0bar); diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index fef7ebac5c865..004e58933179d 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -60,20 +60,25 @@ struct SelectTracks { int status_2prong = 1; // selection flag int status_3prong = 1; // selection flag - if (b_dovalplots) + if (b_dovalplots) { hpt_nocuts->Fill(track.pt()); + } // pT cut - if (track.pt() < ptmintrack_2prong) + if (track.pt() < ptmintrack_2prong) { status_2prong = 0; - if (track.pt() < ptmintrack_3prong) + } + if (track.pt() < ptmintrack_3prong) { status_3prong = 0; + } // eta cut - if (status_2prong && abs(track.eta()) > etamax_2prong) + if (status_2prong && abs(track.eta()) > etamax_2prong) { status_2prong = 0; - if (status_3prong && abs(track.eta()) > etamax_3prong) + } + if (status_3prong && abs(track.eta()) > etamax_3prong) { status_3prong = 0; + } // quality cut if (doCutQuality && (status_2prong || status_3prong)) { @@ -96,10 +101,12 @@ struct SelectTracks { status_2prong = 0; status_3prong = 0; } - if (status_2prong && abs(dca[0]) < dcatoprimxymin_2prong) + if (status_2prong && abs(dca[0]) < dcatoprimxymin_2prong) { status_2prong = 0; - if (status_3prong && abs(dca[0]) < dcatoprimxymin_3prong) + } + if (status_3prong && abs(dca[0]) < dcatoprimxymin_3prong) { status_3prong = 0; + } } // fill histograms @@ -178,8 +185,9 @@ struct HFTrackIndexSkimsCreator { if (trigindex != -1) { uint64_t triggerMask = collision.bc().triggerMask(); bool isTriggerClassFired = triggerMask & 1ul << (trigindex - 1); - if (!isTriggerClassFired) + if (!isTriggerClassFired) { return; + } } // 2-prong vertex fitter diff --git a/Analysis/Tasks/PWGJE/jetfinder.cxx b/Analysis/Tasks/PWGJE/jetfinder.cxx index 187b130a961e6..c5acbad3493a0 100644 --- a/Analysis/Tasks/PWGJE/jetfinder.cxx +++ b/Analysis/Tasks/PWGJE/jetfinder.cxx @@ -55,10 +55,12 @@ struct JetFinderTask { 70, -0.7, 0.7)); hJetN.setObject(new TH1F("h_jet_n", "jet n;n constituents", 30, 0., 30.)); - if (b_DoRhoAreaSub) + if (b_DoRhoAreaSub) { jetFinder.setBkgSubMode(JetFinder::BkgSubMode::rhoAreaSub); - if (b_DoConstSub) + } + if (b_DoConstSub) { jetFinder.setBkgSubMode(JetFinder::BkgSubMode::constSub); + } } void process(aod::Collision const& collision, @@ -86,9 +88,10 @@ struct JetFinderTask { hJetEta->Fill(jet.eta()); hJetN->Fill(jet.constituents().size()); for (const auto& constituent : jet.constituents()) { //event or jetwise - if (b_DoConstSub) + if (b_DoConstSub) { constituentsSubTable(jetsTable.lastIndex(), constituent.pt(), constituent.eta(), constituent.phi(), constituent.E(), constituent.m()); + } constituentsTable(jetsTable.lastIndex(), constituent.user_index()); } } diff --git a/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx b/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx index d5eda89cbca71..6e163be961b05 100644 --- a/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx +++ b/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx @@ -100,8 +100,9 @@ struct JetFinderHadronRecoilTask { inputParticles.emplace_back(track.px(), track.py(), track.pz(), energy); inputParticles.back().set_user_index(track.globalIndex()); } - if (!isTT) + if (!isTT) { return; + } hHadronPt->Fill(trackTTPt); // you can set phi selector here for jets diff --git a/Analysis/Tasks/PWGJE/jetsubstructure.cxx b/Analysis/Tasks/PWGJE/jetsubstructure.cxx index 5a51b6e739e03..d50ea4a07c79f 100644 --- a/Analysis/Tasks/PWGJE/jetsubstructure.cxx +++ b/Analysis/Tasks/PWGJE/jetsubstructure.cxx @@ -97,8 +97,9 @@ struct JetSubstructure { auto zg = -1.0; auto rg = -1.0; while (daughterSubJet.has_parents(parentSubJet1, parentSubJet2)) { - if (parentSubJet1.perp() < parentSubJet2.perp()) + if (parentSubJet1.perp() < parentSubJet2.perp()) { std::swap(parentSubJet1, parentSubJet2); + } auto z = parentSubJet2.perp() / (parentSubJet1.perp() + parentSubJet2.perp()); auto r = parentSubJet1.delta_R(parentSubJet2); if (z >= f_zCut * TMath::Power(r / f_jetR, f_beta)) { diff --git a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx index 902385b40b8dd..89c162cebde29 100644 --- a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx +++ b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx @@ -43,12 +43,15 @@ struct NucleiSpecraTask { { for (auto& track : tracks) { // Part not covered by filters - if (track.tpcNClsFound() < recPointsTPC) + if (track.tpcNClsFound() < recPointsTPC) { continue; - if (track.itsNCls() < recPointsITS) + } + if (track.itsNCls() < recPointsITS) { continue; - if (track.itsNClsInnerBarrel() < recPointsITSInnerBarrel) + } + if (track.itsNClsInnerBarrel() < recPointsITSInnerBarrel) { continue; + } hTPCsignal->Fill(track.p(), track.tpcSignal()); hMomentum->Fill(track.p()); diff --git a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx index b511f7fa62b07..20f4696379910 100644 --- a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx @@ -109,10 +109,12 @@ struct cascadeconsumer { void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::Cascades, aod::CascDataExt>> const& Cascades) { - if (!collision.alias()[kINT7]) + if (!collision.alias()[kINT7]) { return; - if (!collision.sel7()) + } + if (!collision.sel7()) { return; + } for (auto& casc : Cascades) { //FIXME: dynamic columns cannot be filtered on? if (casc.v0radius() > v0radius && @@ -121,15 +123,19 @@ struct cascadeconsumer { casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospa && casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) { if (casc.charge() < 0) { //FIXME: could be done better... - if (TMath::Abs(casc.yXi()) < 0.5) + if (TMath::Abs(casc.yXi()) < 0.5) { h3dMassXiMinus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); - if (TMath::Abs(casc.yOmega()) < 0.5) + } + if (TMath::Abs(casc.yOmega()) < 0.5) { h3dMassOmegaMinus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } } else { - if (TMath::Abs(casc.yXi()) < 0.5) + if (TMath::Abs(casc.yXi()) < 0.5) { h3dMassXiPlus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); - if (TMath::Abs(casc.yOmega()) < 0.5) + } + if (TMath::Abs(casc.yOmega()) < 0.5) { h3dMassOmegaPlus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } } } } diff --git a/Analysis/Tasks/PWGLF/cascadefinder.cxx b/Analysis/Tasks/PWGLF/cascadefinder.cxx index ab8c4391bfb08..fe786ab62a778 100644 --- a/Analysis/Tasks/PWGLF/cascadefinder.cxx +++ b/Analysis/Tasks/PWGLF/cascadefinder.cxx @@ -102,29 +102,37 @@ struct cascadeprefilter { soa::Join<aod::V0FinderData, aod::V0DataExt> const& V0s) { for (auto& t0 : goodPosTracks) { - if (!(t0.flags() & 0x40)) + if (!(t0.flags() & 0x40)) { continue; //TPC refit - if (t0.tpcNClsCrossedRows() < mincrossedrows) + } + if (t0.tpcNClsCrossedRows() < mincrossedrows) { continue; + } cascGoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); } for (auto& t0 : goodNegTracks) { - if (!(t0.flags() & 0x40)) + if (!(t0.flags() & 0x40)) { continue; //TPC refit - if (t0.tpcNClsCrossedRows() < mincrossedrows) + } + if (t0.tpcNClsCrossedRows() < mincrossedrows) { continue; + } cascGoodNegTracks(t0.globalIndex(), t0.collisionId(), -t0.dcaXY()); } for (auto& v0 : goodV0s) { - if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cospaV0) + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cospaV0) { continue; - if (v0.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < dcav0topv) + } + if (v0.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < dcav0topv) { continue; + } - if (fabs(v0.mLambda() - 1.116) < lambdamasswindow) + if (fabs(v0.mLambda() - 1.116) < lambdamasswindow) { cascGoodLambdas(v0.globalIndex(), v0.collisionId()); - if (fabs(v0.mAntiLambda() - 1.116) < lambdamasswindow) + } + if (fabs(v0.mAntiLambda() - 1.116) < lambdamasswindow) { cascGoodAntiLambdas(v0.globalIndex(), v0.collisionId()); + } } } }; @@ -193,8 +201,9 @@ struct cascadefinder { if (nCand != 0) { fitterV0.propagateTracksToVertex(); const auto& v0vtx = fitterV0.getPCACandidate(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { pos[i] = v0vtx[i]; + } std::array<float, 21> cov0 = {0}; std::array<float, 21> cov1 = {0}; @@ -232,8 +241,9 @@ struct cascadefinder { if (nCand2 != 0) { fitterCasc.propagateTracksToVertex(); const auto& cascvtx = fitterCasc.getPCACandidate(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { posXi[i] = cascvtx[i]; + } fitterCasc.getTrack(1).getPxPyPzGlo(pvecbach); lNCand++; @@ -263,8 +273,9 @@ struct cascadefinder { if (nCand != 0) { fitterV0.propagateTracksToVertex(); const auto& v0vtx = fitterV0.getPCACandidate(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { pos[i] = v0vtx[i]; + } std::array<float, 21> cov0 = {0}; std::array<float, 21> cov1 = {0}; @@ -302,8 +313,9 @@ struct cascadefinder { if (nCand2 != 0) { fitterCasc.propagateTracksToVertex(); const auto& cascvtx = fitterCasc.getPCACandidate(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { posXi[i] = cascvtx[i]; + } fitterCasc.getTrack(1).getPxPyPzGlo(pvecbach); lNCand++; @@ -354,10 +366,12 @@ struct cascadefinderQA { ///Connect to CascFinderData: newly indexed, note: CascDataExt table incompatible with standard V0 table! void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::CascFinderData, aod::CascDataExt>> const& Cascades) { - if (!collision.alias()[kINT7]) + if (!collision.alias()[kINT7]) { return; - if (!collision.sel7()) + } + if (!collision.sel7()) { return; + } for (auto& casc : Cascades) { //FIXME: dynamic columns cannot be filtered on? if (casc.v0radius() > v0radius && @@ -366,15 +380,19 @@ struct cascadefinderQA { casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospa && casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) { if (casc.charge() < 0) { //FIXME: could be done better... - if (TMath::Abs(casc.yXi()) < 0.5) + if (TMath::Abs(casc.yXi()) < 0.5) { h3dMassXiMinus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); - if (TMath::Abs(casc.yOmega()) < 0.5) + } + if (TMath::Abs(casc.yOmega()) < 0.5) { h3dMassOmegaMinus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } } else { - if (TMath::Abs(casc.yXi()) < 0.5) + if (TMath::Abs(casc.yXi()) < 0.5) { h3dMassXiPlus->Fill(collision.centV0M(), casc.pt(), casc.mXi()); - if (TMath::Abs(casc.yOmega()) < 0.5) + } + if (TMath::Abs(casc.yOmega()) < 0.5) { h3dMassOmegaPlus->Fill(collision.centV0M(), casc.pt(), casc.mOmega()); + } } } } diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx index 64a31f22699c6..90343a61e9d4c 100644 --- a/Analysis/Tasks/PWGLF/cascadeproducer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -100,16 +100,18 @@ struct cascadeproducer { auto pTrack = getTrackParCov(casc.v0().posTrack()); auto nTrack = getTrackParCov(casc.v0().negTrack()); auto bTrack = getTrackParCov(casc.bachelor()); - if (casc.bachelor().signed1Pt() > 0) + if (casc.bachelor().signed1Pt() > 0) { charge = +1; + } int nCand = fitterV0.process(pTrack, nTrack); if (nCand != 0) { fitterV0.propagateTracksToVertex(); hCascCandidate->Fill(1.5); const auto& v0vtx = fitterV0.getPCACandidate(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { pos[i] = v0vtx[i]; + } std::array<float, 21> cov0 = {0}; std::array<float, 21> cov1 = {0}; @@ -143,8 +145,9 @@ struct cascadeproducer { fitterCasc.propagateTracksToVertex(); hCascCandidate->Fill(2.5); const auto& cascvtx = fitterCasc.getPCACandidate(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { posXi[i] = cascvtx[i]; + } fitterCasc.getTrack(1).getPxPyPzGlo(pvecbach); } //end if cascade recoed } //end if v0 recoed diff --git a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx index 9a133dcfd4cf5..cd1b7ed42787a 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx @@ -84,10 +84,12 @@ struct lambdakzeroconsumer { void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::V0s, aod::V0DataExt>> const& fullV0s) { - if (!collision.alias()[kINT7]) + if (!collision.alias()[kINT7]) { return; - if (!collision.sel7()) + } + if (!collision.sel7()) { return; + } for (auto& v0 : fullV0s) { //FIXME: could not find out how to filter cosPA and radius variables (dynamic columns) @@ -96,8 +98,9 @@ struct lambdakzeroconsumer { h3dMassLambda->Fill(collision.centV0M(), v0.pt(), v0.mLambda()); h3dMassAntiLambda->Fill(collision.centV0M(), v0.pt(), v0.mAntiLambda()); } - if (TMath::Abs(v0.yK0Short()) < 0.5) + if (TMath::Abs(v0.yK0Short()) < 0.5) { h3dMassK0Short->Fill(collision.centV0M(), v0.pt(), v0.mK0Short()); + } } } } diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index 7605546ba775f..c2d6c0f7455d5 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -77,17 +77,21 @@ struct lambdakzeroprefilter { soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& t0 : goodPosTracks) { - if (!(t0.flags() & 0x40)) + if (!(t0.flags() & 0x40)) { continue; //TPC refit - if (t0.tpcNClsCrossedRows() < mincrossedrows) + } + if (t0.tpcNClsCrossedRows() < mincrossedrows) { continue; + } v0GoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); } for (auto& t0 : goodNegTracks) { - if (!(t0.flags() & 0x40)) + if (!(t0.flags() & 0x40)) { continue; //TPC refit - if (t0.tpcNClsCrossedRows() < mincrossedrows) + } + if (t0.tpcNClsCrossedRows() < mincrossedrows) { continue; + } v0GoodNegTracks(t0.globalIndex(), t0.collisionId(), -t0.dcaXY()); } } @@ -135,32 +139,37 @@ struct lambdakzerofinder { //Try to progate to dca int nCand = fitter.process(Track1, Track2); - if (nCand == 0) + if (nCand == 0) { continue; + } const auto& vtx = fitter.getPCACandidate(); //Fiducial: min radius auto thisv0radius = TMath::Sqrt(TMath::Power(vtx[0], 2) + TMath::Power(vtx[1], 2)); - if (thisv0radius < v0radius) + if (thisv0radius < v0radius) { continue; + } //DCA V0 daughters auto thisdcav0dau = fitter.getChi2AtPCACandidate(); - if (thisdcav0dau > dcav0dau) + if (thisdcav0dau > dcav0dau) { continue; + } std::array<float, 3> pos = {0.}; std::array<float, 3> pvec0; std::array<float, 3> pvec1; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { pos[i] = vtx[i]; + } fitter.getTrack(0).getPxPyPzGlo(pvec0); fitter.getTrack(1).getPxPyPzGlo(pvec1); auto thisv0cospa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, array{vtx[0], vtx[1], vtx[2]}, array{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}); - if (thisv0cospa < v0cospa) + if (thisv0cospa < v0cospa) { continue; + } lNCand++; v0finderdata(t0.globalIndex(), t1.globalIndex(), t0.collisionId()); @@ -206,10 +215,12 @@ struct lambdakzerofinderQA { // soa::Filtered<soa::Join<aod::V0FinderData, aod::V0DataExt>> const& fullV0s) soa::Join<aod::V0FinderData, aod::V0DataExt> const& fullV0s) { - if (!collision.alias()[kINT7]) + if (!collision.alias()[kINT7]) { return; - if (!collision.sel7()) + } + if (!collision.sel7()) { return; + } Long_t lNCand = 0; for (auto& v0 : fullV0s) { @@ -224,8 +235,9 @@ struct lambdakzerofinderQA { h3dMassLambda->Fill(collision.centV0M(), v0.pt(), v0.mLambda()); h3dMassAntiLambda->Fill(collision.centV0M(), v0.pt(), v0.mAntiLambda()); } - if (TMath::Abs(v0.yK0Short()) < 0.5) + if (TMath::Abs(v0.yK0Short()) < 0.5) { h3dMassK0Short->Fill(collision.centV0M(), v0.pt(), v0.mK0Short()); + } lNCand++; } } diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index 69664b67f5e50..7bb8ccd925a67 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -95,8 +95,9 @@ struct lambdakzeroproducer { fitter.propagateTracksToVertex(); hCascCandidate->Fill(2.5); const auto& vtx = fitter.getPCACandidate(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { pos[i] = vtx[i]; + } fitter.getTrack(0).getPxPyPzGlo(pvec0); fitter.getTrack(1).getPxPyPzGlo(pvec1); } diff --git a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx index 20636b4160630..76ed9f2e9e12b 100644 --- a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx +++ b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx @@ -64,8 +64,9 @@ struct GeneratedTask { { LOGF(info, "MC. vtx-z = %f", mcCollision.posZ()); for (auto& mcParticle : mcParticles) { - if (abs(mcParticle.eta()) > 0.8) + if (abs(mcParticle.eta()) > 0.8) { continue; + } if (isPhysicalPrimary(mcParticles, mcParticle)) { const auto pdg = Form("%i", mcParticle.pdgCode()); pdgH->Fill(pdg, 1); @@ -130,10 +131,12 @@ struct ReconstructedTask { etaDiff->Fill(track.label().eta() - track.eta(), pdgbin); auto delta = track.label().phi() - track.phi(); - if (delta > M_PI) + if (delta > M_PI) { delta -= 2 * M_PI; - if (delta < -M_PI) + } + if (delta < -M_PI) { delta += 2 * M_PI; + } phiDiff->Fill(delta, pdgbin); pDiff->Fill(sqrt(track.label().px() * track.label().px() + track.label().py() * track.label().py() + track.label().pz() * track.label().pz()) - track.p(), pdgbin); ptDiff->Fill(track.label().pt() - track.pt(), pdgbin); @@ -147,11 +150,14 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) const bool gen = cfgc.options().get<int>("add-gen"); const bool reco = cfgc.options().get<int>("add-reco"); WorkflowSpec workflow{}; - if (vertex) + if (vertex) { workflow.push_back(adaptAnalysisTask<VertexTask>("vertex-histogram")); - if (gen) + } + if (gen) { workflow.push_back(adaptAnalysisTask<GeneratedTask>("generator-histogram")); - if (reco) + } + if (reco) { workflow.push_back(adaptAnalysisTask<ReconstructedTask>("reconstructed-histogram")); + } return workflow; } diff --git a/Analysis/Tasks/PWGLF/raacharged.cxx b/Analysis/Tasks/PWGLF/raacharged.cxx index a1c6d9f6902b7..9f60a86a520bb 100644 --- a/Analysis/Tasks/PWGLF/raacharged.cxx +++ b/Analysis/Tasks/PWGLF/raacharged.cxx @@ -109,26 +109,36 @@ struct raacharged { Int_t WhichParticle(Int_t pdgCode) { //see in AlidNdPtTools - if (pdgCode == 0) + if (pdgCode == 0) { return -1; - if (pdgCode == std::abs(211)) + } + if (pdgCode == std::abs(211)) { return 0; //pi+, pi- - if (pdgCode == std::abs(321)) + } + if (pdgCode == std::abs(321)) { return 1; //K+, K- - if (pdgCode == std::abs(2212)) + } + if (pdgCode == std::abs(2212)) { return 2; //p, pbar - if (pdgCode == 3222 || pdgCode == -3112) + } + if (pdgCode == 3222 || pdgCode == -3112) { return 3; //sigmaPlus, SigmaBarMinus - if (pdgCode == 3112 || pdgCode == -3222) + } + if (pdgCode == 3112 || pdgCode == -3222) { return 4; //sigmaMinus, SigmaBarPlus - if (pdgCode == std::abs(11)) + } + if (pdgCode == std::abs(11)) { return 5; //e-, e+ - if (pdgCode == std::abs(3312)) + } + if (pdgCode == std::abs(3312)) { return 6; //XiP, XiM - if (pdgCode == std::abs(13)) + } + if (pdgCode == std::abs(13)) { return 7; //mu,antimu - if (pdgCode == std::abs(3334)) + } + if (pdgCode == std::abs(3334)) { return 8; //OmegaP, OmegaM + } return 9; //other } @@ -143,30 +153,35 @@ struct raacharged { void process(soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels, aod::Cents>::iterator const& collision, soa::Join<aod::Tracks, aod::McTrackLabels, aod::TrackSelection> const& tracks, aod::McParticles& mcParticles) { - if (!collision.alias()[kINT7]) + if (!collision.alias()[kINT7]) { return; - if (!collision.sel7()) + } + if (!collision.sel7()) { return; + } Double_t eventValues[3] = {0.0, 0.0, collision.posZ()}; fHistEvent->Fill(eventValues); for (auto& track : tracks) { - if (selectedTracks == 1 && !track.isGlobalTrack()) + if (selectedTracks == 1 && !track.isGlobalTrack()) { continue; - else if (selectedTracks == 2 && !track.isGlobalTrackSDD()) + } else if (selectedTracks == 2 && !track.isGlobalTrackSDD()) { continue; + } Double_t trackValues[4] = {0.0, 0.0, track.pt(), (Double_t)track.charge()}; fHistTrack->Fill(trackValues); Double_t mcInfoVal; - if (!isMC) + if (!isMC) { continue; - if (MC::isPhysicalPrimary(mcParticles, track.label())) + } + if (MC::isPhysicalPrimary(mcParticles, track.label())) { mcInfoVal = 0.0; - else + } else { mcInfoVal = 1.0; + } Double_t MCpt = track.label().pt(); Double_t parType = (Double_t)WhichParticle(track.label().pdgCode()); @@ -178,18 +193,21 @@ struct raacharged { if (isMC) { for (auto& mcParticle : mcParticles) { - if (abs(mcParticle.eta()) > 0.8) + if (abs(mcParticle.eta()) > 0.8) { continue; - if (!MC::isPhysicalPrimary(mcParticles, mcParticle)) + } + if (!MC::isPhysicalPrimary(mcParticles, mcParticle)) { continue; + } Double_t MCpt = mcParticle.pt(); Double_t parType = (Double_t)WhichParticle(mcParticle.pdgCode()); Int_t pdg = (Int_t)mcParticle.pdgCode(); Double_t MCcharge = MCCharge(pdg); - if (MCcharge == 0.0) + if (MCcharge == 0.0) { continue; + } Double_t MCvalues[4] = {MCpt, parType, 2.0, MCcharge}; fHistMC->Fill(MCvalues); } diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index e53228945bc18..9fbce2a861d84 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -276,7 +276,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) WorkflowSpec workflow{adaptAnalysisTask<TPCPIDQAExpSignalTask>("TPCpidqa-expsignal-task"), adaptAnalysisTask<TPCPIDQANSigmaTask>("TPCpidqa-nsigma-task"), adaptAnalysisTask<TPCSpectraTask>("tpcspectra-task")}; - if (TPCwTOF) + if (TPCwTOF) { workflow.push_back(adaptAnalysisTask<TPCPIDQASignalwTOFTask>("TPCpidqa-signalwTOF-task")); + } return workflow; } diff --git a/Analysis/Tasks/PWGLF/trackchecks.cxx b/Analysis/Tasks/PWGLF/trackchecks.cxx index e8d994ae15f1a..b8230dec9f549 100644 --- a/Analysis/Tasks/PWGLF/trackchecks.cxx +++ b/Analysis/Tasks/PWGLF/trackchecks.cxx @@ -55,18 +55,19 @@ double eta2y(double pt, double m, double eta) int getparticleint(int pdgcode) { - if (pdgcode == 11) + if (pdgcode == 11) { return kEl; - else if (pdgcode == 211) + } else if (pdgcode == 211) { return kPi; - else if (pdgcode == 321) + } else if (pdgcode == 321) { return kKa; - else if (pdgcode == 2212) + } else if (pdgcode == 2212) { return kPr; - else if (pdgcode == 1000010020) + } else if (pdgcode == 1000010020) { return kDe; - else + } else { return kNull; + } } //No track selection --> only event selection here @@ -107,10 +108,12 @@ struct TrackCheckTaskEvSel { { //event selection - if (!isMC && !col.alias()[kINT7]) // trigger (should be skipped in MC) + if (!isMC && !col.alias()[kINT7]) { // trigger (should be skipped in MC) return; - if (!col.sel7()) //additional cuts + } + if (!col.sel7()) { //additional cuts return; + } //Loop on tracks for (auto& track : tracks) { @@ -126,23 +129,25 @@ struct TrackCheckTaskEvSel { //calculate rapidity int pint = getparticleint(pdgcode); - if (pint == kNull) + if (pint == kNull) { y = (double)kNull; - else + } else { y = eta2y(track.pt(), mass[pint], track.eta()); + } if (isPrimary && abs(y) < cfgCutY) { //histograms with generated distribution (after event selection) - if (pdgcode == 11) + if (pdgcode == 11) { hTrkPrimAftEvSel_truepid->Fill<kEl>(track.pt()); - else if (pdgcode == 211) + } else if (pdgcode == 211) { hTrkPrimAftEvSel_truepid->Fill<kPi>(track.pt()); - else if (pdgcode == 321) + } else if (pdgcode == 321) { hTrkPrimAftEvSel_truepid->Fill<kKa>(track.pt()); - else if (pdgcode == 2212) + } else if (pdgcode == 2212) { hTrkPrimAftEvSel_truepid->Fill<kPr>(track.pt()); - else if (pdgcode == 1000010020) + } else if (pdgcode == 1000010020) { hTrkPrimAftEvSel_truepid->Fill<kDe>(track.pt()); + } hTrkPrimAftEvSel->Fill(track.pt()); //charged particles } @@ -243,10 +248,12 @@ struct TrackCheckTaskEvSelTrackSel { { //event selection - if (!isMC && !col.alias()[kINT7]) // trigger (should be skipped in MC) + if (!isMC && !col.alias()[kINT7]) { // trigger (should be skipped in MC) return; - if (!col.sel7()) //additional cuts + } + if (!col.sel7()) { //additional cuts return; + } //Loop on tracks for (auto& track : tracks) { @@ -261,10 +268,11 @@ struct TrackCheckTaskEvSelTrackSel { } //Calculate y int pint = getparticleint(pdgcode); - if (pint == kNull) + if (pint == kNull) { y = (double)kNull; - else + } else { y = eta2y(track.pt(), mass[pint], track.eta()); + } //DCAxy distributions for reco, primary, secondaries (= not primary) // + distributions for reco primaries (MC truth) @@ -274,36 +282,41 @@ struct TrackCheckTaskEvSelTrackSel { if (isPrimary) { hDCAxyPrim_truepid->Fill<kEl>(track.pt(), track.dcaXY()); hTrkPrimReco_truepid->Fill<kEl>(track.pt()); - } else + } else { hDCAxySeco_truepid->Fill<kEl>(track.pt(), track.dcaXY()); + } } else if (pdgcode == 211) { hDCAxyReco_truepid->Fill<kPi>(track.pt(), track.dcaXY()); if (isPrimary) { hDCAxyPrim_truepid->Fill<kPi>(track.pt(), track.dcaXY()); hTrkPrimReco_truepid->Fill<kPi>(track.pt()); - } else + } else { hDCAxySeco_truepid->Fill<kPi>(track.pt(), track.dcaXY()); + } } else if (pdgcode == 321) { hDCAxyReco_truepid->Fill<kKa>(track.pt(), track.dcaXY()); if (isPrimary) { hDCAxyPrim_truepid->Fill<kKa>(track.pt(), track.dcaXY()); hTrkPrimReco_truepid->Fill<kKa>(track.pt()); - } else + } else { hDCAxySeco_truepid->Fill<kKa>(track.pt(), track.dcaXY()); + } } else if (pdgcode == 2212) { hDCAxyReco_truepid->Fill<kPr>(track.pt(), track.dcaXY()); if (isPrimary) { hDCAxyPrim_truepid->Fill<kPr>(track.pt(), track.dcaXY()); hTrkPrimReco_truepid->Fill<kPr>(track.pt()); - } else + } else { hDCAxySeco_truepid->Fill<kPr>(track.pt(), track.dcaXY()); + } } else if (pdgcode == 1000010020) { hDCAxyReco_truepid->Fill<kDe>(track.pt(), track.dcaXY()); if (isPrimary) { hDCAxyPrim_truepid->Fill<kDe>(track.pt(), track.dcaXY()); hTrkPrimReco_truepid->Fill<kDe>(track.pt()); - } else + } else { hDCAxySeco_truepid->Fill<kDe>(track.pt(), track.dcaXY()); + } } } diff --git a/Analysis/Tasks/PWGUD/upcAnalysis.cxx b/Analysis/Tasks/PWGUD/upcAnalysis.cxx index 57f7583cc9ffd..151d220c485c5 100644 --- a/Analysis/Tasks/PWGUD/upcAnalysis.cxx +++ b/Analysis/Tasks/PWGUD/upcAnalysis.cxx @@ -33,30 +33,38 @@ struct UPCAnalysis { void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection> const& tracks) { bool checkV0 = col.bbV0A() || col.bbV0C() || col.bgV0A() || col.bgV0C(); - if (checkV0) + if (checkV0) { return; + } bool checkFDD = col.bbFDA() || col.bbFDC() || col.bgFDA() || col.bgFDC(); - if (checkFDD) + if (checkFDD) { return; - if (!col.alias()[kCUP9]) + } + if (!col.alias()[kCUP9]) { return; + } std::vector<soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection>::iterator> selTracks; for (auto track : tracks) { - if (!track.isGlobalTrack()) + if (!track.isGlobalTrack()) { continue; + } selTracks.push_back(track); - if (selTracks.size() > 2) + if (selTracks.size() > 2) { break; + } } - if (selTracks.size() != 2) + if (selTracks.size() != 2) { return; - if (selTracks[0].charge() * selTracks[1].charge() >= 0) + } + if (selTracks[0].charge() * selTracks[1].charge() >= 0) { return; + } UChar_t clustermap1 = selTracks[0].itsClusterMap(); UChar_t clustermap2 = selTracks[1].itsClusterMap(); bool checkClusMap = TESTBIT(clustermap1, 0) && TESTBIT(clustermap1, 1) && TESTBIT(clustermap2, 0) && TESTBIT(clustermap2, 1); - if (!checkClusMap) + if (!checkClusMap) { return; + } TLorentzVector p1, p2, p; p1.SetXYZM(selTracks[0].px(), selTracks[0].py(), selTracks[0].pz(), mpion); p2.SetXYZM(selTracks[1].px(), selTracks[1].py(), selTracks[1].pz(), mpion); diff --git a/Analysis/Tasks/centralityQa.cxx b/Analysis/Tasks/centralityQa.cxx index 7d6717f8c67d3..7871c2bea6378 100644 --- a/Analysis/Tasks/centralityQa.cxx +++ b/Analysis/Tasks/centralityQa.cxx @@ -21,10 +21,12 @@ struct CentralityQaTask { OutputObj<TH1F> hCentV0M{TH1F("hCentV0M", "", 21, 0, 105.)}; void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& col) { - if (!col.alias()[kINT7]) + if (!col.alias()[kINT7]) { return; - if (!col.sel7()) + } + if (!col.sel7()) { return; + } LOGF(debug, "centV0M=%.0f", col.centV0M()); // fill centrality histos diff --git a/Analysis/Tasks/eventSelectionQa.cxx b/Analysis/Tasks/eventSelectionQa.cxx index 84810129d813f..3b629d5f95d58 100644 --- a/Analysis/Tasks/eventSelectionQa.cxx +++ b/Analysis/Tasks/eventSelectionQa.cxx @@ -18,45 +18,55 @@ using namespace o2::framework; struct EventSelectionTask { aod::FV0A getVZeroA(aod::BC const& bc, aod::FV0As const& vzeros) { - for (auto& vzero : vzeros) - if (vzero.bc() == bc) + for (auto& vzero : vzeros) { + if (vzero.bc() == bc) { return vzero; + } + } aod::FV0A dummy; return dummy; } aod::FV0C getVZeroC(aod::BC const& bc, aod::FV0Cs const& vzeros) { - for (auto& vzero : vzeros) - if (vzero.bc() == bc) + for (auto& vzero : vzeros) { + if (vzero.bc() == bc) { return vzero; + } + } aod::FV0C dummy; return dummy; } aod::Zdc getZdc(aod::BC const& bc, aod::Zdcs const& zdcs) { - for (auto& zdc : zdcs) - if (zdc.bc() == bc) + for (auto& zdc : zdcs) { + if (zdc.bc() == bc) { return zdc; + } + } aod::Zdc dummy; return dummy; } aod::FT0 getFT0(aod::BC const& bc, aod::FT0s const& ft0s) { - for (auto& ft0 : ft0s) - if (ft0.bc() == bc) + for (auto& ft0 : ft0s) { + if (ft0.bc() == bc) { return ft0; + } + } aod::FT0 dummy; return dummy; } aod::FDD getFDD(aod::BC const& bc, aod::FDDs const& fdds) { - for (auto& fdd : fdds) - if (fdd.bc() == bc) + for (auto& fdd : fdds) { + if (fdd.bc() == bc) { return fdd; + } + } aod::FDD dummy; return dummy; } @@ -82,8 +92,9 @@ struct EventSelectionTask { void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FT0s ft0s, aod::FDDs fdds) { - if (!isMC && !col.alias()[kINT7]) + if (!isMC && !col.alias()[kINT7]) { return; + } auto fv0a = getVZeroA(col.bc(), fv0as); auto fv0c = getVZeroC(col.bc(), fv0cs); @@ -102,8 +113,9 @@ struct EventSelectionTask { hTimeFDAall->Fill(fdd.timeA()); hTimeFDCall->Fill(fdd.timeC()); - if (!col.sel7()) + if (!col.sel7()) { return; + } hTimeV0Aacc->Fill(fv0a.time()); hTimeV0Cacc->Fill(fv0c.time()); diff --git a/Analysis/Tasks/multiplicityQa.cxx b/Analysis/Tasks/multiplicityQa.cxx index a4ab0cc1bd7fc..c3332b31d505e 100644 --- a/Analysis/Tasks/multiplicityQa.cxx +++ b/Analysis/Tasks/multiplicityQa.cxx @@ -29,10 +29,12 @@ struct MultiplicityQaTask { void process(soa::Join<aod::Collisions, aod::EvSels, aod::Mults>::iterator const& col) { - if (!col.alias()[kINT7]) + if (!col.alias()[kINT7]) { return; - if (!col.sel7()) + } + if (!col.sel7()) { return; + } LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multV0M=%5.0f multT0A=%5.0f multT0C=%5.0f multT0M=%5.0f", col.multV0A(), col.multV0C(), col.multV0M(), col.multT0A(), col.multT0C(), col.multT0M()); // fill calibration histos diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx index 40c9952f19104..e2043c13ecc78 100644 --- a/Analysis/Tasks/qaTask.cxx +++ b/Analysis/Tasks/qaTask.cxx @@ -59,10 +59,12 @@ struct QATrackingResolution { etaDiff->Fill(track.label().eta() - track.eta()); auto delta = track.label().phi() - track.phi(); - if (delta > M_PI) + if (delta > M_PI) { delta -= 2 * M_PI; - if (delta < -M_PI) + } + if (delta < -M_PI) { delta += 2 * M_PI; + } phiDiff->Fill(delta); } } diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index a5241b677070b..5c0aebe319452 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -113,8 +113,9 @@ struct TrackQATask { trackpar.fill("snp", track.snp()); trackpar.fill("tgl", track.tgl()); for (unsigned int i = 0; i < 64; i++) { - if (track.flags() & (1 << i)) + if (track.flags() & (1 << i)) { trackpar.fill("flags", i); + } } trackpar.fill("dcaXY", track.dcaXY()); trackpar.fill("dcaZ", track.dcaZ()); @@ -123,8 +124,9 @@ struct TrackQATask { its.fill("itsNCls", track.itsNCls()); its.fill("itsChi2NCl", track.itsChi2NCl()); for (unsigned int i = 0; i < 7; i++) { - if (track.itsClusterMap() & (1 << i)) + if (track.itsClusterMap() & (1 << i)) { its.fill("itsHits", i); + } } // fill TPC variables diff --git a/Analysis/Tutorials/src/histogramTrackSelection.cxx b/Analysis/Tutorials/src/histogramTrackSelection.cxx index cf1b13e1bf857..ff9430ac962b0 100644 --- a/Analysis/Tutorials/src/histogramTrackSelection.cxx +++ b/Analysis/Tutorials/src/histogramTrackSelection.cxx @@ -38,10 +38,11 @@ struct HistogramTrackSelection { { for (auto& track : tracks) { - if (selectedTracks == 1 && !track.isGlobalTrack()) + if (selectedTracks == 1 && !track.isGlobalTrack()) { continue; - else if (selectedTracks == 2 && !track.isGlobalTrackSDD()) + } else if (selectedTracks == 2 && !track.isGlobalTrackSDD()) { continue; + } pt->Fill(track.pt()); } diff --git a/Analysis/Tutorials/src/mcHistograms.cxx b/Analysis/Tutorials/src/mcHistograms.cxx index b9901d5a86d27..0f5521a9739ae 100644 --- a/Analysis/Tutorials/src/mcHistograms.cxx +++ b/Analysis/Tutorials/src/mcHistograms.cxx @@ -64,10 +64,12 @@ struct CTask { // continue; etaDiff->Fill(track.label().eta() - track.eta()); auto delta = track.label().phi() - track.phi(); - if (delta > M_PI) + if (delta > M_PI) { delta -= 2 * M_PI; - if (delta < -M_PI) + } + if (delta < -M_PI) { delta += 2 * M_PI; + } phiDiff->Fill(delta); //LOGF(info, "eta: %.2f %.2f \t phi: %.2f %.2f | %d", track.label().eta(), track.eta(), track.label().phi(), track.phi(), track.label().index()); } From 9e5adb375bb4b74e1b13d1949b11bfbee3b2805e Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Wed, 21 Oct 2020 13:01:40 +0300 Subject: [PATCH 1025/1751] DataFormats: make readability-braces-around-statements happy --- .../CPV/include/DataFormatsCPV/Digit.h | 6 ++- .../DetMatrixCache.h | 3 +- .../Detectors/Common/src/AlignParam.cxx | 5 +- .../DataFormatsEMCAL/AnalysisCluster.h | 10 ++-- .../Detectors/EMCAL/src/AnalysisCluster.cxx | 5 +- DataFormats/Detectors/EMCAL/src/Cell.cxx | 34 ++++++++------ DataFormats/Detectors/EMCAL/src/Digit.cxx | 17 ++++--- .../Detectors/EMCAL/src/EventHandler.cxx | 46 ++++++++++++------- .../FT0/include/DataFormatsFT0/LookUpTable.h | 9 ++-- .../FT0/include/DataFormatsFT0/RawEventData.h | 3 +- .../Detectors/FIT/FT0/src/DigitsTemp.cxx | 3 +- .../Detectors/ITSMFT/ITS/src/TrackITS.cxx | 7 +-- .../include/DataFormatsITSMFT/Cluster.h | 9 ++-- .../DataFormatsITSMFT/ClusterPattern.h | 3 +- .../include/DataFormatsITSMFT/NoiseMap.h | 12 +++-- .../ITSMFT/common/src/ClusterPattern.cxx | 6 ++- .../ITSMFT/common/src/ClusterTopology.cxx | 3 +- .../ITSMFT/common/src/TopologyDictionary.cxx | 9 ++-- .../Detectors/MUON/MID/src/ColumnData.cxx | 5 +- .../PHOS/include/DataFormatsPHOS/Digit.h | 6 ++- DataFormats/Detectors/PHOS/src/Cell.cxx | 24 ++++++---- .../DataFormatsTOF/CalibTimeSlewingParamTOF.h | 3 +- .../Detectors/TOF/src/CalibLHCphaseTOF.cxx | 6 ++- .../TOF/src/CalibTimeSlewingParamTOF.cxx | 18 +++++--- DataFormats/Detectors/TOF/src/Cluster.cxx | 24 ++++++---- DataFormats/Detectors/TRD/src/RawData.cxx | 9 ++-- DataFormats/Detectors/ZDC/src/BCData.cxx | 10 ++-- .../Headers/include/Headers/DataHeader.h | 11 +++-- DataFormats/Headers/include/Headers/Stack.h | 6 ++- DataFormats/Headers/src/DataHeader.cxx | 17 ++++--- .../ReconstructionDataFormats/TrackFwd.h | 3 +- .../TrackParametrizationWithError.h | 3 +- .../include/SimulationDataFormat/MCTrack.h | 8 ++-- .../include/SimulationDataFormat/Stack.h | 3 +- DataFormats/simulation/src/Stack.cxx | 36 ++++++++++----- 35 files changed, 245 insertions(+), 137 deletions(-) diff --git a/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h b/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h index 7b059e65f1094..15eaf170e521b 100644 --- a/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h +++ b/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h @@ -57,8 +57,9 @@ class Digit : public DigitBase { if (fabs(getTimeStamp() - other.getTimeStamp()) < kTimeGate) { return getAbsId() < other.getAbsId(); - } else + } else { return getTimeStamp() < other.getTimeStamp(); + } } /// \brief Comparison oparator, based on time and absId @@ -68,8 +69,9 @@ class Digit : public DigitBase { if (fabs(getTimeStamp() - other.getTimeStamp()) <= kTimeGate) { return getAbsId() > other.getAbsId(); - } else + } else { return getTimeStamp() > other.getTimeStamp(); + } } /// \brief Comparison oparator, based on time and absId diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h index 55246681554e2..c2d0b033ead2b 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h @@ -41,8 +41,9 @@ class MatrixCache /// set the size of the cache void setSize(int s) { - if (!mCache.size()) + if (!mCache.size()) { mCache.resize(s); + } } /// get the size of the cache diff --git a/DataFormats/Detectors/Common/src/AlignParam.cxx b/DataFormats/Detectors/Common/src/AlignParam.cxx index 4ee234e09dcb6..6b351549a812e 100644 --- a/DataFormats/Detectors/Common/src/AlignParam.cxx +++ b/DataFormats/Detectors/Common/src/AlignParam.cxx @@ -318,10 +318,11 @@ int AlignParam::Compare(const TObject* obj) const int level = getLevel(); int level2 = ((AlignParam*)obj)->getLevel(); - if (level == level2) + if (level == level2) { return 0; - else + } else { return ((level > level2) ? 1 : -1); + } } //_____________________________________________________________________________ diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h index 376938a02cb61..365198b608d61 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h @@ -146,18 +146,20 @@ class AnalysisCluster int getCellIndex(int i) const { - if (i >= 0 && i < mNCells) + if (i >= 0 && i < mNCells) { return mCellsIndices[i]; - else + } else { throw CellOutOfRangeException(i); + } } float getCellAmplitudeFraction(int i) const { - if (i >= 0 && i < mNCells) + if (i >= 0 && i < mNCells) { return mCellsAmpFraction[i]; - else + } else { throw CellOutOfRangeException(i); + } } bool getIsExotic() const { return mIsExotic; } diff --git a/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx b/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx index f905e8495ffdd..6119ab75b0971 100644 --- a/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx +++ b/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx @@ -40,10 +40,11 @@ TLorentzVector AnalysisCluster::getMomentum(std::array<const float, 3> vertex) c float r = TMath::Sqrt(pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]); - if (r > 0) + if (r > 0) { p.SetPxPyPzE(mEnergy * pos[0] / r, mEnergy * pos[1] / r, mEnergy * pos[2] / r, mEnergy); - else + } else { LOG(INFO) << "Null cluster radius, momentum calculation not possible"; + } return p; } diff --git a/DataFormats/Detectors/EMCAL/src/Cell.cxx b/DataFormats/Detectors/EMCAL/src/Cell.cxx index 069c23e0e70d0..044b970b638e8 100644 --- a/DataFormats/Detectors/EMCAL/src/Cell.cxx +++ b/DataFormats/Detectors/EMCAL/src/Cell.cxx @@ -25,8 +25,9 @@ Cell::Cell(Short_t tower, Double_t energy, Double_t time, ChannelType_t ctype) void Cell::setTower(Short_t tower) { - if (tower > 0x7fff || tower < 0) + if (tower > 0x7fff || tower < 0) { tower = 0x7fff; + } ULong_t t = (ULong_t)tower; ULong_t b = getLong() & 0xffffff8000; // 1111111111111111111111111000000000000000 @@ -43,12 +44,13 @@ Short_t Cell::getTower() const void Cell::setTimeStamp(Double_t time) { ULong_t t = 0; - if (time > 0x1ff) + if (time > 0x1ff) { t = 0x1ff; - else if (time < 0) + } else if (time < 0) { t = 0; - else + } else { t = (ULong_t)time; + } t <<= 15; ULong_t b = getLong() & 0xffff007fff; // 1111111111111111000000000111111111111111 @@ -65,10 +67,11 @@ Short_t Cell::getTimeStamp() const void Cell::setEnergyBits(Short_t ebits) { - if (ebits > 0x3fff) + if (ebits > 0x3fff) { ebits = 0x3fff; - else if (ebits < 0) + } else if (ebits < 0) { ebits = 0; + } ULong_t a = (ULong_t)ebits; a <<= 24; @@ -119,12 +122,13 @@ void Cell::setType(ChannelType_t ctype) ChannelType_t Cell::getType() const { - if (getHighGain()) + if (getHighGain()) { return ChannelType_t::HIGH_GAIN; - else if (getLEDMon()) + } else if (getLEDMon()) { return ChannelType_t::LEDMON; - else if (getTRU()) + } else if (getTRU()) { return ChannelType_t::TRU; + } return ChannelType_t::LOW_GAIN; } @@ -137,8 +141,9 @@ void Cell::setLowGain() Bool_t Cell::getLowGain() const { ULong_t t = (getLong() >> 38); - if (t) + if (t) { return false; + } return true; } @@ -151,8 +156,9 @@ void Cell::setHighGain() Bool_t Cell::getHighGain() const { ULong_t t = (getLong() >> 38); - if (t == 1) + if (t == 1) { return true; + } return false; } @@ -165,8 +171,9 @@ void Cell::setLEDMon() Bool_t Cell::getLEDMon() const { ULong_t t = (getLong() >> 38); - if (t == 2) + if (t == 2) { return true; + } return false; } @@ -179,8 +186,9 @@ void Cell::setTRU() Bool_t Cell::getTRU() const { ULong_t t = (getLong() >> 38); - if (t == 3) + if (t == 3) { return true; + } return false; } diff --git a/DataFormats/Detectors/EMCAL/src/Digit.cxx b/DataFormats/Detectors/EMCAL/src/Digit.cxx index 7036d03cd6da7..e25d5082b1d8f 100644 --- a/DataFormats/Detectors/EMCAL/src/Digit.cxx +++ b/DataFormats/Detectors/EMCAL/src/Digit.cxx @@ -25,14 +25,15 @@ Digit& Digit::operator+=(const Digit& other) Int_t a = getAmplitudeADC() + other.getAmplitudeADC(); Short_t s = (Short_t)(a); - if (a < -0x8000) + if (a < -0x8000) { setAmplitudeADC(-0x8000); - else if (a <= constants::EMCAL_HGLGTRANSITION) + } else if (a <= constants::EMCAL_HGLGTRANSITION) { setAmplitudeADC(s); - else if (a <= 0x7fff * constants::EMCAL_HGLGFACTOR) + } else if (a <= 0x7fff * constants::EMCAL_HGLGFACTOR) { setAmplitudeADC(s / constants::EMCAL_HGLGFACTOR, ChannelType_t::LOW_GAIN); - else + } else { setAmplitudeADC(0x7fff, ChannelType_t::LOW_GAIN); + } } // Does nothing if the digits are in different towers or have incompatible times. return *this; @@ -66,15 +67,17 @@ Int_t Digit::getAmplitudeADC(ChannelType_t ctype) const { if (ctype == ChannelType_t::LOW_GAIN) { // return in units of Low-Gain ADC counts - if (mChannelType == ChannelType_t::LOW_GAIN) + if (mChannelType == ChannelType_t::LOW_GAIN) { return (Int_t)(mAmplitude); - else + } else { return mAmplitude / constants::EMCAL_HGLGFACTOR; + } } // return in units of High-Gain ADC counts (default) - if (mChannelType == ChannelType_t::LOW_GAIN) + if (mChannelType == ChannelType_t::LOW_GAIN) { return mAmplitude * constants::EMCAL_HGLGFACTOR; + } return (Int_t)(mAmplitude); } diff --git a/DataFormats/Detectors/EMCAL/src/EventHandler.cxx b/DataFormats/Detectors/EMCAL/src/EventHandler.cxx index 69c9a7ff53f6f..ab3f809f5ff73 100644 --- a/DataFormats/Detectors/EMCAL/src/EventHandler.cxx +++ b/DataFormats/Detectors/EMCAL/src/EventHandler.cxx @@ -41,12 +41,13 @@ int EventHandler<CellInputType>::getNumberOfEvents() const { int neventsClusters = mTriggerRecordsClusters.size(), neventsCells = mTriggerRecordsCells.size(); - if (neventsClusters) + if (neventsClusters) { return neventsClusters; - else if (neventsCells) + } else if (neventsCells) { return neventsCells; - else + } else { return 0; + } } template <class CellInputType> @@ -54,20 +55,23 @@ const o2::InteractionRecord& EventHandler<CellInputType>::getInteractionRecordFo { const InteractionRecord *irClusters(nullptr), *irCells(nullptr); if (mTriggerRecordsClusters.size()) { - if (eventID >= mTriggerRecordsClusters.size()) + if (eventID >= mTriggerRecordsClusters.size()) { throw RangeException(eventID, mTriggerRecordsClusters.size()); + } irClusters = &(mTriggerRecordsClusters[eventID].getBCData()); } if (mTriggerRecordsCells.size()) { - if (eventID >= mTriggerRecordsCells.size()) + if (eventID >= mTriggerRecordsCells.size()) { throw RangeException(eventID, mTriggerRecordsCells.size()); + } irCells = &(mTriggerRecordsCellIndices[eventID].getBCData()); } if (irClusters && irCells) { - if (compareInteractionRecords(*irClusters, *irCells)) + if (compareInteractionRecords(*irClusters, *irCells)) { return *irClusters; - else + } else { throw InteractionRecordInvalidException(*irClusters, *irCells); + } } else if (irClusters) { return *irClusters; } else if (irCells) { @@ -80,8 +84,9 @@ template <class CellInputType> const typename EventHandler<CellInputType>::ClusterRange EventHandler<CellInputType>::getClustersForEvent(int eventID) const { if (mTriggerRecordsClusters.size()) { - if (eventID >= mTriggerRecordsClusters.size()) + if (eventID >= mTriggerRecordsClusters.size()) { throw RangeException(eventID, mTriggerRecordsClusters.size()); + } auto& trgrecord = mTriggerRecordsClusters[eventID]; return ClusterRange(mClusters.data() + trgrecord.getFirstEntry(), trgrecord.getNumberOfObjects()); } @@ -92,8 +97,9 @@ template <class CellInputType> const typename EventHandler<CellInputType>::CellRange EventHandler<CellInputType>::getCellsForEvent(int eventID) const { if (mTriggerRecordsCells.size()) { - if (eventID >= mTriggerRecordsCells.size()) + if (eventID >= mTriggerRecordsCells.size()) { throw RangeException(eventID, mTriggerRecordsCells.size()); + } auto& trgrecord = mTriggerRecordsCells[eventID]; return CellRange(mCells.data() + trgrecord.getFirstEntry(), trgrecord.getNumberOfObjects()); } @@ -104,8 +110,9 @@ template <class CellInputType> const typename EventHandler<CellInputType>::CellIndexRange EventHandler<CellInputType>::getClusterCellIndicesForEvent(int eventID) const { if (mTriggerRecordsCellIndices.size()) { - if (eventID >= mTriggerRecordsCellIndices.size()) + if (eventID >= mTriggerRecordsCellIndices.size()) { throw RangeException(eventID, mTriggerRecordsCellIndices.size()); + } auto& trgrecord = mTriggerRecordsCellIndices[eventID]; return CellIndexRange(mClusterCellIndices.data() + trgrecord.getFirstEntry(), trgrecord.getNumberOfObjects()); } @@ -128,12 +135,15 @@ EventData<CellInputType> EventHandler<CellInputType>::buildEvent(int eventID) co { EventData<CellInputType> outputEvent; outputEvent.mInteractionRecord = getInteractionRecordForEvent(eventID); - if (hasClusters()) + if (hasClusters()) { outputEvent.mClusters = getClustersForEvent(eventID); - if (hasClusterIndices()) + } + if (hasClusterIndices()) { outputEvent.mCellIndices = getClusterCellIndicesForEvent(eventID); - if (hasCells()) + } + if (hasCells()) { outputEvent.mCells = getCellsForEvent(eventID); + } return outputEvent; } @@ -162,10 +172,11 @@ bool EventHandler<CellInputType>::EventIterator::operator==(const EventHandler<C template <class CellInputType> typename EventHandler<CellInputType>::EventIterator& EventHandler<CellInputType>::EventIterator::operator++() { - if (mForward) + if (mForward) { mEventID++; - else + } else { mEventID--; + } mCurrentEvent = mEventHandler.buildEvent(mEventID); return *this; } @@ -181,10 +192,11 @@ typename EventHandler<CellInputType>::EventIterator EventHandler<CellInputType>: template <class CellInputType> typename EventHandler<CellInputType>::EventIterator& EventHandler<CellInputType>::EventIterator::operator--() { - if (mForward) + if (mForward) { mEventID--; - else + } else { mEventID++; + } mCurrentEvent = mEventHandler.buildEvent(mEventID); return *this; } diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h index ae3a516a83c2a..1453d934bd797 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h @@ -53,20 +53,23 @@ class LookUpTable explicit LookUpTable(std::vector<Topo> const& topoVector) : mTopoVector(topoVector), mInvTopo(topoVector.size()) { - for (size_t channel = 0; channel < mTopoVector.size(); ++channel) + for (size_t channel = 0; channel < mTopoVector.size(); ++channel) { mInvTopo.at(getIdx(mTopoVector[channel].mPM, mTopoVector[channel].mMCP)) = channel; + } } ~LookUpTable() = default; void printFullMap() const { - for (size_t channel = 0; channel < mTopoVector.size(); ++channel) + for (size_t channel = 0; channel < mTopoVector.size(); ++channel) { std::cout << channel << "\t : PM \t" << mTopoVector[channel].mPM << " MCP \t" << mTopoVector[channel].mMCP << std::endl; - for (size_t idx = 0; idx < mInvTopo.size(); ++idx) + } + for (size_t idx = 0; idx < mInvTopo.size(); ++idx) { std::cout << "PM \t" << getLinkFromIdx(mInvTopo[idx]) << " MCP \t" << getMCPFromIdx(mInvTopo[idx]) << std::endl; + } } int getChannel(int link, int mcp) const diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h index cdf49bad76003..e96e10ee07c9d 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h @@ -324,8 +324,9 @@ class DataPageWriter void writePage() { - if (mBuffer.size() == 0) + if (mBuffer.size() == 0) { return; + } mPages.emplace_back(std::move(mBuffer)); LOG(DEBUG) << " writePage " << mBuffer.size(); mNpackets.push_back(mNpacketsInBuffer); diff --git a/DataFormats/Detectors/FIT/FT0/src/DigitsTemp.cxx b/DataFormats/Detectors/FIT/FT0/src/DigitsTemp.cxx index 202b429ec31cb..10baf8fe41dc1 100644 --- a/DataFormats/Detectors/FIT/FT0/src/DigitsTemp.cxx +++ b/DataFormats/Detectors/FIT/FT0/src/DigitsTemp.cxx @@ -17,9 +17,10 @@ void DigitsTemp::printStream(std::ostream& stream) const stream << "FT0 Digit: event time " << mTime << " BC " << mIntRecord.bc << " orbit " << mIntRecord.orbit << std::endl; stream << " A amp " << mTrigger.amplA << " C amp " << mTrigger.amplC << " time A " << mTrigger.timeA << " time C " << mTrigger.timeC << " signals " << int(mTrigger.triggersignals) << std::endl; - for (auto& chdata : mChDgDataArr) + for (auto& chdata : mChDgDataArr) { stream << "CH " << int(chdata.ChId) << " TIME " << chdata.CFDTime << " ns " << chdata.QTCAmpl << " mV " << " ADC chain " << int(chdata.ChainQTC) << std::endl; + } } std::ostream& operator<<(std::ostream& stream, const DigitsTemp& digi) diff --git a/DataFormats/Detectors/ITSMFT/ITS/src/TrackITS.cxx b/DataFormats/Detectors/ITSMFT/ITS/src/TrackITS.cxx index 9deda82f98906..9ab6eba05f784 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/src/TrackITS.cxx +++ b/DataFormats/Detectors/ITSMFT/ITS/src/TrackITS.cxx @@ -70,10 +70,11 @@ void TrackITS::getImpactParams(Float_t x, Float_t y, Float_t z, Float_t bz, Floa Bool_t TrackITS::propagate(Float_t alpha, Float_t x, Float_t bz) { - if (rotate(alpha)) - if (propagateTo(x, bz)) + if (rotate(alpha)) { + if (propagateTo(x, bz)) { return kTRUE; - + } + } return kFALSE; } diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h index 407ab4b3d8fd0..4c77b8095f5c8 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h @@ -165,8 +165,9 @@ inline void Cluster::decreaseClusterUsage() { // decrease cluster usage counter int n = getClusterUsage(); - if (n) + if (n) { setClusterUsage(--n); + } // } @@ -176,10 +177,12 @@ inline void Cluster::setClusterUsage(Int_t n) // set cluster usage counter mNxNzN &= ~(kMaskClUse << kOffsClUse); mNxNzN |= (n & kMaskClUse) << kOffsClUse; - if (n < 2) + if (n < 2) { resetBit(kShared); - if (!n) + } + if (!n) { resetBit(kUsed); + } } } // namespace itsmft diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h index 585efe56deaad..ea03d1496711d 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h @@ -57,8 +57,9 @@ class ClusterPattern mBitmap[1] = *pattIt++; int nbits = mBitmap[0] * mBitmap[1]; int nBytes = nbits / 8; - if (((nbits) % 8) != 0) + if (((nbits) % 8) != 0) { nBytes++; + } memcpy(&mBitmap[2], &(*pattIt), nBytes); pattIt += nBytes; } diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h index af685a0bf3423..6c0bbf77d40af 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h @@ -48,19 +48,22 @@ class NoiseMap /// Get the noise level for this pixels float getNoiseLevel(int chip, int row, int col) const { - if (chip > mNoisyPixels.size()) + if (chip > mNoisyPixels.size()) { return 0; + } auto key = row * 1024 + col; const auto keyIt = mNoisyPixels[chip].find(key); - if (keyIt != mNoisyPixels[chip].end()) + if (keyIt != mNoisyPixels[chip].end()) { return keyIt->second; + } return 0; } void increaseNoiseCount(int chip, int row, int col) { - if (chip > mNoisyPixels.size()) + if (chip > mNoisyPixels.size()) { return; + } auto key = row * 1024 + col; mNoisyPixels[chip][key]++; } @@ -72,8 +75,9 @@ class NoiseMap while (chipID--) { const auto& map = mNoisyPixels[chipID]; for (const auto& pair : map) { - if (pair.second <= t) + if (pair.second <= t) { continue; + } n++; auto key = pair.first; auto row = key / 1024; diff --git a/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx b/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx index f8d1e58cfc5e9..b7a531f8d2665 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx @@ -43,8 +43,9 @@ int ClusterPattern::getUsedBytes() const { int nBits = (int)mBitmap[0] * (int)mBitmap[1]; int nBytes = nBits / 8; - if (nBits % 8 != 0) + if (nBits % 8 != 0) { nBytes++; + } return nBytes; } @@ -53,8 +54,9 @@ void ClusterPattern::setPattern(int nRow, int nCol, const unsigned char patt[Max mBitmap[0] = (unsigned char)nRow; mBitmap[1] = (unsigned char)nCol; int nBytes = nRow * nCol / 8; - if (((nRow * nCol) % 8) != 0) + if (((nRow * nCol) % 8) != 0) { nBytes++; + } memcpy(&mBitmap[2], patt, nBytes); } diff --git a/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx b/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx index 3819612aa7df8..8e7ece08643a5 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx @@ -97,8 +97,9 @@ unsigned long ClusterTopology::getCompleteHash(int nRow, int nCol, extended_pattern[1] = (unsigned char)nCol; int nBits = nRow * nCol; int nBytes = nBits / 8; - if (nBits % 8 != 0) + if (nBits % 8 != 0) { nBytes++; + } memcpy(&extended_pattern[2], patt, nBytes); unsigned long partialHash = (unsigned long)hashFunction(extended_pattern, nBytes); diff --git a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx index 45b33b3e32825..26439c2472ccf 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx @@ -74,8 +74,9 @@ int TopologyDictionary::readBinaryFile(string fname) { mVectorOfIDs.clear(); mCommonMap.clear(); - for (auto& p : mSmallTopologiesLUT) + for (auto& p : mSmallTopologiesLUT) { p = -1; + } std::ifstream in(fname.data(), std::ios::in | std::ios::binary); GroupStruct gr; int groupID = 0; @@ -97,8 +98,9 @@ int TopologyDictionary::readBinaryFile(string fname) mVectorOfIDs.push_back(gr); if (!gr.mIsGroup) { mCommonMap.insert(std::make_pair(gr.mHash, groupID)); - if (gr.mPattern.getUsedBytes() == 1) + if (gr.mPattern.getUsedBytes() == 1) { mSmallTopologiesLUT[(gr.mPattern.getColumnSpan() - 1) * 255 + (int)gr.mPattern.mBitmap[2]] = groupID; + } } else { mGroupMap.insert(std::make_pair((int)(gr.mHash >> 32) & 0x00000000ffffffff, groupID)); } @@ -112,8 +114,9 @@ int TopologyDictionary::readBinaryFile(string fname) void TopologyDictionary::getTopologyDistribution(const TopologyDictionary& dict, TH1F*& histo, const char* histName) { int dictSize = (int)dict.getSize(); - if (histo) + if (histo) { delete histo; + } histo = new TH1F(histName, ";Topology ID;Frequency", dictSize, -0.5, dictSize - 0.5); histo->SetFillColor(kRed); histo->SetFillStyle(3005); diff --git a/DataFormats/Detectors/MUON/MID/src/ColumnData.cxx b/DataFormats/Detectors/MUON/MID/src/ColumnData.cxx index 479ba823153e5..d0240c259b1d7 100644 --- a/DataFormats/Detectors/MUON/MID/src/ColumnData.cxx +++ b/DataFormats/Detectors/MUON/MID/src/ColumnData.cxx @@ -25,10 +25,11 @@ namespace mid void ColumnData::setPattern(uint16_t pattern, int cathode, int line) { /// Sets the pattern - if (cathode == 0) + if (cathode == 0) { setBendPattern(pattern, line); - else + } else { setNonBendPattern(pattern); + } } uint16_t ColumnData::getPattern(int cathode, int line) const diff --git a/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Digit.h b/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Digit.h index f534c496fc339..3eb61d9e5b837 100644 --- a/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Digit.h +++ b/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Digit.h @@ -57,8 +57,9 @@ class Digit : public DigitBase { if (fabs(getTimeStamp() - other.getTimeStamp()) < kTimeGate) { return getAbsId() < other.getAbsId(); - } else + } else { return getTimeStamp() < other.getTimeStamp(); + } } /// \brief Comparison oparator, based on time and absId @@ -68,8 +69,9 @@ class Digit : public DigitBase { if (fabs(getTimeStamp() - other.getTimeStamp()) <= kTimeGate) { return getAbsId() > other.getAbsId(); - } else + } else { return getTimeStamp() > other.getTimeStamp(); + } } /// \brief Comparison oparator, based on time and absId diff --git a/DataFormats/Detectors/PHOS/src/Cell.cxx b/DataFormats/Detectors/PHOS/src/Cell.cxx index d7cdd2fe43eef..cebcb4f001a62 100644 --- a/DataFormats/Detectors/PHOS/src/Cell.cxx +++ b/DataFormats/Detectors/PHOS/src/Cell.cxx @@ -35,8 +35,9 @@ Cell::Cell(short absId, float energy, float time, ChannelType_t ctype) void Cell::setAbsId(short absId) { //14 bits available - if (absId > kNmaxCell || absId < 0) + if (absId > kNmaxCell || absId < 0) { absId = kNmaxCell; + } ULong_t t = (ULong_t)absId; ULong_t b = getLong() & 0xffffffc000; // 1111 1111 1111 1111 1111 1111 1100 0000 0000 0000 @@ -58,20 +59,22 @@ short Cell::getAbsId() const { ULong_t t = getLong() & 0x3fff; //14 bits short a = (short)t; - if (a <= kNmaxCell) + if (a <= kNmaxCell) { return a; - else + } else { return 0; + } } short Cell::getTRUId() const { ULong_t t = getLong() & 0x3fff; //14 bits short a = (short)t; - if (a > kNmaxCell) + if (a > kNmaxCell) { return a - kNmaxCell - 1; - else + } else { return 0; + } } void Cell::setTime(float time) @@ -137,10 +140,11 @@ void Cell::setType(ChannelType_t ctype) ChannelType_t Cell::getType() const { - if (getHighGain()) + if (getHighGain()) { return ChannelType_t::HIGH_GAIN; - else if (getTRU()) + } else if (getTRU()) { return ChannelType_t::TRU; + } return ChannelType_t::LOW_GAIN; } @@ -153,8 +157,9 @@ void Cell::setLowGain() Bool_t Cell::getLowGain() const { ULong_t t = (getLong() >> 39); - if (t) + if (t) { return false; + } return true; } @@ -167,8 +172,9 @@ void Cell::setHighGain() Bool_t Cell::getHighGain() const { ULong_t t = (getLong() >> 39); - if (t == 1) + if (t == 1) { return true; + } return false; } diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h index 04112a1eaaaad..89d0da80cd279 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h @@ -48,8 +48,9 @@ class CalibTimeSlewingParamTOF int size() const { int n = 0; - for (int i = 0; i < NSECTORS; i++) + for (int i = 0; i < NSECTORS; i++) { n += (mTimeSlewing[i]).size(); + } return n; } diff --git a/DataFormats/Detectors/TOF/src/CalibLHCphaseTOF.cxx b/DataFormats/Detectors/TOF/src/CalibLHCphaseTOF.cxx index 06f023683991b..8cab385255223 100644 --- a/DataFormats/Detectors/TOF/src/CalibLHCphaseTOF.cxx +++ b/DataFormats/Detectors/TOF/src/CalibLHCphaseTOF.cxx @@ -22,8 +22,9 @@ using namespace o2::dataformats; float CalibLHCphaseTOF::getLHCphase(int timestamp) const { int n = 0; - while (n < mLHCphase.size() && mLHCphase[n].first <= timestamp) + while (n < mLHCphase.size() && mLHCphase[n].first <= timestamp) { n++; + } n--; if (n < 0) { // timestamp is before of the first available value @@ -51,8 +52,9 @@ CalibLHCphaseTOF& CalibLHCphaseTOF::operator+=(const CalibLHCphaseTOF& other) { if (other.mLHCphase.size() > mLHCphase.size()) { mLHCphase.clear(); - for (auto obj = other.mLHCphase.begin(); obj != other.mLHCphase.end(); obj++) + for (auto obj = other.mLHCphase.begin(); obj != other.mLHCphase.end(); obj++) { mLHCphase.push_back(*obj); + } } return *this; } diff --git a/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx b/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx index e53a8b5f32ec9..2e7980dd0d9f8 100644 --- a/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx +++ b/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx @@ -45,19 +45,23 @@ float CalibTimeSlewingParamTOF::evalTimeSlewing(int channel, float totIn) const int sector = channel / NCHANNELXSECTOR; channel = channel % NCHANNELXSECTOR; - if (sector >= NSECTORS) + if (sector >= NSECTORS) { return 0.; // something went wrong! + } int n = mChannelStart[sector][channel]; - if (n < 0) + if (n < 0) { return 0.; + } int nstop = (mTimeSlewing[sector]).size(); - if (channel < NCHANNELXSECTOR - 1) + if (channel < NCHANNELXSECTOR - 1) { nstop = mChannelStart[sector][channel + 1]; + } - if (n >= nstop) + if (n >= nstop) { return 0.; // something went wrong! + } if (totIn == 0) { return (float)((mTimeSlewing[sector])[n].second); @@ -75,8 +79,9 @@ float CalibTimeSlewingParamTOF::evalTimeSlewing(int channel, float totIn) const return 0; } - if (n == nstop - 1) + if (n == nstop - 1) { return (float)((mTimeSlewing[sector])[n].second); // use the last value stored for that channel + } float w1 = (float)(tot - (mTimeSlewing[sector])[n].first); float w2 = (float)((mTimeSlewing[sector])[n + 1].first - tot); @@ -100,8 +105,9 @@ void CalibTimeSlewingParamTOF::addTimeSlewingInfo(int channel, float tot, float // printf("DBG: addTimeSlewinginfo sec=%i\n",sector); - if (sector >= NSECTORS) + if (sector >= NSECTORS) { return; // something went wrong! + } int currentch = channel; while (mChannelStart[sector][currentch] == -1 && currentch > -1) { diff --git a/DataFormats/Detectors/TOF/src/Cluster.cxx b/DataFormats/Detectors/TOF/src/Cluster.cxx index c00ede9fcc947..f2a0b0ea67f13 100644 --- a/DataFormats/Detectors/TOF/src/Cluster.cxx +++ b/DataFormats/Detectors/TOF/src/Cluster.cxx @@ -37,22 +37,30 @@ int Cluster::getNumOfContributingChannels() const // int nContributingChannels = 1; - if (isAdditionalChannelSet(kUpLeft)) + if (isAdditionalChannelSet(kUpLeft)) { nContributingChannels++; - if (isAdditionalChannelSet(kUp)) + } + if (isAdditionalChannelSet(kUp)) { nContributingChannels++; - if (isAdditionalChannelSet(kUpRight)) + } + if (isAdditionalChannelSet(kUpRight)) { nContributingChannels++; - if (isAdditionalChannelSet(kRight)) + } + if (isAdditionalChannelSet(kRight)) { nContributingChannels++; - if (isAdditionalChannelSet(kDownRight)) + } + if (isAdditionalChannelSet(kDownRight)) { nContributingChannels++; - if (isAdditionalChannelSet(kDown)) + } + if (isAdditionalChannelSet(kDown)) { nContributingChannels++; - if (isAdditionalChannelSet(kDownLeft)) + } + if (isAdditionalChannelSet(kDownLeft)) { nContributingChannels++; - if (isAdditionalChannelSet(kLeft)) + } + if (isAdditionalChannelSet(kLeft)) { nContributingChannels++; + } return nContributingChannels; } diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index 189ffb2126b67..a67094bc98e6f 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -170,8 +170,9 @@ void printHalfCRUHeader(o2::trd::HalfCRUHeader const& halfcru) getlinkerrorflags(halfcru, errorflags); LOGF(INFO, "V:%d BC:%d SB:%d EType:%d", halfcru.HeaderVersion, halfcru.BunchCrossing, halfcru.StopBit, halfcru.EventType); - for (int i = 0; i < 15; i++) + for (int i = 0; i < 15; i++) { LOGF(INFO, "Link %d size: %ul eflag: 0x%02x", i, sizes[i], errorflags[i]); + } } void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru) @@ -193,12 +194,14 @@ std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru) stream << "BunchCrossing : " << halfcru.BunchCrossing << std::endl; stream << "HeaderVersion : " << halfcru.HeaderVersion << std::endl; stream << "link sizes : "; - for (int link = 0; link < 15; link++) + for (int link = 0; link < 15; link++) { stream << link << ":" << std::hex << std::setw(4) << getlinkdatasize(halfcru, link) << ","; + } stream << std::endl; stream << "link errorflags : "; - for (int link = 0; link < 15; link++) + for (int link = 0; link < 15; link++) { stream << link << ":" << std::hex << std::setw(2) << getlinkerrorflag(halfcru, link) << ","; + } stream << std::endl; stream << "0x" << std::hex << halfcru.word0 << " 0x" << halfcru.word12[0] << " 0x" << halfcru.word12[1] << " 0x" << halfcru.word3 << " 0x" << halfcru.word47[0] << " 0x" << halfcru.word47[1] << " 0x" << halfcru.word47[2] << " 0x" << halfcru.word47[3] << std::endl; return stream; diff --git a/DataFormats/Detectors/ZDC/src/BCData.cxx b/DataFormats/Detectors/ZDC/src/BCData.cxx index 3f35c5e441949..a45d0f2c3da02 100644 --- a/DataFormats/Detectors/ZDC/src/BCData.cxx +++ b/DataFormats/Detectors/ZDC/src/BCData.cxx @@ -21,10 +21,11 @@ void BCData::print() const printf("Read:"); for (int ic = 0; ic < NDigiChannels; ic++) { if (ic % NChPerModule == 0) { - if (ic == 0) + if (ic == 0) { printf(" %d[", ic / NChPerModule); - else + } else { printf("] %d[", ic / NChPerModule); + } } if (channels & (0x1 << ic)) { printf("R"); @@ -35,10 +36,11 @@ void BCData::print() const printf("]\nHits:"); for (int ic = 0; ic < NDigiChannels; ic++) { if (ic % NChPerModule == 0) { - if (ic == 0) + if (ic == 0) { printf(" %d[", ic / NChPerModule); - else + } else { printf("] %d[", ic / NChPerModule); + } } if (triggers & (0x1 << ic)) { printf("H"); diff --git a/DataFormats/Headers/include/Headers/DataHeader.h b/DataFormats/Headers/include/Headers/DataHeader.h index 91eddadc902ba..1780e0ebf1607 100644 --- a/DataFormats/Headers/include/Headers/DataHeader.h +++ b/DataFormats/Headers/include/Headers/DataHeader.h @@ -305,16 +305,19 @@ struct Descriptor { { char* target = str; char* targetEnd = target; - if (length >= 0 && length < (int)N) + if (length >= 0 && length < (int)N) { targetEnd += length; - else + } else { targetEnd += N; + } const char* source = string; - for (; source != nullptr && target < targetEnd && *source != 0; ++target, ++source) + for (; source != nullptr && target < targetEnd && *source != 0; ++target, ++source) { *target = *source; + } targetEnd = str + N; - for (; target < targetEnd; ++target) + for (; target < targetEnd; ++target) { *target = 0; + } // require the string to be not longer than the descriptor size if (source != nullptr && (*source == 0 || (length >= 0 && length <= (int)N))) { } else { diff --git a/DataFormats/Headers/include/Headers/Stack.h b/DataFormats/Headers/include/Headers/Stack.h index 55dae8821265a..27924f3b53036 100644 --- a/DataFormats/Headers/include/Headers/Stack.h +++ b/DataFormats/Headers/include/Headers/Stack.h @@ -155,8 +155,9 @@ struct Stack { } std::copy(h.data(), h.data() + h.size(), here); BaseHeader* last = const_cast<BaseHeader*>(lastHeader(here)); - if (!last) + if (!last) { return here; + } last->flagsNextHeader = more; return here + h.size(); } else if constexpr (std::is_same_v<BaseHeader, headerType>) { @@ -176,8 +177,9 @@ struct Stack { here += from->size(); from = from->next(); }; - if (last) + if (last) { last->flagsNextHeader = more; + } return here; } else { static_assert(true, "Stack can only be constructed from other stacks and BaseHeader derived classes"); diff --git a/DataFormats/Headers/src/DataHeader.cxx b/DataFormats/Headers/src/DataHeader.cxx index 4e66265fc0372..0fe5c446cc5a2 100644 --- a/DataFormats/Headers/src/DataHeader.cxx +++ b/DataFormats/Headers/src/DataHeader.cxx @@ -119,11 +119,13 @@ o2::header::DataIdentifier::DataIdentifier() //__________________________________________________________________________________________________ bool o2::header::DataIdentifier::operator==(const DataIdentifier& other) const { - if (other.dataOrigin != gDataOriginAny && dataOrigin != other.dataOrigin) + if (other.dataOrigin != gDataOriginAny && dataOrigin != other.dataOrigin) { return false; + } if (other.dataDescription != gDataDescriptionAny && - dataDescription != other.dataDescription) + dataDescription != other.dataDescription) { return false; + } return true; } @@ -143,8 +145,9 @@ void o2::header::hexDump(const char* desc, const void* voidaddr, size_t len, siz const byte* addr = reinterpret_cast<const byte*>(voidaddr); // Output description if given. - if (desc != nullptr) + if (desc != nullptr) { printf("%s, ", desc); + } printf("%zu bytes:", len); if (max > 0 && len > max) { len = max; //limit the output if requested @@ -164,8 +167,9 @@ void o2::header::hexDump(const char* desc, const void* voidaddr, size_t len, siz // Multiple of 16 means new line (with line offset). if ((i % 16) == 0) { // Just don't print ASCII for the zeroth line. - if (i != 0) + if (i != 0) { printf(" %s\n", buff); + } // Output the offset. //printf (" %04x ", i); @@ -176,10 +180,11 @@ void o2::header::hexDump(const char* desc, const void* voidaddr, size_t len, siz printf(" %02x", addr[i]); // And store a printable ASCII character for later. - if ((addr[i] < 0x20) || (addr[i] > 0x7e)) + if ((addr[i] < 0x20) || (addr[i] > 0x7e)) { buff[i % 16] = '.'; - else + } else { buff[i % 16] = addr[i]; + } buff[(i % 16) + 1] = '\0'; fflush(stdout); } diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index 930dd46ecd751..77b83fd9f05f4 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -79,8 +79,9 @@ class TrackParFwd /// set the charge (assumed forward motion) void setCharge(Double_t charge) { - if (charge * mParameters(4) < 0.) + if (charge * mParameters(4) < 0.) { mParameters(4) *= -1.; + } } /// return track parameters diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index f88fcc8ecff53..02b77b0fefdd0 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -289,8 +289,9 @@ inline void TrackParametrizationWithError<value_T>::setCov(value_t v, int i) template <typename value_T> inline void TrackParametrizationWithError<value_T>::updateCov(const value_t delta[kCovMatSize]) { - for (int i = kCovMatSize; i--;) + for (int i = kCovMatSize; i--;) { mC[i] += delta[i]; + } } } // namespace track diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h index 29add2b3cfcdd..c333bd3e624d9 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h @@ -109,10 +109,11 @@ class MCTrackT { double_t pmom = GetP(); double mz(mStartVertexMomentumZ); - if (pmom != TMath::Abs(mz)) + if (pmom != TMath::Abs(mz)) { return 0.5 * std::log((pmom + mz) / (pmom - mz)); - else + } else { return 1.e30; + } } Double_t GetTheta() const @@ -154,8 +155,9 @@ class MCTrackT { int count = 0; for (auto i = o2::detectors::DetID::First; i < o2::detectors::DetID::nDetectors; ++i) { - if (leftTrace(i)) + if (leftTrace(i)) { count++; + } } return count; } diff --git a/DataFormats/simulation/include/SimulationDataFormat/Stack.h b/DataFormats/simulation/include/SimulationDataFormat/Stack.h index 3bb5cda6ff82e..6f4f6f9f1358c 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/Stack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/Stack.h @@ -190,8 +190,9 @@ class Stack : public FairGenericStack Reset(); for (auto p : primaries) { Int_t doTrack = 0; - if (p.TestBit(ParticleStatus::kToBeDone)) + if (p.TestBit(ParticleStatus::kToBeDone)) { doTrack = 1; + } PushTrack(doTrack, p); } mNumberOfPrimaryParticles = primaries.size(); diff --git a/DataFormats/simulation/src/Stack.cxx b/DataFormats/simulation/src/Stack.cxx index 95dafc74f5398..49e3c5ebe1732 100644 --- a/DataFormats/simulation/src/Stack.cxx +++ b/DataFormats/simulation/src/Stack.cxx @@ -224,8 +224,9 @@ void Stack::PushTrack(int toBeDone, TParticle& p) mNumberOfPrimaryParticles++; mPrimaryParticles.push_back(p); // Push particle on the stack - if (p.TestBit(ParticleStatus::kPrimary) && p.TestBit(ParticleStatus::kToBeDone)) + if (p.TestBit(ParticleStatus::kPrimary) && p.TestBit(ParticleStatus::kToBeDone)) { mNumberOfPrimariesforTracking++; + } mStack.push(p); mTracks->emplace_back(p); } @@ -448,8 +449,9 @@ void Stack::FinishPrimary() for (Int_t idTrack = imin; idTrack < imax; idTrack++) { Int_t index1 = mTrackIDtoParticlesEntry[idTrack]; Int_t index2 = indicesKept[index1]; - if (index2 == -1) + if (index2 == -1) { continue; + } Int_t index3 = (mIsG4Like) ? invreOrderedIndices[index2] : index2; mIndexMap[idTrack] = index3 + indexoffset; } @@ -578,8 +580,9 @@ void Stack::Print(Int_t iVerbose) const void Stack::Print(Option_t* option) const { Int_t verbose = 0; - if (option) + if (option) { verbose = 1; + } Print(verbose); } @@ -697,8 +700,9 @@ bool Stack::selectTracks() bool Stack::isPrimary(const MCTrack& part) { /** check if primary **/ - if (part.getProcess() == kPPrimary || part.getMotherTrackId() < 0) + if (part.getProcess() == kPPrimary || part.getMotherTrackId() < 0) { return true; + } /** not primary **/ return false; } @@ -709,13 +713,15 @@ bool Stack::isFromPrimaryDecayChain(const MCTrack& part) decay chain of a primary particle **/ /** check if from decay **/ - if (part.getProcess() != kPDecay) + if (part.getProcess() != kPDecay) { return false; + } /** check if mother is primary **/ auto imother = part.getMotherTrackId(); auto mother = mParticles[imother]; - if (isPrimary(mother)) + if (isPrimary(mother)) { return true; + } /** else check if mother is from primary decay **/ return isFromPrimaryDecayChain(mother); } @@ -727,13 +733,15 @@ bool Stack::isFromPrimaryPairProduction(const MCTrack& part) belonging to the primary decay chain **/ /** check if from pair production **/ - if (part.getProcess() != kPPair) + if (part.getProcess() != kPPair) { return false; + } /** check if mother is primary **/ auto imother = part.getMotherTrackId(); auto mother = mParticles[imother]; - if (isPrimary(mother)) + if (isPrimary(mother)) { return true; + } /** else check if mother is from primary decay **/ return isFromPrimaryDecayChain(mother); } @@ -745,12 +753,15 @@ bool Stack::keepPhysics(const MCTrack& part) // by physics analysis. Decision is put here. // - if (isPrimary(part)) + if (isPrimary(part)) { return true; - if (isFromPrimaryDecayChain(part)) + } + if (isFromPrimaryDecayChain(part)) { return true; - if (isFromPrimaryPairProduction(part)) + } + if (isFromPrimaryPairProduction(part)) { return true; + } return false; } @@ -809,8 +820,9 @@ void Stack::ReorderKine(std::vector<MCTrack>& particles, std::vector<int>& reOrd int indexoffset = mTracks->size(); Int_t index = 0; Int_t imoOld = 0; - for (Int_t i = 0; i < ntr; i++) + for (Int_t i = 0; i < ntr; i++) { reOrderedIndices[i] = i; + } for (Int_t i = -1; i < ntr; i++) { if (i != -1) { From 21e5c166e6d364d0a55b1f52dc1b7933c1443b0c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 22 Oct 2020 19:40:24 +0200 Subject: [PATCH 1026/1751] DPL GUI: add support for latest ImGUI (#4654) --- Framework/Core/src/FrameworkGUIDebugger.cxx | 15 +++++++++++++++ Framework/Core/src/FrameworkGUIDevicesGraph.cxx | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/Core/src/FrameworkGUIDebugger.cxx index 11e2ffa70b4c2..f3035a4c5b92e 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/Core/src/FrameworkGUIDebugger.cxx @@ -559,8 +559,13 @@ void displayDeviceHistograms(gui::WorkspaceGUIState& state, currentStyle, devices, metricsInfos); } break; case MetricsDisplayStyle::Sparks: { +#if defined(ImGuiCol_ChildWindowBg) ImGui::BeginChild("##ScrollingRegion", ImVec2(ImGui::GetIO().DisplaySize.x + state.leftPaneSize + state.rightPaneSize - 10, -ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); +#else + ImGui::BeginChild("##ScrollingRegion", ImVec2(ImGui::GetIO().DisplaySize.x + state.leftPaneSize + state.rightPaneSize - 10, -ImGui::GetTextLineHeightWithSpacing()), false, + ImGuiWindowFlags_HorizontalScrollbar); +#endif ImGui::Columns(2); ImGui::SetColumnOffset(1, 300); for (size_t i = 0; i < state.devices.size(); ++i) { @@ -574,8 +579,13 @@ void displayDeviceHistograms(gui::WorkspaceGUIState& state, ImGui::EndChild(); } break; case MetricsDisplayStyle::Table: { +#if defined(ImGuiCol_ChildWindowBg) ImGui::BeginChild("##ScrollingRegion", ImVec2(ImGui::GetIO().DisplaySize.x + state.leftPaneSize + state.rightPaneSize - 10, -ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); +#else + ImGui::BeginChild("##ScrollingRegion", ImVec2(ImGui::GetIO().DisplaySize.x + state.leftPaneSize + state.rightPaneSize - 10, -ImGui::GetTextLineHeightWithSpacing()), false, + ImGuiWindowFlags_HorizontalScrollbar); +#endif // The +1 is for the timestamp column ImGui::Columns(state.devices.size() + 1); @@ -774,8 +784,13 @@ std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos, (int)LogParsingHelpers::LogLevel::Size, 5); ImGui::Separator(); +#if defined(ImGuiCol_ChildWindowBg) ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoMove); +#else + ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetTextLineHeightWithSpacing()), false, + ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoMove); +#endif displayHistory(info, control); ImGui::EndChild(); ImGui::End(); diff --git a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx index b42f811155a4f..488a77ccc176d 100644 --- a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx +++ b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx @@ -382,7 +382,11 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1, 1)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); +#if defined(ImGuiCol_ChildWindowBg) ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, (ImU32)ImColor(60, 60, 70, 200)); +#else + ImGui::PushStyleColor(ImGuiCol_WindowBg, (ImU32)ImColor(60, 60, 70, 200)); +#endif ImVec2 graphSize = ImGui::GetWindowSize(); if (state.leftPaneVisible) { graphSize.x -= state.leftPaneSize; From e326bd41abbd96026d2b96d6dc4f93ad69f27202 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Wed, 7 Oct 2020 14:09:35 +0200 Subject: [PATCH 1027/1751] [math_utils] Refactor Bracket Pull `Bracket` into `o2::math_utils` namespace and clean up implementation files. Change files that include `Bracket` accordingly. --- Common/MathUtils/include/MathUtils/Bracket.h | 226 +++++++++++++----- Common/MathUtils/src/MathUtilsLinkDef.h | 2 +- .../include/GlobalTracking/MatchTOF.h | 40 ++-- .../include/GlobalTracking/MatchTPCITS.h | 58 ++--- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 65 +++-- .../ITSReconstruction/RecoGeomHelper.h | 4 +- .../ITS/reconstruction/src/RecoGeomHelper.cxx | 20 +- .../DetectorsVertexing/VertexTrackMatcher.h | 2 +- .../Vertexing/src/VertexTrackMatcher.cxx | 6 +- 9 files changed, 262 insertions(+), 161 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Bracket.h b/Common/MathUtils/include/MathUtils/Bracket.h index ba8912a4fb1b2..f60fb987524ea 100644 --- a/Common/MathUtils/include/MathUtils/Bracket.h +++ b/Common/MathUtils/include/MathUtils/Bracket.h @@ -10,7 +10,7 @@ /// \file Bracket.h /// \brief Class to represent an interval and some operations over it -/// \author ruben.shahoyan@cern.ch +/// \author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch #ifndef ALICEO2_BRACKET_H #define ALICEO2_BRACKET_H @@ -19,7 +19,7 @@ namespace o2 { -namespace utils +namespace math_utils { template <typename T = float> @@ -30,74 +30,176 @@ class Bracket Inside = 0, Above = 1 }; - Bracket(T minv, T maxv) : mMin(minv), mMax(maxv) {} - Bracket(const Bracket<T>& src) = default; + Bracket(T minv, T maxv); Bracket() = default; + Bracket(const Bracket<T>& src) = default; + Bracket(Bracket<T>&& src) = default; + Bracket& operator=(const Bracket<T>& src) = default; + Bracket& operator=(Bracket<T>&& src) = default; ~Bracket() = default; - void set(T minv, T maxv) - { - mMin = minv; - mMax = maxv; - } - bool operator<(const T rhs) - { - return mMax < rhs; - } - bool operator>(const T rhs) - { - return mMin > rhs; - } - bool operator<(const Bracket<T>& rhs) - { - return mMax < rhs.mMin; - } - bool operator>(const Bracket<T>& rhs) - { - return mMin > rhs.mMax; - } - bool operator==(const Bracket<T>& rhs) - { - return mMin == rhs.mMin && mMax == rhs.mMax; - } + bool operator<(T other) const; + bool operator>(T other) const; - void setMax(T v) { mMax = v; } - void setMin(T v) { mMin = v; } - T& max() { return mMax; } - T& min() { return mMin; } - T max() const { return mMax; } - T min() const { return mMin; } - T mean() const { return (mMin + mMax) / 2; } - T delta() const { return mMax - mMin; } - bool isValid() const { return mMax >= mMin; } - bool isInvalid() const { return mMin > mMax; } - void update(T v) - { - // update limits - if (v > mMax) { - mMax = v; - } - if (v < mMin) { - mMin = v; - } - } - Relation isOutside(const Bracket<T>& t) const - { - ///< check if provided bracket is outside of this bracket - return t.mMax < mMin ? Below : (t.mMin > mMax ? Above : Inside); - } - int isOutside(T t, T tErr) const - { - ///< check if the provided value t with error tErr is outside of the bracket - return t + tErr < mMin ? Below : (t - tErr > mMax ? Above : Inside); - } + bool operator<(const Bracket<T>& other) const; + bool operator>(const Bracket<T>& other) const; + bool operator==(const Bracket<T>& other) const; + bool operator!=(const Bracket<T>& other) const; + + void setMax(T v) noexcept; + void setMin(T v) noexcept; + void set(T minv, T maxv) noexcept; + + T& getMax(); + T& getMin(); + + T getMax() const; + T getMin() const; + T mean() const; + T delta() const; + bool isValid() const; + bool isInvalid() const; + void update(T v); + Relation isOutside(const Bracket<T>& t) const; + Relation isOutside(T t, T tErr) const; private: - T mMin{}, mMax{}; + T mMin{}; + T mMax{}; - ClassDefNV(Bracket, 1); + ClassDefNV(Bracket, 2); }; -} // namespace utils + +template <typename T> +Bracket<T>::Bracket(T minv, T maxv) : mMin(minv), mMax(maxv) +{ +} + +template <typename T> +inline bool Bracket<T>::operator<(T other) const +{ + return mMax < other; +} + +template <typename T> +inline bool Bracket<T>::operator>(T other) const +{ + return mMin > other; +} + +template <typename T> +inline bool Bracket<T>::operator<(const Bracket<T>& other) const +{ + return *this < other.mMin; +} + +template <typename T> +inline bool Bracket<T>::operator>(const Bracket<T>& other) const +{ + return *this > other.mMax; +} + +template <typename T> +inline bool Bracket<T>::operator==(const Bracket<T>& rhs) const +{ + return mMin == rhs.mMin && mMax == rhs.mMax; +} + +template <typename T> +inline bool Bracket<T>::operator!=(const Bracket<T>& rhs) const +{ + return !(*this == rhs); +} + +template <typename T> +inline void Bracket<T>::setMax(T v) noexcept +{ + mMax = v; +} + +template <typename T> +inline void Bracket<T>::setMin(T v) noexcept +{ + mMin = v; +} + +template <typename T> +inline void Bracket<T>::set(T minv, T maxv) noexcept +{ + this->setMin(minv); + this->setMax(maxv); +} + +template <typename T> +inline T& Bracket<T>::getMax() +{ + return mMax; +} + +template <typename T> +inline T& Bracket<T>::getMin() +{ + return mMin; +} + +template <typename T> +inline T Bracket<T>::getMax() const +{ + return mMax; +} + +template <typename T> +inline T Bracket<T>::getMin() const +{ + return mMin; +} + +template <typename T> +inline T Bracket<T>::mean() const +{ + return (mMin + mMax) / 2; +} +template <typename T> +inline T Bracket<T>::delta() const +{ + return mMax - mMin; +} +template <typename T> +inline bool Bracket<T>::isValid() const +{ + return mMax >= mMin; +} +template <typename T> +inline bool Bracket<T>::isInvalid() const +{ + return mMin > mMax; +} +template <typename T> +inline void Bracket<T>::update(T v) +{ + // update limits + if (v > mMax) { + mMax = v; + } + if (v < mMin) { + mMin = v; + } +} + +template <typename T> +inline typename Bracket<T>::Relation Bracket<T>::isOutside(const Bracket<T>& t) const +{ + ///< check if provided bracket is outside of this bracket + return t.mMax < mMin ? Below : (t.mMin > mMax ? Above : Inside); +} +template <typename T> +inline typename Bracket<T>::Relation Bracket<T>::isOutside(T t, T tErr) const +{ + ///< check if the provided value t with error tErr is outside of the bracket + return t + tErr < mMin ? Below : (t - tErr > mMax ? Above : Inside); +} + +} // namespace math_utils } // namespace o2 #endif diff --git a/Common/MathUtils/src/MathUtilsLinkDef.h b/Common/MathUtils/src/MathUtilsLinkDef.h index 7be4951a0bee5..23acd7c864bca 100644 --- a/Common/MathUtils/src/MathUtilsLinkDef.h +++ b/Common/MathUtils/src/MathUtilsLinkDef.h @@ -35,6 +35,6 @@ #pragma link C++ class o2::utils::CircleXY + ; #pragma link C++ class o2::utils::IntervalXY + ; -#pragma link C++ class o2::utils::Bracket < float> + ; +#pragma link C++ class o2::math_utils::Bracket < float> + ; #endif diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 44427c9b324a9..ba5c2221294f1 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -59,7 +59,7 @@ namespace globaltracking ///< original track in the currently loaded TPC-ITS reco output struct TrackLocTPCITS : public o2::track::TrackParCov { o2::dataformats::EvIndex<int, int> source; ///< track origin id - o2::utils::Bracket<float> timeBins; ///< bracketing time-bins + o2::math_utils::Bracket<float> timeBins; ///< bracketing time-bins float zMin = 0; // min possible Z of this track float zMax = 0; // max possible Z of this track int matchID = MinusOne; ///< entry (none if MinusOne) of TOF matchTOF struct in the mMatchesTOF @@ -256,9 +256,9 @@ class MatchTOF gsl::span<const Cluster> mTOFClustersArrayInp; ///< input TOF clusters std::vector<Cluster>* mTOFClustersArrayInpVect; ///< input TOF clusters (vector to read from tree) - o2::dataformats::MCTruthContainer<o2::MCCompLabel> mTOFClusLabels; ///< input TOF clusters MC labels - o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mTOFClusLabelsPtr; ///< input TOF clusters MC labels (pointer to read from tree) - std::vector<o2::MCCompLabel> mTracksLblWork; ///<TPCITS track labels + o2::dataformats::MCTruthContainer<o2::MCCompLabel> mTOFClusLabels; ///< input TOF clusters MC labels + o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mTOFClusLabelsPtr; ///< input TOF clusters MC labels (pointer to read from tree) + std::vector<o2::MCCompLabel> mTracksLblWork; ///<TPCITS track labels gsl::span<const o2::MCCompLabel> mTPCLabels; ///< TPC label of input tracks gsl::span<const o2::MCCompLabel> mITSLabels; ///< ITS label of input tracks @@ -270,11 +270,11 @@ class MatchTOF /// <<<----- ///<working copy of the input tracks - std::vector<matchTrack> mTracksWork; ///<track params prepared for matching + time value - std::vector<float> mExtraTPCFwdTime; ///<track extra params for TPC tracks: Fws Max time - std::vector<o2::track::TrackLTIntegral> mLTinfos; ///<expected times and others - std::vector<Cluster> mTOFClusWork; ///<track params prepared for matching - std::vector<int8_t> mSideTPC; ///<track side for TPC tracks + std::vector<matchTrack> mTracksWork; ///<track params prepared for matching + time value + std::vector<float> mExtraTPCFwdTime; ///<track extra params for TPC tracks: Fws Max time + std::vector<o2::track::TrackLTIntegral> mLTinfos; ///<expected times and others + std::vector<Cluster> mTOFClusWork; ///<track params prepared for matching + std::vector<int8_t> mSideTPC; ///<track side for TPC tracks ///< per sector indices of track entry in mTracksWork std::array<std::vector<int>, o2::constants::math::NSectors> mTracksSectIndexCache; @@ -301,17 +301,17 @@ class MatchTOF int mNumOfClusters; // number of clusters to be matched int* mMatchedClustersIndex = nullptr; //[mNumOfClusters] - std::string mTracksBranchName = "TPCITS"; ///< name of branch containing input matched tracks - std::string mTPCTracksBranchName = "Tracks"; ///< name of branch containing actual TPC tracks - std::string mTPCMCTruthBranchName = "MatchTPCMCTruth"; ///< name of branch containing TPC labels - std::string mITSMCTruthBranchName = "MatchITSMCTruth"; ///< name of branch containing ITS labels - std::string mTOFMCTruthBranchName = "TOFClusterMCTruth"; ///< name of branch containing TOF clusters labels - std::string mTOFClusterBranchName = "TOFCluster"; ///< name of branch containing input ITS clusters - std::string mOutTracksBranchName = "TOFMatchInfo"; ///< name of branch containing output matched tracks - std::string mOutCalibBranchName = "TOFCalibInfo"; ///< name of branch containing output calibration infos - std::string mOutTOFMCTruthBranchName = "MatchTOFMCTruth"; ///< name of branch containing TOF labels for output matched tracks - std::string mOutTPCMCTruthBranchName = "MatchTPCMCTruth"; ///< name of branch containing TOF labels for output matched tracks - std::string mOutITSMCTruthBranchName = "MatchITSMCTruth"; ///< name of branch containing TOF labels for output matched tracks + std::string mTracksBranchName = "TPCITS"; ///< name of branch containing input matched tracks + std::string mTPCTracksBranchName = "Tracks"; ///< name of branch containing actual TPC tracks + std::string mTPCMCTruthBranchName = "MatchTPCMCTruth"; ///< name of branch containing TPC labels + std::string mITSMCTruthBranchName = "MatchITSMCTruth"; ///< name of branch containing ITS labels + std::string mTOFMCTruthBranchName = "TOFClusterMCTruth"; ///< name of branch containing TOF clusters labels + std::string mTOFClusterBranchName = "TOFCluster"; ///< name of branch containing input ITS clusters + std::string mOutTracksBranchName = "TOFMatchInfo"; ///< name of branch containing output matched tracks + std::string mOutCalibBranchName = "TOFCalibInfo"; ///< name of branch containing output calibration infos + std::string mOutTOFMCTruthBranchName = "MatchTOFMCTruth"; ///< name of branch containing TOF labels for output matched tracks + std::string mOutTPCMCTruthBranchName = "MatchTPCMCTruth"; ///< name of branch containing TOF labels for output matched tracks + std::string mOutITSMCTruthBranchName = "MatchITSMCTruth"; ///< name of branch containing TOF labels for output matched tracks std::string mOutTPCTrackMCTruthBranchName = "TracksMCTruth"; ///< name of branch containing TPC labels for input TPC tracks std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut; diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 210987d2bd6f8..eb30024ade60b 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -101,11 +101,11 @@ enum TrackRejFlag : int { ///< TPC track parameters propagated to reference X, with time bracket and index of ///< original track in the currently loaded TPC reco output struct TrackLocTPC : public o2::track::TrackParCov { - o2::utils::Bracket<float> timeBins; ///< bracketing time-bins - int sourceID = 0; ///< track origin id - float zMin = 0; // min possible Z of this track - float zMax = 0; // max possible Z of this track - int matchID = MinusOne; ///< entry (non if MinusOne) of its matchTPC struct in the mMatchesTPC + o2::math_utils::Bracket<float> timeBins; ///< bracketing time-bins + int sourceID = 0; ///< track origin id + float zMin = 0; // min possible Z of this track + float zMax = 0; // max possible Z of this track + int matchID = MinusOne; ///< entry (non if MinusOne) of its matchTPC struct in the mMatchesTPC TrackLocTPC(const o2::track::TrackParCov& src, int tid) : o2::track::TrackParCov(src), sourceID(tid) {} TrackLocTPC() = default; ClassDefNV(TrackLocTPC, 1); @@ -114,9 +114,9 @@ struct TrackLocTPC : public o2::track::TrackParCov { ///< ITS track outward parameters propagated to reference X, with time bracket and index of ///< original track in the currently loaded ITS reco output struct TrackLocITS : public o2::track::TrackParCov { - int sourceID = 0; ///< track origin id - int roFrame = MinusOne; ///< ITS readout frame assigned to this track - int matchID = MinusOne; ///< entry (non if MinusOne) of its matchCand struct in the mMatchesITS + int sourceID = 0; ///< track origin id + int roFrame = MinusOne; ///< ITS readout frame assigned to this track + int matchID = MinusOne; ///< entry (non if MinusOne) of its matchCand struct in the mMatchesITS TrackLocITS(const o2::track::TrackParCov& src, int tid) : o2::track::TrackParCov(src), sourceID(tid) {} TrackLocITS() = default; ClassDefNV(TrackLocITS, 1); @@ -216,7 +216,7 @@ struct ABDebugTrack { short valid = 0; o2::track::TrackParCov tpcSeed; o2::MCCompLabel tpcLabel; - o2::utils::Bracket<float> icTimeBin; + o2::math_utils::Bracket<float> icTimeBin; std::vector<ABDebugLink> links; float chi2 = 0; uint8_t nClusTPC = 0; @@ -241,10 +241,10 @@ struct ABClusterLink { }; struct InteractionCandidate : public o2::InteractionRecord { - o2::utils::Bracket<float> timeBins; // interaction time (int TPC time bins) - int rofITS; // corresponding ITS ROF entry (in the ROFRecord vectors) - uint32_t flag; // origin, etc. - void* clRefPtr = nullptr; // pointer on cluster references container (if any) + o2::math_utils::Bracket<float> timeBins; // interaction time (int TPC time bins) + int rofITS; // corresponding ITS ROF entry (in the ROFRecord vectors) + uint32_t flag; // origin, etc. + void* clRefPtr = nullptr; // pointer on cluster references container (if any) InteractionCandidate() = default; InteractionCandidate(const o2::InteractionRecord& ir, float t, float dt, int rof, uint32_t f = 0) : o2::InteractionRecord(ir), timeBins(t - dt, t + dt), rofITS(rof), flag(f) {} }; @@ -275,8 +275,8 @@ class MatchTPCITS using MCLabContTr = std::vector<o2::MCCompLabel>; using MCLabSpan = gsl::span<const o2::MCCompLabel>; using TPCTransform = o2::gpu::TPCFastTransform; - using BracketF = o2::utils::Bracket<float>; - using BracketIR = o2::utils::Bracket<o2::InteractionRecord>; + using BracketF = o2::math_utils::Bracket<float>; + using BracketIR = o2::math_utils::Bracket<o2::InteractionRecord>; using Params = o2::globaltracking::MatchITSTPCParams; using MatCorrType = o2::base::Propagator::MatCorrType; @@ -593,10 +593,10 @@ class MatchTPCITS //================================================================ - bool mInitDone = false; ///< flag init already done - bool mFieldON = true; ///< flag for field ON/OFF - bool mCosmics = false; ///< flag cosmics mode - bool mMCTruthON = false; ///< flag availability of MC truth + bool mInitDone = false; ///< flag init already done + bool mFieldON = true; ///< flag for field ON/OFF + bool mCosmics = false; ///< flag cosmics mode + bool mMCTruthON = false; ///< flag availability of MC truth o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF @@ -653,14 +653,14 @@ class MatchTPCITS gsl::span<const o2::itsmft::ROFRecord> mITSClusterROFRec; ///< input ITS clusters ROFRecord span gsl::span<const o2::ft0::RecPoints> mFITInfo; ///< optional input FIT info span - const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices + const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices const MCLabContCl* mITSClsLabels = nullptr; ///< input ITS Cluster MC labels MCLabSpan mITSTrkLabels; ///< input ITS Track MC labels MCLabSpan mTPCTrkLabels; ///< input TPC Track MC labels /// <<<----- - std::vector<InteractionCandidate> mInteractions; ///< possible interaction times + std::vector<InteractionCandidate> mInteractions; ///< possible interaction times std::vector<o2::dataformats::RangeRefComp<8>> mITSROFIntCandEntries; ///< entries of InteractionCandidate vector for every ITS ROF bin ///< container for record the match of TPC track to single ITS track @@ -668,13 +668,13 @@ class MatchTPCITS ///< container for reference to MatchRecord involving particular ITS track std::vector<MatchRecord> mMatchRecordsITS; - std::vector<int> mITSROFofTPCBin; ///< aux structure for mapping of TPC time-bins on ITS ROFs - std::vector<BracketF> mITSROFTimes; ///< min/max times of ITS ROFs in TPC time-bins - std::vector<TrackLocTPC> mTPCWork; ///< TPC track params prepared for matching - std::vector<TrackLocITS> mITSWork; ///< ITS track params prepared for matching - MCLabContTr mTPCLblWork; ///< TPC track labels - MCLabContTr mITSLblWork; ///< ITS track labels - std::vector<float> mWinnerChi2Refit; ///< vector of refitChi2 for winners + std::vector<int> mITSROFofTPCBin; ///< aux structure for mapping of TPC time-bins on ITS ROFs + std::vector<BracketF> mITSROFTimes; ///< min/max times of ITS ROFs in TPC time-bins + std::vector<TrackLocTPC> mTPCWork; ///< TPC track params prepared for matching + std::vector<TrackLocITS> mITSWork; ///< ITS track params prepared for matching + MCLabContTr mTPCLblWork; ///< TPC track labels + MCLabContTr mITSLblWork; ///< ITS track labels + std::vector<float> mWinnerChi2Refit; ///< vector of refitChi2 for winners std::deque<ITSChipClustersRefs> mITSChipClustersRefs; ///< range of clusters for each chip in ITS (for AfterBurner) @@ -854,7 +854,7 @@ inline void MatchTPCITS::cleanAfterBurnerClusRefCache(int currentIC, int& startI { // check if some of cached cluster reference from tables startIC to currentIC can be released, // they will be necessarily in front slots of the mITSChipClustersRefs - while (startIC < currentIC && mInteractions[currentIC].timeBins.min() - mInteractions[startIC].timeBins.max() > MinTBToCleanCache) { + while (startIC < currentIC && mInteractions[currentIC].timeBins.getMin() - mInteractions[startIC].timeBins.getMax() > MinTBToCleanCache) { LOG(INFO) << "CAN REMOVE CACHE FOR " << startIC << " curent IC=" << currentIC; while (mInteractions[startIC].clRefPtr == &mITSChipClustersRefs.front()) { LOG(INFO) << "Reset cache pointer" << mInteractions[startIC].clRefPtr << " for IC=" << startIC; diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 87676ee2f770e..ae95d34c65264 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -361,7 +361,7 @@ void MatchTPCITS::init() mRGHelper.init(); // prepare helper for TPC track / ITS clusters matching const auto& zr = mRGHelper.layers.back().zRange; - mITSFiducialZCut = std::max(std::abs(zr.min()), std::abs(zr.max())) + 20.; + mITSFiducialZCut = std::max(std::abs(zr.getMin()), std::abs(zr.getMax())) + 20.; clear(); @@ -580,13 +580,13 @@ bool MatchTPCITS::prepareTPCTracks() std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { auto& trcA = mTPCWork[a]; auto& trcB = mTPCWork[b]; - return (trcA.timeBins.max() - trcB.timeBins.max()) < 0.; + return (trcA.timeBins.getMax() - trcB.timeBins.getMax()) < 0.; }); // build array of 1st entries with tmax corresponding to each ITS ROF (or trigger), // TPC tracks below this entry cannot match to ITS tracks of this and higher ROFs - float tmax = mTPCWork[indexCache.back()].timeBins.max(); + float tmax = mTPCWork[indexCache.back()].timeBins.getMax(); if (maxTimeBin < tmax) { maxTimeBin = tmax; } @@ -616,13 +616,13 @@ bool MatchTPCITS::prepareTPCTracks() // create mapping from TPC time-bins to ITS ROFs if (mITSROFTimes.back() < maxTimeBin) { - maxTimeBin = mITSROFTimes.back().max(); + maxTimeBin = mITSROFTimes.back().getMax(); } int nb = int(maxTimeBin) + 1; mITSROFofTPCBin.resize(nb, -1); int itsROF = 0; for (int ib = 0; ib < nb; ib++) { - while (itsROF < nITSROFs && ib < mITSROFTimes[itsROF].min()) { + while (itsROF < nITSROFs && ib < mITSROFTimes[itsROF].getMin()) { itsROF++; } mITSROFofTPCBin[ib] = itsROF; @@ -680,8 +680,8 @@ bool MatchTPCITS::prepareITSTracks() } int cluROFOffset = mITSClusterROFRec[irof].getFirstEntry(); // clusters of this ROF start at this offset - float tmn = intRecord2TPCTimeBin(rofRec.getBCData()); // ITS track min time in TPC time-bins - mITSROFTimes.emplace_back(tmn, tmn + mITSROFrame2TPCBin); // ITS track min/max time in TPC time-bins + float tmn = intRecord2TPCTimeBin(rofRec.getBCData()); // ITS track min time in TPC time-bins + mITSROFTimes.emplace_back(tmn, tmn + mITSROFrame2TPCBin); // ITS track min/max time in TPC time-bins for (int sec = o2::constants::math::NSectors; sec--;) { // start of sector's tracks for this ROF mITSTimeBinStart[sec][irof] = mITSSectIndexCache[sec].size(); // The sorting does not affect this @@ -782,7 +782,6 @@ bool MatchTPCITS::prepareFITInfo() return true; } - //_____________________________________________________ void MatchTPCITS::doMatching(int sec) { @@ -809,14 +808,14 @@ void MatchTPCITS::doMatching(int sec) } int nCheckTPCControl = 0, nCheckITSControl = 0, nMatchesControl = 0; // temporary - int idxMinTPC = tbinStartTPC[minROFITS]; // index of 1st cached TPC track within cached ITS ROFrames + int idxMinTPC = tbinStartTPC[minROFITS]; // index of 1st cached TPC track within cached ITS ROFrames auto t2nbs = mZ2TPCBin * mParams->tpcTimeICMatchingNSigma; bool checkInteractionCandidates = mUseFT0 && mParams->validateMatchByFIT != MatchITSTPCParams::Disable; for (int itpc = idxMinTPC; itpc < nTracksTPC; itpc++) { auto& trefTPC = mTPCWork[cacheTPC[itpc]]; // estimate ITS 1st ROframe bin this track may match to: TPC track are sorted according to their // timeMax, hence the timeMax - MaxmNTPCBinsFullDrift are non-decreasing - int itsROBin = tpcTimeBin2ITSROFrame(trefTPC.timeBins.max() - maxTDriftSafe); + int itsROBin = tpcTimeBin2ITSROFrame(trefTPC.timeBins.getMax() - maxTDriftSafe); if (itsROBin >= int(tbinStartITS.size())) { // time of TPC track exceeds the max time of ITS in the cache break; @@ -870,7 +869,7 @@ void MatchTPCITS::doMatching(int sec) 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<float> trange(timeTB - timeTBErr, timeTB + timeTBErr); + o2::math_utils::Bracket<float> trange(timeTB - timeTBErr, timeTB + timeTBErr); // is corrected TPC track time compatible with ITS ROF expressed in TPC bins? if (timeITS.isOutside(trange)) { continue; @@ -892,10 +891,10 @@ void MatchTPCITS::doMatching(int sec) int idIC = interactionRefs.getFirstEntry(), maxIC = idIC + nic; for (; idIC < maxIC; idIC++) { auto cmp = mInteractions[idIC].timeBins.isOutside(trange); - if (cmp == o2::utils::Bracket<float>::Above) { // trange is above this interaction candidate, the following ones may match + if (cmp == o2::math_utils::Bracket<float>::Above) { // trange is above this interaction candidate, the following ones may match continue; } - if (cmp == o2::utils::Bracket<float>::Inside) { + if (cmp == o2::math_utils::Bracket<float>::Inside) { matchedIC = idIC; } break; // we loop till 1st matching IC or the one above the trange (since IC are ordered, all others will be above too) @@ -921,8 +920,8 @@ void MatchTPCITS::suppressMatchRecordITS(int itsID, int tpcID) { ///< suppress the reference on the tpcID in the list of matches recorded for itsID auto& tITS = mITSWork[itsID]; - int topID = MinusOne, recordID = tITS.matchID; // 1st entry in mMatchRecordsITS - while (recordID > MinusOne) { // navigate over records for given ITS track + int topID = MinusOne, recordID = tITS.matchID; // 1st entry in mMatchRecordsITS + while (recordID > MinusOne) { // navigate over records for given ITS track if (mMatchRecordsITS[recordID].partnerID == tpcID) { // unlink this record, connecting its child to its parrent if (topID < 0) { @@ -942,10 +941,10 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2, int can { ///< record matching candidate, making sure that number of ITS candidates per TPC track, sorted ///< in matching chi2 does not exceed allowed number - auto& tTPC = mTPCWork[iTPC]; // get MatchRecord structure of this TPC track, create if none - if (tTPC.matchID < 0) { // no matches yet, just add new record - registerMatchRecordITS(iITS, iTPC, chi2, candIC); // register TPC track in the ITS records - tTPC.matchID = mMatchRecordsTPC.size(); // new record will be added in the end + auto& tTPC = mTPCWork[iTPC]; // get MatchRecord structure of this TPC track, create if none + if (tTPC.matchID < 0) { // no matches yet, just add new record + registerMatchRecordITS(iITS, iTPC, chi2, candIC); // register TPC track in the ITS records + tTPC.matchID = mMatchRecordsTPC.size(); // new record will be added in the end mMatchRecordsTPC.emplace_back(iITS, chi2, MinusOne, candIC); // create new record with empty reference on next match return true; } @@ -956,8 +955,8 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2, int can count++; if (!nextMatchRec.isBetter(chi2, candIC)) { // need to insert new record before nextMatchRec? if (count < mParams->maxMatchCandidates) { - break; // will insert in front of nextID - } else { // max number of candidates reached, will overwrite the last one + break; // will insert in front of nextID + } else { // max number of candidates reached, will overwrite the last one suppressMatchRecordITS(nextMatchRec.partnerID, iTPC); // flag as disabled the overriden ITS match registerMatchRecordITS(iITS, iTPC, chi2, candIC); // register TPC track entry in the ITS records // reuse the record of suppressed ITS match to store better one @@ -1019,7 +1018,7 @@ void MatchTPCITS::registerMatchRecordITS(int iITS, int iTPC, float chi2, int can do { auto& nextMatchRec = mMatchRecordsITS[nextRecord]; if (!nextMatchRec.isBetter(chi2, candIC)) { // need to insert new record before nextMatchRec? - newRecord.nextRecID = nextRecord; // new one will refer to old one it overtook + newRecord.nextRecID = nextRecord; // new one will refer to old one it overtook if (topID < 0) { tITS.matchID = idnew; // the new one is the best match, track will refer to it } else { @@ -1774,7 +1773,7 @@ int MatchTPCITS::prepareTPCTracksAfterBurner() mTPCABTimeBinStart.clear(); const auto& outerLr = mRGHelper.layers.back(); // to avoid difference between 3D field propagation and Bz-bazed getXatLabR we propagate RMax+margin - const float ROuter = outerLr.rRange.max() + 0.5f; + const float ROuter = outerLr.rRange.getMax() + 0.5f; auto propagator = o2::base::Propagator::Instance(); @@ -1797,7 +1796,7 @@ int MatchTPCITS::prepareTPCTracksAfterBurner() std::sort(mTPCABIndexCache.begin(), mTPCABIndexCache.end(), [this](int a, int b) { auto& trcA = mTPCWork[a]; auto& trcB = mTPCWork[b]; - return (trcA.timeBins.min() - trcB.timeBins.min()) < 0.; + return (trcA.timeBins.getMin() - trcB.timeBins.getMin()) < 0.; }); return mTPCABIndexCache.size(); @@ -1825,7 +1824,7 @@ int MatchTPCITS::prepareInteractionTimes() if (mITSROFTimes[rof] < fitTime) { continue; } - if (fitTime >= mITSROFTimes[rof].min()) { // belongs to this ROF + if (fitTime >= mITSROFTimes[rof].getMin()) { // belongs to this ROF auto& ref = mITSROFIntCandEntries[rof]; if (!ref.getEntries()) { ref.setFirstEntry(mInteractions.size()); // register entry @@ -1886,7 +1885,7 @@ void MatchTPCITS::runAfterBurner() } else if (iCRes > 0) { continue; // TPC track precedes the interaction (means orphan track?), no need to check it } else { - LOG(INFO) << "All interaction candidates precede track " << itr << " [" << tTPC.timeBins.min() << ":" << tTPC.timeBins.max() << "]"; + LOG(INFO) << "All interaction candidates precede track " << itr << " [" << tTPC.timeBins.getMin() << ":" << tTPC.timeBins.getMax() << "]"; break; // all interaction candidates precede TPC track } } @@ -1930,8 +1929,8 @@ bool MatchTPCITS::runAfterBurner(int tpcWID, int iCStart, int iCEnd) /* // tmp LOG(INFO) << "Check track TPC mtc=" << tTPC.matchID << " int.cand. " << iCC - << " [" << tTPC.timeBins.min() << ":" << tTPC.timeBins.max() << "] for interaction " - << " [" << iCCand.timeBins.min() << ":" << iCCand.timeBins.max() << "]"; + << " [" << tTPC.timeBins.getMin() << ":" << tTPC.timeBins.getMax() << "] for interaction " + << " [" << iCCand.timeBins.getMin() << ":" << iCCand.timeBins.getMax() << "]"; */ if (std::abs(topLink.getZ()) > mITSFiducialZCut) { // we can discard this seed topLink.disable(); @@ -1979,7 +1978,7 @@ int MatchTPCITS::checkABSeedFromLr(int lrSeed, int seedID, ABTrackLinksList& lli auto propagator = o2::base::Propagator::Instance(); float xTgt; const auto& lr = mRGHelper.layers[lrTgt]; - if (!seed.getXatLabR(lr.rRange.max(), xTgt, propagator->getNominalBz(), o2::track::DirInward) || + if (!seed.getXatLabR(lr.rRange.getMax(), xTgt, propagator->getNominalBz(), o2::track::DirInward) || !propagator->PropagateToXBxByBz(seed, xTgt, o2::constants::physics::MassPionCharged, MaxSnp, 2., mUseMatCorrFlag)) { return 0; } @@ -2050,7 +2049,7 @@ int MatchTPCITS::checkABSeedFromLr(int lrSeed, int seedID, ABTrackLinksList& lli printf("Lr %d #%d/%d LadID: %d (phi:%+d) ChipID: %d [%d Ncl: %d from %d] (rRhi:%d Z:%+d[%+.1f:%+.1f]) | %+.3f %+.3f -> %+.3f %+.3f %+.3f (zErr: %.3f)\n", lrTgt, ilad, ich, ladID, lad.isPhiOutside(phi, errPhi), chipID, chipGID, clRange.getEntries(), clRange.getFirstEntry(), - lad.chips[chipID].xyEdges.seenByCircle(trcCircle, errYFrac), lad.chips[chipID].zRange.isOutside(zCross, 3 * errZ), lad.chips[chipID].zRange.min(), lad.chips[chipID].zRange.max(), + lad.chips[chipID].xyEdges.seenByCircle(trcCircle, errYFrac), lad.chips[chipID].zRange.isOutside(zCross, 3 * errZ), lad.chips[chipID].zRange.getMin(), lad.chips[chipID].zRange.getMax(), xCurr, yCurr, xCross, yCross, zCross, errZ); */ // track Y error in chip frame @@ -2691,10 +2690,10 @@ MatchTPCITS::BracketIR MatchTPCITS::tpcTimeBin2IRBracket(const BracketF tbrange) { // convert TPC timebins bracket to IR bracket o2::InteractionRecord irMin(mStartIR), irMax(mStartIR); - if (tbrange.min() > 0) { - irMin += o2::InteractionRecord(tpcTimeBin2NS(tbrange.min())); + if (tbrange.getMin() > 0) { + irMin += o2::InteractionRecord(tpcTimeBin2NS(tbrange.getMin())); } - irMax += o2::InteractionRecord(tpcTimeBin2NS(tbrange.max())); + irMax += o2::InteractionRecord(tpcTimeBin2NS(tbrange.getMax())); irMax++; // to account for rounding int bc = mClosestBunchAbove[irMin.bc]; if (bc < irMin.bc) { diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h index edfe8b28c219d..9e20895190d7e 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h @@ -32,7 +32,7 @@ namespace its { struct RecoGeomHelper { // - using BracketF = o2::utils::Bracket<float>; + using BracketF = o2::math_utils::Bracket<float>; using Vec2D = o2::utils::IntervalXY; enum Relation : int { Below = -1, @@ -131,7 +131,7 @@ inline int RecoGeomHelper::RecoLayer::getChipID(float z) const { // Get chip ID within the ladder corresponding to this phi // Note: this is an approximate method, one should check also the neighbouring ladders +/-1 - int ic = (z - zRange.min()) * z2chipID; + int ic = (z - zRange.getMin()) * z2chipID; return ic < 0 ? 0 : (ic < lastChipInLadder ? ic : lastChipInLadder); } diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx index 42061b2a5d7c9..c7b4ffa2629b0 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx @@ -30,7 +30,7 @@ void RecoGeomHelper::RecoChip::updateLimits(const Point3D<float>& pntTra) void RecoGeomHelper::RecoChip::print() const { printf("Ch#%4d Alp: %+.3f X:%5.2f %+6.3f<y<%+6.3f %+6.3f<z<%+6.3f | XYEdges: {%+6.3f,%+6.3f}{%+6.3f,%+6.3f}\n", - id, alp, xRef, yRange.min(), yRange.max(), zRange.min(), zRange.max(), + id, alp, xRef, yRange.getMin(), yRange.getMax(), zRange.getMin(), zRange.getMax(), xyEdges.getX0(), xyEdges.getY0(), xyEdges.getX1(), xyEdges.getY1()); } @@ -40,18 +40,18 @@ void RecoGeomHelper::RecoLadder::updateLimits(const Point3D<float>& pntGlo) // update limits from the point in Global frame float phi = pntGlo.phi(); // -pi:pi range o2::utils::BringTo02Pi(phi); // temporary bring to 0:2pi range - o2::utils::BringTo02Pi(phiRange.min()); - o2::utils::BringTo02Pi(phiRange.max()); + o2::utils::BringTo02Pi(phiRange.getMin()); + o2::utils::BringTo02Pi(phiRange.getMax()); phiRange.update(phi); phiMean = phiRange.mean(); dphiH = 0.5 * phiRange.delta(); - if (phiRange.delta() > o2::constants::math::PI) { // wrapping, swap - phiRange.set(phiRange.max(), phiRange.min()); // swap + if (phiRange.delta() > o2::constants::math::PI) { // wrapping, swap + phiRange.set(phiRange.getMax(), phiRange.getMin()); // swap phiMean -= o2::constants::math::PI; dphiH = o2::constants::math::PI - dphiH; } - o2::utils::BringToPMPi(phiRange.min()); // -pi:pi range - o2::utils::BringToPMPi(phiRange.max()); + o2::utils::BringToPMPi(phiRange.getMin()); // -pi:pi range + o2::utils::BringToPMPi(phiRange.getMax()); o2::utils::BringToPMPi(phiMean); // zRange.update(pntGlo.Z()); @@ -77,7 +77,7 @@ void RecoGeomHelper::RecoLadder::print() const { assert(overlapWithNext != Undefined || chips.size() == 0); // make sure there are no undefined ladders after init is done printf("Ladder %3d %.3f<phi[<%.3f>]<%.3f dPhiH:%.3f | XYEdges: {%+6.3f,%+6.3f}{%+6.3f,%+6.3f} | %3d chips | OvlNext: %s\n", - id, phiRange.min(), phiMean, phiRange.max(), dphiH, + id, phiRange.getMin(), phiMean, phiRange.getMax(), dphiH, xyEdges.getX0(), xyEdges.getY0(), xyEdges.getX1(), xyEdges.getY1(), (int)chips.size(), overlapWithNext == Undefined ? "N/A" : ((overlapWithNext == NoOverlap ? "NO" : (overlapWithNext == Above ? "Above" : "Below")))); for (const auto& ch : chips) { @@ -144,7 +144,7 @@ void RecoGeomHelper::RecoLayer::init() // make sure chips within the ladder are ordered in Z, renumber ladders for (int i = nLadders; i--;) { auto& lad = ladders[i]; - std::sort(lad.chips.begin(), lad.chips.end(), [](auto& a, auto& b) { return a.zRange.min() < b.zRange.min(); }); + std::sort(lad.chips.begin(), lad.chips.end(), [](auto& a, auto& b) { return a.zRange.getMin() < b.zRange.getMin(); }); lad.id = i; lad.init(); } @@ -218,7 +218,7 @@ void RecoGeomHelper::RecoLayer::updateLimits(const Point3D<float>& pntGlo) void RecoGeomHelper::RecoLayer::print() const { printf("\nLayer %d %.2f<r<%.2f %+.2f<z<%+.2f %d ladders\n", - id, rRange.min(), rRange.max(), zRange.min(), zRange.max(), (int)ladders.size()); + id, rRange.getMin(), rRange.getMax(), zRange.getMin(), zRange.getMax(), (int)ladders.size()); for (const auto& ld : ladders) { ld.print(); } diff --git a/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h index a8d12a73b2ed8..90d9d7fa6749d 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h @@ -44,7 +44,7 @@ class VertexTrackMatcher using TrackTPC = o2::tpc::TrackTPC; using TmpMap = std::unordered_map<int, std::vector<GIndex>>; using TimeEst = o2::dataformats::TimeStampWithError<float, float>; - using TBracket = o2::utils::Bracket<float>; + using TBracket = o2::math_utils::Bracket<float>; void init(); void process(const gsl::span<const PVertex>& vertices, // vertices diff --git a/Detectors/Vertexing/src/VertexTrackMatcher.cxx b/Detectors/Vertexing/src/VertexTrackMatcher.cxx index 8c6bea353fc8c..a52d70684f8c3 100644 --- a/Detectors/Vertexing/src/VertexTrackMatcher.cxx +++ b/Detectors/Vertexing/src/VertexTrackMatcher.cxx @@ -82,8 +82,8 @@ void VertexTrackMatcher::process(const gsl::span<const PVertex>& vertices, tpcTimes.emplace_back(tpcTimeBin2MUS(trc.getTime0() - trc.getDeltaTBwd()), tpcTimeBin2MUS(trc.getTime0() + trc.getDeltaTFwd())); } std::sort(idTPC.begin(), idTPC.end(), [&tpcTimes](int i, int j) { // sort according to max time - float tI = (i < 0) ? 1e9 : tpcTimes[i].max(); - float tJ = (j < 0) ? 1e9 : tpcTimes[j].max(); + float tI = (i < 0) ? 1e9 : tpcTimes[i].getMax(); + float tJ = (j < 0) ? 1e9 : tpcTimes[j].getMax(); return tI < tJ; }); @@ -244,7 +244,7 @@ void VertexTrackMatcher::attachTPC(TmpMap& tmpMap, const std::vector<TBracket>& itrCurr = itr; } else if (rel == TBracket::Inside) { tmpMap[ivtCurr].emplace_back(idTPC[itr], GIndex::TPC); - } else if (tT.max() - mMaxTPCDriftTimeMUS > tV.max()) { + } else if (tT.getMax() - mMaxTPCDriftTimeMUS > tV.getMax()) { break; } itr++; From 5ba64265b3e041fda5ad930673250d4ab28b751b Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Wed, 7 Oct 2020 15:48:31 +0200 Subject: [PATCH 1028/1751] [math_utils] Merge Cartesian2D/3D Merges `Cartesian2D` and `Cartesian3D` headers into a single `Cartesian` header. Change all includes. --- Common/Field/include/Field/MagFieldFast.h | 3 ++- Common/MathUtils/CMakeLists.txt | 8 +++--- .../MathUtils/{Cartesian3D.h => Cartesian.h} | 9 ++++++- .../MathUtils/include/MathUtils/Cartesian2D.h | 27 ------------------- .../src/{Cartesian3D.cxx => Cartesian.cxx} | 2 +- Common/MathUtils/src/Cartesian2D.cxx | 11 -------- ...{testCartesian3D.cxx => testCartesian.cxx} | 4 +-- .../DetMatrixCache.h | 3 ++- .../DataFormatsEMCAL/AnalysisCluster.h | 2 +- .../include/DataFormatsITSMFT/Cluster.h | 2 +- .../DataFormatsITSMFT/TopologyDictionary.h | 2 +- .../TOF/include/DataFormatsTOF/Cluster.h | 2 +- .../TPC/include/DataFormatsTPC/Defs.h | 3 +-- .../ZDC/include/DataFormatsZDC/RecEvent.h | 2 +- .../ReconstructionDataFormats/BaseCluster.h | 2 +- .../ReconstructionDataFormats/Vertex.h | 2 +- .../include/SimulationDataFormat/BaseHits.h | 2 +- .../simulation/src/DigitizationContext.cxx | 2 +- .../include/DetectorsBase/GeometryManager.h | 2 +- .../include/DetectorsBase/MatLayerCylSet.h | 2 +- Detectors/Base/include/DetectorsBase/Ray.h | 2 +- .../include/CPVSimulation/Detector.h | 2 +- .../base/include/EMCALBase/ClusterFactory.h | 2 +- .../EMCAL/base/include/EMCALBase/Geometry.h | 2 +- Detectors/EMCAL/base/src/ClusterFactory.cxx | 2 +- .../include/EMCALSimulation/Detector.h | 2 +- Detectors/EMCAL/simulation/src/Digitizer.cxx | 2 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 2 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 2 +- .../ITSMFT/ITS/base/src/GeometryTGeo.cxx | 2 +- .../ITSMFT/ITS/macros/test/CheckClusters.C | 2 +- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 2 +- .../ITSMFT/ITS/macros/test/DisplayTrack.C | 2 +- .../include/ITSReconstruction/CookedTracker.h | 2 +- .../ITSReconstruction/RecoGeomHelper.h | 2 +- .../ITS/reconstruction/src/ClustererTask.cxx | 2 +- .../ITSMFT/MFT/base/src/GeometryTGeo.cxx | 2 +- .../ITSMFT/MFT/macros/test/CheckTopologies.C | 2 +- .../tracking/include/MFTTracking/Tracker.h | 2 +- Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx | 2 +- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 2 +- .../include/ITSMFTBase/SegmentationAlpide.h | 2 +- .../common/simulation/src/Digitizer.cxx | 2 +- .../test/HitAnalysis/src/HitAnalysis.cxx | 2 +- .../include/MCHSimulation/Geometry.h | 2 +- .../MCH/Tracking/src/TrackAtVertexSpec.cxx | 2 +- .../MCH/Tracking/src/VertexSamplerSpec.cxx | 2 +- .../include/MIDBase/GeometryTransformer.h | 2 +- .../include/MIDSimulation/Digitizer.h | 2 +- .../MUON/MID/Simulation/test/testGeometry.cxx | 2 +- .../MID/Simulation/test/testSimulation.cxx | 2 +- .../include/MIDTestingSimTools/HitFinder.h | 2 +- .../include/PHOSSimulation/Detector.h | 2 +- Detectors/TOF/base/include/TOFBase/Strip.h | 2 +- .../TOF/reconstruction/src/ClustererTask.cxx | 2 +- Detectors/TPC/base/include/TPCBase/Mapper.h | 3 +-- .../Upgrades/IT3/base/src/GeometryTGeo.cxx | 2 +- .../PostLS4/IT4/base/src/GeometryTGeo.cxx | 2 +- 58 files changed, 68 insertions(+), 101 deletions(-) rename Common/MathUtils/include/MathUtils/{Cartesian3D.h => Cartesian.h} (95%) delete mode 100644 Common/MathUtils/include/MathUtils/Cartesian2D.h rename Common/MathUtils/src/{Cartesian3D.cxx => Cartesian.cxx} (97%) delete mode 100644 Common/MathUtils/src/Cartesian2D.cxx rename Common/MathUtils/test/{testCartesian3D.cxx => testCartesian.cxx} (97%) diff --git a/Common/Field/include/Field/MagFieldFast.h b/Common/Field/include/Field/MagFieldFast.h index 79d9d3c16e0c9..d6e23af7b9141 100644 --- a/Common/Field/include/Field/MagFieldFast.h +++ b/Common/Field/include/Field/MagFieldFast.h @@ -16,7 +16,8 @@ #include <Rtypes.h> #include <string> -#include "MathUtils/Cartesian3D.h" + +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/Common/MathUtils/CMakeLists.txt b/Common/MathUtils/CMakeLists.txt index e1ee3ab4233b2..e8e112dfc8d57 100644 --- a/Common/MathUtils/CMakeLists.txt +++ b/Common/MathUtils/CMakeLists.txt @@ -11,8 +11,7 @@ o2_add_library( MathUtils SOURCES src/CachingTF1.cxx - src/Cartesian2D.cxx - src/Cartesian3D.cxx + src/Cartesian.cxx src/Chebyshev3D.cxx src/Chebyshev3DCalc.cxx src/MathBase.cxx @@ -33,8 +32,7 @@ o2_target_root_dictionary( include/MathUtils/Chebyshev3D.h include/MathUtils/Chebyshev3DCalc.h include/MathUtils/MathBase.h - include/MathUtils/Cartesian2D.h - include/MathUtils/Cartesian3D.h + include/MathUtils/Cartesian.h include/MathUtils/CachingTF1.h include/MathUtils/RandomRing.h include/MathUtils/Primitive2D.h @@ -49,7 +47,7 @@ o2_add_test( o2_add_test( Cartesian3D - SOURCES test/testCartesian3D.cxx + SOURCES test/testCartesian.cxx COMPONENT_NAME MathUtils PUBLIC_LINK_LIBRARIES O2::MathUtils LABELS utils) diff --git a/Common/MathUtils/include/MathUtils/Cartesian3D.h b/Common/MathUtils/include/MathUtils/Cartesian.h similarity index 95% rename from Common/MathUtils/include/MathUtils/Cartesian3D.h rename to Common/MathUtils/include/MathUtils/Cartesian.h index 3305da7ee9edb..6ac11ec6c62b5 100644 --- a/Common/MathUtils/include/MathUtils/Cartesian3D.h +++ b/Common/MathUtils/include/MathUtils/Cartesian.h @@ -20,15 +20,22 @@ #include <Math/GenVector/Rotation3D.h> #include <Math/GenVector/Transform3D.h> #include <Math/GenVector/Translation3D.h> +#include <Math/GenVector/DisplacementVector2D.h> +#include <Math/GenVector/PositionVector2D.h> #include <Rtypes.h> #include <TGeoMatrix.h> #include <iosfwd> -#include "MathUtils/Cartesian2D.h" + +template <typename T> +using Point2D = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +template <typename T> +using Vector2D = ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; template <typename T> using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; template <typename T> using Vector3D = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; + // more typedefs can follow namespace o2 diff --git a/Common/MathUtils/include/MathUtils/Cartesian2D.h b/Common/MathUtils/include/MathUtils/Cartesian2D.h deleted file mode 100644 index 72703ec78404a..0000000000000 --- a/Common/MathUtils/include/MathUtils/Cartesian2D.h +++ /dev/null @@ -1,27 +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. - -/// @file Defs.h -/// @brief Common definitions for 2D coordinates -/// @author Jens Wiechula, Jens.Wiechula@ikf.uni-frankfurt.de - -#ifndef ALICEO2_CARTESIAN2D_H -#define ALICEO2_CARTESIAN2D_H - -#include "Math/GenVector/DisplacementVector2D.h" -#include "Math/GenVector/PositionVector2D.h" - -template <typename T> -using Point2D = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; - -template <typename T> -using Vector2D = ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; - -#endif diff --git a/Common/MathUtils/src/Cartesian3D.cxx b/Common/MathUtils/src/Cartesian.cxx similarity index 97% rename from Common/MathUtils/src/Cartesian3D.cxx rename to Common/MathUtils/src/Cartesian.cxx index cf9e17da9070b..098fe2461fefc 100644 --- a/Common/MathUtils/src/Cartesian3D.cxx +++ b/Common/MathUtils/src/Cartesian.cxx @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "MathUtils/Cartesian3D.h" #include <iostream> +#include "MathUtils/Cartesian.h" using namespace o2; diff --git a/Common/MathUtils/src/Cartesian2D.cxx b/Common/MathUtils/src/Cartesian2D.cxx deleted file mode 100644 index ebdb63375afaa..0000000000000 --- a/Common/MathUtils/src/Cartesian2D.cxx +++ /dev/null @@ -1,11 +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. - -#include "MathUtils/Cartesian2D.h" diff --git a/Common/MathUtils/test/testCartesian3D.cxx b/Common/MathUtils/test/testCartesian.cxx similarity index 97% rename from Common/MathUtils/test/testCartesian3D.cxx rename to Common/MathUtils/test/testCartesian.cxx index 4a4b2303b5ab8..18056020e0f20 100644 --- a/Common/MathUtils/test/testCartesian3D.cxx +++ b/Common/MathUtils/test/testCartesian.cxx @@ -17,11 +17,11 @@ #include <algorithm> #include <memory> #include <cstring> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" using namespace o2; -BOOST_AUTO_TEST_CASE(Cartesian3D_test) +BOOST_AUTO_TEST_CASE(Cartesian_test) { // we create Transform3D by conversion from TGeoHMatrix TGeoRotation rotg("r", 10., 20., 30.); diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h index c2d0b033ead2b..0dcdb9c2b6250 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h @@ -16,8 +16,9 @@ #include <array> #include <vector> + +#include "MathUtils/Cartesian.h" #include "DetectorsCommonDataFormats/DetID.h" -#include "MathUtils/Cartesian3D.h" class TGeoHMatrix; diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h index 365198b608d61..e870bf05ebdfc 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h @@ -15,7 +15,7 @@ #include <gsl/span> #include <array> #include "Rtypes.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "TLorentzVector.h" namespace o2 diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h index 4c77b8095f5c8..ad8e844236533 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/Cluster.h @@ -193,7 +193,7 @@ inline void Cluster::setClusterUsage(Int_t n) /// std::is_trivially_copyable<ROOT::Math::Cartesian3D<float>> fails because the class /// implements a copy constructor, although it does not much more than the default copy /// constructor. Have been trying to specialize std::is_trivially_copyable for Point3D -/// alias in MathUtils/Cartesian3D.h, but structures with a member of Point3D are +/// alias in MathUtils/Cartesian.h, but structures with a member of Point3D are /// still not fulfilling the condition. Need to understand how the type trait checks /// the condition for members. /// We believe that o2::itsmft::Cluster is messageable and explicitly specialize the diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h index 5938126cb7485..8e242f3ef3541 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h @@ -34,7 +34,7 @@ #include <string> #include <unordered_map> #include <vector> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "DataFormatsITSMFT/CompCluster.h" #include "TH1F.h" diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h index 0920bbcc9e846..d966dfee52903 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h @@ -136,7 +136,7 @@ std::ostream& operator<<(std::ostream& os, Cluster& c); /// std::is_trivially_copyable<ROOT::Math::Cartesian3D<float>> fails because the class /// implements a copy constructor, although it does not much more than the default copy /// constructor. Have been trying to specialize std::is_trivially_copyable for Point3D -/// alias in MathUtils/Cartesian3D.h, but structures with a member of Point3D are +/// alias in MathUtils/Cartesian.h, but structures with a member of Point3D are /// still not fulfilling the condition. Need to understand how the type trait checks /// the condition for members. /// We believe that o2::tof::Cluster is messageable and explicitly specialize the diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h index f9a4b8967e2d4..45b9430f7e56e 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h @@ -24,8 +24,7 @@ #include "GPUROOTCartesianFwd.h" #ifndef GPUCA_ALIGPUCODE -#include "MathUtils/Cartesian2D.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #endif namespace o2 diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h index 041e27702d432..985adb8d86987 100644 --- a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h @@ -12,7 +12,7 @@ #define _ZDC_RECEVENT_H_ #include "CommonDataFormat/InteractionRecord.h" -#include "MathUtils/Cartesian2D.h" +#include "MathUtils/Cartesian.h" #include "ZDCBase/Constants.h" #include <Rtypes.h> #include <array> diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h index d00ac377ebcc7..7568bb8568ee3 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h @@ -11,13 +11,13 @@ #ifndef ALICEO2_BASE_BASECLUSTER_H #define ALICEO2_BASE_BASECLUSTER_H +#include <MathUtils/Cartesian.h> #include <TObject.h> #include <bitset> #include <iomanip> #include <ios> #include <iosfwd> #include "DetectorsCommonDataFormats/DetMatrixCache.h" -#include "MathUtils/Cartesian3D.h" namespace o2 { diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h index 9749d75c64c71..e62f243bd7e42 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h @@ -11,7 +11,7 @@ #ifndef ALICEO2_VERTEX_H #define ALICEO2_VERTEX_H -#include "MathUtils/Cartesian3D.h" +#include <MathUtils/Cartesian.h> #include "CommonDataFormat/TimeStamp.h" #ifndef __OPENCL__ #include <array> diff --git a/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h b/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h index ce757ced13d63..c29596c6e6572 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h +++ b/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h @@ -10,7 +10,7 @@ #ifndef ALICEO2_BASE_HIT_H #define ALICEO2_BASE_HIT_H -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/DataFormats/simulation/src/DigitizationContext.cxx b/DataFormats/simulation/src/DigitizationContext.cxx index fdd35354909b0..0414e45122ab8 100644 --- a/DataFormats/simulation/src/DigitizationContext.cxx +++ b/DataFormats/simulation/src/DigitizationContext.cxx @@ -15,7 +15,7 @@ #include <TFile.h> #include <iostream> #include <numeric> // for iota -#include <MathUtils/Cartesian3D.h> +#include <MathUtils/Cartesian.h> using namespace o2::steer; diff --git a/Detectors/Base/include/DetectorsBase/GeometryManager.h b/Detectors/Base/include/DetectorsBase/GeometryManager.h index 8b5354f208002..0c14ff7b9dd39 100644 --- a/Detectors/Base/include/DetectorsBase/GeometryManager.h +++ b/Detectors/Base/include/DetectorsBase/GeometryManager.h @@ -23,7 +23,7 @@ #include <string_view> #include "DetectorsCommonDataFormats/DetID.h" #include "FairLogger.h" // for LOG -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "DetectorsBase/MatCell.h" #include <mutex> class TGeoHMatrix; // lines 11-11 diff --git a/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h b/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h index 5c8e741a7a1c0..8170a4d4fe71b 100644 --- a/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h +++ b/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h @@ -20,7 +20,7 @@ #include "FlatObject.h" #ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #endif // !GPUCA_ALIGPUCODE /********************************************************************** diff --git a/Detectors/Base/include/DetectorsBase/Ray.h b/Detectors/Base/include/DetectorsBase/Ray.h index 3e4752a82b720..ba740750bb445 100644 --- a/Detectors/Base/include/DetectorsBase/Ray.h +++ b/Detectors/Base/include/DetectorsBase/Ray.h @@ -21,7 +21,7 @@ #include "MathUtils/Utils.h" #ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #endif // !GPUCA_ALIGPUCODE /********************************************************************** diff --git a/Detectors/CPV/simulation/include/CPVSimulation/Detector.h b/Detectors/CPV/simulation/include/CPVSimulation/Detector.h index 6f174e0d729bb..a97b0516b540e 100644 --- a/Detectors/CPV/simulation/include/CPVSimulation/Detector.h +++ b/Detectors/CPV/simulation/include/CPVSimulation/Detector.h @@ -12,7 +12,7 @@ #define ALICEO2_CPV_DETECTOR_H_ #include "DetectorsBase/Detector.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "CPVBase/Hit.h" #include "RStringView.h" #include "Rtypes.h" diff --git a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h index d6e0e1e1ec99a..088a8cb796292 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h +++ b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h @@ -18,7 +18,7 @@ #include "DataFormatsEMCAL/Cell.h" #include "DataFormatsEMCAL/AnalysisCluster.h" #include "EMCALBase/Geometry.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h index 74324f6b0f366..9391ca611829e 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h @@ -24,7 +24,7 @@ #include "DataFormatsEMCAL/Constants.h" #include "EMCALBase/GeometryBase.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/Detectors/EMCAL/base/src/ClusterFactory.cxx b/Detectors/EMCAL/base/src/ClusterFactory.cxx index 54b7942cbde67..e1d144a1ebbc1 100644 --- a/Detectors/EMCAL/base/src/ClusterFactory.cxx +++ b/Detectors/EMCAL/base/src/ClusterFactory.cxx @@ -18,7 +18,7 @@ #include "DataFormatsEMCAL/AnalysisCluster.h" #include "DataFormatsEMCAL/Constants.h" #include "EMCALBase/Geometry.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "EMCALBase/ClusterFactory.h" diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h index ff02d1f024d57..adf0a80c3950a 100644 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h +++ b/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h @@ -14,7 +14,7 @@ #include "DetectorsBase/Detector.h" #include "EMCALBase/Hit.h" #include "EMCALBase/GeometryBase.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "RStringView.h" #include "Rtypes.h" #include <vector> diff --git a/Detectors/EMCAL/simulation/src/Digitizer.cxx b/Detectors/EMCAL/simulation/src/Digitizer.cxx index 3282094477e97..a5592ca60054f 100644 --- a/Detectors/EMCAL/simulation/src/Digitizer.cxx +++ b/Detectors/EMCAL/simulation/src/Digitizer.cxx @@ -14,7 +14,7 @@ #include "EMCALBase/Geometry.h" #include "EMCALBase/GeometryBase.h" #include "EMCALBase/Hit.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "SimulationDataFormat/MCCompLabel.h" #include <climits> diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index ec58d5f1adc94..0b52c78eac0bb 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -19,7 +19,7 @@ #include "DetectorsBase/Propagator.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" #include "CommonConstants/MathConstants.h" #include "CommonConstants/PhysicsConstants.h" diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index ae95d34c65264..66ebe19a9431d 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -24,7 +24,7 @@ #include "TPCBase/ParameterElectronics.h" #include "TPCBase/ParameterDetector.h" #include "TPCBase/ParameterGas.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" #include "CommonConstants/MathConstants.h" #include "CommonConstants/PhysicsConstants.h" diff --git a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx index 5f3e13e0bb2a1..af38ba4929eb9 100644 --- a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx @@ -18,7 +18,7 @@ #include "ITSBase/GeometryTGeo.h" #include "DetectorsBase/GeometryManager.h" #include "ITSMFTBase/SegmentationAlpide.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "FairLogger.h" // for LOG diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C b/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C index e926af4580898..c1ac87a9ff933 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C @@ -15,7 +15,7 @@ #include "DataFormatsITSMFT/TopologyDictionary.h" #include "ITSMFTSimulation/Hit.h" #include "DataFormatsITSMFT/ROFRecord.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index e51b082aec6dd..f957c76f6f56c 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -23,7 +23,7 @@ #include "DataFormatsITSMFT/ClusterTopology.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "ITSMFTSimulation/Hit.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "DetectorsCommonDataFormats/NameConf.h" diff --git a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C index 8bbb8628cc4d3..3d52a8dd475db 100644 --- a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C +++ b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C @@ -22,7 +22,7 @@ #include "ITSMFTSimulation/Hit.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITS/TrackITS.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h index c998efa35a048..6a4cfd2b36fd9 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/CookedTracker.h @@ -23,7 +23,7 @@ #include <vector> #include <tuple> #include "ITSBase/GeometryTGeo.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "DataFormatsITSMFT/Cluster.h" #include "DataFormatsITS/TrackITS.h" #include "DataFormatsITSMFT/ROFRecord.h" diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h index 9e20895190d7e..5c89b3e8a73b7 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h @@ -18,7 +18,7 @@ #include <Rtypes.h> #include <vector> #include <array> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" #include "MathUtils/Primitive2D.h" #include "CommonConstants/MathConstants.h" diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx index 93f4fd5b5987b..9b22defce827e 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx @@ -13,7 +13,7 @@ #include "DetectorsCommonDataFormats/DetID.h" #include "ITSReconstruction/ClustererTask.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" #include "FairLogger.h" #include <TFile.h> diff --git a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx index 0fe8dea7a0639..88a27a07881c1 100644 --- a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx @@ -18,7 +18,7 @@ #include "MFTBase/GeometryTGeo.h" #include "DetectorsBase/GeometryManager.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "FairLogger.h" // for LOG diff --git a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C index f23568d16510b..c617502c16be3 100644 --- a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C @@ -23,7 +23,7 @@ #include "DataFormatsITSMFT/ClusterTopology.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "ITSMFTSimulation/Hit.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "DetectorsCommonDataFormats/NameConf.h" diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index e72b66536d2a9..49e3315e8799e 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -20,7 +20,7 @@ #include "MFTTracking/Cluster.h" #include "MathUtils/Utils.h" -#include "MathUtils/Cartesian2D.h" +#include "MathUtils/Cartesian.h" #include "DataFormatsMFT/TrackMFT.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx index 004d7522232b8..c53f6904d7acd 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx @@ -15,7 +15,7 @@ #include "MFTTracking/IndexTableUtils.h" #include "MathUtils/Utils.h" -#include "MathUtils/Cartesian2D.h" +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index 568b5ac14c83c..b077fb2301a6c 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -25,7 +25,7 @@ #include "DataFormatsITSMFT/CompCluster.h" #include "DataFormatsITSMFT/TopologyDictionary.h" #include "MathUtils/Utils.h" -#include "MathUtils/Cartesian2D.h" +#include "MathUtils/Cartesian.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h b/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h index 6e80d92560feb..34db8f6c6f073 100644 --- a/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h +++ b/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h @@ -15,7 +15,7 @@ #define ALICEO2_ITSMFT_SEGMENTATIONALPIDE_H_ #include <Rtypes.h> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx b/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx index 8bb45bdb97922..3155e181a7d17 100644 --- a/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx +++ b/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx @@ -14,7 +14,7 @@ #include "DataFormatsITSMFT/Digit.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "ITSMFTSimulation/Digitizer.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "SimulationDataFormat/MCTruthContainer.h" #include <TRandom.h> diff --git a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx index d5f520fa9cfd3..293af7ca2e2c4 100644 --- a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx +++ b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx @@ -27,7 +27,7 @@ #include "ITSBase/GeometryTGeo.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "ITSMFTSimulation/Hit.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" using Segmentation = o2::itsmft::SegmentationAlpide; diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h index 958ec940a117d..bc9b04b4d3c46 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h +++ b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h @@ -16,7 +16,7 @@ #include <vector> #include <iostream> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" class TGeoVolume; class TGeoManager; diff --git a/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx index 6456f5ecf7b93..2fa2019dc80e3 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx @@ -31,7 +31,7 @@ #include "Framework/Task.h" #include "DetectorsBase/GeometryManager.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "Field/MagneticField.h" #include "MCHBase/ClusterBlock.h" #include "MCHBase/TrackBlock.h" diff --git a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx b/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx index a0cae8c3f10cb..852fe3805f9b7 100644 --- a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx @@ -30,7 +30,7 @@ #include "Framework/Task.h" #include "Framework/Logger.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h b/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h index de4797f90e7cd..f7dcc753b1617 100644 --- a/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h +++ b/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h @@ -18,7 +18,7 @@ #include <array> #include "MIDBase/DetectorParameters.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" class TGeoManager; diff --git a/Detectors/MUON/MID/Simulation/include/MIDSimulation/Digitizer.h b/Detectors/MUON/MID/Simulation/include/MIDSimulation/Digitizer.h index a9963b1978601..e1165f727198d 100644 --- a/Detectors/MUON/MID/Simulation/include/MIDSimulation/Digitizer.h +++ b/Detectors/MUON/MID/Simulation/include/MIDSimulation/Digitizer.h @@ -18,7 +18,7 @@ #include <random> #include <vector> #include <array> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "MIDBase/Mapping.h" #include "MIDBase/GeometryTransformer.h" diff --git a/Detectors/MUON/MID/Simulation/test/testGeometry.cxx b/Detectors/MUON/MID/Simulation/test/testGeometry.cxx index 2a8e5a973cfda..591366f3eb13a 100644 --- a/Detectors/MUON/MID/Simulation/test/testGeometry.cxx +++ b/Detectors/MUON/MID/Simulation/test/testGeometry.cxx @@ -22,7 +22,7 @@ #include <boost/test/data/test_case.hpp> #include <fstream> #include <iostream> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "TGeoManager.h" #include "MIDSimulation/Geometry.h" #include "MIDBase/GeometryTransformer.h" diff --git a/Detectors/MUON/MID/Simulation/test/testSimulation.cxx b/Detectors/MUON/MID/Simulation/test/testSimulation.cxx index 663a6fdccf13e..3878f7cd6d12f 100644 --- a/Detectors/MUON/MID/Simulation/test/testSimulation.cxx +++ b/Detectors/MUON/MID/Simulation/test/testSimulation.cxx @@ -14,7 +14,7 @@ #include <boost/test/data/test_case.hpp> #include <sstream> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "CommonConstants/LHCConstants.h" #include "DataFormatsMID/Cluster2D.h" #include "DataFormatsMID/Cluster3D.h" diff --git a/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h b/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h index 239a8c5921f75..73b165036f2ed 100644 --- a/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h +++ b/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h @@ -16,7 +16,7 @@ #ifndef O2_MID_HITFINDER_H #define O2_MID_HITFINDER_H -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "DataFormatsMID/Cluster2D.h" #include "DataFormatsMID/Track.h" #include "MIDBase/GeometryTransformer.h" diff --git a/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h b/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h index aa3629d05b684..f517c34c326e4 100644 --- a/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h +++ b/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h @@ -12,7 +12,7 @@ #define ALICEO2_PHOS_DETECTOR_H_ #include "DetectorsBase/Detector.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "PHOSBase/Hit.h" #include "RStringView.h" #include "Rtypes.h" diff --git a/Detectors/TOF/base/include/TOFBase/Strip.h b/Detectors/TOF/base/include/TOFBase/Strip.h index e4df3fa9fe4ef..cee8e62756864 100644 --- a/Detectors/TOF/base/include/TOFBase/Strip.h +++ b/Detectors/TOF/base/include/TOFBase/Strip.h @@ -22,7 +22,7 @@ #include <map> #include <sstream> #include <vector> -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" namespace o2 { diff --git a/Detectors/TOF/reconstruction/src/ClustererTask.cxx b/Detectors/TOF/reconstruction/src/ClustererTask.cxx index 9bb588bef2efe..0c74c75daced8 100644 --- a/Detectors/TOF/reconstruction/src/ClustererTask.cxx +++ b/Detectors/TOF/reconstruction/src/ClustererTask.cxx @@ -12,7 +12,7 @@ /// \brief Implementation of the TOF cluster finder task #include "TOFReconstruction/ClustererTask.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "MathUtils/Utils.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" diff --git a/Detectors/TPC/base/include/TPCBase/Mapper.h b/Detectors/TPC/base/include/TPCBase/Mapper.h index 21267afc949fa..88ce03706bbd8 100644 --- a/Detectors/TPC/base/include/TPCBase/Mapper.h +++ b/Detectors/TPC/base/include/TPCBase/Mapper.h @@ -27,8 +27,7 @@ #include "TPCBase/PartitionInfo.h" #include "TPCBase/Sector.h" -#include "MathUtils/Cartesian2D.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" // using o2::tpc::PadRegionInfo; // using o2::tpc::PartitionInfo; diff --git a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx index d73e809e8f1be..d661cf725f672 100644 --- a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx @@ -18,7 +18,7 @@ #include "ITS3Base/GeometryTGeo.h" #include "DetectorsBase/GeometryManager.h" #include "ITSMFTBase/SegmentationAlpide.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "FairLogger.h" // for LOG diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx index b56970ed1eba9..b81ff05d88717 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx @@ -18,7 +18,7 @@ #include "ITS4Base/GeometryTGeo.h" #include "DetectorsBase/GeometryManager.h" #include "ITSMFTBase/SegmentationAlpide.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "FairLogger.h" // for LOG From 685f3a7bb0934467eef5dcb6eeacc69f9dc29367 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Thu, 8 Oct 2020 11:09:58 +0200 Subject: [PATCH 1029/1751] [math_utils] Cartesian into math_utils ns Move all classes from the `Cartesian` header to the `math_utils` namespace. Change all affected code. --- .../Core/include/Analysis/trackUtilities.h | 2 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 2 +- Common/Field/include/Field/MagFieldFast.h | 6 ++-- Common/Field/src/MagFieldFast.cxx | 6 ++-- .../MathUtils/include/MathUtils/Cartesian.h | 13 +++++--- Common/MathUtils/src/Cartesian.cxx | 14 ++++++--- Common/MathUtils/src/MathUtilsLinkDef.h | 6 ++-- Common/MathUtils/test/testCartesian.cxx | 12 ++++---- .../DetMatrixCache.h | 10 +++---- .../Detectors/Common/src/DetMatrixCache.cxx | 4 +-- .../src/DetectorsCommonDataFormatsLinkDef.h | 4 +-- .../DataFormatsEMCAL/AnalysisCluster.h | 26 ++++++++-------- .../Detectors/EMCAL/src/AnalysisCluster.cxx | 6 ++-- .../FIT/FV0/include/DataFormatsFV0/Hit.h | 26 ++++++++-------- .../DataFormatsITSMFT/TopologyDictionary.h | 4 +-- .../ITSMFT/common/src/TopologyDictionary.cxx | 8 ++--- .../TPC/include/DataFormatsTPC/Defs.h | 10 +++---- .../ZDC/include/DataFormatsZDC/RecEvent.h | 4 +-- .../ReconstructionDataFormats/BaseCluster.h | 21 +++++++------ .../TrackParametrization.h | 14 ++++----- .../ReconstructionDataFormats/Vertex.h | 22 +++++++------- .../src/TrackParametrization.cxx | 2 +- .../Reconstruction/test/testVertex.cxx | 2 +- .../include/SimulationDataFormat/BaseHits.h | 12 ++++---- .../simulation/src/DigitizationContext.cxx | 4 +-- .../include/DetectorsBase/GeometryManager.h | 8 ++--- .../include/DetectorsBase/MatLayerCylSet.h | 2 +- .../Base/include/DetectorsBase/Propagator.h | 6 ++-- Detectors/Base/include/DetectorsBase/Ray.h | 4 +-- Detectors/Base/src/Propagator.cxx | 14 ++++----- Detectors/Base/test/README.md | 2 +- Detectors/CPV/base/include/CPVBase/Hit.h | 2 +- .../include/CPVSimulation/Detector.h | 2 +- Detectors/CPV/simulation/src/Detector.cxx | 4 +-- .../EMCAL/base/include/EMCALBase/Geometry.h | 12 ++++---- Detectors/EMCAL/base/include/EMCALBase/Hit.h | 10 +++---- Detectors/EMCAL/base/src/ClusterFactory.cxx | 8 ++--- Detectors/EMCAL/base/src/Geometry.cxx | 30 +++++++++---------- .../include/EMCALSimulation/Detector.h | 2 +- Detectors/EMCAL/simulation/src/Detector.cxx | 8 ++--- .../include/FV0Simulation/Detector.h | 4 +-- Detectors/FIT/FV0/simulation/src/Detector.cxx | 10 +++---- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 2 +- .../ITS/base/include/ITSBase/GeometryTGeo.h | 8 ++--- .../ITSMFT/ITS/base/src/GeometryTGeo.cxx | 8 ++--- .../ITSMFT/ITS/macros/EVE/DisplayEventsComp.C | 4 +-- .../ITSMFT/ITS/macros/test/CheckClusters.C | 8 ++--- .../ITSMFT/ITS/macros/test/CheckDigits.C | 4 +-- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 4 +-- .../ITSMFT/ITS/macros/test/DisplayTrack.C | 2 +- .../ITSReconstruction/RecoGeomHelper.h | 6 ++-- .../ITS/reconstruction/src/CookedTracker.cxx | 4 +-- .../ITS/reconstruction/src/RecoGeomHelper.cxx | 10 +++---- .../reconstruction/src/TrivialVertexer.cxx | 2 +- .../tracking/include/ITStracking/Vertexer.h | 2 +- Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx | 10 +++---- .../ITS/workflow/src/CookedTrackerSpec.cxx | 4 +-- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 6 ++-- .../MFT/base/include/MFTBase/GeometryTGeo.h | 8 ++--- .../ITSMFT/MFT/base/src/GeometryTGeo.cxx | 8 ++--- .../ITSMFT/MFT/macros/test/CheckTopologies.C | 4 +-- .../MFT/simulation/src/DigitizerTask.cxx | 2 +- .../tracking/include/MFTTracking/Tracker.h | 2 +- Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx | 4 +-- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 6 ++-- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 4 +-- .../include/ITSMFTBase/SegmentationAlpide.h | 8 ++--- .../simulation/include/ITSMFTSimulation/Hit.h | 16 +++++----- .../common/simulation/src/Digitizer.cxx | 8 ++--- .../test/HitAnalysis/src/HitAnalysis.cxx | 2 +- .../include/MCHSimulation/Geometry.h | 2 +- .../Simulation/include/MCHSimulation/Hit.h | 8 ++--- .../MUON/MCH/Simulation/src/Digitizer.cxx | 4 +-- .../MUON/MCH/Simulation/src/Geometry.cxx | 4 +-- .../MUON/MCH/Simulation/src/GeometryTest.cxx | 22 +++++++------- Detectors/MUON/MCH/Simulation/src/Stepper.cxx | 2 +- Detectors/MUON/MCH/Simulation/src/Stepper.h | 2 +- .../MCH/Simulation/test/testDigitization.cxx | 16 +++++----- .../MUON/MCH/Simulation/test/testGeometry.cxx | 4 +-- .../MCH/Tracking/src/TrackAtVertexSpec.cxx | 10 +++---- .../MCH/Tracking/src/VertexSamplerSpec.cxx | 4 +-- .../include/MIDBase/GeometryTransformer.h | 18 +++++------ .../MUON/MID/Base/src/GeometryTransformer.cxx | 2 +- .../Simulation/include/MIDSimulation/Hit.h | 10 +++---- .../include/MIDSimulation/Stepper.h | 2 +- .../MUON/MID/Simulation/src/Digitizer.cxx | 2 +- Detectors/MUON/MID/Simulation/src/Hit.cxx | 6 ++-- Detectors/MUON/MID/Simulation/src/Stepper.cxx | 2 +- .../MUON/MID/Simulation/test/testGeometry.cxx | 2 +- .../MID/Simulation/test/testSimulation.cxx | 4 +-- .../include/MIDTestingSimTools/HitFinder.h | 2 +- .../MID/TestingSimTools/src/HitFinder.cxx | 12 ++++---- Detectors/PHOS/base/include/PHOSBase/Hit.h | 6 ++-- .../include/PHOSSimulation/Detector.h | 2 +- Detectors/PHOS/simulation/src/Detector.cxx | 4 +-- Detectors/TOF/base/include/TOFBase/Strip.h | 2 +- Detectors/TPC/base/test/testTPCBase.cxx | 2 +- .../simulation/include/TPCSimulation/Point.h | 8 ++--- Detectors/TRD/base/src/TRDGeometry.cxx | 20 ++++++------- .../IT3/base/include/ITS3Base/GeometryTGeo.h | 8 ++--- .../Upgrades/IT3/base/src/GeometryTGeo.cxx | 8 ++--- .../IT4/base/include/ITS4Base/GeometryTGeo.h | 8 ++--- .../PostLS4/IT4/base/src/GeometryTGeo.cxx | 8 ++--- .../include/ZDCSimulation/Detector.h | 14 ++++----- .../simulation/include/ZDCSimulation/Hit.h | 8 ++--- Detectors/ZDC/simulation/src/Detector.cxx | 26 ++++++++-------- .../Detectors/src/DataInterpreterITS.cxx | 2 +- GPU/Common/GPUROOTCartesianFwd.h | 9 ++++++ GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx | 10 +++---- .../src/ITSMFTDigitizerSpec.cxx | 2 +- macro/CheckDigits_mft.C | 4 +-- macro/run_primary_vertexer_ITS.C | 4 +-- macro/run_trac_ca_its.C | 4 +-- macro/run_trac_its.C | 2 +- 114 files changed, 422 insertions(+), 403 deletions(-) diff --git a/Analysis/Core/include/Analysis/trackUtilities.h b/Analysis/Core/include/Analysis/trackUtilities.h index ec32f5210e11f..14a8a0a7227b5 100644 --- a/Analysis/Core/include/Analysis/trackUtilities.h +++ b/Analysis/Core/include/Analysis/trackUtilities.h @@ -49,7 +49,7 @@ o2::track::TrackParCov getTrackParCov(const T& track) template <typename T> o2::dataformats::VertexBase getPrimaryVertex(const T& collision) { - Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); + o2::math_utils::Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); std::array<float, 6> vtxCov{collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}; return o2::dataformats::VertexBase{std::move(vtxXYZ), std::move(vtxCov)}; } diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 004e58933179d..7f2e03fbbdad2 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -55,7 +55,7 @@ struct SelectTracks { void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) { - Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); + math_utils::Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); for (auto& track : tracks) { int status_2prong = 1; // selection flag int status_3prong = 1; // selection flag diff --git a/Common/Field/include/Field/MagFieldFast.h b/Common/Field/include/Field/MagFieldFast.h index d6e23af7b9141..d9215fedf559f 100644 --- a/Common/Field/include/Field/MagFieldFast.h +++ b/Common/Field/include/Field/MagFieldFast.h @@ -50,11 +50,11 @@ class MagFieldFast bool Field(const double xyz[3], double bxyz[3]) const; bool Field(const float xyz[3], float bxyz[3]) const; - bool Field(const Point3D<float> xyz, float bxyz[3]) const; + bool Field(const math_utils::Point3D<float> xyz, float bxyz[3]) const; bool GetBcomp(EDim comp, const double xyz[3], double& b) const; bool GetBcomp(EDim comp, const float xyz[3], float& b) const; - bool GetBcomp(EDim comp, const Point3D<float> xyz, double& b) const; - bool GetBcomp(EDim comp, const Point3D<float> xyz, float& b) const; + bool GetBcomp(EDim comp, const math_utils::Point3D<float> xyz, double& b) const; + bool GetBcomp(EDim comp, const math_utils::Point3D<float> xyz, float& b) const; bool GetBx(const double xyz[3], double& bx) const { return GetBcomp(kX, xyz, bx); } bool GetBx(const float xyz[3], float& bx) const { return GetBcomp(kX, xyz, bx); } diff --git a/Common/Field/src/MagFieldFast.cxx b/Common/Field/src/MagFieldFast.cxx index aabbb4d016b01..ffc1da28e1d75 100644 --- a/Common/Field/src/MagFieldFast.cxx +++ b/Common/Field/src/MagFieldFast.cxx @@ -138,7 +138,7 @@ bool MagFieldFast::GetBcomp(EDim comp, const double xyz[3], double& b) const } //_______________________________________________________________________ -bool MagFieldFast::GetBcomp(EDim comp, const Point3D<float> xyz, double& b) const +bool MagFieldFast::GetBcomp(EDim comp, const math_utils::Point3D<float> xyz, double& b) const { // get field int zSeg, rSeg, quadrant; @@ -152,7 +152,7 @@ bool MagFieldFast::GetBcomp(EDim comp, const Point3D<float> xyz, double& b) cons } //_______________________________________________________________________ -bool MagFieldFast::GetBcomp(EDim comp, const Point3D<float> xyz, float& b) const +bool MagFieldFast::GetBcomp(EDim comp, const math_utils::Point3D<float> xyz, float& b) const { // get field int zSeg, rSeg, quadrant; @@ -196,7 +196,7 @@ bool MagFieldFast::Field(const float xyz[3], float bxyz[3]) const } //_______________________________________________________________________ -bool MagFieldFast::Field(const Point3D<float> xyz, float bxyz[3]) const +bool MagFieldFast::Field(const math_utils::Point3D<float> xyz, float bxyz[3]) const { // get field int zSeg, rSeg, quadrant; diff --git a/Common/MathUtils/include/MathUtils/Cartesian.h b/Common/MathUtils/include/MathUtils/Cartesian.h index 6ac11ec6c62b5..91e3b0732e872 100644 --- a/Common/MathUtils/include/MathUtils/Cartesian.h +++ b/Common/MathUtils/include/MathUtils/Cartesian.h @@ -26,6 +26,12 @@ #include <TGeoMatrix.h> #include <iosfwd> +namespace o2 +{ + +namespace math_utils +{ + template <typename T> using Point2D = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; template <typename T> @@ -38,8 +44,6 @@ using Vector3D = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<T>, RO // more typedefs can follow -namespace o2 -{ /// predefined transformations: Tracking->Local, Tracking->Global, Local->Global etc /// The IDs must be < 32 @@ -229,9 +233,10 @@ class Transform3D : public ROOT::Math::Transform3D ClassDefNV(Transform3D, 1); }; +} // namespace math_utils } // namespace o2 -std::ostream& operator<<(std::ostream& os, const o2::Rotation2D& t); +std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2D& t); namespace std { @@ -248,7 +253,7 @@ namespace std /// This is a workaround, we will also make suggestions to fix the cause in ROOT itself /// TODO: delete once it is fixed in ROOT template <typename T> -struct is_trivially_copyable<Point3D<T>> : std::true_type { +struct is_trivially_copyable<o2::math_utils::Point3D<T>> : std::true_type { }; } // namespace std #endif diff --git a/Common/MathUtils/src/Cartesian.cxx b/Common/MathUtils/src/Cartesian.cxx index 098fe2461fefc..c51daeb2f0474 100644 --- a/Common/MathUtils/src/Cartesian.cxx +++ b/Common/MathUtils/src/Cartesian.cxx @@ -11,10 +11,13 @@ #include <iostream> #include "MathUtils/Cartesian.h" -using namespace o2; +ClassImp(o2::math_utils::Transform3D); +ClassImp(o2::math_utils::Rotation2D); -ClassImp(o2::Transform3D); -ClassImp(o2::Rotation2D); +namespace o2 +{ +namespace math_utils +{ //_________________________________________________ Transform3D::Transform3D(const TGeoMatrix& m) @@ -45,8 +48,11 @@ void Transform3D::print() const std::cout << *this << std::endl; } +} // namespace math_utils +} // namespace o2 + //_________________________________________________ -std::ostream& operator<<(std::ostream& os, const o2::Rotation2D& t) +std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2D& t) { float cs, sn; t.getComponents(cs, sn); diff --git a/Common/MathUtils/src/MathUtilsLinkDef.h b/Common/MathUtils/src/MathUtilsLinkDef.h index 23acd7c864bca..0465b7dbbfb89 100644 --- a/Common/MathUtils/src/MathUtilsLinkDef.h +++ b/Common/MathUtils/src/MathUtilsLinkDef.h @@ -12,7 +12,7 @@ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; -#pragma link C++ enum o2::TransformType; +#pragma link C++ enum o2::math_utils::TransformType; #pragma link C++ class o2::math_utils::Chebyshev3D + ; #pragma link C++ class o2::math_utils::Chebyshev3DCalc + ; @@ -29,8 +29,8 @@ #pragma link C++ function o2::math_utils::math_base::getStatisticsData < double>; #pragma link C++ function o2::math_utils::math_base::getStatisticsData < short>; -#pragma link C++ class o2::Transform3D + ; -#pragma link C++ class o2::Rotation2D + ; +#pragma link C++ class o2::math_utils::Transform3D + ; +#pragma link C++ class o2::math_utils::Rotation2D + ; #pragma link C++ class o2::base::CachingTF1 + ; #pragma link C++ class o2::utils::CircleXY + ; diff --git a/Common/MathUtils/test/testCartesian.cxx b/Common/MathUtils/test/testCartesian.cxx index 18056020e0f20..da17623d5fdc3 100644 --- a/Common/MathUtils/test/testCartesian.cxx +++ b/Common/MathUtils/test/testCartesian.cxx @@ -29,13 +29,13 @@ BOOST_AUTO_TEST_CASE(Cartesian_test) TGeoHMatrix hmat = trag; hmat *= rotg; - Transform3D tr(hmat); - Point3D<double> pd(10., 20., 30.); - Point3D<float> pf(10.f, 20.f, 30.f); + math_utils::Transform3D tr(hmat); + math_utils::Point3D<double> pd(10., 20., 30.); + math_utils::Point3D<float> pf(10.f, 20.f, 30.f); // // local to master auto pdt = tr(pd); // operator form - Point3D<float> pft; + math_utils::Point3D<float> pft; tr.LocalToMaster(pf, pft); // TGeoHMatrix form std::cout << "Create Transform3D " << std::endl @@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE(Cartesian_test) // inverse transform auto pfti = tr ^ (pft); // operator form - Point3D<double> pdti; + math_utils::Point3D<double> pdti; tr.MasterToLocal(pdt, pdti); // TGeoHMatrix form std::cout << " Transforming back to local" << std::endl; @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(Cartesian_test) BOOST_AUTO_TEST_CASE(Point3D_messageable) { - using ElementType = Point3D<int>; + using ElementType = math_utils::Point3D<int>; static_assert(std::is_trivially_copyable<ElementType>::value == true); std::vector<ElementType> pts(10); auto makeElement = [](int idx) { diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h index 0dcdb9c2b6250..70b4010269c69 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h @@ -28,7 +28,7 @@ namespace detectors { /// MatrixCache is a vector of cached transform matrices (per sensor) for specific Transformation type -template <typename T = o2::Transform3D> +template <typename T = o2::math_utils::Transform3D> class MatrixCache { // matrices (per sensor) for specific transformation type @@ -73,8 +73,8 @@ class MatrixCache class DetMatrixCache { public: - typedef o2::Transform3D Mat3D; - typedef o2::Rotation2D Rot2D; + typedef o2::math_utils::Transform3D Mat3D; + typedef o2::math_utils::Rotation2D Rot2D; DetMatrixCache() = default; DetMatrixCache(const o2::detectors::DetID& id) : mDetID(id) {} @@ -129,8 +129,8 @@ class DetMatrixCache class DetMatrixCacheIndirect : private DetMatrixCache { public: - typedef o2::Transform3D Mat3D; - typedef o2::Rotation2D Rot2D; + typedef o2::math_utils::Transform3D Mat3D; + typedef o2::math_utils::Rotation2D Rot2D; DetMatrixCacheIndirect() = default; DetMatrixCacheIndirect(const o2::detectors::DetID& id) : DetMatrixCache(id) {} diff --git a/DataFormats/Detectors/Common/src/DetMatrixCache.cxx b/DataFormats/Detectors/Common/src/DetMatrixCache.cxx index ed17514b2e480..ca14e42ba9f95 100644 --- a/DataFormats/Detectors/Common/src/DetMatrixCache.cxx +++ b/DataFormats/Detectors/Common/src/DetMatrixCache.cxx @@ -15,8 +15,8 @@ using namespace o2::detectors; using namespace o2::utils; -ClassImp(o2::detectors::MatrixCache<o2::Transform3D>); -ClassImp(o2::detectors::MatrixCache<o2::Rotation2D>); +ClassImp(o2::detectors::MatrixCache<o2::math_utils::Transform3D>); +ClassImp(o2::detectors::MatrixCache<o2::math_utils::Rotation2D>); ClassImp(o2::detectors::DetMatrixCache); //_______________________________________________________ diff --git a/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h b/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h index 1e5ab5fe057ef..4eb0b776ee4dc 100644 --- a/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h +++ b/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h @@ -16,8 +16,8 @@ #pragma link C++ class o2::detectors::DetID + ; #pragma link C++ class o2::detectors::AlignParam + ; -#pragma link C++ class o2::detectors::MatrixCache < o2::Transform3D> + ; -#pragma link C++ class o2::detectors::MatrixCache < o2::Rotation2D> + ; +#pragma link C++ class o2::detectors::MatrixCache < o2::math_utils::Transform3D> + ; +#pragma link C++ class o2::detectors::MatrixCache < o2::math_utils::Rotation2D> + ; #pragma link C++ class o2::detectors::DetMatrixCache + ; #pragma link C++ class o2::detectors::DetMatrixCacheIndirect + ; diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h index e870bf05ebdfc..eb65775919cba 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/AnalysisCluster.h @@ -85,14 +85,14 @@ class AnalysisCluster /// /// Set the cluster global position. - void setGlobalPosition(Point3D<float> x); - Point3D<float> getGlobalPosition() const + void setGlobalPosition(math_utils::Point3D<float> x); + math_utils::Point3D<float> getGlobalPosition() const { return mGlobalPos; } - void setLocalPosition(Point3D<float> x); - Point3D<float> getLocalPosition() const + void setLocalPosition(math_utils::Point3D<float> x); + math_utils::Point3D<float> getLocalPosition() const { return mLocalPos; } @@ -200,14 +200,14 @@ class AnalysisCluster /// here we store what fraction of the cell energy is assigned to a given cluster. std::vector<float> mCellsAmpFraction; //[mNCells][0.,1.,16] - Point3D<float> mGlobalPos; ///< Position in global coordinate system (cm). - Point3D<float> mLocalPos; ///< Local position in the sub-detector coordinate - float mEnergy = 0; ///< Energy measured by calorimeter in GeV. - float mCoreEnergy = 0.; ///< Energy in a shower core - float mDispersion = 0; ///< Cluster shape dispersion. - float mChi2 = 0; ///< Chi2 of cluster fit (unfolded clusters) - float mM20 = 0; ///< 2-nd moment along the second eigen axis. - float mM02 = 0; ///< 2-nd moment along the main eigen axis. + math_utils::Point3D<float> mGlobalPos; ///< Position in global coordinate system (cm). + math_utils::Point3D<float> mLocalPos; ///< Local position in the sub-detector coordinate + float mEnergy = 0; ///< Energy measured by calorimeter in GeV. + float mCoreEnergy = 0.; ///< Energy in a shower core + float mDispersion = 0; ///< Cluster shape dispersion. + float mChi2 = 0; ///< Chi2 of cluster fit (unfolded clusters) + float mM20 = 0; ///< 2-nd moment along the second eigen axis. + float mM02 = 0; ///< 2-nd moment along the main eigen axis. float mEmcCpvDistance = 1024; ///< the distance from PHOS EMC rec.point to the closest CPV rec.point. @@ -230,4 +230,4 @@ class AnalysisCluster } // namespace emcal } // namespace o2 -#endif //ANALYSISCLUSTER_H \ No newline at end of file +#endif //ANALYSISCLUSTER_H diff --git a/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx b/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx index 6119ab75b0971..c106ad0ab646d 100644 --- a/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx +++ b/DataFormats/Detectors/EMCAL/src/AnalysisCluster.cxx @@ -50,7 +50,7 @@ TLorentzVector AnalysisCluster::getMomentum(std::array<const float, 3> vertex) c } //______________________________________________________________________________ -void AnalysisCluster::setGlobalPosition(Point3D<float> x) +void AnalysisCluster::setGlobalPosition(math_utils::Point3D<float> x) { mGlobalPos.SetX(x.X()); mGlobalPos.SetY(x.Y()); @@ -58,9 +58,9 @@ void AnalysisCluster::setGlobalPosition(Point3D<float> x) } //______________________________________________________________________________ -void AnalysisCluster::setLocalPosition(Point3D<float> x) +void AnalysisCluster::setLocalPosition(math_utils::Point3D<float> x) { mLocalPos.SetX(x.X()); mLocalPos.SetY(x.Y()); mLocalPos.SetZ(x.Z()); -} \ No newline at end of file +} diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/Hit.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/Hit.h index b31dc2b0813d4..d15d8af19f7cc 100644 --- a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/Hit.h +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/Hit.h @@ -43,16 +43,16 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> /// \param particlePdg PDG code of the partcile associated with the track inline Hit(int trackID, int cellID, - const Point3D<float>& startPos, - const Point3D<float>& endPos, - const Vector3D<float>& startMom, + const math_utils::Point3D<float>& startPos, + const math_utils::Point3D<float>& endPos, + const math_utils::Vector3D<float>& startMom, double startE, double endTime, double eLoss, Int_t particlePdg); // Entrance position getters - Point3D<Float_t> const& GetPosStart() const { return mPositionStart; } + math_utils::Point3D<Float_t> const& GetPosStart() const { return mPositionStart; } Float_t GetStartX() const { return mPositionStart.X(); } Float_t GetStartY() const { return mPositionStart.Y(); } Float_t GetStartZ() const { return mPositionStart.Z(); } @@ -65,8 +65,8 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> } // Momentum getters - Vector3D<Float_t> const& GetMomentum() const { return mMomentumStart; } - Vector3D<Float_t>& GetMomentum() { return mMomentumStart; } + math_utils::Vector3D<Float_t> const& GetMomentum() const { return mMomentumStart; } + math_utils::Vector3D<Float_t>& GetMomentum() { return mMomentumStart; } Float_t GetPx() const { return mMomentumStart.X(); } Float_t GetPy() const { return mMomentumStart.Y(); } Float_t GetPz() const { return mMomentumStart.Z(); } @@ -77,19 +77,19 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> void Print(const Option_t* opt) const; private: - Vector3D<float> mMomentumStart; ///< momentum at entrance - Point3D<float> mPositionStart; ///< position at entrance (base mPos give position on exit) - float mEnergyStart; ///< total energy at entrance - int mParticlePdg; ///< PDG code of the particle associated with this track + math_utils::Vector3D<float> mMomentumStart; ///< momentum at entrance + math_utils::Point3D<float> mPositionStart; ///< position at entrance (base mPos give position on exit) + float mEnergyStart; ///< total energy at entrance + int mParticlePdg; ///< PDG code of the particle associated with this track ClassDefNV(Hit, 2); }; Hit::Hit(int trackID, int detID, - const Point3D<float>& startPos, - const Point3D<float>& endPos, - const Vector3D<float>& startMom, + const math_utils::Point3D<float>& startPos, + const math_utils::Point3D<float>& endPos, + const math_utils::Vector3D<float>& startMom, double startE, double endTime, double eLoss, diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h index 8e242f3ef3541..3110151973538 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h @@ -155,9 +155,9 @@ class TopologyDictionary /// Returns the number of elements in the dicionary; int getSize() const { return (int)mVectorOfIDs.size(); } ///Returns the local position of a compact cluster - Point3D<float> getClusterCoordinates(const CompCluster& cl) const; + math_utils::Point3D<float> getClusterCoordinates(const CompCluster& cl) const; ///Returns the local position of a compact cluster - static Point3D<float> getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt); + static math_utils::Point3D<float> getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt); friend BuildTopologyDictionary; friend LookUp; diff --git a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx index 26439c2472ccf..fe5c1a4e2aacd 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx @@ -126,20 +126,20 @@ void TopologyDictionary::getTopologyDistribution(const TopologyDictionary& dict, } } -Point3D<float> TopologyDictionary::getClusterCoordinates(const CompCluster& cl) const +math_utils::Point3D<float> TopologyDictionary::getClusterCoordinates(const CompCluster& cl) const { - Point3D<float> locCl; + math_utils::Point3D<float> locCl; o2::itsmft::SegmentationAlpide::detectorToLocalUnchecked(cl.getRow(), cl.getCol(), locCl); locCl.SetX(locCl.X() + this->getXCOG(cl.getPatternID())); locCl.SetZ(locCl.Z() + this->getZCOG(cl.getPatternID())); return locCl; } -Point3D<float> TopologyDictionary::getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt) +math_utils::Point3D<float> TopologyDictionary::getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt) { float xCOG = 0, zCOG = 0; patt.getCOG(xCOG, zCOG); - Point3D<float> locCl; + math_utils::Point3D<float> locCl; o2::itsmft::SegmentationAlpide::detectorToLocalUnchecked(cl.getRow() - round(xCOG) + xCOG, cl.getCol() - round(zCOG) + zCOG, locCl); return locCl; } diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h index 45b9430f7e56e..0499dcd7dc6f5 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h @@ -76,11 +76,11 @@ enum class StatisticsType { /// Pad centres as 2D float // For some reason cling does not like the nested using statement, typedef works ... -typedef Point2D<float> PadCentre; -typedef Point2D<float> GlobalPosition2D; -typedef Point2D<float> LocalPosition2D; -typedef Point3D<float> GlobalPosition3D; -typedef Point3D<float> LocalPosition3D; +typedef math_utils::Point2D<float> PadCentre; +typedef math_utils::Point2D<float> GlobalPosition2D; +typedef math_utils::Point2D<float> LocalPosition2D; +typedef math_utils::Point3D<float> GlobalPosition3D; +typedef math_utils::Point3D<float> LocalPosition3D; /// global pad number typedef unsigned short GlobalPadNumber; diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h index 985adb8d86987..a21812e8306e7 100644 --- a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h @@ -36,8 +36,8 @@ struct RecEvent { std::array<float, NChannelsZN> energyZNC; /// reco E in 5 ZNC sectors + sum std::array<float, NChannelsZP> energyZPA; /// reco E in 5 ZPA sectors + sum std::array<float, NChannelsZP> energyZPC; /// reco E in 5 ZPC sectors + sum - Point2D<float> centroidZNA; /// centroid coordinates for ZNA - Point2D<float> centroidZNC; /// centroid coordinates for ZNC + math_utils::Point2D<float> centroidZNA; /// centroid coordinates for ZNA + math_utils::Point2D<float> centroidZNC; /// centroid coordinates for ZNC std::array<TDCChannel, NTDCChannels> tdcChannels; /// At most MaxTDCValues Values in ns per TDC channel void print() const; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h index 7568bb8568ee3..a202249016824 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/BaseCluster.h @@ -30,7 +30,7 @@ template <typename T> class BaseCluster { private: - Point3D<T> mPos; // cartesian position + math_utils::Point3D<T> mPos; // cartesian position T mSigmaY2; // error in Y direction (usually rphi) T mSigmaZ2; // error in Z direction (usually Z) T mSigmaYZ; // non-diagonal term of error matrix @@ -44,9 +44,9 @@ class BaseCluster ~BaseCluster() = default; // constructor - BaseCluster(std::uint16_t sensid, const Point3D<T>& xyz) : mPos(xyz), mSensorID(sensid) {} + BaseCluster(std::uint16_t sensid, const math_utils::Point3D<T>& xyz) : mPos(xyz), mSensorID(sensid) {} BaseCluster(std::uint16_t sensid, T x, T y, T z) : mPos(x, y, z), mSensorID(sensid) {} - BaseCluster(std::uint16_t sensid, const Point3D<T>& xyz, T sy2, T sz2, T syz) + BaseCluster(std::uint16_t sensid, const math_utils::Point3D<T>& xyz, T sy2, T sz2, T syz) : mPos(xyz), mSigmaY2(sy2), mSigmaZ2(sz2), mSigmaYZ(syz), mSensorID(sensid) { } @@ -62,16 +62,16 @@ class BaseCluster T getSigmaY2() const { return mSigmaY2; } T getSigmaZ2() const { return mSigmaZ2; } T getSigmaYZ() const { return mSigmaYZ; } - Point3D<T> getXYZ() const { return mPos; } - Point3D<T>& getXYZ() { return mPos; } + math_utils::Point3D<T> getXYZ() const { return mPos; } + math_utils::Point3D<T>& getXYZ() { return mPos; } // position in local frame, no check for matrices cache validity - Point3D<T> getXYZLoc(const o2::detectors::DetMatrixCache& dm) const { return dm.getMatrixT2L(mSensorID)(mPos); } + math_utils::Point3D<T> getXYZLoc(const o2::detectors::DetMatrixCache& dm) const { return dm.getMatrixT2L(mSensorID)(mPos); } // position in global frame, no check for matrices cache validity - Point3D<T> getXYZGlo(const o2::detectors::DetMatrixCache& dm) const { return dm.getMatrixT2G(mSensorID)(mPos); } + math_utils::Point3D<T> getXYZGlo(const o2::detectors::DetMatrixCache& dm) const { return dm.getMatrixT2G(mSensorID)(mPos); } // position in global frame obtained as simple rotation from tracking one: // much faster for barrel detectors than using full 3D matrix. // no check for matrices cache validity - Point3D<T> getXYZGloRot(const o2::detectors::DetMatrixCache& dm) const { return dm.getMatrixT2GRot(mSensorID)(mPos); } + math_utils::Point3D<T> getXYZGloRot(const o2::detectors::DetMatrixCache& dm) const { return dm.getMatrixT2GRot(mSensorID)(mPos); } // get sensor id std::int16_t getSensorID() const { return mSensorID; } // get count field @@ -80,7 +80,7 @@ class BaseCluster std::uint8_t getBits() const { return mBits; } bool isBitSet(int bit) const { return mBits & (0xff & (0x1 << bit)); } // cast to Point3D - operator Point3D<T>&() { return mPos; } + operator math_utils::Point3D<T>&() { return mPos; } // modifiers // set sensor id @@ -101,7 +101,7 @@ class BaseCluster setY(y); setZ(z); } - void setPos(const Point3D<T>& p) { mPos = p; } + void setPos(const math_utils::Point3D<T>& p) { mPos = p; } void setSigmaY2(T v) { mSigmaY2 = v; } void setSigmaZ2(T v) { mSigmaZ2 = v; } void setSigmaYZ(T v) { mSigmaYZ = v; } @@ -113,7 +113,6 @@ class BaseCluster } protected: - ClassDefNV(BaseCluster, 2); }; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 698c90de64b61..286cfd99b4a77 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -183,7 +183,7 @@ class TrackParametrization value_t getTheta() const; value_t getEta() const; - Point3D<value_t> getXYZGlo() const; + math_utils::Point3D<value_t> getXYZGlo() const; void getXYZGlo(dim3_t& xyz) const; bool getPxPyPzGlo(dim3_t& pxyz) const; bool getPosDirGlo(std::array<value_t, 9>& posdirp) const; @@ -192,7 +192,7 @@ class TrackParametrization bool getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const; value_t getZAt(value_t xk, value_t b) const; value_t getYAt(value_t xk, value_t b) const; - Point3D<value_t> getXYZGloAt(value_t xk, value_t b, bool& ok) const; + math_utils::Point3D<value_t> getXYZGloAt(value_t xk, value_t b, bool& ok) const; // parameters manipulation bool correctForELoss(value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); @@ -200,7 +200,7 @@ class TrackParametrization bool propagateParamTo(value_t xk, value_t b); bool propagateParamTo(value_t xk, const dim3_t& b); - bool propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, dim2_t* dca = nullptr, value_t maxD = 999.f); + bool propagateParamToDCA(const math_utils::Point3D<value_t>& vtx, value_t b, dim2_t* dca = nullptr, value_t maxD = 999.f); void invertParam(); @@ -569,9 +569,9 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu #ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden //_______________________________________________________ template <typename value_T> -inline Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGlo() const +inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGlo() const { - return Rotation2D(getAlpha())(Point3D<value_t>(getX(), getY(), getZ())); + return math_utils::Rotation2D(getAlpha())(math_utils::Point3D<value_t>(getX(), getY(), getZ())); } #endif @@ -589,14 +589,14 @@ inline void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const #ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden //_______________________________________________________ template <typename value_T> -inline Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGloAt(value_t xk, value_t b, bool& ok) const +inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGloAt(value_t xk, value_t b, bool& ok) const { //---------------------------------------------------------------- // estimate global X,Y,Z in global frame at given X //---------------------------------------------------------------- value_t y = 0.f, z = 0.f; ok = getYZAt(xk, b, y, z); - return ok ? Rotation2D(getAlpha())(Point3D<value_t>(xk, y, z)) : Point3D<value_t>(); + return ok ? math_utils::Rotation2D(getAlpha())(math_utils::Point3D<value_t>(xk, y, z)) : math_utils::Point3D<value_t>(); } #endif diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h index e62f243bd7e42..7abcae8423447 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h @@ -38,7 +38,7 @@ class VertexBase static constexpr int kNCov = 6; VertexBase() = default; ~VertexBase() = default; - VertexBase(const Point3D<float>& pos, const std::array<float, kNCov>& cov) : mPos(pos), mCov(cov) + VertexBase(const math_utils::Point3D<float>& pos, const std::array<float, kNCov>& cov) : mPos(pos), mCov(cov) { } @@ -59,8 +59,8 @@ class VertexBase float getSigmaYZ() const { return mCov[kCovYZ]; } const std::array<float, kNCov>& getCov() const { return mCov; } - Point3D<float> getXYZ() const { return mPos; } - Point3D<float>& getXYZ() { return mPos; } + math_utils::Point3D<float> getXYZ() const { return mPos; } + math_utils::Point3D<float>& getXYZ() { return mPos; } void setX(float x) { mPos.SetX(x); } void setY(float y) { mPos.SetY(y); } @@ -72,7 +72,7 @@ class VertexBase setY(y); setZ(z); } - void setPos(const Point3D<float>& p) { mPos = p; } + void setPos(const math_utils::Point3D<float>& p) { mPos = p; } void setSigmaX2(float v) { mCov[kCovXX] = v; } void setSigmaY2(float v) { mCov[kCovYY] = v; } @@ -92,8 +92,8 @@ class VertexBase void setCov(const std::array<float, kNCov>& cov) { mCov = cov; } protected: - Point3D<float> mPos{0., 0., 0.}; ///< cartesian position - std::array<float, kNCov> mCov{}; ///< errors, see CovElems enum + math_utils::Point3D<float> mPos{0., 0., 0.}; ///< cartesian position + std::array<float, kNCov> mCov{}; ///< errors, see CovElems enum ClassDefNV(VertexBase, 1); }; @@ -114,7 +114,7 @@ class Vertex : public VertexBase Vertex() = default; ~Vertex() = default; - Vertex(const Point3D<float>& pos, const std::array<float, kNCov>& cov, ushort nCont, float chi2) + Vertex(const math_utils::Point3D<float>& pos, const std::array<float, kNCov>& cov, ushort nCont, float chi2) : VertexBase(pos, cov), mNContributors(nCont), mChi2(chi2) { } @@ -136,10 +136,10 @@ class Vertex : public VertexBase void setTimeStamp(const Stamp& v) { mTimeStamp = v; } protected: - float mChi2 = 0; ///< chi2 or quality of tracks to vertex attachment - ushort mNContributors = 0; ///< N contributors - ushort mBits = 0; ///< bit field for flags - Stamp mTimeStamp; ///< vertex time-stamp + float mChi2 = 0; ///< chi2 or quality of tracks to vertex attachment + ushort mNContributors = 0; ///< N contributors + ushort mBits = 0; ///< bit field for flags + Stamp mTimeStamp; ///< vertex time-stamp ClassDefNV(Vertex, 3); }; diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index 555dfcc0d70b7..4733648b6e816 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -354,7 +354,7 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) //_______________________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::propagateParamToDCA(const Point3D<value_t>& vtx, value_t b, dim2_t* dca, value_t maxD) +bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3D<value_t>& vtx, value_t b, dim2_t* dca, value_t maxD) { // propagate track to DCA to the vertex value_t sn, cs, alp = getAlpha(); diff --git a/DataFormats/Reconstruction/test/testVertex.cxx b/DataFormats/Reconstruction/test/testVertex.cxx index 94c7066d3c0f9..60300c6c292e6 100644 --- a/DataFormats/Reconstruction/test/testVertex.cxx +++ b/DataFormats/Reconstruction/test/testVertex.cxx @@ -25,7 +25,7 @@ using myVtx = o2::dataformats::Vertex<myTS>; // basic Vertex tests BOOST_AUTO_TEST_CASE(Vertex) { - const Point3D<float> pos(0.1, 0.2, 3.0); + const math_utils::Point3D<float> pos(0.1, 0.2, 3.0); const std::array<float, myVtx::kNCov> cov = {1e-4, -1e-9, 2e-4, -1e-9, 1e-9, 1e-4}; int nc = 10; float chi2 = 5.5f; diff --git a/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h b/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h index c29596c6e6572..31e506cbe65e0 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h +++ b/DataFormats/simulation/include/SimulationDataFormat/BaseHits.h @@ -45,10 +45,10 @@ class BaseHit template <typename T, typename E, typename V = float> class BasicXYZVHit : public BaseHit { - Point3D<T> mPos; // cartesian position of Hit - E mTime; // time of flight - V mHitValue; // hit value - short mDetectorID; // the detector/sensor id + math_utils::Point3D<T> mPos; // cartesian position of Hit + E mTime; // time of flight + V mHitValue; // hit value + short mDetectorID; // the detector/sensor id public: BasicXYZVHit() = default; // for ROOT IO @@ -63,7 +63,7 @@ class BasicXYZVHit : public BaseHit T GetX() const { return mPos.X(); } T GetY() const { return mPos.Y(); } T GetZ() const { return mPos.Z(); } - Point3D<T> GetPos() const { return mPos; } + math_utils::Point3D<T> GetPos() const { return mPos; } // getting hit value V GetHitValue() const { return mHitValue; } // getting the time @@ -84,7 +84,7 @@ class BasicXYZVHit : public BaseHit SetY(y); SetZ(z); } - void SetPos(Point3D<T> const& p) { mPos = p; } + void SetPos(math_utils::Point3D<T> const& p) { mPos = p; } ClassDefNV(BasicXYZVHit, 1); }; diff --git a/DataFormats/simulation/src/DigitizationContext.cxx b/DataFormats/simulation/src/DigitizationContext.cxx index 0414e45122ab8..f6263a1accd26 100644 --- a/DataFormats/simulation/src/DigitizationContext.cxx +++ b/DataFormats/simulation/src/DigitizationContext.cxx @@ -119,14 +119,14 @@ bool DigitizationContext::checkVertexCompatibility(bool verbose) const return true; } - auto checkVertexPair = [](Point3D<double> const& p1, Point3D<double> const& p2) -> bool { + auto checkVertexPair = [](math_utils::Point3D<double> const& p1, math_utils::Point3D<double> const& p2) -> bool { return (p2 - p1).Mag2() < 1E-6; }; std::vector<TChain*> kinematicschain; std::vector<TBranch*> headerbranches; std::vector<o2::dataformats::MCEventHeader*> headers; - std::vector<Point3D<double>> vertices; + std::vector<math_utils::Point3D<double>> vertices; initSimKinematicsChains(kinematicschain); bool consistent = true; if (kinematicschain.size() > 0) { diff --git a/Detectors/Base/include/DetectorsBase/GeometryManager.h b/Detectors/Base/include/DetectorsBase/GeometryManager.h index 0c14ff7b9dd39..dadd378f07968 100644 --- a/Detectors/Base/include/DetectorsBase/GeometryManager.h +++ b/Detectors/Base/include/DetectorsBase/GeometryManager.h @@ -92,21 +92,21 @@ class GeometryManager : public TObject }; static o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1); - static o2::base::MatBudget meanMaterialBudget(const Point3D<float>& start, const Point3D<float>& end) + static o2::base::MatBudget meanMaterialBudget(const math_utils::Point3D<float>& start, const math_utils::Point3D<float>& end) { return meanMaterialBudget(start.X(), start.Y(), start.Z(), end.X(), end.Y(), end.Z()); } - static o2::base::MatBudget meanMaterialBudget(const Point3D<double>& start, const Point3D<double>& end) + static o2::base::MatBudget meanMaterialBudget(const math_utils::Point3D<double>& start, const math_utils::Point3D<double>& end) { return meanMaterialBudget(start.X(), start.Y(), start.Z(), end.X(), end.Y(), end.Z()); } static MatBudgetExt meanMaterialBudgetExt(float x0, float y0, float z0, float x1, float y1, float z1); - static MatBudgetExt meanMaterialBudgetExt(const Point3D<float>& start, const Point3D<float>& end) + static MatBudgetExt meanMaterialBudgetExt(const math_utils::Point3D<float>& start, const math_utils::Point3D<float>& end) { return meanMaterialBudgetExt(start.X(), start.Y(), start.Z(), end.X(), end.Y(), end.Z()); } - static MatBudgetExt meanMaterialBudgetExt(const Point3D<double>& start, const Point3D<double>& end) + static MatBudgetExt meanMaterialBudgetExt(const math_utils::Point3D<double>& start, const math_utils::Point3D<double>& end) { return meanMaterialBudgetExt(start.X(), start.Y(), start.Z(), end.X(), end.Y(), end.Z()); } diff --git a/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h b/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h index 8170a4d4fe71b..e0912de30c691 100644 --- a/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h +++ b/Detectors/Base/include/DetectorsBase/MatLayerCylSet.h @@ -82,7 +82,7 @@ class MatLayerCylSet : public o2::gpu::FlatObject #endif // !GPUCA_ALIGPUCODE #ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version - MatBudget getMatBudget(const Point3D<float>& point0, const Point3D<float>& point1) const + MatBudget getMatBudget(const math_utils::Point3D<float>& point0, const math_utils::Point3D<float>& point1) const { // get material budget traversed on the line between point0 and point1 return getMatBudget(point0.X(), point0.Y(), point0.Z(), point1.X(), point1.Y(), point1.Z()); diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index 9185d70cefd1e..fad54c7a387e7 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -82,12 +82,12 @@ class Propagator o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; - bool propagateToDCA(const Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, + bool propagateToDCA(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, float mass = o2::constants::physics::MassPionCharged, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; - bool propagateToDCABxByBz(const Point3D<float>& vtx, o2::track::TrackPar& track, + bool propagateToDCABxByBz(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float mass = o2::constants::physics::MassPionCharged, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; @@ -110,7 +110,7 @@ class Propagator Propagator(); ~Propagator() = default; - MatBudget getMatBudget(MatCorrType corrType, const Point3D<float>& p0, const Point3D<float>& p1) const; + MatBudget getMatBudget(MatCorrType corrType, const o2::math_utils::Point3D<float>& p0, const o2::math_utils::Point3D<float>& p1) const; const o2::field::MagFieldFast* mField = nullptr; ///< External fast field (barrel only for the moment) float mBz = 0; // nominal field diff --git a/Detectors/Base/include/DetectorsBase/Ray.h b/Detectors/Base/include/DetectorsBase/Ray.h index ba740750bb445..1867f159728a0 100644 --- a/Detectors/Base/include/DetectorsBase/Ray.h +++ b/Detectors/Base/include/DetectorsBase/Ray.h @@ -51,7 +51,7 @@ class Ray GPUdDefault() ~Ray() CON_DEFAULT; #ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version - Ray(const Point3D<float> point0, const Point3D<float> point1); + Ray(const math_utils::Point3D<float> point0, const math_utils::Point3D<float> point1); #endif // !GPUCA_ALIGPUCODE GPUd() Ray(float x0, float y0, float z0, float x1, float y1, float z1); GPUd() int crossLayer(const MatLayerCyl& lr); @@ -107,7 +107,7 @@ class Ray //______________________________________________________ #ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version -inline Ray::Ray(const Point3D<float> point0, const Point3D<float> point1) +inline Ray::Ray(const math_utils::Point3D<float> point0, const math_utils::Point3D<float> point1) : mP{point0.X(), point0.Y(), point0.Z()}, mD{point1.X() - point0.X(), point1.Y() - point0.Y(), point1.Z() - point0.Z()} { mDistXY2 = mD[0] * mD[0] + mD[1] * mD[1]; diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index af890ba9ede7d..6b529a779189a 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -99,7 +99,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, } } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght auto xyz1 = track.getXYZGlo(); - Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); + math_utils::Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); tofInfo->addStep(stepV.R(), track); } dx = xToGo - track.getX(); @@ -158,7 +158,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, flo } } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght auto xyz1 = track.getXYZGlo(); - Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); + math_utils::Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); tofInfo->addStep(stepV.R(), track); } dx = xToGo - track.getX(); @@ -217,7 +217,7 @@ bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float } } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght auto xyz1 = track.getXYZGlo(); - Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); + math_utils::Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); tofInfo->addStep(stepV.R(), track); } dx = xToGo - track.getX(); @@ -276,7 +276,7 @@ bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, } } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght auto xyz1 = track.getXYZGlo(); - Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); + math_utils::Vector3D<float> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z()); tofInfo->addStep(stepV.R(), track); } dx = xToGo - track.getX(); @@ -375,7 +375,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 } //_______________________________________________________________________ -bool Propagator::propagateToDCA(const Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, +bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, float mass, float maxStep, Propagator::MatCorrType matCorr, std::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, int signCorr, float maxD) const @@ -419,7 +419,7 @@ bool Propagator::propagateToDCA(const Point3D<float>& vtx, o2::track::TrackPar& } //_______________________________________________________________________ -bool Propagator::propagateToDCABxByBz(const Point3D<float>& vtx, o2::track::TrackPar& track, +bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float mass, float maxStep, Propagator::MatCorrType matCorr, std::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, int signCorr, float maxD) const @@ -507,7 +507,7 @@ int Propagator::initFieldFromGRP(const o2::parameters::GRPObject* grp, bool verb } //____________________________________________________________ -MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, const Point3D<float>& p0, const Point3D<float>& p1) const +MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, const math_utils::Point3D<float>& p0, const math_utils::Point3D<float>& p1) const { return (corrType == MatCorrType::USEMatCorrTGeo) ? GeometryManager::meanMaterialBudget(p0, p1) : mMatLUT->getMatBudget(p0.X(), p0.Y(), p0.Z(), p1.X(), p1.Y(), p1.Z()); } diff --git a/Detectors/Base/test/README.md b/Detectors/Base/test/README.md index cfbd2390998d2..9b6e798268be6 100644 --- a/Detectors/Base/test/README.md +++ b/Detectors/Base/test/README.md @@ -26,7 +26,7 @@ float xyz0[3] = {0.,0.,0.}; float xyz1[3] = {70.,80.,20.}; auto mb = mbl.getMatBudget(xyz0[0],xyz0[1],xyz0[2], xyz1[0],xyz1[1],xyz1[2]); -// alternatively, use MatCell getMatBudget(const Point3D<float> &point0,const Point3D<float> &point1) method +// alternatively, use MatCell getMatBudget(const math_utils::Point3D<float> &point0,const math_utils::Point3D<float> &point1) method std::cout << "<rho>= " << mb.meanRho << " <x/X0>= " << mb.meanX2X0 << "\n"; ``` diff --git a/Detectors/CPV/base/include/CPVBase/Hit.h b/Detectors/CPV/base/include/CPVBase/Hit.h index 5171a545ea617..4e7e7febba883 100644 --- a/Detectors/CPV/base/include/CPVBase/Hit.h +++ b/Detectors/CPV/base/include/CPVBase/Hit.h @@ -38,7 +38,7 @@ class Hit : public o2::BasicXYZEHit<float> /// \param initialEnergy Energy of the primary particle enering the EMCAL /// \param tof Time of the hit /// \param length Length of the segment - Hit(int trackID, int detID, const Point3D<float>& pos, double tof, double qLoss) + Hit(int trackID, int detID, const math_utils::Point3D<float>& pos, double tof, double qLoss) : o2::BasicXYZEHit<float>(pos.X(), pos.Y(), pos.Z(), tof, qLoss, trackID, detID) { } diff --git a/Detectors/CPV/simulation/include/CPVSimulation/Detector.h b/Detectors/CPV/simulation/include/CPVSimulation/Detector.h index a97b0516b540e..9c95ec79c0017 100644 --- a/Detectors/CPV/simulation/include/CPVSimulation/Detector.h +++ b/Detectors/CPV/simulation/include/CPVSimulation/Detector.h @@ -86,7 +86,7 @@ class Detector : public o2::base::DetImpl<Detector> /// \param[in] time Time of the hit /// \param[in] qdep charge deposited in this pad /// - void addHit(int trackID, short detID, const Point3D<float>& pos, double time, float qdep); + void addHit(int trackID, short detID, const math_utils::Point3D<float>& pos, double time, float qdep); /// /// Register vector with hits diff --git a/Detectors/CPV/simulation/src/Detector.cxx b/Detectors/CPV/simulation/src/Detector.cxx index faf57590b8eb8..a6df5ae4806f6 100644 --- a/Detectors/CPV/simulation/src/Detector.cxx +++ b/Detectors/CPV/simulation/src/Detector.cxx @@ -271,7 +271,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) // Fill hit with pad response ID and amplitude // hist will be sorted and merged later if necessary short detID = Geometry::relToAbsId(moduleNumber, kxg, kzg); - addHit(partID, detID, Point3D<float>(xyzm[0], xyzm[1], xyzm[2]), time, qpad); + addHit(partID, detID, math_utils::Point3D<float>(xyzm[0], xyzm[1], xyzm[2]), time, qpad); } } } @@ -323,7 +323,7 @@ float Detector::CPVCumulPadResponse(float x, float y) return cumulPRF; } -void Detector::addHit(int trackID, short detID, const Point3D<float>& pos, double time, float qdep) +void Detector::addHit(int trackID, short detID, const math_utils::Point3D<float>& pos, double time, float qdep) { LOG(DEBUG) << "Adding hit for track " << trackID << " in a pad " << detID << " with position (" << pos.X() << ", " << pos.Y() << ", " << pos.Z() << "), time" << time << ", qdep =" << qdep << std::endl; diff --git a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h index 9391ca611829e..c6e58ceb7cbea 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Geometry.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Geometry.h @@ -140,21 +140,21 @@ class Geometry /// Calculates the impact coordinates on EMCAL (centre of a tower/not on EMCAL surface) /// of a neutral particle emitted in the vertex vtx[3] with direction theta and phi in /// the global coordinate system - void ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_t phi, Int_t& absId, Point3D<double>& vimpact) const; + void ImpactOnEmcal(const math_utils::Point3D<double>& vtx, Double_t theta, Double_t phi, Int_t& absId, math_utils::Point3D<double>& vimpact) const; /// \brief Checks whether point is inside the EMCal volume /// \param pnt Point to be checked /// \return True if the point is inside EMCAL, false otherwise /// /// See IsInEMCALOrDCAL for the definition of the acceptance check - Bool_t IsInEMCAL(const Point3D<double>& pnt) const; + Bool_t IsInEMCAL(const math_utils::Point3D<double>& pnt) const; /// \brief Checks whether point is inside the DCal volume /// \param pnt Point to be checked /// \return True if the point is inside DCAL, false otherwise /// /// See IsInEMCALOrDCAL for the definition of the acceptance check - Bool_t IsInDCAL(const Point3D<double>& pnt) const; + Bool_t IsInDCAL(const math_utils::Point3D<double>& pnt) const; /// \brief Checks whether point is inside the EMCal volume (included DCal) /// \param pnt Point to be checked @@ -164,7 +164,7 @@ class Geometry /// /// Points behind EMCAl/DCal, i.e. R > outer radius, but eta, phi in acceptance /// are considered to inside - AcceptanceType_t IsInEMCALOrDCAL(const Point3D<double>& pnt) const; + AcceptanceType_t IsInEMCALOrDCAL(const math_utils::Point3D<double>& pnt) const; ////////////////////////////////////// // Return EMCAL geometrical parameters @@ -493,13 +493,13 @@ class Geometry /// /// Same as RelPosCellInSModule(Int_t absId, Double_t &xr, Double_t &yr, Double_t &zr) /// but taking into account position of shower max. - Point3D<double> RelPosCellInSModule(Int_t absId, Double_t distEf) const; + math_utils::Point3D<double> RelPosCellInSModule(Int_t absId, Double_t distEf) const; /// \brief Look to see what the relative position inside a given cell is for a recpoint. /// \param absId cell absolute id. number, input /// \return Point3D with x,y,z coordinates of cell with absId inside SM /// \throw InvalidCellIDException if cell ID does not exist - Point3D<double> RelPosCellInSModule(Int_t absId) const; + math_utils::Point3D<double> RelPosCellInSModule(Int_t absId) const; std::vector<EMCALSMType> GetEMCSystem() const { return mEMCSMSystem; } // EMC System, SM type list // Local Coordinates of SM diff --git a/Detectors/EMCAL/base/include/EMCALBase/Hit.h b/Detectors/EMCAL/base/include/EMCALBase/Hit.h index 8d8905ef83c01..15570bb09f7fb 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Hit.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Hit.h @@ -40,8 +40,8 @@ class Hit : public o2::BasicXYZEHit<float> /// \param mom Momentum vector for the particle at the point /// \param tof Time of the hit /// \param eLoss Energy loss - Hit(Int_t primary, Int_t trackID, Int_t detID, Double_t initialEnergy, const Point3D<float>& pos, - const Vector3D<float>& mom, Double_t tof, Double_t eLoss) + Hit(Int_t primary, Int_t trackID, Int_t detID, Double_t initialEnergy, const math_utils::Point3D<float>& pos, + const math_utils::Vector3D<float>& mom, Double_t tof, Double_t eLoss) : o2::BasicXYZEHit<float>(pos.X(), pos.Y(), pos.Z(), tof, eLoss, trackID, detID), mPvector(mom), mPrimary(primary), @@ -91,9 +91,9 @@ class Hit : public o2::BasicXYZEHit<float> void PrintStream(std::ostream& stream) const; private: - Vector3D<float> mPvector; ///< Momentum Vector - Int_t mPrimary; ///< Primary particles at the origin of the hit - Double32_t mInitialEnergy; ///< Energy of the parent particle that entered the EMCAL + math_utils::Vector3D<float> mPvector; ///< Momentum Vector + Int_t mPrimary; ///< Primary particles at the origin of the hit + Double32_t mInitialEnergy; ///< Energy of the parent particle that entered the EMCAL ClassDefNV(Hit, 1); }; diff --git a/Detectors/EMCAL/base/src/ClusterFactory.cxx b/Detectors/EMCAL/base/src/ClusterFactory.cxx index e1d144a1ebbc1..60a95e8b0ee6c 100644 --- a/Detectors/EMCAL/base/src/ClusterFactory.cxx +++ b/Detectors/EMCAL/base/src/ClusterFactory.cxx @@ -251,7 +251,7 @@ void ClusterFactory<InputType>::evalLocalPosition(gsl::span<const int> inputsInd } } - clusterAnalysis.setLocalPosition(Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2])); + clusterAnalysis.setLocalPosition(math_utils::Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2])); } /// @@ -323,7 +323,7 @@ void ClusterFactory<InputType>::evalGlobalPosition(gsl::span<const int> inputsIn } } - clusterAnalysis.setGlobalPosition(Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2])); + clusterAnalysis.setGlobalPosition(math_utils::Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2])); } /// @@ -399,7 +399,7 @@ void ClusterFactory<InputType>::evalLocalPositionFit(double deff, double mLogWei clXYZ[1] = ycorr; } - clusterAnalysis.setLocalPosition(Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2])); + clusterAnalysis.setLocalPosition(math_utils::Point3D<float>(clXYZ[0], clXYZ[1], clXYZ[2])); } /// @@ -694,4 +694,4 @@ typename ClusterFactory<InputType>::ClusterIterator ClusterFactory<InputType>::C } template class o2::emcal::ClusterFactory<o2::emcal::Cell>; -template class o2::emcal::ClusterFactory<o2::emcal::Digit>; \ No newline at end of file +template class o2::emcal::ClusterFactory<o2::emcal::Digit>; diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index 2e3c806252c03..239abb334e42d 100644 --- a/Detectors/EMCAL/base/src/Geometry.cxx +++ b/Detectors/EMCAL/base/src/Geometry.cxx @@ -1057,7 +1057,7 @@ std::tuple<int, int> Geometry::ShiftOfflineToOnlineCellIndexes(Int_t supermodule return std::tuple<int, int>(iphi, ieta); } -Point3D<double> Geometry::RelPosCellInSModule(Int_t absId) const +o2::math_utils::Point3D<double> Geometry::RelPosCellInSModule(Int_t absId) const { // Shift index taking into account the difference between standard SM // and SM of half (or one third) size in phi direction @@ -1103,7 +1103,7 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId) const if (nSupMod % 2 != 0) { iphi2 = (phiindex / 2 - 1) - iphi; // 11-iphi [1/2SM], revert the ordering on C side in order to keep } - // convention. + // convention. yr = mCentersOfCellsPhiDir[iphi2 + phiindex / 4]; } else if (GetSMType(nSupMod) == EMCAL_THIRD) { if (nSupMod % 2 != 0) { @@ -1119,10 +1119,10 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId) const LOG(DEBUG) << "absId " << absId << " nSupMod " << nSupMod << " iphi " << iphi << " ieta " << ieta << " xr " << xr << " yr " << yr << " zr " << zr; - return Point3D<double>(xr, yr, zr); + return o2::math_utils::Point3D<double>(xr, yr, zr); } -Point3D<double> Geometry::RelPosCellInSModule(Int_t absId, Double_t distEff) const +o2::math_utils::Point3D<double> Geometry::RelPosCellInSModule(Int_t absId, Double_t distEff) const { // Shift index taking into account the difference between standard SM // and SM of half (or one third) size in phi direction @@ -1179,7 +1179,7 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId, Double_t distEff) con if (nSupMod % 2 != 0) { iphi2 = (nphiIndex / 2 - 1) - iphi; // 11-iphi [1/2SM], revert the ordering on C side in order to keep } - // convention. + // convention. yr = mCentersOfCellsPhiDir[iphi2 + nphiIndex / 2]; } else if (GetSMType(nSupMod) == EMCAL_THIRD) { if (nSupMod % 2 != 0) { @@ -1195,7 +1195,7 @@ Point3D<double> Geometry::RelPosCellInSModule(Int_t absId, Double_t distEff) con LOG(DEBUG) << "absId " << absId << " nSupMod " << nSupMod << " iphi " << iphi << " ieta " << ieta << " xr " << xr << " yr " << yr << " zr " << zr; - return Point3D<double>(xr, yr, zr); + return math_utils::Point3D<double>(xr, yr, zr); } void Geometry::CreateListOfTrd1Modules() @@ -1323,7 +1323,7 @@ Bool_t Geometry::Impact(const TParticle* particle) const { Bool_t in = kFALSE; Int_t absID = 0; - Point3D<double> vimpact = {0, 0, 0}; + math_utils::Point3D<double> vimpact = {0, 0, 0}; ImpactOnEmcal({particle->Vx(), particle->Vy(), particle->Vz()}, particle->Theta(), particle->Phi(), absID, vimpact); @@ -1334,9 +1334,9 @@ Bool_t Geometry::Impact(const TParticle* particle) const return in; } -void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_t phi, Int_t& absId, Point3D<double>& vimpact) const +void Geometry::ImpactOnEmcal(const math_utils::Point3D<double>& vtx, Double_t theta, Double_t phi, Int_t& absId, math_utils::Point3D<double>& vimpact) const { - Vector3D<double> p(TMath::Sin(theta) * TMath::Cos(phi), TMath::Sin(theta) * TMath::Sin(phi), TMath::Cos(theta)); + math_utils::Vector3D<double> p(TMath::Sin(theta) * TMath::Cos(phi), TMath::Sin(theta) * TMath::Sin(phi), TMath::Cos(theta)); vimpact.SetXYZ(0, 0, 0); absId = -1; @@ -1344,7 +1344,7 @@ void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_ return; } - Vector3D<double> direction; + math_utils::Vector3D<double> direction; Double_t factor = (mIPDistance - vtx.Y()) / p.Y(); direction = vtx + factor * p; @@ -1421,8 +1421,8 @@ void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_ Double_t dist = mLongModuleSize / 2.; Double_t norm = TMath::Sqrt(a * a + b * b + c * c); Double_t glob4[3] = {}; - Vector3D<double> dir = {a, b, c}; - Point3D<double> point = {glob[0], glob[1], glob[2]}; + math_utils::Vector3D<double> dir = {a, b, c}; + math_utils::Point3D<double> point = {glob[0], glob[1], glob[2]}; if (point.Dot(dir) < 0) { dist *= -1; } @@ -1450,7 +1450,7 @@ void Geometry::ImpactOnEmcal(const Point3D<double>& vtx, Double_t theta, Double_ vimpact.SetXYZ(vimpact.Z() + dist * a / norm, vimpact.Y() + dist * b / norm, vimpact.Z() + dist * c / norm); } -Bool_t Geometry::IsInEMCAL(const Point3D<double>& pnt) const +Bool_t Geometry::IsInEMCAL(const math_utils::Point3D<double>& pnt) const { if (IsInEMCALOrDCAL(pnt) == EMCAL_ACCEPTANCE) { return kTRUE; @@ -1459,7 +1459,7 @@ Bool_t Geometry::IsInEMCAL(const Point3D<double>& pnt) const } } -Bool_t Geometry::IsInDCAL(const Point3D<double>& pnt) const +Bool_t Geometry::IsInDCAL(const math_utils::Point3D<double>& pnt) const { if (IsInEMCALOrDCAL(pnt) == DCAL_ACCEPTANCE) { return kTRUE; @@ -1468,7 +1468,7 @@ Bool_t Geometry::IsInDCAL(const Point3D<double>& pnt) const } } -o2::emcal::AcceptanceType_t Geometry::IsInEMCALOrDCAL(const Point3D<double>& pnt) const +o2::emcal::AcceptanceType_t Geometry::IsInEMCALOrDCAL(const math_utils::Point3D<double>& pnt) const { Double_t r = sqrt(pnt.X() * pnt.X() + pnt.Y() * pnt.Y()); diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h index adf0a80c3950a..a7fb3649ac572 100644 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h +++ b/Detectors/EMCAL/simulation/include/EMCALSimulation/Detector.h @@ -88,7 +88,7 @@ class Detector : public o2::base::DetImpl<Detector> /// /// Internally adding hits coming from the same track Hit* AddHit(Int_t trackID, Int_t primary, Double_t initialEnergy, Int_t detID, - const Point3D<float>& pos, const Vector3D<float>& mom, Double_t time, Double_t energyloss); + const math_utils::Point3D<float>& pos, const math_utils::Vector3D<float>& mom, Double_t time, Double_t energyloss); Parent* AddSuperparent(Int_t trackID, Int_t pdg, Double_t energy); diff --git a/Detectors/EMCAL/simulation/src/Detector.cxx b/Detectors/EMCAL/simulation/src/Detector.cxx index b6720fcd34844..79c27568b7124 100644 --- a/Detectors/EMCAL/simulation/src/Detector.cxx +++ b/Detectors/EMCAL/simulation/src/Detector.cxx @@ -265,7 +265,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) smTypeID = 3; //one third (installed in 2012) supermodule } if (supermoduletype == DCAL_EXT) { - smTypeID = 3; //one third (installed in 2012) supermodule + smTypeID = 3; //one third (installed in 2012) supermodule } iphi = ((geom->GetCentersOfCellsPhiDir()).size() / smTypeID - 1) - iphi; // 23/7-iphi, revert the ordering on C side in order to keep convention. } @@ -303,8 +303,8 @@ Bool_t Detector::ProcessHits(FairVolume* v) LOG(DEBUG3) << "Adding new hit for parent " << mCurrentParentID << " and cell " << detID << std::endl; /// check handling of primary particles - AddHit(mCurrentParentID, mCurrentPrimaryID, mCurrentSuperparent->mEnergy, detID, Point3D<float>(posX, posY, posZ), - Vector3D<float>(momX, momY, momZ), time, lightyield); + AddHit(mCurrentParentID, mCurrentPrimaryID, mCurrentSuperparent->mEnergy, detID, math_utils::Point3D<float>(posX, posY, posZ), + math_utils::Vector3D<float>(momX, momY, momZ), time, lightyield); o2stack->addHit(GetDetId()); } else { LOG(DEBUG3) << "Adding energy to the current hit" << std::endl; @@ -316,7 +316,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) } Hit* Detector::AddHit(Int_t trackID, Int_t primary, Double_t initialEnergy, Int_t detID, - const Point3D<float>& pos, const Vector3D<float>& mom, Double_t time, Double_t eLoss) + const math_utils::Point3D<float>& pos, const math_utils::Vector3D<float>& mom, Double_t time, Double_t eLoss) { LOG(DEBUG3) << "Adding hit for track " << trackID << " with position (" << pos.X() << ", " << pos.Y() << ", " << pos.Z() << ") and momentum (" << mom.X() << ", " << mom.Y() << ", " << mom.Z() diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Detector.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Detector.h index c70a98362c6c5..6e708568282f3 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Detector.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Detector.h @@ -108,8 +108,8 @@ class Detector : public o2::base::DetImpl<Detector> } mTrackData; //! o2::fv0::Hit* addHit(Int_t trackId, Int_t cellId, - const Point3D<float>& startPos, const Point3D<float>& endPos, - const Vector3D<float>& startMom, double startE, + const math_utils::Point3D<float>& startPos, const math_utils::Point3D<float>& endPos, + const math_utils::Vector3D<float>& startMom, double startE, double endTime, double eLoss, Int_t particlePdg); template <typename Det> diff --git a/Detectors/FIT/FV0/simulation/src/Detector.cxx b/Detectors/FIT/FV0/simulation/src/Detector.cxx index 2a2ec90c637ec..d444deab53ea4 100644 --- a/Detectors/FIT/FV0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FV0/simulation/src/Detector.cxx @@ -129,9 +129,9 @@ Bool_t Detector::ProcessHits(FairVolume* v) // Get unique ID of the detector cell (sensitive volume) Int_t cellId = mGeometry->getCurrentCellId(fMC); - Point3D<float> posStart(mTrackData.mPositionStart.X(), mTrackData.mPositionStart.Y(), mTrackData.mPositionStart.Z()); - Point3D<float> posStop(positionStop.X(), positionStop.Y(), positionStop.Z()); - Vector3D<float> momStart(mTrackData.mMomentumStart.Px(), mTrackData.mMomentumStart.Py(), mTrackData.mMomentumStart.Pz()); + math_utils::Point3D<float> posStart(mTrackData.mPositionStart.X(), mTrackData.mPositionStart.Y(), mTrackData.mPositionStart.Z()); + math_utils::Point3D<float> posStop(positionStop.X(), positionStop.Y(), positionStop.Z()); + math_utils::Vector3D<float> momStart(mTrackData.mMomentumStart.Px(), mTrackData.mMomentumStart.Py(), mTrackData.mMomentumStart.Pz()); addHit(trackID, cellId, posStart, posStop, momStart, mTrackData.mMomentumStart.E(), positionStop.T(), mTrackData.mEnergyLoss, particlePdg); @@ -278,8 +278,8 @@ void Detector::ConstructGeometry() } o2::fv0::Hit* Detector::addHit(Int_t trackId, Int_t cellId, - const Point3D<float>& startPos, const Point3D<float>& endPos, - const Vector3D<float>& startMom, double startE, + const math_utils::Point3D<float>& startPos, const math_utils::Point3D<float>& endPos, + const math_utils::Vector3D<float>& startMom, double startE, double endTime, double eLoss, Int_t particlePdg) { mHits->emplace_back(trackId, cellId, startPos, endPos, startMom, startE, endTime, eLoss, particlePdg); diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 66ebe19a9431d..1246c90c0ca71 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -339,7 +339,7 @@ void MatchTPCITS::init() } // make sure T2GRot matrices are loaded into ITS geometry helper - o2::its::GeometryTGeo::Instance()->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2GRot)); + o2::its::GeometryTGeo::Instance()->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); mSectEdgeMargin2 = mParams->crudeAbsDiffCut[o2::track::kY] * mParams->crudeAbsDiffCut[o2::track::kY]; ///< precalculated ^2 std::unique_ptr<TPCTransform> fastTransform = (o2::tpc::TPCFastTransformHelperO2::instance()->create(0)); diff --git a/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h b/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h index 69f3ae4998942..8e53599cf59f0 100644 --- a/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h +++ b/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h @@ -42,7 +42,7 @@ namespace its class GeometryTGeo : public o2::itsmft::GeometryTGeo { public: - typedef o2::Transform3D Mat3D; + typedef o2::math_utils::Transform3D Mat3D; using DetMatrixCache::getMatrixL2G; using DetMatrixCache::getMatrixT2GRot; using DetMatrixCache::getMatrixT2L; @@ -67,9 +67,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already created // Use GeometryTGeo::Instance() instead GeometryTGeo(bool build = kFALSE, int loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::TransformType::T2L, // default transformations to load - o2::TransformType::T2G, - o2::TransformType::L2G)*/ + /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + o2::math_utils::TransformType::T2G, + o2::math_utils::TransformType::L2G)*/ ); /// Default destructor diff --git a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx index af38ba4929eb9..d758ef19c41df 100644 --- a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx @@ -385,7 +385,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } // build matrices - if ((mask & o2::utils::bit2Mask(o2::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation LOG(INFO) << "Loading ITS L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); @@ -397,7 +397,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation LOG(INFO) << "Loading ITS T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -408,7 +408,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { LOG(WARNING) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices"; // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading ITS T2G matrices from TGeo"; @@ -422,7 +422,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { // 2D rotation matrices for Tracking frame to Global rotations LOG(INFO) << "Loading ITS T2G rotation 2D matrices"; auto& cacheT2Gr = getCacheT2GRot(); diff --git a/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C b/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C index a1ad922b4ec2a..5cbb9c56d1279 100644 --- a/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C +++ b/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C @@ -438,8 +438,8 @@ void init(int entry = 0, int chip = 13, // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // Chip View browser->GetTabRight()->SetText("Chip View"); diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C b/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C index c1ac87a9ff933..2eb831ec8cf2c 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C @@ -48,8 +48,8 @@ void CheckClusters(std::string clusfile = "o2clus_its.root", std::string hitfile // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Hits TFile fileH(hitfile.data()); @@ -149,7 +149,7 @@ void CheckClusters(std::string clusfile = "o2clus_its.root", std::string hitfile int npix = 0; auto pattID = cluster.getPatternID(); - Point3D<float> locC; + o2::math_utils::Point3D<float> locC; if (pattID == o2::itsmft::CompCluster::InvalidPatternID || dict.isGroup(pattID)) { o2::itsmft::ClusterPattern patt(pattIt); locC = dict.getClusterCoordinates(cluster, patt); @@ -180,7 +180,7 @@ void CheckClusters(std::string clusfile = "o2clus_its.root", std::string hitfile // float dx = 0, dz = 0; int ievH = lab.getEventID(); - Point3D<float> locH, locHsta; + o2::math_utils::Point3D<float> locH, locHsta; // mean local position of the hit locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C b/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C index 810c593ff95d0..fcd76aff17200 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C @@ -41,7 +41,7 @@ void CheckDigits(std::string digifile = "itsdigits.root", std::string hitfile = // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto* gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::L2G)); + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); SegmentationAlpide seg; @@ -146,7 +146,7 @@ void CheckDigits(std::string digifile = "itsdigits.root", std::string hitfile = seg.detectorToLocal(ix, iz, x, z); - const Point3D<float> locD(x, 0., z); + const o2::math_utils::Point3D<float> locD(x, 0., z); Int_t chipID = (*digArr)[iDigit].getChipIndex(); auto lab = (labels->getLabels(iDigit))[0]; diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index f957c76f6f56c..b15347c49c913 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -61,8 +61,8 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Hits TFile* fileH = nullptr; diff --git a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C index 3d52a8dd475db..7cdcc703eb8e8 100644 --- a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C +++ b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C @@ -166,7 +166,7 @@ void DisplayTrack(Int_t event = 0, Int_t track = 0, std::string tracfile = "o2tr found: o2::its::GeometryTGeo* gman = GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // request cached transforms nc = clusArr->size(); n = 0; diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h index 5c89b3e8a73b7..477ce8b54cebb 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h @@ -47,7 +47,7 @@ struct RecoGeomHelper { BracketF yRange = {1.e9, -1.e9}, zRange = {1.e9, -1.e9}; // bounding box in tracking frame Vec2D xyEdges; - void updateLimits(const Point3D<float>& pnt); + void updateLimits(const o2::math_utils::Point3D<float>& pnt); void print() const; ClassDefNV(RecoChip, 0); }; @@ -67,7 +67,7 @@ struct RecoGeomHelper { std::vector<RecoChip> chips; Relation isPhiOutside(float phi, float toler = 0) const; - void updateLimits(const Point3D<float>& pnt); + void updateLimits(const o2::math_utils::Point3D<float>& pnt); void init(); void print() const; ClassDefNV(RecoLadder, 0); @@ -87,7 +87,7 @@ struct RecoGeomHelper { const RecoLadder& getLadder(int id) const { return ladders[id % nLadders]; } void init(); - void updateLimits(const Point3D<float>& pnt); + void updateLimits(const o2::math_utils::Point3D<float>& pnt); void print() const; int getLadderID(float phi) const; int getChipID(float z) const; diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx index e80b502cdee47..6ceabb11bd090 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx @@ -41,7 +41,7 @@ using namespace o2::constants::math; using namespace o2::utils; using o2::field::MagneticField; using Label = o2::MCCompLabel; -using Point3Df = Point3D<float>; +using Point3Df = o2::math_utils::Point3D<float>; //************************************************ // Constants hardcoded for the moment: @@ -488,7 +488,7 @@ void CookedTracker::process(gsl::span<const o2::itsmft::CompClusterExt> const& c for (const auto& comp : clusters_in_frame) { auto pattID = comp.getPatternID(); - Point3D<float> locXYZ; + o2::math_utils::Point3D<float> locXYZ; float sigmaY2 = 0.0015 * 0.0015, sigmaZ2 = sigmaY2, sigmaYZ = 0; //Dummy COG errors (about half pixel size) if (pattID != itsmft::CompCluster::InvalidPatternID) { sigmaY2 = dict.getErr2X(pattID); diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx index c7b4ffa2629b0..2c14d342e8817 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx @@ -19,7 +19,7 @@ using namespace o2::its; //_____________________________________________________________________ -void RecoGeomHelper::RecoChip::updateLimits(const Point3D<float>& pntTra) +void RecoGeomHelper::RecoChip::updateLimits(const o2::math_utils::Point3D<float>& pntTra) { // update limits from the edge point in tracking frame yRange.update(pntTra.Y()); @@ -35,7 +35,7 @@ void RecoGeomHelper::RecoChip::print() const } //_____________________________________________________________________ -void RecoGeomHelper::RecoLadder::updateLimits(const Point3D<float>& pntGlo) +void RecoGeomHelper::RecoLadder::updateLimits(const o2::math_utils::Point3D<float>& pntGlo) { // update limits from the point in Global frame float phi = pntGlo.phi(); // -pi:pi range @@ -89,7 +89,7 @@ void RecoGeomHelper::RecoLadder::print() const void RecoGeomHelper::RecoLayer::init() { auto gm = o2::its::GeometryTGeo::Instance(); - gm->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2GRot, o2::TransformType::T2L)); // more matrices ? + gm->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2L)); // more matrices ? int nHStaves = gm->getNumberOfHalfStaves(id); int nStaves = gm->getNumberOfStaves(id); @@ -117,7 +117,7 @@ void RecoGeomHelper::RecoLayer::init() gm->getSensorXAlphaRefPlane(chipID, chip.xRef, chip.alp); o2::utils::sincosf(chip.alp, chip.snAlp, chip.csAlp); - Point3D<float> edgeLoc(-dxH, 0.f, -dzH); + o2::math_utils::Point3D<float> edgeLoc(-dxH, 0.f, -dzH); auto edgeTra = gm->getMatrixT2L(chipID) ^ (edgeLoc); // edge in tracking frame chip.updateLimits(edgeTra); auto edgeGloM = gm->getMatrixT2GRot(chipID)(edgeTra); // edge in global frame @@ -207,7 +207,7 @@ void RecoGeomHelper::RecoLayer::init() } //_____________________________________________________________________ -void RecoGeomHelper::RecoLayer::updateLimits(const Point3D<float>& pntGlo) +void RecoGeomHelper::RecoLayer::updateLimits(const o2::math_utils::Point3D<float>& pntGlo) { // update limits from the point in global frame rRange.update(pntGlo.Rho()); diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/TrivialVertexer.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/TrivialVertexer.cxx index 788b8a862be67..6eb0cfbb36f5e 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/TrivialVertexer.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/TrivialVertexer.cxx @@ -27,7 +27,7 @@ using namespace o2::itsmft; using namespace o2::its; -using Point3Df = Point3D<float>; +using Point3Df = o2::math_utils::Point3D<float>; TrivialVertexer::TrivialVertexer() = default; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index ebf6857ec2cf6..88984c94daf32 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -142,7 +142,7 @@ inline std::vector<Vertex> Vertexer::exportVertices() if (fair::Logger::Logging(fair::Severity::info)) { std::cout << "\t\tFound vertex with: " << std::setw(6) << vertex.mContributors << " contributors" << std::endl; } - vertices.emplace_back(Point3D<float>(vertex.mX, vertex.mY, vertex.mZ), vertex.mRMS2, vertex.mContributors, vertex.mAvgDistance2); + vertices.emplace_back(o2::math_utils::Point3D<float>(vertex.mX, vertex.mY, vertex.mZ), vertex.mRMS2, vertex.mContributors, vertex.mAvgDistance2); vertices.back().setTimeStamp(vertex.mTimeStamp); } return vertices; diff --git a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx index 174100f3166c4..4b9a56e87d23d 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx @@ -60,7 +60,7 @@ void ioutils::convertCompactClusters(gsl::span<const itsmft::CompClusterExt> clu GeometryTGeo* geom = GeometryTGeo::Instance(); for (auto& c : clusters) { auto pattID = c.getPatternID(); - Point3D<float> locXYZ; + o2::math_utils::Point3D<float> locXYZ; float sigmaY2 = ioutils::DefClusError2Row, sigmaZ2 = ioutils::DefClusError2Col, sigmaYZ = 0; //Dummy COG errors (about half pixel size) if (pattID != itsmft::CompCluster::InvalidPatternID) { sigmaY2 = dict.getErr2X(pattID); @@ -152,14 +152,14 @@ void ioutils::loadEventData(ROframe& event, gsl::span<const itsmft::CompClusterE } event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(TransformType::T2L, TransformType::L2G)); + geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); int clusterId{0}; for (auto& c : clusters) { int layer = geom->getLayer(c.getSensorID()); auto pattID = c.getPatternID(); - Point3D<float> locXYZ; + o2::math_utils::Point3D<float> locXYZ; float sigmaY2 = ioutils::DefClusError2Row, sigmaZ2 = ioutils::DefClusError2Col, sigmaYZ = 0; //Dummy COG errors (about half pixel size) if (pattID != itsmft::CompCluster::InvalidPatternID) { sigmaY2 = dict.getErr2X(pattID); @@ -199,7 +199,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g { event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(TransformType::T2L, TransformType::L2G)); + geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); int clusterId{0}; auto first = rof.getFirstEntry(); @@ -208,7 +208,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g int layer = geom->getLayer(c.getSensorID()); auto pattID = c.getPatternID(); - Point3D<float> locXYZ; + o2::math_utils::Point3D<float> locXYZ; float sigmaY2 = ioutils::DefClusError2Row, sigmaZ2 = ioutils::DefClusError2Col, sigmaYZ = 0; //Dummy COG errors (about half pixel size) if (pattID != itsmft::CompCluster::InvalidPatternID) { sigmaY2 = dict.getErr2X(pattID); diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index 3ae9eb90fecfd..2a27bcfe725c2 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -63,8 +63,8 @@ void CookedTrackerDPL::init(InitContext& ic) o2::base::GeometryManager::loadGeometry(); o2::its::GeometryTGeo* geom = o2::its::GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::T2G)); + geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::T2G)); mTracker.setGeometry(geom); double origD[3] = {0., 0., 0.}; diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 83047fed62448..97fc88db0835f 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -61,8 +61,8 @@ void TrackerDPL::init(InitContext& ic) base::GeometryManager::loadGeometry(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(TransformType::T2L, TransformType::T2GRot, - TransformType::T2G)); + geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::T2G)); auto* chainITS = mRecChain->AddChain<o2::gpu::GPUChainITS>(); mRecChain->Init(); @@ -212,7 +212,7 @@ void TrackerDPL::run(ProcessingContext& pc) LOG(INFO) << "Found tracks: " << tracks.size(); int number = tracks.size(); trackLabels.swap(mTracker->getTrackLabels()); /// FIXME: assignment ctor is not optimal. - int shiftIdx = -rof.getFirstEntry(); // cluster entry!!! + int shiftIdx = -rof.getFirstEntry(); // cluster entry!!! rof.setFirstEntry(first); rof.setNEntries(number); copyTracks(tracks, allTracks, allClusIdx, shiftIdx); diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h index a710b02723446..21fb944c4a091 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h @@ -35,7 +35,7 @@ namespace mft class GeometryTGeo : public o2::itsmft::GeometryTGeo { public: - typedef o2::Transform3D Mat3D; + typedef o2::math_utils::Transform3D Mat3D; using DetMatrixCache::getMatrixL2G; using DetMatrixCache::getMatrixT2G; using DetMatrixCache::getMatrixT2L; @@ -57,9 +57,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already // created. Use GeometryTGeo::Instance() instead GeometryTGeo(Bool_t build = kFALSE, Int_t loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::TransformType::T2L, // default transformations to load - o2::TransformType::T2G, - o2::TransformType::L2G)*/ + /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + o2::math_utils::TransformType::T2G, + o2::math_utils::TransformType::L2G)*/ ); /// Default destructor diff --git a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx index 88a27a07881c1..9702ffd5b561f 100644 --- a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx @@ -414,10 +414,10 @@ void GeometryTGeo::fillMatrixCache(Int_t mask) Build(mask); return; } - // LOG(INFO) << "mask " << mask << " o2::utils::bit2Mask " << o2::utils::bit2Mask(o2::TransformType::L2G) << + // LOG(INFO) << "mask " << mask << " o2::utils::bit2Mask " << o2::utils::bit2Mask(o2::math_utils::TransformType::L2G) << // FairLogger::endl; // build matrices - if ((mask & o2::utils::bit2Mask(o2::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { LOG(INFO) << "Loading MFT L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); cacheL2G.setSize(mSize); @@ -427,7 +427,7 @@ void GeometryTGeo::fillMatrixCache(Int_t mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local frame transformation LOG(INFO) << "Loading MFT T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -438,7 +438,7 @@ void GeometryTGeo::fillMatrixCache(Int_t mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading MFT T2G matrices from TGeo"; auto& cacheT2G = getCacheT2G(); diff --git a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C index c617502c16be3..6eccaaf040939 100644 --- a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C @@ -61,8 +61,8 @@ void CheckTopologies(std::string clusfile = "mftclusters.root", // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::mft::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Hits TFile* fileH = nullptr; diff --git a/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx b/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx index 72229977cf3c6..e37e22a6637e4 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx @@ -61,7 +61,7 @@ InitStatus DigitizerTask::Init() mgr->RegisterAny("MFTDigitMCTruth", mMCTruthArrayPtr, kTRUE); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::L2G)); // make sure L2G matrices are loaded + geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded mDigitizer.setGeometry(geom); mDigitizer.setDigits(mDigitsArrayPtr); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 49e3315e8799e..708bb16d13f50 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -117,7 +117,7 @@ inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t l dz = constants::mft::LayerZCoordinate()[layer] - constants::mft::LayerZCoordinate()[layer1]; x_proj = cluster1.getX() + dz * cluster1.getX() * constants::mft::InverseLayerZCoordinate()[layer1]; y_proj = cluster1.getY() + dz * cluster1.getY() * constants::mft::InverseLayerZCoordinate()[layer1]; - auto clsPoint2D = Point2D<Float_t>(x_proj, y_proj); + auto clsPoint2D = math_utils::Point2D<Float_t>(x_proj, y_proj); r_proj = clsPoint2D.R(); phi_proj = clsPoint2D.Phi(); o2::utils::BringTo02PiGen(phi_proj); diff --git a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx index c53f6904d7acd..1cf85faa78a1e 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx @@ -29,7 +29,7 @@ Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t clusterId{index}, indexTableBin{0} { - auto clsPoint2D = Point2D<Float_t>(x, y); + auto clsPoint2D = math_utils::Point2D<Float_t>(x, y); rCoordinate = clsPoint2D.R(); phiCoordinate = clsPoint2D.Phi(); o2::utils::BringTo02PiGen(phiCoordinate); @@ -43,7 +43,7 @@ Cluster::Cluster(const Int_t layerIndex, const Cluster& other) indexTableBin{index_table_utils::getBinIndex(index_table_utils::getRBinIndex(layerIndex, rCoordinate), index_table_utils::getPhiBinIndex(phiCoordinate))} { - auto clsPoint2D = Point2D<Float_t>(other.getX(), other.getY()); + auto clsPoint2D = math_utils::Point2D<Float_t>(other.getX(), other.getY()); rCoordinate = clsPoint2D.R(); phiCoordinate = clsPoint2D.Phi(); o2::utils::BringTo02PiGen(phiCoordinate); diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index b077fb2301a6c..84c640766663a 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -39,14 +39,14 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g { event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(TransformType::T2L, TransformType::L2G)); + geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); int clusterId{0}; auto first = rof.getFirstEntry(); auto clusters_in_frame = rof.getROFData(clusters); for (auto& c : clusters_in_frame) { int layer = geom->getLayer(c.getSensorID()); auto pattID = c.getPatternID(); - Point3D<float> locXYZ; + o2::math_utils::Point3D<float> locXYZ; float sigmaX2 = ioutils::DefClusError2Row, sigmaY2 = ioutils::DefClusError2Col; //Dummy COG errors (about half pixel size) if (pattID != itsmft::CompCluster::InvalidPatternID) { //sigmaX2 = dict.getErr2X(pattID); // ALPIDE local X coordinate => MFT global X coordinate (ALPIDE rows) @@ -68,7 +68,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g // Transformation to the local --> global auto gloXYZ = geom->getMatrixL2G(sensorID) * locXYZ; - auto clsPoint2D = Point2D<Float_t>(gloXYZ.x(), gloXYZ.y()); + auto clsPoint2D = math_utils::Point2D<Float_t>(gloXYZ.x(), gloXYZ.y()); Float_t rCoord = clsPoint2D.R(); Float_t phiCoord = clsPoint2D.Phi(); o2::utils::BringTo02PiGen(phiCoord); diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 464fb145b5d66..a44eeada9be75 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -52,8 +52,8 @@ void TrackerDPL::init(InitContext& ic) o2::base::GeometryManager::loadGeometry(); o2::mft::GeometryTGeo* geom = o2::mft::GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::T2G)); + geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::T2G)); mTracker = std::make_unique<o2::mft::Tracker>(mUseMC); double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT diff --git a/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h b/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h index 34db8f6c6f073..658a5c1175305 100644 --- a/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h +++ b/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h @@ -78,12 +78,12 @@ class SegmentationAlpide /// or -0.5*Dz() is returned. static bool detectorToLocal(int iRow, int iCol, float& xRow, float& zCol); static bool detectorToLocal(float row, float col, float& xRow, float& zCol); - static bool detectorToLocal(float row, float col, Point3D<float>& loc); + static bool detectorToLocal(float row, float col, math_utils::Point3D<float>& loc); // same but w/o check for row/col range static void detectorToLocalUnchecked(int iRow, int iCol, float& xRow, float& zCol); static void detectorToLocalUnchecked(float row, float col, float& xRow, float& zCol); - static void detectorToLocalUnchecked(float row, float col, Point3D<float>& loc); + static void detectorToLocalUnchecked(float row, float col, math_utils::Point3D<float>& loc); static constexpr float getFirstRowCoordinate() { @@ -140,7 +140,7 @@ inline void SegmentationAlpide::detectorToLocalUnchecked(float row, float col, f } //_________________________________________________________________________________________________ -inline void SegmentationAlpide::detectorToLocalUnchecked(float row, float col, Point3D<float>& loc) +inline void SegmentationAlpide::detectorToLocalUnchecked(float row, float col, math_utils::Point3D<float>& loc) { loc.SetCoordinates(getFirstRowCoordinate() - row * PitchRow, 0.f, col * PitchCol + getFirstColCoordinate()); } @@ -164,7 +164,7 @@ inline bool SegmentationAlpide::detectorToLocal(float row, float col, float& xRo } //_________________________________________________________________________________________________ -inline bool SegmentationAlpide::detectorToLocal(float row, float col, Point3D<float>& loc) +inline bool SegmentationAlpide::detectorToLocal(float row, float col, math_utils::Point3D<float>& loc) { if (row < 0 || row >= NRows || col < 0 || col >= NCols) return false; diff --git a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/Hit.h b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/Hit.h index bc28d5ed5a54c..5ee373f84a9c1 100644 --- a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/Hit.h +++ b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/Hit.h @@ -56,7 +56,7 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> double endTime, double eLoss, unsigned char statusStart, unsigned char status); // Entrance position getters - Point3D<Float_t> GetPosStart() const { return mPosStart; } + math_utils::Point3D<Float_t> GetPosStart() const { return mPosStart; } Float_t GetStartX() const { return mPosStart.X(); } Float_t GetStartY() const { return mPosStart.Y(); } Float_t GetStartZ() const { return mPosStart.Z(); } @@ -68,8 +68,8 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> z = GetStartZ(); } // momentum getters - Vector3D<Float_t> GetMomentum() const { return mMomentum; } - Vector3D<Float_t>& GetMomentum() { return mMomentum; } + math_utils::Vector3D<Float_t> GetMomentum() const { return mMomentum; } + math_utils::Vector3D<Float_t>& GetMomentum() { return mMomentum; } Float_t GetPx() const { return mMomentum.X(); } Float_t GetPy() const { return mMomentum.Y(); } Float_t GetPz() const { return mMomentum.Z(); } @@ -108,11 +108,11 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> } private: - Vector3D<Float_t> mMomentum; ///< momentum at entrance - Point3D<Float_t> mPosStart; ///< position at entrance (base mPos give position on exit) - Float_t mE; ///< total energy at entrance - UChar_t mTrackStatusEnd; ///< MC status flag at exit - UChar_t mTrackStatusStart; ///< MC status at starting point + math_utils::Vector3D<Float_t> mMomentum; ///< momentum at entrance + math_utils::Point3D<Float_t> mPosStart; ///< position at entrance (base mPos give position on exit) + Float_t mE; ///< total energy at entrance + UChar_t mTrackStatusEnd; ///< MC status flag at exit + UChar_t mTrackStatusStart; ///< MC status at starting point ClassDefNV(Hit, 3); }; diff --git a/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx b/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx index 3155e181a7d17..67e515a35e22d 100644 --- a/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx +++ b/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx @@ -214,14 +214,14 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, UInt_t& maxFr, int evID, float nStepsInv = mParams.getNSimStepsInv(); int nSteps = mParams.getNSimSteps(); const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID()); - Vector3D<float> xyzLocS(matrix ^ (hit.GetPosStart())); // start position in sensor frame - Vector3D<float> xyzLocE(matrix ^ (hit.GetPos())); // end position in sensor frame + math_utils::Vector3D<float> xyzLocS(matrix ^ (hit.GetPosStart())); // start position in sensor frame + math_utils::Vector3D<float> xyzLocE(matrix ^ (hit.GetPos())); // end position in sensor frame - Vector3D<float> step(xyzLocE); + math_utils::Vector3D<float> step(xyzLocE); step -= xyzLocS; step *= nStepsInv; // position increment at each step // the electrons will injected in the middle of each step - Vector3D<float> stepH(step * 0.5); + math_utils::Vector3D<float> stepH(step * 0.5); xyzLocS += stepH; xyzLocE -= stepH; diff --git a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx index 293af7ca2e2c4..5cf737ee92c54 100644 --- a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx +++ b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx @@ -83,7 +83,7 @@ InitStatus HitAnalysis::Init() GeometryTGeo* geom = GeometryTGeo::Instance(); if (!geom->isBuilt()) geom->Build(true); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::L2G)); // make sure T2L matrices are loaded + geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure T2L matrices are loaded mGeometry = geom; diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h index bc9b04b4d3c46..4857f8a3032cd 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h +++ b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h @@ -36,7 +36,7 @@ std::vector<TGeoVolume*> getSensitiveVolumes(); void addAlignableVolumesMCH(); /// get the local-to-global transformation for a given detection element -o2::Transform3D getTransformation(int detElemId, const TGeoManager& geo); +o2::math_utils::Transform3D getTransformation(int detElemId, const TGeoManager& geo); } // namespace mch } // namespace o2 diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h index e8d0c0a0b2cff..8d0d639b39271 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h +++ b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h @@ -23,20 +23,20 @@ class Hit : public ::o2::BasicXYZEHit<float> { public: - Hit(int trackId = 0, short detElemId = 0, Point3D<float> entrancePoint = {}, const Point3D<float> exitPoint = {}, + Hit(int trackId = 0, short detElemId = 0, math_utils::Point3D<float> entrancePoint = {}, const math_utils::Point3D<float> exitPoint = {}, float eloss = 0.0, float length = 0.0, float tof = 0.0) : ::o2::BasicXYZEHit<float>(entrancePoint.x(), entrancePoint.y(), entrancePoint.z(), tof, eloss, trackId, detElemId), mLength{length}, mExitPoint(exitPoint) { } - Point3D<float> entrancePoint() const { return GetPos(); } - Point3D<float> exitPoint() const { return mExitPoint; } + math_utils::Point3D<float> entrancePoint() const { return GetPos(); } + math_utils::Point3D<float> exitPoint() const { return mExitPoint; } short detElemId() const { return GetDetectorID(); } private: float mLength = {}; - Point3D<float> mExitPoint = {}; + math_utils::Point3D<float> mExitPoint = {}; ClassDefNV(Hit, 1); }; diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index c9b7773eb6fe6..57e68a0ba9bec 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -103,7 +103,7 @@ void Digitizer::process(const std::vector<Hit> hits, std::vector<Digit>& digits, //______________________________________________________________________ int Digitizer::processHit(const Hit& hit, int detID, double event_time) { - Point3D<float> pos(hit.GetX(), hit.GetY(), hit.GetZ()); + math_utils::Point3D<float> pos(hit.GetX(), hit.GetY(), hit.GetZ()); Response& resp = response(isStation1(detID)); @@ -113,7 +113,7 @@ int Digitizer::processHit(const Hit& hit, int detID, double event_time) //transformation from global to local auto t = o2::mch::getTransformation(detID, *gGeoManager); - Point3D<float> lpos; + math_utils::Point3D<float> lpos; t.MasterToLocal(pos, lpos); auto anodpos = resp.getAnod(lpos.X()); diff --git a/Detectors/MUON/MCH/Simulation/src/Geometry.cxx b/Detectors/MUON/MCH/Simulation/src/Geometry.cxx index ea8976b91e6f7..a5f6a82541f78 100644 --- a/Detectors/MUON/MCH/Simulation/src/Geometry.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Geometry.cxx @@ -573,7 +573,7 @@ void addAlignableVolumesHalfChamber(int hc, std::string& parent) } // namespace impl -o2::Transform3D getTransformation(int detElemId, const TGeoManager& geo) +o2::math_utils::Transform3D getTransformation(int detElemId, const TGeoManager& geo) { int nCh = detElemId / 100; @@ -602,7 +602,7 @@ o2::Transform3D getTransformation(int detElemId, const TGeoManager& geo) throw std::runtime_error("could not get to volPathName=" + volPathName); } - return o2::Transform3D{*(navig->GetCurrentMatrix())}; + return o2::math_utils::Transform3D{*(navig->GetCurrentMatrix())}; } void addAlignableVolumesMCH() diff --git a/Detectors/MUON/MCH/Simulation/src/GeometryTest.cxx b/Detectors/MUON/MCH/Simulation/src/GeometryTest.cxx index c024f9dd95809..42aa7dc8302b0 100644 --- a/Detectors/MUON/MCH/Simulation/src/GeometryTest.cxx +++ b/Detectors/MUON/MCH/Simulation/src/GeometryTest.cxx @@ -225,11 +225,11 @@ void drawGeometry() // gl->SetStyle(TGLRnrCtx::kFill); } -o2::base::GeometryManager::MatBudgetExt getMatBudgetExt(const o2::Transform3D& t, Vector3D<double>& n, float x, float y, float thickness) +o2::base::GeometryManager::MatBudgetExt getMatBudgetExt(const o2::math_utils::Transform3D& t, math_utils::Vector3D<double>& n, float x, float y, float thickness) { - Point3D<double> point; - t.LocalToMaster(Point3D<double>{x, y, 0}, point); - return o2::base::GeometryManager::meanMaterialBudgetExt(Point3D<double>{point + n * thickness / 2.0}, Point3D<double>{point - n * thickness / 2.0}); + math_utils::Point3D<double> point; + t.LocalToMaster(math_utils::Point3D<double>{x, y, 0}, point); + return o2::base::GeometryManager::meanMaterialBudgetExt(math_utils::Point3D<double>{point + n * thickness / 2.0}, math_utils::Point3D<double>{point - n * thickness / 2.0}); } std::ostream& operator<<(std::ostream& os, o2::base::GeometryManager::MatBudgetExt m) @@ -239,14 +239,14 @@ std::ostream& operator<<(std::ostream& os, o2::base::GeometryManager::MatBudgetE return os; } -Vector3D<double> getNormalVector(const o2::Transform3D& t) +math_utils::Vector3D<double> getNormalVector(const o2::math_utils::Transform3D& t) { - Point3D<double> px, py, po; - t.LocalToMaster(Point3D<double>{0, 1, 0}, py); - t.LocalToMaster(Point3D<double>{1, 0, 0}, px); - t.LocalToMaster(Point3D<double>{0, 0, 0}, po); - Vector3D<double> a{px - po}; - Vector3D<double> b{py - po}; + math_utils::Point3D<double> px, py, po; + t.LocalToMaster(math_utils::Point3D<double>{0, 1, 0}, py); + t.LocalToMaster(math_utils::Point3D<double>{1, 0, 0}, px); + t.LocalToMaster(math_utils::Point3D<double>{0, 0, 0}, po); + math_utils::Vector3D<double> a{px - po}; + math_utils::Vector3D<double> b{py - po}; return a.Cross(b).Unit(); } diff --git a/Detectors/MUON/MCH/Simulation/src/Stepper.cxx b/Detectors/MUON/MCH/Simulation/src/Stepper.cxx index 214eda57ed184..2f50f9da9c13d 100644 --- a/Detectors/MUON/MCH/Simulation/src/Stepper.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Stepper.cxx @@ -61,7 +61,7 @@ void Stepper::process(const TVirtualMC& vmc) float x, y, z; vmc.TrackPosition(x, y, z); mHits->emplace_back(stack->GetCurrentTrackNumber(), detElemId, mEntrancePoint, - Point3D<float>{x, y, z}, mTrackEloss, mTrackLength); + math_utils::Point3D<float>{x, y, z}, mTrackEloss, mTrackLength); resetStep(); } } diff --git a/Detectors/MUON/MCH/Simulation/src/Stepper.h b/Detectors/MUON/MCH/Simulation/src/Stepper.h index 78576c48bc51c..02837f32be475 100644 --- a/Detectors/MUON/MCH/Simulation/src/Stepper.h +++ b/Detectors/MUON/MCH/Simulation/src/Stepper.h @@ -43,7 +43,7 @@ class Stepper float mTrackEloss{0.0}; float mTrackLength{0.0}; std::vector<o2::mch::Hit>* mHits{nullptr}; - Point3D<float> mEntrancePoint; + math_utils::Point3D<float> mEntrancePoint; }; } // namespace mch diff --git a/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx b/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx index 2359b427139af..bf64214d2310e 100644 --- a/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx +++ b/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx @@ -39,10 +39,10 @@ struct GEOMETRY { namespace { -Point3D<float> entrancePoint1(-17.7993, 8.929883, -522.201); //x,y,z coordinates in cm -Point3D<float> exitPoint1(-17.8136, 8.93606, -522.62); -Point3D<float> entrancePoint2(-49.2793, 28.8673, -1441.25); -Point3D<float> exitPoint2(-49.2965, 28.8806, -1441.75); +o2::math_utils::Point3D<float> entrancePoint1(-17.7993, 8.929883, -522.201); //x,y,z coordinates in cm +o2::math_utils::Point3D<float> exitPoint1(-17.8136, 8.93606, -522.62); +o2::math_utils::Point3D<float> entrancePoint2(-49.2793, 28.8673, -1441.25); +o2::math_utils::Point3D<float> exitPoint2(-49.2965, 28.8806, -1441.75); } // namespace /// \brief Test of the Digitization @@ -99,8 +99,8 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) double padsizeY = seg1.padSizeY(padid); auto t = o2::mch::getTransformation(detElemId1, *gGeoManager); - Point3D<float> pos(hits.at(0).GetX(), hits.at(0).GetY(), hits.at(0).GetZ()); - Point3D<float> lpos; + o2::math_utils::Point3D<float> pos(hits.at(0).GetX(), hits.at(0).GetY(), hits.at(0).GetZ()); + o2::math_utils::Point3D<float> lpos; t.MasterToLocal(pos, lpos); BOOST_CHECK_CLOSE(lpos.x(), padposX, padsizeX * 4.0); @@ -117,8 +117,8 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) double padsizeY = seg2.padSizeY(padid); auto t = o2::mch::getTransformation(detElemId2, *gGeoManager); - Point3D<float> pos(hits.at(1).GetX(), hits.at(1).GetY(), hits.at(1).GetZ()); - Point3D<float> lpos; + o2::math_utils::Point3D<float> pos(hits.at(1).GetX(), hits.at(1).GetY(), hits.at(1).GetZ()); + o2::math_utils::Point3D<float> lpos; t.MasterToLocal(pos, lpos); BOOST_CHECK_CLOSE(lpos.x(), padposX, padsizeX * 4.0); diff --git a/Detectors/MUON/MCH/Simulation/test/testGeometry.cxx b/Detectors/MUON/MCH/Simulation/test/testGeometry.cxx index 8e0c531d63e9f..bb8a8a583f2d4 100644 --- a/Detectors/MUON/MCH/Simulation/test/testGeometry.cxx +++ b/Detectors/MUON/MCH/Simulation/test/testGeometry.cxx @@ -196,7 +196,7 @@ bool operator==(const CoarseLocation& a, const CoarseLocation& b) CoarseLocation getDetElemCoarseLocation(int detElemId) { auto t = o2::mch::getTransformation(detElemId, *gGeoManager); - Point3D<double> localTestPos{0.0, 0.0, 0.0}; // slat center + o2::math_utils::Point3D<double> localTestPos{0.0, 0.0, 0.0}; // slat center if (detElemId < 500) { // in the rough ballpark of the center @@ -228,7 +228,7 @@ CoarseLocation getDetElemCoarseLocation(int detElemId) localTestPos.SetXYZ(95.0, -19.75, 0); // ds 104 break; } - Point3D<double> master; + o2::math_utils::Point3D<double> master; t.LocalToMaster(localTestPos, master); bool right = master.x() > 10.; diff --git a/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx index 2fa2019dc80e3..4ea61dbb14021 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx @@ -86,7 +86,7 @@ class TrackAtVertexTask /// propagate them to the corresponding vertex and send the new version // get the vertex - Point3D<double> vertex(0., 0., 0.); + math_utils::Point3D<double> vertex(0., 0., 0.); int eventVtx = readVertex(pc.inputs().get<gsl::span<char>>("vertex"), vertex); // get the tracks @@ -136,7 +136,7 @@ class TrackAtVertexTask }; //_________________________________________________________________________________________________ - int readVertex(const gsl::span<const char>& msgIn, Point3D<double>& vertex) const + int readVertex(const gsl::span<const char>& msgIn, math_utils::Point3D<double>& vertex) const { /// get the vertex and return the event number /// throw an exception in case of error @@ -151,7 +151,7 @@ class TrackAtVertexTask const int& event = *reinterpret_cast<const int*>(bufferPtr); bufferPtr += SSizeOfInt; - vertex = *reinterpret_cast<const Point3D<double>*>(bufferPtr); + vertex = *reinterpret_cast<const math_utils::Point3D<double>*>(bufferPtr); return event; } @@ -232,7 +232,7 @@ class TrackAtVertexTask } //_________________________________________________________________________________________________ - bool extrapTrackToVertex(TrackStruct& track, Point3D<double>& vertex) + bool extrapTrackToVertex(TrackStruct& track, math_utils::Point3D<double>& vertex) { /// compute the track parameters at vertex, at DCA and at the end of the absorber @@ -357,7 +357,7 @@ class TrackAtVertexTask static constexpr int SSizeOfDouble = sizeof(double); static constexpr int SSizeOfTrackParamStruct = sizeof(TrackParamStruct); static constexpr int SSizeOfClusterStruct = sizeof(ClusterStruct); - static constexpr int SSizeOfPoint3D = sizeof(Point3D<double>); + static constexpr int SSizeOfPoint3D = sizeof(math_utils::Point3D<double>); std::chrono::duration<double> mElapsedTime{}; ///< timer }; diff --git a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx b/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx index 852fe3805f9b7..ff9f145833b0c 100644 --- a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx @@ -82,7 +82,7 @@ class VertexSamplerSpec // read the corresponding vertex or set it to (0,0,0) int eventVtx(-1); - Point3D<double> vertex(0., 0., 0.); + math_utils::Point3D<double> vertex(0., 0., 0.); if (mInputFile.is_open()) { do { mInputFile.read(reinterpret_cast<char*>(&eventVtx), SSizeOfInt); @@ -116,7 +116,7 @@ class VertexSamplerSpec }; static constexpr int SSizeOfInt = sizeof(int); static constexpr int SSizeOfVertexStruct = sizeof(VertexStruct); - static constexpr int SSizeOfPoint3D = sizeof(Point3D<double>); + static constexpr int SSizeOfPoint3D = sizeof(math_utils::Point3D<double>); std::ifstream mInputFile{}; ///< input file }; diff --git a/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h b/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h index f7dcc753b1617..141f936d14da0 100644 --- a/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h +++ b/Detectors/MUON/MID/Base/include/MIDBase/GeometryTransformer.h @@ -36,44 +36,44 @@ class GeometryTransformer inline const ROOT::Math::Transform3D getMatrix(int deId) { return mTransformations[deId]; } template <typename T> - Point3D<T> localToGlobal(int deId, const Point3D<T>& position) const + math_utils::Point3D<T> localToGlobal(int deId, const math_utils::Point3D<T>& position) const { /// Converts local coordinates into global ones return mTransformations[deId](position); } template <typename T> - Point3D<T> globalToLocal(int deId, const Point3D<T>& position) const + math_utils::Point3D<T> globalToLocal(int deId, const math_utils::Point3D<T>& position) const { /// Converts global coordinates into local ones return mTransformations[deId].ApplyInverse(position); } template <typename T> - Point3D<T> localToGlobal(int deId, T xPos, T yPos) const + math_utils::Point3D<T> localToGlobal(int deId, T xPos, T yPos) const { /// Converts local coordinates into global ones - return localToGlobal(deId, Point3D<T>(xPos, yPos, 0.)); + return localToGlobal(deId, math_utils::Point3D<T>(xPos, yPos, 0.)); } template <typename T> - Point3D<T> globalToLocal(int deId, T xPos, T yPos, T zPos) const + math_utils::Point3D<T> globalToLocal(int deId, T xPos, T yPos, T zPos) const { /// Converts global coordinates into local ones - return globalToLocal(deId, Point3D<T>(xPos, yPos, zPos)); + return globalToLocal(deId, math_utils::Point3D<T>(xPos, yPos, zPos)); } template <typename T> - Vector3D<T> localToGlobal(int deId, const Vector3D<T>& direction) const + math_utils::Vector3D<T> localToGlobal(int deId, const math_utils::Vector3D<T>& direction) const { /// Converts direction in local coordinates into global ones return mTransformations[deId](direction); } template <typename T> - Vector3D<T> globalToLocal(int deId, const Vector3D<T>& direction) const + math_utils::Vector3D<T> globalToLocal(int deId, const math_utils::Vector3D<T>& direction) const { /// Converts direction in global coordinates into a local ones return mTransformations[deId].ApplyInverse(direction); } private: - std::array<o2::Transform3D, detparams::NDetectionElements> mTransformations; ///< Array of transformation matrices + std::array<o2::math_utils::Transform3D, detparams::NDetectionElements> mTransformations; ///< Array of transformation matrices }; ROOT::Math::Transform3D getDefaultChamberTransform(int ichamber); diff --git a/Detectors/MUON/MID/Base/src/GeometryTransformer.cxx b/Detectors/MUON/MID/Base/src/GeometryTransformer.cxx index c02da32a9c7de..a379ec2d646ee 100644 --- a/Detectors/MUON/MID/Base/src/GeometryTransformer.cxx +++ b/Detectors/MUON/MID/Base/src/GeometryTransformer.cxx @@ -98,7 +98,7 @@ GeometryTransformer createTransformationFromManager(const TGeoManager* geoManage if (!navig->cd(volPath.str().c_str())) { throw std::runtime_error("Could not get to volPathName=" + volPath.str()); } - geoTrans.setMatrix(ide, o2::Transform3D{*(navig->GetCurrentMatrix())}); + geoTrans.setMatrix(ide, o2::math_utils::Transform3D{*(navig->GetCurrentMatrix())}); } return geoTrans; } diff --git a/Detectors/MUON/MID/Simulation/include/MIDSimulation/Hit.h b/Detectors/MUON/MID/Simulation/include/MIDSimulation/Hit.h index dcf0a42efdbee..62c5623018a49 100644 --- a/Detectors/MUON/MID/Simulation/include/MIDSimulation/Hit.h +++ b/Detectors/MUON/MID/Simulation/include/MIDSimulation/Hit.h @@ -29,18 +29,18 @@ class Hit : public ::o2::BasicXYZEHit<float> { public: - Hit(int trackId = 0, short deId = 0, Point3D<float> entrancePoint = {}, Point3D<float> exitPoint = {}, + Hit(int trackId = 0, short deId = 0, math_utils::Point3D<float> entrancePoint = {}, math_utils::Point3D<float> exitPoint = {}, float eloss = 0.0, float length = 0.0, float tof = 0.0); - Point3D<float> entrancePoint() const { return GetPos(); } - Point3D<float> exitPoint() const { return mExitPoint; } - Point3D<float> middlePoint() const; + math_utils::Point3D<float> entrancePoint() const { return GetPos(); } + math_utils::Point3D<float> exitPoint() const { return mExitPoint; } + math_utils::Point3D<float> middlePoint() const; short detElemId() const { return GetDetectorID(); } private: float mLength = {}; - Point3D<float> mExitPoint = {}; + math_utils::Point3D<float> mExitPoint = {}; ClassDefNV(Hit, 1); }; diff --git a/Detectors/MUON/MID/Simulation/include/MIDSimulation/Stepper.h b/Detectors/MUON/MID/Simulation/include/MIDSimulation/Stepper.h index 9d623b3067ecc..1c3551563f930 100644 --- a/Detectors/MUON/MID/Simulation/include/MIDSimulation/Stepper.h +++ b/Detectors/MUON/MID/Simulation/include/MIDSimulation/Stepper.h @@ -41,7 +41,7 @@ class Stepper float mTrackEloss{0.0}; float mTrackLength{0.0}; std::vector<o2::mid::Hit>* mHits{nullptr}; - Point3D<float> mEntrancePoint; + o2::math_utils::Point3D<float> mEntrancePoint; }; } // namespace mid diff --git a/Detectors/MUON/MID/Simulation/src/Digitizer.cxx b/Detectors/MUON/MID/Simulation/src/Digitizer.cxx index be5b6686f7804..210440d9ac147 100644 --- a/Detectors/MUON/MID/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MID/Simulation/src/Digitizer.cxx @@ -95,7 +95,7 @@ bool Digitizer::hitToDigits(const Hit& hit) // Convert point from global to local coordinates auto midPt = hit.middlePoint(); int deId = hit.GetDetectorID(); - Point3D<double> localPoint = mTransformer.globalToLocal(deId, (double)midPt.x(), (double)midPt.y(), (double)midPt.z()); + math_utils::Point3D<double> localPoint = mTransformer.globalToLocal(deId, (double)midPt.x(), (double)midPt.y(), (double)midPt.z()); // First get the touched BP strip Mapping::MpStripIndex stripIndex = mMapping.stripByPosition(localPoint.x(), localPoint.y(), 0, deId); diff --git a/Detectors/MUON/MID/Simulation/src/Hit.cxx b/Detectors/MUON/MID/Simulation/src/Hit.cxx index 75e712b9045ab..395f7566835a0 100644 --- a/Detectors/MUON/MID/Simulation/src/Hit.cxx +++ b/Detectors/MUON/MID/Simulation/src/Hit.cxx @@ -21,15 +21,15 @@ namespace o2 { namespace mid { -Hit::Hit(int trackId, short deId, Point3D<float> entrancePoint, Point3D<float> exitPoint, +Hit::Hit(int trackId, short deId, math_utils::Point3D<float> entrancePoint, math_utils::Point3D<float> exitPoint, float eloss, float length, float tof) : o2::BasicXYZEHit<float>(entrancePoint.x(), entrancePoint.y(), entrancePoint.z(), tof, eloss, trackId, deId), mLength{length}, mExitPoint(exitPoint) { } -Point3D<float> Hit::middlePoint() const +math_utils::Point3D<float> Hit::middlePoint() const { /// Returns the point in between the entrance and exit - Point3D<float> middle(0.5 * (entrancePoint().x() + exitPoint().x()), 0.5 * (entrancePoint().y() + exitPoint().y()), 0.5 * (entrancePoint().z() + exitPoint().z())); + math_utils::Point3D<float> middle(0.5 * (entrancePoint().x() + exitPoint().x()), 0.5 * (entrancePoint().y() + exitPoint().y()), 0.5 * (entrancePoint().z() + exitPoint().z())); return std::move(middle); } diff --git a/Detectors/MUON/MID/Simulation/src/Stepper.cxx b/Detectors/MUON/MID/Simulation/src/Stepper.cxx index 25b0b9da6efb2..c59f7da89b3c6 100644 --- a/Detectors/MUON/MID/Simulation/src/Stepper.cxx +++ b/Detectors/MUON/MID/Simulation/src/Stepper.cxx @@ -56,7 +56,7 @@ bool Stepper::process(const TVirtualMC& vmc) float x, y, z; vmc.TrackPosition(x, y, z); mHits->emplace_back(stack->GetCurrentTrackNumber(), detElemId, mEntrancePoint, - Point3D<float>{x, y, z}, mTrackEloss, mTrackLength); + math_utils::Point3D<float>{x, y, z}, mTrackEloss, mTrackLength); resetStep(); } diff --git a/Detectors/MUON/MID/Simulation/test/testGeometry.cxx b/Detectors/MUON/MID/Simulation/test/testGeometry.cxx index 591366f3eb13a..c2729cbc4a8cf 100644 --- a/Detectors/MUON/MID/Simulation/test/testGeometry.cxx +++ b/Detectors/MUON/MID/Simulation/test/testGeometry.cxx @@ -72,7 +72,7 @@ bool areEqual(double a, double b) return std::fabs(b - a) < 1E-4; // 1E-4 cm = 1 micron } -bool areEqual(const Point3D<double>& p1, const Point3D<double>& p2) +bool areEqual(const o2::math_utils::Point3D<double>& p1, const o2::math_utils::Point3D<double>& p2) { if (!areEqual(p1.x(), p2.x())) return false; diff --git a/Detectors/MUON/MID/Simulation/test/testSimulation.cxx b/Detectors/MUON/MID/Simulation/test/testSimulation.cxx index 3878f7cd6d12f..47c92c41cf7c6 100644 --- a/Detectors/MUON/MID/Simulation/test/testSimulation.cxx +++ b/Detectors/MUON/MID/Simulation/test/testSimulation.cxx @@ -117,11 +117,11 @@ std::vector<Hit> generateHits(size_t nHits, int deId, const Mapping& mapping, co std::uniform_real_distribution<double> distX(-127.5, 127.5); std::uniform_real_distribution<double> distY(-40., 40.); while (hits.size() < nHits) { - Point3D<float> point(distX(mt), distY(mt), 0.); + math_utils::Point3D<float> point(distX(mt), distY(mt), 0.); if (!mapping.stripByPosition(point.x(), point.y(), 0, deId, false).isValid()) { continue; } - Point3D<float> globalPoint = geoTrans.localToGlobal(deId, point); + math_utils::Point3D<float> globalPoint = geoTrans.localToGlobal(deId, point); hits.emplace_back(hits.size(), deId, globalPoint, globalPoint); } return hits; diff --git a/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h b/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h index 73b165036f2ed..b86ddb96984fa 100644 --- a/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h +++ b/Detectors/MUON/MID/TestingSimTools/include/MIDTestingSimTools/HitFinder.h @@ -35,7 +35,7 @@ class HitFinder std::vector<Cluster2D> getLocalPositions(const Track& track, int chamber, bool withUncertainty = false) const; private: - Point3D<double> getIntersectInDefaultPlane(const Track& track, int chamber) const; + math_utils::Point3D<double> getIntersectInDefaultPlane(const Track& track, int chamber) const; Cluster2D getIntersect(const Track& track, int deId) const; int guessRPC(double yPos, int chamber) const; void addUncertainty(Cluster2D& cl, Track track) const; diff --git a/Detectors/MUON/MID/TestingSimTools/src/HitFinder.cxx b/Detectors/MUON/MID/TestingSimTools/src/HitFinder.cxx index cc977e01a6580..6f39180deaa2b 100644 --- a/Detectors/MUON/MID/TestingSimTools/src/HitFinder.cxx +++ b/Detectors/MUON/MID/TestingSimTools/src/HitFinder.cxx @@ -33,13 +33,13 @@ HitFinder::HitFinder(const GeometryTransformer& geoTrans) } //______________________________________________________________________________ -Point3D<double> HitFinder::getIntersectInDefaultPlane(const Track& track, int chamber) const +math_utils::Point3D<double> HitFinder::getIntersectInDefaultPlane(const Track& track, int chamber) const { /// Get the intersection point in the default chamber plane double defaultZ = geoparams::DefaultChamberZ[chamber]; double linePar = ((track.getPositionZ() - defaultZ) * mTanTheta - track.getPositionY()) / (track.getDirectionY() - track.getDirectionZ() * mTanTheta); - Point3D<double> point; + math_utils::Point3D<double> point; point.SetX(track.getPositionX() + linePar * track.getDirectionX()); point.SetY(track.getPositionY() + linePar * track.getDirectionY()); point.SetZ(track.getPositionZ() + linePar * track.getDirectionZ()); @@ -51,16 +51,16 @@ Cluster2D HitFinder::getIntersect(const Track& track, int deId) const { /// Get the intersection point in the specified detection elements /// The point is expressed in local coordinates - Point3D<float> localPoint = mGeometryTransformer.globalToLocal(deId, track.getPositionX(), track.getPositionY(), track.getPositionZ()); + math_utils::Point3D<float> localPoint = mGeometryTransformer.globalToLocal(deId, track.getPositionX(), track.getPositionY(), track.getPositionZ()); // Track localTrack(track); // localTrack.propagateToZ(localTrack.getPosition().z() + 20.); - // Point3D<float> localPoint2 = mGeometryTransformer.globalToLocal(deId, localTrack.getPosition()); + // math_utils::Point3D<float> localPoint2 = mGeometryTransformer.globalToLocal(deId, localTrack.getPosition()); // localTrack.setPosition(localPoint.x(), localPoint.y(), localPoint.z()); // float dZ = localPoint2.z() - localPoint.z(); // localTrack.setDirection((localPoint2.x() - localPoint.x()) / dZ, (localPoint2.y() - localPoint.y()) / dZ, 1.); - Vector3D<float> localDirection = mGeometryTransformer.globalToLocal(deId, Vector3D<float>(track.getDirectionX(), track.getDirectionY(), track.getDirectionZ())); + math_utils::Vector3D<float> localDirection = mGeometryTransformer.globalToLocal(deId, math_utils::Vector3D<float>(track.getDirectionX(), track.getDirectionY(), track.getDirectionZ())); Track localTrack; localTrack.setPosition(localPoint.x(), localPoint.y(), localPoint.z()); localTrack.setDirection(localDirection.x() / localDirection.z(), localDirection.y() / localDirection.z(), 1.); @@ -88,7 +88,7 @@ std::vector<int> HitFinder::getFiredDE(const Track& track, int chamber) const /// @param chamber Chamber ID (0-3) /// @return Vector with the list of the detection element IDs potentially fired std::vector<int> deIdList; - Point3D<double> defPos = getIntersectInDefaultPlane(track, chamber); + math_utils::Point3D<double> defPos = getIntersectInDefaultPlane(track, chamber); double xPos = defPos.x(); double xErr = std::sqrt(track.getCovarianceParameter(Track::CovarianceParamIndex::VarX)); double yPos = defPos.y() / mCosTheta; diff --git a/Detectors/PHOS/base/include/PHOSBase/Hit.h b/Detectors/PHOS/base/include/PHOSBase/Hit.h index 5214c21861999..f987158686a1f 100644 --- a/Detectors/PHOS/base/include/PHOSBase/Hit.h +++ b/Detectors/PHOS/base/include/PHOSBase/Hit.h @@ -38,7 +38,7 @@ class Hit : public o2::BasicXYZEHit<float> /// \param initialEnergy Energy of the primary particle enering the EMCAL /// \param tof Time of the hit /// \param length Length of the segment - Hit(Int_t trackID, Int_t detID, const Point3D<float>& pos, const Vector3D<float>& mom, Double_t totE, Double_t tof, + Hit(Int_t trackID, Int_t detID, const math_utils::Point3D<float>& pos, const math_utils::Vector3D<float>& mom, Double_t totE, Double_t tof, Double_t eLoss) : o2::BasicXYZEHit<float>(pos.X(), pos.Y(), pos.Z(), tof, eLoss, trackID, detID), mPvector(mom), @@ -84,8 +84,8 @@ class Hit : public o2::BasicXYZEHit<float> void PrintStream(std::ostream& stream) const; private: - Vector3D<float> mPvector; // Momentum Vector - Double32_t mInitialEnergy; // Energy of the parent particle that entered the PHOS front surface + math_utils::Vector3D<float> mPvector; // Momentum Vector + Double32_t mInitialEnergy; // Energy of the parent particle that entered the PHOS front surface ClassDefNV(Hit, 1); }; diff --git a/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h b/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h index f517c34c326e4..c0d7739ae4c68 100644 --- a/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h +++ b/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h @@ -95,7 +95,7 @@ class Detector : public o2::base::DetImpl<Detector> /// \param[in] time Time of the hit /// \param[in] energyloss Energy deposited in this step /// - Hit* addHit(Int_t trackID, Int_t detID, const Point3D<float>& pos, const Vector3D<float>& mom, Double_t totE, + Hit* addHit(Int_t trackID, Int_t detID, const math_utils::Point3D<float>& pos, const math_utils::Vector3D<float>& mom, Double_t totE, Double_t time, Double_t eLoss); /// diff --git a/Detectors/PHOS/simulation/src/Detector.cxx b/Detectors/PHOS/simulation/src/Detector.cxx index 1c9fd2f364bf4..4c9796ba12d1a 100644 --- a/Detectors/PHOS/simulation/src/Detector.cxx +++ b/Detectors/PHOS/simulation/src/Detector.cxx @@ -205,7 +205,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) Double_t estart = fMC->Etot(); Double_t time = fMC->TrackTime() * 1.e+9; // time in ns?? To be consistent with EMCAL - mCurrentHit = addHit(superParent, detID, Point3D<float>(posX, posY, posZ), Vector3D<float>(momX, momY, momZ), estart, + mCurrentHit = addHit(superParent, detID, math_utils::Point3D<float>(posX, posY, posZ), math_utils::Vector3D<float>(momX, momY, momZ), estart, time, lostenergy); mCurentSuperParent = superParent; mCurrentTrackID = partID; @@ -214,7 +214,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) return true; } -Hit* Detector::addHit(Int_t trackID, Int_t detID, const Point3D<float>& pos, const Vector3D<float>& mom, Double_t totE, +Hit* Detector::addHit(Int_t trackID, Int_t detID, const math_utils::Point3D<float>& pos, const math_utils::Vector3D<float>& mom, Double_t totE, Double_t time, Double_t eLoss) { LOG(DEBUG4) << "Adding hit for track " << trackID << " with position (" << pos.X() << ", " << pos.Y() << ", " diff --git a/Detectors/TOF/base/include/TOFBase/Strip.h b/Detectors/TOF/base/include/TOFBase/Strip.h index cee8e62756864..7b38c757c9e53 100644 --- a/Detectors/TOF/base/include/TOFBase/Strip.h +++ b/Detectors/TOF/base/include/TOFBase/Strip.h @@ -62,7 +62,7 @@ class Strip /// @param index New chip index void setStripIndex(Int_t index) { mStripIndex = index; } void init(Int_t index) - //, const o2::Transform3D* mat) + //, const o2::math_utils::Transform3D* mat) { mStripIndex = index; //mMat = mat; diff --git a/Detectors/TPC/base/test/testTPCBase.cxx b/Detectors/TPC/base/test/testTPCBase.cxx index dc00b9ecb19bb..37b0bca8129b1 100644 --- a/Detectors/TPC/base/test/testTPCBase.cxx +++ b/Detectors/TPC/base/test/testTPCBase.cxx @@ -23,7 +23,7 @@ namespace tpc BOOST_AUTO_TEST_CASE(Point3D_test) { - Point3D<double> testpoint(2., 3., 4.); + math_utils::Point3D<double> testpoint(2., 3., 4.); BOOST_CHECK_CLOSE(testpoint.X(), 2., 1E-12); BOOST_CHECK_CLOSE(testpoint.Y(), 3., 1E-12); BOOST_CHECK_CLOSE(testpoint.Z(), 4., 1E-12); diff --git a/Detectors/TPC/simulation/include/TPCSimulation/Point.h b/Detectors/TPC/simulation/include/TPCSimulation/Point.h index f7693a8eae19d..baad3a38fede9 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/Point.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/Point.h @@ -27,14 +27,14 @@ class ElementalHit { public: //:: so as to get the right Point3D - ::Point3D<float> mPos; // cartesian position of Hit - float mTime = -1; // time of flight - float mELoss = -2; // energy loss + math_utils::Point3D<float> mPos; // cartesian position of Hit + float mTime = -1; // time of flight + float mELoss = -2; // energy loss float GetX() const { return mPos.X(); } float GetY() const { return mPos.Y(); } float GetZ() const { return mPos.Z(); } - const ::Point3D<float>& getPos() const { return mPos; } + const math_utils::Point3D<float>& getPos() const { return mPos; } float GetEnergyLoss() const { return mELoss; } float GetTime() const { return mTime; } diff --git a/Detectors/TRD/base/src/TRDGeometry.cxx b/Detectors/TRD/base/src/TRDGeometry.cxx index 7e6a75fe6da6a..1f5c07eba90d3 100644 --- a/Detectors/TRD/base/src/TRDGeometry.cxx +++ b/Detectors/TRD/base/src/TRDGeometry.cxx @@ -2548,16 +2548,16 @@ void TRDGeometry::assembleChamber(int ilayer, int istack) void TRDGeometry::fillMatrixCache(int mask) { - if (mask & o2::utils::bit2Mask(o2::TransformType::T2L)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) { useT2LCache(); } - if (mask & o2::utils::bit2Mask(o2::TransformType::L2G)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) { useL2GCache(); } - if (mask & o2::utils::bit2Mask(o2::TransformType::T2G)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) { useT2GCache(); } - if (mask & o2::utils::bit2Mask(o2::TransformType::T2GRot)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) { useT2GRotCache(); } @@ -2614,20 +2614,20 @@ void TRDGeometry::fillMatrixCache(int mask) rotMatrix.RotateY(-90); rotMatrix.MultiplyLeft(m); const TGeoHMatrix& t2l = rotMatrix.Inverse(); - if (mask & o2::utils::bit2Mask(o2::TransformType::L2G)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) { setMatrixL2G(Mat3D(t2l), lid); } Double_t sectorAngle = 20.0 * (isector % 18) + 10.0; TGeoHMatrix rotSector; rotSector.RotateZ(sectorAngle); - if (mask & o2::utils::bit2Mask(o2::TransformType::T2G)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) { setMatrixT2G(Mat3D(rotSector), lid); } - if (mask & o2::utils::bit2Mask(o2::TransformType::T2GRot)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) { setMatrixT2GRot(Rot2D(sectorAngle), lid); } - if (mask & o2::utils::bit2Mask(o2::TransformType::T2L)) { + if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) { const TGeoMatrix& inv = rotSector.Inverse(); rotMatrix.MultiplyLeft(&inv); setMatrixT2L(Mat3D(rotMatrix.Inverse()), lid); @@ -2752,8 +2752,8 @@ bool TRDGeometry::createClusterMatrixArray() } setSize(NCHAMBER, MAXCHAMBER); //Only NCHAMBER=521 of MAXCHAMBER matrices are filled - fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L) | o2::utils::bit2Mask(o2::TransformType::L2G) | - o2::utils::bit2Mask(o2::TransformType::T2G) | o2::utils::bit2Mask(o2::TransformType::T2GRot)); + fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L) | o2::utils::bit2Mask(o2::math_utils::TransformType::L2G) | + o2::utils::bit2Mask(o2::math_utils::TransformType::T2G) | o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); return true; } diff --git a/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h b/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h index 8934bab5e60bf..4c7bf7c1bfbd7 100644 --- a/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h +++ b/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h @@ -42,7 +42,7 @@ namespace its3 class GeometryTGeo : public o2::itsmft::GeometryTGeo { public: - typedef o2::Transform3D Mat3D; + typedef o2::math_utils::Transform3D Mat3D; using DetMatrixCache::getMatrixL2G; using DetMatrixCache::getMatrixT2GRot; using DetMatrixCache::getMatrixT2L; @@ -67,9 +67,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already created // Use GeometryTGeo::Instance() instead GeometryTGeo(bool build = kFALSE, int loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::TransformType::T2L, // default transformations to load - o2::TransformType::T2G, - o2::TransformType::L2G)*/ + /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + o2::math_utils::TransformType::T2G, + o2::math_utils::TransformType::L2G)*/ ); /// Default destructor diff --git a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx index d661cf725f672..5af6c26944544 100644 --- a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx @@ -385,7 +385,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } // build matrices - if ((mask & o2::utils::bit2Mask(o2::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation LOG(INFO) << "Loading ITS L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); @@ -397,7 +397,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation LOG(INFO) << "Loading ITS T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -408,7 +408,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { LOG(WARNING) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices"; // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading ITS T2G matrices from TGeo"; @@ -422,7 +422,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { // 2D rotation matrices for Tracking frame to Global rotations LOG(INFO) << "Loading ITS T2G rotation 2D matrices"; auto& cacheT2Gr = getCacheT2GRot(); diff --git a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h index 5248112ef766f..0e45e0e0c2faa 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h +++ b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h @@ -42,7 +42,7 @@ namespace its4 class GeometryTGeo : public o2::itsmft::GeometryTGeo { public: - typedef o2::Transform3D Mat3D; + typedef o2::math_utils::Transform3D Mat3D; using DetMatrixCache::getMatrixL2G; using DetMatrixCache::getMatrixT2GRot; using DetMatrixCache::getMatrixT2L; @@ -67,9 +67,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already created // Use GeometryTGeo::Instance() instead GeometryTGeo(bool build = kFALSE, int loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::TransformType::T2L, // default transformations to load - o2::TransformType::T2G, - o2::TransformType::L2G)*/ + /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + o2::math_utils::TransformType::T2G, + o2::math_utils::TransformType::L2G)*/ ); /// Default destructor diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx index b81ff05d88717..773759cbe1343 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx @@ -385,7 +385,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } // build matrices - if ((mask & o2::utils::bit2Mask(o2::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation LOG(INFO) << "Loading ITS L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); @@ -397,7 +397,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation LOG(INFO) << "Loading ITS T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -408,7 +408,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { LOG(WARNING) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices"; // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading ITS T2G matrices from TGeo"; @@ -422,7 +422,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { + if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { // 2D rotation matrices for Tracking frame to Global rotations LOG(INFO) << "Loading ITS T2G rotation 2D matrices"; auto& cacheT2Gr = getCacheT2GRot(); diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h index 0835250b0a82d..b6e79327cd041 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h @@ -83,7 +83,7 @@ class Detector : public o2::base::DetImpl<Detector> void addAlignableVolumes() const override {} o2::zdc::Hit* addHit(Int_t trackID, Int_t parentID, Int_t sFlag, Float_t primaryEnergy, Int_t detID, Int_t secID, - Vector3D<float> pos, Vector3D<float> mom, Float_t tof, Vector3D<float> xImpact, Double_t energyloss, + math_utils::Vector3D<float> pos, math_utils::Vector3D<float> mom, Float_t tof, math_utils::Vector3D<float> xImpact, Double_t energyloss, Int_t nphePMC, Int_t nphePMQ); private: @@ -96,8 +96,8 @@ class Detector : public o2::base::DetImpl<Detector> void createDetectors(); // determine detector; sector/tower and impact coordinates given volumename and position - void getDetIDandSecID(TString const& volname, Vector3D<float> const& x, - Vector3D<float>& xDet, int& detector, int& sector) const; + void getDetIDandSecID(TString const& volname, math_utils::Vector3D<float> const& x, + math_utils::Vector3D<float>& xDet, int& detector, int& sector) const; // Define sensitive volumes void defineSensitiveVolumes(); @@ -117,7 +117,7 @@ class Detector : public o2::base::DetImpl<Detector> int parent, float tof, float trackenergy, - Vector3D<float> const& xImp, + math_utils::Vector3D<float> const& xImp, float eDep, float x, float y, float z, float px, float py, float pz) { // A new hit is created when there is nothing yet for this det + sector @@ -129,8 +129,8 @@ class Detector : public o2::base::DetImpl<Detector> mTotLightPMQ = nphe; } - Vector3D<float> pos(x, y, z); - Vector3D<float> mom(px, py, pz); + math_utils::Vector3D<float> pos(x, y, z); + math_utils::Vector3D<float> mom(px, py, pz); addHit(trackn, parent, issecondary, trackenergy, detector, sector, pos, mom, tof, xImp, eDep, mTotLightPMC, mTotLightPMQ); // stack->addHit(GetDetId()); @@ -164,7 +164,7 @@ class Detector : public o2::base::DetImpl<Detector> Float_t mTrackEta; Float_t mPrimaryEnergy; - Vector3D<float> mXImpact; + math_utils::Vector3D<float> mXImpact; Float_t mTotLightPMC; Float_t mTotLightPMQ; Int_t mMediumPMCid = -1; diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Hit.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Hit.h index a4536896134c6..9df0246c5f5db 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Hit.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Hit.h @@ -45,7 +45,7 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> /// \param nphePMC light output on common PMT /// \param nphePMQ light output on sector PMT Hit(int trackID, int parent, Bool_t sFlag, Float_t primaryEnergy, Int_t detID, Int_t sectorID, - Vector3D<float> pos, Vector3D<float> mom, Float_t tof, Vector3D<float> xImpact, Float_t energyloss, Int_t nphePMC, + math_utils::Vector3D<float> pos, math_utils::Vector3D<float> mom, Float_t tof, math_utils::Vector3D<float> xImpact, Float_t energyloss, Int_t nphePMC, Int_t nphePMQ); void setPMCLightYield(float val) { mNphePMC = val; } @@ -64,8 +64,8 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> Float_t mPrimaryEnergy; Int_t mNoContributingSteps = 1; Int_t mSectorID; - Vector3D<float> mMomentum; - Vector3D<float> mXImpact; + math_utils::Vector3D<float> mMomentum; + math_utils::Vector3D<float> mXImpact; Int_t mNphePMC; Int_t mNphePMQ; @@ -73,7 +73,7 @@ class Hit : public o2::BasicXYZEHit<Float_t, Float_t> }; inline Hit::Hit(int trackID, int parent, Bool_t sFlag, Float_t primaryEnergy, Int_t detID, Int_t sectorID, - Vector3D<float> pos, Vector3D<float> mom, Float_t tof, Vector3D<float> xImpact, Float_t energyloss, + math_utils::Vector3D<float> pos, math_utils::Vector3D<float> mom, Float_t tof, math_utils::Vector3D<float> xImpact, Float_t energyloss, Int_t nphePMC, Int_t nphePMQ) : BasicXYZEHit(pos.X(), pos.Y(), pos.Z(), tof, energyloss, trackID, detID), mParentID(parent), diff --git a/Detectors/ZDC/simulation/src/Detector.cxx b/Detectors/ZDC/simulation/src/Detector.cxx index ebc113840be29..243142bd21da7 100644 --- a/Detectors/ZDC/simulation/src/Detector.cxx +++ b/Detectors/ZDC/simulation/src/Detector.cxx @@ -188,19 +188,19 @@ void Detector::defineSensitiveVolumes() } // determines detectorID and sectorID from volume and coordinates -void Detector::getDetIDandSecID(TString const& volname, Vector3D<float> const& x, - Vector3D<float>& xDet, int& detector, int& sector) const +void Detector::getDetIDandSecID(TString const& volname, math_utils::Vector3D<float> const& x, + math_utils::Vector3D<float>& xDet, int& detector, int& sector) const { if (volname.BeginsWith("ZN")) { // for the neutron calorimeter if (x.Z() > 0) { detector = ZNA; - xDet = x - Vector3D<float>(Geometry::ZNAPOSITION[0], Geometry::ZNAPOSITION[1], Geometry::ZNAPOSITION[2]); + xDet = x - math_utils::Vector3D<float>(Geometry::ZNAPOSITION[0], Geometry::ZNAPOSITION[1], Geometry::ZNAPOSITION[2]); } else if (x.Z() < 0) { detector = ZNC; - xDet = x - Vector3D<float>(Geometry::ZNCPOSITION[0], Geometry::ZNCPOSITION[1], Geometry::ZNCPOSITION[2]); + xDet = x - math_utils::Vector3D<float>(Geometry::ZNCPOSITION[0], Geometry::ZNCPOSITION[1], Geometry::ZNCPOSITION[2]); } // now determine sector/tower if (xDet.X() <= 0.) { @@ -221,10 +221,10 @@ void Detector::getDetIDandSecID(TString const& volname, Vector3D<float> const& x // proton calorimeter if (x.Z() > 0) { detector = ZPA; // (NB -> DIFFERENT FROM AliRoot!!!) - xDet = x - Vector3D<float>(Geometry::ZPAPOSITION[0], Geometry::ZPAPOSITION[1], Geometry::ZPAPOSITION[2]); + xDet = x - math_utils::Vector3D<float>(Geometry::ZPAPOSITION[0], Geometry::ZPAPOSITION[1], Geometry::ZPAPOSITION[2]); } else if (x.Z() < 0) { detector = ZPC; // (NB -> DIFFERENT FROM AliRoot!!!) - xDet = x - Vector3D<float>(Geometry::ZPCPOSITION[0], Geometry::ZPCPOSITION[1], Geometry::ZPCPOSITION[2]); + xDet = x - math_utils::Vector3D<float>(Geometry::ZPCPOSITION[0], Geometry::ZPCPOSITION[1], Geometry::ZPCPOSITION[2]); } // determine sector/tower @@ -246,7 +246,7 @@ void Detector::getDetIDandSecID(TString const& volname, Vector3D<float> const& x } else if (volname.BeginsWith("ZE")) { // electromagnetic calorimeter detector = ZEM; - xDet = x - Vector3D<float>(Geometry::ZEMPOSITION[0], Geometry::ZEMPOSITION[1], Geometry::ZEMPOSITION[2]); + xDet = x - math_utils::Vector3D<float>(Geometry::ZEMPOSITION[0], Geometry::ZEMPOSITION[1], Geometry::ZEMPOSITION[2]); sector = (x.X() > 0.) ? Ch1 : Ch2; return; } @@ -292,8 +292,8 @@ Bool_t Detector::ProcessHits(FairVolume* v) // determine detectorID and sectorID int detector = -1; int sector = -1; - Vector3D<float> xImp; - getDetIDandSecID(volname, Vector3D<float>(x[0], x[1], x[2]), xImp, detector, sector); + math_utils::Vector3D<float> xImp; + getDetIDandSecID(volname, math_utils::Vector3D<float>(x[0], x[1], x[2]), xImp, detector, sector); auto stack = (o2::data::Stack*)fMC->GetStack(); int trackn = stack->GetCurrentTrackNumber(); @@ -388,8 +388,8 @@ Bool_t Detector::ProcessHits(FairVolume* v) mTotLightPMQ = nphe; } - Vector3D<float> pos(x[0], x[1], x[2]); - Vector3D<float> mom(p[0], p[1], p[2]); + math_utils::Vector3D<float> pos(x[0], x[1], x[2]); + math_utils::Vector3D<float> mom(p[0], p[1], p[2]); addHit(trackn, mLastPrincipalTrackEntered, issecondary, trackenergy, detector, sector, pos, mom, tof, xImp, eDep, mTotLightPMC, mTotLightPMQ); stack->addHit(GetDetId()); @@ -430,7 +430,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) bool Detector::createHitsFromImage(SpatialPhotonResponse const& image, int detector) { // one image will make one hit per sector - Vector3D<float> xImp(0., 0., 0.); // good value + math_utils::Vector3D<float> xImp(0., 0., 0.); // good value const int Nx = image.getNx(); const int Ny = image.getNy(); @@ -496,7 +496,7 @@ bool Detector::createHitsFromImage(SpatialPhotonResponse const& image, int detec //_____________________________________________________________________________ o2::zdc::Hit* Detector::addHit(Int_t trackID, Int_t parentID, Int_t sFlag, Float_t primaryEnergy, Int_t detID, - Int_t secID, Vector3D<float> pos, Vector3D<float> mom, Float_t tof, Vector3D<float> xImpact, + Int_t secID, math_utils::Vector3D<float> pos, math_utils::Vector3D<float> mom, Float_t tof, math_utils::Vector3D<float> xImpact, Double_t energyloss, Int_t nphePMC, Int_t nphePMQ) { LOG(DEBUG4) << "Adding hit for track " << trackID << " X (" << pos.X() << ", " << pos.Y() << ", " diff --git a/EventVisualisation/Detectors/src/DataInterpreterITS.cxx b/EventVisualisation/Detectors/src/DataInterpreterITS.cxx index 68d927d68653d..0e0dba781e731 100644 --- a/EventVisualisation/Detectors/src/DataInterpreterITS.cxx +++ b/EventVisualisation/Detectors/src/DataInterpreterITS.cxx @@ -44,7 +44,7 @@ DataInterpreterITS::DataInterpreterITS() //Prepare coordinate translator base::GeometryManager::loadGeometry(); its::GeometryTGeo* gman = its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2GRot)); + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); } std::unique_ptr<VisualisationEvent> DataInterpreterITS::interpretDataForType(TObject* data, EVisualisationDataType type) diff --git a/GPU/Common/GPUROOTCartesianFwd.h b/GPU/Common/GPUROOTCartesianFwd.h index 6df0fa43b0f4c..3c495a9d446af 100644 --- a/GPU/Common/GPUROOTCartesianFwd.h +++ b/GPU/Common/GPUROOTCartesianFwd.h @@ -38,9 +38,18 @@ class Cartesian3D; class DefaultCoordinateSystemTag; } // namespace Math } // namespace ROOT + +namespace o2 +{ +namespace math_utils +{ + template <typename T> using Point2D = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; template <typename T> using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +} // namespace math_utils +} // namespace o2 + #endif diff --git a/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx b/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx index 9aa51d047b13f..0e3fba8649e41 100644 --- a/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx +++ b/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx @@ -121,16 +121,16 @@ GPUdii() void GPUITSFitterKernel::Thread<0>(int nBlocks, int nThreads, int iBloc const float y3 = cluster3.positionTrackingFrame[0]; const float z3 = cluster3.positionTrackingFrame[1]; - const float crv = math_utils::computeCurvature(x1, y1, x2, y2, x3, y3); - const float x0 = math_utils::computeCurvatureCentreX(x1, y1, x2, y2, x3, y3); - const float tgl12 = math_utils::computeTanDipAngle(x1, y1, x2, y2, z1, z2); - const float tgl23 = math_utils::computeTanDipAngle(x2, y2, x3, y3, z2, z3); + const float crv = o2::its::math_utils::computeCurvature(x1, y1, x2, y2, x3, y3); + const float x0 = o2::its::math_utils::computeCurvatureCentreX(x1, y1, x2, y2, x3, y3); + const float tgl12 = o2::its::math_utils::computeTanDipAngle(x1, y1, x2, y2, z1, z2); + const float tgl23 = o2::its::math_utils::computeTanDipAngle(x2, y2, x3, y3, z2, z3); const float r2 = CAMath::Sqrt(cluster2.xCoordinate * cluster2.xCoordinate + cluster2.yCoordinate * cluster2.yCoordinate); const float r3 = CAMath::Sqrt(cluster3.xCoordinate * cluster3.xCoordinate + cluster3.yCoordinate * cluster3.yCoordinate); const float fy = 1. / (r2 - r3); const float& tz = fy; - const float cy = (math_utils::computeCurvature(x1, y1, x2, y2 + o2::its::constants::its::Resolution, x3, y3) - crv) / (o2::its::constants::its::Resolution * bz * constants::math::B2C) * 20.f; // FIXME: MS contribution to the cov[14] (*20 added) + const float cy = (o2::its::math_utils::computeCurvature(x1, y1, x2, y2 + o2::its::constants::its::Resolution, x3, y3) - crv) / (o2::its::constants::its::Resolution * bz * constants::math::B2C) * 20.f; // FIXME: MS contribution to the cov[14] (*20 added) constexpr float s2 = o2::its::constants::its::Resolution * o2::its::constants::its::Resolution; temporaryTrack.X() = cluster3.xTrackingFrame; diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx index e8e5f66cd2b57..60fb9ddd1cb2b 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx @@ -63,7 +63,7 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer } else { geom = o2::mft::GeometryTGeo::Instance(); } - geom->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::L2G)); // make sure L2G matrices are loaded + geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded mDigitizer.setGeometry(geom); mDisableQED = ic.options().get<bool>("disable-qed"); diff --git a/macro/CheckDigits_mft.C b/macro/CheckDigits_mft.C index 3b1d2aead1582..078038d41f554 100644 --- a/macro/CheckDigits_mft.C +++ b/macro/CheckDigits_mft.C @@ -43,7 +43,7 @@ void CheckDigits_mft(Int_t nEvents = 1, Int_t nMuons = 10, TString mcEngine = "T gFile->Get("FairGeoParSet"); auto* gman = o2::mft::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::L2G)); + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); SegmentationAlpide seg; @@ -83,7 +83,7 @@ void CheckDigits_mft(Int_t nEvents = 1, Int_t nMuons = 10, TString mcEngine = "T Int_t ix = d->getRow(), iz = d->getColumn(); Float_t x = 0.f, z = 0.f; seg.detectorToLocal(ix, iz, x, z); - const Point3D<Float_t> locD(x, 0., z); + const o2::math_utils::Point3D<Float_t> locD(x, 0., z); const auto& labs = labels->getLabels(nd); diff --git a/macro/run_primary_vertexer_ITS.C b/macro/run_primary_vertexer_ITS.C index 0b01978e186a0..763540f3cedc2 100644 --- a/macro/run_primary_vertexer_ITS.C +++ b/macro/run_primary_vertexer_ITS.C @@ -73,8 +73,8 @@ int run_primary_vertexer_ITS(const GPUDataTypes::DeviceType dtype = GPUDataTypes o2::base::GeometryManager::loadGeometry(path); o2::its::GeometryTGeo* geom = o2::its::GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); // request cached transforms + geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Get event header TChain mcHeaderTree("o2sim"); diff --git a/macro/run_trac_ca_its.C b/macro/run_trac_ca_its.C index c004c3dfd15a6..4ebfcc68fe74a 100644 --- a/macro/run_trac_ca_its.C +++ b/macro/run_trac_ca_its.C @@ -98,8 +98,8 @@ void run_trac_ca_its(std::string path = "./", LOG(INFO) << "ITS is in " << (isContITS ? "CONTINUOS" : "TRIGGERED") << " readout mode"; auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2L, o2::TransformType::T2GRot, - o2::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms //>>>---------- attach input data --------------->>> diff --git a/macro/run_trac_its.C b/macro/run_trac_its.C index 4f9c7c8e23e95..155acbbd6a9a5 100644 --- a/macro/run_trac_its.C +++ b/macro/run_trac_its.C @@ -74,7 +74,7 @@ void run_trac_its(std::string path = "./", std::string outputfile = "o2trac_its. o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::TransformType::T2GRot)); // request cached transforms + gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); // request cached transforms o2::base::Propagator::initFieldFromGRP(grp); auto field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); From 52e21c70b300f1b829e14c1c089c9cd1d7dc0d8b Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Thu, 8 Oct 2020 14:10:41 +0200 Subject: [PATCH 1030/1751] [math_utils] Utils + Primitive2D to math_utils ns move `Utils` and `Primitive2D` headers into the `math_utils` namespace and modify all affected code. --- .../MathUtils/include/MathUtils/Primitive2D.h | 4 +-- Common/MathUtils/include/MathUtils/Utils.h | 7 ++-- Common/MathUtils/src/MathUtilsLinkDef.h | 4 +-- Common/MathUtils/src/Primitive2D.cxx | 8 +++-- Common/MathUtils/test/testUtils.cxx | 5 ++- .../DetectorsCommonDataFormats/DetID.h | 10 +++--- .../DetMatrixCache.h | 2 +- .../Detectors/Common/src/DetMatrixCache.cxx | 1 - .../TrackParametrization.h | 26 +++++++------- DataFormats/Reconstruction/src/TrackFwd.cxx | 18 +++++----- .../src/TrackParametrization.cxx | 26 +++++++------- .../src/TrackParametrizationWithError.cxx | 22 ++++++------ Detectors/Base/include/DetectorsBase/Ray.h | 2 +- Detectors/Base/src/MatLayerCyl.cxx | 2 +- Detectors/Base/src/MatLayerCylSet.cxx | 2 +- Detectors/Base/src/Propagator.cxx | 12 +++---- .../include/GlobalTracking/MatchTPCITS.h | 4 +-- Detectors/GlobalTracking/src/MatchTOF.cxx | 12 +++---- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 34 +++++++++---------- .../ITS/base/include/ITSBase/GeometryTGeo.h | 2 +- .../ITSMFT/ITS/base/src/GeometryTGeo.cxx | 11 +++--- .../ITSMFT/ITS/macros/EVE/DisplayEventsComp.C | 4 +-- .../ITSMFT/ITS/macros/test/CheckClusters.C | 4 +-- .../ITSMFT/ITS/macros/test/CheckDigits.C | 2 +- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 6 ++-- .../ITSMFT/ITS/macros/test/DisplayTrack.C | 2 +- .../ITSReconstruction/RecoGeomHelper.h | 4 +-- .../ITS/reconstruction/src/ClustererTask.cxx | 1 - .../ITS/reconstruction/src/CookedTracker.cxx | 7 ++-- .../ITS/reconstruction/src/RecoGeomHelper.cxx | 30 ++++++++-------- .../tracking/include/ITStracking/MathUtils.h | 2 +- Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx | 4 +-- .../ITS/workflow/src/CookedTrackerSpec.cxx | 4 +-- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 4 +-- .../MFT/base/include/MFTBase/GeometryTGeo.h | 2 +- .../ITSMFT/MFT/base/src/GeometryTGeo.cxx | 9 +++-- .../ITSMFT/MFT/macros/test/CheckTopologies.C | 4 +-- .../MFT/reconstruction/src/ClustererTask.cxx | 1 - .../MFT/simulation/src/DigitizerTask.cxx | 2 +- .../tracking/include/MFTTracking/Tracker.h | 2 +- Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx | 4 +-- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 4 +-- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 4 +-- .../test/HitAnalysis/src/HitAnalysis.cxx | 2 +- .../SpacePoints/src/TrackInterpolation.cxx | 12 +++---- Detectors/TPC/simulation/src/SpaceCharge.cxx | 16 ++++----- Detectors/TRD/base/src/TRDGeometry.cxx | 22 ++++++------ .../IT3/base/include/ITS3Base/GeometryTGeo.h | 2 +- .../Upgrades/IT3/base/src/GeometryTGeo.cxx | 11 +++--- .../IT4/base/include/ITS4Base/GeometryTGeo.h | 2 +- .../PostLS4/IT4/base/src/GeometryTGeo.cxx | 11 +++--- .../include/DetectorsVertexing/DCAFitterN.h | 6 ++-- .../include/DetectorsVertexing/HelixHelper.h | 2 +- .../include/DetectorsVertexing/PVertexer.h | 4 +-- .../DetectorsVertexing/PVertexerHelpers.h | 2 +- Detectors/Vertexing/src/PVertexer.cxx | 2 +- Detectors/Vertexing/test/testDCAFitterN.cxx | 4 +-- .../Detectors/src/DataInterpreterITS.cxx | 2 +- .../include/Framework/AnalysisDataModel.h | 4 +-- .../src/ITSMFTDigitizerSpec.cxx | 2 +- macro/CheckDigits_mft.C | 2 +- macro/run_primary_vertexer_ITS.C | 4 +-- macro/run_trac_ca_its.C | 5 ++- macro/run_trac_its.C | 2 +- 64 files changed, 215 insertions(+), 224 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Primitive2D.h b/Common/MathUtils/include/MathUtils/Primitive2D.h index b2b1b8ca25b4d..d8c2ce344a73b 100644 --- a/Common/MathUtils/include/MathUtils/Primitive2D.h +++ b/Common/MathUtils/include/MathUtils/Primitive2D.h @@ -19,7 +19,7 @@ namespace o2 { -namespace utils +namespace math_utils { struct CircleXY { @@ -63,7 +63,7 @@ struct IntervalXY { ClassDefNV(IntervalXY, 1); }; -} // namespace utils +} // namespace math_utils } // namespace o2 #endif diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index 760e75fc287ad..db8642848a131 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -25,9 +25,7 @@ namespace o2 { -// namespace common -//{ -namespace utils +namespace math_utils { GPUdi() void BringTo02Pi(float& phi) { @@ -269,8 +267,7 @@ struct StatAccumulator { } }; -} // namespace utils -//} +} // namespace math_utils } // namespace o2 #endif diff --git a/Common/MathUtils/src/MathUtilsLinkDef.h b/Common/MathUtils/src/MathUtilsLinkDef.h index 0465b7dbbfb89..e2f0f8473e696 100644 --- a/Common/MathUtils/src/MathUtilsLinkDef.h +++ b/Common/MathUtils/src/MathUtilsLinkDef.h @@ -33,8 +33,8 @@ #pragma link C++ class o2::math_utils::Rotation2D + ; #pragma link C++ class o2::base::CachingTF1 + ; -#pragma link C++ class o2::utils::CircleXY + ; -#pragma link C++ class o2::utils::IntervalXY + ; +#pragma link C++ class o2::math_utils::CircleXY + ; +#pragma link C++ class o2::math_utils::IntervalXY + ; #pragma link C++ class o2::math_utils::Bracket < float> + ; #endif diff --git a/Common/MathUtils/src/Primitive2D.cxx b/Common/MathUtils/src/Primitive2D.cxx index a380d03efe44b..4f86a865cfb25 100644 --- a/Common/MathUtils/src/Primitive2D.cxx +++ b/Common/MathUtils/src/Primitive2D.cxx @@ -15,8 +15,10 @@ #include "MathUtils/Primitive2D.h" #include <cmath> -using namespace o2::utils; - +namespace o2 +{ +namespace math_utils +{ //_____________________________________________________________________ bool IntervalXY::seenByCircle(const CircleXY& circle, float eps) const { @@ -108,3 +110,5 @@ void IntervalXY::getLineCoefs(float& a, float& b, float& c) const c = xP; } } +} // namespace math_utils +} // namespace o2 diff --git a/Common/MathUtils/test/testUtils.cxx b/Common/MathUtils/test/testUtils.cxx index caae0e40e55a3..843124a742791 100644 --- a/Common/MathUtils/test/testUtils.cxx +++ b/Common/MathUtils/test/testUtils.cxx @@ -20,7 +20,6 @@ #include "MathUtils/Utils.h" using namespace o2; -using namespace utils; BOOST_AUTO_TEST_CASE(Utils_test) { @@ -34,7 +33,7 @@ BOOST_AUTO_TEST_CASE(Utils_test) double phi0 = -TMath::Pi() + i * TMath::TwoPi() / n; float x = TMath::Cos(phi0); float y = TMath::Sin(phi0); - float phi = utils::FastATan2(y, x); + float phi = math_utils::FastATan2(y, x); double diff = phi - phi0; p->Fill(phi0, diff); diff = fabs(diff); @@ -109,7 +108,7 @@ BOOST_AUTO_TEST_CASE(Utils_test) begin = std::chrono::high_resolution_clock::now(); for (int i = 0; i < iterations; ++i) { for (int j = 0; j < M; ++j) { - sum += utils::FastATan2(vy[j], vx[j]); + sum += math_utils::FastATan2(vy[j], vx[j]); } } end = std::chrono::high_resolution_clock::now(); diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h index 43988131d846b..39c915b270ec4 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h @@ -139,13 +139,13 @@ class DetID #endif // detector names, will be defined in DataSources static constexpr std::array<mask_t, nDetectors> sMasks = ///< detectot masks - {utils::bit2Mask(ITS), utils::bit2Mask(TPC), utils::bit2Mask(TRD), utils::bit2Mask(TOF), utils::bit2Mask(PHS), - utils::bit2Mask(CPV), utils::bit2Mask(EMC), utils::bit2Mask(HMP), utils::bit2Mask(MFT), utils::bit2Mask(MCH), - utils::bit2Mask(MID), utils::bit2Mask(ZDC), utils::bit2Mask(FT0), utils::bit2Mask(FV0), utils::bit2Mask(FDD), - utils::bit2Mask(ACO) + {math_utils::bit2Mask(ITS), math_utils::bit2Mask(TPC), math_utils::bit2Mask(TRD), math_utils::bit2Mask(TOF), math_utils::bit2Mask(PHS), + math_utils::bit2Mask(CPV), math_utils::bit2Mask(EMC), math_utils::bit2Mask(HMP), math_utils::bit2Mask(MFT), math_utils::bit2Mask(MCH), + math_utils::bit2Mask(MID), math_utils::bit2Mask(ZDC), math_utils::bit2Mask(FT0), math_utils::bit2Mask(FV0), math_utils::bit2Mask(FDD), + math_utils::bit2Mask(ACO) #ifdef ENABLE_UPGRADES , - utils::bit2Mask(IT3), utils::bit2Mask(IT4) + math_utils::bit2Mask(IT3), math_utils::bit2Mask(IT4) #endif }; diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h index 70b4010269c69..ab946fa0ea79c 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h @@ -101,7 +101,7 @@ class DetMatrixCache // detector derived class must define its implementation for the method to populate the matrix cache, as an // example, see ITS implementation GeometryTGeo. // The method can be called multiple times to init caches for different transformations, i.e. - // with differen mask as o2::utils::bit2Mask(T2L), or bit2Mask(L2G,T2L), but for the consistency + // with differen mask as o2::math_utils::bit2Mask(T2L), or bit2Mask(L2G,T2L), but for the consistency // check the nsens must be always the same. virtual void fillMatrixCache(int mask) = 0; diff --git a/DataFormats/Detectors/Common/src/DetMatrixCache.cxx b/DataFormats/Detectors/Common/src/DetMatrixCache.cxx index ca14e42ba9f95..7c1e4dc53fde8 100644 --- a/DataFormats/Detectors/Common/src/DetMatrixCache.cxx +++ b/DataFormats/Detectors/Common/src/DetMatrixCache.cxx @@ -13,7 +13,6 @@ #include "MathUtils/Utils.h" using namespace o2::detectors; -using namespace o2::utils; ClassImp(o2::detectors::MatrixCache<o2::math_utils::Transform3D>); ClassImp(o2::detectors::MatrixCache<o2::math_utils::Rotation2D>); diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 286cfd99b4a77..d2782c4463d33 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -165,9 +165,9 @@ class TrackParametrization // derived getters bool getXatLabR(value_t r, value_t& x, value_t bz, DirType dir = DirAuto) const; - void getCircleParamsLoc(value_t bz, o2::utils::CircleXY& circle) const; - void getCircleParams(value_t bz, o2::utils::CircleXY& circle, value_t& sna, value_t& csa) const; - void getLineParams(o2::utils::IntervalXY& line, value_t& sna, value_t& csa) const; + void getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY& circle) const; + void getCircleParams(value_t bz, o2::math_utils::CircleXY& circle, value_t& sna, value_t& csa) const; + void getLineParams(o2::math_utils::IntervalXY& line, value_t& sna, value_t& csa) const; value_t getCurvature(value_t b) const; int getCharge() const; int getSign() const; @@ -413,7 +413,7 @@ inline void TrackParametrization<value_T>::setAbsCharge(int q) //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::utils::CircleXY& c) const +inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY& c) const { // get circle params in track local frame, for straight line just set to local coordinates c.rC = getCurvature(bz); @@ -434,21 +434,21 @@ inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::ut //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::utils::CircleXY& c, value_t& sna, value_t& csa) const +inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_utils::CircleXY& c, value_t& sna, value_t& csa) const { // get circle params in loc and lab frame, for straight line just set to global coordinates getCircleParamsLoc(bz, c); - o2::utils::sincos(getAlpha(), sna, csa); - o2::utils::rotateZ(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame + o2::math_utils::sincos(getAlpha(), sna, csa); + o2::math_utils::rotateZ(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame } //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getLineParams(o2::utils::IntervalXY& ln, value_t& sna, value_t& csa) const +inline void TrackParametrization<value_T>::getLineParams(o2::math_utils::IntervalXY& ln, value_t& sna, value_t& csa) const { // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } - o2::utils::sincos(getAlpha(), sna, csa); - o2::utils::rotateZ(getX(), getY(), ln.xP, ln.yP, sna, csa); // reference point in global frame + o2::math_utils::sincos(getAlpha(), sna, csa); + o2::math_utils::rotateZ(getX(), getY(), ln.xP, ln.yP, sna, csa); // reference point in global frame value_t snp = getSnp(), csp = sqrtf((1.f - snp) * (1.f + snp)); ln.dxP = csp * csa - snp * sna; ln.dyP = snp * csa + csp * sna; @@ -481,7 +481,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu { // track pt direction phi (in 0:2pi range) value_t phi = asinf(getSnp()) + getAlpha(); - utils::BringTo02Pi(phi); + math_utils::BringTo02Pi(phi); return phi; } @@ -491,7 +491,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu { // angle of track position (in -pi:pi range) value_t phi = atan2f(getY(), getX()) + getAlpha(); - utils::BringTo02Pi(phi); + math_utils::BringTo02Pi(phi); return phi; } @@ -583,7 +583,7 @@ inline void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const xyz[0] = getX(); xyz[1] = getY(); xyz[2] = getZ(); - utils::RotateZ(xyz, getAlpha()); + math_utils::RotateZ(xyz, getAlpha()); } #ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 29949f8dd6446..bec6f2b2eae68 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -39,7 +39,7 @@ void TrackParFwd::propagateParamToZlinear(double zEnd) auto dZ = (zEnd - getZ()); auto phi0 = getPhi(); double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); + o2::math_utils::sincos(phi0, sinphi0, cosphi0); auto invtanl0 = 1.0 / getTanl(); auto n = dZ * invtanl0; mParameters(0) += n * cosphi0; @@ -58,7 +58,7 @@ void TrackParCovFwd::propagateToZlinear(double zEnd) auto tanl0 = getTanl(); auto invtanl0 = 1.0 / tanl0; double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); + o2::math_utils::sincos(phi0, sinphi0, cosphi0); auto n = dZ * invtanl0; auto m = n * invtanl0; @@ -91,7 +91,7 @@ void TrackParFwd::propagateParamToZquadratic(double zEnd, double zField) auto dZ = (zEnd - getZ()); auto phi0 = getPhi(); double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); + o2::math_utils::sincos(phi0, sinphi0, cosphi0); auto invtanl0 = 1.0 / getTanl(); auto invqpt0 = getInvQPt(); auto Hz = std::copysign(1, zField); @@ -119,7 +119,7 @@ void TrackParCovFwd::propagateToZquadratic(double zEnd, double zField) auto dZ = (zEnd - getZ()); auto phi0 = getPhi(); double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); + o2::math_utils::sincos(phi0, sinphi0, cosphi0); auto invtanl0 = 1.0 / getTanl(); auto invqpt0 = getInvQPt(); auto Hz = std::copysign(1, zField); @@ -167,12 +167,12 @@ void TrackParFwd::propagateParamToZhelix(double zEnd, double zField) auto invqpt0 = getInvQPt(); auto qpt0 = 1.0 / invqpt0; double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); + o2::math_utils::sincos(phi0, sinphi0, cosphi0); auto k = TMath::Abs(o2::constants::math::B2C * zField); auto invk = 1.0 / k; auto theta = -invqpt0 * dZ * k * invtanl0; double costheta, sintheta; - o2::utils::sincos(theta, sintheta, costheta); + o2::math_utils::sincos(theta, sintheta, costheta); auto Hz = std::copysign(1, zField); auto Y = sinphi0 * qpt0 * invk; auto X = cosphi0 * qpt0 * invk; @@ -201,12 +201,12 @@ void TrackParCovFwd::propagateToZhelix(double zEnd, double zField) auto invqpt0 = getInvQPt(); auto qpt0 = 1.0 / invqpt0; double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); + o2::math_utils::sincos(phi0, sinphi0, cosphi0); auto k = TMath::Abs(o2::constants::math::B2C * zField); auto invk = 1.0 / k; auto theta = -invqpt0 * dZ * k * invtanl0; double costheta, sintheta; - o2::utils::sincos(theta, sintheta, costheta); + o2::math_utils::sincos(theta, sintheta, costheta); auto Hz = std::copysign(1, zField); auto L = qpt0 * qpt0 * invk; auto N = dZ * invtanl0 * qpt0; @@ -319,7 +319,7 @@ void TrackParCovFwd::addMCSEffect(double dZ, double x_over_X0) auto invqpt0 = getInvQPt(); double cosphi0, sinphi0; - o2::utils::sincos(phi0, sinphi0, cosphi0); + o2::math_utils::sincos(phi0, sinphi0, cosphi0); auto csclambda = TMath::Abs(TMath::Sqrt(1 + tanl0 * tanl0) * invtanl0); auto pathLengthOverX0 = x_over_X0 * csclambda; // diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index 4733648b6e816..087b1b35af8a4 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -59,11 +59,11 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim alp = atan2f(xyz[1], xyz[0]); } if (sectorAlpha) { - alp = utils::Angle2Alpha(alp); + alp = math_utils::Angle2Alpha(alp); } // value_t sn, cs; - utils::sincos(alp, sn, cs); + math_utils::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 if (std::fabs(sn) < 2 * kSafe) { if (alp > 0) { @@ -71,22 +71,22 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim } else { alp += alp > -constants::math::PIHalf ? -2 * kSafe : 2 * kSafe; } - utils::sincos(alp, sn, cs); + math_utils::sincos(alp, sn, cs); } else if (std::fabs(cs) < 2 * kSafe) { if (alp > 0) { alp += alp > constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } else { alp += alp > -constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } - utils::sincos(alp, sn, cs); + math_utils::sincos(alp, sn, cs); } // get the vertex of origin and the momentum dim3_t ver{xyz[0], xyz[1], xyz[2]}; dim3_t mom{pxpypz[0], pxpypz[1], pxpypz[2]}; // // Rotate to the local coordinate system - utils::RotateZ(ver, -alp); - utils::RotateZ(mom, -alp); + math_utils::RotateZ(ver, -alp); + math_utils::RotateZ(mom, -alp); // value_t ptI = 1.f / sqrt(mom[0] * mom[0] + mom[1] * mom[1]); mX = ver[0]; @@ -116,7 +116,7 @@ bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const } value_t cs, sn, pt = getPt(); value_t r = std::sqrt((1.f - getSnp()) * (1.f + getSnp())); - utils::sincos(getAlpha(), sn, cs); + math_utils::sincos(getAlpha(), sn, cs); pxyz[0] = pt * (r * cs - getSnp() * sn); pxyz[1] = pt * (getSnp() * cs + r * sn); pxyz[2] = pt * getTgl(); @@ -137,7 +137,7 @@ bool TrackParametrization<value_T>::getPosDirGlo(std::array<value_t, 9>& posdirp value_t csp = std::sqrt((1.f - snp) * (1.f + snp)); value_t cstht = std::sqrt(1.f + getTgl() * getTgl()); value_t csthti = 1.f / cstht; - utils::sincos(getAlpha(), sn, cs); + math_utils::sincos(getAlpha(), sn, cs); posdirp[0] = getX() * cs - getY() * sn; posdirp[1] = getX() * sn + getY() * cs; posdirp[2] = getZ(); @@ -158,10 +158,10 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) return false; } // - utils::BringToPMPi(alpha); + math_utils::BringToPMPi(alpha); // value_t ca = 0, sa = 0; - utils::sincos(alpha - getAlpha(), sa, ca); + math_utils::sincos(alpha - getAlpha(), sa, ca); value_t snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle // direction in local frame is along the X axis @@ -358,7 +358,7 @@ bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3 { // propagate track to DCA to the vertex value_t sn, cs, alp = getAlpha(); - utils::sincos(alp, sn, cs); + math_utils::sincos(alp, sn, cs); value_t x = getX(), y = getY(), snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); value_t xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; @@ -453,7 +453,7 @@ void TrackParametrization<value_T>::invertParam() // Transform this track to the local coord. system rotated by 180 deg. mX = -mX; mAlpha += constants::math::PI; - utils::BringToPMPi(mAlpha); + math_utils::BringToPMPi(mAlpha); // mP[0] = -mP[0]; mP[3] = -mP[3]; @@ -516,7 +516,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz auto crv = getCurvature(bz); if (std::fabs(crv) > constants::math::Almost0) { // helix // get center of the track circle - utils::CircleXY circle; + math_utils::CircleXY circle; getCircleParamsLoc(bz, circle); value_t r0 = std::sqrt(circle.getCenterD2()); if (r0 <= constants::math::Almost0) { diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index 43334c905d6c2..a44f1c09e9c71 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -167,10 +167,10 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) return false; } // - utils::BringToPMPi(alpha); + math_utils::BringToPMPi(alpha); // value_t ca = 0, sa = 0; - utils::sincos(alpha - this->getAlpha(), sa, ca); + math_utils::sincos(alpha - this->getAlpha(), sa, ca); value_t snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle // direction in local frame is along the X axis @@ -218,7 +218,7 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat { // propagate track to DCA to the vertex value_t sn, cs, alp = this->getAlpha(); - o2::utils::sincos(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); value_t x = this->getX(), y = this->getY(), snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); value_t xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; @@ -247,7 +247,7 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat } *this = tmpT; if (dca) { - o2::utils::sincos(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; dca->set(this->getY() - yv, this->getZ() - zv, getSigmaY2() + s2ylocvtx, getSigmaZY(), getSigmaZ2() + vtx.getSigmaZ2()); } @@ -276,11 +276,11 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 alp = std::atan2(xyz[1], xyz[0]); } if (sectorAlpha) { - alp = utils::Angle2Alpha(alp); + alp = math_utils::Angle2Alpha(alp); } // value_t sn, cs; - utils::sincos(alp, sn, cs); + math_utils::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 if (std::fabs(sn) < 2.f * kSafe) { if (alp > 0) { @@ -288,22 +288,22 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 } else { alp += alp > -constants::math::PIHalf ? -2.f * kSafe : 2.f * kSafe; } - utils::sincos(alp, sn, cs); + math_utils::sincos(alp, sn, cs); } else if (std::fabs(cs) < 2.f * kSafe) { if (alp > 0) { alp += alp > constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } else { alp += alp > -constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } - utils::sincos(alp, sn, cs); + math_utils::sincos(alp, sn, cs); } // get the vertex of origin and the momentum dim3_t ver{xyz[0], xyz[1], xyz[2]}; dim3_t mom{pxpypz[0], pxpypz[1], pxpypz[2]}; // // Rotate to the local coordinate system - utils::RotateZ(ver, -alp); - utils::RotateZ(mom, -alp); + math_utils::RotateZ(ver, -alp); + math_utils::RotateZ(mom, -alp); // value_t pt = sqrt(mom[0] * mom[0] + mom[1] * mom[1]); value_t ptI = 1.f / pt; @@ -1022,7 +1022,7 @@ bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(std::array<value auto pt = this->getPt(); value_t sn, cs; - o2::utils::sincos(this->getAlpha(), sn, cs); + o2::math_utils::sincos(this->getAlpha(), sn, cs); auto r = std::sqrt((1. - this->getSnp()) * (1. + this->getSnp())); auto m00 = -sn, m10 = cs; auto m23 = -pt * (sn + this->getSnp() * cs / r), m43 = -pt * pt * (r * cs - this->getSnp() * sn); diff --git a/Detectors/Base/include/DetectorsBase/Ray.h b/Detectors/Base/include/DetectorsBase/Ray.h index 1867f159728a0..5924d93ce0370 100644 --- a/Detectors/Base/include/DetectorsBase/Ray.h +++ b/Detectors/Base/include/DetectorsBase/Ray.h @@ -79,7 +79,7 @@ class Ray GPUd() float getPhi(float t) const { float p = o2::gpu::CAMath::ATan2(mP[1] + t * mD[1], mP[0] + t * mD[0]); - o2::utils::BringTo02Pi(p); + o2::math_utils::BringTo02Pi(p); return p; } diff --git a/Detectors/Base/src/MatLayerCyl.cxx b/Detectors/Base/src/MatLayerCyl.cxx index 906c2f5936536..fe8468a2292af 100644 --- a/Detectors/Base/src/MatLayerCyl.cxx +++ b/Detectors/Base/src/MatLayerCyl.cxx @@ -132,7 +132,7 @@ void MatLayerCyl::populateFromTGeo(int ip, int iz, int ntrPerCell) float zs = zmn + (isz + 0.5) * dz; float dzt = zs > 0.f ? 0.25 * dz : -0.25 * dz; // to avoid 90 degree polar angle for (int isp = ntrPerCell; isp--;) { - o2::utils::sincosf(phmn + (isp + 0.5) * getDPhi() / ntrPerCell, sn, cs); + o2::math_utils::sincosf(phmn + (isp + 0.5) * getDPhi() / ntrPerCell, sn, cs); auto bud = o2::base::GeometryManager::meanMaterialBudget(rMin * cs, rMin * sn, zs - dzt, rMax * cs, rMax * sn, zs + dzt); if (bud.length > 0.) { meanRho += bud.length * bud.meanRho; diff --git a/Detectors/Base/src/MatLayerCylSet.cxx b/Detectors/Base/src/MatLayerCylSet.cxx index 13915a23fab6e..63d73318c6403 100644 --- a/Detectors/Base/src/MatLayerCylSet.cxx +++ b/Detectors/Base/src/MatLayerCylSet.cxx @@ -135,7 +135,7 @@ void MatLayerCylSet::dumpToTree(const std::string outName) const merge = ips == ips1 ? -1 : lr.canMergePhiSlices(ips, ips1); // -1 for already merged } else merge = -2; // last one - o2::utils::sincosf(phi, sn, cs); + o2::math_utils::sincosf(phi, sn, cs); float x = r * cs, y = r * sn; for (int iz = 0; iz < lr.getNZBins(); iz++) { float z = 0.5 * (lr.getZBinMin(iz) + lr.getZBinMax(iz)); diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 6b529a779189a..88ea48119afc1 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -292,7 +292,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::utils::sincosf(alp, sn, cs); + o2::math_utils::sincosf(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; @@ -321,7 +321,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac } track = tmpT; if (dca) { - o2::utils::sincosf(alp, sn, cs); + o2::math_utils::sincosf(alp, sn, cs); auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; dca->set(track.getY() - yv, track.getZ() - zv, track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2()); @@ -337,7 +337,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::utils::sincosf(alp, sn, cs); + o2::math_utils::sincosf(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; @@ -366,7 +366,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 } track = tmpT; if (dca) { - o2::utils::sincosf(alp, sn, cs); + o2::math_utils::sincosf(alp, sn, cs); auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; dca->set(track.getY() - yv, track.getZ() - zv, track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2()); @@ -382,7 +382,7 @@ bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::utils::sincosf(alp, sn, cs); + o2::math_utils::sincosf(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; @@ -426,7 +426,7 @@ bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2: { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::utils::sincosf(alp, sn, cs); + o2::math_utils::sincosf(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index eb30024ade60b..f15396095a400 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -476,9 +476,9 @@ class MatchTPCITS private: void updateTPCTimeDependentParams(); - int findLaddersToCheckBOn(int ilr, int lad0, const o2::utils::CircleXY& circle, float errYFrac, + int findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils::CircleXY& circle, float errYFrac, std::array<int, MaxLadderCand>& lad2Check) const; - int findLaddersToCheckBOff(int ilr, int lad0, const o2::utils::IntervalXY& trcLinPar, float errYFrac, + int findLaddersToCheckBOff(int ilr, int lad0, const o2::math_utils::IntervalXY& trcLinPar, float errYFrac, std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check) const; int prepareTPCTracksAfterBurner(); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 0b52c78eac0bb..e90acf6aa6a2c 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -483,9 +483,9 @@ bool MatchTOF::prepareTracks() LOG(DEBUG) << "Global coordinates After propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; LOG(DEBUG) << "Radius xy After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); LOG(DEBUG) << "Radius xyz After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); - LOG(DEBUG) << "The track will go to sector " << o2::utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + LOG(DEBUG) << "The track will go to sector " << o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); - mTracksSectIndexCache[o2::utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); + mTracksSectIndexCache[o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); //delete trc; // Check: is this needed? } @@ -626,10 +626,10 @@ bool MatchTOF::prepareTPCTracks() LOG(INFO) << "Global coordinates After propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; LOG(INFO) << "Radius xy After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); LOG(INFO) << "Radius xyz After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); - LOG(INFO) << "The track will go to sector " << o2::utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + LOG(INFO) << "The track will go to sector " << o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); #endif - mTracksSectIndexCache[o2::utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); + mTracksSectIndexCache[o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); //delete trc; // Check: is this needed? } @@ -1510,7 +1510,7 @@ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float st if (fabs(trc.getY()) > trc.getX() * tanHalfSector) { // we are still in the same sector // we need to rotate the track to go to the new sector //Printf("propagateToRefX: changing sector"); - auto alphaNew = o2::utils::Angle2Alpha(trc.getPhiPos()); + auto alphaNew = o2::math_utils::Angle2Alpha(trc.getPhiPos()); if (!trc.rotate(alphaNew) != 0) { // Printf("propagateToRefX: failed to rotate"); break; // failed (this line is taken from MatchTPCITS and the following comment too: RS: check effect on matching tracks to neighbouring sector) @@ -1548,7 +1548,7 @@ bool MatchTOF::propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef if (fabs(trcNoCov.getY()) > trcNoCov.getX() * tanHalfSector) { // we are still in the same sector // we need to rotate the track to go to the new sector //Printf("propagateToRefX: changing sector"); - auto alphaNew = o2::utils::Angle2Alpha(trcNoCov.getPhiPos()); + auto alphaNew = o2::math_utils::Angle2Alpha(trcNoCov.getPhiPos()); if (!trcNoCov.rotateParam(alphaNew) != 0) { // Printf("propagateToRefX: failed to rotate"); break; // failed (this line is taken from MatchTPCITS and the following comment too: RS: check effect on matching tracks to neighbouring sector) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 1246c90c0ca71..12ba07b67f163 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -339,7 +339,7 @@ void MatchTPCITS::init() } // make sure T2GRot matrices are loaded into ITS geometry helper - o2::its::GeometryTGeo::Instance()->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); + o2::its::GeometryTGeo::Instance()->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); mSectEdgeMargin2 = mParams->crudeAbsDiffCut[o2::track::kY] * mParams->crudeAbsDiffCut[o2::track::kY]; ///< precalculated ^2 std::unique_ptr<TPCTransform> fastTransform = (o2::tpc::TPCFastTransformHelperO2::instance()->create(0)); @@ -563,7 +563,7 @@ bool MatchTPCITS::prepareTPCTracks() // TODO : special treatment of tracks crossing the CE // cache work track index - mTPCSectIndexCache[o2::utils::Angle2Sector(trc.getAlpha())].push_back(mTPCWork.size() - 1); + mTPCSectIndexCache[o2::math_utils::Angle2Sector(trc.getAlpha())].push_back(mTPCWork.size() - 1); } /// full drift time + safety margin @@ -702,7 +702,7 @@ bool MatchTPCITS::prepareITSTracks() int nWorkTracks = mITSWork.size(); // working copy of outer track param auto& trc = mITSWork.emplace_back(static_cast<const o2::track::TrackParCov&>(trcOrig.getParamOut()), it); - if (!trc.rotate(o2::utils::Angle2Alpha(trc.getPhiPos()))) { + if (!trc.rotate(o2::math_utils::Angle2Alpha(trc.getPhiPos()))) { mITSWork.pop_back(); // discard failed track continue; } @@ -717,7 +717,7 @@ bool MatchTPCITS::prepareITSTracks() trc.roFrame = irof; // cache work track index - int sector = o2::utils::Angle2Sector(trc.getAlpha()); + int sector = o2::math_utils::Angle2Sector(trc.getAlpha()); mITSSectIndexCache[sector].push_back(nWorkTracks); // If the ITS track is very close to the sector edge, it may match also to a TPC track in the neighb. sector. @@ -1199,7 +1199,7 @@ void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector) // to their setctor edge that their matching should be checked also in the neighbouring sector mITSWork.push_back(mITSWork.back()); // clone the last track defined in given sector auto& trc = mITSWork.back(); - if (trc.rotate(o2::utils::Sector2Angle(sector)) && + if (trc.rotate(o2::math_utils::Sector2Angle(sector)) && o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, XMatchingRef, o2::constants::physics::MassPionCharged, MaxSnp, 2., MatCorrType::USEMatCorrNONE)) { // TODO: use faster prop here, no 3d field, materials @@ -1233,7 +1233,7 @@ bool MatchTPCITS::propagateToRefX(o2::track::TrackParCov& trc) if (!trialsLeft--) { break; } - auto alphaNew = o2::utils::Angle2Alpha(trc.getPhiPos()); + auto alphaNew = o2::math_utils::Angle2Alpha(trc.getPhiPos()); if (!trc.rotate(alphaNew) != 0) { break; // failed (RS: check effect on matching tracks to neighbouring sector) } @@ -1411,7 +1411,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); // rotate to 1 cluster's sector - if (!tracOut.rotate(o2::utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1451,7 +1451,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); if (prevsector != sector) { prevsector = sector; - if (!tracOut.rotate(o2::utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1592,7 +1592,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime() - timeTB, clsX, clsYZ[0], clsYZ[1]); // rotate to 1 cluster's sector - if (!tracOut.rotate(o2::utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1632,7 +1632,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime() - timeTB, clsX, clsYZ[0], clsYZ[1]); if (prevsector != sector) { prevsector = sector; - if (!tracOut.rotate(o2::utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1718,7 +1718,7 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo mTPCTransform->Transform(sectArr[icl], rowArr[icl], clsArr[icl]->getPad(), clsArr[icl]->getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); mTPCClusterParam->GetClusterErrors2(rowArr[icl], clsYZ[1], trcIn.getSnp(), trcIn.getTgl(), clsCov[0], clsCov[2]); uint8_t sectCurr = sectArr[icl]; - if (!trcIn.rotate(o2::utils::Sector2Angle(sectCurr % 18))) { + if (!trcIn.rotate(o2::math_utils::Sector2Angle(sectCurr % 18))) { LOG(WARNING) << "Rotation to sector " << int(sectCurr % 18) << " failed"; return false; } @@ -1733,7 +1733,7 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo for (; icl--;) { if (sectArr[icl] != sectCurr) { sectCurr = sectArr[icl]; - if (!trcIn.rotate(o2::utils::Sector2Angle(sectCurr % 18))) { + if (!trcIn.rotate(o2::math_utils::Sector2Angle(sectCurr % 18))) { LOG(WARNING) << "Rotation to sector " << int(sectCurr % 18) << " failed"; LOG(WARNING) << trcIn.asString(); return false; @@ -1996,8 +1996,8 @@ int MatchTPCITS::checkABSeedFromLr(int lrSeed, int seedID, ABTrackLinksList& lli return 0; } std::vector<int> chipSelClusters; // preliminary cluster candidates //RS TODO do we keep this local / consider array instead of vector - o2::utils::CircleXY trcCircle; - o2::utils::IntervalXY trcLinPar; // line parameters for B OFF data + o2::math_utils::CircleXY trcCircle; + o2::math_utils::IntervalXY trcLinPar; // line parameters for B OFF data // approximate errors float errY = std::sqrt(seed.getSigmaY2() + YErr2Extra), errYFrac = errY * mRGHelper.ladderWidthInv(), errPhi = errY * lr.rInv; if (mFieldON) { @@ -2006,7 +2006,7 @@ int MatchTPCITS::checkABSeedFromLr(int lrSeed, int seedID, ABTrackLinksList& lli seed.getLineParams(trcLinPar, sna, csa); } float xCurr, yCurr; - o2::utils::rotateZ(seed.getX(), seed.getY(), xCurr, yCurr, sna, csa); + o2::math_utils::rotateZ(seed.getX(), seed.getY(), xCurr, yCurr, sna, csa); float phi = std::atan2(yCurr, xCurr); // RS: TODO : can we use fast atan2 here? // find approximate ladder and chip_in_ladder corresponding to this track extrapolation int nLad2Check = 0, ladIDguess = lr.getLadderID(phi), chipIDguess = lr.getChipID(seed.getZ() + 0.5 * zDRStep); @@ -2126,7 +2126,7 @@ void MatchTPCITS::mergeABSeedsOnOverlaps(int ilrPar, ABTrackLinksList& llist) } //______________________________________________ -int MatchTPCITS::findLaddersToCheckBOn(int ilr, int lad0, const o2::utils::CircleXY& circle, float errYFrac, +int MatchTPCITS::findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils::CircleXY& circle, float errYFrac, std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check) const { // check if ladder lad0 and at most +-MaxUpDnLadders around it are compatible with circular track of @@ -2162,7 +2162,7 @@ int MatchTPCITS::findLaddersToCheckBOn(int ilr, int lad0, const o2::utils::Circl } //______________________________________________ -int MatchTPCITS::findLaddersToCheckBOff(int ilr, int lad0, const o2::utils::IntervalXY& trcLinPar, float errYFrac, +int MatchTPCITS::findLaddersToCheckBOff(int ilr, int lad0, const o2::math_utils::IntervalXY& trcLinPar, float errYFrac, std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check) const { // check if ladder lad0 and at most +-MaxUpDnLadders around it are compatible with linear track diff --git a/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h b/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h index 8e53599cf59f0..4c54aaf3e5a21 100644 --- a/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h +++ b/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h @@ -67,7 +67,7 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already created // Use GeometryTGeo::Instance() instead GeometryTGeo(bool build = kFALSE, int loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + /*o2::base::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load o2::math_utils::TransformType::T2G, o2::math_utils::TransformType::L2G)*/ ); diff --git a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx index d758ef19c41df..cc7ccf6610b0d 100644 --- a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx @@ -43,7 +43,6 @@ using namespace TMath; using namespace o2::its; using namespace o2::detectors; -using namespace o2::utils; using Segmentation = o2::itsmft::SegmentationAlpide; @@ -385,7 +384,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } // build matrices - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation LOG(INFO) << "Loading ITS L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); @@ -397,7 +396,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation LOG(INFO) << "Loading ITS T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -408,7 +407,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { LOG(WARNING) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices"; // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading ITS T2G matrices from TGeo"; @@ -422,7 +421,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { // 2D rotation matrices for Tracking frame to Global rotations LOG(INFO) << "Loading ITS T2G rotation 2D matrices"; auto& cacheT2Gr = getCacheT2GRot(); @@ -709,7 +708,7 @@ void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp) double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t; x = Sqrt(xp * xp + yp * yp); alp = ATan2(yp, xp); - BringTo02Pi(alp); + o2::math_utils::BringTo02Pi(alp); } //__________________________________________________________________________ diff --git a/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C b/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C index 5cbb9c56d1279..91aec1299b87c 100644 --- a/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C +++ b/Detectors/ITSMFT/ITS/macros/EVE/DisplayEventsComp.C @@ -438,8 +438,8 @@ void init(int entry = 0, int chip = 13, // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::L2G)); + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // Chip View browser->GetTabRight()->SetText("Chip View"); diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C b/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C index 2eb831ec8cf2c..f311e4268a30c 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckClusters.C @@ -48,8 +48,8 @@ void CheckClusters(std::string clusfile = "o2clus_its.root", std::string hitfile // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Hits TFile fileH(hitfile.data()); diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C b/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C index fcd76aff17200..9fa3d741f43ef 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckDigits.C @@ -41,7 +41,7 @@ void CheckDigits(std::string digifile = "itsdigits.root", std::string hitfile = // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto* gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); SegmentationAlpide seg; diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index b15347c49c913..226fe7bc37551 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -44,8 +44,8 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", using o2::itsmft::BuildTopologyDictionary; using o2::itsmft::ClusterTopology; - using o2::itsmft::CompClusterExt; using o2::itsmft::CompCluster; + using o2::itsmft::CompClusterExt; using o2::itsmft::Hit; using ROFRec = o2::itsmft::ROFRecord; using MC2ROF = o2::itsmft::MC2ROFRecord; @@ -61,8 +61,8 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Hits TFile* fileH = nullptr; diff --git a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C index 7cdcc703eb8e8..e4d47cd3666f9 100644 --- a/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C +++ b/Detectors/ITSMFT/ITS/macros/test/DisplayTrack.C @@ -166,7 +166,7 @@ void DisplayTrack(Int_t event = 0, Int_t track = 0, std::string tracfile = "o2tr found: o2::its::GeometryTGeo* gman = GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // request cached transforms nc = clusArr->size(); n = 0; diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h index 477ce8b54cebb..57d0d69d6fcb8 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h @@ -33,7 +33,7 @@ namespace its struct RecoGeomHelper { // using BracketF = o2::math_utils::Bracket<float>; - using Vec2D = o2::utils::IntervalXY; + using Vec2D = o2::math_utils::IntervalXY; enum Relation : int { Below = -1, Inside = 0, @@ -141,7 +141,7 @@ inline int RecoGeomHelper::RecoLayer::getLadderID(float phi) const // Get ladder ID corresponding to phi. // Note: this is an approximate method, precise within 1/3 of average ladder width, // one should check also the neighbouring ladders +/-1 - o2::utils::BringTo02Pi(phi); + o2::math_utils::BringTo02Pi(phi); constexpr float PI2Inv = 1.f / o2::constants::math::TwoPI; return phi2ladder[int(phi * PI2Inv * phi2ladder.size())]; } diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx index 9b22defce827e..033e5e2b92b87 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/ClustererTask.cxx @@ -20,7 +20,6 @@ #include <TTree.h> using namespace o2::its; -using namespace o2::utils; //_____________________________________________________________________ ClustererTask::ClustererTask(bool useMC, bool raw) : mRawDataMode(raw), diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx index 6ceabb11bd090..35f6f9d49313b 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx @@ -38,7 +38,6 @@ using namespace o2::its; using namespace o2::itsmft; using namespace o2::constants::math; -using namespace o2::utils; using o2::field::MagneticField; using Label = o2::MCCompLabel; using Point3Df = o2::math_utils::Point3D<float>; @@ -368,7 +367,7 @@ void CookedTracker::trackSeeds(std::vector<TrackITSExt>& seeds) auto x = track.getX(); auto y = track.getY(); Float_t phi = track.getAlpha() + TMath::ATan2(y, x); - BringTo02Pi(phi); + o2::math_utils::BringTo02Pi(phi); auto z = track.getZ(); auto crv = track.getCurvature(getBz()); @@ -700,7 +699,7 @@ void CookedTracker::Layer::init() auto xyz = c->getXYZGloRot(*mGeom); r += xyz.rho(); Float_t phi = xyz.Phi(); - BringTo02Pi(phi); + o2::math_utils::BringTo02Pi(phi); mPhi.push_back(phi); Int_t s = phi * kNSectors / k2PI; mSectors[s < kNSectors ? s : kNSectors - 1].emplace_back(i, c->getZ()); @@ -749,7 +748,7 @@ void CookedTracker::Layer::selectClusters(std::vector<Int_t>& selec, Float_t phi Float_t zMin = z - dz; Float_t zMax = z + dz; - BringTo02Pi(phi); + o2::math_utils::BringTo02Pi(phi); Float_t dphi = dy / mR; diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx index 2c14d342e8817..c3b310e3fde10 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx @@ -39,9 +39,9 @@ void RecoGeomHelper::RecoLadder::updateLimits(const o2::math_utils::Point3D<floa { // update limits from the point in Global frame float phi = pntGlo.phi(); // -pi:pi range - o2::utils::BringTo02Pi(phi); // temporary bring to 0:2pi range - o2::utils::BringTo02Pi(phiRange.getMin()); - o2::utils::BringTo02Pi(phiRange.getMax()); + o2::math_utils::BringTo02Pi(phi); // temporary bring to 0:2pi range + o2::math_utils::BringTo02Pi(phiRange.getMin()); + o2::math_utils::BringTo02Pi(phiRange.getMax()); phiRange.update(phi); phiMean = phiRange.mean(); dphiH = 0.5 * phiRange.delta(); @@ -50,9 +50,9 @@ void RecoGeomHelper::RecoLadder::updateLimits(const o2::math_utils::Point3D<floa phiMean -= o2::constants::math::PI; dphiH = o2::constants::math::PI - dphiH; } - o2::utils::BringToPMPi(phiRange.getMin()); // -pi:pi range - o2::utils::BringToPMPi(phiRange.getMax()); - o2::utils::BringToPMPi(phiMean); + o2::math_utils::BringToPMPi(phiRange.getMin()); // -pi:pi range + o2::math_utils::BringToPMPi(phiRange.getMax()); + o2::math_utils::BringToPMPi(phiMean); // zRange.update(pntGlo.Z()); } @@ -89,7 +89,7 @@ void RecoGeomHelper::RecoLadder::print() const void RecoGeomHelper::RecoLayer::init() { auto gm = o2::its::GeometryTGeo::Instance(); - gm->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2L)); // more matrices ? + gm->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2L)); // more matrices ? int nHStaves = gm->getNumberOfHalfStaves(id); int nStaves = gm->getNumberOfStaves(id); @@ -115,7 +115,7 @@ void RecoGeomHelper::RecoLayer::init() auto& chip = ladder.chips.emplace_back(); chip.id = chipID; gm->getSensorXAlphaRefPlane(chipID, chip.xRef, chip.alp); - o2::utils::sincosf(chip.alp, chip.snAlp, chip.csAlp); + o2::math_utils::sincosf(chip.alp, chip.snAlp, chip.csAlp); o2::math_utils::Point3D<float> edgeLoc(-dxH, 0.f, -dzH); auto edgeTra = gm->getMatrixT2L(chipID) ^ (edgeLoc); // edge in tracking frame @@ -136,8 +136,8 @@ void RecoGeomHelper::RecoLayer::init() // sort according to mean phi (in -pi:pi range!!!) std::sort(ladders.begin(), ladders.end(), [](auto& a, auto& b) { float pha = a.phiMean, phb = b.phiMean; - o2::utils::BringTo02Pi(pha); - o2::utils::BringTo02Pi(phb); + o2::math_utils::BringTo02Pi(pha); + o2::math_utils::BringTo02Pi(phb); return pha < phb; }); @@ -166,16 +166,16 @@ void RecoGeomHelper::RecoLayer::init() // find the radius of the edge at low phi float phi0 = std::atan2(lad.xyEdges.getY0(), lad.xyEdges.getX0()); float phi1 = std::atan2(lad.xyEdges.getY1(), lad.xyEdges.getX1()); - o2::utils::BringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa - o2::utils::BringTo02Pi(phi1); + o2::math_utils::BringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa + o2::math_utils::BringTo02Pi(phi1); float r2This = (phi0 < phi1 && phi1 - phi0 < o2::constants::math::PI) ? // pick R of lowest angle lad.xyEdges.getX0() * lad.xyEdges.getX0() + lad.xyEdges.getY0() * lad.xyEdges.getY0() : lad.xyEdges.getX1() * lad.xyEdges.getX1() + lad.xyEdges.getY1() * lad.xyEdges.getY1(); // phi0 = std::atan2(plad.xyEdges.getY0(), plad.xyEdges.getX0()); phi1 = std::atan2(plad.xyEdges.getY1(), plad.xyEdges.getX1()); - o2::utils::BringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa - o2::utils::BringTo02Pi(phi1); + o2::math_utils::BringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa + o2::math_utils::BringTo02Pi(phi1); float r2Prev = (phi0 < phi1 && phi1 - phi0 < o2::constants::math::PI) ? // pick R of highest angle plad.xyEdges.getX1() * plad.xyEdges.getX1() + plad.xyEdges.getY1() * plad.xyEdges.getY1() : plad.xyEdges.getX0() * plad.xyEdges.getX0() + plad.xyEdges.getY0() * plad.xyEdges.getY0(); @@ -189,7 +189,7 @@ void RecoGeomHelper::RecoLayer::init() int laddId = 0; for (int i = 0; i < ndiv; i++) { float phi = (0.5 + i) * dphi; - o2::utils::BringToPMPi(phi); + o2::math_utils::BringToPMPi(phi); while (laddId < nLadders) { const auto& lad = ladders[laddId]; auto rel = lad.isPhiOutside(phi); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h index b2eea8045ee0e..acdeba699af8a 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h @@ -47,7 +47,7 @@ GPUhdni() float computeTanDipAngle(float x1, float y1, float x2, float y2, float GPUhdi() float math_utils::calculatePhiCoordinate(const float xCoordinate, const float yCoordinate) { //return o2::gpu::CAMath::ATan2(-yCoordinate, -xCoordinate) + constants::math::Pi; - return utils::FastATan2(-yCoordinate, -xCoordinate) + constants::math::Pi; + return o2::math_utils::FastATan2(-yCoordinate, -xCoordinate) + constants::math::Pi; } GPUhdi() float math_utils::calculateRCoordinate(const float xCoordinate, const float yCoordinate) diff --git a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx index 4b9a56e87d23d..e521443b8da2a 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx @@ -152,7 +152,7 @@ void ioutils::loadEventData(ROframe& event, gsl::span<const itsmft::CompClusterE } event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); int clusterId{0}; for (auto& c : clusters) { @@ -199,7 +199,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g { event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); int clusterId{0}; auto first = rof.getFirstEntry(); diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index 2a27bcfe725c2..c27ac26b4a6cf 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -63,8 +63,8 @@ void CookedTrackerDPL::init(InitContext& ic) o2::base::GeometryManager::loadGeometry(); o2::its::GeometryTGeo* geom = o2::its::GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::T2G)); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::T2G)); mTracker.setGeometry(geom); double origD[3] = {0., 0., 0.}; diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 97fc88db0835f..47bfbdc8c93de 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -61,8 +61,8 @@ void TrackerDPL::init(InitContext& ic) base::GeometryManager::loadGeometry(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::T2G)); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::T2G)); auto* chainITS = mRecChain->AddChain<o2::gpu::GPUChainITS>(); mRecChain->Init(); diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h index 21fb944c4a091..bb5146fc908d2 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h @@ -57,7 +57,7 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already // created. Use GeometryTGeo::Instance() instead GeometryTGeo(Bool_t build = kFALSE, Int_t loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + /*o2::base::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load o2::math_utils::TransformType::T2G, o2::math_utils::TransformType::L2G)*/ ); diff --git a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx index 9702ffd5b561f..e3067d978a71a 100644 --- a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx @@ -43,7 +43,6 @@ using namespace TMath; using namespace o2::mft; using namespace o2::detectors; -using namespace o2::utils; using AlpideSegmentation = o2::itsmft::SegmentationAlpide; @@ -414,10 +413,10 @@ void GeometryTGeo::fillMatrixCache(Int_t mask) Build(mask); return; } - // LOG(INFO) << "mask " << mask << " o2::utils::bit2Mask " << o2::utils::bit2Mask(o2::math_utils::TransformType::L2G) << + // LOG(INFO) << "mask " << mask << " o2::math_utils::bit2Mask " << o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G) << // FairLogger::endl; // build matrices - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { LOG(INFO) << "Loading MFT L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); cacheL2G.setSize(mSize); @@ -427,7 +426,7 @@ void GeometryTGeo::fillMatrixCache(Int_t mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local frame transformation LOG(INFO) << "Loading MFT T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -438,7 +437,7 @@ void GeometryTGeo::fillMatrixCache(Int_t mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading MFT T2G matrices from TGeo"; auto& cacheT2G = getCacheT2G(); diff --git a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C index 6eccaaf040939..87690f85485d7 100644 --- a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C @@ -61,8 +61,8 @@ void CheckTopologies(std::string clusfile = "mftclusters.root", // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::mft::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::L2G)); // request cached transforms + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Hits TFile* fileH = nullptr; diff --git a/Detectors/ITSMFT/MFT/reconstruction/src/ClustererTask.cxx b/Detectors/ITSMFT/MFT/reconstruction/src/ClustererTask.cxx index a8f6c55266d36..4bff2797b2856 100644 --- a/Detectors/ITSMFT/MFT/reconstruction/src/ClustererTask.cxx +++ b/Detectors/ITSMFT/MFT/reconstruction/src/ClustererTask.cxx @@ -22,7 +22,6 @@ #include <TTree.h> using namespace o2::mft; -using namespace o2::utils; //_____________________________________________________________________ ClustererTask::ClustererTask(bool useMC, bool raw) : mRawDataMode(raw), diff --git a/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx b/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx index e37e22a6637e4..b1070a2a1da18 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/DigitizerTask.cxx @@ -61,7 +61,7 @@ InitStatus DigitizerTask::Init() mgr->RegisterAny("MFTDigitMCTruth", mMCTruthArrayPtr, kTRUE); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded mDigitizer.setGeometry(geom); mDigitizer.setDigits(mDigitsArrayPtr); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 708bb16d13f50..dbb884d5205c1 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -120,7 +120,7 @@ inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t l auto clsPoint2D = math_utils::Point2D<Float_t>(x_proj, y_proj); r_proj = clsPoint2D.R(); phi_proj = clsPoint2D.Phi(); - o2::utils::BringTo02PiGen(phi_proj); + o2::math_utils::BringTo02PiGen(phi_proj); binR_proj = constants::index_table::getRBinIndex(r_proj); binPhi_proj = constants::index_table::getPhiBinIndex(phi_proj); return; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx index 1cf85faa78a1e..98e25f6926aad 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx @@ -32,7 +32,7 @@ Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t auto clsPoint2D = math_utils::Point2D<Float_t>(x, y); rCoordinate = clsPoint2D.R(); phiCoordinate = clsPoint2D.Phi(); - o2::utils::BringTo02PiGen(phiCoordinate); + o2::math_utils::BringTo02PiGen(phiCoordinate); } Cluster::Cluster(const Int_t layerIndex, const Cluster& other) @@ -46,7 +46,7 @@ Cluster::Cluster(const Int_t layerIndex, const Cluster& other) auto clsPoint2D = math_utils::Point2D<Float_t>(other.getX(), other.getY()); rCoordinate = clsPoint2D.R(); phiCoordinate = clsPoint2D.Phi(); - o2::utils::BringTo02PiGen(phiCoordinate); + o2::math_utils::BringTo02PiGen(phiCoordinate); } } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index 84c640766663a..77c96dd9aa5ef 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -39,7 +39,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g { event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); int clusterId{0}; auto first = rof.getFirstEntry(); auto clusters_in_frame = rof.getROFData(clusters); @@ -71,7 +71,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g auto clsPoint2D = math_utils::Point2D<Float_t>(gloXYZ.x(), gloXYZ.y()); Float_t rCoord = clsPoint2D.R(); Float_t phiCoord = clsPoint2D.Phi(); - o2::utils::BringTo02PiGen(phiCoord); + o2::math_utils::BringTo02PiGen(phiCoord); int rBinIndex = constants::index_table::getRBinIndex(rCoord); int phiBinIndex = constants::index_table::getPhiBinIndex(phiCoord); int binIndex = constants::index_table::getBinIndex(rBinIndex, phiBinIndex); diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index a44eeada9be75..41e521f86e263 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -52,8 +52,8 @@ void TrackerDPL::init(InitContext& ic) o2::base::GeometryManager::loadGeometry(); o2::mft::GeometryTGeo* geom = o2::mft::GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::T2G)); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::T2G)); mTracker = std::make_unique<o2::mft::Tracker>(mUseMC); double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT diff --git a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx index 5cf737ee92c54..938df2ab07827 100644 --- a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx +++ b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx @@ -83,7 +83,7 @@ InitStatus HitAnalysis::Init() GeometryTGeo* geom = GeometryTGeo::Instance(); if (!geom->isBuilt()) geom->Build(true); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure T2L matrices are loaded + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure T2L matrices are loaded mGeometry = geom; diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index 6300b33ac2a1a..831f44c963a9e 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -156,7 +156,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo const auto& clTOF = mTOFClustersArray[matchTOF.getTOFClIndex()]; //const int clTOFSec = (TMath::ATan2(-clTOF.getY(), -clTOF.getX()) + o2::constants::math::PI) * o2::constants::math::Rad2Deg * 0.05; // taken from TOF cluster class as there is no const getter for the sector const int clTOFSec = clTOF.getCount(); - const float clTOFAlpha = o2::utils::Sector2Angle(clTOFSec); + const float clTOFAlpha = o2::math_utils::Sector2Angle(clTOFSec); const auto& trkTPC = mTPCTracksArray[matchITSTPC.getRefTPC()]; const auto& trkITS = mITSTracksArray[matchITSTPC.getRefITS()]; auto trkWork = trkITS.getParamOut(); @@ -180,7 +180,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo mCache[row].clAvailable = 1; mCache[row].clY = clTPCYZ[0]; mCache[row].clZ = clTPCYZ[1]; - mCache[row].clAngle = o2::utils::Sector2Angle(sector); + mCache[row].clAngle = o2::math_utils::Sector2Angle(sector); } // first extrapolate through TPC and store track position at each pad row @@ -212,7 +212,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo return false; } //float ca, sa; - //o2::utils::sincosf(clTOFAlpha, sa, ca); + //o2::math_utils::sincosf(clTOFAlpha, sa, ca); //float clTOFX = clTOF.getX() * ca + clTOF.getY() * sa; // cluster x in sector coordinate frame //std::array<float, 2> clTOFYZ{ -clTOF.getX() * sa + clTOF.getY() * ca, clTOF.getZ() }; // cluster y and z in sector coordinate frame float clTOFX = clTOF.getX(); @@ -274,7 +274,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo res.setZ(mCache[iRow].z[Int]); res.setPhi(mCache[iRow].phi[Int]); res.setTgl(mCache[iRow].tgl[Int]); - res.sec = o2::utils::Angle2Sector(mCache[iRow].clAngle); + res.sec = o2::math_utils::Angle2Sector(mCache[iRow].clAngle); res.dRow = deltaRow; res.row = iRow; mClRes.push_back(std::move(res)); @@ -312,7 +312,7 @@ bool TrackInterpolation::extrapolateTrackITS(const o2::its::TrackITS& trkITS, co const auto& cl = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector, row); float x = 0, y = 0, z = 0; mFastTransform->TransformIdeal(sector, row, cl.getPad(), cl.getTime(), x, y, z, clusterTimeBinOffset); - if (!trk.rotate(o2::utils::Sector2Angle(sector))) { + if (!trk.rotate(o2::math_utils::Sector2Angle(sector))) { return false; } if (!propagator->PropagateToXBxByBz(trk, x, o2::constants::physics::MassPionCharged, mMaxSnp, mMaxStep, mMatCorr)) { @@ -325,7 +325,7 @@ bool TrackInterpolation::extrapolateTrackITS(const o2::its::TrackITS& trkITS, co res.setZ(trk.getZ()); res.setPhi(trk.getSnp()); res.setTgl(trk.getTgl()); - res.sec = o2::utils::Angle2Sector(trk.getAlpha()); + res.sec = o2::math_utils::Angle2Sector(trk.getAlpha()); res.dRow = row - rowPrev; res.row = row; rowPrev = row; diff --git a/Detectors/TPC/simulation/src/SpaceCharge.cxx b/Detectors/TPC/simulation/src/SpaceCharge.cxx index 8af0e6027ce99..16c80d3c8c97e 100644 --- a/Detectors/TPC/simulation/src/SpaceCharge.cxx +++ b/Detectors/TPC/simulation/src/SpaceCharge.cxx @@ -196,7 +196,7 @@ float SpaceCharge::calculateLookupTables() matrixDriftRPhi = mMatrixIonDriftRPhiC[iphi].get(); matrixDriftR = mMatrixIonDriftRC[iphi].get(); } - int roc = iside == 0 ? o2::utils::Angle2Sector(phi) : o2::utils::Angle2Sector(phi) + 18; + int roc = iside == 0 ? o2::math_utils::Angle2Sector(phi) : o2::math_utils::Angle2Sector(phi) + 18; for (int ir = 0; ir < mNR; ++ir) { const float radius = static_cast<float>(mCoordR[ir]); /// TODO: what is the electric field stored in the LUTs at iz=0 and iz=mNZSlices-1 @@ -536,7 +536,7 @@ void SpaceCharge::propagateIons() double dz = 0.f; lookUpIonDrift->GetValue(rIon, phiIon, std::abs(zIon), dr, drphi, dz); float phiIonF = static_cast<float>(phiIon + (drphi / rIon)); - o2::utils::BringTo02PiGen(phiIonF); + o2::math_utils::BringTo02PiGen(phiIonF); rIon += dr; zIon += dz; @@ -582,8 +582,8 @@ void SpaceCharge::correctElectron(GlobalPosition3D& point) const float x[3] = {point.X(), point.Y(), point.Z()}; float dx[3] = {0.f, 0.f, 0.f}; float phi = point.phi(); - o2::utils::BringTo02PiGen(phi); - int roc = o2::utils::Angle2Sector(phi); + o2::math_utils::BringTo02PiGen(phi); + int roc = o2::math_utils::Angle2Sector(phi); /// FIXME: which side when z==0? if (x[2] < 0) { roc += 18; @@ -600,8 +600,8 @@ void SpaceCharge::distortElectron(GlobalPosition3D& point) const const float x[3] = {point.X(), point.Y(), point.Z()}; float dx[3] = {0.f, 0.f, 0.f}; float phi = point.phi(); - o2::utils::BringTo02PiGen(phi); - int roc = o2::utils::Angle2Sector(phi); + o2::math_utils::BringTo02PiGen(phi); + int roc = o2::math_utils::Angle2Sector(phi); /// FIXME: which side when z==0? if (x[2] < 0) { roc += 18; @@ -613,8 +613,8 @@ void SpaceCharge::distortElectron(GlobalPosition3D& point) const double SpaceCharge::getChargeDensity(Side side, const GlobalPosition3D& point) const { Float_t x[3] = {point.rho(), point.phi(), point.z()}; - o2::utils::BringTo02PiGen(x[1]); - const int roc = side == Side::A ? o2::utils::Angle2Sector(x[1]) : o2::utils::Angle2Sector(x[1]) + 18; + o2::math_utils::BringTo02PiGen(x[1]); + const int roc = side == Side::A ? o2::math_utils::Angle2Sector(x[1]) : o2::math_utils::Angle2Sector(x[1]) + 18; return mLookUpTableCalculator.GetChargeCylAC(x, roc); } diff --git a/Detectors/TRD/base/src/TRDGeometry.cxx b/Detectors/TRD/base/src/TRDGeometry.cxx index 1f5c07eba90d3..ad47e283eb100 100644 --- a/Detectors/TRD/base/src/TRDGeometry.cxx +++ b/Detectors/TRD/base/src/TRDGeometry.cxx @@ -15,7 +15,7 @@ #include <FairLogger.h> #include "DetectorsBase/GeometryManager.h" -#include "MathUtils/Utils.h" // utils::bit2Mask +#include "MathUtils/Utils.h" // math_utils::bit2Mask #include "TRDBase/TRDGeometry.h" #include "TRDBase/TRDPadPlane.h" @@ -2548,16 +2548,16 @@ void TRDGeometry::assembleChamber(int ilayer, int istack) void TRDGeometry::fillMatrixCache(int mask) { - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) { useT2LCache(); } - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) { useL2GCache(); } - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G)) { useT2GCache(); } - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) { useT2GRotCache(); } @@ -2614,20 +2614,20 @@ void TRDGeometry::fillMatrixCache(int mask) rotMatrix.RotateY(-90); rotMatrix.MultiplyLeft(m); const TGeoHMatrix& t2l = rotMatrix.Inverse(); - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) { setMatrixL2G(Mat3D(t2l), lid); } Double_t sectorAngle = 20.0 * (isector % 18) + 10.0; TGeoHMatrix rotSector; rotSector.RotateZ(sectorAngle); - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G)) { setMatrixT2G(Mat3D(rotSector), lid); } - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) { setMatrixT2GRot(Rot2D(sectorAngle), lid); } - if (mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) { + if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) { const TGeoMatrix& inv = rotSector.Inverse(); rotMatrix.MultiplyLeft(&inv); setMatrixT2L(Mat3D(rotMatrix.Inverse()), lid); @@ -2752,8 +2752,8 @@ bool TRDGeometry::createClusterMatrixArray() } setSize(NCHAMBER, MAXCHAMBER); //Only NCHAMBER=521 of MAXCHAMBER matrices are filled - fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L) | o2::utils::bit2Mask(o2::math_utils::TransformType::L2G) | - o2::utils::bit2Mask(o2::math_utils::TransformType::T2G) | o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); + fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L) | o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G) | + o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G) | o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); return true; } diff --git a/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h b/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h index 4c7bf7c1bfbd7..b37e393291fc7 100644 --- a/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h +++ b/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h @@ -67,7 +67,7 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already created // Use GeometryTGeo::Instance() instead GeometryTGeo(bool build = kFALSE, int loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + /*o2::base::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load o2::math_utils::TransformType::T2G, o2::math_utils::TransformType::L2G)*/ ); diff --git a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx index 5af6c26944544..f4ed7087cd25b 100644 --- a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx @@ -43,7 +43,6 @@ using namespace TMath; using namespace o2::its3; using namespace o2::detectors; -using namespace o2::utils; using Segmentation = o2::itsmft::SegmentationAlpide; @@ -385,7 +384,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } // build matrices - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation LOG(INFO) << "Loading ITS L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); @@ -397,7 +396,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation LOG(INFO) << "Loading ITS T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -408,7 +407,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { LOG(WARNING) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices"; // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading ITS T2G matrices from TGeo"; @@ -422,7 +421,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { // 2D rotation matrices for Tracking frame to Global rotations LOG(INFO) << "Loading ITS T2G rotation 2D matrices"; auto& cacheT2Gr = getCacheT2GRot(); @@ -709,7 +708,7 @@ void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp) double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t; x = Sqrt(xp * xp + yp * yp); alp = ATan2(yp, xp); - BringTo02Pi(alp); + o2::math_utils::BringTo02Pi(alp); } //__________________________________________________________________________ diff --git a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h index 0e45e0e0c2faa..a52cce3d63b54 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h +++ b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h @@ -67,7 +67,7 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo // NEVER use it, it will throw exception if the class instance was already created // Use GeometryTGeo::Instance() instead GeometryTGeo(bool build = kFALSE, int loadTrans = 0 - /*o2::base::utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load + /*o2::base::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, // default transformations to load o2::math_utils::TransformType::T2G, o2::math_utils::TransformType::L2G)*/ ); diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx index 773759cbe1343..60b5c6a90f969 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx @@ -43,7 +43,6 @@ using namespace TMath; using namespace o2::its4; using namespace o2::detectors; -using namespace o2::utils; using Segmentation = o2::itsmft::SegmentationAlpide; @@ -385,7 +384,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } // build matrices - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) { // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation LOG(INFO) << "Loading ITS L2G matrices from TGeo"; auto& cacheL2G = getCacheL2G(); @@ -397,7 +396,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) { // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation LOG(INFO) << "Loading ITS T2L matrices from TGeo"; auto& cacheT2L = getCacheT2L(); @@ -408,7 +407,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) { LOG(WARNING) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices"; // matrices for Tracking to Global frame transformation LOG(INFO) << "Loading ITS T2G matrices from TGeo"; @@ -422,7 +421,7 @@ void GeometryTGeo::fillMatrixCache(int mask) } } - if ((mask & o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { + if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) { // 2D rotation matrices for Tracking frame to Global rotations LOG(INFO) << "Loading ITS T2G rotation 2D matrices"; auto& cacheT2Gr = getCacheT2GRot(); @@ -710,7 +709,7 @@ void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp) double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t; x = Sqrt(xp * xp + yp * yp); alp = ATan2(yp, xp); - BringTo02Pi(alp); + o2::math_utils::BringTo02Pi(alp); } //__________________________________________________________________________ diff --git a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h index d2b2001cfefe1..32ebc33021aa6 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h @@ -583,12 +583,12 @@ void DCAFitterN<N, Args...>::calcPCANoErr() { // calculate point of closest approach for N prongs w/o errors auto& pca = mPCA[mCurHyp]; - o2::utils::rotateZ(mTrPos[mCurHyp][N - 1][0], mTrPos[mCurHyp][N - 1][1], pca[0], pca[1], mTrAux[N - 1].s, mTrAux[N - 1].c); + o2::math_utils::rotateZ(mTrPos[mCurHyp][N - 1][0], mTrPos[mCurHyp][N - 1][1], pca[0], pca[1], mTrAux[N - 1].s, mTrAux[N - 1].c); //RRRR mTrAux[N-1].loc2glo(mTrPos[mCurHyp][N-1][0], mTrPos[mCurHyp][N-1][1], pca[0], pca[1] ); pca[2] = mTrPos[mCurHyp][N - 1][2]; for (int i = N - 1; i--;) { double x, y; - o2::utils::rotateZ(mTrPos[mCurHyp][i][0], mTrPos[mCurHyp][i][1], x, y, mTrAux[i].s, mTrAux[i].c); + o2::math_utils::rotateZ(mTrPos[mCurHyp][i][0], mTrPos[mCurHyp][i][1], x, y, mTrAux[i].s, mTrAux[i].c); //RRRR mTrAux[i].loc2glo(mTrPos[mCurHyp][i][0], mTrPos[mCurHyp][i][1], x, y ); pca[0] += x; pca[1] += y; @@ -620,7 +620,7 @@ void DCAFitterN<N, Args...>::calcTrackResiduals() for (int i = N; i--;) { mTrRes[mCurHyp][i] = mTrPos[mCurHyp][i]; vtxLoc = mPCA[mCurHyp]; - o2::utils::rotateZInv(vtxLoc[0], vtxLoc[1], vtxLoc[0], vtxLoc[1], mTrAux[i].s, mTrAux[i].c); // glo->loc + o2::math_utils::rotateZInv(vtxLoc[0], vtxLoc[1], vtxLoc[0], vtxLoc[1], mTrAux[i].s, mTrAux[i].c); // glo->loc mTrRes[mCurHyp][i] -= vtxLoc; } } diff --git a/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h b/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h index 2514830c9769c..d636f8c5c5f6c 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h @@ -25,7 +25,7 @@ namespace track ///__________________________________________________________________________ //< precalculated track radius, center, alpha sin,cos and their combinations -struct TrackAuxPar : public o2::utils::CircleXY { +struct TrackAuxPar : public o2::math_utils::CircleXY { using Track = o2::track::TrackPar; float c, s, cc, ss, cs; // cos ans sin of track alpha and their products diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index fc227f80fb6c7..443571c0f7a0b 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -119,8 +119,8 @@ class PVertexer o2d::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; std::array<float, 3> mXYConstraintInvErr = {1.0f, 0.f, 1.0f}; ///< nominal vertex constraint inverted errors^2 // - o2::utils::StatAccumulator mStatZErr; - o2::utils::StatAccumulator mStatTErr; + o2::math_utils::StatAccumulator mStatZErr; + o2::math_utils::StatAccumulator mStatTErr; std::vector<TrackVF> mTracksPool; ///< tracks in internal representation used for vertexing std::vector<int> mSortedTrackID; ///< indices of tracks sorted in time std::vector<TimeCluster> mTimesClusters; ///< set of time clusters diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h index 7c481c0495def..91500022d22f7 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h @@ -129,7 +129,7 @@ struct TrackVF { TrackVF(const o2::track::TrackParCov& src, const TimeEst& t_est, uint32_t _entry, uint8_t _srcID) : x(src.getX()), y(src.getY()), z(src.getZ()), tgL(src.getTgl()), tgP(src.getSnp() / std::sqrt(1. - src.getSnp()) * (1. + src.getSnp())), timeEst(t_est), entry(_entry), srcID(_srcID) { - o2::utils::sincosf(src.getAlpha(), sinAlp, cosAlp); + o2::math_utils::sincosf(src.getAlpha(), sinAlp, cosAlp); auto det = src.getSigmaY2() * src.getSigmaZ2() - src.getSigmaZY() * src.getSigmaZY(); auto detI = 1. / det; sig2YI = src.getSigmaZ2() * detI; diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index bb37951a7ad82..3e293c4228fd4 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -409,7 +409,7 @@ float PVertexer::getTukey() const //___________________________________________________________________ TimeEst PVertexer::timeEstimate(const VertexingInput& input) const { - o2::utils::StatAccumulator test; + o2::math_utils::StatAccumulator test; for (int i : input.idRange) { if (mTracksPool[i].canUse()) { const auto& timeT = mTracksPool[i].timeEst; diff --git a/Detectors/Vertexing/test/testDCAFitterN.cxx b/Detectors/Vertexing/test/testDCAFitterN.cxx index c23907cd6c6eb..2b23e2c7facbb 100644 --- a/Detectors/Vertexing/test/testDCAFitterN.cxx +++ b/Detectors/Vertexing/test/testDCAFitterN.cxx @@ -100,8 +100,8 @@ TLorentzVector generate(Vec3D& vtx, std::vector<o2::track::TrackParCov>& vctr, f dt->GetXYZT(p); float s, c, x; std::array<float, 5> params; - o2::utils::sincosf(dt->Phi(), s, c); - o2::utils::rotateZInv(vtx[0], vtx[1], x, params[0], s, c); + o2::math_utils::sincosf(dt->Phi(), s, c); + o2::math_utils::rotateZInv(vtx[0], vtx[1], x, params[0], s, c); params[1] = vtx[2]; params[2] = 0.; // since alpha = phi diff --git a/EventVisualisation/Detectors/src/DataInterpreterITS.cxx b/EventVisualisation/Detectors/src/DataInterpreterITS.cxx index 0e0dba781e731..ef2269ac5666f 100644 --- a/EventVisualisation/Detectors/src/DataInterpreterITS.cxx +++ b/EventVisualisation/Detectors/src/DataInterpreterITS.cxx @@ -44,7 +44,7 @@ DataInterpreterITS::DataInterpreterITS() //Prepare coordinate translator base::GeometryManager::loadGeometry(); its::GeometryTGeo* gman = its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); } std::unique_ptr<VisualisationEvent> DataInterpreterITS::interpretDataForType(TObject* data, EVisualisationDataType type) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 8e92461402b85..592c33a4b868e 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -102,14 +102,14 @@ DECLARE_SOA_DYNAMIC_COLUMN(Charge, charge, [](float signed1Pt) -> short { return DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float signed1Pt, float snp, float alpha) -> float { auto pt = 1.f / std::abs(signed1Pt); float cs, sn; - utils::sincosf(alpha, sn, cs); + math_utils::sincosf(alpha, sn, cs); auto r = std::sqrt((1.f - snp) * (1.f + snp)); return pt * (r * cs - snp * sn); }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float signed1Pt, float snp, float alpha) -> float { auto pt = 1.f / std::abs(signed1Pt); float cs, sn; - utils::sincosf(alpha, sn, cs); + math_utils::sincosf(alpha, sn, cs); auto r = std::sqrt((1.f - snp) * (1.f + snp)); return pt * (snp * cs + r * sn); }); diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx index 60fb9ddd1cb2b..03c5af766a837 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx @@ -63,7 +63,7 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer } else { geom = o2::mft::GeometryTGeo::Instance(); } - geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded mDigitizer.setGeometry(geom); mDisableQED = ic.options().get<bool>("disable-qed"); diff --git a/macro/CheckDigits_mft.C b/macro/CheckDigits_mft.C index 078038d41f554..379c0603cfb91 100644 --- a/macro/CheckDigits_mft.C +++ b/macro/CheckDigits_mft.C @@ -43,7 +43,7 @@ void CheckDigits_mft(Int_t nEvents = 1, Int_t nMuons = 10, TString mcEngine = "T gFile->Get("FairGeoParSet"); auto* gman = o2::mft::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::L2G)); + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); SegmentationAlpide seg; diff --git a/macro/run_primary_vertexer_ITS.C b/macro/run_primary_vertexer_ITS.C index 763540f3cedc2..1a9e8f122f7fc 100644 --- a/macro/run_primary_vertexer_ITS.C +++ b/macro/run_primary_vertexer_ITS.C @@ -73,8 +73,8 @@ int run_primary_vertexer_ITS(const GPUDataTypes::DeviceType dtype = GPUDataTypes o2::base::GeometryManager::loadGeometry(path); o2::its::GeometryTGeo* geom = o2::its::GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::L2G)); // request cached transforms + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms // Get event header TChain mcHeaderTree("o2sim"); diff --git a/macro/run_trac_ca_its.C b/macro/run_trac_ca_its.C index 4ebfcc68fe74a..b29671c2772b7 100644 --- a/macro/run_trac_ca_its.C +++ b/macro/run_trac_ca_its.C @@ -98,9 +98,8 @@ void run_trac_ca_its(std::string path = "./", LOG(INFO) << "ITS is in " << (isContITS ? "CONTINUOS" : "TRIGGERED") << " readout mode"; auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, - o2::math_utils::TransformType::L2G)); // request cached transforms - + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); // request cached transforms //>>>---------- attach input data --------------->>> TChain itsClusters("o2sim"); diff --git a/macro/run_trac_its.C b/macro/run_trac_its.C index 155acbbd6a9a5..d1272e1df3445 100644 --- a/macro/run_trac_its.C +++ b/macro/run_trac_its.C @@ -74,7 +74,7 @@ void run_trac_its(std::string path = "./", std::string outputfile = "o2trac_its. o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); - gman->fillMatrixCache(o2::utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); // request cached transforms + gman->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)); // request cached transforms o2::base::Propagator::initFieldFromGRP(grp); auto field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); From abebfd1ba94cb68d9b2bd4e0d67932e062029870 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Thu, 8 Oct 2020 14:17:31 +0200 Subject: [PATCH 1031/1751] [math_utils] CachingTF1 to math_utils ns move CachingTF1 from `base` ns to `math_utils` namespace amd change affected files. --- Common/MathUtils/include/MathUtils/CachingTF1.h | 4 ++-- Common/MathUtils/src/CachingTF1.cxx | 4 ++-- Common/MathUtils/src/MathUtilsLinkDef.h | 2 +- Common/MathUtils/test/testCachingTF1.cxx | 6 ++---- Detectors/TPC/simulation/src/GEMAmplification.cxx | 12 ++++++------ 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/CachingTF1.h b/Common/MathUtils/include/MathUtils/CachingTF1.h index ccea20753c102..4c3b64915b250 100644 --- a/Common/MathUtils/include/MathUtils/CachingTF1.h +++ b/Common/MathUtils/include/MathUtils/CachingTF1.h @@ -18,7 +18,7 @@ namespace o2 { -namespace base +namespace math_utils { class CachingTF1 : public TF1 { @@ -45,7 +45,7 @@ class CachingTF1 : public TF1 std::vector<double>* mGammaCache = &fGamma; ClassDefOverride(CachingTF1, 1); }; -} // namespace base +} // namespace math_utils } // namespace o2 #endif diff --git a/Common/MathUtils/src/CachingTF1.cxx b/Common/MathUtils/src/CachingTF1.cxx index ce457408984a6..1d3957a476bf2 100644 --- a/Common/MathUtils/src/CachingTF1.cxx +++ b/Common/MathUtils/src/CachingTF1.cxx @@ -10,6 +10,6 @@ #include "MathUtils/CachingTF1.h" -using namespace o2::base; +using namespace o2::math_utils; -ClassImp(o2::base::CachingTF1); +ClassImp(o2::math_utils::CachingTF1); diff --git a/Common/MathUtils/src/MathUtilsLinkDef.h b/Common/MathUtils/src/MathUtilsLinkDef.h index e2f0f8473e696..be848491e7915 100644 --- a/Common/MathUtils/src/MathUtilsLinkDef.h +++ b/Common/MathUtils/src/MathUtilsLinkDef.h @@ -31,7 +31,7 @@ #pragma link C++ class o2::math_utils::Transform3D + ; #pragma link C++ class o2::math_utils::Rotation2D + ; -#pragma link C++ class o2::base::CachingTF1 + ; +#pragma link C++ class o2::math_utils::CachingTF1 + ; #pragma link C++ class o2::math_utils::CircleXY + ; #pragma link C++ class o2::math_utils::IntervalXY + ; diff --git a/Common/MathUtils/test/testCachingTF1.cxx b/Common/MathUtils/test/testCachingTF1.cxx index f20a6f0c249cf..adab3ef589ca5 100644 --- a/Common/MathUtils/test/testCachingTF1.cxx +++ b/Common/MathUtils/test/testCachingTF1.cxx @@ -15,12 +15,10 @@ #include "MathUtils/CachingTF1.h" #include <TFile.h> -using namespace o2::base; - BOOST_AUTO_TEST_CASE(CachingTF1_test) { std::string s("std::pow(x, 1.2)*std::exp(-x/3.)"); - CachingTF1 func("testfunction", s.c_str(), 0, 100.); + o2::math_utils::CachingTF1 func("testfunction", s.c_str(), 0, 100.); const int kNPoints = 500; func.SetNpx(kNPoints); BOOST_CHECK(func.getIntegralVector().size() == 0); @@ -33,7 +31,7 @@ BOOST_AUTO_TEST_CASE(CachingTF1_test) // open for reading and verify that integral was cached f = TFile::Open("tmpTF1Cache.root"); BOOST_CHECK(f); - volatile auto func2 = (CachingTF1*)f->Get("func"); + volatile auto func2 = (o2::math_utils::CachingTF1*)f->Get("func"); BOOST_CHECK(func2); BOOST_CHECK(func2->getIntegralVector().size() == kNPoints + 1); diff --git a/Detectors/TPC/simulation/src/GEMAmplification.cxx b/Detectors/TPC/simulation/src/GEMAmplification.cxx index a0965196c4320..b7b6b58ba9240 100644 --- a/Detectors/TPC/simulation/src/GEMAmplification.cxx +++ b/Detectors/TPC/simulation/src/GEMAmplification.cxx @@ -59,14 +59,14 @@ GEMAmplification::GEMAmplification() float s = mGEMParam->AbsoluteGain[i] / kappa; polya % kappa % s % s % (kappa - 1) % s; std::string name = polya.str(); - o2::base::CachingTF1* polyaDistribution = nullptr; + o2::math_utils::CachingTF1* polyaDistribution = nullptr; if (!cacheexists) { - polyaDistribution = new o2::base::CachingTF1("polya", name.c_str(), 0, 10.f * mGEMParam->AbsoluteGain[i]); + polyaDistribution = new o2::math_utils::CachingTF1("polya", name.c_str(), 0, 10.f * mGEMParam->AbsoluteGain[i]); /// this dramatically alters the speed with which the filling is executed... /// without this, the distribution makes discrete steps at every int polyaDistribution->SetNpx(100000); } else { - polyaDistribution = (o2::base::CachingTF1*)outfile->Get(TString::Format("func%d", i).Data()); + polyaDistribution = (o2::math_utils::CachingTF1*)outfile->Get(TString::Format("func%d", i).Data()); // FIXME: verify that distribution corresponds to the parameters used here } mGain[i].initialize(*polyaDistribution); @@ -84,12 +84,12 @@ GEMAmplification::GEMAmplification() const float sStack = gainStack / (kappaStack * (1.f - effStack)); polya % kappaStack % sStack % sStack % (kappaStack - 1) % sStack; std::string name = polya.str(); - o2::base::CachingTF1* polyaDistribution = nullptr; + o2::math_utils::CachingTF1* polyaDistribution = nullptr; if (!cacheexists) { - polyaDistribution = new o2::base::CachingTF1("polya", name.c_str(), 0, 50000); + polyaDistribution = new o2::math_utils::CachingTF1("polya", name.c_str(), 0, 50000); polyaDistribution->SetNpx(50000); } else { - polyaDistribution = (o2::base::CachingTF1*)outfile->Get("polyaStack"); + polyaDistribution = (o2::math_utils::CachingTF1*)outfile->Get("polyaStack"); } mGainFullStack.initialize(*polyaDistribution); From 85b7201b6db4e22c8a89a8d63dab3937cdcf7ef0 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Mon, 12 Oct 2020 23:24:48 +0200 Subject: [PATCH 1032/1751] [math_utils] Refactor CircleXY and IntervalXY turn `CircleXY` and `IntervalXY` into template classes with respective aliases for float and double versions of each. Change affected code accordingly. Primitive2D only includes the headers containing the CircleXY and IntervalXY implementations. --- Common/MathUtils/CMakeLists.txt | 1 - .../MathUtils/include/MathUtils/Primitive2D.h | 52 +-- .../include/MathUtils/detail/CircleXY.h | 54 ++++ .../include/MathUtils/detail/IntervalXY.h | 303 ++++++++++++++++++ Common/MathUtils/src/MathUtilsLinkDef.h | 6 +- Common/MathUtils/src/Primitive2D.cxx | 114 ------- .../TrackParametrization.h | 38 +-- .../src/TrackParametrization.cxx | 2 +- .../include/GlobalTracking/MatchTPCITS.h | 4 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 8 +- .../ITSReconstruction/RecoGeomHelper.h | 2 +- .../include/DetectorsVertexing/HelixHelper.h | 2 +- 12 files changed, 400 insertions(+), 186 deletions(-) create mode 100644 Common/MathUtils/include/MathUtils/detail/CircleXY.h create mode 100644 Common/MathUtils/include/MathUtils/detail/IntervalXY.h delete mode 100644 Common/MathUtils/src/Primitive2D.cxx diff --git a/Common/MathUtils/CMakeLists.txt b/Common/MathUtils/CMakeLists.txt index e8e112dfc8d57..090fe2abeb7c2 100644 --- a/Common/MathUtils/CMakeLists.txt +++ b/Common/MathUtils/CMakeLists.txt @@ -16,7 +16,6 @@ o2_add_library( src/Chebyshev3DCalc.cxx src/MathBase.cxx src/RandomRing.cxx - src/Primitive2D.cxx PUBLIC_LINK_LIBRARIES ROOT::Hist FairRoot::Base diff --git a/Common/MathUtils/include/MathUtils/Primitive2D.h b/Common/MathUtils/include/MathUtils/Primitive2D.h index d8c2ce344a73b..8af88e98f3005 100644 --- a/Common/MathUtils/include/MathUtils/Primitive2D.h +++ b/Common/MathUtils/include/MathUtils/Primitive2D.h @@ -16,52 +16,22 @@ #define ALICEO2_COMMON_MATH_PRIMITIVE2D_H #include "GPUCommonRtypes.h" +#include "MathUtils/detail/CircleXY.h" +#include "MathUtils/detail/IntervalXY.h" namespace o2 { namespace math_utils { - -struct CircleXY { - float rC, xC, yC; // circle radius, x-center, y-center - CircleXY(float r = 0., float x = 0., float y = 0.) : rC(r), xC(x), yC(y) {} - float getCenterD2() const { return xC * xC + yC * yC; } - ClassDefNV(CircleXY, 1); -}; - -struct IntervalXY { - ///< 2D interval in lab frame defined by its one edge and signed projection lengths on X,Y axes - float xP, yP; ///< one of edges - float dxP, dyP; ///< other edge minus provided - IntervalXY(float x = 0, float y = 0, float dx = 0, float dy = 0) : xP(x), yP(y), dxP(dx), dyP(dy) {} - float getX0() const { return xP; } - float getY0() const { return yP; } - float getX1() const { return xP + dxP; } - float getY1() const { return yP + dyP; } - float getDX() const { return dxP; } - float getDY() const { return dyP; } - void eval(float t, float& x, float& y) const - { - x = xP + t * dxP; - y = yP + t * dyP; - } - void getLineCoefs(float& a, float& b, float& c) const; - - void setEdges(float x0, float y0, float x1, float y1) - { - xP = x0; - yP = y0; - dxP = x1 - x0; - dyP = y1 - y0; - } - bool seenByCircle(const CircleXY& circle, float eps) const; - bool circleCrossParam(const CircleXY& cicle, float& t) const; - - bool seenByLine(const IntervalXY& other, float eps) const; - bool lineCrossParam(const IntervalXY& other, float& t) const; - - ClassDefNV(IntervalXY, 1); -}; +template <typename T> +using CircleXY = detail::CircleXY<T>; +using CircleXYf_t = CircleXY<float>; +using CircleXYd_t = CircleXY<double>; + +template <typename T> +using IntervalXY = detail::IntervalXY<T>; +using IntervalXYf_t = IntervalXY<float>; +using IntervalXYd_t = IntervalXY<double>; } // namespace math_utils } // namespace o2 diff --git a/Common/MathUtils/include/MathUtils/detail/CircleXY.h b/Common/MathUtils/include/MathUtils/detail/CircleXY.h new file mode 100644 index 0000000000000..f33f167df68e5 --- /dev/null +++ b/Common/MathUtils/include/MathUtils/detail/CircleXY.h @@ -0,0 +1,54 @@ +// 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 CircleXY.h +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since Oct 10, 2020 +/// @brief + +#ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_CIRCLEXY_H_ +#define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_CIRCLEXY_H_ + +#include "GPUCommonRtypes.h" + +namespace o2 +{ +namespace math_utils +{ +namespace detail +{ + +template <typename T> +struct CircleXY { + using value_t = T; + + T rC; // circle radius + T xC; // x-center + T yC; // y-center + CircleXY(T r = T(), T x = T(), T y = T()); + T getCenterD2() const; + ClassDefNV(CircleXY, 2); +}; + +template <typename T> +CircleXY<T>::CircleXY(T r, T x, T y) : rC(std::move(r)), xC(std::move(x)), yC(std::move(y)) +{ +} + +template <typename T> +inline T CircleXY<T>::getCenterD2() const +{ + return xC * xC + yC * yC; +} +} // namespace detail +} // namespace math_utils +} // namespace o2 + +#endif /* MATHUTILS_INCLUDE_MATHUTILS_DETAIL_CIRCLEXY_H_ */ diff --git a/Common/MathUtils/include/MathUtils/detail/IntervalXY.h b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h new file mode 100644 index 0000000000000..db232e384122e --- /dev/null +++ b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h @@ -0,0 +1,303 @@ +// 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 IntervalXY.h +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since Oct 10, 2020 +/// @brief + +#ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_INTERVALXY_H_ +#define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_INTERVALXY_H_ + +#include "GPUCommonRtypes.h" +#include <cmath> +#include <tuple> + +#include "MathUtils/detail/CircleXY.h" + +namespace o2 +{ +namespace math_utils +{ +namespace detail +{ + +template <typename T> +class IntervalXY +{ + public: + using value_t = T; + + ///< 2D interval in lab frame defined by its one edge and signed projection lengths on X,Y axes + IntervalXY(T x = T(), T y = T(), T dx = T(), T dy = T()); + T getX0() const; + T getY0() const; + T& getX0(); + T& getY0(); + T getX1() const; + T getY1() const; + T getDX() const; + T getDY() const; + T& getDX(); + T& getDY(); + + void setX0(T x0); + void setY0(T y0); + void setX1(T x1); + void setY1(T y1); + void setDX(T dx); + void setDY(T dy); + void setEdges(T x0, T y0, T x1, T y1); + + void eval(T t, T& x, T& y) const; + std::tuple<T, T> eval(T t) const; + + void getLineCoefs(T& a, T& b, T& c) const; + + /** check if XY interval is seen by the circle. + * The tolerance parameter eps is interpreted as a fraction of the interval + * lenght to be added to the edges along the interval (i.e. while the points + * within the interval are spanning + * x = xc + dx*t + * y = yc + dy*t + * with 0<t<1., we acctually check the interval for -eps<t<1+eps + */ + bool seenByCircle(const CircleXY<T>& circle, T eps) const; + + bool circleCrossParam(const CircleXY<T>& circle, T& t) const; + + /** + * check if XY interval is seen by the line defined by other interval + * The tolerance parameter eps is interpreted as a fraction of the interval + * lenght to be added to the edges along the interval (i.e. while the points + * within the interval are spanning + * x = xc + dx*t + * y = yc + dy*t + * with 0<t<1., we acctually check the interval for -eps<t<1+eps + */ + bool seenByLine(const IntervalXY<T>& other, T eps) const; + + /** + * get crossing parameter of 2 intervals + */ + bool lineCrossParam(const IntervalXY<T>& other, T& t) const; + + private: + T mX, mY; ///< one of edges + T mDx, mDY; ///< other edge minus provided + + ClassDefNV(IntervalXY, 2); +}; + +template <typename T> +IntervalXY<T>::IntervalXY(T x, T y, T dx, T dy) : mX(std::move(x)), mY(std::move(y)), mDx(std::move(dx)), mDY(std::move(dy)) +{ +} + +template <typename T> +inline T IntervalXY<T>::getX0() const +{ + return mX; +} + +template <typename T> +inline T IntervalXY<T>::getY0() const +{ + return mY; +} + +template <typename T> +inline T& IntervalXY<T>::getX0() +{ + return mX; +} + +template <typename T> +inline T& IntervalXY<T>::getY0() +{ + return mY; +} + +template <typename T> +inline T IntervalXY<T>::getX1() const +{ + return mX + mDx; +} +template <typename T> +inline T IntervalXY<T>::getY1() const +{ + return mY + mDY; +} +template <typename T> +inline T IntervalXY<T>::getDX() const +{ + return mDx; +} +template <typename T> +inline T IntervalXY<T>::getDY() const +{ + return mDY; +} + +template <typename T> +inline T& IntervalXY<T>::getDX() +{ + return mDx; +} +template <typename T> +inline T& IntervalXY<T>::getDY() +{ + return mDY; +} + +template <typename T> +inline void IntervalXY<T>::setX0(T x0) +{ + mX = x0; +} + +template <typename T> +inline void IntervalXY<T>::setY0(T y0) +{ + mY = y0; +} +template <typename T> +inline void IntervalXY<T>::setX1(T x1) +{ + mDx = x1 - mX; +} +template <typename T> +inline void IntervalXY<T>::setY1(T y1) +{ + mDY = y1 - mY; +} +template <typename T> +inline void IntervalXY<T>::setDX(T dx) +{ + mDx = dx; +} +template <typename T> +inline void IntervalXY<T>::setDY(T dy) +{ + mDY = dy; +} + +template <typename T> +inline void IntervalXY<T>::setEdges(T x0, T y0, T x1, T y1) +{ + mX = x0; + mY = y0; + mDx = x1 - x0; + mDY = y1 - y0; +} + +template <typename T> +inline std::tuple<T, T> IntervalXY<T>::eval(T t) const +{ + return {mX + t * mDx, mY + t * mDY}; +} + +template <typename T> +inline void IntervalXY<T>::eval(T t, T& x, T& y) const +{ + std::tie(x, y) = eval(t); +} + +template <typename T> +void IntervalXY<T>::getLineCoefs(T& a, T& b, T& c) const +{ + // convert to line parameters in canonical form: a*x+b*y+c = 0 + c = mX * mDY - mY * mDx; + if (c) { + a = -mDY; + b = mDx; + } else if (fabs(mDx) > fabs(mDY)) { + a = 0.; + b = -1.; + c = mY; + } else { + a = -1.; + b = 0.; + c = mX; + } +} + +template <typename T> +bool IntervalXY<T>::seenByCircle(const CircleXY<T>& circle, T eps) const +{ + T dx0 = mX - circle.xC; + T dy0 = mY - circle.yC; + T dx1 = dx0 + mDx; + T dy1 = dy0 + mDY; + if (eps > 0.) { + const T dxeps = eps * mDx, dyeps = eps * mDY; + dx0 -= dxeps; + dx1 += dxeps; + dy0 -= dyeps; + dy1 += dyeps; + } + // distance^2 from circle center to edges + const T d02 = dx0 * dx0 + dy0 * dy0; + const T d12 = dx1 * dx1 + dy1 * dy1; + const T rC2 = circle.rC * circle.rC; + + return (d02 - rC2) * (d12 - rC2) < 0; +} +template <typename T> +bool IntervalXY<T>::circleCrossParam(const CircleXY<T>& circle, T& t) const +{ + const T dx = mX - circle.xC; + const T dy = mY - circle.yC; + const T del2I = 1.f / (mDx * mDx + mDY * mDY); + const T b = (dx * mDx + dy * mDY) * del2I; + const T c = del2I * (dx * dx + dy * dy - circle.rC * circle.rC); + T det = b * b - c; + if (det < 0.f) { + return false; + } + det = std::sqrt(det); + const T t0 = -b - det; + const T t1 = -b + det; + // select the one closer to [0:1] interval + t = (std::fabs(t0 - 0.5f) < std::fabs(t1 - 0.5f)) ? t0 : t1; + return true; +} + +template <typename T> +bool IntervalXY<T>::seenByLine(const IntervalXY<T>& other, T eps) const +{ + T a, b, c; // find equation of the line a*x+b*y+c = 0 + other.getLineCoefs(a, b, c); + const auto [x0, y0] = eval(-eps); + const auto [x1, y1] = eval(1.f + eps); + + return (a * x0 + b * y0 + c) * (a * x1 + b * y1 + c) < 0; +} + +template <typename T> +bool IntervalXY<T>::lineCrossParam(const IntervalXY<T>& other, T& t) const +{ + // tolerance + constexpr float eps = 1.e-9f; + const T dx = other.getX0() - mX; + const T dy = other.getY0() - mY; + const T det = -mDx * other.getY0() + mDY * other.getX0(); + if (std::fabs(det) < eps) { + return false; // parallel + } + t = (-dx * other.getY0() + dy * other.getX0()) / det; + return true; +} +}; // namespace detail + +} // namespace math_utils +} // namespace o2 + +#endif /* MATHUTILS_INCLUDE_MATHUTILS_DETAIL_INTERVALXY_H_ */ diff --git a/Common/MathUtils/src/MathUtilsLinkDef.h b/Common/MathUtils/src/MathUtilsLinkDef.h index be848491e7915..b3c71a810cecc 100644 --- a/Common/MathUtils/src/MathUtilsLinkDef.h +++ b/Common/MathUtils/src/MathUtilsLinkDef.h @@ -33,8 +33,10 @@ #pragma link C++ class o2::math_utils::Rotation2D + ; #pragma link C++ class o2::math_utils::CachingTF1 + ; -#pragma link C++ class o2::math_utils::CircleXY + ; -#pragma link C++ class o2::math_utils::IntervalXY + ; +#pragma link C++ class o2::math_utils::CircleXYf_t + ; +#pragma link C++ class o2::math_utils::CircleXYd_t + ; +#pragma link C++ class o2::math_utils::IntervalXYf_t + ; +#pragma link C++ class o2::math_utils::IntervalXYd_t + ; #pragma link C++ class o2::math_utils::Bracket < float> + ; #endif diff --git a/Common/MathUtils/src/Primitive2D.cxx b/Common/MathUtils/src/Primitive2D.cxx deleted file mode 100644 index 4f86a865cfb25..0000000000000 --- a/Common/MathUtils/src/Primitive2D.cxx +++ /dev/null @@ -1,114 +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. - -/// \file Primitive.cxx -/// \brief Implementation of 2D primitives: straight line (XY interval) and circle -/// \author ruben.shahoyan@cern.ch - -#include "MathUtils/Primitive2D.h" -#include <cmath> - -namespace o2 -{ -namespace math_utils -{ -//_____________________________________________________________________ -bool IntervalXY::seenByCircle(const CircleXY& circle, float eps) const -{ - // check if XY interval is seen by the circle. - // The tolerance parameter eps is interpreted as a fraction of the interval - // lenght to be added to the edges along the interval (i.e. while the points - // within the interval are spanning - // x = xc + dx*t - // y = yc + dy*t - // with 0<t<1., we acctually check the interval for -eps<t<1+eps - auto dx0 = xP - circle.xC, dy0 = yP - circle.yC, dx1 = dx0 + dxP, dy1 = dy0 + dyP; - if (eps > 0.) { - auto dxeps = eps * dxP, dyeps = eps * dyP; - dx0 -= dxeps; - dx1 += dxeps; - dy0 -= dyeps; - dy1 += dyeps; - } - auto d02 = dx0 * dx0 + dy0 * dy0, d12 = dx1 * dx1 + dy1 * dy1, rC2 = circle.rC * circle.rC; // distance^2 from circle center to edges - return (d02 - rC2) * (d12 - rC2) < 0; -} - -//_____________________________________________________________________ -bool IntervalXY::seenByLine(const IntervalXY& other, float eps) const -{ - // check if XY interval is seen by the line defined by other interval - // The tolerance parameter eps is interpreted as a fraction of the interval - // lenght to be added to the edges along the interval (i.e. while the points - // within the interval are spanning - // x = xc + dx*t - // y = yc + dy*t - // with 0<t<1., we acctually check the interval for -eps<t<1+eps - float a, b, c, x0, y0, x1, y1; // find equation of the line a*x+b*y+c = 0 - other.getLineCoefs(a, b, c); - eval(-eps, x0, y0); - eval(1.f + eps, x1, y1); - return (a * x0 + b * y0 + c) * (a * x1 + b * y1 + c) < 0; -} - -//_____________________________________________________________________ -bool IntervalXY::lineCrossParam(const IntervalXY& other, float& t) const -{ - // get crossing parameter of 2 intervals - float dx = other.xP - xP, dy = other.yP - yP; - float det = -dxP * other.dyP + dyP * other.dxP; - if (fabs(det) < 1.e-9) { - return false; // parallel - } - t = (-dx * other.dyP + dy * other.dxP) / det; - return true; -} - -//_____________________________________________________________________ -bool IntervalXY::circleCrossParam(const CircleXY& circle, float& t) const -{ - // get crossing point of circle with the interval - // solution of the system (wrt t) - // (x-xC)^2+(y-yC)^2 = rC2 - // x = xEdge + xProj * t; - // y = yEdge + yProj * t; - float dx = xP - circle.xC, dy = yP - circle.yC, del2I = 1. / (dxP * dxP + dyP * dyP), - b = (dx * dxP + dy * dyP) * del2I, c = del2I * (dx * dx + dy * dy - circle.rC * circle.rC); - float det = b * b - c; - if (det < 0.) { - return false; - } - det = sqrtf(det); - float t0 = -b - det, t1 = -b + det; - // select the one closer to [0:1] interval - t = (fabs(t0 - 0.5) < fabs(t1 - 0.5)) ? t0 : t1; - return true; -} - -//_____________________________________________________________________ -void IntervalXY::getLineCoefs(float& a, float& b, float& c) const -{ - // convert to line parameters in canonical form: a*x+b*y+c = 0 - c = xP * dyP - yP * dxP; - if (c) { - a = -dyP; - b = dxP; - } else if (fabs(dxP) > fabs(dyP)) { - a = 0.; - b = -1.; - c = yP; - } else { - a = -1.; - b = 0.; - c = xP; - } -} -} // namespace math_utils -} // namespace o2 diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index d2782c4463d33..fd985a0859d90 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -165,9 +165,9 @@ class TrackParametrization // derived getters bool getXatLabR(value_t r, value_t& x, value_t bz, DirType dir = DirAuto) const; - void getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY& circle) const; - void getCircleParams(value_t bz, o2::math_utils::CircleXY& circle, value_t& sna, value_t& csa) const; - void getLineParams(o2::math_utils::IntervalXY& line, value_t& sna, value_t& csa) const; + void getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY<value_t>& circle) const; + void getCircleParams(value_t bz, o2::math_utils::CircleXY<value_t>& circle, value_t& sna, value_t& csa) const; + void getLineParams(o2::math_utils::IntervalXY<value_t>& line, value_t& sna, value_t& csa) const; value_t getCurvature(value_t b) const; int getCharge() const; int getSign() const; @@ -337,7 +337,7 @@ inline void TrackParametrization<value_T>::setPID(const PID pid) template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp2() const { - value_t csp2 = (1.f - mP[kSnp]) * (1.f + mP[kSnp]); + const value_t csp2 = (1.f - mP[kSnp]) * (1.f + mP[kSnp]); return csp2 > o2::constants::math::Almost0 ? csp2 : o2::constants::math::Almost0; } @@ -345,7 +345,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp() const { - return sqrtf(getCsp2()); + return std::sqrt(getCsp2()); } //____________________________________________________________ @@ -413,7 +413,7 @@ inline void TrackParametrization<value_T>::setAbsCharge(int q) //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY& c) const +inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY<value_t>& c) const { // get circle params in track local frame, for straight line just set to local coordinates c.rC = getCurvature(bz); @@ -421,10 +421,10 @@ inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::ma constexpr value_t MinSagitta = 0.01f, TPCMidR = 160.f, MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR); if (std::abs(c.rC) > MinCurv) { c.rC = 1.f / getCurvature(bz); - value_t sn = getSnp(), cs = sqrtf((1.f - sn) * (1.f + sn)); + value_t sn = getSnp(), cs = std::sqrt((1.f - sn) * (1.f + sn)); c.xC = getX() - sn * c.rC; // center in tracking c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!! - c.rC = fabs(c.rC); + c.rC = std::abs(c.rC); } else { c.rC = 0.f; // signal straight line c.xC = getX(); @@ -434,7 +434,7 @@ inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::ma //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_utils::CircleXY& c, value_t& sna, value_t& csa) const +inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_utils::CircleXY<value_t>& c, value_t& sna, value_t& csa) const { // get circle params in loc and lab frame, for straight line just set to global coordinates getCircleParamsLoc(bz, c); @@ -444,14 +444,14 @@ inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_ //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getLineParams(o2::math_utils::IntervalXY& ln, value_t& sna, value_t& csa) const +inline void TrackParametrization<value_T>::getLineParams(o2::math_utils::IntervalXY<value_t>& ln, value_t& sna, value_t& csa) const { // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } o2::math_utils::sincos(getAlpha(), sna, csa); - o2::math_utils::rotateZ(getX(), getY(), ln.xP, ln.yP, sna, csa); // reference point in global frame - value_t snp = getSnp(), csp = sqrtf((1.f - snp) * (1.f + snp)); - ln.dxP = csp * csa - snp * sna; - ln.dyP = snp * csa + csp * sna; + o2::math_utils::rotateZ(getX(), getY(), ln.getX0(), ln.getY0(), sna, csa); // reference point in global frame + value_t snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + ln.setDX(csp * csa - snp * sna); + ln.setDY(snp * csa + csp * sna); } //____________________________________________________________ @@ -480,7 +480,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhi() const { // track pt direction phi (in 0:2pi range) - value_t phi = asinf(getSnp()) + getAlpha(); + value_t phi = std::asin(getSnp()) + getAlpha(); math_utils::BringTo02Pi(phi); return phi; } @@ -490,7 +490,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhiPos() const { // angle of track position (in -pi:pi range) - value_t phi = atan2f(getY(), getX()) + getAlpha(); + value_t phi = std::atan2(getY(), getX()) + getAlpha(); math_utils::BringTo02Pi(phi); return phi; } @@ -500,7 +500,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPtInv() const { // return the inverted track pT - const value_t ptInv = fabs(mP[kQ2Pt]); + const value_t ptInv = std::fabs(mP[kQ2Pt]); return (mAbsCharge > 1) ? ptInv / mAbsCharge : ptInv; } @@ -527,7 +527,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPInv() const { // return the inverted track momentum^2 - const value_t pInv = fabs(mP[kQ2Pt]) / sqrtf(1.f + getTgl() * getTgl()); + const value_t pInv = std::fabs(mP[kQ2Pt]) / std::sqrt(1.f + getTgl() * getTgl()); return (mAbsCharge > 1) ? pInv / mAbsCharge : pInv; } @@ -545,7 +545,7 @@ template <typename value_T> inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPt() const { // return the track transverse momentum - value_t ptI = fabs(mP[kQ2Pt]); + value_t ptI = std::fabs(mP[kQ2Pt]); if (mAbsCharge > 1) { ptI /= mAbsCharge; } diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index 087b1b35af8a4..e5952f857e238 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -516,7 +516,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz auto crv = getCurvature(bz); if (std::fabs(crv) > constants::math::Almost0) { // helix // get center of the track circle - math_utils::CircleXY circle; + math_utils::CircleXY<value_t> circle; getCircleParamsLoc(bz, circle); value_t r0 = std::sqrt(circle.getCenterD2()); if (r0 <= constants::math::Almost0) { diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index f15396095a400..dc89b302987c5 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -476,9 +476,9 @@ class MatchTPCITS private: void updateTPCTimeDependentParams(); - int findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils::CircleXY& circle, float errYFrac, + int findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils::CircleXYf_t& circle, float errYFrac, std::array<int, MaxLadderCand>& lad2Check) const; - int findLaddersToCheckBOff(int ilr, int lad0, const o2::math_utils::IntervalXY& trcLinPar, float errYFrac, + int findLaddersToCheckBOff(int ilr, int lad0, const o2::math_utils::IntervalXYf_t& trcLinPar, float errYFrac, std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check) const; int prepareTPCTracksAfterBurner(); diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 12ba07b67f163..df040118e61aa 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -1996,8 +1996,8 @@ int MatchTPCITS::checkABSeedFromLr(int lrSeed, int seedID, ABTrackLinksList& lli return 0; } std::vector<int> chipSelClusters; // preliminary cluster candidates //RS TODO do we keep this local / consider array instead of vector - o2::math_utils::CircleXY trcCircle; - o2::math_utils::IntervalXY trcLinPar; // line parameters for B OFF data + o2::math_utils::CircleXYf_t trcCircle; + o2::math_utils::IntervalXYf_t trcLinPar; // line parameters for B OFF data // approximate errors float errY = std::sqrt(seed.getSigmaY2() + YErr2Extra), errYFrac = errY * mRGHelper.ladderWidthInv(), errPhi = errY * lr.rInv; if (mFieldON) { @@ -2126,7 +2126,7 @@ void MatchTPCITS::mergeABSeedsOnOverlaps(int ilrPar, ABTrackLinksList& llist) } //______________________________________________ -int MatchTPCITS::findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils::CircleXY& circle, float errYFrac, +int MatchTPCITS::findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils::CircleXYf_t& circle, float errYFrac, std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check) const { // check if ladder lad0 and at most +-MaxUpDnLadders around it are compatible with circular track of @@ -2162,7 +2162,7 @@ int MatchTPCITS::findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils:: } //______________________________________________ -int MatchTPCITS::findLaddersToCheckBOff(int ilr, int lad0, const o2::math_utils::IntervalXY& trcLinPar, float errYFrac, +int MatchTPCITS::findLaddersToCheckBOff(int ilr, int lad0, const o2::math_utils::IntervalXYf_t& trcLinPar, float errYFrac, std::array<int, MatchTPCITS::MaxLadderCand>& lad2Check) const { // check if ladder lad0 and at most +-MaxUpDnLadders around it are compatible with linear track diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h index 57d0d69d6fcb8..fb1bac284767a 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h @@ -33,7 +33,7 @@ namespace its struct RecoGeomHelper { // using BracketF = o2::math_utils::Bracket<float>; - using Vec2D = o2::math_utils::IntervalXY; + using Vec2D = o2::math_utils::IntervalXYf_t; enum Relation : int { Below = -1, Inside = 0, diff --git a/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h b/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h index d636f8c5c5f6c..97c7abca67de5 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/HelixHelper.h @@ -25,7 +25,7 @@ namespace track ///__________________________________________________________________________ //< precalculated track radius, center, alpha sin,cos and their combinations -struct TrackAuxPar : public o2::math_utils::CircleXY { +struct TrackAuxPar : public o2::math_utils::CircleXYf_t { using Track = o2::track::TrackPar; float c, s, cc, ss, cs; // cos ans sin of track alpha and their products From bd3f6c4baf0192f8acb08746dab884fe697094e3 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Wed, 21 Oct 2020 17:04:21 +0200 Subject: [PATCH 1033/1751] [math_utils] functions from Utils as template Changes the functions from `Utils` to be templated. There are interfaces for single and double precision implementations, default is single precision, without any suffix, double precision implementation is suffixed with `d`. Templated implementation is hidden in the details folder. Affected code is changed accordingly. --- .../MathUtils/include/MathUtils/Primitive2D.h | 8 +- Common/MathUtils/include/MathUtils/Utils.h | 366 ++++++++---------- .../include/MathUtils/detail/IntervalXY.h | 2 +- .../MathUtils/detail/StatAccumulator.h | 85 ++++ .../include/MathUtils/detail/bitOps.h | 52 +++ .../include/MathUtils/detail/trigonometric.h | 243 ++++++++++++ Common/MathUtils/test/testUtils.cxx | 18 +- .../TrackParametrization.h | 14 +- DataFormats/Reconstruction/src/TrackFwd.cxx | 28 +- .../src/TrackParametrization.cxx | 28 +- .../src/TrackParametrizationWithError.cxx | 24 +- Detectors/Base/include/DetectorsBase/Ray.h | 2 +- Detectors/Base/src/MatLayerCyl.cxx | 2 +- Detectors/Base/src/MatLayerCylSet.cxx | 2 +- Detectors/Base/src/Propagator.cxx | 12 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 12 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 22 +- .../ITSMFT/ITS/base/src/GeometryTGeo.cxx | 2 +- .../ITSReconstruction/RecoGeomHelper.h | 2 +- .../ITS/reconstruction/src/CookedTracker.cxx | 6 +- .../ITS/reconstruction/src/RecoGeomHelper.cxx | 28 +- .../tracking/include/ITStracking/MathUtils.h | 2 +- .../tracking/include/MFTTracking/Tracker.h | 2 +- Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx | 4 +- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 2 +- .../SpacePoints/src/TrackInterpolation.cxx | 12 +- Detectors/TPC/simulation/src/SpaceCharge.cxx | 16 +- .../Upgrades/IT3/base/src/GeometryTGeo.cxx | 2 +- .../PostLS4/IT4/base/src/GeometryTGeo.cxx | 2 +- .../include/DetectorsVertexing/DCAFitterN.h | 30 +- .../DetectorsVertexing/PVertexerHelpers.h | 2 +- Detectors/Vertexing/src/PVertexer.cxx | 16 +- Detectors/Vertexing/test/testDCAFitterN.cxx | 2 +- .../include/Framework/AnalysisDataModel.h | 4 +- GPU/Common/GPUCommonMath.h | 15 + 35 files changed, 702 insertions(+), 367 deletions(-) create mode 100644 Common/MathUtils/include/MathUtils/detail/StatAccumulator.h create mode 100644 Common/MathUtils/include/MathUtils/detail/bitOps.h create mode 100644 Common/MathUtils/include/MathUtils/detail/trigonometric.h diff --git a/Common/MathUtils/include/MathUtils/Primitive2D.h b/Common/MathUtils/include/MathUtils/Primitive2D.h index 8af88e98f3005..120f2d5cdf266 100644 --- a/Common/MathUtils/include/MathUtils/Primitive2D.h +++ b/Common/MathUtils/include/MathUtils/Primitive2D.h @@ -25,13 +25,13 @@ namespace math_utils { template <typename T> using CircleXY = detail::CircleXY<T>; -using CircleXYf_t = CircleXY<float>; -using CircleXYd_t = CircleXY<double>; +using CircleXYf_t = detail::CircleXY<float>; +using CircleXYd_t = detail::CircleXY<double>; template <typename T> using IntervalXY = detail::IntervalXY<T>; -using IntervalXYf_t = IntervalXY<float>; -using IntervalXYd_t = IntervalXY<double>; +using IntervalXYf_t = detail::IntervalXY<float>; +using IntervalXYd_t = detail::IntervalXY<double>; } // namespace math_utils } // namespace o2 diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index db8642848a131..4acf7e633428c 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -10,262 +10,216 @@ /// \file Utils.h /// \brief General auxilliary methods -/// \author ruben.shahoyan@cern.ch +/// \author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch #ifndef ALICEO2_COMMON_MATH_UTILS_ #define ALICEO2_COMMON_MATH_UTILS_ -#ifndef GPUCA_GPUCODE_DEVICE -#include <array> -#include <cmath> -#endif -#include "GPUCommonDef.h" -#include "GPUCommonMath.h" -#include "CommonConstants/MathConstants.h" +#include "MathUtils/detail/bitOps.h" +#include "MathUtils/detail/StatAccumulator.h" +#include "MathUtils/detail/trigonometric.h" namespace o2 { namespace math_utils { -GPUdi() void BringTo02Pi(float& phi) + +GPUdi() float to02Pi(float phi) +{ + return detail::to02Pi<float>(phi); +} + +GPUdi() double to02Pid(double phi) +{ + return detail::to02Pi<double>(phi); +} + +GPUdi() void bringTo02Pi(float& phi) +{ + detail::bringTo02Pi<float>(phi); +} + +GPUdi() void bringTo02Pid(double& phi) +{ + detail::bringTo02Pi<double>(phi); +} + +inline float toPMPiGen(float phi) +{ + return detail::toPMPiGen<float>(phi); +} + +inline double toPMPiGend(double phi) +{ + return detail::toPMPiGen<double>(phi); +} + +inline void bringToPMPiGen(float& phi) +{ + detail::bringToPMPiGen<float>(phi); +} + +inline void bringToPMPiGend(double& phi) +{ + detail::bringToPMPiGen<double>(phi); +} + +inline float to02PiGen(float phi) { - // ensure angle in [0:2pi] for the input in [-pi:pi] or [0:pi] - if (phi < 0.f) { - phi += o2::constants::math::TwoPI; - } + return detail::to02PiGen<float>(phi); } -inline void BringTo02PiGen(float& phi) +inline double to02PiGend(double phi) { - // ensure angle in [0:2pi] for the any input angle - while (phi < 0.f) { - phi += o2::constants::math::TwoPI; - } - while (phi > o2::constants::math::TwoPI) { - phi -= o2::constants::math::TwoPI; - } + return detail::to02PiGen<double>(phi); } -inline void BringToPMPi(float& phi) +inline void bringTo02PiGen(float& phi) { - // ensure angle in [-pi:pi] for the input in [-pi:pi] or [0:pi] - if (phi > o2::constants::math::PI) { - phi -= o2::constants::math::TwoPI; - } else if (phi < -o2::constants::math::PI) { - phi += o2::constants::math::TwoPI; - } + detail::bringTo02PiGen<float>(phi); } -inline void BringToPMPiGen(float& phi) +inline void bringTo02PiGend(double& phi) { - // ensure angle in [-pi:pi] for any input angle - while (phi < -o2::constants::math::PI) { - phi += o2::constants::math::TwoPI; - } - while (phi > o2::constants::math::PI) { - phi -= o2::constants::math::TwoPI; - } + detail::bringTo02PiGen<double>(phi); } -GPUdi() void sincosf(float ang, float& s, float& c) +inline float toPMPi(float phi) { - o2::gpu::GPUCommonMath::SinCos(ang, s, c); + return detail::toPMPi<float>(phi); +} + +inline double toPMPid(double phi) +{ + return detail::toPMPi<double>(phi); +} + +inline void bringToPMPi(float& phi) +{ + return detail::bringToPMPi<float>(phi); +} + +inline void bringToPMPid(double& phi) +{ + return detail::bringToPMPi<double>(phi); } GPUdi() void sincos(float ang, float& s, float& c) { - o2::gpu::GPUCommonMath::SinCos(ang, s, c); + detail::sincos(ang, s, c); +} + +GPUdi() void sincosd(double ang, double& s, double& c) +{ + detail::sincos(ang, s, c); +} + +GPUdi() std::tuple<float, float> sincos(float ang) +{ + return detail::sincos<float>(ang); } -GPUdi() void sincos(double ang, double& s, double& c) +GPUdi() std::tuple<double, double> sincosd(double ang) { - o2::gpu::GPUCommonMath::SinCos(ang, s, c); + return detail::sincos<double>(ang); +} + +inline std::tuple<float, float> rotateZ(float xL, float yL, float snAlp, float csAlp) +{ + return detail::rotateZ<float>(xL, yL, snAlp, csAlp); +} + +inline std::tuple<double, double> rotateZd(double xL, double yL, double snAlp, double csAlp) +{ + return detail::rotateZ<double>(xL, yL, snAlp, csAlp); } inline void rotateZ(float xL, float yL, float& xG, float& yG, float snAlp, float csAlp) { - // 2D rotation of the point by angle alpha (local to global) - xG = xL * csAlp - yL * snAlp; - yG = xL * snAlp + yL * csAlp; + return detail::rotateZ<float>(xL, yL, xG, yG, snAlp, csAlp); } -inline void rotateZInv(float xG, float yG, float& xL, float& yL, float snAlp, float csAlp) +inline void rotateZd(double xL, double yL, double& xG, double& yG, double snAlp, double csAlp) { - // inverse 2D rotation of the point by angle alpha (global to local) - rotateZ(xG, yG, xL, yL, -snAlp, csAlp); + return detail::rotateZ<double>(xL, yL, xG, yG, snAlp, csAlp); } -inline void rotateZ(double xL, double yL, double& xG, double& yG, double snAlp, double csAlp) +inline std::tuple<float, float> rotateZInv(float xG, float yG, float snAlp, float csAlp) { - // 2D rotation of the point by angle alpha (local to global) - xG = xL * csAlp - yL * snAlp; - yG = xL * snAlp + yL * csAlp; + return detail::rotateZInv<float>(xG, yG, snAlp, csAlp); } -inline void rotateZInv(double xG, double yG, double& xL, double& yL, double snAlp, double csAlp) +inline std::tuple<double, double> rotateZInvd(double xG, double yG, double snAlp, double csAlp) +{ + return detail::rotateZInv<double>(xG, yG, snAlp, csAlp); +} + +inline void rotateZInv(float xG, float yG, float& xL, float& yL, float snAlp, float csAlp) { - // inverse 2D rotation of the point by angle alpha (global to local) - rotateZ(xG, yG, xL, yL, -snAlp, csAlp); + detail::rotateZInv<float>(xG, yG, xL, yL, snAlp, csAlp); +} + +inline void rotateZInvd(double xG, double yG, double& xL, double& yL, double snAlp, double csAlp) +{ + detail::rotateZInv<double>(xG, yG, xL, yL, snAlp, csAlp); } #ifndef GPUCA_GPUCODE_DEVICE -inline void RotateZ(std::array<float, 3>& xy, float alpha) +inline void rotateZ(std::array<float, 3>& xy, float alpha) +{ + detail::rotateZ<float>(xy, alpha); +} + +inline void rotateZd(std::array<double, 3>& xy, double alpha) { - // transforms vector in tracking frame alpha to global frame - float sn, cs, x = xy[0]; - o2::gpu::GPUCommonMath::SinCos(alpha, sn, cs); - xy[0] = x * cs - xy[1] * sn; - xy[1] = x * sn + xy[1] * cs; + detail::rotateZ<double>(xy, alpha); } #endif -inline int Angle2Sector(float phi) +inline int angle2Sector(float phi) { - // convert angle to sector ID, phi can be either in 0:2pi or -pi:pi convention - int sect = phi * o2::constants::math::Rad2Deg / o2::constants::math::SectorSpanDeg; - if (phi < 0.f) { - sect += o2::constants::math::NSectors - 1; - } - return sect; -} - -inline float Sector2Angle(int sect) -{ - // convert sector to its angle center, in -pi:pi convention - float ang = o2::constants::math::SectorSpanRad * (0.5f + sect); - BringToPMPi(ang); - return ang; -} - -inline float Angle2Alpha(float phi) -{ - // convert angle to its sector alpha - return Sector2Angle(Angle2Sector(phi)); -} - -//-------------------------------------->>> -// fast bit count -inline int numberOfBitsSet(uint32_t x) -{ - // count number of non-0 bits in 32bit word - x = x - ((x >> 1) & 0x55555555); - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; -} - -// recursive creation of bitmask -template <typename T> -constexpr int bit2Mask(T v) -{ - return 0x1 << v; -} - -template <typename T, typename... Args> -constexpr int bit2Mask(T first, Args... args) -{ - return (0x1 << first) | bit2Mask(args...); -} -//--------------------------------------<<< - -GPUhdi() float FastATan2(float y, float x) -{ - // Fast atan2(y,x) for any angle [-Pi,Pi] - // Average inaccuracy: 0.00048 - // Max inaccuracy: 0.00084 - // Speed: 6.2 times faster than atan2f() - - constexpr float kPi = 3.1415926535897f; - - auto atan = [](float a) -> float { - // returns the arctan for the angular range [-Pi/4, Pi/4] - // the polynomial coefficients are taken from: - // https://stackoverflow.com/questions/42537957/fast-accurate-atan-arctan-approximation-algorithm - constexpr float kA = 0.0776509570923569f; - constexpr float kB = -0.287434475393028f; - constexpr float kC = (kPi / 4 - kA - kB); - float a2 = a * a; - return ((kA * a2 + kB) * a2 + kC) * a; - }; - - auto atan2P = [atan](float yy, float xx) -> float { - // fast atan2(yy,xx) for the angular range [0,+Pi] - constexpr float kPi025 = 1 * kPi / 4; - constexpr float kPi075 = 3 * kPi / 4; - float x1 = xx + yy; // point p1 (x1,y1) = (xx,yy) - Pi/4 - float y1 = yy - xx; - float phi0, tan; - if (xx < 0) { // p1 is in the range [Pi/4, 3*Pi/4] - phi0 = kPi075; - tan = -x1 / y1; - } else { // p1 is in the range [-Pi/4, Pi/4] - phi0 = kPi025; - tan = y1 / x1; - } - return phi0 + atan(tan); - }; - - // fast atan2(y,x) for any angle [-Pi,Pi] - return o2::gpu::GPUCommonMath::Copysign(atan2P(o2::gpu::CAMath::Abs(y), x), y); -} - -struct StatAccumulator { - // mean / RMS accumulator - double sum = 0.; - double sum2 = 0.; - double wsum = 0.; - int n = 0; - void add(float v, float w = 1.) - { - auto c = v * w; - sum += c; - sum2 += c * v; - wsum += w; - n++; - } - double getMean() const { return wsum > 0. ? sum / wsum : 0.; } - bool getMeanRMS2(double& mean, double& rms2) const - { - if (!wsum) { - mean = rms2 = 0; - return false; - } - auto wi = 1. / wsum; - mean = sum * wi; - rms2 = sum2 * wi - mean * mean; - return true; - } - bool getMeanRMS2(float& mean, float& rms2) const - { - if (!wsum) { - mean = rms2 = 0; - return false; - } - auto wi = 1. / wsum; - mean = sum * wi; - rms2 = sum2 * wi - mean * mean; - return true; - } - StatAccumulator& operator+=(const StatAccumulator& other) - { - sum += other.sum; - sum2 += other.sum2; - wsum += other.wsum; - return *this; - } - - StatAccumulator operator+(const StatAccumulator& other) const - { - StatAccumulator res = *this; - res += other; - return res; - } - - void clear() - { - sum = sum2 = wsum = 0.; - n = 0; - } -}; + return detail::angle2Sector<float>(phi); +} + +inline int angle2Sectord(double phi) +{ + return detail::angle2Sector<double>(phi); +} + +inline float sector2Angle(int sect) +{ + return detail::sector2Angle<float>(sect); +} + +inline double sector2Angled(int sect) +{ + return detail::sector2Angle<double>(sect); +} + +inline float angle2Alpha(float phi) +{ + return detail::angle2Alpha<float>(phi); +} + +inline double angle2Alphad(double phi) +{ + return detail::angle2Alpha<double>(phi); +} + +GPUhdi() float fastATan2(float y, float x) +{ + return detail::fastATan2<float>(y, x); +} + +GPUhdi() double fastATan2d(double y, double x) +{ + return detail::fastATan2<double>(y, x); +} + +using detail::StatAccumulator; + +using detail::bit2Mask; +using detail::numberOfBitsSet; } // namespace math_utils } // namespace o2 diff --git a/Common/MathUtils/include/MathUtils/detail/IntervalXY.h b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h index db232e384122e..67d8719a9d3aa 100644 --- a/Common/MathUtils/include/MathUtils/detail/IntervalXY.h +++ b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h @@ -295,8 +295,8 @@ bool IntervalXY<T>::lineCrossParam(const IntervalXY<T>& other, T& t) const t = (-dx * other.getY0() + dy * other.getX0()) / det; return true; } -}; // namespace detail +} // namespace detail } // namespace math_utils } // namespace o2 diff --git a/Common/MathUtils/include/MathUtils/detail/StatAccumulator.h b/Common/MathUtils/include/MathUtils/detail/StatAccumulator.h new file mode 100644 index 0000000000000..2995f30358b7a --- /dev/null +++ b/Common/MathUtils/include/MathUtils/detail/StatAccumulator.h @@ -0,0 +1,85 @@ +// 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 StatAccumulator.h +/// \brief +/// \author ruben.shahoyan@cern.ch michael.lettrich@cern.ch + +#ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_STATACCUMULATOR_H_ +#define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_STATACCUMULATOR_H_ + +#include <tuple> + +namespace o2 +{ +namespace math_utils +{ +namespace detail +{ + +struct StatAccumulator { + // mean / RMS accumulator + double sum = 0.; + double sum2 = 0.; + double wsum = 0.; + int n = 0; + + void add(float v, float w = 1.) + { + const auto c = v * w; + sum += c; + sum2 += c * v; + wsum += w; + n++; + } + double getMean() const { return wsum > 0. ? sum / wsum : 0.; } + + template <typename T = float> + std::tuple<T, T> getMeanRMS2() const + { + T mean = 0; + T rms2 = 0; + + if (wsum) { + const T wi = 1. / wsum; + mean = sum * wi; + rms2 = sum2 * wi - mean * mean; + } + + return {mean, rms2}; + } + + StatAccumulator& operator+=(const StatAccumulator& other) + { + sum += other.sum; + sum2 += other.sum2; + wsum += other.wsum; + return *this; + } + + StatAccumulator operator+(const StatAccumulator& other) const + { + StatAccumulator res = *this; + res += other; + return res; + } + + void clear() + { + sum = sum2 = wsum = 0.; + n = 0; + } +}; + +} // namespace detail +} // namespace math_utils +} // namespace o2 + +#endif /* MATHUTILS_INCLUDE_MATHUTILS_DETAIL_STATACCUMULATOR_H_ */ diff --git a/Common/MathUtils/include/MathUtils/detail/bitOps.h b/Common/MathUtils/include/MathUtils/detail/bitOps.h new file mode 100644 index 0000000000000..1603b74ffde65 --- /dev/null +++ b/Common/MathUtils/include/MathUtils/detail/bitOps.h @@ -0,0 +1,52 @@ +// 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 bitOps.h +/// \brief +/// \author ruben.shahoyan@cern.ch michael.lettrich@cern.ch + +#ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_BITOPS_H_ +#define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_BITOPS_H_ + +#include <cstdint> + +namespace o2 +{ +namespace math_utils +{ +namespace detail +{ +// fast bit count +inline int numberOfBitsSet(uint32_t x) +{ + // count number of non-0 bits in 32bit word + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; +} + +// recursive creation of bitmask +template <typename T> +constexpr int bit2Mask(T v) +{ + return 0x1 << v; +} + +template <typename T, typename... Args> +constexpr int bit2Mask(T first, Args... args) +{ + return (0x1 << first) | bit2Mask(args...); +} + +} // namespace detail +} // namespace math_utils +} // namespace o2 + +#endif /* MATHUTILS_INCLUDE_MATHUTILS_DETAIL_BITOPS_H_ */ diff --git a/Common/MathUtils/include/MathUtils/detail/trigonometric.h b/Common/MathUtils/include/MathUtils/detail/trigonometric.h new file mode 100644 index 0000000000000..20e9d335948d9 --- /dev/null +++ b/Common/MathUtils/include/MathUtils/detail/trigonometric.h @@ -0,0 +1,243 @@ +// 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 trigonometric.h +/// \brief +/// \author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch + +#ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_TRIGONOMETRIC_H_ +#define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_TRIGONOMETRIC_H_ + +#ifndef GPUCA_GPUCODE_DEVICE +#include <array> +#include <cmath> +#endif +#include "GPUCommonDef.h" +#include "GPUCommonMath.h" +#include "CommonConstants/MathConstants.h" +#include <tuple> + +namespace o2 +{ +namespace math_utils +{ +namespace detail +{ + +template <typename T> +GPUdi() T to02Pi(T phi) +{ + T res = phi; + // ensure angle in [0:2pi] for the input in [-pi:pi] or [0:pi] + if (res < 0.f) { + res += o2::constants::math::TwoPI; + } + return res; +} + +template <typename T> +GPUdi() void bringTo02Pi(T& phi) +{ + phi = to02Pi<T>(phi); +} + +template <typename T> +inline T to02PiGen(T phi) +{ + T res = phi; + // ensure angle in [0:2pi] for the any input angle + while (res < 0.f) { + res += o2::constants::math::TwoPI; + } + while (res > o2::constants::math::TwoPI) { + res -= o2::constants::math::TwoPI; + } + return res; +} + +template <typename T> +inline void bringTo02PiGen(T& phi) +{ + phi = to02PiGen<T>(phi); +} + +template <typename T> +inline T toPMPi(T phi) +{ + T res = phi; + // ensure angle in [-pi:pi] for the input in [-pi:pi] or [0:pi] + if (res > o2::constants::math::PI) { + res -= o2::constants::math::TwoPI; + } else if (res < -o2::constants::math::PI) { + res += o2::constants::math::TwoPI; + } + return res; +} + +template <typename T> +inline void bringToPMPi(T& phi) +{ + phi = toPMPi<T>(phi); +} + +template <typename T> +inline T toPMPiGen(T phi) +{ + // ensure angle in [-pi:pi] for any input angle + T res = phi; + while (res < -o2::constants::math::PI) { + res += o2::constants::math::TwoPI; + } + while (res > o2::constants::math::PI) { + res -= o2::constants::math::TwoPI; + } + return res; +} + +template <typename T> +inline void bringToPMPiGen(T& phi) +{ + phi = toPMPiGen<T>(phi); +} + +GPUdi() void sincos(float ang, float& s, float& c) +{ + o2::gpu::GPUCommonMath::SinCos(ang, s, c); +} + +GPUdi() void sincos(double ang, double& s, double& c) +{ + o2::gpu::GPUCommonMath::SinCos(ang, s, c); +} + +template <typename T> +GPUdi() std::tuple<T, T> sincos(T ang) +{ + T sin = 0; + T cos = 0; + o2::gpu::GPUCommonMath::SinCos(ang, sin, cos); + return std::make_tuple(sin, cos); +} + +template <typename T> +inline std::tuple<T, T> rotateZ(T xL, T yL, T snAlp, T csAlp) +{ + // 2D rotation of the point by angle alpha (local to global) + return std::make_tuple(xL * csAlp - yL * snAlp, xL * snAlp + yL * csAlp); +} + +template <typename T> +inline void rotateZ(T xL, T yL, T& xG, T& yG, T snAlp, T csAlp) +{ + std::tie(xG, yG) = rotateZ<T>(xL, yL, snAlp, csAlp); +} + +template <typename T> +inline std::tuple<T, T> rotateZInv(T xG, T yG, T snAlp, T csAlp) +{ + // inverse 2D rotation of the point by angle alpha (global to local) + return rotateZ<T>(xG, yG, -snAlp, csAlp); +} + +template <typename T> +inline void rotateZInv(T xG, T yG, T& xL, T& yL, T snAlp, T csAlp) +{ + // inverse 2D rotation of the point by angle alpha (global to local) + rotateZ<T>(xG, yG, xL, yL, -snAlp, csAlp); +} + +#ifndef GPUCA_GPUCODE_DEVICE + +template <typename T> +inline void rotateZ(std::array<T, 3>& xy, T alpha) +{ + // transforms vector in tracking frame alpha to global frame + auto [sin, cos] = sincos<T>(alpha); + const T x = xy[0]; + xy[0] = x * cos - xy[1] * sin; + xy[1] = x * sin + xy[1] * cos; +} + +#endif + +template <typename T> +inline int angle2Sector(T phi) +{ + // convert angle to sector ID, phi can be either in 0:2pi or -pi:pi convention + int sect = phi * o2::constants::math::Rad2Deg / o2::constants::math::SectorSpanDeg; + if (phi < 0.f) { + sect += o2::constants::math::NSectors - 1; + } + return sect; +} + +template <typename T> +inline T sector2Angle(int sect) +{ + // convert sector to its angle center, in -pi:pi convention + T ang = o2::constants::math::SectorSpanRad * (0.5f + sect); + bringToPMPi<T>(ang); + return ang; +} + +template <typename T> +inline T angle2Alpha(T phi) +{ + // convert angle to its sector alpha + return sector2Angle<T>(angle2Sector<T>(phi)); +} + +template <typename T> +GPUhdi() T fastATan2(T y, T x) +{ + // Fast atan2(y,x) for any angle [-Pi,Pi] + // Average inaccuracy: 0.00048 + // Max inaccuracy: 0.00084 + // Speed: 6.2 times faster than atan2f() + constexpr T Pi = 3.1415926535897932384626433832795; + + auto atan = [](T a) -> T { + // returns the arctan for the angular range [-Pi/4, Pi/4] + // the polynomial coefficients are taken from: + // https://stackoverflow.com/questions/42537957/fast-accurate-atan-arctan-approximation-algorithm + constexpr T A = 0.0776509570923569; + constexpr T B = -0.287434475393028; + constexpr T C = (Pi / 4 - A - B); + const T a2 = a * a; + return ((A * a2 + B) * a2 + C) * a; + }; + + auto atan2P = [atan](T yy, T xx) -> T { + // fast atan2(yy,xx) for the angular range [0,+Pi] + constexpr T Pi025 = 1 * Pi / 4; + constexpr T Pi075 = 3 * Pi / 4; + const T x1 = xx + yy; // point p1 (x1,y1) = (xx,yy) - Pi/4 + const T y1 = yy - xx; + T phi0 = 0; + T tan = 0; + if (xx < 0) { // p1 is in the range [Pi/4, 3*Pi/4] + phi0 = Pi075; + tan = -x1 / y1; + } else { // p1 is in the range [-Pi/4, Pi/4] + phi0 = Pi025; + tan = y1 / x1; + } + return phi0 + atan(tan); + }; + + // fast atan2(y,x) for any angle [-Pi,Pi] + return o2::gpu::GPUCommonMath::Copysign(atan2P(o2::gpu::GPUCommonMath::Abs(y), x), y); +} + +} // namespace detail +} // namespace math_utils +} // namespace o2 + +#endif /* MATHUTILS_INCLUDE_MATHUTILS_DETAIL_TRIGONOMETRIC_H_ */ diff --git a/Common/MathUtils/test/testUtils.cxx b/Common/MathUtils/test/testUtils.cxx index 843124a742791..4bf03b94f8322 100644 --- a/Common/MathUtils/test/testUtils.cxx +++ b/Common/MathUtils/test/testUtils.cxx @@ -25,25 +25,25 @@ BOOST_AUTO_TEST_CASE(Utils_test) { // test MathUtils/Utils.h - { // test FastATan2() + { // test fastATan2() int n = 1000; - TProfile* p = new TProfile("pFastATan2", "FastATan2(y,x)", n, -TMath::Pi(), TMath::Pi()); + TProfile* p = new TProfile("pFastATan2", "fastATan2(y,x)", n, -TMath::Pi(), TMath::Pi()); double maxDiff = 0; for (int i = 0; i < n; i++) { double phi0 = -TMath::Pi() + i * TMath::TwoPi() / n; float x = TMath::Cos(phi0); float y = TMath::Sin(phi0); - float phi = math_utils::FastATan2(y, x); + float phi = math_utils::fastATan2(y, x); double diff = phi - phi0; p->Fill(phi0, diff); - diff = fabs(diff); + diff = std::fabs(diff); if (diff > maxDiff) { maxDiff = diff; } } //p->Draw(); - std::cout << "test FastATan2:" << std::endl; + std::cout << "test fastATan2:" << std::endl; std::cout << " Max inaccuracy " << maxDiff << std::endl; // test the speed @@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(Utils_test) begin = std::chrono::high_resolution_clock::now(); for (int i = 0; i < iterations; ++i) { for (int j = 0; j < M; ++j) { - dsum += atan2(vyd[j], vxd[j]); + dsum += std::atan2(vyd[j], vxd[j]); } } end = std::chrono::high_resolution_clock::now(); @@ -108,15 +108,15 @@ BOOST_AUTO_TEST_CASE(Utils_test) begin = std::chrono::high_resolution_clock::now(); for (int i = 0; i < iterations; ++i) { for (int j = 0; j < M; ++j) { - sum += math_utils::FastATan2(vy[j], vx[j]); + sum += math_utils::fastATan2(vy[j], vx[j]); } } end = std::chrono::high_resolution_clock::now(); auto time4 = scale * std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count(); - std::cout << " FastATan2: time " << time4 << " ns. checksum " << sum << std::endl; + std::cout << " fastATan2: time " << time4 << " ns. checksum " << sum << std::endl; std::cout << " speed up to atan2f(): " << (time3 - time1) / (time4 - time1) << " times " << std::endl; BOOST_CHECK(maxDiff < 1.e-3); - } // test FastATan2() + } // test fastATan2() } diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index fd985a0859d90..aff79675760c9 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -438,8 +438,8 @@ inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_ { // get circle params in loc and lab frame, for straight line just set to global coordinates getCircleParamsLoc(bz, c); - o2::math_utils::sincos(getAlpha(), sna, csa); - o2::math_utils::rotateZ(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame + o2::math_utils::detail::sincos(getAlpha(), sna, csa); + o2::math_utils::detail::rotateZ<value_t>(c.xC, c.yC, c.xC, c.yC, sna, csa); // center in global frame } //_______________________________________________________ @@ -447,8 +447,8 @@ template <typename value_T> inline void TrackParametrization<value_T>::getLineParams(o2::math_utils::IntervalXY<value_t>& ln, value_t& sna, value_t& csa) const { // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } - o2::math_utils::sincos(getAlpha(), sna, csa); - o2::math_utils::rotateZ(getX(), getY(), ln.getX0(), ln.getY0(), sna, csa); // reference point in global frame + o2::math_utils::detail::sincos(getAlpha(), sna, csa); + o2::math_utils::detail::rotateZ<value_t>(getX(), getY(), ln.getX0(), ln.getY0(), sna, csa); // reference point in global frame value_t snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); ln.setDX(csp * csa - snp * sna); ln.setDY(snp * csa + csp * sna); @@ -481,7 +481,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu { // track pt direction phi (in 0:2pi range) value_t phi = std::asin(getSnp()) + getAlpha(); - math_utils::BringTo02Pi(phi); + math_utils::detail::bringTo02Pi<value_t>(phi); return phi; } @@ -491,7 +491,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu { // angle of track position (in -pi:pi range) value_t phi = std::atan2(getY(), getX()) + getAlpha(); - math_utils::BringTo02Pi(phi); + math_utils::detail::bringTo02Pi<value_t>(phi); return phi; } @@ -583,7 +583,7 @@ inline void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const xyz[0] = getX(); xyz[1] = getY(); xyz[2] = getZ(); - math_utils::RotateZ(xyz, getAlpha()); + math_utils::detail::rotateZ<value_t>(xyz, getAlpha()); } #ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index bec6f2b2eae68..c826f73126df1 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -38,8 +38,7 @@ void TrackParFwd::propagateParamToZlinear(double zEnd) // Compute track parameters auto dZ = (zEnd - getZ()); auto phi0 = getPhi(); - double cosphi0, sinphi0; - o2::math_utils::sincos(phi0, sinphi0, cosphi0); + auto [sinphi0, cosphi0] = o2::math_utils::sincosd(phi0); auto invtanl0 = 1.0 / getTanl(); auto n = dZ * invtanl0; mParameters(0) += n * cosphi0; @@ -57,8 +56,7 @@ void TrackParCovFwd::propagateToZlinear(double zEnd) auto phi0 = getPhi(); auto tanl0 = getTanl(); auto invtanl0 = 1.0 / tanl0; - double cosphi0, sinphi0; - o2::math_utils::sincos(phi0, sinphi0, cosphi0); + auto [sinphi0, cosphi0] = o2::math_utils::sincosd(phi0); auto n = dZ * invtanl0; auto m = n * invtanl0; @@ -90,8 +88,7 @@ void TrackParFwd::propagateParamToZquadratic(double zEnd, double zField) // Compute track parameters auto dZ = (zEnd - getZ()); auto phi0 = getPhi(); - double cosphi0, sinphi0; - o2::math_utils::sincos(phi0, sinphi0, cosphi0); + auto [sinphi0, cosphi0] = o2::math_utils::sincosd(phi0); auto invtanl0 = 1.0 / getTanl(); auto invqpt0 = getInvQPt(); auto Hz = std::copysign(1, zField); @@ -118,8 +115,7 @@ void TrackParCovFwd::propagateToZquadratic(double zEnd, double zField) // Compute track parameters auto dZ = (zEnd - getZ()); auto phi0 = getPhi(); - double cosphi0, sinphi0; - o2::math_utils::sincos(phi0, sinphi0, cosphi0); + auto [sinphi0, cosphi0] = o2::math_utils::sincosd(phi0); auto invtanl0 = 1.0 / getTanl(); auto invqpt0 = getInvQPt(); auto Hz = std::copysign(1, zField); @@ -166,13 +162,12 @@ void TrackParFwd::propagateParamToZhelix(double zEnd, double zField) auto invtanl0 = 1.0 / tanl0; auto invqpt0 = getInvQPt(); auto qpt0 = 1.0 / invqpt0; - double cosphi0, sinphi0; - o2::math_utils::sincos(phi0, sinphi0, cosphi0); + auto [sinphi0, cosphi0] = o2::math_utils::sincosd(phi0); + auto k = TMath::Abs(o2::constants::math::B2C * zField); auto invk = 1.0 / k; auto theta = -invqpt0 * dZ * k * invtanl0; - double costheta, sintheta; - o2::math_utils::sincos(theta, sintheta, costheta); + auto [sintheta, costheta] = o2::math_utils::sincosd(theta); auto Hz = std::copysign(1, zField); auto Y = sinphi0 * qpt0 * invk; auto X = cosphi0 * qpt0 * invk; @@ -200,13 +195,11 @@ void TrackParCovFwd::propagateToZhelix(double zEnd, double zField) auto invtanl0 = 1.0 / tanl0; auto invqpt0 = getInvQPt(); auto qpt0 = 1.0 / invqpt0; - double cosphi0, sinphi0; - o2::math_utils::sincos(phi0, sinphi0, cosphi0); + auto [sinphi0, cosphi0] = o2::math_utils::sincosd(phi0); auto k = TMath::Abs(o2::constants::math::B2C * zField); auto invk = 1.0 / k; auto theta = -invqpt0 * dZ * k * invtanl0; - double costheta, sintheta; - o2::math_utils::sincos(theta, sintheta, costheta); + auto [sintheta, costheta] = o2::math_utils::sincosd(theta); auto Hz = std::copysign(1, zField); auto L = qpt0 * qpt0 * invk; auto N = dZ * invtanl0 * qpt0; @@ -318,8 +311,7 @@ void TrackParCovFwd::addMCSEffect(double dZ, double x_over_X0) auto invtanl0 = 1.0 / tanl0; auto invqpt0 = getInvQPt(); - double cosphi0, sinphi0; - o2::math_utils::sincos(phi0, sinphi0, cosphi0); + auto [sinphi0, cosphi0] = o2::math_utils::sincosd(phi0); auto csclambda = TMath::Abs(TMath::Sqrt(1 + tanl0 * tanl0) * invtanl0); auto pathLengthOverX0 = x_over_X0 * csclambda; // diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index e5952f857e238..71ee601915ada 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -54,16 +54,16 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; value_t alp = 0; if (sectorAlpha || radPos2 < 1) { - alp = atan2f(pxpypz[1], pxpypz[0]); + alp = std::atan2(pxpypz[1], pxpypz[0]); } else { - alp = atan2f(xyz[1], xyz[0]); + alp = std::atan2(xyz[1], xyz[0]); } if (sectorAlpha) { - alp = math_utils::Angle2Alpha(alp); + alp = math_utils::detail::angle2Alpha<value_t>(alp); } // value_t sn, cs; - math_utils::sincos(alp, sn, cs); + math_utils::detail::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 if (std::fabs(sn) < 2 * kSafe) { if (alp > 0) { @@ -71,22 +71,22 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim } else { alp += alp > -constants::math::PIHalf ? -2 * kSafe : 2 * kSafe; } - math_utils::sincos(alp, sn, cs); + math_utils::detail::sincos(alp, sn, cs); } else if (std::fabs(cs) < 2 * kSafe) { if (alp > 0) { alp += alp > constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } else { alp += alp > -constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } - math_utils::sincos(alp, sn, cs); + math_utils::detail::sincos(alp, sn, cs); } // get the vertex of origin and the momentum dim3_t ver{xyz[0], xyz[1], xyz[2]}; dim3_t mom{pxpypz[0], pxpypz[1], pxpypz[2]}; // // Rotate to the local coordinate system - math_utils::RotateZ(ver, -alp); - math_utils::RotateZ(mom, -alp); + math_utils::detail::rotateZ<value_t>(ver, -alp); + math_utils::detail::rotateZ<value_t>(mom, -alp); // value_t ptI = 1.f / sqrt(mom[0] * mom[0] + mom[1] * mom[1]); mX = ver[0]; @@ -116,7 +116,7 @@ bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const } value_t cs, sn, pt = getPt(); value_t r = std::sqrt((1.f - getSnp()) * (1.f + getSnp())); - math_utils::sincos(getAlpha(), sn, cs); + math_utils::detail::sincos(getAlpha(), sn, cs); pxyz[0] = pt * (r * cs - getSnp() * sn); pxyz[1] = pt * (getSnp() * cs + r * sn); pxyz[2] = pt * getTgl(); @@ -137,7 +137,7 @@ bool TrackParametrization<value_T>::getPosDirGlo(std::array<value_t, 9>& posdirp value_t csp = std::sqrt((1.f - snp) * (1.f + snp)); value_t cstht = std::sqrt(1.f + getTgl() * getTgl()); value_t csthti = 1.f / cstht; - math_utils::sincos(getAlpha(), sn, cs); + math_utils::detail::sincos(getAlpha(), sn, cs); posdirp[0] = getX() * cs - getY() * sn; posdirp[1] = getX() * sn + getY() * cs; posdirp[2] = getZ(); @@ -158,10 +158,10 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) return false; } // - math_utils::BringToPMPi(alpha); + math_utils::detail::bringToPMPi<value_t>(alpha); // value_t ca = 0, sa = 0; - math_utils::sincos(alpha - getAlpha(), sa, ca); + math_utils::detail::sincos(alpha - getAlpha(), sa, ca); value_t snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle // direction in local frame is along the X axis @@ -358,7 +358,7 @@ bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3 { // propagate track to DCA to the vertex value_t sn, cs, alp = getAlpha(); - math_utils::sincos(alp, sn, cs); + math_utils::detail::sincos(alp, sn, cs); value_t x = getX(), y = getY(), snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); value_t xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; @@ -453,7 +453,7 @@ void TrackParametrization<value_T>::invertParam() // Transform this track to the local coord. system rotated by 180 deg. mX = -mX; mAlpha += constants::math::PI; - math_utils::BringToPMPi(mAlpha); + math_utils::detail::bringToPMPi<value_t>(mAlpha); // mP[0] = -mP[0]; mP[3] = -mP[3]; diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index a44f1c09e9c71..80232070a097a 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -167,10 +167,10 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) return false; } // - math_utils::BringToPMPi(alpha); + math_utils::detail::bringToPMPi<value_t>(alpha); // value_t ca = 0, sa = 0; - math_utils::sincos(alpha - this->getAlpha(), sa, ca); + math_utils::detail::sincos(alpha - this->getAlpha(), sa, ca); value_t snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle // direction in local frame is along the X axis @@ -218,7 +218,7 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat { // propagate track to DCA to the vertex value_t sn, cs, alp = this->getAlpha(); - o2::math_utils::sincos(alp, sn, cs); + o2::math_utils::detail::sincos(alp, sn, cs); value_t x = this->getX(), y = this->getY(), snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); value_t xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; @@ -247,7 +247,7 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat } *this = tmpT; if (dca) { - o2::math_utils::sincos(alp, sn, cs); + o2::math_utils::detail::sincos(alp, sn, cs); auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; dca->set(this->getY() - yv, this->getZ() - zv, getSigmaY2() + s2ylocvtx, getSigmaZY(), getSigmaZ2() + vtx.getSigmaZ2()); } @@ -276,11 +276,11 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 alp = std::atan2(xyz[1], xyz[0]); } if (sectorAlpha) { - alp = math_utils::Angle2Alpha(alp); + alp = math_utils::detail::angle2Alpha<value_t>(alp); } // value_t sn, cs; - math_utils::sincos(alp, sn, cs); + math_utils::detail::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 if (std::fabs(sn) < 2.f * kSafe) { if (alp > 0) { @@ -288,24 +288,24 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 } else { alp += alp > -constants::math::PIHalf ? -2.f * kSafe : 2.f * kSafe; } - math_utils::sincos(alp, sn, cs); + math_utils::detail::sincos(alp, sn, cs); } else if (std::fabs(cs) < 2.f * kSafe) { if (alp > 0) { alp += alp > constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } else { alp += alp > -constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } - math_utils::sincos(alp, sn, cs); + math_utils::detail::sincos(alp, sn, cs); } // get the vertex of origin and the momentum dim3_t ver{xyz[0], xyz[1], xyz[2]}; dim3_t mom{pxpypz[0], pxpypz[1], pxpypz[2]}; // // Rotate to the local coordinate system - math_utils::RotateZ(ver, -alp); - math_utils::RotateZ(mom, -alp); + math_utils::detail::rotateZ<value_t>(ver, -alp); + math_utils::detail::rotateZ<value_t>(mom, -alp); // - value_t pt = sqrt(mom[0] * mom[0] + mom[1] * mom[1]); + value_t pt = std::sqrt(mom[0] * mom[0] + mom[1] * mom[1]); value_t ptI = 1.f / pt; this->setX(ver[0]); this->setAlpha(alp); @@ -1022,7 +1022,7 @@ bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(std::array<value auto pt = this->getPt(); value_t sn, cs; - o2::math_utils::sincos(this->getAlpha(), sn, cs); + o2::math_utils::detail::sincos(this->getAlpha(), sn, cs); auto r = std::sqrt((1. - this->getSnp()) * (1. + this->getSnp())); auto m00 = -sn, m10 = cs; auto m23 = -pt * (sn + this->getSnp() * cs / r), m43 = -pt * pt * (r * cs - this->getSnp() * sn); diff --git a/Detectors/Base/include/DetectorsBase/Ray.h b/Detectors/Base/include/DetectorsBase/Ray.h index 5924d93ce0370..4b489b599fb5f 100644 --- a/Detectors/Base/include/DetectorsBase/Ray.h +++ b/Detectors/Base/include/DetectorsBase/Ray.h @@ -79,7 +79,7 @@ class Ray GPUd() float getPhi(float t) const { float p = o2::gpu::CAMath::ATan2(mP[1] + t * mD[1], mP[0] + t * mD[0]); - o2::math_utils::BringTo02Pi(p); + o2::math_utils::bringTo02Pi(p); return p; } diff --git a/Detectors/Base/src/MatLayerCyl.cxx b/Detectors/Base/src/MatLayerCyl.cxx index fe8468a2292af..f2d3cb89dcde7 100644 --- a/Detectors/Base/src/MatLayerCyl.cxx +++ b/Detectors/Base/src/MatLayerCyl.cxx @@ -132,7 +132,7 @@ void MatLayerCyl::populateFromTGeo(int ip, int iz, int ntrPerCell) float zs = zmn + (isz + 0.5) * dz; float dzt = zs > 0.f ? 0.25 * dz : -0.25 * dz; // to avoid 90 degree polar angle for (int isp = ntrPerCell; isp--;) { - o2::math_utils::sincosf(phmn + (isp + 0.5) * getDPhi() / ntrPerCell, sn, cs); + o2::math_utils::sincos(phmn + (isp + 0.5) * getDPhi() / ntrPerCell, sn, cs); auto bud = o2::base::GeometryManager::meanMaterialBudget(rMin * cs, rMin * sn, zs - dzt, rMax * cs, rMax * sn, zs + dzt); if (bud.length > 0.) { meanRho += bud.length * bud.meanRho; diff --git a/Detectors/Base/src/MatLayerCylSet.cxx b/Detectors/Base/src/MatLayerCylSet.cxx index 63d73318c6403..a6bd484d070f0 100644 --- a/Detectors/Base/src/MatLayerCylSet.cxx +++ b/Detectors/Base/src/MatLayerCylSet.cxx @@ -135,7 +135,7 @@ void MatLayerCylSet::dumpToTree(const std::string outName) const merge = ips == ips1 ? -1 : lr.canMergePhiSlices(ips, ips1); // -1 for already merged } else merge = -2; // last one - o2::math_utils::sincosf(phi, sn, cs); + o2::math_utils::sincos(phi, sn, cs); float x = r * cs, y = r * sn; for (int iz = 0; iz < lr.getNZBins(); iz++) { float z = 0.5 * (lr.getZBinMin(iz) + lr.getZBinMax(iz)); diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 88ea48119afc1..62767f2cfa4c6 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -292,7 +292,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::math_utils::sincosf(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; @@ -321,7 +321,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac } track = tmpT; if (dca) { - o2::math_utils::sincosf(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; dca->set(track.getY() - yv, track.getZ() - zv, track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2()); @@ -337,7 +337,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::math_utils::sincosf(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; @@ -366,7 +366,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 } track = tmpT; if (dca) { - o2::math_utils::sincosf(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn; dca->set(track.getY() - yv, track.getZ() - zv, track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2()); @@ -382,7 +382,7 @@ bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::math_utils::sincosf(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; @@ -426,7 +426,7 @@ bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2: { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); - o2::math_utils::sincosf(alp, sn, cs); + o2::math_utils::sincos(alp, sn, cs); float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index e90acf6aa6a2c..d59b0d9d5d73f 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -483,9 +483,9 @@ bool MatchTOF::prepareTracks() LOG(DEBUG) << "Global coordinates After propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; LOG(DEBUG) << "Radius xy After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); LOG(DEBUG) << "Radius xyz After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); - LOG(DEBUG) << "The track will go to sector " << o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + LOG(DEBUG) << "The track will go to sector " << o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); - mTracksSectIndexCache[o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); + mTracksSectIndexCache[o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); //delete trc; // Check: is this needed? } @@ -626,10 +626,10 @@ bool MatchTOF::prepareTPCTracks() LOG(INFO) << "Global coordinates After propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; LOG(INFO) << "Radius xy After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); LOG(INFO) << "Radius xyz After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); - LOG(INFO) << "The track will go to sector " << o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + LOG(INFO) << "The track will go to sector " << o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); #endif - mTracksSectIndexCache[o2::math_utils::Angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); + mTracksSectIndexCache[o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0]))].push_back(it); //delete trc; // Check: is this needed? } @@ -1510,7 +1510,7 @@ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float st if (fabs(trc.getY()) > trc.getX() * tanHalfSector) { // we are still in the same sector // we need to rotate the track to go to the new sector //Printf("propagateToRefX: changing sector"); - auto alphaNew = o2::math_utils::Angle2Alpha(trc.getPhiPos()); + auto alphaNew = o2::math_utils::angle2Alpha(trc.getPhiPos()); if (!trc.rotate(alphaNew) != 0) { // Printf("propagateToRefX: failed to rotate"); break; // failed (this line is taken from MatchTPCITS and the following comment too: RS: check effect on matching tracks to neighbouring sector) @@ -1548,7 +1548,7 @@ bool MatchTOF::propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef if (fabs(trcNoCov.getY()) > trcNoCov.getX() * tanHalfSector) { // we are still in the same sector // we need to rotate the track to go to the new sector //Printf("propagateToRefX: changing sector"); - auto alphaNew = o2::math_utils::Angle2Alpha(trcNoCov.getPhiPos()); + auto alphaNew = o2::math_utils::angle2Alpha(trcNoCov.getPhiPos()); if (!trcNoCov.rotateParam(alphaNew) != 0) { // Printf("propagateToRefX: failed to rotate"); break; // failed (this line is taken from MatchTPCITS and the following comment too: RS: check effect on matching tracks to neighbouring sector) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index df040118e61aa..226b721c71b42 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -563,7 +563,7 @@ bool MatchTPCITS::prepareTPCTracks() // TODO : special treatment of tracks crossing the CE // cache work track index - mTPCSectIndexCache[o2::math_utils::Angle2Sector(trc.getAlpha())].push_back(mTPCWork.size() - 1); + mTPCSectIndexCache[o2::math_utils::angle2Sector(trc.getAlpha())].push_back(mTPCWork.size() - 1); } /// full drift time + safety margin @@ -702,7 +702,7 @@ bool MatchTPCITS::prepareITSTracks() int nWorkTracks = mITSWork.size(); // working copy of outer track param auto& trc = mITSWork.emplace_back(static_cast<const o2::track::TrackParCov&>(trcOrig.getParamOut()), it); - if (!trc.rotate(o2::math_utils::Angle2Alpha(trc.getPhiPos()))) { + if (!trc.rotate(o2::math_utils::angle2Alpha(trc.getPhiPos()))) { mITSWork.pop_back(); // discard failed track continue; } @@ -717,7 +717,7 @@ bool MatchTPCITS::prepareITSTracks() trc.roFrame = irof; // cache work track index - int sector = o2::math_utils::Angle2Sector(trc.getAlpha()); + int sector = o2::math_utils::angle2Sector(trc.getAlpha()); mITSSectIndexCache[sector].push_back(nWorkTracks); // If the ITS track is very close to the sector edge, it may match also to a TPC track in the neighb. sector. @@ -1199,7 +1199,7 @@ void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector) // to their setctor edge that their matching should be checked also in the neighbouring sector mITSWork.push_back(mITSWork.back()); // clone the last track defined in given sector auto& trc = mITSWork.back(); - if (trc.rotate(o2::math_utils::Sector2Angle(sector)) && + if (trc.rotate(o2::math_utils::sector2Angle(sector)) && o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, XMatchingRef, o2::constants::physics::MassPionCharged, MaxSnp, 2., MatCorrType::USEMatCorrNONE)) { // TODO: use faster prop here, no 3d field, materials @@ -1233,7 +1233,7 @@ bool MatchTPCITS::propagateToRefX(o2::track::TrackParCov& trc) if (!trialsLeft--) { break; } - auto alphaNew = o2::math_utils::Angle2Alpha(trc.getPhiPos()); + auto alphaNew = o2::math_utils::angle2Alpha(trc.getPhiPos()); if (!trc.rotate(alphaNew) != 0) { break; // failed (RS: check effect on matching tracks to neighbouring sector) } @@ -1411,7 +1411,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); // rotate to 1 cluster's sector - if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1451,7 +1451,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); if (prevsector != sector) { prevsector = sector; - if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1592,7 +1592,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime() - timeTB, clsX, clsYZ[0], clsYZ[1]); // rotate to 1 cluster's sector - if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1632,7 +1632,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime() - timeTB, clsX, clsYZ[0], clsYZ[1]); if (prevsector != sector) { prevsector = sector; - if (!tracOut.rotate(o2::math_utils::Sector2Angle(sector % 18))) { + if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1718,7 +1718,7 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo mTPCTransform->Transform(sectArr[icl], rowArr[icl], clsArr[icl]->getPad(), clsArr[icl]->getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); mTPCClusterParam->GetClusterErrors2(rowArr[icl], clsYZ[1], trcIn.getSnp(), trcIn.getTgl(), clsCov[0], clsCov[2]); uint8_t sectCurr = sectArr[icl]; - if (!trcIn.rotate(o2::math_utils::Sector2Angle(sectCurr % 18))) { + if (!trcIn.rotate(o2::math_utils::sector2Angle(sectCurr % 18))) { LOG(WARNING) << "Rotation to sector " << int(sectCurr % 18) << " failed"; return false; } @@ -1733,7 +1733,7 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo for (; icl--;) { if (sectArr[icl] != sectCurr) { sectCurr = sectArr[icl]; - if (!trcIn.rotate(o2::math_utils::Sector2Angle(sectCurr % 18))) { + if (!trcIn.rotate(o2::math_utils::sector2Angle(sectCurr % 18))) { LOG(WARNING) << "Rotation to sector " << int(sectCurr % 18) << " failed"; LOG(WARNING) << trcIn.asString(); return false; diff --git a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx index cc7ccf6610b0d..528e9a65a1a5c 100644 --- a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx @@ -708,7 +708,7 @@ void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp) double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t; x = Sqrt(xp * xp + yp * yp); alp = ATan2(yp, xp); - o2::math_utils::BringTo02Pi(alp); + o2::math_utils::bringTo02Pi(alp); } //__________________________________________________________________________ diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h index fb1bac284767a..ebb3abc109e87 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h @@ -141,7 +141,7 @@ inline int RecoGeomHelper::RecoLayer::getLadderID(float phi) const // Get ladder ID corresponding to phi. // Note: this is an approximate method, precise within 1/3 of average ladder width, // one should check also the neighbouring ladders +/-1 - o2::math_utils::BringTo02Pi(phi); + o2::math_utils::bringTo02Pi(phi); constexpr float PI2Inv = 1.f / o2::constants::math::TwoPI; return phi2ladder[int(phi * PI2Inv * phi2ladder.size())]; } diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx index 35f6f9d49313b..dc7c65bb9a260 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx @@ -367,7 +367,7 @@ void CookedTracker::trackSeeds(std::vector<TrackITSExt>& seeds) auto x = track.getX(); auto y = track.getY(); Float_t phi = track.getAlpha() + TMath::ATan2(y, x); - o2::math_utils::BringTo02Pi(phi); + o2::math_utils::bringTo02Pi(phi); auto z = track.getZ(); auto crv = track.getCurvature(getBz()); @@ -699,7 +699,7 @@ void CookedTracker::Layer::init() auto xyz = c->getXYZGloRot(*mGeom); r += xyz.rho(); Float_t phi = xyz.Phi(); - o2::math_utils::BringTo02Pi(phi); + o2::math_utils::bringTo02Pi(phi); mPhi.push_back(phi); Int_t s = phi * kNSectors / k2PI; mSectors[s < kNSectors ? s : kNSectors - 1].emplace_back(i, c->getZ()); @@ -748,7 +748,7 @@ void CookedTracker::Layer::selectClusters(std::vector<Int_t>& selec, Float_t phi Float_t zMin = z - dz; Float_t zMax = z + dz; - o2::math_utils::BringTo02Pi(phi); + o2::math_utils::bringTo02Pi(phi); Float_t dphi = dy / mR; diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx index c3b310e3fde10..15895fa9b54f8 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/RecoGeomHelper.cxx @@ -39,9 +39,9 @@ void RecoGeomHelper::RecoLadder::updateLimits(const o2::math_utils::Point3D<floa { // update limits from the point in Global frame float phi = pntGlo.phi(); // -pi:pi range - o2::math_utils::BringTo02Pi(phi); // temporary bring to 0:2pi range - o2::math_utils::BringTo02Pi(phiRange.getMin()); - o2::math_utils::BringTo02Pi(phiRange.getMax()); + o2::math_utils::bringTo02Pi(phi); // temporary bring to 0:2pi range + o2::math_utils::bringTo02Pi(phiRange.getMin()); + o2::math_utils::bringTo02Pi(phiRange.getMax()); phiRange.update(phi); phiMean = phiRange.mean(); dphiH = 0.5 * phiRange.delta(); @@ -50,9 +50,9 @@ void RecoGeomHelper::RecoLadder::updateLimits(const o2::math_utils::Point3D<floa phiMean -= o2::constants::math::PI; dphiH = o2::constants::math::PI - dphiH; } - o2::math_utils::BringToPMPi(phiRange.getMin()); // -pi:pi range - o2::math_utils::BringToPMPi(phiRange.getMax()); - o2::math_utils::BringToPMPi(phiMean); + o2::math_utils::bringToPMPi(phiRange.getMin()); // -pi:pi range + o2::math_utils::bringToPMPi(phiRange.getMax()); + o2::math_utils::bringToPMPi(phiMean); // zRange.update(pntGlo.Z()); } @@ -115,7 +115,7 @@ void RecoGeomHelper::RecoLayer::init() auto& chip = ladder.chips.emplace_back(); chip.id = chipID; gm->getSensorXAlphaRefPlane(chipID, chip.xRef, chip.alp); - o2::math_utils::sincosf(chip.alp, chip.snAlp, chip.csAlp); + o2::math_utils::sincos(chip.alp, chip.snAlp, chip.csAlp); o2::math_utils::Point3D<float> edgeLoc(-dxH, 0.f, -dzH); auto edgeTra = gm->getMatrixT2L(chipID) ^ (edgeLoc); // edge in tracking frame @@ -136,8 +136,8 @@ void RecoGeomHelper::RecoLayer::init() // sort according to mean phi (in -pi:pi range!!!) std::sort(ladders.begin(), ladders.end(), [](auto& a, auto& b) { float pha = a.phiMean, phb = b.phiMean; - o2::math_utils::BringTo02Pi(pha); - o2::math_utils::BringTo02Pi(phb); + o2::math_utils::bringTo02Pi(pha); + o2::math_utils::bringTo02Pi(phb); return pha < phb; }); @@ -166,16 +166,16 @@ void RecoGeomHelper::RecoLayer::init() // find the radius of the edge at low phi float phi0 = std::atan2(lad.xyEdges.getY0(), lad.xyEdges.getX0()); float phi1 = std::atan2(lad.xyEdges.getY1(), lad.xyEdges.getX1()); - o2::math_utils::BringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa - o2::math_utils::BringTo02Pi(phi1); + o2::math_utils::bringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa + o2::math_utils::bringTo02Pi(phi1); float r2This = (phi0 < phi1 && phi1 - phi0 < o2::constants::math::PI) ? // pick R of lowest angle lad.xyEdges.getX0() * lad.xyEdges.getX0() + lad.xyEdges.getY0() * lad.xyEdges.getY0() : lad.xyEdges.getX1() * lad.xyEdges.getX1() + lad.xyEdges.getY1() * lad.xyEdges.getY1(); // phi0 = std::atan2(plad.xyEdges.getY0(), plad.xyEdges.getX0()); phi1 = std::atan2(plad.xyEdges.getY1(), plad.xyEdges.getX1()); - o2::math_utils::BringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa - o2::math_utils::BringTo02Pi(phi1); + o2::math_utils::bringTo02Pi(phi0); // we don't know a priori if edge0/1 corresponds to low/high phi or vice versa + o2::math_utils::bringTo02Pi(phi1); float r2Prev = (phi0 < phi1 && phi1 - phi0 < o2::constants::math::PI) ? // pick R of highest angle plad.xyEdges.getX1() * plad.xyEdges.getX1() + plad.xyEdges.getY1() * plad.xyEdges.getY1() : plad.xyEdges.getX0() * plad.xyEdges.getX0() + plad.xyEdges.getY0() * plad.xyEdges.getY0(); @@ -189,7 +189,7 @@ void RecoGeomHelper::RecoLayer::init() int laddId = 0; for (int i = 0; i < ndiv; i++) { float phi = (0.5 + i) * dphi; - o2::math_utils::BringToPMPi(phi); + o2::math_utils::bringToPMPi(phi); while (laddId < nLadders) { const auto& lad = ladders[laddId]; auto rel = lad.isPhiOutside(phi); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h index acdeba699af8a..8e8df9e9c7a74 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h @@ -47,7 +47,7 @@ GPUhdni() float computeTanDipAngle(float x1, float y1, float x2, float y2, float GPUhdi() float math_utils::calculatePhiCoordinate(const float xCoordinate, const float yCoordinate) { //return o2::gpu::CAMath::ATan2(-yCoordinate, -xCoordinate) + constants::math::Pi; - return o2::math_utils::FastATan2(-yCoordinate, -xCoordinate) + constants::math::Pi; + return o2::math_utils::fastATan2(-yCoordinate, -xCoordinate) + constants::math::Pi; } GPUhdi() float math_utils::calculateRCoordinate(const float xCoordinate, const float yCoordinate) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index dbb884d5205c1..e72c6c62eecfa 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -120,7 +120,7 @@ inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t l auto clsPoint2D = math_utils::Point2D<Float_t>(x_proj, y_proj); r_proj = clsPoint2D.R(); phi_proj = clsPoint2D.Phi(); - o2::math_utils::BringTo02PiGen(phi_proj); + o2::math_utils::bringTo02PiGen(phi_proj); binR_proj = constants::index_table::getRBinIndex(r_proj); binPhi_proj = constants::index_table::getPhiBinIndex(phi_proj); return; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx index 98e25f6926aad..5a81fba5d29a8 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx @@ -32,7 +32,7 @@ Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t auto clsPoint2D = math_utils::Point2D<Float_t>(x, y); rCoordinate = clsPoint2D.R(); phiCoordinate = clsPoint2D.Phi(); - o2::math_utils::BringTo02PiGen(phiCoordinate); + o2::math_utils::bringTo02PiGen(phiCoordinate); } Cluster::Cluster(const Int_t layerIndex, const Cluster& other) @@ -46,7 +46,7 @@ Cluster::Cluster(const Int_t layerIndex, const Cluster& other) auto clsPoint2D = math_utils::Point2D<Float_t>(other.getX(), other.getY()); rCoordinate = clsPoint2D.R(); phiCoordinate = clsPoint2D.Phi(); - o2::math_utils::BringTo02PiGen(phiCoordinate); + o2::math_utils::bringTo02PiGen(phiCoordinate); } } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index 77c96dd9aa5ef..4bc5cbb72a854 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -71,7 +71,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g auto clsPoint2D = math_utils::Point2D<Float_t>(gloXYZ.x(), gloXYZ.y()); Float_t rCoord = clsPoint2D.R(); Float_t phiCoord = clsPoint2D.Phi(); - o2::math_utils::BringTo02PiGen(phiCoord); + o2::math_utils::bringTo02PiGen(phiCoord); int rBinIndex = constants::index_table::getRBinIndex(rCoord); int phiBinIndex = constants::index_table::getPhiBinIndex(phiCoord); int binIndex = constants::index_table::getBinIndex(rBinIndex, phiBinIndex); diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index 831f44c963a9e..c5073c92a5de6 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -156,7 +156,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo const auto& clTOF = mTOFClustersArray[matchTOF.getTOFClIndex()]; //const int clTOFSec = (TMath::ATan2(-clTOF.getY(), -clTOF.getX()) + o2::constants::math::PI) * o2::constants::math::Rad2Deg * 0.05; // taken from TOF cluster class as there is no const getter for the sector const int clTOFSec = clTOF.getCount(); - const float clTOFAlpha = o2::math_utils::Sector2Angle(clTOFSec); + const float clTOFAlpha = o2::math_utils::sector2Angle(clTOFSec); const auto& trkTPC = mTPCTracksArray[matchITSTPC.getRefTPC()]; const auto& trkITS = mITSTracksArray[matchITSTPC.getRefITS()]; auto trkWork = trkITS.getParamOut(); @@ -180,7 +180,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo mCache[row].clAvailable = 1; mCache[row].clY = clTPCYZ[0]; mCache[row].clZ = clTPCYZ[1]; - mCache[row].clAngle = o2::math_utils::Sector2Angle(sector); + mCache[row].clAngle = o2::math_utils::sector2Angle(sector); } // first extrapolate through TPC and store track position at each pad row @@ -212,7 +212,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo return false; } //float ca, sa; - //o2::math_utils::sincosf(clTOFAlpha, sa, ca); + //o2::math_utils::sincos(clTOFAlpha, sa, ca); //float clTOFX = clTOF.getX() * ca + clTOF.getY() * sa; // cluster x in sector coordinate frame //std::array<float, 2> clTOFYZ{ -clTOF.getX() * sa + clTOF.getY() * ca, clTOF.getZ() }; // cluster y and z in sector coordinate frame float clTOFX = clTOF.getX(); @@ -274,7 +274,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo res.setZ(mCache[iRow].z[Int]); res.setPhi(mCache[iRow].phi[Int]); res.setTgl(mCache[iRow].tgl[Int]); - res.sec = o2::math_utils::Angle2Sector(mCache[iRow].clAngle); + res.sec = o2::math_utils::angle2Sector(mCache[iRow].clAngle); res.dRow = deltaRow; res.row = iRow; mClRes.push_back(std::move(res)); @@ -312,7 +312,7 @@ bool TrackInterpolation::extrapolateTrackITS(const o2::its::TrackITS& trkITS, co const auto& cl = trkTPC.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector, row); float x = 0, y = 0, z = 0; mFastTransform->TransformIdeal(sector, row, cl.getPad(), cl.getTime(), x, y, z, clusterTimeBinOffset); - if (!trk.rotate(o2::math_utils::Sector2Angle(sector))) { + if (!trk.rotate(o2::math_utils::sector2Angle(sector))) { return false; } if (!propagator->PropagateToXBxByBz(trk, x, o2::constants::physics::MassPionCharged, mMaxSnp, mMaxStep, mMatCorr)) { @@ -325,7 +325,7 @@ bool TrackInterpolation::extrapolateTrackITS(const o2::its::TrackITS& trkITS, co res.setZ(trk.getZ()); res.setPhi(trk.getSnp()); res.setTgl(trk.getTgl()); - res.sec = o2::math_utils::Angle2Sector(trk.getAlpha()); + res.sec = o2::math_utils::angle2Sector(trk.getAlpha()); res.dRow = row - rowPrev; res.row = row; rowPrev = row; diff --git a/Detectors/TPC/simulation/src/SpaceCharge.cxx b/Detectors/TPC/simulation/src/SpaceCharge.cxx index 16c80d3c8c97e..2020d258d2e59 100644 --- a/Detectors/TPC/simulation/src/SpaceCharge.cxx +++ b/Detectors/TPC/simulation/src/SpaceCharge.cxx @@ -196,7 +196,7 @@ float SpaceCharge::calculateLookupTables() matrixDriftRPhi = mMatrixIonDriftRPhiC[iphi].get(); matrixDriftR = mMatrixIonDriftRC[iphi].get(); } - int roc = iside == 0 ? o2::math_utils::Angle2Sector(phi) : o2::math_utils::Angle2Sector(phi) + 18; + int roc = iside == 0 ? o2::math_utils::angle2Sector(phi) : o2::math_utils::angle2Sector(phi) + 18; for (int ir = 0; ir < mNR; ++ir) { const float radius = static_cast<float>(mCoordR[ir]); /// TODO: what is the electric field stored in the LUTs at iz=0 and iz=mNZSlices-1 @@ -536,7 +536,7 @@ void SpaceCharge::propagateIons() double dz = 0.f; lookUpIonDrift->GetValue(rIon, phiIon, std::abs(zIon), dr, drphi, dz); float phiIonF = static_cast<float>(phiIon + (drphi / rIon)); - o2::math_utils::BringTo02PiGen(phiIonF); + o2::math_utils::bringTo02PiGen(phiIonF); rIon += dr; zIon += dz; @@ -582,8 +582,8 @@ void SpaceCharge::correctElectron(GlobalPosition3D& point) const float x[3] = {point.X(), point.Y(), point.Z()}; float dx[3] = {0.f, 0.f, 0.f}; float phi = point.phi(); - o2::math_utils::BringTo02PiGen(phi); - int roc = o2::math_utils::Angle2Sector(phi); + o2::math_utils::bringTo02PiGen(phi); + int roc = o2::math_utils::angle2Sector(phi); /// FIXME: which side when z==0? if (x[2] < 0) { roc += 18; @@ -600,8 +600,8 @@ void SpaceCharge::distortElectron(GlobalPosition3D& point) const const float x[3] = {point.X(), point.Y(), point.Z()}; float dx[3] = {0.f, 0.f, 0.f}; float phi = point.phi(); - o2::math_utils::BringTo02PiGen(phi); - int roc = o2::math_utils::Angle2Sector(phi); + o2::math_utils::bringTo02PiGen(phi); + int roc = o2::math_utils::angle2Sector(phi); /// FIXME: which side when z==0? if (x[2] < 0) { roc += 18; @@ -613,8 +613,8 @@ void SpaceCharge::distortElectron(GlobalPosition3D& point) const double SpaceCharge::getChargeDensity(Side side, const GlobalPosition3D& point) const { Float_t x[3] = {point.rho(), point.phi(), point.z()}; - o2::math_utils::BringTo02PiGen(x[1]); - const int roc = side == Side::A ? o2::math_utils::Angle2Sector(x[1]) : o2::math_utils::Angle2Sector(x[1]) + 18; + o2::math_utils::bringTo02PiGen(x[1]); + const int roc = side == Side::A ? o2::math_utils::angle2Sector(x[1]) : o2::math_utils::angle2Sector(x[1]) + 18; return mLookUpTableCalculator.GetChargeCylAC(x, roc); } diff --git a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx index f4ed7087cd25b..55afcfc8b4b7d 100644 --- a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx @@ -708,7 +708,7 @@ void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp) double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t; x = Sqrt(xp * xp + yp * yp); alp = ATan2(yp, xp); - o2::math_utils::BringTo02Pi(alp); + o2::math_utils::bringTo02Pi(alp); } //__________________________________________________________________________ diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx index 60b5c6a90f969..3e35b82c2f9e2 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx @@ -709,7 +709,7 @@ void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp) double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t; x = Sqrt(xp * xp + yp * yp); alp = ATan2(yp, xp); - o2::math_utils::BringTo02Pi(alp); + o2::math_utils::bringTo02Pi(alp); } //__________________________________________________________________________ diff --git a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h index 32ebc33021aa6..3353526becf93 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h @@ -260,16 +260,16 @@ class DCAFitterN int mCurHyp = 0; int mCrossIDCur = 0; int mCrossIDAlt = -1; - bool mAllowAltPreference = true; // if the fit converges to alternative PCA seed, abandon the current one - bool mUseAbsDCA = false; // use abs. distance minimization rather than chi2 - bool mPropagateToPCA = true; // create tracks version propagated to PCA - int mMaxIter = 20; // max number of iterations - float mBz = 0; // bz field, to be set by user - float mMaxR2 = 200. * 200.; // reject PCA's above this radius - float mMaxDZIni = 4.; // reject (if>0) PCA candidate if tracks DZ exceeds threshold - float mMinParamChange = 1e-3; // stop iterations if largest change of any X is smaller than this - float mMinRelChi2Change = 0.9; // stop iterations is chi2/chi2old > this - float mMaxChi2 = 100; // abs cut on chi2 or abs distance + bool mAllowAltPreference = true; // if the fit converges to alternative PCA seed, abandon the current one + bool mUseAbsDCA = false; // use abs. distance minimization rather than chi2 + bool mPropagateToPCA = true; // create tracks version propagated to PCA + int mMaxIter = 20; // max number of iterations + float mBz = 0; // bz field, to be set by user + float mMaxR2 = 200. * 200.; // reject PCA's above this radius + float mMaxDZIni = 4.; // reject (if>0) PCA candidate if tracks DZ exceeds threshold + float mMinParamChange = 1e-3; // stop iterations if largest change of any X is smaller than this + float mMinRelChi2Change = 0.9; // stop iterations is chi2/chi2old > this + float mMaxChi2 = 100; // abs cut on chi2 or abs distance float mMaxDist2ToMergeSeeds = 1.; // merge 2 seeds to their average if their distance^2 is below the threshold ClassDefNV(DCAFitterN, 1); @@ -288,7 +288,7 @@ int DCAFitterN<N, Args...>::process(const Tr&... args) mTrAux[i].set(*mOrigTrPtr[i], mBz); } if (!mCrossings.set(mTrAux[0], *mOrigTrPtr[0], mTrAux[1], *mOrigTrPtr[1])) { // even for N>2 it should be enough to test just 1 loop - return 0; // no crossing + return 0; // no crossing } if (mUseAbsDCA) { calcRMatrices(); // needed for fast residuals derivatives calculation in case of abs. distance minimization @@ -583,12 +583,12 @@ void DCAFitterN<N, Args...>::calcPCANoErr() { // calculate point of closest approach for N prongs w/o errors auto& pca = mPCA[mCurHyp]; - o2::math_utils::rotateZ(mTrPos[mCurHyp][N - 1][0], mTrPos[mCurHyp][N - 1][1], pca[0], pca[1], mTrAux[N - 1].s, mTrAux[N - 1].c); + o2::math_utils::rotateZd(mTrPos[mCurHyp][N - 1][0], mTrPos[mCurHyp][N - 1][1], pca[0], pca[1], mTrAux[N - 1].s, mTrAux[N - 1].c); //RRRR mTrAux[N-1].loc2glo(mTrPos[mCurHyp][N-1][0], mTrPos[mCurHyp][N-1][1], pca[0], pca[1] ); pca[2] = mTrPos[mCurHyp][N - 1][2]; for (int i = N - 1; i--;) { double x, y; - o2::math_utils::rotateZ(mTrPos[mCurHyp][i][0], mTrPos[mCurHyp][i][1], x, y, mTrAux[i].s, mTrAux[i].c); + o2::math_utils::rotateZd(mTrPos[mCurHyp][i][0], mTrPos[mCurHyp][i][1], x, y, mTrAux[i].s, mTrAux[i].c); //RRRR mTrAux[i].loc2glo(mTrPos[mCurHyp][i][0], mTrPos[mCurHyp][i][1], x, y ); pca[0] += x; pca[1] += y; @@ -620,7 +620,7 @@ void DCAFitterN<N, Args...>::calcTrackResiduals() for (int i = N; i--;) { mTrRes[mCurHyp][i] = mTrPos[mCurHyp][i]; vtxLoc = mPCA[mCurHyp]; - o2::math_utils::rotateZInv(vtxLoc[0], vtxLoc[1], vtxLoc[0], vtxLoc[1], mTrAux[i].s, mTrAux[i].c); // glo->loc + o2::math_utils::rotateZInvd(vtxLoc[0], vtxLoc[1], vtxLoc[0], vtxLoc[1], mTrAux[i].s, mTrAux[i].c); // glo->loc mTrRes[mCurHyp][i] -= vtxLoc; } } @@ -742,7 +742,7 @@ bool DCAFitterN<N, Args...>::minimizeChi2() if (!mCandTr[mCurHyp][i].propagateTo(x, mBz)) { return false; } - setTrackPos(mTrPos[mCurHyp][i], mCandTr[mCurHyp][i]); // prepare positions + setTrackPos(mTrPos[mCurHyp][i], mCandTr[mCurHyp][i]); // prepare positions mTrcEInv[mCurHyp][i].set(mCandTr[mCurHyp][i], XerrFactor); // prepare inverse cov.matrices at starting point } diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h index 91500022d22f7..a9f022aac7b53 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h @@ -129,7 +129,7 @@ struct TrackVF { TrackVF(const o2::track::TrackParCov& src, const TimeEst& t_est, uint32_t _entry, uint8_t _srcID) : x(src.getX()), y(src.getY()), z(src.getZ()), tgL(src.getTgl()), tgP(src.getSnp() / std::sqrt(1. - src.getSnp()) * (1. + src.getSnp())), timeEst(t_est), entry(_entry), srcID(_srcID) { - o2::math_utils::sincosf(src.getAlpha(), sinAlp, cosAlp); + o2::math_utils::sincos(src.getAlpha(), sinAlp, cosAlp); auto det = src.getSigmaY2() * src.getSigmaZ2() - src.getSigmaZY() * src.getSigmaZY(); auto detI = 1. / det; sig2YI = src.getSigmaZ2() * detI; diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index 3e293c4228fd4..0dd30f0ded5aa 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -417,13 +417,9 @@ TimeEst PVertexer::timeEstimate(const VertexingInput& input) const test.add(timeT.getTimeStamp(), trErr2I); } } - if (test.wsum > 0) { - float t = 0., te2 = 0.; - test.getMeanRMS2(t, te2); - return {t, te2}; - } else { - return {0., 0.}; - } + + const auto [t, te2] = test.getMeanRMS2<float>(); + return {t, te2}; } //___________________________________________________________________ @@ -481,11 +477,9 @@ void PVertexer::createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC) mStatTErr.add(tvf.timeEst.getTimeStampError()); } // TODO: try to narrow timestamps using tof times - float zerrMean, zerrRMS; - mStatZErr.getMeanRMS2(zerrMean, zerrRMS); + auto [zerrMean, zerrRMS] = mStatZErr.getMeanRMS2<float>(); - float terrMean, terrRMS; - mStatTErr.getMeanRMS2(terrMean, terrRMS); + auto [terrMean, terrRMS] = mStatTErr.getMeanRMS2<float>(); if (mTracksPool.empty()) { return; diff --git a/Detectors/Vertexing/test/testDCAFitterN.cxx b/Detectors/Vertexing/test/testDCAFitterN.cxx index 2b23e2c7facbb..add77c641f0f6 100644 --- a/Detectors/Vertexing/test/testDCAFitterN.cxx +++ b/Detectors/Vertexing/test/testDCAFitterN.cxx @@ -100,7 +100,7 @@ TLorentzVector generate(Vec3D& vtx, std::vector<o2::track::TrackParCov>& vctr, f dt->GetXYZT(p); float s, c, x; std::array<float, 5> params; - o2::math_utils::sincosf(dt->Phi(), s, c); + o2::math_utils::sincos(dt->Phi(), s, c); o2::math_utils::rotateZInv(vtx[0], vtx[1], x, params[0], s, c); params[1] = vtx[2]; diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 592c33a4b868e..cf62d2df8aab6 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -102,14 +102,14 @@ DECLARE_SOA_DYNAMIC_COLUMN(Charge, charge, [](float signed1Pt) -> short { return DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float signed1Pt, float snp, float alpha) -> float { auto pt = 1.f / std::abs(signed1Pt); float cs, sn; - math_utils::sincosf(alpha, sn, cs); + math_utils::sincos(alpha, sn, cs); auto r = std::sqrt((1.f - snp) * (1.f + snp)); return pt * (r * cs - snp * sn); }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float signed1Pt, float snp, float alpha) -> float { auto pt = 1.f / std::abs(signed1Pt); float cs, sn; - math_utils::sincosf(alpha, sn, cs); + math_utils::sincos(alpha, sn, cs); auto r = std::sqrt((1.f - snp) * (1.f + snp)); return pt * (snp * cs + r * sn); }); diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 2720a741c021a..40d7ac94f2310 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -65,6 +65,7 @@ class GPUCommonMath GPUhdni() static void SinCos(double x, double& s, double& c); GPUd() static float Tan(float x); GPUhdni() static float Copysign(float x, float y); + GPUhdni() static double Copysign(double x, double y); GPUd() static float TwoPi() { return 6.28319f; } GPUd() static float Pi() { return 3.1415926535897f; } GPUd() static int Nint(float x); @@ -382,6 +383,20 @@ GPUhdi() float GPUCommonMath::Copysign(float x, float y) #endif // GPUCA_GPUCODE } +GPUhdi() double GPUCommonMath::Copysign(double x, double y) +{ +#if defined(__OPENCLCPP__) + return copysign(x, y); +#elif defined(GPUCA_GPUCODE) && !defined(__OPENCL__) + return copysignf(x, y); +#elif defined(__cplusplus) && __cplusplus >= 201103L + return std::copysign(x, y); +#else + x = GPUCommonMath::Abs(x); + return (y >= 0) ? x : -x; +#endif // GPUCA_GPUCODE +} + template <class S, class T> GPUdi() unsigned int GPUCommonMath::AtomicExchInt(S* addr, T val) { From 53ccf9c717587c465b093d4b465a0833024d3844 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Tue, 13 Oct 2020 18:51:27 +0200 Subject: [PATCH 1034/1751] [math_utils] Turn Rotation2D into template class Turns `Rotation2D` into a template class with aliases for single and double precision floating point implementations. --- .../MathUtils/include/MathUtils/Cartesian.h | 28 +++++++++++++------ Common/MathUtils/src/Cartesian.cxx | 14 ++++++++-- Common/MathUtils/src/MathUtilsLinkDef.h | 3 +- .../DetMatrixCache.h | 4 +-- .../Detectors/Common/src/DetMatrixCache.cxx | 2 +- .../src/DetectorsCommonDataFormatsLinkDef.h | 2 +- .../TrackParametrization.h | 4 +-- 7 files changed, 39 insertions(+), 18 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Cartesian.h b/Common/MathUtils/include/MathUtils/Cartesian.h index 91e3b0732e872..8166c4166d283 100644 --- a/Common/MathUtils/include/MathUtils/Cartesian.h +++ b/Common/MathUtils/include/MathUtils/Cartesian.h @@ -54,32 +54,37 @@ struct TransformType { static constexpr int T2GRot = 3; }; /// transformation types +template <typename value_T> class Rotation2D { // // class to perform rotation of 3D (around Z) and 2D points public: + using value_t = value_T; + Rotation2D() = default; - Rotation2D(float cs, float sn) : mCos(cs), mSin(sn) {} - Rotation2D(float phiZ) : mCos(cos(phiZ)), mSin(sin(phiZ)) {} + Rotation2D(value_t cs, value_t sn) : mCos(cs), mSin(sn) {} + Rotation2D(value_t phiZ) : mCos(cos(phiZ)), mSin(sin(phiZ)) {} ~Rotation2D() = default; Rotation2D(const Rotation2D& src) = default; + Rotation2D(Rotation2D&& src) = default; Rotation2D& operator=(const Rotation2D& src) = default; + Rotation2D& operator=(Rotation2D&& src) = default; - void set(float phiZ) + void set(value_t phiZ) { mCos = cos(phiZ); mSin = sin(phiZ); } - void set(float cs, float sn) + void set(value_t cs, value_t sn) { mCos = cs; mSin = sn; } - void getComponents(float& cs, float& sn) const + void getComponents(value_t& cs, value_t& sn) const { cs = mCos; sn = mSin; @@ -134,12 +139,15 @@ class Rotation2D } private: - float mCos = 1.f; ///< cos of rotation angle - float mSin = 0.f; ///< sin of rotation angle + value_t mCos = 1; ///< cos of rotation angle + value_t mSin = 0; ///< sin of rotation angle - ClassDefNV(Rotation2D, 1); + ClassDefNV(Rotation2D, 2); }; +using Rotation2Df_t = Rotation2D<float>; +using Rotation2Dd_t = Rotation2D<double>; + class Transform3D : public ROOT::Math::Transform3D { // @@ -236,7 +244,9 @@ class Transform3D : public ROOT::Math::Transform3D } // namespace math_utils } // namespace o2 -std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2D& t); +std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2Df_t& t); + +std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2Dd_t& t); namespace std { diff --git a/Common/MathUtils/src/Cartesian.cxx b/Common/MathUtils/src/Cartesian.cxx index c51daeb2f0474..fc6e950f115bb 100644 --- a/Common/MathUtils/src/Cartesian.cxx +++ b/Common/MathUtils/src/Cartesian.cxx @@ -12,7 +12,8 @@ #include "MathUtils/Cartesian.h" ClassImp(o2::math_utils::Transform3D); -ClassImp(o2::math_utils::Rotation2D); +ClassImp(o2::math_utils::Rotation2Df_t); +ClassImp(o2::math_utils::Rotation2Dd_t); namespace o2 { @@ -52,10 +53,19 @@ void Transform3D::print() const } // namespace o2 //_________________________________________________ -std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2D& t) +std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2Df_t& t) { float cs, sn; t.getComponents(cs, sn); os << "cos: " << cs << " sin: " << sn; return os; } + +//_________________________________________________ +std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2Dd_t& t) +{ + double cs, sn; + t.getComponents(cs, sn); + os << "cos: " << cs << " sin: " << sn; + return os; +} diff --git a/Common/MathUtils/src/MathUtilsLinkDef.h b/Common/MathUtils/src/MathUtilsLinkDef.h index b3c71a810cecc..122741a0b4c86 100644 --- a/Common/MathUtils/src/MathUtilsLinkDef.h +++ b/Common/MathUtils/src/MathUtilsLinkDef.h @@ -30,7 +30,8 @@ #pragma link C++ function o2::math_utils::math_base::getStatisticsData < short>; #pragma link C++ class o2::math_utils::Transform3D + ; -#pragma link C++ class o2::math_utils::Rotation2D + ; +#pragma link C++ class o2::math_utils::Rotation2Df_t + ; +#pragma link C++ class o2::math_utils::Rotation2Dd_t + ; #pragma link C++ class o2::math_utils::CachingTF1 + ; #pragma link C++ class o2::math_utils::CircleXYf_t + ; diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h index ab946fa0ea79c..38b10f1febcf3 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetMatrixCache.h @@ -74,7 +74,7 @@ class DetMatrixCache { public: typedef o2::math_utils::Transform3D Mat3D; - typedef o2::math_utils::Rotation2D Rot2D; + typedef o2::math_utils::Rotation2Df_t Rot2D; DetMatrixCache() = default; DetMatrixCache(const o2::detectors::DetID& id) : mDetID(id) {} @@ -130,7 +130,7 @@ class DetMatrixCacheIndirect : private DetMatrixCache { public: typedef o2::math_utils::Transform3D Mat3D; - typedef o2::math_utils::Rotation2D Rot2D; + typedef o2::math_utils::Rotation2Df_t Rot2D; DetMatrixCacheIndirect() = default; DetMatrixCacheIndirect(const o2::detectors::DetID& id) : DetMatrixCache(id) {} diff --git a/DataFormats/Detectors/Common/src/DetMatrixCache.cxx b/DataFormats/Detectors/Common/src/DetMatrixCache.cxx index 7c1e4dc53fde8..387603bc74160 100644 --- a/DataFormats/Detectors/Common/src/DetMatrixCache.cxx +++ b/DataFormats/Detectors/Common/src/DetMatrixCache.cxx @@ -15,7 +15,7 @@ using namespace o2::detectors; ClassImp(o2::detectors::MatrixCache<o2::math_utils::Transform3D>); -ClassImp(o2::detectors::MatrixCache<o2::math_utils::Rotation2D>); +ClassImp(o2::detectors::MatrixCache<o2::math_utils::Rotation2Df_t>); ClassImp(o2::detectors::DetMatrixCache); //_______________________________________________________ diff --git a/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h b/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h index 4eb0b776ee4dc..019a2bca9499f 100644 --- a/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h +++ b/DataFormats/Detectors/Common/src/DetectorsCommonDataFormatsLinkDef.h @@ -17,7 +17,7 @@ #pragma link C++ class o2::detectors::DetID + ; #pragma link C++ class o2::detectors::AlignParam + ; #pragma link C++ class o2::detectors::MatrixCache < o2::math_utils::Transform3D> + ; -#pragma link C++ class o2::detectors::MatrixCache < o2::math_utils::Rotation2D> + ; +#pragma link C++ class o2::detectors::MatrixCache < o2::math_utils::Rotation2Df_t> + ; #pragma link C++ class o2::detectors::DetMatrixCache + ; #pragma link C++ class o2::detectors::DetMatrixCacheIndirect + ; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index aff79675760c9..9ed5e084846e8 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -571,7 +571,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu template <typename value_T> inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGlo() const { - return math_utils::Rotation2D(getAlpha())(math_utils::Point3D<value_t>(getX(), getY(), getZ())); + return math_utils::Rotation2D<value_t>(getAlpha())(math_utils::Point3D<value_t>(getX(), getY(), getZ())); } #endif @@ -596,7 +596,7 @@ inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> Trac //---------------------------------------------------------------- value_t y = 0.f, z = 0.f; ok = getYZAt(xk, b, y, z); - return ok ? math_utils::Rotation2D(getAlpha())(math_utils::Point3D<value_t>(xk, y, z)) : math_utils::Point3D<value_t>(); + return ok ? math_utils::Rotation2D<value_t>(getAlpha())(math_utils::Point3D<value_t>(xk, y, z)) : math_utils::Point3D<value_t>(); } #endif From 94494f275ec90f4cfe290b89ac5b719f68e77ec1 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Thu, 15 Oct 2020 16:25:57 +0200 Subject: [PATCH 1035/1751] [math_utils] MathBase renaming and ns change Change namespace of `MathBase` to `o2::math_utils` and rename `MathBase.h` to `fit.h`. No changes to functionality. Change affected code as well. --- Common/MathUtils/CMakeLists.txt | 7 ++---- .../MathUtils/include/MathUtils/Primitive2D.h | 10 +++++++-- .../include/MathUtils/{ => detail}/Bracket.h | 3 +++ .../include/MathUtils/{MathBase.h => fit.h} | 3 --- Common/MathUtils/src/MathBase.cxx | 16 -------------- Common/MathUtils/src/MathUtilsLinkDef.h | 19 ++++++++-------- Common/MathUtils/src/RandomRing.cxx | 16 -------------- .../include/GlobalTracking/MatchTPCITS.h | 12 +++++----- .../ITSReconstruction/RecoGeomHelper.h | 4 ++-- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 4 ++-- .../calibration/src/LHCClockCalibrator.cxx | 4 ++-- .../calibration/src/TOFChannelCalibrator.cxx | 4 ++-- .../SpacePoints/src/TrackResiduals.cxx | 22 +++++++++---------- .../include/TPCCalibration/FastHisto.h | 10 ++++----- .../TPC/calibration/src/CalibPedestal.cxx | 10 ++++----- Detectors/TPC/calibration/src/CalibPulser.cxx | 6 ++--- .../TPC/calibration/src/CalibTreeDump.cxx | 4 ++-- .../DetectorsVertexing/VertexTrackMatcher.h | 4 ++-- 18 files changed, 64 insertions(+), 94 deletions(-) rename Common/MathUtils/include/MathUtils/{ => detail}/Bracket.h (99%) rename Common/MathUtils/include/MathUtils/{MathBase.h => fit.h} (99%) delete mode 100644 Common/MathUtils/src/MathBase.cxx delete mode 100644 Common/MathUtils/src/RandomRing.cxx diff --git a/Common/MathUtils/CMakeLists.txt b/Common/MathUtils/CMakeLists.txt index 090fe2abeb7c2..25b369097b408 100644 --- a/Common/MathUtils/CMakeLists.txt +++ b/Common/MathUtils/CMakeLists.txt @@ -14,8 +14,6 @@ o2_add_library( src/Cartesian.cxx src/Chebyshev3D.cxx src/Chebyshev3DCalc.cxx - src/MathBase.cxx - src/RandomRing.cxx PUBLIC_LINK_LIBRARIES ROOT::Hist FairRoot::Base @@ -30,12 +28,11 @@ o2_target_root_dictionary( HEADERS include/MathUtils/Utils.h include/MathUtils/Chebyshev3D.h include/MathUtils/Chebyshev3DCalc.h - include/MathUtils/MathBase.h + include/MathUtils/fit.h include/MathUtils/Cartesian.h include/MathUtils/CachingTF1.h include/MathUtils/RandomRing.h - include/MathUtils/Primitive2D.h - include/MathUtils/Bracket.h) + include/MathUtils/Primitive2D.h) o2_add_test( CachingTF1 diff --git a/Common/MathUtils/include/MathUtils/Primitive2D.h b/Common/MathUtils/include/MathUtils/Primitive2D.h index 120f2d5cdf266..1d69fda1f8710 100644 --- a/Common/MathUtils/include/MathUtils/Primitive2D.h +++ b/Common/MathUtils/include/MathUtils/Primitive2D.h @@ -9,8 +9,8 @@ // or submit itself to any jurisdiction. /// \file Primitive2D.h -/// \brief Declarations of 2D primitives: straight line (XY interval) and circle -/// \author ruben.shahoyan@cern.ch +/// \brief Declarations of 2D primitives +/// \author ruben.shahoyan@cern.ch michael.lettrich@cern.ch #ifndef ALICEO2_COMMON_MATH_PRIMITIVE2D_H #define ALICEO2_COMMON_MATH_PRIMITIVE2D_H @@ -18,6 +18,7 @@ #include "GPUCommonRtypes.h" #include "MathUtils/detail/CircleXY.h" #include "MathUtils/detail/IntervalXY.h" +#include "MathUtils/detail/Bracket.h" namespace o2 { @@ -33,6 +34,11 @@ using IntervalXY = detail::IntervalXY<T>; using IntervalXYf_t = detail::IntervalXY<float>; using IntervalXYd_t = detail::IntervalXY<double>; +template <typename T> +using Bracket = detail::Bracket<T>; +using Bracketf_t = detail::Bracket<float>; +using Bracketd_t = detail::Bracket<double>; + } // namespace math_utils } // namespace o2 diff --git a/Common/MathUtils/include/MathUtils/Bracket.h b/Common/MathUtils/include/MathUtils/detail/Bracket.h similarity index 99% rename from Common/MathUtils/include/MathUtils/Bracket.h rename to Common/MathUtils/include/MathUtils/detail/Bracket.h index f60fb987524ea..2cae7c61e2c7d 100644 --- a/Common/MathUtils/include/MathUtils/Bracket.h +++ b/Common/MathUtils/include/MathUtils/detail/Bracket.h @@ -21,6 +21,8 @@ namespace o2 { namespace math_utils { +namespace detail +{ template <typename T = float> class Bracket @@ -199,6 +201,7 @@ inline typename Bracket<T>::Relation Bracket<T>::isOutside(T t, T tErr) const return t + tErr < mMin ? Below : (t - tErr > mMax ? Above : Inside); } +} // namespace detail } // namespace math_utils } // namespace o2 diff --git a/Common/MathUtils/include/MathUtils/MathBase.h b/Common/MathUtils/include/MathUtils/fit.h similarity index 99% rename from Common/MathUtils/include/MathUtils/MathBase.h rename to Common/MathUtils/include/MathUtils/fit.h index 16d7d46b2b99c..ea7cc626ba0af 100644 --- a/Common/MathUtils/include/MathUtils/MathBase.h +++ b/Common/MathUtils/include/MathUtils/fit.h @@ -39,8 +39,6 @@ namespace o2 { namespace math_utils { -namespace math_base -{ /// fit 1D array of histogrammed data with generic root function /// /// The code was extracted out of ROOT to be able to do fitting on an array with histogrammed data @@ -528,7 +526,6 @@ bool LTMUnbinnedSig(const std::vector<T>& data, std::vector<size_t>& index, std: params[4] = params[3] / std::sqrt(2.0); // error on RMS return true; } -} // namespace math_base } // namespace math_utils } // namespace o2 #endif diff --git a/Common/MathUtils/src/MathBase.cxx b/Common/MathUtils/src/MathBase.cxx deleted file mode 100644 index 29818ee3f0380..0000000000000 --- a/Common/MathUtils/src/MathBase.cxx +++ /dev/null @@ -1,16 +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. - -/// \file MathBase.cxx -/// \author Jens Wiechula, Jens.Wiechula@ikf.uni-frankfurt.de - -#include "MathUtils/MathBase.h" - -using namespace o2::math_utils::math_base; diff --git a/Common/MathUtils/src/MathUtilsLinkDef.h b/Common/MathUtils/src/MathUtilsLinkDef.h index 122741a0b4c86..59f6deb11b8e0 100644 --- a/Common/MathUtils/src/MathUtilsLinkDef.h +++ b/Common/MathUtils/src/MathUtilsLinkDef.h @@ -17,17 +17,15 @@ #pragma link C++ class o2::math_utils::Chebyshev3D + ; #pragma link C++ class o2::math_utils::Chebyshev3DCalc + ; -#pragma link C++ namespace o2::math_utils::math_base; +#pragma link C++ function o2::math_utils::fit < float>; +#pragma link C++ function o2::math_utils::fit < double>; -#pragma link C++ function o2::math_utils::math_base::fit < float>; -#pragma link C++ function o2::math_utils::math_base::fit < double>; +#pragma link C++ function o2::math_utils::fitGaus < float>; +#pragma link C++ function o2::math_utils::fitGaus < double>; -#pragma link C++ function o2::math_utils::math_base::fitGaus < float>; -#pragma link C++ function o2::math_utils::math_base::fitGaus < double>; - -#pragma link C++ function o2::math_utils::math_base::getStatisticsData < float>; -#pragma link C++ function o2::math_utils::math_base::getStatisticsData < double>; -#pragma link C++ function o2::math_utils::math_base::getStatisticsData < short>; +#pragma link C++ function o2::math_utils::getStatisticsData < float>; +#pragma link C++ function o2::math_utils::getStatisticsData < double>; +#pragma link C++ function o2::math_utils::getStatisticsData < short>; #pragma link C++ class o2::math_utils::Transform3D + ; #pragma link C++ class o2::math_utils::Rotation2Df_t + ; @@ -38,6 +36,7 @@ #pragma link C++ class o2::math_utils::CircleXYd_t + ; #pragma link C++ class o2::math_utils::IntervalXYf_t + ; #pragma link C++ class o2::math_utils::IntervalXYd_t + ; -#pragma link C++ class o2::math_utils::Bracket < float> + ; +#pragma link C++ class o2::math_utils::Bracketf_t + ; +#pragma link C++ class o2::math_utils::Bracketd_t + ; #endif diff --git a/Common/MathUtils/src/RandomRing.cxx b/Common/MathUtils/src/RandomRing.cxx deleted file mode 100644 index d30476e781bdc..0000000000000 --- a/Common/MathUtils/src/RandomRing.cxx +++ /dev/null @@ -1,16 +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. - -/// -/// @file RandomRing.cxx -/// @author Jens Wiechula, Jens.Wiechula@cern.ch -/// - -#include "MathUtils/RandomRing.h" diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index dc89b302987c5..4adcd9032cbb5 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -30,7 +30,7 @@ #include "DetectorsBase/Propagator.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/TrackTPCITS.h" -#include "MathUtils/Bracket.h" +#include "MathUtils/Primitive2D.h" #include "CommonDataFormat/EvIndex.h" #include "CommonDataFormat/InteractionRecord.h" #include "CommonDataFormat/RangeReference.h" @@ -101,11 +101,11 @@ enum TrackRejFlag : int { ///< TPC track parameters propagated to reference X, with time bracket and index of ///< original track in the currently loaded TPC reco output struct TrackLocTPC : public o2::track::TrackParCov { - o2::math_utils::Bracket<float> timeBins; ///< bracketing time-bins - int sourceID = 0; ///< track origin id - float zMin = 0; // min possible Z of this track - float zMax = 0; // max possible Z of this track - int matchID = MinusOne; ///< entry (non if MinusOne) of its matchTPC struct in the mMatchesTPC + o2::math_utils::Bracketf_t timeBins; ///< bracketing time-bins + int sourceID = 0; ///< track origin id + float zMin = 0; // min possible Z of this track + float zMax = 0; // max possible Z of this track + int matchID = MinusOne; ///< entry (non if MinusOne) of its matchTPC struct in the mMatchesTPC TrackLocTPC(const o2::track::TrackParCov& src, int tid) : o2::track::TrackParCov(src), sourceID(tid) {} TrackLocTPC() = default; ClassDefNV(TrackLocTPC, 1); diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h index ebb3abc109e87..5e927df91c1e1 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h +++ b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/RecoGeomHelper.h @@ -22,7 +22,7 @@ #include "MathUtils/Utils.h" #include "MathUtils/Primitive2D.h" #include "CommonConstants/MathConstants.h" -#include "MathUtils/Bracket.h" +#include "MathUtils/Primitive2D.h" #include "ITSMFTReconstruction/ChipMappingITS.h" #include "ITSMFTBase/SegmentationAlpide.h" @@ -32,7 +32,7 @@ namespace its { struct RecoGeomHelper { // - using BracketF = o2::math_utils::Bracket<float>; + using BracketF = o2::math_utils::Bracketf_t; using Vec2D = o2::math_utils::IntervalXYf_t; enum Relation : int { Below = -1, diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index c8775497b051d..cc276aa9b0ee9 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -26,10 +26,10 @@ #include <TF1.h> #include <TF2.h> #include "CommonConstants/MathConstants.h" -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "MathUtils/Utils.h" -using o2::math_utils::math_base::fitGaus; +using o2::math_utils::fitGaus; namespace o2 { diff --git a/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx b/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx index a450afd6ce6a1..6313a4aff417c 100644 --- a/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx +++ b/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx @@ -10,7 +10,7 @@ #include "TOFCalibration/LHCClockCalibrator.h" #include "Framework/Logger.h" -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "CommonUtils/MemFileHelper.h" #include "CCDB/CcdbApi.h" #include "DetectorsCalibration/Utils.h" @@ -21,7 +21,7 @@ namespace tof { using Slot = o2::calibration::TimeSlot<o2::tof::LHCClockDataHisto>; -using o2::math_utils::math_base::fitGaus; +using o2::math_utils::fitGaus; using LHCphase = o2::dataformats::CalibLHCphaseTOF; using clbUtils = o2::calibration::Utils; diff --git a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx index 9e5ea78f1df8e..4c84dbc6d012b 100644 --- a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx +++ b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx @@ -10,7 +10,7 @@ #include "TOFCalibration/TOFChannelCalibrator.h" #include "Framework/Logger.h" -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "CommonUtils/MemFileHelper.h" #include "CCDB/CcdbApi.h" #include "DetectorsCalibration/Utils.h" @@ -31,7 +31,7 @@ using Slot = o2::calibration::TimeSlot<o2::tof::TOFChannelData>; using TimeSlewing = o2::dataformats::CalibTimeSlewingParamTOF; using clbUtils = o2::calibration::Utils; using boost::histogram::indexed; -using o2::math_utils::math_base::fitGaus; +using o2::math_utils::fitGaus; //using boost::histogram::algorithm; // not sure why it does not work... //_____________________________________________ diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx index 160340066159f..76d23c027831d 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackResiduals.cxx @@ -18,7 +18,7 @@ #include "SpacePoints/TrackResiduals.h" #include "CommonConstants/MathConstants.h" -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "TMatrixDSym.h" #include "TDecompChol.h" @@ -892,7 +892,7 @@ void TrackResiduals::processSectorResiduals(int iSec) #endif // sort in voxel increasing order - o2::math_utils::math_base::SortData(binData, binIndices); + o2::math_utils::SortData(binData, binIndices); if (mPrintMem) { printMem(); } @@ -1007,7 +1007,7 @@ void TrackResiduals::processVoxelResiduals(std::vector<float>& dy, std::vector<f std::array<float, 7> zResults; resVox.flags = 0; std::vector<size_t> indices(dz.size()); - if (!o2::math_utils::math_base::LTMUnbinned(dz, indices, zResults, mLTMCut)) { + if (!o2::math_utils::LTMUnbinned(dz, indices, zResults, mLTMCut)) { LOG(debug) << "failed trimming input array for voxel " << getGlbVoxBin(resVox.bvox); return; } @@ -1713,12 +1713,12 @@ float TrackResiduals::fitPoly1Robust(std::vector<float>& x, std::vector<float>& } std::array<float, 7> yResults; std::vector<size_t> indY(nPoints); - if (!o2::math_utils::math_base::LTMUnbinned(y, indY, yResults, cutLTM)) { + if (!o2::math_utils::LTMUnbinned(y, indY, yResults, cutLTM)) { return -1; } // rearrange used events in increasing order - o2::math_utils::math_base::Reorder(y, indY); - o2::math_utils::math_base::Reorder(x, indY); + o2::math_utils::Reorder(y, indY); + o2::math_utils::Reorder(x, indY); // // 1st fit to get crude slope int nPointsUsed = std::lrint(yResults[0]); @@ -1732,15 +1732,15 @@ float TrackResiduals::fitPoly1Robust(std::vector<float>& x, std::vector<float>& ycm[i] = y[i] - (a + b * x[i]); } std::vector<size_t> indices(nPoints); - o2::math_utils::math_base::SortData(ycm, indices); - o2::math_utils::math_base::Reorder(ycm, indices); - o2::math_utils::math_base::Reorder(y, indices); - o2::math_utils::math_base::Reorder(x, indices); + o2::math_utils::SortData(ycm, indices); + o2::math_utils::Reorder(ycm, indices); + o2::math_utils::Reorder(y, indices); + o2::math_utils::Reorder(x, indices); // // robust estimate of sigma after crude slope correction float sigMAD = getMAD2Sigma({ycm.begin() + vecOffset, ycm.begin() + vecOffset + nPointsUsed}); // find LTM estimate matching to sigMAD, keaping at least given fraction - if (!o2::math_utils::math_base::LTMUnbinnedSig(ycm, indY, yResults, mMinFracLTM, sigMAD, true)) { + if (!o2::math_utils::LTMUnbinnedSig(ycm, indY, yResults, mMinFracLTM, sigMAD, true)) { return -1; } // final fit diff --git a/Detectors/TPC/calibration/include/TPCCalibration/FastHisto.h b/Detectors/TPC/calibration/include/TPCCalibration/FastHisto.h index 6d9b5a857f00c..7318eda963ee5 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/FastHisto.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/FastHisto.h @@ -17,7 +17,7 @@ #define AliceO2_TPC_FastHisto_H //o2 includes -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "Framework/Logger.h" #include <sstream> #include <vector> @@ -94,7 +94,7 @@ class FastHisto /// \return this function returns the truncated mean for the filled histogram /// \param low lower truncation range /// \param high upper truncation range - math_utils::math_base::StatisticsData getStatisticsData(const float low = 0.05f, const float high = 0.6f) const; + math_utils::StatisticsData getStatisticsData(const float low = 0.05f, const float high = 0.6f) const; /// \return this function returns the bin content for given index /// \param index the index (bin) for which the content is returned @@ -186,7 +186,7 @@ inline void FastHisto<T>::fill(T val, T weight) template <class T> inline void FastHisto<T>::print(const int prec) const { - const math_utils::math_base::StatisticsData data = getStatisticsData(); + const math_utils::StatisticsData data = getStatisticsData(); LOGP(info, "\n Entries: {}", std::accumulate(mBinCont.begin(), mBinCont.end(), 0)); LOGP(info, "Truncated Mean: {}", data.mCOG); LOGP(info, "Standard Deviation: {}", data.mStdDev); @@ -243,9 +243,9 @@ inline void FastHisto<T>::print(const int prec) const } template <class T> -inline math_utils::math_base::StatisticsData FastHisto<T>::getStatisticsData(const float low, const float high) const +inline math_utils::StatisticsData FastHisto<T>::getStatisticsData(const float low, const float high) const { - math_utils::math_base::StatisticsData data{}; + math_utils::StatisticsData data{}; // in case something went wrong the COG is the histogram lower limit data.mCOG = mXmin; if (mBinCont.size() == 0) { diff --git a/Detectors/TPC/calibration/src/CalibPedestal.cxx b/Detectors/TPC/calibration/src/CalibPedestal.cxx index d30411ed23a32..9383713a1ebee 100644 --- a/Detectors/TPC/calibration/src/CalibPedestal.cxx +++ b/Detectors/TPC/calibration/src/CalibPedestal.cxx @@ -17,14 +17,14 @@ #include "TFile.h" #include "TPCBase/ROC.h" -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "TPCCalibration/CalibPedestal.h" using namespace o2::tpc; -using o2::math_utils::math_base::fit; -using o2::math_utils::math_base::fitGaus; -using o2::math_utils::math_base::getStatisticsData; -using o2::math_utils::math_base::StatisticsData; +using o2::math_utils::fit; +using o2::math_utils::fitGaus; +using o2::math_utils::getStatisticsData; +using o2::math_utils::StatisticsData; CalibPedestal::CalibPedestal(PadSubset padSubset) : CalibRawBase(padSubset), diff --git a/Detectors/TPC/calibration/src/CalibPulser.cxx b/Detectors/TPC/calibration/src/CalibPulser.cxx index 0ad6fc07a0d79..53ef51b855989 100644 --- a/Detectors/TPC/calibration/src/CalibPulser.cxx +++ b/Detectors/TPC/calibration/src/CalibPulser.cxx @@ -19,13 +19,13 @@ #include "TFile.h" #include "TPCBase/ROC.h" -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "TPCCalibration/CalibPulser.h" #include "TPCCalibration/CalibPulserParam.h" using namespace o2::tpc; -using o2::math_utils::math_base::getStatisticsData; -using o2::math_utils::math_base::StatisticsData; +using o2::math_utils::getStatisticsData; +using o2::math_utils::StatisticsData; CalibPulser::CalibPulser(PadSubset padSubset) : mNbinsT0{200}, diff --git a/Detectors/TPC/calibration/src/CalibTreeDump.cxx b/Detectors/TPC/calibration/src/CalibTreeDump.cxx index 79b4266b49e11..54d8c15f383cd 100644 --- a/Detectors/TPC/calibration/src/CalibTreeDump.cxx +++ b/Detectors/TPC/calibration/src/CalibTreeDump.cxx @@ -20,7 +20,7 @@ #include "TTree.h" #include "TMath.h" -#include "MathUtils/MathBase.h" +#include "MathUtils/fit.h" #include "TPCBase/CalArray.h" #include "TPCBase/CalDet.h" #include "TPCBase/CRU.h" @@ -30,7 +30,7 @@ #include "TPCCalibration/CalibTreeDump.h" -using o2::math_utils::math_base::median; +using o2::math_utils::median; using namespace o2::tpc; diff --git a/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h index 90d9d7fa6749d..958ca4735a0bd 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/VertexTrackMatcher.h @@ -25,7 +25,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "CommonDataFormat/InteractionRecord.h" #include "DetectorsVertexing/PVertexerParams.h" -#include "MathUtils/Bracket.h" +#include "MathUtils/Primitive2D.h" namespace o2 { @@ -44,7 +44,7 @@ class VertexTrackMatcher using TrackTPC = o2::tpc::TrackTPC; using TmpMap = std::unordered_map<int, std::vector<GIndex>>; using TimeEst = o2::dataformats::TimeStampWithError<float, float>; - using TBracket = o2::math_utils::Bracket<float>; + using TBracket = o2::math_utils::Bracketf_t; void init(); void process(const gsl::span<const PVertex>& vertices, // vertices From 09593e8e80312b1f9dabebdac65a4fd5c6f68378 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Tue, 13 Oct 2020 18:11:05 +0200 Subject: [PATCH 1036/1751] [alignment] Double specialization TrackPar(Cov) Enables the double precision specialization for `TrackParametrization` and `TrackParametrizationWithError`. --- .../Reconstruction/src/ReconstructionDataFormatsLinkDef.h | 4 ++-- DataFormats/Reconstruction/src/TrackParametrization.cxx | 2 +- .../Reconstruction/src/TrackParametrizationWithError.cxx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index c0063614bb1c8..eb8eb8550c05a 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -16,10 +16,10 @@ #pragma link C++ class o2::track::TrackPar + ; #pragma link C++ class o2::track::TrackParametrization < float> + ; -//#pragma link C++ class o2::track::TrackParametrization < double> + ; +#pragma link C++ class o2::track::TrackParametrization < double> + ; #pragma link C++ class o2::track::TrackParCov + ; #pragma link C++ class o2::track::TrackParametrizationWithError < float> + ; -//#pragma link C++ class o2::track::TrackParametrizationWithError < double> + ; +#pragma link C++ class o2::track::TrackParametrizationWithError < double> + ; #pragma link C++ class o2::track::TrackParFwd + ; #pragma link C++ class o2::track::TrackParCovFwd + ; #pragma link C++ class o2::track::PID + ; diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index 71ee601915ada..228a4f8890022 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -733,7 +733,7 @@ bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, } template class TrackParametrization<float>; -//template class TrackParametrization<double>; +template class TrackParametrization<double>; } // namespace track } // namespace o2 diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index 80232070a097a..6bcb26db98aab 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -1086,7 +1086,7 @@ void TrackParametrizationWithError<value_T>::print() const } template class TrackParametrizationWithError<float>; -//template class TrackParametrizationWithError<double>; +template class TrackParametrizationWithError<double>; } // namespace track } // namespace o2 From 74b7ce0a81635842c38a31c1e62efa95f5b126ae Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Thu, 22 Oct 2020 08:42:30 +0200 Subject: [PATCH 1037/1751] [math_utils] temporary namespace alias Temporarily add a namespace alias for of from `o2::math_utils` to `o2::utils`, to make external packages Compile. Will be removed after these packages are patched. --- Common/MathUtils/include/MathUtils/Utils.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index 4acf7e633428c..7e4b8e8bedd13 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -224,4 +224,12 @@ using detail::numberOfBitsSet; } // namespace math_utils } // namespace o2 +namespace o2 +{ +namespace utils +{ +using namespace math_utils; +} // namespace utils +} // namespace o2 + #endif From bbd0c9034a8579c0521888af7f8464cfc636298c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 20:10:43 +0200 Subject: [PATCH 1038/1751] Temporarily add more aliases to fix QC compilation --- .../include/ITSMFTReconstruction/RawPixelReader.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h index c09bf6d5bac89..c6d0d872940cf 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h @@ -27,6 +27,7 @@ #include "ITSMFTReconstruction/GBTLink.h" #include "ITSMFTReconstruction/RUDecodeData.h" #include "DetectorsRaw/RDHUtils.h" +#include "MathUtils/Cartesian.h" #include <TTree.h> #include <TStopwatch.h> @@ -47,8 +48,13 @@ #define OUTHEX(v, l) "0x" << std::hex << std::setfill('0') << std::setw(l) << v << std::dec +template <typename T> +using Point3D = o2::math_utils::Point3D<T>; + namespace o2 { +using TransformType = o2::math_utils::TransformType; + namespace itsmft { From b8a9f1c047cce440b730983e9f2df36100c0c5d8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 22 Oct 2020 23:25:10 +0200 Subject: [PATCH 1039/1751] DPL: fix parsing of inputspec metadata (#4660) --- .../Core/src/WorkflowSerializationHelpers.cxx | 2 + .../Core/test/test_WorkflowSerialization.cxx | 54 ++++++++++--------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Framework/Core/src/WorkflowSerializationHelpers.cxx b/Framework/Core/src/WorkflowSerializationHelpers.cxx index 1b892d19405c5..20bb11ee7407e 100644 --- a/Framework/Core/src/WorkflowSerializationHelpers.cxx +++ b/Framework/Core/src/WorkflowSerializationHelpers.cxx @@ -230,6 +230,8 @@ struct WorkflowImporter : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, outputHasSubSpec = false; } else if (in(State::IN_OPTIONS)) { push(State::IN_OPTION); + } else if (in(State::IN_INPUT_OPTIONS)) { + push(State::IN_OPTION); } else if (in(State::IN_WORKFLOW_OPTIONS)) { push(State::IN_OPTION); } else if (in(State::IN_METADATA)) { diff --git a/Framework/Core/test/test_WorkflowSerialization.cxx b/Framework/Core/test/test_WorkflowSerialization.cxx index 511d4ccca5307..4618b5e28813c 100644 --- a/Framework/Core/test/test_WorkflowSerialization.cxx +++ b/Framework/Core/test/test_WorkflowSerialization.cxx @@ -20,31 +20,35 @@ using namespace o2::framework; BOOST_AUTO_TEST_CASE(TestVerifyWorkflow) { using namespace o2::framework; - WorkflowSpec w0{ - DataProcessorSpec{"A", - {InputSpec{"foo", "A", "COLLISIONCONTEXT", 1, Lifetime::Condition, {ConfigParamSpec{"aUrl", VariantType::String, "foo/bar", {"A InputSpec option"}}}}}, - {OutputSpec{{"bar"}, "C", "D", 2, Lifetime::Timeframe}}, - AlgorithmSpec{[](ProcessingContext& ctx) {}}, - {ConfigParamSpec{"aInt", VariantType::Int, 0, {"An Int"}}, - ConfigParamSpec{"aFloat", VariantType::Float, 1.3, {"A Float"}}, - ConfigParamSpec{"aBool", VariantType::Bool, true, {"A Bool"}}, - ConfigParamSpec{"aString", VariantType::String, "some string", {"A String"}}}}, - DataProcessorSpec{"B", - {InputSpec{"foo", "C", "D"}}, - {OutputSpec{{"bar1"}, "E", "F", 0}, - OutputSpec{{"bar2"}, "E", "F", 1}}, - AlgorithmSpec{[](ProcessingContext& ctx) {}}, - {}}, - DataProcessorSpec{"C", - {}, - {OutputSpec{{"bar"}, "G", "H"}}, - AlgorithmSpec{[](ProcessingContext& ctx) {}}, - {}}, - DataProcessorSpec{"D", - {InputSpec{"foo", {"C", "D"}}}, - {OutputSpec{{"bar"}, {"I", "L"}}}, - AlgorithmSpec{[](ProcessingContext& ctx) {}}, - {}}}; + WorkflowSpec w0{ // + DataProcessorSpec{"A", // + {InputSpec{"foo", "A", "COLLISIONCONTEXT", 1, Lifetime::Condition, { + ConfigParamSpec{"aUrl", VariantType::String, "foo/bar", {"A InputSpec option"}}, // + ConfigParamSpec{"bUrl", VariantType::String, "foo/foo", {"Another InputSpec option"}}, // + }}}, // + {OutputSpec{{"bar"}, "C", "D", 2, Lifetime::Timeframe}}, // + AlgorithmSpec{[](ProcessingContext& ctx) {}}, // + { // + ConfigParamSpec{"aInt", VariantType::Int, 0, {"An Int"}}, // + ConfigParamSpec{"aFloat", VariantType::Float, 1.3, {"A Float"}}, // + ConfigParamSpec{"aBool", VariantType::Bool, true, {"A Bool"}}, // + ConfigParamSpec{"aString", VariantType::String, "some string", {"A String"}}}}, // // + DataProcessorSpec{"B", // + {InputSpec{"foo", "C", "D"}}, // + { // + OutputSpec{{"bar1"}, "E", "F", 0}, // + OutputSpec{{"bar2"}, "E", "F", 1}}, // + AlgorithmSpec{[](ProcessingContext& ctx) {}}, // + {}}, // + DataProcessorSpec{"C", {}, // + { // + OutputSpec{{"bar"}, "G", "H"}}, // + AlgorithmSpec{[](ProcessingContext& ctx) {}}, // + {}}, // + DataProcessorSpec{"D", {InputSpec{"foo", {"C", "D"}}}, // + {OutputSpec{{"bar"}, {"I", "L"}}}, // + AlgorithmSpec{[](ProcessingContext& ctx) {}}, // + {}}}; // std::vector<DataProcessorInfo> metadataOut{ {"A", "test_Framework_test_SerializationWorkflow", {"foo"}, {ConfigParamSpec{"aBool", VariantType::Bool, true, {"A Bool"}}}}, From e4a426e48e518c4880be31f86c15ad28dd1ece88 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 18 Oct 2020 19:34:59 +0200 Subject: [PATCH 1040/1751] Don't store clsuters as attached to a track that fail in the fit --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 63908b70927db..9ed493bf5ca88 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -69,6 +69,8 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* throw std::runtime_error("Invalid input for gpu tracking"); } + constexpr unsigned char flagsReject = GPUTPCGMMergedTrackHit::flagReject | GPUTPCGMMergedTrackHit::flagNotFit; + std::vector<TrackTPC>* outputTracks = data->outputTracks; std::vector<uint32_t>* outClusRefs = data->outputClusRefs; std::vector<o2::MCCompLabel>* outputTracksMCTruth = data->outputTracksMCTruth; @@ -248,7 +250,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* outerPar.C[12], outerPar.C[13], outerPar.C[14]})); int nOutCl = 0; for (int j = 0; j < tracks[i].NClusters(); j++) { - if (!(trackClusters[tracks[i].FirstClusterRef() + j].state & GPUTPCGMMergedTrackHit::flagReject)) { + if (!(trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject)) { nOutCl++; } } @@ -261,7 +263,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* std::vector<std::pair<MCCompLabel, unsigned int>> labels; nOutCl = 0; for (int j = 0; j < tracks[i].NClusters(); j++) { - if (trackClusters[tracks[i].FirstClusterRef() + j].state & GPUTPCGMMergedTrackHit::flagReject) { + if (trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) { continue; } int clusterIdGlobal = trackClusters[tracks[i].FirstClusterRef() + j].num; From 8438e494005c29bcdf8da69d6fbf5927e49a8d65 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 18 Oct 2020 19:35:35 +0200 Subject: [PATCH 1041/1751] GPU: Mark cluster that fail in the fit --- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 70eae65b3754e..00a685aafee8a 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -310,6 +310,8 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, } else if (retVal == 2) { // cluster far away form the track if (allowModification) { MarkClusters(clusters, ihitMergeFirst, ihit, wayDirection, GPUTPCGMMergedTrackHit::flagRejectDistance); + } else if (iWay == nWays - 1) { + MarkClusters(clusters, ihitMergeFirst, ihit, wayDirection, GPUTPCGMMergedTrackHit::flagRejectErr); } nMissed++; nMissed2++; From 64deb95ed3f23c4b4a9735b3b45d37986e1a2bad Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 13 Oct 2020 09:55:52 +0200 Subject: [PATCH 1042/1751] GPU: Add class for TPC Refit --- GPU/GPUTracking/Base/GPUDataTypes.h | 2 + GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/CMakeLists.txt | 4 +- .../GPUTPCClusterStatistics.cxx | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 29 ++ GPU/GPUTracking/Global/GPUChainTracking.h | 1 + GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 14 + GPU/GPUTracking/Merger/GPUTPCGMMerger.h | 2 + GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 322 ++++++++++++++++++ GPU/GPUTracking/Refit/GPUTrackingRefit.h | 101 ++++++ GPU/GPUTracking/Standalone/CMakeLists.txt | 1 + GPU/GPUTracking/Standalone/Refit | 1 + .../Standalone/display/GPUDisplayKeys.cxx | 2 +- GPU/GPUTracking/Standalone/standalone.cxx | 4 + 14 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 GPU/GPUTracking/Refit/GPUTrackingRefit.cxx create mode 100644 GPU/GPUTracking/Refit/GPUTrackingRefit.h create mode 120000 GPU/GPUTracking/Standalone/Refit diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index e04ee771ef7ac..bf326f3923a95 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -124,6 +124,7 @@ class GPUDataTypes TPCdEdx = 64, TPCClusterFinding = 128, TPCDecompression = 256, + Refit = 512, AllRecoSteps = 0x7FFFFFFF, NoRecoStep = 0 }; enum ENUM_CLASS InOutType { TPCClusters = 1, @@ -230,6 +231,7 @@ struct GPUTrackingInOutPointers { const GPUTPCGMMergedTrackHitXYZ* mergedTrackHitsXYZ = nullptr; unsigned int nMergedTrackHits = 0; unsigned int* mergedTrackHitAttachment = nullptr; + unsigned char* mergedTrackHitStates = nullptr; const o2::tpc::CompressedClustersFlat* tpcCompressedClusters = nullptr; const GPUTRDTrackletWord* trdTracklets = nullptr; unsigned int nTRDTracklets = 0; diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 80775a5219f02..64ce92b709f03 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -244,6 +244,7 @@ AddOption(runTRD, int, -1, "", 0, "Enable TRD processing") AddOption(rundEdx, int, -1, "", 0, "Enable dEdx processing") AddOption(runCompression, int, 1, "", 0, "Enable TPC Compression") AddOption(runTransformation, int, 1, "", 0, "Enable TPC Transformation") +AddOption(runRefit, bool, false, "", 0, "Enable final track refit") AddHelp("help", 'h') AddHelpAll("helpall", 'H') AddSubConfig(GPUSettingsRec, rec) diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index bde21257e06a0..5f4d6867f3bc4 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -172,7 +172,8 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) TPCClusterFinder/GPUTPCCFDecodeZS.cxx TPCClusterFinder/GPUTPCCFGather.cxx TPCClusterFinder/TPCCFCalibration.cxx - dEdx/TPCdEdxCalibrationSplines.cxx) + dEdx/TPCdEdxCalibrationSplines.cxx + Refit/GPUTrackingRefit.cxx) set(SRCS_NO_H ${SRCS_NO_H} TPCClusterFinder/GPUTPCClusterFinderDump.cxx) @@ -270,6 +271,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") HLTHeaders Interface Merger + Refit DataCompression TPCClusterFinder TARGETVARNAME targetName diff --git a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx index a0f60ac46b608..e2b85cd4e1dfd 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx @@ -224,7 +224,7 @@ void GPUTPCClusterStatistics::Finish() GPUInfo("Combined Sigma: %6.4f --> %6.4f (%6.4f%%)", eSigma, eSigmaCombined, eSigma > 1e-3 ? (100. * (eSigma - eSigmaCombined) / eSigma) : 0.f); GPUInfo("Combined Q: %6.4f --> %6.4f (%6.4f%%)", eQ, eQCombined, eQ > 1e-3 ? (100. * (eQ - eQCombined) / eQ) : 0.f); - printf("\nConbined Entropy: %7.4f (Size %'13.0f, %'lld cluster)\nCombined Huffman: %7.4f (Size %'13.0f, %f%%)\n\n", mEntropy / mNTotalClusters, mEntropy, (long long int)mNTotalClusters, mHuffman / mNTotalClusters, mHuffman, 100. * (mHuffman - mEntropy) / mHuffman); + printf("\nCombined Entropy: %7.4f (Size %'13.0f, %'lld cluster)\nCombined Huffman: %7.4f (Size %'13.0f, %f%%)\n\n", mEntropy / mNTotalClusters, mEntropy, (long long int)mNTotalClusters, mHuffman / mNTotalClusters, mHuffman, 100. * (mHuffman - mEntropy) / mHuffman); } float GPUTPCClusterStatistics::Analyze(std::vector<int>& p, const char* name, bool count) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 33e4dfc5731ce..1f6db07c30302 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -57,6 +57,7 @@ #include "TPCdEdxCalibrationSplines.h" #include "TPCClusterDecompressor.h" #include "GPUTPCCFChainContext.h" +#include "GPUTrackingRefit.h" #else #include "GPUO2FakeClasses.h" #endif @@ -2063,6 +2064,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) mIOPtrs.mergedTrackHits = Merger.Clusters(); mIOPtrs.nMergedTrackHits = Merger.NOutputTrackClusters(); mIOPtrs.mergedTrackHitAttachment = Merger.ClusterAttachment(); + mIOPtrs.mergedTrackHitStates = Merger.ClusterStateExt(); if (GetProcessingSettings().debugLevel >= 2) { GPUInfo("TPC Merger Finished (output clusters %d / input clusters %d)", Merger.NOutputTrackClusters(), Merger.NClusters()); @@ -2323,6 +2325,29 @@ int GPUChainTracking::DoTRDGPUTracking() return (0); } +int GPUChainTracking::RunRefit() +{ +#ifdef HAVE_O2HEADERS + GPUTrackingRefit re; + re.SetPtrsFromGPUConstantMem(processorsShadow()); + re.SetPropagatorDefault(); + for (unsigned int i = 0; i < mIOPtrs.nMergedTracks; i++) { + if (mIOPtrs.mergedTracks[i].OK()) { + printf("\nRefitting track %d\n", i); + GPUTPCGMMergedTrack t = mIOPtrs.mergedTracks[i]; + int retval = re.RefitTrackAsGPU(t, false, true); + printf("Refit error code: %d\n", retval); + + printf("\nRefitting track TrackParCov %d\n", i); + t = mIOPtrs.mergedTracks[i]; + retval = re.RefitTrackAsTrackParCov(t, false, true); + printf("Refit error code: %d\n", retval); + } + } +#endif + return 0; +} + int GPUChainTracking::RunChain() { const auto threadContext = GetThreadContext(); @@ -2408,6 +2433,10 @@ int GPUChainTracking::RunChain() return 1; } + if (runRecoStep(RecoStep::Refit, &GPUChainTracking::RunRefit)) { + return 1; + } + if (!GetProcessingSettings().doublePipeline) { // Synchronize with output copies running asynchronously SynchronizeStream(mRec->NStreams() - 2); } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index e148cf6e115d7..fc063d5a34cd6 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -148,6 +148,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega int DoTRDGPUTracking(); int RunTPCCompression(); int RunTPCDecompression(); + int RunRefit(); // Getters / setters for parameters const TPCFastTransform* GetTPCTransform() const { return processors()->calibObjects.fastTransform; } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 6bbe9ffc40a48..37b04407510ee 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -278,6 +278,11 @@ void* GPUTPCGMMerger::SetPointersOutput(void* mem) if (!mRec->GetProcessingSettings().fullMergerOnGPU) { mem = SetPointersRefitScratch2(mem); } + if (mRec->GetRecoSteps() & GPUDataTypes::RecoStep::Refit) { + computePointerWithAlignment(mem, mClusterStateExt, mNMaxClusters); + } else { + mClusterStateExt = nullptr; + } return mem; } @@ -1825,6 +1830,15 @@ GPUd() void GPUTPCGMMerger::PrepareClustersForFit2(int nBlocks, int nThreads, in mClusters[i].state |= GPUTPCGMMergedTrackHit::flagShared; } } + if (mClusterStateExt) { + for (unsigned int i = iBlock * nThreads + iThread; i < mNMaxClusters; i += nBlocks * nThreads) { + unsigned char state = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[i].getFlags(); + if (sharedCount[i] > 1) { + state |= GPUTPCGMMergedTrackHit::flagShared; + } + mClusterStateExt[i] = state; + } + } } GPUd() void GPUTPCGMMerger::Finalize0(int nBlocks, int nThreads, int iBlock, int iThread) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h index 77bc80545f480..dd8ff0a76f351 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h @@ -110,6 +110,7 @@ class GPUTPCGMMerger : public GPUProcessor GPUhdi() unsigned int* TrackOrderAttach() const { return mTrackOrderAttach; } GPUhdi() unsigned int* TrackOrderProcess() const { return mTrackOrderProcess; } GPUhdi() unsigned int* RetryRefitIds() const { return mRetryRefitIds; } + GPUhdi() unsigned char* ClusterStateExt() const { return mClusterStateExt; } GPUhdi() GPUTPCGMLoopData* LoopData() const { return mLoopData; } GPUhdi() memory* Memory() const { return mMemory; } GPUhdi() GPUAtomic(unsigned int) * TmpCounter() { return mMemory->tmpCounter; } @@ -218,6 +219,7 @@ class GPUTPCGMMerger : public GPUProcessor GPUAtomic(unsigned int) * mClusterAttachment; unsigned int* mTrackOrderAttach; unsigned int* mTrackOrderProcess; + unsigned char* mClusterStateExt; uint4* mTmpMem; GPUTPCGMBorderTrack* mBorderMemory; // memory for border tracks GPUTPCGMBorderTrack* mBorder[2 * NSLICES]; diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx new file mode 100644 index 0000000000000..e608b6383b214 --- /dev/null +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -0,0 +1,322 @@ +// 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 GPUTrackingRefit.cxx +/// \author David Rohr + +#define GPUCA_CADEBUG 0 + +#include "GPUTrackingRefit.h" +#include "GPUO2DataTypes.h" +#include "GPUTPCGMTrackParam.h" +#include "GPUTPCGMMergedTrack.h" +#include "GPUTPCGMPropagator.h" +#include "GPUConstantMem.h" +#include "TPCFastTransform.h" +#include "ReconstructionDataFormats/Track.h" +#include "DetectorsBase/Propagator.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "GPUParam.inc" + +using namespace GPUCA_NAMESPACE::gpu; +using namespace o2::track; +using namespace o2::base; +using namespace o2::tpc; + +void GPUTrackingRefitProcessor::InitializeProcessor() {} + +void GPUTrackingRefitProcessor::RegisterMemoryAllocation() +{ + AllocateAndInitializeLate(); +} + +void GPUTrackingRefitProcessor::SetMaxData(const GPUTrackingInOutPointers& io) +{ +} + +namespace +{ +template <class T> +struct refitTrackTypes; +template <> +struct refitTrackTypes<GPUTPCGMTrackParam> { + using propagator = GPUTPCGMPropagator; +}; +template <> +struct refitTrackTypes<TrackParCov> { + using propagator = const Propagator*; +}; +} // anonymous namespace + +template <> +void GPUTrackingRefit::initProp<GPUTPCGMPropagator>(GPUTPCGMPropagator& prop) +{ + prop.SetMaterialTPC(); + prop.SetMaxSinPhi(GPUCA_MAX_SIN_PHI); + prop.SetToyMCEventsFlag(false); + prop.SetSeedingErrors(false); + prop.SetFitInProjections(false); + prop.SetPropagateBzOnly(false); + prop.SetPolynomialField(&mPparam->polynomialField); +} + +template <> +void GPUTrackingRefit::initProp<const Propagator*>(const Propagator*& prop) +{ + prop = mPpropagator; +} + +template <class T, class S, class U> +void GPUTrackingRefit::convertTrack(T& trk, const S& trkX, U& prop) +{ + trk = trkX; +} +static void convertTrackParam(GPUTPCGMTrackParam& trk, const TrackParCov& trkX) +{ + for (int i = 0; i < 5; i++) { + trk.Par()[i] = trkX.getParams()[i]; + } + for (int i = 0; i < 15; i++) { + trk.Cov()[i] = trkX.getCov()[i]; + } + trk.X() = trkX.getX(); +} +static void convertTrackParam(TrackParCov& trk, const GPUTPCGMTrackParam& trkX) +{ + for (int i = 0; i < 5; i++) { + trk.setParam(trkX.GetPar()[i], i); + } + for (int i = 0; i < 15; i++) { + trk.setCov(trkX.GetCov()[i], i); + } + trk.setX(trkX.GetX()); +} +template <> +void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, TrackParCov, const Propagator*>(GPUTPCGMMergedTrack& trk, const TrackParCov& trkX, const Propagator*& prop) +{ + convertTrackParam(trk.Param(), trkX); + trk.SetAlpha(trkX.getAlpha()); +} +template <> +void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Propagator*>(TrackParCov& trk, const GPUTPCGMMergedTrack& trkX, const Propagator*& prop) +{ + initProp(prop); + convertTrackParam(trk, trkX.GetParam()); + trk.setAlpha(trkX.GetAlpha()); +} +template <> +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackParCov& trkX, GPUTPCGMPropagator& prop) +{ + convertTrackParam(trk, trkX); + prop.SetTrack(&trk, trkX.getAlpha()); +} +template <> +void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackParCov& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +{ + convertTrackParam(trk, trkX); + trk.setAlpha(prop.GetAlpha()); +} +template <> +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTPCGMMergedTrack, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTPCGMMergedTrack& trkX, GPUTPCGMPropagator& prop) +{ + initProp(prop); + trk = trkX.GetParam(); + prop.SetTrack(&trk, trkX.GetAlpha()); +} +template <> +void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTPCGMMergedTrack& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +{ + trk.SetParam(trkX); + trk.SetAlpha(prop.GetAlpha()); +} +template <> +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackTPC, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackTPC& trkX, GPUTPCGMPropagator& prop) +{ + initProp(prop); + convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX, prop); +} +template <> +void GPUTrackingRefit::convertTrack<TrackTPC, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackTPC& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +{ + initProp(prop); + convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk, trkX, prop); +} +template <> +void GPUTrackingRefit::convertTrack<TrackTPC, TrackParCov, const Propagator*>(TrackTPC& trk, const TrackParCov& trkX, const Propagator*& prop) +{ + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); +} +template <> +void GPUTrackingRefit::convertTrack<TrackParCov, TrackTPC, const Propagator*>(TrackParCov& trk, const TrackTPC& trkX, const Propagator*& prop) +{ + initProp(prop); + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); +} +static const float* getPar(const GPUTPCGMTrackParam& trk) { return trk.GetPar(); } +static const float* getPar(const TrackParCov& trk) { return trk.getParams(); } + +template <class T, class S> +GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) +{ + CADEBUG(int ii; printf("\nRefitting track\n")); + typename refitTrackTypes<S>::propagator prop; + S trk; + convertTrack(trk, trkX, prop); + int begin = 0, count; + float tOffset; + if constexpr (std::is_same<T, GPUTPCGMMergedTrack>::value) { + count = trkX.NClusters(); + if (trkX.Looper()) { + int leg = mPtrackHits[trkX.FirstClusterRef() + trkX.NClusters() - 1].leg; + for (int i = trkX.NClusters() - 2; i > 0; i--) { + if (mPtrackHits[trkX.FirstClusterRef() + i].leg != leg) { + begin = i + 1; + break; + } + } + } + tOffset = trkX.GetParam().GetTZOffset(); + } else if constexpr (std::is_same<T, TrackTPC>::value) { + count = trkX.getNClusters(); + tOffset = trkX.getTime0(); + } + int direction = outward ? -1 : 1; + int start = outward ? count - 1 : begin; + int stop = outward ? begin - 1 : count; + const ClusterNative* cl = nullptr; + uint8_t sector, row, currentSector, currentRow; + short clusterState, nextState; + for (int i = start; i != stop; i += cl ? 0 : direction) { + float x, y, z, charge; + int clusters = 0; + while (true) { + if (!cl) { + CADEBUG(ii = i); + if constexpr (std::is_same<T, GPUTPCGMMergedTrack>::value) { + const auto& hit = mPtrackHits[trkX.FirstClusterRef() + i]; + cl = &mPclusterNative->clustersLinear[hit.num]; + if (hit.state & (GPUTPCGMMergedTrackHit::flagReject | GPUTPCGMMergedTrackHit::flagNotFit)) { + cl = nullptr; + if (i + direction != stop) { + i += direction; + continue; + } + break; + } + row = hit.row; + sector = hit.slice; + nextState = mPclusterState[hit.num]; + } else if constexpr (std::is_same<T, TrackTPC>::value) { + cl = &trkX.getCluster(mPtrackHitReferences, i, *mPclusterNative, sector, row); + nextState = mPclusterState[cl - mPclusterNative->clustersLinear]; + } + } + if (clusters == 0 || (row == currentRow && sector == currentSector)) { + if (clusters == 1) { + x *= charge; + y *= charge; + z *= charge; + } + if (clusters == 0) { + mPfastTransform->Transform(sector, row, cl->getPad(), cl->getTime(), x, y, z, tOffset); + CADEBUG(printf("\tHit %3d/%3d Row %3d: Cluster Alpha %8.3f %3d, X %8.3f - Y %8.3f, Z %8.3f\n", ii, count, row, mPparam->Alpha(sector), (int)sector, x, y, z)); + currentRow = row; + currentSector = sector; + charge = cl->qTot; + clusterState = nextState; + } else { + float xx, yy, zz; + mPfastTransform->Transform(sector, row, cl->getPad(), cl->getTime(), xx, yy, zz, tOffset); + CADEBUG(printf("\tHit %3d/%3d Row %3d: Cluster Alpha %8.3f %3d, X %8.3f - Y %8.3f, Z %8.3f\n", ii, count, row, mPparam->Alpha(sector), (int)sector, xx, yy, zz)); + x += xx * cl->qTot; + y += yy * cl->qTot; + z += zz * cl->qTot; + charge += cl->qTot; + clusterState |= nextState; + } + cl = nullptr; + clusters++; + if (i + direction != stop) { + i += direction; + continue; + } + } + break; + } + if (clusters == 0) { + continue; + } else if (clusters > 1) { + x /= charge; + y /= charge; + z /= charge; + CADEBUG(printf("\tMerged Hit Row %3d: Cluster Alpha %8.3f %3d, X %8.3f - Y %8.3f, Z %8.3f\n", row, mPparam->Alpha(sector), (int)sector, x, y, z)); + } + + if constexpr (std::is_same<S, GPUTPCGMTrackParam>::value) { + if (prop.PropagateToXAlpha(x, mPparam->Alpha(currentSector), !outward)) { + return 2; + } + if (resetCov) { + trk.ResetCovariance(); + } + CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[0] - y, trk.Par()[1] - z, sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); + if (prop.Update(y, z, row, *mPparam, clusterState, 0, nullptr, true)) { + return 3; + } + CADEBUG(printf("\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[3], "", sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); + } else if constexpr (std::is_same<S, TrackParCov>::value) { + if (!trk.rotate(mPparam->Alpha(currentSector))) { + return 1; + } + if (!prop->PropagateToXBxByBz(trk, x, o2::constants::physics::MassPionCharged, GPUCA_MAX_SIN_PHI_LOW)) { + return 2; + } + if (resetCov) { + trk.resetCovariance(); + } + CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[0] - y, trk.getParams()[1] - z, sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); + std::array<float, 2> p = {y, z}; + std::array<float, 3> c = {0, 0, 0}; + mPparam->GetClusterErrors2(currentRow, z, getPar(trk)[2], getPar(trk)[3], c[0], c[2]); + mPparam->UpdateClusterError2ByState(clusterState, c[0], c[2]); + if (!trk.update(p, c)) { + return 3; + } + CADEBUG(printf("\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[3], "", sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); + } + resetCov = false; + } + + convertTrack(trkX, trk, prop); + return 0; +} + +template GPUd() int GPUTrackingRefit::RefitTrack<GPUTPCGMMergedTrack, TrackParCov>(GPUTPCGMMergedTrack& trk, bool outward, bool resetCov); +template GPUd() int GPUTrackingRefit::RefitTrack<TrackTPC, TrackParCov>(TrackTPC& trk, bool outward, bool resetCov); +template GPUd() int GPUTrackingRefit::RefitTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam>(GPUTPCGMMergedTrack& trk, bool outward, bool resetCov); +template GPUd() int GPUTrackingRefit::RefitTrack<TrackTPC, GPUTPCGMTrackParam>(TrackTPC& trk, bool outward, bool resetCov); + +void GPUTrackingRefit::SetPtrsFromGPUConstantMem(const GPUConstantMem* v) +{ + mPclusterState = v->ioPtrs.mergedTrackHitStates; + mPclusterNative = v->ioPtrs.clustersNative; + mPtrackHits = v->ioPtrs.mergedTrackHits; + mPfastTransform = v->calibObjects.fastTransform; + mPparam = &v->param; +} + +void GPUTrackingRefit::SetPropagatorDefault() +{ +#ifndef GPUCA_STANDALONE + mPpropagator = Propagator::Instance(); +#else + throw std::runtime_error("unsupported"); +#endif +} diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.h b/GPU/GPUTracking/Refit/GPUTrackingRefit.h new file mode 100644 index 0000000000000..dea18446a72ca --- /dev/null +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.h @@ -0,0 +1,101 @@ +// 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 GPUTrackingRefit.h +/// \author David Rohr + +#ifndef GPUTRACKINGREFIT_H +#define GPUTRACKINGREFIT_H + +#include "GPUDef.h" +#include "GPUProcessor.h" + +namespace o2::dataformats +{ +template <typename FirstEntry, typename NElem> +class RangeReference; +} +namespace o2::track +{ +template <typename T> +class TrackParametrizationWithError; +using TrackParCov = TrackParametrizationWithError<float>; +} // namespace o2::track +namespace o2::base +{ +class Propagator; +} // namespace o2::base +namespace o2::tpc +{ +struct ClusterNativeAccess; +class TrackTPC; +using TrackTPCClusRef = o2::dataformats::RangeReference<uint32_t, uint16_t>; +} // namespace o2::tpc + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ +class GPUTPCGMTrackParam; +class GPUTPCGMMergedTrack; +MEM_CLASS_PRE() +struct GPUConstantMem; +MEM_CLASS_PRE() +struct GPUParam; +struct GPUTPCGMMergedTrackHit; +class TPCFastTransform; + +class GPUTrackingRefit +{ + public: + void SetClusterStateArray(const unsigned char* v) { mPclusterState = v; } + void SetPtrsFromGPUConstantMem(const GPUConstantMem* v); + void SetPropagator(const o2::base::Propagator* v) { mPpropagator = v; } + void SetPropagatorDefault(); + void SetClusterNative(const o2::tpc::ClusterNativeAccess* v) { mPclusterNative = v; } + void SetTrackHits(const GPUTPCGMMergedTrackHit* v) { mPtrackHits = v; } + void SetTrackHitReferences(const unsigned int* v) { mPtrackHitReferences = v; } + void SetFastTransform(const TPCFastTransform* v) { mPfastTransform = v; } + void SetGPUParam(const MEM_CONSTANT(GPUParam) * v) { mPparam = v; } + GPUd() int RefitTrackAsGPU(GPUTPCGMMergedTrack& trk, bool outward = false, bool resetCov = false) { return RefitTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam>(trk, outward, resetCov); } + GPUd() int RefitTrackAsTrackParCov(GPUTPCGMMergedTrack& trk, bool outward = false, bool resetCov = false) { return RefitTrack<GPUTPCGMMergedTrack, o2::track::TrackParCov>(trk, outward, resetCov); } + GPUd() int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return RefitTrack<o2::tpc::TrackTPC, GPUTPCGMTrackParam>(trk, outward, resetCov); } + GPUd() int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return RefitTrack<o2::tpc::TrackTPC, o2::track::TrackParCov>(trk, outward, resetCov); } + + private: + const unsigned char* mPclusterState = nullptr; // Ptr to shared cluster state + const o2::base::Propagator* mPpropagator = nullptr; // Ptr to propagator for TrackParCov track model + const o2::tpc::ClusterNativeAccess* mPclusterNative = nullptr; // Ptr to cluster native access structure + const GPUTPCGMMergedTrackHit* mPtrackHits = nullptr; // Ptr to hits for GPUTPCGMMergedTrack tracks + const unsigned int* mPtrackHitReferences = nullptr; // Ptr to hits for TrackTPC tracks + const TPCFastTransform* mPfastTransform = nullptr; // Ptr to TPC fast transform object + const MEM_CONSTANT(GPUParam) * mPparam = nullptr; // Ptr to GPUParam + template <class T, class S> + GPUd() int RefitTrack(T& trk, bool outward, bool resetCov); + template <class T, class S, class U> + void convertTrack(T& trk, const S& trkX, U& prop); + template <class U> + void initProp(U& prop); +}; + +class GPUTrackingRefitProcessor : public GPUTrackingRefit, public GPUProcessor +{ + public: +#ifndef GPUCA_GPUCODE + void InitializeProcessor(); + void RegisterMemoryAllocation(); + void SetMaxData(const GPUTrackingInOutPointers& io); +#endif +}; + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 325aec20fb796..a1a56664a65f6 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -112,6 +112,7 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/Global ${CMAKE_SOURCE_DIR}/HLTHeaders ${CMAKE_SOURCE_DIR}/Merger + ${CMAKE_SOURCE_DIR}/Refit ${CMAKE_SOURCE_DIR}/qa ${CMAKE_SOURCE_DIR}/SliceTracker ${CMAKE_SOURCE_DIR}/TRDTracking) diff --git a/GPU/GPUTracking/Standalone/Refit b/GPU/GPUTracking/Standalone/Refit new file mode 120000 index 0000000000000..2cdf319240e0d --- /dev/null +++ b/GPU/GPUTracking/Standalone/Refit @@ -0,0 +1 @@ +../Refit/ \ No newline at end of file diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx index 3d2ae8be4fcf3..e6224985e3f62 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx @@ -23,7 +23,7 @@ const char* HelpText[] = { "[l] / [k] / [J] Draw single slice (next / previous slice), draw related slices (same plane in phi)", "[;] / [:] Show splitting of TPC in slices by extruding volume, [:] resets", "[#] Invert colors", - "[y] / [Y] / ['] / [X] / [M] Start Animation, Add / remove Animation point, Reset, Cycle mode", + "[y] / [Y] / ['] / [X] / [M] Start Animation, Add / remove Animation point, Reset Points, Cycle animation camera mode (resets)", "[>] / [<] Toggle config interpolation during Animation / change Animation interval (via movement)", "[g] Draw Grid", "[i] Project onto XY-plane", diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 1056734d54caf..ddb3874a677a0 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -172,6 +172,7 @@ int ReadConfiguration(int argc, char** argv) #ifndef HAVE_O2HEADERS configStandalone.runTRD = configStandalone.rundEdx = configStandalone.runCompression = configStandalone.runTransformation = configStandalone.testSyncAsync = configStandalone.testSync = 0; configStandalone.rec.ForceEarlyTPCTransform = 1; + configStandalone.runRefit = false; #endif #ifndef GPUCA_TPC_GEOMETRY_O2 configStandalone.rec.mergerReadFromTrackerDirectly = 0; @@ -368,12 +369,15 @@ int SetupReconstruction() if (configStandalone.runTransformation != -1) { steps.steps.setBits(GPUDataTypes::RecoStep::TPCConversion, configStandalone.runTransformation > 0); } + steps.steps.setBits(GPUDataTypes::RecoStep::Refit, configStandalone.runRefit); if (!configStandalone.runMerger) { steps.steps.setBits(GPUDataTypes::RecoStep::TPCMerging, false); steps.steps.setBits(GPUDataTypes::RecoStep::TRDTracking, false); steps.steps.setBits(GPUDataTypes::RecoStep::TPCdEdx, false); steps.steps.setBits(GPUDataTypes::RecoStep::TPCCompression, false); + steps.steps.setBits(GPUDataTypes::RecoStep::Refit, false); } + if (configStandalone.TF.bunchSim || configStandalone.TF.nMerge) { steps.steps.setBits(GPUDataTypes::RecoStep::TRDTracking, false); } From 9af9cbfb6fb3795cc0cb8246692d9b47787d5432 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 15 Oct 2020 17:24:50 +0200 Subject: [PATCH 1043/1751] GPU: Initialize GPU processorsShadow also for non-GPU processing so it can be used conveniently --- GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index db4dd2bd42a14..9ca5ca58cc77b 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -165,6 +165,7 @@ int GPUReconstructionCPU::InitDevice() mBlockCount = getOMPMaxThreads(); } mThreadId = GetThread(); + mProcShadow.mProcessorsProc = processors(); return 0; } From dcccf0929816d3e465d3b9a9ea4ec47f0a8fc967 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 18 Oct 2020 20:13:12 +0200 Subject: [PATCH 1044/1751] GPU: Add interface to run TPC track refit without including GPU headers --- GPU/GPUTracking/CMakeLists.txt | 4 +- GPU/GPUTracking/GPUTrackingLinkDef_O2.h | 1 + .../Interface/GPUO2InterfaceRefit.cxx | 52 ++++++++++++++++ .../Interface/GPUO2InterfaceRefit.h | 61 +++++++++++++++++++ 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx create mode 100644 GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 5f4d6867f3bc4..3bd2719953d2e 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -135,8 +135,8 @@ set(HDRS_INSTALL # Sources only for O2 if(ALIGPU_BUILD_TYPE STREQUAL "O2") - set(SRCS ${SRCS} Interface/GPUO2Interface.cxx Interface/GPUO2InterfaceConfigurableParam.cxx) - set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h Interface/GPUO2InterfaceConfigurableParam.h dEdx/TPCdEdxCalibrationSplines.h) + set(SRCS ${SRCS} Interface/GPUO2Interface.cxx Interface/GPUO2InterfaceRefit.cxx Interface/GPUO2InterfaceConfigurableParam.cxx) + set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h Interface/GPUO2InterfaceRefit.h Interface/GPUO2InterfaceConfigurableParam.h dEdx/TPCdEdxCalibrationSplines.h) set(HDRS_CINT_O2_ADDITIONAL Base/GPUSettings.h Base/GPUSettingsList.h) # Manual depencies for ROOT dictionary generation endif() diff --git a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h index bcd8d5fdb0936..93c1c854de59e 100644 --- a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h +++ b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h @@ -18,6 +18,7 @@ #pragma link off all functions; #pragma link C++ class o2::gpu::GPUTPCO2Interface + ; +#pragma link C++ class o2::gpu::GPUTPCO2InterfaceRefit + ; #pragma link C++ class o2::gpu::TPCdEdxCalibrationSplines + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsO2 + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsRec + ; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx new file mode 100644 index 0000000000000..83b6291d83ce9 --- /dev/null +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx @@ -0,0 +1,52 @@ +// 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 GPUO2InterfaceRefit.cxx +/// \author David Rohr + +#include "GPUO2InterfaceRefit.h" +#include "DataFormatsTPC/ClusterNative.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "GPUParam.h" +#include "GPUTPCGMMergedTrackHit.h" + +using namespace o2::gpu; +using namespace o2::tpc; + +GPUTPCO2InterfaceRefit::GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const TPCFastTransform* trans, float bz, const TPCClRefElem* trackRef, const unsigned char* sharedmap, std::vector<o2::tpc::TrackTPC>* trks, o2::base::Propagator* p) : mRefit(), mParam(new GPUParam) +{ + if (sharedmap == nullptr && trks == nullptr) { + throw std::runtime_error("Must provide either shared cluster map or vector of tpc tracks to build the map"); + } + if (sharedmap == nullptr) { + mSharedMap.resize(cl->nClustersTotal); + sharedmap = mSharedMap.data(); + std::fill(mSharedMap.begin(), mSharedMap.end(), 0); + for (unsigned int i = 0; i < (*trks).size(); i++) { + for (unsigned int j = 0; j < (*trks)[i].getNClusterReferences(); j++) { + size_t idx = &(*trks)[i].getCluster(trackRef, j, *cl) - cl->clustersLinear; + mSharedMap[idx] = mSharedMap[idx] ? 2 : 1; + } + } + for (unsigned int i = 0; i < cl->nClustersTotal; i++) { + mSharedMap[i] = (mSharedMap[i] > 1 ? GPUTPCGMMergedTrackHit::flagShared : 0) | cl->clustersLinear[i].getFlags(); + } + } + + mParam->SetDefaults(bz); + mRefit.SetGPUParam(mParam.get()); + mRefit.SetClusterStateArray(sharedmap); + mRefit.SetPropagator(p); + mRefit.SetClusterNative(cl); + mRefit.SetTrackHitReferences(trackRef); + mRefit.SetFastTransform(trans); +} + +GPUTPCO2InterfaceRefit::~GPUTPCO2InterfaceRefit() = default; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h new file mode 100644 index 0000000000000..56f6cd86a183b --- /dev/null +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -0,0 +1,61 @@ +// 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 GPUO2InterfaceRefit.h +/// \author David Rohr + +#ifndef GPUO2INTERFACEREFIT_H +#define GPUO2INTERFACEREFIT_H + +// Some defines denoting that we are compiling for O2 +#ifndef HAVE_O2HEADERS +#define HAVE_O2HEADERS +#endif +#ifndef GPUCA_TPC_GEOMETRY_O2 +#define GPUCA_TPC_GEOMETRY_O2 +#endif +#ifndef GPUCA_O2_INTERFACE +#define GPUCA_O2_INTERFACE +#endif + +#include "GPUTrackingRefit.h" +#include <memory> +#include <vector> + +namespace o2::tpc +{ +using TPCClRefElem = uint32_t; +} + +namespace o2::gpu +{ +class GPUParam; +class GPUTPCO2InterfaceRefit +{ + public: + // Must initialize with: + // - In any case: Cluster Native access structure (cl), TPC Fast Transformation instance (trans), solenoid field (bz), TPC Track hit references (trackRef) + // - Either the shared cluster map (sharedmap) or the vector of tpc tracks (trks) to build the shared cluster map internally + // - o2::base::Propagator (p) in case RefitTrackAsTrackParCov is to be used + + GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const TPCFastTransform* trans, float bz, const o2::tpc::TPCClRefElem* trackRef, const unsigned char* sharedmap = nullptr, std::vector<o2::tpc::TrackTPC>* trks = nullptr, o2::base::Propagator* p = nullptr); + ~GPUTPCO2InterfaceRefit(); + + int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, outward, resetCov); } + int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, outward, resetCov); } + + private: + GPUTrackingRefit mRefit; + std::unique_ptr<GPUParam> mParam; + std::vector<unsigned char> mSharedMap; +}; +} // namespace o2::gpu + +#endif From f6c95946444df0cc889d2f9102430e4300ef8852 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 18 Oct 2020 20:58:32 +0200 Subject: [PATCH 1045/1751] Add macro to test TPC refit --- macro/CMakeLists.txt | 14 ++++-- macro/runTPCRefit.C | 105 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 macro/runTPCRefit.C diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index f487ab470611e..b98d5319126c6 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -15,7 +15,7 @@ install(FILES CheckDigits_mft.C SetIncludePath.C analyzeHits.C - duplicateHits.C + duplicateHits.C migrateSimFiles.C analyzeDigitLabels.C analyzeOriginHits.C @@ -33,6 +33,7 @@ install(FILES CheckDigits_mft.C readITSDigits.C rootlogon.C runCATrackingClusterNative.C + runTPCRefit.C run_CRUDataSkimming_its.C run_calib_tof.C run_clus_itsSA.C @@ -183,7 +184,7 @@ o2_add_test_root_macro( O2::MCHSimulation O2::MIDSimulation O2::ZDCSimulation - O2::CPVBase + O2::CPVBase O2::CPVSimulation O2::ZDCSimulation) @@ -235,6 +236,13 @@ o2_add_test_root_macro(runCATrackingClusterNative.C O2::ReconstructionDataFormats O2::SimulationDataFormat O2::TPCReconstruction +LABELS tpc) +# FIXME: move to subsystem dir +o2_add_test_root_macro(runTPCRefit.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsTPC + O2::ReconstructionDataFormats + O2::SimulationDataFormat + O2::TPCReconstruction LABELS tpc) # FIXME: move to subsystem dir @@ -261,7 +269,7 @@ o2_add_test_root_macro(run_clus_itsSA.C # FIXME: move to subsystem dir o2_add_test_root_macro(run_clus_tof.C - PUBLIC_LINK_LIBRARIES O2::TOFReconstruction O2::Framework O2::TOFBase + PUBLIC_LINK_LIBRARIES O2::TOFReconstruction O2::Framework O2::TOFBase O2::SimulationDataFormat O2::TOFCalibration O2::DataFormatsTOF LABELS tof) diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C new file mode 100644 index 0000000000000..be087f338f597 --- /dev/null +++ b/macro/runTPCRefit.C @@ -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. + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include <fstream> +#include <iostream> +#include <vector> +#include "TSystem.h" + +#include "TROOT.h" + +#include "GPUO2InterfaceRefit.h" +#include "TPCReconstruction/TPCFastTransformHelperO2.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/ClusterNative.h" +#include "DataFormatsTPC/ClusterNativeHelper.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "DataFormatsTPC/Constants.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#else +#pragma cling load("libO2TPCReconstruction") +#pragma cling load("libO2DataFormatsTPC") +#endif + +using namespace o2::gpu; +using namespace o2::tpc; +using namespace o2::dataformats; +using namespace o2::base; +using namespace std; + +int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc-native-clusters.root") +{ + GeometryManager::loadGeometry(); + Propagator::initFieldFromGRP(NameConf::getGRPFileName()); + const auto grp = o2::parameters::GRPObject::loadFrom("o2sim_grp.root"); + float bz = 5.00668f * grp->getL3Current() / 30000.; + std::unique_ptr<TPCFastTransform> trans = std::move(TPCFastTransformHelperO2::instance()->create(0)); + auto* prop = Propagator::Instance(); + + ClusterNativeAccess clusterIndex; + std::vector<TrackTPC>* tracks = nullptr; + std::vector<TPCClRefElem>* trackHitRefs = nullptr; + + TFile file(trackFile.Data()); + auto tree = (TTree*)file.Get("tpcrec"); + if (tree == nullptr) { + std::cout << "Error getting tree\n"; + return 1; + } + tree->SetBranchAddress("TPCTracks", &tracks); + tree->SetBranchAddress("ClusRefs", &trackHitRefs); + + ClusterNativeHelper::Reader tpcClusterReader{}; + tpcClusterReader.init(clusterFile.Data()); + std::unique_ptr<ClusterNative[]> clusterBuffer{}; + o2::tpc::ClusterNativeHelper::ConstMCLabelContainerViewWithBuffer clusterMCBuffer; + const size_t maxEvent = tree->GetEntriesFast(); + if (maxEvent != tpcClusterReader.getTreeSize()) { + std::cout << "Mismatch of entries in cluster and track file\n"; + return 1; + } + for (unsigned int iEvent = 0; iEvent < maxEvent; ++iEvent) { + std::cout << "Event " << iEvent << " of " << maxEvent << "\n"; + tree->GetEntry(iEvent); + memset(&clusterIndex, 0, sizeof(clusterIndex)); + tpcClusterReader.read(iEvent); + int retVal = tpcClusterReader.fillIndex(clusterIndex, clusterBuffer, clusterMCBuffer); + if (retVal < 0) { + std::cout << "Error reading clusters (code " << retVal << ")\n"; + return 1; + } + GPUTPCO2InterfaceRefit refit(&clusterIndex, trans.get(), bz, trackHitRefs->data(), nullptr, tracks, prop); + for (unsigned int i = 0; i < tracks->size(); i++) { + TrackTPC trk = (*tracks)[i]; + std::cout << "\nTrack " << i << "\n"; + trk.print(); + std::cout << "Refitting as GPU track\n"; + if (refit.RefitTrackAsGPU(trk, false, true)) { + std::cout << "Refit as GPU track failed\n"; + } else { + trk.print(); + } + trk = (*tracks)[i]; + std::cout << "Refitting as TrackParCov track\n"; + if (refit.RefitTrackAsTrackParCov(trk, false, true)) { + std::cout << "Refit as TrackParCov track failed\n"; + } else { + trk.print(); + } + } + } + + return 0; +} From b9b9fef658dfb9fc8ffad3dc8c5e9b62fa4505e0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 21 Oct 2020 16:16:29 +0200 Subject: [PATCH 1046/1751] GPU: Bugfix - don't marke clusters of rejected / copied tracks as shared --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 37b04407510ee..8d5fb8e0b824c 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -1815,10 +1815,13 @@ GPUd() void GPUTPCGMMerger::PrepareClustersForFit1(int nBlocks, int nThreads, in GPUAtomic(unsigned int)* sharedCount = (GPUAtomic(unsigned int)*)(trackSort + CAMath::nextMultipleOf<4>(mMemory->nOutputTracks)); for (unsigned int i = iBlock * nThreads + iThread; i < mMemory->nOutputTracks; i += nBlocks * nThreads) { mTrackOrderAttach[trackSort[i]] = i; - } - for (unsigned int i = iBlock * nThreads + iThread; i < mMemory->nOutputTrackClusters; i += nBlocks * nThreads) { - mClusterAttachment[mClusters[i].num] = attachAttached | attachGood; - CAMath::AtomicAdd(&sharedCount[mClusters[i].num], 1u); + const GPUTPCGMMergedTrack& trk = mOutputTracks[i]; + if (trk.OK()) { + for (unsigned int j = 0; j < trk.NClusters(); j++) { + mClusterAttachment[mClusters[trk.FirstClusterRef() + j].num] = attachAttached | attachGood; + CAMath::AtomicAdd(&sharedCount[mClusters[trk.FirstClusterRef() + j].num], 1u); + } + } } } From 264ea4fbac5c91e4ebccf9624a220acf5656f658 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 21 Oct 2020 16:40:18 +0200 Subject: [PATCH 1047/1751] TPC Workflow: Drop secondary legs of looping tracks by default --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 9 ++++++--- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 1 + GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 9ed493bf5ca88..74a2c58900a9a 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -33,6 +33,7 @@ #include "GPUO2InterfaceConfiguration.h" #include "GPUTPCGMMergedTrack.h" #include "GPUTPCGMMergedTrackHit.h" +#include "GPUTPCGMMergerTypes.h" #include "GPUHostDataTypes.h" #include <atomic> @@ -70,6 +71,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* } constexpr unsigned char flagsReject = GPUTPCGMMergedTrackHit::flagReject | GPUTPCGMMergedTrackHit::flagNotFit; + const unsigned int flagsRequired = mTrackingCAO2Interface->getConfig().configInterface.dropSecondaryLegs ? gputpcgmmergertypes::attachGoodLeg : 0; std::vector<TrackTPC>* outputTracks = data->outputTracks; std::vector<uint32_t>* outClusRefs = data->outputClusRefs; @@ -250,9 +252,10 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* outerPar.C[12], outerPar.C[13], outerPar.C[14]})); int nOutCl = 0; for (int j = 0; j < tracks[i].NClusters(); j++) { - if (!(trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject)) { - nOutCl++; + if ((trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) || (ptrs.mergedTrackHitAttachment[trackClusters[tracks[i].FirstClusterRef() + j].num] & flagsRequired) != flagsRequired) { + continue; } + nOutCl++; } clBuff = clusterOffsetCounter.fetch_add(nOutCl + (nOutCl + 1) / 2); oTrack.setClusterRef(clBuff, nOutCl); // register the references @@ -263,7 +266,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* std::vector<std::pair<MCCompLabel, unsigned int>> labels; nOutCl = 0; for (int j = 0; j < tracks[i].NClusters(); j++) { - if (trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) { + if ((trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) || (ptrs.mergedTrackHitAttachment[trackClusters[tracks[i].FirstClusterRef() + j].num] & flagsRequired) != flagsRequired) { continue; } int clusterIdGlobal = trackClusters[tracks[i].FirstClusterRef() + j].num; diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index e4dabd39d4287..e16378cc5f404 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -129,6 +129,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config processAttributes->outputBufferSize = confParam.outputBufferSize; processAttributes->suppressOutput = (confParam.dump == 2); config.configInterface.dumpEvents = confParam.dump; + config.configInterface.dropSecondaryLegs = confParam.dropSecondaryLegs; if (confParam.display) { #ifdef GPUCA_BUILD_EVENT_DISPLAY processAttributes->displayBackend.reset(new GPUDisplayBackendGlfw); diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 64ce92b709f03..6a64bc1e0b6be 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -272,6 +272,7 @@ AddOption(outputBufferSize, unsigned long, 200000000ul, "", 0, "Size of the outp AddOption(synchronousProcessing, bool, false, "", 0, "Apply performance shortcuts for synchronous processing, disable unneeded steps") AddOption(mutexMemReg, bool, false, "", 0, "Global mutex to serialize GPU memory registration") AddOption(display, bool, false, "", 0, "Enable standalone gpu tracking visualizaion") +AddOption(dropSecondaryLegs, bool, true, "", 0, "Do not store secondary legs of looping track in TrackTPC") EndConfig() #endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index 8f47fbdb304af..a80682c26944b 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -76,6 +76,7 @@ struct GPUO2InterfaceConfiguration { struct GPUInterfaceSettings { int dumpEvents = 0; bool outputToExternalBuffers = false; + bool dropSecondaryLegs = true; // These constants affect GPU memory allocation only and do not limit the CPU processing unsigned long maxTPCZS = 4096ul * 1024 * 1024; unsigned int maxTPCHits = 1024 * 1024 * 1024; From e769c265fc19f2f3d1e9e6effde4fca1ead56553 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 21 Oct 2020 16:51:11 +0200 Subject: [PATCH 1048/1751] GPU: Make fitInProjections in GPU refit configurable --- GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx | 5 +++++ GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h | 1 + GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 2 +- macro/runTPCRefit.C | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx index 83b6291d83ce9..1451fe016c8f2 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx @@ -49,4 +49,9 @@ GPUTPCO2InterfaceRefit::GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAcces mRefit.SetFastTransform(trans); } +void GPUTPCO2InterfaceRefit::setGPUTrackFitInProjections(bool v) +{ + mParam->rec.fitInProjections = v; +} + GPUTPCO2InterfaceRefit::~GPUTPCO2InterfaceRefit() = default; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index 56f6cd86a183b..e14902fc2e000 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -50,6 +50,7 @@ class GPUTPCO2InterfaceRefit int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, outward, resetCov); } int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, outward, resetCov); } + void setGPUTrackFitInProjections(bool v = true); private: GPUTrackingRefit mRefit; diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index e608b6383b214..9b22897da410e 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -62,7 +62,7 @@ void GPUTrackingRefit::initProp<GPUTPCGMPropagator>(GPUTPCGMPropagator& prop) prop.SetMaxSinPhi(GPUCA_MAX_SIN_PHI); prop.SetToyMCEventsFlag(false); prop.SetSeedingErrors(false); - prop.SetFitInProjections(false); + prop.SetFitInProjections(mPparam->rec.fitInProjections != 0); prop.SetPropagateBzOnly(false); prop.SetPolynomialField(&mPparam->polynomialField); } diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C index be087f338f597..cac0c09ee99f5 100644 --- a/macro/runTPCRefit.C +++ b/macro/runTPCRefit.C @@ -81,6 +81,7 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc return 1; } GPUTPCO2InterfaceRefit refit(&clusterIndex, trans.get(), bz, trackHitRefs->data(), nullptr, tracks, prop); + //refit.setGPUTrackFitInProjections(false); // Enable full 3D fit without assuming y and Z are uncorrelated for (unsigned int i = 0; i < tracks->size(); i++) { TrackTPC trk = (*tracks)[i]; std::cout << "\nTrack " << i << "\n"; From dbbeee13622221ce1514fe9f4adbfb37d708a5b9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 10:09:27 +0200 Subject: [PATCH 1049/1751] GPU: Split NormalizeAlpha and MoveToReference in extra functions and apply also during refit --- .../Interface/GPUO2InterfaceRefit.cxx | 6 ++---- .../Interface/GPUO2InterfaceRefit.h | 1 + GPU/GPUTracking/Merger/GPUTPCGMPropagator.h | 1 + GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 15 ++++++++------- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h | 9 +++++++++ GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 19 +++++++++++++++++++ macro/runTPCRefit.C | 12 ++++++++---- 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx index 1451fe016c8f2..e406532c81719 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx @@ -49,9 +49,7 @@ GPUTPCO2InterfaceRefit::GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAcces mRefit.SetFastTransform(trans); } -void GPUTPCO2InterfaceRefit::setGPUTrackFitInProjections(bool v) -{ - mParam->rec.fitInProjections = v; -} +void GPUTPCO2InterfaceRefit::setGPUTrackFitInProjections(bool v) { mParam->rec.fitInProjections = v; } +void GPUTPCO2InterfaceRefit::setTrackReferenceX(float v) { mParam->rec.TrackReferenceX = v; } GPUTPCO2InterfaceRefit::~GPUTPCO2InterfaceRefit() = default; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index e14902fc2e000..cbdd1dfe49d6a 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -51,6 +51,7 @@ class GPUTPCO2InterfaceRefit int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, outward, resetCov); } int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, outward, resetCov); } void setGPUTrackFitInProjections(bool v = true); + void setTrackReferenceX(float v); private: GPUTrackingRefit mRefit; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h index 4d12b1d289da7..97774efeaaf8b 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h @@ -130,6 +130,7 @@ class GPUTPCGMPropagator GPUd() void GetErr2(float& err2Y, float& err2Z, const GPUParam& param, float posZ, int iRow, short clusterState) const; GPUd() float GetAlpha() const { return mAlpha; } + GPUd() void SetAlpha(float v) { mAlpha = v; } GPUd() float GetQPt0() const { return mT0.GetQPt(); } GPUd() float GetSinPhi0() const { return mT0.GetSinPhi(); } GPUd() float GetCosPhi0() const { return mT0.GetCosPhi(); } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 00a685aafee8a..e6817a271339f 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -334,6 +334,14 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, dEdx.computedEdx(*dEdxOut, param); } Alpha = prop.GetAlpha(); + MoveToReference(prop, param, Alpha); + NormalizeAlpha(Alpha); + + return (ok); +} + +GPUd() void GPUTPCGMTrackParam::MoveToReference(GPUTPCGMPropagator& prop, const GPUParam& param, float& Alpha) +{ if (param.rec.TrackReferenceX <= 500) { for (int k = 0; k < 3; k++) // max 3 attempts { @@ -356,13 +364,6 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, ConstrainSinPhi(); Alpha += dAngle; } - if (Alpha > M_PI) { - Alpha -= 2 * M_PI; - } else if (Alpha <= -M_PI) { - Alpha += 2 * M_PI; - } - - return (ok); } GPUd() void GPUTPCGMTrackParam::MirrorTo(GPUTPCGMPropagator& GPUrestrict() prop, float toY, float toZ, bool inFlyDirection, const GPUParam& param, unsigned char row, unsigned char clusterState, bool mirrorParameters) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h index 756f012b7eac9..ad7c97388d249 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h @@ -148,6 +148,7 @@ class GPUTPCGMTrackParam GPUd() bool CheckCov() const; GPUd() bool Fit(const GPUTPCGMMerger* merger, int iTrk, GPUTPCGMMergedTrackHit* clusters, GPUTPCGMMergedTrackHitXYZ* clustersXYZ, int& N, int& NTolerated, float& Alpha, int attempt = 0, float maxSinPhi = GPUCA_MAX_SIN_PHI, GPUTPCOuterParam* outerParam = nullptr, GPUdEdxInfo* dEdxOut = nullptr); + GPUd() void MoveToReference(GPUTPCGMPropagator& prop, const GPUParam& param, float& alpha); GPUd() void MirrorTo(GPUTPCGMPropagator& prop, float toY, float toZ, bool inFlyDirection, const GPUParam& param, unsigned char row, unsigned char clusterState, bool mirrorParameters); GPUd() int MergeDoubleRowClusters(int& ihit, int wayDirection, GPUTPCGMMergedTrackHit* clusters, GPUTPCGMMergedTrackHitXYZ* clustersXYZ, const GPUTPCGMMerger* merger, GPUTPCGMPropagator& prop, float& xx, float& yy, float& zz, int maxN, float clAlpha, unsigned char& clusterState, bool rejectChi2); @@ -178,6 +179,14 @@ class GPUTPCGMTrackParam clusters[ihitFirst].state &= ~state; } } + GPUdi() static void NormalizeAlpha(float& alpha) + { + if (alpha > M_PI) { + alpha -= 2 * M_PI; + } else if (alpha <= -M_PI) { + alpha += 2 * M_PI; + } + } GPUd() bool Rotate(float alpha); GPUd() void ShiftZ(const GPUTPCGMMerger* merger, int slice, float tzInner, float tzOuter); diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 9b22897da410e..e90b7408147fa 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -30,6 +30,9 @@ using namespace o2::track; using namespace o2::base; using namespace o2::tpc; +static constexpr float kDeg2Rad = M_PI / 180.f; +static constexpr float kSectAngle = 2 * M_PI / 18.f; + void GPUTrackingRefitProcessor::InitializeProcessor() {} void GPUTrackingRefitProcessor::RegisterMemoryAllocation() @@ -293,6 +296,22 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } resetCov = false; } + if constexpr (std::is_same<S, GPUTPCGMTrackParam>::value) { + float alpha = prop.GetAlpha(); + trk.MoveToReference(prop, *mPparam, alpha); + trk.NormalizeAlpha(alpha); + prop.SetAlpha(alpha); + } else if constexpr (std::is_same<S, TrackParCov>::value) { + if (mPparam->rec.TrackReferenceX <= 500) { + if (prop->PropagateToXBxByBz(trk, mPparam->rec.TrackReferenceX)) { + if (CAMath::Abs(trk.getY()) > trk.getX() * CAMath::Tan(kSectAngle / 2.f)) { + float newAlpha = trk.getAlpha() + floor(CAMath::ATan2(trk.getY(), trk.getX()) / kDeg2Rad / 20.f + 0.5f) * kSectAngle; + GPUTPCGMTrackParam::NormalizeAlpha(newAlpha); + trk.rotate(newAlpha) && prop->PropagateToXBxByBz(trk, mPparam->rec.TrackReferenceX); + } + } + } + } convertTrack(trkX, trk, prop); return 0; diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C index cac0c09ee99f5..a072984162872 100644 --- a/macro/runTPCRefit.C +++ b/macro/runTPCRefit.C @@ -84,18 +84,22 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc //refit.setGPUTrackFitInProjections(false); // Enable full 3D fit without assuming y and Z are uncorrelated for (unsigned int i = 0; i < tracks->size(); i++) { TrackTPC trk = (*tracks)[i]; + refit.setTrackReferenceX(trk.getX()); std::cout << "\nTrack " << i << "\n"; + std::cout << "Org track:\n"; trk.print(); std::cout << "Refitting as GPU track\n"; - if (refit.RefitTrackAsGPU(trk, false, true)) { - std::cout << "Refit as GPU track failed\n"; + int retval = refit.RefitTrackAsGPU(trk, false, true); + if (retval) { + std::cout << "Refit as GPU track failed " << retval << "\n"; } else { trk.print(); } trk = (*tracks)[i]; std::cout << "Refitting as TrackParCov track\n"; - if (refit.RefitTrackAsTrackParCov(trk, false, true)) { - std::cout << "Refit as TrackParCov track failed\n"; + retval = refit.RefitTrackAsTrackParCov(trk, false, true); + if (retval) { + std::cout << "Refit as TrackParCov track failed " << retval << "\n"; } else { trk.print(); } From d8e83059314f6511b17f67a16dcc2c5d0b611ede Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 10:22:38 +0200 Subject: [PATCH 1050/1751] GPU: Refit returns number of hits used in the fit --- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 14 ++++++++------ macro/runTPCRefit.C | 6 ++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index e90b7408147fa..97beed51d7d81 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -196,6 +196,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) const ClusterNative* cl = nullptr; uint8_t sector, row, currentSector, currentRow; short clusterState, nextState; + int nFitted = 0; for (int i = start; i != stop; i += cl ? 0 : direction) { float x, y, z, charge; int clusters = 0; @@ -264,22 +265,22 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) if constexpr (std::is_same<S, GPUTPCGMTrackParam>::value) { if (prop.PropagateToXAlpha(x, mPparam->Alpha(currentSector), !outward)) { - return 2; + return -2; } if (resetCov) { trk.ResetCovariance(); } CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[0] - y, trk.Par()[1] - z, sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); if (prop.Update(y, z, row, *mPparam, clusterState, 0, nullptr, true)) { - return 3; + return -3; } CADEBUG(printf("\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[3], "", sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); } else if constexpr (std::is_same<S, TrackParCov>::value) { if (!trk.rotate(mPparam->Alpha(currentSector))) { - return 1; + return -1; } if (!prop->PropagateToXBxByBz(trk, x, o2::constants::physics::MassPionCharged, GPUCA_MAX_SIN_PHI_LOW)) { - return 2; + return -2; } if (resetCov) { trk.resetCovariance(); @@ -290,11 +291,12 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) mPparam->GetClusterErrors2(currentRow, z, getPar(trk)[2], getPar(trk)[3], c[0], c[2]); mPparam->UpdateClusterError2ByState(clusterState, c[0], c[2]); if (!trk.update(p, c)) { - return 3; + return -3; } CADEBUG(printf("\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[3], "", sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); } resetCov = false; + nFitted++; } if constexpr (std::is_same<S, GPUTPCGMTrackParam>::value) { float alpha = prop.GetAlpha(); @@ -314,7 +316,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } convertTrack(trkX, trk, prop); - return 0; + return nFitted; } template GPUd() int GPUTrackingRefit::RefitTrack<GPUTPCGMMergedTrack, TrackParCov>(GPUTPCGMMergedTrack& trk, bool outward, bool resetCov); diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C index a072984162872..97a5de86cad10 100644 --- a/macro/runTPCRefit.C +++ b/macro/runTPCRefit.C @@ -90,17 +90,19 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc trk.print(); std::cout << "Refitting as GPU track\n"; int retval = refit.RefitTrackAsGPU(trk, false, true); - if (retval) { + if (retval < 0) { std::cout << "Refit as GPU track failed " << retval << "\n"; } else { + std::cout << "Succeeded using " << retval << " hits\n"; trk.print(); } trk = (*tracks)[i]; std::cout << "Refitting as TrackParCov track\n"; retval = refit.RefitTrackAsTrackParCov(trk, false, true); - if (retval) { + if (retval < 0) { std::cout << "Refit as TrackParCov track failed " << retval << "\n"; } else { + std::cout << "Succeeded using " << retval << " hits\n"; trk.print(); } } From 6888679c6857885d865847853fff176fcf08accd Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 10:52:47 +0200 Subject: [PATCH 1051/1751] Unify default values into constexpr constants --- .../Base/include/DetectorsBase/Propagator.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index fad54c7a387e7..861d0f2810ef4 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -56,39 +56,42 @@ class Propagator return &instance; } + static constexpr float MAX_SIN_PHI = 0.85f; + static constexpr float MAX_STEP = 2.0f; + bool PropagateToXBxByBz(o2::track::TrackParCov& track, float x, float mass = o2::constants::physics::MassPionCharged, - float maxSnp = 0.85, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; bool PropagateToXBxByBz(o2::track::TrackPar& track, float x, float mass = o2::constants::physics::MassPionCharged, - float maxSnp = 0.85, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; bool propagateToX(o2::track::TrackParCov& track, float x, float bZ, float mass = o2::constants::physics::MassPionCharged, - float maxSnp = 0.85, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; bool propagateToX(o2::track::TrackPar& track, float x, float bZ, float mass = o2::constants::physics::MassPionCharged, - float maxSnp = 0.85, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; bool propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, - float mass = o2::constants::physics::MassPionCharged, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; bool propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, - float mass = o2::constants::physics::MassPionCharged, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; bool propagateToDCA(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, - float mass = o2::constants::physics::MassPionCharged, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; bool propagateToDCABxByBz(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, - float mass = o2::constants::physics::MassPionCharged, float maxStep = 2.0, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; From dc91b465b1cd2fe8e9021c18b5ed6383eb72bfe6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 11:00:43 +0200 Subject: [PATCH 1052/1751] GPU: Add option to refit (enabled by default) to ignore errors at high incl. angle / etc. --- GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h | 1 + GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 17 +++++++++++++++++ GPU/GPUTracking/Refit/GPUTrackingRefit.h | 2 ++ 3 files changed, 20 insertions(+) diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index cbdd1dfe49d6a..29c060c1f3410 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -52,6 +52,7 @@ class GPUTPCO2InterfaceRefit int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, outward, resetCov); } void setGPUTrackFitInProjections(bool v = true); void setTrackReferenceX(float v); + void setIgnoreErrorsAtTrackEnds(bool v) { mRefit.mIgnoreErrorsOnTrackEnds = v; } private: GPUTrackingRefit mRefit; diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 97beed51d7d81..0384aa040ef79 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -32,6 +32,18 @@ using namespace o2::tpc; static constexpr float kDeg2Rad = M_PI / 180.f; static constexpr float kSectAngle = 2 * M_PI / 18.f; +static constexpr int kIGNORE_ENDS = 3; + +#define IgnoreErrors(SNP) \ + if (mIgnoreErrorsOnTrackEnds) { \ + if (abs(i - stop) <= kIGNORE_ENDS && (CAMath::Abs(SNP) >= Propagator::MAX_SIN_PHI || abs(start - stop) < 30)) { \ + break; \ + } \ + if (abs(i - start) <= kIGNORE_ENDS && (CAMath::Abs(SNP) >= Propagator::MAX_SIN_PHI || abs(start - stop) < 30)) { \ + continue; \ + } \ + } +// End IgnoreErrors void GPUTrackingRefitProcessor::InitializeProcessor() {} @@ -265,6 +277,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) if constexpr (std::is_same<S, GPUTPCGMTrackParam>::value) { if (prop.PropagateToXAlpha(x, mPparam->Alpha(currentSector), !outward)) { + IgnoreErrors(trk.GetSinPhi()); return -2; } if (resetCov) { @@ -272,14 +285,17 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[0] - y, trk.Par()[1] - z, sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); if (prop.Update(y, z, row, *mPparam, clusterState, 0, nullptr, true)) { + IgnoreErrors(trk.GetSinPhi()); return -3; } CADEBUG(printf("\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[3], "", sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); } else if constexpr (std::is_same<S, TrackParCov>::value) { if (!trk.rotate(mPparam->Alpha(currentSector))) { + IgnoreErrors(trk.getSnp()); return -1; } if (!prop->PropagateToXBxByBz(trk, x, o2::constants::physics::MassPionCharged, GPUCA_MAX_SIN_PHI_LOW)) { + IgnoreErrors(trk.getSnp()); return -2; } if (resetCov) { @@ -291,6 +307,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) mPparam->GetClusterErrors2(currentRow, z, getPar(trk)[2], getPar(trk)[3], c[0], c[2]); mPparam->UpdateClusterError2ByState(clusterState, c[0], c[2]); if (!trk.update(p, c)) { + IgnoreErrors(trk.getSnp()); return -3; } CADEBUG(printf("\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[3], "", sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.h b/GPU/GPUTracking/Refit/GPUTrackingRefit.h index dea18446a72ca..0d657f0ce3b34 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.h +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.h @@ -69,6 +69,8 @@ class GPUTrackingRefit GPUd() int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return RefitTrack<o2::tpc::TrackTPC, GPUTPCGMTrackParam>(trk, outward, resetCov); } GPUd() int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return RefitTrack<o2::tpc::TrackTPC, o2::track::TrackParCov>(trk, outward, resetCov); } + bool mIgnoreErrorsOnTrackEnds = true; // Ignore errors during propagation / update at the beginning / end of tracks for short tracks / tracks with high incl. angle + private: const unsigned char* mPclusterState = nullptr; // Ptr to shared cluster state const o2::base::Propagator* mPpropagator = nullptr; // Ptr to propagator for TrackParCov track model From 72a6f92055fd50ad157b78804f5c9cc2bc518595 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 13:51:06 +0200 Subject: [PATCH 1053/1751] Add interface to fetch cluster from external reference --- .../TPC/include/DataFormatsTPC/TrackTPC.h | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h index 2369b2e76cad8..d26d00b979ff6 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h @@ -74,36 +74,50 @@ class TrackTPC : public o2::track::TrackParCov void setClusterRef(uint32_t entry, uint16_t ncl) { mClustersReference.set(entry, ncl); } template <class T> - void getClusterReference(T& clinfo, int nCluster, - uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex) const + static inline void getClusterReference(T& clinfo, int nCluster, + uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex, const ClusRef& ref) { - // data for given tracks starts at clinfo[ mClustersReference.getFirstEntry() ], - // 1st mClustersReference.getEntries() cluster indices are stored as uint32_t + // data for given tracks starts at clinfo[ ref.getFirstEntry() ], + // 1st ref.getEntries() cluster indices are stored as uint32_t // then sector indices as uint8_t, then row indices ar uin8_t - // const uint32_t* clIndArr = &clinfo[ mClustersReference.getFirstEntry() ]; - const uint32_t* clIndArr = reinterpret_cast<const uint32_t*>(&clinfo[mClustersReference.getFirstEntry()]); // TODO remove this trick + // const uint32_t* clIndArr = &clinfo[ ref.getFirstEntry() ]; + const uint32_t* clIndArr = reinterpret_cast<const uint32_t*>(&clinfo[ref.getFirstEntry()]); // TODO remove this trick clusterIndex = clIndArr[nCluster]; - const uint8_t* srIndexArr = reinterpret_cast<const uint8_t*>(clIndArr + mClustersReference.getEntries()); + const uint8_t* srIndexArr = reinterpret_cast<const uint8_t*>(clIndArr + ref.getEntries()); sectorIndex = srIndexArr[nCluster]; - rowIndex = srIndexArr[nCluster + mClustersReference.getEntries()]; + rowIndex = srIndexArr[nCluster + ref.getEntries()]; } template <class T> - const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, - const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex) const + inline void getClusterReference(T& clinfo, int nCluster, + uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex) const + { + getClusterReference<T>(clinfo, nCluster, sectorIndex, rowIndex, clusterIndex, mClustersReference); + } + + template <class T> + static inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, + const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex, const ClusRef& ref) { uint32_t clusterIndex; - getClusterReference(clinfo, nCluster, sectorIndex, rowIndex, clusterIndex); + getClusterReference<T>(clinfo, nCluster, sectorIndex, rowIndex, clusterIndex, ref); return (clusters.clusters[sectorIndex][rowIndex][clusterIndex]); } template <class T> - const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, - const o2::tpc::ClusterNativeAccess& clusters) const + inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, + const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex) const + { + return getCluster<T>(clinfo, nCluster, clusters, sectorIndex, rowIndex, mClustersReference); + } + + template <class T> + inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, + const o2::tpc::ClusterNativeAccess& clusters) const { uint8_t sectorIndex, rowIndex; - return (getCluster(clinfo, nCluster, clusters, sectorIndex, rowIndex)); + return (getCluster<T>(clinfo, nCluster, clusters, sectorIndex, rowIndex)); } const dEdxInfo& getdEdx() const { return mdEdx; } From df114769ccba835521f4747007a702cd7a6d8936 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 13:51:41 +0200 Subject: [PATCH 1054/1751] GPU: Add Interface to refit with input as TrackParCov + req. parameters --- .../Interface/GPUO2InterfaceRefit.h | 2 + GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 78 ++++++++++++++----- GPU/GPUTracking/Refit/GPUTrackingRefit.h | 24 ++++-- macro/runTPCRefit.C | 11 +++ 4 files changed, 92 insertions(+), 23 deletions(-) diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index 29c060c1f3410..8a09506c5b906 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -50,6 +50,8 @@ class GPUTPCO2InterfaceRefit int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, outward, resetCov); } int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, outward, resetCov); } + int RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, clusRef, time0, outward, resetCov); } + int RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, clusRef, time0, outward, resetCov); } void setGPUTrackFitInProjections(bool v = true); void setTrackReferenceX(float v); void setIgnoreErrorsAtTrackEnds(bool v) { mRefit.mIgnoreErrorsOnTrackEnds = v; } diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 0384aa040ef79..6b21d8363bb99 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -113,13 +113,21 @@ static void convertTrackParam(TrackParCov& trk, const GPUTPCGMTrackParam& trkX) } trk.setX(trkX.GetX()); } +// Generic template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, TrackParCov, const Propagator*>(GPUTPCGMMergedTrack& trk, const TrackParCov& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackParCov& trkX, GPUTPCGMPropagator& prop) { - convertTrackParam(trk.Param(), trkX); - trk.SetAlpha(trkX.getAlpha()); + convertTrackParam(trk, trkX); + prop.SetTrack(&trk, trkX.getAlpha()); } template <> +void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackParCov& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +{ + convertTrackParam(trk, trkX); + trk.setAlpha(prop.GetAlpha()); +} +// GPUTPCGMMergedTrack input +template <> void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Propagator*>(TrackParCov& trk, const GPUTPCGMMergedTrack& trkX, const Propagator*& prop) { initProp(prop); @@ -127,16 +135,10 @@ void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Prop trk.setAlpha(trkX.GetAlpha()); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackParCov& trkX, GPUTPCGMPropagator& prop) -{ - convertTrackParam(trk, trkX); - prop.SetTrack(&trk, trkX.getAlpha()); -} -template <> -void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackParCov& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, TrackParCov, const Propagator*>(GPUTPCGMMergedTrack& trk, const TrackParCov& trkX, const Propagator*& prop) { - convertTrackParam(trk, trkX); - trk.setAlpha(prop.GetAlpha()); + convertTrackParam(trk.Param(), trkX); + trk.SetAlpha(trkX.getAlpha()); } template <> void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTPCGMMergedTrack, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTPCGMMergedTrack& trkX, GPUTPCGMPropagator& prop) @@ -151,6 +153,18 @@ void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam, GPU trk.SetParam(trkX); trk.SetAlpha(prop.GetAlpha()); } +// TrackTPC input +template <> +void GPUTrackingRefit::convertTrack<TrackParCov, TrackTPC, const Propagator*>(TrackParCov& trk, const TrackTPC& trkX, const Propagator*& prop) +{ + initProp(prop); + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); +} +template <> +void GPUTrackingRefit::convertTrack<TrackTPC, TrackParCov, const Propagator*>(TrackTPC& trk, const TrackParCov& trkX, const Propagator*& prop) +{ + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); +} template <> void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackTPC, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackTPC& trkX, GPUTPCGMPropagator& prop) { @@ -160,20 +174,32 @@ void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackTPC, GPUTPCGMPropag template <> void GPUTrackingRefit::convertTrack<TrackTPC, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackTPC& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) { - initProp(prop); convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk, trkX, prop); } +// TrackParCovWithArgs input template <> -void GPUTrackingRefit::convertTrack<TrackTPC, TrackParCov, const Propagator*>(TrackTPC& trk, const TrackParCov& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<TrackParCov, GPUTrackingRefit::TrackParCovWithArgs, const Propagator*>(TrackParCov& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, const Propagator*& prop) { - convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); + initProp(prop); + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX.trk, prop); } template <> -void GPUTrackingRefit::convertTrack<TrackParCov, TrackTPC, const Propagator*>(TrackParCov& trk, const TrackTPC& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, TrackParCov, const Propagator*>(GPUTrackingRefit::TrackParCovWithArgs& trk, const TrackParCov& trkX, const Propagator*& prop) +{ + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk.trk, trkX, prop); +} +template <> +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, GPUTPCGMPropagator& prop) { initProp(prop); - convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); + convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX.trk, prop); } +template <> +void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTrackingRefit::TrackParCovWithArgs& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +{ + convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk.trk, trkX, prop); +} + static const float* getPar(const GPUTPCGMTrackParam& trk) { return trk.GetPar(); } static const float* getPar(const TrackParCov& trk) { return trk.getParams(); } @@ -201,6 +227,11 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } else if constexpr (std::is_same<T, TrackTPC>::value) { count = trkX.getNClusters(); tOffset = trkX.getTime0(); + } else if constexpr (std::is_same<T, TrackParCovWithArgs>::value) { + count = trkX.clusRef.getEntries(); + tOffset = trkX.time0; + } else { + static_assert("Invalid template"); } int direction = outward ? -1 : 1; int start = outward ? count - 1 : begin; @@ -232,6 +263,11 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } else if constexpr (std::is_same<T, TrackTPC>::value) { cl = &trkX.getCluster(mPtrackHitReferences, i, *mPclusterNative, sector, row); nextState = mPclusterState[cl - mPclusterNative->clustersLinear]; + } else if constexpr (std::is_same<T, TrackParCovWithArgs>::value) { + cl = &TrackTPC::getCluster(mPtrackHitReferences, i, *mPclusterNative, sector, row, trkX.clusRef); + nextState = mPclusterState[cl - mPclusterNative->clustersLinear]; + } else { + static_assert("Invalid template"); } } if (clusters == 0 || (row == currentRow && sector == currentSector)) { @@ -311,6 +347,8 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) return -3; } CADEBUG(printf("\t%21sFit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[3], "", sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); + } else { + static_assert("Invalid template"); } resetCov = false; nFitted++; @@ -330,6 +368,8 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } } } + } else { + static_assert("Invalid template"); } convertTrack(trkX, trk, prop); @@ -337,9 +377,11 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } template GPUd() int GPUTrackingRefit::RefitTrack<GPUTPCGMMergedTrack, TrackParCov>(GPUTPCGMMergedTrack& trk, bool outward, bool resetCov); -template GPUd() int GPUTrackingRefit::RefitTrack<TrackTPC, TrackParCov>(TrackTPC& trk, bool outward, bool resetCov); template GPUd() int GPUTrackingRefit::RefitTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam>(GPUTPCGMMergedTrack& trk, bool outward, bool resetCov); +template GPUd() int GPUTrackingRefit::RefitTrack<TrackTPC, TrackParCov>(TrackTPC& trk, bool outward, bool resetCov); template GPUd() int GPUTrackingRefit::RefitTrack<TrackTPC, GPUTPCGMTrackParam>(TrackTPC& trk, bool outward, bool resetCov); +template GPUd() int GPUTrackingRefit::RefitTrack<GPUTrackingRefit::TrackParCovWithArgs, TrackParCov>(GPUTrackingRefit::TrackParCovWithArgs& trk, bool outward, bool resetCov); +template GPUd() int GPUTrackingRefit::RefitTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMTrackParam>(GPUTrackingRefit::TrackParCovWithArgs& trk, bool outward, bool resetCov); void GPUTrackingRefit::SetPtrsFromGPUConstantMem(const GPUConstantMem* v) { diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.h b/GPU/GPUTracking/Refit/GPUTrackingRefit.h index 0d657f0ce3b34..2d619e8392e17 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.h +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.h @@ -16,6 +16,7 @@ #include "GPUDef.h" #include "GPUProcessor.h" +#include <tuple> namespace o2::dataformats { @@ -39,9 +40,7 @@ class TrackTPC; using TrackTPCClusRef = o2::dataformats::RangeReference<uint32_t, uint16_t>; } // namespace o2::tpc -namespace GPUCA_NAMESPACE -{ -namespace gpu +namespace o2::gpu { class GPUTPCGMTrackParam; class GPUTPCGMMergedTrack; @@ -69,6 +68,22 @@ class GPUTrackingRefit GPUd() int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return RefitTrack<o2::tpc::TrackTPC, GPUTPCGMTrackParam>(trk, outward, resetCov); } GPUd() int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return RefitTrack<o2::tpc::TrackTPC, o2::track::TrackParCov>(trk, outward, resetCov); } + struct TrackParCovWithArgs { + o2::track::TrackParCov& trk; + const o2::tpc::TrackTPCClusRef& clusRef; + float time0; + }; + GPUd() int RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) + { + TrackParCovWithArgs x{trk, clusRef, time0}; + return RefitTrack<TrackParCovWithArgs, GPUTPCGMTrackParam>(x, outward, resetCov); + } + GPUd() int RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) + { + TrackParCovWithArgs x{trk, clusRef, time0}; + return RefitTrack<TrackParCovWithArgs, o2::track::TrackParCov>(x, outward, resetCov); + } + bool mIgnoreErrorsOnTrackEnds = true; // Ignore errors during propagation / update at the beginning / end of tracks for short tracks / tracks with high incl. angle private: @@ -97,7 +112,6 @@ class GPUTrackingRefitProcessor : public GPUTrackingRefit, public GPUProcessor #endif }; -} // namespace gpu -} // namespace GPUCA_NAMESPACE +} // namespace o2::gpu #endif diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C index 97a5de86cad10..7c98bf300377e 100644 --- a/macro/runTPCRefit.C +++ b/macro/runTPCRefit.C @@ -37,6 +37,7 @@ using namespace o2::gpu; using namespace o2::tpc; using namespace o2::dataformats; using namespace o2::base; +using namespace o2::track; using namespace std; int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc-native-clusters.root") @@ -105,6 +106,16 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc std::cout << "Succeeded using " << retval << " hits\n"; trk.print(); } + trk = (*tracks)[i]; + TrackParCov trkX = trk; + std::cout << "Refitting as TrackParCov track with TrackParCov input\n"; + retval = refit.RefitTrackAsTrackParCov(trkX, trk.getClusterRef(), trk.getTime0(), false, true); + if (retval < 0) { + std::cout << "Refit as TrackParCov track failed " << retval << "\n"; + } else { + std::cout << "Succeeded using " << retval << " hits\n"; + trkX.print(); + } } } From 6a5e248d45ec6c75c0105fecdbae240a3453f77e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 22:31:24 +0200 Subject: [PATCH 1055/1751] Hide std::tuple compilation from GPU --- Common/MathUtils/include/MathUtils/Utils.h | 42 +++++++++---------- .../include/MathUtils/detail/Bracket.h | 2 +- .../MathUtils/detail/StatAccumulator.h | 4 ++ .../include/MathUtils/detail/bitOps.h | 2 + .../include/MathUtils/detail/trigonometric.h | 24 +++++------ 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index 7e4b8e8bedd13..52bf7ff22a8a1 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -114,57 +114,57 @@ GPUdi() void sincosd(double ang, double& s, double& c) detail::sincos(ang, s, c); } -GPUdi() std::tuple<float, float> sincos(float ang) +#ifndef GPUCA_GPUCODE_DEVICE +inline void rotateZ(float xL, float yL, float& xG, float& yG, float snAlp, float csAlp) { - return detail::sincos<float>(ang); + return detail::rotateZ<float>(xL, yL, xG, yG, snAlp, csAlp); } -GPUdi() std::tuple<double, double> sincosd(double ang) +inline void rotateZd(double xL, double yL, double& xG, double& yG, double snAlp, double csAlp) { - return detail::sincos<double>(ang); + return detail::rotateZ<double>(xL, yL, xG, yG, snAlp, csAlp); } -inline std::tuple<float, float> rotateZ(float xL, float yL, float snAlp, float csAlp) +inline void rotateZInv(float xG, float yG, float& xL, float& yL, float snAlp, float csAlp) { - return detail::rotateZ<float>(xL, yL, snAlp, csAlp); + detail::rotateZInv<float>(xG, yG, xL, yL, snAlp, csAlp); } -inline std::tuple<double, double> rotateZd(double xL, double yL, double snAlp, double csAlp) +inline void rotateZInvd(double xG, double yG, double& xL, double& yL, double snAlp, double csAlp) { - return detail::rotateZ<double>(xL, yL, snAlp, csAlp); + detail::rotateZInv<double>(xG, yG, xL, yL, snAlp, csAlp); } -inline void rotateZ(float xL, float yL, float& xG, float& yG, float snAlp, float csAlp) +inline std::tuple<float, float> rotateZInv(float xG, float yG, float snAlp, float csAlp) { - return detail::rotateZ<float>(xL, yL, xG, yG, snAlp, csAlp); + return detail::rotateZInv<float>(xG, yG, snAlp, csAlp); } -inline void rotateZd(double xL, double yL, double& xG, double& yG, double snAlp, double csAlp) +inline std::tuple<double, double> rotateZInvd(double xG, double yG, double snAlp, double csAlp) { - return detail::rotateZ<double>(xL, yL, xG, yG, snAlp, csAlp); + return detail::rotateZInv<double>(xG, yG, snAlp, csAlp); } -inline std::tuple<float, float> rotateZInv(float xG, float yG, float snAlp, float csAlp) +GPUdi() std::tuple<float, float> sincos(float ang) { - return detail::rotateZInv<float>(xG, yG, snAlp, csAlp); + return detail::sincos<float>(ang); } -inline std::tuple<double, double> rotateZInvd(double xG, double yG, double snAlp, double csAlp) +GPUdi() std::tuple<double, double> sincosd(double ang) { - return detail::rotateZInv<double>(xG, yG, snAlp, csAlp); + return detail::sincos<double>(ang); } -inline void rotateZInv(float xG, float yG, float& xL, float& yL, float snAlp, float csAlp) +inline std::tuple<float, float> rotateZ(float xL, float yL, float snAlp, float csAlp) { - detail::rotateZInv<float>(xG, yG, xL, yL, snAlp, csAlp); + return detail::rotateZ<float>(xL, yL, snAlp, csAlp); } -inline void rotateZInvd(double xG, double yG, double& xL, double& yL, double snAlp, double csAlp) +inline std::tuple<double, double> rotateZd(double xL, double yL, double snAlp, double csAlp) { - detail::rotateZInv<double>(xG, yG, xL, yL, snAlp, csAlp); + return detail::rotateZ<double>(xL, yL, snAlp, csAlp); } -#ifndef GPUCA_GPUCODE_DEVICE inline void rotateZ(std::array<float, 3>& xy, float alpha) { detail::rotateZ<float>(xy, alpha); diff --git a/Common/MathUtils/include/MathUtils/detail/Bracket.h b/Common/MathUtils/include/MathUtils/detail/Bracket.h index 2cae7c61e2c7d..28c0f505ae13d 100644 --- a/Common/MathUtils/include/MathUtils/detail/Bracket.h +++ b/Common/MathUtils/include/MathUtils/detail/Bracket.h @@ -15,7 +15,7 @@ #ifndef ALICEO2_BRACKET_H #define ALICEO2_BRACKET_H -#include <Rtypes.h> +#include <GPUCommonRtypes.h> namespace o2 { diff --git a/Common/MathUtils/include/MathUtils/detail/StatAccumulator.h b/Common/MathUtils/include/MathUtils/detail/StatAccumulator.h index 2995f30358b7a..5ec3781de0d6d 100644 --- a/Common/MathUtils/include/MathUtils/detail/StatAccumulator.h +++ b/Common/MathUtils/include/MathUtils/detail/StatAccumulator.h @@ -15,7 +15,9 @@ #ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_STATACCUMULATOR_H_ #define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_STATACCUMULATOR_H_ +#ifndef GPUCA_GPUCODE_DEVICE #include <tuple> +#endif namespace o2 { @@ -41,6 +43,7 @@ struct StatAccumulator { } double getMean() const { return wsum > 0. ? sum / wsum : 0.; } +#ifndef GPUCA_GPUCODE_DEVICE template <typename T = float> std::tuple<T, T> getMeanRMS2() const { @@ -55,6 +58,7 @@ struct StatAccumulator { return {mean, rms2}; } +#endif StatAccumulator& operator+=(const StatAccumulator& other) { diff --git a/Common/MathUtils/include/MathUtils/detail/bitOps.h b/Common/MathUtils/include/MathUtils/detail/bitOps.h index 1603b74ffde65..d272069baa660 100644 --- a/Common/MathUtils/include/MathUtils/detail/bitOps.h +++ b/Common/MathUtils/include/MathUtils/detail/bitOps.h @@ -15,7 +15,9 @@ #ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_BITOPS_H_ #define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_BITOPS_H_ +#ifndef GPUCA_GPUCODE_DEVICE #include <cstdint> +#endif namespace o2 { diff --git a/Common/MathUtils/include/MathUtils/detail/trigonometric.h b/Common/MathUtils/include/MathUtils/detail/trigonometric.h index 20e9d335948d9..d689de575610d 100644 --- a/Common/MathUtils/include/MathUtils/detail/trigonometric.h +++ b/Common/MathUtils/include/MathUtils/detail/trigonometric.h @@ -18,11 +18,11 @@ #ifndef GPUCA_GPUCODE_DEVICE #include <array> #include <cmath> +#include <tuple> #endif #include "GPUCommonDef.h" #include "GPUCommonMath.h" #include "CommonConstants/MathConstants.h" -#include <tuple> namespace o2 { @@ -117,6 +117,8 @@ GPUdi() void sincos(double ang, double& s, double& c) o2::gpu::GPUCommonMath::SinCos(ang, s, c); } +#ifndef GPUCA_GPUCODE_DEVICE + template <typename T> GPUdi() std::tuple<T, T> sincos(T ang) { @@ -133,12 +135,6 @@ inline std::tuple<T, T> rotateZ(T xL, T yL, T snAlp, T csAlp) return std::make_tuple(xL * csAlp - yL * snAlp, xL * snAlp + yL * csAlp); } -template <typename T> -inline void rotateZ(T xL, T yL, T& xG, T& yG, T snAlp, T csAlp) -{ - std::tie(xG, yG) = rotateZ<T>(xL, yL, snAlp, csAlp); -} - template <typename T> inline std::tuple<T, T> rotateZInv(T xG, T yG, T snAlp, T csAlp) { @@ -147,14 +143,11 @@ inline std::tuple<T, T> rotateZInv(T xG, T yG, T snAlp, T csAlp) } template <typename T> -inline void rotateZInv(T xG, T yG, T& xL, T& yL, T snAlp, T csAlp) +inline void rotateZ(T xL, T yL, T& xG, T& yG, T snAlp, T csAlp) { - // inverse 2D rotation of the point by angle alpha (global to local) - rotateZ<T>(xG, yG, xL, yL, -snAlp, csAlp); + std::tie(xG, yG) = rotateZ<T>(xL, yL, snAlp, csAlp); } -#ifndef GPUCA_GPUCODE_DEVICE - template <typename T> inline void rotateZ(std::array<T, 3>& xy, T alpha) { @@ -165,6 +158,13 @@ inline void rotateZ(std::array<T, 3>& xy, T alpha) xy[1] = x * sin + xy[1] * cos; } +template <typename T> +inline void rotateZInv(T xG, T yG, T& xL, T& yL, T snAlp, T csAlp) +{ + // inverse 2D rotation of the point by angle alpha (global to local) + rotateZ<T>(xG, yG, xL, yL, -snAlp, csAlp); +} + #endif template <typename T> From 14851f87b3a8bc708fb0742cf9ed2d4c2f148f7a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Sep 2020 22:47:33 +0200 Subject: [PATCH 1056/1751] GPU: Allow usage of unsigned short/half instead of float to store charges used for dEdx computation --- GPU/Common/GPUDefGPUParameters.h | 3 +++ GPU/GPUTracking/dEdx/GPUdEdx.cxx | 4 ++-- GPU/GPUTracking/dEdx/GPUdEdx.h | 34 +++++++++++++++++++++++++------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index ee4d5f0f920cf..a3f3277ed33c1 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -351,6 +351,9 @@ #define GPUCA_THREAD_COUNT_FINDER 1 #define GPUCA_COMP_GATHER_KERNEL 0 #endif +#ifndef GPUCA_DEDX_STORAGE_TYPE +#define GPUCA_DEDX_STORAGE_TYPE float +#endif #ifndef GPUCA_WARP_SIZE #ifdef GPUCA_GPUCODE diff --git a/GPU/GPUTracking/dEdx/GPUdEdx.cxx b/GPU/GPUTracking/dEdx/GPUdEdx.cxx index 5443b36456ff0..571e940aea59d 100644 --- a/GPU/GPUTracking/dEdx/GPUdEdx.cxx +++ b/GPU/GPUTracking/dEdx/GPUdEdx.cxx @@ -52,7 +52,7 @@ GPUd() void GPUdEdx::computedEdx(GPUdEdxInfo& GPUrestrict() output, const GPUPar output.NHitsSubThresholdOROC3 = countOROC3; } -GPUd() float GPUdEdx::GetSortTruncMean(float* GPUrestrict() array, int count, int trunclow, int trunchigh) +GPUd() float GPUdEdx::GetSortTruncMean(GPUCA_DEDX_STORAGE_TYPE* GPUrestrict() array, int count, int trunclow, int trunchigh) { trunclow = count * trunclow / 128; trunchigh = count * trunchigh / 128; @@ -62,7 +62,7 @@ GPUd() float GPUdEdx::GetSortTruncMean(float* GPUrestrict() array, int count, in CAAlgo::sort(array, array + count); float mean = 0; for (int i = trunclow; i < trunchigh; i++) { - mean += array[i]; + mean += array[i] * (1.f / scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::factor); } return (mean / (trunchigh - trunclow)); } diff --git a/GPU/GPUTracking/dEdx/GPUdEdx.h b/GPU/GPUTracking/dEdx/GPUdEdx.h index d48eabc8995b5..63a2f1f002b9d 100644 --- a/GPU/GPUTracking/dEdx/GPUdEdx.h +++ b/GPU/GPUTracking/dEdx/GPUdEdx.h @@ -50,13 +50,33 @@ class GPUdEdx GPUd() void computedEdx(GPUdEdxInfo& output, const GPUParam& param); private: - GPUd() float GetSortTruncMean(float* array, int count, int trunclow, int trunchigh); + GPUd() float GetSortTruncMean(GPUCA_DEDX_STORAGE_TYPE* array, int count, int trunclow, int trunchigh); GPUd() void checkSubThresh(int roc); + template <typename T, typename fake = void> + struct scalingFactor; + template <typename fake> + struct scalingFactor<unsigned short, fake> { + static constexpr float factor = 4.f; + static constexpr float round = 0.5f; + }; + template <typename fake> + struct scalingFactor<float, fake> { + static constexpr float factor = 1.f; + static constexpr float round = 0.f; + }; +#if defined(__CUDACC__) || defined(__HIPCC__) + template <typename fake> + struct scalingFactor<half, fake> { + static constexpr float factor = 1.f; + static constexpr float round = 0.f; + }; +#endif + static constexpr int MAX_NCL = GPUCA_ROW_COUNT; // Must fit in mNClsROC (unsigned char)! - float mChargeTot[MAX_NCL]; // No need for default, just some memory - float mChargeMax[MAX_NCL]; // No need for default, just some memory + GPUCA_DEDX_STORAGE_TYPE mChargeTot[MAX_NCL]; // No need for default, just some memory + GPUCA_DEDX_STORAGE_TYPE mChargeMax[MAX_NCL]; // No need for default, just some memory float mSubThreshMinTot = 0.f; float mSubThreshMinMax = 0.f; unsigned char mNClsROC[4] = {0}; @@ -71,8 +91,8 @@ GPUdi() void GPUdEdx::checkSubThresh(int roc) if (roc != mLastROC) { if (mNSubThresh && mCount + mNSubThresh <= MAX_NCL) { for (int i = 0; i < mNSubThresh; i++) { - mChargeTot[mCount] = mSubThreshMinTot; - mChargeMax[mCount++] = mSubThreshMinMax; + mChargeTot[mCount] = (GPUCA_DEDX_STORAGE_TYPE)(mSubThreshMinTot * scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::factor + scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::round); + mChargeMax[mCount++] = (GPUCA_DEDX_STORAGE_TYPE)(mSubThreshMinMax * scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::factor + scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::round); } mNClsROC[mLastROC] += mNSubThresh; mNClsROCSubThresh[mLastROC] += mNSubThresh; @@ -118,8 +138,8 @@ GPUdnii() void GPUdEdx::fillCluster(float qtot, float qmax, int padRow, float tr qmax /= qMaxCorr; qtot /= qTotCorr; - mChargeTot[mCount] = qtot; - mChargeMax[mCount++] = qmax; + mChargeTot[mCount] = (GPUCA_DEDX_STORAGE_TYPE)(qtot * scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::factor + scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::round); + mChargeMax[mCount++] = (GPUCA_DEDX_STORAGE_TYPE)(qmax * scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::factor + scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::round); mNClsROC[roc]++; if (qtot < mSubThreshMinTot) { mSubThreshMinTot = qtot; From 661ac8950bf9daf0ba96d14f338a2faab0cbedd1 Mon Sep 17 00:00:00 2001 From: arvindkhuntia <31609955+arvindkhuntia@users.noreply.github.com> Date: Fri, 23 Oct 2020 12:24:18 +0200 Subject: [PATCH 1057/1751] FV0 bug fix (#4671) * bug fix for FV0; avoiding memory corruption --- Detectors/FIT/FV0/simulation/src/Digitizer.cxx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx index 3ce0a80e69022..146e47705fd87 100644 --- a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx @@ -145,9 +145,17 @@ void Digitizer::createPulse(float mipFraction, int parID, const double hitTime, } ///Time of flight subtracted from Hit time //TODO have different TOF according to thr ring number - Size_t NBinShift = std::lround((hitTime - FV0DigParam::Instance().globalTimeOfFlight) / FV0DigParam::Instance().waveformBinWidth); - mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins, 0.); - std::memcpy(&mPmtResponseTemp[NBinShift], &mPmtResponseGlobal[0], sizeof(double) * (FV0DigParam::Instance().waveformNbins - NBinShift)); + Int_t NBinShift = std::lround((hitTime - FV0DigParam::Instance().globalTimeOfFlight) / FV0DigParam::Instance().waveformBinWidth); + + if (NBinShift >= 0 && NBinShift < FV0DigParam::Instance().waveformNbins) { + mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins, 0.); + std::memcpy(&mPmtResponseTemp[NBinShift], &mPmtResponseGlobal[0], + sizeof(double) * (FV0DigParam::Instance().waveformNbins - NBinShift)); + } else { + mPmtResponseTemp = mPmtResponseGlobal; + mPmtResponseTemp.erase(mPmtResponseTemp.begin(), mPmtResponseTemp.begin() + abs(NBinShift)); + mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins); + } for (int ir = 0; ir < int(mPmtResponseTemp.size() / mNTimeBinsPerBC); ir++) { auto bcCache = getBCCache(cachedIR[ir]); From fd0fe4ac1ed6f0b3b0cc01b83ec190842dd105a4 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 22 Oct 2020 10:39:31 +0200 Subject: [PATCH 1058/1751] Improve class checkin handling Enable streaming of any class with a dictionary, not only classes with IsA functionality --- Common/Utils/include/CommonUtils/TreeStream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Utils/include/CommonUtils/TreeStream.h b/Common/Utils/include/CommonUtils/TreeStream.h index d1df4ca48f600..6882176632d57 100644 --- a/Common/Utils/include/CommonUtils/TreeStream.h +++ b/Common/Utils/include/CommonUtils/TreeStream.h @@ -178,7 +178,7 @@ Int_t TreeStream::CheckIn(T* obj) // check in arbitrary class having dictionary TClass* pClass = nullptr; if (obj) { - pClass = obj->IsA(); + pClass = TClass::GetClass(typeid(*obj)); } if (mCurrentIndex >= static_cast<int>(mElements.size())) { From 109a23cecda3c529d48408bbfbb2ed4255bd2623 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 23 Oct 2020 13:58:35 +0200 Subject: [PATCH 1059/1751] taskwrapper: catch assertion failed --- Utilities/Tools/jobutils.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index dfab53e385043..136c2cbe74f69 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -93,6 +93,7 @@ taskwrapper() { -e \"segmentation violation\" \ -e \"error while setting up workflow\" \ -e \"bus error\" \ + -e \"Assertion.*failed\" \ -e \"There was a crash.\"" grepcommand="grep -H ${pattern} $logfile >> encountered_exceptions_list 2>/dev/null" From 24cd5080ffae405c8db0247ae80ed0a0c5917b49 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 21 Oct 2020 18:52:34 +0200 Subject: [PATCH 1060/1751] Force tree to have N entries consistent with that of branches --- .../ITSMFT/common/workflow/src/DigitWriterSpec.cxx | 11 ++++++++++- Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx | 11 ++++++++++- Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h | 11 ++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx index 8cda4bebe917b..f01f6ae485031 100644 --- a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx @@ -48,7 +48,16 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, o2::header::DataOrigin detOri // the callback to be set as hook for custom action when the writer is closed auto finishWriting = [](TFile* outputfile, TTree* outputtree) { - outputtree->SetEntries(1); + const auto* brArr = outputtree->GetListOfBranches(); + int64_t nent = 0; + for (const auto* brc : *brArr) { + int64_t n = ((const TBranch*)brc)->GetEntries(); + if (nent && (nent != n)) { + LOG(ERROR) << "Branches have different number of entries"; + } + nent = n; + } + outputtree->SetEntries(nent); outputtree->Write("", TObject::kOverwrite); outputfile->Close(); }; diff --git a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx index 951a189e5c07c..b71d52b5b916e 100644 --- a/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx @@ -37,7 +37,16 @@ o2::framework::DataProcessorSpec getTRDDigitWriterSpec(bool mctruth) // the callback to be set as hook for custom action when the writer is closed auto finishWriting = [](TFile* outputfile, TTree* outputtree) { - outputtree->SetEntries(1); + const auto* brArr = outputtree->GetListOfBranches(); + int64_t nent = 0; + for (const auto* brc : *brArr) { + int64_t n = ((const TBranch*)brc)->GetEntries(); + if (nent && (nent != n)) { + LOG(ERROR) << "Branches have different number of entries"; + } + nent = n; + } + outputtree->SetEntries(nent); outputtree->Write(); outputfile->Close(); }; diff --git a/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h b/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h index 577c2a1df4b4b..7b4e31cbca772 100644 --- a/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h +++ b/Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h @@ -35,7 +35,16 @@ o2::framework::DataProcessorSpec getFDDDigitWriterSpec(bool mctruth = true) // the callback to be set as hook for custom action when the writer is closed auto finishWriting = [](TFile* outputfile, TTree* outputtree) { - outputtree->SetEntries(1); + const auto* brArr = outputtree->GetListOfBranches(); + int64_t nent = 0; + for (const auto* brc : *brArr) { + int64_t n = ((const TBranch*)brc)->GetEntries(); + if (nent && (nent != n)) { + LOG(ERROR) << "Branches have different number of entries"; + } + nent = n; + } + outputtree->SetEntries(nent); outputtree->Write(); outputfile->Close(); }; From c787376b9cb001da50655d76bdc332886bfebe47 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 23 Oct 2020 16:02:07 +0200 Subject: [PATCH 1061/1751] DPL Analysis: re-introduce index-builder after fix for input metadata (#4669) --- .../Core/include/Framework/AODReaderHelpers.h | 1 + Framework/Core/include/Framework/ASoA.h | 17 +++- .../include/Framework/AnalysisDataModel.h | 6 +- .../Core/include/Framework/AnalysisTask.h | 34 ++++++- Framework/Core/src/AODReaderHelpers.cxx | 91 +++++++++++++++++-- Framework/Core/src/AnalysisManagers.h | 4 +- Framework/Core/src/WorkflowHelpers.cxx | 62 ++++++++++++- Framework/Core/src/WorkflowHelpers.h | 17 ++++ Framework/Core/src/runDataProcessing.cxx | 17 ---- 9 files changed, 215 insertions(+), 34 deletions(-) diff --git a/Framework/Core/include/Framework/AODReaderHelpers.h b/Framework/Core/include/Framework/AODReaderHelpers.h index 3016f07200fb2..f428f46bce6f5 100644 --- a/Framework/Core/include/Framework/AODReaderHelpers.h +++ b/Framework/Core/include/Framework/AODReaderHelpers.h @@ -65,6 +65,7 @@ struct RuntimeWatchdog { struct AODReaderHelpers { static AlgorithmSpec rootFileReaderCallback(); static AlgorithmSpec aodSpawnerCallback(std::vector<InputSpec> requested); + static AlgorithmSpec indexBuilderCallback(std::vector<InputSpec> requested); }; } // namespace o2::framework::readers diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 1f726cbd9ca62..41f98f2f7d304 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -25,6 +25,7 @@ #include <arrow/compute/kernel.h> #include <gandiva/selection_vector.h> #include <cassert> +#include <fmt/format.h> using o2::framework::runtime_error_f; @@ -1050,6 +1051,7 @@ class TableMetadata static constexpr char const* tableLabel() { return INHERIT::mLabel; } static constexpr char const (&origin())[4] { return INHERIT::mOrigin; } static constexpr char const (&description())[16] { return INHERIT::mDescription; } + static std::string sourceSpec() { return fmt::format("{}/{}/{}", INHERIT::mLabel, INHERIT::mOrigin, INHERIT::mDescription); }; }; template <typename... C1, typename... C2> @@ -1377,7 +1379,7 @@ constexpr auto is_binding_compatible_v() #define DECLARE_SOA_EXTENDED_TABLE_USER(_Name_, _Table_, _Description_, ...) \ DECLARE_SOA_EXTENDED_TABLE_FULL(_Name_, _Table_, "AOD", _Description_, __VA_ARGS__) -#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, ...) \ +#define DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, _Origin_, _Description_, _Exclusive_, ...) \ struct _Name_ : o2::soa::IndexTable<_Key_, __VA_ARGS__> { \ _Name_(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : o2::soa::IndexTable<_Key_, __VA_ARGS__>(table, offset){}; \ _Name_(_Name_ const&) = default; \ @@ -1393,6 +1395,7 @@ constexpr auto is_binding_compatible_v() static constexpr char const* mLabel = #_Name_; \ static constexpr char const mOrigin[4] = _Origin_; \ static constexpr char const mDescription[16] = _Description_; \ + static constexpr bool exclusive = _Exclusive_; \ }; \ \ template <> \ @@ -1406,7 +1409,16 @@ constexpr auto is_binding_compatible_v() }; #define DECLARE_SOA_INDEX_TABLE(_Name_, _Key_, _Description_, ...) \ - DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, __VA_ARGS__) + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "IDX", _Description_, false, __VA_ARGS__) + +#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(_Name_, _Key_, _Description_, ...) \ + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "IDX", _Description_, true, __VA_ARGS__) + +#define DECLARE_SOA_INDEX_TABLE_USER(_Name_, _Key_, _Description_, ...) \ + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, false, __VA_ARGS__) + +#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE_USER(_Name_, _Key_, _Description_, ...) \ + DECLARE_SOA_INDEX_TABLE_FULL(_Name_, _Key_, "AOD", _Description_, true, __VA_ARGS__) namespace o2::soa { @@ -1767,6 +1779,7 @@ struct IndexTable : Table<soa::Index<>, H, Ts...> { using indexing_t = Key; using first_t = typename H::binding_t; using rest_t = framework::pack<typename Ts::binding_t...>; + using sources_t = framework::pack<Key, typename H::binding_t, typename Ts::binding_t...>; IndexTable(std::shared_ptr<arrow::Table> table, uint64_t offset = 0) : base_t{table, offset} diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index cf62d2df8aab6..a3a191c6d9e06 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -608,14 +608,14 @@ DECLARE_SOA_INDEX_COLUMN(FDD, fdd); } // namespace indices #define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FV0CId, indices::FDDId -DECLARE_SOA_INDEX_TABLE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); #define INDEX_LIST_RUN3 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FDDId -DECLARE_SOA_INDEX_TABLE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MA_RN3_SP", INDEX_LIST_RUN3); -DECLARE_SOA_INDEX_TABLE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); DECLARE_SOA_INDEX_TABLE(BCCollisionsSparse, BCs, "MA_BCCOL_SP", indices::BCId, indices::CollisionId); } // namespace aod diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index eacdd9704566c..e6867177bb734 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -53,13 +53,45 @@ struct AnalysisTask { // the contents of an AnalysisTask... struct AnalysisDataProcessorBuilder { + template <typename T> + static ConfigParamSpec getSpec() + { + if constexpr (soa::is_type_with_metadata_v<aod::MetadataTrait<T>>) { + return ConfigParamSpec{aod::MetadataTrait<T>::metadata::tableLabel(), VariantType::String, aod::MetadataTrait<T>::metadata::sourceSpec(), {"\"\""}}; + } else { + using O1 = framework::pack_element_t<0, typename T::originals>; + return ConfigParamSpec{aod::MetadataTrait<T>::metadata::tableLabel(), VariantType::String, aod::MetadataTrait<O1>::metadata::sourceSpec(), {"\"\""}}; + } + } + + template <typename... T> + static std::vector<ConfigParamSpec> getInputSpecs(framework::pack<T...>) + { + return std::vector{getSpec<T>()...}; + } + + template <typename T> + static std::vector<ConfigParamSpec> getIndexSources() + { + static_assert(soa::is_soa_index_table_t<T>::value, "Can only be used with IndexTable"); + return getInputSpecs(typename T::sources_t{}); + } + template <typename Arg> static void doAppendInputWithMetadata(std::vector<InputSpec>& inputs) { using metadata = typename aod::MetadataTrait<std::decay_t<Arg>>::metadata; static_assert(std::is_same_v<metadata, void> == false, "Could not find metadata. Did you register your type?"); - inputs.push_back({metadata::tableLabel(), metadata::origin(), metadata::description()}); + if constexpr (soa::is_soa_index_table_t<std::decay_t<Arg>>::value) { + auto inputSources = getIndexSources<std::decay_t<Arg>>(); + std::sort(inputSources.begin(), inputSources.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name < b.name; }); + auto last = std::unique(inputSources.begin(), inputSources.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name == b.name; }); + inputSources.erase(last, inputSources.end()); + inputs.push_back(InputSpec{metadata::tableLabel(), metadata::origin(), metadata::description(), Lifetime::Timeframe, inputSources}); + } else { + inputs.push_back({metadata::tableLabel(), metadata::origin(), metadata::description()}); + } } template <typename... Args> diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 261b4d84acebc..971c917c28169 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -8,8 +8,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/TableTreeHelpers.h" #include "Framework/AODReaderHelpers.h" +#include "Framework/TableTreeHelpers.h" +#include "Framework/AnalysisHelpers.h" #include "AnalysisDataModelHelpers.h" #include "DataProcessingHelpers.h" #include "ExpressionHelpers.h" @@ -41,16 +42,90 @@ namespace o2::framework::readers { -AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> requested) +auto setEOSCallback(InitContext& ic) +{ + ic.services().get<CallbackService>().set(CallbackService::Id::EndOfStream, + [](EndOfStreamContext& eosc) { + auto& control = eosc.services().get<ControlService>(); + control.endOfStream(); + control.readyToQuit(QuitRequest::Me); + }); +} + +template <typename O> +static inline auto extractTypedOriginal(ProcessingContext& pc) +{ + ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables + return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; +} + +template <typename... Os> +static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +{ + return std::make_tuple(extractTypedOriginal<Os>(pc)...); +} + +AlgorithmSpec AODReaderHelpers::indexBuilderCallback(std::vector<InputSpec> requested) { return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { - auto& callbacks = ic.services().get<CallbackService>(); - auto endofdatacb = [](EndOfStreamContext& eosc) { - auto& control = eosc.services().get<ControlService>(); - control.endOfStream(); - control.readyToQuit(QuitRequest::Me); + setEOSCallback(ic); + + return [requested](ProcessingContext& pc) { + auto outputs = pc.outputs(); + // spawn tables + for (auto& input : requested) { + auto description = std::visit( + overloaded{ + [](ConcreteDataMatcher const& matcher) { return matcher.description; }, + [](auto&&) { return header::DataDescription{""}; }}, + input.matcher); + + auto origin = std::visit( + overloaded{ + [](ConcreteDataMatcher const& matcher) { return matcher.origin; }, + [](auto&&) { return header::DataOrigin{""}; }}, + input.matcher); + + auto maker = [&](auto metadata) { + using metadata_t = decltype(metadata); + using Key = typename metadata_t::Key; + using index_pack_t = typename metadata_t::index_pack_t; + using sources = typename metadata_t::originals; + if constexpr (metadata_t::exclusive == true) { + return o2::framework::IndexExclusive::indexBuilder(index_pack_t{}, + extractTypedOriginal<Key>(pc), + extractOriginalsTuple(sources{}, pc)); + } else { + return o2::framework::IndexSparse::indexBuilder(index_pack_t{}, + extractTypedOriginal<Key>(pc), + extractOriginalsTuple(sources{}, pc)); + } + }; + + if (description == header::DataDescription{"MA_RN2_EX"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run2MatchedExclusiveMetadata{})); + } else if (description == header::DataDescription{"MA_RN2_SP"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run2MatchedSparseMetadata{})); + } else if (description == header::DataDescription{"MA_RN3_EX"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedExclusiveMetadata{})); + } else if (description == header::DataDescription{"MA_RN3_SP"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedSparseMetadata{})); + } else if (description == header::DataDescription{"MA_BCCOL_EX"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsExclusiveMetadata{})); + } else if (description == header::DataDescription{"MA_BCCOL_SP"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsSparseMetadata{})); + } else { + throw std::runtime_error("Not an index table"); + } + } }; - callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); + }}; +} + +AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> requested) +{ + return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { + setEOSCallback(ic); return [requested](ProcessingContext& pc) { auto outputs = pc.outputs(); diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index 33340b70640e9..c59225b8364d0 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -260,14 +260,14 @@ struct OutputManager<Spawns<T>> { /// Builds specialization template <typename O> -static auto extractTypedOriginal(ProcessingContext& pc) +static inline auto extractTypedOriginal(ProcessingContext& pc) { ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; } template <typename... Os> -static auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) { return std::make_tuple(extractTypedOriginal<Os>(pc)...); } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 7ce8a9ab68a72..132f691ee23b0 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -161,6 +161,41 @@ void addMissingOutputsToSpawner(std::vector<InputSpec>&& requestedDYNs, } } +void addMissingOutputsToBuilder(std::vector<InputSpec>&& requestedIDXs, + std::vector<InputSpec>& requestedAODs, + DataProcessorSpec& publisher) +{ + auto inputSpecFromString = [](std::string s) { + std::regex word_regex("(\\w+)"); + auto words = std::sregex_iterator(s.begin(), s.end(), word_regex); + if (std::distance(words, std::sregex_iterator()) != 3) { + throw runtime_error_f("Malformed spec: %s", s.c_str()); + } + std::vector<std::string> data; + for (auto i = words; i != std::sregex_iterator(); ++i) { + data.emplace_back(i->str()); + } + char origin[4]; + char description[16]; + std::memcpy(&origin, data[1].c_str(), 4); + std::memcpy(&description, data[2].c_str(), 16); + return InputSpec{data[0], header::DataOrigin{origin}, header::DataDescription{description}}; + }; + + for (auto& input : requestedIDXs) { + auto concrete = DataSpecUtils::asConcreteDataMatcher(input); + publisher.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec}); + for (auto& i : input.metadata) { + auto spec = inputSpecFromString(i.defaultValue.get<std::string>()); + auto j = std::find_if(publisher.inputs.begin(), publisher.inputs.end(), [&](auto x) { return x.binding == spec.binding; }); + if (j == publisher.inputs.end()) { + publisher.inputs.push_back(spec); + } + requestedAODs.push_back(spec); + } + } +} + void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext const& ctx) { auto fakeCallback = AlgorithmSpec{[](InitContext& ic) { @@ -218,6 +253,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext std::vector<InputSpec> requestedAODs; std::vector<OutputSpec> providedAODs; std::vector<InputSpec> requestedDYNs; + std::vector<InputSpec> requestedIDXs; std::vector<InputSpec> requestedCCDBs; std::vector<OutputSpec> providedCCDBs; @@ -285,7 +321,13 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext requestedDYNs.emplace_back(input); } } + if (DataSpecUtils::partialMatch(input, header::DataOrigin{"IDX"})) { + if (std::find_if(requestedIDXs.begin(), requestedIDXs.end(), [&](InputSpec const& spec) { return input.binding == spec.binding; }) == requestedIDXs.end()) { + requestedIDXs.emplace_back(input); + } + } } + std::stable_sort(timer.outputs.begin(), timer.outputs.end(), [](OutputSpec const& a, OutputSpec const& b) { return *DataSpecUtils::getOptionalSubSpec(a) < *DataSpecUtils::getOptionalSubSpec(b); }); for (size_t oi = 0; oi < processor.outputs.size(); ++oi) { @@ -316,10 +358,15 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } } } - + auto sortingEquals = [](InputSpec const& a, InputSpec const& b) { return DataSpecUtils::describe(a) == DataSpecUtils::describe(b); }; + std::sort(requestedDYNs.begin(), requestedDYNs.end(), sortingEquals); auto last = std::unique(requestedDYNs.begin(), requestedDYNs.end()); requestedDYNs.erase(last, requestedDYNs.end()); + std::sort(requestedIDXs.begin(), requestedIDXs.end(), sortingEquals); + last = std::unique(requestedIDXs.begin(), requestedIDXs.end()); + requestedIDXs.erase(last, requestedIDXs.end()); + DataProcessorSpec aodSpawner{ "internal-dpl-aod-spawner", {}, @@ -327,7 +374,16 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext readers::AODReaderHelpers::aodSpawnerCallback(requestedDYNs), {}}; + DataProcessorSpec indexBuilder{ + "internal-dpl-index-builder", + {}, + {}, + readers::AODReaderHelpers::indexBuilderCallback(requestedIDXs), + {}}; + addMissingOutputsToSpawner(std::move(requestedDYNs), requestedAODs, aodSpawner); + addMissingOutputsToBuilder(std::move(requestedIDXs), requestedAODs, indexBuilder); + addMissingOutputsToReader(providedAODs, requestedAODs, aodReader); addMissingOutputsToReader(providedCCDBs, requestedCCDBs, ccdbBackend); @@ -347,6 +403,10 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext extraSpecs.push_back(aodSpawner); } + if (indexBuilder.outputs.empty() == false) { + extraSpecs.push_back(indexBuilder); + } + if (aodReader.outputs.empty() == false) { extraSpecs.push_back(timePipeline(aodReader, ctx.options().get<int64_t>("readers"))); auto concrete = DataSpecUtils::asConcreteDataMatcher(aodReader.inputs[0]); diff --git a/Framework/Core/src/WorkflowHelpers.h b/Framework/Core/src/WorkflowHelpers.h index 3e90491cb751e..9cb5c46829744 100644 --- a/Framework/Core/src/WorkflowHelpers.h +++ b/Framework/Core/src/WorkflowHelpers.h @@ -24,6 +24,23 @@ namespace o2::framework { +inline static std::string debugWorkflow(std::vector<DataProcessorSpec> const& specs) +{ + std::ostringstream out; + for (auto& spec : specs) { + out << spec.name << "\n"; + out << " Inputs:\n"; + for (auto& ii : spec.inputs) { + out << " - " << DataSpecUtils::describe(ii) << "\n"; + } + // out << "\n Outputs:\n"; + // for (auto& ii : spec.outputs) { + // out << " - " << DataSpecUtils::describe(ii) << "\n"; + // } + } + return out.str(); +} + struct ConfigContext; // Structure to hold information which was derived // for output channels. diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 37eedf985070b..cc372acf36578 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1462,23 +1462,6 @@ std::string debugTopoInfo(std::vector<DataProcessorSpec> const& specs, return out.str(); } -std::string debugWorkflow(std::vector<DataProcessorSpec> const& specs) -{ - std::ostringstream out; - for (auto& spec : specs) { - out << spec.name << "\n"; - // out << " Inputs:\n"; - // for (auto& ii : spec.inputs) { - // out << " - " << DataSpecUtils::describe(ii) << "\n"; - // } - // out << "\n Outputs:\n"; - // for (auto& ii : spec.outputs) { - // out << " - " << DataSpecUtils::describe(ii) << "\n"; - // } - } - return out.str(); -} - // This is a toy executor for the workflow spec // What it needs to do is: // From 9403885cc326f5304063e2c7f7ab5b809375b3ae Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 10:06:45 +0200 Subject: [PATCH 1062/1751] GPU: Add chi2 output to refit --- .../Interface/GPUO2InterfaceRefit.h | 4 +- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 67 ++++++++++++------- GPU/GPUTracking/Refit/GPUTrackingRefit.h | 11 +-- macro/runTPCRefit.C | 9 +-- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index 8a09506c5b906..8126290e198b2 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -50,8 +50,8 @@ class GPUTPCO2InterfaceRefit int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, outward, resetCov); } int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, outward, resetCov); } - int RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, clusRef, time0, outward, resetCov); } - int RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, clusRef, time0, outward, resetCov); } + int RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2 = nullptr, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, clusRef, time0, chi2, outward, resetCov); } + int RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2 = nullptr, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsTrackParCov(trk, clusRef, time0, chi2, outward, resetCov); } void setGPUTrackFitInProjections(bool v = true); void setTrackReferenceX(float v); void setIgnoreErrorsAtTrackEnds(bool v) { mRefit.mIgnoreErrorsOnTrackEnds = v; } diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 6b21d8363bb99..ab1bdeacf006c 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -89,7 +89,7 @@ void GPUTrackingRefit::initProp<const Propagator*>(const Propagator*& prop) } template <class T, class S, class U> -void GPUTrackingRefit::convertTrack(T& trk, const S& trkX, U& prop) +void GPUTrackingRefit::convertTrack(T& trk, const S& trkX, U& prop, float* chi2) { trk = trkX; } @@ -115,89 +115,103 @@ static void convertTrackParam(TrackParCov& trk, const GPUTPCGMTrackParam& trkX) } // Generic template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackParCov& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackParCov& trkX, GPUTPCGMPropagator& prop, float* chi2) { convertTrackParam(trk, trkX); prop.SetTrack(&trk, trkX.getAlpha()); } template <> -void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackParCov& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackParCov& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { convertTrackParam(trk, trkX); trk.setAlpha(prop.GetAlpha()); } // GPUTPCGMMergedTrack input template <> -void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Propagator*>(TrackParCov& trk, const GPUTPCGMMergedTrack& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Propagator*>(TrackParCov& trk, const GPUTPCGMMergedTrack& trkX, const Propagator*& prop, float* chi2) { initProp(prop); convertTrackParam(trk, trkX.GetParam()); trk.setAlpha(trkX.GetAlpha()); + *chi2 = trkX.GetParam().GetChi2(); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, TrackParCov, const Propagator*>(GPUTPCGMMergedTrack& trk, const TrackParCov& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, TrackParCov, const Propagator*>(GPUTPCGMMergedTrack& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) { convertTrackParam(trk.Param(), trkX); trk.SetAlpha(trkX.getAlpha()); + trk.Param().SetChi2(*chi2); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTPCGMMergedTrack, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTPCGMMergedTrack& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTPCGMMergedTrack, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTPCGMMergedTrack& trkX, GPUTPCGMPropagator& prop, float* chi2) { initProp(prop); trk = trkX.GetParam(); prop.SetTrack(&trk, trkX.GetAlpha()); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTPCGMMergedTrack& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTPCGMMergedTrack& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { trk.SetParam(trkX); trk.SetAlpha(prop.GetAlpha()); } // TrackTPC input template <> -void GPUTrackingRefit::convertTrack<TrackParCov, TrackTPC, const Propagator*>(TrackParCov& trk, const TrackTPC& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<TrackParCov, TrackTPC, const Propagator*>(TrackParCov& trk, const TrackTPC& trkX, const Propagator*& prop, float* chi2) { initProp(prop); - convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop, nullptr); + *chi2 = trkX.getChi2(); } template <> -void GPUTrackingRefit::convertTrack<TrackTPC, TrackParCov, const Propagator*>(TrackTPC& trk, const TrackParCov& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<TrackTPC, TrackParCov, const Propagator*>(TrackTPC& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) { - convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop); + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop, nullptr); + trk.setChi2(*chi2); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackTPC, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackTPC& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackTPC, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackTPC& trkX, GPUTPCGMPropagator& prop, float* chi2) { initProp(prop); - convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX, prop); + convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX, prop, nullptr); + trk.SetChi2(trkX.getChi2()); } template <> -void GPUTrackingRefit::convertTrack<TrackTPC, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackTPC& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<TrackTPC, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackTPC& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { - convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk, trkX, prop); + convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk, trkX, prop, nullptr); + trk.setChi2(trkX.GetChi2()); } // TrackParCovWithArgs input template <> -void GPUTrackingRefit::convertTrack<TrackParCov, GPUTrackingRefit::TrackParCovWithArgs, const Propagator*>(TrackParCov& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<TrackParCov, GPUTrackingRefit::TrackParCovWithArgs, const Propagator*>(TrackParCov& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, const Propagator*& prop, float* chi2) { initProp(prop); - convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX.trk, prop); + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX.trk, prop, nullptr); + *chi2 = trkX.chi2 ? *trkX.chi2 : 0.f; } template <> -void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, TrackParCov, const Propagator*>(GPUTrackingRefit::TrackParCovWithArgs& trk, const TrackParCov& trkX, const Propagator*& prop) +void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, TrackParCov, const Propagator*>(GPUTrackingRefit::TrackParCovWithArgs& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) { - convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk.trk, trkX, prop); + convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk.trk, trkX, prop, nullptr); + if (trk.chi2) { + *trk.chi2 = *chi2; + } } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, GPUTPCGMPropagator& prop, float* chi2) { initProp(prop); - convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX.trk, prop); + convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX.trk, prop, nullptr); + trk.SetChi2(trkX.chi2 ? *trkX.chi2 : 0.f); } template <> -void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTrackingRefit::TrackParCovWithArgs& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop) +void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTrackingRefit::TrackParCovWithArgs& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { - convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk.trk, trkX, prop); + convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk.trk, trkX, prop, chi2); + if (trk.chi2) { + *trk.chi2 = trkX.GetChi2(); + } } static const float* getPar(const GPUTPCGMTrackParam& trk) { return trk.GetPar(); } @@ -209,7 +223,8 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) CADEBUG(int ii; printf("\nRefitting track\n")); typename refitTrackTypes<S>::propagator prop; S trk; - convertTrack(trk, trkX, prop); + float TrackParCovChi2 = 0.f; + convertTrack(trk, trkX, prop, &TrackParCovChi2); int begin = 0, count; float tOffset; if constexpr (std::is_same<T, GPUTPCGMMergedTrack>::value) { @@ -336,12 +351,14 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } if (resetCov) { trk.resetCovariance(); + TrackParCovChi2 = 0.f; } CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[0] - y, trk.getParams()[1] - z, sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); std::array<float, 2> p = {y, z}; std::array<float, 3> c = {0, 0, 0}; mPparam->GetClusterErrors2(currentRow, z, getPar(trk)[2], getPar(trk)[3], c[0], c[2]); mPparam->UpdateClusterError2ByState(clusterState, c[0], c[2]); + TrackParCovChi2 += trk.getPredictedChi2(p, c); if (!trk.update(p, c)) { IgnoreErrors(trk.getSnp()); return -3; @@ -372,7 +389,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) static_assert("Invalid template"); } - convertTrack(trkX, trk, prop); + convertTrack(trkX, trk, prop, &TrackParCovChi2); return nFitted; } diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.h b/GPU/GPUTracking/Refit/GPUTrackingRefit.h index 2d619e8392e17..7dbc710beeecc 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.h +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.h @@ -72,15 +72,16 @@ class GPUTrackingRefit o2::track::TrackParCov& trk; const o2::tpc::TrackTPCClusRef& clusRef; float time0; + float* chi2; }; - GPUd() int RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) + GPUd() int RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2 = nullptr, bool outward = false, bool resetCov = false) { - TrackParCovWithArgs x{trk, clusRef, time0}; + TrackParCovWithArgs x{trk, clusRef, time0, chi2}; return RefitTrack<TrackParCovWithArgs, GPUTPCGMTrackParam>(x, outward, resetCov); } - GPUd() int RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, bool outward = false, bool resetCov = false) + GPUd() int RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2 = nullptr, bool outward = false, bool resetCov = false) { - TrackParCovWithArgs x{trk, clusRef, time0}; + TrackParCovWithArgs x{trk, clusRef, time0, chi2}; return RefitTrack<TrackParCovWithArgs, o2::track::TrackParCov>(x, outward, resetCov); } @@ -97,7 +98,7 @@ class GPUTrackingRefit template <class T, class S> GPUd() int RefitTrack(T& trk, bool outward, bool resetCov); template <class T, class S, class U> - void convertTrack(T& trk, const S& trkX, U& prop); + void convertTrack(T& trk, const S& trkX, U& prop, float* chi2); template <class U> void initProp(U& prop); }; diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C index 7c98bf300377e..13ead3aed2fcd 100644 --- a/macro/runTPCRefit.C +++ b/macro/runTPCRefit.C @@ -94,7 +94,7 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc if (retval < 0) { std::cout << "Refit as GPU track failed " << retval << "\n"; } else { - std::cout << "Succeeded using " << retval << " hits\n"; + std::cout << "Succeeded using " << retval << " hits (chi2 = " << trk.getChi2() << ")\n"; trk.print(); } trk = (*tracks)[i]; @@ -103,17 +103,18 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc if (retval < 0) { std::cout << "Refit as TrackParCov track failed " << retval << "\n"; } else { - std::cout << "Succeeded using " << retval << " hits\n"; + std::cout << "Succeeded using " << retval << " hits (chi2 = " << trk.getChi2() << ")\n"; trk.print(); } trk = (*tracks)[i]; TrackParCov trkX = trk; + float chi2 = trk.getChi2(); std::cout << "Refitting as TrackParCov track with TrackParCov input\n"; - retval = refit.RefitTrackAsTrackParCov(trkX, trk.getClusterRef(), trk.getTime0(), false, true); + retval = refit.RefitTrackAsTrackParCov(trkX, trk.getClusterRef(), trk.getTime0(), &chi2, false, true); if (retval < 0) { std::cout << "Refit as TrackParCov track failed " << retval << "\n"; } else { - std::cout << "Succeeded using " << retval << " hits\n"; + std::cout << "Succeeded using " << retval << " hits (chi2 = " << chi2 << ")\n"; trkX.print(); } } From 515ab467d38ec6f850a3c2637270581e6ef5fcf9 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 13 Oct 2020 09:15:48 +0200 Subject: [PATCH 1063/1751] Add TRD grid to GPU display and pT cut for displayed tracks --- .../Standalone/display/GPUDisplay.cxx | 61 +++++++++++++++++++ GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h | 3 + 2 files changed, 64 insertions(+) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index fede022945735..55d03e65a3bad 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -1076,6 +1076,7 @@ GPUDisplay::vboList GPUDisplay::DrawGrid(const GPUTPCTracker& tracker) int iSlice = tracker.ISlice(); size_t startCount = mVertexBufferStart[iSlice].size(); size_t startCountInner = mVertexBuffer[iSlice].size(); + /* for (int i = 0; i < GPUCA_ROW_COUNT; i++) { const GPUTPCRow& row = tracker.Data().Row(i); for (int j = 0; j <= (signed)row.Grid().Ny(); j++) { @@ -1115,6 +1116,66 @@ GPUDisplay::vboList GPUDisplay::DrawGrid(const GPUTPCTracker& tracker) mVertexBuffer[iSlice].emplace_back(xx2 / GL_SCALE_FACTOR, yy2 / GL_SCALE_FACTOR, zz2 / GL_SCALE_FACTOR); } } + */ + if (iSlice < 18) { + // TODO: tilted pads ignored at the moment + int iSec = iSlice; + auto geo = trdTracker().GetGeometry(); + float alpha = geo->GetAlpha() / 2.f + geo->GetAlpha() * iSec; + if (iSec >= 9) { + alpha -= 2 * M_PI; + } + for (int iLy = 0; iLy < GPUTRDTracker::EGPUTRDTracker::kNLayers; ++iLy) { + for (int iStack = 0; iStack < GPUTRDTracker::EGPUTRDTracker::kNStacks; ++iStack) { + int iDet = geo->GetDetector(iLy, iStack, iSec); + auto matrix = geo->GetClusterMatrix(iDet); + if (!matrix) { + continue; + } + auto pp = geo->GetPadPlane(iDet); + for (int i = 0; i < pp->GetNrows(); ++i) { + float xyzLoc1[3]; + float xyzLoc2[3]; + float xyzGlb1[3]; + float xyzGlb2[3]; + xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); + xyzLoc1[1] = pp->GetCol0(); + xyzLoc2[1] = pp->GetColEnd(); + xyzLoc1[2] = xyzLoc2[2] = pp->GetRowPos(i) - pp->GetRowPos(pp->GetNrows() / 2); + matrix->LocalToMaster(xyzLoc1, xyzGlb1); + matrix->LocalToMaster(xyzLoc2, xyzGlb2); + float x1Tmp = xyzGlb1[0]; + xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); + xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); + float x2Tmp = xyzGlb2[0]; + xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); + xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); + mVertexBuffer[iSlice].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); + mVertexBuffer[iSlice].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); + } + for (int j = 0; j < pp->GetNcols(); ++j) { + float xyzLoc1[3]; + float xyzLoc2[3]; + float xyzGlb1[3]; + float xyzGlb2[3]; + xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); + xyzLoc1[1] = xyzLoc2[1] = pp->GetColPos(j) + pp->GetColSize(j) / 2.f; + xyzLoc1[2] = pp->GetRow0() - pp->GetRowPos(pp->GetNrows() / 2); + xyzLoc2[2] = pp->GetRowEnd() - pp->GetRowPos(pp->GetNrows() / 2); + matrix->LocalToMaster(xyzLoc1, xyzGlb1); + matrix->LocalToMaster(xyzLoc2, xyzGlb2); + float x1Tmp = xyzGlb1[0]; + xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); + xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); + float x2Tmp = xyzGlb2[0]; + xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); + xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); + mVertexBuffer[iSlice].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); + mVertexBuffer[iSlice].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); + } + } + } + } insertVertexList(tracker.ISlice(), startCountInner, mVertexBuffer[iSlice].size()); return (vboList(startCount, mVertexBufferStart[iSlice].size() - startCount, iSlice)); } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h b/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h index a06fcf6181eba..37455db6d0790 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h @@ -62,12 +62,15 @@ class GPUTRDpadPlane : private o2::trd::TRDPadPlane public: GPUd() float GetTiltingAngle() const { return getTiltingAngle(); } GPUd() float GetRowSize(int row) const { return getRowSize(row); } + GPUd() float GetColSize(int col) const { return getColSize(col); } GPUd() float GetRow0() const { return getRow0(); } + GPUd() float GetCol0() const { return getCol0(); } GPUd() float GetRowEnd() const { return getRowEnd(); } GPUd() float GetColEnd() const { return getColEnd(); } GPUd() float GetRowPos(int row) const { return getRowPos(row); } GPUd() float GetColPos(int col) const { return getColPos(col); } GPUd() float GetNrows() const { return getNrows(); } + GPUd() float GetNcols() const { return getNcols(); } }; class GPUTRDGeometry : private o2::trd::TRDGeometryFlat From 4c06a7edb86b8fdc46455ea4a66d17ac23556564 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 23:39:48 +0200 Subject: [PATCH 1064/1751] GPU Display: Separate grid of TPC and TRD in standalone visualization --- .../Standalone/display/GPUDisplay.cxx | 153 ++++++++++-------- .../Standalone/display/GPUDisplay.h | 3 + 2 files changed, 91 insertions(+), 65 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 55d03e65a3bad..30c7a602c79c7 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -395,12 +395,21 @@ inline void GPUDisplay::SetColorFinal() inline void GPUDisplay::SetColorGrid() { if (mInvertColors) { - mDrawColor = {0.5, 0.5, 0}; + mDrawColor = {0.5, 0.5, 0.0}; } else { mDrawColor = {0.7, 0.7, 0.0}; } ActivateColor(); } +inline void GPUDisplay::SetColorGridTRD() +{ + if (mInvertColors) { + mDrawColor = {0.5, 0.5, 0.5}; + } else { + mDrawColor = {0.7, 0.7, 0.5}; + } + ActivateColor(); +} inline void GPUDisplay::SetColorMarked() { if (mInvertColors) { @@ -1076,7 +1085,6 @@ GPUDisplay::vboList GPUDisplay::DrawGrid(const GPUTPCTracker& tracker) int iSlice = tracker.ISlice(); size_t startCount = mVertexBufferStart[iSlice].size(); size_t startCountInner = mVertexBuffer[iSlice].size(); - /* for (int i = 0; i < GPUCA_ROW_COUNT; i++) { const GPUTPCRow& row = tracker.Data().Row(i); for (int j = 0; j <= (signed)row.Grid().Ny(); j++) { @@ -1116,70 +1124,75 @@ GPUDisplay::vboList GPUDisplay::DrawGrid(const GPUTPCTracker& tracker) mVertexBuffer[iSlice].emplace_back(xx2 / GL_SCALE_FACTOR, yy2 / GL_SCALE_FACTOR, zz2 / GL_SCALE_FACTOR); } } - */ - if (iSlice < 18) { - // TODO: tilted pads ignored at the moment - int iSec = iSlice; - auto geo = trdTracker().GetGeometry(); - float alpha = geo->GetAlpha() / 2.f + geo->GetAlpha() * iSec; - if (iSec >= 9) { - alpha -= 2 * M_PI; - } - for (int iLy = 0; iLy < GPUTRDTracker::EGPUTRDTracker::kNLayers; ++iLy) { - for (int iStack = 0; iStack < GPUTRDTracker::EGPUTRDTracker::kNStacks; ++iStack) { - int iDet = geo->GetDetector(iLy, iStack, iSec); - auto matrix = geo->GetClusterMatrix(iDet); - if (!matrix) { - continue; - } - auto pp = geo->GetPadPlane(iDet); - for (int i = 0; i < pp->GetNrows(); ++i) { - float xyzLoc1[3]; - float xyzLoc2[3]; - float xyzGlb1[3]; - float xyzGlb2[3]; - xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); - xyzLoc1[1] = pp->GetCol0(); - xyzLoc2[1] = pp->GetColEnd(); - xyzLoc1[2] = xyzLoc2[2] = pp->GetRowPos(i) - pp->GetRowPos(pp->GetNrows() / 2); - matrix->LocalToMaster(xyzLoc1, xyzGlb1); - matrix->LocalToMaster(xyzLoc2, xyzGlb2); - float x1Tmp = xyzGlb1[0]; - xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); - xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); - float x2Tmp = xyzGlb2[0]; - xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); - xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); - mVertexBuffer[iSlice].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); - mVertexBuffer[iSlice].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); - } - for (int j = 0; j < pp->GetNcols(); ++j) { - float xyzLoc1[3]; - float xyzLoc2[3]; - float xyzGlb1[3]; - float xyzGlb2[3]; - xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); - xyzLoc1[1] = xyzLoc2[1] = pp->GetColPos(j) + pp->GetColSize(j) / 2.f; - xyzLoc1[2] = pp->GetRow0() - pp->GetRowPos(pp->GetNrows() / 2); - xyzLoc2[2] = pp->GetRowEnd() - pp->GetRowPos(pp->GetNrows() / 2); - matrix->LocalToMaster(xyzLoc1, xyzGlb1); - matrix->LocalToMaster(xyzLoc2, xyzGlb2); - float x1Tmp = xyzGlb1[0]; - xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); - xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); - float x2Tmp = xyzGlb2[0]; - xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); - xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); - mVertexBuffer[iSlice].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); - mVertexBuffer[iSlice].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); - } - } - } - } insertVertexList(tracker.ISlice(), startCountInner, mVertexBuffer[iSlice].size()); return (vboList(startCount, mVertexBufferStart[iSlice].size() - startCount, iSlice)); } +GPUDisplay::vboList GPUDisplay::DrawGridTRD(int sector) +{ + // TODO: tilted pads ignored at the moment + size_t startCount = mVertexBufferStart[sector].size(); + size_t startCountInner = mVertexBuffer[sector].size(); + auto geo = mChain->GetTRDGeometry(); + int trdsector = NSLICES / 2 - 1 - sector; + float alpha = geo->GetAlpha() / 2.f + geo->GetAlpha() * trdsector; + if (trdsector >= 9) { + alpha -= 2 * M_PI; + } + for (int iLy = 0; iLy < GPUTRDTracker::EGPUTRDTracker::kNLayers; ++iLy) { + for (int iStack = 0; iStack < GPUTRDTracker::EGPUTRDTracker::kNStacks; ++iStack) { + int iDet = geo->GetDetector(iLy, iStack, trdsector); + auto matrix = geo->GetClusterMatrix(iDet); + if (!matrix) { + continue; + } + auto pp = geo->GetPadPlane(iDet); + for (int i = 0; i < pp->GetNrows(); ++i) { + float xyzLoc1[3]; + float xyzLoc2[3]; + float xyzGlb1[3]; + float xyzGlb2[3]; + xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); + xyzLoc1[1] = pp->GetCol0(); + xyzLoc2[1] = pp->GetColEnd(); + xyzLoc1[2] = xyzLoc2[2] = pp->GetRowPos(i) - pp->GetRowPos(pp->GetNrows() / 2); + matrix->LocalToMaster(xyzLoc1, xyzGlb1); + matrix->LocalToMaster(xyzLoc2, xyzGlb2); + float x1Tmp = xyzGlb1[0]; + xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); + xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); + float x2Tmp = xyzGlb2[0]; + xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); + xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); + mVertexBuffer[sector].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); + mVertexBuffer[sector].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); + } + for (int j = 0; j < pp->GetNcols(); ++j) { + float xyzLoc1[3]; + float xyzLoc2[3]; + float xyzGlb1[3]; + float xyzGlb2[3]; + xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); + xyzLoc1[1] = xyzLoc2[1] = pp->GetColPos(j) + pp->GetColSize(j) / 2.f; + xyzLoc1[2] = pp->GetRow0() - pp->GetRowPos(pp->GetNrows() / 2); + xyzLoc2[2] = pp->GetRowEnd() - pp->GetRowPos(pp->GetNrows() / 2); + matrix->LocalToMaster(xyzLoc1, xyzGlb1); + matrix->LocalToMaster(xyzLoc2, xyzGlb2); + float x1Tmp = xyzGlb1[0]; + xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); + xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); + float x2Tmp = xyzGlb2[0]; + xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); + xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); + mVertexBuffer[sector].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); + mVertexBuffer[sector].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); + } + } + } + insertVertexList(sector, startCountInner, mVertexBuffer[sector].size()); + return (vboList(startCount, mVertexBufferStart[sector].size() - startCount, sector)); +} + int GPUDisplay::DrawGLScene(bool mixAnimation, float mAnimateTime) { try { @@ -1655,6 +1668,9 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) mGlDLLines[iSlice][tTRACKLET] = DrawTracklets(tracker); mGlDLLines[iSlice][tSLICETRACK] = DrawTracks(tracker, 0); mGlDLGrid[iSlice] = DrawGrid(tracker); + if (iSlice < NSLICES / 2) { + mGlDLGridTRD[iSlice] = DrawGridTRD(iSlice); + } } GPUCA_OPENMP(barrier) @@ -1829,7 +1845,8 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) #endif } -#define LOOP_SLICE for (int iSlice = (mCfg.drawSlice == -1 ? 0 : mCfg.drawRelatedSlices ? (mCfg.drawSlice % 9) : mCfg.drawSlice); iSlice < NSLICES; iSlice += (mCfg.drawSlice == -1 ? 1 : mCfg.drawRelatedSlices ? 9 : NSLICES)) +#define LOOP_SLICE for (int iSlice = (mCfg.drawSlice == -1 ? 0 : mCfg.drawRelatedSlices ? (mCfg.drawSlice % (NSLICES / 4)) : mCfg.drawSlice); iSlice < NSLICES; iSlice += (mCfg.drawSlice == -1 ? 1 : mCfg.drawRelatedSlices ? (NSLICES / 4) : NSLICES)) +#define LOOP_SLICE2 for (int iSlice = (mCfg.drawSlice == -1 ? 0 : mCfg.drawRelatedSlices ? (mCfg.drawSlice % (NSLICES / 4)) : mCfg.drawSlice) % (NSLICES / 2); iSlice < NSLICES / 2; iSlice += (mCfg.drawSlice == -1 ? 1 : mCfg.drawRelatedSlices ? (NSLICES / 4) : NSLICES)) #define LOOP_COLLISION for (int iCol = (mCfg.showCollision == -1 ? 0 : mCfg.showCollision); iCol < mNCollissions; iCol += (mCfg.showCollision == -1 ? 1 : mNCollissions)) #define LOOP_COLLISION_COL(cmd) \ LOOP_COLLISION \ @@ -1841,8 +1858,14 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) } if (mCfg.drawGrid) { - SetColorGrid(); - LOOP_SLICE drawVertices(mGlDLGrid[iSlice], GL_LINES); + if (mCfg.drawTPC) { + SetColorGrid(); + LOOP_SLICE drawVertices(mGlDLGrid[iSlice], GL_LINES); + } + if (mCfg.drawTRD) { + SetColorGridTRD(); + LOOP_SLICE2 drawVertices(mGlDLGridTRD[iSlice], GL_LINES); + } } if (mCfg.drawClusters) { if (mCfg.drawTRD) { diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.h b/GPU/GPUTracking/Standalone/display/GPUDisplay.h index 7852562ea11b8..036f414c56c9f 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.h @@ -261,6 +261,7 @@ class GPUDisplay void SetColorGlobalTracks(); void SetColorFinal(); void SetColorGrid(); + void SetColorGridTRD(); void SetColorMarked(); void SetCollisionColor(int col); void setQuality(); @@ -282,6 +283,7 @@ class GPUDisplay vboList DrawTracks(const GPUTPCTracker& tracker, int global); void DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, std::array<vecpod<int>, 2>& trackList, threadVertexBuffer& threadBuffer); vboList DrawGrid(const GPUTPCTracker& tracker); + vboList DrawGridTRD(int sector); void DoScreenshot(char* filename, float mAnimateTime = -1.f); void PrintHelp(); void createQuaternionFromMatrix(float* v, const float* mat); @@ -408,6 +410,7 @@ class GPUDisplay vecpod<std::array<vboList, N_FINAL_TYPE>> mGlDLFinal[NSLICES]; vecpod<vboList> mGlDLPoints[NSLICES][N_POINTS_TYPE]; vboList mGlDLGrid[NSLICES]; + vboList mGlDLGridTRD[NSLICES / 2]; vecpod<DrawArraysIndirectCommand> mCmdBuffer; }; } // namespace gpu From 878528ac9d55f610d15bfd8e666a89b1f78d18be Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 22 Oct 2020 22:32:21 +0200 Subject: [PATCH 1065/1751] Make more parts of TrackParCov and Propagator compatible to GPU --- .../TrackParametrization.h | 26 ++++++++++++++----- .../TrackParametrizationWithError.h | 2 +- .../src/TrackParametrization.cxx | 4 ++- .../src/TrackParametrizationWithError.cxx | 4 ++- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 9ed5e084846e8..d9ffc0be528ce 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -25,7 +25,9 @@ #ifndef INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATION_H_ #define INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKPARAMETRIZATION_H_ +#include "GPUCommonDef.h" #include "GPUCommonRtypes.h" +#include "GPUCommonMath.h" #ifndef __OPENCL__ #include <algorithm> @@ -210,8 +212,8 @@ class TrackParametrization uint16_t getUserField() const; void setUserField(uint16_t v); -#ifndef GPUCA_ALIGPUCODE void printParam() const; +#ifndef GPUCA_ALIGPUCODE std::string asString() const; #endif @@ -566,14 +568,18 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu return -std::log(std::tan(0.5f * getTheta())); } -#ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden //_______________________________________________________ template <typename value_T> inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGlo() const { +#ifndef GPUCA_ALIGPUCODE return math_utils::Rotation2D<value_t>(getAlpha())(math_utils::Point3D<value_t>(getX(), getY(), getZ())); -} +#else // mockup on GPU without ROOT + float sina, cosa; + o2::gpu::CAMath::SinCos(getAlpha(), sina, cosa); + return math_utils::Point3D<value_t>(cosa * getX() + sina * getY(), cosa * getY() - sina * getX(), getZ()); #endif +} //_______________________________________________________ template <typename value_T> @@ -586,7 +592,6 @@ inline void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const math_utils::detail::rotateZ<value_t>(xyz, getAlpha()); } -#ifndef GPUCA_ALIGPUCODE //These functions clash with GPU code and are thus hidden //_______________________________________________________ template <typename value_T> inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGloAt(value_t xk, value_t b, bool& ok) const @@ -596,9 +601,18 @@ inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> Trac //---------------------------------------------------------------- value_t y = 0.f, z = 0.f; ok = getYZAt(xk, b, y, z); - return ok ? math_utils::Rotation2D<value_t>(getAlpha())(math_utils::Point3D<value_t>(xk, y, z)) : math_utils::Point3D<value_t>(); -} + if (ok) { +#ifndef GPUCA_ALIGPUCODE + return math_utils::Rotation2D<value_t>(getAlpha())(math_utils::Point3D<value_t>(xk, y, z)); +#else // mockup on GPU without ROOT + float sina, cosa; + o2::gpu::CAMath::SinCos(getAlpha(), sina, cosa); + return math_utils::Point3D<value_t>(cosa * xk + sina * y, cosa * y - sina * xk, z); #endif + } else { + return math_utils::Point3D<value_t>(); + } +} //____________________________________________________________ template <typename value_T> diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index 02b77b0fefdd0..ce9be0e0bf901 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -71,8 +71,8 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> bool getCovXYZPxPyPzGlo(std::array<value_t, kLabCovMatSize>& c) const; -#ifndef GPUCA_ALIGPUCODE void print() const; +#ifndef GPUCA_ALIGPUCODE std::string asString() const; #endif diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index 228a4f8890022..72086dba824c2 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -488,15 +488,17 @@ std::string TrackParametrization<value_T>::asString() const return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d} {:s}", getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName()); } +#endif //______________________________________________________________ template <typename value_T> void TrackParametrization<value_T>::printParam() const { // print parameters +#ifndef GPUCA_ALIGPUCODE printf("%s\n", asString().c_str()); -} #endif +} //______________________________________________________________ template <typename value_T> diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index 6bcb26db98aab..cb4d7e3282b89 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -1076,13 +1076,16 @@ std::string TrackParametrizationWithError<value_T>::asString() const mC[kSigTglZ], mC[kSigTglSnp], mC[kSigTgl2], "", mC[kSigQ2PtY], mC[kSigQ2PtZ], mC[kSigQ2PtSnp], mC[kSigQ2PtTgl], mC[kSigQ2Pt2]); } +#endif //______________________________________________________________ template <typename value_T> void TrackParametrizationWithError<value_T>::print() const { // print parameters +#ifndef GPUCA_ALIGPUCODE printf("%s\n", asString().c_str()); +#endif } template class TrackParametrizationWithError<float>; @@ -1090,4 +1093,3 @@ template class TrackParametrizationWithError<double>; } // namespace track } // namespace o2 -#endif From 27b0753235ff2c737b0c747dbf37d095b8a35703 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 10:16:34 +0200 Subject: [PATCH 1066/1751] Hide some code for compilation on GPU --- Common/Field/include/Field/MagFieldFast.h | 8 +- Common/Field/src/MagFieldFast.cxx | 14 ++- .../MathUtils/include/MathUtils/Cartesian.h | 7 +- DataFormats/Reconstruction/CMakeLists.txt | 1 + .../src/TrackParametrization.cxx | 11 +- .../src/TrackParametrizationWithError.cxx | 11 +- Detectors/Base/src/Propagator.cxx | 111 ++++++++++-------- 7 files changed, 98 insertions(+), 65 deletions(-) diff --git a/Common/Field/include/Field/MagFieldFast.h b/Common/Field/include/Field/MagFieldFast.h index d9215fedf559f..4d904e7adc464 100644 --- a/Common/Field/include/Field/MagFieldFast.h +++ b/Common/Field/include/Field/MagFieldFast.h @@ -14,11 +14,13 @@ #ifndef ALICEO2_FIELD_MAGFIELDFAST_H_ #define ALICEO2_FIELD_MAGFIELDFAST_H_ -#include <Rtypes.h> -#include <string> - +#include <GPUCommonRtypes.h> #include "MathUtils/Cartesian.h" +#ifndef GPUCA_GPUCODE_DEVICE +#include <string> +#endif + namespace o2 { namespace field diff --git a/Common/Field/src/MagFieldFast.cxx b/Common/Field/src/MagFieldFast.cxx index ffc1da28e1d75..4bd709e8f9e69 100644 --- a/Common/Field/src/MagFieldFast.cxx +++ b/Common/Field/src/MagFieldFast.cxx @@ -13,15 +13,16 @@ /// \author ruben.shahoyan@cern.ch // #include "Field/MagFieldFast.h" -#include <FairLogger.h> -#include <TString.h> -#include <TSystem.h> +#include <GPUCommonLogger.h> + +#ifndef GPUCA_GPUCODE_DEVICE #include <cmath> #include <fstream> #include <sstream> +using namespace std; +#endif using namespace o2::field; -using namespace std; ClassImp(o2::field::MagFieldFast); @@ -30,6 +31,10 @@ const float MagFieldFast::kSolR2Max[MagFieldFast::kNSolRRanges] = {80.f * 80.f, const float MagFieldFast::kSolZMax = 550.0f; +#ifndef GPUCA_STANDALONE +#include <TString.h> +#include <TSystem.h> + //_______________________________________________________________________ MagFieldFast::MagFieldFast(const string inpFName) : mFactorSol(1.f) { @@ -106,6 +111,7 @@ bool MagFieldFast::LoadData(const string inpFName) } return true; } +#endif // GPUCA_STANDALONE //_______________________________________________________________________ bool MagFieldFast::Field(const double xyz[3], double bxyz[3]) const diff --git a/Common/MathUtils/include/MathUtils/Cartesian.h b/Common/MathUtils/include/MathUtils/Cartesian.h index 8166c4166d283..3cdd23a144b3b 100644 --- a/Common/MathUtils/include/MathUtils/Cartesian.h +++ b/Common/MathUtils/include/MathUtils/Cartesian.h @@ -148,6 +148,8 @@ class Rotation2D using Rotation2Df_t = Rotation2D<float>; using Rotation2Dd_t = Rotation2D<double>; +#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIGPUCODE) + class Transform3D : public ROOT::Math::Transform3D { // @@ -241,11 +243,12 @@ class Transform3D : public ROOT::Math::Transform3D ClassDefNV(Transform3D, 1); }; +#endif // Disable for GPU } // namespace math_utils } // namespace o2 +#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIGPUCODE) std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2Df_t& t); - std::ostream& operator<<(std::ostream& os, const o2::math_utils::Rotation2Dd_t& t); namespace std @@ -266,4 +269,6 @@ template <typename T> struct is_trivially_copyable<o2::math_utils::Point3D<T>> : std::true_type { }; } // namespace std +#endif // Disable for GPU + #endif diff --git a/DataFormats/Reconstruction/CMakeLists.txt b/DataFormats/Reconstruction/CMakeLists.txt index bef53810a63a2..d8e4e17c54d08 100644 --- a/DataFormats/Reconstruction/CMakeLists.txt +++ b/DataFormats/Reconstruction/CMakeLists.txt @@ -23,6 +23,7 @@ o2_add_library(ReconstructionDataFormats src/VtxTrackIndex.cxx src/VtxTrackRef.cxx PUBLIC_LINK_LIBRARIES O2::GPUCommon + O2::FrameworkLogger O2::DetectorsCommonDataFormats O2::CommonDataFormat) diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index 72086dba824c2..af17de8b1e7f4 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -26,11 +26,16 @@ #include "ReconstructionDataFormats/TrackParametrization.h" #include "ReconstructionDataFormats/Vertex.h" #include "ReconstructionDataFormats/DCA.h" -#include <FairLogger.h> -#include <iostream> +#include <GPUCommonLogger.h> #include "Math/SMatrix.h" + +#ifndef GPUCA_GPUCODE_DEVICE +#include <iostream> +#endif + +#ifndef GPUCA_ALIGPUCODE #include <fmt/printf.h> -#include "Framework/Logger.h" +#endif namespace o2 { diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index cb4d7e3282b89..fbefce1c7bcb2 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -26,11 +26,16 @@ #include "ReconstructionDataFormats/TrackParametrizationWithError.h" #include "ReconstructionDataFormats/Vertex.h" #include "ReconstructionDataFormats/DCA.h" -#include <FairLogger.h> -#include <iostream> +#include <GPUCommonLogger.h> #include "Math/SMatrix.h" + +#ifndef GPUCA_GPUCODE_DEVICE +#include <iostream> +#endif + +#ifndef GPUCA_ALIGPUCODE #include <fmt/printf.h> -#include "Framework/Logger.h" +#endif namespace o2 { diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 62767f2cfa4c6..c9e83f16436b4 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -9,18 +9,20 @@ // or submit itself to any jurisdiction. #include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include <FairLogger.h> -#include <FairRunAna.h> // eventually will get rid of it -#include <TGeoGlobalMagField.h> -#include "DataFormatsParameters/GRPObject.h" +#include <GPUCommonLogger.h> #include "Field/MagFieldFast.h" -#include "Field/MagneticField.h" #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/Vertex.h" using namespace o2::base; +#ifndef GPUCA_STANDALONE +#include "Field/MagneticField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include <FairRunAna.h> // eventually will get rid of it +#include <TGeoGlobalMagField.h> + Propagator::Propagator() { ///< construct checking if needed components were initialized @@ -47,6 +49,52 @@ Propagator::Propagator() mField->GetBz(xyz, mBz); } +//____________________________________________________________ +int Propagator::initFieldFromGRP(const std::string grpFileName, std::string grpName, bool verbose) +{ + /// load grp and init magnetic field + if (verbose) { + LOG(INFO) << "Loading field from GRP of " << grpFileName; + } + const auto grp = o2::parameters::GRPObject::loadFrom(grpFileName, grpName); + if (!grp) { + return -1; + } + if (verbose) { + grp->print(); + } + + return initFieldFromGRP(grp); +} + +//____________________________________________________________ +int Propagator::initFieldFromGRP(const o2::parameters::GRPObject* grp, bool verbose) +{ + /// init mag field from GRP data and attach it to TGeoGlobalMagField + + if (TGeoGlobalMagField::Instance()->IsLocked()) { + if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) { + LOG(WARNING) << "ExpertMode!!! GRP information will be ignored"; + LOG(WARNING) << "ExpertMode!!! Running with the externally locked B field"; + return 0; + } else { + LOG(INFO) << "Destroying existing B field instance"; + delete TGeoGlobalMagField::Instance(); + } + } + auto fld = o2::field::MagneticField::createFieldMap(grp->getL3Current(), grp->getDipoleCurrent()); + TGeoGlobalMagField::Instance()->SetField(fld); + TGeoGlobalMagField::Instance()->Lock(); + if (verbose) { + LOG(INFO) << "Running with the B field constructed out of GRP"; + LOG(INFO) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via"; + LOG(INFO) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )"; + } + return 0; +} + +#endif + //_______________________________________________________________________ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, float mass, float maxSnp, float maxStep, Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const @@ -462,52 +510,13 @@ bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2: return true; } -//____________________________________________________________ -int Propagator::initFieldFromGRP(const std::string grpFileName, std::string grpName, bool verbose) -{ - /// load grp and init magnetic field - if (verbose) { - LOG(INFO) << "Loading field from GRP of " << grpFileName; - } - const auto grp = o2::parameters::GRPObject::loadFrom(grpFileName, grpName); - if (!grp) { - return -1; - } - if (verbose) { - grp->print(); - } - - return initFieldFromGRP(grp); -} - -//____________________________________________________________ -int Propagator::initFieldFromGRP(const o2::parameters::GRPObject* grp, bool verbose) -{ - /// init mag field from GRP data and attach it to TGeoGlobalMagField - - if (TGeoGlobalMagField::Instance()->IsLocked()) { - if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) { - LOG(WARNING) << "ExpertMode!!! GRP information will be ignored"; - LOG(WARNING) << "ExpertMode!!! Running with the externally locked B field"; - return 0; - } else { - LOG(INFO) << "Destroying existing B field instance"; - delete TGeoGlobalMagField::Instance(); - } - } - auto fld = o2::field::MagneticField::createFieldMap(grp->getL3Current(), grp->getDipoleCurrent()); - TGeoGlobalMagField::Instance()->SetField(fld); - TGeoGlobalMagField::Instance()->Lock(); - if (verbose) { - LOG(INFO) << "Running with the B field constructed out of GRP"; - LOG(INFO) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via"; - LOG(INFO) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )"; - } - return 0; -} - //____________________________________________________________ MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, const math_utils::Point3D<float>& p0, const math_utils::Point3D<float>& p1) const { - return (corrType == MatCorrType::USEMatCorrTGeo) ? GeometryManager::meanMaterialBudget(p0, p1) : mMatLUT->getMatBudget(p0.X(), p0.Y(), p0.Z(), p1.X(), p1.Y(), p1.Z()); +#ifndef GPUCA_STANDALONE + if (corrType == MatCorrType::USEMatCorrTGeo) { + return GeometryManager::meanMaterialBudget(p0, p1); + } +#endif + return mMatLUT->getMatBudget(p0.X(), p0.Y(), p0.Z(), p1.X(), p1.Y(), p1.Z()); } From 675af916540736135d2a2e31934e287c6c44c72c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 10:17:35 +0200 Subject: [PATCH 1067/1751] Fix compile warnings / use LOGP instead of LOGF if string ha python syntax --- Common/Field/src/MagFieldFast.cxx | 2 +- .../Reconstruction/src/TrackParametrization.cxx | 6 +++--- .../src/TrackParametrizationWithError.cxx | 10 +++++----- GPU/Common/GPUCommonLogger.h | 11 ++++++++++- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 6 +++--- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Common/Field/src/MagFieldFast.cxx b/Common/Field/src/MagFieldFast.cxx index 4bd709e8f9e69..34eeadfc3b59c 100644 --- a/Common/Field/src/MagFieldFast.cxx +++ b/Common/Field/src/MagFieldFast.cxx @@ -240,7 +240,7 @@ bool MagFieldFast::GetSegment(float x, float y, float z, int& zSeg, int& rSeg, i } } if (rSeg == kNSolRRanges) { - return kFALSE; + return false; } quadrant = GetQuadrant(x, y); return true; diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index af17de8b1e7f4..ae78900a42cb6 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -159,7 +159,7 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) { // rotate to alpha frame if (std::fabs(getSnp()) > constants::math::Almost1) { - LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); + LOGP(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); return false; } // @@ -177,7 +177,7 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) // value_t tmp = snp * ca - csp * sa; if (std::fabs(tmp) > constants::math::Almost1) { - LOGF(WARNING, "Rotation failed: new snp {:.2f}", tmp); + LOGP(WARNING, "Rotation failed: new snp {:.2f}", tmp); return false; } value_t xold = getX(), yold = getY(); @@ -205,7 +205,7 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b } // Do not propagate tracks outside the ALICE detector if (std::fabs(dx) > 1e5 || std::fabs(getY()) > 1e5 || std::fabs(getZ()) > 1e5) { - LOGF(WARNING, "Anomalous track, target X:{:f}", xk); + LOGP(WARNING, "Anomalous track, target X:{:f}", xk); // print(); return false; } diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index fbefce1c7bcb2..2d340193251c5 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -168,7 +168,7 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) { // rotate to alpha frame if (std::fabs(this->getSnp()) > constants::math::Almost1) { - LOGF(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", this->getSnp()); + LOGP(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", this->getSnp()); return false; } // @@ -180,14 +180,14 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle // direction in local frame is along the X axis if ((csp * ca + snp * sa) < 0) { - //LOGF(WARNING,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa); + //LOGP(WARNING,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa); return false; } // value_t updSnp = snp * ca - csp * sa; if (std::fabs(updSnp) > constants::math::Almost1) { - LOGF(WARNING, "Rotation failed: new snp {:.2f}", updSnp); + LOGP(WARNING, "Rotation failed: new snp {:.2f}", updSnp); return false; } value_t xold = this->getX(), yold = this->getY(); @@ -197,7 +197,7 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) this->setSnp(updSnp); if (std::fabs(csp) < constants::math::Almost0) { - LOGF(WARNING, "Too small cosine value {:f}", csp); + LOGP(WARNING, "Too small cosine value {:f}", csp); csp = constants::math::Almost0; } @@ -429,7 +429,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ } // Do not propagate tracks outside the ALICE detector if (std::fabs(dx) > 1e5 || std::fabs(this->getY()) > 1e5 || std::fabs(this->getZ()) > 1e5) { - LOGF(WARNING, "Anomalous track, target X:{:f}", xk); + LOGP(WARNING, "Anomalous track, target X:{:f}", xk); // print(); return false; } diff --git a/GPU/Common/GPUCommonLogger.h b/GPU/Common/GPUCommonLogger.h index e418987edc66e..6c0c851a1c82c 100644 --- a/GPU/Common/GPUCommonLogger.h +++ b/GPU/Common/GPUCommonLogger.h @@ -17,13 +17,18 @@ #if defined(__OPENCL__) #define LOG(...) #define LOGF(...) +#define LOGP(...) #elif defined(GPUCA_GPUCODE_DEVICE) -#define LOG(...) +#define LOG(...) static_assert("LOG(...) << ... unsupported in GPU code"); #define LOGF(type, string, ...) \ { \ printf(string "\n", ##__VA_ARGS__); \ } +#define LOGP(type, string, ...) \ + { \ + printf(string "\n"); \ + } #elif defined(GPUCA_STANDALONE) || \ defined(GPUCA_ALIROOT_LIB) || \ @@ -36,6 +41,10 @@ { \ printf(string "\n", ##__VA_ARGS__); \ } +#define LOGP(type, string, ...) \ + { \ + printf(string "\n"); \ + } #else #include <Framework/Logger.h> diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index ab1bdeacf006c..0612463158b30 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -252,11 +252,11 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) int start = outward ? count - 1 : begin; int stop = outward ? begin - 1 : count; const ClusterNative* cl = nullptr; - uint8_t sector, row, currentSector, currentRow; - short clusterState, nextState; + uint8_t sector, row = 0, currentSector = 0, currentRow = 0; + short clusterState = 0, nextState; int nFitted = 0; for (int i = start; i != stop; i += cl ? 0 : direction) { - float x, y, z, charge; + float x, y, z, charge = 0.f; int clusters = 0; while (true) { if (!cl) { From 6b79e871edd33b2aa0927a4972630da4f00624e1 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 10:19:47 +0200 Subject: [PATCH 1068/1751] Compile TrackParCov/Propagator on GPU/in standalone benchmark --- GPU/GPUTracking/Standalone/CMakeLists.txt | 33 ++++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index a1a56664a65f6..cc513a36b9849 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -121,6 +121,7 @@ if(CONFIG_O2_EXTENSIONS) include_directories(${CMAKE_SOURCE_DIR}/TPCClusterFinder ${CMAKE_SOURCE_DIR}/ITS ${CMAKE_SOURCE_DIR}/DataCompression + ${CMAKE_SOURCE_DIR}/../../../Common/Field/include ${CMAKE_SOURCE_DIR}/../../../Common/Constants/include ${CMAKE_SOURCE_DIR}/../../../Common/MathUtils/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/common/include @@ -160,21 +161,27 @@ target_compile_definitions(standalone_support PUBLIC $<TARGET_PROPERTY:O2::GPUTr # Add all sources and dependencies to to support based on Config File if(CONFIG_O2_EXTENSIONS) target_sources(standalone_support PRIVATE - ../../..//DataFormats/Detectors/TPC/src/CompressedClusters.cxx - ../../..//DataFormats/simulation/src/MCCompLabel.cxx - ../../..//Detectors/TRD/base/src/TRDGeometryBase.cxx - ../../..//Detectors/Base/src/MatLayerCylSet.cxx - ../../..//Detectors/Base/src/MatLayerCyl.cxx - ../../..//Detectors/Base/src/Ray.cxx - ../../..//Detectors/ITSMFT/ITS/tracking/src/Road.cxx) + ../../../Common/Field/src/MagFieldFast.cxx + ../../../DataFormats/Detectors/TPC/src/CompressedClusters.cxx + ../../../DataFormats/simulation/src/MCCompLabel.cxx + ../../../DataFormats/Reconstruction/src/TrackParametrization.cxx + ../../../DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx + ../../../DataFormats/Reconstruction/src/Vertex.cxx + ../../../DataFormats/Reconstruction/src/TrackLTIntegral.cxx + ../../../Detectors/TRD/base/src/TRDGeometryBase.cxx + ../../../Detectors/Base/src/MatLayerCylSet.cxx + ../../../Detectors/Base/src/MatLayerCyl.cxx + ../../../Detectors/Base/src/Ray.cxx + ../../../Detectors/Base/src/Propagator.cxx + ../../../Detectors/ITSMFT/ITS/tracking/src/Road.cxx) if(CONFIG_O2_ITS_TRAITS) target_sources(standalone_support PRIVATE - ../../..//Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx - ../../..//Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx - ../../..//Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx - ../../..//Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx - ../../..//Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx - ../../..//Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx) + ../../../Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx + ../../../Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx + ../../../Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx + ../../../Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx + ../../../Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx + ../../../Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx) target_link_libraries(standalone_support PUBLIC Boost::boost) endif() endif() From 76a8acbecbc16f746d10d30a01fe55d35b7b40d3 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 10:19:19 +0200 Subject: [PATCH 1069/1751] Add mockup for Point2D / Point3D without ROOT for GPU compilation --- Common/MathUtils/CMakeLists.txt | 1 + .../MathUtils/include/MathUtils/Cartesian.h | 19 ++++---- .../include/MathUtils/CartesianGPU.h | 48 +++++++++++++++++++ .../macro/createResidualDistortionObject.C | 1 + .../TPC/simulation/test/testTPCSimulation.cxx | 3 +- GPU/Common/GPUROOTCartesianFwd.h | 29 +++++++++++ 6 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 Common/MathUtils/include/MathUtils/CartesianGPU.h diff --git a/Common/MathUtils/CMakeLists.txt b/Common/MathUtils/CMakeLists.txt index 25b369097b408..0fa418fb1c385 100644 --- a/Common/MathUtils/CMakeLists.txt +++ b/Common/MathUtils/CMakeLists.txt @@ -30,6 +30,7 @@ o2_target_root_dictionary( include/MathUtils/Chebyshev3DCalc.h include/MathUtils/fit.h include/MathUtils/Cartesian.h + include/MathUtils/CartesianGPU.h include/MathUtils/CachingTF1.h include/MathUtils/RandomRing.h include/MathUtils/Primitive2D.h) diff --git a/Common/MathUtils/include/MathUtils/Cartesian.h b/Common/MathUtils/include/MathUtils/Cartesian.h index 3cdd23a144b3b..82f9acfdd1aaf 100644 --- a/Common/MathUtils/include/MathUtils/Cartesian.h +++ b/Common/MathUtils/include/MathUtils/Cartesian.h @@ -15,6 +15,9 @@ #ifndef ALICEO2_CARTESIAN3D_H #define ALICEO2_CARTESIAN3D_H +#include "GPUCommonDef.h" +#include "GPUCommonRtypes.h" +#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE) #include <Math/GenVector/DisplacementVector3D.h> #include <Math/GenVector/PositionVector3D.h> #include <Math/GenVector/Rotation3D.h> @@ -22,9 +25,13 @@ #include <Math/GenVector/Translation3D.h> #include <Math/GenVector/DisplacementVector2D.h> #include <Math/GenVector/PositionVector2D.h> -#include <Rtypes.h> #include <TGeoMatrix.h> #include <iosfwd> +#else +#include "GPUCommonMath.h" +#include "CartesianGPU.h" +#endif +#include "GPUROOTCartesianFwd.h" namespace o2 { @@ -32,16 +39,6 @@ namespace o2 namespace math_utils { -template <typename T> -using Point2D = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; -template <typename T> -using Vector2D = ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; - -template <typename T> -using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; -template <typename T> -using Vector3D = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; - // more typedefs can follow /// predefined transformations: Tracking->Local, Tracking->Global, Local->Global etc diff --git a/Common/MathUtils/include/MathUtils/CartesianGPU.h b/Common/MathUtils/include/MathUtils/CartesianGPU.h new file mode 100644 index 0000000000000..93cc00633dd2d --- /dev/null +++ b/Common/MathUtils/include/MathUtils/CartesianGPU.h @@ -0,0 +1,48 @@ +// 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 CartesianGPU.h +/// @author David Rohr + +#ifndef ALICEO2_CARTESIANGPU_H +#define ALICEO2_CARTESIANGPU_H + +namespace o2::math_utils +{ + +namespace detail +{ +template <typename T, int I> +struct GPUPoint2D { + GPUPoint2D() = default; + GPUPoint2D(T a, T b) : xx(a), yy(b) {} + T xx; + T yy; + float X() const { return xx; } + float Y() const { return yy; } + float R() const { return o2::gpu::CAMath::Sqrt(xx * xx + yy * yy); } + void SetX(float v) { xx = v; } + void SetY(float v) { yy = v; } +}; + +template <typename T, int I> +struct GPUPoint3D : public GPUPoint2D<T, I> { + GPUPoint3D() = default; + GPUPoint3D(T a, T b, T c) : GPUPoint2D<T, I>(a, b), zz(c) {} + T zz; + float Z() const { return zz; } + float R() const { return o2::gpu::CAMath::Sqrt(GPUPoint2D<T, I>::xx * GPUPoint2D<T, I>::xx + GPUPoint2D<T, I>::yy * GPUPoint2D<T, I>::yy + zz * zz); } + void SetZ(float v) { zz = v; } +}; +} // namespace detail + +} // end namespace o2::math_utils + +#endif diff --git a/Detectors/TPC/simulation/macro/createResidualDistortionObject.C b/Detectors/TPC/simulation/macro/createResidualDistortionObject.C index 8660a8dfa25b3..1dcd960a64996 100644 --- a/Detectors/TPC/simulation/macro/createResidualDistortionObject.C +++ b/Detectors/TPC/simulation/macro/createResidualDistortionObject.C @@ -23,6 +23,7 @@ #include "CommonConstants/MathConstants.h" #include "CommonUtils/TreeStreamRedirector.h" #include "TPCSimulation/SpaceCharge.h" +#include "MathUtils/Cartesian.h" using namespace o2::tpc; diff --git a/Detectors/TPC/simulation/test/testTPCSimulation.cxx b/Detectors/TPC/simulation/test/testTPCSimulation.cxx index 34a9bafb2197b..0982ffa7c8c96 100644 --- a/Detectors/TPC/simulation/test/testTPCSimulation.cxx +++ b/Detectors/TPC/simulation/test/testTPCSimulation.cxx @@ -18,9 +18,10 @@ #include <boost/test/unit_test.hpp> #include "TPCSimulation/Point.h" #include "TPCSimulation/DigitMCMetaData.h" +#include "MathUtils/Cartesian.h" template <typename T> -using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +using Point3D = o2::math_utils::Point3D<T>; namespace o2 { diff --git a/GPU/Common/GPUROOTCartesianFwd.h b/GPU/Common/GPUROOTCartesianFwd.h index 3c495a9d446af..dd8b9b53bbcb8 100644 --- a/GPU/Common/GPUROOTCartesianFwd.h +++ b/GPU/Common/GPUROOTCartesianFwd.h @@ -17,6 +17,8 @@ // Standalone forward declarations for Cartesian2D / Cartesian3D / Point2D / Point3D etc. // To be used on GPU where ROOT is not available. +#include "GPUCommonDef.h" + namespace ROOT { namespace Math @@ -31,6 +33,10 @@ template <class CoordSystem, class Tag> class PositionVector2D; template <class CoordSystem, class Tag> class PositionVector3D; +template <class CoordSystem, class Tag> +class DisplacementVector2D; +template <class CoordSystem, class Tag> +class DisplacementVector3D; template <class T> class Cartesian2D; template <class T> @@ -44,10 +50,33 @@ namespace o2 namespace math_utils { +namespace detail +{ +template <typename T, int I> +struct GPUPoint2D; +template <typename T, int I> +struct GPUPoint3D; +} // namespace detail + +#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE) template <typename T> using Point2D = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; template <typename T> +using Vector2D = ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +template <typename T> using Point3D = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +template <typename T> +using Vector3D = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>; +#else +template <typename T> +using Point2D = detail::GPUPoint2D<T, 0>; +template <typename T> +using Vector2D = detail::GPUPoint2D<T, 1>; +template <typename T> +using Point3D = detail::GPUPoint3D<T, 0>; +template <typename T> +using Vector3D = detail::GPUPoint3D<T, 1>; +#endif } // namespace math_utils } // namespace o2 From 553eba1068e7ed1c9cc6cc32fb8fe076a44bb922 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 22:14:27 +0200 Subject: [PATCH 1070/1751] revert temporary changes that were required to keep new math_utils compatible to QC (#4663) * Revert "Temporarily add more aliases to fix QC compilation" This reverts commit bbd0c9034a8579c0521888af7f8464cfc636298c. * Revert "[math_utils] temporary namespace alias" This reverts commit 74b7ce0a81635842c38a31c1e62efa95f5b126ae. --- Common/MathUtils/include/MathUtils/Utils.h | 8 -------- .../include/ITSMFTReconstruction/RawPixelReader.h | 6 ------ 2 files changed, 14 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index 52bf7ff22a8a1..d8c4061b4667a 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -224,12 +224,4 @@ using detail::numberOfBitsSet; } // namespace math_utils } // namespace o2 -namespace o2 -{ -namespace utils -{ -using namespace math_utils; -} // namespace utils -} // namespace o2 - #endif diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h index c6d0d872940cf..c09bf6d5bac89 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h @@ -27,7 +27,6 @@ #include "ITSMFTReconstruction/GBTLink.h" #include "ITSMFTReconstruction/RUDecodeData.h" #include "DetectorsRaw/RDHUtils.h" -#include "MathUtils/Cartesian.h" #include <TTree.h> #include <TStopwatch.h> @@ -48,13 +47,8 @@ #define OUTHEX(v, l) "0x" << std::hex << std::setfill('0') << std::setw(l) << v << std::dec -template <typename T> -using Point3D = o2::math_utils::Point3D<T>; - namespace o2 { -using TransformType = o2::math_utils::TransformType; - namespace itsmft { From 529f43ae81d9664f3c55c4e8453805c9728a0fca Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 23 Oct 2020 16:06:45 +0200 Subject: [PATCH 1071/1751] DPL: drop exception from example --- Framework/TestWorkflows/src/o2DiamondWorkflow.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx index 54e973b4c1f8c..eb1099cdbb7a9 100644 --- a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx +++ b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx @@ -42,7 +42,6 @@ AlgorithmSpec simplePipe(std::string const& what, int minDelay) return AlgorithmSpec{adaptStateful([what, minDelay]() { srand(getpid()); return adaptStateless([what, minDelay](DataAllocator& outputs) { - throw runtime_error_f("This is an error %d", 1); std::this_thread::sleep_for(std::chrono::seconds((rand() % 5) + minDelay)); auto& bData = outputs.make<int>(OutputRef{what}, 1); }); From 7f2b073abc91e021f14161b90c9f50fff764cbbf Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 23 Oct 2020 16:09:14 +0200 Subject: [PATCH 1072/1751] DPL GUI: nicer palette --- Framework/Core/src/FrameworkGUIDebugger.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/Core/src/FrameworkGUIDebugger.cxx index f3035a4c5b92e..077b461c39504 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/Core/src/FrameworkGUIDebugger.cxx @@ -72,9 +72,9 @@ ImVec4 colorForLogLevel(LogParsingHelpers::LogLevel logLevel) case LogParsingHelpers::LogLevel::Error: return PaletteHelpers::RED; case LogParsingHelpers::LogLevel::Unknown: - return ImVec4(153. / 255, 61. / 255, 61. / 255, 255. / 255); + return ImVec4(194. / 255, 195. / 255, 199. / 255, 255. / 255); default: - return PaletteHelpers::WHITE; + return ImVec4(194. / 255, 195. / 255, 199. / 255, 255. / 255); }; } From 128299938afe26155eb4403f73dd33cbab8c18eb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 21 Oct 2020 20:40:51 +0200 Subject: [PATCH 1073/1751] DPL: improve metric creation --- .../include/Framework/DeviceMetricsInfo.h | 110 ++++++++++++++++-- Framework/Core/src/DeviceMetricsInfo.cxx | 12 +- .../Core/test/test_DeviceMetricsInfo.cxx | 56 +++++++++ 3 files changed, 160 insertions(+), 18 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceMetricsInfo.h b/Framework/Core/include/Framework/DeviceMetricsInfo.h index 7e6781b114b07..b314c62707494 100644 --- a/Framework/Core/include/Framework/DeviceMetricsInfo.h +++ b/Framework/Core/include/Framework/DeviceMetricsInfo.h @@ -8,19 +8,19 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -#ifndef FRAMEWORK_DEVICEMETRICSINFO_H -#define FRAMEWORK_DEVICEMETRICSINFO_H +#ifndef O2_FRAMEWORK_DEVICEMETRICSINFO_H_ +#define O2_FRAMEWORK_DEVICEMETRICSINFO_H_ +#include "Framework/RuntimeError.h" #include <array> #include <cstddef> +#include <cstring> #include <functional> #include <string> #include <string_view> #include <vector> -namespace o2 -{ -namespace framework +namespace o2::framework { enum class MetricType { @@ -34,10 +34,10 @@ enum class MetricType { std::ostream& operator<<(std::ostream& oss, MetricType const& val); struct MetricInfo { - enum MetricType type; - size_t storeIdx; // Index in the actual store - size_t pos; // Last position in the circular buffer - size_t filledMetrics; + enum MetricType type = MetricType::Unknown; + size_t storeIdx = -1; // Index in the actual store + size_t pos = 0; // Last position in the circular buffer + size_t filledMetrics = 0; // How many metrics were filled }; // We keep only fixed lenght strings for metrics, as in the end this is not @@ -84,6 +84,7 @@ struct DeviceMetricsInfo { std::vector<size_t> maxDomain; std::vector<MetricLabelIndex> metricLabelsIdx; std::vector<MetricInfo> metrics; + std::vector<bool> changed; }; struct DeviceMetricsHelper { @@ -104,9 +105,94 @@ struct DeviceMetricsHelper { NewMetricCallback newMetricCallback = nullptr); static size_t metricIdxByName(const std::string& name, const DeviceMetricsInfo& info); + + /// Typesafe way to get the actual store + template <typename T> + static auto& getMetricsStore(DeviceMetricsInfo& metrics) + { + if constexpr (std::is_same_v<T, int>) { + return metrics.intMetrics; + } else if constexpr (std::is_same_v<T, float>) { + return metrics.floatMetrics; + } else if constexpr (std::is_same_v<T, uint64_t>) { + return metrics.uint64Metrics; + } else { + throw runtime_error("Unhandled metric type"); + }; + } + + template <typename T> + static auto getMetricType() + { + if constexpr (std::is_same_v<T, int>) { + return MetricType::Int; + } else if constexpr (std::is_same_v<T, float>) { + return MetricType::Float; + } else if constexpr (std::is_same_v<T, uint64_t>) { + return MetricType::Uint64; + } else { + throw runtime_error("Unhandled metric type"); + }; + } + + /// @return helper to insert a given value in the metrics + template <typename T> + static std::function<void(DeviceMetricsInfo&, T value, size_t timestamp)> + createNumericMetric(DeviceMetricsInfo& metrics, + char const* name, + NewMetricCallback newMetricsCallback = nullptr) + { + static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint64_t> || std::is_same_v<T, float>, "Unsupported metric type"); + // Create a new metric + MetricInfo metricInfo; + metricInfo.pos = 0; + metricInfo.type = getMetricType<T>(); + metricInfo.filledMetrics = 0; + metricInfo.storeIdx = getMetricsStore<T>(metrics).size(); + getMetricsStore<T>(metrics).emplace_back(std::array<T, 1024>{}); + + // Add the timestamp buffer for it + metrics.timestamps.emplace_back(std::array<size_t, 1024>{}); + metrics.max.push_back(std::numeric_limits<float>::lowest()); + metrics.min.push_back(std::numeric_limits<float>::max()); + metrics.maxDomain.push_back(std::numeric_limits<size_t>::lowest()); + metrics.minDomain.push_back(std::numeric_limits<size_t>::max()); + metrics.changed.push_back(true); + + // Add the index by name in the correct position + // this will require moving the tail of the index, + // but inserting should happen only once for each metric, + // so who cares. + // Add the the actual Metric info to the store + MetricLabelIndex metricLabelIdx; + strncpy(metricLabelIdx.label, name, MetricLabelIndex::MAX_METRIC_LABEL_SIZE - 1); + metricLabelIdx.label[MetricLabelIndex::MAX_METRIC_LABEL_SIZE - 1] = '\0'; + metricLabelIdx.index = metrics.metrics.size(); + metrics.metricLabelsIdx.push_back(metricLabelIdx); + + // Add the the actual Metric info to the store + auto metricIndex = metrics.metrics.size(); + metrics.metrics.push_back(metricInfo); + + if (newMetricsCallback != nullptr) { + newMetricsCallback(metricLabelIdx.label, metricInfo, 0, metricIndex); + } + return [metricIndex](DeviceMetricsInfo& metrics, T value, size_t timestamp) { + MetricInfo& metric = metrics.metrics[metricIndex]; + + metrics.minDomain[metricIndex] = std::min(metrics.minDomain[metricIndex], timestamp); + metrics.maxDomain[metricIndex] = std::max(metrics.maxDomain[metricIndex], timestamp); + metrics.max[metricIndex] = std::max(metrics.max[metricIndex], (float)value); + metrics.min[metricIndex] = std::min(metrics.min[metricIndex], (float)value); + metrics.changed.at(metricIndex) = true; + auto& store = getMetricsStore<T>(metrics); + size_t pos = metric.pos++ % store[metric.storeIdx].size(); + metrics.timestamps[metricIndex][pos] = timestamp; + store[metric.storeIdx][pos] = value; + }; + } }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif // FRAMEWORK_DEVICEMETRICSINFO_H +#endif // O2_FRAMEWORK_DEVICEMETRICSINFO_H_ diff --git a/Framework/Core/src/DeviceMetricsInfo.cxx b/Framework/Core/src/DeviceMetricsInfo.cxx index 32d8bf6ff5184..25fc36e0602ef 100644 --- a/Framework/Core/src/DeviceMetricsInfo.cxx +++ b/Framework/Core/src/DeviceMetricsInfo.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "Framework/DeviceMetricsInfo.h" +#include "Framework/RuntimeError.h" #include <cassert> #include <cinttypes> #include <cstdlib> @@ -19,9 +20,7 @@ #include <tuple> #include <iostream> -namespace o2 -{ -namespace framework +namespace o2::framework { // Parses a metric in the form @@ -180,6 +179,7 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, info.min.push_back(std::numeric_limits<float>::max()); info.maxDomain.push_back(std::numeric_limits<size_t>::lowest()); info.minDomain.push_back(std::numeric_limits<size_t>::max()); + info.changed.push_back(false); // Add the index by name in the correct position // this will require moving the tail of the index, @@ -256,7 +256,8 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, return false; break; }; - + // Note that we updated a given metric. + info.changed[metricIndex] = true; return true; } @@ -296,5 +297,4 @@ std::ostream& operator<<(std::ostream& oss, MetricType const& val) return oss; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/test/test_DeviceMetricsInfo.cxx b/Framework/Core/test/test_DeviceMetricsInfo.cxx index de32a3cc62c8a..9b056b315549d 100644 --- a/Framework/Core/test/test_DeviceMetricsInfo.cxx +++ b/Framework/Core/test/test_DeviceMetricsInfo.cxx @@ -129,3 +129,59 @@ BOOST_AUTO_TEST_CASE(TestDeviceMetricsInfo) result = DeviceMetricsHelper::processMetric(match, info); BOOST_CHECK_EQUAL(result, true); } + +BOOST_AUTO_TEST_CASE(TestDeviceMetricsInfo2) +{ + using namespace o2::framework; + DeviceMetricsInfo info; + auto bkey = DeviceMetricsHelper::createNumericMetric<int>(info, "bkey"); + auto akey = DeviceMetricsHelper::createNumericMetric<float>(info, "akey"); + auto ckey = DeviceMetricsHelper::createNumericMetric<uint64_t>(info, "ckey"); + BOOST_CHECK_EQUAL(DeviceMetricsHelper::metricIdxByName("akey", info), 1); + BOOST_CHECK_EQUAL(DeviceMetricsHelper::metricIdxByName("bkey", info), 0); + BOOST_CHECK_EQUAL(DeviceMetricsHelper::metricIdxByName("ckey", info), 2); + BOOST_CHECK_EQUAL(info.changed.at(0), true); + size_t t = 1000; + bkey(info, 0, t++); + bkey(info, 1, t++); + bkey(info, 2, t++); + bkey(info, 3, t++); + bkey(info, 4, t++); + bkey(info, 5, t++); + BOOST_CHECK_EQUAL(info.changed[0], true); + BOOST_CHECK_EQUAL(info.intMetrics[0][0], 0); + BOOST_CHECK_EQUAL(info.intMetrics[0][1], 1); + BOOST_CHECK_EQUAL(info.intMetrics[0][2], 2); + BOOST_CHECK_EQUAL(info.intMetrics[0][3], 3); + BOOST_CHECK_EQUAL(info.intMetrics[0][4], 4); + BOOST_CHECK_EQUAL(info.intMetrics[0][5], 5); + BOOST_CHECK_EQUAL(info.changed[1], true); + bkey(info, 5., t++); + akey(info, 1., t++); + akey(info, 2., t++); + akey(info, 3., t++); + akey(info, 4., t++); + BOOST_CHECK_EQUAL(info.intMetrics[0][6], 5); + BOOST_CHECK_EQUAL(info.floatMetrics[0][0], 1.); + BOOST_CHECK_EQUAL(info.floatMetrics[0][1], 2.); + BOOST_CHECK_EQUAL(info.floatMetrics[0][2], 3.); + BOOST_CHECK_EQUAL(info.floatMetrics[0][3], 4.); + BOOST_CHECK_EQUAL(info.timestamps.size(), 3); + BOOST_CHECK_EQUAL(info.timestamps[0][0], 1000); + BOOST_CHECK_EQUAL(info.timestamps[0][1], 1001); + BOOST_CHECK_EQUAL(info.timestamps[0][2], 1002); + BOOST_CHECK_EQUAL(info.timestamps[0][3], 1003); + BOOST_CHECK_EQUAL(info.timestamps[0][4], 1004); + BOOST_CHECK_EQUAL(info.timestamps[0][5], 1005); + BOOST_CHECK_EQUAL(info.timestamps[1][0], 1007); + BOOST_CHECK_EQUAL(info.timestamps[1][1], 1008); + BOOST_CHECK_EQUAL(info.timestamps[1][2], 1009); + BOOST_CHECK_EQUAL(info.timestamps[1][3], 1010); + BOOST_CHECK_EQUAL(info.changed.size(), 3); + for (int i = 0; i < 1026; ++i) { + ckey(info, i, t++); + } + BOOST_CHECK_EQUAL(info.uint64Metrics[0][0], 1024); + BOOST_CHECK_EQUAL(info.uint64Metrics[0][1], 1025); + BOOST_CHECK_EQUAL(info.uint64Metrics[0][2], 2); +} From 68ba7c07e85204d401ba0d6e7c224ade06cab19c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 23:19:16 +0200 Subject: [PATCH 1074/1751] Fix integer trancation of payload size to 32 bits --- Framework/Core/include/Framework/DataRefUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/DataRefUtils.h b/Framework/Core/include/Framework/DataRefUtils.h index 962f85b20faac..5640cde2d2d50 100644 --- a/Framework/Core/include/Framework/DataRefUtils.h +++ b/Framework/Core/include/Framework/DataRefUtils.h @@ -152,7 +152,7 @@ struct DataRefUtils { } } - static unsigned getPayloadSize(const DataRef& ref) + static o2::header::DataHeader::PayloadSizeType getPayloadSize(const DataRef& ref) { using DataHeader = o2::header::DataHeader; auto* header = o2::header::get<const DataHeader*>(ref.header); From faf4d9c600d84b88b280a83d843f7466d1c5c034 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 22:15:27 +0200 Subject: [PATCH 1075/1751] GPU: Do not disable memory reuse if we use OpenMP with ompKernels --- GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx index 87de160778a69..af45c60ee9bdf 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx @@ -106,7 +106,7 @@ void* GPUTPCTracker::SetPointersCommon(void* mem) void GPUTPCTracker::RegisterMemoryAllocation() { AllocateAndInitializeLate(); - bool reuseCondition = !mRec->GetProcessingSettings().keepDisplayMemory && mRec->GetProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetProcessingSettings().ompThreads == 1); + bool reuseCondition = !mRec->GetProcessingSettings().keepDisplayMemory && mRec->GetProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetProcessingSettings().ompKernels || mRec->GetProcessingSettings().ompThreads == 1); GPUMemoryReuse reLinks{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerDataLinks, (unsigned short)(mISlice % mRec->GetProcessingSettings().nStreams)}; mMemoryResLinks = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataLinks, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCSliceLinks", reLinks); mMemoryResSliceScratch = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK | GPUMemoryResource::MEMORY_CUSTOM, "TPCSliceScratch"); From e4c882f7dead6c718f078148cf55662e3faeb102 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 23 Oct 2020 22:27:05 +0200 Subject: [PATCH 1076/1751] Improve memory usage debug output --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 96421d0047de1..95a5709959227 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -676,8 +676,11 @@ void GPUReconstruction::PushNonPersistentMemory() void GPUReconstruction::PopNonPersistentMemory(RecoStep step) { - if (mProcessingSettings.debugLevel >= 3 || mProcessingSettings.allocDebugLevel) { - printf("Allocated memory after %30s: %'13lld (non temporary %'13lld, blocked %'13lld)\n", GPUDataTypes::RECO_STEP_NAMES[getRecoStepNum(step, true)], ptrDiff(mDeviceMemoryPool, mDeviceMemoryBase) + ptrDiff((char*)mDeviceMemoryBase + mDeviceMemorySize, mDeviceMemoryPoolEnd), ptrDiff(mDeviceMemoryPool, mDeviceMemoryBase), mDeviceMemoryPoolBlocked == nullptr ? 0ll : ptrDiff((char*)mDeviceMemoryBase + mDeviceMemorySize, mDeviceMemoryPoolBlocked)); + if ((mProcessingSettings.debugLevel >= 3 || mProcessingSettings.allocDebugLevel) && (IsGPU() || mProcessingSettings.forceHostMemoryPoolSize)) { + if (IsGPU()) { + printf("Allocated Device memory after %30s: %'13lld (non temporary %'13lld, blocked %'13lld)\n", GPUDataTypes::RECO_STEP_NAMES[getRecoStepNum(step, true)], ptrDiff(mDeviceMemoryPool, mDeviceMemoryBase) + ptrDiff((char*)mDeviceMemoryBase + mDeviceMemorySize, mDeviceMemoryPoolEnd), ptrDiff(mDeviceMemoryPool, mDeviceMemoryBase), mDeviceMemoryPoolBlocked == nullptr ? 0ll : ptrDiff((char*)mDeviceMemoryBase + mDeviceMemorySize, mDeviceMemoryPoolBlocked)); + } + printf("Allocated Host memory after %30s: %'13lld (non temporary %'13lld, blocked %'13lld)\n", GPUDataTypes::RECO_STEP_NAMES[getRecoStepNum(step, true)], ptrDiff(mHostMemoryPool, mHostMemoryBase) + ptrDiff((char*)mHostMemoryBase + mHostMemorySize, mHostMemoryPoolEnd), ptrDiff(mHostMemoryPool, mHostMemoryBase), mHostMemoryPoolBlocked == nullptr ? 0ll : ptrDiff((char*)mHostMemoryBase + mHostMemorySize, mHostMemoryPoolBlocked)); } if (mProcessingSettings.keepDisplayMemory || mProcessingSettings.disableMemoryReuse) { return; From 590988ab704e0e75eeff66767d3a6902a3d70c7f Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Sat, 24 Oct 2020 12:31:42 +0200 Subject: [PATCH 1077/1751] taskwrapper: simple mechanism to allow task skipping --- Utilities/Tools/jobutils.sh | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index 136c2cbe74f69..014f753547c16 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -43,6 +43,7 @@ childprocs() { # conditions early and prevent longtime hanging executables # (until DPL offers signal handling and automatic shutdown) # - possibility to provide user hooks for "start" and "failure" +# - possibility to skip (jump over) job alltogether taskwrapper() { local logfile=$1 shift 1 @@ -59,6 +60,18 @@ taskwrapper() { eval "${hook}" fi + # We offer the possibility to jump this stage/task when a "done" file is present. + # (this is mainly interesting for debugging in order to avoid going through all pipeline stages again) + # The feature should be used with care! To make this nice, a proper dependency chain and a checksum mechanism + # needs to be put into place. + if [ "${JOBUTILS_SKIPDONE}" ]; then + if [ -f "${logfile}_done" ]; then + echo "Skipping task since file ${logfile}_done found"; + return 0 + fi + fi + [ -f "${logfile}_done" ] && rm "${logfile}"_done + # the time command is non-standard on MacOS if [ "$(uname)" == "Darwin" ]; then GTIME=$(which gtime) @@ -156,7 +169,13 @@ taskwrapper() { # return code RC=$? RC_ACUM=$((RC_ACUM+RC)) - [ ! "${RC} -eq 0" ] && echo "command ${command} had nonzero exit code ${RC}" - + if [ "${RC}" -eq "0" ]; then + # if return code 0 we mark this task as done + echo "Command \"${command}\" successfully finished." > "${logfile}"_done + echo "The presence of this file can be used to skip this command in future runs" >> "${logfile}"_done + echo "of the pipeline by setting the JOBUTILS_SKIPDONE environment variable." >> "${logfile}"_done + else + echo "command ${command} had nonzero exit code ${RC}" + fi return ${RC} } From 3c7bb1a98b78d5fc34a01ef426c4ce26fcf5a819 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 8 Oct 2020 16:34:08 +0200 Subject: [PATCH 1078/1751] add conet mode for raw decoding to digits add on-the-fly noise filter in TOF decoding for cosmic runs allowing filtering emtpy row in TOF digits add diagnostic and error in TOF decoding fix in TOF encoding (word counter) --- .../TOF/include/DataFormatsTOF/Cluster.h | 2 +- .../tofworkflow/src/tof-reco-workflow.cxx | 34 ++-- .../TOF/base/include/TOFBase/WindowFiller.h | 20 +++ Detectors/TOF/base/src/WindowFiller.cxx | 17 +- Detectors/TOF/compression/src/Compressor.cxx | 2 +- .../include/TOFReconstruction/Decoder.h | 3 + .../TOF/reconstruction/src/Clusterer.cxx | 2 + Detectors/TOF/reconstruction/src/Decoder.cxx | 12 +- Detectors/TOF/reconstruction/src/Encoder.cxx | 10 +- .../TOFWorkflowUtils/CompressedDecodingTask.h | 17 +- .../TOFWorkflowUtils/TOFDigitWriterSpec.h | 2 +- .../workflow/src/CompressedDecodingTask.cxx | 152 ++++++++++++++++-- .../TOF/workflow/src/TOFDigitWriterSpec.cxx | 18 ++- 13 files changed, 253 insertions(+), 38 deletions(-) diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h index d966dfee52903..35126f49cb32f 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h @@ -63,7 +63,7 @@ class Cluster : public o2::BaseCluster<float> double getTime() const { return mTime; } // Cluster ToF getter void setTime(double time) { mTime = time; } // Cluster ToF setter float getTot() const { return mTot; } // Cluster Charge getter - void setTot(int tot) { mTot = tot; } // Cluster ToT setter + void setTot(float tot) { mTot = tot; } // Cluster ToT setter int getL0L1Latency() const { return mL0L1Latency; }; // L0L1 latency void setL0L1Latency(int value) { mL0L1Latency = value; }; // L0-L1 latency int getDeltaBC() const { return mDeltaBC; }; // deltaBC diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 51dcba8bb5fed..feb89cfc11d88 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -58,7 +58,10 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) workflowOptions.push_back(ConfigParamSpec{"input-desc", o2::framework::VariantType::String, "CRAWDATA", {"Input specs description string"}}); workflowOptions.push_back(ConfigParamSpec{"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input readers"}}); workflowOptions.push_back(ConfigParamSpec{"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writers"}}); + workflowOptions.push_back(ConfigParamSpec{"conet-mode", o2::framework::VariantType::Bool, false, {"enable conet mode"}}); workflowOptions.push_back(ConfigParamSpec{"configKeyValues", o2::framework::VariantType::String, "", {"Semicolon separated key=value strings ..."}}); + workflowOptions.push_back(ConfigParamSpec{"disable-row-writing", o2::framework::VariantType::Bool, false, {"disable ROW in Digit writing"}}); + workflowOptions.push_back(ConfigParamSpec{"write-decoding-errors", o2::framework::VariantType::Bool, false, {"trace errors in digits output when decoding"}}); } #include "Framework/runDataProcessing.h" // the main driver @@ -84,13 +87,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) WorkflowSpec specs; if (!cfgc.helpOnCommandLine()) { - std::string inputGRP = o2::base::NameConf::getGRPFileName(); - o2::base::Propagator::initFieldFromGRP(inputGRP); - const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP); - if (!grp) { - LOG(ERROR) << "This workflow needs a valid GRP file to start"; - return specs; - } o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); // o2::conf::ConfigurableParam::writeINI("o2tofrecoflow_configuration.ini"); } @@ -107,6 +103,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) bool writedigit = 0; bool writeraw = 0; bool writectf = 0; + bool writeerr = 0; if (outputType.rfind("clusters") < outputType.size()) writecluster = 1; @@ -131,15 +128,31 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) clusterinput = 1; } else if (inputType == "raw") { rawinput = 1; + writeerr = cfgc.options().get<bool>("write-decoding-errors"); } else if (inputType == "ctf") { ctfinput = 1; } + if (ctfinput || rawinput) { + } else { + if (!cfgc.helpOnCommandLine()) { + std::string inputGRP = o2::base::NameConf::getGRPFileName(); + o2::base::Propagator::initFieldFromGRP(inputGRP); + const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP); + if (!grp) { + LOG(ERROR) << "This workflow needs a valid GRP file to start"; + return specs; + } + } + } + auto useMC = !cfgc.options().get<bool>("disable-mc"); auto useCCDB = cfgc.options().get<bool>("use-ccdb"); auto useFIT = cfgc.options().get<bool>("use-fit"); bool disableRootInput = cfgc.options().get<bool>("disable-root-input") || rawinput; bool disableRootOutput = cfgc.options().get<bool>("disable-root-output"); + bool conetmode = cfgc.options().get<bool>("conet-mode"); + bool disableROWwriting = cfgc.options().get<bool>("disable-row-writing"); LOG(INFO) << "TOF RECO WORKFLOW configuration"; LOG(INFO) << "TOF input = " << cfgc.options().get<std::string>("input-type"); @@ -151,6 +164,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) LOG(INFO) << "TOF use-fit = " << cfgc.options().get<std::string>("use-fit"); LOG(INFO) << "TOF disable-root-input = " << disableRootInput; LOG(INFO) << "TOF disable-root-output = " << disableRootOutput; + LOG(INFO) << "TOF conet-mode = " << conetmode; + LOG(INFO) << "TOF disable-row-writing = " << disableROWwriting; + LOG(INFO) << "TOF write-decoding-errors = " << writeerr; if (clusterinput) { LOG(INFO) << "Insert TOF Cluster Reader"; @@ -167,13 +183,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } else if (rawinput) { LOG(INFO) << "Insert TOF Compressed Raw Decoder"; auto inputDesc = cfgc.options().get<std::string>("input-desc"); - specs.emplace_back(o2::tof::getCompressedDecodingSpec(inputDesc)); + specs.emplace_back(o2::tof::getCompressedDecodingSpec(inputDesc, conetmode)); useMC = 0; if (writedigit && !disableRootOutput) { // add TOF digit writer without mc labels LOG(INFO) << "Insert TOF Digit Writer"; - specs.emplace_back(o2::tof::getTOFDigitWriterSpec(0)); + specs.emplace_back(o2::tof::getTOFDigitWriterSpec(0, writeerr)); } } else if (ctfinput) { LOG(INFO) << "Insert TOF CTF decoder"; diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index 2b049ae5c90b7..65aa28e74b922 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -42,6 +42,7 @@ class WindowFiller std::vector<Digit>* getDigitPerTimeFrame() { return &mDigitsPerTimeFrame; } std::vector<ReadoutWindowData>* getReadoutWindowData() { return &mReadoutWindowData; } + std::vector<ReadoutWindowData>* getReadoutWindowDataFiltered() { return &mReadoutWindowDataFiltered; } void fillOutputContainer(std::vector<Digit>& digits); void flushOutputContainer(std::vector<Digit>& digits); // flush all residual buffered data @@ -52,6 +53,17 @@ class WindowFiller void setFirstIR(const o2::InteractionRecord& ir) { mFirstIR = ir; } + void maskNoiseRate(int val) { mMaskNoiseRate = val; } + + void clearCounts() + { + for (int i = 0; i < o2::tof::Geo::NCHANNELS; i++) + mChannelCounts[i] = 0; + } + + std::vector<uint32_t>& getPatterns() { return mPatterns; } + void addPattern(const uint32_t val, int icrate) { mPatterns.push_back(val); } + protected: // info TOF timewindow uint64_t mReadoutWindowCurrent = 0; @@ -61,6 +73,10 @@ class WindowFiller bool mContinuous = true; bool mFutureToBeSorted = false; + // only needed from Decoder + int mMaskNoiseRate = -1; + int mChannelCounts[o2::tof::Geo::NCHANNELS]; // count of channel hits in the current TF (if MaskNoiseRate enabled) + // digit info //std::vector<Digit>* mDigits; @@ -68,6 +84,7 @@ class WindowFiller std::vector<Digit> mDigitsPerTimeFrame; std::vector<ReadoutWindowData> mReadoutWindowData; + std::vector<ReadoutWindowData> mReadoutWindowDataFiltered; int mIcurrentReadoutWindow = 0; @@ -79,6 +96,9 @@ class WindowFiller // arrays with digit and MCLabels out of the current readout windows (stored to fill future readout window) std::vector<Digit> mFutureDigits; + std::vector<uint32_t> mPatterns; + std::vector<uint32_t> mErrors; + void fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); // void fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID); diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index 12d633295015f..a1484a673ac1d 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -95,6 +95,7 @@ void WindowFiller::reset() mDigitsPerTimeFrame.clear(); mReadoutWindowData.clear(); + mReadoutWindowDataFiltered.clear(); mFirstIR.bc = 0; mFirstIR.orbit = 0; @@ -124,8 +125,19 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) int orbit_shift = mReadoutWindowData.size() / 3; int bc_shift = (mReadoutWindowData.size() % 3) * Geo::BC_IN_WINDOW; info.setBCData(mFirstIR.orbit + orbit_shift, mFirstIR.bc + bc_shift); - if (digits.size()) + int firstPattern = 0; + int npatterns = mPatterns.size(); + if (mReadoutWindowData.size()) { + auto prevROW = mReadoutWindowData[mReadoutWindowData.size() - 1]; + firstPattern = prevROW.firstDia() + prevROW.sizeDia(); + npatterns -= firstPattern; + } + info.setFirstEntryDia(firstPattern); + info.setNEntriesDia(npatterns); + if (digits.size()) { mDigitsPerTimeFrame.insert(mDigitsPerTimeFrame.end(), digits.begin(), digits.end()); + mReadoutWindowDataFiltered.push_back(info); + } mReadoutWindowData.push_back(info); } @@ -294,7 +306,8 @@ void WindowFiller::checkIfReuseFutureDigitsRO() // the same but using readout in strips = mStripsNext[isnext - 1]; } - fillDigitsInStrip(strips, digit->getChannel(), digit->getTDC(), digit->getTOT(), digit->getBC(), digit->getChannel() / Geo::NPADS); + if (mMaskNoiseRate < 0 || mChannelCounts[digit->getChannel()] < mMaskNoiseRate) + fillDigitsInStrip(strips, digit->getChannel(), digit->getTDC(), digit->getTOT(), digit->getBC(), digit->getChannel() / Geo::NPADS); // int labelremoved = digit->getLabel(); mFutureDigits.erase(mFutureDigits.begin() + idigit); diff --git a/Detectors/TOF/compression/src/Compressor.cxx b/Detectors/TOF/compression/src/Compressor.cxx index 318aa7867bd78..a2fc2506cee45 100644 --- a/Detectors/TOF/compression/src/Compressor.cxx +++ b/Detectors/TOF/compression/src/Compressor.cxx @@ -889,7 +889,7 @@ bool Compressor<RDH, verbose>::checkerCheck() for (int itrm = 0; itrm < 10; ++itrm) { mDecoderSummary.trmDataHeader[itrm] = nullptr; mDecoderSummary.trmDataTrailer[itrm] = nullptr; - for (int ichain = 0; ichain < 2; ++ichain) { + for (int ichain = 0; ichain < 10; ++ichain) { mDecoderSummary.trmChainHeader[itrm][ichain] = nullptr; mDecoderSummary.trmChainTrailer[itrm][ichain] = nullptr; mDecoderSummary.trmErrors[itrm][ichain] = 0; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h index 8c2738d07d328..16b0a6946d6ad 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h @@ -71,6 +71,9 @@ class Decoder : public WindowFiller char* nextPage(void* current, int shift = 8192); + std::vector<uint32_t>& getErrors() { return mErrors; } + void addError(const uint32_t val, int icrate) { mErrors.push_back(val); } + protected: static const int NCRU = 4; diff --git a/Detectors/TOF/reconstruction/src/Clusterer.cxx b/Detectors/TOF/reconstruction/src/Clusterer.cxx index 7601a9fcb4291..5cc612a247518 100644 --- a/Detectors/TOF/reconstruction/src/Clusterer.cxx +++ b/Detectors/TOF/reconstruction/src/Clusterer.cxx @@ -169,6 +169,8 @@ void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth) c.setTime(mContributingDigit[0]->getCalibratedTime()); // time in ps (for now we assume it calibrated) c.setTimeRaw(mContributingDigit[0]->getTDC() * Geo::TDCBIN + mContributingDigit[0]->getBC() * o2::constants::lhc::LHCBunchSpacingNS * 1E3); // time in ps (for now we assume it calibrated) + //printf("timeraw= %lf - time real = %lf (%d, %lu) \n",c.getTimeRaw(),mContributingDigit[0]->getTDC() * Geo::TDCBIN + mContributingDigit[0]->getBC() * o2::constants::lhc::LHCBunchSpacingNS * 1E3,mContributingDigit[0]->getTDC(),mContributingDigit[0]->getBC()); + c.setTot(mContributingDigit[0]->getTOT() * Geo::TOTBIN_NS); // TOT in ns (for now we assume it calibrated) //setL0L1Latency(); // to be filled (maybe) //setDeltaBC(); // to be filled (maybe) diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index 11fed56cee81b..df239a31c2904 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -34,6 +34,7 @@ Decoder::Decoder() mBuffer[i] = nullptr; mCruIn[i] = false; } + clearCounts(); } bool Decoder::open(const std::string name) @@ -110,6 +111,11 @@ bool Decoder::close() void Decoder::clear() { reset(); + if (mMaskNoiseRate > 0) + clearCounts(); + + mPatterns.clear(); + mErrors.clear(); } void Decoder::InsertDigit(int icrate, int itrm, int itdc, int ichain, int channel, uint32_t orbit, uint16_t bunchid, int time_ext, int tdc, int tot) @@ -117,6 +123,8 @@ void Decoder::InsertDigit(int icrate, int itrm, int itdc, int ichain, int channe DigitInfo digitInfo; fromRawHit2Digit(icrate, itrm, itdc, ichain, channel, orbit, bunchid, time_ext + tdc, tot, digitInfo); + if (mMaskNoiseRate > 0) + mChannelCounts[digitInfo.channel]++; mHitDecoded++; @@ -162,6 +170,8 @@ void Decoder::readTRM(int icru, int icrate, uint32_t orbit, uint16_t bunchid) for (int i = 0; i < nhits; i++) { fromRawHit2Digit(icrate, itrm, mUnion[icru]->packedHit.tdcID, mUnion[icru]->packedHit.chain, mUnion[icru]->packedHit.channel, orbit, bunchid, time_ext + mUnion[icru]->packedHit.time, mUnion[icru]->packedHit.tot, digitInfo); + if (mMaskNoiseRate > 0) + mChannelCounts[digitInfo.channel]++; mHitDecoded++; @@ -261,7 +271,7 @@ bool Decoder::decode() // return a vector of digits in a TOF readout window //read Orbit int orbit = mUnion[icru]->crateOrbit.orbitID; if (mVerbose) - printf("orbit ID = %d\n", orbit); + printf("%d) orbit ID = %d -- bunch ID = %d\n", icrate, orbit, bunchid); mUnion[icru]++; mIntegratedBytes[icru] += 4; diff --git a/Detectors/TOF/reconstruction/src/Encoder.cxx b/Detectors/TOF/reconstruction/src/Encoder.cxx index 483f0a0ff24f8..3f976faacda3b 100644 --- a/Detectors/TOF/reconstruction/src/Encoder.cxx +++ b/Detectors/TOF/reconstruction/src/Encoder.cxx @@ -147,6 +147,7 @@ void Encoder::encodeTRM(const std::vector<Digit>& summary, Int_t icrate, Int_t i printf("Crate %d: encode TRM %d \n", icrate, itrm); // TRM HEADER + Union_t* trmheader = mUnion[icrate]; mUnion[icrate]->trmDataHeader.slotId = itrm; mUnion[icrate]->trmDataHeader.eventWords = 0; // to be filled at the end mUnion[icrate]->trmDataHeader.eventCnt = mEventCounter; @@ -206,6 +207,11 @@ void Encoder::encodeTRM(const std::vector<Digit>& summary, Int_t icrate, Int_t i nextWord(icrate); } + // set TRM data size + int neventwords = getSize(trmheader, mUnion[icrate]) / 4 + 1; + neventwords -= neventwords / 4 * 2; + trmheader->trmDataHeader.eventWords = neventwords; + // TRM TRAILER mUnion[icrate]->trmDataTrailer.trailerMark = 3; mUnion[icrate]->trmDataTrailer.eventCRC = 0; // to be implemented @@ -330,12 +336,14 @@ bool Encoder::encode(std::vector<std::vector<o2::tof::Digit>> digitWindow, int t mUnion[i]->drmDataTrailer.locEvCnt = mEventCounter; mUnion[i]->drmDataTrailer.mbz = 0; mUnion[i]->drmDataTrailer.dataId = 5; + int neventwords = getSize(mDRMDataHeader[i], mUnion[i]) / 4 + 1; + neventwords -= neventwords / 4 * 2 + 6; + mDRMDataHeader[i]->eventWords = neventwords; nextWord(i); mUnion[i]->data = 0x70000000; nextWord(i); mTOFDataHeader[i]->bytePayload = getSize(mTOFDataHeader[i], mUnion[i]); - mDRMDataHeader[i]->eventWords = mTOFDataHeader[i]->bytePayload / 4; } // check that all digits were used diff --git a/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedDecodingTask.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedDecodingTask.h index 1913eec763909..35b67d5224b78 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedDecodingTask.h +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/CompressedDecodingTask.h @@ -36,7 +36,12 @@ using namespace compressed; class CompressedDecodingTask : public DecoderBase, public Task { public: - CompressedDecodingTask() = default; + CompressedDecodingTask(bool conet = false) + { + mConetMode = conet; + setDecoderCONET(conet); + } + ~CompressedDecodingTask() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -46,12 +51,12 @@ class CompressedDecodingTask : public DecoderBase, public Task private: /** decoding handlers **/ void rdhHandler(const o2::header::RAWDataHeader* rdh) override; - void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) override{}; + void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) override; void frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, const FrameHeader_t* frameHeader, const PackedHit_t* packedHits) override; void trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics, - const Error_t* errors) override{}; + const Error_t* errors) override; o2::tof::compressed::Decoder mDecoder; std::vector<std::vector<o2::tof::Digit>> mDigits; @@ -59,11 +64,15 @@ class CompressedDecodingTask : public DecoderBase, public Task int mNCrateOpenTF = 0; int mNCrateCloseTF = 0; bool mHasToBePosted = false; + bool mConetMode = false; uint32_t mInitOrbit = 0; + bool mRowFilter = false; + bool mMaskNoise = false; + int mNoiseRate = 1000; TStopwatch mTimer; }; -framework::DataProcessorSpec getCompressedDecodingSpec(const std::string& inputDesc); +framework::DataProcessorSpec getCompressedDecodingSpec(const std::string& inputDesc, bool conet = false); } // namespace tof } // namespace o2 diff --git a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSpec.h index b62ae8272d642..d45d2e4c95509 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSpec.h +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSpec.h @@ -18,7 +18,7 @@ namespace o2 namespace tof { -o2::framework::DataProcessorSpec getTOFDigitWriterSpec(bool useMC = 1); +o2::framework::DataProcessorSpec getTOFDigitWriterSpec(bool useMC = 1, bool writeErr = 0); } // end namespace tof } // end namespace o2 diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 03ecd071c1a33..65717746e82e4 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -39,6 +39,13 @@ void CompressedDecodingTask::init(InitContext& ic) { LOG(INFO) << "CompressedDecoding init"; + mMaskNoise = ic.options().get<bool>("mask-noise"); + mNoiseRate = ic.options().get<int>("noise-counts"); + mRowFilter = ic.options().get<bool>("row-filter"); + + if (mMaskNoise) + mDecoder.maskNoiseRate(mNoiseRate); + auto finishFunction = [this]() { LOG(INFO) << "CompressedDecoding finish"; }; @@ -55,6 +62,8 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) // send output message std::vector<o2::tof::Digit>* alldigits = mDecoder.getDigitPerTimeFrame(); std::vector<o2::tof::ReadoutWindowData>* row = mDecoder.getReadoutWindowData(); + if (mRowFilter) + row = mDecoder.getReadoutWindowDataFiltered(); ReadoutWindowData* last = nullptr; o2::InteractionRecord lastIR; @@ -82,16 +91,18 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) int n_orbits = n_tof_window / 3; int digit_size = alldigits->size(); - LOG(INFO) << "TOF: N tof window decoded = " << n_tof_window << "(orbits = " << n_orbits << ") with " << digit_size << " digits"; + // LOG(INFO) << "TOF: N tof window decoded = " << n_tof_window << "(orbits = " << n_orbits << ") with " << digit_size << " digits"; // add digits in the output snapshot pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, *alldigits); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, *row); - // RS FIXME: At the moment dummy output to comply with CTF encoded inputs - std::vector<uint32_t> patterns; + std::vector<uint32_t> patterns = mDecoder.getPatterns(); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, patterns); + std::vector<uint32_t> errors = mDecoder.getErrors(); + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ERRORS", 0, Lifetime::Timeframe}, errors); + // RS this is a hack to be removed once we have correct propagation of the firstTForbit by the framework auto setFirstTFOrbit = [&](const Output& spec, uint32_t orb) { auto* hd = pc.outputs().findMessageHeader(spec); @@ -106,8 +117,6 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) mDecoder.clear(); - LOG(INFO) << "TOF: TF = " << mNTF << " - Crate in " << mNCrateOpenTF; - mNTF++; mNCrateOpenTF = 0; mNCrateCloseTF = 0; @@ -115,10 +124,9 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) void CompressedDecodingTask::run(ProcessingContext& pc) { - LOG(INFO) << "CompressedDecoding run"; mTimer.Start(false); - if (pc.inputs().getNofParts(0)) { + if (pc.inputs().getNofParts(0) && !mConetMode) { //RS set the 1st orbit of the TF from the O2 header, relying on rdhHandler is not good (in fact, the RDH might be eliminated in the derived data) const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().getByPos(0).header); mInitOrbit = dh->firstTForbit; @@ -133,7 +141,6 @@ void CompressedDecodingTask::run(ProcessingContext& pc) /** loop over input parts **/ for (auto const& ref : iit) { - const auto* headerIn = DataRefUtils::getHeader<o2::header::DataHeader*>(ref); auto payloadIn = ref.payload; auto payloadInSize = headerIn->payloadSize; @@ -144,7 +151,7 @@ void CompressedDecodingTask::run(ProcessingContext& pc) } } - if (mNCrateOpenTF == 72 && mNCrateOpenTF == mNCrateCloseTF) + if ((mNCrateOpenTF == 72 || mConetMode) && mNCrateOpenTF == mNCrateCloseTF) mHasToBePosted = true; if (mHasToBePosted) { @@ -159,6 +166,121 @@ void CompressedDecodingTask::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } +void CompressedDecodingTask::headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) +{ + if (mConetMode) { + LOG(DEBUG) << "Crate found" << crateHeader->drmID; + + mInitOrbit = crateOrbit->orbitID; + + mNCrateOpenTF++; + } +} +void CompressedDecodingTask::trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics, + const Error_t* errors) +{ + if (mConetMode) { + LOG(DEBUG) << "Crate closed" << crateHeader->drmID; + mNCrateCloseTF++; + } + + // Diagnostics used to fill digit patterns + auto numberOfDiagnostics = crateTrailer->numberOfDiagnostics; + auto numberOfErrors = crateTrailer->numberOfErrors; + for (int i = 0; i < numberOfDiagnostics; i++) { + const uint32_t* val = reinterpret_cast<const uint32_t*>(&(diagnostics[i])); + mDecoder.addPattern(*val, crateHeader->drmID); + + int islot = (*val & 15); + printf("DRM = %d (orbit = %d) slot = %d: \n", crateHeader->drmID, crateOrbit->orbitID, islot); + if (islot == 1) { + if (o2::tof::diagnostic::DRM_HEADER_MISSING & *val) + printf("DRM_HEADER_MISSING\n"); + if (o2::tof::diagnostic::DRM_TRAILER_MISSING & *val) + printf("DRM_TRAILER_MISSING\n"); + if (o2::tof::diagnostic::DRM_FEEID_MISMATCH & *val) + printf("DRM_FEEID_MISMATCH\n"); + if (o2::tof::diagnostic::DRM_ORBIT_MISMATCH & *val) + printf("DRM_ORBIT_MISMATCH\n"); + if (o2::tof::diagnostic::DRM_CRC_MISMATCH & *val) + printf("DRM_CRC_MISMATCH\n"); + if (o2::tof::diagnostic::DRM_ENAPARTMASK_DIFFER & *val) + printf("DRM_ENAPARTMASK_DIFFER\n"); + if (o2::tof::diagnostic::DRM_CLOCKSTATUS_WRONG & *val) + printf("DRM_CLOCKSTATUS_WRONG\n"); + if (o2::tof::diagnostic::DRM_FAULTSLOTMASK_NOTZERO & *val) + printf("DRM_FAULTSLOTMASK_NOTZERO\n"); + if (o2::tof::diagnostic::DRM_READOUTTIMEOUT_NOTZERO & *val) + printf("DRM_READOUTTIMEOUT_NOTZERO\n"); + if (o2::tof::diagnostic::DRM_EVENTWORDS_MISMATCH & *val) + printf("DRM_EVENTWORDS_MISMATCH\n"); + if (o2::tof::diagnostic::DRM_MAXDIAGNOSTIC_BIT & *val) + printf("DRM_MAXDIAGNOSTIC_BIT\n"); + } else if (islot == 2) { + if (o2::tof::diagnostic::LTM_HEADER_MISSING & *val) + printf("LTM_HEADER_MISSING\n"); + if (o2::tof::diagnostic::LTM_TRAILER_MISSING & *val) + printf("LTM_TRAILER_MISSING\n"); + if (o2::tof::diagnostic::LTM_HEADER_UNEXPECTED & *val) + printf("LTM_HEADER_UNEXPECTED\n"); + if (o2::tof::diagnostic::LTM_MAXDIAGNOSTIC_BIT & *val) + printf("LTM_MAXDIAGNOSTIC_BIT\n"); + } else if (islot < 13) { + if (o2::tof::diagnostic::TRM_HEADER_MISSING & *val) + printf("TRM_HEADER_MISSING\n"); + if (o2::tof::diagnostic::TRM_TRAILER_MISSING & *val) + printf("TRM_TRAILER_MISSING\n"); + if (o2::tof::diagnostic::TRM_CRC_MISMATCH & *val) + printf("TRM_CRC_MISMATCH\n"); + if (o2::tof::diagnostic::TRM_HEADER_UNEXPECTED & *val) + printf("TRM_HEADER_UNEXPECTED\n"); + if (o2::tof::diagnostic::TRM_EVENTCNT_MISMATCH & *val) + printf("TRM_EVENTCNT_MISMATCH\n"); + if (o2::tof::diagnostic::TRM_EMPTYBIT_NOTZERO & *val) + printf("TRM_EMPTYBIT_NOTZERO\n"); + if (o2::tof::diagnostic::TRM_LBIT_NOTZERO & *val) + printf("TRM_LBIT_NOTZERO\n"); + if (o2::tof::diagnostic::TRM_FAULTSLOTBIT_NOTZERO & *val) + printf("TRM_FAULTSLOTBIT_NOTZERO\n"); + if (o2::tof::diagnostic::TRM_EVENTWORDS_MISMATCH & *val) + printf("TRM_EVENTWORDS_MISMATCH\n"); + if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE1 & *val) + printf("TRM_DIAGNOSTIC_SPARE1\n"); + if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE2 & *val) + printf("TRM_DIAGNOSTIC_SPARE2\n"); + if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE3 & *val) + printf("TRM_DIAGNOSTIC_SPARE3\n"); + if (o2::tof::diagnostic::TRM_MAXDIAGNOSTIC_BIT & *val) + printf("TRM_MAXDIAGNOSTIC_BIT\n"); + + if (o2::tof::diagnostic::TRMCHAIN_HEADER_MISSING & *val) + printf("TRMCHAIN_HEADER_MISSING\n"); + if (o2::tof::diagnostic::TRMCHAIN_TRAILER_MISSING & *val) + printf("TRMCHAIN_TRAILER_MISSING\n"); + if (o2::tof::diagnostic::TRMCHAIN_STATUS_NOTZERO & *val) + printf("TRMCHAIN_STATUS_NOTZERO\n"); + if (o2::tof::diagnostic::TRMCHAIN_EVENTCNT_MISMATCH & *val) + printf("TRMCHAIN_EVENTCNT_MISMATCH\n"); + if (o2::tof::diagnostic::TRMCHAIN_TDCERROR_DETECTED & *val) + printf("TRMCHAIN_TDCERROR_DETECTED\n"); + if (o2::tof::diagnostic::TRMCHAIN_BUNCHCNT_MISMATCH & *val) + printf("TRMCHAIN_BUNCHCNT_MISMATCH\n"); + if (o2::tof::diagnostic::TRMCHAIN_DIAGNOSTIC_SPARE1 & *val) + printf("TRMCHAIN_DIAGNOSTIC_SPARE1\n"); + if (o2::tof::diagnostic::TRMCHAIN_DIAGNOSTIC_SPARE2 & *val) + printf("TRMCHAIN_DIAGNOSTIC_SPARE2\n"); + if (o2::tof::diagnostic::TRMCHAIN_MAXDIAGNOSTIC_BIT & *val) + printf("TRMCHAIN_MAXDIAGNOSTIC_BIT\n"); + } + printf("------\n"); + } + for (int i = 0; i < numberOfErrors; i++) { + const uint32_t* val = reinterpret_cast<const uint32_t*>(&(errors[i])); + mDecoder.addError(*val, crateHeader->drmID); + } +} + void CompressedDecodingTask::rdhHandler(const o2::header::RAWDataHeader* rdh) { @@ -187,19 +309,23 @@ void CompressedDecodingTask::frameHandler(const CrateHeader_t* crateHeader, cons } }; -DataProcessorSpec getCompressedDecodingSpec(const std::string& inputDesc) +DataProcessorSpec getCompressedDecodingSpec(const std::string& inputDesc, bool conet) { std::vector<OutputSpec> outputs; outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe); - outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); // RS FIXME: At the moment dummy output to comply with CTF encoded inputs + outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTOF, "ERRORS", 0, Lifetime::Timeframe); return DataProcessorSpec{ "tof-compressed-decoder", select(std::string("x:TOF/" + inputDesc).c_str()), outputs, - AlgorithmSpec{adaptFromTask<CompressedDecodingTask>()}, - Options{}}; + AlgorithmSpec{adaptFromTask<CompressedDecodingTask>(conet)}, + Options{ + {"row-filter", VariantType::Bool, false, {"Filter empty row"}}, + {"mask-noise", VariantType::Bool, false, {"Flag to mask noisy digits"}}, + {"noise-counts", VariantType::Int, 1000, {"Counts in a single (TF) payload"}}}}; } } // namespace tof diff --git a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx index 0667003043115..9bca21d5a2824 100644 --- a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx @@ -27,10 +27,11 @@ using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; using OutputType = std::vector<o2::tof::Digit>; using ReadoutWinType = std::vector<o2::tof::ReadoutWindowData>; using PatternType = std::vector<uint32_t>; +using ErrorType = std::vector<uint32_t>; using LabelsType = std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>; using namespace o2::header; -DataProcessorSpec getTOFDigitWriterSpec(bool useMC) +DataProcessorSpec getTOFDigitWriterSpec(bool useMC, bool writeErr) { auto nCalls = std::make_shared<int>(); *nCalls = 0; @@ -47,14 +48,16 @@ DataProcessorSpec getTOFDigitWriterSpec(bool useMC) (*nCalls)++; }; auto logger = [nCalls](OutputType const& indata) { - LOG(INFO) << "Call " << *nCalls; - LOG(INFO) << "RECEIVED DIGITS SIZE " << indata.size(); + // LOG(INFO) << "RECEIVED DIGITS SIZE " << indata.size(); }; auto loggerROW = [nCalls](ReadoutWinType const& row) { - LOG(INFO) << "RECEIVED READOUT WINDOWS " << row.size(); + // LOG(INFO) << "RECEIVED READOUT WINDOWS " << row.size(); }; auto loggerPatterns = [nCalls](PatternType const& patterns) { - LOG(INFO) << "RECEIVED PATTERNS " << patterns.size(); + // LOG(INFO) << "RECEIVED PATTERNS " << patterns.size(); + }; + auto loggerErrors = [nCalls](ErrorType const& errors) { + // LOG(INFO) << "RECEIVED PATTERNS " << patterns.size(); }; return MakeRootTreeWriterSpec("TOFDigitWriter", "tofdigits.root", @@ -77,6 +80,11 @@ DataProcessorSpec getTOFDigitWriterSpec(bool useMC) "patterns-branch-name", 1, loggerPatterns}, + BranchDefinition<ErrorType>{InputSpec{"errors", gDataOriginTOF, "ERRORS", 0}, + "TOFErrors", + "errors-branch-name", + (writeErr ? 1 : 0), // one branch if mc labels enabled + loggerErrors}, BranchDefinition<LabelsType>{InputSpec{"labels", gDataOriginTOF, "DIGITSMCTR", 0}, "TOFDigitMCTruth", (useMC ? 1 : 0), // one branch if mc labels enabled From d3dc311dd2bcd793d471b2b21fd32d14975dacd4 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Mon, 19 Oct 2020 17:34:15 +0200 Subject: [PATCH 1079/1751] order TOF patterns according to crate and readout window update TOF CTF with crate info for diagnostic --- .../TOF/include/DataFormatsTOF/CTF.h | 8 +++-- DataFormats/Detectors/TOF/src/CTF.cxx | 1 + .../Detectors/TOF/src/DataFormatsTOFLinkDef.h | 2 +- Detectors/TOF/base/include/TOFBase/Digit.h | 13 ++++++++ .../TOF/base/include/TOFBase/WindowFiller.h | 15 +++++++-- Detectors/TOF/base/src/WindowFiller.cxx | 31 +++++++++++++++---- Detectors/TOF/compression/src/Compressor.cxx | 2 +- .../include/TOFReconstruction/CTFCoder.h | 6 ++++ .../include/TOFReconstruction/Decoder.h | 4 +-- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 7 ++++- Detectors/TOF/reconstruction/src/Decoder.cxx | 2 ++ .../workflow/src/CompressedDecodingTask.cxx | 4 +-- .../TOF/workflow/src/TOFDigitWriterSpec.cxx | 2 +- 13 files changed, 77 insertions(+), 20 deletions(-) diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h index 7f6b981ee88cb..7212ce778bb5b 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h @@ -35,7 +35,7 @@ struct CTFHeader { uint32_t firstOrbit = 0; /// 1st orbit of TF uint16_t firstBC = 0; /// 1st BC of TF - ClassDefNV(CTFHeader, 1); + ClassDefNV(CTFHeader, 2); }; /// Compressed but not yet entropy-encoded infos @@ -59,6 +59,7 @@ struct CompressedInfos { std::vector<uint32_t> orbitIncROF; /// increment of ROF orbit wrt orbit of previous ROF std::vector<uint32_t> ndigROF; /// number of digits in ROF std::vector<uint32_t> ndiaROF; /// number of diagnostic/pattern words in ROF + std::vector<uint32_t> ndiaCrate; /// number of diagnostic/pattern words per crate in ROF // Hit data std::vector<uint16_t> timeFrameInc; /// time increment with respect of previous digit in TimeFrame units @@ -72,17 +73,18 @@ struct CompressedInfos { void clear(); - ClassDefNV(CompressedInfos, 1); + ClassDefNV(CompressedInfos, 2); }; /// wrapper for the Entropy-encoded clusters of the TF -struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 10, uint32_t> { +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 11, uint32_t> { static constexpr size_t N = getNBlocks(); enum Slots { BLCbcIncROF, BLCorbitIncROF, BLCndigROF, BLCndiaROF, + BLCndiaCrate, BLCtimeFrameInc, BLCtimeTDCInc, BLCstripID, diff --git a/DataFormats/Detectors/TOF/src/CTF.cxx b/DataFormats/Detectors/TOF/src/CTF.cxx index ce3559df1b3d6..a1097f94efbae 100644 --- a/DataFormats/Detectors/TOF/src/CTF.cxx +++ b/DataFormats/Detectors/TOF/src/CTF.cxx @@ -22,6 +22,7 @@ void CompressedInfos::clear() orbitIncROF.clear(); ndigROF.clear(); ndiaROF.clear(); + ndiaCrate.clear(); timeFrameInc.clear(); timeTDCInc.clear(); stripID.clear(); diff --git a/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h b/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h index 12964816922cf..c6142bb3e8ec1 100644 --- a/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h +++ b/DataFormats/Detectors/TOF/src/DataFormatsTOFLinkDef.h @@ -28,6 +28,6 @@ #pragma link C++ class o2::tof::CTFHeader + ; #pragma link C++ class o2::tof::CompressedInfos + ; #pragma link C++ class o2::tof::CTF + ; -#pragma link C++ class o2::ctf::EncodedBlocks < o2::tof::CTFHeader, 10, uint32_t> + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::tof::CTFHeader, 11, uint32_t> + ; #endif diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index cfad7f4b6fcfc..06d65eaa942c9 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -114,10 +114,23 @@ struct ReadoutWindowData { // for given trigger (or BC or RO frame) o2::dataformats::RangeReference<int, int> ref; o2::dataformats::RangeReference<int, int> refDiagnostic; + + // crate info for diagnostic patterns + int mNdiaCrate[72] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + InteractionRecord mFirstIR{0, 0}; const InteractionRecord& getBCData() const { return mFirstIR; } + void addedDiagnostic(int crate) { mNdiaCrate[crate]++; } + void setDiagnosticInCrate(int crate, int val) { mNdiaCrate[crate] = val; } + int getDiagnosticInCrate(int crate) const { return mNdiaCrate[crate]; } + void setBCData(int orbit, int bc) { mFirstIR.orbit = orbit; diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index 65aa28e74b922..91470fa1cf708 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -24,8 +24,15 @@ namespace tof class WindowFiller { - public: + struct PatternData { + uint32_t pattern; + int icrate; + ulong row; + + PatternData(uint32_t patt = 0, int icr = 0, ulong rw = 0) : pattern(patt), icrate(icr), row(rw) {} + }; + WindowFiller() { initObj(); }; ~WindowFiller() = default; @@ -62,7 +69,7 @@ class WindowFiller } std::vector<uint32_t>& getPatterns() { return mPatterns; } - void addPattern(const uint32_t val, int icrate) { mPatterns.push_back(val); } + void addPattern(const uint32_t val, int icrate, int orbit, int bc) { mCratePatterns.emplace_back(val, icrate, orbit * 3 + (bc + 100) / 1188); } protected: // info TOF timewindow @@ -97,7 +104,9 @@ class WindowFiller std::vector<Digit> mFutureDigits; std::vector<uint32_t> mPatterns; - std::vector<uint32_t> mErrors; + std::vector<uint64_t> mErrors; + + std::vector<PatternData> mCratePatterns; void fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); // void fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID); diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index a1484a673ac1d..e53501bc634ee 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -125,13 +125,28 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) int orbit_shift = mReadoutWindowData.size() / 3; int bc_shift = (mReadoutWindowData.size() % 3) * Geo::BC_IN_WINDOW; info.setBCData(mFirstIR.orbit + orbit_shift, mFirstIR.bc + bc_shift); - int firstPattern = 0; - int npatterns = mPatterns.size(); - if (mReadoutWindowData.size()) { - auto prevROW = mReadoutWindowData[mReadoutWindowData.size() - 1]; - firstPattern = prevROW.firstDia() + prevROW.sizeDia(); - npatterns -= firstPattern; + int firstPattern = mPatterns.size(); + int npatterns = 0; + + // check if patterns are in the current row + int ipatt = mCratePatterns.size() - 1; + for (std::vector<PatternData>::reverse_iterator it = mCratePatterns.rbegin(); it != mCratePatterns.rend(); ++it) { + if (it->row > mReadoutWindowCurrent) + break; + + if (it->row < mReadoutWindowCurrent) { // this should not happen + LOG(ERROR) << "One pattern skipped because appears to occur early of the current row " << it->row << " < " << mReadoutWindowCurrent << " ?!"; + mCratePatterns.erase(mCratePatterns.begin() + ipatt); + } else { + mPatterns.push_back(it->pattern); + info.addedDiagnostic(it->icrate); + + mCratePatterns.erase(mCratePatterns.begin() + ipatt); + npatterns++; + } + ipatt--; } + info.setFirstEntryDia(firstPattern); info.setNEntriesDia(npatterns); if (digits.size()) { @@ -161,6 +176,10 @@ void WindowFiller::flushOutputContainer(std::vector<Digit>& digits) { // flush all residual buffered data // TO be implemented + // sort patterns (diagnostic words) in time + std::sort(mCratePatterns.begin(), mCratePatterns.end(), + [](PatternData a, PatternData b) { if(a.row == b.row) return a.icrate > b.icrate; else return a.row > b.row; }); + for (Int_t i = 0; i < MAXWINDOWS; i++) { int n = 0; for (int j = 0; j < mStrips[i].size(); j++) diff --git a/Detectors/TOF/compression/src/Compressor.cxx b/Detectors/TOF/compression/src/Compressor.cxx index a2fc2506cee45..318aa7867bd78 100644 --- a/Detectors/TOF/compression/src/Compressor.cxx +++ b/Detectors/TOF/compression/src/Compressor.cxx @@ -889,7 +889,7 @@ bool Compressor<RDH, verbose>::checkerCheck() for (int itrm = 0; itrm < 10; ++itrm) { mDecoderSummary.trmDataHeader[itrm] = nullptr; mDecoderSummary.trmDataTrailer[itrm] = nullptr; - for (int ichain = 0; ichain < 10; ++ichain) { + for (int ichain = 0; ichain < 2; ++ichain) { mDecoderSummary.trmChainHeader[itrm][ichain] = nullptr; mDecoderSummary.trmChainTrailer[itrm][ichain] = nullptr; mDecoderSummary.trmErrors[itrm][ichain] = 0; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index 6d393a065f31e..9144225f17056 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -74,6 +74,7 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRe MD::EENCODE, //BLCorbitIncROF MD::EENCODE, //BLCndigROF MD::EENCODE, //BLCndiaROF + MD::EENCODE, //BLCndiaCrate MD::EENCODE, //BLCtimeFrameInc MD::EENCODE, //BLCtimeTDCInc MD::EENCODE, //BLCstripID @@ -100,6 +101,7 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const ReadoutWindowData>& rofRe ENCODETOF(cc.orbitIncROF, CTF::BLCorbitIncROF, 0); ENCODETOF(cc.ndigROF, CTF::BLCndigROF, 0); ENCODETOF(cc.ndiaROF, CTF::BLCndiaROF, 0); + ENCODETOF(cc.ndiaCrate, CTF::BLCndiaCrate, 0); ENCODETOF(cc.timeFrameInc, CTF::BLCtimeFrameInc, 0); ENCODETOF(cc.timeTDCInc, CTF::BLCtimeTDCInc, 0); ENCODETOF(cc.stripID, CTF::BLCstripID, 0); @@ -124,6 +126,7 @@ void CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& cdigVec, VPAT& DECODETOF(cc.orbitIncROF, CTF::BLCorbitIncROF); DECODETOF(cc.ndigROF, CTF::BLCndigROF); DECODETOF(cc.ndiaROF, CTF::BLCndiaROF); + DECODETOF(cc.ndiaCrate, CTF::BLCndiaCrate); DECODETOF(cc.timeFrameInc, CTF::BLCtimeFrameInc); DECODETOF(cc.timeTDCInc, CTF::BLCtimeTDCInc); @@ -161,6 +164,9 @@ void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdig rofRec.setNEntries(cc.ndigROF[irof]); rofRec.setFirstEntryDia(ndiagnostic); rofRec.setNEntriesDia(cc.ndiaROF[irof]); + for (int icrate = 0; icrate < 72; icrate++) + rofRec.setDiagnosticInCrate(icrate, cc.ndiaCrate[irof * 72 + icrate]); + firstEntry += cc.ndigROF[irof]; ndiagnostic += cc.ndiaROF[irof]; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h index 16b0a6946d6ad..735273db631f4 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/Decoder.h @@ -71,8 +71,8 @@ class Decoder : public WindowFiller char* nextPage(void* current, int shift = 8192); - std::vector<uint32_t>& getErrors() { return mErrors; } - void addError(const uint32_t val, int icrate) { mErrors.push_back(val); } + std::vector<uint64_t>& getErrors() { return mErrors; } + void addError(const uint32_t val, int icrate) { mErrors.push_back((uint64_t(icrate) << 32) + val); } protected: static const int NCRU = 4; diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index 507e923122375..8d745f9dd50c2 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -61,6 +61,7 @@ void CTFCoder::compress(CompressedInfos& cc, cc.orbitIncROF.resize(cc.header.nROFs); cc.ndigROF.resize(cc.header.nROFs); cc.ndiaROF.resize(cc.header.nROFs); + cc.ndiaCrate.resize(cc.header.nROFs * 72); // cc.timeFrameInc.resize(cc.header.nDigits); cc.timeTDCInc.resize(cc.header.nDigits); @@ -92,6 +93,8 @@ void CTFCoder::compress(CompressedInfos& cc, auto ndig = rofRec.size(); cc.ndigROF[irof] = ndig; cc.ndiaROF[irof] = rofRec.sizeDia(); + for (int icrate = 0; icrate < 72; icrate++) + cc.ndiaCrate[irof * 72 + icrate] = rofRec.getDiagnosticInCrate(icrate); if (!ndig) { // no hits data for this ROF --> not fill continue; @@ -176,7 +179,8 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: MAKECODER(cc.orbitIncROF, CTF::BLCorbitIncROF); MAKECODER(cc.ndigROF, CTF::BLCndigROF); MAKECODER(cc.ndiaROF, CTF::BLCndiaROF); - + MAKECODER(cc.ndiaCrate, CTF::BLCndiaCrate); + MAKECODER(cc.timeFrameInc, CTF::BLCtimeFrameInc); MAKECODER(cc.timeTDCInc, CTF::BLCtimeTDCInc); MAKECODER(cc.stripID, CTF::BLCstripID); @@ -200,6 +204,7 @@ size_t CTFCoder::estimateCompressedSize(const CompressedInfos& cc) sz += ESTSIZE(cc.orbitIncROF, CTF::BLCorbitIncROF); sz += ESTSIZE(cc.ndigROF, CTF::BLCndigROF); sz += ESTSIZE(cc.ndiaROF, CTF::BLCndiaROF); + sz += ESTSIZE(cc.ndiaCrate, CTF::BLCndiaCrate); sz += ESTSIZE(cc.timeFrameInc, CTF::BLCtimeFrameInc); sz += ESTSIZE(cc.timeTDCInc, CTF::BLCtimeTDCInc); sz += ESTSIZE(cc.stripID, CTF::BLCstripID); diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index df239a31c2904..10a349648d188 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -115,6 +115,8 @@ void Decoder::clear() clearCounts(); mPatterns.clear(); + mCratePatterns.clear(); + mErrors.clear(); } diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 65717746e82e4..719abbe62da16 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -100,7 +100,7 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) std::vector<uint32_t> patterns = mDecoder.getPatterns(); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, patterns); - std::vector<uint32_t> errors = mDecoder.getErrors(); + std::vector<uint64_t> errors = mDecoder.getErrors(); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ERRORS", 0, Lifetime::Timeframe}, errors); // RS this is a hack to be removed once we have correct propagation of the firstTForbit by the framework @@ -190,7 +190,7 @@ void CompressedDecodingTask::trailerHandler(const CrateHeader_t* crateHeader, co auto numberOfErrors = crateTrailer->numberOfErrors; for (int i = 0; i < numberOfDiagnostics; i++) { const uint32_t* val = reinterpret_cast<const uint32_t*>(&(diagnostics[i])); - mDecoder.addPattern(*val, crateHeader->drmID); + mDecoder.addPattern(*val, crateHeader->drmID, crateOrbit->orbitID, crateHeader->bunchID); int islot = (*val & 15); printf("DRM = %d (orbit = %d) slot = %d: \n", crateHeader->drmID, crateOrbit->orbitID, islot); diff --git a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx index 9bca21d5a2824..b174c808aabad 100644 --- a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx @@ -27,7 +27,7 @@ using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; using OutputType = std::vector<o2::tof::Digit>; using ReadoutWinType = std::vector<o2::tof::ReadoutWindowData>; using PatternType = std::vector<uint32_t>; -using ErrorType = std::vector<uint32_t>; +using ErrorType = std::vector<uint64_t>; using LabelsType = std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>; using namespace o2::header; From 7397c7bbde5dc6113fbcbbb594ed3abe4f3086c3 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Tue, 20 Oct 2020 22:25:27 +0200 Subject: [PATCH 1080/1751] fixes for PR 4645 --- DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h | 2 +- Detectors/TOF/base/include/TOFBase/Digit.h | 7 +------ Detectors/TOF/base/include/TOFBase/WindowFiller.h | 7 +++---- Detectors/TOF/base/src/WindowFiller.cxx | 5 +---- Detectors/TOF/workflow/src/CompressedDecodingTask.cxx | 4 ++-- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h index 7212ce778bb5b..75341a074681b 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CTF.h @@ -35,7 +35,7 @@ struct CTFHeader { uint32_t firstOrbit = 0; /// 1st orbit of TF uint16_t firstBC = 0; /// 1st BC of TF - ClassDefNV(CTFHeader, 2); + ClassDefNV(CTFHeader, 1); }; /// Compressed but not yet entropy-encoded infos diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index 06d65eaa942c9..69627ea275c8e 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -116,12 +116,7 @@ struct ReadoutWindowData { o2::dataformats::RangeReference<int, int> refDiagnostic; // crate info for diagnostic patterns - int mNdiaCrate[72] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int mNdiaCrate[72] = {0}; InteractionRecord mFirstIR{0, 0}; diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index 91470fa1cf708..9ff6a7123d8bc 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -28,9 +28,9 @@ class WindowFiller struct PatternData { uint32_t pattern; int icrate; - ulong row; + unsigned long row; - PatternData(uint32_t patt = 0, int icr = 0, ulong rw = 0) : pattern(patt), icrate(icr), row(rw) {} + PatternData(uint32_t patt = 0, int icr = 0, unsigned long rw = 0) : pattern(patt), icrate(icr), row(rw) {} }; WindowFiller() { initObj(); }; @@ -64,8 +64,7 @@ class WindowFiller void clearCounts() { - for (int i = 0; i < o2::tof::Geo::NCHANNELS; i++) - mChannelCounts[i] = 0; + memset(mChannelCounts, 0, o2::tof::Geo::NCHANNELS * sizeof(mChannelCounts[0])); } std::vector<uint32_t>& getPatterns() { return mPatterns; } diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index e53501bc634ee..ad2d1115592ab 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -129,22 +129,19 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) int npatterns = 0; // check if patterns are in the current row - int ipatt = mCratePatterns.size() - 1; for (std::vector<PatternData>::reverse_iterator it = mCratePatterns.rbegin(); it != mCratePatterns.rend(); ++it) { if (it->row > mReadoutWindowCurrent) break; if (it->row < mReadoutWindowCurrent) { // this should not happen LOG(ERROR) << "One pattern skipped because appears to occur early of the current row " << it->row << " < " << mReadoutWindowCurrent << " ?!"; - mCratePatterns.erase(mCratePatterns.begin() + ipatt); } else { mPatterns.push_back(it->pattern); info.addedDiagnostic(it->icrate); - mCratePatterns.erase(mCratePatterns.begin() + ipatt); npatterns++; } - ipatt--; + mCratePatterns.pop_back(); } info.setFirstEntryDia(firstPattern); diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 719abbe62da16..adf55a273bdf7 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -97,10 +97,10 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, *alldigits); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, *row); - std::vector<uint32_t> patterns = mDecoder.getPatterns(); + std::vector<uint32_t>& patterns = mDecoder.getPatterns(); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, patterns); - std::vector<uint64_t> errors = mDecoder.getErrors(); + std::vector<uint64_t>& errors = mDecoder.getErrors(); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ERRORS", 0, Lifetime::Timeframe}, errors); // RS this is a hack to be removed once we have correct propagation of the firstTForbit by the framework From e270bff9775ad04adccc246897e144af7560d697 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 21 Oct 2020 18:00:39 +0200 Subject: [PATCH 1081/1751] Change ITS/MFT GBT data ERRORCHECK, new error for unknown GBT word --- .../ITSMFTReconstruction/DecodingStat.h | 8 +-- .../include/ITSMFTReconstruction/GBTLink.h | 51 ++++++++++--------- .../common/reconstruction/src/GBTLink.cxx | 3 ++ 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h index 4c759ee6dce4d..f93d17141eb28 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h @@ -93,7 +93,7 @@ struct GBTLinkDecodingStat { enum DecErrors : int { ErrNoRDHAtStart, // page does not start with RDH - ErrPageNotStopped, // new HB/trigger page started w/o stopping previous one + ErrPageNotStopped, // RDH is stopped, but the time is not matching the ~stop packet ErrStopPageNotEmpty, // Page with RDH.stop is not empty ErrPageCounterDiscontinuity, // RDH page counters for the same RU/trigger are not continuous ErrRDHvsGBTHPageCnt, // RDH and GBT header page counters are not consistent @@ -110,11 +110,12 @@ struct GBTLinkDecodingStat { ErrPacketCounterJump, // jump in RDH.packetCounter ErrPacketDoneMissing, // packet done is missing in the trailer while CRU page is not over ErrMissingDiagnosticWord, // missing diagnostic word after RDH with stop + ErrGBTWordNotRecognized, // GBT word not recognized NErrorsDefined }; static constexpr std::array<std::string_view, NErrorsDefined> ErrNames = { "Page data not start with expected RDH", // ErrNoRDHAtStart - "New HB/trigger page started w/o stopping previous one", // ErrPageNotStopped + "RDH is stopped, but the time is not matching the ~stop packet", // ErrPageNotStopped "Page with RDH.stop does not contain diagnostic word only", // ErrStopPageNotEmpty "RDH page counters for the same RU/trigger are not continuous", // ErrPageCounterDiscontinuity "RDH and GBT header page counters are not consistent", // ErrRDHvsGBTHPageCnt @@ -130,7 +131,8 @@ struct GBTLinkDecodingStat { "Active lanes pattern conflicts with expected for given RU type", // ErrInvalidActiveLanes "Jump in RDH_packetCounter", // ErrPacketCounterJump "Packet done is missing in the trailer while CRU page is not over", // ErrPacketDoneMissing - "Missing diagnostic GBT word after RDH with stop" // ErrMissingDiagnosticWord + "Missing diagnostic GBT word after RDH with stop", // ErrMissingDiagnosticWord + "GBT word not recognized" // ErrGBTWordNotRecognized }; uint32_t ruLinkID = 0; // Link ID within RU diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h index 29c987611cd62..f8e459f31d407 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h @@ -29,13 +29,12 @@ #include "DetectorsRaw/RDHUtils.h" #include "CommonDataFormat/InteractionRecord.h" -#define GBTLINK_DECODE_ERRORCHECK(what) \ - if ((what) == Abort) { \ - discardData(); \ - LOG(ERROR) << "Aborting decoding"; \ - return AbortedOnError; \ - } else if ((what) == Skip) { \ - continue; \ +#define GBTLINK_DECODE_ERRORCHECK(errRes, errEval) \ + errRes = errEval; \ + if ((errRes) == Abort) { \ + discardData(); \ + LOG(ERROR) << "Aborting decoding"; \ + return AbortedOnError; \ } namespace o2 @@ -181,6 +180,7 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) int nw = 0; status = None; auto* currRawPiece = rawData.currentPiece(); + GBTLink::ErrorType errRes = GBTLink::NoError; while (currRawPiece) { // we may loop over multiple CRU page if (dataOffset >= currRawPiece->size) { dataOffset = 0; // start of the RDH @@ -193,8 +193,9 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) if (verbosity >= VerboseHeaders) { RDHUtils::printRDH(rdh); } - GBTLINK_DECODE_ERRORCHECK(checkErrorsRDH(*rdh)); // make sure we are dealing with RDH - GBTLINK_DECODE_ERRORCHECK(checkErrorsRDHStop(*rdh)); // if new HB starts, the lastRDH must have stop + + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsRDH(*rdh)); // make sure we are dealing with RDH + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsRDHStop(*rdh)); // if new HB starts, the lastRDH must have stop // GBTLINK_DECODE_ERRORCHECK(checkErrorsRDHStopPageEmpty(*rdh)); // end of HBF should be an empty page with stop lastRDH = rdh; statistics.nPackets++; @@ -209,7 +210,7 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) if (verbosity >= VerboseHeaders) { printDiagnostic(gbtDiag); } - GBTLINK_DECODE_ERRORCHECK(checkErrorsDiagnosticWord(gbtDiag)); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsDiagnosticWord(gbtDiag)); dataOffset += RDHUtils::getOffsetToNext(*rdh) - sizeof(RDH); continue; } @@ -221,14 +222,14 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) printHeader(gbtH); } if (format == OldFormat) { - GBTLINK_DECODE_ERRORCHECK(checkErrorsHeaderWord(reinterpret_cast<const GBTDataHeaderL*>(gbtH))); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsHeaderWord(reinterpret_cast<const GBTDataHeaderL*>(gbtH))); lanesActive = reinterpret_cast<const GBTDataHeaderL*>(gbtH)->activeLanesL; // TODO do we need to update this for every page? } else { - GBTLINK_DECODE_ERRORCHECK(checkErrorsHeaderWord(gbtH)); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsHeaderWord(gbtH)); lanesActive = gbtH->activeLanes; // TODO do we need to update this for every page? } - GBTLINK_DECODE_ERRORCHECK(checkErrorsActiveLanes(chmap.getCablesOnRUType(ruPtr->ruInfo->ruType))); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsActiveLanes(chmap.getCablesOnRUType(ruPtr->ruInfo->ruType))); if (format == OldFormat && reinterpret_cast<const GBTDataHeaderL*>(gbtH)->packetIdx == 0) { // reset flags in case of 1st page of new ROF (old format: judge by RDH) lanesStop = 0; lanesWithData = 0; @@ -247,7 +248,7 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) if (verbosity >= VerboseHeaders) { printTrigger(gbtTrg); } - GBTLINK_DECODE_ERRORCHECK(checkErrorsTriggerWord(gbtTrg)); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsTriggerWord(gbtTrg)); if (gbtTrg->noData) { // emtpy trigger return status; } @@ -267,16 +268,18 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) while (!gbtD->isDataTrailer()) { // start reading real payload nw++; - GBTLINK_DECODE_ERRORCHECK(checkErrorsGBTDataID(gbtD)); - int cableHW = gbtD->getCableID(), cableSW = chmap.cableHW2SW(ruPtr->ruInfo->ruType, cableHW); if (verbosity >= VerboseData) { gbtD->printX(); } - GBTLINK_DECODE_ERRORCHECK(checkErrorsGBTData(chmap.cableHW2Pos(ruPtr->ruInfo->ruType, cableHW))); - ruPtr->cableData[cableSW].add(gbtD->getW8(), 9); - ruPtr->cableHWID[cableSW] = cableHW; - ruPtr->cableLinkID[cableSW] = idInRU; - ruPtr->cableLinkPtr[cableSW] = this; + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsGBTDataID(gbtD)); + if (errRes != GBTLink::Skip) { + int cableHW = gbtD->getCableID(), cableSW = chmap.cableHW2SW(ruPtr->ruInfo->ruType, cableHW); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsGBTData(chmap.cableHW2Pos(ruPtr->ruInfo->ruType, cableHW))); + ruPtr->cableData[cableSW].add(gbtD->getW8(), 9); + ruPtr->cableHWID[cableSW] = cableHW; + ruPtr->cableLinkID[cableSW] = idInRU; + ruPtr->cableLinkPtr[cableSW] = this; + } dataOffset += GBTPaddedWordLength; gbtD = reinterpret_cast<const o2::itsmft::GBTData*>(&currRawPiece->data[dataOffset]); } // we are at the trailer, packet is over, check if there are more data on the next page @@ -286,14 +289,14 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) if (verbosity >= VerboseHeaders) { printTrailer(gbtT); } - GBTLINK_DECODE_ERRORCHECK(checkErrorsTrailerWord(gbtT)); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsTrailerWord(gbtT)); // we finished the GBT page, but there might be continuation on the next CRU page if (!gbtT->packetDone) { - GBTLINK_DECODE_ERRORCHECK(checkErrorsPacketDoneMissing(gbtT, dataOffset < currRawPiece->size)); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsPacketDoneMissing(gbtT, dataOffset < currRawPiece->size)); continue; // keep reading next CRU page } if (format == OldFormat) { - GBTLINK_DECODE_ERRORCHECK(checkErrorsLanesStops()); + GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsLanesStops()); } // accumulate packet states statistics.packetStates[gbtT->getPacketState()]++; diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index 4b1219e988500..e37fa485b5ca7 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -327,6 +327,9 @@ GBTLink::ErrorType GBTLink::checkErrorsGBTDataID(const GBTData* gbtD) } else if (gbtD->isStatus()) { printCableStatus((GBTCableStatus*)gbtD); } + LOG(ERROR) << describe() << ' ' << statistics.ErrNames[GBTLinkDecodingStat::ErrGBTWordNotRecognized]; + gbtD->printX(true); + statistics.errorCounts[GBTLinkDecodingStat::ErrGBTWordNotRecognized]++; return Skip; } From 905c1f58000b48d9b6b51896b58e0324469614db Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 25 Sep 2020 00:02:58 +0200 Subject: [PATCH 1082/1751] add raw conversion operators for AbstractRef and VtxTrackIndex --- .../include/ReconstructionDataFormats/VtxTrackIndex.h | 2 ++ DataFormats/common/include/CommonDataFormat/AbstractRef.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h index b55c0b521fc8e..92dd28cf0b914 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h @@ -53,6 +53,8 @@ class VtxTrackIndex : public AbstractRef<26, 3, 3> void print() const; std::string asString() const; + operator auto() const { return AbstractRef<26, 3, 3>(); } + ClassDefNV(VtxTrackIndex, 1); }; diff --git a/DataFormats/common/include/CommonDataFormat/AbstractRef.h b/DataFormats/common/include/CommonDataFormat/AbstractRef.h index fbfc95d49d213..70fdc16735902 100644 --- a/DataFormats/common/include/CommonDataFormat/AbstractRef.h +++ b/DataFormats/common/include/CommonDataFormat/AbstractRef.h @@ -70,6 +70,8 @@ class AbstractRef Base_t getRaw() const { return mRef; } + operator Base_t() const { return mRef; } + protected: Base_t mRef = 0; // packed reference From 272c9c80f34a85224772171f27e40b113f06dff5 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 12 Oct 2020 15:57:33 +0200 Subject: [PATCH 1083/1751] getter for Mass^2 of predefined particles --- .../include/ReconstructionDataFormats/PID.h | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h index 9f1b6b12477aa..25f010b20d2e4 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h @@ -22,6 +22,8 @@ namespace o2 { namespace track { +namespace o2cp = o2::constants::physics; + class PID { public: @@ -68,6 +70,7 @@ class PID static constexpr const char* getName(ID id) { return sNames[id]; } static constexpr float getMass(ID id) { return sMasses[id]; } + static constexpr float getMass2(ID id) { return sMasses2[id]; } static constexpr float getMass2Z(ID id) { return sMasses2Z[id]; } static constexpr int getCharge(ID id) { return sCharges[id]; } @@ -91,22 +94,34 @@ class PID nullptr}; static constexpr const float sMasses[NIDsTot] = ///< defined particle masses - {o2::constants::physics::MassElectron, o2::constants::physics::MassMuon, - o2::constants::physics::MassPionCharged, o2::constants::physics::MassKaonCharged, - o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron, - o2::constants::physics::MassTriton, o2::constants::physics::MassHelium3, - o2::constants::physics::MassAlpha, - o2::constants::physics::MassPionNeutral, o2::constants::physics::MassPhoton, - o2::constants::physics::MassKaonNeutral, o2::constants::physics::MassLambda, - o2::constants::physics::MassHyperTriton}; + {o2cp::MassElectron, o2cp::MassMuon, o2cp::MassPionCharged, o2cp::MassKaonCharged, + o2cp::MassProton, o2cp::MassDeuteron, o2cp::MassTriton, o2cp::MassHelium3, + o2cp::MassAlpha, o2cp::MassPionNeutral, o2cp::MassPhoton, + o2cp::MassKaonNeutral, o2cp::MassLambda, o2cp::MassHyperTriton}; + + static constexpr const float sMasses2[NIDsTot] = ///< defined particle masses^2 + {o2cp::MassElectron * o2cp::MassElectron, + o2cp::MassMuon* o2cp::MassMuon, + o2cp::MassPionCharged* o2cp::MassPionCharged, + o2cp::MassKaonCharged* o2cp::MassKaonCharged, + o2cp::MassProton* o2cp::MassProton, + o2cp::MassDeuteron* o2cp::MassDeuteron, + o2cp::MassTriton* o2cp::MassTriton, + o2cp::MassHelium3* o2cp::MassHelium3, + o2cp::MassAlpha* o2cp::MassAlpha, + o2cp::MassPionNeutral* o2cp::MassPionNeutral, + o2cp::MassPhoton* o2cp::MassPhoton, + o2cp::MassKaonNeutral* o2cp::MassKaonNeutral, + o2cp::MassLambda* o2cp::MassLambda, + o2cp::MassHyperTriton* o2cp::MassHyperTriton}; static constexpr const float sMasses2Z[NIDsTot] = ///< defined particle masses / Z - {o2::constants::physics::MassElectron, o2::constants::physics::MassMuon, - o2::constants::physics::MassPionCharged, o2::constants::physics::MassKaonCharged, - o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron, - o2::constants::physics::MassTriton, o2::constants::physics::MassHelium3 / 2., - o2::constants::physics::MassAlpha / 2., - 0, 0, 0, 0, o2::constants::physics::MassHyperTriton}; + {o2cp::MassElectron, o2cp::MassMuon, + o2cp::MassPionCharged, o2cp::MassKaonCharged, + o2cp::MassProton, o2cp::MassDeuteron, + o2cp::MassTriton, o2cp::MassHelium3 / 2., + o2cp::MassAlpha / 2., + 0, 0, 0, 0, o2cp::MassHyperTriton}; static constexpr const int sCharges[NIDsTot] = ///< defined particle charges {1, 1, 1, 1, 1, 1, 1, 2, 2, From 3dc11a1528b7338b6458939fc2be069cf378d588 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 12 Oct 2020 15:58:09 +0200 Subject: [PATCH 1084/1751] Allow using TrackPar constructors in TrackParCov --- .../ReconstructionDataFormats/TrackParametrizationWithError.h | 1 + 1 file changed, 1 insertion(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index ce9be0e0bf901..dfd3e1ad2ed75 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -49,6 +49,7 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> TrackParametrizationWithError& operator=(const TrackParametrizationWithError& src) = default; TrackParametrizationWithError& operator=(TrackParametrizationWithError&& src) = default; ~TrackParametrizationWithError() = default; + using TrackParametrization<value_T>::TrackParametrization; const value_t* getCov() const; value_t getSigmaY2() const; From 401ffcb13a3cab32344ffd421567a71f35fdefd2 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 12 Oct 2020 15:59:58 +0200 Subject: [PATCH 1085/1751] Fixes in Prim.vertexer --- .../src/PrimaryVertexReaderSpec.cxx | 4 ++-- .../src/PrimaryVertexingSpec.cxx | 16 +++++++++++++++- .../src/primary-vertexing-workflow.cxx | 2 +- Detectors/Vertexing/src/PVertexer.cxx | 6 +++++- Detectors/Vertexing/src/VertexTrackMatcher.cxx | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx index d87aaa9e99b2f..a5640d7503689 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexReaderSpec.cxx @@ -39,7 +39,7 @@ void PrimaryVertexReader::run(ProcessingContext& pc) pc.outputs().snapshot(Output{"GLO", "PVTX", 0, Lifetime::Timeframe}, mVertices); pc.outputs().snapshot(Output{"GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe}, mPV2MatchIdx); - pc.outputs().snapshot(Output{"GLO", "PVTX_TRMTCREF", 0, Lifetime::Timeframe}, mPV2MatchIdxRef); + pc.outputs().snapshot(Output{"GLO", "PVTX_TRMTCREFS", 0, Lifetime::Timeframe}, mPV2MatchIdxRef); if (mUseMC) { pc.outputs().snapshot(Output{"GLO", "PVTX_MCTR", 0, Lifetime::Timeframe}, mLabels); @@ -108,7 +108,7 @@ DataProcessorSpec getPrimaryVertexReaderSpec(bool useMC) std::vector<OutputSpec> outputs; outputs.emplace_back("GLO", "PVTX", 0, Lifetime::Timeframe); outputs.emplace_back("GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe); - outputs.emplace_back("GLO", "PVTX_TRMTCREF", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_TRMTCREFS", 0, Lifetime::Timeframe); if (useMC) { outputs.emplace_back("GLO", "PVTX_MCTR", 0, Lifetime::Timeframe); diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx index 27995a0db2962..95e46098a117e 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx @@ -13,10 +13,13 @@ #include <vector> #include "ReconstructionDataFormats/TrackTPCITS.h" #include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" #include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" #include "SimulationDataFormat/MCEventLabel.h" #include "CommonDataFormat/BunchFilling.h" #include "SimulationDataFormat/DigitizationContext.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "Framework/ConfigParamRegistry.h" using namespace o2::framework; @@ -28,7 +31,18 @@ namespace vertexing void PrimaryVertexingSpec::init(InitContext& ic) { //-------- init geometry and field --------// + o2::base::GeometryManager::loadGeometry(); o2::base::Propagator::initFieldFromGRP("o2sim_grp.root"); + // this is a hack to provide Mat.LUT from the local file, in general will be provided by the framework from CCDB + std::string matLUTPath = ic.options().get<std::string>("material-lut-path"); + std::string matLUTFile = o2::base::NameConf::getMatLUTFileName(matLUTPath); + if (o2::base::NameConf::pathExists(matLUTFile)) { + auto* lut = o2::base::MatLayerCylSet::loadFromFile(matLUTFile); + o2::base::Propagator::Instance()->setMatLUT(lut); + LOG(INFO) << "Loaded material LUT from " << matLUTFile; + } else { + LOG(INFO) << "Material LUT " << matLUTFile << " file is absent, only TGeo can be used"; + } mTimer.Stop(); mTimer.Reset(); mVertexer.setValidateWithFT0(mValidateWithFT0); @@ -108,7 +122,7 @@ DataProcessorSpec getPrimaryVertexingSpec(bool validateWithFT0, bool useMC) inputs, outputs, AlgorithmSpec{adaptFromTask<PrimaryVertexingSpec>(validateWithFT0, useMC)}, - Options{}}; + Options{{"material-lut-path", VariantType::String, "", {"Path of the material LUT file"}}}}; } } // namespace vertexing diff --git a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx index a7fd115237c5a..6b8a06d649c60 100644 --- a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx @@ -65,7 +65,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } specs.emplace_back(o2::vertexing::getPrimaryVertexingSpec(validateWithFT0, useMC)); - if (!disableMatching) { + if (!disableMatching && !disableRootInp) { specs.emplace_back(o2::its::getITSTrackReaderSpec(false)); specs.emplace_back(o2::tpc::getTPCTrackReaderSpec(false)); specs.emplace_back(o2::vertexing::getVertexTrackMatcherSpec()); diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index 0dd30f0ded5aa..9bddad9bed829 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -14,6 +14,7 @@ #include "DetectorsVertexing/PVertexer.h" #include "ReconstructionDataFormats/DCA.h" +#include "DetectorsBase/Propagator.h" #include "Math/SMatrix.h" #include "Math/SVector.h" #include <numeric> @@ -87,7 +88,7 @@ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span int it = v2tRefsLoc[i].getFirstEntry(), itEnd = it + v2tRefsLoc[i].getEntries(), dest0 = vertexTrackIDs.size(); for (; it < itEnd; it++) { auto& gid = vertexTrackIDs.emplace_back(vertexTrackIDsLoc[it], GIndex::TPCITS); - gid.setBit(GIndex::Contributor); + gid.setPVContributor(); } v2tRefs.emplace_back(dest0, v2tRefsLoc[i].getEntries()); LOG(DEBUG) << "#" << count++ << " " << vertices.back() << " | " << v2tRefs.back().getEntries() << " indices from " << v2tRefs.back().getFirstEntry(); // RS REM @@ -429,6 +430,9 @@ void PVertexer::init() mFT0Params = &o2::ft0::InteractionTag::Instance(); setTukey(mPVParams->tukey); initMeanVertexConstraint(); + + auto* prop = o2::base::Propagator::Instance(); + setBz(prop->getNominalBz()); } //___________________________________________________________________ diff --git a/Detectors/Vertexing/src/VertexTrackMatcher.cxx b/Detectors/Vertexing/src/VertexTrackMatcher.cxx index a52d70684f8c3..e45f9da7d7fa5 100644 --- a/Detectors/Vertexing/src/VertexTrackMatcher.cxx +++ b/Detectors/Vertexing/src/VertexTrackMatcher.cxx @@ -134,7 +134,7 @@ void VertexTrackMatcher::process(const gsl::span<const PVertex>& vertices, } auto& gid = trackIndex.emplace_back(gid0); if ((*vptr[src])[gid.getIndex()] > 1) { - gid.setBit(GIndex::Ambiguous); + gid.setAmbiguous(); } } From 2b82f65a8b3e7ff0a197035cef7d78f236c249a3 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 12 Oct 2020 16:01:02 +0200 Subject: [PATCH 1086/1751] V0 finder + related workflows --- DataFormats/Reconstruction/CMakeLists.txt | 2 + .../include/ReconstructionDataFormats/V0.h | 77 ++++++ .../ReconstructionDataFormats/VtxTrackIndex.h | 6 + .../src/ReconstructionDataFormatsLinkDef.h | 3 + DataFormats/Reconstruction/src/V0.cxx | 28 +++ .../GlobalTrackingWorkflow/CMakeLists.txt | 15 +- .../SecondaryVertexReaderSpec.h | 65 +++++ .../SecondaryVertexWriterSpec.h | 29 +++ .../SecondaryVertexingSpec.h | 48 ++++ .../src/SecondaryVertexReaderSpec.cxx | 81 ++++++ .../src/SecondaryVertexWriterSpec.cxx | 50 ++++ .../src/SecondaryVertexingSpec.cxx | 120 +++++++++ .../src/secondary-vertex-reader-workflow.cxx | 42 ++++ .../src/secondary-vertexing-workflow.cxx | 64 +++++ Detectors/Vertexing/CMakeLists.txt | 9 +- .../include/DetectorsVertexing/SVertexer.h | 120 +++++++++ .../DetectorsVertexing/SVertexerParams.h | 70 ++++++ .../include/DetectorsVertexing/V0Hypothesis.h | 80 ++++++ .../Vertexing/src/DetectorsVertexingLinkDef.h | 4 + Detectors/Vertexing/src/SVertexer.cxx | 235 ++++++++++++++++++ Detectors/Vertexing/src/SVertexerParams.cxx | 17 ++ Detectors/Vertexing/src/V0Hypothesis.cxx | 34 +++ 22 files changed, 1197 insertions(+), 2 deletions(-) create mode 100644 DataFormats/Reconstruction/include/ReconstructionDataFormats/V0.h create mode 100644 DataFormats/Reconstruction/src/V0.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexReaderSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexWriterSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexingSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/src/SecondaryVertexReaderSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/SecondaryVertexWriterSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/secondary-vertex-reader-workflow.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.cxx create mode 100644 Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h create mode 100644 Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h create mode 100644 Detectors/Vertexing/include/DetectorsVertexing/V0Hypothesis.h create mode 100644 Detectors/Vertexing/src/SVertexer.cxx create mode 100644 Detectors/Vertexing/src/SVertexerParams.cxx create mode 100644 Detectors/Vertexing/src/V0Hypothesis.cxx diff --git a/DataFormats/Reconstruction/CMakeLists.txt b/DataFormats/Reconstruction/CMakeLists.txt index d8e4e17c54d08..c24054a29dcde 100644 --- a/DataFormats/Reconstruction/CMakeLists.txt +++ b/DataFormats/Reconstruction/CMakeLists.txt @@ -20,6 +20,7 @@ o2_add_library(ReconstructionDataFormats src/TrackLTIntegral.cxx src/PID.cxx src/DCA.cxx + src/V0.cxx src/VtxTrackIndex.cxx src/VtxTrackRef.cxx PUBLIC_LINK_LIBRARIES O2::GPUCommon @@ -39,6 +40,7 @@ o2_target_root_dictionary( include/ReconstructionDataFormats/TrackLTIntegral.h include/ReconstructionDataFormats/PID.h include/ReconstructionDataFormats/DCA.h + include/ReconstructionDataFormats/V0.h include/ReconstructionDataFormats/VtxTrackIndex.h include/ReconstructionDataFormats/VtxTrackRef.h) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/V0.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/V0.h new file mode 100644 index 0000000000000..3c8055dc33219 --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/V0.h @@ -0,0 +1,77 @@ +// 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_V0_H +#define ALICEO2_V0_H + +#include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/PID.h" +#include <array> +#include <Math/SVector.h> + +namespace o2 +{ +namespace dataformats +{ + +class V0 : public o2::track::TrackParCov +{ + public: + using GIndex = o2::dataformats::VtxTrackIndex; + using Track = o2::track::TrackParCov; + using PID = o2::track::PID; + + V0() = default; + V0(const std::array<float, 3>& xyz, const std::array<float, 3>& pxyz, + const o2::track::TrackParCov& trPos, const o2::track::TrackParCov& trNeg, + GIndex trPosID, GIndex trNegID); + + GIndex getProngID(int i) const { return mProngIDs[i]; } + void setProngID(int i, GIndex gid) { mProngIDs[i] = gid; } + + const Track& getProng(int i) const { return mProngs[i]; } + Track& getProng(int i) { return mProngs[i]; } + void setProng(int i, const Track& t) { mProngs[i] = t; } + + float getCosPA() const { return mCosPA; } + void setCosPA(float c) { mCosPA = c; } + + float getDCA() const { return mDCA; } + void setDCA(float d) { mDCA = d; } + + int getVertexID() const { return mVertexID; } + void setVertexID(int id) { mVertexID = id; } + + float getMass2() const + { + return calcMass2(mProngs[0].getPID(), mProngs[1].getPID()); + } + + float calcMass2(PID pidPos, PID pidNeg) const + { + return calcMass2(PID::getMass2(pidPos), PID::getMass2(pidNeg)); + } + + float calcMass2(float massPos2, float massNeg2) const; + + protected: + std::array<GIndex, 2> mProngIDs; // global IDs of prongs + std::array<Track, 2> mProngs; // prongs kinematics at vertex + float mCosPA = 0; // cos of pointing angle + float mDCA = 9990; // distance of closest approach of prongs + int mVertexID = -1; // id of parent vertex + + ClassDefNV(V0, 1); +}; + +} // namespace dataformats +} // namespace o2 +#endif diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h index 92dd28cf0b914..44b6ff228ba33 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h @@ -55,6 +55,12 @@ class VtxTrackIndex : public AbstractRef<26, 3, 3> operator auto() const { return AbstractRef<26, 3, 3>(); } + bool isPVContributor() const { return testBit(Contributor); } + void setPVContributor() { setBit(Contributor); } + + bool isAmbiguous() const { return testBit(Ambiguous); } + void setAmbiguous() { setBit(Ambiguous); } + ClassDefNV(VtxTrackIndex, 1); }; diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index eb8eb8550c05a..6cf9150f89429 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -53,4 +53,7 @@ #pragma link C++ class o2::dataformats::DCA + ; +#pragma link C++ class o2::dataformats::V0 + ; +#pragma link C++ class std::vector < o2::dataformats::V0> + ; + #endif diff --git a/DataFormats/Reconstruction/src/V0.cxx b/DataFormats/Reconstruction/src/V0.cxx new file mode 100644 index 0000000000000..0fee7300a103c --- /dev/null +++ b/DataFormats/Reconstruction/src/V0.cxx @@ -0,0 +1,28 @@ +// 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 "ReconstructionDataFormats/V0.h" + +using namespace o2::dataformats; + +V0::V0(const std::array<float, 3>& xyz, const std::array<float, 3>& pxyz, + const o2::track::TrackParCov& trPos, const o2::track::TrackParCov& trNeg, + GIndex trPosID, GIndex trNegID) + : o2::track::TrackParCov{xyz, pxyz, 0, false}, mProngIDs{trPosID, trNegID}, mProngs{trPos, trNeg} +{ +} + +float V0::calcMass2(float massPos2, float massNeg2) const +{ + auto p2 = getP2(); + auto p2pos = mProngs[0].getP2(), p2neg = mProngs[1].getP2(); + auto energy = std::sqrt(massPos2 + p2pos) + std::sqrt(massNeg2 + p2neg); + return energy * energy - p2; +} diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index ce3b5df0d4986..8e75ed40d0cfe 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -18,6 +18,9 @@ o2_add_library(GlobalTrackingWorkflow src/PrimaryVertexWriterSpec.cxx src/PrimaryVertexReaderSpec.cxx src/VertexTrackMatcherSpec.cxx + src/SecondaryVertexingSpec.cxx + src/SecondaryVertexWriterSpec.cxx + src/SecondaryVertexReaderSpec.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTracking O2::ITStracking O2::ITSWorkflow @@ -36,12 +39,22 @@ o2_add_executable(vertexing-workflow COMPONENT_NAME primary SOURCES src/primary-vertexing-workflow.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) - + o2_add_executable(vertex-reader-workflow COMPONENT_NAME primary SOURCES src/primary-vertex-reader-workflow.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) +o2_add_executable(vertex-reader-workflow + COMPONENT_NAME secondary + SOURCES src/secondary-vertex-reader-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) + +o2_add_executable(vertexing-workflow + COMPONENT_NAME secondary + SOURCES src/secondary-vertexing-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) + add_subdirectory(tofworkflow) add_subdirectory(tpcinterpolationworkflow) diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexReaderSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexReaderSpec.h new file mode 100644 index 0000000000000..c7864843e2b47 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexReaderSpec.h @@ -0,0 +1,65 @@ +// 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 SecondaryVertexReaderSpec.h + +#ifndef O2_SECONDARY_VERTEXREADER +#define O2_SECONDARY_VERTEXREADER + +#include "TFile.h" +#include "TTree.h" + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "CommonDataFormat/RangeReference.h" +#include "ReconstructionDataFormats/V0.h" + +namespace o2 +{ +namespace vertexing +{ +// read secondary vertices produces by the o2-secondary-vertexing-workflow + +class SecondaryVertexReader : public o2::framework::Task +{ + using RRef = o2::dataformats::RangeReference<int, int>; + using V0 = o2::dataformats::V0; + + public: + SecondaryVertexReader() = default; + ~SecondaryVertexReader() override = default; + void init(o2::framework::InitContext& ic) final; + void run(o2::framework::ProcessingContext& pc) final; + + protected: + void connectTree(); + + bool mVerbose = false; + + std::vector<V0> mV0s, *mV0sPtr = &mV0s; + std::vector<RRef> mPV2V0Ref, *mPV2V0RefPtr = &mPV2V0Ref; + + std::unique_ptr<TFile> mFile; + std::unique_ptr<TTree> mTree; + std::string mFileName = ""; + std::string mFileNameMatches = ""; + std::string mSVertexTreeName = "o2sim"; + std::string mV0BranchName = "V0s"; + std::string mPVertex2V0RefBranchName = "PV2V0Refs"; +}; + +/// create a processor spec +/// read secondary vertex data from a root file +o2::framework::DataProcessorSpec getSecondaryVertexReaderSpec(); + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexWriterSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexWriterSpec.h new file mode 100644 index 0000000000000..76b3b1d815119 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexWriterSpec.h @@ -0,0 +1,29 @@ +// 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 SecondaryVertexWriterSpec.h + +#ifndef O2_SECONDARY_VERTEX_WRITER +#define O2_SECONDARY_VERTEX_WRITER + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +namespace vertexing +{ + +/// create a processor spec +framework::DataProcessorSpec getSecondaryVertexWriterSpec(); + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexingSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexingSpec.h new file mode 100644 index 0000000000000..e419c3e3b570a --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/SecondaryVertexingSpec.h @@ -0,0 +1,48 @@ +// 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_SECONDARY_VERTEXER_SPEC_H +#define O2_SECONDARY_VERTEXER_SPEC_H + +/// @file SecondaryVertexingSpec.h + +#include "DetectorsVertexing/SVertexer.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "TStopwatch.h" + +namespace o2 +{ +namespace vertexing +{ + +using namespace o2::framework; + +class SecondaryVertexingSpec : public Task +{ + public: + SecondaryVertexingSpec() = default; + ~SecondaryVertexingSpec() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + void endOfStream(EndOfStreamContext& ec) final; + + private: + o2::vertexing::SVertexer mVertexer; + TStopwatch mTimer; +}; + +/// create a processor spec +DataProcessorSpec getSecondaryVertexingSpec(); + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexReaderSpec.cxx new file mode 100644 index 0000000000000..5b4e068369bca --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexReaderSpec.cxx @@ -0,0 +1,81 @@ +// 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 SecondaryVertexReaderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" +#include "GlobalTrackingWorkflow/SecondaryVertexReaderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace vertexing +{ + +void SecondaryVertexReader::init(InitContext& ic) +{ + mFileName = ic.options().get<std::string>("secondary-vertex-infile"); + connectTree(); +} + +void SecondaryVertexReader::run(ProcessingContext& pc) +{ + auto ent = mTree->GetReadEntry() + 1; + assert(ent < mTree->GetEntries()); // this should not happen + mTree->GetEntry(ent); + LOG(INFO) << "Pushing " << mV0sPtr->size() << " V0s at entry " << ent; + + pc.outputs().snapshot(Output{"GLO", "V0s", 0, Lifetime::Timeframe}, mV0s); + pc.outputs().snapshot(Output{"GLO", "PVTX_V0REFS", 0, Lifetime::Timeframe}, mPV2V0Ref); + + if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) { + pc.services().get<ControlService>().endOfStream(); + pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); + } +} + +void SecondaryVertexReader::connectTree() +{ + mTree.reset(nullptr); // in case it was already loaded + mFile.reset(TFile::Open(mFileName.c_str())); + assert(mFile && !mFile->IsZombie()); + mTree.reset((TTree*)mFile->Get(mSVertexTreeName.c_str())); + assert(mTree); + assert(mTree->GetBranch(mV0BranchName.c_str())); + assert(mTree->GetBranch(mPVertex2V0RefBranchName.c_str())); + + mTree->SetBranchAddress(mV0BranchName.c_str(), &mV0sPtr); + mTree->SetBranchAddress(mPVertex2V0RefBranchName.c_str(), &mPV2V0RefPtr); + + LOG(INFO) << "Loaded " << mSVertexTreeName << " tree from " << mFileName << " with " << mTree->GetEntries() << " entries"; +} + +DataProcessorSpec getSecondaryVertexReaderSpec() +{ + std::vector<OutputSpec> outputs; + outputs.emplace_back("GLO", "V0s", 0, Lifetime::Timeframe); + outputs.emplace_back("GLO", "PVTX_V0REFS", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "secondary-vertex-reader", + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask<SecondaryVertexReader>()}, + Options{ + {"secondary-vertex-infile", VariantType::String, "o2_secondary_vertex.root", {"Name of the input secondary vertex file"}}}}; +} + +} // namespace vertexing +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexWriterSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexWriterSpec.cxx new file mode 100644 index 0000000000000..021951c35bc78 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexWriterSpec.cxx @@ -0,0 +1,50 @@ +// 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 SecondaryVertexWriterSpec.cxx + +#include <vector> + +#include "GlobalTrackingWorkflow/SecondaryVertexWriterSpec.h" +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "CommonDataFormat/TimeStamp.h" +#include "CommonDataFormat/RangeReference.h" +#include "ReconstructionDataFormats/V0.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace vertexing +{ +using RRef = o2::dataformats::RangeReference<int, int>; +using V0 = o2::dataformats::V0; + +template <typename T> +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; + +using namespace o2::header; + +DataProcessorSpec getSecondaryVertexWriterSpec() +{ + auto logger = [](std::vector<V0> const& v) { + LOG(INFO) << "SecondaryVertexWriter pulled " << v.size() << " v0s"; + }; + auto inpID = InputSpec{"v0s", "GLO", "V0s", 0}; + auto inpIDRef = InputSpec{"pv2v0ref", "GLO", "PVTX_V0REFS", 0}; + return MakeRootTreeWriterSpec("secondary-vertex-writer", + "o2_secondary_vertex.root", + MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree with Secondary Vertices"}, + BranchDefinition<std::vector<V0>>{inpID, "V0s", logger}, + BranchDefinition<std::vector<RRef>>{inpIDRef, "PV2V0Refs"})(); +} + +} // namespace vertexing +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx new file mode 100644 index 0000000000000..87f51f104549c --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx @@ -0,0 +1,120 @@ +// 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 SecondaryVertexingSpec.cxx + +#include <vector> +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "GlobalTrackingWorkflow/SecondaryVertexingSpec.h" +#include "SimulationDataFormat/MCEventLabel.h" +#include "CommonDataFormat/BunchFilling.h" +#include "SimulationDataFormat/DigitizationContext.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "Framework/ConfigParamRegistry.h" + +using namespace o2::framework; + +using GIndex = o2::dataformats::VtxTrackIndex; +using VRef = o2::dataformats::VtxTrackRef; +using PVertex = const o2::dataformats::PrimaryVertex; +using V0 = o2::dataformats::V0; +using TrackTPCITS = o2::dataformats::TrackTPCITS; +using TrackITS = o2::its::TrackITS; +using TrackTPC = o2::tpc::TrackTPC; +using RRef = o2::dataformats::RangeReference<int, int>; + +namespace o2 +{ +namespace vertexing +{ + +void SecondaryVertexingSpec::init(InitContext& ic) +{ + //-------- init geometry and field --------// + o2::base::GeometryManager::loadGeometry(); + o2::base::Propagator::initFieldFromGRP("o2sim_grp.root"); + // this is a hack to provide Mat.LUT from the local file, in general will be provided by the framework from CCDB + std::string matLUTPath = ic.options().get<std::string>("material-lut-path"); + std::string matLUTFile = o2::base::NameConf::getMatLUTFileName(matLUTPath); + if (o2::base::NameConf::pathExists(matLUTFile)) { + auto* lut = o2::base::MatLayerCylSet::loadFromFile(matLUTFile); + o2::base::Propagator::Instance()->setMatLUT(lut); + LOG(INFO) << "Loaded material LUT from " << matLUTFile; + } else { + LOG(INFO) << "Material LUT " << matLUTFile << " file is absent, only TGeo can be used"; + } + mTimer.Stop(); + mTimer.Reset(); + + mVertexer.init(); +} + +void SecondaryVertexingSpec::run(ProcessingContext& pc) +{ + double timeCPU0 = mTimer.CpuTime(), timeReal0 = mTimer.RealTime(); + mTimer.Start(false); + + const auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("tpcits"); + const auto tracksTPC = pc.inputs().get<gsl::span<o2::tpc::TrackTPC>>("tpc"); + const auto tracksITS = pc.inputs().get<gsl::span<o2::its::TrackITS>>("its"); + + const auto pvertices = pc.inputs().get<gsl::span<o2::dataformats::PrimaryVertex>>("pvtx"); + const auto pvtxTracks = pc.inputs().get<gsl::span<o2::dataformats::VtxTrackIndex>>("pvtx_cont"); + const auto pvtxTrackRefs = pc.inputs().get<gsl::span<o2::dataformats::VtxTrackRef>>("pvtx_tref"); + + std::vector<V0> v0s; + std::vector<RRef> pv2v0ref; + + mVertexer.process(pvertices, pvtxTracks, pvtxTrackRefs, + tracksITSTPC, tracksITS, tracksTPC, + v0s, pv2v0ref); + + pc.outputs().snapshot(Output{"GLO", "V0s", 0, Lifetime::Timeframe}, v0s); + pc.outputs().snapshot(Output{"GLO", "PVTX_V0REFS", 0, Lifetime::Timeframe}, pv2v0ref); + + mTimer.Stop(); + LOG(INFO) << "Found " << v0s.size() << " V0s, timing: CPU: " + << mTimer.CpuTime() - timeCPU0 << " Real: " << mTimer.RealTime() - timeReal0 << " s"; +} + +void SecondaryVertexingSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "Secondary vertexing total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getSecondaryVertexingSpec() +{ + std::vector<InputSpec> inputs; + std::vector<OutputSpec> outputs; + + inputs.emplace_back("pvtx", "GLO", "PVTX", 0, Lifetime::Timeframe); // prim.vertices + inputs.emplace_back("pvtx_cont", "GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe); // global ids of associated tracks + inputs.emplace_back("pvtx_tref", "GLO", "PVTX_TRMTCREFS", 0, Lifetime::Timeframe); // vertex - trackID refs + // + inputs.emplace_back("tpcits", "GLO", "TPCITS", 0, Lifetime::Timeframe); // matched ITS-TPC tracks + inputs.emplace_back("its", "ITS", "TRACKS", 0, Lifetime::Timeframe); // standalone ITS tracks + inputs.emplace_back("tpc", "TPC", "TRACKS", 0, Lifetime::Timeframe); // standalone TPC tracks + // + outputs.emplace_back("GLO", "V0s", 0, Lifetime::Timeframe); // found V0s + outputs.emplace_back("GLO", "PVTX_V0REFS", 0, Lifetime::Timeframe); // prim.vertex -> V0s refs + + return DataProcessorSpec{ + "secondary-vertexing", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<SecondaryVertexingSpec>()}, + Options{{"material-lut-path", VariantType::String, "", {"Path of the material LUT file"}}}}; +} + +} // namespace vertexing +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/secondary-vertex-reader-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/secondary-vertex-reader-workflow.cxx new file mode 100644 index 0000000000000..433d095889277 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/secondary-vertex-reader-workflow.cxx @@ -0,0 +1,42 @@ +// 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 "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/ConfigParamSpec.h" +#include "GlobalTrackingWorkflow/SecondaryVertexReaderSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<o2::framework::ConfigParamSpec> options{ + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); + + WorkflowSpec specs; + specs.emplace_back(o2::vertexing::getSecondaryVertexReaderSpec()); + return std::move(specs); +} diff --git a/Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.cxx new file mode 100644 index 0000000000000..a81eaf9dd89c3 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.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 "GlobalTrackingWorkflow/SecondaryVertexingSpec.h" +#include "GlobalTrackingWorkflow/SecondaryVertexWriterSpec.h" +#include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" +#include "GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h" +#include "ITSWorkflow/TrackReaderSpec.h" +#include "TPCWorkflow/TrackReaderSpec.h" + +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<o2::framework::ConfigParamSpec> options{ + {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, + {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); + // write the configuration used for the workflow + o2::conf::ConfigurableParam::writeINI("o2secondary-vertexing-workflow_configuration.ini"); + + auto disableRootInp = configcontext.options().get<bool>("disable-root-input"); + auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); + + WorkflowSpec specs; + if (!disableRootInp) { + specs.emplace_back(o2::vertexing::getPrimaryVertexReaderSpec(false)); + specs.emplace_back(o2::globaltracking::getTrackTPCITSReaderSpec(false)); + specs.emplace_back(o2::its::getITSTrackReaderSpec(false)); + specs.emplace_back(o2::tpc::getTPCTrackReaderSpec(false)); + } + specs.emplace_back(o2::vertexing::getSecondaryVertexingSpec()); + if (!disableRootOut) { + specs.emplace_back(o2::vertexing::getSecondaryVertexWriterSpec()); + } + return std::move(specs); +} diff --git a/Detectors/Vertexing/CMakeLists.txt b/Detectors/Vertexing/CMakeLists.txt index 3cb55ae1654b8..b36d310a214f4 100644 --- a/Detectors/Vertexing/CMakeLists.txt +++ b/Detectors/Vertexing/CMakeLists.txt @@ -14,6 +14,9 @@ o2_add_library(DetectorsVertexing src/PVertexerHelpers.cxx src/PVertexerParams.cxx src/VertexTrackMatcher.cxx + src/SVertexer.cxx + src/SVertexerParams.cxx + src/V0Hypothesis.cxx PUBLIC_LINK_LIBRARIES ROOT::Core O2::CommonUtils O2::ReconstructionDataFormats @@ -29,8 +32,12 @@ o2_target_root_dictionary(DetectorsVertexing HEADERS include/DetectorsVertexing/HelixHelper.h include/DetectorsVertexing/PVertexer.h include/DetectorsVertexing/PVertexerHelpers.h + include/DetectorsVertexing/PVertexerParams.h include/DetectorsVertexing/VertexTrackMatcher.h - include/DetectorsVertexing/DCAFitterN.h) + include/DetectorsVertexing/DCAFitterN.h + include/DetectorsVertexing/SVertexer.h + include/DetectorsVertexing/SVertexerParams.h + include/DetectorsVertexing/V0Hypothesis.h) o2_add_test( DCAFitterN diff --git a/Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h new file mode 100644 index 0000000000000..db00b27d0c735 --- /dev/null +++ b/Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h @@ -0,0 +1,120 @@ +// 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 SVertexer.h +/// \brief Secondary vertex finder +/// \author ruben.shahoyan@cern.ch +#ifndef O2_S_VERTEXER_H +#define O2_S_VERTEXER_H + +#include "gsl/span" +#include "ReconstructionDataFormats/PrimaryVertex.h" +#include "ReconstructionDataFormats/V0.h" +#include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/VtxTrackRef.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "DataFormatsITS/TrackITS.h" +#include "CommonDataFormat/RangeReference.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "DetectorsVertexing/SVertexerParams.h" +#include "DetectorsVertexing/V0Hypothesis.h" + +namespace o2 +{ +namespace vertexing +{ + +namespace o2d = o2::dataformats; + +class SVertexer +{ + public: + using GIndex = o2::dataformats::VtxTrackIndex; + using VRef = o2::dataformats::VtxTrackRef; + using PVertex = const o2::dataformats::PrimaryVertex; + using V0 = o2::dataformats::V0; + using TrackTPCITS = o2::dataformats::TrackTPCITS; + using TrackITS = o2::its::TrackITS; + using TrackTPC = o2::tpc::TrackTPC; + using RRef = o2::dataformats::RangeReference<int, int>; + + // struct to access tracks and extra info from different sources + struct TrackAccessor { + static constexpr std::array<size_t, GIndex::NSources> sizes{sizeof(TrackTPCITS), sizeof(TrackITS), sizeof(TrackTPC)}; + std::array<const char*, GIndex::NSources> startOfSource{}; + std::array<std::vector<char>, GIndex::NSources> charges; + + TrackAccessor(const gsl::span<const TrackTPCITS>& tpcits, const gsl::span<const TrackITS>& its, const gsl::span<const TrackTPC>& tpc) + { + if (tpcits.size()) { + startOfSource[GIndex::TPCITS] = reinterpret_cast<const char*>(tpcits.data()); + auto& ch = charges[GIndex::TPCITS]; + ch.resize(tpcits.size()); + for (uint32_t ic = 0; ic < tpcits.size(); ic++) { + ch[ic] = tpcits[ic].getCharge(); + } + } + if (its.size()) { + startOfSource[GIndex::ITS] = reinterpret_cast<const char*>(its.data()); + auto& ch = charges[GIndex::ITS]; + ch.resize(its.size()); + for (uint32_t ic = 0; ic < its.size(); ic++) { + ch[ic] = its[ic].getCharge(); + } + } + if (tpc.size()) { + startOfSource[GIndex::TPC] = reinterpret_cast<const char*>(tpc.data()); + auto& ch = charges[GIndex::TPC]; + ch.resize(tpc.size()); + for (uint32_t ic = 0; ic < tpc.size(); ic++) { + ch[ic] = tpc[ic].getCharge(); + } + } + } + char getCharge(GIndex id) const { return getCharge(id.getSource(), id.getIndex()); } + char getCharge(int src, int idx) const { return charges[src][idx]; } + const o2::track::TrackParCov& getTrack(GIndex id) const { return getTrack(id.getSource(), id.getIndex()); } + const o2::track::TrackParCov& getTrack(int src, int idx) const { return *reinterpret_cast<const o2::track::TrackParCov*>(startOfSource[src] + sizes[src] * idx); } + }; + + void init(); + void process(const gsl::span<const PVertex>& vertices, // primary vertices + const gsl::span<const GIndex>& trackIndex, // Global ID's for associated tracks + const gsl::span<const VRef>& vtxRefs, // references from vertex to these track IDs + const gsl::span<const TrackTPCITS>& tpcits, // global tracks + const gsl::span<const TrackITS>& its, // ITS tracks + const gsl::span<const TrackTPC>& tpc, // TPC tracks + std::vector<V0>& v0s, // found V0s + std::vector<RRef>& vtx2V0refs // references from PVertex to V0 + ); + + auto& getMeanVertex() const { return mMeanVertex; } + void setMeanVertex(const o2d::VertexBase& v) { mMeanVertex = v; } + + private: + uint64_t getPairIdx(GIndex id1, GIndex id2) const + { + return (uint64_t(id1) << 32) | id2; + } + o2d::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; + const SVertexerParams* mSVParams = nullptr; + std::array<V0Hypothesis, SVertexerParams::NPIDV0> mV0Hyps; + DCAFitterN<2> mFitter2Prong; + + float mMinR2ToMeanVertex = 0; + float mMaxDCAXY2ToMeanVertex = 0; + float mMinCosPointingAngle = 0; +}; + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h new file mode 100644 index 0000000000000..96ac7cfde2f14 --- /dev/null +++ b/Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h @@ -0,0 +1,70 @@ +// 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 SVertexerParams.h +/// \brief Configurable params for secondary vertexer +/// \author ruben.shahoyan@cern.ch + +#ifndef ALICEO2_SVERTEXER_PARAMS_H +#define ALICEO2_SVERTEXER_PARAMS_H + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace vertexing +{ + +// These are configurable params for Primary Vertexer +struct SVertexerParams : public o2::conf::ConfigurableParamHelper<SVertexerParams> { + + enum PIDV0 { Photon, + K0, + Lambda, + AntiLambda, + HyperTriton, + AntiHyperTriton, + NPIDV0 }; + enum PIDParams { SigmaMV0, + NSigmaMV0, + Margin, + CPt, + NPIDParams }; + // parameters + float maxChi2 = 2.; ///< max dca from prongs to vertex + float minParamChange = 1e-3; ///< stop when tracks X-params being minimized change by less that this value + float minRelChi2Change = 0.9; ///< stop when chi2 changes by less than this value + float maxDZIni = 5.; ///< don't consider as a seed (circles intersection) if Z distance exceeds this + float maxRIni = 150; ///< don't consider as a seed (circles intersection) if its R exceeds this + + bool useAbsDCA = true; ///< use abs dca minimization + // + float minRfromMeanVertex = 0.5; ///< min radial distance of V0 from beam line (mean vertex) + float maxDCAXYfromMeanVertex = 0.2; ///< min DCA of V0 from beam line (mean vertex) + float minCosPointingAngle = 0.8; + // cuts on different PID params + float pidCuts[NPIDV0][NPIDParams] = { + // + {0.001, 20, 0.6, 0.}, // Photon + {0.003, 20, 0.07, 0.5}, // K0 + {0.001, 20, 0.07, 0.5}, // Lambda + {0.001, 20, 0.07, 0.5}, // AntiLambda + {0.0025, 14, 0.07, 0.5}, // HyperTriton + {0.0025, 14, 0.07, 0.5} // AntiHyperTriton + }; + + O2ParamDef(SVertexerParams, "svertexer"); +}; + +} // namespace vertexing +} // end namespace o2 + +#endif diff --git a/Detectors/Vertexing/include/DetectorsVertexing/V0Hypothesis.h b/Detectors/Vertexing/include/DetectorsVertexing/V0Hypothesis.h new file mode 100644 index 0000000000000..8a95d9d6a6d9e --- /dev/null +++ b/Detectors/Vertexing/include/DetectorsVertexing/V0Hypothesis.h @@ -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. + +/// \file V0Hypothesis.h +/// \brief V0 hypothesis checker +/// \author ruben.shahoyan@cern.ch + +#ifndef ALICEO2_V0_HYPOTHESIS_H +#define ALICEO2_V0_HYPOTHESIS_H + +#include "ReconstructionDataFormats/PID.h" +#include "DetectorsVertexing/SVertexerParams.h" + +namespace o2 +{ +namespace vertexing +{ + +class V0Hypothesis +{ + + public: + using PID = o2::track::PID; + + void set(PID v0, PID ppos, PID pneg, float sig, float nSig, float margin, float cpt, float bz = 0.f); + void set(PID v0, PID ppos, PID pneg, const float pars[SVertexerParams::NPIDParams], float bz = 0.f); + + float getMassV0Hyp() const { return PID::getMass(mPIDV0); } + float getMassPosProng() const { return PID::getMass(mPIDPosProng); } + float getMassNegProng() const { return PID::getMass(mPIDNegProng); } + + float calcMass2(float p2Pos, float p2Neg, float p2V0) const + { + // calculate v0 mass from squared momentum of its prongs and total momentum + float ePos = std::sqrt(p2Pos + getMass2PosProng()), eNeg = std::sqrt(p2Neg + getMass2NegProng()), eV0 = ePos + eNeg; + return eV0 * eV0 - p2V0; + } + + float calcMass(float p2Pos, float p2Neg, float p2V0) const { return std::sqrt(calcMass2(p2Pos, p2Neg, p2V0)); } + + bool check(float p2Pos, float p2Neg, float p2V0, float ptV0) const + { // check if given mass and pt is matching to hypothesis + return check(calcMass(p2Pos, p2Neg, p2V0), ptV0); + } + + bool check(float mass, float pt) const + { // check if given mass and pt is matching to hypothesis + return std::abs(mass - getMassV0Hyp()) < getMargin(pt); + } + + float getSigma(float pt) const { return 1.f + mCPt * pt; } + float getMargin(float pt) const { return mNSigma * getSigma(pt) + mMargin; } + + private: + float getMass2PosProng() const { return PID::getMass2(mPIDPosProng); } + float getMass2NegProng() const { return PID::getMass2(mPIDNegProng); } + + PID mPIDV0 = PID::K0; + PID mPIDPosProng = PID::Pion; + PID mPIDNegProng = PID::Pion; + + float mNSigma = 0.; // number of sigmas of mass res + float mSigma = 0.; // sigma of mass res at 0 pt + float mMargin = 0.; // additive safety margin in mass cut + float mCPt = 0.; // pT dependence of mass resolution parameterized as mSigma*(1+mC1*pt); + + ClassDefNV(V0Hypothesis, 1); +}; + +} // namespace vertexing +} // namespace o2 + +#endif diff --git a/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h b/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h index 7c50e9ebd0e69..14703c3d763b6 100644 --- a/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h +++ b/Detectors/Vertexing/src/DetectorsVertexingLinkDef.h @@ -24,6 +24,10 @@ #pragma link C++ class o2::vertexing::VertexTrackMatcher + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::vertexing::PVertexerParams> + ; +#pragma link C++ class o2::vertexing::SVertexer + ; +#pragma link C++ class o2::vertexing::SVertexerParams + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::vertexing::SVertexerParams> + ; + #pragma link C++ class o2::track::TrackAuxPar + ; #pragma link C++ class o2::track::CrossInfo + ; diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx new file mode 100644 index 0000000000000..cd659acee7e81 --- /dev/null +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -0,0 +1,235 @@ +// 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 SVertexer.cxx +/// \brief Secondary vertex finder +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/SVertexer.h" +#include "DetectorsBase/Propagator.h" + +using namespace o2::vertexing; + +using PID = o2::track::PID; + +void SVertexer::init() +{ + mSVParams = &SVertexerParams::Instance(); + + mFitter2Prong.setUseAbsDCA(mSVParams->useAbsDCA); + mFitter2Prong.setPropagateToPCA(false); + mFitter2Prong.setMaxR(mSVParams->maxRIni); + mFitter2Prong.setMinParamChange(mSVParams->minParamChange); + mFitter2Prong.setMinRelChi2Change(mSVParams->minRelChi2Change); + mFitter2Prong.setMaxDZIni(mSVParams->maxDZIni); + mFitter2Prong.setMaxChi2(mSVParams->maxChi2); + + // precalculated selection cuts + mMinR2ToMeanVertex = mSVParams->minRfromMeanVertex * mSVParams->minRfromMeanVertex; + mMaxDCAXY2ToMeanVertex = mSVParams->maxDCAXYfromMeanVertex * mSVParams->maxDCAXYfromMeanVertex; + mMinCosPointingAngle = mSVParams->minCosPointingAngle; + // + auto bz = o2::base::Propagator::Instance()->getNominalBz(); + mFitter2Prong.setBz(bz); + // + mV0Hyps[SVertexerParams::Photon].set(PID::Photon, PID::Electron, PID::Electron, mSVParams->pidCuts[SVertexerParams::Photon], bz); + mV0Hyps[SVertexerParams::K0].set(PID::K0, PID::Pion, PID::Pion, mSVParams->pidCuts[SVertexerParams::K0], bz); + mV0Hyps[SVertexerParams::Lambda].set(PID::Lambda, PID::Proton, PID::Pion, mSVParams->pidCuts[SVertexerParams::Lambda], bz); + mV0Hyps[SVertexerParams::AntiLambda].set(PID::Lambda, PID::Pion, PID::Proton, mSVParams->pidCuts[SVertexerParams::AntiLambda], bz); + mV0Hyps[SVertexerParams::HyperTriton].set(PID::HyperTriton, PID::Helium3, PID::Pion, mSVParams->pidCuts[SVertexerParams::HyperTriton], bz); + mV0Hyps[SVertexerParams::AntiHyperTriton].set(PID::HyperTriton, PID::Pion, PID::Helium3, mSVParams->pidCuts[SVertexerParams::AntiHyperTriton], bz); + // +} + +void SVertexer::process(const gsl::span<const PVertex>& vertices, // primary vertices + const gsl::span<const GIndex>& trackIndex, // Global ID's for associated tracks + const gsl::span<const VRef>& vtxRefs, // references from vertex to these track IDs + const gsl::span<const TrackTPCITS>& tpcits, // global tracks + const gsl::span<const TrackITS>& its, // ITS tracks + const gsl::span<const TrackTPC>& tpc, // TPC tracks + std::vector<V0>& v0s, // found V0s + std::vector<RRef>& vtx2V0refs // references from PVertex to V0 +) +{ + std::unordered_map<uint64_t, int> cache; // cache for tested combinations, the value >0 will give the entry of prevalidated V0 in the v0sTmp + std::vector<V0> v0sTmp(1); // 1st one is dummy! + std::vector<int> v0sIdx; // id's in v0sTmp used attached to p.vertices + std::vector<RRef> pv2v0sRefs; // p.vertex to v0 index references + + TrackAccessor tracksPool(tpcits, its, tpc); + + auto rejectTrack = [&tracksPool](GIndex id, char wantCharge) { + if (id.isPVContributor()) { + return true; + } + auto s = id.getSource(); + return (s != GIndex::TPCITS && s != GIndex::ITS) || tracksPool.getCharge(id) != wantCharge; + }; + + int nv = vertices.size(); + size_t countTot = 0, countTotUnique = 0; + for (int iv = 0; iv < nv; iv++) { + // + // select vertices + auto& pvrefs = pv2v0sRefs.emplace_back(v0sIdx.size(), 0); + const auto& pv = vertices[iv]; + if (pv.getNContributors() < 5) { + continue; + } + // + const auto& vtref = vtxRefs[iv]; + //LOG(INFO) << "P.Vertex " << iv << pv; + //LOG(INFO) << "P.V. -> tracks " << vtref; + // + int first = vtref.getFirstEntry(); + int last = first + vtref.getEntries(); + size_t count = 0, countUnique = 0; + for (int ipos = first; ipos < last; ipos++) { + auto idpos = trackIndex[ipos]; + if (rejectTrack(idpos, 1)) { // skip at the moment TPC only tracks + continue; + } + bool ambiguousPos = idpos.isAmbiguous(); // is this track compatible also with other vertex? + const auto& trPos = tracksPool.getTrack(idpos); + + for (int ineg = first; ineg < last; ineg++) { + auto idneg = trackIndex[ineg]; + if (rejectTrack(idneg, -1)) { // skip at the moment TPC only tracks + continue; + } + count++; + bool accept = false, newPair = true, ambiguousV0 = ambiguousPos && idneg.isAmbiguous(); // V0 is ambiguous if both tracks are compatible with other vertices + uint64_t idPosNeg = getPairIdx(idpos, idneg); + int* resPair = nullptr; + if (ambiguousV0) { // check if it was already processed + resPair = &cache[idPosNeg]; + if ((*resPair) < 0) { // was already checked and rejected + continue; + } else if ((*resPair) == 0) { // was not checked yet + countUnique++; + (*resPair) = -1; // this is rejection flag + } else { + newPair = false; + } + } + if (newPair) { + auto trNeg = tracksPool.getTrack(idneg); + // LOG(INFO) << "0: " << idpos << " " << tr0.o2::track::TrackPar::asString(); + // LOG(INFO) << "1: " << idneg << " " << tr1.o2::track::TrackPar::asString(); + int nCand = mFitter2Prong.process(trPos, trNeg); + if (nCand == 0) { // discard this pair + continue; + } + const auto& v0pos = mFitter2Prong.getPCACandidate(); + // check closeness to the beam-line + auto r2 = (v0pos[0] - mMeanVertex.getX()) * (v0pos[0] - mMeanVertex.getX()) + (v0pos[1] - mMeanVertex.getY()) * (v0pos[1] - mMeanVertex.getY()); + if (r2 < mMinR2ToMeanVertex) { + continue; + } + if (!mFitter2Prong.isPropagateTracksToVertexDone() && !mFitter2Prong.propagateTracksToVertex()) { + continue; + } + auto& trPosProp = mFitter2Prong.getTrack(0); + auto& trNegProp = mFitter2Prong.getTrack(1); + std::array<float, 3> pPos, pNeg; + trPosProp.getPxPyPzGlo(pPos); + trNegProp.getPxPyPzGlo(pNeg); + // estimate DCA of neutral V0 track to beamline: straight line with parametric equation + // x = X0 + pV0[0]*t, y = Y0 + pV0[1]*t reaches DCA to beamline (Xv, Yv) at + // t = -[ (x0-Xv)*pV0[0] + (y0-Yv)*pV0[1]) ] / ( pT(pV0)^2 ) + // Similar equation for 3D distance involving pV0[2] + std::array<float, 3> pV0 = {pPos[0] + pNeg[0], pPos[1] + pNeg[1], pPos[2] + pNeg[2]}; + float dx = v0pos[0] - mMeanVertex.getX(), dy = v0pos[1] - mMeanVertex.getY(); + float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXY = dx * pV0[0] + dy * pV0[1], tDCAXY = -prodXY / pt2V0; + float dcaX = dx + pV0[0] * tDCAXY, dcaY = dy + pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; + if (dca2 > mMaxDCAXY2ToMeanVertex) { + continue; + } + float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); + + // apply mass selections + float p2Pos = pPos[0] * pPos[0] + pPos[1] * pPos[1] + pPos[2] * pPos[2], p2Neg = pNeg[0] * pNeg[0] + pNeg[1] * pNeg[1] + pNeg[2] * pNeg[2]; + bool goodHyp = false; + for (int ipid = 0; ipid < SVertexerParams::NPIDV0; ipid++) { + if (mV0Hyps[ipid].check(p2Pos, p2Neg, p2V0, ptV0)) { + goodHyp = true; + break; + } + } + if (!goodHyp) { + continue; + } + // check cos of pointing angle + float dz = v0pos[2] - mMeanVertex.getZ(), cosPointingAngle = (prodXY + dz * pV0[2]) / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + if (cosPointingAngle < mMinCosPointingAngle) { + if (ambiguousV0) { + continue; // no need to check this pair wrt other vertices + } + cosPointingAngle = mMinCosPointingAngle - 1e-6; + } else { // cuts passed, register v0 + accept = true; + } + // preliminary checks passed, cache V0 and proceed to specific vertex check + int szV0tmp = v0sTmp.size(); + if (resPair) { + *resPair = szV0tmp; // index of V0 to be created + } + // LOG(INFO) << "Adding new V0 " << szV0tmp; + + std::array<float, 3> v0posF = {float(v0pos[0]), float(v0pos[1]), float(v0pos[2])}; + auto& v0 = v0sTmp.emplace_back(v0posF, pV0, trPosProp, trNegProp, idpos, idneg); + if (accept) { + v0.setCosPA(cosPointingAngle); + v0.setDCA(mFitter2Prong.getChi2AtPCACandidate()); + v0.setVertexID(iv); + v0sIdx.push_back(szV0tmp); + pvrefs.changeEntriesBy(1); + } + } else { // check if already created V0 is good for this vertex + // LOG(INFO) << "Rechecking new V0 " << *resPair; + auto& v0 = v0sTmp[*resPair]; + std::array<float, 3> posV0, momV0; + v0.getXYZGlo(posV0); + v0.getPxPyPzGlo(momV0); + float cosPointingAngle = posV0[0] * momV0[0] + posV0[1] * momV0[1] + posV0[2] * momV0[2]; + cosPointingAngle /= std::sqrt((posV0[0] * posV0[0] + posV0[1] * posV0[1] + posV0[2] * posV0[2]) * (momV0[0] * momV0[0] + momV0[1] * momV0[1] + momV0[2] * momV0[2])); + if (cosPointingAngle > v0.getCosPA()) { // reassign + v0.setCosPA(cosPointingAngle); + v0.setVertexID(iv); + pvrefs.changeEntriesBy(1); + } + } + } + } + countTot += count; + countTotUnique += countUnique; + // LOG(INFO) << "Tried " << count << " combs with " << countUnique << " uniques"; + } + // finalize V0s + for (int iv = 0; iv < nv; iv++) { + const auto& pvtx = vertices[iv]; + const auto& pvrefsTmp = pv2v0sRefs[iv]; + auto& pvrefsFin = vtx2V0refs.emplace_back(v0s.size(), 0); + int from = pvrefsTmp.getFirstEntry(), to = from + pvrefsTmp.getEntries(), nAdded = 0; + for (int iv0 = from; iv0 < to; iv0++) { + const auto& v0tmp = v0sTmp[v0sIdx[iv0]]; + if (v0tmp.getVertexID() != iv) { // this v0 - p.vertex association was reassigned + continue; + } + v0s.push_back(v0tmp); + nAdded++; + } + pvrefsFin.setEntries(nAdded); + LOG(INFO) << nAdded << " V0s added for vertex " << iv << " with " << pvtx.getNContributors() << " tracks, out of initial " << pvrefsTmp.getEntries(); + pvtx.print(); + } + + LOG(INFO) << "Tried " << countTot << " combs in total " << countTotUnique << " uniques"; +} diff --git a/Detectors/Vertexing/src/SVertexerParams.cxx b/Detectors/Vertexing/src/SVertexerParams.cxx new file mode 100644 index 0000000000000..802910be6c97b --- /dev/null +++ b/Detectors/Vertexing/src/SVertexerParams.cxx @@ -0,0 +1,17 @@ +// 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 PVertexerParams.cxx +/// \brief Configurable params for secondary vertexer +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/SVertexerParams.h" + +O2ParamImpl(o2::vertexing::SVertexerParams); diff --git a/Detectors/Vertexing/src/V0Hypothesis.cxx b/Detectors/Vertexing/src/V0Hypothesis.cxx new file mode 100644 index 0000000000000..7ccd60ea1d18f --- /dev/null +++ b/Detectors/Vertexing/src/V0Hypothesis.cxx @@ -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 V0Hypothesis.cxx +/// \brief V0 hypothesis checker +/// \author ruben.shahoyan@cern.ch + +#include "DetectorsVertexing/V0Hypothesis.h" + +using namespace o2::vertexing; + +void V0Hypothesis::set(PID v0, PID ppos, PID pneg, float sig, float nSig, float margin, float cpt, float bz) +{ + mPIDV0 = v0; + mPIDPosProng = ppos; + mPIDNegProng = pneg; + mSigma = sig; + mNSigma = nSig; + mMargin = margin; + mCPt = std::abs(bz) > 1e-3 ? cpt * 5.0066791 / bz : 0.; // assume that pT dependent sigma is linear with B +} + +void V0Hypothesis::set(PID v0, PID ppos, PID pneg, const float pars[SVertexerParams::NPIDParams], float bz) +{ + set(v0, ppos, pneg, pars[SVertexerParams::SigmaMV0], pars[SVertexerParams::NSigmaMV0], + pars[SVertexerParams::Margin], pars[SVertexerParams::CPt], bz); +} From 5b831e25c8b460847594f5492682e12897d23c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Sat, 24 Oct 2020 14:45:39 +0200 Subject: [PATCH 1087/1751] =?UTF-8?q?PWGHF:=20Add=20more=20D=C2=B1=20prese?= =?UTF-8?q?lection=20cuts.=20(#4667)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add cuts on cosine of pointing angle, decay length. * Rename cut variables. * Add CPA histograms in D0 and D± tasks. * PWGHF: Use post-vertexing momenta in the CPA cut. --- .../include/Analysis/HFSecondaryVertex.h | 2 +- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 6 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 6 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 320 ++++++++++-------- Analysis/Tasks/PWGHF/taskD0.cxx | 36 +- Analysis/Tasks/PWGHF/taskDPlus.cxx | 38 ++- 6 files changed, 229 insertions(+), 179 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 67a9303d370cc..c5aec251b588a 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -31,7 +31,7 @@ DECLARE_SOA_COLUMN(DCAPrim0, dcaPrim0, float); DECLARE_SOA_COLUMN(DCAPrim1, dcaPrim1, float); } // namespace hf_seltrack -DECLARE_SOA_TABLE(HFSelTrack, "AOD", "SELTRACK", +DECLARE_SOA_TABLE(HFSelTrack, "AOD", "HFSELTRACK", hf_seltrack::IsSel2Prong, hf_seltrack::IsSel3Prong, hf_seltrack::DCAPrim0, diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 46cb0a13a1063..c1e621cbf1602 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -36,9 +36,9 @@ struct HFCandidateCreator2Prong { Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - OutputObj<TH1F> hmass2{TH1F("hmass2", "2-track inv mass", 500, 0., 5.)}; - OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.e-4)}; - OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "XX element of SV cov. matrix", 100, 0., 0.2)}; + OutputObj<TH1F> hmass2{TH1F("hmass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; + OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; + OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", 100, 0., 0.2)}; double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index a00ae4c8f2bf9..8eda2e2d7df11 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -36,9 +36,9 @@ struct HFCandidateCreator3Prong { Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable<bool> b_dovalplots{"b_dovalplots", true, "do validation plots"}; - OutputObj<TH1F> hmass3{TH1F("hmass3", "3-track inv mass", 500, 1.6, 2.1)}; - OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "XX element of PV cov. matrix", 100, 0., 1.e-4)}; - OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "XX element of SV cov. matrix", 100, 0., 0.2)}; + OutputObj<TH1F> hmass3{TH1F("hmass3", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 2.1)}; + OutputObj<TH1F> hCovPVXX{TH1F("hCovPVXX", "3-prong candidates;XX element of cov. matrix of prim. vtx position (cm^{2});entries", 100, 0., 1.e-4)}; + OutputObj<TH1F> hCovSVXX{TH1F("hCovSVXX", "3-prong candidates;XX element of cov. matrix of sec. vtx position (cm^{2});entries", 100, 0., 0.2)}; double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 7f2e03fbbdad2..7e4ce0b9eafbe 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -42,15 +42,15 @@ struct SelectTracks { Configurable<double> dcatoprimxymin_3prong{"dcatoprimxymin_3prong", 0., "min. DCAXY to prim. vtx."}; Configurable<double> etamax_3prong{"etamax_3prong", 999., "max. pseudorapidity"}; - OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "#it{p}_{T}^{track} (GeV/#it{c})", 100, 0., 10.)}; + OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "all tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", 100, 0., 10.)}; // 2-prong histograms - OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "#it{p}_{T}^{track} (GeV/#it{c})", 100, 0., 10.)}; - OutputObj<TH1F> hdcatoprimxy_cuts_2prong{TH1F("hdcatoprimxy_cuts_2prong", "DCAXY to prim. vtx. (cm)", 100, -1., 1.)}; - OutputObj<TH1F> heta_cuts_2prong{TH1F("heta_cuts_2prong", "#it{#eta}", 100, -1., 1.)}; + OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "tracks selected for 2-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hdcatoprimxy_cuts_2prong{TH1F("hdcatoprimxy_cuts_2prong", "tracks selected for 2-prong vertexing;DCAxy to prim. vtx. (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> heta_cuts_2prong{TH1F("heta_cuts_2prong", "tracks selected for 2-prong vertexing;#it{#eta};entries", 100, -1., 1.)}; // 3-prong histograms - OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "#it{p}_{T}^{track} (GeV/#it{c})", 100, 0., 10.)}; - OutputObj<TH1F> hdcatoprimxy_cuts_3prong{TH1F("hdcatoprimxy_cuts_3prong", "DCAXY to prim. vtx. (cm)", 100, -1., 1.)}; - OutputObj<TH1F> heta_cuts_3prong{TH1F("heta_cuts_3prong", "#it{#eta}", 100, -1., 1.)}; + OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hdcatoprimxy_cuts_3prong{TH1F("hdcatoprimxy_cuts_3prong", "tracks selected for 3-prong vertexing;DCAxy to prim. vtx. (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> heta_cuts_3prong{TH1F("heta_cuts_3prong", "tracks selected for 3-prong vertexing;#it{#eta};entries", 100, -1., 1.)}; void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) @@ -114,10 +114,12 @@ struct SelectTracks { if (status_2prong == 1) { hpt_cuts_2prong->Fill(track.pt()); hdcatoprimxy_cuts_2prong->Fill(dca[0]); + heta_cuts_2prong->Fill(track.eta()); } if (status_3prong == 1) { hpt_cuts_3prong->Fill(track.pt()); hdcatoprimxy_cuts_3prong->Fill(dca[0]); + heta_cuts_3prong->Fill(track.eta()); } } @@ -144,26 +146,28 @@ struct HFTrackIndexSkimsCreator { Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations if chi2/chi2old > this"}; // 2-prong cuts - Configurable<double> ptmincand_2prong{"ptmincand_2prong", -1., "ptmin 2prong candidate"}; - Configurable<double> cutCPAMin{"cutCPAMin", -2., "min. cosine of pointing angle"}; - Configurable<double> cutInvMassD0Min{"cutInvMassD0Min", -1., "min. D0 candidate invariant mass"}; - Configurable<double> cutInvMassD0Max{"cutInvMassD0Max", -1., "max. D0 candidate invariant mass"}; - Configurable<double> cutImpParProductMax{"cutImpParProductMax", 100., "max. product of imp. par. of D0 candidate prongs"}; + Configurable<double> cut2ProngPtCandMin{"cut2ProngPtCandMin", -1., "min. pT of the 2-prong candidate"}; + Configurable<double> cut2ProngInvMassD0Min{"cut2ProngInvMassD0Min", -1., "min. D0 candidate invariant mass"}; + Configurable<double> cut2ProngInvMassD0Max{"cut2ProngInvMassD0Max", -1., "max. D0 candidate invariant mass"}; + Configurable<double> cut2ProngCPAMin{"cut2ProngCPAMin", -2., "min. cosine of pointing angle"}; + Configurable<double> cut2ProngImpParProductMax{"cut2ProngImpParProductMax", 100., "max. product of imp. par. of D0 candidate prongs"}; // 3-prong cuts - Configurable<double> ptmincand_3prong{"ptmincand_3prong", -1., "ptmin 3prong candidate"}; - Configurable<double> d_minmassDp{"d_minmassDp", 1.5, "min. D+ candidate invariant mass"}; - Configurable<double> d_maxmassDp{"d_maxmassDp", 2.1, "min. D+ candidate invariant mass"}; + Configurable<double> cut3ProngPtCandMin{"cut3ProngPtCandMin", -1., "min. pT of the 3-prong candidate"}; + Configurable<double> cut3ProngInvMassDPlusMin{"cut3ProngInvMassDPlusMin", 1.5, "min. D+ candidate invariant mass"}; + Configurable<double> cut3ProngInvMassDPlusMax{"cut3ProngInvMassDPlusMax", 2.1, "min. D+ candidate invariant mass"}; + Configurable<double> cut3ProngCPAMin{"cut3ProngCPAMin", -2., "min. cosine of pointing angle"}; + Configurable<double> cut3ProngDecLenMin{"cut3ProngDecLenMin", -1., "min. decay length"}; // 2-prong histograms - OutputObj<TH1F> hvtx_x{TH1F("hvtx_x", "2-track vtx", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx_y{TH1F("hvtx_y", "2-track vtx", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx_z{TH1F("hvtx_z", "2-track vtx", 1000, -20., 20.)}; - OutputObj<TH1F> hmass2{TH1F("hmass2", ";Inv Mass (GeV/#it{c}^{2})", 500, 0., 5.)}; + OutputObj<TH1F> hvtx2_x{TH1F("hvtx2_x", "2-prong candidates;#it{x}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx2_y{TH1F("hvtx2_y", "2-prong candidates;#it{y}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx2_z{TH1F("hvtx2_z", "2-prong candidates;#it{z}_{sec. vtx.} (cm);entries", 1000, -20., 20.)}; + OutputObj<TH1F> hmass2{TH1F("hmass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; // 3-prong histograms - OutputObj<TH1F> hvtx3_x{TH1F("hvtx3_x", "3-track vtx", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx3_y{TH1F("hvtx3_y", "3-track vtx", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx3_z{TH1F("hvtx3_z", "3-track vtx", 1000, -20., 20.)}; - OutputObj<TH1F> hmass3{TH1F("hmass3", ";Inv Mass (GeV/#it{c}^{2})", 500, 1.6, 2.1)}; + OutputObj<TH1F> hvtx3_x{TH1F("hvtx3_x", "3-prong candidates;#it{x}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx3_y{TH1F("hvtx3_y", "3-prong candidates;#it{y}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; + OutputObj<TH1F> hvtx3_z{TH1F("hvtx3_z", "3-prong candidates;#it{z}_{sec. vtx.} (cm);entries", 1000, -20., 20.)}; + OutputObj<TH1F> hmass3{TH1F("hmass3", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 2.1)}; Filter filterSelectTracks = (aod::hf_seltrack::isSel2Prong == 1); using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::HFSelTrack>>; @@ -191,14 +195,14 @@ struct HFTrackIndexSkimsCreator { } // 2-prong vertex fitter - o2::vertexing::DCAFitterN<2> df; - df.setBz(d_bz); - df.setPropagateToPCA(b_propdca); - df.setMaxR(d_maxr); - df.setMaxDZIni(d_maxdzini); - df.setMinParamChange(d_minparamchange); - df.setMinRelChi2Change(d_minrelchi2change); - df.setUseAbsDCA(true); + o2::vertexing::DCAFitterN<2> df2; + df2.setBz(d_bz); + df2.setPropagateToPCA(b_propdca); + df2.setMaxR(d_maxr); + df2.setMaxDZIni(d_maxdzini); + df2.setMinParamChange(d_minparamchange); + df2.setMinRelChi2Change(d_minrelchi2change); + df2.setUseAbsDCA(true); // 3-prong vertex fitter o2::vertexing::DCAFitterN<3> df3; @@ -227,47 +231,47 @@ struct HFTrackIndexSkimsCreator { } auto trackParVarNeg1 = getTrackParCov(trackNeg1); - auto pVecCand = array{trackPos1.px() + trackNeg1.px(), - trackPos1.py() + trackNeg1.py(), - trackPos1.pz() + trackNeg1.pz()}; - bool isSelectedCandD0 = true; - - // pT cand cut - double pt_Cand_before2vertex = RecoDecay::Pt(pVecCand); - if (pt_Cand_before2vertex < ptmincand_2prong) { - isSelectedCandD0 = false; + auto pVecCandProng2 = array{trackPos1.px() + trackNeg1.px(), + trackPos1.py() + trackNeg1.py(), + trackPos1.pz() + trackNeg1.pz()}; + bool isSelectedCand2Prong = true; + + // candidate pT cut + if (RecoDecay::Pt(pVecCandProng2) < cut2ProngPtCandMin) { + isSelectedCand2Prong = false; } - if (isSelectedCandD0) { + if (isSelectedCand2Prong) { // reconstruct the 2-prong secondary vertex - if (df.process(trackParVarPos1, trackParVarNeg1) == 0) { + if (df2.process(trackParVarPos1, trackParVarNeg1) == 0) { continue; } // imp. par. product cut - if (isSelectedCandD0 && cutImpParProductMax < 100.) { - if (trackPos1.dcaPrim0() * trackNeg1.dcaPrim0() > cutImpParProductMax) { - isSelectedCandD0 = false; + if (isSelectedCand2Prong && cut2ProngImpParProductMax < 100.) { + if (trackPos1.dcaPrim0() * trackNeg1.dcaPrim0() > cut2ProngImpParProductMax) { + isSelectedCand2Prong = false; } } // get secondary vertex - const auto& secondaryVertex = df.getPCACandidate(); + const auto& secondaryVertex2 = df2.getPCACandidate(); + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + df2.getTrack(0).getPxPyPzGlo(pvec0); + df2.getTrack(1).getPxPyPzGlo(pvec1); // CPA cut - if (isSelectedCandD0 && cutCPAMin > -2.) { - auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, pVecCand); - if (cpa < cutCPAMin) { - isSelectedCandD0 = false; + if (isSelectedCand2Prong && cut2ProngCPAMin > -2.) { + pVecCandProng2 = RecoDecay::PVec(pvec0, pvec1); + auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex2, pVecCandProng2); + if (cpa < cut2ProngCPAMin) { + isSelectedCand2Prong = false; } } - if (isSelectedCandD0) { - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - df.getTrack(0).getPxPyPzGlo(pvec0); - df.getTrack(1).getPxPyPzGlo(pvec1); + if (isSelectedCand2Prong) { // calculate invariant masses auto arrMom = array{pvec0, pvec1}; mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); @@ -275,23 +279,23 @@ struct HFTrackIndexSkimsCreator { } // invariant-mass cut - if (isSelectedCandD0 && cutInvMassD0Min >= 0. && cutInvMassD0Max > 0.) { - if ((mass2PiK < cutInvMassD0Min || mass2PiK > cutInvMassD0Max) && - (mass2KPi < cutInvMassD0Min || mass2KPi > cutInvMassD0Max)) { - isSelectedCandD0 = false; + if (isSelectedCand2Prong && cut2ProngInvMassD0Min >= 0. && cut2ProngInvMassD0Max > 0.) { + if ((mass2PiK < cut2ProngInvMassD0Min || mass2PiK > cut2ProngInvMassD0Max) && + (mass2KPi < cut2ProngInvMassD0Min || mass2KPi > cut2ProngInvMassD0Max)) { + isSelectedCand2Prong = false; } } - if (isSelectedCandD0) { + if (isSelectedCand2Prong) { // fill table row rowTrackIndexProng2(trackPos1.globalIndex(), trackNeg1.globalIndex(), 1); // fill histograms if (b_dovalplots) { - hvtx_x->Fill(secondaryVertex[0]); - hvtx_y->Fill(secondaryVertex[1]); - hvtx_z->Fill(secondaryVertex[2]); + hvtx2_x->Fill(secondaryVertex2[0]); + hvtx2_y->Fill(secondaryVertex2[1]); + hvtx2_z->Fill(secondaryVertex2[2]); hmass2->Fill(mass2PiK); hmass2->Fill(mass2KPi); } @@ -317,53 +321,73 @@ struct HFTrackIndexSkimsCreator { continue; } - // calculate invariant mass - auto arr3Mom = array{ - array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, - array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, - array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + auto pVecCandProng3Pos = RecoDecay::PVec(pVecCandProng2, array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}); - if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) { + // candidate pT cut + if (RecoDecay::Pt(pVecCandProng3Pos) < cut3ProngPtCandMin) { continue; } - double pt_Cand3_before2vertex = RecoDecay::Pt(trackPos1.px() + trackNeg1.px() + trackPos2.px(), - trackPos1.py() + trackNeg1.py() + trackPos2.py()); + // invariant-mass cut + if (cut3ProngInvMassDPlusMin >= 0. && cut3ProngInvMassDPlusMax > 0.) { + // calculate invariant mass + auto arr3Mom = array{ + array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, + array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, + array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + if (mass3PiKPi < cut3ProngInvMassDPlusMin || mass3PiKPi > cut3ProngInvMassDPlusMax) { + continue; + } + } + + // reconstruct the 3-prong secondary vertex + auto trackParVarPos2 = getTrackParCov(trackPos2); + if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) { + continue; + } - if (pt_Cand3_before2vertex >= ptmincand_3prong) { - // reconstruct the 3-prong secondary vertex - auto trackParVarPos2 = getTrackParCov(trackPos2); - if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) { + // get secondary vertex + const auto& secondaryVertex3 = df3.getPCACandidate(); + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); + + // CPA cut + if (cut3ProngCPAMin > -2.) { + pVecCandProng3Pos = RecoDecay::PVec(pvec0, pvec1, pvec2); + auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3, pVecCandProng3Pos); + if (cpa < cut3ProngCPAMin) { continue; } + } - // fill table row - rowTrackIndexProng3(trackPos1.globalIndex(), - trackNeg1.globalIndex(), - trackPos2.globalIndex(), 2); - - // fill histograms - if (b_dovalplots) { - // get secondary vertex - const auto& secondaryVertex3 = df3.getPCACandidate(); - hvtx3_x->Fill(secondaryVertex3[0]); - hvtx3_y->Fill(secondaryVertex3[1]); - hvtx3_z->Fill(secondaryVertex3[2]); - - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - array<float, 3> pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); - - // calculate invariant mass - arr3Mom = array{pvec0, pvec1, pvec2}; - hmass3->Fill(RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi})); + // decay length cut + if (cut3ProngDecLenMin > 0.) { + auto decayLength = RecoDecay::distance(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3); + if (decayLength < cut3ProngDecLenMin) { + continue; } } + + // fill table row + rowTrackIndexProng3(trackPos1.globalIndex(), + trackNeg1.globalIndex(), + trackPos2.globalIndex(), 2); + + // fill histograms + if (b_dovalplots) { + hvtx3_x->Fill(secondaryVertex3[0]); + hvtx3_y->Fill(secondaryVertex3[1]); + hvtx3_z->Fill(secondaryVertex3[2]); + + // calculate invariant mass + hmass3->Fill(RecoDecay::M(array{pvec0, pvec1, pvec2}, array{massPi, massK, massPi})); + } } // second loop over negative tracks @@ -376,53 +400,73 @@ struct HFTrackIndexSkimsCreator { continue; } - // calculate invariant mass - auto arr3Mom = array{ - array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, - array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, - array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + auto pVecCandProng3Neg = RecoDecay::PVec(pVecCandProng2, array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}); - if (mass3PiKPi < d_minmassDp || mass3PiKPi > d_maxmassDp) { + // candidate pT cut + if (RecoDecay::Pt(pVecCandProng3Neg) < cut3ProngPtCandMin) { continue; } - double pt_Cand3_before2vertex = RecoDecay::Pt(trackPos1.px() + trackNeg1.px() + trackNeg2.px(), - trackPos1.py() + trackNeg1.py() + trackNeg2.py()); + // invariant-mass cut + if (cut3ProngInvMassDPlusMin >= 0. && cut3ProngInvMassDPlusMax > 0.) { + // calculate invariant mass + auto arr3Mom = array{ + array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, + array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, + array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}}; + mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); + if (mass3PiKPi < cut3ProngInvMassDPlusMin || mass3PiKPi > cut3ProngInvMassDPlusMax) { + continue; + } + } + + // reconstruct the 3-prong secondary vertex + auto trackParVarNeg2 = getTrackParCov(trackNeg2); + if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) { + continue; + } - if (pt_Cand3_before2vertex >= ptmincand_3prong) { - // reconstruct the 3-prong secondary vertex - auto trackParVarNeg2 = getTrackParCov(trackNeg2); - if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) { + // get secondary vertex + const auto& secondaryVertex3 = df3.getPCACandidate(); + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + array<float, 3> pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); + + // CPA cut + if (cut3ProngCPAMin > -2.) { + pVecCandProng3Neg = RecoDecay::PVec(pvec0, pvec1, pvec2); + auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3, pVecCandProng3Neg); + if (cpa < cut3ProngCPAMin) { continue; } + } - // fill table row - rowTrackIndexProng3(trackNeg1.globalIndex(), - trackPos1.globalIndex(), - trackNeg2.globalIndex(), 2); - - // fill histograms - if (b_dovalplots) { - // get secondary vertex - const auto& secondaryVertex3 = df3.getPCACandidate(); - hvtx3_x->Fill(secondaryVertex3[0]); - hvtx3_y->Fill(secondaryVertex3[1]); - hvtx3_z->Fill(secondaryVertex3[2]); - - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - array<float, 3> pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); - - // calculate invariant mass - arr3Mom = array{pvec0, pvec1, pvec2}; - hmass3->Fill(RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi})); + // decay length cut + if (cut3ProngDecLenMin > 0.) { + auto decayLength = RecoDecay::distance(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3); + if (decayLength < cut3ProngDecLenMin) { + continue; } } + + // fill table row + rowTrackIndexProng3(trackNeg1.globalIndex(), + trackPos1.globalIndex(), + trackNeg2.globalIndex(), 2); + + // fill histograms + if (b_dovalplots) { + hvtx3_x->Fill(secondaryVertex3[0]); + hvtx3_y->Fill(secondaryVertex3[1]); + hvtx3_z->Fill(secondaryVertex3[2]); + + // calculate invariant mass + hmass3->Fill(RecoDecay::M(array{pvec0, pvec1, pvec2}, array{massPi, massK, massPi})); + } } } } diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index c08a4c59fd683..dc913c950ae90 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -26,22 +26,23 @@ using namespace o2::framework::expressions; /// D0 analysis task struct TaskD0 { - OutputObj<TH1F> hmass{TH1F("hmass", "2-track inv mass", 500, 0., 5.)}; - OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0., 10.)}; - OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0., 10.)}; - OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0., 10.)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.)}; - OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.)}; - OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "prong 0 dca xy to prim. vertex (cm)", 100, -1., 1.)}; - OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "prong 1 dca xy to prim. vertex (cm)", 100, -1., 1.)}; - OutputObj<TH1F> hd0d0{TH1F("hd0d0", "product of dca xy to prim. vertex (cm^{2})", 500, -1., 1.)}; - OutputObj<TH1F> hCTS{TH1F("hCTS", "cos #it{#theta}*", 120, -1.1, 1.1)}; - OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20., 100.)}; - OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2., 2.)}; - OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; - OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1., 1.)}; - OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.)}; - OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.)}; + OutputObj<TH1F> hmass{TH1F("hmass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; + OutputObj<TH1F> hptcand{TH1F("hptcand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong0{TH1F("hptprong0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong1{TH1F("hptprong1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hdeclength{TH1F("declength", "2-prong candidates;decay length (cm);entries", 200, 0., 2.)}; + OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "2-prong candidates;decay length xy (cm);entries", 200, 0., 2.)}; + OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hd0d0{TH1F("hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", 500, -1., 1.)}; + OutputObj<TH1F> hCTS{TH1F("hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", 110, -1.1, 1.1)}; + OutputObj<TH1F> hCt{TH1F("hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", 120, -20., 100.)}; + OutputObj<TH1F> hCPA{TH1F("hCPA", "2-prong candidates;cosine of pointing angle;entries", 110, -1.1, 1.1)}; + OutputObj<TH1F> hEta{TH1F("hEta", "2-prong candidates;candidate #it{#eta};entries", 100, -2., 2.)}; + //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "2-prong candidates;selection status;entries", 5, -0.5, 4.5)}; + OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "2-prong candidates;impact parameter error (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "2-prong candidates;decay length error (cm);entries", 100, 0., 1.)}; + OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", 100, 0., 1.)}; Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; @@ -67,8 +68,9 @@ struct TaskD0 { hd0d0->Fill(candidate.impactParameterProduct()); hCTS->Fill(CosThetaStarD0(candidate)); hCt->Fill(CtD0(candidate)); + hCPA->Fill(candidate.cpa()); hEta->Fill(candidate.eta()); - hselectionstatus->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); + //hselectionstatus->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); hImpParErr->Fill(candidate.errorImpactParameter0()); hImpParErr->Fill(candidate.errorImpactParameter1()); hDecLenErr->Fill(candidate.errorDecayLength()); diff --git a/Analysis/Tasks/PWGHF/taskDPlus.cxx b/Analysis/Tasks/PWGHF/taskDPlus.cxx index 1072358098b62..e422476a556f0 100644 --- a/Analysis/Tasks/PWGHF/taskDPlus.cxx +++ b/Analysis/Tasks/PWGHF/taskDPlus.cxx @@ -26,20 +26,23 @@ using namespace o2::aod::hf_cand_prong3; /// D± analysis task struct TaskDPlus { - OutputObj<TH1F> hmass{TH1F("hmass", "3-track inv mass", 500, 1.6, 2.1)}; - OutputObj<TH1F> hptcand{TH1F("hptcand", "pt candidate", 100, 0., 10.)}; - OutputObj<TH1F> hptprong0{TH1F("hptprong0", "pt prong0", 100, 0., 10.)}; - OutputObj<TH1F> hptprong1{TH1F("hptprong1", "pt prong1", 100, 0., 10.)}; - OutputObj<TH1F> hptprong2{TH1F("hptprong2", "pt prong2", 100, 0., 10.)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "decay length", 200, 0., 2.)}; - OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "decay length xy", 200, 0., 2.)}; - OutputObj<TH1F> hd0{TH1F("hd0", "dca xy to prim. vertex (cm)", 100, -1., 1.)}; - OutputObj<TH1F> hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20., 100.)}; - OutputObj<TH1F> hEta{TH1F("hEta", "#it{#eta}", 100, -2., 2.)}; - //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; - OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "impact parameter error", 100, -1., 1.)}; - OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "decay length error", 100, 0., 1.)}; - OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "decay length XY error", 100, 0., 1.)}; + OutputObj<TH1F> hmass{TH1F("hmass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 2.1)}; + OutputObj<TH1F> hptcand{TH1F("hptcand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong0{TH1F("hptprong0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong1{TH1F("hptprong1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong2{TH1F("hptprong2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hdeclength{TH1F("declength", "3-prong candidates;decay length (cm);entries", 200, 0., 2.)}; + OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "3-prong candidates;decay length xy (cm);entries", 200, 0., 2.)}; + OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hd0Prong2{TH1F("hd0Prong2", "3-prong candidates;prong 2 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hCt{TH1F("hCt", "3-prong candidates;proper lifetime (D^{#pm}) * #it{c} (cm);entries", 120, -20., 100.)}; + OutputObj<TH1F> hCPA{TH1F("hCPA", "3-prong candidates;cosine of pointing angle;entries", 110, -1.1, 1.1)}; + OutputObj<TH1F> hEta{TH1F("hEta", "3-prong candidates;candidate #it{#eta};entries", 100, -2., 2.)}; + //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "3-prong candidates;selection status;entries", 5, -0.5, 4.5)}; + OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "3-prong candidates;impact parameter error (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "3-prong candidates;decay length error (cm);entries", 100, 0., 1.)}; + OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "3-prong candidates;decay length xy error (cm);entries", 100, 0., 1.)}; Configurable<int> d_selectionFlagDPlus{"d_selectionFlagDPlus", 1, "Selection Flag for DPlus"}; @@ -56,10 +59,11 @@ struct TaskDPlus { hptprong2->Fill(candidate.ptProng2()); hdeclength->Fill(candidate.decayLength()); hdeclengthxy->Fill(candidate.decayLengthXY()); - hd0->Fill(candidate.impactParameter0()); - hd0->Fill(candidate.impactParameter1()); - hd0->Fill(candidate.impactParameter2()); + hd0Prong0->Fill(candidate.impactParameter0()); + hd0Prong1->Fill(candidate.impactParameter1()); + hd0Prong2->Fill(candidate.impactParameter2()); hCt->Fill(CtDPlus(candidate)); + hCPA->Fill(candidate.cpa()); hEta->Fill(candidate.eta()); //hselectionstatus->Fill(candidate.isSelDPlus()); hImpParErr->Fill(candidate.errorImpactParameter0()); From 1027bffc5672292a5c1b48da71ba410a86a13afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= <mario.kruger@cern.ch> Date: Thu, 22 Oct 2020 16:30:14 +0200 Subject: [PATCH 1088/1751] HistogramRegistry: add option to store registry content in dedicated directory --- Analysis/Tutorials/src/histogramRegistry.cxx | 4 ++-- .../Core/include/Framework/HistogramRegistry.h | 18 ++++++++++++------ Framework/Core/src/CommonDataProcessors.cxx | 18 +++++++++++++++--- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index c178e0ad3f084..fc833c15413f1 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -126,8 +126,8 @@ struct CTask { }; struct DTask { - HistogramRegistry spectra{"spectra", true, {}}; - HistogramRegistry etaStudy{"etaStudy", true, {}}; + HistogramRegistry spectra{"spectra", true, {}, OutputObjHandlingPolicy::AnalysisObject, true}; + HistogramRegistry etaStudy{"etaStudy", true, {}, OutputObjHandlingPolicy::AnalysisObject, true}; void init(o2::framework::InitContext&) { diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 8d4e3552b8d9b..cdb14e2b6b9fa 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -393,11 +393,12 @@ struct HistFiller { class HistogramRegistry { public: - HistogramRegistry(char const* const name_, bool enable, std::vector<HistogramSpec> histSpecs_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) : name(name_), - policy(policy_), - enabled(enable), - mRegistryKey(), - mRegistryValue() + HistogramRegistry(char const* const name_, bool enable, std::vector<HistogramSpec> histSpecs_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, bool createFolder_ = false) : name(name_), + policy(policy_), + enabled(enable), + mRegistryKey(), + mRegistryValue(), + mCreateFolder(createFolder_) { mRegistryKey.fill(0u); for (auto& histSpec : histSpecs_) { @@ -474,6 +475,7 @@ class HistogramRegistry { TList* list = new TList(); list->SetName(this->name.data()); + for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { TNamed* rawPtr = nullptr; std::visit([&](const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[j]); @@ -490,7 +492,10 @@ class HistogramRegistry } } } - list->SetOwner(false); // object deletion will be handled by shared_ptrs + if (mCreateFolder) { + // propagate wether or not to create a dedicated folder for this registry to the writer by adding this 'flag' to the list + list->AddLast(new TNamed("createFolder", "")); + } return list; } @@ -612,6 +617,7 @@ class HistogramRegistry std::string name{}; bool enabled{}; + bool mCreateFolder{}; OutputObjHandlingPolicy policy{}; uint32_t taskHash{}; diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 432a1847f6cdb..c243036e90e20 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -121,10 +121,22 @@ DataProcessorSpec CommonDataProcessors::getHistogramRegistrySink(outputObjects c } } }; + + TDirectory* currentDir = f[route.policy]->GetDirectory(currentDirectory.c_str()); TList* outputList = (TList*)entry.obj; - writeListToFile(outputList, f[route.policy]->GetDirectory(currentDirectory.c_str())); - outputList->SetOwner(true); - delete outputList; // properly remove the empty list and its sub-lists + outputList->SetOwner(false); + + // if registry should live in dedicated folder a TNamed object is appended to the list + if (outputList->Last()->IsA() == TNamed::Class()) { + delete outputList->Last(); + outputList->RemoveLast(); + currentDir = currentDir->mkdir(outputList->GetName(), outputList->GetName(), true); + } + + writeListToFile(outputList, currentDir); + outputList->SetOwner(); + delete outputList; + entry.obj = nullptr; } } for (auto i = 0u; i < OutputObjHandlingPolicy::numPolicies; ++i) { From 6be03b4be29064f088b2056efcab76dc49878833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= <mario.kruger@cern.ch> Date: Fri, 23 Oct 2020 13:32:30 +0200 Subject: [PATCH 1089/1751] TrackQA: use grouping feature of registry --- Analysis/Tasks/trackqa.cxx | 114 +++++++++++++++---------------------- 1 file changed, 47 insertions(+), 67 deletions(-) diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 5c0aebe319452..eddc3812b59eb 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -40,25 +40,11 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) //**************************************************************************************** struct TrackQATask { - HistogramRegistry kine{"Kine", true, {}, OutputObjHandlingPolicy::QAObject}; - HistogramRegistry trackpar{"TrackPar", true, {}, OutputObjHandlingPolicy::QAObject}; - HistogramRegistry its{"ITS", true, {}, OutputObjHandlingPolicy::QAObject}; - HistogramRegistry tpc{"TPC", true, {}, OutputObjHandlingPolicy::QAObject}; - - //HistogramRegistry trd{"TRD", true, {}, OutputObjHandlingPolicy::QAObject}; - //HistogramRegistry tof{"TOF", true, {}, OutputObjHandlingPolicy::QAObject}; - //HistogramRegistry emcal{"EMCAL", true, {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry histos{"Histos", true, {}, OutputObjHandlingPolicy::QAObject}; Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; Filter trackFilter = aod::track::isGlobalTrack == true; - /* - //Function float castFLOAT4(uint8) not supported yet - Filter trackFilter = ((0 * aod::track::isGlobalTrack == (float)selectedTracks) || - (1 * aod::track::isGlobalTrack == (float)selectedTracks) || - (2 * aod::track::isGlobalTrackSDD == (float)selectedTracks) || - (3 * aod::track::isGlobalTrackwTOF == (float)selectedTracks)); - */ void init(o2::framework::InitContext&) { @@ -66,83 +52,77 @@ struct TrackQATask { 1.1, 1.2, 1.3, 1.4, 1.5, 2.0, 5.0, 10.0, 20.0, 50.0}; // kine histograms - kine.add("pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", kTH1D, {{ptBinning}}); - kine.add("eta", "#eta;#eta", kTH1D, {{180, -0.9, 0.9}}); - kine.add("phi", "#phi;#phi [rad]", kTH1D, {{180, 0., 2 * M_PI}}); + histos.add("Kine/pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", kTH1D, {{ptBinning}}); + histos.add("Kine/eta", "#eta;#eta", kTH1D, {{180, -0.9, 0.9}}); + histos.add("Kine/phi", "#phi;#phi [rad]", kTH1D, {{180, 0., 2 * M_PI}}); // track histograms - trackpar.add("x", "track #it{x} position at dca in local coordinate system;#it{x} [cm]", kTH1D, {{200, -0.36, 0.36}}); - trackpar.add("y", "track #it{y} position at dca in local coordinate system;#it{y} [cm]", kTH1D, {{200, -0.5, 0.5}}); - trackpar.add("z", "track #it{z} position at dca in local coordinate system;#it{z} [cm]", kTH1D, {{200, -11., 11.}}); - trackpar.add("alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", kTH1D, {{36, -M_PI, M_PI}}); - trackpar.add("signed1Pt", "track signed 1/#it{p}_{T};#it{q}/#it{p}_{T}", kTH1D, {{200, -8, 8}}); - trackpar.add("snp", "sinus of track momentum azimuthal angle;snp", kTH1D, {{11, -0.1, 0.1}}); - trackpar.add("tgl", "tangent of the track momentum dip angle;tgl;", kTH1D, {{200, -1., 1.}}); - trackpar.add("flags", "track flag;flag bit", kTH1D, {{64, -0.5, 63.5}}); - trackpar.add("dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", kTH1D, {{200, -0.15, 0.15}}); - trackpar.add("dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", kTH1D, {{200, -0.15, 0.15}}); + histos.add("TrackPar/x", "track #it{x} position at dca in local coordinate system;#it{x} [cm]", kTH1D, {{200, -0.36, 0.36}}); + histos.add("TrackPar/y", "track #it{y} position at dca in local coordinate system;#it{y} [cm]", kTH1D, {{200, -0.5, 0.5}}); + histos.add("TrackPar/z", "track #it{z} position at dca in local coordinate system;#it{z} [cm]", kTH1D, {{200, -11., 11.}}); + histos.add("TrackPar/alpha", "rotation angle of local wrt. global coordinate system;#alpha [rad]", kTH1D, {{36, -M_PI, M_PI}}); + histos.add("TrackPar/signed1Pt", "track signed 1/#it{p}_{T};#it{q}/#it{p}_{T}", kTH1D, {{200, -8, 8}}); + histos.add("TrackPar/snp", "sinus of track momentum azimuthal angle;snp", kTH1D, {{11, -0.1, 0.1}}); + histos.add("TrackPar/tgl", "tangent of the track momentum dip angle;tgl;", kTH1D, {{200, -1., 1.}}); + histos.add("TrackPar/flags", "track flag;flag bit", kTH1D, {{64, -0.5, 63.5}}); + histos.add("TrackPar/dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", kTH1D, {{200, -0.15, 0.15}}); + histos.add("TrackPar/dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", kTH1D, {{200, -0.15, 0.15}}); // its histograms - its.add("itsNCls", "number of found ITS clusters;# clusters ITS", kTH1D, {{8, -0.5, 7.5}}); - its.add("itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", kTH1D, {{100, 0, 40}}); - its.add("itsHits", "hitmap ITS;layer ITS", kTH1D, {{7, -0.5, 6.5}}); + histos.add("ITS/itsNCls", "number of found ITS clusters;# clusters ITS", kTH1D, {{8, -0.5, 7.5}}); + histos.add("ITS/itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", kTH1D, {{100, 0, 40}}); + histos.add("ITS/itsHits", "hitmap ITS;layer ITS", kTH1D, {{7, -0.5, 6.5}}); // tpc histograms - tpc.add("tpcNClsFindable", "number of findable TPC clusters;# findable clusters TPC", kTH1D, {{165, -0.5, 164.5}}); - tpc.add("tpcNClsFound", "number of found TPC clusters;# clusters TPC", kTH1D, {{165, -0.5, 164.5}}); - tpc.add("tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", kTH1D, {{165, -0.5, 164.5}}); - tpc.add("tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", kTH1D, {{165, -0.5, 164.5}}); - tpc.add("tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", kTH1D, {{100, 0., 1.}}); - tpc.add("tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {{120, 0.0, 1.2}}); - tpc.add("tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {{100, 0, 10}}); + histos.add("TPC/tpcNClsFindable", "number of findable TPC clusters;# findable clusters TPC", kTH1D, {{165, -0.5, 164.5}}); + histos.add("TPC/tpcNClsFound", "number of found TPC clusters;# clusters TPC", kTH1D, {{165, -0.5, 164.5}}); + histos.add("TPC/tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", kTH1D, {{165, -0.5, 164.5}}); + histos.add("TPC/tpcNClsCrossedRows", "number of crossed TPC rows;# crossed rows TPC", kTH1D, {{165, -0.5, 164.5}}); + histos.add("TPC/tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", kTH1D, {{100, 0., 1.}}); + histos.add("TPC/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {{120, 0.0, 1.2}}); + histos.add("TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {{100, 0, 10}}); } void process(soa::Filtered<soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection>>::iterator const& track) { // fill kinematic variables - kine.fill("pt", track.pt()); - kine.fill("eta", track.eta()); - kine.fill("phi", track.phi()); + histos.fill("Kine/pt", track.pt()); + histos.fill("Kine/eta", track.eta()); + histos.fill("Kine/phi", track.phi()); // fill track parameters - trackpar.fill("alpha", track.alpha()); - trackpar.fill("x", track.x()); - trackpar.fill("y", track.y()); - trackpar.fill("z", track.z()); - trackpar.fill("signed1Pt", track.signed1Pt()); - trackpar.fill("snp", track.snp()); - trackpar.fill("tgl", track.tgl()); + histos.fill("TrackPar/alpha", track.alpha()); + histos.fill("TrackPar/x", track.x()); + histos.fill("TrackPar/y", track.y()); + histos.fill("TrackPar/z", track.z()); + histos.fill("TrackPar/signed1Pt", track.signed1Pt()); + histos.fill("TrackPar/snp", track.snp()); + histos.fill("TrackPar/tgl", track.tgl()); for (unsigned int i = 0; i < 64; i++) { if (track.flags() & (1 << i)) { - trackpar.fill("flags", i); + histos.fill("TrackPar/flags", i); } } - trackpar.fill("dcaXY", track.dcaXY()); - trackpar.fill("dcaZ", track.dcaZ()); + histos.fill("TrackPar/dcaXY", track.dcaXY()); + histos.fill("TrackPar/dcaZ", track.dcaZ()); // fill ITS variables - its.fill("itsNCls", track.itsNCls()); - its.fill("itsChi2NCl", track.itsChi2NCl()); + histos.fill("ITS/itsNCls", track.itsNCls()); + histos.fill("ITS/itsChi2NCl", track.itsChi2NCl()); for (unsigned int i = 0; i < 7; i++) { if (track.itsClusterMap() & (1 << i)) { - its.fill("itsHits", i); + histos.fill("ITS/itsHits", i); } } // fill TPC variables - tpc.fill("tpcNClsFindable", track.tpcNClsFindable()); - tpc.fill("tpcNClsFound", track.tpcNClsFound()); - tpc.fill("tpcNClsShared", track.tpcNClsShared()); - tpc.fill("tpcNClsCrossedRows", track.tpcNClsCrossedRows()); - tpc.fill("tpcCrossedRowsOverFindableCls", track.tpcCrossedRowsOverFindableCls()); - tpc.fill("tpcFractionSharedCls", track.tpcFractionSharedCls()); - tpc.fill("tpcChi2NCl", track.tpcChi2NCl()); - - // fill TRD variables - - // fill TOF variables - - // fill EMCAL variables + histos.fill("TPC/tpcNClsFindable", track.tpcNClsFindable()); + histos.fill("TPC/tpcNClsFound", track.tpcNClsFound()); + histos.fill("TPC/tpcNClsShared", track.tpcNClsShared()); + histos.fill("TPC/tpcNClsCrossedRows", track.tpcNClsCrossedRows()); + histos.fill("TPC/tpcCrossedRowsOverFindableCls", track.tpcCrossedRowsOverFindableCls()); + histos.fill("TPC/tpcFractionSharedCls", track.tpcFractionSharedCls()); + histos.fill("TPC/tpcChi2NCl", track.tpcChi2NCl()); } }; From a9a7ed3edf84f809afdbd7cc287d17d6ee1ebbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= <mario.kruger@cern.ch> Date: Sat, 24 Oct 2020 10:42:32 +0200 Subject: [PATCH 1090/1751] HistogramRegistry: add sorting and cloning features - added option to sort histograms alphabetically in the output file - added possibility to clone histograms or groups of histograms stored in the registry and store the copy under a different (group-)name --- Analysis/Tasks/trackqa.cxx | 6 +- Analysis/Tutorials/src/histogramRegistry.cxx | 52 +++++--- .../include/Framework/HistogramRegistry.h | 121 +++++++++++++----- .../Core/test/benchmark_HistogramRegistry.cxx | 2 +- .../Core/test/test_HistogramRegistry.cxx | 22 ++-- 5 files changed, 143 insertions(+), 60 deletions(-) diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index eddc3812b59eb..27e21d0b80753 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -40,7 +40,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) //**************************************************************************************** struct TrackQATask { - HistogramRegistry histos{"Histos", true, {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; @@ -127,7 +127,7 @@ struct TrackQATask { }; struct TrackCutQATask { - HistogramRegistry cuts{"Cuts", true, {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry cuts{"Cuts", {}, OutputObjHandlingPolicy::QAObject}; TrackSelection selectedTracks = getGlobalTrackSelection(); static constexpr int ncuts = static_cast<int>(TrackSelection::TrackCuts::kNCuts); void init(InitContext&) @@ -155,7 +155,7 @@ struct TrackCutQATask { //**************************************************************************************** struct TrackQATaskMC { - HistogramRegistry resolution{"Resolution", true, {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry resolution{"Resolution", {}, OutputObjHandlingPolicy::QAObject}; void init(o2::framework::InitContext&){ diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index fc833c15413f1..773c90377f0fd 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -25,7 +25,6 @@ struct ATask { /// Construct a registry object with direct declaration HistogramRegistry registry{ "registry", - true, { {"eta", "#eta", {HistType::kTH1F, {{102, -2.01, 2.01}}}}, // {"phi", "#varphi", {HistType::kTH1F, {{100, 0., 2. * M_PI}}}} // @@ -45,7 +44,6 @@ struct BTask { /// Construct a registry object with direct declaration HistogramRegistry registry{ "registry", - true, { {"eta", "#eta", {HistType::kTH1F, {{102, -2.01, 2.01}}}}, // {"ptToPt", "#ptToPt", {HistType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // @@ -63,34 +61,35 @@ struct CTask { HistogramRegistry registry{ "registry", - true, { {"1d", "test 1d", {HistType::kTH1I, {{100, -10.0f, 10.0f}}}}, // {"2d", "test 2d", {HistType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}}, // {"3d", "test 3d", {HistType::kTH3D, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}}, // {"4d", "test 4d", {HistType::kTHnC, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}}, // {"5d", "test 5d", {HistType::kTHnSparseL, {{10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}, {10, -10.0f, 10.01f}}}}, // - } // + }, + OutputObjHandlingPolicy::AnalysisObject, + true // }; void init(o2::framework::InitContext&) { - registry.add({"7d", "test 7d", {HistType::kTHnC, {{3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}}}}); + registry.add("7d", "test 7d", {HistType::kTHnC, {{3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}}}); - registry.add({"6d", "test 6d", {HistType::kTHnC, {{3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}}}}); + registry.add("6d", "test 6d", {HistType::kTHnC, {{3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}, {3, -10.0f, 10.01f}}}); - registry.add({"1d-profile", "test 1d profile", {HistType::kTProfile, {{20, 0.0f, 10.01f}}}}); - registry.add({"2d-profile", "test 2d profile", {HistType::kTProfile2D, {{20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}}}}); - registry.add({"3d-profile", "test 3d profile", {HistType::kTProfile3D, {{20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}}}}); + registry.add("1d-profile", "test 1d profile", {HistType::kTProfile, {{20, 0.0f, 10.01f}}}); + registry.add("2d-profile", "test 2d profile", {HistType::kTProfile2D, {{20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}}}); + registry.add("3d-profile", "test 3d profile", {HistType::kTProfile3D, {{20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}, {20, 0.0f, 10.01f}}}); - registry.add({"2d-weight", "test 2d weight", {HistType::kTH2C, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true}); + registry.add("2d-weight", "test 2d weight", {HistType::kTH2C, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true); - registry.add({"3d-weight", "test 3d weight", {HistType::kTH3C, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true}); + registry.add("3d-weight", "test 3d weight", {HistType::kTH3C, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true); - registry.add({"4d-weight", "test 4d weight", {HistType::kTHnC, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}, true}); + registry.add("4d-weight", "test 4d weight", {HistType::kTHnC, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}, true); - registry.add({"1d-profile-weight", "test 1d profile weight", {HistType::kTProfile, {{2, -10.0f, 10.01f}}}, true}); - registry.add({"2d-profile-weight", "test 2d profile weight", {HistType::kTProfile2D, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true}); + registry.add("1d-profile-weight", "test 1d profile weight", {HistType::kTProfile, {{2, -10.0f, 10.01f}}}, true); + registry.add("2d-profile-weight", "test 2d profile weight", {HistType::kTProfile2D, {{2, -10.0f, 10.01f}, {2, -10.0f, 10.01f}}}, true); } void process(aod::Tracks const& tracks) @@ -126,8 +125,8 @@ struct CTask { }; struct DTask { - HistogramRegistry spectra{"spectra", true, {}, OutputObjHandlingPolicy::AnalysisObject, true}; - HistogramRegistry etaStudy{"etaStudy", true, {}, OutputObjHandlingPolicy::AnalysisObject, true}; + HistogramRegistry spectra{"spectra", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry etaStudy{"etaStudy", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; void init(o2::framework::InitContext&) { @@ -158,6 +157,19 @@ struct DTask { etaStudy.add("positive", "A side spectra", kTH1I, {ptAxis}); etaStudy.add("negative", "C side spectra", kTH1I, {ptAxis}); + + spectra.add("before_cuts/hist1", "asdf", defaultParticleHist); + spectra.add("before_cuts/hist2", "asdf", defaultParticleHist); + spectra.add("before_cuts/hist3", "asdf", defaultParticleHist); + spectra.add("before_cuts/hist4", "asdf", defaultParticleHist); + spectra.add("before_cuts/hist5", "asdf", defaultParticleHist); + + // clone whole category / group + spectra.addClone("before_cuts/", "after_cuts/"); + + // clone single histograms + spectra.addClone("sigmas", "cascades"); + spectra.addClone("neutral/pions", "strange/funny/particles"); } void process(aod::Tracks const& tracks) @@ -175,6 +187,14 @@ struct DTask { spectra.fill("one/two/three/four/kaons", track.pt(), track.eta(), 50., 0.); spectra.fill("sigmas", track.pt(), track.eta(), 50., 0.); spectra.fill("lambdas", track.pt(), track.eta(), 50., 0.); + + spectra.fill("before_cuts/hist2", track.pt(), track.eta(), 50., 0.); + spectra.fill("before_cuts/hist2", track.pt(), track.eta(), 50., 0.); + + spectra.fill("after_cuts/hist2", track.pt(), track.eta(), 50., 0.); + + spectra.fill("cascades", track.pt(), track.eta(), 50., 0.); + spectra.fill("strange/funny/particles", track.pt(), track.eta(), 50., 0.); } } }; diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index cdb14e2b6b9fa..11023a9f45e98 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -215,7 +215,7 @@ struct HistFactory { // create histogram std::shared_ptr<T> hist{generateHist<T>(histSpec.name, histSpec.title, nAxes, nBins, lowerBounds, upperBounds)}; if (!hist) { - LOGF(FATAL, "The number of specified dimensions does not match the type."); + LOGF(FATAL, "The number of dimensions specified for histogram %s does not match the type.", histSpec.name); return nullptr; } @@ -361,16 +361,16 @@ struct HistFiller { hist->Fill(static_cast<double>(positionAndWeight)...); } else if constexpr (validComplexFill) { // savety check for n dimensional histograms (runtime overhead) - if (hist->GetNdimensions() != nDim) - throw runtime_error("The number of position (and weight) arguments in fill() does not match the histogram dimensions!"); - + if (hist->GetNdimensions() != nDim) { + LOGF(FATAL, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName()); + } double tempArray[sizeof...(Ts)] = {static_cast<double>(positionAndWeight)...}; if constexpr (useWeight) hist->Fill(tempArray, tempArray[sizeof...(Ts) - 1]); else hist->Fill(tempArray); } else { - throw runtime_error("The number of position (and weight) arguments in fill() does not match the histogram dimensions!"); + LOGF(FATAL, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName()); } } @@ -393,12 +393,8 @@ struct HistFiller { class HistogramRegistry { public: - HistogramRegistry(char const* const name_, bool enable, std::vector<HistogramSpec> histSpecs_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, bool createFolder_ = false) : name(name_), - policy(policy_), - enabled(enable), - mRegistryKey(), - mRegistryValue(), - mCreateFolder(createFolder_) + HistogramRegistry(char const* const name_, std::vector<HistogramSpec> histSpecs_ = {}, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, bool sortHistos_ = false, bool createRegistryDir_ = false) + : mName(name_), mPolicy(policy_), mRegistryKey(), mRegistryValue(), mSortHistos(sortHistos_), mCreateRegistryDir(createRegistryDir_) { mRegistryKey.fill(0u); for (auto& histSpec : histSpecs_) { @@ -421,6 +417,33 @@ class HistogramRegistry insert({name_, title_, {histType_, axes_}, callSumw2_}); } + // store a copy of an existing histogram (or group of histograms) under a different name + void addClone(const std::string& source_, const std::string& target_) + { + // search for histograms starting with source_ substring + for (auto& histVariant : mRegistryValue) { + std::visit([&](const auto& sharedPtr) { + if (!sharedPtr.get()) + return; + std::string sourceName{((TNamed*)sharedPtr.get())->GetName()}; + if (sourceName.rfind(source_, 0) == 0) { + // when cloning groups of histograms source_ and target_ must end with "/" + if (sourceName.size() != source_.size() && (source_.back() != '/' || target_.back() != '/')) { + return; + } + // when cloning a single histogram the specified target_ must not be a group name + if (sourceName.size() == source_.size() && target_.back() == '/') { + LOGF(FATAL, "Cannot turn histogram into folder!"); + } + std::string targetName{target_}; + targetName += sourceName.substr(sourceName.find(source_) + source_.size()); + insertClone(targetName.data(), sharedPtr); + } + }, + histVariant); + } + } + // gets the underlying histogram pointer // we cannot automatically infer type here so it has to be explicitly specified // -> get<TH1>(), get<TH2>(), get<TH3>(), get<THn>(), get<THnSparse>(), get<TProfile>(), get<TProfile2D>(), get<TProfile3D>() @@ -458,23 +481,23 @@ class HistogramRegistry OutputSpec const spec() { ConcreteDataMatcher matcher{"HIST", "\0", 0}; - strncpy(matcher.description.str, this->name.data(), 16); - return OutputSpec{OutputLabel{this->name}, matcher}; + strncpy(matcher.description.str, mName.data(), 16); + return OutputSpec{OutputLabel{mName}, matcher}; } OutputRef ref() { - return OutputRef{std::string{this->name}, 0, o2::header::Stack{OutputObjHeader{policy, taskHash}}}; + return OutputRef{std::string{mName}, 0, o2::header::Stack{OutputObjHeader{mPolicy, mTaskHash}}}; } void setHash(uint32_t hash) { - taskHash = hash; + mTaskHash = hash; } TList* operator*() { TList* list = new TList(); - list->SetName(this->name.data()); + list->SetName(mName.data()); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { TNamed* rawPtr = nullptr; @@ -492,8 +515,29 @@ class HistogramRegistry } } } - if (mCreateFolder) { - // propagate wether or not to create a dedicated folder for this registry to the writer by adding this 'flag' to the list + + // sort histograms in output file alphabetically + // TODO: in cases where histograms and directories reside in same level, we could put directories always on top + if (mSortHistos) { + std::function<void(TList*)> sortSubLists; + sortSubLists = [&](TList* list) { + TIter next(list); + TNamed* object = nullptr; + while ((object = (TNamed*)next())) { + if (object->InheritsFrom(TList::Class())) { + TList* subList = (TList*)object; + subList->Sort(); + sortSubLists(subList); + } + } + }; + list->Sort(); + sortSubLists(list); + } + + // create dedicated directory containing all of the registrys histograms + if (mCreateRegistryDir) { + // propagate this to the writer by adding a 'flag' to the output list list->AddLast(new TNamed("createFolder", "")); } return list; @@ -515,7 +559,7 @@ class HistogramRegistry return; } } - throw runtime_error("No matching histogram found in HistogramRegistry!"); + LOGF(FATAL, "No histogram called %s found in HistogramRegistry!", name); } template <typename... Ts> @@ -552,7 +596,7 @@ class HistogramRegistry return; } } - throw runtime_error("No matching histogram found in HistogramRegistry!"); + LOGF(FATAL, "No histogram called %s found in HistogramRegistry!", name); } /// lookup distance counter for benchmarking @@ -573,12 +617,31 @@ class HistogramRegistry return; } } - throw runtime_error("Internal array of HistogramRegistry is full."); + LOGF(FATAL, "Internal array of HistogramRegistry %s is full.", mName); + } + + // clone an existing histogram and insert it into the registry + template <typename T> + void insertClone(const char* name, const std::shared_ptr<T>& originalHist) + { + const uint32_t id = compile_time_hash(name); + uint32_t i = imask(id); + for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + TObject* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); + if (!rawPtr) { + mRegistryKey[imask(j + i)] = id; + mRegistryValue[imask(j + i)] = std::shared_ptr<T>(static_cast<T*>(originalHist->Clone(name))); + lookup += j; + return; + } + } + LOGF(FATAL, "Internal array of HistogramRegistry %s is full.", mName); } inline constexpr uint32_t imask(uint32_t i) const { - return i & mask; + return i & MASK; } // helper function to create resp. find the subList defined by path @@ -615,16 +678,16 @@ class HistogramRegistry return pathAndName; } - std::string name{}; - bool enabled{}; - bool mCreateFolder{}; - OutputObjHandlingPolicy policy{}; - uint32_t taskHash{}; + std::string mName{}; + OutputObjHandlingPolicy mPolicy{}; + bool mCreateRegistryDir{}; + bool mSortHistos{}; + uint32_t mTaskHash{}; /// The maximum number of histograms in buffer is currently set to 512 /// which seems to be both reasonably large and allowing for very fast lookup - static constexpr uint32_t mask = 0x1FF; - static constexpr uint32_t MAX_REGISTRY_SIZE = mask + 1; + static constexpr uint32_t MASK{0x1FF}; + static constexpr uint32_t MAX_REGISTRY_SIZE{MASK + 1}; std::array<uint32_t, MAX_REGISTRY_SIZE> mRegistryKey{}; std::array<HistPtr, MAX_REGISTRY_SIZE> mRegistryValue{}; }; diff --git a/Framework/Core/test/benchmark_HistogramRegistry.cxx b/Framework/Core/test/benchmark_HistogramRegistry.cxx index 05c4d17047ec8..009d7eb35e462 100644 --- a/Framework/Core/test/benchmark_HistogramRegistry.cxx +++ b/Framework/Core/test/benchmark_HistogramRegistry.cxx @@ -32,7 +32,7 @@ static void BM_HashedNameLookup(benchmark::State& state) for (auto i = 0; i < state.range(0); ++i) { histSpecs.push_back({fmt::format("histo{}", i + 1).c_str(), fmt::format("Histo {}", i + 1).c_str(), {HistType::kTH1F, {{100, 0, 1}}}}); } - HistogramRegistry registry{"registry", true, histSpecs}; + HistogramRegistry registry{"registry", histSpecs}; state.ResumeTiming(); for (auto i = 0; i < nLookups; ++i) { diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 59227a8ba0388..39d5618392a2d 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -25,19 +25,19 @@ DECLARE_SOA_COLUMN_FULL(Y, y, float, "y"); HistogramRegistry foo() { - return {"r", true, {{"histo", "histo", {HistType::kTH1F, {{100, 0, 1}}}}}}; + return {"r", {{"histo", "histo", {HistType::kTH1F, {{100, 0, 1}}}}}}; } BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) { /// Construct a registry object with direct declaration HistogramRegistry registry{ - "registry", true, { - {"eta", "#Eta", {HistType::kTH1F, {{100, -2.0, 2.0}}}}, // - {"phi", "#Phi", {HistType::kTH1D, {{102, 0, 2 * M_PI}}}}, // - {"pt", "p_{T}", {HistType::kTH1D, {{1002, -0.01, 50.1}}}}, // - {"ptToPt", "#ptToPt", {HistType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // - } // + "registry", { + {"eta", "#Eta", {HistType::kTH1F, {{100, -2.0, 2.0}}}}, // + {"phi", "#Phi", {HistType::kTH1D, {{102, 0, 2 * M_PI}}}}, // + {"pt", "p_{T}", {HistType::kTH1D, {{1002, -0.01, 50.1}}}}, // + {"ptToPt", "#ptToPt", {HistType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} // + } // }; /// Get histograms by name @@ -77,10 +77,10 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryExpressionFill) /// Construct a registry object with direct declaration HistogramRegistry registry{ - "registry", true, { - {"x", "test x", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, // - {"xy", "test xy", {HistType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}} // - } // + "registry", { + {"x", "test x", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, // + {"xy", "test xy", {HistType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}} // + } // }; /// Fill histogram with expression and table From 2c620af17133907d5e7f150753cb63eaac2cfe1b Mon Sep 17 00:00:00 2001 From: Nazar <nazar.burmasov@cern.ch> Date: Sat, 24 Oct 2020 18:27:17 +0300 Subject: [PATCH 1091/1751] Preliminary version of AOD producer workflow (#4637) --- Detectors/AOD/CMakeLists.txt | 29 ++ .../AODProducerWorkflow/AODProducerWorkflow.h | 24 ++ .../AODProducerWorkflowSpec.h | 84 +++++ Detectors/AOD/src/AODProducerWorkflow.cxx | 56 +++ Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 349 ++++++++++++++++++ Detectors/AOD/src/aod-producer-workflow.cxx | 23 ++ 6 files changed, 565 insertions(+) create mode 100644 Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflow.h create mode 100644 Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h create mode 100644 Detectors/AOD/src/AODProducerWorkflow.cxx create mode 100644 Detectors/AOD/src/AODProducerWorkflowSpec.cxx create mode 100644 Detectors/AOD/src/aod-producer-workflow.cxx diff --git a/Detectors/AOD/CMakeLists.txt b/Detectors/AOD/CMakeLists.txt index 626fcd8ef7258..9cab93768602f 100644 --- a/Detectors/AOD/CMakeLists.txt +++ b/Detectors/AOD/CMakeLists.txt @@ -8,6 +8,33 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +o2_add_library( + AODProducerWorkflow + SOURCES src/AODProducerWorkflow.cxx + src/AODProducerWorkflowSpec.cxx + PUBLIC_LINK_LIBRARIES + O2::AnalysisDataModel + O2::DetectorsVertexing + O2::Framework + O2::FT0Workflow + O2::GlobalTracking + O2::GlobalTrackingWorkflow + O2::ITSMFTWorkflow + O2::ITStracking + O2::ITSWorkflow + O2::SimulationDataFormat + O2::Steer + O2::TOFWorkflow + O2::TPCWorkflow +) + +o2_add_executable( + workflow + COMPONENT_NAME aod-producer + SOURCES src/aod-producer-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::AODProducerWorkflow +) + o2_add_executable( standalone-aod-producer COMPONENT_NAME reco @@ -32,3 +59,5 @@ o2_add_executable( O2::Steer ) + + diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflow.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflow.h new file mode 100644 index 0000000000000..c9ce6f23400b3 --- /dev/null +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflow.h @@ -0,0 +1,24 @@ +// 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_AODPRODUCER_WORKFLOW_H +#define O2_AODPRODUCER_WORKFLOW_H + +/// @file AODProducerWorkflow.h + +#include "Framework/WorkflowSpec.h" + +namespace o2::aodproducer +{ + +framework::WorkflowSpec getAODProducerWorkflow(); + +} // namespace o2::aodproducer +#endif diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h new file mode 100644 index 0000000000000..77053713e74a0 --- /dev/null +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -0,0 +1,84 @@ +// 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 AODProducerWorkflowSpec.h + +#ifndef O2_AODPRODUCER_WORKFLOW_SPEC +#define O2_AODPRODUCER_WORKFLOW_SPEC + +#include "DataFormatsFT0/RecPoints.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "TStopwatch.h" +#include <string> +#include <vector> + +using namespace o2::framework; + +namespace o2::aodproducer +{ + +using TracksTable = o2::soa::Table<o2::aod::track::CollisionId, + o2::aod::track::TrackType, + o2::aod::track::X, + o2::aod::track::Alpha, + o2::aod::track::Y, + o2::aod::track::Z, + o2::aod::track::Snp, + o2::aod::track::Tgl, + o2::aod::track::Signed1Pt, + o2::aod::track::SigmaY, + o2::aod::track::SigmaZ, + o2::aod::track::SigmaSnp, + o2::aod::track::SigmaTgl, + o2::aod::track::Sigma1Pt, + o2::aod::track::RhoZY, + o2::aod::track::RhoSnpY, + o2::aod::track::RhoSnpZ, + o2::aod::track::RhoTglY, + o2::aod::track::RhoTglZ, + o2::aod::track::RhoTglSnp, + o2::aod::track::Rho1PtY, + o2::aod::track::Rho1PtZ, + o2::aod::track::Rho1PtSnp, + o2::aod::track::Rho1PtTgl>; + +class AODProducerWorkflowDPL : public Task +{ + public: + AODProducerWorkflowDPL() = default; + ~AODProducerWorkflowDPL() override = default; + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + void endOfStream(framework::EndOfStreamContext& ec) final; + + private: + int mFillTracksITS = 1; + int mFillTracksTPC = 1; + int mFillTracksITSTPC = 1; + TStopwatch mTimer; + + uint64_t maxGlBC = 0; + uint64_t minGlBC = INT64_MAX; + + void findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC); + + template <typename TracksType, typename TracksCursorType> + void fillTracksTable(const TracksType& tracks, std::vector<int>& vCollRefs, const TracksCursorType& tracksCursor, int trackType); +}; + +/// create a processor spec +framework::DataProcessorSpec getAODProducerWorkflowSpec(); + +} // namespace o2::aodproducer + +#endif /* O2_AODPRODUCER_WORKFLOW_SPEC */ diff --git a/Detectors/AOD/src/AODProducerWorkflow.cxx b/Detectors/AOD/src/AODProducerWorkflow.cxx new file mode 100644 index 0000000000000..cc1d052ab2626 --- /dev/null +++ b/Detectors/AOD/src/AODProducerWorkflow.cxx @@ -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 AODProducerWorkflow.cxx + +#include "Algorithm/RangeTokenizer.h" +#include "AODProducerWorkflow/AODProducerWorkflow.h" +#include "AODProducerWorkflow/AODProducerWorkflowSpec.h" +#include "DataFormatsTPC/Constants.h" +#include "FT0Workflow/DigitReaderSpec.h" +#include "FT0Workflow/ReconstructionSpec.h" +#include "GlobalTracking/MatchTPCITSParams.h" +#include "GlobalTrackingWorkflow/MatchTPCITSWorkflow.h" +#include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" +#include "GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h" +#include "GlobalTrackingWorkflow/TPCITSMatchingSpec.h" +#include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" +#include "GlobalTrackingWorkflow/TrackWriterTPCITSSpec.h" +#include "ITSMFTWorkflow/ClusterReaderSpec.h" +#include "ITSWorkflow/TrackReaderSpec.h" +#include "TPCWorkflow/PublisherSpec.h" +#include "TPCWorkflow/TrackReaderSpec.h" + +namespace o2::aodproducer +{ + +framework::WorkflowSpec getAODProducerWorkflow() +{ + // TODO: + // switch to configurable parameters (?) + bool useFT0 = true; + bool useMC = false; + + // FIXME: + // switch (?) from o2::ft0::getReconstructionSpec to RecPointReader + // (which does not return RECCHDATA at the moment) + framework::WorkflowSpec specs{ + o2::vertexing::getPrimaryVertexingSpec(useFT0, useMC), + o2::globaltracking::getTrackTPCITSReaderSpec(useMC), + o2::its::getITSTrackReaderSpec(useMC), + o2::tpc::getTPCTrackReaderSpec(useMC), + o2::ft0::getDigitReaderSpec(useMC), + o2::ft0::getReconstructionSpec(useMC), + o2::aodproducer::getAODProducerWorkflowSpec()}; + + return specs; +} + +} // namespace o2::aodproducer diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx new file mode 100644 index 0000000000000..b9eabb7f7df9b --- /dev/null +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -0,0 +1,349 @@ +// 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 AODProducerWorkflowSpec.cxx + +#include "AODProducerWorkflow/AODProducerWorkflowSpec.h" +#include "DataFormatsFT0/RecPoints.h" +#include "DataFormatsITS/TrackITS.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/DataTypes.h" +#include "Framework/InputRecordWalker.h" +#include "Framework/Logger.h" +#include "Framework/TableBuilder.h" +#include "Framework/TableTreeHelpers.h" +#include "GlobalTracking/MatchTOF.h" +#include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" +#include "Headers/DataHeader.h" +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "SimulationDataFormat/DigitizationContext.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCEventHeader.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "Steer/MCKinematicsReader.h" +#include "TMath.h" +#include <map> +#include <vector> + +using namespace o2::framework; + +namespace o2::aodproducer +{ + +void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC) +{ + for (auto& ft0RecPoint : ft0RecPoints) { + uint64_t bc = ft0RecPoint.getInteractionRecord().orbit * o2::constants::lhc::LHCMaxBunches + ft0RecPoint.getInteractionRecord().bc; + if (minGlBC > bc) { + minGlBC = bc; + } + if (maxGlBC < bc) { + maxGlBC = bc; + } + } + + for (auto& trackITSTPC : tracksITSTPC) { + Double_t timeStamp = trackITSTPC.getTimeMUS().getTimeStamp() * 1.E3; // ms to ns + uint64_t bc = (int)(timeStamp / o2::constants::lhc::LHCBunchSpacingNS); + if (minGlBC > bc) { + minGlBC = bc; + } + if (maxGlBC < bc) { + maxGlBC = bc; + } + } +} + +template <typename TracksType, typename TracksCursorType> +void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vector<int>& vCollRefs, const TracksCursorType& tracksCursor, int trackType) +{ + for (int i = 0; i < tracks.size(); i++) { + auto& track = tracks[i]; + int collisionID = vCollRefs[i]; + tracksCursor(0, + collisionID, + trackType, + track.getX(), + track.getAlpha(), + track.getY(), + track.getZ(), + track.getSnp(), + track.getTgl(), + track.getQ2Pt(), + TMath::Sqrt(track.getSigmaY2()), + TMath::Sqrt(track.getSigmaZ2()), + TMath::Sqrt(track.getSigmaSnp2()), + TMath::Sqrt(track.getSigmaTgl2()), + TMath::Sqrt(track.getSigma1Pt2()), + (Char_t)(128. * track.getSigmaZY() / track.getSigmaZ2() / track.getSigmaY2()), + (Char_t)(128. * track.getSigmaSnpY() / track.getSigmaSnp2() / track.getSigmaY2()), + (Char_t)(128. * track.getSigmaSnpZ() / track.getSigmaSnp2() / track.getSigmaZ2()), + (Char_t)(128. * track.getSigmaTglY() / track.getSigmaTgl2() / track.getSigmaY2()), + (Char_t)(128. * track.getSigmaTglZ() / track.getSigmaTgl2() / track.getSigmaZ2()), + (Char_t)(128. * track.getSigmaTglSnp() / track.getSigmaTgl2() / track.getSigmaSnp2()), + (Char_t)(128. * track.getSigma1PtY() / track.getSigma1Pt2() / track.getSigmaY2()), + (Char_t)(128. * track.getSigma1PtZ() / track.getSigma1Pt2() / track.getSigmaZ2()), + (Char_t)(128. * track.getSigma1PtSnp() / track.getSigma1Pt2() / track.getSigmaSnp2()), + (Char_t)(128. * track.getSigma1PtTgl() / track.getSigma1Pt2() / track.getSigmaTgl2())); + } +} + +void AODProducerWorkflowDPL::init(InitContext& ic) +{ + mTimer.Stop(); + + mFillTracksITS = ic.options().get<int>("fill-tracks-its"); + mFillTracksTPC = ic.options().get<int>("fill-tracks-tpc"); + mFillTracksITSTPC = ic.options().get<int>("fill-tracks-its-tpc"); + LOG(INFO) << "track filling flags set to: " + << "\n ITS = " << mFillTracksITS << "\n TPC = " << mFillTracksTPC << "\n ITSTPC = " << mFillTracksITSTPC; + + mTimer.Reset(); +} + +void AODProducerWorkflowDPL::run(ProcessingContext& pc) +{ + mTimer.Start(false); + + auto ft0ChData = pc.inputs().get<gsl::span<o2::ft0::ChannelDataFloat>>("ft0ChData"); + auto ft0RecPoints = pc.inputs().get<gsl::span<o2::ft0::RecPoints>>("ft0RecPoints"); + auto primVer2TRefs = pc.inputs().get<gsl::span<o2::vertexing::V2TRef>>("primVer2TRefs"); + auto primVerGIs = pc.inputs().get<gsl::span<o2::vertexing::GIndex>>("primVerGIs"); + auto primVertices = pc.inputs().get<gsl::span<o2::vertexing::PVertex>>("primVertices"); + auto tracksITS = pc.inputs().get<gsl::span<o2::its::TrackITS>>("trackITS"); + auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("tracksITSTPC"); + auto tracksTPC = pc.inputs().get<gsl::span<o2::tpc::TrackTPC>>("trackTPC"); + + LOG(INFO) << "FOUND " << tracksTPC.size() << " TPC tracks"; + LOG(INFO) << "FOUND " << tracksITS.size() << " ITS tracks"; + LOG(INFO) << "FOUND " << tracksITSTPC.size() << " ITCTPC tracks"; + + auto& bcBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "BC"}); + auto& collisionsBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "COLLISION"}); + auto& ft0Builder = pc.outputs().make<TableBuilder>(Output{"AOD", "FT0"}); + auto& mcCollisionsBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "MCCOLLISION"}); + auto& tracksBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "TRACK"}); + + // TODO: + // add FV0A, FV0C, FDD tables + // auto& fv0aBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0A"}); + // auto& fv0cBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0C"}); + // auto& fddBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FDD"}); + + auto bcCursor = bcBuilder.cursor<o2::aod::BCs>(); + auto collisionsCursor = collisionsBuilder.cursor<o2::aod::Collisions>(); + auto ft0Cursor = ft0Builder.cursor<o2::aod::FT0s>(); + auto mcCollisionsCursor = mcCollisionsBuilder.cursor<o2::aod::McCollisions>(); + auto tracksCursor = tracksBuilder.cursor<o2::aodproducer::TracksTable>(); + + // TODO: + // add FV0A, FV0C, FDD tables + // auto fv0aCursor = fv0aBuilder.cursor<o2::aod::FV0As>(); + // auto fv0cCursor = fv0cBuilder.cursor<o2::aod::FV0Cs>(); + // auto fddCursor = fddBuilder.cursor<o2::aod::FDDs>(); + + // float dummyfv0AmplA[48] = {0.}; + // float dummyfv0AmplC[32] = {0.}; + // float dummyfddAmplA[4] = {0.}; + // float dummyfddAmplC[4] = {0.}; + // fv0aCursor(0, (uint64_t)0, dummyfv0AmplA, 0.f, (uint8_t)0); + // fv0cCursor(0, (uint64_t)0, dummyfv0AmplC, 0.f); + // fddCursor(0, (uint64_t)0, dummyfddAmplA, dummyfddAmplC, 0.f, 0.f, (uint8_t)0); + + o2::steer::MCKinematicsReader mcReader("collisioncontext.root"); + const auto context = mcReader.getDigitizationContext(); + const auto& records = context->getEventRecords(); + const auto& parts = context->getEventParts(); + + LOG(INFO) << "FOUND " << records.size() << " records"; + LOG(INFO) << "FOUND " << parts.size() << " parts"; + + // TODO: + // change index to BCId (?) + // figure out generatorID and collision weight + int index = 0; + int generatorID = 0; + float mcColWeight = 1.; + + // filling mcCollison table + for (auto& rec : records) { + auto time = rec.getTimeNS(); + auto& colparts = parts[index]; + auto eventID = colparts[0].entryID; + auto sourceID = colparts[0].sourceID; + auto& header = mcReader.getMCEventHeader(sourceID, eventID); + mcCollisionsCursor(0, + index, + generatorID, + header.GetX(), + header.GetY(), + header.GetZ(), + time, + mcColWeight, + header.GetB()); + index++; + } + + findMinMaxBc(ft0RecPoints, tracksITSTPC); + + std::map<uint64_t, uint64_t> mGlobBC2BCID; + + // TODO: + // get real run number and triggerMask + int runNumber = 244918; + uint64_t triggerMask = 1; + + // filling BC table and map<globalBC, BCId> + for (uint64_t i = 0; i <= maxGlBC - minGlBC; i++) { + bcCursor(0, + runNumber, + minGlBC + i, + triggerMask); + mGlobBC2BCID[minGlBC + i] = i; + } + + // vector of FT0 amplitudes + std::vector<float> vAmplitudes(208, 0.); + // filling FT0 table + for (auto& ft0RecPoint : ft0RecPoints) { + const auto channelData = ft0RecPoint.getBunchChannelData(ft0ChData); + // TODO: + // switch to calibrated amplitude + for (auto& channel : channelData) { + vAmplitudes[channel.ChId] = channel.QTCAmpl; // amplitude, mV + } + float aAmplitudesA[96]; + float aAmplitudesC[112]; + std::copy(vAmplitudes.begin(), vAmplitudes.begin() + 95, aAmplitudesA); + std::copy(vAmplitudes.begin() + 96, vAmplitudes.end(), aAmplitudesC); + uint64_t globalBC = ft0RecPoint.getInteractionRecord().orbit * o2::constants::lhc::LHCMaxBunches + ft0RecPoint.getInteractionRecord().bc; + ft0Cursor(0, + mGlobBC2BCID[globalBC], + aAmplitudesA, + aAmplitudesC, + ft0RecPoint.getCollisionTimeA() / 1E3, // ps to ns + ft0RecPoint.getCollisionTimeC() / 1E3, // ps to ns + ft0RecPoint.getTrigger().triggersignals); + } + + // initializing vectors for trackID --> collisionID connection + std::vector<int> vCollRefsITS(tracksITS.size(), -1); + std::vector<int> vCollRefsTPC(tracksTPC.size(), -1); + std::vector<int> vCollRefsTPCITS(tracksITSTPC.size(), -1); + + // filling collisions table + int collisionID = 0; + for (auto& vertex : primVertices) { + auto& cov = vertex.getCov(); + auto& timeStamp = vertex.getTimeStamp(); + Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // ms to ns + uint64_t globalBC = tsTimeStamp / o2::constants::lhc::LHCBunchSpacingNS; + int BCid = mGlobBC2BCID[globalBC]; + // TODO: + // get real collision time mask + int collisionTimeMask = 1; + collisionsCursor(0, + BCid, + vertex.getX(), + vertex.getY(), + vertex.getZ(), + cov[0], + cov[1], + cov[2], + cov[3], + cov[4], + cov[5], + vertex.getChi2(), + vertex.getNContributors(), + timeStamp.getTimeStamp(), + timeStamp.getTimeStampError(), + collisionTimeMask); + auto trackRef = primVer2TRefs[collisionID]; + int start = trackRef.getFirstEntryOfSource(0); + int ntracks = trackRef.getEntriesOfSource(0); + for (int ti = 0; ti < ntracks; ti++) { + auto trackIndex = primVerGIs[start + ti]; + const auto source = trackIndex.getSource(); + // setting collisionID for tracks attached to vertices + if (source == o2::vertexing::GIndex::Source::TPC) { + vCollRefsTPC[trackIndex.getIndex()] = collisionID; + } else if (source == o2::vertexing::GIndex::Source::ITS) { + vCollRefsITS[trackIndex.getIndex()] = collisionID; + } else if (source == o2::vertexing::GIndex::Source::TPCITS) { + vCollRefsTPCITS[trackIndex.getIndex()] = collisionID; + } else { + LOG(WARNING) << "Unsupported track type!"; + } + } + collisionID++; + } + + // filling tracks tables + if (mFillTracksITS) { + fillTracksTable(tracksITS, vCollRefsITS, tracksCursor, o2::vertexing::GIndex::Source::ITS); // fTrackType = 1 + } + if (mFillTracksTPC) { + fillTracksTable(tracksTPC, vCollRefsTPC, tracksCursor, o2::vertexing::GIndex::Source::TPC); // fTrackType = 2 + } + if (mFillTracksITSTPC) { + fillTracksTable(tracksITSTPC, vCollRefsTPCITS, tracksCursor, o2::vertexing::GIndex::Source::TPCITS); // fTrackType = 0 + } + + mTimer.Stop(); +} + +void AODProducerWorkflowDPL::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "aod producer dpl total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getAODProducerWorkflowSpec() +{ + std::vector<InputSpec> inputs; + std::vector<OutputSpec> outputs; + + inputs.emplace_back("ft0ChData", "FT0", "RECCHDATA", 0, Lifetime::Timeframe); + inputs.emplace_back("ft0RecPoints", "FT0", "RECPOINTS", 0, Lifetime::Timeframe); + inputs.emplace_back("primVer2TRefs", "GLO", "PVTX_CONTIDREFS", 0, Lifetime::Timeframe); + inputs.emplace_back("primVerGIs", "GLO", "PVTX_CONTID", 0, Lifetime::Timeframe); + inputs.emplace_back("primVertices", "GLO", "PVTX", 0, Lifetime::Timeframe); + inputs.emplace_back("trackITS", "ITS", "TRACKS", 0, Lifetime::Timeframe); + inputs.emplace_back("tracksITSTPC", "GLO", "TPCITS", 0, Lifetime::Timeframe); + inputs.emplace_back("trackTPC", "TPC", "TRACKS", 0, Lifetime::Timeframe); + + outputs.emplace_back(OutputLabel{"O2bc"}, "AOD", "BC", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2collision"}, "AOD", "COLLISION", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2ft0"}, "AOD", "FT0", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2mccollision"}, "AOD", "MCCOLLISION", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2track"}, "AOD", "TRACK", 0, Lifetime::Timeframe); + + // TODO: + // add FV0A, FV0C, FDD tables + // outputs.emplace_back(OutputLabel{"O2fv0a"}, "AOD", "FV0A", 0, Lifetime::Timeframe); + // outputs.emplace_back(OutputLabel{"O2fv0c"}, "AOD", "FV0C", 0, Lifetime::Timeframe); + // outputs.emplace_back(OutputLabel{"O2fdd"}, "AOD", "FDD", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "aod-producer-workflow", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<AODProducerWorkflowDPL>()}, + Options{ + ConfigParamSpec{"fill-tracks-its", VariantType::Int, 1, {"Fill ITS tracks into tracks table"}}, + ConfigParamSpec{"fill-tracks-tpc", VariantType::Int, 1, {"Fill TPC tracks into tracks table"}}, + ConfigParamSpec{"fill-tracks-its-tpc", VariantType::Int, 1, {"Fill ITS-TPC tracks into tracks table"}}}}; +} + +} // namespace o2::aodproducer diff --git a/Detectors/AOD/src/aod-producer-workflow.cxx b/Detectors/AOD/src/aod-producer-workflow.cxx new file mode 100644 index 0000000000000..62226f01db3bf --- /dev/null +++ b/Detectors/AOD/src/aod-producer-workflow.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 "AODProducerWorkflow/AODProducerWorkflow.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" + +using namespace o2::framework; + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + return std::move(o2::aodproducer::getAODProducerWorkflow()); +} From 86374b1af1065c8a7b6cbcbab670b47f06176613 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 24 Oct 2020 00:02:39 +0200 Subject: [PATCH 1092/1751] Add option for shm-segment-id --- Framework/Core/src/DeviceSpecHelpers.cxx | 2 ++ Framework/Core/test/test_FrameworkDataFlowToDDS.cxx | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index f6513e2b01984..f1365407c088a 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -983,6 +983,7 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, realOdesc.add_options()("shm-mlock-segment", bpo::value<std::string>()); realOdesc.add_options()("shm-zero-segment", bpo::value<std::string>()); realOdesc.add_options()("shm-throw-bad-alloc", bpo::value<std::string>()); + realOdesc.add_options()("shm-segment-id", bpo::value<std::string>()); realOdesc.add_options()("shm-monitor", bpo::value<std::string>()); realOdesc.add_options()("session", bpo::value<std::string>()); filterArgsFct(expansions.we_wordc, expansions.we_wordv, realOdesc); @@ -1098,6 +1099,7 @@ boost::program_options::options_description DeviceSpecHelpers::getForwardedDevic ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // ("shm-zero-segment", bpo::value<std::string>()->default_value("false"), "zero shared memory segment") // ("shm-throw-bad-alloc", bpo::value<std::string>()->default_value("true"), "throw if insufficient shm memory") // + ("shm-segment-id", bpo::value<std::string>()->default_value("0"), "shm segment id") // ("environment", bpo::value<std::string>(), "comma separated list of environment variables to set for the device") // ("post-fork-command", bpo::value<std::string>(), "post fork command to execute (e.g. numactl {pid}") // ("session", bpo::value<std::string>(), "unique label for the shared memory session") // diff --git a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx index 784adf5533015..2b03b3a0cc5e3 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx @@ -97,16 +97,16 @@ BOOST_AUTO_TEST_CASE(TestDDS) dumpDeviceSpec2DDS(ss, devices, executions); BOOST_CHECK_EQUAL(ss.str(), R"EXPECTED(<topology name="o2-dataflow"> <decltask name="A"> - <exe reachable="true">foo --id A --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id A --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-segment-id 0 --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="B"> - <exe reachable="true">foo --id B --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id B --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-segment-id 0 --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="C"> - <exe reachable="true">foo --id C --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id C --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-segment-id 0 --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <decltask name="D"> - <exe reachable="true">foo --id D --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> + <exe reachable="true">foo --id D --control static --shm-monitor false --log-color false --color false --jobs 4 --severity info --shm-mlock-segment false --shm-segment-id 0 --shm-throw-bad-alloc true --shm-zero-segment false --session dpl_workflow-id --plugin-search-path $FAIRMQ_ROOT/lib --plugin dds</exe> </decltask> <declcollection name="DPL"> <tasks> From fd1d76308ed53fb562f25728ac1ca37f6f7aa3fc Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 24 Oct 2020 23:58:47 +0200 Subject: [PATCH 1093/1751] Add fixed margin to projected size of rANS encoder output --- .../Common/include/DetectorsCommonDataFormats/EncodedBlocks.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index 6f8141cb95edc..db9e0666e2866 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -775,6 +775,7 @@ void EncodedBlocks<H, N, W>::encode(const S_IT srcBegin, // iterator begin o // case 3: message where entropy coding should be applied if (opt == Metadata::OptStore::EENCODE) { // build symbol statistics + constexpr size_t SizeEstMargin = 1024; const o2::rans::LiteralEncoder64<STYP>* encoder = reinterpret_cast<const o2::rans::LiteralEncoder64<STYP>*>(encoderExt); std::unique_ptr<o2::rans::LiteralEncoder64<STYP>> encoderLoc; std::unique_ptr<o2::rans::FrequencyTable> frequencies = nullptr; @@ -790,7 +791,7 @@ void EncodedBlocks<H, N, W>::encode(const S_IT srcBegin, // iterator begin o // estimate size of encode buffer int dataSize = rans::calculateMaxBufferSize(messageLength, encoder->getAlphabetRangeBits(), sizeof(STYP)); // size in bytes // preliminary expansion of storage based on dict size + estimated size of encode buffer - dataSize = dataSize / sizeof(W) + (sizeof(STYP) < sizeof(W)); // size in words of output stream + dataSize = SizeEstMargin + dataSize / sizeof(W) + (sizeof(STYP) < sizeof(W)); // size in words of output stream expandStorage(dictSize + dataSize); //store dictionary first if (dictSize) { From a0e1aa2513208bd3b52e03c78b1fc5c0563e8394 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 24 Oct 2020 00:31:24 +0200 Subject: [PATCH 1094/1751] Allow skipping MC in MID ditis reader and do this in DigitsToRawWorkflow --- .../include/MIDWorkflow/DigitReaderSpec.h | 2 +- .../MUON/MID/Workflow/src/DigitReaderSpec.cxx | 34 +++++++++++++------ .../MID/Workflow/src/DigitsToRawWorkflow.cxx | 2 +- .../MUON/MID/Workflow/src/RawWriterSpec.cxx | 2 +- .../MUON/MID/Workflow/src/RecoWorkflowMC.cxx | 2 +- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h index 9fb82249b7a41..dbcee885b3b0b 100644 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h @@ -22,7 +22,7 @@ namespace o2 { namespace mid { -framework::DataProcessorSpec getDigitReaderSpec(); +framework::DataProcessorSpec getDigitReaderSpec(bool useMC); } } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx b/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx index c69ba2b03dbd8..1008ee6c712b9 100644 --- a/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx @@ -38,6 +38,8 @@ namespace mid class DigitsReaderDeviceDPL { public: + DigitsReaderDeviceDPL(bool useMC = true) : mUseMC(useMC) {} + void init(o2::framework::InitContext& ic) { auto filename = ic.options().get<std::string>("mid-digit-infile"); @@ -54,7 +56,9 @@ class DigitsReaderDeviceDPL return; } mTree->SetBranchAddress("MIDDigit", &mDigits); - mTree->SetBranchAddress("MIDDigitMCLabels", &mMCContainer); + if (mUseMC) { + mTree->SetBranchAddress("MIDDigitMCLabels", &mMCContainer); + } mTree->SetBranchAddress("MIDROFRecords", &mROFRecords); mState = 0; } @@ -72,16 +76,19 @@ class DigitsReaderDeviceDPL for (auto ientry = 0; ientry < mTree->GetEntries(); ++ientry) { mTree->GetEntry(ientry); digits.insert(digits.end(), mDigits->begin(), mDigits->end()); - mcContainer.mergeAtBack(*mMCContainer); rofRecords.insert(rofRecords.end(), mROFRecords->begin(), mROFRecords->end()); + if (mUseMC) { + mcContainer.mergeAtBack(*mMCContainer); + } } LOG(DEBUG) << "MIDDigitsReader pushed " << digits.size() << " merged digits"; pc.outputs().snapshot(of::Output{"MID", "DATA", 0, of::Lifetime::Timeframe}, digits); pc.outputs().snapshot(of::Output{"MID", "DATAROF", 0, of::Lifetime::Timeframe}, rofRecords); - LOG(DEBUG) << "MIDDigitsReader pushed " << mcContainer.getIndexedSize() << " indexed digits"; - pc.outputs().snapshot(of::Output{"MID", "DATALABELS", 0, of::Lifetime::Timeframe}, mcContainer); - + LOG(DEBUG) << "MIDDigitsReader pushed " << digits.size() << " indexed digits"; + if (mUseMC) { + pc.outputs().snapshot(of::Output{"MID", "DATALABELS", 0, of::Lifetime::Timeframe}, mcContainer); + } mState = 2; pc.services().get<of::ControlService>().endOfStream(); } @@ -93,18 +100,23 @@ class DigitsReaderDeviceDPL o2::dataformats::MCTruthContainer<MCLabel>* mMCContainer{nullptr}; // not owner std::vector<o2::mid::ROFRecord>* mROFRecords{nullptr}; // not owner int mState = 0; + bool mUseMC = true; }; -framework::DataProcessorSpec getDigitReaderSpec() +framework::DataProcessorSpec getDigitReaderSpec(bool useMC) { + std::vector<of::OutputSpec> outputs; + outputs.emplace_back("MID", "DATA", o2::framework::Lifetime::Timeframe); + outputs.emplace_back("MID", "DATAROF", o2::framework::Lifetime::Timeframe); + if (useMC) { + outputs.emplace_back("MID", "DATALABELS", o2::framework::Lifetime::Timeframe); + } + return of::DataProcessorSpec{ "MIDDigitsReader", of::Inputs{}, - of::Outputs{ - of::OutputSpec{"MID", "DATA"}, - of::OutputSpec{"MID", "DATAROF"}, - of::OutputSpec{"MID", "DATALABELS"}}, - of::AlgorithmSpec{of::adaptFromTask<o2::mid::DigitsReaderDeviceDPL>()}, + outputs, + of::AlgorithmSpec{of::adaptFromTask<o2::mid::DigitsReaderDeviceDPL>(useMC)}, of::Options{ {"mid-digit-infile", of::VariantType::String, "middigits.root", {"Name of the input file"}}}}; } diff --git a/Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx b/Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx index b1b8c89794a40..f81520acefbd0 100644 --- a/Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx @@ -30,7 +30,7 @@ of::WorkflowSpec getDigitsToRawWorkflow() { of::WorkflowSpec specs; - specs.emplace_back(getDigitReaderSpec()); + specs.emplace_back(getDigitReaderSpec(false)); specs.emplace_back(getRawWriterSpec()); return specs; } diff --git a/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx b/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx index 159176026b143..6444952c8d643 100644 --- a/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx @@ -89,7 +89,7 @@ class RawWriterDeviceDPL framework::DataProcessorSpec getRawWriterSpec() { - std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_data", header::gDataOriginMID, "DATA"}, of::InputSpec{"mid_data_rof", header::gDataOriginMID, "DATAROF"}, of::InputSpec{"mid_data_labels", header::gDataOriginMID, "DATALABELS"}}; + std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_data", header::gDataOriginMID, "DATA"}, of::InputSpec{"mid_data_rof", header::gDataOriginMID, "DATAROF"}}; return of::DataProcessorSpec{ "MIDRawWriter", diff --git a/Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx b/Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx index cb0e9d06bcf60..fa02d86cb76bc 100644 --- a/Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx +++ b/Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx @@ -47,7 +47,7 @@ of::WorkflowSpec getRecoWorkflowMC() of::WorkflowSpec specs; - specs.emplace_back(getDigitReaderSpec()); + specs.emplace_back(getDigitReaderSpec(true)); specs.emplace_back(getClusterizerMCSpec()); specs.emplace_back(getTrackerMCSpec()); specs.emplace_back(of::MakeRootTreeWriterSpec("MIDTrackLabelsWriter", From f5f2c84ef02ab64fa14f8112088c81ca15427c1e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 25 Oct 2020 00:41:31 +0200 Subject: [PATCH 1095/1751] option to disable MID tracks output to root file --- .../include/MIDWorkflow/RecoWorkflow.h | 2 +- .../MUON/MID/Workflow/src/RecoWorkflow.cxx | 22 ++++++++++--------- .../MID/Workflow/src/mid-reco-workflow.cxx | 6 +++-- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h index d35367efa83e3..c7485bc53a60b 100644 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h @@ -23,7 +23,7 @@ namespace o2 { namespace mid { -framework::WorkflowSpec getRecoWorkflow(bool ctfInput); +framework::WorkflowSpec getRecoWorkflow(bool ctfInput, bool disableRootOut); } } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx b/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx index 90ad7f7f21e80..b46a5d4ee3e72 100644 --- a/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx @@ -29,7 +29,7 @@ namespace o2 namespace mid { -of::WorkflowSpec getRecoWorkflow(bool ctf) +of::WorkflowSpec getRecoWorkflow(bool ctf, bool disableRootOut) { auto checkReady = [](o2::framework::DataRef const& ref) { @@ -50,15 +50,17 @@ of::WorkflowSpec getRecoWorkflow(bool ctf) } specs.emplace_back(getClusterizerSpec()); specs.emplace_back(getTrackerSpec()); - specs.emplace_back(of::MakeRootTreeWriterSpec("MIDTracksWriter", - "mid-tracks.root", - "midtracks", - of::MakeRootTreeWriterSpec::TerminationPolicy::Process, - of::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_tracks", "MID", "TRACKS"}, "MIDTrack"}, - of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_trackClusters", "MID", "TRACKCLUSTERS"}, "MIDTrackClusters"}, - of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_tracks_rof", "MID", "TRACKSROF"}, "MIDTrackROF"}, - of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_trclus_rof", "MID", "TRCLUSROF"}, "MIDTrackClusterROF"})()); + if (!disableRootOut) { + specs.emplace_back(of::MakeRootTreeWriterSpec("MIDTracksWriter", + "mid-tracks.root", + "midtracks", + of::MakeRootTreeWriterSpec::TerminationPolicy::Process, + of::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, + of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_tracks", "MID", "TRACKS"}, "MIDTrack"}, + of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_trackClusters", "MID", "TRACKCLUSTERS"}, "MIDTrackClusters"}, + of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_tracks_rof", "MID", "TRACKSROF"}, "MIDTrackROF"}, + of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_trclus_rof", "MID", "TRCLUSROF"}, "MIDTrackClusterROF"})()); + } return specs; } diff --git a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx b/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx index 8f6ca738487d4..493129902dd09 100644 --- a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx @@ -27,7 +27,8 @@ using namespace o2::framework; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { std::vector<ConfigParamSpec> options{ - {"input-ctf", VariantType::Bool, false, {"Input data comes from CTF"}}}; + {"input-ctf", VariantType::Bool, false, {"Input data comes from CTF"}}, + {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}}; std::swap(workflowOptions, options); std::string keyvaluehelp("Semicolon separated key=value strings ..."); @@ -46,5 +47,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // write the configuration used for the digitizer workflow o2::conf::ConfigurableParam::writeINI("o2mid-recoflow_configuration.ini"); auto ctf = configcontext.options().get<bool>("input-ctf"); - return std::move(o2::mid::getRecoWorkflow(ctf)); + auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); + return std::move(o2::mid::getRecoWorkflow(ctf, disableRootOut)); } From 0f1f867e51a065016981661fc97fc87007110a5c Mon Sep 17 00:00:00 2001 From: Artur Furs <afurs@cern.ch> Date: Wed, 21 Oct 2020 16:43:29 +0300 Subject: [PATCH 1096/1751] new FITRaw lib --- .../FIT/FT0/include/DataFormatsFT0/Digit.h | 23 ++++ .../FT0/include/DataFormatsFT0/RawEventData.h | 4 +- .../FIT/FT0/src/DataFormatsFT0LinkDef.h | 4 + Detectors/FIT/CMakeLists.txt | 1 + Detectors/FIT/FT0/raw/CMakeLists.txt | 4 +- .../FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h | 107 +++++++++++++++ .../FT0/raw/include/FT0Raw/DataBlockReader.h | 129 ------------------ .../FT0/raw/include/FT0Raw/DigitBlockFT0.h | 125 +++++++++++++++-- .../FT0/raw/include/FT0Raw/RawReaderFT0Base.h | 78 +++++++++++ .../{DataBlockRaw.cxx => DataBlockFT0.cxx} | 2 +- Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx | 2 + Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h | 6 +- ...taBlockReader.cxx => RawReaderFT0Base.cxx} | 2 +- Detectors/FIT/FT0/simulation/src/Detector.cxx | 2 +- Detectors/FIT/FT0/workflow/CMakeLists.txt | 1 + .../FT0Workflow/FT0DataReaderDPLSpec.h | 58 +++++--- .../include/FT0Workflow/FT0Workflow.h | 4 +- .../include/FT0Workflow/RawReaderFT0.h | 118 ++++++++++++++++ .../FT0/workflow/src/FT0DataReaderDPLSpec.cxx | 54 -------- .../FIT/FT0/workflow/src/FT0Workflow.cxx | 13 +- .../FIT/FT0/workflow/src/RawReaderFT0.cxx | 12 ++ .../FIT/FT0/workflow/src/ft0-flp-workflow.cxx | 2 +- Detectors/FIT/raw/CMakeLists.txt | 13 ++ Detectors/FIT/raw/README.md | 41 ++++++ .../include/FITRaw/DataBlockBase.h} | 129 +++++------------- .../FIT/raw/include/FITRaw/DigitBlockBase.h | 53 +++++++ .../FIT/raw/include/FITRaw/RawReaderBase.h | 95 +++++++++++++ Detectors/FIT/raw/src/DataBlockBase.cxx | 12 ++ Detectors/FIT/raw/src/DigitBlockBase.cxx | 12 ++ Detectors/FIT/raw/src/FITRawLinkDef.h | 24 ++++ Detectors/FIT/raw/src/RawReaderBase.cxx | 12 ++ 31 files changed, 814 insertions(+), 328 deletions(-) create mode 100644 Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h delete mode 100644 Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h create mode 100644 Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h rename Detectors/FIT/FT0/raw/src/{DataBlockRaw.cxx => DataBlockFT0.cxx} (93%) rename Detectors/FIT/FT0/raw/src/{DataBlockReader.cxx => RawReaderFT0Base.cxx} (93%) create mode 100644 Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h create mode 100644 Detectors/FIT/FT0/workflow/src/RawReaderFT0.cxx create mode 100644 Detectors/FIT/raw/CMakeLists.txt create mode 100644 Detectors/FIT/raw/README.md rename Detectors/FIT/{FT0/raw/include/FT0Raw/DataBlockRaw.h => raw/include/FITRaw/DataBlockBase.h} (74%) create mode 100644 Detectors/FIT/raw/include/FITRaw/DigitBlockBase.h create mode 100644 Detectors/FIT/raw/include/FITRaw/RawReaderBase.h create mode 100644 Detectors/FIT/raw/src/DataBlockBase.cxx create mode 100644 Detectors/FIT/raw/src/DigitBlockBase.cxx create mode 100644 Detectors/FIT/raw/src/FITRawLinkDef.h create mode 100644 Detectors/FIT/raw/src/RawReaderBase.cxx diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h index 68bd05ffae8bc..6279720661bc5 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h @@ -114,6 +114,29 @@ struct Digit { bool getStatusFlag(EEventStatus bit) const { return bool(mEventStatus << bit); } ClassDefNV(Digit, 4); }; + +//For TCM extended mode (calibration mode), TCMdataExtended digit +struct TriggersExt { + TriggersExt(uint32_t triggerWord) + { + mTriggerWord = triggerWord; + } + TriggersExt() = default; + uint32_t mTriggerWord; + ClassDefNV(TriggersExt, 1); +}; + +//For TCM extended mode (calibration mode) +struct DigitExt : Digit { + DigitExt(int first, int ne, int firstExt, int neExt, const o2::InteractionRecord& iRec, const Triggers& chTrig, int event) : Digit(first, ne, iRec, chTrig, event) + { + refExt.setFirstEntry(firstExt); + refExt.setEntries(neExt); + } + DigitExt() = default; + o2::dataformats::RangeReference<int, int> refExt; //range reference to container with TriggerExt objects + ClassDefNV(DigitExt, 1); +}; } // namespace ft0 } // namespace o2 diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h index e96e10ee07c9d..d163157e57ae1 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h @@ -205,14 +205,14 @@ struct TCMdata { struct TCMdataExtended { static constexpr size_t PayloadSize = 4; static constexpr size_t PayloadPerGBTword = 10; - static constexpr int MinNelements = 1; + static constexpr int MinNelements = 0; static constexpr int MaxNelements = 20; union { uint32_t word[1] = {}; uint32_t triggerWord; }; - void print() + void print() const { std::cout << std::hex; diff --git a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h index b3a0badf1fecd..4ecf56013a65a 100644 --- a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h +++ b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h @@ -15,13 +15,17 @@ #pragma link off all functions; #pragma link C++ class o2::ft0::Digit + ; +#pragma link C++ class o2::ft0::DigitExt + ; #pragma link C++ class o2::ft0::DigitsTemp + ; #pragma link C++ class o2::ft0::ChannelData + ; #pragma link C++ class o2::ft0::Triggers + ; +#pragma link C++ class o2::ft0::TriggersExt + ; #pragma link C++ class vector < o2::ft0::ChannelData> + ; #pragma link C++ class vector < o2::ft0::Digit> + ; +#pragma link C++ class vector < o2::ft0::DigitExt> + ; #pragma link C++ class vector < o2::ft0::DigitsTemp> + ; #pragma link C++ class vector < o2::ft0::Triggers> + ; +#pragma link C++ class vector < o2::ft0::TriggersExt> + ; #pragma link C++ class o2::ft0::RecPoints + ; #pragma link C++ class vector < o2::ft0::RecPoints> + ; diff --git a/Detectors/FIT/CMakeLists.txt b/Detectors/FIT/CMakeLists.txt index 16976f8e705bc..62bf1cd0a9b11 100644 --- a/Detectors/FIT/CMakeLists.txt +++ b/Detectors/FIT/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(FT0) add_subdirectory(common) +add_subdirectory(raw) add_subdirectory(FV0) add_subdirectory(FDD) add_subdirectory(macros) diff --git a/Detectors/FIT/FT0/raw/CMakeLists.txt b/Detectors/FIT/FT0/raw/CMakeLists.txt index 80a09489805ee..c2bd979816935 100644 --- a/Detectors/FIT/FT0/raw/CMakeLists.txt +++ b/Detectors/FIT/FT0/raw/CMakeLists.txt @@ -9,5 +9,5 @@ #submit itself to any jurisdiction. o2_add_library(FT0Raw - SOURCES src/DataBlockRaw.cxx src/DigitBlockFT0.cxx src/DataBlockReader.cxx - PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::DataFormatsFT0) + SOURCES src/DataBlockFT0.cxx src/DigitBlockFT0.cxx src/RawReaderFT0Base.cxx + PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::DataFormatsFT0 O2::FITRaw) diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h new file mode 100644 index 0000000000000..30bf27f61dd0e --- /dev/null +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h @@ -0,0 +1,107 @@ +// 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 DataBlockFT0.h class for RAW data format data blocks at FT0 +// +// Artur.Furs +// afurs@cern.ch +// + +#ifndef ALICEO2_FIT_DATABLOCKFT0_H_ +#define ALICEO2_FIT_DATABLOCKFT0_H_ +#include <iostream> +#include <Rtypes.h> +#include <DataFormatsFT0/RawEventData.h> +#include <FITRaw/DataBlockBase.h> + +#include <gsl/span> +#include <iostream> +#include <cassert> +using namespace o2::fit; +namespace o2 +{ +namespace ft0 +{ +using RawHeaderPM = o2::ft0::EventHeader; +using RawDataPM = o2::ft0::EventData; +using RawHeaderTCM = o2::ft0::EventHeader; +using RawDataTCM = o2::ft0::TCMdata; +using RawHeaderTCMext = o2::ft0::EventHeader; +using RawDataTCMext = o2::ft0::TCMdataExtended; + +using namespace std; + +//FT0 DATA BLOCK DEFINITIONS + +//standard data block from PM +class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> +{ + public: + DataBlockPM() = default; + DataBlockPM(const DataBlockPM&) = default; + void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) + { + DataBlockWrapper<RawHeaderPM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderPM>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataPM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderPM>::mData[0].nGBTWords, srcByteShift); + } + //Custom sanity checking for current deserialized block + // put here code for raw data checking + void sanityCheck(bool& flag) + { + if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) + DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling + //TODO, Descriptor checking, Channel range + } +}; + +//standard data block from TCM +class DataBlockTCM : public DataBlockBase<DataBlockTCM, RawHeaderTCM, RawDataTCM> +{ + public: + DataBlockTCM() = default; + DataBlockTCM(const DataBlockTCM&) = default; + void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) + { + DataBlockWrapper<RawHeaderTCM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCM>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataTCM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCM>::mData[0].nGBTWords, srcByteShift); + } + //Custom sanity checking for current deserialized block + // put here code for raw data checking + void sanityCheck(bool& flag) + { + //TODO, Descriptor checking + } +}; + +//extended TCM mode, 1 TCMdata + 8 TCMdataExtendedstructs +class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, RawDataTCM, RawDataTCMext> +{ + public: + DataBlockTCMext() = default; + DataBlockTCMext(const DataBlockTCMext&) = default; + void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) + { + DataBlockWrapper<RawHeaderTCMext>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCMext>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataTCM>::deserialize(srcBytes, DataBlockWrapper<RawDataTCM>::MaxNwords, srcByteShift); + DataBlockWrapper<RawDataTCMext>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCMext>::mData[0].nGBTWords - DataBlockWrapper<RawDataTCM>::MaxNwords, srcByteShift); + } + + //Custom sanity checking for current deserialized block + // put here code for raw data checking + void sanityCheck(bool& flag) + { + + //TODO, Descriptor checking + } +}; + +} // namespace ft0 +} // namespace o2 +#endif \ No newline at end of file diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h deleted file mode 100644 index 80527589b9e0b..0000000000000 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockReader.h +++ /dev/null @@ -1,129 +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. -// -//file DataBlockReader.h class for RAW data reading -// -// Artur.Furs -// afurs@cern.ch -// -//Main purpuse is to decode FT0 data blocks and push them to DigitBlockFT0 for proccess -//TODO: -// in place contruction, change push_back to emplace_back in DataBlockReader -// move semantic for DataBlocks - -#ifndef ALICEO2_FIT_DATABLOCKREADER_H_ -#define ALICEO2_FIT_DATABLOCKREADER_H_ -#include <iostream> -#include <vector> -#include <Rtypes.h> -#include "FT0Raw/DataBlockRaw.h" -#include "FT0Raw/DigitBlockFT0.h" -#include <boost/mpl/inherit.hpp> -#include <boost/mpl/vector.hpp> - -#include <CommonDataFormat/InteractionRecord.h> -#include "Headers/RAWDataHeader.h" -#include "DataFormatsFT0/Digit.h" -#include "DataFormatsFT0/ChannelData.h" - -#include <gsl/span> -namespace o2 -{ -namespace ft0 -{ - -template <class DataBlockType> -class DataBlockReader -{ - public: - DataBlockReader() = default; - ~DataBlockReader() = default; - typedef DataBlockType DataBlock; - size_t decodeBlocks(const gsl::span<const uint8_t> binaryPayload, std::vector<DataBlockType>& vecDataBlocks) - { - size_t srcPos = 0; - while (srcPos < binaryPayload.size()) { //checking element - DataBlockType dataBlock; - dataBlock.decodeBlock(binaryPayload, srcPos); - srcPos += dataBlock.mSize; - if (dataBlock.isCorrect()) - vecDataBlocks.push_back(dataBlock); //change to in-place construction? TODO - } - return srcPos; - } -}; - -//Composition over multiple inheritance(multiple data block reader) -template <class DigitBlockType, class... DataBlockTypes> -class RawReaderBase : public boost::mpl::inherit<DataBlockReader<DataBlockTypes>...>::type -{ - public: - typedef boost::mpl::vector<DataBlockTypes...> DataBlockVectorTypes; - typedef boost::mpl::vector<DataBlockReader<DataBlockTypes>...> ReaderTypes; - RawReaderBase() = default; - ~RawReaderBase() = default; - - std::map<InteractionRecord, DigitBlockType> mMapDigits; - template <class DataBlockType> - void pushDataBlock(gsl::span<const uint8_t> payload, int linkID) - { - std::vector<DataBlockType> vecDataBlocks; - auto srcPos = DataBlockReader<DataBlockType>::decodeBlocks(payload, vecDataBlocks); - for (auto& dataBlock : vecDataBlocks) { - auto intRec = dataBlock.getInteractionRecord(); - auto [digitIter, isNew] = mMapDigits.try_emplace(intRec, intRec); - digitIter->second.template proccess<DataBlockType>(dataBlock, linkID); - } - } -}; - -// Raw reader for FT0 -template <bool IsExtendedMode = false> -class RawReaderFT0 : public RawReaderBase<DigitBlockFT0, DataBlockPM, typename std::conditional<IsExtendedMode, DataBlockTCMext, DataBlockTCM>::type> -{ - public: - typedef typename std::conditional<IsExtendedMode, DataBlockTCMext, DataBlockTCM>::type DataBlockTCMtype; - typedef RawReaderBase<DigitBlockFT0, DataBlockPM, DataBlockTCMtype> RawReaderBaseType; - - RawReaderFT0() = default; - ~RawReaderFT0() = default; - //deserialize payload to raw data blocks and proccesss them to digits - void proccess(int linkID, gsl::span<const uint8_t> payload) - { - if (0 <= linkID && linkID < 18) { - //PM data proccessing - RawReaderBaseType::template pushDataBlock<DataBlockPM>(payload, linkID); - } else if (linkID == 18) { - //TCM data proccessing - RawReaderBaseType::template pushDataBlock<DataBlockTCMtype>(payload, linkID); - } else { - //put here code in case of bad rdh.linkID value - LOG(INFO) << "WARNING! WRONG LINK ID!"; - return; - } - - // - } - //pop digits - int popDigits(std::vector<Digit>& vecDigit, std::vector<ChannelData>& vecChannelData) - { - int digitCounter = RawReaderBaseType::mMapDigits.size(); - for (auto& digit : (RawReaderBaseType::mMapDigits)) { - digit.second.popData(vecDigit, vecChannelData); - } - (RawReaderBaseType::mMapDigits).clear(); - return digitCounter; - } -}; - -} // namespace ft0 -} // namespace o2 - -#endif \ No newline at end of file diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h index 6913499d0014d..cc7bd3cbdb18e 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h @@ -22,7 +22,9 @@ #include <vector> #include <algorithm> #include <Rtypes.h> -#include "FT0Raw/DataBlockRaw.h" +#include "FT0Raw/DataBlockFT0.h" +#include "FITRaw/DigitBlockBase.h" + #include <CommonDataFormat/InteractionRecord.h> #include "DataFormatsFT0/Digit.h" #include "DataFormatsFT0/ChannelData.h" @@ -32,30 +34,30 @@ #include <boost/mpl/contains.hpp> #include <gsl/span> + +using namespace o2::fit; + namespace o2 { namespace ft0 { - -class DigitBlockFT0 +//Normal data taking mode +class DigitBlockFT0 : public DigitBlockBase<DigitBlockFT0> { - //Mandatory to fill! Just add class type into corresponding template header. - typedef boost::mpl::vector<DataBlockPM, DataBlockTCM, DataBlockTCMext> ProccessBlockTypes; - //typedef boost::mpl::vector<DataBlockTCM,DataBlockTCMext> TrgInfoTypes; - // public: - DigitBlockFT0(o2::InteractionRecord intRec) { mDigit.mIntRecord = intRec; } + typedef DigitBlockBase<DigitBlockFT0> DigitBlockBaseType; + DigitBlockFT0(o2::InteractionRecord intRec) { setIntRec(intRec); } DigitBlockFT0() = default; DigitBlockFT0(const DigitBlockFT0& other) = default; ~DigitBlockFT0() = default; - + void setIntRec(o2::InteractionRecord intRec) { mDigit.mIntRecord = intRec; } Digit mDigit; std::vector<ChannelData> mVecChannelData; static o2::ft0::LookUpTable sLookupTable; static int sEventID; + template <class DataBlockType> - //,typename enable_if<boost::mpl::contains<ProccessBlockTypes,DataBlockType>::type::value>::type > //TODO traits - void proccess(DataBlockType& dataBlock, int linkID) + void processDigits(DataBlockType& dataBlock, int linkID) { if constexpr (std::is_same<DataBlockType, DataBlockPM>::value) { //Filling data from PM for (int iEventData = 0; iEventData < dataBlock.DataBlockWrapper<RawDataPM>::mNelements; iEventData++) { @@ -67,20 +69,113 @@ class DigitBlockFT0 } else if constexpr (std::is_same<DataBlockType, DataBlockTCM>::value) { //Filling data from TCM (normal/extended mode) dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].fillTrigger(mDigit.mTriggers); } + } + void getDigits(std::vector<Digit>& vecDigits, std::vector<ChannelData>& vecChannelData) + { + //last digit filling + mDigit.ref.set(vecChannelData.size(), mVecChannelData.size()); + mDigit.mEventID = sEventID; + // + vecDigits.push_back(std::move(mDigit)); + std::move(mVecChannelData.begin(), mVecChannelData.end(), std::back_inserter(vecChannelData)); + mVecChannelData.clear(); + + sEventID++; //Increasing static eventID. After each poping of the data, it will increase + } + void print() const + { + std::cout << "\n______________DIGIT DATA____________"; + std::cout << std::hex; + std::cout << "\nBC: " << mDigit.mIntRecord.bc << "| ORBIT: " << mDigit.mIntRecord.orbit; + std::cout << "\nRef first: " << mDigit.ref.getFirstEntry() << "| Ref entries: " << mDigit.ref.getEntries(); + std::cout << "\nmTrigger: " << static_cast<uint16_t>(mDigit.mTriggers.triggersignals); + std::cout << "\nnChanA: " << static_cast<uint16_t>(mDigit.mTriggers.nChanA) << " | nChanC: " << static_cast<uint16_t>(mDigit.mTriggers.nChanC); + std::cout << "\namplA: " << mDigit.mTriggers.amplA << " | amplC: " << mDigit.mTriggers.amplC; + std::cout << "\ntimeA: " << mDigit.mTriggers.timeA << " | timeC: " << mDigit.mTriggers.timeC; + + std::cout << "\n______________CHANNEL DATA____________\n"; + std::cout << "\nN channel: " << mVecChannelData.size(); + for (const auto& chData : mVecChannelData) { + std::cout << "\nChId: " << static_cast<uint16_t>(chData.ChId) << " | ChainQTC:" << static_cast<uint16_t>(chData.ChainQTC) << " | CFDTime: " << chData.CFDTime << " | QTCAmpl: " << chData.QTCAmpl; + } + std::cout << std::dec; + std::cout << "\n"; + LOG(INFO) << "______________________________________"; + } + + static void print(std::vector<Digit>& vecDigit, std::vector<ChannelData>& vecChannelData) + { + for (const auto& digit : vecDigit) { + std::cout << "\n______________DIGIT DATA____________"; + std::cout << std::hex; + std::cout << "\nBC: " << digit.mIntRecord.bc << "| ORBIT: " << digit.mIntRecord.orbit << " | EventID: " << digit.mEventID; + std::cout << "\nRef first: " << digit.ref.getFirstEntry() << "| Ref entries: " << digit.ref.getEntries(); + std::cout << "\nmTrigger: " << static_cast<uint16_t>(digit.mTriggers.triggersignals); + std::cout << "\nnChanA: " << static_cast<uint16_t>(digit.mTriggers.nChanA) << " | nChanC: " << static_cast<uint16_t>(digit.mTriggers.nChanC); + std::cout << "\namplA: " << digit.mTriggers.amplA << " | amplC: " << digit.mTriggers.amplC; + std::cout << "\ntimeA: " << digit.mTriggers.timeA << " | timeC: " << digit.mTriggers.timeC; + + std::cout << "\n______________CHANNEL DATA____________\n"; + for (int iChData = digit.ref.getFirstEntry(); iChData < digit.ref.getFirstEntry() + digit.ref.getEntries(); iChData++) { + + std::cout << "\nChId: " << static_cast<uint16_t>(vecChannelData[iChData].ChId) << " | ChainQTC:" << static_cast<uint16_t>(vecChannelData[iChData].ChainQTC) + << " | CFDTime: " << vecChannelData[iChData].CFDTime << " | QTCAmpl: " << vecChannelData[iChData].QTCAmpl; + } + std::cout << std::dec; + std::cout << "\n______________________________________\n"; + } + } +}; - else if constexpr (std::is_same<DataBlockType, DataBlockTCMext>::value) { //Filling data from TCM, extended mode. Same proccess as for normal mode, for now. +//TCM extended data taking mode +class DigitBlockFT0ext : public DigitBlockBase<DigitBlockFT0ext> +{ + public: + typedef DigitBlockBase<DigitBlockFT0ext> DigitBlockBaseType; + + DigitBlockFT0ext(o2::InteractionRecord intRec) { setIntRec(intRec); } + DigitBlockFT0ext() = default; + DigitBlockFT0ext(const DigitBlockFT0ext& other) = default; + ~DigitBlockFT0ext() = default; + void setIntRec(o2::InteractionRecord intRec) { mDigit.mIntRecord = intRec; } + DigitExt mDigit; + std::vector<ChannelData> mVecChannelData; + std::vector<TriggersExt> mVecTriggersExt; + + static o2::ft0::LookUpTable sLookupTable; + static int sEventID; + + template <class DataBlockType> + void processDigits(DataBlockType& dataBlock, int linkID) + { + if constexpr (std::is_same<DataBlockType, DataBlockPM>::value) { //Filling data from PM + for (int iEventData = 0; iEventData < dataBlock.DataBlockWrapper<RawDataPM>::mNelements; iEventData++) { + mVecChannelData.emplace_back(uint8_t(sLookupTable.getChannel(linkID, dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].channelID)), + int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].time), + int(dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].charge), + dataBlock.DataBlockWrapper<RawDataPM>::mData[iEventData].getFlagWord()); + } + } else if constexpr (std::is_same<DataBlockType, DataBlockTCMext>::value) { //Filling data from TCM, extended mode. Same proccess as for normal mode, for now. dataBlock.DataBlockWrapper<RawDataTCM>::mData[0].fillTrigger(mDigit.mTriggers); + for (int iTriggerWord = 0; iTriggerWord < dataBlock.DataBlockWrapper<RawDataTCMext>::mNelements; iTriggerWord++) { + mVecTriggersExt.emplace_back(dataBlock.DataBlockWrapper<RawDataTCMext>::mData[iTriggerWord].triggerWord); + } } } - void popData(std::vector<Digit>& vecDigits, std::vector<ChannelData>& vecChannelData) + void getDigits(std::vector<DigitExt>& vecDigits, std::vector<ChannelData>& vecChannelData, std::vector<TriggersExt>& vecTriggersExt) { //last digit filling mDigit.ref.set(vecChannelData.size(), mVecChannelData.size()); + mDigit.refExt.set(vecTriggersExt.size(), mVecTriggersExt.size()); mDigit.mEventID = sEventID; - // + //Digits vecDigits.push_back(std::move(mDigit)); + //ChannelData std::move(mVecChannelData.begin(), mVecChannelData.end(), std::back_inserter(vecChannelData)); mVecChannelData.clear(); + //TriggersExt + std::move(mVecTriggersExt.begin(), mVecTriggersExt.end(), std::back_inserter(vecTriggersExt)); + mVecTriggersExt.clear(); sEventID++; //Increasing static eventID. After each poping of the data, it will increase } @@ -105,7 +200,7 @@ class DigitBlockFT0 LOG(INFO) << "______________________________________"; } - static void print(std::vector<Digit>& vecDigit, std::vector<ChannelData>& vecChannelData) + static void print(std::vector<DigitExt>& vecDigit, std::vector<ChannelData>& vecChannelData, std::vector<TriggersExt>& vecTriggersExt) { for (const auto& digit : vecDigit) { std::cout << "\n______________DIGIT DATA____________"; diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h b/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h new file mode 100644 index 0000000000000..7ff11acd0b038 --- /dev/null +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h @@ -0,0 +1,78 @@ +// 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 RawReaderFT0Base.h Base class for RAW data reading +// +// Artur.Furs +// afurs@cern.ch +// +//Main purpuse is to decode FT0 data blocks and push them to DigitBlockFT0 for proccess +//Base class only provides static linkID-moduleType conformity + +#ifndef ALICEO2_FIT_RAWREADERFT0BASE_H_ +#define ALICEO2_FIT_RAWREADERFT0BASE_H_ +#include <iostream> +#include <vector> +#include <Rtypes.h> +#include "FT0Raw/DataBlockFT0.h" +#include "FT0Raw/DigitBlockFT0.h" +#include "FITRaw/RawReaderBase.h" + +#include <boost/mpl/inherit.hpp> +#include <boost/mpl/vector.hpp> + +#include <CommonDataFormat/InteractionRecord.h> +#include "Headers/RAWDataHeader.h" +//#include "DataFormatsFT0/Digit.h" +//#include "DataFormatsFT0/ChannelData.h" + +#include <gsl/span> + +using namespace o2::fit; +namespace o2 +{ +namespace ft0 +{ + +// Common raw reader for FT0 +template <class DigitBlockFT0type, class DataBlockPMtype, class DataBlockTCMtype> +class RawReaderFT0Base : public RawReaderBase<DigitBlockFT0type> +{ + public: + typedef RawReaderBase<DigitBlockFT0type> RawReaderBaseType; + RawReaderFT0Base() = default; + ~RawReaderFT0Base() = default; + //deserialize payload to raw data blocks and proccesss them to digits + void process(int linkID, gsl::span<const uint8_t> payload) + { + if (0 <= linkID && linkID < 18) { + //PM data proccessing + RawReaderBaseType::template processBinaryData<DataBlockPMtype>(payload, linkID); + } else if (linkID == 18) { + //TCM data proccessing + RawReaderBaseType::template processBinaryData<DataBlockTCMtype>(payload, linkID); + } else { + //put here code in case of bad rdh.linkID value + LOG(INFO) << "WARNING! WRONG LINK ID!"; + return; + } + + // + } +}; +//Normal TCM mode +using RawReaderFT0BaseNorm = RawReaderFT0Base<DigitBlockFT0, DataBlockPM, DataBlockTCM>; +//Extended TCM mode +using RawReaderFT0BaseExt = RawReaderFT0Base<DigitBlockFT0ext, DataBlockPM, DataBlockTCMext>; + +} // namespace ft0 +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx b/Detectors/FIT/FT0/raw/src/DataBlockFT0.cxx similarity index 93% rename from Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx rename to Detectors/FIT/FT0/raw/src/DataBlockFT0.cxx index 7eec38be58b3e..3a8eddd8b3a5c 100644 --- a/Detectors/FIT/FT0/raw/src/DataBlockRaw.cxx +++ b/Detectors/FIT/FT0/raw/src/DataBlockFT0.cxx @@ -8,5 +8,5 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "FT0Raw/DataBlockRaw.h" +#include "FT0Raw/DataBlockFT0.h" using namespace o2::ft0; diff --git a/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx index b232b80e84de7..710ebee6249a2 100644 --- a/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx +++ b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx @@ -13,3 +13,5 @@ using namespace o2::ft0; int DigitBlockFT0::sEventID = 0; o2::ft0::LookUpTable DigitBlockFT0::sLookupTable = o2::ft0::LookUpTable::linear(); +int DigitBlockFT0ext::sEventID = 0; +o2::ft0::LookUpTable DigitBlockFT0ext::sLookupTable = o2::ft0::LookUpTable::linear(); diff --git a/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h b/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h index c01219fcc0901..e19b7f162e426 100644 --- a/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h +++ b/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h @@ -18,7 +18,9 @@ #pragma link C++ class o2::ft0::DataBlockTCM + ; #pragma link C++ class o2::ft0::DataBlockTCMext + ; #pragma link C++ class o2::ft0::DigitBlockFT0 + ; -#pragma link C++ class o2::ft0::RawReaderFT0 < true> + ; -#pragma link C++ class o2::ft0::RawReaderFT0 < false> + ; +#pragma link C++ class o2::ft0::DigitBlockFT0ext + ; + +//#pragma link C++ class o2::ft0::RawReaderFT0 < true> + ; +//#pragma link C++ class o2::ft0::RawReaderFT0 < false> + ; #endif diff --git a/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx b/Detectors/FIT/FT0/raw/src/RawReaderFT0Base.cxx similarity index 93% rename from Detectors/FIT/FT0/raw/src/DataBlockReader.cxx rename to Detectors/FIT/FT0/raw/src/RawReaderFT0Base.cxx index 15b2c9a0beef3..f4c76fb9585c0 100644 --- a/Detectors/FIT/FT0/raw/src/DataBlockReader.cxx +++ b/Detectors/FIT/FT0/raw/src/RawReaderFT0Base.cxx @@ -8,5 +8,5 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "FT0Raw/DataBlockReader.h" +#include "FT0Raw/RawReaderFT0Base.h" using namespace o2::ft0; diff --git a/Detectors/FIT/FT0/simulation/src/Detector.cxx b/Detectors/FIT/FT0/simulation/src/Detector.cxx index dc1693129de85..961b8bd5e5c67 100644 --- a/Detectors/FIT/FT0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FT0/simulation/src/Detector.cxx @@ -356,7 +356,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) int iPart = fMC->TrackPid(); float enDep = fMC->Edep(); Int_t parentID = stack->GetCurrentTrack()->GetMother(0); - if (fMC->TrackCharge()) { //charge particles for MCtrue + if (fMC->TrackCharge() && volname.Contains("0REG")) { //charge particles for MCtrue AddHit(x, y, z, time, 10, trackID, detID); } if (iPart == 50000050) { // If particles is photon then ... diff --git a/Detectors/FIT/FT0/workflow/CMakeLists.txt b/Detectors/FIT/FT0/workflow/CMakeLists.txt index e56e686e0a47e..69c116c041b14 100644 --- a/Detectors/FIT/FT0/workflow/CMakeLists.txt +++ b/Detectors/FIT/FT0/workflow/CMakeLists.txt @@ -20,6 +20,7 @@ o2_add_library(FT0Workflow src/FT0DataProcessDPLSpec.cxx src/FT0DataReaderDPLSpec.cxx src/FT0DigitWriterDPLSpec.cxx + src/RawReaderFT0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsFT0 O2::FT0Reconstruction diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h index cf6b7f0d4079d..d48cb55d8fde3 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h @@ -23,11 +23,11 @@ #include "Framework/WorkflowSpec.h" #include "Framework/SerializationMethods.h" #include "DPLUtils/DPLRawParser.h" -#include "FT0Raw/DataBlockReader.h" -#include "FT0Raw/DigitBlockFT0.h" +//#include "FT0Raw/RawReaderFT0.h" +//#include "FT0Raw/DigitBlockFT0.h" -#include "DataFormatsFT0/Digit.h" -#include "DataFormatsFT0/ChannelData.h" +//#include "DataFormatsFT0/Digit.h" +//#include "DataFormatsFT0/ChannelData.h" #include <iostream> #include <vector> #include <gsl/span> @@ -37,25 +37,47 @@ namespace o2 { namespace ft0 { -template <bool IsExtendedMode> +template <typename RawReader> class FT0DataReaderDPLSpec : public Task { public: - FT0DataReaderDPLSpec(bool dumpEventBlocks, bool isExtendedMode) : mIsExtendedMode(isExtendedMode), mDumpEventBlocks(dumpEventBlocks) {} + FT0DataReaderDPLSpec(const RawReader& rawReader) : mRawReader(rawReader) {} + FT0DataReaderDPLSpec() = default; ~FT0DataReaderDPLSpec() override = default; - void init(InitContext& ic) final; - void run(ProcessingContext& pc) final; - - private: - bool mDumpEventBlocks; - bool mIsExtendedMode; - std::vector<Digit> mVecDigits; - std::vector<ChannelData> mVecChannelData; - RawReaderFT0<IsExtendedMode> mRawReaderFT0; - o2::header::DataOrigin mOrigin = o2::header::gDataOriginFT0; + void init(InitContext& ic) final {} + void run(ProcessingContext& pc) final + { + DPLRawParser parser(pc.inputs()); + mRawReader.clear(); + LOG(INFO) << "FT0DataReaderDPLSpec"; + uint64_t count = 0; + for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { + //Proccessing each page + count++; + auto rdhPtr = it.get_if<o2::header::RAWDataHeader>(); + gsl::span<const uint8_t> payload(it.data(), it.size()); + mRawReader.process(rdhPtr->linkID, payload); + } + LOG(INFO) << "Pages: " << count; + mRawReader.accumulateDigits(); + mRawReader.makeSnapshot(pc); + } + RawReader mRawReader; }; -framework::AlgorithmSpec getAlgorithmSpec(bool dumpReader, bool isExtendedMode); -framework::DataProcessorSpec getFT0DataReaderDPLSpec(bool dumpReader, bool isExtendedMode); + +template <typename RawReader> +framework::DataProcessorSpec getFT0DataReaderDPLSpec(const RawReader& rawReader) +{ + LOG(INFO) << "DataProcessorSpec initDataProcSpec() for RawReaderFT0"; + std::vector<OutputSpec> outputSpec; + RawReader::prepareOutputSpec(outputSpec); + return DataProcessorSpec{ + "ft0-datareader-dpl", + o2::framework::select("TF:FT0/RAWDATA"), + outputSpec, + adaptFromTask<FT0DataReaderDPLSpec<RawReader>>(rawReader), + Options{}}; +} } // namespace ft0 } // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h index 518773debf15b..f2cd562af2e02 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0Workflow.h @@ -17,11 +17,11 @@ namespace o2 { -namespace fit +namespace ft0 { framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, bool dumpProcessor, bool dumpReader, bool disableRootOut); -} // namespace fit +} // namespace ft0 } // namespace o2 #endif diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h new file mode 100644 index 0000000000000..ca97dfeb1cccb --- /dev/null +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.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 RawReaderFT0.h class for RAW data reading +// +// Artur.Furs +// afurs@cern.ch +// +//Main purpuse is to decode FT0 data blocks and push them to DigitBlockFT0 for proccess +//TODO: prepare wrappers for containers with digits and combine classes below into one template class? +#ifndef ALICEO2_FIT_RAWREADERFT0_H_ +#define ALICEO2_FIT_RAWREADERFT0_H_ +#include <iostream> +#include <vector> +#include <Rtypes.h> +#include "FT0Raw/RawReaderFT0Base.h" + +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsFT0/ChannelData.h" + +#include "Framework/ProcessingContext.h" +#include "Framework/OutputSpec.h" +#include <gsl/span> + +namespace o2 +{ +namespace ft0 +{ +//Normal TCM mode +class RawReaderFT0 : public RawReaderFT0BaseNorm +{ + public: + RawReaderFT0(bool dumpData) : mDumpData(dumpData) {} + RawReaderFT0(const RawReaderFT0&) = default; + + RawReaderFT0() = default; + ~RawReaderFT0() = default; + void clear() + { + mVecDigits.clear(); + mVecChannelData.clear(); + } + void accumulateDigits() + { + getDigits(mVecDigits, mVecChannelData); + LOG(INFO) << "Number of Digits: " << mVecDigits.size(); + LOG(INFO) << "Number of ChannelData: " << mVecChannelData.size(); + if (mDumpData) + DigitBlockFT0::print(mVecDigits, mVecChannelData); + } + static void prepareOutputSpec(std::vector<o2::framework::OutputSpec>& outputSpec) + { + outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSBC", 0, o2::framework::Lifetime::Timeframe); + outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSCH", 0, o2::framework::Lifetime::Timeframe); + } + void makeSnapshot(o2::framework::ProcessingContext& pc) + { + pc.outputs().snapshot(o2::framework::Output{o2::header::gDataOriginFT0, "DIGITSBC", 0, o2::framework::Lifetime::Timeframe}, mVecDigits); + pc.outputs().snapshot(o2::framework::Output{o2::header::gDataOriginFT0, "DIGITSCH", 0, o2::framework::Lifetime::Timeframe}, mVecChannelData); + } + bool mDumpData; + std::vector<Digit> mVecDigits; + std::vector<ChannelData> mVecChannelData; +}; + +//Extended TCM mode (additional raw data struct) +class RawReaderFT0ext : public RawReaderFT0BaseExt +{ + public: + RawReaderFT0ext(bool dumpData) : mDumpData(dumpData) {} + RawReaderFT0ext(const RawReaderFT0ext&) = default; + + RawReaderFT0ext() = default; + ~RawReaderFT0ext() = default; + void clear() + { + mVecDigitsExt.clear(); + mVecChannelData.clear(); + mVecTrgExt.clear(); + } + void accumulateDigits() + { + getDigits(mVecDigitsExt, mVecChannelData, mVecTrgExt); + LOG(INFO) << "Number of Digits: " << mVecDigitsExt.size(); + LOG(INFO) << "Number of ChannelData: " << mVecChannelData.size(); + LOG(INFO) << "Number of TriggerExt: " << mVecTrgExt.size(); + if (mDumpData) + DigitBlockFT0ext::print(mVecDigitsExt, mVecChannelData, mVecTrgExt); + } + static void prepareOutputSpec(std::vector<o2::framework::OutputSpec>& outputSpec) + { + outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSBC", 0, o2::framework::Lifetime::Timeframe); + outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSCH", 0, o2::framework::Lifetime::Timeframe); + outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSTRGEXT", 0, o2::framework::Lifetime::Timeframe); + } + void makeSnapshot(o2::framework::ProcessingContext& pc) + { + pc.outputs().snapshot(o2::framework::Output{o2::header::gDataOriginFT0, "DIGITSBC", 0, o2::framework::Lifetime::Timeframe}, mVecDigitsExt); + pc.outputs().snapshot(o2::framework::Output{o2::header::gDataOriginFT0, "DIGITSCH", 0, o2::framework::Lifetime::Timeframe}, mVecChannelData); + pc.outputs().snapshot(o2::framework::Output{o2::header::gDataOriginFT0, "DIGITSTRGEXT", 0, o2::framework::Lifetime::Timeframe}, mVecTrgExt); + } + bool mDumpData; + std::vector<DigitExt> mVecDigitsExt; + std::vector<ChannelData> mVecChannelData; + std::vector<TriggersExt> mVecTrgExt; +}; + +} // namespace ft0 +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx index 2e338ce41b20e..d8451ba6ccb1e 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0DataReaderDPLSpec.cxx @@ -18,60 +18,6 @@ namespace o2 { namespace ft0 { -using namespace std; -template <bool IsExtendedMode> -void FT0DataReaderDPLSpec<IsExtendedMode>::init(InitContext& ic) - -{ -} -template <bool IsExtendedMode> -void FT0DataReaderDPLSpec<IsExtendedMode>::run(ProcessingContext& pc) - -{ - DPLRawParser parser(pc.inputs()); - mVecDigits.clear(); - mVecChannelData.clear(); - LOG(INFO) << "FT0DataReaderDPLSpec"; - uint64_t count = 0; - for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { - //Proccessing each page - count++; - auto rdhPtr = it.get_if<o2::header::RAWDataHeader>(); - gsl::span<const uint8_t> payload(it.data(), it.size()); - mRawReaderFT0.proccess(rdhPtr->linkID, payload); - } - - mRawReaderFT0.popDigits(mVecDigits, mVecChannelData); - LOG(INFO) << "Number of Digits: " << mVecDigits.size(); - LOG(INFO) << "Number of ChannelData: " << mVecChannelData.size(); - if (mDumpEventBlocks) - DigitBlockFT0::print(mVecDigits, mVecChannelData); - pc.outputs().snapshot(Output{o2::header::gDataOriginFT0, "DIGITSBC", 0, Lifetime::Timeframe}, mVecDigits); - pc.outputs().snapshot(Output{o2::header::gDataOriginFT0, "DIGITSCH", 0, Lifetime::Timeframe}, mVecChannelData); -} -AlgorithmSpec getAlgorithmSpec(bool dumpReader, bool isExtendedMode) -{ - if (isExtendedMode) { - LOG(INFO) << "TCM mode: extended, additional TCM data blocks(TCMdataExtended) will be in payload from TCM!"; - return adaptFromTask<FT0DataReaderDPLSpec<true>>(dumpReader, isExtendedMode); - } - LOG(INFO) << "TCM mode: normal, only TCMdata will be in payload from TCM."; - return adaptFromTask<FT0DataReaderDPLSpec<false>>(dumpReader, isExtendedMode); -} - -DataProcessorSpec getFT0DataReaderDPLSpec(bool dumpReader, bool isExtendedMode) -{ - std::vector<OutputSpec> outputSpec; - outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSBC", 0, Lifetime::Timeframe); - outputSpec.emplace_back(o2::header::gDataOriginFT0, "DIGITSCH", 0, Lifetime::Timeframe); - LOG(INFO) << "DataProcessorSpec getFT0DataReaderDPLSpec"; - return DataProcessorSpec{ - "ft0-datareader-dpl-flp", - o2::framework::select("TF:FT0/RAWDATA"), - outputSpec, - getAlgorithmSpec(dumpReader, isExtendedMode), - Options{}}; -} } // namespace ft0 } // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx index 0031832efd2bd..ada920a29c99f 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx @@ -14,10 +14,10 @@ #include "FT0Workflow/FT0DataProcessDPLSpec.h" #include "FT0Workflow/FT0DataReaderDPLSpec.h" #include "FT0Workflow/FT0DigitWriterDPLSpec.h" - +#include "FT0Workflow/RawReaderFT0.h" namespace o2 { -namespace fit +namespace ft0 { framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, @@ -26,8 +26,11 @@ framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, { LOG(INFO) << "framework::WorkflowSpec getFT0Workflow"; framework::WorkflowSpec specs; - specs.emplace_back( - o2::ft0::getFT0DataReaderDPLSpec(dumpReader, isExtendedMode)); + if (isExtendedMode) { + specs.emplace_back(o2::ft0::getFT0DataReaderDPLSpec(RawReaderFT0ext{dumpReader})); + } else { + specs.emplace_back(o2::ft0::getFT0DataReaderDPLSpec(RawReaderFT0{dumpReader})); + } if (useProcess) specs.emplace_back(o2::ft0::getFT0DataProcessDPLSpec(dumpProcessor)); if (!disableRootOut) @@ -35,5 +38,5 @@ framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, return specs; } -} // namespace fit +} // namespace ft0 } // namespace o2 diff --git a/Detectors/FIT/FT0/workflow/src/RawReaderFT0.cxx b/Detectors/FIT/FT0/workflow/src/RawReaderFT0.cxx new file mode 100644 index 0000000000000..3de0026f13b55 --- /dev/null +++ b/Detectors/FIT/FT0/workflow/src/RawReaderFT0.cxx @@ -0,0 +1,12 @@ +// 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 "FT0Workflow/RawReaderFT0.h" +using namespace o2::ft0; diff --git a/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx b/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx index 059dda0028a86..f452eee06a53f 100644 --- a/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/ft0-flp-workflow.cxx @@ -62,6 +62,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); LOG(INFO) << "WorkflowSpec FLPWorkflow"; - return std::move(o2::fit::getFT0Workflow( + return std::move(o2::ft0::getFT0Workflow( isExtendedMode, useProcessor, dumpProcessor, dumpReader, disableRootOut)); } diff --git a/Detectors/FIT/raw/CMakeLists.txt b/Detectors/FIT/raw/CMakeLists.txt new file mode 100644 index 0000000000000..9fa77d178fedb --- /dev/null +++ b/Detectors/FIT/raw/CMakeLists.txt @@ -0,0 +1,13 @@ +#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_library(FITRaw + SOURCES src/DataBlockBase.cxx src/DigitBlockBase.cxx src/RawReaderBase.cxx + PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers ms_gsl::ms_gsl) diff --git a/Detectors/FIT/raw/README.md b/Detectors/FIT/raw/README.md new file mode 100644 index 0000000000000..d51b86bb0737b --- /dev/null +++ b/Detectors/FIT/raw/README.md @@ -0,0 +1,41 @@ +# DataBlockBase +DataBlockWrapper - wrapper for raw data structures\ +There should be three static fields in raw data structs, which defines its "signature":\ + payloadSize - actual payload size per one raw data struct element (can be larger than GBTword size!)\ + payloadPerGBTword - maximum payload per one GBT word\ + MaxNelements - maximum number of elements per data block(for header it should be equal to 1)\ + MinNelements - minimum number of elements per data block(for header it should be equal to 1)\ + +Also it requares several methods:\ + print() - for printing raw data structs\ + getIntRec() - for InteractionRecord extraction, should be in Header struct\ + +DataBlockBase - base class for making composition of raw data structures, uses CRTP(static polyporphism)\ +usage:\ + class DataBlockOfYourModule: public DataBlockBase< DataBlockOfYourModule, RawHeaderStruct, RawDataStruct ...>\ + define "deserialization" method with deserialization logic for current DataBlock\ + define "sanityCheck" method for checking if the DataBlock is correct\ +Warning! Classes should be simple, without refs and pointers!\ + +# DigitBlockBase +Base class for digit block, which containes "digit" structures\ +usage:\ + class DigitBlockYourDetector : public DigitBlockBase<DigitBlockYourDetector>\ + define "template <class DataBlockType> void processDigits(DataBlockType& dataBlock, int linkID)" with Raw2Digit conversion logic\ + define "template <class DigitType,...>void getDigits(std::vector<DigitType>&... vecDigits) for pushing digits into vectors which will be pushed through DPL channels, + variadic arguments are applied\ +Example:\ + /alice/O2/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h \ + +# RawReaderBase +Base class for raw reader.\ +usage:\ + class RawReaderFT0Base : public RawReaderBase<DigitBlockYourDetector>\ + just provide statically which linkID corresponds to DataBlockOfYourModule\ +Example:\ + /alice/O2/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h\ + +# RawReader +Stores vectors with digit classes and manages them at DPL level\ +Example: \ + /alice/O2/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0\ \ No newline at end of file diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h b/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h similarity index 74% rename from Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h rename to Detectors/FIT/raw/include/FITRaw/DataBlockBase.h index bfbac3c37520b..1ef0e7a7e826a 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockRaw.h +++ b/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -//file DataBlockRaw.h class for RAW data format data blocks +//file DataBlockBase.h base class for RAW data format data blocks // // Artur.Furs // afurs@cern.ch @@ -17,7 +17,8 @@ // payloadSize - actual payload size per one raw data struct element (can be larger than GBTword size!) // payloadPerGBTword - maximum payload per one GBT word // MaxNelements - maximum number of elements per data block(for header it should be equal to 1) -// +// MinNelements - minimum number of elements per data block(for header it should be equal to 1) + //Also it requares several methods: // print() - for printing raw data structs // getIntRec() - for InteractionRecord extraction, should be in Header struct @@ -33,17 +34,17 @@ // traites for classes and structs // -#ifndef ALICEO2_FIT_DATABLOCKRAW_H_ -#define ALICEO2_FIT_DATABLOCKRAW_H_ +#ifndef ALICEO2_FIT_DATABLOCKBASE_H_ +#define ALICEO2_FIT_DATABLOCKBASE_H_ #include <iostream> #include <vector> #include <Rtypes.h> #include "CommonDataFormat/InteractionRecord.h" -#include <DataFormatsFT0/RawEventData.h> +//#include <DataFormatsFT0/RawEventData.h> #include <gsl/span> #include <boost/mpl/inherit.hpp> #include <boost/mpl/vector.hpp> - +#include <Framework/Logger.h> #include <vector> #include <tuple> #include <array> @@ -52,14 +53,8 @@ namespace o2 { -namespace ft0 +namespace fit { -using RawHeaderPM = o2::ft0::EventHeader; -using RawDataPM = o2::ft0::EventData; -using RawHeaderTCM = o2::ft0::EventHeader; -using RawDataTCM = o2::ft0::TCMdata; -using RawHeaderTCMext = o2::ft0::EventHeader; -using RawDataTCMext = o2::ft0::TCMdataExtended; using namespace std; @@ -67,7 +62,7 @@ template <typename T> struct DataBlockWrapper { DataBlockWrapper() = default; DataBlockWrapper(const DataBlockWrapper&) = default; - + static constexpr size_t sizeWord = 16; // should be changed to gloabal variable std::vector<uint8_t> serialize(int nWords) { std::vector<uint8_t> vecBytes(sizeWord * nWords); @@ -76,7 +71,7 @@ struct DataBlockWrapper { return std::move(vecBytes); gsl::span<uint8_t> serializedBytes(vecBytes); size_t countBytes = 0; - int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords - 1]); + int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords]); for (int iStep = 0; iStep < nSteps; iStep++) { memcpy(serializedBytes.data() + std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]), srcAddress + std::get<kDESTBYTEPOS>(sByteLookupTable[iStep]), std::get<kNBYTES>(sByteLookupTable[iStep])); countBytes += std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]); @@ -84,20 +79,21 @@ struct DataBlockWrapper { return std::move(vecBytes); } - void deserialize(const gsl::span<const uint8_t> inputBytes, int nWords, size_t& srcPos) + void deserialize(const gsl::span<const uint8_t> inputBytes, size_t nWords, size_t& srcPos) { mNelements = 0; mNwords = 0; - if (nWords == 0 || nWords > MaxNwords || inputBytes.size() - srcPos < nWords * sizeWord) { + if (nWords < MinNwords || nWords > MaxNwords || inputBytes.size() - srcPos < nWords * sizeWord) { //in case of bad fields responsible for deserialization logic, byte position will be pushed to the end of binary sequence srcPos = inputBytes.size(); + mIsIncorrect = true; return; } uint8_t* destAddress = (uint8_t*)mData; size_t countBytes = 0; - int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords - 1]); + int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords]); mNwords = nWords; - mNelements = std::get<kNELEMENTS>(sReadingLookupTable[nWords - 1]); + mNelements = std::get<kNELEMENTS>(sReadingLookupTable[nWords]); for (int iStep = 0; iStep < nSteps; iStep++) { memcpy(destAddress + std::get<kDESTBYTEPOS>(sByteLookupTable[iStep]), inputBytes.data() + std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]) + srcPos, std::get<kNBYTES>(sByteLookupTable[iStep])); countBytes += std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]); @@ -108,6 +104,9 @@ struct DataBlockWrapper { static constexpr int MaxNwords = T::PayloadSize * T::MaxNelements / T::PayloadPerGBTword + (T::PayloadSize * T::MaxNelements % T::PayloadPerGBTword > 0); //calculating max GBT words per block static constexpr int MaxNbytes = sizeWord * MaxNwords; + static constexpr int MinNwords = T::PayloadSize * T::MinNelements / T::PayloadPerGBTword + (T::PayloadSize * T::MinNelements % T::PayloadPerGBTword > 0); //calculating min GBT words per block + static constexpr int MinNbytes = sizeWord * MinNwords; + //get number of byte reading steps static constexpr size_t getNsteps() { @@ -212,20 +211,23 @@ struct DataBlockWrapper { static constexpr std::array<std::tuple<size_t, size_t, size_t, int, int>, getNsteps()> sByteLookupTable = GetByteLookupTable(); //enumerator for tuple access: - //[Index] is word index position, i.e. "Index+1" number of words will be deserialized + //[Index] is word index position, i.e. "Index" number of words will be deserialized //kNELEMENTS - number of T elements will be fully deserialized in "Index+1" words - //kNSTEPS - number of steps for reading "Index+1" words + //kNSTEPS - number of steps for reading "Index" words //kISPARTED - if one T-element is parted at current word,i.e. current word contains partially deserialized T element at the end of the word enum AccessReadingLUT { kNELEMENTS, kNSTEPS, kISPARTED }; - static constexpr std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords> GetReadingLookupTable() + static constexpr std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords + 1> GetReadingLookupTable() { - std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords> readingScheme{}; + std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords + 1> readingScheme{}; size_t payloadPerElem = T::PayloadSize; - int countWord = 0; + std::get<kNSTEPS>(readingScheme[0]) = 0; + std::get<kNELEMENTS>(readingScheme[0]) = 0; + std::get<kISPARTED>(readingScheme[0]) = false; + int countWord = 1; for (int iStep = 0; iStep < getNsteps(); iStep++) { - if (countWord < std::get<kWORDINDEX>((GetByteLookupTable())[iStep])) { //new word + if (countWord - 1 < std::get<kWORDINDEX>((GetByteLookupTable())[iStep])) { //new word std::get<kNSTEPS>(readingScheme[countWord]) = iStep; std::get<kNELEMENTS>(readingScheme[countWord]) = std::get<kELEMENTINDEX>((GetByteLookupTable())[iStep]); if (payloadPerElem > 0) { @@ -250,7 +252,7 @@ struct DataBlockWrapper { } return readingScheme; } - static constexpr std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords> sReadingLookupTable = GetReadingLookupTable(); + static constexpr std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords + 1> sReadingLookupTable = GetReadingLookupTable(); // //Printing LookupTables static void printLUT() @@ -258,7 +260,7 @@ struct DataBlockWrapper { cout << endl << "-------------------------------------------" << endl; std::cout << "kNELEMENTS|kNSTEPS|kISPARTED" << std::endl; - for (int i = 0; i < MaxNwords; i++) { + for (int i = 0; i < MaxNwords + 1; i++) { std::cout << std::endl << std::get<kNELEMENTS>(sReadingLookupTable[i]) << "|" << std::get<kNSTEPS>(sReadingLookupTable[i]) << "|" @@ -287,6 +289,7 @@ struct DataBlockWrapper { T mData[T::MaxNelements]; unsigned int mNelements; //number of deserialized elements; unsigned int mNwords; //number of deserialized GBT words; //can be excluded + bool mIsIncorrect; }; //CRTP(static polymorphism) + Composition over multiple inheritance(Header + multiple data structures) @@ -336,8 +339,8 @@ class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataB void update() { mIsCorrect = true; - isNonZeroBlockSizes(mIsCorrect, DataBlockWrapper<Header>::mNelements); // checking sub-block(header) size - (isNonZeroBlockSizes(mIsCorrect, DataBlockWrapper<DataStructures>::mNelements), ...); // checking sub-block sizes + checkDeserialization(mIsCorrect, DataBlockWrapper<Header>::mIsIncorrect); // checking deserialization status for header + (checkDeserialization(mIsCorrect, DataBlockWrapper<DataStructures>::mIsIncorrect), ...); // checking deserialization status for sub-block static_cast<DataBlock*>(this)->sanityCheck(mIsCorrect); } @@ -347,73 +350,9 @@ class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataB protected: //check if there are sub blocks with zero number of elements void isNonZeroBlockSizes(bool& flag, unsigned int nElements) { flag &= (bool)nElements; } - //void updateSize(size_t blockSize) { mSize += blockSize; } -}; - -//FT0 DATA BLOCK DEFINITIONS - -//standard data block from PM -class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> -{ - public: - DataBlockPM() = default; - DataBlockPM(const DataBlockPM&) = default; - void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) - { - DataBlockWrapper<RawHeaderPM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderPM>::MaxNwords, srcByteShift); - DataBlockWrapper<RawDataPM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderPM>::mData[0].nGBTWords, srcByteShift); - } - //Custom sanity checking for current deserialized block - // put here code for raw data checking - void sanityCheck(bool& flag) - { - if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) - DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling - //TODO, Descriptor checking, Channel range - } -}; - -//standard data block from TCM -class DataBlockTCM : public DataBlockBase<DataBlockTCM, RawHeaderTCM, RawDataTCM> -{ - public: - DataBlockTCM() = default; - DataBlockTCM(const DataBlockTCM&) = default; - void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) - { - DataBlockWrapper<RawHeaderTCM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCM>::MaxNwords, srcByteShift); - DataBlockWrapper<RawDataTCM>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCM>::mData[0].nGBTWords, srcByteShift); - } - //Custom sanity checking for current deserialized block - // put here code for raw data checking - void sanityCheck(bool& flag) - { - //TODO, Descriptor checking, Channel range - } -}; - -//extended TCM mode, 1 TCMdata + 8 TCMdataExtendedstructs -class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, RawDataTCM, RawDataTCMext> -{ - public: - DataBlockTCMext() = default; - DataBlockTCMext(const DataBlockTCMext&) = default; - //virtual ~DataBlockTCMext() = default; - void deserialize(gsl::span<const uint8_t> srcBytes, size_t& srcByteShift) - { - DataBlockWrapper<RawHeaderTCMext>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCMext>::MaxNwords, srcByteShift); - DataBlockWrapper<RawDataTCM>::deserialize(srcBytes, DataBlockWrapper<RawDataTCM>::MaxNwords, srcByteShift); - DataBlockWrapper<RawDataTCMext>::deserialize(srcBytes, DataBlockWrapper<RawHeaderTCMext>::mData[0].nGBTWords - DataBlockWrapper<RawDataTCM>::MaxNwords, srcByteShift); - } - - //Custom sanity checking for current deserialized block - // put here code for raw data checking - void sanityCheck(bool& flag) - { - //TODO, Descriptor checking, Channel range - } + void checkDeserialization(bool& flag, bool isIncorrect) { flag &= !(isIncorrect); } }; -} // namespace ft0 +} // namespace fit } // namespace o2 #endif \ No newline at end of file diff --git a/Detectors/FIT/raw/include/FITRaw/DigitBlockBase.h b/Detectors/FIT/raw/include/FITRaw/DigitBlockBase.h new file mode 100644 index 0000000000000..5fd2d2738c8d8 --- /dev/null +++ b/Detectors/FIT/raw/include/FITRaw/DigitBlockBase.h @@ -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. +// +//file DigitBlockBase.h base class for processing RAW data into Digits +// +// Artur.Furs +// afurs@cern.ch + +#ifndef ALICEO2_FIT_DIGITBLOCKBASE_H_ +#define ALICEO2_FIT_DIGITBLOCKBASE_H_ +#include <iostream> +#include <vector> +#include <algorithm> +#include <Rtypes.h> +#include <CommonDataFormat/InteractionRecord.h> + +#include <gsl/span> +namespace o2 +{ +namespace fit +{ +template <class DigitBlock> +class DigitBlockBase //:public DigitBlock +{ + public: + DigitBlockBase(o2::InteractionRecord intRec) + { /*static_cast<DigitBlock*>(this)->setIntRec(intRec);*/ + } + DigitBlockBase() = default; + DigitBlockBase(const DigitBlockBase& other) = default; + ~DigitBlockBase() = default; + template <class DataBlockType> + void process(DataBlockType& dataBlock, int linkID) + { + static_cast<DigitBlock*>(this)->processDigits(dataBlock, linkID); + } + template <class... DigitType> + void pop(std::vector<DigitType>&... vecDigits) + { + static_cast<DigitBlock*>(this)->getDigits(vecDigits...); + } +}; + +} // namespace fit +} // namespace o2 +#endif diff --git a/Detectors/FIT/raw/include/FITRaw/RawReaderBase.h b/Detectors/FIT/raw/include/FITRaw/RawReaderBase.h new file mode 100644 index 0000000000000..bc290305c5bca --- /dev/null +++ b/Detectors/FIT/raw/include/FITRaw/RawReaderBase.h @@ -0,0 +1,95 @@ +// 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 RawReaderBase.h base class for RAW data reading +// +// Artur.Furs +// afurs@cern.ch +// +//Main purpuse is to decode FT0 data blocks and push them to DigitBlockFT0 for process + +#ifndef ALICEO2_FIT_RAWREADERBASE_H_ +#define ALICEO2_FIT_RAWREADERBASE_H_ +#include <iostream> +#include <vector> +#include <map> + +#include <Rtypes.h> +#include <CommonDataFormat/InteractionRecord.h> +#include "Headers/RAWDataHeader.h" +#include <Framework/Logger.h> + +#include <gsl/span> +namespace o2 +{ +namespace fit +{ +template <class DigitBlockType> +class RawReaderBase +{ + public: + RawReaderBase() = default; + ~RawReaderBase() = default; + + std::map<InteractionRecord, DigitBlockType> mMapDigits; + + //decoding binary data into data blocks + template <class DataBlockType> + size_t decodeBlocks(const gsl::span<const uint8_t> binaryPayload, std::vector<DataBlockType>& vecDataBlocks) + { + size_t srcPos = 0; + while (srcPos < binaryPayload.size()) { //checking element + DataBlockType dataBlock; + dataBlock.decodeBlock(binaryPayload, srcPos); + srcPos += dataBlock.mSize; + if (dataBlock.isCorrect()) + vecDataBlocks.push_back(dataBlock); //change to in-place construction? TODO + else + LOG(INFO) << "WARNING! INCORRECT DATA BLOCK!"; + } + return srcPos; + } + + //processing data blocks into digits + template <class DataBlockType> + void processBinaryData(gsl::span<const uint8_t> payload, int linkID) + { + std::vector<DataBlockType> vecDataBlocks; + auto srcPos = decodeBlocks(payload, vecDataBlocks); + + for (auto& dataBlock : vecDataBlocks) { + auto intRec = dataBlock.getInteractionRecord(); + auto [digitIter, isNew] = mMapDigits.try_emplace(intRec, intRec); + digitIter->second.template process<DataBlockType>(dataBlock, linkID); + } + } + /* + void process(int linkID, gsl::span<const uint8_t> payload) + { + static_cast<RawReader*>(this)->processDigits(linkID,payload); + } + */ + //pop digits + template <class... DigitType> + int getDigits(std::vector<DigitType>&... vecDigit) + { + int digitCounter = mMapDigits.size(); + for (auto& digit : mMapDigits) { + digit.second.pop(vecDigit...); + } + mMapDigits.clear(); + return digitCounter; + } +}; + +} // namespace fit +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/FIT/raw/src/DataBlockBase.cxx b/Detectors/FIT/raw/src/DataBlockBase.cxx new file mode 100644 index 0000000000000..82ed86360af98 --- /dev/null +++ b/Detectors/FIT/raw/src/DataBlockBase.cxx @@ -0,0 +1,12 @@ +// 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 "FITRaw/DataBlockBase.h" +using namespace o2::fit; diff --git a/Detectors/FIT/raw/src/DigitBlockBase.cxx b/Detectors/FIT/raw/src/DigitBlockBase.cxx new file mode 100644 index 0000000000000..9e626d77b064a --- /dev/null +++ b/Detectors/FIT/raw/src/DigitBlockBase.cxx @@ -0,0 +1,12 @@ +// 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 "FITRaw/DigitBlockBase.h" +using namespace o2::fit; \ No newline at end of file diff --git a/Detectors/FIT/raw/src/FITRawLinkDef.h b/Detectors/FIT/raw/src/FITRawLinkDef.h new file mode 100644 index 0000000000000..9fb7fce75f028 --- /dev/null +++ b/Detectors/FIT/raw/src/FITRawLinkDef.h @@ -0,0 +1,24 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; +/* +#pragma link C++ class o2::ft0::DataBlockPM + ; +#pragma link C++ class o2::ft0::DataBlockTCM + ; +#pragma link C++ class o2::ft0::DataBlockTCMext + ; +#pragma link C++ class o2::ft0::DigitBlockFT0 + ; +#pragma link C++ class o2::ft0::RawReaderFT0 < true> + ; +#pragma link C++ class o2::ft0::RawReaderFT0 < false> + ; +*/ +#endif diff --git a/Detectors/FIT/raw/src/RawReaderBase.cxx b/Detectors/FIT/raw/src/RawReaderBase.cxx new file mode 100644 index 0000000000000..24b38a3138533 --- /dev/null +++ b/Detectors/FIT/raw/src/RawReaderBase.cxx @@ -0,0 +1,12 @@ +// 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 "FITRaw/RawReaderBase.h" +using namespace o2::fit; From 31b6b7c3d4253a7b7732a6bcfd641e1786b8008f Mon Sep 17 00:00:00 2001 From: Arthur Furs <9881239+afurs@users.noreply.github.com> Date: Wed, 21 Oct 2020 18:43:00 +0300 Subject: [PATCH 1097/1751] Update FT0DataReaderDPLSpec.h some comments deleted --- .../FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h index d48cb55d8fde3..3925995bab968 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/FT0DataReaderDPLSpec.h @@ -23,11 +23,7 @@ #include "Framework/WorkflowSpec.h" #include "Framework/SerializationMethods.h" #include "DPLUtils/DPLRawParser.h" -//#include "FT0Raw/RawReaderFT0.h" -//#include "FT0Raw/DigitBlockFT0.h" -//#include "DataFormatsFT0/Digit.h" -//#include "DataFormatsFT0/ChannelData.h" #include <iostream> #include <vector> #include <gsl/span> From 7ae1065a366566429a18b82a98599387e70d730c Mon Sep 17 00:00:00 2001 From: Arthur Furs <9881239+afurs@users.noreply.github.com> Date: Wed, 21 Oct 2020 18:44:17 +0300 Subject: [PATCH 1098/1751] Update DataBlockBase.h some comments deleted --- Detectors/FIT/raw/include/FITRaw/DataBlockBase.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h b/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h index 1ef0e7a7e826a..64842fd2bcae4 100644 --- a/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h +++ b/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h @@ -40,7 +40,6 @@ #include <vector> #include <Rtypes.h> #include "CommonDataFormat/InteractionRecord.h" -//#include <DataFormatsFT0/RawEventData.h> #include <gsl/span> #include <boost/mpl/inherit.hpp> #include <boost/mpl/vector.hpp> @@ -355,4 +354,4 @@ class DataBlockBase : public boost::mpl::inherit<DataBlockWrapper<Header>, DataB } // namespace fit } // namespace o2 -#endif \ No newline at end of file +#endif From 1687288072f70f6578383223020d7b8cb539e993 Mon Sep 17 00:00:00 2001 From: Arthur Furs <9881239+afurs@users.noreply.github.com> Date: Wed, 21 Oct 2020 18:44:56 +0300 Subject: [PATCH 1099/1751] Update FITRawLinkDef.h --- Detectors/FIT/raw/src/FITRawLinkDef.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Detectors/FIT/raw/src/FITRawLinkDef.h b/Detectors/FIT/raw/src/FITRawLinkDef.h index 9fb7fce75f028..71519a02a652e 100644 --- a/Detectors/FIT/raw/src/FITRawLinkDef.h +++ b/Detectors/FIT/raw/src/FITRawLinkDef.h @@ -13,12 +13,5 @@ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; -/* -#pragma link C++ class o2::ft0::DataBlockPM + ; -#pragma link C++ class o2::ft0::DataBlockTCM + ; -#pragma link C++ class o2::ft0::DataBlockTCMext + ; -#pragma link C++ class o2::ft0::DigitBlockFT0 + ; -#pragma link C++ class o2::ft0::RawReaderFT0 < true> + ; -#pragma link C++ class o2::ft0::RawReaderFT0 < false> + ; -*/ + #endif From a29cb21cf4f398366907287844358cc1c007d13a Mon Sep 17 00:00:00 2001 From: Arthur Furs <9881239+afurs@users.noreply.github.com> Date: Wed, 21 Oct 2020 19:00:47 +0300 Subject: [PATCH 1100/1751] Update RawReaderFT0Base.h --- Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h b/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h index 7ff11acd0b038..213d869782df2 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h @@ -30,8 +30,6 @@ #include <CommonDataFormat/InteractionRecord.h> #include "Headers/RAWDataHeader.h" -//#include "DataFormatsFT0/Digit.h" -//#include "DataFormatsFT0/ChannelData.h" #include <gsl/span> @@ -75,4 +73,4 @@ using RawReaderFT0BaseExt = RawReaderFT0Base<DigitBlockFT0ext, DataBlockPM, Data } // namespace ft0 } // namespace o2 -#endif \ No newline at end of file +#endif From c0f2f2642ac51e71c6d1c6b30df93026b40bc5ec Mon Sep 17 00:00:00 2001 From: Arthur Furs <9881239+afurs@users.noreply.github.com> Date: Wed, 21 Oct 2020 19:01:33 +0300 Subject: [PATCH 1101/1751] Update FT0RawLinkDef.h --- Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h b/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h index e19b7f162e426..0928d12d07f28 100644 --- a/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h +++ b/Detectors/FIT/FT0/raw/src/FT0RawLinkDef.h @@ -20,7 +20,4 @@ #pragma link C++ class o2::ft0::DigitBlockFT0 + ; #pragma link C++ class o2::ft0::DigitBlockFT0ext + ; -//#pragma link C++ class o2::ft0::RawReaderFT0 < true> + ; -//#pragma link C++ class o2::ft0::RawReaderFT0 < false> + ; - #endif From 7ff2d30207e6b8c48a8bfe8a5855848c82a5839e Mon Sep 17 00:00:00 2001 From: Artur Furs <afurs@cern.ch> Date: Thu, 22 Oct 2020 19:33:35 +0300 Subject: [PATCH 1102/1751] README updated --- Detectors/FIT/raw/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Detectors/FIT/raw/README.md b/Detectors/FIT/raw/README.md index d51b86bb0737b..dbc0c741e7c41 100644 --- a/Detectors/FIT/raw/README.md +++ b/Detectors/FIT/raw/README.md @@ -16,7 +16,8 @@ usage:\ define "deserialization" method with deserialization logic for current DataBlock\ define "sanityCheck" method for checking if the DataBlock is correct\ Warning! Classes should be simple, without refs and pointers!\ - +Example: + /alice/O2/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h # DigitBlockBase Base class for digit block, which containes "digit" structures\ usage:\ @@ -25,7 +26,7 @@ usage:\ define "template <class DigitType,...>void getDigits(std::vector<DigitType>&... vecDigits) for pushing digits into vectors which will be pushed through DPL channels, variadic arguments are applied\ Example:\ - /alice/O2/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h \ + /alice/O2/Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h # RawReaderBase Base class for raw reader.\ @@ -38,4 +39,4 @@ Example:\ # RawReader Stores vectors with digit classes and manages them at DPL level\ Example: \ - /alice/O2/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0\ \ No newline at end of file + /alice/O2/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0 \ No newline at end of file From ca981855bbda9fff43ebda2d727c8f8a0107b07e Mon Sep 17 00:00:00 2001 From: Jorge Lopez <jorgext@gmail.com> Date: Mon, 26 Oct 2020 07:10:10 -0300 Subject: [PATCH 1103/1751] TRD: Fix trigger records (digitizer), and MC step size (hits) (#4680) * Fix TRD trigger records * Add getADCsum method to the Digit class * Fix analyze digit labels macro for new labels IO * Drop unnecessary conditional --- Detectors/TRD/base/include/TRDBase/Digit.h | 2 + .../include/TRDSimulation/Digitizer.h | 13 ++-- Detectors/TRD/simulation/src/Detector.cxx | 1 + Detectors/TRD/simulation/src/Digitizer.cxx | 29 --------- .../TRD/workflow/src/TRDDigitizerSpec.cxx | 59 ++++++++++++------- macro/analyzeDigitLabels.C | 10 ++-- 6 files changed, 53 insertions(+), 61 deletions(-) diff --git a/Detectors/TRD/base/include/TRDBase/Digit.h b/Detectors/TRD/base/include/TRDBase/Digit.h index 8c6bb74629226..50cc405d209a6 100644 --- a/Detectors/TRD/base/include/TRDBase/Digit.h +++ b/Detectors/TRD/base/include/TRDBase/Digit.h @@ -15,6 +15,7 @@ #include <vector> #include <array> #include <unordered_map> +#include <numeric> #include "Rtypes.h" // for ClassDef #include "CommonDataFormat/TimeStamp.h" @@ -52,6 +53,7 @@ class Digit : public TimeStamp int getRow() const { return mRow; } int getPad() const { return mPad; } ArrayADC const& getADC() const { return mADC; } + ADC_t getADCsum() const { return std::accumulate(mADC.begin(), mADC.end(), (ADC_t)0); } private: std::uint16_t mDetector{0}; // TRD detector number, 0-539 diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h index 4b6106a313564..d716acbeb1f00 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h @@ -59,6 +59,7 @@ class Digitizer void process(std::vector<HitType> const&, DigitContainer&, o2::dataformats::MCTruthContainer<MCLabel>&); void flush(DigitContainer&, o2::dataformats::MCTruthContainer<MCLabel>&); + void pileup(); void setEventTime(double timeNS) { mTime = timeNS; } void setEventID(int entryID) { mEventID = entryID; } void setSrcID(int sourceID) { mSrcID = sourceID; } @@ -67,6 +68,11 @@ class Digitizer int getEventID() const { return mEventID; } int getSrcID() const { return mSrcID; } + // Trigger parameters + static constexpr double READOUT_TIME = 3000; // the time the readout takes, as 30 TB = 3 micro-s. + static constexpr double DEAD_TIME = 200; // trigger deadtime, 2 micro-s + static constexpr double BUSY_TIME = READOUT_TIME + DEAD_TIME; // the time for which no new trigger can be received in nanoseconds + private: TRDGeometry* mGeo = nullptr; // access to TRDGeometry PadResponse* mPRF = nullptr; // access to PadResponse @@ -96,12 +102,6 @@ class Digitizer kEmbeddingEvent }; - // Trigger parameters - bool mTriggeredEvent = false; - static constexpr double READOUT_TIME = 3000; // the time the readout takes, as 30 TB = 3 micro-s. - static constexpr double DEAD_TIME = 200; // trigger deadtime, 2 micro-s - static constexpr double BUSY_TIME = READOUT_TIME + DEAD_TIME; // the time for which no new trigger can be received in nanoseconds - // Digitization parameters static constexpr float AmWidth = TRDGeometry::amThick(); // Width of the amplification region static constexpr float DrWidth = TRDGeometry::drThick(); // Width of the drift retion @@ -125,7 +125,6 @@ class Digitizer // Digitization chain methods int triggerEventProcessing(DigitContainer&, o2::dataformats::MCTruthContainer<MCLabel>&); - void pileup(); SignalContainer addSignalsFromPileup(); void clearContainers(); bool convertHits(const int, const std::vector<HitType>&, SignalContainer&, int thread = 0); // True if hit-to-signal conversion is successful diff --git a/Detectors/TRD/simulation/src/Detector.cxx b/Detectors/TRD/simulation/src/Detector.cxx index f2e69fb2b78ba..5f7b638dcb4ed 100644 --- a/Detectors/TRD/simulation/src/Detector.cxx +++ b/Detectors/TRD/simulation/src/Detector.cxx @@ -92,6 +92,7 @@ bool Detector::ProcessHits(FairVolume* v) if ((!fMC->TrackCharge()) || fMC->IsTrackDisappeared()) { return false; } + fMC->SetMaxStep(0.1); // Should we optimize this value? // Inside sensitive volume ? bool drRegion = false; diff --git a/Detectors/TRD/simulation/src/Digitizer.cxx b/Detectors/TRD/simulation/src/Digitizer.cxx index efcc78e90545a..7a5d429c345ac 100644 --- a/Detectors/TRD/simulation/src/Digitizer.cxx +++ b/Detectors/TRD/simulation/src/Digitizer.cxx @@ -188,33 +188,6 @@ void Digitizer::clearContainers() } } -int Digitizer::triggerEventProcessing(DigitContainer& digits, o2::dataformats::MCTruthContainer<MCLabel>& labels) -{ - if (mCurrentTriggerTime < 0 && mLastTime < 0) { - // very first event - mCurrentTriggerTime = mTime; - mLastTime = mTime; - return EventType::kFirstEvent; - } - if (mTime > mLastTime) { - if ((mTime - mCurrentTriggerTime) < BUSY_TIME) { - // send the signal containers to the pileup container, and do not change the current trigger time. - pileup(); - mLastTime = mTime; - return EventType::kPileupEvent; - } else { - // flush the digits: signals from the pileup container are converted to adcs - // digits and labels are produced, and the current trigger time is changed after the flush is completed - flush(digits, labels); - mCurrentTriggerTime = mTime; - mLastTime = mTime; - return EventType::kTriggerFired; - } - } else { - return EventType::kEmbeddingEvent; - } -} - void Digitizer::process(std::vector<HitType> const& hits, DigitContainer& digits, o2::dataformats::MCTruthContainer<MCLabel>& labels) { @@ -222,8 +195,6 @@ void Digitizer::process(std::vector<HitType> const& hits, DigitContainer& digits LOG(FATAL) << "TRD Calibration database not available"; } - int status = triggerEventProcessing(digits, labels); - // Get the a hit container for all the hits in a given detector then call convertHits for a given detector (0 - 539) std::array<std::vector<HitType>, MAXCHAMBER> hitsPerDetector; getHitContainerPerDetector(hits, hitsPerDetector); diff --git a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx index 7093d336e369a..5d8ca8b7b5257 100644 --- a/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDDigitizerSpec.cxx @@ -79,44 +79,61 @@ class TRDDPLDigitizerTask : public o2::base::BaseDPLDigitizer std::vector<o2::trd::Digit> digits; // digits which get filled o2::dataformats::MCTruthContainer<o2::trd::MCLabel> labels; // labels which get filled + o2::InteractionTimeRecord currentTime; // the current time + o2::InteractionTimeRecord triggerTime; // the time at which the TRD start reading out a signal + bool firstEvent = true; // Flag for the first event processed + TStopwatch timer; timer.Start(); - // loop over all composite collisions given from context // (aka loop over all the interaction records) for (int collID = 0; collID < irecords.size(); ++collID) { - mDigitizer.setEventTime(irecords[collID].getTimeNS()); + currentTime = irecords[collID]; + // Trigger logic implemented here + if (firstEvent) { + triggerTime = currentTime; + firstEvent = false; + } else { + double dT = currentTime.getTimeNS() - triggerTime.getTimeNS(); + if (dT < o2::trd::Digitizer::BUSY_TIME) { + // BUSY_TIME = READOUT_TIME + DEAD_TIME, if less than that, pile up the signals and update the last time + mDigitizer.pileup(); + } else { + // A new signal can be received, and the detector read it out: + // flush previous stored digits, labels and keep a trigger record + // then update the trigger time to the new one + mDigitizer.flush(digits, labels); + assert(digits.size() == labels.getIndexedSize()); + // Add trigger record, and send digits to the accumulator + triggers.emplace_back(triggerTime, digitsAccum.size(), digits.size()); + std::copy(digits.begin(), digits.end(), std::back_inserter(digitsAccum)); + if (mctruth) { + labelsAccum.mergeAtBack(labels); + } + triggerTime = currentTime; + digits.clear(); + labels.clear(); + } + } + + mDigitizer.setEventTime(triggerTime.getTimeNS()); // do we need this? // for each collision, loop over the constituents event and source IDs // (background signal merging is basically taking place here) for (auto& part : eventParts[collID]) { mDigitizer.setEventID(part.entryID); mDigitizer.setSrcID(part.sourceID); - - // get the hits for this event and this source + // get the hits for this event and this source and process them std::vector<o2::trd::HitType> hits; context->retrieveHits(mSimChains, "TRDHit", part.sourceID, part.entryID, &hits); - LOG(INFO) << "For collision " << collID << " eventID " << part.entryID << " found TRD " << hits.size() << " hits "; - mDigitizer.process(hits, digits, labels); - assert(digits.size() == labels.getIndexedSize()); - - // Add trigger record - triggers.emplace_back(irecords[collID], digitsAccum.size(), digits.size()); - - std::copy(digits.begin(), digits.end(), std::back_inserter(digitsAccum)); - if (mctruth) { - labelsAccum.mergeAtBack(labels); - } - digits.clear(); - labels.clear(); } } + // Force flush of the digits that remain in the digitizer cache mDigitizer.flush(digits, labels); assert(digits.size() == labels.getIndexedSize()); - - triggers.emplace_back(irecords[irecords.size() - 1], digitsAccum.size(), digits.size()); + triggers.emplace_back(triggerTime, digitsAccum.size(), digits.size()); std::copy(digits.begin(), digits.end(), std::back_inserter(digitsAccum)); if (mctruth) { labelsAccum.mergeAtBack(labels); @@ -146,7 +163,7 @@ class TRDDPLDigitizerTask : public o2::base::BaseDPLDigitizer std::vector<TChain*> mSimChains; // RS: at the moment using hardcoded flag for continuos readout o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::PRESENT; // readout mode -}; +}; // namespace trd o2::framework::DataProcessorSpec getTRDDigitizerSpec(int channel, bool mctruth) { @@ -173,5 +190,5 @@ o2::framework::DataProcessorSpec getTRDDigitizerSpec(int channel, bool mctruth) Options{}}; } -} // end namespace trd +} // namespace trd } // end namespace o2 diff --git a/macro/analyzeDigitLabels.C b/macro/analyzeDigitLabels.C index ad1902f65bff6..19fc2d6129403 100644 --- a/macro/analyzeDigitLabels.C +++ b/macro/analyzeDigitLabels.C @@ -79,14 +79,16 @@ void analyse(TTree* tr, const char* brname, Accumulator& prop) return; } auto entries = br->GetEntries(); - o2::dataformats::MCTruthContainer<LabelType>* labels = nullptr; - br->SetAddress(&labels); + o2::dataformats::IOMCTruthContainerView* io2 = nullptr; + br->SetAddress(&io2); for (int i = 0; i < entries; ++i) { br->GetEntry(i); + o2::dataformats::ConstMCTruthContainer<LabelType> labels; + io2->copyandflatten(labels); - for (int i = 0; i < (int)labels->getIndexedSize(); ++i) { - prop.addLabels(labels->getLabels(i)); + for (int i = 0; i < (int)labels.getIndexedSize(); ++i) { + prop.addLabels(labels.getLabels(i)); } } }; From 57c8818a626a1629900f5452afb3b931b6f020b9 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 26 Oct 2020 14:35:09 +0100 Subject: [PATCH 1104/1751] Simple GRID submission tool A helper script, making it easy to submit existing local scripts as an ALIEN GRID job (with the following notation): grid-submit my_script.sh jobname All communication with the GRID system will be done by the script and JDLs setup automatically. This can also be used to emulate a GRID-like environment locally. Mainly a convenience tool for (aliperf) testing. Not yet powerful for production usages. --- Utilities/Tools/CMakeLists.txt | 1 + Utilities/Tools/grid_submit.sh | 186 +++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100755 Utilities/Tools/grid_submit.sh diff --git a/Utilities/Tools/CMakeLists.txt b/Utilities/Tools/CMakeLists.txt index f8459d0cf14ea..b8c1346d84d49 100644 --- a/Utilities/Tools/CMakeLists.txt +++ b/Utilities/Tools/CMakeLists.txt @@ -11,3 +11,4 @@ install(PROGRAMS monitor-mem.sh DESTINATION share/scripts/) install(PROGRAMS jobutils.sh DESTINATION share/scripts/) +install(PROGRAMS grid_submit.sh DESTINATION share/scripts/) diff --git a/Utilities/Tools/grid_submit.sh b/Utilities/Tools/grid_submit.sh new file mode 100755 index 0000000000000..be58158393f71 --- /dev/null +++ b/Utilities/Tools/grid_submit.sh @@ -0,0 +1,186 @@ +#!/bin/bash + +# A helper script, making it easy to submit existing +# scripts as an ALIEN GRID job (with the following notation): +# +# grid-submit my_script.sh jobname +# +# The script then handles all interaction with the GRID automatically. The user +# does not need to create JDLs files nor upload them to the GRID manually/herself. +# +# The script can also simulate execution of the job locally. To this end, it suffices +# to say +# +# ALIEN_PROC_ID=1 grid-submit my_script.sh +# +# Currently handles only a very basic JDL configuration. Further improvements would be: +# +# -) allow JDL customization via command line arguments or JDL tags inside the script +# + +# set -o pipefail + +function per() { printf "\033[31m$1\033[m\n" >&2; } +function pok() { printf "\033[32m$1\033[m\n" >&2; } +function banner() { echo ; echo ==================== $1 ==================== ; } + +if [[ ! $ALIEN_PROC_ID && ! $1 ]]; then + per "Please give a job script" + exit 1 +fi + +# find out if this script is really executed on GRID +# in this case, we should be in a workdir labeled alien-job-${ALIEN_PROC_ID} +ONGRID=0 +$(cd ../alien-job-${ALIEN_PROC_ID} 2> /dev/null) +if [[ "$?" == "0" ]]; then + ONGRID=1 +fi + +# General job configuration +MY_USER=${ALIEN_USER:-`whoami`} +if [[ ! $MY_USER ]]; then + per "Problems retrieving current AliEn user. Did you run alien-token-init?" + exit 1 +fi +MY_HOMEDIR="/alice/cern.ch/user/${MY_USER:0:1}/${MY_USER}" +MY_BINDIR="$MY_HOMEDIR/bintest" +MY_JOBPREFIX="$MY_HOMEDIR/${ALIEN_TOPWORKDIR:-selfjobs}" +MY_JOBSCRIPT="$(cd "$(dirname "$1")" && pwd -P)/$(basename "$1")" # the job script with full path +MY_JOBNAME=${2:-$(basename ${MY_JOBSCRIPT})} +MY_JOBNAMEDATE="${MY_JOBNAME}-$(date -u +%Y%m%d-%H%M%S)" +MY_JOBWORKDIR="$MY_JOBPREFIX/${MY_JOBNAMEDATE}" # ISO-8601 UTC + +pok "Your job's working directory will be $MY_JOBWORKDIR" +pok "Set the job name by running $0 <scriptname> <jobname>" + +# +# Generate local workdir +# +if [[ "${ONGRID}" == "0" ]]; then + WORKDIR=${WORKDIR:-/tmp/alien_work/$(basename "$MY_JOBWORKDIR")} + mkdir -p ${WORKDIR} + cp "${MY_JOBSCRIPT}" "${WORKDIR}/alien_jobscript.sh" +fi + +# +# Submitter code +# +if [[ ! $ALIEN_PROC_ID ]]; then + # We are not on a worker node: assuming client --> test if alien is there? + which alien.py 2> /dev/null + # check exit code + if [[ ! "$?" == "0" ]]; then + XJALIEN_LATEST=`find /cvmfs/alice.cern.ch/el7-x86_64/Modules/modulefiles/xjalienfs -type f -printf "%f\n" | tail -n1` + banner "Loading xjalienfs package $XJALIEN_LATEST since not yet loaded" + eval "$(/cvmfs/alice.cern.ch/bin/alienv printenv xjalienfs::"$XJALIEN_LATEST")" + fi + + # Create temporary workdir to assemble files, and submit from there (or execute locally) + cd "$(dirname "$0")" + THIS_SCRIPT="$PWD/$(basename "$0")" + + cd "${WORKDIR}" + + # ---- Generate JDL ---------------- + # TODO: Make this configurable or read from a preamble section in the jobfile + cat > "${MY_JOBNAMEDATE}.jdl" <<EOF +Executable = "${MY_BINDIR}/${MY_JOBNAMEDATE}.sh"; +InputFile = "LF:${MY_JOBWORKDIR}/alien_jobscript.sh"; +OutputDir = "${MY_JOBWORKDIR}"; +Output = { + "*.log*,log.txt@disk=2" +}; +Requirements = member(other.GridPartitions,"multicore_8"); +MemorySize = "60GB"; +TTL=80000; +EOF +# + + pok "Local working directory is $PWD" + + pok "Preparing job \"$MY_JOBNAMEDATE\"" + ( + set -x + alien.py rmdir "$MY_JOBWORKDIR" || true # remove existing job dir + alien.py mkdir "$MY_BINDIR" || true # create bindir + alien.py mkdir "$MY_JOBPREFIX" || true # create job output prefix + alien.py mkdir jdl || true + alien.py mkdir "$MY_JOBWORKDIR" || true + alien.py rm "$MY_BINDIR/${MY_JOBNAMEDATE}.sh" || true # remove current job script + alien.py cp "${PWD}/${MY_JOBNAMEDATE}.jdl" alien://${MY_HOMEDIR}/jdl/${MY_JOBNAMEDATE}.jdl@ALICE::CERN::EOS || true # copy the jdl + alien.py cp "$THIS_SCRIPT" alien://${MY_BINDIR}/${MY_JOBNAMEDATE}.sh@ALICE::CERN::EOS || true # copy current job script to AliEn + alien.py cp "${MY_JOBSCRIPT}" alien://${MY_JOBWORKDIR}/alien_jobscript.sh@ALICE::CERN::EOS || true + ) &> alienlog.txt + + pok "Submitting job \"${MY_JOBNAMEDATE}\" from $PWD" + ( + alien.py submit jdl/${MY_JOBNAMEDATE}.jdl || true + ) &>> alienlog.txt + + MY_JOBID=$( (grep 'Your new job ID is' alienlog.txt | grep -oE '[0-9]+' || true) | sort -n | tail -n1) + if [[ $MY_JOBID ]]; then + pok "OK, display progress on https://alimonitor.cern.ch/agent/jobs/details.jsp?pid=$MY_JOBID" + else + per "Job submission failed: error log follows" + cat alienlog.txt + fi + + exit 0 +fi + +#################################################################################################### +# The following part is executed on the worker node or locally +#################################################################################################### +if [[ "${ONGRID}" == 0 ]]; then + banner "Executing job in directory ${WORKDIR}" + cd "${WORKDIR}" 2> /dev/null +fi + +# All is redirected to log.txt but kept on stdout as well +if [[ $ALIEN_PROC_ID ]]; then + exec &> >(tee -a log.txt) +fi + +# ----------- START JOB PREAMBLE ----------------------------- +banner "Environment" +env + +banner "OS detection" +lsb_release -a || true +cat /etc/os-release || true +cat /etc/redhat-release || true + +if [ ! "$O2_ROOT" ]; then + O2_PACKAGE_LATEST=`find /cvmfs/alice.cern.ch/el7-x86_64/Modules/modulefiles/O2 -type f -printf "%f\n" | tail -n1` + banner "Loading O2 package $O2_PACKAGE_LATEST" + eval "$(/cvmfs/alice.cern.ch/bin/alienv printenv O2::"$O2_PACKAGE_LATEST")" +fi +if [ ! "$XJALIEN_ROOT" ]; then + XJALIEN_LATEST=`find /cvmfs/alice.cern.ch/el7-x86_64/Modules/modulefiles/xjalienfs -type f -printf "%f\n" | tail -n1` + banner "Loading XJALIEN package $XJALIEN_LATEST" + eval "$(/cvmfs/alice.cern.ch/bin/alienv printenv xjalienfs::"$XJALIEN_LATEST")" +fi +if [ ! "$O2DPG_ROOT" ]; then + O2DPG_LATEST=`find /cvmfs/alice.cern.ch/el7-x86_64/Modules/modulefiles/O2DPG -type f -printf "%f\n" | tail -n1` + banner "Loading O2DPG package $O2DPG_LATEST" + eval "$(/cvmfs/alice.cern.ch/bin/alienv printenv O2DPG::"$O2DPG_LATEST")" +fi + +banner "Running workflow" + +ldd `which o2-sim` > ldd.log +ls > ls.log + +# collect some common information + +cat /proc/cpuinfo > cpuinfo.log +cat /proc/meminfo > meminfo.log + +# ----------- EXECUTE ACTUAL JOB ----------------------------- +# source the actual job script from the work dir +chmod +x ./alien_jobscript.sh +./alien_jobscript.sh + +# We need to exit for the ALIEN JOB HANDLER! +exit 0 From f8f5690291b3abc43e61557d07f38fb864ac1bce Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Mon, 26 Oct 2020 20:56:39 +0100 Subject: [PATCH 1105/1751] Enable reader / writer to use TF numbers consistently in input / output (#4683) Allow reader to read TF numbers and create a corresponding output. The writer reads these messages and creates accordingly the output folders --- .../include/Framework/DataInputDirector.h | 16 +++- .../include/Framework/DataOutputDirector.h | 5 +- .../include/Framework/runDataProcessing.h | 2 +- Framework/Core/src/AODReaderHelpers.cxx | 28 +++++- Framework/Core/src/CommonDataProcessors.cxx | 49 +++++++--- Framework/Core/src/DataInputDirector.cxx | 95 +++++++++++++------ Framework/Core/src/DataOutputDirector.cxx | 17 ++-- Framework/Core/src/WorkflowHelpers.cxx | 22 +++-- 8 files changed, 164 insertions(+), 70 deletions(-) diff --git a/Framework/Core/include/Framework/DataInputDirector.h b/Framework/Core/include/Framework/DataInputDirector.h index 952fd08e0f734..a059dafa8348d 100644 --- a/Framework/Core/include/Framework/DataInputDirector.h +++ b/Framework/Core/include/Framework/DataInputDirector.h @@ -27,10 +27,16 @@ using namespace rapidjson; struct FileNameHolder { std::string fileName; int numberOfTimeFrames = 0; + std::vector<uint64_t> listOfTimeFrameNumbers; std::vector<std::string> listOfTimeFrameKeys; }; FileNameHolder* makeFileNameHolder(std::string fileName); +struct FileAndFolder { + TFile* file = nullptr; + std::string folderName = ""; +}; + struct DataInputDescriptor { /// Holds information concerning the reading of an aod table. /// The information includes the table specification, treename, @@ -55,6 +61,7 @@ struct DataInputDescriptor { void addFileNameHolder(FileNameHolder* fn); int fillInputfiles(); + bool setFile(int counter); // getters std::string getInputfilesFilename(); @@ -63,7 +70,8 @@ struct DataInputDescriptor { int getNumberInputfiles() { return mfilenames.size(); } int getNumberTimeFrames() { return mtotalNumberTimeFrames; } - std::tuple<TFile*, std::string> getFileFolder(int counter, int numTF); + uint64_t getTimeFrameNumber(int counter, int numTF); + FileAndFolder getFileFolder(int counter, int numTF); void closeInputFile(); bool isAlienSupportOn() { return mAlienSupport; } @@ -103,10 +111,12 @@ struct DataInputDirector { // getters DataInputDescriptor* getDataInputDescriptor(header::DataHeader dh); + int getNumberInputDescriptors() { return mdataInputDescriptors.size(); } + std::unique_ptr<TTreeReader> getTreeReader(header::DataHeader dh, int counter, int numTF, std::string treeName); - std::tuple<TFile*, std::string> getFileFolder(header::DataHeader dh, int counter, int numTF); TTree* getDataTree(header::DataHeader dh, int counter, int numTF); - int getNumberInputDescriptors() { return mdataInputDescriptors.size(); } + uint64_t getTimeFrameNumber(header::DataHeader dh, int counter, int numTF); + FileAndFolder getFileFolder(header::DataHeader dh, int counter, int numTF); private: std::string minputfilesFile; diff --git a/Framework/Core/include/Framework/DataOutputDirector.h b/Framework/Core/include/Framework/DataOutputDirector.h index 706a0d7c8cfc0..4cf2fa13ad6b7 100644 --- a/Framework/Core/include/Framework/DataOutputDirector.h +++ b/Framework/Core/include/Framework/DataOutputDirector.h @@ -16,6 +16,7 @@ #include "Framework/DataDescriptorMatcher.h" #include "Framework/DataSpecUtils.h" #include "Framework/InputSpec.h" +#include "Framework/DataInputDirector.h" #include "rapidjson/fwd.h" @@ -72,7 +73,7 @@ struct DataOutputDirector { // read/write private members int getNumberTimeFramesToMerge() { return mnumberTimeFramesToMerge; } - void setNumberTimeFramesToMerge(int ntfmerge) { mnumberTimeFramesToMerge = ntfmerge; } + void setNumberTimeFramesToMerge(int ntfmerge) { mnumberTimeFramesToMerge = ntfmerge > 0 ? ntfmerge : 1; } std::string getFileMode() { return mfileMode; } void setFileMode(std::string filemode) { mfileMode = filemode; } @@ -81,7 +82,7 @@ struct DataOutputDirector { std::vector<DataOutputDescriptor*> getDataOutputDescriptors(InputSpec spec); // get the matching TFile - std::tuple<TFile*, std::string> getFileFolder(DataOutputDescriptor* dodesc, uint64_t folderNumber); + FileAndFolder getFileFolder(DataOutputDescriptor* dodesc, uint64_t folderNumber); void closeDataFiles(); diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index b2cc4606e6a83..7c6716fba485a 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -131,7 +131,7 @@ int main(int argc, char** argv) // options for AOD writer workflowOptions.push_back(ConfigParamSpec{"aod-writer-json", VariantType::String, "", {"Name of the json configuration file"}}); workflowOptions.push_back(ConfigParamSpec{"aod-writer-resfile", VariantType::String, "", {"Default name of the output file"}}); - workflowOptions.push_back(ConfigParamSpec{"aod-writer-resmode", VariantType::String, "", {"Creation mode of the result files: NEW, CREATE, RECREATE, UPDATE"}}); + workflowOptions.push_back(ConfigParamSpec{"aod-writer-resmode", VariantType::String, "RECREATE", {"Creation mode of the result files: NEW, CREATE, RECREATE, UPDATE"}}); workflowOptions.push_back(ConfigParamSpec{"aod-writer-ntfmerge", VariantType::Int, -1, {"Number of time frames to merge into one file"}}); workflowOptions.push_back(ConfigParamSpec{"aod-writer-keep", VariantType::String, "", {"Comma separated list of ORIGIN/DESCRIPTION/SUBSPECIFICATION:treename:col1/col2/..:filename"}}); diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 971c917c28169..32f3d8b0e5db3 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -187,12 +187,24 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() // get the run time watchdog auto* watchdog = new RuntimeWatchdog(options.get<int64_t>("time-limit")); + // selected the TFN input and // create list of requested tables - std::vector<OutputRoute> requestedTables(spec.outputs); + header::DataHeader TFNumberHeader; + std::vector<OutputRoute> requestedTables; + std::vector<OutputRoute> routes(spec.outputs); + for (auto route : routes) { + if (DataSpecUtils::partialMatch(route.matcher, header::DataOrigin("TFN"))) { + auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); + TFNumberHeader = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); + } else { + requestedTables.emplace_back(route); + } + } auto fileCounter = std::make_shared<int>(0); auto numTF = std::make_shared<int>(-1); - return adaptStateless([requestedTables, + return adaptStateless([TFNumberHeader, + requestedTables, fileCounter, numTF, watchdog, @@ -210,6 +222,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() // Each parallel reader device.inputTimesliceId reads the files fileCounter*device.maxInputTimeslices+device.inputTimesliceId // the TF to read is numTF assert(device.inputTimesliceId < device.maxInputTimeslices); + uint64_t timeFrameNumber = 0; int fcnt = (*fileCounter * device.maxInputTimeslices) + device.inputTimesliceId; int ntf = *numTF + 1; @@ -218,10 +231,11 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() bool first = true; for (auto route : requestedTables) { - // create a TreeToTable object + // create header auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); auto dh = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); + // create a TreeToTable object tr = didir->getDataTree(dh, fcnt, ntf); if (!tr) { if (first) { @@ -246,8 +260,13 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() throw std::runtime_error("Processing is stopped!"); } } - first = false; + if (first) { + timeFrameNumber = didir->getTimeFrameNumber(dh, fcnt, ntf); + auto o = Output(TFNumberHeader); + outputs.make<uint64_t>(o) = timeFrameNumber; + } + // create table output auto o = Output(dh); auto& t2t = outputs.make<TreeToTable>(o); @@ -263,6 +282,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() // fill the table t2t.fill(tr); + first = false; } // save file number and time frame diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index c243036e90e20..509476072494c 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -399,32 +399,57 @@ DataProcessorSpec auto& callbacks = ic.services().get<CallbackService>(); callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); + // prepare map<uint64_t, uint64_t>(startTime, tfNumber) + std::map<uint64_t, uint64_t> tfNumbers; + // this functor is called once per time frame - return std::move([dod](ProcessingContext& pc) mutable -> void { + return std::move([dod, tfNumbers](ProcessingContext& pc) mutable -> void { LOGP(DEBUG, "======== getGlobalAODSink::processing =========="); LOGP(DEBUG, " processing data set with {} entries", pc.inputs().size()); // return immediately if pc.inputs() is empty. This should never happen! - auto ninputs = pc.inputs().size(); - if (ninputs == 0) { + if (pc.inputs().size() == 0) { LOGP(INFO, "No inputs available!"); return; } + // update tfNumbers + uint64_t startTime = 0; + uint64_t tfNumber = 0; + auto ref = pc.inputs().get("tfn"); + if (ref.spec && ref.payload) { + startTime = DataRefUtils::getHeader<DataProcessingHeader*>(ref)->startTime; + tfNumber = pc.inputs().get<uint64_t>("tfn"); + tfNumbers.insert(std::pair<uint64_t, uint64_t>(startTime, tfNumber)); + } + // loop over the DataRefs which are contained in pc.inputs() for (const auto& ref : pc.inputs()) { + if (!ref.spec || !ref.payload) { + LOGP(WARNING, "The input \"{}\" is not valid and will be skipped!", ref.spec->binding); + continue; + } + + // skip non-AOD refs + if (!DataSpecUtils::partialMatch(*ref.spec, header::DataOrigin("AOD"))) { + continue; + } + startTime = DataRefUtils::getHeader<DataProcessingHeader*>(ref)->startTime; // does this need to be saved? auto dh = DataRefUtils::getHeader<header::DataHeader*>(ref); - auto dataProcessingHeader = DataRefUtils::getHeader<DataProcessingHeader*>(ref); - - // the startTime contained in the header determines the folder number - uint64_t folderNumber = dataProcessingHeader->startTime; - - // get the relevant DataOutputDescriptors auto ds = dod->getDataOutputDescriptors(*dh); if (ds.size() > 0) { + // get TF number fro startTime + auto it = tfNumbers.find(startTime); + if (it != tfNumbers.end()) { + tfNumber = (it->second / dod->getNumberTimeFramesToMerge()) * dod->getNumberTimeFramesToMerge(); + } else { + LOGP(FATAL, "No time frame number found for output with start time {}", startTime); + throw std::runtime_error("Processing is stopped!"); + } + // get the TableConsumer and corresponding arrow table auto s = pc.inputs().get<TableConsumer>(ref.spec->binding); auto table = s->asArrowTable(); @@ -440,10 +465,10 @@ DataProcessorSpec // e.g. different selections of columns to different files for (auto d : ds) { - auto [file, directory] = dod->getFileFolder(d, folderNumber); - auto treename = directory + d->treename; + auto fileAndFolder = dod->getFileFolder(d, tfNumber); + auto treename = fileAndFolder.folderName + d->treename; TableToTree ta2tr(table, - file, + fileAndFolder.file, treename.c_str()); if (d->colnames.size() > 0) { diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index ecaa59ea4a123..a4ec70289a284 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -78,18 +78,11 @@ void DataInputDescriptor::addFileNameHolder(FileNameHolder* fn) mfilenames.emplace_back(fn); } -std::tuple<TFile*, std::string> DataInputDescriptor::getFileFolder(int counter, int numTF) +bool DataInputDescriptor::setFile(int counter) { - std::string directoryName(""); - // no files left if (counter >= getNumberInputfiles()) { - return std::make_tuple((TFile*)nullptr, directoryName); - } - - // no TF left - if (mfilenames[counter]->numberOfTimeFrames > 0 && numTF >= mfilenames[counter]->numberOfTimeFrames) { - return std::make_tuple((TFile*)nullptr, directoryName); + return false; } // open file @@ -106,30 +99,64 @@ std::tuple<TFile*, std::string> DataInputDescriptor::getFileFolder(int counter, throw std::runtime_error(fmt::format("Couldn't open file \"{}\"!", filename)); } - // get the directory name + // get the directory names if (mfilenames[counter]->numberOfTimeFrames <= 0) { std::regex TFRegex = std::regex("TF_[0-9]+"); TList* keyList = mcurrentFile->GetListOfKeys(); // extract TF numbers and sort accordingly - std::list<uint64_t> folderNumbers; for (auto key : *keyList) { if (std::regex_match(((TObjString*)key)->GetString().Data(), TFRegex)) { auto folderNumber = std::stoul(std::string(((TObjString*)key)->GetString().Data()).substr(3)); - folderNumbers.emplace_back(folderNumber); + mfilenames[counter]->listOfTimeFrameNumbers.emplace_back(folderNumber); } } - folderNumbers.sort(); + std::sort(mfilenames[counter]->listOfTimeFrameNumbers.begin(), mfilenames[counter]->listOfTimeFrameNumbers.end()); - for (auto folderNumber : folderNumbers) { + for (auto folderNumber : mfilenames[counter]->listOfTimeFrameNumbers) { auto folderName = "TF_" + std::to_string(folderNumber); mfilenames[counter]->listOfTimeFrameKeys.emplace_back(folderName); } mfilenames[counter]->numberOfTimeFrames = mfilenames[counter]->listOfTimeFrameKeys.size(); } - directoryName = (mfilenames[counter]->listOfTimeFrameKeys)[numTF]; - return std::make_tuple(mcurrentFile, directoryName); + return true; +} + +uint64_t DataInputDescriptor::getTimeFrameNumber(int counter, int numTF) +{ + + // open file + if (!setFile(counter)) { + return 0ul; + } + + // no TF left + if (mfilenames[counter]->numberOfTimeFrames > 0 && numTF >= mfilenames[counter]->numberOfTimeFrames) { + return 0ul; + } + + return (mfilenames[counter]->listOfTimeFrameNumbers)[numTF]; +} + +FileAndFolder DataInputDescriptor::getFileFolder(int counter, int numTF) +{ + FileAndFolder fileAndFolder; + + // open file + if (!setFile(counter)) { + return fileAndFolder; + } + + // no TF left + if (mfilenames[counter]->numberOfTimeFrames > 0 && numTF >= mfilenames[counter]->numberOfTimeFrames) { + return fileAndFolder; + } + + fileAndFolder.file = mcurrentFile; + fileAndFolder.folderName = (mfilenames[counter]->listOfTimeFrameKeys)[numTF]; + + return fileAndFolder; } void DataInputDescriptor::closeInputFile() @@ -471,28 +498,38 @@ std::unique_ptr<TTreeReader> DataInputDirector::getTreeReader(header::DataHeader didesc = mdefaultDataInputDescriptor; } - auto [file, directory] = didesc->getFileFolder(counter, numTF); - if (file) { - treename = directory + "/" + treename; - reader = std::make_unique<TTreeReader>(treename.c_str(), file); + auto fileAndFolder = didesc->getFileFolder(counter, numTF); + if (fileAndFolder.file) { + treename = fileAndFolder.folderName + "/" + treename; + reader = std::make_unique<TTreeReader>(treename.c_str(), fileAndFolder.file); if (!reader) { - throw std::runtime_error(fmt::format(R"(Couldn't create TTreeReader for tree "{}" in file "{}")", treename, file->GetName())); + throw std::runtime_error(fmt::format(R"(Couldn't create TTreeReader for tree "{}" in file "{}")", treename, fileAndFolder.file->GetName())); } } return reader; } -std::tuple<TFile*, std::string> DataInputDirector::getFileFolder(header::DataHeader dh, int counter, int numTF) +FileAndFolder DataInputDirector::getFileFolder(header::DataHeader dh, int counter, int numTF) +{ + auto didesc = getDataInputDescriptor(dh); + // if NOT match then use defaultDataInputDescriptor + if (!didesc) { + didesc = mdefaultDataInputDescriptor; + } + + return didesc->getFileFolder(counter, numTF); +} + +uint64_t DataInputDirector::getTimeFrameNumber(header::DataHeader dh, int counter, int numTF) { auto didesc = getDataInputDescriptor(dh); // if NOT match then use defaultDataInputDescriptor if (!didesc) { didesc = mdefaultDataInputDescriptor; } - auto [file, directory] = didesc->getFileFolder(counter, numTF); - return std::make_tuple(file, directory); + return didesc->getTimeFrameNumber(counter, numTF); } TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter, int numTF) @@ -512,12 +549,12 @@ TTree* DataInputDirector::getDataTree(header::DataHeader dh, int counter, int nu treename = aod::datamodel::getTreeName(dh); } - auto [file, directory] = didesc->getFileFolder(counter, numTF); - if (file) { - treename = directory + "/" + treename; - tree = (TTree*)file->Get(treename.c_str()); + auto fileAndFolder = didesc->getFileFolder(counter, numTF); + if (fileAndFolder.file) { + treename = fileAndFolder.folderName + "/" + treename; + tree = (TTree*)fileAndFolder.file->Get(treename.c_str()); if (!tree) { - throw std::runtime_error(fmt::format(R"(Couldn't get TTree "{}" from "{}")", treename, file->GetName())); + throw std::runtime_error(fmt::format(R"(Couldn't get TTree "{}" from "{}")", treename, fileAndFolder.file->GetName())); } } diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index f1f8857395457..4c71b4ef1e554 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -428,11 +428,10 @@ std::vector<DataOutputDescriptor*> DataOutputDirector::getDataOutputDescriptors( return result; } -std::tuple<TFile*, std::string> DataOutputDirector::getFileFolder(DataOutputDescriptor* dodesc, uint64_t folderNumber) +FileAndFolder DataOutputDirector::getFileFolder(DataOutputDescriptor* dodesc, uint64_t folderNumber) { // initialisation - TFile* filePtr = nullptr; - std::string directoryName(""); + FileAndFolder fileAndFolder; // search dodesc->filename in mfilenameBases and return corresponding filePtr auto it = std::find(mfilenameBases.begin(), mfilenameBases.end(), dodesc->getFilenameBase()); @@ -442,18 +441,18 @@ std::tuple<TFile*, std::string> DataOutputDirector::getFileFolder(DataOutputDesc auto fn = mfilenameBases[ind] + ".root"; mfilePtrs[ind] = new TFile(fn.c_str(), mfileMode.c_str()); } - filePtr = mfilePtrs[ind]; + fileAndFolder.file = mfilePtrs[ind]; // check if folder TF_* exists - directoryName = "TF_" + std::to_string(folderNumber) + "/"; - auto key = filePtr->GetKey(directoryName.c_str()); + fileAndFolder.folderName = "TF_" + std::to_string(folderNumber) + "/"; + auto key = fileAndFolder.file->GetKey(fileAndFolder.folderName.c_str()); if (!key) { - filePtr->mkdir(directoryName.c_str()); + fileAndFolder.file->mkdir(fileAndFolder.folderName.c_str()); } - filePtr->cd(directoryName.c_str()); + fileAndFolder.file->cd(fileAndFolder.folderName.c_str()); } - return std::make_tuple(filePtr, directoryName); + return fileAndFolder; } void DataOutputDirector::closeDataFiles() diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 132f691ee23b0..894bf015be996 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -407,12 +407,15 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext extraSpecs.push_back(indexBuilder); } + // add the reader if (aodReader.outputs.empty() == false) { + aodReader.outputs.emplace_back(OutputSpec{"TFN", "TFNumber"}); extraSpecs.push_back(timePipeline(aodReader, ctx.options().get<int64_t>("readers"))); auto concrete = DataSpecUtils::asConcreteDataMatcher(aodReader.inputs[0]); timer.outputs.emplace_back(OutputSpec{concrete.origin, concrete.description, concrete.subSpec, Lifetime::Enumeration}); } + // add the timer if (timer.outputs.empty() == false) { extraSpecs.push_back(timer); } @@ -431,21 +434,15 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); + extraSpecs.clear(); - /// This will create different file sinks - /// . AOD - getGlobalAODSink - /// . dangling, not AOD - getGlobalFileSink - /// - // First analyze all ouputs + /// Analyze all ouputs // outputTypes = isAOD*2 + isdangling*1 + 0 auto [OutputsInputs, outputTypes] = analyzeOutputs(workflow); // create DataOutputDescriptor std::shared_ptr<DataOutputDirector> dod = getDataOutputDirector(ctx.options(), OutputsInputs, outputTypes); - // file sink for any AOD output - extraSpecs.clear(); - // select outputs of type AOD which need to be saved // ATTENTION: if there are dangling outputs the getGlobalAODSink // has to be created in any case! @@ -459,15 +456,18 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } } + // file sink for any AOD output if (outputsInputsAOD.size() > 0) { + // add TFNumber as input to the writer + outputsInputsAOD.emplace_back(InputSpec{"tfn", "TFN", "TFNumber"}); auto fileSink = CommonDataProcessors::getGlobalAODSink(dod, outputsInputsAOD); extraSpecs.push_back(fileSink); } - workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); - // file sink for notAOD dangling outputs + workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); extraSpecs.clear(); + // file sink for notAOD dangling outputs // select dangling outputs which are not of type AOD std::vector<InputSpec> outputsInputsDangling; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { @@ -489,7 +489,9 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext if (unmatched.size() > 0) { extraSpecs.push_back(CommonDataProcessors::getDummySink(unmatched)); } + workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); + extraSpecs.clear(); } void WorkflowHelpers::constructGraph(const WorkflowSpec& workflow, From a8677d9fbfa5e4666aba40b79a60e9ecc1477c3a Mon Sep 17 00:00:00 2001 From: Matteo Concas <mconcas@cern.ch> Date: Mon, 26 Oct 2020 20:56:59 +0100 Subject: [PATCH 1106/1751] [ITS EVE] Fix typo in geometry list (#4689) I was playing a bit with the event display and I saw a missing stave not being displayed. --- Detectors/ITSMFT/ITS/macros/EVE/geom_list_ITS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/macros/EVE/geom_list_ITS.txt b/Detectors/ITSMFT/ITS/macros/EVE/geom_list_ITS.txt index ec12b17e5b6f6..ad648c2945c20 100644 --- a/Detectors/ITSMFT/ITS/macros/EVE/geom_list_ITS.txt +++ b/Detectors/ITSMFT/ITS/macros/EVE/geom_list_ITS.txt @@ -4,7 +4,7 @@ #/cave_1/barrel_1/ITSV_2/ITSUWrapVol0_1/ITSULayer0_1 # #/cave_1/barrel_1/ITSV_2/ITSUWrapVol0_1/ITSULayer0_1/ITSUStave0_0 -/cave_1/barrel_1/barel_1/ITSV_2/ITSUWrapVol0_1/ITSULayer0_1/ITSUStave0_0/ITSUHalfStave0_0 +/cave_1/barrel_1/ITSV_2/ITSUWrapVol0_1/ITSULayer0_1/ITSUStave0_0/ITSUHalfStave0_0 #/cave_1/barrel_1/ITSV_2/ITSUWrapVol0_1/ITSULayer0_1/ITSUStave0_1 /cave_1/barrel_1/ITSV_2/ITSUWrapVol0_1/ITSULayer0_1/ITSUStave0_1/ITSUHalfStave0_0 #/cave_1/barrel_1/ITSV_2/ITSUWrapVol0_1/ITSULayer0_1/ITSUStave0_2 From 1565c137f4ff8996d352a086a3aaa132e226f1e2 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Mon, 26 Oct 2020 20:57:31 +0100 Subject: [PATCH 1107/1751] HistogramRegistry: improve output sorting (#4684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - improve code doing the sorting - place subdirectories always at the top Co-authored-by: Mario Krüger <mario.kruger@cern.ch> --- .../include/Framework/HistogramRegistry.h | 79 +++++++++++-------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 11023a9f45e98..2e6f147c28d9d 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -364,7 +364,7 @@ struct HistFiller { if (hist->GetNdimensions() != nDim) { LOGF(FATAL, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName()); } - double tempArray[sizeof...(Ts)] = {static_cast<double>(positionAndWeight)...}; + double tempArray[] = {static_cast<double>(positionAndWeight)...}; if constexpr (useWeight) hist->Fill(tempArray, tempArray[sizeof...(Ts) - 1]); else @@ -420,27 +420,29 @@ class HistogramRegistry // store a copy of an existing histogram (or group of histograms) under a different name void addClone(const std::string& source_, const std::string& target_) { - // search for histograms starting with source_ substring - for (auto& histVariant : mRegistryValue) { - std::visit([&](const auto& sharedPtr) { - if (!sharedPtr.get()) + auto doInsertClone = [&](const auto& sharedPtr) { + if (!sharedPtr.get()) { + return; + } + std::string sourceName{((TNamed*)sharedPtr.get())->GetName()}; + // search for histograms starting with source_ substring + if (sourceName.rfind(source_, 0) == 0) { + // when cloning groups of histograms source_ and target_ must end with "/" + if (sourceName.size() != source_.size() && (source_.back() != '/' || target_.back() != '/')) { return; - std::string sourceName{((TNamed*)sharedPtr.get())->GetName()}; - if (sourceName.rfind(source_, 0) == 0) { - // when cloning groups of histograms source_ and target_ must end with "/" - if (sourceName.size() != source_.size() && (source_.back() != '/' || target_.back() != '/')) { - return; - } - // when cloning a single histogram the specified target_ must not be a group name - if (sourceName.size() == source_.size() && target_.back() == '/') { - LOGF(FATAL, "Cannot turn histogram into folder!"); - } - std::string targetName{target_}; - targetName += sourceName.substr(sourceName.find(source_) + source_.size()); - insertClone(targetName.data(), sharedPtr); } - }, - histVariant); + // when cloning a single histogram the specified target_ must not be a group name + if (sourceName.size() == source_.size() && target_.back() == '/') { + LOGF(FATAL, "Cannot turn histogram into folder!"); + } + std::string targetName{target_}; + targetName += sourceName.substr(sourceName.find(source_) + source_.size()); + insertClone(targetName.data(), sharedPtr); + } + }; + + for (auto& histVariant : mRegistryValue) { + std::visit(doInsertClone, histVariant); } } @@ -489,6 +491,7 @@ class HistogramRegistry { return OutputRef{std::string{mName}, 0, o2::header::Stack{OutputObjHeader{mPolicy, mTaskHash}}}; } + void setHash(uint32_t hash) { mTaskHash = hash; @@ -517,22 +520,27 @@ class HistogramRegistry } // sort histograms in output file alphabetically - // TODO: in cases where histograms and directories reside in same level, we could put directories always on top if (mSortHistos) { - std::function<void(TList*)> sortSubLists; - sortSubLists = [&](TList* list) { + std::function<void(TList*)> sortList; + sortList = [&](TList* list) { + list->Sort(); TIter next(list); - TNamed* object = nullptr; - while ((object = (TNamed*)next())) { - if (object->InheritsFrom(TList::Class())) { - TList* subList = (TList*)object; - subList->Sort(); - sortSubLists(subList); + TNamed* subList = nullptr; + std::vector<TObject*> subLists; + while ((subList = (TNamed*)next())) { + if (subList->InheritsFrom(TList::Class())) { + subLists.push_back(subList); + sortList((TList*)subList); } } + // place lists always at the top + std::reverse(subLists.begin(), subLists.end()); + for (auto curList : subLists) { + list->Remove(curList); + list->AddFirst(curList); + } }; - list->Sort(); - sortSubLists(list); + sortList(list); } // create dedicated directory containing all of the registrys histograms @@ -559,7 +567,7 @@ class HistogramRegistry return; } } - LOGF(FATAL, "No histogram called %s found in HistogramRegistry!", name); + LOGF(FATAL, "No histogram called %s found in HistogramRegistry %s!", name, mName); } template <typename... Ts> @@ -574,6 +582,7 @@ class HistogramRegistry { fillTable<false, Cs...>(name, table, filter); } + template <typename... Cs, typename T> void fillWeight(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) { @@ -596,7 +605,7 @@ class HistogramRegistry return; } } - LOGF(FATAL, "No histogram called %s found in HistogramRegistry!", name); + LOGF(FATAL, "No histogram called %s found in HistogramRegistry %s!", name, mName); } /// lookup distance counter for benchmarking @@ -606,7 +615,7 @@ class HistogramRegistry // create histogram from specification and insert it into the registry void insert(const HistogramSpec& histSpec) { - uint32_t i = imask(histSpec.id); + const uint32_t i = imask(histSpec.id); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { TObject* rawPtr = nullptr; std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); @@ -625,7 +634,7 @@ class HistogramRegistry void insertClone(const char* name, const std::shared_ptr<T>& originalHist) { const uint32_t id = compile_time_hash(name); - uint32_t i = imask(id); + const uint32_t i = imask(id); for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { TObject* rawPtr = nullptr; std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); From 1d8eecb95b20a3ceb0f38ba9b57f98e328bfdff6 Mon Sep 17 00:00:00 2001 From: Alla Maevskaya <Alla.Maevskaya@cern.ch> Date: Mon, 26 Oct 2020 15:41:55 +0300 Subject: [PATCH 1108/1751] fix assert --- Detectors/FIT/FT0/simulation/src/Digitizer.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx index 56ac6da062909..d34d5f22aec8f 100644 --- a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx @@ -284,6 +284,7 @@ void Digitizer::flush(std::vector<o2::ft0::Digit>& digitsBC, { assert(firstBCinDeque <= mIntRecord); + while (firstBCinDeque < mIntRecord && !mCache.empty()) { storeBC(mCache.front(), digitsBC, digitsCh, labels); mCache.pop_front(); @@ -296,7 +297,8 @@ void Digitizer::flush_all(std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& labels) { - assert(firstBCinDeque < mIntRecord); + + assert(firstBCinDeque <= mIntRecord); ++mEventID; while (!mCache.empty()) { storeBC(mCache.front(), digitsBC, digitsCh, labels); From 4fb6ce0fdad31bf356305ea474a7cec237a21f9c Mon Sep 17 00:00:00 2001 From: Manso <manso@clraliceport15.in2p3.fr> Date: Tue, 13 Oct 2020 13:48:19 +0200 Subject: [PATCH 1109/1751] Disk Mothers Boards --- Detectors/ITSMFT/MFT/base/src/HalfCone.cxx | 214 ++++++++++++++++++++- 1 file changed, 212 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx index edcd91be1b5ac..98b7a8c9e46e8 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx @@ -29,6 +29,7 @@ #include "TGeoXtru.h" #include "MFTBase/HalfCone.h" +#include "MFTBase/Constants.h" using namespace o2::mft; @@ -1488,6 +1489,9 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t r_final_y; Double_t r_final_z; + Double_t tyMB0; + Double_t tzMB0; + if (half == 0) { t_final_x = 0; t_final_y = 0.0; @@ -1496,6 +1500,9 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) r_final_x = 0; r_final_y = 0; r_final_z = 0; + + tyMB0 = -16.72; + tzMB0 = -(45.3 + 46.7) / 2; } if (half == 1) { @@ -1506,6 +1513,9 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) r_final_x = 0; r_final_y = 0; r_final_z = 180; + + tyMB0 = 16.72; + tzMB0 = -(45.3 + 46.7) / 2; } auto* t_final = @@ -1752,7 +1762,6 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) combi_coat->RegisterYourself(); Half_3->AddNode(Half_3_Volume, 1, combi_coat); - // Half_3_Volume->SetLineColor(1); HalfConeVolume->AddNode(stair, 1, c_final); // HalfConeVolume->AddNode(base, 2, c_final); @@ -1762,7 +1771,208 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) HalfConeVolume->AddNode(frame_back, 6, c_final); // HalfConeVolume->AddNode(colonne_mb, 7, c_final); // - // HalfConeVolume->AddNode(Half_3, 6, c_final); + //========================== Mother Boards ========================================= + + // ============= MotherBoard 0 and 1 + Double_t mMB0cu[3]; + Double_t mMB0fr4; + Double_t mMB0pol; + Double_t mMB0epo; + // Sizes + mMB0cu[0] = {13.65}; + mMB0cu[1] = {0.00615}; // 122.5 microns * taux d'occupation 50% = 61.5 microns + mMB0cu[2] = {2.39}; + mMB0fr4 = 0.1; // 1 mm + mMB0pol = 0.0150; // 150 microns + mMB0epo = 0.0225; // 225 microns + // Materials + auto* mCu = gGeoManager->GetMedium("MFT_Cu$"); + auto* mFR4 = gGeoManager->GetMedium("MFT_FR4$"); + auto* mPol = gGeoManager->GetMedium("MFT_Polyimide$"); + auto* mEpo = gGeoManager->GetMedium("MFT_Epoxy$"); + auto* mInox = gGeoManager->GetMedium("MFT_Inox$"); + + auto* MotherBoard0 = new TGeoVolumeAssembly(Form("MotherBoard0_H%d", half)); + // 4 layers + TGeoVolume* vMB0cu = gGeoManager->MakeBox("vMB0cu", mCu, mMB0cu[0] / 2, mMB0cu[1] / 2, mMB0cu[2] / 2); + TGeoVolume* vMB0fr4 = gGeoManager->MakeBox("vMB0fr4", mFR4, mMB0cu[0] / 2, mMB0fr4 / 2, mMB0cu[2] / 2); + TGeoVolume* vMB0pol = gGeoManager->MakeBox("vMB0pol", mPol, mMB0cu[0] / 2, mMB0pol / 2, mMB0cu[2] / 2); + TGeoVolume* vMB0epo = gGeoManager->MakeBox("vMB0epo", mEpo, mMB0cu[0] / 2, mMB0epo / 2, mMB0cu[2] / 2); + // Screws = Head + Thread + TGeoVolume* vMB0screwH = gGeoManager->MakeTube("vMB0screwH", mInox, 0.0, 0.7 / 2, 0.35 / 2); // tete + TGeoVolume* vMB0screwT = gGeoManager->MakeTube("vMB0screwT", mInox, 0.0, 0.4 / 2, 1.2 / 2); // filetage + // Insert Sertitec + TGeoVolume* vMB0serti = gGeoManager->MakeTube("vMB0serti", mInox, 0.16 / 2, 0.556 / 2, 0.15 / 2); // tete + + vMB0cu->SetLineColor(kRed); + vMB0fr4->SetLineColor(kBlack); + vMB0pol->SetLineColor(kGreen); + vMB0epo->SetLineColor(kBlue); + vMB0screwH->SetLineColor(kOrange); + vMB0screwT->SetLineColor(kOrange); + vMB0serti->SetLineColor(kOrange); + // Positioning the layers + MotherBoard0->AddNode(vMB0cu, 1); + Int_t signe; + if (half == 0) + signe = -1; + if (half == 1) + signe = +1; + auto* t_MB0fr4 = new TGeoTranslation("translation_fr4", 0.0, signe * (mMB0fr4 + mMB0cu[1]) / 2, 0.0); + t_MB0fr4->RegisterYourself(); + MotherBoard0->AddNode(vMB0fr4, 1, t_MB0fr4); + auto* t_MB0pol = new TGeoTranslation("translation_pol", 0.0, signe * (mMB0fr4 + (mMB0cu[1] + mMB0pol) / 2), 0.0); + t_MB0pol->RegisterYourself(); + MotherBoard0->AddNode(vMB0pol, 1, t_MB0pol); + auto* t_MB0epo = new TGeoTranslation("translation_epo", 0.0, signe * (mMB0fr4 + mMB0pol + (mMB0cu[1] + mMB0epo) / 2), 0.0); + t_MB0epo->RegisterYourself(); + MotherBoard0->AddNode(vMB0epo, 1, t_MB0epo); + auto* r_MB0screw = new TGeoRotation("rotation_vMB0screw", 0, 90, 0); + auto* t_MB0screwH1 = new TGeoCombiTrans(mMB0cu[0] / 2 - 1.65, + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.35) / 2), 0.0, r_MB0screw); + t_MB0screwH1->RegisterYourself(); + auto* t_MB0screwT1 = new TGeoCombiTrans(mMB0cu[0] / 2 - 1.65, -signe * (mMB0cu[1] + 1.2) / 2, 0.0, r_MB0screw); + t_MB0screwT1->RegisterYourself(); + auto* t_MB0screwH2 = new TGeoCombiTrans(-(mMB0cu[0] / 2 - 1.65), + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.35) / 2), 0.0, r_MB0screw); + t_MB0screwH2->RegisterYourself(); + auto* t_MB0screwT2 = new TGeoCombiTrans(-(mMB0cu[0] / 2 - 1.65), -signe * (mMB0cu[1] + 1.2) / 2, 0.0, r_MB0screw); + t_MB0screwT2->RegisterYourself(); + auto* t_MB0serti1 = new TGeoCombiTrans(mMB0cu[0] / 2 - 2.65, + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.153) / 2), 0.0, r_MB0screw); + t_MB0serti1->RegisterYourself(); + auto* t_MB0serti2 = new TGeoCombiTrans(-(mMB0cu[0] / 2 - 2.65), + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.153) / 2), 0.0, r_MB0screw); + t_MB0serti2->RegisterYourself(); + MotherBoard0->AddNode(vMB0screwH, 1, t_MB0screwH1); + MotherBoard0->AddNode(vMB0screwT, 1, t_MB0screwT1); + MotherBoard0->AddNode(vMB0screwH, 1, t_MB0screwH2); + MotherBoard0->AddNode(vMB0screwT, 1, t_MB0screwT2); + MotherBoard0->AddNode(vMB0serti, 1, t_MB0serti1); + MotherBoard0->AddNode(vMB0serti, 1, t_MB0serti2); + + // Positioning the board + auto* t_MB0 = new TGeoTranslation("translation_MB0", 0.0, tyMB0, tzMB0); + t_MB0->RegisterYourself(); + auto* t_MB1 = new TGeoTranslation("translation_MB1", 0.0, tyMB0, tzMB0 - 3.3); // 3.3 cm is the interdistance between disk 0 and 1 + t_MB1->RegisterYourself(); + auto* r_MB0 = new TGeoRotation("rotation_MB0", 0.0, 0.0, 0.0); + r_MB0->RegisterYourself(); + auto* p_MB0 = new TGeoCombiTrans(*t_MB0, *r_MB0); + p_MB0->RegisterYourself(); + auto* p_MB1 = new TGeoCombiTrans(*t_MB1, *r_MB0); + p_MB1->RegisterYourself(); + // Final addition of the board + HalfConeVolume->AddNode(MotherBoard0, 1, p_MB0); + HalfConeVolume->AddNode(MotherBoard0, 1, p_MB1); + + auto* MotherBoard0_1 = new TGeoVolumeAssembly(Form("MotherBoard0_1_H%d", half)); + // 4 layers + TGeoVolume* vMB0cu_1 = gGeoManager->MakeBox("vMB0cu_1", mCu, 18.0 / 2, mMB0cu[1] / 2, 1.2 / 2); + TGeoVolume* vMB0fr4_1 = gGeoManager->MakeBox("vMB0fr4_1", mFR4, 18.0 / 2, mMB0fr4 / 2, 1.2 / 2); + TGeoVolume* vMB0pol_1 = gGeoManager->MakeBox("vMB0pol_1", mPol, 18.0 / 2, mMB0pol / 2, 1.2 / 2); + TGeoVolume* vMB0epo_1 = gGeoManager->MakeBox("vMB0epo_1", mEpo, 18.0 / 2, mMB0epo / 2, 1.2 / 2); + vMB0cu_1->SetLineColor(kRed); + vMB0fr4_1->SetLineColor(kBlack); + vMB0pol_1->SetLineColor(kGreen); + vMB0epo_1->SetLineColor(kBlue); + + MotherBoard0_1->AddNode(vMB0cu_1, 1); + MotherBoard0_1->AddNode(vMB0fr4_1, 1, t_MB0fr4); + MotherBoard0_1->AddNode(vMB0pol_1, 1, t_MB0pol); + MotherBoard0_1->AddNode(vMB0epo_1, 1, t_MB0epo); + + // ================ MotherBoard 2 + Double_t mMB2cu[4]; + Double_t mMB2fr4; + Double_t mMB2pol; + Double_t mMB2epo; + // Sizes + mMB2cu[0] = {24.0}; + mMB2cu[1] = {21.0}; + mMB2cu[2] = {0.0079}; // 315 microns * taux d'occupation 25% = 79 microns + mMB2cu[3] = {8.5}; + mMB2fr4 = 0.2; // 2 mm + mMB2pol = 0.0175; // 175 microns + mMB2epo = 0.0075; // 75 microns + auto* MotherBoard2 = new TGeoVolumeAssembly(Form("MotherBoard2_H%d", half)); + // 4 layers + TGeoVolume* vMB2cu = gGeoManager->MakeTrd1("vMB2cu", mCu, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2cu[2] / 2, mMB2cu[3] / 2); + TGeoVolume* vMB2fr4 = gGeoManager->MakeTrd1("vMB2fr4", mFR4, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2fr4 / 2, mMB2cu[3] / 2); + TGeoVolume* vMB2pol = gGeoManager->MakeTrd1("vMB2pol", mPol, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2pol / 2, mMB2cu[3] / 2); + TGeoVolume* vMB2epo = gGeoManager->MakeTrd1("vMB2epo", mEpo, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2epo / 2, mMB2cu[3] / 2); + + vMB2cu->SetLineColor(kRed); + vMB2fr4->SetLineColor(kBlack); + vMB2pol->SetLineColor(kGreen); + vMB2epo->SetLineColor(kBlue); + + auto* t_MB2fr4 = new TGeoTranslation("translation_fr4", 0.0, signe * (mMB2fr4 + mMB2cu[2]) / 2, 0.0); + t_MB2fr4->RegisterYourself(); + auto* t_MB2pol = new TGeoTranslation("translation_pol", 0.0, signe * (mMB2fr4 + (mMB2cu[2] + mMB2pol) / 2), 0.0); + t_MB2pol->RegisterYourself(); + auto* t_MB2epo = new TGeoTranslation("translation_epo", 0.0, signe * (mMB2fr4 + mMB2pol + (mMB2cu[2] + mMB2epo) / 2), 0.0); + t_MB2epo->RegisterYourself(); + + MotherBoard2->AddNode(vMB2cu, 1); + MotherBoard2->AddNode(vMB2fr4, 1, t_MB2fr4); + MotherBoard2->AddNode(vMB2pol, 1, t_MB2pol); + MotherBoard2->AddNode(vMB2epo, 1, t_MB2epo); + for (Float_t i = -1; i < 3; i++) { + auto* t_MB2serti1 = new TGeoTranslation("translationMB2serti1", 8.5, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + t_MB2serti1->RegisterYourself(); + auto* t_MB2serti2 = new TGeoTranslation("translationMB2serti2", -8.5, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + t_MB2serti2->RegisterYourself(); + auto* p_MB2serti1 = new TGeoCombiTrans(*t_MB2serti1, *r_MB0screw); + p_MB2serti1->RegisterYourself(); + auto* p_MB2serti2 = new TGeoCombiTrans(*t_MB2serti2, *r_MB0screw); + p_MB2serti2->RegisterYourself(); + MotherBoard2->AddNode(vMB0serti, 1, p_MB2serti1); + MotherBoard2->AddNode(vMB0serti, 1, p_MB2serti2); + } + for (Float_t i = -2; i < 1; i++) { + auto* t_MB2serti3 = new TGeoTranslation("translationMB2serti3", 0.7, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + t_MB2serti3->RegisterYourself(); + auto* t_MB2serti4 = new TGeoTranslation("translationMB2serti4", -0.7, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + t_MB2serti4->RegisterYourself(); + auto* p_MB2serti3 = new TGeoCombiTrans(*t_MB2serti3, *r_MB0screw); + p_MB2serti3->RegisterYourself(); + auto* p_MB2serti4 = new TGeoCombiTrans(*t_MB2serti4, *r_MB0screw); + p_MB2serti4->RegisterYourself(); + MotherBoard2->AddNode(vMB0serti, 1, p_MB2serti3); + MotherBoard2->AddNode(vMB0serti, 1, p_MB2serti4); + } + + for (Float_t i = -2; i < 2; i++) { + auto* t_MB2serti5 = new TGeoTranslation("translationMB2serti5", 7.0 * i + 3.5, -signe * (mMB2cu[2] + 0.153) / 2, -2.5); + t_MB2serti5->RegisterYourself(); + auto* p_MB2serti5 = new TGeoCombiTrans(*t_MB2serti5, *r_MB0screw); + p_MB2serti5->RegisterYourself(); + auto* t_MB2serti6 = new TGeoTranslation("translationMB2serti6", 7.0 * i + 3.5, -signe * (mMB2cu[2] + 0.153) / 2, -3.5); + t_MB2serti6->RegisterYourself(); + auto* p_MB2serti6 = new TGeoCombiTrans(*t_MB2serti6, *r_MB0screw); + p_MB2serti6->RegisterYourself(); + MotherBoard2->AddNode(vMB0serti, 1, p_MB2serti5); + MotherBoard2->AddNode(vMB0serti, 1, p_MB2serti6); + } + // Connector board of MB0 on MB2 + auto* t_MotherBoard0_1 = new TGeoTranslation("translation_MB0_1", 0.0, -signe * (-0.5), 3.5); + t_MotherBoard0_1->RegisterYourself(); + auto* t_MotherBoard0_2 = new TGeoTranslation("translation_MB0_2", 0.0, -signe * (-0.5), 1.5); + t_MotherBoard0_2->RegisterYourself(); + MotherBoard2->AddNode(MotherBoard0_1, 1, t_MotherBoard0_1); + MotherBoard2->AddNode(MotherBoard0_1, 1, t_MotherBoard0_2); + // Positioning the board + auto* t_MotherBoard2 = new TGeoTranslation("translation_MB2", 0.0, + -signe * (-20.52 + mMB2fr4 + mMB2pol + mMB2epo + 2.2 * TMath::Sin(19.0)), + -62.8 + 2.2 * TMath::Cos(19.0)); + t_MotherBoard2->RegisterYourself(); + auto* r_MotherBoard2 = new TGeoRotation("rotation_MB2", 0.0, -signe * (-19.0), 0.0); + r_MotherBoard2->RegisterYourself(); + auto* p_MB2 = new TGeoCombiTrans(*t_MotherBoard2, *r_MotherBoard2); + p_MB2->RegisterYourself(); + HalfConeVolume->AddNode(MotherBoard2, 1, p_MB2); + //=================================================================== return HalfConeVolume; } From 2940c5b1e13e30a8229cb6c082abff4e32117cf0 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 27 Oct 2020 09:10:55 +0100 Subject: [PATCH 1110/1751] rewrite of THnStep including fill method with variable arguments (#4641) --- .../include/Analysis/CorrelationContainer.h | 22 +- Analysis/Core/include/Analysis/StepTHn.h | 160 ++++++-- Analysis/Core/src/AnalysisCoreLinkDef.h | 12 +- Analysis/Core/src/CorrelationContainer.cxx | 12 +- Analysis/Core/src/StepTHn.cxx | 379 +++++------------- Analysis/Tasks/PWGCF/correlations.cxx | 134 +++++-- Analysis/Tasks/PWGCF/correlationsFiltered.cxx | 31 +- Analysis/Tasks/PWGCF/correlationsMixed.cxx | 109 ++--- 8 files changed, 373 insertions(+), 486 deletions(-) diff --git a/Analysis/Core/include/Analysis/CorrelationContainer.h b/Analysis/Core/include/Analysis/CorrelationContainer.h index 4e1ba81cad44e..5591193f104df 100644 --- a/Analysis/Core/include/Analysis/CorrelationContainer.h +++ b/Analysis/Core/include/Analysis/CorrelationContainer.h @@ -27,7 +27,7 @@ class TH2D; class TCollection; class THnSparse; class THnBase; -class StepTHnBase; +class StepTHn; class CorrelationContainer : public TNamed { @@ -51,14 +51,14 @@ class CorrelationContainer : public TNamed const char* getStepTitle(CFStep step); - StepTHnBase* getPairHist() { return mPairHist; } - StepTHnBase* getTriggerHist() { return mTriggerHist; } - StepTHnBase* getTrackHistEfficiency() { return mTrackHistEfficiency; } + StepTHn* getPairHist() { return mPairHist; } + StepTHn* getTriggerHist() { return mTriggerHist; } + StepTHn* getTrackHistEfficiency() { return mTrackHistEfficiency; } TH2F* getEventCount() { return mEventCount; } - void setPairHist(StepTHnBase* hist) { mPairHist = hist; } - void setTriggerHist(StepTHnBase* hist) { mTriggerHist = hist; } - void setTrackHistEfficiency(StepTHnBase* hist) { mTrackHistEfficiency = hist; } + void setPairHist(StepTHn* hist) { mPairHist = hist; } + void setTriggerHist(StepTHn* hist) { mTriggerHist = hist; } + void setTrackHistEfficiency(StepTHn* hist) { mTrackHistEfficiency = hist; } void deepCopy(CorrelationContainer* from); @@ -149,9 +149,9 @@ class CorrelationContainer : public TNamed void weightHistogram(TH3* hist1, TH1* hist2); void multiplyHistograms(THnBase* grid, THnBase* target, TH1* histogram, Int_t var1, Int_t var2); - StepTHnBase* mPairHist; // container for pair level distributions at all analysis steps - StepTHnBase* mTriggerHist; // container for "trigger" particle (single-particle) level distribution at all analysis steps - StepTHnBase* mTrackHistEfficiency; // container for tracking efficiency and contamination (all particles filled including leading one): axes: eta, pT, particle species + StepTHn* mPairHist; // container for pair level distributions at all analysis steps + StepTHn* mTriggerHist; // container for "trigger" particle (single-particle) level distribution at all analysis steps + StepTHn* mTrackHistEfficiency; // container for tracking efficiency and contamination (all particles filled including leading one): axes: eta, pT, particle species TH2F* mEventCount; // event count as function of step, (for pp: event type (plus additional step -1 for all events without vertex range even in MC)) (for PbPb: centrality) @@ -171,7 +171,7 @@ class CorrelationContainer : public TNamed Bool_t mWeightPerEvent; // weight with the number of trigger particles per event Bool_t mSkipScaleMixedEvent; // scale the mixed event with (0, 0) plus finite bin correction (default: kTRUE) - StepTHnBase* mCache; //! cache variable for getTrackEfficiency + StepTHn* mCache; //! cache variable for getTrackEfficiency Bool_t mGetMultCacheOn; //! cache for getHistsZVtxMult function active THnBase* mGetMultCache; //! cache for getHistsZVtxMult function diff --git a/Analysis/Core/include/Analysis/StepTHn.h b/Analysis/Core/include/Analysis/StepTHn.h index 9e3fa76bfcc5a..24f0201d3de1c 100644 --- a/Analysis/Core/include/Analysis/StepTHn.h +++ b/Analysis/Core/include/Analysis/StepTHn.h @@ -16,75 +16,58 @@ #include "TNamed.h" #include "THnSparse.h" +#include "TAxis.h" +#include "TArray.h" + +#include "Framework/Logger.h" class TArray; class TArrayF; class TArrayD; class TCollection; -class StepTHnBase : public TNamed -{ - public: - StepTHnBase() : TNamed() {} - StepTHnBase(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binLimits[], const char** axisTitles) : TNamed(name, title) {} - - virtual void Fill(const Double_t* var, Int_t istep, Double_t weight = 1.) = 0; - - virtual THnBase* getTHn(Int_t step, Bool_t sparse = kFALSE) = 0; - virtual Int_t getNSteps() = 0; - virtual Int_t getNVar() = 0; - - virtual TArray* getValues(Int_t step) = 0; - virtual TArray* getSumw2(Int_t step) = 0; - - virtual void deleteContainers() = 0; - - virtual Long64_t Merge(TCollection* list) = 0; - - ClassDef(StepTHnBase, 1) // StepTHn base class -}; - -template <class TemplateArray, typename TemplateType> -class StepTHn : public StepTHnBase +class StepTHn : public TNamed { public: StepTHn(); StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binLimits[], const char** axisTitles); ~StepTHn() override; - void Fill(const Double_t* var, Int_t istep, Double_t weight = 1.) override; + template <typename... Ts> + void Fill(Int_t istep, const Ts&... valuesAndWeight); - THnBase* getTHn(Int_t step, Bool_t sparse = kFALSE) override + THnBase* getTHn(Int_t step, Bool_t sparse = kFALSE) { if (!mTarget || !mTarget[step]) { createTarget(step, sparse); } return mTarget[step]; } - Int_t getNSteps() override { return mNSteps; } - Int_t getNVar() override { return mNVars; } + Int_t getNSteps() { return mNSteps; } + Int_t getNVar() { return mNVars; } - TArray* getValues(Int_t step) override { return mValues[step]; } - TArray* getSumw2(Int_t step) override { return mSumw2[step]; } + TArray* getValues(Int_t step) { return mValues[step]; } + TArray* getSumw2(Int_t step) { return mSumw2[step]; } StepTHn(const StepTHn& c); StepTHn& operator=(const StepTHn& corr); void Copy(TObject& c) const override; - Long64_t Merge(TCollection* list) override; + virtual Long64_t Merge(TCollection* list) = 0; protected: void init(); + virtual TArray* createArray(const TArray* src = nullptr) const = 0; void createTarget(Int_t step, Bool_t sparse); - void deleteContainers() override; + void deleteContainers(); Long64_t getGlobalBinIndex(const Int_t* binIdx); - Long64_t mNBins; // number of total bins - Int_t mNVars; // number of variables - Int_t mNSteps; // number of selection steps - TemplateArray** mValues; //[mNSteps] data container - TemplateArray** mSumw2; //[mNSteps] data container + Long64_t mNBins; // number of total bins + Int_t mNVars; // number of variables + Int_t mNSteps; // number of selection steps + TArray** mValues; //[mNSteps] data container + TArray** mSumw2; //[mNSteps] data container THnBase** mTarget; //! target histogram @@ -98,7 +81,106 @@ class StepTHn : public StepTHnBase ClassDef(StepTHn, 1) // THn like container }; -typedef StepTHn<TArrayF, Float_t> StepTHnF; -typedef StepTHn<TArrayD, Double_t> StepTHnD; +template <class TemplateArray> +class StepTHnT : public StepTHn +{ + public: + StepTHnT() : StepTHn() {} + StepTHnT(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binLimits[], const char** axisTitles); + ~StepTHnT() override = default; + + protected: + TArray* createArray(const TArray* src = nullptr) const override + { + if (src == nullptr) { + return new TemplateArray(mNBins); + } else { + return new TemplateArray(*((TemplateArray*)src)); + } + } + + Long64_t Merge(TCollection* list) override; + + ClassDef(StepTHnT, 1) // THn like container +}; + +typedef StepTHnT<TArrayF> StepTHnF; +typedef StepTHnT<TArrayD> StepTHnD; + +template <typename... Ts> +void StepTHn::Fill(Int_t istep, const Ts&... valuesAndWeight) +{ + constexpr int nParams = sizeof...(Ts); + // TODO Find a way to avoid the array + double tempArray[nParams] = {static_cast<double>(valuesAndWeight)...}; + + double weight = 1.0; + if (nParams == mNVars + 1) { + weight = tempArray[mNVars]; + } else if (nParams != mNVars) { + LOGF(fatal, "Fill called with invalid number of parameters (%d vs %d)", mNVars, nParams); + } + + // fill axis cache + if (!mAxisCache) { + mAxisCache = new TAxis*[mNVars]; + mNbinsCache = new Int_t[mNVars]; + for (Int_t i = 0; i < mNVars; i++) { + mAxisCache[i] = mPrototype->GetAxis(i); + mNbinsCache[i] = mAxisCache[i]->GetNbins(); + } + + mLastVars = new Double_t[mNVars]; + mLastBins = new Int_t[mNVars]; + + // initial values to prevent checking for 0 below + for (Int_t i = 0; i < mNVars; i++) { + mLastVars[i] = tempArray[i]; + mLastBins[i] = mAxisCache[i]->FindBin(mLastVars[i]); + } + } + + // calculate global bin index + Long64_t bin = 0; + for (Int_t i = 0; i < mNVars; i++) { + bin *= mNbinsCache[i]; + + Int_t tmpBin = 0; + if (mLastVars[i] == tempArray[i]) + tmpBin = mLastBins[i]; + else { + tmpBin = mAxisCache[i]->FindBin(tempArray[i]); + mLastBins[i] = tmpBin; + mLastVars[i] = tempArray[i]; + } + //Printf("%d", tmpBin); + + // under/overflow not supported + if (tmpBin < 1 || tmpBin > mNbinsCache[i]) + return; + + // bins start from 0 here + bin += tmpBin - 1; + // Printf("%lld", bin); + } + + if (!mValues[istep]) { + mValues[istep] = createArray(); + LOGF(info, "Created values container for step %d", istep); + } + + if (weight != 1) { + // initialize with already filled entries (which have been filled with weight == 1), in this case mSumw2 := mValues + if (!mSumw2[istep]) { + mSumw2[istep] = createArray(); + LOGF(info, "Created sumw2 container for step %d", istep); + } + } + + // TODO probably slow; add StepTHnT::add ? + mValues[istep]->SetAt(mValues[istep]->GetAt(bin) + weight, bin); + if (mSumw2[istep]) + mSumw2[istep]->SetAt(mSumw2[istep]->GetAt(bin) + weight, bin); +} #endif diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index bc79d27b607be..e54a820e13beb 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -12,15 +12,15 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class StepTHnBase+; -#pragma link C++ class StepTHn<TArrayF, Float_t>+; -#pragma link C++ class StepTHn<TArrayD, Double_t>+; +#pragma link C++ class StepTHn + ; +#pragma link C++ class StepTHnT < TArrayF> + ; +#pragma link C++ class StepTHnT < TArrayD> + ; #pragma link C++ typedef StepTHnF; #pragma link C++ typedef StepTHnD; -#pragma link C++ class CorrelationContainer+; -#pragma link C++ class TrackSelection+; -#pragma link C++ class TriggerAliases+; +#pragma link C++ class CorrelationContainer + ; +#pragma link C++ class TrackSelection + ; +#pragma link C++ class TriggerAliases + ; #pragma link C++ class VarManager + ; #pragma link C++ class HistogramManager + ; diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index f23f01ecf7ca5..183651d700b76 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -459,15 +459,15 @@ void CorrelationContainer::Copy(TObject& c) const CorrelationContainer& target = (CorrelationContainer&)c; if (mPairHist) { - target.mPairHist = dynamic_cast<StepTHnBase*>(mPairHist->Clone()); + target.mPairHist = dynamic_cast<StepTHn*>(mPairHist->Clone()); } if (mTriggerHist) { - target.mTriggerHist = dynamic_cast<StepTHnBase*>(mTriggerHist->Clone()); + target.mTriggerHist = dynamic_cast<StepTHn*>(mTriggerHist->Clone()); } if (mTrackHistEfficiency) { - target.mTrackHistEfficiency = dynamic_cast<StepTHnBase*>(mTrackHistEfficiency->Clone()); + target.mTrackHistEfficiency = dynamic_cast<StepTHn*>(mTrackHistEfficiency->Clone()); } target.mEtaMin = mEtaMin; @@ -1133,7 +1133,7 @@ THnBase* CorrelationContainer::getTrackEfficiencyND(CFStep step1, CFStep step2) // creates a track-level efficiency by dividing step2 by step1 // in all dimensions but the particle species one - StepTHnBase* sourceContainer = mTrackHistEfficiency; + StepTHn* sourceContainer = mTrackHistEfficiency; // step offset because we start with kCFStepAnaTopology step1 = (CFStep)((Int_t)step1 - (Int_t)kCFStepAnaTopology); step2 = (CFStep)((Int_t)step2 - (Int_t)kCFStepAnaTopology); @@ -1176,7 +1176,7 @@ TH1* CorrelationContainer::getTrackEfficiency(CFStep step1, CFStep step2, Int_t // cache it for efficiency (usually more than one efficiency is requested) - StepTHnBase* sourceContainer = nullptr; + StepTHn* sourceContainer = nullptr; if (source == 0) { return nullptr; @@ -1485,7 +1485,7 @@ TH1* CorrelationContainer::getBias(CFStep step1, CFStep step2, const char* axis, // 1 = only track bias is returned // 2 = only event bias is returned - StepTHnBase* tmp = mPairHist; + StepTHn* tmp = mPairHist; resetBinLimits(tmp->getTHn(step1)); resetBinLimits(mTriggerHist->getTHn(step1)); diff --git a/Analysis/Core/src/StepTHn.cxx b/Analysis/Core/src/StepTHn.cxx index f4ef928f0ca83..30d1b16d93305 100644 --- a/Analysis/Core/src/StepTHn.cxx +++ b/Analysis/Core/src/StepTHn.cxx @@ -25,41 +25,36 @@ #include "THn.h" #include "TMath.h" -// for LOGF -#include "Framework/AnalysisTask.h" - -templateClassImp(StepTHn) - - template <class TemplateArray, typename TemplateType> - StepTHn<TemplateArray, TemplateType>::StepTHn() : StepTHnBase(), - mNBins(0), - mNVars(0), - mNSteps(0), - mValues(nullptr), - mSumw2(nullptr), - mTarget(nullptr), - mAxisCache(nullptr), - mNbinsCache(nullptr), - mLastVars(nullptr), - mLastBins(nullptr), - mPrototype(nullptr) +ClassImp(StepTHn) + templateClassImp(StepTHnT) + + StepTHn::StepTHn() : mNBins(0), + mNVars(0), + mNSteps(0), + mValues(nullptr), + mSumw2(nullptr), + mTarget(nullptr), + mAxisCache(nullptr), + mNbinsCache(nullptr), + mLastVars(nullptr), + mLastBins(nullptr), + mPrototype(nullptr) { // Default constructor (for streaming) } -template <class TemplateArray, typename TemplateType> -StepTHn<TemplateArray, TemplateType>::StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binEdges[], const char** axisTitles) : StepTHnBase(name, title, nSteps, nAxis, nBins, binEdges, axisTitles), - mNBins(0), - mNVars(nAxis), - mNSteps(nSteps), - mValues(nullptr), - mSumw2(nullptr), - mTarget(nullptr), - mAxisCache(nullptr), - mNbinsCache(nullptr), - mLastVars(nullptr), - mLastBins(nullptr), - mPrototype(nullptr) +StepTHn::StepTHn(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, Int_t* nBins, std::vector<Double_t> binEdges[], const char** axisTitles) : TNamed(name, title), + mNBins(0), + mNVars(nAxis), + mNSteps(nSteps), + mValues(nullptr), + mSumw2(nullptr), + mTarget(nullptr), + mAxisCache(nullptr), + mNbinsCache(nullptr), + mLastVars(nullptr), + mLastBins(nullptr), + mPrototype(nullptr) { // Constructor // @@ -68,12 +63,17 @@ StepTHn<TemplateArray, TemplateType>::StepTHn(const Char_t* name, const Char_t* // For each step a <nAxis> dimensional histogram is created. // The axis have <nBins[i]> bins. The bin edges are given in <binEdges[i]>. If there are only two bin edges, equidistant binning is set. + init(); +} + +template <class TemplateArray> +StepTHnT<TemplateArray>::StepTHnT(const Char_t* name, const Char_t* title, const Int_t nSteps, const Int_t nAxis, + Int_t* nBins, std::vector<Double_t> binEdges[], const char** axisTitles) : StepTHn(name, title, nSteps, nAxis, nBins, binEdges, axisTitles) +{ mNBins = 1; - for (Int_t i = 0; i < mNVars; i++) { + for (Int_t i = 0; i < mNVars; i++) mNBins *= nBins[i]; - } - - if constexpr (std::is_same_v<TemplateType, Double_t>) { + if constexpr (std::is_same_v<TemplateArray, TArrayD>) { mPrototype = new THnSparseD(Form("%s_sparse", name), title, nAxis, nBins); } else { mPrototype = new THnSparseF(Form("%s_sparse", name), title, nAxis, nBins); @@ -89,16 +89,14 @@ StepTHn<TemplateArray, TemplateType>::StepTHn(const Char_t* name, const Char_t* LOGF(debug, "Histogram %s Axis %d created with %d bins and %d edges", name, i, nBins[i], binEdges[i].size()); mPrototype->GetAxis(i)->SetTitle(axisTitles[i]); } - init(); } -template <class TemplateArray, typename TemplateType> -void StepTHn<TemplateArray, TemplateType>::StepTHn::init() +void StepTHn::init() { // initialize - mValues = new TemplateArray*[mNSteps]; - mSumw2 = new TemplateArray*[mNSteps]; + mValues = new TArray*[mNSteps]; + mSumw2 = new TArray*[mNSteps]; for (Int_t i = 0; i < mNSteps; i++) { mValues[i] = nullptr; @@ -106,19 +104,17 @@ void StepTHn<TemplateArray, TemplateType>::StepTHn::init() } } -template <class TemplateArray, typename TemplateType> -StepTHn<TemplateArray, TemplateType>::StepTHn(const StepTHn<TemplateArray, TemplateType>& c) : StepTHnBase(c), - mNBins(c.mNBins), - mNVars(c.mNVars), - mNSteps(c.mNSteps), - mValues(new TemplateArray*[c.mNSteps]), - mSumw2(new TemplateArray*[c.mNSteps]), - mTarget(nullptr), - mAxisCache(nullptr), - mNbinsCache(nullptr), - mLastVars(nullptr), - mLastBins(nullptr), - mPrototype(nullptr) +StepTHn::StepTHn(const StepTHn& c) : mNBins(c.mNBins), + mNVars(c.mNVars), + mNSteps(c.mNSteps), + mValues(new TArray*[c.mNSteps]), + mSumw2(new TArray*[c.mNSteps]), + mTarget(nullptr), + mAxisCache(nullptr), + mNbinsCache(nullptr), + mLastVars(nullptr), + mLastBins(nullptr), + mPrototype(nullptr) { // // StepTHn copy constructor @@ -127,8 +123,7 @@ StepTHn<TemplateArray, TemplateType>::StepTHn(const StepTHn<TemplateArray, Templ ((StepTHn&)c).Copy(*this); } -template <class TemplateArray, typename TemplateType> -StepTHn<TemplateArray, TemplateType>::~StepTHn() +StepTHn::~StepTHn() { // Destructor @@ -144,8 +139,7 @@ StepTHn<TemplateArray, TemplateType>::~StepTHn() delete mPrototype; } -template <class TemplateArray, typename TemplateType> -void StepTHn<TemplateArray, TemplateType>::deleteContainers() +void StepTHn::deleteContainers() { // delete data containers @@ -167,22 +161,17 @@ void StepTHn<TemplateArray, TemplateType>::deleteContainers() } } -//____________________________________________________________________ -template <class TemplateArray, typename TemplateType> -StepTHn<TemplateArray, TemplateType>& StepTHn<TemplateArray, TemplateType>::operator=(const StepTHn<TemplateArray, TemplateType>& c) +StepTHn& StepTHn::operator=(const StepTHn& c) { // assigment operator - if (this != &c) { + if (this != &c) ((StepTHn&)c).Copy(*this); - } return *this; } -//____________________________________________________________________ -template <class TemplateArray, typename TemplateType> -void StepTHn<TemplateArray, TemplateType>::Copy(TObject& c) const +void StepTHn::Copy(TObject& c) const { // copy function @@ -197,39 +186,33 @@ void StepTHn<TemplateArray, TemplateType>::Copy(TObject& c) const target.init(); for (Int_t i = 0; i < mNSteps; i++) { - if (mValues[i]) { - target.mValues[i] = new TemplateArray(*(mValues[i])); - } else { + if (mValues[i]) + target.mValues[i] = createArray(mValues[i]); + else target.mValues[i] = nullptr; - } - if (mSumw2[i]) { - target.mSumw2[i] = new TemplateArray(*(mSumw2[i])); - } else { + if (mSumw2[i]) + target.mSumw2[i] = createArray(mSumw2[i]); + else target.mSumw2[i] = nullptr; - } } - if (mPrototype) { + if (mPrototype) target.mPrototype = dynamic_cast<THnSparseF*>(mPrototype->Clone()); - } } -//____________________________________________________________________ -template <class TemplateArray, typename TemplateType> -Long64_t StepTHn<TemplateArray, TemplateType>::Merge(TCollection* list) +template <class TemplateArray> +Long64_t StepTHnT<TemplateArray>::Merge(TCollection* list) { // Merge a list of StepTHn objects with this (needed for // PROOF). // Returns the number of merged objects (including this). - if (!list) { + if (!list) return 0; - } - if (list->IsEmpty()) { + if (list->IsEmpty()) return 1; - } TIterator* iter = list->MakeIterator(); TObject* obj; @@ -237,30 +220,29 @@ Long64_t StepTHn<TemplateArray, TemplateType>::Merge(TCollection* list) Int_t count = 0; while ((obj = iter->Next())) { - StepTHn* entry = dynamic_cast<StepTHn*>(obj); - if (entry == nullptr) { + StepTHnT<TemplateArray>* entry = dynamic_cast<StepTHnT<TemplateArray>*>(obj); + if (entry == nullptr) continue; - } for (Int_t i = 0; i < mNSteps; i++) { if (entry->mValues[i]) { - if (!mValues[i]) { - mValues[i] = new TemplateArray(mNBins); - } + if (!mValues[i]) + mValues[i] = createArray(); - for (Long64_t l = 0; l < mNBins; l++) { - mValues[i]->GetArray()[l] += entry->mValues[i]->GetArray()[l]; - } + auto source = dynamic_cast<TemplateArray*>(entry->mValues[i])->GetArray(); + auto target = dynamic_cast<TemplateArray*>(mValues[i])->GetArray(); + for (Long64_t l = 0; l < mNBins; l++) + target[l] += source[l]; } if (entry->mSumw2[i]) { - if (!mSumw2[i]) { - mSumw2[i] = new TemplateArray(mNBins); - } + if (!mSumw2[i]) + mSumw2[i] = createArray(); - for (Long64_t l = 0; l < mNBins; l++) { - mSumw2[i]->GetArray()[l] += entry->mSumw2[i]->GetArray()[l]; - } + auto source = dynamic_cast<TemplateArray*>(entry->mSumw2[i])->GetArray(); + auto target = dynamic_cast<TemplateArray*>(mSumw2[i])->GetArray(); + for (Long64_t l = 0; l < mNBins; l++) + target[l] += source[l]; } } @@ -270,81 +252,7 @@ Long64_t StepTHn<TemplateArray, TemplateType>::Merge(TCollection* list) return count + 1; } -template <class TemplateArray, typename TemplateType> -void StepTHn<TemplateArray, TemplateType>::Fill(const Double_t* var, Int_t istep, Double_t weight) -{ - // fills an entry - - // fill axis cache - if (!mAxisCache) { - mAxisCache = new TAxis*[mNVars]; - mNbinsCache = new Int_t[mNVars]; - for (Int_t i = 0; i < mNVars; i++) { - mAxisCache[i] = mPrototype->GetAxis(i); - mNbinsCache[i] = mAxisCache[i]->GetNbins(); - } - - mLastVars = new Double_t[mNVars]; - mLastBins = new Int_t[mNVars]; - - // initial values to prevent checking for 0 below - for (Int_t i = 0; i < mNVars; i++) { - mLastBins[i] = mAxisCache[i]->FindBin(var[i]); - mLastVars[i] = var[i]; - } - } - - // calculate global bin index - Long64_t bin = 0; - for (Int_t i = 0; i < mNVars; i++) { - bin *= mNbinsCache[i]; - - Int_t tmpBin = 0; - if (mLastVars[i] == var[i]) { - tmpBin = mLastBins[i]; - } else { - tmpBin = mAxisCache[i]->FindBin(var[i]); - mLastBins[i] = tmpBin; - mLastVars[i] = var[i]; - } - //Printf("%d", tmpBin); - - // under/overflow not supported - if (tmpBin < 1 || tmpBin > mNbinsCache[i]) { - return; - } - - // bins start from 0 here - bin += tmpBin - 1; - // Printf("%lld", bin); - } - - if (!mValues[istep]) { - mValues[istep] = new TemplateArray(mNBins); - LOGF(info, "Created values container for step %d", istep); - } - - if (weight != 1) { - // initialize with already filled entries (which have been filled with weight == 1), in this case mSumw2 := mValues - if (!mSumw2[istep]) { - mSumw2[istep] = new TemplateArray(*mValues[istep]); - LOGF(info, "Created sumw2 container for step %d", istep); - } - } - - mValues[istep]->GetArray()[bin] += weight; - if (mSumw2[istep]) { - mSumw2[istep]->GetArray()[bin] += weight * weight; - } - - // Printf("%f", mValues[istep][bin]); - - // debug - // AliCFContainer::Fill(var, istep, weight); -} - -template <class TemplateArray, typename TemplateType> -Long64_t StepTHn<TemplateArray, TemplateType>::getGlobalBinIndex(const Int_t* binIdx) +Long64_t StepTHn::getGlobalBinIndex(const Int_t* binIdx) { // calculates global bin index // binIdx contains TAxis bin indexes @@ -359,8 +267,7 @@ Long64_t StepTHn<TemplateArray, TemplateType>::getGlobalBinIndex(const Int_t* bi return bin; } -template <class TemplateArray, typename TemplateType> -void StepTHn<TemplateArray, TemplateType>::createTarget(Int_t step, Bool_t sparse) +void StepTHn::createTarget(Int_t step, Bool_t sparse) { // fills the information stored in the buffer in this class into the target THn @@ -371,27 +278,23 @@ void StepTHn<TemplateArray, TemplateType>::createTarget(Int_t step, Bool_t spars if (!mTarget) { mTarget = new THnBase*[mNSteps]; - for (Int_t i = 0; i < mNSteps; i++) { + for (Int_t i = 0; i < mNSteps; i++) mTarget[i] = nullptr; - } } - if (mTarget[step]) { + if (mTarget[step]) return; - } - TemplateType* source = mValues[step]->GetArray(); + TArray* source = mValues[step]; // if mSumw2 is not stored, the sqrt of the number of bin entries in source is filled below; otherwise we use mSumw2 - TemplateType* sourceSumw2 = source; - if (mSumw2[step]) { - sourceSumw2 = mSumw2[step]->GetArray(); - } + TArray* sourceSumw2 = source; + if (mSumw2[step]) + sourceSumw2 = mSumw2[step]; - if (sparse) { + if (sparse) mTarget[step] = THnSparse::CreateSparse(Form("%s_%d", GetName(), step), Form("%s_%d", GetTitle(), step), mPrototype); - } else { + else mTarget[step] = THn::CreateHn(Form("%s_%d", GetName(), step), Form("%s_%d", GetTitle(), step), mPrototype); - } THnBase* target = mTarget[step]; @@ -411,9 +314,11 @@ void StepTHn<TemplateArray, TemplateType>::createTarget(Int_t step, Bool_t spars Long64_t globalBin = getGlobalBinIndex(binIdx); // Printf(" --> %lld", globalBin); - if (source[globalBin] != 0) { - target->SetBinContent(binIdx, source[globalBin]); - target->SetBinError(binIdx, TMath::Sqrt(sourceSumw2[globalBin])); + // TODO probably slow + double value = source->GetAt(globalBin); + if (value != 0) { + target->SetBinContent(binIdx, value); + target->SetBinError(binIdx, TMath::Sqrt(sourceSumw2->GetAt(globalBin))); count++; } @@ -427,9 +332,8 @@ void StepTHn<TemplateArray, TemplateType>::createTarget(Int_t step, Bool_t spars } } - if (binIdx[0] > nBins[0]) { + if (binIdx[0] > nBins[0]) break; - } } LOGF(info, "Step %d: copied %lld entries out of %lld bins", step, count, getGlobalBinIndex(binIdx)); @@ -441,94 +345,5 @@ void StepTHn<TemplateArray, TemplateType>::createTarget(Int_t step, Bool_t spars mValues[step] = nullptr; } -/* -template <class TemplateArray, typename TemplateType> -void StepTHn<TemplateArray, TemplateType>::FillParent() -{ - // fills the information stored in the buffer in this class into the baseclass containers - - FillContainer(this); -} - -template <class TemplateArray, typename TemplateType> -void StepTHn<TemplateArray, TemplateType>::ReduceAxis() -{ - // "removes" one axis by summing over the axis and putting the entry to bin 1 - // TODO presently only implemented for the last axis - - Int_t axis = mNVars-1; - - for (Int_t i=0; i<mNSteps; i++) - { - if (!mValues[i]) - continue; - - TemplateType* source = mValues[i]->GetArray(); - TemplateType* sourceSumw2 = 0; - if (mSumw2[i]) - sourceSumw2 = mSumw2[i]->GetArray(); - - THnSparse* target = GetGrid(i)->GetGrid(); - - Int_t* binIdx = new Int_t[mNVars]; - Int_t* nBins = new Int_t[mNVars]; - for (Int_t j=0; j<mNVars; j++) - { - binIdx[j] = 1; - nBins[j] = target->GetAxis(j)->GetNbins(); - } - - Long64_t count = 0; - - while (1) - { - // sum over axis <axis> - TemplateType sumValues = 0; - TemplateType sumSumw2 = 0; - for (Int_t j=1; j<=nBins[axis]; j++) - { - binIdx[axis] = j; - Long64_t globalBin = getGlobalBinIndex(binIdx); - sumValues += source[globalBin]; - source[globalBin] = 0; - - if (sourceSumw2) - { - sumSumw2 += sourceSumw2[globalBin]; - sourceSumw2[globalBin] = 0; - } - } - binIdx[axis] = 1; - - Long64_t globalBin = getGlobalBinIndex(binIdx); - source[globalBin] = sumValues; - if (sourceSumw2) - sourceSumw2[globalBin] = sumSumw2; - - count++; - - // next bin - binIdx[mNVars-2]++; - - for (Int_t j=mNVars-2; j>0; j--) - { - if (binIdx[j] > nBins[j]) - { - binIdx[j] = 1; - binIdx[j-1]++; - } - } - - if (binIdx[0] > nBins[0]) - break; - } - - AliInfo(Form("Step %d: reduced %lld bins to %lld entries", i, getGlobalBinIndex(binIdx), count)); - - delete[] binIdx; - delete[] nBins; - } -}*/ - -template class StepTHn<TArrayF, Float_t>; -template class StepTHn<TArrayD, Double_t>; +template class StepTHnT<TArrayF>; +template class StepTHnT<TArrayD>; diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index b55bec738780d..5b807bf3fe2c3 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -11,6 +11,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include <CCDB/BasicCCDBManager.h> #include "Analysis/EventSelection.h" #include "Analysis/TrackSelectionTables.h" @@ -22,6 +23,7 @@ #include <TH1F.h> #include <cmath> #include <TDirectory.h> +#include <THn.h> using namespace o2; using namespace o2::framework; @@ -50,6 +52,9 @@ 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") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyTrigger, std::string, "", "CCDB path to efficiency object for trigger particles") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyAssociated, std::string, "", "CCDB path to efficiency object for associated particles") + // 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 == true) || (aod::track::isGlobalTrackSDD == true)); @@ -62,8 +67,8 @@ struct CorrelationTask { struct Config { bool mPairCuts = false; - //THn* mEfficiencyTrigger = nullptr; - //THn* mEfficiencyAssociated = nullptr; + THn* mEfficiencyTrigger = nullptr; + THn* mEfficiencyAssociated = nullptr; } cfg; // HistogramRegistry registry{"qa", true, { @@ -76,6 +81,8 @@ struct CorrelationTask { PairCuts mPairCuts; + Service<o2::ccdb::BasicCCDBManager> ccdb; + void init(o2::framework::InitContext&) { // --- CONFIGURATION --- @@ -109,11 +116,39 @@ struct CorrelationTask { same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentralityVtx", binning)); mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentralityVtx", binning)); //qaOutput.setObject(new TDirectory("qa", "qa")); + + // o2-ccdb-upload -p Users/jgrosseo/correlations/LHC15o -f /tmp/correction_2011_global.root -k correction + + ccdb->setURL("http://ccdb-test.cern.ch:8080"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + long now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); // TODO must become global parameter from the train creation time + + if (cfgEfficiencyTrigger.value.empty() == false) { + cfg.mEfficiencyTrigger = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyTrigger, now); + LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), cfg.mEfficiencyTrigger); + } + if (cfgEfficiencyAssociated.value.empty() == false) { + cfg.mEfficiencyAssociated = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyAssociated, now); + LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), cfg.mEfficiencyAssociated); + } } // Version with explicit nested loop - void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents>>::iterator const& collision, myTracks const& tracks) + void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents>>::iterator const& collision, aod::BCsWithTimestamps const&, myTracks const& tracks) { + auto bc = collision.bc_as<aod::BCsWithTimestamps>(); + if (cfgEfficiencyTrigger.value.empty() == false) { + cfg.mEfficiencyTrigger = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyTrigger, bc.timestamp()); + LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), cfg.mEfficiencyTrigger); + } + if (cfgEfficiencyAssociated.value.empty() == false) { + cfg.mEfficiencyAssociated = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyAssociated, bc.timestamp()); + LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), cfg.mEfficiencyAssociated); + } + LOGF(info, "Tracks for collision: %d | Vertex: %.1f | INT7: %d | V0M: %.1f", tracks.size(), collision.posZ(), collision.sel7(), collision.centV0M()); const auto centrality = collision.centV0M(); @@ -133,6 +168,16 @@ struct CorrelationTask { int bSign = 1; // TODO magnetic field from CCDB + // Cache efficiency for particles (too many FindBin lookups) + float* efficiencyAssociated = nullptr; + if (cfg.mEfficiencyAssociated) { + efficiencyAssociated = new float[tracks.size()]; + int i = 0; + for (auto& track1 : tracks) { + efficiencyAssociated[i++] = getEfficiency(cfg.mEfficiencyAssociated, track1.eta(), track1.pt(), centrality, collision.posZ()); + } + } + for (auto& track1 : tracks) { // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); @@ -147,15 +192,17 @@ struct CorrelationTask { continue; } - double eventValues[3]; - eventValues[0] = track1.pt(); - eventValues[1] = centrality; - eventValues[2] = collision.posZ(); + float triggerWeight = 1.0; + if (cfg.mEfficiencyTrigger) { + triggerWeight = getEfficiency(cfg.mEfficiencyTrigger, track1.eta(), track1.pt(), centrality, collision.posZ()); + } - same->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + same->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, track1.pt(), centrality, collision.posZ(), triggerWeight); //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + int i = -1; for (auto& track2 : tracks) { + i++; // HACK if (track1 == track2) { continue; } @@ -179,34 +226,36 @@ struct CorrelationTask { continue; } - double values[6] = {0}; - - values[0] = track1.eta() - track2.eta(); - values[1] = track2.pt(); - values[2] = track1.pt(); - values[3] = centrality; + float associatedWeight = 1.0; + if (cfg.mEfficiencyAssociated) { + associatedWeight = efficiencyAssociated[i]; + } - values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) { - values[4] -= TMath::TwoPi(); + float deltaPhi = track1.phi() - track2.phi(); + if (deltaPhi > 1.5 * TMath::Pi()) { + deltaPhi -= TMath::TwoPi(); } - if (values[4] < -0.5 * TMath::Pi()) { - values[4] += TMath::TwoPi(); + if (deltaPhi < -0.5 * TMath::Pi()) { + deltaPhi += TMath::TwoPi(); } - values[5] = collision.posZ(); - - same->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + same->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, + track1.eta() - track2.eta(), track2.pt(), track1.pt(), centrality, deltaPhi, collision.posZ(), + triggerWeight * associatedWeight); //mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); } } + + delete[] efficiencyAssociated; } // Version with combinations - void process2(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& tracks) + void process2(soa::Join<aod::Collisions, aod::Cents>::iterator const& collision, soa::Filtered<aod::Tracks> const& tracks) { LOGF(info, "Tracks for collision (Combination run): %d", tracks.size()); + const auto centrality = collision.centV0M(); + int bSign = 1; // TODO magnetic field from CCDB for (auto track1 = tracks.begin(); track1 != tracks.end(); ++track1) { @@ -217,12 +266,7 @@ struct CorrelationTask { // LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi2(), track1.pt(), track1.pt()); - double eventValues[3]; - eventValues[0] = track1.pt(); - eventValues[1] = 0; // collision.v0mult(); - eventValues[2] = collision.posZ(); - - same->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + same->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, track1.pt(), centrality, collision.posZ()); //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); } @@ -247,27 +291,29 @@ struct CorrelationTask { continue; } - double values[6] = {0}; - - values[0] = track1.eta() - track2.eta(); - values[1] = track1.pt(); - values[2] = track2.pt(); - values[3] = 0; // collision.v0mult(); - - values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) { - values[4] -= TMath::TwoPi(); + float deltaPhi = track1.phi() - track2.phi(); + if (deltaPhi > 1.5 * TMath::Pi()) { + deltaPhi -= TMath::TwoPi(); } - if (values[4] < -0.5 * TMath::Pi()) { - values[4] += TMath::TwoPi(); + if (deltaPhi < -0.5 * TMath::Pi()) { + deltaPhi += TMath::TwoPi(); } - values[5] = collision.posZ(); - - same->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + same->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, + track1.eta() - track2.eta(), track2.pt(), track1.pt(), centrality, deltaPhi, collision.posZ()); //mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); } } + + double getEfficiency(THn* eff, float eta, float pt, float centrality, float posZ) + { + int effVars[4]; + effVars[0] = eff->GetAxis(0)->FindBin(eta); + effVars[1] = eff->GetAxis(1)->FindBin(pt); + effVars[2] = eff->GetAxis(2)->FindBin(centrality); + effVars[3] = eff->GetAxis(3)->FindBin(posZ); + return eff->GetBinContent(effVars); + } }; WorkflowSpec defineDataProcessing(ConfigContext const&) diff --git a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx index 349329d9a7afa..dfe2bdd13c8b1 100644 --- a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx +++ b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx @@ -146,12 +146,7 @@ struct CorrelationTask { continue; } - double eventValues[3]; - eventValues[0] = track1.pt(); - eventValues[1] = centrality; - eventValues[2] = collision.posZ(); - - same->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + same->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, track1.pt(), centrality, collision.posZ()); //mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); for (auto& track2 : tracks) { @@ -178,24 +173,14 @@ struct CorrelationTask { continue; } - double values[6] = {0}; - - values[0] = track1.eta() - track2.eta(); - values[1] = track2.pt(); - values[2] = track1.pt(); - values[3] = centrality; - - values[4] = track1.phi() - track2.phi(); - if (values[4] > 1.5 * TMath::Pi()) { - values[4] -= TMath::TwoPi(); - } - if (values[4] < -0.5 * TMath::Pi()) { - values[4] += TMath::TwoPi(); - } - - values[5] = collision.posZ(); + float deltaPhi = track1.phi() - track2.phi(); + if (deltaPhi > 1.5 * TMath::Pi()) + deltaPhi -= TMath::TwoPi(); + if (deltaPhi < -0.5 * TMath::Pi()) + deltaPhi += TMath::TwoPi(); - same->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + same->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, + track1.eta() - track2.eta(), track2.pt(), track1.pt(), centrality, deltaPhi, collision.posZ()); //mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); } } diff --git a/Analysis/Tasks/PWGCF/correlationsMixed.cxx b/Analysis/Tasks/PWGCF/correlationsMixed.cxx index a3c1f27c14e9f..62251eefb73c1 100644 --- a/Analysis/Tasks/PWGCF/correlationsMixed.cxx +++ b/Analysis/Tasks/PWGCF/correlationsMixed.cxx @@ -22,18 +22,6 @@ #include <cmath> #include <TDirectory.h> -namespace o2::aod -{ -namespace etaphi -{ -DECLARE_SOA_COLUMN(Etam, etam, float); -DECLARE_SOA_COLUMN(Phim, phim, float); -DECLARE_SOA_COLUMN(Ptm, ptm, float); -} // namespace etaphi -DECLARE_SOA_TABLE(EtaPhi, "AOD", "ETAPHI", - etaphi::Etam, etaphi::Phim, etaphi::Ptm); -} // namespace o2::aod - namespace o2::aod { namespace hash @@ -49,21 +37,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct ATask { - Produces<aod::EtaPhi> etaphi; - - void process(aod::Tracks const& tracks) - { - for (auto& track : tracks) { - float eta = log(tan(0.25f * static_cast<float>(M_PI) - 0.5f * atan(track.tgl()))); - float phi = asin(track.snp()) + track.alpha() + static_cast<float>(M_PI); - float pt = fabs(1.0f / track.signed1Pt()); - - etaphi(eta, phi, pt); - } - } -}; - struct HashTask { std::vector<float> vtxBins{-7.0f, -5.0f, -3.0f, -1.0f, 1.0f, 3.0f, 5.0f, 7.0f}; std::vector<float> multBins{0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f}; @@ -108,10 +81,10 @@ struct HashTask { struct CorrelationTask { // Input definitions - using myTracks = soa::Filtered<soa::Join<aod::Tracks, aod::EtaPhi>>; + using myTracks = soa::Filtered<aod::Tracks>; // Filters - Filter trackFilter = (aod::etaphi::etam > -0.8f) && (aod::etaphi::etam < 0.8f) && (aod::etaphi::ptm > 1.0f); + Filter trackFilter = (aod::track::eta > -0.8f) && (aod::track::eta < 0.8f) && (aod::track::pt > 1.0f); // Output definitions OutputObj<CorrelationContainer> same{"sameEvent"}; @@ -228,14 +201,9 @@ struct CorrelationTask { continue; } - //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.etam(), track1.phi(), track1.phim(), track1.pt(), track1.ptm()); + //LOGF(info, "TRACK %f %f | %f %f | %f %f", track1.eta(), track1.eta(), track1.phi(), track1.phi(), track1.pt(), track1.pt()); - double eventValues[3]; - eventValues[0] = track1.ptm(); - eventValues[1] = collision1.centV0M(); - eventValues[2] = collision1.posZ(); - - mixed->getTriggerHist()->Fill(eventValues, CorrelationContainer::kCFStepReconstructed); + mixed->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, track1.pt(), collision1.centV0M(), collision1.posZ()); for (auto& track2 : tracks2) { @@ -254,24 +222,16 @@ struct CorrelationTask { continue; } - double values[6] = {0}; - - values[0] = track1.etam() - track2.etam(); - values[1] = track1.ptm(); - values[2] = track2.ptm(); - values[3] = collision1.centV0M(); - - values[4] = track1.phim() - track2.phim(); - if (values[4] > 1.5 * TMath::Pi()) { - values[4] -= TMath::TwoPi(); + float deltaPhi = track1.phi() - track2.phi(); + if (deltaPhi > 1.5 * TMath::Pi()) { + deltaPhi -= TMath::TwoPi(); } - if (values[4] < -0.5 * TMath::Pi()) { - values[4] += TMath::TwoPi(); + if (deltaPhi < -0.5 * TMath::Pi()) { + deltaPhi += TMath::TwoPi(); } - values[5] = collision1.posZ(); - - mixed->getPairHist()->Fill(values, CorrelationContainer::kCFStepReconstructed); + mixed->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, + track1.eta() - track2.eta(), track2.pt(), track1.pt(), collision1.centV0M(), deltaPhi, collision1.posZ()); } } } @@ -312,7 +272,7 @@ struct CorrelationTask { template <typename T> bool conversionCut(T const& track1, T const& track2, PairCuts conv, double cut) { - //LOGF(info, "pt is %f %f", track1.ptm(), track2.ptm()); + //LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); if (cut < 0) { return false; @@ -376,21 +336,21 @@ struct CorrelationTask { float tantheta1 = 1e10; - if (track1.etam() < -1e-10 || track1.etam() > 1e-10) { - float expTmp = TMath::Exp(-track1.etam()); + if (track1.eta() < -1e-10 || track1.eta() > 1e-10) { + float expTmp = TMath::Exp(-track1.eta()); tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); } float tantheta2 = 1e10; - if (track2.etam() < -1e-10 || track2.etam() > 1e-10) { - float expTmp = TMath::Exp(-track2.etam()); + if (track2.eta() < -1e-10 || track2.eta() > 1e-10) { + float expTmp = TMath::Exp(-track2.eta()); tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); } - float e1squ = m0_1 * m0_1 + track1.ptm() * track1.ptm() * (1.0 + 1.0 / tantheta1 / tantheta1); - float e2squ = m0_2 * m0_2 + track2.ptm() * track2.ptm() * (1.0 + 1.0 / tantheta2 / tantheta2); + float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); - float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.ptm() * track2.ptm() * (TMath::Cos(track1.phim() - track2.phim()) + 1.0 / tantheta1 / tantheta2))); + float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (TMath::Cos(track1.phi() - track2.phi()) + 1.0 / tantheta1 / tantheta2))); // Printf(Form("%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2)); @@ -402,12 +362,12 @@ struct CorrelationTask { { // calculate inv mass squared approximately - const float eta1 = track1.etam(); - const float eta2 = track2.etam(); - const float phi1 = track1.phim(); - const float phi2 = track2.phim(); - const float pt1 = track1.ptm(); - const float pt2 = track2.ptm(); + const float eta1 = track1.eta(); + const float eta2 = track2.eta(); + const float phi1 = track1.phi(); + const float phi2 = track2.phi(); + const float pt1 = track1.pt(); + const float pt2 = track2.pt(); float tantheta1 = 1e10; @@ -456,7 +416,7 @@ struct CorrelationTask { // the variables & cuthave been developed by the HBT group // see e.g. https://indico.cern.ch/materialDisplay.py?contribId=36&sessionId=6&materialId=slides&confId=142700 - auto deta = track1.etam() - track2.etam(); + auto deta = track1.eta() - track2.eta(); // optimization if (TMath::Abs(deta) < cfgTwoTrackCut * 2.5 * 3) { @@ -480,14 +440,14 @@ struct CorrelationTask { } } - qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.ptm() - track2.ptm())); + qa.mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); if (dphistarminabs < cfgTwoTrackCut && TMath::Abs(deta) < cfgTwoTrackCut) { - //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phim(), track1.ptm(), track1.charge(), track2.phim(), track2.ptm(), track2.charge(), bSign); + //Printf("Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi(), track1.pt(), track1.charge(), track2.phi(), track2.pt(), track2.charge(), bSign); return true; } - qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.ptm() - track2.ptm())); + qa.mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); } } @@ -501,12 +461,12 @@ struct CorrelationTask { // calculates dphistar // - auto phi1 = track1.phim(); - auto pt1 = track1.ptm(); + auto phi1 = track1.phi(); + auto pt1 = track1.pt(); auto charge1 = track1.charge(); - auto phi2 = track2.phim(); - auto pt2 = track2.ptm(); + auto phi2 = track2.phi(); + auto pt2 = track2.pt(); auto charge2 = track2.charge(); float dphistar = phi1 - phi2 - charge1 * bSign * TMath::ASin(0.075 * radius / pt1) + charge2 * bSign * TMath::ASin(0.075 * radius / pt2); @@ -533,7 +493,7 @@ struct CorrelationTask { // static_assert("Need to pass aod::track"); // // - // // LOGF(info, "pt %f", track1.ptm()); + // // LOGF(info, "pt %f", track1.pt()); // return false; // } @@ -543,7 +503,6 @@ struct CorrelationTask { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<ATask>("produce-etaphi"), adaptAnalysisTask<HashTask>("produce-hashes"), adaptAnalysisTask<CorrelationTask>("correlation-task")}; } From 6aff34723502e69a54d80c93d86c11e330a637e5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 26 Oct 2020 22:56:04 +0100 Subject: [PATCH 1111/1751] GPU: Fix debug code for track merging by MC label --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 2 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 8d5fb8e0b824c..bfb5a3ba18768 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -41,7 +41,7 @@ #include "GPUTPCGMSliceTrack.h" #include "GPUTPCGMBorderTrack.h" -#ifdef GPUCA_CADEBUG_ENABLED +#if defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) #include "AliHLTTPCClusterMCData.h" #endif diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 6c25f4f666389..3756b9bac4500 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -66,8 +66,8 @@ using namespace GPUCA_NAMESPACE::gpu; #ifdef GPUCA_MERGER_BY_MC_LABEL #define CHECK_CLUSTER_STATE_INIT_LEG_BY_MC() \ if (!unattached && mTrackMCLabels[id].isValid()) { \ - int mcLabel = mTrackMCLabels[id].getTrackID()); \ - if (mTrackMCLabelsReverse[mcLabel] != id) { \ + int mcLabel = mTrackMCLabels[id].getTrackID(); \ + if (mTrackMCLabelsReverse[0][mcLabel] != id) { \ attach &= (~gputpcgmmergertypes::attachGoodLeg); \ } \ } From fb758ff995c07841d57c101004f475a73d526890 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 26 Oct 2020 23:17:10 +0100 Subject: [PATCH 1112/1751] GPU: Add option to force standalone QA to ignore MC labels even if present --- GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 6a64bc1e0b6be..e00b6e2c3f0f8 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -111,6 +111,7 @@ AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan i AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") AddOption(runQA, bool, false, "qa", 'q', "Enable tracking QA", message("Running QA: %s")) +AddOption(QAnoMC, bool, false, "", 0, "Force running QA without MC labels even if present") AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") AddOption(forceMemoryPoolSize, unsigned long, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ul)) AddOption(forceHostMemoryPoolSize, unsigned long, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ul)) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 3756b9bac4500..9a08545be3f3b 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -180,7 +180,7 @@ inline int GPUQA::GetMCLabelCol(unsigned int i, unsigned int j) { return mTracki inline float GPUQA::GetMCLabelWeight(unsigned int i, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return 1; } -inline bool GPUQA::mcPresent() { return mTracking->mIOPtrs.clustersNative->clustersMCTruth && mNColTracks.size(); } +inline bool GPUQA::mcPresent() { return !mTracking->GetProcessingSettings().QAnoMC && mTracking->mIOPtrs.clustersNative->clustersMCTruth && mNColTracks.size(); } #define TRACK_EXPECTED_REFERENCE_X 78 #else inline GPUQA::mcLabelI_t::mcLabelI_t(const GPUQA::mcLabel_t& l) : track(l.fMCID) @@ -206,7 +206,7 @@ inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return label.fWeight; } inline int GPUQA::FakeLabelID(int id) { return id < 0 ? id : (-2 - id); } inline int GPUQA::AbsLabelID(int id) { return id >= 0 ? id : (-id - 2); } -inline bool GPUQA::mcPresent() { return GetNMCLabels() && GetNMCTracks(0); } +inline bool GPUQA::mcPresent() { return !mTracking->GetProcessingSettings().QAnoMC && GetNMCLabels() && GetNMCTracks(0); } #define TRACK_EXPECTED_REFERENCE_X 81 #endif template <class T> From 2e56e6bd73ee83732383fdadc46f6e7e6770fe5c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 10:15:22 +0100 Subject: [PATCH 1113/1751] GPU: FollowCircle will always find clusters of high incl. angle, impossible to store as goodLeg --- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 17 ++++++++--------- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h | 5 ++--- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index e6817a271339f..87efc2346b9b9 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -172,7 +172,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, if (tryFollow) { const GPUTPCGMTrackParam backup = *this; const float backupAlpha = prop.GetAlpha(); - if (FollowCircle<0>(merger, prop, lastSlice, lastRow, iTrk, clusters[ihit].leg == clusters[maxN - 1].leg, clAlpha, xx, yy, clusters[ihit].slice, clusters[ihit].row, inFlyDirection)) { + if (FollowCircle<0>(merger, prop, lastSlice, lastRow, iTrk, clAlpha, xx, yy, clusters[ihit].slice, clusters[ihit].row, inFlyDirection)) { CADEBUG(printf("Error during follow circle, resetting track!\n")); *this = backup; prop.SetTrack(this, backupAlpha); @@ -569,7 +569,7 @@ GPUd() bool GPUTPCGMTrackParam::FollowCircleChk(float lrFactor, float toY, float (up ? (-mP[0] * lrFactor > toX || (right ^ (mP[2] > 0))) : (-mP[0] * lrFactor < toX || (right ^ (mP[2] < 0)))); // don't overshoot in X } -GPUdic(0, 1) void GPUTPCGMTrackParam::StoreAttachMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toY, float toX, int toSlice, int toRow, bool inFlyDirection, float alpha) +GPUdic(0, 1) void GPUTPCGMTrackParam::StoreAttachMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, float toAlpha, float toY, float toX, int toSlice, int toRow, bool inFlyDirection, float alpha) { unsigned int nLoopData = CAMath::AtomicAdd(&Merger->Memory()->nLoopData, 1u); if (nLoopData >= Merger->NMaxTracks()) { @@ -581,7 +581,6 @@ GPUdic(0, 1) void GPUTPCGMTrackParam::StoreAttachMirror(const GPUTPCGMMerger* GP data.param = *this; data.alpha = alpha; data.track = iTrack; - data.goodLeg = goodLeg; data.toAlpha = toAlpha; data.toY = toY; data.toX = toX; @@ -610,18 +609,18 @@ GPUdii() void GPUTPCGMTrackParam::RefitLoop(const GPUTPCGMMerger* GPUrestrict() if (data.toRow == 0) { data.param.AttachClustersMirror<1>(Merger, data.slice, data.row, data.track, data.toY, prop, true); } else { - data.param.FollowCircle<1>(Merger, prop, data.slice, data.row, data.track, data.goodLeg, data.toAlpha, data.toY, data.toX, data.toSlice, data.toRow, data.inFlyDirection, true); + data.param.FollowCircle<1>(Merger, prop, data.slice, data.row, data.track, data.toAlpha, data.toY, data.toX, data.toSlice, data.toRow, data.inFlyDirection, true); } } template <int I> -GPUdic(0, 1) int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestrict() Merger, GPUTPCGMPropagator& GPUrestrict() prop, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toX, float toY, int toSlice, int toRow, bool inFlyDirection, bool phase2) +GPUdic(0, 1) int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestrict() Merger, GPUTPCGMPropagator& GPUrestrict() prop, int slice, int iRow, int iTrack, float toAlpha, float toX, float toY, int toSlice, int toRow, bool inFlyDirection, bool phase2) { if (Merger->Param().rec.DisableRefitAttachment & 4) { return 1; } if (Merger->Param().rec.loopInterpolationInExtraPass && phase2 == false) { - StoreAttachMirror(Merger, slice, iRow, iTrack, goodLeg, toAlpha, toY, toX, toSlice, toRow, inFlyDirection, prop.GetAlpha()); + StoreAttachMirror(Merger, slice, iRow, iTrack, toAlpha, toY, toX, toSlice, toRow, inFlyDirection, prop.GetAlpha()); return 1; } const GPUParam& GPUrestrict() param = Merger->Param(); @@ -639,7 +638,7 @@ GPUdic(0, 1) int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestr CADEBUG(printf("CIRCLE Track %d: Slice %d Alpha %f X %f Y %f Z %f SinPhi %f DzDs %f - Next hit: Slice %d Alpha %f X %f Y %f - Right %d Up %d dAlpha %f lrFactor %f\n", iTrack, slice, prop.GetAlpha(), mX, mP[0], mP[1], mP[2], mP[3], toSlice, toAlpha, toX, toY, (int)right, (int)up, dAlpha, lrFactor)); // clang-format on - AttachClustersPropagate(Merger, slice, iRow, targetRow, iTrack, goodLeg, prop, inFlyDirection, 0.7f); + AttachClustersPropagate(Merger, slice, iRow, targetRow, iTrack, false, prop, inFlyDirection, 0.7f); if (prop.RotateToAlpha(prop.GetAlpha() + (M_PI / 2.f) * lrFactor)) { return 1; } @@ -710,7 +709,7 @@ GPUdic(0, 1) int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestr } } prop.PropagateToXAlpha(Merger->Param().tpcGeometry.Row2X(iRow) + dx, prop.GetAlpha(), inFlyDirection); - AttachClustersPropagate(Merger, slice, iRow, toRow, iTrack, !goodLeg, prop, inFlyDirection); + AttachClustersPropagate(Merger, slice, iRow, toRow, iTrack, false, prop, inFlyDirection); } if (prop.PropagateToXAlpha(toX, prop.GetAlpha(), inFlyDirection)) { mX = toX; @@ -726,7 +725,7 @@ GPUdni() void GPUTPCGMTrackParam::AttachClustersMirror(const GPUTPCGMMerger* GPU return; } if (Merger->Param().rec.loopInterpolationInExtraPass && phase2 == false) { - StoreAttachMirror(Merger, slice, iRow, iTrack, false, 0, toY, 0, 0, 0, 0, prop.GetAlpha()); + StoreAttachMirror(Merger, slice, iRow, iTrack, 0, toY, 0, 0, 0, 0, prop.GetAlpha()); return; } float X = mP[2] > 0 ? mP[0] : -mP[0]; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h index ad7c97388d249..dd7706547f8fd 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.h @@ -159,8 +159,8 @@ class GPUTPCGMTrackParam template <int I> GPUd() void AttachClustersMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, float toY, GPUTPCGMPropagator& prop, bool phase2 = false); template <int I> - GPUd() int FollowCircle(const GPUTPCGMMerger* GPUrestrict() Merger, GPUTPCGMPropagator& prop, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toX, float toY, int toSlice, int toRow, bool inFlyDirection, bool phase2 = false); - GPUd() void StoreAttachMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, bool goodLeg, float toAlpha, float toY, float toX, int toSlice, int toRow, bool inFlyDirection, float alpha); + GPUd() int FollowCircle(const GPUTPCGMMerger* GPUrestrict() Merger, GPUTPCGMPropagator& prop, int slice, int iRow, int iTrack, float toAlpha, float toX, float toY, int toSlice, int toRow, bool inFlyDirection, bool phase2 = false); + GPUd() void StoreAttachMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, float toAlpha, float toY, float toX, int toSlice, int toRow, bool inFlyDirection, float alpha); GPUd() static void RefitLoop(const GPUTPCGMMerger* GPUrestrict() Merger, int loopIdx); GPUdi() void MarkClusters(GPUTPCGMMergedTrackHit* GPUrestrict() clusters, int ihitFirst, int ihitLast, int wayDirection, unsigned char state) @@ -247,7 +247,6 @@ struct GPUTPCGMLoopData { unsigned char toSlice; unsigned char toRow; unsigned char inFlyDirection; - unsigned char goodLeg; }; GPUdi() int GPUTPCGMTrackParam::initResetT0() From 251902c6a31f52ea2dc9dbc2351881e0e1ae247e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 10:15:50 +0100 Subject: [PATCH 1114/1751] GPU: Use ptCut from parameters instead of hardcoded constant --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 9a08545be3f3b..e3d1fbb7aa9a0 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -83,7 +83,7 @@ using namespace GPUCA_NAMESPACE::gpu; int id = attach & gputpcgmmergertypes::attachTrackMask; \ if (!unattached) { \ qpt = fabsf(merger.OutputTracks()[id].GetParam().GetQPt()); \ - lowPt = qpt > 20; \ + lowPt = qpt > mTracking->GetParam().rec.tpcRejectQPt; \ mev200 = qpt > 5; \ } \ bool physics = false, protect = false; \ From 3f3cb4853081fe8c73b03cafce416be0a9835c11 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 10:16:48 +0100 Subject: [PATCH 1115/1751] GPU: Bugfix, primary leg of track with 50<pt<200 MeV should be protected --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index e3d1fbb7aa9a0..169146d292394 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -98,10 +98,11 @@ using namespace GPUCA_NAMESPACE::gpu; mNRecClustersLowPt++; \ } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { \ mNRecClustersLoopers++; \ - } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ - mNRecClustersTube200++; \ } else if (attach & gputpcgmmergertypes::attachHighIncl) { \ mNRecClustersHighIncl++; \ + } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ + mNRecClustersTube200++; \ + protect = true; \ } else if (attach & gputpcgmmergertypes::attachTube) { \ protect = true; \ mNRecClustersTube++; \ @@ -116,8 +117,9 @@ using namespace GPUCA_NAMESPACE::gpu; if (unattached) { \ } else if (lowPt) { \ } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { \ - } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ } else if (attach & gputpcgmmergertypes::attachHighIncl) { \ + } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ + protect = true; \ } else if (attach & gputpcgmmergertypes::attachTube) { \ protect = true; \ } else if ((attach & gputpcgmmergertypes::attachGood) == 0) { \ From 957792889ac2117306bbe1836e7a8a7e4d0908b4 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 10:38:20 +0100 Subject: [PATCH 1116/1751] GPU: Unify cluster rejection logic in central inline function --- GPU/GPUTracking/CMakeLists.txt | 1 + .../DataCompression/GPUTPCClusterRejection.h | 72 +++++++++++ .../GPUTPCCompressionKernels.cxx | 8 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 122 +++++++----------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 7 +- 5 files changed, 126 insertions(+), 84 deletions(-) create mode 100644 GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 3bd2719953d2e..afa465d8e025c 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -131,6 +131,7 @@ set(HDRS_INSTALL Global/GPUErrorCodes.h Standalone/qconfigoptions.h Base/GPUSettingsList.h + DataCompression/GPUTPCClusterRejection.h ) # Sources only for O2 diff --git a/GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h b/GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h new file mode 100644 index 0000000000000..890e15b7df61d --- /dev/null +++ b/GPU/GPUTracking/DataCompression/GPUTPCClusterRejection.h @@ -0,0 +1,72 @@ +// 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 GPUTPCClusterRejection.h +/// \author David Rohr + +#ifndef GPUTPCCLUSTERREJECTION_H +#define GPUTPCCLUSTERREJECTION_H + +#include "GPUTPCGMMergerTypes.h" + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ +struct GPUTPCClusterRejection { + template <bool C, class T = void, class S = void> + static constexpr inline bool GetProtectionStatus(int attach, bool& physics, bool& protect, T* counts = nullptr, S* mev200 = nullptr) + { + (void)counts; // Avoid incorrect -Wunused-but-set-parameter warning + (void)mev200; + if (attach == 0) { + return false; + } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { + if constexpr (C) { + counts->nLoopers++; + } + return true; + } else if (attach & gputpcgmmergertypes::attachHighIncl) { + if constexpr (C) { + counts->nHighIncl++; + } + return true; + } else if (attach & gputpcgmmergertypes::attachTube) { + protect = true; + if constexpr (C) { + if (*mev200) { + counts->nTube200++; + } else { + counts->nTube++; + } + } + return false; + } else if ((attach & gputpcgmmergertypes::attachGood) == 0) { + protect = true; + if constexpr (C) { + counts->nRejected++; + } + return false; + } else { + physics = true; + return false; + } + } + + static constexpr inline bool GetIsRejected(int attach) + { + bool physics = false, protect = false; + return GetProtectionStatus<false>(attach, physics, protect); + } +}; +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 36696abf96714..0d10bd5732d03 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -19,6 +19,7 @@ #include "GPUCommonAlgorithm.h" #include "GPUTPCCompressionTrackModel.h" #include "GPUTPCGeometry.h" +#include "GPUTPCClusterRejection.h" using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; @@ -56,7 +57,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at if ((attach & gputpcgmmergertypes::attachTrackMask) != i) { continue; // Main attachment to different track } - bool rejectCluster = processors.param.rec.tpcRejectionMode && (rejectTrk || ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) || (attach & gputpcgmmergertypes::attachHighIncl)); + bool rejectCluster = processors.param.rec.tpcRejectionMode && (rejectTrk || GPUTPCClusterRejection::GetIsRejected(attach)); if (rejectCluster) { compressor.mClusterStatus[hitId] = 1; // Cluster rejected, do not store continue; @@ -214,10 +215,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un break; } } else if (processors.param.rec.tpcRejectionMode >= GPUSettings::RejectionStrategyA) { - if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { - break; - } - if (attach & gputpcgmmergertypes::attachHighIncl) { + if (GPUTPCClusterRejection::GetIsRejected(attach)) { break; } int id = attach & gputpcgmmergertypes::attachTrackMask; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 169146d292394..993a562312a93 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -41,6 +41,7 @@ #include "GPUTPCClusterData.h" #include "GPUO2DataTypes.h" #include "GPUParam.inc" +#include "GPUTPCClusterRejection.h" #ifdef GPUCA_O2_LIB #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" @@ -89,55 +90,24 @@ using namespace GPUCA_NAMESPACE::gpu; bool physics = false, protect = false; \ CHECK_CLUSTER_STATE_INIT_LEG_BY_MC(); -#define CHECK_CLUSTER_STATE_CHK_COUNT() \ - if (!unattached && mev200) { \ - mNRecClusters200MeV++; \ - } \ - if (unattached) { \ - } else if (lowPt) { \ - mNRecClustersLowPt++; \ - } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { \ - mNRecClustersLoopers++; \ - } else if (attach & gputpcgmmergertypes::attachHighIncl) { \ - mNRecClustersHighIncl++; \ - } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ - mNRecClustersTube200++; \ - protect = true; \ - } else if (attach & gputpcgmmergertypes::attachTube) { \ - protect = true; \ - mNRecClustersTube++; \ - } else if ((attach & gputpcgmmergertypes::attachGood) == 0) { \ - protect = true; \ - mNRecClustersRejected++; \ - } else { \ - physics = true; \ +#define CHECK_CLUSTER_STATE() \ + CHECK_CLUSTER_STATE_INIT() \ + if (mev200) { \ + mClusterCounts.n200MeV++; \ + } \ + if (lowPt) { \ + mClusterCounts.nLowPt++; \ + } else { \ + GPUTPCClusterRejection::GetProtectionStatus<true>(attach, physics, protect, &mClusterCounts, &mev200); \ } -#define CHECK_CLUSTER_STATE_CHK_NOCOUNT() \ - if (unattached) { \ - } else if (lowPt) { \ - } else if ((attach & gputpcgmmergertypes::attachGoodLeg) == 0) { \ - } else if (attach & gputpcgmmergertypes::attachHighIncl) { \ - } else if ((attach & gputpcgmmergertypes::attachTube) && mev200) { \ - protect = true; \ - } else if (attach & gputpcgmmergertypes::attachTube) { \ - protect = true; \ - } else if ((attach & gputpcgmmergertypes::attachGood) == 0) { \ - protect = true; \ - } else { \ - physics = true; \ +#define CHECK_CLUSTER_STATE_NOCOUNT() \ + CHECK_CLUSTER_STATE_INIT() \ + (void)mev200; /* silence unused variable warning*/ \ + if (!lowPt) { \ + GPUTPCClusterRejection::GetProtectionStatus<false>(attach, physics, protect); \ } -// clang-format off -#define CHECK_CLUSTER_STATE() \ - CHECK_CLUSTER_STATE_INIT() \ - CHECK_CLUSTER_STATE_CHK_COUNT() //Fill state variables, increase counters - -#define CHECK_CLUSTER_STATE_NOCOUNT() \ - CHECK_CLUSTER_STATE_INIT() \ - CHECK_CLUSTER_STATE_CHK_NOCOUNT() //Fill state variables, do not increase counters -// clang-format on - #ifdef GPUCA_STANDALONE namespace GPUCA_NAMESPACE::gpu { @@ -1106,7 +1076,7 @@ GPUCA_OPENMP(parallel for) mClusters[CL_fake]->Fill(0.f, weight); mClusters[CL_att_adj]->Fill(0.f, weight); mClusters[CL_all]->Fill(0.f, weight); - mNRecClustersUnaccessible += weight; + mClusterCounts.nUnaccessible += weight; if (protect || physics) { mClusters[CL_prot]->Fill(0.f, weight); } @@ -1202,7 +1172,7 @@ GPUCA_OPENMP(parallel for) mClusters[CL_att_adj]->Fill(0.f, 1.f); mClusters[CL_fakeAdj]->Fill(0.f, 1.f); mClusters[CL_all]->Fill(0.f, 1.f); - mNRecClustersUnaccessible++; + mClusterCounts.nUnaccessible++; if (protect || physics) { mClusters[CL_prot]->Fill(0.f, 1.f); } @@ -1268,7 +1238,7 @@ GPUCA_OPENMP(parallel for) mClusters[CL_att_adj]->Fill(0.f, 1.f); } mClusters[CL_all]->Fill(0.f, 1.f); - mNRecClustersUnaccessible++; + mClusterCounts.nUnaccessible++; if (protect || physics) { mClusters[CL_prot]->Fill(0.f, 1.f); } @@ -1317,10 +1287,10 @@ GPUCA_OPENMP(parallel for) } if (totalWeight > 0 && 10.f * weight400 >= totalWeight) { if (!unattached && !protect && !physics) { - mNRecClustersFakeRemove400++; + mClusterCounts.nFakeRemove400++; int totalFake = weight400 < 0.9f * totalWeight; if (totalFake) { - mNRecClustersFullFakeRemove400++; + mClusterCounts.nFullFakeRemove400++; } /*printf("Fake removal (%d): Hit %7d, attached %d lowPt %d looper %d tube200 %d highIncl %d tube %d bad %d recPt %7.2f recLabel %6d", totalFake, i, (int) (mClusterParam[i].attached || mClusterParam[i].fakeAttached), (int) lowPt, (int) ((attach & gputpcgmmergertypes::attachGoodLeg) == 0), (int) ((attach & gputpcgmmergertypes::attachTube) && mev200), @@ -1335,24 +1305,24 @@ GPUCA_OPENMP(parallel for) } printf("\n");*/ } - mNRecClustersAbove400++; + mClusterCounts.nAbove400++; } if (totalWeight == 0 && weight40 >= 0.9 * totalWeight) { - mNRecClustersBelow40++; + mClusterCounts.nBelow40++; if (protect || physics) { - mNRecClustersFakeProtect40++; + mClusterCounts.nFakeProtect40++; } } } else { - mNRecClustersTotal++; + mClusterCounts.nTotal++; if (physics) { - mNRecClustersPhysics++; + mClusterCounts.nPhysics++; } if (physics || protect) { - mNRecClustersProt++; + mClusterCounts.nProt++; } if (unattached) { - mNRecClustersUnattached++; + mClusterCounts.nUnattached++; } } } @@ -2029,9 +1999,9 @@ int GPUQA::DrawQAHistograms() } counts[i] = val; } - mNRecClustersRejected += mNRecClustersHighIncl; + mClusterCounts.nRejected += mClusterCounts.nHighIncl; if (!mcAvail) { - counts[N_CLS_HIST - 1] = mNRecClustersTotal; + counts[N_CLS_HIST - 1] = mClusterCounts.nTotal; } if (counts[N_CLS_HIST - 1]) { if (mcAvail) { @@ -2040,30 +2010,30 @@ int GPUQA::DrawQAHistograms() } printf("\t%35s: %'12llu (%6.2f%%)\n", "Unattached", counts[N_CLS_HIST - 1] - counts[CL_att_adj], 100.f * (counts[N_CLS_HIST - 1] - counts[CL_att_adj]) / counts[N_CLS_HIST - 1]); printf("\t%35s: %'12llu (%6.2f%%)\n", "Removed", counts[CL_att_adj] - counts[CL_prot], 100.f * (counts[CL_att_adj] - counts[CL_prot]) / counts[N_CLS_HIST - 1]); // Attached + Adjacent (also fake) - protected - printf("\t%35s: %'12llu (%6.2f%%)\n", "Unaccessible", (unsigned long long int)mNRecClustersUnaccessible, 100.f * mNRecClustersUnaccessible / counts[N_CLS_HIST - 1]); // No contribution from track >= 10 MeV, unattached or fake-attached/adjacent + printf("\t%35s: %'12llu (%6.2f%%)\n", "Unaccessible", (unsigned long long int)mClusterCounts.nUnaccessible, 100.f * mClusterCounts.nUnaccessible / counts[N_CLS_HIST - 1]); // No contribution from track >= 10 MeV, unattached or fake-attached/adjacent } else { printf("\t%35s: %'12llu (%6.2f%%)\n", "All Clusters", counts[N_CLS_HIST - 1], 100.f); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Used in Physics", mNRecClustersPhysics, 100.f * mNRecClustersPhysics / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Protected", mNRecClustersProt, 100.f * mNRecClustersProt / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Unattached", mNRecClustersUnattached, 100.f * mNRecClustersUnattached / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Removed", mNRecClustersTotal - mNRecClustersUnattached - mNRecClustersProt, 100.f * (mNRecClustersTotal - mNRecClustersUnattached - mNRecClustersProt) / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Used in Physics", mClusterCounts.nPhysics, 100.f * mClusterCounts.nPhysics / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Protected", mClusterCounts.nProt, 100.f * mClusterCounts.nProt / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Unattached", mClusterCounts.nUnattached, 100.f * mClusterCounts.nUnattached / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Removed", mClusterCounts.nTotal - mClusterCounts.nUnattached - mClusterCounts.nProt, 100.f * (mClusterCounts.nTotal - mClusterCounts.nUnattached - mClusterCounts.nProt) / counts[N_CLS_HIST - 1]); } - printf("\t%35s: %'12llu (%6.2f%%)\n", "High Inclination Angle", mNRecClustersHighIncl, 100.f * mNRecClustersHighIncl / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Rejected", mNRecClustersRejected, 100.f * mNRecClustersRejected / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Tube (> 200 MeV)", mNRecClustersTube, 100.f * mNRecClustersTube / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Tube (< 200 MeV)", mNRecClustersTube200, 100.f * mNRecClustersTube200 / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Looping Legs", mNRecClustersLoopers, 100.f * mNRecClustersLoopers / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Low Pt < 50 MeV", mNRecClustersLowPt, 100.f * mNRecClustersLowPt / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Low Pt < 200 MeV", mNRecClusters200MeV, 100.f * mNRecClusters200MeV / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "High Inclination Angle", mClusterCounts.nHighIncl, 100.f * mClusterCounts.nHighIncl / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Rejected", mClusterCounts.nRejected, 100.f * mClusterCounts.nRejected / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Tube (> 200 MeV)", mClusterCounts.nTube, 100.f * mClusterCounts.nTube / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Tube (< 200 MeV)", mClusterCounts.nTube200, 100.f * mClusterCounts.nTube200 / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Looping Legs", mClusterCounts.nLoopers, 100.f * mClusterCounts.nLoopers / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Low Pt < 50 MeV", mClusterCounts.nLowPt, 100.f * mClusterCounts.nLowPt / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Low Pt < 200 MeV", mClusterCounts.n200MeV, 100.f * mClusterCounts.n200MeV / counts[N_CLS_HIST - 1]); if (mcAvail) { - printf("\t%35s: %'12llu (%6.2f%%)\n", "Tracks > 400 MeV", mNRecClustersAbove400, 100.f * mNRecClustersAbove400 / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Fake Removed (> 400 MeV)", mNRecClustersFakeRemove400, 100.f * mNRecClustersFakeRemove400 / std::max(mNRecClustersAbove400, 1ll)); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Full Fake Removed (> 400 MeV)", mNRecClustersFullFakeRemove400, 100.f * mNRecClustersFullFakeRemove400 / std::max(mNRecClustersAbove400, 1ll)); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Tracks > 400 MeV", mClusterCounts.nAbove400, 100.f * mClusterCounts.nAbove400 / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Fake Removed (> 400 MeV)", mClusterCounts.nFakeRemove400, 100.f * mClusterCounts.nFakeRemove400 / std::max(mClusterCounts.nAbove400, 1ll)); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Full Fake Removed (> 400 MeV)", mClusterCounts.nFullFakeRemove400, 100.f * mClusterCounts.nFullFakeRemove400 / std::max(mClusterCounts.nAbove400, 1ll)); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Tracks < 40 MeV", mNRecClustersBelow40, 100.f * mNRecClustersBelow40 / counts[N_CLS_HIST - 1]); - printf("\t%35s: %'12llu (%6.2f%%)\n", "Fake Protect (< 40 MeV)", mNRecClustersFakeProtect40, 100.f * mNRecClustersFakeProtect40 / std::max(mNRecClustersBelow40, 1ll)); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Tracks < 40 MeV", mClusterCounts.nBelow40, 100.f * mClusterCounts.nBelow40 / counts[N_CLS_HIST - 1]); + printf("\t%35s: %'12llu (%6.2f%%)\n", "Fake Protect (< 40 MeV)", mClusterCounts.nFakeProtect40, 100.f * mClusterCounts.nFakeProtect40 / std::max(mClusterCounts.nBelow40, 1ll)); } } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index a9e6e98dcca2a..1082853b0d537 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -236,9 +236,10 @@ class GPUQA TPad* mPClust[N_CLS_TYPE]; TLegend* mLClust[N_CLS_TYPE]; - long long int mNRecClustersRejected = 0, mNRecClustersTube = 0, mNRecClustersTube200 = 0, mNRecClustersLoopers = 0, mNRecClustersLowPt = 0, mNRecClusters200MeV = 0, mNRecClustersPhysics = 0, mNRecClustersProt = 0, mNRecClustersUnattached = 0, mNRecClustersTotal = 0, mNRecClustersHighIncl = 0, - mNRecClustersAbove400 = 0, mNRecClustersFakeRemove400 = 0, mNRecClustersFullFakeRemove400 = 0, mNRecClustersBelow40 = 0, mNRecClustersFakeProtect40 = 0; - double mNRecClustersUnaccessible = 0; + struct counts_t { + long long int nRejected = 0, nTube = 0, nTube200 = 0, nLoopers = 0, nLowPt = 0, n200MeV = 0, nPhysics = 0, nProt = 0, nUnattached = 0, nTotal = 0, nHighIncl = 0, nAbove400 = 0, nFakeRemove400 = 0, nFullFakeRemove400 = 0, nBelow40 = 0, nFakeProtect40 = 0; + double nUnaccessible = 0; + } mClusterCounts; TH1F* mTracks; TCanvas* mCTracks; From deba9912ee3379ac85e081ebea6d98ae6e3daafc Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 27 Oct 2020 09:43:16 +0100 Subject: [PATCH 1117/1751] DPL: cleanup a few warnings / header leaking --- Framework/Core/include/Framework/DeviceInfo.h | 1 - Framework/Core/include/Framework/ServiceRegistry.h | 1 - Framework/Core/include/Framework/Variant.h | 1 - 3 files changed, 3 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceInfo.h b/Framework/Core/include/Framework/DeviceInfo.h index 8d384b36d1b23..3cf0e1c46e105 100644 --- a/Framework/Core/include/Framework/DeviceInfo.h +++ b/Framework/Core/include/Framework/DeviceInfo.h @@ -12,7 +12,6 @@ #include "Framework/LogParsingHelpers.h" #include "Framework/Metric2DViewIndex.h" -#include "Framework/Variant.h" #include "Framework/DeviceState.h" #include <cstddef> diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index 5490a1bbc32f2..b9bf54eddacce 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -163,7 +163,6 @@ struct ServiceRegistry { // This method should NEVER register a new service, event when requested. int getPos(uint32_t typeHash, uint64_t threadId) const { - auto id = typeHash & MAX_SERVICES_MASK; auto threadHashId = (typeHash ^ threadId) & MAX_SERVICES_MASK; std::atomic_thread_fence(std::memory_order_acquire); for (uint8_t i = 0; i < MAX_DISTANCE; ++i) { diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index e2bddf83dba57..cc3ac3ac008ba 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -219,7 +219,6 @@ class Variant template <typename T> T get() const { - auto v = variant_trait_v<T>; if (mType != variant_trait_v<T>) { throw runtime_error("Mismatch between types"); } From f60a610f3352ca3825b9b3811aedcc9c9224fc92 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 20 Oct 2020 00:32:07 +0200 Subject: [PATCH 1118/1751] DPL Analysis: initial attempt at rate limiting --- .../include/Framework/DeviceMetricsInfo.h | 1 + .../Core/include/Framework/ServiceSpec.h | 9 +- Framework/Core/src/CommonMessageBackends.cxx | 120 +++++++++++++- Framework/Core/src/DataProcessor.cxx | 6 +- Framework/Core/src/DeviceMetricsInfo.cxx | 1 - Framework/Core/src/DriverInfo.h | 3 + Framework/Core/src/FrameworkGUIDebugger.cxx | 152 +++++++++--------- Framework/Core/src/WorkflowHelpers.cxx | 2 +- Framework/Core/src/runDataProcessing.cxx | 75 +++++++-- Framework/Core/test/test_WorkflowHelpers.cxx | 1 + 10 files changed, 271 insertions(+), 99 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceMetricsInfo.h b/Framework/Core/include/Framework/DeviceMetricsInfo.h index b314c62707494..439537083e373 100644 --- a/Framework/Core/include/Framework/DeviceMetricsInfo.h +++ b/Framework/Core/include/Framework/DeviceMetricsInfo.h @@ -103,6 +103,7 @@ struct DeviceMetricsHelper { static bool processMetric(ParsedMetricMatch& results, DeviceMetricsInfo& info, NewMetricCallback newMetricCallback = nullptr); + /// @return the index in metrics for the information of given metric static size_t metricIdxByName(const std::string& name, const DeviceMetricsInfo& info); diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index e7dce7623f2d3..73f107a11065d 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -11,6 +11,8 @@ #define O2_FRAMEWORK_SERVICESPEC_H_ #include "Framework/ServiceHandle.h" +#include "Framework/DeviceMetricsInfo.h" +#include "Framework/DeviceInfo.h" #include <functional> #include <string> #include <vector> @@ -64,7 +66,12 @@ using ServicePostForkChild = std::function<void(ServiceRegistry&)>; using ServicePostForkParent = std::function<void(ServiceRegistry&)>; /// Callback executed in the driver in order to process a metric. -using ServiceMetricHandling = std::function<void(ServiceRegistry&)>; +using ServiceMetricHandling = std::function<void(ServiceRegistry&, + std::vector<o2::framework::DeviceMetricsInfo>& metrics, + std::vector<o2::framework::DeviceSpec>& specs, + std::vector<o2::framework::DeviceInfo>& infos, + DeviceMetricsInfo& driverMetrics, + size_t timestamp)>; /// Callback executed in the child after dispatching happened. using ServicePostDispatching = std::function<void(ProcessingContext&, void*)>; diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index 968facc299a5a..d8ddeee713f46 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -18,12 +18,17 @@ #include "Framework/DeviceSpec.h" #include "Framework/EndOfStreamContext.h" #include "Framework/Tracing.h" +#include "Framework/DeviceMetricsInfo.h" +#include "Framework/DeviceInfo.h" #include <Monitoring/Monitoring.h> #include <Headers/DataHeader.h> #include <options/FairMQProgOptions.h> +#include <uv.h> +#include <csignal> + namespace o2::framework { @@ -98,10 +103,102 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() nullptr, nullptr, nullptr, - nullptr, + [](ServiceRegistry& registry, + std::vector<DeviceMetricsInfo>& allDeviceMetrics, + std::vector<DeviceSpec>& specs, + std::vector<DeviceInfo>& infos, + DeviceMetricsInfo& driverMetrics, + size_t timestamp) { + int64_t totalBytesCreated = 0; + int64_t totalBytesDestroyed = 0; + int64_t totalMessagesCreated = 0; + int64_t totalMessagesDestroyed = 0; + static bool wasChanged = false; + static auto totalBytesCreatedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-bytes-created"); + static auto totalBytesDestroyedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-bytes-destroyed"); + static auto totalMessagesCreatedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-messages-created"); + static auto totalMessagesDestroyedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-messages-destroyed"); + static auto totalBytesDeltaMetric = DeviceMetricsHelper::createNumericMetric<int>(driverMetrics, "arrow-bytes-delta"); + static auto totalSignalsMetric = DeviceMetricsHelper::createNumericMetric<int>(driverMetrics, "aod-reader-signals"); + + bool changed = false; + for (auto& deviceMetrics : allDeviceMetrics) { + { + size_t index = DeviceMetricsHelper::metricIdxByName("arrow-bytes-created", deviceMetrics); + if (index < deviceMetrics.metrics.size()) { + changed |= deviceMetrics.changed.at(index); + MetricInfo info = deviceMetrics.metrics.at(index); + auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); + totalBytesCreated += (int64_t)data.at((info.pos - 1) % data.size()); + } + } + { + size_t index = DeviceMetricsHelper::metricIdxByName("arrow-bytes-destroyed", deviceMetrics); + if (index < deviceMetrics.metrics.size()) { + changed |= deviceMetrics.changed.at(index); + MetricInfo info = deviceMetrics.metrics.at(index); + auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); + totalBytesDestroyed += (int64_t)data.at((info.pos - 1) % data.size()); + } + } + { + size_t index = DeviceMetricsHelper::metricIdxByName("arrow-messages-created", deviceMetrics); + if (index < deviceMetrics.metrics.size()) { + changed |= deviceMetrics.changed.at(index); + MetricInfo info = deviceMetrics.metrics.at(index); + auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); + totalMessagesCreated += (int64_t)data.at((info.pos - 1) % data.size()); + } + } + { + size_t index = DeviceMetricsHelper::metricIdxByName("arrow-messages-destroyed", deviceMetrics); + if (index < deviceMetrics.metrics.size()) { + changed |= deviceMetrics.changed.at(index); + MetricInfo info = deviceMetrics.metrics.at(index); + auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); + totalMessagesDestroyed += (int64_t)data.at((info.pos - 1) % data.size()); + } + } + } + if (changed) { + totalBytesCreatedMetric(driverMetrics, totalBytesCreated, timestamp); + totalBytesDestroyedMetric(driverMetrics, totalBytesDestroyed, timestamp); + totalMessagesCreatedMetric(driverMetrics, totalMessagesCreated, timestamp); + totalMessagesDestroyedMetric(driverMetrics, totalMessagesDestroyed, timestamp); + totalBytesDeltaMetric(driverMetrics, totalBytesCreated - totalBytesDestroyed, timestamp); + } + // Only when the metric stabilises... + if (changed) { + /// Trigger next timeframe only when we have more than 1GB in memory available. + if (totalBytesCreated <= (totalBytesDestroyed + 100000000)) { + for (size_t di = 0; di < specs.size(); ++di) { + if (specs[di].name == "internal-dpl-aod-reader") { + if (di < infos.size()) { + kill(infos[di].pid, SIGUSR1); + totalSignalsMetric(driverMetrics, 1, timestamp); + } + } + } + } + } else if (wasChanged == changed) { + if (totalBytesCreated < totalBytesDestroyed) { + for (size_t di = 0; di < specs.size(); ++di) { + if (specs[di].name == "internal-dpl-aod-reader") { + if (di < infos.size()) { + kill(infos[di].pid, SIGUSR1); + totalSignalsMetric(driverMetrics, 1, timestamp); + } + } + } + } + } + wasChanged = changed; + }, [](ProcessingContext& ctx, void* service) { using DataHeader = o2::header::DataHeader; ArrowContext* arrow = reinterpret_cast<ArrowContext*>(service); + auto totalBytes = 0; + auto totalMessages = 0; for (auto& input : ctx.inputs()) { if (input.header == nullptr) { continue; @@ -111,16 +208,25 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() continue; } auto dph = o2::header::get<DataProcessingHeader*>(input.header); + bool forwarded = false; for (auto const& forward : ctx.services().get<DeviceSpec const>().forwards) { - if (DataSpecUtils::match(forward.matcher, dh->dataOrigin, dh->dataDescription, dh->subSpecification) == true && (dph->startTime % forward.maxTimeslices) == forward.timeslice) { - continue; + if (DataSpecUtils::match(forward.matcher, dh->dataOrigin, dh->dataDescription, dh->subSpecification)) { + forwarded = true; + break; } } - arrow->updateBytesDestroyed(dh->payloadSize); - arrow->updateMessagesDestroyed(1); + if (forwarded) { + continue; + } + totalBytes += dh->payloadSize; + totalMessages += 1; } - ctx.services().get<Monitoring>().send(Metric{(uint64_t)arrow->bytesDestroyed(), "arrow-bytes-destroyed"}.addTag(Key::Subsystem, Value::DPL)); - ctx.services().get<Monitoring>().send(Metric{(uint64_t)arrow->messagesDestroyed(), "arrow-messages-destroyed"}.addTag(Key::Subsystem, Value::DPL)); + arrow->updateBytesDestroyed(totalBytes); + arrow->updateMessagesDestroyed(totalMessages); + auto& monitoring = ctx.services().get<Monitoring>(); + monitoring.send(Metric{(uint64_t)arrow->bytesDestroyed(), "arrow-bytes-destroyed"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(uint64_t)arrow->messagesDestroyed(), "arrow-messages-destroyed"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.flushBuffer(); }, ServiceKind::Serial}; } diff --git a/Framework/Core/src/DataProcessor.cxx b/Framework/Core/src/DataProcessor.cxx index c26e5e89251f7..35a4ce1d12cbd 100644 --- a/Framework/Core/src/DataProcessor.cxx +++ b/Framework/Core/src/DataProcessor.cxx @@ -97,12 +97,14 @@ void DataProcessor::doSend(FairMQDevice& device, ArrowContext& context, ServiceR dh->serialization = o2::header::gSerializationMethodArrow; context.updateBytesSent(payload->GetSize()); context.updateMessagesSent(1); - registry.get<Monitoring>().send(Metric{(uint64_t)context.bytesSent(), "arrow-bytes-created"}.addTag(Key::Subsystem, Value::DPL)); - registry.get<Monitoring>().send(Metric{(uint64_t)context.messagesCreated(), "arrow-messages-created"}.addTag(Key::Subsystem, Value::DPL)); parts.AddPart(std::move(messageRef.header)); parts.AddPart(std::move(payload)); device.Send(parts, messageRef.channel, 0); } + auto& monitoring = registry.get<Monitoring>(); + monitoring.send(Metric{(uint64_t)context.bytesSent(), "arrow-bytes-created"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(uint64_t)context.messagesCreated(), "arrow-messages-created"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.flushBuffer(); } void DataProcessor::doSend(FairMQDevice& device, RawBufferContext& context, ServiceRegistry& registry) diff --git a/Framework/Core/src/DeviceMetricsInfo.cxx b/Framework/Core/src/DeviceMetricsInfo.cxx index 25fc36e0602ef..7b4c467fdadbd 100644 --- a/Framework/Core/src/DeviceMetricsInfo.cxx +++ b/Framework/Core/src/DeviceMetricsInfo.cxx @@ -261,7 +261,6 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, return true; } -/// @return the index in metrics for the information of given metric size_t DeviceMetricsHelper::metricIdxByName(const std::string& name, const DeviceMetricsInfo& info) { diff --git a/Framework/Core/src/DriverInfo.h b/Framework/Core/src/DriverInfo.h index 494e5604e6f90..972012ce19838 100644 --- a/Framework/Core/src/DriverInfo.h +++ b/Framework/Core/src/DriverInfo.h @@ -22,6 +22,7 @@ #include "Framework/TerminationPolicy.h" #include "Framework/CompletionPolicy.h" #include "Framework/DispatchPolicy.h" +#include "Framework/DeviceMetricsInfo.h" #include "DataProcessorInfo.h" namespace o2::framework @@ -135,6 +136,8 @@ struct DriverInfo { unsigned short resourcesMonitoringInterval; /// Last port used for tracy short tracyPort = 8086; + /// Aggregate metrics calculated in the driver itself + DeviceMetricsInfo metrics; }; } // namespace o2::framework diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/Core/src/FrameworkGUIDebugger.cxx index 077b461c39504..65930fec30746 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/Core/src/FrameworkGUIDebugger.cxx @@ -16,6 +16,7 @@ #include "Framework/ConfigContext.h" #include "Framework/ConfigParamRegistry.h" #include "DebugGUI/imgui.h" +#include "DebugGUI/implot.h" #include "DebugGUI/imgui_extras.h" #include "DriverControl.cxx" #include "DriverInfo.cxx" @@ -172,22 +173,15 @@ enum struct MetricsDisplayStyle : int { Table = 3 }; -void displayDeviceMetrics(const char* label, ImVec2 canvasSize, std::string const& selectedMetricName, +void displayDeviceMetrics(const char* label, std::string const& selectedMetricName, size_t rangeBegin, size_t rangeEnd, size_t bins, MetricsDisplayStyle displayType, - std::vector<DeviceSpec> const& specs, std::vector<DeviceMetricsInfo> const& metricsInfos) + std::vector<DeviceSpec> const& specs, + std::vector<DeviceMetricsInfo> const& metricsInfos, + DeviceMetricsInfo const& driverMetric) { - static std::vector<ImColor> palette = { - ImColor{218, 124, 48}, - ImColor{62, 150, 81}, - ImColor{204, 37, 41}, - ImColor{83, 81, 84}, - ImColor{107, 76, 154}, - ImColor{146, 36, 40}, - ImColor{148, 139, 61}}; - std::vector<void const*> metricsToDisplay; + std::vector<void*> metricsToDisplay; std::vector<const char*> deviceNames; std::vector<MultiplotData> userData; - std::vector<ImColor> colors; MetricType metricType; size_t metricSize = 0; assert(specs.size() == metricsInfos.size()); @@ -203,7 +197,6 @@ void displayDeviceMetrics(const char* label, ImVec2 canvasSize, std::string cons } auto& metric = metricsInfos[mi].metrics[vi]; deviceNames.push_back(specs[mi].name.c_str()); - colors.push_back(palette[mi % palette.size()]); metricType = metric.type; MultiplotData data; data.mod = metricsInfos[mi].timestamps[vi].size(); @@ -213,27 +206,20 @@ void displayDeviceMetrics(const char* label, ImVec2 canvasSize, std::string cons maxValue = std::max(maxValue, metricsInfos[mi].max[vi]); minDomain = std::min(minDomain, metricsInfos[mi].minDomain[vi]); maxDomain = std::max(maxDomain, metricsInfos[mi].maxDomain[vi]); + metricType = metric.type; + data.type = metric.type; switch (metric.type) { case MetricType::Int: { data.size = metricsInfos[mi].intMetrics[metric.storeIdx].size(); data.Y = metricsInfos[mi].intMetrics[metric.storeIdx].data(); - data.type = MetricType::Int; - metricType = MetricType::Int; - metricSize = metricsInfos[mi].intMetrics[metric.storeIdx].size(); } break; case MetricType::Uint64: { data.size = metricsInfos[mi].uint64Metrics[metric.storeIdx].size(); data.Y = metricsInfos[mi].uint64Metrics[metric.storeIdx].data(); - data.type = MetricType::Uint64; - metricType = MetricType::Uint64; - metricSize = metricsInfos[mi].uint64Metrics[metric.storeIdx].size(); } break; case MetricType::Float: { data.size = metricsInfos[mi].floatMetrics[metric.storeIdx].size(); data.Y = metricsInfos[mi].floatMetrics[metric.storeIdx].data(); - data.type = MetricType::Float; - metricType = MetricType::Float; - metricSize = metricsInfos[mi].floatMetrics[metric.storeIdx].size(); } break; case MetricType::Unknown: case MetricType::String: { @@ -241,71 +227,96 @@ void displayDeviceMetrics(const char* label, ImVec2 canvasSize, std::string cons data.Y = nullptr; data.type = MetricType::String; metricType = MetricType::String; - metricSize = metricsInfos[mi].stringMetrics[metric.storeIdx].size(); } break; } + metricSize = data.size; userData.emplace_back(data); } + if (true) { + auto vi = DeviceMetricsHelper::metricIdxByName(selectedMetricName, driverMetric); + if (vi < driverMetric.metricLabelsIdx.size()) { + auto& metric = driverMetric.metrics[vi]; + deviceNames.push_back("driver"); + metricType = metric.type; + MultiplotData data; + data.mod = driverMetric.timestamps[vi].size(); + data.first = metric.pos - data.mod; + data.X = driverMetric.timestamps[vi].data(); + minValue = std::min(minValue, driverMetric.min[vi]); + maxValue = std::max(maxValue, driverMetric.max[vi]); + minDomain = std::min(minDomain, driverMetric.minDomain[vi]); + maxDomain = std::max(maxDomain, driverMetric.maxDomain[vi]); + metricType = metric.type; + data.type = metric.type; + switch (metric.type) { + case MetricType::Int: { + data.size = driverMetric.intMetrics[metric.storeIdx].size(); + data.Y = driverMetric.intMetrics[metric.storeIdx].data(); + } break; + case MetricType::Uint64: { + data.size = driverMetric.uint64Metrics[metric.storeIdx].size(); + data.Y = driverMetric.uint64Metrics[metric.storeIdx].data(); + } break; + case MetricType::Float: { + data.size = driverMetric.floatMetrics[metric.storeIdx].size(); + data.Y = driverMetric.floatMetrics[metric.storeIdx].data(); + } break; + case MetricType::Unknown: + case MetricType::String: { + data.size = driverMetric.stringMetrics[metric.storeIdx].size(); + data.Y = nullptr; + data.type = MetricType::String; + metricType = MetricType::String; + } break; + } + metricSize = data.size; + userData.emplace_back(data); + } + } maxDomain = std::max(minDomain + 1024, maxDomain); for (size_t ui = 0; ui < userData.size(); ++ui) { metricsToDisplay.push_back(&(userData[ui])); } - auto getterY = [](const void* hData, int idx) -> float { + auto getterXY = [](void* hData, int idx) -> ImPlotPoint { auto histoData = reinterpret_cast<const MultiplotData*>(hData); size_t pos = (histoData->first + static_cast<size_t>(idx)) % histoData->mod; - // size_t pos = (static_cast<size_t>(idx)) % histoData->mod; - assert(pos >= 0 && pos < 1024); + double x = static_cast<const size_t*>(histoData->X)[pos]; + double y = 0.; if (histoData->type == MetricType::Int) { - return static_cast<const int*>(histoData->Y)[pos]; + y = static_cast<const int*>(histoData->Y)[pos]; } else if (histoData->type == MetricType::Uint64) { - return static_cast<const uint64_t*>(histoData->Y)[pos]; + y = static_cast<const uint64_t*>(histoData->Y)[pos]; } else if (histoData->type == MetricType::Float) { - return static_cast<const float*>(histoData->Y)[pos]; - } else { - return 0; + y = static_cast<const float*>(histoData->Y)[pos]; } + return ImPlotPoint{x, y}; }; - auto getterX = [](const void* hData, int idx) -> size_t { - auto histoData = reinterpret_cast<const MultiplotData*>(hData); - size_t pos = (histoData->first + static_cast<size_t>(idx)) % histoData->mod; - //size_t pos = (static_cast<size_t>(idx)) % histoData->mod; - assert(pos >= 0 && pos < 1024); - return static_cast<const size_t*>(histoData->X)[pos]; - }; + switch (displayType) { case MetricsDisplayStyle::Histos: - ImGui::PlotMultiHistograms( - label, - userData.size(), - deviceNames.data(), - colors.data(), - getterY, - getterX, - metricsToDisplay.data(), - metricSize, - minValue, - maxValue * 1.2f, - minDomain, - maxDomain, - canvasSize); + ImPlot::SetNextPlotLimitsX(minDomain, maxDomain, ImGuiCond_Once); + ImPlot::SetNextPlotLimitsY(minValue, maxValue, ImGuiCond_Always); + ImPlot::SetNextPlotTicksX(minDomain, maxDomain, 5); + if (ImPlot::BeginPlot(selectedMetricName.c_str(), "time", "value")) { + for (size_t pi = 0; pi < metricsToDisplay.size(); ++pi) { + ImPlot::PlotBarsG(deviceNames[pi], getterXY, metricsToDisplay[pi], metricSize, 1, 0); + } + ImPlot::EndPlot(); + } + break; case MetricsDisplayStyle::Lines: - ImGui::PlotMultiLines( - label, - userData.size(), - deviceNames.data(), - colors.data(), - getterY, - getterX, - metricsToDisplay.data(), - metricSize, - minValue, - maxValue * 1.2f, - minDomain, - maxDomain, - canvasSize); + ImPlot::SetNextPlotLimitsX(minDomain, maxDomain, ImGuiCond_Once); + ImPlot::SetNextPlotLimitsY(minValue, maxValue * 1.2, ImGuiCond_Always); + ImPlot::SetNextPlotTicksX(minDomain, maxDomain, 5); + if (ImPlot::BeginPlot("##Some plot", "time", "value")) { + for (size_t pi = 0; pi < metricsToDisplay.size(); ++pi) { + ImPlot::PlotLineG(deviceNames[pi], getterXY, metricsToDisplay[pi], metricSize, 0); + } + ImPlot::EndPlot(); + } break; default: break; @@ -546,17 +557,14 @@ void displayDeviceHistograms(gui::WorkspaceGUIState& state, maxTime = maxTime > curMaxTime ? maxTime : curMaxTime; } } - if (minTime != -1) { - ImGui::Text("min timestamp: %zu, max timestamp: %zu", minTime, maxTime); - } ImGui::EndGroup(); if (!currentMetricName.empty()) { switch (currentStyle) { case MetricsDisplayStyle::Histos: case MetricsDisplayStyle::Lines: { displayDeviceMetrics("Metrics", - ImVec2(ImGui::GetIO().DisplaySize.x - 10, state.bottomPaneSize - ImGui::GetItemRectSize().y - 20), currentMetricName, minTime, maxTime, 1024, - currentStyle, devices, metricsInfos); + currentMetricName, minTime, maxTime, 1024, + currentStyle, devices, metricsInfos, driverInfo.metrics); } break; case MetricsDisplayStyle::Sparks: { #if defined(ImGuiCol_ChildWindowBg) @@ -736,7 +744,7 @@ std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos, gui::DeviceGUIState& state = guiState.devices[i]; state.label = devices[i].id + "(" + std::to_string(infos[i].pid) + ")"; } - guiState.bottomPaneSize = 300; + guiState.bottomPaneSize = 340; guiState.leftPaneSize = 200; guiState.rightPaneSize = 300; diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 894bf015be996..613cc60a879c6 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -240,7 +240,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext {InputSpec{"enumeration", "DPL", "ENUM", - static_cast<DataAllocator::SubSpecificationType>(compile_time_hash("internal-dpl-aod-reader")), Lifetime::Enumeration}}, + static_cast<DataAllocator::SubSpecificationType>(compile_time_hash("internal-dpl-aod-reader")), Lifetime::Signal}}, {}, readers::AODReaderHelpers::rootFileReaderCallback(), {ConfigParamSpec{"aod-file", VariantType::String, {"Input AOD file"}}, diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index cc372acf36578..dde2b01a293b6 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -183,6 +183,23 @@ std::ostream& operator<<(std::ostream& out, const enum TerminationPolicy& policy } // namespace framework } // namespace o2 +size_t current_time_with_ms() +{ + long ms; // Milliseconds + time_t s; // Seconds + struct timespec spec; + + clock_gettime(CLOCK_REALTIME, &spec); + + s = spec.tv_sec; + ms = round(spec.tv_nsec / 1.0e6); // Convert nanoseconds to milliseconds + if (ms > 999) { + s++; + ms = 0; + } + return s * 1000 + ms; +} + // Read from a given fd and print it. // return true if we can still read from it, // return false if we need to close the input pipe. @@ -538,7 +555,7 @@ void spawnDevice(std::string const& forwardedStdin, addPoller(deviceInfos.size() - 1, childstderr[0]); } -void updateMetricsNames(DriverInfo& state, std::vector<DeviceMetricsInfo> const& metricsInfos) +void updateMetricsNames(DriverInfo& driverInfo, std::vector<DeviceMetricsInfo> const& metricsInfos) { // Calculate the unique set of metrics, as available in the metrics service static std::unordered_set<std::string> allMetricsNames; @@ -547,13 +564,27 @@ void updateMetricsNames(DriverInfo& state, std::vector<DeviceMetricsInfo> const& allMetricsNames.insert(std::string(labelsPairs.label)); } } + for (const auto& labelsPairs : driverInfo.metrics.metricLabelsIdx) { + allMetricsNames.insert(std::string(labelsPairs.label)); + } std::vector<std::string> result(allMetricsNames.begin(), allMetricsNames.end()); std::sort(result.begin(), result.end()); - state.availableMetrics.swap(result); + driverInfo.availableMetrics.swap(result); } -void processChildrenOutput(DriverInfo& driverInfo, DeviceInfos& infos, DeviceSpecs const& specs, - DeviceControls& controls, std::vector<DeviceMetricsInfo>& metricsInfos) +struct LogProcessingState { + bool didProcessLog = false; + bool didProcessControl = true; + bool didProcessConfig = true; + bool didProcessMetric = false; + bool hasNewMetric = false; +}; + +LogProcessingState processChildrenOutput(DriverInfo& driverInfo, + DeviceInfos& infos, + DeviceSpecs const& specs, + DeviceControls& controls, + std::vector<DeviceMetricsInfo>& metricsInfos) { // Display part. All you need to display should actually be in // `infos`. @@ -568,6 +599,8 @@ void processChildrenOutput(DriverInfo& driverInfo, DeviceInfos& infos, DeviceSpe ParsedConfigMatch configMatch; const std::string delimiter("\n"); bool hasNewMetric = false; + LogProcessingState result; + for (size_t di = 0, de = infos.size(); di < de; ++di) { DeviceInfo& info = infos[di]; DeviceControl& control = controls[di]; @@ -618,6 +651,7 @@ void processChildrenOutput(DriverInfo& driverInfo, DeviceInfos& infos, DeviceSpe // We use this callback to cache which metrics are needed to provide a // the DataRelayer view. DeviceMetricsHelper::processMetric(metricMatch, metrics, newMetricCallback); + result.didProcessMetric = true; } else if (logLevel == LogParsingHelpers::LogLevel::Info && parseControl(token, match)) { auto command = match[1]; auto arg = match[2]; @@ -638,8 +672,10 @@ void processChildrenOutput(DriverInfo& driverInfo, DeviceInfos& infos, DeviceSpe // FIXME: this should really be a policy... doToMatchingPid(info.pid, [](DeviceInfo& info) { info.streamingState = StreamingState::EndOfStreaming; }); } + result.didProcessControl = true; } else if (logLevel == LogParsingHelpers::LogLevel::Info && DeviceConfigHelper::parseConfig(token, configMatch)) { DeviceConfigHelper::processConfig(configMatch, info); + result.didProcessConfig = true; } else if (!control.quiet && (token.find(control.logFilter) != std::string::npos) && logLevel >= control.logLevel) { assert(info.historyPos >= 0); @@ -648,6 +684,7 @@ void processChildrenOutput(DriverInfo& driverInfo, DeviceInfos& infos, DeviceSpe info.historyLevel[info.historyPos] = logLevel; info.historyPos = (info.historyPos + 1) % info.history.size(); std::cout << "[" << info.pid << ":" << spec.name << "]: " << token << std::endl; + result.didProcessLog = true; } // We keep track of the maximum log error a // device has seen. @@ -664,13 +701,12 @@ void processChildrenOutput(DriverInfo& driverInfo, DeviceInfos& infos, DeviceSpe info.unprinted = std::string(s); O2_SIGNPOST_END(DriverStatus::ID, DriverStatus::BYTES_PROCESSED, oldSize - info.unprinted.size(), 0, 0); } + result.hasNewMetric = hasNewMetric; if (hasNewMetric) { hasNewMetric = false; updateMetricsNames(driverInfo, metricsInfos); } - // FIXME: for the gui to work correctly I would actually need to - // run the loop more often and update whenever enough time has - // passed. + return result; } // Process all the sigchld which are pending @@ -1121,9 +1157,15 @@ int runStateMachine(DataProcessorSpecs const& workflow, { uint64_t inputProcessingStart = uv_hrtime(); auto inputProcessingLatency = inputProcessingStart - inputProcessingLast; - processChildrenOutput(driverInfo, infos, deviceSpecs, controls, metricsInfos); - for (auto& callback : metricProcessingCallbacks) { - callback(serviceRegistry); + auto outputProcessing = processChildrenOutput(driverInfo, infos, deviceSpecs, controls, metricsInfos); + if (outputProcessing.didProcessMetric) { + size_t timestamp = current_time_with_ms(); + for (auto& callback : metricProcessingCallbacks) { + callback(serviceRegistry, metricsInfos, deviceSpecs, infos, driverInfo.metrics, timestamp); + } + for (auto& metricsInfo : metricsInfos) { + std::fill(metricsInfo.changed.begin(), metricsInfo.changed.end(), false); + } } auto inputProcessingEnd = uv_hrtime(); driverInfo.inputProcessingCost = (inputProcessingEnd - inputProcessingStart) / 1000000; @@ -1144,7 +1186,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, uv_timer_start(&force_step_timer, single_step_callback, 0, 300); driverInfo.states.push_back(DriverState::HANDLE_CHILDREN); break; - case DriverState::HANDLE_CHILDREN: + case DriverState::HANDLE_CHILDREN: { // Run any pending libUV event loop, block if // any, so that we do not consume CPU time when the driver is // idle. @@ -1162,9 +1204,12 @@ int runStateMachine(DataProcessorSpecs const& workflow, } sigchld_requested = false; driverInfo.sigchldRequested = false; - processChildrenOutput(driverInfo, infos, deviceSpecs, controls, metricsInfos); - for (auto& callback : metricProcessingCallbacks) { - callback(serviceRegistry); + auto outputProcessing = processChildrenOutput(driverInfo, infos, deviceSpecs, controls, metricsInfos); + if (outputProcessing.didProcessMetric) { + size_t timestamp = current_time_with_ms(); + for (auto& callback : metricProcessingCallbacks) { + callback(serviceRegistry, metricsInfos, deviceSpecs, infos, driverInfo.metrics, timestamp); + } } hasError = processSigChild(infos); if (areAllChildrenGone(infos) == true && @@ -1181,7 +1226,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, driverInfo.states.push_back(DriverState::QUIT_REQUESTED); } else { } - break; + } break; case DriverState::EXIT: { if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(driverInfo.resourcesMonitoringInterval)) { LOG(INFO) << "Dumping performance metrics to performanceMetrics.json file"; diff --git a/Framework/Core/test/test_WorkflowHelpers.cxx b/Framework/Core/test/test_WorkflowHelpers.cxx index 27b52cd1667f4..b3ccd86aac17b 100644 --- a/Framework/Core/test/test_WorkflowHelpers.cxx +++ b/Framework/Core/test/test_WorkflowHelpers.cxx @@ -31,6 +31,7 @@ std::unique_ptr<ConfigContext> makeEmptyConfigContext() std::vector<std::unique_ptr<ParamRetriever>> retrievers; static std::vector<ConfigParamSpec> specs; specs.push_back(ConfigParamSpec{"dangling-outputs-policy", VariantType::String, "file", {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}); + specs.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::String, "0", {"rate"}}); auto store = std::make_unique<ConfigParamStore>(specs, std::move(retrievers)); store->preload(); store->activate(); From e94fe5f012e66078bbffc80eb8d05b87cf1d0529 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 26 Oct 2020 12:56:39 +0100 Subject: [PATCH 1119/1751] DPL: add support for pre-schedule / post-schedule services --- .../Core/include/Framework/ServiceSpec.h | 10 +++++++ Framework/Core/src/CommonMessageBackends.cxx | 9 +++++++ Framework/Core/src/CommonServices.cxx | 26 +++++++++++++++++++ Framework/Core/src/runDataProcessing.cxx | 25 ++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index 73f107a11065d..e4f80382edc9a 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -65,6 +65,12 @@ using ServicePostForkChild = std::function<void(ServiceRegistry&)>; /// but before doing exec / starting the device. using ServicePostForkParent = std::function<void(ServiceRegistry&)>; +/// Callback executed before each redeployment of the whole configuration +using ServicePreSchedule = std::function<void(ServiceRegistry&, boost::program_options::variables_map const&)>; + +/// Callback executed after each redeployment of the whole configuration +using ServicePostSchedule = std::function<void(ServiceRegistry&, boost::program_options::variables_map const&)>; + /// Callback executed in the driver in order to process a metric. using ServiceMetricHandling = std::function<void(ServiceRegistry&, std::vector<o2::framework::DeviceMetricsInfo>& metrics, @@ -112,6 +118,10 @@ struct ServiceSpec { /// but before doing exec / starting the device. ServicePostForkParent postForkParent = nullptr; + /// Callback executed before and after we schedule a topology + ServicePreSchedule preSchedule = nullptr; + ServicePostSchedule postSchedule = nullptr; + ///Callback executed after each metric is received by the driver. ServiceMetricHandling metricHandling = nullptr; diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index d8ddeee713f46..19863ce4375f9 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -27,6 +27,7 @@ #include <options/FairMQProgOptions.h> #include <uv.h> +#include <boost/program_options/variables_map.hpp> #include <csignal> namespace o2::framework @@ -103,6 +104,8 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, [](ServiceRegistry& registry, std::vector<DeviceMetricsInfo>& allDeviceMetrics, std::vector<DeviceSpec>& specs, @@ -267,6 +270,8 @@ o2::framework::ServiceSpec CommonMessageBackends::fairMQBackendSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -286,6 +291,8 @@ o2::framework::ServiceSpec CommonMessageBackends::stringBackendSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -305,6 +312,8 @@ o2::framework::ServiceSpec CommonMessageBackends::rawBufferBackendSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index cac9a6fdfeb91..f92114b1de2bd 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -72,6 +72,8 @@ o2::framework::ServiceSpec CommonServices::monitoringSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -91,6 +93,8 @@ o2::framework::ServiceSpec CommonServices::infologgerContextSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -178,6 +182,8 @@ o2::framework::ServiceSpec CommonServices::infologgerSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -205,6 +211,8 @@ o2::framework::ServiceSpec CommonServices::configurationSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Global}; } @@ -228,6 +236,8 @@ o2::framework::ServiceSpec CommonServices::controlSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -248,6 +258,8 @@ o2::framework::ServiceSpec CommonServices::rootFileSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -272,6 +284,8 @@ o2::framework::ServiceSpec CommonServices::parallelSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -292,6 +306,8 @@ o2::framework::ServiceSpec CommonServices::timesliceIndex() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -312,6 +328,8 @@ o2::framework::ServiceSpec CommonServices::callbacksSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -339,6 +357,8 @@ o2::framework::ServiceSpec CommonServices::dataRelayer() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -371,6 +391,8 @@ o2::framework::ServiceSpec CommonServices::tracingSpec() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -406,6 +428,8 @@ o2::framework::ServiceSpec CommonServices::threadPool(int numWorkers) }, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } @@ -507,6 +531,8 @@ o2::framework::ServiceSpec CommonServices::dataProcessingStats() nullptr, nullptr, nullptr, + nullptr, + nullptr, ServiceKind::Serial}; } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index dde2b01a293b6..1fe3955a5fe70 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -920,6 +920,8 @@ int runStateMachine(DataProcessorSpecs const& workflow, // different versions of the service ServiceRegistry serviceRegistry; std::vector<ServiceMetricHandling> metricProcessingCallbacks; + std::vector<ServicePreSchedule> preScheduleCallbacks; + std::vector<ServicePostSchedule> postScheduleCallbacks; while (true) { // If control forced some transition on us, we push it to the queue. @@ -1031,6 +1033,23 @@ int runStateMachine(DataProcessorSpecs const& workflow, } } } + preScheduleCallbacks.clear(); + for (auto& device : deviceSpecs) { + for (auto& service : device.services) { + if (service.preSchedule) { + preScheduleCallbacks.push_back(service.preSchedule); + } + } + } + postScheduleCallbacks.clear(); + for (auto& device : deviceSpecs) { + for (auto& service : device.services) { + if (service.postSchedule) { + postScheduleCallbacks.push_back(service.postSchedule); + } + } + } + // This should expand nodes so that we can build a consistent DAG. } catch (std::runtime_error& e) { std::cerr << "Invalid workflow: " << e.what() << std::endl; @@ -1110,6 +1129,9 @@ int runStateMachine(DataProcessorSpecs const& workflow, #elif __has_include(<cpuid.h>) GETCPU(parentCPU); #endif + for (auto& callback : preScheduleCallbacks) { + callback(serviceRegistry, varmap); + } for (size_t di = 0; di < deviceSpecs.size(); ++di) { if (deviceSpecs[di].resource.hostname != driverInfo.deployHostname) { spawnRemoteDevice(forwardedStdin.str(), @@ -1121,6 +1143,9 @@ int runStateMachine(DataProcessorSpecs const& workflow, serviceRegistry, varmap, loop, pollHandles, parentCPU, parentNode); } } + for (auto& callback : postScheduleCallbacks) { + callback(serviceRegistry, varmap); + } assert(infos.empty() == false); LOG(INFO) << "Redeployment of configuration done."; } break; From e7f4ed93d9650d977e3ed111fa78437dc4d78742 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 26 Oct 2020 12:58:05 +0100 Subject: [PATCH 1120/1751] Make rate-limit-configurable --- .../Core/include/Framework/ArrowContext.h | 1 + .../include/Framework/CommonMessageBackends.h | 2 + .../include/Framework/runDataProcessing.h | 3 + Framework/Core/src/CommonMessageBackends.cxx | 70 ++++++++++++++----- Framework/Core/src/WorkflowHelpers.cxx | 16 ++++- 5 files changed, 72 insertions(+), 20 deletions(-) diff --git a/Framework/Core/include/Framework/ArrowContext.h b/Framework/Core/include/Framework/ArrowContext.h index 0c9d4e5cdce43..4fc2f1e320462 100644 --- a/Framework/Core/include/Framework/ArrowContext.h +++ b/Framework/Core/include/Framework/ArrowContext.h @@ -137,6 +137,7 @@ class ArrowContext size_t mBytesDestroyed = 0; size_t mMessagesCreated = 0; size_t mMessagesDestroyed = 0; + size_t mRateLimit = 0; }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/CommonMessageBackends.h b/Framework/Core/include/Framework/CommonMessageBackends.h index 0348807ea737c..048e2ef6648b4 100644 --- a/Framework/Core/include/Framework/CommonMessageBackends.h +++ b/Framework/Core/include/Framework/CommonMessageBackends.h @@ -18,6 +18,8 @@ namespace o2::framework /// A few ServiceSpecs data sending backends struct CommonMessageBackends { + // Rate limiting service + static ServiceSpec rateLimitingSpec(); // Create spec for backend used to send Arrow messages static ServiceSpec arrowBackendSpec(); static ServiceSpec fairMQBackendSpec(); diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 7c6716fba485a..2d54954f7de15 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -128,6 +128,9 @@ int main(int argc, char** argv) workflowOptions.push_back(ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}); workflowOptions.push_back(ConfigParamSpec{"dangling-outputs-policy", VariantType::String, "file", {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}); + // options for AOD rate limiting + workflowOptions.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::Int64, 0LL, {"Rate limit AOD processing based on memory"}}); + // options for AOD writer workflowOptions.push_back(ConfigParamSpec{"aod-writer-json", VariantType::String, "", {"Name of the json configuration file"}}); workflowOptions.push_back(ConfigParamSpec{"aod-writer-resfile", VariantType::String, "", {"Default name of the output file"}}); diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index 19863ce4375f9..bea3610064abf 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -85,6 +85,41 @@ struct CommonMessageBackendsHelpers { }; } // namespace +struct RateLimitConfig { + int64_t maxMemory = 0; +}; + +static int64_t memLimit = 0; + +/// Service for common handling of rate limiting +o2::framework::ServiceSpec CommonMessageBackends::rateLimitingSpec() +{ + return ServiceSpec{"aod-rate-limiting", + [](ServiceRegistry& services, DeviceState&, fair::mq::ProgOptions& options) { + return ServiceHandle{TypeIdHelpers::uniqueId<RateLimitConfig>(), new RateLimitConfig{}}; + }, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + [](ServiceRegistry& registry, boost::program_options::variables_map const& vm) { + if (!vm["aod-memory-rate-limit"].defaulted()) { + memLimit = std::stoll(vm["aod-memory-rate-limit"].as<std::string const>()); + // registry.registerService(ServiceRegistryHelpers::handleForService<RateLimitConfig>(new RateLimitConfig{memLimit})); + } + }, + nullptr, + nullptr, + nullptr, + ServiceKind::Serial}; +} + o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() { using o2::monitoring::Metric; @@ -170,26 +205,27 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() totalMessagesDestroyedMetric(driverMetrics, totalMessagesDestroyed, timestamp); totalBytesDeltaMetric(driverMetrics, totalBytesCreated - totalBytesDestroyed, timestamp); } - // Only when the metric stabilises... - if (changed) { - /// Trigger next timeframe only when we have more than 1GB in memory available. - if (totalBytesCreated <= (totalBytesDestroyed + 100000000)) { - for (size_t di = 0; di < specs.size(); ++di) { - if (specs[di].name == "internal-dpl-aod-reader") { - if (di < infos.size()) { - kill(infos[di].pid, SIGUSR1); - totalSignalsMetric(driverMetrics, 1, timestamp); + if (memLimit) { + if (changed) { + /// Trigger next timeframe only when we have more than 1GB in memory available. + if (totalBytesCreated <= (totalBytesDestroyed + memLimit)) { + for (size_t di = 0; di < specs.size(); ++di) { + if (specs[di].name == "internal-dpl-aod-reader") { + if (di < infos.size()) { + kill(infos[di].pid, SIGUSR1); + totalSignalsMetric(driverMetrics, 1, timestamp); + } } } } - } - } else if (wasChanged == changed) { - if (totalBytesCreated < totalBytesDestroyed) { - for (size_t di = 0; di < specs.size(); ++di) { - if (specs[di].name == "internal-dpl-aod-reader") { - if (di < infos.size()) { - kill(infos[di].pid, SIGUSR1); - totalSignalsMetric(driverMetrics, 1, timestamp); + } else if (wasChanged == changed) { + if (totalBytesCreated < totalBytesDestroyed) { + for (size_t di = 0; di < specs.size(); ++di) { + if (specs[di].name == "internal-dpl-aod-reader") { + if (di < infos.size()) { + kill(infos[di].pid, SIGUSR1); + totalSignalsMetric(driverMetrics, 1, timestamp); + } } } } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 613cc60a879c6..c3cf4ccb4304a 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -18,6 +18,7 @@ #include "Framework/ControlService.h" #include "Framework/RawDeviceService.h" #include "Framework/StringHelpers.h" +#include "Framework/CommonMessageBackends.h" #include "Headers/DataHeader.h" #include <algorithm> @@ -234,13 +235,21 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // reads them from file. // // FIXME: source branch is DataOrigin, for the moment. We should - // make it configurable via ConfigParamsOptions. + // make it configurable via ConfigParamsOptions + auto aodLifetime = Lifetime::Enumeration; + if (ctx.options().get<int64_t>("aod-memory-rate-limit")) { + aodLifetime = Lifetime::Signal; + } + auto readerServices = CommonServices::defaultServices(); + readerServices.push_back(CommonMessageBackends::rateLimitingSpec()); + DataProcessorSpec aodReader{ "internal-dpl-aod-reader", {InputSpec{"enumeration", "DPL", "ENUM", - static_cast<DataAllocator::SubSpecificationType>(compile_time_hash("internal-dpl-aod-reader")), Lifetime::Signal}}, + static_cast<DataAllocator::SubSpecificationType>(compile_time_hash("internal-dpl-aod-reader")), + aodLifetime}}, {}, readers::AODReaderHelpers::rootFileReaderCallback(), {ConfigParamSpec{"aod-file", VariantType::String, {"Input AOD file"}}, @@ -248,7 +257,8 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext ConfigParamSpec{"time-limit", VariantType::Int64, 0ll, {"Maximum run time limit in seconds"}}, ConfigParamSpec{"start-value-enumeration", VariantType::Int64, 0ll, {"initial value for the enumeration"}}, ConfigParamSpec{"end-value-enumeration", VariantType::Int64, -1ll, {"final value for the enumeration"}}, - ConfigParamSpec{"step-value-enumeration", VariantType::Int64, 1ll, {"step between one value and the other"}}}}; + ConfigParamSpec{"step-value-enumeration", VariantType::Int64, 1ll, {"step between one value and the other"}}}, + readerServices}; std::vector<InputSpec> requestedAODs; std::vector<OutputSpec> providedAODs; From dc9daa552d75004f1b320b1709f8ad66a90ba382 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 28 Oct 2020 01:15:58 +0100 Subject: [PATCH 1121/1751] Update test_ConfigurationOptionsRetriever.cxx --- Framework/Core/test/test_ConfigurationOptionsRetriever.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/test/test_ConfigurationOptionsRetriever.cxx b/Framework/Core/test/test_ConfigurationOptionsRetriever.cxx index d7eb05a2aef06..bba681ef59ea6 100644 --- a/Framework/Core/test/test_ConfigurationOptionsRetriever.cxx +++ b/Framework/Core/test/test_ConfigurationOptionsRetriever.cxx @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(TestOptionsRetriever) }; std::vector<std::unique_ptr<ParamRetriever>> retrievers; - std::unique_ptr<ParamRetriever> fairmqRetriver{new ConfigurationOptionsRetriever(conf.get(), ".")}; + std::unique_ptr<ParamRetriever> fairmqRetriver{new ConfigurationOptionsRetriever(conf.get(), "")}; retrievers.emplace_back(std::move(fairmqRetriver)); ConfigParamStore store{specs, std::move(retrievers)}; From a7fe3e0e0d230cce6ae925868de8dcc89978520a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 28 Oct 2020 07:57:47 +0100 Subject: [PATCH 1122/1751] DPL: fix persisting ROOT serialised options (O2-1690) (#4696) --- Framework/Core/src/DataProcessingDevice.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index fe4e17d00a155..e4d6dc467685b 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -32,6 +32,7 @@ #include "Framework/SourceInfoHeader.h" #include "Framework/Logger.h" #include "Framework/Monitoring.h" +#include "PropertyTreeHelpers.h" #include "DataProcessingStatus.h" #include "DataProcessingHelpers.h" #include "DataRelayerHelpers.h" @@ -221,9 +222,21 @@ void DataProcessingDevice::Init() auto configStore = std::move(std::make_unique<ConfigParamStore>(mSpec.options, std::move(retrievers))); configStore->preload(); configStore->activate(); + using boost::property_tree::ptree; + /// Dump the configuration so that we can get it from the driver. for (auto& entry : configStore->store()) { LOG(INFO) << "[CONFIG] " << entry.first << "=" << configStore->store().get<std::string>(entry.first) << " 1 " << configStore->provenance(entry.first.c_str()); + PropertyTreeHelpers::WalkerFunction printer = [&configStore, topLevel = entry.first](ptree const& parent, ptree::path_type childPath, ptree const& child) { + // FIXME: not clear why we get invoked for the root entry + // and twice for each node. It nevertheless works + // because the net result is that we call twice + // ptree put. + if (childPath.dump() != "") { + LOG(INFO) << "[CONFIG] " << topLevel << "." << childPath.dump() << "=" << child.data() << " 1 " << configStore->provenance(topLevel.c_str()); + } + }; + PropertyTreeHelpers::traverse(entry.second, printer); } mConfigRegistry = std::make_unique<ConfigParamRegistry>(std::move(configStore)); From 1a133216f4e8da9dbf4a64a2fd8e7abcaf156765 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 28 Oct 2020 08:55:35 +0100 Subject: [PATCH 1123/1751] Fix: libfmt does not allow non-void* ptrs, triggers assertion (#4694) --- Analysis/Tasks/PWGCF/correlations.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index 5b807bf3fe2c3..a0e9fa53322cd 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -128,11 +128,11 @@ struct CorrelationTask { if (cfgEfficiencyTrigger.value.empty() == false) { cfg.mEfficiencyTrigger = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyTrigger, now); - LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), cfg.mEfficiencyTrigger); + LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), (void*)cfg.mEfficiencyTrigger); } if (cfgEfficiencyAssociated.value.empty() == false) { cfg.mEfficiencyAssociated = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyAssociated, now); - LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), cfg.mEfficiencyAssociated); + LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), (void*)cfg.mEfficiencyAssociated); } } @@ -142,11 +142,11 @@ struct CorrelationTask { auto bc = collision.bc_as<aod::BCsWithTimestamps>(); if (cfgEfficiencyTrigger.value.empty() == false) { cfg.mEfficiencyTrigger = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyTrigger, bc.timestamp()); - LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), cfg.mEfficiencyTrigger); + LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), (void*)cfg.mEfficiencyTrigger); } if (cfgEfficiencyAssociated.value.empty() == false) { cfg.mEfficiencyAssociated = ccdb->getForTimeStamp<THnT<float>>(cfgEfficiencyAssociated, bc.timestamp()); - LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), cfg.mEfficiencyAssociated); + LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), (void*)cfg.mEfficiencyAssociated); } LOGF(info, "Tracks for collision: %d | Vertex: %.1f | INT7: %d | V0M: %.1f", tracks.size(), collision.posZ(), collision.sel7(), collision.centV0M()); From b34d66289b9b5fb506097bed16c6f8a8bb3e2879 Mon Sep 17 00:00:00 2001 From: nzardosh <nima.zardoshti@cern.ch> Date: Wed, 28 Oct 2020 08:56:48 +0100 Subject: [PATCH 1124/1751] fixing nsigma return in D0 selection (#4692) --- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index b0de359ef6fd6..ab9826ef6bf4b 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -79,8 +79,11 @@ struct HFD0CandidateSelector { int getpTBin(T candpT) { double pTBins[npTBins + 1] = {0, 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8., 9., 10., 12., 16., 20., 24., 36., 50., 100.}; + if (candpT < pTBins[0] || candpT >= pTBins[npTBins]) { + return -1; + } for (int i = 0; i < npTBins; i++) { - if (candpT >= pTBins[i] && candpT < pTBins[i + 1]) { + if (candpT < pTBins[i + 1]) { return i; } } @@ -230,20 +233,16 @@ struct HFD0CandidateSelector { template <typename T> bool selectionPIDTPC(const T& track, int nPDG, int nSigmaCut) { - double nSigma = 0.0; + double nSigma = 100.0; //arbitarily large value 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; } + return nSigma < nSigmaCut; } /// Check if track is compatible with given TOF NSigma cut for a given flavour hypothesis @@ -255,20 +254,16 @@ struct HFD0CandidateSelector { template <typename T> bool selectionPIDTOF(const T& track, int nPDG, int nSigmaCut) { - double nSigma = 0.0; + double nSigma = 100.0; //arbitarily large value 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; } + return nSigma < nSigmaCut; } /// PID selection on daughter track @@ -325,7 +320,7 @@ struct HFD0CandidateSelector { { int statusD0, statusD0bar; // final selection flag : 0-rejected 1-accepted bool topolD0, topolD0bar; - int pidD0, pidD0bar, piPlus, piMinus, kPlus, kMinus; + int pidD0, pidD0bar, pionPlus, pionMinus, kaonPlus, kaonMinus; for (auto& hfCandProng2 : hfCandProng2s) { //looping over 2 prong candidates @@ -338,10 +333,10 @@ struct HFD0CandidateSelector { topolD0bar = true; pidD0 = -1; pidD0bar = -1; - piPlus = -1; - piMinus = -1; - kPlus = -1; - kMinus = -1; + pionPlus = -1; + pionMinus = -1; + kaonPlus = -1; + kaonMinus = -1; // daughter track validity selection if (!daughterSelection(trackPos) || !daughterSelection(trackNeg)) { @@ -368,21 +363,21 @@ struct HFD0CandidateSelector { continue; } - piPlus = selectionPID(trackPos, 211); - kMinus = selectionPID(trackNeg, 321); - piMinus = selectionPID(trackNeg, 211); - kPlus = selectionPID(trackPos, 321); + pionPlus = selectionPID(trackPos, 211); + kaonMinus = selectionPID(trackNeg, 321); + pionMinus = selectionPID(trackNeg, 211); + kaonPlus = selectionPID(trackPos, 321); - if (piPlus == 0 || kMinus == 0 || piMinus == 1 || kPlus == 1) { + if (pionPlus == 0 || kaonMinus == 0 || pionMinus == 1 || kaonPlus == 1) { pidD0 = 0; //exclude D0 } - if (piPlus == 1 || kMinus == 1 || piMinus == 0 || kPlus == 0) { + if (pionPlus == 1 || kaonMinus == 1 || pionMinus == 0 || kaonPlus == 0) { pidD0bar = 0; //exclude D0bar } - if (piPlus == 1 && kMinus == 1) { + if (pionPlus == 1 && kaonMinus == 1) { pidD0 = 1; //accept D0 } - if (piMinus == 1 && kPlus == 1) { + if (pionMinus == 1 && kaonPlus == 1) { pidD0bar = 1; //accept D0bar } From 1424a2802884219d686bc8bce58c2b54b6641fe4 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 15:13:02 +0100 Subject: [PATCH 1125/1751] Fix compiler warnings (implicit signed/unsigned cast / irrelevant const specifier) --- .../include/SimulationDataFormat/ConstMCTruthContainer.h | 8 ++++---- .../include/SimulationDataFormat/MCTruthContainer.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h index 6e0d30f593956..855ec6f2bf254 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -86,7 +86,7 @@ class ConstMCTruthContainer : public std::vector<char> source += sizeof(FlatHeader); const size_t headerSize = flatheader.sizeofHeaderElement * flatheader.nofHeaderElements; source += headerSize; - return (TruthElement const* const)source; + return (TruthElement const*)source; } FlatHeader const& getHeader() const @@ -100,7 +100,7 @@ class ConstMCTruthContainer : public std::vector<char> { auto* source = &(*this)[0]; source += sizeof(FlatHeader); - return (MCTruthHeaderElement const* const)source; + return (MCTruthHeaderElement const*)source; } }; } // namespace dataformats @@ -185,7 +185,7 @@ class ConstMCTruthContainerView source += sizeof(FlatHeader); const size_t headerSize = flatheader.sizeofHeaderElement * flatheader.nofHeaderElements; source += headerSize; - return (TruthElement const* const)source; + return (TruthElement const*)source; } FlatHeader const& getHeader() const @@ -199,7 +199,7 @@ class ConstMCTruthContainerView { auto* source = &(mStorage)[0]; source += sizeof(FlatHeader); - return (MCTruthHeaderElement const* const)source; + return (MCTruthHeaderElement const*)source; } }; diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h index ed5391da4f803..cf39f7aa3a8e8 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h @@ -267,7 +267,7 @@ class MCTruthContainer // fix headers for (uint32_t i = dataindex + 1; i < mHeaderArray.size(); ++i) { auto oldindex = mHeaderArray[i].index; - mHeaderArray[i].index = (oldindex != -1) ? oldindex + 1 : oldindex; + mHeaderArray[i].index = (oldindex != (uint32_t)-1) ? oldindex + 1 : oldindex; } } } From 59f0a438b7cc5d59f33935c0c1528838d724587b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20von=20Haller?= <barthelemy.von.haller@cern.ch> Date: Wed, 28 Oct 2020 12:57:16 +0100 Subject: [PATCH 1126/1751] Fix test fetching headers (#4699) --- CCDB/test/testCcdbApi.cxx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CCDB/test/testCcdbApi.cxx b/CCDB/test/testCcdbApi.cxx index f5a619eb09de3..40b51774c9f49 100644 --- a/CCDB/test/testCcdbApi.cxx +++ b/CCDB/test/testCcdbApi.cxx @@ -421,16 +421,24 @@ BOOST_AUTO_TEST_CASE(TestHeaderParsing) BOOST_AUTO_TEST_CASE(TestFetchingHeaders, *utf::precondition(if_reachable())) { + // first store the object + string objectPath = basePath + "objectETag"; + test_fixture f; + TH1F h1("objectETag", "objectETag", 100, 0, 99); + f.api.storeAsTFile(&h1, objectPath, f.metadata); + + // then get the headers std::string etag; std::vector<std::string> headers; std::vector<std::string> pfns; - auto updated = CcdbApi::getCCDBEntryHeaders("http://ccdb-test.cern.ch:8080/TOF/LHCphase/1567080816927", etag, headers); + string path = objectPath + "/" + std::to_string(getCurrentTimestamp()); + auto updated = CcdbApi::getCCDBEntryHeaders("http://ccdb-test.cern.ch:8080/" + path, etag, headers); BOOST_CHECK_EQUAL(updated, true); BOOST_REQUIRE(headers.size() != 0); CcdbApi::parseCCDBHeaders(headers, pfns, etag); BOOST_REQUIRE(etag != ""); BOOST_REQUIRE(pfns.size()); - updated = CcdbApi::getCCDBEntryHeaders("http://ccdb-test.cern.ch:8080/TOF/LHCphase/1567080816927", etag, headers); + updated = CcdbApi::getCCDBEntryHeaders("http://ccdb-test.cern.ch:8080/" + path, etag, headers); BOOST_CHECK_EQUAL(updated, false); } From 13c9022d098485abe1f3aba01aba91099ad1b3b3 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 28 Oct 2020 11:31:12 +0100 Subject: [PATCH 1127/1751] Script for the full system test A full system test script (MC - raw - reco) meant for nightly testing. --- Utilities/Tools/jobutils.sh | 25 ++++++++++++- prodtests/CMakeLists.txt | 4 +- prodtests/full_system_test.sh | 70 +++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100755 prodtests/full_system_test.sh diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index 014f753547c16..a9a5cd814ac5c 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -51,6 +51,11 @@ taskwrapper() { # launch the actual command in the background echo "Launching task: ${command} &> $logfile &" + # the command might be a complex block: For the timing measurement below + # it is better to execute this as a script + SCRIPTNAME="${logfile}_tmp.sh" + echo "${command}" > ${SCRIPTNAME} + chmod +x ${SCRIPTNAME} # this gives some possibility to customize the wrapper # and do some special task at the start. The hook takes 2 arguments: @@ -67,6 +72,7 @@ taskwrapper() { if [ "${JOBUTILS_SKIPDONE}" ]; then if [ -f "${logfile}_done" ]; then echo "Skipping task since file ${logfile}_done found"; + rm ${SCRIPTNAME} 2> /dev/null return 0 fi fi @@ -81,9 +87,9 @@ taskwrapper() { fi # with or without memory monitoring ? - finalcommand="TIME=\"#walltime %e\" ${TIMECOMMAND} ${command}" + finalcommand="TIME=\"#walltime %e\" ${TIMECOMMAND} ./${SCRIPTNAME}" if [[ "$(uname)" != "Darwin" && "${JOBUTILS_MONITORMEM}" ]]; then - finalcommand="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh ${TIMECOMMAND} '${command}'" + finalcommand="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh ${TIMECOMMAND} './${SCRIPTNAME}'" fi echo "Running: ${finalcommand}" > ${logfile} eval ${finalcommand} >> ${logfile} 2>&1 & @@ -140,6 +146,7 @@ taskwrapper() { done RC_ACUM=$((RC_ACUM+1)) + rm ${SCRIPTNAME} 2> /dev/null return 1 fi @@ -177,5 +184,19 @@ taskwrapper() { else echo "command ${command} had nonzero exit code ${RC}" fi + rm ${SCRIPTNAME} 2> /dev/null return ${RC} } + +getNumberOfPhysicalCPUCores() { + if [ "$(uname)" == "Darwin" ]; then + CORESPERSOCKET=`system_profiler SPHardwareDataType | grep "Total Number of Cores:" | awk '{print $5}'` + SOCKETS=`system_profiler SPHardwareDataType | grep "Number of Processors:" | awk '{print $4}'` + else + # Do something under GNU/Linux platform + CORESPERSOCKET=`lscpu | grep "Core(s) per socket" | awk '{print $4}'` + SOCKETS=`lscpu | grep "Socket(s)" | awk '{print $2}'` + fi + N=`bc <<< "${CORESPERSOCKET}*${SOCKETS}"` + echo "${N}" +} diff --git a/prodtests/CMakeLists.txt b/prodtests/CMakeLists.txt index 58dee216b7114..1401750c63abb 100644 --- a/prodtests/CMakeLists.txt +++ b/prodtests/CMakeLists.txt @@ -9,4 +9,6 @@ # submit itself to any jurisdiction. -install(PROGRAMS sim_performance_test.sh sim_challenge.sh check_embedding_pileup.sh produce_QEDhits.sh DESTINATION prodtests) +install(PROGRAMS sim_performance_test.sh sim_challenge.sh check_embedding_pileup.sh produce_QEDhits.sh + full_system_test.sh + DESTINATION prodtests) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh new file mode 100755 index 0000000000000..fac1006d03ba3 --- /dev/null +++ b/prodtests/full_system_test.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# +# A workflow performing a full system test: +# - simulation of digits +# - creation of raw data +# - reconstruction of raw data +# +# Note that this might require a production server to run. +# +# This script needs some binary objects (for the moment): +# - matbud.root + ITSdictionary.bin + ctf_dictionary.root +# +# authors: D. Rohr / S. Wenzel + +# include jobutils, which notably brings +# --> the taskwrapper as a simple control and monitoring tool +# (look inside the jobutils.sh file for documentation) +# --> utilities to query CPU count +. ${O2_ROOT}/share/scripts/jobutils.sh + + +NEvents=${NEvents:-10} #550 for full TF (the number of PbPb events) +NEventsQED=${NEventsQED:-1000} #35000 for full TF +NCPUS=$(getNumberOfPhysicalCPUCores) +echo "Found ${NCPUS} physical CPU cores" +NJOBS=${NJOBS:-"${NCPUS}"} +SHMSIZE=128000000000 # 128000000000 # Size of shared memory for messages +TPCTRACKERSCRATCHMEMORY=22000000000 +NTIMEFRAMES=${NTIMEFRAMES:-1} # Number of time frames to process +TFDELAY=100 # Delay in seconds between publishing time frames +NOMCLABELS="--disable-mc" + +# allow skipping +JOBUTILS_SKIPDONE=ON + +ulimit -n 4096 # Make sure we can open sufficiently many files +mkdir qed +cd qed +taskwrapper qedsim.log o2-sim -j $NJOBS -n$NEventsQED -m PIPE ITS MFT FT0 FV0 -g extgen --configKeyValues '"GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-5;QEDGenParam.yMax=6;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;Diamond.width[2]=6."' +cd .. + +GLOBALDPLOPT="-b --monitoring-backend no-op://" +taskwrapper sim.log o2-sim -n $NEvents --skipModules ZDC --configKeyValues "Diamond.width[2]=6." -g pythia8hi -j $NJOBS +taskwrapper digi.log o2-sim-digitizer-workflow -n $NEvents --simPrefixQED qed/o2sim --qed-x-section-ratio 3735 ${NOMCLABELS} --firstOrbit 0 --firstBC 0 --skipDet TRD --tpc-lanes $((NJOBS < 36 ? NJOBS : 36)) --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} +taskwrapper digiTRD.log o2-sim-digitizer-workflow -n $NEvents --simPrefixQED qed/o2sim --qed-x-section-ratio 3735 ${NOMCLABELS} --firstOrbit 0 --firstBC 0 --onlyDet TRD --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} --incontext collisioncontext.root --configKeyValues "TRDSimParams.digithreads=${NJOBS}" +mkdir raw +taskwrapper itsraw.log o2-its-digi2raw --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/ITS +taskwrapper mftraw.log o2-mft-digi2raw --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/MFT +taskwrapper ft0raw.log o2-ft0-digi2raw --file-per-link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/FT0 +taskwrapper tpcraw.log o2-tpc-digits-to-rawzs --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -i tpcdigits.root -o raw/TPC +taskwrapper tofraw.log o2-tof-reco-workflow ${GLOBALDPLOPT} --tof-raw-file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' --output-type raw --tof-raw-outdir raw/TOF +taskwrapper midraw.log o2-mid-digits-to-raw-workflow ${GLOBALDPLOPT} --mid-raw-outdir raw/MID --mid-raw-perlink --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' +cat raw/*/*.cfg > rawAll.cfg + +ARGS_ALL="--session default" +taskwrapper reco.log "o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | +o2-itsmft-stf-decoder-workflow $ARGS_ALL | +o2-itsmft-stf-decoder-workflow $ARGS_ALL --runmft true | +o2-its-reco-workflow $ARGS_ALL --trackerCA ${NOMCLABELS} --clusters-from-upstream --disable-root-output --entropy-encoding --configKeyValues \"fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500\" | +o2-itsmft-entropy-encoder-workflow $ARGS_ALL --runmft true | +o2-tpc-reco-workflow $ARGS_ALL --input-type=zsraw ${NOMCLABELS} --output-type tracks,clusters,encoded-clusters,disable-writer --configKeyValues \"HBFUtils.nHBFPerTF=128;GPU_proc.forceHostMemoryPoolSize=${TPCTRACKERSCRATCHMEMORY}\" | +o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | +o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | +o2-ft0-entropy-encoder-workflow $ARGS_ALL | +o2-tpcits-match-workflow $ARGS_ALL -b --disable-root-input --disable-root-output ${NOMCLABELS} | +o2-mid-reco-workflow $ARGS_ALL --disable-root-output | +o2-mid-entropy-encoder-workflow $ARGS_ALL | +o2-tof-compressor $ARGS_ALL | +o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output ${NOMCLABELS} | +o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input --shm-segment-size $SHMSIZE ${GLOBALDPLOPT}" From 4048b55c2da92e3a606ae29538179db1d9e49418 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 11:18:23 +0100 Subject: [PATCH 1128/1751] GPU Display: don't show TRD grid if TRD Geometry is not loaded --- .../Standalone/display/GPUDisplay.cxx | 108 +++++++++--------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 30c7a602c79c7..d816a00d0fc3b 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -1133,59 +1133,61 @@ GPUDisplay::vboList GPUDisplay::DrawGridTRD(int sector) // TODO: tilted pads ignored at the moment size_t startCount = mVertexBufferStart[sector].size(); size_t startCountInner = mVertexBuffer[sector].size(); - auto geo = mChain->GetTRDGeometry(); - int trdsector = NSLICES / 2 - 1 - sector; - float alpha = geo->GetAlpha() / 2.f + geo->GetAlpha() * trdsector; - if (trdsector >= 9) { - alpha -= 2 * M_PI; - } - for (int iLy = 0; iLy < GPUTRDTracker::EGPUTRDTracker::kNLayers; ++iLy) { - for (int iStack = 0; iStack < GPUTRDTracker::EGPUTRDTracker::kNStacks; ++iStack) { - int iDet = geo->GetDetector(iLy, iStack, trdsector); - auto matrix = geo->GetClusterMatrix(iDet); - if (!matrix) { - continue; - } - auto pp = geo->GetPadPlane(iDet); - for (int i = 0; i < pp->GetNrows(); ++i) { - float xyzLoc1[3]; - float xyzLoc2[3]; - float xyzGlb1[3]; - float xyzGlb2[3]; - xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); - xyzLoc1[1] = pp->GetCol0(); - xyzLoc2[1] = pp->GetColEnd(); - xyzLoc1[2] = xyzLoc2[2] = pp->GetRowPos(i) - pp->GetRowPos(pp->GetNrows() / 2); - matrix->LocalToMaster(xyzLoc1, xyzGlb1); - matrix->LocalToMaster(xyzLoc2, xyzGlb2); - float x1Tmp = xyzGlb1[0]; - xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); - xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); - float x2Tmp = xyzGlb2[0]; - xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); - xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); - mVertexBuffer[sector].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); - mVertexBuffer[sector].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); - } - for (int j = 0; j < pp->GetNcols(); ++j) { - float xyzLoc1[3]; - float xyzLoc2[3]; - float xyzGlb1[3]; - float xyzGlb2[3]; - xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); - xyzLoc1[1] = xyzLoc2[1] = pp->GetColPos(j) + pp->GetColSize(j) / 2.f; - xyzLoc1[2] = pp->GetRow0() - pp->GetRowPos(pp->GetNrows() / 2); - xyzLoc2[2] = pp->GetRowEnd() - pp->GetRowPos(pp->GetNrows() / 2); - matrix->LocalToMaster(xyzLoc1, xyzGlb1); - matrix->LocalToMaster(xyzLoc2, xyzGlb2); - float x1Tmp = xyzGlb1[0]; - xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); - xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); - float x2Tmp = xyzGlb2[0]; - xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); - xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); - mVertexBuffer[sector].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); - mVertexBuffer[sector].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); + auto* geo = mChain->GetTRDGeometry(); + if (geo) { + int trdsector = NSLICES / 2 - 1 - sector; + float alpha = geo->GetAlpha() / 2.f + geo->GetAlpha() * trdsector; + if (trdsector >= 9) { + alpha -= 2 * M_PI; + } + for (int iLy = 0; iLy < GPUTRDTracker::EGPUTRDTracker::kNLayers; ++iLy) { + for (int iStack = 0; iStack < GPUTRDTracker::EGPUTRDTracker::kNStacks; ++iStack) { + int iDet = geo->GetDetector(iLy, iStack, trdsector); + auto matrix = geo->GetClusterMatrix(iDet); + if (!matrix) { + continue; + } + auto pp = geo->GetPadPlane(iDet); + for (int i = 0; i < pp->GetNrows(); ++i) { + float xyzLoc1[3]; + float xyzLoc2[3]; + float xyzGlb1[3]; + float xyzGlb2[3]; + xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); + xyzLoc1[1] = pp->GetCol0(); + xyzLoc2[1] = pp->GetColEnd(); + xyzLoc1[2] = xyzLoc2[2] = pp->GetRowPos(i) - pp->GetRowPos(pp->GetNrows() / 2); + matrix->LocalToMaster(xyzLoc1, xyzGlb1); + matrix->LocalToMaster(xyzLoc2, xyzGlb2); + float x1Tmp = xyzGlb1[0]; + xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); + xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); + float x2Tmp = xyzGlb2[0]; + xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); + xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); + mVertexBuffer[sector].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); + mVertexBuffer[sector].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); + } + for (int j = 0; j < pp->GetNcols(); ++j) { + float xyzLoc1[3]; + float xyzLoc2[3]; + float xyzGlb1[3]; + float xyzGlb2[3]; + xyzLoc1[0] = xyzLoc2[0] = geo->AnodePos(); + xyzLoc1[1] = xyzLoc2[1] = pp->GetColPos(j) + pp->GetColSize(j) / 2.f; + xyzLoc1[2] = pp->GetRow0() - pp->GetRowPos(pp->GetNrows() / 2); + xyzLoc2[2] = pp->GetRowEnd() - pp->GetRowPos(pp->GetNrows() / 2); + matrix->LocalToMaster(xyzLoc1, xyzGlb1); + matrix->LocalToMaster(xyzLoc2, xyzGlb2); + float x1Tmp = xyzGlb1[0]; + xyzGlb1[0] = xyzGlb1[0] * cosf(alpha) + xyzGlb1[1] * sinf(alpha); + xyzGlb1[1] = -x1Tmp * sinf(alpha) + xyzGlb1[1] * cosf(alpha); + float x2Tmp = xyzGlb2[0]; + xyzGlb2[0] = xyzGlb2[0] * cosf(alpha) + xyzGlb2[1] * sinf(alpha); + xyzGlb2[1] = -x2Tmp * sinf(alpha) + xyzGlb2[1] * cosf(alpha); + mVertexBuffer[sector].emplace_back(xyzGlb1[0] / GL_SCALE_FACTOR, xyzGlb1[1] / GL_SCALE_FACTOR, xyzGlb1[2] / GL_SCALE_FACTOR); + mVertexBuffer[sector].emplace_back(xyzGlb2[0] / GL_SCALE_FACTOR, xyzGlb2[1] / GL_SCALE_FACTOR, xyzGlb2[2] / GL_SCALE_FACTOR); + } } } } From b8121f9ad9635452b2ff58a487eb22f7ac834d96 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 13:27:27 +0100 Subject: [PATCH 1129/1751] GPU Display: add option to highlight TPC clusters at high incl angle --- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 6 ++++-- GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx | 11 +++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index d816a00d0fc3b..064ad942d8622 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -721,8 +721,8 @@ GPUDisplay::vboList GPUDisplay::DrawClusters(const GPUTPCTracker& tracker, int s if (mMarkAdjacentClusters) { const int attach = tracker.GetConstantMem()->ioPtrs.mergedTrackHitAttachment[cid]; if (attach) { - if (mMarkAdjacentClusters >= 16) { - if (mQA && mQA->clusterRemovable(cid, mMarkAdjacentClusters == 17)) { + if (mMarkAdjacentClusters >= 32) { + if (mQA && mQA->clusterRemovable(cid, mMarkAdjacentClusters == 33)) { draw = select == tMARKED; } } else if ((mMarkAdjacentClusters & 2) && (attach & gputpcgmmergertypes::attachTube)) { @@ -731,6 +731,8 @@ GPUDisplay::vboList GPUDisplay::DrawClusters(const GPUTPCTracker& tracker, int s draw = select == tMARKED; } else if ((mMarkAdjacentClusters & 4) && (attach & gputpcgmmergertypes::attachGoodLeg) == 0) { draw = select == tMARKED; + } else if ((mMarkAdjacentClusters & 16) && (attach & gputpcgmmergertypes::attachHighIncl)) { + draw = select == tMARKED; } else if (mMarkAdjacentClusters & 8) { if (fabsf(tracker.GetConstantMem()->ioPtrs.mergedTracks[attach & gputpcgmmergertypes::attachTrackMask].GetParam().GetQPt()) > 20.f) { draw = select == tMARKED; diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx index e6224985e3f62..e7c85ef06826e 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx @@ -183,15 +183,18 @@ void GPUDisplay::HandleKeyRelease(unsigned char key) if (mMarkAdjacentClusters == 9) { mMarkAdjacentClusters = 15; } - if (mMarkAdjacentClusters == 18) { + if (mMarkAdjacentClusters == 17) { + mMarkAdjacentClusters = 31; + } + if (mMarkAdjacentClusters == 34) { mMarkAdjacentClusters = 0; } - if (mMarkAdjacentClusters == 17) { + if (mMarkAdjacentClusters == 33) { SetInfo("Marking protected clusters (%d)", mMarkAdjacentClusters); - } else if (mMarkAdjacentClusters == 16) { + } else if (mMarkAdjacentClusters == 32) { SetInfo("Marking removable clusters (%d)", mMarkAdjacentClusters); } else { - SetInfo("Marking adjacent clusters (%d): rejected %s, tube %s, looper leg %s, low Pt %s", mMarkAdjacentClusters, (mMarkAdjacentClusters & 1) ? "yes" : " no", (mMarkAdjacentClusters & 2) ? "yes" : " no", (mMarkAdjacentClusters & 4) ? "yes" : " no", (mMarkAdjacentClusters & 8) ? "yes" : " no"); + SetInfo("Marking adjacent clusters (%d): rejected %s, tube %s, looper leg %s, low Pt %s, high incl %s", mMarkAdjacentClusters, (mMarkAdjacentClusters & 1) ? "yes" : " no", (mMarkAdjacentClusters & 2) ? "yes" : " no", (mMarkAdjacentClusters & 4) ? "yes" : " no", (mMarkAdjacentClusters & 8) ? "yes" : " no", (mMarkAdjacentClusters & 16) ? "yes" : " no"); } mUpdateDLList = true; } else if (key == 'C') { From b9fbb16b11452441973f9f4f89e3eb885fac133a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 28 Oct 2020 17:05:41 +0100 Subject: [PATCH 1130/1751] more robust ON GRID detection --- Utilities/Tools/grid_submit.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Utilities/Tools/grid_submit.sh b/Utilities/Tools/grid_submit.sh index be58158393f71..b26839a3c87e3 100755 --- a/Utilities/Tools/grid_submit.sh +++ b/Utilities/Tools/grid_submit.sh @@ -30,12 +30,9 @@ if [[ ! $ALIEN_PROC_ID && ! $1 ]]; then fi # find out if this script is really executed on GRID -# in this case, we should be in a workdir labeled alien-job-${ALIEN_PROC_ID} +# in this case, we should find an environment variable JALIEN_TOKEN_CERT ONGRID=0 -$(cd ../alien-job-${ALIEN_PROC_ID} 2> /dev/null) -if [[ "$?" == "0" ]]; then - ONGRID=1 -fi +[ "${JALIEN_TOKEN_CERT}" ] && ONGRID=1 # General job configuration MY_USER=${ALIEN_USER:-`whoami`} From 4929edda6acc06a882815abc9d7c9e150d330950 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 18 Oct 2020 18:13:29 +0200 Subject: [PATCH 1131/1751] direct BC -> microsec. conversions --- .../include/CommonConstants/LHCConstants.h | 2 ++ .../CommonDataFormat/InteractionRecord.h | 18 ++++++++++-------- .../include/FT0Reconstruction/InteractionTag.h | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Common/Constants/include/CommonConstants/LHCConstants.h b/Common/Constants/include/CommonConstants/LHCConstants.h index 083c1a79d45dc..ba3cc93331a5a 100644 --- a/Common/Constants/include/CommonConstants/LHCConstants.h +++ b/Common/Constants/include/CommonConstants/LHCConstants.h @@ -30,6 +30,8 @@ static constexpr double LHCRFFreq = 400.789e6; // LHC R static constexpr double LHCBunchSpacingNS = 10 * 1.e9 / LHCRFFreq; // bunch spacing in ns (10 RFbuckets) static constexpr double LHCOrbitNS = LHCMaxBunches * LHCBunchSpacingNS; // orbit duration in ns static constexpr double LHCRevFreq = 1.e9 / LHCOrbitNS; // revolution frequency +static constexpr double LHCBunchSpacingMS = LHCBunchSpacingNS * 1e-3; // bunch spacing in ms (10 RFbuckets) +static constexpr double LHCOrbitMS = LHCOrbitNS * 1e-3; // orbit duration in ms static constexpr unsigned int MaxNOrbits = 0xffffffff; } // namespace lhc diff --git a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h index e68f0260266a6..841197c2af4ee 100644 --- a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h +++ b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h @@ -90,7 +90,7 @@ struct InteractionRecord { int64_t differenceInBC(const InteractionRecord& other) const { - // return differenc in bunch-crossings + // return difference in bunch-crossings int64_t diffBC = int(bc) - other.bc; if (orbit != other.orbit) { diffBC += (int64_t(orbit) - other.orbit) * o2::constants::lhc::LHCMaxBunches; @@ -98,14 +98,16 @@ struct InteractionRecord { return diffBC; } - float differenceInBCns(const InteractionRecord& other) const + 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; + // return difference in bunch-crossings in ns + return differenceInBC(other) * o2::constants::lhc::LHCBunchSpacingNS; + } + + float differenceInBCMS(const InteractionRecord& other) const + { + // return difference in bunch-crossings in ms + return differenceInBC(other) * o2::constants::lhc::LHCBunchSpacingMS; } int64_t toLong() const diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h index 21edc29013c30..962bb4b599ca9 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h @@ -34,7 +34,7 @@ struct InteractionTag : public o2::conf::ConfigurableParamHelper<InteractionTag> float getInteractionTimeNS(const RecPoints& rp, const o2::InteractionRecord& refIR) const { - return rp.getInteractionRecord().differenceInBCns(refIR); // RS FIXME do we want use precise MeanTime? + return rp.getInteractionRecord().differenceInBCNS(refIR); // RS FIXME do we want use precise MeanTime? } O2ParamDef(InteractionTag, "ft0tag"); From c87607a91111c7111d8e14fe096f9f6b456039e8 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 24 Oct 2020 18:36:21 +0200 Subject: [PATCH 1132/1751] option to pass debug flags to ITS-TPC matching --- Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index b96e965ea34b9..5776401f66e87 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -87,6 +87,9 @@ void TPCITSMatchingDPL::init(InitContext& ic) LOG(INFO) << "Material LUT " << matLUTFile << " file is absent, only TGeo can be used"; } + int dbgFlags = ic.options().get<int>("debug-tree-flags"); + mMatching.setDebugFlag(dbgFlags); + // set bunch filling. Eventually, this should come from CCDB const auto* digctx = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); const auto& bcfill = digctx->getBunchFilling(); @@ -313,7 +316,8 @@ DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool useMC, const std::vect AlgorithmSpec{adaptFromTask<TPCITSMatchingDPL>(useFT0, useMC)}, Options{ {"its-dictionary-path", VariantType::String, "", {"Path of the cluster-topology dictionary file"}}, - {"material-lut-path", VariantType::String, "", {"Path of the material LUT file"}}}}; + {"material-lut-path", VariantType::String, "", {"Path of the material LUT file"}}, + {"debug-tree-flags", VariantType::Int, 0, {"DebugFlagTypes bit-pattern for debug tree"}}}}; } } // namespace globaltracking From f222f229b8b6bfbb7bd40c8dd037e4292899c577 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 24 Oct 2020 21:49:57 +0200 Subject: [PATCH 1133/1751] Method to update TrackParCov matrix particular element --- .../TrackParametrizationWithError.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index dfd3e1ad2ed75..9910623f25f24 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -108,8 +108,8 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> void checkCovariance(); void setCov(value_t v, int i); - protected: void updateCov(const value_t delta[kCovMatSize]); + void updateCov(value_t delta, int i); protected: value_t mC[kCovMatSize] = {0.f}; // 15 covariance matrix elements @@ -286,6 +286,13 @@ inline void TrackParametrizationWithError<value_T>::setCov(value_t v, int i) mC[i] = v; } +//__________________________________________________________________________ +template <typename value_T> +inline void TrackParametrizationWithError<value_T>::updateCov(value_t delta, int i) +{ + mC[i] += delta; +} + //__________________________________________________________________________ template <typename value_T> inline void TrackParametrizationWithError<value_T>::updateCov(const value_t delta[kCovMatSize]) From e9c52c452c9d62d96d6d84e493dbc909f6c72786 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 26 Oct 2020 23:35:41 +0100 Subject: [PATCH 1134/1751] Fix in MatchTPCITSParams class / filename mismatch --- .../include/GlobalTracking/MatchTPCITS.h | 6 +- .../GlobalTracking/MatchTPCITSParams.h | 6 +- .../src/GlobalTrackingLinkDef.h | 4 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 128 +++++++++++------- .../GlobalTracking/src/MatchTPCITSParams.cxx | 2 +- 5 files changed, 93 insertions(+), 53 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 4adcd9032cbb5..359e0f53c85ff 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -277,7 +277,7 @@ class MatchTPCITS using TPCTransform = o2::gpu::TPCFastTransform; using BracketF = o2::math_utils::Bracket<float>; using BracketIR = o2::math_utils::Bracket<o2::InteractionRecord>; - using Params = o2::globaltracking::MatchITSTPCParams; + using Params = o2::globaltracking::MatchTPCITSParams; using MatCorrType = o2::base::Propagator::MatCorrType; MatchTPCITS(); // std::unique_ptr to forward declared type needs constructor / destructor in .cxx @@ -509,7 +509,7 @@ class MatchTPCITS bool isDisabledITS(const TrackLocITS& t) const; int compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& tTPC, float& chi2) const; - float getPredictedChi2NoZ(const o2::track::TrackParCov& tr1, const o2::track::TrackParCov& tr2) const; + float getPredictedChi2NoZ(const o2::track::TrackParCov& trITS, const o2::track::TrackParCov& trTPC) const; bool propagateToRefX(o2::track::TrackParCov& trc); void addLastTrackCloneForNeighbourSector(int sector); @@ -635,6 +635,8 @@ class MatchTPCITS float mMinTPCTrackPtInv = 999.; ///< cutoff on TPC track inverse pT float mMinITSTrackPtInv = 999.; ///< cutoff on ITS track inverse pT + bool mVDriftCalibOn = false; ///< flag to produce VDrift calibration data + std::unique_ptr<TPCTransform> mTPCTransform; ///< TPC cluster transformation std::unique_ptr<o2::gpu::GPUParam> mTPCClusterParam; ///< TPC clusters error param diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h index 9c7cdd404dbfc..dceee1989c669 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h @@ -24,7 +24,7 @@ namespace globaltracking { // There are configurable params for TPC-ITS matching -struct MatchITSTPCParams : public o2::conf::ConfigurableParamHelper<MatchITSTPCParams> { +struct MatchTPCITSParams : public o2::conf::ConfigurableParamHelper<MatchTPCITSParams> { enum ValidateMatchByFIT { Disable, Prefer, Require }; // flags for usage of FT0 in match validation @@ -55,9 +55,11 @@ struct MatchITSTPCParams : public o2::conf::ConfigurableParamHelper<MatchITSTPCP float tpcTimeICMatchingNSigma = 4.; ///< nsigma for matching TPC corrected time and InteractionCandidate from FT0 + float maxVDriftUncertainty = 0.; ///< max assumed VDrift uncertainty, used only in VDrift calibration mode + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; /// Material correction type - O2ParamDef(MatchITSTPCParams, "tpcitsMatch"); + O2ParamDef(MatchTPCITSParams, "tpcitsMatch"); }; } // namespace globaltracking diff --git a/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h b/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h index ee2df157f55dd..74f3ce33f51aa 100644 --- a/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h +++ b/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h @@ -18,8 +18,8 @@ #pragma link C++ class o2::globaltracking::MatchTOF + ; #pragma link C++ class o2::globaltracking::TrackLocTPC + ; #pragma link C++ class o2::globaltracking::TrackLocITS + ; -#pragma link C++ class o2::globaltracking::MatchITSTPCParams + ; -#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::globaltracking::MatchITSTPCParams> + ; +#pragma link C++ class o2::globaltracking::MatchTPCITSParams + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::globaltracking::MatchTPCITSParams> + ; #pragma link C++ class o2::globaltracking::ABDebugLink + ; #pragma link C++ class o2::globaltracking::ABDebugTrack + ; diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 226b721c71b42..fa9a7d8faa0e5 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -352,6 +352,8 @@ void MatchTPCITS::init() mMinTPCTrackPtInv = (mFieldON && mParams->minTPCTrackR > 0) ? 1. / std::abs(mParams->minTPCTrackR * bz * o2::constants::math::B2C) : 999.; mMinITSTrackPtInv = (mFieldON && mParams->minITSTrackR > 0) ? 1. / std::abs(mParams->minITSTrackR * bz * o2::constants::math::B2C) : 999.; + mVDriftCalibOn = mParams->maxVDriftUncertainty > 0.; + #ifdef _ALLOW_DEBUG_TREES_ // debug streamer if (mDBGFlags) { @@ -799,6 +801,8 @@ void MatchTPCITS::doMatching(int sec) /// full drift time + safety margin float maxTDriftSafe = (mNTPCBinsFullDrift + mParams->safeMarginTPCITSTimeBin + mTPCTimeEdgeTSafeMargin); + float vdErr2TB = mZ2TPCBin * mParams->maxVDriftUncertainty; + // get min ROFrame (in TPC time-bins) of ITS tracks currently in cache auto minROFITS = mITSWork[cacheITS.front()].roFrame; @@ -810,7 +814,7 @@ void MatchTPCITS::doMatching(int sec) int nCheckTPCControl = 0, nCheckITSControl = 0, nMatchesControl = 0; // temporary int idxMinTPC = tbinStartTPC[minROFITS]; // index of 1st cached TPC track within cached ITS ROFrames auto t2nbs = mZ2TPCBin * mParams->tpcTimeICMatchingNSigma; - bool checkInteractionCandidates = mUseFT0 && mParams->validateMatchByFIT != MatchITSTPCParams::Disable; + bool checkInteractionCandidates = mUseFT0 && mParams->validateMatchByFIT != MatchTPCITSParams::Disable; for (int itpc = idxMinTPC; itpc < nTracksTPC; itpc++) { auto& trefTPC = mTPCWork[cacheTPC[itpc]]; // estimate ITS 1st ROframe bin this track may match to: TPC track are sorted according to their @@ -835,6 +839,18 @@ void MatchTPCITS::doMatching(int sec) continue; } + // is corrected TPC track time compatible with ITS ROF expressed in TPC bins? + auto deltaT = (trefITS.getZ() - trefTPC.getZ()) * mZ2TPCBin; // time difference in TPC time bins corresponding to Z differences + auto timeTB = getTPCTrackCorrectedTimeBin(mTPCTracksArray[trefTPC.sourceID], deltaT); // TPC time required to match to Z of ITS track + auto timeTBErr = std::sqrt(trefITS.getSigmaZ2() + trefTPC.getSigmaZ2()) * t2nbs; // nsigma*error in number of TPC time bins + if (mVDriftCalibOn) { + timeTBErr += vdErr2TB * (250. - abs(trefITS.getZ())); // account for the extra error from TPC VDrift uncertainty + } + o2::math_utils::Bracket<float> trange(timeTB - timeTBErr, timeTB + timeTBErr); + if (timeITS.isOutside(trange)) { + continue; + } + nCheckITSControl++; float chi2 = -1; int rejFlag = compareTPCITSTracks(trefITS, trefTPC, chi2); @@ -866,15 +882,6 @@ 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::math_utils::Bracket<float> 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 (!isCosmics()) { // validate by bunch filling scheme @@ -901,7 +908,7 @@ void MatchTPCITS::doMatching(int sec) } } } - if (mParams->validateMatchByFIT == MatchITSTPCParams::Require && matchedIC == MinusOne) { + if (mParams->validateMatchByFIT == MatchTPCITSParams::Require && matchedIC == MinusOne) { continue; } } @@ -1038,61 +1045,63 @@ void MatchTPCITS::registerMatchRecordITS(int iITS, int iTPC, float chi2, int can int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& tTPC, float& chi2) const { ///< compare pair of ITS and TPC tracks - auto& trackTPC = tTPC; - auto& trackITS = tITS; chi2 = -1.f; int rejFlag = Accept; float diff; // make rough check differences and their nsigmas // start with check on Tgl, since rjection on it will allow to profit from sorting - diff = trackITS.getParam(o2::track::kTgl) - trackTPC.getParam(o2::track::kTgl); + diff = tITS.getParam(o2::track::kTgl) - tTPC.getParam(o2::track::kTgl); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kTgl], RejectOnTgl))) { return rejFlag; } - diff *= diff / (trackITS.getDiagError2(o2::track::kTgl) + trackTPC.getDiagError2(o2::track::kTgl)); + auto err2Tgl = tITS.getDiagError2(o2::track::kTgl) + tTPC.getDiagError2(o2::track::kTgl); + if (mVDriftCalibOn) { + auto addErr = tITS.getParam(o2::track::kTgl) * mParams->maxVDriftUncertainty; + err2Tgl += addErr * addErr; // account for VDrift uncertainty + } + diff *= diff / err2Tgl; if ((rejFlag = roughCheckDif(diff, mParams->crudeNSigma2Cut[o2::track::kTgl], RejectOnTgl + NSigmaShift))) { return rejFlag; } - - diff = trackITS.getParam(o2::track::kY) - trackTPC.getParam(o2::track::kY); + diff = tITS.getParam(o2::track::kY) - tTPC.getParam(o2::track::kY); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kY], RejectOnY))) { return rejFlag; } - diff *= diff / (trackITS.getDiagError2(o2::track::kY) + trackTPC.getDiagError2(o2::track::kY)); + diff *= diff / (tITS.getDiagError2(o2::track::kY) + tTPC.getDiagError2(o2::track::kY)); if ((rejFlag = roughCheckDif(diff, mParams->crudeNSigma2Cut[o2::track::kY], RejectOnY + NSigmaShift))) { return rejFlag; } if (mCompareTracksDZ) { // in continuous mode we usually don't use DZ - diff = trackITS.getParam(o2::track::kZ) - trackTPC.getParam(o2::track::kZ); + diff = tITS.getParam(o2::track::kZ) - tTPC.getParam(o2::track::kZ); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kZ], RejectOnZ))) { return rejFlag; } - diff *= diff / (trackITS.getDiagError2(o2::track::kZ) + trackTPC.getDiagError2(o2::track::kZ)); + diff *= diff / (tITS.getDiagError2(o2::track::kZ) + tTPC.getDiagError2(o2::track::kZ)); if ((rejFlag = roughCheckDif(diff, mParams->crudeNSigma2Cut[o2::track::kZ], RejectOnZ + NSigmaShift))) { return rejFlag; } } else { // in continuous mode we use special check on allowed Z range - if (trackITS.getParam(o2::track::kZ) - tTPC.zMax > mParams->crudeAbsDiffCut[o2::track::kZ]) + if (tITS.getParam(o2::track::kZ) - tTPC.zMax > mParams->crudeAbsDiffCut[o2::track::kZ]) return RejectOnZ; - if (trackITS.getParam(o2::track::kZ) - tTPC.zMin < -mParams->crudeAbsDiffCut[o2::track::kZ]) + if (tITS.getParam(o2::track::kZ) - tTPC.zMin < -mParams->crudeAbsDiffCut[o2::track::kZ]) return -RejectOnZ; } - diff = trackITS.getParam(o2::track::kSnp) - trackTPC.getParam(o2::track::kSnp); + diff = tITS.getParam(o2::track::kSnp) - tTPC.getParam(o2::track::kSnp); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kSnp], RejectOnSnp))) { return rejFlag; } - diff *= diff / (trackITS.getDiagError2(o2::track::kSnp) + trackTPC.getDiagError2(o2::track::kSnp)); + diff *= diff / (tITS.getDiagError2(o2::track::kSnp) + tTPC.getDiagError2(o2::track::kSnp)); if ((rejFlag = roughCheckDif(diff, mParams->crudeNSigma2Cut[o2::track::kSnp], RejectOnSnp + NSigmaShift))) { return rejFlag; } - diff = trackITS.getParam(o2::track::kQ2Pt) - trackTPC.getParam(o2::track::kQ2Pt); + diff = tITS.getParam(o2::track::kQ2Pt) - tTPC.getParam(o2::track::kQ2Pt); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kQ2Pt], RejectOnQ2Pt))) { return rejFlag; } - diff *= diff / (trackITS.getDiagError2(o2::track::kQ2Pt) + trackTPC.getDiagError2(o2::track::kQ2Pt)); + diff *= diff / (tITS.getDiagError2(o2::track::kQ2Pt) + tTPC.getDiagError2(o2::track::kQ2Pt)); if ((rejFlag = roughCheckDif(diff, mParams->crudeNSigma2Cut[o2::track::kQ2Pt], RejectOnQ2Pt + NSigmaShift))) { return rejFlag; } @@ -1147,41 +1156,45 @@ void MatchTPCITS::printCandidatesITS() const } //______________________________________________ -float MatchTPCITS::getPredictedChi2NoZ(const o2::track::TrackParCov& tr1, const o2::track::TrackParCov& tr2) const +float MatchTPCITS::getPredictedChi2NoZ(const o2::track::TrackParCov& trITS, const o2::track::TrackParCov& trTPC) const { /// get chi2 between 2 tracks, neglecting Z parameter. /// 2 tracks must be defined at the same parameters X,alpha (check is currently commented) - // if (std::abs(tr1.getAlpha() - tr2.getAlpha()) > FLT_EPSILON) { + // if (std::abs(trITS.getAlpha() - trTPC.getAlpha()) > FLT_EPSILON) { // LOG(ERROR) << "The reference Alpha of the tracks differ: " - // << tr1.getAlpha() << " : " << tr2.getAlpha(); + // << trITS.getAlpha() << " : " << trTPC.getAlpha(); // return 2. * o2::track::HugeF; // } - // if (std::abs(tr1.getX() - tr2.getX()) > FLT_EPSILON) { + // if (std::abs(trITS.getX() - trTPC.getX()) > FLT_EPSILON) { // LOG(ERROR) << "The reference X of the tracks differ: " - // << tr1.getX() << " : " << tr2.getX(); + // << trITS.getX() << " : " << trTPC.getX(); // return 2. * o2::track::HugeF; // } MatrixDSym4 covMat; - covMat(0, 0) = static_cast<double>(tr1.getSigmaY2()) + static_cast<double>(tr2.getSigmaY2()); - covMat(1, 0) = static_cast<double>(tr1.getSigmaSnpY()) + static_cast<double>(tr2.getSigmaSnpY()); - covMat(1, 1) = static_cast<double>(tr1.getSigmaSnp2()) + static_cast<double>(tr2.getSigmaSnp2()); - covMat(2, 0) = static_cast<double>(tr1.getSigmaTglY()) + static_cast<double>(tr2.getSigmaTglY()); - covMat(2, 1) = static_cast<double>(tr1.getSigmaTglSnp()) + static_cast<double>(tr2.getSigmaTglSnp()); - covMat(2, 2) = static_cast<double>(tr1.getSigmaTgl2()) + static_cast<double>(tr2.getSigmaTgl2()); - covMat(3, 0) = static_cast<double>(tr1.getSigma1PtY()) + static_cast<double>(tr2.getSigma1PtY()); - covMat(3, 1) = static_cast<double>(tr1.getSigma1PtSnp()) + static_cast<double>(tr2.getSigma1PtSnp()); - covMat(3, 2) = static_cast<double>(tr1.getSigma1PtTgl()) + static_cast<double>(tr2.getSigma1PtTgl()); - covMat(3, 3) = static_cast<double>(tr1.getSigma1Pt2()) + static_cast<double>(tr2.getSigma1Pt2()); + covMat(0, 0) = static_cast<double>(trITS.getSigmaY2()) + static_cast<double>(trTPC.getSigmaY2()); + covMat(1, 0) = static_cast<double>(trITS.getSigmaSnpY()) + static_cast<double>(trTPC.getSigmaSnpY()); + covMat(1, 1) = static_cast<double>(trITS.getSigmaSnp2()) + static_cast<double>(trTPC.getSigmaSnp2()); + covMat(2, 0) = static_cast<double>(trITS.getSigmaTglY()) + static_cast<double>(trTPC.getSigmaTglY()); + covMat(2, 1) = static_cast<double>(trITS.getSigmaTglSnp()) + static_cast<double>(trTPC.getSigmaTglSnp()); + covMat(2, 2) = static_cast<double>(trITS.getSigmaTgl2()) + static_cast<double>(trTPC.getSigmaTgl2()); + if (mVDriftCalibOn) { + auto addErr = trITS.getParam(o2::track::kTgl) * mParams->maxVDriftUncertainty; + covMat(2, 2) += addErr * addErr; + } + covMat(3, 0) = static_cast<double>(trITS.getSigma1PtY()) + static_cast<double>(trTPC.getSigma1PtY()); + covMat(3, 1) = static_cast<double>(trITS.getSigma1PtSnp()) + static_cast<double>(trTPC.getSigma1PtSnp()); + covMat(3, 2) = static_cast<double>(trITS.getSigma1PtTgl()) + static_cast<double>(trTPC.getSigma1PtTgl()); + covMat(3, 3) = static_cast<double>(trITS.getSigma1Pt2()) + static_cast<double>(trTPC.getSigma1Pt2()); if (!covMat.Invert()) { LOG(ERROR) << "Cov.matrix inversion failed: " << covMat; return 2. * o2::track::HugeF; } double chi2diag = 0., chi2ndiag = 0., - diff[o2::track::kNParams - 1] = {tr1.getParam(o2::track::kY) - tr2.getParam(o2::track::kY), - tr1.getParam(o2::track::kSnp) - tr2.getParam(o2::track::kSnp), - tr1.getParam(o2::track::kTgl) - tr2.getParam(o2::track::kTgl), - tr1.getParam(o2::track::kQ2Pt) - tr2.getParam(o2::track::kQ2Pt)}; + diff[o2::track::kNParams - 1] = {trITS.getParam(o2::track::kY) - trTPC.getParam(o2::track::kY), + trITS.getParam(o2::track::kSnp) - trTPC.getParam(o2::track::kSnp), + trITS.getParam(o2::track::kTgl) - trTPC.getParam(o2::track::kTgl), + trITS.getParam(o2::track::kQ2Pt) - trTPC.getParam(o2::track::kQ2Pt)}; for (int i = o2::track::kNParams - 1; i--;) { chi2diag += diff[i] * diff[i] * covMat(i, i); for (int j = i; j--;) { @@ -1353,8 +1366,16 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) // NOTE: the ITS cluster index is stored wrt 1st cluster of relevant ROF, while here we extract clusters from the // buffer for the whole TF. Therefore, we should shift the index by the entry of the ROF's 1st cluster in the global cluster buffer int clusIndOffs = mITSClusterROFRec[tITS.roFrame].getFirstEntry(); - int clEntry = itsTrOrig.getFirstClusterEntry(); + + float addErr2 = 0; + // extra error on tgl due to the assumed vdrift uncertainty + if (mVDriftCalibOn) { + addErr2 = tITS.getParam(o2::track::kTgl) * mParams->maxVDriftUncertainty; + addErr2 *= addErr2; + trfit.updateCov(addErr2, o2::track::kSigTgl2); + } + for (int icl = 0; icl < ncl; icl++) { const auto& clus = mITSClustersArray[clusIndOffs + mITSTrackClusIdx[clEntry++]]; float alpha = geom->getSensorRefAlpha(clus.getSensorID()), x = clus.getX(); @@ -1401,6 +1422,9 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) // outward refit auto& tracOut = trfit.getParamOut(); // this track is already at the matching reference X { + if (mVDriftCalibOn) { + tracOut.updateCov(addErr2, o2::track::kSigTgl2); + } int icl = tpcTrOrig.getNClusterReferences() - 1; uint8_t sector, prevsector, row, prevrow; uint32_t clusterIndexInRow; @@ -1529,6 +1553,15 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) // buffer for the whole TF. Therefore, we should shift the index by the entry of the ROF's 1st cluster in the global cluster buffer int clusIndOffs = mITSClusterROFRec[tITS.roFrame].getFirstEntry(); int clEntry = itsTrOrig.getFirstClusterEntry(); + + float addErr2 = 0; + // extra error on tgl due to the assumed vdrift uncertainty + if (mVDriftCalibOn) { + addErr2 = tITS.getParam(o2::track::kTgl) * mParams->maxVDriftUncertainty; + addErr2 *= addErr2; + trfit.updateCov(addErr2, o2::track::kSigTgl2); + } + for (int icl = 0; icl < ncl; icl++) { const auto& clus = mITSClustersArray[clusIndOffs + mITSTrackClusIdx[clEntry++]]; float alpha = geom->getSensorRefAlpha(clus.getSensorID()), x = clus.getX(); @@ -1582,6 +1615,9 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) // outward refit auto& tracOut = trfit.getParamOut(); // this track is already at the matching reference X { + if (mVDriftCalibOn) { + tracOut.updateCov(addErr2, o2::track::kSigTgl2); + } int icl = tpcTrOrig.getNClusterReferences() - 1; uint8_t sector, prevsector, row, prevrow; uint32_t clusterIndexInRow; diff --git a/Detectors/GlobalTracking/src/MatchTPCITSParams.cxx b/Detectors/GlobalTracking/src/MatchTPCITSParams.cxx index e0f046725c737..6783099b24074 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITSParams.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITSParams.cxx @@ -13,4 +13,4 @@ /// \author ruben.shahoyan@cern.ch #include "GlobalTracking/MatchTPCITSParams.h" -O2ParamImpl(o2::globaltracking::MatchITSTPCParams); +O2ParamImpl(o2::globaltracking::MatchTPCITSParams); From ffd7b973af68b5c8fe99940d243e24df7e77d5fb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 26 Oct 2020 23:36:56 +0100 Subject: [PATCH 1135/1751] Flat 1D and 2D messageable histo classes --- DataFormats/common/CMakeLists.txt | 16 +- .../include/CommonDataFormat/FlatHisto1D.h | 215 ++++++++++++ .../include/CommonDataFormat/FlatHisto2D.h | 305 ++++++++++++++++++ .../common/src/CommonDataFormatLinkDef.h | 10 + DataFormats/common/src/FlatHisto1D.cxx | 17 + DataFormats/common/src/FlatHisto2D.cxx | 17 + DataFormats/common/test/testFlatHisto.cxx | 79 +++++ 7 files changed, 656 insertions(+), 3 deletions(-) create mode 100644 DataFormats/common/include/CommonDataFormat/FlatHisto1D.h create mode 100644 DataFormats/common/include/CommonDataFormat/FlatHisto2D.h create mode 100644 DataFormats/common/src/FlatHisto1D.cxx create mode 100644 DataFormats/common/src/FlatHisto2D.cxx create mode 100644 DataFormats/common/test/testFlatHisto.cxx diff --git a/DataFormats/common/CMakeLists.txt b/DataFormats/common/CMakeLists.txt index 1a1e512672fa0..f1c4e4eda918e 100644 --- a/DataFormats/common/CMakeLists.txt +++ b/DataFormats/common/CMakeLists.txt @@ -9,9 +9,12 @@ # submit itself to any jurisdiction. o2_add_library(CommonDataFormat - SOURCES src/InteractionRecord.cxx src/BunchFilling.cxx + SOURCES src/InteractionRecord.cxx + src/BunchFilling.cxx + src/FlatHisto1D.cxx + src/FlatHisto2D.cxx PUBLIC_LINK_LIBRARIES O2::CommonConstants O2::GPUCommon - ROOT::Core FairRoot::Base) + ROOT::Core FairRoot::Base ms_gsl::ms_gsl) o2_target_root_dictionary(CommonDataFormat HEADERS include/CommonDataFormat/TimeStamp.h @@ -19,7 +22,9 @@ o2_target_root_dictionary(CommonDataFormat include/CommonDataFormat/RangeReference.h include/CommonDataFormat/InteractionRecord.h include/CommonDataFormat/BunchFilling.h - include/CommonDataFormat/AbstractRef.h) + include/CommonDataFormat/AbstractRef.h + include/CommonDataFormat/FlatHisto1D.h + include/CommonDataFormat/FlatHisto2D.h) o2_add_test(TimeStamp SOURCES test/testTimeStamp.cxx @@ -30,3 +35,8 @@ o2_add_test(RangeRef SOURCES test/testRangeRef.cxx COMPONENT_NAME CommonDataFormat PUBLIC_LINK_LIBRARIES O2::CommonDataFormat) + +o2_add_test(FlatHisto + SOURCES test/testFlatHisto.cxx + COMPONENT_NAME CommonDataFormat + PUBLIC_LINK_LIBRARIES O2::CommonDataFormat) diff --git a/DataFormats/common/include/CommonDataFormat/FlatHisto1D.h b/DataFormats/common/include/CommonDataFormat/FlatHisto1D.h new file mode 100644 index 0000000000000..18407f295cbf4 --- /dev/null +++ b/DataFormats/common/include/CommonDataFormat/FlatHisto1D.h @@ -0,0 +1,215 @@ +// 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 FlatHisto1D.h +/// \brief 1D messeageable histo class +/// \author ruben.shahoyan@cern.ch + +#ifndef ALICEO2_FLATHISTO1D_H +#define ALICEO2_FLATHISTO1D_H + +#include <Rtypes.h> +#include <vector> +#include <gsl/span> +#include <TH1F.h> +#include <type_traits> + +namespace o2 +{ +namespace dataformats +{ + +/* + Fast 1D histo class which can be messages as + FlatHisto1D<float> histo(nbins, xmin, xmax); + histo.fill(...); + pc.outputs().snapshot(Output{"Origin", "Desc", 0, Lifetime::Timeframe}, histo.getBase()); + + and received (read only!) as + const auto hdata = pc.inputs().get<gsl::span<float>>("histodata"); + FlatHisto1D<float> histoView; + histoView.adoptExternal(hdata); + or directly + FlatHisto1D<float> histoView(pc.inputs().get<gsl::span<float>>("histodata")); +*/ + +template <typename T = float> +class FlatHisto1D +{ + static_assert(std::is_same<T, float>::value || std::is_same<T, double>::value, "T must be float or double"); + + public: + enum { NBins, + XMin, + XMax, + BinSize, + BinSizeInv, + NServiceSlots }; + + FlatHisto1D() = default; + + FlatHisto1D(int nb, T xmin, T xmax) + { + assert(nb > 0 && xmin < xmax); + mData.resize(nb + NServiceSlots, 0.); + mData[NBins] = nb; + mData[XMin] = xmin; + mData[XMax] = xmax; + mData[BinSize] = (xmax - xmin) / nb; + mData[BinSizeInv] = nb / (xmax - xmin); + init(); + } + + FlatHisto1D(const gsl::span<const T> ext) + { + adoptExternal(ext); + } + + int getNBins() const { return mNBins; } + T getXMin() const { return mDataView[XMin]; } + T getXMax() const { return mDataView[XMax]; } + T getBinSize() const { return mDataView[BinSize]; } + T getBinContent(uint32_t ib) const { return ib < mNBins ? mDataView[ib + NServiceSlots] : 0.; } + T getBinContentForX(T x) const { getBinContent(getBin(x)); } + + T getBinStart(int i) const + { + assert(i < getNBins()); + return getXMin() + i * getBinSize(); + } + + T getBinCenter(int i) const + { + assert(i < getNBins()); + return getXMin() + (i + 0.5) * getBinSize(); + } + + T getBinEnd(int i) const + { + assert(i < getNBins()); + return getXMin() + (i + 1) * getBinSize(); + } + + void add(const FlatHisto1D& other) + { + assert(getNBins() == other.getNBins() && getXMin() == other.getXMin() && getXMax() == other.getXMax() && canFill()); + int last = NServiceSlots + getNBins(); + const auto& otherView = other.getView(); + for (int i = NServiceSlots; i < last; i++) { + mData[i] += otherView[i]; + } + } + + void subtract(const FlatHisto1D& other) + { + assert(getNBins() == other.getNBins() && getXMin() == other.getXMin() && getXMax() == other.getXMax() && canFill()); + int last = NServiceSlots + getNBins(); + const auto& otherView = other.getView(); + for (int i = NServiceSlots; i < last; i++) { + mData[i] -= otherView[i]; + } + } + + void setBinContent(uint32_t bin, T w) + { + assert(canFill() && bin < mNBins); + mData[bin + NServiceSlots] = w; + } + + void clear() + { + assert(canFill()); + memset(mData.data() + NServiceSlots, 0, sizeof(T) * getNBins()); + } + + T getSum() const + { + T sum = 0; + for (int i = getNBins(); i--;) { + sum += getBinContent(i); + } + return sum; + } + + void adoptExternal(const gsl::span<const T> ext) + { + assert(ext.size() > NServiceSlots); + mData.clear(); + mDataView = ext; + mNBins = (int)mDataView[NBins]; + } + + void init() + { // when reading from file, need to call this method to make it operational + assert(mData.size() > NServiceSlots); + mDataView = gsl::span<const T>(mData.data(), mData.size()); + mNBins = (int)mData[NBins]; + } + + void fill(T x) + { + uint32_t bin = getBin(x); + if (bin < mNBins) { + mData[NServiceSlots + bin]++; + } + } + + void fill(T x, T w) + { + uint32_t bin = getBin(x); + if (bin < mNBins) { + mData[NServiceSlots + bin] += w; + } + } + + uint32_t getBin(T x) const + { + auto dx = x - getXMin(); + return dx < 0 ? 0xffffffff : uint32_t(dx * getBinSizeInv()); + } + + bool canFill() const + { + // histo can be filled only if hase its own data, otherwise only query can be done on the view + return mData.size() > NServiceSlots; + } + + TH1F createTH1F(const std::string& name = "histo1d") + { + TH1F h(name.c_str(), name.c_str(), getNBins(), getXMin(), getXMax()); + for (int i = getNBins(); i--;) { + auto w = getBinContent(i); + if (w) { + h.SetBinContent(i + 1, w); + } + } + return h; + } + + const std::vector<T>& getBase() const { return mData; } + gsl::span<const T> getView() const { return mDataView; } + + protected: + T getBinSizeInv() const { return mDataView[BinSizeInv]; } + + std::vector<T> mData; // data to fill + gsl::span<const T> mDataView; //! + int mNBins = 0; //! + + ClassDefNV(FlatHisto1D, 1); +}; + +using FlatHisto1D_f = FlatHisto1D<float>; +using FlatHisto1D_d = FlatHisto1D<double>; + +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/DataFormats/common/include/CommonDataFormat/FlatHisto2D.h b/DataFormats/common/include/CommonDataFormat/FlatHisto2D.h new file mode 100644 index 0000000000000..8da1daf658162 --- /dev/null +++ b/DataFormats/common/include/CommonDataFormat/FlatHisto2D.h @@ -0,0 +1,305 @@ +// 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 FlatHisto2D.h +/// \brief 2D messeageable histo class +/// \author ruben.shahoyan@cern.ch + +#ifndef ALICEO2_FLATHISTO2D_H +#define ALICEO2_FLATHISTO2D_H + +#include <Rtypes.h> +#include <vector> +#include <gsl/span> +#include <TH2F.h> +#include <type_traits> + +namespace o2 +{ +namespace dataformats +{ + +/* + Fast 2D histo class which can be messages as + FlatHisto2D<float> histo(nbinsX, xmin, xmax, nbinsY, ymin, ymax); + histo.fill(...); + pc.outputs().snapshot(Output{"Origin", "Desc", 0, Lifetime::Timeframe}, histo.getBase()); + + and received (read only!) as + const auto hdata = pc.inputs().get<gsl::span<float>>("histodata"); + FlatHisto2D<float> histoView; + histoView.adoptExternal(hdata); + or directly + FlatHisto2D<float> histoView(pc.inputs().get<gsl::span<float>>("histodata")); +*/ + +template <typename T = float> +class FlatHisto2D +{ + static_assert(std::is_same<T, float>::value || std::is_same<T, double>::value, "T must be float or double"); + + public: + enum { NBinsX, + NBinsY, + XMin, + XMax, + YMin, + YMax, + BinSizeX, + BinSizeY, + BinSizeXInv, + BinSizeYInv, + NServiceSlots }; + + FlatHisto2D() = default; + + FlatHisto2D(int nbx, T xmin, T xmax, int nby, T ymin, T ymax) + { + assert(nbx > 0 && xmin < xmax); + assert(nby > 0 && ymin < ymax); + mData.resize(nbx * nby + NServiceSlots, 0.); + mData[NBinsX] = nbx; + mData[NBinsY] = nby; + mData[XMin] = xmin; + mData[XMax] = xmax; + mData[YMin] = ymin; + mData[YMax] = ymax; + mData[BinSizeX] = (xmax - xmin) / nbx; + mData[BinSizeXInv] = nbx / (xmax - xmin); + mData[BinSizeY] = (ymax - ymin) / nby; + mData[BinSizeYInv] = nby / (ymax - ymin); + init(); + } + + FlatHisto2D(const gsl::span<const T> ext) + { + adoptExternal(ext); + } + + int getNBinsX() const { return mNBinsX; } + int getNBinsY() const { return mNBinsY; } + int getNBins() const { return mNBins; } + T getXMin() const { return mDataView[XMin]; } + T getXMax() const { return mDataView[XMax]; } + T getYMin() const { return mDataView[YMin]; } + T getYMax() const { return mDataView[YMax]; } + T getBinSizeX() const { return mDataView[BinSizeX]; } + T getBinSizeY() const { return mDataView[BinSizeY]; } + T getBinContent(uint32_t ib) const { return ib < mNBins ? mDataView[ib + NServiceSlots] : 0.; } + T getBinContent(uint32_t ibx, uint32_t iby) const { return getBinContent(getGlobalBin(ibx, iby)); } + T getBinContentForXY(T x, T y) const { return getBinContent(getBinX(x), getBinY(y)); } + + T getBinStartX(int i) const + { + assert(i < getNBinsX()); + return getXMin() + i * getBinSizeX(); + } + + T getBinCenterX(int i) const + { + assert(i < getNBinsX()); + return getXMin() + (i + 0.5) * getBinSizeX(); + } + + T getBinEndX(int i) const + { + assert(i < getNBinsX()); + return getXMin() + (i + 1) * getBinSizeX(); + } + + T getBinStartY(int i) const + { + assert(i < getNBinsY()); + return getYMin() + i * getBinSizeY(); + } + + T getBinCenterY(int i) const + { + assert(i < getNBinsY()); + return getYMin() + (i + 0.5) * getBinSizeY(); + } + + T getBinEndY(int i) const + { + assert(i < getNBinsY()); + return getYMin() + (i + 1) * getBinSizeY(); + } + + void add(const FlatHisto2D& other) + { + assert(getNBinsX() == other.getNBinsX() && getXMin() == other.getXMin() && getXMax() == other.getXMax() && + getNBinsY() == other.getNBinsY() && getYMin() == other.getYMin() && getYMax() == other.getYMax() && + canFill()); + int last = NServiceSlots + getNBins(); + const auto& otherView = other.getView(); + for (int i = NServiceSlots; i < last; i++) { + mData[i] += otherView[i]; + } + } + + void subtract(const FlatHisto2D& other) + { + assert(getNBinsX() == other.getNBinsX() && getXMin() == other.getXMin() && getXMax() == other.getXMax() && + getNBinsY() == other.getNBinsY() && getYMin() == other.getYMin() && getYMax() == other.getYMax() && + canFill()); + int last = NServiceSlots + getNBins(); + const auto& otherView = other.getView(); + for (int i = NServiceSlots; i < last; i++) { + mData[i] -= otherView[i]; + } + } + + void setBinContent(uint32_t bin, T w) + { + assert(canFill()); + if (bin < getNBins()) { + mData[bin + NServiceSlots] = w; + } + } + + void setBinContent(uint32_t binX, uint32_t binY, T w) + { + assert(canFill()); + auto bin = getGlobalBin(binX, binY); + if (bin < getNBins()) { + mData[+NServiceSlots] = w; + } + } + + void clear() + { + assert(canFill()); + memset(mData.data() + NServiceSlots, 0, sizeof(T) * getNBins()); + } + + T getSum() const + { + T sum = 0; + for (int i = getNBins(); i--;) { + sum += getBinContent(i); + } + return sum; + } + + void adoptExternal(const gsl::span<const T> ext) + { + assert(ext.size() > NServiceSlots); + mData.clear(); + mDataView = ext; + mNBinsX = (int)mDataView[NBinsX]; + mNBinsY = (int)mDataView[NBinsY]; + mNBins = mNBinsX * mNBinsY; + } + + void init() + { // when reading from file, need to call this method to make it operational + assert(mData.size() > NServiceSlots); + mDataView = gsl::span<const T>(mData.data(), mData.size()); + mNBinsX = (int)mData[NBinsX]; + mNBinsY = (int)mData[NBinsY]; + mNBins = mNBinsX * mNBinsY; + } + + void fill(T x, T y) + { + uint32_t bin = getBin(x, y); + if (bin < mNBins) { + mData[NServiceSlots + bin]++; + } + } + + void fill(T x, T y, T w) + { + uint32_t bin = getBin(x, y); + if (bin < mNBins) { + mData[NServiceSlots + bin] += w; + } + } + + uint32_t getBinX(T x) const + { + auto dx = x - getXMin(); + return dx < 0 ? 0xffffffff : uint32_t(dx * getBinSizeXInv()); + } + + uint32_t getBinY(T y) const + { + auto dy = y - getYMin(); + return dy < 0 ? 0xffffffff : uint32_t(dy * getBinSizeYInv()); + } + + uint32_t getBin(T x, T y) const + { + auto bx = getBinX(x), by = getBinY(y); + return bx < getNBinsX() && by < getNBinsY() ? getGlobalBin(bx, by) : 0xffffffff; + } + + bool canFill() const + { + // histo can be filled only if hase its own data, otherwise only query can be done on the view + return mData.size() > NServiceSlots; + } + + gsl::span<const T> getSliceY(uint32_t binX) const + { + int offs = NServiceSlots + binX * getNBinsY(); + return binX < getNBinsX() ? gsl::span<const T>(&mDataView[offs], getNBinsY()) : gsl::span<const T>(); + } + + TH1F createSliceYTH1F(uint32_t binX, const std::string& name = "histo2dslice") const + { + TH1F h(name.c_str(), name.c_str(), getNBinsY(), getYMin(), getYMax()); + if (binX < getNBinsX()) { + for (int i = getNBinsY(); i--;) { + h.SetBinContent(i + 1, getBinContent(binX, i)); + } + } + return h; + } + + TH2F createTH2F(const std::string& name = "histo2d") + { + TH2F h(name.c_str(), name.c_str(), getNBinsX(), getXMin(), getXMax(), getNBinsY(), getYMin(), getYMax()); + for (int i = getNBinsX(); i--;) { + for (int j = getNBinsY(); j--;) { + auto w = getBinContent(i, j); + if (w) { + h.SetBinContent(i + 1, j + 1, w); + } + } + } + return h; + } + + const std::vector<T>& getBase() const { return mData; } + gsl::span<const T> getView() const { return mDataView; } + + int getGlobalBin(uint32_t binX, uint32_t binY) const { return binX * getNBinsY() + binY; } + + protected: + T getBinSizeXInv() const { return mDataView[BinSizeXInv]; } + T getBinSizeYInv() const { return mDataView[BinSizeYInv]; } + + std::vector<T> mData; // data to fill + gsl::span<const T> mDataView; //! + int mNBinsX = 0; //! + int mNBinsY = 0; //! + int mNBins = 0; //! + + ClassDefNV(FlatHisto2D, 1); +}; + +using FlatHisto2D_f = FlatHisto2D<float>; +using FlatHisto2D_d = FlatHisto2D<double>; + +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/DataFormats/common/src/CommonDataFormatLinkDef.h b/DataFormats/common/src/CommonDataFormatLinkDef.h index 502697b733e6d..d4503c6722057 100644 --- a/DataFormats/common/src/CommonDataFormatLinkDef.h +++ b/DataFormats/common/src/CommonDataFormatLinkDef.h @@ -48,4 +48,14 @@ #pragma link C++ class o2::dataformats::AbstractRef < 26, 3, 3> + ; +#pragma link C++ class o2::dataformats::FlatHisto1D < float> + ; +#pragma link C++ class o2::dataformats::FlatHisto1D < double> + ; +#pragma link C++ class o2::dataformats::FlatHisto1D_f + ; +#pragma link C++ class o2::dataformats::FlatHisto1D_d + ; + +#pragma link C++ class o2::dataformats::FlatHisto2D < float> + ; +#pragma link C++ class o2::dataformats::FlatHisto2D < double> + ; +#pragma link C++ class o2::dataformats::FlatHisto2D_f + ; +#pragma link C++ class o2::dataformats::FlatHisto2D_d + ; + #endif diff --git a/DataFormats/common/src/FlatHisto1D.cxx b/DataFormats/common/src/FlatHisto1D.cxx new file mode 100644 index 0000000000000..0b59cd2b8259d --- /dev/null +++ b/DataFormats/common/src/FlatHisto1D.cxx @@ -0,0 +1,17 @@ +// 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 FlatHisto1D.cxx +/// \brief 1D messeageable histo class +/// \author ruben.shahoyan@cern.ch + +#include "CommonDataFormat/FlatHisto1D.h" + +using namespace o2::dataformats; diff --git a/DataFormats/common/src/FlatHisto2D.cxx b/DataFormats/common/src/FlatHisto2D.cxx new file mode 100644 index 0000000000000..3266a23b81fd3 --- /dev/null +++ b/DataFormats/common/src/FlatHisto2D.cxx @@ -0,0 +1,17 @@ +// 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 FlatHisto1D.cxx +/// \brief 2D messeageable histo class +/// \author ruben.shahoyan@cern.ch + +#include "CommonDataFormat/FlatHisto2D.h" + +using namespace o2::dataformats; diff --git a/DataFormats/common/test/testFlatHisto.cxx b/DataFormats/common/test/testFlatHisto.cxx new file mode 100644 index 0000000000000..d1f9a56cdfd05 --- /dev/null +++ b/DataFormats/common/test/testFlatHisto.cxx @@ -0,0 +1,79 @@ +// 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. + +#define BOOST_TEST_MODULE Test FlatHisto class +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "CommonDataFormat/FlatHisto1D.h" +#include "CommonDataFormat/FlatHisto2D.h" +#include <TFile.h> +#include <TRandom.h> +#include <TFitResult.h> + +namespace o2 +{ + +// basic Vertex tests +BOOST_AUTO_TEST_CASE(FlatHisto) +{ + o2::dataformats::FlatHisto1D_f h1(100, -100., 100.); + o2::dataformats::FlatHisto2D_f h2(100, -100., 100., 50, -5., 45.); + for (int i = 0; i < 1000000; i++) { + h1.fill(gRandom->Gaus(10, 30)); + } + auto h2ref = h2.createTH2F("h2ref"); + for (int i = 0; i < 10000000; i++) { + auto x = gRandom->Gaus(10, 40), y = gRandom->Gaus(10, 10); + h2.fill(x, y); + h2ref.Fill(x, y); + } + auto th1f = h1.createTH1F(); + auto res = th1f.Fit("gaus", "S"); + BOOST_CHECK_CLOSE(res->GetParams()[1], 10, 0.2); + + printf("%e %e\n", h2.getSum(), h2ref.Integral()); + BOOST_CHECK(h2.getSum() == h2ref.Integral()); + + o2::dataformats::FlatHisto1D_f h1v(h1); + + BOOST_CHECK_CLOSE(h1.getBinStart(0), -100, 1e-5); + BOOST_CHECK_CLOSE(h1.getBinEnd(h1.getNBins() - 1), 100, 1e-5); + + BOOST_CHECK_CLOSE(h2.getBinStartX(0), -100, 1e-5); + BOOST_CHECK_CLOSE(h2.getBinEndY(h2.getNBinsY() - 1), 45, 1e-5); + BOOST_CHECK_CLOSE(h2.getBinStartY(h2.getNBinsY() - 1), 45 - h2.getBinSizeY(), 1e-5); + + BOOST_CHECK(h1.canFill() && h1v.canFill()); + BOOST_CHECK(h1.getSum() == h1v.getSum()); + { + TFile flout("flathisto.root", "recreate"); + flout.WriteObjectAny(&h1, "o2::dataformats::FlatHisto1D_f", "h1"); + flout.WriteObjectAny(&h2, "o2::dataformats::FlatHisto2D_f", "h2"); + flout.Close(); + } + + TFile flin("flathisto.root"); + o2::dataformats::FlatHisto1D_f* h1r = (o2::dataformats::FlatHisto1D_f*)flin.GetObjectUnchecked("h1"); + o2::dataformats::FlatHisto2D_f* h2r = (o2::dataformats::FlatHisto2D_f*)flin.GetObjectUnchecked("h2"); + flin.Close(); + h1r->init(); + h2r->init(); + + o2::dataformats::FlatHisto1D_f h1vv; + h1vv.adoptExternal(h1r->getView()); + BOOST_CHECK(h1.getSum() == h1vv.getSum()); + h1.add(h1vv); + h2.subtract(*h2r); + BOOST_CHECK(h1.getSum() == 2 * h1vv.getSum()); + BOOST_CHECK(h2.getSum() == 0.); +} + +} // namespace o2 From 97608f01e4efd03aa0fb47f47eda820d49578925 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 27 Oct 2020 14:07:01 +0100 Subject: [PATCH 1136/1751] Optionally fill TPC VDrift calib info in TPC matching --- .../include/GlobalTracking/MatchTPCITS.h | 13 ++++++++++++- .../include/GlobalTracking/MatchTPCITSParams.h | 4 ++++ Detectors/GlobalTracking/src/MatchTPCITS.cxx | 14 +++++++++++++- .../MatchTPCITSWorkflow.h | 2 +- .../GlobalTrackingWorkflow/TPCITSMatchingSpec.h | 5 +++-- .../src/MatchTPCITSWorkflow.cxx | 4 ++-- .../src/TPCITSMatchingSpec.cxx | 17 +++++++++++++++-- .../src/tpcits-match-workflow.cxx | 4 +++- 8 files changed, 53 insertions(+), 10 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 359e0f53c85ff..0ba1d951e0371 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -46,6 +46,7 @@ #include "ITSReconstruction/RecoGeomHelper.h" #include "TPCFastTransform.h" #include "GlobalTracking/MatchTPCITSParams.h" +#include "CommonDataFormat/FlatHisto2D.h" class TTree; @@ -353,6 +354,15 @@ class MatchTPCITS mMCTruthON = v; } + ///< request VDrift calibration + void setVDriftCalib(bool v) + { + mVDriftCalibOn = v; + } + + ///< get histo for tgl differences for VDrift calibration + auto getHistoDTgl() { return mHistoDTgl.get(); } + ///< set input ITS tracks void setITSTracksInp(const gsl::span<const o2::its::TrackITS> inp) { @@ -635,7 +645,8 @@ class MatchTPCITS float mMinTPCTrackPtInv = 999.; ///< cutoff on TPC track inverse pT float mMinITSTrackPtInv = 999.; ///< cutoff on ITS track inverse pT - bool mVDriftCalibOn = false; ///< flag to produce VDrift calibration data + bool mVDriftCalibOn = false; ///< flag to produce VDrift calibration data + std::unique_ptr<o2::dataformats::FlatHisto2D_f> mHistoDTgl; ///< histo for VDrift calibration data std::unique_ptr<TPCTransform> mTPCTransform; ///< TPC cluster transformation std::unique_ptr<o2::gpu::GPUParam> mTPCClusterParam; ///< TPC clusters error param diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h index dceee1989c669..c10f2c13b1621 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h @@ -57,6 +57,10 @@ struct MatchTPCITSParams : public o2::conf::ConfigurableParamHelper<MatchTPCITSP float maxVDriftUncertainty = 0.; ///< max assumed VDrift uncertainty, used only in VDrift calibration mode + float maxTglForVDriftCalib = 1.; ///< maximum ITS tgl to collect data for VDrift calibration + int nBinsTglVDriftCalib = 50; ///< number of bins in reference ITS tgl for VDrift calibration + int nBinsDTglVDriftCalib = 100; ///< number of bins in delta tgl for VDrift calibration + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; /// Material correction type O2ParamDef(MatchTPCITSParams, "tpcitsMatch"); diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index fa9a7d8faa0e5..7a1903602381c 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -352,7 +352,11 @@ void MatchTPCITS::init() mMinTPCTrackPtInv = (mFieldON && mParams->minTPCTrackR > 0) ? 1. / std::abs(mParams->minTPCTrackR * bz * o2::constants::math::B2C) : 999.; mMinITSTrackPtInv = (mFieldON && mParams->minITSTrackR > 0) ? 1. / std::abs(mParams->minITSTrackR * bz * o2::constants::math::B2C) : 999.; - mVDriftCalibOn = mParams->maxVDriftUncertainty > 0.; + if (mVDriftCalibOn) { + float maxDTgl = std::min(0.02f, mParams->maxVDriftUncertainty) * mParams->maxTglForVDriftCalib; + mHistoDTgl = std::make_unique<o2::dataformats::FlatHisto2D_f>(mParams->nBinsTglVDriftCalib, -mParams->maxTglForVDriftCalib, mParams->maxTglForVDriftCalib, + mParams->nBinsDTglVDriftCalib, -maxDTgl, maxDTgl); + } #ifdef _ALLOW_DEBUG_TREES_ // debug streamer @@ -1707,6 +1711,14 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) mOutTPCLabels.emplace_back(mTPCLblWork[iTPC]); } + // if requested, fill the difference of ITS and TPC tracks tgl for vdrift calibation + if (mHistoDTgl) { + auto tglITS = tITS.getTgl(); + if (std::abs(tglITS) < mHistoDTgl->getXMax()) { + auto dTgl = tglITS - tTPC.getTgl(); + mHistoDTgl->fill(tglITS, dTgl); + } + } // trfit.print(); // DBG return true; diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h index 4dad9f6506780..cc9f9d3b7a403 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/MatchTPCITSWorkflow.h @@ -20,7 +20,7 @@ namespace o2 namespace globaltracking { -framework::WorkflowSpec getMatchTPCITSWorkflow(bool useFT0, bool useMC, bool disableRootInp, bool disableRootOut); +framework::WorkflowSpec getMatchTPCITSWorkflow(bool useFT0, bool calib, bool useMC, bool disableRootInp, bool disableRootOut); } // namespace globaltracking } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h index dd6c561182bf4..3d63a7b26257b 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TPCITSMatchingSpec.h @@ -32,7 +32,7 @@ namespace globaltracking class TPCITSMatchingDPL : public Task { public: - TPCITSMatchingDPL(bool useFT0, bool useMC) : mUseFT0(useFT0), mUseMC(useMC) {} + TPCITSMatchingDPL(bool useFT0, bool calib, bool useMC) : mUseFT0(useFT0), mCalibMode(calib), mUseMC(useMC) {} ~TPCITSMatchingDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -42,12 +42,13 @@ class TPCITSMatchingDPL : public Task o2::globaltracking::MatchTPCITS mMatching; // matching engine o2::itsmft::TopologyDictionary mITSDict; // cluster patterns dictionary bool mUseFT0 = false; + bool mCalibMode = false; bool mUseMC = true; TStopwatch mTimer; }; /// create a processor spec -framework::DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool useMC, const std::vector<int>& tpcClusLanes); +framework::DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool calib, bool useMC, const std::vector<int>& tpcClusLanes); } // namespace globaltracking } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx b/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx index de2e206045298..dd5930b3d0d28 100644 --- a/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx @@ -27,7 +27,7 @@ namespace o2 namespace globaltracking { -framework::WorkflowSpec getMatchTPCITSWorkflow(bool useFT0, bool useMC, bool disableRootInp, bool disableRootOut) +framework::WorkflowSpec getMatchTPCITSWorkflow(bool useFT0, bool useMC, bool disableRootInp, bool disableRootOut, bool calib) { framework::WorkflowSpec specs; @@ -57,7 +57,7 @@ framework::WorkflowSpec getMatchTPCITSWorkflow(bool useFT0, bool useMC, bool dis specs.emplace_back(o2::ft0::getRecPointReaderSpec(useMC)); } } - specs.emplace_back(o2::globaltracking::getTPCITSMatchingSpec(useFT0, useMC, tpcClusLanes)); + specs.emplace_back(o2::globaltracking::getTPCITSMatchingSpec(useFT0, calib, useMC, tpcClusLanes)); if (!disableRootOut) { specs.emplace_back(o2::globaltracking::getTrackWriterTPCITSSpec(useMC)); diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index 5776401f66e87..6cf75338fea35 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -36,6 +36,7 @@ #include "DataFormatsParameters/GRPObject.h" #include "Headers/DataHeader.h" #include "CommonDataFormat/BunchFilling.h" +#include "CommonDataFormat/FlatHisto2D.h" // RSTODO to remove once the framework will start propagating the header.firstTForbit #include "DetectorsRaw/HBFUtils.h" @@ -66,6 +67,7 @@ void TPCITSMatchingDPL::init(InitContext& ic) } mMatching.setMCTruthOn(mUseMC); mMatching.setUseFT0(mUseFT0); + mMatching.setVDriftCalib(mCalibMode); // std::string dictPath = ic.options().get<std::string>("its-dictionary-path"); std::string dictFile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::ITS, dictPath, ".bin"); @@ -269,6 +271,13 @@ void TPCITSMatchingDPL::run(ProcessingContext& pc) pc.outputs().snapshot(Output{"GLO", "TPCITS_ITSMC", 0, Lifetime::Timeframe}, mMatching.getMatchedITSLabels()); pc.outputs().snapshot(Output{"GLO", "TPCITS_TPCMC", 0, Lifetime::Timeframe}, mMatching.getMatchedTPCLabels()); } + + if (mCalibMode) { + auto* hdtgl = mMatching.getHistoDTgl(); + pc.outputs().snapshot(Output{"GLO", "TPCITS_VDHDTGL", 0, Lifetime::Timeframe}, (*hdtgl).getBase()); + hdtgl->clear(); + } + mTimer.Stop(); } @@ -278,7 +287,7 @@ void TPCITSMatchingDPL::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool useMC, const std::vector<int>& tpcClusLanes) +DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool calib, bool useMC, const std::vector<int>& tpcClusLanes) { std::vector<InputSpec> inputs; @@ -300,6 +309,10 @@ DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool useMC, const std::vect outputs.emplace_back("GLO", "TPCITS", 0, Lifetime::Timeframe); + if (calib) { + outputs.emplace_back("GLO", "TPCITS_VDHDTGL", 0, Lifetime::Timeframe); + } + if (useMC) { inputs.emplace_back("trackITSMCTR", "ITS", "TRACKSMCTR", 0, Lifetime::Timeframe); inputs.emplace_back("trackTPCMCTR", "TPC", "TRACKSMCLBL", 0, Lifetime::Timeframe); @@ -313,7 +326,7 @@ DataProcessorSpec getTPCITSMatchingSpec(bool useFT0, bool useMC, const std::vect "itstpc-track-matcher", inputs, outputs, - AlgorithmSpec{adaptFromTask<TPCITSMatchingDPL>(useFT0, useMC)}, + AlgorithmSpec{adaptFromTask<TPCITSMatchingDPL>(useFT0, calib, useMC)}, Options{ {"its-dictionary-path", VariantType::String, "", {"Path of the cluster-topology dictionary file"}}, {"material-lut-path", VariantType::String, "", {"Path of the material LUT file"}}, diff --git a/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx index 656ce73af2e84..0a1025134841b 100644 --- a/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx @@ -26,6 +26,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}, {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, + {"produce-calibration-data", o2::framework::VariantType::Bool, false, {"produce output for TPC vdrift calibration"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; std::swap(workflowOptions, options); @@ -57,5 +58,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto useMC = !configcontext.options().get<bool>("disable-mc"); auto disableRootInp = configcontext.options().get<bool>("disable-root-input"); auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); - return std::move(o2::globaltracking::getMatchTPCITSWorkflow(useFT0, useMC, disableRootInp, disableRootOut)); + auto calib = configcontext.options().get<bool>("produce-calibration-data"); + return std::move(o2::globaltracking::getMatchTPCITSWorkflow(useFT0, useMC, disableRootInp, disableRootOut, calib)); } From a6fee28ca84e86ebe187d8ee01b95311b5a876e5 Mon Sep 17 00:00:00 2001 From: Paul Buehler <pbuehler@users.noreply.github.com> Date: Wed, 28 Oct 2020 20:44:01 +0100 Subject: [PATCH 1137/1751] enable using file names with leading file:// (#4705) --- Framework/Core/src/DataInputDirector.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index a4ec70289a284..09e0479bab585 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -68,8 +68,11 @@ std::regex DataInputDescriptor::getFilenamesRegex() void DataInputDescriptor::addFileNameHolder(FileNameHolder* fn) { - if (!mAlienSupport && fn->fileName.rfind("alien://", 0) == 0) { - LOG(debug) << "AliEn file requested. Enabling support."; + // remove leading file:// from file name + if (fn->fileName.rfind("file://", 0) == 0) { + fn->fileName.erase(0, 7); + } else if (!mAlienSupport && fn->fileName.rfind("alien://", 0) == 0) { + LOGP(DEBUG, "AliEn file requested. Enabling support."); TGrid::Connect("alien://"); mAlienSupport = true; } From fe44badea180014bea1dd170033926f4d0949c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Wed, 28 Oct 2020 20:44:25 +0100 Subject: [PATCH 1138/1751] Add plot of track length to trackqa task (#4698) --- Analysis/Tasks/trackqa.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 27e21d0b80753..ae4b64cd5275e 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -67,6 +67,7 @@ struct TrackQATask { histos.add("TrackPar/flags", "track flag;flag bit", kTH1D, {{64, -0.5, 63.5}}); histos.add("TrackPar/dcaXY", "distance of closest approach in #it{xy} plane;#it{dcaXY} [cm];", kTH1D, {{200, -0.15, 0.15}}); histos.add("TrackPar/dcaZ", "distance of closest approach in #it{z};#it{dcaZ} [cm];", kTH1D, {{200, -0.15, 0.15}}); + histos.add("TrackPar/length", "track length in cm;#it{Length} [cm];", kTH1D, {{400, 0, 1000}}); // its histograms histos.add("ITS/itsNCls", "number of found ITS clusters;# clusters ITS", kTH1D, {{8, -0.5, 7.5}}); @@ -105,6 +106,7 @@ struct TrackQATask { } histos.fill("TrackPar/dcaXY", track.dcaXY()); histos.fill("TrackPar/dcaZ", track.dcaZ()); + histos.fill("TrackPar/length", track.length()); // fill ITS variables histos.fill("ITS/itsNCls", track.itsNCls()); From 45ae1de2e4eedeb6cebadf0389f886219cbfc36b Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 28 Oct 2020 20:45:01 +0100 Subject: [PATCH 1139/1751] HistogramRegistry: add sanity check for histogram names (#4700) --- .../include/Framework/HistogramRegistry.h | 133 ++++++++++-------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 2e6f147c28d9d..640d2841de2be 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -315,6 +315,7 @@ struct HistFactory { } return std::nullopt; } + template <typename T, typename Next, typename... Rest> static std::optional<HistPtr> castToVariant(std::shared_ptr<TObject> obj) { @@ -323,6 +324,7 @@ struct HistFactory { } return castToVariant<Next, Rest...>(obj); } + static std::optional<HistPtr> castToVariant(std::shared_ptr<TObject> obj) { if (obj) { @@ -453,23 +455,10 @@ class HistogramRegistry template <typename T> auto& get(char const* const name) { - const uint32_t id = compile_time_hash(name); - const uint32_t i = imask(id); - if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { - if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[i])) - return *histPtr; - else - throw runtime_error("Histogram type specified in get() does not match actual histogram type!"); - } - for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { - if (id == mRegistryKey[imask(j + i)]) { - if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[imask(j + i)])) - return *histPtr; - else - throw runtime_error("Histogram type specified in get() does not match actual histogram type!"); - } - } - throw runtime_error("No matching histogram found in HistogramRegistry!"); + if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[getHistIndex(name)])) + return *histPtr; + else + throw runtime_error("Histogram type specified in get() does not match actual histogram type!"); } /// @return the histogram registered with name @a name @@ -555,21 +544,10 @@ class HistogramRegistry template <bool useWeight = false, typename... Ts> void fill(char const* const name, Ts&&... positionAndWeight) { - const uint32_t id = compile_time_hash(name); - const uint32_t i = imask(id); - if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { - std::visit([this, &positionAndWeight...](auto&& hist) { HistFiller::fillHistAny<useWeight>(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[i]); - return; - } - for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { - if (id == mRegistryKey[imask(j + i)]) { - std::visit([this, &positionAndWeight...](auto&& hist) { HistFiller::fillHistAny<useWeight>(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[imask(j + i)]); - return; - } - } - LOGF(FATAL, "No histogram called %s found in HistogramRegistry %s!", name, mName); + std::visit([&positionAndWeight...](auto&& hist) { HistFiller::fillHistAny<useWeight>(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[getHistIndex(name)]); } + // fill hist with values and weight template <typename... Ts> void fillWeight(char const* const name, Ts&&... positionAndWeight) { @@ -583,32 +561,14 @@ class HistogramRegistry fillTable<false, Cs...>(name, table, filter); } + // fill hist with content of (filtered) table columns and weight template <typename... Cs, typename T> void fillWeight(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) { fillTable<true, Cs...>(name, table, filter); } - // this is for internal use only because we dont want user to have to specify 'useWeight' argument - template <bool useWeight = false, typename... Cs, typename T> - void fillTable(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) - { - const uint32_t id = compile_time_hash(name); - const uint32_t i = imask(id); - if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { - std::visit([this, &table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<useWeight, Cs...>(hist, table, filter); }, mRegistryValue[i]); - return; - } - for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { - if (id == mRegistryKey[imask(j + i)]) { - std::visit([this, &table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<useWeight, Cs...>(hist, table, filter); }, mRegistryValue[imask(j + i)]); - return; - } - } - LOGF(FATAL, "No histogram called %s found in HistogramRegistry %s!", name, mName); - } - - /// lookup distance counter for benchmarking + // lookup distance counter for benchmarking mutable uint32_t lookup = 0; private: @@ -620,6 +580,7 @@ class HistogramRegistry TObject* rawPtr = nullptr; std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); if (!rawPtr) { + registerName(histSpec.name); mRegistryKey[imask(j + i)] = histSpec.id; mRegistryValue[imask(j + i)] = HistFactory::createHistVariant(histSpec); lookup += j; @@ -639,6 +600,7 @@ class HistogramRegistry TObject* rawPtr = nullptr; std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); if (!rawPtr) { + registerName(name); mRegistryKey[imask(j + i)] = id; mRegistryValue[imask(j + i)] = std::shared_ptr<T>(static_cast<T*>(originalHist->Clone(name))); lookup += j; @@ -653,19 +615,43 @@ class HistogramRegistry return i & MASK; } + uint32_t getHistIndex(char const* const name) + { + const uint32_t id = compile_time_hash(name); + const uint32_t i = imask(id); + if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { + return i; + } + for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { + if (id == mRegistryKey[imask(j + i)]) { + return imask(j + i); + } + } + throw runtime_error("No matching histogram found in HistogramRegistry!"); + } + + // this is for internal use only because we dont want user to have to specify 'useWeight' argument + template <bool useWeight = false, typename... Cs, typename T> + void fillTable(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + { + std::visit([&table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<useWeight, Cs...>(hist, table, filter); }, mRegistryValue[getHistIndex(name)]); + } + // helper function to create resp. find the subList defined by path - TList* getSubList(TList* list, std::deque<std::string> path) + TList* getSubList(TList* list, std::deque<std::string>& path) { - if (path.empty()) + if (path.empty()) { return list; + } TList* targetList{nullptr}; std::string nextList = path[0]; path.pop_front(); if (auto subList = (TList*)list->FindObject(nextList.data())) { - if (subList->InheritsFrom(TList::Class())) + if (subList->InheritsFrom(TList::Class())) { targetList = getSubList((TList*)subList, path); - else + } else { return nullptr; + } } else { subList = new TList(); subList->SetName(nextList.data()); @@ -676,7 +662,7 @@ class HistogramRegistry } // helper function to split user defined path/to/hist/name string - std::deque<std::string> splitPath(std::string pathAndNameUser) + std::deque<std::string> splitPath(const std::string& pathAndNameUser) { std::istringstream pathAndNameStream(pathAndNameUser); std::deque<std::string> pathAndName; @@ -687,14 +673,47 @@ class HistogramRegistry return pathAndName; } + // helper function that checks if name of histogram is reasonable and keeps track of names already in use + void registerName(const std::string& name) + { + if (name.empty() || name.back() == '/') { + LOGF(FATAL, "Invalid name for a histogram."); + } + std::deque<std::string> path = splitPath(name); + std::string cumulativeName{}; + int depth = path.size(); + for (auto& step : path) { + if (step.empty()) { + LOGF(FATAL, "Found empty group name in path for histogram %s.", name); + } + cumulativeName += step; + for (auto& curName : mRegisteredNames) { + // there is already a histogram where we want to put a folder or histogram + if (cumulativeName == curName) { + LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); + } + // for the full new histogram name we need to check that none of the existing histograms already uses this as a group name + if (depth == 1) { + if (curName.rfind(cumulativeName, 0) == 0 && curName.size() > cumulativeName.size() && curName.at(cumulativeName.size()) == '/') { + LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); + } + } + } + --depth; + cumulativeName += "/"; + } + mRegisteredNames.push_back(name); + } + std::string mName{}; OutputObjHandlingPolicy mPolicy{}; bool mCreateRegistryDir{}; bool mSortHistos{}; uint32_t mTaskHash{}; + std::vector<std::string> mRegisteredNames{}; - /// The maximum number of histograms in buffer is currently set to 512 - /// which seems to be both reasonably large and allowing for very fast lookup + // The maximum number of histograms in buffer is currently set to 512 + // which seems to be both reasonably large and allowing for very fast lookup static constexpr uint32_t MASK{0x1FF}; static constexpr uint32_t MAX_REGISTRY_SIZE{MASK + 1}; std::array<uint32_t, MAX_REGISTRY_SIZE> mRegistryKey{}; From 208415e1a32662df884e35718bcd4caa6c1b5417 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 28 Oct 2020 10:35:20 +0100 Subject: [PATCH 1140/1751] GPU: Use propper data access instead of fetching pointers from the tracker's internals in standalone QA --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 122 ++++++++++++------------ 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 993a562312a93..3588098074299 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -76,18 +76,18 @@ using namespace GPUCA_NAMESPACE::gpu; #define CHECK_CLUSTER_STATE_INIT_LEG_BY_MC() #endif -#define CHECK_CLUSTER_STATE_INIT() \ - bool unattached = attach == 0; \ - float qpt = 0; \ - bool lowPt = false; \ - bool mev200 = false; \ - int id = attach & gputpcgmmergertypes::attachTrackMask; \ - if (!unattached) { \ - qpt = fabsf(merger.OutputTracks()[id].GetParam().GetQPt()); \ - lowPt = qpt > mTracking->GetParam().rec.tpcRejectQPt; \ - mev200 = qpt > 5; \ - } \ - bool physics = false, protect = false; \ +#define CHECK_CLUSTER_STATE_INIT() \ + bool unattached = attach == 0; \ + float qpt = 0; \ + bool lowPt = false; \ + bool mev200 = false; \ + int id = attach & gputpcgmmergertypes::attachTrackMask; \ + if (!unattached) { \ + qpt = fabsf(mTracking->mIOPtrs.mergedTracks[id].GetParam().GetQPt()); \ + lowPt = qpt > mTracking->GetParam().rec.tpcRejectQPt; \ + mev200 = qpt > 5; \ + } \ + bool physics = false, protect = false; \ CHECK_CLUSTER_STATE_INIT_LEG_BY_MC(); #define CHECK_CLUSTER_STATE() \ @@ -195,8 +195,7 @@ inline bool GPUQA::MCComp(const mcLabel_t& a, const mcLabel_t& b) { return (GPUQ bool GPUQA::clusterRemovable(int cid, bool prot) const { - const GPUTPCGMMerger& merger = mTracking->GetTPCMerger(); - int attach = merger.ClusterAttachment()[cid]; + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[cid]; CHECK_CLUSTER_STATE_NOCOUNT(); if (prot) { return protect || physics; @@ -523,8 +522,7 @@ void GPUQA::RunQA(bool matchOnly) } // Initialize Arrays - const GPUTPCGMMerger& merger = mTracking->GetTPCMerger(); - mTrackMCLabels.resize(merger.NOutputTracks()); + mTrackMCLabels.resize(mTracking->mIOPtrs.nMergedTracks); for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) { mTrackMCLabelsReverse[iCol].resize(GetNMCTracks(iCol)); mRecTracks[iCol].resize(GetNMCTracks(iCol)); @@ -546,7 +544,7 @@ void GPUQA::RunQA(bool matchOnly) mcEffBuffer.resize(mNEvents); mcLabelBuffer.resize(mNEvents); mcEffBuffer[mNEvents - 1].resize(GetNMCTracks(0)); - mcLabelBuffer[mNEvents - 1].resize(merger.NOutputTracks()); + mcLabelBuffer[mNEvents - 1].resize(mTracking->mIOPtrs.nMergedTracks); } bool mcAvail = mcPresent(); @@ -560,22 +558,23 @@ void GPUQA::RunQA(bool matchOnly) // Assign Track MC Labels timer.Start(); bool ompError = false; + #if QA_DEBUG == 0 -GPUCA_OPENMP(parallel for) + GPUCA_OPENMP(parallel for) #endif - for (int i = 0; i < merger.NOutputTracks(); i++) { + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { if (ompError) { continue; } int nClusters = 0; - const GPUTPCGMMergedTrack& track = merger.OutputTracks()[i]; + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; std::vector<mcLabel_t> labels; for (unsigned int k = 0; k < track.NClusters(); k++) { - if (merger.Clusters()[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { continue; } nClusters++; - unsigned int hitId = merger.Clusters()[track.FirstClusterRef() + k].num; + unsigned int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; if (hitId >= GetNMCLabels()) { GPUError("Invalid hit id %u > %d", hitId, GetNMCLabels()); ompError = true; @@ -651,27 +650,27 @@ GPUCA_OPENMP(parallel for) if (ompError) { return; } - for (int i = 0; i < merger.NOutputTracks(); i++) { - const GPUTPCGMMergedTrack& track = merger.OutputTracks()[i]; + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if (!track.OK()) { continue; } if (!mTrackMCLabels[i].isValid()) { for (unsigned int k = 0; k < track.NClusters(); k++) { - if (merger.Clusters()[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { continue; } - mClusterParam[merger.Clusters()[track.FirstClusterRef() + k].num].fakeAttached++; + mClusterParam[mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num].fakeAttached++; } continue; } mcLabelI_t label = mTrackMCLabels[i]; if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) { for (unsigned int k = 0; k < track.NClusters(); k++) { - if (merger.Clusters()[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { continue; } - int hitId = merger.Clusters()[track.FirstClusterRef() + k].num; + int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; bool correct = false; for (int j = 0; j < GetMCLabelNID(hitId); j++) { if (label == GetMCLabel(hitId, j)) { @@ -692,7 +691,7 @@ GPUCA_OPENMP(parallel for) GetMCTrackObj(mRecTracks, label)++; if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) { int& revLabel = GetMCTrackObj(mTrackMCLabelsReverse, label); - if (revLabel == -1 || !merger.OutputTracks()[revLabel].OK() || (merger.OutputTracks()[i].OK() && fabsf(merger.OutputTracks()[i].GetParam().GetZ()) < fabsf(merger.OutputTracks()[revLabel].GetParam().GetZ()))) { + if (revLabel == -1 || !mTracking->mIOPtrs.mergedTracks[revLabel].OK() || (mTracking->mIOPtrs.mergedTracks[i].OK() && fabsf(mTracking->mIOPtrs.mergedTracks[i].GetParam().GetZ()) < fabsf(mTracking->mIOPtrs.mergedTracks[revLabel].GetParam().GetZ()))) { revLabel = i; } } @@ -700,7 +699,7 @@ GPUCA_OPENMP(parallel for) } for (unsigned int i = 0; i < GetNMCLabels(); i++) { if (mClusterParam[i].attached == 0 && mClusterParam[i].fakeAttached == 0) { - int attach = merger.ClusterAttachment()[i]; + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; if (attach & gputpcgmmergertypes::attachFlagMask) { int track = attach & gputpcgmmergertypes::attachTrackMask; mcLabelI_t trackL = mTrackMCLabels[track]; @@ -726,7 +725,7 @@ GPUCA_OPENMP(parallel for) for (unsigned int k = 0; k < GetNMCTracks(0); k++) { allowMCLabels[k] = false; } - for (int i = 0; i < merger.NOutputTracks(); i++) { + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { if (!mGoodTracks[mNEvents - 1][i]) { continue; } @@ -740,9 +739,9 @@ GPUCA_OPENMP(parallel for) } } - const GPUTPCGMMergedTrack& track = merger.OutputTracks()[i]; + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; for (unsigned int j = 0; j < track.NClusters(); j++) { - int hitId = merger.Clusters()[track.FirstClusterRef() + j].num; + int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + j].num; if (GetMCLabelNID(hitId)) { int mcID = GetMCLabelID(hitId, 0); if (mcID >= 0) { @@ -900,10 +899,10 @@ GPUCA_OPENMP(parallel for) GPUTPCGMPropagator prop; prop.SetMaxSinPhi(.999); prop.SetMaterialTPC(); - prop.SetPolynomialField(&merger.Param().polynomialField); - prop.SetToyMCEventsFlag(merger.Param().ToyMCEventsFlag); + prop.SetPolynomialField(&mTracking->GetParam().polynomialField); + prop.SetToyMCEventsFlag(mTracking->GetParam().ToyMCEventsFlag); - for (int i = 0; i < merger.NOutputTracks(); i++) { + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { if (mConfig.writeMCLabels) { std::vector<int>& labelBuffer = mcLabelBuffer[mNEvents - 1]; labelBuffer[i] = mTrackMCLabels[i].getTrackID(); @@ -913,7 +912,7 @@ GPUCA_OPENMP(parallel for) } const mcInfo_t& mc1 = GetMCTrack(mTrackMCLabels[i]); const additionalMCParameters& mc2 = GetMCTrackObj(mMCParam, mTrackMCLabels[i]); - const GPUTPCGMMergedTrack& track = merger.OutputTracks()[i]; + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if ((mMCTrackMin != -1 && mTrackMCLabels[i].getTrackID() < mMCTrackMin) || (mMCTrackMax != -1 && mTrackMCLabels[i].getTrackID() >= mMCTrackMax)) { continue; @@ -945,7 +944,7 @@ GPUCA_OPENMP(parallel for) } else if (mConfig.resPrimaries == 2 && (mc1.prim || mc1.primDaughters)) { continue; } - if (GetMCTrackObj(mTrackMCLabelsReverse, mTrackMCLabels[i]) != i) { + if (GetMCTrackObj(mTrackMCLabelsReverse, mTrackMCLabels[i]) != (int)i) { continue; } @@ -977,7 +976,7 @@ GPUCA_OPENMP(parallel for) prop.SetTrack(¶m, alpha); bool inFlyDirection = 0; #ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (merger.Param().continuousMaxTimeBin ? 0 : ((param.Z() - mc1.z) * (param.Z() - mc1.z))) > (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X)) * (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X))) { + if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (mTracking->GetParam().continuousMaxTimeBin ? 0 : ((param.Z() - mc1.z) * (param.Z() - mc1.z))) > (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X)) * (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X))) { #else // Consider Z offset (pseudo-tf mc tracks have shifted z) if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (param.Z() + param.TZOffset() - mc1.z) * (param.Z() + param.TZOffset() - mc1.z) > 25) { // TODO: fix TZOffset #endif @@ -988,7 +987,7 @@ GPUCA_OPENMP(parallel for) continue; } #ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || (merger.Param().continuousMaxTimeBin == 0 && fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f))) { // TODO: fix TZOffset here + if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || (mTracking->GetParam().continuousMaxTimeBin == 0 && fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f))) { // TODO: fix TZOffset here #else if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f)) { // TODO: fix TZOffset here #endif @@ -1029,24 +1028,24 @@ GPUCA_OPENMP(parallel for) timer.ResetStart(); // Fill cluster histograms - for (int iTrk = 0; iTrk < merger.NOutputTracks(); iTrk++) { - const GPUTPCGMMergedTrack& track = merger.OutputTracks()[iTrk]; + for (unsigned int iTrk = 0; iTrk < mTracking->mIOPtrs.nMergedTracks; iTrk++) { + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[iTrk]; if (!track.OK()) { continue; } if (!mTrackMCLabels[iTrk].isValid()) { for (unsigned int k = 0; k < track.NClusters(); k++) { - if (merger.Clusters()[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { continue; } - int hitId = merger.Clusters()[track.FirstClusterRef() + k].num; + int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; float totalWeight = 0.; for (int j = 0; j < GetMCLabelNID(hitId); j++) { if (GetMCLabelID(hitId, j) >= 0 && GetMCTrackObj(mMCParam, GetMCLabel(hitId, j)).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { totalWeight += GetMCLabelWeight(hitId, j); } } - int attach = merger.ClusterAttachment()[hitId]; + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[hitId]; CHECK_CLUSTER_STATE_NOCOUNT(); if (totalWeight > 0) { float weight = 1.f / (totalWeight * (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached)); @@ -1092,10 +1091,10 @@ GPUCA_OPENMP(parallel for) continue; } for (unsigned int k = 0; k < track.NClusters(); k++) { - if (merger.Clusters()[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { continue; } - int hitId = merger.Clusters()[track.FirstClusterRef() + k].num; + int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; float pt = GetMCTrackObj(mMCParam, label).pt; if (pt < PT_MIN_CLUST) { pt = PT_MIN_CLUST; @@ -1116,7 +1115,7 @@ GPUCA_OPENMP(parallel for) } mClusters[CL_att_adj]->Fill(pt, weight); mClusters[CL_all]->Fill(pt, weight); - int attach = merger.ClusterAttachment()[hitId]; + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[hitId]; CHECK_CLUSTER_STATE_NOCOUNT(); if (protect || physics) { mClusters[CL_prot]->Fill(pt, weight); @@ -1133,10 +1132,10 @@ GPUCA_OPENMP(parallel for) if (mClusterParam[i].attached || mClusterParam[i].fakeAttached) { continue; } - int attach = merger.ClusterAttachment()[i]; + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; CHECK_CLUSTER_STATE_NOCOUNT(); if (mClusterParam[i].adjacent) { - int label = merger.ClusterAttachment()[i] & gputpcgmmergertypes::attachTrackMask; + int label = mTracking->mIOPtrs.mergedTrackHitAttachment[i] & gputpcgmmergertypes::attachTrackMask; if (!mTrackMCLabels[label].isValid()) { float totalWeight = 0.; for (int j = 0; j < GetMCLabelNID(i); j++) { @@ -1258,8 +1257,8 @@ GPUCA_OPENMP(parallel for) } // Fill other histograms - for (int i = 0; i < merger.NOutputTracks(); i++) { - const GPUTPCGMMergedTrack& track = merger.OutputTracks()[i]; + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if (!track.OK()) { continue; } @@ -1267,8 +1266,9 @@ GPUCA_OPENMP(parallel for) mNCl->Fill(track.NClustersFitted()); } - for (unsigned int i = 0; i < merger.NMaxClusters(); i++) { - int attach = merger.ClusterAttachment()[i]; + unsigned int nCl = mTracking->mIOPtrs.clustersNative ? mTracking->mIOPtrs.clustersNative->nClustersTotal : mTracking->GetTPCMerger().NMaxClusters(); + for (unsigned int i = 0; i < nCl; i++) { + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; CHECK_CLUSTER_STATE(); if (mcAvail) { @@ -1333,7 +1333,7 @@ GPUCA_OPENMP(parallel for) // Create CSV DumpTrackHits if (mConfig.csvDump) { - if (!merger.Param().earlyTpcTransform) { + if (!mTracking->GetParam().earlyTpcTransform) { GPUError("Unsupported settings for csv dump\n"); return; } @@ -1346,16 +1346,16 @@ GPUCA_OPENMP(parallel for) std::vector<float> clusterInfo(totalNCls); memset(clusterInfo.data(), 0, clusterInfo.size() * sizeof(clusterInfo[0])); - for (int i = 0; i < merger.NOutputTracks(); i++) { - const GPUTPCGMMergedTrack& track = merger.OutputTracks()[i]; + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if (!track.OK()) { continue; } for (unsigned int k = 0; k < track.NClusters(); k++) { - if (merger.Clusters()[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { continue; } - int hitId = merger.Clusters()[track.FirstClusterRef() + k].num; + int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; float pt = fabsf(1.f / track.GetParam().GetQPt()); if (pt > clusterInfo[hitId]) { clusterInfo[hitId] = pt; @@ -1373,7 +1373,7 @@ GPUCA_OPENMP(parallel for) const auto& cl = mTracking->mIOPtrs.clusterData[iSlice][i]; float x, y, z; const int cid = cl.id; - merger.Param().Slice2Global(iSlice, cl.x, cl.y, cl.z, &x, &y, &z); + mTracking->GetParam().Slice2Global(iSlice, cl.x, cl.y, cl.z, &x, &y, &z); float totalWeight = 0.f; if (mcPresent()) { @@ -1409,7 +1409,7 @@ GPUCA_OPENMP(parallel for) } dumpClTot++; - int attach = merger.ClusterAttachment()[cid]; + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[cid]; CHECK_CLUSTER_STATE(); if (protect || physics) { continue; From 50d945c086690acf5e257d0f149937e9252e4107 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 15:13:18 +0100 Subject: [PATCH 1141/1751] GPU: Make Merge-by-MC-label compression benchmark study compatible to Run 3 data --- .../SimulationDataFormat/MCCompLabel.h | 1 + GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 46 ++++++++++++++----- GPU/GPUTracking/Merger/GPUTPCGMMerger.h | 4 +- .../Standalone/display/GPUDisplay.cxx | 2 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 16 +++---- GPU/GPUTracking/Standalone/qa/GPUQA.h | 4 +- 6 files changed, 50 insertions(+), 23 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h b/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h index 90d5c1a7ba5a2..ca536e767e4cc 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h @@ -120,6 +120,7 @@ class MCCompLabel int getTrackIDSigned() const { return isFake() ? -getTrackID() : getTrackID(); } int getEventID() const { return (mLabel >> nbitsTrackID) & maskEvID; } int getSourceID() const { return (mLabel >> (nbitsTrackID + nbitsEvID)) & maskSrcID; } + ULong64_t getTrackEventSourceID() const { return static_cast<ULong64_t>(mLabel & maskFull); } void get(int& trackID, int& evID, int& srcID, bool& fake) { /// parse label diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index bfb5a3ba18768..e7e230eb0d16e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -41,8 +41,13 @@ #include "GPUTPCGMSliceTrack.h" #include "GPUTPCGMBorderTrack.h" -#if defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) +#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED)) #include "AliHLTTPCClusterMCData.h" +#ifdef GPUCA_O2_LIB +#include "DataFormatsTPC/ClusterNative.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/MCCompLabel.h" +#endif #endif using namespace GPUCA_NAMESPACE::gpu; @@ -85,7 +90,7 @@ GPUTPCGMMerger::GPUTPCGMMerger() } // DEBUG CODE -#if defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) +#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED)) void GPUTPCGMMerger::CheckMergedTracks() { std::vector<bool> trkUsed(SliceTrackInfoLocalTotal()); @@ -135,11 +140,12 @@ void GPUTPCGMMerger::CheckMergedTracks() } } -int GPUTPCGMMerger::GetTrackLabel(const GPUTPCGMBorderTrack& trk) +template <class T> +long int GPUTPCGMMerger::GetTrackLabelA(const GPUTPCGMBorderTrack& trk) { GPUTPCGMSliceTrack* track = &mSliceTrackInfos[trk.TrackID()]; int nClusters = track->OrigTrack()->NHits(); - std::vector<int> labels; + std::vector<long int> labels; for (int i = 0; i < nClusters; i++) { int id; if (Param().rec.mergerReadFromTrackerDirectly) { @@ -149,10 +155,16 @@ int GPUTPCGMMerger::GetTrackLabel(const GPUTPCGMBorderTrack& trk) } else { id = track->OrigTrack()->OutTrackClusters()[i].GetId(); } - for (int j = 0; j < 3; j++) { - int label = GetConstantMem()->ioPtrs.mcLabelsTPC[id].fClusterID[j].fMCID; - if (label >= 0) { - labels.push_back(label); + if constexpr (std::is_same<T, AliHLTTPCClusterMCLabel>::value) { + for (int j = 0; j < 3; j++) { + int label = GetConstantMem()->ioPtrs.mcLabelsTPC[id].fClusterID[j].fMCID; + if (label >= 0) { + labels.push_back(label); + } + } + } else { + for (auto label : GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth->getLabels(id)) { + labels.push_back(label.getTrackEventSourceID()); } } } @@ -161,8 +173,8 @@ int GPUTPCGMMerger::GetTrackLabel(const GPUTPCGMBorderTrack& trk) } labels.push_back(-1); std::sort(labels.begin(), labels.end()); - int bestLabel = -1, bestLabelCount = 0; - int curLabel = labels[0], curCount = 1; + long int bestLabel = -1, curLabel = labels[0]; + int curCount = 1, bestLabelCount = 0; for (unsigned int i = 1; i < labels.size(); i++) { if (labels[i] == curLabel) { curCount++; @@ -178,6 +190,18 @@ int GPUTPCGMMerger::GetTrackLabel(const GPUTPCGMBorderTrack& trk) return bestLabel; } +long int GPUTPCGMMerger::GetTrackLabel(const GPUTPCGMBorderTrack& trk) +{ +#ifdef GPUCA_O2_LIB + if (GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth) { + return GetTrackLabelA<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>>(trk); + } else +#endif + { + return GetTrackLabelA<AliHLTTPCClusterMCLabel>(trk); + } +} + #endif // END DEBUG CODE @@ -781,7 +805,7 @@ GPUd() void GPUTPCGMMerger::MergeBorderTracks<2>(int nBlocks, int nThreads, int // do check GPUTPCGMBorderTrack& b2 = B2[r2.fId]; -#ifdef GPUCA_MERGER_BY_MC_LABEL +#if defined(GPUCA_MERGER_BY_MC_LABEL) && !defined(GPUCA_GPUCODE) if (GetTrackLabel(b1) != GetTrackLabel(b2)) // DEBUG CODE, match by MC label #endif { diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h index dd8ff0a76f351..1b1defc27e8d5 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h @@ -175,7 +175,9 @@ class GPUTPCGMMerger : public GPUProcessor void CheckMergedTracks(); #ifndef GPUCA_GPUCODE void PrintMergeGraph(const GPUTPCGMSliceTrack* trk, std::ostream& out); - int GetTrackLabel(const GPUTPCGMBorderTrack& trk); + template <class T> + long int GetTrackLabelA(const GPUTPCGMBorderTrack& trk); + long int GetTrackLabel(const GPUTPCGMBorderTrack& trk); #endif GPUdi() int SliceTrackInfoFirst(int iSlice) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 064ad942d8622..27eb381b83b41 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -722,7 +722,7 @@ GPUDisplay::vboList GPUDisplay::DrawClusters(const GPUTPCTracker& tracker, int s const int attach = tracker.GetConstantMem()->ioPtrs.mergedTrackHitAttachment[cid]; if (attach) { if (mMarkAdjacentClusters >= 32) { - if (mQA && mQA->clusterRemovable(cid, mMarkAdjacentClusters == 33)) { + if (mQA && mQA->clusterRemovable(attach, mMarkAdjacentClusters == 33)) { draw = select == tMARKED; } } else if ((mMarkAdjacentClusters & 2) && (attach & gputpcgmmergertypes::attachTube)) { diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 3588098074299..151f0ffbda70f 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -65,12 +65,13 @@ using namespace GPUCA_NAMESPACE::gpu; #define QA_TIMING 0 #ifdef GPUCA_MERGER_BY_MC_LABEL -#define CHECK_CLUSTER_STATE_INIT_LEG_BY_MC() \ - if (!unattached && mTrackMCLabels[id].isValid()) { \ - int mcLabel = mTrackMCLabels[id].getTrackID(); \ - if (mTrackMCLabelsReverse[0][mcLabel] != id) { \ - attach &= (~gputpcgmmergertypes::attachGoodLeg); \ - } \ +#define CHECK_CLUSTER_STATE_INIT_LEG_BY_MC() \ + if (!unattached && mTrackMCLabels[id].isValid()) { \ + int mcLabel = mTrackMCLabels[id].getTrackID(); \ + int mcEvent = mTrackMCLabels[id].getEventID(); \ + if (mTrackMCLabelsReverse[mcEvent][mcLabel] != id) { \ + attach &= (~gputpcgmmergertypes::attachGoodLeg); \ + } \ } #else #define CHECK_CLUSTER_STATE_INIT_LEG_BY_MC() @@ -193,9 +194,8 @@ GPUQA::~GPUQA() = default; inline bool GPUQA::MCComp(const mcLabel_t& a, const mcLabel_t& b) { return (GPUQA::GetMCLabelID(a) > GPUQA::GetMCLabelID(b)); } -bool GPUQA::clusterRemovable(int cid, bool prot) const +bool GPUQA::clusterRemovable(int attach, bool prot) const { - int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[cid]; CHECK_CLUSTER_STATE_NOCOUNT(); if (prot) { return protect || physics; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 1082853b0d537..5e21d54be6269 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -51,7 +51,7 @@ class GPUQA bool SuppressHit(int iHit) const { return false; } int HitAttachStatus(int iHit) const { return false; } int GetMCTrackLabel(unsigned int trackId) const { return -1; } - bool clusterRemovable(int cid, bool prot) const { return false; } + bool clusterRemovable(int attach, bool prot) const { return false; } static bool QAAvailable() { return false; } static bool IsInitialized() { return false; } }; @@ -95,7 +95,7 @@ class GPUQA bool SuppressHit(int iHit) const; int HitAttachStatus(int iHit) const; int GetMCTrackLabel(unsigned int trackId) const; - bool clusterRemovable(int cid, bool prot) const; + bool clusterRemovable(int attach, bool prot) const; static bool QAAvailable() { return true; } bool IsInitialized() { return mQAInitialized; } From f58a13a677094f67a8a3e8db8e2de83f45e82a41 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 27 Oct 2020 16:15:46 +0100 Subject: [PATCH 1142/1751] GPU: Fix typo (fake protected ratio was computed incorrectly) --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 151f0ffbda70f..fba5d3f2bbb50 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -1307,7 +1307,7 @@ void GPUQA::RunQA(bool matchOnly) } mClusterCounts.nAbove400++; } - if (totalWeight == 0 && weight40 >= 0.9 * totalWeight) { + if (totalWeight > 0 && weight40 >= 0.9 * totalWeight) { mClusterCounts.nBelow40++; if (protect || physics) { mClusterCounts.nFakeProtect40++; From 871151b940549b8140112ab9dccfa17d155d62d4 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 28 Oct 2020 17:22:00 +0100 Subject: [PATCH 1143/1751] Fix in material LUT step sign definition --- Detectors/Base/src/MatLayerCylSet.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Detectors/Base/src/MatLayerCylSet.cxx b/Detectors/Base/src/MatLayerCylSet.cxx index a6bd484d070f0..ed31f12d3ba00 100644 --- a/Detectors/Base/src/MatLayerCylSet.cxx +++ b/Detectors/Base/src/MatLayerCylSet.cxx @@ -305,7 +305,7 @@ GPUd() MatBudget MatLayerCylSet::getMatBudget(float x0, float y0, float z0, floa } } // account materials of this step - float step = tEndZ - tStartZ; // the real step is ray.getDist(tEnd-tStart), will rescale all later + float step = tEndZ > tStartZ ? tEndZ - tStartZ : tStartZ - tEndZ; // the real step is ray.getDist(tEnd-tStart), will rescale all later const auto& cell = lr.getCell(phiID, zID); rval.meanRho += cell.meanRho * step; rval.meanX2X0 += cell.meanX2X0 * step; @@ -325,7 +325,7 @@ GPUd() MatBudget MatLayerCylSet::getMatBudget(float x0, float y0, float z0, floa zID += stepZID; } while (checkMoreZ); } else { - float step = tEndPhi - tStartPhi; // the real step is |ray.getDist(tEnd-tStart)|, will rescale all later + float step = tEndPhi > tStartPhi ? tEndPhi - tStartPhi : tStartPhi - tEndPhi; // the real step is |ray.getDist(tEnd-tStart)|, will rescale all later const auto& cell = lr.getCell(phiID, zID); rval.meanRho += cell.meanRho * step; rval.meanX2X0 += cell.meanX2X0 * step; @@ -352,8 +352,7 @@ GPUd() MatBudget MatLayerCylSet::getMatBudget(float x0, float y0, float z0, floa if (rval.length != 0.f) { rval.meanRho /= rval.length; // average - float norm = (rval.length < 0.f) ? -ray.getDist() : ray.getDist(); // normalize - rval.meanX2X0 *= norm; + rval.meanX2X0 *= ray.getDist(); // normalize } rval.length = ray.getDist(); From b45c1e17356f3028b9bb477f3e89354cfbe29067 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Tue, 22 Sep 2020 12:00:58 +0200 Subject: [PATCH 1144/1751] [EMCAL-551] Move cell format to bitfield - Move underlying structure to bitfield and expand to 48 bit (min. size) - Increase number of time bits from 9 to 11, and use an internal time shift of 600 ns in order to cover the time range from -600 ns to 900 ns with 0.7 ns precision - Add truncations for time and energy - Make truncations and resolution constants, and calculate based on the range and the max. integer number representable with the amount of bits assigned. - Add doxygen documentation for cell class - Fixes in test: - Default cell type: High gain(0) instead of LowGain(1) - Test of times should reflect negative values as time can be shifted - In practice cells with E > 16 GeV are low gain cells, energy test should reflect this --- .../EMCAL/include/DataFormatsEMCAL/Cell.h | 183 ++++++++++++---- DataFormats/Detectors/EMCAL/src/Cell.cxx | 198 +++--------------- DataFormats/Detectors/EMCAL/test/testCell.cxx | 34 +-- 3 files changed, 195 insertions(+), 220 deletions(-) diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h index 568a069543c2d..361faf1d13e90 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h @@ -12,7 +12,6 @@ #define ALICEO2_EMCAL_CELL_H_ #include <bitset> -#include "Rtypes.h" #include "DataFormatsEMCAL/Constants.h" namespace o2 @@ -22,62 +21,162 @@ namespace emcal /// \class Cell /// \brief EMCAL compressed cell information +/// \author Anders Knospe, University of Houston +/// \author Markus Fasel <markus.fasel@cern.ch>, Oak Ridge National Laboratory +/// \since March 6, 2019 /// \ingroup EMCALDataFormat /// -/// Structure: -/// Bits 38-39: Cell type: 00=Low Gain, 01=High Gain, 10=LED mon, 11=TRU -/// Bits 24-37: Energy (input/output in GeV/c^2, resolution 1/16 ADC count) -/// Bits 15-23: Time (ns) -/// Bits 0-14: Tower ID +/// # Base format for EMCAL cell information in the Compressed Timeframe +/// +/// The cell class contains the relevant information for each tower per event +/// - Tower ID +/// - Energy of the raw fit +/// - Time of the raw fit +/// - Type of the cell +/// While cell type and tower ID have a predefined range based on the hardware +/// design, energy and time have a finite resolution influenced by the resolution +/// of the digitizer. This is used in order to compress the information stored +/// in the compressed timeframe by not storing the full double values but instead +/// assigning a certain amount of bits to each information. Therefore for certain +/// information (energy, time) precision loss has to be taken into account. +/// +/// # Internal structure and resolution +/// +/// The internal structure is a bit field compressing the information to +/// 48 bits. The definition of the bit field as well as the value range and the resolution +/// is listed in the table below: +/// +/// | Bits | Content | Resolution | Range | +/// |-------|---------------|---------------|-----------------------------| +/// | 0-14 | Tower ID | - | 0 to 17644 | +/// | 15-26 | Time (ns) | 0.73 ns | -600 to 900 ns | +/// | 27-40 | Energy (GeV) | 0.0153 GeV | 0 to 250 GeV | +/// | 41-42 | Cell type | - | 0=LG, 1=HG, 2=LEMon, 4=TRU | +/// +/// The remaining bits are 0 class Cell { public: - Cell() = default; - Cell(Short_t tower, Double_t energy, Double_t time, ChannelType_t ctype = ChannelType_t::LOW_GAIN); + Cell(); + Cell(short tower, float energy, float time, ChannelType_t ctype = ChannelType_t::LOW_GAIN); ~Cell() = default; // override - void setTower(Short_t tower); - Short_t getTower() const; - - void setTimeStamp(Double_t time); - Short_t getTimeStamp() const; - - void setEnergyBits(Short_t ebits); - Short_t getEnergyBits() const; - - void setEnergy(Double_t energy); - Double_t getEnergy() const; - - void setAmplitude(Double_t energy) { setEnergy(energy); } - Double_t getAmplitude() const { return getEnergy(); } - - void setType(ChannelType_t ctype); - ChannelType_t getType() const; - - void setLowGain(); - Bool_t getLowGain() const; - - void setHighGain(); - Bool_t getHighGain() const; - - void setLEDMon(); - Bool_t getLEDMon() const; - - void setTRU(); - Bool_t getTRU() const; - - void setLong(ULong_t l); - ULong_t getLong() const { return mBits.to_ulong(); } + void setTower(short tower) { getDataRepresentation()->mTowerID = tower; } + short getTower() const { return getDataRepresentation()->mTowerID; } + + /// \brief Set the time stamp + /// \param time Time in ns + /// + /// The time stamp is expressed in ns and has + /// a resolution of 1 ns. The time range which can + /// be stored is from -1023 to 1023 ns. In case the + /// range is exceeded the time is set to the limit + /// of the range. + void setTimeStamp(float time); + + /// \brief Get the time stamp + /// \return Time in ns + /// + /// Time has a resolution of 1 ns and can cover + /// a range from -1023 to 1023 ns + float getTimeStamp() const; + + /// \brief Set the energy of the cell + /// \brief Energy of the cell in GeV + /// + /// The energy range covered by the cell + /// is 0 - 250 GeV, with a resolution of + /// 0.0153 GeV. In case an energy exceeding + /// the limits is provided the energy is + /// set to the limits (0 in case of negative + /// energy, 250. in case of energies > 250 GeV) + void setEnergy(float energy); + + /// \brief Get the energy of the cell + /// \return Energy of the cell + /// + /// The energy is truncated to a range + /// covering 0 to 250 GeV with a resolution + /// of 0.0153 GeV + float getEnergy() const; + + /// \brief Set the amplitude of the cell + /// \param amplitude Cell amplitude + /// + /// See setEnergy for more information + void setAmplitude(float amplitude) { setEnergy(amplitude); } + + /// \brief Get cell amplitude + /// \return cell Amplitude + /// + /// Set getEnergy for more information + float getAmplitude() const { return getEnergy(); } + + /// \brief Set the type of the cell + /// \param ctype Type of the cell (HIGH_GAIN, LOW_GAIN, LEDMON, TRU) + void setType(ChannelType_t ctype) { getDataRepresentation()->mCellStatus = static_cast<uint16_t>(ctype); } + + /// \brief Get the type of the cell + /// \return Type of the cell (HIGH_GAIN, LOW_GAIN, LEDMON, TRU) + ChannelType_t getType() const { return static_cast<ChannelType_t>(getDataRepresentation()->mCellStatus); } + + /// \brief Check whether the cell is of a given type + /// \param ctype Type of the cell (HIGH_GAIN, LOW_GAIN, LEDMON, TRU) + /// \return True if the type of the cell matches the requested type, false otherwise + bool isChannelType(ChannelType_t ctype) const { return getType() == ctype; } + + /// \brief Mark cell as low gain cell + void setLowGain() { setType(ChannelType_t::LOW_GAIN); } + + /// \brief Check whether the cell is a low gain cell + /// \return True if the cell type is low gain, false otherwise + Bool_t getLowGain() const { return isChannelType(ChannelType_t::LOW_GAIN); } + + /// \brief Mark cell as high gain cell + void setHighGain() { setType(ChannelType_t::HIGH_GAIN); } + + /// \brief Check whether the cell is a high gain cell + /// \return True if the cell type is high gain, false otherwise + Bool_t getHighGain() const { return isChannelType(ChannelType_t::HIGH_GAIN); }; + + /// \brief Mark cell as LED monitor cell + void setLEDMon() { setType(ChannelType_t::LEDMON); } + + /// \brief Check whether the cell is a LED monitor cell + /// \return True if the cell type is LED monitor, false otherwise + Bool_t getLEDMon() const { return isChannelType(ChannelType_t::LEDMON); } + + /// \brief Mark cell as TRU cell + void setTRU() { setType(ChannelType_t::TRU); } + + /// \brief Check whether the cell is a TRU cell + /// \return True if the cell type is TRU, false otherwise + Bool_t getTRU() const { return isChannelType(ChannelType_t::TRU); } void PrintStream(std::ostream& stream) const; private: - std::bitset<40> mBits; + struct __attribute__((packed)) CellData { + uint16_t mTowerID : 15; ///< bits 0-14 Tower ID + uint16_t mTime : 11; ///< bits 15-25: Time (signed, can become negative after calibration) + uint16_t mEnergy : 14; ///< bits 26-39: Energy + uint16_t mCellStatus : 2; ///< bits 40-41: Cell status + uint16_t mZerod : 6; ///< bits 42-47: Zerod + }; + + CellData* getDataRepresentation() { return reinterpret_cast<CellData*>(mCellWords); } + const CellData* getDataRepresentation() const { return reinterpret_cast<const CellData*>(mCellWords); } + + uint16_t mCellWords[3]; ///< data word ClassDefNV(Cell, 1); }; -std::ostream& operator<<(std::ostream& stream, const Cell& c); +/// \brief Stream operator for EMCAL cell +/// \param stream Stream where to print the EMCAL cell +/// \param cell Cell to be printed +/// \return Stream after printing +std::ostream& operator<<(std::ostream& stream, const Cell& cell); } // namespace emcal } // namespace o2 diff --git a/DataFormats/Detectors/EMCAL/src/Cell.cxx b/DataFormats/Detectors/EMCAL/src/Cell.cxx index 044b970b638e8..706f274f0093a 100644 --- a/DataFormats/Detectors/EMCAL/src/Cell.cxx +++ b/DataFormats/Detectors/EMCAL/src/Cell.cxx @@ -15,192 +15,62 @@ using namespace o2::emcal; -Cell::Cell(Short_t tower, Double_t energy, Double_t time, ChannelType_t ctype) -{ - setTower(tower); - setTimeStamp(time); - setEnergy(energy); - setType(ctype); -} - -void Cell::setTower(Short_t tower) -{ - if (tower > 0x7fff || tower < 0) { - tower = 0x7fff; - } - ULong_t t = (ULong_t)tower; - - ULong_t b = getLong() & 0xffffff8000; // 1111111111111111111111111000000000000000 - mBits = b + t; -} - -Short_t Cell::getTower() const -{ - ULong_t t = getLong(); - t &= 0x7fff; - return ((Short_t)t); -} - -void Cell::setTimeStamp(Double_t time) -{ - ULong_t t = 0; - if (time > 0x1ff) { - t = 0x1ff; - } else if (time < 0) { - t = 0; - } else { - t = (ULong_t)time; - } - - t <<= 15; - ULong_t b = getLong() & 0xffff007fff; // 1111111111111111000000000111111111111111 - mBits = b + t; -} - -Short_t Cell::getTimeStamp() const -{ - ULong_t t = getLong(); - t >>= 15; - t &= 0x1ff; - return ((Short_t)t); -} - -void Cell::setEnergyBits(Short_t ebits) -{ - if (ebits > 0x3fff) { - ebits = 0x3fff; - } else if (ebits < 0) { - ebits = 0; - } - ULong_t a = (ULong_t)ebits; - - a <<= 24; - ULong_t b = getLong() & 0xc00ffffff; // 1100000000000000111111111111111111111111 - mBits = b + a; -} - -Short_t Cell::getEnergyBits() const -{ - ULong_t a = getLong(); - a >>= 24; - a &= 0x3fff; - return ((Short_t)a); -} +const float TIME_SHIFT = 600., + TIME_RANGE = 1500., + TIME_RESOLUTION = TIME_RANGE / 2047., + ENERGY_TRUNCATION = 250., + ENERGY_RESOLUTION = ENERGY_TRUNCATION / 16383.; -void Cell::setEnergy(Double_t energy) +Cell::Cell() { - ULong_t a = static_cast<ULong_t>(energy / 0.0153); - a = a & 0x3FFF; - - a <<= 24; - ULong_t b = getLong() & 0xc000ffffff; // 1100000000000000111111111111111111111111 - mBits = b + a; -} - -Double_t Cell::getEnergy() const -{ - return double(getEnergyBits() * 0.0153); -} - -void Cell::setType(ChannelType_t ctype) -{ - switch (ctype) { - case ChannelType_t::HIGH_GAIN: - setHighGain(); - break; - case ChannelType_t::LOW_GAIN: - setLowGain(); - break; - case ChannelType_t::TRU: - setTRU(); - break; - case ChannelType_t::LEDMON: - setHighGain(); - break; - }; -} - -ChannelType_t Cell::getType() const -{ - if (getHighGain()) { - return ChannelType_t::HIGH_GAIN; - } else if (getLEDMon()) { - return ChannelType_t::LEDMON; - } else if (getTRU()) { - return ChannelType_t::TRU; - } - return ChannelType_t::LOW_GAIN; -} - -void Cell::setLowGain() -{ - std::bitset<40> b(0x3fffffffff); // 0011111111111111111111111111111111111111 - mBits = (mBits & b); -} - -Bool_t Cell::getLowGain() const -{ - ULong_t t = (getLong() >> 38); - if (t) { - return false; - } - return true; -} - -void Cell::setHighGain() -{ - ULong_t b = getLong() & 0x3fffffffff; // 0011111111111111111111111111111111111111 - mBits = b + 0x4000000000; // 0100000000000000000000000000000000000000 + memset(mCellWords, 0, sizeof(uint16_t) * 3); } -Bool_t Cell::getHighGain() const +Cell::Cell(short tower, float energy, float time, ChannelType_t ctype) { - ULong_t t = (getLong() >> 38); - if (t == 1) { - return true; - } - return false; -} - -void Cell::setLEDMon() -{ - ULong_t b = getLong() & 0x3fffffffff; // 0011111111111111111111111111111111111111 - mBits = b + 0x8000000000; // 1000000000000000000000000000000000000000 + memset(mCellWords, 0, sizeof(uint16_t) * 3); + setTower(tower); + setTimeStamp(time); + setEnergy(energy); + setType(ctype); } -Bool_t Cell::getLEDMon() const +void Cell::setTimeStamp(float timestamp) { - ULong_t t = (getLong() >> 38); - if (t == 2) { - return true; - } - return false; + // truncate: + const float TIME_MIN = -1. * TIME_SHIFT, + TIME_MAX = TIME_RANGE - TIME_SHIFT; + if (timestamp < TIME_MIN) + timestamp = TIME_MIN; + else if (timestamp > TIME_MAX) + timestamp = TIME_MAX; + getDataRepresentation()->mTime = static_cast<uint16_t>((timestamp + TIME_SHIFT) / TIME_RESOLUTION); } -void Cell::setTRU() +float Cell::getTimeStamp() const { - ULong_t b = getLong() & 0x3fffffffff; // 0011111111111111111111111111111111111111 - mBits = b + 0xc000000000; // 1100000000000000000000000000000000000000 + return (static_cast<float>(getDataRepresentation()->mTime) * TIME_RESOLUTION) - TIME_SHIFT; } -Bool_t Cell::getTRU() const +void Cell::setEnergy(float energy) { - ULong_t t = (getLong() >> 38); - if (t == 3) { - return true; + double truncatedEnergy = energy; + if (truncatedEnergy < 0.) { + truncatedEnergy = 0.; + } else if (truncatedEnergy > ENERGY_TRUNCATION) { + truncatedEnergy = ENERGY_TRUNCATION; } - return false; + getDataRepresentation()->mEnergy = static_cast<int16_t>(truncatedEnergy / ENERGY_RESOLUTION); } -void Cell::setLong(ULong_t l) +float Cell::getEnergy() const { - std::bitset<40> b(l); - mBits = b; + return static_cast<float>(getDataRepresentation()->mEnergy) * ENERGY_RESOLUTION; } void Cell::PrintStream(std::ostream& stream) const { - stream << "EMCAL Cell: Type " << getType() << ", Energy " << getEnergy() << ", Time " << getTimeStamp() << ", Tower " << getTower() << ", Bits " << mBits; + stream << "EMCAL Cell: Type " << getType() << ", Energy " << getEnergy() << ", Time " << getTimeStamp() << ", Tower " << getTower(); } std::ostream& operator<<(std::ostream& stream, const Cell& c) diff --git a/DataFormats/Detectors/EMCAL/test/testCell.cxx b/DataFormats/Detectors/EMCAL/test/testCell.cxx index b24703e2bc890..c021523cf387e 100644 --- a/DataFormats/Detectors/EMCAL/test/testCell.cxx +++ b/DataFormats/Detectors/EMCAL/test/testCell.cxx @@ -27,25 +27,26 @@ namespace emcal /// - verify that set and get functions return consistent values BOOST_AUTO_TEST_CASE(Cell_test) { - Cell c; + Cell c(0, 0, 0, o2::emcal::ChannelType_t::HIGH_GAIN); for (short j = 0; j < 17664; j++) { c.setTower(j); BOOST_CHECK_EQUAL(c.getTower(), j); - BOOST_CHECK_EQUAL(c.getTimeStamp(), 0); + BOOST_CHECK_SMALL(double(c.getTimeStamp()), 0.73); BOOST_CHECK_EQUAL(c.getEnergy(), 0); - BOOST_CHECK_EQUAL(c.getLowGain(), true); + BOOST_CHECK_EQUAL(c.getHighGain(), true); } c.setTower(0); - std::vector<int> times = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 50, 100, 200}; + // Test time over the full range + std::vector<int> times = {-500, -200, -100, -50, -20, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 50, 100, 200, 500, 900}; for (auto t : times) { c.setTimeStamp(t); BOOST_CHECK_EQUAL(c.getTower(), 0); - BOOST_CHECK_EQUAL(c.getTimeStamp(), t); + BOOST_CHECK_SMALL(double(c.getTimeStamp() - t), 0.73); BOOST_CHECK_EQUAL(c.getEnergy(), 0); - BOOST_CHECK_EQUAL(c.getLowGain(), true); + BOOST_CHECK_EQUAL(c.getHighGain(), true); } c.setTimeStamp(0); @@ -53,35 +54,40 @@ BOOST_AUTO_TEST_CASE(Cell_test) for (auto e : energies) { c.setEnergy(e); + if (e > 16) + c.setLowGain(); BOOST_CHECK_EQUAL(c.getTower(), 0); - BOOST_CHECK_EQUAL(c.getTimeStamp(), 0); + BOOST_CHECK_SMALL(double(c.getTimeStamp()), 0.73); BOOST_CHECK_SMALL(e - c.getEnergy(), 0.02); // Require 20 MeV resolution - BOOST_CHECK_EQUAL(c.getLowGain(), true); + if (e > 16) + BOOST_CHECK_EQUAL(c.getLowGain(), true); + else + BOOST_CHECK_EQUAL(c.getHighGain(), true); } c.setEnergy(0); c.setLowGain(); BOOST_CHECK_EQUAL(c.getTower(), 0); - BOOST_CHECK_EQUAL(c.getTimeStamp(), 0); + BOOST_CHECK_SMALL(double(c.getTimeStamp()), 0.73); BOOST_CHECK_EQUAL(c.getEnergy(), 0); - BOOST_CHECK_EQUAL(c.getLowGain(), true); BOOST_CHECK_EQUAL(c.getHighGain(), false); + BOOST_CHECK_EQUAL(c.getLowGain(), true); BOOST_CHECK_EQUAL(c.getLEDMon(), false); BOOST_CHECK_EQUAL(c.getTRU(), false); c.setHighGain(); BOOST_CHECK_EQUAL(c.getTower(), 0); - BOOST_CHECK_EQUAL(c.getTimeStamp(), 0); + BOOST_CHECK_SMALL(double(c.getTimeStamp()), 0.73); BOOST_CHECK_EQUAL(c.getEnergy(), 0); - BOOST_CHECK_EQUAL(c.getLowGain(), false); BOOST_CHECK_EQUAL(c.getHighGain(), true); + BOOST_CHECK_EQUAL(c.getLowGain(), false); BOOST_CHECK_EQUAL(c.getLEDMon(), false); BOOST_CHECK_EQUAL(c.getTRU(), false); c.setLEDMon(); BOOST_CHECK_EQUAL(c.getTower(), 0); - BOOST_CHECK_EQUAL(c.getTimeStamp(), 0); + BOOST_CHECK_SMALL(double(c.getTimeStamp()), 0.73); BOOST_CHECK_EQUAL(c.getEnergy(), 0); BOOST_CHECK_EQUAL(c.getLowGain(), false); BOOST_CHECK_EQUAL(c.getHighGain(), false); @@ -90,7 +96,7 @@ BOOST_AUTO_TEST_CASE(Cell_test) c.setTRU(); BOOST_CHECK_EQUAL(c.getTower(), 0); - BOOST_CHECK_EQUAL(c.getTimeStamp(), 0); + BOOST_CHECK_SMALL(double(c.getTimeStamp()), 0.73); BOOST_CHECK_EQUAL(c.getEnergy(), 0); BOOST_CHECK_EQUAL(c.getLowGain(), false); BOOST_CHECK_EQUAL(c.getHighGain(), false); From 99c695adf4de3bf9e48783ee0db6d8b628774dc0 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 28 Oct 2020 22:04:27 +0100 Subject: [PATCH 1145/1751] Use simple TF counter in CTF name instead of 1st TF orbit Temporary measure to avoid ovewriting the CTF in case of multiple TFs processing. Will be reverted once DPL will propagate the 1st TF orbit. --- Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index a71affd80a35d..127d913c229bb 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -84,7 +84,9 @@ void CTFWriterSpec::run(ProcessingContext& pc) std::unique_ptr<TFile> fileOut; std::unique_ptr<TTree> treeOut; if (mWriteCTF) { - fileOut.reset(TFile::Open(o2::base::NameConf::getCTFFileName(tfOrb).c_str(), "recreate")); + // fileOut.reset(TFile::Open(o2::base::NameConf::getCTFFileName(tfOrb).c_str(), "recreate")); + // RS Until the DPL will propagate the firstTForbit, we will use simple counter in CTF file name to avoid overwriting in case of multiple TFs + fileOut.reset(TFile::Open(o2::base::NameConf::getCTFFileName(mNTF).c_str(), "recreate")); treeOut = std::make_unique<TTree>(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); } From ef71fd24d104e91b546db2f5ab9492aedcf8d617 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Thu, 29 Oct 2020 04:36:00 +0300 Subject: [PATCH 1146/1751] Detectors/CPV,CTF,FIT,HMPID: make readability-braces-around-statements happy --- Detectors/CPV/calib/src/BadChannelMap.cxx | 3 +- .../CPV/reconstruction/src/Clusterer.cxx | 12 ++-- .../include/CPVSimulation/GeometryParams.h | 9 ++- Detectors/CPV/workflow/src/RecoWorkflow.cxx | 3 +- Detectors/CTF/test/test_ctf_io_tof.cxx | 3 +- .../FDD/reconstruction/src/Reconstructor.cxx | 6 +- .../include/FDDSimulation/Detector.h | 3 +- .../FIT/FDD/simulation/src/Digitizer.cxx | 25 ++++--- Detectors/FIT/FT0/base/src/Geometry.cxx | 6 +- .../FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h | 3 +- .../include/FT0Reconstruction/ReadRaw.h | 6 +- .../FIT/FT0/reconstruction/src/ReadRaw.cxx | 6 +- .../include/FT0Simulation/Digitizer.h | 9 ++- .../include/FT0Simulation/Digits2Raw.h | 6 +- Detectors/FIT/FT0/simulation/src/Detector.cxx | 6 +- .../FIT/FT0/simulation/src/Digitizer.cxx | 18 +++-- .../FIT/FT0/simulation/src/Digits2Raw.cxx | 15 +++-- .../include/FT0Workflow/RawReaderFT0.h | 6 +- .../workflow/src/FT0DataProcessDPLSpec.cxx | 3 +- .../FIT/FT0/workflow/src/FT0Workflow.cxx | 6 +- .../FIT/FV0/reconstruction/src/ReadRaw.cxx | 3 +- .../FIT/FV0/simulation/src/Digitizer.cxx | 3 +- .../FIT/raw/include/FITRaw/DataBlockBase.h | 15 +++-- .../FIT/raw/include/FITRaw/RawReaderBase.h | 5 +- .../HMPID/base/include/HMPIDBase/Param.h | 6 +- Detectors/HMPID/base/src/Param.cxx | 67 ++++++++++++------- Detectors/HMPID/simulation/src/Detector.cxx | 62 +++++++++++------ 27 files changed, 207 insertions(+), 108 deletions(-) diff --git a/Detectors/CPV/calib/src/BadChannelMap.cxx b/Detectors/CPV/calib/src/BadChannelMap.cxx index b453b8e030903..92bf6f77f2cb1 100644 --- a/Detectors/CPV/calib/src/BadChannelMap.cxx +++ b/Detectors/CPV/calib/src/BadChannelMap.cxx @@ -79,8 +79,9 @@ void BadChannelMap::PrintStream(std::ostream& stream) const // first sort bad channel IDs stream << "Number of bad cells: " << mBadCells.count() << "\n"; for (int cellID = 0; cellID < mBadCells.size(); cellID++) { - if (mBadCells.test(cellID)) + if (mBadCells.test(cellID)) { stream << cellID << "\n"; + } } } diff --git a/Detectors/CPV/reconstruction/src/Clusterer.cxx b/Detectors/CPV/reconstruction/src/Clusterer.cxx index 74105acc4f378..5af836e70d79e 100644 --- a/Detectors/CPV/reconstruction/src/Clusterer.cxx +++ b/Detectors/CPV/reconstruction/src/Clusterer.cxx @@ -40,8 +40,9 @@ void Clusterer::process(gsl::span<const Digit> digits, gsl::span<const TriggerRe { clusters->clear(); //final out list of clusters trigRec->clear(); - if (cluMC) + if (cluMC) { cluMC->clear(); + } for (const auto& tr : dtr) { mFirstDigitInEvent = tr.getFirstEntry(); @@ -103,8 +104,9 @@ void Clusterer::makeClusters(gsl::span<const Digit> digits) int iFirst = mFirstDigitInEvent; // first index of digit which potentially can be a part of cluster for (int i = iFirst; i < mLastDigitInEvent; i++) { - if (digitsUsed[i - mFirstDigitInEvent]) + if (digitsUsed[i - mFirstDigitInEvent]) { continue; + } const Digit& digitSeed = digits[i]; float digitSeedEnergy = calibrate(digitSeed.getAmplitude(), digitSeed.getAbsId()); @@ -134,8 +136,9 @@ void Clusterer::makeClusters(gsl::span<const Digit> digits) short digitSeedAbsId = clu->getDigitAbsId(index); index++; for (Int_t j = iFirst; j < mLastDigitInEvent; j++) { - if (digitsUsed[j - mFirstDigitInEvent]) + if (digitsUsed[j - mFirstDigitInEvent]) { continue; // look through remaining digits + } const Digit* digitN = &(digits[j]); float digitNEnergy = calibrate(digitN->getAmplitude(), digitN->getAbsId()); if (isBadChannel(digitN->getAbsId())) { //remove digit @@ -251,8 +254,9 @@ void Clusterer::unfoldOneCluster(FullCluster& iniClu, char nMax, gsl::span<int> a[iclu] += mfij[idig][iclu] * mfij[idig][iclu]; b[iclu] += it.energy * mfij[idig][iclu]; for (int kclu = 0; kclu < nMax; kclu++) { - if (iclu == kclu) + if (iclu == kclu) { continue; + } c[iclu] += eMax[kclu] * mfij[idig][iclu] * mfij[idig][kclu]; } } diff --git a/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h b/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h index 26ffdc379dcd4..7c40586b518f7 100644 --- a/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h +++ b/Detectors/CPV/simulation/include/CPVSimulation/GeometryParams.h @@ -41,17 +41,20 @@ class GeometryParams final : public TNamed void GetModuleAngle(int module, float angle[3][2]) const { - for (int i = 0; i < 3; i++) - for (int ian = 0; ian < 2; ian++) + for (int i = 0; i < 3; i++) { + for (int ian = 0; ian < 2; ian++) { angle[i][ian] = mModuleAngle[module][i][ian]; + } + } } float GetCPVAngle(Int_t index) const { return mCPVAngle[index - 1]; } void GetModuleCenter(int module, float* pos) const { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { pos[i] = mModuleCenter[module][i]; + } } int GetNModules() const { return mNModules; } diff --git a/Detectors/CPV/workflow/src/RecoWorkflow.cxx b/Detectors/CPV/workflow/src/RecoWorkflow.cxx index 50d860a856c25..82bc452753350 100644 --- a/Detectors/CPV/workflow/src/RecoWorkflow.cxx +++ b/Detectors/CPV/workflow/src/RecoWorkflow.cxx @@ -95,8 +95,9 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, o2::framework::OutputSpec{"CPV", "DIGITSMCTR"}}, propagateMC)); - if (enableDigitsPrinter) + if (enableDigitsPrinter) { specs.emplace_back(o2::cpv::reco_workflow::getPhosDigitsPrinterSpec()); + } if (isEnabled(OutputType::Clusters)) { // add clusterizer diff --git a/Detectors/CTF/test/test_ctf_io_tof.cxx b/Detectors/CTF/test/test_ctf_io_tof.cxx index dce6d920c19e6..27810fc5b9292 100644 --- a/Detectors/CTF/test/test_ctf_io_tof.cxx +++ b/Detectors/CTF/test/test_ctf_io_tof.cxx @@ -67,8 +67,9 @@ BOOST_AUTO_TEST_CASE(CompressedClustersTest) [](const Digit& a, const Digit& b) { int strip1 = a.getChannel() / Geo::NPADS, strip2 = b.getChannel() / Geo::NPADS; if (strip1 == strip2) { - if (a.getBC() == b.getBC()) + if (a.getBC() == b.getBC()) { return a.getTDC() < b.getTDC(); + } return a.getBC() < b.getBC(); } return strip1 < strip2; diff --git a/Detectors/FIT/FDD/reconstruction/src/Reconstructor.cxx b/Detectors/FIT/FDD/reconstruction/src/Reconstructor.cxx index 30cc96d5a0aa6..7bfcca22dedb1 100644 --- a/Detectors/FIT/FDD/reconstruction/src/Reconstructor.cxx +++ b/Detectors/FIT/FDD/reconstruction/src/Reconstructor.cxx @@ -28,11 +28,13 @@ void Reconstructor::process(const o2::fdd::Digit& digitBC, gsl::span<const o2::f Float_t adc = channel.mChargeADC; Float_t time = channel.mTime; //LOG(INFO) <<adc <<" "<<time; - if (time == o2::InteractionRecord::DummyTime) + if (time == o2::InteractionRecord::DummyTime) { continue; + } Float_t timeErr = 1; - if (adc > 1) + if (adc > 1) { timeErr = 1 / adc; + } if (channel.mPMNumber < 8) { timeFDC += time / (timeErr * timeErr); weightFDC += 1. / (timeErr * timeErr); diff --git a/Detectors/FIT/FDD/simulation/include/FDDSimulation/Detector.h b/Detectors/FIT/FDD/simulation/include/FDDSimulation/Detector.h index 2f5862e960568..9ea50b4ee45fb 100644 --- a/Detectors/FIT/FDD/simulation/include/FDDSimulation/Detector.h +++ b/Detectors/FIT/FDD/simulation/include/FDDSimulation/Detector.h @@ -52,8 +52,9 @@ class Detector : public o2::base::DetImpl<Detector> std::vector<o2::fdd::Hit>* getHits(Int_t iColl) { - if (iColl == 0) + if (iColl == 0) { return mHits; + } return nullptr; } diff --git a/Detectors/FIT/FDD/simulation/src/Digitizer.cxx b/Detectors/FIT/FDD/simulation/src/Digitizer.cxx index e3909e028b80f..fdb232dc95d66 100644 --- a/Detectors/FIT/FDD/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FDD/simulation/src/Digitizer.cxx @@ -90,17 +90,19 @@ void Digitizer::createPulse(int nPhE, int parID, double timeHit, std::array<o2:: double time0 = cachedIR[0].bc2ns(); // start time of the 1st cashed BC float timeDiff = time0 - timeHit; - if (channel < 9) + if (channel < 9) { timeDiff += parameters.TimeDelayFDC; - else + } else { timeDiff += parameters.TimeDelayFDA; + } //LOG(INFO) <<"Ch = "<<channel<<" NphE = " << nPhE <<" timeDiff "<<timeDiff; float charge = TMath::Qe() * parameters.PmGain * mBinSize / (mPmtTimeIntegral * ChargePerADC); Bool_t added[nCachedIR]; - for (int ir = 0; ir < nCachedIR; ir++) + for (int ir = 0; ir < nCachedIR; ir++) { added[ir] = kFALSE; + } constexpr float BinSizeInv = 1.0 / mBinSize; for (int iPhE = 0; iPhE < nPhE; ++iPhE) { @@ -195,8 +197,9 @@ void Digitizer::storeBC(const BCCache& bc, int nBC = digitsBC.size(); digitsBC.emplace_back(first, 16, bc, mTriggers); - for (const auto& lbl : bc.labels) + for (const auto& lbl : bc.labels) { labels.addElement(nBC, lbl); + } } //_____________________________________________________________________________ @@ -221,10 +224,11 @@ float Digitizer::simulateTimeCFD(const ChannelBCDataF& pulse) int binShift = TMath::Nint(parameters.TimeShiftCFD / mBinSize); for (int iBin = 0; iBin < NTimeBinsPerBC; ++iBin) { //if (mTime[channel][iBin] != 0) std::cout << mTime[channel][iBin] / parameters.mChargePerADC << ", "; - if (iBin >= binShift) + if (iBin >= binShift) { mTimeCFD[iBin] = 5.0 * pulse[iBin - binShift] - pulse[iBin]; - else + } else { mTimeCFD[iBin] = -1.0 * pulse[iBin]; + } } for (int iBin = 1; iBin < NTimeBinsPerBC; ++iBin) { if (mTimeCFD[iBin - 1] < 0 && mTimeCFD[iBin] >= 0) { @@ -328,8 +332,9 @@ void Digitizer::finish() {} int Digitizer::simulateLightYield(int pmt, int nPhot) { const float p = parameters.LightYield * PhotoCathodeEfficiency; - if (p == 1.0f || nPhot == 0) + if (p == 1.0f || nPhot == 0) { return nPhot; + } const int n = int(nPhot < 100 ? gRandom->Binomial(nPhot, p) : gRandom->Gaus(p * nPhot + 0.5, TMath::Sqrt(p * (1 - p) * nPhot))); return n; } @@ -350,8 +355,9 @@ Double_t Digitizer::SinglePhESpectrum(Double_t* x, Double_t*) { // this function describes the PM amplitude response to a single photoelectron Double_t y = x[0]; - if (y < 0) + if (y < 0) { return 0; + } return (TMath::Poisson(y, PMNbOfSecElec) + PMTransparency * TMath::Poisson(y, 1.0)); } //______________________________________________________________ @@ -361,8 +367,9 @@ void Digitizer::BCCache::print() const for (int ic = 0; ic < 16; ic++) { printf("Ch[%d] | ", ic); for (int ib = 0; ib < NTimeBinsPerBC; ib++) { - if (ib % 10 == 0) + if (ib % 10 == 0) { printf("%f ", pulse[ic][ib]); + } } printf("\n"); } diff --git a/Detectors/FIT/FT0/base/src/Geometry.cxx b/Detectors/FIT/FT0/base/src/Geometry.cxx index ef2712bc789ee..6d30591501427 100644 --- a/Detectors/FIT/FT0/base/src/Geometry.cxx +++ b/Detectors/FIT/FT0/base/src/Geometry.cxx @@ -90,8 +90,10 @@ Geometry::Geometry() : mMCP{{0, 0, 0}} gc[i] = -1 * ac[i]; } // Set coordinate - for (int ipmt = 0; ipmt < 24; ipmt++) + for (int ipmt = 0; ipmt < 24; ipmt++) { mMCP[ipmt].SetXYZ(xa[ipmt], xa[ipmt], zDetA); - for (int ipmt = 24; ipmt < 52; ipmt++) + } + for (int ipmt = 24; ipmt < 52; ipmt++) { mMCP[ipmt].SetXYZ(xc2[ipmt - 24], yc2[ipmt - 24], zc2[ipmt - 24]); + } } diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h index 30bf27f61dd0e..407fba225fc1d 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h @@ -55,8 +55,9 @@ class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> // put here code for raw data checking void sanityCheck(bool& flag) { - if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) + if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) { DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling + } //TODO, Descriptor checking, Channel range } }; diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h index 47e83b3c16426..84185564bb6a5 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h @@ -60,9 +60,11 @@ class ReadRaw static o2::ft0::LookUpTable linear() { std::vector<o2::ft0::Topo> lut_data(Nchannels_PM * NPMs); - for (int link = 0; link < NPMs; ++link) - for (int mcp = 0; mcp < Nchannels_PM; ++mcp) + for (int link = 0; link < NPMs; ++link) { + for (int mcp = 0; mcp < Nchannels_PM; ++mcp) { lut_data[link * Nchannels_PM + mcp] = o2::ft0::Topo{link, mcp}; + } + } return o2::ft0::LookUpTable{lut_data}; } diff --git a/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx b/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx index 27c6008b33ab0..bd72a9f5a7625 100644 --- a/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx @@ -173,8 +173,9 @@ void ReadRaw::readData(const std::string fileRaw, const o2::ft0::LookUpTable& lu void ReadRaw::close() { LOG(INFO) << " CLOSE "; - if (mFileDest.is_open()) + if (mFileDest.is_open()) { mFileDest.close(); + } } //_____________________________________________________________________________ void ReadRaw::writeDigits(std::string fileDataOut) @@ -196,8 +197,9 @@ void ReadRaw::writeDigits(std::string fileDataOut) std::vector<o2::ft0::ChannelData> chDataVec; digitVec.reserve(mDigitAccum.size()); size_t numberOfChData = 0; - for (auto const& [intrec, digit] : mDigitAccum) + for (auto const& [intrec, digit] : mDigitAccum) { numberOfChData += digit.getChDgData().size(); + } chDataVec.reserve(numberOfChData); for (auto& [intrec, digit] : mDigitAccum) { int first = gsl::narrow_cast<int>(chDataVec.size()); diff --git a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h index c53064101a6e7..faf0576122531 100644 --- a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h +++ b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h @@ -94,8 +94,9 @@ class Digitizer protected: inline float signalForm(float x) const { // table lookup for the signal shape - if (x <= 0.0f) + if (x <= 0.0f) { return 0.0f; + } float const y = x / mParameters.bunchWidth * DP::SIGNAL_TABLE_SIZE; int const index = std::floor(y); if (index + 1 >= DP::SIGNAL_TABLE_SIZE) { @@ -112,8 +113,9 @@ class Digitizer auto const rem = y - index; Vc::float_v val(0); for (size_t i = 0; i < float_v::size(); ++i) { - if (y[i] < 0.0f) + if (y[i] < 0.0f) { continue; + } if (index[i] + 1 < DP::SIGNAL_TABLE_SIZE) { val[i] = mSignalTable[index[i]] + rem[i] * (mSignalTable[index[i] + 1] - mSignalTable[index[i]]); } else { @@ -170,8 +172,9 @@ inline float signalForm_integral(float x) using namespace std; double const a = -0.45458; double const b = -0.83344945; - if (x < 0) + if (x < 0) { x = 0; + } return -(exp(b * x) / b - exp(a * x) / a) / 7.8446501; }; diff --git a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h index 9cbfa837a0881..4a4b4cabd3f15 100644 --- a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h +++ b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h @@ -59,9 +59,11 @@ class Digits2Raw static o2::ft0::LookUpTable linear() { std::vector<o2::ft0::Topo> lut_data(Nchannels_PM * (NPMs - 1)); - for (int link = 0; link < NPMs - 1; ++link) - for (int mcp = 0; mcp < Nchannels_PM; ++mcp) + for (int link = 0; link < NPMs - 1; ++link) { + for (int mcp = 0; mcp < Nchannels_PM; ++mcp) { lut_data[link * Nchannels_PM + mcp] = o2::ft0::Topo{link, mcp}; + } + } return o2::ft0::LookUpTable{lut_data}; } diff --git a/Detectors/FIT/FT0/simulation/src/Detector.cxx b/Detectors/FIT/FT0/simulation/src/Detector.cxx index 961b8bd5e5c67..6becdfbf2866c 100644 --- a/Detectors/FIT/FT0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FT0/simulation/src/Detector.cxx @@ -478,8 +478,9 @@ void Detector::DefineOpticalProperties() // Path of the optical properties input file TString inputDir; const char* aliceO2env = std::getenv("O2_ROOT"); - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/FT0/files/"; TString optPropPath = inputDir + "quartzOptProperties.txt"; @@ -560,8 +561,9 @@ Bool_t Detector::RegisterPhotoE(float energy) { float eff = mPMTeff->Eval(energy); float p = gRandom->Rndm(); - if (p > eff) + if (p > eff) { return kFALSE; + } return kTRUE; } diff --git a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx index d34d5f22aec8f..3cde3b5b42ef6 100644 --- a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx @@ -161,15 +161,17 @@ void Digitizer::process(const std::vector<o2::ft0::HitType>* hits, Int_t parent = -10; for (auto const& hit : *hits) { - if (hit.GetEnergyLoss() > 0) + if (hit.GetEnergyLoss() > 0) { continue; + } Int_t hit_ch = hit.GetDetectorID(); Bool_t is_A_side = (hit_ch < 4 * mParameters.nCellsA); Float_t time_compensate = is_A_side ? mParameters.A_side_cable_cmps : mParameters.C_side_cable_cmps; Double_t hit_time = hit.GetTime() - time_compensate; - if (hit_time > 250) + if (hit_time > 250) { continue; //not collect very slow particles + } auto relBC = o2::InteractionRecord{hit_time}; if (mCache.size() <= relBC.bc) { mCache.resize(relBC.bc + 1); @@ -189,8 +191,9 @@ void Digitizer::storeBC(BCCache& bc, std::vector<o2::ft0::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& labels) { - if (bc.hits.empty()) + if (bc.hits.empty()) { return; + } int n_hit_A = 0, n_hit_C = 0, mean_time_A = 0, mean_time_C = 0; int summ_ampl_A = 0, summ_ampl_C = 0; int vertex_time; @@ -216,14 +219,16 @@ void Digitizer::storeBC(BCCache& bc, mDeadTimes[ipmt].intrec = firstBCinDeque; mDeadTimes[ipmt].deadTime = cfd.deadTime; - if (!cfd.particle) + if (!cfd.particle) { continue; + } int smeared_time = 1000. * (*cfd.particle - mParameters.mCfdShift) * mParameters.ChannelWidthInverse; bool is_time_in_signal_gate = (smeared_time > -mParameters.mTime_trg_gate && smeared_time < mParameters.mTime_trg_gate); float charge = measure_amplitude(channel_times) * mParameters.charge2amp; float amp = is_time_in_signal_gate ? mParameters.mV_2_Nchannels * charge : 0; - if (amp > 4095) + if (amp > 4095) { amp = 4095; + } LOG(DEBUG) << mEventID << " bc " << firstBCinDeque.bc << " orbit " << firstBCinDeque.orbit << ", ipmt " << ipmt << ", smeared_time " << smeared_time << " nStored " << nStored; digitsCh.emplace_back(ipmt, smeared_time, int(amp), chain); nStored++; @@ -264,8 +269,9 @@ void Digitizer::storeBC(BCCache& bc, digitsBC.emplace_back(first, nStored, firstBCinDeque, triggers, mEventID - 1); size_t const nBC = digitsBC.size(); - for (auto const& lbl : bc.labels) + for (auto const& lbl : bc.labels) { labels.addElement(nBC - 1, lbl); + } } // Debug output ------------------------------------------------------------- diff --git a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx index 6986a709b1bca..d564780137f2e 100644 --- a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx @@ -114,8 +114,9 @@ void Digits2Raw::readDigits(const std::string& outDir, const std::string& fileDi auto& bcd = digitsBC[ibc]; intRecord = bcd.getIntRecord(); auto channels = bcd.getBunchChannelData(digitsCh); - if (!channels.empty()) + if (!channels.empty()) { convertDigits(bcd, channels, lut, intRecord); + } } } } @@ -136,8 +137,9 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, if (oldlink >= 0) { uint nGBTWords = uint((nchannels + 1) / 2); LOG(DEBUG) << " oldlink " << oldlink << " nGBTWords " << nGBTWords; - if ((nchannels % 2) == 1) + if ((nchannels % 2) == 1) { mRawEventData.mEventData[nchannels] = {}; + } mRawEventData.mEventHeader.nGBTWords = nGBTWords; auto data = mRawEventData.to_vector(false); mLinkID = uint32_t(oldlink); @@ -160,8 +162,9 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, } // fill mEventData[nchannels] with 0s to flag that this is a dummy data uint nGBTWords = uint((nchannels + 1) / 2); - if ((nchannels % 2) == 1) + if ((nchannels % 2) == 1) { mRawEventData.mEventData[nchannels] = {}; + } mRawEventData.mEventHeader.nGBTWords = nGBTWords; auto datalast = mRawEventData.to_vector(false); mLinkID = uint32_t(oldlink); @@ -176,10 +179,12 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, float ampA = mTriggers.amplA; float ampC = mTriggers.amplC; - if (ampA > 131071) + if (ampA > 131071) { ampA = 131071; //2^17 - if (ampC > 131071) + } + if (ampC > 131071) { ampC = 131071; //2^17 + } tcmdata.vertex = mTriggers.getVertex(); tcmdata.orA = mTriggers.getOrA(); tcmdata.orC = mTriggers.getOrC(); diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h index ca97dfeb1cccb..20adeed3cda20 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h @@ -52,8 +52,9 @@ class RawReaderFT0 : public RawReaderFT0BaseNorm getDigits(mVecDigits, mVecChannelData); LOG(INFO) << "Number of Digits: " << mVecDigits.size(); LOG(INFO) << "Number of ChannelData: " << mVecChannelData.size(); - if (mDumpData) + if (mDumpData) { DigitBlockFT0::print(mVecDigits, mVecChannelData); + } } static void prepareOutputSpec(std::vector<o2::framework::OutputSpec>& outputSpec) { @@ -91,8 +92,9 @@ class RawReaderFT0ext : public RawReaderFT0BaseExt LOG(INFO) << "Number of Digits: " << mVecDigitsExt.size(); LOG(INFO) << "Number of ChannelData: " << mVecChannelData.size(); LOG(INFO) << "Number of TriggerExt: " << mVecTrgExt.size(); - if (mDumpData) + if (mDumpData) { DigitBlockFT0ext::print(mVecDigitsExt, mVecChannelData, mVecTrgExt); + } } static void prepareOutputSpec(std::vector<o2::framework::OutputSpec>& outputSpec) { diff --git a/Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx b/Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx index 7fe7de20506b9..9ad55e06a8c56 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0DataProcessDPLSpec.cxx @@ -28,8 +28,9 @@ void FT0DataProcessDPLSpec::run(ProcessingContext& pc) LOG(INFO) << "FT0DataProcessDPLSpec running..."; auto vecDigits = pc.inputs().get<std::vector<Digit>>("digits"); auto vecChannelData = pc.inputs().get<std::vector<ChannelData>>("digch"); - if (mDumpEventBlocks) + if (mDumpEventBlocks) { DigitBlockFT0::print(vecDigits, vecChannelData); + } } DataProcessorSpec getFT0DataProcessDPLSpec(bool dumpProcessor) diff --git a/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx index ada920a29c99f..db4187ee49169 100644 --- a/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/FT0Workflow.cxx @@ -31,10 +31,12 @@ framework::WorkflowSpec getFT0Workflow(bool isExtendedMode, bool useProcess, } else { specs.emplace_back(o2::ft0::getFT0DataReaderDPLSpec(RawReaderFT0{dumpReader})); } - if (useProcess) + if (useProcess) { specs.emplace_back(o2::ft0::getFT0DataProcessDPLSpec(dumpProcessor)); - if (!disableRootOut) + } + if (!disableRootOut) { specs.emplace_back(o2::ft0::getFT0DigitWriterDPLSpec()); + } return specs; } diff --git a/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx b/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx index ab8902f6dca54..db2dd6e2c33ca 100644 --- a/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx +++ b/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx @@ -121,8 +121,9 @@ void ReadRaw::readRawData(const LookUpTable& lut) void ReadRaw::close() { - if (mRawFileIn.is_open()) + if (mRawFileIn.is_open()) { mRawFileIn.close(); + } } void ReadRaw::writeDigits(const std::string& outputDigitsFilePath) diff --git a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx index 146e47705fd87..c457619ef529a 100644 --- a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx @@ -202,8 +202,9 @@ void Digitizer::storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsB double cfdWithOffset = SimulateTimeCfd(bc.mPmtChargeVsTime[iPmt]); double cfdZero = cfdWithOffset - FV0DigParam::Instance().avgCfdTimeForMip; - if (cfdZero < -FV0DigParam::Instance().cfdCheckWindow || cfdZero > FV0DigParam::Instance().cfdCheckWindow) + if (cfdZero < -FV0DigParam::Instance().cfdCheckWindow || cfdZero > FV0DigParam::Instance().cfdCheckWindow) { continue; + } //LOG(INFO) << "time inside analyse and store =========> " << cfdZero <<" detid "<<iPmt; float charge = IntegrateCharge(bc.mPmtChargeVsTime[iPmt]); diff --git a/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h b/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h index 64842fd2bcae4..c200070b6c258 100644 --- a/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h +++ b/Detectors/FIT/raw/include/FITRaw/DataBlockBase.h @@ -66,8 +66,9 @@ struct DataBlockWrapper { { std::vector<uint8_t> vecBytes(sizeWord * nWords); uint8_t* srcAddress = (uint8_t*)mData; - if (nWords == 0 || nWords > MaxNwords) + if (nWords == 0 || nWords > MaxNwords) { return std::move(vecBytes); + } gsl::span<uint8_t> serializedBytes(vecBytes); size_t countBytes = 0; int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords]); @@ -125,10 +126,12 @@ struct DataBlockWrapper { payloadPerElem -= payloadInWord; payloadInWord = 0; } - if (payloadInWord == 0) + if (payloadInWord == 0) { payloadInWord = T::PayloadPerGBTword; - if (payloadPerElem == 0) + } + if (payloadPerElem == 0) { payloadPerElem = T::PayloadSize; + } } return count; } @@ -193,8 +196,9 @@ struct DataBlockWrapper { bytesInWord = 0; } - if (payloadInWord == 0) + if (payloadInWord == 0) { payloadInWord = T::PayloadPerGBTword; + } if (payloadPerElem == 0) { payloadPerElem = T::PayloadSize; countElement++; @@ -236,8 +240,9 @@ struct DataBlockWrapper { } countWord++; } - if (payloadPerElem == 0) + if (payloadPerElem == 0) { payloadPerElem = T::PayloadSize; + } payloadPerElem -= std::get<kNBYTES>((GetByteLookupTable())[iStep]); } //Last step checking diff --git a/Detectors/FIT/raw/include/FITRaw/RawReaderBase.h b/Detectors/FIT/raw/include/FITRaw/RawReaderBase.h index bc290305c5bca..bea49dd68fc07 100644 --- a/Detectors/FIT/raw/include/FITRaw/RawReaderBase.h +++ b/Detectors/FIT/raw/include/FITRaw/RawReaderBase.h @@ -49,10 +49,11 @@ class RawReaderBase DataBlockType dataBlock; dataBlock.decodeBlock(binaryPayload, srcPos); srcPos += dataBlock.mSize; - if (dataBlock.isCorrect()) + if (dataBlock.isCorrect()) { vecDataBlocks.push_back(dataBlock); //change to in-place construction? TODO - else + } else { LOG(INFO) << "WARNING! INCORRECT DATA BLOCK!"; + } } return srcPos; } diff --git a/Detectors/HMPID/base/include/HMPIDBase/Param.h b/Detectors/HMPID/base/include/HMPIDBase/Param.h index c71cf5942a331..d94a6c2caee95 100644 --- a/Detectors/HMPID/base/include/HMPIDBase/Param.h +++ b/Detectors/HMPID/base/include/HMPIDBase/Param.h @@ -119,16 +119,18 @@ class Param static Int_t InHVSector(float y); //find HV sector static Int_t Radiator(float y) { - if (InHVSector(y) < 0) + if (InHVSector(y) < 0) { return -1; + } return InHVSector(y) / 2; } // height in the radiator to estimate temperature from gradient static double HinRad(float y) { - if (Radiator(y) < 0) + if (Radiator(y) < 0) { return -1; + } return y - Radiator(y) * fgkMinPcY[Radiator(y)]; } //is point inside chamber boundaries? diff --git a/Detectors/HMPID/base/src/Param.cxx b/Detectors/HMPID/base/src/Param.cxx index 3a75748b7ab12..9358bc480e691 100644 --- a/Detectors/HMPID/base/src/Param.cxx +++ b/Detectors/HMPID/base/src/Param.cxx @@ -93,13 +93,15 @@ Param::Param(bool noGeo) : mX(0), mY(0), mRefIdx(1.28947), mPhotEMean(6.675), mT float dead = 2.6; // cm of the dead zones between PCs-> See 2CRC2099P1 - if (noGeo == kTRUE) + if (noGeo == kTRUE) { fgInstanceType = kFALSE; //instance from ideal geometry, no actual geom is present + } if (noGeo == kFALSE && !gGeoManager) { TGeoManager::Import("geometry.root"); - if (!gGeoManager) + if (!gGeoManager) { Printf("!!!!!!No geometry loaded!!!!!!!"); + } } fgCellX = 0.8; @@ -150,7 +152,7 @@ Param::Param(bool noGeo) : mX(0), mY(0), mRefIdx(1.28947), mPhotEMean(6.675), mT } } - for (Int_t i = kMinCh; i <= kMaxCh; i++) + for (Int_t i = kMinCh; i <= kMaxCh; i++) { if (gGeoManager && gGeoManager->IsClosed()) { TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(Form("/HMPID/Chamber%i", i)); if (!pne) { @@ -159,9 +161,9 @@ Param::Param(bool noGeo) : mX(0), mY(0), mRefIdx(1.28947), mPhotEMean(6.675), mT IdealPosition(i, mM[i]); } else { TGeoPhysicalNode* pnode = pne->GetPhysicalNode(); - if (pnode) + if (pnode) { mM[i] = new TGeoHMatrix(*(pnode->GetMatrix())); - else { + } else { mM[i] = new TGeoHMatrix; IdealPosition(i, mM[i]); } @@ -170,6 +172,7 @@ Param::Param(bool noGeo) : mX(0), mY(0), mRefIdx(1.28947), mPhotEMean(6.675), mT mM[i] = new TGeoHMatrix; IdealPosition(i, mM[i]); } + } fgInstance = this; } //ctor //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -177,8 +180,9 @@ void Param::Print(Option_t* opt) const { // print some usefull (hopefully) info on some internal guts of HMPID parametrisation - for (Int_t i = 0; i < 7; i++) + for (Int_t i = 0; i < 7; i++) { mM[i]->Print(opt); + } } //Print() //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Param::IdealPosition(Int_t iCh, TGeoHMatrix* pMatrix) @@ -284,10 +288,12 @@ double Param::Sigma2(double trkTheta, double trkPhi, double ckovTh, double ckovP TVector3 v(-999, -999, -999); double trkBeta = 1. / (TMath::Cos(ckovTh) * GetRefIdx()); - if (trkBeta > 1) + if (trkBeta > 1) { trkBeta = 1; //protection against bad measured thetaCer - if (trkBeta < 0) + } + if (trkBeta < 0) { trkBeta = 0.0001; // + } v.SetX(SigLoc(trkTheta, trkPhi, ckovTh, ckovPh, trkBeta)); v.SetY(SigGeom(trkTheta, trkPhi, ckovTh, ckovPh, trkBeta)); @@ -318,8 +324,9 @@ double Param::SigLoc(double trkTheta, double trkPhi, double thetaC, double phiC, double alpha = cost - tantheta * cosfd * sint; // formula (11) double k = 1. - GetRefIdx() * GetRefIdx() + alpha * alpha / (betaM * betaM); // formula (after 8 in the text) - if (k < 0) + if (k < 0) { return 1e10; + } double mu = sint * sinf + tantheta * (cost * cosfd * sinf + sinfd * cosf); // formula (10) double e = sint * cosf + tantheta * (cost * cosfd * cosf - sinfd * sinf); // formula (9) @@ -381,8 +388,9 @@ double Param::SigGeom(double trkTheta, double trkPhi, double thetaC, double phiC double alpha = cost - tantheta * cosfd * sint; // formula (11) double k = 1. - GetRefIdx() * GetRefIdx() + alpha * alpha / (betaM * betaM); // formula (after 8 in the text) - if (k < 0) + if (k < 0) { return 1e10; + } double eTr = 0.5 * RadThick() * betaM * TMath::Sqrt(k) / (GapThick() * alpha); // formula (14) double lambda = (1. - sint * sinf) * (1. + sint * sinf); // formula (15) @@ -427,8 +435,9 @@ Param* Param::Instance() // Return pointer to the AliHMPIDParam singleton. // Arguments: none // Returns: pointer to the instance of AliHMPIDParam or 0 if no geometry - if (!fgInstance) + if (!fgInstance) { new Param(kFALSE); //default setting for reconstruction, if no geometry.root -> AliFatal + } return fgInstance; } //Instance() @@ -438,8 +447,9 @@ Param* Param::InstanceNoGeo() // Return pointer to the AliHMPIDParam singleton without the geometry.root. // Arguments: none // Returns: pointer to the instance of AliHMPIDParam or 0 if no geometry - if (!fgInstance) + if (!fgInstance) { new Param(kTRUE); //to avoid AliFatal, for MOOD and displays, use ideal geometry parameters + } return fgInstance; } //Instance() //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -448,9 +458,11 @@ bool Param::IsInDead(float x, float y) // Check is the current point is outside of sensitive area or in dead zones // Arguments: x,y -position // Returns: 1 if not in sensitive zone - for (Int_t iPc = 0; iPc < 6; iPc++) - if (x >= fgkMinPcX[iPc] && x <= fgkMaxPcX[iPc] && y >= fgkMinPcY[iPc] && y <= fgkMaxPcY[iPc]) + for (Int_t iPc = 0; iPc < 6; iPc++) { + if (x >= fgkMinPcX[iPc] && x <= fgkMaxPcX[iPc] && y >= fgkMinPcY[iPc] && y <= fgkMaxPcY[iPc]) { return kFALSE; //in current pc + } + } return kTRUE; } @@ -461,8 +473,9 @@ bool Param::IsDeadPad(Int_t padx, Int_t pady, Int_t ch) // Arguments: padx,pady pad integer coord // Returns: kTRUE if dead, kFALSE if active - if (fgMapPad[padx - 1][pady - 1][ch]) + if (fgMapPad[padx - 1][pady - 1][ch]) { return kFALSE; //current pad active + } return kTRUE; } @@ -481,8 +494,9 @@ void Param::Lors2Pad(float x, float y, Int_t& pc, Int_t& px, Int_t& py) pc = 1; px = Int_t((x - fgkMinPcX[1]) / SizePadX()); } //PC 1 or 3 or 5 - else + else { return; + } if (y > fgkMinPcY[0] && y < fgkMaxPcY[0]) { py = Int_t(y / SizePadY()); } //PC 0 or 1 @@ -494,8 +508,9 @@ void Param::Lors2Pad(float x, float y, Int_t& pc, Int_t& px, Int_t& py) pc += 4; py = Int_t((y - fgkMinPcY[4]) / SizePadY()); } //PC 4 or 5 - else + else { return; + } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Int_t Param::InHVSector(float y) @@ -507,8 +522,9 @@ Int_t Param::InHVSector(float y) Int_t hvsec = -1; Int_t pc, px, py; Lors2Pad(1., y, pc, px, py); - if (py == -1) + if (py == -1) { return hvsec; + } hvsec = (py + (pc / 2) * (kMaxPy + 1)) / ((kMaxPy + 1) / 2); @@ -519,12 +535,15 @@ double Param::FindTemp(double tLow, double tHigh, double y) { // Model for gradient in temperature double yRad = HinRad(y); //height in a given radiator - if (tHigh < tLow) + if (tHigh < tLow) { tHigh = tLow; //if Tout < Tin consider just Tin as reference... - if (yRad < 0) + } + if (yRad < 0) { yRad = 0; //protection against fake y values - if (yRad > SizePcY()) + } + if (yRad > SizePcY()) { yRad = SizePcY(); //protection against fake y values + } double gradT = (tHigh - tLow) / SizePcY(); // linear gradient return gradT * yRad + tLow; @@ -589,13 +608,15 @@ void Param::PrintChStatus(Int_t ch) Printf(" --------- C H A M B E R %d ---------------", ch); for (Int_t pady = kMaxPcy; pady >= 0; pady--) { for (Int_t padx = 0; padx < kMaxPcx + 1; padx++) { - if (padx == 80) + if (padx == 80) { printf(" "); + } printf("%d", fgMapPad[padx][pady][ch]); } printf(" %d \n", pady + 1); - if (pady % 48 == 0) + if (pady % 48 == 0) { printf("\n"); + } } printf("\n"); } diff --git a/Detectors/HMPID/simulation/src/Detector.cxx b/Detectors/HMPID/simulation/src/Detector.cxx index 60ff9d033d970..89af501ba15cd 100644 --- a/Detectors/HMPID/simulation/src/Detector.cxx +++ b/Detectors/HMPID/simulation/src/Detector.cxx @@ -151,17 +151,19 @@ void Detector::GenFee(Float_t qtot) Double_t ranf[2]; fMC->GetRandom()->RndmArray(2, ranf); //Sample direction cthf = ranf[0] * 2 - 1.0; - if (cthf < 0) + if (cthf < 0) { continue; + } sthf = TMath::Sqrt((1. - cthf) * (1. + cthf)); phif = ranf[1] * 2 * TMath::Pi(); - if (Double_t randomNumber = fMC->GetRandom()->Rndm() <= 0.57) + if (Double_t randomNumber = fMC->GetRandom()->Rndm() <= 0.57) { enfp = 7.5e-9; - else if (randomNumber <= 0.7) + } else if (randomNumber <= 0.7) { enfp = 6.4e-9; - else + } else { enfp = 7.9e-9; + } dir[0] = sthf * TMath::Sin(phif); dir[1] = cthf; @@ -184,40 +186,49 @@ void Detector::GenFee(Float_t qtot) e3[2] = -dir[0]; vmod = 0; - for (j = 0; j < 3; j++) + for (j = 0; j < 3; j++) { vmod += e1[j] * e1[j]; - if (!vmod) + } + if (!vmod) { for (j = 0; j < 3; j++) { uswop = e1[j]; e1[j] = e3[j]; e3[j] = uswop; } + } vmod = 0; - for (j = 0; j < 3; j++) + for (j = 0; j < 3; j++) { vmod += e2[j] * e2[j]; - if (!vmod) + } + if (!vmod) { for (j = 0; j < 3; j++) { uswop = e2[j]; e2[j] = e3[j]; e3[j] = uswop; } + } vmod = 0; - for (j = 0; j < 3; j++) + for (j = 0; j < 3; j++) { vmod += e1[j] * e1[j]; + } vmod = TMath::Sqrt(1 / vmod); - for (j = 0; j < 3; j++) + for (j = 0; j < 3; j++) { e1[j] *= vmod; + } vmod = 0; - for (j = 0; j < 3; j++) + for (j = 0; j < 3; j++) { vmod += e2[j] * e2[j]; + } vmod = TMath::Sqrt(1 / vmod); - for (j = 0; j < 3; j++) + for (j = 0; j < 3; j++) { e2[j] *= vmod; + } phi = fMC->GetRandom()->Rndm() * 2 * TMath::Pi(); - for (j = 0; j < 3; j++) + for (j = 0; j < 3; j++) { pol[j] = e1[j] * TMath::Sin(phi) + e2[j] * TMath::Cos(phi); + } fMC->Gdtom(pol, pol, 2); Int_t outputNtracksStored; } //feedbacks loop @@ -242,8 +253,9 @@ Bool_t Detector::IsLostByFresnel() if (fMC->GetRandom()->Rndm() < Fresnel(p4.E() * 1e9, cotheta, 1)) { // AliDebug(1,"Photon lost"); return kTRUE; - } else + } else { return kFALSE; + } } //IsLostByFresnel() //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Float_t Detector::Fresnel(Float_t ene, Float_t pdoti, Bool_t pola) @@ -296,8 +308,9 @@ Float_t Detector::Fresnel(Float_t ene, Float_t pdoti, Bool_t pola) if (pola) { Float_t pdotr = 0.8; //DEGREE OF POLARIZATION : 1->P , -1->S fresn = 0.5 * (rp * (1 + pdotr) + rs * (1 - pdotr)); - } else + } else { fresn = 0.5 * (rp + rs); + } fresn = fresn * rO; return fresn; @@ -613,13 +626,16 @@ TGeoVolume* Detector::createChamber(int number) rad->AddNode(si1, 2, new TGeoTranslation(0 * mm, +204 * mm, -0.5 * mm)); rad->AddNode(si2, 1, new TGeoTranslation(-660 * mm, 0 * mm, -0.5 * mm)); rad->AddNode(si2, 2, new TGeoTranslation(+660 * mm, 0 * mm, -0.5 * mm)); - for (Int_t i = 0; i < 3; i++) - for (Int_t j = 0; j < 10; j++) + for (Int_t i = 0; i < 3; i++) { + for (Int_t j = 0; j < 10; j++) { rad->AddNode(spa, 10 * i + j, new TGeoTranslation(-1330 * mm / 2 + 116 * mm + j * 122 * mm, (i - 1) * 105 * mm, -0.5 * mm)); + } + } hmp->AddNode(fr4, 1, new TGeoTranslation(0 * mm, 0 * mm, 9.00 * mm)); // p.84 TDR - for (int i = 1; i <= 322; i++) + for (int i = 1; i <= 322; i++) { fr4->AddNode(col, i, new TGeoCombiTrans(0 * mm, -1296 / 2 * mm + i * 4 * mm, -5 * mm, rot)); // F4 2043P1 + } fr4->AddNode(f4a, 1, new TGeoTranslation(0 * mm, 0 * mm, 2.5 * mm)); f4a->AddNode(f4i, 1, new TGeoTranslation(0 * mm, 0 * mm, 0 * mm)); hmp->AddNode(sec, 4, new TGeoTranslation(-335 * mm, +433 * mm, 78.6 * mm)); @@ -1152,15 +1168,17 @@ TGeoVolume* Detector::CradleBaseVolume(TGeoMedium* med, Double_t l[7], const cha xtruOut->DefineSection(1, +l[4] / 2., 0., 0., 1.0); // 1= II plane z; Double_t tgalpha = 0; - if (xv[3] - xv[0] == 0) + if (xv[3] - xv[0] == 0) { tgalpha = 999999; - else + } else { tgalpha = l[2] / TMath::Abs(xv[3] - xv[0]); + } Double_t tgbeta = 0; - if (xv[2] - xv[1] == 0) + if (xv[2] - xv[1] == 0) { tgbeta = 999999; - else + } else { tgbeta = l[2] / TMath::Abs(xv[2] - xv[1]); + } xv[0] = xv[0] - l[5] / tgalpha; yv[0] = l[2] / 2 - l[5]; From b7a5f2cd899437a7a5b6c08d1ed8229bbe2c0b49 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Thu, 29 Oct 2020 01:10:35 +0300 Subject: [PATCH 1147/1751] Detectors/misc: make readability-braces-around-statements happy --- .../Base/include/DetectorsBase/Detector.h | 3 +- .../Base/include/DetectorsBase/MatLayerCyl.h | 3 +- Detectors/Base/src/MatLayerCyl.cxx | 6 +- Detectors/Base/src/MatLayerCylSet.cxx | 3 +- Detectors/Base/src/Ray.cxx | 3 +- .../TimeSlotCalibration.h | 7 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 168 ++++++++++++------ Detectors/GlobalTracking/src/MatchTPCITS.cxx | 12 +- .../tofworkflow/src/CalibInfoReaderSpec.cxx | 5 +- .../tofworkflow/src/tof-calibinfo-reader.cxx | 3 +- .../tofworkflow/src/tof-matcher-global.cxx | 6 +- .../tofworkflow/src/tof-matcher-tpc.cxx | 6 +- .../tofworkflow/src/tof-reco-workflow.cxx | 18 +- 13 files changed, 159 insertions(+), 84 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Detector.h b/Detectors/Base/include/DetectorsBase/Detector.h index 7a8877f00bab5..f37d2bc5b2ca2 100644 --- a/Detectors/Base/include/DetectorsBase/Detector.h +++ b/Detectors/Base/include/DetectorsBase/Detector.h @@ -363,8 +363,9 @@ class DetImpl : public o2::base::Detector } else { Int_t entries = origin.GetEntries(); Int_t nprimTot = 0; - for (auto entry = 0; entry < entries; entry++) + for (auto entry = 0; entry < entries; entry++) { nprimTot += nprimaries[entry]; + } // offset for pimary track index Int_t idelta0 = 0; // offset for secondary track index diff --git a/Detectors/Base/include/DetectorsBase/MatLayerCyl.h b/Detectors/Base/include/DetectorsBase/MatLayerCyl.h index b2dac5df80439..cf0acc750b53b 100644 --- a/Detectors/Base/include/DetectorsBase/MatLayerCyl.h +++ b/Detectors/Base/include/DetectorsBase/MatLayerCyl.h @@ -171,8 +171,9 @@ class MatLayerCyl : public o2::gpu::FlatObject // Get edge bin (in direction dir) of the slice, to which phiBin belongs // No check for phiBin validity is done auto slice = phiBin2Slice(phiBin); - while (slice == phiBin2Slice((phiBin += dir))) + while (slice == phiBin2Slice((phiBin += dir))) { ; + } return phiBin - dir; } diff --git a/Detectors/Base/src/MatLayerCyl.cxx b/Detectors/Base/src/MatLayerCyl.cxx index f2d3cb89dcde7..f8705a505b334 100644 --- a/Detectors/Base/src/MatLayerCyl.cxx +++ b/Detectors/Base/src/MatLayerCyl.cxx @@ -174,10 +174,12 @@ bool MatLayerCyl::cellsDiffer(const MatCell& cellA, const MatCell& cellB, float /// check if the cells content is different within the tolerance float rav = 0.5 * (cellA.meanRho + cellB.meanRho), xav = 0.5 * (cellA.meanX2X0 + cellB.meanX2X0); float rdf = 0.5 * (cellA.meanRho - cellB.meanRho), xdf = 0.5 * (cellA.meanX2X0 - cellB.meanX2X0); - if (rav > 0 && std::abs(rdf / rav) > maxRelDiff) + if (rav > 0 && std::abs(rdf / rav) > maxRelDiff) { return true; - if (xav > 0 && std::abs(xdf / xav) > maxRelDiff) + } + if (xav > 0 && std::abs(xdf / xav) > maxRelDiff) { return true; + } return false; } diff --git a/Detectors/Base/src/MatLayerCylSet.cxx b/Detectors/Base/src/MatLayerCylSet.cxx index ed31f12d3ba00..3d110766c6436 100644 --- a/Detectors/Base/src/MatLayerCylSet.cxx +++ b/Detectors/Base/src/MatLayerCylSet.cxx @@ -133,8 +133,9 @@ void MatLayerCylSet::dumpToTree(const std::string outName) const if (ip + 1 < nphib) { int ips1 = lr.phiBin2Slice(ip + 1); merge = ips == ips1 ? -1 : lr.canMergePhiSlices(ips, ips1); // -1 for already merged - } else + } else { merge = -2; // last one + } o2::math_utils::sincos(phi, sn, cs); float x = r * cs, y = r * sn; for (int iz = 0; iz < lr.getNZBins(); iz++) { diff --git a/Detectors/Base/src/Ray.cxx b/Detectors/Base/src/Ray.cxx index abad6ee80fd9b..1fede46d3be26 100644 --- a/Detectors/Base/src/Ray.cxx +++ b/Detectors/Base/src/Ray.cxx @@ -26,8 +26,9 @@ GPUd() int Ray::crossLayer(const MatLayerCyl& lr) // Region of valid t is 0:1. // Straigh line may have 2 crossings with cyl. layer float detMax = mXDxPlusYDy2 - mDistXY2 * (mR02 - lr.getRMax2()); - if (detMax < 0) + if (detMax < 0) { return 0; // does not reach outer R, hence inner also + } float detMaxRed = CAMath::Sqrt(detMax) * mDistXY2i; float tCross0Max = mXDxPlusYDyRed + detMaxRed; // largest possible t diff --git a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h index 35ae9e3d7a48d..a1ed3375ad166 100644 --- a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h +++ b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h @@ -158,8 +158,9 @@ inline TFType TimeSlotCalibration<Input, Container>::tf2SlotMin(TFType tf) const if (tf < mFirstTF) { throw std::runtime_error("invalide TF"); } - if (mUpdateAtTheEndOfRunOnly) + if (mUpdateAtTheEndOfRunOnly) { return mFirstTF; + } return TFType((tf - mFirstTF) / mSlotLength) * mSlotLength + mFirstTF; } @@ -169,9 +170,9 @@ TimeSlot<Container>& TimeSlotCalibration<Input, Container>::getSlotForTF(TFType { if (mUpdateAtTheEndOfRunOnly) { - if (!mSlots.empty() && mSlots.back().getTFEnd() < tf) + if (!mSlots.empty() && mSlots.back().getTFEnd() < tf) { mSlots.back().setTFEnd(tf); - else if (mSlots.empty()) { + } else if (mSlots.empty()) { emplaceNewSlot(true, mFirstTF, tf); } return mSlots.back(); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index d59b0d9d5d73f..f1b84e296de23 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -65,10 +65,11 @@ void MatchTOF::run() if (mIsworkflowON) { LOG(DEBUG) << "Number of entries in track tree = " << mCurrTracksTreeEntry; - if (mIsITSused) + if (mIsITSused) { prepareTracks(); - else + } else { prepareTPCTracks(); + } mMatchedTracks.clear(); mOutTOFLabels.clear(); @@ -81,10 +82,11 @@ void MatchTOF::run() for (int sec = o2::constants::math::NSectors; sec--;) { LOG(INFO) << "Doing matching for sector " << sec << "..."; - if (mIsITSused) + if (mIsITSused) { doMatching(sec); - else + } else { doMatchingForTPC(sec); + } LOG(INFO) << "...done. Now check the best matches"; selectBestMatches(); } @@ -94,10 +96,11 @@ void MatchTOF::run() while (!mIsworkflowON && mCurrTracksTreeEntry + 1 < mInputTreeTracks->GetEntries()) { // we add "+1" because mCurrTracksTreeEntry starts from -1, and it is incremented in loadTracksNextChunk which is called by prepareTracks LOG(DEBUG) << "Number of entries in track tree = " << mCurrTracksTreeEntry; - if (mIsITSused) + if (mIsITSused) { prepareTracks(); - else + } else { prepareTPCTracks(); + } mMatchedTracks.clear(); mOutTOFLabels.clear(); @@ -110,10 +113,11 @@ void MatchTOF::run() for (int sec = o2::constants::math::NSectors; sec--;) { LOG(INFO) << "Doing matching for sector " << sec << "..."; - if (mIsITSused) + if (mIsITSused) { doMatching(sec); - else + } else { doMatchingForTPC(sec); + } LOG(INFO) << "...done. Now check the best matches"; selectBestMatches(); } @@ -140,8 +144,9 @@ void MatchTOF::run() void MatchTOF::fill() { mOutputTree->Fill(); - if (mOutputTreeCalib) + if (mOutputTreeCalib) { mOutputTreeCalib->Fill(); + } } //______________________________________________ @@ -343,18 +348,21 @@ void MatchTOF::attachInputTrees() mTOFClusLabelsPtr = &mTOFClusLabels; mTreeTOFClusters->SetBranchAddress(mTOFMCTruthBranchName.data(), &mTOFClusLabelsPtr); LOG(INFO) << "Found TOF Clusters MCLabels branch " << mTOFMCTruthBranchName; - } else + } else { mMCTruthON = false; + } if (mInputTreeTracks->GetBranch(mTPCMCTruthBranchName.data())) { mInputTreeTracks->SetBranchAddress(mTPCMCTruthBranchName.data(), &mTPCLabelsVect); LOG(INFO) << "Found TPC tracks MCLabels branch " << mTPCMCTruthBranchName.data(); - } else + } else { mMCTruthON = false; + } if (mInputTreeTracks->GetBranch(mITSMCTruthBranchName.data())) { mInputTreeTracks->SetBranchAddress(mITSMCTruthBranchName.data(), &mITSLabelsVect); LOG(INFO) << "Found ITS tracks MCLabels branch " << mITSMCTruthBranchName.data(); - } else + } else { mMCTruthON = false; + } mCurrTracksTreeEntry = -1; mCurrTOFClustersTreeEntry = -1; @@ -396,13 +404,15 @@ void MatchTOF::attachInputTreesTPConly() mTOFClusLabelsPtr = &mTOFClusLabels; mTreeTOFClusters->SetBranchAddress(mTOFMCTruthBranchName.data(), &mTOFClusLabelsPtr); LOG(INFO) << "Found TOF Clusters MCLabels branch " << mTOFMCTruthBranchName; - } else + } else { mMCTruthON = false; + } if (mTreeTPCTracks->GetBranch(mOutTPCTrackMCTruthBranchName.data())) { mTreeTPCTracks->SetBranchAddress(mOutTPCTrackMCTruthBranchName.data(), &mTPCLabelsVect); LOG(INFO) << "Found TPC tracks MCLabels branch " << mOutTPCTrackMCTruthBranchName; - } else + } else { mMCTruthON = false; + } mCurrTracksTreeEntry = -1; mCurrTOFClustersTreeEntry = -1; @@ -418,8 +428,9 @@ bool MatchTOF::prepareTracks() } mNumOfTracks = mTracksArrayInp.size(); - if (mNumOfTracks == 0) + if (mNumOfTracks == 0) { return false; // no tracks to be matched + } mMatchedTracksIndex.resize(mNumOfTracks); std::fill(mMatchedTracksIndex.begin(), mMatchedTracksIndex.end(), -1); // initializing all to -1 @@ -495,8 +506,9 @@ bool MatchTOF::prepareTracks() for (int sec = o2::constants::math::NSectors; sec--;) { auto& indexCache = mTracksSectIndexCache[sec]; LOG(INFO) << "Sorting sector" << sec << " | " << indexCache.size() << " tracks"; - if (!indexCache.size()) + if (!indexCache.size()) { continue; + } std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { auto& trcA = mTracksWork[a].second; auto& trcB = mTracksWork[b].second; @@ -535,8 +547,9 @@ bool MatchTOF::prepareTPCTracks() } mNumOfTracks = mTPCTracksArrayInp.size(); - if (mNumOfTracks == 0) + if (mNumOfTracks == 0) { return false; // no tracks to be matched + } mMatchedTracksIndex.resize(mNumOfTracks); std::fill(mMatchedTracksIndex.begin(), mMatchedTracksIndex.end(), -1); // initializing all to -1 @@ -608,11 +621,12 @@ bool MatchTOF::prepareTPCTracks() continue; } - if (trc.getX() < o2::globaltracking::MatchTPCITS::XTPCOuterRef - 1.) + if (trc.getX() < o2::globaltracking::MatchTPCITS::XTPCOuterRef - 1.) { if (!propagateToRefX(trc, o2::globaltracking::MatchTPCITS::XTPCOuterRef, 10, intLT) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happen that it does not if the propagation without the errors succeeded? nNotPropagatedToTOF++; continue; } + } // the "rough" propagation worked; now we can propagate considering also the cov matrix if (!propagateToRefX(trc, mXRef, 2, intLT) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happen that it does not if the propagation without the errors succeeded? @@ -639,8 +653,9 @@ bool MatchTOF::prepareTPCTracks() for (int sec = o2::constants::math::NSectors; sec--;) { auto& indexCache = mTracksSectIndexCache[sec]; LOG(INFO) << "Sorting sector" << sec << " | " << indexCache.size() << " tracks"; - if (!indexCache.size()) + if (!indexCache.size()) { continue; + } std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { auto& trcA = mTracksWork[a].second; auto& trcB = mTracksWork[b].second; @@ -722,8 +737,9 @@ bool MatchTOF::prepareTOFClusters() for (int sec = o2::constants::math::NSectors; sec--;) { auto& indexCache = mTOFClusSectIndexCache[sec]; LOG(INFO) << "Sorting sector" << sec << " | " << indexCache.size() << " TOF clusters"; - if (!indexCache.size()) + if (!indexCache.size()) { continue; + } std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { auto& clA = mTOFClusWork[a]; auto& clB = mTOFClusWork[b]; @@ -731,8 +747,9 @@ bool MatchTOF::prepareTOFClusters() }); } // loop over TOF clusters of single sector - if (mMatchedClustersIndex) + if (mMatchedClustersIndex) { delete[] mMatchedClustersIndex; + } mMatchedClustersIndex = new int[mNumOfClusters]; std::fill_n(mMatchedClustersIndex, mNumOfClusters, -1); // initializing all to -1 @@ -881,8 +898,9 @@ void MatchTOF::doMatching(int sec) Printf("radius xyz = %f", TMath::Sqrt(posFloat[0]*posFloat[0] + posFloat[1]*posFloat[1] + posFloat[2]*posFloat[2])); */ - for (int idet = 0; idet < 5; idet++) + for (int idet = 0; idet < 5; idet++) { detIdTemp[idet] = -1; + } Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp); @@ -925,8 +943,9 @@ void MatchTOF::doMatching(int sec) // LOG(DEBUG) << "nStripsCrossedInPropagation = " << nStripsCrossedInPropagation << ", detId[nStripsCrossedInPropagation][0] = " << detId[nStripsCrossedInPropagation][0] << ", detIdTemp[0] = " << detIdTemp[0] << ", detId[nStripsCrossedInPropagation][1] = " << detId[nStripsCrossedInPropagation][1] << ", detIdTemp[1] = " << detIdTemp[1] << ", detId[nStripsCrossedInPropagation][2] = " << detId[nStripsCrossedInPropagation][2] << ", detIdTemp[2] = " << detIdTemp[2]; if (nStripsCrossedInPropagation == 0 || // we are crossing a strip for the first time... (nStripsCrossedInPropagation >= 1 && (detId[nStripsCrossedInPropagation - 1][0] != detIdTemp[0] || detId[nStripsCrossedInPropagation - 1][1] != detIdTemp[1] || detId[nStripsCrossedInPropagation - 1][2] != detIdTemp[2]))) { // ...or we are crossing a new strip - if (nStripsCrossedInPropagation == 0) + if (nStripsCrossedInPropagation == 0) { LOG(DEBUG) << "We cross a strip for the first time"; + } if (nStripsCrossedInPropagation == 2) { break; // we have already matched 2 strips, we cannot match more } @@ -1004,22 +1023,30 @@ void MatchTOF::doMatching(int sec) int ndigits = 1; float posCorr[3] = {0, 0, 0}; - if (trefTOF.isBitSet(Cluster::kLeft)) + if (trefTOF.isBitSet(Cluster::kLeft)) { posCorr[0] += Geo::XPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUpLeft)) + } + if (trefTOF.isBitSet(Cluster::kUpLeft)) { posCorr[0] += Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDownLeft)) + } + if (trefTOF.isBitSet(Cluster::kDownLeft)) { posCorr[0] += Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUp)) + } + if (trefTOF.isBitSet(Cluster::kUp)) { posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDown)) + } + if (trefTOF.isBitSet(Cluster::kDown)) { posCorr[2] += Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kRight)) + } + if (trefTOF.isBitSet(Cluster::kRight)) { posCorr[0] -= Geo::XPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUpRight)) + } + if (trefTOF.isBitSet(Cluster::kUpRight)) { posCorr[0] -= Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDownRight)) + } + if (trefTOF.isBitSet(Cluster::kDownRight)) { posCorr[0] -= Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; + } float ndifInv = 1. / ndigits; if (ndigits > 1) { @@ -1056,12 +1083,15 @@ void MatchTOF::doMatching(int sec) fillTOFmatchTreeWithLabels("matchPossibleWithLabels", cacheTOF[itof], indices[0], indices[1], indices[2], indices[3], indices[4], cacheTrk[itrk], iPropagation, detId[iPropagation][0], detId[iPropagation][1], detId[iPropagation][2], detId[iPropagation][3], detId[iPropagation][4], resX, resZ, res, trackWork, labelTPC.getTrackID(), labelTPC.getEventID(), labelTPC.getSourceID(), labelITS.getTrackID(), labelITS.getEventID(), labelITS.getSourceID(), tofLabelTrackID[0], tofLabelEventID[0], tofLabelSourceID[0], tofLabelTrackID[1], tofLabelEventID[1], tofLabelSourceID[1], tofLabelTrackID[2], tofLabelEventID[2], tofLabelSourceID[2], trkLTInt[iPropagation].getL(), trkLTInt[iPropagation].getTOF(o2::track::PID::Pion), trefTOF.getTime()); } #endif - if (indices[0] != detId[iPropagation][0]) + if (indices[0] != detId[iPropagation][0]) { continue; - if (indices[1] != detId[iPropagation][1]) + } + if (indices[1] != detId[iPropagation][1]) { continue; - if (indices[2] != detId[iPropagation][2]) + } + if (indices[2] != detId[iPropagation][2]) { continue; + } float chi2 = res; // TODO: take into account also the time! #ifdef _ALLOW_TOF_DEBUG_ fillTOFmatchTree("match1", cacheTOF[itof], indices[0], indices[1], indices[2], indices[3], indices[4], cacheTrk[itrk], iPropagation, detId[iPropagation][0], detId[iPropagation][1], detId[iPropagation][2], detId[iPropagation][3], detId[iPropagation][4], resX, resZ, res, trackWork, trkLTInt[iPropagation].getL(), trkLTInt[iPropagation].getTOF(o2::track::PID::Pion), trefTOF.getTime()); @@ -1173,9 +1203,11 @@ void MatchTOF::doMatchingForTPC(int sec) bool isalreadyin = false; - for (int k = 0; k < BCcand.size(); k++) - if (bc == BCcand[k]) + for (int k = 0; k < BCcand.size(); k++) { + if (bc == BCcand[k]) { isalreadyin = true; + } + } if (!isalreadyin) { BCcand.emplace_back(bc); @@ -1243,15 +1275,17 @@ void MatchTOF::doMatchingForTPC(int sec) // check if you fall in a strip for (int ibc = 0; ibc < BCcand.size(); ibc++) { - for (int idet = 0; idet < 5; idet++) + for (int idet = 0; idet < 5; idet++) { detIdTemp[idet] = -1; + } - if (side > 0) + if (side > 0) { posFloat[2] = pos[2] - vdrift * (trackWork.second.getTimeStamp() - BCcand[ibc] * Geo::BC_TIME_INPS * 1E-6); - else if (side < 0) + } else if (side < 0) { posFloat[2] = pos[2] + vdrift * (trackWork.second.getTimeStamp() - BCcand[ibc] * Geo::BC_TIME_INPS * 1E-6); - else + } else { posFloat[2] = pos[2]; + } Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp); @@ -1261,8 +1295,9 @@ void MatchTOF::doMatchingForTPC(int sec) if (nStripsCrossedInPropagation[ibc] == 0 || // we are crossing a strip for the first time... (nStripsCrossedInPropagation[ibc] >= 1 && (detId[ibc][nStripsCrossedInPropagation[ibc] - 1][0] != detIdTemp[0] || detId[ibc][nStripsCrossedInPropagation[ibc] - 1][1] != detIdTemp[1] || detId[ibc][nStripsCrossedInPropagation[ibc] - 1][2] != detIdTemp[2]))) { // ...or we are crossing a new strip - if (nStripsCrossedInPropagation[ibc] == 0) + if (nStripsCrossedInPropagation[ibc] == 0) { LOG(DEBUG) << "We cross a strip for the first time"; + } if (nStripsCrossedInPropagation[ibc] == 2) { continue; // we have already matched 2 strips, we cannot match more } @@ -1333,22 +1368,30 @@ void MatchTOF::doMatchingForTPC(int sec) int ndigits = 1; float posCorr[3] = {0, 0, 0}; - if (trefTOF.isBitSet(Cluster::kLeft)) + if (trefTOF.isBitSet(Cluster::kLeft)) { posCorr[0] += Geo::XPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUpLeft)) + } + if (trefTOF.isBitSet(Cluster::kUpLeft)) { posCorr[0] += Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDownLeft)) + } + if (trefTOF.isBitSet(Cluster::kDownLeft)) { posCorr[0] += Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUp)) + } + if (trefTOF.isBitSet(Cluster::kUp)) { posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDown)) + } + if (trefTOF.isBitSet(Cluster::kDown)) { posCorr[2] += Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kRight)) + } + if (trefTOF.isBitSet(Cluster::kRight)) { posCorr[0] -= Geo::XPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kUpRight)) + } + if (trefTOF.isBitSet(Cluster::kUpRight)) { posCorr[0] -= Geo::XPAD, posCorr[2] -= Geo::ZPAD, ndigits++; - if (trefTOF.isBitSet(Cluster::kDownRight)) + } + if (trefTOF.isBitSet(Cluster::kDownRight)) { posCorr[0] -= Geo::XPAD, posCorr[2] += Geo::ZPAD, ndigits++; + } float ndifInv = 1. / ndigits; if (ndigits > 1) { @@ -1366,12 +1409,15 @@ void MatchTOF::doMatchingForTPC(int sec) float resX = deltaPos[ibc][iPropagation][0] - (indices[4] - detId[ibc][iPropagation][4]) * Geo::XPAD + posCorr[0]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster float resZ = deltaPos[ibc][iPropagation][2] - (indices[3] - detId[ibc][iPropagation][3]) * Geo::ZPAD + posCorr[2]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster float res = TMath::Sqrt(resX * resX + resZ * resZ); - if (indices[0] != detId[ibc][iPropagation][0]) + if (indices[0] != detId[ibc][iPropagation][0]) { continue; - if (indices[1] != detId[ibc][iPropagation][1]) + } + if (indices[1] != detId[ibc][iPropagation][1]) { continue; - if (indices[2] != detId[ibc][iPropagation][2]) + } + if (indices[2] != detId[ibc][iPropagation][2]) { continue; + } LOG(DEBUG) << "resX = " << resX << ", resZ = " << resZ << ", res = " << res; float chi2 = res; // TODO: take into account also the time! @@ -1408,8 +1454,9 @@ int MatchTOF::findFITIndex(int bc) int bct0 = ir.orbit * o2::constants::lhc::LHCMaxBunches + ir.bc; int dist = bc - bct0; - if (dist < 0 || dist > distMax) + if (dist < 0 || dist > distMax) { continue; + } distMax = dist; index = i; @@ -1475,8 +1522,9 @@ void MatchTOF::selectBestMatches() if (!labelOk) { // we have not found the track label among those associated to the TOF cluster --> fake match! We will associate the label of the main channel, but negative //assert(labelsTOF.size()); - if (!labelsTOF.size()) + if (!labelsTOF.size()) { throw std::runtime_error("TOF label not found since size of label is zero. This should not happen!!!!"); + } mOutTOFLabels.emplace_back(labelsTOF[0].getTrackID(), labelsTOF[0].getEventID(), labelsTOF[0].getSourceID(), true); } mOutTPCLabels.push_back(labelTPC); @@ -1498,8 +1546,9 @@ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float st bool refReached = false; float xStart = trc.getX(); // the first propagation will be from 2m, if the track is not at least at 2m - if (xStart < 50.) + if (xStart < 50.) { xStart = 50.; + } int istep = 1; bool hasPropagated = o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, xStart + istep * stepInCm, o2::constants::physics::MassPionCharged, MAXSNP, stepInCm, matCorr, &intLT); while (hasPropagated) { @@ -1516,8 +1565,9 @@ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float st break; // failed (this line is taken from MatchTPCITS and the following comment too: RS: check effect on matching tracks to neighbouring sector) } } - if (refReached) + if (refReached) { break; + } hasPropagated = o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, xStart + istep * stepInCm, o2::constants::physics::MassPionCharged, MAXSNP, stepInCm, matCorr, &intLT); } @@ -1536,8 +1586,9 @@ bool MatchTOF::propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef bool refReached = false; float xStart = trcNoCov.getX(); // the first propagation will be from 2m, if the track is not at least at 2m - if (xStart < 50.) + if (xStart < 50.) { xStart = 50.; + } int istep = 1; bool hasPropagated = trcNoCov.propagateParamTo(xStart + istep * stepInCm, bzField); while (hasPropagated) { @@ -1554,8 +1605,9 @@ bool MatchTOF::propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef break; // failed (this line is taken from MatchTPCITS and the following comment too: RS: check effect on matching tracks to neighbouring sector) } } - if (refReached) + if (refReached) { break; + } hasPropagated = trcNoCov.propagateParamTo(xStart + istep * stepInCm, bzField); } // if (std::abs(trc.getSnp()) > MAXSNP) Printf("propagateToRefX: condition on snp not ok, returning false"); diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 7a1903602381c..fbd034c487e96 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -581,8 +581,9 @@ bool MatchTPCITS::prepareTPCTracks() for (int sec = o2::constants::math::NSectors; sec--;) { auto& indexCache = mTPCSectIndexCache[sec]; LOG(INFO) << "Sorting sector" << sec << " | " << indexCache.size() << " TPC tracks"; - if (!indexCache.size()) + if (!indexCache.size()) { continue; + } std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { auto& trcA = mTPCWork[a]; auto& trcB = mTPCWork[b]; @@ -1086,10 +1087,12 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& return rejFlag; } } else { // in continuous mode we use special check on allowed Z range - if (tITS.getParam(o2::track::kZ) - tTPC.zMax > mParams->crudeAbsDiffCut[o2::track::kZ]) + if (tITS.getParam(o2::track::kZ) - tTPC.zMax > mParams->crudeAbsDiffCut[o2::track::kZ]) { return RejectOnZ; - if (tITS.getParam(o2::track::kZ) - tTPC.zMin < -mParams->crudeAbsDiffCut[o2::track::kZ]) + } + if (tITS.getParam(o2::track::kZ) - tTPC.zMin < -mParams->crudeAbsDiffCut[o2::track::kZ]) { return -RejectOnZ; + } } diff = tITS.getParam(o2::track::kSnp) - tTPC.getParam(o2::track::kSnp); @@ -1111,8 +1114,9 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& } // calculate mutual chi2 excluding Z in continuos mode chi2 = getPredictedChi2NoZ(tITS, tTPC); - if (chi2 > mParams->cutMatchingChi2) + if (chi2 > mParams->cutMatchingChi2) { return RejectOnChi2; + } return Accept; } diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx index b1ad021285f92..d78e95a392393 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/CalibInfoReaderSpec.cxx @@ -77,10 +77,11 @@ DataProcessorSpec getCalibInfoReaderSpec(int instance, int ninstances, const cha outputs.emplace_back(o2::header::gDataOriginTOF, "CALIBDATA", 0, Lifetime::Timeframe); const char* nameSpec; - if (ninstances == 1) + if (ninstances == 1) { nameSpec = "tof-calibinfo-reader"; - else + } else { nameSpec = Form("tof-calibinfo-reader-%d", instance); + } return DataProcessorSpec{ nameSpec, diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx index 586573be21b2a..ca362c48ba2b0 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-calibinfo-reader.cxx @@ -73,8 +73,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // auto tofSectors = o2::RangeTokenizer::tokenize<int>(cfgc.options().get<std::string>("tof-sectors")); // std::vector<int> laneConfiguration = tofSectors; - for (int i = 0; i < ninstances; i++) + for (int i = 0; i < ninstances; i++) { specs.emplace_back(o2::tof::getCalibInfoReaderSpec(i, ninstances, stringTBP)); + } LOG(INFO) << "Number of active devices = " << specs.size(); diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx index cde47586ff985..3d965c015134e 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-global.cxx @@ -96,10 +96,12 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) bool writematching = 0; bool writecalib = 0; - if (outputType.rfind("matching-info") < outputType.size()) + if (outputType.rfind("matching-info") < outputType.size()) { writematching = 1; - if (outputType.rfind("calib-info") < outputType.size()) + } + if (outputType.rfind("calib-info") < outputType.size()) { writecalib = 1; + } bool clusterinput = 0; bool trackinput = 0; diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx index 2dbea93775e0f..d2882f177a79f 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-matcher-tpc.cxx @@ -96,10 +96,12 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) bool writematching = 0; bool writecalib = 0; - if (outputType.rfind("matching-info") < outputType.size()) + if (outputType.rfind("matching-info") < outputType.size()) { writematching = 1; - if (outputType.rfind("calib-info") < outputType.size()) + } + if (outputType.rfind("calib-info") < outputType.size()) { writecalib = 1; + } bool clusterinput = 0; bool trackinput = 0; diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index feb89cfc11d88..18b6e2f75f4a9 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -105,18 +105,24 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) bool writectf = 0; bool writeerr = 0; - if (outputType.rfind("clusters") < outputType.size()) + if (outputType.rfind("clusters") < outputType.size()) { writecluster = 1; - if (outputType.rfind("matching-info") < outputType.size()) + } + if (outputType.rfind("matching-info") < outputType.size()) { writematching = 1; - if (outputType.rfind("calib-info") < outputType.size()) + } + if (outputType.rfind("calib-info") < outputType.size()) { writecalib = 1; - if (outputType.rfind("digits") < outputType.size()) + } + if (outputType.rfind("digits") < outputType.size()) { writedigit = 1; - if (outputType.rfind("raw") < outputType.size()) + } + if (outputType.rfind("raw") < outputType.size()) { writeraw = 1; - if (outputType.rfind("ctf") < outputType.size()) + } + if (outputType.rfind("ctf") < outputType.size()) { writectf = 1; + } bool dgtinput = 0; bool clusterinput = 0; From f214ecb91552694e8b65d2fa7fa1bc0639a5bee9 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Thu, 29 Oct 2020 11:06:16 +0100 Subject: [PATCH 1148/1751] DPL Analysis: fix for bool serialization from structs and example update (#4711) --- Analysis/Tutorials/include/Analysis/configurableCut.h | 10 +++++++--- Analysis/Tutorials/src/configurableCut.cxx | 10 ++++++++++ Analysis/Tutorials/src/configurableObjects.cxx | 4 ++-- Framework/Core/src/RootConfigParamHelpers.cxx | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h index 84737a67fb2dc..d63b39e75fbca 100644 --- a/Analysis/Tutorials/include/Analysis/configurableCut.h +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -17,8 +17,8 @@ class configurableCut { public: - configurableCut(float cut_ = 2., int state_ = 1) - : cut{cut_}, state{state_} + configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true) + : cut{cut_}, state{state_}, option{option_} { } @@ -30,11 +30,15 @@ class configurableCut void setState(int state_); int getState() const; + void setOption(bool option_); + bool getOption() const; + private: float cut; int state; + bool option; - ClassDef(configurableCut, 2); + ClassDef(configurableCut, 3); }; std::ostream& operator<<(std::ostream& os, configurableCut const& c); diff --git a/Analysis/Tutorials/src/configurableCut.cxx b/Analysis/Tutorials/src/configurableCut.cxx index fabca8db4b8cf..1b52790828268 100644 --- a/Analysis/Tutorials/src/configurableCut.cxx +++ b/Analysis/Tutorials/src/configurableCut.cxx @@ -41,3 +41,13 @@ int configurableCut::getState() const { return state; } + +void configurableCut::setOption(bool option_) +{ + option = option_; +} + +bool configurableCut::getOption() const +{ + return option; +} diff --git a/Analysis/Tutorials/src/configurableObjects.cxx b/Analysis/Tutorials/src/configurableObjects.cxx index 5ae293436f981..2cf3dbb035672 100644 --- a/Analysis/Tutorials/src/configurableObjects.cxx +++ b/Analysis/Tutorials/src/configurableObjects.cxx @@ -20,8 +20,8 @@ using namespace o2::framework::expressions; /// use it with supplied configuration: "configurableObject.json" struct ConfigurableObjectDemo { - Configurable<configurableCut> cut{"cut", {0.5, 1}, "generic cut"}; - MutableConfigurable<configurableCut> mutable_cut{"mutable_cut", {1., 2}, "generic cut"}; + Configurable<configurableCut> cut{"cut", {0.5, 1, true}, "generic cut"}; + MutableConfigurable<configurableCut> mutable_cut{"mutable_cut", {1., 2, false}, "generic cut"}; void init(InitContext const&){}; void process(aod::Collision const&, aod::Tracks const& tracks) { diff --git a/Framework/Core/src/RootConfigParamHelpers.cxx b/Framework/Core/src/RootConfigParamHelpers.cxx index 171722e62d3f8..6c1cb07efb02c 100644 --- a/Framework/Core/src/RootConfigParamHelpers.cxx +++ b/Framework/Core/src/RootConfigParamHelpers.cxx @@ -197,7 +197,7 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember const* dm return ConfigParamSpec{tname, VariantType::Double, *(double*)ptr, {"No help"}}; } case kBool_t: { - return ConfigParamSpec{tname, VariantType::Double, *(bool*)ptr, {"No help"}}; + return ConfigParamSpec{tname, VariantType::Bool, *(bool*)ptr, {"No help"}}; } case kLong64_t: { return ConfigParamSpec{tname, VariantType::Int64, *(int64_t*)ptr, {"No help"}}; From 3f4bbfb8d00f50d408335d21723c71d7bb6c67a6 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 29 Oct 2020 13:56:47 +0100 Subject: [PATCH 1149/1751] Run full system test in CPU+GPU mode (#4716) --- prodtests/full_system_test.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index fac1006d03ba3..8667e2ca174bf 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -52,13 +52,22 @@ taskwrapper tofraw.log o2-tof-reco-workflow ${GLOBALDPLOPT} --tof-raw-file-for l taskwrapper midraw.log o2-mid-digits-to-raw-workflow ${GLOBALDPLOPT} --mid-raw-outdir raw/MID --mid-raw-perlink --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' cat raw/*/*.cfg > rawAll.cfg -ARGS_ALL="--session default" -taskwrapper reco.log "o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | +# We run the workflow in both CPU-only and With-GPU mode +for STAGE in "NOGPU" "WITHGPU"; do + + if [[ "$STAGE" = "WITHGPU" ]]; then + TPC_GPU_OPT="GPU_proc.deviceNum=0;GPU_global.deviceType=CUDA;GPU_proc.forceMemoryPoolSize=6000000000;GPU_proc.forceHostMemoryPoolSize=3000000000" + else + TPC_GPU_OPT="GPU_proc.forceHostMemoryPoolSize=${TPCTRACKERSCRATCHMEMORY}" + fi + + ARGS_ALL="--session default" + taskwrapper reco_${STAGE}.log "o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | o2-itsmft-stf-decoder-workflow $ARGS_ALL | o2-itsmft-stf-decoder-workflow $ARGS_ALL --runmft true | o2-its-reco-workflow $ARGS_ALL --trackerCA ${NOMCLABELS} --clusters-from-upstream --disable-root-output --entropy-encoding --configKeyValues \"fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500\" | o2-itsmft-entropy-encoder-workflow $ARGS_ALL --runmft true | -o2-tpc-reco-workflow $ARGS_ALL --input-type=zsraw ${NOMCLABELS} --output-type tracks,clusters,encoded-clusters,disable-writer --configKeyValues \"HBFUtils.nHBFPerTF=128;GPU_proc.forceHostMemoryPoolSize=${TPCTRACKERSCRATCHMEMORY}\" | +o2-tpc-reco-workflow $ARGS_ALL --input-type=zsraw ${NOMCLABELS} --output-type tracks,clusters,encoded-clusters,disable-writer --configKeyValues \"HBFUtils.nHBFPerTF=128;${TPC_GPU_OPT}\" | o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | o2-ft0-entropy-encoder-workflow $ARGS_ALL | @@ -68,3 +77,5 @@ o2-mid-entropy-encoder-workflow $ARGS_ALL | o2-tof-compressor $ARGS_ALL | o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output ${NOMCLABELS} | o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input --shm-segment-size $SHMSIZE ${GLOBALDPLOPT}" + +done From 06b8579537e73008f4cf4e1e7742551d748a890c Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <chiara.zampolli@cern.ch> Date: Thu, 29 Oct 2020 14:01:31 +0100 Subject: [PATCH 1150/1751] Mean vertex calibration (#4638) * First implementation of MeanVertex calibration In the direction of the moving average. Vectors for SMA Compiling, but I did not check if it works typos Processing MeanVertex. * First bunch of comments by Ruben (a couple left, for next week :-) ) Following review to PR. following review clang-format * Using ConfigurableParams clang * remove mTmpMVobjDqTimeEnd, and fixes * Fix determination of startValidity clang * Using Bracket Using Bracket and changes related to modifications of Utils in dev clang --- DataFormats/CMakeLists.txt | 1 + DataFormats/Calibration/CMakeLists.txt | 15 ++ .../DataFormatsCalibration/MeanVertexObject.h | 85 +++++++ .../src/DataFormatsCalibrationLinkDef.h | 19 ++ .../Calibration/src/MeanVertexObject.cxx | 11 + Detectors/Calibration/CMakeLists.txt | 34 ++- .../MeanVertexCalibrator.h | 102 +++++++++ .../DetectorsCalibration/MeanVertexData.h | 113 +++++++++ .../DetectorsCalibration/MeanVertexParams.h | 45 ++++ .../src/DetectorsCalibrationLinkDef.h | 24 ++ .../Calibration/src/MeanVertexCalibrator.cxx | 214 ++++++++++++++++++ Detectors/Calibration/src/MeanVertexData.cxx | 115 ++++++++++ .../Calibration/src/MeanVertexParams.cxx | 17 ++ Detectors/Calibration/src/TimeSlot.cxx | 11 + .../Calibration/src/TimeSlotCalibration.cxx | 11 + Detectors/Calibration/src/Utils.cxx | 11 + Detectors/Calibration/workflow/CMakeLists.txt | 31 +++ .../MeanVertexCalibratorSpec.h | 50 ++++ .../workflow/src/MeanVertexCalibratorSpec.cxx | 123 ++++++++++ .../src/mean-vertex-calibration-workflow.cxx | 32 +++ .../calibration/src/LHCClockCalibrator.cxx | 2 +- .../calibration/src/TOFChannelCalibrator.cxx | 2 +- 22 files changed, 1057 insertions(+), 11 deletions(-) create mode 100644 DataFormats/Calibration/CMakeLists.txt create mode 100644 DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h create mode 100644 DataFormats/Calibration/src/DataFormatsCalibrationLinkDef.h create mode 100644 DataFormats/Calibration/src/MeanVertexObject.cxx create mode 100644 Detectors/Calibration/include/DetectorsCalibration/MeanVertexCalibrator.h create mode 100644 Detectors/Calibration/include/DetectorsCalibration/MeanVertexData.h create mode 100644 Detectors/Calibration/include/DetectorsCalibration/MeanVertexParams.h create mode 100644 Detectors/Calibration/src/DetectorsCalibrationLinkDef.h create mode 100644 Detectors/Calibration/src/MeanVertexCalibrator.cxx create mode 100644 Detectors/Calibration/src/MeanVertexData.cxx create mode 100644 Detectors/Calibration/src/MeanVertexParams.cxx create mode 100644 Detectors/Calibration/src/TimeSlot.cxx create mode 100644 Detectors/Calibration/src/TimeSlotCalibration.cxx create mode 100644 Detectors/Calibration/src/Utils.cxx create mode 100644 Detectors/Calibration/workflow/CMakeLists.txt create mode 100644 Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h create mode 100644 Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx create mode 100644 Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx diff --git a/DataFormats/CMakeLists.txt b/DataFormats/CMakeLists.txt index 06f4597cdb328..b6b2899c4e56f 100644 --- a/DataFormats/CMakeLists.txt +++ b/DataFormats/CMakeLists.txt @@ -6,4 +6,5 @@ add_subdirectory(MemoryResources) add_subdirectory(simulation) add_subdirectory(TimeFrame) add_subdirectory(Parameters) +add_subdirectory(Calibration) diff --git a/DataFormats/Calibration/CMakeLists.txt b/DataFormats/Calibration/CMakeLists.txt new file mode 100644 index 0000000000000..c63199a6e02b8 --- /dev/null +++ b/DataFormats/Calibration/CMakeLists.txt @@ -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. + +o2_add_library(DataFormatsCalibration + SOURCES src/MeanVertexObject.cxx) + +o2_target_root_dictionary(DataFormatsCalibration + HEADERS include/DataFormatsCalibration/MeanVertexObject.h) diff --git a/DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h b/DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h new file mode 100644 index 0000000000000..43f1d2fac2d46 --- /dev/null +++ b/DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h @@ -0,0 +1,85 @@ +// 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 MEAN_VERTEX_OBJECT_H_ +#define MEAN_VERTEX_OBJECT_H_ + +#include <array> +#include "Rtypes.h" + +namespace o2 +{ +namespace dataformats +{ +class MeanVertexObject +{ + + public: + MeanVertexObject(float x, float y, float z, float sigmax, float sigmay, float sigmaz) + { + mPos[0] = x; + mPos[1] = y; + mPos[2] = z; + mSigma[0] = sigmax; + mSigma[1] = sigmay; + mSigma[2] = sigmaz; + } + MeanVertexObject(std::array<float, 3> pos, std::array<float, 3> sigma) + { + for (int i = 0; i < 3; i++) { + mPos[i] = pos[i]; + mSigma[i] = sigma[i]; + } + } + MeanVertexObject() = default; + ~MeanVertexObject() = default; + MeanVertexObject(const MeanVertexObject& other) = default; + MeanVertexObject(MeanVertexObject&& other) = default; + MeanVertexObject& operator=(MeanVertexObject& other) = default; + MeanVertexObject& operator=(MeanVertexObject&& other) = default; + + void setX(float val) { mPos[0] = val; } + void setY(float val) { mPos[1] = val; } + void setZ(float val) { mPos[2] = val; } + void setPos(std::array<float, 3> val) + { + for (int i = 0; i < 3; i++) + mPos[i] = val[i]; + } + + float getX() const { return mPos[0]; } + float getY() const { return mPos[1]; } + float getZ() const { return mPos[2]; } + const std::array<float, 3>& getPos() const { return mPos; } + + void setSigmaX(float val) { mSigma[0] = val; } + void setSigmaY(float val) { mSigma[1] = val; } + void setSigmaZ(float val) { mSigma[2] = val; } + void setSigma(std::array<float, 3> val) + { + for (int i = 0; i < 3; i++) + mSigma[i] = val[i]; + } + + float getSigmaX() const { return mSigma[0]; } + float getSigmaY() const { return mSigma[1]; } + float getSigmaZ() const { return mSigma[2]; } + const std::array<float, 3>& getSigma() const { return mSigma; } + + private: + std::array<float, 3> mPos; // position of mean vertex + std::array<float, 3> mSigma; // sigma of mean vertex + + ClassDefNV(MeanVertexObject, 1); +}; +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/DataFormats/Calibration/src/DataFormatsCalibrationLinkDef.h b/DataFormats/Calibration/src/DataFormatsCalibrationLinkDef.h new file mode 100644 index 0000000000000..f364ef185a8dc --- /dev/null +++ b/DataFormats/Calibration/src/DataFormatsCalibrationLinkDef.h @@ -0,0 +1,19 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ struct o2::dataformats::MeanVertexObject + ; + +#endif diff --git a/DataFormats/Calibration/src/MeanVertexObject.cxx b/DataFormats/Calibration/src/MeanVertexObject.cxx new file mode 100644 index 0000000000000..c76593ac7908a --- /dev/null +++ b/DataFormats/Calibration/src/MeanVertexObject.cxx @@ -0,0 +1,11 @@ +// 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 "DataFormatsCalibration/MeanVertexObject.h" diff --git a/Detectors/Calibration/CMakeLists.txt b/Detectors/Calibration/CMakeLists.txt index 1bf25fbaa0173..795e51ca34a5d 100644 --- a/Detectors/Calibration/CMakeLists.txt +++ b/Detectors/Calibration/CMakeLists.txt @@ -8,16 +8,30 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_header_only_library(DetectorsCalibration - INTERFACE_LINK_LIBRARIES O2::Headers - O2::CCDB - O2::CommonUtils - ms_gsl::ms_gsl) +o2_add_library(DetectorsCalibration + SOURCES src/TimeSlot.cxx + src/TimeSlotCalibration.cxx + src/Utils.cxx + src/MeanVertexData.cxx + src/MeanVertexCalibrator.cxx + src/MeanVertexParams.cxx + PUBLIC_LINK_LIBRARIES O2::Headers + O2::CCDB + O2::CommonUtils + ROOT::Minuit + ms_gsl::ms_gsl + O2::ReconstructionDataFormats + O2::SimConfig + O2::DataFormatsCalibration) + -#o2_target_root_dictionary(DetectorsCalibration -# HEADERS include/DetectorsCalibration/TimeSlotCalibration.h -# include/DetectorsCalibration/TimeSlot.h -# include/DetectorsCalibration/Utils.h) +o2_target_root_dictionary(DetectorsCalibration + HEADERS include/DetectorsCalibration/TimeSlotCalibration.h + include/DetectorsCalibration/TimeSlot.h + include/DetectorsCalibration/Utils.h + include/DetectorsCalibration/MeanVertexData.h + include/DetectorsCalibration/MeanVertexCalibrator.h + include/DetectorsCalibration/MeanVertexParams.h) o2_add_executable(ccdb-populator-workflow COMPONENT_NAME calibration @@ -27,3 +41,5 @@ o2_add_executable(ccdb-populator-workflow O2::DetectorsCalibration O2::DataFormatsTOF O2::CCDB) + +add_subdirectory(workflow) diff --git a/Detectors/Calibration/include/DetectorsCalibration/MeanVertexCalibrator.h b/Detectors/Calibration/include/DetectorsCalibration/MeanVertexCalibrator.h new file mode 100644 index 0000000000000..d033f35f08024 --- /dev/null +++ b/Detectors/Calibration/include/DetectorsCalibration/MeanVertexCalibrator.h @@ -0,0 +1,102 @@ +// 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 MEAN_VERTEX_CALIBRATOR_H_ +#define MEAN_VERTEX_CALIBRATOR_H_ + +#include "DetectorsCalibration/TimeSlotCalibration.h" +#include "DetectorsCalibration/TimeSlot.h" +#include "DetectorsCalibration/MeanVertexData.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "CCDB/CcdbObjectInfo.h" +#include "MathUtils/detail/Bracket.h" +#include <array> +#include <deque> + +namespace o2 +{ +namespace calibration +{ + +class MeanVertexCalibrator final : public o2::calibration::TimeSlotCalibration<o2::dataformats::PrimaryVertex, o2::calibration::MeanVertexData> +{ + using PVertex = o2::dataformats::PrimaryVertex; + using MeanVertexData = o2::calibration::MeanVertexData; + using TFType = uint64_t; + using Slot = o2::calibration::TimeSlot<MeanVertexData>; + using MVObject = o2::dataformats::MeanVertexObject; + using MVObjectVector = std::vector<MVObject>; + using CcdbObjectInfo = o2::ccdb::CcdbObjectInfo; + using CcdbObjectInfoVector = std::vector<CcdbObjectInfo>; + + public: + MeanVertexCalibrator(int minEnt = 500, bool useFit = false, int nBinsX = 100, float rangeX = 1.f, + int nBinsY = 100, float rangeY = 1.f, int nBinsZ = 100, float rangeZ = 20.f, + int nSlotsSMA = 5) : mMinEntries(minEnt), mUseFit(useFit), mNBinsX(nBinsX), mRangeX(rangeX), mNBinsY(nBinsY), mRangeY(rangeY), mNBinsZ(nBinsZ), mRangeZ(rangeZ), mSMAslots(nSlotsSMA) + { + mSMAdata.init(useFit, nBinsX, rangeX, nBinsY, rangeY, nBinsZ, rangeZ); + } + + ~MeanVertexCalibrator() final = default; + + bool hasEnoughData(const Slot& slot) const final + { + LOG(INFO) << "container entries = " << slot.getContainer()->entries << ", minEntries = " << mMinEntries; + return slot.getContainer()->entries >= mMinEntries; + } + void initOutput() final; + void finalizeSlot(Slot& slot) final; + Slot& emplaceNewSlot(bool front, TFType tstart, TFType tend) final; + + uint64_t getNSlotsSMA() const { return mSMAslots; } + void setNSlotsSMA(uint64_t nslots) { mSMAslots = nslots; } + + void doSimpleMovingAverage(std::deque<float>& dq, float& sma); + void doSimpleMovingAverage(std::deque<MVObject>& dq, MVObject& sma); + + const MVObjectVector& getMeanVertexObjectVector() const { return mMeanVertexVector; } + const CcdbObjectInfoVector& getMeanVertexObjectInfoVector() const { return mInfoVector; } + CcdbObjectInfoVector& getMeanVertexObjectInfoVector() { return mInfoVector; } + + private: + int mMinEntries = 0; + int mNBinsX = 0; + float mRangeX = 0.; + int mNBinsY = 0; + float mRangeY = 0.; + int mNBinsZ = 0; + float mRangeZ = 0.; + bool mUseFit = false; + uint64_t mSMAslots = 5; + CcdbObjectInfoVector mInfoVector; // vector of CCDB Infos , each element is filled with the CCDB description + // of the accompanying LHCPhase + MVObjectVector mMeanVertexVector; // vector of Mean Vertex Objects, each element is filled in "process" + // when we finalize one slot (multiple can be finalized during the same + // "process", which is why we have a vector. Each element is to be considered + // the output of the device, and will go to the CCDB. It is the simple + // moving average + std::deque<MVObject> mTmpMVobjDq; // This is the deque of MeanVertex objecs that will be used for the + // simple moving average + MVObject mSMAMVobj; // object containing the Simple Moving Average to be put to CCDB + std::deque<TFType> mTmpMVobjDqTimeStart; // This is the deque of MeanVertex objecs that will be used for the + // simple moving average, start time of used TFs + std::deque<o2::math_utils::detail::Bracket<TFType>> mTmpMVobjDqTime; // This is the deque for the start and end time of the + // slots used for the SMA + std::deque<MeanVertexData> mTmpMVdataDq; // This is the vector of Mean Vertex data to be used for the simple + // moving average + MeanVertexData mSMAdata; // This is to do the SMA when we keep the histos + + ClassDefOverride(MeanVertexCalibrator, 1); +}; + +} // end namespace calibration +} // end namespace o2 + +#endif /* TOF_LHCPHASE_CALIBRATION_H_ */ diff --git a/Detectors/Calibration/include/DetectorsCalibration/MeanVertexData.h b/Detectors/Calibration/include/DetectorsCalibration/MeanVertexData.h new file mode 100644 index 0000000000000..42f5f67920143 --- /dev/null +++ b/Detectors/Calibration/include/DetectorsCalibration/MeanVertexData.h @@ -0,0 +1,113 @@ +// 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 MEAN_VERTEX_DATA_H_ +#define MEAN_VERTEX_DATA_H_ + +#include "DetectorsCalibration/TimeSlot.h" +#include "ReconstructionDataFormats/PrimaryVertex.h" +#include <array> +#include <deque> +#include <gsl/span> + +namespace o2 +{ +namespace calibration +{ + +struct MeanVertexData { + + using PVertex = o2::dataformats::PrimaryVertex; + float rangeX = 1.f; + float rangeY = 1.f; + float rangeZ = 20.f; + int nbinsX = 100; + int nbinsY = 100; + int nbinsZ = 100; + float v2BinX = nbinsX / (2 * rangeX); + float v2BinY = nbinsY / (2 * rangeY); + float v2BinZ = nbinsZ / (2 * rangeZ); + int entries = 0; + std::vector<float> histoX{0}; + std::vector<float> histoY{0}; + std::vector<float> histoZ{0}; + bool useFit = false; + + MeanVertexData(); + + ~MeanVertexData() + { + useFit = false; + nbinsX = 1000; + rangeX = 10.f; + nbinsY = 1000; + rangeY = 10.f; + nbinsZ = 1000; + rangeZ = 10.f; + v2BinX = 0.f; + v2BinY = 0.f; + v2BinZ = 0.f; + histoX.clear(); + histoY.clear(); + histoZ.clear(); + } + + MeanVertexData(bool buseFit, int nbX, float rX, int nbY, float rY, int nbZ, float rZ) : useFit(buseFit), nbinsX(nbX), rangeX(rX), v2BinX(0), nbinsY(nbY), rangeY(rY), v2BinY(0), nbinsZ(nbZ), rangeZ(rZ), v2BinZ(0) + { + if (rX <= 0. || nbX < 1 || rY <= 0. || nbY < 1 || rZ <= 0. || nbZ < 1) { + throw std::runtime_error("Wrong initialization of the histogram"); + } + v2BinX = nbinsX / (2 * rangeX); + v2BinY = nbinsY / (2 * rangeY); + v2BinZ = nbinsZ / (2 * rangeZ); + histoX.resize(nbinsX, 0.); + histoY.resize(nbinsY, 0.); + histoZ.resize(nbinsZ, 0.); + } + + MeanVertexData(MeanVertexData&& other) = default; + MeanVertexData(const MeanVertexData& other) = default; + MeanVertexData& operator=(MeanVertexData& other) = default; + MeanVertexData& operator=(MeanVertexData&& other) = default; + + //_____________________________________________ + void init(bool buseFit, int nbX, float rX, int nbY, float rY, int nbZ, float rZ) + { + + useFit = buseFit; + nbinsX = nbX; + rangeX = rX; + nbinsY = nbY; + rangeY = rY; + nbinsZ = nbZ; + rangeZ = rZ; + v2BinX = nbinsX / (2 * rangeX); + v2BinY = nbinsY / (2 * rangeY); + v2BinZ = nbinsZ / (2 * rangeZ); + histoX.resize(nbinsX, 0.); + histoY.resize(nbinsY, 0.); + histoZ.resize(nbinsZ, 0.); + } + + //_____________________________________________ + + size_t getEntries() const { return entries; } + void print() const; + void fill(const gsl::span<const PVertex> data); + void merge(const MeanVertexData* prev); + void subtract(const MeanVertexData* prev); + + ClassDefNV(MeanVertexData, 1); +}; + +} // end namespace calibration +} // end namespace o2 + +#endif /* MEAN_VERTEX_DATA_H_ */ diff --git a/Detectors/Calibration/include/DetectorsCalibration/MeanVertexParams.h b/Detectors/Calibration/include/DetectorsCalibration/MeanVertexParams.h new file mode 100644 index 0000000000000..11beb9e1435d3 --- /dev/null +++ b/Detectors/Calibration/include/DetectorsCalibration/MeanVertexParams.h @@ -0,0 +1,45 @@ +// 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 Chiara.Zampolli@cern.ch + +#ifndef ALICEO2_MEANVERTEX_PARAMS_H +#define ALICEO2_MEANVERTEX_PARAMS_H + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace calibration +{ + +// There are configurable params for TPC-ITS matching +struct MeanVertexParams : public o2::conf::ConfigurableParamHelper<MeanVertexParams> { + + int minEntries = 100; + int nbinsX = 100; + float rangeX = 1.f; + int nbinsY = 100; + float rangeY = 1.f; + int nbinsZ = 100; + float rangeZ = 20.f; + int nSlots4SMA = 5; + bool useFit = false; + int tfPerSlot = 5; + int maxTFdelay = 3; + + O2ParamDef(MeanVertexParams, "MeanVertexCalib"); +}; + +} // namespace calibration +} // end namespace o2 + +#endif diff --git a/Detectors/Calibration/src/DetectorsCalibrationLinkDef.h b/Detectors/Calibration/src/DetectorsCalibrationLinkDef.h new file mode 100644 index 0000000000000..337be0f3bbb5c --- /dev/null +++ b/Detectors/Calibration/src/DetectorsCalibrationLinkDef.h @@ -0,0 +1,24 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::calibration::MeanVertexData + ; +#pragma link C++ class o2::calibration::TimeSlot < o2::calibration::MeanVertexData> + ; +#pragma link C++ class o2::calibration::TimeSlotCalibration < o2::dataformats::PrimaryVertex, o2::calibration::MeanVertexData> + ; +#pragma link C++ class o2::calibration::MeanVertexCalibrator + ; +#pragma link C++ class o2::calibration::MeanVertexParams + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::calibration::MeanVertexParams> + ; + +#endif diff --git a/Detectors/Calibration/src/MeanVertexCalibrator.cxx b/Detectors/Calibration/src/MeanVertexCalibrator.cxx new file mode 100644 index 0000000000000..1141e872e4b3f --- /dev/null +++ b/Detectors/Calibration/src/MeanVertexCalibrator.cxx @@ -0,0 +1,214 @@ +// 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 "DetectorsCalibration/MeanVertexCalibrator.h" +#include "Framework/Logger.h" +#include "MathUtils/fit.h" +#include "CommonUtils/MemFileHelper.h" +#include "CCDB/CcdbApi.h" +#include "DetectorsCalibration/Utils.h" + +namespace o2 +{ +namespace calibration +{ + +using Slot = o2::calibration::TimeSlot<o2::calibration::MeanVertexData>; +using o2::math_utils::fitGaus; +using clbUtils = o2::calibration::Utils; +using MeanVertexObject = o2::dataformats::MeanVertexObject; + +void MeanVertexCalibrator::initOutput() +{ + // Here we initialize the vector of our output objects + mMeanVertexVector.clear(); + mInfoVector.clear(); + return; +} + +//_____________________________________________ +void MeanVertexCalibrator::finalizeSlot(Slot& slot) +{ + // Extract results for the single slot + o2::calibration::MeanVertexData* c = slot.getContainer(); + LOG(INFO) << "Finalize slot " << slot.getTFStart() << " <= TF <= " << slot.getTFEnd() << " with " + << c->getEntries() << " entries"; + mTmpMVobjDqTime.emplace_back(slot.getTFStart(), slot.getTFEnd()); + + if (mUseFit) { + MeanVertexObject mvo; + // x coordinate + std::vector<float> fitValues; + float* array = &c->histoX[0]; + double fitres = fitGaus(c->nbinsX, array, -(c->rangeX), c->rangeX, fitValues); + if (fitres >= 0) { + LOG(INFO) << "X: Fit result (of single Slot) => " << fitres << ". Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; + } else { + LOG(ERROR) << "X: Fit failed with result = " << fitres; + } + mvo.setX(fitValues[1]); + mvo.setSigmaX(fitValues[2]); + + // y coordinate + array = &c->histoY[0]; + fitres = fitGaus(c->nbinsY, array, -(c->rangeY), c->rangeY, fitValues); + if (fitres >= 0) { + LOG(INFO) << "Y: Fit result (of single Slot) => " << fitres << ". Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; + } else { + LOG(ERROR) << "Y: Fit failed with result = " << fitres; + } + mvo.setY(fitValues[1]); + mvo.setSigmaY(fitValues[2]); + + // z coordinate + array = &c->histoZ[0]; + fitres = fitGaus(c->nbinsZ, array, -(c->rangeZ), c->rangeZ, fitValues); + if (fitres >= 0) { + LOG(INFO) << "Z: Fit result (of single Slot) => " << fitres << ". Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; + } else { + LOG(ERROR) << "Z: Fit failed with result = " << fitres; + } + mvo.setZ(fitValues[1]); + mvo.setSigmaZ(fitValues[2]); + + // now we add the object to the deque + mTmpMVobjDq.push_back(std::move(mvo)); + } else { + mTmpMVdataDq.push_back(std::move(*c)); + mSMAdata.merge(&mTmpMVdataDq.back()); + if (mTmpMVobjDqTime.size() > mSMAslots) { + mSMAdata.subtract(&mTmpMVdataDq.front()); + mTmpMVdataDq.pop_front(); + } + } + + // output object + MeanVertexObject mvo; + + if (mUseFit) { + doSimpleMovingAverage(mTmpMVobjDq, mSMAMVobj); + } else { + // now we need to fit, on the merged data + LOG(DEBUG) << "**** Printing content of SMA MVData object for x coordinate"; + for (int i = 0; i < mSMAdata.nbinsX; i++) { + LOG(DEBUG) << "i = " << i << ", content of histogram = " << mSMAdata.histoX[i]; + } + std::vector<float> fitValues; + float* array = &mSMAdata.histoX[0]; + double fitres = fitGaus(mSMAdata.nbinsX, array, -(mSMAdata.rangeX), mSMAdata.rangeX, fitValues); + if (fitres >= 0) { + LOG(INFO) << "X: Fit result (of merged Slots) => " << fitres << ". Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; + } else { + LOG(ERROR) << "X: Fit failed with result = " << fitres; + } + mSMAMVobj.setX(fitValues[1]); + mSMAMVobj.setSigmaX(fitValues[2]); + + // y coordinate + array = &mSMAdata.histoY[0]; + fitres = fitGaus(mSMAdata.nbinsY, array, -(mSMAdata.rangeY), mSMAdata.rangeY, fitValues); + if (fitres >= 0) { + LOG(INFO) << "Y: Fit result (of merged Slots) => " << fitres << ". Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; + } else { + LOG(ERROR) << "Y: Fit failed with result = " << fitres; + } + mSMAMVobj.setY(fitValues[1]); + mSMAMVobj.setSigmaY(fitValues[2]); + + // z coordinate + array = &mSMAdata.histoZ[0]; + fitres = fitGaus(mSMAdata.nbinsZ, array, -(mSMAdata.rangeZ), mSMAdata.rangeZ, fitValues); + if (fitres >= 0) { + LOG(INFO) << "Z: Fit result (of merged Slots) => " << fitres << ". Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; + } else { + LOG(ERROR) << "Z: Fit failed with result = " << fitres; + } + mSMAMVobj.setZ(fitValues[1]); + mSMAMVobj.setSigmaZ(fitValues[2]); + } + + // TODO: the timestamp is now given with the TF index, but it will have + // to become an absolute time. This is true both for the lhc phase object itself + // and the CCDB entry + if (mTmpMVobjDqTime.size() > mSMAslots) { + mTmpMVobjDqTime.pop_front(); + } + TFType startValidity = (mTmpMVobjDqTime.front().getMin() + mTmpMVobjDqTime.back().getMax()) / 2; // will be rounded to uint64_t + LOG(INFO) << "start validity = " << startValidity; + std::map<std::string, std::string> md; + auto clName = o2::utils::MemFileHelper::getClassName(mSMAMVobj); + auto flName = o2::ccdb::CcdbApi::generateFileName(clName); + mInfoVector.emplace_back("GRP/MeanVertex", clName, flName, md, startValidity, 99999999999999); + mMeanVertexVector.emplace_back(mSMAMVobj); + + slot.print(); +} + +//_____________________________________________ +void MeanVertexCalibrator::doSimpleMovingAverage(std::deque<float>& dq, float& sma) +{ + + // doing simple moving average + + if (dq.size() <= mSMAslots) { + sma = std::accumulate(dq.begin(), dq.end(), 0.0) / dq.size(); + //avg = (avg * (vect.size() - 1) + vect.back()) / vect.size(); + return; + } + + // if the vector has size > mSMAslots, we calculate the SMA, and then we drop 1 element + // (note that it can have a size > mSMAslots only of 1 element!) + sma += (dq[dq.size() - 1] - dq[0]) / mSMAslots; + dq.pop_front(); + + return; +} + +//_____________________________________________ +void MeanVertexCalibrator::doSimpleMovingAverage(std::deque<MVObject>& dq, MVObject& sma) +{ + + // doing simple moving average + + if (dq.size() <= mSMAslots) { + sma.setX((sma.getX() * (dq.size() - 1) + dq.back().getX()) / dq.size()); + sma.setY((sma.getY() * (dq.size() - 1) + dq.back().getY()) / dq.size()); + sma.setZ((sma.getZ() * (dq.size() - 1) + dq.back().getZ()) / dq.size()); + sma.setSigmaX((sma.getSigmaX() * (dq.size() - 1) + dq.back().getSigmaX()) / dq.size()); + sma.setSigmaY((sma.getSigmaY() * (dq.size() - 1) + dq.back().getSigmaY()) / dq.size()); + sma.setSigmaZ((sma.getSigmaZ() * (dq.size() - 1) + dq.back().getSigmaZ()) / dq.size()); + return; + } + + // if the vector has size > mSMAslots, we calculate the SMA, and then we drop 1 element + // (note that it can have a size > mSMAslots only of 1 element!) + sma.setX(sma.getX() + (dq[dq.size() - 1].getX() - dq[0].getX()) / mSMAslots); + sma.setY(sma.getY() + (dq[dq.size() - 1].getY() - dq[0].getY()) / mSMAslots); + sma.setZ(sma.getZ() + (dq[dq.size() - 1].getZ() - dq[0].getZ()) / mSMAslots); + sma.setSigmaX(sma.getSigmaX() + (dq[dq.size() - 1].getSigmaX() - dq[0].getSigmaX()) / mSMAslots); + sma.setSigmaY(sma.getSigmaY() + (dq[dq.size() - 1].getSigmaY() - dq[0].getSigmaY()) / mSMAslots); + sma.setSigmaZ(sma.getSigmaZ() + (dq[dq.size() - 1].getSigmaZ() - dq[0].getSigmaZ()) / mSMAslots); + + dq.pop_front(); + + return; +} + +//_____________________________________________ +Slot& MeanVertexCalibrator::emplaceNewSlot(bool front, TFType tstart, TFType tend) +{ + auto& cont = getSlots(); + auto& slot = front ? cont.emplace_front(tstart, tend) : cont.emplace_back(tstart, tend); + slot.setContainer(std::make_unique<MeanVertexData>(mUseFit, mNBinsX, mRangeX, mNBinsY, mRangeY, mNBinsZ, mRangeZ)); + return slot; +} + +} // end namespace calibration +} // end namespace o2 diff --git a/Detectors/Calibration/src/MeanVertexData.cxx b/Detectors/Calibration/src/MeanVertexData.cxx new file mode 100644 index 0000000000000..dbcaf5b7616f8 --- /dev/null +++ b/Detectors/Calibration/src/MeanVertexData.cxx @@ -0,0 +1,115 @@ +// 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 "DetectorsCalibration/MeanVertexData.h" +#include "Framework/Logger.h" +#include "CommonUtils/MemFileHelper.h" +#include "CCDB/CcdbApi.h" +#include "DetectorsCalibration/Utils.h" + +using namespace o2::calibration; + +namespace o2 +{ +namespace calibration +{ + +using Slot = o2::calibration::TimeSlot<o2::calibration::MeanVertexData>; +using PVertex = o2::dataformats::PrimaryVertex; +using clbUtils = o2::calibration::Utils; + +//_____________________________________________ +MeanVertexData::MeanVertexData() +{ + LOG(INFO) << "Default c-tor, not to be used"; +} + +//_____________________________________________ +void MeanVertexData::print() const +{ + LOG(INFO) << entries << " entries"; +} + +//_____________________________________________ +void MeanVertexData::fill(const gsl::span<const PVertex> data) +{ + // fill container + + LOG(INFO) << "input size = " << data.size(); + for (int i = data.size(); i--;) { + // filling the histogram in binned mode + auto x = data[i].getX(); + auto y = data[i].getY(); + auto z = data[i].getZ(); + LOG(DEBUG) << "i = " << i << " --> x = " << x << ", y = " << y << ", z = " << z; + auto dx = x + rangeX; + uint32_t binx = dx < 0 ? 0xffffffff : (x + rangeX) * v2BinX; + auto dy = y + rangeY; + uint32_t biny = dy < 0 ? 0xffffffff : (y + rangeY) * v2BinY; + auto dz = z + rangeZ; + uint32_t binz = dz < 0 ? 0xffffffff : (z + rangeZ) * v2BinZ; + if (binx < nbinsX || biny < nbinsY || binz < nbinsZ) { // accounts also for z<-rangeZ + histoX[binx]++; + histoY[biny]++; + histoZ[binz]++; + entries++; + } + } + + for (int i = 0; i < histoX.size(); i++) { + LOG(DEBUG) << "histoX, bin " << i << ": entries = " << histoX[i]; + } + for (int i = 0; i < histoY.size(); i++) { + LOG(DEBUG) << "histoY, bin " << i << ": entries = " << histoY[i]; + } + for (int i = 0; i < histoZ.size(); i++) { + LOG(DEBUG) << "histoZ, bin " << i << ": entries = " << histoZ[i]; + } +} + +//_____________________________________________ +void MeanVertexData::subtract(const MeanVertexData* prev) +{ + // remove entries from prev + + assert(histoX.size() == prev->histoX.size()); + assert(histoY.size() == prev->histoY.size()); + assert(histoZ.size() == prev->histoZ.size()); + + for (int i = histoX.size(); i--;) { + histoX[i] -= prev->histoX[i]; + } + for (int i = histoY.size(); i--;) { + histoY[i] -= prev->histoY[i]; + } + for (int i = histoZ.size(); i--;) { + histoZ[i] -= prev->histoZ[i]; + } + entries -= prev->entries; +} + +//_____________________________________________ +void MeanVertexData::merge(const MeanVertexData* prev) +{ + // merge data of 2 slots + assert(histoX.size() == prev->histoX.size()); + assert(histoY.size() == prev->histoY.size()); + assert(histoZ.size() == prev->histoZ.size()); + + for (int i = histoX.size(); i--;) { + histoX[i] += prev->histoX[i]; + histoY[i] += prev->histoY[i]; + histoZ[i] += prev->histoZ[i]; + } + entries += prev->entries; +} + +} // end namespace calibration +} // end namespace o2 diff --git a/Detectors/Calibration/src/MeanVertexParams.cxx b/Detectors/Calibration/src/MeanVertexParams.cxx new file mode 100644 index 0000000000000..99a7b8252f959 --- /dev/null +++ b/Detectors/Calibration/src/MeanVertexParams.cxx @@ -0,0 +1,17 @@ +// 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 MeanVertex.h +/// \brief Configurable params for MeanVertex calibration +/// \author Chiara.Zampolli@cern.ch + +#include "DetectorsCalibration/MeanVertexParams.h" + +O2ParamImpl(o2::calibration::MeanVertexParams); diff --git a/Detectors/Calibration/src/TimeSlot.cxx b/Detectors/Calibration/src/TimeSlot.cxx new file mode 100644 index 0000000000000..af2e495a4bed0 --- /dev/null +++ b/Detectors/Calibration/src/TimeSlot.cxx @@ -0,0 +1,11 @@ +// 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 "DetectorsCalibration/TimeSlot.h" diff --git a/Detectors/Calibration/src/TimeSlotCalibration.cxx b/Detectors/Calibration/src/TimeSlotCalibration.cxx new file mode 100644 index 0000000000000..cb8ee39a9a405 --- /dev/null +++ b/Detectors/Calibration/src/TimeSlotCalibration.cxx @@ -0,0 +1,11 @@ +// 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 "DetectorsCalibration/TimeSlotCalibration.h" diff --git a/Detectors/Calibration/src/Utils.cxx b/Detectors/Calibration/src/Utils.cxx new file mode 100644 index 0000000000000..5d97b143344a8 --- /dev/null +++ b/Detectors/Calibration/src/Utils.cxx @@ -0,0 +1,11 @@ +// 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 "DetectorsCalibration/Utils.h" diff --git a/Detectors/Calibration/workflow/CMakeLists.txt b/Detectors/Calibration/workflow/CMakeLists.txt new file mode 100644 index 0000000000000..7e7375d613a9e --- /dev/null +++ b/Detectors/Calibration/workflow/CMakeLists.txt @@ -0,0 +1,31 @@ +# 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_library(DetectorsCalibrationWorkflow + SOURCES src/MeanVertexCalibratorSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::Headers + O2::CCDB + O2::CommonUtils + ms_gsl::ms_gsl + O2::ReconstructionDataFormats + O2::DataFormatsCalibration + O2::DetectorsCalibration) + + +o2_add_executable(mean-vertex-calibration-workflow + COMPONENT_NAME calibration + SOURCES src/mean-vertex-calibration-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DetectorsCalibration + O2::DetectorsCalibrationWorkflow + O2::ReconstructionDataFormats + O2::DataFormatsCalibration + O2::CCDB) diff --git a/Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h b/Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h new file mode 100644 index 0000000000000..3fc11e625e4f2 --- /dev/null +++ b/Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h @@ -0,0 +1,50 @@ +// 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_MEANVERTEX_CALIB_DEVICE_H +#define O2_MEANVERTEX_CALIB_DEVICE_H + +/// @file MeanVertexCalibratorSpec.h +/// @brief Device to calibrate MeanVertex + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "DetectorsCalibration/MeanVertexCalibrator.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace calibration +{ + +class MeanVertexCalibDevice : public Task +{ + public: + void init(o2::framework::InitContext& ic) final; + void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + void sendOutput(DataAllocator& output); + + std::unique_ptr<o2::calibration::MeanVertexCalibrator> mCalibrator; +}; + +} // namespace calibration + +namespace framework +{ +DataProcessorSpec getMeanVertexCalibDeviceSpec(); + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx b/Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx new file mode 100644 index 0000000000000..a43f9568496a3 --- /dev/null +++ b/Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx @@ -0,0 +1,123 @@ +// 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 MeanVertexCalibratorSpec.cxx + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" +#include "DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h" +#include "DetectorsCalibration/Utils.h" +#include "DetectorsCalibration/MeanVertexParams.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/CcdbObjectInfo.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace calibration +{ +void MeanVertexCalibDevice::init(InitContext& ic) +{ + + const o2::calibration::MeanVertexParams* params = &o2::calibration::MeanVertexParams::Instance(); + int minEnt = params->minEntries; + int nbX = params->nbinsX; + float rangeX = params->rangeX; + int nbY = params->nbinsY; + float rangeY = params->rangeY; + int nbZ = params->nbinsZ; + float rangeZ = params->rangeZ; + int nSlots4SMA = params->nSlots4SMA; + bool useFit = params->useFit; + int slotL = params->tfPerSlot; + int delay = params->maxTFdelay; + mCalibrator = std::make_unique<o2::calibration::MeanVertexCalibrator>(minEnt, useFit, nbX, rangeX, nbY, rangeY, nbZ, rangeZ, nSlots4SMA); + mCalibrator->setSlotLength(slotL); + mCalibrator->setMaxSlotsDelay(delay); +} + +//_____________________________________________________________ + +void MeanVertexCalibDevice::run(o2::framework::ProcessingContext& pc) +{ + + auto tfcounter = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; + auto data = pc.inputs().get<gsl::span<o2::dataformats::PrimaryVertex>>("input"); + LOG(INFO) << "Processing TF " << tfcounter << " with " << data.size() << " tracks"; + mCalibrator->process(tfcounter, data); + sendOutput(pc.outputs()); + const auto& infoVec = mCalibrator->getMeanVertexObjectInfoVector(); + LOG(INFO) << "Created " << infoVec.size() << " objects for TF " << tfcounter; +} + +//_____________________________________________________________ + +void MeanVertexCalibDevice::endOfStream(o2::framework::EndOfStreamContext& ec) +{ + + LOG(INFO) << "Finalizing calibration"; + constexpr uint64_t INFINITE_TF = 0xffffffffffffffff; + mCalibrator->checkSlotsToFinalize(INFINITE_TF); + sendOutput(ec.outputs()); +} + +//_____________________________________________________________ + +void MeanVertexCalibDevice::sendOutput(DataAllocator& output) +{ + + // extract CCDB infos and calibration objects, convert it to TMemFile and send them to the output + // TODO in principle, this routine is generic, can be moved to Utils.h + + using clbUtils = o2::calibration::Utils; + const auto& payloadVec = mCalibrator->getMeanVertexObjectVector(); + auto& infoVec = mCalibrator->getMeanVertexObjectInfoVector(); // use non-const version as we update it + assert(payloadVec.size() == infoVec.size()); + + for (uint32_t i = 0; i < payloadVec.size(); i++) { + auto& w = infoVec[i]; + auto image = o2::ccdb::CcdbApi::createObjectImage(&payloadVec[i], &w); + LOG(INFO) << "Sending object " << w.getPath() << "/" << w.getFileName() << " of size " << image->size() + << " bytes, valid for " << w.getStartValidityTimestamp() << " : " << w.getEndValidityTimestamp(); + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, i}, *image.get()); // vector<char> + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, i}, w); // root-serialized + } + if (payloadVec.size()) { + mCalibrator->initOutput(); // reset the outputs once they are already sent + } +} +} // namespace calibration + +namespace framework +{ + +DataProcessorSpec getMeanVertexCalibDeviceSpec() +{ + + using device = o2::calibration::MeanVertexCalibDevice; + using clbUtils = o2::calibration::Utils; + + std::vector<OutputSpec> outputs; + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload}); + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); + + return DataProcessorSpec{ + "mean-vertex-calibration", + Inputs{{"input", "GLO", "PVTX"}}, + outputs, + AlgorithmSpec{adaptFromTask<device>()}, + Options{ + {}}}; +} + +} // namespace framework +} // namespace o2 diff --git a/Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx b/Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx new file mode 100644 index 0000000000000..030a201ef954d --- /dev/null +++ b/Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx @@ -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. + +#include "Framework/DataProcessorSpec.h" +#include "DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getMeanVertexCalibDeviceSpec()); + return specs; +} diff --git a/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx b/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx index 6313a4aff417c..5391071dd833b 100644 --- a/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx +++ b/Detectors/TOF/calibration/src/LHCClockCalibrator.cxx @@ -81,7 +81,7 @@ void LHCClockCalibrator::finalizeSlot(Slot& slot) << c->getEntries() << " entries"; std::vector<float> fitValues; float* array = &c->histo[0]; - int fitres = fitGaus(c->nbins, array, -(c->range), c->range, fitValues); + double fitres = fitGaus(c->nbins, array, -(c->range), c->range, fitValues); if (fitres >= 0) { LOG(INFO) << "Fit result " << fitres << " Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; } else { diff --git a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx index 4c84dbc6d012b..78727f4016fec 100644 --- a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx +++ b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx @@ -473,7 +473,7 @@ void TOFChannelCalibrator::finalizeSlot(Slot& slot) } } - int fitres = fitGaus(c->getNbins(), histoValues.data(), -(c->getRange()), c->getRange(), fitValues); + double fitres = fitGaus(c->getNbins(), histoValues.data(), -(c->getRange()), c->getRange(), fitValues); if (fitValues[2] < 0) fitValues[2] = -fitValues[2]; From 09482d3edc129630438fd1ca6df7440b96b83cc5 Mon Sep 17 00:00:00 2001 From: Henrique Zanoli <hzanoli@gmail.com> Date: Thu, 29 Oct 2020 15:58:03 +0100 Subject: [PATCH 1151/1751] Add new plots for QA task (#4674) * Add new plots for QA task * Fix formating and add multiplicity * Fill impact parameter histogram only if propagation succeeds --- Analysis/Tasks/qaTask.cxx | 225 ++++++++++++++++++++++++++++++-------- 1 file changed, 182 insertions(+), 43 deletions(-) diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx index e2043c13ecc78..2e6c5f73a11b1 100644 --- a/Analysis/Tasks/qaTask.cxx +++ b/Analysis/Tasks/qaTask.cxx @@ -9,71 +9,210 @@ // or submit itself to any jurisdiction. /// \author Peter Hristov <Peter.Hristov@cern.ch>, CERN /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN +/// \author Henrique J C Zanoli <henrique.zanoli@cern.ch>, Utrecht University #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Analysis/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" #include "Analysis/MC.h" #include <TH1F.h> #include <TH2F.h> #include <cmath> -using namespace o2; -using namespace o2::framework; +namespace o2fw = o2::framework; +namespace o2exp = o2::framework::expressions; +namespace o2df = o2::dataformats; -struct QATrackingKine { - Configurable<bool> ismc{"ismc", false, "option to flag mc"}; - OutputObj<TH1F> hpt{TH1F("pt", ";p_{T} [GeV]", 100, 0., 10.)}; - OutputObj<TH1F> hphi{TH1F("phi", ";#phi", 100, 0, 2 * M_PI)}; - OutputObj<TH1F> heta{TH1F("eta", ";#eta", 100, -6, 6)}; - - void process(aod::Collision const& collision, - aod::BCs const& bcs, - soa::Join<aod::Tracks, aod::TracksCov> const& tracks) +namespace track_utils +{ +/// Converts a angle phi to the -pi to pi range. +double ConvertPhiRange(double phi) +{ + if (phi > M_PI) { + phi -= 2 * M_PI; + } else if (phi < -M_PI) { + phi += 2 * M_PI; + } + + return phi; +} + +/// Determines the impact parameter and its error for a given track. +/// \param track the track to get the impact parameter from. +/// \param primaryVertex the primary vertex of th collision. +/// \param impactParameter variable to save the impact parameter in micrometers. +/// \param impactParameterError variable to save the impact parameter error in micrometers. +template <typename Track> +bool GetImpactParameterAndError(const Track& track, const o2df::VertexBase& primaryVertex, double& impactParameter, + double& impactParameterError) +{ + impactParameter = -999.; + impactParameterError = -999.; + + o2df::DCA dca; + // FIXME: get this from CCDB + constexpr float magneticField{5.0}; // in kG + auto trackParameter = getTrackParCov(track); + bool propagate = trackParameter.propagateToDCA(primaryVertex, magneticField, &dca); + + if (propagate) { + impactParameter = 1000 * dca.getY(); + impactParameterError = 1000 * std::sqrt(dca.getSigmaY2()); + } + return propagate; +} +} // namespace track_utils + +/// Task to QA global observables of the event +struct QAGlobalObservables { + std::array<float, 2> collisionPositionRange = {-20., 20.}; + std::array<float, 2> numberOfTracksRange = {0, 2000}; + + o2fw::Configurable<int> nBinsNumberOfTracks{"nBinsNumberOfTracks", 2000, "Number of bins fot the Number of Tracks"}; + + o2fw::Configurable<int> nBinsVertexPosition{"nBinsPt", 100, "Number of bins for the Vertex Position"}; + + o2fw::OutputObj<TH1F> hCollisionX{ + TH1F("collisionX", "; X [cm];Counts", nBinsVertexPosition, collisionPositionRange[0], collisionPositionRange[1])}; + + o2fw::OutputObj<TH1F> hCollisionY{ + TH1F("collisionY", "; Y [cm];Counts", nBinsVertexPosition, collisionPositionRange[0], collisionPositionRange[1])}; + + o2fw::OutputObj<TH1F> hCollisionZ{ + TH1F("collisionZ", "; Z [cm];Counts", nBinsVertexPosition, collisionPositionRange[0], collisionPositionRange[1])}; + + o2fw::OutputObj<TH1F> hNumberOfTracks{TH1F("NumberOfTracks", "; Number of Tracks;Counts", nBinsNumberOfTracks, + numberOfTracksRange[0], numberOfTracksRange[1])}; + + void process(const o2::aod::Collision& collision, const o2::aod::Tracks& tracks) { - for (auto& track : tracks) { - heta->Fill(track.eta()); - hphi->Fill(track.phi()); - hpt->Fill(track.pt()); + hCollisionX->Fill(collision.posX()); + hCollisionY->Fill(collision.posY()); + hCollisionZ->Fill(collision.posZ()); + + int nTracks(0); + for (const auto& track : tracks) { + nTracks++; } + hNumberOfTracks->Fill(nTracks); } }; +/// Task to QA the kinematic properties of the tracks +struct QATrackingKine { + o2fw::Configurable<int> nBinsPt{"nBinsPt", 100, "Number of bins for Pt"}; + std::array<double, 2> ptRange = {0, 10.}; + o2fw::Configurable<int> nBinsPhi{"nBinsPhi", 100, "Number of bins for Phi"}; + o2fw::Configurable<int> nBinsEta{"nBinsEta", 100, "Number of bins for the eta histogram."}; + std::array<double, 2> etaRange = {-6, 6}; + + o2fw::OutputObj<TH1F> hPt{TH1F("pt", ";p_{T} [GeV];Counts", nBinsPt, ptRange[0], ptRange[1])}; + o2fw::OutputObj<TH1F> hEta{TH1F("eta", ";#eta;Counts", nBinsEta, etaRange[0], etaRange[1])}; + o2fw::OutputObj<TH1F> hPhi{TH1F("phi", ";#varphi [rad];Counts", nBinsPhi, 0, 2 * M_PI)}; + + void process(const o2::aod::Track& track) + { + hEta->Fill(track.eta()); + hPhi->Fill(track.phi()); + hPt->Fill(track.pt()); + } +}; + +/// Task to evaluate the tracking resolution (Pt, Eta, Phi and impact parameter) struct QATrackingResolution { - OutputObj<TH1F> etaDiff{TH1F("etaDiff", ";eta_{MC} - eta_{Rec}", 100, -2, 2)}; - OutputObj<TH1F> phiDiff{TH1F("phiDiff", ";phi_{MC} - phi_{Rec}", 100, -M_PI, M_PI)}; - OutputObj<TH1F> ptDiff{TH1F("ptDiff", ";p_{T}_{MC} - p_{T}_{Rec}", 400, -2., 2.)}; - OutputObj<TH1F> ptRes{TH1F("ptDRes", ";p_{T}_{MC} - p_{T}_{Rec} / p_{T}_{Rec} ", 400, -2., 2.)}; - OutputObj<TH2F> ptResvspt{TH2F("ptDResvspt", ";p_{T};Res p_{T}", 100, 0., 10., 400, -2., 2.)}; - OutputObj<TH2F> ptResvseta{TH2F("ptDResvseta", ";#eta;Res p_{T}", 400, -4., 4., 400, -2., 2.)}; - - void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const& collision, soa::Join<aod::Tracks, aod::McTrackLabels> const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcCollisions) + o2fw::Configurable<int> nBinsPtTrack{"nBinsPtTrack", 100, "Number of bins for the transverse momentum"}; + std::array<double, 2> ptRange = {0, 10.}; + + o2fw::Configurable<int> nBinsEtaTrack{"nBinsEtaTrack", 400, "Number of bins for the pseudorapidity"}; + std::array<double, 2> etaRange = {-6, 6}; + + o2fw::Configurable<int> nBinsDeltaPt{"nBinsDeltaPt", 400, "Number of bins for the transverse momentum differences"}; + + o2fw::Configurable<int> nBinsDeltaPhi{"nBinsPhi", 100, "Number of bins for the azimuthal angle differences"}; + + o2fw::Configurable<int> nBinsDeltaEta{"nBinsEta", 100, "Number of bins for the pseudorapidity differences"}; + + o2fw::Configurable<int> nBinsImpactParameter{"nBinsImpactParameter", 1000, "Number of bins for the Impact parameter"}; + + std::array<double, 2> impactParameterRange = {-1500, 1500}; // micrometer + std::array<double, 2> impactParameterResolutionRange = {0, 1000}; // micrometer + + o2fw::OutputObj<TH1F> etaDiffMCRec{TH1F("etaDiffMCReco", ";#eta_{MC} - #eta_{Rec}", nBinsDeltaEta, -2, 2)}; + + o2fw::OutputObj<TH1F> phiDiffMCRec{ + TH1F("phiDiffMCRec", ";#varphi_{MC} - #varphi_{Rec} [rad]", nBinsDeltaPhi, -M_PI, M_PI)}; + + o2fw::OutputObj<TH1F> ptDiffMCRec{TH1F("ptDiffMCRec", ";p_{T}_{MC} - p_{T}_{Rec} [GeV/c]", nBinsDeltaPt, -2., 2.)}; + + o2fw::OutputObj<TH1F> ptResolution{ + TH1F("ptResolution", ";(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec}) ", nBinsDeltaPt, -2., 2.)}; + + o2fw::OutputObj<TH2F> ptResolutionVsPt{TH2F("ptResolutionVsPt", + ";p_{T} [GeV/c];(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", nBinsPtTrack, + ptRange[0], ptRange[1], nBinsDeltaPt, 0, 2.)}; + + o2fw::OutputObj<TH2F> ptResolutionVsEta{TH2F("ptResolutionVsEta", ";#eta;(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", + nBinsEtaTrack, -4., 4., nBinsDeltaPt, -2., 2.)}; + + o2fw::OutputObj<TH2F> impactParameterVsPt{TH2F("impactParameterVsPt", ";p_{T} [GeV/c];Impact Parameter [{#mu}m]", + nBinsPtTrack, ptRange[0], ptRange[1], nBinsImpactParameter, + impactParameterRange[0], impactParameterRange[1])}; + + o2fw::OutputObj<TH2F> impactParameterVsEta{TH2F("impactParameterVsEta", "#eta;Impact Parameter [{#mu}m]", + nBinsEtaTrack, etaRange[0], etaRange[1], nBinsImpactParameter, + impactParameterRange[0], impactParameterRange[1])}; + + o2fw::OutputObj<TH2F> impactParameterErrorVsPt{ + TH2F("impactParameterErrorVsPt", ";p_{T} [GeV/c];Impact Parameter Error [#mum]", nBinsPtTrack, ptRange[0], + ptRange[1], nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1])}; + + o2fw::OutputObj<TH2F> impactParameterErrorVsEta{ + TH2F("impactParameterErrorVsEta", ";#eta;Impact Parameter Error [#mum]", nBinsEtaTrack, etaRange[0], etaRange[1], + nBinsImpactParameter, 0, impactParameterRange[1])}; + + void process(const o2::soa::Join<o2::aod::Collisions, o2::aod::McCollisionLabels>::iterator& collision, + const o2::soa::Join<o2::aod::Tracks, o2::aod::TracksCov, o2::aod::McTrackLabels>& tracks, + const o2::aod::McParticles& mcParticles, const o2::aod::McCollisions& mcCollisions) { - LOGF(info, "vtx-z (data) = %f | vtx-z (MC) = %f", collision.posZ(), collision.label().posZ()); - for (auto& track : tracks) { - ptDiff->Fill(track.label().pt() - track.pt()); - ptRes->Fill((track.label().pt() - track.pt()) / track.pt()); - ptResvspt->Fill(track.pt(), abs(track.label().pt() - track.pt()) / track.pt()); - ptResvseta->Fill(track.eta(), abs(track.label().pt() - track.pt()) / track.pt()); - etaDiff->Fill(track.label().eta() - track.eta()); - - auto delta = track.label().phi() - track.phi(); - if (delta > M_PI) { - delta -= 2 * M_PI; - } - if (delta < -M_PI) { - delta += 2 * M_PI; + const o2df::VertexBase primaryVertex = getPrimaryVertex(collision); + + for (const auto& track : tracks) { + const double deltaPt = track.label().pt() - track.pt(); + ptDiffMCRec->Fill(deltaPt); + + const double deltaPtOverPt = deltaPt / track.pt(); + ptResolution->Fill((deltaPtOverPt)); + ptResolutionVsPt->Fill(track.pt(), abs(deltaPtOverPt)); + ptResolutionVsEta->Fill(track.eta(), abs(deltaPtOverPt)); + + const double deltaEta = track.label().eta() - track.eta(); + etaDiffMCRec->Fill(deltaEta); + + const auto deltaPhi = track_utils::ConvertPhiRange(track.label().phi() - track.phi()); + phiDiffMCRec->Fill(deltaPhi); + + double impactParameter{-999.}; + double impactParameterError{-999.}; + + const bool propagate = + track_utils::GetImpactParameterAndError(track, primaryVertex, impactParameter, impactParameterError); + + if (propagate) { + impactParameterVsPt->Fill(track.pt(), impactParameter); + impactParameterVsEta->Fill(track.eta(), impactParameter); + impactParameterErrorVsPt->Fill(track.pt(), impactParameterError); + impactParameterErrorVsEta->Fill(track.eta(), impactParameterError); } - phiDiff->Fill(delta); } } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +o2fw::WorkflowSpec defineDataProcessing(o2fw::ConfigContext const&) { - return WorkflowSpec{ - adaptAnalysisTask<QATrackingKine>("qa-tracking-kine"), - adaptAnalysisTask<QATrackingResolution>("qa-tracking-resolution"), - }; + return o2fw::WorkflowSpec{o2fw::adaptAnalysisTask<QAGlobalObservables>("qa-global-observables"), + o2fw::adaptAnalysisTask<QATrackingKine>("qa-tracking-kine"), + o2fw::adaptAnalysisTask<QATrackingResolution>("qa-tracking-resolution")}; } From cd1565349ba9df14b330b322a633fba6fa52865a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 29 Oct 2020 15:48:56 +0100 Subject: [PATCH 1152/1751] Full-system-test: Extract metrics --- prodtests/full_system_test.sh | 40 ++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 8667e2ca174bf..4076170ae001d 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -32,6 +32,19 @@ NOMCLABELS="--disable-mc" # allow skipping JOBUTILS_SKIPDONE=ON +# enable memory monitoring (independent on whether DPL or not) +JOBUTILS_MONITORMEM=ON +# CPU monitoring JOBUTILS_MONITORCPU=ON + +# prepare some metrics file for the monitoring system +METRICFILE=metrics.dat +CONFIG="full_system_test_N${NEvents}" +HOST=`hostname` + +# include header information such as tested alidist tag and O2 tag +TAG="conf=${CONFIG},host=${HOST}${ALIDISTCOMMIT:+,alidist=$ALIDISTCOMMIT}${O2COMMIT:+,o2=$O2COMMIT}" +echo "versions,${TAG} alidist=\"${ALIDISTCOMMIT}\",O2=\"${O2COMMIT}\" " > ${METRICFILE} + ulimit -n 4096 # Make sure we can open sufficiently many files mkdir qed @@ -62,7 +75,8 @@ for STAGE in "NOGPU" "WITHGPU"; do fi ARGS_ALL="--session default" - taskwrapper reco_${STAGE}.log "o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | + logfile=reco_${STAGE}.log + taskwrapper ${logfile} "o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | o2-itsmft-stf-decoder-workflow $ARGS_ALL | o2-itsmft-stf-decoder-workflow $ARGS_ALL --runmft true | o2-its-reco-workflow $ARGS_ALL --trackerCA ${NOMCLABELS} --clusters-from-upstream --disable-root-output --entropy-encoding --configKeyValues \"fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500\" | @@ -78,4 +92,28 @@ o2-tof-compressor $ARGS_ALL | o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output ${NOMCLABELS} | o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input --shm-segment-size $SHMSIZE ${GLOBALDPLOPT}" + + # --- record interesting metrics to monitor ---- + # boolean flag indicating if workflow completed successfully at all + RC=$? + SUCCESS=0 + [ -f "${logfile}_done" ] && [ "$RC" = 0 ] && SUCCESS=1 + echo "success_${STAGE},${TAG} value=${SUCCESS}" >> ${METRICFILE} + + # runtime + walltime=`grep "#walltime" ${logfile}_time | awk '//{print $2}'` + echo "walltime_${STAGE},${TAG} value=${walltime}" >> ${METRICFILE} + + # memory + maxmem=`awk '/PROCESS MAX MEM/{print $5}' ${logfile}` # in MB + avgmem=`awk '/PROCESS AVG MEM/{print $5}' ${logfile}` # in MB + echo "maxmem_${STAGE},${TAG} value=${maxmem}" >> ${METRICFILE} + echo "avgmem_${STAGE},${TAG} value=${avgmem}" >> ${METRICFILE} + + # some physics quantities + tpctracks=`grep "tpc-tracker" ${logfile} | grep -e "found.*track" | awk '//{print $4}'` + echo "tpctracks_${STAGE},${TAG} value=${tpctracks}" >> ${METRICFILE} + tpcclusters=`grep -e "Event has.*TPC Clusters" ${logfile} | awk '//{print $5}'` + echo "tpcclusters_${STAGE},${TAG} value=${tpcclusters}" >> ${METRICFILE} done + From 36b52589874c95650bfbab654939e915dd7835e7 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 29 Oct 2020 18:34:49 +0100 Subject: [PATCH 1153/1751] Only consider Bz in propagator if specific flag is set (#4615) * Only consider Bz in propagator if specific flag is set * Fix Bz lookup --- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index 0703dadaa500d..24d29626b36b4 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -155,11 +155,20 @@ GPUd() int GPUTPCGMPropagator::RotateToAlpha(float newAlpha) float trackX = x0 * cc + ss * mT->Y(); // transport t0 to trackX - float B[3]; - GetBxByBz(newAlpha, t0.X(), t0.Y(), t0.Z(), B); float dLp = 0; - if (t0.PropagateToXBxByBz(trackX, B[0], B[1], B[2], dLp)) { - return -1; + float Bz; + if (mPropagateBzOnly) { + Bz = GetBzBase(newCosAlpha, newSinAlpha, t0.X(), t0.Y(), t0.Z()); + if (t0.PropagateToXBzLight(trackX, Bz, dLp)) { + return -1; + } + } else { + float B[3]; + GetBxByBz(newAlpha, t0.X(), t0.Y(), t0.Z(), B); + Bz = B[2]; + if (t0.PropagateToXBxByBz(trackX, B[0], B[1], B[2], dLp)) { + return -1; + } } if (CAMath::Abs(t0.SinPhi()) >= mMaxSinPhi) { @@ -233,7 +242,7 @@ GPUd() int GPUTPCGMPropagator::RotateToAlpha(float newAlpha) // only covariance changes. Use rotated and transported t0 for linearisation float j3 = -t0.Py() / t0.Px(); float j4 = -t0.Pz() / t0.Px(); - float j5 = t0.QPt() * B[2]; + float j5 = t0.QPt() * Bz; // Y Z Sin DzDs q/p X // Jacobian J1 = { { 1, 0, 0, 0, 0, j3 }, // Y From 254fa66ecd4654fc2317a6da3245afcd22d5f720 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 29 Oct 2020 19:10:38 +0100 Subject: [PATCH 1154/1751] DPL: avoid concurrent access to mPendingRegionInfos (#4713) --- Framework/Core/src/DataProcessingDevice.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index e4d6dc467685b..de06b901006cc 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -451,11 +451,14 @@ bool DataProcessingDevice::ConditionalRun() // Notify on the main thread the new region callbacks, making sure // no callback is issued if there is something still processing. - if (mPendingRegionInfos.empty() == false) { - std::vector<FairMQRegionInfo> toBeNotified; - toBeNotified.swap(mPendingRegionInfos); // avoid any MT issue. - for (auto const& info : toBeNotified) { - mServiceRegistry.get<CallbackService>()(CallbackService::Id::RegionInfoCallback, info); + { + std::lock_guard<std::mutex> lock(mRegionInfoMutex); + if (mPendingRegionInfos.empty() == false) { + std::vector<FairMQRegionInfo> toBeNotified; + toBeNotified.swap(mPendingRegionInfos); // avoid any MT issue. + for (auto const& info : toBeNotified) { + mServiceRegistry.get<CallbackService>()(CallbackService::Id::RegionInfoCallback, info); + } } } // Synchronous execution of the callbacks. This will be moved in the From 6c308d2a6bd842c18938b76fb758498b84034b2b Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <bogdan.vulpescu@clermont.in2p3.fr> Date: Thu, 29 Oct 2020 22:36:03 +0100 Subject: [PATCH 1155/1751] Mft raw (#4625) * MFT: add flag for MFT data in GBT data word * MFT: add the link information in the FEEID MSB --- .../include/ITSMFTReconstruction/ChipMappingMFT.h | 10 +++++----- Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h index 242b020b32e07..2075290916818 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h @@ -61,10 +61,10 @@ class ChipMappingMFT static constexpr Int_t getNRUs() { return NRUs; } ///< get FEEId of the RU (software id of the RU), read via given link - uint8_t FEEId2RUSW(uint16_t hw) const { return mFEEId2RUSW[hw]; } + uint8_t FEEId2RUSW(uint16_t hw) const { return mFEEId2RUSW[hw & 0xff]; } ///< get HW id of the RU (software id of the RU) - uint16_t RUSW2FEEId(uint16_t sw, uint16_t linkID = 0) const { return mRUInfo[sw].idHW; } + uint16_t RUSW2FEEId(uint16_t sw, uint16_t linkID = 0) const { return ((linkID << 8) + mRUInfo[sw].idHW); } ///< compose FEEid for given stave (ru) relative to layer and link, see documentation in the constructor uint16_t composeFEEId(uint16_t layer, uint16_t ruOnLayer, uint16_t link) const @@ -78,14 +78,14 @@ class ChipMappingMFT auto ddisk = std::div(layer, 2); uint16_t disk = ddisk.quot; uint16_t plane = layer % 2; - return (half << 6) + (disk << 3) + (plane << 2) + zone; + return (link << 8) + (half << 6) + (disk << 3) + (plane << 2) + zone; } ///< decompose FEEid to layer, stave (ru) relative to layer, link, see documentation in the constructor void expandFEEId(uint16_t feeID, uint16_t& layer, uint16_t& ruOnLayer, uint16_t& link) const { - link = 0; - uint16_t half = feeID >> 6; + link = feeID >> 8; + uint16_t half = (feeID >> 6) & 0x1; uint16_t disk = (feeID >> 3) & 0x7; uint16_t plane = (feeID >> 2) & 0x1; uint16_t zone = feeID & 0x3; diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index e37fa485b5ca7..efafcf3422abc 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -24,7 +24,6 @@ using namespace o2::itsmft; using RDHUtils = o2::raw::RDHUtils; using RDH = o2::header::RAWDataHeader; - ///====================================================================== /// GBT Link data decoding class ///====================================================================== @@ -79,7 +78,7 @@ void GBTLink::printTrigger(const GBTTrigger* gbtTrg) void GBTLink::printCalibrationWord(const GBTCalibration* gbtCal) { gbtCal->printX(); - LOGF(INFO, "Calibration word %5d | user_data 0x%012lx", gbtCal->calibCounter, gbtCal->bc); + LOGF(INFO, "Calibration word %5d | user_data 0x%06lx", gbtCal->calibCounter, gbtCal->calibUserField); } ///_________________________________________________________________ From 4a799a0dfba139e59e17b4c12ffecdb77416a89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Thu, 29 Oct 2020 22:40:18 +0100 Subject: [PATCH 1156/1751] Make the return type explicit. (#4718) --- Analysis/Core/include/Analysis/trackUtilities.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Analysis/Core/include/Analysis/trackUtilities.h b/Analysis/Core/include/Analysis/trackUtilities.h index 14a8a0a7227b5..83d38ab54d47b 100644 --- a/Analysis/Core/include/Analysis/trackUtilities.h +++ b/Analysis/Core/include/Analysis/trackUtilities.h @@ -21,9 +21,8 @@ #include "Analysis/RecoDecay.h" /// Extracts track parameters from a track. -/// \return o2::track::TrackPar template <typename T> -auto getTrackPar(const T& track) +o2::track::TrackPar getTrackPar(const T& track) { std::array<float, 5> arraypar = {track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt()}; From 885832c5148f776590aa9180d0b61dcbe61d6a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Thu, 29 Oct 2020 22:41:49 +0100 Subject: [PATCH 1157/1751] PWGHF: Add MC matching. (#4717) - Add functions for MC matching to RecoDecay. - Add tables with MC matching results. - Add an optional D0 MC task enabled by a command line option. - Fix iteratorAt. Exact PDG code match is required by default. Antiparticle variant can be accepted if requested via a boolean argument. Reconstruction level matching works for N prongs. Generator level matching works for 2 prongs only because of missing support for more daughters in the McParticles table. Only single-level decays are supported. Momentum conservation is not checked. Decay channel is not checked at the generator level if PDG codes of daughters are not provided. --- Analysis/Core/include/Analysis/RecoDecay.h | 127 ++++++++++++++++++ .../include/Analysis/HFSecondaryVertex.h | 11 ++ .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 43 +++++- Framework/Core/include/Framework/ASoA.h | 2 +- 4 files changed, 179 insertions(+), 4 deletions(-) diff --git a/Analysis/Core/include/Analysis/RecoDecay.h b/Analysis/Core/include/Analysis/RecoDecay.h index 228802391be27..39ac36afba093 100644 --- a/Analysis/Core/include/Analysis/RecoDecay.h +++ b/Analysis/Core/include/Analysis/RecoDecay.h @@ -25,6 +25,7 @@ #include <TPDGCode.h> #include "CommonConstants/MathConstants.h" +#include "Framework/Logger.h" using std::array; using namespace o2::constants::math; @@ -404,6 +405,132 @@ class RecoDecay return newMass; } + /// Check whether the reconstructed decay candidate is the expected decay. + /// \param particlesMC table with MC particles + /// \param arrDaughters array of candidate daughters + /// \param PDGMother expected mother PDG code + /// \param arrPDGDaughters array of expected daughter PDG codes + /// \param acceptAntiParticles switch to accept the antiparticle version of the expected decay + /// \return true if PDG codes of the mother and daughters are correct, false otherwise + template <std::size_t N, typename T, typename U> + static bool isMCMatchedDecayRec(const T& particlesMC, const array<U, N>& arrDaughters, int PDGMother, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false) + { + LOGF(debug, "isMCMatchedDecayRec: Expected mother PDG: %d", PDGMother); + int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle + array<o2::aod::McParticle, N> arrMothers; // array of mother particles + // loop over daughter particles + for (auto iProng = 0; iProng < N; ++iProng) { + auto particleI = arrDaughters[iProng].label(); // ith daughter particle + auto indexParticleIMother = particleI.mother0(); + if (indexParticleIMother == -1) { + return false; + } + // Check mother PDG code. + auto particleIMother = particlesMC.iteratorAt(indexParticleIMother); // mother of the ith daughter + auto PDGParticleIMother = particleIMother.pdgCode(); // PDG code of the mother of the ith daughter + LOGF(debug, "isMCMatchedDecayRec: Daughter %d mother PDG: %d", iProng, PDGParticleIMother); + if (PDGParticleIMother != sgn * PDGMother) { + if (acceptAntiParticles && iProng == 0 && PDGParticleIMother == -PDGMother) { + sgn = -1; // PDG code of the first daughter's mother determines whether the expected mother is a particle or antiparticle. + } else { + return false; + } + } + // Check daughter PDG code. + auto PDGParticleI = particleI.pdgCode(); // PDG code of the ith daughter + LOGF(debug, "isMCMatchedDecayRec: Daughter %d PDG: %d", iProng, PDGParticleI); + bool PDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? + for (auto iProngCp = 0; iProngCp < N; ++iProngCp) { + if (PDGParticleI == sgn * arrPDGDaughters[iProngCp]) { + arrPDGDaughters[iProngCp] = 0; // Remove this PDG code from the array of expected ones. + PDGFound = true; + break; + } + } + if (!PDGFound) { + return false; + } + arrMothers[iProng] = particleIMother; + } + // Check that all daughters have the same mother. + for (auto iProng = 1; iProng < N; ++iProng) { + if (arrMothers[iProng] != arrMothers[0]) { + return false; + } + } + LOGF(debug, "isMCMatchedDecayRec: Matched"); + return true; + } + + /// Check whether the MC particle is the expected one. + /// \param particlesMC table with MC particles + /// \param candidate candidate MC particle + /// \param PDGParticle expected particle PDG code + /// \param acceptAntiParticles switch to accept the antiparticle + /// \return true if PDG code of the particle is correct, false otherwise + template <typename T, typename U> + static bool isMCMatchedDecayGen(const T& particlesMC, const U& candidate, int PDGParticle, bool acceptAntiParticles = false) + { + return isMCMatchedDecayGen(particlesMC, candidate, PDGParticle, array{0}, acceptAntiParticles); + } + + /// Check whether the MC particle is the expected one and whether it decayed via the expected decay channel. + /// \param particlesMC table with MC particles + /// \param candidate candidate MC particle + /// \param PDGParticle expected particle PDG code + /// \param arrPDGDaughters array of expected PDG codes of daughters + /// \param acceptAntiParticles switch to accept the antiparticle + /// \return true if PDG codes of the particle and its daughters are correct, false otherwise + template <std::size_t N, typename T, typename U> + static bool isMCMatchedDecayGen(const T& particlesMC, const U& candidate, int PDGParticle, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false) + { + LOGF(debug, "isMCMatchedDecayGen: Expected particle PDG: %d", PDGParticle); + int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle + // Check the PDG code of the particle. + auto PDGCandidate = candidate.pdgCode(); + LOGF(debug, "isMCMatchedDecayGen: Candidate PDG: %d", PDGCandidate); + if (PDGCandidate != PDGParticle) { + if (acceptAntiParticles && PDGCandidate == -PDGParticle) { + sgn = -1; + } else { + return false; + } + } + // Check the PDG codes of the decay products. + if (N > 1) { + LOGF(debug, "isMCMatchedDecayGen: Checking %d daughters", N); + auto indexCandidateDaughterI = candidate.daughter0(); + for (auto iProng = 0; iProng < N; ++iProng) { + if (iProng == 1) { + indexCandidateDaughterI = candidate.daughter1(); + } + // FIXME: 3-prong decays + //else if (iProng == 2) { + // indexCandidateDaughterI = candidate.daughter2(); + //} + if (indexCandidateDaughterI == -1) { + return false; + } + auto candidateDaughterI = particlesMC.iteratorAt(indexCandidateDaughterI); // ith daughter particle + auto PDGCandidateDaughterI = candidateDaughterI.pdgCode(); // PDG code of the ith daughter + LOGF(debug, "isMCMatchedDecayGen: Daughter %d PDG: %d", iProng, PDGCandidateDaughterI); + bool PDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? + for (auto iProngCp = 0; iProngCp < N; ++iProngCp) { + if (PDGCandidateDaughterI == sgn * arrPDGDaughters[iProngCp]) { + arrPDGDaughters[iProngCp] = 0; // Remove this PDG code from the array of expected ones. + PDGFound = true; + break; + } + } + if (!PDGFound) { + return false; + } + } + } + LOGF(debug, "isMCMatchedDecayGen: Matched"); + return true; + } + private: static std::vector<std::tuple<int, double>> mListMass; ///< list of particle masses in form (PDG code, mass) }; diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index c5aec251b588a..2e83aaaa78a35 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -38,6 +38,7 @@ DECLARE_SOA_TABLE(HFSelTrack, "AOD", "HFSELTRACK", hf_seltrack::DCAPrim1); using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, HFSelTrack, pidRespTPC, pidRespTOF>; +using BigTracksMC = soa::Join<BigTracks, McTrackLabels>; // FIXME: this is a workaround until we get the index columns to work with joins. @@ -129,6 +130,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, [](fl DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m, double mTot, int iProng) { return RecoDecay::CosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); +DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, uint8_t); // Rec MC matching result: 0 - not matched, 1 - matched D0(bar) +DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, uint8_t); // Gen MC matching result: 0 - not matched, 1 - matched D0(bar) // functions for specific particles @@ -232,6 +235,14 @@ DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng2Ext, HfCandProng2Base, "HFCANDP2EXT" using HfCandProng2 = HfCandProng2Ext; +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfCandProng2MCRec, "AOD", "HFCANDP2MCREC", + hf_cand_prong2::FlagMCMatchRec); + +// table with results of generator level MC matching +DECLARE_SOA_TABLE(HfCandProng2MCGen, "AOD", "HFCANDP2MCGEN", + hf_cand_prong2::FlagMCMatchGen); + // specific 3-prong decay properties namespace hf_cand_prong3 { diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index c1e621cbf1602..f1d6adbad7ec4 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -14,7 +14,6 @@ /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN /// \author Vít Kučera <vit.kucera@cern.ch>, CERN -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" #include "Analysis/HFSecondaryVertex.h" @@ -24,6 +23,14 @@ using namespace o2; using namespace o2::framework; +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + ConfigParamSpec optionDoMC{"doMC", VariantType::Bool, false, {"Perform MC matching."}}; + workflowOptions.push_back(optionDoMC); +} + +#include "Framework/runDataProcessing.h" + /// Reconstruction of heavy-flavour 2-prong decay candidates struct HFCandidateCreator2Prong { Produces<aod::HfCandProng2Base> rowCandidateBase; @@ -128,9 +135,39 @@ struct HFCandidateCreator2ProngExpressions { void init(InitContext const&) {} }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +/// Performs MC matching. +struct HFCandidateCreator2ProngMC { + Produces<aod::HfCandProng2MCRec> rowMCMatchRec; + Produces<aod::HfCandProng2MCGen> rowMCMatchGen; + + void process(aod::HfCandProng2 const& candidates, + aod::BigTracksMC const& tracks, + aod::McParticles const& particlesMC) + { + // Match reconstructed candidates. + for (auto& candidate : candidates) { + auto isMatchedRec = RecoDecay::isMCMatchedDecayRec( + particlesMC, array{candidate.index0_as<aod::BigTracksMC>(), candidate.index1_as<aod::BigTracksMC>()}, + 421, array{+kPiPlus, -kKPlus}, true); + rowMCMatchRec(uint8_t(isMatchedRec)); + } + + // Match generated particles. + for (auto& particle : particlesMC) { + auto isMatchedGen = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 421, array{+kPiPlus, -kKPlus}, true); + rowMCMatchGen(uint8_t(isMatchedGen)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ + WorkflowSpec workflow{ adaptAnalysisTask<HFCandidateCreator2Prong>("hf-cand-creator-2prong"), adaptAnalysisTask<HFCandidateCreator2ProngExpressions>("hf-cand-creator-2prong-expressions")}; + const bool doMC = cfgc.options().get<bool>("doMC"); + if (doMC) { + workflow.push_back(adaptAnalysisTask<HFCandidateCreator2ProngMC>("hf-cand-creator-2prong-mc")); + } + return workflow; } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 41f98f2f7d304..a31588e003489 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -956,7 +956,7 @@ class Table return filtered_iterator(mColumnChunks, {selection, mOffset}); } - unfiltered_iterator iteratorAt(uint64_t i) + unfiltered_iterator iteratorAt(uint64_t i) const { return mBegin + (i - mOffset); } From addbd06acd8745726d7662bba4bab4d96294f929 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Fri, 30 Oct 2020 08:47:56 +0100 Subject: [PATCH 1158/1751] different formatting of severe error summary (#4719) --- Framework/Core/src/runDataProcessing.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 1fe3955a5fe70..8bf23a6651c02 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -272,13 +272,16 @@ bool areAllChildrenGone(std::vector<DeviceInfo>& infos) } /// Calculate exit code -int calculateExitCode(std::vector<DeviceInfo>& infos) +int calculateExitCode(DeviceSpecs& deviceSpecs, DeviceInfos& infos) { + std::regex regexp(R"(^\[([\d+:]*)\]\[\w+\] )"); int exitCode = 0; - for (auto& info : infos) { + for (size_t di = 0; di < deviceSpecs.size(); ++di) { + auto& info = infos[di]; + auto& spec = deviceSpecs[di]; if (exitCode == 0 && info.maxLogLevel >= LogParsingHelpers::LogLevel::Error) { - LOG(ERROR) << "Child " << info.pid << " had at least one " - << "message above severity ERROR: " << info.lastError; + LOG(ERROR) << "SEVERE: Device " << spec.name << " (" << info.pid << ") had at least one " + << "message above severity ERROR: " << std::regex_replace(info.lastError, regexp, ""); exitCode = 1; } } @@ -1270,7 +1273,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, LOG(INFO) << "Dumping used configuration in dpl-config.json"; boost::property_tree::write_json("dpl-config.json", finalConfig); cleanupSHM(driverInfo.uniqueWorkflowId); - return calculateExitCode(infos); + return calculateExitCode(deviceSpecs, infos); } case DriverState::PERFORM_CALLBACKS: for (auto& callback : driverControl.callbacks) { From b6eb1d9cd9381c3625730e1cd4ff19ad3bd64b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Fri, 30 Oct 2020 08:50:01 +0100 Subject: [PATCH 1159/1751] Extend QA task, fix MC particles eta (#4725) --- Analysis/Tasks/qaTask.cxx | 12 ++++++++---- Framework/Core/include/Framework/AnalysisDataModel.h | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx index 2e6c5f73a11b1..c77b4402ccca9 100644 --- a/Analysis/Tasks/qaTask.cxx +++ b/Analysis/Tasks/qaTask.cxx @@ -126,7 +126,7 @@ struct QATrackingResolution { o2fw::Configurable<int> nBinsPtTrack{"nBinsPtTrack", 100, "Number of bins for the transverse momentum"}; std::array<double, 2> ptRange = {0, 10.}; - o2fw::Configurable<int> nBinsEtaTrack{"nBinsEtaTrack", 400, "Number of bins for the pseudorapidity"}; + o2fw::Configurable<int> nBinsEta{"nBinsEta", 400, "Number of bins for the pseudorapidity"}; std::array<double, 2> etaRange = {-6, 6}; o2fw::Configurable<int> nBinsDeltaPt{"nBinsDeltaPt", 400, "Number of bins for the transverse momentum differences"}; @@ -141,6 +141,8 @@ struct QATrackingResolution { std::array<double, 2> impactParameterResolutionRange = {0, 1000}; // micrometer o2fw::OutputObj<TH1F> etaDiffMCRec{TH1F("etaDiffMCReco", ";#eta_{MC} - #eta_{Rec}", nBinsDeltaEta, -2, 2)}; + o2fw::OutputObj<TH2F> etaDiffMCRecoVsEtaMC{TH2F("etaDiffMCRecoVsEtaMC", ";#eta_{MC} - #eta_{Rec};#eta_{MC}", nBinsDeltaEta, -2, 2, nBinsEta, etaRange[0], etaRange[1])}; + o2fw::OutputObj<TH2F> etaDiffMCRecoVsEtaReco{TH2F("etaDiffMCRecoVsEtaReco", ";#eta_{MC} - #eta_{Rec};#eta_{Rec}", nBinsDeltaEta, -2, 2, nBinsEta, etaRange[0], etaRange[1])}; o2fw::OutputObj<TH1F> phiDiffMCRec{ TH1F("phiDiffMCRec", ";#varphi_{MC} - #varphi_{Rec} [rad]", nBinsDeltaPhi, -M_PI, M_PI)}; @@ -155,14 +157,14 @@ struct QATrackingResolution { ptRange[0], ptRange[1], nBinsDeltaPt, 0, 2.)}; o2fw::OutputObj<TH2F> ptResolutionVsEta{TH2F("ptResolutionVsEta", ";#eta;(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", - nBinsEtaTrack, -4., 4., nBinsDeltaPt, -2., 2.)}; + nBinsEta, -4., 4., nBinsDeltaPt, -2., 2.)}; o2fw::OutputObj<TH2F> impactParameterVsPt{TH2F("impactParameterVsPt", ";p_{T} [GeV/c];Impact Parameter [{#mu}m]", nBinsPtTrack, ptRange[0], ptRange[1], nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1])}; o2fw::OutputObj<TH2F> impactParameterVsEta{TH2F("impactParameterVsEta", "#eta;Impact Parameter [{#mu}m]", - nBinsEtaTrack, etaRange[0], etaRange[1], nBinsImpactParameter, + nBinsEta, etaRange[0], etaRange[1], nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1])}; o2fw::OutputObj<TH2F> impactParameterErrorVsPt{ @@ -170,7 +172,7 @@ struct QATrackingResolution { ptRange[1], nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1])}; o2fw::OutputObj<TH2F> impactParameterErrorVsEta{ - TH2F("impactParameterErrorVsEta", ";#eta;Impact Parameter Error [#mum]", nBinsEtaTrack, etaRange[0], etaRange[1], + TH2F("impactParameterErrorVsEta", ";#eta;Impact Parameter Error [#mum]", nBinsEta, etaRange[0], etaRange[1], nBinsImpactParameter, 0, impactParameterRange[1])}; void process(const o2::soa::Join<o2::aod::Collisions, o2::aod::McCollisionLabels>::iterator& collision, @@ -190,6 +192,8 @@ struct QATrackingResolution { const double deltaEta = track.label().eta() - track.eta(); etaDiffMCRec->Fill(deltaEta); + etaDiffMCRecoVsEtaMC->Fill(deltaEta, track.label().eta()); + etaDiffMCRecoVsEtaReco->Fill(deltaEta, track.eta()); const auto deltaPhi = track_utils::ConvertPhiRange(track.label().phi() - track.phi()); phiDiffMCRec->Fill(deltaPhi); diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index a3a191c6d9e06..c3a9ff1271b40 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -539,7 +539,7 @@ DECLARE_SOA_COLUMN(Vy, vy, float); DECLARE_SOA_COLUMN(Vz, vz, float); DECLARE_SOA_COLUMN(Vt, vt, float); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) -> float { return static_cast<float>(M_PI) + std::atan2(-py, -px); }); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return -0.5f * std::log((std::sqrt(px * px + py * py + pz * pz) + pz) / (std::sqrt(px * px + py * py + pz * pz) - pz)); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return 0.5f * std::log((std::sqrt(px * px + py * py + pz * pz) + pz) / (std::sqrt(px * px + py * py + pz * pz) - pz)); }); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return std::sqrt(px * px + py * py); }); DECLARE_SOA_DYNAMIC_COLUMN(ProducedByGenerator, producedByGenerator, [](uint8_t flags) -> bool { return (flags & 0x1) == 0x0; }); } // namespace mcparticle From 88658d56bbf66812e5d836c4aa6edbbf711b3280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Fri, 30 Oct 2020 08:50:26 +0100 Subject: [PATCH 1160/1751] Update to PID qa and spectra tasks (#4726) - Update pid QA tasks for TPC and TOF - Add histogram for collision time - Update PID QA using HistogramRegistry - Add configurable parameters for PID QA - Update spectra tasks - Using HistogramRegistry only - Avoid custom cuts and use filters from table instead - Streamlined tasks --- Analysis/Tasks/PWGLF/spectraTOF.cxx | 216 +++++----------------- Analysis/Tasks/PWGLF/spectraTPC.cxx | 252 ++++++-------------------- Analysis/Tasks/pidTOF.cxx | 267 +++++++--------------------- Analysis/Tasks/pidTPC.cxx | 161 +++++------------ 4 files changed, 209 insertions(+), 687 deletions(-) diff --git a/Analysis/Tasks/PWGLF/spectraTOF.cxx b/Analysis/Tasks/PWGLF/spectraTOF.cxx index 3cad077b5a146..e83db317184b6 100644 --- a/Analysis/Tasks/PWGLF/spectraTOF.cxx +++ b/Analysis/Tasks/PWGLF/spectraTOF.cxx @@ -9,199 +9,73 @@ // or submit itself to any jurisdiction. // O2 includes +#include "ReconstructionDataFormats/Track.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/Track.h" -#include "PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" - -// ROOT includes -#include <TH1F.h> - -#define DOTH1F(OBJ, ...) \ - OutputObj<TH1F> OBJ{TH1F(#OBJ, __VA_ARGS__)}; -#define DOTH2F(OBJ, ...) \ - OutputObj<TH2F> OBJ{TH2F(#OBJ, __VA_ARGS__)}; +#include "PID/PIDResponse.h" +#include "Analysis/TrackSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#define TRACKSELECTION \ - UChar_t clustermap = i.itsClusterMap(); \ - bool issel = (i.tpcNClsFindable() > 70) && (i.flags() & 0x4) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); \ - issel = issel && (i.flags() & 0x2000); \ - issel = issel && (i.flags() & 0x80000000); \ - if (!issel) \ - continue; - -// #define TRACKSELECTION 1; - -struct TOFQATask { - // Event quantities - DOTH1F(hvtxz, ";Vertex Z position;Events", 300, -15, 15); - DOTH1F(hevtime, ";Event time (ns);Tracks", 100, -2, 2); - // Track quantities - DOTH1F(heta, ";#eta;Tracks", 100, -1, 1); - DOTH1F(hp, ";#it{p} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hpt, ";#it{p}_{T} (GeV/#it{c});Tracks", 100, 0, 20); - DOTH1F(hlength, ";Track Length (cm);Tracks", 100, 0, 1000); - DOTH1F(htime, ";TOF Time (ns);Tracks", 1000, 0, 600); - // Beta - DOTH2F(hp_beta, ";#it{p} (GeV/#it{c});TOF #beta;Tracks", 100, 0, 20, 100, 0, 2); - - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) - { - hvtxz->Fill(collision.posZ()); - for (auto i : tracks) { - // Track selection - TRACKSELECTION; - // - hevtime->Fill(collision.collisionTime() / 1000); - // hevtime->Fill(collision.collisionTime0() / 1000); - const float psq = sqrt(i.px() * i.px() + i.py() * i.py() + i.pz() * i.pz()); - heta->Fill(i.eta()); - hp->Fill(i.p()); - hpt->Fill(i.pt()); - // - hlength->Fill(i.length()); - htime->Fill(i.tofSignal() / 1000); - // Beta - hp_beta->Fill(i.p(), i.beta()); - } - } -}; - -struct TOFExpTimeQATask { - // T-Texp -#define TIT(part) Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp %s});Tracks", part) - DOTH2F(htimediffEl, TIT("e"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffMu, TIT("#mu"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffPi, TIT("#pi"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffKa, TIT("K"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffPr, TIT("p"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffDe, TIT("d"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffTr, TIT("t"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffHe, TIT("^{3}He"), 100, 0, 5, 100, -1000, 1000); - DOTH2F(htimediffAl, TIT("#alpha"), 100, 0, 5, 100, -1000, 1000); -#undef TIT - - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) - { - for (auto i : tracks) { - // Track selection - TRACKSELECTION; - // - const float tof = i.tofSignal() - collision.collisionTime(); - htimediffEl->Fill(i.p(), tof - i.tofExpSignalEl()); - htimediffMu->Fill(i.p(), tof - i.tofExpSignalMu()); - htimediffPi->Fill(i.p(), tof - i.tofExpSignalPi()); - htimediffKa->Fill(i.p(), tof - i.tofExpSignalKa()); - htimediffPr->Fill(i.p(), tof - i.tofExpSignalPr()); - htimediffDe->Fill(i.p(), tof - i.tofExpSignalDe()); - htimediffTr->Fill(i.p(), tof - i.tofExpSignalTr()); - htimediffHe->Fill(i.p(), tof - i.tofExpSignalHe()); - htimediffAl->Fill(i.p(), tof - i.tofExpSignalAl()); - } - } -}; - -struct TOFNSigmaQATask { - // NSigma -#define TIT(part) Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp %s})/N_{sigma %s};Tracks", part, part) - DOTH2F(hnsigmaEl, TIT("e"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaMu, TIT("#mu"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaPi, TIT("#pi"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaKa, TIT("K"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaPr, TIT("p"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaDe, TIT("d"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaTr, TIT("t"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaHe, TIT("^{3}He"), 100, 0, 5, 100, -10, 10); - DOTH2F(hnsigmaAl, TIT("#alpha"), 100, 0, 5, 100, -10, 10); -#undef TIT +const int Np = 9; +const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; +const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; +struct TOFSpectraTask { + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) + void init(o2::framework::InitContext&) { - for (auto i : tracks) { - // Track selection - TRACKSELECTION; - // - hnsigmaEl->Fill(i.p(), i.tofNSigmaEl()); - hnsigmaMu->Fill(i.p(), i.tofNSigmaMu()); - hnsigmaPi->Fill(i.p(), i.tofNSigmaPi()); - hnsigmaKa->Fill(i.p(), i.tofNSigmaKa()); - hnsigmaPr->Fill(i.p(), i.tofNSigmaPr()); - hnsigmaDe->Fill(i.p(), i.tofNSigmaDe()); - hnsigmaTr->Fill(i.p(), i.tofNSigmaTr()); - hnsigmaHe->Fill(i.p(), i.tofNSigmaHe()); - hnsigmaAl->Fill(i.p(), i.tofNSigmaAl()); + histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + for (int i = 0; i < Np; i++) { + histos.add(Form("p/%s", pN[i].Data()), Form("%s;#it{p} (GeV/#it{c})", pT[i].Data()), kTH1F, {{100, 0, 20}}); + histos.add(Form("pt/%s", pN[i].Data()), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i].Data()), kTH1F, {{100, 0, 20}}); } + histos.add("electronbeta/hp_El", ";#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("electronbeta/hpt_El", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("electronbeta/hlength_El", ";Track Length (cm);Tracks", kTH1D, {{100, 0, 1000}}); + histos.add("electronbeta/htime_El", ";TOF Time (ns);Tracks", kTH1D, {{1000, 0, 600}}); + histos.add("electronbeta/hp_beta_El", ";#it{p} (GeV/#it{c});#beta - #beta_{e};Tracks", kTH2D, {{100, 0, 20}, {100, -0.01, 0.01}}); + histos.add("electronbeta/hp_betasigma_El", ";#it{p} (GeV/#it{c});(#beta - #beta_{e})/#sigma;Tracks", kTH2D, {{100, 0, 20}, {100, -5, 5}}); } -}; -struct TOFSpectraTask { - // Pt -#define TIT ";#it{p}_{T} (GeV/#it{c});Tracks" - DOTH1F(hpt_El, TIT, 100, 0, 20); - DOTH1F(hpt_Pi, TIT, 100, 0, 20); - DOTH1F(hpt_Ka, TIT, 100, 0, 20); - DOTH1F(hpt_Pr, TIT, 100, 0, 20); -#undef TIT - // P -#define TIT ";#it{p} (GeV/#it{c});Tracks" - DOTH1F(hp_El, TIT, 100, 0, 20); - DOTH1F(hp_Pi, TIT, 100, 0, 20); - DOTH1F(hp_Ka, TIT, 100, 0, 20); - DOTH1F(hp_Pr, TIT, 100, 0, 20); -#undef TIT - // - DOTH1F(hlength_El, ";Track Length (cm);Tracks", 100, 0, 1000); - DOTH1F(htime_El, ";TOF Time (ns);Tracks", 1000, 0, 600); - // DOTH1F(hevtime_El, ";Event time (ns);Tracks", 100, -2, 2); - // - DOTH2F(hp_beta_El, ";#it{p} (GeV/#it{c});#beta - #beta_{el};Tracks", 100, 0, 20, 100, -0.01, 0.01); - DOTH2F(hp_betasigma_El, ";#it{p} (GeV/#it{c});(#beta - #beta_{el})/#sigma;Tracks", 100, 0, 20, 100, -5, 5); + Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; - // Filter trk_filter = (aod::track::tpcNClsFindable > 70); + Filter trackFilter = aod::track::isGlobalTrack == true; - void process(soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta, aod::TrackSelection>>; + void process(TrackCandidates::iterator const& track) { - for (auto i : tracks) { - // Track selection - TRACKSELECTION; - // - if (TMath::Abs(i.tofNSigmaPi()) < 3) { - hp_Pi->Fill(i.p()); - hpt_Pi->Fill(i.pt()); - } else if (TMath::Abs(i.tofNSigmaKa()) < 3) { - hp_Ka->Fill(i.p()); - hpt_Ka->Fill(i.pt()); - } else if (TMath::Abs(i.tofNSigmaPr()) < 3) { - hp_Pr->Fill(i.p()); - hpt_Pr->Fill(i.pt()); - } - if (TMath::Abs(i.separationbetael() < 1.f)) { - hp_El->Fill(i.p()); - hpt_El->Fill(i.pt()); - // - hlength_El->Fill(i.length()); - htime_El->Fill(i.tofSignal() / 1000); - // - hp_beta_El->Fill(i.p(), i.diffbetael()); - hp_betasigma_El->Fill(i.p(), i.separationbetael()); + const float nsigma[Np] = {track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), + track.tofNSigmaKa(), track.tofNSigmaPr(), track.tofNSigmaDe(), + track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl()}; + histos.fill("p/Unselected", track.p()); + histos.fill("pt/Unselected", track.pt()); + for (int i = 0; i < Np; i++) { + if (abs(nsigma[i]) > nsigmacut.value) { + continue; } + histos.fill(Form("p/%s", pN[i].Data()), track.p()); + histos.fill(Form("pt/%s", pN[i].Data()), track.pt()); + } + // + if (TMath::Abs(track.separationbetael() < 1.f)) { + histos.fill("electronbeta/hp_El", track.p()); + histos.fill("electronbeta/hpt_El", track.pt()); + histos.fill("electronbeta/hlength_El", track.length()); + histos.fill("electronbeta/htime_El", track.tofSignal() / 1000); + histos.fill("electronbeta/hp_beta_El", track.p(), track.diffbetael()); + histos.fill("electronbeta/hp_betasigma_El", track.p(), track.separationbetael()); } } }; WorkflowSpec defineDataProcessing(ConfigContext const&) { - return WorkflowSpec{ - adaptAnalysisTask<TOFQATask>("tofqa-task"), - adaptAnalysisTask<TOFExpTimeQATask>("tofexptime-task"), - adaptAnalysisTask<TOFNSigmaQATask>("tofnsigma-task"), - adaptAnalysisTask<TOFSpectraTask>("tofspectra-task")}; + WorkflowSpec workflow{adaptAnalysisTask<TOFSpectraTask>("tofspectra-task")}; + return workflow; } - -#undef TRACKSELECTION diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index 9fbce2a861d84..0441f591aeeb7 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -16,13 +16,14 @@ #include "PID/PIDResponse.h" #include "Analysis/TrackSelectionTables.h" -// ROOT includes -#include <TH1F.h> - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +const int Np = 9; +const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; +const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { std::vector<ConfigParamSpec> options{ @@ -32,21 +33,11 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) #include "Framework/runDataProcessing.h" -#define DOTH1F(OBJ, ...) \ - OutputObj<TH1F> OBJ{TH1F(#OBJ, __VA_ARGS__)}; -#define DOTH2F(OBJ, ...) \ - OutputObj<TH2F> OBJ{TH2F(#OBJ, __VA_ARGS__)}; -#define DOTH3F(OBJ, ...) \ - OutputObj<TH3F> OBJ{TH3F(#OBJ, __VA_ARGS__)}; - -#define CANDIDATE_SELECTION \ - Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; \ - Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; \ - Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; \ - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); \ - using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>>; \ - using TrackCandidateswTOF = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>>; \ - using CollisionCandidates = soa::Filtered<aod::Collisions>; +#define CANDIDATE_SELECTION \ + Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; \ + Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; \ + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; \ + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == true); #define makelogaxis(h) \ { \ @@ -63,209 +54,72 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) h->GetXaxis()->Set(nbins, binp); \ } -struct TPCPIDQAExpSignalTask { - // Options -#define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000 - - DOTH1F(hvertexz, ";Vtx_{z} (cm);Entries", 100, -20, 20); - DOTH2F(htpcsignal, ";#it{p} (GeV/#it{c});TPC Signal;Tracks", BIN_AXIS); - DOTH2F(hexpEl, ";#it{p} (GeV/#it{c});TPC expected signal e;Tracks", BIN_AXIS); - DOTH2F(hexpMu, ";#it{p} (GeV/#it{c});TPC expected signal #mu;Tracks", BIN_AXIS); - DOTH2F(hexpPi, ";#it{p} (GeV/#it{c});TPC expected signal #pi;Tracks", BIN_AXIS); - DOTH2F(hexpKa, ";#it{p} (GeV/#it{c});TPC expected signal K;Tracks", BIN_AXIS); - DOTH2F(hexpPr, ";#it{p} (GeV/#it{c});TPC expected signal p;Tracks", BIN_AXIS); - DOTH2F(hexpDe, ";#it{p} (GeV/#it{c});TPC expected signal d;Tracks", BIN_AXIS); - DOTH2F(hexpTr, ";#it{p} (GeV/#it{c});TPC expected signal t;Tracks", BIN_AXIS); - DOTH2F(hexpHe, ";#it{p} (GeV/#it{c});TPC expected signal ^{3}He;Tracks", BIN_AXIS); - DOTH2F(hexpAl, ";#it{p} (GeV/#it{c});TPC expected signal #alpha;Tracks", BIN_AXIS); - -#undef BIN_AXIS +struct TPCPIDQASignalwTOFTask { + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { - // Log binning for p - makelogaxis(htpcsignal); - makelogaxis(hexpEl); - makelogaxis(hexpMu); - makelogaxis(hexpPi); - makelogaxis(hexpKa); - makelogaxis(hexpPr); - makelogaxis(hexpDe); - makelogaxis(hexpTr); - makelogaxis(hexpHe); - makelogaxis(hexpAl); - } - - // Filters - CANDIDATE_SELECTION - - void process(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) - { - hvertexz->Fill(collision.posZ()); - for (auto const& i : tracks) { - // const float mom = i.p(); - const float mom = i.tpcInnerParam(); - htpcsignal->Fill(mom, i.tpcSignal()); - hexpEl->Fill(mom, i.tpcExpSignalEl()); - hexpMu->Fill(mom, i.tpcExpSignalMu()); - hexpPi->Fill(mom, i.tpcExpSignalPi()); - hexpKa->Fill(mom, i.tpcExpSignalKa()); - hexpPr->Fill(mom, i.tpcExpSignalPr()); - hexpDe->Fill(mom, i.tpcExpSignalDe()); - hexpTr->Fill(mom, i.tpcExpSignalTr()); - hexpHe->Fill(mom, i.tpcExpSignalHe()); - hexpAl->Fill(mom, i.tpcExpSignalAl()); + for (int i = 0; i < Np; i++) { + histos.add("signal/htpcsignal" + pN[i], ";#it{p} (GeV/#it{c});TPC Signal;N_{#sigma}^{TPC}(" + pT[i] + ")", kTH3D, {{1000, 0.001, 20}, {1000, 0, 1000}, {20, -10, 10}}); + makelogaxis(histos.get<TH3>("hexp" + pN[i])); } } -}; - -struct TPCPIDQANSigmaTask { - // Options -#define BIN_AXIS 1000, 0.001, 20, 1000, -10, 10 - - // TPC NSigma - DOTH2F(hnsigmaEl, ";#it{p} (GeV/#it{c});TPC N_{sigma e};Tracks", BIN_AXIS); - DOTH2F(hnsigmaMu, ";#it{p} (GeV/#it{c});TPC N_{sigma #mu};Tracks", BIN_AXIS); - DOTH2F(hnsigmaPi, ";#it{p} (GeV/#it{c});TPC N_{sigma #pi};Tracks", BIN_AXIS); - DOTH2F(hnsigmaKa, ";#it{p} (GeV/#it{c});TPC N_{sigma K};Tracks", BIN_AXIS); - DOTH2F(hnsigmaPr, ";#it{p} (GeV/#it{c});TPC N_{sigma p};Tracks", BIN_AXIS); - DOTH2F(hnsigmaDe, ";#it{p} (GeV/#it{c});TPC N_{sigma d};Tracks", BIN_AXIS); - DOTH2F(hnsigmaTr, ";#it{p} (GeV/#it{c});TPC N_{sigma t};Tracks", BIN_AXIS); - DOTH2F(hnsigmaHe, ";#it{p} (GeV/#it{c});TPC N_{sigma ^{3}He};Tracks", BIN_AXIS); - DOTH2F(hnsigmaAl, ";#it{p} (GeV/#it{c});TPC N_{sigma #alpha};Tracks", BIN_AXIS); - -#undef BIN_AXIS - - void init(o2::framework::InitContext&) - { - // Log binning for p - makelogaxis(hnsigmaEl); - makelogaxis(hnsigmaMu); - makelogaxis(hnsigmaPi); - makelogaxis(hnsigmaKa); - makelogaxis(hnsigmaPr); - makelogaxis(hnsigmaDe); - makelogaxis(hnsigmaTr); - makelogaxis(hnsigmaHe); - makelogaxis(hnsigmaAl); - } // Filters CANDIDATE_SELECTION - void process(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) + Filter trackFilterTOF = (aod::track::tofSignal > 0); // Skip tracks without TOF + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>>; + void process(TrackCandidates::iterator const& track) { - for (auto const& i : tracks) { - hnsigmaEl->Fill(i.p(), i.tpcNSigmaEl()); - hnsigmaMu->Fill(i.p(), i.tpcNSigmaMu()); - hnsigmaPi->Fill(i.p(), i.tpcNSigmaPi()); - hnsigmaKa->Fill(i.p(), i.tpcNSigmaKa()); - hnsigmaPr->Fill(i.p(), i.tpcNSigmaPr()); - hnsigmaDe->Fill(i.p(), i.tpcNSigmaDe()); - hnsigmaTr->Fill(i.p(), i.tpcNSigmaTr()); - hnsigmaHe->Fill(i.p(), i.tpcNSigmaHe()); - hnsigmaAl->Fill(i.p(), i.tpcNSigmaAl()); - } + // const float mom = track.p(); + const float mom = track.tpcInnerParam(); + histos.fill("htpcsignalEl", mom, track.tpcSignal(), track.tofNSigmaEl()); + histos.fill("htpcsignalMu", mom, track.tpcSignal(), track.tofNSigmaMu()); + histos.fill("htpcsignalPi", mom, track.tpcSignal(), track.tofNSigmaPi()); + histos.fill("htpcsignalKa", mom, track.tpcSignal(), track.tofNSigmaKa()); + histos.fill("htpcsignalPr", mom, track.tpcSignal(), track.tofNSigmaPr()); + histos.fill("htpcsignalDe", mom, track.tpcSignal(), track.tofNSigmaDe()); + histos.fill("htpcsignalTr", mom, track.tpcSignal(), track.tofNSigmaTr()); + histos.fill("htpcsignalHe", mom, track.tpcSignal(), track.tofNSigmaHe()); + histos.fill("htpcsignalAl", mom, track.tpcSignal(), track.tofNSigmaAl()); } }; -struct TPCPIDQASignalwTOFTask { - -#define BIN_AXIS 1000, 0.001, 20, 1000, 0, 1000, 20, -10, 10 - - DOTH3F(htpcsignalEl, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma e", BIN_AXIS); - DOTH3F(htpcsignalMu, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma #mu", BIN_AXIS); - DOTH3F(htpcsignalPi, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma #pi", BIN_AXIS); - DOTH3F(htpcsignalKa, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma K", BIN_AXIS); - DOTH3F(htpcsignalPr, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma p", BIN_AXIS); - DOTH3F(htpcsignalDe, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma d", BIN_AXIS); - DOTH3F(htpcsignalTr, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma t", BIN_AXIS); - DOTH3F(htpcsignalHe, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma ^{3}He", BIN_AXIS); - DOTH3F(htpcsignalAl, ";#it{p} (GeV/#it{c});TPC Signal;TOF N#sigma #alpha", BIN_AXIS); - -#undef BIN_AXIS +struct TPCSpectraTask { + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry pt{"pt", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry p{"pt", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { - // Log binning for p - makelogaxis(htpcsignalEl); - makelogaxis(htpcsignalMu); - makelogaxis(htpcsignalPi); - makelogaxis(htpcsignalKa); - makelogaxis(htpcsignalPr); - makelogaxis(htpcsignalDe); - makelogaxis(htpcsignalTr); - makelogaxis(htpcsignalHe); - makelogaxis(htpcsignalAl); - } - - // Filters - CANDIDATE_SELECTION - - void process(CollisionCandidates::iterator const& collision, TrackCandidateswTOF const& tracks) - { - for (auto const& i : tracks) { - // const float mom = i.p(); - const float mom = i.tpcInnerParam(); - if (i.tofSignal() < 0) { // Skip tracks without TOF - continue; - } - htpcsignalEl->Fill(mom, i.tpcSignal(), i.tofNSigmaEl()); - htpcsignalMu->Fill(mom, i.tpcSignal(), i.tofNSigmaMu()); - htpcsignalPi->Fill(mom, i.tpcSignal(), i.tofNSigmaPi()); - htpcsignalKa->Fill(mom, i.tpcSignal(), i.tofNSigmaKa()); - htpcsignalPr->Fill(mom, i.tpcSignal(), i.tofNSigmaPr()); - htpcsignalDe->Fill(mom, i.tpcSignal(), i.tofNSigmaDe()); - htpcsignalTr->Fill(mom, i.tpcSignal(), i.tofNSigmaTr()); - htpcsignalHe->Fill(mom, i.tpcSignal(), i.tofNSigmaHe()); - htpcsignalAl->Fill(mom, i.tpcSignal(), i.tofNSigmaAl()); + histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + for (int i = 0; i < Np; i++) { + histos.add("p/" + pN[i], pT[i] + ";#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("pt/" + pN[i], pT[i] + ";#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); } } -}; - -struct TPCSpectraTask { - - // Pt -#define TIT ";#it{p}_{T} (GeV/#it{c});Tracks" - DOTH1F(hpt, TIT, 100, 0, 20); - DOTH1F(hpt_El, TIT, 100, 0, 20); - DOTH1F(hpt_Pi, TIT, 100, 0, 20); - DOTH1F(hpt_Ka, TIT, 100, 0, 20); - DOTH1F(hpt_Pr, TIT, 100, 0, 20); -#undef TIT - // P -#define TIT ";#it{p} (GeV/#it{c});Tracks" - DOTH1F(hp, TIT, 100, 0, 20); - DOTH1F(hp_El, TIT, 100, 0, 20); - DOTH1F(hp_Pi, TIT, 100, 0, 20); - DOTH1F(hp_Ka, TIT, 100, 0, 20); - DOTH1F(hp_Pr, TIT, 100, 0, 20); -#undef TIT //Defining filters and input CANDIDATE_SELECTION - void process(CollisionCandidates::iterator const& collision, TrackCandidates const& tracks) + Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; + + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>>; + void process(TrackCandidates::iterator const& track) { - for (auto i : tracks) { - hp->Fill(i.p()); - hpt->Fill(i.pt()); - if (TMath::Abs(i.tpcNSigmaEl()) < 3) { - hp_El->Fill(i.p()); - hpt_El->Fill(i.pt()); - } - if (TMath::Abs(i.tpcNSigmaPi()) < 3) { - hp_Pi->Fill(i.p()); - hpt_Pi->Fill(i.pt()); - } - if (TMath::Abs(i.tpcNSigmaKa()) < 3) { - hp_Ka->Fill(i.p()); - hpt_Ka->Fill(i.pt()); - } - if (TMath::Abs(i.tpcNSigmaPr()) < 3) { - hp_Pr->Fill(i.p()); - hpt_Pr->Fill(i.pt()); + const float nsigma[Np] = {track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), + track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tpcNSigmaDe(), + track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl()}; + p.fill("Unselected", track.p()); + pt.fill("Unselected", track.pt()); + for (int i = 0; i < Np; i++) { + if (abs(nsigma[i]) > nsigmacut.value) { + continue; } + p.fill(pN[i], track.p()); + pt.fill(pN[i], track.pt()); } } }; @@ -273,9 +127,7 @@ struct TPCSpectraTask { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { int TPCwTOF = cfgc.options().get<int>("add-tof-histos"); - WorkflowSpec workflow{adaptAnalysisTask<TPCPIDQAExpSignalTask>("TPCpidqa-expsignal-task"), - adaptAnalysisTask<TPCPIDQANSigmaTask>("TPCpidqa-nsigma-task"), - adaptAnalysisTask<TPCSpectraTask>("tpcspectra-task")}; + WorkflowSpec workflow{adaptAnalysisTask<TPCSpectraTask>("tpcspectra-task")}; if (TPCwTOF) { workflow.push_back(adaptAnalysisTask<TPCPIDQASignalwTOFTask>("TPCpidqa-signalwTOF-task")); } diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index af985a6cf9464..800e629add311 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -12,20 +12,12 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" #include "ReconstructionDataFormats/Track.h" -#include "PID/PIDResponse.h" #include <CCDB/BasicCCDBManager.h> -#include "Analysis/HistHelpers.h" +#include "PID/PIDResponse.h" #include "PID/PIDTOF.h" -// #define USE_REGISTRY -#ifdef USE_REGISTRY -#include "Framework/HistogramRegistry.h" -#endif - -// ROOT includes -#include <TH1F.h> - using namespace o2; using namespace o2::framework; using namespace o2::pid; @@ -143,212 +135,85 @@ struct pidTOFTaskBeta { } }; +const int Np = 9; +const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; +const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; struct pidTOFTaskQA { - enum event_histo : uint8_t { vertexz, - signal, - tofbeta }; - enum Particle : uint8_t { El, - Mu, - Pi, - Ka, - Pr, - De, - Tr, - He, - Al }; - -#ifdef USE_REGISTRY - // Event - HistogramRegistry event{ - "event", - true, - { - {"hvertexz", ";Vtx_{z} (cm);Entries", {HistogramType::kTH1F, {{100, -20, 20}}}}, - {"htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}} // - {"htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", {HistogramType::kTH2F, {{100, 0, 5}, {100, 0, 2}}}} // - } // - }; - // Exp signal - HistogramRegistry expected{ - "expected", - true, - { - {"hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}}, - {"hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", {HistogramType::kTH2F, {{100, 0, 5}, {1000, 0, 2e6}}}} // - } // - }; - // T-Texp - HistogramRegistry timediff{ - "timediff", - true, - { - {"htimediffEl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffMu", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffPi", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffKa", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffPr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffDe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp d})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffTr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp t})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffHe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp ^{3}He})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}}, - {"htimediffAl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #alpha})", {HistogramType::kTH2F, {{100, 0, 5}, {100, -1000, 1000}}}} // - } // - }; - - // NSigma - HistogramRegistry nsigma{ - "nsigma", - true, - { - {"hnsigmaEl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(e)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaMu", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#mu)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaPi", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#pi)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaKa", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(K)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaPr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(p)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaDe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(d)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaTr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(t)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaHe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(^{3}He)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}}, - {"hnsigmaAl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#alpha)", {HistogramType::kTH2F, {{1000, 0.001, 20}, {200, -10, 10}}}} // - } // - }; -#else - // Event - OutputObj<experimental::histhelpers::HistFolder> event{experimental::histhelpers::HistFolder("event"), OutputObjHandlingPolicy::QAObject}; - // Exp signal - OutputObj<experimental::histhelpers::HistFolder> expected{experimental::histhelpers::HistFolder("expected"), OutputObjHandlingPolicy::QAObject}; - // T-Texp - OutputObj<experimental::histhelpers::HistFolder> timediff{experimental::histhelpers::HistFolder("timediff"), OutputObjHandlingPolicy::QAObject}; - // NSigma - OutputObj<experimental::histhelpers::HistFolder> nsigma{experimental::histhelpers::HistFolder("nsigma"), OutputObjHandlingPolicy::QAObject}; -#endif + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; + + Configurable<int> nBinsP{"nBinsP", 400, "Number of bins for the momentum"}; + Configurable<float> MinP{"MinP", 0.1, "Minimum momentum in range"}; + Configurable<float> MaxP{"MaxP", 5, "Maximum momentum in range"}; + +#define makelogaxis(h) \ + { \ + const Int_t nbins = h->GetNbinsX(); \ + double binp[nbins + 1]; \ + double max = h->GetXaxis()->GetBinUpEdge(nbins); \ + double min = h->GetXaxis()->GetBinLowEdge(1); \ + if (min <= 0) \ + min = 0.00001; \ + double lmin = TMath::Log10(min); \ + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); \ + for (int i = 0; i < nbins; i++) { \ + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); \ + } \ + binp[nbins] = max + 1; \ + h->GetXaxis()->Set(nbins, binp); \ + } void init(o2::framework::InitContext&) { -#ifndef USE_REGISTRY - event->Add<vertexz>(new TH1F("hvertexz", ";Vtx_{z} (cm);Entries", 100, -20, 20)); - event->Add<signal>(new TH2F("htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", 100, 0, 5, 1000, 0, 2e6)); - event->Add<tofbeta>(new TH2F("htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", 100, 0, 5, 100, 0, 2)); - // - expected->Add<El>(new TH2F("hexpectedEl", ";#it{p} (GeV/#it{c});t_{exp e}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<Mu>(new TH2F("hexpectedMu", ";#it{p} (GeV/#it{c});t_{exp #mu}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<Pi>(new TH2F("hexpectedPi", ";#it{p} (GeV/#it{c});t_{exp #pi}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<Ka>(new TH2F("hexpectedKa", ";#it{p} (GeV/#it{c});t_{exp K}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<Pr>(new TH2F("hexpectedPr", ";#it{p} (GeV/#it{c});t_{exp p}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<De>(new TH2F("hexpectedDe", ";#it{p} (GeV/#it{c});t_{exp d}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<Tr>(new TH2F("hexpectedTr", ";#it{p} (GeV/#it{c});t_{exp t}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<He>(new TH2F("hexpectedHe", ";#it{p} (GeV/#it{c});t_{exp ^{3}He}", 100, 0, 5, 1000, 0, 2e6)); - expected->Add<Al>(new TH2F("hexpectedAl", ";#it{p} (GeV/#it{c});t_{exp #alpha}", 100, 0, 5, 1000, 0, 2e6)); - // - timediff->Add<El>(new TH2F("htimediffEl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp e})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<Mu>(new TH2F("htimediffMu", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #mu})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<Pi>(new TH2F("htimediffPi", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #pi})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<Ka>(new TH2F("htimediffKa", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp K})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<Pr>(new TH2F("htimediffPr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp p})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<De>(new TH2F("htimediffDe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp d})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<Tr>(new TH2F("htimediffTr", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp t})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<He>(new TH2F("htimediffHe", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp ^{3}He})", 100, 0, 5, 100, -1000, 1000)); - timediff->Add<Al>(new TH2F("htimediffAl", ";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp #alpha})", 100, 0, 5, 100, -1000, 1000)); - // - nsigma->Add<El>(new TH2F("nsigmaEl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(e)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Mu>(new TH2F("nsigmaMu", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#mu)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Pi>(new TH2F("nsigmaPi", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#pi)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Ka>(new TH2F("nsigmaKa", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(K)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Pr>(new TH2F("nsigmaPr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(p)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<De>(new TH2F("nsigmaDe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(d)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Tr>(new TH2F("nsigmaTr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(t)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<He>(new TH2F("nsigmaHe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(^{3}He)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Al>(new TH2F("nsigmaAl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(#alpha)", 1000, 0.001, 20, 200, -10, 10)); -#endif + // Event properties + histos.add("event/hvertexz", ";Vtx_{z} (cm);Entries", HistType::kTH1F, {{100, -20, 20}}); + histos.add("event/colltime", ";Collision time (ps);Entries", HistType::kTH1F, {{100, -2000, 2000}}); + histos.add("event/htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {10000, 0, 2e6}}); + makelogaxis(histos.get<TH2>("event/htofsignal")); + histos.add("event/htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2}}); + makelogaxis(histos.get<TH2>("event/htofbeta")); + for (int i = 0; i < Np; i++) { + // Exp signal + histos.add("expected/" + pN[i], Form(";#it{p} (GeV/#it{c});t_{exp}(%s)", pT[i].Data()), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2e6}}); + makelogaxis(histos.get<TH2>("expected/" + pN[i])); + // T-Texp + histos.add("timediff/" + pN[i], Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp}(%s))", pT[i].Data()), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {100, -1000, 1000}}); + makelogaxis(histos.get<TH2>("timediff/" + pN[i])); + // NSigma + histos.add("nsigma/" + pN[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(%s)", pT[i].Data()), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get<TH2>("nsigma/" + pN[i])); + } } +#undef makelogaxis void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) { -#ifdef USE_REGISTRY - event("vertexz")->Fill(collision.posZ()); -#else - event->Fill<vertexz>(collision.posZ()); -#endif + histos.fill("event/vertexz", collision.posZ()); + histos.fill("event/colltime", collision.collisionTime()); - for (auto i : tracks) { + for (auto t : tracks) { // - if (i.tofSignal() < 0) { // Skipping tracks without TOF + if (t.tofSignal() < 0) { // Skipping tracks without TOF continue; } - const float tof = i.tofSignal() - collision.collisionTime(); -#ifdef USE_REGISTRY - event("htofsignal")->Fill(i.p(), i.tofSignal()); - event("htofbeta")->Fill(i.p(), i.beta()); - // - expected("hexpectedEl")->Fill(i.p(), i.tofExpSignalEl()); - expected("hexpectedEl")->Fill(i.p(), i.tofExpSignalEl()); - expected("hexpectedMu")->Fill(i.p(), i.tofExpSignalMu()); - expected("hexpectedPi")->Fill(i.p(), i.tofExpSignalPi()); - expected("hexpectedKa")->Fill(i.p(), i.tofExpSignalKa()); - expected("hexpectedPr")->Fill(i.p(), i.tofExpSignalPr()); - expected("hexpectedDe")->Fill(i.p(), i.tofExpSignalDe()); - expected("hexpectedTr")->Fill(i.p(), i.tofExpSignalTr()); - expected("hexpectedHe")->Fill(i.p(), i.tofExpSignalHe()); - expected("hexpectedAl")->Fill(i.p(), i.tofExpSignalAl()); + const float tof = t.tofSignal() - collision.collisionTime(); // - timediff("htimediffEl")->Fill(i.p(), tof - i.tofExpSignalEl()); - timediff("htimediffMu")->Fill(i.p(), tof - i.tofExpSignalMu()); - timediff("htimediffPi")->Fill(i.p(), tof - i.tofExpSignalPi()); - timediff("htimediffKa")->Fill(i.p(), tof - i.tofExpSignalKa()); - timediff("htimediffPr")->Fill(i.p(), tof - i.tofExpSignalPr()); - timediff("htimediffDe")->Fill(i.p(), tof - i.tofExpSignalDe()); - timediff("htimediffTr")->Fill(i.p(), tof - i.tofExpSignalTr()); - timediff("htimediffHe")->Fill(i.p(), tof - i.tofExpSignalHe()); - timediff("htimediffAl")->Fill(i.p(), tof - i.tofExpSignalAl()); + histos.fill("event/htofsignal", t.p(), t.tofSignal()); + histos.fill("event/htofbeta", t.p(), t.beta()); // - nsigma("hnsigmaEl")->Fill(i.p(), i.tofNSigmaEl()); - nsigma("hnsigmaMu")->Fill(i.p(), i.tofNSigmaMu()); - nsigma("hnsigmaPi")->Fill(i.p(), i.tofNSigmaPi()); - nsigma("hnsigmaKa")->Fill(i.p(), i.tofNSigmaKa()); - nsigma("hnsigmaPr")->Fill(i.p(), i.tofNSigmaPr()); - nsigma("hnsigmaDe")->Fill(i.p(), i.tofNSigmaDe()); - nsigma("hnsigmaTr")->Fill(i.p(), i.tofNSigmaTr()); - nsigma("hnsigmaHe")->Fill(i.p(), i.tofNSigmaHe()); - nsigma("hnsigmaAl")->Fill(i.p(), i.tofNSigmaAl()); -#else - event->Fill<signal>(i.p(), i.tofSignal()); - event->Fill<tofbeta>(i.p(), i.beta()); - // - expected->Fill<El>(i.p(), i.tofExpSignalEl()); - expected->Fill<Mu>(i.p(), i.tofExpSignalMu()); - expected->Fill<Pi>(i.p(), i.tofExpSignalPi()); - expected->Fill<Ka>(i.p(), i.tofExpSignalKa()); - expected->Fill<Pr>(i.p(), i.tofExpSignalPr()); - expected->Fill<De>(i.p(), i.tofExpSignalDe()); - expected->Fill<Tr>(i.p(), i.tofExpSignalTr()); - expected->Fill<He>(i.p(), i.tofExpSignalHe()); - expected->Fill<Al>(i.p(), i.tofExpSignalAl()); - // - timediff->Fill<El>(i.p(), tof - i.tofExpSignalEl()); - timediff->Fill<Mu>(i.p(), tof - i.tofExpSignalMu()); - timediff->Fill<Pi>(i.p(), tof - i.tofExpSignalPi()); - timediff->Fill<Ka>(i.p(), tof - i.tofExpSignalKa()); - timediff->Fill<Pr>(i.p(), tof - i.tofExpSignalPr()); - timediff->Fill<De>(i.p(), tof - i.tofExpSignalDe()); - timediff->Fill<Tr>(i.p(), tof - i.tofExpSignalTr()); - timediff->Fill<He>(i.p(), tof - i.tofExpSignalHe()); - timediff->Fill<Al>(i.p(), tof - i.tofExpSignalAl()); + const float exp[Np] = {t.tofExpSignalEl(), t.tofExpSignalMu(), t.tofExpSignalPi(), + t.tofExpSignalKa(), t.tofExpSignalPr(), t.tofExpSignalDe(), + t.tofExpSignalTr(), t.tofExpSignalHe(), t.tofExpSignalAl()}; + for (int i = 0; i < Np; i++) { + histos.fill("expected/" + pN[i], t.p(), exp[i]); + histos.fill("timediff/" + pN[i], t.p(), tof - exp[i]); + } // - nsigma->Fill<El>(i.p(), i.tofNSigmaEl()); - nsigma->Fill<Mu>(i.p(), i.tofNSigmaMu()); - nsigma->Fill<Pi>(i.p(), i.tofNSigmaPi()); - nsigma->Fill<Ka>(i.p(), i.tofNSigmaKa()); - nsigma->Fill<Pr>(i.p(), i.tofNSigmaPr()); - nsigma->Fill<De>(i.p(), i.tofNSigmaDe()); - nsigma->Fill<Tr>(i.p(), i.tofNSigmaTr()); - nsigma->Fill<He>(i.p(), i.tofNSigmaHe()); - nsigma->Fill<Al>(i.p(), i.tofNSigmaAl()); -#endif + const float nsigma[Np] = {t.tofNSigmaEl(), t.tofNSigmaMu(), t.tofNSigmaPi(), + t.tofNSigmaKa(), t.tofNSigmaPr(), t.tofNSigmaDe(), + t.tofNSigmaTr(), t.tofNSigmaHe(), t.tofNSigmaAl()}; + for (int i = 0; i < Np; i++) { + histos.fill("nsigma/" + pN[i], t.p(), nsigma[i]); + } } } }; diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index 190b0e642e658..e068d99c7b9b8 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -12,10 +12,10 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" #include "ReconstructionDataFormats/Track.h" -#include "PID/PIDResponse.h" #include <CCDB/BasicCCDBManager.h> -#include "Analysis/HistHelpers.h" +#include "PID/PIDResponse.h" #include "PID/PIDTPC.h" using namespace o2; @@ -111,28 +111,16 @@ struct pidTPCTask { } }; +const int Np = 9; +const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; +const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; struct pidTPCTaskQA { - enum event_histo : uint8_t { vertexz, - signal }; - enum Particle : uint8_t { El, - Mu, - Pi, - Ka, - Pr, - De, - Tr, - He, - Al - }; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; + + Configurable<int> nBinsP{"nBinsP", 400, "Number of bins for the momentum"}; + Configurable<float> MinP{"MinP", 0, "Minimum momentum in range"}; + Configurable<float> MaxP{"MaxP", 20, "Maximum momentum in range"}; - // Event - OutputObj<experimental::histhelpers::HistFolder> event{experimental::histhelpers::HistFolder("event"), OutputObjHandlingPolicy::QAObject}; - // Exp signal - OutputObj<experimental::histhelpers::HistFolder> expected{experimental::histhelpers::HistFolder("expected"), OutputObjHandlingPolicy::QAObject}; - // Exp signal difference - OutputObj<experimental::histhelpers::HistFolder> expected_diff{experimental::histhelpers::HistFolder("expected_diff"), OutputObjHandlingPolicy::QAObject}; - // NSigma - OutputObj<experimental::histhelpers::HistFolder> nsigma{experimental::histhelpers::HistFolder("nsigma"), OutputObjHandlingPolicy::QAObject}; void init(o2::framework::InitContext&) { @@ -142,6 +130,8 @@ struct pidTPCTaskQA { double binp[nbins + 1]; \ double max = h->GetXaxis()->GetBinUpEdge(nbins); \ double min = h->GetXaxis()->GetBinLowEdge(1); \ + if (min <= 0) \ + min = 0.00001; \ double lmin = TMath::Log10(min); \ double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); \ for (int i = 0; i < nbins; i++) { \ @@ -151,105 +141,46 @@ struct pidTPCTaskQA { h->GetXaxis()->Set(nbins, binp); \ } - event->Add<vertexz>(new TH1F("hvertexz", ";Vtx_{z} (cm);Entries", 100, -20, 20)); - event->Add<signal>(new TH2F("htpcsignal", ";#it{p} (GeV/#it{c});TPC Signal", 1000, 0.001, 20, 1000, 0, 1000)); - makelogaxis(event->Get<TH2>(signal)); - // - expected->Add<El>(new TH2F("hexpectedEl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{e}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<Mu>(new TH2F("hexpectedMu", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{#mu}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<Pi>(new TH2F("hexpectedPi", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{#pi}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<Ka>(new TH2F("hexpectedKa", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{K}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<Pr>(new TH2F("hexpectedPr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{p}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<De>(new TH2F("hexpectedDe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{d}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<Tr>(new TH2F("hexpectedTr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{t}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<He>(new TH2F("hexpectedHe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{^{3}He}", 1000, 0.001, 20, 1000, 0, 1000)); - expected->Add<Al>(new TH2F("hexpectedAl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{#alpha}", 1000, 0.001, 20, 1000, 0, 1000)); - makelogaxis(expected->Get<TH2>(El)); - makelogaxis(expected->Get<TH2>(Mu)); - makelogaxis(expected->Get<TH2>(Pi)); - makelogaxis(expected->Get<TH2>(Ka)); - makelogaxis(expected->Get<TH2>(Pr)); - makelogaxis(expected->Get<TH2>(De)); - makelogaxis(expected->Get<TH2>(Tr)); - makelogaxis(expected->Get<TH2>(He)); - makelogaxis(expected->Get<TH2>(Al)); - // - expected_diff->Add<El>(new TH2F("hexpdiffEl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{e}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<Mu>(new TH2F("hexpdiffMu", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{#mu}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<Pi>(new TH2F("hexpdiffPi", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{#pi}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<Ka>(new TH2F("hexpdiffKa", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{K}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<Pr>(new TH2F("hexpdiffPr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{p}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<De>(new TH2F("hexpdiffDe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{d}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<Tr>(new TH2F("hexpdiffTr", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{t}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<He>(new TH2F("hexpdiffHe", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{^{3}He}", 1000, 0.001, 20, 1000, -500, 500)); - expected_diff->Add<Al>(new TH2F("hexpdiffAl", ";#it{p} (GeV/#it{c});d#it{E}/d#it{x} - d#it{E}/d#it{x}_{#alpha}", 1000, 0.001, 20, 1000, -500, 500)); - makelogaxis(expected_diff->Get<TH2>(El)); - makelogaxis(expected_diff->Get<TH2>(Mu)); - makelogaxis(expected_diff->Get<TH2>(Pi)); - makelogaxis(expected_diff->Get<TH2>(Ka)); - makelogaxis(expected_diff->Get<TH2>(Pr)); - makelogaxis(expected_diff->Get<TH2>(De)); - makelogaxis(expected_diff->Get<TH2>(Tr)); - makelogaxis(expected_diff->Get<TH2>(He)); - makelogaxis(expected_diff->Get<TH2>(Al)); - // - nsigma->Add<El>(new TH2F("hnsigmaEl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(e)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Mu>(new TH2F("hnsigmaMu", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(#mu)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Pi>(new TH2F("hnsigmaPi", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(#pi)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Ka>(new TH2F("hnsigmaKa", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(K)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Pr>(new TH2F("hnsigmaPr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(p)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<De>(new TH2F("hnsigmaDe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(d)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Tr>(new TH2F("hnsigmaTr", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(t)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<He>(new TH2F("hnsigmaHe", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(^{3}He)", 1000, 0.001, 20, 200, -10, 10)); - nsigma->Add<Al>(new TH2F("hnsigmaAl", ";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(#alpha)", 1000, 0.001, 20, 200, -10, 10)); - makelogaxis(nsigma->Get<TH2>(El)); - makelogaxis(nsigma->Get<TH2>(Mu)); - makelogaxis(nsigma->Get<TH2>(Pi)); - makelogaxis(nsigma->Get<TH2>(Ka)); - makelogaxis(nsigma->Get<TH2>(Pr)); - makelogaxis(nsigma->Get<TH2>(De)); - makelogaxis(nsigma->Get<TH2>(Tr)); - makelogaxis(nsigma->Get<TH2>(He)); - makelogaxis(nsigma->Get<TH2>(Al)); + // Event properties + histos.add("event/hvertexz", ";Vtx_{z} (cm);Entries", kTH1F, {{100, -20, 20}}); + histos.add("event/htpcsignal", ";#it{p} (GeV/#it{c});TPC Signal", kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); + makelogaxis(histos.get<TH2>("event/htpcsignal")); + for (int i = 0; i < Np; i++) { + // Exp signal + histos.add("expected/" + pN[i], Form(";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_(%s)", pT[i].Data()), kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); + makelogaxis(histos.get<TH2>("expected/" + pN[i])); + // Signal - Expected signal + histos.add("expected_diff/" + pN[i], Form(";#it{p} (GeV/#it{c});;d#it{E}/d#it{x} - d#it{E}/d#it{x}(%s)", pT[i].Data()), kTH2F, {{nBinsP, MinP, MaxP}, {1000, -500, 500}}); + makelogaxis(histos.get<TH2>("expected_diff/" + pN[i])); + // NSigma + histos.add("nsigma/" + pN[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(%s)", pT[i].Data()), kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get<TH2>("nsigma/" + pN[i])); + } #undef makelogaxis } void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) { - event->Fill<vertexz>(collision.posZ()); - for (auto i : tracks) { - // const float mom = i.p(); - const float mom = i.tpcInnerParam(); - event->Fill<signal>(mom, i.tpcSignal()); - // - expected->Fill<El>(mom, i.tpcExpSignalEl()); - expected->Fill<Mu>(mom, i.tpcExpSignalMu()); - expected->Fill<Pi>(mom, i.tpcExpSignalPi()); - expected->Fill<Ka>(mom, i.tpcExpSignalKa()); - expected->Fill<Pr>(mom, i.tpcExpSignalPr()); - expected->Fill<De>(mom, i.tpcExpSignalDe()); - expected->Fill<Tr>(mom, i.tpcExpSignalTr()); - expected->Fill<He>(mom, i.tpcExpSignalHe()); - expected->Fill<Al>(mom, i.tpcExpSignalAl()); + histos.fill("event/vertexz", collision.posZ()); + + for (auto t : tracks) { + // const float mom = t.p(); + const float mom = t.tpcInnerParam(); + histos.fill("event/htpcsignal", mom, t.tpcSignal()); // - expected_diff->Fill<El>(mom, i.tpcSignal() - i.tpcExpSignalEl()); - expected_diff->Fill<Mu>(mom, i.tpcSignal() - i.tpcExpSignalMu()); - expected_diff->Fill<Pi>(mom, i.tpcSignal() - i.tpcExpSignalPi()); - expected_diff->Fill<Ka>(mom, i.tpcSignal() - i.tpcExpSignalKa()); - expected_diff->Fill<Pr>(mom, i.tpcSignal() - i.tpcExpSignalPr()); - expected_diff->Fill<De>(mom, i.tpcSignal() - i.tpcExpSignalDe()); - expected_diff->Fill<Tr>(mom, i.tpcSignal() - i.tpcExpSignalTr()); - expected_diff->Fill<He>(mom, i.tpcSignal() - i.tpcExpSignalHe()); - expected_diff->Fill<Al>(mom, i.tpcSignal() - i.tpcExpSignalAl()); + const float exp[Np] = {t.tpcExpSignalEl(), t.tpcExpSignalMu(), t.tpcExpSignalPi(), + t.tpcExpSignalKa(), t.tpcExpSignalPr(), t.tpcExpSignalDe(), + t.tpcExpSignalTr(), t.tpcExpSignalHe(), t.tpcExpSignalAl()}; + for (int i = 0; i < Np; i++) { + histos.fill("expected/" + pN[i], mom, exp[i]); + histos.fill("expected_diff/" + pN[i], mom, t.tpcSignal() - exp[i]); + } // - nsigma->Fill<El>(mom, i.tpcNSigmaEl()); - nsigma->Fill<Mu>(mom, i.tpcNSigmaMu()); - nsigma->Fill<Pi>(mom, i.tpcNSigmaPi()); - nsigma->Fill<Ka>(mom, i.tpcNSigmaKa()); - nsigma->Fill<Pr>(mom, i.tpcNSigmaPr()); - nsigma->Fill<De>(mom, i.tpcNSigmaDe()); - nsigma->Fill<Tr>(mom, i.tpcNSigmaTr()); - nsigma->Fill<He>(mom, i.tpcNSigmaHe()); - nsigma->Fill<Al>(mom, i.tpcNSigmaAl()); + const float nsigma[Np] = {t.tpcNSigmaEl(), t.tpcNSigmaMu(), t.tpcNSigmaPi(), + t.tpcNSigmaKa(), t.tpcNSigmaPr(), t.tpcNSigmaDe(), + t.tpcNSigmaTr(), t.tpcNSigmaHe(), t.tpcNSigmaAl()}; + for (int i = 0; i < Np; i++) { + histos.fill("nsigma/" + pN[i], t.p(), nsigma[i]); + } } } }; From 4a12ca0c8ed215c81f1932bad24a07b9d592e2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Fri, 30 Oct 2020 08:51:36 +0100 Subject: [PATCH 1161/1751] PWGHF: Add candidate and track counter histograms. Subscribe to PID tables only when needed. (#4723) --- .../include/Analysis/HFSecondaryVertex.h | 3 ++- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 6 ++--- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 2e83aaaa78a35..4e4437a8daa85 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -37,8 +37,9 @@ DECLARE_SOA_TABLE(HFSelTrack, "AOD", "HFSELTRACK", hf_seltrack::DCAPrim0, hf_seltrack::DCAPrim1); -using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, HFSelTrack, pidRespTPC, pidRespTOF>; +using BigTracks = soa::Join<Tracks, TracksCov, TracksExtra, HFSelTrack>; using BigTracksMC = soa::Join<BigTracks, McTrackLabels>; +using BigTracksPID = soa::Join<BigTracks, pidRespTPC, pidRespTOF>; // FIXME: this is a workaround until we get the index columns to work with joins. diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index ab9826ef6bf4b..6d50a5f9d73bf 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -316,7 +316,7 @@ struct HFD0CandidateSelector { } } - void process(aod::HfCandProng2 const& hfCandProng2s, aod::BigTracks const& tracks) + void process(aod::HfCandProng2 const& hfCandProng2s, aod::BigTracksPID const& tracks) { int statusD0, statusD0bar; // final selection flag : 0-rejected 1-accepted bool topolD0, topolD0bar; @@ -324,8 +324,8 @@ struct HFD0CandidateSelector { for (auto& hfCandProng2 : hfCandProng2s) { //looping over 2 prong candidates - auto trackPos = hfCandProng2.index0(); //positive daughter - auto trackNeg = hfCandProng2.index1(); //negative daughter + auto trackPos = hfCandProng2.index0_as<aod::BigTracksPID>(); //positive daughter + auto trackNeg = hfCandProng2.index1_as<aod::BigTracksPID>(); //negative daughter statusD0 = 0; statusD0bar = 0; diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 7e4ce0b9eafbe..f203f9c6e9d17 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -169,6 +169,15 @@ struct HFTrackIndexSkimsCreator { OutputObj<TH1F> hvtx3_z{TH1F("hvtx3_z", "3-prong candidates;#it{z}_{sec. vtx.} (cm);entries", 1000, -20., 20.)}; OutputObj<TH1F> hmass3{TH1F("hmass3", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 2.1)}; + /* + // Counter histograms + OutputObj<TH2F> hNCand2ProngVsNTracks{TH2F("hNCand2ProngVsNTracks", "2-prong candidates;# of tracks;# of candidates;entries", 1000, 0., 1000., 1000, 0., 10000.)}; + OutputObj<TH2F> hNCand3ProngVsNTracks{TH2F("hNCand3ProngVsNTracks", "3-prong candidates;# of tracks;# of candidates;entries", 1000, 0., 1000., 1000, 0., 10000.)}; + OutputObj<TH1F> hNCand2Prong{TH1F("hNCand2Prong", "2-prong candidates;# of candidates;entries", 1000, 0., 10000.)}; + OutputObj<TH1F> hNCand3Prong{TH1F("hNCand3Prong", "3-prong candidates;# of candidates;entries", 1000, 0., 10000.)}; + OutputObj<TH1F> hNTracks{TH1F("hNTracks", ";# of tracks;entries", 1000, 0., 1000.)}; + */ + Filter filterSelectTracks = (aod::hf_seltrack::isSel2Prong == 1); using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::HFSelTrack>>; // FIXME @@ -214,6 +223,9 @@ struct HFTrackIndexSkimsCreator { df3.setMinRelChi2Change(d_minrelchi2change); df3.setUseAbsDCA(true); + //auto nCand2 = rowTrackIndexProng2.lastIndex(); + //auto nCand3 = rowTrackIndexProng3.lastIndex(); + // first loop over positive tracks //for (auto trackPos1 = tracksPos.begin(); trackPos1 != tracksPos.end(); ++trackPos1) { for (auto trackPos1 = tracks.begin(); trackPos1 != tracks.end(); ++trackPos1) { @@ -471,6 +483,16 @@ struct HFTrackIndexSkimsCreator { } } } + /* + auto nTracks = tracks.size(); // number of tracks in this collision + nCand2 = rowTrackIndexProng2.lastIndex() - nCand2; // number of 2-prong candidates in this collision + nCand3 = rowTrackIndexProng3.lastIndex() - nCand3; // number of 3-prong candidates in this collision + hNTracks->Fill(nTracks); + hNCand2Prong->Fill(nCand2); + hNCand3Prong->Fill(nCand3); + hNCand2ProngVsNTracks->Fill(nTracks, nCand2); + hNCand3ProngVsNTracks->Fill(nTracks, nCand3); + */ } }; From 9a3e245e1e56ea1f93f85e517c177ecb1efaad69 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Thu, 29 Oct 2020 20:05:20 +0300 Subject: [PATCH 1162/1751] Detectors/ITSMFT: make readability-braces-around-statements happy --- .../src/TestDataReader.cxx | 36 +++-- .../ITS/base/include/ITSBase/GeometryTGeo.h | 3 +- .../ITSMFT/ITS/base/src/GeometryTGeo.cxx | 3 +- .../ITS/reconstruction/src/CookedTracker.cxx | 78 ++++++---- .../ITSMFT/ITS/simulation/src/Detector.cxx | 9 +- .../ITSMFT/ITS/simulation/src/V3Layer.cxx | 115 +++++++++----- .../ITSMFT/ITS/simulation/src/V3Services.cxx | 54 ++++--- .../include/ITStracking/ClusterLines.h | 12 +- .../include/ITStracking/Configuration.h | 9 +- .../ITS/tracking/include/ITStracking/json.h | 3 +- .../ITSMFT/ITS/tracking/src/ClusterLines.cxx | 24 ++- Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx | 3 +- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 24 ++- .../ITS/tracking/src/VertexerTraits.cxx | 12 +- .../MFT/base/include/MFTBase/GeometryTGeo.h | 3 +- .../base/include/MFTBase/HalfSegmentation.h | 5 +- .../ITSMFT/MFT/base/include/MFTBase/Support.h | 5 +- Detectors/ITSMFT/MFT/base/src/Geometry.cxx | 12 +- .../ITSMFT/MFT/base/src/GeometryTGeo.cxx | 6 +- Detectors/ITSMFT/MFT/base/src/HalfCone.cxx | 6 +- Detectors/ITSMFT/MFT/base/src/HalfDisk.cxx | 3 +- .../MFT/base/src/HalfDiskSegmentation.cxx | 11 +- .../ITSMFT/MFT/base/src/HalfSegmentation.cxx | 9 +- .../ITSMFT/MFT/base/src/HeatExchanger.cxx | 143 +++++++++++------- .../MFT/base/src/LadderSegmentation.cxx | 11 +- Detectors/ITSMFT/MFT/base/src/PCBSupport.cxx | 13 +- .../ITSMFT/MFT/base/src/PowerSupplyUnit.cxx | 15 +- .../ITSMFT/MFT/base/src/Segmentation.cxx | 9 +- .../ITSMFT/MFT/base/src/VSegmentation.cxx | 3 +- .../include/MFTSimulation/Detector.h | 5 +- .../ITSMFT/MFT/simulation/src/Detector.cxx | 15 +- .../ITSMFT/MFT/simulation/src/digi2raw.cxx | 3 +- .../tracking/include/MFTTracking/TrackCA.h | 3 +- .../tracking/include/MFTTracking/Tracker.h | 6 +- Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx | 9 +- .../ITSMFT/MFT/tracking/src/TrackFitter.cxx | 32 ++-- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 12 +- .../MFT/workflow/src/ClusterReaderSpec.cxx | 3 +- .../MFT/workflow/src/DigitReaderSpec.cxx | 3 +- .../include/ITSMFTBase/SegmentationAlpide.h | 15 +- .../ITSMFTReconstruction/ChipMappingITS.h | 3 +- .../ITSMFTReconstruction/ChipMappingMFT.h | 3 +- .../ITSMFTReconstruction/RawPixelReader.h | 6 +- .../src/BuildTopologyDictionary.cxx | 17 ++- .../common/reconstruction/src/Clusterer.cxx | 9 +- .../reconstruction/src/DigitPixelReader.cxx | 3 +- .../common/reconstruction/src/LookUp.cxx | 8 +- .../include/ITSMFTSimulation/ClusterShape.h | 20 ++- .../common/simulation/src/AlpideChip.cxx | 5 +- .../simulation/src/AlpideSimResponse.cxx | 30 ++-- .../common/simulation/src/ClusterShape.cxx | 15 +- .../common/simulation/src/Digitizer.cxx | 6 +- .../test/HitAnalysis/src/HitAnalysis.cxx | 3 +- 53 files changed, 568 insertions(+), 305 deletions(-) diff --git a/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx b/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx index 49ebbd7b020e3..1d665b89db39e 100644 --- a/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx +++ b/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx @@ -213,8 +213,9 @@ void TestDataReader::run(ProcessingContext& pc) int pos = mNowFolderNames[i].find_last_of("/"); - if (pos != string::npos) + if (pos != string::npos) { mRunID = mNowFolderNames[i].substr(pos + 1); + } LOG(DEBUG) << "FileDone = " << mFileDone << endl; @@ -234,8 +235,9 @@ void TestDataReader::run(ProcessingContext& pc) //Getting the FileID string FileIDS; pos = mDiffFileNames[i][0].find_last_of("/"); - if (pos != string::npos) + if (pos != string::npos) { FileIDS = mDiffFileNames[i][0].substr(pos + 1); + } cout << "Before FileIDS = " << FileIDS << endl; @@ -274,8 +276,9 @@ void TestDataReader::run(ProcessingContext& pc) mErrorsVecTest.clear(); mDigitsTest.clear(); mMultiDigitsTest.clear(); - if (mFolderNames.size() < mNowFolderNames.size()) + if (mFolderNames.size() < mNowFolderNames.size()) { mFileNames.push_back(NewNextFold); + } cout << "Done!!! You should see the Canvas Updated " << endl; break; } @@ -298,8 +301,9 @@ void TestDataReader::run(ProcessingContext& pc) auto& rawErrorReader = reinterpret_cast<RawReader&>(mRawReader); while ((mChipData = mRawReader.getNextChipData(mChips))) { - if (NChip < NChipMax) + if (NChip < NChipMax) { break; + } // cout << "Pass Chip" << endl; const auto* ruInfo = rawErrorReader.getCurrRUDecodeData()->ruInfo; @@ -342,12 +346,14 @@ void TestDataReader::run(ProcessingContext& pc) TimePrint = 1; } - if (NEvent % 100000 != 0) + if (NEvent % 100000 != 0) { TimePrint = 0; + } for (int i = 0; i < o2::itsmft::GBTLinkDecodingStat::NErrorsDefined; i++) { - if (mErrors[i] < 4294967295) + if (mErrors[i] < 4294967295) { mErrors[i] = mErrors[i] + (int)statRU->errorCounts[i]; + } } if (mTrackError == 1) { @@ -355,8 +361,9 @@ void TestDataReader::run(ProcessingContext& pc) ErrorDetcted = 0; for (int i = 0; i < o2::itsmft::GBTLinkDecodingStat::NErrorsDefined; i++) { - if ((int)statRU->errorCounts[i] > 0) + if ((int)statRU->errorCounts[i] > 0) { ErrorDetcted = 1; + } } if (ErrorDetcted == 1) { @@ -375,8 +382,9 @@ void TestDataReader::run(ProcessingContext& pc) int ChipID = mChipData->getChipID(); for (auto& pixel : pixels) { - if (Index < IndexMax) + if (Index < IndexMax) { break; + } int col = pixel.getCol(); int row = pixel.getRow(); mDigits.emplace_back(ChipID, row, col, 0); @@ -390,8 +398,9 @@ void TestDataReader::run(ProcessingContext& pc) mNDigits.push_back(mTotalPixelSize); mErrorsVec.push_back(mErrors); LOG(DEBUG) << "Run " << mNowFolderNames[i] << " File " << mInputName << " Integrated Raw Pixel Pushed " << mDigits.size(); - if (mFolderNames.size() < mNowFolderNames.size()) + if (mFolderNames.size() < mNowFolderNames.size()) { mFileNames.push_back(NewNextFold); + } mFileNames[i].push_back(mInputName); fout << " END OF ERROR REPORT " << endl; } @@ -401,8 +410,9 @@ void TestDataReader::run(ProcessingContext& pc) LOG(DEBUG) << "mIndexPush Before = " << mIndexPush << " mDigits.size() = " << mDigits.size(); - if (mDigits.size() > 0) + if (mDigits.size() > 0) { PercentDone = double(mIndexPush) / double(mDigits.size()); + } cout << "Percentage Processed = " << Form("%.2f", 100. * PercentDone) << endl; if (mIndexPush < mDigits.size()) { @@ -421,8 +431,9 @@ void TestDataReader::run(ProcessingContext& pc) pc.outputs().snapshot(Output{"ITS", "Error", 0, Lifetime::Timeframe}, mErrorsVec[j]); mIndexPushEx = mIndexPush + mNDigits[j]; LOG(DEBUG) << "IndexPushEx = " << mIndexPushEx << " mDigits.size() " << mDigits.size(); - if (mIndexPushEx > mDigits.size() - 5) + if (mIndexPushEx > mDigits.size() - 5) { mFileDone = 1; + } LOG(DEBUG) << "FileDone = " << mFileDone; LOG(DEBUG) << "FileRemain = " << mFileRemain; @@ -514,8 +525,9 @@ std::vector<string> TestDataReader::GetFName(std::string folder) //printf("%s\n", directory->d_name); - if (!(!strcmp(directory->d_name, ".") || !strcmp(directory->d_name, ".."))) + if (!(!strcmp(directory->d_name, ".") || !strcmp(directory->d_name, ".."))) { names.push_back(folder + "/" + directory->d_name); + } } closedir(dirp); diff --git a/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h b/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h index 4c54aaf3e5a21..02b46cb982050 100644 --- a/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h +++ b/Detectors/ITSMFT/ITS/base/include/ITSBase/GeometryTGeo.h @@ -53,8 +53,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo static GeometryTGeo* Instance() { // get (create if needed) a unique instance of the object - if (!sInstance) + if (!sInstance) { sInstance = std::unique_ptr<GeometryTGeo>(new GeometryTGeo(true, 0)); + } return sInstance.get(); } diff --git a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx index 528e9a65a1a5c..eeb3917886377 100644 --- a/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/ITS/base/src/GeometryTGeo.cxx @@ -679,8 +679,9 @@ int GeometryTGeo::extractLayerChipType(int lay) const void GeometryTGeo::Print(Option_t*) const { printf("NLayers:%d NChips:%d\n", mNumberOfLayers, getNumberOfChips()); - if (!isBuilt()) + if (!isBuilt()) { return; + } for (int i = 0; i < mNumberOfLayers; i++) { printf( diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx index dc7c65bb9a260..b70282cd5416c 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx @@ -84,8 +84,9 @@ CookedTracker::CookedTracker(Int_t n) : mNumOfThreads(n), mBz(0.) //-------------------------------------------------------------------- const Double_t klRadius[7] = {2.34, 3.15, 3.93, 19.61, 24.55, 34.39, 39.34}; // tdr6 - for (Int_t i = 0; i < kNLayers; i++) + for (Int_t i = 0; i < kNLayers; i++) { sLayers[i].setR(klRadius[i]); + } } //__________________________________________________________________________ @@ -104,8 +105,9 @@ Label CookedTracker::cookLabel(TrackITSExt& t, Float_t wrong) const auto labels = mClsLabels->getLabels(idx); for (auto lab : labels) { // check all labels of the cluster - if (lab.isEmpty()) + if (lab.isEmpty()) { break; // all following labels will be empty also + } // was this label already accounted for ? labelOccurence[lab]++; } @@ -113,8 +115,9 @@ Label CookedTracker::cookLabel(TrackITSExt& t, Float_t wrong) const Label lab; Int_t maxL = 0; // find most encountered label for (auto [label, count] : labelOccurence) { - if (count <= maxL) + if (count <= maxL) { continue; + } maxL = count; lab = label; } @@ -146,8 +149,9 @@ static Double_t f1(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Double_t Double_t xr = TMath::Abs(d / (d * x1 - a)), yr = TMath::Abs(d / (d * y1 - b)); Double_t crv = xr * yr / sqrt(xr * xr + yr * yr); - if (d > 0) + if (d > 0) { crv = -crv; + } return crv; } @@ -307,8 +311,9 @@ void CookedTracker::makeSeeds(std::vector<TrackITSExt>& seeds, Int_t first, Int_ auto r3 = xyz3.rho(); zr3 = z1 + (r3 - r1) / (r2 - r1) * (z2 - z1); - if (std::abs(z3 - zr3) > 0.2 * dz3) + if (std::abs(z3 - zr3) > 0.2 * dz3) { continue; + } const Point3Df& txyz2 = c2->getXYZ(); // tracking coordinates @@ -316,16 +321,19 @@ void CookedTracker::makeSeeds(std::vector<TrackITSExt>& seeds, Int_t first, Int_ float ip[2]; seed.getImpactParams(getX(), getY(), getZ(), getBz(), ip); - if (TMath::Abs(ip[0]) > kmaxDCAxy) + if (TMath::Abs(ip[0]) > kmaxDCAxy) { continue; - if (TMath::Abs(ip[1]) > kmaxDCAz) + } + if (TMath::Abs(ip[1]) > kmaxDCAz) { continue; + } { Double_t xx0 = 0.008; // Rough layer thickness Double_t radl = 9.36; // Radiation length of Si [cm] Double_t rho = 2.33; // Density of Si [g/cm^3] - if (!seed.correctForMaterial(xx0, xx0 * radl * rho, kTRUE)) + if (!seed.correctForMaterial(xx0, xx0 * radl * rho, kTRUE)) { continue; + } } seed.setClusterIndex(kSeedingLayer1, n1); seed.setClusterIndex(kSeedingLayer3, n3); @@ -393,31 +401,39 @@ void CookedTracker::trackSeeds(std::vector<TrackITSExt>& seeds) Int_t ci = -1; TrackITSExt t3(track); for (auto& ci3 : selec[3]) { - if (used[3][ci3]) + if (used[3][ci3]) { continue; - if (!attachCluster(volID, 3, ci3, t3, track)) + } + if (!attachCluster(volID, 3, ci3, t3, track)) { continue; + } TrackITSExt t2(t3); for (auto& ci2 : selec[2]) { - if (used[2][ci2]) + if (used[2][ci2]) { continue; - if (!attachCluster(volID, 2, ci2, t2, t3)) + } + if (!attachCluster(volID, 2, ci2, t2, t3)) { continue; + } TrackITSExt t1(t2); for (auto& ci1 : selec[1]) { - if (used[1][ci1]) + if (used[1][ci1]) { continue; - if (!attachCluster(volID, 1, ci1, t1, t2)) + } + if (!attachCluster(volID, 1, ci1, t1, t2)) { continue; + } TrackITSExt t0(t1); for (auto& ci0 : selec[0]) { - if (used[0][ci0]) + if (used[0][ci0]) { continue; - if (!attachCluster(volID, 0, ci0, t0, t1)) + } + if (!attachCluster(volID, 0, ci0, t0, t1)) { continue; + } if (t0.isBetter(best, kmaxChi2PerTrack)) { best = t0; } @@ -559,8 +575,9 @@ std::tuple<int, int> CookedTracker::processLoadedClusters(TrackInserter& inserte seedArray[t] = futures[t].get(); nSeeds += seedArray[t].size(); for (auto& track : seedArray[t]) { - if (track.getNumberOfClusters() < kminNumberOfClusters) + if (track.getNumberOfClusters() < kminNumberOfClusters) { continue; + } nAllTracks = inserter(track); nTracks++; if (mTrkLabels) { @@ -631,8 +648,9 @@ int CookedTracker::loadClusters() // sort them, distribute over the internal tracker arrays, etc //-------------------------------------------------------------------- - if (mClusterCache.empty()) + if (mClusterCache.empty()) { return 0; + } for (const auto& c : mClusterCache) { Int_t layer = mGeom->getLayer(c.getSensorID()); @@ -642,13 +660,15 @@ int CookedTracker::loadClusters() std::vector<std::future<void>> fut; for (Int_t l = 0; l < kNLayers; l += mNumOfThreads) { for (Int_t t = 0; t < mNumOfThreads; t++) { - if (l + t >= kNLayers) + if (l + t >= kNLayers) { break; + } auto f = std::async(std::launch::async, &CookedTracker::Layer::init, sLayers + (l + t)); fut.push_back(std::move(f)); } - for (Int_t t = 0; t < fut.size(); t++) + for (Int_t t = 0; t < fut.size(); t++) { fut[t].wait(); + } } return mClusterCache.size(); @@ -660,8 +680,9 @@ void CookedTracker::unloadClusters() // This function unloads ITSU clusters from the RAM //-------------------------------------------------------------------- mClusterCache.clear(); - for (Int_t i = 0; i < kNLayers; i++) + for (Int_t i = 0; i < kNLayers; i++) { sLayers[i].unloadClusters(); + } } const Cluster* CookedTracker::getCluster(Int_t index) const @@ -705,8 +726,9 @@ void CookedTracker::Layer::init() mSectors[s < kNSectors ? s : kNSectors - 1].emplace_back(i, c->getZ()); } - if (m) + if (m) { mR = r / m; + } } void CookedTracker::Layer::unloadClusters() @@ -717,8 +739,9 @@ void CookedTracker::Layer::unloadClusters() mClusters.clear(); mAlphaRef.clear(); mPhi.clear(); - for (Int_t s = 0; s < kNSectors; s++) + for (Int_t s = 0; s < kNSectors; s++) { mSectors[s].clear(); + } } Bool_t CookedTracker::Layer::insertCluster(const Cluster* c) @@ -770,8 +793,9 @@ void CookedTracker::Layer::selectClusters(std::vector<Int_t>& selec, Float_t phi if (cdphi > kPI) { cdphi = k2PI - cdphi; } - if (cdphi > dphi) + if (cdphi > dphi) { continue; // check in Phi + } } selec.push_back(i); } @@ -792,8 +816,9 @@ Bool_t CookedTracker::attachCluster(Int_t& volID, Int_t nl, Int_t ci, TrackITSEx volID = vid; t = o; Double_t alpha = layer.getAlphaRef(ci); - if (!t.propagate(alpha, c->getX(), getBz())) + if (!t.propagate(alpha, c->getX(), getBz())) { return kFALSE; + } } Double_t chi2 = t.getPredictedChi2(*c); @@ -818,6 +843,7 @@ void CookedTracker::setGeometry(o2::its::GeometryTGeo* geom) { /// attach geometry interface mGeom = geom; - for (Int_t i = 0; i < kNLayers; i++) + for (Int_t i = 0; i < kNLayers; i++) { sLayers[i].setGeometry(geom); + } } diff --git a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx index 621bda9c95823..4fb226daa8a6e 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx @@ -282,8 +282,9 @@ Bool_t Detector::ProcessHits(FairVolume* vol) while ((lay < sNumberLayers) && (notSens = (volID != mLayerID[lay]))) { ++lay; } - if (notSens) + if (notSens) { return kFALSE; // RS: can this happen? This method must be called for sensors only? + } // Is it needed to keep a track reference when the outer ITS volume is encountered? auto stack = (o2::data::Stack*)fMC->GetStack(); @@ -323,10 +324,12 @@ Bool_t Detector::ProcessHits(FairVolume* vol) } // increment energy loss at all steps except entrance - if (!startHit) + if (!startHit) { mTrackData.mEnergyLoss += fMC->Edep(); - if (!(startHit | stopHit)) + } + if (!(startHit | stopHit)) { return kFALSE; // do noting + } if (startHit) { mTrackData.mEnergyLoss = 0.; diff --git a/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx b/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx index a4599f208d01e..48c4b63d42370 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx @@ -477,8 +477,9 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) mechStaveVol = createStaveStructInnerB(); if (mechStaveVol) { ypos = (static_cast<TGeoBBox*>(modVol->GetShape()))->GetDY() - ypos; - if (mStaveModel != Detector::kIBModel4) + if (mStaveModel != Detector::kIBModel4) { ypos += (static_cast<TGeoBBox*>(mechStaveVol->GetShape()))->GetDY(); + } staveVol->AddNode(mechStaveVol, 1, new TGeoCombiTrans(0, -ypos, 0, new TGeoRotation("", 0, 0, 180))); } } else { @@ -496,9 +497,10 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) mechStaveVol = createSpaceFrameOuterB(); if (mechStaveVol) { - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon staveVol->AddNode(mechStaveVol, 1, new TGeoCombiTrans(0, -sOBSFrameULegHeight1, 0, new TGeoRotation("", 180, 0, 0))); + } } } } @@ -547,10 +549,11 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) char chipName[nameLen], sensName[nameLen], volumeName[nameLen]; // For material budget studies - if (mBuildLevel < 6) + if (mBuildLevel < 6) { dummyChip = kFALSE; // will be made of Si - else + } else { dummyChip = kTRUE; // will be made of Air + } // First create the single chip snprintf(chipName, nameLen, "%s%d", GeometryTGeo::getITSChipPattern(), mLayerNumber); @@ -581,8 +584,9 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) Double_t yano = (static_cast<TGeoBBox*>(aluAnodeCableVol->GetShape()))->GetDY(); ytot = ymod; - if (mStaveModel == Detector::kIBModel4) + if (mStaveModel == Detector::kIBModel4) { ytot += (sIBGlueThick / 2 + ygnd + sIBFlexCableKapThick / 2 + yano + sIBFlexCapacitorYHi / 2); + } TGeoBBox* module = new TGeoBBox(xtot, ytot, ztot); @@ -615,8 +619,9 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) if (mStaveModel == Detector::kIBModel4) { ypos += (ymod + glue->GetDY()); - if (mBuildLevel < 2) // Glue + if (mBuildLevel < 2) { // Glue modVol->AddNode(glueVol, 1, new TGeoTranslation(xpos, ypos, 0)); + } ypos += glue->GetDY(); if (mBuildLevel < 4) { // Kapton @@ -738,20 +743,22 @@ void V3Layer::createIBCapacitors(TGeoVolume* modvol, Double_t zchip, Double_t yz nCapacitors++; for (Int_t j = 0; j < sIBChipsPerRow; j++) { - if (j == (sIBChipsPerRow - 1)) + if (j == (sIBChipsPerRow - 1)) { xpos = xGroup4[1]; - else + } else { xpos = xGroup4[0]; + } zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup4[j]; modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); } nCapacitors += sIBChipsPerRow; for (Int_t j = 0; j < nGroup5A; j++) { - if (j == 0) + if (j == 0) { xpos = xGroup5A[0]; - else + } else { xpos = xGroup5A[1]; + } zpos = zGroup5A[j]; modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); } @@ -799,8 +806,9 @@ TGeoVolume* V3Layer::createIBFPCAlGnd(const Double_t xcable, const Double_t zcab aluminumVol->SetFillColor(kCyan); ypos = coverlay->GetDY() - aluminum->GetDY(); - if (mBuildLevel < 1) // Aluminum + if (mBuildLevel < 1) { // Aluminum coverlayVol->AddNode(aluminumVol, 1, new TGeoTranslation(0, ypos, 0)); + } return coverlayVol; } @@ -850,8 +858,9 @@ TGeoVolume* V3Layer::createIBFPCAlAnode(const Double_t xcable, const Double_t zc aluminumVol->SetFillColor(kCyan); ypos = -coverlay->GetDY() + aluminum->GetZ(1); - if (mBuildLevel < 1) // Aluminum + if (mBuildLevel < 1) { // Aluminum coverlayVol->AddNode(aluminumVol, 1, new TGeoCombiTrans(0, ypos, 0, new TGeoRotation("", 0, -90, 0))); + } return coverlayVol; } @@ -1154,16 +1163,19 @@ TGeoVolume* V3Layer::createStaveModelInnerB4(const TGeoManager* mgr) // Now build up the half stave ypos = glue->GetDY(); - if (mBuildLevel < 2) // Glue + if (mBuildLevel < 2) { // Glue mechStavVol->AddNode(glueVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (glue->GetDY() + fleecbot->GetDY()); - if (mBuildLevel < 5) // Carbon + if (mBuildLevel < 5) { // Carbon mechStavVol->AddNode(fleecbotVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (fleecbot->GetDY() + cfplate->GetDY()); - if (mBuildLevel < 5) // Carbon + if (mBuildLevel < 5) { // Carbon mechStavVol->AddNode(cfplateVol, 1, new TGeoTranslation(0, ypos, 0)); + } ylay = ypos + cfplate->GetDY(); // The level where tubes etc. lay @@ -1835,10 +1847,11 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) ymod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDY(); zmod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDZ(); - if (mLayerNumber <= 4) + if (mLayerNumber <= 4) { zlen = sOBColdPlateZLenML / 2; // Middle Layer - else + } else { zlen = sOBColdPlateZLenOL / 2; // Outer Layer + } xlen = sOBColdPlateXWidth / 2; @@ -1873,8 +1886,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) new TGeoTubeSeg("FleecTube", rCoolMax + yGraph, rCoolMax + yCFleece + yGraph, zlen, 180., 360.); TGeoTube* gammaConvRod; - if (mAddGammaConv) + if (mAddGammaConv) { gammaConvRod = new TGeoTube("GammaConver", 0, 0.5 * mGammaConvDiam, zlen - sOBCPConnHollowZLen); + } // TGeoBBox* flex1_5cm = new TGeoBBox("Flex1MV_5cm", xHalfSt, yFlex1 / 2, flexOverlap / 2); // TGeoBBox* flex2_5cm = new TGeoBBox("Flex2MV_5cm", xHalfSt, yFlex2 / 2, flexOverlap / 2); @@ -1887,8 +1901,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) // The half stave container (an XTru to avoid overlaps between neightbours) xHalfSt = xmod; // add the cross cables when done! yHalfSt = ypowbus + ymod + coldPlate->GetDY() + 2 * fleeccent->GetDY() + graphlat->GetDY() + fleeclat->GetDY(); - if (mAddGammaConv) + if (mAddGammaConv) { yHalfSt += mGammaConvDiam; + } xtru[0] = xHalfSt; ytru[0] = 0; @@ -1898,8 +1913,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) ytru[2] = ytru[1]; xtru[3] = xtru[2]; ytru[3] = ytru[2] - (coolTube->GetRmax() + fleectub->GetRmax()); - if (mAddGammaConv) + if (mAddGammaConv) { ytru[3] -= mGammaConvDiam; + } xtru[4] = sOBCoolTubeXDist / 2 - fleectub->GetRmax(); ytru[4] = ytru[3]; xtru[5] = xtru[4]; @@ -1923,8 +1939,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) new TGeoBBox("connCsideOB", sOBCPConnectorXWidth / 2, sOBCPConnBlockYHei / 2, sOBCPConnBlockZLen / 2); // The StaveStruct container, a Composite Shape - if (mAddGammaConv) + if (mAddGammaConv) { yHalfSt -= mGammaConvDiam; + } ypos = 2 * yHalfSt + connAside->GetDY() - sOBCPConnHollowYHei; zpos = zlen + connAside->GetDZ() - sOBCPConnHollowZLen; snprintf(volname, nameLen, "transAsideOB%d", mLayerNumber); @@ -2048,18 +2065,21 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) ypos -= ymod; ypos -= fleeccent->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(fleeccentVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos -= fleeccent->GetDY(); ypos -= coldPlate->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(coldPlateVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos -= coldPlate->GetDY(); ypos -= fleeccent->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(fleeccentVol, 2, new TGeoTranslation(0, ypos, 0)); + } xpos = sOBCoolTubeXDist / 2; ypos1 = ypos - (fleeccent->GetDY() + coolTube->GetRmax()); @@ -2236,45 +2256,55 @@ TGeoVolume* V3Layer::createOBPowerBiasBuses(const Double_t zcable, const TGeoMan // Volumes are piled up from bottom to top ypos = -pnbBus->GetDY() + kapPB->GetDY(); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (kapPB->GetDY() + gndPB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(gndPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (gndPB->GetDY() + dielPB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(dielPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (dielPB->GetDY() + topPB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(topPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (topPB->GetDY() + kapPB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapPBVol, 2, new TGeoTranslation(0, ypos, 0)); + } // ypos += (kapPB->GetDY() + kapBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (kapBB->GetDY() + botBB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(botBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (botBB->GetDY() + dielBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(dielBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (dielBB->GetDY() + topBB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(topBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (topBB->GetDY() + kapBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapBBVol, 2, new TGeoTranslation(0, ypos, 0)); + } // return pnbBusVol; @@ -3380,10 +3410,11 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) // First create all needed shapes // For material budget studies - if (mBuildLevel < 7) + if (mBuildLevel < 7) { dummyChip = kFALSE; // will be made of Si - else + } else { dummyChip = kTRUE; // will be made of Air + } // The chip (the same as for IB) snprintf(chipName, nameLen, "%s%d", GeometryTGeo::getITSChipPattern(), mLayerNumber); @@ -3453,8 +3484,9 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) // Now build up the module ypos = -module->GetDY() + glueCP->GetDY(); - if (mBuildLevel < 3) // Glue + if (mBuildLevel < 3) { // Glue modVol->AddNode(glueCPVol, 1, new TGeoTranslation(0, ypos, 0)); + } xpos = xchip + xGap / 2; ypos += (ychip + glueCP->GetDY()); @@ -3478,8 +3510,9 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) } ypos += (ychip + glueFPC->GetDY()); - if (mBuildLevel < 3) // Glue + if (mBuildLevel < 3) { // Glue modVol->AddNode(glueFPCVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += glueFPC->GetDY(); if (mBuildLevel < 5) { // Kapton @@ -3536,8 +3569,9 @@ TGeoVolume* V3Layer::createOBFPCCuGnd(const Double_t zcable, const TGeoManager* copperVol->SetFillColor(kCyan); ypos = -soldmask->GetDY() + copper->GetDY(); - if (mBuildLevel < 1) // Copper + if (mBuildLevel < 1) { // Copper soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + } return soldmaskVol; } @@ -3581,8 +3615,9 @@ TGeoVolume* V3Layer::createOBFPCCuSig(const Double_t zcable, const TGeoManager* copperVol->SetFillColor(kCyan); ypos = soldmask->GetDY() - copper->GetDY(); - if (mBuildLevel < 1) // Copper + if (mBuildLevel < 1) { // Copper soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + } return soldmaskVol; } diff --git a/Detectors/ITSMFT/ITS/simulation/src/V3Services.cxx b/Detectors/ITSMFT/ITS/simulation/src/V3Services.cxx index b0d44c1c9c32b..38294eb0ca47f 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/V3Services.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/V3Services.cxx @@ -81,8 +81,9 @@ TGeoVolume* V3Services::createIBEndWheelsSideA(const TGeoManager* mgr) TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideA"); endWheelsVol->SetVisibility(kTRUE); - for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) { ibEndWheelSideA(jLay, endWheelsVol, mgr); + } // Return the wheels return endWheelsVol; @@ -108,8 +109,9 @@ TGeoVolume* V3Services::createIBEndWheelsSideC(const TGeoManager* mgr) TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideC"); endWheelsVol->SetVisibility(kTRUE); - for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) { ibEndWheelSideC(jLay, endWheelsVol, mgr); + } // Return the wheels return endWheelsVol; @@ -182,8 +184,9 @@ void V3Services::createMBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* m // Created: 24 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) { obEndWheelSideA(jLay, mother, mgr); + } } void V3Services::createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) @@ -202,8 +205,9 @@ void V3Services::createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* m // Created: 26 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) { mbEndWheelSideC(jLay, mother, mgr); + } } void V3Services::createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* mgr) @@ -222,8 +226,9 @@ void V3Services::createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* m // Created: 27 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) { obEndWheelSideA(jLay + sNumberMiddlLayers, mother, mgr); + } } void V3Services::createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) @@ -242,8 +247,9 @@ void V3Services::createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* m // Created: 27 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) { obEndWheelSideC(jLay, mother, mgr); + } } void V3Services::createOBConeSideA(TGeoVolume* mother, const TGeoManager* mgr) @@ -668,10 +674,11 @@ void V3Services::ibEndWheelSideC(const Int_t iLay, TGeoVolume* endWheel, const T endwcbshmata->RegisterYourself(); TGeoTranslation* endwcbshmatb = new TGeoTranslation(Form("endwcbshmat%dl%db", ihole, iLay), -xpos, -ypos, zpos); endwcbshmatb->RegisterYourself(); - if ((ihole > 1 && ihole < 5) || (ihole > 5 && ihole < 9)) // Small holes + if ((ihole > 1 && ihole < 5) || (ihole > 5 && ihole < 9)) { // Small holes strcpy(holename, endwcbasShol->GetName()); - else + } else { strcpy(holename, endwcbasBhol->GetName()); + } endWheelComposite += Form("-%s:endwcbshmat%dl%da-%s:endwcbshmat%dl%db", holename, ihole, iLay, holename, ihole, iLay); } @@ -1270,10 +1277,11 @@ TString V3Services::ibCreateHollowsCyssFlangeSideA(const Double_t zlen) cyssFlangeAHollows += Form("-roundhalf:roundtr%d-roundhalf:roundtr%d", j + 2, j + 5); phi = 360 - phi - 0.05; - if (j == 3) + if (j == 3) { dphi = 360 - sCyssFlangeAHollowPhi0 + 0.05; - else + } else { dphi = phi + (sCyssFlangeAHole1PhiStep - sCyssFlangeAHollowPhi1) + 0.1; + } TGeoTubeSeg* hollow1 = new TGeoTubeSeg(Form("hollow%d", j), rmin, rmax, 2 * zlen, phi, dphi); @@ -1611,10 +1619,11 @@ void V3Services::obEndWheelSideA(const Int_t iLay, TGeoVolume* mother, const TGe // Finally put everything in the mother volume // In blueprints the Z position is given wrt the shelf holes // First the ring - if (iLay < sNumberMiddlLayers) + if (iLay < sNumberMiddlLayers) { zpos = sMBWheelsZpos + sOBWheelShelfHoleZpos; - else + } else { zpos = sOBWheelsZpos + sOBWheelShelfHoleZpos; + } zpos -= outerRingSh->GetDz(); mother->AddNode(ringOuterVol, 1, new TGeoTranslation(0, 0, zpos)); @@ -1697,10 +1706,11 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe TGeoTube* innerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], sOBWheelSuppRmax[iLay], sOBWheelThickness / 2); // The outer ring with the flange - if (iLay == 0) + if (iLay == 0) { nsect = 6; - else + } else { nsect = 4; + } TGeoPcon* outerRingSh = new TGeoPcon(0, 360, nsect); @@ -1722,17 +1732,19 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe } // The lower ring - if (iLay == 0) + if (iLay == 0) { zlen = sOBWheelSuppZlen[iLay] - sOBWheelFlangeZlen - 2 * sOBWheelThickness; - else + } else { zlen = sOBWheelSuppZlen[iLay] - sOBWheelThickness - outerRingSh->GetZ(nsect - 1); + } rmax = sOBWheelSuppRmin[iLay] + sOBWheelThickness; TGeoTube* lowerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], rmax, zlen / 2); // The upper ring - if (iLay == 1) // For odd layers the upper and lower rings length is the same + if (iLay == 1) { // For odd layers the upper and lower rings length is the same zlen = sOBWheelSuppZlen[iLay] - 2 * sOBWheelThickness; + } rmin = sOBWheelSuppRmax[iLay] - sOBWheelThickness; TGeoTube* upperRingSh = new TGeoTube(rmin, sOBWheelSuppRmax[iLay], zlen / 2); @@ -1929,8 +1941,9 @@ void V3Services::obEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe mother->AddNode(ringLowerVol, 1, new TGeoTranslation(0, 0, -zpos)); - if (iLay == 1) + if (iLay == 1) { zpos -= (sOBWheelThickness + (static_cast<TGeoTube*>(upperRingSh))->GetDz()); + } mother->AddNode(ringUpperVol, 1, new TGeoTranslation(0, 0, -zpos)); } @@ -2165,10 +2178,11 @@ void V3Services::obConeTraysSideA(TGeoVolume* mother, const TGeoManager* mgr) // Finally put everything in the mother volume for (Int_t j = 0; j < 2; j++) { - if (j == 0) + if (j == 0) { zpos = sOBConesZpos - sOBTrayZpos[j] - sOBTrayZlen[j]; - else + } else { zpos = sOBConesZpos + sOBTrayZpos[j]; + } mother->AddNode(obTrayVol[j], 1, new TGeoTranslation(0, 0, zpos)); mother->AddNode(obTrayVol[j], 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 0, 0))); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h index b179c35e3b482..16a3446eaf72f 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h @@ -91,8 +91,9 @@ GPUhdi() Line::Line(const float firstPoint[3], const float secondPoint[3]) float inverseNorm{1.f / gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + cosinesDirector[2] * cosinesDirector[2])}; - for (int index{0}; index < 3; ++index) + for (int index{0}; index < 3; ++index) { cosinesDirector[index] *= inverseNorm; + } } GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, const Cluster* outerClusters) @@ -108,8 +109,9 @@ GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, cons float inverseNorm{1.f / gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + cosinesDirector[2] * cosinesDirector[2])}; - for (int index{0}; index < 3; ++index) + for (int index{0}; index < 3; ++index) { cosinesDirector[index] *= inverseNorm; + } } #ifdef _ALLOW_DEBUG_TREES_ITS_ @@ -150,8 +152,9 @@ GPUhdi() float Line::getDistanceFromPoint(const Line& line, const float point[3] { float DCASquared{0}; float cdelta{0}; - for (int i{0}; i < 3; ++i) + for (int i{0}; i < 3; ++i) { cdelta -= line.cosinesDirector[i] * (line.originPoint[i] - point[i]); + } for (int i{0}; i < 3; ++i) { DCASquared += (line.originPoint[i] - point[i] + line.cosinesDirector[i] * cdelta) * (line.originPoint[i] - point[i] + line.cosinesDirector[i] * cdelta); @@ -193,8 +196,9 @@ GPUhdi() float Line::getDCA(const Line& firstLine, const Line& secondLine, const GPUhdi() void Line::getDCAComponents(const Line& line, const float point[3], float destArray[6]) { float cdelta{0.}; - for (int i{0}; i < 3; ++i) + for (int i{0}; i < 3; ++i) { cdelta -= line.cosinesDirector[i] * (line.originPoint[i] - point[i]); + } destArray[0] = line.originPoint[0] - point[0] + line.cosinesDirector[0] * cdelta; destArray[3] = line.originPoint[1] - point[1] + line.cosinesDirector[1] * cdelta; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 866e3480cd69a..2951da3b81ae3 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -83,8 +83,9 @@ inline TrackingParameters& TrackingParameters::operator=(const TrackingParameter this->MinTrackLength = t.MinTrackLength; /// Trackleting cuts this->TrackletMaxDeltaPhi = t.TrackletMaxDeltaPhi; - for (int iT = 0; iT < constants::its::TrackletsPerRoad; ++iT) + for (int iT = 0; iT < constants::its::TrackletsPerRoad; ++iT) { this->TrackletMaxDeltaZ[iT] = t.TrackletMaxDeltaZ[iT]; + } /// Cell finding cuts this->CellMaxDeltaTanLambda = t.CellMaxDeltaTanLambda; this->CellMaxDeltaPhi = t.CellMaxDeltaPhi; @@ -103,10 +104,12 @@ inline TrackingParameters& TrackingParameters::operator=(const TrackingParameter inline MemoryParameters& MemoryParameters::operator=(const MemoryParameters& t) { this->MemoryOffset = t.MemoryOffset; - for (int iC = 0; iC < constants::its::CellsPerRoad; ++iC) + for (int iC = 0; iC < constants::its::CellsPerRoad; ++iC) { this->CellsMemoryCoefficients[iC] = t.CellsMemoryCoefficients[iC]; - for (int iT = 0; iT < constants::its::TrackletsPerRoad; ++iT) + } + for (int iT = 0; iT < constants::its::TrackletsPerRoad; ++iT) { this->TrackletsMemoryCoefficients[iT] = t.TrackletsMemoryCoefficients[iT]; + } return *this; } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/json.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/json.h index 1a7efb0394021..f6bf18f6e04e5 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/json.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/json.h @@ -6293,10 +6293,11 @@ class binary_writer } case value_t::boolean: { - if (add_prefix) + if (add_prefix) { oa->write_character(j.m_value.boolean ? static_cast<CharType>('T') : static_cast<CharType>('F')); + } break; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx index 8ff4b4635b9ba..a51e30edd2117 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx @@ -27,8 +27,9 @@ Line::Line(std::array<float, 3> firstPoint, std::array<float, 3> secondPoint) float inverseNorm{1.f / std::sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + cosinesDirector[2] * cosinesDirector[2])}; - for (int index{0}; index < 3; ++index) + for (int index{0}; index < 3; ++index) { cosinesDirector[index] *= inverseNorm; + } } bool Line::areParallel(const Line& firstLine, const Line& secondLine, const float precision) @@ -37,22 +38,25 @@ bool Line::areParallel(const Line& firstLine, const Line& secondLine, const floa firstLine.cosinesDirector[2] * secondLine.cosinesDirector[1]}; float module{std::abs(firstLine.cosinesDirector[1] * secondLine.cosinesDirector[2]) + std::abs(firstLine.cosinesDirector[2] * secondLine.cosinesDirector[1])}; - if (std::abs(crossProdX) > precision * module) + if (std::abs(crossProdX) > precision * module) { return false; + } float crossProdY{-firstLine.cosinesDirector[0] * secondLine.cosinesDirector[2] + firstLine.cosinesDirector[2] * secondLine.cosinesDirector[0]}; module = std::abs(firstLine.cosinesDirector[0] * secondLine.cosinesDirector[2]) + std::abs(firstLine.cosinesDirector[2] * secondLine.cosinesDirector[0]); - if (std::abs(crossProdY) > precision * module) + if (std::abs(crossProdY) > precision * module) { return false; + } float crossProdZ = firstLine.cosinesDirector[0] * secondLine.cosinesDirector[1] - firstLine.cosinesDirector[1] * secondLine.cosinesDirector[0]; module = std::abs(firstLine.cosinesDirector[0] * secondLine.cosinesDirector[1]) + std::abs(firstLine.cosinesDirector[1] * secondLine.cosinesDirector[0]); - if (std::abs(crossProdZ) > precision * module) + if (std::abs(crossProdZ) > precision * module) { return false; + } return true; } @@ -61,8 +65,9 @@ std::array<float, 6> Line::getDCAComponents(const Line& line, const std::array<f { std::array<float, 6> components{0., 0., 0., 0., 0., 0.}; float cdelta{0.}; - for (int i{0}; i < 3; ++i) + for (int i{0}; i < 3; ++i) { cdelta -= line.cosinesDirector[i] * (line.originPoint[i] - point[i]); + } components[0] = line.originPoint[0] - point[0] + line.cosinesDirector[0] * cdelta; components[3] = line.originPoint[1] - point[1] + line.cosinesDirector[1] * cdelta; @@ -84,8 +89,9 @@ ClusterLines::ClusterLines(const int firstLabel, const Line& firstLine, const in std::array<float, 3> covarianceFirst{1., 1., 1.}; std::array<float, 3> covarianceSecond{1., 1., 1.}; - for (int i{0}; i < 6; ++i) + for (int i{0}; i < 6; ++i) { mWeightMatrix[i] = firstLine.weightMatrix[i] + secondLine.weightMatrix[i]; + } float determinantFirst = firstLine.cosinesDirector[2] * firstLine.cosinesDirector[2] * covarianceFirst[0] * covarianceFirst[1] + @@ -187,8 +193,9 @@ ClusterLines::ClusterLines(const Line& firstLine, const Line& secondLine) std::array<float, 3> covarianceFirst{1., 1., 1.}; std::array<float, 3> covarianceSecond{1., 1., 1.}; - for (int i{0}; i < 6; ++i) + for (int i{0}; i < 6; ++i) { mWeightMatrix[i] = firstLine.weightMatrix[i] + secondLine.weightMatrix[i]; + } float determinantFirst = firstLine.cosinesDirector[2] * firstLine.cosinesDirector[2] * covarianceFirst[0] * covarianceFirst[1] + @@ -282,8 +289,9 @@ void ClusterLines::add(const int& lineLabel, const Line& line, const bool& weigh #endif std::array<float, 3> covariance{1., 1., 1.}; - for (int i{0}; i < 6; ++i) + for (int i{0}; i < 6; ++i) { mWeightMatrix[i] += line.weightMatrix[i]; + } // if(weight) line->GetSigma2P0(covariance); float determinant{line.cosinesDirector[2] * line.cosinesDirector[2] * covariance[0] * covariance[1] + diff --git a/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx b/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx index d2139bffc5102..e4375d1caafb9 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx @@ -51,8 +51,9 @@ void ROframe::printPrimaryVertices() const int ROframe::getTotalClusters() const { size_t totalClusters{0}; - for (auto& clusters : mClusters) + for (auto& clusters : mClusters) { totalClusters += clusters.size(); + } return int(totalClusters); } } // namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 57a0168f29bdf..1aa9483d6f84b 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -249,8 +249,9 @@ void Tracker::findTracks(const ROframe& event) CA_DEBUGGER(assert(nClusters >= mTrkParams[0].MinTrackLength)); CA_DEBUGGER(roadCounters[nClusters - 4]++); - if (lastCellLevel == constants::its::UnusedIndex) + if (lastCellLevel == constants::its::UnusedIndex) { continue; + } /// From primary vertex context index to event index (== the one used as input of the tracking code) for (int iC{0}; iC < clusters.size(); iC++) { @@ -271,19 +272,22 @@ void Tracker::findTracks(const ROframe& event) temporaryTrack.setExternalClusterIndex(iC, clusters[iC], clusters[iC] != constants::its::UnusedIndex); } bool fitSuccess = fitTrack(event, temporaryTrack, constants::its::LayersNumber - 4, -1, -1); - if (!fitSuccess) + if (!fitSuccess) { continue; + } CA_DEBUGGER(fitCounters[nClusters - 4]++); temporaryTrack.resetCovariance(); fitSuccess = fitTrack(event, temporaryTrack, 0, constants::its::LayersNumber, 1); - if (!fitSuccess) + if (!fitSuccess) { continue; + } CA_DEBUGGER(backpropagatedCounters[nClusters - 4]++); temporaryTrack.getParamOut() = temporaryTrack; temporaryTrack.resetCovariance(); fitSuccess = fitTrack(event, temporaryTrack, constants::its::LayersNumber - 1, -1, -1); - if (!fitSuccess) + if (!fitSuccess) { continue; + } CA_DEBUGGER(refitCounters[nClusters - 4]++); tracks.emplace_back(temporaryTrack); CA_DEBUGGER(assert(nClusters == temporaryTrack.getNumberOfClusters())); @@ -393,22 +397,26 @@ bool Tracker::fitTrack(const ROframe& event, TrackITSExt& track, int start, int } const TrackingFrameInfo& trackingHit = event.getTrackingFrameInfoOnLayer(iLayer).at(track.getClusterIndex(iLayer)); - if (!track.rotate(trackingHit.alphaTrackingFrame)) + if (!track.rotate(trackingHit.alphaTrackingFrame)) { return false; + } - if (!track.propagateTo(trackingHit.xTrackingFrame, getBz())) + if (!track.propagateTo(trackingHit.xTrackingFrame, getBz())) { return false; + } track.setChi2(track.getChi2() + track.getPredictedChi2(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)); - if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) + if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) { return false; + } const float xx0 = (iLayer > 2) ? 0.008f : 0.003f; // Rough layer thickness constexpr float radiationLength = 9.36f; // Radiation length of Si [cm] constexpr float density = 2.33f; // Density of Si [g/cm^3] - if (!track.correctForMaterial(xx0, xx0 * radiationLength * density, true)) + if (!track.correctForMaterial(xx0, xx0 * radiationLength * density, true)) { return false; + } } return true; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index c55fca3840077..b5b843f33e24e 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -238,8 +238,9 @@ const std::vector<std::pair<int, int>> VertexerTraits::selectClusters(const std: { std::vector<std::pair<int, int>> filteredBins{}; int phiBinsNum{selectedBinsRect[3] - selectedBinsRect[1] + 1}; - if (phiBinsNum < 0) + if (phiBinsNum < 0) { phiBinsNum += PhiBins; + } filteredBins.reserve(phiBinsNum); for (int iPhiBin{selectedBinsRect[1]}, iPhiCount{0}; iPhiCount < phiBinsNum; iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) { @@ -396,11 +397,13 @@ void VertexerTraits::computeVertices() std::vector<bool> usedTracklets{}; usedTracklets.resize(mTracklets.size(), false); for (int tracklet1{0}; tracklet1 < numTracklets; ++tracklet1) { - if (usedTracklets[tracklet1]) + if (usedTracklets[tracklet1]) { continue; + } for (int tracklet2{tracklet1 + 1}; tracklet2 < numTracklets; ++tracklet2) { - if (usedTracklets[tracklet2]) + if (usedTracklets[tracklet2]) { continue; + } if (Line::getDCA(mTracklets[tracklet1], mTracklets[tracklet2]) <= mVrtParams.pairCut) { mTrackletClusters.emplace_back(tracklet1, mTracklets[tracklet1], tracklet2, mTracklets[tracklet2]); std::array<float, 3> tmpVertex{mTrackletClusters.back().getVertex()}; @@ -411,8 +414,9 @@ void VertexerTraits::computeVertices() usedTracklets[tracklet1] = true; usedTracklets[tracklet2] = true; for (int tracklet3{0}; tracklet3 < numTracklets; ++tracklet3) { - if (usedTracklets[tracklet3]) + if (usedTracklets[tracklet3]) { continue; + } if (Line::getDistanceFromPoint(mTracklets[tracklet3], tmpVertex) < mVrtParams.pairCut) { mTrackletClusters.back().add(tracklet3, mTracklets[tracklet3]); usedTracklets[tracklet3] = true; diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h index bb5146fc908d2..59d724b2f886c 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/GeometryTGeo.h @@ -43,8 +43,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo static GeometryTGeo* Instance() { // get (create if needed) a unique instance of the object - if (!sInstance) + if (!sInstance) { sInstance = std::unique_ptr<GeometryTGeo>(new GeometryTGeo(true, 0)); + } return sInstance.get(); } diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfSegmentation.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfSegmentation.h index 96a6e2b6e5e61..45a3efd7d6768 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfSegmentation.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/HalfSegmentation.h @@ -52,10 +52,11 @@ class HalfSegmentation : public VSegmentation HalfDiskSegmentation* getHalfDisk(Int_t iDisk) const { - if (iDisk >= 0 && iDisk < mHalfDisks->GetEntries()) + if (iDisk >= 0 && iDisk < mHalfDisks->GetEntries()) { return (HalfDiskSegmentation*)mHalfDisks->At(iDisk); - else + } else { return nullptr; + } } private: diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/Support.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/Support.h index b0a97a5ee1269..a61575c759358 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/Support.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/Support.h @@ -136,10 +136,11 @@ auto serialBoolOperation(L&& base, SHAPE&& shape, EL&& elements, OP&& op) localTranslation = new TGeoTranslation(par[3], par[4], par[5]); //The first subtraction needs a shape, the base shape - if (!localCS) + if (!localCS) { localCS = new TGeoCompositeShape(nullptr, compositeOperation(base, localshape, localTranslation, std::forward<OP>(op))); - else + } else { localCS = new TGeoCompositeShape(nullptr, compositeOperation(localCS, localshape, localTranslation, std::forward<OP>(op))); + } } return localCS; } diff --git a/Detectors/ITSMFT/MFT/base/src/Geometry.cxx b/Detectors/ITSMFT/MFT/base/src/Geometry.cxx index 76b88158cea6d..37e81f9ac3955 100644 --- a/Detectors/ITSMFT/MFT/base/src/Geometry.cxx +++ b/Detectors/ITSMFT/MFT/base/src/Geometry.cxx @@ -97,8 +97,9 @@ Geometry* Geometry::sInstance = nullptr; Geometry* Geometry::instance() { - if (!sInstance) + if (!sInstance) { sInstance = new Geometry(); + } return sInstance; } @@ -125,12 +126,14 @@ void Geometry::build() { // load the detector segmentation - if (!mSegmentation) + if (!mSegmentation) { mSegmentation = new Segmentation(gSystem->ExpandPathName("$(VMCWORKDIR)/Detectors/Geometry/MFT/data/Geometry.xml")); + } // build the geometry - if (!mBuilder) + if (!mBuilder) { mBuilder = new GeometryBuilder(); + } mBuilder->buildGeometry(); delete mBuilder; } @@ -162,8 +165,9 @@ Int_t Geometry::getDiskNSensors(Int_t diskId) const Int_t nSensors = 0; for (int iHalf = 0; iHalf < 2; iHalf++) { HalfDiskSegmentation* diskSeg = mSegmentation->getHalf(iHalf)->getHalfDisk(diskId); - if (diskSeg) + if (diskSeg) { nSensors += diskSeg->getNChips(); + } } return nSensors; } diff --git a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx index e3067d978a71a..1757e32facfff 100644 --- a/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx +++ b/Detectors/ITSMFT/MFT/base/src/GeometryTGeo.cxx @@ -131,8 +131,9 @@ void GeometryTGeo::Build(Int_t loadTrans) mLadderId2Index[j].resize(numberOfLadders + 1); Int_t nL = 0; for (Int_t nSensor = MinSensorsPerLadder; nSensor <= MaxSensorsPerLadder; nSensor++) { - if (mNumberOfLadders[j][nSensor] == 0) + if (mNumberOfLadders[j][nSensor] == 0) { continue; + } Int_t n = extractNumberOfLadders(i, j, nSensor, nL); } // nSensor @@ -473,8 +474,9 @@ void GeometryTGeo::extractSensorXAlpha(int index, float& x, float& alpha) {} //__________________________________________________________________________ Bool_t GeometryTGeo::getSensorID(Int_t index, Int_t& half, Int_t& disk, Int_t& ladder, Int_t& sensor) const { - if (index < 0 || index >= mTotalNumberOfSensors) + if (index < 0 || index >= mTotalNumberOfSensors) { return kFALSE; + } half = index / (mTotalNumberOfSensors / mNumberOfHalves); index = index % (mTotalNumberOfSensors / mNumberOfHalves); diff --git a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx index 98b7a8c9e46e8..458c8f4465065 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx @@ -1814,10 +1814,12 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) // Positioning the layers MotherBoard0->AddNode(vMB0cu, 1); Int_t signe; - if (half == 0) + if (half == 0) { signe = -1; - if (half == 1) + } + if (half == 1) { signe = +1; + } auto* t_MB0fr4 = new TGeoTranslation("translation_fr4", 0.0, signe * (mMB0fr4 + mMB0cu[1]) / 2, 0.0); t_MB0fr4->RegisterYourself(); MotherBoard0->AddNode(vMB0fr4, 1, t_MB0fr4); diff --git a/Detectors/ITSMFT/MFT/base/src/HalfDisk.cxx b/Detectors/ITSMFT/MFT/base/src/HalfDisk.cxx index a6d41e1122df3..6783e8440d0a0 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfDisk.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfDisk.cxx @@ -141,8 +141,9 @@ void HalfDisk::createLadders() for (Int_t iLadder = 0; iLadder < mSegmentation->getNLadders(); iLadder++) { LadderSegmentation* ladderSeg = mSegmentation->getLadder(iLadder); - if (!ladderSeg) + if (!ladderSeg) { Fatal("CreateLadders", Form("No Segmentation found for ladder %d ", iLadder), 0, 0); + } auto* ladder = new Ladder(ladderSeg); TGeoVolume* ladVol = ladder->createVolume(); diff --git a/Detectors/ITSMFT/MFT/base/src/HalfDiskSegmentation.cxx b/Detectors/ITSMFT/MFT/base/src/HalfDiskSegmentation.cxx index 252de65243f34..5b5651c566712 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfDiskSegmentation.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfDiskSegmentation.cxx @@ -60,10 +60,11 @@ HalfDiskSegmentation::HalfDiskSegmentation(const HalfDiskSegmentation& input) { // copy constructor - if (input.mLadders) + if (input.mLadders) { mLadders = new TClonesArray(*(input.mLadders)); - else + } else { mLadders = new TClonesArray("o2::mft::LadderSegmentation"); + } mLadders->SetOwner(kTRUE); } @@ -76,8 +77,9 @@ HalfDiskSegmentation::~HalfDiskSegmentation() { Clear(""); } void HalfDiskSegmentation::Clear(const Option_t* /*opt*/) { - if (mLadders) + if (mLadders) { mLadders->Delete(); + } delete mLadders; mLadders = nullptr; } @@ -184,7 +186,8 @@ void HalfDiskSegmentation::print(Option_t* opt) getTransformation()->Print(); if (opt && (strstr(opt, "ladder") || strstr(opt, "l"))) { - for (int i = 0; i < getNLadders(); i++) + for (int i = 0; i < getNLadders(); i++) { getLadder(i)->Print(opt); + } } } diff --git a/Detectors/ITSMFT/MFT/base/src/HalfSegmentation.cxx b/Detectors/ITSMFT/MFT/base/src/HalfSegmentation.cxx index 838961cafdd90..0d6521e6cf3d1 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfSegmentation.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfSegmentation.cxx @@ -37,8 +37,9 @@ HalfSegmentation::HalfSegmentation() : VSegmentation(), mHalfDisks(nullptr) {} HalfSegmentation::HalfSegmentation(const HalfSegmentation& source) : VSegmentation(source), mHalfDisks(nullptr) { - if (source.mHalfDisks) + if (source.mHalfDisks) { mHalfDisks = new TClonesArray(*(source.mHalfDisks)); + } } /// Constructor @@ -86,8 +87,9 @@ HalfSegmentation::HalfSegmentation(const Char_t* nameGeomFile, const Short_t id) HalfSegmentation::~HalfSegmentation() { - if (mHalfDisks) + if (mHalfDisks) { mHalfDisks->Delete(); + } delete mHalfDisks; } @@ -97,8 +99,9 @@ HalfSegmentation::~HalfSegmentation() void HalfSegmentation::Clear(const Option_t* /*opt*/) { - if (mHalfDisks) + if (mHalfDisks) { mHalfDisks->Delete(); + } delete mHalfDisks; mHalfDisks = nullptr; } diff --git a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx index 18e3877e16e78..b674159cdb603 100644 --- a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx @@ -262,8 +262,9 @@ void HeatExchanger::createManifold(Int_t disk) tTop[5] = new TGeoTranslation(Form("tTop6MF%d", disk), -lengthTop1[disk] / 2, widthTop1[disk] / 2 - cornerRadiusTop[disk], thicknessMiddle[disk] / 2 + thicknessTop[disk] / 2); tTop[6] = new TGeoTranslation(Form("tTop7MF%d", disk), -lengthTop1[disk] / 2, -(widthTop1[disk] / 2 - cornerRadiusTop[disk]), thicknessMiddle[disk] / 2 + thicknessTop[disk] / 2); - for (Int_t i = 0; i < 7; ++i) + for (Int_t i = 0; i < 7; ++i) { tTop[i]->RegisterYourself(); + } TGeoTranslation* tMiddle1 = new TGeoTranslation(Form("tMiddle1MF%d", disk), 0, 0, 0); TGeoTranslation* tBottom1 = new TGeoTranslation(Form("tBottom1MF%d", disk), 0, 0, -(thicknessMiddle[disk] / 2 + thicknessBottom[disk] / 2)); @@ -359,10 +360,11 @@ void HeatExchanger::createManifold(Int_t disk) tPipe = new TGeoTranslation(Form("tPipe%dMF%d", iPipeRow + 1, disk), lengthMiddle1[disk] / 2 - offsetPipeRow[disk][iPipeRow], 0, 0); tPipe->RegisterYourself(); - if (iPipeRow == nPipeRow[disk] - 1) + if (iPipeRow == nPipeRow[disk] - 1) { namePipe += Form("shapePipeMF%d:tPipe%dMF%d", disk, iPipeRow + 1, disk); - else + } else { namePipe += Form("shapePipeMF%d:tPipe%dMF%d +", disk, iPipeRow + 1, disk); + } } TGeoCompositeShape* posiPipeOneCol = new TGeoCompositeShape(Form("posiPipeOneColMF%d", disk), namePipe); @@ -446,8 +448,9 @@ void HeatExchanger::createManifold(Int_t disk) tcoverBodyBathtub[5] = new TGeoTranslation(Form("tcoverBodyBathtub6MF%d", disk), -(lengthBodyBathtub1 / 2), widthBodyBathtub1 / 2 - cornerRadiusBodyBathtub1[disk], 0.); tcoverBodyBathtub[6] = new TGeoTranslation(Form("tcoverBodyBathtub7MF%d", disk), -(lengthBodyBathtub1 / 2), -(widthBodyBathtub1 / 2 - cornerRadiusBodyBathtub1[disk]), 0.); - for (Int_t i = 0; i < 7; ++i) + for (Int_t i = 0; i < 7; ++i) { tcoverBodyBathtub[i]->RegisterYourself(); + } TGeoCompositeShape* shapeCoverBathtub = new TGeoCompositeShape(Form("shapeCoverBathtubMF%d", disk), Form("coverBodyBathtub1MF%d + coverBodyBathtub2MF%d:tcoverBodyBathtub2MF%d + coverBodyBathtub3MF%d:tcoverBodyBathtub3MF%d + coverBodyBathtub3MF%d:tcoverBodyBathtub4MF%d + coverBodyBathtub2MF%d:tcoverBodyBathtub5MF%d + coverBodyBathtub3MF%d:tcoverBodyBathtub6MF%d + coverBodyBathtub3MF%d:tcoverBodyBathtub7MF%d", disk, disk, disk, disk, disk, disk, disk, disk, disk, disk, disk, disk, disk)); @@ -521,8 +524,9 @@ void HeatExchanger::createManifold(Int_t disk) combtcoverBodyStep[3] = new TGeoCombiTrans(Form("combtcoverBodyStep4MF%d", disk), -(lengthStep1[disk] - lengthStep2) / 2, -widthStep1[disk] / 2, 0., rcoverBodyStep); combtcoverBodyStep[3]->RegisterYourself(); - for (Int_t i = 0; i < 4; ++i) + for (Int_t i = 0; i < 4; ++i) { tcoverBodyStep[i]->RegisterYourself(); + } TGeoCompositeShape* shapeStep = new TGeoCompositeShape(Form("shapeStepMF%d", disk), Form("coverBodyStep1MF%d:tcoverBodyStep1MF%d + coverBodyStep2MF%d:tcoverBodyStep2MF%d + coverBodyStep3MF%d:tcoverBodyStep3MF%d + coverBodyStep4MF%d:combtcoverBodyStep4MF%d", disk, disk, disk, disk, disk, disk, disk, disk)); @@ -753,12 +757,13 @@ void HeatExchanger::createManifold(Int_t disk) TString namePlug = ""; for (Int_t ipart = 0; ipart < 12; ++ipart) { tPlug[ipart]->RegisterYourself(); - if (ipart == 0) + if (ipart == 0) { namePlug += Form("plug1MF%d:tPlug1MF%d", disk, disk); - else if (ipart == 11) + } else if (ipart == 11) { namePlug += Form(" - plug%dMF%d:tPlug%dMF%d", ipart + 1, disk, ipart + 1, disk); - else + } else { namePlug += Form(" + plug%dMF%d:tPlug%dMF%d", ipart + 1, disk, ipart + 1, disk); + } } TGeoCompositeShape* shapePlug = new TGeoCompositeShape(Form("shapePlugMF%d", disk), namePlug); @@ -789,8 +794,9 @@ void HeatExchanger::createManifold(Int_t disk) twater[5] = new TGeoTranslation(Form("twater6MF%d", disk), -(lengthBodyBathtub1 / 2), widthBodyBathtub1 / 2 - cornerRadiusBodyBathtub1[disk], 0.); twater[6] = new TGeoTranslation(Form("twater7MF%d", disk), -(lengthBodyBathtub1 / 2), -(widthBodyBathtub1 / 2 - cornerRadiusBodyBathtub1[disk]), 0.); - for (Int_t i = 0; i < 7; ++i) + for (Int_t i = 0; i < 7; ++i) { twater[i]->RegisterYourself(); + } TGeoCompositeShape* shapeWater = new TGeoCompositeShape(Form("shapeCoverBathtubMF%d", disk), Form("water1MF%d + water2MF%d:twater2MF%d + water3MF%d:twater3MF%d + water3MF%d:twater4MF%d + water2MF%d:twater5MF%d +" @@ -816,8 +822,9 @@ void HeatExchanger::createManifold(Int_t disk) Double_t mfY = 6.8 - 0.1; // height, decrease to avoid overlap with support, to be solved, fm Double_t mfZ = 1.7 - 0.85; // thickness, decrease to avoid overlap with support, to be solved, fm Double_t fShift = 0; - if (disk == 3 || disk == 4) + if (disk == 3 || disk == 4) { fShift = 0.015; // to avoid overlap with the 2 curved water pipes on the 2 upstream chambers + } auto* MF01 = new TGeoVolume(Form("MF%d1", disk), shapeManifold, kMedPeek); auto* MFplug01 = new TGeoVolume(Form("MFplug%d1", disk), shapePlug, kMed_plug); @@ -870,12 +877,13 @@ void HeatExchanger::createHalfDisk0(Int_t half) Int_t disk = 0; - if (half == Top) + if (half == Top) { printf("Creating MFT heat exchanger for disk0 top\n"); - else if (half == Bottom) + } else if (half == Bottom) { printf("Creating MFT heat exchanger for disk0 bottom\n"); - else + } else { printf("No valid option for MFT heat exchanger on disk0\n"); + } mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); @@ -1248,10 +1256,12 @@ void HeatExchanger::createHalfDisk0(Int_t half) // Passage du beam pipe TGeoBoolNode* rohacellBase; - if (Geometry::sGrooves == 0) + if (Geometry::sGrooves == 0) { rohacellBase = new TGeoSubtraction(rohacellBase0, holeRohacell0, t01, t02); - if (Geometry::sGrooves == 1) + } + if (Geometry::sGrooves == 1) { rohacellBase = new TGeoSubtraction(rohacellGroove[iCount - 1], holeRohacell0, t01, t02); + } auto* rh0 = new TGeoCompositeShape(Form("rohacellTore%d_D0_H%d", 0, half), rohacellBase); auto* rohacellBaseWithHole = new TGeoVolume(Form("rohacellBaseWithHole_D0_H%d", half), rh0, mRohacell); @@ -1357,8 +1367,9 @@ void HeatExchanger::createHalfDisk0(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D0_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D0_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D0_H%d_%d", half, ipart), partRohacell0, mRohacell); + } } if (Geometry::sGrooves == 1) { @@ -1367,8 +1378,9 @@ void HeatExchanger::createHalfDisk0(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D0_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D0_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D0_H%d_%d", half, ipart), rohacellGroove[iCount - 1], mRohacell); + } } //=========================================================================================================== //=========================================================================================================== @@ -1381,8 +1393,9 @@ void HeatExchanger::createHalfDisk0(Int_t half) TGeoTranslation* tinsert0; TGeoVolume* insert0 = gGeoManager->MakeBox(Form("insert0_H%d_%d", half, ipart), mPeek, 1.0, 0.35 / 2., mRohacellThickness); Double_t ylocation = mSupportYDimensions[disk][0] + mHalfDiskGap - 0.35 / 2.; - for (Int_t ip = 1; ip < mNPart[disk]; ip++) + for (Int_t ip = 1; ip < mNPart[disk]; ip++) { ylocation = ylocation + mSupportYDimensions[disk][ip]; + } tinsert0 = new TGeoTranslation("tinsert0", 0., -ylocation, 0.); tinsert0->RegisterYourself(); mHalfDisk->AddNode(insert0, 0., tinsert0); @@ -1403,12 +1416,13 @@ void HeatExchanger::createHalfDisk1(Int_t half) Int_t disk = 1; - if (half == Top) + if (half == Top) { printf("Creating MFT heat exchanger for disk1 top\n"); - else if (half == Bottom) + } else if (half == Bottom) { printf("Creating MFT heat exchanger for disk1 bottom\n"); - else + } else { printf("No valid option for MFT heat exchanger on disk1\n"); + } mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); @@ -1786,10 +1800,12 @@ void HeatExchanger::createHalfDisk1(Int_t half) // Passage du beam pipe TGeoBoolNode* rohacellBase; - if (Geometry::sGrooves == 0) + if (Geometry::sGrooves == 0) { rohacellBase = new TGeoSubtraction(rohacellBase1, holeRohacell1, t11, t12); - if (Geometry::sGrooves == 1) + } + if (Geometry::sGrooves == 1) { rohacellBase = new TGeoSubtraction(rohacellGroove[iCount - 1], holeRohacell1, t11, t12); + } auto* rh1 = new TGeoCompositeShape(Form("rohacellBase1_D1_H%d", half), rohacellBase); auto* rohacellBaseWithHole = new TGeoVolume(Form("rohacellBaseWithHole_D1_H%d", half), rh1, mRohacell); @@ -1900,8 +1916,9 @@ void HeatExchanger::createHalfDisk1(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D1_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D1_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D1_H%d_%d", half, ipart), partRohacell0, mRohacell); + } } if (Geometry::sGrooves == 1) { if (ipart == (mNPart[disk] - 1)) { @@ -1909,8 +1926,9 @@ void HeatExchanger::createHalfDisk1(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D1_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D1_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D1_H%d_%d", half, ipart), rohacellGroove[iCount - 1], mRohacell); + } } //=========================================================================================================== @@ -1924,8 +1942,9 @@ void HeatExchanger::createHalfDisk1(Int_t half) TGeoTranslation* tinsert1; TGeoVolume* insert1 = gGeoManager->MakeBox(Form("insert1_H%d_%d", half, ipart), mPeek, 1.0, 0.35 / 2., mRohacellThickness); Double_t ylocation = mSupportYDimensions[disk][0] + mHalfDiskGap - 0.35 / 2.; - for (Int_t ip = 1; ip < mNPart[disk]; ip++) + for (Int_t ip = 1; ip < mNPart[disk]; ip++) { ylocation = ylocation + mSupportYDimensions[disk][ip]; + } tinsert1 = new TGeoTranslation("tinsert1", 0., -ylocation, 0.); tinsert1->RegisterYourself(); mHalfDisk->AddNode(insert1, 0., tinsert1); @@ -1946,12 +1965,13 @@ void HeatExchanger::createHalfDisk2(Int_t half) Int_t disk = 2; - if (half == Top) + if (half == Top) { printf("Creating MFT heat exchanger for disk2 top\n"); - else if (half == Bottom) + } else if (half == Bottom) { printf("Creating MFT heat exchanger for disk2 bottom\n"); - else + } else { printf("No valid option for MFT heat exchanger on disk2\n"); + } mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); @@ -2423,10 +2443,12 @@ void HeatExchanger::createHalfDisk2(Int_t half) // Passage du beam pipe TGeoBoolNode* rohacellBase; - if (Geometry::sGrooves == 0) + if (Geometry::sGrooves == 0) { rohacellBase = new TGeoSubtraction(rohacellBase2, holeRohacell2, t21, t22); - if (Geometry::sGrooves == 1) + } + if (Geometry::sGrooves == 1) { rohacellBase = new TGeoSubtraction(rohacellGroove[iCount - 1], holeRohacell2, t21, t22); + } auto* rh2 = new TGeoCompositeShape(Form("rohacellTore%d_D2_H%d", 0, half), rohacellBase); auto* rohacellBaseWithHole = new TGeoVolume(Form("rohacellBaseWithHole_D2_H%d", half), rh2, mRohacell); @@ -2547,8 +2569,9 @@ void HeatExchanger::createHalfDisk2(Int_t half) auto* rhinit2 = new TGeoCompositeShape(Form("rhinit2%d_D2_H%d", 0, half), partRohacellini2); partRohacell = new TGeoVolume(Form("partRohacelli_D2_H%d_%d", half, ipart), rhinit2, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D2_H%d_%d", half, ipart), partRohacell0, mRohacell); + } } if (Geometry::sGrooves == 1) { if (ipart == (mNPart[disk] - 1)) { @@ -2558,8 +2581,9 @@ void HeatExchanger::createHalfDisk2(Int_t half) auto* rhinit2 = new TGeoCompositeShape(Form("rhinit2%d_D2_H%d", 0, half), partRohacellini2); partRohacell = new TGeoVolume(Form("partRohacelli_D2_H%d_%d", half, ipart), rhinit2, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D2_H%d_%d", half, ipart), rohacellGroove[iCount - 1], mRohacell); + } } //=========================================================================================================== @@ -2573,8 +2597,9 @@ void HeatExchanger::createHalfDisk2(Int_t half) TGeoTranslation* tinsert2; TGeoVolume* insert2 = gGeoManager->MakeBox(Form("insert2_H%d_%d", half, ipart), mPeek, 1.0, 0.40 / 2., mRohacellThickness); Double_t ylocation = mSupportYDimensions[disk][0] + mHalfDiskGap - 0.80; - for (Int_t ip = 1; ip < mNPart[disk]; ip++) + for (Int_t ip = 1; ip < mNPart[disk]; ip++) { ylocation = ylocation + mSupportYDimensions[disk][ip]; + } tinsert2 = new TGeoTranslation("tinsert2", 0., -ylocation, 0.); tinsert2->RegisterYourself(); mHalfDisk->AddNode(insert2, 0., tinsert2); @@ -2595,12 +2620,13 @@ void HeatExchanger::createHalfDisk3(Int_t half) Int_t disk = 3; - if (half == Top) + if (half == Top) { printf("Creating MFT heat exchanger for disk3 top\n"); - else if (half == Bottom) + } else if (half == Bottom) { printf("Creating MFT heat exchanger for disk3 bottom\n"); - else + } else { printf("No valid option for MFT heat exchanger on disk3\n"); + } mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); @@ -2973,10 +2999,12 @@ void HeatExchanger::createHalfDisk3(Int_t half) // ********************************************************************************************************** // Passage du beam pipe TGeoBoolNode* rohacellBase; - if (Geometry::sGrooves == 0) + if (Geometry::sGrooves == 0) { rohacellBase = new TGeoSubtraction(rohacellBase3, holeRohacell3, t31, t32); - if (Geometry::sGrooves == 1) + } + if (Geometry::sGrooves == 1) { rohacellBase = new TGeoSubtraction(rohacellGroove[iCount - 1], holeRohacell3, t31, t32); + } auto* rh3 = new TGeoCompositeShape(Form("rohacellTore%d_D0_H%d", 0, half), rohacellBase); auto* rohacellBaseWithHole = new TGeoVolume(Form("rohacellBaseWithHole_D3_H%d", half), rh3, mRohacell); @@ -3091,8 +3119,9 @@ void HeatExchanger::createHalfDisk3(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D3_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D3_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D3_H%d_%d", half, ipart), partRohacell0, mRohacell); + } } if (Geometry::sGrooves == 1) { if (ipart == (mNPart[disk] - 1)) { @@ -3100,8 +3129,9 @@ void HeatExchanger::createHalfDisk3(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D3_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D3_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D3_H%d_%d", half, ipart), rohacellGroove[iCount - 1], mRohacell); + } } //=========================================================================================================== @@ -3114,8 +3144,9 @@ void HeatExchanger::createHalfDisk3(Int_t half) TGeoTranslation* tinsert3; TGeoVolume* insert3 = gGeoManager->MakeBox(Form("insert3_H%d_%d", half, ipart), mPeek, 4.0 / 2., 0.44 / 2., mRohacellThickness); Double_t ylocation = mSupportYDimensions[disk][0] + mHalfDiskGap + 0.44 / 2. - ynotch; - for (Int_t ip = 1; ip < mNPart[disk]; ip++) + for (Int_t ip = 1; ip < mNPart[disk]; ip++) { ylocation = ylocation + mSupportYDimensions[disk][ip]; + } tinsert3 = new TGeoTranslation("tinsert3", 0., -ylocation, 0.); tinsert3->RegisterYourself(); mHalfDisk->AddNode(insert3, 0., tinsert3); @@ -3137,12 +3168,13 @@ void HeatExchanger::createHalfDisk4(Int_t half) Int_t disk = 4; - if (half == Top) + if (half == Top) { printf("Creating MFT heat exchanger for disk4 top\n"); - else if (half == Bottom) + } else if (half == Bottom) { printf("Creating MFT heat exchanger for disk4 bottom\n"); - else + } else { printf("No valid option for MFT heat exchanger on disk4\n"); + } mCarbon = gGeoManager->GetMedium("MFT_CarbonFiber$"); mWater = gGeoManager->GetMedium("MFT_Water$"); @@ -3520,10 +3552,12 @@ void HeatExchanger::createHalfDisk4(Int_t half) // Passage du beam pipe TGeoBoolNode* rohacellBase; - if (Geometry::sGrooves == 0) + if (Geometry::sGrooves == 0) { rohacellBase = new TGeoSubtraction(rohacellBase4, holeRohacell4, t41, t42); - if (Geometry::sGrooves == 1) + } + if (Geometry::sGrooves == 1) { rohacellBase = new TGeoSubtraction(rohacellGroove[iCount - 1], holeRohacell4, t41, t42); + } auto* rh4 = new TGeoCompositeShape(Form("rohacellTore%d_D4_H%d", 0, half), rohacellBase); auto* rohacellBaseWithHole = new TGeoVolume(Form("rohacellBaseWithHole_D4_H%d", half), rh4, mRohacell); @@ -3638,8 +3672,9 @@ void HeatExchanger::createHalfDisk4(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D4_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D4_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D4_H%d_%d", half, ipart), partRohacell0, mRohacell); + } } if (Geometry::sGrooves == 1) { if (ipart == (mNPart[disk] - 1)) { @@ -3647,8 +3682,9 @@ void HeatExchanger::createHalfDisk4(Int_t half) auto* rhinit = new TGeoCompositeShape(Form("rhinit%d_D4_H%d", 0, half), partRohacellini); partRohacell = new TGeoVolume(Form("partRohacelli_D4_H%d_%d", half, ipart), rhinit, mRohacell); } - if (ipart < (mNPart[disk] - 1)) + if (ipart < (mNPart[disk] - 1)) { partRohacell = new TGeoVolume(Form("partRohacelli_D4_H%d_%d", half, ipart), rohacellGroove[iCount - 1], mRohacell); + } } //=========================================================================================================== //=========================================================================================================== @@ -3660,8 +3696,9 @@ void HeatExchanger::createHalfDisk4(Int_t half) TGeoTranslation* tinsert4; TGeoVolume* insert4 = gGeoManager->MakeBox(Form("insert4_H%d_%d", half, ipart), mPeek, 4.0 / 2., 0.44 / 2., mRohacellThickness); Double_t ylocation = mSupportYDimensions[disk][0] + mHalfDiskGap + 0.44 / 2. - ynotch; - for (Int_t ip = 1; ip < mNPart[disk]; ip++) + for (Int_t ip = 1; ip < mNPart[disk]; ip++) { ylocation = ylocation + mSupportYDimensions[disk][ip]; + } tinsert4 = new TGeoTranslation("tinsert4", 0., -ylocation, 0.); tinsert4->RegisterYourself(); mHalfDisk->AddNode(insert4, 0., tinsert4); @@ -3693,10 +3730,12 @@ void HeatExchanger::initParameters() } } - if (Geometry::sGrooves == 0) + if (Geometry::sGrooves == 0) { mRohacellThickness = mHeatExchangerThickness / 2. - 2. * mCarbonThickness - 2 * Geometry::sGlueRohacellCarbonThickness - 2 * Geometry::sKaptonOnCarbonThickness - 2 * Geometry::sKaptonGlueThickness - 2 * (mRWater + mDRPipe); // smaller rohacell thickness, no grooves - if (Geometry::sGrooves == 1) + } + if (Geometry::sGrooves == 1) { mRohacellThickness = mHeatExchangerThickness / 2. - 2. * mCarbonThickness - 2 * Geometry::sGlueRohacellCarbonThickness - 2 * Geometry::sKaptonOnCarbonThickness - 2 * Geometry::sKaptonGlueThickness; // with grooves + } mHalfDiskGap = 0.1; diff --git a/Detectors/ITSMFT/MFT/base/src/LadderSegmentation.cxx b/Detectors/ITSMFT/MFT/base/src/LadderSegmentation.cxx index 4ade7baad61bb..6791d13307e4d 100644 --- a/Detectors/ITSMFT/MFT/base/src/LadderSegmentation.cxx +++ b/Detectors/ITSMFT/MFT/base/src/LadderSegmentation.cxx @@ -53,10 +53,11 @@ LadderSegmentation::LadderSegmentation(const LadderSegmentation& ladder) { // copy constructor - if (ladder.mChips) + if (ladder.mChips) { mChips = new TClonesArray(*(ladder.mChips)); - else + } else { mChips = new TClonesArray("o2::mft::ChipSegmentation", mNSensors); + } mChips->SetOwner(kTRUE); } @@ -142,8 +143,9 @@ void LadderSegmentation::createSensors(TXMLEngine* xml, XMLNodePointer_t node) ChipSegmentation* LadderSegmentation::getSensor(Int_t sensorID) const { - if (sensorID < 0 || sensorID >= mNSensors) + if (sensorID < 0 || sensorID >= mNSensors) { return nullptr; + } ChipSegmentation* chip = (ChipSegmentation*)mChips->At(sensorID); @@ -159,7 +161,8 @@ void LadderSegmentation::print(Option_t* opt) getTransformation()->Print(); if (opt && (strstr(opt, "sensor") || strstr(opt, "s"))) { - for (int i = 0; i < getNSensors(); i++) + for (int i = 0; i < getNSensors(); i++) { getSensor(i)->Print(""); + } } } diff --git a/Detectors/ITSMFT/MFT/base/src/PCBSupport.cxx b/Detectors/ITSMFT/MFT/base/src/PCBSupport.cxx index 71112e3ee8e3f..e6d1ca89ca65a 100644 --- a/Detectors/ITSMFT/MFT/base/src/PCBSupport.cxx +++ b/Detectors/ITSMFT/MFT/base/src/PCBSupport.cxx @@ -56,21 +56,23 @@ TGeoVolumeAssembly* PCBSupport::create(Int_t half, Int_t disk) mSomeBox = new TGeoBBox(boxName, mBoxCuts[disk][cut][0] / 2. + 2 * mT_delta, mBoxCuts[disk][cut][1] / 2. + 2 * mT_delta, mFR4Thickness + mT_delta); mSomeTranslation = new TGeoTranslation(mBoxCuts[disk][cut][2], mBoxCuts[disk][cut][3], 0.); //The first subtraction needs a shape, the base tube - if (cut == 0) + if (cut == 0) { mSomeSubtraction = new TGeoSubtraction(PCBCu, mSomeBox, nullptr, mSomeTranslation); - else + } else { mSomeSubtraction = new TGeoSubtraction(mPCBCu, mSomeBox, nullptr, mSomeTranslation); + } mPCBCu = new TGeoCompositeShape(boxCSName, mSomeSubtraction); - if (cut == 0) + if (cut == 0) { mSomeSubtraction = new TGeoSubtraction(PCBFR4, mSomeBox, nullptr, mSomeTranslation); - else + } else { mSomeSubtraction = new TGeoSubtraction(mPCBFR4, mSomeBox, nullptr, mSomeTranslation); + } mPCBFR4 = new TGeoCompositeShape(boxCSName, mSomeSubtraction); } //Info("Create",Form("Cutting Boxes PCB_H%d_D%d", half,disk),0,0); - if (mNumberOfBoxAdd[disk] != 0) + if (mNumberOfBoxAdd[disk] != 0) { for (auto iBox = 0; iBox < mNumberOfBoxAdd[disk]; iBox++) { auto* boxName = Form("PCBBoxAdd_%d_H%d_D%d", iBox, half, disk); auto* boxCSName = Form("PCBBoxAddCS_%d_H%d_D%d", iBox, half, disk); @@ -82,6 +84,7 @@ TGeoVolumeAssembly* PCBSupport::create(Int_t half, Int_t disk) mSomeUnion = new TGeoUnion(mPCBCu, mSomeBox, nullptr, mSomeTranslation); mPCBCu = new TGeoCompositeShape(boxCSName, mSomeUnion); } + } // ================= Holes ================== diff --git a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx index ce227260a32d9..e780b4bacd467 100644 --- a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx +++ b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx @@ -567,10 +567,11 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() combtrans_DCDC_cover_inner_box_left->RegisterYourself(); combtrans_DCDC_cover_inner_box_right->RegisterYourself(); - if (iB == 0) + if (iB == 0) { name_DCDC_cover_box += Form("DCDC_cover_outer_box:combtrans_DCDC_cover_outer_box_No%d - DCDC_cover_inner_box:combtrans_DCDC_cover_inner_box_No%d", 2 * iB, 2 * iB); - else + } else { name_DCDC_cover_box += Form("+DCDC_cover_outer_box:combtrans_DCDC_cover_outer_box_No%d - DCDC_cover_inner_box:combtrans_DCDC_cover_inner_box_No%d", 2 * iB, 2 * iB); + } name_DCDC_cover_box += Form("+DCDC_cover_outer_box:combtrans_DCDC_cover_outer_box_No%d - DCDC_cover_inner_box:combtrans_DCDC_cover_inner_box_No%d", 2 * iB + 1, 2 * iB + 1); } @@ -629,10 +630,11 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() combtrans_DCDC_connector_box_left->RegisterYourself(); combtrans_DCDC_connector_box_right->RegisterYourself(); - if (iB == 0) + if (iB == 0) { name_DCDC_connector_box += Form("DCDC_connector_box:combtrans_DCDC_connector_box_No%d", 2 * iB); - else + } else { name_DCDC_connector_box += Form("+DCDC_connector_box:combtrans_DCDC_connector_box_No%d", 2 * iB); + } name_DCDC_connector_box += Form("+DCDC_connector_box:combtrans_DCDC_connector_box_No%d", 2 * iB + 1); } @@ -1060,10 +1062,11 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() combtrans_coil_torus_left->RegisterYourself(); combtrans_coil_torus_right->RegisterYourself(); - if (iB == 0) + if (iB == 0) { name_coil += Form("coil_torus:combtrans_coil_torus_No%d", 2 * iB); - else + } else { name_coil += Form("+coil_torus:combtrans_coil_torus_No%d", 2 * iB); + } name_coil += Form("+coil_torus:combtrans_coil_torus_No%d", 2 * iB + 1); } diff --git a/Detectors/ITSMFT/MFT/base/src/Segmentation.cxx b/Detectors/ITSMFT/MFT/base/src/Segmentation.cxx index 251b27c5d9f92..9da51d9a88b28 100644 --- a/Detectors/ITSMFT/MFT/base/src/Segmentation.cxx +++ b/Detectors/ITSMFT/MFT/base/src/Segmentation.cxx @@ -51,8 +51,9 @@ Segmentation::Segmentation(const Char_t* nameGeomFile) : mHalves(nullptr) Segmentation::~Segmentation() { - if (mHalves) + if (mHalves) { mHalves->Delete(); + } delete mHalves; } @@ -95,16 +96,18 @@ Int_t Segmentation::getDetElemLocalID(Int_t half, Int_t disk, Int_t ladder, Int_ Int_t localId = 0; - if (half == 1) + if (half == 1) { localId += getHalf(0)->getHalfDisk(disk)->getNChips(); + } for (Int_t iLad = 0; iLad < getHalf(half)->getHalfDisk(disk)->getNLadders(); iLad++) { if (iLad < ladder) { localId += getHalf(half)->getHalfDisk(disk)->getLadder(iLad)->getNSensors(); } else { for (Int_t iSens = 0; iSens < getHalf(half)->getHalfDisk(disk)->getLadder(iLad)->getNSensors(); iSens++) { - if (iSens == sensor) + if (iSens == sensor) { return localId; + } localId++; } } diff --git a/Detectors/ITSMFT/MFT/base/src/VSegmentation.cxx b/Detectors/ITSMFT/MFT/base/src/VSegmentation.cxx index 6f25b95e86f77..646cdf923b3ac 100644 --- a/Detectors/ITSMFT/MFT/base/src/VSegmentation.cxx +++ b/Detectors/ITSMFT/MFT/base/src/VSegmentation.cxx @@ -38,8 +38,9 @@ void VSegmentation::setRotationAngles(const Double_t* ang) { /// Set Rotation Angles - if (!mTransformation) + if (!mTransformation) { mTransformation = new TGeoCombiTrans(); + } auto* rot = new TGeoRotation(); rot->SetAngles(ang[0], ang[1], ang[2]); // all angles in degrees mTransformation->SetRotation(rot); diff --git a/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h b/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h index 8986b68c3f6a9..70d01ef726ef5 100644 --- a/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h +++ b/Detectors/ITSMFT/MFT/simulation/include/MFTSimulation/Detector.h @@ -92,10 +92,11 @@ class Detector : public o2::base::DetImpl<Detector> void createMaterials(); void setDensitySupportOverSi(Double_t density) { - if (density > 1e-6) + if (density > 1e-6) { mDensitySupportOverSi = density; - else + } else { mDensitySupportOverSi = 1e-6; + } } void createGeometry(); diff --git a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx index 1d4e1c33f8035..a1c934cc90aa3 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx @@ -111,8 +111,9 @@ Bool_t Detector::ProcessHits(FairVolume* vol) Int_t copy; // Check if hit is into a MFT sensor volume - if (fMC->CurrentVolID(copy) != mftGeo->getSensorVolumeID()) + if (fMC->CurrentVolID(copy) != mftGeo->getSensorVolumeID()) { return kFALSE; + } // Get The Sensor Unique ID Int_t sensorID = -1, ladderID = -1, diskID = -1, halfID = -1, level = 0; @@ -155,10 +156,12 @@ Bool_t Detector::ProcessHits(FairVolume* vol) } // increment energy loss at all steps except entrance - if (!startHit) + if (!startHit) { mTrackData.mEnergyLoss += fMC->Edep(); - if (!(startHit | stopHit)) + } + if (!(startHit | stopHit)) { return kFALSE; // do noting + } if (startHit) { @@ -263,10 +266,12 @@ void Detector::createMaterials() Float_t zRohacell[nRohacell] = {1., 6., 8.}; Float_t wRohacell[nRohacell] = {0.0858, 0.5964, 0.3178}; Float_t dRohacell; - if (Geometry::sGrooves == 0) + if (Geometry::sGrooves == 0) { dRohacell = 0.032 / (1 - 0.15); // No grooves, water pipes outside rohacell ==> smaller thcikness, greater rohacell density by 15% - if (Geometry::sGrooves == 1) + } + if (Geometry::sGrooves == 1) { dRohacell = 0.032; // With grooves, usual rohacell density: 0.032 g/cm3 rohacell 31, 0.075 g/cm3 rohacell 71; + } // Polyimide pipe mixture const Int_t nPolyimide = 4; diff --git a/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx b/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx index 109c3d2056b00..4158628616e16 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx @@ -209,8 +209,9 @@ void setupLinks(o2::itsmft::MC2RawEncoder<MAP>& m2r, std::string_view outDir, st for (int ir = 0; ir < nruLr; ir++) { - if (h != (ir / 4)) + if (h != (ir / 4)) { continue; + } // RU software id ruSW = nruLr * ilr + (nruLr / 2) * (ir / 4) + (ir % 4); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index 19f27a6a19f55..779c75efe27f5 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -114,11 +114,12 @@ inline void TrackLTF::setPoint(const Cluster cl, const Int_t layer, const Int_t { auto nPoints = getNumberOfPoints(); if (newPoint) { - if (nPoints > 0) + if (nPoints > 0) { if (mZ[nPoints - 1] == cl.getZ()) { LOG(WARN) << "MFT TrackLTF: skipping setPoint (1 cluster per layer!)"; return; } + } if (nPoints > constants::mft::LayersNumber) { LOG(WARN) << "MFT TrackLTF Overflow"; return; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index e72c6c62eecfa..45b0fc2792eba 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -130,8 +130,9 @@ inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t l inline Bool_t Tracker::getBinClusterRange(const ROframe& event, const Int_t layer, const Int_t bin, Int_t& clsMinIndex, Int_t& clsMaxIndex) const { const auto pair2 = event.getClusterBinIndexRange(layer).find(bin); - if (pair2 == event.getClusterBinIndexRange(layer).end()) + if (pair2 == event.getClusterBinIndexRange(layer).end()) { return kFALSE; + } Int_t binIndex = pair2->first; // get the range in ordered cluster index within this bin std::pair<Int_t, Int_t> pair1 = pair2->second; @@ -272,8 +273,9 @@ inline void Tracker::computeTracksMClabels(const T& tracks) } count = 0; for (int iCluster = 0; iCluster < nClusters; ++iCluster) { - if (track.getMCCompLabels()[iCluster] == maxOccurrencesValue) + if (track.getMCCompLabels()[iCluster] == maxOccurrencesValue) { count++; + } } auto labelratio = 1.0 * count / nClusters; diff --git a/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx b/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx index bd4f39c7863ee..78aedf7fea6d3 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx @@ -27,8 +27,9 @@ ROframe::ROframe(const Int_t ROframeId) : mROframeId{ROframeId} Int_t ROframe::getTotalClusters() const { size_t totalClusters{0}; - for (auto& clusters : mClusters) + for (auto& clusters : mClusters) { totalClusters += clusters.size(); + } return Int_t(totalClusters); } @@ -47,8 +48,9 @@ void ROframe::sortClusters() Int_t nClsInLayer, binPrevIndex, clsMinIndex, clsMaxIndex, jClsLayer; // sort the clusters in R-Phi for (Int_t iLayer = 0; iLayer < constants::mft::LayersNumber; ++iLayer) { - if (mClusters[iLayer].size() == 0) + if (mClusters[iLayer].size() == 0) { continue; + } // sort clusters in layer according to the bin index sort(mClusters[iLayer].begin(), mClusters[iLayer].end(), [](Cluster& c1, Cluster& c2) { return c1.indexTableBin < c2.indexTableBin; }); @@ -58,8 +60,9 @@ void ROframe::sortClusters() binPrevIndex = mClusters[iLayer].at(0).indexTableBin; clsMinIndex = 0; for (jClsLayer = 1; jClsLayer < nClsInLayer; ++jClsLayer) { - if (mClusters[iLayer].at(jClsLayer).indexTableBin == binPrevIndex) + if (mClusters[iLayer].at(jClsLayer).indexTableBin == binPrevIndex) { continue; + } clsMaxIndex = jClsLayer - 1; std::pair<Int_t, Int_t> pair1(clsMinIndex, clsMaxIndex); mClusterBinIndexRange[iLayer].insert(std::pair<Int_t, std::pair<Int_t, Int_t>>(binPrevIndex, pair1)); diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx index cc276aa9b0ee9..e21d0bc11c2bd 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx @@ -241,8 +241,9 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) LOG(INFO) << "track.getZ() = " << track.getZ() << " ; newClusterZ = " << clz << " ==> Skipping point."; return true; } - if (mftTrackingParam.verbose) + if (mftTrackingParam.verbose) { std::cout << "computeCluster: X = " << clx << " Y = " << cly << " Z = " << clz << " nCluster = " << cluster << std::endl; + } // add MCS effects for the new cluster using o2::mft::constants::LayerZPosition; @@ -250,18 +251,23 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) auto dZ = clz - track.getZ(); //LayerID of each cluster from ZPosition // TODO: Use ChipMapping - for (auto layer = 10; layer--;) - if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3) + for (auto layer = 10; layer--;) { + if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3) { startingLayerID = layer; - for (auto layer = 10; layer--;) - if (clz<LayerZPosition[layer] + .3 & clz> LayerZPosition[layer] - .3) + } + } + for (auto layer = 10; layer--;) { + if (clz<LayerZPosition[layer] + .3 & clz> LayerZPosition[layer] - .3) { newLayerID = layer; + } + } // Number of disks crossed by this tracklet int NDisksMS; - if (clz - track.getZ() > 0) + if (clz - track.getZ() > 0) { NDisksMS = (startingLayerID % 2 == 0) ? (startingLayerID - newLayerID) / 2 : (startingLayerID - newLayerID + 1) / 2; - else + } else { NDisksMS = (startingLayerID % 2 == 0) ? (newLayerID - startingLayerID + 1) / 2 : (newLayerID - startingLayerID) / 2; + } auto MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLength / 5.0; if (mftTrackingParam.verbose) { @@ -272,11 +278,13 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) std::cout << "NDisksMS = " << NDisksMS << std::endl; } - if ((NDisksMS * MFTDiskThicknessInX0) != 0) + if ((NDisksMS * MFTDiskThicknessInX0) != 0) { track.addMCSEffect(-1, NDisksMS * MFTDiskThicknessInX0); + } - if (mftTrackingParam.verbose) + if (mftTrackingParam.verbose) { std::cout << " BeforeExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + } // Propagate track to the z position of the new cluster switch (mftTrackingParam.trackmodel) { @@ -295,8 +303,9 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster) break; } - if (mftTrackingParam.verbose) + if (mftTrackingParam.verbose) { std::cout << " AfterExtrap: X = " << track.getX() << " Y = " << track.getY() << " Z = " << track.getZ() << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl; + } // recompute parameters const std::array<float, 2>& pos = {clx, cly}; @@ -473,8 +482,9 @@ Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yE SX += xVal[i] * invYErr2; SY += yVal[i] * invYErr2; SXX += xVal[i] * xVal[i] * invYErr2; - if (i > 0) + if (i > 0) { difx += TMath::Abs(xVal[i] - xVal[i - 1]); + } Xm += xVal[i]; Ym += yVal[i]; SsXX += xVal[i] * xVal[i]; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index 65793fba75579..acc564d173544 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -250,8 +250,9 @@ void Tracker::findTracksLTF(ROframe& event) } nPointDisks = 0; for (Int_t disk = 0; disk < (constants::mft::DisksNumber); ++disk) { - if (hasDisk[disk]) + if (hasDisk[disk]) { ++nPointDisks; + } } if (nPointDisks < constants::mft::MinTrackPoints) { event.removeCurrentTrackLTF(); @@ -409,8 +410,9 @@ void Tracker::findTracksCA(ROframe& event) } nPointDisks = 0; for (Int_t disk = 0; disk < (constants::mft::DisksNumber); ++disk) { - if (hasDisk[disk]) + if (hasDisk[disk]) { ++nPointDisks; + } } if (nPointDisks < constants::mft::MinTrackPoints) { event.removeCurrentRoad(); @@ -526,8 +528,9 @@ void Tracker::runForwardInRoad(ROframe& event) //_________________________________________________________________________________________________ void Tracker::runBackwardInRoad(ROframe& event) { - if (mMaxCellLevel == 1) + if (mMaxCellLevel == 1) { return; // we have only isolated cells + } Bool_t addCellToNewTrack, hasDisk[constants::mft::DisksNumber]; @@ -833,8 +836,9 @@ const Bool_t Tracker::LinearRegression(Int_t npoints, Float_t* x, Float_t* y, Fl SX += xCl[i] / (yClErr[i] * yClErr[i]); SY += yCl[i] / (yClErr[i] * yClErr[i]); SXX += xCl[i] * xCl[i] / (yClErr[i] * yClErr[i]); - if (i > 0) + if (i > 0) { difx += TMath::Abs(xCl[i] - xCl[i - 1]); + } Xm += xCl[i]; Ym += yCl[i]; SsXX += xCl[i] * xCl[i]; diff --git a/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx index cb6318809c17a..896aacf27d59b 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/ClusterReaderSpec.cxx @@ -45,8 +45,9 @@ void ClusterReader::init(InitContext& ic) void ClusterReader::run(ProcessingContext& pc) { - if (mState != 1) + if (mState != 1) { return; + } std::unique_ptr<TTree> tree((TTree*)mFile->Get("o2sim")); diff --git a/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx index e185fc6bcd69d..7baf9b858ab9a 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/DigitReaderSpec.cxx @@ -46,8 +46,9 @@ void DigitReader::init(InitContext& ic) void DigitReader::run(ProcessingContext& pc) { - if (mState != 1) + if (mState != 1) { return; + } std::unique_ptr<TTree> treeDig((TTree*)mFile->Get("o2sim")); diff --git a/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h b/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h index 658a5c1175305..394aa268d410c 100644 --- a/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h +++ b/Detectors/ITSMFT/common/base/include/ITSMFTBase/SegmentationAlpide.h @@ -104,10 +104,12 @@ inline void SegmentationAlpide::localToDetectorUnchecked(float xRow, float zCol, zCol += 0.5 * ActiveMatrixSizeCols; // coordinate wrt left edge of Active matrix iRow = int(xRow / PitchRow); iCol = int(zCol / PitchCol); - if (xRow < 0) + if (xRow < 0) { iRow -= 1; - if (zCol < 0) + } + if (zCol < 0) { iCol -= 1; + } } //_________________________________________________________________________________________________ @@ -148,8 +150,9 @@ inline void SegmentationAlpide::detectorToLocalUnchecked(float row, float col, m //_________________________________________________________________________________________________ inline bool SegmentationAlpide::detectorToLocal(int iRow, int iCol, float& xRow, float& zCol) { - if (iRow < 0 || iRow >= NRows || iCol < 0 || iCol >= NCols) + if (iRow < 0 || iRow >= NRows || iCol < 0 || iCol >= NCols) { return false; + } detectorToLocalUnchecked(iRow, iCol, xRow, zCol); return true; } @@ -157,8 +160,9 @@ inline bool SegmentationAlpide::detectorToLocal(int iRow, int iCol, float& xRow, //_________________________________________________________________________________________________ inline bool SegmentationAlpide::detectorToLocal(float row, float col, float& xRow, float& zCol) { - if (row < 0 || row >= NRows || col < 0 || col >= NCols) + if (row < 0 || row >= NRows || col < 0 || col >= NCols) { return false; + } detectorToLocalUnchecked(row, col, xRow, zCol); return true; } @@ -166,8 +170,9 @@ inline bool SegmentationAlpide::detectorToLocal(float row, float col, float& xRo //_________________________________________________________________________________________________ inline bool SegmentationAlpide::detectorToLocal(float row, float col, math_utils::Point3D<float>& loc) { - if (row < 0 || row >= NRows || col < 0 || col >= NCols) + if (row < 0 || row >= NRows || col < 0 || col >= NCols) { return false; + } detectorToLocalUnchecked(row, col, loc); return true; } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h index ae278d79e3e0b..feafb6298bf23 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h @@ -214,8 +214,9 @@ class ChipMappingITS { int sid = 0; for (int i = 0; i < NLayers; i++) { - if (i >= lr) + if (i >= lr) { break; + } sid += NStavesOnLr[i]; } return sid + ruOnLr; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h index 2075290916818..e87c5b44be6c2 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h @@ -209,8 +209,9 @@ class ChipMappingMFT { int sid = 0; for (int i = 0; i < NLayers; i++) { - if (i >= layer) + if (i >= layer) { break; + } sid += NZonesPerLayer; } return sid + ruOnLayer; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h index c09bf6d5bac89..ac61b0af3f71d 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h @@ -302,10 +302,12 @@ class RawPixelReader : public PixelReader auto& pixels = chipData.getData(); std::sort(pixels.begin(), pixels.end(), [](auto lhs, auto rhs) { - if (lhs.getRow() < rhs.getRow()) + if (lhs.getRow() < rhs.getRow()) { return true; - if (lhs.getRow() > rhs.getRow()) + } + if (lhs.getRow() > rhs.getRow()) { return false; + } return lhs.getCol() < rhs.getCol(); }); ruData.cableData[chip.cableHWPos].ensureFreeCapacity(40 * (2 + pixels.size())); // make sure buffer has enough capacity diff --git a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx index f22604766f14d..0e553517db7de 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx @@ -83,10 +83,11 @@ void BuildTopologyDictionary::setThreshold(double thr) mDictionary.mGroupMap.clear(); mFrequencyThreshold = thr; for (auto& q : mTopologyFrequency) { - if (((double)q.first) / mTotClusters > thr) + if (((double)q.first) / mTotClusters > thr) { mNCommonTopologies++; - else + } else { break; + } } } @@ -108,8 +109,9 @@ void BuildTopologyDictionary::setNCommon(unsigned int nCommon) void BuildTopologyDictionary::setThresholdCumulative(double cumulative) { mTopologyFrequency.clear(); - if (cumulative <= 0. || cumulative >= 1.) + if (cumulative <= 0. || cumulative >= 1.) { cumulative = 0.99; + } double totFreq = 0.; for (auto&& p : mTopologyMap) { // p os pair<ulong,TopoStat> mTopologyFrequency.emplace_back(std::make_pair(p.second.countsTotal, p.first)); @@ -124,12 +126,14 @@ void BuildTopologyDictionary::setThresholdCumulative(double cumulative) totFreq += ((double)(q.first)) / mTotClusters; if (totFreq < cumulative) { mNCommonTopologies++; - } else + } else { break; + } } mFrequencyThreshold = ((double)(mTopologyFrequency[--mNCommonTopologies].first)) / mTotClusters; - while (std::fabs(((double)mTopologyFrequency[mNCommonTopologies].first) / mTotClusters - mFrequencyThreshold) < 1.e-15) + while (std::fabs(((double)mTopologyFrequency[mNCommonTopologies].first) / mTotClusters - mFrequencyThreshold) < 1.e-15) { mNCommonTopologies--; + } mFrequencyThreshold = ((double)mTopologyFrequency[mNCommonTopologies++].first) / mTotClusters; } @@ -229,8 +233,9 @@ void BuildTopologyDictionary::groupRareTopologies() GroupStruct& gr = mDictionary.mVectorOfIDs[iKey]; if (!gr.mIsGroup) { mDictionary.mCommonMap.insert(std::make_pair(gr.mHash, iKey)); - if (gr.mPattern.getUsedBytes() == 1) + if (gr.mPattern.getUsedBytes() == 1) { mDictionary.mSmallTopologiesLUT[(gr.mPattern.getColumnSpan() - 1) * 255 + (int)gr.mPattern.mBitmap[2]] = iKey; + } } else { mDictionary.mGroupMap.insert(std::make_pair((int)(gr.mHash >> 32) & 0x00000000ffffffff, iKey)); } diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index 3def2b727f23a..60bb389ad93ee 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -253,12 +253,14 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus LOG(WARNING) << "Splitting a huge cluster ! ChipID: " << chipID; colSpan %= o2::itsmft::ClusterPattern::MaxColSpan; - if (colSpan == 0) + if (colSpan == 0) { colSpan = o2::itsmft::ClusterPattern::MaxColSpan; + } rowSpan %= o2::itsmft::ClusterPattern::MaxRowSpan; - if (rowSpan == 0) + if (rowSpan == 0) { rowSpan = o2::itsmft::ClusterPattern::MaxRowSpan; + } do { uint16_t r = rowMin, rsp = rowSpan; @@ -315,8 +317,9 @@ void Clusterer::ClustererThread::streamCluster(const std::vector<PixelData>& pix patternsPtr->emplace_back((unsigned char)rowSpanW); patternsPtr->emplace_back((unsigned char)colSpanW); int nBytes = rowSpanW * colSpanW / 8; - if (((rowSpanW * colSpanW) % 8) != 0) + if (((rowSpanW * colSpanW) % 8) != 0) { nBytes++; + } patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + nBytes); } } diff --git a/Detectors/ITSMFT/common/reconstruction/src/DigitPixelReader.cxx b/Detectors/ITSMFT/common/reconstruction/src/DigitPixelReader.cxx index f69a93a0f020d..44fd0cb25f224 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/DigitPixelReader.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/DigitPixelReader.cxx @@ -125,8 +125,9 @@ bool DigitPixelReader::readNextEntry() // load next entry from the self-managed input auto nev = mInputTree->GetEntries(); auto evID = mInputTree->GetReadEntry(); - if (evID < -1) + if (evID < -1) { evID = -1; + } if (++evID < nev) { init(); mInputTree->GetEntry(evID); diff --git a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx index d8bbc3781db9f..ee7f6be12ee32 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx @@ -62,9 +62,9 @@ int LookUp::findGroupID(int nRow, int nCol, const unsigned char patt[ClusterPatt // Small topology if (nBits < 9) { int ID = mDictionary.mSmallTopologiesLUT[(nCol - 1) * 255 + (int)patt[0]]; - if (ID >= 0) + if (ID >= 0) { return ID; - else { //small rare topology (inside groups) + } else { //small rare topology (inside groups) int index = groupFinder(nRow, nCol); return mDictionary.mGroupMap[index]; } @@ -72,9 +72,9 @@ int LookUp::findGroupID(int nRow, int nCol, const unsigned char patt[ClusterPatt // Big topology unsigned long hash = ClusterTopology::getCompleteHash(nRow, nCol, patt); auto ret = mDictionary.mCommonMap.find(hash); - if (ret != mDictionary.mCommonMap.end()) + if (ret != mDictionary.mCommonMap.end()) { return ret->second; - else { // Big rare topology (inside groups) + } else { // Big rare topology (inside groups) int index = groupFinder(nRow, nCol); return mDictionary.mGroupMap[index]; } diff --git a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/ClusterShape.h b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/ClusterShape.h index 05480b06afc12..3d6b85a459fcc 100644 --- a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/ClusterShape.h +++ b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/ClusterShape.h @@ -109,8 +109,9 @@ class ClusterShape : public TObject std::stringstream out; for (UInt_t i = 0; i < shape.size(); ++i) { out << shape[i]; - if (i < shape.size() - 1) + if (i < shape.size() - 1) { out << " "; + } } return out.str(); } @@ -121,21 +122,26 @@ class ClusterShape : public TObject for (Int_t r = -1; r < (Int_t)v.mNrows; ++r) { for (UInt_t c = 0; c < v.mNcols; ++c) { if (r == -1) { - if (c == 0) + if (c == 0) { out << " "; + } out << c; - if (c < v.mNcols - 1) + if (c < v.mNcols - 1) { out << " "; + } } else { - if (c == 0) + if (c == 0) { out << r << " "; + } index = r * v.mNcols + c; - if (std::find(begin(v.mShape), end(v.mShape), index) != end(v.mShape)) + if (std::find(begin(v.mShape), end(v.mShape), index) != end(v.mShape)) { out << "X"; - else + } else { out << " "; - if (c < v.mNcols - 1) + } + if (c < v.mNcols - 1) { out << " "; + } } } out << std::endl; diff --git a/Detectors/ITSMFT/common/simulation/src/AlpideChip.cxx b/Detectors/ITSMFT/common/simulation/src/AlpideChip.cxx index bd623967fc7d9..6b643b7d0a01f 100644 --- a/Detectors/ITSMFT/common/simulation/src/AlpideChip.cxx +++ b/Detectors/ITSMFT/common/simulation/src/AlpideChip.cxx @@ -94,10 +94,11 @@ TGeoVolume* AlpideChip::createChip(const Double_t ychip, TGeoMedium* medChip; - if (dummy) + if (dummy) { medChip = medAir; - else + } else { medChip = medSi; + } TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medChip); chipVol->SetVisibility(kTRUE); diff --git a/Detectors/ITSMFT/common/simulation/src/AlpideSimResponse.cxx b/Detectors/ITSMFT/common/simulation/src/AlpideSimResponse.cxx index af4db658eeab4..4557bc97b1ebf 100644 --- a/Detectors/ITSMFT/common/simulation/src/AlpideSimResponse.cxx +++ b/Detectors/ITSMFT/common/simulation/src/AlpideSimResponse.cxx @@ -73,8 +73,9 @@ void AlpideSimResponse::initData() LOG(FATAL) << "Failed to open file " << inpfname; } - while (inpGrid >> mStepInvRow && inpGrid.good()) + while (inpGrid >> mStepInvRow && inpGrid.good()) { mNBinRow++; + } if (!mNBinRow || mStepInvRow < kTiny) { LOG(FATAL) << "Failed to read Y(row) binning from " << inpfname; } @@ -130,15 +131,18 @@ void AlpideSimResponse::initData() << iz << " from " << inpfname; } - if (mDptMax < -1e9) + if (mDptMax < -1e9) { mDptMax = gz; - if (mDptMin > gz) + } + if (mDptMin > gz) { mDptMin = gz; + } // normalize float norm = 1.f / nele; - for (int ip = npix * npix; ip--;) + for (int ip = npix * npix; ip--;) { (*arr)[ip] *= norm; + } mData.push_back(mat); // store in the final container } // loop over z @@ -206,20 +210,23 @@ bool AlpideSimResponse::getResponse(float vRow, float vCol, float vDepth, Alpide LOG(FATAL) << "response object is not initialized"; } bool flipCol = false, flipRow = true; - if (vDepth < mDptMin || vDepth > mDptMax) + if (vDepth < mDptMin || vDepth > mDptMax) { return false; + } if (vCol < 0) { vCol = -vCol; flipCol = true; } - if (vCol > mColMax) + if (vCol > mColMax) { return false; + } if (vRow < 0) { vRow = -vRow; flipRow = false; } - if (vRow > mRowMax) + if (vRow > mRowMax) { return false; + } size_t bin = getDepthBin(vDepth) + mNBinDpt * (getRowBin(vRow) + mNBinRow * getColBin(vCol)); if (bin >= mData.size()) { @@ -245,24 +252,27 @@ const AlpideRespSimMat* AlpideSimResponse::getResponse(float vRow, float vCol, f if (!mNBinDpt) { LOG(FATAL) << "response object is not initialized"; } - if (vDepth < mDptMin || vDepth > mDptMax) + if (vDepth < mDptMin || vDepth > mDptMax) { return nullptr; + } if (vCol < 0) { vCol = -vCol; flipCol = true; } else { flipCol = false; } - if (vCol > mColMax) + if (vCol > mColMax) { return nullptr; + } if (vRow < 0) { vRow = -vRow; flipRow = false; } else { flipRow = true; } - if (vRow > mRowMax) + if (vRow > mRowMax) { return nullptr; + } size_t bin = getDepthBin(vDepth) + mNBinDpt * (getRowBin(vRow) + mNBinRow * getColBin(vCol)); if (bin >= mData.size()) { diff --git a/Detectors/ITSMFT/common/simulation/src/ClusterShape.cxx b/Detectors/ITSMFT/common/simulation/src/ClusterShape.cxx index 4b4e3b6ab1dcf..0a0b2f0cdde37 100644 --- a/Detectors/ITSMFT/common/simulation/src/ClusterShape.cxx +++ b/Detectors/ITSMFT/common/simulation/src/ClusterShape.cxx @@ -56,16 +56,19 @@ ClusterShape::~ClusterShape() = default; Bool_t ClusterShape::IsValidShape() { // Check the size - if (mShape.size() > mNrows * mNcols) + if (mShape.size() > mNrows * mNcols) { return false; + } // Check for duplicates and the validity of the position std::sort(mShape.begin(), mShape.end()); for (size_t i = 0; i < mShape.size() - 1; i++) { - if (mShape[i] >= mNrows * mNcols || mShape[i + 1] >= mNrows * mNcols) + if (mShape[i] >= mNrows * mNcols || mShape[i + 1] >= mNrows * mNcols) { return false; - if (mShape[i] == mShape[i + 1]) + } + if (mShape[i] == mShape[i + 1]) { return false; + } } return true; @@ -88,10 +91,12 @@ Long64_t ClusterShape::GetShapeID() const Bool_t ClusterShape::HasElement(UInt_t value) const { for (auto& el : mShape) { - if (el > value) + if (el > value) { break; - if (el == value) + } + if (el == value) { return true; + } } return false; } diff --git a/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx b/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx index 67e515a35e22d..d18d55d1476b7 100644 --- a/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx +++ b/Detectors/ITSMFT/common/simulation/src/Digitizer.cxx @@ -361,10 +361,12 @@ void Digitizer::registerDigits(ChipDigitsContainer& chip, UInt_t roFrame, float if (nEleROF < mParams.getMinChargeToAccount()) { continue; } - if (roFr > mEventROFrameMax) + if (roFr > mEventROFrameMax) { mEventROFrameMax = roFr; - if (roFr < mEventROFrameMin) + } + if (roFr < mEventROFrameMin) { mEventROFrameMin = roFr; + } auto key = chip.getOrderingKey(roFr, row, col); PreDigit* pd = chip.findDigit(key); if (!pd) { diff --git a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx index 938df2ab07827..2b8ce3edbd0f6 100644 --- a/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx +++ b/Detectors/ITSMFT/test/HitAnalysis/src/HitAnalysis.cxx @@ -81,8 +81,9 @@ InitStatus HitAnalysis::Init() // Create geometry, initialize chip array GeometryTGeo* geom = GeometryTGeo::Instance(); - if (!geom->isBuilt()) + if (!geom->isBuilt()) { geom->Build(true); + } geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure T2L matrices are loaded mGeometry = geom; From 9fb55b428f88ff0b86ef361d7d8412575b2e5d10 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Fri, 30 Oct 2020 00:32:46 +0300 Subject: [PATCH 1163/1751] Detectors/MUON,PHOS,Passive: make readability-braces-around-statements happy --- .../PreClustering/src/PreClusterFinder.cxx | 12 +- .../MUON/MCH/Simulation/src/Digitizer.cxx | 6 +- .../MUON/MCH/Simulation/src/Response.cxx | 12 +- .../MCH/Simulation/src/Station1Geometry.cxx | 36 +++-- .../MCH/Simulation/src/Station2Geometry.cxx | 12 +- .../MCH/Simulation/src/Station345Geometry.cxx | 18 ++- .../MCH/Simulation/test/testDigitization.cxx | 18 ++- .../Tracking/include/MCHTracking/TrackParam.h | 3 +- .../MUON/MCH/Tracking/src/TrackParam.cxx | 128 +++++++++++------- .../MUON/MCH/Workflow/src/DataDecoderSpec.cxx | 3 +- Detectors/MUON/MID/Base/src/MpArea.cxx | 3 +- Detectors/MUON/MID/Raw/test/testRaw.cxx | 4 +- .../MUON/MID/Simulation/test/testGeometry.cxx | 9 +- Detectors/PHOS/base/src/Geometry.cxx | 6 +- Detectors/PHOS/base/src/Hit.cxx | 9 +- Detectors/PHOS/calib/src/BadChannelMap.cxx | 3 +- Detectors/PHOS/calib/src/CalibDB.cxx | 30 ++-- .../PHOS/reconstruction/src/Clusterer.cxx | 12 +- .../PHOS/reconstruction/src/FullCluster.cxx | 13 +- .../include/PHOSSimulation/Detector.h | 5 +- Detectors/PHOS/simulation/src/Detector.cxx | 9 +- .../PHOS/workflow/src/CellConverterSpec.cxx | 5 +- Detectors/PHOS/workflow/src/RecoWorkflow.cxx | 3 +- Detectors/Passive/src/Absorber.cxx | 3 +- Detectors/Passive/src/Cave.cxx | 3 +- Detectors/Passive/src/Compensator.cxx | 3 +- Detectors/Passive/src/Dipole.cxx | 3 +- Detectors/Passive/src/FrameStructure.cxx | 72 ++++++---- Detectors/Passive/src/Hall.cxx | 3 +- Detectors/Passive/src/Magnet.cxx | 3 +- Detectors/Passive/src/Pipe.cxx | 15 +- Detectors/Passive/src/Shil.cxx | 15 +- 32 files changed, 314 insertions(+), 165 deletions(-) diff --git a/Detectors/MUON/MCH/PreClustering/src/PreClusterFinder.cxx b/Detectors/MUON/MCH/PreClustering/src/PreClusterFinder.cxx index 03e6261bf5708..608aef049b23f 100644 --- a/Detectors/MUON/MCH/PreClustering/src/PreClusterFinder.cxx +++ b/Detectors/MUON/MCH/PreClustering/src/PreClusterFinder.cxx @@ -256,14 +256,18 @@ void PreClusterFinder::addPad(DetectionElement& de, uint16_t iPad, PreCluster& c } cluster.lastPad = de.nOrderedPads[0]; ++de.nOrderedPads[0]; - if (pad.area[0][0] < cluster.area[0][0]) + if (pad.area[0][0] < cluster.area[0][0]) { cluster.area[0][0] = pad.area[0][0]; - if (pad.area[0][1] > cluster.area[0][1]) + } + if (pad.area[0][1] > cluster.area[0][1]) { cluster.area[0][1] = pad.area[0][1]; - if (pad.area[1][0] < cluster.area[1][0]) + } + if (pad.area[1][0] < cluster.area[1][0]) { cluster.area[1][0] = pad.area[1][0]; - if (pad.area[1][1] > cluster.area[1][1]) + } + if (pad.area[1][1] > cluster.area[1][1]) { cluster.area[1][1] = pad.area[1][1]; + } pad.useMe = false; diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index 57e68a0ba9bec..953afa8015625 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -249,8 +249,9 @@ void Digitizer::mergeDigits(std::vector<Digit>& digits, o2::dataformats::MCTruth void Digitizer::fillOutputContainer(std::vector<Digit>& digits) { // filling the digit container - if (mDigits.empty()) + if (mDigits.empty()) { return; + } digits.clear(); digits.reserve(mDigits.size()); @@ -285,8 +286,9 @@ void Digitizer::provideMC(o2::dataformats::MCTruthContainer<o2::MCCompLabel>& mc { //fill MCtruth info mcContainer.clear(); - if (mMCTruthOutputContainer.getNElements() == 0) + if (mMCTruthOutputContainer.getNElements() == 0) { return; + } //need to fill groups of labels not only single labels, since index in addElements // is the data index diff --git a/Detectors/MUON/MCH/Simulation/src/Response.cxx b/Detectors/MUON/MCH/Simulation/src/Response.cxx index e9511ea0e517c..4bb0c73703ab5 100644 --- a/Detectors/MUON/MCH/Simulation/src/Response.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Response.cxx @@ -69,12 +69,14 @@ float Response::etocharge(float edepos) //expression in PH, i.e. ADC! int nel = int(edepos * 1.e9 / 27.4); float charge = 0; - if (nel == 0) + if (nel == 0) { nel = 1; + } for (int i = 1; i <= nel; i++) { float arg = 0.; - while (!arg) + while (!arg) { arg = gRandom->Rndm(); + } charge -= mChargeSlope * TMath::Log(arg); } //no translation to fC, as in Aliroot @@ -117,10 +119,12 @@ unsigned long Response::response(unsigned long adc) adc = TMath::Nint(adc_out + pedestalMean + adcNoise + 0.5); - if (adc_out < TMath::Nint(pedestalMean + fgNSigma * pedestalSigma + 0.5)) + if (adc_out < TMath::Nint(pedestalMean + fgNSigma * pedestalSigma + 0.5)) { adc = 0; - if (adc > mMaxADC) + } + if (adc > mMaxADC) { adc = mMaxADC; + } return adc; } //______________________________________________________________________ diff --git a/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx b/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx index 426df458f1134..046f16d23f5f0 100644 --- a/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx @@ -674,8 +674,9 @@ void createFrame(int chamber) vy[15] = 0.; // shift center in the middle - for (int i = 0; i < nv; i++) + for (int i = 0; i < nv; i++) { vy[i] += dy4 / 2; + } TGeoXtru* xtruS1 = new TGeoXtru(nz); xtruS1->DefinePolygon(nv, vx, vy); @@ -1119,8 +1120,9 @@ void createFrame(int chamber) x = kDeltaQuadLHC + scruX[i] + 0.1; y = kDeltaQuadLHC + scruY[i] + 0.1; Mlayer->AddNode(vol43, i + 1, new TGeoTranslation(x, y, z - kHzInHFrame - kSCRUHLE)); - if (chamber == 1) + if (chamber == 1) { gGeoManager->GetVolume("SQ40")->AddNode(vol44, i + 1, new TGeoTranslation(x - kMidHXPos, y - kMidHYPos, z - kMidHZPos)); + } Mlayer->AddNode(vol45, i + 1, new TGeoTranslation(x, y, z + kHzInHFrame + kSCRUNLE)); } @@ -1134,8 +1136,9 @@ void createFrame(int chamber) Mlayer->AddNode(vol43, kNScrews, new TGeoTranslation(x, y, z - kHzInHFrame - kSCRUHLE)); - if (chamber == 1) + if (chamber == 1) { gGeoManager->GetVolume("SQ40")->AddNode(vol44, kNScrews, new TGeoTranslation(x - kMidHXPos, y - kMidHYPos, z - kMidHZPos)); + } Mlayer->AddNode(vol45, kNScrews, new TGeoTranslation(x, y, z + kHzInHFrame + kSCRUNLE)); @@ -1162,8 +1165,9 @@ void createFrame(int chamber) Mlayer->AddNode(vol43, i, new TGeoTranslation(x, y, z - kHzInHFrame - kSCRUHLE)); - if (chamber == 1) + if (chamber == 1) { gGeoManager->GetVolume("SQ00")->AddNode(vol44, i, new TGeoTranslation(x - kMidVXPos, y - kMidVYPos, z - kMidVZPos)); + } Mlayer->AddNode(vol45, i, new TGeoTranslation(x, y, z + kHzInHFrame + kSCRUNLE)); } @@ -1189,8 +1193,9 @@ void createFrame(int chamber) y = kDeltaQuadLHC + scruY[i - 1] + 0.1; Mlayer->AddNode(vol43, i, new TGeoTranslation(x, y, z - kHzInHFrame - kSCRUHLE)); - if (chamber == 1) + if (chamber == 1) { gGeoManager->GetVolume("SQ25")->AddNode(vol44, i, new TGeoTranslation(x - kMidOVXPos, y - kMidOVYPos, z - kMidOVZPos)); + } Mlayer->AddNode(vol45, i, new TGeoTranslation(x, y, z + kHzInHFrame + kSCRUNLE)); } @@ -1200,8 +1205,9 @@ void createFrame(int chamber) y = kDeltaQuadLHC + scruY[firstScrew - 1] + 0.1 - kMidHYPos; z = -kMidHZPos; - if (chamber == 1) + if (chamber == 1) { gGeoManager->GetVolume("SQ40")->AddNode(vol44, firstScrew, new TGeoTranslation(x, y, z)); + } // inner arc of Frame, screw positions and numbers firstScrew = 58; @@ -1223,8 +1229,9 @@ void createFrame(int chamber) Mlayer->AddNode(vol43, i + 1, new TGeoTranslation(x, y, z - kHzInHFrame - kSCRUHLE)); - if (chamber == 1) + if (chamber == 1) { gGeoManager->GetVolume("SQ42")->AddNode(vol44, i + 1, new TGeoTranslation(x - kMidArcXPos, y - kMidArcYPos, z - kMidArcZPos)); + } Mlayer->AddNode(vol45, i + 1, new TGeoTranslation(x, y, z + kHzInHFrame + kSCRUNLE)); } @@ -1261,28 +1268,32 @@ TGeoVolume* createPlaneSegment(int iSegment, float halfLength, float halfHeight, y = 0.75; z = -0.1; - if (is267or351) + if (is267or351) { y += kPadYOffsetBP; + } foam->AddNode(gGeoManager->GetVolume("Spacer5A"), 1, new TGeoTranslation(x, y, z)); y = -0.75; - if (is267or351) + if (is267or351) { y += kPadYOffsetBP; + } foam->AddNode(gGeoManager->GetVolume("Spacer5A"), 2, new TGeoTranslation(x, y, z)); y = 0.; z = 1.1515; - if (is267or351) + if (is267or351) { y += kPadYOffsetBP; + } foam->AddNode(gGeoManager->GetVolume("Spacer6"), 1, new TGeoTranslation(x, y, z)); y = 0.; z = 0.; - if (is267or351) + if (is267or351) { y += kPadYOffsetBP; + } foam->AddNode(gGeoManager->GetVolume("Spacer7A"), 1, new TGeoTranslation(x, y, z)); } @@ -1570,8 +1581,9 @@ void createStation1Geometry(TGeoVolume& topVolume) if (x[i] > 0) { in->AddNode(quadrant, detElemID, new TGeoCombiTrans(x[i], y[i], z, rot[i])); - } else + } else { out->AddNode(quadrant, detElemID, new TGeoCombiTrans(x[i], y[i], z, rot[i])); + } } // place the half-chambers in the top volume diff --git a/Detectors/MUON/MCH/Simulation/src/Station2Geometry.cxx b/Detectors/MUON/MCH/Simulation/src/Station2Geometry.cxx index 0414a5ea6eafd..db98d78535296 100644 --- a/Detectors/MUON/MCH/Simulation/src/Station2Geometry.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Station2Geometry.cxx @@ -221,8 +221,9 @@ void createFrames() for (int i = 1; i <= kNFrames; i++) { // in this loop, we only create box frames - if (i == 3 || i == 7) + if (i == 3 || i == 7) { continue; // go to next frame + } // create the frame auto frame = new TGeoVolumeAssembly(Form("Frame %d", i)); @@ -325,8 +326,9 @@ TGeoVolume* createQuadrant() const double kSegXPos[kNSegments] = {kSegmentRadius[0] + kBoxSegHalfLength[0], 0., -kBoxSegHalfLength[2]}; const double kSegYPos[kNSegments] = {-kBoxSegHalfHeight[0], 0., kSegmentRadius[0] + kBoxSegHalfHeight[2]}; - for (int i = 0; i < kNSegments; i++) + for (int i = 0; i < kNSegments; i++) { quadrant->AddNode(createSegment(i), 0, new TGeoTranslation(kSegXPos[i], kSegYPos[i], 0.)); + } // create and place the frames in the quadrant createFrames(); @@ -354,9 +356,10 @@ TGeoVolume* createQuadrant() kSegYPos[0], // frame n°8 aligned with the segment 0 }; - for (int i = 1; i <= kNFrames; i++) + for (int i = 1; i <= kNFrames; i++) { quadrant->AddNode(gGeoManager->GetVolume(Form("Frame %d", i)), 1, new TGeoTranslation(kFrameXPos[i - 1], kFrameYPos[i - 1], 0.)); + } return quadrant; } @@ -399,8 +402,9 @@ void createStation2Geometry(TGeoVolume& topVolume) if (i == 0 || i == 3) { in->AddNode(quadrant, detElemID, new TGeoCombiTrans(0., 0., z, rot[i])); - } else + } else { out->AddNode(quadrant, detElemID, new TGeoCombiTrans(0., 0., z, rot[i])); + } } // place the half-chambers in the top volume diff --git a/Detectors/MUON/MCH/Simulation/src/Station345Geometry.cxx b/Detectors/MUON/MCH/Simulation/src/Station345Geometry.cxx index 7460012f0c2d3..d672a32f66039 100644 --- a/Detectors/MUON/MCH/Simulation/src/Station345Geometry.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Station345Geometry.cxx @@ -411,11 +411,13 @@ void createSlats() // compute the LV cable length float cableHalfLength = (typeName.find('3') < typeName.size()) ? kSt45SupportHalfLength : kCh5SupportHalfLength; - if (typeName == "122200N") + if (typeName == "122200N") { cableHalfLength = kCh6SupportHalfLength; + } cableHalfLength -= halfLength; - if (typeName == "122330N") + if (typeName == "122330N") { cableHalfLength -= kGasLength / 2; + } float rightSpacerHalfHeight = kSlatPanelHalfHeight; if (isRounded(typeName)) { @@ -542,8 +544,9 @@ void createSlats() x = halfLength - kVertSpacerHalfLength; slat->AddNode(leftSpacer, 1, new TGeoTranslation(-(x - panelShift), 0., 0.)); // don't place a right spacer for S(N)R1 slat - if (typeName.back() != '1') + if (typeName.back() != '1') { slat->AddNode(rightSpacer, 1, new TGeoTranslation(x + panelShift, 0., 0.)); + } // place the LV cables (top and bottom) auto LVcable = gGeoManager->MakeBox(Form("%s LV cable", name), assertMedium(Medium::Copper), cableHalfLength + kVertSpacerHalfLength, kLVCableHalfHeight, kLVCableHalfThickness); @@ -644,8 +647,9 @@ void buildHalfChambers(TGeoVolume& topVolume) // loop over the objects (half-chambers) of the array for (const auto& halfCh : hChs.GetArray()) { // check that "halfCh" is an object - if (!halfCh.IsObject()) + if (!halfCh.IsObject()) { throw runtime_error("Can't create the half-chambers : wrong Value input"); + } int moduleID = halfCh["moduleID"].GetInt(); const string name = halfCh["name"].GetString(); @@ -657,15 +661,17 @@ void buildHalfChambers(TGeoVolume& topVolume) // place the support panel corresponding to the chamber number auto supRot = new TGeoRotation(); - if (moduleID % 2) + if (moduleID % 2) { supRot->RotateY(180.); + } halfChVol->AddNode(gGeoManager->GetVolume(Form("Chamber %d support panel", nCh)), moduleID, supRot); // place the slat volumes on the different nodes of the half-chamber for (const auto& slat : halfCh["nodes"].GetArray()) { // check that "slat" is an object - if (!slat.IsObject()) + if (!slat.IsObject()) { throw runtime_error("Can't create the slat : wrong Value input"); + } int detID = slat["detID"].GetInt(); diff --git a/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx b/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx index bf64214d2310e..5bde3ab89b307 100644 --- a/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx +++ b/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx @@ -91,8 +91,9 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) if (trackID == trackId1) { bool check = seg1.isValid(digit.getPadID()); - if (!check) + if (!check) { BOOST_FAIL(" digit-pad not belonging to hit det-element-ID "); + } double padposX = seg1.padPositionX(padid); double padsizeX = seg1.padSizeX(padid); double padposY = seg1.padPositionY(padid); @@ -109,8 +110,9 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) digitcounter1++; } else if (trackID == trackId2) { bool check = seg2.isValid(digit.getPadID()); - if (!check) + if (!check) { BOOST_FAIL(" digit-pad not belonging to hit det-element-ID "); + } double padposX = seg2.padPositionX(padid); double padsizeX = seg2.padSizeX(padid); double padposY = seg2.padPositionY(padid); @@ -130,14 +132,18 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) }; } - if (digitcounter1 == 0) + if (digitcounter1 == 0) { BOOST_FAIL(" no digit at all from hit in station 1 "); - if (digitcounter1 > 9) + } + if (digitcounter1 > 9) { BOOST_FAIL("more than 10 digits for one hit in station 1 "); - if (digitcounter2 == 0) + } + if (digitcounter2 == 0) { BOOST_FAIL(" no digit at all from hit in station 2 "); - if (digitcounter2 > 9) + } + if (digitcounter2 > 9) { BOOST_FAIL(" more than 10 digits for one hit in station 2 "); + } } BOOST_TEST_DECORATOR(*boost::unit_test::disabled()) diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h index 0dc37971fdef7..9adec547d5936 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h @@ -68,8 +68,9 @@ class TrackParam /// set the charge (assumed forward motion) void setCharge(Double_t charge) { - if (charge * mParameters(4, 0) < 0.) + if (charge * mParameters(4, 0) < 0.) { mParameters(4, 0) *= -1.; + } } /// return track parameters diff --git a/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx b/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx index 3c3c389a1973e..95a353d14e6ea 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx @@ -41,78 +41,97 @@ TrackParam::TrackParam(const TrackParam& tp) mLocalChi2(tp.mLocalChi2) { /// Copy constructor - if (tp.mCovariances) + if (tp.mCovariances) { mCovariances = std::make_unique<TMatrixD>(*(tp.mCovariances)); - if (tp.mPropagator) + } + if (tp.mPropagator) { mPropagator = std::make_unique<TMatrixD>(*(tp.mPropagator)); - if (tp.mExtrapParameters) + } + if (tp.mExtrapParameters) { mExtrapParameters = std::make_unique<TMatrixD>(*(tp.mExtrapParameters)); - if (tp.mExtrapCovariances) + } + if (tp.mExtrapCovariances) { mExtrapCovariances = std::make_unique<TMatrixD>(*(tp.mExtrapCovariances)); - if (tp.mSmoothParameters) + } + if (tp.mSmoothParameters) { mSmoothParameters = std::make_unique<TMatrixD>(*(tp.mSmoothParameters)); - if (tp.mSmoothCovariances) + } + if (tp.mSmoothCovariances) { mSmoothCovariances = std::make_unique<TMatrixD>(*(tp.mSmoothCovariances)); + } } //_________________________________________________________________________ TrackParam& TrackParam::operator=(const TrackParam& tp) { /// Assignment operator - if (this == &tp) + if (this == &tp) { return *this; + } mZ = tp.mZ; mParameters = tp.mParameters; if (tp.mCovariances) { - if (mCovariances) + if (mCovariances) { *mCovariances = *(tp.mCovariances); - else + } else { mCovariances = std::make_unique<TMatrixD>(*(tp.mCovariances)); - } else + } + } else { mCovariances.reset(); + } if (tp.mPropagator) { - if (mPropagator) + if (mPropagator) { *mPropagator = *(tp.mPropagator); - else + } else { mPropagator = std::make_unique<TMatrixD>(*(tp.mPropagator)); - } else + } + } else { mPropagator.reset(); + } if (tp.mExtrapParameters) { - if (mExtrapParameters) + if (mExtrapParameters) { *mExtrapParameters = *(tp.mExtrapParameters); - else + } else { mExtrapParameters = std::make_unique<TMatrixD>(*(tp.mExtrapParameters)); - } else + } + } else { mExtrapParameters.reset(); + } if (tp.mExtrapCovariances) { - if (mExtrapCovariances) + if (mExtrapCovariances) { *mExtrapCovariances = *(tp.mExtrapCovariances); - else + } else { mExtrapCovariances = std::make_unique<TMatrixD>(*(tp.mExtrapCovariances)); - } else + } + } else { mExtrapCovariances.reset(); + } if (tp.mSmoothParameters) { - if (mSmoothParameters) + if (mSmoothParameters) { *mSmoothParameters = *(tp.mSmoothParameters); - else + } else { mSmoothParameters = std::make_unique<TMatrixD>(*(tp.mSmoothParameters)); - } else + } + } else { mSmoothParameters.reset(); + } if (tp.mSmoothCovariances) { - if (mSmoothCovariances) + if (mSmoothCovariances) { *mSmoothCovariances = *(tp.mSmoothCovariances); - else + } else { mSmoothCovariances = std::make_unique<TMatrixD>(*(tp.mSmoothCovariances)); - } else + } + } else { mSmoothCovariances.reset(); + } mClusterPtr = tp.mClusterPtr; @@ -171,8 +190,9 @@ Double_t TrackParam::pz() const if (TMath::Abs(mParameters(4, 0)) > 0) { Double_t pYZ = TMath::Abs(1.0 / mParameters(4, 0)); return -pYZ / (TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0))); // spectro. (z<0) - } else + } else { return -FLT_MAX / TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0) + mParameters(1, 0) * mParameters(1, 0)); + } } //__________________________________________________________________________ @@ -183,8 +203,9 @@ Double_t TrackParam::p() const Double_t pYZ = TMath::Abs(1.0 / mParameters(4, 0)); Double_t pZ = -pYZ / (TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0))); // spectro. (z<0) return -pZ * TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0) + mParameters(1, 0) * mParameters(1, 0)); - } else + } else { return FLT_MAX; + } } //__________________________________________________________________________ @@ -202,31 +223,35 @@ const TMatrixD& TrackParam::getCovariances() const void TrackParam::setCovariances(const TMatrixD& covariances) { /// Set the covariance matrix - if (mCovariances) + if (mCovariances) { *mCovariances = covariances; - else + } else { mCovariances = std::make_unique<TMatrixD>(covariances); + } } //__________________________________________________________________________ void TrackParam::setCovariances(const Double_t matrix[5][5]) { /// Set the covariance matrix - if (mCovariances) + if (mCovariances) { mCovariances->SetMatrixArray(&(matrix[0][0])); - else + } else { mCovariances = std::make_unique<TMatrixD>(5, 5, &(matrix[0][0])); + } } //__________________________________________________________________________ void TrackParam::setVariances(const Double_t matrix[5][5]) { /// Set the diagonal terms of the covariance matrix (variances) - if (!mCovariances) + if (!mCovariances) { mCovariances = std::make_unique<TMatrixD>(5, 5); + } mCovariances->Zero(); - for (Int_t i = 0; i < 5; i++) + for (Int_t i = 0; i < 5; i++) { (*mCovariances)(i, i) = matrix[i][i]; + } } //__________________________________________________________________________ @@ -251,18 +276,20 @@ const TMatrixD& TrackParam::getPropagator() const void TrackParam::resetPropagator() { /// Reset the propagator - if (mPropagator) + if (mPropagator) { mPropagator->UnitMatrix(); + } } //__________________________________________________________________________ void TrackParam::updatePropagator(const TMatrixD& propagator) { /// Update the propagator - if (mPropagator) + if (mPropagator) { *mPropagator = TMatrixD(propagator, TMatrixD::kMult, *mPropagator); - else + } else { mPropagator = std::make_unique<TMatrixD>(propagator); + } } //__________________________________________________________________________ @@ -280,10 +307,11 @@ const TMatrixD& TrackParam::getExtrapParameters() const void TrackParam::setExtrapParameters(const TMatrixD& extrapParameters) { /// Set extrapolated parameters - if (mExtrapParameters) + if (mExtrapParameters) { *mExtrapParameters = extrapParameters; - else + } else { mExtrapParameters = std::make_unique<TMatrixD>(extrapParameters); + } } //__________________________________________________________________________ @@ -301,10 +329,11 @@ const TMatrixD& TrackParam::getExtrapCovariances() const void TrackParam::setExtrapCovariances(const TMatrixD& extrapCovariances) { /// Set the extrapolated covariance matrix - if (mExtrapCovariances) + if (mExtrapCovariances) { *mExtrapCovariances = extrapCovariances; - else + } else { mExtrapCovariances = std::make_unique<TMatrixD>(extrapCovariances); + } } //__________________________________________________________________________ @@ -322,10 +351,11 @@ const TMatrixD& TrackParam::getSmoothParameters() const void TrackParam::setSmoothParameters(const TMatrixD& smoothParameters) { /// Set the smoothed parameters - if (mSmoothParameters) + if (mSmoothParameters) { *mSmoothParameters = smoothParameters; - else + } else { mSmoothParameters = std::make_unique<TMatrixD>(smoothParameters); + } } //__________________________________________________________________________ @@ -343,10 +373,11 @@ const TMatrixD& TrackParam::getSmoothCovariances() const void TrackParam::setSmoothCovariances(const TMatrixD& smoothCovariances) { /// Set the smoothed covariance matrix - if (mSmoothCovariances) + if (mSmoothCovariances) { *mSmoothCovariances = smoothCovariances; - else + } else { mSmoothCovariances = std::make_unique<TMatrixD>(smoothCovariances); + } } //__________________________________________________________________________ @@ -379,10 +410,12 @@ Bool_t TrackParam::isCompatibleTrackParam(const TrackParam& trackParam, Double_t // build the error matrix TMatrixD weight(5, 5); - if (mCovariances) + if (mCovariances) { weight += *mCovariances; - if (trackParam.mCovariances) + } + if (trackParam.mCovariances) { weight += *(trackParam.mCovariances); + } // invert the error matrix to get the parameter weights if possible if (weight.Determinant() == 0) { @@ -399,8 +432,9 @@ Bool_t TrackParam::isCompatibleTrackParam(const TrackParam& trackParam, Double_t chi2 = mChi2(0, 0); // check compatibility - if (chi2 > maxChi2) + if (chi2 > maxChi2) { return kFALSE; + } return kTRUE; } diff --git a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx index ce7dc048bf95b..e763d202f1d66 100644 --- a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx @@ -296,8 +296,9 @@ class DataDecoderTask decodeTF(pc, digits); for (auto&& input : pc.inputs()) { - if (input.spec->binding == "readout") + if (input.spec->binding == "readout") { decodeReadout(input, digits); + } } if (mPrint) { diff --git a/Detectors/MUON/MID/Base/src/MpArea.cxx b/Detectors/MUON/MID/Base/src/MpArea.cxx index 03da62ea81e3e..cc8880339ab15 100644 --- a/Detectors/MUON/MID/Base/src/MpArea.cxx +++ b/Detectors/MUON/MID/Base/src/MpArea.cxx @@ -61,8 +61,9 @@ bool MpArea::isValid() const { /// Check if area is valid for (int icoor = 0; icoor < 2; ++icoor) { - if (mPositions[icoor] == mPositions[icoor + 2]) + if (mPositions[icoor] == mPositions[icoor + 2]) { return false; + } } return true; } diff --git a/Detectors/MUON/MID/Raw/test/testRaw.cxx b/Detectors/MUON/MID/Raw/test/testRaw.cxx index eb675544979dd..71682b205bb55 100644 --- a/Detectors/MUON/MID/Raw/test/testRaw.cxx +++ b/Detectors/MUON/MID/Raw/test/testRaw.cxx @@ -54,7 +54,9 @@ o2::mid::ColumnData getColData(uint8_t deId, uint8_t columnId, uint16_t nbp = 0, std::vector<o2::mid::ColumnData> sortData(const std::vector<o2::mid::ColumnData>& data, size_t first, size_t last) { std::vector<o2::mid::ColumnData> sortedData(data.begin() + first, data.begin() + last); - std::sort(sortedData.begin(), sortedData.end(), [](o2::mid::ColumnData& a, o2::mid::ColumnData& b) { if (a.deId == b.deId ) return (a.columnId < b.columnId); return (a.deId < b.deId); }); + std::sort(sortedData.begin(), sortedData.end(), [](o2::mid::ColumnData& a, o2::mid::ColumnData& b) { if (a.deId == b.deId ) { return (a.columnId < b.columnId); + +}return (a.deId < b.deId); }); return sortedData; } diff --git a/Detectors/MUON/MID/Simulation/test/testGeometry.cxx b/Detectors/MUON/MID/Simulation/test/testGeometry.cxx index c2729cbc4a8cf..785e030925c3d 100644 --- a/Detectors/MUON/MID/Simulation/test/testGeometry.cxx +++ b/Detectors/MUON/MID/Simulation/test/testGeometry.cxx @@ -74,12 +74,15 @@ bool areEqual(double a, double b) bool areEqual(const o2::math_utils::Point3D<double>& p1, const o2::math_utils::Point3D<double>& p2) { - if (!areEqual(p1.x(), p2.x())) + if (!areEqual(p1.x(), p2.x())) { return false; - if (!areEqual(p1.y(), p2.y())) + } + if (!areEqual(p1.y(), p2.y())) { return false; - if (!areEqual(p1.z(), p2.z())) + } + if (!areEqual(p1.z(), p2.z())) { return false; + } return true; } diff --git a/Detectors/PHOS/base/src/Geometry.cxx b/Detectors/PHOS/base/src/Geometry.cxx index 64666a4c7e3b8..fd625a50e1e5c 100644 --- a/Detectors/PHOS/base/src/Geometry.cxx +++ b/Detectors/PHOS/base/src/Geometry.cxx @@ -100,14 +100,16 @@ int Geometry::areNeighbours(short absId1, short absId2) if ((coldiff <= 1) && (rowdiff <= 1)) { // At least common vertex return 1; } else { - if ((relid2[1] > relid1[1]) && (relid2[2] > relid1[2] + 1)) + if ((relid2[1] > relid1[1]) && (relid2[2] > relid1[2] + 1)) { return 2; // Difference in row numbers is too large to look further + } } return 0; } else { - if (relid1[0] > relid2[0]) // we switched to the next module + if (relid1[0] > relid2[0]) { // we switched to the next module return -1; + } return 2; } return 0; diff --git a/Detectors/PHOS/base/src/Hit.cxx b/Detectors/PHOS/base/src/Hit.cxx index f27ede8c0930f..9c767ab3db959 100644 --- a/Detectors/PHOS/base/src/Hit.cxx +++ b/Detectors/PHOS/base/src/Hit.cxx @@ -33,8 +33,9 @@ void Hit::PrintStream(std::ostream& stream) const Bool_t Hit::operator<(const Hit& rhs) const { - if (GetDetectorID() == rhs.GetDetectorID()) + if (GetDetectorID() == rhs.GetDetectorID()) { return GetTrackID() < rhs.GetTrackID(); + } return GetDetectorID() < rhs.GetDetectorID(); } @@ -45,8 +46,9 @@ Bool_t Hit::operator==(const Hit& rhs) const Hit& Hit::operator+=(const Hit& rhs) { - if (rhs.GetEnergyLoss() > GetEnergyLoss()) + if (rhs.GetEnergyLoss() > GetEnergyLoss()) { SetTime(rhs.GetTime()); + } SetEnergyLoss(GetEnergyLoss() + rhs.GetEnergyLoss()); return *this; } @@ -54,8 +56,9 @@ Hit& Hit::operator+=(const Hit& rhs) Hit Hit::operator+(const Hit& rhs) const { Hit result(*this); - if (rhs.GetEnergyLoss() > result.GetEnergyLoss()) + if (rhs.GetEnergyLoss() > result.GetEnergyLoss()) { result.SetTime(rhs.GetTime()); + } result.SetEnergyLoss(result.GetEnergyLoss() + rhs.GetEnergyLoss()); return *this; } diff --git a/Detectors/PHOS/calib/src/BadChannelMap.cxx b/Detectors/PHOS/calib/src/BadChannelMap.cxx index 9e2cc5cdbe021..4e920ef009671 100644 --- a/Detectors/PHOS/calib/src/BadChannelMap.cxx +++ b/Detectors/PHOS/calib/src/BadChannelMap.cxx @@ -84,8 +84,9 @@ void BadChannelMap::PrintStream(std::ostream& stream) const // first sort bad channel IDs stream << "Number of bad cells: " << mBadCells.count() << "\n"; for (int cellID = 0; cellID < mBadCells.size(); cellID++) { - if (mBadCells.test(cellID)) + if (mBadCells.test(cellID)) { stream << cellID << "\n"; + } } } diff --git a/Detectors/PHOS/calib/src/CalibDB.cxx b/Detectors/PHOS/calib/src/CalibDB.cxx index 5c5b0e37655cf..08aa853a24997 100644 --- a/Detectors/PHOS/calib/src/CalibDB.cxx +++ b/Detectors/PHOS/calib/src/CalibDB.cxx @@ -26,42 +26,52 @@ void CalibDB::init() void CalibDB::storeBadChannelMap(BadChannelMap* bcm, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFile(new o2::TObjectWrapper<o2::phos::BadChannelMap>(bcm), "BadChannelMap/PHS", metadata, rangestart, rangeend); } BadChannelMap* CalibDB::readBadChannelMap(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } auto result = mCCDBManager.retrieveFromTFile("BadChannelMap/PHS", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "BadChannelMap/PHS", metadata, timestamp); - if (result->IsA() != TObjectWrapper<o2::phos::BadChannelMap>::Class()) + } + if (result->IsA() != TObjectWrapper<o2::phos::BadChannelMap>::Class()) { throw TypeMismatchException("TObjectWrapper<o2::phos::BadChannelMap>", result->IsA()->GetName()); + } auto wrap = dynamic_cast<TObjectWrapper<o2::phos::BadChannelMap>*>(result); - if (!wrap) + if (!wrap) { throw TypeMismatchException("TObjectWrapper<o2::phos::BadChannelMap>", result->IsA()->GetName()); // type checked before - should not enter here + } return wrap->getObj(); } void CalibDB::storeCalibParams(CalibParams* prms, const std::map<std::string, std::string>& metadata, ULong_t rangestart, ULong_t rangeend) { - if (!mInit) + if (!mInit) { init(); + } mCCDBManager.storeAsTFile(new o2::TObjectWrapper<o2::phos::CalibParams>(prms), "CalibParams/PHS", metadata, rangestart, rangeend); } CalibParams* CalibDB::readCalibParams(ULong_t timestamp, const std::map<std::string, std::string>& metadata) { - if (!mInit) + if (!mInit) { init(); + } auto result = mCCDBManager.retrieveFromTFile("CalibParams/PHS", metadata, timestamp); - if (!result) + if (!result) { throw ObjectNotFoundException(mCCDBServer, "CalibParams/PHS", metadata, timestamp); - if (result->IsA() != TObjectWrapper<o2::phos::CalibParams>::Class()) + } + if (result->IsA() != TObjectWrapper<o2::phos::CalibParams>::Class()) { throw TypeMismatchException("TObjectWrapper<o2::phos::CalibParams>", result->IsA()->GetName()); + } auto wrap = dynamic_cast<TObjectWrapper<o2::phos::CalibParams>*>(result); - if (!wrap) + if (!wrap) { throw TypeMismatchException("TObjectWrapper<o2::phos::CalibParams>", result->IsA()->GetName()); // type checked before - should not enter here + } return wrap->getObj(); } diff --git a/Detectors/PHOS/reconstruction/src/Clusterer.cxx b/Detectors/PHOS/reconstruction/src/Clusterer.cxx index 9a7d5bffa8616..fc1ae809d9c6b 100644 --- a/Detectors/PHOS/reconstruction/src/Clusterer.cxx +++ b/Detectors/PHOS/reconstruction/src/Clusterer.cxx @@ -175,8 +175,9 @@ void Clusterer::convertCellsToDigits(gsl::span<const Cell> cells, int firstCellI if (mcmap[iLab] == i) { label = iLab; ++iLab; - if (iLab >= nLab) + if (iLab >= nLab) { --iLab; + } } mDigits.emplace_back(c.getAbsId(), c.getEnergy(), c.getTime(), label); mDigits.back().setHighGain(c.getHighGain()); @@ -197,8 +198,9 @@ void Clusterer::makeClusters(gsl::span<const Digit> digits) int iFirst = mFirstDigitInEvent; // first index of digit which potentially can be a part of cluster for (int i = iFirst; i < mLastDigitInEvent; i++) { - if (digitsUsed[i - mFirstDigitInEvent]) + if (digitsUsed[i - mFirstDigitInEvent]) { continue; + } const Digit& digitSeed = digits[i]; float digitSeedEnergy = calibrate(digitSeed.getAmplitude(), digitSeed.getAbsId()); @@ -230,8 +232,9 @@ void Clusterer::makeClusters(gsl::span<const Digit> digits) short digitSeedAbsId = clu->getDigitAbsId(index); index++; for (Int_t j = iFirst; j < mLastDigitInEvent; j++) { - if (digitsUsed[j - mFirstDigitInEvent]) + if (digitsUsed[j - mFirstDigitInEvent]) { continue; // look through remaining digits + } const Digit* digitN = &(digits[j]); float digitNEnergy = calibrate(digitN->getAmplitude(), digitN->getAbsId()); if (isBadChannel(digitN->getAbsId())) { //remove digit @@ -345,8 +348,9 @@ void Clusterer::unfoldOneCluster(FullCluster& iniClu, char nMax, gsl::span<int> a[iclu] += fij[idig][iclu] * fij[idig][iclu]; b[iclu] += it.energy * fij[idig][iclu]; for (int kclu = 0; kclu < nMax; kclu++) { - if (iclu == kclu) + if (iclu == kclu) { continue; + } c[iclu] += eMax[kclu] * fij[idig][iclu] * fij[idig][kclu]; } } diff --git a/Detectors/PHOS/reconstruction/src/FullCluster.cxx b/Detectors/PHOS/reconstruction/src/FullCluster.cxx index 80671129244b4..38d9fc69d3894 100644 --- a/Detectors/PHOS/reconstruction/src/FullCluster.cxx +++ b/Detectors/PHOS/reconstruction/src/FullCluster.cxx @@ -180,10 +180,11 @@ void FullCluster::evalDispersion() mDispersion /= wtot; } - if (mDispersion >= 0) + if (mDispersion >= 0) { mDispersion = std::sqrt(mDispersion); - else + } else { mDispersion = 0.; + } } //____________________________________________________________________________ void FullCluster::evalElipsAxis() @@ -219,14 +220,16 @@ void FullCluster::evalElipsAxis() dxz -= x * z; mLambdaLong = 0.5 * (dxx + dzz) + std::sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz); - if (mLambdaLong > 0) + if (mLambdaLong > 0) { mLambdaLong = std::sqrt(mLambdaLong); + } mLambdaShort = 0.5 * (dxx + dzz) - std::sqrt(0.25 * (dxx - dzz) * (dxx - dzz) + dxz * dxz); - if (mLambdaShort > 0) // To avoid exception if numerical errors lead to negative lambda. + if (mLambdaShort > 0) { // To avoid exception if numerical errors lead to negative lambda. mLambdaShort = std::sqrt(mLambdaShort); - else + } else { mLambdaShort = 0.; + } } else { mLambdaLong = mLambdaShort = 0.; } diff --git a/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h b/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h index c0d7739ae4c68..34d7dfc138a40 100644 --- a/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h +++ b/Detectors/PHOS/simulation/include/PHOSSimulation/Detector.h @@ -108,10 +108,11 @@ class Detector : public o2::base::DetImpl<Detector> /// std::vector<Hit>* getHits(Int_t iColl) const { - if (iColl == 0) + if (iColl == 0) { return mHits; - else + } else { return nullptr; + } } /// diff --git a/Detectors/PHOS/simulation/src/Detector.cxx b/Detectors/PHOS/simulation/src/Detector.cxx index 4c9796ba12d1a..8a64841d18cc9 100644 --- a/Detectors/PHOS/simulation/src/Detector.cxx +++ b/Detectors/PHOS/simulation/src/Detector.cxx @@ -161,8 +161,9 @@ Bool_t Detector::ProcessHits(FairVolume* v) } Double_t lostenergy = fMC->Edep(); - if (lostenergy < DBL_EPSILON && !isNewPartile) + if (lostenergy < DBL_EPSILON && !isNewPartile) { return false; // do not create hits with zero energy deposition + } // if(strcmp(mc->CurrentVolName(),"PXTL")!=0) //Non need to check, alwais there... // return false ; // We are not inside a PBWO crystal @@ -186,8 +187,9 @@ Bool_t Detector::ProcessHits(FairVolume* v) if (!isNewPartile) { for (Int_t itr = mHits->size() - 1; itr >= 0; itr--) { Hit* h = &(mHits->at(itr)); - if (h->GetTrackID() != superParent) // switched to another SuperParent, do not search further + if (h->GetTrackID() != superParent) { // switched to another SuperParent, do not search further break; + } if (h->GetDetectorID() == detID) { // found correct hit h->addEnergyLoss(lostenergy); mCurentSuperParent = superParent; @@ -560,8 +562,9 @@ void Detector::ConstructEMCGeometry() Float_t x = (2 * irow + 1 - geom->getNStripX()) * strip[0]; for (icol = 0; icol < geom->getNStripZ(); icol++) { z = (2 * icol + 1 - geom->getNStripZ()) * strip[2]; - if (irow >= geom->getNStripX() / 2) + if (irow >= geom->getNStripX() / 2) { fMC->Gspos("PSTR", nr, "PTIH", x, y, z, 0, "ONLY"); + } nr++; } } diff --git a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx index 0eb8c1691771f..d3c9ced7ef8c0 100644 --- a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx +++ b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx @@ -86,10 +86,11 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) } ChannelType_t chantype; - if (dig.isHighGain()) + if (dig.isHighGain()) { chantype = ChannelType_t::HIGH_GAIN; - else + } else { chantype = ChannelType_t::LOW_GAIN; + } // TODO!!! TRU copying... // if (dig.getTRU()) diff --git a/Detectors/PHOS/workflow/src/RecoWorkflow.cxx b/Detectors/PHOS/workflow/src/RecoWorkflow.cxx index 2d144debf5662..cc925c40d7011 100644 --- a/Detectors/PHOS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/PHOS/workflow/src/RecoWorkflow.cxx @@ -97,8 +97,9 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, o2::framework::OutputSpec{"PHS", ""}}, // it empty, do not create propagateMC, false)); - if (enableDigitsPrinter) + if (enableDigitsPrinter) { specs.emplace_back(o2::phos::reco_workflow::getPhosDigitsPrinterSpec()); + } if (isEnabled(OutputType::Cells)) { // add converter for cells diff --git a/Detectors/Passive/src/Absorber.cxx b/Detectors/Passive/src/Absorber.cxx index b325b33b26063..959fea59a8449 100644 --- a/Detectors/Passive/src/Absorber.cxx +++ b/Detectors/Passive/src/Absorber.cxx @@ -40,8 +40,9 @@ Absorber::Absorber(const Absorber& rhs) = default; Absorber& Absorber::operator=(const Absorber& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment FairModule::operator=(rhs); diff --git a/Detectors/Passive/src/Cave.cxx b/Detectors/Passive/src/Cave.cxx index a7265703d2dbc..80f5a2be02cc7 100644 --- a/Detectors/Passive/src/Cave.cxx +++ b/Detectors/Passive/src/Cave.cxx @@ -115,8 +115,9 @@ Cave::Cave(const Cave& rhs) : FairDetector(rhs) {} Cave& Cave::operator=(const Cave& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment FairModule::operator=(rhs); diff --git a/Detectors/Passive/src/Compensator.cxx b/Detectors/Passive/src/Compensator.cxx index b917d6f84ade7..deba512284a5d 100644 --- a/Detectors/Passive/src/Compensator.cxx +++ b/Detectors/Passive/src/Compensator.cxx @@ -36,8 +36,9 @@ Compensator::Compensator(const Compensator& rhs) = default; Compensator& Compensator::operator=(const Compensator& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment PassiveBase::operator=(rhs); diff --git a/Detectors/Passive/src/Dipole.cxx b/Detectors/Passive/src/Dipole.cxx index 535e50ba13b0e..694cf1e1d8844 100644 --- a/Detectors/Passive/src/Dipole.cxx +++ b/Detectors/Passive/src/Dipole.cxx @@ -37,8 +37,9 @@ Dipole::Dipole(const Dipole& rhs) = default; Dipole& Dipole::operator=(const Dipole& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment PassiveBase::operator=(rhs); diff --git a/Detectors/Passive/src/FrameStructure.cxx b/Detectors/Passive/src/FrameStructure.cxx index 5eefcf02b962f..c9290e061b889 100644 --- a/Detectors/Passive/src/FrameStructure.cxx +++ b/Detectors/Passive/src/FrameStructure.cxx @@ -159,8 +159,9 @@ void FrameStructure::createWebFrame(const char* name, float dHz, float theta0, f float theta = TMath::Pi() / 2.; float phi = TMath::ACos(TMath::Cos(theta0) * TMath::Cos(phi0)); - if (phi0 < 0) + if (phi0 < 0) { phi = -phi; + } phi *= krad2deg; theta *= krad2deg; @@ -801,8 +802,9 @@ void FrameStructure::ConstructGeometry() char name[16]; // official module numbering int mod = i + 13; - if (mod > 17) + if (mod > 17) { mod -= 18; + } snprintf(name, 16, "BSEGMO%d", mod); // TGeoVolume* voTRD1 = new TGeoVolume(name, shCS, kMedAir); @@ -810,8 +812,9 @@ void FrameStructure::ConstructGeometry() // Place volume i float phi1 = i * 20.; float phi2 = 270. + phi1; - if (phi2 >= 360.) + if (phi2 >= 360.) { phi2 -= 360.; + } dx = TMath::Sin(phi1 * kdeg2rad) * r; dy = -TMath::Cos(phi1 * kdeg2rad) * r; @@ -1041,28 +1044,36 @@ void FrameStructure::ConstructGeometry() jmod = isec_1[index]; float dz1 = dz + 3. + (zpos - 4.); dx0 = (hR + dz0 + zpos - 4.) * tan10 - (longW / 2. + 0.2) / cos10 - 0.05; - if (jmod != 5) + if (jmod != 5) { vmc->Gspos("BTRDR_10", 2 * jmod + 1, module[jmod], dx0, 0.0, dz1, idrotm[2096], "ONLY"); - if (jmod != 13) + } + if (jmod != 13) { vmc->Gspos("BTRDR_10", 2 * jmod + 2, module[jmod], -dx0, 0.0, dz1, idrotm[2086], "ONLY"); + } dx0 -= 0.5; - if (jmod != 5) + if (jmod != 5) { vmc->Gspos("BTRDR_12", 2 * jmod + 1, module[jmod], dx0, 0.0, dz1, idrotm[2096], "ONLY"); - if (jmod != 13) + } + if (jmod != 13) { vmc->Gspos("BTRDR_12", 2 * jmod + 2, module[jmod], -dx0, 0.0, dz1, idrotm[2087], "ONLY"); + } dz1 += (4 - 0.2); dz1 += dext; dx0 = (hR + dz0 + zpos - 0.2) * tan10 - (longW / 2. + 3. + 0.4) / cos10; - if (jmod != 5) + if (jmod != 5) { vmc->Gspos("BTRDR_11", 2 * jmod + 1, module[jmod], dx0, 0.0, dz1, 0, "ONLY"); - if (jmod != 13) + } + if (jmod != 13) { vmc->Gspos("BTRDR_11", 2 * jmod + 2, module[jmod], -dx0, 0.0, dz1, 0, "ONLY"); + } dz1 -= 0.3; dx0 -= 0.5; - if (jmod != 5) + if (jmod != 5) { vmc->Gspos("BTRDR_14", 2 * jmod + 1, module[jmod], dx0, 0.0, dz1, 0, "ONLY"); - if (jmod != 13) + } + if (jmod != 13) { vmc->Gspos("BTRDR_14", 2 * jmod + 2, module[jmod], -dx0, 0.0, dz1, 0, "ONLY"); + } } // Pos 2 @@ -1116,10 +1127,12 @@ void FrameStructure::ConstructGeometry() for (int index = 0; index < 9; index++) { jmod = isec_3[index]; - if (index > 1) + if (index > 1) { vmc->Gspos("BTRDR_3", 2 * jmod + 1, module[jmod], 50.96 - 5 - 2., 0.0, dz + 3.7, 0, "ONLY"); - if (index < 7) + } + if (index < 7) { vmc->Gspos("BTRDR_3", 2 * jmod + 2, module[jmod], -50.96 + 5 + 2., 0.0, dz + 3.7, 0, "ONLY"); + } } // // Fixation Blocks with tie anchors @@ -1234,29 +1247,37 @@ void FrameStructure::ConstructGeometry() for (int index = 0; index < 11; index++) { int imod = isec_1[index]; - if (imod != 5) + if (imod != 5) { vmc->Gspos("BTRD_FBAS2", index, module[imod], dx, -yFB1, zTA1, idrotm[2097], "ONLY"); + } - if (imod != 13) + if (imod != 13) { vmc->Gspos("BTRD_FBAS1", 11 + index, module[imod], -dx, -yFB1, zTA1, idrotm[2087], "ONLY"); + } - if (imod != 5) + if (imod != 5) { vmc->Gspos("BTRD_FBAS1", 22 + index, module[imod], dx, yFB1, zTA1, idrotm[2096], "ONLY"); + } - if (imod != 13) + if (imod != 13) { vmc->Gspos("BTRD_FBAS2", 33 + index, module[imod], -dx, yFB1, zTA1, idrotm[2086], "ONLY"); + } - if (imod != 5) + if (imod != 5) { vmc->Gspos("BTRD_FBAS4", index, module[imod], dx, -yFB2, zTA1, idrotm[2097], "ONLY"); + } - if (imod != 13) + if (imod != 13) { vmc->Gspos("BTRD_FBAS3", 11 + index, module[imod], -dx, -yFB2, zTA1, idrotm[2087], "ONLY"); + } - if (imod != 5) + if (imod != 5) { vmc->Gspos("BTRD_FBAS3", 22 + index, module[imod], dx, yFB2, zTA1, idrotm[2096], "ONLY"); + } - if (imod != 13) + if (imod != 13) { vmc->Gspos("BTRD_FBAS4", 33 + index, module[imod], -dx, yFB2, zTA1, idrotm[2086], "ONLY"); + } } // @@ -1307,8 +1328,9 @@ void FrameStructure::ConstructGeometry() yxtru1[6] = -6.0; double xxtru2[7]; - for (i = 0; i < 7; i++) + for (i = 0; i < 7; i++) { xxtru2[i] = -xxtru1[i]; + } double xxtru3[5]; double yxtru3[5]; @@ -1319,8 +1341,9 @@ void FrameStructure::ConstructGeometry() } xxtru3[4] = xxtru1[6]; yxtru3[4] = yxtru1[6]; - for (i = 0; i < 5; i++) + for (i = 0; i < 5; i++) { xxtru4[i] = -xxtru3[i]; + } shBTOFS2->DefinePolygon(7, xxtru1, yxtru1); shBTOFS2->DefineSection(0, -4.); @@ -1376,8 +1399,9 @@ void FrameStructure::ConstructGeometry() asTOFS01->SetVisibility(1); for (i = 0; i < 18; i++) { - if (i >= 4 && i <= 8) + if (i >= 4 && i <= 8) { continue; + } float phi1 = i * 20.; float phi2 = 270. + phi1; rot1 = new TGeoRotation(Form("TOFS_R1_%d", i), 90.0, phi1, 90., phi2, 0., 0.); diff --git a/Detectors/Passive/src/Hall.cxx b/Detectors/Passive/src/Hall.cxx index 7980ba2188887..316488a8c6a8a 100644 --- a/Detectors/Passive/src/Hall.cxx +++ b/Detectors/Passive/src/Hall.cxx @@ -32,8 +32,9 @@ Hall::Hall(const Hall& rhs) = default; Hall& Hall::operator=(const Hall& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment PassiveBase::operator=(rhs); diff --git a/Detectors/Passive/src/Magnet.cxx b/Detectors/Passive/src/Magnet.cxx index 6616f9490870b..13faacbcbb08b 100644 --- a/Detectors/Passive/src/Magnet.cxx +++ b/Detectors/Passive/src/Magnet.cxx @@ -46,8 +46,9 @@ Magnet::Magnet(const Magnet& rhs) = default; Magnet& Magnet::operator=(const Magnet& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment PassiveBase::operator=(rhs); diff --git a/Detectors/Passive/src/Pipe.cxx b/Detectors/Passive/src/Pipe.cxx index e637046f008bb..57d4e0678540e 100644 --- a/Detectors/Passive/src/Pipe.cxx +++ b/Detectors/Passive/src/Pipe.cxx @@ -51,8 +51,9 @@ Pipe::Pipe(const Pipe& rhs) = default; Pipe& Pipe::operator=(const Pipe& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment PassiveBase::operator=(rhs); @@ -2730,8 +2731,9 @@ TGeoPcon* Pipe::MakeMotherFromTemplate(const TGeoPcon* shape, Int_t imin, Int_t // Int_t nz0 = shape->GetNz(); // if nz > -1 the number of planes is given by nz - if (nz != -1) + if (nz != -1) { nz0 = nz; + } TGeoPcon* mother = new TGeoPcon(0., 360., nz0); if (imin == -1 || imax == -1) { @@ -2760,8 +2762,9 @@ TGeoPcon* Pipe::MakeMotherFromTemplate(const TGeoPcon* shape, Int_t imin, Int_t double zlast, rminlast, rmaxlast; for (Int_t i = 0; i < shape->GetNz(); i++) { Double_t rmin = shape->GetRmin(i); - if ((i >= imin) && (i <= imax)) + if ((i >= imin) && (i <= imax)) { rmin = r0; + } Double_t rmax = shape->GetRmax(i); Double_t z = shape->GetZ(i); if (i == 0 || (z != zlast || rmin != rminlast || rmax != rmaxlast)) { @@ -2776,9 +2779,11 @@ TGeoPcon* Pipe::MakeMotherFromTemplate(const TGeoPcon* shape, Int_t imin, Int_t pconparams[2] = zplanecounter; // reinit polycon from parameters mother->SetDimensions(pconparams.data()); - } else - for (Int_t i = 0; i < zplanecounter; i++) + } else { + for (Int_t i = 0; i < zplanecounter; i++) { mother->DefineSection(i, pconparams[3 + 3 * i], pconparams[4 + 3 * i], pconparams[5 + 3 * i]); + } + } return mother; } diff --git a/Detectors/Passive/src/Shil.cxx b/Detectors/Passive/src/Shil.cxx index 16883dce6f336..d8dc7b2401396 100644 --- a/Detectors/Passive/src/Shil.cxx +++ b/Detectors/Passive/src/Shil.cxx @@ -36,8 +36,9 @@ Shil::Shil(const Shil& rhs) = default; Shil& Shil::operator=(const Shil& rhs) { // self assignment - if (this == &rhs) + if (this == &rhs) { return *this; + } // base class assignment PassiveBase::operator=(rhs); @@ -85,8 +86,9 @@ TGeoPcon* MakeShapeFromTemplate(const TGeoPcon* pcon, Float_t drMin, Float_t drM // Int_t nz = pcon->GetNz(); TGeoPcon* cpcon = new TGeoPcon(0., 360., nz); - for (Int_t i = 0; i < nz; i++) + for (Int_t i = 0; i < nz; i++) { cpcon->DefineSection(i, pcon->GetZ(i), pcon->GetRmin(i) + drMin, pcon->GetRmax(i) + drMax); + } return cpcon; } } // namespace @@ -1273,23 +1275,26 @@ void Shil::ConstructGeometry() // FA Tail Section for (Int_t iz = 1; iz < 9; iz++) { z = shFaWTail->GetZ(iz - 1); - if (iz == 8) + if (iz == 8) { z -= ozFaSaa1; + } shYOUT1->DefineSection(iz - 1, z + ziFaWTail, shFaWTail->GetRmax(iz - 1) + eps, 150.); } // FA-SAA1 Joint z = shYOUT1->GetZ(7); Int_t izc = 8; for (Int_t iz = 9; iz < 17; iz++) { - if (iz == 11 || iz == 15) + if (iz == 11 || iz == 15) { continue; + } shYOUT1->DefineSection(izc, z + shFaSaa1->GetZ(iz - 9), shFaSaa1->GetRmax(iz - 9) + eps, 150.); izc++; } z = shYOUT1->GetZ(13) - ozSaa1; // SAA1 - Dipole - for (Int_t iz = 15; iz < 22; iz++) + for (Int_t iz = 15; iz < 22; iz++) { shYOUT1->DefineSection(iz - 1, z + shSaa1M->GetZ(iz - 11), shSaa1M->GetRmax(iz - 11) + eps, 150.); + } // Distance between dipole and start of SAA1 2deg opening cone dz = ziDipole - (zSaa1StEnv[0] - dSt + zSaa1StEnvS + ziSaa1); rOut = rOuSaa1StEnv2 + dz * TMath::Tan(2. * kDegRad); From 3d33d4c165003800942fc45e5e7950a2e0ca7536 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Thu, 29 Oct 2020 10:49:36 +0100 Subject: [PATCH 1164/1751] error checking in trd calibrations class --- Detectors/TRD/base/src/Calibrations.cxx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Detectors/TRD/base/src/Calibrations.cxx b/Detectors/TRD/base/src/Calibrations.cxx index 0ef78cd985e6d..022e4407771eb 100644 --- a/Detectors/TRD/base/src/Calibrations.cxx +++ b/Detectors/TRD/base/src/Calibrations.cxx @@ -48,17 +48,34 @@ void Calibrations::setCCDB(int calibrationobjecttype, long timestamp) switch (calibrationobjecttype) { case 1: //simulation mChamberCalibrations = ccdbmgr.get<o2::trd::ChamberCalibrations>("TRD_test/ChamberCalibrations"); + if (!mChamberCalibrations) + LOG(fatal) << "No chamber calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; mLocalVDrift = ccdbmgr.get<o2::trd::LocalVDrift>("TRD_test/LocalVDrift"); + if (!mLocalVDrift) + LOG(fatal) << "No Local V Drift calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; mLocalT0 = ccdbmgr.get<o2::trd::LocalT0>("TRD_test/LocalT0"); + if (!mLocalT0) + LOG(fatal) << "No Local T0 calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; mLocalGainFactor = ccdbmgr.get<o2::trd::LocalGainFactor>("TRD_test/LocalGainFactor"); + if (!mLocalT0) + LOG(fatal) << "No Local T0 calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; mPadNoise = ccdbmgr.get<o2::trd::PadNoise>("TRD_test/PadNoise"); + if (!mPadNoise) + LOG(fatal) << "No Padnoise calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; mChamberStatus = ccdbmgr.get<o2::trd::ChamberStatus>("TRD_test/ChamberStatus"); + if (!mChamberStatus) + LOG(fatal) << "No ChamberStatus calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; mPadStatus = ccdbmgr.get<o2::trd::PadStatus>("TRD_test/PadStatus"); + if (!mPadStatus) + LOG(fatal) << "No Pad Status calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; mChamberNoise = ccdbmgr.get<o2::trd::ChamberNoise>("TRD_test/ChamberNoise"); + if (!mChamberNoise) + LOG(fatal) << "No ChamberNoise calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; //mCalOnlineGainTables= ccdbmgr.get<o2::trd::CalOnlineGainTables>("TRD_test/OnlineGainTables"); //std::shared_ptr<TrapConfig> mTrapConfig; //std::shared_ptr<PRFWidth> mPRDWidth //std::shared_ptr<CalOnlineGainTables> mCalOnlineGainTables; + break; case 2: //reconstruction LOG(fatal) << "Reconstruction calibration not implemented yet "; From 3bde65833a35fcf208cc49c6845a88a65e0279d4 Mon Sep 17 00:00:00 2001 From: mwinn2 <mwinn@cern.ch> Date: Tue, 6 Oct 2020 16:53:29 +0200 Subject: [PATCH 1165/1751] modification: noise and time structure for digitization --- .../include/MCHSimulation/Digitizer.h | 18 +++++++-- .../MUON/MCH/Simulation/src/Digitizer.cxx | 39 ++++++++++++++++++- .../src/MCHDigitizerSpec.cxx | 4 +- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h index dd2f177dc2888..0b2047b5854c4 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h +++ b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h @@ -40,6 +40,7 @@ class Digitizer void process(const std::vector<Hit> hits, std::vector<Digit>& digits, o2::dataformats::MCTruthContainer<o2::MCCompLabel>& mcContainer); void provideMC(o2::dataformats::MCTruthContainer<o2::MCCompLabel>& mcContainer); void mergeDigits(); + void generateNoiseDigits(); //external pile-up adding up void mergeDigits(std::vector<Digit>& digits, o2::dataformats::MCTruthContainer<o2::MCCompLabel>& mcContainer); @@ -56,22 +57,33 @@ class Digitizer void setEventID(int v); int getEventID() const { return mEventID; } + void setNoise(bool val) { mNoise = val; } + bool isNoise() const { return mNoise; } + //for debugging std::vector<Digit> getDigits() { return mDigits; } std::vector<o2::MCCompLabel> getTrackLabels() { return mTrackLabels; } private: - double mEventTime; + int mEventTime; int mEventID = 0; int mSrcID = 0; bool mContinuous = false; - + bool mNoise = true; + //time difference allowed for pileup (in ns (assuming that event time is in ns)) float mDeltat = 100.; //number of detector elements const static int mNdE = 156; + + //noise above threshold probability within read-out window + float mProbNoise = 1e-5; + //sum_i 1/padcount_i where i is the detelemID + float mInvPadSum = 0.0450832; + float mNormProbNoise = mProbNoise / mInvPadSum; + // digit per pad std::vector<Digit> mDigits; @@ -80,7 +92,7 @@ class Digitizer //MCLabel container (output) o2::dataformats::MCTruthContainer<o2::MCCompLabel> mMCTruthOutputContainer; - int processHit(const Hit& hit, int detID, double event_time); + int processHit(const Hit& hit, int detID, int event_time); }; } // namespace mch diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index 953afa8015625..68f9a27837a3b 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -15,10 +15,14 @@ #include "MCHSimulation/Response.h" #include "TGeoManager.h" #include "TMath.h" +#include "TRandom.h" #include <algorithm> #include <cassert> #include <fairlogger/Logger.h> +#include <iostream> +using namespace std; + using namespace o2::mch; namespace @@ -97,11 +101,15 @@ void Digitizer::process(const std::vector<Hit> hits, std::vector<Digit>& digits, mMCTruthOutputContainer.addElement(digitIndex, label); } //loop over digits to generate MCdigits } //loop over hits + + //generate noise-only digits + if(mNoise) generateNoiseDigits(); + fillOutputContainer(digits); provideMC(mcContainer); } //______________________________________________________________________ -int Digitizer::processHit(const Hit& hit, int detID, double event_time) +int Digitizer::processHit(const Hit& hit, int detID, int event_time) { math_utils::Point3D<float> pos(hit.GetX(), hit.GetY(), hit.GetZ()); @@ -109,7 +117,9 @@ int Digitizer::processHit(const Hit& hit, int detID, double event_time) //convert energy to charge auto charge = resp.etocharge(hit.GetEnergyLoss()); - auto time = event_time + hit.GetTime(); + + //convert float ns time to BC counts + auto time = event_time & int(hit.GetTime()/25.); //transformation from global to local auto t = o2::mch::getTransformation(detID, *gGeoManager); @@ -170,6 +180,31 @@ int Digitizer::processHit(const Hit& hit, int detID, double event_time) return ndigits; } //______________________________________________________________________ +void Digitizer::generateNoiseDigits() +{ + + o2::mch::mapping::forEachDetectionElement([& digits = this->mDigits, &normProbNoise = this->mNormProbNoise, + &eventTime = this->mEventTime, &eventID = this->mEventID, + &srcID = this->mSrcID, &mcTruthOutputContainer = this->mMCTruthOutputContainer](int detID) { + auto& seg = segmentation(detID); + auto nPads = seg.nofPads(); + auto nNoisyPadsAv = (float)nPads * normProbNoise; + int nNoisyPads = TMath::Nint(gRandom->Gaus(nNoisyPadsAv, TMath::Sqrt(nNoisyPadsAv))); + for (int i = 0; i < nNoisyPads; i++) { + int padid = gRandom->Integer(nNoisyPads + 1); + Digit::Time dtime; + dtime.sampaTime = static_cast<uint16_t>(eventTime) & 0x3FF; + digits.emplace_back(detID, padid, 0.6, dtime); + //just to roun adbove threshold when added + MCCompLabel label(-1, eventID, srcID, true); + mcTruthOutputContainer.addElement(digits.size() - 1, label); + } + }); + //not clear how to normalise to time: + //assume that only "one" event equivalent, + //otherwise the probability will strongly depend on read-out-frame time length +} +//______________________________________________________________________ void Digitizer::mergeDigits() { std::vector<int> indices(mDigits.size()); diff --git a/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx index e8e210bf6acb6..c6c8bafc155e8 100644 --- a/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx @@ -60,6 +60,7 @@ class MCHDPLDigitizerTask : public o2::base::BaseDPLDigitizer for (auto& record : irecords) { LOG(DEBUG) << "MCH TIME RECEIVED " << record.getTimeNS(); + LOG(DEBUG) << "MCH TIME RECEIVED: bc " << record.bc; } auto& eventParts = context->getEventParts(); @@ -69,7 +70,8 @@ class MCHDPLDigitizerTask : public o2::base::BaseDPLDigitizer // loop over all composite collisions given from context // (aka loop over all the interaction records) for (int collID = 0; collID < irecords.size(); ++collID) { - mDigitizer.setEventTime(irecords[collID].getTimeNS()); + // mDigitizer.setEventTime(irecords[collID].getTimeNS()); + mDigitizer.setEventTime(irecords[collID].bc); // for each collision, loop over the constituents event and source IDs // (background signal merging is basically taking place here) for (auto& part : eventParts[collID]) { From 55973a66377876d40198de585b6b08d143af4767 Mon Sep 17 00:00:00 2001 From: mwinn2 <mwinn@cern.ch> Date: Tue, 6 Oct 2020 17:37:55 +0200 Subject: [PATCH 1166/1751] clang format --- .../MCH/Simulation/include/MCHSimulation/Digitizer.h | 4 ++-- Detectors/MUON/MCH/Simulation/src/Digitizer.cxx | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h index 0b2047b5854c4..72d727241d9c3 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h +++ b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Digitizer.h @@ -59,7 +59,7 @@ class Digitizer void setNoise(bool val) { mNoise = val; } bool isNoise() const { return mNoise; } - + //for debugging std::vector<Digit> getDigits() { return mDigits; } std::vector<o2::MCCompLabel> getTrackLabels() { return mTrackLabels; } @@ -71,7 +71,7 @@ class Digitizer bool mContinuous = false; bool mNoise = true; - + //time difference allowed for pileup (in ns (assuming that event time is in ns)) float mDeltat = 100.; diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index 68f9a27837a3b..3bd1d2fd52f0b 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -103,7 +103,8 @@ void Digitizer::process(const std::vector<Hit> hits, std::vector<Digit>& digits, } //loop over hits //generate noise-only digits - if(mNoise) generateNoiseDigits(); + if (mNoise) + generateNoiseDigits(); fillOutputContainer(digits); provideMC(mcContainer); @@ -117,9 +118,9 @@ int Digitizer::processHit(const Hit& hit, int detID, int event_time) //convert energy to charge auto charge = resp.etocharge(hit.GetEnergyLoss()); - + //convert float ns time to BC counts - auto time = event_time & int(hit.GetTime()/25.); + auto time = event_time & int(hit.GetTime() / 25.); //transformation from global to local auto t = o2::mch::getTransformation(detID, *gGeoManager); @@ -183,7 +184,7 @@ int Digitizer::processHit(const Hit& hit, int detID, int event_time) void Digitizer::generateNoiseDigits() { - o2::mch::mapping::forEachDetectionElement([& digits = this->mDigits, &normProbNoise = this->mNormProbNoise, + o2::mch::mapping::forEachDetectionElement([&digits = this->mDigits, &normProbNoise = this->mNormProbNoise, &eventTime = this->mEventTime, &eventID = this->mEventID, &srcID = this->mSrcID, &mcTruthOutputContainer = this->mMCTruthOutputContainer](int detID) { auto& seg = segmentation(detID); @@ -209,7 +210,7 @@ void Digitizer::mergeDigits() { std::vector<int> indices(mDigits.size()); std::iota(begin(indices), end(indices), 0); - std::sort(indices.begin(), indices.end(), [& digits = this->mDigits, this](int a, int b) { + std::sort(indices.begin(), indices.end(), [&digits = this->mDigits, this](int a, int b) { return (getGlobalDigit(digits[a].getDetID(), digits[a].getPadID()) < getGlobalDigit(digits[b].getDetID(), digits[b].getPadID())); }); From 072fda89e63fdead48e3ada3d79fb14a7d9039e0 Mon Sep 17 00:00:00 2001 From: mwinn2 <mwinn@cern.ch> Date: Thu, 22 Oct 2020 17:44:15 +0200 Subject: [PATCH 1167/1751] clang --- Detectors/MUON/MCH/Simulation/src/Digitizer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index 3bd1d2fd52f0b..e36dce5060867 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -184,7 +184,7 @@ int Digitizer::processHit(const Hit& hit, int detID, int event_time) void Digitizer::generateNoiseDigits() { - o2::mch::mapping::forEachDetectionElement([&digits = this->mDigits, &normProbNoise = this->mNormProbNoise, + o2::mch::mapping::forEachDetectionElement([& digits = this->mDigits, &normProbNoise = this->mNormProbNoise, &eventTime = this->mEventTime, &eventID = this->mEventID, &srcID = this->mSrcID, &mcTruthOutputContainer = this->mMCTruthOutputContainer](int detID) { auto& seg = segmentation(detID); @@ -210,7 +210,7 @@ void Digitizer::mergeDigits() { std::vector<int> indices(mDigits.size()); std::iota(begin(indices), end(indices), 0); - std::sort(indices.begin(), indices.end(), [&digits = this->mDigits, this](int a, int b) { + std::sort(indices.begin(), indices.end(), [& digits = this->mDigits, this](int a, int b) { return (getGlobalDigit(digits[a].getDetID(), digits[a].getPadID()) < getGlobalDigit(digits[b].getDetID(), digits[b].getPadID())); }); From ca5e1a1bc41ef0faf0f93d351b8a8e2a0146a6df Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Fri, 30 Oct 2020 14:37:33 +0100 Subject: [PATCH 1168/1751] PWGHF: Adding Lc in pKpi in the analysis workflow (#4727) --- .../Analysis/HFCandidateSelectionTables.h | 9 + .../include/Analysis/HFSecondaryVertex.h | 26 ++ Analysis/Tasks/PWGHF/CMakeLists.txt | 10 + .../Tasks/PWGHF/HFLcCandidateSelector.cxx | 356 ++++++++++++++++++ Analysis/Tasks/PWGHF/taskLc.cxx | 84 +++++ 5 files changed, 485 insertions(+) create mode 100644 Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx create mode 100644 Analysis/Tasks/PWGHF/taskLc.cxx diff --git a/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h b/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h index 9507e32113e4b..fa5ffde065dc4 100644 --- a/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h @@ -21,4 +21,13 @@ DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int); DECLARE_SOA_TABLE(HFSelD0Candidate, "AOD", "HFSELD0CAND", hf_selcandidate::IsSelD0, hf_selcandidate::IsSelD0bar); } // namespace o2::aod +namespace o2::aod +{ +namespace hf_selcandidate_lc +{ +DECLARE_SOA_COLUMN(IsSelLc, isSelLc, int); +} // namespace hf_selcandidate_lc +DECLARE_SOA_TABLE(HFSelLcCandidate, "AOD", "HFSELLcCAND", hf_selcandidate_lc::IsSelLc); +} // namespace o2::aod + #endif // O2_ANALYSIS_HFCANDIDATESELECTIONTABLES_H_ diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 4e4437a8daa85..7637fd5571754 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -280,6 +280,32 @@ auto InvMassDPlus(const T& candidate) { return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); } + +// Lc+ → p K- π+ + +template <typename T> +auto CtLc(const T& candidate) +{ + return candidate.ct(RecoDecay::getMassPDG(4122)); +} + +template <typename T> +auto YLc(const T& candidate) +{ + return candidate.y(RecoDecay::getMassPDG(4122)); +} + +template <typename T> +auto ELc(const T& candidate) +{ + return candidate.e(RecoDecay::getMassPDG(4122)); +} + +template <typename T> +auto InvMassLc(const T& candidate) +{ + return candidate.m(array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); +} } // namespace hf_cand_prong3 // 3-prong decay candidate table diff --git a/Analysis/Tasks/PWGHF/CMakeLists.txt b/Analysis/Tasks/PWGHF/CMakeLists.txt index f37b15d1ad06a..934b0800e2bb2 100644 --- a/Analysis/Tasks/PWGHF/CMakeLists.txt +++ b/Analysis/Tasks/PWGHF/CMakeLists.txt @@ -28,6 +28,11 @@ o2_add_dpl_workflow(hf-d0-candidate-selector PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) +o2_add_dpl_workflow(hf-lc-candidate-selector + SOURCES HFLcCandidateSelector.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::AnalysisCore O2::DetectorsVertexing @@ -37,3 +42,8 @@ o2_add_dpl_workflow(hf-task-dplus SOURCES taskDPlus.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(hf-task-lc + SOURCES taskLc.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx new file mode 100644 index 0000000000000..c4865dd141d19 --- /dev/null +++ b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx @@ -0,0 +1,356 @@ +// 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 Lc->pKpi selection task. +/// +/// \author Luigi Dello Stritto <luigi.dellostritto@cern.ch>, CERN +/// \author Nima Zardoshti <nima.zardoshti@cern.ch>, CERN + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Analysis/HFSecondaryVertex.h" +#include "Analysis/HFCandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::hf_cand_prong3; + +static const int npTBins = 10; +static const int nCutVars = 8; +//temporary until 2D array in configurable is solved - then move to json +//m ptp ptk ptpi DCA sigmavtx dlenght cosp +constexpr double cuts[npTBins][nCutVars] = {{0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* pt<1 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 1<pt<2 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 2<pt<3 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 3<pt<4 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 4<pt<5 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 5<pt<6 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 6<pt<8 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 8<pt<12 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 12<pt<24 */ + {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}}; /* 24<pt<36 */ + +/// Struct for applying Lc selection cuts + +struct HFLcCandidateSelector { + + Produces<aod::HFSelLcCandidate> hfSelLcCandidate; + + Configurable<double> d_pTCandMin{"d_pTCandMin", 0., "Lower bound of candidate pT"}; + Configurable<double> d_pTCandMax{"d_pTCandMax", 36., "Upper bound of candidate pT"}; + + Configurable<double> d_pidTPCMinpT{"d_pidTPCMinpT", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable<double> d_pidTPCMaxpT{"d_pidTPCMaxpT", 1., "Upper bound of track pT for TPC PID"}; + Configurable<double> d_pidTOFMinpT{"d_pidTOFMinpT", 0.5, "Lower bound of track pT for TOF PID"}; + Configurable<double> d_pidTOFMaxpT{"d_pidTOFMaxpT", 4., "Upper bound of track pT for TOF PID"}; + + Configurable<double> d_TPCNClsFindablePIDCut{"d_TPCNClsFindablePIDCut", 70., "Lower bound of TPC findable clusters for good PID"}; + Configurable<double> d_nSigmaTPC{"d_nSigmaTPC", 3., "Nsigma cut on TPC only"}; + Configurable<double> d_nSigmaTPCCombined{"d_nSigmaTPCCombined", 5., "Nsigma cut on TPC combined with TOF"}; + Configurable<double> d_nSigmaTOF{"d_nSigmaTOF", 3., "Nsigma cut on TOF only"}; + Configurable<double> d_nSigmaTOFCombined{"d_nSigmaTOFCombined", 5., "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 <typename T> + int getpTBin(T candpT) + { + double pTBins[npTBins + 1] = {0, 1., 2., 3., 4., 5., 6., 8., 12., 24., 36.}; + 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 <typename T> + 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 hfCandProng3 is candidate + /// \return true if candidate passes all cuts + template <typename T> + bool selectionTopol(const T& hfCandProng3) + { + auto candpT = hfCandProng3.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 (hfCandProng3.cpa() <= cuts[pTBin][7]) { + return false; //cosine of pointing angle + } + // if (hfCandProng3.dca() > cuts[pTBin][4]) return false; //candidate DCA + if (hfCandProng3.chi2PCA() > cuts[pTBin][5]) { //candidate DCA + return false; + } + + if (hfCandProng3.decayLength() * hfCandProng3.decayLength() < cuts[pTBin][6] * cuts[pTBin][6]) { + return false; + } + return true; + } + + /// Conjugate dependent toplogical cuts + /// \param hfCandProng3 is candidate + /// \param trackProton is the track with the proton hypothesis + /// \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 <typename T1, typename T2> + bool selectionTopolConjugate(const T1& hfCandProng3, const T2& trackProton, const T2& trackKaon, const T2& trackPion) + { + + auto candpT = hfCandProng3.pt(); + int pTBin = getpTBin(candpT); + if (pTBin == -1) { + return false; + } + + //invariant mass cut + if (TMath::Abs(InvMassLc(hfCandProng3) - RecoDecay::getMassPDG(4122)) > cuts[pTBin][0]) { + return false; + } + + if (TMath::Abs(trackProton.pt()) < TMath::Abs(cuts[pTBin][1]) || TMath::Abs(trackKaon.pt()) < TMath::Abs(cuts[pTBin][2]) || TMath::Abs(trackPion.pt()) < TMath::Abs(cuts[pTBin][3])) { + return false; //cut on daughter pT + } + + /* if (TMath::Sqrt( trackProton.dcaPrim0()*trackProton.dcaPrim0() + trackKaon.dcaPrim0()*trackKaon.dcaPrim0() + trackPion.dcaPrim0()*trackPion.dcaPrim0() ) > cuts[pTBin][5]) { + return false; //cut on daughter dca - need to add secondary vertex constraint here + }*/ + + 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 <typename T> + bool validTPCPID(const T& track) + { + if (TMath::Abs(track.pt()) < d_pidTPCMinpT || TMath::Abs(track.pt()) >= 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 <typename T> + bool validTOFPID(const T& track) + { + if (TMath::Abs(track.pt()) < d_pidTOFMinpT || TMath::Abs(track.pt()) >= 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=2212 proton nPDG=211 pion nPDG=321 kaon + /// \return true if track satisfies TPC PID hypothesis for given Nsigma cut + template <typename T> + bool selectionPIDTPC(const T& track, int nPDG, int nSigmaCut) + { + double nSigma = 0.0; + nPDG = TMath::Abs(nPDG); + if (nPDG == 2212) { + nSigma = track.tpcNSigmaPr(); + } else if (nPDG == 321) { + nSigma = track.tpcNSigmaKa(); + } else if (nPDG == 111) { + nSigma = track.tpcNSigmaPi(); + + } 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=2212 proton nPDG=211 pion nPDG=321 kaon + /// \return true if track satisfies TOF PID hypothesis for given NSigma cut + template <typename T> + bool selectionPIDTOF(const T& track, int nPDG, int nSigmaCut) + { + double nSigma = 0.0; + nPDG = TMath::Abs(nPDG); + if (nPDG == 2212) { + nSigma = track.tofNSigmaPr(); + } else if (nPDG == 321) { + nSigma = track.tofNSigmaKa(); + } else if (nPDG == 321) { + nSigma = track.tofNSigmaPi(); + } 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=2212 nPDG=211 pion nPDG=321 kaon + /// \return 1 if successful PID match, 0 if successful PID rejection, -1 if no PID info + template <typename T> + 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::HfCandProng3 const& hfCandProng3s, aod::BigTracksPID const& tracks) + { + int statusLc; // final selection flag : 0-rejected 1-accepted + bool topolLc; + int pidLc, proton, kMinus, piPlus; + + for (auto& hfCandProng3 : hfCandProng3s) { //looping over 3 prong candidates + + auto trackPos1 = hfCandProng3.index0_as<aod::BigTracksPID>(); //positive daughter + auto trackNeg1 = hfCandProng3.index1_as<aod::BigTracksPID>(); //negative daughter + auto trackPos2 = hfCandProng3.index2_as<aod::BigTracksPID>(); //positive daughter + + statusLc = 0; + topolLc = true; + pidLc = -1; + proton = -1; + kMinus = -1; + piPlus = -1; + + // daughter track validity selection + if (!daughterSelection(trackPos1) || !daughterSelection(trackNeg1) || !daughterSelection(trackPos2)) { + hfSelLcCandidate(statusLc); + continue; + } + + //implement filter bit 4 cut - should be done before this task at the track selection level + + //conjugate independent topological selection + if (!selectionTopol(hfCandProng3)) { + hfSelLcCandidate(statusLc); + continue; + } + + //conjugate dependent toplogical selection for Lc + topolLc = selectionTopolConjugate(hfCandProng3, trackPos1, trackNeg1, trackPos2); + + if (!topolLc) { + hfSelLcCandidate(statusLc); + continue; + } + + proton = selectionPID(trackPos1, 2212); + kMinus = selectionPID(trackNeg1, 321); + piPlus = selectionPID(trackPos2, 211); + + if (proton == 0 || kMinus == 0 || piPlus == 0) { + pidLc = 0; //exclude Lc + } + if (proton == 1 && kMinus == 1 && piPlus == 1) { + pidLc = 1; //accept Lc + } + + if (pidLc == 0) { + hfSelLcCandidate(statusLc); + continue; + } + + if ((pidLc == -1 || pidLc == 1) && topolLc) { + statusLc = 1; //identified as Lc + } + + hfSelLcCandidate(statusLc); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<HFLcCandidateSelector>("hf-lc-candidate-selector")}; +} diff --git a/Analysis/Tasks/PWGHF/taskLc.cxx b/Analysis/Tasks/PWGHF/taskLc.cxx new file mode 100644 index 0000000000000..ca721dbc97e9e --- /dev/null +++ b/Analysis/Tasks/PWGHF/taskLc.cxx @@ -0,0 +1,84 @@ +// 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 taskDPlus.cxx +/// \brief D± analysis task +/// \note Extended from taskD0 +/// +/// \author Vít Kučera <vit.kucera@cern.ch>, CERN + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Analysis/HFSecondaryVertex.h" +#include "Analysis/HFCandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::hf_cand_prong3; +using namespace o2::framework::expressions; + +/// Lc+ analysis task +struct TaskLc { + OutputObj<TH1F> hmass{TH1F("hmass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 3.1)}; + OutputObj<TH1F> hptcand{TH1F("hptcand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong0{TH1F("hptprong0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong1{TH1F("hptprong1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hptprong2{TH1F("hptprong2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj<TH1F> hdeclength{TH1F("declength", "3-prong candidates;decay length (cm);entries", 200, 0., 2.)}; + OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hd0Prong2{TH1F("hd0Prong2", "3-prong candidates;prong 2 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hCt{TH1F("hCt", "3-prong candidates;proper lifetime (D^{#pm}) * #it{c} (cm);entries", 120, -20., 100.)}; + OutputObj<TH1F> hCPA{TH1F("hCPA", "3-prong candidates;cosine of pointing angle;entries", 110, -1.1, 1.1)}; + OutputObj<TH1F> hEta{TH1F("hEta", "3-prong candidates;candidate #it{#eta};entries", 100, -2., 2.)}; + //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "3-prong candidates;selection status;entries", 5, -0.5, 4.5)}; + OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "3-prong candidates;impact parameter error (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "3-prong candidates;decay length error (cm);entries", 100, 0., 1.)}; + //OutputObj<TH1F> hdca{TH1F("hdca", "3-prong candidates;prongs DCA to prim. vertex (cm);entries", 100, -1., 1.)}; + OutputObj<TH1F> hdca2{TH1F("hdca2", "3-prong candidates;prongs DCA to sec. vertex (cm);entries", 100, 0., 1.)}; + + Configurable<int> d_selectionFlagLc{"d_selectionFlagLc", 1, "Selection Flag for Lc"}; + + Filter filterSelectCandidates = (aod::hf_selcandidate_lc::isSelLc >= d_selectionFlagLc); + + //void process(aod::HfCandProng3 const& candidates) + void process(soa::Filtered<soa::Join<aod::HfCandProng3, aod::HFSelLcCandidate>> const& candidates) + { + for (auto& candidate : candidates) { + if (candidate.isSelLc() >= d_selectionFlagLc) { + hmass->Fill(InvMassLc(candidate)); + } + hptcand->Fill(candidate.pt()); + hptprong0->Fill(candidate.ptProng0()); + hptprong1->Fill(candidate.ptProng1()); + hptprong2->Fill(candidate.ptProng2()); + hdeclength->Fill(candidate.decayLength()); + hd0Prong0->Fill(candidate.impactParameter0()); + hd0Prong1->Fill(candidate.impactParameter1()); + hd0Prong2->Fill(candidate.impactParameter2()); + hCt->Fill(CtLc(candidate)); + hCPA->Fill(candidate.cpa()); + hEta->Fill(candidate.eta()); + //hselectionstatus->Fill(candidate.isSelLc()); + hImpParErr->Fill(candidate.errorImpactParameter0()); + hImpParErr->Fill(candidate.errorImpactParameter1()); + hImpParErr->Fill(candidate.errorImpactParameter2()); + hDecLenErr->Fill(candidate.errorDecayLength()); + // hdca->Fill(candidate.dca()); + hdca2->Fill(candidate.chi2PCA()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<TaskLc>("hf-task-lc")}; +} From de90052444f68ed7f9bc8c4ac8397fa34bf3946f Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Fri, 30 Oct 2020 14:37:55 +0100 Subject: [PATCH 1169/1751] HistogramRegistry: provide some rough size estimates for the histograms (#4721) --- .../include/Framework/HistogramRegistry.h | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 640d2841de2be..4d4c9d6b4dfb0 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -302,7 +302,9 @@ struct HistFactory { return hist->GetAxis(i); } else { return (i == 0) ? hist->GetXaxis() - : (i == 1) ? hist->GetYaxis() : (i == 2) ? hist->GetZaxis() : nullptr; + : (i == 1) ? hist->GetYaxis() + : (i == 2) ? hist->GetZaxis() + : nullptr; } } @@ -385,6 +387,71 @@ struct HistFiller { fillHistAny<useWeight>(hist, (*(static_cast<Cs>(t).getIterator()))...); } } + + // function that returns rough estimate for the size of a histogram in MB + // should be somewhat realistic for TH{1,2,3} + // for ndimensional arrays the memory is allocated lazily so the size estimates might + // not yet be entirely correct and should be seen as a 'worst case' scenario for now + // this will require some more detailed understanding of the root interna... + template <typename T> + static double getSize(std::shared_ptr<T>& hist, double fillFraction = 1.) + { + double size{0.}; + if constexpr (std::is_base_of_v<TH1, T>) { + size = hist->GetNcells() * (HistFiller::getBaseElementSize(hist.get()) + ((hist->GetSumw2()->fN) ? sizeof(double) : 0.)); + } else if constexpr (std::is_base_of_v<THn, T>) { + return hist->GetNbins() * (HistFiller::getBaseElementSize(hist.get()) + ((hist->GetSumw2() != -1.) ? sizeof(double) : 0.)); + } else if constexpr (std::is_base_of_v<THnSparse, T>) { + double nbinsTotal = 1.; + for (int d = 0; d < hist->GetNdimensions(); ++d) { + nbinsTotal *= hist->GetAxis(d)->GetNbins() + 2; + } + double overhead = 4.; // probably often less; unfortunatley we cannot access hist->GetCompactCoord()->GetBufferSize(); + size = fillFraction * nbinsTotal * (HistFiller::getBaseElementSize(hist.get()) + overhead + ((hist->GetSumw2() != -1.) ? sizeof(double) : 0.)); + } + return size / 1048576.; + } + + private: + // helper function to determine base element size of histograms (in bytes) + // the complicated casting gymnastics are needed here since we only store the interface types in the registry + template <typename T> + static int getBaseElementSize(T* ptr) + { + if constexpr (std::is_base_of_v<TH1, T>) { + return getBaseElementSize<TArrayD, TArrayF, TArrayC, TArrayI, TArrayC>(ptr); + } else { + return getBaseElementSize<double, float, int, short, char, long>(ptr); + } + } + + template <typename T, typename Next, typename... Rest, typename P> + static int getBaseElementSize(P* ptr) + { + if (auto size = getBaseElementSize<T>(ptr)) { + return size; + } + return getBaseElementSize<Next, Rest...>(ptr); + } + + template <typename B, typename T> + static int getBaseElementSize(T* ptr) + { + if constexpr (std::is_base_of_v<THn, T>) { + if (dynamic_cast<THnT<B>*>(ptr)) { + return sizeof(B); + } + } else if constexpr (std::is_base_of_v<THnSparse, T>) { + if (dynamic_cast<THnSparseT<B>*>(ptr)) { + return sizeof(B); + } + } else if constexpr (std::is_base_of_v<TH1, T>) { + if (auto arrayPtr = dynamic_cast<B*>(ptr)) { + return sizeof(arrayPtr->At(0)); + } + } + return 0; + }; }; //************************************************************************************************** @@ -568,6 +635,24 @@ class HistogramRegistry fillTable<true, Cs...>(name, table, filter); } + // get rough estimate for size of histogram stored in registry + double getSize(char const* const name, double fillFraction = 1.) + { + double size{}; + std::visit([&fillFraction, &size](auto&& hist) { size = HistFiller::getSize(hist, fillFraction); }, mRegistryValue[getHistIndex(name)]); + return size; + } + + // get rough estimate for size of all histograms stored in registry + double getSize(double fillFraction = 1.) + { + double size{}; + for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + std::visit([&fillFraction, &size](auto&& hist) { if(hist) { size += HistFiller::getSize(hist, fillFraction);} }, mRegistryValue[j]); + } + return size; + } + // lookup distance counter for benchmarking mutable uint32_t lookup = 0; From a8a9dabd10fed034ecf9bcde74104dd006edbf5b Mon Sep 17 00:00:00 2001 From: Gian Michele Innocenti <ginnocen@cern.ch> Date: Fri, 30 Oct 2020 14:45:32 +0100 Subject: [PATCH 1170/1751] Fix authorship --- CODEOWNERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 6a230634f7d43..33ab2dfb99c6d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -13,7 +13,8 @@ /Algorithm @matthiasrichter /Analysis @jgrosseo @iarsene -/Analysis/Tasks/hf* @ginnocen +/Analysis/Tasks/ALICE3 @ginnocen +/Analysis/Tasks/PWGHF @ginnocen /CCDB @costing @Barthelemy @sawenzel @AliceO2Group/framework-admins From 8b8873b86ff6ce8e36a9fae951775766a2d16ec0 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Fri, 30 Oct 2020 22:53:36 +0100 Subject: [PATCH 1171/1751] Do not track neutral particles for MID --- Detectors/MUON/MID/Simulation/src/Stepper.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Detectors/MUON/MID/Simulation/src/Stepper.cxx b/Detectors/MUON/MID/Simulation/src/Stepper.cxx index c59f7da89b3c6..59451eafbc6a8 100644 --- a/Detectors/MUON/MID/Simulation/src/Stepper.cxx +++ b/Detectors/MUON/MID/Simulation/src/Stepper.cxx @@ -29,6 +29,14 @@ Stepper::~Stepper() bool Stepper::process(const TVirtualMC& vmc) { + + if (!(vmc.TrackCharge())) { + // Only charged particles + return false; + } + + // TODO: Update basing on AliRoot + o2::SimTrackStatus ts{vmc}; int detElemId; From 2b15b018034af421fd7fdd3dd82431b5fa771ef6 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 1 Nov 2020 01:58:39 +0100 Subject: [PATCH 1172/1751] DPL: hopefully fix current CPU detection (#4735) Due to some include path missing / not being installed on the Centos 7 build system, the system falls back to direct usage of CPUID, which is nowadays not 100% correct, especially on high profile Intel hardware. This makes sure we first try the sys call sched_getcpu before trying to be smart. --- Framework/Core/src/runDataProcessing.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 8bf23a6651c02..039f9c815014a 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -108,7 +108,9 @@ #include <sys/wait.h> #include <unistd.h> #include <execinfo.h> -#if __has_include(<linux/getcpu.h>) +#if defined(__linux__) && __has_include(<sched.h>) +#include <sched.h> +#elif __has_include(<linux/getcpu.h>) #include <linux/getcpu.h> #elif __has_include(<cpuid.h>) #include <cpuid.h> @@ -1127,9 +1129,13 @@ int runStateMachine(DataProcessorSpecs const& workflow, // This is guaranteed to be a single CPU. unsigned parentCPU = -1; unsigned parentNode = -1; -#if __has_include(<linux/getcpu.h>) +#if defined(__linux__) && __has_include(<sched.h>) + parentCPU = sched_getcpu(); +#elif __has_include(<linux/getcpu.h>) getcpu(&parentCPU, &parentNode, nullptr); #elif __has_include(<cpuid.h>) + // FIXME: this is a last resort as it is apparently buggy + // on some Intel CPUs. GETCPU(parentCPU); #endif for (auto& callback : preScheduleCallbacks) { From 928f4c6aca82b4de592db8487295c60a8c466e66 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 26 Oct 2020 21:04:56 +0100 Subject: [PATCH 1173/1751] Dump profiling information --- Framework/Core/src/ResourcesMonitoringHelper.cxx | 9 +++++---- Framework/Core/src/ResourcesMonitoringHelper.h | 13 ++++++------- Framework/Core/src/runDataProcessing.cxx | 4 +++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Framework/Core/src/ResourcesMonitoringHelper.cxx b/Framework/Core/src/ResourcesMonitoringHelper.cxx index b1630e9a48e3a..28d90351816f7 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.cxx +++ b/Framework/Core/src/ResourcesMonitoringHelper.cxx @@ -13,10 +13,13 @@ #include <fstream> #include <string_view> #include <algorithm> +#include <cassert> using namespace o2::framework; -bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetricsInfo>& metrics, const std::vector<DeviceSpec>& specs) noexcept +bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetricsInfo>& metrics, + const std::vector<DeviceSpec>& specs, + std::vector<std::string> const& performanceMetrics) noexcept { assert(metrics.size() == specs.size()); @@ -25,8 +28,6 @@ bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetric return false; } - std::vector<std::string> performanceMetrics = monitoring::ProcessMonitor::getAvailableMetricsNames(); - boost::property_tree::ptree root; for (unsigned int idx = 0; idx < metrics.size(); ++idx) { @@ -84,4 +85,4 @@ bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetric file.close(); return true; -} \ No newline at end of file +} diff --git a/Framework/Core/src/ResourcesMonitoringHelper.h b/Framework/Core/src/ResourcesMonitoringHelper.h index c231be960a00f..d520f903b8b20 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.h +++ b/Framework/Core/src/ResourcesMonitoringHelper.h @@ -22,13 +22,14 @@ namespace o2::framework { -class ResourcesMonitoringHelper -{ - public: - static bool dumpMetricsToJSON(const std::vector<DeviceMetricsInfo>& metrics, const std::vector<DeviceSpec>& specs) noexcept; +struct ResourcesMonitoringHelper { + /// Dump the metrics in @a metrics which match the names specified in @a metricsToDump + /// @a specs are the DeviceSpecs associated to the metrics. + static bool dumpMetricsToJSON(std::vector<DeviceMetricsInfo> const& metrics, + std::vector<DeviceSpec> const& specs, + std::vector<std::string> const& metricsToDump) noexcept; static bool isResourcesMonitoringEnabled(unsigned short interval) noexcept { return interval > 0; } - private: template <typename T> static boost::property_tree::ptree fillNodeWithValue(const DeviceMetricsInfo& deviceMetrics, const T& metricsStorage, size_t labelIndex, size_t storageIndex); @@ -42,8 +43,6 @@ class ResourcesMonitoringHelper { return std::string(val.get().data); } - - ResourcesMonitoringHelper() = delete; }; template <typename T> diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 039f9c815014a..079d1e59697f1 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1264,7 +1264,9 @@ int runStateMachine(DataProcessorSpecs const& workflow, case DriverState::EXIT: { if (ResourcesMonitoringHelper::isResourcesMonitoringEnabled(driverInfo.resourcesMonitoringInterval)) { LOG(INFO) << "Dumping performance metrics to performanceMetrics.json file"; - ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, deviceSpecs); + auto performanceMetrics = o2::monitoring::ProcessMonitor::getAvailableMetricsNames(); + performanceMetrics.push_back("arrow-bytes-delta"); + ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, deviceSpecs, performanceMetrics); } // This is a clean exit. Before we do so, if required, // we dump the configuration of all the devices so that From 5eb029acbb08766dd6b0a80c1789ae1a3a94b952 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 28 Oct 2020 20:48:26 +0100 Subject: [PATCH 1174/1751] DPL: send metric on init --- Framework/Core/src/AODReaderHelpers.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 32f3d8b0e5db3..9219a028a9fe3 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -167,7 +167,11 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> reques AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() { auto callback = AlgorithmSpec{adaptStateful([](ConfigParamRegistry const& options, - DeviceSpec const& spec) { + DeviceSpec const& spec, + Monitoring& monitoring) { + monitoring.send(Metric{0LL, "arrow-bytes-created"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{0LL, "arrow-messages-created"}.addTag(Key::Subsystem, Value::DPL)); + if (!options.isSet("aod-file")) { LOGP(ERROR, "No input file defined!"); throw std::runtime_error("Processing is stopped!"); From 9ab80ccfa8adc31793f3a08ad83dbc327dcd3ca0 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 29 Oct 2020 10:12:52 +0100 Subject: [PATCH 1175/1751] DPL GUI: add stems plot ... and use it display SIGUSR1 event. --- Framework/Core/src/AODReaderHelpers.cxx | 13 ++++++++++-- Framework/Core/src/CommonMessageBackends.cxx | 7 ++++--- Framework/Core/src/FrameworkGUIDebugger.cxx | 22 ++++++++++++++++++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 9219a028a9fe3..f020da39b2224 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -28,6 +28,8 @@ #include "Framework/ChannelInfo.h" #include "Framework/Logger.h" +#include <Monitoring/Monitoring.h> + #include <ROOT/RDataFrame.hxx> #include <TGrid.h> #include <TFile.h> @@ -40,6 +42,11 @@ #include <thread> +using o2::monitoring::Metric; +using o2::monitoring::Monitoring; +using o2::monitoring::tags::Key; +using o2::monitoring::tags::Value; + namespace o2::framework::readers { auto setEOSCallback(InitContext& ic) @@ -169,8 +176,10 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() auto callback = AlgorithmSpec{adaptStateful([](ConfigParamRegistry const& options, DeviceSpec const& spec, Monitoring& monitoring) { - monitoring.send(Metric{0LL, "arrow-bytes-created"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{0LL, "arrow-messages-created"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(uint64_t)0, "arrow-bytes-created"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)0, "arrow-messages-created"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)0, "arrow-bytes-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)0, "arrow-messages-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); if (!options.isSet("aod-file")) { LOGP(ERROR, "No input file defined!"); diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index bea3610064abf..d46571aeb6e93 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -157,7 +157,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() static auto totalMessagesCreatedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-messages-created"); static auto totalMessagesDestroyedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-messages-destroyed"); static auto totalBytesDeltaMetric = DeviceMetricsHelper::createNumericMetric<int>(driverMetrics, "arrow-bytes-delta"); - static auto totalSignalsMetric = DeviceMetricsHelper::createNumericMetric<int>(driverMetrics, "aod-reader-signals"); + static auto totalSignalsMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "aod-reader-signals"); bool changed = false; for (auto& deviceMetrics : allDeviceMetrics) { @@ -209,6 +209,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() if (changed) { /// Trigger next timeframe only when we have more than 1GB in memory available. if (totalBytesCreated <= (totalBytesDestroyed + memLimit)) { + totalSignalsMetric(driverMetrics, 1, timestamp); for (size_t di = 0; di < specs.size(); ++di) { if (specs[di].name == "internal-dpl-aod-reader") { if (di < infos.size()) { @@ -263,8 +264,8 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() arrow->updateBytesDestroyed(totalBytes); arrow->updateMessagesDestroyed(totalMessages); auto& monitoring = ctx.services().get<Monitoring>(); - monitoring.send(Metric{(uint64_t)arrow->bytesDestroyed(), "arrow-bytes-destroyed"}.addTag(Key::Subsystem, Value::DPL)); - monitoring.send(Metric{(uint64_t)arrow->messagesDestroyed(), "arrow-messages-destroyed"}.addTag(Key::Subsystem, Value::DPL)); + monitoring.send(Metric{(uint64_t)arrow->bytesDestroyed(), "arrow-bytes-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)arrow->messagesDestroyed(), "arrow-messages-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); monitoring.flushBuffer(); }, ServiceKind::Serial}; diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/Core/src/FrameworkGUIDebugger.cxx index 65930fec30746..ed297217fdd70 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/Core/src/FrameworkGUIDebugger.cxx @@ -170,7 +170,8 @@ enum struct MetricsDisplayStyle : int { Lines = 0, Histos = 1, Sparks = 2, - Table = 3 + Table = 3, + Stems = 4 }; void displayDeviceMetrics(const char* label, std::string const& selectedMetricName, @@ -318,6 +319,21 @@ void displayDeviceMetrics(const char* label, std::string const& selectedMetricNa ImPlot::EndPlot(); } break; + case MetricsDisplayStyle::Stems: + ImPlot::SetNextPlotLimitsX(minDomain, maxDomain, ImGuiCond_Once); + ImPlot::SetNextPlotLimitsY(minValue, maxValue * 1.2, ImGuiCond_Always); + ImPlot::SetNextPlotTicksX(minDomain, maxDomain, 5); + if (ImPlot::BeginPlot("##Some plot", "time", "value")) { + for (size_t pi = 0; pi < userData.size(); ++pi) { + auto stemsData = reinterpret_cast<const MultiplotData*>(metricsToDisplay[pi]); + // FIXME: display a message for other metrics + if (stemsData->type == MetricType::Uint64) { + ImPlot::PlotStems(deviceNames[pi], (const ImU64*)stemsData->X, (const ImU64*)stemsData->Y, metricSize); + } + } + ImPlot::EndPlot(); + } + break; default: break; } @@ -522,7 +538,8 @@ void displayDeviceHistograms(gui::WorkspaceGUIState& state, "lines", "histograms", "sparks", - "table"}; + "table", + "stems"}; ImGui::SameLine(); static enum MetricsDisplayStyle currentStyle = MetricsDisplayStyle::Lines; ImGui::Combo("##Select style", reinterpret_cast<int*>(¤tStyle), plotStyles, IM_ARRAYSIZE(plotStyles)); @@ -560,6 +577,7 @@ void displayDeviceHistograms(gui::WorkspaceGUIState& state, ImGui::EndGroup(); if (!currentMetricName.empty()) { switch (currentStyle) { + case MetricsDisplayStyle::Stems: case MetricsDisplayStyle::Histos: case MetricsDisplayStyle::Lines: { displayDeviceMetrics("Metrics", From eed91060c5954453e2399a9e1f685becf222a69a Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Mon, 2 Nov 2020 08:49:39 +0100 Subject: [PATCH 1176/1751] PWGHF: Adressing comments to the pull request #4727 (#4734) --- .../Analysis/HFCandidateSelectionTables.h | 8 +-- .../Tasks/PWGHF/HFLcCandidateSelector.cxx | 56 +++++++++---------- Analysis/Tasks/PWGHF/taskD0.cxx | 2 +- Analysis/Tasks/PWGJE/jetfinderhf.cxx | 2 +- 4 files changed, 31 insertions(+), 37 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h b/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h index fa5ffde065dc4..c8d231a401fae 100644 --- a/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h @@ -13,12 +13,12 @@ namespace o2::aod { -namespace hf_selcandidate +namespace hf_selcandidate_d0 { DECLARE_SOA_COLUMN(IsSelD0, isSelD0, int); DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int); -} // namespace hf_selcandidate -DECLARE_SOA_TABLE(HFSelD0Candidate, "AOD", "HFSELD0CAND", hf_selcandidate::IsSelD0, hf_selcandidate::IsSelD0bar); +} // namespace hf_selcandidate_d0 +DECLARE_SOA_TABLE(HFSelD0Candidate, "AOD", "HFSELD0CAND", hf_selcandidate_d0::IsSelD0, hf_selcandidate_d0::IsSelD0bar); } // namespace o2::aod namespace o2::aod @@ -27,7 +27,7 @@ namespace hf_selcandidate_lc { DECLARE_SOA_COLUMN(IsSelLc, isSelLc, int); } // namespace hf_selcandidate_lc -DECLARE_SOA_TABLE(HFSelLcCandidate, "AOD", "HFSELLcCAND", hf_selcandidate_lc::IsSelLc); +DECLARE_SOA_TABLE(HFSelLcCandidate, "AOD", "HFSELLCCAND", hf_selcandidate_lc::IsSelLc); } // namespace o2::aod #endif // O2_ANALYSIS_HFCANDIDATESELECTIONTABLES_H_ diff --git a/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx index c4865dd141d19..fbdb2edb72c57 100644 --- a/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx @@ -27,16 +27,16 @@ static const int npTBins = 10; static const int nCutVars = 8; //temporary until 2D array in configurable is solved - then move to json //m ptp ptk ptpi DCA sigmavtx dlenght cosp -constexpr double cuts[npTBins][nCutVars] = {{0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* pt<1 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 1<pt<2 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 2<pt<3 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 3<pt<4 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 4<pt<5 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 5<pt<6 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 6<pt<8 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 8<pt<12 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}, /* 12<pt<24 */ - {0.5, 0.1, 0.1, 0.1, 0.05, 0.09, 0.005, 0.}}; /* 24<pt<36 */ +constexpr double cuts[npTBins][nCutVars] = {{0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* pt<1 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 1<pt<2 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 2<pt<3 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 3<pt<4 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 4<pt<5 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 5<pt<6 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 6<pt<8 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 8<pt<12 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 12<pt<24 */ + {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}}; /* 24<pt<36 */ /// Struct for applying Lc selection cuts @@ -65,8 +65,11 @@ struct HFLcCandidateSelector { int getpTBin(T candpT) { double pTBins[npTBins + 1] = {0, 1., 2., 3., 4., 5., 6., 8., 12., 24., 36.}; + if (candpT < pTBins[0] || candpT >= pTBins[npTBins]) { + return -1; + } for (int i = 0; i < npTBins; i++) { - if (candpT >= pTBins[i] && candpT < pTBins[i + 1]) { + if (candpT < pTBins[i + 1]) { return i; } } @@ -187,7 +190,7 @@ struct HFLcCandidateSelector { template <typename T> bool selectionPIDTPC(const T& track, int nPDG, int nSigmaCut) { - double nSigma = 0.0; + double nSigma = 100.0; //arbitarily large value nPDG = TMath::Abs(nPDG); if (nPDG == 2212) { nSigma = track.tpcNSigmaPr(); @@ -195,15 +198,10 @@ struct HFLcCandidateSelector { nSigma = track.tpcNSigmaKa(); } else if (nPDG == 111) { nSigma = track.tpcNSigmaPi(); - - } else { - return nSigma = 100; //arbitarily large value - } - if (nSigma < nSigmaCut) { - return true; } else { return false; } + return nSigma < nSigmaCut; } /// Check if track is compatible with given TOF NSigma cut for a given flavour hypothesis @@ -215,7 +213,7 @@ struct HFLcCandidateSelector { template <typename T> bool selectionPIDTOF(const T& track, int nPDG, int nSigmaCut) { - double nSigma = 0.0; + double nSigma = 100.0; //arbitarily large value nPDG = TMath::Abs(nPDG); if (nPDG == 2212) { nSigma = track.tofNSigmaPr(); @@ -223,14 +221,10 @@ struct HFLcCandidateSelector { nSigma = track.tofNSigmaKa(); } else if (nPDG == 321) { nSigma = track.tofNSigmaPi(); - } else { - return nSigma = 100; //arbitarily large value - } - if (nSigma < nSigmaCut) { - return true; } else { return false; } + return nSigma < nSigmaCut; } /// PID selection on daughter track @@ -287,7 +281,7 @@ struct HFLcCandidateSelector { { int statusLc; // final selection flag : 0-rejected 1-accepted bool topolLc; - int pidLc, proton, kMinus, piPlus; + int pidLc, proton, kaonMinus, pionPlus; for (auto& hfCandProng3 : hfCandProng3s) { //looping over 3 prong candidates @@ -299,8 +293,8 @@ struct HFLcCandidateSelector { topolLc = true; pidLc = -1; proton = -1; - kMinus = -1; - piPlus = -1; + kaonMinus = -1; + pionPlus = -1; // daughter track validity selection if (!daughterSelection(trackPos1) || !daughterSelection(trackNeg1) || !daughterSelection(trackPos2)) { @@ -325,13 +319,13 @@ struct HFLcCandidateSelector { } proton = selectionPID(trackPos1, 2212); - kMinus = selectionPID(trackNeg1, 321); - piPlus = selectionPID(trackPos2, 211); + kaonMinus = selectionPID(trackNeg1, 321); + pionPlus = selectionPID(trackPos2, 211); - if (proton == 0 || kMinus == 0 || piPlus == 0) { + if (proton == 0 || kaonMinus == 0 || pionPlus == 0) { pidLc = 0; //exclude Lc } - if (proton == 1 && kMinus == 1 && piPlus == 1) { + if (proton == 1 && kaonMinus == 1 && pionPlus == 1) { pidLc = 1; //accept Lc } diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index dc913c950ae90..13ad591b7f557 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -47,7 +47,7 @@ struct TaskD0 { Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; - Filter filterSelectCandidates = (aod::hf_selcandidate::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate::isSelD0bar >= d_selectionFlagD0bar); + Filter filterSelectCandidates = (aod::hf_selcandidate_d0::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate_d0::isSelD0bar >= d_selectionFlagD0bar); void process(soa::Filtered<soa::Join<aod::HfCandProng2, aod::HFSelD0Candidate>> const& candidates) { diff --git a/Analysis/Tasks/PWGJE/jetfinderhf.cxx b/Analysis/Tasks/PWGJE/jetfinderhf.cxx index d32a7018e94b4..5f6bc347f7528 100644 --- a/Analysis/Tasks/PWGJE/jetfinderhf.cxx +++ b/Analysis/Tasks/PWGJE/jetfinderhf.cxx @@ -55,7 +55,7 @@ struct JetFinderHFTask { enum pdgCode { pdgD0 = 421 }; Filter trackCuts = (aod::track::pt > 0.15f && aod::track::eta > -0.9f && aod::track::eta < 0.9f); - Filter seltrack = (aod::hf_selcandidate::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate::isSelD0bar >= d_selectionFlagD0bar); + Filter seltrack = (aod::hf_selcandidate_d0::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate_d0::isSelD0bar >= d_selectionFlagD0bar); void process(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& tracks, From 298e88011cde8f300dae42f423dd5d582f706631 Mon Sep 17 00:00:00 2001 From: saganatt <8majak8@gmail.com> Date: Mon, 2 Nov 2020 08:51:47 +0100 Subject: [PATCH 1177/1751] Merged hist and output obj sinks (#4730) --- Analysis/Tutorials/src/histogramRegistry.cxx | 14 ++ .../include/Framework/CommonDataProcessors.h | 5 +- .../include/Framework/HistogramRegistry.h | 2 +- Framework/Core/src/CommonDataProcessors.cxx | 162 ++---------------- Framework/Core/src/WorkflowHelpers.cxx | 32 +--- 5 files changed, 43 insertions(+), 172 deletions(-) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index 773c90377f0fd..e8f29677eeaed 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -199,9 +199,23 @@ struct DTask { } }; +struct ETask { + OutputObj<TH1F> phiH{TH1F("phi", "phi", 100, 0., 2. * M_PI)}; + OutputObj<TH1F> etaH{TH1F("eta", "eta", 102, -2.01, 2.01)}; + + void process(aod::Tracks const& tracks) + { + for (auto& track : tracks) { + phiH->Fill(track.phi()); + etaH->Fill(track.eta()); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ + adaptAnalysisTask<ETask>("output-obj-test"), adaptAnalysisTask<ATask>("eta-and-phi-histograms"), adaptAnalysisTask<BTask>("filtered-histograms"), adaptAnalysisTask<CTask>("dimension-test"), diff --git a/Framework/Core/include/Framework/CommonDataProcessors.h b/Framework/Core/include/Framework/CommonDataProcessors.h index 8724029468cd6..c8162fbd3487f 100644 --- a/Framework/Core/include/Framework/CommonDataProcessors.h +++ b/Framework/Core/include/Framework/CommonDataProcessors.h @@ -24,12 +24,9 @@ using outputObjects = std::vector<std::pair<uint32_t, std::vector<std::string>>> /// Helpers to create a few general data processors struct CommonDataProcessors { - /// Match all inputs of kind HIST and write them to a ROOT file, - /// one root file per originating task. - static DataProcessorSpec getHistogramRegistrySink(outputObjects const& objmap, const outputTasks& tskmap); /// Match all inputs of kind ATSK and write them to a ROOT file, /// one root file per originating task. - static DataProcessorSpec getOutputObjSink(outputObjects const& objmap, const outputTasks& tskmap); + static DataProcessorSpec getOutputObjHistSink(outputObjects const& objmap, const outputTasks& tskmap); /// Given the list of @a danglingInputs @return a DataProcessor which does /// a binary dump for all the dangling inputs matching the Timeframe /// lifetime. @a unmatched will be filled with all the InputSpecs which are diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 4d4c9d6b4dfb0..ced72a9ce591c 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -538,7 +538,7 @@ class HistogramRegistry /// @return the associated OutputSpec OutputSpec const spec() { - ConcreteDataMatcher matcher{"HIST", "\0", 0}; + ConcreteDataMatcher matcher{"ATSK", "\0", 0}; strncpy(matcher.description.str, mName.data(), 16); return OutputSpec{OutputLabel{mName}, matcher}; } diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 509476072494c..5fd6e9abd94ff 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -72,14 +72,14 @@ const static std::unordered_map<OutputObjHandlingPolicy, std::string> ROOTfileNa {OutputObjHandlingPolicy::QAObject, "QAResults.root"}}; // ============================================================================= -DataProcessorSpec CommonDataProcessors::getHistogramRegistrySink(outputObjects const& objmap, const outputTasks& tskmap) +DataProcessorSpec CommonDataProcessors::getOutputObjHistSink(outputObjects const& objmap, outputTasks const& tskmap) { auto writerFunction = [objmap, tskmap](InitContext& ic) -> std::function<void(ProcessingContext&)> { auto& callbacks = ic.services().get<CallbackService>(); auto inputObjects = std::make_shared<std::vector<std::pair<InputObjectRoute, InputObject>>>(); auto endofdatacb = [inputObjects](EndOfStreamContext& context) { - LOG(DEBUG) << "Writing merged histograms to file"; + LOG(DEBUG) << "Writing merged objects and histograms to file"; if (inputObjects->empty()) { LOG(ERROR) << "Output object map is empty!"; context.services().get<ControlService>().readyToQuit(QuitRequest::Me); @@ -123,149 +123,25 @@ DataProcessorSpec CommonDataProcessors::getHistogramRegistrySink(outputObjects c }; TDirectory* currentDir = f[route.policy]->GetDirectory(currentDirectory.c_str()); - TList* outputList = (TList*)entry.obj; - outputList->SetOwner(false); - - // if registry should live in dedicated folder a TNamed object is appended to the list - if (outputList->Last()->IsA() == TNamed::Class()) { - delete outputList->Last(); - outputList->RemoveLast(); - currentDir = currentDir->mkdir(outputList->GetName(), outputList->GetName(), true); - } - - writeListToFile(outputList, currentDir); - outputList->SetOwner(); - delete outputList; - entry.obj = nullptr; - } - } - for (auto i = 0u; i < OutputObjHandlingPolicy::numPolicies; ++i) { - if (f[i] != nullptr) { - f[i]->Close(); - } - } - LOG(INFO) << "All outputs merged in their respective target files"; - context.services().get<ControlService>().readyToQuit(QuitRequest::Me); - }; - - callbacks.set(CallbackService::Id::EndOfStream, endofdatacb); - return [inputObjects, objmap, tskmap](ProcessingContext& pc) mutable -> void { - auto const& ref = pc.inputs().get("y"); - if (!ref.header) { - LOG(ERROR) << "Header not found"; - return; - } - if (!ref.payload) { - LOG(ERROR) << "Payload not found"; - return; - } - auto datah = o2::header::get<o2::header::DataHeader*>(ref.header); - if (!datah) { - LOG(ERROR) << "No data header in stack"; - return; - } - - auto objh = o2::header::get<o2::framework::OutputObjHeader*>(ref.header); - if (!objh) { - LOG(ERROR) << "No output object header in stack"; - return; - } - - FairTMessage tm(const_cast<char*>(ref.payload), static_cast<int>(datah->payloadSize)); - InputObject obj; - obj.kind = tm.GetClass(); - if (obj.kind == nullptr) { - LOG(error) << "Cannot read class info from buffer."; - return; - } - - auto policy = objh->mPolicy; - auto hash = objh->mTaskHash; - - obj.obj = tm.ReadObjectAny(obj.kind); - TNamed* named = static_cast<TNamed*>(obj.obj); - obj.name = named->GetName(); - - auto hpos = std::find_if(tskmap.begin(), tskmap.end(), [&](auto&& x) { return x.first == hash; }); - if (hpos == tskmap.end()) { - LOG(ERROR) << "No task found for hash " << hash; - return; - } - auto taskname = hpos->second; - auto opos = std::find_if(objmap.begin(), objmap.end(), [&](auto&& x) { return x.first == hash; }); - if (opos == objmap.end()) { - LOG(ERROR) << "No object list found for task " << taskname << " (hash=" << hash << ")"; - return; - } - auto objects = opos->second; - if (std::find(objects.begin(), objects.end(), obj.name) == objects.end()) { - LOG(ERROR) << "No object " << obj.name << " in map for task " << taskname; - return; - } - auto nameHash = compile_time_hash(obj.name.c_str()); - InputObjectRoute key{obj.name, nameHash, taskname, hash, policy}; - auto existing = std::find_if(inputObjects->begin(), inputObjects->end(), [&](auto&& x) { return (x.first.uniqueId == nameHash) && (x.first.taskHash == hash); }); - if (existing == inputObjects->end()) { - inputObjects->push_back(std::make_pair(key, obj)); - return; - } - auto merger = existing->second.kind->GetMerge(); - if (!merger) { - LOG(ERROR) << "Already one unmergeable object found for " << obj.name; - return; - } - - TList coll; - coll.Add(static_cast<TObject*>(obj.obj)); - merger(existing->second.obj, &coll, nullptr); - }; - }; - - DataProcessorSpec spec{ - "internal-dpl-global-analysis-file-sink", - {InputSpec("y", DataSpecUtils::dataDescriptorMatcherFrom(header::DataOrigin{"HIST"}))}, - Outputs{}, - AlgorithmSpec(writerFunction), - {}}; - - return spec; -} - -DataProcessorSpec CommonDataProcessors::getOutputObjSink(outputObjects const& objmap, outputTasks const& tskmap) -{ - auto writerFunction = [objmap, tskmap](InitContext& ic) -> std::function<void(ProcessingContext&)> { - auto& callbacks = ic.services().get<CallbackService>(); - auto inputObjects = std::make_shared<std::vector<std::pair<InputObjectRoute, InputObject>>>(); - - auto endofdatacb = [inputObjects](EndOfStreamContext& context) { - LOG(DEBUG) << "Writing merged objects to file"; - if (inputObjects->empty()) { - LOG(ERROR) << "Output object map is empty!"; - context.services().get<ControlService>().readyToQuit(QuitRequest::Me); - return; - } - std::string currentDirectory = ""; - std::string currentFile = ""; - TFile* f[OutputObjHandlingPolicy::numPolicies]; - for (auto i = 0u; i < OutputObjHandlingPolicy::numPolicies; ++i) { - f[i] = nullptr; - } - for (auto& [route, entry] : *inputObjects) { - auto file = ROOTfileNames.find(route.policy); - if (file != ROOTfileNames.end()) { - auto filename = file->second; - if (f[route.policy] == nullptr) { - f[route.policy] = TFile::Open(filename.c_str(), "RECREATE"); - } - auto nextDirectory = route.directory; - if ((nextDirectory != currentDirectory) || (filename != currentFile)) { - if (!f[route.policy]->FindKey(nextDirectory.c_str())) { - f[route.policy]->mkdir(nextDirectory.c_str()); + TNamed* named = static_cast<TNamed*>(entry.obj); + if (named->InheritsFrom(TList::Class())) { + TList* outputList = (TList*)entry.obj; + outputList->SetOwner(false); + + // if registry should live in dedicated folder a TNamed object is appended to the list + if (outputList->Last()->IsA() == TNamed::Class()) { + delete outputList->Last(); + outputList->RemoveLast(); + currentDir = currentDir->mkdir(outputList->GetName(), outputList->GetName(), true); } - currentDirectory = nextDirectory; - currentFile = filename; + + writeListToFile(outputList, currentDir); + outputList->SetOwner(); + delete outputList; + entry.obj = nullptr; + } else { + currentDir->WriteObjectAny(entry.obj, entry.kind, entry.name.c_str()); } - (f[route.policy]->GetDirectory(currentDirectory.c_str()))->WriteObjectAny(entry.obj, entry.kind, entry.name.c_str()); } } for (auto i = 0u; i < OutputObjHandlingPolicy::numPolicies; ++i) { diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index c3cf4ccb4304a..fd1ddd6dbcf06 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -267,12 +267,10 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext std::vector<InputSpec> requestedCCDBs; std::vector<OutputSpec> providedCCDBs; - std::vector<OutputSpec> providedOutputObj; - std::vector<OutputSpec> providedHist; + std::vector<OutputSpec> providedOutputObjHist; outputTasks outTskMap; - outputObjects outObjMap; - outputObjects outHistMap; + outputObjects outObjHistMap; for (size_t wi = 0; wi < workflow.size(); ++wi) { auto& processor = workflow[wi]; @@ -347,18 +345,10 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext } else if (DataSpecUtils::partialMatch(output, header::DataOrigin{"RN2"})) { providedAODs.emplace_back(output); } else if (DataSpecUtils::partialMatch(output, header::DataOrigin{"ATSK"})) { - providedOutputObj.emplace_back(output); - auto it = std::find_if(outObjMap.begin(), outObjMap.end(), [&](auto&& x) { return x.first == hash; }); - if (it == outObjMap.end()) { - outObjMap.push_back({hash, {output.binding.value}}); - } else { - it->second.push_back(output.binding.value); - } - } else if (DataSpecUtils::partialMatch(output, header::DataOrigin{"HIST"})) { - providedHist.emplace_back(output); - auto it = std::find_if(outHistMap.begin(), outHistMap.end(), [&](auto&& x) { return x.first == hash; }); - if (it == outHistMap.end()) { - outHistMap.push_back({hash, {output.binding.value}}); + providedOutputObjHist.emplace_back(output); + auto it = std::find_if(outObjHistMap.begin(), outObjHistMap.end(), [&](auto&& x) { return x.first == hash; }); + if (it == outObjHistMap.end()) { + outObjHistMap.push_back({hash, {output.binding.value}}); } else { it->second.push_back(output.binding.value); } @@ -432,14 +422,8 @@ 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.empty() == false) { - auto rootSink = CommonDataProcessors::getOutputObjSink(outObjMap, outTskMap); - extraSpecs.push_back(rootSink); - } - // This is to inject a file sink so that any dangling HIST object is written - // to a ROOT file. - if (providedHist.empty() == false) { - auto rootSink = CommonDataProcessors::getHistogramRegistrySink(outHistMap, outTskMap); + if (providedOutputObjHist.empty() == false) { + auto rootSink = CommonDataProcessors::getOutputObjHistSink(outObjHistMap, outTskMap); extraSpecs.push_back(rootSink); } From 57a91afd0512f826f3b4aad0aaa5e5aaa3a9e6a2 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Mon, 2 Nov 2020 08:52:56 +0100 Subject: [PATCH 1178/1751] HistogramRegistry: add print function (#4737) - fix size calculation for ndim histograms - add print function to show registry content and size estimates - sort histograms in output file alphabetically by default --- .../include/Framework/HistogramRegistry.h | 78 ++++++++++++------- Framework/Core/src/HistogramRegistry.cxx | 74 ++++++++++++++++++ 2 files changed, 125 insertions(+), 27 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index ced72a9ce591c..8609f623ccd9a 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -31,6 +31,8 @@ #include <TProfile2D.h> #include <TProfile3D.h> #include <TList.h> +#include <TDataMember.h> +#include <TDataType.h> #include <string> #include <variant> @@ -267,6 +269,20 @@ struct HistFactory { return HistogramCreationCallbacks.at(histSpec.config.type)(histSpec); } + // helper function to get the axis via index for any type of root histogram + template <typename T> + static TAxis* getAxis(const int i, std::shared_ptr<T>& hist) + { + if constexpr (std::is_base_of_v<THnBase, T>) { + return hist->GetAxis(i); + } else { + return (i == 0) ? hist->GetXaxis() + : (i == 1) ? hist->GetYaxis() + : (i == 2) ? hist->GetZaxis() + : nullptr; + } + } + private: static const std::map<HistType, std::function<HistPtr(const HistogramSpec&)>> HistogramCreationCallbacks; @@ -294,20 +310,6 @@ struct HistFactory { return nullptr; } - // helper function to get the axis via index for any type of root histogram - template <typename T> - static TAxis* getAxis(const int i, std::shared_ptr<T>& hist) - { - if constexpr (std::is_base_of_v<THnBase, T>) { - return hist->GetAxis(i); - } else { - return (i == 0) ? hist->GetXaxis() - : (i == 1) ? hist->GetYaxis() - : (i == 2) ? hist->GetZaxis() - : nullptr; - } - } - // helper function to cast the actual histogram type (e.g. TH2F) to the correct interface type (e.g. TH2) that is stored in the HistPtr variant template <typename T> static std::optional<HistPtr> castToVariant(std::shared_ptr<TObject> obj) @@ -389,10 +391,6 @@ struct HistFiller { } // function that returns rough estimate for the size of a histogram in MB - // should be somewhat realistic for TH{1,2,3} - // for ndimensional arrays the memory is allocated lazily so the size estimates might - // not yet be entirely correct and should be seen as a 'worst case' scenario for now - // this will require some more detailed understanding of the root interna... template <typename T> static double getSize(std::shared_ptr<T>& hist, double fillFraction = 1.) { @@ -400,14 +398,36 @@ struct HistFiller { if constexpr (std::is_base_of_v<TH1, T>) { size = hist->GetNcells() * (HistFiller::getBaseElementSize(hist.get()) + ((hist->GetSumw2()->fN) ? sizeof(double) : 0.)); } else if constexpr (std::is_base_of_v<THn, T>) { - return hist->GetNbins() * (HistFiller::getBaseElementSize(hist.get()) + ((hist->GetSumw2() != -1.) ? sizeof(double) : 0.)); + size = hist->GetNbins() * (HistFiller::getBaseElementSize(hist.get()) + ((hist->GetSumw2() != -1.) ? sizeof(double) : 0.)); } else if constexpr (std::is_base_of_v<THnSparse, T>) { - double nbinsTotal = 1.; + // THnSparse has massive overhead and should only be used when histogram is large and a very small fraction of bins is filled + double nBinsTotal = 1.; + int compCoordSize = 0; // size required to store a compact coordinate representation for (int d = 0; d < hist->GetNdimensions(); ++d) { - nbinsTotal *= hist->GetAxis(d)->GetNbins() + 2; + int nBins = hist->GetAxis(d)->GetNbins() + 2; + nBinsTotal *= nBins; + + // number of bits needed to store compact coordinates + int b = 1; + while (nBins /= 2) { + ++b; + } + compCoordSize += b; } - double overhead = 4.; // probably often less; unfortunatley we cannot access hist->GetCompactCoord()->GetBufferSize(); - size = fillFraction * nbinsTotal * (HistFiller::getBaseElementSize(hist.get()) + overhead + ((hist->GetSumw2() != -1.) ? sizeof(double) : 0.)); + compCoordSize = (compCoordSize + 7) / 8; // turn bits into bytes + + // THnSparse stores the data in an array of chunks (THnSparseArrayChunk), each containing a fixed number of bins (e.g. 1024 * 16) + double nBinsFilled = fillFraction * nBinsTotal; + int nCunks = ceil(nBinsFilled / hist->GetChunkSize()); + int chunkOverhead = sizeof(THnSparseArrayChunk); + + // each chunk holds array of compact bin-coordinates and an array of bin content (+ one of bin error if requested) + double binSize = compCoordSize + HistFiller::getBaseElementSize(hist.get()) + ((hist->GetSumw2() != -1.) ? sizeof(double) : 0.); + size = nCunks * (chunkOverhead + hist->GetChunkSize() * binSize); + // since THnSparse must keep track of all the stored bins, it stores a map that + // relates the compact bin coordinates (or a hash thereof) to a linear index + // this index determines in which chunk and therein at which position to find / store bin coordinate and content + size += nBinsFilled * 3 * sizeof(Long64_t); // hash, key, value; not sure why 3 are needed here... } return size / 1048576.; } @@ -418,8 +438,8 @@ struct HistFiller { template <typename T> static int getBaseElementSize(T* ptr) { - if constexpr (std::is_base_of_v<TH1, T>) { - return getBaseElementSize<TArrayD, TArrayF, TArrayC, TArrayI, TArrayC>(ptr); + if constexpr (std::is_base_of_v<TH1, T> || std::is_base_of_v<THnSparse, T>) { + return getBaseElementSize<TArrayD, TArrayF, TArrayC, TArrayI, TArrayC, TArrayL>(ptr); } else { return getBaseElementSize<double, float, int, short, char, long>(ptr); } @@ -443,7 +463,8 @@ struct HistFiller { } } else if constexpr (std::is_base_of_v<THnSparse, T>) { if (dynamic_cast<THnSparseT<B>*>(ptr)) { - return sizeof(B); + TDataMember* dm = B::Class()->GetDataMember("fArray"); + return dm ? dm->GetDataType()->Size() : 0; } } else if constexpr (std::is_base_of_v<TH1, T>) { if (auto arrayPtr = dynamic_cast<B*>(ptr)) { @@ -462,7 +483,7 @@ struct HistFiller { class HistogramRegistry { public: - HistogramRegistry(char const* const name_, std::vector<HistogramSpec> histSpecs_ = {}, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, bool sortHistos_ = false, bool createRegistryDir_ = false) + HistogramRegistry(char const* const name_, std::vector<HistogramSpec> histSpecs_ = {}, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, bool sortHistos_ = true, bool createRegistryDir_ = false) : mName(name_), mPolicy(policy_), mRegistryKey(), mRegistryValue(), mSortHistos(sortHistos_), mCreateRegistryDir(createRegistryDir_) { mRegistryKey.fill(0u); @@ -653,6 +674,9 @@ class HistogramRegistry return size; } + // print summary of the histograms stored in registry + void print(bool showAxisDetails = false); + // lookup distance counter for benchmarking mutable uint32_t lookup = 0; diff --git a/Framework/Core/src/HistogramRegistry.cxx b/Framework/Core/src/HistogramRegistry.cxx index ef336c52ce208..ba217068edaad 100644 --- a/Framework/Core/src/HistogramRegistry.cxx +++ b/Framework/Core/src/HistogramRegistry.cxx @@ -34,4 +34,78 @@ const std::map<HistType, std::function<HistPtr(const HistogramSpec&)>> HistFacto #undef CALLB +void HistogramRegistry::print(bool showAxisDetails) +{ + std::vector<double> fillFractions{0.1, 0.25, 0.5}; + std::vector<double> totalSizes(fillFractions.size()); + + uint32_t nHistos{}; + bool containsSparseHist{}; + auto printHistInfo = [&](auto&& hist) { + if (hist) { + using T = std::decay_t<decltype(*hist)>; + bool isSparse{}; + if (hist->InheritsFrom(THnSparse::Class())) { + isSparse = true; + containsSparseHist = true; + } + ++nHistos; + std::vector<double> sizes; + std::string sizeInfo{}; + if (isSparse) { + std::transform(std::begin(fillFractions), std::end(fillFractions), std::back_inserter(sizes), [&hist](auto& fraction) { return HistFiller::getSize(hist, fraction); }); + for (int i = 0; i < fillFractions.size(); ++i) { + sizeInfo += fmt::format("{:.2f} kB ({:.0f} %)", sizes[i] * 1024, fillFractions[i] * 100); + if (i != fillFractions.size() - 1) { + sizeInfo += ", "; + } + } + } else { + double size = HistFiller::getSize(hist); + sizes.resize(fillFractions.size(), size); + sizeInfo = fmt::format("{:.2f} kB", sizes[0] * 1024); + } + std::transform(totalSizes.begin(), totalSizes.end(), sizes.begin(), totalSizes.begin(), std::plus<double>()); + LOGF(INFO, "Hist %03d: %-35s %-19s [%s]", nHistos, hist->GetName(), hist->IsA()->GetName(), sizeInfo); + + if (showAxisDetails) { + int nDim = 0; + if constexpr (std::is_base_of_v<THnBase, T>) { + nDim = hist->GetNdimensions(); + } else if constexpr (std::is_base_of_v<TH1, T>) { + nDim = hist->GetDimension(); + } + for (int d = 0; d < nDim; ++d) { + TAxis* axis = HistFactory::getAxis(d, hist); + LOGF(INFO, "- Axis %d: %-20s (%d bins)", d, axis->GetTitle(), axis->GetNbins()); + } + } + } + }; + + std::string titleString{"======================== HistogramRegistry ========================"}; + LOGF(INFO, ""); + LOGF(INFO, "%s", titleString); + LOGF(INFO, "%s\"%s\"", std::string((int)(0.5 * titleString.size() - (1 + 0.5 * mName.size())), ' '), mName); + std::sort(mRegisteredNames.begin(), mRegisteredNames.end()); + for (auto& curHistName : mRegisteredNames) { + std::visit(printHistInfo, mRegistryValue[getHistIndex(curHistName.data())]); + } + std::string totalSizeInfo{}; + if (containsSparseHist) { + for (int i = 0; i < totalSizes.size(); ++i) { + totalSizeInfo += fmt::format("{:.2f} MB ({:.0f} %)", totalSizes[i], fillFractions[i] * 100); + if (i != totalSizes.size() - 1) { + totalSizeInfo += ", "; + } + } + } else { + totalSizeInfo = fmt::format("{:.2f} MB", totalSizes[0]); + } + LOGF(INFO, "%s", std::string(titleString.size(), '='), titleString); + LOGF(INFO, "Total: %d histograms, ca. %s", nHistos, totalSizeInfo); + LOGF(INFO, "%s", std::string(titleString.size(), '='), titleString); + LOGF(INFO, ""); +} + } // namespace o2::framework From fbd17a953d157438f2ef79eee62f350306279fd7 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 2 Nov 2020 09:42:47 +0100 Subject: [PATCH 1179/1751] Jobutils: option to keep scripts --- Utilities/Tools/jobutils.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index a9a5cd814ac5c..7bf9552e0338c 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -72,7 +72,7 @@ taskwrapper() { if [ "${JOBUTILS_SKIPDONE}" ]; then if [ -f "${logfile}_done" ]; then echo "Skipping task since file ${logfile}_done found"; - rm ${SCRIPTNAME} 2> /dev/null + [ ! "${JOBUTILS_KEEPJOBSCRIPT}" ] && rm ${SCRIPTNAME} 2> /dev/null return 0 fi fi @@ -146,7 +146,7 @@ taskwrapper() { done RC_ACUM=$((RC_ACUM+1)) - rm ${SCRIPTNAME} 2> /dev/null + [ ! "${JOBUTILS_KEEPJOBSCRIPT}" ] && rm ${SCRIPTNAME} 2> /dev/null return 1 fi @@ -184,7 +184,7 @@ taskwrapper() { else echo "command ${command} had nonzero exit code ${RC}" fi - rm ${SCRIPTNAME} 2> /dev/null + [ ! "${JOBUTILS_KEEPJOBSCRIPT}" ] && rm ${SCRIPTNAME} 2> /dev/null return ${RC} } From 4685f5ef6c3a8f616b281561829b2232de66a589 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 2 Nov 2020 09:43:30 +0100 Subject: [PATCH 1180/1751] monitor-mem: Return with actual command exit status --- Utilities/Tools/monitor-mem.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Utilities/Tools/monitor-mem.sh b/Utilities/Tools/monitor-mem.sh index d4acdfa80a89b..159bf83ca5a66 100755 --- a/Utilities/Tools/monitor-mem.sh +++ b/Utilities/Tools/monitor-mem.sh @@ -43,6 +43,9 @@ while [ 1 ] ; do sleep ${JOBUTILS_MONITORMEM_SLEEP:-0.005} done +# record return code of original command +wait ${PID} +RC=$? # print summary MAXMEM=`awk '/^[0-9]/{ for(i=1; i<=NF;i++) j+=$i; print j; j=0 }' ${memlogfile} | awk 'BEGIN {m = 0} //{if($1>m){m=$1}} END {print m}'` @@ -50,3 +53,5 @@ AVGMEM=`awk '/^[0-9]/{ for(i=1; i<=NF;i++) j+=$i; print j; j=0 }' ${memlogfile} echo "PROCESS MAX MEM = ${MAXMEM}" echo "PROCESS AVG MEM = ${AVGMEM}" + +exit ${RC} From b0741b27a489577c65933b5a8cc35828dd12ac96 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 2 Nov 2020 09:44:23 +0100 Subject: [PATCH 1181/1751] full_system_test: record metrics only for successful run --- prodtests/full_system_test.sh | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 4076170ae001d..32df683595e73 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -100,20 +100,22 @@ o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable [ -f "${logfile}_done" ] && [ "$RC" = 0 ] && SUCCESS=1 echo "success_${STAGE},${TAG} value=${SUCCESS}" >> ${METRICFILE} - # runtime - walltime=`grep "#walltime" ${logfile}_time | awk '//{print $2}'` - echo "walltime_${STAGE},${TAG} value=${walltime}" >> ${METRICFILE} - - # memory - maxmem=`awk '/PROCESS MAX MEM/{print $5}' ${logfile}` # in MB - avgmem=`awk '/PROCESS AVG MEM/{print $5}' ${logfile}` # in MB - echo "maxmem_${STAGE},${TAG} value=${maxmem}" >> ${METRICFILE} - echo "avgmem_${STAGE},${TAG} value=${avgmem}" >> ${METRICFILE} - - # some physics quantities - tpctracks=`grep "tpc-tracker" ${logfile} | grep -e "found.*track" | awk '//{print $4}'` - echo "tpctracks_${STAGE},${TAG} value=${tpctracks}" >> ${METRICFILE} - tpcclusters=`grep -e "Event has.*TPC Clusters" ${logfile} | awk '//{print $5}'` - echo "tpcclusters_${STAGE},${TAG} value=${tpcclusters}" >> ${METRICFILE} + if [ "${SUCCESS}" = "1" ]; then + # runtime + walltime=`grep "#walltime" ${logfile}_time | awk '//{print $2}'` + echo "walltime_${STAGE},${TAG} value=${walltime}" >> ${METRICFILE} + + # memory + maxmem=`awk '/PROCESS MAX MEM/{print $5}' ${logfile}` # in MB + avgmem=`awk '/PROCESS AVG MEM/{print $5}' ${logfile}` # in MB + echo "maxmem_${STAGE},${TAG} value=${maxmem}" >> ${METRICFILE} + echo "avgmem_${STAGE},${TAG} value=${avgmem}" >> ${METRICFILE} + + # some physics quantities + tpctracks=`grep "tpc-tracker" ${logfile} | grep -e "found.*track" | awk '//{print $4}'` + echo "tpctracks_${STAGE},${TAG} value=${tpctracks}" >> ${METRICFILE} + tpcclusters=`grep -e "Event has.*TPC Clusters" ${logfile} | awk '//{print $5}'` + echo "tpcclusters_${STAGE},${TAG} value=${tpcclusters}" >> ${METRICFILE} + fi done From 0355306e80cb24398b1a98c9b876509fe82efc1a Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 2 Nov 2020 11:59:52 +0100 Subject: [PATCH 1182/1751] removing obsolete matcher tasks (#4740) --- Analysis/Tasks/CMakeLists.txt | 10 ------ Analysis/Tasks/run2Matcher.cxx | 37 ------------------- Analysis/Tasks/run3Matcher.cxx | 38 -------------------- Analysis/Tutorials/src/ZDCVZeroIteration.cxx | 2 -- 4 files changed, 87 deletions(-) delete mode 100644 Analysis/Tasks/run2Matcher.cxx delete mode 100644 Analysis/Tasks/run3Matcher.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index e56c4c6476024..44ce185982209 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -91,13 +91,3 @@ o2_add_dpl_workflow(weak-decay-indices SOURCES weakDecayIndices.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(run2-matcher - SOURCES run2Matcher.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel - COMPONENT_NAME Analysis) - -o2_add_dpl_workflow(run3-matcher - SOURCES run3Matcher.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel - COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/run2Matcher.cxx b/Analysis/Tasks/run2Matcher.cxx deleted file mode 100644 index 53fb49d731c44..0000000000000 --- a/Analysis/Tasks/run2Matcher.cxx +++ /dev/null @@ -1,37 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - -// This task prepares the matching between collisions and other tables available -// in run2 converted data through the bc column. -// For an example how to use this, please see: o2-analysistutorial-zdc-vzero-iteration - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -struct Run2Matcher { - BuildsExclusive<aod::Run2MatchedExclusive> matched_e; - Builds<aod::Run2MatchedSparse> matched_s; - BuildsExclusive<aod::BCCollisionsExclusive> bc_e; - Builds<aod::BCCollisionsSparse> bc; - void init(o2::framework::InitContext&) - { - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<Run2Matcher>("produce-run2-bc-matching"), - }; -} diff --git a/Analysis/Tasks/run3Matcher.cxx b/Analysis/Tasks/run3Matcher.cxx deleted file mode 100644 index 10263ca6fa2d3..0000000000000 --- a/Analysis/Tasks/run3Matcher.cxx +++ /dev/null @@ -1,38 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - -// This task prepares the matching between collisions and other tables available -// in run 3 data. -// For an example how to use this (but based on run 2 data), -// please see: o2-analysistutorial-zdc-vzero-iteration - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -struct Run3Matcher { - BuildsExclusive<aod::Run3MatchedExclusive> matched_e; - Builds<aod::Run3MatchedSparse> matched_s; - BuildsExclusive<aod::BCCollisionsExclusive> bc_e; - Builds<aod::BCCollisionsSparse> bc; - void init(o2::framework::InitContext&) - { - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<Run3Matcher>("produce-run3-bc-matching"), - }; -} diff --git a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx index 2cebd397f4c36..fc89aca047b3c 100644 --- a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx +++ b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx @@ -17,8 +17,6 @@ using namespace o2::framework::expressions; // This task shows how to access the ZDC and FV0A information which belongs to a collision // The association is made through the BC column (and in Run 3 may not be unique!) -// To run this workflow, the o2-analysis-run2-matcher has to be run as well. -// Example: o2-analysis-run2-matcher --aod-file AO2D.root | o2-analysistutorial-zdc-vzero-iteration // This example access the collisions and the related FV0A information. // Note that one has to subscribe to aod::Collisions const& and aod::FV0As const& to load From a7056319961c038fec44d9c0173d29d62cb16f88 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Mon, 2 Nov 2020 15:06:41 +0300 Subject: [PATCH 1183/1751] Detectors/TOF: make readability-braces-around-statements happy --- Detectors/TOF/base/src/Digit.cxx | 11 +- Detectors/TOF/base/src/Geo.cxx | 115 ++++++++++------ Detectors/TOF/base/src/Strip.cxx | 3 +- Detectors/TOF/base/src/WindowFiller.cxx | 41 ++++-- Detectors/TOF/base/test/testTOFIndex.cxx | 3 +- Detectors/TOF/calibration/src/CalibTOF.cxx | 93 ++++++++----- Detectors/TOF/calibration/src/CalibTOFapi.cxx | 3 +- .../calibration/src/CollectCalibInfoTOF.cxx | 5 +- .../TOF/calibration/src/TOFCalibCollector.cxx | 6 +- .../calibration/src/TOFChannelCalibrator.cxx | 33 +++-- .../testWorkflow/TOFCalibCollectorSpec.h | 3 +- .../TOFCalibCollectorWriterSpec.h | 3 +- .../testWorkflow/tof-calib-workflow.cxx | 6 +- .../include/TOFCompression/Compressor.h | 9 +- Detectors/TOF/compression/src/Compressor.cxx | 69 ++++++---- .../TOF/compression/src/CompressorTask.cxx | 3 +- .../src/tof-compressed-inspector.cxx | 5 +- .../include/TOFReconstruction/CTFCoder.h | 6 +- .../include/TOFReconstruction/DecoderBase.h | 6 +- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 8 +- .../TOF/reconstruction/src/Clusterer.cxx | 12 +- .../TOF/reconstruction/src/ClustererTask.cxx | 12 +- .../TOF/reconstruction/src/DataReader.cxx | 3 +- Detectors/TOF/reconstruction/src/Decoder.cxx | 45 ++++--- .../TOF/reconstruction/src/DecoderBase.cxx | 9 +- Detectors/TOF/reconstruction/src/Encoder.cxx | 27 ++-- Detectors/TOF/simulation/src/Detector.cxx | 88 ++++++++----- Detectors/TOF/simulation/src/Digitizer.cxx | 123 +++++++++++------- .../TOF/simulation/src/DigitizerTask.cxx | 6 +- .../workflow/src/CompressedAnalysisTask.cxx | 3 +- .../workflow/src/CompressedDecodingTask.cxx | 123 ++++++++++++------ .../workflow/src/CompressedInspectorTask.cxx | 18 ++- .../TOF/workflow/src/DigitReaderSpec.cxx | 3 +- .../TOF/workflow/src/TOFClusterizerSpec.cxx | 6 +- .../TOF/workflow/src/TOFRawWriterSpec.cxx | 6 +- 35 files changed, 593 insertions(+), 322 deletions(-) diff --git a/Detectors/TOF/base/src/Digit.cxx b/Detectors/TOF/base/src/Digit.cxx index a019e61d6b32d..e1de38006e59d 100644 --- a/Detectors/TOF/base/src/Digit.cxx +++ b/Detectors/TOF/base/src/Digit.cxx @@ -68,16 +68,17 @@ void Digit::getPhiAndEtaIndex(int& phi, int& eta) const chan = getChannel(); // note that inside the strip the digits are ordered per channel number Geo::getVolumeIndices(chan, detId); // Get volume index from channel index eta = detId[2] /*strip*/ * 2 + detId[3] /*pad Z*/; - if (detId[1] /*module*/ == 0) + if (detId[1] /*module*/ == 0) { eta += 0; - else if (detId[1] == 1) + } else if (detId[1] == 1) { eta += 38; - else if (detId[1] == 2) + } else if (detId[1] == 2) { eta += 76; - else if (detId[1] == 3) + } else if (detId[1] == 3) { eta += 106; - else if (detId[1] == 4) + } else if (detId[1] == 4) { eta += 144; + } phi = detId[0] /*phi sector*/ * 48 + detId[4] /*pad x*/; return; diff --git a/Detectors/TOF/base/src/Geo.cxx b/Detectors/TOF/base/src/Geo.cxx index ab5cc797b4a2b..79c12f697d934 100644 --- a/Detectors/TOF/base/src/Geo.cxx +++ b/Detectors/TOF/base/src/Geo.cxx @@ -45,8 +45,9 @@ void Geo::Init() for (Int_t iplate = 0; iplate < NPLATES; iplate++) { det[1] = iplate; - if (iplate == 2 && (isector == 13 || isector == 14 || isector == 15)) + if (iplate == 2 && (isector == 13 || isector == 14 || isector == 15)) { continue; // PHOS HOLES + } for (Int_t istrip = 0; istrip < NSTRIPC; istrip++) { // maximum number of strip is 19 for plate B and C det[2] = istrip; @@ -72,8 +73,9 @@ void Geo::Init() Double_t rotationAngles[6] = {90., 90. /*+ (isector + 0.5) * PHISEC*/, 0., 0., 90., 0 /* + (isector + 0.5) * PHISEC*/}; - for (Int_t ii = 0; ii < 6; ii++) + for (Int_t ii = 0; ii < 6; ii++) { rotationAngles[ii] *= TMath::DegToRad(); + } for (Int_t isector = 0; isector < NSECTORS; isector++) { rotationAngles[5] = ((isector + 0.5) * PHISEC) * TMath::DegToRad(); @@ -162,23 +164,30 @@ void Geo::getVolumePath(const Int_t* ind, Char_t* path) Int_t iplate = ind[1]; Int_t istrip = ind[2]; - if (iplate == 0) + if (iplate == 0) { icopy = istrip; - if (iplate == 1) + } + if (iplate == 1) { icopy = istrip + NSTRIPC; - if (iplate == 2) + } + if (iplate == 2) { icopy = istrip + NSTRIPC + NSTRIPB; - if (iplate == 3) + } + if (iplate == 3) { icopy = istrip + NSTRIPC + NSTRIPB + NSTRIPA; - if (iplate == 4) + } + if (iplate == 4) { icopy = istrip + NSTRIPC + 2 * NSTRIPB + NSTRIPA; + } icopy++; snprintf(string2, kSize, "FTOA_0/FLTA_0/FSTR_%i", icopy); if (fgHoles && (sector == 13 || sector == 14 || sector == 15)) { - if (iplate < 2) + if (iplate < 2) { snprintf(string2, kSize, "FTOB_0/FLTB_0/FSTR_%i", icopy); - if (iplate > 2) + } + if (iplate > 2) { snprintf(string2, kSize, "FTOC_0/FLTC_0/FSTR_%i", icopy); + } } Int_t padz = ind[3] + 1; @@ -193,8 +202,9 @@ void Geo::getPos(Int_t* det, Float_t* pos) // Returns space point coor (x,y,z) (cm) for Detector // Indices (iSect,iPlate,iStrip,iPadZ,iPadX) // - if (mToBeIntit) + if (mToBeIntit) { Init(); + } // printf("TOFDBG: %d, %d, %d, %d, %d -> %f %f %f\n", det[0], det[1], det[2], det[3], det[4], mPadPosition[det[0]][det[1]][det[2]][det[3]][det[4]][0], mPadPosition[det[0]][det[1]][det[2]][det[3]][det[4]][1], mPadPosition[det[0]][det[1]][det[2]][det[3]][det[4]][2]); pos[0] = mPadPosition[det[0]][det[1]][det[2]][det[3]][det[4]][0]; @@ -208,12 +218,14 @@ void Geo::getDetID(Float_t* pos, Int_t* det) // Returns Detector Indices (iSect,iPlate,iStrip,iPadZ,iPadX) // space point coor (x,y,z) (cm) - if (mToBeIntit) + if (mToBeIntit) { Init(); + } Float_t posLocal[3]; - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { posLocal[ii] = pos[ii]; + } det[0] = getSector(posLocal); @@ -402,8 +414,9 @@ Int_t Geo::fromPlateToStrip(Float_t* pos, Int_t iplate) step[2] = -0.5 * NPADZ * ZPAD; translate(posLoc2, step); - for (Int_t jj = 0; jj < 3; jj++) + for (Int_t jj = 0; jj < 3; jj++) { pos[jj] = posLoc2[jj]; + } return istrip; } @@ -442,11 +455,13 @@ void Geo::getPadDxDyDz(const Float_t* pos, Int_t* det, Float_t* DeltaPos) // // Returns the x coordinate in the Pad reference frame // - if (mToBeIntit) + if (mToBeIntit) { Init(); + } - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { DeltaPos[ii] = pos[ii]; + } det[0] = getSector(DeltaPos); fromGlobalToSector(DeltaPos, det[0]); @@ -488,41 +503,45 @@ Int_t Geo::getPlate(const Float_t* pos) deltaRHOmax = (RMAX - RMIN) * 0.5 - MODULEWALLTHICKNESS - 2. * LENGTHEXINMODBORDER; // old 5.35, new 4.8 if (deltaRhoLoc > deltaZetaLoc * deltaRHOmax / (INTERCENTRMODBORDER2 - INTERCENTRMODBORDER1)) { - if (zLocal < 0) + if (zLocal < 0) { iPlate = 0; - else + } else { iPlate = 4; + } } else { - if (zLocal < 0) + if (zLocal < 0) { iPlate = 1; - else + } else { iPlate = 3; + } } } else if (TMath::Abs(zLocal) >= INTERCENTRMODBORDER1 && TMath::Abs(zLocal) <= INTERCENTRMODBORDER2) { deltaRhoLoc -= LENGTHINCEMODBORDERD; deltaZetaLoc = deltaZetaLoc - INTERCENTRMODBORDER1; deltaRHOmax = (RMAX - RMIN) * 0.5 - MODULEWALLTHICKNESS - 2. * LENGTHINCEMODBORDERD; // old 0.39, new 0.2 - if (deltaRhoLoc > deltaZetaLoc * deltaRHOmax / (INTERCENTRMODBORDER2 - INTERCENTRMODBORDER1)) + if (deltaRhoLoc > deltaZetaLoc * deltaRHOmax / (INTERCENTRMODBORDER2 - INTERCENTRMODBORDER1)) { iPlate = 2; - else { - if (zLocal < 0) + } else { + if (zLocal < 0) { iPlate = 1; - else + } else { iPlate = 3; + } } } - if (zLocal > -ZLENA * 0.5 && zLocal < -EXTERINTERMODBORDER2) + if (zLocal > -ZLENA * 0.5 && zLocal < -EXTERINTERMODBORDER2) { iPlate = 0; - else if (zLocal > -EXTERINTERMODBORDER1 && zLocal < -INTERCENTRMODBORDER2) + } else if (zLocal > -EXTERINTERMODBORDER1 && zLocal < -INTERCENTRMODBORDER2) { iPlate = 1; - else if (zLocal > -INTERCENTRMODBORDER1 && zLocal < INTERCENTRMODBORDER1) + } else if (zLocal > -INTERCENTRMODBORDER1 && zLocal < INTERCENTRMODBORDER1) { iPlate = 2; - else if (zLocal > INTERCENTRMODBORDER2 && zLocal < EXTERINTERMODBORDER1) + } else if (zLocal > INTERCENTRMODBORDER2 && zLocal < EXTERINTERMODBORDER1) { iPlate = 3; - else if (zLocal > EXTERINTERMODBORDER2 && zLocal < ZLENA * 0.5) + } else if (zLocal > EXTERINTERMODBORDER2 && zLocal < ZLENA * 0.5) { iPlate = 4; + } return iPlate; } @@ -534,10 +553,11 @@ Int_t Geo::getPadZ(const Float_t* pos) // Int_t iPadZ = (Int_t)(pos[2] / ZPAD); - if (iPadZ == NPADZ) + if (iPadZ == NPADZ) { iPadZ--; - else if (iPadZ > NPADZ) + } else if (iPadZ > NPADZ) { iPadZ = -1; + } return iPadZ; } @@ -549,10 +569,11 @@ Int_t Geo::getPadX(const Float_t* pos) // Int_t iPadX = (Int_t)(pos[0] / XPAD); - if (iPadX == NPADX) + if (iPadX == NPADX) { iPadX--; - else if (iPadX > NPADX) + } else if (iPadX > NPADX) { iPadX = -1; + } return iPadX; } @@ -563,15 +584,17 @@ void Geo::translate(Float_t* xyz, Float_t translationVector[3]) // Return the vector xyz translated by translationVector vector // - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { xyz[ii] -= translationVector[ii]; + } return; } void Geo::antiRotateToSector(Float_t* xyz, Int_t isector) { - if (mToBeIntit) + if (mToBeIntit) { Init(); + } Float_t xyzDummy[3] = {0., 0., 0.}; @@ -591,16 +614,18 @@ void Geo::antiRotateToSector(Float_t* xyz, Int_t isector) xyz[2] * matAR[ii][2]; } - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { xyz[ii] = xyzDummy[ii]; + } return; } void Geo::rotateToSector(Float_t* xyz, Int_t isector) { - if (mToBeIntit) + if (mToBeIntit) { Init(); + } Float_t xyzDummy[3] = {0., 0., 0.}; @@ -609,8 +634,9 @@ void Geo::rotateToSector(Float_t* xyz, Int_t isector) xyz[2] * mRotationMatrixSector[isector][ii][2]; } - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { xyz[ii] = xyzDummy[ii]; + } return; } @@ -625,8 +651,9 @@ void Geo::rotateToStrip(Float_t* xyz, Int_t iplate, Int_t istrip) xyz[2] * mRotationMatrixPlateStrip[iplate][istrip][ii][2]; } - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { xyz[ii] = xyzDummy[ii]; + } return; } @@ -643,8 +670,9 @@ void Geo::rotate(Float_t* xyz, Double_t rotationAngles[6]) angles[4], angles[5]); */ - for (Int_t ii = 0; ii < 6; ii++) + for (Int_t ii = 0; ii < 6; ii++) { rotationAngles[ii] *= TMath::DegToRad(); + } Float_t xyzDummy[3] = {0., 0., 0.}; @@ -654,8 +682,9 @@ void Geo::rotate(Float_t* xyz, Double_t rotationAngles[6]) xyz[2] * TMath::Cos(rotationAngles[2 * ii]); } - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { xyz[ii] = xyzDummy[ii]; + } return; } @@ -666,8 +695,9 @@ void Geo::antiRotate(Float_t* xyz, Double_t rotationAngles[6]) // Rotates the vector xyz acordint to the rotationAngles // - for (Int_t ii = 0; ii < 6; ii++) + for (Int_t ii = 0; ii < 6; ii++) { rotationAngles[ii] *= TMath::DegToRad(); + } Float_t xyzDummy[3] = {0., 0., 0.}; @@ -682,8 +712,9 @@ void Geo::antiRotate(Float_t* xyz, Double_t rotationAngles[6]) xyzDummy[2] = xyz[0] * TMath::Cos(rotationAngles[0]) + xyz[1] * TMath::Cos(rotationAngles[2]) + xyz[2] * TMath::Cos(rotationAngles[4]); - for (Int_t ii = 0; ii < 3; ii++) + for (Int_t ii = 0; ii < 3; ii++) { xyz[ii] = xyzDummy[ii]; + } return; } diff --git a/Detectors/TOF/base/src/Strip.cxx b/Detectors/TOF/base/src/Strip.cxx index 35efb304ecd89..82eedd5c561ed 100644 --- a/Detectors/TOF/base/src/Strip.cxx +++ b/Detectors/TOF/base/src/Strip.cxx @@ -59,8 +59,9 @@ void Strip::fillOutputContainer(std::vector<Digit>& digits) // we assume that the Strip has stored inside only digits from one readout // window --> we flush them all - if (mDigits.empty()) + if (mDigits.empty()) { return; + } auto itBeg = mDigits.begin(); auto iter = itBeg; for (; iter != mDigits.end(); ++iter) { diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index ad2d1115592ab..0457cb274608f 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -130,8 +130,9 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) // check if patterns are in the current row for (std::vector<PatternData>::reverse_iterator it = mCratePatterns.rbegin(); it != mCratePatterns.rend(); ++it) { - if (it->row > mReadoutWindowCurrent) + if (it->row > mReadoutWindowCurrent) { break; + } if (it->row < mReadoutWindowCurrent) { // this should not happen LOG(ERROR) << "One pattern skipped because appears to occur early of the current row " << it->row << " < " << mReadoutWindowCurrent << " ?!"; @@ -155,13 +156,15 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) // switch to next mStrip after flushing current readout window data mIcurrentReadoutWindow++; - if (mIcurrentReadoutWindow >= MAXWINDOWS) + if (mIcurrentReadoutWindow >= MAXWINDOWS) { mIcurrentReadoutWindow = 0; + } mStripsCurrent = &(mStrips[mIcurrentReadoutWindow]); int k = mIcurrentReadoutWindow + 1; for (Int_t i = 0; i < MAXWINDOWS - 1; i++) { - if (k >= MAXWINDOWS) + if (k >= MAXWINDOWS) { k = 0; + } mStripsNext[i] = &(mStrips[k]); k++; } @@ -175,19 +178,22 @@ void WindowFiller::flushOutputContainer(std::vector<Digit>& digits) // sort patterns (diagnostic words) in time std::sort(mCratePatterns.begin(), mCratePatterns.end(), - [](PatternData a, PatternData b) { if(a.row == b.row) return a.icrate > b.icrate; else return a.row > b.row; }); + [](PatternData a, PatternData b) { if(a.row == b.row) { return a.icrate > b.icrate; } else { return a.row > b.row; + +} }); for (Int_t i = 0; i < MAXWINDOWS; i++) { int n = 0; - for (int j = 0; j < mStrips[i].size(); j++) + for (int j = 0; j < mStrips[i].size(); j++) { n += ((mStrips[i])[j]).getNumberOfDigits(); + } } checkIfReuseFutureDigitsRO(); - if (!mContinuous) + if (!mContinuous) { fillOutputContainer(digits); - else { + } else { for (Int_t i = 0; i < MAXWINDOWS; i++) { fillOutputContainer(digits); // fill all windows which are before (not yet stored) of the new current one checkIfReuseFutureDigitsRO(); @@ -215,8 +221,9 @@ void WindowFiller::flushOutputContainer(std::vector<Digit>& digits) //______________________________________________________________________ void WindowFiller::checkIfReuseFutureDigits() { - if (!mFutureDigits.size()) + if (!mFutureDigits.size()) { return; + } // check if digits stored very far in future match the new readout windows currently available if (mFutureToBeSorted) { @@ -232,8 +239,9 @@ void WindowFiller::checkIfReuseFutureDigits() for (std::vector<Digit>::reverse_iterator digit = mFutureDigits.rbegin(); digit != mFutureDigits.rend(); ++digit) { - if (digit->getBC() > bclimit) + if (digit->getBC() > bclimit) { break; + } double timestamp = digit->getBC() * Geo::BC_TIME + digit->getTDC() * Geo::TDCBIN * 1E-3; // in ns int isnext = Int_t(timestamp * Geo::READOUTWINDOW_INV) - (mReadoutWindowCurrent + 1); // to be replaced with uncalibrated time @@ -271,18 +279,21 @@ void WindowFiller::checkIfReuseFutureDigits() //______________________________________________________________________ void WindowFiller::checkIfReuseFutureDigitsRO() // the same but using readout info information from raw { - if (!mFutureDigits.size()) + if (!mFutureDigits.size()) { return; + } // check if digits stored very far in future match the new readout windows currently available if (mFutureToBeSorted) { // sort digit in descending BC order: kept last as first std::sort(mFutureDigits.begin(), mFutureDigits.end(), [](o2::tof::Digit a, o2::tof::Digit b) { - if (a.getTriggerOrbit() != b.getTriggerOrbit()) + if (a.getTriggerOrbit() != b.getTriggerOrbit()) { return a.getTriggerOrbit() > b.getTriggerOrbit(); - if (a.getTriggerBunch() != b.getTriggerBunch()) + } + if (a.getTriggerBunch() != b.getTriggerBunch()) { return a.getTriggerBunch() > b.getTriggerBunch(); + } return a.getBC() > b.getBC(); }); mFutureToBeSorted = false; @@ -298,8 +309,9 @@ void WindowFiller::checkIfReuseFutureDigitsRO() // the same but using readout in row *= Geo::BC_IN_WINDOW_INV; - if (row > rolimit) + if (row > rolimit) { break; + } int isnext = row - mReadoutWindowCurrent; @@ -322,8 +334,9 @@ void WindowFiller::checkIfReuseFutureDigitsRO() // the same but using readout in strips = mStripsNext[isnext - 1]; } - if (mMaskNoiseRate < 0 || mChannelCounts[digit->getChannel()] < mMaskNoiseRate) + if (mMaskNoiseRate < 0 || mChannelCounts[digit->getChannel()] < mMaskNoiseRate) { fillDigitsInStrip(strips, digit->getChannel(), digit->getTDC(), digit->getTOT(), digit->getBC(), digit->getChannel() / Geo::NPADS); + } // int labelremoved = digit->getLabel(); mFutureDigits.erase(mFutureDigits.begin() + idigit); diff --git a/Detectors/TOF/base/test/testTOFIndex.cxx b/Detectors/TOF/base/test/testTOFIndex.cxx index bd3bd7566673b..beec1680ef462 100644 --- a/Detectors/TOF/base/test/testTOFIndex.cxx +++ b/Detectors/TOF/base/test/testTOFIndex.cxx @@ -42,8 +42,9 @@ BOOST_AUTO_TEST_CASE(testTOFIndex) : j > 2 ? Geo::NSTRIPC : Geo::NSTRIPA; // Define the numer of strips of the plate if (j == 2 && - (i == 15 || i == 14 || i == 13)) // Skip sectors without A plate + (i == 15 || i == 14 || i == 13)) { // Skip sectors without A plate continue; + } // for (Int_t k = 0; k < nStrips; k++) { // Loop on all Strips indextof[2] = k; diff --git a/Detectors/TOF/calibration/src/CalibTOF.cxx b/Detectors/TOF/calibration/src/CalibTOF.cxx index ffe8fde0c929e..2a1c5890ab108 100644 --- a/Detectors/TOF/calibration/src/CalibTOF.cxx +++ b/Detectors/TOF/calibration/src/CalibTOF.cxx @@ -44,8 +44,9 @@ CalibTOF::~CalibTOF() // destructor - if (mHistoLHCphase) + if (mHistoLHCphase) { delete mHistoLHCphase; + } delete mHistoChTimeSlewingAll; } //______________________________________________ @@ -108,8 +109,9 @@ void CalibTOF::init() // booking the histogram of the LHCphase int nbinsLHCphase = TMath::Min(1000, int((mMaxTimestamp - mMinTimestamp) / 300) + 1); - if (nbinsLHCphase < 1000) + if (nbinsLHCphase < 1000) { mMaxTimestamp = mMinTimestamp + nbinsLHCphase * 300; // we want that the last bin of the histogram is also large 300s; this we need to do only when we have less than 1000 bins, because in this case we will integrate over intervals that are larger than 300s anyway + } mHistoLHCphase = new TH2F("hLHCphase", ";clock offset (ps); timestamp (s)", 1000, -24400, 24400, nbinsLHCphase, mMinTimestamp, mMaxTimestamp); // setting CCDB for output @@ -155,10 +157,11 @@ void CalibTOF::run(int flag, int sector) std::vector<o2::dataformats::CalibInfoTOFshort>* calibTimePad[NPADSPERSTEP]; for (int ipad = 0; ipad < NPADSPERSTEP; ipad++) { histoChOffsetTemp[ipad] = new TH1F(Form("OffsetTemp_Sec%02d_Pad%04d", sector, ipad), Form("Sector %02d (pad = %04d);channel offset (ps)", sector, ipad), 1000, -24400, 24400); - if (flag & kChannelTimeSlewing) + if (flag & kChannelTimeSlewing) { calibTimePad[ipad] = new std::vector<o2::dataformats::CalibInfoTOFshort>; // temporary array containing [time, tot] for every pad that we process; this will be the input for the 2D histo for timeSlewing calibration (to be filled after we get the channel offset) - else + } else { calibTimePad[ipad] = nullptr; + } } TF1* funcChOffset = new TF1(Form("fTOFchOffset_%02d", sector), "[0]*TMath::Gaus((x-[1])*(x-[1] < 12500 && x-[1] > -12500) + (x-[1]+25000)*(x-[1] < -12500) + (x-[1]-25000)*(x-[1] > 12500),0,[2])*(x > -12500 && x < 12500)", -12500, 12500); @@ -196,8 +199,9 @@ void CalibTOF::run(int flag, int sector) } } TFile* fout = nullptr; - if (flag & kChannelTimeSlewing && mDebugMode) + if (flag & kChannelTimeSlewing && mDebugMode) { fout = new TFile(Form("timeslewingTOF%06i.root", ich / 96), "RECREATE"); + } for (ipad = 0; ipad < NPADSPERSTEP; ipad++) { if (histoChOffsetTemp[ipad]->GetEntries() > 30) { @@ -220,8 +224,9 @@ void CalibTOF::run(int flag, int sector) TGraphErrors* gTimeVsTot = processSlewing(histoChTimeSlewingTemp, 1, funcChOffset); if (gTimeVsTot && gTimeVsTot->GetN()) { - for (int itot = 0; itot < gTimeVsTot->GetN(); itot++) + for (int itot = 0; itot < gTimeVsTot->GetN(); itot++) { mTimeSlewingObj->addTimeSlewingInfo(ich + ipad, gTimeVsTot->GetX()[itot], gTimeVsTot->GetY()[itot] + mCalibChannelOffset[ich + ipad]); + } } else { // just add the channel offset mTimeSlewingObj->addTimeSlewingInfo(ich + ipad, 0, mCalibChannelOffset[ich + ipad]); } @@ -246,8 +251,9 @@ void CalibTOF::run(int flag, int sector) for (int ipad = 0; ipad < NPADSPERSTEP; ipad++) { delete histoChOffsetTemp[ipad]; - if (calibTimePad[ipad]) + if (calibTimePad[ipad]) { delete calibTimePad[ipad]; + } } delete histoChTimeSlewingTemp; delete funcChOffset; @@ -350,8 +356,9 @@ void CalibTOF::doLHCPhaseCalib() } int res = FitPeak(mFuncLHCphase, htemp, 500., 3., 2., "LHCphase"); - if (res) + if (res) { continue; + } mLHCphaseObj->addLHCphase(mHistoLHCphase->GetYaxis()->GetBinLowEdge(ifit0), mFuncLHCphase->GetParameter(1)); ifit0 = ifit + 1; // starting point for the next LHC interval @@ -372,8 +379,9 @@ void CalibTOF::fillChannelCalibInput(std::vector<o2::dataformats::CalibInfoTOFsh dtime -= (int(dtime * bc_inv + 5.5) - 5) * bc; // do truncation far (by 5 units) from zero to avoid truncation of negative numbers histo->Fill(dtime); - if (calibTimePad) + if (calibTimePad) { calibTimePad->push_back(*infotof); + } } } //______________________________________________ @@ -402,14 +410,16 @@ float CalibTOF::doChannelCalibration(int ipad, TH1F* histo, TF1* funcChOffset) // calibrate single channel from histos - offsets float integral = histo->Integral(); - if (!integral) + if (!integral) { return -1; // we skip directly the channels that were switched off online, the PHOS holes... + } int resfit = FitPeak(funcChOffset, histo, 500., 3., 2., "ChannelOffset"); // return a number greater than zero to distinguish bad fit from empty channels(fraction=0) - if (resfit) + if (resfit) { return 0.0001; // fit was not good + } float mean = funcChOffset->GetParameter(1); float sigma = funcChOffset->GetParameter(2); @@ -444,10 +454,12 @@ float CalibTOF::doChannelCalibration(int ipad, TH1F* histo, TF1* funcChOffset) int binmin = histo->FindBin(intmin); int binmax = histo->FindBin(intmax); - if (binmin < 1) + if (binmin < 1) { binmin = 1; // avoid to take the underflow bin (can happen in case the sigma is too large) - if (binmax > histo->GetNbinsX()) + } + if (binmax > histo->GetNbinsX()) { binmax = histo->GetNbinsX(); // avoid to take the overflow bin (can happen in case the sigma is too large) + } return (histo->Integral(binmin, binmax) + addduetoperiodicity) / integral; } @@ -460,8 +472,9 @@ void CalibTOF::resetChannelLevelHistos(TH1F* histoOffset[NPADSPERSTEP], TH2F* hi for (int ipad = 0; ipad < NPADSPERSTEP; ipad++) { histoOffset[ipad]->Reset(); - if (calibTimePad[ipad]) + if (calibTimePad[ipad]) { calibTimePad[ipad]->clear(); + } } histoTimeSlewing->Reset(); } @@ -491,17 +504,20 @@ TGraphErrors* CalibTOF::processSlewing(TH2F* histo, Bool_t forceZero, TF1* fitFu Int_t startBin = ibin; Int_t endBin = ibin; while (hpx->Integral(startBin, endBin) < 300) { - if (startBin == 1 && forceZero) + if (startBin == 1 && forceZero) { break; - if (endBin < maxBin) + } + if (endBin < maxBin) { endBin++; - else if (startBin > minBin) + } else if (startBin > minBin) { startBin--; - else + } else { break; + } } - if (hpx->Integral(startBin, endBin) <= 0) + if (hpx->Integral(startBin, endBin) <= 0) { continue; + } // printf("TOT window defined: %f < TOT < %f ns [%d, %d], %d tracks\n", hpx->GetBinLowEdge(startBin), hpx->GetBinLowEdge(endBin + 1), startBin, endBin, (Int_t)hpx->Integral(startBin, endBin)); /* projection-y */ @@ -568,29 +584,35 @@ Int_t CalibTOF::FitPeak(TF1* fitFunc, TH1* h, Float_t startSigma, Float_t nSigma } Double_t fitMin = fitCent - nSigmaMin * startSigma; Double_t fitMax = fitCent + nSigmaMax * startSigma; - if (fitMin < -12500) + if (fitMin < -12500) { fitMin = -12500; - if (fitMax > 12500) + } + if (fitMax > 12500) { fitMax = 12500; + } fitFunc->SetParLimits(1, fitMin, fitMax); fitFunc->SetParameter(0, 100); fitFunc->SetParameter(1, fitCent); fitFunc->SetParameter(2, startSigma); Int_t fitres = h->Fit(fitFunc, "WWq0", "", fitMin, fitMax); //printf("%s) init: %f %f\n ",h->GetName(),fitMin,fitMax); - if (fitres != 0) + if (fitres != 0) { return fitres; + } /* refit with better range */ for (Int_t i = 0; i < 3; i++) { fitCent = fitFunc->GetParameter(1); fitMin = fitCent - nSigmaMin * abs(fitFunc->GetParameter(2)); fitMax = fitCent + nSigmaMax * abs(fitFunc->GetParameter(2)); - if (fitMin < -12500) + if (fitMin < -12500) { fitMin = -12500; - if (fitMax > 12500) + } + if (fitMax > 12500) { fitMax = 12500; - if (fitMin >= fitMax) + } + if (fitMin >= fitMax) { printf("%s) step%i: %f %f\n ", h->GetName(), i, fitMin, fitMax); + } fitFunc->SetParLimits(1, fitMin, fitMax); fitres = h->Fit(fitFunc, "q0", "", fitMin, fitMax); if (fitres != 0) { @@ -598,13 +620,15 @@ Int_t CalibTOF::FitPeak(TF1* fitFunc, TH1* h, Float_t startSigma, Float_t nSigma if (mDebugMode > 1) { char* filename = Form("TOFDBG_%s.root", h->GetName()); - if (hdbg) + if (hdbg) { filename = Form("TOFDBG_%s_%s.root", hdbg->GetName(), debuginfo); + } // printf("write %s\n", filename); TFile ff(filename, "RECREATE"); h->Write(); - if (hdbg) + if (hdbg) { hdbg->Write(); + } ff.Close(); } @@ -614,13 +638,15 @@ Int_t CalibTOF::FitPeak(TF1* fitFunc, TH1* h, Float_t startSigma, Float_t nSigma if (mDebugMode > 1 && fitFunc->GetParError(1) > 100) { char* filename = Form("TOFDBG_%s.root", h->GetName()); - if (hdbg) + if (hdbg) { filename = Form("TOFDBG_%s_%s.root", hdbg->GetName(), debuginfo); + } // printf("write %s\n", filename); TFile ff(filename, "RECREATE"); h->Write(); - if (hdbg) + if (hdbg) { hdbg->Write(); + } ff.Close(); } @@ -694,8 +720,9 @@ void CalibTOF::flagProblematics() for (int i = 0; i < 18; i++) { // exclude channel without entries - if (mTimeSlewingObj->getFractionUnderPeak(i, ipad) < 0) + if (mTimeSlewingObj->getFractionUnderPeak(i, ipad) < 0) { continue; + } nActiveChannels++; @@ -716,16 +743,18 @@ void CalibTOF::flagProblematics() for (int i = 0; i < 18; i++) { // exclude channel without entries - if (mTimeSlewingObj->getFractionUnderPeak(i, ipad) < 0) + if (mTimeSlewingObj->getFractionUnderPeak(i, ipad) < 0) { continue; + } if (mTimeSlewingObj->getSigmaPeak(i, ipad) < sigmaMin || mTimeSlewingObj->getSigmaPeak(i, ipad) > sigmaMax || mTimeSlewingObj->getFractionUnderPeak(i, ipad) < fractionMin) { mTimeSlewingObj->setFractionUnderPeak(i, ipad, -mTimeSlewingObj->getFractionUnderPeak(i, ipad)); mTimeSlewingObj->setSigmaPeak(i, ipad, -mTimeSlewingObj->getSigmaPeak(i, ipad)); - } else + } else { nGoodChannels++; + } } } } diff --git a/Detectors/TOF/calibration/src/CalibTOFapi.cxx b/Detectors/TOF/calibration/src/CalibTOFapi.cxx index b8f1a54156ed7..2e994bc802675 100644 --- a/Detectors/TOF/calibration/src/CalibTOFapi.cxx +++ b/Detectors/TOF/calibration/src/CalibTOFapi.cxx @@ -71,8 +71,9 @@ void CalibTOFapi::writeTimeSlewingParam(SlewParam* param, std::map<std::string, api.init(mgr.getURL()); if (maxTimeStamp == 0) { api.storeAsTFileAny(param, "TOF/ChannelCalib", metadataChannelCalib, minTimeStamp); - } else + } else { api.storeAsTFileAny(param, "TOF/ChannelCalib", metadataChannelCalib, minTimeStamp, maxTimeStamp); + } } //______________________________________________________________________ diff --git a/Detectors/TOF/calibration/src/CollectCalibInfoTOF.cxx b/Detectors/TOF/calibration/src/CollectCalibInfoTOF.cxx index 1129db6910856..3c96a22781f82 100644 --- a/Detectors/TOF/calibration/src/CollectCalibInfoTOF.cxx +++ b/Detectors/TOF/calibration/src/CollectCalibInfoTOF.cxx @@ -144,10 +144,11 @@ void CollectCalibInfoTOF::addHit(o2::dataformats::CalibInfoTOF& calibInfo) if (mTOFCollectedCalibInfo[calibInfo.getTOFChIndex()].size() == MAXNUMBEROFHITS) { // the current channel has arrived to the limit of hits that we can store between two fills --> filling the tree fillTree(); } - if (calibInfo.getTimestamp() < mMinTimestamp.GetVal() || mMinTimestamp.GetVal() == -1) + if (calibInfo.getTimestamp() < mMinTimestamp.GetVal() || mMinTimestamp.GetVal() == -1) { mMinTimestamp.SetVal(calibInfo.getTimestamp()); - else if (calibInfo.getTimestamp() > mMaxTimestamp.GetVal()) + } else if (calibInfo.getTimestamp() > mMaxTimestamp.GetVal()) { mMaxTimestamp.SetVal(calibInfo.getTimestamp()); + } } //______________________________________________ void CollectCalibInfoTOF::fillTree() diff --git a/Detectors/TOF/calibration/src/TOFCalibCollector.cxx b/Detectors/TOF/calibration/src/TOFCalibCollector.cxx index 2e69bf9d6a42d..eef82b962e436 100644 --- a/Detectors/TOF/calibration/src/TOFCalibCollector.cxx +++ b/Detectors/TOF/calibration/src/TOFCalibCollector.cxx @@ -129,13 +129,15 @@ bool TOFCalibCollector::hasEnoughData(const Slot& slot) const // (see header file for the fact that mMaxNumOfHits = 500) // The case in which mScaleMaxNumOfHits = false allows for a fast check - if (mTest) + if (mTest) { return true; + } const o2::tof::TOFCalibInfoSlot* c = slot.getContainer(); LOG(INFO) << "we have " << c->getCollectedCalibInfoSlot().size() << " entries"; int maxNumberOfHits = mAbsMaxNumOfHits ? mMaxNumOfHits : mMaxNumOfHits * o2::tof::Geo::NCHANNELS; - if (mTFsendingPolicy || c->getCollectedCalibInfoSlot().size() > maxNumberOfHits) + if (mTFsendingPolicy || c->getCollectedCalibInfoSlot().size() > maxNumberOfHits) { return true; + } return false; } diff --git a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx index 78727f4016fec..a2d89aa0ec793 100644 --- a/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx +++ b/Detectors/TOF/calibration/src/TOFChannelCalibrator.cxx @@ -135,8 +135,9 @@ void TOFChannelData::print(int isect) const void TOFChannelData::printEntries() const { // to print number of entries per channel - for (int i = 0; i < mEntries.size(); ++i) + for (int i = 0; i < mEntries.size(); ++i) { LOG(INFO) << "channel " << i << " has " << mEntries[i] << " entries"; + } } //_____________________________________________ @@ -145,8 +146,9 @@ int TOFChannelData::findBin(float v) const // find the bin along the x-axis (with t-texp) where the value "v" is; this does not depend on the channel // (axis 1), nor on the sector, so we use sector0 - if (v == mRange) + if (v == mRange) { v -= 1.e-1; + } LOG(DEBUG) << "In FindBin, v = : " << v; LOG(DEBUG) << "bin0 limits: lower = " << mHisto[0].axis(0).bin(0).lower() << ", upper = " << mHisto[0].axis(0).bin(0).upper(); @@ -169,8 +171,9 @@ float TOFChannelData::integral(int chmin, int chmax, float binmin, float binmax) } int sector = chmin / o2::tof::Geo::NPADSXSECTOR; - if (sector != chmax / o2::tof::Geo::NPADSXSECTOR) + if (sector != chmax / o2::tof::Geo::NPADSXSECTOR) { throw std::runtime_error("We cannot integrate over channels that belong to different sectors"); + } int chinsectormin = chmin % o2::tof::Geo::NPADSXSECTOR; int chinsectormax = chmax % o2::tof::Geo::NPADSXSECTOR; @@ -285,15 +288,17 @@ float TOFChannelData::integral(int chmin, int chmax, int binxmin, int binxmax) c { // calculates the integral in [chmin, chmax] and in [binmin, binmax] - if (binxmin < 0 || binxmax > mNBins || chmin < 0 || chmax >= o2::tof::Geo::NCHANNELS) + if (binxmin < 0 || binxmax > mNBins || chmin < 0 || chmax >= o2::tof::Geo::NCHANNELS) { throw std::runtime_error("Check your bins, we cannot calculate the integrals in under/overflows bins"); + } if (binxmax < binxmin || chmax < chmin) { throw std::runtime_error("Check your bin limits!"); } int sector = chmin / o2::tof::Geo::NPADSXSECTOR; - if (sector != chmax / o2::tof::Geo::NPADSXSECTOR) + if (sector != chmax / o2::tof::Geo::NPADSXSECTOR) { throw std::runtime_error("We cannot integrate over channels that belong to different sectors"); + } int chinsectormin = chmin % o2::tof::Geo::NPADSXSECTOR; int chinsectormax = chmax % o2::tof::Geo::NPADSXSECTOR; @@ -459,8 +464,9 @@ void TOFChannelCalibrator::finalizeSlot(Slot& slot) if (mTest) { LOG(DEBUG) << "Skipping channel " << ich << " because it has zero entries, but it should not be"; // should become error! continue; - } else + } else { throw std::runtime_error("We found one channel with no entries, we cannot calibrate!"); + } } // more efficient way @@ -475,8 +481,9 @@ void TOFChannelCalibrator::finalizeSlot(Slot& slot) double fitres = fitGaus(c->getNbins(), histoValues.data(), -(c->getRange()), c->getRange(), fitValues); - if (fitValues[2] < 0) + if (fitValues[2] < 0) { fitValues[2] = -fitValues[2]; + } if (fitres >= 0) { LOG(DEBUG) << "Channel " << ich << " :: Fit result " << fitres << " Mean = " << fitValues[1] << " Sigma = " << fitValues[2]; @@ -487,14 +494,18 @@ void TOFChannelCalibrator::finalizeSlot(Slot& slot) float intmin = fitValues[1] - 5 * fitValues[2]; // mean - 5*sigma float intmax = fitValues[1] + 5 * fitValues[2]; // mean + 5*sigma - if (intmin < -mRange) + if (intmin < -mRange) { intmin = -mRange; - if (intmax < -mRange) + } + if (intmax < -mRange) { intmax = -mRange; - if (intmin > mRange) + } + if (intmin > mRange) { intmin = mRange; - if (intmax > mRange) + } + if (intmax > mRange) { intmax = mRange; + } /* // needed if we calculate the integral using the values diff --git a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h index f1d8542481111..9f9df0953a107 100644 --- a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorSpec.h @@ -62,8 +62,9 @@ class TOFCalibCollectorDevice : public o2::framework::Task constexpr uint64_t INFINITE_TF = 0xffffffffffffffff; mCollector->checkSlotsToFinalize(INFINITE_TF); // we force finalizing slot zero (unless everything was already finalized), no matter how many entries we had - if (mCollector->getNSlots() != 0) + if (mCollector->getNSlots() != 0) { mCollector->finalizeSlot(mCollector->getSlot(0)); + } sendOutput(ec.outputs()); } diff --git a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h index 07808b0802ab9..fc126b0fc1670 100644 --- a/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h +++ b/Detectors/TOF/calibration/testWorkflow/TOFCalibCollectorWriterSpec.h @@ -95,8 +95,9 @@ class TOFCalibCollectorWriter : public o2::framework::Task mOutputTree.reset(); mfileOut.reset(); mCount++; - if (!mIsEndOfStream) + if (!mIsEndOfStream) { createAndOpenFileAndTree(); + } } }; } // namespace calibration diff --git a/Detectors/TOF/calibration/testWorkflow/tof-calib-workflow.cxx b/Detectors/TOF/calibration/testWorkflow/tof-calib-workflow.cxx index f5e9a67fefc35..4d14607ff69cd 100644 --- a/Detectors/TOF/calibration/testWorkflow/tof-calib-workflow.cxx +++ b/Detectors/TOF/calibration/testWorkflow/tof-calib-workflow.cxx @@ -45,9 +45,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) LOG(INFO) << "doChannelOffsetCalib = " << doChannelOffsetCalib; LOG(INFO) << "useCCDB = " << useCCDB; LOG(INFO) << "attachChannelOffsetToLHCphase = " << attachChannelOffsetToLHCphase; - if (doLHCcalib) + if (doLHCcalib) { specs.emplace_back(getLHCClockCalibDeviceSpec()); - if (doChannelOffsetCalib) + } + if (doChannelOffsetCalib) { specs.emplace_back(getTOFChannelCalibDeviceSpec(useCCDB, attachChannelOffsetToLHCphase)); + } return specs; } diff --git a/Detectors/TOF/compression/include/TOFCompression/Compressor.h b/Detectors/TOF/compression/include/TOFCompression/Compressor.h index e88e6341dfd03..7d958bb863d05 100644 --- a/Detectors/TOF/compression/include/TOFCompression/Compressor.h +++ b/Detectors/TOF/compression/include/TOFCompression/Compressor.h @@ -44,15 +44,18 @@ class Compressor while (mDecoderPointer < mDecoderPointerMax) { mEventCounter++; processDRM(); - if (mDecoderFatal) + if (mDecoderFatal) { mFatalCounter++; - if (mDecoderError) + } + if (mDecoderError) { mErrorCounter++; + } } return false; } - while (!processHBF()) + while (!processHBF()) { ; + } return false; }; diff --git a/Detectors/TOF/compression/src/Compressor.cxx b/Detectors/TOF/compression/src/Compressor.cxx index 318aa7867bd78..1b31d746f36ed 100644 --- a/Detectors/TOF/compression/src/Compressor.cxx +++ b/Detectors/TOF/compression/src/Compressor.cxx @@ -135,8 +135,9 @@ bool Compressor<RDH, verbose>::processHBF() rdh = reinterpret_cast<const RDH*>(reinterpret_cast<const char*>(rdh) + offsetToNext); /** check next RDH is within buffer **/ - if (reinterpret_cast<const char*>(rdh) < mDecoderBuffer + mDecoderBufferSize) + if (reinterpret_cast<const char*>(rdh) < mDecoderBuffer + mDecoderBufferSize) { continue; + } /** otherwise return **/ return true; @@ -172,8 +173,9 @@ bool Compressor<RDH, verbose>::processHBF() mEncoderPointer = mEncoderPointerStart; } - if (mDecoderError) + if (mDecoderError) { mErrorCounter++; + } /** updated encoder RDH open **/ mEncoderRDH->memorySize = reinterpret_cast<char*>(mEncoderPointer) - reinterpret_cast<char*>(mEncoderRDH); @@ -198,8 +200,9 @@ bool Compressor<RDH, verbose>::processHBF() mDecoderPointer = reinterpret_cast<const uint32_t*>(reinterpret_cast<const char*>(rdh) + rdh->offsetToNext); /** check next RDH is within buffer **/ - if (reinterpret_cast<const char*>(mDecoderPointer) < mDecoderBuffer + mDecoderBufferSize) + if (reinterpret_cast<const char*>(mDecoderPointer) < mDecoderBuffer + mDecoderBufferSize) { return false; + } /** otherwise return **/ return true; @@ -369,14 +372,16 @@ bool Compressor<RDH, verbose>::processDRM() /** LTM global header detected **/ if (IS_LTM_GLOBAL_HEADER(*mDecoderPointer)) { - if (processLTM()) + if (processLTM()) { return true; + } } /** TRM Data Header detected **/ if (IS_TRM_GLOBAL_HEADER(*mDecoderPointer) && GET_TRMDATAHEADER_SLOTID(*mDecoderPointer) > 2) { - if (processTRM()) + if (processTRM()) { return true; + } continue; } @@ -483,8 +488,9 @@ bool Compressor<RDH, verbose>::processDRM() } /** decode error detected, be paranoid **/ - if (decoderParanoid()) + if (decoderParanoid()) { return true; + } decoderNext(); @@ -571,14 +577,16 @@ bool Compressor<RDH, verbose>::processTRM() /** TRM Chain-A Header detected **/ if (IS_TRM_CHAINA_HEADER(*mDecoderPointer) && GET_TRMCHAINHEADER_SLOTID(*mDecoderPointer) == slotId) { - if (processTRMchain(itrm, 0)) + if (processTRMchain(itrm, 0)) { return true; + } } /** TRM Chain-B Header detected **/ if (IS_TRM_CHAINB_HEADER(*mDecoderPointer) && GET_TRMCHAINHEADER_SLOTID(*mDecoderPointer) == slotId) { - if (processTRMchain(itrm, 1)) + if (processTRMchain(itrm, 1)) { return true; + } } /** TRM Data Trailer detected **/ @@ -609,8 +617,9 @@ bool Compressor<RDH, verbose>::processTRM() } /** encoder Spider **/ - if (mDecoderSummary.hasHits[itrm][0] || mDecoderSummary.hasHits[itrm][1]) + if (mDecoderSummary.hasHits[itrm][0] || mDecoderSummary.hasHits[itrm][1]) { encoderSpider(itrm); + } /** success **/ return false; @@ -623,8 +632,9 @@ bool Compressor<RDH, verbose>::processTRM() printf("%s %08x [ERROR] breaking TRM decode stream %s \n", colorRed, *mDecoderPointer, colorReset); } /** decode error detected, be paranoid **/ - if (decoderParanoid()) + if (decoderParanoid()) { return true; + } decoderNext(); return false; @@ -721,8 +731,9 @@ bool Compressor<RDH, verbose>::processTRMchain(int itrm, int ichain) printf("%s %08x [ERROR] breaking TRM Chain-%c decode stream %s \n", colorRed, *mDecoderPointer, ichain == 0 ? 'A' : 'B', colorReset); } /** decode error detected, be paranoid **/ - if (decoderParanoid()) + if (decoderParanoid()) { return true; + } decoderNext(); break; @@ -760,22 +771,25 @@ void Compressor<RDH, verbose>::encoderSpider(int itrm) /** loop over TRM chains **/ for (int ichain = 0; ichain < 2; ++ichain) { - if (!mDecoderSummary.hasHits[itrm][ichain]) + if (!mDecoderSummary.hasHits[itrm][ichain]) { continue; + } /** loop over TDCs **/ for (int itdc = 0; itdc < 15; ++itdc) { auto nhits = mDecoderSummary.trmDataHits[ichain][itdc]; - if (nhits == 0) + if (nhits == 0) { continue; + } /** loop over hits **/ for (int ihit = 0; ihit < nhits; ++ihit) { auto lhit = *mDecoderSummary.trmDataHit[ichain][itdc][ihit]; - if (!IS_TDC_HIT_LEADING(lhit)) // must be a leading hit + if (!IS_TDC_HIT_LEADING(lhit)) { // must be a leading hit continue; + } auto chan = GET_TRMDATAHIT_CHANID(lhit); auto hitTime = GET_TRMDATAHIT_TIME(lhit); @@ -803,10 +817,12 @@ void Compressor<RDH, verbose>::encoderSpider(int itrm) mSpiderSummary.FramePackedHit[iframe][phit] |= ichain << 31; mSpiderSummary.nFramePackedHits[iframe]++; - if (iframe < firstFilledFrame) + if (iframe < firstFilledFrame) { firstFilledFrame = iframe; - if (iframe > lastFilledFrame) + } + if (iframe > lastFilledFrame) { lastFilledFrame = iframe; + } } mDecoderSummary.trmDataHits[ichain][itdc] = 0; @@ -817,8 +833,9 @@ void Compressor<RDH, verbose>::encoderSpider(int itrm) for (int iframe = firstFilledFrame; iframe < lastFilledFrame + 1; iframe++) { /** check if frame is empty **/ - if (mSpiderSummary.nFramePackedHits[iframe] == 0) + if (mSpiderSummary.nFramePackedHits[iframe] == 0) { continue; + } // encode Frame Header *mEncoderPointer = 0x00000000; @@ -930,8 +947,9 @@ bool Compressor<RDH, verbose>::checkerCheck() uint32_t locEvCnt = GET_DRMDATATRAILER_LOCEVCNT(*mDecoderSummary.drmDataTrailer); /** check RDH **/ - if (!mDecoderCONET) + if (!mDecoderCONET) { checkerCheckRDH(); + } /** check enable/participating mask **/ if (verbose && mCheckerVerbose) { @@ -979,8 +997,9 @@ bool Compressor<RDH, verbose>::checkerCheck() /** check DRM event words (careful with pointers because we have 64 bits extra! only for CRU data! **/ auto drmEventWords = mDecoderSummary.drmDataTrailer - mDecoderSummary.drmDataHeader + 1; - if (!mDecoderCONET) + if (!mDecoderCONET) { drmEventWords -= (drmEventWords / 4) * 2; + } drmEventWords -= 6; if (verbose && mCheckerVerbose) { printf(" --- Checking DRM declared/detected event words: %u/%ld \n", GET_DRMDATAHEADER_EVENTWORDS(*mDecoderSummary.drmDataHeader), drmEventWords); @@ -1058,8 +1077,9 @@ bool Compressor<RDH, verbose>::checkerCheck() if (verbose && mCheckerVerbose) { printf(" Non-participating header found (slotId=%u) \n", slotId); } - } else + } else { continue; + } } /** check TRM bit in DRM fault mask **/ @@ -1138,8 +1158,9 @@ bool Compressor<RDH, verbose>::checkerCheck() /** check TRM event words (careful with pointers because we have 64 bits extra! only for CRU data! **/ auto trmEventWords = mDecoderSummary.trmDataTrailer[itrm] - mDecoderSummary.trmDataHeader[itrm] + 1; - if (!mDecoderCONET) + if (!mDecoderCONET) { trmEventWords -= (trmEventWords / 4) * 2; + } if (verbose && mCheckerVerbose) { printf(" --- Checking TRM (slotId=%u) declared/detected event words: %d/%ld \n", slotId, GET_TRMDATAHEADER_EVENTWORDS(*mDecoderSummary.trmDataHeader[itrm]), trmEventWords); } @@ -1240,8 +1261,9 @@ bool Compressor<RDH, verbose>::checkerCheck() } /** end of loop over TRMs **/ /** check current diagnostic word **/ - if (mCheckerSummary.DiagnosticWord[iword] & 0xFFFFFFF0) + if (mCheckerSummary.DiagnosticWord[iword] & 0xFFFFFFF0) { mCheckerSummary.nDiagnosticWords++; + } if (verbose && mCheckerVerbose) { std::cout << colorBlue @@ -1386,8 +1408,9 @@ void Compressor<RDH, verbose>::checkSummary() #ifndef CHECKER_COUNTER return; #endif - if (mEventCounter == 0) + if (mEventCounter == 0) { return; + } printf("\n"); printf(" DRM "); float drmheaders = 100. * (float)mDRMCounters.Headers / (float)mEventCounter; diff --git a/Detectors/TOF/compression/src/CompressorTask.cxx b/Detectors/TOF/compression/src/CompressorTask.cxx index de3a490ec05dd..7e4d5854daec8 100644 --- a/Detectors/TOF/compression/src/CompressorTask.cxx +++ b/Detectors/TOF/compression/src/CompressorTask.cxx @@ -66,8 +66,9 @@ void CompressorTask<RDH, verbose>::run(ProcessingContext& pc) /** loop over inputs routes **/ for (auto iit = pc.inputs().begin(), iend = pc.inputs().end(); iit != iend; ++iit) { - if (!iit.isValid()) + if (!iit.isValid()) { continue; + } /** prepare output parts **/ FairMQParts parts; diff --git a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx index b177a8eca25b1..654858b3b264a 100644 --- a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx +++ b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx @@ -39,10 +39,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) auto rdhVersion = cfgc.options().get<int>("tof-compressed-inspector-rdh-version"); AlgorithmSpec algoSpec; - if (rdhVersion == 4) + if (rdhVersion == 4) { algoSpec = AlgorithmSpec{adaptFromTask<o2::tof::CompressedInspectorTask<o2::header::RAWDataHeaderV4>>()}; - else if (rdhVersion == 6) + } else if (rdhVersion == 6) { algoSpec = AlgorithmSpec{adaptFromTask<o2::tof::CompressedInspectorTask<o2::header::RAWDataHeaderV6>>()}; + } WorkflowSpec workflow; workflow.emplace_back(DataProcessorSpec{ diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index 9144225f17056..303490ad74ba3 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -164,14 +164,16 @@ void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdig rofRec.setNEntries(cc.ndigROF[irof]); rofRec.setFirstEntryDia(ndiagnostic); rofRec.setNEntriesDia(cc.ndiaROF[irof]); - for (int icrate = 0; icrate < 72; icrate++) + for (int icrate = 0; icrate < 72; icrate++) { rofRec.setDiagnosticInCrate(icrate, cc.ndiaCrate[irof * 72 + icrate]); + } firstEntry += cc.ndigROF[irof]; ndiagnostic += cc.ndiaROF[irof]; - if (!cc.ndigROF[irof]) + if (!cc.ndigROF[irof]) { continue; + } // restore hit data uint ctimeframe = 0; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h index fa6ea9e670384..a4346afb59298 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h @@ -44,13 +44,15 @@ class DecoderBaseT if (mDecoderCONET) { mDecoderPointerMax = reinterpret_cast<const uint32_t*>(mDecoderBuffer + mDecoderBufferSize); while (mDecoderPointer < mDecoderPointerMax) { - if (processDRM()) + if (processDRM()) { return false; + } } return false; } - while (!processHBF()) + while (!processHBF()) { ; + } return false; }; diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index 8d745f9dd50c2..58676a9406dbc 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -93,8 +93,9 @@ void CTFCoder::compress(CompressedInfos& cc, auto ndig = rofRec.size(); cc.ndigROF[irof] = ndig; cc.ndiaROF[irof] = rofRec.sizeDia(); - for (int icrate = 0; icrate < 72; icrate++) + for (int icrate = 0; icrate < 72; icrate++) { cc.ndiaCrate[irof * 72 + icrate] = rofRec.getDiagnosticInCrate(icrate); + } if (!ndig) { // no hits data for this ROF --> not fill continue; @@ -112,10 +113,11 @@ void CTFCoder::compress(CompressedInfos& cc, // sort digits according to time (ascending order) std::sort(digCopy.begin(), digCopy.end(), [](o2::tof::Digit a, o2::tof::Digit b) { - if (a.getBC() == b.getBC()) + if (a.getBC() == b.getBC()) { return a.getTDC() < b.getTDC(); - else + } else { return a.getBC() < b.getBC(); + } }); int timeframe = 0; diff --git a/Detectors/TOF/reconstruction/src/Clusterer.cxx b/Detectors/TOF/reconstruction/src/Clusterer.cxx index 5cc612a247518..bb191e5dcf9b5 100644 --- a/Detectors/TOF/reconstruction/src/Clusterer.cxx +++ b/Detectors/TOF/reconstruction/src/Clusterer.cxx @@ -74,8 +74,9 @@ void Clusterer::processStrip(std::vector<Cluster>& clusters, MCLabelContainer co // LOG(DEBUG) << "Checking digit " << idig; Digit* dig = &mStripData.digits[idig]; //printf("checking digit %d - alreadyUsed=%d - problematic=%d\n",idig,dig->isUsedInCluster(),dig->isProblematic()); // toberem - if (dig->isUsedInCluster() || dig->isProblematic()) + if (dig->isUsedInCluster() || dig->isProblematic()) { continue; // the digit was already used to build a cluster, or it was declared problematic + } mNumberOfContributingDigits = 0; dig->getPhiAndEtaIndex(iphi, ieta); @@ -93,20 +94,23 @@ void Clusterer::processStrip(std::vector<Cluster>& clusters, MCLabelContainer co for (int idigNext = idig + 1; idigNext < mStripData.digits.size(); idigNext++) { Digit* digNext = &mStripData.digits[idigNext]; - if (digNext->isUsedInCluster() || dig->isProblematic()) + if (digNext->isUsedInCluster() || dig->isProblematic()) { continue; // the digit was already used to build a cluster, or was problematic + } // check if the TOF time are close enough to be merged; if not, it means that nothing else will contribute to the cluster (since digits are ordered in time) double timeDigNext = digNext->getCalibratedTime(); // in ps LOG(DEBUG) << "Time difference = " << timeDigNext - timeDig; - if (timeDigNext - timeDig > 500 /*in ps*/) + if (timeDigNext - timeDig > 500 /*in ps*/) { break; + } digNext->getPhiAndEtaIndex(iphi2, ieta2); // check if the fired pad are close in space LOG(DEBUG) << "phi difference = " << iphi - iphi2; LOG(DEBUG) << "eta difference = " << ieta - ieta2; - if ((TMath::Abs(iphi - iphi2) > 1) || (TMath::Abs(ieta - ieta2) > 1)) + if ((TMath::Abs(iphi - iphi2) > 1) || (TMath::Abs(ieta - ieta2) > 1)) { continue; + } // if we are here, the digit contributes to the cluster addContributingDigit(digNext); diff --git a/Detectors/TOF/reconstruction/src/ClustererTask.cxx b/Detectors/TOF/reconstruction/src/ClustererTask.cxx index 0c74c75daced8..2410a47b349d1 100644 --- a/Detectors/TOF/reconstruction/src/ClustererTask.cxx +++ b/Detectors/TOF/reconstruction/src/ClustererTask.cxx @@ -27,8 +27,9 @@ using namespace o2::tof; //_____________________________________________________________________ ClustererTask::ClustererTask(Bool_t useMCTruth) : FairTask("TOFClustererTask") { - if (useMCTruth) + if (useMCTruth) { mClsLabels = new o2::dataformats::MCTruthContainer<o2::MCCompLabel>; + } } //_____________________________________________________________________ @@ -74,8 +75,9 @@ InitStatus ClustererTask::Init() mgr->RegisterAny("TOFCluster", mClustersArray, kTRUE); // Register new MC Truth container --> here we will now associate to the clusters all labels that belonged to all digits that formed that cluster - if (mClsLabels) + if (mClsLabels) { mgr->RegisterAny("TOFClusterMCTruth", mClsLabels, kTRUE); + } mClusterer.setMCTruthContainer(mClsLabels); @@ -85,10 +87,12 @@ InitStatus ClustererTask::Init() //_____________________________________________________________________ void ClustererTask::Exec(Option_t* option) { - if (mClustersArray) + if (mClustersArray) { mClustersArray->clear(); - if (mClsLabels) + } + if (mClsLabels) { mClsLabels->clear(); + } LOG(DEBUG) << "Running clusterization on new event"; mClusterer.process(mReader, *mClustersArray, mDigitMCTruth); diff --git a/Detectors/TOF/reconstruction/src/DataReader.cxx b/Detectors/TOF/reconstruction/src/DataReader.cxx index 81a53c7c84d42..8057f86fbeebd 100644 --- a/Detectors/TOF/reconstruction/src/DataReader.cxx +++ b/Detectors/TOF/reconstruction/src/DataReader.cxx @@ -41,8 +41,9 @@ Bool_t DigitDataReader::getNextStripData(StripData& stripData) while (mIdx < mDigitArray->size()) { mLastDigit = &((*mDigitArray)[mIdx++]); - if (stripData.stripID != mLastDigit->getChannel() / Geo::NPADS) + if (stripData.stripID != mLastDigit->getChannel() / Geo::NPADS) { break; + } stripData.digits.emplace_back(*mLastDigit); mLastDigit = nullptr; } diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index 10a349648d188..2cd9c323395f9 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -79,8 +79,9 @@ bool Decoder::open(const std::string name) char* pos = new char[fullsize]; //mBufferLocal.data(); for (int i = 0; i < NCRU; i++) { - if (!mCruIn[i]) + if (!mCruIn[i]) { continue; + } mBuffer[i] = pos; @@ -102,8 +103,9 @@ bool Decoder::open(const std::string name) bool Decoder::close() { for (int i = 0; i < NCRU; i++) { - if (mFile[i].is_open()) + if (mFile[i].is_open()) { mFile[i].close(); + } } return false; } @@ -111,8 +113,9 @@ bool Decoder::close() void Decoder::clear() { reset(); - if (mMaskNoiseRate > 0) + if (mMaskNoiseRate > 0) { clearCounts(); + } mPatterns.clear(); mCratePatterns.clear(); @@ -125,8 +128,9 @@ void Decoder::InsertDigit(int icrate, int itrm, int itdc, int ichain, int channe DigitInfo digitInfo; fromRawHit2Digit(icrate, itrm, itdc, ichain, channel, orbit, bunchid, time_ext + tdc, tot, digitInfo); - if (mMaskNoiseRate > 0) + if (mMaskNoiseRate > 0) { mChannelCounts[digitInfo.channel]++; + } mHitDecoded++; @@ -162,8 +166,9 @@ void Decoder::readTRM(int icru, int icrate, uint32_t orbit, uint16_t bunchid) int itrm = mUnion[icru]->frameHeader.trmID; int deltaBC = mUnion[icru]->frameHeader.deltaBC; - if (deltaBC != 0) + if (deltaBC != 0) { printf("DeltaBC = %d\n", deltaBC); + } mUnion[icru]++; mIntegratedBytes[icru] += 4; @@ -172,13 +177,15 @@ void Decoder::readTRM(int icru, int icrate, uint32_t orbit, uint16_t bunchid) for (int i = 0; i < nhits; i++) { fromRawHit2Digit(icrate, itrm, mUnion[icru]->packedHit.tdcID, mUnion[icru]->packedHit.chain, mUnion[icru]->packedHit.channel, orbit, bunchid, time_ext + mUnion[icru]->packedHit.time, mUnion[icru]->packedHit.tot, digitInfo); - if (mMaskNoiseRate > 0) + if (mMaskNoiseRate > 0) { mChannelCounts[digitInfo.channel]++; + } mHitDecoded++; - if (mVerbose) + if (mVerbose) { printHitInfo(icru); + } uint64_t isnext = digitInfo.bcAbs * Geo::BC_IN_WINDOW_INV; @@ -187,8 +194,9 @@ void Decoder::readTRM(int icru, int icrate, uint32_t orbit, uint16_t bunchid) insertDigitInFuture(digitInfo.channel, digitInfo.tdc, digitInfo.tot, digitInfo.bcAbs, 0, digitInfo.orbit, digitInfo.bc); } else { std::vector<Strip>* cstrip = mStripsCurrent; // first window - if (isnext) + if (isnext) { cstrip = mStripsNext[isnext - 1]; // next window + } UInt_t istrip = digitInfo.channel / Geo::NPADS; @@ -238,16 +246,18 @@ bool Decoder::decode() // return a vector of digits in a TOF readout window // loop over CRUs for (int icru = 0; icru < NCRU; icru++) { - if (!mCruIn[icru]) + if (!mCruIn[icru]) { continue; // no data stream available for this cru + } printf("decoding cru %d\n", icru); while (mUnion[icru] < mUnionEnd[icru]) { // read all the buffer // read open RDH mRDH = reinterpret_cast<o2::header::RAWDataHeader*>(mUnion[icru]); - if (mVerbose) + if (mVerbose) { printRDH(); + } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // note that RDH continue is not yet considered as option (to be added) @@ -259,21 +269,24 @@ bool Decoder::decode() // return a vector of digits in a TOF readout window mUnion[icru] = reinterpret_cast<Union_t*>(shift + rdhsz); mIntegratedBytes[icru] += rdhsz; - if (mUnion[icru] >= mUnionEnd[icru]) + if (mUnion[icru] >= mUnionEnd[icru]) { continue; // end of data stream reac + } for (int window = 0; window < Geo::NWINDOW_IN_ORBIT; window++) { // read Crate Header int bunchid = mUnion[icru]->crateHeader.bunchID; int icrate = mUnion[icru]->crateHeader.drmID; - if (mVerbose) + if (mVerbose) { printCrateInfo(icru); + } mUnion[icru]++; mIntegratedBytes[icru] += 4; //read Orbit int orbit = mUnion[icru]->crateOrbit.orbitID; - if (mVerbose) + if (mVerbose) { printf("%d) orbit ID = %d -- bunch ID = %d\n", icrate, orbit, bunchid); + } mUnion[icru]++; mIntegratedBytes[icru] += 4; @@ -282,8 +295,9 @@ bool Decoder::decode() // return a vector of digits in a TOF readout window } // read Crate Trailer - if (mVerbose) + if (mVerbose) { printCrateTrailerInfo(icru); + } auto ndw = mUnion[icru]->crateTrailer.numberOfDiagnostics; mUnion[icru]++; mIntegratedBytes[icru] += 4; @@ -297,8 +311,9 @@ bool Decoder::decode() // return a vector of digits in a TOF readout window // read close RDH mRDH = reinterpret_cast<o2::header::RAWDataHeader*>(nextPage(mRDH, RDHUtils::getMemorySize(*mRDH))); - if (mVerbose) + if (mVerbose) { printRDH(); + } mIntegratedBytes[icru] += RDHUtils::getHeaderSize(*mRDH); // go to next page diff --git a/Detectors/TOF/reconstruction/src/DecoderBase.cxx b/Detectors/TOF/reconstruction/src/DecoderBase.cxx index a52b6277cb1a1..8c7fcb4a299fe 100644 --- a/Detectors/TOF/reconstruction/src/DecoderBase.cxx +++ b/Detectors/TOF/reconstruction/src/DecoderBase.cxx @@ -90,8 +90,9 @@ bool DecoderBaseT<RDH>::processHBF() rdh = reinterpret_cast<const RDH*>(reinterpret_cast<const char*>(rdh) + offsetToNext); /** check next RDH is within buffer **/ - if (reinterpret_cast<const char*>(rdh) < mDecoderBuffer + mDecoderBufferSize) + if (reinterpret_cast<const char*>(rdh) < mDecoderBuffer + mDecoderBufferSize) { continue; + } /** otherwise return **/ return true; @@ -111,8 +112,9 @@ bool DecoderBaseT<RDH>::processHBF() mDecoderPointer = reinterpret_cast<const uint32_t*>(mDecoderSaveBuffer); mDecoderPointerMax = reinterpret_cast<const uint32_t*>(mDecoderSaveBuffer + mDecoderSaveBufferDataSize); while (mDecoderPointer < mDecoderPointerMax) { - if (processDRM()) + if (processDRM()) { break; + } } mDecoderSaveBufferDataSize = 0; @@ -132,8 +134,9 @@ bool DecoderBaseT<RDH>::processHBF() mDecoderPointer = reinterpret_cast<const uint32_t*>(reinterpret_cast<const char*>(rdh) + RDHUtils::getOffsetToNext(*rdh)); /** check next RDH is within buffer **/ - if (reinterpret_cast<const char*>(mDecoderPointer) < mDecoderBuffer + mDecoderBufferSize) + if (reinterpret_cast<const char*>(mDecoderPointer) < mDecoderBuffer + mDecoderBufferSize) { return false; + } /** otherwise return **/ return true; diff --git a/Detectors/TOF/reconstruction/src/Encoder.cxx b/Detectors/TOF/reconstruction/src/Encoder.cxx index 3f976faacda3b..41f0146bc97b5 100644 --- a/Detectors/TOF/reconstruction/src/Encoder.cxx +++ b/Detectors/TOF/reconstruction/src/Encoder.cxx @@ -119,8 +119,9 @@ bool Encoder::close() bool Encoder::alloc(long size) { - if (size < 500000) + if (size < 500000) { size = 500000; + } mSize = size; @@ -143,8 +144,9 @@ void Encoder::encodeTRM(const std::vector<Digit>& summary, Int_t icrate, Int_t i // return next TRM index (-1 if not in the same crate) // start to convert digiti from istart --> then update istart to the starting position of the new TRM { - if (mVerbose) + if (mVerbose) { printf("Crate %d: encode TRM %d \n", icrate, itrm); + } // TRM HEADER Union_t* trmheader = mUnion[icrate]; @@ -167,14 +169,17 @@ void Encoder::encodeTRM(const std::vector<Digit>& summary, Int_t icrate, Int_t i while (istart < summary.size()) { // fill hits /** loop over hits **/ int whatChain = summary[istart].getElChainIndex(); - if (whatChain != ichain) + if (whatChain != ichain) { break; + } int whatTRM = summary[istart].getElTRMIndex(); - if (whatTRM != itrm) + if (whatTRM != itrm) { break; + } int whatCrate = summary[istart].getElCrateIndex(); - if (whatCrate != icrate) + if (whatCrate != icrate) { break; + } int hittimeTDC = (summary[istart].getBC() - mEventCounter * Geo::BC_IN_WINDOW) * 1024 + summary[istart].getTDC(); // time in TDC bin within the TOF WINDOW @@ -245,16 +250,18 @@ bool Encoder::encode(std::vector<std::vector<o2::tof::Digit>> digitWindow, int t } #ifdef VERBOSE - if (mVerbose) + if (mVerbose) { std::cout << "-------- START ENCODE EVENT ----------------------------------------" << std::endl; + } #endif auto start = std::chrono::high_resolution_clock::now(); mEventCounter = tofwindow; // tof window index mIR.orbit = mEventCounter / Geo::NWINDOW_IN_ORBIT; - for (int i = 0; i < 72; i++) + for (int i = 0; i < 72; i++) { mNextWordStatus[i] = false; + } int bcFirstWin; @@ -266,8 +273,9 @@ bool Encoder::encode(std::vector<std::vector<o2::tof::Digit>> digitWindow, int t mIR.bc = ((mEventCounter % Geo::NWINDOW_IN_ORBIT) * Geo::BC_IN_ORBIT) / Geo::NWINDOW_IN_ORBIT + mFirstBC; // bunch crossing in the current orbit at the beginning of the window. - if (iwin == 0) + if (iwin == 0) { bcFirstWin = mIR.bc; + } int icurrentdigit = 0; // TOF data header @@ -354,8 +362,9 @@ bool Encoder::encode(std::vector<std::vector<o2::tof::Digit>> digitWindow, int t mIR.bc = bcFirstWin; - for (int i = 0; i < 72; i++) + for (int i = 0; i < 72; i++) { flush(i); + } mStartRun = false; diff --git a/Detectors/TOF/simulation/src/Detector.cxx b/Detectors/TOF/simulation/src/Detector.cxx index f93f64bc72058..5001fda818ef6 100644 --- a/Detectors/TOF/simulation/src/Detector.cxx +++ b/Detectors/TOF/simulation/src/Detector.cxx @@ -29,8 +29,9 @@ ClassImp(Detector); Detector::Detector(Bool_t active) : o2::base::DetImpl<Detector>("TOF", active), mEventNr(0), mTOFHoles(kTRUE), mHits(o2::utils::createSimVector<HitType>()) { - for (Int_t i = 0; i < Geo::NSECTORS; i++) + for (Int_t i = 0; i < Geo::NSECTORS; i++) { mTOFSectors[i] = 1; + } } Detector::Detector(const Detector& rhs) @@ -39,8 +40,9 @@ Detector::Detector(const Detector& rhs) mTOFHoles(rhs.mTOFHoles), mHits(o2::utils::createSimVector<HitType>()) { - for (Int_t i = 0; i < Geo::NSECTORS; i++) + for (Int_t i = 0; i < Geo::NSECTORS; i++) { mTOFSectors[i] = rhs.mTOFSectors[i]; + } } Detector::~Detector() @@ -51,9 +53,9 @@ Detector::~Detector() void Detector::InitializeO2Detector() { TGeoVolume* v = gGeoManager->GetVolume("FPAD"); - if (v == nullptr) + if (v == nullptr) { printf("Sensitive volume FSEN not found!!!!!!!!"); - else { + } else { AddSensitiveVolume(v); } } @@ -72,8 +74,9 @@ Bool_t Detector::ProcessHits(FairVolume* v) LOG(DEBUG) << "Process hit in TOF volume ar R=" << radius << " - Z=" << pos2z; Float_t enDep = fMC->Edep(); - if (enDep < 1E-8) + if (enDep < 1E-8) { return kFALSE; // wo se need a threshold? + } // ADD HIT float posx, posy, posz; @@ -193,14 +196,17 @@ void Detector::CreateMaterials() Float_t asc[4] = {12.011, 1.00794, 26.981539, 63.546}; Float_t zsc[4] = {6., 1., 13., 29.}; Float_t wsc[4]; - for (Int_t ii = 0; ii < 4; ii++) + for (Int_t ii = 0; ii < 4; ii++) { wsc[ii] = 0.; + } Float_t wDummy[4], nDummy[4]; - for (Int_t ii = 0; ii < 4; ii++) + for (Int_t ii = 0; ii < 4; ii++) { wDummy[ii] = 0.; - for (Int_t ii = 0; ii < 4; ii++) + } + for (Int_t ii = 0; ii < 4; ii++) { nDummy[ii] = 0.; + } nDummy[0] = 1.; nDummy[1] = 2.; MaterialMixer(wDummy, asc, nDummy, 2); @@ -344,8 +350,9 @@ void Detector::createModules(Float_t xtof, Float_t ytof, Float_t zlenA, Float_t // Int_t idrotm[8]; - for (Int_t ii = 0; ii < 8; ii++) + for (Int_t ii = 0; ii < 8; ii++) { idrotm[ii] = 0; + } // Definition of the of fibre glass modules (FTOA, FTOB and FTOC) Float_t par[3]; @@ -748,23 +755,26 @@ void Detector::makeStripsInModules(Float_t ytof, Float_t zlenA) const Int_t maxStripNumbers[5] = {Geo::NSTRIPC, Geo::NSTRIPB, Geo::NSTRIPA, Geo::NSTRIPB, Geo::NSTRIPC}; Int_t idrotm[Geo::NSTRIPXSECTOR]; - for (Int_t ii = 0; ii < Geo::NSTRIPXSECTOR; ii++) + for (Int_t ii = 0; ii < Geo::NSTRIPXSECTOR; ii++) { idrotm[ii] = 0; + } Int_t totalStrip = 0; Float_t xpos, zpos, ypos, ang; for (Int_t iplate = 0; iplate < Geo::NPLATES; iplate++) { - if (iplate > 0) + if (iplate > 0) { totalStrip += maxStripNumbers[iplate - 1]; + } for (Int_t istrip = 0; istrip < maxStripNumbers[iplate]; istrip++) { ang = Geo::getAngles(iplate, istrip); - if (ang > 0.) + if (ang > 0.) { Matrix(idrotm[istrip + totalStrip], 90., 0., 90. + ang, 90., ang, 90.); - else if (ang == 0.) + } else if (ang == 0.) { Matrix(idrotm[istrip + totalStrip], 90., 0., 90., 90., 0., 0.); - else if (ang < 0.) + } else if (ang < 0.) { Matrix(idrotm[istrip + totalStrip], 90., 0., 90. + ang, 90., -ang, 270.); + } xpos = 0.; ypos = Geo::getHeights(iplate, istrip) + yFLT * 0.5; @@ -773,16 +783,18 @@ void Detector::makeStripsInModules(Float_t ytof, Float_t zlenA) const idrotm[istrip + totalStrip], "ONLY"); if (mTOFHoles) { - if (istrip + totalStrip + 1 > 53) + if (istrip + totalStrip + 1 > 53) { TVirtualMC::GetMC()->Gspos( "FSTR", istrip + totalStrip + 1, "FLTC", xpos, ypos, -zpos - (zlenA * 0.5 - 2. * Geo::MODULEWALLTHICKNESS + Geo::INTERCENTRMODBORDER1) * 0.5, idrotm[istrip + totalStrip], "ONLY"); - if (istrip + totalStrip + 1 < 39) + } + if (istrip + totalStrip + 1 < 39) { TVirtualMC::GetMC()->Gspos( "FSTR", istrip + totalStrip + 1, "FLTB", xpos, ypos, -zpos + (zlenA * 0.5 - 2. * Geo::MODULEWALLTHICKNESS + Geo::INTERCENTRMODBORDER1) * 0.5, idrotm[istrip + totalStrip], "ONLY"); + } } } } @@ -805,8 +817,9 @@ void Detector::createModuleCovers(Float_t xtof, Float_t zlenA) const par[1] = Geo::MODULECOVERTHICKNESS * 0.5; par[2] = zlenA * 0.5 + 2.; TVirtualMC::GetMC()->Gsvolu("FPEA", "BOX ", getMediumID(kAir), par, 3); // Air - if (mTOFHoles) + if (mTOFHoles) { TVirtualMC::GetMC()->Gsvolu("FPEB", "BOX ", getMediumID(kAir), par, 3); // Air + } constexpr Float_t ALCOVERTHICKNESS = 1.5; constexpr Float_t INTERFACECARDTHICKNESS = 0.16; @@ -818,15 +831,17 @@ void Detector::createModuleCovers(Float_t xtof, Float_t zlenA) const par[1] = ALCOVERTHICKNESS * 0.5; // par[2] = zlenA*0.5 + 2.; TVirtualMC::GetMC()->Gsvolu("FALT", "BOX ", getMediumID(kAlFrame), par, 3); // Al - if (mTOFHoles) + if (mTOFHoles) { TVirtualMC::GetMC()->Gsvolu("FALB", "BOX ", getMediumID(kAlFrame), par, 3); // Al + } Float_t xcoor, ycoor, zcoor; xcoor = 0.; ycoor = 0.; zcoor = 0.; TVirtualMC::GetMC()->Gspos("FALT", 0, "FPEA", xcoor, ycoor, zcoor, 0, "ONLY"); - if (mTOFHoles) + if (mTOFHoles) { TVirtualMC::GetMC()->Gspos("FALB", 0, "FPEB", xcoor, ycoor, zcoor, 0, "ONLY"); + } par[0] = xtof * 0.5; // par[1] = ALCOVERTHICKNESS*0.5; @@ -1001,8 +1016,9 @@ void Detector::createBackZone(Float_t xtof, Float_t ytof, Float_t zlenA) const par[1] = (ytof * 0.5 - Geo::MODULECOVERTHICKNESS) * 0.5; par[2] = zlenA * 0.5; TVirtualMC::GetMC()->Gsvolu("FAIA", "BOX ", getMediumID(kAir), par, 3); // Air - if (mTOFHoles) + if (mTOFHoles) { TVirtualMC::GetMC()->Gsvolu("FAIB", "BOX ", getMediumID(kAir), par, 3); // Air + } TVirtualMC::GetMC()->Gsvolu("FAIC", "BOX ", getMediumID(kAir), par, 3); // Air Float_t feaParam[3] = {Geo::FEAPARAMETERS[0], Geo::FEAPARAMETERS[1], Geo::FEAPARAMETERS[2]}; @@ -1676,8 +1692,9 @@ void Detector::makeReadoutCrates(Float_t ytof) const // Int_t idrotm[Geo::NSECTORS]; - for (Int_t ii = 0; ii < Geo::NSECTORS; ii++) + for (Int_t ii = 0; ii < Geo::NSECTORS; ii++) { idrotm[ii] = 0; + } // volume definition Float_t serpar[3] = {29. * 0.5, 121. * 0.5, 90. * 0.5}; @@ -1719,8 +1736,9 @@ void Detector::makeModulesInBTOFvolumes(Float_t ytof, Float_t zlenA) const // Positioning of fibre glass modules (FTOA, FTOB and FTOC) for (Int_t isec = 0; isec < Geo::NSECTORS; isec++) { - if (mTOFSectors[isec] == -1) + if (mTOFSectors[isec] == -1) { continue; + } char name[SIZESTR]; snprintf(name, SIZESTR, "BTOF%d", isec); @@ -1773,13 +1791,15 @@ void Detector::makeCoversInBTOFvolumes() const // Positioning of module covers (FPEA, FPEB) for (Int_t isec = 0; isec < Geo::NSECTORS; isec++) { - if (mTOFSectors[isec] == -1) + if (mTOFSectors[isec] == -1) { continue; + } snprintf(name, SIZESTR, "BTOF%d", isec); - if (mTOFHoles && (isec == 13 || isec == 14 || isec == 15)) + if (mTOFHoles && (isec == 13 || isec == 14 || isec == 15)) { TVirtualMC::GetMC()->Gspos("FPEB", 0, name, xcoor, ycoor, zcoor, idrotm[0], "ONLY"); - else + } else { TVirtualMC::GetMC()->Gspos("FPEA", 0, name, xcoor, ycoor, zcoor, idrotm[0], "ONLY"); + } } } @@ -1809,16 +1829,18 @@ void Detector::makeBackInBTOFvolumes(Float_t ytof) const // Positioning of FEA cards and services containers (FAIA, FAIC and FAIB) for (Int_t isec = 0; isec < Geo::NSECTORS; isec++) { - if (mTOFSectors[isec] == -1) + if (mTOFSectors[isec] == -1) { continue; + } snprintf(name, SIZESTR, "BTOF%d", isec); - if (Geo::FEAWITHMASKS[isec]) + if (Geo::FEAWITHMASKS[isec]) { TVirtualMC::GetMC()->Gspos("FAIA", 0, name, xcoor, ycoor, zcoor, idrotm[0], "ONLY"); - else { - if (mTOFHoles && (isec == 13 || isec == 14 || isec == 15)) + } else { + if (mTOFHoles && (isec == 13 || isec == 14 || isec == 15)) { TVirtualMC::GetMC()->Gspos("FAIB", 0, name, xcoor, ycoor, zcoor, idrotm[0], "ONLY"); - else + } else { TVirtualMC::GetMC()->Gspos("FAIC", 0, name, xcoor, ycoor, zcoor, idrotm[0], "ONLY"); + } } } } @@ -1859,8 +1881,9 @@ void Detector::addAlignableVolumes() const modUID = o2::base::GeometryManager::getSensID(idTOF, modnum++); LOG(DEBUG) << "modUID: " << modUID; - if (mTOFSectors[isect] == -1) + if (mTOFSectors[isect] == -1) { continue; + } if (mTOFHoles && (isect == 13 || isect == 14 || isect == 15)) { if (istr < 39) { @@ -1869,8 +1892,9 @@ void Detector::addAlignableVolumes() const } else if (istr > 53) { vpL3 = "/FTOC_0"; vpL4 = "/FLTC_0/FSTR_"; - } else + } else { continue; + } } else { vpL3 = "/FTOA_0"; vpL4 = "/FLTA_0/FSTR_"; diff --git a/Detectors/TOF/simulation/src/Digitizer.cxx b/Detectors/TOF/simulation/src/Digitizer.cxx index 2b27665a75b52..553615fdb7587 100644 --- a/Detectors/TOF/simulation/src/Digitizer.cxx +++ b/Detectors/TOF/simulation/src/Digitizer.cxx @@ -130,8 +130,9 @@ Int_t Digitizer::processHit(const HitType& hit, Double_t event_time) detIndOtherPad[2] = detInd[2]; // same sector, plate, strip Int_t otherraw = 0; - if (detInd[3] == 0) + if (detInd[3] == 0) { otherraw = 1; + } Int_t iZshift = otherraw ? 1 : -1; @@ -167,10 +168,11 @@ Int_t Digitizer::processHit(const HitType& hit, Double_t event_time) detIndOtherPad[4] = detInd[4]; channel = Geo::getIndex(detIndOtherPad); xLocal = deltapos[0]; // recompute local coordinates - if (otherraw) + if (otherraw) { zLocal = deltapos[2] - Geo::ZPAD; // recompute local coordinates - else + } else { zLocal = deltapos[2] + Geo::ZPAD; + } if (isFired(xLocal, zLocal, charge)) { ndigits++; addDigit(channel, istrip, time, xLocal, zLocal, charge, 0, iZshift, detInd[3], trackID); @@ -208,10 +210,11 @@ Int_t Digitizer::processHit(const HitType& hit, Double_t event_time) if (detIndOtherPad[4] >= 0) { channel = Geo::getIndex(detIndOtherPad); xLocal = deltapos[0] + Geo::XPAD; // recompute local coordinates - if (otherraw) + if (otherraw) { zLocal = deltapos[2] - Geo::ZPAD; // recompute local coordinates - else + } else { zLocal = deltapos[2] + Geo::ZPAD; + } if (isFired(xLocal, zLocal, charge)) { ndigits++; addDigit(channel, istrip, time, xLocal, zLocal, charge, -1, iZshift, detInd[3], trackID); @@ -224,10 +227,11 @@ Int_t Digitizer::processHit(const HitType& hit, Double_t event_time) if (detIndOtherPad[4] < Geo::NPADX) { channel = Geo::getIndex(detIndOtherPad); xLocal = deltapos[0] - Geo::XPAD; // recompute local coordinates - if (otherraw) + if (otherraw) { zLocal = deltapos[2] - Geo::ZPAD; // recompute local coordinates - else + } else { zLocal = deltapos[2] + Geo::ZPAD; + } if (isFired(xLocal, zLocal, charge)) { ndigits++; addDigit(channel, istrip, time, xLocal, zLocal, charge, 1, iZshift, detInd[3], trackID); @@ -248,8 +252,9 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, // tot tuned to reproduce 0.8% of orphans tot(=0) Float_t tot = gRandom->Gaus(12., 1.5); // time-over-threshold - if (tot < 8.4) + if (tot < 8.4) { tot = 0; + } Float_t xborder = Geo::XPAD * 0.5 - TMath::Abs(x); Float_t zborder = Geo::ZPAD * 0.5 - TMath::Abs(z); @@ -267,8 +272,9 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, // if(border > 0) printf("deltat =%f\n",mTimeDelay*border*border*border); // else printf("deltat=0\n"); // getchar(); - if (border > 0) + if (border > 0) { time += mTimeDelay * border * border * border; + } } time += TMath::Sqrt(timewalkX * timewalkX + timewalkZ * timewalkZ) - mTimeDelayCorr - mTimeWalkeSlope * 2; @@ -299,9 +305,9 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, isnext = nbc / Geo::BC_IN_WINDOW - mReadoutWindowCurrent; isIfOverlap = (nbc - Geo::OVERLAP_IN_BC) / Geo::BC_IN_WINDOW - mReadoutWindowCurrent; - if (isnext == isIfOverlap) + if (isnext == isIfOverlap) { isIfOverlap = -1; - else if (isnext < 0 && isIfOverlap >= 0) { + } else if (isnext < 0 && isIfOverlap >= 0) { isnext = isIfOverlap; isIfOverlap = -1; } else if (isnext >= MAXWINDOWS && isIfOverlap < MAXWINDOWS) { @@ -336,8 +342,9 @@ void Digitizer::addDigit(Int_t channel, UInt_t istrip, Double_t time, Float_t x, insertDigitInFuture(channel, tdc, tot * Geo::NTOTBIN_PER_NS, nbc, lblCurrent); } - if (isnext) + if (isnext) { iscurrent = false; + } } //printf("add TOF digit c=%i n=%i\n",iscurrent,isnext); @@ -420,18 +427,21 @@ Float_t Digitizer::getCharge(Float_t eDep) //______________________________________________________________________ Bool_t Digitizer::isFired(Float_t x, Float_t z, Float_t charge) { - if (TMath::Abs(x) > Geo::XPAD * 0.5 + 0.3) + if (TMath::Abs(x) > Geo::XPAD * 0.5 + 0.3) { return kFALSE; - if (TMath::Abs(z) > Geo::ZPAD * 0.5 + 0.3) + } + if (TMath::Abs(z) > Geo::ZPAD * 0.5 + 0.3) { return kFALSE; + } Float_t effX = getEffX(x); Float_t effZ = getEffZ(z); Float_t efficiency = TMath::Min(effX, effZ); - if (gRandom->Rndm() > efficiency) + if (gRandom->Rndm() > efficiency) { return kFALSE; + } return kTRUE; } @@ -442,20 +452,22 @@ Float_t Digitizer::getEffX(Float_t x) Float_t xborder = Geo::XPAD * 0.5 - TMath::Abs(x); if (xborder > 0) { - if (xborder > mBound1) + if (xborder > mBound1) { return mEffCenter; - else if (xborder > mBound2) + } else if (xborder > mBound2) { return mEffBoundary1 + (mEffCenter - mEffBoundary1) * (xborder - mBound2) / (mBound1 - mBound2); - else + } else { return mEffBoundary2 + (mEffBoundary1 - mEffBoundary2) * xborder / mBound2; + } } else { xborder *= -1; - if (xborder > mBound4) + if (xborder > mBound4) { return 0; - else if (xborder > mBound3) + } else if (xborder > mBound3) { return mEffBoundary3 - mEffBoundary3 * (xborder - mBound3) / (mBound4 - mBound3); - else + } else { return mEffBoundary2 + (mEffBoundary3 - mEffBoundary2) * xborder / mBound3; + } } return 0; @@ -467,20 +479,22 @@ Float_t Digitizer::getEffZ(Float_t z) Float_t zborder = Geo::ZPAD * 0.5 - TMath::Abs(z); if (zborder > 0) { - if (zborder > mBound1) + if (zborder > mBound1) { return mEffCenter; - else if (zborder > mBound2) + } else if (zborder > mBound2) { return mEffBoundary1 + (mEffCenter - mEffBoundary1) * (zborder - mBound2) / (mBound1 - mBound2); - else + } else { return mEffBoundary2 + (mEffBoundary1 - mEffBoundary2) * zborder / mBound2; + } } else { zborder *= -1; - if (zborder > mBound4) + if (zborder > mBound4) { return 0; - else if (zborder > mBound3) + } else if (zborder > mBound3) { return mEffBoundary3 - mEffBoundary3 * (zborder - mBound3) / (mBound4 - mBound3); - else + } else { return mEffBoundary2 + (mEffBoundary3 - mEffBoundary2) * zborder / mBound3; + } } return 0; @@ -500,10 +514,10 @@ void Digitizer::initParameters() // resolution parameters mTOFresolution = 60; // TOF global resolution in ps mShowerResolution = 50; // smearing correlated for all digits of the same hit - if (mTOFresolution > mShowerResolution) + if (mTOFresolution > mShowerResolution) { mDigitResolution = TMath::Sqrt(mTOFresolution * mTOFresolution - mShowerResolution * mShowerResolution); // independent smearing for each digit - else { + } else { mShowerResolution = mTOFresolution; mDigitResolution = 0; } @@ -519,15 +533,17 @@ void Digitizer::initParameters() } mTimeDelayCorr = mTimeDelay / 3.5; - if (mShowerResolution > mTimeDelayCorr) + if (mShowerResolution > mTimeDelayCorr) { mShowerResolution = TMath::Sqrt(mShowerResolution * mShowerResolution - mTimeDelayCorr * mTimeDelayCorr); - else + } else { mShowerResolution = 0; + } - if (mShowerResolution > mTimeWalkeSlope * 0.8) + if (mShowerResolution > mTimeWalkeSlope * 0.8) { mShowerResolution = TMath::Sqrt(mShowerResolution * mShowerResolution - mTimeWalkeSlope * mTimeWalkeSlope * 0.64); - else + } else { mShowerResolution = 0; + } // efficiency parameters mEffCenter = 0.995; // efficiency in the center of the fired pad @@ -542,12 +558,15 @@ void Digitizer::printParameters() printf("Efficiency in the pad center = %f\n", mEffCenter); printf("Efficiency in the pad border = %f\n", mEffBoundary2); printf("Time resolution = %f ps (shower=%f, digit=%f)\n", mTOFresolution, mShowerResolution, mDigitResolution); - if (mTimeSlope > 0) + if (mTimeSlope > 0) { printf("Degration resolution for pad with signal induced = %f ps/cm x border distance\n", mTimeSlope); - if (mTimeDelay > 0) + } + if (mTimeDelay > 0) { printf("Time delay for pad with signal induced = %f ps\n", mTimeDelay); - if (mTimeWalkeSlope > 0) + } + if (mTimeWalkeSlope > 0) { printf("Time walk ON = %f ps/cm\n", mTimeWalkeSlope); + } } //______________________________________________________________________ @@ -660,12 +679,15 @@ void Digitizer::test(const char* geo) h3->Fill(ndigits); hpadAll->Fill(xlocal, zlocal); for (Int_t k = 0; k < ndigits; k++) { - if (k == 0) + if (k == 0) { h->Fill(getTimeLastHit(k)); - if (k == 0) + } + if (k == 0) { h2->Fill(getTotLastHit(k)); - if (k == 0 && getXshift(k) == 0 && getZshift(k) == 0) + } + if (k == 0 && getXshift(k) == 0 && getZshift(k) == 0) { hTimeWalk->Fill(xlocal, zlocal * (0.5 - detCur[3]) * 2, getTimeLastHit(k)); + } hpad[getXshift(k) + 1][-getZshift(k) + 1]->Fill(getTimeLastHit(k)); hpadHit[getXshift(k) + 1][-getZshift(k) + 1]->Fill(xlocal, zlocal); @@ -704,8 +726,9 @@ void Digitizer::test(const char* geo) for (Int_t j = 0; j < 3; j++) { cpadH->cd(j * 3 + i + 1); hpadHit[i][j]->Draw("colz"); - if (j != 1) + if (j != 1) { hpadHit[i][j]->Scale(2); + } hpadEff[i][j]->Divide(hpadHit[i][j], hpadAll, 1, 1, "B"); hpadEff[i][j]->Draw("surf"); hpadEff[i][j]->SetMaximum(1); @@ -806,20 +829,23 @@ void Digitizer::fillOutputContainer(std::vector<Digit>& digits) } } - if (mContinuous) + if (mContinuous) { mMCTruthOutputContainerPerTimeFrame.push_back(*mMCTruthOutputContainer); + } mMCTruthContainerCurrent->clear(); // switch to next mStrip after flushing current readout window data mIcurrentReadoutWindow++; - if (mIcurrentReadoutWindow >= MAXWINDOWS) + if (mIcurrentReadoutWindow >= MAXWINDOWS) { mIcurrentReadoutWindow = 0; + } mStripsCurrent = &(mStrips[mIcurrentReadoutWindow]); mMCTruthContainerCurrent = &(mMCTruthContainer[mIcurrentReadoutWindow]); int k = mIcurrentReadoutWindow + 1; for (Int_t i = 0; i < MAXWINDOWS - 1; i++) { - if (k >= MAXWINDOWS) + if (k >= MAXWINDOWS) { k = 0; + } mMCTruthContainerNext[i] = &(mMCTruthContainer[k]); mStripsNext[i] = &(mStrips[k]); k++; @@ -830,9 +856,9 @@ void Digitizer::fillOutputContainer(std::vector<Digit>& digits) void Digitizer::flushOutputContainer(std::vector<Digit>& digits) { // flush all residual buffered data // TO be implemented - if (!mContinuous) + if (!mContinuous) { fillOutputContainer(digits); - else { + } else { for (Int_t i = 0; i < MAXWINDOWS; i++) { fillOutputContainer(digits); // fill all windows which are before (not yet stored) of the new current one checkIfReuseFutureDigits(); @@ -862,16 +888,17 @@ void Digitizer::checkIfReuseFutureDigits() int idigit = mFutureDigits.size() - 1; for (std::vector<Digit>::reverse_iterator digit = mFutureDigits.rbegin(); digit != mFutureDigits.rend(); ++digit) { - if (digit->getBC() > bclimit) + if (digit->getBC() > bclimit) { break; + } double timestamp = digit->getBC() * Geo::BC_TIME + digit->getTDC() * Geo::TDCBIN * 1E-3; // in ns int isnext = Int_t(timestamp * Geo::READOUTWINDOW_INV) - (mReadoutWindowCurrent + 1); // to be replaced with uncalibrated time int isIfOverlap = Int_t((timestamp - Geo::BC_TIME_INPS * Geo::OVERLAP_IN_BC * 1E-3) * Geo::READOUTWINDOW_INV) - (mReadoutWindowCurrent + 1); // to be replaced with uncalibrated time; - if (isnext == isIfOverlap) + if (isnext == isIfOverlap) { isIfOverlap = -1; - else if (isnext < 0 && isIfOverlap >= 0) { + } else if (isnext < 0 && isIfOverlap >= 0) { isnext = isIfOverlap; isIfOverlap = -1; } else if (isnext >= MAXWINDOWS && isIfOverlap < MAXWINDOWS) { diff --git a/Detectors/TOF/simulation/src/DigitizerTask.cxx b/Detectors/TOF/simulation/src/DigitizerTask.cxx index 3f1463256bb2c..80470b4e6a548 100644 --- a/Detectors/TOF/simulation/src/DigitizerTask.cxx +++ b/Detectors/TOF/simulation/src/DigitizerTask.cxx @@ -95,12 +95,14 @@ void DigitizerTask::Exec(Option_t* option) void DigitizerTask::FinishTask() { // finalize digitization, if needed, flash remaining digits - if (!mContinuous) + if (!mContinuous) { return; + } FairRootManager* mgr = FairRootManager::Instance(); mgr->SetLastFill(kTRUE); /// necessary, otherwise the data is not written out - if (mDigitsArray) + if (mDigitsArray) { mDigitsArray->clear(); + } // TODO: reenable this mMCTruthArray->getIndexedSize(); diff --git a/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx index 967353089b65d..efd9efc9198ef 100644 --- a/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedAnalysisTask.cxx @@ -77,8 +77,9 @@ void CompressedAnalysisTask::run(ProcessingContext& pc) /** loop over inputs routes **/ for (auto iit = pc.inputs().begin(), iend = pc.inputs().end(); iit != iend; ++iit) { - if (!iit.isValid()) + if (!iit.isValid()) { continue; + } /** loop over input parts **/ for (auto const& ref : iit) { diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index adf55a273bdf7..e2e3ab84b844b 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -43,8 +43,9 @@ void CompressedDecodingTask::init(InitContext& ic) mNoiseRate = ic.options().get<int>("noise-counts"); mRowFilter = ic.options().get<bool>("row-filter"); - if (mMaskNoise) + if (mMaskNoise) { mDecoder.maskNoiseRate(mNoiseRate); + } auto finishFunction = [this]() { LOG(INFO) << "CompressedDecoding finish"; @@ -62,8 +63,9 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) // send output message std::vector<o2::tof::Digit>* alldigits = mDecoder.getDigitPerTimeFrame(); std::vector<o2::tof::ReadoutWindowData>* row = mDecoder.getReadoutWindowData(); - if (mRowFilter) + if (mRowFilter) { row = mDecoder.getReadoutWindowDataFiltered(); + } ReadoutWindowData* last = nullptr; o2::InteractionRecord lastIR; @@ -136,8 +138,9 @@ void CompressedDecodingTask::run(ProcessingContext& pc) /** loop over inputs routes **/ for (auto iit = pc.inputs().begin(), iend = pc.inputs().end(); iit != iend; ++iit) { - if (!iit.isValid()) + if (!iit.isValid()) { continue; + } /** loop over input parts **/ for (auto const& ref : iit) { @@ -151,8 +154,9 @@ void CompressedDecodingTask::run(ProcessingContext& pc) } } - if ((mNCrateOpenTF == 72 || mConetMode) && mNCrateOpenTF == mNCrateCloseTF) + if ((mNCrateOpenTF == 72 || mConetMode) && mNCrateOpenTF == mNCrateCloseTF) { mHasToBePosted = true; + } if (mHasToBePosted) { postData(pc); @@ -195,83 +199,120 @@ void CompressedDecodingTask::trailerHandler(const CrateHeader_t* crateHeader, co int islot = (*val & 15); printf("DRM = %d (orbit = %d) slot = %d: \n", crateHeader->drmID, crateOrbit->orbitID, islot); if (islot == 1) { - if (o2::tof::diagnostic::DRM_HEADER_MISSING & *val) + if (o2::tof::diagnostic::DRM_HEADER_MISSING & *val) { printf("DRM_HEADER_MISSING\n"); - if (o2::tof::diagnostic::DRM_TRAILER_MISSING & *val) + } + if (o2::tof::diagnostic::DRM_TRAILER_MISSING & *val) { printf("DRM_TRAILER_MISSING\n"); - if (o2::tof::diagnostic::DRM_FEEID_MISMATCH & *val) + } + if (o2::tof::diagnostic::DRM_FEEID_MISMATCH & *val) { printf("DRM_FEEID_MISMATCH\n"); - if (o2::tof::diagnostic::DRM_ORBIT_MISMATCH & *val) + } + if (o2::tof::diagnostic::DRM_ORBIT_MISMATCH & *val) { printf("DRM_ORBIT_MISMATCH\n"); - if (o2::tof::diagnostic::DRM_CRC_MISMATCH & *val) + } + if (o2::tof::diagnostic::DRM_CRC_MISMATCH & *val) { printf("DRM_CRC_MISMATCH\n"); - if (o2::tof::diagnostic::DRM_ENAPARTMASK_DIFFER & *val) + } + if (o2::tof::diagnostic::DRM_ENAPARTMASK_DIFFER & *val) { printf("DRM_ENAPARTMASK_DIFFER\n"); - if (o2::tof::diagnostic::DRM_CLOCKSTATUS_WRONG & *val) + } + if (o2::tof::diagnostic::DRM_CLOCKSTATUS_WRONG & *val) { printf("DRM_CLOCKSTATUS_WRONG\n"); - if (o2::tof::diagnostic::DRM_FAULTSLOTMASK_NOTZERO & *val) + } + if (o2::tof::diagnostic::DRM_FAULTSLOTMASK_NOTZERO & *val) { printf("DRM_FAULTSLOTMASK_NOTZERO\n"); - if (o2::tof::diagnostic::DRM_READOUTTIMEOUT_NOTZERO & *val) + } + if (o2::tof::diagnostic::DRM_READOUTTIMEOUT_NOTZERO & *val) { printf("DRM_READOUTTIMEOUT_NOTZERO\n"); - if (o2::tof::diagnostic::DRM_EVENTWORDS_MISMATCH & *val) + } + if (o2::tof::diagnostic::DRM_EVENTWORDS_MISMATCH & *val) { printf("DRM_EVENTWORDS_MISMATCH\n"); - if (o2::tof::diagnostic::DRM_MAXDIAGNOSTIC_BIT & *val) + } + if (o2::tof::diagnostic::DRM_MAXDIAGNOSTIC_BIT & *val) { printf("DRM_MAXDIAGNOSTIC_BIT\n"); + } } else if (islot == 2) { - if (o2::tof::diagnostic::LTM_HEADER_MISSING & *val) + if (o2::tof::diagnostic::LTM_HEADER_MISSING & *val) { printf("LTM_HEADER_MISSING\n"); - if (o2::tof::diagnostic::LTM_TRAILER_MISSING & *val) + } + if (o2::tof::diagnostic::LTM_TRAILER_MISSING & *val) { printf("LTM_TRAILER_MISSING\n"); - if (o2::tof::diagnostic::LTM_HEADER_UNEXPECTED & *val) + } + if (o2::tof::diagnostic::LTM_HEADER_UNEXPECTED & *val) { printf("LTM_HEADER_UNEXPECTED\n"); - if (o2::tof::diagnostic::LTM_MAXDIAGNOSTIC_BIT & *val) + } + if (o2::tof::diagnostic::LTM_MAXDIAGNOSTIC_BIT & *val) { printf("LTM_MAXDIAGNOSTIC_BIT\n"); + } } else if (islot < 13) { - if (o2::tof::diagnostic::TRM_HEADER_MISSING & *val) + if (o2::tof::diagnostic::TRM_HEADER_MISSING & *val) { printf("TRM_HEADER_MISSING\n"); - if (o2::tof::diagnostic::TRM_TRAILER_MISSING & *val) + } + if (o2::tof::diagnostic::TRM_TRAILER_MISSING & *val) { printf("TRM_TRAILER_MISSING\n"); - if (o2::tof::diagnostic::TRM_CRC_MISMATCH & *val) + } + if (o2::tof::diagnostic::TRM_CRC_MISMATCH & *val) { printf("TRM_CRC_MISMATCH\n"); - if (o2::tof::diagnostic::TRM_HEADER_UNEXPECTED & *val) + } + if (o2::tof::diagnostic::TRM_HEADER_UNEXPECTED & *val) { printf("TRM_HEADER_UNEXPECTED\n"); - if (o2::tof::diagnostic::TRM_EVENTCNT_MISMATCH & *val) + } + if (o2::tof::diagnostic::TRM_EVENTCNT_MISMATCH & *val) { printf("TRM_EVENTCNT_MISMATCH\n"); - if (o2::tof::diagnostic::TRM_EMPTYBIT_NOTZERO & *val) + } + if (o2::tof::diagnostic::TRM_EMPTYBIT_NOTZERO & *val) { printf("TRM_EMPTYBIT_NOTZERO\n"); - if (o2::tof::diagnostic::TRM_LBIT_NOTZERO & *val) + } + if (o2::tof::diagnostic::TRM_LBIT_NOTZERO & *val) { printf("TRM_LBIT_NOTZERO\n"); - if (o2::tof::diagnostic::TRM_FAULTSLOTBIT_NOTZERO & *val) + } + if (o2::tof::diagnostic::TRM_FAULTSLOTBIT_NOTZERO & *val) { printf("TRM_FAULTSLOTBIT_NOTZERO\n"); - if (o2::tof::diagnostic::TRM_EVENTWORDS_MISMATCH & *val) + } + if (o2::tof::diagnostic::TRM_EVENTWORDS_MISMATCH & *val) { printf("TRM_EVENTWORDS_MISMATCH\n"); - if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE1 & *val) + } + if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE1 & *val) { printf("TRM_DIAGNOSTIC_SPARE1\n"); - if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE2 & *val) + } + if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE2 & *val) { printf("TRM_DIAGNOSTIC_SPARE2\n"); - if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE3 & *val) + } + if (o2::tof::diagnostic::TRM_DIAGNOSTIC_SPARE3 & *val) { printf("TRM_DIAGNOSTIC_SPARE3\n"); - if (o2::tof::diagnostic::TRM_MAXDIAGNOSTIC_BIT & *val) + } + if (o2::tof::diagnostic::TRM_MAXDIAGNOSTIC_BIT & *val) { printf("TRM_MAXDIAGNOSTIC_BIT\n"); + } - if (o2::tof::diagnostic::TRMCHAIN_HEADER_MISSING & *val) + if (o2::tof::diagnostic::TRMCHAIN_HEADER_MISSING & *val) { printf("TRMCHAIN_HEADER_MISSING\n"); - if (o2::tof::diagnostic::TRMCHAIN_TRAILER_MISSING & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_TRAILER_MISSING & *val) { printf("TRMCHAIN_TRAILER_MISSING\n"); - if (o2::tof::diagnostic::TRMCHAIN_STATUS_NOTZERO & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_STATUS_NOTZERO & *val) { printf("TRMCHAIN_STATUS_NOTZERO\n"); - if (o2::tof::diagnostic::TRMCHAIN_EVENTCNT_MISMATCH & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_EVENTCNT_MISMATCH & *val) { printf("TRMCHAIN_EVENTCNT_MISMATCH\n"); - if (o2::tof::diagnostic::TRMCHAIN_TDCERROR_DETECTED & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_TDCERROR_DETECTED & *val) { printf("TRMCHAIN_TDCERROR_DETECTED\n"); - if (o2::tof::diagnostic::TRMCHAIN_BUNCHCNT_MISMATCH & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_BUNCHCNT_MISMATCH & *val) { printf("TRMCHAIN_BUNCHCNT_MISMATCH\n"); - if (o2::tof::diagnostic::TRMCHAIN_DIAGNOSTIC_SPARE1 & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_DIAGNOSTIC_SPARE1 & *val) { printf("TRMCHAIN_DIAGNOSTIC_SPARE1\n"); - if (o2::tof::diagnostic::TRMCHAIN_DIAGNOSTIC_SPARE2 & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_DIAGNOSTIC_SPARE2 & *val) { printf("TRMCHAIN_DIAGNOSTIC_SPARE2\n"); - if (o2::tof::diagnostic::TRMCHAIN_MAXDIAGNOSTIC_BIT & *val) + } + if (o2::tof::diagnostic::TRMCHAIN_MAXDIAGNOSTIC_BIT & *val) { printf("TRMCHAIN_MAXDIAGNOSTIC_BIT\n"); + } } printf("------\n"); } diff --git a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx index 07b23eb2131ae..5c8629363cf3c 100644 --- a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx @@ -65,10 +65,12 @@ void CompressedInspectorTask<RDH>::init(InitContext& ic) auto finishFunction = [this]() { LOG(INFO) << "CompressedInspector finish"; - for (auto& histo : mHistos1D) + for (auto& histo : mHistos1D) { histo.second->Write(); - for (auto& histo : mHistos2D) + } + for (auto& histo : mHistos2D) { histo.second->Write(); + } mFile->Close(); }; ic.services().get<CallbackService>().set(CallbackService::Id::Stop, finishFunction); @@ -87,8 +89,9 @@ void CompressedInspectorTask<RDH>::run(ProcessingContext& pc) /** loop over inputs routes **/ for (auto iit = pc.inputs().begin(), iend = pc.inputs().end(); iit != iend; ++iit) { - if (!iit.isValid()) + if (!iit.isValid()) { continue; + } /** loop over input parts **/ for (auto const& ref : iit) { @@ -107,9 +110,11 @@ void CompressedInspectorTask<RDH>::run(ProcessingContext& pc) template <typename RDH> void CompressedInspectorTask<RDH>::headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) { - for (int ibit = 0; ibit < 11; ++ibit) - if (crateHeader->slotPartMask & (1 << ibit)) + for (int ibit = 0; ibit < 11; ++ibit) { + if (crateHeader->slotPartMask & (1 << ibit)) { mHistos2D["slotPartMask"]->Fill(crateHeader->drmID, ibit + 2); + } + } }; template <typename RDH> @@ -155,8 +160,9 @@ void CompressedInspectorTask<RDH>::trailerHandler(const CrateHeader_t* crateHead nError++; mHistos2D["error"]->Fill(error->slotID + 0.5 * error->chain, error->tdcID); for (int ibit = 0; ibit < 15; ++ibit) { - if (error->errorFlags & (1 << ibit)) + if (error->errorFlags & (1 << ibit)) { mHistos1D["errorBit"]->Fill(ibit); + } } } } diff --git a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx index 6684255d03898..66081b514dff6 100644 --- a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx @@ -64,8 +64,9 @@ void DigitReader::run(ProcessingContext& pc) pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, mDigits); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, mRow); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, mPatterns); - if (mUseMC) + if (mUseMC) { pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITSMCTR", 0, Lifetime::Timeframe}, mLabels); + } static o2::parameters::GRPObject::ROMode roMode = o2::parameters::GRPObject::CONTINUOUS; diff --git a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx index eb1149d23fe85..550e56690aacc 100644 --- a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx @@ -121,8 +121,9 @@ class TOFDPLClustererTask mReader.setDigitArray(&digitsRO); if (mUseMC) { mClusterer.process(mReader, mClustersArray, &(labelvector->at(i))); - } else + } else { mClusterer.process(mReader, mClustersArray, nullptr); + } } LOG(INFO) << "TOF CLUSTERER : TRANSFORMED " << digits.size() << " DIGITS TO " << mClustersArray.size() << " CLUSTERS"; @@ -130,8 +131,9 @@ class TOFDPLClustererTask // send clusters pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CLUSTERS", 0, Lifetime::Timeframe}, mClustersArray); // send labels - if (mUseMC) + if (mUseMC) { pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CLUSTERSMCTR", 0, Lifetime::Timeframe}, mClsLabels); + } mTimer.Stop(); } diff --git a/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx index 6a503127fd47c..832e18b4995f2 100644 --- a/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFRawWriterSpec.cxx @@ -76,8 +76,9 @@ void RawWriter::run(ProcessingContext& pc) std::vector<std::vector<o2::tof::Digit>> digitWindows; for (int i = 0; i < nwindow; i += nwindowperorbit) { // encode 3 tof windows (1 orbit) - if (verbosity) + if (verbosity) { printf("----------\nwindow = %d - %d\n----------\n", i, i + nwindowperorbit - 1); + } digitWindows.clear(); @@ -85,8 +86,9 @@ void RawWriter::run(ProcessingContext& pc) for (int j = i; j < i + nwindowperorbit; j++) { if (j < nwindow) { digitRO.clear(); - for (int id = 0; id < row->at(j).size(); id++) + for (int id = 0; id < row->at(j).size(); id++) { digitRO.push_back((*digits)[row->at(j).first() + id]); + } digitWindows.push_back(digitRO); } else { digitWindows.push_back(emptyWindow); From 2ad85f167ddb635e50ce7bad25741ca739168392 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Fri, 2 Oct 2020 16:59:38 +0200 Subject: [PATCH 1184/1751] Improve MID raw data encoding - use framework as much as possible (e.g. implementing emptyHBFMethod) - flush the delayed regional board response in the correct chronological order - fix bug occurring when data are in orbit 0 --- .../include/MIDRaw/ColumnDataToLocalBoard.h | 5 + .../MUON/MID/Raw/include/MIDRaw/Encoder.h | 20 ++- .../Raw/include/MIDRaw/GBTUserLogicEncoder.h | 35 ++--- .../MID/Raw/src/ColumnDataToLocalBoard.cxx | 18 ++- Detectors/MUON/MID/Raw/src/Encoder.cxx | 94 ++++++++----- .../MUON/MID/Raw/src/GBTUserLogicEncoder.cxx | 128 +++++++----------- Detectors/MUON/MID/Raw/test/testRaw.cxx | 31 +++-- 7 files changed, 183 insertions(+), 148 deletions(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h b/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h index 7e653b96f9568..c2ad23e532fcf 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h @@ -34,13 +34,18 @@ class ColumnDataToLocalBoard void process(gsl::span<const ColumnData> data); /// Gets the output data per GBT link const std::unordered_map<uint16_t, std::vector<LocalBoardRO>> getData() { return mGBTMap; } + /// Sets debug mode + void setDebugMode(bool debugMode = true) { mDebugMode = debugMode; } private: + bool keepBoard(const LocalBoardRO& loc) const; std::unordered_map<uint16_t, LocalBoardRO> mLocalBoardsMap{}; /// Map of data per board std::unordered_map<uint16_t, std::vector<LocalBoardRO>> mGBTMap{}; /// Map of data per GBT link CrateMapper mCrateMapper{}; /// Crate mapper Mapping mMapping{}; /// Segmentation + bool mDebugMode{false}; /// Debug mode (no zero suppression) }; + } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h index c3ca341cd32a5..871b12546a0d2 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/Encoder.h @@ -18,6 +18,7 @@ #include <cstdint> #include <array> #include <map> +#include <vector> #include <gsl/gsl> #include "CommonDataFormat/InteractionRecord.h" #include "DetectorsRaw/RawFileWriter.h" @@ -28,6 +29,8 @@ #include "MIDRaw/GBTUserLogicEncoder.h" #include "MIDRaw/LocalBoardRO.h" +class RDHAny; + namespace o2 { namespace mid @@ -35,7 +38,7 @@ namespace mid class Encoder { public: - void init(const char* filename, bool perLink = false, int verbosity = 0); + void init(const char* filename, bool perLink = false, int verbosity = 0, bool debugMode = false); void process(gsl::span<const ColumnData> data, const InteractionRecord& ir, EventType eventType = EventType::Standard); /// Sets the maximum size of the superpage void setSuperpageSize(int maxSize) { mRawWriter.setSuperPageSize(maxSize); } @@ -44,9 +47,14 @@ class Encoder auto& getWriter() { return mRawWriter; } + void emptyHBFMethod(const o2::header::RDHAny* rdh, std::vector<char>& toAdd) const; + private: - void flush(uint16_t feeId, const InteractionRecord& ir); - void hbTrigger(const InteractionRecord& ir); + void completeWord(std::vector<char>& buffer); + void writePayload(uint16_t feeId, const InteractionRecord& ir); + void onOrbitChange(uint32_t orbit); + // Returns the interaction record expected for the orbit trigger + inline InteractionRecord getOrbitIR(uint32_t orbit) const { return {o2::constants::lhc::LHCMaxBunches - 1, orbit}; } o2::raw::RawFileWriter mRawWriter{o2::header::gDataOriginMID}; /// Raw file writer @@ -55,8 +63,10 @@ class Encoder FEEIdConfig mFEEIdConfig{}; /// Crate FEEId mapper InteractionRecord mLastIR{}; /// Last interaction record - std::array<GBTUserLogicEncoder, crateparams::sNGBTs> mGBTEncoders{}; /// Array of encoders per link - std::array<uint32_t, crateparams::sNGBTs> mGBTIds{}; /// Array of GBT Ids + std::array<GBTUserLogicEncoder, crateparams::sNGBTs> mGBTEncoders{}; /// Array of encoders per link + std::array<std::vector<char>, crateparams::sNGBTs> mOrbitResponse{}; /// Response to orbit trigger + std::array<std::vector<char>, crateparams::sNGBTs> mOrbitResponseWord{}; /// CRU word for response to orbit trigger + std::array<uint32_t, crateparams::sNGBTs> mGBTIds{}; /// Array of GBT Ids }; } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h index e853b759428ec..aee2f00a2a278 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicEncoder.h @@ -16,8 +16,9 @@ #define O2_MID_GBTUSERLOGICENCODER_H #include <cstdint> -#include <vector> +#include <map> #include <gsl/gsl> +#include "CommonDataFormat/InteractionRecord.h" #include "DataFormatsMID/ROFRecord.h" #include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/LocalBoardRO.h" @@ -29,14 +30,13 @@ namespace mid class GBTUserLogicEncoder { public: - void process(gsl::span<const LocalBoardRO> data, const uint16_t bc, uint8_t triggerWord = 0); - void processTrigger(uint16_t bc, uint8_t triggerWord); + void process(gsl::span<const LocalBoardRO> data, const InteractionRecord& ir); + void processTrigger(const InteractionRecord& ir, uint8_t triggerWord); - /// Gets the buffer - const std::vector<uint8_t>& getBuffer() { return mBytes; } + void flush(std::vector<char>& buffer, const InteractionRecord& ir); - /// Gets the buffer size in bytes - size_t getBufferSize() const { return mBytes.size(); } + // Encoder has no data left + bool isEmpty() { return mBoards.empty(); } /// Sets the mask void setMask(uint8_t mask) { mMask = mask; } @@ -44,26 +44,17 @@ class GBTUserLogicEncoder /// Sets the feeID void setFeeId(uint16_t feeId) { mFeeId = feeId; } - /// Clears the buffer - void clear() { mBytes.clear(); } - /// Sets the delay in the electronics void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } private: - /// Adds the board id and the fired chambers - inline void addIdAndChambers(uint8_t id, uint8_t firedChambers) { mBytes.emplace_back((id << 4) | firedChambers); } - - void addBoard(uint8_t statusWord, uint8_t triggerWord, uint16_t localClock, uint8_t id, uint8_t firedChambers); - void addLoc(const LocalBoardRO& loc, uint16_t bc, uint8_t triggerWord); - void addReg(uint16_t bc, uint8_t triggerWord, uint8_t id, uint8_t firedChambers); - void addShort(uint16_t shortWord); - bool checkAndAdd(gsl::span<const LocalBoardRO> data, uint16_t bc, uint8_t triggerWord); + void addRegionalBoards(uint8_t activeBoards, InteractionRecord ir); + void addShort(std::vector<char>& buffer, uint16_t shortWord) const; - std::vector<uint8_t> mBytes{}; /// Vector with encoded information - uint16_t mFeeId{0}; /// FEE ID - uint8_t mMask{0xFF}; /// GBT mask - ElectronicsDelay mElectronicsDelay; /// Delays in the electronics + std::map<InteractionRecord, std::vector<LocalBoardRO>> mBoards{}; /// Vector with boards + uint16_t mFeeId{0}; /// FEE ID + uint8_t mMask{0xFF}; /// GBT mask + ElectronicsDelay mElectronicsDelay; /// Delays in the electronics }; } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx b/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx index 7c85f66e197c6..69b67e7a78457 100644 --- a/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx +++ b/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx @@ -23,6 +23,16 @@ namespace o2 namespace mid { +bool ColumnDataToLocalBoard::keepBoard(const LocalBoardRO& loc) const +{ + for (int ich = 0; ich < 4; ++ich) { + if (loc.patternsBP[ich] && loc.patternsNBP[ich]) { + return true; + } + } + return false; +} + void ColumnDataToLocalBoard::process(gsl::span<const ColumnData> data) { /// Converts incoming data to FEE format @@ -48,9 +58,11 @@ void ColumnDataToLocalBoard::process(gsl::span<const ColumnData> data) // Then group the boards belonging to the same GBT link for (auto& item : mLocalBoardsMap) { - auto crateId = crateparams::getCrateId(item.first); - auto feeId = crateparams::makeROId(crateId, crateparams::getGBTIdFromBoardInCrate(item.second.boardId)); - mGBTMap[feeId].emplace_back(item.second); + if (mDebugMode || keepBoard(item.second)) { + auto crateId = crateparams::getCrateId(item.first); + auto feeId = crateparams::makeROId(crateId, crateparams::getGBTIdFromBoardInCrate(item.second.boardId)); + mGBTMap[feeId].emplace_back(item.second); + } } } diff --git a/Detectors/MUON/MID/Raw/src/Encoder.cxx b/Detectors/MUON/MID/Raw/src/Encoder.cxx index 6e1e3eb0d1d35..01ceda0a70737 100644 --- a/Detectors/MUON/MID/Raw/src/Encoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Encoder.cxx @@ -25,7 +25,7 @@ namespace o2 namespace mid { -void Encoder::init(const char* filename, bool perLink, int verbosity) +void Encoder::init(const char* filename, bool perLink, int verbosity, bool debugMode) { /// Initializes links @@ -36,57 +36,82 @@ void Encoder::init(const char* filename, bool perLink, int verbosity) int lcnt = 0; for (auto& gbtId : gbtIds) { auto feeId = mFEEIdConfig.getFeeId(gbtId); - mRawWriter.registerLink(feeId, mFEEIdConfig.getCRUId(gbtId), mFEEIdConfig.getLinkId(gbtId), mFEEIdConfig.getEndPointId(gbtId), - perLink ? fmt::format("{:s}_L{:d}.raw", filename, lcnt) : fmt::format("{:s}.raw", filename)); + mRawWriter.registerLink(feeId, mFEEIdConfig.getCRUId(gbtId), mFEEIdConfig.getLinkId(gbtId), mFEEIdConfig.getEndPointId(gbtId), perLink ? fmt::format("{:s}_L{:d}.raw", filename, lcnt) : fmt::format("{:s}.raw", filename)); mGBTEncoders[feeId].setFeeId(feeId); mGBTEncoders[feeId].setMask(masks.getMask(feeId)); mGBTIds[feeId] = gbtId; lcnt++; + + // Initializes the trigger response to be added to the empty HBs + auto ir = getOrbitIR(0); + mGBTEncoders[feeId].processTrigger(ir, raw::sORB); + mGBTEncoders[feeId].flush(mOrbitResponse[feeId], ir); + mOrbitResponseWord[feeId] = mOrbitResponse[feeId]; + completeWord(mOrbitResponseWord[feeId]); } + + mRawWriter.setEmptyPageCallBack(this); + + mConverter.setDebugMode(debugMode); } -void Encoder::hbTrigger(const InteractionRecord& ir) +void Encoder::emptyHBFMethod(const o2::header::RDHAny* rdh, std::vector<char>& toAdd) const { - /// Processes HB trigger - if (mLastIR.isDummy()) { - mLastIR = o2::raw::HBFUtils::Instance().getFirstIR(); - } + /// Response to orbit triggers in empty HBFs + auto feeId = o2::raw::RDHUtils::getFEEID(rdh); + toAdd = mOrbitResponseWord[feeId]; +} - std::vector<InteractionRecord> HBIRVec; - o2::raw::HBFUtils::Instance().fillHBIRvector(HBIRVec, mLastIR + 1, ir); - for (auto& hbIr : HBIRVec) { - for (uint16_t feeId = 0; feeId < crateparams::sNGBTs; ++feeId) { - flush(feeId, mLastIR); - mGBTEncoders[feeId].processTrigger(o2::constants::lhc::LHCMaxBunches, raw::sORB); +void Encoder::onOrbitChange(uint32_t orbit) +{ + /// Performs action when orbit changes + auto ir = getOrbitIR(orbit); + for (uint16_t feeId = 0; feeId < crateparams::sNGBTs; ++feeId) { + // Write the data corresponding to the previous orbit + if (!mGBTEncoders[feeId].isEmpty()) { + writePayload(feeId, ir); } - mLastIR = hbIr; } - mLastIR = ir; } -void Encoder::flush(uint16_t feeId, const InteractionRecord& ir) +void Encoder::completeWord(std::vector<char>& buffer) { - /// Flushes data - - if (mGBTEncoders[feeId].getBufferSize() == 0) { - return; + /// Completes the buffer with zeros to reach the expected CRU word size + size_t dataSize = buffer.size(); + size_t cruWord = 2 * o2::raw::RDHUtils::GBTWord; + size_t modulo = dataSize % cruWord; + if (modulo) { + dataSize += cruWord - modulo; + buffer.resize(dataSize, static_cast<char>(0)); } - size_t dataSize = mGBTEncoders[feeId].getBufferSize(); - size_t resto = dataSize % o2::raw::RDHUtils::GBTWord; - if (dataSize % o2::raw::RDHUtils::GBTWord) { - dataSize += o2::raw::RDHUtils::GBTWord - resto; - } - std::vector<char> buf(dataSize); - memcpy(buf.data(), mGBTEncoders[feeId].getBuffer().data(), mGBTEncoders[feeId].getBufferSize()); +} + +void Encoder::writePayload(uint16_t feeId, const InteractionRecord& ir) +{ + /// Writes data + + // The first part of data is the answer to the orbit trigger + std::vector<char> buf = mOrbitResponse[feeId]; + // Then we flush the received data + mGBTEncoders[feeId].flush(buf, ir); + completeWord(buf); mRawWriter.addData(feeId, mFEEIdConfig.getCRUId(mGBTIds[feeId]), mFEEIdConfig.getLinkId(mGBTIds[feeId]), mFEEIdConfig.getEndPointId(mGBTIds[feeId]), ir, buf); - mGBTEncoders[feeId].clear(); } void Encoder::finalize(bool closeFile) { - /// Finish the flushing and closes the + /// Writes remaining data and closes the file + auto ir = getOrbitIR(mLastIR.orbit); for (uint16_t feeId = 0; feeId < crateparams::sNGBTs; ++feeId) { - flush(feeId, mLastIR); + // Write the last payload + writePayload(feeId, ir); + if (!mGBTEncoders[feeId].isEmpty()) { + // Since the regional response comes after few clocks, + // we might have the corresponding regional cards in the next orbit. + // If this is the case, we flush all data of the next orbit + ++ir.orbit; + writePayload(feeId, ir); + } } if (closeFile) { mRawWriter.close(); @@ -96,13 +121,16 @@ void Encoder::finalize(bool closeFile) void Encoder::process(gsl::span<const ColumnData> data, const InteractionRecord& ir, EventType eventType) { /// Encodes data - hbTrigger(ir); + if (ir.orbit != mLastIR.orbit) { + onOrbitChange(mLastIR.orbit); + } mConverter.process(data); for (auto& item : mConverter.getData()) { - mGBTEncoders[item.first].process(item.second, ir.bc); + mGBTEncoders[item.first].process(item.second, ir); } + mLastIR = ir; } } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx b/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx index 8e7259764d32a..36b00367256f1 100644 --- a/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx @@ -22,115 +22,89 @@ namespace o2 namespace mid { -void GBTUserLogicEncoder::addShort(uint16_t shortWord) +void GBTUserLogicEncoder::addShort(std::vector<char>& buffer, uint16_t shortWord) const { /// Adds a 16 bits word - mBytes.emplace_back((shortWord >> 8) & 0xFF); - mBytes.emplace_back(shortWord & 0xFF); + buffer.emplace_back((shortWord >> 8) & 0xFF); + buffer.emplace_back(shortWord & 0xFF); } -void GBTUserLogicEncoder::addBoard(uint8_t statusWord, uint8_t triggerWord, uint16_t localClock, uint8_t id, uint8_t firedChambers) -{ - /// Adds the board information - mBytes.emplace_back(statusWord); - mBytes.emplace_back(triggerWord); - addShort(localClock); - addIdAndChambers(id, firedChambers); -} - -void GBTUserLogicEncoder::processTrigger(const uint16_t bc, uint8_t triggerWord) +void GBTUserLogicEncoder::processTrigger(const InteractionRecord& ir, uint8_t triggerWord) { /// Adds the information in triggered mode - for (int ireg = 0; ireg < 2; ++ireg) { + auto& vec = mBoards[ir]; + for (uint8_t ireg = 0; ireg < 2; ++ireg) { uint8_t firedLoc = (mMask >> (4 * ireg)) & 0xF; - addReg(bc, triggerWord, ireg, firedLoc); + vec.push_back({raw::sSTARTBIT, triggerWord, ireg, firedLoc}); } - for (int iloc = 0; iloc < 8; ++iloc) { + for (uint8_t iloc = 0; iloc < 8; ++iloc) { if (mMask & (1 << iloc)) { - addBoard(raw::sSTARTBIT | raw::sCARDTYPE, triggerWord, bc, iloc + 8 * crateparams::getGBTIdInCrate(mFeeId), 0); + vec.push_back({raw::sSTARTBIT | raw::sCARDTYPE, triggerWord, static_cast<uint8_t>(iloc + 8 * crateparams::getGBTIdInCrate(mFeeId)), 0}); if (triggerWord & (raw::sSOX | raw::sEOX)) { /// Write masks for (int ich = 0; ich < 4; ++ich) { - addShort(0xFFFF); // BP - addShort(0xFFFF); // NBP + vec.back().patternsBP[ich] = 0xFFFF; + vec.back().patternsNBP[ich] = 0xFFFF; } } } } } -bool GBTUserLogicEncoder::checkAndAdd(gsl::span<const LocalBoardRO> data, const uint16_t bc, uint8_t triggerWord) +void GBTUserLogicEncoder::addRegionalBoards(uint8_t activeBoards, InteractionRecord ir) { - /// Checks the local boards and write the regional and local output if needed - uint8_t activeBoards = 0; - for (auto& loc : data) { - int regId = loc.boardId / 4; - for (int ich = 0; ich < 4; ++ich) { - if (loc.patternsBP[ich] && loc.patternsNBP[ich]) { - activeBoards |= (1 << (loc.boardId % 8)); - } - } - } - for (int ireg = 0; ireg < 2; ++ireg) { + /// Adds the regional board information + ir += mElectronicsDelay.BCToLocal + mElectronicsDelay.regToLocal; + auto& vec = mBoards[ir]; + for (uint8_t ireg = 0; ireg < 2; ++ireg) { uint8_t firedLoc = (activeBoards >> (4 * ireg)) & 0xF; if (firedLoc > 0) { - addReg(bc, triggerWord, ireg, firedLoc); + vec.push_back({raw::sSTARTBIT, 0, ireg, firedLoc}); } } - for (auto& loc : data) { - if (activeBoards & (1 << (loc.boardId % 8))) { - addLoc(loc, bc, triggerWord); - } - } - return (activeBoards > 0); -} - -void GBTUserLogicEncoder::addReg(uint16_t bc, uint8_t triggerWord, uint8_t id, uint8_t firedChambers) -{ - /// Adds the regional board information - mBytes.emplace_back(raw::sSTARTBIT); - mBytes.emplace_back(triggerWord); - uint16_t localClock = bc; - if (triggerWord == 0) { - localClock += mElectronicsDelay.BCToLocal + mElectronicsDelay.regToLocal; - } - addShort(localClock); - addIdAndChambers(id + 8 * crateparams::getGBTIdInCrate(mFeeId), firedChambers); } -void GBTUserLogicEncoder::addLoc(const LocalBoardRO& loc, uint16_t bc, uint8_t triggerWord) +void GBTUserLogicEncoder::process(gsl::span<const LocalBoardRO> data, const InteractionRecord& ir) { - /// Adds the local board information - - mBytes.emplace_back(loc.statusWord); - mBytes.emplace_back(triggerWord ? triggerWord : loc.triggerWord); - - uint16_t localClock = bc; - if (loc.triggerWord == 0) { - localClock += mElectronicsDelay.BCToLocal; - } - addShort(localClock); - - addIdAndChambers(loc.boardId, loc.firedChambers); - for (int ich = 4; ich >= 0; --ich) { - if (loc.firedChambers & (1 << ich)) { - addShort(loc.patternsBP[ich]); - addShort(loc.patternsNBP[ich]); + /// Encode data + auto& vec = mBoards[ir]; + uint8_t activeBoards = 0; + for (auto& loc : data) { + for (int ich = 0; ich < 4; ++ich) { + if (loc.patternsBP[ich] && loc.patternsNBP[ich]) { + activeBoards |= (1 << (loc.boardId % 8)); + } } + vec.emplace_back(loc); } + addRegionalBoards(activeBoards, ir); } -void GBTUserLogicEncoder::process(gsl::span<const LocalBoardRO> data, const uint16_t bc, uint8_t triggerWord) +void GBTUserLogicEncoder::flush(std::vector<char>& buffer, const InteractionRecord& ir) { - /// Encode data - if (triggerWord != 0) { - processTrigger(bc, triggerWord); - } - checkAndAdd(data, bc, triggerWord); - if (triggerWord == raw::sCALIBRATE) { - // Add FET - checkAndAdd(data, bc + mElectronicsDelay.calibToFET, 0); + /// Flush buffer + std::map<InteractionRecord, std::vector<LocalBoardRO>> tmpBoards; + for (auto& item : mBoards) { + if (item.first <= ir) { + for (auto& loc : item.second) { + buffer.emplace_back(loc.statusWord); + buffer.emplace_back(loc.triggerWord); + addShort(buffer, item.first.bc); + buffer.emplace_back((loc.boardId << 4) | loc.firedChambers); + if (raw::isLoc(loc.statusWord)) { + for (int ich = 4; ich >= 0; --ich) { + if (loc.firedChambers & (1 << ich)) { + addShort(buffer, loc.patternsBP[ich]); + addShort(buffer, loc.patternsNBP[ich]); + } + } + } + } + } else { + tmpBoards[item.first] = item.second; + } } + mBoards.swap(tmpBoards); } } // namespace mid diff --git a/Detectors/MUON/MID/Raw/test/testRaw.cxx b/Detectors/MUON/MID/Raw/test/testRaw.cxx index 71682b205bb55..9dc458ac0140d 100644 --- a/Detectors/MUON/MID/Raw/test/testRaw.cxx +++ b/Detectors/MUON/MID/Raw/test/testRaw.cxx @@ -91,13 +91,14 @@ std::tuple<std::vector<o2::mid::ColumnData>, std::vector<o2::mid::ROFRecord>> en std::string tmpFilename = tmpFilename0 + ".raw"; o2::mid::Encoder encoder; encoder.init(tmpFilename0.c_str()); + std::string tmpConfigFilename = "tmp_MIDConfig.cfg"; + encoder.getWriter().writeConfFile("MID", "RAWDATA", tmpConfigFilename.c_str(), false); for (auto& item : inData) { encoder.process(item.second, item.first, inEventType); } encoder.finalize(); - o2::raw::RawFileReader rawReader; - rawReader.addFile(tmpFilename.c_str()); + o2::raw::RawFileReader rawReader(tmpConfigFilename.c_str()); rawReader.init(); std::vector<char> buffer; for (size_t itf = 0; itf < rawReader.getNTimeFrames(); ++itf) { @@ -116,6 +117,7 @@ std::tuple<std::vector<o2::mid::ColumnData>, std::vector<o2::mid::ROFRecord>> en fair::Logger::SetConsoleSeverity(severity); std::remove(tmpFilename.c_str()); + std::remove(tmpConfigFilename.c_str()); o2::mid::Decoder<o2::mid::GBTUserLogicDecoder> decoder; gsl::span<const uint8_t> data(reinterpret_cast<uint8_t*>(buffer.data()), buffer.size()); @@ -136,12 +138,17 @@ BOOST_AUTO_TEST_CASE(ColumnDataConverter) ir.bc = 200; inData[ir].emplace_back(getColData(3, 4, 0xFF00, 0xFF)); - inData[ir].emplace_back(getColData(12, 4, 0xFF)); + inData[ir].emplace_back(getColData(12, 4, 0, 0, 0xFF)); + + ir.bc = 400; + inData[ir].emplace_back(getColData(5, 1, 0xFF00, 0xFF)); + inData[ir].emplace_back(getColData(14, 1, 0, 0, 0, 0xFF)); std::vector<o2::mid::ROFRecord> rofs; std::vector<o2::mid::LocalBoardRO> outData; auto inEventType = o2::mid::EventType::Standard; o2::mid::ColumnDataToLocalBoard converter; + converter.setDebugMode(true); for (auto& item : inData) { converter.process(item.second); auto firstEntry = outData.size(); @@ -196,16 +203,20 @@ BOOST_AUTO_TEST_CASE(GBTUserLogicDecoder) o2::mid::GBTUserLogicEncoder encoder; encoder.setFeeId(feeId); for (auto& item : inData) { - encoder.process(item.second, item.first); + encoder.process(item.second, o2::InteractionRecord(item.first, 0)); } + std::vector<char> buf; + encoder.flush(buf, o2::InteractionRecord()); o2::header::RAWDataHeader rdh; - auto memSize = encoder.getBufferSize() + 64; + auto memSize = buf.size() + 64; rdh.word1 |= (memSize | (memSize << 16)); // Sets the feeId rdh.word0 |= ((5 * 2) << 16); o2::mid::GBTUserLogicDecoder decoder; decoder.init(feeId); - decoder.process(encoder.getBuffer(), rdh); + std::vector<uint8_t> convertedBuffer(buf.size()); + memcpy(convertedBuffer.data(), buf.data(), buf.size()); + decoder.process(convertedBuffer, rdh); BOOST_REQUIRE(decoder.getROFRecords().size() == inData.size()); auto inItMap = inData.begin(); for (auto rofIt = decoder.getROFRecords().begin(); rofIt != decoder.getROFRecords().end(); ++rofIt) { @@ -233,7 +244,7 @@ BOOST_AUTO_TEST_CASE(SmallSample) std::map<o2::InteractionRecord, std::vector<o2::mid::ColumnData>> inData; // Small standard event - o2::InteractionRecord ir(100, 1); + o2::InteractionRecord ir(100, 0); // Crate 5 link 0 inData[ir].emplace_back(getColData(2, 4, 0x1, 0xFFFF)); @@ -243,11 +254,15 @@ BOOST_AUTO_TEST_CASE(SmallSample) inData[ir].emplace_back(getColData(5, 1, 0xFFFF, 0, 0xF, 0xF0)); // Crate 10 link 1 and crate 11 link 1 inData[ir].emplace_back(getColData(41, 2, 0xFF0F, 0, 0xF0FF, 0xF)); - ir.bc = 200; + ir.bc = 0xde6; ir.orbit = 2; // Crate 12 link 1 inData[ir].emplace_back(getColData(70, 3, 0xFF00, 0xFF)); + ir.bc = 0xdea; + ir.orbit = 3; + inData[ir].emplace_back(getColData(70, 3, 0xFF00, 0xFF)); + auto [data, rofs] = encodeDecode(inData); doTest(inData, rofs, data); From c559e7374ab679bd54cfc8fe3d1f36c3289cb7c2 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Wed, 28 Oct 2020 10:29:00 +0100 Subject: [PATCH 1185/1751] Use correct detector in function name --- .../MUON/MID/CTF/include/MIDCTF/CTFCoder.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h b/Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h index ed5e5098dffa7..da7a2cd56ba9a 100644 --- a/Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h +++ b/Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h @@ -107,16 +107,16 @@ void CTFCoder::decode(const CTF::base& ec, VROF& rofVec, VCOL& colVec) std::vector<uint32_t> orbitInc; std::vector<uint8_t> evType, deId, colId; -#define DECODEFT0(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) +#define DECODEMID(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) // clang-format off - DECODEFT0(bcInc, CTF::BLC_bcIncROF); - DECODEFT0(orbitInc, CTF::BLC_orbitIncROF); - DECODEFT0(entries, CTF::BLC_entriesROF); - DECODEFT0(evType, CTF::BLC_evtypeROF); - - DECODEFT0(pattern, CTF::BLC_pattern); - DECODEFT0(deId, CTF::BLC_deId); - DECODEFT0(colId, CTF::BLC_colId); + DECODEMID(bcInc, CTF::BLC_bcIncROF); + DECODEMID(orbitInc, CTF::BLC_orbitIncROF); + DECODEMID(entries, CTF::BLC_entriesROF); + DECODEMID(evType, CTF::BLC_evtypeROF); + + DECODEMID(pattern, CTF::BLC_pattern); + DECODEMID(deId, CTF::BLC_deId); + DECODEMID(colId, CTF::BLC_colId); // clang-format on // rofVec.clear(); From 490daac6196b6d96fc71c159655e3862f40778bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= <mario.kruger@cern.ch> Date: Mon, 2 Nov 2020 17:23:16 +0100 Subject: [PATCH 1186/1751] HistogramRegistry: remove fillWeight --- Analysis/Tasks/trackqa.cxx | 2 + Analysis/Tutorials/src/histogramRegistry.cxx | 10 ++-- .../include/Framework/HistogramRegistry.h | 60 ++++++------------- 3 files changed, 26 insertions(+), 46 deletions(-) diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index ae4b64cd5275e..6fa1fbc1a935f 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -82,6 +82,8 @@ struct TrackQATask { histos.add("TPC/tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", kTH1D, {{100, 0., 1.}}); histos.add("TPC/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {{120, 0.0, 1.2}}); histos.add("TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {{100, 0, 10}}); + + histos.print(); } void process(soa::Filtered<soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection>>::iterator const& track) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index e8f29677eeaed..fdecd0a8596c3 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -103,11 +103,11 @@ struct CTask { registry.fill<Pt, Eta, RawPhi>("2d-profile", tracks, eta > -0.5f); // fill 4d histogram with weight (column X) - registry.fillWeight<Pt, Eta, RawPhi, Z, X>("4d-weight", tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi, Z, X>("4d-weight", tracks, eta > 0.f); - registry.fillWeight<Pt, Eta, RawPhi>("2d-weight", tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi>("2d-weight", tracks, eta > 0.f); - registry.fillWeight<Pt, Eta, RawPhi>("1d-profile-weight", tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi>("1d-profile-weight", tracks, eta > 0.f); for (auto& track : tracks) { registry.fill("2d", track.eta(), track.pt()); @@ -117,9 +117,9 @@ struct CTask { registry.fill("3d-profile", track.pt(), track.eta(), track.phi(), track.snp()); // fill 3d histogram with weight (2.) - registry.fillWeight("3d-weight", track.pt(), track.eta(), track.phi(), 2.); + registry.fill("3d-weight", track.pt(), track.eta(), track.phi(), 2.); - registry.fillWeight("2d-profile-weight", track.pt(), track.eta(), track.phi(), 5.); + registry.fill("2d-profile-weight", track.pt(), track.eta(), track.phi(), 5.); } } }; diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 8609f623ccd9a..fa416811490ff 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -347,17 +347,17 @@ struct HistFactory { //************************************************************************************************** struct HistFiller { // fill any type of histogram (if weight was requested it must be the last argument) - template <bool useWeight = false, typename T, typename... Ts> + template <typename T, typename... Ts> static void fillHistAny(std::shared_ptr<T>& hist, const Ts&... positionAndWeight) { - constexpr int nDim = sizeof...(Ts) - useWeight; + constexpr int nArgs = sizeof...(Ts); - constexpr bool validTH3 = (std::is_same_v<TH3, T> && nDim == 3); - constexpr bool validTH2 = (std::is_same_v<TH2, T> && nDim == 2); - constexpr bool validTH1 = (std::is_same_v<TH1, T> && nDim == 1); - constexpr bool validTProfile3D = (std::is_same_v<TProfile3D, T> && nDim == 4); - constexpr bool validTProfile2D = (std::is_same_v<TProfile2D, T> && nDim == 3); - constexpr bool validTProfile = (std::is_same_v<TProfile, T> && nDim == 2); + constexpr bool validTH3 = (std::is_same_v<TH3, T> && (nArgs == 3 || nArgs == 4)); + constexpr bool validTH2 = (std::is_same_v<TH2, T> && (nArgs == 2 || nArgs == 3)); + constexpr bool validTH1 = (std::is_same_v<TH1, T> && (nArgs == 1 || nArgs == 2)); + constexpr bool validTProfile3D = (std::is_same_v<TProfile3D, T> && (nArgs == 4 || nArgs == 5)); + constexpr bool validTProfile2D = (std::is_same_v<TProfile2D, T> && (nArgs == 3 || nArgs == 4)); + constexpr bool validTProfile = (std::is_same_v<TProfile, T> && (nArgs == 2 || nArgs == 3)); constexpr bool validSimpleFill = validTH1 || validTH2 || validTH3 || validTProfile || validTProfile2D || validTProfile3D; // unfortunately we dont know at compile the dimension of THn(Sparse) @@ -366,27 +366,26 @@ struct HistFiller { if constexpr (validSimpleFill) { hist->Fill(static_cast<double>(positionAndWeight)...); } else if constexpr (validComplexFill) { - // savety check for n dimensional histograms (runtime overhead) - if (hist->GetNdimensions() != nDim) { + double tempArray[] = {static_cast<double>(positionAndWeight)...}; + double weight{1.}; + if (hist->GetNdimensions() == nArgs - 1) { + weight = tempArray[nArgs - 1]; + } else if (hist->GetNdimensions() != nArgs) { LOGF(FATAL, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName()); } - double tempArray[] = {static_cast<double>(positionAndWeight)...}; - if constexpr (useWeight) - hist->Fill(tempArray, tempArray[sizeof...(Ts) - 1]); - else - hist->Fill(tempArray); + hist->Fill(tempArray, weight); } else { LOGF(FATAL, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName()); } } // fill any type of histogram with columns (Cs) of a filtered table (if weight is requested it must reside the last specified column) - template <bool useWeight = false, typename... Cs, typename R, typename T> + template <typename... Cs, typename R, typename T> static void fillHistAnyTable(std::shared_ptr<R>& hist, const T& table, const o2::framework::expressions::Filter& filter) { auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; for (auto& t : filtered) { - fillHistAny<useWeight>(hist, (*(static_cast<Cs>(t).getIterator()))...); + fillHistAny(hist, (*(static_cast<Cs>(t).getIterator()))...); } } @@ -629,31 +628,17 @@ class HistogramRegistry } // fill hist with values - template <bool useWeight = false, typename... Ts> - void fill(char const* const name, Ts&&... positionAndWeight) - { - std::visit([&positionAndWeight...](auto&& hist) { HistFiller::fillHistAny<useWeight>(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[getHistIndex(name)]); - } - - // fill hist with values and weight template <typename... Ts> - void fillWeight(char const* const name, Ts&&... positionAndWeight) + void fill(char const* const name, Ts&&... positionAndWeight) { - fill<true>(name, std::forward<Ts>(positionAndWeight)...); + std::visit([&positionAndWeight...](auto&& hist) { HistFiller::fillHistAny(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[getHistIndex(name)]); } // fill hist with content of (filtered) table columns template <typename... Cs, typename T> void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) { - fillTable<false, Cs...>(name, table, filter); - } - - // fill hist with content of (filtered) table columns and weight - template <typename... Cs, typename T> - void fillWeight(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) - { - fillTable<true, Cs...>(name, table, filter); + std::visit([&table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<Cs...>(hist, table, filter); }, mRegistryValue[getHistIndex(name)]); } // get rough estimate for size of histogram stored in registry @@ -739,13 +724,6 @@ class HistogramRegistry throw runtime_error("No matching histogram found in HistogramRegistry!"); } - // this is for internal use only because we dont want user to have to specify 'useWeight' argument - template <bool useWeight = false, typename... Cs, typename T> - void fillTable(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) - { - std::visit([&table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<useWeight, Cs...>(hist, table, filter); }, mRegistryValue[getHistIndex(name)]); - } - // helper function to create resp. find the subList defined by path TList* getSubList(TList* list, std::deque<std::string>& path) { From eb2174c68dc939d2c69c0cafd48408df58405d3e Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 25 May 2020 17:19:52 +0200 Subject: [PATCH 1187/1751] Pass options as arguments --- .../include/MIDWorkflow/RawDecoderSpec.h | 4 ++ .../MUON/MID/Workflow/src/RawDecoderSpec.cxx | 56 +++++++------------ 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h index 8e4388bef8ef1..43c2c58b791bb 100644 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h @@ -17,12 +17,16 @@ #define O2_MID_RAWDECODERSPEC_H #include "Framework/DataProcessorSpec.h" +#include "MIDRaw/CrateMasks.h" +#include "MIDRaw/ElectronicsDelay.h" +#include "MIDRaw/FEEIdConfig.h" namespace o2 { namespace mid { framework::DataProcessorSpec getRawDecoderSpec(bool isBare = false); +framework::DataProcessorSpec getRawDecoderSpec(bool isBare, bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay); } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx b/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx index b383a9aebd7a1..93fbf2bf248f6 100644 --- a/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx @@ -16,18 +16,14 @@ #include "MIDWorkflow/RawDecoderSpec.h" #include <chrono> -#include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" +#include "Framework/CallbackService.h" #include "Framework/Logger.h" #include "Framework/Output.h" #include "Framework/Task.h" #include "Framework/WorkflowSpec.h" #include "DPLUtils/DPLRawParser.h" -#include "MIDRaw/FEEIdConfig.h" -#include "MIDRaw/CrateMasks.h" +#include "Headers/RDHAny.h" #include "MIDRaw/Decoder.h" -#include "MIDRaw/GBTBareDecoder.h" -#include "MIDRaw/GBTUserLogicDecoder.h" namespace of = o2::framework; @@ -40,6 +36,8 @@ template <typename GBTDECODER> class RawDecoderDeviceDPL { public: + RawDecoderDeviceDPL<GBTDECODER>(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay) : mIsDebugMode(isDebugMode), mFeeIdConfig(feeIdConfig), mCrateMasks(crateMasks), mElectronicsDelay(electronicsDelay) {} + void init(of::InitContext& ic) { auto stop = [this]() { @@ -49,35 +47,22 @@ class RawDecoderDeviceDPL }; ic.services().get<of::CallbackService>().set(of::CallbackService::Id::Stop, stop); - auto feeIdConfigFilename = ic.options().get<std::string>("feeId-config-file"); - if (!feeIdConfigFilename.empty()) { - o2::mid::FEEIdConfig feeIdConfig(feeIdConfigFilename.c_str()); - mDecoder.setFeeIdConfig(feeIdConfig); - } - auto crateMasksFilename = ic.options().get<std::string>("crate-masks-file"); - if (!crateMasksFilename.empty()) { - o2::mid::CrateMasks crateMasks(crateMasksFilename.c_str()); - mDecoder.setCrateMasks(crateMasks); - } + mDecoder.setFeeIdConfig(mFeeIdConfig); + mDecoder.setCrateMasks(mCrateMasks); - auto isDebugMode = ic.options().get<bool>("debug-mode"); - mDecoder.init(isDebugMode); + mDecoder.init(mIsDebugMode); } void run(of::ProcessingContext& pc) { auto tStart = std::chrono::high_resolution_clock::now(); - auto msg = pc.inputs().get("mid_raw"); - auto buffer = of::DataRefUtils::as<const uint8_t>(msg); - auto tAlgoStart = std::chrono::high_resolution_clock::now(); - of::DPLRawParser parser(pc.inputs()); + of::DPLRawParser parser(pc.inputs(), of::select("mid_raw:MID/RAWDATA")); mDecoder.clear(); for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { - // retrieving RDH v4 - auto rdhPtr = it.get_if<o2::header::RAWDataHeader>(); + auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(it.raw()); gsl::span<const uint8_t> payload(it.data(), it.size()); mDecoder.process(payload, *rdhPtr); } @@ -85,8 +70,8 @@ class RawDecoderDeviceDPL mDecoder.flush(); mTimerAlgo += std::chrono::high_resolution_clock::now() - tAlgoStart; - pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODED", 0, of::Lifetime::Timeframe}, mDecoder.getData()); - pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODEDROF", 0, of::Lifetime::Timeframe}, mDecoder.getROFRecords()); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODED", 0}, mDecoder.getData()); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODEDROF", 0}, mDecoder.getROFRecords()); mTimer += std::chrono::high_resolution_clock::now() - tStart; mNROFs += mDecoder.getROFRecords().size(); @@ -94,20 +79,21 @@ class RawDecoderDeviceDPL private: Decoder<GBTDECODER> mDecoder{}; + bool mIsDebugMode{false}; + FEEIdConfig mFeeIdConfig{}; + CrateMasks mCrateMasks{}; + ElectronicsDelay mElectronicsDelay{}; std::chrono::duration<double> mTimer{0}; ///< full timer std::chrono::duration<double> mTimerAlgo{0}; ///< algorithm timer unsigned int mNROFs{0}; /// Total number of processed ROFs }; -of::AlgorithmSpec getAlgorithmSpec(bool isBare) +of::DataProcessorSpec getRawDecoderSpec(bool isBare) { - if (isBare) { - return of::adaptFromTask<o2::mid::RawDecoderDeviceDPL<o2::mid::GBTBareDecoder>>(); - } - return of::adaptFromTask<o2::mid::RawDecoderDeviceDPL<o2::mid::GBTUserLogicDecoder>>(); + return getRawDecoderSpec(isBare, false, FEEIdConfig(), CrateMasks(), ElectronicsDelay()); } -framework::DataProcessorSpec getRawDecoderSpec(bool isBare) +of::DataProcessorSpec getRawDecoderSpec(bool isBare, bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay) { std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_raw", of::ConcreteDataTypeMatcher{header::gDataOriginMID, header::gDataDescriptionRawData}, of::Lifetime::Timeframe}}; std::vector<of::OutputSpec> outputSpecs{of::OutputSpec{header::gDataOriginMID, "DECODED", 0, of::Lifetime::Timeframe}, of::OutputSpec{header::gDataOriginMID, "DECODEDROF", 0, of::Lifetime::Timeframe}}; @@ -116,11 +102,7 @@ framework::DataProcessorSpec getRawDecoderSpec(bool isBare) "MIDRawDecoder", {inputSpecs}, {outputSpecs}, - getAlgorithmSpec(isBare), - of::Options{ - {"feeId-config-file", of::VariantType::String, "", {"Filename with crate FEE ID correspondence"}}, - {"crate-masks-file", of::VariantType::String, "", {"Filename with crate masks"}}, - {"debug-mode", of::VariantType::Bool, false, {"Debug mode: sends all boards"}}}}; + isBare ? of::adaptFromTask<o2::mid::RawDecoderDeviceDPL<o2::mid::GBTBareDecoder>>(isDebugMode, feeIdConfig, crateMasks, electronicsDelay) : of::adaptFromTask<o2::mid::RawDecoderDeviceDPL<o2::mid::GBTUserLogicDecoder>>(isDebugMode, feeIdConfig, crateMasks, electronicsDelay)}; } } // namespace mid } // namespace o2 From b965903397cf076bbbdf01b46fb076049b377912 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Tue, 22 Sep 2020 15:10:26 +0200 Subject: [PATCH 1188/1751] MID raw to digits workflow --- Detectors/MUON/MID/Workflow/CMakeLists.txt | 58 +++++++++------- .../Workflow/src/raw-to-digits-workflow.cxx | 67 +++++++++++++++++++ 2 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx diff --git a/Detectors/MUON/MID/Workflow/CMakeLists.txt b/Detectors/MUON/MID/Workflow/CMakeLists.txt index 6a8be67985f22..454442bea8333 100644 --- a/Detectors/MUON/MID/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MID/Workflow/CMakeLists.txt @@ -12,34 +12,33 @@ o2_add_library(MIDWorkflow TARGETVARNAME targetName SOURCES src/RecoWorkflow.cxx src/ClusterizerMCSpec.cxx + src/ClusterizerSpec.cxx src/DigitReaderSpec.cxx - src/RecoWorkflowMC.cxx - src/TrackerMCSpec.cxx - src/ClusterizerSpec.cxx - src/RecoWorkflow.cxx - src/RawDecoderSpec.cxx - src/RawAggregatorSpec.cxx - src/TrackerSpec.cxx - src/DigitReaderSpec.cxx - src/DigitsToRawWorkflow.cxx - src/RawWriterSpec.cxx + src/DigitsToRawWorkflow.cxx src/EntropyDecoderSpec.cxx src/EntropyEncoderSpec.cxx - PUBLIC_LINK_LIBRARIES - O2::Framework - O2::SimConfig - ms_gsl::ms_gsl - O2::DetectorsBase - O2::SimulationDataFormat - O2::DataFormatsMID - O2::DPLUtils - O2::MIDSimulation - O2::MIDClustering - O2::MIDTracking - O2::MIDRaw + src/RawAggregatorSpec.cxx + src/RawDecoderSpec.cxx + src/RecoWorkflow.cxx + src/RecoWorkflowMC.cxx + src/RawWriterSpec.cxx + src/TrackerMCSpec.cxx + src/TrackerSpec.cxx + PUBLIC_LINK_LIBRARIES + O2::Framework + O2::SimConfig + ms_gsl::ms_gsl + O2::DetectorsBase + O2::DPLUtils + O2::SimulationDataFormat + O2::DataFormatsMID + O2::MIDClustering O2::MIDCTF - ) - + O2::MIDRaw + O2::MIDSimulation + O2::MIDTracking + ) + o2_add_executable( reco-workflow-mc COMPONENT_NAME mid @@ -83,3 +82,14 @@ o2_add_executable( target_include_directories( ${exenameentropy} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) + +o2_add_executable( + raw-to-digits-workflow + COMPONENT_NAME mid + SOURCES src/raw-to-digits-workflow.cxx + TARGETVARNAME exanamedigitstoraw + PUBLIC_LINK_LIBRARIES O2::MIDWorkflow) + +target_include_directories( + ${exanamedigitstoraw} + PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) diff --git a/Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx b/Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx new file mode 100644 index 0000000000000..8e9e964b11b0e --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx @@ -0,0 +1,67 @@ +// 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 MID/Workflow/src/raw-to-digits-workflow.cxx +/// \brief MID raw to digits workflow +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 22 September 2020 + +#include <string> +#include <vector> +#include "Framework/Variant.h" +#include "Framework/ConfigParamSpec.h" +#include "MIDWorkflow/RawDecoderSpec.h" +#include "MIDWorkflow/RawAggregatorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> + options{ + {"feeId-config-file", VariantType::String, "", {"Filename with crate FEE ID correspondence"}}, + {"crate-masks-file", VariantType::String, "", {"Filename with crate masks"}}, + {"electronics-delay-file", VariantType::String, "", {"Filename with electronics delay"}}, + {"bare", VariantType::Bool, false, {"Is bare decoder"}}, + {"decode-only", o2::framework::VariantType::Bool, false, {"Output decoded boards instead of digits"}}}; + workflowOptions.insert(workflowOptions.end(), options.begin(), options.end()); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + auto feeIdConfigFilename = cfgc.options().get<std::string>("feeId-config-file"); + o2::mid::FEEIdConfig feeIdConfig; + if (!feeIdConfigFilename.empty()) { + feeIdConfig = o2::mid::FEEIdConfig(feeIdConfigFilename.c_str()); + } + auto crateMasksFilename = cfgc.options().get<std::string>("crate-masks-file"); + o2::mid::CrateMasks crateMasks; + if (!crateMasksFilename.empty()) { + crateMasks = o2::mid::CrateMasks(crateMasksFilename.c_str()); + } + auto electronicsDelayFilename = cfgc.options().get<std::string>("electronics-delay-file"); + o2::mid::ElectronicsDelay electronicsDelay; + if (!electronicsDelayFilename.empty()) { + electronicsDelay = o2::mid::readElectronicsDelay(electronicsDelayFilename.c_str()); + } + + bool isBare = cfgc.options().get<bool>("bare"); + bool decodeOnly = cfgc.options().get<bool>("decode-only"); + + o2::framework::WorkflowSpec specs; + specs.emplace_back(o2::mid::getRawDecoderSpec(isBare, false, feeIdConfig, crateMasks, electronicsDelay)); + if (!decodeOnly) { + specs.emplace_back(o2::mid::getRawAggregatorSpec()); + } + return specs; +} From bc063040e186b6ea80114ab76e42a7258444c38b Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Sun, 25 Oct 2020 13:30:05 +0100 Subject: [PATCH 1189/1751] Add spec to perform zero suppression on MID digits --- Detectors/MUON/MID/Workflow/CMakeLists.txt | 1 + .../include/MIDWorkflow/ZeroSuppressionSpec.h | 29 +++++ .../MID/Workflow/src/ZeroSuppressionSpec.cxx | 118 ++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 Detectors/MUON/MID/Workflow/include/MIDWorkflow/ZeroSuppressionSpec.h create mode 100644 Detectors/MUON/MID/Workflow/src/ZeroSuppressionSpec.cxx diff --git a/Detectors/MUON/MID/Workflow/CMakeLists.txt b/Detectors/MUON/MID/Workflow/CMakeLists.txt index 454442bea8333..d059a019649fd 100644 --- a/Detectors/MUON/MID/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MID/Workflow/CMakeLists.txt @@ -24,6 +24,7 @@ o2_add_library(MIDWorkflow src/RawWriterSpec.cxx src/TrackerMCSpec.cxx src/TrackerSpec.cxx + src/ZeroSuppressionSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::SimConfig diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/ZeroSuppressionSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/ZeroSuppressionSpec.h new file mode 100644 index 0000000000000..b819acafaccfd --- /dev/null +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/ZeroSuppressionSpec.h @@ -0,0 +1,29 @@ +// 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 MIDWorkflow/ZeroSuppressionSpec.h +/// \brief MID zero suppression spec +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 23 October 2020 + +#ifndef O2_MID_ZEROSUPPRESSIONSPEC_H +#define O2_MID_ZEROSUPPRESSIONSPEC_H + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +namespace mid +{ +framework::DataProcessorSpec getZeroSuppressionSpec(bool useMC = true); +} +} // namespace o2 + +#endif //O2_MID_ZEROSUPPRESSIONSPEC_H diff --git a/Detectors/MUON/MID/Workflow/src/ZeroSuppressionSpec.cxx b/Detectors/MUON/MID/Workflow/src/ZeroSuppressionSpec.cxx new file mode 100644 index 0000000000000..12a7e0940c3e5 --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/ZeroSuppressionSpec.cxx @@ -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 MID/Workflow/src/ZeroSuppressionSpec.cxx +/// \brief MID zero suppression spec +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 23 October 2020 + +#include "MIDWorkflow/ZeroSuppressionSpec.h" + +#include <vector> +#include <gsl/gsl> +#include "Framework/Output.h" +#include "Framework/Task.h" +#include "DataFormatsMID/ColumnData.h" +#include "DataFormatsMID/ROFRecord.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "MIDRaw/ColumnDataToLocalBoard.h" +#include "MIDRaw/DecodedDataAggregator.h" +#include "MIDSimulation/MCLabel.h" + +namespace of = o2::framework; + +namespace o2 +{ +namespace mid +{ + +class ZeroSuppressionDeviceDPL +{ + public: + ZeroSuppressionDeviceDPL(bool useMC) : mUseMC(useMC) {} + + void init(o2::framework::InitContext& ic) + { + } + + void run(o2::framework::ProcessingContext& pc) + { + const auto patterns = pc.inputs().get<gsl::span<ColumnData>>("mid_data_mc"); + + const auto inROFRecords = pc.inputs().get<gsl::span<ROFRecord>>("mid_data_mc_rof"); + + const auto inMCContainer = mUseMC ? pc.inputs().get<const o2::dataformats::MCTruthContainer<MCLabel>*>("mid_data_mc_labels") : nullptr; + + o2::dataformats::MCTruthContainer<MCLabel> outMCContainer; + + std::vector<ROFRecord> zsROFs, tmpROFs(1); + std::vector<ColumnData> zsData; + for (auto& rof : inROFRecords) { + mConverter.process(patterns.subspan(rof.firstEntry, rof.nEntries)); + if (!mConverter.getData().empty()) { + std::vector<LocalBoardRO> decodedData; + for (auto& item : mConverter.getData()) { + decodedData.insert(decodedData.end(), item.second.begin(), item.second.end()); + } + tmpROFs.front().interactionRecord = rof.interactionRecord; + tmpROFs.front().eventType = rof.eventType; + tmpROFs.front().firstEntry = 0; + tmpROFs.front().nEntries = decodedData.size(); + mAggregator.process(decodedData, tmpROFs); + auto& tmpOut = mAggregator.getData(); + zsROFs.emplace_back(rof.interactionRecord, rof.eventType, zsData.size(), tmpOut.size()); + zsData.insert(zsData.end(), tmpOut.begin(), tmpOut.end()); + + if (mUseMC) { + for (auto outColIt = zsData.begin() + zsROFs.back().firstEntry, outEnd = zsData.begin() + zsROFs.back().firstEntry + zsROFs.back().nEntries; outColIt != outEnd; ++outColIt) { + for (auto inColIt = patterns.begin() + rof.firstEntry, inEnd = patterns.begin() + rof.firstEntry + rof.nEntries; inColIt != inEnd; ++inColIt) { + if (inColIt->deId == outColIt->deId && inColIt->columnId == outColIt->columnId) { + auto inIdx = std::distance(patterns.begin(), inColIt); + auto outIdx = std::distance(zsData.begin(), outColIt); + outMCContainer.addElements(outIdx, inMCContainer->getLabels(inIdx)); + break; + } + } + } + } + } + } + + pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DATA", 0, of::Lifetime::Timeframe}, zsData); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DATAROF", 0, of::Lifetime::Timeframe}, zsROFs); + if (mUseMC) { + pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DATALABELS", 0, of::Lifetime::Timeframe}, outMCContainer); + } + } + + private: + ColumnDataToLocalBoard mConverter{}; + DecodedDataAggregator mAggregator{}; + bool mUseMC{true}; +}; + +framework::DataProcessorSpec getZeroSuppressionSpec(bool useMC) +{ + std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_data_mc", header::gDataOriginMID, "DATAMC"}, of::InputSpec{"mid_data_mc_rof", header::gDataOriginMID, "DATAMCROF"}}; + + std::vector<of::OutputSpec> outputSpecs{of::OutputSpec{header::gDataOriginMID, "DATA"}, of::OutputSpec{header::gDataOriginMID, "DATAROF"}}; + if (useMC) { + inputSpecs.emplace_back(of::InputSpec{"mid_data_mc_labels", header::gDataOriginMID, "DATAMCLABELS"}); + outputSpecs.emplace_back(of::OutputSpec{header::gDataOriginMID, "DATALABELS"}); + } + + return of::DataProcessorSpec{ + "MIDZeroSuppression", + {inputSpecs}, + {outputSpecs}, + of::AlgorithmSpec{of::adaptFromTask<o2::mid::ZeroSuppressionDeviceDPL>(useMC)}}; +} +} // namespace mid +} // namespace o2 \ No newline at end of file From e2731530e71d1949ecdde86ba13160bfb6a4976e Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Sun, 25 Oct 2020 13:30:57 +0100 Subject: [PATCH 1190/1751] Split MID reconstruction workflow into digits reader and digits to track This allows for a better modularity. Digits can be produced: - from raw data - by reading MC simulated digits - from CTF using dedicated devices --- Detectors/MUON/MID/Workflow/CMakeLists.txt | 49 +++++------ Detectors/MUON/MID/Workflow/README.md | 87 +++++++++++++++---- .../include/MIDWorkflow/DigitReaderSpec.h | 2 +- .../include/MIDWorkflow/RecoWorkflow.h | 30 ------- .../include/MIDWorkflow/RecoWorkflowMC.h | 30 ------- .../MUON/MID/Workflow/src/DigitReaderSpec.cxx | 41 +++++---- .../MUON/MID/Workflow/src/RecoWorkflow.cxx | 68 --------------- .../MUON/MID/Workflow/src/RecoWorkflowMC.cxx | 68 --------------- .../Workflow/src/digits-reader-workflow.cxx | 52 +++++++++++ .../MUON/MID/Workflow/src/reco-workflow.cxx | 77 ++++++++++++++++ 10 files changed, 249 insertions(+), 255 deletions(-) delete mode 100644 Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h delete mode 100644 Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflowMC.h delete mode 100644 Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx delete mode 100644 Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx create mode 100644 Detectors/MUON/MID/Workflow/src/digits-reader-workflow.cxx create mode 100644 Detectors/MUON/MID/Workflow/src/reco-workflow.cxx diff --git a/Detectors/MUON/MID/Workflow/CMakeLists.txt b/Detectors/MUON/MID/Workflow/CMakeLists.txt index d059a019649fd..b827dc8e67529 100644 --- a/Detectors/MUON/MID/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MID/Workflow/CMakeLists.txt @@ -10,8 +10,7 @@ o2_add_library(MIDWorkflow TARGETVARNAME targetName - SOURCES src/RecoWorkflow.cxx - src/ClusterizerMCSpec.cxx + SOURCES src/ClusterizerMCSpec.cxx src/ClusterizerSpec.cxx src/DigitReaderSpec.cxx src/DigitsToRawWorkflow.cxx @@ -19,8 +18,6 @@ o2_add_library(MIDWorkflow src/EntropyEncoderSpec.cxx src/RawAggregatorSpec.cxx src/RawDecoderSpec.cxx - src/RecoWorkflow.cxx - src/RecoWorkflowMC.cxx src/RawWriterSpec.cxx src/TrackerMCSpec.cxx src/TrackerSpec.cxx @@ -40,28 +37,6 @@ o2_add_library(MIDWorkflow O2::MIDTracking ) -o2_add_executable( - reco-workflow-mc - COMPONENT_NAME mid - SOURCES src/mid-reco-workflow-mc.cxx - TARGETVARNAME exenamerecomc - PUBLIC_LINK_LIBRARIES - O2::MIDWorkflow) - -target_include_directories( - ${exenamerecomc} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) - -o2_add_executable( - reco-workflow - COMPONENT_NAME mid - SOURCES src/mid-reco-workflow.cxx - TARGETVARNAME exenamereco - PUBLIC_LINK_LIBRARIES - O2::MIDWorkflow) - -target_include_directories( - ${exenamereco} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) - o2_add_executable( digits-to-raw-workflow COMPONENT_NAME mid @@ -94,3 +69,25 @@ o2_add_executable( target_include_directories( ${exanamedigitstoraw} PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) + +o2_add_executable( + reco-workflow + COMPONENT_NAME mid + SOURCES src/reco-workflow.cxx + TARGETVARNAME exanamereco + PUBLIC_LINK_LIBRARIES O2::MIDWorkflow) + +target_include_directories( + ${exanamereco} + PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) + +o2_add_executable( + digits-reader-workflow + COMPONENT_NAME mid + SOURCES src/digits-reader-workflow.cxx + TARGETVARNAME exanamedigitsreader + PUBLIC_LINK_LIBRARIES O2::MIDWorkflow) + +target_include_directories( + ${exanamedigitsreader} + PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>) diff --git a/Detectors/MUON/MID/Workflow/README.md b/Detectors/MUON/MID/Workflow/README.md index 563f23581c553..391d981567ce8 100644 --- a/Detectors/MUON/MID/Workflow/README.md +++ b/Detectors/MUON/MID/Workflow/README.md @@ -3,58 +3,111 @@ /doxy --> # MID reconstruction workflow -The MID reconstruction can start either from simulated digits or from raw data. -The reconstruction algorithm is the same in the two cases, but the workflow is slightly different. -Indeed, in the case of MC digits, the MC labels are propagated as well, thus allowing to relate the reconstructed tracks with the corresponding generated particles. + +The MID reconstruction starts from the digits and produced MID tracks. +The input digits cna be: + +- MC digits +- digits obtained after decoding raw data +- digits read from CTF + +In the case of the MC digits, the MC labels are propagated as well, thus allowing to relate the reconstructed tracks with the corresponding generated particles. The procedure to run the reconstruction, either from the digits or from raw data, is detailed in the following. ## Preface: getting the digits + If you do not have the digits, you can obtain a sample with: + ```bash o2-sim -g fwmugen -m MID -n 100 o2-sim-digitizer-workflow ``` + ## Reconstruction from MC digits -To run the MC reconstruction workflow, run: + +To reconstruct the MC digits, run: + +```bash +o2-mid-digits-reader-workflow | o2-mid-reco-workflow --mc +``` + +The `--mc` option at the end of the workflow allow to propagate the MC labels up to the tracks. + +### Zero suppression + +The MID electronics has a default zero suppression mode. Digits are transmitted only if there is at least one strip fired in both the bending and non-bending plane in at least one of the 4 RPCs which are read-out by a local board. +The zero suppression is not applied to the MC digits that are stored on disk. +This allows to decide whether to apply the zero suppression or not at a later stage, since this mode can be disabled on data. + +The digit reader workflow reads the MC digits and applies the zero suppression as default, so that the output is compatible with what would be expected from raw data. +However, one can disable the zero suppression by running the digits reader with: + ```bash -o2-mid-reco-workflow-mc +o2-mid-digits-reader-workflow --disable-zero-suppression ``` ## Reconstruction from raw data + +To reconstruct the raw data (either from converted MC digits or real data), run: + +```bash +o2-raw-file-reader-workflow --input-conf MIDraw.cfg | o2-mid-raw-to-digits-workflow | o2-mid-reco-workflow +``` + The reconstruction from raw data can also be tested using as input raw data obtained from the MC digits. -### From MC digits to Raw data + +### From MC digits to raw data + To convert the MC digits into raw data format, run: + ```bash o2-mid-digits-to-raw-workflow ``` + The output will be a binary file named by default *raw_mid.dat*. -Notice that the executable also generate a configuration file that is needed to read the file with the raw reader workflow (see [here](../../../Raw/README.md) for further details) +Notice that the executable also generates a configuration file that is needed to read the file with the raw reader workflow (see [here](../../../Raw/README.md) for further details) + +## From CTF + +The CTF for MID corresponds to the digit. +So one can retrieve the digits from the CTF and run the reconstruction with the usual workflow with: -### Reconstruction from raw data -To reconstruct the raw data (either from converted MC digits or real data), run: ```bash -o2-raw-file-reader-workflow --conf mid_raw.cfg | o2-mid-reco-workflow +o2-ctf-reader-workflow --ctf-input o2_ctf_0000000000.root --onlyDet MID | o2-mid-reco-workflow +``` + +### Generate CTF + +The MID contribution can be added to CTF by attaching the `o2-mid-entropy-encoder-workflow` device to reconstruction workflow ending by CTF writer, e.g.: + +```bash +o2-raw-file-reader-workflow --input-conf MIDraw.cfg | o2-mid-raw-to-digits-workflow | o2-mid-entropy-encoder-workflow | o2-ctf-writer-workflow ``` ## Timing + In each device belonging to the reconstruction workflow, the execution time is measured using the `chrono` c++ library. At the end of the execution, when the *stop* command is launched, the execution time is written to the `LOG(INFO)`. An example output is the following: -``` + +```less Processing time / 90 ROFs: full: 3.55542 us tracking: 2.02182 us ``` + Two timing values are provided: one is for the full execution of the device (including retrieval and sending of the DPL messages) and one which concerns only the execution of the algorithm (the tracking algorithm in the above example) The timing refers to the time needed to process one read-out-frame, i.e. one event. -## Operations with CTF +## Reconstruction options + +By default, the reconstruction produces clusters and tracks that are written on file. +It is however possible to only run clustering with: -The MID contribution can be added to CTF by attaching the ``o2-mid-entropy-encoder-workflow`` device to reconstruction workflow ending by CTF writer, e.g.: ```bash -o2-raw-file-reader-workflow --input-conf raw/MID/MIDraw.cfg | o2-mid-reco-workflow | o2-mid-entropy-encoder-workflow | o2-ctf-writer-workflow +o2-mid-reco-workflow --disable-tracking ``` -The reconstruction staring from CTF can be done as (option ``--input-ctf`` will prevent the ``o2-mid-reco-workflow`` from -adding raw data decoding/aggregation to the workflow): +It is also possible to avoid producing a root file with: + ```bash -o2-ctf-reader-workflow --ctf-input o2_ctf_0000000000.root --onlyDet MID | o2-mid-reco-workflow --input-ctf +o2-mid-reco-workflow --disable-output-file ``` diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h index dbcee885b3b0b..334e61e1c61c7 100644 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitReaderSpec.h @@ -22,7 +22,7 @@ namespace o2 { namespace mid { -framework::DataProcessorSpec getDigitReaderSpec(bool useMC); +framework::DataProcessorSpec getDigitReaderSpec(bool useMC, const char* baseDescription = "DATAMC"); } } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h deleted file mode 100644 index c7485bc53a60b..0000000000000 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflow.h +++ /dev/null @@ -1,30 +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. - -/// \file MIDWorkflow/RecoWorkflow.h -/// \brief Definition of the reconstruction workflow for MID -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 11 April 2019 - -#ifndef O2_MID_RECOWORKFLOWSPEC_H -#define O2_MID_RECOWORKFLOWSPEC_H - -#include "Framework/RootSerializationSupport.h" -#include "Framework/WorkflowSpec.h" - -namespace o2 -{ -namespace mid -{ -framework::WorkflowSpec getRecoWorkflow(bool ctfInput, bool disableRootOut); -} -} // namespace o2 - -#endif //O2_MID_RECOWORKFLOWSPEC_H diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflowMC.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflowMC.h deleted file mode 100644 index 2c3ef96078642..0000000000000 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RecoWorkflowMC.h +++ /dev/null @@ -1,30 +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. - -/// \file MIDWorkflow/RecoWorkflowMC.h -/// \brief Definition of the reconstruction workflow for MID MC -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 11 April 2019 - -#ifndef O2_MID_RECOWORKFLOWMCSPEC_H -#define O2_MID_RECOWORKFLOWMCSPEC_H - -#include "Framework/RootSerializationSupport.h" -#include "Framework/WorkflowSpec.h" - -namespace o2 -{ -namespace mid -{ -framework::WorkflowSpec getRecoWorkflowMC(); -} -} // namespace o2 - -#endif //O2_MID_RECOWORKFLOWMCSPEC_H diff --git a/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx b/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx index 1008ee6c712b9..1e87b11e22648 100644 --- a/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/DigitReaderSpec.cxx @@ -15,18 +15,23 @@ #include "MIDWorkflow/DigitReaderSpec.h" -#include "Framework/ControlService.h" +#include <sstream> +#include <string> +#include "fmt/format.h" +#include "TFile.h" +#include "TTree.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/DataSpecUtils.h" #include "Framework/Logger.h" #include "Framework/Output.h" #include "Framework/Task.h" +#include "Framework/WorkflowSpec.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "DataFormatsMID/ColumnData.h" #include "DataFormatsMID/ROFRecord.h" #include "MIDSimulation/ColumnDataMC.h" #include "MIDSimulation/MCLabel.h" -#include "TFile.h" -#include "TTree.h" namespace of = o2::framework; @@ -38,8 +43,7 @@ namespace mid class DigitsReaderDeviceDPL { public: - DigitsReaderDeviceDPL(bool useMC = true) : mUseMC(useMC) {} - + DigitsReaderDeviceDPL(bool useMC, const std::vector<header::DataDescription>& descriptions) : mUseMC(useMC), mDescriptions(descriptions) {} void init(o2::framework::InitContext& ic) { auto filename = ic.options().get<std::string>("mid-digit-infile"); @@ -83,11 +87,11 @@ class DigitsReaderDeviceDPL } LOG(DEBUG) << "MIDDigitsReader pushed " << digits.size() << " merged digits"; - pc.outputs().snapshot(of::Output{"MID", "DATA", 0, of::Lifetime::Timeframe}, digits); - pc.outputs().snapshot(of::Output{"MID", "DATAROF", 0, of::Lifetime::Timeframe}, rofRecords); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, mDescriptions[0], 0, of::Lifetime::Timeframe}, digits); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, mDescriptions[1], 0, of::Lifetime::Timeframe}, rofRecords); LOG(DEBUG) << "MIDDigitsReader pushed " << digits.size() << " indexed digits"; if (mUseMC) { - pc.outputs().snapshot(of::Output{"MID", "DATALABELS", 0, of::Lifetime::Timeframe}, mcContainer); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, mDescriptions[2], 0, of::Lifetime::Timeframe}, mcContainer); } mState = 2; pc.services().get<of::ControlService>().endOfStream(); @@ -99,26 +103,33 @@ class DigitsReaderDeviceDPL std::vector<o2::mid::ColumnDataMC>* mDigits{nullptr}; // not owner o2::dataformats::MCTruthContainer<MCLabel>* mMCContainer{nullptr}; // not owner std::vector<o2::mid::ROFRecord>* mROFRecords{nullptr}; // not owner + std::vector<header::DataDescription> mDescriptions{}; int mState = 0; bool mUseMC = true; }; -framework::DataProcessorSpec getDigitReaderSpec(bool useMC) +framework::DataProcessorSpec getDigitReaderSpec(bool useMC, const char* baseDescription) { std::vector<of::OutputSpec> outputs; - outputs.emplace_back("MID", "DATA", o2::framework::Lifetime::Timeframe); - outputs.emplace_back("MID", "DATAROF", o2::framework::Lifetime::Timeframe); + std::vector<header::DataDescription> descriptions; + std::stringstream ss; + ss << "A:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "/0"; + ss << ";B:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "ROF/0"; if (useMC) { - outputs.emplace_back("MID", "DATALABELS", o2::framework::Lifetime::Timeframe); + ss << ";C:" << header::gDataOriginMID.as<std::string>() << "/" << baseDescription << "LABELS/0"; + } + auto matchers = of::select(ss.str().c_str()); + for (auto& matcher : matchers) { + outputs.emplace_back(of::DataSpecUtils::asOutputSpec(matcher)); + descriptions.emplace_back(of::DataSpecUtils::asConcreteDataDescription(matcher)); } return of::DataProcessorSpec{ "MIDDigitsReader", of::Inputs{}, outputs, - of::AlgorithmSpec{of::adaptFromTask<o2::mid::DigitsReaderDeviceDPL>(useMC)}, - of::Options{ - {"mid-digit-infile", of::VariantType::String, "middigits.root", {"Name of the input file"}}}}; + of::AlgorithmSpec{of::adaptFromTask<o2::mid::DigitsReaderDeviceDPL>(useMC, descriptions)}, + of::Options{{"mid-digit-infile", of::VariantType::String, "middigits.root", {"Name of the input file"}}}}; } } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx b/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx deleted file mode 100644 index b46a5d4ee3e72..0000000000000 --- a/Detectors/MUON/MID/Workflow/src/RecoWorkflow.cxx +++ /dev/null @@ -1,68 +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. - -/// \file MID/Workflow/src/RecoWorkflow.cxx -/// \brief Definition of MID reconstruction workflow -/// \author Gabriele G. Fronze <gfronze at cern.ch> -/// \date 11 July 2018 - -#include "MIDWorkflow/RecoWorkflow.h" - -#include "DPLUtils/MakeRootTreeWriterSpec.h" -#include "DataFormatsMID/ROFRecord.h" -#include "MIDWorkflow/ClusterizerSpec.h" -#include "MIDWorkflow/RawAggregatorSpec.h" -#include "MIDWorkflow/RawDecoderSpec.h" -#include "MIDWorkflow/TrackerSpec.h" - -namespace of = o2::framework; - -namespace o2 -{ -namespace mid -{ - -of::WorkflowSpec getRecoWorkflow(bool ctf, bool disableRootOut) -{ - - auto checkReady = [](o2::framework::DataRef const& ref) { - // The default checkReady function is not defined in MakeRootTreeWriterSpec: - // this leads to a std::exception in DPL. - // While the exception seems harmless (the processing goes on without apparent consequence), - // it is quite ugly to see. - // So, let us define checkReady here. - // FIXME: to be fixed in MakeRootTreeWriterSpec - return false; - }; - - of::WorkflowSpec specs; - - if (!ctf) { - specs.emplace_back(getRawDecoderSpec(false)); - specs.emplace_back(getRawAggregatorSpec()); - } - specs.emplace_back(getClusterizerSpec()); - specs.emplace_back(getTrackerSpec()); - if (!disableRootOut) { - specs.emplace_back(of::MakeRootTreeWriterSpec("MIDTracksWriter", - "mid-tracks.root", - "midtracks", - of::MakeRootTreeWriterSpec::TerminationPolicy::Process, - of::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_tracks", "MID", "TRACKS"}, "MIDTrack"}, - of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_trackClusters", "MID", "TRACKCLUSTERS"}, "MIDTrackClusters"}, - of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_tracks_rof", "MID", "TRACKSROF"}, "MIDTrackROF"}, - of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_trclus_rof", "MID", "TRCLUSROF"}, "MIDTrackClusterROF"})()); - } - - return specs; -} -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx b/Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx deleted file mode 100644 index fa02d86cb76bc..0000000000000 --- a/Detectors/MUON/MID/Workflow/src/RecoWorkflowMC.cxx +++ /dev/null @@ -1,68 +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. - -/// \file MID/Workflow/src/RecoWorkflowMC.cxx -/// \brief Definition of MID reconstruction workflow for MC -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 27 September 2019 - -#include "MIDWorkflow/RecoWorkflowMC.h" - -#include "DPLUtils/Utils.h" -#include "DPLUtils/MakeRootTreeWriterSpec.h" -#include "SimulationDataFormat/MCTruthContainer.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "DataFormatsMID/ROFRecord.h" -#include "MIDWorkflow/ClusterizerMCSpec.h" -#include "MIDWorkflow/DigitReaderSpec.h" -#include "MIDWorkflow/TrackerMCSpec.h" -#include "MIDSimulation/MCClusterLabel.h" - -namespace of = o2::framework; - -namespace o2 -{ -namespace mid -{ - -of::WorkflowSpec getRecoWorkflowMC() -{ - - auto checkReady = [](o2::framework::DataRef const& ref) { - // The default checkReady function is not defined in MakeRootTreeWriterSpec: - // this leads to a std::exception in DPL. - // While the exception seems harmless (the processing goes on without apparent consequence), - // it is quite ugly to see. - // So, let us define checkReady here. - // FIXME: to be fixed in MakeRootTreeWriterSpec - return false; - }; - - of::WorkflowSpec specs; - - specs.emplace_back(getDigitReaderSpec(true)); - specs.emplace_back(getClusterizerMCSpec()); - specs.emplace_back(getTrackerMCSpec()); - specs.emplace_back(of::MakeRootTreeWriterSpec("MIDTrackLabelsWriter", - "mid-track-labels.root", - "midtracklabels", - of::MakeRootTreeWriterSpec::TerminationPolicy::Workflow, - of::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_tracks", "MID", "TRACKS"}, "MIDTrack"}, - of::MakeRootTreeWriterSpec::BranchDefinition<const char*>{of::InputSpec{"mid_trackClusters", "MID", "TRACKCLUSTERS"}, "MIDTrackClusters"}, - of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_tracks_rof", "MID", "TRACKSROF"}, "MIDTrackROF"}, - of::MakeRootTreeWriterSpec::BranchDefinition<std::vector<ROFRecord>>{of::InputSpec{"mid_trclus_rof", "MID", "TRCLUSROF"}, "MIDTrackClusterROF"}, - of::MakeRootTreeWriterSpec::BranchDefinition<dataformats::MCTruthContainer<MCCompLabel>>{of::InputSpec{"mid_track_labels", "MID", "TRACKSLABELS"}, "MIDTrackLabels"}, - of::MakeRootTreeWriterSpec::BranchDefinition<dataformats::MCTruthContainer<MCClusterLabel>>{of::InputSpec{"mid_trclus_labels", "MID", "TRCLUSLABELS"}, "MIDTrackClusterLabels"})()); - - return specs; -} -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/digits-reader-workflow.cxx b/Detectors/MUON/MID/Workflow/src/digits-reader-workflow.cxx new file mode 100644 index 0000000000000..fed38802c2c04 --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/digits-reader-workflow.cxx @@ -0,0 +1,52 @@ +// 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 MID/Workflow/src/digits-reader-workflow.cxx +/// \brief MID digits reader workflow +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 23 October 2020 + +#include <string> +#include <vector> +#include "Framework/Variant.h" +#include "Framework/ConfigParamSpec.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "DataFormatsMID/ColumnData.h" +#include "DataFormatsMID/ROFRecord.h" +#include "MIDSimulation/MCLabel.h" +#include "MIDWorkflow/DigitReaderSpec.h" +#include "MIDWorkflow/ZeroSuppressionSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"disable-mc", VariantType::Bool, false, {"Do not propagate MC info"}}, + {"disable-zero-suppression", VariantType::Bool, false, {"Do not apply zero suppression"}}}; + workflowOptions.insert(workflowOptions.end(), options.begin(), options.end()); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + bool disableZS = cfgc.options().get<bool>("disable-zero-suppression"); + bool useMC = !cfgc.options().get<bool>("disable-mc"); + + WorkflowSpec specs; + specs.emplace_back(o2::mid::getDigitReaderSpec(useMC, disableZS ? "DATA" : "DATAMC")); + if (!disableZS) { + specs.emplace_back(o2::mid::getZeroSuppressionSpec(useMC)); + } + + return specs; +} diff --git a/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx b/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx new file mode 100644 index 0000000000000..b3ed220b29178 --- /dev/null +++ b/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx @@ -0,0 +1,77 @@ +// 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 MID/Workflow/src/reco-workflow.cxx +/// \brief MID reconstruction workflow from digits +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 23 October 2020 + +#include <array> +#include <string> +#include <vector> +#include "Framework/Variant.h" +#include "Framework/ConfigParamSpec.h" +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "DataFormatsMID/ROFRecord.h" +#include "MIDSimulation/MCClusterLabel.h" +#include "MIDWorkflow/ClusterizerMCSpec.h" +#include "MIDWorkflow/ClusterizerSpec.h" +#include "MIDWorkflow/TrackerMCSpec.h" +#include "MIDWorkflow/TrackerSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> + options{ + {"mc", VariantType::Bool, false, {"Propagate labels"}}, + {"disable-tracking", VariantType::Bool, false, {"Only run clustering"}}, + {"disable-output-file", VariantType::Bool, false, {"Do not write output to file"}}}; + workflowOptions.insert(workflowOptions.end(), options.begin(), options.end()); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + bool isMC = cfgc.options().get<bool>("mc"); + bool disableTracking = cfgc.options().get<bool>("disable-tracking"); + bool disableFile = cfgc.options().get<bool>("disable-output-file"); + + WorkflowSpec specs; + specs.emplace_back(isMC ? o2::mid::getClusterizerMCSpec() : o2::mid::getClusterizerSpec()); + if (!disableTracking) { + specs.emplace_back(isMC ? o2::mid::getTrackerMCSpec() : o2::mid::getTrackerSpec()); + } + if (!disableFile) { + std::array<o2::header::DataDescription, 2> clusterDescriptions{"CLUSTERS", "TRACKCLUSTERS"}; + std::array<o2::header::DataDescription, 2> clusterROFDescriptions{"CLUSTERSROF", "TRCLUSROF"}; + std::array<o2::header::DataDescription, 2> clusterLabelDescriptions{"CLUSTERSLABELS", "TRCLUSLABELS"}; + std::array<std::string, 2> clusterBranch{"MIDCluster", "MIDTrackCluster"}; + std::array<std::string, 2> clusterROFBranch{"MIDClusterROF", "MIDTrackClusterROF"}; + std::array<std::string, 2> clusterLabelBranch{"MIDClusterLabels", "MIDTrackClusterLabels"}; + int idx = disableTracking ? 0 : 1; + specs.emplace_back(MakeRootTreeWriterSpec("MIDRecoWriter", + "mid-reco.root", + "midreco", + MakeRootTreeWriterSpec::BranchDefinition<const char*>{InputSpec{"mid_tracks", o2::header::gDataOriginMID, "TRACKS"}, "MIDTrack", disableTracking ? 0 : 1}, + MakeRootTreeWriterSpec::BranchDefinition<const char*>{InputSpec{"mid_trackClusters", o2::header::gDataOriginMID, clusterDescriptions[idx]}, clusterBranch[idx]}, + MakeRootTreeWriterSpec::BranchDefinition<std::vector<o2::mid::ROFRecord>>{InputSpec{"mid_tracks_rof", o2::header::gDataOriginMID, "TRACKSROF"}, "MIDTrackROF", disableTracking ? 0 : 1}, + MakeRootTreeWriterSpec::BranchDefinition<std::vector<o2::mid::ROFRecord>>{InputSpec{"mid_trclus_rof", o2::header::gDataOriginMID, clusterROFDescriptions[idx]}, clusterROFBranch[idx]}, + MakeRootTreeWriterSpec::BranchDefinition<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>{InputSpec{"mid_track_labels", o2::header::gDataOriginMID, "TRACKSLABELS"}, "MIDTrackLabels", (disableTracking || !isMC) ? 0 : 1}, + MakeRootTreeWriterSpec::BranchDefinition<o2::dataformats::MCTruthContainer<o2::mid::MCClusterLabel>>{InputSpec{"mid_trclus_labels", o2::header::gDataOriginMID, clusterLabelDescriptions[idx]}, clusterLabelBranch[idx], (!isMC) ? 0 : 1})()); + } + + return specs; +} From 73cbeba02032786fab4d9fb7dd3b5c8c443774da Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@cern.ch> Date: Mon, 2 Nov 2020 17:38:20 +0100 Subject: [PATCH 1191/1751] Update README.md --- Detectors/MUON/MID/Workflow/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/MUON/MID/Workflow/README.md b/Detectors/MUON/MID/Workflow/README.md index 391d981567ce8..d31d57eaed032 100644 --- a/Detectors/MUON/MID/Workflow/README.md +++ b/Detectors/MUON/MID/Workflow/README.md @@ -5,7 +5,7 @@ # MID reconstruction workflow The MID reconstruction starts from the digits and produced MID tracks. -The input digits cna be: +The input digits can be: - MC digits - digits obtained after decoding raw data From 969f481c56461c42ca9d5caa8b378b84360d54ad Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 3 Nov 2020 13:26:30 +0100 Subject: [PATCH 1192/1751] moving StepTHn to AnalysisTools folder (#4743) --- Analysis/Core/CMakeLists.txt | 8 +++----- Analysis/Core/src/AnalysisCoreLinkDef.h | 8 -------- Analysis/Core/src/CorrelationContainer.cxx | 2 +- Analysis/Tasks/PWGCF/correlations.cxx | 2 +- Analysis/Tasks/PWGCF/correlationsFiltered.cxx | 2 +- Analysis/Tasks/PWGCF/correlationsMixed.cxx | 2 +- Framework/AnalysisTools/CMakeLists.txt | 17 +++++++++++++++++ .../include/Framework}/StepTHn.h | 0 .../AnalysisTools/src/AnalysisToolsLinkDef.h | 19 +++++++++++++++++++ .../AnalysisTools}/src/StepTHn.cxx | 2 +- Framework/CMakeLists.txt | 1 + 11 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 Framework/AnalysisTools/CMakeLists.txt rename {Analysis/Core/include/Analysis => Framework/AnalysisTools/include/Framework}/StepTHn.h (100%) create mode 100644 Framework/AnalysisTools/src/AnalysisToolsLinkDef.h rename {Analysis/Core => Framework/AnalysisTools}/src/StepTHn.cxx (99%) diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index d6dca70436d7e..63d608698c184 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -9,19 +9,17 @@ # submit itself to any jurisdiction. o2_add_library(AnalysisCore - SOURCES src/StepTHn.cxx - src/CorrelationContainer.cxx + SOURCES src/CorrelationContainer.cxx src/TrackSelection.cxx src/VarManager.cxx src/HistogramManager.cxx src/AnalysisCut.cxx src/AnalysisCompositeCut.cxx src/TriggerAliases.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel) + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisTools) o2_target_root_dictionary(AnalysisCore - HEADERS include/Analysis/StepTHn.h - include/Analysis/CorrelationContainer.h + HEADERS include/Analysis/CorrelationContainer.h include/Analysis/TrackSelection.h include/Analysis/TrackSelectionDefaults.h include/Analysis/VarManager.h diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index e54a820e13beb..ed2833df8a9f0 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -12,12 +12,6 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class StepTHn + ; -#pragma link C++ class StepTHnT < TArrayF> + ; -#pragma link C++ class StepTHnT < TArrayD> + ; -#pragma link C++ typedef StepTHnF; -#pragma link C++ typedef StepTHnD; - #pragma link C++ class CorrelationContainer + ; #pragma link C++ class TrackSelection + ; #pragma link C++ class TriggerAliases + ; @@ -26,5 +20,3 @@ #pragma link C++ class HistogramManager + ; #pragma link C++ class AnalysisCut + ; #pragma link C++ class AnalysisCompositeCut + ; - -// #pragma link C++ class JetFinder+; diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 183651d700b76..5a38a00167200 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -14,7 +14,7 @@ // Author: Jan Fiete Grosse-Oetringhaus #include "Analysis/CorrelationContainer.h" -#include "Analysis/StepTHn.h" +#include "Framework/StepTHn.h" #include "THnSparse.h" #include "TMath.h" #include "TList.h" diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index a0e9fa53322cd..bdfce0e96a85c 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -12,11 +12,11 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include <CCDB/BasicCCDBManager.h> +#include "Framework/StepTHn.h" #include "Analysis/EventSelection.h" #include "Analysis/TrackSelectionTables.h" #include "Analysis/Centrality.h" -#include "Analysis/StepTHn.h" #include "Analysis/CorrelationContainer.h" #include "Analysis/PairCuts.h" diff --git a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx index dfe2bdd13c8b1..b09d256cc79e8 100644 --- a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx +++ b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx @@ -11,11 +11,11 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/StepTHn.h" #include "Analysis/EventSelection.h" #include "Analysis/TrackSelectionTables.h" #include "Analysis/Centrality.h" -#include "Analysis/StepTHn.h" #include "Analysis/CorrelationContainer.h" #include "Analysis/CFDerived.h" diff --git a/Analysis/Tasks/PWGCF/correlationsMixed.cxx b/Analysis/Tasks/PWGCF/correlationsMixed.cxx index 62251eefb73c1..529dd9eba04fa 100644 --- a/Analysis/Tasks/PWGCF/correlationsMixed.cxx +++ b/Analysis/Tasks/PWGCF/correlationsMixed.cxx @@ -11,10 +11,10 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/StepTHn.h" #include "Analysis/EventSelection.h" #include "Analysis/Centrality.h" -#include "Analysis/StepTHn.h" #include "Analysis/CorrelationContainer.h" #include "Analysis/TrackSelectionTables.h" diff --git a/Framework/AnalysisTools/CMakeLists.txt b/Framework/AnalysisTools/CMakeLists.txt new file mode 100644 index 0000000000000..17a188a04298b --- /dev/null +++ b/Framework/AnalysisTools/CMakeLists.txt @@ -0,0 +1,17 @@ +# 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_library(AnalysisTools + SOURCES src/StepTHn.cxx + PUBLIC_LINK_LIBRARIES O2::Framework) + +o2_target_root_dictionary(AnalysisTools + HEADERS include/Framework/StepTHn.h + LINKDEF src/AnalysisToolsLinkDef.h) diff --git a/Analysis/Core/include/Analysis/StepTHn.h b/Framework/AnalysisTools/include/Framework/StepTHn.h similarity index 100% rename from Analysis/Core/include/Analysis/StepTHn.h rename to Framework/AnalysisTools/include/Framework/StepTHn.h diff --git a/Framework/AnalysisTools/src/AnalysisToolsLinkDef.h b/Framework/AnalysisTools/src/AnalysisToolsLinkDef.h new file mode 100644 index 0000000000000..368cb36e4b745 --- /dev/null +++ b/Framework/AnalysisTools/src/AnalysisToolsLinkDef.h @@ -0,0 +1,19 @@ +// 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. + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class StepTHn + ; +#pragma link C++ class StepTHnT < TArrayF> + ; +#pragma link C++ class StepTHnT < TArrayD> + ; +#pragma link C++ typedef StepTHnF; +#pragma link C++ typedef StepTHnD; diff --git a/Analysis/Core/src/StepTHn.cxx b/Framework/AnalysisTools/src/StepTHn.cxx similarity index 99% rename from Analysis/Core/src/StepTHn.cxx rename to Framework/AnalysisTools/src/StepTHn.cxx index 30d1b16d93305..8e99d3cac4db9 100644 --- a/Analysis/Core/src/StepTHn.cxx +++ b/Framework/AnalysisTools/src/StepTHn.cxx @@ -17,7 +17,7 @@ // // Templated version allows also the use of double as storage container -#include "Analysis/StepTHn.h" +#include "Framework/StepTHn.h" #include "TList.h" #include "TCollection.h" #include "TArrayF.h" diff --git a/Framework/CMakeLists.txt b/Framework/CMakeLists.txt index fefcb8488ba4e..17b18bebad581 100644 --- a/Framework/CMakeLists.txt +++ b/Framework/CMakeLists.txt @@ -18,3 +18,4 @@ add_subdirectory(Utils) add_subdirectory(TestWorkflows) +add_subdirectory(AnalysisTools) From 7b4592364cab2074645a3f76b9a188801be66324 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Tue, 3 Nov 2020 12:30:52 +0300 Subject: [PATCH 1193/1751] Detectors/TRD: make readability-braces-around-statements happy --- .../TRD/base/include/TRDBase/PadParameters.h | 14 +- .../base/include/TRDBase/TRDGeometryFlat.h | 3 +- .../TRD/base/include/TRDBase/TRDPadPlane.h | 31 ++- Detectors/TRD/base/src/CalDet.cxx | 18 +- .../TRD/base/src/CalOnlineGainTables.cxx | 3 +- Detectors/TRD/base/src/CalROC.cxx | 35 +-- Detectors/TRD/base/src/Calibrations.cxx | 63 +++-- Detectors/TRD/base/src/ChamberStatus.cxx | 24 +- Detectors/TRD/base/src/FeeParam.cxx | 81 +++--- Detectors/TRD/base/src/PadResponse.cxx | 3 +- Detectors/TRD/base/src/TRDCommonParam.cxx | 15 +- .../src/TRDDiffAndTimeStructEstimator.cxx | 9 +- Detectors/TRD/base/src/TRDGeometry.cxx | 3 +- Detectors/TRD/base/src/TRDGeometryBase.cxx | 15 +- .../include/TRDSimulation/TrapConfig.h | 3 +- .../include/TRDSimulation/TrapSimulator.h | 6 +- Detectors/TRD/simulation/src/TrapConfig.cxx | 35 +-- .../TRD/simulation/src/TrapConfigHandler.cxx | 44 ++-- .../TRD/simulation/src/TrapSimulator.cxx | 234 +++++++++++------- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 47 ++-- 20 files changed, 432 insertions(+), 254 deletions(-) diff --git a/Detectors/TRD/base/include/TRDBase/PadParameters.h b/Detectors/TRD/base/include/TRDBase/PadParameters.h index 56168216caf12..7743e20a9ebeb 100644 --- a/Detectors/TRD/base/include/TRDBase/PadParameters.h +++ b/Detectors/TRD/base/include/TRDBase/PadParameters.h @@ -72,15 +72,17 @@ int PadParameters<T>::init(int chamberindex) { mPlane = TRDGeometry::getLayer(chamberindex); mChamber = TRDGeometry::getStack(chamberindex); - if (mChamber == 2) + if (mChamber == 2) { mNrows = constants::NROWC0; - else + } else { mNrows = constants::NROWC1; + } // the FeeParam variables need to be unprotected, and dont want to change FeeParam in this PR. mNchannels = mNrows * mNcols; mData.resize(mNchannels); - if (mData.size() != mNchannels || mData.size() == 0) + if (mData.size() != mNchannels || mData.size() == 0) { return -1; + } return 0; } @@ -93,11 +95,13 @@ int PadParameters<T>::reset(int chamberindex, int cols, int rows, std::vector<T> mNcols = cols; // the FeeParam variables need to be unprotected, and dont want to change FeeParam in this PR. mNchannels = mNrows * mNcols; - if (mData.size() != mNchannels) + if (mData.size() != mNchannels) { return -2; + } mData.resize(mNchannels); - if (mData.size() != mNchannels || mData.size() == 0) + if (mData.size() != mNchannels || mData.size() == 0) { return -1; + } // now reset the data of the pads. int counter = 0; diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h index 54b82c5757815..8e5ae76b6ff0d 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h +++ b/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h @@ -46,8 +46,9 @@ class TRDGeometryFlat : public o2::gpu::FlatObject, public TRDGeometryBase #endif GPUd() const o2::gpu::Transform3D* getMatrixT2L(int det) const { - if (mMatrixIndirection[det] == -1) + if (mMatrixIndirection[det] == -1) { return nullptr; + } return &mMatrixCache[mMatrixIndirection[det]]; ; } diff --git a/Detectors/TRD/base/include/TRDBase/TRDPadPlane.h b/Detectors/TRD/base/include/TRDBase/TRDPadPlane.h index 130483dae6f16..8ac893a2ffa25 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDPadPlane.h +++ b/Detectors/TRD/base/include/TRDBase/TRDPadPlane.h @@ -49,13 +49,15 @@ class TRDPadPlane void setNrows(int n); void setPadCol(int ic, double c) { - if (ic < mNcols) + if (ic < mNcols) { mPadCol[ic] = c; + } }; void setPadRow(int ir, double r) { - if (ir < mNrows) + if (ir < mNrows) { mPadRow[ir] = r; + } }; void setLength(double l) { mLength = l; }; void setWidth(double w) { mWidth = w; }; @@ -74,25 +76,28 @@ class TRDPadPlane GPUd() double getTiltOffset(double rowOffset) const { return mTiltingTan * (rowOffset - 0.5 * mLengthIPad); }; GPUd() double getPadRowOffset(int row, double z) const { - if ((row < 0) || (row >= mNrows)) + if ((row < 0) || (row >= mNrows)) { return -1.0; - else + } else { return mPadRow[row] + mPadRowSMOffset - z; + } }; GPUd() double getPadRowOffsetROC(int row, double z) const { - if ((row < 0) || (row >= mNrows)) + if ((row < 0) || (row >= mNrows)) { return -1.0; - else + } else { return mPadRow[row] - z; + } }; GPUd() double getPadColOffset(int col, double rphi) const { - if ((col < 0) || (col >= mNcols)) + if ((col < 0) || (col >= mNcols)) { return -1.0; - else + } else { return rphi - mPadCol[col]; + } }; GPUd() double getTiltingAngle() const { return mTiltingAngle; }; @@ -109,17 +114,19 @@ class TRDPadPlane GPUd() double getColPos(int col) const { return mPadCol[col]; }; GPUd() double getRowSize(int row) const { - if ((row == 0) || (row == mNrows - 1)) + if ((row == 0) || (row == mNrows - 1)) { return mLengthOPad; - else + } else { return mLengthIPad; + } }; GPUd() double getColSize(int col) const { - if ((col == 0) || (col == mNcols - 1)) + if ((col == 0) || (col == mNcols - 1)) { return mWidthOPad; - else + } else { return mWidthIPad; + } }; GPUd() double getLengthRim() const { return mLengthRim; }; diff --git a/Detectors/TRD/base/src/CalDet.cxx b/Detectors/TRD/base/src/CalDet.cxx index bb0ffc10f85d6..9923bbbd82dc9 100644 --- a/Detectors/TRD/base/src/CalDet.cxx +++ b/Detectors/TRD/base/src/CalDet.cxx @@ -116,10 +116,12 @@ double CalDet::getRMSRobust(double robust) const for (int i = 0; i < MAXCHAMBER; i++) { bool rej = kFALSE; for (int k = 0; k < reject; k++) { - if (i == index[k]) + if (i == index[k]) { rej = kTRUE; - if (i == index[MAXCHAMBER - (k + 1)]) + } + if (i == index[MAXCHAMBER - (k + 1)]) { rej = kTRUE; + } } if (!rej) { ddata[nPoints] = mData[i]; @@ -142,20 +144,24 @@ double CalDet::getMeanRobust(double robust) const // reject double reject = (int)(MAXCHAMBER * (1 - robust) / 2.0); - if (reject <= 0) + if (reject <= 0) { reject = 0; - if (reject >= MAXCHAMBER) + } + if (reject >= MAXCHAMBER) { reject = 0; + } std::array<double, MAXCHAMBER> ddata; int nPoints = 0; for (int i = 0; i < MAXCHAMBER; i++) { bool rej = kFALSE; for (int k = 0; k < reject; k++) { - if (i == index[k]) + if (i == index[k]) { rej = kTRUE; - if (i == index[MAXCHAMBER - (k + 1)]) + } + if (i == index[MAXCHAMBER - (k + 1)]) { rej = kTRUE; + } } if (!rej) { ddata[nPoints] = mData[i]; diff --git a/Detectors/TRD/base/src/CalOnlineGainTables.cxx b/Detectors/TRD/base/src/CalOnlineGainTables.cxx index 4d01a770608ba..31b15418542e8 100644 --- a/Detectors/TRD/base/src/CalOnlineGainTables.cxx +++ b/Detectors/TRD/base/src/CalOnlineGainTables.cxx @@ -59,8 +59,9 @@ float CalOnlineGainTables::getGainCorrectionFactor(int det, int row, int col) co GainCorrectionFactor = -1.0; } else if (mGainTable[arrayoffset].mFGFN[channel] > 511) { GainCorrectionFactor = CalOnlineGainTables::UnDef; - } else + } else { GainCorrectionFactor = (mGainTable[arrayoffset].mFGFN[channel] / 2048.) + 0.875; + } } else { float ADCCorrection = (1. / (1. + ((float)mGainTable[arrayoffset].mAdcdac / 31.) * 0.4 / 1.05)); GainCorrectionFactor = ADCCorrection * (((mGainTable[arrayoffset].mFGFN[channel]) / 2048.) + 0.875); diff --git a/Detectors/TRD/base/src/CalROC.cxx b/Detectors/TRD/base/src/CalROC.cxx index 4e9f0924e0d4d..7c52cba96daa3 100644 --- a/Detectors/TRD/base/src/CalROC.cxx +++ b/Detectors/TRD/base/src/CalROC.cxx @@ -247,9 +247,9 @@ bool CalROC::add(float c1) bool result = true; for (int idata = 0; idata < mNchannels; idata++) { - if (((getValue(idata) + c1) <= 6.5535) && ((getValue(idata) + c1) >= 0.0)) + if (((getValue(idata) + c1) <= 6.5535) && ((getValue(idata) + c1) >= 0.0)) { setValue(idata, getValue(idata) + c1); - else { + } else { setValue(idata, 0.0); result = false; } @@ -265,12 +265,13 @@ bool CalROC::multiply(float c1) // bool result = true; - if (c1 < 0) + if (c1 < 0) { return false; + } for (int idata = 0; idata < mNchannels; idata++) { - if ((getValue(idata) * c1) <= 6.5535) + if ((getValue(idata) * c1) <= 6.5535) { setValue(idata, getValue(idata) * c1); - else { + } else { setValue(idata, 0.0); result = false; } @@ -288,9 +289,9 @@ bool CalROC::add(const CalROC* roc, double c1) bool result = true; for (int idata = 0; idata < mNchannels; idata++) { if (((getValue(idata) + roc->getValue(idata) * c1) <= 6.5535) && - ((getValue(idata) + roc->getValue(idata) * c1) >= 0.0)) + ((getValue(idata) + roc->getValue(idata) * c1) >= 0.0)) { setValue(idata, getValue(idata) + roc->getValue(idata) * c1); - else { + } else { setValue(idata, 0.0); result = false; } @@ -307,9 +308,9 @@ bool CalROC::multiply(const CalROC* roc) bool result = true; for (int idata = 0; idata < mNchannels; idata++) { - if ((getValue(idata) * roc->getValue(idata)) <= 6.5535) + if ((getValue(idata) * roc->getValue(idata)) <= 6.5535) { setValue(idata, getValue(idata) * roc->getValue(idata)); - else { + } else { setValue(idata, 0.0); result = false; } @@ -328,9 +329,9 @@ bool CalROC::divide(const CalROC* roc) float eps = 0.00000000000000001; for (int idata = 0; idata < mNchannels; idata++) { if (TMath::Abs(roc->getValue(idata)) > eps) { - if ((getValue(idata) / roc->getValue(idata)) <= 6.5535) + if ((getValue(idata) / roc->getValue(idata)) <= 6.5535) { setValue(idata, getValue(idata) / roc->getValue(idata)); - else { + } else { setValue(idata, 0.0); result = false; } @@ -401,8 +402,9 @@ TH2F* CalROC::makeHisto2D(float min, float max, int type, float mu) float sigma = getRMS(); float nsigma = TMath::Abs(min); sigma *= nsigma; - if (sigma < epsr) + if (sigma < epsr) { sigma = epsr; + } min = mean - sigma; max = mean + sigma; } @@ -417,8 +419,9 @@ TH2F* CalROC::makeHisto2D(float min, float max, int type, float mu) double sigma; float mean = getLTM(&sigma, max); sigma *= min; - if (sigma < epsr) + if (sigma < epsr) { sigma = epsr; + } min = mean - sigma; max = mean + sigma; } @@ -455,8 +458,9 @@ TH1F* CalROC::makeHisto1D(float min, float max, int type, float mu) float sigma = getRMS(); float nsigma = TMath::Abs(min); sigma *= nsigma; - if (sigma < epsr) + if (sigma < epsr) { sigma = epsr; + } min = mean - sigma; max = mean + sigma; } @@ -474,8 +478,9 @@ TH1F* CalROC::makeHisto1D(float min, float max, int type, float mu) double sigma; float mean = getLTM(&sigma, max); sigma *= min; - if (sigma < epsr) + if (sigma < epsr) { sigma = epsr; + } min = mean - sigma; max = mean + sigma; } diff --git a/Detectors/TRD/base/src/Calibrations.cxx b/Detectors/TRD/base/src/Calibrations.cxx index 022e4407771eb..64a45c7ab116a 100644 --- a/Detectors/TRD/base/src/Calibrations.cxx +++ b/Detectors/TRD/base/src/Calibrations.cxx @@ -48,29 +48,37 @@ void Calibrations::setCCDB(int calibrationobjecttype, long timestamp) switch (calibrationobjecttype) { case 1: //simulation mChamberCalibrations = ccdbmgr.get<o2::trd::ChamberCalibrations>("TRD_test/ChamberCalibrations"); - if (!mChamberCalibrations) + if (!mChamberCalibrations) { LOG(fatal) << "No chamber calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } mLocalVDrift = ccdbmgr.get<o2::trd::LocalVDrift>("TRD_test/LocalVDrift"); - if (!mLocalVDrift) + if (!mLocalVDrift) { LOG(fatal) << "No Local V Drift calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } mLocalT0 = ccdbmgr.get<o2::trd::LocalT0>("TRD_test/LocalT0"); - if (!mLocalT0) + if (!mLocalT0) { LOG(fatal) << "No Local T0 calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } mLocalGainFactor = ccdbmgr.get<o2::trd::LocalGainFactor>("TRD_test/LocalGainFactor"); - if (!mLocalT0) + if (!mLocalT0) { LOG(fatal) << "No Local T0 calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } mPadNoise = ccdbmgr.get<o2::trd::PadNoise>("TRD_test/PadNoise"); - if (!mPadNoise) + if (!mPadNoise) { LOG(fatal) << "No Padnoise calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } mChamberStatus = ccdbmgr.get<o2::trd::ChamberStatus>("TRD_test/ChamberStatus"); - if (!mChamberStatus) + if (!mChamberStatus) { LOG(fatal) << "No ChamberStatus calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } mPadStatus = ccdbmgr.get<o2::trd::PadStatus>("TRD_test/PadStatus"); - if (!mPadStatus) + if (!mPadStatus) { LOG(fatal) << "No Pad Status calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } mChamberNoise = ccdbmgr.get<o2::trd::ChamberNoise>("TRD_test/ChamberNoise"); - if (!mChamberNoise) + if (!mChamberNoise) { LOG(fatal) << "No ChamberNoise calibrations returned from CCDB for TRD calibrations, or TRD from what ever you are running."; + } //mCalOnlineGainTables= ccdbmgr.get<o2::trd::CalOnlineGainTables>("TRD_test/OnlineGainTables"); //std::shared_ptr<TrapConfig> mTrapConfig; //std::shared_ptr<PRFWidth> mPRDWidth @@ -101,62 +109,69 @@ void Calibrations::setOnlineGainTables(std::string& tablename) double Calibrations::getVDrift(int det, int col, int row) const { - if (mChamberCalibrations && mLocalVDrift) + if (mChamberCalibrations && mLocalVDrift) { return (double)mChamberCalibrations->getVDrift(det) * (double)mLocalVDrift->getValue(det, col, row); - else + } else { return -1; + } } double Calibrations::getT0(int det, int col, int row) const { - if (mChamberCalibrations && mLocalT0) + if (mChamberCalibrations && mLocalT0) { return (double)mChamberCalibrations->getT0(det) + (double)mLocalT0->getValue(det, col, row); - else { + } else { return -1; } } double Calibrations::getExB(int det) const { - if (mChamberCalibrations) + if (mChamberCalibrations) { return (double)mChamberCalibrations->getExB(det); - else + } else { return -1; + } } double Calibrations::getGainFactor(int det, int col, int row) const { - if (mChamberCalibrations && mLocalGainFactor) + if (mChamberCalibrations && mLocalGainFactor) { return (double)mChamberCalibrations->getGainFactor(det) * (double)mLocalGainFactor->getValue(det, col, row); - else + } else { return -1; + } } double Calibrations::getPadGainFactor(int det, int col, int row) const { - if (mLocalGainFactor) + if (mLocalGainFactor) { return (double)mLocalGainFactor->getValue(det, col, row); - else + } else { return -1; + } } double Calibrations::getOnlineGainAdcdac(int det, int row, int mcm) const { - if (mCalOnlineGainTables) + if (mCalOnlineGainTables) { return mCalOnlineGainTables->getAdcdacrm(det, row, mcm); - else + } else { return -1; + } } double Calibrations::getOnlineGainFGAN(int det, int rob, int mcm, int adc) const { - if (mCalOnlineGainTables) + if (mCalOnlineGainTables) { return mCalOnlineGainTables->getFGANrm(det, rob, mcm, adc); - else + } else { return -1; + } } double Calibrations::getOnlineGainFGFN(int det, int rob, int mcm, int adc) const { - if (mCalOnlineGainTables) + if (mCalOnlineGainTables) { return mCalOnlineGainTables->getFGFNrm(det, rob, mcm, adc); - else + } else { return -1; + } } diff --git a/Detectors/TRD/base/src/ChamberStatus.cxx b/Detectors/TRD/base/src/ChamberStatus.cxx index f7694bb8c1c6b..46e0a1a83ced0 100644 --- a/Detectors/TRD/base/src/ChamberStatus.cxx +++ b/Detectors/TRD/base/src/ChamberStatus.cxx @@ -130,11 +130,13 @@ TH2D* ChamberStatus::plot(int sm, int rphi) int status = getStatus(i); h2->Fill(stackn, layer, status); if (rphi == 0) { - if (!(mStatus[i] & kNoDataHalfChamberSideBpat)) + if (!(mStatus[i] & kNoDataHalfChamberSideBpat)) { h2->Fill(stackn, layer, status); + } } else if (rphi == 1) { - if (!(mStatus[i] & kNoDataHalfChamberSideApat)) + if (!(mStatus[i] & kNoDataHalfChamberSideApat)) { h2->Fill(stackn, layer, status); + } } } @@ -161,15 +163,19 @@ TH2D* ChamberStatus::plotNoData(int sm, int rphi) int layer = i % 6; int stackn = static_cast<int>((i - start) / 6.); if (rphi == 0) { - if (mStatus[i] & kNoDataHalfChamberSideBpat) + if (mStatus[i] & kNoDataHalfChamberSideBpat) { h2->Fill(stackn, layer, 1); - if (mStatus[i] & kNoDatapat) + } + if (mStatus[i] & kNoDatapat) { h2->Fill(stackn, layer, 1); + } } else if (rphi == 1) { - if (!(mStatus[i] & kNoDataHalfChamberSideApat)) + if (!(mStatus[i] & kNoDataHalfChamberSideApat)) { h2->Fill(stackn, layer, 1); - if (!(mStatus[i] & kNoDatapat)) + } + if (!(mStatus[i] & kNoDatapat)) { h2->Fill(stackn, layer, 1); + } } } @@ -196,11 +202,13 @@ TH2D* ChamberStatus::plotBadCalibrated(int sm, int rphi) int layer = i % 6; int stackn = static_cast<int>((i - start) / 6.); if (rphi == 0) { - if (mStatus[i] & kBadCalibratedpat) + if (mStatus[i] & kBadCalibratedpat) { h2->Fill(stackn, layer, 1); + } } else if (rphi == 1) { - if (mStatus[i] & kBadCalibratedpat) + if (mStatus[i] & kBadCalibratedpat) { h2->Fill(stackn, layer, 1); + } } } diff --git a/Detectors/TRD/base/src/FeeParam.cxx b/Detectors/TRD/base/src/FeeParam.cxx index c4eb5f5f36e27..1a539e8780079 100644 --- a/Detectors/TRD/base/src/FeeParam.cxx +++ b/Detectors/TRD/base/src/FeeParam.cxx @@ -96,8 +96,9 @@ FeeParam* FeeParam::instance() mgInstance = new FeeParam(); } // this is moved here to remove recursive calls induced by the line 2 above this one. - if (!mgLUTPadNumberingFilled) + if (!mgLUTPadNumberingFilled) { mgInstance->createPad2MCMLookUpTable(); + } return mgInstance; } @@ -160,8 +161,9 @@ FeeParam::FeeParam(const FeeParam& p) // mRAWversion = p.mRAWversion; mCP = p.mCP; - if (!mgLUTPadNumberingFilled) + if (!mgLUTPadNumberingFilled) { mgInstance->createPad2MCMLookUpTable(); + } } //_____________________________________________________________________________ @@ -218,8 +220,9 @@ int FeeParam::getPadColFromADC(int irob, int imcm, int iadc) const // http://wiki.kip.uni-heidelberg.de/ti/TRD/index.php/Image:ROB_MCM_numbering.pdf // - if (iadc < 0 || iadc > NADCMCM) + if (iadc < 0 || iadc > NADCMCM) { return -100; + } int mcmcol = imcm % NMCMROBINCOL + getRobSide(irob) * NMCMROBINCOL; // MCM column number on ROC [0..7] int padcol = mcmcol * NCOLMCM + NCOLMCM + 1 - iadc; if (padcol < 0 || padcol >= NCOLUMN) { @@ -237,8 +240,9 @@ int FeeParam::getExtendedPadColFromADC(int irob, int imcm, int iadc) const // so we have to introduce new virtual pad numbering scheme for this purpose. // - if (iadc < 0 || iadc > NADCMCM) + if (iadc < 0 || iadc > NADCMCM) { return -100; + } int mcmcol = imcm % NMCMROBINCOL + getRobSide(irob) * NMCMROBINCOL; // MCM column number on ROC [0..7] int padcol = mcmcol * NADCMCM + NCOLMCM + 2 - iadc; @@ -253,8 +257,9 @@ int FeeParam::getMCMfromPad(int irow, int icol) const // Return -1 for error. // - if (irow < 0 || icol < 0 || irow > NROWC1 || icol > NCOLUMN) + if (irow < 0 || icol < 0 || irow > NROWC1 || icol > NCOLUMN) { return -1; + } return (icol % (NCOLUMN / 2)) / NCOLMCM + NMCMROBINCOL * (irow % NMCMROBINROW); } @@ -266,8 +271,9 @@ int FeeParam::getMCMfromSharedPad(int irow, int icol) const // Return -1 for error. // - if (irow < 0 || icol < 0 || irow > NROWC1 || icol > NCOLUMN + 8 * 3) + if (irow < 0 || icol < 0 || irow > NROWC1 || icol > NCOLUMN + 8 * 3) { return -1; + } int adc = 20 - (icol % 18) - 1; switch (adc) { @@ -318,8 +324,9 @@ int FeeParam::getRobSide(int irob) const // Return on which side this rob sits (A side = 0, B side = 1) // - if (irob < 0 || irob >= NROBC1) + if (irob < 0 || irob >= NROBC1) { return -1; + } return irob % 2; } @@ -331,16 +338,18 @@ int FeeParam::getColSide(int icol) const // Return on which side this column sits (A side = 0, B side = 1) // - if (icol < 0 || icol >= NCOLUMN) + if (icol < 0 || icol >= NCOLUMN) { return -1; + } return icol / (NCOLUMN / 2); } unsigned int FeeParam::aliToExtAli(int rob, int aliid) { - if (aliid != 127) + if (aliid != 127) { return ((1 << 10) | (rob << 7) | aliid); + } return 127; } @@ -411,12 +420,15 @@ int FeeParam::extAliToAli(unsigned int dest, unsigned short linkpair, unsigned s cmA &= gkChipmaskDefLp[linkpair]; cmB &= gkChipmaskDefLp[linkpair]; // Remove if only one side is selected - if (robAB == 1) + if (robAB == 1) { cmB = 0; - if (robAB == 2) + } + if (robAB == 2) { cmA = 0; - if (robAB == 4 && linkpair != 2) + } + if (robAB == 4 && linkpair != 2) { cmA = cmB = 0; // Restrict to only T3A and T3B + } // Finally convert chipmask to list of slaves nmcm = chipmaskToMCMlist(cmA, cmB, linkpair, mcmList, listSize); @@ -430,10 +442,12 @@ short FeeParam::getRobAB(unsigned short robsel, unsigned short linkpair) if ((robsel & 0x8) != 0) { // 1000 .. direct ROB selection. Only one of the 8 ROBs are used. robsel = robsel & 7; - if ((robsel % 2) == 0 && (robsel / 2) == linkpair) + if ((robsel % 2) == 0 && (robsel / 2) == linkpair) { return 1; // Even means A side (position 0,2,4,6) - if ((robsel % 2) == 1 && (robsel / 2) == linkpair) + } + if ((robsel % 2) == 1 && (robsel / 2) == linkpair) { return 2; // Odd means B side (position 1,3,5,7) + } return 0; } @@ -519,11 +533,13 @@ int FeeParam::getORIinSM(int detector, int readoutboard) const if (trdstack > 2 || (trdstack == 2 && side == 1)) // CSide { int newside = side; - if (trdstack == 2) + if (trdstack == 2) { newside = 0; // the last part of C side CRU is a special case. + } ori = (4 - trdstack) * 12 + (5 - trdlayer + newside * 5) + trdlayer / 6 + newside; - } else + } else { LOG(warn) << " something wrong with calculation of ORI for detector " << detector << " and readoutboard" << readoutboard; + } } // now offset for supermodule (+60*supermodule); @@ -625,8 +641,9 @@ int FeeParam::getDyCorrection(int det, int rob, int mcm) const // calculate Lorentz correction float dyCorr = -mOmegaTau * mgDriftLength; - if (mTiltCorr) + if (mTiltCorr) { dyCorr += dyTilt; // add tilt correction + } return (int)TMath::Nint(dyCorr * mgScalePad * mgInvWidthPad[layer]); } @@ -640,8 +657,9 @@ void FeeParam::getDyRange(int det, int rob, int mcm, int ch, dyMaxInt = mgDyMax; // deflection cut is considered for |B| > 0.1 T only - if (std::abs(mMagField) < 0.1) + if (std::abs(mMagField) < 0.1) { return; + } float e = 0.30; @@ -657,20 +675,22 @@ void FeeParam::getDyRange(int det, int rob, int mcm, int ch, dyMinInt = int(dyMin / mgBinDy); // clipping to allowed range - if (dyMinInt < mgDyMin) + if (dyMinInt < mgDyMin) { dyMinInt = mgDyMin; - else if (dyMinInt > mgDyMax) + } else if (dyMinInt > mgDyMax) { dyMinInt = mgDyMax; + } float dyMax = (mgDriftLength * std::tan(phi + maxDeflAngle)); dyMaxInt = int(dyMax / mgBinDy); // clipping to allowed range - if (dyMaxInt > mgDyMax) + if (dyMaxInt > mgDyMax) { dyMaxInt = mgDyMax; - else if (dyMaxInt < mgDyMin) + } else if (dyMaxInt < mgDyMin) { dyMaxInt = mgDyMin; + } } else if (maxDeflTemp < 0.) { // this must not happen printf("Inconsistent calculation of sin(alpha): %f\n", maxDeflTemp); @@ -707,8 +727,9 @@ void FeeParam::getCorrectionFactors(int det, int rob, int mcm, int ch, { // calculate the gain correction factors for the given ADC channel float Invgain = 1.0; - if (mPidGainCorr == true) + if (mPidGainCorr == true) { Invgain = 1 / gain; + } if (mPidTracklengthCorr == true) { float InvElongationOverGain = 1 / getElongation(det, rob, mcm, ch) * Invgain; @@ -754,19 +775,21 @@ float FeeParam::getLocalZ(int det, int rob, int mcm) const int row = (rob / 2) * 4 + mcm / 4; if (stack == 2) { - if (row == 0) + if (row == 0) { return (mgZrow[layer * NLAYER + stack] - 0.5 * mgLengthOuterPadC0); - else if (row == 11) + } else if (row == 11) { return (mgZrow[layer * NLAYER + stack] - 1.5 * mgLengthOuterPadC0 - (row - 1) * mgLengthInnerPadC0); - else + } else { return (mgZrow[layer * NLAYER + stack] - mgLengthOuterPadC0 - (row - 0.5) * mgLengthInnerPadC0); + } } else { - if (row == 0) + if (row == 0) { return (mgZrow[layer * NLAYER + stack] - 0.5 * mgLengthOuterPadC1[layer]); - else if (row == 15) + } else if (row == 15) { return (mgZrow[layer * NLAYER + stack] - 1.5 * mgLengthOuterPadC1[layer] - (row - 1) * mgLengthInnerPadC1[layer]); - else + } else { return (mgZrow[layer * NLAYER + stack] - mgLengthOuterPadC1[layer] - (row - 0.5) * mgLengthInnerPadC1[layer]); + } } } diff --git a/Detectors/TRD/base/src/PadResponse.cxx b/Detectors/TRD/base/src/PadResponse.cxx index 070b007f416d3..c011add451b66 100644 --- a/Detectors/TRD/base/src/PadResponse.cxx +++ b/Detectors/TRD/base/src/PadResponse.cxx @@ -147,8 +147,9 @@ void PadResponse::samplePRF() mPRFsmp[iLayer * mPRFbin + iBin] = prf[iLayer][ipos2 - 1]; } else { --ipos2; - if (ipos2 >= kPRFbin) + if (ipos2 >= kPRFbin) { ipos2 = kPRFbin - 1; + } ipos1 = ipos2 - 1; mPRFsmp[iLayer * mPRFbin + iBin] = prf[iLayer][ipos2] + diff * (prf[iLayer][ipos2] - prf[iLayer][ipos1]) / sPRFwid; } diff --git a/Detectors/TRD/base/src/TRDCommonParam.cxx b/Detectors/TRD/base/src/TRDCommonParam.cxx index 41dc82e340602..c453569edf190 100644 --- a/Detectors/TRD/base/src/TRDCommonParam.cxx +++ b/Detectors/TRD/base/src/TRDCommonParam.cxx @@ -263,13 +263,16 @@ double TRDCommonParam::TimeStruct(float vdrift, double dist, double z) // Indices: int r1 = (int)(10 * dist); - if (r1 < 0) + if (r1 < 0) { r1 = 0; - if (r1 > 37) + } + if (r1 > 37) { r1 = 37; + } int r2 = r1 + 1; - if (r2 > 37) + if (r2 > 37) { r2 = 37; + } const int kz1 = ((int)(100 * z / 2.5)); const int kz2 = kz1 + 1; @@ -678,10 +681,12 @@ void TRDCommonParam::SampleTimeStruct(float vdrift) {1.43524, 1.43533, 1.43796, 1.44310, 1.45371, 1.49305, 1.48224, 1.47941, 1.49034, 1.52601, 1.78552}, {1.48122, 1.48219, 1.48482, 1.48991, 1.50030, 1.53991, 1.52898, 1.52653, 1.53653, 1.57282, 1.82386}}; - if (!mTimeStruct1) + if (!mTimeStruct1) { mTimeStruct1 = new float[ktimebin * kZbin]; - if (!mTimeStruct2) + } + if (!mTimeStruct2) { mTimeStruct2 = new float[ktimebin * kZbin]; + } memset(mTimeStruct1, 0, ktimebin * kZbin * sizeof(float)); memset(mTimeStruct2, 0, ktimebin * kZbin * sizeof(float)); diff --git a/Detectors/TRD/base/src/TRDDiffAndTimeStructEstimator.cxx b/Detectors/TRD/base/src/TRDDiffAndTimeStructEstimator.cxx index d7ef65c81349b..ccecc3fd4fa5f 100644 --- a/Detectors/TRD/base/src/TRDDiffAndTimeStructEstimator.cxx +++ b/Detectors/TRD/base/src/TRDDiffAndTimeStructEstimator.cxx @@ -460,13 +460,16 @@ float TRDDiffusionAndTimeStructEstimator::TimeStruct(float vdrift, float dist, f // Indices: int r1 = (int)(10 * dist); - if (r1 < 0) + if (r1 < 0) { r1 = 0; - if (r1 > 37) + } + if (r1 > 37) { r1 = 37; + } int r2 = r1 + 1; - if (r2 > 37) + if (r2 > 37) { r2 = 37; + } const int kz1 = ((int)(100 * z / 2.5)); const int kz2 = kz1 + 1; diff --git a/Detectors/TRD/base/src/TRDGeometry.cxx b/Detectors/TRD/base/src/TRDGeometry.cxx index ad47e283eb100..f3c731a1d5321 100644 --- a/Detectors/TRD/base/src/TRDGeometry.cxx +++ b/Detectors/TRD/base/src/TRDGeometry.cxx @@ -2676,8 +2676,9 @@ void TRDGeometry::addAlignableVolumes() const // The symbolic names are: TRD/sm00/st0/pl0 ... TRD/sm17/st4/pl5 for (int isector = 0; isector < NSECTOR; isector++) { - if (!getSMstatus(isector)) + if (!getSMstatus(isector)) { continue; + } for (int ilayer = 0; ilayer < NLAYER; ilayer++) { for (int istack = 0; istack < NSTACK; istack++) { Int_t lid = getDetector(ilayer, istack, isector); diff --git a/Detectors/TRD/base/src/TRDGeometryBase.cxx b/Detectors/TRD/base/src/TRDGeometryBase.cxx index bd86f5c0b8cba..d561b04b05eb5 100644 --- a/Detectors/TRD/base/src/TRDGeometryBase.cxx +++ b/Detectors/TRD/base/src/TRDGeometryBase.cxx @@ -22,8 +22,9 @@ GPUd() int TRDGeometryBase::getStack(float z, int layer) const // The return function has to be protected for positiveness !! // - if ((layer < 0) || (layer >= NLAYER)) + if ((layer < 0) || (layer >= NLAYER)) { return -1; + } int istck = NSTACK; float zmin = 0.0; @@ -31,8 +32,9 @@ GPUd() int TRDGeometryBase::getStack(float z, int layer) const do { istck--; - if (istck < 0) + if (istck < 0) { break; + } const TRDPadPlane* pp = getPadPlane(layer, istck); zmax = pp->getRow0(); int nrows = pp->getNrows(); @@ -50,16 +52,19 @@ GPUd() bool TRDGeometryBase::isOnBoundary(int det, float y, float z, float eps) // int ly = getLayer(det); - if ((ly < 0) || (ly >= NLAYER)) + if ((ly < 0) || (ly >= NLAYER)) { return true; + } int stk = getStack(det); - if ((stk < 0) || (stk >= NSTACK)) + if ((stk < 0) || (stk >= NSTACK)) { return true; + } const TRDPadPlane* pp = &mPadPlanes[getDetectorSec(ly, stk)]; - if (!pp) + if (!pp) { return true; + } float max = pp->getRow0(); int n = pp->getNrows(); diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h index 926997cad942d..8f527eb3063d3 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapConfig.h @@ -565,8 +565,9 @@ class TrapConfig if (index < mData.size()) { mData[index] = value; mValid[index] = valid; - } else + } else { LOG(debug) << "attempt to write data outside array with size : " << mData.size() << "and index of :" << index; + } } //next 3 functions are putrely for back ref cross checks to run2. int getAllocMode() { return (int)mAllocMode; } diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h index eb2bc36480b26..76bfd284d3c5f 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h @@ -80,12 +80,14 @@ class TrapSimulator void unsetData() { mDataIsSet = false; - for (auto& fitreg : mFitReg) + for (auto& fitreg : mFitReg) { fitreg.ClearReg(); + } mNHits = 0; mADCFilled = 0; - for (auto& tmplabel : mADCLabels) + for (auto& tmplabel : mADCLabels) { tmplabel.clear(); // clear MC Labels sent in from the digits coming in. + } mTrackletLabels.clear(); // clear the stored labels. mTrackletArray.clear(); mTrackletArray64.clear(); diff --git a/Detectors/TRD/simulation/src/TrapConfig.cxx b/Detectors/TRD/simulation/src/TrapConfig.cxx index 58da7f1398b3a..ea06669b56594 100644 --- a/Detectors/TRD/simulation/src/TrapConfig.cxx +++ b/Detectors/TRD/simulation/src/TrapConfig.cxx @@ -528,8 +528,9 @@ void TrapConfig::resetDmem() { // reset the data memory - for (int iAddr = 0; iAddr < mgkDmemWords; iAddr++) + for (int iAddr = 0; iAddr < mgkDmemWords; iAddr++) { mDmem[iAddr].reset(); + } } int TrapConfig::getTrapReg(TrapReg_t reg, int det, int rob, int mcm) @@ -624,8 +625,9 @@ bool TrapConfig::setDmem(int addr, unsigned int value, int det) if (!mDmem[addr].setValue(value, det)) { LOG(error) << "Problem writing to DMEM address 0x" << hex << std::setw(4) << addr; return false; - } else + } else { return true; + } } bool TrapConfig::setDmem(int addr, unsigned int value, int det, int rob, int mcm) @@ -641,8 +643,9 @@ bool TrapConfig::setDmem(int addr, unsigned int value, int det, int rob, int mcm if (!mDmem[addr].setValue(value, det, rob, mcm)) { LOG(error) << "Problem writing to DMEM address 0x" << hex << std::setw(4) << addr; return false; - } else + } else { return true; + } } unsigned int TrapConfig::getDmemUnsigned(int addr, int det, int rob, int mcm) @@ -698,20 +701,21 @@ TrapConfig::TrapReg_t TrapConfig::getRegByAddress(int address) // get register by its address // used for reading of configuration data as sent to real FEE - if (address < mgkRegisterAddressBlockStart[0]) + if (address < mgkRegisterAddressBlockStart[0]) { return kLastReg; - else if (address < mgkRegisterAddressBlockStart[0] + mgkRegisterAddressBlockSize[0]) + } else if (address < mgkRegisterAddressBlockStart[0] + mgkRegisterAddressBlockSize[0]) { return mgRegAddressMap[address - mgkRegisterAddressBlockStart[0]]; - else if (address < mgkRegisterAddressBlockStart[1]) + } else if (address < mgkRegisterAddressBlockStart[1]) { return kLastReg; - else if (address < mgkRegisterAddressBlockStart[1] + mgkRegisterAddressBlockSize[1]) + } else if (address < mgkRegisterAddressBlockStart[1] + mgkRegisterAddressBlockSize[1]) { return mgRegAddressMap[address - mgkRegisterAddressBlockStart[1] + mgkRegisterAddressBlockSize[0]]; - else if (address < mgkRegisterAddressBlockStart[2]) + } else if (address < mgkRegisterAddressBlockStart[2]) { return kLastReg; - else if (address < mgkRegisterAddressBlockStart[2] + mgkRegisterAddressBlockSize[2]) + } else if (address < mgkRegisterAddressBlockStart[2] + mgkRegisterAddressBlockSize[2]) { return mgRegAddressMap[address - mgkRegisterAddressBlockStart[2] + mgkRegisterAddressBlockSize[1] + mgkRegisterAddressBlockSize[0]]; - else + } else { return kLastReg; + } } void TrapConfig::printMemDatx(ostream& os, int addr) @@ -757,10 +761,11 @@ void TrapConfig::printDatx(ostream& os, unsigned int addr, unsigned int data, in os << std::setw(5) << 10 << std::setw(8) << addr << std::setw(12) << data; - if (mcm == 127) + if (mcm == 127) { os << std::setw(8) << 127; - else + } else { os << std::setw(8) << FeeParam::aliToExtAli(rob, mcm); + } os << std::endl; } @@ -778,8 +783,9 @@ void TrapConfig::printVerify(ostream& os, int det, int rob, int mcm) } for (int iWord = 0; iWord < mgkDmemWords; ++iWord) { - if (getDmemUnsigned(mgkDmemStartAddress + iWord, det, rob, mcm) == 0) + if (getDmemUnsigned(mgkDmemStartAddress + iWord, det, rob, mcm) == 0) { continue; + } os << std::setw(5) << 9 << std::setw(8) << mgkDmemStartAddress + iWord << std::setw(12) << getDmemUnsigned(mgkDmemStartAddress + iWord, det, rob, mcm) @@ -981,8 +987,9 @@ void TrapConfig::TrapRegister::init(const char* name, int addr, int nBits, int r mAddr = addr; mNbits = nBits; mResetValue = resetValue; - } else + } else { LOG(fatal) << "Re-initialising an existing TRAP register "; + } } void TrapConfig::TrapRegister::initfromrun2(const char* name, int addr, int nBits, int resetValue) diff --git a/Detectors/TRD/simulation/src/TrapConfigHandler.cxx b/Detectors/TRD/simulation/src/TrapConfigHandler.cxx index 888be9dd15c4f..5e96fded2c1f1 100644 --- a/Detectors/TRD/simulation/src/TrapConfigHandler.cxx +++ b/Detectors/TRD/simulation/src/TrapConfigHandler.cxx @@ -54,8 +54,9 @@ void TrapConfigHandler::init() // I/O configuration which we don't care about mTrapConfig->setTrapRegAlloc(TrapConfig::kSEBDOU, TrapConfig::kAllocNone); // position look-up table by layer - for (int iBin = 0; iBin < 128; iBin++) + for (int iBin = 0; iBin < 128; iBin++) { mTrapConfig->setTrapRegAlloc((TrapConfig::TrapReg_t)(TrapConfig::kTPL00 + iBin), TrapConfig::kAllocByLayer); + } // ... individual mTrapConfig->setTrapRegAlloc(TrapConfig::kC14CPUA, TrapConfig::kAllocByMCM); mTrapConfig->setTrapRegAlloc(TrapConfig::kC15CPUA, TrapConfig::kAllocByMCM); @@ -64,35 +65,36 @@ void TrapConfigHandler::init() for (int iAddr = TrapConfig::mgkDmemStartAddress; iAddr < (TrapConfig::mgkDmemWords + TrapConfig::mgkDmemStartAddress); iAddr++) { - if (iAddr == TrapSimulator::mgkDmemAddrDeflCorr) + if (iAddr == TrapSimulator::mgkDmemAddrDeflCorr) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocByMCMinSM); - else if (iAddr == TrapSimulator::mgkDmemAddrNdrift) + } else if (iAddr == TrapSimulator::mgkDmemAddrNdrift) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocByDetector); - else if ((iAddr >= TrapSimulator::mgkDmemAddrDeflCutStart) && (iAddr <= TrapSimulator::mgkDmemAddrDeflCutEnd)) + } else if ((iAddr >= TrapSimulator::mgkDmemAddrDeflCutStart) && (iAddr <= TrapSimulator::mgkDmemAddrDeflCutEnd)) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocByMCMinSM); - else if ((iAddr >= TrapSimulator::mgkDmemAddrTrackletStart) && (iAddr <= TrapSimulator::mgkDmemAddrTrackletEnd)) + } else if ((iAddr >= TrapSimulator::mgkDmemAddrTrackletStart) && (iAddr <= TrapSimulator::mgkDmemAddrTrackletEnd)) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocByMCM); - else if ((iAddr >= TrapSimulator::mgkDmemAddrLUTStart) && (iAddr <= TrapSimulator::mgkDmemAddrLUTEnd)) + } else if ((iAddr >= TrapSimulator::mgkDmemAddrLUTStart) && (iAddr <= TrapSimulator::mgkDmemAddrLUTEnd)) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocGlobal); - else if (iAddr == TrapSimulator::mgkDmemAddrLUTcor0) + } else if (iAddr == TrapSimulator::mgkDmemAddrLUTcor0) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocByMCMinSM); - else if (iAddr == TrapSimulator::mgkDmemAddrLUTcor1) + } else if (iAddr == TrapSimulator::mgkDmemAddrLUTcor1) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocByMCMinSM); - else if (iAddr == TrapSimulator::mgkDmemAddrLUTnbins) + } else if (iAddr == TrapSimulator::mgkDmemAddrLUTnbins) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocGlobal); - else if (iAddr == TrapSimulator::mgkDmemAddrLUTLength) + } else if (iAddr == TrapSimulator::mgkDmemAddrLUTLength) { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocGlobal); - else + } else { mTrapConfig->setDmemAlloc(iAddr, TrapConfig::kAllocGlobal); + } } mFeeParam = FeeParam::instance(); } @@ -217,10 +219,11 @@ int TrapConfigHandler::loadConfig() } for (int iBin = 0; iBin < 128; iBin++) { int corr = (int)(gr.Eval(iBin)) - iBin; - if (corr < 0) + if (corr < 0) { corr = 0; - else if (corr > 31) + } else if (corr > 31) { corr = 31; + } for (int iStack = 0; iStack < 540 / 6; iStack++) { mTrapConfig->setTrapReg((TrapConfig::TrapReg_t)(TrapConfig::kTPL00 + iBin), corr, 6 * iStack + iLayer); } @@ -552,10 +555,11 @@ void TrapConfigHandler::configurePIDcorr(int det) // int nRobs = TRDGeometry::getStack(det) == 2 ? 6 : 8; int MaxRows; FeeParam* feeparam = FeeParam::instance(); - if (TRDGeometry::getStack(det) == 2) + if (TRDGeometry::getStack(det) == 2) { MaxRows = NROWC0; - else + } else { MaxRows = NROWC1; + } int MaxCols = NCOLUMN; for (int row = 0; row < MaxRows; row++) { //TODO put this back to rob/mcm and not row/col as done in TrapSimulator for (int col = 0; col < MaxCols; col++) { @@ -563,10 +567,11 @@ void TrapConfigHandler::configurePIDcorr(int det) mcm = feeparam->getMCMfromPad(row, col); int dest = 1 << 10 | readoutboard << 7 | mcm; //TODO impelment a method for determining if gaintables are valid, used to be if pointer was valid. - if (mGtbl.getMCMGain(det, row, col) != 0.0) //TODO check this logic there might be problems here. + if (mGtbl.getMCMGain(det, row, col) != 0.0) { //TODO check this logic there might be problems here. mFeeParam->getCorrectionFactors(det, readoutboard, mcm, 9, cor0, cor1, mGtbl.getMCMGain(det, row, col)); - else + } else { mFeeParam->getCorrectionFactors(det, readoutboard, mcm, 9, cor0, cor1); + } addValues(det, mgkScsnCmdWrite, dest, addrLUTcor0, cor0); addValues(det, mgkScsnCmdWrite, dest, addrLUTcor1, cor1); } @@ -620,10 +625,11 @@ bool TrapConfigHandler::addValues(unsigned int det, unsigned int cmd, unsigned i if (FeeParam::extAliToAli(extali, linkPair, rocType, mcmList, mcmListSize) != 0) { int i = 0; while (i < mcmListSize && mcmList[i] != -1) { - if (mcmList[i] == 127) + if (mcmList[i] == 127) { mTrapConfig->setDmem(addr, data, det, 0, 127); - else + } else { mTrapConfig->setDmem(addr, data, det, mcmList[i] >> 7, mcmList[i] & 0x7f); + } i++; } } diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index dad19d150b310..998583c7d49e0 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -124,8 +124,9 @@ void TrapSimulator::reset() // Resets the data values and internal filter registers // by re-initialising them - if (!checkInitialized()) + if (!checkInitialized()) { return; + } //clear the adc data memset(&mADCR[0], 0, sizeof(mADCR[0]) * mADCR.size()); @@ -138,8 +139,9 @@ void TrapSimulator::reset() mTrackletLabels.clear(); // as the name implies clear the stored labels mNHits = 0; - for (auto filterreg : mInternalFilterRegisters) + for (auto filterreg : mInternalFilterRegisters) { filterreg.ClearReg(); + } // Default unread, low active bit mask memset(&mZSMap[0], 0, sizeof(mZSMap[0]) * NADCMCM); memset(&mMCMT[0], 0, sizeof(mMCMT[0]) * mgkMaxTracklets); @@ -185,8 +187,9 @@ std::ostream& o2::trd::operator<<(std::ostream& os, const TrapSimulator& mcm) // output implementation // no output for non-initialized MCM - if (!mcm.checkInitialized()) + if (!mcm.checkInitialized()) { return os; + } // ----- human-readable output ----- if (os.iword(TrapSimulator::mgkFormatIndex) == 0) { @@ -195,8 +198,9 @@ std::ostream& o2::trd::operator<<(std::ostream& os, const TrapSimulator& mcm) os << "----- Unfiltered ADC data (10 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < NADCMCM; iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(5) << iChannel; + } os << std::endl; for (int iTimeBin = 0; iTimeBin < mcm.getNumberOfTimeBins(); iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; @@ -207,9 +211,10 @@ std::ostream& o2::trd::operator<<(std::ostream& os, const TrapSimulator& mcm) } os << "----- Filtered ADC data (10+2 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < NADCMCM; iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(4) << iChannel << ((~mcm.getZeroSupressionMap(iChannel) != 0) ? "!" : " "); + } os << std::endl; for (int iTimeBin = 0; iTimeBin < mcm.getNumberOfTimeBins(); iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; @@ -245,8 +250,9 @@ std::ostream& o2::trd::operator<<(std::ostream& os, const TrapSimulator& mcm) buf.reserve(bufSize); int bufLength = mcm.getRawStream(buf, 0); - for (int i = 0; i < bufLength; i++) + for (int i = 0; i < bufLength; i++) { std::cout << "0x" << std::hex << buf[i] << std::dec << std::endl; + } } @@ -264,8 +270,9 @@ void TrapSimulator::printFitRegXml(ostream& os) const bool tracklet = false; for (int cpu = 0; cpu < 4; cpu++) { - if (mFitPtr[cpu] != 31) + if (mFitPtr[cpu] != 31) { tracklet = true; + } } const char* const aquote{R"(")"}; const char* const cmdid{R"(" cmdid="0">)"}; @@ -369,8 +376,9 @@ void TrapSimulator::printAdcDatHuman(ostream& os) const os << "----- Unfiltered ADC data (10 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < NADCMCM; iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(5) << iChannel; + } os << std::endl; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; @@ -382,9 +390,10 @@ void TrapSimulator::printAdcDatHuman(ostream& os) const os << "----- Filtered ADC data (10+2 bit) -----" << std::endl; os << "ch "; - for (int iChannel = 0; iChannel < NADCMCM; iChannel++) + for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { os << std::setw(4) << iChannel << ((~mZSMap[iChannel] != 0) ? "!" : " "); + } os << std::endl; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { os << "tb " << std::setw(2) << iTimeBin << ":"; @@ -438,15 +447,17 @@ void TrapSimulator::printAdcDatDatx(ostream& os, bool broadcast, int timeBinOffs for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { for (int iChannel = 0; iChannel < NADCMCM; iChannel++) { if ((iTimeBin < timeBinOffset) || (iTimeBin >= mNTimeBin + timeBinOffset)) { - if (broadcast == false) + if (broadcast == false) { mTrapConfig->printDatx(os, addrOffset + iChannel * addrStep + addrOffsetEBSIA + iTimeBin, 10, getRobPos(), getMcmPos()); - else + } else { mTrapConfig->printDatx(os, addrOffset + iChannel * addrStep + addrOffsetEBSIA + iTimeBin, 10, 0, 127); + } } else { - if (broadcast == false) + if (broadcast == false) { mTrapConfig->printDatx(os, addrOffset + iChannel * addrStep + addrOffsetEBSIA + iTimeBin, (getDataFiltered(iChannel, iTimeBin - timeBinOffset) / 4), getRobPos(), getMcmPos()); - else + } else { mTrapConfig->printDatx(os, addrOffset + iChannel * addrStep + addrOffsetEBSIA + iTimeBin, (getDataFiltered(iChannel, iTimeBin - timeBinOffset) / 4), 0, 127); + } } } os << std::endl; @@ -482,8 +493,9 @@ void TrapSimulator::setNTimebins(int ntimebins) // is needed (should not be the case for real data) LOG(fatal) << "setNTimebins(" << ntimebins << ") not implemented as we can no longer change the size of the ADC array"; - if (!checkInitialized()) + if (!checkInitialized()) { return; + } mNTimeBin = ntimebins; // for( int iAdc = 0 ; iAdc < NADCMCM; iAdc++ ) { @@ -520,8 +532,9 @@ void TrapSimulator::noiseTest(int nsamples, int mean, int sigma, int inputGain, // same way as in normal simulation. // The functions produces four histograms with the values at the different stages. - if (!checkInitialized()) + if (!checkInitialized()) { return; + } std::string nameInputGain; std::string nameInputTail; @@ -582,17 +595,19 @@ void TrapSimulator::noiseTest(int nsamples, int mean, int sigma, int inputGain, valuep = filterPedestalNextSample(1, 0, ((int)value) << 2); - if (inputGain == 0) + if (inputGain == 0) { valueg = filterGainNextSample(1, ((int)value) << 2); - else + } else { valueg = filterGainNextSample(1, valuep); + } - if (inputTail == 0) + if (inputTail == 0) { valuet = filterTailNextSample(1, ((int)value) << 2); - else if (inputTail == 1) + } else if (inputTail == 1) { valuet = filterTailNextSample(1, valuep); - else + } else { valuet = filterTailNextSample(1, valueg); + } hfp->SetBinContent(i, valuep >> 2); hfg->SetBinContent(i, valueg >> 2); @@ -635,8 +650,9 @@ void TrapSimulator::print(int choice) const // have been performed. // Codacy wont let us use string choices, as it says we must use string::starts_with() instead of string::find() - if (!checkInitialized()) + if (!checkInitialized()) { return; + } LOG(info) << "MCM " << mMcmPos << " on ROB " << mRobPos << " in detector " << mDetector; @@ -669,8 +685,9 @@ void TrapSimulator::draw(int choice, int index) // In addition to the ADC values: // PLOTHITS - plot hits // PLOTTRACKLETS - plot tracklets - if (!checkInitialized()) + if (!checkInitialized()) { return; + } TFile* rootfile = new TFile("trdtrackletplots.root", "UPDATE"); TCanvas* c1 = new TCanvas(Form("canvas_%i_%i:%i:%i_%i", index, mDetector, mRobPos, mMcmPos, (int)mTrackletArray.size())); TH2F* hist = new TH2F(Form("mcmdata_%i", index), @@ -724,10 +741,11 @@ void TrapSimulator::draw(int choice, int index) if ((choice & PLOTTRACKLETS) != 0) { TLine* trklLines = new TLine[4]; LOG(info) << "Tracklet start for index : " << index; - if (mTrackletArray.size() > 0) + if (mTrackletArray.size() > 0) { LOG(info) << "Tracklet : for " << mTrackletArray[0].getDetector() << "::" << mTrackletArray[0].getROB() << " : " << mTrackletArray[0].getMCM(); - else + } else { LOG(info) << "Tracklet : for trackletarray size of zero "; + } for (int iTrkl = 0; iTrkl < mTrackletArray.size(); iTrkl++) { Tracklet trkl = mTrackletArray[iTrkl]; float padWidth = 0.635 + 0.03 * (mDetector % 6); @@ -735,8 +753,9 @@ void TrapSimulator::draw(int choice, int index) //TODO replace the 18, 4 3 and 7 with constants for readability int ndrift = mTrapConfig->getDmemUnsigned(mgkDmemAddrNdrift, mDetector, mRobPos, mMcmPos) >> 5; float slope = 0; - if (ndrift) + if (ndrift) { slope = trkl.getdY() * 140e-4 / ndrift; + } int t0 = mTrapConfig->getTrapReg(TrapConfig::kTPFS, mDetector, mRobPos, mMcmPos); int t1 = mTrapConfig->getTrapReg(TrapConfig::kTPFE, mDetector, mRobPos, mMcmPos); @@ -764,8 +783,9 @@ void TrapSimulator::setData(int adc, const ArrayADC& data, std::vector<o2::MCCom // Store ADC data into array of raw data // - if (!checkInitialized()) + if (!checkInitialized()) { return; + } if (adc < 0 || adc >= NADCMCM) { // LOG(error) << "Error: ADC " << adc << " is out of range (0 .. " << NADCMCM - 1 << ")"; @@ -795,8 +815,9 @@ void TrapSimulator::setData(int adc, int it, int data) // This time enter it element by element. // - if (!checkInitialized()) + if (!checkInitialized()) { return; + } if (adc < 0 || adc >= NADCMCM) { LOG(error) << "Error: ADC " << adc << " is out of range (0 .. " << NADCMCM - 1 << ")"; @@ -835,8 +856,9 @@ void TrapSimulator::setDataPedestal(int adc) // Store ADC data into array of raw data // - if (!checkInitialized()) + if (!checkInitialized()) { return; + } if (adc < 0 || adc >= NADCMCM) { return; @@ -852,8 +874,9 @@ bool TrapSimulator::getHit(int index, int& channel, int& timebin, int& qtot, int { // retrieve the MC hit information (not available in TRAP hardware) - if (index < 0 || index >= mNHits) + if (index < 0 || index >= mNHits) { return false; + } channel = mHits[index].mChannel; timebin = mHits[index].mTimebin; @@ -877,14 +900,16 @@ int TrapSimulator::getCol(int adc) // Return column id of the pad for the given ADC channel // - if (!checkInitialized()) + if (!checkInitialized()) { return -1; + } int col = mFeeParam->getPadColFromADC(mRobPos, mMcmPos, adc); - if (col < 0 || col >= NCOLUMN) + if (col < 0 || col >= NCOLUMN) { return -1; - else + } else { return col; + } } //TODO figure why I could not get span to work here @@ -962,10 +987,12 @@ int TrapSimulator::packData(std::vector<uint32_t>& rawdata, uint32_t offset) LOG(info) << ">>>>> START DEBUG OUTPUT OF packData trackletcount:-:wordcount" << trackletcount << ":-:" << wordswritten; o2::trd::printTrackletMCMHeader(mcmhead); o2::trd::printTrackletMCMData(tracklets[0]); - if (trackletcount > 1) + if (trackletcount > 1) { o2::trd::printTrackletMCMData(tracklets[1]); - if (trackletcount > 2) + } + if (trackletcount > 2) { o2::trd::printTrackletMCMData(tracklets[2]); + } LOG(info) << "<<<<< END DEBUG OUTPUT OF packData"; } //must produce between 2 and 4 words ... 1 and 3 tracklets. @@ -982,8 +1009,9 @@ int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, uns // Returns number of words filled, or negative value // with -1 * number of overflowed words // - if (!checkInitialized()) + if (!checkInitialized()) { return 0; + } unsigned int x; unsigned int mcmHeader = 0; @@ -993,13 +1021,15 @@ int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, uns int rawVer = mFeeParam->getRAWversion(); std::vector<int> adc; //TODO come back an avoid a copy. - if (!checkInitialized()) + if (!checkInitialized()) { return 0; + } - if (mTrapConfig->getTrapReg(TrapConfig::kEBSF, mDetector, mRobPos, mMcmPos) != 0) // store unfiltered data + if (mTrapConfig->getTrapReg(TrapConfig::kEBSF, mDetector, mRobPos, mMcmPos) != 0) { // store unfiltered data adc = mADCR; - else + } else { adc = mADCF; + } // Produce ADC mask : nncc cccm mmmm mmmm mmmm mmmm mmmm 1100 // n : unused , c : ADC count, m : selected ADCs @@ -1014,8 +1044,9 @@ int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, uns } if ((nActiveADC == 0) && - (mTrapConfig->getTrapReg(TrapConfig::kC15CPUA, mDetector, mRobPos, mMcmPos) & (1 << 8))) // check for DEH flag in TRAP configuration + (mTrapConfig->getTrapReg(TrapConfig::kC15CPUA, mDetector, mRobPos, mMcmPos) & (1 << 8))) { // check for DEH flag in TRAP configuration return 0; + } // assemble adc mask word adcMask |= (1 << 30) | ((0x3FFFFFFC) & (~(nActiveADC) << 25)) | 0xC; // nn = 01, ccccc are inverted, 0xc=1100 @@ -1023,17 +1054,19 @@ int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, uns // MCM header mcmHeader = (1 << 31) | (mRobPos << 28) | (mMcmPos << 24) | ((iEv % 0x100000) << 4) | 0xC; - if (numberWordsWritten < buf.size()) + if (numberWordsWritten < buf.size()) { buf[numberWordsWritten++] = mcmHeader; - else + } else { numberOverFlowWordsWritten++; + } // ADC mask if (adcMask != 0) { - if (numberWordsWritten < buf.size()) + if (numberWordsWritten < buf.size()) { buf[numberWordsWritten++] = adcMask; - else + } else { numberOverFlowWordsWritten++; + } } // Produce ADC data. 3 timebins are packed into one 32 bits word @@ -1042,8 +1075,9 @@ int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, uns unsigned int aa = 0, a1 = 0, a2 = 0, a3 = 0; for (int iAdc = 0; iAdc < 21; iAdc++) { - if (rawVer >= 3 && ~mZSMap[iAdc] == 0) + if (rawVer >= 3 && ~mZSMap[iAdc] == 0) { continue; // Zero Suppression, 0 means not suppressed + } aa = !(iAdc & 1) + 2; for (int iT = 0; iT < mNTimeBin; iT += 3) { a1 = ((iT) < mNTimeBin) ? adc[iAdc * mNTimeBin + iT] >> mgkAddDigits : 0; @@ -1058,10 +1092,11 @@ int TrapSimulator::getRawStream(std::vector<uint32_t>& buf, uint32_t offset, uns } } - if (numberOverFlowWordsWritten != 0) + if (numberOverFlowWordsWritten != 0) { return -numberOverFlowWordsWritten; - else + } else { return numberWordsWritten; + } } int TrapSimulator::getTrackletStream(std::vector<uint32_t>& buf, uint32_t offset) @@ -1073,8 +1108,9 @@ int TrapSimulator::getTrackletStream(std::vector<uint32_t>& buf, uint32_t offset // with -1 * number of overflowed words // - if (!checkInitialized()) + if (!checkInitialized()) { return 0; + } int numberWordsWritten = 0; // Number of written words @@ -1098,8 +1134,9 @@ void TrapSimulator::filter() // sequentially for parameter tuning. // - if (!checkInitialized()) + if (!checkInitialized()) { return; + } // Apply filters sequentially. Bypass is handled by filters // since counters and internal registers may be updated even @@ -1124,8 +1161,9 @@ void TrapSimulator::filterPedestalInit(int baseline) unsigned short fptc = mTrapConfig->getTrapReg(TrapConfig::kFPTC, mDetector, mRobPos, mMcmPos); // 0..3, 0 - fastest, 3 - slowest - for (int adc = 0; adc < NADCMCM; adc++) + for (int adc = 0; adc < NADCMCM; adc++) { mInternalFilterRegisters[adc].mPedAcc = (baseline << 2) * (1 << mgkFPshifts[fptc]); + } // LOG(info) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; } @@ -1153,17 +1191,19 @@ unsigned short TrapSimulator::filterPedestalNextSample(int adc, int timebin, uns } // LOG(info) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; - if (fpby == 0) + if (fpby == 0) { return value; + } - if (inpAdd <= accumulatorShifted) + if (inpAdd <= accumulatorShifted) { return 0; - else { + } else { inpAdd = inpAdd - accumulatorShifted; - if (inpAdd > 0xFFF) + if (inpAdd > 0xFFF) { return 0xFFF; - else + } else { return inpAdd; + } } } @@ -1240,10 +1280,11 @@ unsigned short TrapSimulator::filterGainNextSample(int adc, unsigned short value // stop when full { // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr << " mgtb : " << mgtb; - if (corr >= mgtb) + if (corr >= mgtb) { mInternalFilterRegisters[adc].mGainCounterB++; - else if (corr >= mgta) + } else if (corr >= mgta) { mInternalFilterRegisters[adc].mGainCounterA++; + } } // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr << " mgby : " << mgby; @@ -1285,8 +1326,9 @@ void TrapSimulator::filterTailInit(int baseline) float ql, qs; - if (baseline < 0) + if (baseline < 0) { baseline = mTrapConfig->getTrapReg(TrapConfig::kFPNP, mDetector, mRobPos, mMcmPos); + } ql = lambdaL * (1 - lambdaS) * alphaL; qs = lambdaS * (1 - lambdaL) * (1 - alphaL); @@ -1328,10 +1370,11 @@ unsigned short TrapSimulator::filterTailNextSample(int adc, unsigned short value aQ = addUintClipping(mInternalFilterRegisters[adc].mTailAmplLong, mInternalFilterRegisters[adc].mTailAmplShort, 12); // calculate the difference between the input and the generated signal - if (inpVolt > aQ) + if (inpVolt > aQ) { aDiff = inpVolt - aQ; - else + } else { aDiff = 0; + } // the inputs to the two generators, weighted alInpv = (aDiff * alphaLong) >> 11; @@ -1347,10 +1390,11 @@ unsigned short TrapSimulator::filterTailNextSample(int adc, unsigned short value mInternalFilterRegisters[adc].mTailAmplShort = tmp & 0xFFF; // the output of the filter - if (mTrapConfig->getTrapReg(TrapConfig::kFTBY, mDetector, mRobPos, mMcmPos) == 0) // bypass mode, active low + if (mTrapConfig->getTrapReg(TrapConfig::kFTBY, mDetector, mRobPos, mMcmPos) == 0) { // bypass mode, active low return value; - else + } else { return aDiff; + } } void TrapSimulator::filterTail() @@ -1374,16 +1418,18 @@ void TrapSimulator::zeroSupressionMapping() // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf // - if (!checkInitialized()) + if (!checkInitialized()) { return; + } int eBIS = mTrapConfig->getTrapReg(TrapConfig::kEBIS, mDetector, mRobPos, mMcmPos); int eBIT = mTrapConfig->getTrapReg(TrapConfig::kEBIT, mDetector, mRobPos, mMcmPos); int eBIL = mTrapConfig->getTrapReg(TrapConfig::kEBIL, mDetector, mRobPos, mMcmPos); int eBIN = mTrapConfig->getTrapReg(TrapConfig::kEBIN, mDetector, mRobPos, mMcmPos); - for (int iAdc = 0; iAdc < NADCMCM; iAdc++) + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { mZSMap[iAdc] = -1; + } for (int it = 0; it < mNTimeBin; it++) { int iAdc; // current ADC channel @@ -1655,8 +1701,9 @@ void TrapSimulator::calcFitreg() } if (found > 4) // sorting like in the TRAP in case of 5 or 6 candidates! { - if (marked[4] == marked[5]) + if (marked[4] == marked[5]) { marked[5] = 19; + } for (found = 0; found < 6; found++) { qMarked[found] = qTotal[marked[found]] >> 4; } @@ -1693,31 +1740,37 @@ void TrapSimulator::calcFitreg() // LOG(info) << "Hit found, time=" << timebin << ", adcch=" << adcch << "/" << adcch + 1 << "/" // << adcch + 2 << ", adc values=" << adcLeft << "/" << adcCentral << "/" // << adcRight << ", regTPFP=" << regTPFP << ", TPHT=" << mTrapConfig->getTrapReg(TrapConfig::kTPHT, mDetector, mRobPos, mMcmPos); - if (adcLeft < regTPFP) + if (adcLeft < regTPFP) { adcLeft = 0; - else + } else { adcLeft -= regTPFP; - if (adcCentral < regTPFP) + } + if (adcCentral < regTPFP) { adcCentral = 0; - else + } else { adcCentral -= regTPFP; - if (adcRight < regTPFP) + } + if (adcRight < regTPFP) { adcRight = 0; - else + } else { adcRight -= regTPFP; + } // Calculate the center of gravity // checking for adcCentral != 0 (in case of "bad" configuration) - if (adcCentral == 0) + if (adcCentral == 0) { continue; + } ypos = 128 * (adcRight - adcLeft) / adcCentral; - if (ypos < 0) + if (ypos < 0) { ypos = -ypos; + } // make the correction using the position LUT ypos = ypos + mTrapConfig->getTrapReg((TrapConfig::TrapReg_t)(TrapConfig::kTPL00 + (ypos & 0x7F)), mDetector, mRobPos, mMcmPos); - if (adcLeft > adcRight) + if (adcLeft > adcRight) { ypos = -ypos; + } /* TODO this is left in here as a ref for what was done with labels, its stored externally now figure something out. */ // add the hit to the fitregister @@ -1797,10 +1850,12 @@ void TrapSimulator::trackletSelection() } } } - for (i = 0; i < ntracks; i++) // CPUs with tracklets. + for (i = 0; i < ntracks; i++) { // CPUs with tracklets. mFitPtr[i] = trackletCandch[i]; // pointer to the left channel with tracklet for CPU[i] - for (i = ntracks; i < 4; i++) // CPUs without tracklets + } + for (i = ntracks; i < 4; i++) { // CPUs without tracklets mFitPtr[i] = 31; // pointer to the left channel with tracklet for CPU[i] = 31 (invalid) + } // LOG(info) << "-------------------------------------------- found " << ntracks << " tracklet candidates"; // for (i = 0; i < 4; i++) // LOG(info) << "fitPtr[" << i << "]: " << mFitPtr[i]; @@ -1809,13 +1864,15 @@ void TrapSimulator::trackletSelection() if (FeeParam::instance()->getRejectMultipleTracklets()) { unsigned short counts = 0; for (j = 0; j < (ntracks - 1); j++) { - if (mFitPtr[j] == 31) + if (mFitPtr[j] == 31) { continue; + } for (i = j + 1; i < ntracks; i++) { // check if tracklets are from neighbouring ADC channels - if (TMath::Abs(mFitPtr[j] - mFitPtr[i]) > 1.) + if (TMath::Abs(mFitPtr[j] - mFitPtr[i]) > 1.) { continue; + } // check which tracklet candidate has higher amount of hits if ((mFitReg[mFitPtr[j]].mNhits + mFitReg[mFitPtr[j] + 1].mNhits) >= @@ -2185,13 +2242,15 @@ int TrapSimulator::getPID(int q0, int q1) unsigned int nBinsQ0 = mTrapConfig->getDmemUnsigned(mgkDmemAddrLUTnbins, mDetector, mRobPos, mMcmPos); // number of bins in q0 / 4 !! unsigned int pidTotalSize = mTrapConfig->getDmemUnsigned(mgkDmemAddrLUTLength, mDetector, mRobPos, mMcmPos); - if (nBinsQ0 == 0 || pidTotalSize == 0) // make sure we don't run into trouble if the value for Q0 is not configured + if (nBinsQ0 == 0 || pidTotalSize == 0) { // make sure we don't run into trouble if the value for Q0 is not configured return 0; // Q1 not configured is ok for 1D LUT + } unsigned long corrQ0 = mTrapConfig->getDmemUnsigned(mgkDmemAddrLUTcor0, mDetector, mRobPos, mMcmPos); unsigned long corrQ1 = mTrapConfig->getDmemUnsigned(mgkDmemAddrLUTcor1, mDetector, mRobPos, mMcmPos); - if (corrQ0 == 0) // make sure we don't run into trouble if one of the values is not configured + if (corrQ0 == 0) { // make sure we don't run into trouble if one of the values is not configured return 0; + } addrQ0 = corrQ0; addrQ0 = (((addrQ0 * q0) >> 16) >> 16); // because addrQ0 = (q0 * corrQ0) >> 32; does not work for unknown reasons @@ -2228,11 +2287,13 @@ unsigned int TrapSimulator::addUintClipping(unsigned int a, unsigned int b, unsi unsigned int sum = a + b; if (nbits < 32) { unsigned int maxv = (1 << nbits) - 1; - if (sum > maxv) + if (sum > maxv) { sum = maxv; + } } else { - if ((sum < a) || (sum < b)) + if ((sum < a) || (sum < b)) { sum = 0xFFFFFFFF; + } } return sum; } @@ -2266,14 +2327,17 @@ void TrapSimulator::sort3(unsigned short idx1i, unsigned short idx2i, unsigned s int sel; - if (val1i > val2i) + if (val1i > val2i) { sel = 4; - else + } else { sel = 0; - if (val2i > val3i) + } + if (val2i > val3i) { sel = sel + 2; - if (val3i > val1i) + } + if (val3i > val1i) { sel = sel + 1; + } switch (sel) { case 6: // 1 > 2 > 3 => 1 2 3 case 0: // 1 = 2 = 3 => 1 2 3 : in this case doesn't matter, but so is in hardware! diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 37d5ae14deff7..6060d4d35ed22 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -90,16 +90,18 @@ bool msgDigitSortComparator(o2::trd::Digit const& a, o2::trd::Digit const& b) // LOG(info) << "yip timea < timeb " << timea <<"<" << timeb; return 1; } else if (timea == timeb) { - if (hcida < hcidb) + if (hcida < hcidb) { return 1; - else { + } else { if (hcida == hcidb) { - if (mcma < mcmb) + if (mcma < mcmb) { return 1; - else + } else { return 0; - } else + } + } else { return 0; + } } return 0; @@ -173,8 +175,9 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() LOG(warn) << " failed to get trapconfig from ccdb with name : " << mTrapConfigName; } else { //TODO figure out how to get the debug level from logger and only do this for debug option to --severity debug (or what ever the command actualy is) - if (mEnableTrapConfigDump) + if (mEnableTrapConfigDump) { mTrapConfig->DumpTrapConfig2File("run3trapconfig_dump"); + } } } @@ -271,25 +274,32 @@ bool digitindexcompare(unsigned int A, unsigned int B, const std::vector<o2::trd int robb = fee->getROBfromPad(rowb, padb); int mcma = fee->getMCMfromPad(rowa, pada); int mcmb = fee->getMCMfromPad(rowb, padb); - if (a->getTimeStamp() < b->getTimeStamp()) + if (a->getTimeStamp() < b->getTimeStamp()) { return 1; - if (a->getTimeStamp() > b->getTimeStamp()) + } + if (a->getTimeStamp() > b->getTimeStamp()) { return 0; + } // timestamps are equal - if (a->getDetector() < b->getDetector()) + if (a->getDetector() < b->getDetector()) { return 1; - if (a->getDetector() > b->getDetector()) + } + if (a->getDetector() > b->getDetector()) { return 0; + } //detectors are equal - if (roba < robb) + if (roba < robb) { return 1; - if (roba > robb) + } + if (roba > robb) { return 0; + } //rob is equal - if (mcma < mcmb) + if (mcma < mcmb) { return 1; - else + } else { return 0; + } } void TRDDPLTrapSimulatorTask::setTriggerRecord(std::vector<o2::trd::TriggerRecord>& triggerrecord, uint32_t currentrecord, uint64_t recordsize) @@ -361,8 +371,9 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) LOG(debug) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); } // fix incoming trigger records if requested. - if (mFixTriggerRecords) + if (mFixTriggerRecords) { fixTriggerRecords(triggerRecords); + } std::vector<o2::trd::TriggerRecord> trackletTriggerRecords = triggerRecords; // copy over the whole thing but we only really want the bunch crossing info. std::vector<o2::trd::TriggerRecord> rawTriggerRecords = triggerRecords; // as we have the option of having tracklets and/or raw data, we need both triggerrecords. @@ -542,15 +553,17 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // mTrapSimulator[trapcounter].zeroSupressionMapping(); - if (mDrawTrackletOptions != 0) + if (mDrawTrackletOptions != 0) { mTrapSimulator[trapcounter].draw(mDrawTrackletOptions, loopindex); + } if (mDebugRejectedTracklets) { //&& trapTracklets.size()==0) { mTrapSimulator[trapcounter].draw(7, loopindex); //draw adc when no tracklets are found.A LOG(debug) << "loop index : " << loopindex; mTrapSimulator[trapcounter].print(1); } - if (mPrintTrackletOptions != 0) + if (mPrintTrackletOptions != 0) { mTrapSimulator[trapcounter].print(mPrintTrackletOptions); + } loopindex++; //set this trap sim object to have not data (effectively) reset. From ccc79d0fdaadcd0af89ec281ac3cedf8b12676a6 Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaya@cern.ch> Date: Tue, 3 Nov 2020 18:24:57 +0100 Subject: [PATCH 1194/1751] Event quality flag added to CTF; (#4736) * add EventStatusWord to CTF * replace assert with alarm printout for tests * remove printouts Co-authored-by: Alla <Alla.Maevskaia@cern.ch> --- .../Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h | 10 +++++----- .../Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h | 4 +++- .../FIT/FT0/include/DataFormatsFT0/LookUpTable.h | 6 +++++- DataFormats/Detectors/FIT/FT0/src/CTF.cxx | 2 +- .../include/FT0Reconstruction/CTFCoder.h | 7 +++---- Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx | 6 ++++-- .../FT0/reconstruction/src/CollisionTimeRecoTask.cxx | 6 +++--- 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h index 1989a8f2df02c..fdf54804c0d1a 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/CTF.h @@ -26,7 +26,7 @@ namespace ft0 /// Header for a single CTF struct CTFHeader { - uint32_t nTriggers = 0; /// number of truggers in TF + uint32_t nTriggers = 0; /// number of triggers in TF uint32_t firstOrbit = 0; /// 1st orbit of TF uint16_t firstBC = 0; /// 1st BC of TF @@ -43,12 +43,12 @@ struct CompressedDigits { std::vector<uint16_t> bcInc; // increment in BC if the same orbit, otherwise abs bc std::vector<uint32_t> orbitInc; // increment in orbit std::vector<uint8_t> nChan; // number of fired channels - // std::vector<uint8_t> eventFlags; // special flags about event conditions: pile-up, not use for collision time, not use for event plane, etc. + std::vector<uint8_t> eventFlags; // special flags about event conditions: pile-up, not use for collision time, not use for event plane, etc. // channel data std::vector<uint8_t> idChan; // channels ID: 1st on absolute, then increment std::vector<int16_t> cfdTime; // CFD time - std::vector<int16_t> qtcAmpl; // Amplitude + std::vector<int32_t> qtcAmpl; // Amplitude std::vector<uint8_t> qtcChain; // QTC chain CompressedDigits() = default; @@ -59,7 +59,7 @@ struct CompressedDigits { }; /// wrapper for the Entropy-encoded clusters of the TF -struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 8, uint32_t> { +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 9, uint32_t> { static constexpr size_t N = getNBlocks(); enum Slots { @@ -67,7 +67,7 @@ struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 8, uint32_t> { BLC_bcInc, // increment in BC BLC_orbitInc, // increment in orbit BLC_nChan, // number of fired channels - // BLC_flags, // flags special flags about event conditions: pile-up, not use for collision time, not use for event plane, etc. + BLC_flags, // flags special flags about event conditions: pile-up, not use for collision time, not use for event plane, etc. BLC_idChan, // channels ID: 1st on absolute, then increment BLC_qtcChain, // ADC chain BLC_cfdTime, // CFD time diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h index 6279720661bc5..1abe2b60fe19d 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h @@ -43,6 +43,7 @@ struct Triggers { int32_t amplC = -1000; // sum amplitude C side int16_t timeA = -1000; // average time A side int16_t timeC = -1000; // average time C side + uint8_t eventFlags = 0; // event conditions Triggers() = default; Triggers(uint8_t signals, int8_t chanA, int8_t chanC, int32_t aamplA, int32_t aamplC, int16_t atimeA, int16_t atimeC) { @@ -112,7 +113,8 @@ struct Digit { void setEventStatus(uint8_t stat) { mEventStatus = stat; }; void setStatusFlag(EEventStatus bit, bool value) { mEventStatus |= (value << bit); }; bool getStatusFlag(EEventStatus bit) const { return bool(mEventStatus << bit); } - ClassDefNV(Digit, 4); + uint8_t getEventStatusWord() const { return mEventStatus; } + ClassDefNV(Digit, 5); }; //For TCM extended mode (calibration mode), TCMdataExtended digit diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h index 1453d934bd797..de6aeb8ae653e 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h @@ -97,7 +97,11 @@ class LookUpTable static int getIdx(int link, int mcp) { - assert(mcp < NUMBER_OF_MCPs); + if (mcp >= NUMBER_OF_MCPs) { + std::cout << " !!! MCP number > max NUMBER_OF_MCPs " << mcp << " data will be skipped " << std::endl; + return -1; + } + //assert(mcp < NUMBER_OF_MCPs); return link * NUMBER_OF_MCPs + mcp; } static int getLinkFromIdx(int idx) { return idx / NUMBER_OF_MCPs; } diff --git a/DataFormats/Detectors/FIT/FT0/src/CTF.cxx b/DataFormats/Detectors/FIT/FT0/src/CTF.cxx index 8298be41f5b84..7a8b5818d1d9f 100644 --- a/DataFormats/Detectors/FIT/FT0/src/CTF.cxx +++ b/DataFormats/Detectors/FIT/FT0/src/CTF.cxx @@ -22,7 +22,7 @@ void CompressedDigits::clear() bcInc.clear(); orbitInc.clear(); nChan.clear(); - // eventFlags.clear(); + eventFlags.clear(); idChan.clear(); qtcChain.clear(); diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index 5a6dd6bb5ddea..c6a922c529244 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -75,7 +75,7 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g MD::EENCODE, // BLC_bcInc MD::EENCODE, // BLC_orbitInc MD::EENCODE, // BLC_nChan - // MD::EENCODE, // BLC_flags + MD::EENCODE, // BLC_flags MD::EENCODE, // BLC_idChan MD::EENCODE, // BLC_qtcChain MD::EENCODE, // BLC_cfdTime @@ -101,7 +101,7 @@ void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const g ENCODEFT0(cd.bcInc, CTF::BLC_bcInc, 0); ENCODEFT0(cd.orbitInc, CTF::BLC_orbitInc, 0); ENCODEFT0(cd.nChan, CTF::BLC_nChan, 0); - // ENCODEFT0(cd.eventFlags, CTF::BLC_flags, 0); + ENCODEFT0(cd.eventFlags, CTF::BLC_flags, 0); ENCODEFT0(cd.idChan , CTF::BLC_idChan, 0); ENCODEFT0(cd.qtcChain, CTF::BLC_qtcChain, 0); ENCODEFT0(cd.cfdTime, CTF::BLC_cfdTime, 0); @@ -123,7 +123,7 @@ void CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec) DECODEFT0(cd.bcInc, CTF::BLC_bcInc); DECODEFT0(cd.orbitInc, CTF::BLC_orbitInc); DECODEFT0(cd.nChan, CTF::BLC_nChan); - // DECODEFT0(cd.eventFlags, CTF::BLC_flags); + DECODEFT0(cd.eventFlags, CTF::BLC_flags); DECODEFT0(cd.idChan, CTF::BLC_idChan); DECODEFT0(cd.qtcChain, CTF::BLC_qtcChain); DECODEFT0(cd.cfdTime, CTF::BLC_cfdTime); @@ -159,7 +159,6 @@ void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& cha firstEntry = channelVec.size(); uint8_t chID = 0; int amplA = 0, amplC = 0, timeA = 0, timeC = 0; - // int mTime_trg_gate = 192; // #channels for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { auto icc = channelVec.size(); const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtcChain[icc]); diff --git a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx index 3dc5aa2c36e19..fe15747186622 100644 --- a/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/CTFCoder.cxx @@ -52,6 +52,7 @@ void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digi cd.trigger.resize(cd.header.nTriggers); cd.bcInc.resize(cd.header.nTriggers); cd.orbitInc.resize(cd.header.nTriggers); + cd.eventFlags.resize(cd.header.nTriggers); cd.nChan.resize(cd.header.nTriggers); cd.idChan.resize(channelVec.size()); @@ -68,6 +69,7 @@ void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digi // fill trigger info cd.trigger[idig] = digit.getTriggers().triggersignals; + cd.eventFlags[idig] = digit.getEventStatusWord(); if (prevOrbit == digit.getOrbit()) { cd.bcInc[idig] = digit.getBC() - prevBC; cd.orbitInc[idig] = 0; @@ -127,7 +129,7 @@ void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase:: MAKECODER(cd.bcInc, CTF::BLC_bcInc); MAKECODER(cd.orbitInc, CTF::BLC_orbitInc); MAKECODER(cd.nChan, CTF::BLC_nChan); - // MAKECODER(cd.eventFlags, CTF::BLC_flags); + MAKECODER(cd.eventFlags, CTF::BLC_flags); MAKECODER(cd.idChan, CTF::BLC_idChan); MAKECODER(cd.qtcChain, CTF::BLC_qtcChain); MAKECODER(cd.cfdTime, CTF::BLC_cfdTime); @@ -148,7 +150,7 @@ size_t CTFCoder::estimateCompressedSize(const CompressedDigits& cd) sz += ESTSIZE(cd.bcInc, CTF::BLC_bcInc); sz += ESTSIZE(cd.orbitInc, CTF::BLC_orbitInc); sz += ESTSIZE(cd.nChan, CTF::BLC_nChan); - // sz += ESTSIZE(cd.eventFlags, CTF::BLC_flags); + sz += ESTSIZE(cd.eventFlags, CTF::BLC_flags); sz += ESTSIZE(cd.idChan, CTF::BLC_idChan); sz += ESTSIZE(cd.qtcChain, CTF::BLC_qtcChain); sz += ESTSIZE(cd.cfdTime, CTF::BLC_cfdTime); diff --git a/Detectors/FIT/FT0/reconstruction/src/CollisionTimeRecoTask.cxx b/Detectors/FIT/FT0/reconstruction/src/CollisionTimeRecoTask.cxx index 538d31e3b95e3..492a588dbd90c 100644 --- a/Detectors/FIT/FT0/reconstruction/src/CollisionTimeRecoTask.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/CollisionTimeRecoTask.cxx @@ -30,7 +30,7 @@ o2::ft0::RecPoints CollisionTimeRecoTask::process(o2::ft0::Digit const& bcd, gsl::span<const o2::ft0::ChannelData> inChData, gsl::span<o2::ft0::ChannelDataFloat> outChData) { - LOG(INFO) << "Running reconstruction on new event"; + LOG(DEBUG) << "Running reconstruction on new event"; Int_t ndigitsC = 0, ndigitsA = 0; @@ -42,7 +42,7 @@ o2::ft0::RecPoints CollisionTimeRecoTask::process(o2::ft0::Digit const& bcd, auto timeStamp = o2::InteractionRecord::bc2ns(bcd.mIntRecord.bc, bcd.mIntRecord.orbit); - LOG(INFO) << " event time " << timeStamp << " orbit " << bcd.mIntRecord.orbit << " bc " << bcd.mIntRecord.bc; + LOG(DEBUG) << " event time " << timeStamp << " orbit " << bcd.mIntRecord.orbit << " bc " << bcd.mIntRecord.bc; int nch = inChData.size(); for (int ich = 0; ich < nch; ich++) { @@ -76,7 +76,7 @@ o2::ft0::RecPoints CollisionTimeRecoTask::process(o2::ft0::Digit const& bcd, } else { mCollisionTime[TimeMean] = std::min(mCollisionTime[TimeA], mCollisionTime[TimeC]); } - LOG(INFO) << " Collision time " << mCollisionTime[TimeA] << " " << mCollisionTime[TimeC] << " " << mCollisionTime[TimeMean] << " " << mCollisionTime[Vertex]; + LOG(DEBUG) << " Collision time " << mCollisionTime[TimeA] << " " << mCollisionTime[TimeC] << " " << mCollisionTime[TimeMean] << " " << mCollisionTime[Vertex]; return RecPoints{ mCollisionTime, bcd.ref.getFirstEntry(), bcd.ref.getEntries(), bcd.mIntRecord, bcd.mTriggers}; } From 762aa3aac51f0d5b9a539b6d3be0de9bcedb1fc9 Mon Sep 17 00:00:00 2001 From: Sylvain Chapeland <o2.syc@cern.ch> Date: Tue, 3 Nov 2020 14:58:02 +0100 Subject: [PATCH 1195/1751] removed obsolete DataBlock references --- Framework/Core/src/ReadoutAdapter.cxx | 2 -- .../src/DataSamplingReadoutAdapter.cxx | 14 ++++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Framework/Core/src/ReadoutAdapter.cxx b/Framework/Core/src/ReadoutAdapter.cxx index 65642b6040094..a002d3b8ff3ad 100644 --- a/Framework/Core/src/ReadoutAdapter.cxx +++ b/Framework/Core/src/ReadoutAdapter.cxx @@ -13,8 +13,6 @@ #include "Framework/DataSpecUtils.h" #include "Headers/DataHeader.h" -#include <Common/DataBlock.h> - namespace o2 { namespace framework diff --git a/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx index 408adb7029d87..1eee4db1f86ed 100644 --- a/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx +++ b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx @@ -11,8 +11,7 @@ #include "Framework/DataProcessingHeader.h" #include "Headers/DataHeader.h" #include "Framework/DataSpecUtils.h" - -#include <Common/DataBlock.h> +#include <atomic> using namespace o2::framework; @@ -21,23 +20,22 @@ namespace o2::utilities using DataHeader = o2::header::DataHeader; +static std::atomic<unsigned int> blockId = 0; + InjectorFunction dataSamplingReadoutAdapter(OutputSpec const& spec) { return [spec](FairMQDevice& device, FairMQParts& parts, ChannelRetriever channelRetriever) { for (size_t i = 0; i < parts.Size() / 2; ++i) { - auto dbh = reinterpret_cast<DataBlockHeaderBase*>(parts.At(2 * i)->GetData()); - assert(dbh->dataSize == parts.At(2 * i + 1)->GetSize()); - DataHeader dh; ConcreteDataTypeMatcher dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec); dh.dataOrigin = dataType.origin; dh.dataDescription = dataType.description; - dh.subSpecification = DataSpecUtils::getOptionalSubSpec(spec).value_or(dbh->linkId); - dh.payloadSize = dbh->dataSize; + dh.subSpecification = DataSpecUtils::getOptionalSubSpec(spec).value_or(0xFF); + dh.payloadSize = parts.At(2 * i + 1)->GetSize(); dh.payloadSerializationMethod = o2::header::gSerializationMethodNone; - DataProcessingHeader dph{dbh->blockId, 0}; + DataProcessingHeader dph{++blockId, 0}; o2::header::Stack headerStack{dh, dph}; sendOnChannel(device, std::move(headerStack), std::move(parts.At(2 * i + 1)), spec, channelRetriever); } From aed1af5426f65faaa806dff16195fe02249e8480 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 3 Nov 2020 15:50:45 +0100 Subject: [PATCH 1196/1751] Set ITS/MFT global chip ID during decoding --- .../include/ITSMFTReconstruction/AlpideCoder.h | 8 ++++---- .../ITSMFTReconstruction/RUDecodeData.h | 18 +++++------------- .../ITSMFTReconstruction/RawPixelReader.h | 10 +++++++--- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h index fa0a5f0aaf921..e6aed3815c70c 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h @@ -118,8 +118,8 @@ class AlpideCoder static void setNoiseThreshold(int t) { mNoiseThreshold = t; } /// decode alpide data for the next non-empty chip from the buffer - template <class T> - static int decodeChip(ChipPixelData& chipData, T& buffer) + template <class T, typename CG> + static int decodeChip(ChipPixelData& chipData, T& buffer, CG cidGetter) { // read record for single non-empty chip, updating on change module and cycle. // return number of records filled (>0), EOFFlag or Error @@ -141,7 +141,7 @@ class AlpideCoder uint8_t dataCM = dataC & (~MaskChipID); // if ((expectInp & ExpectChipEmpty) && dataCM == CHIPEMPTY) { // empty chip was expected - //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module // now set upstream + chipData.setChipID(cidGetter(dataC & MaskChipID)); // here we set the global chip ID if (!buffer.next(timestamp)) { #ifdef ALPIDE_DECODING_STAT chipData.setError(ChipStat::TruncatedChipEmpty); @@ -153,7 +153,7 @@ class AlpideCoder } if ((expectInp & ExpectChipHeader) && dataCM == CHIPHEADER) { // chip header was expected - //chipData.setChipID(dataC & MaskChipID); // here we set the chip ID within the module // now set upstream + chipData.setChipID(cidGetter(dataC & MaskChipID)); // here we set the global chip ID if (!buffer.next(timestamp)) { #ifdef ALPIDE_DECODING_STAT chipData.setError(ChipStat::TruncatedChipHeader); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h index 1000a9e258e05..e8cda7a633bd4 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h @@ -73,14 +73,11 @@ int RUDecodeData::decodeROF(const Mapping& mp) if (!cableData[icab].getSize()) { continue; } - int cid = AlpideCoder::getChipID(cableData[icab]); - if (cid < 0) { - continue; - } - chipData->setChipID(mp.getGlobalChipID(cid, cableHWID[icab], *ruInfo)); - while (AlpideCoder::decodeChip(*chipData, cableData[icab]) || chipData->isErrorSet()) { // we register only chips with hits or errors flags set - // convert HW chip id within the module to absolute chip id - //chipData->setChipID(mp.getGlobalChipID(chipData->getChipID(), cableHWID[icab], *ruInfo)); + auto cabHW = cableHWID[icab]; + auto chIdGetter = [this, &mp, cabHW](int cid) { + return mp.getGlobalChipID(cid, cabHW, *this->ruInfo); + }; + while (AlpideCoder::decodeChip(*chipData, cableData[icab], chIdGetter) || chipData->isErrorSet()) { // we register only chips with hits or errors flags set setROFInfo(chipData, cableLinkPtr[icab]); ntot += chipData->getData().size(); #ifdef ALPIDE_DECODING_STAT @@ -88,11 +85,6 @@ int RUDecodeData::decodeROF(const Mapping& mp) #endif if (++nChipsFired < chipsData.size()) { // fetch next free chip chipData = &chipsData[nChipsFired]; - cid = AlpideCoder::getChipID(cableData[icab]); - if (cid < 0) { - continue; - } - chipData->setChipID(mp.getGlobalChipID(cid, cableHWID[icab], *ruInfo)); } else { break; // last chip decoded } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h index ac61b0af3f71d..baca178dfd0f6 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h @@ -1256,8 +1256,12 @@ class RawPixelReader : public PixelReader RDHUtils::printRDH(reinterpret_cast<const o2::header::RAWDataHeader*>(getGBTLink(decData.links[decData.cableLinkID[icab]])->lastRDH)); } #endif - - while ((res = mCoder.decodeChip(*chipData, cableData))) { // we register only chips with hits or errors flags set + auto cabHW = decData.cableHWID[icab]; + auto ri = decData.ruInfo; + auto chIdGetter = [this, cabHW, ri](int cid) { + return this->mMAP.getGlobalChipID(cid, cabHW, *ri); + }; + while ((res = mCoder.decodeChip(*chipData, cableData, chIdGetter))) { // we register only chips with hits or errors flags set if (res > 0) { #ifdef _RAW_READER_ERROR_CHECKS_ // for the IB staves check if the cable ID is the same as the chip ID on the module @@ -1271,7 +1275,7 @@ class RawPixelReader : public PixelReader } #endif // convert HW chip id within the module to absolute chip id - chipData->setChipID(mMAP.getGlobalChipID(chipData->getChipID(), decData.cableHWID[icab], *decData.ruInfo)); + // chipData->setChipID(mMAP.getGlobalChipID(chipData->getChipID(), decData.cableHWID[icab], *decData.ruInfo)); chipData->setInteractionRecord(mInteractionRecord); chipData->setTrigger(mTrigger); mDecodingStat.nNonEmptyChips++; From 644cd91bc8f995f44024abe76c1bd85da33ab8ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <nicolo.jacazio@cern.ch> Date: Tue, 3 Nov 2020 12:42:24 +0100 Subject: [PATCH 1197/1751] Update configurable name in QATask --- Analysis/Tasks/qaTask.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx index c77b4402ccca9..5c20b3550b90f 100644 --- a/Analysis/Tasks/qaTask.cxx +++ b/Analysis/Tasks/qaTask.cxx @@ -133,7 +133,7 @@ struct QATrackingResolution { o2fw::Configurable<int> nBinsDeltaPhi{"nBinsPhi", 100, "Number of bins for the azimuthal angle differences"}; - o2fw::Configurable<int> nBinsDeltaEta{"nBinsEta", 100, "Number of bins for the pseudorapidity differences"}; + o2fw::Configurable<int> nBinsDeltaEta{"nBinsDeltaEta", 100, "Number of bins for the pseudorapidity differences"}; o2fw::Configurable<int> nBinsImpactParameter{"nBinsImpactParameter", 1000, "Number of bins for the Impact parameter"}; From bf2086fa23cba51eee077876bbeb3e6a47d9e66a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 3 Nov 2020 13:30:17 +0100 Subject: [PATCH 1198/1751] DPL: improve rate limit --- .../include/Framework/DataProcessingDevice.h | 1 - Framework/Core/src/AODReaderHelpers.cxx | 4 +- Framework/Core/src/CommonMessageBackends.cxx | 89 ++++++++++++++++--- Framework/Core/src/DataProcessingDevice.cxx | 3 +- 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingDevice.h b/Framework/Core/include/Framework/DataProcessingDevice.h index 4eccdc78fc676..89d8dd90d9f20 100644 --- a/Framework/Core/include/Framework/DataProcessingDevice.h +++ b/Framework/Core/include/Framework/DataProcessingDevice.h @@ -133,7 +133,6 @@ class DataProcessingDevice : public FairMQDevice std::mutex mRegionInfoMutex; enum TerminationPolicy mErrorPolicy = TerminationPolicy::WAIT; /// What to do when an error arises bool mWasActive = false; /// Whether or not the device was active at last iteration. - bool mFirst = true; /// Whether or not this was the first iteration }; } // namespace o2::framework diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index f020da39b2224..6600cf0b06171 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -180,6 +180,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() monitoring.send(Metric{(uint64_t)0, "arrow-messages-created"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); monitoring.send(Metric{(uint64_t)0, "arrow-bytes-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); monitoring.send(Metric{(uint64_t)0, "arrow-messages-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.flushBuffer(); if (!options.isSet("aod-file")) { LOGP(ERROR, "No input file defined!"); @@ -221,7 +222,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() fileCounter, numTF, watchdog, - didir](DataAllocator& outputs, ControlService& control, DeviceSpec const& device) { + didir](Monitoring& monitoring, DataAllocator& outputs, ControlService& control, DeviceSpec const& device) { // check if RuntimeLimit is reached if (!watchdog->update()) { LOGP(INFO, "Run time exceeds run time limit of {} seconds!", watchdog->runTimeLimit); @@ -238,6 +239,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() uint64_t timeFrameNumber = 0; int fcnt = (*fileCounter * device.maxInputTimeslices) + device.inputTimesliceId; int ntf = *numTF + 1; + monitoring.send(Metric{(uint64_t)ntf, "tf-sent"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); // loop over requested tables TTree* tr = nullptr; diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index d46571aeb6e93..c2a855820d36c 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -85,6 +85,15 @@ struct CommonMessageBackendsHelpers { }; } // namespace +enum struct RateLimitingState { + UNKNOWN = 0, // No information received yet. + STARTED = 1, // Information received, new timeframe not requested. + CHANGED = 2, // Information received, new timeframe requested but not yet accounted. + BELOW_LIMIT = 3, // New metric received, we are below limit. + NEXT_ITERATION_FROM_BELOW = 4, // Iteration when previously in BELOW_LIMIT. + ABOVE_LIMIT = 5, // New metric received, we are above limit. +}; + struct RateLimitConfig { int64_t maxMemory = 0; }; @@ -151,38 +160,54 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() int64_t totalBytesDestroyed = 0; int64_t totalMessagesCreated = 0; int64_t totalMessagesDestroyed = 0; - static bool wasChanged = false; + static RateLimitingState currentState = RateLimitingState::UNKNOWN; + static auto stateMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "rate-limit-state"); static auto totalBytesCreatedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-bytes-created"); static auto totalBytesDestroyedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-bytes-destroyed"); static auto totalMessagesCreatedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-messages-created"); static auto totalMessagesDestroyedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-messages-destroyed"); static auto totalBytesDeltaMetric = DeviceMetricsHelper::createNumericMetric<int>(driverMetrics, "arrow-bytes-delta"); static auto totalSignalsMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "aod-reader-signals"); + static auto remainingBytes = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "aod-remaining-bytes"); bool changed = false; + bool hasMetrics = false; + // Find the last timestamp when we signaled. + size_t signalIndex = DeviceMetricsHelper::metricIdxByName("aod-reader-signals", driverMetrics); + size_t lastSignalTimestamp = 0; + if (signalIndex < driverMetrics.metrics.size()) { + MetricInfo info = driverMetrics.metrics.at(signalIndex); + lastSignalTimestamp = driverMetrics.timestamps[signalIndex][info.pos - 1]; + } + + size_t lastCreatedBytesTimestamp = 0; + size_t lastDestroyedBytesTimestamp = 0; for (auto& deviceMetrics : allDeviceMetrics) { { size_t index = DeviceMetricsHelper::metricIdxByName("arrow-bytes-created", deviceMetrics); if (index < deviceMetrics.metrics.size()) { + hasMetrics = true; changed |= deviceMetrics.changed.at(index); MetricInfo info = deviceMetrics.metrics.at(index); auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); totalBytesCreated += (int64_t)data.at((info.pos - 1) % data.size()); + lastCreatedBytesTimestamp = deviceMetrics.timestamps[index][info.pos - 1]; } } { size_t index = DeviceMetricsHelper::metricIdxByName("arrow-bytes-destroyed", deviceMetrics); if (index < deviceMetrics.metrics.size()) { + hasMetrics = true; changed |= deviceMetrics.changed.at(index); MetricInfo info = deviceMetrics.metrics.at(index); auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); totalBytesDestroyed += (int64_t)data.at((info.pos - 1) % data.size()); + lastDestroyedBytesTimestamp = deviceMetrics.timestamps[index][info.pos - 1]; } } { size_t index = DeviceMetricsHelper::metricIdxByName("arrow-messages-created", deviceMetrics); if (index < deviceMetrics.metrics.size()) { - changed |= deviceMetrics.changed.at(index); MetricInfo info = deviceMetrics.metrics.at(index); auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); totalMessagesCreated += (int64_t)data.at((info.pos - 1) % data.size()); @@ -191,7 +216,6 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() { size_t index = DeviceMetricsHelper::metricIdxByName("arrow-messages-destroyed", deviceMetrics); if (index < deviceMetrics.metrics.size()) { - changed |= deviceMetrics.changed.at(index); MetricInfo info = deviceMetrics.metrics.at(index); auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); totalMessagesDestroyed += (int64_t)data.at((info.pos - 1) % data.size()); @@ -205,11 +229,21 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() totalMessagesDestroyedMetric(driverMetrics, totalMessagesDestroyed, timestamp); totalBytesDeltaMetric(driverMetrics, totalBytesCreated - totalBytesDestroyed, timestamp); } - if (memLimit) { - if (changed) { - /// Trigger next timeframe only when we have more than 1GB in memory available. - if (totalBytesCreated <= (totalBytesDestroyed + memLimit)) { - totalSignalsMetric(driverMetrics, 1, timestamp); + bool done = false; + static int stateTransitions = 0; + while (!done) { + stateMetric(driverMetrics, (uint64_t)(currentState), stateTransitions++); + switch (currentState) { + case RateLimitingState::UNKNOWN: { + for (auto& deviceMetrics : allDeviceMetrics) { + size_t index = DeviceMetricsHelper::metricIdxByName("arrow-bytes-created", deviceMetrics); + if (index < deviceMetrics.metrics.size()) { + currentState = RateLimitingState::STARTED; + } + } + done = true; + } break; + case RateLimitingState::STARTED: { for (size_t di = 0; di < specs.size(); ++di) { if (specs[di].name == "internal-dpl-aod-reader") { if (di < infos.size()) { @@ -218,9 +252,19 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() } } } - } - } else if (wasChanged == changed) { - if (totalBytesCreated < totalBytesDestroyed) { + changed = false; + currentState = RateLimitingState::CHANGED; + } break; + case RateLimitingState::CHANGED: { + remainingBytes(driverMetrics, totalBytesCreated <= (totalBytesDestroyed + memLimit) ? (totalBytesDestroyed + memLimit) - totalBytesCreated : 0, timestamp); + if (totalBytesCreated <= (totalBytesDestroyed + memLimit)) { + currentState = RateLimitingState::BELOW_LIMIT; + } else { + currentState = RateLimitingState::ABOVE_LIMIT; + } + changed = false; + } break; + case RateLimitingState::BELOW_LIMIT: { for (size_t di = 0; di < specs.size(); ++di) { if (specs[di].name == "internal-dpl-aod-reader") { if (di < infos.size()) { @@ -229,10 +273,27 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() } } } - } - } + changed = false; + currentState = RateLimitingState::NEXT_ITERATION_FROM_BELOW; + } break; + case RateLimitingState::NEXT_ITERATION_FROM_BELOW: { + if (!changed) { + done = true; + } else { + currentState = RateLimitingState::CHANGED; + } + } break; + case RateLimitingState::ABOVE_LIMIT: { + if (!changed) { + done = true; + } else if (totalBytesCreated > (totalBytesDestroyed + memLimit / 3)) { + done = true; + } else { + currentState = RateLimitingState::CHANGED; + } + }; + }; } - wasChanged = changed; }, [](ProcessingContext& ctx, void* service) { using DataHeader = o2::header::DataHeader; diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index de06b901006cc..4d75c4eb7383c 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -445,8 +445,7 @@ bool DataProcessingDevice::ConditionalRun() if (mState.loop) { ZoneScopedN("uv idle"); TracyPlot("past activity", (int64_t)mWasActive); - uv_run(mState.loop, (mFirst == true) || (mWasActive && (mDataProcessorContexes.at(0).state->streaming != StreamingState::Idle) && (mState.activeSignals.empty())) ? UV_RUN_NOWAIT : UV_RUN_ONCE); - mFirst = false; + uv_run(mState.loop, (mWasActive && (mDataProcessorContexes.at(0).state->streaming != StreamingState::Idle) && (mState.activeSignals.empty())) ? UV_RUN_NOWAIT : UV_RUN_ONCE); } // Notify on the main thread the new region callbacks, making sure From 4de686a4bb03a28152a1a1e4923b0a1ed96e14db Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 3 Nov 2020 16:21:10 +0100 Subject: [PATCH 1199/1751] Rename TRD classes from TRDFoo to Foo - remove testArrayADC.cxx which was dummy - remove some using namespace o2::trd directives in header files --- .../TRD/include/DataFormatsTRD/Tracklet64.h | 2 +- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 4 +- Detectors/TRD/base/CMakeLists.txt | 26 ++++---- Detectors/TRD/base/include/TRDBase/CalDet.h | 8 +-- .../include/TRDBase/CalOnlineGainTables.h | 22 +++---- .../{TRDCalPadStatus.h => CalPadStatus.h} | 28 ++++---- ...amberStatus.h => CalSingleChamberStatus.h} | 20 +++--- .../TRD/base/include/TRDBase/Calibrations.h | 4 +- .../include/TRDBase/ChamberCalibrations.h | 20 +++--- .../TRD/base/include/TRDBase/ChamberNoise.h | 8 +-- .../TRD/base/include/TRDBase/ChamberStatus.h | 8 +-- .../{TRDCommonParam.h => CommonParam.h} | 24 +++---- ...timator.h => DiffAndTimeStructEstimator.h} | 12 ++-- Detectors/TRD/base/include/TRDBase/Digit.h | 2 +- Detectors/TRD/base/include/TRDBase/FeeParam.h | 8 +-- .../TRDBase/{TRDGeometry.h => Geometry.h} | 23 +++---- .../{TRDGeometryBase.h => GeometryBase.h} | 23 ++++--- .../{TRDGeometryFlat.h => GeometryFlat.h} | 22 +++---- .../base/include/TRDBase/PadCalibrations.h | 10 +-- .../TRD/base/include/TRDBase/PadParameters.h | 12 ++-- .../TRDBase/{TRDPadPlane.h => PadPlane.h} | 18 ++--- .../TRDBase/{TRDSimParam.h => SimParam.h} | 24 +++---- Detectors/TRD/base/include/TRDBase/Tracklet.h | 6 +- Detectors/TRD/base/macros/OCDB2CCDB.C | 52 +++++++-------- Detectors/TRD/base/src/CalDet.cxx | 12 ++-- .../TRD/base/src/CalOnlineGainTables.cxx | 2 +- Detectors/TRD/base/src/CalPad.cxx | 8 +-- .../{TRDCalPadStatus.cxx => CalPadStatus.cxx} | 66 +++++++++---------- ...rStatus.cxx => CalSingleChamberStatus.cxx} | 18 ++--- Detectors/TRD/base/src/Calibrations.cxx | 2 +- Detectors/TRD/base/src/ChamberNoise.cxx | 2 +- .../{TRDCommonParam.cxx => CommonParam.cxx} | 42 ++++++------ ...tor.cxx => DiffAndTimeStructEstimator.cxx} | 22 +++---- Detectors/TRD/base/src/FeeParam.cxx | 16 ++--- .../src/{TRDGeometry.cxx => Geometry.cxx} | 38 +++++------ .../{TRDGeometryBase.cxx => GeometryBase.cxx} | 10 +-- .../{TRDGeometryFlat.cxx => GeometryFlat.cxx} | 11 ++-- .../src/{TRDPadPlane.cxx => PadPlane.cxx} | 14 ++-- .../src/{TRDSimParam.cxx => SimParam.cxx} | 41 ++++++------ Detectors/TRD/base/src/TRDBaseLinkDef.h | 10 +-- Detectors/TRD/base/src/Tracklet.cxx | 10 +-- Detectors/TRD/base/test/testArrayADC.cxx | 41 ------------ .../base/test/testTRDDiffusionCoefficient.cxx | 14 ++-- Detectors/TRD/base/test/testTRDGeometry.cxx | 30 ++++----- Detectors/TRD/macros/CheckDigits.C | 6 +- Detectors/TRD/macros/CheckHits.C | 8 +-- .../include/TRDSimulation/Detector.h | 4 +- .../include/TRDSimulation/Digitizer.h | 22 +++---- Detectors/TRD/simulation/src/Detector.cxx | 34 +++++----- Detectors/TRD/simulation/src/Digitizer.cxx | 14 ++-- Detectors/TRD/simulation/src/Trap2CRU.cxx | 2 +- Detectors/TRD/simulation/src/TrapConfig.cxx | 10 +-- .../TRD/simulation/src/TrapConfigHandler.cxx | 16 ++--- .../TRD/simulation/src/TrapSimulator.cxx | 7 +- .../TRDWorkflow/TRDTrapSimulatorSpec.h | 2 +- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 16 ++--- GPU/GPUTracking/Base/GPUDataTypes.h | 4 +- GPU/GPUTracking/Base/GPUO2DataTypes.h | 2 +- GPU/GPUTracking/Base/GPUO2FakeClasses.h | 2 +- .../Base/GPUReconstructionIncludesDevice.h | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- GPU/GPUTracking/Global/GPUChainTracking.h | 8 +-- GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 2 +- GPU/GPUTracking/Standalone/CMakeLists.txt | 2 +- GPU/GPUTracking/Standalone/tools/createGeo.C | 8 +-- .../Standalone/tools/dumpTRDClusterMatrices.C | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h | 12 ++-- .../TRDTracking/GPUTRDTrackerComponent.cxx | 2 +- .../TRDTracking/macros/run_trd_tracker.C | 6 +- 69 files changed, 470 insertions(+), 520 deletions(-) rename Detectors/TRD/base/include/TRDBase/{TRDCalPadStatus.h => CalPadStatus.h} (76%) rename Detectors/TRD/base/include/TRDBase/{TRDCalSingleChamberStatus.h => CalSingleChamberStatus.h} (83%) rename Detectors/TRD/base/include/TRDBase/{TRDCommonParam.h => CommonParam.h} (80%) rename Detectors/TRD/base/include/TRDBase/{TRDDiffAndTimeStructEstimator.h => DiffAndTimeStructEstimator.h} (86%) rename Detectors/TRD/base/include/TRDBase/{TRDGeometry.h => Geometry.h} (77%) rename Detectors/TRD/base/include/TRDBase/{TRDGeometryBase.h => GeometryBase.h} (96%) rename Detectors/TRD/base/include/TRDBase/{TRDGeometryFlat.h => GeometryFlat.h} (75%) rename Detectors/TRD/base/include/TRDBase/{TRDPadPlane.h => PadPlane.h} (94%) rename Detectors/TRD/base/include/TRDBase/{TRDSimParam.h => SimParam.h} (90%) rename Detectors/TRD/base/src/{TRDCalPadStatus.cxx => CalPadStatus.cxx} (79%) rename Detectors/TRD/base/src/{TRDCalSingleChamberStatus.cxx => CalSingleChamberStatus.cxx} (84%) rename Detectors/TRD/base/src/{TRDCommonParam.cxx => CommonParam.cxx} (98%) rename Detectors/TRD/base/src/{TRDDiffAndTimeStructEstimator.cxx => DiffAndTimeStructEstimator.cxx} (98%) rename Detectors/TRD/base/src/{TRDGeometry.cxx => Geometry.cxx} (99%) rename Detectors/TRD/base/src/{TRDGeometryBase.cxx => GeometryBase.cxx} (87%) rename Detectors/TRD/base/src/{TRDGeometryFlat.cxx => GeometryFlat.cxx} (84%) rename Detectors/TRD/base/src/{TRDPadPlane.cxx => PadPlane.cxx} (92%) rename Detectors/TRD/base/src/{TRDSimParam.cxx => SimParam.cxx} (91%) delete mode 100644 Detectors/TRD/base/test/testArrayADC.cxx diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index 465d0f9f195e5..de93a0a31465c 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -//#include "TRDBase/TRDGeometryBase.h" +//#include "TRDBase/GeometryBase.h" //#include "DetectorsCommonDataFormats/DetMatrixCache.h" //#include "DetectorsCommonDataFormats/DetID.h" diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index e16378cc5f404..a43084001d8fe 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -218,10 +218,10 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config // Sample code what needs to be done for the TRD Geometry, when we extend this to TRD tracking. /*o2::base::GeometryManager::loadGeometry(); - o2::trd::TRDGeometry gm; + o2::trd::Geometry gm; gm.createPadPlaneArray(); gm.createClusterMatrixArray(); - std::unique_ptr<o2::trd::TRDGeometryFlat> gf(gm); + std::unique_ptr<o2::trd::GeometryFlat> gf(gm); config.trdGeometry = gf.get();*/ // Configuration is prepared, initialize the tracker. diff --git a/Detectors/TRD/base/CMakeLists.txt b/Detectors/TRD/base/CMakeLists.txt index 54c50ed5cba1e..d61d638a63fc4 100644 --- a/Detectors/TRD/base/CMakeLists.txt +++ b/Detectors/TRD/base/CMakeLists.txt @@ -8,13 +8,13 @@ # submit itself to any jurisdiction. o2_add_library(TRDBase - SOURCES src/TRDPadPlane.cxx - src/TRDGeometryBase.cxx - src/TRDGeometry.cxx - src/TRDGeometryFlat.cxx - src/TRDCommonParam.cxx - src/TRDDiffAndTimeStructEstimator.cxx - src/TRDSimParam.cxx + SOURCES src/PadPlane.cxx + src/GeometryBase.cxx + src/Geometry.cxx + src/GeometryFlat.cxx + src/CommonParam.cxx + src/DiffAndTimeStructEstimator.cxx + src/SimParam.cxx src/PadResponse.cxx src/Digit.cxx src/CalDet.cxx @@ -40,12 +40,12 @@ o2_add_library(TRDBase O2::CCDB) o2_target_root_dictionary(TRDBase - HEADERS include/TRDBase/TRDPadPlane.h - include/TRDBase/TRDGeometryBase.h - include/TRDBase/TRDGeometry.h - include/TRDBase/TRDGeometryFlat.h - include/TRDBase/TRDSimParam.h - include/TRDBase/TRDCommonParam.h + HEADERS include/TRDBase/PadPlane.h + include/TRDBase/GeometryBase.h + include/TRDBase/Geometry.h + include/TRDBase/GeometryFlat.h + include/TRDBase/SimParam.h + include/TRDBase/CommonParam.h include/TRDBase/PadResponse.h include/TRDBase/Digit.h include/TRDBase/MCLabel.h diff --git a/Detectors/TRD/base/include/TRDBase/CalDet.h b/Detectors/TRD/base/include/TRDBase/CalDet.h index 15df17376723a..9affc767fdcdc 100644 --- a/Detectors/TRD/base/include/TRDBase/CalDet.h +++ b/Detectors/TRD/base/include/TRDBase/CalDet.h @@ -20,8 +20,8 @@ #include "DataFormatsTRD/Constants.h" -class TRDGeometry; -class TRDPadPlane; +class Geometry; +class PadPlane; class TH1F; class TH2F; @@ -37,9 +37,9 @@ class CalDet ~CalDet() = default; // float getValue(int d) const { return mData[d]; }; - float getValue(int p, int c, int s) const { return mData[TRDGeometry::getDetector(p, c, s)]; }; + float getValue(int p, int c, int s) const { return mData[Geometry::getDetector(p, c, s)]; }; void setValue(int d, float value) { mData[d] = value; }; - void setValue(int p, int c, int s, float value) { mData[TRDGeometry::getDetector(p, c, s)] = value; }; + void setValue(int p, int c, int s, float value) { mData[Geometry::getDetector(p, c, s)] = value; }; void setName(std::string name) { mName = name; }; // these 4 get and set methods are probably not needed (were not in the old code) but are here for completeness void setTitle(std::string title) { mTitle = title; }; std::string& getName() { return mName; }; diff --git a/Detectors/TRD/base/include/TRDBase/CalOnlineGainTables.h b/Detectors/TRD/base/include/TRDBase/CalOnlineGainTables.h index c44b70ab06f8f..2537830bac80c 100644 --- a/Detectors/TRD/base/include/TRDBase/CalOnlineGainTables.h +++ b/Detectors/TRD/base/include/TRDBase/CalOnlineGainTables.h @@ -28,7 +28,7 @@ /////////////////////////////////////////////////////////////////////////////// #include <array> -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" class FeeParam; namespace o2 @@ -44,34 +44,34 @@ class CalOnlineGainTables // get and set the various values stored internally in the gain tables. float getGainCorrectionFactorrm(int det, int rob, int mcm) const; float getGainCorrectionFactor(int det, int row, int col) const; - float getGainCorrectionFactor(int sector, int stack, int layer, int row, int col) const { return getGainCorrectionFactor(TRDGeometry::getDetector(sector, stack, layer), row, col); }; + float getGainCorrectionFactor(int sector, int stack, int layer, int row, int col) const { return getGainCorrectionFactor(Geometry::getDetector(sector, stack, layer), row, col); }; short getAdcdacrm(int det, int rob, int mcm) const; short getAdcdac(int det, int row, int col) const; - short getAdcdac(int sector, int stack, int layer, int row, int col) const { return getAdcdac(TRDGeometry::getDetector(sector, stack, layer), row, col); }; + short getAdcdac(int sector, int stack, int layer, int row, int col) const { return getAdcdac(Geometry::getDetector(sector, stack, layer), row, col); }; float getMCMGainrm(int det, int rob, int mcm) const; float getMCMGain(int det, int row, int col) const; - float getMCMGain(int sector, int stack, int layer, int row, int col) const { return getMCMGain(TRDGeometry::getDetector(sector, stack, layer), row, col); }; + float getMCMGain(int sector, int stack, int layer, int row, int col) const { return getMCMGain(Geometry::getDetector(sector, stack, layer), row, col); }; short getFGANrm(int det, int rob, int mcm, int channel) const; short getFGAN(int det, int row, int col) const; - short getFGAN(int sector, int stack, int layer, int row, int col) const { return getFGAN(TRDGeometry::getDetector(sector, stack, layer), row, col); }; + short getFGAN(int sector, int stack, int layer, int row, int col) const { return getFGAN(Geometry::getDetector(sector, stack, layer), row, col); }; short getFGFNrm(int det, int rob, int mcm, int channel) const; short getFGFN(int det, int row, int col) const; - short getFGFN(int sector, int stack, int layer, int row, int col) const { return getFGFN(TRDGeometry::getDetector(sector, stack, layer), row, col); }; + short getFGFN(int sector, int stack, int layer, int row, int col) const { return getFGFN(Geometry::getDetector(sector, stack, layer), row, col); }; void setGainCorrectionFactorrm(int det, int rob, int mcm, float gain); void setGainCorrectionFactor(int det, int row, int col, float gain); - void setGainCorrectionFactor(int sector, int stack, int layer, int row, int col, float gain) { setGainCorrectionFactor(TRDGeometry::getDetector(sector, stack, layer), row, col, gain); }; + void setGainCorrectionFactor(int sector, int stack, int layer, int row, int col, float gain) { setGainCorrectionFactor(Geometry::getDetector(sector, stack, layer), row, col, gain); }; void setAdcdacrm(int det, int rob, int mcm, short gain); void setAdcdac(int det, int row, int col, short gain); - void setAdcdac(int sector, int stack, int layer, int row, int col, short gain) { setAdcdac(TRDGeometry::getDetector(sector, stack, layer), row, col, gain); }; + void setAdcdac(int sector, int stack, int layer, int row, int col, short gain) { setAdcdac(Geometry::getDetector(sector, stack, layer), row, col, gain); }; void setMCMGainrm(int det, int rob, int mcm, float gain); void setMCMGain(int det, int row, int col, float gain); - void setMCMGain(int sector, int stack, int layer, int row, int col, float gain) { setMCMGain(TRDGeometry::getDetector(sector, stack, layer), row, col, gain); }; + void setMCMGain(int sector, int stack, int layer, int row, int col, float gain) { setMCMGain(Geometry::getDetector(sector, stack, layer), row, col, gain); }; void setFGANrm(int det, int rob, int mcm, int channel, short gain); void setFGAN(int det, int row, int col, short gain); - void setFGAN(int sector, int stack, int layer, int row, int col, short gain) { setFGAN(TRDGeometry::getDetector(sector, stack, layer), row, col, gain); }; + void setFGAN(int sector, int stack, int layer, int row, int col, short gain) { setFGAN(Geometry::getDetector(sector, stack, layer), row, col, gain); }; void setFGFNrm(int det, int rob, int mcm, int channel, short gain); void setFGFN(int det, int row, int col, short gain); - void setFGFN(int sector, int stack, int layer, int row, int col, short gain) { setFGFN(TRDGeometry::getDetector(sector, stack, layer), row, col, gain); }; + void setFGFN(int sector, int stack, int layer, int row, int col, short gain) { setFGFN(Geometry::getDetector(sector, stack, layer), row, col, gain); }; // these 4 are used primarily to reading in from run2 ocdb, might have wider uses. void setAdcdac(int arrayoffset, short adc) { mGainTable[arrayoffset].mAdcdac = adc; }; diff --git a/Detectors/TRD/base/include/TRDBase/TRDCalPadStatus.h b/Detectors/TRD/base/include/TRDBase/CalPadStatus.h similarity index 76% rename from Detectors/TRD/base/include/TRDBase/TRDCalPadStatus.h rename to Detectors/TRD/base/include/TRDBase/CalPadStatus.h index a3307b36b72d6..32a61b5285a61 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDCalPadStatus.h +++ b/Detectors/TRD/base/include/TRDBase/CalPadStatus.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDCALPADSTATUS_H -#define O2_TRDCALPADSTATUS_H +#ifndef O2_TRD_CALPADSTATUS_H +#define O2_TRD_CALPADSTATUS_H #include "DataFormatsTRD/Constants.h" @@ -28,9 +28,9 @@ namespace trd // // /////////////////////////////////////////////////////////////////////////////// -class TRDCalSingleChamberStatus; +class CalSingleChamberStatus; -class TRDCalPadStatus +class CalPadStatus { public: @@ -40,13 +40,13 @@ class TRDCalPadStatus kReadSecond = 16, kNotConnected = 32 }; - TRDCalPadStatus(); - TRDCalPadStatus(const Text_t* name, const Text_t* title); - TRDCalPadStatus(const TRDCalPadStatus& c); - ~TRDCalPadStatus(); - TRDCalPadStatus& operator=(const TRDCalPadStatus& c); + CalPadStatus(); + CalPadStatus(const Text_t* name, const Text_t* title); + CalPadStatus(const CalPadStatus& c); + ~CalPadStatus(); + CalPadStatus& operator=(const CalPadStatus& c); - void Copy(TRDCalPadStatus& c) const; + void Copy(CalPadStatus& c) const; Bool_t isMasked(Int_t d, Int_t col, Int_t row) const { @@ -70,8 +70,8 @@ class TRDCalPadStatus }; Bool_t checkStatus(Int_t d, Int_t col, Int_t row, Int_t bitMask) const; - TRDCalSingleChamberStatus* getCalROC(Int_t d) const { return mROC[d]; }; - TRDCalSingleChamberStatus* getCalROC(Int_t p, Int_t c, Int_t s) const; + CalSingleChamberStatus* getCalROC(Int_t d) const { return mROC[d]; }; + CalSingleChamberStatus* getCalROC(Int_t p, Int_t c, Int_t s) const; // Plot functions TH1F* makeHisto1D(); @@ -84,12 +84,12 @@ class TRDCalPadStatus void setName(const std::string newName) { mName = newName; }; protected: - TRDCalSingleChamberStatus* mROC[constants::MAXCHAMBER]; // Array of ROC objects which contain the values per pad + CalSingleChamberStatus* mROC[constants::MAXCHAMBER]; // Array of ROC objects which contain the values per pad private: std::string mName; std::string mTitle; - ClassDefNV(TRDCalPadStatus, 1); // TRD calibration class for the single pad status + ClassDefNV(CalPadStatus, 1); // TRD calibration class for the single pad status }; } //namespace trd } //namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/TRDCalSingleChamberStatus.h b/Detectors/TRD/base/include/TRDBase/CalSingleChamberStatus.h similarity index 83% rename from Detectors/TRD/base/include/TRDBase/TRDCalSingleChamberStatus.h rename to Detectors/TRD/base/include/TRDBase/CalSingleChamberStatus.h index b0b0a4189ae7d..d1566ab1b0266 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDCalSingleChamberStatus.h +++ b/Detectors/TRD/base/include/TRDBase/CalSingleChamberStatus.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDCALSINGLECHAMBERSTATUS_H -#define O2_TRDCALSINGLECHAMBERSTATUS_H +#ifndef O2_TRD_CALSINGLECHAMBERSTATUS_H +#define O2_TRD_CALSINGLECHAMBERSTATUS_H #include <Rtypes.h> namespace o2 @@ -24,7 +24,7 @@ namespace trd //////////////////////////////////////////////////////////////////////////// //_____________________________________________________________________________ -class TRDCalSingleChamberStatus +class CalSingleChamberStatus { public: @@ -34,12 +34,12 @@ class TRDCalSingleChamberStatus kReadSecond = 16, kNotConnected = 32 }; - TRDCalSingleChamberStatus(); - TRDCalSingleChamberStatus(Int_t p, Int_t c, Int_t cols); - TRDCalSingleChamberStatus(const TRDCalSingleChamberStatus& c); - ~TRDCalSingleChamberStatus(); - TRDCalSingleChamberStatus& operator=(const TRDCalSingleChamberStatus& c); - void Copy(TRDCalSingleChamberStatus& c) const; + CalSingleChamberStatus(); + CalSingleChamberStatus(Int_t p, Int_t c, Int_t cols); + CalSingleChamberStatus(const CalSingleChamberStatus& c); + ~CalSingleChamberStatus(); + CalSingleChamberStatus& operator=(const CalSingleChamberStatus& c); + void Copy(CalSingleChamberStatus& c) const; Bool_t isMasked(Int_t col, Int_t row) const { return ((getStatus(col, row) & kMasked) ? kTRUE @@ -68,7 +68,7 @@ class TRDCalSingleChamberStatus Int_t mNchannels{0}; // Number of channels std::vector<char> mData; //[fNchannels] Data - ClassDefNV(TRDCalSingleChamberStatus, 1); // TRD ROC calibration class + ClassDefNV(CalSingleChamberStatus, 1); // TRD ROC calibration class }; } // namespace trd diff --git a/Detectors/TRD/base/include/TRDBase/Calibrations.h b/Detectors/TRD/base/include/TRDBase/Calibrations.h index 6dbb386a5c3c5..3a513b399aa3c 100644 --- a/Detectors/TRD/base/include/TRDBase/Calibrations.h +++ b/Detectors/TRD/base/include/TRDBase/Calibrations.h @@ -35,7 +35,7 @@ #include <memory> #include <string> -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "TRDBase/ChamberCalibrations.h" #include "TRDBase/LocalVDrift.h" #include "TRDBase/LocalT0.h" @@ -46,7 +46,7 @@ #include "TRDBase/PadStatus.h" #include "TRDBase/CalOnlineGainTables.h" -class TRDGeometry; +class Geometry; namespace o2 { namespace trd diff --git a/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h b/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h index f286178b252d9..9c433deb76c2e 100644 --- a/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h +++ b/Detectors/TRD/base/include/TRDBase/ChamberCalibrations.h @@ -18,10 +18,10 @@ // Most things were stored in AliTRDcalROC,AliTRDcalPad, AliTRDcalDet // /////////////////////////////////////////////////////////////////////////////// -#include "TRDBase/TRDSimParam.h" +#include "TRDBase/SimParam.h" #include "DataFormatsTRD/Constants.h" // -class TRDGeometry; +class Geometry; namespace o2 { @@ -33,21 +33,21 @@ class ChamberCalibrations ChamberCalibrations() = default; ~ChamberCalibrations() = default; // - float getVDrift(int p, int c, int s) const { return mVDrift[o2::trd::TRDGeometry::getDetector(p, c, s)]; }; + float getVDrift(int p, int c, int s) const { return mVDrift[o2::trd::Geometry::getDetector(p, c, s)]; }; float getVDrift(int roc) const { return mVDrift[roc]; }; - float getGainFactor(int p, int c, int s) const { return mGainFactor[TRDGeometry::getDetector(p, c, s)]; }; + float getGainFactor(int p, int c, int s) const { return mGainFactor[Geometry::getDetector(p, c, s)]; }; float getGainFactor(int roc) const { return mGainFactor[roc]; }; - float getT0(int p, int c, int s) const { return mT0[TRDGeometry::getDetector(p, c, s)]; }; + float getT0(int p, int c, int s) const { return mT0[Geometry::getDetector(p, c, s)]; }; float getT0(int roc) const { return mT0[roc]; }; - float getExB(int p, int c, int s) const { return mExB[TRDGeometry::getDetector(p, c, s)]; }; + float getExB(int p, int c, int s) const { return mExB[Geometry::getDetector(p, c, s)]; }; float getExB(int roc) const { return mExB[roc]; }; - void setVDrift(int p, int c, int s, float vdrift) { mVDrift[o2::trd::TRDGeometry::getDetector(p, c, s)] = vdrift; }; + void setVDrift(int p, int c, int s, float vdrift) { mVDrift[o2::trd::Geometry::getDetector(p, c, s)] = vdrift; }; void setVDrift(int roc, float vdrift) { mVDrift[roc] = vdrift; }; - void setGainFactor(int p, int c, int s, float gainfactor) { mGainFactor[TRDGeometry::getDetector(p, c, s)] = gainfactor; }; + void setGainFactor(int p, int c, int s, float gainfactor) { mGainFactor[Geometry::getDetector(p, c, s)] = gainfactor; }; void setGainFactor(int roc, float gainfactor) { mGainFactor[roc] = gainfactor; }; - void setT0(int p, int c, int s, float t0) { mT0[TRDGeometry::getDetector(p, c, s)] = t0; }; + void setT0(int p, int c, int s, float t0) { mT0[Geometry::getDetector(p, c, s)] = t0; }; void setT0(int roc, float t0) { mT0[roc] = t0; }; - void setExB(int p, int c, int s, float exb) { mExB[TRDGeometry::getDetector(p, c, s)] = exb; }; + void setExB(int p, int c, int s, float exb) { mExB[Geometry::getDetector(p, c, s)] = exb; }; void setExB(int roc, float exb) { mExB[roc] = exb; }; //bulk gets ? bool init(int run2run = 0); diff --git a/Detectors/TRD/base/include/TRDBase/ChamberNoise.h b/Detectors/TRD/base/include/TRDBase/ChamberNoise.h index 37147afd9a216..a6f4df8785fb6 100644 --- a/Detectors/TRD/base/include/TRDBase/ChamberNoise.h +++ b/Detectors/TRD/base/include/TRDBase/ChamberNoise.h @@ -18,10 +18,10 @@ // Originally stored in AliTRDCalDet and instantiated at DetNoise in ocdb // /////////////////////////////////////////////////////////////////////////////// -#include "TRDBase/TRDSimParam.h" +#include "TRDBase/SimParam.h" #include "DataFormatsTRD/Constants.h" // -class TRDGeometry; +class Geometry; namespace o2 { @@ -33,9 +33,9 @@ class ChamberNoise ChamberNoise() = default; ~ChamberNoise() = default; // - float getNoise(int p, int c, int s) const { return mNoise[o2::trd::TRDGeometry::getDetector(p, c, s)]; }; + float getNoise(int p, int c, int s) const { return mNoise[o2::trd::Geometry::getDetector(p, c, s)]; }; float getNoise(int det) const { return mNoise[det]; }; - void setNoise(int p, int c, int s, float noise) { mNoise[o2::trd::TRDGeometry::getDetector(p, c, s)] = noise; }; + void setNoise(int p, int c, int s, float noise) { mNoise[o2::trd::Geometry::getDetector(p, c, s)] = noise; }; void setNoise(int det, float noise) { mNoise[det] = noise; }; //bulk gets ? protected: diff --git a/Detectors/TRD/base/include/TRDBase/ChamberStatus.h b/Detectors/TRD/base/include/TRDBase/ChamberStatus.h index 759aacbb273c7..642a1a56995c4 100644 --- a/Detectors/TRD/base/include/TRDBase/ChamberStatus.h +++ b/Detectors/TRD/base/include/TRDBase/ChamberStatus.h @@ -21,8 +21,8 @@ /////////////////////////////////////////////////////////////////////////////// #include <array> -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDSimParam.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/SimParam.h" #include "DataFormatsTRD/Constants.h" class TH2D; @@ -50,9 +50,9 @@ class ChamberStatus ChamberStatus() = default; ~ChamberStatus() = default; // - // char getStatus(int p, int c, int s) const { int roc=TRDGeometry::getDetector(p,c,s); return mStatus[roc];} + // char getStatus(int p, int c, int s) const { int roc=Geometry::getDetector(p,c,s); return mStatus[roc];} char getStatus(int det) const { return mStatus[det]; } - // void setStatus(int p, int c, int s, char status) { int roc=TRDGeometry::getDetector(p,c,s); setStatus(roc,status);} + // void setStatus(int p, int c, int s, char status) { int roc=Geometry::getDetector(p,c,s); setStatus(roc,status);} void setStatus(int det, char status); void setRawStatus(int det, char status) { mStatus[det] = status; }; void unsetStatusBit(int det, char status); diff --git a/Detectors/TRD/base/include/TRDBase/TRDCommonParam.h b/Detectors/TRD/base/include/TRDBase/CommonParam.h similarity index 80% rename from Detectors/TRD/base/include/TRDBase/TRDCommonParam.h rename to Detectors/TRD/base/include/TRDBase/CommonParam.h index a3a957347c26b..5c1f6e079a9ef 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDCommonParam.h +++ b/Detectors/TRD/base/include/TRDBase/CommonParam.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDCOMMONPARAM_H -#define O2_TRDCOMMONPARAM_H +#ifndef O2_TRD_COMMONPARAM_H +#define O2_TRD_COMMONPARAM_H #include "GPUCommonRtypes.h" @@ -18,19 +18,19 @@ namespace o2 namespace trd { -class TRDPadPlane; +class PadPlane; -class TRDCommonParam +class CommonParam { public: enum { kXenon = 0, kArgon = 1 }; - TRDCommonParam(const TRDCommonParam& p); - TRDCommonParam& operator=(const TRDCommonParam& p); - ~TRDCommonParam(); + CommonParam(const CommonParam& p); + CommonParam& operator=(const CommonParam& p); + ~CommonParam(); - static TRDCommonParam* Instance(); + static CommonParam* Instance(); static void Terminate(); void SetExB(int exbOn = 1) { mExBOn = exbOn; } @@ -56,8 +56,8 @@ class TRDCommonParam void SampleTimeStruct(float vdrift); #ifndef GPUCA_GPUCODE_DEVICE - static TRDCommonParam* fgInstance; // Instance of this class (singleton implementation) - static bool fgTerminated; // Defines if this class has already been terminated + static CommonParam* fgInstance; // Instance of this class (singleton implementation) + static bool fgTerminated; // Defines if this class has already been terminated #endif int mExBOn; // Switch for the ExB effects double mField; // cached magnetic field @@ -77,9 +77,9 @@ class TRDCommonParam private: // This is a singleton, constructor is private! - TRDCommonParam(); + CommonParam(); - ClassDef(TRDCommonParam, 1); // The constant parameters common to simulation and reconstruction + ClassDef(CommonParam, 1); // The constant parameters common to simulation and reconstruction }; } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/TRDDiffAndTimeStructEstimator.h b/Detectors/TRD/base/include/TRDBase/DiffAndTimeStructEstimator.h similarity index 86% rename from Detectors/TRD/base/include/TRDBase/TRDDiffAndTimeStructEstimator.h rename to Detectors/TRD/base/include/TRDBase/DiffAndTimeStructEstimator.h index 3e968847e0e73..33f339ec6e3e1 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDDiffAndTimeStructEstimator.h +++ b/Detectors/TRD/base/include/TRDBase/DiffAndTimeStructEstimator.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDDIFFANDTIMESTRUCTESTIMATOR_H -#define O2_TRDDIFFANDTIMESTRUCTESTIMATOR_H +#ifndef O2_TRD_DIFFANDTIMESTRUCTESTIMATOR_H +#define O2_TRD_DIFFANDTIMESTRUCTESTIMATOR_H #include <array> @@ -23,12 +23,12 @@ constexpr int ktimebin = 38; constexpr int kZbin = 11; /// A class to calculate diffusion and time structure values (GARFIELD model) -/// (used in digitization). Class was split off trom TRDCommonParam +/// (used in digitization). Class was split off trom CommonParam /// and is no longer a singleton so that we can use it in a multithreaded context. -class TRDDiffusionAndTimeStructEstimator +class DiffusionAndTimeStructEstimator { public: - TRDDiffusionAndTimeStructEstimator() = default; + DiffusionAndTimeStructEstimator() = default; /// determines the diffusion coefficients as a function of drift velocity bool GetDiffCoeff(float& dl, float& dt, float vdrift); @@ -55,4 +55,4 @@ class TRDDiffusionAndTimeStructEstimator } // namespace trd } // namespace o2 -#endif //O2_TRDDIFFANDTIMESTRUCTESTIMATOR_H +#endif //O2_TRD_DIFFANDTIMESTRUCTESTIMATOR_H diff --git a/Detectors/TRD/base/include/TRDBase/Digit.h b/Detectors/TRD/base/include/TRDBase/Digit.h index 50cc405d209a6..d76ed2445139b 100644 --- a/Detectors/TRD/base/include/TRDBase/Digit.h +++ b/Detectors/TRD/base/include/TRDBase/Digit.h @@ -19,7 +19,7 @@ #include "Rtypes.h" // for ClassDef #include "CommonDataFormat/TimeStamp.h" -#include "TRDBase/TRDCommonParam.h" +#include "TRDBase/CommonParam.h" #include "DataFormatsTRD/Constants.h" namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/FeeParam.h b/Detectors/TRD/base/include/TRDBase/FeeParam.h index f0c43617a695c..5e16d67b1aa7e 100644 --- a/Detectors/TRD/base/include/TRDBase/FeeParam.h +++ b/Detectors/TRD/base/include/TRDBase/FeeParam.h @@ -31,9 +31,9 @@ #include <array> #include <vector> -class TRDCommonParam; -class TRDPadPlane; -class TRDGeometry; +class CommonParam; +class PadPlane; +class Geometry; namespace o2 { @@ -140,7 +140,7 @@ class FeeParam static FeeParam* mgInstance; // Singleton instance static bool mgTerminated; // Defines if this class has already been terminated - TRDCommonParam* mCP = nullptr; // TRD common parameters class + CommonParam* mCP = nullptr; // TRD common parameters class static std::vector<short> mgLUTPadNumbering; // Lookup table mapping Pad to MCM static bool mgLUTPadNumberingFilled; // Lookup table mapping Pad to MCM diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometry.h b/Detectors/TRD/base/include/TRDBase/Geometry.h similarity index 77% rename from Detectors/TRD/base/include/TRDBase/TRDGeometry.h rename to Detectors/TRD/base/include/TRDBase/Geometry.h index 1e9ec5a5beefa..eb9c6573424cf 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometry.h +++ b/Detectors/TRD/base/include/TRDBase/Geometry.h @@ -8,10 +8,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDGEOMETRY_H -#define O2_TRDGEOMETRY_H +#ifndef O2_TRD_GEOMETRY_H +#define O2_TRD_GEOMETRY_H -#include "TRDBase/TRDGeometryBase.h" +#include "TRDBase/GeometryBase.h" #include "DetectorsCommonDataFormats/DetMatrixCache.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -19,24 +19,19 @@ #include <vector> #include <memory> -using namespace o2::trd; -class TRootIOCtor; - namespace o2 { namespace trd { -class TRDGeometry : public TRDGeometryBase, public o2::detectors::DetMatrixCacheIndirect +class Geometry : public GeometryBase, public o2::detectors::DetMatrixCacheIndirect { public: - ~TRDGeometry() override = default; - // A ROOT IO constructor (to silence warnings about missing default constructor) - TRDGeometry(TRootIOCtor*) {} + ~Geometry() override = default; - static TRDGeometry* instance() + static Geometry* instance() { - static TRDGeometry mGeom; + static Geometry mGeom; return &mGeom; } @@ -65,9 +60,9 @@ class TRDGeometry : public TRDGeometryBase, public o2::detectors::DetMatrixCache // helper function to create volumes and registering them automatically void createVolume(const char* name, const char* shape, int nmed, float* upar, int np); - TRDGeometry(); + Geometry(); - ClassDefOverride(TRDGeometry, 2); // TRD geometry class + ClassDefOverride(Geometry, 2); // TRD geometry class }; } // end namespace trd } // end namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h b/Detectors/TRD/base/include/TRDBase/GeometryBase.h similarity index 96% rename from Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h rename to Detectors/TRD/base/include/TRDBase/GeometryBase.h index eb06c9ae1c263..7bb5fec24b65d 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryBase.h +++ b/Detectors/TRD/base/include/TRDBase/GeometryBase.h @@ -8,23 +8,22 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDGEOMETRYBASE_H -#define O2_TRDGEOMETRYBASE_H +#ifndef O2_TRD_GEOMETRYBASE_H +#define O2_TRD_GEOMETRYBASE_H #include "GPUCommonDef.h" -#include "TRDBase/TRDCommonParam.h" +#include "TRDBase/CommonParam.h" #include "DataFormatsTRD/Constants.h" -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/PadPlane.h" namespace o2 { namespace trd { -class TRDGeometryBase +class GeometryBase { public: - ~TRDGeometryBase() = default; - + ~GeometryBase() = default; GPUd() int isVersion() { return 1; } GPUd() bool isHole(int la, int st, int se) const { return (((se == 13) || (se == 14) || (se == 15)) && (st == 2)); } @@ -46,8 +45,8 @@ class TRDGeometryBase GPUd() static int getStack(int det) { return ((det % (constants::NLAYER * constants::NSTACK)) / constants::NLAYER); } GPUd() int getStack(float z, int layer) const; - GPUd() const TRDPadPlane* getPadPlane(int layer, int stack) const { return &mPadPlanes[getDetectorSec(layer, stack)]; } - GPUd() const TRDPadPlane* getPadPlane(int det) const { return &mPadPlanes[getDetectorSec(det)]; } + GPUd() const PadPlane* getPadPlane(int layer, int stack) const { return &mPadPlanes[getDetectorSec(layer, stack)]; } + GPUd() const PadPlane* getPadPlane(int det) const { return &mPadPlanes[getDetectorSec(det)]; } GPUd() int getRowMax(int layer, int stack, int /*sector*/) const { return getPadPlane(layer, stack)->getNrows(); } GPUd() int getColMax(int layer) const { return getPadPlane(layer, 0)->getNcols(); } @@ -95,7 +94,7 @@ class TRDGeometryBase static constexpr GPUd() int rowmaxC1() { return ROWMAXC1; } protected: - TRDGeometryBase() = default; + GeometryBase() = default; static constexpr float TLENGTH = 751.0; ///< Total length of the TRD mother volume @@ -211,11 +210,11 @@ class TRDGeometryBase {145.0, 145.0, 110.0, 145.0, 145.0}, {147.0, 147.0, 110.0, 147.0, 147.0}}; - TRDPadPlane mPadPlanes[constants::NLAYER * constants::NSTACK]; + PadPlane mPadPlanes[constants::NLAYER * constants::NSTACK]; int mSMStatus = 0x3ffff; - ClassDefNV(TRDGeometryBase, 1); + ClassDefNV(GeometryBase, 1); }; } // end namespace trd } // end namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h b/Detectors/TRD/base/include/TRDBase/GeometryFlat.h similarity index 75% rename from Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h rename to Detectors/TRD/base/include/TRDBase/GeometryFlat.h index 8e5ae76b6ff0d..394c4be5595af 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDGeometryFlat.h +++ b/Detectors/TRD/base/include/TRDBase/GeometryFlat.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDGEOMETRYFLAT_H -#define O2_TRDGEOMETRYFLAT_H +#ifndef O2_TRD_GEOMETRYFLAT_H +#define O2_TRD_GEOMETRYFLAT_H #ifndef GPUCA_GPUCODE_DEVICE #include <cstring> @@ -17,32 +17,30 @@ #include "FlatObject.h" #include "GPUCommonDef.h" #include "GPUCommonTransform3D.h" -#include "TRDBase/TRDGeometryBase.h" -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/GeometryBase.h" +#include "TRDBase/PadPlane.h" #include "DataFormatsTRD/Constants.h" -using namespace o2::trd; - namespace o2 { namespace trd { -class TRDGeometry; +class Geometry; //Reduced flat version of TRD geometry class. //Contains all entries required for tracking on GPUs. -class TRDGeometryFlat : public o2::gpu::FlatObject, public TRDGeometryBase +class GeometryFlat : public o2::gpu::FlatObject, public GeometryBase { public: #ifndef GPUCA_GPUCODE_DEVICE - TRDGeometryFlat() = default; - TRDGeometryFlat(const TRDGeometryFlat& v) : FlatObject(), TRDGeometryBase() + GeometryFlat() = default; + GeometryFlat(const GeometryFlat& v) : FlatObject(), GeometryBase() { memcpy((void*)this, (void*)&v, sizeof(*this)); } - TRDGeometryFlat(const TRDGeometry& geo); - ~TRDGeometryFlat() = default; + GeometryFlat(const Geometry& geo); + ~GeometryFlat() = default; #endif GPUd() const o2::gpu::Transform3D* getMatrixT2L(int det) const { diff --git a/Detectors/TRD/base/include/TRDBase/PadCalibrations.h b/Detectors/TRD/base/include/TRDBase/PadCalibrations.h index f42e5d524d2ac..f0523a6e9d53f 100644 --- a/Detectors/TRD/base/include/TRDBase/PadCalibrations.h +++ b/Detectors/TRD/base/include/TRDBase/PadCalibrations.h @@ -21,10 +21,10 @@ #include <array> #include "TRDBase/PadParameters.h" -#include "TRDBase/TRDSimParam.h" +#include "TRDBase/SimParam.h" #include "DataFormatsTRD/Constants.h" -class TRDGeometry; +class Geometry; namespace o2 { @@ -54,9 +54,9 @@ template <class T> PadCalibrations<T>::PadCalibrations() { // - // TRDCalPadStatus constructor + // CalPadStatus constructor // - //TRDGeometry fgeom; + //Geometry fgeom; int chamberindex = 0; for (auto& roc : mreadOutChamber) { // Range-for! roc.init(chamberindex++); @@ -67,7 +67,7 @@ template <class T> void PadCalibrations<T>::init() { // - // TRDCalPadStatus constructor + // CalPadStatus constructor // int chamberindex = 0; for (auto& roc : mreadOutChamber) { // Range-for! diff --git a/Detectors/TRD/base/include/TRDBase/PadParameters.h b/Detectors/TRD/base/include/TRDBase/PadParameters.h index 7743e20a9ebeb..a147d21f19c99 100644 --- a/Detectors/TRD/base/include/TRDBase/PadParameters.h +++ b/Detectors/TRD/base/include/TRDBase/PadParameters.h @@ -22,8 +22,8 @@ // #include <vector> -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDSimParam.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/SimParam.h" #include "TRDBase/FeeParam.h" #include "DataFormatsTRD/Constants.h" @@ -70,8 +70,8 @@ PadParameters<T>::PadParameters(int chamberindex) template <class T> int PadParameters<T>::init(int chamberindex) { - mPlane = TRDGeometry::getLayer(chamberindex); - mChamber = TRDGeometry::getStack(chamberindex); + mPlane = Geometry::getLayer(chamberindex); + mChamber = Geometry::getStack(chamberindex); if (mChamber == 2) { mNrows = constants::NROWC0; } else { @@ -89,8 +89,8 @@ int PadParameters<T>::init(int chamberindex) template <class T> int PadParameters<T>::reset(int chamberindex, int cols, int rows, std::vector<T>& data) { - mPlane = TRDGeometry::getLayer(chamberindex); - mChamber = TRDGeometry::getStack(chamberindex); + mPlane = Geometry::getLayer(chamberindex); + mChamber = Geometry::getStack(chamberindex); mNrows = rows; mNcols = cols; // the FeeParam variables need to be unprotected, and dont want to change FeeParam in this PR. diff --git a/Detectors/TRD/base/include/TRDBase/TRDPadPlane.h b/Detectors/TRD/base/include/TRDBase/PadPlane.h similarity index 94% rename from Detectors/TRD/base/include/TRDBase/TRDPadPlane.h rename to Detectors/TRD/base/include/TRDBase/PadPlane.h index 8ac893a2ffa25..7e72d508c0e03 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDPadPlane.h +++ b/Detectors/TRD/base/include/TRDBase/PadPlane.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDPADPLANE_H -#define O2_TRDPADPLANE_H +#ifndef O2_TRD_PADPLANE_H +#define O2_TRD_PADPLANE_H //Forwards to standard header with protection for GPU compilation #include "GPUCommonRtypes.h" // for ClassDef @@ -30,14 +30,14 @@ namespace o2 { namespace trd { -class TRDPadPlane +class PadPlane { public: - TRDPadPlane() = default; - TRDPadPlane(int layer, int stack) : mLayer(layer), mStack(stack){}; - TRDPadPlane(const TRDPadPlane& p) = delete; - TRDPadPlane& operator=(const TRDPadPlane& p) = delete; - ~TRDPadPlane() = default; + PadPlane() = default; + PadPlane(int layer, int stack) : mLayer(layer), mStack(stack){}; + PadPlane(const PadPlane& p) = delete; + PadPlane& operator=(const PadPlane& p) = delete; + ~PadPlane() = default; void setLayer(int l) { mLayer = l; }; void setStack(int s) { mStack = s; }; @@ -175,7 +175,7 @@ class TRDPadPlane double mAnodeWireOffset; // Distance of first anode wire from pad edge private: - ClassDefNV(TRDPadPlane, 1); // TRD ROC pad plane + ClassDefNV(PadPlane, 1); // TRD ROC pad plane }; } // namespace trd } // namespace o2 diff --git a/Detectors/TRD/base/include/TRDBase/TRDSimParam.h b/Detectors/TRD/base/include/TRDBase/SimParam.h similarity index 90% rename from Detectors/TRD/base/include/TRDBase/TRDSimParam.h rename to Detectors/TRD/base/include/TRDBase/SimParam.h index 3440682c7078a..e6de326bc8650 100644 --- a/Detectors/TRD/base/include/TRDBase/TRDSimParam.h +++ b/Detectors/TRD/base/include/TRDBase/SimParam.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_TRDSIMPARAM_H -#define O2_TRDSIMPARAM_H +#ifndef O2_TRD_SIMPARAM_H +#define O2_TRD_SIMPARAM_H //Forwards to standard header with protection for GPU compilation #include "GPUCommonRtypes.h" // for ClassDef @@ -23,14 +23,14 @@ namespace trd // Class containing constant simulation parameters // // // //////////////////////////////////////////////////////////////////////////// -class TRDSimParam +class SimParam { public: enum { kNPadsInPadResponse = 3 // Number of pads included in the pad response }; - static TRDSimParam* Instance(); + static SimParam* Instance(); static void Terminate(); void SetGasGain(float gasgain) { mGasGain = gasgain; } @@ -83,9 +83,9 @@ class TRDSimParam void ReInit(); protected: - static TRDSimParam* fgInstance; // Instance of this class (singleton implementation) - static bool fgTerminated; // Defines if this class has already been terminated and - // therefore does not return instances in GetInstance anymore + static SimParam* fgInstance; // Instance of this class (singleton implementation) + static bool fgTerminated; // Defines if this class has already been terminated and + // therefore does not return instances in GetInstance anymore // Digitization parameter float mGasGain; // Gas gain @@ -122,16 +122,16 @@ class TRDSimParam private: // This is a singleton, constructor is private! - TRDSimParam(); - ~TRDSimParam(); + SimParam(); + ~SimParam(); void Init(); void SampleTRF(); - ClassDefNV(TRDSimParam, 1); // The TRD simulation parameters + ClassDefNV(SimParam, 1); // The TRD simulation parameters }; -inline double TRDSimParam::TimeResponse(double time) const +inline double SimParam::TimeResponse(double time) const { // // Applies the preamp shaper time response @@ -148,7 +148,7 @@ inline double TRDSimParam::TimeResponse(double time) const } } -inline double TRDSimParam::CrossTalk(double time) const +inline double SimParam::CrossTalk(double time) const { // // Applies the pad-pad capacitive cross talk diff --git a/Detectors/TRD/base/include/TRDBase/Tracklet.h b/Detectors/TRD/base/include/TRDBase/Tracklet.h index 0a3e14de509e4..88d6d042ff35f 100644 --- a/Detectors/TRD/base/include/TRDBase/Tracklet.h +++ b/Detectors/TRD/base/include/TRDBase/Tracklet.h @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -//#include "TRDBase/TRDGeometryBase.h" +//#include "TRDBase/GeometryBase.h" //#include "DetectorsCommonDataFormats/DetMatrixCache.h" //#include "DetectorsCommonDataFormats/DetID.h" @@ -32,7 +32,7 @@ #include <memory> // for std::unique_ptr #include "Rtypes.h" // for ClassDef -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include <SimulationDataFormat/MCCompLabel.h> namespace o2 @@ -125,7 +125,7 @@ class Tracklet std::vector<float> getClsCharges() const { return mClsCharges; } //TODO this is a problem, giving a pointer out to an internal class member protected: - TRDGeometry* mGeo; //! TRD geometry + Geometry* mGeo; //! TRD geometry int mHCId; // half-chamber ID (only transient) // unsigned int mTrackletWord; // tracklet word: PID | Z | deflection length | Y diff --git a/Detectors/TRD/base/macros/OCDB2CCDB.C b/Detectors/TRD/base/macros/OCDB2CCDB.C index 132546513eecf..ae27dbfafc420 100644 --- a/Detectors/TRD/base/macros/OCDB2CCDB.C +++ b/Detectors/TRD/base/macros/OCDB2CCDB.C @@ -77,7 +77,7 @@ #include "TRDBase/ChamberNoise.h" #include "TRDBase/CalOnlineGainTables.h" #include "TRDBase/FeeParam.h" -#include "TRDBase/TrapConfig.h" +#include "TRDSimulation/TrapConfig.h" using namespace std; using namespace o2::ccdb; @@ -453,38 +453,38 @@ void OCDB2CCDB(Int_t run, const Char_t* storageURI = "alien://folder=/alice/data /* THESE ARE THE ONES NOT CURRENTLY INCLUDED. -trd_ddchamberStatus -trd_gaschromatographXe -trd_gasOverpressure +trd_ddchamberStatus +trd_gaschromatographXe +trd_gasOverpressure trd_hvDriftImon -MonitoringData -PIDLQ -trd_envTemp -trd_gasCO2 +MonitoringData +PIDLQ +trd_envTemp +trd_gasCO2 trd_hvDriftUmon -PIDLQ1D -trd_gaschromatographCO2 -trd_gasH2O -trd_hvAnodeImon +PIDLQ1D +trd_gaschromatographCO2 +trd_gasH2O +trd_hvAnodeImon TrkAttach -PIDNN -PHQ PIDThresholds +PIDNN +PHQ PIDThresholds This pulls stuff from DCS I should hopefully not need this stuff for simulation. -DCS +DCS AliTRDSensorArray descends from AliTRDDCSSensorArray -trd_gaschromatographN2 -trd_gasO2 -trd_goofieHv -trd_goofiePressure +trd_gaschromatographN2 +trd_gasO2 +trd_goofieHv +trd_goofiePressure trd_hvAnodeUmon -trd_goofieN2 -trd_goofieTemp -trd_goofieCO2 -trd_goofiePeakArea -trd_goofieVelocity -trd_goofieGain -trd_goofiePeakPos +trd_goofieN2 +trd_goofieTemp +trd_goofieCO2 +trd_goofiePeakArea +trd_goofieVelocity +trd_goofieGain +trd_goofiePeakPos */ return; } diff --git a/Detectors/TRD/base/src/CalDet.cxx b/Detectors/TRD/base/src/CalDet.cxx index 9923bbbd82dc9..7fdf6ecd2a6fb 100644 --- a/Detectors/TRD/base/src/CalDet.cxx +++ b/Detectors/TRD/base/src/CalDet.cxx @@ -20,8 +20,8 @@ #include <TH2F.h> #include <TRobustEstimator.h> -#include "TRDBase/TRDPadPlane.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/PadPlane.h" +#include "TRDBase/Geometry.h" #include "TRDBase/CalDet.h" // #include "AliMathBase.h" @@ -328,7 +328,7 @@ TH2F* CalDet::makeHisto2DCh(int ch, float min, float max, int type) } } - TRDGeometry* trdGeo = TRDGeometry::instance(); + Geometry* trdGeo = Geometry::instance(); float poslocal[3] = {0, 0, 0}; float posglobal[3] = {0, 0, 0}; @@ -344,7 +344,7 @@ TH2F* CalDet::makeHisto2DCh(int ch, float min, float max, int type) for (int isec = 0; isec < NSECTOR; isec++) { for (int ipl = 0; ipl < NLAYER; ipl++) { int det = offsetch + isec * 30 + ipl; - const TRDPadPlane* padPlane = trdGeo->getPadPlane(ipl, ch); + const PadPlane* padPlane = trdGeo->getPadPlane(ipl, ch); for (int icol = 0; icol < padPlane->getNcols(); icol++) { poslocal[0] = trdGeo->getTime0(ipl); poslocal[2] = padPlane->getRowPos(0); @@ -401,8 +401,8 @@ TH2F* CalDet::makeHisto2DSmPl(int sm, int pl, float min, float max, int type) } } - TRDGeometry* trdGeo = TRDGeometry::instance(); - const TRDPadPlane* padPlane0 = trdGeo->getPadPlane(pl, 0); + Geometry* trdGeo = Geometry::instance(); + const PadPlane* padPlane0 = trdGeo->getPadPlane(pl, 0); double row0 = padPlane0->getRow0(); double col0 = padPlane0->getCol0(); diff --git a/Detectors/TRD/base/src/CalOnlineGainTables.cxx b/Detectors/TRD/base/src/CalOnlineGainTables.cxx index 31b15418542e8..6164137870c2f 100644 --- a/Detectors/TRD/base/src/CalOnlineGainTables.cxx +++ b/Detectors/TRD/base/src/CalOnlineGainTables.cxx @@ -16,7 +16,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "TRDBase/CalOnlineGainTables.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "TRDBase/FeeParam.h" #include "DataFormatsTRD/Constants.h" diff --git a/Detectors/TRD/base/src/CalPad.cxx b/Detectors/TRD/base/src/CalPad.cxx index acee7e291ca6d..418e36c51c247 100644 --- a/Detectors/TRD/base/src/CalPad.cxx +++ b/Detectors/TRD/base/src/CalPad.cxx @@ -14,8 +14,8 @@ #include <TStyle.h> #include "TRDBase/CalPad.h" -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/PadPlane.h" #include "CalROC.h" #include "CalDet.h" @@ -426,7 +426,7 @@ TH2F* CalPad::makeHisto2DSmPl(int sm, int pl, const CalDet* calDet, int typedet, float kEpsilon = 0.000000000001; - TRDGeometry* trdGeo = new TRDGeometry(); + Geometry* trdGeo = new Geometry(); if (type >= 0) { float kEpsilonr = 0.005; @@ -571,7 +571,7 @@ TH2F* CalPad::makeHisto2DCh(int ch, const CalDet* calDet, int typedet, float min } } - TRDGeometry* trdGeo = new TRDGeometry(); + Geometry* trdGeo = new Geometry(); float kEpsilon = 0.000000000001; diff --git a/Detectors/TRD/base/src/TRDCalPadStatus.cxx b/Detectors/TRD/base/src/CalPadStatus.cxx similarity index 79% rename from Detectors/TRD/base/src/TRDCalPadStatus.cxx rename to Detectors/TRD/base/src/CalPadStatus.cxx index f4852f457aea3..de82b5155ba33 100644 --- a/Detectors/TRD/base/src/TRDCalPadStatus.cxx +++ b/Detectors/TRD/base/src/CalPadStatus.cxx @@ -19,23 +19,23 @@ #include <TStyle.h> #include <TCanvas.h> -#include "TRDBase/TRDGeometryBase.h" +#include "TRDBase/GeometryBase.h" #include "DetectorsCommonDataFormats/DetMatrixCache.h" #include "DetectorsCommonDataFormats/DetID.h" -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDPadPlane.h" -#include "TRDBase/TRDCalSingleChamberStatus.h" // test -#include "TRDBase/TRDCalPadStatus.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/PadPlane.h" +#include "TRDBase/CalSingleChamberStatus.h" // test +#include "TRDBase/CalPadStatus.h" using namespace o2::trd; using namespace o2::trd::constants; //_____________________________________________________________________________ -TRDCalPadStatus::TRDCalPadStatus() +CalPadStatus::CalPadStatus() { // - // TRDCalPadStatus default constructor + // CalPadStatus default constructor // for (int idet = 0; idet < MAXCHAMBER; idet++) { @@ -44,18 +44,18 @@ TRDCalPadStatus::TRDCalPadStatus() } //_____________________________________________________________________________ -TRDCalPadStatus::TRDCalPadStatus(const Text_t* name, const Text_t* title) +CalPadStatus::CalPadStatus(const Text_t* name, const Text_t* title) { // - // TRDCalPadStatus constructor + // CalPadStatus constructor // - //TRDGeometry fgeom; + //Geometry fgeom; for (int isec = 0; isec < NSECTOR; isec++) { for (int ipla = 0; ipla < NLAYER; ipla++) { for (int icha = 0; icha < NSTACK; icha++) { - int idet = o2::trd::TRDGeometry::getDetector(ipla, icha, isec); - // int idet = fgeom.getDetector(ipla,icha,isec);//TRDGeometryBase::getDetector(ipla,icha,isec); - mROC[idet] = new TRDCalSingleChamberStatus(ipla, icha, 144); + int idet = o2::trd::Geometry::getDetector(ipla, icha, isec); + // int idet = fgeom.getDetector(ipla,icha,isec);//GeometryBase::getDetector(ipla,icha,isec); + mROC[idet] = new CalSingleChamberStatus(ipla, icha, 144); } } } @@ -64,20 +64,20 @@ TRDCalPadStatus::TRDCalPadStatus(const Text_t* name, const Text_t* title) } //_____________________________________________________________________________ -TRDCalPadStatus::TRDCalPadStatus(const TRDCalPadStatus& c) +CalPadStatus::CalPadStatus(const CalPadStatus& c) { // - // TRDCalPadStatus copy constructor + // CalPadStatus copy constructor // - ((TRDCalPadStatus&)c).Copy(*this); + ((CalPadStatus&)c).Copy(*this); } //_____________________________________________________________________________ -TRDCalPadStatus::~TRDCalPadStatus() +CalPadStatus::~CalPadStatus() { // - // TRDCalPadStatus destructor + // CalPadStatus destructor // for (int idet = 0; idet < MAXCHAMBER; idet++) { @@ -89,19 +89,19 @@ TRDCalPadStatus::~TRDCalPadStatus() } //_____________________________________________________________________________ -TRDCalPadStatus& TRDCalPadStatus::operator=(const TRDCalPadStatus& c) +CalPadStatus& CalPadStatus::operator=(const CalPadStatus& c) { // // Assignment operator // if (this != &c) - ((TRDCalPadStatus&)c).Copy(*this); + ((CalPadStatus&)c).Copy(*this); return *this; } //_____________________________________________________________________________ -void TRDCalPadStatus::Copy(TRDCalPadStatus& c) const +void CalPadStatus::Copy(CalPadStatus& c) const { // // Copy function @@ -109,19 +109,19 @@ void TRDCalPadStatus::Copy(TRDCalPadStatus& c) const for (int idet = 0; idet < MAXCHAMBER; idet++) { if (mROC[idet]) { - mROC[idet]->Copy(*((TRDCalPadStatus&)c).mROC[idet]); + mROC[idet]->Copy(*((CalPadStatus&)c).mROC[idet]); } } } //_____________________________________________________________________________ -Bool_t TRDCalPadStatus::checkStatus(int d, int col, int row, int bitMask) const +Bool_t CalPadStatus::checkStatus(int d, int col, int row, int bitMask) const { // // Checks the pad status // - TRDCalSingleChamberStatus* roc = getCalROC(d); + CalSingleChamberStatus* roc = getCalROC(d); if (!roc) { return kFALSE; } else { @@ -130,18 +130,18 @@ Bool_t TRDCalPadStatus::checkStatus(int d, int col, int row, int bitMask) const } //_____________________________________________________________________________ -TRDCalSingleChamberStatus* TRDCalPadStatus::getCalROC(int p, int c, int s) const +CalSingleChamberStatus* CalPadStatus::getCalROC(int p, int c, int s) const { // // Returns the readout chamber of this pad // - //TRDGeometry fgeom; + //Geometry fgeom; //return mROC[fgeom.getDetector(p,c,s)]; - return mROC[o2::trd::TRDGeometry::getDetector(p, c, s)]; + return mROC[o2::trd::Geometry::getDetector(p, c, s)]; } //_____________________________________________________________________________ -TH1F* TRDCalPadStatus::makeHisto1D() +TH1F* CalPadStatus::makeHisto1D() { // // Make 1D histo @@ -180,15 +180,15 @@ TH1F* TRDCalPadStatus::makeHisto1D() } //_____________________________________________________________________________ -TH2F* TRDCalPadStatus::makeHisto2DSmPl(int sm, int pl) +TH2F* CalPadStatus::makeHisto2DSmPl(int sm, int pl) { // // Make 2D graph // gStyle->SetPalette(1); - TRDGeometry* trdGeo = new TRDGeometry(); - const TRDPadPlane* padPlane0 = trdGeo->getPadPlane(pl, 0); + Geometry* trdGeo = new Geometry(); + const PadPlane* padPlane0 = trdGeo->getPadPlane(pl, 0); Double_t row0 = padPlane0->getRow0(); Double_t col0 = padPlane0->getCol0(); @@ -202,7 +202,7 @@ TH2F* TRDCalPadStatus::makeHisto2DSmPl(int sm, int pl) for (int k = 0; k < NSTACK; k++) { int det = offsetsmpl + k * 6; if (mROC[det]) { - TRDCalSingleChamberStatus* calRoc = mROC[det]; + CalSingleChamberStatus* calRoc = mROC[det]; for (int icol = 0; icol < calRoc->getNcols(); icol++) { for (int irow = 0; irow < calRoc->getNrows(); irow++) { int binz = 0; @@ -252,7 +252,7 @@ TH2F* TRDCalPadStatus::makeHisto2DSmPl(int sm, int pl) } //_____________________________________________________________________________ -void TRDCalPadStatus::plotHistos2DSm(int sm, const char* name) +void CalPadStatus::plotHistos2DSm(int sm, const char* name) { // // Make 2D graph diff --git a/Detectors/TRD/base/src/TRDCalSingleChamberStatus.cxx b/Detectors/TRD/base/src/CalSingleChamberStatus.cxx similarity index 84% rename from Detectors/TRD/base/src/TRDCalSingleChamberStatus.cxx rename to Detectors/TRD/base/src/CalSingleChamberStatus.cxx index bc44f6a19dbf7..f74a3817df95f 100644 --- a/Detectors/TRD/base/src/TRDCalSingleChamberStatus.cxx +++ b/Detectors/TRD/base/src/CalSingleChamberStatus.cxx @@ -15,18 +15,18 @@ // // /////////////////////////////////////////////////////////////////////////////// -#include "TRDBase/TRDCalSingleChamberStatus.h" +#include "TRDBase/CalSingleChamberStatus.h" #include <TMath.h> #include <Rtypes.h> -#include "TRDBase/TRDCommonParam.h" +#include "TRDBase/CommonParam.h" using namespace o2::trd; //_____________________________________________________________________________ -TRDCalSingleChamberStatus::TRDCalSingleChamberStatus() = default; +CalSingleChamberStatus::CalSingleChamberStatus() = default; //_____________________________________________________________________________ -TRDCalSingleChamberStatus::TRDCalSingleChamberStatus(Int_t p, Int_t c, Int_t cols) +CalSingleChamberStatus::CalSingleChamberStatus(Int_t p, Int_t c, Int_t cols) : mPla(p), mCha(c), mNcols(cols) { // @@ -101,21 +101,21 @@ TRDCalSingleChamberStatus::TRDCalSingleChamberStatus(Int_t p, Int_t c, Int_t col } //_____________________________________________________________________________ -TRDCalSingleChamberStatus::TRDCalSingleChamberStatus(const TRDCalSingleChamberStatus& c) +CalSingleChamberStatus::CalSingleChamberStatus(const CalSingleChamberStatus& c) : mPla(c.mPla), mCha(c.mCha), mNrows(c.mNrows), mNcols(c.mNcols), mNchannels(c.mNchannels) { // - // TRDCalSingleChamberStatus copy constructor + // CalSingleChamberStatus copy constructor // mData = c.mData; } //_____________________________________________________________________________ -TRDCalSingleChamberStatus::~TRDCalSingleChamberStatus() = default; +CalSingleChamberStatus::~CalSingleChamberStatus() = default; //_____________________________________________________________________________ -TRDCalSingleChamberStatus& TRDCalSingleChamberStatus::operator=(const TRDCalSingleChamberStatus& c) +CalSingleChamberStatus& CalSingleChamberStatus::operator=(const CalSingleChamberStatus& c) { // // Assignment operator @@ -136,7 +136,7 @@ TRDCalSingleChamberStatus& TRDCalSingleChamberStatus::operator=(const TRDCalSing } //_____________________________________________________________________________ -void TRDCalSingleChamberStatus::Copy(TRDCalSingleChamberStatus& c) const +void CalSingleChamberStatus::Copy(CalSingleChamberStatus& c) const { // // Copy function diff --git a/Detectors/TRD/base/src/Calibrations.cxx b/Detectors/TRD/base/src/Calibrations.cxx index 64a45c7ab116a..fe251323adfc6 100644 --- a/Detectors/TRD/base/src/Calibrations.cxx +++ b/Detectors/TRD/base/src/Calibrations.cxx @@ -18,7 +18,7 @@ #include <sstream> #include <string> -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "TRDBase/Calibrations.h" #include "TRDBase/ChamberCalibrations.h" #include "TRDBase/ChamberNoise.h" diff --git a/Detectors/TRD/base/src/ChamberNoise.cxx b/Detectors/TRD/base/src/ChamberNoise.cxx index 9145783b0ca7e..f1e48b53fd5db 100644 --- a/Detectors/TRD/base/src/ChamberNoise.cxx +++ b/Detectors/TRD/base/src/ChamberNoise.cxx @@ -16,7 +16,7 @@ #include <array> -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "TRDBase/ChamberNoise.h" #include "TH2D.h" diff --git a/Detectors/TRD/base/src/TRDCommonParam.cxx b/Detectors/TRD/base/src/CommonParam.cxx similarity index 98% rename from Detectors/TRD/base/src/TRDCommonParam.cxx rename to Detectors/TRD/base/src/CommonParam.cxx index c453569edf190..c8fe591d0536d 100644 --- a/Detectors/TRD/base/src/TRDCommonParam.cxx +++ b/Detectors/TRD/base/src/CommonParam.cxx @@ -21,20 +21,20 @@ #include <TMath.h> #include <FairLogger.h> -#include "TRDBase/TRDCommonParam.h" -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDSimParam.h" +#include "TRDBase/CommonParam.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/SimParam.h" #include "Field/MagneticField.h" using namespace o2::trd; -ClassImp(TRDCommonParam); +ClassImp(CommonParam); -TRDCommonParam* TRDCommonParam::fgInstance = nullptr; -bool TRDCommonParam::fgTerminated = false; +CommonParam* CommonParam::fgInstance = nullptr; +bool CommonParam::fgTerminated = false; //_ singleton implementation __________________________________________________ -TRDCommonParam* TRDCommonParam::Instance() +CommonParam* CommonParam::Instance() { // // Singleton implementation @@ -46,14 +46,14 @@ TRDCommonParam* TRDCommonParam::Instance() } if (fgInstance == nullptr) { - fgInstance = new TRDCommonParam(); + fgInstance = new CommonParam(); } return fgInstance; } //_____________________________________________________________________________ -void TRDCommonParam::Terminate() +void CommonParam::Terminate() { // // Singleton implementation @@ -71,7 +71,7 @@ void TRDCommonParam::Terminate() } //_____________________________________________________________________________ -TRDCommonParam::TRDCommonParam() +CommonParam::CommonParam() : mExBOn(true), mDiffusionT(0.0), mDiffusionL(0.0), @@ -91,7 +91,7 @@ TRDCommonParam::TRDCommonParam() } //_____________________________________________________________________________ -TRDCommonParam::~TRDCommonParam() +CommonParam::~CommonParam() { // // Destructor @@ -107,7 +107,7 @@ TRDCommonParam::~TRDCommonParam() } //_____________________________________________________________________________ -bool TRDCommonParam::cacheMagField() +bool CommonParam::cacheMagField() { // The magnetic field strength const o2::field::MagneticField* fld = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); @@ -120,7 +120,7 @@ bool TRDCommonParam::cacheMagField() } //_____________________________________________________________________________ -float TRDCommonParam::GetOmegaTau(float vdrift) +float CommonParam::GetOmegaTau(float vdrift) { /* // @@ -176,7 +176,7 @@ float TRDCommonParam::GetOmegaTau(float vdrift) } //_____________________________________________________________________________ -bool TRDCommonParam::GetDiffCoeff(float& dl, float& dt, float vdrift) +bool CommonParam::GetDiffCoeff(float& dl, float& dt, float vdrift) { // // Calculates the diffusion coefficients in longitudinal <dl> and @@ -239,7 +239,7 @@ bool TRDCommonParam::GetDiffCoeff(float& dl, float& dt, float vdrift) } //_____________________________________________________________________________ -double TRDCommonParam::TimeStruct(float vdrift, double dist, double z) +double CommonParam::TimeStruct(float vdrift, double dist, double z) { // // Applies the time structure of the drift cells (by C.Lippmann). @@ -300,7 +300,7 @@ double TRDCommonParam::TimeStruct(float vdrift, double dist, double z) // Dist now is the drift distance to the anode wires (negative if electrons are // between anode wire plane and cathode pad plane) - dist -= TRDGeometry::amThick() / 2.0; + dist -= Geometry::amThick() / 2.0; // Interpolation in z-directions, lower drift time map const float ktdrift1 = @@ -318,7 +318,7 @@ double TRDCommonParam::TimeStruct(float vdrift, double dist, double z) } //_____________________________________________________________________________ -void TRDCommonParam::SampleTimeStruct(float vdrift) +void CommonParam::SampleTimeStruct(float vdrift) { // // Samples the timing structure of a drift cell @@ -732,14 +732,14 @@ void TRDCommonParam::SampleTimeStruct(float vdrift) } } -void TRDCommonParam::SetXenon() +void CommonParam::SetXenon() { mGasMixture = kXenon; - TRDSimParam::Instance()->ReInit(); + SimParam::Instance()->ReInit(); } -void TRDCommonParam::SetArgon() +void CommonParam::SetArgon() { mGasMixture = kArgon; - TRDSimParam::Instance()->ReInit(); + SimParam::Instance()->ReInit(); } diff --git a/Detectors/TRD/base/src/TRDDiffAndTimeStructEstimator.cxx b/Detectors/TRD/base/src/DiffAndTimeStructEstimator.cxx similarity index 98% rename from Detectors/TRD/base/src/TRDDiffAndTimeStructEstimator.cxx rename to Detectors/TRD/base/src/DiffAndTimeStructEstimator.cxx index ccecc3fd4fa5f..5c9a131050a22 100644 --- a/Detectors/TRD/base/src/TRDDiffAndTimeStructEstimator.cxx +++ b/Detectors/TRD/base/src/DiffAndTimeStructEstimator.cxx @@ -8,9 +8,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "TRDBase/TRDCommonParam.h" -#include "TRDBase/TRDDiffAndTimeStructEstimator.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/CommonParam.h" +#include "TRDBase/DiffAndTimeStructEstimator.h" +#include "TRDBase/Geometry.h" #include <cmath> namespace o2::trd @@ -345,7 +345,7 @@ constexpr float time2200[ktimebin][kZbin] = { {1.48122, 1.48219, 1.48482, 1.48991, 1.50030, 1.53991, 1.52898, 1.52653, 1.53653, 1.57282, 1.82386}}; //_____________________________________________________________________________ -void TRDDiffusionAndTimeStructEstimator::SampleTimeStruct(float vdrift) +void DiffusionAndTimeStructEstimator::SampleTimeStruct(float vdrift) { // // Samples the timing structure of a drift cell @@ -436,7 +436,7 @@ void TRDDiffusionAndTimeStructEstimator::SampleTimeStruct(float vdrift) } //_____________________________________________________________________________ -float TRDDiffusionAndTimeStructEstimator::TimeStruct(float vdrift, float dist, float z) +float DiffusionAndTimeStructEstimator::TimeStruct(float vdrift, float dist, float z) { // // Applies the time structure of the drift cells (by C.Lippmann). @@ -497,7 +497,7 @@ float TRDDiffusionAndTimeStructEstimator::TimeStruct(float vdrift, float dist, f // Dist now is the drift distance to the anode wires (negative if electrons are // between anode wire plane and cathode pad plane) - dist -= TRDGeometry::amThick() * 0.5; + dist -= Geometry::amThick() * 0.5; // Interpolation in z-directions, lower drift time map const bool condition = ((std::abs(dist) > 0.005) || (z > 0.005)); @@ -516,7 +516,7 @@ float TRDDiffusionAndTimeStructEstimator::TimeStruct(float vdrift, float dist, f } //_____________________________________________________________________________ -bool TRDDiffusionAndTimeStructEstimator::GetDiffCoeff(float& dl, float& dt, float vdrift) +bool DiffusionAndTimeStructEstimator::GetDiffCoeff(float& dl, float& dt, float vdrift) { // // Calculates the diffusion coefficients in longitudinal <dl> and @@ -531,7 +531,7 @@ bool TRDDiffusionAndTimeStructEstimator::GetDiffCoeff(float& dl, float& dt, floa } mDiffLastVdrift = vdrift; - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { // // Vd and B-field dependent diffusion and Lorentz angle // @@ -541,7 +541,7 @@ bool TRDDiffusionAndTimeStructEstimator::GetDiffCoeff(float& dl, float& dt, floa // If looking at compatibility with AliRoot: // ibL and ibT are calculated the same way so, just define ib = ibL = ibT - int ib = ((int)(10 * (TRDCommonParam::Instance()->GetCachedField() - 0.15))); + int ib = ((int)(10 * (CommonParam::Instance()->GetCachedField() - 0.15))); ib = std::max(0, ib); ib = std::min(kNb - 1, ib); @@ -564,7 +564,7 @@ bool TRDDiffusionAndTimeStructEstimator::GetDiffCoeff(float& dl, float& dt, floa dl = mDiffusionL; dt = mDiffusionT; return true; - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { // // Diffusion constants and Lorentz angle only for B = 0.5T // @@ -578,4 +578,4 @@ bool TRDDiffusionAndTimeStructEstimator::GetDiffCoeff(float& dl, float& dt, floa } } -} // namespace o2::trd \ No newline at end of file +} // namespace o2::trd diff --git a/Detectors/TRD/base/src/FeeParam.cxx b/Detectors/TRD/base/src/FeeParam.cxx index 1a539e8780079..38df171513dbf 100644 --- a/Detectors/TRD/base/src/FeeParam.cxx +++ b/Detectors/TRD/base/src/FeeParam.cxx @@ -36,10 +36,10 @@ #include <array> #include "DetectorsBase/GeometryManager.h" -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/PadPlane.h" #include "TRDBase/FeeParam.h" -#include "TRDBase/TRDCommonParam.h" +#include "TRDBase/CommonParam.h" //#include "DataFormatsTRD/Constants.h" using namespace std; @@ -131,7 +131,7 @@ FeeParam::FeeParam() : mMagField(0.), // // Default constructor // - mCP = TRDCommonParam::Instance(); + mCP = CommonParam::Instance(); // These variables are used internally in the class to elliminate divisions. // putting them at the top was messy. @@ -522,8 +522,8 @@ int FeeParam::getORIinSM(int detector, int readoutboard) const { int ori = -1; int chamberside = 0; - int trdstack = TRDGeometry::getStack(detector); - int trdlayer = TRDGeometry::getLayer(detector); + int trdstack = Geometry::getStack(detector); + int trdlayer = Geometry::getLayer(detector); int side = getRobSide(readoutboard); //see TDP for explanation of mapping TODO should probably come from CCDB for the instances where the mapping of ori fibers is misconfigured (accidental fibre swaps). if (trdstack < 2 || (trdstack == 2 && side == 0)) // A Side @@ -552,8 +552,8 @@ int FeeParam::getORIfromHCID(int hcid) const int side = hcid % 2; // 0 for side 0, 1 for side 1; int ori = -1; int chamberside = 0; - int trdstack = TRDGeometry::getStack(detector); - int trdlayer = TRDGeometry::getLayer(detector); + int trdstack = Geometry::getStack(detector); + int trdlayer = Geometry::getLayer(detector); return getORIinSM(detector, side); // it takes readoutboard but only cares if its odd or even hence side here. return 1; } diff --git a/Detectors/TRD/base/src/TRDGeometry.cxx b/Detectors/TRD/base/src/Geometry.cxx similarity index 99% rename from Detectors/TRD/base/src/TRDGeometry.cxx rename to Detectors/TRD/base/src/Geometry.cxx index f3c731a1d5321..361644709bf73 100644 --- a/Detectors/TRD/base/src/TRDGeometry.cxx +++ b/Detectors/TRD/base/src/Geometry.cxx @@ -16,24 +16,24 @@ #include "DetectorsBase/GeometryManager.h" #include "MathUtils/Utils.h" // math_utils::bit2Mask -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/PadPlane.h" using namespace o2::trd; using namespace o2::trd::constants; //_____________________________________________________________________________ -const o2::detectors::DetID TRDGeometry::sDetID(o2::detectors::DetID::TRD); +const o2::detectors::DetID Geometry::sDetID(o2::detectors::DetID::TRD); //_____________________________________________________________________________ -TRDGeometry::TRDGeometry() : TRDGeometryBase(), o2::detectors::DetMatrixCacheIndirect(sDetID) +Geometry::Geometry() : GeometryBase(), o2::detectors::DetMatrixCacheIndirect(sDetID) { createPadPlaneArray(); } //_____________________________________________________________________________ -bool TRDGeometry::rotateBack(int det, const float* const loc, float* glb) const +bool Geometry::rotateBack(int det, const float* const loc, float* glb) const { // // Rotates a chambers to transform the corresponding local frame @@ -51,10 +51,10 @@ bool TRDGeometry::rotateBack(int det, const float* const loc, float* glb) const } //_____________________________________________________________________________ -void TRDGeometry::createPadPlaneArray() +void Geometry::createPadPlaneArray() { // - // Creates the array of TRDPadPlane objects + // Creates the array of PadPlane objects // for (int ilayer = 0; ilayer < NLAYER; ilayer++) { @@ -65,10 +65,10 @@ void TRDGeometry::createPadPlaneArray() } //_____________________________________________________________________________ -void TRDGeometry::createPadPlane(int ilayer, int istack) +void Geometry::createPadPlane(int ilayer, int istack) { // - // Creates an TRDPadPlane object + // Creates an PadPlane object // int ipp = getDetectorSec(ilayer, istack); auto& padPlane = mPadPlanes[ipp]; @@ -242,7 +242,7 @@ void TRDGeometry::createPadPlane(int ilayer, int istack) padPlane.setPadRowSMOffset(rowTmp - CLENGTH[ilayer][istack] / 2.0); } -void TRDGeometry::createVolume(const char* name, const char* shape, int nmed, float* upar, int np) +void Geometry::createVolume(const char* name, const char* shape, int nmed, float* upar, int np) { TVirtualMC::GetMC()->Gsvolu(name, shape, nmed, upar, np); @@ -254,7 +254,7 @@ void TRDGeometry::createVolume(const char* name, const char* shape, int nmed, fl } //_____________________________________________________________________________ -void TRDGeometry::createGeometry(std::vector<int> const& idtmed) +void Geometry::createGeometry(std::vector<int> const& idtmed) { // // Create the TRD geometry @@ -267,7 +267,7 @@ void TRDGeometry::createGeometry(std::vector<int> const& idtmed) createVolumes(idtmed); } -void TRDGeometry::createVolumes(std::vector<int> const& idtmed) +void Geometry::createVolumes(std::vector<int> const& idtmed) { // // Create the TRD geometry volumes @@ -783,7 +783,7 @@ void TRDGeometry::createVolumes(std::vector<int> const& idtmed) } //_____________________________________________________________________________ -void TRDGeometry::createFrame(std::vector<int> const& idtmed) +void Geometry::createFrame(std::vector<int> const& idtmed) { // // Create the geometry of the frame of the supermodule @@ -1505,7 +1505,7 @@ void TRDGeometry::createFrame(std::vector<int> const& idtmed) } //_____________________________________________________________________________ -void TRDGeometry::createServices(std::vector<int> const& idtmed) +void Geometry::createServices(std::vector<int> const& idtmed) { // // Create the geometry of the services @@ -2447,7 +2447,7 @@ void TRDGeometry::createServices(std::vector<int> const& idtmed) } //_____________________________________________________________________________ -void TRDGeometry::assembleChamber(int ilayer, int istack) +void Geometry::assembleChamber(int ilayer, int istack) { // // Group volumes UA, UD, UF, UU into an assembly that defines the @@ -2546,7 +2546,7 @@ void TRDGeometry::assembleChamber(int ilayer, int istack) } } -void TRDGeometry::fillMatrixCache(int mask) +void Geometry::fillMatrixCache(int mask) { if (mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) { useT2LCache(); @@ -2638,7 +2638,7 @@ void TRDGeometry::fillMatrixCache(int mask) } //_____________________________________________________________________________ -void TRDGeometry::addAlignableVolumes() const +void Geometry::addAlignableVolumes() const { // // define alignable volumes of the TRD @@ -2739,7 +2739,7 @@ void TRDGeometry::addAlignableVolumes() const } //_____________________________________________________________________________ -bool TRDGeometry::createClusterMatrixArray() +bool Geometry::createClusterMatrixArray() { if (!gGeoManager) { @@ -2759,7 +2759,7 @@ bool TRDGeometry::createClusterMatrixArray() } //_____________________________________________________________________________ -bool TRDGeometry::chamberInGeometry(int det) const +bool Geometry::chamberInGeometry(int det) const { // // Checks whether the given detector is part of the current geometry diff --git a/Detectors/TRD/base/src/TRDGeometryBase.cxx b/Detectors/TRD/base/src/GeometryBase.cxx similarity index 87% rename from Detectors/TRD/base/src/TRDGeometryBase.cxx rename to Detectors/TRD/base/src/GeometryBase.cxx index d561b04b05eb5..167c9f73899c5 100644 --- a/Detectors/TRD/base/src/TRDGeometryBase.cxx +++ b/Detectors/TRD/base/src/GeometryBase.cxx @@ -8,13 +8,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "TRDBase/TRDGeometryBase.h" +#include "TRDBase/GeometryBase.h" using namespace o2::trd; using namespace o2::trd::constants; //_____________________________________________________________________________ -GPUd() int TRDGeometryBase::getStack(float z, int layer) const +GPUd() int GeometryBase::getStack(float z, int layer) const { // // Reconstruct the chamber number from the z position and layer number @@ -35,7 +35,7 @@ GPUd() int TRDGeometryBase::getStack(float z, int layer) const if (istck < 0) { break; } - const TRDPadPlane* pp = getPadPlane(layer, istck); + const PadPlane* pp = getPadPlane(layer, istck); zmax = pp->getRow0(); int nrows = pp->getNrows(); zmin = zmax - 2 * pp->getLengthOPad() - (nrows - 2) * pp->getLengthIPad() - (nrows - 1) * pp->getRowSpacing(); @@ -45,7 +45,7 @@ GPUd() int TRDGeometryBase::getStack(float z, int layer) const } //_____________________________________________________________________________ -GPUd() bool TRDGeometryBase::isOnBoundary(int det, float y, float z, float eps) const +GPUd() bool GeometryBase::isOnBoundary(int det, float y, float z, float eps) const { // // Checks whether position is at the boundary of the sensitive volume @@ -61,7 +61,7 @@ GPUd() bool TRDGeometryBase::isOnBoundary(int det, float y, float z, float eps) return true; } - const TRDPadPlane* pp = &mPadPlanes[getDetectorSec(ly, stk)]; + const PadPlane* pp = &mPadPlanes[getDetectorSec(ly, stk)]; if (!pp) { return true; } diff --git a/Detectors/TRD/base/src/TRDGeometryFlat.cxx b/Detectors/TRD/base/src/GeometryFlat.cxx similarity index 84% rename from Detectors/TRD/base/src/TRDGeometryFlat.cxx rename to Detectors/TRD/base/src/GeometryFlat.cxx index 2fac44700569e..34ca9ee05db9f 100644 --- a/Detectors/TRD/base/src/TRDGeometryFlat.cxx +++ b/Detectors/TRD/base/src/GeometryFlat.cxx @@ -8,16 +8,17 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "TRDBase/TRDGeometryFlat.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/GeometryFlat.h" +#include "TRDBase/Geometry.h" #include "DataFormatsTRD/Constants.h" +using namespace o2::trd; using namespace o2::trd::constants; -TRDGeometryFlat::TRDGeometryFlat(const TRDGeometry& geo) +GeometryFlat::GeometryFlat(const Geometry& geo) { - TRDGeometryBase& b1 = *this; - const TRDGeometryBase& b2 = geo; + GeometryBase& b1 = *this; + const GeometryBase& b2 = geo; memcpy((void*)&b1, (void*)&b2, sizeof(b1)); int matrixCount = 0; for (int i = 0; i < MAXCHAMBER; i++) { diff --git a/Detectors/TRD/base/src/TRDPadPlane.cxx b/Detectors/TRD/base/src/PadPlane.cxx similarity index 92% rename from Detectors/TRD/base/src/TRDPadPlane.cxx rename to Detectors/TRD/base/src/PadPlane.cxx index 62c94ebff3650..bc8a65c485869 100644 --- a/Detectors/TRD/base/src/TRDPadPlane.cxx +++ b/Detectors/TRD/base/src/PadPlane.cxx @@ -21,14 +21,14 @@ // // /////////////////////////////////////////////////////////////////////////////// -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/PadPlane.h" #include <TMath.h> #include <FairLogger.h> using namespace o2::trd; //_____________________________________________________________________________ -void TRDPadPlane::setTiltingAngle(double t) +void PadPlane::setTiltingAngle(double t) { // // Set the tilting angle of the pads @@ -39,7 +39,7 @@ void TRDPadPlane::setTiltingAngle(double t) } //_____________________________________________________________________________ -int TRDPadPlane::getPadRowNumber(double z) const +int PadPlane::getPadRowNumber(double z) const { // // Finds the pad row number for a given z-position in local supermodule system @@ -74,7 +74,7 @@ int TRDPadPlane::getPadRowNumber(double z) const } //_____________________________________________________________________________ -int TRDPadPlane::getPadRowNumberROC(double z) const +int PadPlane::getPadRowNumberROC(double z) const { // // Finds the pad row number for a given z-position in local ROC system @@ -109,7 +109,7 @@ int TRDPadPlane::getPadRowNumberROC(double z) const } //_____________________________________________________________________________ -int TRDPadPlane::getPadColNumber(double rphi) const +int PadPlane::getPadColNumber(double rphi) const { // // Finds the pad column number for a given rphi-position @@ -143,7 +143,7 @@ int TRDPadPlane::getPadColNumber(double rphi) const return col; } -void TRDPadPlane::setNcols(int n) +void PadPlane::setNcols(int n) { if (n > MAXCOLS) { LOG(FATAL) << "MAXCOLS exceeded " << n << " > " << MAXCOLS; @@ -151,7 +151,7 @@ void TRDPadPlane::setNcols(int n) mNcols = n; }; -void TRDPadPlane::setNrows(int n) +void PadPlane::setNrows(int n) { if (n > MAXROWS) { LOG(FATAL) << "MAXROWS exceeded " << n << " > " << MAXROWS; diff --git a/Detectors/TRD/base/src/TRDSimParam.cxx b/Detectors/TRD/base/src/SimParam.cxx similarity index 91% rename from Detectors/TRD/base/src/TRDSimParam.cxx rename to Detectors/TRD/base/src/SimParam.cxx index cc71d7629ced6..83223d8af1b23 100644 --- a/Detectors/TRD/base/src/TRDSimParam.cxx +++ b/Detectors/TRD/base/src/SimParam.cxx @@ -12,25 +12,24 @@ // // // Class containing constant simulation parameters // // // -// Request an instance with TRDSimParam::Instance() // +// Request an instance with SimParam::Instance() // // Then request the needed values // // // //////////////////////////////////////////////////////////////////////////// -#include "TRDBase/TRDSimParam.h" +#include "TRDBase/SimParam.h" #include <TMath.h> -#include "TRDBase/TRDCommonParam.h" -//#include "AliLog.h" +#include "TRDBase/CommonParam.h" #include <FairLogger.h> using namespace o2::trd; -ClassImp(TRDSimParam); +ClassImp(SimParam); -TRDSimParam* TRDSimParam::fgInstance = nullptr; -bool TRDSimParam::fgTerminated = false; +SimParam* SimParam::fgInstance = nullptr; +bool SimParam::fgTerminated = false; //_ singleton implementation __________________________________________________ -TRDSimParam* TRDSimParam::Instance() +SimParam* SimParam::Instance() { // // Singleton implementation @@ -42,14 +41,14 @@ TRDSimParam* TRDSimParam::Instance() } if (fgInstance == nullptr) { - fgInstance = new TRDSimParam(); + fgInstance = new SimParam(); } return fgInstance; } //_ singleton implementation __________________________________________________ -void TRDSimParam::Terminate() +void SimParam::Terminate() { // // Singleton implementation @@ -67,7 +66,7 @@ void TRDSimParam::Terminate() } //_____________________________________________________________________________ -TRDSimParam::TRDSimParam() +SimParam::SimParam() : mGasGain(0.0), mNoise(0.0), mChipGain(0.0), @@ -100,7 +99,7 @@ TRDSimParam::TRDSimParam() } //_____________________________________________________________________________ -void TRDSimParam::Init() +void SimParam::Init() { // // Default initializiation @@ -149,7 +148,7 @@ void TRDSimParam::Init() } //_____________________________________________________________________________ -TRDSimParam::~TRDSimParam() +SimParam::~SimParam() { // // Destructor @@ -166,13 +165,13 @@ TRDSimParam::~TRDSimParam() } //_____________________________________________________________________________ -void TRDSimParam::ReInit() +void SimParam::ReInit() { // // Reinitializes the parameter class after a change // - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { // The range and the binwidth for the sampled TRF mTRFbin = 200; // Start 0.2 mus before the signal @@ -181,7 +180,7 @@ void TRDSimParam::ReInit() mTRFhi = 3.58; // Standard gas gain mGasGain = 4000.0; - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { // The range and the binwidth for the sampled TRF mTRFbin = 50; // Start 0.2 mus before the signal @@ -200,7 +199,7 @@ void TRDSimParam::ReInit() } //_____________________________________________________________________________ -void TRDSimParam::SampleTRF() +void SimParam::SampleTRF() { // // Samples the new time response function. @@ -274,21 +273,21 @@ void TRDSimParam::SampleTRF() } mCTsmp = new float[mTRFbin]; - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { if (mTRFbin != kNpasa) { LOG(ERROR) << "Array mismatch (xenon)\n\n"; } - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { if (mTRFbin != kNpasaAr) { LOG(ERROR) << "Array mismatch (argon)\n\n"; } } for (int iBin = 0; iBin < mTRFbin; iBin++) { - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { mTRFsmp[iBin] = signal[iBin]; mCTsmp[iBin] = xtalk[iBin]; - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { mTRFsmp[iBin] = signalAr[iBin]; mCTsmp[iBin] = xtalkAr[iBin]; } diff --git a/Detectors/TRD/base/src/TRDBaseLinkDef.h b/Detectors/TRD/base/src/TRDBaseLinkDef.h index 65dca8213dee7..7b9247326057c 100644 --- a/Detectors/TRD/base/src/TRDBaseLinkDef.h +++ b/Detectors/TRD/base/src/TRDBaseLinkDef.h @@ -14,11 +14,11 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class o2::trd::TRDPadPlane + ; -#pragma link C++ class o2::trd::TRDGeometry + ; -#pragma link C++ class o2::trd::TRDGeometryBase + ; -#pragma link C++ class o2::trd::TRDCommonParam + ; -#pragma link C++ class o2::trd::TRDSimParam + ; +#pragma link C++ class o2::trd::PadPlane + ; +#pragma link C++ class o2::trd::Geometry + ; +#pragma link C++ class o2::trd::GeometryBase + ; +#pragma link C++ class o2::trd::CommonParam + ; +#pragma link C++ class o2::trd::SimParam + ; #pragma link C++ class o2::trd::Digit + ; #pragma link C++ class std::vector < o2::trd::Digit> + ; #pragma link C++ class o2::trd::FeeParam + ; diff --git a/Detectors/TRD/base/src/Tracklet.cxx b/Detectors/TRD/base/src/Tracklet.cxx index d7ec1f82ff2bc..723cdffcae627 100644 --- a/Detectors/TRD/base/src/Tracklet.cxx +++ b/Detectors/TRD/base/src/Tracklet.cxx @@ -22,7 +22,7 @@ #include "TRDBase/Tracklet.h" #include <fairlogger/Logger.h> -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include <SimulationDataFormat/MCCompLabel.h> #include <SimulationDataFormat/MCTruthContainer.h> //_____________________________________________________________________________ @@ -32,25 +32,25 @@ using namespace o2::trd; Tracklet::Tracklet() { // constructor - mGeo = TRDGeometry::instance(); + mGeo = Geometry::instance(); } Tracklet::Tracklet(int hcid) : mHCId(hcid) { // constructor - mGeo = TRDGeometry::instance(); + mGeo = Geometry::instance(); } Tracklet::Tracklet(int hcid, int rob, int mcm, float pid, float rawslope, float rawoffset, float rawslope4trackletword, float rawoffset4trackletword) : mHCId(hcid), mMCM(mcm), mROB(rob), mPID(pid), mdY(rawslope), mY(rawoffset), mdY4tw(rawslope4trackletword), mY4tw(rawoffset4trackletword) { // constructor - mGeo = TRDGeometry::instance(); + mGeo = Geometry::instance(); } Tracklet::Tracklet(const Tracklet& rhs) : mHCId(rhs.mHCId), mMCM(rhs.mMCM), mROB(rhs.mROB), mQ0(rhs.mQ0), mQ1(rhs.mQ1), mPID(rhs.mPID), mdY(rhs.mdY), mY(rhs.mY), mdY4tw(rhs.mdY4tw), mY4tw(rhs.mY4tw), mNHits(rhs.mNHits), mNHits0(rhs.mNHits0), mNHits1(rhs.mNHits1), mSlope(rhs.mSlope), mOffset(rhs.mOffset), mError(rhs.mError), mNClusters(rhs.mNClusters) { // copy constructor - mGeo = TRDGeometry::instance(); + mGeo = Geometry::instance(); mResiduals = rhs.mResiduals; mClsCharges = rhs.mClsCharges; diff --git a/Detectors/TRD/base/test/testArrayADC.cxx b/Detectors/TRD/base/test/testArrayADC.cxx deleted file mode 100644 index 4cc1da4e09c02..0000000000000 --- a/Detectors/TRD/base/test/testArrayADC.cxx +++ /dev/null @@ -1,41 +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. - -/// \file testTPCMapper.cxx -/// \brief This task tests the mapper function -/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de - -#define BOOST_TEST_MODULE Test TRD_ArrayADC -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK -#include <boost/test/unit_test.hpp> -#include <cstdlib> -#include <fstream> -#include <iostream> -#include <sstream> -#include <string> -#include "TRDBase/TRDArrayADC.h" - -namespace o2 -{ -namespace tcp -{ - -/// \brief Test the arrayadc class operation -// -/// check the bit manipulations -BOOST_AUTO_TEST_CASE(ArrayADCtest1) -{ - TRDArrayADC data = new TRDArrayADC(); - //set bits as corrupted and see if they are detected correctly -} - -} // namespace tcp -} // namespace o2 diff --git a/Detectors/TRD/base/test/testTRDDiffusionCoefficient.cxx b/Detectors/TRD/base/test/testTRDDiffusionCoefficient.cxx index 1d21e2d5a5e8b..55355fc7ef386 100644 --- a/Detectors/TRD/base/test/testTRDDiffusionCoefficient.cxx +++ b/Detectors/TRD/base/test/testTRDDiffusionCoefficient.cxx @@ -16,8 +16,8 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include <boost/test/unit_test.hpp> -#include "TRDBase/TRDCommonParam.h" -#include "TRDBase/TRDDiffAndTimeStructEstimator.h" +#include "TRDBase/CommonParam.h" +#include "TRDBase/DiffAndTimeStructEstimator.h" #include "Field/MagneticField.h" #include <TGeoGlobalMagField.h> @@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(TRDDiffusionCoefficient_test1) TGeoGlobalMagField::Instance()->SetField(fld); TGeoGlobalMagField::Instance()->Lock(); - auto commonParam = TRDCommonParam::Instance(); + auto commonParam = CommonParam::Instance(); float dl = 0; float dt = 0; float vd = 1.48; @@ -47,8 +47,8 @@ BOOST_AUTO_TEST_CASE(TRDDiffusionCoefficient_test1) /// \brief Test time structure BOOST_AUTO_TEST_CASE(TRDTimeStructure_test) { - auto commonParam = TRDCommonParam::Instance(); - TRDDiffusionAndTimeStructEstimator estimator; + auto commonParam = CommonParam::Instance(); + DiffusionAndTimeStructEstimator estimator; BOOST_CHECK_CLOSE(estimator.TimeStruct(1.48, 1., 0.1), commonParam->TimeStruct(1.48, 1., 0.1), 0.001); BOOST_CHECK_CLOSE(estimator.TimeStruct(1.1, 1., 0.1), commonParam->TimeStruct(1.1, 1., 0.1), 0.001); BOOST_CHECK_CLOSE(estimator.TimeStruct(2, 1., 0.1), commonParam->TimeStruct(2, 1., 0.1), 0.001); @@ -58,8 +58,8 @@ BOOST_AUTO_TEST_CASE(TRDTimeStructure_test) /// \brief compare diffusion coeff BOOST_AUTO_TEST_CASE(TRDDiffusion_test) { - auto commonParam = TRDCommonParam::Instance(); - TRDDiffusionAndTimeStructEstimator estimator; + auto commonParam = CommonParam::Instance(); + DiffusionAndTimeStructEstimator estimator; float dl1 = 0.; float dl2 = 0.; float dt1 = 0.; diff --git a/Detectors/TRD/base/test/testTRDGeometry.cxx b/Detectors/TRD/base/test/testTRDGeometry.cxx index e99d46fc1ffab..976f20b9a2699 100644 --- a/Detectors/TRD/base/test/testTRDGeometry.cxx +++ b/Detectors/TRD/base/test/testTRDGeometry.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. /// \file testTRDGeometry.cxx -/// \brief This task tests the TRDGeometry +/// \brief This task tests the Geometry /// \author Sean Murray, murrays@cern.ch #define BOOST_TEST_MODULE Test TRD_Geometry @@ -21,7 +21,7 @@ #include <iostream> #include <sstream> #include <string> -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include <iostream> namespace o2 @@ -29,26 +29,26 @@ namespace o2 namespace trd { -/// \brief Test the TRDGeometry class +/// \brief Test the Geometry class // /// BOOST_AUTO_TEST_CASE(TRDGeometry_test1) { //arbitrary chosen - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowPos(1, 1, 3), 154.5, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowSize(1, 1, 3), 7.5, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRow0(1, 1), 177, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowEnd(1, 1), 57, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowPos(1, 1, 3), 154.5, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowSize(1, 1, 3), 7.5, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRow0(1, 1), 177, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowEnd(1, 1), 57, 1e-3); //start - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowPos(0, 0, 3), 278.5, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowSize(0, 0, 3), 7.5, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRow0(0, 0), 301, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowEnd(0, 0), 181, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowPos(0, 0, 3), 278.5, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowSize(0, 0, 3), 7.5, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRow0(0, 0), 301, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowEnd(0, 0), 181, 1e-3); //end of trd. - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowPos(5, 4, 0), -204, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowSize(5, 4, 3), 9, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRow0(5, 4), -204, 1e-3); - BOOST_CHECK_CLOSE(TRDGeometry::instance()->getRowEnd(5, 4), -347, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowPos(5, 4, 0), -204, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowSize(5, 4, 3), 9, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRow0(5, 4), -204, 1e-3); + BOOST_CHECK_CLOSE(Geometry::instance()->getRowEnd(5, 4), -347, 1e-3); } } // namespace trd diff --git a/Detectors/TRD/macros/CheckDigits.C b/Detectors/TRD/macros/CheckDigits.C index c754c6c163034..f887fe44d6d3f 100644 --- a/Detectors/TRD/macros/CheckDigits.C +++ b/Detectors/TRD/macros/CheckDigits.C @@ -22,8 +22,8 @@ #include "FairLogger.h" #include "TRDBase/Digit.h" -#include "TRDBase/TRDSimParam.h" -#include "TRDBase/TRDCommonParam.h" +#include "TRDBase/SimParam.h" +#include "TRDBase/CommonParam.h" #include "DataFormatsTRD/Constants.h" #endif @@ -77,7 +77,7 @@ void CheckDigits(std::string digifile = "trddigits.root", hPad->Fill(pad); for (int tb = 0; tb < o2::trd::constants::TIMEBINS; ++tb) { ADC_t adc = adcs[tb]; - if (adc == (ADC_t)TRDSimParam::Instance()->GetADCoutRange()) { + if (adc == (ADC_t)SimParam::Instance()->GetADCoutRange()) { // LOG(INFO) << "Out of range ADC " << adc; continue; } diff --git a/Detectors/TRD/macros/CheckHits.C b/Detectors/TRD/macros/CheckHits.C index a861b49da4262..5f06c5456d92c 100644 --- a/Detectors/TRD/macros/CheckHits.C +++ b/Detectors/TRD/macros/CheckHits.C @@ -20,7 +20,7 @@ #include "FairLogger.h" #include "TRDSimulation/Detector.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "TRDBase/Calibrations.h" #include "DetectorsCommonDataFormats/NameConf.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -57,15 +57,15 @@ void CheckHits(const int detector = 50, // 354, 14, 242, 50 hitTree->GetEvent(iev); for (const auto& hit : *hits) { int det = hit.GetDetectorID(); - // if (calib.isChamberNoData(det) || o2::trd::TRDGeometry::getStack(det)!=2 || o2::trd::TRDGeometry::getSector(det) != 4) { + // if (calib.isChamberNoData(det) || o2::trd::Geometry::getStack(det)!=2 || o2::trd::Geometry::getSector(det) != 4) { // if (calib.isChamberNoData(det)) { // continue; // } if (det != detector) { - // LOG(INFO) << "REJECTED Detector = " << det <<"\t Stack = " << o2::trd::TRDGeometry::getStack(det) << "\t Sector = " << o2::trd::TRDGeometry::getSector(det); + // LOG(INFO) << "REJECTED Detector = " << det <<"\t Stack = " << o2::trd::Geometry::getStack(det) << "\t Sector = " << o2::trd::Geometry::getSector(det); continue; } - LOG(INFO) << "ACCEPTED Detector = " << det << "\t Stack = " << o2::trd::TRDGeometry::getStack(det) << "\t Sector = " << o2::trd::TRDGeometry::getSector(det); + LOG(INFO) << "ACCEPTED Detector = " << det << "\t Stack = " << o2::trd::Geometry::getStack(det) << "\t Sector = " << o2::trd::Geometry::getSector(det); // loop over det, pad, row? double locC = hit.getLocalC(); // col direction in amplification or drift volume double locR = hit.getLocalR(); // row direction in amplification or drift volume diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Detector.h b/Detectors/TRD/simulation/include/TRDSimulation/Detector.h index b7fe798677867..a943d6758155b 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/Detector.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/Detector.h @@ -60,7 +60,7 @@ namespace o2 namespace trd { -class TRDGeometry; +class Geometry; class TRsim; class Detector : public o2::base::DetImpl<Detector> @@ -111,7 +111,7 @@ class Detector : public o2::base::DetImpl<Detector> float mWion; // Ionization potential - TRDGeometry* mGeom = nullptr; + Geometry* mGeom = nullptr; template <typename Det> friend class o2::base::DetImpl; diff --git a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h index d716acbeb1f00..03b0203e438e7 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/Digitizer.h @@ -16,8 +16,8 @@ #include "TRDBase/Calibrations.h" #include "TRDBase/Digit.h" #include "TRDBase/MCLabel.h" -#include "TRDBase/TRDCommonParam.h" -#include "TRDBase/TRDDiffAndTimeStructEstimator.h" +#include "TRDBase/CommonParam.h" +#include "TRDBase/DiffAndTimeStructEstimator.h" #include "DataFormatsTRD/Constants.h" #include "MathUtils/RandomRing.h" @@ -33,9 +33,9 @@ namespace o2 namespace trd { -class TRDGeometry; -class TRDSimParam; -class TRDPadPlane; +class Geometry; +class SimParam; +class PadPlane; class TRDArraySignal; class PadResponse; @@ -74,10 +74,10 @@ class Digitizer static constexpr double BUSY_TIME = READOUT_TIME + DEAD_TIME; // the time for which no new trigger can be received in nanoseconds private: - TRDGeometry* mGeo = nullptr; // access to TRDGeometry + Geometry* mGeo = nullptr; // access to Geometry PadResponse* mPRF = nullptr; // access to PadResponse - TRDSimParam* mSimParam = nullptr; // access to TRDSimParam instance - TRDCommonParam* mCommonParam = nullptr; // access to TRDCommonParam instance + SimParam* mSimParam = nullptr; // access to SimParam instance + CommonParam* mCommonParam = nullptr; // access to CommonParam instance Calibrations* mCalib = nullptr; // access to Calibrations in CCDB // number of digitizer threads @@ -87,7 +87,7 @@ class Digitizer std::vector<math_utils::RandomRing<>> mGausRandomRings; // pre-generated normal distributed random numbers std::vector<math_utils::RandomRing<>> mFlatRandomRings; // pre-generated flat distributed random numbers std::vector<math_utils::RandomRing<>> mLogRandomRings; // pre-generated exp distributed random number - std::vector<TRDDiffusionAndTimeStructEstimator> mDriftEstimators; + std::vector<DiffusionAndTimeStructEstimator> mDriftEstimators; double mTime = 0.; // time in nanoseconds double mLastTime = -1; // negative, by default to flag the first event @@ -103,8 +103,8 @@ class Digitizer }; // Digitization parameters - static constexpr float AmWidth = TRDGeometry::amThick(); // Width of the amplification region - static constexpr float DrWidth = TRDGeometry::drThick(); // Width of the drift retion + static constexpr float AmWidth = Geometry::amThick(); // Width of the amplification region + static constexpr float DrWidth = Geometry::drThick(); // Width of the drift retion static constexpr float DrMin = -0.5 * AmWidth; // Drift + Amplification region static constexpr float DrMax = DrWidth + 0.5 * AmWidth; // Drift + Amplification region float mSamplingRate = 0; // The sampling rate diff --git a/Detectors/TRD/simulation/src/Detector.cxx b/Detectors/TRD/simulation/src/Detector.cxx index 5f7b638dcb4ed..dfed6e56c5c12 100644 --- a/Detectors/TRD/simulation/src/Detector.cxx +++ b/Detectors/TRD/simulation/src/Detector.cxx @@ -10,8 +10,8 @@ #include "TRDSimulation/Detector.h" -#include "TRDBase/TRDCommonParam.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/CommonParam.h" +#include "TRDBase/Geometry.h" #include "TRDSimulation/TRsim.h" #include "DataFormatsTRD/Constants.h" @@ -34,9 +34,9 @@ Detector::Detector(Bool_t active) : o2::base::DetImpl<Detector>("TRD", active) { mHits = o2::utils::createSimVector<HitType>(); - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { mWion = 23.53; // Ionization energy XeCO2 (85/15) - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { mWion = 27.21; // Ionization energy ArCO2 (82/18) } else { LOG(FATAL) << "Wrong gas mixture"; @@ -58,9 +58,9 @@ Detector::Detector(const Detector& rhs) mGasDensity(rhs.mGasDensity), mGeom(rhs.mGeom) { - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { mWion = 23.53; // Ionization energy XeCO2 (85/15) - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { mWion = 27.21; // Ionization energy ArCO2 (82/18) } else { LOG(FATAL) << "Wrong gas mixture"; @@ -187,7 +187,7 @@ bool Detector::ProcessHits(FairVolume* v) gGeoManager->MasterToLocal(pos, loc); // Go to the local coordinate system (locR, locC, locT) float locC = loc[0], locR = loc[1], locT = loc[2]; if (drRegion) { - locT = locT - 0.5 * (TRDGeometry::drThick() + TRDGeometry::amThick()); // Relative to middle of amplification region + locT = locT - 0.5 * (Geometry::drThick() + Geometry::amThick()); // Relative to middle of amplification region } addHit(xp, yp, zp, locC, locR, locT, tof, totalChargeDep, trackID, det, drRegion); stack->addHit(GetDetId()); @@ -229,7 +229,7 @@ void Detector::createTRhit(int det) sigma = muMy * mFoilDensity; if (sigma > 0.0) { absLength = gRandom->Exp(1.0 / sigma); - if (absLength < TRDGeometry::myThick()) { + if (absLength < Geometry::myThick()) { continue; } } else { @@ -238,9 +238,9 @@ void Detector::createTRhit(int det) // The absorbtion cross sections in the drift gas // Gas-mixture (Xe/CO2) double muNo = 0.0; - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { muNo = mTR->getMuXe(energyMeV); - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { muNo = mTR->getMuAr(energyMeV); } double muCO = mTR->getMuCO(energyMeV); @@ -252,7 +252,7 @@ void Detector::createTRhit(int det) // is deposited. if (sigma > 0.0) { absLength = gRandom->Exp(1.0 / sigma); - if (absLength > (TRDGeometry::drThick() + TRDGeometry::amThick())) { + if (absLength > (Geometry::drThick() + Geometry::amThick())) { continue; } } else { @@ -277,7 +277,7 @@ void Detector::createTRhit(int det) double loc[3] = {-99, -99, -99}; gGeoManager->MasterToLocal(pos, loc); // Go to the local coordinate system (locR, locC, locT) float locC = loc[0], locR = loc[1], locT = loc[2]; - locT = locT - 0.5 * (TRDGeometry::drThick() + TRDGeometry::amThick()); // Relative to middle of amplification region + locT = locT - 0.5 * (Geometry::drThick() + Geometry::amThick()); // Relative to middle of amplification region addHit(x, y, z, locC, locR, locT, tof, totalChargeDep, trackID, det, true); // All TR hits are in drift region stack->addHit(GetDetId()); } @@ -365,9 +365,9 @@ void Detector::createMaterials() float fac = 0.82; float dar = 0.00166; // at 20C float dgmAr = fac * dar + (1.0 - fac) * dco; - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { Mixture(53, "XeCO2", aXeCO2, zXeCO2, dgmXe, -3, wXeCO2); - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { LOG(INFO) << "Gas mixture: Ar C02 (80/20)"; Mixture(53, "ArCO2", aArCO2, zArCO2, dgmAr, -3, wArCO2); } else { @@ -498,10 +498,10 @@ void Detector::createMaterials() // Save the density values for the TRD absorbtion float dmy = 1.39; mFoilDensity = dmy; - if (TRDCommonParam::Instance()->IsXenon()) { + if (CommonParam::Instance()->IsXenon()) { mGasDensity = dgmXe; mGasNobleFraction = fxc; - } else if (TRDCommonParam::Instance()->IsArgon()) { + } else if (CommonParam::Instance()->IsArgon()) { mGasDensity = dgmAr; mGasNobleFraction = fac; } @@ -517,7 +517,7 @@ void Detector::ConstructGeometry() // to the geometry creation getMediumIDMappingAsVector(medmapping); - mGeom = TRDGeometry::instance(); + mGeom = Geometry::instance(); mGeom->createGeometry(medmapping); } diff --git a/Detectors/TRD/simulation/src/Digitizer.cxx b/Detectors/TRD/simulation/src/Digitizer.cxx index 7a5d429c345ac..3647c95a99bc2 100644 --- a/Detectors/TRD/simulation/src/Digitizer.cxx +++ b/Detectors/TRD/simulation/src/Digitizer.cxx @@ -14,9 +14,9 @@ #include "FairLogger.h" #include "DetectorsBase/GeometryManager.h" -#include "TRDBase/TRDGeometry.h" -#include "TRDBase/TRDSimParam.h" -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/Geometry.h" +#include "TRDBase/SimParam.h" +#include "TRDBase/PadPlane.h" #include "TRDBase/PadResponse.h" #include "TRDSimulation/Digitizer.h" @@ -34,11 +34,11 @@ using namespace o2::math_utils; // init method for late initialization void Digitizer::init() { - mGeo = TRDGeometry::instance(); + mGeo = Geometry::instance(); mGeo->createClusterMatrixArray(); // Requiered for chamberInGeometry() mPRF = new PadResponse(); // Pad response function initialization - mSimParam = TRDSimParam::Instance(); // Instance for simulation parameters - mCommonParam = TRDCommonParam::Instance(); // Instance for common parameters + mSimParam = SimParam::Instance(); // Instance for simulation parameters + mCommonParam = CommonParam::Instance(); // Instance for common parameters if (!mSimParam) { } if (!mCommonParam) { @@ -253,7 +253,7 @@ bool Digitizer::convertHits(const int det, const std::vector<HitType>& hits, Sig double padSignal[mNpad]; const double calExBDetValue = mCalib->getExB(det); // T * V/cm (check units) - const TRDPadPlane* padPlane = mGeo->getPadPlane(det); + const PadPlane* padPlane = mGeo->getPadPlane(det); const int layer = mGeo->getLayer(det); const float rowEndROC = padPlane->getRowEndROC(); const float row0 = padPlane->getRow0ROC(); diff --git a/Detectors/TRD/simulation/src/Trap2CRU.cxx b/Detectors/TRD/simulation/src/Trap2CRU.cxx index c1279c29395af..ff2f3f6514d02 100644 --- a/Detectors/TRD/simulation/src/Trap2CRU.cxx +++ b/Detectors/TRD/simulation/src/Trap2CRU.cxx @@ -28,7 +28,7 @@ #include "DetectorsRaw/RawFileWriter.h" #include "TRDSimulation/Trap2CRU.h" #include "CommonUtils/StringUtils.h" -#include "TRDBase/TRDCommonParam.h" +#include "TRDBase/CommonParam.h" #include "TFile.h" #include "TTree.h" #include <TStopwatch.h> diff --git a/Detectors/TRD/simulation/src/TrapConfig.cxx b/Detectors/TRD/simulation/src/TrapConfig.cxx index ea06669b56594..3090036aa2c41 100644 --- a/Detectors/TRD/simulation/src/TrapConfig.cxx +++ b/Detectors/TRD/simulation/src/TrapConfig.cxx @@ -16,7 +16,7 @@ // S. Murray (murrays@cern.ch) // //////////////////////////////////////////////////////////////////////////// -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "TRDBase/FeeParam.h" #include "TRDSimulation/TrapConfig.h" #include "DataFormatsTRD/Constants.h" @@ -1051,8 +1051,8 @@ void TrapConfig::configureOnlineGains() // we dont want to do this anymore .... but here for future reference. /* if (hasOnlineFilterGain()) { const int nDets = MAXCHAMBER; - const int nMcms = TRDGeometry::MCMmax(); - const int nChs = TRDGeometry::ADCmax(); + const int nMcms = Geometry::MCMmax(); + const int nChs = Geometry::ADCmax(); for (int ch = 0; ch < nChs; ++ch) { TrapConfig::TrapReg_t regFGAN = (TrapConfig::TrapReg_t)(TrapConfig::kFGA0 + ch); @@ -1062,10 +1062,10 @@ void TrapConfig::configureOnlineGains() } for (int iDet = 0; iDet < nDets; ++iDet) { - //const int MaxRows = TRDGeometry::getStack(iDet) == 2 ? NROWC0 : NROWC1; + //const int MaxRows = Geometry::getStack(iDet) == 2 ? NROWC0 : NROWC1; int MaxCols = NCOLUMN; // CalOnlineGainTableROC gainTbl = mGainTable.getGainTableROC(iDet); - const int nRobs = TRDGeometry::getStack(iDet) == 2 ? TRDGeometry::ROBmaxC0() : TRDGeometry::ROBmaxC1(); + const int nRobs = Geometry::getStack(iDet) == 2 ? Geometry::ROBmaxC0() : Geometry::ROBmaxC1(); for (int rob = 0; rob < nRobs; ++rob) { for (int mcm = 0; mcm < nMcms; ++mcm) { diff --git a/Detectors/TRD/simulation/src/TrapConfigHandler.cxx b/Detectors/TRD/simulation/src/TrapConfigHandler.cxx index 5e96fded2c1f1..e0c144dd11ec3 100644 --- a/Detectors/TRD/simulation/src/TrapConfigHandler.cxx +++ b/Detectors/TRD/simulation/src/TrapConfigHandler.cxx @@ -22,7 +22,7 @@ #include "TRDBase/FeeParam.h" #include "TRDBase/Tracklet.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "TRDBase/CalOnlineGainTables.h" #include "TRDBase/PadResponse.h" #include "TRDSimulation/TrapConfigHandler.h" @@ -282,7 +282,7 @@ int TrapConfigHandler::loadConfig(std::string filename) if (cmd == mgkScsnCmdWrite) { for (int det = 0; det < MAXCHAMBER; det++) { - unsigned int rocpos = (1 << (TRDGeometry::getSector(det) + 11)) | (1 << (TRDGeometry::getStack(det) + 6)) | (1 << TRDGeometry::getLayer(det)); + unsigned int rocpos = (1 << (Geometry::getSector(det) + 11)) | (1 << (Geometry::getStack(det) + 6)) | (1 << Geometry::getLayer(det)); LOG(debug) << "checking restriction: mask=0x" << hex << std::setw(8) << mRestrictiveMask << " rocpos=0x" << hex << std::setw(8) << rocpos; if ((mRestrictiveMask & rocpos) == rocpos) { LOG(debug) << "match:" @@ -310,7 +310,7 @@ int TrapConfigHandler::loadConfig(std::string filename) int fullVersion = ((data & 0x7F00) >> 1) | (data & 0x7f); for (int iDet = 0; iDet < MAXCHAMBER; iDet++) { - int smls = (TRDGeometry::getSector(iDet) << 6) | (TRDGeometry::getLayer(iDet) << 3) | TRDGeometry::getStack(iDet); + int smls = (Geometry::getSector(iDet) << 6) | (Geometry::getLayer(iDet) << 3) | Geometry::getStack(iDet); for (int iRob = 0; iRob < 8; iRob++) { // HC mergers @@ -459,7 +459,7 @@ void TrapConfigHandler::configureDyCorr(int det) return; } - int nRobs = TRDGeometry::getStack(det) == 2 ? 6 : 8; + int nRobs = Geometry::getStack(det) == 2 ? 6 : 8; for (int r = 0; r < nRobs; r++) { for (int m = 0; m < 16; m++) { @@ -484,7 +484,7 @@ void TrapConfigHandler::configureDRange(int det) return; } - int nRobs = TRDGeometry::getStack(det) == 2 ? 6 : 8; + int nRobs = Geometry::getStack(det) == 2 ? 6 : 8; int dyMinInt; int dyMaxInt; @@ -552,10 +552,10 @@ void TrapConfigHandler::configurePIDcorr(int det) unsigned int cor1; int readoutboard; int mcm; - // int nRobs = TRDGeometry::getStack(det) == 2 ? 6 : 8; + // int nRobs = Geometry::getStack(det) == 2 ? 6 : 8; int MaxRows; FeeParam* feeparam = FeeParam::instance(); - if (TRDGeometry::getStack(det) == 2) { + if (Geometry::getStack(det) == 2) { MaxRows = NROWC0; } else { MaxRows = NROWC1; @@ -593,7 +593,7 @@ bool TrapConfigHandler::addValues(unsigned int det, unsigned int cmd, unsigned i } TrapConfig::TrapReg_t mcmReg = mTrapConfig->getRegByAddress(addr); - int rocType = TRDGeometry::getStack(det) == 2 ? 0 : 1; + int rocType = Geometry::getStack(det) == 2 ? 0 : 1; static const int mcmListSize = 40; // 40 is more or less arbitrary int mcmList[mcmListSize]; diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 998583c7d49e0..793a2d3a2ef0f 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -17,10 +17,9 @@ // // /////////////////////////////////////////////////////////////////////////////// - -#include "TRDBase/TRDSimParam.h" -#include "TRDBase/TRDCommonParam.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/SimParam.h" +#include "TRDBase/CommonParam.h" +#include "TRDBase/Geometry.h" #include "TRDBase/FeeParam.h" #include "TRDBase/Tracklet.h" #include "TRDBase/CalOnlineGainTables.h" diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h index a1aa8b1f443a1..07db64f44eaa1 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h @@ -52,7 +52,7 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task std::array<TrapSimulator, 8> mTrapSimulator; //the 8 trap simulators for a given padrow. FeeParam* mFeeParam = nullptr; TrapConfig* mTrapConfig = nullptr; - std::unique_ptr<TRDGeometry> mGeo; + std::unique_ptr<Geometry> mGeo; // std::unique_ptr<TrapConfigHandler> mTrapConfigHandler; int mNumThreads = 8; unsigned long mRunNumber = 297595; //run number to anchor simulation to. diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 6060d4d35ed22..c4eed5f25ef39 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -183,9 +183,9 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() void TRDDPLTrapSimulatorTask::setOnlineGainTables() { - const int nDets = 540; //TRDGeometry::Ndet(); - const int nMcms = TRDGeometry::MCMmax(); - const int nChs = TRDGeometry::ADCmax(); + const int nDets = 540; //Geometry::Ndet(); + const int nMcms = Geometry::MCMmax(); + const int nChs = Geometry::ADCmax(); //check FGBY from trapconfig. //check the input parameter of trd-onlinegaincorrection. //warn if you have chosen a trapconfig with gaincorrections but chosen not to use them. @@ -208,7 +208,7 @@ void TRDDPLTrapSimulatorTask::setOnlineGainTables() } for (int iDet = 0; iDet < nDets; ++iDet) { - const int nRobs = TRDGeometry::getStack(iDet) == 2 ? TRDGeometry::ROBmaxC0() : TRDGeometry::ROBmaxC1(); + const int nRobs = Geometry::getStack(iDet) == 2 ? Geometry::ROBmaxC0() : Geometry::ROBmaxC1(); for (int rob = 0; rob < nRobs; ++rob) { for (int mcm = 0; mcm < nMcms; ++mcm) { // set ADC reference voltage @@ -428,8 +428,8 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) << mFeeParam->getROBfromPad(digit.getRow(), digit.getPad()) << ":" << mFeeParam->getMCMfromPad(digit.getRow(), digit.getPad()) << " LinkId:" << LinkRecord::getHalfChamberLinkId(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << "\t\t SM:stack:layer:side " - << digit.getDetector() / 30 << ":" << TRDGeometry::getStack(digit.getDetector()) - << ":" << TRDGeometry::getLayer(digit.getDetector()) << ":" << FeeParam::instance()->getRobSide(mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) + << digit.getDetector() / 30 << ":" << Geometry::getStack(digit.getDetector()) + << ":" << Geometry::getLayer(digit.getDetector()) << ":" << FeeParam::instance()->getRobSide(mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << " with ORI# : " << mFeeParam->getORI(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << " within SM ori#:" << mFeeParam->getORIinSM(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())); } @@ -463,8 +463,8 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) int detector = digititerator->getDetector(); int rob = mFeeParam->getROBfromPad(row, pad); int mcm = mFeeParam->getMCMfromPad(row, pad); - int trdstack = TRDGeometry::getStack(detector); - int trdlayer = TRDGeometry::getLayer(detector); + int trdstack = Geometry::getStack(detector); + int trdlayer = Geometry::getLayer(detector); int fibreside = FeeParam::instance()->getRobSide(rob); LOG(debug) << "calculated rob and mcm at top of loop with detector:row:pad:rob:mcm ::" diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index bf326f3923a95..7795e7fa6e5e1 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -52,7 +52,7 @@ class MatLayerCylSet; } // namespace base namespace trd { -class TRDGeometryFlat; +class GeometryFlat; } // namespace trd namespace dataformats { @@ -173,7 +173,7 @@ template <template <typename T> class S> struct GPUCalibObjectsTemplate { typename S<TPCFastTransform>::type* fastTransform = nullptr; typename S<o2::base::MatLayerCylSet>::type* matLUT = nullptr; - typename S<o2::trd::TRDGeometryFlat>::type* trdGeometry = nullptr; + typename S<o2::trd::GeometryFlat>::type* trdGeometry = nullptr; typename S<TPCdEdxCalibrationSplines>::type* dEdxSplines = nullptr; typename S<TPCCFCalibration>::type* tpcCalibration = nullptr; }; diff --git a/GPU/GPUTracking/Base/GPUO2DataTypes.h b/GPU/GPUTracking/Base/GPUO2DataTypes.h index f1356ddd2c7ee..8d359abf4b1d3 100644 --- a/GPU/GPUTracking/Base/GPUO2DataTypes.h +++ b/GPU/GPUTracking/Base/GPUO2DataTypes.h @@ -19,7 +19,7 @@ #if defined(HAVE_O2HEADERS) && (!defined(__OPENCL__) || defined(__OPENCLCPP__)) #include "DataFormatsTPC/ClusterNative.h" #include "DetectorsBase/MatLayerCylSet.h" -#include "TRDBase/TRDGeometryFlat.h" +#include "TRDBase/GeometryFlat.h" #else #include "GPUO2FakeClasses.h" #endif diff --git a/GPU/GPUTracking/Base/GPUO2FakeClasses.h b/GPU/GPUTracking/Base/GPUO2FakeClasses.h index 49431fe94427d..68c592366fd76 100644 --- a/GPU/GPUTracking/Base/GPUO2FakeClasses.h +++ b/GPU/GPUTracking/Base/GPUO2FakeClasses.h @@ -69,7 +69,7 @@ class MatLayerCylSet } // namespace base namespace trd { -class TRDGeometryFlat +class GeometryFlat { }; } // namespace trd diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h index d8653412fa8a7..2b946e254c6c9 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h @@ -86,7 +86,7 @@ using namespace GPUCA_NAMESPACE::gpu; #include "GPUTRDTrack.cxx" #include "GPUTRDTracker.cxx" #include "GPUTRDTrackletWord.cxx" -#include "TRDGeometryBase.cxx" +#include "GeometryBase.cxx" // Files for ITS Track Fit #include "GPUITSFitterKernels.cxx" diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 1f6db07c30302..4753a65801187 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -617,7 +617,7 @@ void GPUChainTracking::SetMatLUT(std::unique_ptr<o2::base::MatLayerCylSet>&& lut processors()->calibObjects.matLUT = mMatLUTU.get(); } -void GPUChainTracking::SetTRDGeometry(std::unique_ptr<o2::trd::TRDGeometryFlat>&& geo) +void GPUChainTracking::SetTRDGeometry(std::unique_ptr<o2::trd::GeometryFlat>&& geo) { mTRDGeometryU = std::move(geo); processors()->calibObjects.trdGeometry = mTRDGeometryU.get(); diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index fc063d5a34cd6..d7ae3816579c2 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -25,7 +25,7 @@ namespace o2 { namespace trd { -class TRDGeometryFlat; +class GeometryFlat; } } // namespace o2 @@ -159,12 +159,12 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void SetTPCFastTransform(std::unique_ptr<TPCFastTransform>&& tpcFastTransform); void SetdEdxSplines(std::unique_ptr<TPCdEdxCalibrationSplines>&& dEdxSplines); void SetMatLUT(std::unique_ptr<o2::base::MatLayerCylSet>&& lut); - void SetTRDGeometry(std::unique_ptr<o2::trd::TRDGeometryFlat>&& geo); + void SetTRDGeometry(std::unique_ptr<o2::trd::GeometryFlat>&& geo); void SetTPCFastTransform(const TPCFastTransform* tpcFastTransform) { processors()->calibObjects.fastTransform = tpcFastTransform; } void SetTPCCFCalibration(const TPCCFCalibration* tpcCalibration) { processors()->calibObjects.tpcCalibration = tpcCalibration; } void SetdEdxSplines(const TPCdEdxCalibrationSplines* dEdxSplines) { processors()->calibObjects.dEdxSplines = dEdxSplines; } void SetMatLUT(const o2::base::MatLayerCylSet* lut) { processors()->calibObjects.matLUT = lut; } - void SetTRDGeometry(const o2::trd::TRDGeometryFlat* geo) { processors()->calibObjects.trdGeometry = geo; } + void SetTRDGeometry(const o2::trd::GeometryFlat* geo) { processors()->calibObjects.trdGeometry = geo; } void LoadClusterErrors(); void SetOutputControlCompressedClusters(GPUOutputControl* v) { mOutputCompressedClusters = v; } void SetOutputControlClustersNative(GPUOutputControl* v) { mOutputClustersNative = v; } @@ -234,7 +234,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega std::unique_ptr<TPCCFCalibration> mTPCCalibrationU; // TPC gain calibration and cluster finder parameters std::unique_ptr<TPCdEdxCalibrationSplines> mdEdxSplinesU; // TPC dEdx calibration splines std::unique_ptr<o2::base::MatLayerCylSet> mMatLUTU; // Material Lookup Table - std::unique_ptr<o2::trd::TRDGeometryFlat> mTRDGeometryU; // TRD Geometry + std::unique_ptr<o2::trd::GeometryFlat> mTRDGeometryU; // TRD Geometry std::unique_ptr<o2::tpc::ClusterNativeAccess> mClusterNativeAccess; diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index 9a918c3ceed36..e5127f94654b5 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -271,7 +271,7 @@ void GPUChainTracking::ReadSettings(const char* dir) processors()->calibObjects.matLUT = mMatLUTU.get(); f = dir; f += "trdgeometry.dump"; - mTRDGeometryU = ReadStructFromFile<o2::trd::TRDGeometryFlat>(f.c_str()); + mTRDGeometryU = ReadStructFromFile<o2::trd::GeometryFlat>(f.c_str()); processors()->calibObjects.trdGeometry = mTRDGeometryU.get(); #endif } diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index cc513a36b9849..5b6075108ca19 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -168,7 +168,7 @@ if(CONFIG_O2_EXTENSIONS) ../../../DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx ../../../DataFormats/Reconstruction/src/Vertex.cxx ../../../DataFormats/Reconstruction/src/TrackLTIntegral.cxx - ../../../Detectors/TRD/base/src/TRDGeometryBase.cxx + ../../../Detectors/TRD/base/src/GeometryBase.cxx ../../../Detectors/Base/src/MatLayerCylSet.cxx ../../../Detectors/Base/src/MatLayerCyl.cxx ../../../Detectors/Base/src/Ray.cxx diff --git a/GPU/GPUTracking/Standalone/tools/createGeo.C b/GPU/GPUTracking/Standalone/tools/createGeo.C index bd8d1443768d7..81e6ed7e3cbd6 100644 --- a/GPU/GPUTracking/Standalone/tools/createGeo.C +++ b/GPU/GPUTracking/Standalone/tools/createGeo.C @@ -1,8 +1,8 @@ #if !defined(__CLING__) || defined(__ROOTCLING__) #include <TSystem.h> -#include "TRDBase/TRDGeometryFlat.h" +#include "TRDBase/GeometryFlat.h" #include "DetectorsBase/GeometryManager.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "GPUO2Interface.h" #include "GPUReconstruction.h" #include "GPUChainTracking.h" @@ -12,10 +12,10 @@ using namespace GPUCA_NAMESPACE::gpu; void createGeo() { o2::base::GeometryManager::loadGeometry(); - auto gm = o2::trd::TRDGeometry::instance(); + auto gm = o2::trd::Geometry::instance(); gm->createPadPlaneArray(); gm->createClusterMatrixArray(); - o2::trd::TRDGeometryFlat gf(*gm); + o2::trd::GeometryFlat gf(*gm); //if (!gf.readMatricesFromFile()) return; // uncomment this line when the matrices dumped from AliRoot should be used gSystem->Load("libO2GPUTracking.so"); GPUReconstruction* rec = GPUReconstruction::CreateInstance(GPUReconstruction::DeviceType::CPU); diff --git a/GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C b/GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C index 362e4cdc6287c..51a2b4922ab6e 100644 --- a/GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C +++ b/GPU/GPUTracking/Standalone/tools/dumpTRDClusterMatrices.C @@ -11,7 +11,7 @@ This macro loads the TRD geometry taking into account the alignment from Run 2 and dumps the inverse of all cluster matrices to a file. To load the matrices add the following include and method to - TRDGeometryFlat.h: + GeometryFlat.h: #include <fstream> diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h b/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h index 37455db6d0790..92dd33af49a02 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDGeometry.h @@ -47,8 +47,8 @@ class GPUTRDGeometry : public AliTRDgeometry class TObjArray; #include "GPUDef.h" -#include "TRDBase/TRDGeometryFlat.h" -#include "TRDBase/TRDPadPlane.h" +#include "TRDBase/GeometryFlat.h" +#include "TRDBase/PadPlane.h" #include "DataFormatsTRD/Constants.h" #include "GPUCommonTransform3D.h" @@ -57,7 +57,7 @@ namespace GPUCA_NAMESPACE namespace gpu { -class GPUTRDpadPlane : private o2::trd::TRDPadPlane +class GPUTRDpadPlane : private o2::trd::PadPlane { public: GPUd() float GetTiltingAngle() const { return getTiltingAngle(); } @@ -73,7 +73,7 @@ class GPUTRDpadPlane : private o2::trd::TRDPadPlane GPUd() float GetNcols() const { return getNcols(); } }; -class GPUTRDGeometry : private o2::trd::TRDGeometryFlat +class GPUTRDGeometry : private o2::trd::GeometryFlat { public: GPUd() static bool CheckGeometryAvailable() { return true; } @@ -84,7 +84,7 @@ class GPUTRDGeometry : private o2::trd::TRDGeometryFlat GPUd() float GetPadPlaneRowSize(int layer, int stack, int row) const { return getPadPlane(layer, stack)->getRowSize(row); } GPUd() int GetGeomManagerVolUID(int det, int modId) const { return 0; } - // Base functionality of TRDGeometry + // Base functionality of Geometry GPUd() float GetTime0(int layer) const { return getTime0(layer); } GPUd() float GetCol0(int layer) const { return getCol0(layer); } GPUd() int GetLayer(int det) const { return getLayer(det); } @@ -151,7 +151,7 @@ class GPUTRDGeometry GPUd() float GetPadPlaneRowSize(int layer, int stack, int row) const { return 0; } GPUd() int GetGeomManagerVolUID(int det, int modId) const { return 0; } - // Base functionality of TRDGeometry + // Base functionality of Geometry GPUd() float GetTime0(int layer) const { return 0; } GPUd() float GetCol0(int layer) const { return 0; } GPUd() int GetLayer(int det) const { return 0; } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx index becb53949aa38..fcfdb62b13969 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTrackerComponent.cxx @@ -210,7 +210,7 @@ int GPUTRDTrackerComponent::DoInit(int argc, const char** argv) fTracker->EnableDebugOutput(); } fRec->RegisterGPUProcessor(fTracker, false); - fChain->SetTRDGeometry(reinterpret_cast<o2::trd::TRDGeometryFlat*>(fGeo)); + fChain->SetTRDGeometry(reinterpret_cast<o2::trd::GeometryFlat*>(fGeo)); if (fRec->Init()) { return -EINVAL; } diff --git a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C index 44dc93012e573..525432e87dab2 100644 --- a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C +++ b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C @@ -19,7 +19,7 @@ #include "CommonConstants/LHCConstants.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" -#include "TRDBase/TRDGeometry.h" +#include "TRDBase/Geometry.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "DataFormatsTRD/Tracklet64.h" #include "DataFormatsTRD/TriggerRecord.h" @@ -50,10 +50,10 @@ void run_trd_tracker(std::string path = "./", o2::base::GeometryManager::loadGeometry(); o2::base::Propagator::initFieldFromGRP(o2::base::NameConf::getGRPFileName()); - auto geo = o2::trd::TRDGeometry::instance(); + auto geo = o2::trd::Geometry::instance(); geo->createPadPlaneArray(); geo->createClusterMatrixArray(); - const o2::trd::TRDGeometryFlat geoFlat(*geo); + const o2::trd::GeometryFlat geoFlat(*geo); //-------- init GPU reconstruction --------// GPUSettingsEvent cfgEvent; // defaults should be ok From 2311d5c6260ad8875ac5a5a0bf0a6e14d4c641d1 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Tue, 3 Nov 2020 10:56:13 +0300 Subject: [PATCH 1200/1751] Detectors/TPC: make readability-braces-around-statements happy --- Detectors/TPC/base/include/TPCBase/CRU.h | 9 +-- Detectors/TPC/base/include/TPCBase/Mapper.h | 6 +- .../TPC/base/include/TPCBase/PadROCPos.h | 6 +- Detectors/TPC/base/src/CDBInterface.cxx | 9 ++- Detectors/TPC/base/src/Mapper.cxx | 3 +- Detectors/TPC/base/src/PadRegionInfo.cxx | 12 ++-- Detectors/TPC/base/src/Painter.cxx | 3 +- Detectors/TPC/base/src/Utils.cxx | 6 +- Detectors/TPC/base/test/testTPCMapper.cxx | 3 +- .../include/TPCCalibration/CalibRawBase.h | 21 ++++--- .../TPC/calibration/src/CalibPedestal.cxx | 9 ++- Detectors/TPC/calibration/src/CalibPulser.cxx | 24 +++++--- .../TPC/calibration/src/CalibRawBase.cxx | 3 +- .../TPC/calibration/src/CalibTreeDump.cxx | 3 +- Detectors/TPC/calibration/src/DigitDump.cxx | 6 +- .../TPC/monitor/src/SimpleEventDisplay.cxx | 21 ++++--- .../DigitalCurrentClusterIntegrator.h | 6 +- .../TPCReconstruction/GBTFrameContainer.h | 3 +- .../include/TPCReconstruction/HwClusterer.h | 3 +- .../include/TPCReconstruction/RawReader.h | 3 +- .../include/TPCReconstruction/RawReaderCRU.h | 24 ++++---- .../TPCReconstruction/SyncPatternMonitor.h | 8 ++- .../TPC/reconstruction/run/readGBTFrames.cxx | 24 +++++--- .../TPC/reconstruction/run/readRawData.cxx | 10 ++-- .../reconstruction/src/AdcClockMonitor.cxx | 12 ++-- .../TPC/reconstruction/src/ClustererTask.cxx | 12 ++-- .../reconstruction/src/GBTFrameContainer.cxx | 27 ++++++--- .../src/HardwareClusterDecoder.cxx | 6 +- .../TPC/reconstruction/src/HwClusterer.cxx | 33 +++++++---- .../TPC/reconstruction/src/RawReader.cxx | 57 ++++++++++++------- .../TPC/reconstruction/src/RawReaderCRU.cxx | 18 ++++-- .../src/TPCFastTransformHelperO2.cxx | 3 +- .../test/testTPCFastTransform.cxx | 6 +- .../include/TPCSimulation/ElectronTransport.h | 3 +- .../include/TPCSimulation/SAMPAProcessing.h | 3 +- Detectors/TPC/simulation/src/Detector.cxx | 19 ++++--- .../TPC/simulation/src/GEMAmplification.cxx | 3 +- Detectors/TPC/simulation/src/PadResponse.cxx | 3 +- .../TPC/workflow/src/LinkZSToDigitsSpec.cxx | 6 +- Detectors/TPC/workflow/src/ZSSpec.cxx | 6 +- 40 files changed, 289 insertions(+), 153 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/CRU.h b/Detectors/TPC/base/include/TPCBase/CRU.h index e92751fb7dcd0..55e6224512a68 100644 --- a/Detectors/TPC/base/include/TPCBase/CRU.h +++ b/Detectors/TPC/base/include/TPCBase/CRU.h @@ -82,14 +82,15 @@ inline GEMstack CRU::gemStack() const { const int reg = int(region()); - if (reg < CRUperIROC) + if (reg < CRUperIROC) { return GEMstack::IROCgem; - else if (reg - CRUperIROC < CRUperPartition) + } else if (reg - CRUperIROC < CRUperPartition) { return GEMstack::OROC1gem; - else if (reg - CRUperIROC - CRUperPartition < CRUperPartition) + } else if (reg - CRUperIROC - CRUperPartition < CRUperPartition) { return GEMstack::OROC2gem; - else + } else { return GEMstack::OROC3gem; + } } } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/base/include/TPCBase/Mapper.h b/Detectors/TPC/base/include/TPCBase/Mapper.h index 88ce03706bbd8..c8f5cd7ca8729 100644 --- a/Detectors/TPC/base/include/TPCBase/Mapper.h +++ b/Detectors/TPC/base/include/TPCBase/Mapper.h @@ -581,8 +581,9 @@ inline const DigitPos Mapper::findDigitPosFromLocalPosition(const LocalPosition3 for (const PadRegionInfo& padRegion : mMapPadRegionInfo) { cru = CRU(sec, padRegion.getRegion()); pad = padRegion.findPad(pos); - if (pad.isValid()) + if (pad.isValid()) { break; + } } return DigitPos(cru, pad); @@ -592,8 +593,9 @@ inline const DigitPos Mapper::findDigitPosFromGlobalPosition(const GlobalPositio { // ===| find sector |========================================================= float phi = std::atan2(pos.Y(), pos.X()); - if (phi < 0.) + if (phi < 0.) { phi += TWOPI; + } const unsigned char secNum = std::floor(phi / SECPHIWIDTH); // const float secPhi = secNum * SECPHIWIDTH + SECPHIWIDTH / 2.; Sector sec(secNum + (pos.Z() < 0) * SECTORSPERSIDE); diff --git a/Detectors/TPC/base/include/TPCBase/PadROCPos.h b/Detectors/TPC/base/include/TPCBase/PadROCPos.h index f1520ccc374a0..cb76a725591db 100644 --- a/Detectors/TPC/base/include/TPCBase/PadROCPos.h +++ b/Detectors/TPC/base/include/TPCBase/PadROCPos.h @@ -89,10 +89,12 @@ class PadROCPos /// smaller operator bool operator<(const PadROCPos& other) const { - if (mROC < other.mROC) + if (mROC < other.mROC) { return true; - if (mROC == other.mROC && mPadPos < other.mPadPos) + } + if (mROC == other.mROC && mPadPos < other.mPadPos) { return true; + } return false; } diff --git a/Detectors/TPC/base/src/CDBInterface.cxx b/Detectors/TPC/base/src/CDBInterface.cxx index 612f129372dcb..b6fb55d2083ad 100644 --- a/Detectors/TPC/base/src/CDBInterface.cxx +++ b/Detectors/TPC/base/src/CDBInterface.cxx @@ -52,8 +52,9 @@ const CalPad& CDBInterface::getPedestals() loadNoiseAndPedestalFromFile(); } } else if (mUseDefaults) { - if (!mPedestals) + if (!mPedestals) { createDefaultPedestals(); + } } else { // return from CDB, assume that check for object existence are done there return getObjectFromCDB<CalPad>(CDBTypeMap.at(CDBType::CalPedestal)); @@ -75,8 +76,9 @@ const CalPad& CDBInterface::getNoise() loadNoiseAndPedestalFromFile(); } } else if (mUseDefaults) { - if (!mNoise) + if (!mNoise) { createDefaultNoise(); + } } else { // return from CDB, assume that check for object existence are done there return getObjectFromCDB<CalPad>(CDBTypeMap.at(CDBType::CalNoise)); @@ -98,8 +100,9 @@ const CalPad& CDBInterface::getGainMap() loadGainMapFromFile(); } } else if (mUseDefaults) { - if (!mGainMap) + if (!mGainMap) { createDefaultGainMap(); + } } else { // return from CDB, assume that check for object existence are done there return getObjectFromCDB<CalPad>(CDBTypeMap.at(CDBType::CalPadGainFull)); diff --git a/Detectors/TPC/base/src/Mapper.cxx b/Detectors/TPC/base/src/Mapper.cxx index 46abd930a4a39..3acc10d73edd2 100644 --- a/Detectors/TPC/base/src/Mapper.cxx +++ b/Detectors/TPC/base/src/Mapper.cxx @@ -191,8 +191,9 @@ void Mapper::load(const std::string& mappingDir) //readMappingFile(inputDir+"/Detectors/TPC/base/files/TABLE-OROC3.txt"); const char* aliceO2env = std::getenv("O2_ROOT"); - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/TPC/files"; } readMappingFile(inputDir + "/TABLE-IROC.txt"); diff --git a/Detectors/TPC/base/src/PadRegionInfo.cxx b/Detectors/TPC/base/src/PadRegionInfo.cxx index fe80e757125c1..6a3117ad53730 100644 --- a/Detectors/TPC/base/src/PadRegionInfo.cxx +++ b/Detectors/TPC/base/src/PadRegionInfo.cxx @@ -54,25 +54,29 @@ const PadPos PadRegionInfo::findPad(const LocalPosition2D& pos, const Side side const PadPos PadRegionInfo::findPad(const float localX, const float localY, const Side side /*=Side::A*/) const { - if (!isInRegion(localX)) + if (!isInRegion(localX)) { return PadPos(255, 255); + } // the pad coordinate system is for pad-side view. // on the A-Side one looks from the back-side, therefore // the localY-sign must be changed const float localYfactor = (side == Side::A) ? -1.f : 1.f; const unsigned int row = std::floor((localX - mRadiusFirstRow) / mPadHeight); - if (row >= mNumberOfPadRows) + if (row >= mNumberOfPadRows) { return PadPos(255, 255); + } const unsigned int npads = getPadsInRowRegion(row); const float padfloat = (npads / 2 * mPadWidth - localYfactor * localY) / mPadWidth; - if (padfloat < 0) + if (padfloat < 0) { return PadPos(255, 255); + } const unsigned int pad = static_cast<unsigned int>(padfloat); - if (pad >= npads) + if (pad >= npads) { return PadPos(255, 255); + } return PadPos(row, pad); } diff --git a/Detectors/TPC/base/src/Painter.cxx b/Detectors/TPC/base/src/Painter.cxx index 8089c4bc0cc87..f818bad0e7add 100644 --- a/Detectors/TPC/base/src/Painter.cxx +++ b/Detectors/TPC/base/src/Painter.cxx @@ -77,8 +77,9 @@ TCanvas* painter::draw(const CalDet<T>& calDet, int nbins1D, float xMin1D, float const auto val = calDet.getValue(roc, irow, ipad); const GlobalPosition2D pos = mapper.getPadCentre(PadROCPos(roc, irow, ipad)); const int bin = hist2D->FindBin(pos.X(), pos.Y()); - if (!hist2D->GetBinContent(bin)) + if (!hist2D->GetBinContent(bin)) { hist2D->SetBinContent(bin, val); + } hist1D->Fill(val); } } diff --git a/Detectors/TPC/base/src/Utils.cxx b/Detectors/TPC/base/src/Utils.cxx index afffced098dcd..6469639e34171 100644 --- a/Detectors/TPC/base/src/Utils.cxx +++ b/Detectors/TPC/base/src/Utils.cxx @@ -91,10 +91,12 @@ void utils::addFECInfo() const auto& mapper = Mapper::instance(); const int roc = h->GetUniqueID(); - if (roc < 0 || roc >= (int)ROC::MaxROC) + if (roc < 0 || roc >= (int)ROC::MaxROC) { return; - if (row < 0 || row >= (int)mapper.getNumberOfRowsROC(roc)) + } + if (row < 0 || row >= (int)mapper.getNumberOfRowsROC(roc)) { return; + } const int nPads = mapper.getNumberOfPadsInRowROC(roc, row); const int pad = cpad + nPads / 2; //printf("row %d, cpad %d, pad %d, nPads %d\n", row, cpad, pad, nPads); diff --git a/Detectors/TPC/base/test/testTPCMapper.cxx b/Detectors/TPC/base/test/testTPCMapper.cxx index bfd701298282b..54682abb179ee 100644 --- a/Detectors/TPC/base/test/testTPCMapper.cxx +++ b/Detectors/TPC/base/test/testTPCMapper.cxx @@ -59,8 +59,9 @@ BOOST_AUTO_TEST_CASE(Mapper_complex_test1) std::string line; const char* aliceO2env = std::getenv("O2_ROOT"); std::string inputDir = " "; - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/TPC/files"; std::string file = inputDir + mappingTables[i]; diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h index cb607d0563453..0639335c88bd1 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h @@ -204,8 +204,9 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEvent(int eventNumber) //______________________________________________________________________________ inline CalibRawBase::ProcessStatus CalibRawBase::processEventGBT() { - if (!mGBTFrameContainers.size()) + if (!mGBTFrameContainers.size()) { return ProcessStatus::NoReaders; + } resetEvent(); // loop over raw readers, fill digits for 500 time bins and process @@ -231,8 +232,9 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventGBT() // row is local in region (CRU) const int row = digi.getRow(); const int pad = digi.getPad(); - if (row == 255 || pad == 255) + if (row == 255 || pad == 255) { continue; + } int rowOffset = 0; switch (mPadSubset) { @@ -285,8 +287,9 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventGBT() //______________________________________________________________________________ inline CalibRawBase::ProcessStatus CalibRawBase::processEventRawReader(int eventNumber) { - if (!mRawReaders.size()) + if (!mRawReaders.size()) { return ProcessStatus::NoReaders; + } resetEvent(); // loop over raw readers, fill digits for 500 time bins and process @@ -317,8 +320,9 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventRawReader(int event o2::tpc::PadPos padPos; while (std::shared_ptr<std::vector<uint16_t>> data = reader->getNextData(padPos)) { - if (!data) + if (!data) { continue; + } mProcessedTimeBins = std::max(mProcessedTimeBins, data->size()); @@ -331,8 +335,9 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventRawReader(int event // row is local in region (CRU) const int row = padPos.getRow(); const int pad = padPos.getPad(); - if (row == 255 || pad == 255) + if (row == 255 || pad == 255) { continue; + } int timeBin = 0; for (const auto& signalI : *data) { @@ -387,8 +392,9 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventRawReader(int event //______________________________________________________________________________ inline CalibRawBase::ProcessStatus CalibRawBase::processEventRawReaderCRU(int eventNumber) { - if (!mRawReaderCRUManager.getNumberOfReaders()) + if (!mRawReaderCRUManager.getNumberOfReaders()) { return ProcessStatus::NoReaders; + } resetEvent(); mRawReaderCRUManager.init(); @@ -514,8 +520,9 @@ inline CalibRawBase::ProcessStatus CalibRawBase::processEventDigitTree(int event const PadRegionInfo& regionInfo = mMapper.getPadRegionInfo(cru.region()); const PartitionInfo& partInfo = mMapper.getPartitionInfo(cru.partition()); - if (row == 255 || pad == 255) + if (row == 255 || pad == 255) { continue; + } int rowOffset = 0; switch (mPadSubset) { diff --git a/Detectors/TPC/calibration/src/CalibPedestal.cxx b/Detectors/TPC/calibration/src/CalibPedestal.cxx index 9383713a1ebee..df8f5496d0b64 100644 --- a/Detectors/TPC/calibration/src/CalibPedestal.cxx +++ b/Detectors/TPC/calibration/src/CalibPedestal.cxx @@ -59,10 +59,12 @@ Int_t CalibPedestal::updateROC(const Int_t roc, const Int_t row, const Int_t pad const Int_t timeBin, const Float_t signal) { Int_t adcValue = Int_t(signal); - if (timeBin < mFirstTimeBin || timeBin > mLastTimeBin) + if (timeBin < mFirstTimeBin || timeBin > mLastTimeBin) { return 0; - if (adcValue < mADCMin || adcValue > mADCMax) + } + if (adcValue < mADCMin || adcValue > mADCMax) { return 0; + } const GlobalPadNumber padInROC = mMapper.getPadNumberInROC(PadROCPos(roc, row, pad)); Int_t bin = padInROC * mNumberOfADCs + (adcValue - mADCMin); @@ -78,8 +80,9 @@ Int_t CalibPedestal::updateROC(const Int_t roc, const Int_t row, const Int_t pad CalibPedestal::vectorType* CalibPedestal::getVector(ROC roc, bool create /*=kFALSE*/) { vectorType* vec = mADCdata[roc].get(); - if (vec || !create) + if (vec || !create) { return vec; + } const size_t numberOfPads = (roc.rocType() == RocType::IROC) ? mMapper.getPadsInIROC() : mMapper.getPadsInOROC(); diff --git a/Detectors/TPC/calibration/src/CalibPulser.cxx b/Detectors/TPC/calibration/src/CalibPulser.cxx index 53ef51b855989..d3e2bbb618067 100644 --- a/Detectors/TPC/calibration/src/CalibPulser.cxx +++ b/Detectors/TPC/calibration/src/CalibPulser.cxx @@ -106,8 +106,9 @@ Int_t CalibPulser::updateROC(const Int_t roc, const Int_t row, const Int_t pad, signal -= mPedestal->getValue(ROC(roc), row, pad); } - if (signal < mADCMin || signal > mADCMax) + if (signal < mADCMin || signal > mADCMax) { return 0; + } // ===| temporary calibration data |========================================== const PadROCPos padROCPos(roc, row, pad); @@ -174,8 +175,9 @@ TH2S* CalibPulser::getHistogram(ROC roc, CalibPulser::PtrVectorType& rocVector, std::string_view type, bool create /*=kFALSE*/) { TH2S* vec = rocVector[roc].get(); - if (vec || !create) + if (vec || !create) { return vec; + } const size_t nChannels = mMapper.getNumberOfPads(roc); rocVector[roc] = std::make_unique<TH2S>(Form("hCalib%s%02d", type.data(), roc.getRoc()), @@ -210,8 +212,9 @@ CalibPulser::PulserData CalibPulser::processPadData(const PadROCPos& padROCPos, for (int t = maxPosition - mPeakIntMinus; t <= maxPosition + mPeakIntPlus; ++t) { const auto signal = adcData[t]; // check time bounds - if (t < 0 || t >= vectorSize) + if (t < 0 || t >= vectorSize) { continue; + } weightedSum += signal * (t + 0.5); // +0.5 to get the center of the time bin weightedSum2 += signal * (t + 0.5) * (t + 0.5); chargeSum += signal; @@ -259,8 +262,9 @@ void CalibPulser::resetData() for (auto histArray : v) { for (auto& histPtr : *histArray) { auto ptr = histPtr.get(); - if (ptr) + if (ptr) { ptr->Reset(); + } } } } @@ -273,8 +277,9 @@ void CalibPulser::analyse() auto histWidth = mWidthHistograms.at(roc).get(); auto histQtot = mQtotHistograms.at(roc).get(); - if (!histT0 || !histWidth || !histQtot) + if (!histT0 || !histWidth || !histQtot) { continue; + } // array pointer const auto arrT0 = histT0->GetArray(); @@ -311,14 +316,17 @@ void CalibPulser::dumpToFile(const std::string filename, uint32_t type /* = 0*/) printf("dump debug info\n"); // temporary arrays for writing the objects TObjArray vT0; - for (auto& val : mT0Histograms) + for (auto& val : mT0Histograms) { vT0.Add(val.get()); + } TObjArray vWidth; - for (auto& val : mWidthHistograms) + for (auto& val : mWidthHistograms) { vWidth.Add(val.get()); + } TObjArray vQtot; - for (auto& val : mQtotHistograms) + for (auto& val : mQtotHistograms) { vQtot.Add(val.get()); + } vT0.Write("T0Histograms", TObject::kSingleKey); vWidth.Write("WidthHistograms", TObject::kSingleKey); diff --git a/Detectors/TPC/calibration/src/CalibRawBase.cxx b/Detectors/TPC/calibration/src/CalibRawBase.cxx index a2291159d33fe..a414cbf1f4934 100644 --- a/Detectors/TPC/calibration/src/CalibRawBase.cxx +++ b/Detectors/TPC/calibration/src/CalibRawBase.cxx @@ -113,8 +113,9 @@ void CalibRawBase::setupContainers(TString fileInfo, uint32_t verbosity, uint32_ TString& filename = static_cast<TObjString*>(arrDataInfo->At(0))->String(); iCRU = static_cast<TObjString*>(arrDataInfo->At(1))->String().Atoi(); iLink = static_cast<TObjString*>(arrDataInfo->At(2))->String().Atoi(); - if (arrDataInfo->GetEntriesFast() > 3) + if (arrDataInfo->GetEntriesFast() > 3) { iSampaVersion = static_cast<TObjString*>(arrDataInfo->At(3))->String().Atoi(); + } auto cont = new GBTFrameContainer(iSize, iCRU, iLink, iSampaVersion); diff --git a/Detectors/TPC/calibration/src/CalibTreeDump.cxx b/Detectors/TPC/calibration/src/CalibTreeDump.cxx index 54d8c15f383cd..0f92e2c502518 100644 --- a/Detectors/TPC/calibration/src/CalibTreeDump.cxx +++ b/Detectors/TPC/calibration/src/CalibTreeDump.cxx @@ -257,8 +257,9 @@ void CalibTreeDump::readTraceLengths(std::string_view mappingDir) std::string inputDir = mappingDir.data(); if (!inputDir.size()) { const char* aliceO2env = std::getenv("O2_ROOT"); - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/TPC/files"; } diff --git a/Detectors/TPC/calibration/src/DigitDump.cxx b/Detectors/TPC/calibration/src/DigitDump.cxx index 1797f6352f2f8..dfbfbe38f3d5e 100644 --- a/Detectors/TPC/calibration/src/DigitDump.cxx +++ b/Detectors/TPC/calibration/src/DigitDump.cxx @@ -100,10 +100,12 @@ void DigitDump::sortDigits() // sort digits for (auto& digits : mDigits) { std::sort(digits.begin(), digits.end(), [](const auto& a, const auto& b) { - if (a.getTimeStamp() < b.getTimeStamp()) + if (a.getTimeStamp() < b.getTimeStamp()) { return true; - if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) + } + if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) { return true; + } return false; }); } diff --git a/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx b/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx index 77f02a12b537b..bd85cb9bb057c 100644 --- a/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx +++ b/Detectors/TPC/monitor/src/SimpleEventDisplay.cxx @@ -87,16 +87,21 @@ Int_t SimpleEventDisplay::updateROC(const Int_t roc, // assumes that it is looped over consecutive time bins of one pad // //printf("update called: %d, %d, %d, %d, %.3f\n", roc, row, pad, timeBin, signal); - if (row < 0) + if (row < 0) { return 0; - if (pad < 0) + } + if (pad < 0) { return 0; - if (timeBin < 0) + } + if (timeBin < 0) { return 0; - if ((timeBin > mLastTimeBin) || (timeBin < mFirstTimeBin)) + } + if ((timeBin > mLastTimeBin) || (timeBin < mFirstTimeBin)) { return 0; - if (mSectorLoop && roc % 36 != mSelectedSector % 36) + } + if (mSectorLoop && roc % 36 != mSelectedSector % 36) { return 0; + } if (row < 0 || pad < 0) { printf("Wrong Pad or Row number, skipping!"); @@ -194,8 +199,9 @@ TH1D* SimpleEventDisplay::makePadSignals(Int_t roc, Int_t row, Int_t pad) } TH1D* h = nullptr; const Int_t nbins = mLastTimeBin - mFirstTimeBin; - if (nbins <= 0) + if (nbins <= 0) { return nullptr; + } const Int_t offset = (nbins + 2) * (channel + 1); Double_t* arrP = nullptr; @@ -247,8 +253,9 @@ void SimpleEventDisplay::resetEvent() //for (auto reader : mGBTFrameContainers) { //reader->reProcessAllFrames(); //} - if (!mSectorLoop) + if (!mSectorLoop) { mPadMax.multiply(0.); + } mHSigIROC->Reset(); mHSigOROC->Reset(); } diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h index 7023025781622..e30ea4e2ff186 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/DigitalCurrentClusterIntegrator.h @@ -44,11 +44,13 @@ class DigitalCurrentClusterIntegrator void integrateCluster(int sector, int row, float pad, unsigned int charge) { int ipad = ipad + 0.5; - if (ipad < 0) + if (ipad < 0) { ipad = 0; + } int maxPad = o2::tpc::Mapper::instance().getNumberOfPadsInRowSector(row); - if (ipad >= maxPad) + if (ipad >= maxPad) { ipad = maxPad - 1; + } mIntegratedCurrents[sector][row][ipad] += charge; } void clear(); //Clear all currents to 0 diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/GBTFrameContainer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/GBTFrameContainer.h index 264c686e2999f..c5f6a7afa26e8 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/GBTFrameContainer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/GBTFrameContainer.h @@ -147,8 +147,9 @@ class GBTFrameContainer void setEnableStoreGBTFrames(bool val) { mEnableStoreGBTFrames = val; - if (!mEnableStoreGBTFrames) + if (!mEnableStoreGBTFrames) { mGBTFrames.resize(2); + } }; /// Extracts the digits after all 80 channels were transmitted (5*16) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h index b57d06b8dcd85..3d9fe3c9a2c76 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/HwClusterer.h @@ -275,8 +275,9 @@ inline Vc::uint_v HwClusterer::getFpOfADC(const Vc::uint_v value) inline short HwClusterer::getFirstSetBitOfField() { for (short i = 0; i < mTimebinsInBuffer; ++i) { - if ((mCurrentMcContainerInBuffer >> i) & 0x1) + if ((mCurrentMcContainerInBuffer >> i) & 0x1) { return i; + } } return -1; } diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReader.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReader.h index fe22594aee82c..b75c4c0fcbb9b 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReader.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReader.h @@ -247,8 +247,9 @@ inline std::shared_ptr<std::vector<uint16_t>> RawReader::getData(const PadPos& p inline std::shared_ptr<std::vector<uint16_t>> RawReader::getNextData(PadPos& padPos) { - if (mDataIterator == mData.end()) + if (mDataIterator == mData.end()) { return nullptr; + } std::map<PadPos, std::shared_ptr<std::vector<uint16_t>>>::iterator last = mDataIterator; mDataIterator++; padPos = last->first; diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h index 5e14e6e23ad41..ef6ca52e2ae3a 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h @@ -109,10 +109,11 @@ class ADCRawData /// limit. void setNumTimebins(uint32_t numTB) { - if (numTB >= mADCRaw[mOutputStream].size()) + if (numTB >= mADCRaw[mOutputStream].size()) { mNumTimeBins = mADCRaw[mOutputStream].size(); - else + } else { mNumTimeBins = numTB; + } }; /// number of time bin for selected stream @@ -757,18 +758,19 @@ inline void GBTFrame::updateSyncCheck(SyncArray& syncArray) { const auto offset = mPrevHWpos ^ 4; - for (int s = 0; s < 5; s++) + for (int s = 0; s < 5; s++) { for (int h = 0; h < 4; h++) { const auto hPos = h + offset; // set position of last filled HW // shift in a 1 if the halfword is 0x15 - if (mFrameHalfWords[s][hPos] == 0x15) + if (mFrameHalfWords[s][hPos] == 0x15) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1) | 1; // shift in a 0 if the halfword is 0xA - else if (mFrameHalfWords[s][hPos] == 0xA) + } else if (mFrameHalfWords[s][hPos] == 0xA) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1); // otherwise reset the register to 0 - else + } else { mSyncCheckRegister[s] = 0; + } // std::cout << " SReg : " << s << " : " << std::hex << mSyncCheckRegister[s] << std::endl; // check the register content for the SYNC pattern // Patterh is : 1100.1100.1100.1100.1111.0000.1111.0000 = 0xCCCCF0F0 @@ -776,7 +778,8 @@ inline void GBTFrame::updateSyncCheck(SyncArray& syncArray) if (mSyncCheckRegister[s] == 0xCCCCF0F0 or mSyncCheckRegister[s] == 0x4CCCF0F0 or mSyncCheckRegister[s] == 0x0CCCF0F0) { syncArray[s].setPos(mPacketNum, mFrameNum, mFilePos, h); }; - }; + } + }; } inline void GBTFrame::updateSyncCheck(bool verbose) @@ -787,14 +790,15 @@ inline void GBTFrame::updateSyncCheck(bool verbose) for (int h = 0; h < 4; h++) { const auto hPos = h + offset; // set position of last filled HW // shift in a 1 if the halfword is 0x15 - if (mFrameHalfWords[s][hPos] == 0x15) + if (mFrameHalfWords[s][hPos] == 0x15) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1) | 1; // shift in a 0 if the halfword is 0xA - else if (mFrameHalfWords[s][hPos] == 0xA) + } else if (mFrameHalfWords[s][hPos] == 0xA) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1); // otherwise reset the register to 0 - else + } else { mSyncCheckRegister[s] = 0; + } // std::cout << " SReg : " << s << " : " << std::hex << mSyncCheckRegister[s] << std::endl; // check the register content for the SYNC pattern // Patterh is : 1100.1100.1100.1100.1111.0000.1111.0000 = 0xCCCCF0F0 diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/SyncPatternMonitor.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/SyncPatternMonitor.h index 6340c49542cd8..a788d63da9722 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/SyncPatternMonitor.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/SyncPatternMonitor.h @@ -102,10 +102,11 @@ inline short SyncPatternMonitor::addSequence(const short hw0, const short hw1, c inline void SyncPatternMonitor::checkWord(const short hw, const short pos) { ++mCheckedWords; - if (hw == SYNC_PATTERN[mPosition]) + if (hw == SYNC_PATTERN[mPosition]) { ++mPosition; - else if (!(mPosition == SYNC_START + 2 && hw == SYNC_PATTERN[mPosition - 1])) + } else if (!(mPosition == SYNC_START + 2 && hw == SYNC_PATTERN[mPosition - 1])) { mPosition = SYNC_START; + } // Don't reset mPosition at the beginning to avoid missing of start of sync pattern in cases like // // @@ -116,8 +117,9 @@ inline void SyncPatternMonitor::checkWord(const short hw, const short pos) // | // real start - if (mPosition == 32) + if (mPosition == 32) { patternFound(pos); + } }; inline void SyncPatternMonitor::patternFound(const short hw) diff --git a/Detectors/TPC/reconstruction/run/readGBTFrames.cxx b/Detectors/TPC/reconstruction/run/readGBTFrames.cxx index 31356aea130e8..96cac97f2adff 100644 --- a/Detectors/TPC/reconstruction/run/readGBTFrames.cxx +++ b/Detectors/TPC/reconstruction/run/readGBTFrames.cxx @@ -32,8 +32,9 @@ std::mutex mtx; bool isVector1(std::vector<int>& vec) { for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) { - if ((*it) != 1) + if ((*it) != 1) { return false; + } } return true; } @@ -125,18 +126,21 @@ int main(int argc, char* argv[]) std::vector<int> addData_done(infile.size(), 0); std::vector<int> reading_done(infile.size(), 0); for (int i = 0; i < infile.size(); ++i) { - if (size.size() >= infile.size()) + if (size.size() >= infile.size()) { iSize = size[i]; - else + } else { iSize = size[0]; - if (CRU.size() >= infile.size()) + } + if (CRU.size() >= infile.size()) { iCRU = CRU[i]; - else + } else { iCRU = CRU[0]; - if (link.size() >= infile.size()) + } + if (link.size() >= infile.size()) { iLink = link[i]; - else + } else { iLink = link[0]; + } container.push_back(new o2::tpc::GBTFrameContainer(iSize, iCRU, iLink)); container.back()->setEnableAdcClockWarning(checkAdcClock); @@ -149,8 +153,9 @@ int main(int argc, char* argv[]) start = std::chrono::system_clock::now(); for (int i = 0; i < infile.size(); ++i) { - if (infile[i] != "NOFILE") + if (infile[i] != "NOFILE") { threads.emplace_back(addData, std::ref(*container[i]), std::ref(infile[i]), frames, rorcFlavor, std::ref(addData_done[i])); + } } std::vector<std::vector<std::ofstream*>> outfiles(infile.size()); @@ -173,8 +178,9 @@ int main(int argc, char* argv[]) outfiles[i].push_back(out); } - if (j == 2) + if (j == 2) { continue; + } outname = ""; if (i >= outfile.size()) { outfiles[i].push_back(nullptr); diff --git a/Detectors/TPC/reconstruction/run/readRawData.cxx b/Detectors/TPC/reconstruction/run/readRawData.cxx index ac9fd8e1fd55b..137d5d40486c6 100644 --- a/Detectors/TPC/reconstruction/run/readRawData.cxx +++ b/Detectors/TPC/reconstruction/run/readRawData.cxx @@ -65,8 +65,9 @@ int main(int argc, char* argv[]) return EXIT_SUCCESS; } - if (infile[0] == "NOFILE") + if (infile[0] == "NOFILE") { return EXIT_SUCCESS; + } // Initialize logger FairLogger* logger = FairLogger::GetLogger(); @@ -80,12 +81,13 @@ int main(int argc, char* argv[]) for (int i = 0; i < infile.size(); ++i) { readers.emplace_back(); readers[i].addEventSynchronizer(eventSync); - if (region.size() != infile.size() && link.size() == infile.size()) + if (region.size() != infile.size() && link.size() == infile.size()) { readers[i].addInputFile(region[0], link[i], sampaVersion[i], infile[i]); - else if (region.size() == infile.size() && link.size() != infile.size()) + } else if (region.size() == infile.size() && link.size() != infile.size()) { readers[i].addInputFile(region[i], link[0], sampaVersion[i], infile[i]); - else + } else { readers[i].addInputFile(region[i], link[i], sampaVersion[i], infile[i]); + } readers[i].setUseRawInMode3(useRawInMode3); readers[i].setCheckAdcClock(false); } diff --git a/Detectors/TPC/reconstruction/src/AdcClockMonitor.cxx b/Detectors/TPC/reconstruction/src/AdcClockMonitor.cxx index ef33491e5394f..8b0f3be173da4 100644 --- a/Detectors/TPC/reconstruction/src/AdcClockMonitor.cxx +++ b/Detectors/TPC/reconstruction/src/AdcClockMonitor.cxx @@ -82,14 +82,16 @@ int AdcClockMonitor::addSequence(const short seq) mSequencePosition == 0 || mSequencePosition == 1 || mSequencePosition == 2) { - if (seq != 0xF) + if (seq != 0xF) { mState = state::error; + } ++mSequencePosition; break; } if (mSequencePosition == 3) { - if (seq != mTransition0) + if (seq != mTransition0) { mState = state::error; + } ++mSequencePosition; break; } @@ -97,14 +99,16 @@ int AdcClockMonitor::addSequence(const short seq) mSequencePosition == 4 || mSequencePosition == 5 || mSequencePosition == 6) { - if (seq != 0x0) + if (seq != 0x0) { mState = state::error; + } mSequencePosition++; break; } if (mSequencePosition == 7) { - if (seq != mTransition1) + if (seq != mTransition1) { mState = state::error; + } ++mSequencePosition; mSequenceCompleted = true; break; diff --git a/Detectors/TPC/reconstruction/src/ClustererTask.cxx b/Detectors/TPC/reconstruction/src/ClustererTask.cxx index 831078120784a..67bbb1b207dbc 100644 --- a/Detectors/TPC/reconstruction/src/ClustererTask.cxx +++ b/Detectors/TPC/reconstruction/src/ClustererTask.cxx @@ -98,10 +98,12 @@ void ClustererTask::Exec(Option_t* option) { LOG(DEBUG) << "Running clusterization on event " << mEventCount << " with " << mDigitsArray->size() << " digits."; - if (mHwClustersArray) + if (mHwClustersArray) { mHwClustersArray->clear(); - if (mHwClustersMCTruthArray) + } + if (mHwClustersMCTruthArray) { mHwClustersMCTruthArray->clear(); + } mHwClusterer->process(gsl::span<o2::tpc::Digit const>(mDigitsArray->data(), mDigitsArray->size()), *mDigitMCTruthArray.get()); LOG(DEBUG) << "Hw clusterer delivered " << mHwClustersArray->size() << " cluster container"; @@ -114,10 +116,12 @@ void ClustererTask::FinishTask() { LOG(DEBUG) << "Finish clusterization"; - if (mHwClustersArray) + if (mHwClustersArray) { mHwClustersArray->clear(); - if (mHwClustersMCTruthArray) + } + if (mHwClustersMCTruthArray) { mHwClustersMCTruthArray->clear(); + } mHwClusterer->finishProcess(*mDigitsArray.get(), *mDigitMCTruthArray.get()); LOG(DEBUG) << "Hw clusterer delivered " << mHwClustersArray->size() << " cluster container"; diff --git a/Detectors/TPC/reconstruction/src/GBTFrameContainer.cxx b/Detectors/TPC/reconstruction/src/GBTFrameContainer.cxx index c855834166b36..cce8657deeb46 100644 --- a/Detectors/TPC/reconstruction/src/GBTFrameContainer.cxx +++ b/Detectors/TPC/reconstruction/src/GBTFrameContainer.cxx @@ -185,8 +185,9 @@ void GBTFrameContainer::addGBTFramesFromBinaryFile(std::string fileName, std::st std::cout << std::endl; for (int j = 0; j < 5; ++j) { - if (ids[j] == 0x8) + if (ids[j] == 0x8) { writeValue[j] = true; + } } for (int j = 0; j < 5; ++j) { if ((writeValue[j] & ids[j]) == 0xF) { @@ -232,8 +233,9 @@ void GBTFrameContainer::addGBTFramesFromBinaryFile(std::string fileName, std::st adcValues[0][((ids[0] & 0x7) * 2)] = (((ids[0] >> 3) & 0x1) == 0) ? 0 : ((words[4] & 0xF) << 6) | ((words[5] >> 26) & 0x3F); for (int j = 0; j < 5; ++j) { - if (ids[j] == 0x8) + if (ids[j] == 0x8) { writeValue[j] = true; + } } for (int j = 0; j < 5; ++j) { if ((writeValue[j] & ids[j]) == 0xF) { @@ -304,13 +306,15 @@ void GBTFrameContainer::processFrame(std::vector<GBTFrame>::iterator iFrame) { ++mGBTFramesAnalyzed; - if (mEnableAdcClockWarning) + if (mEnableAdcClockWarning) { checkAdcClock(iFrame); + } searchSyncPattern(iFrame); - if (mEnableCompileAdcValues) + if (mEnableCompileAdcValues) { compileAdcValues(iFrame); + } } void GBTFrameContainer::compileAdcValues(std::vector<GBTFrame>::iterator iFrame) @@ -319,10 +323,12 @@ void GBTFrameContainer::compileAdcValues(std::vector<GBTFrame>::iterator iFrame) short value2; mAdcMutex.lock(); for (short iHalfSampa = 0; iHalfSampa < 5; ++iHalfSampa) { - if (mPositionForHalfSampa[iHalfSampa] == -1) + if (mPositionForHalfSampa[iHalfSampa] == -1) { continue; - if (mPositionForHalfSampa[iHalfSampa + 5] == -1) + } + if (mPositionForHalfSampa[iHalfSampa + 5] == -1) { continue; + } switch (mPositionForHalfSampa[iHalfSampa]) { case 0: @@ -477,8 +483,9 @@ bool GBTFrameContainer::getData(std::vector<Digit>& container) } mAdcMutex.unlock(); - if (!dataAvailable) + if (!dataAvailable) { return dataAvailable; + } const Mapper& mapper = Mapper::instance(); int iTimeBin = mTimebin; @@ -508,8 +515,9 @@ bool GBTFrameContainer::getData(std::vector<Digit>& container) } } - if (dataAvailable) + if (dataAvailable) { ++mTimebin; + } return dataAvailable; } @@ -531,8 +539,9 @@ bool GBTFrameContainer::getData(std::vector<HalfSAMPAData>& container) } mAdcMutex.unlock(); - if (!dataAvailable) + if (!dataAvailable) { return dataAvailable; + } // if (container.size() != 5) { //// LOG(INFO) << "Container had the wrong size, set it to 5"; diff --git a/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx b/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx index 67537a7d4b34f..a11156a2e0d05 100644 --- a/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx +++ b/Detectors/TPC/reconstruction/src/HardwareClusterDecoder.cxx @@ -37,8 +37,9 @@ int HardwareClusterDecoder::decodeClusters(std::vector<std::pair<const ClusterHa const std::vector<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>>* inMCLabels, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* outMCLabels) { - if (mIntegrator == nullptr) + if (mIntegrator == nullptr) { mIntegrator.reset(new DigitalCurrentClusterIntegrator); + } // MCLabelContainer does only allow appending new labels, so we need to write to separate // containers per {sector,padrow} and merge at the end; std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>> outMCLabelContainers; @@ -95,8 +96,9 @@ int HardwareClusterDecoder::decodeClusters(std::vector<std::pair<const ClusterHa } } else { //Count how many output buffers we need (and how large they are below) - if (nCls == 0) + if (nCls == 0) { numberOfOutputContainers++; + } } nCls++; nTotalClusters++; diff --git a/Detectors/TPC/reconstruction/src/HwClusterer.cxx b/Detectors/TPC/reconstruction/src/HwClusterer.cxx index 15da2996b7e02..f7016bf40ea45 100644 --- a/Detectors/TPC/reconstruction/src/HwClusterer.cxx +++ b/Detectors/TPC/reconstruction/src/HwClusterer.cxx @@ -132,11 +132,13 @@ void HwClusterer::init() void HwClusterer::process(gsl::span<o2::tpc::Digit const> const& digits, ConstMCLabelContainerView const& mcDigitTruth, bool clearContainerFirst) { if (clearContainerFirst) { - if (mClusterArray) + if (mClusterArray) { mClusterArray->clear(); + } - if (mClusterMcLabelArray) + if (mClusterMcLabelArray) { mClusterMcLabelArray->clear(); + } mClusterCounter = 0; } @@ -585,10 +587,12 @@ void HwClusterer::hwClusterProcessor(const Vc::uint_m peakMask, unsigned qMaxInd } selectionMask = peakMask; - if (mRejectSinglePadClusters) + if (mRejectSinglePadClusters) { selectionMask &= !(sigmaPad2 == 0); - if (mRejectSingleTimeClusters) + } + if (mRejectSingleTimeClusters) { selectionMask &= !(sigmaTime2 == 0); + } ClusterHardware tmpCluster; for (int i = 0; i < Vc::uint_v::Size; ++i) { @@ -720,8 +724,9 @@ void HwClusterer::writeOutputWithTimeOffset(int timeOffset) { // Check in which regions cluster were found for (unsigned int region = 0; region < 10; ++region) { - if (mTmpClusterArray[region]->size() == 0) + if (mTmpClusterArray[region]->size() == 0) { continue; + } if (mClusterArray) { // Create new container @@ -762,8 +767,9 @@ void HwClusterer::writeOutputWithTimeOffset(int timeOffset) //______________________________________________________________________________ void HwClusterer::findPeaksForTime(int timebin) { - if (timebin < 0) + if (timebin < 0) { return; + } const unsigned timeBinWrapped = mapTimeInRange(timebin); for (unsigned short row = 0; row < mNumRowSets; ++row) { @@ -780,8 +786,9 @@ void HwClusterer::findPeaksForTime(int timebin) //______________________________________________________________________________ void HwClusterer::computeClusterForTime(int timebin) { - if (timebin < 0) + if (timebin < 0) { return; + } const unsigned timeBinWrapped = mapTimeInRange(timebin); if (mRejectLaterTimebin) { @@ -798,8 +805,9 @@ void HwClusterer::computeClusterForTime(int timebin) const auto peakMask = ((mDataBuffer[row][qMaxIndex] >> 27) == 0x1F) & // True if current pad is peak AND (getFpOfADC(mDataBuffer[row][qMaxIndex]) > getFpOfADC(mDataBuffer[row][qMaxPreviousIndex]) | // previous has smaller charge !((mDataBuffer[row][qMaxPreviousIndex] >> 27) == 0x1F)); // or previous one was not a peak - if (peakMask.isEmpty()) + if (peakMask.isEmpty()) { continue; + } hwClusterProcessor(peakMask, qMaxIndex, pad, timebin, row); } @@ -812,8 +820,9 @@ void HwClusterer::computeClusterForTime(int timebin) const unsigned qMaxIndex = padOffset + pad; const auto peakMask = ((mDataBuffer[row][qMaxIndex] >> 27) == 0x1F); - if (peakMask.isEmpty()) + if (peakMask.isEmpty()) { continue; + } hwClusterProcessor(peakMask, qMaxIndex, pad, timebin, row); } @@ -840,8 +849,9 @@ void HwClusterer::finishFrame(bool clear) writeOutputWithTimeOffset(mLastHB * 447); if (clear) { - for (int i = 0; i < mTimebinsInBuffer; ++i) + for (int i = 0; i < mTimebinsInBuffer; ++i) { clearBuffer(i); + } } } @@ -866,8 +876,9 @@ void HwClusterer::updateCluster( Vc::uint_v& qTot, Vc::int_v& pad, Vc::int_v& time, Vc::int_v& sigmaPad2, Vc::int_v& sigmaTime2, std::vector<std::unique_ptr<std::vector<std::pair<MCCompLabel, unsigned>>>>& mcLabels, const Vc::uint_m splitMask) { - if (selectionMask.isEmpty()) + if (selectionMask.isEmpty()) { return; + } const int mappedTime = mapTimeInRange(centerTime + dt); const int index = mappedTime * mPadsPerRowSet[row] + centerPad + dp; diff --git a/Detectors/TPC/reconstruction/src/RawReader.cxx b/Detectors/TPC/reconstruction/src/RawReader.cxx index 450739357f499..5e0aeb6994314 100644 --- a/Detectors/TPC/reconstruction/src/RawReader.cxx +++ b/Detectors/TPC/reconstruction/src/RawReader.cxx @@ -105,14 +105,18 @@ bool RawReader::addInputFile(std::string infile) bool RawReader::addInputFile(int region, int link, int sampaVersion, std::string path, int run) { - if (mRun == -1) + if (mRun == -1) { mRun = run; - if (mRegion == -1) + } + if (mRegion == -1) { mRegion = region; - if (mLink == -1) + } + if (mLink == -1) { mLink = link; - if (mSampaVersion == -1) + } + if (mSampaVersion == -1) { mSampaVersion = sampaVersion; + } if (run != mRun) { LOG(DEBUG) << "Run of RawReader is " << mRun << " and not " << run; @@ -198,8 +202,9 @@ bool RawReader::loadEvent(int64_t event) auto ev = mEvents.find(event); - if (ev == mEvents.end()) + if (ev == mEvents.end()) { return false; + } mLastEvent = event; for (auto& eventInfo : *(ev->second)) { @@ -207,27 +212,31 @@ bool RawReader::loadEvent(int64_t event) case 1: // RAW GBT frames { LOG(DEBUG) << "Data of readout mode 1 (RAW GBT frames)"; - if (!decodeRawGBTFrames(eventInfo)) + if (!decodeRawGBTFrames(eventInfo)) { return false; + } break; } case 2: // Decoded data { LOG(DEBUG) << "Data of readout mode 2 (decoded data)"; - if (!decodePreprocessedData(eventInfo)) + if (!decodePreprocessedData(eventInfo)) { return false; + } break; } case 3: // both, RAW GBT frames and decoded data { if (mUseRawInMode3) { LOG(DEBUG) << "Data of readout mode 3 (decoding RAW GBT frames)"; - if (!decodeRawGBTFrames(eventInfo)) + if (!decodeRawGBTFrames(eventInfo)) { return false; + } } else { LOG(DEBUG) << "Data of readout mode 3 (using decoded data)"; - if (!decodePreprocessedData(eventInfo)) + if (!decodePreprocessedData(eventInfo)) { return false; + } } break; } @@ -312,8 +321,9 @@ bool RawReader::decodePreprocessedData(EventInfo eventInfo) if (ids[j] == 0x8) { writeValue[j] = true; // header TS is one before first word -> +1 - if (mTimestampOfFirstData[j] == 0) + if (mTimestampOfFirstData[j] == 0) { mTimestampOfFirstData[j] = eventInfo.header.timeStamp() + 1 + i / indexStep; + } } } @@ -398,8 +408,9 @@ bool RawReader::decodeRawGBTFrames(EventInfo eventInfo) LOG(DEBUG) << "Start index for Event " << eventInfo.header.eventCount() << " is " << i_start; GBTFrame frame; - if (eventInfo.header.eventCount() > 0) + if (eventInfo.header.eventCount() > 0) { frame.setData(words[i_start - indexStep], words[i_start - indexStep + 1], words[i_start - indexStep + 2], words[i_start - indexStep + 3]); + } GBTFrame lastFrame; for (long i = i_start; i < nWords; i = i + indexStep) { @@ -408,16 +419,21 @@ bool RawReader::decodeRawGBTFrames(EventInfo eventInfo) lastFrame = frame; frame.setData(words[i], words[i + 1], words[i + 2], words[i + 3]); - if (syncMon[0].addSequence(frame.getHalfWord(0, 0, 0), frame.getHalfWord(0, 1, 0), frame.getHalfWord(0, 2, 0), frame.getHalfWord(0, 3, 0))) + if (syncMon[0].addSequence(frame.getHalfWord(0, 0, 0), frame.getHalfWord(0, 1, 0), frame.getHalfWord(0, 2, 0), frame.getHalfWord(0, 3, 0))) { mSyncPos[0] = syncMon[0].getPosition(); - if (syncMon[1].addSequence(frame.getHalfWord(0, 0, 1), frame.getHalfWord(0, 1, 1), frame.getHalfWord(0, 2, 1), frame.getHalfWord(0, 3, 1))) + } + if (syncMon[1].addSequence(frame.getHalfWord(0, 0, 1), frame.getHalfWord(0, 1, 1), frame.getHalfWord(0, 2, 1), frame.getHalfWord(0, 3, 1))) { mSyncPos[1] = syncMon[1].getPosition(); - if (syncMon[2].addSequence(frame.getHalfWord(1, 0, 0), frame.getHalfWord(1, 1, 0), frame.getHalfWord(1, 2, 0), frame.getHalfWord(1, 3, 0))) + } + if (syncMon[2].addSequence(frame.getHalfWord(1, 0, 0), frame.getHalfWord(1, 1, 0), frame.getHalfWord(1, 2, 0), frame.getHalfWord(1, 3, 0))) { mSyncPos[2] = syncMon[2].getPosition(); - if (syncMon[3].addSequence(frame.getHalfWord(1, 0, 1), frame.getHalfWord(1, 1, 1), frame.getHalfWord(1, 2, 1), frame.getHalfWord(1, 3, 1))) + } + if (syncMon[3].addSequence(frame.getHalfWord(1, 0, 1), frame.getHalfWord(1, 1, 1), frame.getHalfWord(1, 2, 1), frame.getHalfWord(1, 3, 1))) { mSyncPos[3] = syncMon[3].getPosition(); - if (syncMon[4].addSequence(frame.getHalfWord(2, 0), frame.getHalfWord(2, 1), frame.getHalfWord(2, 2), frame.getHalfWord(2, 3))) + } + if (syncMon[4].addSequence(frame.getHalfWord(2, 0), frame.getHalfWord(2, 1), frame.getHalfWord(2, 2), frame.getHalfWord(2, 3))) { mSyncPos[4] = syncMon[4].getPosition(); + } if (mCheckAdcClock) { @@ -425,12 +441,15 @@ bool RawReader::decodeRawGBTFrames(EventInfo eventInfo) bool adcCheckErr1 = adcClockMon[1].addSequence(frame.getAdcClock(1)); bool adcCheckErr2 = adcClockMon[2].addSequence(frame.getAdcClock(2)); - if (mSyncPos[0] >= 0) + if (mSyncPos[0] >= 0) { adcClockFound[0] = adcClockFound[0] | (!adcCheckErr0); - if (mSyncPos[2] >= 0) + } + if (mSyncPos[2] >= 0) { adcClockFound[1] = adcClockFound[1] | (!adcCheckErr1); - if (mSyncPos[4] >= 0) + } + if (mSyncPos[4] >= 0) { adcClockFound[2] = adcClockFound[2] | (!adcCheckErr2); + } if (adcClockFound[0] & adcCheckErr0) { adcClockFound[0] = false; LOG(DEBUG) << "ADC clock error of SAMPA " << ((mRegion % 2) ? 3 : 0) << " in frame [" << i / indexStep << "]"; diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index e3f3e9414cdfe..91db830c8b619 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -199,8 +199,9 @@ void RawReaderCRUEventSync::streamTo(std::ostream& output) const //============================================================================== int RawReaderCRU::scanFile() { - if (mFileIsScanned) + if (mFileIsScanned) { return 0; + } // std::vector<PacketDescriptor> mPacketDescriptorMap; //const uint64_t RDH_HEADERWORD0 = 0x1ea04003; @@ -210,8 +211,9 @@ int RawReaderCRU::scanFile() std::ifstream& file = mFileHandle; if (!file.is_open()) { file.open(mInputFileName, std::ifstream::binary); - if (!file.good()) + if (!file.good()) { throw std::runtime_error("Unable to open or access file " + mInputFileName); + } } // get length of file in bytes @@ -398,8 +400,9 @@ void RawReaderCRU::findSyncPositions() std::ifstream& file = mFileHandle; if (!file.is_open()) { file.open(mInputFileName, std::ifstream::binary); - if (!file.good()) + if (!file.good()) { throw std::runtime_error("Unable to open or access file " + mInputFileName); + } } // loop over the MaxNumberOfLinks potential links in the data @@ -460,8 +463,9 @@ int RawReaderCRU::processPacket(GBTFrame& gFrame, uint32_t startPos, uint32_t si std::ifstream& file = mFileHandle; if (!file.is_open()) { file.open(mInputFileName, std::ifstream::binary); - if (!file.good()) + if (!file.good()) { throw std::runtime_error("Unable to open or access file " + mInputFileName); + } } // jump to the start position of the packet @@ -705,8 +709,9 @@ void RawReaderCRU::collectGBTData(std::vector<o2::byte>& data) std::ifstream& file = mFileHandle; if (!file.is_open()) { file.open(mInputFileName, std::ios::binary); - if (!file.good()) + if (!file.good()) { throw std::runtime_error("Unable to open or access file " + mInputFileName); + } } size_t presentDataPosition = 0; @@ -845,8 +850,9 @@ void ADCRawData::streamTo(std::ostream& output) const { const auto numTimeBins = std::min(getNumTimebins(), mNumTimeBins); for (int i = 0; i < numTimeBins * 16; i++) { - if (i % 16 == 0) + if (i % 16 == 0) { output << std::setw(4) << std::to_string(i / 16) << " : "; + } output << std::setw(4) << mADCRaw[(mOutputStream)][i]; output << (((i + 1) % 16 == 0) ? "\n" : " "); }; diff --git a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx index 8b7294cbf3198..456c9513d5245 100644 --- a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx +++ b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx @@ -65,8 +65,9 @@ void TPCFastTransformHelperO2::init() for (int iRow = 0; iRow < mGeo.getNumberOfRows(); iRow++) { Sector sector = 0; int regionNumber = 0; - while (iRow >= mapper.getGlobalRowOffsetRegion(regionNumber) + mapper.getNumberOfRowsRegion(regionNumber)) + while (iRow >= mapper.getGlobalRowOffsetRegion(regionNumber) + mapper.getNumberOfRowsRegion(regionNumber)) { regionNumber++; + } const PadRegionInfo& region = mapper.getPadRegionInfo(regionNumber); diff --git a/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx b/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx index 9c70c60f4557f..ae088c52054b5 100644 --- a/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx +++ b/Detectors/TPC/reconstruction/test/testTPCFastTransform.cxx @@ -180,11 +180,13 @@ BOOST_AUTO_TEST_CASE(FastTransform_test_setSpaceChargeCorrection) } } } - if (statN > 0) + if (statN > 0) { statDiff /= statN; + } - if (statNFile > 0) + if (statNFile > 0) { statDiffFile /= statNFile; + } std::cout << "average difference in correction " << statDiff << " cm " << std::endl; BOOST_CHECK_MESSAGE(fabs(statDiff) < 1.e-3, "test of correction map failed, average difference " << statDiff << " cm is too large"); diff --git a/Detectors/TPC/simulation/include/TPCSimulation/ElectronTransport.h b/Detectors/TPC/simulation/include/TPCSimulation/ElectronTransport.h index 9df17f2db1035..19da546c95264 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/ElectronTransport.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/ElectronTransport.h @@ -87,8 +87,9 @@ inline bool ElectronTransport::isElectronAttachment(float driftTime) { if (mRandomFlat.getNextValue() < mGasParam->AttCoeff * mGasParam->OxygenCont * driftTime) { return true; /// electron is attached and lost - } else + } else { return false; /// not attached + } } inline float ElectronTransport::getDriftTime(float zPos, float signChange) const diff --git a/Detectors/TPC/simulation/include/TPCSimulation/SAMPAProcessing.h b/Detectors/TPC/simulation/include/TPCSimulation/SAMPAProcessing.h index fc1aaf402695d..1c1bc2c85b0ee 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/SAMPAProcessing.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/SAMPAProcessing.h @@ -183,8 +183,9 @@ inline float SAMPAProcessing::makeSignal(float ADCcounts, const int sector, cons inline float SAMPAProcessing::getADCSaturation(const float signal) const { const float adcSaturation = mEleParam->ADCsaturation; - if (signal > adcSaturation - 1) + if (signal > adcSaturation - 1) { return adcSaturation - 1; + } return signal; } diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index cf26551fc756f..41e08eb6d9f77 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -200,8 +200,9 @@ Bool_t Detector::ProcessHits(FairVolume* vol) //<< fMC->Edep() << ", Nelectrons: " //<< numberOfElectrons; - if (numberOfElectrons <= 0) // Could maybe be smaller than 0 due to the Gamma function + if (numberOfElectrons <= 0) { // Could maybe be smaller than 0 due to the Gamma function return kFALSE; + } // ADD HIT static thread_local int oldTrackId = trackID; @@ -418,8 +419,9 @@ void Detector::CreateMaterials() Int_t cnt = 0; for (Int_t i = 0; i < 6; i++) { if (comp[i]) { - if (cnt) + if (cnt) { gname += "-"; + } gname += names[i]; cnt++; } @@ -3086,12 +3088,13 @@ Double_t Detector::Gamma(Double_t k) static thread_local Double_t b1 = 0; static thread_local Double_t b2 = 0; if (k > 0) { - if (k < 0.4) + if (k < 0.4) { n = 1. / k; - else if (k >= 0.4 && k < 4) + } else if (k >= 0.4 && k < 4) { n = 1. / k + (k - 0.4) / k / 3.6; - else if (k >= 4.) + } else if (k >= 4.) { n = 1. / TMath::Sqrt(k); + } b1 = k - 1. / n; b2 = k + 1. / n; c1 = (k < 0.4) ? 0 : b1 * (TMath::Log(b1) - 1.) / 2.; @@ -3105,11 +3108,13 @@ Double_t Detector::Gamma(Double_t k) Double_t w1 = c1 + TMath::Log(nu1); Double_t w2 = c2 + TMath::Log(nu2); y = n * (b1 * w2 - b2 * w1); - if (y < 0) + if (y < 0) { continue; + } x = n * (w2 - w1); - if (TMath::Log(y) >= x) + if (TMath::Log(y) >= x) { break; + } } return TMath::Exp(x); } diff --git a/Detectors/TPC/simulation/src/GEMAmplification.cxx b/Detectors/TPC/simulation/src/GEMAmplification.cxx index b7b6b58ba9240..78da03d0cf495 100644 --- a/Detectors/TPC/simulation/src/GEMAmplification.cxx +++ b/Detectors/TPC/simulation/src/GEMAmplification.cxx @@ -98,8 +98,9 @@ GEMAmplification::GEMAmplification() } delete polyaDistribution; - if (outfile) + if (outfile) { outfile->Close(); + } watch.Stop(); LOG(INFO) << "TPC: GEM setup (polya) took " << watch.CpuTime(); } diff --git a/Detectors/TPC/simulation/src/PadResponse.cxx b/Detectors/TPC/simulation/src/PadResponse.cxx index 5a24f955356c8..ebcc2b3fb722a 100644 --- a/Detectors/TPC/simulation/src/PadResponse.cxx +++ b/Detectors/TPC/simulation/src/PadResponse.cxx @@ -43,8 +43,9 @@ bool PadResponse::importPRF(std::string file, std::unique_ptr<TGraph2D>& grPRF) { std::string inputDir; const char* aliceO2env = std::getenv("O2_ROOT"); - if (aliceO2env) + if (aliceO2env) { inputDir = aliceO2env; + } inputDir += "/share/Detectors/TPC/files/"; float x, y, normalizedPadResponse; diff --git a/Detectors/TPC/workflow/src/LinkZSToDigitsSpec.cxx b/Detectors/TPC/workflow/src/LinkZSToDigitsSpec.cxx index 4125822558658..cfb3905b3b3c1 100644 --- a/Detectors/TPC/workflow/src/LinkZSToDigitsSpec.cxx +++ b/Detectors/TPC/workflow/src/LinkZSToDigitsSpec.cxx @@ -69,10 +69,12 @@ o2::framework::DataProcessorSpec getLinkZSToDigitsSpec(int channel, const std::s // sort digits for (auto& digits : digitsAll) { std::sort(digits.begin(), digits.end(), [](const auto& a, const auto& b) { - if (a.getTimeStamp() < b.getTimeStamp()) + if (a.getTimeStamp() < b.getTimeStamp()) { return true; - if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) + } + if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) { return true; + } return false; }); } diff --git a/Detectors/TPC/workflow/src/ZSSpec.cxx b/Detectors/TPC/workflow/src/ZSSpec.cxx index 4ad3dd477b543..91db1b93f5dbd 100644 --- a/Detectors/TPC/workflow/src/ZSSpec.cxx +++ b/Detectors/TPC/workflow/src/ZSSpec.cxx @@ -241,10 +241,12 @@ DataProcessorSpec getZStoDigitsSpec(std::vector<int> const& inputIds) // sort digits for (auto& digits : outDigits) { std::sort(digits.begin(), digits.end(), [](const auto& a, const auto& b) { - if (a.getTimeStamp() < b.getTimeStamp()) + if (a.getTimeStamp() < b.getTimeStamp()) { return true; - if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) + } + if ((a.getTimeStamp() == b.getTimeStamp()) && (a.getRow() < b.getRow())) { return true; + } return false; }); } From c3e00da2bc0f802bfbf75e3a9dfcca1e6edffbd0 Mon Sep 17 00:00:00 2001 From: Paul Buehler <paul.buehler@oeaw.ac.at> Date: Thu, 29 Oct 2020 11:04:49 +0100 Subject: [PATCH 1201/1751] Make sure that the message with the time frame number arrives at the writer before it is needed to save the related tables to file --- .../Framework/CompletionPolicyHelpers.h | 2 + Framework/Core/src/CompletionPolicy.cxx | 2 +- .../Core/src/CompletionPolicyHelpers.cxx | 46 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/CompletionPolicyHelpers.h b/Framework/Core/include/Framework/CompletionPolicyHelpers.h index 9a3bc32f25664..ea892feb1852d 100644 --- a/Framework/Core/include/Framework/CompletionPolicyHelpers.h +++ b/Framework/Core/include/Framework/CompletionPolicyHelpers.h @@ -50,6 +50,8 @@ struct CompletionPolicyHelpers { } /// Attach a given @a op to a device matching @name. static CompletionPolicy defineByName(std::string const& name, CompletionPolicy::CompletionOp op); + /// Attach a given @a op to a device matching @name, check message of origin @origin is available + static CompletionPolicy defineByNameOrigin(std::string const& name, std::string const& origin, CompletionPolicy::CompletionOp op); /// Get a specific header from the input template <typename T, typename U> static auto getHeader(U const& input) diff --git a/Framework/Core/src/CompletionPolicy.cxx b/Framework/Core/src/CompletionPolicy.cxx index f4cc5b26861c8..06e1ef159fe3b 100644 --- a/Framework/Core/src/CompletionPolicy.cxx +++ b/Framework/Core/src/CompletionPolicy.cxx @@ -23,7 +23,7 @@ std::vector<CompletionPolicy> CompletionPolicy::createDefaultPolicies() { return { - CompletionPolicyHelpers::defineByName("internal-dpl-aod-writer", CompletionOp::Consume), + CompletionPolicyHelpers::defineByNameOrigin("internal-dpl-aod-writer", "TFN", CompletionOp::Consume), CompletionPolicyHelpers::consumeWhenAll()}; } diff --git a/Framework/Core/src/CompletionPolicyHelpers.cxx b/Framework/Core/src/CompletionPolicyHelpers.cxx index b481823f0ba1f..ab19536a93843 100644 --- a/Framework/Core/src/CompletionPolicyHelpers.cxx +++ b/Framework/Core/src/CompletionPolicyHelpers.cxx @@ -12,6 +12,7 @@ #include "Framework/CompletionPolicy.h" #include "Framework/DeviceSpec.h" #include "Framework/CompilerBuiltins.h" +#include "Framework/Logger.h" #include <cassert> #include <regex> @@ -21,6 +22,51 @@ namespace o2 namespace framework { +CompletionPolicy CompletionPolicyHelpers::defineByNameOrigin(std::string const& name, std::string const& origin, CompletionPolicy::CompletionOp op) +{ + auto matcher = [name](DeviceSpec const& device) -> bool { + return std::regex_match(device.name.begin(), device.name.end(), std::regex(name)); + }; + + auto originReceived = std::make_shared<std::vector<uint64_t>>(); + + auto callback = [originReceived, origin, op](CompletionPolicy::InputSet inputRefs) -> CompletionPolicy::CompletionOp { + // update list of the start times of inputs with origin @origin + for (auto& ref : inputRefs) { + if (ref.header != nullptr) { + auto header = CompletionPolicyHelpers::getHeader<o2::header::DataHeader>(ref); + if (header->dataOrigin.str == origin) { + auto startTime = DataRefUtils::getHeader<DataProcessingHeader*>(ref)->startTime; + auto it = std::find(originReceived->begin(), originReceived->end(), startTime); + if (it == originReceived->end()) { + originReceived->emplace_back(startTime); + } + } + } + } + + // find out if all inputs which are not of origin @origin have a corresponding entry in originReceived + // if one is missing then we have to wait + for (auto& ref : inputRefs) { + if (ref.header != nullptr) { + auto header = CompletionPolicyHelpers::getHeader<o2::header::DataHeader>(ref); + if (header->dataOrigin.str != origin) { + auto startTime = DataRefUtils::getHeader<DataProcessingHeader*>(ref)->startTime; + auto it = std::find(originReceived->begin(), originReceived->end(), startTime); + if (it == originReceived->end()) { + LOGP(INFO, "Have to wait until message of origin {} with startTime {} has arrived.", origin, startTime); + return CompletionPolicy::CompletionOp::Wait; + } + } + } + } + return op; + }; + return CompletionPolicy{"wait-origin", matcher, callback}; + + O2_BUILTIN_UNREACHABLE(); +} + CompletionPolicy CompletionPolicyHelpers::defineByName(std::string const& name, CompletionPolicy::CompletionOp op) { auto matcher = [name](DeviceSpec const& device) -> bool { From 4c4a664e62d37aaa7ebba52a47b117918e3db42e Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 22 Oct 2020 17:01:16 +0200 Subject: [PATCH 1202/1751] Default TPC compression track model implemented - Currently reproduces merger track model performance (entropy) - Has the same speed as the slice tracker track model TODO - remove further steps to speed up compression keeping the entropy as low as possible --- .../GPUTPCCompressionTrackModel.cxx | 937 ++++++++++++++++++ .../GPUTPCCompressionTrackModel.h | 83 +- 2 files changed, 1018 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx index 82f7eb6da8f7d..4f6bc8cf3122d 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx @@ -112,4 +112,941 @@ GPUd() int GPUTPCCompressionTrackModel::Mirror() #else // Default internal track model for compression +GPUd() void GPUTPCCompressionTrackModel::Init(float x, float y, float z, float alpha, unsigned char qPt, const GPUParam& GPUrestrict() param) +{ + // initialize track model + mX = x; + mAlpha = alpha; + mCosAlpha = CAMath::Cos(alpha); + mSinAlpha = CAMath::Sin(alpha); + mP[0] = y; + mP[1] = z; + mP[2] = 0.f; + mP[3] = 0.f; + mP[4] = (qPt - 127.f) * (20.f / 127.f); + resetCovariance(); + mNDF = -5; + mField = ¶m.polynomialField; + float pti = CAMath::Abs(mP[4]); + if (pti < 1.e-4f) { + pti = 1.e-4f; // set 10.000 GeV momentum for straight track + } + mTrk.x = x; + mTrk.y = y; + mTrk.z = z; + mTrk.q = (mP[4] >= 0) ? 1.f : -1.f; + mTrk.pt = 1.f / pti; + mTrk.p = mTrk.pt; + mTrk.px = mTrk.pt; + mTrk.py = 0.f; + mTrk.pz = 0.f; + mTrk.qpt = mTrk.q * pti; + calculateMaterialCorrection(); +} + +GPUd() int GPUTPCCompressionTrackModel::Propagate(float x, float alpha) +{ + // constrain sin(phi) + if (mP[2] > MaxSinPhi) { + mP[2] = MaxSinPhi; + } else if (mP[2] < -MaxSinPhi) { + mP[2] = -MaxSinPhi; + } + // propagate track parameters to specified x + if (CAMath::Abs(alpha - mAlpha) > 1.e-4) { + if (rotateToAlpha(alpha) != 0) { + return -2; + } + } + if (CAMath::Abs(x - mX) < 1.e-7f) { + mX = x; + return 0; + } + + float Bz = getBz(mTrk.x, mTrk.y, mTrk.z); + + // propagate mTrk to t0e + PhysicalTrackModel t0e(mTrk); + float dLp = 0; + if (CAMath::Abs(x - t0e.x) < 1.e-8f) { + return 0; + } + if (propagateToXBzLightNoUpdate(t0e, x, Bz, dLp)) { + return 1; + } + updatePhysicalTrackValues(t0e); + if (CAMath::Abs(t0e.sinphi) >= MaxSinPhi) { + return -3; + } + return followLinearization(t0e, Bz, dLp); +} + +GPUd() int GPUTPCCompressionTrackModel::Filter(float y, float z, int iRow) +{ + // apply kalman filter update with measurement y/z + float err2Y, err2Z; + getClusterRMS2(iRow, z, mTrk.sinphi, mTrk.dzds, err2Y, err2Z); + if (mNDF == -5) { + // first measurement: no need to filter, as the result is known in advance. so just set it + // ignore offline statistical errors for now (as is also done by default) + mP[0] = y; + mP[1] = z; + mC[0] = err2Y; + mC[2] = err2Z; + mNDF = -3; + return 0; + } + + // constrain sin(phi) + if (mP[2] > MaxSinPhi) { + mP[2] = MaxSinPhi; + } else if (mP[2] < -MaxSinPhi) { + mP[2] = -MaxSinPhi; + } + + const float d00 = mC[0], d01 = mC[1], d02 = mC[3], d03 = mC[6], d04 = mC[10]; + const float d10 = mC[1], d11 = mC[2], d12 = mC[4], d13 = mC[7], d14 = mC[11]; + + const float z0 = y - mP[0]; + const float z1 = z - mP[1]; + float w0, w1, w2; + if (mNDF <= 0) { + w0 = 1.f / (err2Y + d00); + w1 = 0; + w2 = 1.f / (err2Z + d11); + } else { + w0 = d11 + err2Z, w1 = d10, w2 = d00 + err2Y; + { // Invert symmetric matrix + float det = w0 * w2 - w1 * w1; + if (CAMath::Abs(det) < 1.e-10f) { + return -1; + } + det = 1.f / det; + w0 = w0 * det; + w1 = -w1 * det; + w2 = w2 * det; + } + } + mNDF += 2; + + if (mNDF <= 0) { + const float k00 = d00 * w0; + const float k20 = d02 * w0; + const float k40 = d04 * w0; + const float k11 = d11 * w2; + const float k31 = d13 * w2; + mP[0] += k00 * z0; + mP[1] += k11 * z1; + mP[2] += k20 * z0; + mP[3] += k31 * z1; + mP[4] += k40 * z0; + + mC[0] -= k00 * d00; + mC[2] -= k11 * d11; + mC[3] -= k20 * d00; + mC[5] -= k20 * d02; + mC[7] -= k31 * d11; + mC[9] -= k31 * d13; + mC[10] -= k00 * d04; + mC[12] -= k40 * d02; + mC[14] -= k40 * d04; + } else { + const float k00 = d00 * w0 + d01 * w1; + const float k01 = d00 * w1 + d10 * w2; + const float k10 = d01 * w0 + d11 * w1; + const float k11 = d01 * w1 + d11 * w2; + const float k20 = d02 * w0 + d12 * w1; + const float k21 = d02 * w1 + d12 * w2; + const float k30 = d03 * w0 + d13 * w1; + const float k31 = d03 * w1 + d13 * w2; + const float k40 = d04 * w0 + d14 * w1; + const float k41 = d04 * w1 + d14 * w2; + + mP[0] += k00 * z0 + k01 * z1; + mP[1] += k10 * z0 + k11 * z1; + mP[2] += k20 * z0 + k21 * z1; + mP[3] += k30 * z0 + k31 * z1; + mP[4] += k40 * z0 + k41 * z1; + + mC[0] -= k00 * d00 + k01 * d10; + + mC[2] -= k10 * d01 + k11 * d11; + + mC[3] -= k20 * d00 + k21 * d10; + mC[5] -= k20 * d02 + k21 * d12; + + mC[7] -= k30 * d01 + k31 * d11; + mC[9] -= k30 * d03 + k31 * d13; + + mC[10] -= k40 * d00 + k41 * d10; + mC[12] -= k40 * d02 + k41 * d12; + mC[14] -= k40 * d04 + k41 * d14; + + mC[1] -= k10 * d00 + k11 * d10; + mC[4] -= k20 * d01 + k21 * d11; + mC[6] -= k30 * d00 + k31 * d10; + mC[8] -= k30 * d02 + k31 * d12; + mC[11] -= k40 * d01 + k41 * d11; + mC[13] -= k40 * d03 + k41 * d13; + } + return 0; +} + +GPUd() int GPUTPCCompressionTrackModel::Mirror() +{ + float Bz = getBz(mTrk.x, mTrk.y, mTrk.z); + if (CAMath::Abs(Bz) < 1.e-8f) { + Bz = 1.e-8f; + } + float dy = -2.f * mTrk.q * mTrk.px / Bz; + float dS; // path in XY + { + float chord = dy; // chord to the extrapolated point == |dy|*sign(x direction) + float sa = -mTrk.cosphi; // sin( half of the rotation angle ) == (chord/2) / radius + + // dS = (Pt/b)*2*arcsin( sa ) + // = (Pt/b)*2*sa*(1 + 1/6 sa^2 + 3/40 sa^4 + 5/112 sa^6 +... ) + // = chord*(1 + 1/6 sa^2 + 3/40 sa^4 + 5/112 sa^6 +... ) + + float sa2 = sa * sa; + const float k2 = 1.f / 6.f; + const float k4 = 3.f / 40.f; + // const float k6 = 5.f/112.f; + dS = chord + chord * sa2 * (k2 + k4 * sa2); + // dS = sqrtf(pt2)/b*2.*CAMath::ASin( sa ); + } + + if (mTrk.sinphi < 0.f) { + dS = -dS; + } + + mTrk.y = mTrk.y + 2.f * dy; // TODO check why dy is added TWICE to the track position + mTrk.z = mTrk.z + 2.f * mTrk.dzds * dS; + changeDirection(); + + // Energy Loss + + float dL = CAMath::Copysign(dS * mTrk.dlds, -1.f); // we are in flight direction + + float& mC40 = mC[10]; + float& mC41 = mC[11]; + float& mC42 = mC[12]; + float& mC43 = mC[13]; + float& mC44 = mC[14]; + + float dLmask = 0.f; + bool maskMS = (CAMath::Abs(dL) < mMaterial.DLMax); + if (maskMS) { + dLmask = dL; + } + float dLabs = CAMath::Abs(dLmask); + float corr = 1.f - mMaterial.EP2 * dLmask; + + float corrInv = 1.f / corr; + mTrk.px *= corrInv; + mTrk.py *= corrInv; + mTrk.pz *= corrInv; + mTrk.pt *= corrInv; + mTrk.p *= corrInv; + mTrk.qpt *= corr; + + mP[4] *= corr; + + mC40 *= corr; + mC41 *= corr; + mC42 *= corr; + mC43 *= corr; + mC44 = mC44 * corr * corr + dLabs * mMaterial.sigmadE2; + + return 0; +} + +GPUd() void GPUTPCCompressionTrackModel::getBxByBz(float cosAlpha, float sinAlpha, float x, float y, float z, float b[3]) const +{ + float xGlb = x * cosAlpha - y * sinAlpha; + float yGlb = x * sinAlpha + y * cosAlpha; + float bb[3]; + mField->GetField(xGlb, yGlb, z, bb); + // rotate field to local coordinates + b[0] = bb[0] * cosAlpha + bb[1] * sinAlpha; + b[1] = -bb[0] * sinAlpha + bb[1] * cosAlpha; + b[2] = bb[2]; +} + +GPUd() float GPUTPCCompressionTrackModel::getBz(float x, float y, float z) const +{ + float xGlb = x * mCosAlpha - y * mSinAlpha; + float yGlb = x * mSinAlpha + y * mCosAlpha; + return mField->GetFieldBz(xGlb, yGlb, z); +} + +GPUd() void GPUTPCCompressionTrackModel::updatePhysicalTrackValues(PhysicalTrackModel& trk) +{ + float px = trk.px; + if (CAMath::Abs(px) < 1.e-4f) { + px = CAMath::Copysign(1.e-4f, px); + } + + trk.pt = sqrt(px * px + trk.py * trk.py); + float pti = 1.f / trk.pt; + trk.p = sqrt(px * px + trk.py * trk.py + trk.pz * trk.pz); + trk.sinphi = trk.py * pti; + trk.cosphi = px * pti; + trk.secphi = trk.pt / px; + trk.dzds = trk.pz * pti; + trk.dlds = trk.p * pti; + trk.qpt = trk.q * pti; +} + +GPUd() void GPUTPCCompressionTrackModel::changeDirection() +{ + mTrk.py = -mTrk.py; + mTrk.pz = -mTrk.pz; + mTrk.q = -mTrk.q; + mTrk.sinphi = -mTrk.sinphi; + mTrk.dzds = -mTrk.dzds; + mTrk.qpt = -mTrk.qpt; + updatePhysicalTrackValues(mTrk); + + mC[3] = -mC[3]; + mC[4] = -mC[4]; + mC[6] = -mC[6]; + mC[7] = -mC[7]; + mC[10] = -mC[10]; + mC[11] = -mC[11]; +} + +GPUd() int GPUTPCCompressionTrackModel::rotateToAlpha(float newAlpha) +{ + // + // Rotate the track coordinate system in XY to the angle newAlpha + // return value is error code (0==no error) + // + + float newCosAlpha = CAMath::Cos(newAlpha); + float newSinAlpha = CAMath::Sin(newAlpha); + + float cc = newCosAlpha * mCosAlpha + newSinAlpha * mSinAlpha; // cos(newAlpha - mAlpha); + float ss = newSinAlpha * mCosAlpha - newCosAlpha * mSinAlpha; // sin(newAlpha - mAlpha); + + PhysicalTrackModel t0 = mTrk; + + float x0 = mTrk.x; + float y0 = mTrk.y; + float px0 = mTrk.px; + float py0 = mTrk.py; + + if (CAMath::Abs(mP[2]) >= MaxSinPhi || CAMath::Abs(px0) < (1 - MaxSinPhi)) { + return -1; + } + + // rotate t0 track + float px1 = px0 * cc + py0 * ss; + float py1 = -px0 * ss + py0 * cc; + + { + t0.x = x0 * cc + y0 * ss; + t0.y = -x0 * ss + y0 * cc; + t0.px = px1; + t0.py = py1; + updatePhysicalTrackValues(t0); + } + + if (CAMath::Abs(py1) > MaxSinPhi * mTrk.pt || CAMath::Abs(px1) < (1 - MaxSinPhi)) { + return -1; + } + + // calculate X of rotated track: + float trackX = x0 * cc + ss * mP[0]; + + // transport t0 to trackX + float B[3]; + getBxByBz(CAMath::Cos(newAlpha), CAMath::Sin(newAlpha), t0.x, t0.y, t0.z, B); + float dLp = 0; + if (propagateToXBxByBz(t0, trackX, B[0], B[1], B[2], dLp)) { + return -1; + } + + if (CAMath::Abs(t0.sinphi) >= MaxSinPhi) { + return -1; + } + + // now t0 is rotated and propagated, all checks are passed + + // Rotate track using mTrk for linearisation. After rotation X is not fixed, but has a covariance + + // Y Z Sin DzDs q/p + // Jacobian J0 = { { j0, 0, 0, 0, 0 }, // Y + // { 0, 1, 0, 0, 0 }, // Z + // { 0, 0, j1, 0, 0 }, // SinPhi + // { 0, 0, 0, 1, 0 }, // DzDs + // { 0, 0, 0, 0, 1 }, // q/p + // { j2, 0, 0, 0, 0 } }// X (rotated ) + + float j0 = cc; + float j1 = px1 / px0; + float j2 = ss; + // float dy = mT->Y() - y0; + // float ds = mT->SinPhi() - mTrk.SinPhi(); + + mX = trackX; // == x0*cc + ss*mP[0] == t0.x + j0*dy; + mP[0] = -x0 * ss + cc * mP[0]; //== t0.y + j0*dy; + // mP[2] = py1/pt0 + j1*ds; // == t0.sinphi + j1*ds; // use py1, since t0.sinphi can have different sign + mP[2] = -CAMath::Sqrt(1.f - mP[2] * mP[2]) * ss + mP[2] * cc; + + // Rotate cov. matrix Cr = J0 x C x J0T. Cr has one more row+column for X: + float* c = mC; + + float c15 = c[0] * j0 * j2; + float c16 = c[1] * j2; + float c17 = c[3] * j1 * j2; + float c18 = c[6] * j2; + float c19 = c[10] * j2; + float c20 = c[0] * j2 * j2; + + c[0] *= j0 * j0; + c[3] *= j0; + c[10] *= j0; + + c[3] *= j1; + c[5] *= j1 * j1; + c[12] *= j1; + + if (setDirectionAlongX(t0)) { // change direction if Px < 0 + mP[2] = -mP[2]; + mP[3] = -mP[3]; + mP[4] = -mP[4]; + c[3] = -c[3]; // covariances with SinPhi + c[4] = -c[4]; + c17 = -c17; + c[6] = -c[6]; // covariances with DzDs + c[7] = -c[7]; + c18 = -c18; + c[10] = -c[10]; // covariances with QPt + c[11] = -c[11]; + c19 = -c19; + } + + // Now fix the X coordinate: so to say, transport track T to fixed X = mX. + // only covariance changes. Use rotated and transported t0 for linearisation + float j3 = -t0.py / t0.px; + float j4 = -t0.pz / t0.px; + float j5 = t0.qpt * B[2]; + + // Y Z Sin DzDs q/p X + // Jacobian J1 = { { 1, 0, 0, 0, 0, j3 }, // Y + // { 0, 1, 0, 0, 0, j4 }, // Z + // { 0, 0, 1, 0, 0, j5 }, // SinPhi + // { 0, 0, 0, 1, 0, 0 }, // DzDs + // { 0, 0, 0, 0, 1, 0 } }; // q/p + + float h15 = c15 + c20 * j3; + float h16 = c16 + c20 * j4; + float h17 = c17 + c20 * j5; + + c[0] += j3 * (c15 + h15); + + c[2] += j4 * (c16 + h16); + + c[3] += c17 * j3 + h15 * j5; + c[5] += j5 * (c17 + h17); + + c[7] += c18 * j4; + // c[ 9] = c[ 9]; + + c[10] += c19 * j3; + c[12] += c19 * j5; + // c[14] = c[14]; + + mAlpha = newAlpha; + mCosAlpha = newCosAlpha; + mSinAlpha = newSinAlpha; + mTrk = t0; + + return 0; +} + +GPUd() int GPUTPCCompressionTrackModel::propagateToXBxByBz(PhysicalTrackModel& t, float x, float Bx, float By, float Bz, float& dLp) +{ + // + // transport the track to X=x in magnetic field B = ( Bx, By, Bz )[kG*0.000299792458] + // xyzPxPyPz as well as all the additional values will change. No need to call UpdateValues() afterwards. + // the method returns error code (0 == no error) + // + dLp = 0.f; + + // Rotate to the system where Bx=By=0. + + float bt = CAMath::Sqrt(Bz * Bz + By * By); + float bb = CAMath::Sqrt(Bx * Bx + By * By + Bz * Bz); + + float c1 = 1.f, s1 = 0.f; + float c2 = 1.f, s2 = 0.f; + + if (bt > 1.e-4f) { + c1 = Bz / bt; + s1 = By / bt; + c2 = bt / bb; + s2 = -Bx / bb; + } + + // rotation matrix: first around x, then around y' + // after the first rotation: Bx'==Bx, By'==0, Bz'==Bt, X'==X + // after the second rotation: Bx''==0, By''==0, Bz''==B, X'' axis is as close as possible to the original X + + // + // ( c2 0 s2 ) ( 1 0 0 ) + // R = ( 0 1 0 ) X ( 0 c1 -s1 ) + // (-s2 0 c2 ) ( 0 s1 c1 ) + // + + float R0[3] = {c2, s1 * s2, c1 * s2}; + float R1[3] = {0, c1, -s1}; + float R2[3] = {-s2, s1 * c2, c1 * c2}; + + // parameters and the extrapolation point in the rotated coordinate system + { + float lx = t.x, ly = t.y, lz = t.z, lpx = t.px, lpy = t.py, lpz = t.pz; + + t.x = R0[0] * lx + R0[1] * ly + R0[2] * lz; + t.y = R1[0] * lx + R1[1] * ly + R1[2] * lz; + t.z = R2[0] * lx + R2[1] * ly + R2[2] * lz; + + t.px = R0[0] * lpx + R0[1] * lpy + R0[2] * lpz; + t.py = R1[0] * lpx + R1[1] * lpy + R1[2] * lpz; + t.pz = R2[0] * lpx + R2[1] * lpy + R2[2] * lpz; + } + + float dx = x - mX; + float xe = t.x + dx; // propagate on same dx in rotated system + + // transport in rotated coordinate system to X''=xe: + + if (t.px < (1.f - MaxSinPhi)) { + t.px = 1.f - MaxSinPhi; + } + if (propagateToXBzLightNoUpdate(t, xe, bb, dLp) != 0) { + return -1; + } + + // rotate coordinate system back to the original R{-1}==R{T} + { + float lx = t.x, ly = t.y, lz = t.z, lpx = t.px, lpy = t.py, lpz = t.pz; + + t.x = R0[0] * lx + R1[0] * ly + R2[0] * lz; + t.y = R0[1] * lx + R1[1] * ly + R2[1] * lz; + t.z = R0[2] * lx + R1[2] * ly + R2[2] * lz; + + t.px = R0[0] * lpx + R1[0] * lpy + R2[0] * lpz; + t.py = R0[1] * lpx + R1[1] * lpy + R2[1] * lpz; + t.pz = R0[2] * lpx + R1[2] * lpy + R2[2] * lpz; + } + + // a small (hopefully) additional step to X=x. Perhaps it may be replaced by linear extrapolation. + + float ddLp = 0; + if (t.px < (1.f - MaxSinPhi)) { + t.px = 1.f - MaxSinPhi; + } + if (propagateToXBzLightNoUpdate(t, x, Bz, ddLp) != 0) { + return -1; + } + + dLp += ddLp; + + updatePhysicalTrackValues(t); + return 0; +} + +GPUd() int GPUTPCCompressionTrackModel::propagateToXBzLightNoUpdate(PhysicalTrackModel& t, float x, float Bz, float& dLp) +{ + // + // transport the track to X=x in magnetic field B = ( 0, 0, Bz[kG*0.000299792458] ) + // dLp is a return value == path length / track momentum [cm/(GeV/c)] + // the method returns error code (0 == no error) + // + // Additional values are not recalculated, UpdateValues() has to be called afterwards!! + // + float b = t.q * Bz; + float pt2 = t.px * t.px + t.py * t.py; + float dx = x - t.x; + float pye = t.py - dx * b; // extrapolated py + float pxe2 = pt2 - pye * pye; + + if (t.px < (1.f - MaxSinPhi) || pxe2 < (1.f - MaxSinPhi) * (1.f - MaxSinPhi)) { + return -1; // can not transport to x=x + } + float pxe = CAMath::Sqrt(pxe2); // extrapolated px + float pti = 1.f / CAMath::Sqrt(pt2); + + float ty = (t.py + pye) / (t.px + pxe); + float dy = dx * ty; + float dS; // path in XY + { + float chord = dx * CAMath::Sqrt(1.f + ty * ty); // chord to the extrapolated point == sqrt(dx^2+dy^2)*sign(dx) + float sa = 0.5f * chord * b * pti; // sin( half of the rotation angle ) == (chord/2) / radius + + // dS = (Pt/b)*2*arcsin( sa ) + // = (Pt/b)*2*sa*(1 + 1/6 sa^2 + 3/40 sa^4 + 5/112 sa^6 +... ) + // = chord*(1 + 1/6 sa^2 + 3/40 sa^4 + 5/112 sa^6 +... ) + + float sa2 = sa * sa; + const float k2 = 1.f / 6.f; + const float k4 = 3.f / 40.f; + // const float k6 = 5.f/112.f; + dS = chord + chord * sa2 * (k2 + k4 * sa2); + // dS = sqrt(pt2)/b*2.*CAMath::ASin( sa ); + } + + dLp = pti * dS; // path in XYZ / p == path in XY / pt + + float dz = t.pz * dLp; + + t.x = x; + t.y += dy; + t.z += dz; + t.px = pxe; + t.py = pye; + return 0; +} + +GPUd() bool GPUTPCCompressionTrackModel::setDirectionAlongX(PhysicalTrackModel& t) +{ + // + // set direction of movenment collinear to X axis + // return value is true when direction has been changed + // + if (t.px >= 0) { + return 0; + } + + t.px = -t.px; + t.py = -t.py; + t.pz = -t.pz; + t.q = -t.q; + updatePhysicalTrackValues(t); + return 1; +} + +GPUd() int GPUTPCCompressionTrackModel::followLinearization(const PhysicalTrackModel& t0e, float Bz, float dLp) +{ + // t0e is alrerady extrapolated t0 + + // propagate track and cov matrix with derivatives for (0,0,Bz) field + + float dS = dLp * t0e.pt; + float dL = CAMath::Abs(dLp * t0e.p); + + dL = -dL; // we are always in flight direction + + float ey = mTrk.sinphi; + float ex = mTrk.cosphi; + float exi = mTrk.secphi; + float ey1 = t0e.sinphi; + float ex1 = t0e.cosphi; + float ex1i = t0e.secphi; + + float k = -mTrk.qpt * Bz; + float dx = t0e.x - mTrk.x; + float kdx = k * dx; + float cc = ex + ex1; + float cci = 1.f / cc; + + float dxcci = dx * cci; + float hh = dxcci * ex1i * (1.f + ex * ex1 + ey * ey1); + + float j02 = exi * hh; + float j04 = -Bz * dxcci * hh; + float j13 = dS; + float j24 = -dx * Bz; + + float* p = mP; + + float d0 = p[0] - mTrk.y; + float d1 = p[1] - mTrk.z; + float d2 = p[2] - mTrk.sinphi; + float d3 = p[3] - mTrk.dzds; + float d4 = p[4] - mTrk.qpt; + + float newSinPhi = ey1 + d2 + j24 * d4; + if (mNDF >= 15 && CAMath::Abs(newSinPhi) > MaxSinPhi) { + return -4; + } + + mTrk = t0e; + mX = t0e.x; + p[0] = t0e.y + d0 + j02 * d2 + j04 * d4; + p[1] = t0e.z + d1 + j13 * d3; + p[2] = newSinPhi; + p[3] = t0e.dzds + d3; + p[4] = t0e.qpt + d4; + + float* c = mC; + + float c20 = c[3]; + float c21 = c[4]; + float c22 = c[5]; + + float c30 = c[6]; + float c31 = c[7]; + float c32 = c[8]; + float c33 = c[9]; + + float c40 = c[10]; + float c41 = c[11]; + float c42 = c[12]; + float c43 = c[13]; + float c44 = c[14]; + + if (mNDF <= 0) { + float c20ph04c42 = c20 + j04 * c42; + float j02c22 = j02 * c22; + float j04c44 = j04 * c44; + + float n6 = c30 + j02 * c32 + j04 * c43; + float n7 = c31 + j13 * c33; + float n10 = c40 + j02 * c42 + j04c44; + float n11 = c41 + j13 * c43; + float n12 = c42 + j24 * c44; + + c[0] += j02 * j02c22 + j04 * j04c44 + 2.f * (j02 * c20ph04c42 + j04 * c40); + c[1] += j02 * c21 + j04 * c41 + j13 * n6; + c[2] += j13 * (c31 + n7); + c[3] = c20ph04c42 + j02c22 + j24 * n10; + c[4] = c21 + j13 * c32 + j24 * n11; + c[5] = c22 + j24 * (c42 + n12); + c[6] = n6; + c[7] = n7; + c[8] = c32 + c43 * j24; + c[10] = n10; + c[11] = n11; + c[12] = n12; + } else { + float c00 = c[0]; + float c10 = c[1]; + float c11 = c[2]; + + float ss = ey + ey1; + float tg = ss * cci; + float xx = 1.f - 0.25f * kdx * kdx * (1.f + tg * tg); + if (xx < 1.e-8f) { + return -1; + } + xx = CAMath::Sqrt(xx); + float yy = CAMath::Sqrt(ss * ss + cc * cc); + + float j12 = dx * mTrk.dzds * tg * (2.f + tg * (ey * exi + ey1 * ex1i)) / (xx * yy); + float j14 = 0; + if (CAMath::Abs(mTrk.qpt) > 1.e-6f) { + j14 = (2.f * xx * ex1i * dx / yy - dS) * mTrk.dzds / mTrk.qpt; + } else { + j14 = -mTrk.dzds * Bz * dx * dx * exi * exi * exi * (0.5f * ey + (1.f / 3.f) * kdx * (1 + 2.f * ey * ey) * exi * exi); + } + + p[1] += j12 * d2 + j14 * d4; + + float h00 = c00 + c20 * j02 + c40 * j04; + // float h01 = c10 + c21*j02 + c41*j04; + float h02 = c20 + c22 * j02 + c42 * j04; + // float h03 = c30 + c32*j02 + c43*j04; + float h04 = c40 + c42 * j02 + c44 * j04; + + float h10 = c10 + c20 * j12 + c30 * j13 + c40 * j14; + float h11 = c11 + c21 * j12 + c31 * j13 + c41 * j14; + float h12 = c21 + c22 * j12 + c32 * j13 + c42 * j14; + float h13 = c31 + c32 * j12 + c33 * j13 + c43 * j14; + float h14 = c41 + c42 * j12 + c43 * j13 + c44 * j14; + + float h20 = c20 + c40 * j24; + float h21 = c21 + c41 * j24; + float h22 = c22 + c42 * j24; + float h23 = c32 + c43 * j24; + float h24 = c42 + c44 * j24; + + c[0] = h00 + h02 * j02 + h04 * j04; + + c[1] = h10 + h12 * j02 + h14 * j04; + c[2] = h11 + h12 * j12 + h13 * j13 + h14 * j14; + + c[3] = h20 + h22 * j02 + h24 * j04; + c[4] = h21 + h22 * j12 + h23 * j13 + h24 * j14; + c[5] = h22 + h24 * j24; + + c[6] = c30 + c32 * j02 + c43 * j04; + c[7] = c31 + c32 * j12 + c33 * j13 + c43 * j14; + c[8] = c32 + c43 * j24; + // c[ 9] = c33; + + c[10] = c40 + c42 * j02 + c44 * j04; + c[11] = c41 + c42 * j12 + c43 * j13 + c44 * j14; + c[12] = c42 + c44 * j24; + // c[13] = c43; + // c[14] = c44; + } + + float& mC22 = c[5]; + float& mC33 = c[9]; + float& mC40 = c[10]; + float& mC41 = c[11]; + float& mC42 = c[12]; + float& mC43 = c[13]; + float& mC44 = c[14]; + + float dLmask = 0.f; + bool maskMS = (CAMath::Abs(dL) < mMaterial.DLMax); + if (maskMS) { + dLmask = dL; + } + float dLabs = CAMath::Abs(dLmask); + + // Energy Loss + { + // std::cout<<"APPLY ENERGY LOSS!!!"<<std::endl; + float corr = 1.f - mMaterial.EP2 * dLmask; + float corrInv = 1.f / corr; + mTrk.px *= corrInv; + mTrk.py *= corrInv; + mTrk.pz *= corrInv; + mTrk.pt *= corrInv; + mTrk.p *= corrInv; + mTrk.qpt *= corr; + + p[4] *= corr; + + mC40 *= corr; + mC41 *= corr; + mC42 *= corr; + mC43 *= corr; + mC44 = mC44 * corr * corr + dLabs * mMaterial.sigmadE2; + } + // Multiple Scattering + + { + mC22 += dLabs * mMaterial.k22 * mTrk.cosphi * mTrk.cosphi; + mC33 += dLabs * mMaterial.k33; + mC43 += dLabs * mMaterial.k43; + mC44 += dLabs * mMaterial.k44; + } + + return 0; +} + +GPUd() void GPUTPCCompressionTrackModel::calculateMaterialCorrection() +{ + const float mass = 0.13957f; + + float qpt = mTrk.qpt; + if (CAMath::Abs(qpt) > 20) { + qpt = 20; + } + + float w2 = (1.f + mTrk.dzds * mTrk.dzds); //==(P/pt)2 + float pti2 = qpt * qpt; + if (pti2 < 1.e-4f) { + pti2 = 1.e-4f; + } + + float mass2 = mass * mass; + float beta2 = w2 / (w2 + mass2 * pti2); + + float p2 = w2 / pti2; // impuls 2 + float betheRho = approximateBetheBloch(p2 / mass2) * mMaterial.rho; + float E = CAMath::Sqrt(p2 + mass2); + float theta2 = (14.1f * 14.1f / 1.e6f) / (beta2 * p2) * mMaterial.radLenInv; + + mMaterial.EP2 = E / p2; + + // Approximate energy loss fluctuation (M.Ivanov) + + const float knst = 0.07f; // To be tuned. + mMaterial.sigmadE2 = knst * mMaterial.EP2 * qpt; + mMaterial.sigmadE2 = mMaterial.sigmadE2 * mMaterial.sigmadE2; + + mMaterial.k22 = theta2 * w2; + mMaterial.k33 = mMaterial.k22 * w2; + mMaterial.k43 = 0.f; + mMaterial.k44 = theta2 * mTrk.dzds * mTrk.dzds * pti2; + + float br = (betheRho > 1.e-8f) ? betheRho : 1.e-8f; + mMaterial.DLMax = 0.3f * E / br; + mMaterial.EP2 *= betheRho; + mMaterial.sigmadE2 = mMaterial.sigmadE2 * betheRho; // + mMaterial.fK44; +} + +GPUd() float GPUTPCCompressionTrackModel::approximateBetheBloch(float beta2) +{ + //------------------------------------------------------------------ + // This is an approximation of the Bethe-Bloch formula with + // the density effect taken into account at beta*gamma > 3.5 + // (the approximation is reasonable only for solid materials) + //------------------------------------------------------------------ + + const float log0 = log(5940.f); + const float log1 = log(3.5f * 5940.f); + + bool bad = (beta2 >= .999f) || (beta2 < 1.e-8f); + + if (bad) { + return 0.f; + } + + float a = beta2 / (1.f - beta2); + float b = 0.5f * log(a); + float d = 0.153e-3f / beta2; + float c = b - beta2; + + float ret = d * (log0 + b + c); + float case1 = d * (log1 + c); + + if (a > 3.5f * 3.5f) { + ret = case1; + } + + return ret; +} + +GPUd() void GPUTPCCompressionTrackModel::getClusterRMS2(int iRow, float z, float sinPhi, float DzDs, float& ErrY2, float& ErrZ2) const +{ + // Only O2 geometry considered at the moment. Is AliRoot geometry support needed? + int rowType = iRow < 97 ? (iRow < 63 ? 0 : 1) : (iRow < 127 ? 2 : 3); + if (rowType > 2) { + rowType = 2; // TODO: Add type 3 + } + z = CAMath::Abs((250.f - 0.275f) - CAMath::Abs(z)); + float s2 = sinPhi * sinPhi; + if (s2 > 0.95f * 0.95f) { + s2 = 0.95f * 0.95f; + } + float sec2 = 1.f / (1.f - s2); + float angleY2 = s2 * sec2; // dy/dx + float angleZ2 = DzDs * DzDs * sec2; // dz/dx + + const float* cY = kParamRMS0[0][rowType]; + ErrY2 = cY[0] + cY[1] * z + cY[2] * angleY2; + ErrY2 *= ErrY2; + + const float* cZ = kParamRMS0[1][rowType]; + ErrZ2 = cZ[0] + cZ[1] * z + cZ[2] * angleZ2; + ErrZ2 *= ErrZ2; +} + +GPUd() void GPUTPCCompressionTrackModel::resetCovariance() +{ + mC[0] = 100.f; + mC[1] = 0.f; + mC[2] = 100.f; + mC[3] = 0.f; + mC[4] = 0.f; + mC[5] = 1.f; + mC[6] = 0.f; + mC[7] = 0.f; + mC[8] = 0.f; + mC[9] = 10.f; + mC[10] = 0.f; + mC[11] = 0.f; + mC[12] = 0.f; + mC[13] = 0.f; + mC[14] = 10.f; +} + #endif diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h index 28d9392f039bb..67c23ee01f2cd 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h @@ -28,7 +28,7 @@ #include "GPUTPCTrackParam.h" #else // Default internal track model for compression -#error Not yet implemented +#include "GPUTPCGMPolynomialField.h" #endif namespace GPUCA_NAMESPACE::gpu @@ -39,6 +39,8 @@ namespace GPUCA_NAMESPACE::gpu struct GPUParam; +constexpr float MaxSinPhi = 0.999f; + class GPUTPCCompressionTrackModel { public: @@ -60,21 +62,98 @@ class GPUTPCCompressionTrackModel #else // Default internal track model for compression + struct PhysicalTrackModel { // see GPUTPCGMPhysicalTrackModel + // physical parameters of the trajectory + + float x = 0.f; // X + float y = 0.f; // Y + float z = 0.f; // Z + float px = 1.e4f; // Px, >0 + float py = 0.f; // Py + float pz = 0.f; // Pz + float q = 1.f; // charge, +-1 + + // some additional variables needed for GMTrackParam transport + + float sinphi = 0.f; // SinPhi = Py/Pt + float cosphi = 1.f; // CosPhi = abs(Px)/Pt + float secphi = 1.f; // 1/cos(phi) = Pt/abs(Px) + float dzds = 0.f; // DzDs = Pz/Pt + float dlds = 1.f; // DlDs = P/Pt + float qpt = 0.f; // QPt = q/Pt + float p = 1.e4f; // momentum + float pt = 1.e4f; // Pt momentum + }; + + GPUd() float Y() const { return mP[0]; } + GPUd() float Z() const { return mP[1]; } + + // helper functions for standalone propagation and update methods + GPUd() void getBxByBz(float cosAlpha, float sinAlpha, float x, float y, float z, float b[3]) const; + GPUd() float getBz(float x, float y, float z) const; + GPUd() void updatePhysicalTrackValues(PhysicalTrackModel& trk); + GPUd() void changeDirection(); + GPUd() int rotateToAlpha(float newAlpha); + GPUd() int propagateToXBxByBz(PhysicalTrackModel& t, float x, float Bx, float By, float Bz, float& dLp); + GPUd() int propagateToXBzLightNoUpdate(PhysicalTrackModel& t, float x, float Bz, float& dLp); + GPUd() bool setDirectionAlongX(PhysicalTrackModel& t); + GPUd() int followLinearization(const PhysicalTrackModel& t0e, float Bz, float dLp); + GPUd() void calculateMaterialCorrection(); + GPUd() float approximateBetheBloch(float beta2); + GPUd() void getClusterRMS2(int iRow, float z, float sinPhi, float DzDs, float& ErrY2, float& ErrZ2) const; + GPUd() void resetCovariance(); + #endif protected: - const GPUParam* mParam; #ifdef GPUCA_COMPRESSION_TRACK_MODEL_MERGER GPUTPCGMPropagator mProp; GPUTPCGMTrackParam mTrk; + const GPUParam* mParam; #elif defined(GPUCA_COMPRESSION_TRACK_MODEL_SLICETRACKER) GPUTPCTrackParam mTrk; float mAlpha; + const GPUParam* mParam; #else // Default internal track model for compression + struct MaterialCorrection { + GPUhd() MaterialCorrection() : radLen(28811.7f), rho(1.025e-3f), radLenInv(1.f / radLen), DLMax(0.f), EP2(0.f), sigmadE2(0.f), k22(0.f), k33(0.f), k43(0.f), k44(0.f) {} + + float radLen; // [cm] + float rho; // [g/cm^3] + float radLenInv, DLMax, EP2, sigmadE2, k22, k33, k43, k44; // precalculated values for MS and EnergyLoss correction + }; + + // default TPC cluster error parameterization taken from GPUParam.cxx + // clang-format off + const float kParamRMS0[2][3][4] = + { + { { 4.17516864836e-02, 1.87623649254e-04, 5.63788712025e-02, 5.38373768330e-01, }, + { 8.29434990883e-02, 2.03291710932e-04, 6.81538805366e-02, 9.70965325832e-01, }, + { 8.67543518543e-02, 2.10733342101e-04, 1.38366967440e-01, 2.55089461803e-01, } + }, { + { 5.96254616976e-02, 8.62886518007e-05, 3.61776389182e-02, 4.79704320431e-01, }, + { 6.12571723759e-02, 7.23929333617e-05, 3.93057651818e-02, 9.29222583771e-01, }, + { 6.58465921879e-02, 1.03639606095e-04, 6.07583411038e-02, 9.90289509296e-01, } } + }; + // clang-format on + + float mX; + float mAlpha; + float mP[5]; + float mC[15]; + int mNDF = -5; + float mCosAlpha; + float mSinAlpha; + + // propagation parameters + const GPUTPCGMPolynomialField* mField = nullptr; + MaterialCorrection mMaterial; + + PhysicalTrackModel mTrk; #endif }; } // namespace GPUCA_NAMESPACE::gpu From 99515ccd138c36ee530ab62d700711281cdd17ec Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 27 Oct 2020 10:13:47 +0100 Subject: [PATCH 1203/1751] Use default compression track model --- GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h index 67c23ee01f2cd..5aabb67e5cea4 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h @@ -15,7 +15,7 @@ #define GPUTPCCOMPRESSIONTRACKMODEL_H // For debugging purposes, we provide means to use other track models -#define GPUCA_COMPRESSION_TRACK_MODEL_MERGER +// #define GPUCA_COMPRESSION_TRACK_MODEL_MERGER // #define GPUCA_COMPRESSION_TRACK_MODEL_SLICETRACKER #include "GPUDef.h" From fe2c48f131a6d159a4a87f19672cc01257ea047c Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 27 Oct 2020 15:01:28 +0100 Subject: [PATCH 1204/1751] Fully removed polynomial magnetic field - assuming constant Bz: entropy constant, 7% speedup - removed function for propagation with bxbybz --- .../GPUTPCCompressionTrackModel.cxx | 132 +----------------- .../GPUTPCCompressionTrackModel.h | 6 +- 2 files changed, 8 insertions(+), 130 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx index 4f6bc8cf3122d..e32f58ef68635 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx @@ -126,7 +126,7 @@ GPUd() void GPUTPCCompressionTrackModel::Init(float x, float y, float z, float a mP[4] = (qPt - 127.f) * (20.f / 127.f); resetCovariance(); mNDF = -5; - mField = ¶m.polynomialField; + mBz = param.ConstBz; float pti = CAMath::Abs(mP[4]); if (pti < 1.e-4f) { pti = 1.e-4f; // set 10.000 GeV momentum for straight track @@ -163,22 +163,20 @@ GPUd() int GPUTPCCompressionTrackModel::Propagate(float x, float alpha) return 0; } - float Bz = getBz(mTrk.x, mTrk.y, mTrk.z); - // propagate mTrk to t0e PhysicalTrackModel t0e(mTrk); float dLp = 0; if (CAMath::Abs(x - t0e.x) < 1.e-8f) { return 0; } - if (propagateToXBzLightNoUpdate(t0e, x, Bz, dLp)) { + if (propagateToXBzLightNoUpdate(t0e, x, mBz, dLp)) { return 1; } updatePhysicalTrackValues(t0e); if (CAMath::Abs(t0e.sinphi) >= MaxSinPhi) { return -3; } - return followLinearization(t0e, Bz, dLp); + return followLinearization(t0e, mBz, dLp); } GPUd() int GPUTPCCompressionTrackModel::Filter(float y, float z, int iRow) @@ -294,11 +292,7 @@ GPUd() int GPUTPCCompressionTrackModel::Filter(float y, float z, int iRow) GPUd() int GPUTPCCompressionTrackModel::Mirror() { - float Bz = getBz(mTrk.x, mTrk.y, mTrk.z); - if (CAMath::Abs(Bz) < 1.e-8f) { - Bz = 1.e-8f; - } - float dy = -2.f * mTrk.q * mTrk.px / Bz; + float dy = -2.f * mTrk.q * mTrk.px / mBz; float dS; // path in XY { float chord = dy; // chord to the extrapolated point == |dy|*sign(x direction) @@ -361,25 +355,6 @@ GPUd() int GPUTPCCompressionTrackModel::Mirror() return 0; } -GPUd() void GPUTPCCompressionTrackModel::getBxByBz(float cosAlpha, float sinAlpha, float x, float y, float z, float b[3]) const -{ - float xGlb = x * cosAlpha - y * sinAlpha; - float yGlb = x * sinAlpha + y * cosAlpha; - float bb[3]; - mField->GetField(xGlb, yGlb, z, bb); - // rotate field to local coordinates - b[0] = bb[0] * cosAlpha + bb[1] * sinAlpha; - b[1] = -bb[0] * sinAlpha + bb[1] * cosAlpha; - b[2] = bb[2]; -} - -GPUd() float GPUTPCCompressionTrackModel::getBz(float x, float y, float z) const -{ - float xGlb = x * mCosAlpha - y * mSinAlpha; - float yGlb = x * mSinAlpha + y * mCosAlpha; - return mField->GetFieldBz(xGlb, yGlb, z); -} - GPUd() void GPUTPCCompressionTrackModel::updatePhysicalTrackValues(PhysicalTrackModel& trk) { float px = trk.px; @@ -460,12 +435,11 @@ GPUd() int GPUTPCCompressionTrackModel::rotateToAlpha(float newAlpha) float trackX = x0 * cc + ss * mP[0]; // transport t0 to trackX - float B[3]; - getBxByBz(CAMath::Cos(newAlpha), CAMath::Sin(newAlpha), t0.x, t0.y, t0.z, B); float dLp = 0; - if (propagateToXBxByBz(t0, trackX, B[0], B[1], B[2], dLp)) { + if (propagateToXBzLightNoUpdate(t0, trackX, mBz, dLp)) { return -1; } + updatePhysicalTrackValues(t0); if (CAMath::Abs(t0.sinphi) >= MaxSinPhi) { return -1; @@ -531,7 +505,7 @@ GPUd() int GPUTPCCompressionTrackModel::rotateToAlpha(float newAlpha) // only covariance changes. Use rotated and transported t0 for linearisation float j3 = -t0.py / t0.px; float j4 = -t0.pz / t0.px; - float j5 = t0.qpt * B[2]; + float j5 = t0.qpt * mBz; // Y Z Sin DzDs q/p X // Jacobian J1 = { { 1, 0, 0, 0, 0, j3 }, // Y @@ -566,98 +540,6 @@ GPUd() int GPUTPCCompressionTrackModel::rotateToAlpha(float newAlpha) return 0; } -GPUd() int GPUTPCCompressionTrackModel::propagateToXBxByBz(PhysicalTrackModel& t, float x, float Bx, float By, float Bz, float& dLp) -{ - // - // transport the track to X=x in magnetic field B = ( Bx, By, Bz )[kG*0.000299792458] - // xyzPxPyPz as well as all the additional values will change. No need to call UpdateValues() afterwards. - // the method returns error code (0 == no error) - // - dLp = 0.f; - - // Rotate to the system where Bx=By=0. - - float bt = CAMath::Sqrt(Bz * Bz + By * By); - float bb = CAMath::Sqrt(Bx * Bx + By * By + Bz * Bz); - - float c1 = 1.f, s1 = 0.f; - float c2 = 1.f, s2 = 0.f; - - if (bt > 1.e-4f) { - c1 = Bz / bt; - s1 = By / bt; - c2 = bt / bb; - s2 = -Bx / bb; - } - - // rotation matrix: first around x, then around y' - // after the first rotation: Bx'==Bx, By'==0, Bz'==Bt, X'==X - // after the second rotation: Bx''==0, By''==0, Bz''==B, X'' axis is as close as possible to the original X - - // - // ( c2 0 s2 ) ( 1 0 0 ) - // R = ( 0 1 0 ) X ( 0 c1 -s1 ) - // (-s2 0 c2 ) ( 0 s1 c1 ) - // - - float R0[3] = {c2, s1 * s2, c1 * s2}; - float R1[3] = {0, c1, -s1}; - float R2[3] = {-s2, s1 * c2, c1 * c2}; - - // parameters and the extrapolation point in the rotated coordinate system - { - float lx = t.x, ly = t.y, lz = t.z, lpx = t.px, lpy = t.py, lpz = t.pz; - - t.x = R0[0] * lx + R0[1] * ly + R0[2] * lz; - t.y = R1[0] * lx + R1[1] * ly + R1[2] * lz; - t.z = R2[0] * lx + R2[1] * ly + R2[2] * lz; - - t.px = R0[0] * lpx + R0[1] * lpy + R0[2] * lpz; - t.py = R1[0] * lpx + R1[1] * lpy + R1[2] * lpz; - t.pz = R2[0] * lpx + R2[1] * lpy + R2[2] * lpz; - } - - float dx = x - mX; - float xe = t.x + dx; // propagate on same dx in rotated system - - // transport in rotated coordinate system to X''=xe: - - if (t.px < (1.f - MaxSinPhi)) { - t.px = 1.f - MaxSinPhi; - } - if (propagateToXBzLightNoUpdate(t, xe, bb, dLp) != 0) { - return -1; - } - - // rotate coordinate system back to the original R{-1}==R{T} - { - float lx = t.x, ly = t.y, lz = t.z, lpx = t.px, lpy = t.py, lpz = t.pz; - - t.x = R0[0] * lx + R1[0] * ly + R2[0] * lz; - t.y = R0[1] * lx + R1[1] * ly + R2[1] * lz; - t.z = R0[2] * lx + R1[2] * ly + R2[2] * lz; - - t.px = R0[0] * lpx + R1[0] * lpy + R2[0] * lpz; - t.py = R0[1] * lpx + R1[1] * lpy + R2[1] * lpz; - t.pz = R0[2] * lpx + R1[2] * lpy + R2[2] * lpz; - } - - // a small (hopefully) additional step to X=x. Perhaps it may be replaced by linear extrapolation. - - float ddLp = 0; - if (t.px < (1.f - MaxSinPhi)) { - t.px = 1.f - MaxSinPhi; - } - if (propagateToXBzLightNoUpdate(t, x, Bz, ddLp) != 0) { - return -1; - } - - dLp += ddLp; - - updatePhysicalTrackValues(t); - return 0; -} - GPUd() int GPUTPCCompressionTrackModel::propagateToXBzLightNoUpdate(PhysicalTrackModel& t, float x, float Bz, float& dLp) { // diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h index 5aabb67e5cea4..906a71fe0b742 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h @@ -28,7 +28,6 @@ #include "GPUTPCTrackParam.h" #else // Default internal track model for compression -#include "GPUTPCGMPolynomialField.h" #endif namespace GPUCA_NAMESPACE::gpu @@ -89,12 +88,9 @@ class GPUTPCCompressionTrackModel GPUd() float Z() const { return mP[1]; } // helper functions for standalone propagation and update methods - GPUd() void getBxByBz(float cosAlpha, float sinAlpha, float x, float y, float z, float b[3]) const; - GPUd() float getBz(float x, float y, float z) const; GPUd() void updatePhysicalTrackValues(PhysicalTrackModel& trk); GPUd() void changeDirection(); GPUd() int rotateToAlpha(float newAlpha); - GPUd() int propagateToXBxByBz(PhysicalTrackModel& t, float x, float Bx, float By, float Bz, float& dLp); GPUd() int propagateToXBzLightNoUpdate(PhysicalTrackModel& t, float x, float Bz, float& dLp); GPUd() bool setDirectionAlongX(PhysicalTrackModel& t); GPUd() int followLinearization(const PhysicalTrackModel& t0e, float Bz, float dLp); @@ -150,7 +146,7 @@ class GPUTPCCompressionTrackModel float mSinAlpha; // propagation parameters - const GPUTPCGMPolynomialField* mField = nullptr; + float mBz; MaterialCorrection mMaterial; PhysicalTrackModel mTrk; From 8a97280f1c927c81964540763afa8de3508d0cf4 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Wed, 4 Nov 2020 16:59:39 +0100 Subject: [PATCH 1205/1751] Follow O2 naming convention --- .../DataCompression/GPUTPCCompressionTrackModel.cxx | 4 ++-- GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx index e32f58ef68635..627d16828683a 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx @@ -903,11 +903,11 @@ GPUd() void GPUTPCCompressionTrackModel::getClusterRMS2(int iRow, float z, float float angleY2 = s2 * sec2; // dy/dx float angleZ2 = DzDs * DzDs * sec2; // dz/dx - const float* cY = kParamRMS0[0][rowType]; + const float* cY = mParamRMS0[0][rowType]; ErrY2 = cY[0] + cY[1] * z + cY[2] * angleY2; ErrY2 *= ErrY2; - const float* cZ = kParamRMS0[1][rowType]; + const float* cZ = mParamRMS0[1][rowType]; ErrZ2 = cZ[0] + cZ[1] * z + cZ[2] * angleZ2; ErrZ2 *= ErrZ2; } diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h index 906a71fe0b742..7f13e434bea45 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.h @@ -125,7 +125,7 @@ class GPUTPCCompressionTrackModel // default TPC cluster error parameterization taken from GPUParam.cxx // clang-format off - const float kParamRMS0[2][3][4] = + const float mParamRMS0[2][3][4] = { { { 4.17516864836e-02, 1.87623649254e-04, 5.63788712025e-02, 5.38373768330e-01, }, { 8.29434990883e-02, 2.03291710932e-04, 6.81538805366e-02, 9.70965325832e-01, }, From 30986c78e123db556b60b66611cd886ea0d164d2 Mon Sep 17 00:00:00 2001 From: ppillot <pillot@subatech.in2p3.fr> Date: Mon, 2 Nov 2020 10:56:51 +0100 Subject: [PATCH 1206/1751] new MCH track format + update of tracking workflows --- DataFormats/Detectors/MUON/CMakeLists.txt | 1 + DataFormats/Detectors/MUON/MCH/CMakeLists.txt | 16 + .../MCH/include/DataFormatsMCH/TrackMCH.h | 118 ++++++ .../MUON/MCH/src/DataFormatsMCHLinkDef.h | 18 + .../Detectors/MUON/MCH/src/TrackMCH.cxx | 84 ++++ Detectors/MUON/MCH/README.md | 1 + Detectors/MUON/MCH/Tracking/CMakeLists.txt | 31 +- Detectors/MUON/MCH/Tracking/README.md | 135 +++++++ .../Tracking/include/MCHTracking/Cluster.h | 4 +- .../MCHTracking}/TrackExtrap.h | 0 .../MCHTracking}/TrackFinder.h | 2 +- .../MCHTracking}/TrackFinderOriginal.h | 2 +- .../MCHTracking}/TrackFitter.h | 0 .../Tracking/include/MCHTracking/TrackParam.h | 8 +- .../MCH/Tracking/src/TrackAtVertexSpec.cxx | 379 ------------------ .../MUON/MCH/Tracking/src/TrackExtrap.cxx | 2 +- .../MUON/MCH/Tracking/src/TrackFinder.cxx | 4 +- .../MCH/Tracking/src/TrackFinderOriginal.cxx | 4 +- .../Tracking/src/TrackFinderOriginalSpec.cxx | 243 ----------- .../MUON/MCH/Tracking/src/TrackFinderSpec.cxx | 244 ----------- .../MUON/MCH/Tracking/src/TrackFitter.cxx | 4 +- .../MUON/MCH/Tracking/src/TrackFitterSpec.cxx | 220 ---------- .../MUON/MCH/Tracking/src/TrackParam.cxx | 51 ++- Detectors/MUON/MCH/Workflow/CMakeLists.txt | 53 ++- Detectors/MUON/MCH/Workflow/README.md | 133 ++++++ .../src/ClusterSamplerSpec.cxx | 47 ++- .../src/ClusterSamplerSpec.h | 0 .../MCH/Workflow/src/TrackAtVertexSpec.cxx | 203 ++++++++++ .../src/TrackAtVertexSpec.h | 0 .../Workflow/src/TrackFinderOriginalSpec.cxx | 149 +++++++ .../src/TrackFinderOriginalSpec.h | 0 .../MUON/MCH/Workflow/src/TrackFinderSpec.cxx | 149 +++++++ .../src/TrackFinderSpec.h | 0 .../MUON/MCH/Workflow/src/TrackFitterSpec.cxx | 128 ++++++ .../src/TrackFitterSpec.h | 0 .../src/TrackSamplerSpec.cxx | 71 ++-- .../src/TrackSamplerSpec.h | 2 +- .../src/TrackSinkSpec.cxx | 53 ++- .../src/TrackSinkSpec.h | 3 +- .../src/VertexSamplerSpec.cxx | 43 +- .../src/VertexSamplerSpec.h | 0 .../src/clusters-sampler-workflow.cxx} | 14 +- .../clusters-to-tracks-original-workflow.cxx | 25 ++ .../src/clusters-to-tracks-workflow.cxx | 25 ++ .../Workflow/src/tracks-sampler-workflow.cxx | 37 ++ .../MCH/Workflow/src/tracks-sink-workflow.cxx | 40 ++ .../tracks-to-tracks-at-vertex-workflow.cxx} | 18 +- .../src/tracks-to-tracks-workflow.cxx} | 14 +- .../Workflow/src/vertex-sampler-workflow.cxx | 25 ++ 49 files changed, 1548 insertions(+), 1255 deletions(-) create mode 100644 DataFormats/Detectors/MUON/MCH/CMakeLists.txt create mode 100644 DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h create mode 100644 DataFormats/Detectors/MUON/MCH/src/DataFormatsMCHLinkDef.h create mode 100644 DataFormats/Detectors/MUON/MCH/src/TrackMCH.cxx create mode 100644 Detectors/MUON/MCH/Tracking/README.md rename Detectors/MUON/MCH/Tracking/{src => include/MCHTracking}/TrackExtrap.h (100%) rename Detectors/MUON/MCH/Tracking/{src => include/MCHTracking}/TrackFinder.h (99%) rename Detectors/MUON/MCH/Tracking/{src => include/MCHTracking}/TrackFinderOriginal.h (99%) rename Detectors/MUON/MCH/Tracking/{src => include/MCHTracking}/TrackFitter.h (100%) delete mode 100644 Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx delete mode 100644 Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx delete mode 100644 Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx delete mode 100644 Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx rename Detectors/MUON/MCH/{Tracking => Workflow}/src/ClusterSamplerSpec.cxx (76%) rename Detectors/MUON/MCH/{Tracking => Workflow}/src/ClusterSamplerSpec.h (100%) create mode 100644 Detectors/MUON/MCH/Workflow/src/TrackAtVertexSpec.cxx rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackAtVertexSpec.h (100%) create mode 100644 Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackFinderOriginalSpec.h (100%) create mode 100644 Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackFinderSpec.h (100%) create mode 100644 Detectors/MUON/MCH/Workflow/src/TrackFitterSpec.cxx rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackFitterSpec.h (100%) rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackSamplerSpec.cxx (55%) rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackSamplerSpec.h (91%) rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackSinkSpec.cxx (55%) rename Detectors/MUON/MCH/{Tracking => Workflow}/src/TrackSinkSpec.h (86%) rename Detectors/MUON/MCH/{Tracking => Workflow}/src/VertexSamplerSpec.cxx (70%) rename Detectors/MUON/MCH/{Tracking => Workflow}/src/VertexSamplerSpec.h (100%) rename Detectors/MUON/MCH/{Tracking/src/TrackFinderOriginalWorkflow.cxx => Workflow/src/clusters-sampler-workflow.cxx} (67%) create mode 100644 Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-original-workflow.cxx create mode 100644 Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-workflow.cxx create mode 100644 Detectors/MUON/MCH/Workflow/src/tracks-sampler-workflow.cxx create mode 100644 Detectors/MUON/MCH/Workflow/src/tracks-sink-workflow.cxx rename Detectors/MUON/MCH/{Tracking/src/TrackFinderWorkflow.cxx => Workflow/src/tracks-to-tracks-at-vertex-workflow.cxx} (59%) rename Detectors/MUON/MCH/{Tracking/src/TrackFitterWorkflow.cxx => Workflow/src/tracks-to-tracks-workflow.cxx} (67%) create mode 100644 Detectors/MUON/MCH/Workflow/src/vertex-sampler-workflow.cxx diff --git a/DataFormats/Detectors/MUON/CMakeLists.txt b/DataFormats/Detectors/MUON/CMakeLists.txt index 25f5ebce089ac..497e1d502f36f 100644 --- a/DataFormats/Detectors/MUON/CMakeLists.txt +++ b/DataFormats/Detectors/MUON/CMakeLists.txt @@ -9,3 +9,4 @@ # submit itself to any jurisdiction. add_subdirectory(MID) +add_subdirectory(MCH) diff --git a/DataFormats/Detectors/MUON/MCH/CMakeLists.txt b/DataFormats/Detectors/MUON/MCH/CMakeLists.txt new file mode 100644 index 0000000000000..d7f5190bed5b2 --- /dev/null +++ b/DataFormats/Detectors/MUON/MCH/CMakeLists.txt @@ -0,0 +1,16 @@ +# 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_library(DataFormatsMCH + SOURCES src/TrackMCH.cxx + PUBLIC_LINK_LIBRARIES O2::CommonDataFormat) + +o2_target_root_dictionary(DataFormatsMCH + HEADERS include/DataFormatsMCH/TrackMCH.h) diff --git a/DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h b/DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h new file mode 100644 index 0000000000000..becd8805e93f7 --- /dev/null +++ b/DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.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 TrackMCH.h +/// \brief Definition of the MCH track +/// +/// \author Philippe Pillot, Subatech + +#ifndef ALICEO2_MCH_TRACKMCH_H_ +#define ALICEO2_MCH_TRACKMCH_H_ + +#include <TMatrixD.h> + +#include "CommonDataFormat/RangeReference.h" + +namespace o2 +{ +namespace mch +{ + +/// MCH track external format +class TrackMCH +{ + using ClusRef = o2::dataformats::RangeRefComp<5>; + + public: + TrackMCH() = default; + TrackMCH(double z, const TMatrixD& param, const TMatrixD& cov, double chi2, int firstClIdx, int nClusters); + ~TrackMCH() = default; + + TrackMCH(const TrackMCH& track) = default; + TrackMCH& operator=(const TrackMCH& track) = default; + TrackMCH(TrackMCH&&) = default; + TrackMCH& operator=(TrackMCH&&) = default; + + /// get the track x position + double getX() const { return mParam[0]; } + /// get the track y position + double getY() const { return mParam[2]; } + /// get the track z position where the parameters are evaluated + double getZ() const { return mZ; } + /// set the track z position where the parameters are evaluated + void setZ(double z) { mZ = z; } + + double getPx() const; + double getPy() const; + double getPz() const; + double getP() const; + + /// get the muon sign + short getSign() const { return (mParam[4] < 0) ? -1 : 1; } + + /// get the track parameters + const double* getParameters() const { return mParam; } + /// set the track parameters + void setParameters(const TMatrixD& param) { param.GetMatrix2Array(mParam); } + + /// get the track parameter covariances + const double* getCovariances() const { return mCov; } + /// get the covariance between track parameters i and j + double getCovariance(int i, int j) const { return mCov[SCovIdx[i][j]]; } + // set the track parameter covariances + void setCovariances(const TMatrixD& cov); + + /// get the track chi2 + double getChi2() const { return mChi2; } + /// set the track chi2 + void setChi2(double chi2) { mChi2 = chi2; } + /// get the number of degrees of freedom of the track + int getNDF() const { return 2 * mClusRef.getEntries() - 5; } + /// get the track normalized chi2 + double getChi2OverNDF() const { return mChi2 / getNDF(); } + + /// get the number of clusters attached to the track + int getNClusters() const { return mClusRef.getEntries(); } + /// get the index of the first cluster attached to the track + int getFirstClusterIdx() const { return mClusRef.getFirstEntry(); } + /// get the index of the last cluster attached to the track + int getLastClusterIdx() const { return mClusRef.getFirstEntry() + mClusRef.getEntries() - 1; } + /// set the number of the clusters attached to the track and the index of the first one + void setClusterRef(int firstClusterIdx, int nClusters) { mClusRef.set(firstClusterIdx, nClusters); } + + private: + static constexpr int SNParams = 5; ///< number of track parameters + static constexpr int SCovSize = 15; ///< number of different elements in the symmetric covariance matrix + /// corresponding indices to access the covariance matrix elements by row and column + static constexpr int SCovIdx[SNParams][SNParams] = {{0, 1, 3, 6, 10}, + {1, 2, 4, 7, 11}, + {3, 4, 5, 8, 12}, + {6, 7, 8, 9, 13}, + {10, 11, 12, 13, 14}}; + + double mZ = 0.; ///< z position where the parameters are evaluated + double mParam[SNParams] = {0.}; ///< 5 parameters: X (cm), SlopeX, Y (cm), SlopeY, q/pYZ ((GeV/c)^-1) + /// reduced covariance matrix of track parameters, formated as follow: <pre> + /// [0] = <X,X> + /// [1] = <SlopeX,X> [2] = <SlopeX,SlopeX> + /// [3] = <Y,X> [4] = <Y,SlopeX> [5] = <Y,Y> + /// [6] = <SlopeY,X> [7] = <SlopeY,SlopeX> [8] = <SlopeY,Y> [9] = <SlopeY,SlopeY> + /// [10]= <q/pYZ,X> [11]= <q/pYZ,SlopeX> [12]= <q/pYZ,Y> [13]= <q/pYZ,SlopeY> [14]= <q/pYZ,q/pYZ> </pre> + double mCov[SCovSize] = {0.}; + double mChi2 = 0.; ///< chi2 of track + ClusRef mClusRef{}; ///< reference to external cluster indices + + ClassDefNV(TrackMCH, 1); +}; + +} // namespace mch +} // namespace o2 + +#endif // ALICEO2_MCH_TRACKMCH_H_ diff --git a/DataFormats/Detectors/MUON/MCH/src/DataFormatsMCHLinkDef.h b/DataFormats/Detectors/MUON/MCH/src/DataFormatsMCHLinkDef.h new file mode 100644 index 0000000000000..7784e087e6eb5 --- /dev/null +++ b/DataFormats/Detectors/MUON/MCH/src/DataFormatsMCHLinkDef.h @@ -0,0 +1,18 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::mch::TrackMCH + ; +#endif diff --git a/DataFormats/Detectors/MUON/MCH/src/TrackMCH.cxx b/DataFormats/Detectors/MUON/MCH/src/TrackMCH.cxx new file mode 100644 index 0000000000000..80ef07470b556 --- /dev/null +++ b/DataFormats/Detectors/MUON/MCH/src/TrackMCH.cxx @@ -0,0 +1,84 @@ +// 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 TrackMCH.cxx +/// \brief Implementation of the MCH track +/// +/// \author Philippe Pillot, Subatech + +#include "DataFormatsMCH/TrackMCH.h" + +#include <cmath> +#include <limits> + +namespace o2 +{ +namespace mch +{ + +//__________________________________________________________________________ +TrackMCH::TrackMCH(double z, const TMatrixD& param, const TMatrixD& cov, double chi2, int firstClIdx, int nClusters) + : mZ(z), mChi2(chi2), mClusRef(firstClIdx, nClusters) +{ + /// constructor + setParameters(param); + setCovariances(cov); +} + +//__________________________________________________________________________ +double TrackMCH::getPx() const +{ + /// return track momentum along x + return getPz() * mParam[1]; +} + +//__________________________________________________________________________ +double TrackMCH::getPy() const +{ + /// return track momentum along y + return getPz() * mParam[3]; +} + +//__________________________________________________________________________ +double TrackMCH::getPz() const +{ + /// return track momentum along z + if (mParam[4] != 0.) { + return -std::abs(1. / mParam[4]) / std::sqrt(1. + mParam[3] * mParam[3]); // spectro. (z<0) + } else { + return -std::numeric_limits<float>::max() / std::sqrt(1. + mParam[3] * mParam[3] + mParam[1] * mParam[1]); + } +} + +//__________________________________________________________________________ +double TrackMCH::getP() const +{ + /// return track momentum + if (mParam[4] != 0.) { + return std::abs(1. / mParam[4]) / std::sqrt(1. + mParam[3] * mParam[3]) * + std::sqrt(1. + mParam[3] * mParam[3] + mParam[1] * mParam[1]); + } else { + return std::numeric_limits<float>::max(); + } +} + +//__________________________________________________________________________ +void TrackMCH::setCovariances(const TMatrixD& cov) +{ + /// set the track parameter covariances + for (int i = 0; i < SNParams; i++) { + for (int j = 0; j <= i; j++) { + mCov[SCovIdx[i][j]] = cov(i, j); + } + } +} + +} // namespace mch +} // namespace o2 diff --git a/Detectors/MUON/MCH/README.md b/Detectors/MUON/MCH/README.md index 8b49bf20caf2d..6f2ebf1975925 100644 --- a/Detectors/MUON/MCH/README.md +++ b/Detectors/MUON/MCH/README.md @@ -11,5 +11,6 @@ This is a top page for the MCH detector documentation. \subpage refDetectorsMUONMCHClustering \subpage refDetectorsMUONMCHRaw \subpage refDetectorsMUONMCHMapping +\subpage refDetectorsMUONMCHTracking \subpage refDetectorsMUONMCHWorkflow /doxy --> diff --git a/Detectors/MUON/MCH/Tracking/CMakeLists.txt b/Detectors/MUON/MCH/Tracking/CMakeLists.txt index c69ac3d56014f..9aee91ff5e676 100644 --- a/Detectors/MUON/MCH/Tracking/CMakeLists.txt +++ b/Detectors/MUON/MCH/Tracking/CMakeLists.txt @@ -17,33 +17,4 @@ o2_add_library(MCHTracking src/TrackFitter.cxx src/TrackFinderOriginal.cxx src/TrackFinder.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::Field O2::MCHBase) - -o2_add_executable(trackfitter-workflow - SOURCES - src/TrackFitterWorkflow.cxx - src/TrackSamplerSpec.cxx - src/TrackFitterSpec.cxx - src/TrackSinkSpec.cxx - COMPONENT_NAME mch - PUBLIC_LINK_LIBRARIES O2::MCHTracking) - -o2_add_executable(trackfinderoriginal-workflow - SOURCES - src/TrackFinderOriginalWorkflow.cxx - src/ClusterSamplerSpec.cxx - src/TrackFinderOriginalSpec.cxx - src/TrackSinkSpec.cxx - COMPONENT_NAME mch - PUBLIC_LINK_LIBRARIES O2::MCHTracking) - - o2_add_executable(trackfinder-workflow - SOURCES - src/TrackFinderWorkflow.cxx - src/ClusterSamplerSpec.cxx - src/VertexSamplerSpec.cxx - src/TrackFinderSpec.cxx - src/TrackAtVertexSpec.cxx - src/TrackSinkSpec.cxx - COMPONENT_NAME mch - PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::MCHTracking) + PUBLIC_LINK_LIBRARIES O2::Field O2::MCHBase) diff --git a/Detectors/MUON/MCH/Tracking/README.md b/Detectors/MUON/MCH/Tracking/README.md new file mode 100644 index 0000000000000..df99f211f7559 --- /dev/null +++ b/Detectors/MUON/MCH/Tracking/README.md @@ -0,0 +1,135 @@ +<!-- doxy +\page refDetectorsMUONMCHTracking Tracking +/doxy --> + +# TrackExtrap.h(cxx) + +Contains all the tools to: +- extrapolate the track parameters (and covariances) from one z position to another, taking into account or not the +magnetic field. +- add the dispersion from Multiple Coulomb Scattering (MCS) to the covariance matrix when crossing a tracking chamber. +- extrapolate the track parameters (and covariances) through the front absorber, taking into account (or not) the +effects from MCS and energy loss. + +# TrackFitter.h(cxx) + +Fit a track to the clusters attached to it, using the Kalman Filter. + +## Short description of the algorithm + +The seeds for the track parameters and covariances are computed using the position and resolution of the 2 clusters in +the last two fired chambers. An estimate of the bending momentum is obtained by assuming that the track is coming from +the vertex (0,0,0) and crosses a constant magnetic field (both with sufficiently large uncertainties to do not bias the +final result). +The initial track parameters and covariances are then propagated to every clusters, up to the most upstream one, and are +updated at each step by "attaching" the cluster with the Kalman filter. The dispersion from MCS is added to the +covariances each time a chamber is crossed. +This algorithm gives the track parameters and covariances at the first cluster (the last attached one). Optionally, the +Smoother algorithm can be run to fit back the track and compute the track parameters and covariances at every clusters. +If the pointer to the parameters at one of the attached clusters is given, the fit is resumed starting from this point. + +# TrackFinderOriginal.h(cxx) + +This is a reimplementation of the original tracking algorithm from AliRoot. + +## Input / Output + +It takes as input a list of reconstructed clusters per chambers, the clusters' position being given in the global +coordinate system. It returns the list of reconstructed tracks, each of them containing (in the TrackParams) the +pointers to the associated clusters. + +## Short description of the algorithm + +The original tracking algorithm is described in detail here: +https://edms.cern.ch/ui/file/1054937/1/ALICE-INT-2009-044.pdf + +The main difference with the original implementation is in the order the tracking of the initial candidates (made of +clusters in stations 4&5) is performed. In the original implementation, all candidates are propagated to station 3 to +search for compatible clusters, tracks are duplicated to consider all possibilities, then all candidates are propagated +to station 2, and so on. In some events with very high multiplicity, it results in a temporarily huge number of +candidates in memory at the same time (>10000) and a limitation is needed to abort the tracking in such case to do not +break the reconstruction. In the new implementation, each candidate is treated one by one. The current candidate is +propagated to station 3 to search for compatible clusters, duplicated to consider every posibilities, then each of them +is tracked one by one to station 2, then to station 1. This limits drastically the number of candidates in memory at the +same time, thus avoiding to abort the tracking for any event, while reconstructing exactly the same tracks in the end. + +# TrackFinder.h(cxx) + +This is the implementation of the new tracking algorithm. + +## Input / Output + +It takes as input a list of reconstructed clusters mapped per DE, the clusters' position being given in the global +coordinate system. It returns the list of reconstructed tracks, each of them containing (in the TrackParams) the +pointers to the associated clusters. + +## Short description of the algorithm + +### General ideas to improve the original algorithm: +- Consider the overlaps between DE on the same chamber during the tracking (the original algorithm considers only one +cluster per chamber during the tracking, duplicating the tracks with 2 clusters in overlapping DE to consider both), so +there is no need to complete the tracks to add the missing clusters afterward and to cleanup the duplicates. We assume +there is no overlap between the 2 half-planes of chambers 5 to 10. +- Do not try to recover tracks by removing one of the previously attached clusters in the previous station if no +compatible cluster is found in the current one. Assume that a good track will not be lost if several clusters are +attached in a station and some of them are bad (i.e. not belonging to that track). +- Further reduce the number of track duplication and memory consumption by pursuing the tracking of the current +candidate with the newly found compatible clusters down to station 1, or until the tracking fails, before testing other +clusters, so that we duplicate the original candidate only to store valid complete tracks. +- Speedup the cleanup of connected tracks in the end by reducing the number of imbricated loops. +- Speedup the track extrapolation in the magnetic field by reducing the number of steps to reach to desired z position. + +### Algorithm: +- Build candidates on station 5 starting from pairs of clusters on chambers 9 and 10 and looking for compatible clusters +in overlap DE. Consider every combinations of different clusters and discard candidates whose parameters are outside of +acceptance limits within uncertainties. +- Propagate the candidates to station 4 and look for compatible clusters, taking into account overlaps. At least one +cluster is requested and the track is duplicated to consider every possibilities, eliminating the ones driving the track +parameters outside of acceptance limits within uncertainties. +- Repeat the two steps above starting from station 4 then going to station 5 to look for additional candidates with only +one chamber fired on station 5. +- Propagate each candidate found in the previous steps from chamber 6 to 1, looking for compatible clusters taking into +account the overlaps. This is a recursive procedure. For each cluster or couple of clusters found on one chamber, the +current parameters of the initial candidate are updated and the tracking continue to the next chamber, and so on and so +forth, until chamber 1 or until the tracking fails (at least one cluster per station is requested to continue). Only at +the end, when/if the track reaches the first station, it is duplicated and the clusters found in the process are +attached to the new track. Clusters that drive the track parameters outside of acceptance limits within uncertainties +are discarded. +- Improve the tracks: run the smoother to recompute the local chi2 at each cluster, remove the worst cluster if it does +not pass a stricter chi2 cut, refit the track and repeat the procedure until all clusters pass the cut or one of them +cannot be removed (the track must contain at least 1 cluster per station), in which case the track is removed. +- Remove connected tracks in station 3, 4 and 5. If two tracks share at least one cluster in these stations, remove the +one with the smallest number of clusters or with the highest chi2 in case of equality, assuming it is a fake track. + +In all stations, the search for compatible clusters is done in a way to consider every possibilities, i.e. every +combinations of 1 to 4 clusters, while skipping the already tested combinations. This includes subsets of previously +found combinations, so that we always attach the maximum number of clusters to a candidate (e.g. if we can attach 4 +clusters in one station because of the overlaps, we do not consider the possibility to attach only 3, 2, or 1 of them +even if the track would still be valid). + +A more detailed description of the various parts of the algorithm is given in the code itself. + +### Available options: +- Find more track candidates, with only one chamber fired on station 4 and one on station 5, taking into account the +overlaps between DE and excluding those whose parameters are outside of acceptance limits within uncertainties. +- Do not request certain stations. When building initial candidates on stations 4 and 5, it means to keep the candidates +found on station 5(4) even if no compatible cluster is found on station 4(5) if that station is not requested. However, +if one or more compatible clusters are found we do not consider the possibility to do not attach any cluster on that +station. When tracking the candidates to station 3 to 1, it means to consider the possibility to continue the tracking +without attaching any cluster on the station that is not requested, even if compatible clusters are found on that +station. However the clusters found upstream after having attached cluster(s) on that station are skipped. + +## Examples of workflow + +- The line below allows to read the clusters from the file `clusters.in`, run the new tracking algorithm, read the +associated vertex from the file `vertices.in`, extrapolate the tracks to the vertex and write the result (tracks at +vertex, MCH tracks and associated clusters) in the file `tracks.out`: + +`o2-mch-clusters-sampler-workflow --infile "clusters.in" | o2-mch-clusters-to-tracks-workflow --l3Current 29999.998047 --dipoleCurrent 5999.966797 | o2-mch-vertex-sampler-workflow --infile "vertices.in" | o2-mch-tracks-to-tracks-at-vertex-workflow --l3Current 29999.998047 --dipoleCurrent 5999.966797 | o2-mch-tracks-sink-workflow --outfile "tracks.out"` + +- The line below allows to read the MCH tracks and associated clusters from the file `tracks.in`, refit them and write +them in the file `tracks.out`: + +`o2-mch-tracks-sampler-workflow --infile "tracks.in" --forTrackFitter | o2-mch-tracks-to-tracks-workflow --l3Current -30000.025391 --dipoleCurrent -5999.954590 | o2-mch-tracks-sink-workflow --outfile "tracks.out" --mchTracksOnly` + +See the [workflow documentation](../Workflow/README.md) for more details about each individual workflow. diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/Cluster.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/Cluster.h index 076237f3e47e5..d31e907f26c1b 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/Cluster.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/Cluster.h @@ -36,8 +36,8 @@ class Cluster Cluster(const Cluster& cl) = default; Cluster& operator=(const Cluster& cl) = default; - Cluster(Cluster&&) = delete; - Cluster& operator=(Cluster&&) = delete; + Cluster(Cluster&&) = default; + Cluster& operator=(Cluster&&) = default; ClusterStruct getClusterStruct() const; diff --git a/Detectors/MUON/MCH/Tracking/src/TrackExtrap.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackExtrap.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/TrackExtrap.h rename to Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackExtrap.h diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinder.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinder.h similarity index 99% rename from Detectors/MUON/MCH/Tracking/src/TrackFinder.h rename to Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinder.h index c540fee52ccb5..6970810810665 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinder.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinder.h @@ -26,7 +26,7 @@ #include "MCHTracking/Cluster.h" #include "MCHTracking/Track.h" -#include "TrackFitter.h" +#include "MCHTracking/TrackFitter.h" namespace o2 { diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinderOriginal.h similarity index 99% rename from Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.h rename to Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinderOriginal.h index f740959a86268..f2c412c65d0a4 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinderOriginal.h @@ -20,7 +20,7 @@ #include "MCHTracking/Cluster.h" #include "MCHTracking/Track.h" -#include "TrackFitter.h" +#include "MCHTracking/TrackFitter.h" namespace o2 { diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitter.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFitter.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/TrackFitter.h rename to Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFitter.h diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h index 9adec547d5936..267f19f17bb4f 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h @@ -32,6 +32,8 @@ class TrackParam { public: TrackParam() = default; + TrackParam(Double_t z, const Double_t param[5]); + TrackParam(Double_t z, const Double_t param[5], const Double_t cov[15]); ~TrackParam() = default; TrackParam(const TrackParam& tp); @@ -77,6 +79,8 @@ class TrackParam const TMatrixD& getParameters() const { return mParameters; } /// set track parameters void setParameters(const TMatrixD& parameters) { mParameters = parameters; } + /// set track parameters from the array + void setParameters(const Double_t parameters[5]) { mParameters.SetMatrixArray(parameters); } /// add track parameters void addParameters(const TMatrixD& parameters) { mParameters += parameters; } @@ -90,8 +94,8 @@ class TrackParam const TMatrixD& getCovariances() const; void setCovariances(const TMatrixD& covariances); - void setCovariances(const Double_t matrix[5][5]); - void setVariances(const Double_t matrix[5][5]); + void setCovariances(const Double_t covariances[15]); + void setVariances(const Double_t covariances[15]); void deleteCovariances(); const TMatrixD& getPropagator() const; diff --git a/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx deleted file mode 100644 index 4ea61dbb14021..0000000000000 --- a/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.cxx +++ /dev/null @@ -1,379 +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. - -/// \file TrackAtVertexSpec.cxx -/// \brief Implementation of a data processor to extrapolate the tracks to the vertex -/// -/// \author Philippe Pillot, Subatech - -#include "TrackAtVertexSpec.h" - -#include <chrono> -#include <stdexcept> -#include <list> - -#include <TMath.h> -#include <TGeoManager.h> -#include <TGeoGlobalMagField.h> - -#include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/Lifetime.h" -#include "Framework/Output.h" -#include "Framework/Task.h" - -#include "DetectorsBase/GeometryManager.h" -#include "MathUtils/Cartesian.h" -#include "Field/MagneticField.h" -#include "MCHBase/ClusterBlock.h" -#include "MCHBase/TrackBlock.h" -#include "MCHTracking/TrackParam.h" -#include "TrackExtrap.h" - -namespace o2 -{ -namespace mch -{ - -using namespace std; -using namespace o2::framework; - -class TrackAtVertexTask -{ - public: - //_________________________________________________________________________________________________ - void init(framework::InitContext& ic) - { - /// Prepare the track extrapolation tools - - LOG(INFO) << "initializing track extrapolation to vertex"; - - if (!gGeoManager) { - o2::base::GeometryManager::loadGeometry(); - if (!gGeoManager) { - throw runtime_error("cannot load the geometry"); - } - } - - if (!TGeoGlobalMagField::Instance()->GetField()) { - auto l3Current = ic.options().get<float>("l3Current"); - auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); - auto field = o2::field::MagneticField::createFieldMap(l3Current, dipoleCurrent, o2::field::MagneticField::kConvLHC, false, - 3500., "A-A", "$(O2_ROOT)/share/Common/maps/mfchebKGI_sym.root"); - TGeoGlobalMagField::Instance()->SetField(field); - TGeoGlobalMagField::Instance()->Lock(); - TrackExtrap::setField(); - } - - auto stop = [this]() { - LOG(INFO) << "track propagation to vertex duration = " << mElapsedTime.count() << " s"; - }; - ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); - } - - //_________________________________________________________________________________________________ - void run(framework::ProcessingContext& pc) - { - /// read the tracks with attached clusters of the current event, - /// propagate them to the corresponding vertex and send the new version - - // get the vertex - math_utils::Point3D<double> vertex(0., 0., 0.); - int eventVtx = readVertex(pc.inputs().get<gsl::span<char>>("vertex"), vertex); - - // get the tracks - std::list<TrackStruct> tracks{}; - int eventTracks = readTracks(pc.inputs().get<gsl::span<char>>("tracks"), tracks); - - if (eventVtx > -1 && eventVtx != eventTracks) { - throw runtime_error("vertex and tracks are from different events"); - } - - // propagate the tracks to the vertex - auto tStart = std::chrono::high_resolution_clock::now(); - for (auto itTrack = tracks.begin(); itTrack != tracks.end();) { - if (extrapTrackToVertex(*itTrack, vertex)) { - ++itTrack; - } else { - itTrack = tracks.erase(itTrack); - } - } - auto tEnd = std::chrono::high_resolution_clock::now(); - mElapsedTime += tEnd - tStart; - - // calculate the size of the payload for the output message, excluding the event header - int trackSize = getSize(tracks); - - // create the output message - auto msgOut = pc.outputs().make<char>(Output{"MCH", "TRACKSATVERTEX", 0, Lifetime::Timeframe}, 2 * SSizeOfInt + trackSize); - auto bufferPtrOut = msgOut.data(); - - // write the event header - writeHeader(eventTracks, trackSize, bufferPtrOut); - - // write the tracks - if (trackSize > 0) { - writeTracks(tracks, bufferPtrOut); - } - } - - private: - struct TrackStruct { - TrackParamStruct paramAtVertex{}; - double dca = 0.; - double rAbs = 0.; - TrackParamStruct paramAt1stCluster{}; - double chi2 = 0.; - std::vector<ClusterStruct> clusters{}; - }; - - //_________________________________________________________________________________________________ - int readVertex(const gsl::span<const char>& msgIn, math_utils::Point3D<double>& vertex) const - { - /// get the vertex and return the event number - /// throw an exception in case of error - - auto bufferPtr = msgIn.data(); - int size = msgIn.size(); - - if (size != SSizeOfInt + SSizeOfPoint3D) { - throw length_error("incorrect payload size"); - } - - const int& event = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - - vertex = *reinterpret_cast<const math_utils::Point3D<double>*>(bufferPtr); - - return event; - } - - //_________________________________________________________________________________________________ - int readTracks(const gsl::span<const char>& msgIn, std::list<TrackStruct>& tracks) const - { - /// get the tracks and return the event number - /// throw an exception in case of error - - auto bufferPtr = msgIn.data(); - int size = msgIn.size(); - - if (size < 2 * SSizeOfInt) { - throw out_of_range("missing event header"); - } - const int& event = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - int sizeLeft = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - - if (sizeLeft != size - 2 * SSizeOfInt) { - throw length_error("incorrect payload size"); - } - - if (sizeLeft > 0) { - - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing number of tracks"); - } - const int& nTracks = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - for (int iTrack = 0; iTrack < nTracks; ++iTrack) { - - tracks.emplace_back(); - auto& track = tracks.back(); - - if (sizeLeft < SSizeOfTrackParamStruct) { - throw out_of_range("missing track parameters"); - } - track.paramAt1stCluster = *reinterpret_cast<const TrackParamStruct*>(bufferPtr); - bufferPtr += SSizeOfTrackParamStruct; - sizeLeft -= SSizeOfTrackParamStruct; - - if (sizeLeft < SSizeOfDouble) { - throw out_of_range("missing chi2"); - } - track.chi2 = *reinterpret_cast<const double*>(bufferPtr); - bufferPtr += SSizeOfDouble; - sizeLeft -= SSizeOfDouble; - - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing number of clusters"); - } - const int& nClusters = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - for (int iCl = 0; iCl < nClusters; ++iCl) { - - if (sizeLeft < SSizeOfClusterStruct) { - throw out_of_range("missing cluster"); - } - track.clusters.emplace_back(*reinterpret_cast<const ClusterStruct*>(bufferPtr)); - bufferPtr += SSizeOfClusterStruct; - sizeLeft -= SSizeOfClusterStruct; - } - } - - if (sizeLeft != 0) { - throw length_error("incorrect payload size"); - } - } - - return event; - } - - //_________________________________________________________________________________________________ - bool extrapTrackToVertex(TrackStruct& track, math_utils::Point3D<double>& vertex) - { - /// compute the track parameters at vertex, at DCA and at the end of the absorber - - // convert parameters at first cluster in internal format - TrackParam trackParam; - trackParam.setNonBendingCoor(track.paramAt1stCluster.x); - trackParam.setBendingCoor(track.paramAt1stCluster.y); - trackParam.setZ(track.paramAt1stCluster.z); - trackParam.setNonBendingSlope(track.paramAt1stCluster.px / track.paramAt1stCluster.pz); - trackParam.setBendingSlope(track.paramAt1stCluster.py / track.paramAt1stCluster.pz); - trackParam.setInverseBendingMomentum(track.paramAt1stCluster.sign / TMath::Sqrt(track.paramAt1stCluster.py * track.paramAt1stCluster.py + track.paramAt1stCluster.pz * track.paramAt1stCluster.pz)); - - // extrapolate to vertex - TrackParam trackParamAtVertex(trackParam); - if (!TrackExtrap::extrapToVertex(&trackParamAtVertex, vertex.x(), vertex.y(), vertex.z(), 0., 0.)) { - return false; - } - track.paramAtVertex.x = trackParamAtVertex.getNonBendingCoor(); - track.paramAtVertex.y = trackParamAtVertex.getBendingCoor(); - track.paramAtVertex.z = trackParamAtVertex.getZ(); - track.paramAtVertex.px = trackParamAtVertex.px(); - track.paramAtVertex.py = trackParamAtVertex.py(); - track.paramAtVertex.pz = trackParamAtVertex.pz(); - track.paramAtVertex.sign = trackParamAtVertex.getCharge(); - - // extrapolate to DCA - TrackParam trackParamAtDCA(trackParam); - if (!TrackExtrap::extrapToVertexWithoutBranson(&trackParamAtDCA, vertex.z())) { - return false; - } - double dcaX = trackParamAtDCA.getNonBendingCoor() - vertex.x(); - double dcaY = trackParamAtDCA.getBendingCoor() - vertex.y(); - track.dca = TMath::Sqrt(dcaX * dcaX + dcaY * dcaY); - - // extrapolate to the end of the absorber - if (!TrackExtrap::extrapToZ(&trackParam, -505.)) { - return false; - } - double xAbs = trackParam.getNonBendingCoor(); - double yAbs = trackParam.getBendingCoor(); - track.rAbs = TMath::Sqrt(xAbs * xAbs + yAbs * yAbs); - - return true; - } - - //_________________________________________________________________________________________________ - int getSize(const std::list<TrackStruct>& tracks) - { - /// calculate the total number of bytes requested to store the tracks - - int size(0); - for (const auto& track : tracks) { - size += 2 * SSizeOfTrackParamStruct + 3 * SSizeOfDouble + SSizeOfInt + track.clusters.size() * SSizeOfClusterStruct; - } - if (size > 0) { - size += SSizeOfInt; - } - - return size; - } - - //_________________________________________________________________________________________________ - void writeHeader(int event, int trackSize, char*& bufferPtr) const - { - /// write header informations in the output buffer and move the buffer ptr - - // write the event number - memcpy(bufferPtr, &event, SSizeOfInt); - bufferPtr += SSizeOfInt; - - // write the size of the payload - memcpy(bufferPtr, &trackSize, SSizeOfInt); - bufferPtr += SSizeOfInt; - } - - //_________________________________________________________________________________________________ - void writeTracks(const std::list<TrackStruct>& tracks, char*& bufferPtr) const - { - /// write the track informations in the buffer and move the buffer ptr - - // write the number of tracks - int nTracks = tracks.size(); - memcpy(bufferPtr, &nTracks, SSizeOfInt); - bufferPtr += SSizeOfInt; - - for (const auto& track : tracks) { - - // write track parameters at vertex - memcpy(bufferPtr, &(track.paramAtVertex), SSizeOfTrackParamStruct); - bufferPtr += SSizeOfTrackParamStruct; - - // write dca - memcpy(bufferPtr, &(track.dca), SSizeOfDouble); - bufferPtr += SSizeOfDouble; - - // write rAbs - memcpy(bufferPtr, &(track.rAbs), SSizeOfDouble); - bufferPtr += SSizeOfDouble; - - // write track parameters at first cluster - memcpy(bufferPtr, &(track.paramAt1stCluster), SSizeOfTrackParamStruct); - bufferPtr += SSizeOfTrackParamStruct; - - // write track chi2 - memcpy(bufferPtr, &(track.chi2), SSizeOfDouble); - bufferPtr += SSizeOfDouble; - - // write the number of clusters - int nClusters = track.clusters.size(); - memcpy(bufferPtr, &nClusters, SSizeOfInt); - bufferPtr += SSizeOfInt; - - // write clusters - for (const auto& cluster : track.clusters) { - memcpy(bufferPtr, &cluster, SSizeOfClusterStruct); - bufferPtr += SSizeOfClusterStruct; - } - } - } - - static constexpr int SSizeOfInt = sizeof(int); - static constexpr int SSizeOfDouble = sizeof(double); - static constexpr int SSizeOfTrackParamStruct = sizeof(TrackParamStruct); - static constexpr int SSizeOfClusterStruct = sizeof(ClusterStruct); - static constexpr int SSizeOfPoint3D = sizeof(math_utils::Point3D<double>); - - std::chrono::duration<double> mElapsedTime{}; ///< timer -}; - -//_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getTrackAtVertexSpec() -{ - return DataProcessorSpec{ - "TrackAtVertex", - Inputs{InputSpec{"vertex", "MCH", "VERTEX", 0, Lifetime::Timeframe}, - InputSpec{"tracks", "MCH", "TRACKS", 0, Lifetime::Timeframe}}, - Outputs{OutputSpec{"MCH", "TRACKSATVERTEX", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask<TrackAtVertexTask>()}, - Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, - {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}}}; -} - -} // namespace mch -} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackExtrap.cxx b/Detectors/MUON/MCH/Tracking/src/TrackExtrap.cxx index 38424a5b43a51..9fe21ca5a455f 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackExtrap.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackExtrap.cxx @@ -13,7 +13,7 @@ /// /// \author Philippe Pillot, Subatech -#include "TrackExtrap.h" +#include "MCHTracking/TrackExtrap.h" #include <TGeoGlobalMagField.h> #include <TGeoManager.h> diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx index 73395f545e7e3..c5db52bf5246c 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx @@ -13,7 +13,7 @@ /// /// \author Philippe Pillot, Subatech -#include "TrackFinder.h" +#include "MCHTracking/TrackFinder.h" #include <cassert> #include <iostream> @@ -24,7 +24,7 @@ #include <TMath.h> #include "Field/MagneticField.h" -#include "TrackExtrap.h" +#include "MCHTracking/TrackExtrap.h" namespace o2 { diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx index 704f3c068d77d..2af108313e62d 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx @@ -13,7 +13,7 @@ /// /// \author Philippe Pillot, Subatech -#include "TrackFinderOriginal.h" +#include "MCHTracking/TrackFinderOriginal.h" #include <iostream> #include <stdexcept> @@ -23,7 +23,7 @@ #include <TMath.h> #include "Field/MagneticField.h" -#include "TrackExtrap.h" +#include "MCHTracking/TrackExtrap.h" namespace o2 { diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx deleted file mode 100644 index faf2ae3de8d15..0000000000000 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.cxx +++ /dev/null @@ -1,243 +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. - -/// \file TrackFinderOriginalSpec.cxx -/// \brief Implementation of a data processor to read clusters, reconstruct tracks and send them -/// -/// \author Philippe Pillot, Subatech - -#include "Framework/ConfigParamRegistry.h" -#include "TrackFinderOriginalSpec.h" - -#include <chrono> -#include <list> -#include <stdexcept> - -#include "Framework/CallbackService.h" -#include "Framework/ControlService.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/Lifetime.h" -#include "Framework/Output.h" -#include "Framework/Task.h" -#include "Framework/Logger.h" - -#include "MCHBase/ClusterBlock.h" -#include "MCHBase/TrackBlock.h" -#include "MCHTracking/TrackParam.h" -#include "MCHTracking/Cluster.h" -#include "MCHTracking/Track.h" -#include "TrackFinderOriginal.h" - -namespace o2 -{ -namespace mch -{ - -using namespace std; -using namespace o2::framework; - -class TrackFinderTask -{ - public: - //_________________________________________________________________________________________________ - void init(framework::InitContext& ic) - { - /// Prepare the track extrapolation tools - - LOG(INFO) << "initializing track finder"; - - auto l3Current = ic.options().get<float>("l3Current"); - auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); - mTrackFinder.init(l3Current, dipoleCurrent); - - auto moreCandidates = ic.options().get<bool>("moreCandidates"); - mTrackFinder.findMoreTrackCandidates(moreCandidates); - - auto debugLevel = ic.options().get<int>("debug"); - mTrackFinder.debug(debugLevel); - - auto stop = [this]() { - mTrackFinder.printStats(); - mTrackFinder.printTimers(); - LOG(INFO) << "tracking duration = " << mElapsedTime.count() << " s"; - }; - ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); - } - - //_________________________________________________________________________________________________ - void run(framework::ProcessingContext& pc) - { - /// read the clusters of the current event, find tracks and send them - - // get the input buffer - auto msgIn = pc.inputs().get<gsl::span<char>>("clusters"); - auto bufferPtr = msgIn.data(); - int sizeLeft = msgIn.size(); - - // get the event number - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing event header"); - } - const int& event = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - // get the input clusters - std::array<std::list<Cluster>, 10> clusters{}; - readClusters(bufferPtr, sizeLeft, clusters); - - // run the track finder - auto tStart = std::chrono::high_resolution_clock::now(); - const auto& tracks = mTrackFinder.findTracks(&clusters); - auto tEnd = std::chrono::high_resolution_clock::now(); - mElapsedTime += tEnd - tStart; - - // calculate the size of the payload for the output message, excluding the event header - int trackSize = getSize(tracks); - - // create the output message - auto msgOut = pc.outputs().make<char>(Output{"MCH", "TRACKS", 0, Lifetime::Timeframe}, SHeaderSize + trackSize); - auto bufferPtrOut = msgOut.data(); - - // write the event header - writeHeader(event, trackSize, bufferPtrOut); - - // write the tracks - if (trackSize > 0) { - writeTracks(tracks, bufferPtrOut); - } - } - - private: - //_________________________________________________________________________________________________ - void readClusters(const char*& bufferPtr, int& sizeLeft, std::array<std::list<Cluster>, 10>& clusters) - { - /// read the cluster informations from the buffer - /// move the buffer ptr and decrease the size left - /// throw an exception in case of error - - // read the number of clusters - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing number of clusters"); - } - const int& nClusters = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - for (int iCl = 0; iCl < nClusters; ++iCl) { - - // read cluster info - if (sizeLeft < SSizeOfClusterStruct) { - throw out_of_range("missing cluster"); - } - const auto cluster = reinterpret_cast<const ClusterStruct*>(bufferPtr); - clusters[cluster->getChamberId()].emplace_back(*cluster); - bufferPtr += SSizeOfClusterStruct; - sizeLeft -= SSizeOfClusterStruct; - } - - if (sizeLeft != 0) { - throw length_error("incorrect payload"); - } - } - - //_________________________________________________________________________________________________ - int getSize(const std::list<Track>& tracks) - { - /// calculate the total number of bytes requested to store the tracks - - int size(0); - for (const auto& track : tracks) { - size += SSizeOfTrackParamStruct + SSizeOfDouble + SSizeOfInt + track.getNClusters() * SSizeOfClusterStruct; - } - if (size > 0) { - size += SSizeOfInt; - } - - return size; - } - - //_________________________________________________________________________________________________ - void writeHeader(int event, int trackSize, char*& bufferPtr) const - { - /// write header informations in the output buffer and move the buffer ptr - - // write the event number - memcpy(bufferPtr, &event, SSizeOfInt); - bufferPtr += SSizeOfInt; - - // write the size of the payload - memcpy(bufferPtr, &trackSize, SSizeOfInt); - bufferPtr += SSizeOfInt; - } - - //_________________________________________________________________________________________________ - void writeTracks(const std::list<Track>& tracks, char*& bufferPtr) const - { - /// write the track informations in the buffer and move the buffer ptr - - // write the number of tracks - int nTracks = tracks.size(); - memcpy(bufferPtr, &nTracks, SSizeOfInt); - bufferPtr += SSizeOfInt; - - for (const auto& track : tracks) { - - // write track parameters - TrackParamStruct paramStruct = track.first().getTrackParamStruct(); - memcpy(bufferPtr, ¶mStruct, SSizeOfTrackParamStruct); - bufferPtr += SSizeOfTrackParamStruct; - - // write track chi2 - double chi2 = track.first().getTrackChi2(); - memcpy(bufferPtr, &chi2, SSizeOfDouble); - bufferPtr += SSizeOfDouble; - - // write the number of clusters - int nClusters = track.getNClusters(); - memcpy(bufferPtr, &nClusters, SSizeOfInt); - bufferPtr += SSizeOfInt; - - for (const auto& param : track) { - - // write cluster info - ClusterStruct clusterStruct = param.getClusterPtr()->getClusterStruct(); - memcpy(bufferPtr, &clusterStruct, SSizeOfClusterStruct); - bufferPtr += SSizeOfClusterStruct; - } - } - } - - static constexpr int SSizeOfInt = sizeof(int); - static constexpr int SSizeOfDouble = sizeof(double); - static constexpr int SHeaderSize = 2 * SSizeOfInt; - static constexpr int SSizeOfClusterStruct = sizeof(ClusterStruct); - static constexpr int SSizeOfTrackParamStruct = sizeof(TrackParamStruct); - - TrackFinderOriginal mTrackFinder{}; ///< track finder - std::chrono::duration<double> mElapsedTime{}; ///< timer -}; - -//_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getTrackFinderOriginalSpec() -{ - return DataProcessorSpec{ - "TrackFinderOriginal", - Inputs{InputSpec{"clusters", "MCH", "CLUSTERS", 0, Lifetime::Timeframe}}, - Outputs{OutputSpec{"MCH", "TRACKS", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask<TrackFinderTask>()}, - Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, - {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}, - {"moreCandidates", VariantType::Bool, false, {"Find more track candidates"}}, - {"debug", VariantType::Int, 0, {"debug level"}}}}; -} - -} // namespace mch -} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx deleted file mode 100644 index 68da3ac602722..0000000000000 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx +++ /dev/null @@ -1,244 +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. - -/// \file TrackFinderSpec.cxx -/// \brief Implementation of a data processor to read clusters, reconstruct tracks and send them -/// -/// \author Philippe Pillot, Subatech - -#include "TrackFinderSpec.h" - -#include <chrono> -#include <unordered_map> -#include <list> -#include <stdexcept> - -#include "Framework/CallbackService.h" -#include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/Lifetime.h" -#include "Framework/Output.h" -#include "Framework/Task.h" -#include "Framework/Logger.h" - -#include "MCHBase/ClusterBlock.h" -#include "MCHBase/TrackBlock.h" -#include "MCHTracking/TrackParam.h" -#include "MCHTracking/Cluster.h" -#include "MCHTracking/Track.h" -#include "TrackFinder.h" - -namespace o2 -{ -namespace mch -{ - -using namespace std; -using namespace o2::framework; - -class TrackFinderTask -{ - public: - //_________________________________________________________________________________________________ - void init(framework::InitContext& ic) - { - /// Prepare the track extrapolation tools - - LOG(INFO) << "initializing track finder"; - - auto l3Current = ic.options().get<float>("l3Current"); - auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); - mTrackFinder.init(l3Current, dipoleCurrent); - - auto moreCandidates = ic.options().get<bool>("moreCandidates"); - mTrackFinder.findMoreTrackCandidates(moreCandidates); - - auto debugLevel = ic.options().get<int>("debug"); - mTrackFinder.debug(debugLevel); - - auto stop = [this]() { - mTrackFinder.printStats(); - mTrackFinder.printTimers(); - LOG(INFO) << "tracking duration = " << mElapsedTime.count() << " s"; - }; - ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); - } - - //_________________________________________________________________________________________________ - void run(framework::ProcessingContext& pc) - { - /// read the clusters of the current event, find tracks and send them - - // get the input buffer - auto msgIn = pc.inputs().get<gsl::span<char>>("clusters"); - auto bufferPtr = msgIn.data(); - int sizeLeft = msgIn.size(); - - // get the event number - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing event header"); - } - const int& event = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - // get the input clusters - std::unordered_map<int, std::list<Cluster>> clusters{}; - readClusters(bufferPtr, sizeLeft, clusters); - - // run the track finder - auto tStart = std::chrono::high_resolution_clock::now(); - const auto& tracks = mTrackFinder.findTracks(clusters); - auto tEnd = std::chrono::high_resolution_clock::now(); - mElapsedTime += tEnd - tStart; - - // calculate the size of the payload for the output message, excluding the event header - int trackSize = getSize(tracks); - - // create the output message - auto msgOut = pc.outputs().make<char>(Output{"MCH", "TRACKS", 0, Lifetime::Timeframe}, SHeaderSize + trackSize); - auto bufferPtrOut = msgOut.data(); - - // write the event header - writeHeader(event, trackSize, bufferPtrOut); - - // write the tracks - if (trackSize > 0) { - writeTracks(tracks, bufferPtrOut); - } - } - - private: - //_________________________________________________________________________________________________ - void readClusters(const char*& bufferPtr, int& sizeLeft, std::unordered_map<int, std::list<Cluster>>& clusters) - { - /// read the cluster informations from the buffer - /// move the buffer ptr and decrease the size left - /// throw an exception in case of error - - // read the number of clusters - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing number of clusters"); - } - const int& nClusters = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - for (int iCl = 0; iCl < nClusters; ++iCl) { - - // read cluster info - if (sizeLeft < SSizeOfClusterStruct) { - throw out_of_range("missing cluster"); - } - const auto cluster = reinterpret_cast<const ClusterStruct*>(bufferPtr); - clusters[cluster->getDEId()].emplace_back(*cluster); - bufferPtr += SSizeOfClusterStruct; - sizeLeft -= SSizeOfClusterStruct; - } - - if (sizeLeft != 0) { - throw length_error("incorrect payload"); - } - } - - //_________________________________________________________________________________________________ - int getSize(const std::list<Track>& tracks) - { - /// calculate the total number of bytes requested to store the tracks - - int size(0); - for (const auto& track : tracks) { - size += SSizeOfTrackParamStruct + SSizeOfDouble + SSizeOfInt + track.getNClusters() * SSizeOfClusterStruct; - } - if (size > 0) { - size += SSizeOfInt; - } - - return size; - } - - //_________________________________________________________________________________________________ - void writeHeader(int event, int trackSize, char*& bufferPtr) const - { - /// write header informations in the output buffer and move the buffer ptr - - // write the event number - memcpy(bufferPtr, &event, SSizeOfInt); - bufferPtr += SSizeOfInt; - - // write the size of the payload - memcpy(bufferPtr, &trackSize, SSizeOfInt); - bufferPtr += SSizeOfInt; - } - - //_________________________________________________________________________________________________ - void writeTracks(const std::list<Track>& tracks, char*& bufferPtr) const - { - /// write the track informations in the buffer and move the buffer ptr - - // write the number of tracks - int nTracks = tracks.size(); - memcpy(bufferPtr, &nTracks, SSizeOfInt); - bufferPtr += SSizeOfInt; - - for (const auto& track : tracks) { - - // write track parameters - TrackParamStruct paramStruct = track.first().getTrackParamStruct(); - memcpy(bufferPtr, ¶mStruct, SSizeOfTrackParamStruct); - bufferPtr += SSizeOfTrackParamStruct; - - // write track chi2 - double chi2 = track.first().getTrackChi2(); - memcpy(bufferPtr, &chi2, SSizeOfDouble); - bufferPtr += SSizeOfDouble; - - // write the number of clusters - int nClusters = track.getNClusters(); - memcpy(bufferPtr, &nClusters, SSizeOfInt); - bufferPtr += SSizeOfInt; - - for (const auto& param : track) { - - // write cluster info - ClusterStruct clusterStruct = param.getClusterPtr()->getClusterStruct(); - memcpy(bufferPtr, &clusterStruct, SSizeOfClusterStruct); - bufferPtr += SSizeOfClusterStruct; - } - } - } - - static constexpr int SSizeOfInt = sizeof(int); - static constexpr int SSizeOfDouble = sizeof(double); - static constexpr int SHeaderSize = 2 * SSizeOfInt; - static constexpr int SSizeOfClusterStruct = sizeof(ClusterStruct); - static constexpr int SSizeOfTrackParamStruct = sizeof(TrackParamStruct); - - TrackFinder mTrackFinder{}; ///< track finder - std::chrono::duration<double> mElapsedTime{}; ///< timer -}; - -//_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getTrackFinderSpec() -{ - return DataProcessorSpec{ - "TrackFinder", - Inputs{InputSpec{"clusters", "MCH", "CLUSTERS", 0, Lifetime::Timeframe}}, - Outputs{OutputSpec{"MCH", "TRACKS", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask<TrackFinderTask>()}, - Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, - {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}, - {"moreCandidates", VariantType::Bool, false, {"Find more track candidates"}}, - {"debug", VariantType::Int, 0, {"debug level"}}}}; -} - -} // namespace mch -} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx index 0052bee51abfa..c845c2b8279cb 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx @@ -13,7 +13,7 @@ /// /// \author Philippe Pillot, Subatech -#include "TrackFitter.h" +#include "MCHTracking/TrackFitter.h" #include <stdexcept> @@ -21,7 +21,7 @@ #include <TMatrixD.h> #include "Field/MagneticField.h" -#include "TrackExtrap.h" +#include "MCHTracking/TrackExtrap.h" namespace o2 { diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx deleted file mode 100644 index bcaedac5499d8..0000000000000 --- a/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.cxx +++ /dev/null @@ -1,220 +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. - -/// \file TrackFitterSpec.cxx -/// \brief Implementation of a data processor to read, refit and send tracks with attached clusters -/// -/// \author Philippe Pillot, Subatech - -#include "TrackFitterSpec.h" - -#include <stdexcept> -#include <list> - -#include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/Lifetime.h" -#include "Framework/Output.h" -#include "Framework/Task.h" -#include "Framework/Logger.h" - -#include "MCHBase/ClusterBlock.h" -#include "MCHBase/TrackBlock.h" -#include "MCHTracking/TrackParam.h" -#include "MCHTracking/Cluster.h" -#include "MCHTracking/Track.h" -#include "TrackFitter.h" - -namespace o2 -{ -namespace mch -{ - -using namespace std; -using namespace o2::framework; - -class TrackFitterTask -{ - public: - //_________________________________________________________________________________________________ - void init(framework::InitContext& ic) - { - /// Prepare the track extrapolation tools - LOG(INFO) << "initializing track fitter"; - auto l3Current = ic.options().get<float>("l3Current"); - auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); - mTrackFitter.initField(l3Current, dipoleCurrent); - mTrackFitter.smoothTracks(true); - } - - //_________________________________________________________________________________________________ - void run(framework::ProcessingContext& pc) - { - /// read the tracks with attached clusters of the current event, - /// refit them and send the new version - - // get the input buffer - auto msgIn = pc.inputs().get<gsl::span<char>>("tracks"); - auto bufferPtr = msgIn.data(); - int sizeLeft = msgIn.size(); - - // create the output message - auto msgOut = pc.outputs().make<char>(Output{"MCH", "REFITTRACKS", 0, Lifetime::Timeframe}, sizeLeft); - auto bufferPtrOut = msgOut.data(); - - // copy header info - copyHeader(bufferPtr, sizeLeft, bufferPtrOut); - - // get the number of tracks and copy it to the output message - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing number of tracks"); - } - const int& nTracks = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - memcpy(bufferPtrOut, &nTracks, SSizeOfInt); - bufferPtrOut += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - std::list<Cluster> clusters{}; - for (int iTrack = 0; iTrack < nTracks; ++iTrack) { - - // get the input track - Track track{}; - readTrack(bufferPtr, sizeLeft, track, clusters); - - // refit the track - try { - mTrackFitter.fit(track); - } catch (exception const& e) { - throw std::runtime_error(std::string("Track fit failed: ") + e.what()); - } - - // write the refitted track to the ouput message - writeTrack(track, bufferPtrOut); - } - - if (sizeLeft != 0) { - throw length_error("incorrect payload"); - } - } - - private: - //_________________________________________________________________________________________________ - void copyHeader(const char*& bufferPtr, int& sizeLeft, char*& bufferPtrOut) const - { - /// copy header informations from the input buffer to the output message - /// move the buffer ptr and decrease the size left - /// throw an exception in case of error - - if (sizeLeft < SHeaderSize) { - throw out_of_range("missing event header"); - } - - const int& event = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - memcpy(bufferPtrOut, &event, SSizeOfInt); - bufferPtrOut += SSizeOfInt; - - const int& size = *reinterpret_cast<const int*>(bufferPtr); - bufferPtr += SSizeOfInt; - memcpy(bufferPtrOut, &size, SSizeOfInt); - bufferPtrOut += SSizeOfInt; - - sizeLeft -= SHeaderSize; - if (sizeLeft != size) { - throw length_error("incorrect payload size"); - } - } - - //_________________________________________________________________________________________________ - void readTrack(const char*& bufferPtr, int& sizeLeft, Track& track, std::list<Cluster>& clusters) const - { - /// read the track informations from the buffer - /// move the buffer ptr and decrease the size left - /// throw an exception in case of error - - // skip the track parameters - if (sizeLeft < SSizeOfTrackParamStruct) { - throw out_of_range("missing track parameters"); - } - bufferPtr += SSizeOfTrackParamStruct; - sizeLeft -= SSizeOfTrackParamStruct; - - // read number of clusters - if (sizeLeft < SSizeOfInt) { - throw out_of_range("missing number of clusters"); - } - const int& nClusters = *reinterpret_cast<const int*>(bufferPtr); - if (nClusters > 20) { - throw length_error("too many (>20) clusters attached to the track"); - } - bufferPtr += SSizeOfInt; - sizeLeft -= SSizeOfInt; - - for (int iCl = 0; iCl < nClusters; ++iCl) { - - // read cluster info - if (sizeLeft < SSizeOfClusterStruct) { - throw out_of_range("missing cluster"); - } - clusters.emplace_back(*reinterpret_cast<const ClusterStruct*>(bufferPtr)); - track.createParamAtCluster(clusters.back()); - bufferPtr += SSizeOfClusterStruct; - sizeLeft -= SSizeOfClusterStruct; - } - } - - //_________________________________________________________________________________________________ - void writeTrack(Track& track, char*& bufferPtrOut) const - { - /// write the track informations to the buffer and move the buffer ptr - - // fill track parameters - TrackParamStruct paramStruct = track.first().getTrackParamStruct(); - memcpy(bufferPtrOut, ¶mStruct, SSizeOfTrackParamStruct); - bufferPtrOut += SSizeOfTrackParamStruct; - - // fill number of clusters - int nClusters = track.getNClusters(); - memcpy(bufferPtrOut, &nClusters, SSizeOfInt); - bufferPtrOut += SSizeOfInt; - - for (const auto& param : track) { - - // fill cluster info - ClusterStruct clusterStruct = param.getClusterPtr()->getClusterStruct(); - memcpy(bufferPtrOut, &clusterStruct, SSizeOfClusterStruct); - bufferPtrOut += SSizeOfClusterStruct; - } - } - - static constexpr int SSizeOfInt = sizeof(int); - static constexpr int SHeaderSize = 2 * SSizeOfInt; - static constexpr int SSizeOfTrackParamStruct = sizeof(TrackParamStruct); - static constexpr int SSizeOfClusterStruct = sizeof(ClusterStruct); - - TrackFitter mTrackFitter{}; ///< track fitter -}; - -//_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getTrackFitterSpec() -{ - return DataProcessorSpec{ - "TrackFitter", - Inputs{InputSpec{"tracks", "MCH", "TRACKS", 0, Lifetime::Timeframe}}, - Outputs{OutputSpec{"MCH", "REFITTRACKS", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask<TrackFitterTask>()}, - Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, - {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}}}; -} - -} // namespace mch -} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx b/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx index 95a353d14e6ea..b445f660f7178 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackParam.cxx @@ -31,6 +31,21 @@ namespace mch using namespace std; +//_________________________________________________________________________ +TrackParam::TrackParam(Double_t z, const Double_t param[5]) : mZ(z) +{ + /// constructor with given parameters + setParameters(param); +} + +//_________________________________________________________________________ +TrackParam::TrackParam(Double_t z, const Double_t param[5], const Double_t cov[15]) : mZ(z) +{ + /// constructor with given parameters and covariances + setParameters(param); + setCovariances(cov); +} + //_________________________________________________________________________ TrackParam::TrackParam(const TrackParam& tp) : mZ(tp.mZ), @@ -161,7 +176,7 @@ Double_t TrackParam::px() const /// return p_x from track parameters Double_t pZ; if (TMath::Abs(mParameters(4, 0)) > 0) { - Double_t pYZ = (TMath::Abs(mParameters(4, 0)) > 0) ? TMath::Abs(1.0 / mParameters(4, 0)) : FLT_MAX; + Double_t pYZ = TMath::Abs(1.0 / mParameters(4, 0)); pZ = -pYZ / (TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0))); // spectro. (z<0) } else { pZ = -FLT_MAX / TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0) + mParameters(1, 0) * mParameters(1, 0)); @@ -175,7 +190,7 @@ Double_t TrackParam::py() const /// return p_y from track parameters Double_t pZ; if (TMath::Abs(mParameters(4, 0)) > 0) { - Double_t pYZ = (TMath::Abs(mParameters(4, 0)) > 0) ? TMath::Abs(1.0 / mParameters(4, 0)) : FLT_MAX; + Double_t pYZ = TMath::Abs(1.0 / mParameters(4, 0)); pZ = -pYZ / (TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0))); // spectro. (z<0) } else { pZ = -FLT_MAX / TMath::Sqrt(1.0 + mParameters(3, 0) * mParameters(3, 0) + mParameters(1, 0) * mParameters(1, 0)); @@ -231,26 +246,40 @@ void TrackParam::setCovariances(const TMatrixD& covariances) } //__________________________________________________________________________ -void TrackParam::setCovariances(const Double_t matrix[5][5]) +void TrackParam::setCovariances(const Double_t covariances[15]) { - /// Set the covariance matrix - if (mCovariances) { - mCovariances->SetMatrixArray(&(matrix[0][0])); - } else { - mCovariances = std::make_unique<TMatrixD>(5, 5, &(matrix[0][0])); + /// Set the covariance matrix from the reduced matrix formated as follow: <pre> + /// [0] = <X,X> + /// [1] = <SlopeX,X> [2] = <SlopeX,SlopeX> + /// [3] = <Y,X> [4] = <Y,SlopeX> [5] = <Y,Y> + /// [6] = <SlopeY,X> [7] = <SlopeY,SlopeX> [8] = <SlopeY,Y> [9] = <SlopeY,SlopeY> + /// [10]= <q/pYZ,X> [11]= <q/pYZ,SlopeX> [12]= <q/pYZ,Y> [13]= <q/pYZ,SlopeY> [14]= <q/pYZ,q/pYZ> </pre> + if (!mCovariances) { + mCovariances = std::make_unique<TMatrixD>(5, 5); + } + for (Int_t i = 0; i < 5; i++) { + for (Int_t j = 0; j <= i; j++) { + (*mCovariances)(i, j) = (*mCovariances)(j, i) = covariances[i * (i + 1) / 2 + j]; + } } } //__________________________________________________________________________ -void TrackParam::setVariances(const Double_t matrix[5][5]) +void TrackParam::setVariances(const Double_t covariances[15]) { - /// Set the diagonal terms of the covariance matrix (variances) + /// Set the diagonal terms of the covariance matrix (variances) from the reduced matrix formated as follow: <pre> + /// [0] = <X,X> + /// [1] = <SlopeX,X> [2] = <SlopeX,SlopeX> + /// [3] = <Y,X> [4] = <Y,SlopeX> [5] = <Y,Y> + /// [6] = <SlopeY,X> [7] = <SlopeY,SlopeX> [8] = <SlopeY,Y> [9] = <SlopeY,SlopeY> + /// [10]= <q/pYZ,X> [11]= <q/pYZ,SlopeX> [12]= <q/pYZ,Y> [13]= <q/pYZ,SlopeY> [14]= <q/pYZ,q/pYZ> </pre> + static constexpr int varIdx[5] = {0, 2, 5, 9, 14}; if (!mCovariances) { mCovariances = std::make_unique<TMatrixD>(5, 5); } mCovariances->Zero(); for (Int_t i = 0; i < 5; i++) { - (*mCovariances)(i, i) = matrix[i][i]; + (*mCovariances)(i, i) = covariances[varIdx[i]]; } } diff --git a/Detectors/MUON/MCH/Workflow/CMakeLists.txt b/Detectors/MUON/MCH/Workflow/CMakeLists.txt index 45483c603ba46..80022eab2b4de 100644 --- a/Detectors/MUON/MCH/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MCH/Workflow/CMakeLists.txt @@ -12,8 +12,9 @@ o2_add_library(MCHWorkflow SOURCES src/DataDecoderSpec.cxx src/PreClusterFinderSpec.cxx src/ClusterFinderOriginalSpec.cxx TARGETVARNAME targetName PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::MCHRawDecoder Boost::program_options - O2::MCHRawImplHelpers RapidJSON::RapidJSON O2::MCHMappingInterface O2::MCHPreClustering - O2::MCHMappingImpl4 O2::MCHRawElecMap O2::MCHBase O2::MCHClustering) + O2::MCHRawImplHelpers RapidJSON::RapidJSON O2::MCHMappingInterface + O2::MCHPreClustering O2::MCHMappingImpl4 O2::MCHRawElecMap O2::MCHBase + O2::MCHClustering) o2_add_executable( cru-page-reader-workflow @@ -68,3 +69,51 @@ o2_add_executable( SOURCES src/ClusterSinkSpec.cxx src/clusters-sink-workflow.cxx COMPONENT_NAME mch PUBLIC_LINK_LIBRARIES O2::MCHWorkflow) + +o2_add_executable( + clusters-sampler-workflow + SOURCES src/ClusterSamplerSpec.cxx src/clusters-sampler-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework O2::MCHBase) + +o2_add_executable( + clusters-to-tracks-original-workflow + SOURCES src/TrackFinderOriginalSpec.cxx src/clusters-to-tracks-original-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHTracking) + +o2_add_executable( + clusters-to-tracks-workflow + SOURCES src/TrackFinderSpec.cxx src/clusters-to-tracks-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHTracking) + +o2_add_executable( + vertex-sampler-workflow + SOURCES src/VertexSamplerSpec.cxx src/vertex-sampler-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework) + +o2_add_executable( + tracks-to-tracks-at-vertex-workflow + SOURCES src/TrackAtVertexSpec.cxx src/tracks-to-tracks-at-vertex-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::DataFormatsMCH O2::MCHTracking) + +o2_add_executable( + tracks-sink-workflow + SOURCES src/TrackSinkSpec.cxx src/tracks-sink-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHBase) + +o2_add_executable( + tracks-sampler-workflow + SOURCES src/TrackSamplerSpec.cxx src/tracks-sampler-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHBase) + +o2_add_executable( + tracks-to-tracks-workflow + SOURCES src/TrackFitterSpec.cxx src/tracks-to-tracks-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHTracking) diff --git a/Detectors/MUON/MCH/Workflow/README.md b/Detectors/MUON/MCH/Workflow/README.md index 4fa24678409c0..8b167b4631a63 100644 --- a/Detectors/MUON/MCH/Workflow/README.md +++ b/Detectors/MUON/MCH/Workflow/README.md @@ -26,3 +26,136 @@ where the `file-reader.cfg` looks like this: dataOrigin = MCH dataDescription = RAWDATA filePath = /home/data/data-de819-ped-raw.raw + +## Cluster sampler + +`o2-mch-clusters-sampler-workflow --infile "clusters.in"` + +where `clusters.in` is a binary file containing for each event: +> number of clusters (int)<br> +> number of associated digits (int)<br> +> list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h))<br> +> list of associated digits ([Digit](../Base/include/MCHBase/Digit.h))<br> + +Send the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data +description "CLUSTERS". + +## Original track finder + +`o2-mch-clusters-to-tracks-original-workflow` + +Take as input the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with +the data description "CLUSTERS" and send the list of MCH tracks +([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated +clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description +"TRACKS" and "TRACKCLUSTERS", respectively. + +Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to +set the magnetic field. + +Option `--moreCandidates` allows to enable the search for more track candidates in stations 4 & 5. + +Option `--debug x` allows to enable the debug level x (0 = no debug, 1 or 2). + +## New track finder + +`o2-mch-clusters-to-tracks-workflow` + +Take as input the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with +the data description "CLUSTERS" and send the list of MCH tracks +([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated +clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description +"TRACKS" and "TRACKCLUSTERS", respectively. + +Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to +set the magnetic field. + +Option `--moreCandidates` allows to enable the search for more track candidates in stations 4 & 5. + +Option `--debug x` allows to enable the debug level x (0 = no debug, 1 or 2). + +## Vertex sampler + +`o2-mch-vertex-sampler-workflow` + +Send the vertex position (`Point3D<double>`) of the current event with the data description "VERTEX". + +Option `--infile "vertices.in"` allows to read the position of the vertex from the binary file `vertices.in` containing +for each event: +> event number (int)<br> +> x (double)<br> +> y (double)<br> +> z (double)<br> + +If no binary file is provided, the vertex is always set to (0,0,0). + +## Track extrapolation to vertex + +`o2-mch-tracks-to-tracks-at-vertex-workflow` + +Take as input the vertex position (`Point3D<double>`) and the list of MCH tracks +([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) of the current event with +the data description "VERTEX" and "TRACKS", respectively, and send the list of tracks at vertex (`TrackAtVtxStruct` as +described below) with the data description "TRACKSATVERTEX". +```c++ + struct TrackAtVtxStruct { + TrackParamStruct paramAtVertex{}; + double dca = 0.; + double rAbs = 0.; + int mchTrackIdx = 0; + }; +``` + +Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to +set the magnetic field. + +## Track sink + +`o2-mch-tracks-sink-workflow --outfile "tracks.out"` + +Take as input the list of tracks at vertex (`TrackAtVtxStruct` as described above), the list of MCH tracks +([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated +clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description +"TRACKSATVERTEX", "TRACKS" and "TRACKCLUSTERS", respectively, and write them in the binary file `tracks.out` with the +following format: +> number of tracks at vertex (int)<br> +> number of MCH tracks (int)<br> +> number of associated clusters (int)<br> +> list of tracks at vertex (`TrackAtVtxStruct` as described above)<br> +> list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h))<br> +> list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h))<br> + +Option `--tracksAtVertexOnly` allows to take as input and write only the tracks at vertex (number of MCH tracks and +number of associated clusters = 0). + +Option `--mchTracksOnly` allows to take as input and write only the MCH tracks and associated clusters (number of tracks +at vertex = 0). + +## Track sampler + +`o2-mch-tracks-sampler-workflow --infile "tracks.in"` + +where `tracks.in` is a binary file with the same format as the one written by the workflow `o2-mch-tracks-sink-workflow` +described above. + +Send the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) +and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages +with the data description "TRACKS" and "TRACKCLUSTERS", respectively. + +Option `--forTrackFitter` allows to send the messages with the data description "TRACKSIN" and "TRACKCLUSTERSIN", +respectively, as expected by the workflow `o2-mch-tracks-to-tracks-workflow` described below. + +## Track fitter + +`o2-mch-tracks-to-tracks-workflow` + +Take as input the list of MCH tracks +([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated +clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description +"TRACKSIN" and "TRACKCLUSTERSIN", respectively, and send the list of refitted MCH tracks +([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated +clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description +"TRACKS" and "TRACKCLUSTERS", respectively. + +Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to +set the magnetic field. diff --git a/Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx b/Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx similarity index 76% rename from Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx rename to Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx index 3d5b94503ed87..77ae8cdcac199 100644 --- a/Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx @@ -30,6 +30,7 @@ #include "Framework/Logger.h" #include "MCHBase/ClusterBlock.h" +#include "MCHBase/Digit.h" namespace o2 { @@ -67,43 +68,41 @@ class ClusterSamplerTask { /// send the clusters of the current event - int event(0); - mInputFile.read(reinterpret_cast<char*>(&event), SSizeOfInt); + // get the number of clusters and associated digits + int nClusters(0); + mInputFile.read(reinterpret_cast<char*>(&nClusters), sizeof(int)); if (mInputFile.fail()) { pc.services().get<ControlService>().endOfStream(); return; // probably reached eof } + int nDigits(0); + mInputFile.read(reinterpret_cast<char*>(&nDigits), sizeof(int)); - int nClusters(0); - mInputFile.read(reinterpret_cast<char*>(&nClusters), SSizeOfInt); - if (nClusters == 0) { - return; // skip empty event + if (nClusters < 0 || nDigits < 0) { + throw length_error("incorrect message payload"); } // create the output message - auto size = nClusters * SSizeOfClusterStruct; - auto msgOut = pc.outputs().make<char>(Output{"MCH", "CLUSTERS", 0, Lifetime::Timeframe}, SHeaderSize + size); - if (msgOut.size() != SHeaderSize + size) { - throw length_error("incorrect message payload"); + auto clusters = pc.outputs().make<ClusterStruct>(Output{"MCH", "CLUSTERS", 0, Lifetime::Timeframe}, nClusters); + + // fill clusters in O2 format, if any + if (nClusters > 0) { + mInputFile.read(reinterpret_cast<char*>(clusters.data()), clusters.size_bytes()); + for (auto& cluster : clusters) { + cluster.ex = 0.2f; + cluster.ey = 0.2f; + } + } else { + LOG(INFO) << "event is empty"; } - auto bufferPtr = msgOut.data(); - - // fill header info - memcpy(bufferPtr, &event, SSizeOfInt); - bufferPtr += SSizeOfInt; - memcpy(bufferPtr, &nClusters, SSizeOfInt); - bufferPtr += SSizeOfInt; - - // fill tracks and clusters info - mInputFile.read(bufferPtr, size); + // skip the digits if any + if (nDigits > 0) { + mInputFile.seekg(nDigits * sizeof(Digit), std::ios::cur); + } } private: - static constexpr int SSizeOfInt = sizeof(int); - static constexpr int SHeaderSize = 2 * SSizeOfInt; - static constexpr int SSizeOfClusterStruct = sizeof(ClusterStruct); - std::ifstream mInputFile{}; ///< input file }; diff --git a/Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.h b/Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/ClusterSamplerSpec.h rename to Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.h diff --git a/Detectors/MUON/MCH/Workflow/src/TrackAtVertexSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackAtVertexSpec.cxx new file mode 100644 index 0000000000000..b52e5677f026f --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/TrackAtVertexSpec.cxx @@ -0,0 +1,203 @@ +// 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 TrackAtVertexSpec.cxx +/// \brief Implementation of a data processor to extrapolate the tracks to the vertex +/// +/// \author Philippe Pillot, Subatech + +#include "TrackAtVertexSpec.h" + +#include <chrono> +#include <stdexcept> +#include <list> + +#include <gsl/span> + +#include <TMath.h> +#include <TGeoManager.h> +#include <TGeoGlobalMagField.h> + +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Lifetime.h" +#include "Framework/Output.h" +#include "Framework/Task.h" + +#include "DetectorsBase/GeometryManager.h" +#include "MathUtils/Cartesian.h" +#include "Field/MagneticField.h" +#include "DataFormatsMCH/TrackMCH.h" +#include "MCHBase/TrackBlock.h" +#include "MCHTracking/TrackParam.h" +#include "MCHTracking/TrackExtrap.h" + +namespace o2 +{ +namespace mch +{ + +using namespace std; +using namespace o2::framework; + +class TrackAtVertexTask +{ + public: + //_________________________________________________________________________________________________ + void init(framework::InitContext& ic) + { + /// Prepare the track extrapolation tools + + LOG(INFO) << "initializing track extrapolation to vertex"; + + if (!gGeoManager) { + o2::base::GeometryManager::loadGeometry("O2geometry.root"); + if (!gGeoManager) { + throw std::runtime_error("cannot load the geometry"); + } + } + + if (!TGeoGlobalMagField::Instance()->GetField()) { + auto l3Current = ic.options().get<float>("l3Current"); + auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); + auto field = o2::field::MagneticField::createFieldMap(l3Current, dipoleCurrent, o2::field::MagneticField::kConvLHC, false, + 3500., "A-A", "$(O2_ROOT)/share/Common/maps/mfchebKGI_sym.root"); + TGeoGlobalMagField::Instance()->SetField(field); + TGeoGlobalMagField::Instance()->Lock(); + TrackExtrap::setField(); + } + + auto stop = [this]() { + LOG(INFO) << "track propagation to vertex duration = " << mElapsedTime.count() << " s"; + }; + ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); + } + + //_________________________________________________________________________________________________ + void run(framework::ProcessingContext& pc) + { + /// propagate the MCH tracks to the vertex and send the results + + // get the vertex + auto vertex = pc.inputs().get<math_utils::Point3D<double>>("vertex"); + + // get the tracks + auto tracks = pc.inputs().get<gsl::span<TrackMCH>>("tracks"); + + // propagate the tracks to the vertex + auto tStart = std::chrono::high_resolution_clock::now(); + extrapTracksToVertex(tracks, vertex); + auto tEnd = std::chrono::high_resolution_clock::now(); + mElapsedTime += tEnd - tStart; + + // create the output message + auto msgOut = pc.outputs().make<char>(Output{"MCH", "TRACKSATVERTEX", 0, Lifetime::Timeframe}, + sizeof(int) + mTracksAtVtx.size() * sizeof(TrackAtVtxStruct)); + + // write the tracks + writeTracks(msgOut.data()); + } + + private: + struct TrackAtVtxStruct { + TrackParamStruct paramAtVertex{}; + double dca = 0.; + double rAbs = 0.; + int mchTrackIdx = 0; + }; + + //_________________________________________________________________________________________________ + void extrapTracksToVertex(gsl::span<const TrackMCH>& tracks, const math_utils::Point3D<double>& vertex) + { + /// compute the tracks parameters at vertex, at DCA and at the end of the absorber + + mTracksAtVtx.clear(); + int trackIdx(-1); + + for (const auto& track : tracks) { + + // create a new track at vertex pointing to the current track + mTracksAtVtx.emplace_back(); + auto& trackAtVtx = mTracksAtVtx.back(); + trackAtVtx.mchTrackIdx = ++trackIdx; + + // extrapolate to vertex + TrackParam trackParamAtVertex(track.getZ(), track.getParameters()); + if (!TrackExtrap::extrapToVertex(&trackParamAtVertex, vertex.x(), vertex.y(), vertex.z(), 0., 0.)) { + mTracksAtVtx.pop_back(); + continue; + } + trackAtVtx.paramAtVertex.x = trackParamAtVertex.getNonBendingCoor(); + trackAtVtx.paramAtVertex.y = trackParamAtVertex.getBendingCoor(); + trackAtVtx.paramAtVertex.z = trackParamAtVertex.getZ(); + trackAtVtx.paramAtVertex.px = trackParamAtVertex.px(); + trackAtVtx.paramAtVertex.py = trackParamAtVertex.py(); + trackAtVtx.paramAtVertex.pz = trackParamAtVertex.pz(); + trackAtVtx.paramAtVertex.sign = trackParamAtVertex.getCharge(); + + // extrapolate to DCA + TrackParam trackParamAtDCA(track.getZ(), track.getParameters()); + if (!TrackExtrap::extrapToVertexWithoutBranson(&trackParamAtDCA, vertex.z())) { + mTracksAtVtx.pop_back(); + continue; + } + double dcaX = trackParamAtDCA.getNonBendingCoor() - vertex.x(); + double dcaY = trackParamAtDCA.getBendingCoor() - vertex.y(); + trackAtVtx.dca = TMath::Sqrt(dcaX * dcaX + dcaY * dcaY); + + // extrapolate to the end of the absorber + TrackParam trackParamAtRAbs(track.getZ(), track.getParameters()); + if (!TrackExtrap::extrapToZ(&trackParamAtRAbs, -505.)) { + mTracksAtVtx.pop_back(); + continue; + } + double xAbs = trackParamAtRAbs.getNonBendingCoor(); + double yAbs = trackParamAtRAbs.getBendingCoor(); + trackAtVtx.rAbs = TMath::Sqrt(xAbs * xAbs + yAbs * yAbs); + } + } + + //_________________________________________________________________________________________________ + void writeTracks(char* bufferPtr) const + { + /// write the track informations in the message payload + + // write the number of tracks + int nTracks = mTracksAtVtx.size(); + memcpy(bufferPtr, &nTracks, sizeof(int)); + bufferPtr += sizeof(int); + + // write the tracks + if (nTracks > 0) { + memcpy(bufferPtr, mTracksAtVtx.data(), nTracks * sizeof(TrackAtVtxStruct)); + } + } + + std::vector<TrackAtVtxStruct> mTracksAtVtx{}; ///< list of tracks extrapolated to vertex + std::chrono::duration<double> mElapsedTime{}; ///< timer +}; + +//_________________________________________________________________________________________________ +o2::framework::DataProcessorSpec getTrackAtVertexSpec() +{ + return DataProcessorSpec{ + "TrackAtVertex", + Inputs{InputSpec{"vertex", "MCH", "VERTEX", 0, Lifetime::Timeframe}, + InputSpec{"tracks", "MCH", "TRACKS", 0, Lifetime::Timeframe}, + InputSpec{"clusters", "MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}}, + Outputs{OutputSpec{"MCH", "TRACKSATVERTEX", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<TrackAtVertexTask>()}, + Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, + {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}}}; +} + +} // namespace mch +} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.h b/Detectors/MUON/MCH/Workflow/src/TrackAtVertexSpec.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/TrackAtVertexSpec.h rename to Detectors/MUON/MCH/Workflow/src/TrackAtVertexSpec.h diff --git a/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx new file mode 100644 index 0000000000000..a30b8b8027cbe --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx @@ -0,0 +1,149 @@ +// 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 TrackFinderOriginalSpec.cxx +/// \brief Implementation of a data processor to read clusters, reconstruct tracks and send them +/// +/// \author Philippe Pillot, Subatech + +#include "TrackFinderOriginalSpec.h" + +#include <chrono> +#include <array> +#include <list> +#include <stdexcept> + +#include <gsl/span> + +#include "Framework/CallbackService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Lifetime.h" +#include "Framework/Output.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" + +#include "DataFormatsMCH/TrackMCH.h" +#include "MCHBase/ClusterBlock.h" +#include "MCHTracking/TrackParam.h" +#include "MCHTracking/Cluster.h" +#include "MCHTracking/Track.h" +#include "MCHTracking/TrackFinderOriginal.h" + +namespace o2 +{ +namespace mch +{ + +using namespace std; +using namespace o2::framework; + +class TrackFinderTask +{ + public: + //_________________________________________________________________________________________________ + void init(framework::InitContext& ic) + { + /// Prepare the track extrapolation tools + + LOG(INFO) << "initializing track finder"; + + auto l3Current = ic.options().get<float>("l3Current"); + auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); + mTrackFinder.init(l3Current, dipoleCurrent); + + auto moreCandidates = ic.options().get<bool>("moreCandidates"); + mTrackFinder.findMoreTrackCandidates(moreCandidates); + + auto debugLevel = ic.options().get<int>("debug"); + mTrackFinder.debug(debugLevel); + + auto stop = [this]() { + mTrackFinder.printStats(); + mTrackFinder.printTimers(); + LOG(INFO) << "tracking duration = " << mElapsedTime.count() << " s"; + }; + ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); + } + + //_________________________________________________________________________________________________ + void run(framework::ProcessingContext& pc) + { + /// read the clusters of the current event, find tracks and send them + + // get the input clusters + auto clustersIn = pc.inputs().get<gsl::span<ClusterStruct>>("clusters"); + std::array<std::list<Cluster>, 10> clusters{}; + for (const auto& cluster : clustersIn) { + clusters[cluster.getChamberId()].emplace_back(cluster); + } + + // run the track finder + auto tStart = std::chrono::high_resolution_clock::now(); + const auto& tracks = mTrackFinder.findTracks(&clusters); + auto tEnd = std::chrono::high_resolution_clock::now(); + mElapsedTime += tEnd - tStart; + + // create the output messages for tracks and attached clusters + auto& mchTracks = pc.outputs().make<std::vector<TrackMCH>>(Output{"MCH", "TRACKS", 0, Lifetime::Timeframe}); + auto& usedClusters = pc.outputs().make<std::vector<ClusterStruct>>(Output{"MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}); + + // write the messages + if (tracks.size() > 0) { + writeTracks(tracks, mchTracks, usedClusters); + } + } + + private: + //_________________________________________________________________________________________________ + void writeTracks(const std::list<Track>& tracks, + std::vector<TrackMCH, o2::pmr::polymorphic_allocator<TrackMCH>>& mchTracks, + std::vector<ClusterStruct, o2::pmr::polymorphic_allocator<ClusterStruct>>& usedClusters) const + { + /// fill the output messages with tracks and attached clusters + + // avoid memory reallocation + mchTracks.reserve(tracks.size()); + usedClusters.reserve(20. * tracks.size()); + + for (const auto& track : tracks) { + + const auto& param = track.first(); + mchTracks.emplace_back(param.getZ(), param.getParameters(), param.getCovariances(), + param.getTrackChi2(), usedClusters.size(), track.getNClusters()); + + for (const auto& param : track) { + usedClusters.emplace_back(param.getClusterPtr()->getClusterStruct()); + } + } + } + + TrackFinderOriginal mTrackFinder{}; ///< track finder + std::chrono::duration<double> mElapsedTime{}; ///< timer +}; + +//_________________________________________________________________________________________________ +o2::framework::DataProcessorSpec getTrackFinderOriginalSpec() +{ + return DataProcessorSpec{ + "TrackFinderOriginal", + Inputs{InputSpec{"clusters", "MCH", "CLUSTERS", 0, Lifetime::Timeframe}}, + Outputs{OutputSpec{"MCH", "TRACKS", 0, Lifetime::Timeframe}, + OutputSpec{"MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<TrackFinderTask>()}, + Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, + {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}, + {"moreCandidates", VariantType::Bool, false, {"Find more track candidates"}}, + {"debug", VariantType::Int, 0, {"debug level"}}}}; +} + +} // namespace mch +} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.h b/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalSpec.h rename to Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.h diff --git a/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx new file mode 100644 index 0000000000000..430be7df506d4 --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx @@ -0,0 +1,149 @@ +// 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 TrackFinderSpec.cxx +/// \brief Implementation of a data processor to read clusters, reconstruct tracks and send them +/// +/// \author Philippe Pillot, Subatech + +#include "TrackFinderSpec.h" + +#include <chrono> +#include <unordered_map> +#include <list> +#include <stdexcept> + +#include <gsl/span> + +#include "Framework/CallbackService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Lifetime.h" +#include "Framework/Output.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" + +#include "DataFormatsMCH/TrackMCH.h" +#include "MCHBase/ClusterBlock.h" +#include "MCHTracking/TrackParam.h" +#include "MCHTracking/Cluster.h" +#include "MCHTracking/Track.h" +#include "MCHTracking/TrackFinder.h" + +namespace o2 +{ +namespace mch +{ + +using namespace std; +using namespace o2::framework; + +class TrackFinderTask +{ + public: + //_________________________________________________________________________________________________ + void init(framework::InitContext& ic) + { + /// Prepare the track extrapolation tools + + LOG(INFO) << "initializing track finder"; + + auto l3Current = ic.options().get<float>("l3Current"); + auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); + mTrackFinder.init(l3Current, dipoleCurrent); + + auto moreCandidates = ic.options().get<bool>("moreCandidates"); + mTrackFinder.findMoreTrackCandidates(moreCandidates); + + auto debugLevel = ic.options().get<int>("debug"); + mTrackFinder.debug(debugLevel); + + auto stop = [this]() { + mTrackFinder.printStats(); + mTrackFinder.printTimers(); + LOG(INFO) << "tracking duration = " << mElapsedTime.count() << " s"; + }; + ic.services().get<CallbackService>().set(CallbackService::Id::Stop, stop); + } + + //_________________________________________________________________________________________________ + void run(framework::ProcessingContext& pc) + { + /// read the clusters of the current event, find tracks and send them + + // get the input clusters + auto clustersIn = pc.inputs().get<gsl::span<ClusterStruct>>("clusters"); + std::unordered_map<int, std::list<Cluster>> clusters{}; + for (const auto& cluster : clustersIn) { + clusters[cluster.getDEId()].emplace_back(cluster); + } + + // run the track finder + auto tStart = std::chrono::high_resolution_clock::now(); + const auto& tracks = mTrackFinder.findTracks(clusters); + auto tEnd = std::chrono::high_resolution_clock::now(); + mElapsedTime += tEnd - tStart; + + // create the output messages for tracks and attached clusters + auto& mchTracks = pc.outputs().make<std::vector<TrackMCH>>(Output{"MCH", "TRACKS", 0, Lifetime::Timeframe}); + auto& usedClusters = pc.outputs().make<std::vector<ClusterStruct>>(Output{"MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}); + + // write the messages + if (tracks.size() > 0) { + writeTracks(tracks, mchTracks, usedClusters); + } + } + + private: + //_________________________________________________________________________________________________ + void writeTracks(const std::list<Track>& tracks, + std::vector<TrackMCH, o2::pmr::polymorphic_allocator<TrackMCH>>& mchTracks, + std::vector<ClusterStruct, o2::pmr::polymorphic_allocator<ClusterStruct>>& usedClusters) const + { + /// fill the output messages with tracks and attached clusters + + // avoid memory reallocation + mchTracks.reserve(tracks.size()); + usedClusters.reserve(20. * tracks.size()); + + for (const auto& track : tracks) { + + const auto& param = track.first(); + mchTracks.emplace_back(param.getZ(), param.getParameters(), param.getCovariances(), + param.getTrackChi2(), usedClusters.size(), track.getNClusters()); + + for (const auto& param : track) { + usedClusters.emplace_back(param.getClusterPtr()->getClusterStruct()); + } + } + } + + TrackFinder mTrackFinder{}; ///< track finder + std::chrono::duration<double> mElapsedTime{}; ///< timer +}; + +//_________________________________________________________________________________________________ +o2::framework::DataProcessorSpec getTrackFinderSpec() +{ + return DataProcessorSpec{ + "TrackFinder", + Inputs{InputSpec{"clusters", "MCH", "CLUSTERS", 0, Lifetime::Timeframe}}, + Outputs{OutputSpec{"MCH", "TRACKS", 0, Lifetime::Timeframe}, + OutputSpec{"MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<TrackFinderTask>()}, + Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, + {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}, + {"moreCandidates", VariantType::Bool, false, {"Find more track candidates"}}, + {"debug", VariantType::Int, 0, {"debug level"}}}}; +} + +} // namespace mch +} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.h b/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.h rename to Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.h diff --git a/Detectors/MUON/MCH/Workflow/src/TrackFitterSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackFitterSpec.cxx new file mode 100644 index 0000000000000..30c23b87daf3f --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/TrackFitterSpec.cxx @@ -0,0 +1,128 @@ +// 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 TrackFitterSpec.cxx +/// \brief Implementation of a data processor to read, refit and send tracks with attached clusters +/// +/// \author Philippe Pillot, Subatech + +#include "TrackFitterSpec.h" + +#include <stdexcept> +#include <list> +#include <vector> + +#include <gsl/span> + +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Lifetime.h" +#include "Framework/Output.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" + +#include "DataFormatsMCH/TrackMCH.h" +#include "MCHBase/ClusterBlock.h" +#include "MCHTracking/TrackParam.h" +#include "MCHTracking/Cluster.h" +#include "MCHTracking/Track.h" +#include "MCHTracking/TrackExtrap.h" +#include "MCHTracking/TrackFitter.h" + +namespace o2 +{ +namespace mch +{ + +using namespace std; +using namespace o2::framework; + +class TrackFitterTask +{ + public: + //_________________________________________________________________________________________________ + void init(framework::InitContext& ic) + { + /// Prepare the track extrapolation tools + LOG(INFO) << "initializing track fitter"; + auto l3Current = ic.options().get<float>("l3Current"); + auto dipoleCurrent = ic.options().get<float>("dipoleCurrent"); + mTrackFitter.initField(l3Current, dipoleCurrent); + mTrackFitter.smoothTracks(true); + TrackExtrap::useExtrapV2(); + } + + //_________________________________________________________________________________________________ + void run(framework::ProcessingContext& pc) + { + /// read the tracks with attached clusters, refit them and send the new version + + // get the input tracks and attached clusters + auto tracksIn = pc.inputs().get<gsl::span<TrackMCH>>("tracks"); + auto clustersIn = pc.inputs().get<gsl::span<ClusterStruct>>("clusters"); + + // create the output messages for refitted tracks and attached clusters + auto& tracksOut = pc.outputs().make<std::vector<TrackMCH>>(Output{"MCH", "TRACKS", 0, Lifetime::Timeframe}); + auto& clustersOut = pc.outputs().make<std::vector<ClusterStruct>>(Output{"MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}); + + // avoid memory reallocation + tracksOut.reserve(tracksIn.size()); + clustersOut.reserve(clustersIn.size()); + + for (const auto& mchTrack : tracksIn) { + + // get the clusters attached to the track + auto trackClusters = clustersIn.subspan(mchTrack.getFirstClusterIdx(), mchTrack.getNClusters()); + + // create the internal track + Track track{}; + std::list<Cluster> clusters{}; + for (const auto& cluster : trackClusters) { + clusters.emplace_back(cluster); + track.createParamAtCluster(clusters.back()); + } + + // refit the track + try { + mTrackFitter.fit(track); + } catch (exception const& e) { + LOG(ERROR) << "Track fit failed: " << e.what(); + continue; + } + + // write the refitted track and attached clusters (same as those of the input track) + const auto& param = track.first(); + tracksOut.emplace_back(param.getZ(), param.getParameters(), param.getCovariances(), + param.getTrackChi2(), clustersOut.size(), track.getNClusters()); + clustersOut.insert(clustersOut.end(), trackClusters.begin(), trackClusters.end()); + } + } + + private: + TrackFitter mTrackFitter{}; ///< track fitter +}; + +//_________________________________________________________________________________________________ +o2::framework::DataProcessorSpec getTrackFitterSpec() +{ + return DataProcessorSpec{ + "TrackFitter", + Inputs{InputSpec{"tracks", "MCH", "TRACKSIN", 0, Lifetime::Timeframe}, + InputSpec{"clusters", "MCH", "TRACKCLUSTERSIN", 0, Lifetime::Timeframe}}, + Outputs{OutputSpec{"MCH", "TRACKS", 0, Lifetime::Timeframe}, + OutputSpec{"MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<TrackFitterTask>()}, + Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, + {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}}}; +} + +} // namespace mch +} // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.h b/Detectors/MUON/MCH/Workflow/src/TrackFitterSpec.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/TrackFitterSpec.h rename to Detectors/MUON/MCH/Workflow/src/TrackFitterSpec.h diff --git a/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackSamplerSpec.cxx similarity index 55% rename from Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx rename to Detectors/MUON/MCH/Workflow/src/TrackSamplerSpec.cxx index a18f533605003..3c46fc36bce87 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/TrackSamplerSpec.cxx @@ -17,7 +17,6 @@ #include <iostream> #include <fstream> - #include <stdexcept> #include "Framework/CallbackService.h" @@ -26,9 +25,14 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Lifetime.h" #include "Framework/Output.h" +#include "Framework/OutputRef.h" #include "Framework/Task.h" #include "Framework/Logger.h" +#include "DataFormatsMCH/TrackMCH.h" +#include "MCHBase/ClusterBlock.h" +#include "MCHBase/TrackBlock.h" + namespace o2 { namespace mch @@ -65,51 +69,68 @@ class TrackSamplerTask { /// send the tracks with attached clusters of the current event - int event(0); - mInputFile.read(reinterpret_cast<char*>(&event), SSizeOfInt); + // read the number of tracks at vertex, MCH tracks and attached clusters + int nTracksAtVtx(-1); + mInputFile.read(reinterpret_cast<char*>(&nTracksAtVtx), sizeof(int)); if (mInputFile.fail()) { + pc.services().get<ControlService>().endOfStream(); return; // probably reached eof } + int nMCHTracks(-1); + mInputFile.read(reinterpret_cast<char*>(&nMCHTracks), sizeof(int)); + int nClusters(-1); + mInputFile.read(reinterpret_cast<char*>(&nClusters), sizeof(int)); - int size(0); - mInputFile.read(reinterpret_cast<char*>(&size), SSizeOfInt); - if (size == 0) { - LOG(INFO) << "event " << event + 1 << " is empty"; - return; // skip empty event + if (nTracksAtVtx < 0 || nMCHTracks < 0 || nClusters < 0) { + throw length_error("invalid data input"); } - - // create the output message - auto msgOut = pc.outputs().make<char>(Output{"MCH", "TRACKS", 0, Lifetime::Timeframe}, SHeaderSize + size); - if (msgOut.size() != SHeaderSize + size) { - throw length_error("incorrect message payload"); + if (nMCHTracks > 0 && nClusters == 0) { + throw out_of_range("clusters are missing"); } - auto bufferPtr = msgOut.data(); + // create the output messages + auto tracks = pc.outputs().make<TrackMCH>(OutputRef{"tracks"}, nMCHTracks); + auto clusters = pc.outputs().make<ClusterStruct>(OutputRef{"clusters"}, nClusters); - // fill header info - memcpy(bufferPtr, &event, SSizeOfInt); - bufferPtr += SSizeOfInt; - memcpy(bufferPtr, &size, SSizeOfInt); - bufferPtr += SSizeOfInt; + // skip the tracks at vertex if any + if (nTracksAtVtx > 0) { + mInputFile.seekg(nTracksAtVtx * sizeof(TrackAtVtxStruct), std::ios::cur); + } - // fill tracks and clusters info - mInputFile.read(bufferPtr, size); + // read the MCH tracks and the attached clusters + if (nMCHTracks > 0) { + mInputFile.read(reinterpret_cast<char*>(tracks.data()), tracks.size_bytes()); + mInputFile.read(reinterpret_cast<char*>(clusters.data()), clusters.size_bytes()); + } } private: - static constexpr int SSizeOfInt = sizeof(int); - static constexpr int SHeaderSize = 2 * SSizeOfInt; + struct TrackAtVtxStruct { + TrackParamStruct paramAtVertex{}; + double dca = 0.; + double rAbs = 0.; + int mchTrackIdx = 0; + }; std::ifstream mInputFile{}; ///< input file }; //_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getTrackSamplerSpec() +o2::framework::DataProcessorSpec getTrackSamplerSpec(bool forTrackFitter) { + Outputs outputs{}; + if (forTrackFitter) { + outputs.emplace_back(OutputLabel{"tracks"}, "MCH", "TRACKSIN", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"clusters"}, "MCH", "TRACKCLUSTERSIN", 0, Lifetime::Timeframe); + } else { + outputs.emplace_back(OutputLabel{"tracks"}, "MCH", "TRACKS", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"clusters"}, "MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe); + } + return DataProcessorSpec{ "TrackSampler", Inputs{}, - Outputs{OutputSpec{"MCH", "TRACKS", 0, Lifetime::Timeframe}}, + outputs, AlgorithmSpec{adaptFromTask<TrackSamplerTask>()}, Options{{"infile", VariantType::String, "", {"input filename"}}}}; } diff --git a/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.h b/Detectors/MUON/MCH/Workflow/src/TrackSamplerSpec.h similarity index 91% rename from Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.h rename to Detectors/MUON/MCH/Workflow/src/TrackSamplerSpec.h index eb4f57d7d35a7..993d514dbeac8 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackSamplerSpec.h +++ b/Detectors/MUON/MCH/Workflow/src/TrackSamplerSpec.h @@ -23,7 +23,7 @@ namespace o2 namespace mch { -o2::framework::DataProcessorSpec getTrackSamplerSpec(); +o2::framework::DataProcessorSpec getTrackSamplerSpec(bool forTrackFitter); } // end namespace mch } // end namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackSinkSpec.cxx similarity index 55% rename from Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx rename to Detectors/MUON/MCH/Workflow/src/TrackSinkSpec.cxx index ca1c7f954f124..30efb7d8eadc3 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/TrackSinkSpec.cxx @@ -17,9 +17,10 @@ #include <iostream> #include <fstream> - #include <stdexcept> +#include <gsl/span> + #include "Framework/CallbackService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" @@ -28,6 +29,9 @@ #include "Framework/Task.h" #include "Framework/Logger.h" +#include "DataFormatsMCH/TrackMCH.h" +#include "MCHBase/ClusterBlock.h" + namespace o2 { namespace mch @@ -63,8 +67,35 @@ class TrackSinkTask void run(framework::ProcessingContext& pc) { /// dump the tracks with attached clusters of the current event - auto msgIn = pc.inputs().get<gsl::span<char>>("tracks"); - mOutputFile.write(msgIn.data(), msgIn.size()); + + // get the input messages + gsl::span<const TrackMCH> tracks{}; + if (pc.inputs().getPos("tracks") >= 0) { + tracks = pc.inputs().get<gsl::span<TrackMCH>>("tracks"); + } + gsl::span<const ClusterStruct> clusters{}; + if (pc.inputs().getPos("clusters") >= 0) { + clusters = pc.inputs().get<gsl::span<ClusterStruct>>("clusters"); + } + gsl::span<const char> tracksAtVtx{}; + if (pc.inputs().getPos("tracksAtVtx") >= 0) { + tracksAtVtx = pc.inputs().get<gsl::span<char>>("tracksAtVtx"); + } + + // write the number of tracks at vertex, MCH tracks and attached clusters + int nTracksAtVtx = tracksAtVtx.empty() ? 0 : *reinterpret_cast<const int*>(tracksAtVtx.data()); + mOutputFile.write(reinterpret_cast<char*>(&nTracksAtVtx), sizeof(int)); + int nTracks = tracks.size(); + mOutputFile.write(reinterpret_cast<char*>(&nTracks), sizeof(int)); + int nClusters = clusters.size(); + mOutputFile.write(reinterpret_cast<char*>(&nClusters), sizeof(int)); + + // write the tracks at vertex, MCH tracks and attached clusters + if (tracksAtVtx.size() > sizeof(int)) { + mOutputFile.write(&tracksAtVtx[sizeof(int)], tracksAtVtx.size() - sizeof(int)); + } + mOutputFile.write(reinterpret_cast<const char*>(tracks.data()), tracks.size_bytes()); + mOutputFile.write(reinterpret_cast<const char*>(clusters.data()), clusters.size_bytes()); } private: @@ -72,11 +103,23 @@ class TrackSinkTask }; //_________________________________________________________________________________________________ -o2::framework::DataProcessorSpec getTrackSinkSpec(o2::header::DataDescription description) +o2::framework::DataProcessorSpec getTrackSinkSpec(bool mchTracks, bool tracksAtVtx) { + Inputs inputs{}; + if (mchTracks) { + inputs.emplace_back("tracks", "MCH", "TRACKS", 0, Lifetime::Timeframe); + inputs.emplace_back("clusters", "MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe); + } + if (tracksAtVtx) { + inputs.emplace_back("tracksAtVtx", "MCH", "TRACKSATVERTEX", 0, Lifetime::Timeframe); + } + if (inputs.empty()) { + throw invalid_argument("nothing to write"); + } + return DataProcessorSpec{ "TrackSink", - Inputs{InputSpec{"tracks", "MCH", description, 0, Lifetime::Timeframe}}, + inputs, Outputs{}, AlgorithmSpec{adaptFromTask<TrackSinkTask>()}, Options{{"outfile", VariantType::String, "AliESDs.out.dat", {"output filename"}}}}; diff --git a/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.h b/Detectors/MUON/MCH/Workflow/src/TrackSinkSpec.h similarity index 86% rename from Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.h rename to Detectors/MUON/MCH/Workflow/src/TrackSinkSpec.h index 13e99835bbdce..64e9ba6af64ac 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackSinkSpec.h +++ b/Detectors/MUON/MCH/Workflow/src/TrackSinkSpec.h @@ -17,14 +17,13 @@ #define O2_MCH_TRACKSINKSPEC_H_ #include "Framework/DataProcessorSpec.h" -#include "Headers/DataHeader.h" namespace o2 { namespace mch { -o2::framework::DataProcessorSpec getTrackSinkSpec(o2::header::DataDescription description); +o2::framework::DataProcessorSpec getTrackSinkSpec(bool mchTracks, bool tracksAtVtx); } // end namespace mch } // end namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx b/Detectors/MUON/MCH/Workflow/src/VertexSamplerSpec.cxx similarity index 70% rename from Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx rename to Detectors/MUON/MCH/Workflow/src/VertexSamplerSpec.cxx index ff9f145833b0c..541ad1568f692 100644 --- a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/VertexSamplerSpec.cxx @@ -73,39 +73,21 @@ class VertexSamplerSpec /// send the vertex of the current event if an input file is provided /// or the default vertex (0.,0.,0.) otherwise - // get the current event - auto msgIn = pc.inputs().get<gsl::span<char>>("tracks"); - if (msgIn.size() < SSizeOfInt) { - throw out_of_range("missing event header"); - } - const int& eventTracks = *reinterpret_cast<const int*>(msgIn.data()); - // read the corresponding vertex or set it to (0,0,0) - int eventVtx(-1); math_utils::Point3D<double> vertex(0., 0., 0.); if (mInputFile.is_open()) { - do { - mInputFile.read(reinterpret_cast<char*>(&eventVtx), SSizeOfInt); - if (mInputFile.fail()) { - throw out_of_range(std::string("missing vertex for event ") + eventTracks); - } - VertexStruct vtx{}; - mInputFile.read(reinterpret_cast<char*>(&vtx), SSizeOfVertexStruct); - vertex.SetCoordinates(vtx.x, vtx.y, vtx.z); - } while (eventVtx != eventTracks); + int event(-1); + mInputFile.read(reinterpret_cast<char*>(&event), sizeof(int)); + if (mInputFile.fail()) { + throw out_of_range("missing vertex"); + } + VertexStruct vtx{}; + mInputFile.read(reinterpret_cast<char*>(&vtx), sizeof(VertexStruct)); + vertex.SetCoordinates(vtx.x, vtx.y, vtx.z); } // create the output message - auto msgOut = pc.outputs().make<char>(Output{"MCH", "VERTEX", 0, Lifetime::Timeframe}, SSizeOfInt + SSizeOfPoint3D); - if (msgOut.size() != SSizeOfInt + SSizeOfPoint3D) { - throw length_error("incorrect message payload"); - } - - // fill it - auto bufferPtr = msgOut.data(); - memcpy(bufferPtr, &eventVtx, SSizeOfInt); - bufferPtr += SSizeOfInt; - memcpy(bufferPtr, &vertex, SSizeOfPoint3D); + pc.outputs().snapshot(Output{"MCH", "VERTEX", 0, Lifetime::Timeframe}, vertex); } private: @@ -114,9 +96,6 @@ class VertexSamplerSpec double y; double z; }; - static constexpr int SSizeOfInt = sizeof(int); - static constexpr int SSizeOfVertexStruct = sizeof(VertexStruct); - static constexpr int SSizeOfPoint3D = sizeof(math_utils::Point3D<double>); std::ifstream mInputFile{}; ///< input file }; @@ -126,7 +105,9 @@ o2::framework::DataProcessorSpec getVertexSamplerSpec() { return DataProcessorSpec{ "VertexSampler", - Inputs{InputSpec{"tracks", "MCH", "TRACKS", 0, Lifetime::Timeframe}}, + // the input message is just used to synchronize the sending of the vertex with the track reconstruction + Inputs{InputSpec{"tracks", "MCH", "TRACKS", 0, Lifetime::Timeframe}, + InputSpec{"clusters", "MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe}}, Outputs{OutputSpec{"MCH", "VERTEX", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask<VertexSamplerSpec>()}, Options{{"infile", VariantType::String, "", {"input filename"}}}}; diff --git a/Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.h b/Detectors/MUON/MCH/Workflow/src/VertexSamplerSpec.h similarity index 100% rename from Detectors/MUON/MCH/Tracking/src/VertexSamplerSpec.h rename to Detectors/MUON/MCH/Workflow/src/VertexSamplerSpec.h diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalWorkflow.cxx b/Detectors/MUON/MCH/Workflow/src/clusters-sampler-workflow.cxx similarity index 67% rename from Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalWorkflow.cxx rename to Detectors/MUON/MCH/Workflow/src/clusters-sampler-workflow.cxx index 130952e254a30..ed21436dc0bb9 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginalWorkflow.cxx +++ b/Detectors/MUON/MCH/Workflow/src/clusters-sampler-workflow.cxx @@ -8,18 +8,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file clusters-sampler-workflow.cxx +/// \brief Implementation of a DPL device to send clusters read from a binary file +/// +/// \author Philippe Pillot, Subatech + #include "Framework/runDataProcessing.h" #include "ClusterSamplerSpec.h" -#include "TrackFinderOriginalSpec.h" -#include "TrackSinkSpec.h" using namespace o2::framework; -WorkflowSpec defineDataProcessing(ConfigContext const&) +WorkflowSpec defineDataProcessing(const ConfigContext&) { - return WorkflowSpec{ - o2::mch::getClusterSamplerSpec(), - o2::mch::getTrackFinderOriginalSpec(), - o2::mch::getTrackSinkSpec("TRACKS")}; + return WorkflowSpec{o2::mch::getClusterSamplerSpec()}; } diff --git a/Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-original-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-original-workflow.cxx new file mode 100644 index 0000000000000..a5b0e2ab7e65d --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-original-workflow.cxx @@ -0,0 +1,25 @@ +// 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 clusters-to-tracks-original-workflow.cxx +/// \brief Implementation of a DPL device to run the original track finder algorithm +/// +/// \author Philippe Pillot, Subatech + +#include "Framework/runDataProcessing.h" + +#include "TrackFinderOriginalSpec.h" + +using namespace o2::framework; + +WorkflowSpec defineDataProcessing(const ConfigContext&) +{ + return WorkflowSpec{o2::mch::getTrackFinderOriginalSpec()}; +} diff --git a/Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-workflow.cxx new file mode 100644 index 0000000000000..b999e23056d41 --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/clusters-to-tracks-workflow.cxx @@ -0,0 +1,25 @@ +// 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 clusters-to-tracks-workflow.cxx +/// \brief Implementation of a DPL device to run the track finder algorithm +/// +/// \author Philippe Pillot, Subatech + +#include "Framework/runDataProcessing.h" + +#include "TrackFinderSpec.h" + +using namespace o2::framework; + +WorkflowSpec defineDataProcessing(const ConfigContext&) +{ + return WorkflowSpec{o2::mch::getTrackFinderSpec()}; +} diff --git a/Detectors/MUON/MCH/Workflow/src/tracks-sampler-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/tracks-sampler-workflow.cxx new file mode 100644 index 0000000000000..1f1c59af61ff9 --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/tracks-sampler-workflow.cxx @@ -0,0 +1,37 @@ +// 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 tracks-sampler-workflow.cxx +/// \brief Implementation of a DPL device to send tracks and attached clusters read from a binary file +/// +/// \author Philippe Pillot, Subatech + +#include <vector> + +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back( + ConfigParamSpec{"forTrackFitter", VariantType::Bool, false, {"message description as expected by TrackFitterSpec"}}); +} + +#include "Framework/runDataProcessing.h" + +#include "TrackSamplerSpec.h" + +WorkflowSpec defineDataProcessing(const ConfigContext& config) +{ + bool forTrackFitter = config.options().get<bool>("forTrackFitter"); + return WorkflowSpec{o2::mch::getTrackSamplerSpec(forTrackFitter)}; +} diff --git a/Detectors/MUON/MCH/Workflow/src/tracks-sink-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/tracks-sink-workflow.cxx new file mode 100644 index 0000000000000..16e3b9572f39d --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/tracks-sink-workflow.cxx @@ -0,0 +1,40 @@ +// 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 tracks-sink-workflow.cxx +/// \brief Implementation of a DPL device to write tracks and attached clusters into a binary file +/// +/// \author Philippe Pillot, Subatech + +#include <vector> + +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back( + ConfigParamSpec{"mchTracksOnly", VariantType::Bool, false, {"only write MCH tracks and attached clusters"}}); + workflowOptions.push_back( + ConfigParamSpec{"tracksAtVertexOnly", VariantType::Bool, false, {"only write track parameters at vertex"}}); +} + +#include "Framework/runDataProcessing.h" + +#include "TrackSinkSpec.h" + +WorkflowSpec defineDataProcessing(const ConfigContext& config) +{ + bool mchTracks = !config.options().get<bool>("tracksAtVertexOnly"); + bool tracksAtVtx = !config.options().get<bool>("mchTracksOnly"); + return WorkflowSpec{o2::mch::getTrackSinkSpec(mchTracks, tracksAtVtx)}; +} diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderWorkflow.cxx b/Detectors/MUON/MCH/Workflow/src/tracks-to-tracks-at-vertex-workflow.cxx similarity index 59% rename from Detectors/MUON/MCH/Tracking/src/TrackFinderWorkflow.cxx rename to Detectors/MUON/MCH/Workflow/src/tracks-to-tracks-at-vertex-workflow.cxx index 5ad3f0d82f04c..4f5d55ca857a0 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderWorkflow.cxx +++ b/Detectors/MUON/MCH/Workflow/src/tracks-to-tracks-at-vertex-workflow.cxx @@ -8,22 +8,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file tracks-to-tracks-at-vertex-workflow.cxx +/// \brief Implementation of a DPL device to run the algorithm that extrapolates tracks to the vertex +/// +/// \author Philippe Pillot, Subatech + #include "Framework/runDataProcessing.h" -#include "ClusterSamplerSpec.h" -#include "TrackFinderSpec.h" -#include "VertexSamplerSpec.h" #include "TrackAtVertexSpec.h" -#include "TrackSinkSpec.h" using namespace o2::framework; -WorkflowSpec defineDataProcessing(ConfigContext const&) +WorkflowSpec defineDataProcessing(const ConfigContext&) { - return WorkflowSpec{ - o2::mch::getClusterSamplerSpec(), - o2::mch::getTrackFinderSpec(), - o2::mch::getVertexSamplerSpec(), - o2::mch::getTrackAtVertexSpec(), - o2::mch::getTrackSinkSpec("TRACKSATVERTEX")}; + return WorkflowSpec{o2::mch::getTrackAtVertexSpec()}; } diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitterWorkflow.cxx b/Detectors/MUON/MCH/Workflow/src/tracks-to-tracks-workflow.cxx similarity index 67% rename from Detectors/MUON/MCH/Tracking/src/TrackFitterWorkflow.cxx rename to Detectors/MUON/MCH/Workflow/src/tracks-to-tracks-workflow.cxx index 397a17500a01a..6f3673cd35f7d 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFitterWorkflow.cxx +++ b/Detectors/MUON/MCH/Workflow/src/tracks-to-tracks-workflow.cxx @@ -8,18 +8,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file tracks-to-tracks-workflow.cxx +/// \brief Implementation of a DPL device to refit the tracks from the attached clusters +/// +/// \author Philippe Pillot, Subatech + #include "Framework/runDataProcessing.h" -#include "TrackSamplerSpec.h" #include "TrackFitterSpec.h" -#include "TrackSinkSpec.h" using namespace o2::framework; -WorkflowSpec defineDataProcessing(ConfigContext const&) +WorkflowSpec defineDataProcessing(const ConfigContext&) { - return WorkflowSpec{ - o2::mch::getTrackSamplerSpec(), - o2::mch::getTrackFitterSpec(), - o2::mch::getTrackSinkSpec("REFITTRACKS")}; + return WorkflowSpec{o2::mch::getTrackFitterSpec()}; } diff --git a/Detectors/MUON/MCH/Workflow/src/vertex-sampler-workflow.cxx b/Detectors/MUON/MCH/Workflow/src/vertex-sampler-workflow.cxx new file mode 100644 index 0000000000000..f43ded9067fc2 --- /dev/null +++ b/Detectors/MUON/MCH/Workflow/src/vertex-sampler-workflow.cxx @@ -0,0 +1,25 @@ +// 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 vertex-sampler-workflow.cxx +/// \brief Implementation of a DPL device to send vertices read from a binary file +/// +/// \author Philippe Pillot, Subatech + +#include "Framework/runDataProcessing.h" + +#include "VertexSamplerSpec.h" + +using namespace o2::framework; + +WorkflowSpec defineDataProcessing(const ConfigContext&) +{ + return WorkflowSpec{o2::mch::getVertexSamplerSpec()}; +} From e4ff64f078d4096f62326d95adaf53ff69460891 Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@cern.ch> Date: Wed, 4 Nov 2020 17:45:59 +0100 Subject: [PATCH 1207/1751] Add TOC and reshuffle a bit --- Detectors/MUON/MCH/Workflow/README.md | 207 +++++++++++++------------- 1 file changed, 103 insertions(+), 104 deletions(-) diff --git a/Detectors/MUON/MCH/Workflow/README.md b/Detectors/MUON/MCH/Workflow/README.md index 8b167b4631a63..1ed6fd6dd6bd8 100644 --- a/Detectors/MUON/MCH/Workflow/README.md +++ b/Detectors/MUON/MCH/Workflow/README.md @@ -4,158 +4,157 @@ # MCH Workflows -## Raw data decoding: +<!-- vim-markdown-toc GFM --> + +* [Raw to digits](#raw-to-digits) +* [Digits to preclusters](#digits-to-preclusters) +* [Tracking](#tracking) + * [Original track finder](#original-track-finder) + * [New track finder](#new-track-finder) +* [Track extrapolation to vertex](#track-extrapolation-to-vertex) +* [Track fitter](#track-fitter) +* [Samplers](#samplers) + * [Cluster sampler](#cluster-sampler) + * [Track sampler](#track-sampler) + * [Vertex sampler](#vertex-sampler) +* [Sinks](#sinks) + * [Preclusters sink](#preclusters-sink) + * [Track sink](#track-sink) + +<!-- vim-markdown-toc --> + +## Raw to digits `o2-mch-raw-to-digits-workflow` -## Pre-clustering: +## Digits to preclusters `o2-mch-digits-to-preclusters-workflow` -## Pre-clustering sink: +Example of a DPL chain to go from a raw data file to a file of preclusters : -`o2-mch-preclusters-sink-workflow` - -## Example of DPL chain: - -`o2-raw-file-reader-workflow --conf file-reader.cfg --loop 0 -b | o2-mch-raw-to-digits-workflow -b | o2-mch-digits-to-preclusters-workflow -b | o2-mch-preclusters-sink-workflow -b` +```shell +o2-raw-file-reader-workflow --conf file-reader.cfg --loop 0 -b | +o2-mch-raw-to-digits-workflow -b | +o2-mch-digits-to-preclusters-workflow -b | +o2-mch-preclusters-sink-workflow -b +``` where the `file-reader.cfg` looks like this: - [input-0] - dataOrigin = MCH - dataDescription = RAWDATA - filePath = /home/data/data-de819-ped-raw.raw - -## Cluster sampler - -`o2-mch-clusters-sampler-workflow --infile "clusters.in"` - -where `clusters.in` is a binary file containing for each event: -> number of clusters (int)<br> -> number of associated digits (int)<br> -> list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h))<br> -> list of associated digits ([Digit](../Base/include/MCHBase/Digit.h))<br> +```ini +[input-0] +dataOrigin = MCH +dataDescription = RAWDATA +filePath = /home/data/data-de819-ped-raw.raw +``` -Send the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data -description "CLUSTERS". +## Tracking -## Original track finder +### Original track finder `o2-mch-clusters-to-tracks-original-workflow` -Take as input the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with -the data description "CLUSTERS" and send the list of MCH tracks -([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated -clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description -"TRACKS" and "TRACKCLUSTERS", respectively. +Take as input the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description "CLUSTERS" and send the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description "TRACKS" and "TRACKCLUSTERS", respectively. -Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to -set the magnetic field. +Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to set the magnetic field. Option `--moreCandidates` allows to enable the search for more track candidates in stations 4 & 5. Option `--debug x` allows to enable the debug level x (0 = no debug, 1 or 2). -## New track finder +### New track finder `o2-mch-clusters-to-tracks-workflow` -Take as input the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with -the data description "CLUSTERS" and send the list of MCH tracks -([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated -clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description -"TRACKS" and "TRACKCLUSTERS", respectively. +Same behavior and options as [Original track finder](#original-track-finder) -Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to -set the magnetic field. +## Track extrapolation to vertex -Option `--moreCandidates` allows to enable the search for more track candidates in stations 4 & 5. +`o2-mch-tracks-to-tracks-at-vertex-workflow` -Option `--debug x` allows to enable the debug level x (0 = no debug, 1 or 2). +Take as input the vertex position (`Point3D<double>`) and the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) of the current event with the data description "VERTEX" and "TRACKS", respectively, and send the list of tracks at vertex (`TrackAtVtxStruct` as described below) with the data description "TRACKSATVERTEX". -## Vertex sampler +```c++ +struct TrackAtVtxStruct { + TrackParamStruct paramAtVertex{}; + double dca = 0.; + double rAbs = 0.; + int mchTrackIdx = 0; +}; +``` -`o2-mch-vertex-sampler-workflow` +Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to set the magnetic field. -Send the vertex position (`Point3D<double>`) of the current event with the data description "VERTEX". +## Track fitter -Option `--infile "vertices.in"` allows to read the position of the vertex from the binary file `vertices.in` containing -for each event: -> event number (int)<br> -> x (double)<br> -> y (double)<br> -> z (double)<br> +`o2-mch-tracks-to-tracks-workflow` -If no binary file is provided, the vertex is always set to (0,0,0). +Take as input the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description "TRACKSIN" and "TRACKCLUSTERSIN", respectively, and send the list of refitted MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description "TRACKS" and "TRACKCLUSTERS", respectively. -## Track extrapolation to vertex +Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to set the magnetic field. -`o2-mch-tracks-to-tracks-at-vertex-workflow` +## Samplers -Take as input the vertex position (`Point3D<double>`) and the list of MCH tracks -([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) of the current event with -the data description "VERTEX" and "TRACKS", respectively, and send the list of tracks at vertex (`TrackAtVtxStruct` as -described below) with the data description "TRACKSATVERTEX". -```c++ - struct TrackAtVtxStruct { - TrackParamStruct paramAtVertex{}; - double dca = 0.; - double rAbs = 0.; - int mchTrackIdx = 0; - }; +### Cluster sampler + +```shell +o2-mch-clusters-sampler-workflow --infile "clusters.in" ``` -Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to -set the magnetic field. +where `clusters.in` is a binary file containing for each event: -## Track sink +* number of clusters (int) +* number of associated digits (int) +* list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) +* list of associated digits ([Digit](../Base/include/MCHBase/Digit.h)) -`o2-mch-tracks-sink-workflow --outfile "tracks.out"` +Send the list of clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description "CLUSTERS". -Take as input the list of tracks at vertex (`TrackAtVtxStruct` as described above), the list of MCH tracks -([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated -clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description -"TRACKSATVERTEX", "TRACKS" and "TRACKCLUSTERS", respectively, and write them in the binary file `tracks.out` with the -following format: -> number of tracks at vertex (int)<br> -> number of MCH tracks (int)<br> -> number of associated clusters (int)<br> -> list of tracks at vertex (`TrackAtVtxStruct` as described above)<br> -> list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h))<br> -> list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h))<br> +### Track sampler -Option `--tracksAtVertexOnly` allows to take as input and write only the tracks at vertex (number of MCH tracks and -number of associated clusters = 0). +`o2-mch-tracks-sampler-workflow --infile "tracks.in"` -Option `--mchTracksOnly` allows to take as input and write only the MCH tracks and associated clusters (number of tracks -at vertex = 0). +where `tracks.in` is a binary file with the same format as the one written by the workflow [o2-mch-tracks-sink-workflow](#track-sink) -## Track sampler +Send the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description "TRACKS" and "TRACKCLUSTERS", respectively. -`o2-mch-tracks-sampler-workflow --infile "tracks.in"` +Option `--forTrackFitter` allows to send the messages with the data description "TRACKSIN" and "TRACKCLUSTERSIN", respectively, as expected by the workflow `o2-mch-tracks-to-tracks-workflow` described below. -where `tracks.in` is a binary file with the same format as the one written by the workflow `o2-mch-tracks-sink-workflow` -described above. +### Vertex sampler -Send the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) -and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages -with the data description "TRACKS" and "TRACKCLUSTERS", respectively. +`o2-mch-vertex-sampler-workflow` -Option `--forTrackFitter` allows to send the messages with the data description "TRACKSIN" and "TRACKCLUSTERSIN", -respectively, as expected by the workflow `o2-mch-tracks-to-tracks-workflow` described below. +Send the vertex position (`Point3D<double>`) of the current event with the data description "VERTEX". -## Track fitter +Option `--infile "vertices.in"` allows to read the position of the vertex from the binary file `vertices.in` containing for each event: -`o2-mch-tracks-to-tracks-workflow` +* event number (int) +* x (double) +* y (double) +* z (double) + +If no binary file is provided, the vertex is always set to (0,0,0). + +## Sinks + +### Preclusters sink + +`o2-mch-preclusters-sink-workflow` + +### Track sink + +`o2-mch-tracks-sink-workflow --outfile "tracks.out"` + +Take as input the list of tracks at vertex (`TrackAtVtxStruct` as described above), the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description "TRACKSATVERTEX", "TRACKS" and "TRACKCLUSTERS", respectively, and write them in the binary file `tracks.out` with the following format: + +* number of tracks at vertex (int) +* number of MCH tracks (int) +* number of associated clusters (int) +* list of tracks at vertex (`TrackAtVtxStruct` as described above) +* list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) +* list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) -Take as input the list of MCH tracks -([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated -clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description -"TRACKSIN" and "TRACKCLUSTERSIN", respectively, and send the list of refitted MCH tracks -([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated -clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description -"TRACKS" and "TRACKCLUSTERS", respectively. +Option `--tracksAtVertexOnly` allows to take as input and write only the tracks at vertex (number of MCH tracks and number of associated clusters = 0). -Options `--l3Current xxx` and `--dipoleCurrent yyy` allow to specify the current in L3 and in the dipole to be used to -set the magnetic field. +Option `--mchTracksOnly` allows to take as input and write only the MCH tracks and associated clusters (number of tracks at vertex = 0). From d57067790d39e69b4823c20ca6418f93b1f732b1 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Thu, 5 Nov 2020 08:19:48 +0100 Subject: [PATCH 1208/1751] HistogramRegistry: add function to check if name is already used (#4761) * HistogramRegistry: move more non-template functions to .cxx * HistogramRegistry: add function to check if name is in use * HistogramRegistry: move contains() to .cxx * add slim contains() function in header --- .../include/Framework/HistogramRegistry.h | 183 ++--------------- Framework/Core/src/HistogramRegistry.cxx | 184 ++++++++++++++++++ 2 files changed, 205 insertions(+), 162 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index fa416811490ff..7232a9e9297c9 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -381,7 +381,7 @@ struct HistFiller { // fill any type of histogram with columns (Cs) of a filtered table (if weight is requested it must reside the last specified column) template <typename... Cs, typename R, typename T> - static void fillHistAnyTable(std::shared_ptr<R>& hist, const T& table, const o2::framework::expressions::Filter& filter) + static void fillHistAny(std::shared_ptr<R>& hist, const T& table, const o2::framework::expressions::Filter& filter) { auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)}; for (auto& t : filtered) { @@ -482,57 +482,25 @@ struct HistFiller { class HistogramRegistry { public: - HistogramRegistry(char const* const name_, std::vector<HistogramSpec> histSpecs_ = {}, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, bool sortHistos_ = true, bool createRegistryDir_ = false) - : mName(name_), mPolicy(policy_), mRegistryKey(), mRegistryValue(), mSortHistos(sortHistos_), mCreateRegistryDir(createRegistryDir_) + HistogramRegistry(char const* const name, std::vector<HistogramSpec> histSpecs = {}, OutputObjHandlingPolicy policy = OutputObjHandlingPolicy::AnalysisObject, bool sortHistos = true, bool createRegistryDir = false) + : mName(name), mPolicy(policy), mRegistryKey(), mRegistryValue(), mSortHistos(sortHistos), mCreateRegistryDir(createRegistryDir) { mRegistryKey.fill(0u); - for (auto& histSpec : histSpecs_) { + for (auto& histSpec : histSpecs) { insert(histSpec); } } - void add(const HistogramSpec& histSpec_) - { - insert(histSpec_); - } - - void add(char const* const name_, char const* const title_, const HistogramConfigSpec& histConfigSpec_, bool callSumw2_ = false) - { - insert({name_, title_, histConfigSpec_, callSumw2_}); - } - - void add(char const* const name_, char const* const title_, HistType histType_, std::vector<AxisSpec> axes_, bool callSumw2_ = false) - { - insert({name_, title_, {histType_, axes_}, callSumw2_}); - } + // functions to add histograms to the registry + void add(const HistogramSpec& histSpec); + void add(char const* const name, char const* const title, const HistogramConfigSpec& histConfigSpec, bool callSumw2 = false); + void add(char const* const name, char const* const title, HistType histType, std::vector<AxisSpec> axes, bool callSumw2 = false); + void addClone(const std::string& source, const std::string& target); - // store a copy of an existing histogram (or group of histograms) under a different name - void addClone(const std::string& source_, const std::string& target_) + // function to query if name is already in use + bool contains(char const* const name) { - auto doInsertClone = [&](const auto& sharedPtr) { - if (!sharedPtr.get()) { - return; - } - std::string sourceName{((TNamed*)sharedPtr.get())->GetName()}; - // search for histograms starting with source_ substring - if (sourceName.rfind(source_, 0) == 0) { - // when cloning groups of histograms source_ and target_ must end with "/" - if (sourceName.size() != source_.size() && (source_.back() != '/' || target_.back() != '/')) { - return; - } - // when cloning a single histogram the specified target_ must not be a group name - if (sourceName.size() == source_.size() && target_.back() == '/') { - LOGF(FATAL, "Cannot turn histogram into folder!"); - } - std::string targetName{target_}; - targetName += sourceName.substr(sourceName.find(source_) + source_.size()); - insertClone(targetName.data(), sharedPtr); - } - }; - - for (auto& histVariant : mRegistryValue) { - std::visit(doInsertClone, histVariant); - } + return contains(compile_time_hash(name), name); } // gets the underlying histogram pointer @@ -573,59 +541,7 @@ class HistogramRegistry mTaskHash = hash; } - TList* operator*() - { - TList* list = new TList(); - list->SetName(mName.data()); - - for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { - TNamed* rawPtr = nullptr; - std::visit([&](const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[j]); - if (rawPtr) { - std::deque<std::string> path = splitPath(rawPtr->GetName()); - std::string name = path.back(); - path.pop_back(); - TList* targetList{getSubList(list, path)}; - if (targetList) { - rawPtr->SetName(name.data()); - targetList->Add(rawPtr); - } else { - LOGF(FATAL, "Specified subfolder could not be created."); - } - } - } - - // sort histograms in output file alphabetically - if (mSortHistos) { - std::function<void(TList*)> sortList; - sortList = [&](TList* list) { - list->Sort(); - TIter next(list); - TNamed* subList = nullptr; - std::vector<TObject*> subLists; - while ((subList = (TNamed*)next())) { - if (subList->InheritsFrom(TList::Class())) { - subLists.push_back(subList); - sortList((TList*)subList); - } - } - // place lists always at the top - std::reverse(subLists.begin(), subLists.end()); - for (auto curList : subLists) { - list->Remove(curList); - list->AddFirst(curList); - } - }; - sortList(list); - } - - // create dedicated directory containing all of the registrys histograms - if (mCreateRegistryDir) { - // propagate this to the writer by adding a 'flag' to the output list - list->AddLast(new TNamed("createFolder", "")); - } - return list; - } + TList* operator*(); // fill hist with values template <typename... Ts> @@ -638,7 +554,7 @@ class HistogramRegistry template <typename... Cs, typename T> void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) { - std::visit([&table, &filter](auto&& hist) { HistFiller::fillHistAnyTable<Cs...>(hist, table, filter); }, mRegistryValue[getHistIndex(name)]); + std::visit([&table, &filter](auto&& hist) { HistFiller::fillHistAny<Cs...>(hist, table, filter); }, mRegistryValue[getHistIndex(name)]); } // get rough estimate for size of histogram stored in registry @@ -686,7 +602,7 @@ class HistogramRegistry // clone an existing histogram and insert it into the registry template <typename T> - void insertClone(const char* name, const std::shared_ptr<T>& originalHist) + void insertClone(char const* const name, const std::shared_ptr<T>& originalHist) { const uint32_t id = compile_time_hash(name); const uint32_t i = imask(id); @@ -704,7 +620,7 @@ class HistogramRegistry LOGF(FATAL, "Internal array of HistogramRegistry %s is full.", mName); } - inline constexpr uint32_t imask(uint32_t i) const + constexpr uint32_t imask(uint32_t i) const { return i & MASK; } @@ -724,73 +640,16 @@ class HistogramRegistry throw runtime_error("No matching histogram found in HistogramRegistry!"); } + bool contains(const uint32_t id, char const* const name); + // helper function to create resp. find the subList defined by path - TList* getSubList(TList* list, std::deque<std::string>& path) - { - if (path.empty()) { - return list; - } - TList* targetList{nullptr}; - std::string nextList = path[0]; - path.pop_front(); - if (auto subList = (TList*)list->FindObject(nextList.data())) { - if (subList->InheritsFrom(TList::Class())) { - targetList = getSubList((TList*)subList, path); - } else { - return nullptr; - } - } else { - subList = new TList(); - subList->SetName(nextList.data()); - list->Add(subList); - targetList = getSubList(subList, path); - } - return targetList; - } + TList* getSubList(TList* list, std::deque<std::string>& path); // helper function to split user defined path/to/hist/name string - std::deque<std::string> splitPath(const std::string& pathAndNameUser) - { - std::istringstream pathAndNameStream(pathAndNameUser); - std::deque<std::string> pathAndName; - std::string curDir; - while (std::getline(pathAndNameStream, curDir, '/')) { - pathAndName.push_back(curDir); - } - return pathAndName; - } + std::deque<std::string> splitPath(const std::string& pathAndNameUser); // helper function that checks if name of histogram is reasonable and keeps track of names already in use - void registerName(const std::string& name) - { - if (name.empty() || name.back() == '/') { - LOGF(FATAL, "Invalid name for a histogram."); - } - std::deque<std::string> path = splitPath(name); - std::string cumulativeName{}; - int depth = path.size(); - for (auto& step : path) { - if (step.empty()) { - LOGF(FATAL, "Found empty group name in path for histogram %s.", name); - } - cumulativeName += step; - for (auto& curName : mRegisteredNames) { - // there is already a histogram where we want to put a folder or histogram - if (cumulativeName == curName) { - LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); - } - // for the full new histogram name we need to check that none of the existing histograms already uses this as a group name - if (depth == 1) { - if (curName.rfind(cumulativeName, 0) == 0 && curName.size() > cumulativeName.size() && curName.at(cumulativeName.size()) == '/') { - LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); - } - } - } - --depth; - cumulativeName += "/"; - } - mRegisteredNames.push_back(name); - } + void registerName(const std::string& name); std::string mName{}; OutputObjHandlingPolicy mPolicy{}; diff --git a/Framework/Core/src/HistogramRegistry.cxx b/Framework/Core/src/HistogramRegistry.cxx index ba217068edaad..b7ec3d9c0060c 100644 --- a/Framework/Core/src/HistogramRegistry.cxx +++ b/Framework/Core/src/HistogramRegistry.cxx @@ -34,6 +34,67 @@ const std::map<HistType, std::function<HistPtr(const HistogramSpec&)>> HistFacto #undef CALLB +void HistogramRegistry::add(const HistogramSpec& histSpec) +{ + insert(histSpec); +} + +void HistogramRegistry::add(char const* const name, char const* const title, const HistogramConfigSpec& histConfigSpec, bool callSumw2) +{ + insert({name, title, histConfigSpec, callSumw2}); +} + +void HistogramRegistry::add(char const* const name, char const* const title, HistType histType, std::vector<AxisSpec> axes, bool callSumw2) +{ + insert({name, title, {histType, axes}, callSumw2}); +} + +// store a copy of an existing histogram (or group of histograms) under a different name +void HistogramRegistry::addClone(const std::string& source, const std::string& target) +{ + auto doInsertClone = [&](const auto& sharedPtr) { + if (!sharedPtr.get()) { + return; + } + std::string sourceName{((TNamed*)sharedPtr.get())->GetName()}; + // search for histograms starting with source_ substring + if (sourceName.rfind(source, 0) == 0) { + // when cloning groups of histograms source_ and target_ must end with "/" + if (sourceName.size() != source.size() && (source.back() != '/' || target.back() != '/')) { + return; + } + // when cloning a single histogram the specified target_ must not be a group name + if (sourceName.size() == source.size() && target.back() == '/') { + LOGF(FATAL, "Cannot turn histogram into folder!"); + } + std::string targetName{target}; + targetName += sourceName.substr(sourceName.find(source) + source.size()); + insertClone(targetName.data(), sharedPtr); + } + }; + + for (auto& histVariant : mRegistryValue) { + std::visit(doInsertClone, histVariant); + } +} + +// function to query if name is already in use +bool HistogramRegistry::contains(const uint32_t id, char const* const name) +{ + // check for all occurances of the hash + auto iter = mRegistryKey.begin(); + while ((iter = std::find(iter, mRegistryKey.end(), id)) != mRegistryKey.end()) { + const char* curName = nullptr; + std::visit([&](auto&& hist) { if(hist) { curName = hist->GetName(); } }, mRegistryValue[iter - mRegistryKey.begin()]); + // if hash is the same, make sure that name is indeed the same + if (strcmp(curName, name) == 0) { + return true; + } + } + return false; +} + +// print some useful meta-info about the stored histograms void HistogramRegistry::print(bool showAxisDetails) { std::vector<double> fillFractions{0.1, 0.25, 0.5}; @@ -108,4 +169,127 @@ void HistogramRegistry::print(bool showAxisDetails) LOGF(INFO, ""); } +// create output structure will be propagated to file-sink +TList* HistogramRegistry::operator*() +{ + TList* list = new TList(); + list->SetName(mName.data()); + + for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + TNamed* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[j]); + if (rawPtr) { + std::deque<std::string> path = splitPath(rawPtr->GetName()); + std::string name = path.back(); + path.pop_back(); + TList* targetList{getSubList(list, path)}; + if (targetList) { + rawPtr->SetName(name.data()); + targetList->Add(rawPtr); + } else { + LOGF(FATAL, "Specified subfolder could not be created."); + } + } + } + + // sort histograms in output file alphabetically + if (mSortHistos) { + std::function<void(TList*)> sortList; + sortList = [&](TList* list) { + list->Sort(); + TIter next(list); + TNamed* subList = nullptr; + std::vector<TObject*> subLists; + while ((subList = (TNamed*)next())) { + if (subList->InheritsFrom(TList::Class())) { + subLists.push_back(subList); + sortList((TList*)subList); + } + } + // place lists always at the top + std::reverse(subLists.begin(), subLists.end()); + for (auto curList : subLists) { + list->Remove(curList); + list->AddFirst(curList); + } + }; + sortList(list); + } + + // create dedicated directory containing all of the registrys histograms + if (mCreateRegistryDir) { + // propagate this to the writer by adding a 'flag' to the output list + list->AddLast(new TNamed("createFolder", "")); + } + return list; +} + +// helper function to create resp. find the subList defined by path +TList* HistogramRegistry::getSubList(TList* list, std::deque<std::string>& path) +{ + if (path.empty()) { + return list; + } + TList* targetList{nullptr}; + std::string nextList = path[0]; + path.pop_front(); + if (auto subList = (TList*)list->FindObject(nextList.data())) { + if (subList->InheritsFrom(TList::Class())) { + targetList = getSubList((TList*)subList, path); + } else { + return nullptr; + } + } else { + subList = new TList(); + subList->SetName(nextList.data()); + list->Add(subList); + targetList = getSubList(subList, path); + } + return targetList; +} + +// helper function to split user defined path/to/hist/name string +std::deque<std::string> HistogramRegistry::splitPath(const std::string& pathAndNameUser) +{ + std::istringstream pathAndNameStream(pathAndNameUser); + std::deque<std::string> pathAndName; + std::string curDir; + while (std::getline(pathAndNameStream, curDir, '/')) { + pathAndName.push_back(curDir); + } + return pathAndName; +} + +// helper function that checks if name of histogram is reasonable and keeps track of names already in use +void HistogramRegistry::registerName(const std::string& name) +{ + if (name.empty() || name.back() == '/') { + LOGF(FATAL, "Invalid name for a histogram."); + } + std::deque<std::string> path = splitPath(name); + std::string cumulativeName{}; + int depth = path.size(); + for (auto& step : path) { + if (step.empty()) { + LOGF(FATAL, "Found empty group name in path for histogram %s.", name); + } + cumulativeName += step; + for (auto& curName : mRegisteredNames) { + // there is already a histogram where we want to put a folder or histogram + if (cumulativeName == curName) { + LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); + } + // for the full new histogram name we need to check that none of the existing histograms already uses this as a group name + if (depth == 1) { + if (curName.rfind(cumulativeName, 0) == 0 && curName.size() > cumulativeName.size() && curName.at(cumulativeName.size()) == '/') { + LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); + } + } + } + --depth; + cumulativeName += "/"; + } + mRegisteredNames.push_back(name); +} + } // namespace o2::framework From 1b8bea430dd6c8d5243691bca49e93dd1e3a30ba Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Thu, 5 Nov 2020 11:50:32 +0100 Subject: [PATCH 1209/1751] DPL: Add array support to Variant (#4754) --- Framework/Core/include/Framework/Variant.h | 268 ++++++++++++------- Framework/Core/src/BoostOptionsRetriever.cxx | 4 + Framework/Core/src/ConfigParamsHelper.cxx | 4 + Framework/Core/src/Variant.cxx | 31 ++- Framework/Core/test/test_Variants.cxx | 46 +++- 5 files changed, 245 insertions(+), 108 deletions(-) diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index cc3ac3ac008ba..f14b2c99ffeb7 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -18,6 +18,7 @@ #include <iosfwd> #include <initializer_list> #include <string_view> +#include <vector> #include <string> namespace o2 @@ -31,6 +32,10 @@ enum class VariantType : int { Int = 0, Double, String, Bool, + ArrayInt, + ArrayFloat, + ArrayDouble, + ArrayBool, Empty, Unknown }; @@ -38,53 +43,27 @@ template <typename T> struct variant_trait : std::integral_constant<VariantType, VariantType::Unknown> { }; -template <> -struct variant_trait<int> : std::integral_constant<VariantType, VariantType::Int> { -}; - -template <> -struct variant_trait<long int> : std::integral_constant<VariantType, VariantType::Int64> { -}; - -template <> -struct variant_trait<long long int> : std::integral_constant<VariantType, VariantType::Int64> { -}; - -template <> -struct variant_trait<float> : std::integral_constant<VariantType, VariantType::Float> { -}; - -template <> -struct variant_trait<double> : std::integral_constant<VariantType, VariantType::Double> { -}; - -template <> -struct variant_trait<const char*> : std::integral_constant<VariantType, VariantType::String> { -}; - -template <> -struct variant_trait<char*> : std::integral_constant<VariantType, VariantType::String> { -}; - -template <> -struct variant_trait<char* const> : std::integral_constant<VariantType, VariantType::String> { -}; - -template <> -struct variant_trait<const char* const> : std::integral_constant<VariantType, VariantType::String> { -}; - -template <> -struct variant_trait<std::string_view> : std::integral_constant<VariantType, VariantType::String> { -}; - -template <> -struct variant_trait<std::string> : std::integral_constant<VariantType, VariantType::String> { -}; - -template <> -struct variant_trait<bool> : std::integral_constant<VariantType, VariantType::Bool> { -}; +#define DECLARE_VARIANT_TRAIT(_Type1_, _Type2_) \ + template <> \ + struct variant_trait<_Type1_> : std::integral_constant<VariantType, VariantType::_Type2_> { \ + }; + +DECLARE_VARIANT_TRAIT(int, Int); +DECLARE_VARIANT_TRAIT(long int, Int64); +DECLARE_VARIANT_TRAIT(long long int, Int64); +DECLARE_VARIANT_TRAIT(float, Float); +DECLARE_VARIANT_TRAIT(double, Double); +DECLARE_VARIANT_TRAIT(const char*, String); +DECLARE_VARIANT_TRAIT(char*, String); +DECLARE_VARIANT_TRAIT(char* const, String); +DECLARE_VARIANT_TRAIT(const char* const, String); +DECLARE_VARIANT_TRAIT(std::string_view, String); +DECLARE_VARIANT_TRAIT(std::string, String); +DECLARE_VARIANT_TRAIT(bool, Bool); +DECLARE_VARIANT_TRAIT(int*, ArrayInt); +DECLARE_VARIANT_TRAIT(float*, ArrayFloat); +DECLARE_VARIANT_TRAIT(double*, ArrayDouble); +DECLARE_VARIANT_TRAIT(bool*, ArrayBool); template <typename T> inline constexpr VariantType variant_trait_v = variant_trait<T>::value; @@ -93,39 +72,34 @@ template <VariantType type> struct variant_type { }; -template <> -struct variant_type<VariantType::Int> { - using type = int; -}; - -template <> -struct variant_type<VariantType::Int64> { - using type = int64_t; -}; - -template <> -struct variant_type<VariantType::Float> { - using type = float; -}; - -template <> -struct variant_type<VariantType::Double> { - using type = double; -}; - -template <> -struct variant_type<VariantType::String> { - using type = const char*; -}; - -template <> -struct variant_type<VariantType::Bool> { - using type = bool; -}; +#define DECLARE_VARIANT_TYPE(_Type1_, _Type2_) \ + template <> \ + struct variant_type<VariantType::_Type2_> { \ + using type = _Type1_; \ + }; + +DECLARE_VARIANT_TYPE(int, Int); +DECLARE_VARIANT_TYPE(int64_t, Int64); +DECLARE_VARIANT_TYPE(float, Float); +DECLARE_VARIANT_TYPE(double, Double); +DECLARE_VARIANT_TYPE(const char*, String); +DECLARE_VARIANT_TYPE(bool, Bool); +DECLARE_VARIANT_TYPE(int*, ArrayInt); +DECLARE_VARIANT_TYPE(float*, ArrayFloat); +DECLARE_VARIANT_TYPE(double*, ArrayDouble); +DECLARE_VARIANT_TYPE(bool*, ArrayBool); template <typename S, typename T> struct variant_helper { static void set(S* store, T value) { *(reinterpret_cast<T*>(store)) = value; } + static void set(S* store, T values, size_t size) + { + *reinterpret_cast<T*>(store) = reinterpret_cast<T>(std::memcpy(std::malloc(size * sizeof(std::remove_pointer_t<T>)), reinterpret_cast<void*>(values), size * sizeof(std::remove_pointer_t<T>))); + } + static void reset(S* store, T values, size_t) + { + *reinterpret_cast<T*>(store) = values; + } static T get(const S* store) { return *(reinterpret_cast<const T*>(store)); } }; @@ -151,24 +125,34 @@ struct variant_helper<S, std::string> { static void set(S* store, std::string value) { *reinterpret_cast<char**>(store) = strdup(value.data()); } }; -// Poor man variant class. Does not take ownership of anything passed to it. -// FIXME: we should really use C++17 std::variant when it -// comes about +/// Variant for configuration parameter storage. Owns stored data. class Variant { - using storage_t = std::aligned_union<8, int, int64_t, const char*, float, double, bool>::type; + using storage_t = std::aligned_union<8, int, int64_t, const char*, float, double, bool, int*, float*, double*, bool*>::type; public: - Variant(VariantType type = VariantType::Unknown) : mType{type} {} + Variant(VariantType type = VariantType::Unknown) : mType{type}, mSize{1} {} template <typename T> - Variant(T value) : mType{variant_trait_v<T>} + Variant(T value) : mType{variant_trait_v<T>}, mSize{1} { variant_helper<storage_t, decltype(value)>::set(&mStore, value); } template <typename T> - Variant(std::initializer_list<T>) : mType{VariantType::Unknown} + Variant(T values, size_t size) : mType{variant_trait_v<T>}, mSize{size} + { + variant_helper<storage_t, T>::set(&mStore, values, mSize); + } + + template <typename T> + Variant(std::vector<T>& values) : mType{variant_trait_v<T*>}, mSize{values.size()} + { + variant_helper<storage_t, T*>::set(&mStore, values.data(), mSize); + } + + template <typename T> + Variant(std::initializer_list<T>) : mType{VariantType::Unknown}, mSize{1} { static_assert(sizeof(T) == 0, "brace-enclosed initializer list forbidden for Variant" @@ -177,42 +161,105 @@ class Variant Variant(const Variant& other) : mType(other.mType) { - // In case this is a string we need to duplicate it to avoid + // In case this is an array we need to duplicate it to avoid // double deletion. - if (mType == variant_trait_v<const char*>) { - variant_helper<storage_t, const char*>::set(&mStore, other.get<const char*>()); - } else { - mStore = other.mStore; + switch (mType) { + case variant_trait_v<const char*>: + mSize = other.mSize; + variant_helper<storage_t, const char*>::set(&mStore, other.get<const char*>()); + return; + case variant_trait_v<int*>: + mSize = other.mSize; + variant_helper<storage_t, int*>::set(&mStore, other.get<int*>(), mSize); + return; + case variant_trait_v<float*>: + mSize = other.mSize; + variant_helper<storage_t, float*>::set(&mStore, other.get<float*>(), mSize); + return; + case variant_trait_v<double*>: + mSize = other.mSize; + variant_helper<storage_t, double*>::set(&mStore, other.get<double*>(), mSize); + return; + case variant_trait_v<bool*>: + mSize = other.mSize; + variant_helper<storage_t, bool*>::set(&mStore, other.get<bool*>(), mSize); + return; + default: + mStore = other.mStore; + mSize = other.mSize; } } Variant(Variant&& other) : mType(other.mType) { - // In case this is a string we need to duplicate it to avoid - // double deletion. - if (mType == variant_trait_v<const char*>) { - mStore = other.mStore; - *reinterpret_cast<char**>(&(other.mStore)) = nullptr; - } else { - mStore = other.mStore; + mStore = other.mStore; + mSize = other.mSize; + switch (mType) { + case variant_trait_v<const char*>: + *reinterpret_cast<char**>(&(other.mStore)) = nullptr; + return; + case variant_trait_v<int*>: + *reinterpret_cast<int**>(&(other.mStore)) = nullptr; + return; + case variant_trait_v<float*>: + *reinterpret_cast<float**>(&(other.mStore)) = nullptr; + return; + case variant_trait_v<double*>: + *reinterpret_cast<double**>(&(other.mStore)) = nullptr; + return; + case variant_trait_v<bool*>: + *reinterpret_cast<bool**>(&(other.mStore)) = nullptr; + return; + default: + return; } } ~Variant() { - // In case we allocated a string out of bound, we + // In case we allocated an array, we // should delete it. - if (mType == variant_trait_v<const char*> || mType == variant_trait_v<char*>) { - free(*reinterpret_cast<void**>(&mStore)); + switch (mType) { + case variant_trait_v<const char*>: + case variant_trait_v<int*>: + case variant_trait_v<float*>: + case variant_trait_v<double*>: + case variant_trait_v<bool*>: + if (reinterpret_cast<void**>(&mStore) != nullptr) { + free(*reinterpret_cast<void**>(&mStore)); + } + return; + default: + return; } } void operator=(const Variant& other) { - if (mType == variant_trait_v<const char*>) { - variant_helper<storage_t, const char*>::set(&mStore, other.get<const char*>()); - } else { - mStore = other.mStore; + switch (mType) { + case variant_trait_v<const char*>: + mSize = other.mSize; + variant_helper<storage_t, const char*>::set(&mStore, other.get<const char*>()); + return; + case variant_trait_v<int*>: + mSize = other.mSize; + variant_helper<storage_t, int*>::set(&mStore, other.get<int*>(), mSize); + return; + case variant_trait_v<float*>: + mSize = other.mSize; + variant_helper<storage_t, float*>::set(&mStore, other.get<float*>(), mSize); + return; + case variant_trait_v<double*>: + mSize = other.mSize; + variant_helper<storage_t, double*>::set(&mStore, other.get<double*>(), mSize); + return; + case variant_trait_v<bool*>: + mSize = other.mSize; + variant_helper<storage_t, bool*>::set(&mStore, other.get<bool*>(), mSize); + return; + default: + mStore = other.mStore; + mSize = other.mSize; } } @@ -228,15 +275,30 @@ class Variant template <typename T> void set(T value) { - return variant_helper<storage_t, T>::set(mStore, value); + return variant_helper<storage_t, T>::set(&mStore, value); + } + + template <typename T> + void set(T value, size_t size) + { + mSize = size; + return variant_helper<storage_t, T>::set(&mStore, value, mSize); + } + + template <typename T> + void set(std::vector<T>& values) + { + return variant_helper<storage_t, T*>::set(&mStore, values.data(), values.size()); } VariantType type() const { return mType; } + size_t size() const { return mSize; } private: friend std::ostream& operator<<(std::ostream& oss, Variant const& val); storage_t mStore; VariantType mType; + size_t mSize = 1; }; } // namespace framework diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index 892574e3eae11..df87c691a60b3 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -64,6 +64,10 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> const& specs, case VariantType::Bool: options = options(name, bpo::value<bool>()->zero_tokens()->default_value(spec.defaultValue.get<bool>()), help); break; + case VariantType::ArrayInt: + case VariantType::ArrayFloat: + case VariantType::ArrayDouble: + case VariantType::ArrayBool: case VariantType::Unknown: case VariantType::Empty: break; diff --git a/Framework/Core/src/ConfigParamsHelper.cxx b/Framework/Core/src/ConfigParamsHelper.cxx index 4fa7415b9234e..e41ab45af7bb1 100644 --- a/Framework/Core/src/ConfigParamsHelper.cxx +++ b/Framework/Core/src/ConfigParamsHelper.cxx @@ -59,6 +59,10 @@ void ConfigParamsHelper::populateBoostProgramOptions( case VariantType::Bool: addConfigSpecOption<VariantType::Bool>(spec, options); break; + case VariantType::ArrayInt: + case VariantType::ArrayFloat: + case VariantType::ArrayDouble: + case VariantType::ArrayBool: case VariantType::Unknown: case VariantType::Empty: break; diff --git a/Framework/Core/src/Variant.cxx b/Framework/Core/src/Variant.cxx index 151a728f93b9c..53d75228ef388 100644 --- a/Framework/Core/src/Variant.cxx +++ b/Framework/Core/src/Variant.cxx @@ -10,10 +10,22 @@ #include "Framework/Variant.h" #include <iostream> -namespace o2 +namespace o2::framework { -namespace framework + +namespace +{ +template <typename T> +void printArray(std::ostream& oss, T* array, size_t size) { + for (auto i = 0u; i < size; ++i) { + oss << array[i]; + if (i < size - 1) { + oss << ", "; + } + } +} +} // namespace std::ostream& operator<<(std::ostream& oss, Variant const& val) { @@ -36,6 +48,18 @@ std::ostream& operator<<(std::ostream& oss, Variant const& val) case VariantType::Bool: oss << val.get<bool>(); break; + case VariantType::ArrayInt: + printArray<int>(oss, val.get<int*>(), val.size()); + break; + case VariantType::ArrayFloat: + printArray<float>(oss, val.get<float*>(), val.size()); + break; + case VariantType::ArrayDouble: + printArray<double>(oss, val.get<double*>(), val.size()); + break; + case VariantType::ArrayBool: + printArray<bool>(oss, val.get<bool*>(), val.size()); + break; case VariantType::Empty: break; default: @@ -45,5 +69,4 @@ std::ostream& operator<<(std::ostream& oss, Variant const& val) return oss; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/test/test_Variants.cxx b/Framework/Core/test/test_Variants.cxx index 671b62a6dabfb..0b34a853f8713 100644 --- a/Framework/Core/test/test_Variants.cxx +++ b/Framework/Core/test/test_Variants.cxx @@ -55,10 +55,54 @@ BOOST_AUTO_TEST_CASE(VariantTest) Variant sa("foo"); Variant sb(sa); // Copy constructor Variant sc(std::move(sa)); // Move constructor - Variant sd = sc; // Copy operator + Variant sd = sc; // Copy assignment BOOST_CHECK(std::string(sb.get<const char*>()) == "foo"); BOOST_CHECK(std::string(sc.get<const char*>()) == "foo"); BOOST_CHECK(std::string(sd.get<const char*>()) == "foo"); BOOST_CHECK(sa.get<const char*>() == nullptr); + + int iarr[] = {1, 2, 3, 4, 5}; + float farr[] = {0.2, 0.3, 123.123, 123.123, 3.005e-5, 1.1e6}; + std::vector<double> dvec = {0.1, 0.2, 0.4, 0.9, 1.3, 14.5, 123.234, 1.213e-20}; + Variant viarr(iarr, 5); + Variant vfarr(farr, 6); + Variant vdvec(dvec); + + BOOST_CHECK(viarr.size() == 5); + BOOST_CHECK(viarr.get<int*>() != iarr); + for (auto i = 0u; i < viarr.size(); ++i) { + BOOST_CHECK(iarr[i] == (viarr.get<int*>())[i]); + } + + BOOST_CHECK(vfarr.size() == 6); + BOOST_CHECK(vfarr.get<float*>() != farr); + for (auto i = 0u; i < vfarr.size(); ++i) { + BOOST_CHECK(farr[i] == (vfarr.get<float*>())[i]); + } + + BOOST_CHECK(vdvec.size() == dvec.size()); + BOOST_CHECK(vdvec.get<double*>() != dvec.data()); + for (auto i = 0u; i < dvec.size(); ++i) { + BOOST_CHECK(dvec[i] == (vdvec.get<double*>())[i]); + } + + Variant fb(vfarr); // Copy constructor + Variant fc(std::move(vfarr)); // Move constructor + Variant fd = fc; // Copy assignment + + BOOST_CHECK(vfarr.get<float*>() == nullptr); + + BOOST_CHECK(fb.get<float*>() != farr); + for (auto i = 0u; i < fb.size(); ++i) { + BOOST_CHECK(farr[i] == (fb.get<float*>())[i]); + } + BOOST_CHECK(fc.get<float*>() != farr); + for (auto i = 0u; i < fc.size(); ++i) { + BOOST_CHECK(farr[i] == (fc.get<float*>())[i]); + } + BOOST_CHECK(fd.get<float*>() != farr); + for (auto i = 0u; i < fd.size(); ++i) { + BOOST_CHECK(farr[i] == (fd.get<float*>())[i]); + } } From ae5b8dc89d24a77047e055f43c876d7607b956a3 Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Thu, 5 Nov 2020 12:29:30 +0100 Subject: [PATCH 1210/1751] Applied change for TOF commissioning in real data (#4755) * Must reset TRM TDC error counter in case header/trailer is not detected * Stop decoding if error is found in CONET mode * Increase size of buffers and alloc them dynamically * Make sure we reset counters and flags in the most extreme error case * Add labels for the Diagnostic bits * Add DRM and TRM_DECODE_ERROR diagnostic check and bit * add conet mode for raw decoding to digits add on-the-fly noise filter in TOF decoding for cosmic runs allowing filtering emtpy row in TOF digits add diagnostic and error in TOF decoding fix in TOF encoding (word counter) * order TOF patterns according to crate and readout window update TOF CTF with crate info for diagnostic * keep TOF row if diagnostic words available also in filtered mode * Add labels for the Diagnostic bits * Add DRM and TRM_DECODE_ERROR diagnostic check and bit * add conet mode for raw decoding to digits add on-the-fly noise filter in TOF decoding for cosmic runs allowing filtering emtpy row in TOF digits add diagnostic and error in TOF decoding fix in TOF encoding (word counter) * order TOF patterns according to crate and readout window update TOF CTF with crate info for diagnostic * keep TOF row if diagnostic words available also in filtered mode * use bc and eventcounter during TOF decoding * Add labels for the Diagnostic bits * Add DRM and TRM_DECODE_ERROR diagnostic check and bit * order TOF patterns according to crate and readout window update TOF CTF with crate info for diagnostic * keep TOF row if diagnostic words available also in filtered mode * use bc and eventcounter during TOF decoding * fix rebasing * fix for trigger bc decoding * restore version 1 of TOF CTF * add event counter and tracing of empty crates in TOF decoding * change way to trace TOF empty crates, adding also header with counter of failures * add TOFSimParams * Add labels for the Diagnostic bits * Add DRM and TRM_DECODE_ERROR diagnostic check and bit * order TOF patterns according to crate and readout window update TOF CTF with crate info for diagnostic * keep TOF row if diagnostic words available also in filtered mode * use bc and eventcounter during TOF decoding * fix rebasing * fix for trigger bc decoding * Add labels for the Diagnostic bits * Add DRM and TRM_DECODE_ERROR diagnostic check and bit * add conet mode for raw decoding to digits add on-the-fly noise filter in TOF decoding for cosmic runs allowing filtering emtpy row in TOF digits add diagnostic and error in TOF decoding fix in TOF encoding (word counter) * order TOF patterns according to crate and readout window update TOF CTF with crate info for diagnostic * use bc and eventcounter during TOF decoding * add conet mode for raw decoding to digits add on-the-fly noise filter in TOF decoding for cosmic runs allowing filtering emtpy row in TOF digits add diagnostic and error in TOF decoding fix in TOF encoding (word counter) * order TOF patterns according to crate and readout window update TOF CTF with crate info for diagnostic * restore version 1 of TOF CTF * add event counter and tracing of empty crates in TOF decoding * change way to trace TOF empty crates, adding also header with counter of failures * add TOFSimParams * replace TOF INFOs with DEBUGs * add specific TOF digit writer for commissioning tests * add counters for number of crates active in a TOF row * Please consider the following formatting changes * fix for PR4755 Co-authored-by: Roberto Preghenella <preghenella@bo.infn.it> Co-authored-by: ALICE Action Bot <alibuild@cern.ch> --- Detectors/TOF/base/include/TOFBase/Digit.h | 47 ++++- .../TOF/base/include/TOFBase/WindowFiller.h | 16 +- Detectors/TOF/base/src/TOFBaseLinkDef.h | 4 +- Detectors/TOF/base/src/WindowFiller.cxx | 64 ++++++- .../include/TOFReconstruction/CTFCoder.h | 3 +- Detectors/TOF/reconstruction/src/CTFCoder.cxx | 6 +- .../TOF/reconstruction/src/Clusterer.cxx | 8 +- Detectors/TOF/reconstruction/src/Decoder.cxx | 2 +- Detectors/TOF/simulation/CMakeLists.txt | 5 +- .../include/TOFSimulation/TOFSimParams.h | 41 +++++ Detectors/TOF/simulation/src/Digitizer.cxx | 11 +- Detectors/TOF/simulation/src/TOFSimParams.cxx | 12 ++ .../TOF/simulation/src/TOFSimulationLinkDef.h | 3 + Detectors/TOF/workflow/CMakeLists.txt | 4 + .../TOFDigitWriterSplitterSpec.h | 160 ++++++++++++++++++ .../workflow/src/CompressedDecodingTask.cxx | 8 + .../TOF/workflow/src/EntropyDecoderSpec.cxx | 2 + .../TOF/workflow/src/TOFDigitWriterSpec.cxx | 8 + .../src/digit-writer-commissioning.cxx | 39 +++++ .../src/TOFDigitizerSpec.cxx | 4 + 20 files changed, 420 insertions(+), 27 deletions(-) create mode 100644 Detectors/TOF/simulation/include/TOFSimulation/TOFSimParams.h create mode 100644 Detectors/TOF/simulation/src/TOFSimParams.cxx create mode 100644 Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h create mode 100644 Detectors/TOF/workflow/src/digit-writer-commissioning.cxx diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index 69627ea275c8e..ae07cb36e175f 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -116,15 +116,27 @@ struct ReadoutWindowData { o2::dataformats::RangeReference<int, int> refDiagnostic; // crate info for diagnostic patterns - int mNdiaCrate[72] = {0}; + int mNdiaCrate[Geo::kNCrate] = {0}; + int mDeltaBCCrate[Geo::kNCrate] = {0}; + int mDeltaEventCounterCrate[Geo::kNCrate] = {0}; InteractionRecord mFirstIR{0, 0}; + int mEventCounter = 0; const InteractionRecord& getBCData() const { return mFirstIR; } + void setEmptyCrate(int crate) { mNdiaCrate[crate] = -1; } + bool isEmptyCrate(int crate) const { return (mNdiaCrate[crate] == -1); } void addedDiagnostic(int crate) { mNdiaCrate[crate]++; } void setDiagnosticInCrate(int crate, int val) { mNdiaCrate[crate] = val; } - int getDiagnosticInCrate(int crate) const { return mNdiaCrate[crate]; } + int getDiagnosticInCrate(int crate) const + { + if (isEmptyCrate(crate)) { + return 0; + } else { + return mNdiaCrate[crate]; + } + } void setBCData(int orbit, int bc) { @@ -164,7 +176,36 @@ struct ReadoutWindowData { void setFirstEntryDia(int first) { refDiagnostic.setFirstEntry(first); } void setNEntriesDia(int ne) { refDiagnostic.setEntries(ne); } - ClassDefNV(ReadoutWindowData, 3); + void setEventCounter(int ev) { mEventCounter = ev; } + void setDeltaEventCounterCrate(int crate, int ev) { mDeltaEventCounterCrate[crate] = ev; } + int getEventCounter() const { return mEventCounter; } + int getDeltaEventCounterCrate(int crate) const { return mDeltaEventCounterCrate[crate]; } + void setDeltaBCCrate(int crate, int bc) { mDeltaBCCrate[crate] = bc; } + int getDeltaBCCrate(int crate) const { return mDeltaBCCrate[crate]; } + + ClassDefNV(ReadoutWindowData, 4); +}; + +struct DigitHeader { + int mCountsCrate[Geo::kNCrate] = {0}; + int mNumberOfCrates[Geo::kNCrate] = {0}; + int mCountsRow = 0; + + void clear() + { + memset(mCountsCrate, 0, Geo::kNCrate * 4); + memset(mNumberOfCrates, 0, Geo::kNCrate * 4); + mCountsRow = 0; + } + DigitHeader() { clear(); } + void addRow() { mCountsRow++; } + int getNRow() const { return mCountsRow; } + void crateSeen(int crate) { mCountsCrate[crate]++; } + void numCratesSeen(int ncrates) { mNumberOfCrates[ncrates]++; } + int getCrateCounts(int crate) const { return mCountsCrate[crate]; } + int numCratesCounts(int ncrates) const { return mNumberOfCrates[ncrates]; } + + ClassDefNV(DigitHeader, 2); }; } // namespace tof diff --git a/Detectors/TOF/base/include/TOFBase/WindowFiller.h b/Detectors/TOF/base/include/TOFBase/WindowFiller.h index 9ff6a7123d8bc..4c2f43764cd9c 100644 --- a/Detectors/TOF/base/include/TOFBase/WindowFiller.h +++ b/Detectors/TOF/base/include/TOFBase/WindowFiller.h @@ -28,11 +28,18 @@ class WindowFiller struct PatternData { uint32_t pattern; int icrate; + unsigned long row; PatternData(uint32_t patt = 0, int icr = 0, unsigned long rw = 0) : pattern(patt), icrate(icr), row(rw) {} }; + struct CrateHeaderData { + int32_t bc[Geo::kNCrate] = {-1}; + uint32_t eventCounter[Geo::kNCrate] = {0}; + CrateHeaderData() { memset(bc, -1, Geo::kNCrate * 4); } + }; + WindowFiller() { initObj(); }; ~WindowFiller() = default; @@ -50,6 +57,7 @@ class WindowFiller std::vector<Digit>* getDigitPerTimeFrame() { return &mDigitsPerTimeFrame; } std::vector<ReadoutWindowData>* getReadoutWindowData() { return &mReadoutWindowData; } std::vector<ReadoutWindowData>* getReadoutWindowDataFiltered() { return &mReadoutWindowDataFiltered; } + DigitHeader& getDigitHeader() { return mDigitHeader; } void fillOutputContainer(std::vector<Digit>& digits); void flushOutputContainer(std::vector<Digit>& digits); // flush all residual buffered data @@ -68,7 +76,8 @@ class WindowFiller } std::vector<uint32_t>& getPatterns() { return mPatterns; } - void addPattern(const uint32_t val, int icrate, int orbit, int bc) { mCratePatterns.emplace_back(val, icrate, orbit * 3 + (bc + 100) / 1188); } + void addPattern(const uint32_t val, int icrate, int orbit, int bc) { mCratePatterns.emplace_back(val, icrate, orbit * 3 + (bc + 100) / Geo::BC_IN_WINDOW); } + void addCrateHeaderData(unsigned long orbit, int crate, int32_t bc, uint32_t eventCounter); protected: // info TOF timewindow @@ -106,6 +115,9 @@ class WindowFiller std::vector<uint64_t> mErrors; std::vector<PatternData> mCratePatterns; + std::vector<CrateHeaderData> mCrateHeaderData; + + DigitHeader mDigitHeader; void fillDigitsInStrip(std::vector<Strip>* strips, int channel, int tdc, int tot, uint64_t nbc, UInt_t istrip, uint32_t triggerorbit = 0, uint16_t triggerbunch = 0); // void fillDigitsInStrip(std::vector<Strip>* strips, o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer, int channel, int tdc, int tot, int nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID); @@ -136,7 +148,7 @@ class WindowFiller return true; } - ClassDefNV(WindowFiller, 1); + ClassDefNV(WindowFiller, 2); }; } // namespace tof } // namespace o2 diff --git a/Detectors/TOF/base/src/TOFBaseLinkDef.h b/Detectors/TOF/base/src/TOFBaseLinkDef.h index 75e88f696b0d1..f5cc651c66c47 100644 --- a/Detectors/TOF/base/src/TOFBaseLinkDef.h +++ b/Detectors/TOF/base/src/TOFBaseLinkDef.h @@ -21,5 +21,7 @@ #pragma link C++ class o2::tof::WindowFiller + ; #pragma link C++ class o2::tof::ReadoutWindowData + ; #pragma link C++ class vector < o2::tof::ReadoutWindowData> + ; - +#pragma link C++ class o2::tof::DigitHeader + ; +#pragma link C++ class vector < o2::tof::DigitHeader> + ; +#pragma link C++ class vector < unsigned int> + ; #endif diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index 0457cb274608f..6b8094f6661c7 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -97,6 +97,8 @@ void WindowFiller::reset() mReadoutWindowData.clear(); mReadoutWindowDataFiltered.clear(); + mDigitHeader.clear(); + mFirstIR.bc = 0; mFirstIR.orbit = 0; } @@ -107,6 +109,22 @@ void WindowFiller::fillDigitsInStrip(std::vector<Strip>* strips, int channel, in (*strips)[istrip].addDigit(channel, tdc, tot, nbc, 0, triggerorbit, triggerbunch); } //______________________________________________________________________ +void WindowFiller::addCrateHeaderData(unsigned long orbit, int crate, int32_t bc, uint32_t eventCounter) +{ + if (orbit < mFirstIR.orbit) + return; + orbit -= mFirstIR.orbit; + + orbit *= Geo::NWINDOW_IN_ORBIT; // move from orbit to N readout window + orbit += (bc + 100) / Geo::BC_IN_WINDOW; // select readout window in the orbit according to the BC (100 shift to avoid border effects) + + if (mCrateHeaderData.size() < orbit + 1) + mCrateHeaderData.resize(orbit + 1); + + mCrateHeaderData[orbit].bc[crate] = bc; + mCrateHeaderData[orbit].eventCounter[crate] = eventCounter; +} +//______________________________________________________________________ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) { if (mContinuous) { @@ -122,9 +140,45 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) int first = mDigitsPerTimeFrame.size(); int ne = digits.size(); ReadoutWindowData info(first, ne); - int orbit_shift = mReadoutWindowData.size() / 3; - int bc_shift = (mReadoutWindowData.size() % 3) * Geo::BC_IN_WINDOW; + int orbit_shift = mReadoutWindowData.size() / Geo::NWINDOW_IN_ORBIT; + + mDigitHeader.addRow(); + + int bc_shift = -1; + int eventcounter = -1; + int ncratesSeen = 0; + if (mReadoutWindowData.size() >= mCrateHeaderData.size()) { + bc_shift = (mReadoutWindowData.size() % Geo::NWINDOW_IN_ORBIT) * Geo::BC_IN_WINDOW; // insert default value + eventcounter = mReadoutWindowData.size() % 4096; + for (int icrate = 0; icrate < Geo::kNCrate; icrate++) { + info.setEmptyCrate(icrate); + } + } else { + unsigned long irow = mReadoutWindowData.size(); + for (int icrate = 0; icrate < Geo::kNCrate; icrate++) { + if (mCrateHeaderData[irow].bc[icrate] == -1) { // crate not read + info.setEmptyCrate(icrate); + continue; + } else + mDigitHeader.crateSeen(icrate); + ncratesSeen++; + + if (bc_shift == -1 || mCrateHeaderData[irow].bc[icrate] < bc_shift) + bc_shift = mCrateHeaderData[irow].bc[icrate]; + if (eventcounter == -1 || mCrateHeaderData[irow].eventCounter[icrate] < eventcounter) + eventcounter = mCrateHeaderData[irow].eventCounter[icrate]; + } + + mDigitHeader.numCratesSeen(ncratesSeen); + + if (bc_shift == -1) + bc_shift = (mReadoutWindowData.size() % Geo::NWINDOW_IN_ORBIT) * Geo::BC_IN_WINDOW; // insert default value + if (eventcounter == -1) + eventcounter = mReadoutWindowData.size() % 4096; // insert default value + } + info.setBCData(mFirstIR.orbit + orbit_shift, mFirstIR.bc + bc_shift); + info.setEventCounter(eventcounter); int firstPattern = mPatterns.size(); int npatterns = 0; @@ -147,7 +201,7 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) info.setFirstEntryDia(firstPattern); info.setNEntriesDia(npatterns); - if (digits.size()) { + if (digits.size() || npatterns) { mDigitsPerTimeFrame.insert(mDigitsPerTimeFrame.end(), digits.begin(), digits.end()); mReadoutWindowDataFiltered.push_back(info); } @@ -178,9 +232,7 @@ void WindowFiller::flushOutputContainer(std::vector<Digit>& digits) // sort patterns (diagnostic words) in time std::sort(mCratePatterns.begin(), mCratePatterns.end(), - [](PatternData a, PatternData b) { if(a.row == b.row) { return a.icrate > b.icrate; } else { return a.row > b.row; - -} }); + [](PatternData a, PatternData b) { if(a.row == b.row) { return a.icrate > b.icrate; } else { return a.row > b.row; } }); for (Int_t i = 0; i < MAXWINDOWS; i++) { int n = 0; diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h index 303490ad74ba3..edea8157d760e 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/CTFCoder.h @@ -165,9 +165,8 @@ void CTFCoder::decompress(const CompressedInfos& cc, VROF& rofRecVec, VDIG& cdig rofRec.setFirstEntryDia(ndiagnostic); rofRec.setNEntriesDia(cc.ndiaROF[irof]); for (int icrate = 0; icrate < 72; icrate++) { - rofRec.setDiagnosticInCrate(icrate, cc.ndiaCrate[irof * 72 + icrate]); + rofRec.setDiagnosticInCrate(icrate, cc.ndiaCrate[irof * 72 + icrate] - 1); // -1 because number were traslated since (-1 means crate not available) } - firstEntry += cc.ndigROF[irof]; ndiagnostic += cc.ndiaROF[irof]; diff --git a/Detectors/TOF/reconstruction/src/CTFCoder.cxx b/Detectors/TOF/reconstruction/src/CTFCoder.cxx index 58676a9406dbc..8a72aab4ac933 100644 --- a/Detectors/TOF/reconstruction/src/CTFCoder.cxx +++ b/Detectors/TOF/reconstruction/src/CTFCoder.cxx @@ -94,7 +94,11 @@ void CTFCoder::compress(CompressedInfos& cc, cc.ndigROF[irof] = ndig; cc.ndiaROF[irof] = rofRec.sizeDia(); for (int icrate = 0; icrate < 72; icrate++) { - cc.ndiaCrate[irof * 72 + icrate] = rofRec.getDiagnosticInCrate(icrate); + if (rofRec.isEmptyCrate(icrate)) { + cc.ndiaCrate[irof * 72 + icrate] = 0; + } else { + cc.ndiaCrate[irof * 72 + icrate] = rofRec.getDiagnosticInCrate(icrate) + 1; // shifted by one since -1 means crate not available (then to get unsigned int) + } } if (!ndig) { // no hits data for this ROF --> not fill diff --git a/Detectors/TOF/reconstruction/src/Clusterer.cxx b/Detectors/TOF/reconstruction/src/Clusterer.cxx index bb191e5dcf9b5..ccaa484954303 100644 --- a/Detectors/TOF/reconstruction/src/Clusterer.cxx +++ b/Detectors/TOF/reconstruction/src/Clusterer.cxx @@ -129,17 +129,17 @@ void Clusterer::addContributingDigit(Digit* dig) // adding a digit to the array that stores the contributing ones if (mNumberOfContributingDigits == 6) { - LOG(WARNING) << "The cluster has already 6 digits associated to it, we cannot add more; returning without doing anything"; + LOG(DEBUG) << "The cluster has already 6 digits associated to it, we cannot add more; returning without doing anything"; int phi, eta; for (int i = 0; i < mNumberOfContributingDigits; i++) { mContributingDigit[i]->getPhiAndEtaIndex(phi, eta); - LOG(WARNING) << "digit already in " << i << ", channel = " << mContributingDigit[i]->getChannel() << ",phi,eta = (" << phi << "," << eta << "), TDC = " << mContributingDigit[i]->getTDC() << ", calibrated time = " << mContributingDigit[i]->getCalibratedTime(); + LOG(DEBUG) << "digit already in " << i << ", channel = " << mContributingDigit[i]->getChannel() << ",phi,eta = (" << phi << "," << eta << "), TDC = " << mContributingDigit[i]->getTDC() << ", calibrated time = " << mContributingDigit[i]->getCalibratedTime(); } dig->getPhiAndEtaIndex(phi, eta); - LOG(WARNING) << "skipped digit" - << ", channel = " << dig->getChannel() << ",phi,eta = (" << phi << "," << eta << "), TDC = " << dig->getTDC() << ", calibrated time = " << dig->getCalibratedTime(); + LOG(DEBUG) << "skipped digit" + << ", channel = " << dig->getChannel() << ",phi,eta = (" << phi << "," << eta << "), TDC = " << dig->getTDC() << ", calibrated time = " << dig->getCalibratedTime(); dig->setIsUsedInCluster(); // flag is at used in any case diff --git a/Detectors/TOF/reconstruction/src/Decoder.cxx b/Detectors/TOF/reconstruction/src/Decoder.cxx index 2cd9c323395f9..46cb81b1ab31f 100644 --- a/Detectors/TOF/reconstruction/src/Decoder.cxx +++ b/Detectors/TOF/reconstruction/src/Decoder.cxx @@ -119,7 +119,7 @@ void Decoder::clear() mPatterns.clear(); mCratePatterns.clear(); - + mCrateHeaderData.clear(); mErrors.clear(); } diff --git a/Detectors/TOF/simulation/CMakeLists.txt b/Detectors/TOF/simulation/CMakeLists.txt index 2eb23925337d1..0b02ad8df9897 100644 --- a/Detectors/TOF/simulation/CMakeLists.txt +++ b/Detectors/TOF/simulation/CMakeLists.txt @@ -9,7 +9,7 @@ # submit itself to any jurisdiction. o2_add_library(TOFSimulation - SOURCES src/Detector.cxx src/Digitizer.cxx src/DigitizerTask.cxx + SOURCES src/Detector.cxx src/Digitizer.cxx src/DigitizerTask.cxx src/TOFSimParams.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::TOFBase O2::SimulationDataFormat O2::TOFCalibration) @@ -17,7 +17,8 @@ o2_add_library(TOFSimulation o2_target_root_dictionary(TOFSimulation HEADERS include/TOFSimulation/Detector.h include/TOFSimulation/Digitizer.h - include/TOFSimulation/DigitizerTask.h) + include/TOFSimulation/DigitizerTask.h + include/TOFSimulation/TOFSimParams.h) o2_add_executable(digi2raw COMPONENT_NAME tof diff --git a/Detectors/TOF/simulation/include/TOFSimulation/TOFSimParams.h b/Detectors/TOF/simulation/include/TOFSimulation/TOFSimParams.h new file mode 100644 index 0000000000000..9103b3a341f32 --- /dev/null +++ b/Detectors/TOF/simulation/include/TOFSimulation/TOFSimParams.h @@ -0,0 +1,41 @@ +// 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_CONF_TOFDIGIPARAMS_H_ +#define O2_CONF_TOFDIGIPARAMS_H_ + +// Global parameters for TOF simulation / digitization + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace tof +{ + +// Global parameters for TOF simulation / digitization +struct TOFSimParams : public o2::conf::ConfigurableParamHelper<TOFSimParams> { + + int time_resolution = 60; // TOF resolution in ps + + // efficiency parameters + float eff_center = 0.995; // efficiency in the center of the fired pad + float eff_boundary1 = 0.94; // efficiency in mBound2 + float eff_boundary2 = 0.833; // efficiency in the pad border + float eff_boundary3 = 0.1; // efficiency in mBound3 + + O2ParamDef(TOFSimParams, "TOFSimParams"); +}; + +} // namespace tof +} // namespace o2 + +#endif diff --git a/Detectors/TOF/simulation/src/Digitizer.cxx b/Detectors/TOF/simulation/src/Digitizer.cxx index 553615fdb7587..d855866604c2f 100644 --- a/Detectors/TOF/simulation/src/Digitizer.cxx +++ b/Detectors/TOF/simulation/src/Digitizer.cxx @@ -10,6 +10,7 @@ #include "TOFSimulation/Digitizer.h" #include "DetectorsBase/GeometryManager.h" +#include "TOFSimulation/TOFSimParams.h" #include "TCanvas.h" #include "TFile.h" @@ -512,7 +513,7 @@ void Digitizer::initParameters() mBound4 = 0.9; // distance from border (not fired pad) when efficiency vanishes // resolution parameters - mTOFresolution = 60; // TOF global resolution in ps + mTOFresolution = TOFSimParams::Instance().time_resolution; // TOF global resolution in ps mShowerResolution = 50; // smearing correlated for all digits of the same hit if (mTOFresolution > mShowerResolution) { mDigitResolution = TMath::Sqrt(mTOFresolution * mTOFresolution - @@ -546,10 +547,10 @@ void Digitizer::initParameters() } // efficiency parameters - mEffCenter = 0.995; // efficiency in the center of the fired pad - mEffBoundary1 = 0.94; // efficiency in mBound2 - mEffBoundary2 = 0.833; // efficiency in the pad border - mEffBoundary3 = 0.1; // efficiency in mBound3 + mEffCenter = TOFSimParams::Instance().eff_center; // efficiency in the center of the fired pad + mEffBoundary1 = TOFSimParams::Instance().eff_boundary1; // efficiency in mBound2 + mEffBoundary2 = TOFSimParams::Instance().eff_boundary2; // efficiency in the pad border + mEffBoundary3 = TOFSimParams::Instance().eff_boundary3; // efficiency in mBound3 } //______________________________________________________________________ diff --git a/Detectors/TOF/simulation/src/TOFSimParams.cxx b/Detectors/TOF/simulation/src/TOFSimParams.cxx new file mode 100644 index 0000000000000..b2fd20ceb4e97 --- /dev/null +++ b/Detectors/TOF/simulation/src/TOFSimParams.cxx @@ -0,0 +1,12 @@ +// 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 "TOFSimulation/TOFSimParams.h" +O2ParamImpl(o2::tof::TOFSimParams); diff --git a/Detectors/TOF/simulation/src/TOFSimulationLinkDef.h b/Detectors/TOF/simulation/src/TOFSimulationLinkDef.h index 9fc14b6a7c0a4..9e656b7eb03ff 100644 --- a/Detectors/TOF/simulation/src/TOFSimulationLinkDef.h +++ b/Detectors/TOF/simulation/src/TOFSimulationLinkDef.h @@ -21,4 +21,7 @@ #pragma link C++ class o2::tof::HitType + ; #pragma link C++ class vector < o2::tof::HitType> + ; +#pragma link C++ class o2::tof::TOFSimParams + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::tof::TOFSimParams> + ; + #endif diff --git a/Detectors/TOF/workflow/CMakeLists.txt b/Detectors/TOF/workflow/CMakeLists.txt index 418837f9c01ce..567c372173917 100644 --- a/Detectors/TOF/workflow/CMakeLists.txt +++ b/Detectors/TOF/workflow/CMakeLists.txt @@ -27,3 +27,7 @@ o2_add_executable(entropy-encoder-workflow COMPONENT_NAME tof PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils) +o2_add_executable(digit-writer-workflow + SOURCES src/digit-writer-commissioning.cxx + COMPONENT_NAME tof + PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils) diff --git a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h new file mode 100644 index 0000000000000..d03d747cc76cc --- /dev/null +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h @@ -0,0 +1,160 @@ +// 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_TOFDIGIT_SPLITTER_WRITER_H +#define O2_TOFDIGIT_SPLITTER_WRITER_H + +/// @file TOFDigitWriterSplitterSpec.h +/// @brief Device to write to tree the information for TOF time slewing calibration. + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "TOFBase/Digit.h" +#include "Framework/Logger.h" +#include <TTree.h> +#include <gsl/span> + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ +class TOFDigitWriterSplitter : public Task +{ + using OutputType = std::vector<o2::tof::Digit>; + using ReadoutWinType = std::vector<o2::tof::ReadoutWindowData>; + using PatternType = std::vector<uint32_t>; + using ErrorType = std::vector<uint64_t>; + using HeaderType = o2::tof::DigitHeader; + + public: + TOFDigitWriterSplitter(int nTF, bool storeErr = false) : mTFthr(nTF), mStoreErrors(storeErr) {} + + void createAndOpenFileAndTree() + { + TString filename = TString::Format("tofdigits_%d.root", mCount); + LOG(DEBUG) << "opening file " << filename.Data(); + mfileOut.reset(TFile::Open(TString::Format("%s", filename.Data()), "RECREATE")); + mOutputTree = std::make_unique<TTree>("o2sim", "Tree with TOF digits"); + mOutputTree->Branch("TOFHeader", &mPHeader); + mOutputTree->Branch("TOFDigit", &mPDigits); + mOutputTree->Branch("TOFReadoutWindow", &mPROW); + mOutputTree->Branch("TOFPatterns", &mPDia); + if (mStoreErrors) + mOutputTree->Branch("TOFErrors", &mPErr); + + mNTF = 0; + } + + void init(o2::framework::InitContext& ic) final + { + mCount = 0; + createAndOpenFileAndTree(); + } + + void run(o2::framework::ProcessingContext& pc) final + { + auto digits = pc.inputs().get<OutputType>("digits"); + mPDigits = &digits; + auto header = pc.inputs().get<HeaderType>("header"); + mPHeader = &header; + auto row = pc.inputs().get<ReadoutWinType>("rows"); + mPROW = &row; + auto dia = pc.inputs().get<PatternType>("patterns"); + mPDia = &dia; + if (mStoreErrors) { + auto error = pc.inputs().get<ErrorType>("errors"); + mPErr = &error; + + mOutputTree->Fill(); + } else { + mOutputTree->Fill(); + } + mNTF++; + + if (mNTF >= mTFthr) { + sendOutput(); + } + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + mIsEndOfStream = true; + sendOutput(); + } + + private: + int mCount = 0; // how many times we filled the tree + int mNTF = 0; + int mTFthr = 1; + bool mStoreErrors = false; + bool mIsEndOfStream = false; + OutputType mDigits; + const OutputType* mPDigits = &mDigits; + ReadoutWinType mROW; + const ReadoutWinType* mPROW = &mROW; + PatternType mDia; + const PatternType* mPDia = &mDia; + ErrorType mErr; + const ErrorType* mPErr = &mErr; + HeaderType mHeader; + const HeaderType* mPHeader = &mHeader; + std::unique_ptr<TTree> mOutputTree; ///< tree for the collected calib tof info + std::unique_ptr<TFile> mfileOut = nullptr; // file in which to write the output + + //________________________________________________________________ + void sendOutput() + { + // This is to fill the tree. + // One file with an empty tree will be created at the end, because we have to have a + // tree opened before processing, since we do not know a priori if something else + // will still come. The size of this extra file is ~6.5 kB + + mfileOut->cd(); + mOutputTree->Write(); + mOutputTree.reset(); + mfileOut.reset(); + mCount++; + if (!mIsEndOfStream) { + createAndOpenFileAndTree(); + } + } +}; +} // namespace tof + +namespace framework +{ + +DataProcessorSpec getTOFCalibCollectorWriterSpec(int nTF, bool storeErr = false) +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("header", o2::header::gDataOriginTOF, "DIGITHEADER"); + inputs.emplace_back("digits", o2::header::gDataOriginTOF, "DIGITS"); + inputs.emplace_back("rows", o2::header::gDataOriginTOF, "READOUTWINDOW"); + inputs.emplace_back("patterns", o2::header::gDataOriginTOF, "PATTERNS"); + + if (storeErr) + inputs.emplace_back("errors", o2::header::gDataOriginTOF, "ERRORS"); + + std::vector<OutputSpec> outputs; // empty + + return DataProcessorSpec{ + "tof-digit-splitter-writer", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<o2::tof::TOFDigitWriterSplitter>(nTF, storeErr)}, + Options{}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index e2e3ab84b844b..e6bb8ee347c7b 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -105,6 +105,9 @@ void CompressedDecodingTask::postData(ProcessingContext& pc) std::vector<uint64_t>& errors = mDecoder.getErrors(); pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ERRORS", 0, Lifetime::Timeframe}, errors); + DigitHeader& digitH = mDecoder.getDigitHeader(); + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITHEADER", 0, Lifetime::Timeframe}, digitH); + // RS this is a hack to be removed once we have correct propagation of the firstTForbit by the framework auto setFirstTFOrbit = [&](const Output& spec, uint32_t orb) { auto* hd = pc.outputs().findMessageHeader(spec); @@ -189,6 +192,8 @@ void CompressedDecodingTask::trailerHandler(const CrateHeader_t* crateHeader, co mNCrateCloseTF++; } + mDecoder.addCrateHeaderData(crateOrbit->orbitID, crateHeader->drmID, crateHeader->bunchID, crateTrailer->eventCounter); + // Diagnostics used to fill digit patterns auto numberOfDiagnostics = crateTrailer->numberOfDiagnostics; auto numberOfErrors = crateTrailer->numberOfErrors; @@ -196,6 +201,7 @@ void CompressedDecodingTask::trailerHandler(const CrateHeader_t* crateHeader, co const uint32_t* val = reinterpret_cast<const uint32_t*>(&(diagnostics[i])); mDecoder.addPattern(*val, crateHeader->drmID, crateOrbit->orbitID, crateHeader->bunchID); + /* int islot = (*val & 15); printf("DRM = %d (orbit = %d) slot = %d: \n", crateHeader->drmID, crateOrbit->orbitID, islot); if (islot == 1) { @@ -315,6 +321,7 @@ void CompressedDecodingTask::trailerHandler(const CrateHeader_t* crateHeader, co } } printf("------\n"); + */ } for (int i = 0; i < numberOfErrors; i++) { const uint32_t* val = reinterpret_cast<const uint32_t*>(&(errors[i])); @@ -353,6 +360,7 @@ void CompressedDecodingTask::frameHandler(const CrateHeader_t* crateHeader, cons DataProcessorSpec getCompressedDecodingSpec(const std::string& inputDesc, bool conet) { std::vector<OutputSpec> outputs; + outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITHEADER", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); diff --git a/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx index db048a4e59850..ca1fa309a8831 100644 --- a/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/TOF/workflow/src/EntropyDecoderSpec.cxx @@ -44,6 +44,7 @@ void EntropyDecoderSpec::run(ProcessingContext& pc) auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + auto& digitheader = pc.outputs().make<DigitHeader>(OutputRef{"digitheader"}); auto& digits = pc.outputs().make<std::vector<Digit>>(OutputRef{"digits"}); auto& row = pc.outputs().make<std::vector<ReadoutWindowData>>(OutputRef{"row"}); auto& patterns = pc.outputs().make<std::vector<uint32_t>>(OutputRef{"patterns"}); @@ -65,6 +66,7 @@ void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) DataProcessorSpec getEntropyDecoderSpec() { std::vector<OutputSpec> outputs{ + OutputSpec{{"digitheader"}, o2::header::gDataOriginTOF, "DIGITHEADER", 0, Lifetime::Timeframe}, OutputSpec{{"digits"}, o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe}, OutputSpec{{"row"}, o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe}, OutputSpec{{"patterns"}, o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}}; diff --git a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx index b174c808aabad..24a81ffaa1793 100644 --- a/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFDigitWriterSpec.cxx @@ -29,6 +29,7 @@ using ReadoutWinType = std::vector<o2::tof::ReadoutWindowData>; using PatternType = std::vector<uint32_t>; using ErrorType = std::vector<uint64_t>; using LabelsType = std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>; +using HeaderType = o2::tof::DigitHeader; using namespace o2::header; DataProcessorSpec getTOFDigitWriterSpec(bool useMC, bool writeErr) @@ -47,6 +48,8 @@ DataProcessorSpec getTOFDigitWriterSpec(bool useMC, bool writeErr) auto preprocessor = [nCalls](ProcessingContext&) { (*nCalls)++; }; + auto loggerH = [nCalls](HeaderType const& indata) { + }; auto logger = [nCalls](OutputType const& indata) { // LOG(INFO) << "RECEIVED DIGITS SIZE " << indata.size(); }; @@ -65,6 +68,11 @@ DataProcessorSpec getTOFDigitWriterSpec(bool useMC, bool writeErr) // the preprocessor only increments the call count, we keep this functionality // of the original implementation MakeRootTreeWriterSpec::Preprocessor{preprocessor}, + BranchDefinition<HeaderType>{InputSpec{"digitheader", gDataOriginTOF, "DIGITHEADER", 0}, + "TOFHeader", + "tofdigitheader-branch-name", + 1, + loggerH}, BranchDefinition<OutputType>{InputSpec{"digits", gDataOriginTOF, "DIGITS", 0}, "TOFDigit", "tofdigits-branch-name", diff --git a/Detectors/TOF/workflow/src/digit-writer-commissioning.cxx b/Detectors/TOF/workflow/src/digit-writer-commissioning.cxx new file mode 100644 index 0000000000000..a42cd1fef3046 --- /dev/null +++ b/Detectors/TOF/workflow/src/digit-writer-commissioning.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. + +#include "TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + workflowOptions.push_back(ConfigParamSpec{"ntf", o2::framework::VariantType::Int, 1, {"number of timeframe written for output file"}}); + workflowOptions.push_back(ConfigParamSpec{"write-decoding-errors", o2::framework::VariantType::Bool, false, {"trace errors in digits output when decoding"}}); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + auto ntf = cfgc.options().get<int>("ntf"); + auto write_err = cfgc.options().get<bool>("write-decoding-errors"); + wf.emplace_back(o2::framework::getTOFCalibCollectorWriterSpec(ntf, write_err)); + return wf; +} diff --git a/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx index 75be3e028db3b..743dd00bdf9f5 100644 --- a/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TOFDigitizerSpec.cxx @@ -168,6 +168,9 @@ class TOFDPLDigitizerTask : public o2::base::BaseDPLDigitizer static std::vector<uint32_t> patterns; pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe}, patterns); + DigitHeader& digitH = mDigitizer->getDigitHeader(); + pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITHEADER", 0, Lifetime::Timeframe}, digitH); + LOG(INFO) << "TOF: Sending ROMode= " << roMode << " to GRPUpdater"; pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ROMode", 0, Lifetime::Timeframe}, roMode); @@ -202,6 +205,7 @@ DataProcessorSpec getTOFDigitizerSpec(int channel, bool useCCDB, bool mctruth) inputs.emplace_back("tofccdbChannelCalib", o2::header::gDataOriginTOF, "ChannelCalib"); } std::vector<OutputSpec> outputs; + outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITHEADER", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe); outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe); From 543f37545e69447c021d8d2722aa660ba0505d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Thu, 5 Nov 2020 14:53:48 +0100 Subject: [PATCH 1211/1751] Use HistogramRegistry in qa task (#4764) --- Analysis/Tasks/qaTask.cxx | 92 ++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx index 5c20b3550b90f..b6c2b0a641a16 100644 --- a/Analysis/Tasks/qaTask.cxx +++ b/Analysis/Tasks/qaTask.cxx @@ -10,10 +10,12 @@ /// \author Peter Hristov <Peter.Hristov@cern.ch>, CERN /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN /// \author Henrique J C Zanoli <henrique.zanoli@cern.ch>, Utrecht University +/// \author Nicolo' Jacazio <nicolo.jacazio@cern.ch>, CERN #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" #include "Analysis/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" #include "Analysis/MC.h" @@ -140,40 +142,40 @@ struct QATrackingResolution { std::array<double, 2> impactParameterRange = {-1500, 1500}; // micrometer std::array<double, 2> impactParameterResolutionRange = {0, 1000}; // micrometer - o2fw::OutputObj<TH1F> etaDiffMCRec{TH1F("etaDiffMCReco", ";#eta_{MC} - #eta_{Rec}", nBinsDeltaEta, -2, 2)}; - o2fw::OutputObj<TH2F> etaDiffMCRecoVsEtaMC{TH2F("etaDiffMCRecoVsEtaMC", ";#eta_{MC} - #eta_{Rec};#eta_{MC}", nBinsDeltaEta, -2, 2, nBinsEta, etaRange[0], etaRange[1])}; - o2fw::OutputObj<TH2F> etaDiffMCRecoVsEtaReco{TH2F("etaDiffMCRecoVsEtaReco", ";#eta_{MC} - #eta_{Rec};#eta_{Rec}", nBinsDeltaEta, -2, 2, nBinsEta, etaRange[0], etaRange[1])}; + // Registry of histograms + o2fw::HistogramRegistry histos{"Histos", {}, o2fw::OutputObjHandlingPolicy::AnalysisObject}; - o2fw::OutputObj<TH1F> phiDiffMCRec{ - TH1F("phiDiffMCRec", ";#varphi_{MC} - #varphi_{Rec} [rad]", nBinsDeltaPhi, -M_PI, M_PI)}; - - o2fw::OutputObj<TH1F> ptDiffMCRec{TH1F("ptDiffMCRec", ";p_{T}_{MC} - p_{T}_{Rec} [GeV/c]", nBinsDeltaPt, -2., 2.)}; - - o2fw::OutputObj<TH1F> ptResolution{ - TH1F("ptResolution", ";(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec}) ", nBinsDeltaPt, -2., 2.)}; - - o2fw::OutputObj<TH2F> ptResolutionVsPt{TH2F("ptResolutionVsPt", - ";p_{T} [GeV/c];(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", nBinsPtTrack, - ptRange[0], ptRange[1], nBinsDeltaPt, 0, 2.)}; - - o2fw::OutputObj<TH2F> ptResolutionVsEta{TH2F("ptResolutionVsEta", ";#eta;(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", - nBinsEta, -4., 4., nBinsDeltaPt, -2., 2.)}; - - o2fw::OutputObj<TH2F> impactParameterVsPt{TH2F("impactParameterVsPt", ";p_{T} [GeV/c];Impact Parameter [{#mu}m]", - nBinsPtTrack, ptRange[0], ptRange[1], nBinsImpactParameter, - impactParameterRange[0], impactParameterRange[1])}; - - o2fw::OutputObj<TH2F> impactParameterVsEta{TH2F("impactParameterVsEta", "#eta;Impact Parameter [{#mu}m]", - nBinsEta, etaRange[0], etaRange[1], nBinsImpactParameter, - impactParameterRange[0], impactParameterRange[1])}; - - o2fw::OutputObj<TH2F> impactParameterErrorVsPt{ - TH2F("impactParameterErrorVsPt", ";p_{T} [GeV/c];Impact Parameter Error [#mum]", nBinsPtTrack, ptRange[0], - ptRange[1], nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1])}; - - o2fw::OutputObj<TH2F> impactParameterErrorVsEta{ - TH2F("impactParameterErrorVsEta", ";#eta;Impact Parameter Error [#mum]", nBinsEta, etaRange[0], etaRange[1], - nBinsImpactParameter, 0, impactParameterRange[1])}; + void init(o2fw::InitContext&) + { + // Eta + histos.add("Eta/etaDiffMCReco", ";#eta_{MC} - #eta_{Rec}", o2fw::kTH1F, + {{nBinsDeltaEta, -2, 2}}); + histos.add("Eta/etaDiffMCRecoVsEtaMC", ";#eta_{MC} - #eta_{Rec};#eta_{MC}", o2fw::kTH2F, + {{nBinsDeltaEta, -2, 2}, {nBinsEta, etaRange[0], etaRange[1]}}); + histos.add("Eta/etaDiffMCRecoVsEtaReco", ";#eta_{MC} - #eta_{Rec};#eta_{Rec}", o2fw::kTH2F, + {{nBinsDeltaEta, -2, 2}, {nBinsEta, etaRange[0], etaRange[1]}}); + // Phi + histos.add("Phi/phiDiffMCRec", ";#varphi_{MC} - #varphi_{Rec} [rad]", o2fw::kTH1F, + {{nBinsDeltaPhi, -M_PI, M_PI}}); + // Pt + histos.add("Pt/ptDiffMCRec", ";p_{T}_{MC} - p_{T}_{Rec} [GeV/c]", o2fw::kTH1F, + {{nBinsDeltaPt, -2., 2.}}); + histos.add("Pt/ptResolution", ";(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", o2fw::kTH1F, + {{nBinsDeltaPt, -2., 2.}}); + histos.add("Pt/ptResolutionVsPt", ";p_{T} [GeV/c];(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", o2fw::kTH2F, + {{nBinsPtTrack, ptRange[0], ptRange[1]}, {nBinsDeltaPt, 0, 2.}}); + histos.add("Pt/ptResolutionVsEta", ";#eta;(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", o2fw::kTH2F, + {{nBinsEta, -4., 4.}, {nBinsDeltaPt, -2., 2.}}); + // Impact parameters + histos.add("ImpactParameter/impactParameterVsPt", ";p_{T} [GeV/c];Impact Parameter [{#mu}m]", o2fw::kTH2F, + {{nBinsPtTrack, ptRange[0], ptRange[1]}, {nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}}); + histos.add("ImpactParameter/impactParameterVsEta", "#eta;Impact Parameter [{#mu}m]", o2fw::kTH2F, + {{nBinsEta, etaRange[0], etaRange[1]}, {nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}}); + histos.add("ImpactParameter/impactParameterErrorVsPt", ";p_{T} [GeV/c];Impact Parameter Error [#mum]", o2fw::kTH2F, + {{nBinsPtTrack, ptRange[0], ptRange[1]}, {nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}}); + histos.add("ImpactParameter/impactParameterErrorVsEta", ";#eta;Impact Parameter Error [#mum]", o2fw::kTH2F, + {{nBinsEta, etaRange[0], etaRange[1]}, {nBinsImpactParameter, 0, impactParameterRange[1]}}); + } void process(const o2::soa::Join<o2::aod::Collisions, o2::aod::McCollisionLabels>::iterator& collision, const o2::soa::Join<o2::aod::Tracks, o2::aod::TracksCov, o2::aod::McTrackLabels>& tracks, @@ -183,20 +185,20 @@ struct QATrackingResolution { for (const auto& track : tracks) { const double deltaPt = track.label().pt() - track.pt(); - ptDiffMCRec->Fill(deltaPt); + histos.fill("Pt/ptDiffMCRec", deltaPt); const double deltaPtOverPt = deltaPt / track.pt(); - ptResolution->Fill((deltaPtOverPt)); - ptResolutionVsPt->Fill(track.pt(), abs(deltaPtOverPt)); - ptResolutionVsEta->Fill(track.eta(), abs(deltaPtOverPt)); + histos.fill("Pt/ptResolution", deltaPtOverPt); + histos.fill("Pt/ptResolutionVsPt", track.pt(), abs(deltaPtOverPt)); + histos.fill("Pt/ptResolutionVsEta", track.eta(), abs(deltaPtOverPt)); const double deltaEta = track.label().eta() - track.eta(); - etaDiffMCRec->Fill(deltaEta); - etaDiffMCRecoVsEtaMC->Fill(deltaEta, track.label().eta()); - etaDiffMCRecoVsEtaReco->Fill(deltaEta, track.eta()); + histos.fill("Eta/etaDiffMCReco", deltaEta); + histos.fill("Eta/etaDiffMCRecoVsEtaMC", deltaEta, track.label().eta()); + histos.fill("Eta/etaDiffMCRecoVsEtaReco", deltaEta, track.eta()); const auto deltaPhi = track_utils::ConvertPhiRange(track.label().phi() - track.phi()); - phiDiffMCRec->Fill(deltaPhi); + histos.fill("Phi/phiDiffMCRec", deltaPhi); double impactParameter{-999.}; double impactParameterError{-999.}; @@ -205,10 +207,10 @@ struct QATrackingResolution { track_utils::GetImpactParameterAndError(track, primaryVertex, impactParameter, impactParameterError); if (propagate) { - impactParameterVsPt->Fill(track.pt(), impactParameter); - impactParameterVsEta->Fill(track.eta(), impactParameter); - impactParameterErrorVsPt->Fill(track.pt(), impactParameterError); - impactParameterErrorVsEta->Fill(track.eta(), impactParameterError); + histos.fill("ImpactParameter/impactParameterVsPt", track.pt(), impactParameter); + histos.fill("ImpactParameter/impactParameterVsEta", track.eta(), impactParameter); + histos.fill("ImpactParameter/impactParameterErrorVsPt", track.pt(), impactParameterError); + histos.fill("ImpactParameter/impactParameterErrorVsEta", track.eta(), impactParameterError); } } } From 1dfc5f0299b46c86096676f55ed2dbf0788a524e Mon Sep 17 00:00:00 2001 From: Peter Hristov <pzhristov@users.noreply.github.com> Date: Thu, 5 Nov 2020 17:02:07 +0100 Subject: [PATCH 1212/1751] Include what is needed (Root 6.23.01) (#4768) * Include what is needed (Root 6.23.01) * Apply clang-format Co-authored-by: hristov <Peter.Hristov@cern.ch> --- Analysis/Tutorials/include/Analysis/configurableCut.h | 1 + .../include/ReconstructionDataFormats/TrackFwd.h | 1 + Detectors/CPV/base/include/CPVBase/Geometry.h | 3 +++ .../MUON/MCH/Tracking/include/MCHTracking/TrackParam.h | 1 + Detectors/PHOS/base/include/PHOSBase/Geometry.h | 3 +++ Detectors/ZDC/base/include/ZDCBase/Geometry.h | 1 + Framework/Core/test/test_DataInputDirector.cxx | 7 +++++-- 7 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h index d63b39e75fbca..76ab55847b0b6 100644 --- a/Analysis/Tutorials/include/Analysis/configurableCut.h +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -12,6 +12,7 @@ #define CONFIGURABLECUT_H #include <iosfwd> +#include <Rtypes.h> #include <TMath.h> class configurableCut diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index 77b83fd9f05f4..bf9749a55d1ca 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -16,6 +16,7 @@ #ifndef ALICEO2_BASE_TRACKFWD #define ALICEO2_BASE_TRACKFWD +#include <Rtypes.h> #include <TMath.h> #include "Math/SMatrix.h" #include "MathUtils/Utils.h" diff --git a/Detectors/CPV/base/include/CPVBase/Geometry.h b/Detectors/CPV/base/include/CPVBase/Geometry.h index 21e535639ce74..922d1d5064097 100644 --- a/Detectors/CPV/base/include/CPVBase/Geometry.h +++ b/Detectors/CPV/base/include/CPVBase/Geometry.h @@ -13,6 +13,7 @@ #include <string> +#include <Rtypes.h> #include <RStringView.h> #include <TMath.h> @@ -74,6 +75,8 @@ class Geometry { return absId > 0 && absId <= getTotalNPads(); } // TODO: evaluate from real geometry + + ClassDefNV(Geometry, 1); }; } // namespace cpv } // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h index 267f19f17bb4f..9415f238b54a6 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackParam.h @@ -16,6 +16,7 @@ #ifndef ALICEO2_MCH_TRACKPARAM_H_ #define ALICEO2_MCH_TRACKPARAM_H_ +#include <memory> // for std::unique_ptr #include <TMatrixD.h> #include "MCHBase/TrackBlock.h" diff --git a/Detectors/PHOS/base/include/PHOSBase/Geometry.h b/Detectors/PHOS/base/include/PHOSBase/Geometry.h index e8be99ff6094b..8a48225c28dc0 100644 --- a/Detectors/PHOS/base/include/PHOSBase/Geometry.h +++ b/Detectors/PHOS/base/include/PHOSBase/Geometry.h @@ -13,6 +13,7 @@ #include <string> +#include <Rtypes.h> #include <RStringView.h> #include <TMath.h> @@ -114,6 +115,8 @@ class Geometry static Geometry* sGeom; // Pointer to the unique instance of the singleton std::string mGeoName; ///< Geometry name string + + ClassDefNV(Geometry, 1); }; } // namespace phos } // namespace o2 diff --git a/Detectors/ZDC/base/include/ZDCBase/Geometry.h b/Detectors/ZDC/base/include/ZDCBase/Geometry.h index eedb9e3b38a48..3eec00b9a3656 100644 --- a/Detectors/ZDC/base/include/ZDCBase/Geometry.h +++ b/Detectors/ZDC/base/include/ZDCBase/Geometry.h @@ -11,6 +11,7 @@ #ifndef ALICEO2_ZDC_GEOMETRY_H #define ALICEO2_ZDC_GEOMETRY_H +#include <Rtypes.h> #include "TMath.h" #include <cmath> diff --git a/Framework/Core/test/test_DataInputDirector.cxx b/Framework/Core/test/test_DataInputDirector.cxx index ac77c341151ae..f8456d7935380 100644 --- a/Framework/Core/test/test_DataInputDirector.cxx +++ b/Framework/Core/test/test_DataInputDirector.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include <fstream> #include <boost/test/unit_test.hpp> #include "Headers/DataHeader.h" @@ -50,7 +51,8 @@ BOOST_AUTO_TEST_CASE(TestDatainputDirector) DataInputDirector didir1; BOOST_CHECK(didir1.readJson(jsonFile)); - didir1.printOut(); printf("\n\n"); + didir1.printOut(); + printf("\n\n"); BOOST_CHECK_EQUAL(didir1.getNumberInputDescriptors(), 2); @@ -94,7 +96,8 @@ BOOST_AUTO_TEST_CASE(TestDatainputDirector) "Bresults_1.root", "Bresults_2.root"}; DataInputDirector didir2(inputFiles); - didir2.printOut(); printf("\n\n"); + didir2.printOut(); + printf("\n\n"); BOOST_CHECK(didir2.readJson(jsonFile)); //auto [file2, directory2] = didir2.getFileFolder(dh, 1, 0); From ae57cc813b5f9b25976546bc939b41cf659686ef Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 5 Nov 2020 19:51:42 +0100 Subject: [PATCH 1213/1751] DPL: make ProcessingContext forward declare DataAllocator (#4763) --- Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h | 1 + Framework/Core/include/Framework/DataProcessorSpec.h | 1 + Framework/Core/include/Framework/ProcessingContext.h | 2 +- Framework/Core/include/Framework/runDataProcessing.h | 1 + Framework/Core/src/WorkflowHelpers.cxx | 1 + Framework/Core/test/test_SimpleRDataFrameProcessing.cxx | 1 + Framework/Utils/include/DPLUtils/RootTreeReader.h | 1 + 7 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h index 20adeed3cda20..fc65ff17b1f18 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/RawReaderFT0.h @@ -26,6 +26,7 @@ #include "DataFormatsFT0/ChannelData.h" #include "Framework/ProcessingContext.h" +#include "Framework/DataAllocator.h" #include "Framework/OutputSpec.h" #include <gsl/span> diff --git a/Framework/Core/include/Framework/DataProcessorSpec.h b/Framework/Core/include/Framework/DataProcessorSpec.h index 4cdae26b3f7a8..c60346dc5dc4c 100644 --- a/Framework/Core/include/Framework/DataProcessorSpec.h +++ b/Framework/Core/include/Framework/DataProcessorSpec.h @@ -14,6 +14,7 @@ #include "Framework/ConfigParamSpec.h" #include "Framework/DataProcessorLabel.h" #include "Framework/DataRef.h" +#include "Framework/DataAllocator.h" #include "Framework/InputSpec.h" #include "Framework/OutputSpec.h" #include "Framework/CommonServices.h" diff --git a/Framework/Core/include/Framework/ProcessingContext.h b/Framework/Core/include/Framework/ProcessingContext.h index c28d88ff556fe..fe85785922ef2 100644 --- a/Framework/Core/include/Framework/ProcessingContext.h +++ b/Framework/Core/include/Framework/ProcessingContext.h @@ -11,12 +11,12 @@ #define O2_FRAMEWORK_PROCESSINGCONTEXT_H_ #include "Framework/InputRecord.h" -#include "Framework/DataAllocator.h" namespace o2::framework { struct ServiceRegistry; +struct DataAllocator; // This is a utility class to reduce the amount of boilerplate when defining // an algorithm. diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 2d54954f7de15..9e47b6757b78b 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -14,6 +14,7 @@ #include "Framework/CompletionPolicy.h" #include "Framework/DispatchPolicy.h" #include "Framework/DataProcessorSpec.h" +#include "Framework/DataAllocator.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigContext.h" #include "Framework/BoostOptionsRetriever.h" diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index fd1ddd6dbcf06..8cc278b707bdf 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -15,6 +15,7 @@ #include "Framework/ConfigContext.h" #include "Framework/DeviceSpec.h" #include "Framework/DataSpecUtils.h" +#include "Framework/DataAllocator.h" #include "Framework/ControlService.h" #include "Framework/RawDeviceService.h" #include "Framework/StringHelpers.h" diff --git a/Framework/Core/test/test_SimpleRDataFrameProcessing.cxx b/Framework/Core/test/test_SimpleRDataFrameProcessing.cxx index 472844f972eb7..6af1a87b4d114 100644 --- a/Framework/Core/test/test_SimpleRDataFrameProcessing.cxx +++ b/Framework/Core/test/test_SimpleRDataFrameProcessing.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "Framework/DataRefUtils.h" #include "Framework/AlgorithmSpec.h" +#include "Framework/DataAllocator.h" #include "Framework/ServiceRegistry.h" #include "Framework/runDataProcessing.h" #include "Framework/ControlService.h" diff --git a/Framework/Utils/include/DPLUtils/RootTreeReader.h b/Framework/Utils/include/DPLUtils/RootTreeReader.h index ba2624a88bfaf..20d2772d82f6e 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/DataAllocator.h" #include "Framework/Logger.h" #include "Headers/DataHeader.h" #include <TChain.h> From 723765a6bab951d5713517527e9a96da1cb07318 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 6 Nov 2020 02:03:47 +0100 Subject: [PATCH 1214/1751] DPL GUI: allow attaching more than one debugger (#4773) --- Framework/Core/src/FrameworkGUIDebugger.cxx | 2 ++ Framework/Core/src/FrameworkGUIDeviceInspector.cxx | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/Core/src/FrameworkGUIDebugger.cxx index ed297217fdd70..f7a173b0e647e 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/Core/src/FrameworkGUIDebugger.cxx @@ -712,6 +712,7 @@ struct DriverHelper { void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverControl) { ImGui::Begin("Driver information"); + static int pid = getpid(); if (driverControl.state == DriverControlState::STEP) { driverControl.state = DriverControlState::PAUSE; @@ -726,6 +727,7 @@ void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverContro auto& registry = driverInfo.configContext->options(); ImGui::Columns(); + ImGui::Text("PID: %d", pid); ImGui::Text("Frame cost (latency): %.1f(%.1f)ms", driverInfo.frameCost, driverInfo.frameLatency); ImGui::Text("Input parsing cost (latency): %.1f(%.1f)ms", driverInfo.inputProcessingCost, driverInfo.inputProcessingLatency); ImGui::Text("State stack (depth %lu)", driverInfo.states.size()); diff --git a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx index cd0686b3a6a32..8322ed1b87d6e 100644 --- a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx +++ b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx @@ -200,8 +200,7 @@ void displayDeviceInspector(DeviceSpec const& spec, #ifdef __APPLE__ std::string defaultAppleDebugCommand = "osascript -e 'tell application \"Terminal\" to activate'" - " -e 'tell application \"Terminal\" to do script \"lldb -p " + - pid + "\"'"; + " -e 'tell application \"Terminal\" to do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\")'"; setenv("O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0); #else setenv("O2DPLDEBUG", "xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0); From dc86a2278aadb3b15e6d3ac2ab83539f8889fdf0 Mon Sep 17 00:00:00 2001 From: hristov <Peter.Hristov@cern.ch> Date: Thu, 5 Nov 2020 17:20:57 +0100 Subject: [PATCH 1215/1751] Do not add global using namespace std in the generation of Root dictionaries --- cmake/rootcling_wrapper.sh.in | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/rootcling_wrapper.sh.in b/cmake/rootcling_wrapper.sh.in index 5a6d8e7bc398b..72e101cd1cbf8 100755 --- a/cmake/rootcling_wrapper.sh.in +++ b/cmake/rootcling_wrapper.sh.in @@ -85,6 +85,7 @@ LOGFILE=${DICTIONARY_FILE}.log @CMAKE_COMMAND@ -E env LD_LIBRARY_PATH=${LD_LIBRARY_PATH} @ROOT_rootcling_CMD@ \ -f $DICTIONARY_FILE \ -inlineInputHeader \ + -noGlobalUsingStd \ -rmf ${ROOTMAP_FILE} \ -rml ${ROOTMAP_LIBRARY_NAME} \ ${INCLUDE_DIRS//;/ } \ From 55a2a7ce34e5358ec77d1ea497e3c441d97ab229 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 5 Nov 2020 21:29:17 +0100 Subject: [PATCH 1216/1751] Update shaping time of electronics A time offset between TPC and ITS tracks is observed. The reason is that the peaking time of the electronics and the average shaping time has a slight offset due to the tail of the gamma4 function. This fixes this issue. --- Detectors/TPC/base/include/TPCBase/ParameterElectronics.h | 7 +++++++ .../TPC/reconstruction/src/TPCFastTransformHelperO2.cxx | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Detectors/TPC/base/include/TPCBase/ParameterElectronics.h b/Detectors/TPC/base/include/TPCBase/ParameterElectronics.h index 6432b3c617bf4..3946084f72784 100644 --- a/Detectors/TPC/base/include/TPCBase/ParameterElectronics.h +++ b/Detectors/TPC/base/include/TPCBase/ParameterElectronics.h @@ -45,6 +45,13 @@ struct ParameterElectronics : public o2::conf::ConfigurableParamHelper<Parameter float ElectronCharge = 1.602e-19f; ///< Electron charge [C] DigitzationMode DigiMode = DigitzationMode::SubtractPedestal; ///< Digitization mode [full / ... ] + /// Average time from the start of the signal shaping to the COG of the sampled distribution + /// + /// Since the shaping of the electronic starts when the signals arrive, the cluster finder + /// reconstructs signals later in time. Due to the asymmetry of the signal, the average + /// shaping time is somewhat larger then the PeakingTime + float getAverageShapingTime() const { return PeakingTime + 35e-3f; } + O2ParamDef(ParameterElectronics, "TPCEleParam"); }; } // namespace tpc diff --git a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx index 456c9513d5245..ce79babfe0b57 100644 --- a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx +++ b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx @@ -246,7 +246,7 @@ int TPCFastTransformHelperO2::updateCalibration(TPCFastTransform& fastTransform, // spline corrections for xyz // Time-of-flight correction: ldrift += dist-to-vtx*tofCorr - const double t0 = elParam.PeakingTime / elParam.ZbinWidth; + const double t0 = elParam.getAverageShapingTime() / elParam.ZbinWidth; const double vdCorrY = 0.; const double ldCorr = 0.; From 74521a6d8a4254c6ca405ce6d51c673484d81ee6 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 6 Nov 2020 09:10:51 +0100 Subject: [PATCH 1217/1751] DPL: use enum for AOD dumping logic (#4774) --- Framework/Core/src/CommonDataProcessors.cxx | 5 +++++ Framework/Core/src/WorkflowHelpers.cxx | 20 +++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 5fd6e9abd94ff..f3f57edbc3b20 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -235,6 +235,11 @@ DataProcessorSpec CommonDataProcessors::getOutputObjHistSink(outputObjects const return spec; } +enum FileType : int { + AOD, + DANGLING +}; + // add sink for the AODs DataProcessorSpec CommonDataProcessors::getGlobalAODSink(std::shared_ptr<DataOutputDirector> dod, diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 8cc278b707bdf..d33bd314f28b7 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -41,6 +41,12 @@ std::ostream& operator<<(std::ostream& out, TopoIndexInfo const& info) return out; } +enum OutputType : char { + UNKNOWN = 0, + DANGLING = 1, + ANALYSIS = 2, +}; + std::vector<TopoIndexInfo> WorkflowHelpers::topologicalSort(size_t nodeCount, int const* edgeIn, @@ -443,9 +449,9 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // has to be created in any case! std::vector<InputSpec> outputsInputsAOD; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { - if ((outputTypes[ii] & 2) == 2) { + if ((outputTypes[ii] & ANALYSIS) == ANALYSIS) { auto ds = dod->getDataOutputDescriptors(OutputsInputs[ii]); - if (ds.size() > 0 || (outputTypes[ii] & 1) == 1) { + if (ds.size() > 0 || (outputTypes[ii] & DANGLING) == DANGLING) { outputsInputsAOD.emplace_back(OutputsInputs[ii]); } } @@ -466,7 +472,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select dangling outputs which are not of type AOD std::vector<InputSpec> outputsInputsDangling; for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { - if ((outputTypes[ii] & 1) == 1 && (outputTypes[ii] & 2) == 0) { + if ((outputTypes[ii] & DANGLING) == DANGLING && (outputTypes[ii] & ANALYSIS) == 0) { outputsInputsDangling.emplace_back(OutputsInputs[ii]); } } @@ -906,15 +912,15 @@ std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers:: auto& outputSpec = workflow[output.workflowId].outputs[output.id]; // compute output type - unsigned char outputType = 0; + unsigned char outputType = UNKNOWN; // is AOD? if (DataSpecUtils::partialMatch(outputSpec, header::DataOrigin("AOD"))) { - outputType += 2; + outputType |= ANALYSIS; } // is RN2? if (DataSpecUtils::partialMatch(outputSpec, header::DataOrigin("RN2"))) { - outputType += 2; + outputType |= ANALYSIS; } // is dangling output? @@ -932,7 +938,7 @@ std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers:: } } if (!matched) { - outputType += 1; + outputType |= DANGLING; } // update results and outputTypes From 013af8a1bca835d4e5e56773870f591268cf4076 Mon Sep 17 00:00:00 2001 From: Nazar <nazar.burmasov@cern.ch> Date: Fri, 6 Nov 2020 12:49:18 +0300 Subject: [PATCH 1218/1751] Added TFNumber getter function, some dummy tables, some minor fixes applied. (#4772) * TFNumber fix added. Dummy TrackExtra table added. Switched to PrimaryVertexReader * Added some columns to TrackExtra table * TF number obtained via vtx. timestamps, added dummy tables for FV0, FDD, ZDC, TrackExtra, some minor fixes applied * Fix for TF number getter --- Detectors/AOD/CMakeLists.txt | 3 +- .../AODProducerWorkflowSpec.h | 24 +- Detectors/AOD/src/AODProducerWorkflow.cxx | 3 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 261 ++++++++++++++---- 4 files changed, 238 insertions(+), 53 deletions(-) diff --git a/Detectors/AOD/CMakeLists.txt b/Detectors/AOD/CMakeLists.txt index 9cab93768602f..238591fed5a55 100644 --- a/Detectors/AOD/CMakeLists.txt +++ b/Detectors/AOD/CMakeLists.txt @@ -26,13 +26,14 @@ o2_add_library( O2::Steer O2::TOFWorkflow O2::TPCWorkflow + O2::CCDB ) o2_add_executable( workflow COMPONENT_NAME aod-producer SOURCES src/aod-producer-workflow.cxx - PUBLIC_LINK_LIBRARIES O2::AODProducerWorkflow + PUBLIC_LINK_LIBRARIES O2::AODProducerWorkflow ) o2_add_executable( diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 77053713e74a0..c36b47bc2800c 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -15,10 +15,12 @@ #include "DataFormatsFT0/RecPoints.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "TStopwatch.h" +#include <CCDB/BasicCCDBManager.h> #include <string> #include <vector> @@ -50,7 +52,26 @@ using TracksTable = o2::soa::Table<o2::aod::track::CollisionId, o2::aod::track::Rho1PtY, o2::aod::track::Rho1PtZ, o2::aod::track::Rho1PtSnp, - o2::aod::track::Rho1PtTgl>; + o2::aod::track::Rho1PtTgl, + o2::aod::track::TPCInnerParam, + o2::aod::track::Flags, + o2::aod::track::ITSClusterMap, + o2::aod::track::TPCNClsFindable, + o2::aod::track::TPCNClsFindableMinusFound, + o2::aod::track::TPCNClsFindableMinusCrossedRows, + o2::aod::track::TPCNClsShared, + o2::aod::track::TRDPattern, + o2::aod::track::ITSChi2NCl, + o2::aod::track::TPCChi2NCl, + o2::aod::track::TRDChi2, + o2::aod::track::TOFChi2, + o2::aod::track::TPCSignal, + o2::aod::track::TRDSignal, + o2::aod::track::TOFSignal, + o2::aod::track::Length, + o2::aod::track::TOFExpMom, + o2::aod::track::TrackEtaEMCAL, + o2::aod::track::TrackPhiEMCAL>; class AODProducerWorkflowDPL : public Task { @@ -71,6 +92,7 @@ class AODProducerWorkflowDPL : public Task uint64_t minGlBC = INT64_MAX; void findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC); + int64_t getTFNumber(uint64_t firstVtxGlBC, int runNumber); template <typename TracksType, typename TracksCursorType> void fillTracksTable(const TracksType& tracks, std::vector<int>& vCollRefs, const TracksCursorType& tracksCursor, int trackType); diff --git a/Detectors/AOD/src/AODProducerWorkflow.cxx b/Detectors/AOD/src/AODProducerWorkflow.cxx index cc1d052ab2626..51a46f46f5cd0 100644 --- a/Detectors/AOD/src/AODProducerWorkflow.cxx +++ b/Detectors/AOD/src/AODProducerWorkflow.cxx @@ -35,14 +35,13 @@ framework::WorkflowSpec getAODProducerWorkflow() { // TODO: // switch to configurable parameters (?) - bool useFT0 = true; bool useMC = false; // FIXME: // switch (?) from o2::ft0::getReconstructionSpec to RecPointReader // (which does not return RECCHDATA at the moment) framework::WorkflowSpec specs{ - o2::vertexing::getPrimaryVertexingSpec(useFT0, useMC), + o2::vertexing::getPrimaryVertexReaderSpec(useMC), o2::globaltracking::getTrackTPCITSReaderSpec(useMC), o2::its::getITSTrackReaderSpec(useMC), o2::tpc::getTPCTrackReaderSpec(useMC), diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index b9eabb7f7df9b..ccd90acc63d75 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -15,7 +15,10 @@ #include "DataFormatsITS/TrackITS.h" #include "DataFormatsTPC/TrackTPC.h" #include "DetectorsCommonDataFormats/NameConf.h" +#include <CCDB/BasicCCDBManager.h> +#include "CommonDataFormat/InteractionRecord.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/DataTypes.h" #include "Framework/InputRecordWalker.h" @@ -54,8 +57,8 @@ void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& f } for (auto& trackITSTPC : tracksITSTPC) { - Double_t timeStamp = trackITSTPC.getTimeMUS().getTimeStamp() * 1.E3; // ms to ns - uint64_t bc = (int)(timeStamp / o2::constants::lhc::LHCBunchSpacingNS); + Double_t timeStamp = trackITSTPC.getTimeMUS().getTimeStamp() * 1.E3; // mus to ns + uint64_t bc = (uint64_t)(timeStamp / o2::constants::lhc::LHCBunchSpacingNS); if (minGlBC > bc) { minGlBC = bc; } @@ -65,12 +68,97 @@ void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& f } } +int64_t AODProducerWorkflowDPL::getTFNumber(uint64_t firstVtxGlBC, int runNumber) +{ + // FIXME: + // check if this code is correct + + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); + o2::ccdb::CcdbApi ccdb_api; + const std::string rct_path = "RCT/RunInformation/"; + const std::string start_orbit_path = "Trigger/StartOrbit"; + const std::string url = "http://ccdb-test.cern.ch:8080"; + + mgr.setURL(url); + ccdb_api.init(url); + + std::map<int, int>* mapStartOrbit = mgr.get<std::map<int, int>>(start_orbit_path); + int64_t ts = 0; + std::map<std::string, std::string> metadata; + std::map<std::string, std::string> headers; + const std::string run_path = Form("%s/%i", rct_path.data(), runNumber); + headers = ccdb_api.retrieveHeaders(run_path, metadata, -1); + ts = atol(headers["SOR"].c_str()); + + // ccdb returns timestamp in mus + // mus to ms + ts = ts / 1000; + + // firstRec --> calculated using `minimal` global BC in the simulation (see AODProducerWorkflowDPL::findMinMaxBc) + // firstVtxGlBC --> calculated using global BC correspinding to the first prim. vertex + + uint32_t initialOrbit = mapStartOrbit->at(runNumber); + uint16_t firstRecBC = minGlBC % o2::constants::lhc::LHCMaxBunches; + uint32_t firstRecOrbit = minGlBC / o2::constants::lhc::LHCMaxBunches; + uint16_t firstVtxBC = firstVtxGlBC % o2::constants::lhc::LHCMaxBunches; + uint32_t firstVtxOrbit = firstVtxGlBC / o2::constants::lhc::LHCMaxBunches; + const o2::InteractionRecord firstRec(firstRecBC, firstRecOrbit); + const o2::InteractionRecord firstVtx(firstVtxBC, firstVtxOrbit); + ts += (firstVtx - firstRec).bc2ns() / 1000000; + + return ts; +}; + template <typename TracksType, typename TracksCursorType> void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vector<int>& vCollRefs, const TracksCursorType& tracksCursor, int trackType) { for (int i = 0; i < tracks.size(); i++) { auto& track = tracks[i]; int collisionID = vCollRefs[i]; + + float tpcInnerParam = 0.f; + uint32_t flags = 0; + uint8_t itsClusterMap = 0; + uint8_t tpcNClsFindable = 0; + int8_t tpcNClsFindableMinusFound = 0; + int8_t tpcNClsFindableMinusCrossedRows = 0; + uint8_t tpcNClsShared = 0; + uint8_t trdPattern = 0; + float itsChi2NCl = -999.f; + float tpcChi2NCl = -999.f; + float trdChi2 = -999.f; + float tofChi2 = -999.f; + float tpcSignal = -999.f; + float trdSignal = -999.f; + float tofSignal = -999.f; + float length = -999.f; + float tofExpMom = -999.f; + float trackEtaEMCAL = -999.f; + float trackPhiEMCAL = -999.f; + + // filling available columns for different track types + // FIXME: + // is there a more nice/simple way to do this? + std::variant<o2::its::TrackITS, o2::tpc::TrackTPC, o2::dataformats::TrackTPCITS> tmp = track; + std::visit( + overloaded{ + [&](o2::its::TrackITS itsTrack) { + itsClusterMap = itsTrack.getPattern(); + }, + [&](o2::tpc::TrackTPC tpcTrack) { + tpcChi2NCl = tpcTrack.getChi2(); + // FIXME: + // what values to fill here? + tpcSignal = tpcTrack.getdEdx().dEdxTotTPC; + tpcNClsFindable = tpcTrack.getNClusters(); + }, + [&](o2::dataformats::TrackTPCITS itsTpcTrack) { + LOG(DEBUG) << "TrackTPCITS: check"; + }}, + tmp); + + // TODO: + // fill trackextra table tracksCursor(0, collisionID, trackType, @@ -95,7 +183,26 @@ void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vect (Char_t)(128. * track.getSigma1PtY() / track.getSigma1Pt2() / track.getSigmaY2()), (Char_t)(128. * track.getSigma1PtZ() / track.getSigma1Pt2() / track.getSigmaZ2()), (Char_t)(128. * track.getSigma1PtSnp() / track.getSigma1Pt2() / track.getSigmaSnp2()), - (Char_t)(128. * track.getSigma1PtTgl() / track.getSigma1Pt2() / track.getSigmaTgl2())); + (Char_t)(128. * track.getSigma1PtTgl() / track.getSigma1Pt2() / track.getSigmaTgl2()), + tpcInnerParam, + flags, + itsClusterMap, + tpcNClsFindable, + tpcNClsFindableMinusFound, + tpcNClsFindableMinusCrossedRows, + tpcNClsShared, + trdPattern, + itsChi2NCl, + tpcChi2NCl, + trdChi2, + tofChi2, + tpcSignal, + trdSignal, + tofSignal, + length, + tofExpMom, + trackEtaEMCAL, + trackPhiEMCAL); } } @@ -134,12 +241,12 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto& ft0Builder = pc.outputs().make<TableBuilder>(Output{"AOD", "FT0"}); auto& mcCollisionsBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "MCCOLLISION"}); auto& tracksBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "TRACK"}); + auto& timeFrameNumberBuilder = pc.outputs().make<uint64_t>(Output{"TFN", "TFNumber"}); - // TODO: - // add FV0A, FV0C, FDD tables - // auto& fv0aBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0A"}); - // auto& fv0cBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0C"}); - // auto& fddBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FDD"}); + auto& fv0aBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0A"}); + auto& fv0cBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0C"}); + auto& fddBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FDD"}); + auto& zdcBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "ZDC"}); auto bcCursor = bcBuilder.cursor<o2::aod::BCs>(); auto collisionsCursor = collisionsBuilder.cursor<o2::aod::Collisions>(); @@ -147,19 +254,76 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto mcCollisionsCursor = mcCollisionsBuilder.cursor<o2::aod::McCollisions>(); auto tracksCursor = tracksBuilder.cursor<o2::aodproducer::TracksTable>(); + auto fv0aCursor = fv0aBuilder.cursor<o2::aod::FV0As>(); + auto fv0cCursor = fv0cBuilder.cursor<o2::aod::FV0Cs>(); + auto fddCursor = fddBuilder.cursor<o2::aod::FDDs>(); + auto zdcCursor = zdcBuilder.cursor<o2::aod::Zdcs>(); + + findMinMaxBc(ft0RecPoints, tracksITSTPC); + + std::map<uint64_t, uint64_t> mGlobBC2BCID; + // TODO: - // add FV0A, FV0C, FDD tables - // auto fv0aCursor = fv0aBuilder.cursor<o2::aod::FV0As>(); - // auto fv0cCursor = fv0cBuilder.cursor<o2::aod::FV0Cs>(); - // auto fddCursor = fddBuilder.cursor<o2::aod::FDDs>(); - - // float dummyfv0AmplA[48] = {0.}; - // float dummyfv0AmplC[32] = {0.}; - // float dummyfddAmplA[4] = {0.}; - // float dummyfddAmplC[4] = {0.}; - // fv0aCursor(0, (uint64_t)0, dummyfv0AmplA, 0.f, (uint8_t)0); - // fv0cCursor(0, (uint64_t)0, dummyfv0AmplC, 0.f); - // fddCursor(0, (uint64_t)0, dummyfddAmplA, dummyfddAmplC, 0.f, 0.f, (uint8_t)0); + // get real run number and triggerMask + int runNumber = 244918; + uint64_t triggerMask = 1; + + // filling BC table and map<globalBC, BCId> + for (uint64_t i = 0; i <= maxGlBC - minGlBC; i++) { + bcCursor(0, + runNumber, + minGlBC + i, + triggerMask); + mGlobBC2BCID[minGlBC + i] = i; + } + + // TODO: + // add real FV0A, FV0C, FDD, ZDC tables instead of dummies + float dummyfv0AmplA[48] = {0.}; + fv0aCursor(0, + (uint64_t)0, + dummyfv0AmplA, + 0.f, + (uint8_t)0); + + float dummyfv0AmplC[32] = {0.}; + fv0cCursor(0, + (uint64_t)0, + dummyfv0AmplC, + 0.f); + + float dummyfddAmplA[4] = {0.}; + float dummyfddAmplC[4] = {0.}; + fddCursor(0, + (uint64_t)0, + dummyfddAmplA, + dummyfddAmplC, + 0.f, + 0.f, + (uint8_t)0); + + float dummyEnergySectorZNA[4] = {0.}; + float dummyEnergySectorZNC[4] = {0.}; + float dummyEnergySectorZPA[4] = {0.}; + float dummyEnergySectorZPC[4] = {0.}; + zdcCursor(0, + (uint64_t)0, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + dummyEnergySectorZNA, + dummyEnergySectorZNC, + dummyEnergySectorZPA, + dummyEnergySectorZPC, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f); o2::steer::MCKinematicsReader mcReader("collisioncontext.root"); const auto context = mcReader.getDigitizationContext(); @@ -170,7 +334,6 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) LOG(INFO) << "FOUND " << parts.size() << " parts"; // TODO: - // change index to BCId (?) // figure out generatorID and collision weight int index = 0; int generatorID = 0; @@ -183,8 +346,9 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto eventID = colparts[0].entryID; auto sourceID = colparts[0].sourceID; auto& header = mcReader.getMCEventHeader(sourceID, eventID); + uint64_t globalBC = rec.bc + rec.orbit * o2::constants::lhc::LHCMaxBunches; mcCollisionsCursor(0, - index, + mGlobBC2BCID.at(globalBC), generatorID, header.GetX(), header.GetY(), @@ -195,24 +359,6 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) index++; } - findMinMaxBc(ft0RecPoints, tracksITSTPC); - - std::map<uint64_t, uint64_t> mGlobBC2BCID; - - // TODO: - // get real run number and triggerMask - int runNumber = 244918; - uint64_t triggerMask = 1; - - // filling BC table and map<globalBC, BCId> - for (uint64_t i = 0; i <= maxGlBC - minGlBC; i++) { - bcCursor(0, - runNumber, - minGlBC + i, - triggerMask); - mGlobBC2BCID[minGlBC + i] = i; - } - // vector of FT0 amplitudes std::vector<float> vAmplitudes(208, 0.); // filling FT0 table @@ -229,7 +375,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) std::copy(vAmplitudes.begin() + 96, vAmplitudes.end(), aAmplitudesC); uint64_t globalBC = ft0RecPoint.getInteractionRecord().orbit * o2::constants::lhc::LHCMaxBunches + ft0RecPoint.getInteractionRecord().bc; ft0Cursor(0, - mGlobBC2BCID[globalBC], + mGlobBC2BCID.at(globalBC), aAmplitudesA, aAmplitudesC, ft0RecPoint.getCollisionTimeA() / 1E3, // ps to ns @@ -242,17 +388,27 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) std::vector<int> vCollRefsTPC(tracksTPC.size(), -1); std::vector<int> vCollRefsTPCITS(tracksITSTPC.size(), -1); + // global bc of the 1st vertex for TF number + uint64_t firstVtxGlBC; + // filling collisions table int collisionID = 0; for (auto& vertex : primVertices) { auto& cov = vertex.getCov(); auto& timeStamp = vertex.getTimeStamp(); - Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // ms to ns + Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // mus to ns + // FIXME: + // should use IRMin and IRMax for globalBC calculation uint64_t globalBC = tsTimeStamp / o2::constants::lhc::LHCBunchSpacingNS; - int BCid = mGlobBC2BCID[globalBC]; + + if (collisionID == 0) { + firstVtxGlBC = globalBC; + } + + int BCid = mGlobBC2BCID.at(globalBC); // TODO: // get real collision time mask - int collisionTimeMask = 1; + int collisionTimeMask = 0; collisionsCursor(0, BCid, vertex.getX(), @@ -272,6 +428,9 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto trackRef = primVer2TRefs[collisionID]; int start = trackRef.getFirstEntryOfSource(0); int ntracks = trackRef.getEntriesOfSource(0); + + // FIXME: + // `track<-->vertex` ambiguity is not accounted for in this code for (int ti = 0; ti < ntracks; ti++) { auto trackIndex = primVerGIs[start + ti]; const auto source = trackIndex.getSource(); @@ -300,6 +459,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) fillTracksTable(tracksITSTPC, vCollRefsTPCITS, tracksCursor, o2::vertexing::GIndex::Source::TPCITS); // fTrackType = 0 } + timeFrameNumberBuilder = getTFNumber(firstVtxGlBC, runNumber); + mTimer.Stop(); } @@ -316,8 +477,8 @@ DataProcessorSpec getAODProducerWorkflowSpec() inputs.emplace_back("ft0ChData", "FT0", "RECCHDATA", 0, Lifetime::Timeframe); inputs.emplace_back("ft0RecPoints", "FT0", "RECPOINTS", 0, Lifetime::Timeframe); - inputs.emplace_back("primVer2TRefs", "GLO", "PVTX_CONTIDREFS", 0, Lifetime::Timeframe); - inputs.emplace_back("primVerGIs", "GLO", "PVTX_CONTID", 0, Lifetime::Timeframe); + inputs.emplace_back("primVer2TRefs", "GLO", "PVTX_TRMTCREFS", 0, Lifetime::Timeframe); + inputs.emplace_back("primVerGIs", "GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe); inputs.emplace_back("primVertices", "GLO", "PVTX", 0, Lifetime::Timeframe); inputs.emplace_back("trackITS", "ITS", "TRACKS", 0, Lifetime::Timeframe); inputs.emplace_back("tracksITSTPC", "GLO", "TPCITS", 0, Lifetime::Timeframe); @@ -328,12 +489,14 @@ DataProcessorSpec getAODProducerWorkflowSpec() outputs.emplace_back(OutputLabel{"O2ft0"}, "AOD", "FT0", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2mccollision"}, "AOD", "MCCOLLISION", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2track"}, "AOD", "TRACK", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputSpec{"TFN", "TFNumber"}); // TODO: // add FV0A, FV0C, FDD tables - // outputs.emplace_back(OutputLabel{"O2fv0a"}, "AOD", "FV0A", 0, Lifetime::Timeframe); - // outputs.emplace_back(OutputLabel{"O2fv0c"}, "AOD", "FV0C", 0, Lifetime::Timeframe); - // outputs.emplace_back(OutputLabel{"O2fdd"}, "AOD", "FDD", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2fv0a"}, "AOD", "FV0A", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2fv0c"}, "AOD", "FV0C", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2fdd"}, "AOD", "FDD", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2zdc"}, "AOD", "ZDC", 0, Lifetime::Timeframe); return DataProcessorSpec{ "aod-producer-workflow", From 7186b2e9ebec26c9ac3d6af171ece69decdbf70e Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 26 Oct 2020 15:31:32 +0100 Subject: [PATCH 1219/1751] Use correct data description for MID raw writer spec --- Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx b/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx index 6444952c8d643..ce4741c29b1b5 100644 --- a/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/RawWriterSpec.cxx @@ -71,10 +71,10 @@ class RawWriterDeviceDPL void run(o2::framework::ProcessingContext& pc) { - auto msg = pc.inputs().get("mid_data"); + auto msg = pc.inputs().get("mid_data_mc"); gsl::span<const ColumnData> data = of::DataRefUtils::as<const ColumnData>(msg); - auto msgROF = pc.inputs().get("mid_data_rof"); + auto msgROF = pc.inputs().get("mid_data_mc_rof"); gsl::span<const ROFRecord> rofRecords = of::DataRefUtils::as<const ROFRecord>(msgROF); for (auto& rofRecord : rofRecords) { @@ -89,7 +89,7 @@ class RawWriterDeviceDPL framework::DataProcessorSpec getRawWriterSpec() { - std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_data", header::gDataOriginMID, "DATA"}, of::InputSpec{"mid_data_rof", header::gDataOriginMID, "DATAROF"}}; + std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_data_mc", header::gDataOriginMID, "DATAMC"}, of::InputSpec{"mid_data_mc_rof", header::gDataOriginMID, "DATAMCROF"}}; return of::DataProcessorSpec{ "MIDRawWriter", From 27df2923808ce1aad775b0e2bce47168a69b5961 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 6 Nov 2020 13:22:10 +0100 Subject: [PATCH 1220/1751] Rename MID option to use the name parameter name as other detectors --- Detectors/MUON/MID/Workflow/README.md | 2 +- Detectors/MUON/MID/Workflow/src/reco-workflow.cxx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/README.md b/Detectors/MUON/MID/Workflow/README.md index d31d57eaed032..b42719509a09c 100644 --- a/Detectors/MUON/MID/Workflow/README.md +++ b/Detectors/MUON/MID/Workflow/README.md @@ -109,5 +109,5 @@ o2-mid-reco-workflow --disable-tracking It is also possible to avoid producing a root file with: ```bash -o2-mid-reco-workflow --disable-output-file +o2-mid-reco-workflow --disable-root-output ``` diff --git a/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx b/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx index b3ed220b29178..816abb8917611 100644 --- a/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx @@ -37,7 +37,7 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) options{ {"mc", VariantType::Bool, false, {"Propagate labels"}}, {"disable-tracking", VariantType::Bool, false, {"Only run clustering"}}, - {"disable-output-file", VariantType::Bool, false, {"Do not write output to file"}}}; + {"disable-root-output", VariantType::Bool, false, {"Do not write output to file"}}}; workflowOptions.insert(workflowOptions.end(), options.begin(), options.end()); } @@ -47,7 +47,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { bool isMC = cfgc.options().get<bool>("mc"); bool disableTracking = cfgc.options().get<bool>("disable-tracking"); - bool disableFile = cfgc.options().get<bool>("disable-output-file"); + bool disableFile = cfgc.options().get<bool>("disable-root-output"); WorkflowSpec specs; specs.emplace_back(isMC ? o2::mid::getClusterizerMCSpec() : o2::mid::getClusterizerSpec()); From 41283e796bced6784d4debaf732dc1a7089d0b90 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 6 Nov 2020 13:24:53 +0100 Subject: [PATCH 1221/1751] Fix full-system-test benchmark after change in MID workflow --- prodtests/full_system_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 32df683595e73..52d1a0ce44514 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -86,6 +86,7 @@ o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | o2-ft0-entropy-encoder-workflow $ARGS_ALL | o2-tpcits-match-workflow $ARGS_ALL -b --disable-root-input --disable-root-output ${NOMCLABELS} | +o2-mid-raw-to-digits-workflow $ARGS_ALL | \ o2-mid-reco-workflow $ARGS_ALL --disable-root-output | o2-mid-entropy-encoder-workflow $ARGS_ALL | o2-tof-compressor $ARGS_ALL | From 73580255d11f222cc8e5fe6381456a27dc8cf070 Mon Sep 17 00:00:00 2001 From: anerokhi <44967087+anerokhi@users.noreply.github.com> Date: Fri, 6 Nov 2020 16:40:34 +0300 Subject: [PATCH 1222/1751] Detectors/Upgrades: make readability-braces-around-statements happy (#4776) --- .../IT3/base/include/ITS3Base/GeometryTGeo.h | 3 +- .../Upgrades/IT3/base/src/GeometryTGeo.cxx | 3 +- .../Upgrades/IT3/simulation/src/Detector.cxx | 15 ++- .../Upgrades/IT3/simulation/src/V3Layer.cxx | 115 ++++++++++++------ .../IT3/simulation/src/V3Services.cxx | 54 +++++--- .../IT4/base/include/ITS4Base/GeometryTGeo.h | 3 +- .../PostLS4/IT4/base/src/GeometryTGeo.cxx | 3 +- .../PostLS4/IT4/simulation/src/Detector.cxx | 15 ++- .../PostLS4/IT4/simulation/src/V3Layer.cxx | 115 ++++++++++++------ .../PostLS4/IT4/simulation/src/V3Services.cxx | 54 +++++--- 10 files changed, 246 insertions(+), 134 deletions(-) diff --git a/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h b/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h index b37e393291fc7..2857cf19c86f4 100644 --- a/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h +++ b/Detectors/Upgrades/IT3/base/include/ITS3Base/GeometryTGeo.h @@ -53,8 +53,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo static GeometryTGeo* Instance() { // get (create if needed) a unique instance of the object - if (!sInstance) + if (!sInstance) { sInstance = std::unique_ptr<GeometryTGeo>(new GeometryTGeo(true, 0)); + } return sInstance.get(); } diff --git a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx index 55afcfc8b4b7d..210e677910de5 100644 --- a/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/IT3/base/src/GeometryTGeo.cxx @@ -679,8 +679,9 @@ int GeometryTGeo::extractLayerChipType(int lay) const void GeometryTGeo::Print(Option_t*) const { printf("NLayers:%d NChips:%d\n", mNumberOfLayers, getNumberOfChips()); - if (!isBuilt()) + if (!isBuilt()) { return; + } for (int i = 0; i < mNumberOfLayers; i++) { printf( diff --git a/Detectors/Upgrades/IT3/simulation/src/Detector.cxx b/Detectors/Upgrades/IT3/simulation/src/Detector.cxx index a564dcb442087..760fecf285dc2 100644 --- a/Detectors/Upgrades/IT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/IT3/simulation/src/Detector.cxx @@ -394,8 +394,9 @@ Bool_t Detector::ProcessHits(FairVolume* vol) while ((lay < mTotalNumberOfLayers) && (notSens = (volID != mLayerID[lay]))) { ++lay; } - if (notSens) + if (notSens) { return kFALSE; // RS: can this happen? This method must be called for sensors only? + } // Is it needed to keep a track reference when the outer ITS volume is encountered? auto stack = (o2::data::Stack*)fMC->GetStack(); @@ -435,10 +436,12 @@ Bool_t Detector::ProcessHits(FairVolume* vol) } // increment energy loss at all steps except entrance - if (!startHit) + if (!startHit) { mTrackData.mEnergyLoss += fMC->Edep(); - if (!(startHit | stopHit)) + } + if (!(startHit | stopHit)) { return kFALSE; // do noting + } if (startHit) { mTrackData.mEnergyLoss = 0.; @@ -976,8 +979,9 @@ void Detector::constructDetectorGeometry() vITSV->AddNode(wrapVols[id], 1, nullptr); } } - if (!mCreateOuterBarrel) + if (!mCreateOuterBarrel) { mTotalNumberOfLayers = mNumberOfInnerLayers; + } // Now create the actual geometry for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { @@ -1021,7 +1025,7 @@ void Detector::constructDetectorGeometry() mGeometry[j]->setSensorThick(mDetectorThickness[j]); } - if (mCreateOuterBarrel && j >= mNumberOfInnerLayers) + if (mCreateOuterBarrel && j >= mNumberOfInnerLayers) { for (int iw = 0; iw < sNumberOfWrapperVolumes; iw++) { if (mLayerRadii[j] > mWrapperMinRadius[iw] && mLayerRadii[j] < mWrapperMaxRadius[iw]) { LOG(DEBUG) << "Will embed layer " << j << " in wrapper volume " << iw; @@ -1031,6 +1035,7 @@ void Detector::constructDetectorGeometry() break; } } + } mGeometry[j]->createLayer(dest); } diff --git a/Detectors/Upgrades/IT3/simulation/src/V3Layer.cxx b/Detectors/Upgrades/IT3/simulation/src/V3Layer.cxx index f4e6815106a47..cbc2914b68a74 100644 --- a/Detectors/Upgrades/IT3/simulation/src/V3Layer.cxx +++ b/Detectors/Upgrades/IT3/simulation/src/V3Layer.cxx @@ -547,8 +547,9 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) // mechStaveVol = createStaveStructInnerB(); if (mechStaveVol) { ypos = (static_cast<TGeoBBox*>(modVol->GetShape()))->GetDY() - ypos; - if (mStaveModel != Detector::kIBModel4) + if (mStaveModel != Detector::kIBModel4) { ypos += (static_cast<TGeoBBox*>(mechStaveVol->GetShape()))->GetDY(); + } staveVol->AddNode(mechStaveVol, 1, new TGeoCombiTrans(0, -ypos, 0, new TGeoRotation("", 0, 0, 180))); } } else { @@ -566,9 +567,10 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) mechStaveVol = createSpaceFrameOuterB(); if (mechStaveVol) { - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon staveVol->AddNode(mechStaveVol, 1, new TGeoCombiTrans(0, -sOBSFrameULegHeight1, 0, new TGeoRotation("", 180, 0, 0))); + } } } } @@ -617,10 +619,11 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) char chipName[nameLen], sensName[nameLen], volumeName[nameLen]; // For material budget studies - if (mBuildLevel < 6) + if (mBuildLevel < 6) { dummyChip = kFALSE; // will be made of Si - else + } else { dummyChip = kTRUE; // will be made of Air + } // First create the single chip snprintf(chipName, nameLen, "%s%d", o2::its3::GeometryTGeo::getITSChipPattern(), mLayerNumber); @@ -651,8 +654,9 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) Double_t yano = (static_cast<TGeoBBox*>(aluAnodeCableVol->GetShape()))->GetDY(); ytot = ymod; - if (mStaveModel == Detector::kIBModel4) + if (mStaveModel == Detector::kIBModel4) { ytot += (sIBGlueThick / 2 + ygnd + sIBFlexCableKapThick / 2 + yano + sIBFlexCapacitorYHi / 2); + } TGeoBBox* module = new TGeoBBox(xtot, ytot, ztot); @@ -685,8 +689,9 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) if (mStaveModel == Detector::kIBModel4) { ypos += (ymod + glue->GetDY()); - if (mBuildLevel < 2) // Glue + if (mBuildLevel < 2) { // Glue modVol->AddNode(glueVol, 1, new TGeoTranslation(xpos, ypos, 0)); + } ypos += glue->GetDY(); if (mBuildLevel < 4) { // Kapton @@ -808,20 +813,22 @@ void V3Layer::createIBCapacitors(TGeoVolume* modvol, Double_t zchip, Double_t yz nCapacitors++; for (Int_t j = 0; j < sIBChipsPerRow; j++) { - if (j == (sIBChipsPerRow - 1)) + if (j == (sIBChipsPerRow - 1)) { xpos = xGroup4[1]; - else + } else { xpos = xGroup4[0]; + } zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup4[j]; modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); } nCapacitors += sIBChipsPerRow; for (Int_t j = 0; j < nGroup5A; j++) { - if (j == 0) + if (j == 0) { xpos = xGroup5A[0]; - else + } else { xpos = xGroup5A[1]; + } zpos = zGroup5A[j]; modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); } @@ -869,8 +876,9 @@ TGeoVolume* V3Layer::createIBFPCAlGnd(const Double_t xcable, const Double_t zcab aluminumVol->SetFillColor(kCyan); ypos = coverlay->GetDY() - aluminum->GetDY(); - if (mBuildLevel < 1) // Aluminum + if (mBuildLevel < 1) { // Aluminum coverlayVol->AddNode(aluminumVol, 1, new TGeoTranslation(0, ypos, 0)); + } return coverlayVol; } @@ -920,8 +928,9 @@ TGeoVolume* V3Layer::createIBFPCAlAnode(const Double_t xcable, const Double_t zc aluminumVol->SetFillColor(kCyan); ypos = -coverlay->GetDY() + aluminum->GetZ(1); - if (mBuildLevel < 1) // Aluminum + if (mBuildLevel < 1) { // Aluminum coverlayVol->AddNode(aluminumVol, 1, new TGeoCombiTrans(0, ypos, 0, new TGeoRotation("", 0, -90, 0))); + } return coverlayVol; } @@ -1224,16 +1233,19 @@ TGeoVolume* V3Layer::createStaveModelInnerB4(const TGeoManager* mgr) // Now build up the half stave ypos = glue->GetDY(); - if (mBuildLevel < 2) // Glue + if (mBuildLevel < 2) { // Glue mechStavVol->AddNode(glueVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (glue->GetDY() + fleecbot->GetDY()); - if (mBuildLevel < 5) // Carbon + if (mBuildLevel < 5) { // Carbon mechStavVol->AddNode(fleecbotVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (fleecbot->GetDY() + cfplate->GetDY()); - if (mBuildLevel < 5) // Carbon + if (mBuildLevel < 5) { // Carbon mechStavVol->AddNode(cfplateVol, 1, new TGeoTranslation(0, ypos, 0)); + } ylay = ypos + cfplate->GetDY(); // The level where tubes etc. lay @@ -1906,10 +1918,11 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) zmod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDZ(); if (mLayerNumber == mNumberOfInnerLayers || - mLayerNumber == mNumberOfInnerLayers + 1) + mLayerNumber == mNumberOfInnerLayers + 1) { zlen = sOBColdPlateZLenML / 2; // Middle Layer - else + } else { zlen = sOBColdPlateZLenOL / 2; // Outer Layer + } xlen = sOBColdPlateXWidth / 2; @@ -1944,8 +1957,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) new TGeoTubeSeg("FleecTube", rCoolMax + yGraph, rCoolMax + yCFleece + yGraph, zlen, 180., 360.); TGeoTube* gammaConvRod; - if (mAddGammaConv) + if (mAddGammaConv) { gammaConvRod = new TGeoTube("GammaConver", 0, 0.5 * mGammaConvDiam, zlen - sOBCPConnHollowZLen); + } // TGeoBBox* flex1_5cm = new TGeoBBox("Flex1MV_5cm", xHalfSt, yFlex1 / 2, flexOverlap / 2); // TGeoBBox* flex2_5cm = new TGeoBBox("Flex2MV_5cm", xHalfSt, yFlex2 / 2, flexOverlap / 2); @@ -1958,8 +1972,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) // The half stave container (an XTru to avoid overlaps between neightbours) xHalfSt = xmod; // add the cross cables when done! yHalfSt = ypowbus + ymod + coldPlate->GetDY() + 2 * fleeccent->GetDY() + graphlat->GetDY() + fleeclat->GetDY(); - if (mAddGammaConv) + if (mAddGammaConv) { yHalfSt += mGammaConvDiam; + } xtru[0] = xHalfSt; ytru[0] = 0; @@ -1969,8 +1984,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) ytru[2] = ytru[1]; xtru[3] = xtru[2]; ytru[3] = ytru[2] - (coolTube->GetRmax() + fleectub->GetRmax()); - if (mAddGammaConv) + if (mAddGammaConv) { ytru[3] -= mGammaConvDiam; + } xtru[4] = sOBCoolTubeXDist / 2 - fleectub->GetRmax(); ytru[4] = ytru[3]; xtru[5] = xtru[4]; @@ -1994,8 +2010,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) new TGeoBBox("connCsideOB", sOBCPConnectorXWidth / 2, sOBCPConnBlockYHei / 2, sOBCPConnBlockZLen / 2); // The StaveStruct container, a Composite Shape - if (mAddGammaConv) + if (mAddGammaConv) { yHalfSt -= mGammaConvDiam; + } ypos = 2 * yHalfSt + connAside->GetDY() - sOBCPConnHollowYHei; zpos = zlen + connAside->GetDZ() - sOBCPConnHollowZLen; snprintf(volname, nameLen, "transAsideOB%d", mLayerNumber); @@ -2119,18 +2136,21 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) ypos -= ymod; ypos -= fleeccent->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(fleeccentVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos -= fleeccent->GetDY(); ypos -= coldPlate->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(coldPlateVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos -= coldPlate->GetDY(); ypos -= fleeccent->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(fleeccentVol, 2, new TGeoTranslation(0, ypos, 0)); + } xpos = sOBCoolTubeXDist / 2; ypos1 = ypos - (fleeccent->GetDY() + coolTube->GetRmax()); @@ -2307,45 +2327,55 @@ TGeoVolume* V3Layer::createOBPowerBiasBuses(const Double_t zcable, const TGeoMan // Volumes are piled up from bottom to top ypos = -pnbBus->GetDY() + kapPB->GetDY(); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (kapPB->GetDY() + gndPB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(gndPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (gndPB->GetDY() + dielPB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(dielPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (dielPB->GetDY() + topPB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(topPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (topPB->GetDY() + kapPB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapPBVol, 2, new TGeoTranslation(0, ypos, 0)); + } // ypos += (kapPB->GetDY() + kapBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (kapBB->GetDY() + botBB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(botBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (botBB->GetDY() + dielBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(dielBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (dielBB->GetDY() + topBB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(topBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (topBB->GetDY() + kapBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapBBVol, 2, new TGeoTranslation(0, ypos, 0)); + } // return pnbBusVol; @@ -3452,10 +3482,11 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) // First create all needed shapes // For material budget studies - if (mBuildLevel < 7) + if (mBuildLevel < 7) { dummyChip = kFALSE; // will be made of Si - else + } else { dummyChip = kTRUE; // will be made of Air + } // The chip (the same as for IB) snprintf(chipName, nameLen, "%s%d", o2::its3::GeometryTGeo::getITSChipPattern(), mLayerNumber); @@ -3525,8 +3556,9 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) // Now build up the module ypos = -module->GetDY() + glueCP->GetDY(); - if (mBuildLevel < 3) // Glue + if (mBuildLevel < 3) { // Glue modVol->AddNode(glueCPVol, 1, new TGeoTranslation(0, ypos, 0)); + } xpos = xchip + xGap / 2; ypos += (ychip + glueCP->GetDY()); @@ -3550,8 +3582,9 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) } ypos += (ychip + glueFPC->GetDY()); - if (mBuildLevel < 3) // Glue + if (mBuildLevel < 3) { // Glue modVol->AddNode(glueFPCVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += glueFPC->GetDY(); if (mBuildLevel < 5) { // Kapton @@ -3608,8 +3641,9 @@ TGeoVolume* V3Layer::createOBFPCCuGnd(const Double_t zcable, const TGeoManager* copperVol->SetFillColor(kCyan); ypos = -soldmask->GetDY() + copper->GetDY(); - if (mBuildLevel < 1) // Copper + if (mBuildLevel < 1) { // Copper soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + } return soldmaskVol; } @@ -3653,8 +3687,9 @@ TGeoVolume* V3Layer::createOBFPCCuSig(const Double_t zcable, const TGeoManager* copperVol->SetFillColor(kCyan); ypos = soldmask->GetDY() - copper->GetDY(); - if (mBuildLevel < 1) // Copper + if (mBuildLevel < 1) { // Copper soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + } return soldmaskVol; } diff --git a/Detectors/Upgrades/IT3/simulation/src/V3Services.cxx b/Detectors/Upgrades/IT3/simulation/src/V3Services.cxx index aa89b344a34ed..0f99e37b716cc 100644 --- a/Detectors/Upgrades/IT3/simulation/src/V3Services.cxx +++ b/Detectors/Upgrades/IT3/simulation/src/V3Services.cxx @@ -81,8 +81,9 @@ TGeoVolume* V3Services::createIBEndWheelsSideA(const TGeoManager* mgr) TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideA"); endWheelsVol->SetVisibility(kTRUE); - for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) { ibEndWheelSideA(jLay, endWheelsVol, mgr); + } // Return the wheels return endWheelsVol; @@ -108,8 +109,9 @@ TGeoVolume* V3Services::createIBEndWheelsSideC(const TGeoManager* mgr) TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideC"); endWheelsVol->SetVisibility(kTRUE); - for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) { ibEndWheelSideC(jLay, endWheelsVol, mgr); + } // Return the wheels return endWheelsVol; @@ -182,8 +184,9 @@ void V3Services::createMBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* m // Created: 24 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) { obEndWheelSideA(jLay, mother, mgr); + } } void V3Services::createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) @@ -202,8 +205,9 @@ void V3Services::createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* m // Created: 26 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) { mbEndWheelSideC(jLay, mother, mgr); + } } void V3Services::createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* mgr) @@ -222,8 +226,9 @@ void V3Services::createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* m // Created: 27 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) { obEndWheelSideA(jLay + sNumberMiddlLayers, mother, mgr); + } } void V3Services::createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) @@ -242,8 +247,9 @@ void V3Services::createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* m // Created: 27 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) { obEndWheelSideC(jLay, mother, mgr); + } } void V3Services::createOBConeSideA(TGeoVolume* mother, const TGeoManager* mgr) @@ -668,10 +674,11 @@ void V3Services::ibEndWheelSideC(const Int_t iLay, TGeoVolume* endWheel, const T endwcbshmata->RegisterYourself(); TGeoTranslation* endwcbshmatb = new TGeoTranslation(Form("endwcbshmat%dl%db", ihole, iLay), -xpos, -ypos, zpos); endwcbshmatb->RegisterYourself(); - if ((ihole > 1 && ihole < 5) || (ihole > 5 && ihole < 9)) // Small holes + if ((ihole > 1 && ihole < 5) || (ihole > 5 && ihole < 9)) { // Small holes strcpy(holename, endwcbasShol->GetName()); - else + } else { strcpy(holename, endwcbasBhol->GetName()); + } endWheelComposite += Form("-%s:endwcbshmat%dl%da-%s:endwcbshmat%dl%db", holename, ihole, iLay, holename, ihole, iLay); } @@ -1270,10 +1277,11 @@ TString V3Services::ibCreateHollowsCyssFlangeSideA(const Double_t zlen) cyssFlangeAHollows += Form("-roundhalf:roundtr%d-roundhalf:roundtr%d", j + 2, j + 5); phi = 360 - phi - 0.05; - if (j == 3) + if (j == 3) { dphi = 360 - sCyssFlangeAHollowPhi0 + 0.05; - else + } else { dphi = phi + (sCyssFlangeAHole1PhiStep - sCyssFlangeAHollowPhi1) + 0.1; + } TGeoTubeSeg* hollow1 = new TGeoTubeSeg(Form("hollow%d", j), rmin, rmax, 2 * zlen, phi, dphi); @@ -1611,10 +1619,11 @@ void V3Services::obEndWheelSideA(const Int_t iLay, TGeoVolume* mother, const TGe // Finally put everything in the mother volume // In blueprints the Z position is given wrt the shelf holes // First the ring - if (iLay < sNumberMiddlLayers) + if (iLay < sNumberMiddlLayers) { zpos = sMBWheelsZpos + sOBWheelShelfHoleZpos; - else + } else { zpos = sOBWheelsZpos + sOBWheelShelfHoleZpos; + } zpos -= outerRingSh->GetDz(); mother->AddNode(ringOuterVol, 1, new TGeoTranslation(0, 0, zpos)); @@ -1697,10 +1706,11 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe TGeoTube* innerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], sOBWheelSuppRmax[iLay], sOBWheelThickness / 2); // The outer ring with the flange - if (iLay == 0) + if (iLay == 0) { nsect = 6; - else + } else { nsect = 4; + } TGeoPcon* outerRingSh = new TGeoPcon(0, 360, nsect); @@ -1722,17 +1732,19 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe } // The lower ring - if (iLay == 0) + if (iLay == 0) { zlen = sOBWheelSuppZlen[iLay] - sOBWheelFlangeZlen - 2 * sOBWheelThickness; - else + } else { zlen = sOBWheelSuppZlen[iLay] - sOBWheelThickness - outerRingSh->GetZ(nsect - 1); + } rmax = sOBWheelSuppRmin[iLay] + sOBWheelThickness; TGeoTube* lowerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], rmax, zlen / 2); // The upper ring - if (iLay == 1) // For odd layers the upper and lower rings length is the same + if (iLay == 1) { // For odd layers the upper and lower rings length is the same zlen = sOBWheelSuppZlen[iLay] - 2 * sOBWheelThickness; + } rmin = sOBWheelSuppRmax[iLay] - sOBWheelThickness; TGeoTube* upperRingSh = new TGeoTube(rmin, sOBWheelSuppRmax[iLay], zlen / 2); @@ -1929,8 +1941,9 @@ void V3Services::obEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe mother->AddNode(ringLowerVol, 1, new TGeoTranslation(0, 0, -zpos)); - if (iLay == 1) + if (iLay == 1) { zpos -= (sOBWheelThickness + (static_cast<TGeoTube*>(upperRingSh))->GetDz()); + } mother->AddNode(ringUpperVol, 1, new TGeoTranslation(0, 0, -zpos)); } @@ -2165,10 +2178,11 @@ void V3Services::obConeTraysSideA(TGeoVolume* mother, const TGeoManager* mgr) // Finally put everything in the mother volume for (Int_t j = 0; j < 2; j++) { - if (j == 0) + if (j == 0) { zpos = sOBConesZpos - sOBTrayZpos[j] - sOBTrayZlen[j]; - else + } else { zpos = sOBConesZpos + sOBTrayZpos[j]; + } mother->AddNode(obTrayVol[j], 1, new TGeoTranslation(0, 0, zpos)); mother->AddNode(obTrayVol[j], 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 0, 0))); diff --git a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h index a52cce3d63b54..104b227f419ea 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h +++ b/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h @@ -53,8 +53,9 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo static GeometryTGeo* Instance() { // get (create if needed) a unique instance of the object - if (!sInstance) + if (!sInstance) { sInstance = std::unique_ptr<GeometryTGeo>(new GeometryTGeo(true, 0)); + } return sInstance.get(); } diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx index 3e35b82c2f9e2..1a12df0555369 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx @@ -680,8 +680,9 @@ int GeometryTGeo::extractLayerChipType(int lay) const void GeometryTGeo::Print(Option_t*) const { printf("NLayers:%d NChips:%d\n", mNumberOfLayers, getNumberOfChips()); - if (!isBuilt()) + if (!isBuilt()) { return; + } for (int i = 0; i < mNumberOfLayers; i++) { printf( diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx index 909259e2459a8..30dc0658cd6be 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx @@ -346,8 +346,9 @@ Bool_t Detector::ProcessHits(FairVolume* vol) while ((lay < mTotalNumberOfLayers) && (notSens = (volID != mLayerID[lay]))) { ++lay; } - if (notSens) + if (notSens) { return kFALSE; // RS: can this happen? This method must be called for sensors only? + } // Is it needed to keep a track reference when the outer ITS volume is encountered? auto stack = (o2::data::Stack*)fMC->GetStack(); @@ -387,10 +388,12 @@ Bool_t Detector::ProcessHits(FairVolume* vol) } // increment energy loss at all steps except entrance - if (!startHit) + if (!startHit) { mTrackData.mEnergyLoss += fMC->Edep(); - if (!(startHit | stopHit)) + } + if (!(startHit | stopHit)) { return kFALSE; // do noting + } if (startHit) { mTrackData.mEnergyLoss = 0.; @@ -883,8 +886,9 @@ void Detector::constructDetectorGeometry() vITSV->AddNode(wrapVols[id], 1, nullptr); } } - if (!mCreateOuterBarrel) + if (!mCreateOuterBarrel) { mTotalNumberOfLayers = mNumberOfInnerLayers; + } // Now create the actual geometry for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { @@ -928,7 +932,7 @@ void Detector::constructDetectorGeometry() mGeometry[j]->setSensorThick(mDetectorThickness[j]); } - if (mCreateOuterBarrel && j >= mNumberOfInnerLayers) + if (mCreateOuterBarrel && j >= mNumberOfInnerLayers) { for (int iw = 0; iw < sNumberOfWrapperVolumes; iw++) { if (mLayerRadii[j] > mWrapperMinRadius[iw] && mLayerRadii[j] < mWrapperMaxRadius[iw]) { LOG(DEBUG) << "Will embed layer " << j << " in wrapper volume " << iw; @@ -938,6 +942,7 @@ void Detector::constructDetectorGeometry() break; } } + } mGeometry[j]->createLayer(dest); } diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx index 22d264a981b73..d9840e6ae6b7e 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx @@ -547,8 +547,9 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) // mechStaveVol = createStaveStructInnerB(); if (mechStaveVol) { ypos = (static_cast<TGeoBBox*>(modVol->GetShape()))->GetDY() - ypos; - if (mStaveModel != Detector::kIBModel4) + if (mStaveModel != Detector::kIBModel4) { ypos += (static_cast<TGeoBBox*>(mechStaveVol->GetShape()))->GetDY(); + } staveVol->AddNode(mechStaveVol, 1, new TGeoCombiTrans(0, -ypos, 0, new TGeoRotation("", 0, 0, 180))); } } else { @@ -566,9 +567,10 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) mechStaveVol = createSpaceFrameOuterB(); if (mechStaveVol) { - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon staveVol->AddNode(mechStaveVol, 1, new TGeoCombiTrans(0, -sOBSFrameULegHeight1, 0, new TGeoRotation("", 180, 0, 0))); + } } } } @@ -617,10 +619,11 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) char chipName[nameLen], sensName[nameLen], volumeName[nameLen]; // For material budget studies - if (mBuildLevel < 6) + if (mBuildLevel < 6) { dummyChip = kFALSE; // will be made of Si - else + } else { dummyChip = kTRUE; // will be made of Air + } // First create the single chip snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); @@ -651,8 +654,9 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) Double_t yano = (static_cast<TGeoBBox*>(aluAnodeCableVol->GetShape()))->GetDY(); ytot = ymod; - if (mStaveModel == Detector::kIBModel4) + if (mStaveModel == Detector::kIBModel4) { ytot += (sIBGlueThick / 2 + ygnd + sIBFlexCableKapThick / 2 + yano + sIBFlexCapacitorYHi / 2); + } TGeoBBox* module = new TGeoBBox(xtot, ytot, ztot); @@ -685,8 +689,9 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) if (mStaveModel == Detector::kIBModel4) { ypos += (ymod + glue->GetDY()); - if (mBuildLevel < 2) // Glue + if (mBuildLevel < 2) { // Glue modVol->AddNode(glueVol, 1, new TGeoTranslation(xpos, ypos, 0)); + } ypos += glue->GetDY(); if (mBuildLevel < 4) { // Kapton @@ -808,20 +813,22 @@ void V3Layer::createIBCapacitors(TGeoVolume* modvol, Double_t zchip, Double_t yz nCapacitors++; for (Int_t j = 0; j < sIBChipsPerRow; j++) { - if (j == (sIBChipsPerRow - 1)) + if (j == (sIBChipsPerRow - 1)) { xpos = xGroup4[1]; - else + } else { xpos = xGroup4[0]; + } zpos = -mIBModuleZLength / 2 + j * (2 * zchip + sIBChipZGap) + zchip + zGroup4[j]; modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); } nCapacitors += sIBChipsPerRow; for (Int_t j = 0; j < nGroup5A; j++) { - if (j == 0) + if (j == 0) { xpos = xGroup5A[0]; - else + } else { xpos = xGroup5A[1]; + } zpos = zGroup5A[j]; modvol->AddNode(capacitor, j + 1 + nCapacitors, new TGeoTranslation(-xpos, ypos, -zpos)); } @@ -869,8 +876,9 @@ TGeoVolume* V3Layer::createIBFPCAlGnd(const Double_t xcable, const Double_t zcab aluminumVol->SetFillColor(kCyan); ypos = coverlay->GetDY() - aluminum->GetDY(); - if (mBuildLevel < 1) // Aluminum + if (mBuildLevel < 1) { // Aluminum coverlayVol->AddNode(aluminumVol, 1, new TGeoTranslation(0, ypos, 0)); + } return coverlayVol; } @@ -920,8 +928,9 @@ TGeoVolume* V3Layer::createIBFPCAlAnode(const Double_t xcable, const Double_t zc aluminumVol->SetFillColor(kCyan); ypos = -coverlay->GetDY() + aluminum->GetZ(1); - if (mBuildLevel < 1) // Aluminum + if (mBuildLevel < 1) { // Aluminum coverlayVol->AddNode(aluminumVol, 1, new TGeoCombiTrans(0, ypos, 0, new TGeoRotation("", 0, -90, 0))); + } return coverlayVol; } @@ -1224,16 +1233,19 @@ TGeoVolume* V3Layer::createStaveModelInnerB4(const TGeoManager* mgr) // Now build up the half stave ypos = glue->GetDY(); - if (mBuildLevel < 2) // Glue + if (mBuildLevel < 2) { // Glue mechStavVol->AddNode(glueVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (glue->GetDY() + fleecbot->GetDY()); - if (mBuildLevel < 5) // Carbon + if (mBuildLevel < 5) { // Carbon mechStavVol->AddNode(fleecbotVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (fleecbot->GetDY() + cfplate->GetDY()); - if (mBuildLevel < 5) // Carbon + if (mBuildLevel < 5) { // Carbon mechStavVol->AddNode(cfplateVol, 1, new TGeoTranslation(0, ypos, 0)); + } ylay = ypos + cfplate->GetDY(); // The level where tubes etc. lay @@ -1906,10 +1918,11 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) zmod = (static_cast<TGeoBBox*>(moduleVol->GetShape()))->GetDZ(); if (mLayerNumber == mNumberOfInnerLayers || - mLayerNumber == mNumberOfInnerLayers + 1) + mLayerNumber == mNumberOfInnerLayers + 1) { zlen = sOBColdPlateZLenML / 2; // Middle Layer - else + } else { zlen = sOBColdPlateZLenOL / 2; // Outer Layer + } xlen = sOBColdPlateXWidth / 2; @@ -1944,8 +1957,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) new TGeoTubeSeg("FleecTube", rCoolMax + yGraph, rCoolMax + yCFleece + yGraph, zlen, 180., 360.); TGeoTube* gammaConvRod; - if (mAddGammaConv) + if (mAddGammaConv) { gammaConvRod = new TGeoTube("GammaConver", 0, 0.5 * mGammaConvDiam, zlen - sOBCPConnHollowZLen); + } // TGeoBBox* flex1_5cm = new TGeoBBox("Flex1MV_5cm", xHalfSt, yFlex1 / 2, flexOverlap / 2); // TGeoBBox* flex2_5cm = new TGeoBBox("Flex2MV_5cm", xHalfSt, yFlex2 / 2, flexOverlap / 2); @@ -1958,8 +1972,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) // The half stave container (an XTru to avoid overlaps between neightbours) xHalfSt = xmod; // add the cross cables when done! yHalfSt = ypowbus + ymod + coldPlate->GetDY() + 2 * fleeccent->GetDY() + graphlat->GetDY() + fleeclat->GetDY(); - if (mAddGammaConv) + if (mAddGammaConv) { yHalfSt += mGammaConvDiam; + } xtru[0] = xHalfSt; ytru[0] = 0; @@ -1969,8 +1984,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) ytru[2] = ytru[1]; xtru[3] = xtru[2]; ytru[3] = ytru[2] - (coolTube->GetRmax() + fleectub->GetRmax()); - if (mAddGammaConv) + if (mAddGammaConv) { ytru[3] -= mGammaConvDiam; + } xtru[4] = sOBCoolTubeXDist / 2 - fleectub->GetRmax(); ytru[4] = ytru[3]; xtru[5] = xtru[4]; @@ -1994,8 +2010,9 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) new TGeoBBox("connCsideOB", sOBCPConnectorXWidth / 2, sOBCPConnBlockYHei / 2, sOBCPConnBlockZLen / 2); // The StaveStruct container, a Composite Shape - if (mAddGammaConv) + if (mAddGammaConv) { yHalfSt -= mGammaConvDiam; + } ypos = 2 * yHalfSt + connAside->GetDY() - sOBCPConnHollowYHei; zpos = zlen + connAside->GetDZ() - sOBCPConnHollowZLen; snprintf(volname, nameLen, "transAsideOB%d", mLayerNumber); @@ -2119,18 +2136,21 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) ypos -= ymod; ypos -= fleeccent->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(fleeccentVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos -= fleeccent->GetDY(); ypos -= coldPlate->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(coldPlateVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos -= coldPlate->GetDY(); ypos -= fleeccent->GetDY(); - if (mBuildLevel < 6) // Carbon + if (mBuildLevel < 6) { // Carbon halfStaveVol->AddNode(fleeccentVol, 2, new TGeoTranslation(0, ypos, 0)); + } xpos = sOBCoolTubeXDist / 2; ypos1 = ypos - (fleeccent->GetDY() + coolTube->GetRmax()); @@ -2307,45 +2327,55 @@ TGeoVolume* V3Layer::createOBPowerBiasBuses(const Double_t zcable, const TGeoMan // Volumes are piled up from bottom to top ypos = -pnbBus->GetDY() + kapPB->GetDY(); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (kapPB->GetDY() + gndPB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(gndPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (gndPB->GetDY() + dielPB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(dielPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (dielPB->GetDY() + topPB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(topPBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (topPB->GetDY() + kapPB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapPBVol, 2, new TGeoTranslation(0, ypos, 0)); + } // ypos += (kapPB->GetDY() + kapBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (kapBB->GetDY() + botBB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(botBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (botBB->GetDY() + dielBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(dielBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (dielBB->GetDY() + topBB->GetDY()); - if (mBuildLevel < 2) // Aluminum + if (mBuildLevel < 2) { // Aluminum pnbBusVol->AddNode(topBBVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += (topBB->GetDY() + kapBB->GetDY()); - if (mBuildLevel < 5) // Kapton + if (mBuildLevel < 5) { // Kapton pnbBusVol->AddNode(kapBBVol, 2, new TGeoTranslation(0, ypos, 0)); + } // return pnbBusVol; @@ -3452,10 +3482,11 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) // First create all needed shapes // For material budget studies - if (mBuildLevel < 7) + if (mBuildLevel < 7) { dummyChip = kFALSE; // will be made of Si - else + } else { dummyChip = kTRUE; // will be made of Air + } // The chip (the same as for IB) snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); @@ -3525,8 +3556,9 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) // Now build up the module ypos = -module->GetDY() + glueCP->GetDY(); - if (mBuildLevel < 3) // Glue + if (mBuildLevel < 3) { // Glue modVol->AddNode(glueCPVol, 1, new TGeoTranslation(0, ypos, 0)); + } xpos = xchip + xGap / 2; ypos += (ychip + glueCP->GetDY()); @@ -3550,8 +3582,9 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) } ypos += (ychip + glueFPC->GetDY()); - if (mBuildLevel < 3) // Glue + if (mBuildLevel < 3) { // Glue modVol->AddNode(glueFPCVol, 1, new TGeoTranslation(0, ypos, 0)); + } ypos += glueFPC->GetDY(); if (mBuildLevel < 5) { // Kapton @@ -3608,8 +3641,9 @@ TGeoVolume* V3Layer::createOBFPCCuGnd(const Double_t zcable, const TGeoManager* copperVol->SetFillColor(kCyan); ypos = -soldmask->GetDY() + copper->GetDY(); - if (mBuildLevel < 1) // Copper + if (mBuildLevel < 1) { // Copper soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + } return soldmaskVol; } @@ -3653,8 +3687,9 @@ TGeoVolume* V3Layer::createOBFPCCuSig(const Double_t zcable, const TGeoManager* copperVol->SetFillColor(kCyan); ypos = soldmask->GetDY() - copper->GetDY(); - if (mBuildLevel < 1) // Copper + if (mBuildLevel < 1) { // Copper soldmaskVol->AddNode(copperVol, 1, new TGeoTranslation(0, ypos, 0)); + } return soldmaskVol; } diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx index f78117f351ff1..ae775db4f3b96 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx +++ b/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx @@ -81,8 +81,9 @@ TGeoVolume* V3Services::createIBEndWheelsSideA(const TGeoManager* mgr) TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideA"); endWheelsVol->SetVisibility(kTRUE); - for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) { ibEndWheelSideA(jLay, endWheelsVol, mgr); + } // Return the wheels return endWheelsVol; @@ -108,8 +109,9 @@ TGeoVolume* V3Services::createIBEndWheelsSideC(const TGeoManager* mgr) TGeoVolume* endWheelsVol = new TGeoVolumeAssembly("EndWheelsSideC"); endWheelsVol->SetVisibility(kTRUE); - for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberInnerLayers; jLay++) { ibEndWheelSideC(jLay, endWheelsVol, mgr); + } // Return the wheels return endWheelsVol; @@ -182,8 +184,9 @@ void V3Services::createMBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* m // Created: 24 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) { obEndWheelSideA(jLay, mother, mgr); + } } void V3Services::createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) @@ -202,8 +205,9 @@ void V3Services::createMBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* m // Created: 26 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberMiddlLayers; jLay++) { mbEndWheelSideC(jLay, mother, mgr); + } } void V3Services::createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* mgr) @@ -222,8 +226,9 @@ void V3Services::createOBEndWheelsSideA(TGeoVolume* mother, const TGeoManager* m // Created: 27 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) { obEndWheelSideA(jLay + sNumberMiddlLayers, mother, mgr); + } } void V3Services::createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* mgr) @@ -242,8 +247,9 @@ void V3Services::createOBEndWheelsSideC(TGeoVolume* mother, const TGeoManager* m // Created: 27 Sep 2019 Mario Sitta // - for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) + for (Int_t jLay = 0; jLay < sNumberOuterLayers; jLay++) { obEndWheelSideC(jLay, mother, mgr); + } } void V3Services::createOBConeSideA(TGeoVolume* mother, const TGeoManager* mgr) @@ -668,10 +674,11 @@ void V3Services::ibEndWheelSideC(const Int_t iLay, TGeoVolume* endWheel, const T endwcbshmata->RegisterYourself(); TGeoTranslation* endwcbshmatb = new TGeoTranslation(Form("endwcbshmat%dl%db", ihole, iLay), -xpos, -ypos, zpos); endwcbshmatb->RegisterYourself(); - if ((ihole > 1 && ihole < 5) || (ihole > 5 && ihole < 9)) // Small holes + if ((ihole > 1 && ihole < 5) || (ihole > 5 && ihole < 9)) { // Small holes strcpy(holename, endwcbasShol->GetName()); - else + } else { strcpy(holename, endwcbasBhol->GetName()); + } endWheelComposite += Form("-%s:endwcbshmat%dl%da-%s:endwcbshmat%dl%db", holename, ihole, iLay, holename, ihole, iLay); } @@ -1270,10 +1277,11 @@ TString V3Services::ibCreateHollowsCyssFlangeSideA(const Double_t zlen) cyssFlangeAHollows += Form("-roundhalf:roundtr%d-roundhalf:roundtr%d", j + 2, j + 5); phi = 360 - phi - 0.05; - if (j == 3) + if (j == 3) { dphi = 360 - sCyssFlangeAHollowPhi0 + 0.05; - else + } else { dphi = phi + (sCyssFlangeAHole1PhiStep - sCyssFlangeAHollowPhi1) + 0.1; + } TGeoTubeSeg* hollow1 = new TGeoTubeSeg(Form("hollow%d", j), rmin, rmax, 2 * zlen, phi, dphi); @@ -1611,10 +1619,11 @@ void V3Services::obEndWheelSideA(const Int_t iLay, TGeoVolume* mother, const TGe // Finally put everything in the mother volume // In blueprints the Z position is given wrt the shelf holes // First the ring - if (iLay < sNumberMiddlLayers) + if (iLay < sNumberMiddlLayers) { zpos = sMBWheelsZpos + sOBWheelShelfHoleZpos; - else + } else { zpos = sOBWheelsZpos + sOBWheelShelfHoleZpos; + } zpos -= outerRingSh->GetDz(); mother->AddNode(ringOuterVol, 1, new TGeoTranslation(0, 0, zpos)); @@ -1697,10 +1706,11 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe TGeoTube* innerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], sOBWheelSuppRmax[iLay], sOBWheelThickness / 2); // The outer ring with the flange - if (iLay == 0) + if (iLay == 0) { nsect = 6; - else + } else { nsect = 4; + } TGeoPcon* outerRingSh = new TGeoPcon(0, 360, nsect); @@ -1722,17 +1732,19 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe } // The lower ring - if (iLay == 0) + if (iLay == 0) { zlen = sOBWheelSuppZlen[iLay] - sOBWheelFlangeZlen - 2 * sOBWheelThickness; - else + } else { zlen = sOBWheelSuppZlen[iLay] - sOBWheelThickness - outerRingSh->GetZ(nsect - 1); + } rmax = sOBWheelSuppRmin[iLay] + sOBWheelThickness; TGeoTube* lowerRingSh = new TGeoTube(sOBWheelSuppRmin[iLay], rmax, zlen / 2); // The upper ring - if (iLay == 1) // For odd layers the upper and lower rings length is the same + if (iLay == 1) { // For odd layers the upper and lower rings length is the same zlen = sOBWheelSuppZlen[iLay] - 2 * sOBWheelThickness; + } rmin = sOBWheelSuppRmax[iLay] - sOBWheelThickness; TGeoTube* upperRingSh = new TGeoTube(rmin, sOBWheelSuppRmax[iLay], zlen / 2); @@ -1929,8 +1941,9 @@ void V3Services::obEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe mother->AddNode(ringLowerVol, 1, new TGeoTranslation(0, 0, -zpos)); - if (iLay == 1) + if (iLay == 1) { zpos -= (sOBWheelThickness + (static_cast<TGeoTube*>(upperRingSh))->GetDz()); + } mother->AddNode(ringUpperVol, 1, new TGeoTranslation(0, 0, -zpos)); } @@ -2165,10 +2178,11 @@ void V3Services::obConeTraysSideA(TGeoVolume* mother, const TGeoManager* mgr) // Finally put everything in the mother volume for (Int_t j = 0; j < 2; j++) { - if (j == 0) + if (j == 0) { zpos = sOBConesZpos - sOBTrayZpos[j] - sOBTrayZlen[j]; - else + } else { zpos = sOBConesZpos + sOBTrayZpos[j]; + } mother->AddNode(obTrayVol[j], 1, new TGeoTranslation(0, 0, zpos)); mother->AddNode(obTrayVol[j], 2, new TGeoCombiTrans(0, 0, zpos, new TGeoRotation("", 180, 0, 0))); From d34cf8561bf86127db97f8e236b8aa217abfd336 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 3 Nov 2020 17:45:25 +0100 Subject: [PATCH 1223/1751] Better cleanup in taskwrapper: Avoid leaving behind dev/shm segments This commit introduces 2 things: a) cleanup mechanism for leaked /dev/shm/fqm_ files (these can otherwise cloak the system and prevent new jobs to run) b) signal handling in the taskwrapper: - do some cleanup - actually exit on SIGINT etc.. --- Utilities/Tools/jobutils.sh | 58 ++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index 7bf9552e0338c..5ad3cdc40eafc 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -16,6 +16,35 @@ # simply sourced into the target script. +# returns list of files used in /dev/shm (this is done by DPL for shared memory communication) +# arguments is a list of pids +getShmFiles() { + F=`for p in "$@"; do + lsof -p ${p} 2>/dev/null | grep "/dev/shm/" | awk '//{print $9}' + done | sort | uniq | tr '\n' ' '` + echo "$F" +} + +o2_cleanup_shm_files() { + # find shared memory files **CURRENTLY IN USE** by FairMQ + USEDFILES=`lsof -u $(whoami) | grep "/dev/shm/fmq" | sed 's/.*\/dev/\/dev/g' | sort | uniq | tr '\n' ' '` + + echo "${USEDFILES}" + if [ ! "${USEDFILES}" ]; then + # in this case we can remove everything + COMMAND="find /dev/shm/ -name \"fmq_*\" -delete" + else + # build exclusion list + for f in ${USEDFILES}; do + LOGICALOP="" + [ "${EXCLPATTERN}" ] && LOGICALOP="-o" + EXCLPATTERN="${EXCLPATTERN} ${LOGICALOP} -wholename ${f}" + done + COMMAND="find /dev/shm/ -type f -not \( ${EXCLPATTERN} \) -delete" + fi + eval "${COMMAND}" +} + # Function to find out all the (recursive) child processes starting from a parent PID. # The output includes includes the parent # output is saved in child_pid_list @@ -33,6 +62,21 @@ childprocs() { fi } +taskwrapper_cleanup_handler() { + PID=$1 + SIGNAL=$2 + echo "CLEANUP HANDLER FOR PROCESS ${PID} AND SIGNAL ${SIGNAL}" + PROCS=$(childprocs ${PID}) + # make sure to bring down everything, including all kids + for p in ${PROCS}; do + echo "killing ${p}" + kill -s ${SIGNAL} ${p} 2> /dev/null + done + o2_cleanup_shm_files + # I prefer to exit the current job completely + exit 1 +} + # Function wrapping some process and asyncronously supervises and controls it. # Main features provided at the moment are: # - optional recording of walltime and memory consumption (time evolution) @@ -97,6 +141,9 @@ taskwrapper() { # THE NEXT PART IS THE SUPERVISION PART # get the PID PID=$! + # register signal handlers + trap "taskwrapper_cleanup_handler ${PID} SIGINT" SIGINT + trap "taskwrapper_cleanup_handler ${PID} SIGTERM" SIGTERM cpucounter=1 @@ -143,7 +190,9 @@ taskwrapper() { for p in $(childprocs ${PID}); do echo "killing child $p" kill $p 2> /dev/null - done + done + # remove leftover shm files + o2_cleanup_shm_files RC_ACUM=$((RC_ACUM+1)) [ ! "${JOBUTILS_KEEPJOBSCRIPT}" ] && rm ${SCRIPTNAME} 2> /dev/null @@ -185,6 +234,12 @@ taskwrapper() { echo "command ${command} had nonzero exit code ${RC}" fi [ ! "${JOBUTILS_KEEPJOBSCRIPT}" ] && rm ${SCRIPTNAME} 2> /dev/null + + # deregister signal handlers + trap '' SIGINT + trap '' SIGTERM + + o2_cleanup_shm_files #--> better to register a general trap at EXIT return ${RC} } @@ -200,3 +255,4 @@ getNumberOfPhysicalCPUCores() { N=`bc <<< "${CORESPERSOCKET}*${SOCKETS}"` echo "${N}" } + From b51403fee5595ee4a40d5c41a5deef5e97afbb2c Mon Sep 17 00:00:00 2001 From: mwinn2 <43405856+mwinn2@users.noreply.github.com> Date: Fri, 6 Nov 2020 15:54:49 +0100 Subject: [PATCH 1224/1751] MCH: Stepper update (#4775) * only positive charge for muon stations --- Detectors/MUON/MCH/Simulation/src/Stepper.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Detectors/MUON/MCH/Simulation/src/Stepper.cxx b/Detectors/MUON/MCH/Simulation/src/Stepper.cxx index 2f50f9da9c13d..67c50340f2ac9 100644 --- a/Detectors/MUON/MCH/Simulation/src/Stepper.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Stepper.cxx @@ -34,6 +34,12 @@ Stepper::~Stepper() void Stepper::process(const TVirtualMC& vmc) { + + if (!(vmc.TrackCharge())) { + // Only charged particles + return; + } + o2::SimTrackStatus t{vmc}; int detElemId; From f9e0a65655782d1d6536799fcee559fbf5485466 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 6 Nov 2020 14:07:18 +0100 Subject: [PATCH 1225/1751] TPC Workflow: Fix workflow in case creating only clusters but no tracks with caclusterer --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 14 ++++++++------ Detectors/TPC/workflow/src/RecoWorkflow.cxx | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index a43084001d8fe..37af779f2d2d4 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -576,12 +576,14 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config outputRegions.clustersNative.size = clusterOutput->get().size() - sizeof(ClusterCountIndex); } } - if (processAttributes->allocateOutputOnTheFly) { - outputRegions.tpcTracks.allocator = [&bufferTPCTracksChar, &pc](size_t size) -> void* {bufferTPCTracksChar = pc.outputs().make<char>(Output{gDataOriginTPC, "TRACKSGPU", 0}, size).data(); return bufferTPCTracksChar; }; - } else { - bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, processAttributes->outputBufferSize)); - outputRegions.tpcTracks.ptr = bufferTPCTracksChar = bufferTPCTracks->get().data(); - outputRegions.tpcTracks.size = bufferTPCTracks->get().size(); + if (specconfig.outputTracks) { + if (processAttributes->allocateOutputOnTheFly) { + outputRegions.tpcTracks.allocator = [&bufferTPCTracksChar, &pc](size_t size) -> void* {bufferTPCTracksChar = pc.outputs().make<char>(Output{gDataOriginTPC, "TRACKSGPU", 0}, size).data(); return bufferTPCTracksChar; }; + } else { + bufferTPCTracks.emplace(pc.outputs().make<std::vector<char>>(Output{gDataOriginTPC, "TRACKSGPU", 0}, processAttributes->outputBufferSize)); + outputRegions.tpcTracks.ptr = bufferTPCTracksChar = bufferTPCTracks->get().data(); + outputRegions.tpcTracks.size = bufferTPCTracks->get().size(); + } } if (specconfig.processMC) { outputRegions.clusterLabels.allocator = [&clustersMCBuffer](size_t size) -> void* { return &clustersMCBuffer; }; diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 195079d0149e3..8c850f3b8c03e 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -238,7 +238,7 @@ framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vecto // ClusterDecoderRawSpec bool produceCompClusters = isEnabled(OutputType::CompClusters); bool produceTracks = isEnabled(OutputType::Tracks); - bool runTracker = produceTracks || produceCompClusters; + bool runTracker = produceTracks || produceCompClusters || (isEnabled(OutputType::Clusters) && caClusterer); bool runHWDecoder = !caClusterer && (runTracker || isEnabled(OutputType::Clusters)); bool runClusterer = !caClusterer && (runHWDecoder || isEnabled(OutputType::ClustersHardware)); bool zsDecoder = inputType == InputType::ZSRaw; From 21cd337d3880af4d7f6fd84c9412709e4adb23cd Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 6 Nov 2020 20:32:16 +0100 Subject: [PATCH 1226/1751] DPL: keep running when in EOF (#4785) We need to keep running in end of stream to make sure we can flush the remaining messages. --- Framework/Core/src/DataProcessingDevice.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 4d75c4eb7383c..23479c1c539c7 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -445,7 +445,10 @@ bool DataProcessingDevice::ConditionalRun() if (mState.loop) { ZoneScopedN("uv idle"); TracyPlot("past activity", (int64_t)mWasActive); - uv_run(mState.loop, (mWasActive && (mDataProcessorContexes.at(0).state->streaming != StreamingState::Idle) && (mState.activeSignals.empty())) ? UV_RUN_NOWAIT : UV_RUN_ONCE); + auto shouldNotWait = (mWasActive && + (mDataProcessorContexes.at(0).state->streaming != StreamingState::Idle) && (mState.activeSignals.empty())) || + (mDataProcessorContexes.at(0).state->streaming == StreamingState::EndOfStreaming); + uv_run(mState.loop, shouldNotWait ? UV_RUN_NOWAIT : UV_RUN_ONCE); } // Notify on the main thread the new region callbacks, making sure From a8ae51b0687a7b2b63da1e6a511842626b80d8e7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 6 Nov 2020 17:11:06 +0100 Subject: [PATCH 1227/1751] GPU: Add an option to the TPC workflow to scale all buffer size estimations with a factor --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 1 + GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/Interface/GPUO2Interface.cxx | 1 + GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h | 3 ++- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 37af779f2d2d4..37d9a9622de7c 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -130,6 +130,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config processAttributes->suppressOutput = (confParam.dump == 2); config.configInterface.dumpEvents = confParam.dump; config.configInterface.dropSecondaryLegs = confParam.dropSecondaryLegs; + config.configInterface.memoryBufferScaleFactor = confParam.memoryBufferScaleFactor; if (confParam.display) { #ifdef GPUCA_BUILD_EVENT_DISPLAY processAttributes->displayBackend.reset(new GPUDisplayBackendGlfw); diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index e00b6e2c3f0f8..6014c6079fdc0 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -274,6 +274,7 @@ AddOption(synchronousProcessing, bool, false, "", 0, "Apply performance shortcut AddOption(mutexMemReg, bool, false, "", 0, "Global mutex to serialize GPU memory registration") AddOption(display, bool, false, "", 0, "Enable standalone gpu tracking visualizaion") AddOption(dropSecondaryLegs, bool, true, "", 0, "Do not store secondary legs of looping track in TrackTPC") +AddOption(memoryBufferScaleFactor, float, 1.f, "", 0, "Factor to scale buffer size estimations") EndConfig() #endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 6d040e667b6e7..4d5cdebeada84 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -75,6 +75,7 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) if (!mRec->IsGPU() && mConfig->configProcessing.memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) { mRec->MemoryScalers()->factor *= 2; } + mRec->MemoryScalers()->factor *= mConfig->configInterface.memoryBufferScaleFactor; mInitialized = true; return (0); } diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index a80682c26944b..5e14f54075c94 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -77,8 +77,9 @@ struct GPUO2InterfaceConfiguration { int dumpEvents = 0; bool outputToExternalBuffers = false; bool dropSecondaryLegs = true; + float memoryBufferScaleFactor = 1.f; // These constants affect GPU memory allocation only and do not limit the CPU processing - unsigned long maxTPCZS = 4096ul * 1024 * 1024; + unsigned long maxTPCZS = 8192ul * 1024 * 1024; unsigned int maxTPCHits = 1024 * 1024 * 1024; unsigned int maxTRDTracklets = 128 * 1024; unsigned int maxITSTracks = 96 * 1024; From 2825b1d89aef9e1cf7d1200dbd5f813de386e306 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 6 Nov 2020 20:33:11 +0100 Subject: [PATCH 1228/1751] DPL Analysis: do not write to disk TFN output. (#4782) This is really some internal data which should never be serialised. --- Framework/Core/src/CommonDataProcessors.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index f3f57edbc3b20..59b216abef4db 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -434,11 +434,13 @@ DataProcessorSpec std::vector<InputSpec> validBinaryInputs; auto onlyTimeframe = [](InputSpec const& input) { - return input.lifetime == Lifetime::Timeframe; + return (DataSpecUtils::partialMatch(input, o2::header::DataOrigin("TFN")) == false) && + input.lifetime == Lifetime::Timeframe; }; auto noTimeframe = [](InputSpec const& input) { - return input.lifetime != Lifetime::Timeframe; + return (DataSpecUtils::partialMatch(input, o2::header::DataOrigin("TFN")) == true) || + input.lifetime != Lifetime::Timeframe; }; std::copy_if(danglingOutputInputs.begin(), danglingOutputInputs.end(), From 1522c870ba2ef1d1eec46d54952dae13d6a64ad2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 6 Nov 2020 20:49:38 +0100 Subject: [PATCH 1229/1751] TPC: Remove crossing-CE flag if all clusters on one side are rejected --- .../TPC/reconstruction/src/GPUCATracking.cxx | 108 ++++++++++-------- 1 file changed, 59 insertions(+), 49 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 74a2c58900a9a..d6a2fcaf546c6 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -187,38 +187,6 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* for (int iTmp = 0; iTmp < nTracks; iTmp++) { auto& oTrack = (*outputTracks)[iTmp]; const int i = trackSort[iTmp].first; - float time0 = 0.f, tFwd = 0.f, tBwd = 0.f; - if (mTrackingCAO2Interface->GetParamContinuous()) { - time0 = tracks[i].GetParam().GetTZOffset(); - - if (tracks[i].CCE()) { - bool lastSide = trackClusters[tracks[i].FirstClusterRef()].slice < Sector::MAXSECTOR / 2; - float delta = 0.f; - for (int iCl = 1; iCl < tracks[i].NClusters(); iCl++) { - if (lastSide ^ (trackClusters[tracks[i].FirstClusterRef() + iCl].slice < Sector::MAXSECTOR / 2)) { - auto& cacl1 = trackClusters[tracks[i].FirstClusterRef() + iCl]; - auto& cacl2 = trackClusters[tracks[i].FirstClusterRef() + iCl - 1]; - auto& cl1 = data->clusters->clustersLinear[cacl1.num]; - auto& cl2 = data->clusters->clustersLinear[cacl2.num]; - delta = fabs(cl1.getTime() - cl2.getTime()) * 0.5f; - if (delta < MinDelta) { - delta = MinDelta; - } - break; - } - } - tFwd = tBwd = delta; - } else { - // estimate max/min time increments which still keep track in the physical limits of the TPC - auto& c1 = trackClusters[tracks[i].FirstClusterRef()]; - auto& c2 = trackClusters[tracks[i].FirstClusterRef() + tracks[i].NClusters() - 1]; - float t1 = data->clusters->clustersLinear[c1.num].getTime(); - float t2 = data->clusters->clustersLinear[c2.num].getTime(); - auto times = std::minmax(t1, t2); - tFwd = times.first - time0; - tBwd = time0 - (times.second - maxDriftTime); - } - } oTrack = TrackTPC(tracks[i].GetParam().GetX(), tracks[i].GetAlpha(), @@ -229,17 +197,6 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* tracks[i].GetParam().GetCov(6), tracks[i].GetParam().GetCov(7), tracks[i].GetParam().GetCov(8), tracks[i].GetParam().GetCov(9), tracks[i].GetParam().GetCov(10), tracks[i].GetParam().GetCov(11), tracks[i].GetParam().GetCov(12), tracks[i].GetParam().GetCov(13), tracks[i].GetParam().GetCov(14)}); - oTrack.setTime0(time0); - oTrack.setDeltaTBwd(tBwd); - oTrack.setDeltaTFwd(tFwd); - if (tracks[i].CCE()) { - oTrack.setHasCSideClusters(); - oTrack.setHasASideClusters(); - } else if (tracks[i].CSide()) { - oTrack.setHasCSideClusters(); - } else { - oTrack.setHasASideClusters(); - } oTrack.setChi2(tracks[i].GetParam().GetChi2()); auto& outerPar = tracks[i].OuterParam(); @@ -264,7 +221,9 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* uint8_t* rowIndexArr = sectorIndexArr + nOutCl; std::vector<std::pair<MCCompLabel, unsigned int>> labels; - nOutCl = 0; + int nOutCl2 = 0; + float t1, t2; + int sector1, sector2; for (int j = 0; j < tracks[i].NClusters(); j++) { if ((trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) || (ptrs.mergedTrackHitAttachment[trackClusters[tracks[i].FirstClusterRef() + j].num] & flagsRequired) != flagsRequired) { continue; @@ -277,10 +236,18 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* while (globalRow > mapper.getGlobalRowOffsetRegion(regionNumber) + mapper.getNumberOfRowsRegion(regionNumber)) { regionNumber++; } - clIndArr[nOutCl] = clusterIdInRow; - sectorIndexArr[nOutCl] = sector; - rowIndexArr[nOutCl] = globalRow; - nOutCl++; + clIndArr[nOutCl2] = clusterIdInRow; + sectorIndexArr[nOutCl2] = sector; + rowIndexArr[nOutCl2] = globalRow; + if (nOutCl2 == 0) { + t1 = data->clusters->clustersLinear[clusterIdGlobal].getTime(); + sector1 = sector; + } + nOutCl2++; + if (nOutCl2 == nOutCl) { + t2 = data->clusters->clustersLinear[clusterIdGlobal].getTime(); + sector2 = sector; + } if (outputTracksMCTruth && data->clusters->clustersMCTruth) { for (const auto& element : data->clusters->clustersMCTruth->getLabels(clusterIdGlobal)) { bool found = false; @@ -291,11 +258,54 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* break; } } - if (!found) + if (!found) { labels.emplace_back(element, 1); + } + } + } + } + + bool cce = tracks[i].CCE() && ((sector1 < Sector::MAXSECTOR / 2) ^ (sector2 < Sector::MAXSECTOR / 2)); + float time0 = 0.f, tFwd = 0.f, tBwd = 0.f; + if (mTrackingCAO2Interface->GetParamContinuous()) { + time0 = tracks[i].GetParam().GetTZOffset(); + + if (cce) { + bool lastSide = trackClusters[tracks[i].FirstClusterRef()].slice < Sector::MAXSECTOR / 2; + float delta = 0.f; + for (int iCl = 1; iCl < tracks[i].NClusters(); iCl++) { + if (lastSide ^ (trackClusters[tracks[i].FirstClusterRef() + iCl].slice < Sector::MAXSECTOR / 2)) { + auto& cacl1 = trackClusters[tracks[i].FirstClusterRef() + iCl]; + auto& cacl2 = trackClusters[tracks[i].FirstClusterRef() + iCl - 1]; + auto& cl1 = data->clusters->clustersLinear[cacl1.num]; + auto& cl2 = data->clusters->clustersLinear[cacl2.num]; + delta = fabs(cl1.getTime() - cl2.getTime()) * 0.5f; + if (delta < MinDelta) { + delta = MinDelta; + } + break; + } } + tFwd = tBwd = delta; + } else { + // estimate max/min time increments which still keep track in the physical limits of the TPC + auto times = std::minmax(t1, t2); + tFwd = times.first - time0; + tBwd = time0 - (times.second - maxDriftTime); } } + oTrack.setTime0(time0); + oTrack.setDeltaTBwd(tBwd); + oTrack.setDeltaTFwd(tFwd); + if (cce) { + oTrack.setHasCSideClusters(); + oTrack.setHasASideClusters(); + } else if (tracks[i].CSide()) { + oTrack.setHasCSideClusters(); + } else { + oTrack.setHasASideClusters(); + } + if (outputTracksMCTruth) { if (labels.size() == 0) { outputTracksMCTruth->emplace_back(); //default constructor creates NotSet label From 4e36bd6b4472cda9fb951c2189d7eff15e8ffd70 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Sat, 7 Nov 2020 08:19:02 +0100 Subject: [PATCH 1230/1751] A few changes and optimizations (#4765) --- Analysis/Core/include/Analysis/VarManager.h | 52 ++++++++------ Analysis/Tasks/PWGDQ/tableMaker.cxx | 75 +++++++++++---------- Analysis/Tasks/PWGDQ/tableReader.cxx | 13 +++- 3 files changed, 81 insertions(+), 59 deletions(-) diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 79e9c23448998..568064a5e5d29 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -36,6 +36,7 @@ static const float fgkMuonMass = 0.105; // GeV class VarManager : public TObject { public: + // map the information contained in the objects passed to the Fill functions enum ObjTypes { BC = BIT(0), Collision = BIT(1), @@ -47,13 +48,15 @@ class VarManager : public TObject TrackCov = BIT(1), TrackExtra = BIT(2), TrackPID = BIT(3), + TrackDCA = BIT(4), + TrackSelection = BIT(5), // TODO: Central model MUON variables to be added - ReducedTrack = BIT(4), - ReducedTrackBarrel = BIT(5), - ReducedTrackBarrelCov = BIT(6), - ReducedTrackBarrelPID = BIT(7), - ReducedTrackMuon = BIT(8), - Pair = BIT(9) + ReducedTrack = BIT(6), + ReducedTrackBarrel = BIT(7), + ReducedTrackBarrelCov = BIT(8), + ReducedTrackBarrelPID = BIT(9), + ReducedTrackMuon = BIT(10), + Pair = BIT(11) }; public: @@ -103,6 +106,8 @@ class VarManager : public TObject // Barrel track variables kPin, + kIsGlobalTrack, + kIsGlobalTrackSDD, kIsITSrefit, kIsSPDany, kIsSPDfirst, @@ -298,22 +303,22 @@ void VarManager::FillEvent(T const& event, float* values) values[kBC] = event.globalBC(); values[kCentVZERO] = event.centV0M(); if (fgUsedVars[kIsINT7]) { - values[kIsINT7] = event.triggerAlias() & (uint32_t(1) << kINT7); + values[kIsINT7] = (event.triggerAlias() & (uint32_t(1) << kINT7)) > 0; } if (fgUsedVars[kIsEMC7]) { - values[kIsEMC7] = event.triggerAlias() & (uint32_t(1) << kEMC7); + values[kIsEMC7] = (event.triggerAlias() & (uint32_t(1) << kEMC7)) > 0; } if (fgUsedVars[kIsINT7inMUON]) { - values[kIsINT7inMUON] = event.triggerAlias() & (uint32_t(1) << kINT7inMUON); + values[kIsINT7inMUON] = (event.triggerAlias() & (uint32_t(1) << kINT7inMUON)) > 0; } if (fgUsedVars[kIsMuonSingleLowPt7]) { - values[kIsMuonSingleLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonSingleLowPt7); + values[kIsMuonSingleLowPt7] = (event.triggerAlias() & (uint32_t(1) << kMuonSingleLowPt7)) > 0; } if (fgUsedVars[kIsMuonUnlikeLowPt7]) { - values[kIsMuonUnlikeLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonUnlikeLowPt7); + values[kIsMuonUnlikeLowPt7] = (event.triggerAlias() & (uint32_t(1) << kMuonUnlikeLowPt7)) > 0; } if (fgUsedVars[kIsMuonLikeLowPt7]) { - values[kIsMuonLikeLowPt7] = event.triggerAlias() & (uint32_t(1) << kMuonLikeLowPt7); + values[kIsMuonLikeLowPt7] = (event.triggerAlias() & (uint32_t(1) << kMuonLikeLowPt7)) > 0; } } @@ -356,19 +361,19 @@ void VarManager::FillTrack(T const& track, float* values) if constexpr ((fillMap & TrackExtra) > 0 || (fillMap & ReducedTrackBarrel) > 0) { values[kPin] = track.tpcInnerParam(); if (fgUsedVars[kIsITSrefit]) { - values[kIsITSrefit] = track.flags() & (uint64_t(1) << 2); // TODO: the flag mapping needs to be updated + values[kIsITSrefit] = (track.flags() & (uint32_t(1) << 0)) > 0; } if (fgUsedVars[kIsTPCrefit]) { - values[kIsTPCrefit] = track.flags() & (uint64_t(1) << 6); // TODO: the flag mapping needs to be updated + values[kIsTPCrefit] = (track.flags() & (uint32_t(1) << 1)) > 0; } if (fgUsedVars[kIsSPDfirst]) { - values[kIsSPDfirst] = track.itsClusterMap() & uint8_t(1); + values[kIsSPDfirst] = (track.itsClusterMap() & uint8_t(1)) > 0; } if (fgUsedVars[kIsSPDboth]) { - values[kIsSPDboth] = track.itsClusterMap() & uint8_t(3); + values[kIsSPDboth] = (track.itsClusterMap() & uint8_t(3)) > 0; } if (fgUsedVars[kIsSPDany]) { - values[kIsSPDfirst] = (track.itsClusterMap() & uint8_t(1)) || (track.itsClusterMap() & uint8_t(2)); + values[kIsSPDany] = (track.itsClusterMap() & uint8_t(1)) || (track.itsClusterMap() & uint8_t(2)); } values[kITSchi2] = track.itsChi2NCl(); values[kTPCncls] = track.tpcNClsFound(); @@ -379,9 +384,6 @@ void VarManager::FillTrack(T const& track, float* values) if (fgUsedVars[kITSncls]) { values[kITSncls] = track.itsNCls(); // dynamic column } - // TODO: DCA calculation for central data model tracks to be added here - values[kTrackDCAxy] = -9999.; - values[kTrackDCAz] = -9999.; } if constexpr ((fillMap & ReducedTrackBarrel) > 0) { if (fgUsedVars[kITSncls]) { @@ -395,6 +397,16 @@ void VarManager::FillTrack(T const& track, float* values) } } + if constexpr ((fillMap & TrackDCA) > 0) { + values[kTrackDCAxy] = track.dcaXY(); + values[kTrackDCAz] = track.dcaZ(); + } + + if constexpr ((fillMap & TrackSelection) > 0) { + values[kIsGlobalTrack] = track.isGlobalTrack(); + values[kIsGlobalTrackSDD] = track.isGlobalTrackSDD(); + } + if constexpr ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0) { values[kTrackCYY] = track.cYY(); values[kTrackCZZ] = track.cZZ(); diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index d47dd428f249b..d65a471e422fb 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -24,6 +24,7 @@ #include "Analysis/AnalysisCut.h" #include "Analysis/AnalysisCompositeCut.h" #include "PID/PIDResponse.h" +#include "Analysis/TrackSelectionTables.h" #include <iostream> using std::cout; @@ -35,7 +36,7 @@ using namespace o2::framework; using namespace o2::aod; using MyEvents = soa::Join<aod::Collisions, aod::EvSels, aod::Cents>; -using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta>; +using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::TracksExtended, aod::TrackSelection, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta>; // 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 @@ -45,7 +46,7 @@ using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, // 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 gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent; -constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; +constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; struct TableMaker { @@ -71,6 +72,14 @@ struct TableMaker { // Cuts should be defined using Configurables (prepare cut libraries, as discussed in O2 DQ meetings) AnalysisCompositeCut* fTrackCut; + // Partition will select fast a group of tracks with basic requirements + // If some of the cuts cannot be included in the Partition expression, add them via AnalysisCut(s) + Partition<MyBarrelTracks> barrelSelectedTracks = o2::aod::track::pt >= 1.0f && nabs(o2::aod::track::eta) <= 0.9f && o2::aod::track::tpcSignal >= 70.0f && o2::aod::track::tpcSignal <= 100.0f && o2::aod::track::tpcChi2NCl < 4.0f && o2::aod::track::itsChi2NCl < 36.0f; + + // TODO a few of the important muon variables in the central data model are dynamic columns so not usable in expressions (e.g. eta, phi) + // Update the data model to have them as expression columns + Partition<aod::Muons> muonSelectedTracks = o2::aod::muon::pt >= 1.0f; + void init(o2::framework::InitContext&) { fValues = new float[VarManager::kNVars]; @@ -95,13 +104,13 @@ struct TableMaker { fTrackCut = new AnalysisCompositeCut(true); AnalysisCut* trackVarCut = new AnalysisCut(); - trackVarCut->AddCut(VarManager::kPt, 1.0, 1000.0); - trackVarCut->AddCut(VarManager::kEta, -0.9, 0.9); - trackVarCut->AddCut(VarManager::kTPCsignal, 70.0, 100.0); - //trackVarCut->AddCut(VarManager::kIsITSrefit, 0.5, 1.5); - //trackVarCut->AddCut(VarManager::kIsTPCrefit, 0.5, 1.5); - trackVarCut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); - trackVarCut->AddCut(VarManager::kITSchi2, 0.1, 36.0); + //trackVarCut->AddCut(VarManager::kPt, 1.0, 1000.0); + //trackVarCut->AddCut(VarManager::kEta, -0.9, 0.9); + //trackVarCut->AddCut(VarManager::kTPCsignal, 70.0, 100.0); + trackVarCut->AddCut(VarManager::kIsITSrefit, 0.5, 1.5); + trackVarCut->AddCut(VarManager::kIsTPCrefit, 0.5, 1.5); + //trackVarCut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + //trackVarCut->AddCut(VarManager::kITSchi2, 0.1, 36.0); trackVarCut->AddCut(VarManager::kTPCncls, 100.0, 161.); AnalysisCut* pidCut1 = new AnalysisCut(); @@ -140,14 +149,12 @@ struct TableMaker { eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); uint64_t trackFilteringTag = 0; - float sinAlpha = 0.f; - float cosAlpha = 0.f; - float globalX = 0.f; - float globalY = 0.f; - float dcaXY = 0.f; - float dcaZ = 0.f; - for (auto& track : tracksBarrel) { + trackBasic.reserve(barrelSelectedTracks.size()); + trackBarrel.reserve(barrelSelectedTracks.size()); + trackBarrelCov.reserve(barrelSelectedTracks.size()); + trackBarrelPID.reserve(barrelSelectedTracks.size()); + for (auto& track : barrelSelectedTracks) { VarManager::FillTrack<gkTrackFillMap>(track, fValues); fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); if (!fTrackCut->IsSelected(fValues)) { @@ -155,27 +162,20 @@ struct TableMaker { } fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); - // TODO: update the DCA calculation (use the values computed in the trackSelection workflow or use the propagateToDCA function from there) - // TODO: Move the DCA calculation in the VarManager, so the DCA is available for cuts and histograms - sinAlpha = sin(track.alpha()); - cosAlpha = cos(track.alpha()); - globalX = track.x() * cosAlpha - track.y() * sinAlpha; - globalY = track.x() * sinAlpha + track.y() * cosAlpha; - - dcaXY = sqrt(pow((globalX - collision.posX()), 2) + - pow((globalY - collision.posY()), 2)); - dcaZ = sqrt(pow(track.z() - collision.posZ(), 2)); - + if (track.isGlobalTrack()) { + trackFilteringTag |= (uint64_t(1) << 0); + } + if (track.isGlobalTrackSDD()) { + trackFilteringTag |= (uint64_t(1) << 1); + } trackBasic(event.lastIndex(), track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.trdChi2(), track.tofChi2(), - track.length(), dcaXY, dcaZ); + track.length(), track.dcaXY(), track.dcaZ()); trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); trackBarrelPID(track.tpcSignal(), - /*0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);*/ track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), @@ -186,12 +186,14 @@ struct TableMaker { track.trdSignal()); } - for (auto& muon : tracksMuon) { + muonBasic.reserve(muonSelectedTracks.size()); + muonExtended.reserve(muonSelectedTracks.size()); + for (auto& muon : muonSelectedTracks) { // TODO: add proper information for muon tracks - if (muon.bc() != collision.bc()) { + if (muon.bcId() != collision.bcId()) { continue; } - // TODO: the trackFilteringFlag will not be needed to encode whether the track is a muon since there is a dedicated table for muons + // TODO: the trackFilteringTag will not be needed to encode whether the track is a muon since there is a dedicated table for muons trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track muonBasic(event.lastIndex(), trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); @@ -233,9 +235,10 @@ struct TableMaker { 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(), "DCAxy", "DCAxy", false, 100, -3.0, 3.0, VarManager::kTrackDCAxy); // TH1F histogram - //fHistMan->AddHistogram(classStr.Data(), "DCAz", "DCAz", false, 100, -5.0, 5.0, VarManager::kTrackDCAz); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "DCAxy", "DCAxy", false, 100, -3.0, 3.0, VarManager::kTrackDCAxy); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "DCAz", "DCAz", false, 100, -5.0, 5.0, VarManager::kTrackDCAz); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "IsGlobalTrack", "IsGlobalTrack", false, 2, -0.5, 1.5, VarManager::kIsGlobalTrack); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "IsGlobalTrackSDD", "IsGlobalTrackSDD", false, 2, -0.5, 1.5, VarManager::kIsGlobalTrackSDD); // TH1F histogram } } } // end loop over histogram classes diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index b4fc30978d128..acd92db6fdea5 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -228,6 +228,8 @@ struct BarrelTrackSelection { uint8_t filterMap = uint8_t(0); + trackSel.reserve(tracks.size()); + for (auto& track : tracks) { filterMap = uint8_t(0); VarManager::FillTrack<gkTrackFillMap>(track, fValues); @@ -500,8 +502,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) adaptAnalysisTask<EventSelection>("my-event-selection"), adaptAnalysisTask<BarrelTrackSelection>("barrel-track-selection"), adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), - adaptAnalysisTask<TableReader>("table-reader") - //adaptAnalysisTask<DileptonHadronAnalysis>("dilepton-hadron") + adaptAnalysisTask<TableReader>("table-reader"), + adaptAnalysisTask<DileptonHadronAnalysis>("dilepton-hadron") + }; } @@ -556,9 +559,13 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) histMan->AddHistogram(classStr.Data(), "TPCncls_Run", "Number of cluster in TPC", true, kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, 10, -0.5, 159.5, VarManager::kTPCncls, 10, 0., 1., VarManager::kNothing, runsStr.Data()); // TH1F histogram histMan->AddHistogram(classStr.Data(), "ITSncls", "Number of cluster in ITS", false, 8, -0.5, 7.5, VarManager::kITSncls); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "ITSchi2", "ITS chi2", false, 100, 0.0, 50.0, VarManager::kITSchi2); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "IsITSrefit", "", false, 2, -0.5, 1.5, VarManager::kIsITSrefit); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "IsTPCrefit", "", false, 2, -0.5, 1.5, VarManager::kIsTPCrefit); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "IsSPDany", "", false, 2, -0.5, 1.5, VarManager::kIsSPDany); // 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(), "TPCchi2", "TPC chi2", false, 100, 0.0, 10.0, VarManager::kTPCchi2); // TH1F histogram histMan->AddHistogram(classStr.Data(), "DCAxy", "DCAxy", false, 100, -3.0, 3.0, VarManager::kTrackDCAxy); // TH1F histogram histMan->AddHistogram(classStr.Data(), "DCAz", "DCAz", false, 100, -5.0, 5.0, VarManager::kTrackDCAz); // TH1F histogram } From e85855f1767366537130f98fe36fac1f5a547683 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Sat, 7 Nov 2020 18:56:49 +0100 Subject: [PATCH 1231/1751] Update jobutils.sh Be specific about lsof location. (job inside slurm does not find it). --- Utilities/Tools/jobutils.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index 5ad3cdc40eafc..38bc130bdd09e 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -27,7 +27,7 @@ getShmFiles() { o2_cleanup_shm_files() { # find shared memory files **CURRENTLY IN USE** by FairMQ - USEDFILES=`lsof -u $(whoami) | grep "/dev/shm/fmq" | sed 's/.*\/dev/\/dev/g' | sort | uniq | tr '\n' ' '` + USEDFILES=`/usr/sbin/lsof -u $(whoami) | grep "/dev/shm/fmq" | sed 's/.*\/dev/\/dev/g' | sort | uniq | tr '\n' ' '` echo "${USEDFILES}" if [ ! "${USEDFILES}" ]; then From 4da794427277e0a9c805c1a564d1144f2350f212 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 30 Oct 2020 19:16:24 +0100 Subject: [PATCH 1232/1751] GPU: First naive implementation to use chi2 criterion for adjacent clusters instaed of fixed tube size --- GPU/GPUTracking/Base/GPUSettingsList.h | 2 ++ GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 12 +++++++++--- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 6014c6079fdc0..027b6090bba2d 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -43,6 +43,8 @@ AddOption(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required AddOption(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") AddOption(TrackReferenceX, float, 1000.f, "", 0, "Transport all tracks to this X after tracking (disabled if > 500, auto = 1000)") AddOption(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") +AddOption(tpcTubeChi2, float, 5.f * 5.f, "", 0, "Max chi2 to mark cluster adjacent to track") +AddOption(tpcTubeMaxSize2, float, 2.5f * 2.5f, "", 0, "Square of max tube size (normally derrived from tpcTubeChi2)") AddOption(tpcCFqmaxCutoff, unsigned char, 3, "", 0, "Cluster Finder rejects cluster with qmax below this threshold") AddOption(tpcCFqtotCutoff, unsigned char, 0, "", 0, "Cluster Finder rejects cluster with qtot below this threshold") AddOption(tpcCFinnerThreshold, unsigned char, 0, "", 0, "Cluster Finder extends cluster if inner charge above this threshold") diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 87efc2346b9b9..a246ed5bf2d6c 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -32,6 +32,7 @@ #include "TPCFastTransform.h" #include "GPUTPCConvertImpl.h" #include "GPUTPCGMMergerTypes.h" +#include "GPUParam.inc" #ifdef GPUCA_ALIROOT_LIB #include "AliExternalTrackParam.h" @@ -494,7 +495,13 @@ GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict const float z0 = row.Grid().ZMin() - zOffset; // We can use our own ZOffset, since this is only used temporarily anyway const float stepZ = row.HstepZ(); int bin, ny, nz; - const float tube = 2.5f; + + float err2Y, err2Z; + Merger->Param().GetClusterErrors2(iRow, Z, mP[2], mP[3], err2Y, err2Z); + const float sy2 = CAMath::Min(Merger->Param().rec.tpcTubeMaxSize2, Merger->Param().rec.tpcTubeChi2 * (err2Y + mC[0])); + const float sz2 = CAMath::Min(Merger->Param().rec.tpcTubeMaxSize2, Merger->Param().rec.tpcTubeChi2 * (err2Z + mC[2])); + const float tubeY = CAMath::Sqrt(sy2); + const float tubeZ = CAMath::Sqrt(sz2); float nY, nZ; if (Merger->Param().earlyTpcTransform) { nY = Y; @@ -502,8 +509,7 @@ GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict } else { Merger->GetConstantMem()->calibObjects.fastTransform->InverseTransformYZtoNominalYZ(slice, iRow, Y, Z, nY, nZ); } - row.Grid().GetBinArea(nY, nZ + zOffset, tube, tube, bin, ny, nz); - float sy2 = tube * tube, sz2 = tube * tube; + row.Grid().GetBinArea(nY, nZ + zOffset, tubeY, tubeZ, bin, ny, nz); const int nBinsY = row.Grid().Ny(); const int idOffset = tracker.Data().ClusterIdOffset(); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index fba5d3f2bbb50..3d0174c1fe7c5 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -1253,7 +1253,7 @@ void GPUQA::RunQA(bool matchOnly) } timer.ResetStart(); } else if (!mConfig.inputHistogramsOnly) { - GPUWarning("No MC information available, cannot run QA!"); + GPUWarning("No MC information available, only running partial TPC QA!"); } // Fill other histograms From 17b00275511b37830961c00b5d066cc4549fa28e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 1 Nov 2020 22:26:21 +0100 Subject: [PATCH 1233/1751] GPU: Use SinCos instead of Sin and Cos --- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 4 ++-- GPU/GPUTracking/Merger/GPUTPCGMPropagator.h | 11 +++++++---- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 8 ++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index 24d29626b36b4..64ed311224d31 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -117,8 +117,8 @@ GPUd() int GPUTPCGMPropagator::RotateToAlpha(float newAlpha) // return value is error code (0==no error) // - float newCosAlpha = CAMath::Cos(newAlpha); - float newSinAlpha = CAMath::Sin(newAlpha); + float newCosAlpha, newSinAlpha; + CAMath::SinCos(newAlpha, newSinAlpha, newCosAlpha); float cc = newCosAlpha * mCosAlpha + newSinAlpha * mSinAlpha; // cos(newAlpha - mAlpha); float ss = newSinAlpha * mCosAlpha - newCosAlpha * mSinAlpha; //sin(newAlpha - mAlpha); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h index 97774efeaaf8b..5e42cc1be2993 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.h @@ -187,12 +187,16 @@ class GPUTPCGMPropagator GPUdi() void GPUTPCGMPropagator::GetBxByBz(float Alpha, float X, float Y, float Z, float B[3]) const { - GetBxByBzBase(CAMath::Cos(Alpha), CAMath::Sin(Alpha), X, Y, Z, B); + float c, s; + CAMath::SinCos(Alpha, s, c); + GetBxByBzBase(c, s, X, Y, Z, B); } GPUdi() float GPUTPCGMPropagator::GetBz(float Alpha, float X, float Y, float Z) const { - return GetBzBase(CAMath::Cos(Alpha), CAMath::Sin(Alpha), X, Y, Z); + float c, s; + CAMath::SinCos(Alpha, s, c); + return GetBzBase(c, s, X, Y, Z); } GPUdi() void GPUTPCGMPropagator::GetBxByBz(float X, float Y, float Z, float B[3]) const @@ -221,8 +225,7 @@ GPUdi() void GPUTPCGMPropagator::SetTrack(GPUTPCGMTrackParam* GPUrestrict() trac } mT0.Set(*mT); mAlpha = Alpha; - mCosAlpha = CAMath::Cos(mAlpha); - mSinAlpha = CAMath::Sin(mAlpha); + CAMath::SinCos(mAlpha, mSinAlpha, mCosAlpha); CalculateMaterialCorrection(); } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index a246ed5bf2d6c..4430d15a6d7d8 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -1023,8 +1023,8 @@ GPUd() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() tr const ClusterNative& GPUrestrict() cl = merger->GetConstantMem()->ioPtrs.clustersNative->clustersLinear[merger->Clusters()[ind].num]; merger->GetConstantMem()->calibObjects.fastTransform->Transform(merger->Clusters()[ind].slice, merger->Clusters()[ind].row, cl.getPad(), cl.getTime(), xx, yy, zz, track.Param().GetTZOffset()); } - float sinA = CAMath::Sin(alphaa - track.Alpha()); - float cosA = CAMath::Cos(alphaa - track.Alpha()); + float sinA, cosA; + CAMath::SinCos(alphaa - track.Alpha(), sinA, cosA); track.SetLastX(xx * cosA - yy * sinA); track.SetLastY(xx * sinA + yy * cosA); track.SetLastZ(zz); @@ -1033,8 +1033,8 @@ GPUd() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() tr GPUd() bool GPUTPCGMTrackParam::Rotate(float alpha) { - float cA = CAMath::Cos(alpha); - float sA = CAMath::Sin(alpha); + float cA, sA; + CAMath::SinCos(alpha, sA, cA); float x0 = mX; float sinPhi0 = mP[2], cosPhi0 = CAMath::Sqrt(1 - mP[2] * mP[2]); float cosPhi = cosPhi0 * cA + sinPhi0 * sA; From c0811e7c021e93f6237061ecf273df8735b9526b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 1 Nov 2020 14:58:48 +0100 Subject: [PATCH 1234/1751] GPU: Implement first version of afterburner for looper merging --- GPU/Common/GPUCommonMath.h | 12 ++ GPU/Common/GPUDefGPUParameters.h | 3 + GPU/GPUTracking/Base/GPUParam.inc | 6 +- .../Base/GPUReconstructionKernels.h | 1 + GPU/GPUTracking/Base/GPUSettingsList.h | 1 + .../GPUTPCCompressionKernels.cxx | 5 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 3 + GPU/GPUTracking/Merger/GPUTPCGMMergedTrack.h | 9 ++ GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 113 +++++++++++++++--- GPU/GPUTracking/Merger/GPUTPCGMMerger.h | 8 +- GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx | 6 + GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h | 9 ++ GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 2 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 12 +- GPU/GPUTracking/Standalone/qa/GPUQA.h | 2 +- 15 files changed, 165 insertions(+), 27 deletions(-) diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 40d7ac94f2310..8ca0cb0338ed4 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -147,6 +147,18 @@ class GPUCommonMath template <int I, class T> GPUd() CONSTEXPR17 static T nextMultipleOf(T val); +#ifdef GPUCA_NOCOMPAT + template <typename... Args> + GPUdi() static float Sum2(float w, Args... args) + { + if constexpr (sizeof...(Args) == 0) { + return w * w; + } else { + return w * w + Sum2(args...); + } + } +#endif + private: template <class S, class T> GPUd() static unsigned int AtomicExchInt(S* addr, T val); diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index a3f3277ed33c1..380e903b4e9cd 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -269,6 +269,9 @@ #ifndef GPUCA_LB_GPUTPCGMMergerFinalize_step2 #define GPUCA_LB_GPUTPCGMMergerFinalize_step2 256 #endif + #ifndef GPUCA_LB_GPUTPCGMMergerMergeLoopers + #define GPUCA_LB_GPUTPCGMMergerMergeLoopers 256 + #endif #ifndef GPUCA_LB_GPUITSFitterKernel #define GPUCA_LB_GPUITSFitterKernel 256 #endif diff --git a/GPU/GPUTracking/Base/GPUParam.inc b/GPU/GPUTracking/Base/GPUParam.inc index 4c04619184e17..d269adea60bb0 100644 --- a/GPU/GPUTracking/Base/GPUParam.inc +++ b/GPU/GPUTracking/Base/GPUParam.inc @@ -25,7 +25,7 @@ namespace gpu MEM_CLASS_PRE() GPUdi() void MEM_LG(GPUParam)::Slice2Global(int iSlice, float x, float y, float z, float* X, float* Y, float* Z) const { - // conversion of coorinates sector->global + // conversion of coordinates sector->global *X = x * SliceParam[iSlice].CosAlpha - y * SliceParam[iSlice].SinAlpha; *Y = y * SliceParam[iSlice].CosAlpha + x * SliceParam[iSlice].SinAlpha; *Z = z; @@ -34,7 +34,7 @@ GPUdi() void MEM_LG(GPUParam)::Slice2Global(int iSlice, float x, float y, float MEM_CLASS_PRE() GPUdi() void MEM_LG(GPUParam)::Global2Slice(int iSlice, float X, float Y, float Z, float* x, float* y, float* z) const { - // conversion of coorinates global->sector + // conversion of coordinates global->sector *x = X * SliceParam[iSlice].CosAlpha + Y * SliceParam[iSlice].SinAlpha; *y = Y * SliceParam[iSlice].CosAlpha - X * SliceParam[iSlice].SinAlpha; *z = Z; @@ -43,7 +43,7 @@ GPUdi() void MEM_LG(GPUParam)::Global2Slice(int iSlice, float X, float Y, float MEM_CLASS_PRE() GPUdi() float MEM_LG(GPUParam)::GetClusterRMS(int yz, int type, float z, float angle2) const { - //* recalculate the cluster error wih respect to the track slope + //* recalculate the cluster RMS wih respect to the track slope MakeType(const float*) c = ParamRMS0[yz][type]; float v = c[0] + c[1] * z + c[2] * angle2; diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index aa3e11400159b..cad31625cf1bb 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -57,6 +57,7 @@ GPUCA_KRNL_LB((GPUTPCGMMergerPrepareClusters, step2 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCGMMergerFinalize, step0 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCGMMergerFinalize, step1 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCGMMergerFinalize, step2 ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCGMMergerMergeLoopers ), (simple), (), ()) #ifdef HAVE_O2HEADERS GPUCA_KRNL_LB((GPUTRDTrackerKernels ), (simple), (), ()) GPUCA_KRNL_LB((GPUITSFitterKernel ), (simple), (), ()) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 027b6090bba2d..bb46fb652c380 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -59,6 +59,7 @@ AddOption(dEdxTruncHigh, unsigned char, 77, "", 0, "High truncation threshold, f AddOption(GlobalTracking, char, 1, "", 0, "Enable Global Tracking (prolong tracks to adjacent sectors to find short segments)") AddOption(DisableRefitAttachment, unsigned char, 0, "", 0, "Bitmask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") AddOption(tpcRejectionMode, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression (0 = no, 1 = strategy A, 2 = strategy B)") +AddOption(tpcMergeLoopersAfterburner, unsigned char, 0, "", 0, "Run afterburner for additional looper merging") AddOption(tpcCompressionModes, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOption(tpcCompressionSortOrder, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") AddOption(tpcSigBitsCharge, unsigned char, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 0d10bd5732d03..5e20120d906d8 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -40,7 +40,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at if (!trk.OK()) { continue; } - bool rejectTrk = CAMath::Abs(trk.GetParam().GetQPt()) > processors.param.rec.tpcRejectQPt; + bool rejectTrk = CAMath::Abs(trk.GetParam().GetQPt()) > processors.param.rec.tpcRejectQPt || trk.MergedLooper(); unsigned int nClustersStored = 0; CompressedClustersPtrs& GPUrestrict() c = compressor.mPtrs; unsigned int lastRow = 0, lastSlice = 0; // BUG: These should be unsigned char, but then CUDA breaks @@ -219,7 +219,8 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un break; } int id = attach & gputpcgmmergertypes::attachTrackMask; - if (CAMath::Abs(merger.OutputTracks()[id].GetParam().GetQPt()) > processors.param.rec.tpcRejectQPt) { + auto& trk = merger.OutputTracks()[id]; + if (CAMath::Abs(trk.GetParam().GetQPt()) > processors.param.rec.tpcRejectQPt || trk.MergedLooper()) { break; } } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 4753a65801187..ff2e5c86ed8b2 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2033,6 +2033,9 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) runKernel<GPUTPCGMMergerFinalize, 1>(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); runKernel<GPUTPCGMMergerFinalize, 2>(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); } + if (param().rec.tpcMergeLoopersAfterburner) { + runKernel<GPUTPCGMMergerMergeLoopers>(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); + } DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpFinal, *mDebugFile); if (doGPUall) { diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergedTrack.h b/GPU/GPUTracking/Merger/GPUTPCGMMergedTrack.h index 6f72a23f8b13c..1a4479fc74d38 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergedTrack.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergedTrack.h @@ -50,6 +50,7 @@ class GPUTPCGMMergedTrack GPUd() bool Looper() const { return mFlags & 0x02; } GPUd() bool CSide() const { return mFlags & 0x04; } GPUd() bool CCE() const { return mFlags & 0x08; } + GPUd() bool MergedLooper() const { return mFlags & 0x10; } GPUd() void SetNClusters(int v) { mNClusters = v; } GPUd() void SetNClustersFitted(int v) { mNClustersFitted = v; } @@ -91,6 +92,14 @@ class GPUTPCGMMergedTrack mFlags &= 0xF7; } } + GPUd() void SetMergedLooper(bool v) + { + if (v) { + mFlags |= 0x10; + } else { + mFlags &= 0xEF; + } + } GPUd() void SetFlags(unsigned char v) { mFlags = v; } GPUd() void SetLegs(unsigned char v) { mLegs = v; } GPUd() unsigned char Legs() const { return mLegs; } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index e7e230eb0d16e..d5a0afe1f0d9f 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -12,6 +12,7 @@ /// \author Sergey Gorbunov, David Rohr #define GPUCA_CADEBUG 0 +#define GPUCA_MERGE_LOOPER_MC 0 #ifndef GPUCA_GPUCODE_DEVICE #include <cstdio> @@ -41,7 +42,7 @@ #include "GPUTPCGMSliceTrack.h" #include "GPUTPCGMBorderTrack.h" -#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED)) +#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) || GPUCA_MERGE_LOOPER_MC) #include "AliHLTTPCClusterMCData.h" #ifdef GPUCA_O2_LIB #include "DataFormatsTPC/ClusterNative.h" @@ -90,7 +91,7 @@ GPUTPCGMMerger::GPUTPCGMMerger() } // DEBUG CODE -#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED)) +#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) || GPUCA_MERGE_LOOPER_MC) void GPUTPCGMMerger::CheckMergedTracks() { std::vector<bool> trkUsed(SliceTrackInfoLocalTotal()); @@ -140,20 +141,30 @@ void GPUTPCGMMerger::CheckMergedTracks() } } -template <class T> -long int GPUTPCGMMerger::GetTrackLabelA(const GPUTPCGMBorderTrack& trk) +template <class T, class S> +long int GPUTPCGMMerger::GetTrackLabelA(const S& trk) { - GPUTPCGMSliceTrack* track = &mSliceTrackInfos[trk.TrackID()]; - int nClusters = track->OrigTrack()->NHits(); + GPUTPCGMSliceTrack* sliceTrack = nullptr; + int nClusters = 0; + if constexpr (std::is_same<S, GPUTPCGMBorderTrack&>::value) { + sliceTrack = &mSliceTrackInfos[trk.TrackID()]; + nClusters = sliceTrack->OrigTrack()->NHits(); + } else { + nClusters = trk.NClusters(); + } std::vector<long int> labels; for (int i = 0; i < nClusters; i++) { int id; - if (Param().rec.mergerReadFromTrackerDirectly) { - const GPUTPCTracker& tracker = GetConstantMem()->tpcTrackers[track->Slice()]; - const GPUTPCHitId& ic = tracker.TrackHits()[track->OrigTrack()->FirstHitID() + i]; - id = tracker.Data().ClusterDataIndex(tracker.Data().Row(ic.RowIndex()), ic.HitIndex()) + GetConstantMem()->ioPtrs.clustersNative->clusterOffset[track->Slice()][0]; + if constexpr (std::is_same<S, GPUTPCGMBorderTrack&>::value) { + if (Param().rec.mergerReadFromTrackerDirectly) { + const GPUTPCTracker& tracker = GetConstantMem()->tpcTrackers[sliceTrack->Slice()]; + const GPUTPCHitId& ic = tracker.TrackHits()[sliceTrack->OrigTrack()->FirstHitID() + i]; + id = tracker.Data().ClusterDataIndex(tracker.Data().Row(ic.RowIndex()), ic.HitIndex()) + GetConstantMem()->ioPtrs.clustersNative->clusterOffset[sliceTrack->Slice()][0]; + } else { + id = sliceTrack->OrigTrack()->OutTrackClusters()[i].GetId(); + } } else { - id = track->OrigTrack()->OutTrackClusters()[i].GetId(); + id = mClusters[trk.FirstClusterRef() + i].num; } if constexpr (std::is_same<T, AliHLTTPCClusterMCLabel>::value) { for (int j = 0; j < 3; j++) { @@ -163,9 +174,11 @@ long int GPUTPCGMMerger::GetTrackLabelA(const GPUTPCGMBorderTrack& trk) } } } else { +#ifdef GPUCA_O2_LIB for (auto label : GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth->getLabels(id)) { labels.push_back(label.getTrackEventSourceID()); } +#endif } } if (labels.size() == 0) { @@ -190,15 +203,16 @@ long int GPUTPCGMMerger::GetTrackLabelA(const GPUTPCGMBorderTrack& trk) return bestLabel; } -long int GPUTPCGMMerger::GetTrackLabel(const GPUTPCGMBorderTrack& trk) +template <class S> +long int GPUTPCGMMerger::GetTrackLabel(const S& trk) { #ifdef GPUCA_O2_LIB if (GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth) { - return GetTrackLabelA<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>>(trk); + return GetTrackLabelA<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>, S>(trk); } else #endif { - return GetTrackLabelA<AliHLTTPCClusterMCLabel>(trk); + return GetTrackLabelA<AliHLTTPCClusterMCLabel, S>(trk); } } @@ -806,7 +820,9 @@ GPUd() void GPUTPCGMMerger::MergeBorderTracks<2>(int nBlocks, int nThreads, int GPUTPCGMBorderTrack& b2 = B2[r2.fId]; #if defined(GPUCA_MERGER_BY_MC_LABEL) && !defined(GPUCA_GPUCODE) - if (GetTrackLabel(b1) != GetTrackLabel(b2)) // DEBUG CODE, match by MC label + long int label1 = GetTrackLabel(b1); + long int label2 = GetTrackLabel(b2); + if (label1 != label2 && label1 != -1) // DEBUG CODE, match by MC label #endif { CADEBUG( @@ -1919,3 +1935,70 @@ GPUd() void GPUTPCGMMerger::Finalize2(int nBlocks, int nThreads, int iBlock, int } } } + +struct MergeLooperParam { + float absz; + float tgl; + float qpt; + float x; + float y; + unsigned int id; +}; + +GPUd() void GPUTPCGMMerger::MergeLoopers(int nBlocks, int nThreads, int iBlock, int iThread) +{ + if (iThread || iBlock) { + return; + } +#ifndef GPUCA_GPUCODE + std::vector<MergeLooperParam> params; + const float lowPtThresh = Param().rec.tpcRejectQPt * 1.1f; // Might need to merge tracks above the threshold with parts below the threshold + for (unsigned int i = 0; i < mMemory->nOutputTracks; i++) { + const auto& trk = mOutputTracks[i]; + const auto& p = trk.GetParam(); + const float qptabs = CAMath::Abs(p.GetQPt()); + if (trk.NClusters() && qptabs > 5.f && qptabs <= lowPtThresh) { + const int slice = mClusters[trk.FirstClusterRef() + trk.NClusters() - 1].slice; + const float z = p.GetZ() + (Param().earlyTpcTransform ? p.GetTZOffset() : GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(slice, p.GetTZOffset(), Param().continuousMaxTimeBin)); + float sinA, cosA; + CAMath::SinCos(trk.GetAlpha(), sinA, cosA); + float gx = cosA * p.GetX() - sinA * p.GetY(); + float gy = cosA * p.GetY() + sinA * p.GetX(); + float bz = Param().polynomialField.GetFieldBz(gx, gy, p.GetZ()); + const float r1 = p.GetQPt() * bz; + const float r = CAMath::Abs(r1) > 0.0001 ? (1.f / r1) : 10000; + const float mx = p.GetX() + r * p.GetSinPhi(); + const float my = p.GetY() - r * CAMath::Sqrt(1 - p.GetSinPhi() * p.GetSinPhi()); + const float gmx = cosA * mx - sinA * my; + const float gmy = cosA * my + sinA * mx; + params.emplace_back(MergeLooperParam{CAMath::Abs(z), CAMath::Abs(p.GetDzDs()), p.GetDzDs() > 0 ? p.GetQPt() : -p.GetQPt(), gmx, gmy, i}); + } + } + std::sort(params.begin(), params.end(), [](const MergeLooperParam& a, const MergeLooperParam& b) { return a.absz < b.absz; }); + for (unsigned int i = 0; i < params.size(); i++) { + for (unsigned int j = i + 1; j < params.size(); j++) { + if (params[j].absz > params[i].absz + 100.f) { + break; + } + float dqpt = CAMath::Min(CAMath::Abs(params[i].tgl), CAMath::Abs(params[j].tgl)) < 0.05f ? (CAMath::Abs(params[i].qpt) - CAMath::Abs(params[i].qpt)) : (params[i].qpt - params[j].qpt); + float d = CAMath::Sum2((params[i].x - params[j].x) * (1.f / 5.f), (params[i].y - params[j].y) * (1.f / 5.f), (params[i].tgl - params[j].tgl) * (1.f / 0.15f), dqpt / CAMath::Min(params[i].qpt, params[j].qpt) * (1.f / 0.15f)); + //bool EQ = CAMath::Abs(params[i].x - params[j].x) < 10.f && CAMath::Abs(params[i].y - params[j].y) < 10.f && CAMath::Abs(params[i].tgl - params[j].tgl) < 0.15f && CAMath::Abs((params[i].qpt - params[j].qpt) / CAMath::Min(params[i].qpt, params[j].qpt)) < 0.15f; + bool EQ = d < 1.5f; +#if GPUCA_MERGE_LOOPER_MC + long int label1 = GetTrackLabel(mOutputTracks[params[i].id]); + long int label2 = GetTrackLabel(mOutputTracks[params[j].id]); + bool labelEQ = label1 != -1 && label1 == label2; + if (EQ || labelEQ) { + printf("Matching track %d/%d %u-%u (%ld): side %d %d, tgl %f %f, qpt %f %f, x %f %f, y %f %f\n", (int)EQ, (int)labelEQ, i, j, label1, (int)mOutputTracks[params[i].id].CSide(), (int)mOutputTracks[params[j].id].CSide(), params[i].tgl, params[j].tgl, params[i].qpt, params[j].qpt, params[i].x, params[j].x, params[i].y, params[j].y); + } +#endif + if (EQ) { + mOutputTracks[params[j].id].SetMergedLooper(true); + if (CAMath::Abs(params[j].qpt) >= Param().rec.tpcRejectQPt) { + mOutputTracks[params[i].id].SetMergedLooper(true); + } + } + } + } +#endif +} diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h index 1b1defc27e8d5..c5e0da4c571d8 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.h @@ -153,6 +153,7 @@ class GPUTPCGMMerger : public GPUProcessor GPUd() void ResolveFindConnectedComponentsHookLinks(int nBlocks, int nThreads, int iBlock, int iThread); GPUd() void ResolveFindConnectedComponentsMultiJump(int nBlocks, int nThreads, int iBlock, int iThread); GPUd() void ResolveMergeSlices(gputpcgmmergertypes::GPUResolveSharedMemory& smem, int nBlocks, int nThreads, int iBlock, int iThread, char useOrigTrackParam, char mergeAll); + GPUd() void MergeLoopers(int nBlocks, int nThreads, int iBlock, int iThread); #ifndef GPUCA_GPUCODE void DumpSliceTracks(std::ostream& out); @@ -175,9 +176,10 @@ class GPUTPCGMMerger : public GPUProcessor void CheckMergedTracks(); #ifndef GPUCA_GPUCODE void PrintMergeGraph(const GPUTPCGMSliceTrack* trk, std::ostream& out); - template <class T> - long int GetTrackLabelA(const GPUTPCGMBorderTrack& trk); - long int GetTrackLabel(const GPUTPCGMBorderTrack& trk); + template <class T, class S> + long int GetTrackLabelA(const S& trk); + template <class S> + long int GetTrackLabel(const S& trk); #endif GPUdi() int SliceTrackInfoFirst(int iSlice) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx index b268e15e1ca35..8068955daaac6 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx @@ -204,3 +204,9 @@ GPUdii() void GPUTPCGMMergerFinalize::Thread<2>(int nBlocks, int nThreads, int i { merger.Finalize2(nBlocks, nThreads, iBlock, iThread); } + +template <> +GPUdii() void GPUTPCGMMergerMergeLoopers::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() merger) +{ + merger.MergeLoopers(nBlocks, nThreads, iBlock, iThread); +} diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h index 0614f82926b1e..ee6a50d56f9ed 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.h @@ -214,6 +214,15 @@ class GPUTPCGMMergerFinalize : public GPUTPCGMMergerGeneral #endif }; +class GPUTPCGMMergerMergeLoopers : public GPUTPCGMMergerGeneral +{ + public: +#if !defined(GPUCA_ALIROOT_LIB) || !defined(GPUCA_GPUCODE) + template <int iKernel = defaultKernel> + GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& merger); +#endif +}; + } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 4430d15a6d7d8..699b94996c34e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -814,7 +814,7 @@ GPUd() void GPUTPCGMTrackParam::ShiftZ(const GPUTPCGMMerger* GPUrestrict() merge const float dxf = -CAMath::Abs(mP[2]); const float dyf = cosPhi * (mP[2] > 0 ? 1.f : -1.f); const float r1 = CAMath::Abs(mP[4] * merger->Param().polynomialField.GetNominalBz()); - const float r = r1 > 0.0001 ? (1.f / CAMath::Abs(r1)) : 10000; + const float r = r1 > 0.0001 ? (1.f / r1) : 10000; float xp = mX + dxf * r; float yp = mP[0] + dyf * r; // printf("X %f Y %f SinPhi %f QPt %f R %f --> XP %f YP %f\n", mX, mP[0], mP[2], mP[4], r, xp, yp); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 3d0174c1fe7c5..06bbe54520c97 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -82,11 +82,13 @@ using namespace GPUCA_NAMESPACE::gpu; float qpt = 0; \ bool lowPt = false; \ bool mev200 = false; \ + bool mergedLooper = false; \ int id = attach & gputpcgmmergertypes::attachTrackMask; \ if (!unattached) { \ qpt = fabsf(mTracking->mIOPtrs.mergedTracks[id].GetParam().GetQPt()); \ lowPt = qpt > mTracking->GetParam().rec.tpcRejectQPt; \ mev200 = qpt > 5; \ + mergedLooper = mTracking->mIOPtrs.mergedTracks[id].MergedLooper(); \ } \ bool physics = false, protect = false; \ CHECK_CLUSTER_STATE_INIT_LEG_BY_MC(); @@ -98,6 +100,8 @@ using namespace GPUCA_NAMESPACE::gpu; } \ if (lowPt) { \ mClusterCounts.nLowPt++; \ + } else if (mergedLooper) { \ + mClusterCounts.nMergedLooper++; \ } else { \ GPUTPCClusterRejection::GetProtectionStatus<true>(attach, physics, protect, &mClusterCounts, &mev200); \ } @@ -105,7 +109,7 @@ using namespace GPUCA_NAMESPACE::gpu; #define CHECK_CLUSTER_STATE_NOCOUNT() \ CHECK_CLUSTER_STATE_INIT() \ (void)mev200; /* silence unused variable warning*/ \ - if (!lowPt) { \ + if (!lowPt && !mergedLooper) { \ GPUTPCClusterRejection::GetProtectionStatus<false>(attach, physics, protect); \ } @@ -687,7 +691,7 @@ void GPUQA::RunQA(bool matchOnly) } if (mTrackMCLabels[i].isFake()) { (GetMCTrackObj(mFakeTracks, label))++; - } else { + } else if (!track.MergedLooper()) { GetMCTrackObj(mRecTracks, label)++; if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) { int& revLabel = GetMCTrackObj(mTrackMCLabelsReverse, label); @@ -921,6 +925,9 @@ void GPUQA::RunQA(bool matchOnly) if (!track.OK()) { continue; } + if (track.MergedLooper()) { + continue; + } if (fabsf(mc2.eta) > ETA_MAX || mc2.pt < PT_MIN || mc2.pt > PT_MAX) { continue; } @@ -2019,6 +2026,7 @@ int GPUQA::DrawQAHistograms() printf("\t%35s: %'12llu (%6.2f%%)\n", "Removed", mClusterCounts.nTotal - mClusterCounts.nUnattached - mClusterCounts.nProt, 100.f * (mClusterCounts.nTotal - mClusterCounts.nUnattached - mClusterCounts.nProt) / counts[N_CLS_HIST - 1]); } + printf("\t%35s: %'12llu (%6.2f%%)\n", "Merged Loopers (Afterburner)", mClusterCounts.nMergedLooper, 100.f * mClusterCounts.nMergedLooper / counts[N_CLS_HIST - 1]); printf("\t%35s: %'12llu (%6.2f%%)\n", "High Inclination Angle", mClusterCounts.nHighIncl, 100.f * mClusterCounts.nHighIncl / counts[N_CLS_HIST - 1]); printf("\t%35s: %'12llu (%6.2f%%)\n", "Rejected", mClusterCounts.nRejected, 100.f * mClusterCounts.nRejected / counts[N_CLS_HIST - 1]); printf("\t%35s: %'12llu (%6.2f%%)\n", "Tube (> 200 MeV)", mClusterCounts.nTube, 100.f * mClusterCounts.nTube / counts[N_CLS_HIST - 1]); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 5e21d54be6269..b35d52579b26e 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -237,7 +237,7 @@ class GPUQA TLegend* mLClust[N_CLS_TYPE]; struct counts_t { - long long int nRejected = 0, nTube = 0, nTube200 = 0, nLoopers = 0, nLowPt = 0, n200MeV = 0, nPhysics = 0, nProt = 0, nUnattached = 0, nTotal = 0, nHighIncl = 0, nAbove400 = 0, nFakeRemove400 = 0, nFullFakeRemove400 = 0, nBelow40 = 0, nFakeProtect40 = 0; + long long int nRejected = 0, nTube = 0, nTube200 = 0, nLoopers = 0, nLowPt = 0, n200MeV = 0, nPhysics = 0, nProt = 0, nUnattached = 0, nTotal = 0, nHighIncl = 0, nAbove400 = 0, nFakeRemove400 = 0, nFullFakeRemove400 = 0, nBelow40 = 0, nFakeProtect40 = 0, nMergedLooper = 0; double nUnaccessible = 0; } mClusterCounts; From 94ec556c182cdda35adb4b1cefcb828b111e6d16 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 2 Nov 2020 09:06:59 +0100 Subject: [PATCH 1235/1751] GPU: Apply combined criterion on y/z for track tube definition --- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 699b94996c34e..dffa40a038633 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -498,10 +498,12 @@ GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict float err2Y, err2Z; Merger->Param().GetClusterErrors2(iRow, Z, mP[2], mP[3], err2Y, err2Z); - const float sy2 = CAMath::Min(Merger->Param().rec.tpcTubeMaxSize2, Merger->Param().rec.tpcTubeChi2 * (err2Y + mC[0])); - const float sz2 = CAMath::Min(Merger->Param().rec.tpcTubeMaxSize2, Merger->Param().rec.tpcTubeChi2 * (err2Z + mC[2])); + const float sy2 = CAMath::Min(Merger->Param().rec.tpcTubeMaxSize2, Merger->Param().rec.tpcTubeChi2 * (err2Y + CAMath::Abs(mC[0]))); // Cov can be bogus when following circle + const float sz2 = CAMath::Min(Merger->Param().rec.tpcTubeMaxSize2, Merger->Param().rec.tpcTubeChi2 * (err2Z + CAMath::Abs(mC[2]))); // In that case we should provide the track error externally const float tubeY = CAMath::Sqrt(sy2); const float tubeZ = CAMath::Sqrt(sz2); + const float sy21 = 1.f / sy2; + const float sz21 = 1.f / sz2; float nY, nZ; if (Merger->Param().earlyTpcTransform) { nY = Y; @@ -537,7 +539,7 @@ GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict const float z = z0 + hh.y * stepZ; const float dy = y - nY; const float dz = z - nZ; - if (dy * dy < sy2 && dz * dz < sz2) { + if (dy * dy * sy21 + dz * dz * sz21 <= CAMath::Sqrt(2.f)) { // CADEBUG(printf("Found Y %f Z %f\n", y, z)); CAMath::AtomicMax(weight, myWeight); } From 6834b40962cd727d1b07f10052e915ec84476b16 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 2 Nov 2020 09:07:30 +0100 Subject: [PATCH 1236/1751] GPU: Bugfix for on-the-fly MC label assignment in tracking QA --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index d5a0afe1f0d9f..dd61b78e22ecc 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -184,8 +184,8 @@ long int GPUTPCGMMerger::GetTrackLabelA(const S& trk) if (labels.size() == 0) { return (-1); } - labels.push_back(-1); std::sort(labels.begin(), labels.end()); + labels.push_back(-1); long int bestLabel = -1, curLabel = labels[0]; int curCount = 1, bestLabelCount = 0; for (unsigned int i = 1; i < labels.size(); i++) { From d341e32b86df923d029c4b3e7275a3f26a0830c0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 2 Nov 2020 09:35:47 +0100 Subject: [PATCH 1237/1751] GPU: Add some on-the-fly QA for looper merging efficiency --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 72 ++++++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index dd61b78e22ecc..0ad56f3983b5a 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -1972,9 +1972,40 @@ GPUd() void GPUTPCGMMerger::MergeLoopers(int nBlocks, int nThreads, int iBlock, const float gmx = cosA * mx - sinA * my; const float gmy = cosA * my + sinA * mx; params.emplace_back(MergeLooperParam{CAMath::Abs(z), CAMath::Abs(p.GetDzDs()), p.GetDzDs() > 0 ? p.GetQPt() : -p.GetQPt(), gmx, gmy, i}); + + /*printf("Track %d Sanity qpt %f snp %f bz %f\n", (int)params.size(), p.GetQPt(), p.GetSinPhi(), bz); + for (unsigned int k = 0;k < trk.NClusters();k++) { + float xx, yy, zz; + if (Param().earlyTpcTransform) { + const float zOffset = (mClusters[trk.FirstClusterRef() + k].slice < 18) == (mClusters[trk.FirstClusterRef() + 0].slice < 18) ? p.GetTZOffset() : -p.GetTZOffset(); + xx = mClustersXYZ[trk.FirstClusterRef() + k].x; + yy = mClustersXYZ[trk.FirstClusterRef() + k].y; + zz = mClustersXYZ[trk.FirstClusterRef() + k].z - zOffset; + } else { + const ClusterNative& GPUrestrict() cl = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[mClusters[trk.FirstClusterRef() + k].num]; + GetConstantMem()->calibObjects.fastTransform->Transform(mClusters[trk.FirstClusterRef() + k].slice, mClusters[trk.FirstClusterRef() + k].row, cl.getPad(), cl.getTime(), xx, yy, zz, p.GetTZOffset()); + } + float sa2, ca2; + CAMath::SinCos(Param().Alpha(mClusters[trk.FirstClusterRef() + k].slice), sa2, ca2); + float cx = ca2 * xx - sa2 * yy; + float cy = ca2 * yy + sa2 * xx; + float dist = sqrtf((cx - gmx) * (cx - gmx) + (cy - gmy) * (cy - gmy)); + printf("Hit %3d/%3d slice %d xy %f %f R %f\n", k, trk.NClusters(), (int)mClusters[trk.FirstClusterRef() + k].slice, cx, cy, dist); + }*/ } } std::sort(params.begin(), params.end(), [](const MergeLooperParam& a, const MergeLooperParam& b) { return a.absz < b.absz; }); +#if GPUCA_MERGE_LOOPER_MC + std::vector<long int> paramLabels(params.size()); + for (unsigned int i = 0; i < params.size(); i++) { + paramLabels[i] = GetTrackLabel(mOutputTracks[params[i].id]); + } + std::vector<bool> dropped(params.size()); + std::vector<bool> droppedMC(params.size()); + std::vector<int> histMatch(101); + std::vector<int> histFail(101); +#endif + for (unsigned int i = 0; i < params.size(); i++) { for (unsigned int j = i + 1; j < params.size(); j++) { if (params[j].absz > params[i].absz + 100.f) { @@ -1985,11 +2016,21 @@ GPUd() void GPUTPCGMMerger::MergeLoopers(int nBlocks, int nThreads, int iBlock, //bool EQ = CAMath::Abs(params[i].x - params[j].x) < 10.f && CAMath::Abs(params[i].y - params[j].y) < 10.f && CAMath::Abs(params[i].tgl - params[j].tgl) < 0.15f && CAMath::Abs((params[i].qpt - params[j].qpt) / CAMath::Min(params[i].qpt, params[j].qpt)) < 0.15f; bool EQ = d < 1.5f; #if GPUCA_MERGE_LOOPER_MC - long int label1 = GetTrackLabel(mOutputTracks[params[i].id]); - long int label2 = GetTrackLabel(mOutputTracks[params[j].id]); + const long int label1 = paramLabels[i]; + const long int label2 = paramLabels[j]; bool labelEQ = label1 != -1 && label1 == label2; if (EQ || labelEQ) { - printf("Matching track %d/%d %u-%u (%ld): side %d %d, tgl %f %f, qpt %f %f, x %f %f, y %f %f\n", (int)EQ, (int)labelEQ, i, j, label1, (int)mOutputTracks[params[i].id].CSide(), (int)mOutputTracks[params[j].id].CSide(), params[i].tgl, params[j].tgl, params[i].qpt, params[j].qpt, params[i].x, params[j].x, params[i].y, params[j].y); + printf("Matching track %d/%d %u-%u (%ld/%ld): dist %f side %d %d, tgl %f %f, qpt %f %f, x %f %f, y %f %f\n", (int)EQ, (int)labelEQ, i, j, label1, label2, d, (int)mOutputTracks[params[i].id].CSide(), (int)mOutputTracks[params[j].id].CSide(), params[i].tgl, params[j].tgl, params[i].qpt, params[j].qpt, params[i].x, params[j].x, params[i].y, params[j].y); + } + if (EQ) { + dropped[j] = true; + } + if (labelEQ) { + droppedMC[j] = true; + histMatch[CAMath::Min<int>(100, d * 10.f)]++; + } + if (d < 10.f && !labelEQ) { + histFail[CAMath::Min<int>(100, d * 10.f)]++; } #endif if (EQ) { @@ -2000,5 +2041,30 @@ GPUd() void GPUTPCGMMerger::MergeLoopers(int nBlocks, int nThreads, int iBlock, } } } +#if GPUCA_MERGE_LOOPER_MC + int total = 0, totalmc = 0, good = 0, missed = 0, fake = 0; + for (unsigned int i = 0; i < params.size(); i++) { + total += dropped[i]; + totalmc += droppedMC[i]; + good += dropped[i] && droppedMC[i]; + missed += droppedMC[i] && !dropped[i]; + fake += dropped[i] && !droppedMC[i]; + } + if (good) { + printf("%20s: %8d\n", "Total", total); + printf("%20s: %8d\n", "TotalMC", totalmc); + printf("%20s: %8d (%8.3f%% %8.3f%%)\n", "Good", good, 100.f * good / total, 100.f * good / totalmc); + printf("%20s: %8d (%8.3f%%)\n", "Missed", missed, 100.f * missed / totalmc); + printf("%20s: %8d (%8.3f%%)\n", "Fake", fake, 100.f * fake / total); + } + printf("Match histo\n"); + for (unsigned int i = 0; i < histMatch.size(); i++) { + printf("%8.3f: %3d\n", i / 10.f + 0.05f, histMatch[i]); + } + printf("Fake histo\n"); + for (unsigned int i = 0; i < histFail.size(); i++) { + printf("%8.3f: %3d\n", i / 10.f + 0.05f, histFail[i]); + } +#endif #endif } From 9455c4c10b78729bace2e462e25b1e8d779f5cfb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 8 Nov 2020 01:24:30 +0100 Subject: [PATCH 1238/1751] remove duplicate file --- .../src/mid-entropy-encoder-workflow.cxx | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx diff --git a/Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx b/Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx deleted file mode 100644 index b59fc88c58ba3..0000000000000 --- a/Detectors/MUON/MID/Workflow/src/mid-entropy-encoder-workflow.cxx +++ /dev/null @@ -1,45 +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. - -/// \file mid-entropy-encoder-workflow.cxx -/// \brief MID reconstruction workflow -/// \author ruben.shahoyan@cern.ch - -#include <string> -#include <vector> -#include "Framework/Variant.h" -#include "CommonUtils/ConfigurableParam.h" -#include "MIDWorkflow/EntropyEncoderSpec.h" - -using namespace o2::framework; - -// ------------------------------------------------------------------ - -// we need to add workflow options before including Framework/runDataProcessing -void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) -{ - std::string keyvaluehelp("Semicolon separated key=value strings ..."); - workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); -} - -// ------------------------------------------------------------------ - -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" - -WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) -{ - // Update the (declared) parameters if changed from the command line - o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); - - WorkflowSpec wf; - wf.emplace_back(o2::mid::getEntropyEncoderSpec()); - return std::move(wf); -} From f2fe2ee81b02d6e219d8a008bc5764c601275b2f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 8 Nov 2020 11:58:23 +0100 Subject: [PATCH 1239/1751] Add EMCAL CTF class --- DataFormats/Detectors/EMCAL/CMakeLists.txt | 4 +- .../EMCAL/include/DataFormatsEMCAL/CTF.h | 57 +++++++++++++++++++ .../EMCAL/include/DataFormatsEMCAL/Cell.h | 15 +++++ DataFormats/Detectors/EMCAL/src/CTF.cxx | 15 +++++ .../EMCAL/src/DataFormatsEMCALLinkDef.h | 4 ++ 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CTF.h create mode 100644 DataFormats/Detectors/EMCAL/src/CTF.cxx diff --git a/DataFormats/Detectors/EMCAL/CMakeLists.txt b/DataFormats/Detectors/EMCAL/CMakeLists.txt index f8b83e4808fac..df6fd86c0205f 100644 --- a/DataFormats/Detectors/EMCAL/CMakeLists.txt +++ b/DataFormats/Detectors/EMCAL/CMakeLists.txt @@ -17,6 +17,7 @@ o2_add_library(DataFormatsEMCAL src/Cell.cxx src/Digit.cxx src/EventHandler.cxx + src/CTF.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::MathUtils @@ -33,7 +34,8 @@ o2_target_root_dictionary(DataFormatsEMCAL include/DataFormatsEMCAL/Cluster.h include/DataFormatsEMCAL/AnalysisCluster.h include/DataFormatsEMCAL/EventHandler.h - include/DataFormatsEMCAL/MCLabel.h) + include/DataFormatsEMCAL/MCLabel.h + include/DataFormatsEMCAL/CTF.h) o2_add_test(Cell SOURCES test/testCell.cxx diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CTF.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CTF.h new file mode 100644 index 0000000000000..283c98d52bed2 --- /dev/null +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CTF.h @@ -0,0 +1,57 @@ +// 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 CTF.h +/// \author ruben.shahoyan@cern.ch +/// \brief Definitions for EMC CTF data + +#ifndef O2_EMC_CTF_H +#define O2_EMC_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" +#include "DataFormatsEMCAL/TriggerRecord.h" +#include "DataFormatsEMCAL/Cell.h" + +namespace o2 +{ +namespace emcal +{ + +/// Header for a single CTF +struct CTFHeader { + uint32_t nTriggers = 0; /// number of triggers + uint32_t nCells = 0; /// number of referred cells + uint32_t firstOrbit = 0; /// orbit of 1st trigger + uint16_t firstBC = 0; /// bc of 1st trigger + + ClassDefNV(CTFHeader, 1); +}; + +/// wrapper for the Entropy-encoded triggers and cells of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 7, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { BLC_bcIncTrig, + BLC_orbitIncTrig, + BLC_entriesTrig, + BLC_towerID, + BLC_time, + BLC_energy, + BLC_status + }; + ClassDefNV(CTF, 1); +}; + +} // namespace emcal +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h index 361faf1d13e90..a9872a9039bd2 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/Cell.h @@ -155,6 +155,21 @@ class Cell void PrintStream(std::ostream& stream) const; + /// used for CTF encoding/decoding: access to packed data + void setPacked(uint16_t tower, uint16_t t, uint16_t en, uint16_t status) + { + auto dt = getDataRepresentation(); + dt->mTowerID = tower; + dt->mTime = t; + dt->mEnergy = en; + dt->mCellStatus = status; + } + + auto getPackedTowerID() const { return getDataRepresentation()->mTowerID; } + auto getPackedTime() const { return getDataRepresentation()->mTime; } + auto getPackedEnergy() const { return getDataRepresentation()->mEnergy; } + auto getPackedCellStatus() const { return getDataRepresentation()->mCellStatus; } + private: struct __attribute__((packed)) CellData { uint16_t mTowerID : 15; ///< bits 0-14 Tower ID diff --git a/DataFormats/Detectors/EMCAL/src/CTF.cxx b/DataFormats/Detectors/EMCAL/src/CTF.cxx new file mode 100644 index 0000000000000..1f9b440e65ec2 --- /dev/null +++ b/DataFormats/Detectors/EMCAL/src/CTF.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 <stdexcept> +#include <cstring> +#include "DataFormatsEMCAL/CTF.h" + +using namespace o2::emcal; diff --git a/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h b/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h index 1f1161c95a798..5f9bdd0c321cd 100644 --- a/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h +++ b/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h @@ -41,4 +41,8 @@ #pragma link C++ class o2::emcal::EventHandler < o2::emcal::Cell> + ; #pragma link C++ class o2::emcal::EventHandler < o2::emcal::Digit> + ; +#pragma link C++ struct o2::emcal::CTFHeader + ; +#pragma link C++ struct o2::emcal::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::emcal::CTFHeader, 7, uint32_t> + ; + #endif From 3b28800253a9b1a5b424de475b3f3499a667405e Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 8 Nov 2020 12:01:15 +0100 Subject: [PATCH 1240/1751] EMCAL entropy encoder/decoder + workflows --- Detectors/EMCAL/reconstruction/CMakeLists.txt | 6 +- .../include/EMCALReconstruction/CTFCoder.h | 153 ++++++++++++++ .../include/EMCALReconstruction/CTFHelper.h | 193 ++++++++++++++++++ .../EMCAL/reconstruction/src/CTFCoder.cxx | 76 +++++++ .../EMCAL/reconstruction/src/CTFHelper.cxx | 15 ++ Detectors/EMCAL/workflow/CMakeLists.txt | 7 + .../EMCALWorkflow/EntropyDecoderSpec.h | 47 +++++ .../EMCALWorkflow/EntropyEncoderSpec.h | 47 +++++ .../EMCAL/workflow/src/EntropyDecoderSpec.cxx | 79 +++++++ .../EMCAL/workflow/src/EntropyEncoderSpec.cxx | 79 +++++++ .../workflow/src/entropy-encoder-workflow.cxx | 39 ++++ 11 files changed, 740 insertions(+), 1 deletion(-) create mode 100644 Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFCoder.h create mode 100644 Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFHelper.h create mode 100644 Detectors/EMCAL/reconstruction/src/CTFCoder.cxx create mode 100644 Detectors/EMCAL/reconstruction/src/CTFHelper.cxx create mode 100644 Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyDecoderSpec.h create mode 100644 Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyEncoderSpec.h create mode 100644 Detectors/EMCAL/workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/EMCAL/workflow/src/EntropyEncoderSpec.cxx create mode 100644 Detectors/EMCAL/workflow/src/entropy-encoder-workflow.cxx diff --git a/Detectors/EMCAL/reconstruction/CMakeLists.txt b/Detectors/EMCAL/reconstruction/CMakeLists.txt index 514822ba1ec5a..ea2bbdeef9b59 100644 --- a/Detectors/EMCAL/reconstruction/CMakeLists.txt +++ b/Detectors/EMCAL/reconstruction/CMakeLists.txt @@ -24,12 +24,16 @@ o2_add_library(EMCALReconstruction src/Clusterizer.cxx src/ClusterizerTask.cxx src/DigitReader.cxx + src/CTFCoder.cxx + src/CTFHelper.cxx PUBLIC_LINK_LIBRARIES FairRoot::Base O2::Headers AliceO2::InfoLogger O2::DataFormatsEMCAL O2::DetectorsBase O2::DetectorsRaw - O2::EMCALBase) + O2::EMCALBase + O2::rANS + ms_gsl::ms_gsl) o2_target_root_dictionary( EMCALReconstruction diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFCoder.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFCoder.h new file mode 100644 index 0000000000000..a51ca476032d3 --- /dev/null +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFCoder.h @@ -0,0 +1,153 @@ +// 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 CTFCoder.h +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of EMCAL data + +#ifndef O2_EMCAL_CTFCODER_H +#define O2_EMCAL_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include <array> +#include "DataFormatsEMCAL/CTF.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" +#include "rANS/rans.h" +#include "EMCALReconstruction/CTFHelper.h" + +class TTree; + +namespace o2 +{ +namespace emcal +{ + +class CTFCoder : public o2::ctf::CTFCoderBase +{ + public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::EMC) {} + ~CTFCoder() = default; + + /// entropy-encode data to buffer with CTF + template <typename VEC> + void encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cell>& cellData); + + /// entropy decode data from buffer with CTF + template <typename VTRG, typename VCELL> + void decode(const CTF::base& ec, VTRG& trigVec, VCELL& cellVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); + + private: + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Cell>& cellVec); +}; + +/// entropy-encode clusters to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cell>& cellData) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, // BLC_bcIncTrig + MD::EENCODE, // BLC_orbitIncTrig + MD::EENCODE, // BLC_entriesTrig + MD::EENCODE, // BLC_towerID + MD::EENCODE, // BLC_time + MD::EENCODE, // BLC_energy + MD::EENCODE // BLC_status + }; + + CTFHelper helper(trigData, cellData); + + // book output size with some margin + auto szIni = sizeof(CTFHeader) + helper.getSize() / 4; // will be autoexpanded if needed + buff.resize(szIni); + + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(helper.createHeader()); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODEEMC(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); + // clang-format off + ENCODEEMC(helper.begin_bcIncTrig(), helper.end_bcIncTrig(), CTF::BLC_bcIncTrig, 0); + ENCODEEMC(helper.begin_orbitIncTrig(), helper.end_orbitIncTrig(), CTF::BLC_orbitIncTrig, 0); + ENCODEEMC(helper.begin_entriesTrig(), helper.end_entriesTrig(), CTF::BLC_entriesTrig, 0); + + ENCODEEMC(helper.begin_towerID(), helper.end_towerID(), CTF::BLC_towerID, 0); + ENCODEEMC(helper.begin_time(), helper.end_time(), CTF::BLC_time, 0); + ENCODEEMC(helper.begin_energy(), helper.end_energy(), CTF::BLC_energy, 0); + ENCODEEMC(helper.begin_status(), helper.end_status(), CTF::BLC_status, 0); + // clang-format on + CTF::get(buff.data())->print(getPrefix()); +} + +/// decode entropy-encoded clusters to standard compact clusters +template <typename VTRG, typename VCELL> +void CTFCoder::decode(const CTF::base& ec, VTRG& trigVec, VCELL& cellVec) +{ + auto header = ec.getHeader(); + ec.print(getPrefix()); + std::vector<uint16_t> bcInc, entries, energy, cellTime, tower; + std::vector<uint32_t> orbitInc; + std::vector<uint8_t> status; + +#define DECODEEMCAL(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) + // clang-format off + DECODEEMCAL(bcInc, CTF::BLC_bcIncTrig); + DECODEEMCAL(orbitInc, CTF::BLC_orbitIncTrig); + DECODEEMCAL(entries, CTF::BLC_entriesTrig); + DECODEEMCAL(tower, CTF::BLC_towerID); + + DECODEEMCAL(cellTime, CTF::BLC_time); + DECODEEMCAL(energy, CTF::BLC_energy); + DECODEEMCAL(status, CTF::BLC_status); + // clang-format on + // + trigVec.clear(); + cellVec.clear(); + trigVec.reserve(header.nTriggers); + status.reserve(header.nCells); + + uint32_t firstEntry = 0, cellCount = 0; + o2::InteractionRecord ir(header.firstBC, header.firstOrbit); + + Cell cell; + for (uint32_t itrig = 0; itrig < header.nTriggers; itrig++) { + // restore TrigRecord + if (orbitInc[itrig]) { // non-0 increment => new orbit + ir.bc = bcInc[itrig]; // bcInc has absolute meaning + ir.orbit += orbitInc[itrig]; + } else { + ir.bc += bcInc[itrig]; + } + + firstEntry = cellVec.size(); + for (uint16_t ic = 0; ic < entries[itrig]; ic++) { + cell.setPacked(tower[cellCount], cellTime[cellCount], energy[cellCount], status[cellCount]); + cellVec.emplace_back(cell); + cellCount++; + } + trigVec.emplace_back(ir, firstEntry, entries[itrig]); + } + assert(cellCount == header.nCells); +} + +} // namespace emcal +} // namespace o2 + +#endif // O2_EMCAL_CTFCODER_H diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFHelper.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFHelper.h new file mode 100644 index 0000000000000..4589f217226d1 --- /dev/null +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFHelper.h @@ -0,0 +1,193 @@ +// 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 CTFHelper.h +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for EMCAL CTF creation + +#ifndef O2_EMCAL_CTF_HELPER_H +#define O2_EMCAL_CTF_HELPER_H + +#include "DataFormatsEMCAL/CTF.h" +#include <gsl/span> + +namespace o2 +{ +namespace emcal +{ + +class CTFHelper +{ + + public: + CTFHelper(const gsl::span<const TriggerRecord>& trgData, const gsl::span<const Cell>& cellData) + : mTrigData(trgData), mCellData(cellData) {} + + CTFHeader createHeader() + { + CTFHeader h{uint32_t(mTrigData.size()), uint32_t(mCellData.size()), 0, 0}; + if (mTrigData.size()) { + h.firstOrbit = mTrigData[0].getBCData().orbit; + h.firstBC = mTrigData[0].getBCData().bc; + } + return h; + } + + size_t getSize() const { return mTrigData.size() * sizeof(TriggerRecord) + mCellData.size() * sizeof(Cell); } + + //>>> =========================== ITERATORS ======================================== + + template <typename I, typename D, typename T> + class _Iter + { + public: + using difference_type = int64_t; + using value_type = T; + using pointer = const T*; + using reference = const T&; + using iterator_category = std::random_access_iterator_tag; + + _Iter(const gsl::span<const D>& data, bool end = false) : mData(data), mIndex(end ? data.size() : 0){}; + _Iter() = default; + + const I& operator++() + { + ++mIndex; + return (I&)(*this); + } + + const I& operator--() + { + mIndex--; + return (I&)(*this); + } + + difference_type operator-(const I& other) const { return mIndex - other.mIndex; } + + difference_type operator-(size_t idx) const { return mIndex - idx; } + + const I& operator-(size_t idx) + { + mIndex -= idx; + return (I&)(*this); + } + + bool operator!=(const I& other) const { return mIndex != other.mIndex; } + bool operator==(const I& other) const { return mIndex == other.mIndex; } + bool operator>(const I& other) const { return mIndex > other.mIndex; } + bool operator<(const I& other) const { return mIndex < other.mIndex; } + + protected: + gsl::span<const D> mData{}; + size_t mIndex = 0; + }; + + //_______________________________________________ + // BC difference wrt previous if in the same orbit, otherwise the abs.value. + // For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_bcIncTrig : public _Iter<Iter_bcIncTrig, TriggerRecord, uint16_t> + { + public: + using _Iter<Iter_bcIncTrig, TriggerRecord, uint16_t>::_Iter; + value_type operator*() const + { + if (mIndex) { + if (mData[mIndex].getBCData().orbit == mData[mIndex - 1].getBCData().orbit) { + return mData[mIndex].getBCData().bc - mData[mIndex - 1].getBCData().bc; + } else { + return mData[mIndex].getBCData().bc; + } + } + return 0; + } + }; + + //_______________________________________________ + // Orbit difference wrt previous. For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_orbitIncTrig : public _Iter<Iter_orbitIncTrig, TriggerRecord, uint32_t> + { + public: + using _Iter<Iter_orbitIncTrig, TriggerRecord, uint32_t>::_Iter; + value_type operator*() const { return mIndex ? mData[mIndex].getBCData().orbit - mData[mIndex - 1].getBCData().orbit : 0; } + }; + + //_______________________________________________ + // Number of cells for trigger + class Iter_entriesTrig : public _Iter<Iter_entriesTrig, TriggerRecord, uint16_t> + { + public: + using _Iter<Iter_entriesTrig, TriggerRecord, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getNumberOfObjects(); } + }; + + //_______________________________________________ + class Iter_towerID : public _Iter<Iter_towerID, Cell, uint16_t> + { + public: + using _Iter<Iter_towerID, Cell, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedTowerID(); } + }; + + //_______________________________________________ + class Iter_time : public _Iter<Iter_time, Cell, uint16_t> + { + public: + using _Iter<Iter_time, Cell, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedTime(); } + }; + + //_______________________________________________ + class Iter_energy : public _Iter<Iter_energy, Cell, uint16_t> + { + public: + using _Iter<Iter_energy, Cell, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedEnergy(); } + }; + + //_______________________________________________ + class Iter_status : public _Iter<Iter_status, Cell, uint8_t> + { + public: + using _Iter<Iter_status, Cell, uint8_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedCellStatus(); } + }; + + //<<< =========================== ITERATORS ======================================== + + Iter_bcIncTrig begin_bcIncTrig() const { return Iter_bcIncTrig(mTrigData, false); } + Iter_bcIncTrig end_bcIncTrig() const { return Iter_bcIncTrig(mTrigData, true); } + + Iter_orbitIncTrig begin_orbitIncTrig() const { return Iter_orbitIncTrig(mTrigData, false); } + Iter_orbitIncTrig end_orbitIncTrig() const { return Iter_orbitIncTrig(mTrigData, true); } + + Iter_entriesTrig begin_entriesTrig() const { return Iter_entriesTrig(mTrigData, false); } + Iter_entriesTrig end_entriesTrig() const { return Iter_entriesTrig(mTrigData, true); } + + Iter_towerID begin_towerID() const { return Iter_towerID(mCellData, false); } + Iter_towerID end_towerID() const { return Iter_towerID(mCellData, true); } + + Iter_time begin_time() const { return Iter_time(mCellData, false); } + Iter_time end_time() const { return Iter_time(mCellData, true); } + + Iter_energy begin_energy() const { return Iter_energy(mCellData, false); } + Iter_energy end_energy() const { return Iter_energy(mCellData, true); } + + Iter_status begin_status() const { return Iter_status(mCellData, false); } + Iter_status end_status() const { return Iter_status(mCellData, true); } + + private: + const gsl::span<const o2::emcal::TriggerRecord> mTrigData; + const gsl::span<const o2::emcal::Cell> mCellData; +}; + +} // namespace emcal +} // namespace o2 + +#endif diff --git a/Detectors/EMCAL/reconstruction/src/CTFCoder.cxx b/Detectors/EMCAL/reconstruction/src/CTFCoder.cxx new file mode 100644 index 0000000000000..3fc31aaea0a7a --- /dev/null +++ b/Detectors/EMCAL/reconstruction/src/CTFCoder.cxx @@ -0,0 +1,76 @@ +// 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 CTFCoder.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of EMCAL data + +#include "EMCALReconstruction/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::emcal; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) +{ + ec.appendToTree(tree, mDet.getName()); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Cell>& cellVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, mDet.getName(), entry); + decode(ec, trigVec, cellVec); +} + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + // just to get types + uint16_t bcInc = 0, entries = 0, cellTime = 0, energy = 0, tower = 0; + uint32_t orbitInc = 0; + uint8_t status = 0; +#define MAKECODER(part, slot) createCoder<decltype(part)>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(bcInc, CTF::BLC_bcIncTrig); + MAKECODER(orbitInc, CTF::BLC_orbitIncTrig); + MAKECODER(entries, CTF::BLC_entriesTrig); + MAKECODER(tower, CTF::BLC_towerID); + MAKECODER(cellTime, CTF::BLC_time); + MAKECODER(energy, CTF::BLC_energy); + MAKECODER(status, CTF::BLC_status); + // clang-format on +} diff --git a/Detectors/EMCAL/reconstruction/src/CTFHelper.cxx b/Detectors/EMCAL/reconstruction/src/CTFHelper.cxx new file mode 100644 index 0000000000000..1e0f385b72fce --- /dev/null +++ b/Detectors/EMCAL/reconstruction/src/CTFHelper.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. + +/// \file CTFHelper.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for EMCAL CTF creation + +#include "EMCALReconstruction/CTFHelper.h" diff --git a/Detectors/EMCAL/workflow/CMakeLists.txt b/Detectors/EMCAL/workflow/CMakeLists.txt index e26b42363121f..aac2708bddbbb 100644 --- a/Detectors/EMCAL/workflow/CMakeLists.txt +++ b/Detectors/EMCAL/workflow/CMakeLists.txt @@ -16,6 +16,8 @@ o2_add_library(EMCALWorkflow src/DigitsPrinterSpec.cxx src/AnalysisClusterSpec.cxx src/RawToCellConverterSpec.cxx + src/EntropyEncoderSpec.cxx + src/EntropyDecoderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsEMCAL O2::DPLUtils O2::EMCALBase O2::EMCALReconstruction O2::Algorithm) @@ -23,3 +25,8 @@ o2_add_executable(reco-workflow COMPONENT_NAME emcal SOURCES src/emc-reco-workflow.cxx PUBLIC_LINK_LIBRARIES O2::EMCALWorkflow) + +o2_add_executable(entropy-encoder-workflow + COMPONENT_NAME emcal + SOURCES src/entropy-encoder-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::EMCALWorkflow) diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyDecoderSpec.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..2273f60d5a1f6 --- /dev/null +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyDecoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to EMCAL digit/channels strean + +#ifndef O2_EMCAL_ENTROPYDECODER_SPEC +#define O2_EMCAL_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "EMCALReconstruction/CTFCoder.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace emcal +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::emcal::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace emcal +} // namespace o2 + +#endif diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyEncoderSpec.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..f0852d9367577 --- /dev/null +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/EntropyEncoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert EMCAL data to CTF (EncodedBlocks) + +#ifndef O2_EMCAL_ENTROPYENCODER_SPEC +#define O2_EMCAL_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> +#include "EMCALReconstruction/CTFCoder.h" + +namespace o2 +{ +namespace emcal +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::emcal::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace emcal +} // namespace o2 + +#endif diff --git a/Detectors/EMCAL/workflow/src/EntropyDecoderSpec.cxx b/Detectors/EMCAL/workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..dec7ed2f81cdd --- /dev/null +++ b/Detectors/EMCAL/workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "EMCALWorkflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace emcal +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("emcal-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& triggers = pc.outputs().make<std::vector<TriggerRecord>>(OutputRef{"triggers"}); + auto& cells = pc.outputs().make<std::vector<Cell>>(OutputRef{"cells"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::emcal::CTF::getImage(buff.data()); + mCTFCoder.decode(ctfImage, triggers, cells); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << cells.size() << " EMCAL cells in " << triggers.size() << " triggers in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "EMCAL Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"triggers"}, "EMC", "CELLSTRGR", 0, Lifetime::Timeframe}, + OutputSpec{{"cells"}, "EMC", "CELLS", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "emcal-entropy-decoder", + Inputs{InputSpec{"ctf", "EMC", "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{{"emcal-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; +} + +} // namespace emcal +} // namespace o2 diff --git a/Detectors/EMCAL/workflow/src/EntropyEncoderSpec.cxx b/Detectors/EMCAL/workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..b4372ed4d8186 --- /dev/null +++ b/Detectors/EMCAL/workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyEncoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "EMCALWorkflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace emcal +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("emcal-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto triggers = pc.inputs().get<gsl::span<TriggerRecord>>("triggers"); + auto cells = pc.inputs().get<gsl::span<Cell>>("cells"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"EMC", "CTFDATA", 0, Lifetime::Timeframe}); + mCTFCoder.encode(buffer, triggers, cells); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + // eeb->print(); + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for EMCAL in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "EMCAL Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("triggers", "EMC", "CELLSTRGR", 0, Lifetime::Timeframe); + inputs.emplace_back("cells", "EMC", "CELLS", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "emcal-entropy-encoder", + inputs, + Outputs{{"EMC", "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{{"emcal-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; +} + +} // namespace emcal +} // namespace o2 diff --git a/Detectors/EMCAL/workflow/src/entropy-encoder-workflow.cxx b/Detectors/EMCAL/workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..a6e34eddf3e95 --- /dev/null +++ b/Detectors/EMCAL/workflow/src/entropy-encoder-workflow.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. + +#include "EMCALWorkflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::emcal::getEntropyEncoderSpec()); + return wf; +} From b1fc5e735d637d16b2c334241148547690d42844 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 8 Nov 2020 12:02:05 +0100 Subject: [PATCH 1241/1751] Make EMCAL reco-workflow defaults consistent --- Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx b/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx index 53159b3345365..b4579e5848808 100644 --- a/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx +++ b/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx @@ -27,8 +27,8 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { std::vector<o2::framework::ConfigParamSpec> options{ - {"input-type", o2::framework::VariantType::String, "digits", {"digitizer, digits, raw, clusters"}}, - {"output-type", o2::framework::VariantType::String, "digits", {"digits, raw, clusters"}}, + {"input-type", o2::framework::VariantType::String, "digits", {"digits, cells, raw, clusters"}}, + {"output-type", o2::framework::VariantType::String, "cells", {"digits, cells, raw, clusters, analysisclusters"}}, {"enable-digits-printer", o2::framework::VariantType::Bool, false, {"enable digits printer component"}}, {"disable-root-input", o2::framework::VariantType::Bool, false, {"do not initialize root files readers"}}, {"disable-root-output", o2::framework::VariantType::Bool, false, {"do not initialize root file writers"}}, From 447c1a4984082b863b3fece2ae0d2b38ac7fec13 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 8 Nov 2020 12:02:56 +0100 Subject: [PATCH 1242/1751] Add EMCAL CTF I/O to CTFReader/Writer + unit test --- Detectors/CTF/CMakeLists.txt | 8 ++ Detectors/CTF/test/test_ctf_io_emcal.cxx | 120 ++++++++++++++++++ Detectors/CTF/workflow/CMakeLists.txt | 1 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 ++ Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 3 + .../CTF/workflow/src/ctf-reader-workflow.cxx | 4 + 6 files changed, 144 insertions(+) create mode 100644 Detectors/CTF/test/test_ctf_io_emcal.cxx diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index c0297405a0126..bd94549fcc201 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -57,3 +57,11 @@ o2_add_test(mid SOURCES test/test_ctf_io_mid.cxx COMPONENT_NAME ctf LABELS ctf) + +o2_add_test(emcal + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::DataFormatsEMCAL + O2::EMCALReconstruction + SOURCES test/test_ctf_io_emcal.cxx + COMPONENT_NAME ctf + LABELS ctf) diff --git a/Detectors/CTF/test/test_ctf_io_emcal.cxx b/Detectors/CTF/test/test_ctf_io_emcal.cxx new file mode 100644 index 0000000000000..205efd84f7d49 --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_emcal.cxx @@ -0,0 +1,120 @@ +// 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. + +#define BOOST_TEST_MODULE Test EMCCTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DetectorsCommonDataFormats/NameConf.h" +#include "EMCALReconstruction/CTFCoder.h" +#include "DataFormatsEMCAL/CTF.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <TSystem.h> +#include <cstring> + +using namespace o2::emcal; + +BOOST_AUTO_TEST_CASE(CTFTest) +{ + std::vector<TriggerRecord> triggers; + std::vector<Cell> cells; + // gSystem->Load("libO2DetectorsCommonDataFormats.so"); + TStopwatch sw; + sw.Start(); + o2::InteractionRecord ir(0, 0); + for (int irof = 0; irof < 1000; irof++) { + ir += 1 + gRandom->Integer(200); + + auto start = cells.size(); + short tower = gRandom->Poisson(10); + while (tower < 17665) { + float timeCell = gRandom->Rndm() * 1500 - 600.; + float en = gRandom->Rndm() * 250.; + int stat = gRandom->Integer(5); + cells.emplace_back(tower, en, timeCell, (ChannelType_t)stat); + tower += 1 + gRandom->Integer(100); + } + triggers.emplace_back(ir, start, cells.size() - start); + } + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + { + CTFCoder coder; + coder.encode(vec, triggers, cells); // compress + } + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + auto* ctfImage = o2::emcal::CTF::get(vec.data()); + TFile flOut("test_ctf_emcal.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "EMC"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + { + sw.Start(); + TFile flIn("test_ctf_emcal.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + o2::emcal::CTF::readFromTree(vec, *(tree.get()), "EMC"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<TriggerRecord> triggersD; + std::vector<Cell> cellsD; + + sw.Start(); + const auto ctfImage = o2::emcal::CTF::getImage(vec.data()); + { + CTFCoder coder; + coder.decode(ctfImage, triggersD, cellsD); // decompress + } + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + BOOST_CHECK(triggersD.size() == triggers.size()); + BOOST_CHECK(cellsD.size() == cells.size()); + LOG(INFO) << " BOOST_CHECK triggersD.size() " << triggersD.size() << " triggers.size() " << triggers.size() + << " BOOST_CHECK(cellsD.size() " << cellsD.size() << " cells.size()) " << cells.size(); + + for (size_t i = 0; i < triggers.size(); i++) { + const auto& dor = triggers[i]; + const auto& ddc = triggersD[i]; + LOG(DEBUG) << " Orig.TriggerRecord " << i << " " << dor.getBCData() << " " << dor.getFirstEntry() << " " << dor.getNumberOfObjects(); + LOG(DEBUG) << " Deco.TriggerRecord " << i << " " << ddc.getBCData() << " " << ddc.getFirstEntry() << " " << ddc.getNumberOfObjects(); + + BOOST_CHECK(dor.getBCData() == ddc.getBCData()); + BOOST_CHECK(dor.getNumberOfObjects() == ddc.getNumberOfObjects()); + BOOST_CHECK(dor.getFirstEntry() == dor.getFirstEntry()); + } + + for (size_t i = 0; i < cells.size(); i++) { + const auto& cor = cells[i]; + const auto& cdc = cellsD[i]; + BOOST_CHECK(cor.getPackedTowerID() == cdc.getPackedTowerID()); + BOOST_CHECK(cor.getPackedTime() == cdc.getPackedTime()); + BOOST_CHECK(cor.getPackedEnergy() == cdc.getPackedEnergy()); + BOOST_CHECK(cor.getPackedCellStatus() == cdc.getPackedCellStatus()); + } +} diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index b067550797317..746e8c12ee2b9 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -26,6 +26,7 @@ o2_add_library(CTFWorkflow O2::FV0Workflow O2::TOFWorkflow O2::MIDWorkflow + O2::EMCALWorkflow O2::Algorithm O2::CommonUtils) diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 0ee5a31257e24..2b5edde54d7c7 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -29,6 +29,7 @@ #include "DataFormatsFV0/CTF.h" #include "DataFormatsTOF/CTF.h" #include "DataFormatsMID/CTF.h" +#include "DataFormatsEMCAL/CTF.h" #include "Algorithm/RangeTokenizer.h" using namespace o2::framework; @@ -157,6 +158,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::EMC; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::emcal::CTF)); + o2::emcal::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + mTimer.Stop(); LOG(INFO) << "Read CTF " << inputFile << " in " << mTimer.CpuTime() - cput << " s"; diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 127d913c229bb..7b135edc2cfbd 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -26,6 +26,7 @@ #include "DataFormatsFV0/CTF.h" #include "DataFormatsTOF/CTF.h" #include "DataFormatsMID/CTF.h" +#include "DataFormatsEMCAL/CTF.h" using namespace o2::framework; @@ -100,6 +101,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) processDet<o2::ft0::CTF>(pc, DetID::FT0, header, treeOut.get()); processDet<o2::fv0::CTF>(pc, DetID::FV0, header, treeOut.get()); processDet<o2::mid::CTF>(pc, DetID::MID, header, treeOut.get()); + processDet<o2::emcal::CTF>(pc, DetID::EMC, header, treeOut.get()); mTimer.Stop(); @@ -168,6 +170,7 @@ void CTFWriterSpec::storeDictionaries() storeDictionary<o2::ft0::CTF>(DetID::FT0, header); storeDictionary<o2::fv0::CTF>(DetID::FV0, header); storeDictionary<o2::mid::CTF>(DetID::MID, header); + storeDictionary<o2::emcal::CTF>(DetID::EMC, header); // close remnants if (mDictTreeOut) { closeDictionaryTreeAndFile(header); diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index ab255537b9dc7..be564efa94034 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -26,6 +26,7 @@ #include "FV0Workflow/EntropyDecoderSpec.h" #include "TOFWorkflowUtils/EntropyDecoderSpec.h" #include "MIDWorkflow/EntropyDecoderSpec.h" +#include "EMCALWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -88,6 +89,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets[DetID::MID]) { specs.push_back(o2::mid::getEntropyDecoderSpec()); } + if (dets[DetID::EMC]) { + specs.push_back(o2::emcal::getEntropyDecoderSpec()); + } return std::move(specs); } From bf3f99f9c13c5a3a36fdb0e3a801cc5f660c2135 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Sun, 8 Nov 2020 20:00:27 +0100 Subject: [PATCH 1243/1751] full_system_test: Remove spurious symbol --- prodtests/full_system_test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 52d1a0ce44514..8a0a4f8565022 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -86,10 +86,10 @@ o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | o2-ft0-entropy-encoder-workflow $ARGS_ALL | o2-tpcits-match-workflow $ARGS_ALL -b --disable-root-input --disable-root-output ${NOMCLABELS} | -o2-mid-raw-to-digits-workflow $ARGS_ALL | \ +o2-mid-raw-to-digits-workflow $ARGS_ALL | o2-mid-reco-workflow $ARGS_ALL --disable-root-output | -o2-mid-entropy-encoder-workflow $ARGS_ALL | -o2-tof-compressor $ARGS_ALL | +o2-mid-entropy-encoder-workflow $ARGS_ALL | +o2-tof-compressor $ARGS_ALL | o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output ${NOMCLABELS} | o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input --shm-segment-size $SHMSIZE ${GLOBALDPLOPT}" From 2798b867b50ebc47b99513f7a1da8d6c2ed6bc5d Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 9 Nov 2020 01:48:27 +0100 Subject: [PATCH 1244/1751] fix in p.vertex - tracks matcher initialization --- .../src/primary-vertexing-workflow.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx index 6b8a06d649c60..67e6ae1e43f2c 100644 --- a/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/primary-vertexing-workflow.cxx @@ -65,9 +65,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } specs.emplace_back(o2::vertexing::getPrimaryVertexingSpec(validateWithFT0, useMC)); - if (!disableMatching && !disableRootInp) { - specs.emplace_back(o2::its::getITSTrackReaderSpec(false)); - specs.emplace_back(o2::tpc::getTPCTrackReaderSpec(false)); + if (!disableMatching) { + if (!disableRootInp) { + specs.emplace_back(o2::its::getITSTrackReaderSpec(false)); + specs.emplace_back(o2::tpc::getTPCTrackReaderSpec(false)); + } specs.emplace_back(o2::vertexing::getVertexTrackMatcherSpec()); } From 70df500ee56e4403c502ba99cbbf30c2af4c30e5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 3 Nov 2020 10:03:21 +0100 Subject: [PATCH 1245/1751] GPU: Remove obsolete display and QA config files (were left when configuration was refactored) --- GPU/GPUTracking/Base/GPUSettingsList.h | 6 ++-- GPU/GPUTracking/CMakeLists.txt | 2 -- .../Interface/GPUO2InterfaceConfiguration.h | 6 ++-- .../Standalone/display/GPUDisplay.cxx | 6 ++-- .../Standalone/display/GPUDisplay.h | 8 ++--- .../Standalone/display/GPUDisplayConfig.h | 29 ------------------- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 6 ++-- GPU/GPUTracking/Standalone/qa/GPUQA.h | 8 ++--- GPU/GPUTracking/Standalone/qa/GPUQAConfig.h | 29 ------------------- GPU/GPUTracking/Standalone/qconfigoptions.h | 2 ++ 10 files changed, 18 insertions(+), 84 deletions(-) delete mode 100644 GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h delete mode 100644 GPU/GPUTracking/Standalone/qa/GPUQAConfig.h diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index bb46fb652c380..a368a4e8cb6e3 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -19,7 +19,9 @@ // Create static constexpr with default values for GPU run time compilation #include "GPUDefConstantsAndSettings.h" -#include "GPUSettings.h" +#ifndef GPUSETTINGS_H +#error Please include GPUSettings.h! +#endif // clang-format off @@ -284,5 +286,5 @@ EndConfig() EndNamespace() // gpu EndNamespace() // GPUCA_NAMESPACE -#endif +#endif // #ifdef BeginNamespace // clang-format on diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index afa465d8e025c..43e6d89e2a4f2 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -109,8 +109,6 @@ set(HDRS_INSTALL TRDTracking/GPUTRDGeometry.h TRDTracking/GPUTRDTrackerDebug.h TRDTracking/GPUTRDInterfaces.h - Standalone/display/GPUDisplayConfig.h - Standalone/qa/GPUQAConfig.h Base/GPUConstantMem.h Base/GPUReconstructionKernels.h Base/GPUReconstructionIncludesITS.h diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index 5e14f54075c94..eac5c9d7363ec 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -30,8 +30,6 @@ #include <functional> #include <gsl/gsl> #include "GPUSettings.h" -#include "GPUDisplayConfig.h" -#include "GPUQAConfig.h" #include "GPUDataTypes.h" #include "GPUHostDataTypes.h" #include "DataFormatsTPC/Constants.h" @@ -89,8 +87,8 @@ struct GPUO2InterfaceConfiguration { GPUSettingsProcessing configProcessing; GPUSettingsEvent configEvent; GPUSettingsRec configReconstruction; - GPUDisplayConfig configDisplay; - GPUQAConfig configQA; + GPUSettingsDisplay configDisplay; + GPUSettingsQA configQA; GPUInterfaceSettings configInterface; GPURecoStepConfiguration configWorkflow; GPUCalibObjects configCalib; diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 27eb381b83b41..91d5aad5f2fdf 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -84,12 +84,12 @@ namespace GPUCA_NAMESPACE::gpu extern GPUSettingsStandalone configStandalone; } #endif -static const GPUDisplay::configDisplay& GPUDisplay_GetConfig(GPUChainTracking* rec) +static const GPUSettingsDisplay& GPUDisplay_GetConfig(GPUChainTracking* rec) { #if !defined(GPUCA_STANDALONE) - static GPUDisplay::configDisplay defaultConfig; + static GPUSettingsDisplay defaultConfig; if (rec->mConfigDisplay) { - return *((const GPUDisplay::configDisplay*)rec->mConfigDisplay); + return *((const GPUSettingsDisplay*)rec->mConfigDisplay); } else { return defaultConfig; } diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.h b/GPU/GPUTracking/Standalone/display/GPUDisplay.h index 036f414c56c9f..8f0efea771780 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.h @@ -32,7 +32,7 @@ #endif #endif -#include "GPUDisplayConfig.h" +#include "GPUSettings.h" #include "GPUDisplayBackend.h" namespace GPUCA_NAMESPACE @@ -57,8 +57,6 @@ class GPUDisplay ~GPUDisplay() = default; GPUDisplay(const GPUDisplay&) = delete; - typedef GPUDisplayConfig configDisplay; - int StartDisplay() { return 1; } void ShowNextEvent() {} void WaitForNextEvent() {} @@ -100,8 +98,6 @@ class GPUDisplay ~GPUDisplay() = default; GPUDisplay(const GPUDisplay&) = delete; - typedef GPUDisplayConfig configDisplay; - int StartDisplay(); void ShowNextEvent(); void WaitForNextEvent(); @@ -297,7 +293,7 @@ class GPUDisplay GPUDisplayBackend* mBackend; GPUChainTracking* mChain; - const configDisplay& mConfig; + const GPUSettingsDisplay& mConfig; OpenGLConfig mCfg; GPUQA* mQA; const GPUTPCGMMerger& mMerger; diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h b/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h deleted file mode 100644 index b4d44813e490c..0000000000000 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayConfig.h +++ /dev/null @@ -1,29 +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. - -/// \file GPUDisplayConfig.h -/// \author David Rohr - -#ifndef GPUDISPLAYCONFIG_H -#define GPUDISPLAYCONFIG_H - -#include "GPUCommonDef.h" - -#include "utils/qconfig.h" - -namespace GPUCA_NAMESPACE -{ -namespace gpu -{ -typedef GPUSettingsDisplay GPUDisplayConfig; -} -} // namespace GPUCA_NAMESPACE - -#endif diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 06bbe54520c97..298c5f46ee310 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -119,12 +119,12 @@ namespace GPUCA_NAMESPACE::gpu extern GPUSettingsStandalone configStandalone; } #endif -static const GPUQA::configQA& GPUQA_GetConfig(GPUChainTracking* rec) +static const GPUSettingsQA& GPUQA_GetConfig(GPUChainTracking* rec) { #if !defined(GPUCA_STANDALONE) - static GPUQA::configQA defaultConfig; + static GPUSettingsQA defaultConfig; if (rec->mConfigQA) { - return *((const GPUQA::configQA*)rec->mConfigQA); + return *((const GPUSettingsQA*)rec->mConfigQA); } else { return defaultConfig; } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index b35d52579b26e..df2e8b0e4a6eb 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -14,7 +14,7 @@ #ifndef GPUQA_H #define GPUQA_H -#include "GPUQAConfig.h" +#include "GPUSettings.h" struct AliHLTTPCClusterMCWeight; class TH1F; class TH2F; @@ -41,8 +41,6 @@ class GPUQA GPUQA(GPUChainTracking* rec) {} ~GPUQA() = default; - typedef GPUQAConfig configQA; - int InitQA() { return 1; } void RunQA(bool matchOnly = false) {} int DrawQAHistograms() { return 1; } @@ -85,8 +83,6 @@ class GPUQA GPUQA(GPUChainTracking* rec); ~GPUQA(); - typedef GPUQAConfig configQA; - int InitQA(); void RunQA(bool matchOnly = false); int DrawQAHistograms(); @@ -172,7 +168,7 @@ class GPUQA static bool MCComp(const mcLabel_t& a, const mcLabel_t& b); GPUChainTracking* mTracking; - const configQA& mConfig; + const GPUSettingsQA& mConfig; //-------------------------: Some compile time settings.... static const constexpr bool PLOT_ROOT = 0; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h b/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h deleted file mode 100644 index 97d9ba5622945..0000000000000 --- a/GPU/GPUTracking/Standalone/qa/GPUQAConfig.h +++ /dev/null @@ -1,29 +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. - -/// \file GPUQAConfig.h -/// \author David Rohr - -#ifndef GPUQACONFIG_H -#define GPUQACONFIG_H - -#include "GPUCommonDef.h" - -#include "utils/qconfig.h" - -namespace GPUCA_NAMESPACE -{ -namespace gpu -{ -typedef GPUSettingsQA GPUQAConfig; -} -} // namespace GPUCA_NAMESPACE - -#endif diff --git a/GPU/GPUTracking/Standalone/qconfigoptions.h b/GPU/GPUTracking/Standalone/qconfigoptions.h index 42486f7bc75d2..5c44f007ffd47 100644 --- a/GPU/GPUTracking/Standalone/qconfigoptions.h +++ b/GPU/GPUTracking/Standalone/qconfigoptions.h @@ -11,4 +11,6 @@ /// \file qconfigoptions.h /// \author David Rohr +#include "GPUSettings.h" // Usually we are included from GPUSettings.h, so this doesn't do anything. + // But ROOT or qconfig.cpp will include us directly, so load the settings first. #include "GPUSettingsList.h" From a1b7c584d4e27c35aaf9ba1a57a83abc34756e5d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 3 Nov 2020 14:42:25 +0100 Subject: [PATCH 1246/1751] GPU: Fix standalone compilation without availability of O2 headers --- GPU/GPUTracking/Standalone/CMakeLists.txt | 2 +- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 2 ++ GPU/GPUTracking/dEdx/GPUdEdx.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 5b6075108ca19..0168de0e5c4ad 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -115,12 +115,12 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/Refit ${CMAKE_SOURCE_DIR}/qa ${CMAKE_SOURCE_DIR}/SliceTracker + ${CMAKE_SOURCE_DIR}/DataCompression ${CMAKE_SOURCE_DIR}/TRDTracking) if(CONFIG_O2_EXTENSIONS) include_directories(${CMAKE_SOURCE_DIR}/TPCClusterFinder ${CMAKE_SOURCE_DIR}/ITS - ${CMAKE_SOURCE_DIR}/DataCompression ${CMAKE_SOURCE_DIR}/../../../Common/Field/include ${CMAKE_SOURCE_DIR}/../../../Common/Constants/include ${CMAKE_SOURCE_DIR}/../../../Common/MathUtils/include diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 91d5aad5f2fdf..bf32ad254f192 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -1135,6 +1135,7 @@ GPUDisplay::vboList GPUDisplay::DrawGridTRD(int sector) // TODO: tilted pads ignored at the moment size_t startCount = mVertexBufferStart[sector].size(); size_t startCountInner = mVertexBuffer[sector].size(); +#ifdef HAVE_O2HEADERS auto* geo = mChain->GetTRDGeometry(); if (geo) { int trdsector = NSLICES / 2 - 1 - sector; @@ -1193,6 +1194,7 @@ GPUDisplay::vboList GPUDisplay::DrawGridTRD(int sector) } } } +#endif insertVertexList(sector, startCountInner, mVertexBuffer[sector].size()); return (vboList(startCount, mVertexBufferStart[sector].size() - startCount, sector)); } diff --git a/GPU/GPUTracking/dEdx/GPUdEdx.h b/GPU/GPUTracking/dEdx/GPUdEdx.h index 63a2f1f002b9d..b3d2406171984 100644 --- a/GPU/GPUTracking/dEdx/GPUdEdx.h +++ b/GPU/GPUTracking/dEdx/GPUdEdx.h @@ -19,7 +19,7 @@ #include "GPUCommonMath.h" #include "GPUParam.h" #include "GPUdEdxInfo.h" -#ifndef GPUCA_ALIROOT_LIB +#ifdef HAVE_O2HEADERS #include "TPCdEdxCalibrationSplines.h" #endif From ca5d573a9e0a274c2500eadafec7d41d254b0f01 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 3 Nov 2020 12:30:47 +0100 Subject: [PATCH 1247/1751] GPU: Pass in part of GPUParam as static constexpr for GPU RTC compilation --- GPU/GPUTracking/Base/GPUParam.cxx | 28 ++-- GPU/GPUTracking/Base/GPUParam.h | 22 ++-- GPU/GPUTracking/Base/GPUParamRTC.h | 43 +++++++ GPU/GPUTracking/Base/GPUReconstruction.cxx | 3 + .../Base/GPUReconstructionIncludesDevice.h | 1 - GPU/GPUTracking/Base/GPUSettings.h | 2 + GPU/GPUTracking/Base/GPUSettingsList.h | 88 ++++++------- .../Base/cuda/GPUReconstructionCUDA.cu | 19 +++ GPU/GPUTracking/CMakeLists.txt | 1 + .../GPUO2InterfaceConfigurableParam.cxx | 12 ++ .../GPUO2InterfaceConfigurableParam.h | 7 + GPU/GPUTracking/Standalone/utils/qconfig.cxx | 29 +---- GPU/GPUTracking/Standalone/utils/qconfig.h | 120 +++++++++++++----- .../Standalone/utils/qconfig_helpers.h | 46 +++++++ GPU/GPUTracking/Standalone/utils/qconfigrtc.h | 39 ++++++ 15 files changed, 340 insertions(+), 120 deletions(-) create mode 100644 GPU/GPUTracking/Base/GPUParamRTC.h create mode 100644 GPU/GPUTracking/Standalone/utils/qconfig_helpers.h create mode 100644 GPU/GPUTracking/Standalone/utils/qconfigrtc.h diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index d3037cd8ef14e..82765e92f8175 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -12,6 +12,7 @@ /// \author David Rohr, Sergey Gorbunov #include "GPUParam.h" +#include "GPUParamRTC.h" #include "GPUDef.h" #include "GPUCommonMath.h" #include "GPUTPCGMPolynomialFieldManager.h" @@ -19,14 +20,15 @@ using namespace GPUCA_NAMESPACE::gpu; -#if !defined(GPUCA_GPUCODE) && defined(GPUCA_ALIROOT_LIB) +#ifdef GPUCA_ALIROOT_LIB #include "AliTPCClusterParam.h" #include "AliTPCcalibDB.h" #include <iostream> #endif - -#if !defined(GPUCA_GPUCODE) #include <cstring> +#include <tuple> + +#include "utils/qconfigrtc.h" void GPUParam::SetDefaults(float solenoidBz) { @@ -155,10 +157,7 @@ void GPUParam::SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r, c UpdateEventSettings(e, p); } -#endif - -#if !defined(GPUCA_GPUCODE) -#if !defined(GPUCA_ALIROOT_LIB) +#ifndef GPUCA_ALIROOT_LIB void GPUParam::LoadClusterErrors(bool Print) { } @@ -235,4 +234,17 @@ void GPUParam::LoadClusterErrors(bool Print) } } #endif -#endif + +void GPUParamRTC::setFrom(const GPUParam& param) +{ + memcpy((char*)this + sizeof(gpu_rtc::GPUSettingsRec), (char*)¶m + sizeof(GPUSettingsRec), sizeof(param) - sizeof(GPUSettingsRec)); + qConfigConvertRtc(this->rec, param.rec); +} + +std::string GPUParamRTC::generateRTCCode(const GPUParam& param, bool useConstexpr) +{ + return "namespace o2::gpu { class GPUDisplayBackend; }\n" + qConfigPrintRtc(std::make_tuple(¶m.rec), useConstexpr); +} + +static_assert(alignof(o2::gpu::GPUParam) == alignof(o2::gpu::GPUSettingsRec)); +static_assert(sizeof(o2::gpu::GPUParam) - sizeof(o2::gpu::GPUParamRTC) == sizeof(o2::gpu::GPUSettingsRec) - sizeof(o2::gpu::gpu_rtc::GPUSettingsRec)); diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index 0cc23fdb70f1c..a80c91e084df6 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -36,10 +36,11 @@ struct GPUParamSlice { float ZMin, ZMax; // slice Z range }; -MEM_CLASS_PRE() -struct GPUParam { - public: - GPUSettingsRec rec; +namespace internal +{ +template <class T> +struct GPUParam_t { + T rec; float DAlpha; // angular size float RMin, RMax; // slice R range @@ -61,6 +62,15 @@ struct GPUParam { GPUParamSlice SliceParam[GPUCA_NSLICES]; + protected: + float ParamRMS0[2][3][4]; // cluster shape parameterization coeficients + float ParamS0Par[2][3][6]; // cluster error parameterization coeficients +}; +} // namespace internal + +MEM_CLASS_PRE() +struct GPUParam : public internal::GPUParam_t<GPUSettingsRec> { + #ifndef GPUCA_GPUCODE void SetDefaults(float solenoidBz); void SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r = nullptr, const GPUSettingsProcessing* p = nullptr, const GPURecoStepConfiguration* w = nullptr); @@ -87,10 +97,6 @@ struct GPUParam { GPUd() void Slice2Global(int iSlice, float x, float y, float z, float* X, float* Y, float* Z) const; GPUd() void Global2Slice(int iSlice, float x, float y, float z, float* X, float* Y, float* Z) const; - - protected: - float ParamRMS0[2][3][4]; // cluster shape parameterization coeficients - float ParamS0Par[2][3][6]; // cluster error parameterization coeficients }; } // namespace gpu diff --git a/GPU/GPUTracking/Base/GPUParamRTC.h b/GPU/GPUTracking/Base/GPUParamRTC.h new file mode 100644 index 0000000000000..fe32522d94e8b --- /dev/null +++ b/GPU/GPUTracking/Base/GPUParamRTC.h @@ -0,0 +1,43 @@ +// 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 GPUParamRTC.h +/// \author David Rohr + +#ifndef GPUPARAMRTC_H +#define GPUPARAMRTC_H + +#include "GPUParam.h" +#include <string> + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ +namespace gpu_rtc +{ +#define QCONFIG_GENRTC +#define BeginNamespace(...) +#define EndNamespace(...) +#include "utils/qconfig.h" +#undef QCONFIG_GENRTC +#undef BeginNamespace +#undef EndNamespace +} // namespace gpu_rtc + +struct GPUParamRTC : public internal::GPUParam_t<gpu_rtc::GPUSettingsRec> { + void setFrom(const GPUParam& param); + static std::string generateRTCCode(const GPUParam& param, bool useConstexpr); +}; + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 95a5709959227..3bf1c47e157dc 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -255,6 +255,9 @@ int GPUReconstruction::InitPhaseBeforeDevice() if (!mProcessingSettings.trackletConstructorInPipeline) { mProcessingSettings.trackletSelectorInPipeline = false; } + if (!mProcessingSettings.enableRTC) { + mProcessingSettings.rtcConstexpr = false; + } mMemoryScalers->factor = mProcessingSettings.memoryScalingFactor; diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h index 2b946e254c6c9..a6aa6d19e8245 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h @@ -28,7 +28,6 @@ using namespace GPUCA_NAMESPACE::gpu; #include "GPUTPCTrack.cxx" #include "GPUTPCGrid.cxx" #include "GPUTPCRow.cxx" -#include "GPUParam.cxx" #include "GPUTPCTracker.cxx" #include "GPUGeneralKernels.cxx" diff --git a/GPU/GPUTracking/Base/GPUSettings.h b/GPU/GPUTracking/Base/GPUSettings.h index 00f03ebaba744..5b7bda9d647ca 100644 --- a/GPU/GPUTracking/Base/GPUSettings.h +++ b/GPU/GPUTracking/Base/GPUSettings.h @@ -74,6 +74,8 @@ struct GPUSettingsDeviceBackend { #define QCONFIG_GPU #endif // See GPUSettingsList.h for a list of all available settings of GPU Reconstruction +#ifndef GPUCA_GPUCODE_GENRTC #include "utils/qconfig.h" +#endif #endif diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index a368a4e8cb6e3..327469ef4525a 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -35,50 +35,51 @@ BeginNamespace(gpu) // Settings concerning the reconstruction // There must be no bool in here, use char, as sizeof(bool) is compiler dependent and fails on GPUs!!!!!! BeginSubConfig(GPUSettingsRec, rec, configStandalone, "REC", 0, "Reconstruction settings") -AddOption(tpcRejectQPt, float, 1.f / 0.05f, "", 0, "QPt threshold to reject clusters of TPC tracks (Inverse Pt!!!)") -AddOption(HitPickUpFactor, float, 2., "", 0, "multiplier for the chi2 window for hit pick up procedure") -AddOption(NeighboursSearchArea, float, 3., "", 0, "area in cm for the search of neighbours") -AddOption(ClusterError2CorrectionY, float, 1., "", 0, "correction for the squared cluster error during tracking") -AddOption(ClusterError2CorrectionZ, float, 1., "", 0, "correction for the squared cluster error during tracking") -AddOption(MinNTrackClusters, int, -1, "", 0, "required min number of clusters on the track") -AddOption(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required max Q/Pt (==min Pt) of tracks") -AddOption(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") -AddOption(TrackReferenceX, float, 1000.f, "", 0, "Transport all tracks to this X after tracking (disabled if > 500, auto = 1000)") -AddOption(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") -AddOption(tpcTubeChi2, float, 5.f * 5.f, "", 0, "Max chi2 to mark cluster adjacent to track") -AddOption(tpcTubeMaxSize2, float, 2.5f * 2.5f, "", 0, "Square of max tube size (normally derrived from tpcTubeChi2)") -AddOption(tpcCFqmaxCutoff, unsigned char, 3, "", 0, "Cluster Finder rejects cluster with qmax below this threshold") -AddOption(tpcCFqtotCutoff, unsigned char, 0, "", 0, "Cluster Finder rejects cluster with qtot below this threshold") -AddOption(tpcCFinnerThreshold, unsigned char, 0, "", 0, "Cluster Finder extends cluster if inner charge above this threshold") -AddOption(tpcCFminSplitNum, unsigned char, 1, "", 0, "Minimum number of split charges in a cluster for the cluster to be marked as split") -AddOption(tpcCFnoiseSuppressionEpsilon, unsigned char, 10, "", 0, "Cluster Finder: Difference between peak and charge for the charge to count as a minima during noise suppression") -AddOption(NWays, char, 3, "", 0, "Do N fit passes in final fit of merger") -AddOption(NWaysOuter, char, 0, "", 0, "Store outer param") -AddOption(RejectMode, char, 5, "", 0, "0: no limit on rejection or missed hits, >0: break after n rejected hits, <0: reject at max -n hits") -AddOption(NonConsecutiveIDs, char, false, "", 0, "Non-consecutive cluster IDs as in HLT, disables features that need access to slice data in TPC merger") -AddOption(dEdxTruncLow, unsigned char, 2, "", 0, "Low truncation threshold, fraction of 128") -AddOption(dEdxTruncHigh, unsigned char, 77, "", 0, "High truncation threshold, fraction of 128") -AddOption(GlobalTracking, char, 1, "", 0, "Enable Global Tracking (prolong tracks to adjacent sectors to find short segments)") -AddOption(DisableRefitAttachment, unsigned char, 0, "", 0, "Bitmask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") -AddOption(tpcRejectionMode, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression (0 = no, 1 = strategy A, 2 = strategy B)") -AddOption(tpcMergeLoopersAfterburner, unsigned char, 0, "", 0, "Run afterburner for additional looper merging") -AddOption(tpcCompressionModes, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") -AddOption(tpcCompressionSortOrder, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") -AddOption(tpcSigBitsCharge, unsigned char, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") -AddOption(tpcSigBitsWidth, unsigned char, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") -AddOption(ForceEarlyTPCTransform, char, -1, "", 0, "Force early TPC transformation also for continuous data (-1 = auto)") -AddOption(fwdTPCDigitsAsClusters, unsigned char, 0, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") -AddOption(bz0Pt, unsigned char, 60, "", 0, "Nominal Pt to set when bz = 0 (in 10 MeV)") -AddOption(dropLoopers, unsigned char, 0, "", 0, "Drop looping tracks starting from second loop") -AddOption(mergerCovSource, unsigned char, 2, "", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following, 2 = refit") -AddOption(mergerInterpolateErrors, unsigned char, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") -AddOption(fitInProjections, char, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") -AddOption(fitPropagateBzOnly, char, -1, "", 0, "Propagate using Bz only for n passes") -AddOption(retryRefit, char, 1, "", 0, "Retry refit when fit fails") -AddOption(loopInterpolationInExtraPass, char, -1, "", 0, "Perform loop interpolation in an extra pass") -AddOption(mergerReadFromTrackerDirectly, char, 1, "", 0, "Forward data directly from tracker to merger on GPU") -AddOption(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") +AddOptionRTC(tpcRejectQPt, float, 1.f / 0.05f, "", 0, "QPt threshold to reject clusters of TPC tracks (Inverse Pt!!!)") +AddOptionRTC(HitPickUpFactor, float, 2., "", 0, "multiplier for the chi2 window for hit pick up procedure") +AddOptionRTC(NeighboursSearchArea, float, 3., "", 0, "area in cm for the search of neighbours") +AddOptionRTC(ClusterError2CorrectionY, float, 1., "", 0, "correction for the squared cluster error during tracking") +AddOptionRTC(ClusterError2CorrectionZ, float, 1., "", 0, "correction for the squared cluster error during tracking") +AddOptionRTC(MinNTrackClusters, int, -1, "", 0, "required min number of clusters on the track") +AddOptionRTC(MaxTrackQPt, float, 1.f / GPUCA_MIN_TRACK_PT_DEFAULT, "", 0, "required max Q/Pt (==min Pt) of tracks") +AddOptionRTC(SearchWindowDZDR, float, 2.5, "", 0, "Use DZDR window for seeding instead of vertex window") +AddOptionRTC(TrackReferenceX, float, 1000.f, "", 0, "Transport all tracks to this X after tracking (disabled if > 500, auto = 1000)") +AddOptionRTC(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") +AddOptionRTC(tpcTubeChi2, float, 5.f * 5.f, "", 0, "Max chi2 to mark cluster adjacent to track") +AddOptionRTC(tpcTubeMaxSize2, float, 2.5f * 2.5f, "", 0, "Square of max tube size (normally derrived from tpcTubeChi2)") +AddOptionRTC(tpcCFqmaxCutoff, unsigned char, 3, "", 0, "Cluster Finder rejects cluster with qmax below this threshold") +AddOptionRTC(tpcCFqtotCutoff, unsigned char, 0, "", 0, "Cluster Finder rejects cluster with qtot below this threshold") +AddOptionRTC(tpcCFinnerThreshold, unsigned char, 0, "", 0, "Cluster Finder extends cluster if inner charge above this threshold") +AddOptionRTC(tpcCFminSplitNum, unsigned char, 1, "", 0, "Minimum number of split charges in a cluster for the cluster to be marked as split") +AddOptionRTC(tpcCFnoiseSuppressionEpsilon, unsigned char, 10, "", 0, "Cluster Finder: Difference between peak and charge for the charge to count as a minima during noise suppression") +AddOptionRTC(NWays, char, 3, "", 0, "Do N fit passes in final fit of merger") +AddOptionRTC(NWaysOuter, char, 0, "", 0, "Store outer param") +AddOptionRTC(RejectMode, char, 5, "", 0, "0: no limit on rejection or missed hits, >0: break after n rejected hits, <0: reject at max -n hits") +AddOptionRTC(NonConsecutiveIDs, char, false, "", 0, "Non-consecutive cluster IDs as in HLT, disables features that need access to slice data in TPC merger") +AddOptionRTC(dEdxTruncLow, unsigned char, 2, "", 0, "Low truncation threshold, fraction of 128") +AddOptionRTC(dEdxTruncHigh, unsigned char, 77, "", 0, "High truncation threshold, fraction of 128") +AddOptionRTC(GlobalTracking, char, 1, "", 0, "Enable Global Tracking (prolong tracks to adjacent sectors to find short segments)") +AddOptionRTC(DisableRefitAttachment, unsigned char, 0, "", 0, "Bitmask to disable certain attachment steps during refit (1: attachment, 2: propagation, 4: loop following, 8: mirroring)") +AddOptionRTC(tpcRejectionMode, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression (0 = no, 1 = strategy A, 2 = strategy B)") +AddOptionRTC(tpcMergeLoopersAfterburner, unsigned char, 0, "", 0, "Run afterburner for additional looper merging") +AddOptionRTC(tpcCompressionModes, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits (1=truncate charge/width LSB, 2=differences, 4=track-model)") +AddOptionRTC(tpcCompressionSortOrder, unsigned char, GPUCA_NAMESPACE::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression (0 = time, 1 = pad, 2 = Z-time-pad, 3 = Z-pad-time, 4 = no sorting (use incoming order))") +AddOptionRTC(tpcSigBitsCharge, unsigned char, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") +AddOptionRTC(tpcSigBitsWidth, unsigned char, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") +AddOptionRTC(ForceEarlyTPCTransform, char, -1, "", 0, "Force early TPC transformation also for continuous data (-1 = auto)") +AddOptionRTC(fwdTPCDigitsAsClusters, unsigned char, 0, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") +AddOptionRTC(bz0Pt, unsigned char, 60, "", 0, "Nominal Pt to set when bz = 0 (in 10 MeV)") +AddOptionRTC(dropLoopers, unsigned char, 0, "", 0, "Drop looping tracks starting from second loop") +AddOptionRTC(mergerCovSource, unsigned char, 2, "", 0, "Method to obtain covariance in track merger: 0 = simple filterErrors method, 1 = use cov from track following, 2 = refit") +AddOptionRTC(mergerInterpolateErrors, unsigned char, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") +AddOptionRTC(fitInProjections, char, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") +AddOptionRTC(fitPropagateBzOnly, char, -1, "", 0, "Propagate using Bz only for n passes") +AddOptionRTC(retryRefit, char, 1, "", 0, "Retry refit when fit fails") +AddOptionRTC(loopInterpolationInExtraPass, char, -1, "", 0, "Perform loop interpolation in an extra pass") +AddOptionRTC(mergerReadFromTrackerDirectly, char, 1, "", 0, "Forward data directly from tracker to merger on GPU") +AddOptionRTC(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") AddCustomCPP(void SetMinTrackPt(float v) { MaxTrackQPt = v > 0.001 ? (1. / v) : (1. / 0.001); }) +AddVariable(dummyRTC, float, 0.f) // Ensure non empty struct and proper alignment even if all normal members are constexpr AddHelp("help", 'h') EndConfig() @@ -126,6 +127,7 @@ AddOption(registerStandaloneInputMemory, bool, false, "registerInputMemory", 0, 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") +AddOption(rtcConstexpr, bool, true, "", 0, "Replace constant variables by static constexpr expressions") AddOption(showOutputStat, bool, false, "", 0, "Print some track output statistics") AddVariable(eventDisplay, GPUCA_NAMESPACE::gpu::GPUDisplayBackend*, nullptr) AddHelp("help", 'h') diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 0e0d0636b1e4a..a8fdc867b1480 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -20,6 +20,7 @@ #include "GPUReconstructionCUDA.h" #include "GPUReconstructionCUDAInternals.h" #include "GPUReconstructionIncludes.h" +#include "GPUParamRTC.h" static constexpr size_t REQUIRE_MIN_MEMORY = 1024u * 1024 * 1024; static constexpr size_t REQUIRE_MEMORY_RESERVED = 512u * 1024 * 1024; @@ -449,6 +450,10 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() if (fp == nullptr) { throw std::runtime_error("Error opening file"); } + std::string rtcparam = GPUParamRTC::generateRTCCode(param(), mProcessingSettings.rtcConstexpr); + if (fwrite(rtcparam.c_str(), 1, rtcparam.size(), fp) != rtcparam.size()) { + throw std::runtime_error("Error writing 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"); } @@ -616,6 +621,20 @@ size_t GPUReconstructionCUDABackend::WriteToConstantMemory(size_t offset, const if (mProcessingSettings.enableRTC) #endif { + std::unique_ptr<GPUParamRTC> tmpParam; + if (mProcessingSettings.rtcConstexpr) { + if (offset < sizeof(GPUParam) && (offset != 0 || size > sizeof(GPUParam))) { + throw std::runtime_error("Invalid write to constant memory, crossing GPUParam border"); + } + if (offset == 0) { + tmpParam.reset(new GPUParamRTC); + tmpParam->setFrom(*(GPUParam*)src); + src = tmpParam.get(); + size = sizeof(*tmpParam); + } else { + offset = offset - sizeof(GPUParam) + sizeof(GPUParamRTC); + } + } if (stream == -1) { GPUFailedMsg(cudaMemcpy(((char*)mDeviceConstantMem) + offset, src, size, cudaMemcpyHostToDevice)); } else { diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 43e6d89e2a4f2..7daaa1eceef1b 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -110,6 +110,7 @@ set(HDRS_INSTALL TRDTracking/GPUTRDTrackerDebug.h TRDTracking/GPUTRDInterfaces.h Base/GPUConstantMem.h + Base/GPUParamRTC.h Base/GPUReconstructionKernels.h Base/GPUReconstructionIncludesITS.h Base/GPUReconstructionHelpers.h diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx index d7ee19f625da9..6f00ea4431117 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx @@ -19,12 +19,15 @@ using namespace o2::gpu; #define BeginNamespace(name) #define EndNamespace() #define AddOption(name, type, default, optname, optnameshort, help, ...) +#define AddOptionRTC(...) AddOption(__VA_ARGS__) #define AddVariable(name, type, default) +#define AddVariableRTC(...) AddVariable(__VA_ARGS__) #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) #define AddOptionVec(name, type, optname, optnameshort, help, ...) #define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) #define AddSubConfig(name, instance) #define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) O2ParamImpl(GPUCA_M_CAT(GPUConfigurableParam, name)) +#define BeginHiddenConfig(...) #define EndConfig() #define AddCustomCPP(...) #define AddHelp(...) @@ -33,12 +36,15 @@ using namespace o2::gpu; #undef BeginNamespace #undef EndNamespace #undef AddOption +#undef AddOptionRTC #undef AddVariable +#undef AddVariableRTC #undef AddOptionSet #undef AddOptionVec #undef AddOptionArray #undef AddSubConfig #undef BeginSubConfig +#undef BeginHiddenConfig #undef EndConfig #undef AddCustomCPP #undef AddHelp @@ -49,7 +55,9 @@ GPUSettingsO2 GPUO2InterfaceConfiguration::ReadConfigurableParam() #define BeginNamespace(name) #define EndNamespace() #define AddOption(name, type, default, optname, optnameshort, help, ...) dst.name = src.name; +#define AddOptionRTC(...) AddOption(__VA_ARGS__) #define AddVariable(name, type, default) +#define AddVariableRTC(...) AddVariable(__VA_ARGS__) #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) #define AddOptionVec(name, type, optname, optnameshort, help, ...) #define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) \ @@ -62,6 +70,7 @@ GPUSettingsO2 GPUO2InterfaceConfiguration::ReadConfigurableParam() { \ auto& src = GPUCA_M_CAT(GPUConfigurableParam, name)::Instance(); \ name& dst = instance; +#define BeginHiddenConfig(name, instance) { #define EndConfig() } #define AddCustomCPP(...) #define AddHelp(...) @@ -70,12 +79,15 @@ GPUSettingsO2 GPUO2InterfaceConfiguration::ReadConfigurableParam() #undef BeginNamespace #undef EndNamespace #undef AddOption +#undef AddOptionRTC #undef AddVariable +#undef AddVariableRTC #undef AddOptionSet #undef AddOptionVec #undef AddOptionArray #undef AddSubConfig #undef BeginSubConfig +#undef BeginHiddenConfig #undef EndConfig #undef AddCustomCPP #undef AddHelp diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h index 90e472fb1a6e3..0f55a60f17874 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.h @@ -43,7 +43,9 @@ { #define EndNamespace() } #define AddOption(name, type, default, optname, optnameshort, help, ...) type name = default; +#define AddOptionRTC(...) AddOption(__VA_ARGS__) #define AddVariable(name, type, default) +#define AddVariableRTC(...) AddVariable(__VA_ARGS__) #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) #define AddOptionVec(name, type, optname, optnameshort, help, ...) #define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) type name[count] = {default}; @@ -51,22 +53,27 @@ #define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ struct GPUCA_M_CAT(GPUConfigurableParam, name) : public o2::conf::ConfigurableParamHelper<GPUCA_M_CAT(GPUConfigurableParam, name)> { \ O2ParamDef(GPUCA_M_CAT(GPUConfigurableParam, name), GPUCA_M_STR(GPUCA_M_CAT(GPU_, instance))) public: +#define BeginHiddenConfig(name, instance) struct GPUCA_M_CAT(GPUConfigurableParam, name) { #define EndConfig() \ } \ ; #define AddCustomCPP(...) __VA_ARGS__ #define AddHelp(...) #define AddShortcut(...) +#define AddOptionRTC(...) AddOption(__VA_ARGS__) #include "GPUSettingsList.h" #undef BeginNamespace #undef EndNamespace #undef AddOption +#undef AddOptionRTC #undef AddVariable +#undef AddVariableRTC #undef AddOptionSet #undef AddOptionVec #undef AddOptionArray #undef AddSubConfig #undef BeginSubConfig +#undef BeginHiddenConfig #undef EndConfig #undef AddCustomCPP #undef AddHelp diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index bc918419f3958..bc943254a8b6f 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -20,9 +20,8 @@ #include <iostream> #include <tuple> #include <vector> -#include <string> -#include <sstream> #include "qconfig.h" +#include "qconfig_helpers.h" // Create config instances #define QCONFIG_INSTANCE @@ -500,32 +499,6 @@ static inline int qConfigParse(int argc, const char** argv, const char* /*filena // Main parse function called from outside int qConfigParse(int argc, const char** argv, const char* filename) { return (qConfig::qConfigParse(argc, argv, filename)); } -// Print current config settings -namespace -{ -template <class T> -std::string print_type(T val) -{ - std::ostringstream s; - s << val; - return s.str(); -}; -template <> -std::string print_type<char>(char val) -{ - return std::to_string(val); -}; -template <> -std::string print_type<unsigned char>(unsigned char val) -{ - return std::to_string(val); -}; -template <> -std::string print_type<bool>(bool val) -{ - return val ? "true" : "false"; -}; -} // namespace void qConfigPrint() { std::string blockName; diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index 4b931f97136b1..cc2a262989332 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -11,7 +11,25 @@ /// \file qconfig.h /// \author David Rohr -#ifndef QCONFIG_HEADER_GUARD_NO_INCLUDE +#ifndef QCONFIG_H_GENERAL +#define QCONFIG_H_GENERAL +extern int qConfigParse(int argc, const char** argv, const char* filename = nullptr); +extern void qConfigPrint(); +namespace qConfig +{ +enum qConfigRetVal { qcrOK = 0, + qcrError = 1, + qcrMinFailure = 2, + qcrMaxFailure = 3, + qcrHelp = 4, + qcrCmd = 5, + qcrArgMissing = 6, + qcrArgIncomplete = 7, + qcrArrayOverflow = 8 }; +} +#endif + +#if !defined(QCONFIG_HEADER_GUARD_NO_INCLUDE) || defined(QCONFIG_GENRTC) #define AddArrayDefaults(...) \ { \ @@ -156,8 +174,8 @@ // End QCONFIG_HELP #elif defined(QCONFIG_PRINT) -#define AddOption(name, type, default, optname, optnameshort, ...) std::cout << "\t" << blockName << qon_mxstr(name) << ": " << print_type(tmp.name) << "\n"; -#define AddVariable(name, type, default) std::cout << "\t" << blockName << qon_mxstr(name) << ": " << print_type(tmp.name) << "\n"; +#define AddOption(name, type, default, optname, optnameshort, ...) std::cout << "\t" << blockName << qon_mxstr(name) << ": " << qConfig::print_type(tmp.name) << "\n"; +#define AddVariable(name, type, default) std::cout << "\t" << blockName << qon_mxstr(name) << ": " << qConfig::print_type(tmp.name) << "\n"; #define AddOptionSet(name, type, value, optname, optnameshort, ...) #define AddOptionVec(name, type, optname, optnameshort, ...) \ { \ @@ -166,17 +184,17 @@ if (i) { \ std::cout << ", "; \ } \ - std::cout << print_type(tmp.name[i]); \ + std::cout << qConfig::print_type(tmp.name[i]); \ } \ std::cout << "\n"; \ } -#define AddOptionArray(name, type, count, default, optname, optnameshort, ...) \ - { \ - std::cout << "\t" << blockName << qon_mxstr(name) << "[" << count << "]: " << print_type(tmp.name[0]); \ - for (int i = 1; i < count; i++) { \ - std::cout << ", " << print_type(tmp.name[i]); \ - } \ - std::cout << "\n"; \ +#define AddOptionArray(name, type, count, default, optname, optnameshort, ...) \ + { \ + std::cout << "\t" << blockName << qon_mxstr(name) << "[" << count << "]: " << qConfig::print_type(tmp.name[0]); \ + for (int i = 1; i < count; i++) { \ + std::cout << ", " << qConfig::print_type(tmp.name[i]); \ + } \ + std::cout << "\n"; \ } #define AddSubConfig(name, instance) #define AddHelpText(text) printf(" " text ":\n"); @@ -208,32 +226,63 @@ #define EndConfig() // End QCONFIG_INSTANCE +#elif defined(QCONFIG_PRINT_RTC) +#define AddOption(name, type, default, optname, optnameshort, help, ...) out << qon_mxstr(type) << " " << qon_mxstr(name) << ";\n"; +#define AddVariable(name, type, default) out << qon_mxstr(type) << " " << qon_mxstr(name) << ";\n"; +#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) out << qon_mxstr(type) << " " << qon_mxstr(name) << "[" << qon_mxstr(count) << "];\n"; +#define AddOptionVec(name, type, optname, optnameshort, help, ...) out << "std::vector<" << qon_mxstr(type) << "> " << qon_mxstr(name) << ";\n"; +#define AddOptionRTC(name, type, default, optname, optnameshort, help, ...) \ + if (useConstexpr) { \ + out << "static constexpr " << qon_mxstr(type) << " " << qon_mxstr(name) << " = " << qConfig::print_type(std::get<const qConfigCurrentType*>(tSrc)->name) << ";\n"; \ + } else { \ + AddOption(name, type, default, optname, optnameshort, help); \ + } +#define BeginConfig(name, instance) \ + { \ + using qConfigCurrentType = name; \ + out << "struct " << qon_mxstr(name) << " {\n"; +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) BeginConfig(name, instance) +#define EndConfig() \ + out << "};"; \ + } +#define BeginNamespace(name) out << "namespace " << qon_mxstr(name) << " {\n"; +#define EndNamespace() out << "}\n"; +#define AddSubConfig(name, instance) +#define AddOptionSet(...) + +// End QCONFIG_PRINT_RTC +#elif defined(QCONFIG_CONVERT_RTC) +#define AddOption(name, type, default, optname, optnameshort, help, ...) out.name = in.name; +#define AddVariable(name, type, default) out.name = in.name; +#define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) \ + for (unsigned int i = 0; i < count; i++) \ + out.name[i] = in.name[i]; +#define AddOptionVec(name, type, optname, optnameshort, help, ...) \ + for (unsigned int i = 0; i < in.name.size(); i++) \ + out.name[i] = in.name[i]; +#define AddOptionRTC(name, type, default, optname, optnameshort, help, ...) +#define BeginConfig(name, instance) \ + template <class T> \ + void qConfigConvertRtc(T& out, const name& in) \ + { +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) BeginConfig(name, instance) +#define EndConfig() } +#define AddSubConfig(name, instance) +#define AddOptionSet(...) + +// End QCONFIG_CONVERT_RTC #else // Define structures -#ifdef QCONFIG_HEADER_GUARD +#if defined(QCONFIG_HEADER_GUARD) && !defined(QCONFIG_GENRTC) #define QCONFIG_HEADER_GUARD_NO_INCLUDE #else #define QCONFIG_HEADER_GUARD -extern int qConfigParse(int argc, const char** argv, const char* filename = nullptr); -extern void qConfigPrint(); -namespace qConfig -{ -enum qConfigRetVal { qcrOK = 0, - qcrError = 1, - qcrMinFailure = 2, - qcrMaxFailure = 3, - qcrHelp = 4, - qcrCmd = 5, - qcrArgMissing = 6, - qcrArgIncomplete = 7, - qcrArrayOverflow = 8 }; -} - +#ifndef BeginNamespace #define BeginNamespace(name) \ namespace name \ { #define EndNamespace() } -#define AddCustomCPP(...) __VA_ARGS__ +#endif #if !defined(QCONFIG_GPU) #define AddOption(name, type, default, optname, optnameshort, help, ...) type name = default; #define AddVariable(name, type, default) type name = default; @@ -245,12 +294,15 @@ enum qConfigRetVal { qcrOK = 0, #define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) type name[count]; #define AddOptionVec(name, type, optname, optnameshort, help, ...) void* name[sizeof(std::vector<type>) / sizeof(void*)]; #endif +#ifdef QCONFIG_GENRTC +#define AddOptionRTC(name, type, default, optname, optnameshort, help, ...) static constexpr type name = default; +#else +#define AddCustomCPP(...) __VA_ARGS__ +#endif #define AddOptionSet(name, type, value, optname, optnameshort, help, ...) #define AddSubConfig(name, instance) name instance; -#define BeginConfig(name, instance) \ - struct name { -#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ - struct name { +#define BeginConfig(name, instance) struct name { +#define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) struct name { #define EndConfig() \ } \ ; @@ -286,10 +338,14 @@ enum qConfigRetVal { qcrOK = 0, #ifndef AddCustomCPP #define AddCustomCPP(...) #endif +#ifndef AddOptionRTC +#define AddOptionRTC(...) AddOption(__VA_ARGS__) +#endif #include "qconfigoptions.h" #undef AddOption +#undef AddOptionRTC #undef AddVariable #undef AddOptionSet #undef AddOptionVec diff --git a/GPU/GPUTracking/Standalone/utils/qconfig_helpers.h b/GPU/GPUTracking/Standalone/utils/qconfig_helpers.h new file mode 100644 index 0000000000000..d230dcbf419b1 --- /dev/null +++ b/GPU/GPUTracking/Standalone/utils/qconfig_helpers.h @@ -0,0 +1,46 @@ +// 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 qconfig_helpers.h +/// \author David Rohr + +#ifndef QCONFIG_HELPERS_H +#define QCONFIG_HELPERS_H + +#include <string> +#include <sstream> + +namespace qConfig +{ +template <class T> +std::string print_type(T val) +{ + std::ostringstream s; + s << val; + return s.str(); +}; +template <> +std::string print_type<char>(char val) +{ + return std::to_string(val); +}; +template <> +std::string print_type<unsigned char>(unsigned char val) +{ + return std::to_string(val); +}; +template <> +std::string print_type<bool>(bool val) +{ + return val ? "true" : "false"; +}; +} // namespace qConfig + +#endif diff --git a/GPU/GPUTracking/Standalone/utils/qconfigrtc.h b/GPU/GPUTracking/Standalone/utils/qconfigrtc.h new file mode 100644 index 0000000000000..0420d4cc66cf4 --- /dev/null +++ b/GPU/GPUTracking/Standalone/utils/qconfigrtc.h @@ -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 qconfigrtc.h +/// \author David Rohr + +#ifndef QCONFIG_RTC_H +#define QCONFIG_RTC_H + +#include "qconfig.h" +#include "qconfig_helpers.h" + +#ifndef qon_mxstr +#define qon_mstr(a) #a +#define qon_mxstr(a) qon_mstr(a) +#endif + +template <class T> +static std::string qConfigPrintRtc(const T& tSrc, bool useConstexpr) +{ + std::stringstream out; +#define QCONFIG_PRINT_RTC +#include "qconfig.h" +#undef QCONFIG_PRINT_RTC + return out.str(); +} + +#define QCONFIG_CONVERT_RTC +#include "qconfig.h" +#undef QCONFIG_CONVERT_RTC + +#endif From 083ef404fabd6c634f277e099a462cd499c496a2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 3 Nov 2020 18:42:01 +0100 Subject: [PATCH 1248/1751] GPU: Remove unused settings from GPUParam --- GPU/GPUTracking/Base/GPUParam.cxx | 6 ------ GPU/GPUTracking/Base/GPUParam.h | 3 --- 2 files changed, 9 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 82765e92f8175..4de425c60c304 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -75,16 +75,10 @@ void GPUParam::SetDefaults(float solenoidBz) } } - RMin = 83.65f; - RMax = 247.7f; DAlpha = 0.349066f; - PadPitch = 0.4f; BzkG = solenoidBz; constexpr double kCLight = 0.000299792458f; ConstBz = solenoidBz * kCLight; - ErrX = PadPitch / CAMath::Sqrt(12.f); - ErrY = 1.; - ErrZ = 0.228808; dodEdx = 0; constexpr float plusZmin = 0.0529937; diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index a80c91e084df6..9f0105e5051bd 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -43,9 +43,6 @@ struct GPUParam_t { T rec; float DAlpha; // angular size - float RMin, RMax; // slice R range - float ErrX, ErrY, ErrZ; // default cluster errors - float PadPitch; // pad pitch float BzkG; // constant magnetic field value in kG float ConstBz; // constant magnetic field value in kG*clight From d95873d0b13c5d49925e35a405f826143ee41623 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 3 Nov 2020 19:52:20 +0100 Subject: [PATCH 1249/1751] GPU: Move scalar constant part of GPUParam to hidden part of GPUSettings to exploit RTC constexpr optimization --- GPU/GPUTracking/Base/GPUParam.cxx | 62 ++++++++++--------- GPU/GPUTracking/Base/GPUParam.h | 19 ++---- GPU/GPUTracking/Base/GPUParamRTC.h | 2 +- GPU/GPUTracking/Base/GPUSettingsList.h | 16 +++++ .../GPUTPCCompressionTrackModel.cxx | 4 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 18 +++--- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 54 ++++++++-------- GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx | 16 ++--- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 26 ++++---- .../SliceTracker/GPUTPCGlobalTracking.cxx | 12 ++-- .../SliceTracker/GPUTPCSliceData.cxx | 12 ++-- .../SliceTracker/GPUTPCTracker.cxx | 4 +- GPU/GPUTracking/SliceTracker/GPUTPCTracker.h | 6 +- .../SliceTracker/GPUTPCTrackerDump.cxx | 2 +- .../GPUTPCTrackletConstructor.cxx | 9 ++- .../Standalone/display/GPUDisplay.cxx | 18 +++--- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 8 +-- GPU/GPUTracking/Standalone/standalone.cxx | 2 +- GPU/GPUTracking/Standalone/utils/qconfig.h | 31 +++++++++- GPU/GPUTracking/TPCConvert/GPUTPCConvert.cxx | 2 +- .../TPCConvert/GPUTPCConvertImpl.h | 4 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 2 +- 22 files changed, 180 insertions(+), 149 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 4de425c60c304..a338bc8202a6b 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -75,11 +75,11 @@ void GPUParam::SetDefaults(float solenoidBz) } } - DAlpha = 0.349066f; - BzkG = solenoidBz; + par.DAlpha = 0.349066f; + par.BzkG = solenoidBz; constexpr double kCLight = 0.000299792458f; - ConstBz = solenoidBz * kCLight; - dodEdx = 0; + par.ConstBz = solenoidBz * kCLight; + par.dodEdx = 0; constexpr float plusZmin = 0.0529937; constexpr float plusZmax = 249.778; @@ -96,51 +96,51 @@ void GPUParam::SetDefaults(float solenoidBz) if (tmp >= GPUCA_NSLICES / 4) { tmp -= GPUCA_NSLICES / 2; } - SliceParam[i].Alpha = 0.174533 + DAlpha * tmp; + SliceParam[i].Alpha = 0.174533 + par.DAlpha * tmp; SliceParam[i].CosAlpha = CAMath::Cos(SliceParam[i].Alpha); SliceParam[i].SinAlpha = CAMath::Sin(SliceParam[i].Alpha); - SliceParam[i].AngleMin = SliceParam[i].Alpha - DAlpha / 2.f; - SliceParam[i].AngleMax = SliceParam[i].Alpha + DAlpha / 2.f; + SliceParam[i].AngleMin = SliceParam[i].Alpha - par.DAlpha / 2.f; + SliceParam[i].AngleMax = SliceParam[i].Alpha + par.DAlpha / 2.f; } - AssumeConstantBz = false; - ToyMCEventsFlag = false; - ContinuousTracking = false; - continuousMaxTimeBin = 0; - debugLevel = 0; - resetTimers = false; - earlyTpcTransform = false; + par.AssumeConstantBz = false; + par.ToyMCEventsFlag = false; + par.ContinuousTracking = false; + par.continuousMaxTimeBin = 0; + par.debugLevel = 0; + par.resetTimers = false; + par.earlyTpcTransform = false; polynomialField.Reset(); // set very wrong initial value in order to see if the field was not properly initialised - GPUTPCGMPolynomialFieldManager::GetPolynomialField(BzkG, polynomialField); + GPUTPCGMPolynomialFieldManager::GetPolynomialField(par.BzkG, polynomialField); } void GPUParam::UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsProcessing* p) { if (e) { - AssumeConstantBz = e->constBz; - ToyMCEventsFlag = e->homemadeEvents; - ContinuousTracking = e->continuousMaxTimeBin != 0; - continuousMaxTimeBin = e->continuousMaxTimeBin == -1 ? GPUSettings::TPC_MAX_TF_TIME_BIN : e->continuousMaxTimeBin; + par.AssumeConstantBz = e->constBz; + par.ToyMCEventsFlag = e->homemadeEvents; + par.ContinuousTracking = e->continuousMaxTimeBin != 0; + par.continuousMaxTimeBin = e->continuousMaxTimeBin == -1 ? GPUSettings::TPC_MAX_TF_TIME_BIN : e->continuousMaxTimeBin; polynomialField.Reset(); - if (AssumeConstantBz) { - GPUTPCGMPolynomialFieldManager::GetPolynomialField(GPUTPCGMPolynomialFieldManager::kUniform, BzkG, polynomialField); + if (par.AssumeConstantBz) { + GPUTPCGMPolynomialFieldManager::GetPolynomialField(GPUTPCGMPolynomialFieldManager::kUniform, par.BzkG, polynomialField); } else { - GPUTPCGMPolynomialFieldManager::GetPolynomialField(BzkG, polynomialField); + GPUTPCGMPolynomialFieldManager::GetPolynomialField(par.BzkG, polynomialField); } } if (p) { - debugLevel = p->debugLevel; - resetTimers = p->resetTimers; + par.debugLevel = p->debugLevel; + par.resetTimers = p->resetTimers; } - earlyTpcTransform = rec.ForceEarlyTPCTransform == -1 ? (!ContinuousTracking) : rec.ForceEarlyTPCTransform; + par.earlyTpcTransform = rec.ForceEarlyTPCTransform == -1 ? (!par.ContinuousTracking) : rec.ForceEarlyTPCTransform; } void GPUParam::SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r, const GPUSettingsProcessing* p, const GPURecoStepConfiguration* w) { SetDefaults(e->solenoidBz); if (w) { - dodEdx = w->steps.isSet(GPUDataTypes::RecoStep::TPCdEdx); + par.dodEdx = w->steps.isSet(GPUDataTypes::RecoStep::TPCdEdx); } if (r) { rec = *r; @@ -231,14 +231,16 @@ void GPUParam::LoadClusterErrors(bool Print) void GPUParamRTC::setFrom(const GPUParam& param) { - memcpy((char*)this + sizeof(gpu_rtc::GPUSettingsRec), (char*)¶m + sizeof(GPUSettingsRec), sizeof(param) - sizeof(GPUSettingsRec)); + memcpy((char*)this + sizeof(gpu_rtc::GPUSettingsRec) + sizeof(gpu_rtc::GPUSettingsParam), (char*)¶m + sizeof(GPUSettingsRec) + sizeof(GPUSettingsParam), sizeof(param) - sizeof(GPUSettingsRec) - sizeof(GPUSettingsParam)); qConfigConvertRtc(this->rec, param.rec); + qConfigConvertRtc(this->par, param.par); } std::string GPUParamRTC::generateRTCCode(const GPUParam& param, bool useConstexpr) { - return "namespace o2::gpu { class GPUDisplayBackend; }\n" + qConfigPrintRtc(std::make_tuple(¶m.rec), useConstexpr); + return "namespace o2::gpu { class GPUDisplayBackend; }\n" + qConfigPrintRtc(std::make_tuple(¶m.rec, ¶m.par), useConstexpr); } -static_assert(alignof(o2::gpu::GPUParam) == alignof(o2::gpu::GPUSettingsRec)); -static_assert(sizeof(o2::gpu::GPUParam) - sizeof(o2::gpu::GPUParamRTC) == sizeof(o2::gpu::GPUSettingsRec) - sizeof(o2::gpu::gpu_rtc::GPUSettingsRec)); +static_assert(alignof(GPUCA_NAMESPACE::gpu::GPUParam) == alignof(GPUCA_NAMESPACE::gpu::GPUSettingsRec)); +static_assert(alignof(GPUCA_NAMESPACE::gpu::GPUParam) == alignof(GPUCA_NAMESPACE::gpu::GPUSettingsParam)); +static_assert(sizeof(GPUCA_NAMESPACE::gpu::GPUParam) - sizeof(GPUCA_NAMESPACE::gpu::GPUParamRTC) == sizeof(GPUCA_NAMESPACE::gpu::GPUSettingsRec) + sizeof(GPUCA_NAMESPACE::gpu::GPUSettingsParam) - sizeof(GPUCA_NAMESPACE::gpu::gpu_rtc::GPUSettingsRec) - sizeof(GPUCA_NAMESPACE::gpu::gpu_rtc::GPUSettingsParam)); diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index 9f0105e5051bd..3c92e1d09f7a2 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -38,22 +38,11 @@ struct GPUParamSlice { namespace internal { -template <class T> +template <class T, class S> struct GPUParam_t { T rec; + S par; - float DAlpha; // angular size - float BzkG; // constant magnetic field value in kG - float ConstBz; // constant magnetic field value in kG*clight - - char AssumeConstantBz; // Assume a constant magnetic field - char ToyMCEventsFlag; // events were build with home-made event generator - char ContinuousTracking; // Continuous tracking, estimate bz and errors for abs(z) = 125cm during seeding - char resetTimers; // Reset benchmark timers before event processing - char dodEdx; // Do dEdx computation - char earlyTpcTransform; // do Early TPC transformation - int debugLevel; // Debug level - int continuousMaxTimeBin; // Max time bin for continuous tracking GPUTPCGeometry tpcGeometry; // TPC Geometry GPUTPCGMPolynomialField polynomialField; // Polynomial approx. of magnetic field for TPC GM @@ -66,7 +55,7 @@ struct GPUParam_t { } // namespace internal MEM_CLASS_PRE() -struct GPUParam : public internal::GPUParam_t<GPUSettingsRec> { +struct GPUParam : public internal::GPUParam_t<GPUSettingsRec, GPUSettingsParam> { #ifndef GPUCA_GPUCODE void SetDefaults(float solenoidBz); @@ -83,7 +72,7 @@ struct GPUParam : public internal::GPUParam_t<GPUSettingsRec> { if (iSlice >= GPUCA_NSLICES / 4) { iSlice -= GPUCA_NSLICES / 2; } - return 0.174533f + DAlpha * iSlice; + return 0.174533f + par.DAlpha * iSlice; } GPUd() float GetClusterRMS(int yz, int type, float z, float angle2) const; GPUd() void GetClusterRMS2(int row, float z, float sinPhi, float DzDs, float& ErrY2, float& ErrZ2) const; diff --git a/GPU/GPUTracking/Base/GPUParamRTC.h b/GPU/GPUTracking/Base/GPUParamRTC.h index fe32522d94e8b..2647d7152dbea 100644 --- a/GPU/GPUTracking/Base/GPUParamRTC.h +++ b/GPU/GPUTracking/Base/GPUParamRTC.h @@ -32,7 +32,7 @@ namespace gpu_rtc #undef EndNamespace } // namespace gpu_rtc -struct GPUParamRTC : public internal::GPUParam_t<gpu_rtc::GPUSettingsRec> { +struct GPUParamRTC : public internal::GPUParam_t<gpu_rtc::GPUSettingsRec, gpu_rtc::GPUSettingsParam> { void setFrom(const GPUParam& param); static std::string generateRTCCode(const GPUParam& param, bool useConstexpr); }; diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 327469ef4525a..beb952583cb00 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -286,6 +286,22 @@ EndConfig() #endif // GPUCA_O2_LIB #endif // !GPUCA_GPUCODE_DEVICE +// Derrived parameters used in GPUParam +BeginHiddenConfig(GPUSettingsParam, param) +AddVariableRTC(DAlpha, float, 0.f) // angular size +AddVariableRTC(BzkG, float, 0.f) // constant magnetic field value in kG +AddVariableRTC(ConstBz, float, 0.f) // constant magnetic field value in kG*clight +AddVariableRTC(AssumeConstantBz, char, 0) // Assume a constant magnetic field +AddVariableRTC(ToyMCEventsFlag, char, 0) // events were build with home-made event generator +AddVariableRTC(ContinuousTracking, char, 0) // Continuous tracking, estimate bz and errors for abs(z) = 125cm during seeding +AddVariableRTC(resetTimers, char, 0) // Reset benchmark timers before event processing +AddVariableRTC(dodEdx, char, 0) // Do dEdx computation +AddVariableRTC(earlyTpcTransform, char, 0) // do Early TPC transformation +AddVariableRTC(debugLevel, char, 0) // Debug level +AddVariableRTC(continuousMaxTimeBin, int, 0) // Max time bin for continuous tracking +AddVariable(dummyRTC, float, 0.f) // Ensure non empty struct and proper alignment even if all normal members are constexpr +EndConfig() + EndNamespace() // gpu EndNamespace() // GPUCA_NAMESPACE #endif // #ifdef BeginNamespace diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx index 627d16828683a..1434885468d2c 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx @@ -90,7 +90,7 @@ GPUd() int GPUTPCCompressionTrackModel::Propagate(float x, float alpha) if (alpha != mAlpha && !mTrk.Rotate(alpha, t0, GPUCA_MAX_SIN_PHI)) { return 2; } - int retVal = !mTrk.TransportToX(x, t0, mParam->ConstBz, GPUCA_MAX_SIN_PHI); + int retVal = !mTrk.TransportToX(x, t0, mParam->par.ConstBz, GPUCA_MAX_SIN_PHI); // GPUInfo("Propagated to: x %f y %f z %f alpha %f qPt %f", x, mTrk.Y(), mTrk.Z(), alpha, mTrk.QPt()); return retVal; } @@ -126,7 +126,7 @@ GPUd() void GPUTPCCompressionTrackModel::Init(float x, float y, float z, float a mP[4] = (qPt - 127.f) * (20.f / 127.f); resetCovariance(); mNDF = -5; - mBz = param.ConstBz; + mBz = param.par.ConstBz; float pti = CAMath::Abs(mP[4]); if (pti < 1.e-4f) { pti = 1.e-4f; // set 10.000 GeV momentum for straight track diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index ff2e5c86ed8b2..ecad6f9b2b1ca 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -184,7 +184,7 @@ bool GPUChainTracking::ValidateSteps() GPUError("Invalid GPU Reconstruction Step Setting: dEdx requires TPC Merger to be active"); return false; } - if (!param().earlyTpcTransform) { + if (!param().par.earlyTpcTransform) { if (((GetRecoSteps() & GPUDataTypes::RecoStep::TPCSliceTracking) || (GetRecoSteps() & GPUDataTypes::RecoStep::TPCMerging)) && !(GetRecoSteps() & GPUDataTypes::RecoStep::TPCConversion)) { GPUError("Invalid Reconstruction Step Setting: Tracking without early transform requires TPC Conversion to be active"); return false; @@ -272,7 +272,7 @@ bool GPUChainTracking::ValidateSettings() GPUError("Cannot do error interpolation with NWays = 1!"); return false; } - if ((param().rec.mergerReadFromTrackerDirectly || !param().earlyTpcTransform) && param().rec.NonConsecutiveIDs) { + if ((param().rec.mergerReadFromTrackerDirectly || !param().par.earlyTpcTransform) && param().rec.NonConsecutiveIDs) { GPUError("incompatible settings for non consecutive ids"); return false; } @@ -280,7 +280,7 @@ bool GPUChainTracking::ValidateSettings() GPUError("OMP Kernels require mergerReadFromTrackerDirectly"); return false; } - if (param().continuousMaxTimeBin > (int)GPUSettings::TPC_MAX_TF_TIME_BIN) { + if (param().par.continuousMaxTimeBin > (int)GPUSettings::TPC_MAX_TF_TIME_BIN) { GPUError("configure max time bin exceeds 256 orbits"); return false; } @@ -507,7 +507,7 @@ int GPUChainTracking::ConvertNativeToClusterData() TransferMemoryResourceLinkToGPU(RecoStep::TPCConversion, mInputsHost->mResourceClusterNativeAccess, 0); } } - if (!param().earlyTpcTransform) { + if (!param().par.earlyTpcTransform) { if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Early transform inactive, skipping TPC Early transformation kernel, transformed on the fly during slice data creation / refit"); } @@ -538,7 +538,7 @@ void GPUChainTracking::ConvertNativeToClusterDataLegacy() if (tmp != mIOPtrs.clustersNative) { *tmp = *mIOPtrs.clustersNative; } - GPUReconstructionConvert::ConvertNativeToClusterData(mIOMem.clusterNativeAccess.get(), mIOMem.clusterData, mIOPtrs.nClusterData, processors()->calibObjects.fastTransform, param().continuousMaxTimeBin); + GPUReconstructionConvert::ConvertNativeToClusterData(mIOMem.clusterNativeAccess.get(), mIOMem.clusterData, mIOPtrs.nClusterData, processors()->calibObjects.fastTransform, param().par.continuousMaxTimeBin); for (unsigned int i = 0; i < NSLICES; i++) { mIOPtrs.clusterData[i] = mIOMem.clusterData[i].get(); if (GetProcessingSettings().registerStandaloneInputMemory) { @@ -969,7 +969,7 @@ int GPUChainTracking::RunTPCClusterizer_prepare(bool restorePointers) if (mCFContext == nullptr) { mCFContext.reset(new GPUTPCCFChainContext); } - mCFContext->tpcMaxTimeBin = std::max<int>(param().continuousMaxTimeBin, TPC_MAX_FRAGMENT_LEN); + mCFContext->tpcMaxTimeBin = std::max<int>(param().par.continuousMaxTimeBin, TPC_MAX_FRAGMENT_LEN); const CfFragment fragmentMax{(tpccf::TPCTime)mCFContext->tpcMaxTimeBin + 1, TPC_MAX_FRAGMENT_LEN}; mCFContext->prepare(mIOPtrs.tpcZS, fragmentMax); if (mIOPtrs.tpcZS) { @@ -1084,7 +1084,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) auto* digitsMC = propagateMCLabels ? processors()->ioPtrs.tpcPackedDigits->tpcDigitsMC : nullptr; - if (param().continuousMaxTimeBin > 0 && mCFContext->tpcMaxTimeBin >= (unsigned int)std::max(param().continuousMaxTimeBin + 1, TPC_MAX_FRAGMENT_LEN)) { + if (param().par.continuousMaxTimeBin > 0 && mCFContext->tpcMaxTimeBin >= (unsigned int)std::max(param().par.continuousMaxTimeBin + 1, TPC_MAX_FRAGMENT_LEN)) { GPUError("Input data has invalid time bin\n"); return 1; } @@ -1424,7 +1424,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } bool doGPU = GetRecoStepsGPU() & RecoStep::TPCSliceTracking; bool doSliceDataOnGPU = processors()->tpcTrackers[0].SliceDataOnGPU(); - if (!param().earlyTpcTransform) { + if (!param().par.earlyTpcTransform) { for (unsigned int i = 0; i < NSLICES; i++) { processors()->tpcTrackers[i].Data().SetClusterData(nullptr, mIOPtrs.clustersNative->nClustersSector[i], mIOPtrs.clustersNative->clusterOffset[i][0]); if (doGPU) { @@ -2045,7 +2045,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) } else { GPUMemCpy(RecoStep::TPCMerging, Merger.OutputTracks(), MergerShadowAll.OutputTracks(), Merger.NOutputTracks() * sizeof(*Merger.OutputTracks()), mRec->NStreams() - 2, 0, nullptr, &mEvents->single); GPUMemCpy(RecoStep::TPCMerging, Merger.Clusters(), MergerShadowAll.Clusters(), Merger.NOutputTrackClusters() * sizeof(*Merger.Clusters()), mRec->NStreams() - 2, 0); - if (param().earlyTpcTransform) { + if (param().par.earlyTpcTransform) { GPUMemCpy(RecoStep::TPCMerging, Merger.ClustersXYZ(), MergerShadowAll.ClustersXYZ(), Merger.NOutputTrackClusters() * sizeof(*Merger.ClustersXYZ()), mRec->NStreams() - 2, 0); } GPUMemCpy(RecoStep::TPCMerging, Merger.ClusterAttachment(), MergerShadowAll.ClusterAttachment(), Merger.NMaxClusters() * sizeof(*Merger.ClusterAttachment()), mRec->NStreams() - 2, 0); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 0ad56f3983b5a..0238773cd889b 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -309,7 +309,7 @@ void* GPUTPCGMMerger::SetPointersOutput(void* mem) { computePointerWithAlignment(mem, mOutputTracks, mNMaxTracks); computePointerWithAlignment(mem, mClusters, mNMaxOutputTrackClusters); - if (mRec->GetParam().earlyTpcTransform) { + if (mRec->GetParam().par.earlyTpcTransform) { computePointerWithAlignment(mem, mClustersXYZ, mNMaxOutputTrackClusters); } computePointerWithAlignment(mem, mClusterAttachment, mNMaxClusters); @@ -400,7 +400,7 @@ GPUd() int GPUTPCGMMerger::RefitSliceTrack(GPUTPCGMSliceTrack& sliceTrack, const trk.SinPhi() = inTrack->Param().GetSinPhi(); trk.DzDs() = inTrack->Param().GetDzDs(); trk.QPt() = inTrack->Param().GetQPt(); - trk.TZOffset() = Param().earlyTpcTransform ? inTrack->Param().GetZOffset() : GetConstantMem()->calibObjects.fastTransform->convZOffsetToVertexTime(slice, inTrack->Param().GetZOffset(), Param().continuousMaxTimeBin); + trk.TZOffset() = Param().par.earlyTpcTransform ? inTrack->Param().GetZOffset() : GetConstantMem()->calibObjects.fastTransform->convZOffsetToVertexTime(slice, inTrack->Param().GetZOffset(), Param().par.continuousMaxTimeBin); trk.ShiftZ(this, slice, sliceTrack.ClusterZT0(), sliceTrack.ClusterZTN()); for (int way = 0; way < 2; way++) { if (way) { @@ -422,7 +422,7 @@ GPUd() int GPUTPCGMMerger::RefitSliceTrack(GPUTPCGMSliceTrack& sliceTrack, const row = ic.RowIndex(); const ClusterNative& cl = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[GetConstantMem()->ioPtrs.clustersNative->clusterOffset[slice][0] + clusterIndex]; flags = cl.getFlags(); - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { x = tracker.Data().ClusterData()[clusterIndex].x; y = tracker.Data().ClusterData()[clusterIndex].y; z = tracker.Data().ClusterData()[clusterIndex].z - trk.TZOffset(); @@ -433,7 +433,7 @@ GPUd() int GPUTPCGMMerger::RefitSliceTrack(GPUTPCGMSliceTrack& sliceTrack, const const GPUTPCSliceOutCluster& clo = inTrack->OutTrackCluster(i); row = clo.GetRow(); flags = clo.GetFlags(); - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { x = clo.GetX(); y = clo.GetY(); z = clo.GetZ() - trk.TZOffset(); @@ -469,14 +469,14 @@ GPUd() void GPUTPCGMMerger::SetTrackClusterZT(GPUTPCGMSliceTrack& track, int iSl const GPUTPCHitId& ic2 = trk.TrackHits()[sliceTr->FirstHitID() + sliceTr->NHits() - 1]; int clusterIndex1 = trk.Data().ClusterDataIndex(trk.Data().Row(ic1.RowIndex()), ic1.HitIndex()); int clusterIndex2 = trk.Data().ClusterDataIndex(trk.Data().Row(ic2.RowIndex()), ic2.HitIndex()); - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { track.SetClusterZT(trk.Data().ClusterData()[clusterIndex1].z, trk.Data().ClusterData()[clusterIndex2].z); } else { const ClusterNative* cl = GetConstantMem()->ioPtrs.clustersNative->clustersLinear + GetConstantMem()->ioPtrs.clustersNative->clusterOffset[iSlice][0]; track.SetClusterZT(cl[clusterIndex1].getTime(), cl[clusterIndex2].getTime()); } } else { - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { track.SetClusterZT(sliceTr->OutTrackClusters()->GetZ(), (sliceTr->OutTrackClusters() + sliceTr->NHits() - 1)->GetZ()); } else { const ClusterNative* cls = mConstantMem->ioPtrs.clustersNative->clustersLinear; @@ -595,9 +595,9 @@ GPUd() void GPUTPCGMMerger::MakeBorderTracks(int nBlocks, int nThreads, int iBlo //* prepare slice tracks for merging with next/previous/same sector //* each track transported to the border line - float fieldBz = Param().ConstBz; + float fieldBz = Param().par.ConstBz; - float dAlpha = Param().DAlpha / 2; + float dAlpha = Param().par.DAlpha / 2; float x0 = 0; if (iBorder == 0) { // transport to the left edge of the sector and rotate horizontally @@ -932,7 +932,7 @@ GPUd() void GPUTPCGMMerger::MergeWithinSlicesPrepare(int nBlocks, int nThreads, int iSlice = track.Slice(); GPUTPCGMBorderTrack b; ; - if (track.TransportToX(this, x0, Param().ConstBz, b, maxSin)) { + if (track.TransportToX(this, x0, Param().par.ConstBz, b, maxSin)) { b.SetTrackID(itr); CADEBUG( printf("WITHIN SLICE %d Track %d - ", iSlice, itr); for (int i = 0; i < 5; i++) { printf("%8.3f ", b.Par()[i]); } printf(" - "); for (int i = 0; i < 5; i++) { printf("%8.3f ", b.Cov()[i]); } printf("\n")); @@ -1258,7 +1258,7 @@ GPUd() void GPUTPCGMMerger::MergeCEFill(const GPUTPCGMSliceTrack* track, const G #endif float z = 0; - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { z = clsXYZ->z; } else { float x, y; @@ -1266,14 +1266,14 @@ GPUd() void GPUTPCGMMerger::MergeCEFill(const GPUTPCGMSliceTrack* track, const G GPUTPCConvertImpl::convert(*mConstantMem, cls.slice, cls.row, cln.getPad(), cln.getTime(), x, y, z); } - if (!Param().ContinuousTracking && CAMath::Abs(z) > 10) { + if (!Param().par.ContinuousTracking && CAMath::Abs(z) > 10) { return; } int slice = track->Slice(); for (int attempt = 0; attempt < 2; attempt++) { GPUTPCGMBorderTrack b; const float x0 = Param().tpcGeometry.Row2X(attempt == 0 ? 63 : cls.row); - if (track->TransportToX(this, x0, Param().ConstBz, b, GPUCA_MAX_SIN_PHI_LOW)) { + if (track->TransportToX(this, x0, Param().par.ConstBz, b, GPUCA_MAX_SIN_PHI_LOW)) { b.SetTrackID(itr); b.SetNClusters(mOutputTracks[itr].NClusters()); if (CAMath::Abs(b.Cov()[4]) >= 0.5) { @@ -1294,7 +1294,7 @@ GPUd() void GPUTPCGMMerger::MergeCEFill(const GPUTPCGMSliceTrack* track, const G GPUd() void GPUTPCGMMerger::MergeCE(int nBlocks, int nThreads, int iBlock, int iThread) { - const ClusterNative* cls = Param().earlyTpcTransform ? nullptr : mConstantMem->ioPtrs.clustersNative->clustersLinear; + const ClusterNative* cls = Param().par.earlyTpcTransform ? nullptr : mConstantMem->ioPtrs.clustersNative->clustersLinear; for (unsigned int i = iBlock * nThreads + iThread; i < mMemory->nOutputTracks; i += nThreads * nBlocks) { if (mOutputTracks[i].CSide() == 0 && mTrackLinks[i] >= 0) { if (mTrackLinks[mTrackLinks[i]] != (int)i) { @@ -1324,7 +1324,7 @@ GPUd() void GPUTPCGMMerger::MergeCE(int nBlocks, int nThreads, int iBlock, int i bool needswap = false; if (looper) { float z0max, z1max; - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { z0max = CAMath::Max(CAMath::Abs(mClustersXYZ[trk[0]->FirstClusterRef()].z), CAMath::Abs(mClustersXYZ[trk[0]->FirstClusterRef() + trk[0]->NClusters() - 1].z)); z1max = CAMath::Max(CAMath::Abs(mClustersXYZ[trk[1]->FirstClusterRef()].z), CAMath::Abs(mClustersXYZ[trk[1]->FirstClusterRef() + trk[1]->NClusters() - 1].z)); } else { @@ -1345,7 +1345,7 @@ GPUd() void GPUTPCGMMerger::MergeCE(int nBlocks, int nThreads, int iBlock, int i bool reverse[2] = {false, false}; if (looper) { - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { reverse[0] = (mClustersXYZ[trk[0]->FirstClusterRef()].z > mClustersXYZ[trk[0]->FirstClusterRef() + trk[0]->NClusters() - 1].z) ^ (trk[0]->CSide() > 0); reverse[1] = (mClustersXYZ[trk[1]->FirstClusterRef()].z < mClustersXYZ[trk[1]->FirstClusterRef() + trk[1]->NClusters() - 1].z) ^ (trk[1]->CSide() > 0); } else { @@ -1354,8 +1354,8 @@ GPUd() void GPUTPCGMMerger::MergeCE(int nBlocks, int nThreads, int iBlock, int i } } - if (Param().ContinuousTracking) { - if (Param().earlyTpcTransform) { + if (Param().par.ContinuousTracking) { + if (Param().par.earlyTpcTransform) { const float z0 = trk[0]->CSide() ? CAMath::Max(mClustersXYZ[trk[0]->FirstClusterRef()].z, mClustersXYZ[trk[0]->FirstClusterRef() + trk[0]->NClusters() - 1].z) : CAMath::Min(mClustersXYZ[trk[0]->FirstClusterRef()].z, mClustersXYZ[trk[0]->FirstClusterRef() + trk[0]->NClusters() - 1].z); const float z1 = trk[1]->CSide() ? CAMath::Max(mClustersXYZ[trk[1]->FirstClusterRef()].z, mClustersXYZ[trk[1]->FirstClusterRef() + trk[1]->NClusters() - 1].z) : CAMath::Min(mClustersXYZ[trk[1]->FirstClusterRef()].z, mClustersXYZ[trk[1]->FirstClusterRef() + trk[1]->NClusters() - 1].z); const float offset = CAMath::Abs(z1) > CAMath::Abs(z0) ? -z0 : z1; @@ -1377,14 +1377,14 @@ GPUd() void GPUTPCGMMerger::MergeCE(int nBlocks, int nThreads, int iBlock, int i for (int k = 1; k >= 0; k--) { if (reverse[k]) { for (int j = trk[k]->NClusters() - 1; j >= 0; j--) { - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { mClustersXYZ[pos] = mClustersXYZ[trk[k]->FirstClusterRef() + j]; } mClusters[pos++] = mClusters[trk[k]->FirstClusterRef() + j]; } } else { for (unsigned int j = 0; j < trk[k]->NClusters(); j++) { - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { mClustersXYZ[pos] = mClustersXYZ[trk[k]->FirstClusterRef() + j]; } mClusters[pos++] = mClusters[trk[k]->FirstClusterRef() + j]; @@ -1576,7 +1576,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int i for (int i = 0; i < nParts; i++) { if (trackParts[i]->Leg() == 0 || trackParts[i]->Leg() == leg) { float zt; - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { zt = CAMath::Min(CAMath::Abs(trackParts[i]->ClusterZT0()), CAMath::Abs(trackParts[i]->ClusterZTN())); } else { zt = -trackParts[i]->MinClusterZT(); // Negative time ~ smallest z, to behave the same way // TODO: Check all these min / max ZT @@ -1599,7 +1599,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int i } } bool outwards; - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { outwards = (trackParts[iLongest]->ClusterZT0() > trackParts[iLongest]->ClusterZTN()) ^ trackParts[iLongest]->CSide(); } else { outwards = trackParts[iLongest]->ClusterZT0() < trackParts[iLongest]->ClusterZTN(); @@ -1664,7 +1664,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int i cl[i] XYZ.time = c->mTime; #endif state = c->GetFlags(); - } else if (Param().earlyTpcTransform) { + } else if (Param().par.earlyTpcTransform) { const GPUTPCClusterData& c = GetConstantMem()->tpcTrackers[trackClusters[i].slice].ClusterData()[trackClusters[i].id - GetConstantMem()->tpcTrackers[trackClusters[i].slice].Data().ClusterIdOffset()]; clXYZ[i].x = c.x; clXYZ[i].y = c.y; @@ -1713,8 +1713,8 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int i mergedTrack.SetCSide(p2.CSide()); GPUTPCGMBorderTrack b; - const float toX = Param().earlyTpcTransform ? clXYZ[0].x : Param().tpcGeometry.Row2X(cl[0].row); - if (p2.TransportToX(this, toX, Param().ConstBz, b, GPUCA_MAX_SIN_PHI, false)) { + const float toX = Param().par.earlyTpcTransform ? clXYZ[0].x : Param().tpcGeometry.Row2X(cl[0].row); + if (p2.TransportToX(this, toX, Param().par.ConstBz, b, GPUCA_MAX_SIN_PHI, false)) { p1.X() = toX; p1.Y() = b.Par()[0]; p1.Z() = b.Par()[1]; @@ -1744,7 +1744,7 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int nBlocks, int nThreads, int i if (mergedTrack.NClusters() && mergedTrack.OK()) */ { bool CEside; - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { CEside = (mergedTrack.CSide() != 0) ^ (clXYZ[0].z > clXYZ[nHits - 1].z); } else { auto& cls = mConstantMem->ioPtrs.clustersNative->clustersLinear; @@ -1959,7 +1959,7 @@ GPUd() void GPUTPCGMMerger::MergeLoopers(int nBlocks, int nThreads, int iBlock, const float qptabs = CAMath::Abs(p.GetQPt()); if (trk.NClusters() && qptabs > 5.f && qptabs <= lowPtThresh) { const int slice = mClusters[trk.FirstClusterRef() + trk.NClusters() - 1].slice; - const float z = p.GetZ() + (Param().earlyTpcTransform ? p.GetTZOffset() : GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(slice, p.GetTZOffset(), Param().continuousMaxTimeBin)); + const float z = p.GetZ() + (Param().par.earlyTpcTransform ? p.GetTZOffset() : GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(slice, p.GetTZOffset(), Param().par.continuousMaxTimeBin)); float sinA, cosA; CAMath::SinCos(trk.GetAlpha(), sinA, cosA); float gx = cosA * p.GetX() - sinA * p.GetY(); @@ -1976,7 +1976,7 @@ GPUd() void GPUTPCGMMerger::MergeLoopers(int nBlocks, int nThreads, int iBlock, /*printf("Track %d Sanity qpt %f snp %f bz %f\n", (int)params.size(), p.GetQPt(), p.GetSinPhi(), bz); for (unsigned int k = 0;k < trk.NClusters();k++) { float xx, yy, zz; - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { const float zOffset = (mClusters[trk.FirstClusterRef() + k].slice < 18) == (mClusters[trk.FirstClusterRef() + 0].slice < 18) ? p.GetTZOffset() : -p.GetTZOffset(); xx = mClustersXYZ[trk.FirstClusterRef() + k].x; yy = mClustersXYZ[trk.FirstClusterRef() + k].y; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx b/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx index c7b8b67ac8cc9..1627d5bdcbe67 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx @@ -36,10 +36,10 @@ GPUd() void GPUTPCGMSliceTrack::Set(const GPUTPCGMMerger* merger, const GPUTPCTr mParam.mSecPhi = 1.f / mParam.mCosPhi; mAlpha = alpha; mSlice = slice; - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { mTZOffset = t.GetZOffset(); } else { - mTZOffset = merger->GetConstantMem()->calibObjects.fastTransform->convZOffsetToVertexTime(slice, t.GetZOffset(), merger->Param().continuousMaxTimeBin); + mTZOffset = merger->GetConstantMem()->calibObjects.fastTransform->convZOffsetToVertexTime(slice, t.GetZOffset(), merger->Param().par.continuousMaxTimeBin); } mNClusters = sliceTr->NHits(); } @@ -94,7 +94,7 @@ GPUd() void GPUTPCGMSliceTrack::SetParam2(const GPUTPCGMTrackParam& trk) GPUd() bool GPUTPCGMSliceTrack::FilterErrors(const GPUTPCGMMerger* merger, int iSlice, float maxSinPhi, float sinPhiMargin) { float lastX; - if (merger->Param().earlyTpcTransform && !merger->Param().rec.mergerReadFromTrackerDirectly) { + if (merger->Param().par.earlyTpcTransform && !merger->Param().rec.mergerReadFromTrackerDirectly) { lastX = mOrigTrack->OutTrackCluster(mOrigTrack->NHits() - 1).GetX(); // TODO: Why is this needed, Row2X should work, but looses some tracks } else { //float lastX = merger->Param().tpcGeometry.Row2X(mOrigTrack->Cluster(mOrigTrack->NClusters() - 1).GetRow()); // TODO: again, why does this reduce efficiency? @@ -117,7 +117,7 @@ GPUd() bool GPUTPCGMSliceTrack::FilterErrors(const GPUTPCGMMerger* merger, int i const int N = 3; - float bz = -merger->Param().ConstBz; + float bz = -merger->Param().par.ConstBz; float k = mParam.mQPt * bz; float dx = (1.f / N) * (lastX - mParam.mX); @@ -321,10 +321,10 @@ GPUd() bool GPUTPCGMSliceTrack::TransportToX(GPUTPCGMMerger* merger, float x, fl b.SetPar(2, ey1); b.SetPar(3, mParam.mDzDs); b.SetPar(4, mParam.mQPt); - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { b.SetZOffsetLinear(mTZOffset); } else { - b.SetZOffsetLinear(merger->GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(mSlice, mTZOffset, merger->Param().continuousMaxTimeBin)); + b.SetZOffsetLinear(merger->GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(mSlice, mTZOffset, merger->Param().par.continuousMaxTimeBin)); } if (!doCov) { @@ -477,10 +477,10 @@ GPUd() bool GPUTPCGMSliceTrack::TransportToXAlpha(GPUTPCGMMerger* merger, float b.SetPar(2, ey1); b.SetPar(3, dzds); b.SetPar(4, qpt); - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { b.SetZOffsetLinear(mTZOffset); } else { - b.SetZOffsetLinear(merger->GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(mSlice, mTZOffset, merger->Param().continuousMaxTimeBin)); + b.SetZOffsetLinear(merger->GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(mSlice, mTZOffset, merger->Param().par.continuousMaxTimeBin)); } b.SetCov(0, c00 + h2 * h2c22 + h4 * h4c44 + 2.f * (h2 * c20ph4c42 + h4 * c40)); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index dffa40a038633..3f0a32dad2a35 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -66,7 +66,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, prop.SetMaterialTPC(); prop.SetPolynomialField(&merger->Param().polynomialField); prop.SetMaxSinPhi(maxSinPhi); - prop.SetToyMCEventsFlag(param.ToyMCEventsFlag); + prop.SetToyMCEventsFlag(param.par.ToyMCEventsFlag); if ((clusters[0].slice < 18) == (clusters[N - 1].slice < 18)) { ShiftZ2(clusters, clustersXYZ, merger, N); } @@ -143,7 +143,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, prop.SetStatErrorCurCluster(&clusters[ihit]); float xx, yy, zz; - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { const float zOffset = (clusters[ihit].slice < 18) == (clusters[0].slice < 18) ? mTZOffset : -mTZOffset; xx = clustersXYZ[ihit].x; yy = clustersXYZ[ihit].y; @@ -414,7 +414,7 @@ GPUd() int GPUTPCGMTrackParam::MergeDoubleRowClusters(int& ihit, int wayDirectio clusterState = 0; while (true) { float clx, cly, clz, clamp; - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { const float zOffset = (clusters[ihit].slice < 18) == (clusters[0].slice < 18) ? mTZOffset : -mTZOffset; clx = clustersXYZ[ihit].x; cly = clustersXYZ[ihit].y; @@ -460,7 +460,7 @@ GPUd() int GPUTPCGMTrackParam::MergeDoubleRowClusters(int& ihit, int wayDirectio GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, bool goodLeg, GPUTPCGMPropagator& prop) { float Y, Z; - if (Merger->Param().earlyTpcTransform) { + if (Merger->Param().par.earlyTpcTransform) { Y = mP[0]; Z = mP[1]; } else { @@ -489,7 +489,7 @@ GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict return; } - const float zOffset = Merger->Param().earlyTpcTransform ? ((Merger->OutputTracks()[iTrack].CSide() ^ (slice >= 18)) ? -mTZOffset : mTZOffset) : Merger->GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(slice, mTZOffset, Merger->Param().continuousMaxTimeBin); + const float zOffset = Merger->Param().par.earlyTpcTransform ? ((Merger->OutputTracks()[iTrack].CSide() ^ (slice >= 18)) ? -mTZOffset : mTZOffset) : Merger->GetConstantMem()->calibObjects.fastTransform->convVertexTimeToZOffset(slice, mTZOffset, Merger->Param().par.continuousMaxTimeBin); const float y0 = row.Grid().YMin(); const float stepY = row.HstepY(); const float z0 = row.Grid().ZMin() - zOffset; // We can use our own ZOffset, since this is only used temporarily anyway @@ -505,7 +505,7 @@ GPUd() void GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestrict const float sy21 = 1.f / sy2; const float sz21 = 1.f / sz2; float nY, nZ; - if (Merger->Param().earlyTpcTransform) { + if (Merger->Param().par.earlyTpcTransform) { nY = Y; nZ = Z; } else { @@ -606,7 +606,7 @@ GPUdii() void GPUTPCGMTrackParam::RefitLoop(const GPUTPCGMMerger* GPUrestrict() prop.SetMaterialTPC(); prop.SetPolynomialField(&Merger->Param().polynomialField); prop.SetMaxSinPhi(GPUCA_MAX_SIN_PHI); - prop.SetToyMCEventsFlag(Merger->Param().ToyMCEventsFlag); + prop.SetToyMCEventsFlag(Merger->Param().par.ToyMCEventsFlag); prop.SetMatLUT(Merger->Param().rec.useMatLUT ? Merger->GetConstantMem()->calibObjects.matLUT : nullptr); prop.SetSeedingErrors(false); prop.SetFitInProjections(true); @@ -796,7 +796,7 @@ GPUdni() void GPUTPCGMTrackParam::AttachClustersMirror(const GPUTPCGMMerger* GPU GPUd() void GPUTPCGMTrackParam::ShiftZ2(const GPUTPCGMMergedTrackHit* clusters, GPUTPCGMMergedTrackHitXYZ* clustersXYZ, const GPUTPCGMMerger* merger, int N) { float tzInner, tzOuter; - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { tzInner = clustersXYZ[N - 1].z; tzOuter = clustersXYZ[0].z; } else { @@ -809,7 +809,7 @@ GPUd() void GPUTPCGMTrackParam::ShiftZ2(const GPUTPCGMMergedTrackHit* clusters, GPUd() void GPUTPCGMTrackParam::ShiftZ(const GPUTPCGMMerger* GPUrestrict() merger, int slice, float tz1, float tz2) { - if (!merger->Param().ContinuousTracking) { + if (!merger->Param().par.ContinuousTracking) { return; } const float cosPhi = CAMath::Abs(mP[2]) < 1.f ? CAMath::Sqrt(1 - mP[2] * mP[2]) : 0.f; @@ -834,7 +834,7 @@ GPUd() void GPUTPCGMTrackParam::ShiftZ(const GPUTPCGMMerger* GPUrestrict() merge z0 = z0 > 0 ? 250.f : -250.f; } float deltaZ = mP[1] - z0; - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { mTZOffset += deltaZ; mP[1] -= deltaZ; deltaZ = 0; @@ -982,7 +982,7 @@ GPUd() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() tr GPUTPCGMTrackParam t = track.Param(); float Alpha = track.Alpha(); CADEBUG(int nTrackHitsOld = nTrackHits; float ptOld = t.QPt()); - bool ok = t.Fit(merger, iTrk, merger->Clusters() + track.FirstClusterRef(), merger->ClustersXYZ() + track.FirstClusterRef(), nTrackHits, NTolerated, Alpha, attempt, GPUCA_MAX_SIN_PHI, &track.OuterParam(), merger->Param().dodEdx ? &track.dEdxInfo() : nullptr); + bool ok = t.Fit(merger, iTrk, merger->Clusters() + track.FirstClusterRef(), merger->ClustersXYZ() + track.FirstClusterRef(), nTrackHits, NTolerated, Alpha, attempt, GPUCA_MAX_SIN_PHI, &track.OuterParam(), merger->Param().par.dodEdx ? &track.dEdxInfo() : nullptr); CADEBUG(printf("Finished Fit Track %d\n", iTrk)); CADEBUG(printf("OUTPUT hits %d -> %d+%d = %d, QPt %f -> %f, SP %f, ok %d chi2 %f chi2ndf %f\n", nTrackHitsOld, nTrackHits, NTolerated, nTrackHits + NTolerated, ptOld, t.QPt(), t.SinPhi(), (int)ok, t.Chi2(), t.Chi2() / CAMath::Max(1, nTrackHits))); @@ -996,7 +996,7 @@ GPUd() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() tr NTolerated = 0; // Clusters not fit but tollerated for track length cut t = track.Param(); Alpha = track.Alpha(); - ok = t.Fit(merger, iTrk, merger->Clusters() + track.FirstClusterRef(), merger->ClustersXYZ() + track.FirstClusterRef(), nTrackHits, NTolerated, Alpha, 1, GPUCA_MAX_SIN_PHI, &track.OuterParam(), merger->Param().dodEdx ? &track.dEdxInfo() : nullptr); + ok = t.Fit(merger, iTrk, merger->Clusters() + track.FirstClusterRef(), merger->ClustersXYZ() + track.FirstClusterRef(), nTrackHits, NTolerated, Alpha, 1, GPUCA_MAX_SIN_PHI, &track.OuterParam(), merger->Param().par.dodEdx ? &track.dEdxInfo() : nullptr); } else { unsigned int nRefit = CAMath::AtomicAdd(&merger->Memory()->nRetryRefit, 1u); merger->RetryRefitIds()[nRefit] = iTrk; @@ -1017,7 +1017,7 @@ GPUd() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() tr const GPUParam& GPUrestrict() param = merger->Param(); float alphaa = param.Alpha(merger->Clusters()[ind].slice); float xx, yy, zz; - if (merger->Param().earlyTpcTransform) { + if (merger->Param().par.earlyTpcTransform) { xx = merger->ClustersXYZ()[ind].x; yy = merger->ClustersXYZ()[ind].y; zz = merger->ClustersXYZ()[ind].z - track.Param().GetTZOffset(); diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx index 8c4cecc096de7..0498d0a44c9b6 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx @@ -50,7 +50,7 @@ GPUd() int GPUTPCGlobalTracking::PerformGlobalTrackingRun(GPUTPCTracker& tracker GPUTPCTrackLinearisation t0(tParam); do { rowIndex += direction; - if (!tParam.TransportToX(tracker.Row(rowIndex).X(), t0, tracker.Param().ConstBz, GPUCA_MAX_SIN_PHI)) { + if (!tParam.TransportToX(tracker.Row(rowIndex).X(), t0, tracker.Param().par.ConstBz, GPUCA_MAX_SIN_PHI)) { return (0); // Reuse t0 linearization until we are in the next sector } // GPUInfo("Transported X %f Y %f Z %f SinPhi %f DzDs %f QPt %f SignCosPhi %f (MaxY %f)", tParam.X(), tParam.Y(), tParam.Z(), tParam.SinPhi(), tParam.DzDs(), tParam.QPt(), tParam.SignCosPhi(), Row(rowIndex).MaxY()); @@ -86,7 +86,7 @@ GPUd() int GPUTPCGlobalTracking::PerformGlobalTrackingRun(GPUTPCTracker& tracker if (rowHit != CALINK_INVAL) { // GPUInfo("New track: entry %d, row %d, hitindex %d", i, rowIndex, mTrackletRowHits[rowIndex * tracker.CommonMemory()->nTracklets]); tracker.TrackHits()[hitId + i].Set(rowIndex, rowHit); - // if (i == 0) tParam.TransportToX(Row(rowIndex).X(), Param().ConstBz(), GPUCA_MAX_SIN_PHI); //Use transport with new linearisation, we have changed the track in between - NOT needed, fitting will always start at outer end of global track! + // if (i == 0) tParam.TransportToX(Row(rowIndex).X(), Param().par.ConstBz(), GPUCA_MAX_SIN_PHI); //Use transport with new linearisation, we have changed the track in between - NOT needed, fitting will always start at outer end of global track! i++; } rowIndex++; @@ -128,11 +128,11 @@ GPUd() void GPUTPCGlobalTracking::PerformGlobalTracking(int nBlocks, int nThread } if (!right && Y < -row.MaxY() * GPUCA_GLOBAL_TRACKING_Y_RANGE_LOWER) { // GPUInfo("Track %d, lower row %d, left border (%f of %f)", i, mTrackHits[tmpHit].RowIndex(), Y, -row.MaxY()); - PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, -tracker.Param().DAlpha, -1); + PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, -tracker.Param().par.DAlpha, -1); } if (right && Y > row.MaxY() * GPUCA_GLOBAL_TRACKING_Y_RANGE_LOWER) { // GPUInfo("Track %d, lower row %d, right border (%f of %f)", i, mTrackHits[tmpHit].RowIndex(), Y, row.MaxY()); - PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, tracker.Param().DAlpha, -1); + PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, tracker.Param().par.DAlpha, -1); } } } @@ -149,11 +149,11 @@ GPUd() void GPUTPCGlobalTracking::PerformGlobalTracking(int nBlocks, int nThread } if (!right && Y < -row.MaxY() * GPUCA_GLOBAL_TRACKING_Y_RANGE_UPPER) { // GPUInfo("Track %d, upper row %d, left border (%f of %f)", i, mTrackHits[tmpHit].RowIndex(), Y, -row.MaxY()); - PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, -tracker.Param().DAlpha, 1); + PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, -tracker.Param().par.DAlpha, 1); } if (right && Y > row.MaxY() * GPUCA_GLOBAL_TRACKING_Y_RANGE_UPPER) { // GPUInfo("Track %d, upper row %d, right border (%f of %f)", i, mTrackHits[tmpHit].RowIndex(), Y, row.MaxY()); - PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, tracker.Param().DAlpha, 1); + PerformGlobalTrackingRun(sliceTarget, smem, tracker, i, rowIndex, tracker.Param().par.DAlpha, 1); } } } diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx index ddf0c76d5ad33..22bb02f75a61f 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx @@ -39,7 +39,7 @@ void GPUTPCSliceData::InitializeRows(const MEM_CONSTANT(GPUParam) & p) } for (int i = 0; i < GPUCA_ROW_COUNT; ++i) { mRows[i].mX = p.tpcGeometry.Row2X(i); - mRows[i].mMaxY = CAMath::Tan(p.DAlpha / 2.) * mRows[i].mX; + mRows[i].mMaxY = CAMath::Tan(p.par.DAlpha / 2.) * mRows[i].mX; } } @@ -111,7 +111,7 @@ void* GPUTPCSliceData::SetPointersRows(void* mem) GPUd() void GPUTPCSliceData::GetMaxNBins(GPUconstantref() const MEM_CONSTANT(GPUConstantMem) * mem, GPUTPCRow* GPUrestrict() row, int& maxY, int& maxZ) { maxY = row->mMaxY * 2.f / GPUCA_MIN_BIN_SIZE + 1; - maxZ = mem->param.continuousMaxTimeBin > 0 ? mem->calibObjects.fastTransform->convTimeToZinTimeFrame(0, 0, mem->param.continuousMaxTimeBin) + 50 : 300; + maxZ = mem->param.par.continuousMaxTimeBin > 0 ? mem->calibObjects.fastTransform->convTimeToZinTimeFrame(0, 0, mem->param.par.continuousMaxTimeBin) + 50 : 300; maxZ = maxZ / GPUCA_MIN_BIN_SIZE + 1; } @@ -159,7 +159,7 @@ GPUdii() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int #ifdef GPUCA_GPUCODE constexpr bool EarlyTransformWithoutClusterNative = false; #else - bool EarlyTransformWithoutClusterNative = mem->param.earlyTpcTransform && mem->ioPtrs.clustersNative == nullptr; + bool EarlyTransformWithoutClusterNative = mem->param.par.earlyTpcTransform && mem->ioPtrs.clustersNative == nullptr; #endif int* tmpHitIndex = nullptr; const unsigned int* NumberOfClustersInRow = nullptr; @@ -172,7 +172,7 @@ GPUdii() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int unsigned int NumberOfClustersInRowA[GPUCA_ROW_COUNT]; vecpod<int> tmpHitIndexA; - if (EarlyTransformWithoutClusterNative) { // Implies mem->param.earlyTpcTransform but no ClusterNative present + if (EarlyTransformWithoutClusterNative) { // Implies mem->param.par.earlyTpcTransform but no ClusterNative present NumberOfClustersInRow = NumberOfClustersInRowA; RowOffsets = RowOffsetsA; tmpHitIndexA.resize(mNumberOfHits); @@ -256,7 +256,7 @@ GPUdii() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int UpdateMinMaxYZ(yMin, yMax, zMin, zMax, YZData[RowOffset + i].x, YZData[RowOffset + i].y); } } else { - if (mem->param.earlyTpcTransform) { // Early transform case with ClusterNative present + if (mem->param.par.earlyTpcTransform) { // Early transform case with ClusterNative present for (unsigned int i = iThread; i < NumberOfClusters; i += nThreads) { float2 tmp; tmp.x = mClusterData[RowOffset + i].y; @@ -393,7 +393,7 @@ GPUdii() int GPUTPCSliceData::InitFromClusterData(int nBlocks, int nThreads, int if (iThread == 0) { const float maxAbsZ = CAMath::Max(CAMath::Abs(tmpMinMax[2]), CAMath::Abs(tmpMinMax[3])); - if (maxAbsZ > 300 && !mem->param.ContinuousTracking) { + if (maxAbsZ > 300 && !mem->param.par.ContinuousTracking) { mem->errorCodes.raiseError(GPUErrors::ERROR_SLICEDATA_Z_OVERFLOW, (unsigned int)maxAbsZ); return 1; } diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx index af45c60ee9bdf..5db4985b15cc4 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx @@ -253,7 +253,7 @@ GPUh() void GPUTPCTracker::WriteOutput() unsigned char flags; unsigned short amp; int id; - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { origX = mData.ClusterData()[clusterIndex].x; origY = mData.ClusterData()[clusterIndex].y; origZ = mData.ClusterData()[clusterIndex].z; @@ -290,7 +290,7 @@ GPUh() void GPUTPCTracker::WriteOutput() mOutput->SetNTracks(nStoredTracks); mOutput->SetNLocalTracks(nStoredLocalTracks); mOutput->SetNTrackClusters(nStoredHits); - if (Param().debugLevel >= 3) { + if (Param().par.debugLevel >= 3) { GPUInfo("Slice %d, Output: Tracks %d, local tracks %d, hits %d", mISlice, nStoredTracks, nStoredLocalTracks, nStoredHits); } } diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h index d948662d91774..6f70b47a96464 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h @@ -111,19 +111,19 @@ class GPUTPCTracker : public GPUProcessor GPUdi() static void GetErrors2Seeding(const MEM_CONSTANT(GPUParam) & param, int iRow, const MEM_LG2(GPUTPCTrackParam) & t, float& ErrY2, float& ErrZ2) { // param.GetClusterErrors2( iRow, param.GetContinuousTracking() != 0. ? 125. : t.Z(), t.SinPhi(), t.DzDs(), ErrY2, ErrZ2 ); - param.GetClusterRMS2(iRow, param.ContinuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), ErrY2, ErrZ2); + param.GetClusterRMS2(iRow, param.par.ContinuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), ErrY2, ErrZ2); } MEM_CLASS_PRE2() GPUdi() void GetErrors2Seeding(int iRow, const MEM_LG2(GPUTPCTrackParam) & t, float& ErrY2, float& ErrZ2) const { // Param().GetClusterErrors2( iRow, Param().GetContinuousTracking() != 0. ? 125. : t.Z(), t.SinPhi(), t.DzDs(), ErrY2, ErrZ2 ); - Param().GetClusterRMS2(iRow, Param().ContinuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), ErrY2, ErrZ2); + Param().GetClusterRMS2(iRow, Param().par.ContinuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), ErrY2, ErrZ2); } GPUdi() void GetErrors2Seeding(int iRow, float z, float sinPhi, float DzDs, float& ErrY2, float& ErrZ2) const { // Param().GetClusterErrors2( iRow, Param().GetContinuousTracking() != 0. ? 125. : z, sinPhi, DzDs, ErrY2, ErrZ2 ); - Param().GetClusterRMS2(iRow, Param().ContinuousTracking != 0.f ? 125.f : z, sinPhi, DzDs, ErrY2, ErrZ2); + Param().GetClusterRMS2(iRow, Param().par.ContinuousTracking != 0.f ? 125.f : z, sinPhi, DzDs, ErrY2, ErrZ2); } void SetupCommonMemory(); diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx index 7f113aa94ca04..1b9f6a0af18f7 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackerDump.cxx @@ -27,7 +27,7 @@ using namespace GPUCA_NAMESPACE::gpu; void GPUTPCTracker::DumpOutput(std::ostream& out) { - if (Param().earlyTpcTransform) { + if (Param().par.earlyTpcTransform) { out << "Slice " << mISlice << "\n"; const GPUTPCTrack* track = (Output())->GetFirstTrack(); for (unsigned int j = 0; j < (Output())->NTracks(); j++) { diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx index 1c605118d6e2b..42590e8f64849 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx @@ -140,7 +140,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int tParam.SetX(x); tParam.SetY(y); r.mLastY = y; - if (tracker.Param().ContinuousTracking) { + if (tracker.Param().par.ContinuousTracking) { tParam.SetZ(0.f); r.mLastZ = 0.f; tParam.SetZOffset(z); @@ -186,7 +186,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int } CADEBUG( printf("%14s: FIT TRACK ROW %3d X %8.3f -", "", iRow, tParam.X()); for (int i = 0; i < 5; i++) { printf(" %8.3f", tParam.Par()[i]); } printf(" -"); for (int i = 0; i < 15; i++) { printf(" %8.3f", tParam.Cov()[i]); } printf("\n")); - if (!tParam.TransportToX(x, sinPhi, cosPhi, tracker.Param().ConstBz, GPUCA_MAX_SIN_PHI)) { + if (!tParam.TransportToX(x, sinPhi, cosPhi, tracker.Param().par.ConstBz, GPUCA_MAX_SIN_PHI)) { rowHit = CALINK_INVAL; break; } @@ -257,7 +257,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int float err2Y, err2Z; CADEBUG( printf("%14s: SEA TRACK ROW %3d X %8.3f -", "", iRow, tParam.X()); for (int i = 0; i < 5; i++) { printf(" %8.3f", tParam.Par()[i]); } printf(" -"); for (int i = 0; i < 15; i++) { printf(" %8.3f", tParam.Cov()[i]); } printf("\n")); - if (!tParam.TransportToX(x, tParam.SinPhi(), tParam.GetCosPhi(), tracker.Param().ConstBz, GPUCA_MAX_SIN_PHI_LOW)) { + if (!tParam.TransportToX(x, tParam.SinPhi(), tParam.GetCosPhi(), tracker.Param().par.ConstBz, GPUCA_MAX_SIN_PHI_LOW)) { r.mGo = 0; rowHit = CALINK_INVAL; break; @@ -370,7 +370,6 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::DoTracklet(GPUconstantref() MEM_GLO } r.mStage = 0; r.mNHits = 0; - // if (tracker.Param().ISlice() != 35 && tracker.Param().ISlice() != 34 || r.mISH == CALINK_INVAL) {StoreTracklet( 0, 0, 0, 0, s, r, tracker, tParam );return;} #ifdef __HIPCC__ // Todo: fixme! for (int k = -1; ++k < 2; /*k++*/) { @@ -392,7 +391,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::DoTracklet(GPUconstantref() MEM_GLO StoreTracklet(0, 0, 0, 0, s, r, tracker, tParam, rowHits); } else { r.mNMissed = 0; - if ((r.mGo = (tParam.TransportToX(tracker.Row(r.mEndRow).X(), tracker.Param().ConstBz, GPUCA_MAX_SIN_PHI) && tParam.Filter(r.mLastY, r.mLastZ, tParam.Err2Y() * 0.5f, tParam.Err2Z() * 0.5f, GPUCA_MAX_SIN_PHI_LOW, true)))) { + if ((r.mGo = (tParam.TransportToX(tracker.Row(r.mEndRow).X(), tracker.Param().par.ConstBz, GPUCA_MAX_SIN_PHI) && tParam.Filter(r.mLastY, r.mLastZ, tParam.Err2Y() * 0.5f, tParam.Err2Z() * 0.5f, GPUCA_MAX_SIN_PHI_LOW, true)))) { CADEBUG( printf("%14s: SEA BACK ROW %3d X %8.3f -", "", iRow, tParam.X()); for (int i = 0; i < 5; i++) { printf(" %8.3f", tParam.Par()[i]); } printf(" -"); for (int i = 0; i < 15; i++) { printf(" %8.3f", tParam.Cov()[i]); } printf("\n")); float err2Y, err2Z; diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index bf32ad254f192..1a5c77b0a5ecb 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -76,7 +76,7 @@ using namespace GPUCA_NAMESPACE::gpu; #define SEPERATE_GLOBAL_TRACKS_LIMIT (mSeparateGlobalTracks ? tGLOBALTRACK : TRACK_TYPE_ID_LIMIT) -#define GET_CID(slice, i) (tracker.Param().earlyTpcTransform ? tracker.ClusterData()[i].id : (tracker.GetConstantMem()->ioPtrs.clustersNative->clusterOffset[slice][0] + i)) +#define GET_CID(slice, i) (tracker.Param().par.earlyTpcTransform ? tracker.ClusterData()[i].id : (tracker.GetConstantMem()->ioPtrs.clustersNative->clusterOffset[slice][0] + i)) #ifdef GPUCA_STANDALONE namespace GPUCA_NAMESPACE::gpu @@ -741,7 +741,7 @@ GPUDisplay::vboList GPUDisplay::DrawClusters(const GPUTPCTracker& tracker, int s } } else if (mMarkClusters) { short flags; - if (tracker.Param().earlyTpcTransform) { + if (tracker.Param().par.earlyTpcTransform) { flags = tracker.ClusterData()[cidInSlice].flags; } else { flags = tracker.GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cid].getFlags(); @@ -972,7 +972,7 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s float alpha = param().Alpha(slice); if (iMC == 0) { trkParam.Set(track->GetParam()); - if (mMerger.Param().earlyTpcTransform) { + if (mMerger.Param().par.earlyTpcTransform) { auto cl = mMerger.ClustersXYZ()[track->FirstClusterRef() + lastCluster]; // Todo: Remove direct usage of merger x = cl.x; ZOffset = track->GetParam().GetTZOffset(); @@ -981,7 +981,7 @@ void GPUDisplay::DrawFinal(int iSlice, int /*iCol*/, GPUTPCGMPropagator* prop, s const auto& cln = mMerger.GetConstantMem()->ioPtrs.clustersNative->clustersLinear[cl.num]; float y, z; GPUTPCConvertImpl::convert(*mMerger.GetConstantMem(), cl.slice, cl.row, cln.getPad(), cln.getTime(), x, y, z); - ZOffset = mMerger.GetConstantMem()->calibObjects.fastTransform->convTimeToZinTimeFrame(slice, track->GetParam().GetTZOffset(), mMerger.Param().continuousMaxTimeBin); + ZOffset = mMerger.GetConstantMem()->calibObjects.fastTransform->convTimeToZinTimeFrame(slice, track->GetParam().GetTZOffset(), mMerger.Param().par.continuousMaxTimeBin); } } else { const GPUTPCMCInfo& mc = ioptrs().mcInfosTPC[i]; @@ -1262,10 +1262,10 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) continue; } int row = 0; - unsigned int nCls = mMerger.Param().earlyTpcTransform ? ioptrs().nClusterData[iSlice] : ioptrs().clustersNative->nClustersSector[iSlice]; + unsigned int nCls = mMerger.Param().par.earlyTpcTransform ? ioptrs().nClusterData[iSlice] : ioptrs().clustersNative->nClustersSector[iSlice]; for (unsigned int i = 0; i < nCls; i++) { int cid; - if (mMerger.Param().earlyTpcTransform) { + if (mMerger.Param().par.earlyTpcTransform) { const auto& cl = ioptrs().clusterData[iSlice][i]; cid = cl.id; } else { @@ -1280,7 +1280,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) break; } float4* ptr = &mGlobalPos[cid]; - if (mMerger.Param().earlyTpcTransform) { + if (mMerger.Param().par.earlyTpcTransform) { const auto& cl = ioptrs().clusterData[iSlice][i]; mChain->GetParam().Slice2Global(iSlice, cl.x + mXadd, cl.y, cl.z, &ptr->x, &ptr->y, &ptr->z); } else { @@ -1474,7 +1474,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) nextViewMatrix = nextViewMatrix * HMM_Translate({-vals[0], -vals[1], -vals[2]}); } } else if (mResetScene) { - nextViewMatrix = nextViewMatrix * HMM_Translate({0, 0, param().ContinuousTracking ? (-mMaxClusterZ / GL_SCALE_FACTOR - 8) : -8}); + nextViewMatrix = nextViewMatrix * HMM_Translate({0, 0, param().par.ContinuousTracking ? (-mMaxClusterZ / GL_SCALE_FACTOR - 8) : -8}); mCfg.pointSize = 2.0; mCfg.drawSlice = -1; @@ -1662,7 +1662,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) prop.SetMaxSinPhi(.999); prop.SetMaterialTPC(); prop.SetPolynomialField(&mMerger.Param().polynomialField); - prop.SetToyMCEventsFlag(mMerger.Param().ToyMCEventsFlag); + prop.SetToyMCEventsFlag(mMerger.Param().par.ToyMCEventsFlag); GPUCA_OPENMP(barrier) GPUCA_OPENMP(for) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 298c5f46ee310..0aa569f33cb3c 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -904,7 +904,7 @@ void GPUQA::RunQA(bool matchOnly) prop.SetMaxSinPhi(.999); prop.SetMaterialTPC(); prop.SetPolynomialField(&mTracking->GetParam().polynomialField); - prop.SetToyMCEventsFlag(mTracking->GetParam().ToyMCEventsFlag); + prop.SetToyMCEventsFlag(mTracking->GetParam().par.ToyMCEventsFlag); for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { if (mConfig.writeMCLabels) { @@ -983,7 +983,7 @@ void GPUQA::RunQA(bool matchOnly) prop.SetTrack(¶m, alpha); bool inFlyDirection = 0; #ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (mTracking->GetParam().continuousMaxTimeBin ? 0 : ((param.Z() - mc1.z) * (param.Z() - mc1.z))) > (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X)) * (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X))) { + if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (mTracking->GetParam().par.continuousMaxTimeBin ? 0 : ((param.Z() - mc1.z) * (param.Z() - mc1.z))) > (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X)) * (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X))) { #else // Consider Z offset (pseudo-tf mc tracks have shifted z) if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (param.Z() + param.TZOffset() - mc1.z) * (param.Z() + param.TZOffset() - mc1.z) > 25) { // TODO: fix TZOffset #endif @@ -994,7 +994,7 @@ void GPUQA::RunQA(bool matchOnly) continue; } #ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || (mTracking->GetParam().continuousMaxTimeBin == 0 && fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f))) { // TODO: fix TZOffset here + if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || (mTracking->GetParam().par.continuousMaxTimeBin == 0 && fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f))) { // TODO: fix TZOffset here #else if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f)) { // TODO: fix TZOffset here #endif @@ -1340,7 +1340,7 @@ void GPUQA::RunQA(bool matchOnly) // Create CSV DumpTrackHits if (mConfig.csvDump) { - if (!mTracking->GetParam().earlyTpcTransform) { + if (!mTracking->GetParam().par.earlyTpcTransform) { GPUError("Unsupported settings for csv dump\n"); return; } diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index ddb3874a677a0..d589ab09a803c 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -536,7 +536,7 @@ int LoadEvent(int iEvent, int x) } } - if (!rec->GetParam().earlyTpcTransform && chainTracking->mIOPtrs.clustersNative == nullptr && chainTracking->mIOPtrs.tpcPackedDigits == nullptr && chainTracking->mIOPtrs.tpcZS == nullptr) { + if (!rec->GetParam().par.earlyTpcTransform && chainTracking->mIOPtrs.clustersNative == nullptr && chainTracking->mIOPtrs.tpcPackedDigits == nullptr && chainTracking->mIOPtrs.tpcZS == nullptr) { printf("Need cluster native data for on-the-fly TPC transform\n"); return 1; } diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.h b/GPU/GPUTracking/Standalone/utils/qconfig.h index cc2a262989332..80cad5f540275 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.h +++ b/GPU/GPUTracking/Standalone/utils/qconfig.h @@ -88,17 +88,24 @@ enum qConfigRetVal { qcrOK = 0, name& tmp = instance; \ bool tmpfound = true; \ if (found) { \ - ; \ } #define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ { \ constexpr const char* preopt = preoptname; \ + (void)preopt; \ constexpr const char preoptshort = preoptnameshort; \ + (void)preoptshort; \ name& tmp = parent.instance; \ + (void)tmp; \ bool tmpfound = true; \ if (found) { \ - ; \ + } + +#define BeginHiddenConfig(name, instance) \ + { \ + bool tmpfound; \ + if (0) { \ } #define EndConfig() \ @@ -160,11 +167,15 @@ enum qConfigRetVal { qcrOK = 0, printf("\n"); #define BeginSubConfig(name, instance, parent, preoptname, preoptnameshort, descr) \ const char* qon_mxcat(qConfig_subconfig_, name) = preoptnameshort == 0 ? (qon_mxstr(name) ": --" preoptname "\n\t\t" descr) : (qon_mxstr(name) ": -" qon_mxstr('a') " (--" preoptname ")\n\t\t" descr); \ + (void)qon_mxcat(qConfig_subconfig_, name); \ if (subConfig == nullptr || strcmp(subConfig, followSub == 2 ? qon_mxstr(name) : preoptname) == 0) { \ constexpr const char* preopt = preoptname; \ + (void)preopt; \ constexpr const char preoptshort = preoptnameshort; \ + (void)preoptshort; \ char argBuffer[2] = {preoptnameshort, 0}; \ printf("\n %s: (--%s%s%s)\n", descr, preoptname, preoptnameshort == 0 ? "" : " or -", argBuffer); +#define BeginHiddenConfig(name, instance) { #define EndConfig() } #define AddHelp(cmd, cmdshort) qConfigType<void*>::qConfigHelpOption("help", "help", nullptr, cmd, cmdshort, preopt, preoptshort, 3, "Show usage information"); #define AddHelpAll(cmd, cmdshort) qConfigType<void*>::qConfigHelpOption("help all", "help all", nullptr, cmd, cmdshort, preopt, preoptshort, 3, "Show usage info including all subparameters"); @@ -207,6 +218,9 @@ enum qConfigRetVal { qcrOK = 0, name& tmp = parent.instance; \ blockName = std::string("\t") + qon_mxstr(name) + "."; \ std::cout << "\t" << qon_mxstr(name) << "\n"; +#define BeginHiddenConfig(name, instance) \ + if (0) { \ + name tmp; #define EndConfig() } // End QCONFIG_PRINT @@ -231,12 +245,13 @@ enum qConfigRetVal { qcrOK = 0, #define AddVariable(name, type, default) out << qon_mxstr(type) << " " << qon_mxstr(name) << ";\n"; #define AddOptionArray(name, type, count, default, optname, optnameshort, help, ...) out << qon_mxstr(type) << " " << qon_mxstr(name) << "[" << qon_mxstr(count) << "];\n"; #define AddOptionVec(name, type, optname, optnameshort, help, ...) out << "std::vector<" << qon_mxstr(type) << "> " << qon_mxstr(name) << ";\n"; -#define AddOptionRTC(name, type, default, optname, optnameshort, help, ...) \ +#define AddVariableRTC(name, type, default) \ if (useConstexpr) { \ out << "static constexpr " << qon_mxstr(type) << " " << qon_mxstr(name) << " = " << qConfig::print_type(std::get<const qConfigCurrentType*>(tSrc)->name) << ";\n"; \ } else { \ AddOption(name, type, default, optname, optnameshort, help); \ } +#define AddOptionRTC(name, type, default, optname, optnameshort, help, ...) AddVariableRTC(name, type, default) #define BeginConfig(name, instance) \ { \ using qConfigCurrentType = name; \ @@ -261,6 +276,7 @@ enum qConfigRetVal { qcrOK = 0, for (unsigned int i = 0; i < in.name.size(); i++) \ out.name[i] = in.name[i]; #define AddOptionRTC(name, type, default, optname, optnameshort, help, ...) +#define AddVariableRTC(name, type, default) #define BeginConfig(name, instance) \ template <class T> \ void qConfigConvertRtc(T& out, const name& in) \ @@ -296,6 +312,7 @@ enum qConfigRetVal { qcrOK = 0, #endif #ifdef QCONFIG_GENRTC #define AddOptionRTC(name, type, default, optname, optnameshort, help, ...) static constexpr type name = default; +#define AddVariableRTC(name, type, default) static constexpr type name = default; #else #define AddCustomCPP(...) __VA_ARGS__ #endif @@ -341,12 +358,19 @@ enum qConfigRetVal { qcrOK = 0, #ifndef AddOptionRTC #define AddOptionRTC(...) AddOption(__VA_ARGS__) #endif +#ifndef AddVariableRTC +#define AddVariableRTC(...) AddVariable(__VA_ARGS__) +#endif +#ifndef BeginHiddenConfig +#define BeginHiddenConfig(name, instance) BeginSubConfig(name, instance, , , , ) +#endif #include "qconfigoptions.h" #undef AddOption #undef AddOptionRTC #undef AddVariable +#undef AddVariableRTC #undef AddOptionSet #undef AddOptionVec #undef AddOptionArray @@ -354,6 +378,7 @@ enum qConfigRetVal { qcrOK = 0, #undef AddSubConfig #undef BeginConfig #undef BeginSubConfig +#undef BeginHiddenConfig #undef EndConfig #undef AddHelp #undef AddHelpAll diff --git a/GPU/GPUTracking/TPCConvert/GPUTPCConvert.cxx b/GPU/GPUTracking/TPCConvert/GPUTPCConvert.cxx index 9247ed1dcc56b..47edc6bd72727 100644 --- a/GPU/GPUTracking/TPCConvert/GPUTPCConvert.cxx +++ b/GPU/GPUTracking/TPCConvert/GPUTPCConvert.cxx @@ -23,7 +23,7 @@ void GPUTPCConvert::InitializeProcessor() {} void* GPUTPCConvert::SetPointersOutput(void* mem) { - if (mRec->GetParam().earlyTpcTransform) { + if (mRec->GetParam().par.earlyTpcTransform) { computePointerWithAlignment(mem, mClusters, mNClustersTotal); } return mem; diff --git a/GPU/GPUTracking/TPCConvert/GPUTPCConvertImpl.h b/GPU/GPUTracking/TPCConvert/GPUTPCConvertImpl.h index 654d4a00a61fb..3bd58e336ca50 100644 --- a/GPU/GPUTracking/TPCConvert/GPUTPCConvertImpl.h +++ b/GPU/GPUTracking/TPCConvert/GPUTPCConvertImpl.h @@ -28,8 +28,8 @@ class GPUTPCConvertImpl public: GPUd() static void convert(const GPUConstantMem& GPUrestrict() cm, int slice, int row, float pad, float time, float& GPUrestrict() x, float& GPUrestrict() y, float& GPUrestrict() z) { - if (cm.param.ContinuousTracking) { - cm.calibObjects.fastTransform->TransformInTimeFrame(slice, row, pad, time, x, y, z, cm.param.continuousMaxTimeBin); + if (cm.param.par.ContinuousTracking) { + cm.calibObjects.fastTransform->TransformInTimeFrame(slice, row, pad, time, x, y, z, cm.param.par.continuousMaxTimeBin); } else { cm.calibObjects.fastTransform->Transform(slice, row, pad, time, x, y, z); } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index 10abe93b69454..1e02bdd9cad04 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -132,7 +132,7 @@ void GPUTRDTracker_t<TRDTRK, PROP>::InitializeProcessor() Error("Init", "TRD geometry must be provided externally"); } - float Bz = Param().BzkG; + float Bz = Param().par.BzkG; GPUInfo("Initializing with B-field: %f kG", Bz); if (abs(abs(Bz) - 2) < 0.1) { // magnetic field +-0.2 T From 9afcdc5d69ee4829c04425e35223afdc37a8de36 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 3 Nov 2020 21:45:53 +0100 Subject: [PATCH 1250/1751] GPU: Use unsigned short to store dEdx charges on NVIDIA --- GPU/Common/GPUDefGPUParameters.h | 1 + GPU/GPUTracking/dEdx/GPUdEdx.cxx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 380e903b4e9cd..47aceb6e88be7 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -135,6 +135,7 @@ #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_NO_ATOMIC_PRECHECK 1 #define GPUCA_COMP_GATHER_KERNEL 0 + #define GPUCA_DEDX_STORAGE_TYPE unsigned short // #define GPUCA_USE_TEXTURES #elif defined(GPUCA_GPUTYPE_OPENCL) #elif defined(GPUCA_GPUCODE) diff --git a/GPU/GPUTracking/dEdx/GPUdEdx.cxx b/GPU/GPUTracking/dEdx/GPUdEdx.cxx index 571e940aea59d..2fe03a6e20cb3 100644 --- a/GPU/GPUTracking/dEdx/GPUdEdx.cxx +++ b/GPU/GPUTracking/dEdx/GPUdEdx.cxx @@ -62,7 +62,7 @@ GPUd() float GPUdEdx::GetSortTruncMean(GPUCA_DEDX_STORAGE_TYPE* GPUrestrict() ar CAAlgo::sort(array, array + count); float mean = 0; for (int i = trunclow; i < trunchigh; i++) { - mean += array[i] * (1.f / scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::factor); + mean += (float)array[i] * (1.f / scalingFactor<GPUCA_DEDX_STORAGE_TYPE>::factor); } return (mean / (trunchigh - trunclow)); } From 54d893afbfbe4482cdd63b396015a7a119312233 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 3 Nov 2020 21:52:46 +0100 Subject: [PATCH 1251/1751] GPU: Use half as storage type for interpolation errors on NVIDIA --- GPU/Common/GPUDefGPUParameters.h | 4 ++++ GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h | 6 ++---- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 47aceb6e88be7..2eabbdc704fc2 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -136,6 +136,7 @@ #define GPUCA_NO_ATOMIC_PRECHECK 1 #define GPUCA_COMP_GATHER_KERNEL 0 #define GPUCA_DEDX_STORAGE_TYPE unsigned short + #define GPUCA_MERGER_INTERPOLATION_ERROR_TYPE half // #define GPUCA_USE_TEXTURES #elif defined(GPUCA_GPUTYPE_OPENCL) #elif defined(GPUCA_GPUCODE) @@ -358,6 +359,9 @@ #ifndef GPUCA_DEDX_STORAGE_TYPE #define GPUCA_DEDX_STORAGE_TYPE float #endif +#ifndef GPUCA_MERGER_INTERPOLATION_ERROR_TYPE +#define GPUCA_MERGER_INTERPOLATION_ERROR_TYPE float +#endif #ifndef GPUCA_WARP_SIZE #ifdef GPUCA_GPUCODE diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h b/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h index a40e29c181c2f..4911313921c8e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerTypes.h @@ -33,10 +33,8 @@ enum attachTypes { attachAttached = 0x40000000, attachFlagMask = 0xFC000000 }; struct InterpolationErrorHit { - float posY; - float errorY; - float posZ; - float errorZ; + float posY, posZ; + GPUCA_MERGER_INTERPOLATION_ERROR_TYPE errorY, errorZ; }; struct InterpolationErrors { diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index 64ed311224d31..8ad930d91fdb4 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -642,7 +642,7 @@ GPUd() int GPUTPCGMPropagator::Update(float posY, float posZ, int iRow, const GP GetErr2(err2Y, err2Z, param, posZ, iRow, clusterState); if (rejectChi2 >= 2) { - if (rejectChi2 == 3 && inter->errorY < 0) { + if (rejectChi2 == 3 && inter->errorY < (GPUCA_MERGER_INTERPOLATION_ERROR_TYPE)0) { rejectChi2 = 1; } else { int retVal = InterpolateReject(posY, posZ, clusterState, rejectChi2, inter, err2Y, err2Z); @@ -686,8 +686,8 @@ GPUd() int GPUTPCGMPropagator::InterpolateReject(float posY, float posZ, short c if (mFitInProjections || mT->NDF() <= 0) { const float Iz0 = inter->posY - mP[0]; const float Iz1 = inter->posZ - mP[1]; - const float Iw0 = 1.f / (mC[0] + inter->errorY); - const float Iw2 = 1.f / (mC[2] + inter->errorZ); + const float Iw0 = 1.f / (mC[0] + (float)inter->errorY); + const float Iw2 = 1.f / (mC[2] + (float)inter->errorZ); const float Ik00 = mC[0] * Iw0; const float Ik11 = mC[2] * Iw2; const float ImP0 = mP[0] + Ik00 * Iz0; @@ -704,8 +704,8 @@ GPUd() int GPUTPCGMPropagator::InterpolateReject(float posY, float posZ, short c } else { const float Iz0 = inter->posY - mP[0]; const float Iz1 = inter->posZ - mP[1]; - float Iw0 = mC[2] + inter->errorZ; - float Iw2 = mC[0] + inter->errorY; + float Iw0 = mC[2] + (float)inter->errorZ; + float Iw2 = mC[0] + (float)inter->errorY; float Idet = CAMath::Max(1e-10f, Iw0 * Iw2 - mC[1] * mC[1]); Idet = 1.f / Idet; Iw0 *= Idet; From 6a975242a9ae56fd76dca4a6c4d120942cd495e8 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 4 Nov 2020 20:03:53 +0100 Subject: [PATCH 1252/1751] GPU: Add yet another tpcCompression gather mode --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 3 ++ GPU/GPUTracking/Base/GPUSettingsList.h | 2 +- .../DataCompression/GPUTPCCompression.cxx | 21 +++++++--- .../DataCompression/GPUTPCCompression.h | 3 ++ GPU/GPUTracking/Global/GPUChainTracking.cxx | 39 +++++++++++++++---- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 3bf1c47e157dc..2fe51bece4f8e 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -601,6 +601,9 @@ void* GPUReconstruction::AllocateVolatileDeviceMemory(size_t size) if (mVolatileMemoryStart == nullptr) { mVolatileMemoryStart = mDeviceMemoryPool; } + if (size == 0) { + return nullptr; // Future GPU memory allocation is volatile + } char* retVal; GPUProcessor::computePointerWithAlignment(mDeviceMemoryPool, retVal, size); if (mDeviceMemoryPool > mDeviceMemoryPoolEnd) { diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index beb952583cb00..96d120a636d09 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -108,7 +108,7 @@ AddOption(nStreams, int, 8, "", 0, "Number of GPU streams / command queues") AddOption(trackletConstructorInPipeline, int, -1, "", 0, "Run tracklet constructor in the pipeline") AddOption(trackletSelectorInPipeline, int, -1, "", 0, "Run tracklet selector in the pipeline") AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fit") -AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode") +AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode (0: DMA transfer gather gpu to host, 1: serial DMA to host and gather by copy on CPU, 2. gather via GPU kernal DMA access, 3. gather on GPU via kernel, dma afterwards") AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") AddOption(runMC, bool, false, "", 0, "Process MC labels") AddOption(ompKernels, bool, true, "", 0, "Parallelize with OMP inside kernels instead of over slices") diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx index 99c1557cccbb6..02f141fe7baee 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompression.cxx @@ -19,6 +19,12 @@ using namespace GPUCA_NAMESPACE::gpu; void GPUTPCCompression::InitializeProcessor() {} +void* GPUTPCCompression::SetPointersOutputGPU(void* mem) +{ + SetPointersCompressedClusters(mem, *mOutputA, mOutputA->nAttachedClusters, mOutputA->nTracks, mOutputA->nUnattachedClusters, true); + return mem; +} + void* GPUTPCCompression::SetPointersOutputHost(void* mem) { computePointerWithoutAlignment(mem, mOutputFlat); @@ -29,7 +35,7 @@ void* GPUTPCCompression::SetPointersOutputHost(void* mem) void* GPUTPCCompression::SetPointersScratch(void* mem) { computePointerWithAlignment(mem, mClusterStatus, mMaxClusters); - if (mRec->GetProcessingSettings().tpcCompressionGatherMode == 2) { + if (mRec->GetProcessingSettings().tpcCompressionGatherMode >= 2) { computePointerWithAlignment(mem, mAttachedClusterFirstIndex, mMaxTracks); } if (mRec->GetProcessingSettings().tpcCompressionGatherMode != 1) { @@ -50,7 +56,7 @@ void* GPUTPCCompression::SetPointersOutput(void* mem) template <class T> void GPUTPCCompression::SetPointersCompressedClusters(void*& mem, T& c, unsigned int nClA, unsigned int nTr, unsigned int nClU, bool reducedClA) { - computePointerWithAlignment(mem, c.qTotU, nClU); + computePointerWithAlignment(mem, c.qTotU, nClU); // Do not reorder, qTotU ist used as first address in GPUChainTracking::RunTPCCompression computePointerWithAlignment(mem, c.qMaxU, nClU); computePointerWithAlignment(mem, c.flagsU, nClU); computePointerWithAlignment(mem, c.padDiffU, nClU); @@ -87,6 +93,7 @@ void* GPUTPCCompression::SetPointersMemory(void* mem) { computePointerWithAlignment(mem, mMemory); computePointerWithAlignment(mem, mOutput); + mOutputA = mOutput; return mem; } @@ -94,10 +101,14 @@ void GPUTPCCompression::RegisterMemoryAllocation() { AllocateAndInitializeLate(); mMemoryResOutputHost = mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersOutputHost, GPUMemoryResource::MEMORY_OUTPUT_FLAG | GPUMemoryResource::MEMORY_HOST | GPUMemoryResource::MEMORY_CUSTOM, "TPCCompressionOutputHost"); - if (mRec->GetProcessingSettings().tpcCompressionGatherMode != 2) { - mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersOutput, GPUMemoryResource::MEMORY_OUTPUT | GPUMemoryResource::MEMORY_STACK, "TPCCompressionOutput"); + if (mRec->GetProcessingSettings().tpcCompressionGatherMode == 3) { + mMemoryResOutputGPU = mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersOutputGPU, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_GPU | GPUMemoryResource::MEMORY_CUSTOM | GPUMemoryResource::MEMORY_STACK, "TPCCompressionOutputGPU"); + } + unsigned int stackScratch = (mRec->GetProcessingSettings().tpcCompressionGatherMode != 3) ? GPUMemoryResource::MEMORY_STACK : 0; + if (mRec->GetProcessingSettings().tpcCompressionGatherMode < 2) { + mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersOutput, GPUMemoryResource::MEMORY_OUTPUT | stackScratch, "TPCCompressionOutput"); } - mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCCompressionScratch"); + mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersScratch, GPUMemoryResource::MEMORY_SCRATCH | stackScratch, "TPCCompressionScratch"); mRec->RegisterMemoryAllocation(this, &GPUTPCCompression::SetPointersMemory, GPUMemoryResource::MEMORY_PERMANENT, "TPCCompressionMemory"); } diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompression.h b/GPU/GPUTracking/DataCompression/GPUTPCCompression.h index acc64b439c91b..b0f449bd81edb 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompression.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompression.h @@ -49,6 +49,7 @@ class GPUTPCCompression : public GPUProcessor void RegisterMemoryAllocation(); void SetMaxData(const GPUTrackingInOutPointers& io); + void* SetPointersOutputGPU(void* mem); void* SetPointersOutputHost(void* mem); void* SetPointersOutputPtrs(void* mem); void* SetPointersOutput(void* mem); @@ -79,6 +80,7 @@ class GPUTPCCompression : public GPUProcessor o2::tpc::CompressedClustersPtrs mPtrs; o2::tpc::CompressedClusters* mOutput = nullptr; + o2::tpc::CompressedClusters* mOutputA = nullptr; // Always points to host buffer o2::tpc::CompressedClustersFlat* mOutputFlat = nullptr; memory* mMemory = nullptr; @@ -96,6 +98,7 @@ class GPUTPCCompression : public GPUProcessor GPUd() static void truncateSignificantBits(T& val, unsigned int nBits, unsigned int max); short mMemoryResOutputHost = -1; + short mMemoryResOutputGPU = -1; }; template <class T> diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index ecad6f9b2b1ca..fbc0d64b2cd1c 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -306,6 +306,10 @@ bool GPUChainTracking::ValidateSettings() return false; } } + if (!(GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCCompression) && (ProcessingSettings().tpcCompressionGatherMode == 1 || ProcessingSettings().tpcCompressionGatherMode == 3)) { + GPUError("Invalid tpcCompressionGatherMode for compression on CPU"); + return false; + } return true; } @@ -2096,6 +2100,10 @@ int GPUChainTracking::RunTPCCompression() } } } + + if (ProcessingSettings().tpcCompressionGatherMode == 3) { + mRec->AllocateVolatileDeviceMemory(0); // make future device memory allocation volatile + } SetupGPUProcessor(&Compressor, true); new (Compressor.mMemory) GPUTPCCompression::memory; @@ -2124,6 +2132,12 @@ int GPUChainTracking::RunTPCCompression() O->nComppressionModes = param().rec.tpcCompressionModes; size_t outputSize = AllocateRegisteredMemory(Compressor.mMemoryResOutputHost, mOutputCompressedClusters); Compressor.mOutputFlat->set(outputSize, *Compressor.mOutput); + void* hostFlatPtr = Compressor.mOutput->qTotU; // First array as allocated in GPUTPCCompression::SetPointersCompressedClusters + size_t copySize = 0; + if (ProcessingSettings().tpcCompressionGatherMode == 3) { + CompressorShadow.mOutputA = Compressor.mOutput; + copySize = AllocateRegisteredMemory(Compressor.mMemoryResOutputGPU); // We overwrite Compressor.mOutput with the allocated output pointers on the GPU + } const o2::tpc::CompressedClustersPtrs* P = nullptr; HighResTimer* gatherTimer = nullptr; int outputStream = 0; @@ -2132,12 +2146,14 @@ int GPUChainTracking::RunTPCCompression() outputStream = mRec->NStreams() - 2; } - if (ProcessingSettings().tpcCompressionGatherMode == 2) { - void* devicePtr = mRec->getGPUPointer(Compressor.mOutputFlat); - if (devicePtr != Compressor.mOutputFlat) { - CompressedClustersPtrs& ptrs = *Compressor.mOutput; // We need to update the ptrs with the gpu-mapped version of the host address space - for (unsigned int i = 0; i < sizeof(ptrs) / sizeof(void*); i++) { - reinterpret_cast<char**>(&ptrs)[i] = reinterpret_cast<char**>(&ptrs)[i] + (reinterpret_cast<char*>(devicePtr) - reinterpret_cast<char*>(Compressor.mOutputFlat)); + if (ProcessingSettings().tpcCompressionGatherMode >= 2) { + if (ProcessingSettings().tpcCompressionGatherMode == 2) { + void* devicePtr = mRec->getGPUPointer(Compressor.mOutputFlat); + if (devicePtr != Compressor.mOutputFlat) { + CompressedClustersPtrs& ptrs = *Compressor.mOutput; // We need to update the ptrs with the gpu-mapped version of the host address space + for (unsigned int i = 0; i < sizeof(ptrs) / sizeof(void*); i++) { + reinterpret_cast<char**>(&ptrs)[i] = reinterpret_cast<char**>(&ptrs)[i] + (reinterpret_cast<char*>(devicePtr) - reinterpret_cast<char*>(Compressor.mOutputFlat)); + } } } TransferMemoryResourcesToGPU(myStep, &Compressor, outputStream); @@ -2163,7 +2179,10 @@ int GPUChainTracking::RunTPCCompression() GPUError("Invalid compression kernel selected."); return 1; } - + if (ProcessingSettings().tpcCompressionGatherMode == 3) { + RecordMarker(&mEvents->stream[outputStream], outputStream); + GPUMemCpy(myStep, hostFlatPtr, Compressor.mOutput->qTotU, copySize, outputStream, false); + } } else { char direction = 0; if (ProcessingSettings().tpcCompressionGatherMode == 0) { @@ -2215,6 +2234,12 @@ int GPUChainTracking::RunTPCCompression() gatherTimer->Stop(); } mIOPtrs.tpcCompressedClusters = Compressor.mOutputFlat; + if (ProcessingSettings().tpcCompressionGatherMode == 3) { + SynchronizeEvents(&mEvents->stream[outputStream]); + ReleaseEvent(&mEvents->stream[outputStream]); + mRec->ReturnVolatileDeviceMemory(); + } + if (mPipelineFinalizationCtx == nullptr) { SynchronizeStream(outputStream); } else { From 5b731a51064806770383695fa3c9d35fe743490f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 4 Nov 2020 21:38:27 +0100 Subject: [PATCH 1253/1751] GPU: Add fast GPU to GPU mem gather kernel --- GPU/Common/GPUDefGPUParameters.h | 1 + .../Base/GPUReconstructionKernels.h | 1 + GPU/GPUTracking/Base/GPUSettingsList.h | 2 +- .../GPUTPCCompressionKernels.cxx | 85 +++++++++++++++++++ .../GPUTPCCompressionKernels.h | 3 + GPU/GPUTracking/Global/GPUChainTracking.cxx | 17 ++-- 6 files changed, 103 insertions(+), 6 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 2eabbdc704fc2..2619f64dc8991 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -312,6 +312,7 @@ #define GPUCA_LB_GPUTPCCompressionGatherKernels_buffered32 GPUCA_LB_COMPRESSION_GATHER #define GPUCA_LB_GPUTPCCompressionGatherKernels_buffered64 GPUCA_LB_COMPRESSION_GATHER #define GPUCA_LB_GPUTPCCompressionGatherKernels_buffered128 GPUCA_LB_COMPRESSION_GATHER +#define GPUCA_LB_GPUTPCCompressionGatherKernels_multiBlock GPUCA_LB_COMPRESSION_GATHER #ifndef GPUCA_NEIGHBORSFINDER_REGS #define GPUCA_NEIGHBORSFINDER_REGS NONE, 0 diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index cad31625cf1bb..5f8bca44375db 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -68,6 +68,7 @@ GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, unbuffered ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered32 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered64 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered128 ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, multiBlock ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillIndexMap ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillFromDigits ), (single), (), ()) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 96d120a636d09..572cfc27636b8 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -109,7 +109,7 @@ AddOption(trackletConstructorInPipeline, int, -1, "", 0, "Run tracklet construct AddOption(trackletSelectorInPipeline, int, -1, "", 0, "Run tracklet selector in the pipeline") AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fit") AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode (0: DMA transfer gather gpu to host, 1: serial DMA to host and gather by copy on CPU, 2. gather via GPU kernal DMA access, 3. gather on GPU via kernel, dma afterwards") -AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel") +AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel (0: unbufferd, 1-3: buffered, 4: multi-block)") AddOption(runMC, bool, false, "", 0, "Process MC labels") AddOption(ompKernels, bool, true, "", 0, "Parallelize with OMP inside kernels instead of over slices") AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 5e20120d906d8..63e7087e5ad2e 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -707,6 +707,85 @@ GPUdii() void GPUTPCCompressionGatherKernels::gatherBuffered(int nBlocks, int nT compressorMemcpyBuffered(buf, output->timeResA + tracksOffsetDiff, input.timeResA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); } +GPUdii() void GPUTPCCompressionGatherKernels::gatherMulti(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +{ + GPUTPCCompression& GPUrestrict() compressor = processors.tpcCompressor; + const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = processors.ioPtrs.clustersNative; + const auto& input = compressor.mPtrs; + auto* output = compressor.mOutput; + + const int nWarps = nThreads / GPUCA_WARP_SIZE; + const int iWarp = iThread / GPUCA_WARP_SIZE; + const int nLanes = GPUCA_WARP_SIZE; + const int iLane = iThread % GPUCA_WARP_SIZE; + auto* buf = smem.getBuffer<Vec128>(iWarp); + + if (iBlock == 0) { + compressorMemcpyBasic(output->nSliceRowClusters, input.nSliceRowClusters, compressor.NSLICES * GPUCA_ROW_COUNT, nThreads, iThread); + compressorMemcpyBasic(output->nTrackClusters, input.nTrackClusters, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->qPtA, input.qPtA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->rowA, input.rowA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->sliceA, input.sliceA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->timeA, input.timeA, compressor.mMemory->nStoredTracks, nThreads, iThread); + compressorMemcpyBasic(output->padA, input.padA, compressor.mMemory->nStoredTracks, nThreads, iThread); + } else if (iBlock & 1) { + const unsigned int nGlobalWarps = nWarps * (nBlocks - 1) / 2; + const unsigned int iGlobalWarp = nWarps * (iBlock - 1) / 2 + iWarp; + + const unsigned int nRows = compressor.NSLICES * GPUCA_ROW_COUNT; + unsigned int rowsPerWarp = (nRows + nGlobalWarps - 1) / nGlobalWarps; + unsigned int rowStart = rowsPerWarp * iGlobalWarp; + unsigned int rowEnd = CAMath::Min(nRows, rowStart + rowsPerWarp); + if (rowStart >= nRows) { + rowStart = 0; + rowEnd = 0; + } + rowsPerWarp = rowEnd - rowStart; + + const unsigned int rowsOffset = calculateWarpOffsets(smem, input.nSliceRowClusters, rowStart, rowEnd, nWarps, iWarp, nLanes, iLane); + const unsigned int* clusterOffsets = reinterpret_cast<const unsigned int*>(clusters->clusterOffset) + rowStart; + const unsigned int* nSliceRowClusters = input.nSliceRowClusters + rowStart; + + compressorMemcpyBuffered(buf, output->qTotU + rowsOffset, input.qTotU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->qMaxU + rowsOffset, input.qMaxU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->flagsU + rowsOffset, input.flagsU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->padDiffU + rowsOffset, input.padDiffU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->timeDiffU + rowsOffset, input.timeDiffU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaPadU + rowsOffset, input.sigmaPadU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaTimeU + rowsOffset, input.sigmaTimeU, nSliceRowClusters, clusterOffsets, rowsPerWarp, nLanes, iLane, 0); + } else { + const unsigned int nGlobalWarps = nWarps * (nBlocks - 1) / 2; + const unsigned int iGlobalWarp = nWarps * (iBlock / 2 - 1) + iWarp; + + const unsigned int nStoredTracks = compressor.mMemory->nStoredTracks; + unsigned int tracksPerWarp = (nStoredTracks + nGlobalWarps - 1) / nGlobalWarps; + unsigned int trackStart = tracksPerWarp * iGlobalWarp; + unsigned int trackEnd = CAMath::Min(nStoredTracks, trackStart + tracksPerWarp); + if (trackStart >= nStoredTracks) { + trackStart = 0; + trackEnd = 0; + } + tracksPerWarp = trackEnd - trackStart; + + const unsigned int tracksOffset = calculateWarpOffsets(smem, input.nTrackClusters, trackStart, trackEnd, nWarps, iWarp, nLanes, iLane); + const unsigned short* nTrackClustersPtr = input.nTrackClusters + trackStart; + const unsigned int* aClsFstIdx = compressor.mAttachedClusterFirstIndex + trackStart; + + compressorMemcpyBuffered(buf, output->qTotA + tracksOffset, input.qTotA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->qMaxA + tracksOffset, input.qMaxA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->flagsA + tracksOffset, input.flagsA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaPadA + tracksOffset, input.sigmaPadA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + compressorMemcpyBuffered(buf, output->sigmaTimeA + tracksOffset, input.sigmaTimeA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 0); + + // First index stored with track + unsigned int tracksOffsetDiff = tracksOffset - trackStart; + compressorMemcpyBuffered(buf, output->rowDiffA + tracksOffsetDiff, input.rowDiffA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); + compressorMemcpyBuffered(buf, output->sliceLegDiffA + tracksOffsetDiff, input.sliceLegDiffA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); + compressorMemcpyBuffered(buf, output->padResA + tracksOffsetDiff, input.padResA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); + compressorMemcpyBuffered(buf, output->timeResA + tracksOffsetDiff, input.timeResA, nTrackClustersPtr, aClsFstIdx, tracksPerWarp, nLanes, iLane, 1); + } +} + template <> GPUdii() void GPUTPCCompressionGatherKernels::Thread<GPUTPCCompressionGatherKernels::buffered32>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) { @@ -724,3 +803,9 @@ GPUdii() void GPUTPCCompressionGatherKernels::Thread<GPUTPCCompressionGatherKern { gatherBuffered<Vec128>(nBlocks, nThreads, iBlock, iThread, smem, processors); } + +template <> +GPUdii() void GPUTPCCompressionGatherKernels::Thread<GPUTPCCompressionGatherKernels::multiBlock>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +{ + gatherMulti(nBlocks, nThreads, iBlock, iThread, smem, processors); +} diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h index 94227cf8474e2..06fb6a6ffa297 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h @@ -64,6 +64,7 @@ class GPUTPCCompressionGatherKernels : public GPUKernelTemplate buffered32, buffered64, buffered128, + multiBlock }; using Vec16 = unsigned short; @@ -119,6 +120,8 @@ class GPUTPCCompressionGatherKernels : public GPUKernelTemplate template <typename V> GPUdii() static void gatherBuffered(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); + + GPUdii() static void gatherMulti(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); }; } // namespace GPUCA_NAMESPACE::gpu diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index fbc0d64b2cd1c..bc2f6aabf51df 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2157,24 +2157,31 @@ int GPUChainTracking::RunTPCCompression() } } TransferMemoryResourcesToGPU(myStep, &Compressor, outputStream); - unsigned int nBlocks = 2; + constexpr unsigned int nBlocksDefault = 2; + constexpr unsigned int nBlocksMulti = 1 + 2 * 200; switch (ProcessingSettings().tpcCompressionGatherModeKernel) { case 0: - runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::unbuffered>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::unbuffered>(GetGridBlkStep(nBlocksDefault, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::unbuffered>(RecoStep::TPCCompression, 0, outputSize); break; case 1: - runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered32>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered32>(GetGridBlkStep(nBlocksDefault, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered32>(RecoStep::TPCCompression, 0, outputSize); break; case 2: - runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered64>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered64>(GetGridBlkStep(nBlocksDefault, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered64>(RecoStep::TPCCompression, 0, outputSize); break; case 3: - runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered128>(GetGridBlkStep(nBlocks, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered128>(GetGridBlkStep(nBlocksDefault, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::buffered128>(RecoStep::TPCCompression, 0, outputSize); break; + case 4: + + static_assert((nBlocksMulti & 1) && nBlocksMulti >= 3); + runKernel<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::multiBlock>(GetGridBlkStep(nBlocksMulti, outputStream, RecoStep::TPCCompression), krnlRunRangeNone, krnlEventNone); + getKernelTimer<GPUTPCCompressionGatherKernels, GPUTPCCompressionGatherKernels::multiBlock>(RecoStep::TPCCompression, 0, outputSize); + break; default: GPUError("Invalid compression kernel selected."); return 1; From 84e4679acf7786757aadea93bf840405bb064756 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 4 Nov 2020 22:09:30 +0100 Subject: [PATCH 1254/1751] GPU: Split dma transfer of clusters in double-pipeline to enable intermittant small transfers --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index bc2f6aabf51df..6caf6545c278a 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2132,7 +2132,7 @@ int GPUChainTracking::RunTPCCompression() O->nComppressionModes = param().rec.tpcCompressionModes; size_t outputSize = AllocateRegisteredMemory(Compressor.mMemoryResOutputHost, mOutputCompressedClusters); Compressor.mOutputFlat->set(outputSize, *Compressor.mOutput); - void* hostFlatPtr = Compressor.mOutput->qTotU; // First array as allocated in GPUTPCCompression::SetPointersCompressedClusters + char* hostFlatPtr = (char*)Compressor.mOutput->qTotU; // First array as allocated in GPUTPCCompression::SetPointersCompressedClusters size_t copySize = 0; if (ProcessingSettings().tpcCompressionGatherMode == 3) { CompressorShadow.mOutputA = Compressor.mOutput; @@ -2188,7 +2188,16 @@ int GPUChainTracking::RunTPCCompression() } if (ProcessingSettings().tpcCompressionGatherMode == 3) { RecordMarker(&mEvents->stream[outputStream], outputStream); - GPUMemCpy(myStep, hostFlatPtr, Compressor.mOutput->qTotU, copySize, outputStream, false); + char* deviceFlatPts = (char*)Compressor.mOutput->qTotU; + if (GetProcessingSettings().doublePipeline) { + const size_t blockSize = CAMath::nextMultipleOf<1024>(copySize / 30); + const unsigned int n = (copySize + blockSize - 1) / blockSize; + for (unsigned int i = 0; i < n; i++) { + GPUMemCpy(myStep, hostFlatPtr + i * blockSize, deviceFlatPts + i * blockSize, CAMath::Min(blockSize, copySize - i * blockSize), outputStream, false); + } + } else { + GPUMemCpy(myStep, hostFlatPtr, deviceFlatPts, copySize, outputStream, false); + } } } else { char direction = 0; From 7f84b7936bb8bd56040e2fe5a7622097c397cb11 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 5 Nov 2020 09:15:48 +0100 Subject: [PATCH 1255/1751] GPU: Add tuned parameters for NVIDIA Ampere family --- GPU/Common/GPUDefGPUParameters.h | 61 +++++++++++++++++++ GPU/Common/test/testGPUsortCUDA.cu | 2 - GPU/GPUTracking/Base/GPUReconstruction.cxx | 3 - .../Base/GPUReconstructionIncludes.h | 3 + .../Base/cuda/GPUReconstructionCUDADef.h | 2 +- 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 2619f64dc8991..afede0285efaa 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -81,6 +81,63 @@ #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_NO_ATOMIC_PRECHECK 1 #define GPUCA_COMP_GATHER_KERNEL 3 +#elif defined(GPUCA_GPUTYPE_AMPERE) + #define GPUCA_WARP_SIZE 32 + #define GPUCA_THREAD_COUNT 512 + #define GPUCA_LB_GPUTPCCreateSliceData 384 + #define GPUCA_LB_GPUTPCStartHitsSorter 512, 1 + #define GPUCA_LB_GPUTPCStartHitsFinder 512 + #define GPUCA_LB_GPUTPCTrackletConstructor 256, 2 // best single-kernel: 128, 4 + #define GPUCA_LB_GPUTPCTrackletSelector 192, 3 // best single-kernel: 128, 4 + #define GPUCA_LB_GPUTPCNeighboursFinder 640, 1 // best single-kernel: 768, 1 + #define GPUCA_LB_GPUTPCNeighboursCleaner 512 + #define GPUCA_LB_GPUTPCGlobalTracking 128, 4 + #define GPUCA_LB_GPUTPCCFDecodeZS 64, 10 + #define GPUCA_LB_GPUTPCCFGather 1024, 1 + #define GPUCA_LB_GPUTPCGMMergerTrackFit 64, 4 + #define GPUCA_LB_GPUTPCGMMergerFollowLoopers 64, 12 + #define GPUCA_LB_GPUTPCGMMergerSliceRefit 32, 6 + #define GPUCA_LB_GPUTPCGMMergerUnpackResetIds 256 + #define GPUCA_LB_GPUTPCGMMergerUnpackGlobal 256 + #define GPUCA_LB_GPUTPCGMMergerResolve_step0 256 + #define GPUCA_LB_GPUTPCGMMergerResolve_step1 256 + #define GPUCA_LB_GPUTPCGMMergerResolve_step2 256 + #define GPUCA_LB_GPUTPCGMMergerResolve_step3 256 + #define GPUCA_LB_GPUTPCGMMergerResolve_step4 256, 4 + #define GPUCA_LB_GPUTPCGMMergerClearLinks 256 + #define GPUCA_LB_GPUTPCGMMergerMergeWithinPrepare 256 + #define GPUCA_LB_GPUTPCGMMergerMergeSlicesPrepare 256, 2 + #define GPUCA_LB_GPUTPCGMMergerMergeBorders_step0 192 + #define GPUCA_LB_GPUTPCGMMergerMergeBorders_step2 64, 2 + #define GPUCA_LB_GPUTPCGMMergerMergeCE 256 + #define GPUCA_LB_GPUTPCGMMergerLinkGlobalTracks 256 + #define GPUCA_LB_GPUTPCGMMergerCollect 256, 2 + #define GPUCA_LB_GPUTPCGMMergerSortTracks 256 + #define GPUCA_LB_GPUTPCGMMergerSortTracksQPt 256 + #define GPUCA_LB_GPUTPCGMMergerSortTracksPrepare 256 + #define GPUCA_LB_GPUTPCGMMergerPrepareClusters_step0 256 + #define GPUCA_LB_GPUTPCGMMergerPrepareClusters_step1 256 + #define GPUCA_LB_GPUTPCGMMergerPrepareClusters_step2 256 + #define GPUCA_LB_GPUTPCGMMergerFinalize_0 256 + #define GPUCA_LB_GPUTPCGMMergerFinalize_1 256 + #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 + #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 64, 2 + #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 3 + #define GPUCA_LB_COMPRESSION_GATHER 1024 + #define GPUCA_LB_CLUSTER_FINDER 448 + #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 4 + #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 20 + #define GPUCA_CONSTRUCTOR_IN_PIPELINE 1 + #define GPUCA_SELECTOR_IN_PIPELINE 1 + #define GPUCA_ALTERNATE_BORDER_SORT 1 + #define GPUCA_SORT_BEFORE_FIT 1 + #define GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION 1 + #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 + #define GPUCA_NO_ATOMIC_PRECHECK 1 + #define GPUCA_DEDX_STORAGE_TYPE unsigned short + #define GPUCA_MERGER_INTERPOLATION_ERROR_TYPE half + #define GPUCA_COMP_GATHER_KERNEL 4 + #define GPUCA_COMP_GATHER_MODE 3 #elif defined(GPUCA_GPUTYPE_TURING) #define GPUCA_WARP_SIZE 32 #define GPUCA_THREAD_COUNT 512 @@ -345,6 +402,9 @@ #ifndef GPUCA_COMP_GATHER_KERNEL #define GPUCA_COMP_GATHER_KERNEL 0 #endif + #ifndef GPUCA_COMP_GATHER_MODE + #define GPUCA_COMP_GATHER_MODE 2 + #endif #else #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 0 #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 0 @@ -356,6 +416,7 @@ #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_THREAD_COUNT_FINDER 1 #define GPUCA_COMP_GATHER_KERNEL 0 + #define GPUCA_COMP_GATHER_MODE 0 #endif #ifndef GPUCA_DEDX_STORAGE_TYPE #define GPUCA_DEDX_STORAGE_TYPE float diff --git a/GPU/Common/test/testGPUsortCUDA.cu b/GPU/Common/test/testGPUsortCUDA.cu index 44a302bcf9520..e6bd5206cbec9 100644 --- a/GPU/Common/test/testGPUsortCUDA.cu +++ b/GPU/Common/test/testGPUsortCUDA.cu @@ -11,8 +11,6 @@ /// \file testGPUsortCUDA.cu /// \author Michael Lettrich -#define GPUCA_GPUTYPE_TURING - #define BOOST_TEST_MODULE Test GPUCommonAlgorithm Sorting CUDA #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 2fe51bece4f8e..203d50f7d403c 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -229,9 +229,6 @@ int GPUReconstruction::InitPhaseBeforeDevice() mProcessingSettings.trackletSelectorSlices = 1; } } - if (mProcessingSettings.tpcCompressionGatherMode < 0) { - mProcessingSettings.tpcCompressionGatherMode = (mRecoStepsGPU & GPUDataTypes::RecoStep::TPCCompression) ? 2 : 0; - } if (!(mRecoStepsGPU & GPUDataTypes::RecoStep::TPCMerging)) { mProcessingSettings.mergerSortTracks = false; } diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h index 8ba82395794b3..0a7a34e089ad2 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h @@ -58,6 +58,9 @@ } \ if (mProcessingSettings.tpcCompressionGatherModeKernel < 0) { \ mProcessingSettings.tpcCompressionGatherModeKernel = GPUCA_COMP_GATHER_KERNEL; \ + } \ + if (mProcessingSettings.tpcCompressionGatherMode < 0) { \ + mProcessingSettings.tpcCompressionGatherMode = GPUCA_COMP_GATHER_MODE; \ } #endif diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h index ce3d0c53b4d78..56d9409f8f5cc 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h @@ -14,7 +14,7 @@ #ifndef O2_GPU_GPURECONSTRUCTIONCUDADEF_H #define O2_GPU_GPURECONSTRUCTIONCUDADEF_H -#define GPUCA_GPUTYPE_TURING +#define GPUCA_GPUTYPE_AMPERE #define GPUCA_UNROLL(CUDA, HIP) GPUCA_M_UNROLL_##CUDA #define GPUdic(CUDA, HIP) GPUCA_GPUdic_select_##CUDA() From b4103fc5d0b9ca6896f8f41f6240c32df1fce19b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 6 Nov 2020 21:42:59 +0100 Subject: [PATCH 1256/1751] GPU: Improve automatic free GPU mem size estimation on NVIDIA --- .../Base/cuda/GPUReconstructionCUDA.cu | 31 ++++++++++++------- .../Base/hip/GPUReconstructionHIP.hip.cxx | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index a8fdc867b1480..addaf5fa869ad 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -22,9 +22,11 @@ #include "GPUReconstructionIncludes.h" #include "GPUParamRTC.h" -static constexpr size_t REQUIRE_MIN_MEMORY = 1024u * 1024 * 1024; -static constexpr size_t REQUIRE_MEMORY_RESERVED = 512u * 1024 * 1024; -static constexpr size_t REQUIRE_FREE_MEMORY_RESERVED = 2048u * 1024 * 1024; +static constexpr size_t REQUIRE_MIN_MEMORY = 1024L * 1024 * 1024; +static constexpr size_t REQUIRE_MEMORY_RESERVED = 512L * 1024 * 1024; +static constexpr size_t REQUIRE_FREE_MEMORY_RESERVED_PER_SM = 40L * 1024 * 1024; +static constexpr size_t RESERVE_EXTRA_MEM_THRESHOLD = 10L * 1024 * 1024 * 1024; +static constexpr size_t RESERVE_EXTRA_MEM_OFFSET = 1L * 512 * 1024 * 1024; using namespace GPUCA_NAMESPACE::gpu; @@ -33,7 +35,7 @@ texture<cahit2, cudaTextureType1D, cudaReadModeElementType> gAliTexRefu2; texture<calink, cudaTextureType1D, cudaReadModeElementType> gAliTexRefu; #endif -__global__ void dummyInitKernel(void* foo) +__global__ void dummyInitKernel(void*) { } @@ -285,20 +287,20 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() if (cudaDeviceProp.major < reqVerMaj || (cudaDeviceProp.major == reqVerMaj && cudaDeviceProp.minor < reqVerMin)) { deviceOK = false; deviceFailure = "Too low device revision"; - } else if (free < std::max(mDeviceMemorySize, REQUIRE_MIN_MEMORY)) { + } else if (free < std::max<size_t>(mDeviceMemorySize, REQUIRE_MIN_MEMORY)) { deviceOK = false; deviceFailure = "Insufficient GPU memory"; } deviceSpeed = (double)cudaDeviceProp.multiProcessorCount * (double)cudaDeviceProp.clockRate * (double)cudaDeviceProp.warpSize * (double)free * (double)cudaDeviceProp.major * (double)cudaDeviceProp.major; if (mProcessingSettings.debugLevel >= 2) { - GPUImportant("Device %s%2d: %s (Rev: %d.%d - Mem Avail %lld / %lld)%s %s", deviceOK ? " " : "[", i, cudaDeviceProp.name, cudaDeviceProp.major, cudaDeviceProp.minor, (long long int)free, (long long int)cudaDeviceProp.totalGlobalMem, deviceOK ? " " : " ]", deviceOK ? "" : deviceFailure); + GPUImportant("Device %s%2d: %s (Rev: %d.%d - Mem Avail %lu / %lu)%s %s", deviceOK ? " " : "[", i, cudaDeviceProp.name, cudaDeviceProp.major, cudaDeviceProp.minor, free, (size_t)cudaDeviceProp.totalGlobalMem, deviceOK ? " " : " ]", deviceOK ? "" : deviceFailure); } if (!deviceOK) { continue; } devicesOK[i] = true; - devMemory[i] = std::min(free, total - REQUIRE_MEMORY_RESERVED); + devMemory[i] = std::min<size_t>(free, std::max<long int>(0, total - REQUIRE_MEMORY_RESERVED)); if (deviceSpeed > bestDeviceSpeed) { bestDevice = i; bestDeviceSpeed = deviceSpeed; @@ -312,7 +314,7 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() bool noDevice = false; if (bestDevice == -1) { GPUWarning("No %sCUDA Device available, aborting CUDA Initialisation", count ? "appropriate " : ""); - GPUImportant("Requiring Revision %d.%d, Mem: %lld", reqVerMaj, reqVerMin, (long long int)std::max(mDeviceMemorySize, REQUIRE_MIN_MEMORY)); + GPUImportant("Requiring Revision %d.%d, Mem: %lu", reqVerMaj, reqVerMin, std::max<size_t>(mDeviceMemorySize, REQUIRE_MIN_MEMORY)); noDevice = true; } else if (mProcessingSettings.deviceNum > -1) { if (mProcessingSettings.deviceNum >= (signed)count) { @@ -354,6 +356,9 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() GPUInfo("\ttextureAlignment = %lld", (unsigned long long int)cudaDeviceProp.textureAlignment); GPUInfo(" "); } + if (cudaDeviceProp.warpSize != GPUCA_WARP_SIZE) { + throw std::runtime_error("Invalid warp size on GPU"); + } mBlockCount = cudaDeviceProp.multiProcessorCount; mWarpSize = 32; mMaxThreads = std::max<int>(mMaxThreads, cudaDeviceProp.maxThreadsPerBlock * mBlockCount); @@ -394,10 +399,14 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() return (1); } + if (mDeviceMemorySize == 1 || mDeviceMemorySize == 2) { + mDeviceMemorySize = std::max<long int>(0, devMemory[mDeviceId] - REQUIRE_FREE_MEMORY_RESERVED_PER_SM * cudaDeviceProp.multiProcessorCount); // Take all GPU memory but some reserve + if (mDeviceMemorySize >= RESERVE_EXTRA_MEM_THRESHOLD) { + mDeviceMemorySize -= RESERVE_EXTRA_MEM_OFFSET; + } + } if (mDeviceMemorySize == 2) { - mDeviceMemorySize = devMemory[mDeviceId] * 2 / 3; // Leave 1/3 of GPU memory for event display - } else if (mDeviceMemorySize == 1) { - mDeviceMemorySize = devMemory[mDeviceId] - REQUIRE_FREE_MEMORY_RESERVED; // Take all GPU memory but 1/2 GB + mDeviceMemorySize = mDeviceMemorySize * 2 / 3; // Leave 1/3 of GPU memory for event display } if (mDeviceMemorySize > cudaDeviceProp.totalGlobalMem || GPUFailedMsgI(cudaMalloc(&mDeviceMemoryBase, mDeviceMemorySize))) { diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index f8fd21c4d4904..98b8882d6b81f 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -54,7 +54,7 @@ __global__ void gGPUConstantMemBuffer_dummy(int* p) { *p = *(int*)&gGPUConstantM using namespace GPUCA_NAMESPACE::gpu; -__global__ void dummyInitKernel(void* foo) {} +__global__ void dummyInitKernel(void*) {} #if defined(HAVE_O2HEADERS) && !defined(GPUCA_NO_ITS_TRAITS) #include "ITStrackingHIP/VertexerTraitsHIP.h" From f64b3b477a39a6bb97bb0f7acb0f16c53e45bd7a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 6 Nov 2020 22:06:54 +0100 Subject: [PATCH 1257/1751] GPU: Don't allocate page-locked host buffer of same size as GPU buffer if not needed --- GPU/Common/GPUDefGPUParameters.h | 2 +- GPU/GPUTracking/Base/GPUReconstruction.cxx | 16 +++++++++++----- GPU/GPUTracking/Interface/GPUO2Interface.cxx | 3 +++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index afede0285efaa..d1bb0bc16676a 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -449,7 +449,7 @@ #define GPUCA_MAX_ITS_FIT_TRACKS ((size_t) 96 * 1024) // Max number of tracks for ITS track fit #define GPUCA_TRACKER_CONSTANT_MEM ((size_t) 63 * 1024) // Amount of Constant Memory to reserve #define GPUCA_MEMORY_SIZE ((size_t) 6 * 1024 * 1024 * 1024) // Size of memory allocated on Device -#define GPUCA_HOST_MEMORY_SIZE ((size_t) 6 * 1024 * 1024 * 1024) // Size of memory allocated on Host +#define GPUCA_HOST_MEMORY_SIZE ((size_t) 1 * 1024 * 1024 * 1024) // Size of memory allocated on Host #define GPUCA_GPU_STACK_SIZE ((size_t) 8 * 1024) // Stack size per GPU thread #define GPUCA_GPU_HEAP_SIZE ((size_t) 16 * 1025 * 1024) // Stack size per GPU thread diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 203d50f7d403c..56945a35b01ef 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -284,15 +284,21 @@ int GPUReconstruction::InitPhaseBeforeDevice() mDeviceMemorySize = mHostMemorySize = 0; for (unsigned int i = 0; i < mChains.size(); i++) { mChains[i]->RegisterPermanentMemoryAndProcessors(); - size_t memGpu, memHost; - mChains[i]->MemorySize(memGpu, memHost); - mDeviceMemorySize += memGpu; - mHostMemorySize += memHost; + size_t memPrimary, memPageLocked; + mChains[i]->MemorySize(memPrimary, memPageLocked); + if (!IsGPU() || mOutputControl.OutputType == GPUOutputControl::AllocateInternal) { + memPageLocked = memPrimary; + } + mDeviceMemorySize += memPrimary; + mHostMemorySize += memPageLocked; } if (mProcessingSettings.forceMemoryPoolSize && mProcessingSettings.forceMemoryPoolSize <= 2 && CanQueryMaxMemory()) { mDeviceMemorySize = mProcessingSettings.forceMemoryPoolSize; } else if (mProcessingSettings.forceMemoryPoolSize > 2) { - mDeviceMemorySize = mHostMemorySize = mProcessingSettings.forceMemoryPoolSize; + mDeviceMemorySize = mProcessingSettings.forceMemoryPoolSize; + if (!IsGPU() || mOutputControl.OutputType == GPUOutputControl::AllocateInternal) { + mHostMemorySize = mDeviceMemorySize; + } } if (mProcessingSettings.forceHostMemoryPoolSize) { mHostMemorySize = mProcessingSettings.forceHostMemoryPoolSize; diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 4d5cdebeada84..4c65f08a9aaa7 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -63,6 +63,9 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) mChain->SetOutputControlClustersNative(mOutputClustersNative.get()); mOutputTPCTracks.reset(new GPUOutputControl); mChain->SetOutputControlTPCTracks(mOutputTPCTracks.get()); + GPUOutputControl dummy; + dummy.set([](size_t size) -> void* {throw std::runtime_error("invalid output memory request, no common output buffer set"); return nullptr; }); + mRec->SetOutputControl(dummy); } if (mConfig->configProcessing.runMC) { mOutputTPCClusterLabels.reset(new GPUOutputControl); From 3c94b4c791d4cb1473e0801e51541c2881135f0e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 8 Nov 2020 22:36:47 +0100 Subject: [PATCH 1258/1751] GPU: Auto-set NVIDIA GPU Type variable from compute-target --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 40 ++++++++++++------- .../Base/cuda/GPUReconstructionCUDADef.h | 1 - 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 5d5e41b5fa28d..dae17401295c2 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -20,10 +20,15 @@ set(HDRS GPUReconstructionCUDA.h GPUReconstructionCUDAInternals.h GPUReconstruct # -------------------------------- Prepare RTC ------------------------------------------------------- if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") - set(CURTC_DEFINES "-D$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>,$<SEMICOLON>-D>" - -DGPUCA_GPUCODE_GENRTC -DGPUCA_GPULIBRARY=CUDA + if(ALIGPU_BUILD_TYPE STREQUAL "O2") + set(defineIncludeSrc "O2::${MODULE}") + else() + set(defineIncludeSrc "${MODULE}") + endif() + set(CURTC_DEFINES "-D$<JOIN:$<TARGET_PROPERTY:${defineIncludeSrc},COMPILE_DEFINITIONS>,$<SEMICOLON>-D>" + -DGPUCA_GPUCODE_GENRTC ) - set(CURTC_INCLUDES "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>" + set(CURTC_INCLUDES "-I$<JOIN:$<TARGET_PROPERTY:${defineIncludeSrc},INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>" -I${CMAKE_SOURCE_DIR}/Detectors/Base/src -I${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src ) @@ -113,8 +118,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") TARGETVARNAME targetName) target_compile_definitions( - ${targetName} PUBLIC GPUCA_GPULIBRARY=CUDA - $<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>) + ${targetName} PUBLIC $<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>) set_target_properties(${targetName} PROPERTIES LINKER_LANGUAGE CXX) @@ -122,34 +126,32 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") endif() if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") - add_definitions(-DGPUCA_GPULIBRARY=CUDA) - + set(targetName Ali${MODULE}) # Generate the dictionary get_directory_property(incdirs INCLUDE_DIRECTORIES) - generate_dictionary("Ali${MODULE}" "" "GPUReconstructionCUDA.h" + generate_dictionary("${targetName}" "" "GPUReconstructionCUDA.h" "${incdirs} .") # Generate the ROOT map Dependecies - generate_rootmap("Ali${MODULE}" "" "") + generate_rootmap("${targetName}" "" "") # Add a library to the project using the specified source files - add_library_tested(Ali${MODULE} SHARED ${SRCS} G__Ali${MODULE}.cxx) + add_library_tested(${targetName} SHARED ${SRCS} G__${targetName}.cxx) # CUDA run-time and driver - target_link_libraries(Ali${MODULE} PUBLIC AliGPUTracking) + target_link_libraries(${targetName} PUBLIC AliGPUTracking) # Additional compilation flags - set_target_properties(Ali${MODULE} PROPERTIES COMPILE_FLAGS "") + set_target_properties(${targetName} PROPERTIES COMPILE_FLAGS "") # Installation - install(TARGETS Ali${MODULE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) + install(TARGETS ${targetName} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) install(FILES ${HDRS} DESTINATION include) - set(targetName Ali${MODULE}) + endif() if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") - add_definitions(-DGPUCA_GPULIBRARY=CUDA) add_library(${MODULE} SHARED ${SRCS}) target_link_libraries(${MODULE} PUBLIC GPUTracking) set(targetName ${MODULE}) @@ -158,3 +160,11 @@ endif() # Since target_link_libraries(${targetName} PRIVATE cuda cudart nvrtc) +target_compile_definitions(${targetName} PUBLIC GPUCA_GPULIBRARY=CUDA) +if(CUDA_COMPUTETARGET AND CUDA_COMPUTETARGET STREQUAL "86") +target_compile_definitions(${targetName} PUBLIC GPUCA_GPUTYPE_AMPERE) +elseif(CUDA_COMPUTETARGET AND CUDA_COMPUTETARGET STREQUAL "75") +target_compile_definitions(${targetName} PUBLIC GPUCA_GPUTYPE_TURING) +else() +target_compile_definitions(${targetName} PUBLIC GPUCA_GPUTYPE_AMPERE) +endif() diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h index 56d9409f8f5cc..9ef1ce9a820e6 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h @@ -14,7 +14,6 @@ #ifndef O2_GPU_GPURECONSTRUCTIONCUDADEF_H #define O2_GPU_GPURECONSTRUCTIONCUDADEF_H -#define GPUCA_GPUTYPE_AMPERE #define GPUCA_UNROLL(CUDA, HIP) GPUCA_M_UNROLL_##CUDA #define GPUdic(CUDA, HIP) GPUCA_GPUdic_select_##CUDA() From c1b204f94a5f6ed61cd2fb8c23ce238549c519f5 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 9 Nov 2020 01:24:10 +0100 Subject: [PATCH 1259/1751] Suppress TOF ctf input mode: digits input will be provided by CTFreader w-flow --- .../tofworkflow/src/tof-reco-workflow.cxx | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 18b6e2f75f4a9..c924950007c7c 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -48,7 +48,7 @@ // including Framework/runDataProcessing void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { - workflowOptions.push_back(ConfigParamSpec{"input-type", o2::framework::VariantType::String, "digits", {"digits, raw, clusters, ctf"}}); + workflowOptions.push_back(ConfigParamSpec{"input-type", o2::framework::VariantType::String, "digits", {"digits, raw, clusters"}}); workflowOptions.push_back(ConfigParamSpec{"output-type", o2::framework::VariantType::String, "clusters,matching-info,calib-info", {"digits, clusters, matching-info, calib-info, raw, ctf"}}); workflowOptions.push_back(ConfigParamSpec{"disable-mc", o2::framework::VariantType::Bool, false, {"disable sending of MC information, TBI"}}); workflowOptions.push_back(ConfigParamSpec{"tof-sectors", o2::framework::VariantType::String, "0-17", {"TOF sector range, e.g. 5-7,8,9 ,TBI"}}); @@ -127,7 +127,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) bool dgtinput = 0; bool clusterinput = 0; bool rawinput = 0; - bool ctfinput = 0; if (inputType == "digits") { dgtinput = 1; } else if (inputType == "clusters") { @@ -135,11 +134,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } else if (inputType == "raw") { rawinput = 1; writeerr = cfgc.options().get<bool>("write-decoding-errors"); - } else if (inputType == "ctf") { - ctfinput = 1; } - if (ctfinput || rawinput) { + if (rawinput) { } else { if (!cfgc.helpOnCommandLine()) { std::string inputGRP = o2::base::NameConf::getGRPFileName(); @@ -179,9 +176,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) specs.emplace_back(o2::tof::getClusterReaderSpec(useMC)); } else if (dgtinput) { // TOF clusterizer - LOG(INFO) << "Insert TOF Digit reader from file"; - specs.emplace_back(o2::tof::getDigitReaderSpec(useMC)); - + if (!disableRootInput) { + LOG(INFO) << "Insert TOF Digit reader from file"; + specs.emplace_back(o2::tof::getDigitReaderSpec(useMC)); + } if (writeraw) { LOG(INFO) << "Insert TOF Raw writer"; specs.emplace_back(o2::tof::getTOFRawWriterSpec()); @@ -197,15 +195,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) LOG(INFO) << "Insert TOF Digit Writer"; specs.emplace_back(o2::tof::getTOFDigitWriterSpec(0, writeerr)); } - } else if (ctfinput) { - LOG(INFO) << "Insert TOF CTF decoder"; - specs.emplace_back(o2::tof::getEntropyDecoderSpec()); - - if (writedigit && !disableRootOutput) { - // add TOF digit writer without mc labels - LOG(INFO) << "Insert TOF Digit Writer"; - specs.emplace_back(o2::tof::getTOFDigitWriterSpec(0)); - } } if (!clusterinput && writecluster) { From 863b6c58f8768730bf1e05fa4ce5969726eb0eca Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 9 Nov 2020 10:19:10 +0100 Subject: [PATCH 1260/1751] GPU: Reject tracks with too large fraction of ignored clusters --- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 3f0a32dad2a35..663a80820cd59 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -326,8 +326,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, } ConstrainSinPhi(); - bool ok = N + NTolerated >= GPUCA_TRACKLET_SELECTOR_MIN_HITS(mP[4]) && CheckNumericalQuality(covYYUpd); - if (!ok) { + if (!(N + NTolerated >= GPUCA_TRACKLET_SELECTOR_MIN_HITS(mP[4]) && 2 * NTolerated <= CAMath::Max(10, N) && CheckNumericalQuality(covYYUpd))) { return (false); } @@ -338,7 +337,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, MoveToReference(prop, param, Alpha); NormalizeAlpha(Alpha); - return (ok); + return (true); } GPUd() void GPUTPCGMTrackParam::MoveToReference(GPUTPCGMPropagator& prop, const GPUParam& param, float& Alpha) From 666bba5588cd93a55fcffa07a346472aaed73a07 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 9 Nov 2020 13:36:15 +0100 Subject: [PATCH 1261/1751] DPL: do not invoke end of stream for pipe devices (#4796) EndOfStream + Quit should only be raised by devices which produce data from no source. All the other devices should simply process all the data the got in input. --- Framework/Core/src/AODReaderHelpers.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 6600cf0b06171..f7300b825bfcb 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -75,7 +75,6 @@ static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingConte AlgorithmSpec AODReaderHelpers::indexBuilderCallback(std::vector<InputSpec> requested) { return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { - setEOSCallback(ic); return [requested](ProcessingContext& pc) { auto outputs = pc.outputs(); @@ -132,7 +131,6 @@ AlgorithmSpec AODReaderHelpers::indexBuilderCallback(std::vector<InputSpec> requ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> requested) { return AlgorithmSpec::InitCallback{[requested](InitContext& ic) { - setEOSCallback(ic); return [requested](ProcessingContext& pc) { auto outputs = pc.outputs(); From 47507f3f440c557ea0e54bb064a7ba20c31b5334 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 9 Nov 2020 13:44:25 +0100 Subject: [PATCH 1262/1751] create dict in full system test (#4799) * full system: Dictionary creation in CPU stage Co-authored-by: David Rohr <drohr@jwdt.org> --- prodtests/full_system_test.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 8a0a4f8565022..a42f00fa1c86a 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -68,13 +68,14 @@ cat raw/*/*.cfg > rawAll.cfg # We run the workflow in both CPU-only and With-GPU mode for STAGE in "NOGPU" "WITHGPU"; do + ARGS_ALL="--session default" if [[ "$STAGE" = "WITHGPU" ]]; then TPC_GPU_OPT="GPU_proc.deviceNum=0;GPU_global.deviceType=CUDA;GPU_proc.forceMemoryPoolSize=6000000000;GPU_proc.forceHostMemoryPoolSize=3000000000" else TPC_GPU_OPT="GPU_proc.forceHostMemoryPoolSize=${TPCTRACKERSCRATCHMEMORY}" + DICTCREATION=" | o2-ctf-writer-workflow $ARGS_ALL --output-type dict --save-dict-after 1 --onlyDet ITS,MFT,TPC,TOF,FT0,MID " fi - ARGS_ALL="--session default" logfile=reco_${STAGE}.log taskwrapper ${logfile} "o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | o2-itsmft-stf-decoder-workflow $ARGS_ALL | @@ -85,13 +86,13 @@ o2-tpc-reco-workflow $ARGS_ALL --input-type=zsraw ${NOMCLABELS} --output-type tr o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | o2-ft0-entropy-encoder-workflow $ARGS_ALL | -o2-tpcits-match-workflow $ARGS_ALL -b --disable-root-input --disable-root-output ${NOMCLABELS} | +o2-tpcits-match-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | o2-mid-raw-to-digits-workflow $ARGS_ALL | o2-mid-reco-workflow $ARGS_ALL --disable-root-output | -o2-mid-entropy-encoder-workflow $ARGS_ALL | -o2-tof-compressor $ARGS_ALL | +o2-mid-entropy-encoder-workflow $ARGS_ALL | +o2-tof-compressor $ARGS_ALL | o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output ${NOMCLABELS} | -o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input --shm-segment-size $SHMSIZE ${GLOBALDPLOPT}" +o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input ${DICTCREATION} --shm-segment-size $SHMSIZE ${GLOBALDPLOPT}" # --- record interesting metrics to monitor ---- From c056d9eaa27da6f9c5fba6ffe9eded8b87f379cb Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 9 Nov 2020 13:49:29 +0100 Subject: [PATCH 1263/1751] Cleanup + stability fixes in jobutils --- Utilities/Tools/jobutils.sh | 49 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index 38bc130bdd09e..ad2a04ecf85bb 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -16,33 +16,30 @@ # simply sourced into the target script. -# returns list of files used in /dev/shm (this is done by DPL for shared memory communication) -# arguments is a list of pids -getShmFiles() { - F=`for p in "$@"; do - lsof -p ${p} 2>/dev/null | grep "/dev/shm/" | awk '//{print $9}' - done | sort | uniq | tr '\n' ' '` - echo "$F" -} - o2_cleanup_shm_files() { - # find shared memory files **CURRENTLY IN USE** by FairMQ - USEDFILES=`/usr/sbin/lsof -u $(whoami) | grep "/dev/shm/fmq" | sed 's/.*\/dev/\/dev/g' | sort | uniq | tr '\n' ' '` + # check if we have lsof (otherwise we do nothing) + which lsof &> /dev/null + if [ "$?" = "0" ]; then + # find shared memory files **CURRENTLY IN USE** by FairMQ + USEDFILES=`lsof -u $(whoami) | grep -e \"/dev/shm/.*fmq\" | sed 's/.*\/dev/\/dev/g' | sort | uniq | tr '\n' ' '` - echo "${USEDFILES}" - if [ ! "${USEDFILES}" ]; then - # in this case we can remove everything - COMMAND="find /dev/shm/ -name \"fmq_*\" -delete" + echo "${USEDFILES}" + if [ ! "${USEDFILES}" ]; then + # in this case we can remove everything + COMMAND="find /dev/shm/ -user $(whoami) -name \"*fmq_*\" -delete 2> /dev/null" + else + # build exclusion list + for f in ${USEDFILES}; do + LOGICALOP="" + [ "${EXCLPATTERN}" ] && LOGICALOP="-o" + EXCLPATTERN="${EXCLPATTERN} ${LOGICALOP} -wholename ${f}" + done + COMMAND="find /dev/shm/ -user $(whoami) -type f -not \( ${EXCLPATTERN} \) -delete 2> /dev/null" + fi + eval "${COMMAND}" else - # build exclusion list - for f in ${USEDFILES}; do - LOGICALOP="" - [ "${EXCLPATTERN}" ] && LOGICALOP="-o" - EXCLPATTERN="${EXCLPATTERN} ${LOGICALOP} -wholename ${f}" - done - COMMAND="find /dev/shm/ -type f -not \( ${EXCLPATTERN} \) -delete" + echo "Can't do shared mem cleanup: lsof not found" fi - eval "${COMMAND}" } # Function to find out all the (recursive) child processes starting from a parent PID. @@ -186,11 +183,13 @@ taskwrapper() { sleep 2 - # query processes still alive + # query processes still alive and terminate them for p in $(childprocs ${PID}); do echo "killing child $p" - kill $p 2> /dev/null + kill -9 $p 2> /dev/null done + sleep 2 + # remove leftover shm files o2_cleanup_shm_files From 6cba4f993185b238b647cbb46bdbd90f1ec391c2 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 9 Nov 2020 14:12:58 +0100 Subject: [PATCH 1264/1751] full_system_test: do not create ctf dict for GPU stage --- prodtests/full_system_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index a42f00fa1c86a..24cf2346e0ea8 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -69,6 +69,7 @@ cat raw/*/*.cfg > rawAll.cfg for STAGE in "NOGPU" "WITHGPU"; do ARGS_ALL="--session default" + DICTCREATION="" if [[ "$STAGE" = "WITHGPU" ]]; then TPC_GPU_OPT="GPU_proc.deviceNum=0;GPU_global.deviceType=CUDA;GPU_proc.forceMemoryPoolSize=6000000000;GPU_proc.forceHostMemoryPoolSize=3000000000" else From d1c23a82f1f3cdd08590f2677b44e1d1db965b92 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 9 Nov 2020 16:02:57 +0100 Subject: [PATCH 1265/1751] DPL: fix naming (#4801) --- .../include/Framework/CommonDataProcessors.h | 2 +- Framework/Core/src/CommonDataProcessors.cxx | 8 +++---- Framework/Core/src/WorkflowHelpers.cxx | 22 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Framework/Core/include/Framework/CommonDataProcessors.h b/Framework/Core/include/Framework/CommonDataProcessors.h index c8162fbd3487f..fbdff88521022 100644 --- a/Framework/Core/include/Framework/CommonDataProcessors.h +++ b/Framework/Core/include/Framework/CommonDataProcessors.h @@ -41,7 +41,7 @@ struct CommonDataProcessors { /// writes inputs of kind AOD to file static DataProcessorSpec getGlobalAODSink(std::shared_ptr<DataOutputDirector> dod, - std::vector<InputSpec> const& OutputInputs); + std::vector<InputSpec> const& outputInputs); /// @return a dummy DataProcessorSpec which requires all the passed @a InputSpec /// and simply discards them. diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 59b216abef4db..cc587aa7b928e 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -243,15 +243,15 @@ enum FileType : int { // add sink for the AODs DataProcessorSpec CommonDataProcessors::getGlobalAODSink(std::shared_ptr<DataOutputDirector> dod, - std::vector<InputSpec> const& OutputInputs) + std::vector<InputSpec> const& outputInputs) { - auto writerFunction = [dod, OutputInputs](InitContext& ic) -> std::function<void(ProcessingContext&)> { + auto writerFunction = [dod, outputInputs](InitContext& ic) -> std::function<void(ProcessingContext&)> { LOGP(DEBUG, "======== getGlobalAODSink::Init =========="); // find out if any table needs to be saved bool hasOutputsToWrite = false; - for (auto& outobj : OutputInputs) { + for (auto& outobj : outputInputs) { auto ds = dod->getDataOutputDescriptors(outobj); if (ds.size() > 0) { hasOutputsToWrite = true; @@ -375,7 +375,7 @@ DataProcessorSpec // see runDataProcessing.h DataProcessorSpec spec{ "internal-dpl-aod-writer", - OutputInputs, + outputInputs, Outputs{}, AlgorithmSpec(writerFunction), {}}; diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index d33bd314f28b7..c13e614268d5c 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -439,20 +439,20 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext /// Analyze all ouputs // outputTypes = isAOD*2 + isdangling*1 + 0 - auto [OutputsInputs, outputTypes] = analyzeOutputs(workflow); + auto [outputsInputs, outputTypes] = analyzeOutputs(workflow); // create DataOutputDescriptor - std::shared_ptr<DataOutputDirector> dod = getDataOutputDirector(ctx.options(), OutputsInputs, outputTypes); + std::shared_ptr<DataOutputDirector> dod = getDataOutputDirector(ctx.options(), outputsInputs, outputTypes); // select outputs of type AOD which need to be saved // ATTENTION: if there are dangling outputs the getGlobalAODSink // has to be created in any case! std::vector<InputSpec> outputsInputsAOD; - for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { + for (auto ii = 0u; ii < outputsInputs.size(); ii++) { if ((outputTypes[ii] & ANALYSIS) == ANALYSIS) { - auto ds = dod->getDataOutputDescriptors(OutputsInputs[ii]); + auto ds = dod->getDataOutputDescriptors(outputsInputs[ii]); if (ds.size() > 0 || (outputTypes[ii] & DANGLING) == DANGLING) { - outputsInputsAOD.emplace_back(OutputsInputs[ii]); + outputsInputsAOD.emplace_back(outputsInputs[ii]); } } } @@ -471,9 +471,9 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // file sink for notAOD dangling outputs // select dangling outputs which are not of type AOD std::vector<InputSpec> outputsInputsDangling; - for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { + for (auto ii = 0u; ii < outputsInputs.size(); ii++) { if ((outputTypes[ii] & DANGLING) == DANGLING && (outputTypes[ii] & ANALYSIS) == 0) { - outputsInputsDangling.emplace_back(OutputsInputs[ii]); + outputsInputsDangling.emplace_back(outputsInputs[ii]); } } @@ -961,12 +961,12 @@ std::tuple<std::vector<InputSpec>, std::vector<unsigned char>> WorkflowHelpers:: std::vector<InputSpec> WorkflowHelpers::computeDanglingOutputs(WorkflowSpec const& workflow) { - auto [OutputsInputs, outputTypes] = analyzeOutputs(workflow); + auto [outputsInputs, outputTypes] = analyzeOutputs(workflow); std::vector<InputSpec> results; - for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { - if ((outputTypes[ii] & 1) == 1) { - results.emplace_back(OutputsInputs[ii]); + for (auto ii = 0u; ii < outputsInputs.size(); ii++) { + if (outputTypes[ii] & DANGLING) { + results.emplace_back(outputsInputs[ii]); } } From cb9f6cd195dd33c8ab578b49e3a0bfc8f13ae024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Mon, 9 Nov 2020 19:59:01 +0100 Subject: [PATCH 1266/1751] Use constexpr for histogram naming (#4798) --- Analysis/Tasks/PWGLF/spectraTOF.cxx | 21 ++++--- Analysis/Tasks/PWGLF/spectraTPC.cxx | 90 +++++++++++++++-------------- Analysis/Tasks/pidTOF.cxx | 46 +++++++++------ Analysis/Tasks/pidTPC.cxx | 40 ++++++++----- 4 files changed, 109 insertions(+), 88 deletions(-) diff --git a/Analysis/Tasks/PWGLF/spectraTOF.cxx b/Analysis/Tasks/PWGLF/spectraTOF.cxx index e83db317184b6..73a12607a8f96 100644 --- a/Analysis/Tasks/PWGLF/spectraTOF.cxx +++ b/Analysis/Tasks/PWGLF/spectraTOF.cxx @@ -21,10 +21,11 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -const int Np = 9; -const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; -const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; struct TOFSpectraTask { + static constexpr int Np = 9; + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr const char* hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr const char* hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) @@ -32,8 +33,8 @@ struct TOFSpectraTask { histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); for (int i = 0; i < Np; i++) { - histos.add(Form("p/%s", pN[i].Data()), Form("%s;#it{p} (GeV/#it{c})", pT[i].Data()), kTH1F, {{100, 0, 20}}); - histos.add(Form("pt/%s", pN[i].Data()), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i].Data()), kTH1F, {{100, 0, 20}}); + histos.add(hp[i], Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i], Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); } histos.add("electronbeta/hp_El", ";#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); histos.add("electronbeta/hpt_El", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); @@ -43,10 +44,12 @@ struct TOFSpectraTask { histos.add("electronbeta/hp_betasigma_El", ";#it{p} (GeV/#it{c});(#beta - #beta_{e})/#sigma;Tracks", kTH2D, {{100, 0, 20}, {100, -5, 5}}); } + Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; - Filter trackFilter = aod::track::isGlobalTrack == true; - + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == true) && (aod::track::tofSignal > 0.f); using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta, aod::TrackSelection>>; void process(TrackCandidates::iterator const& track) { @@ -59,8 +62,8 @@ struct TOFSpectraTask { if (abs(nsigma[i]) > nsigmacut.value) { continue; } - histos.fill(Form("p/%s", pN[i].Data()), track.p()); - histos.fill(Form("pt/%s", pN[i].Data()), track.pt()); + histos.fill(hp[i], track.p()); + histos.fill(hpt[i], track.pt()); } // if (TMath::Abs(track.separationbetael() < 1.f)) { diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index 0441f591aeeb7..f112b42012af1 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -20,10 +20,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -const int Np = 9; -const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; -const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; - void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { std::vector<ConfigParamSpec> options{ @@ -54,50 +50,20 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) h->GetXaxis()->Set(nbins, binp); \ } -struct TPCPIDQASignalwTOFTask { - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - void init(o2::framework::InitContext&) - { - for (int i = 0; i < Np; i++) { - histos.add("signal/htpcsignal" + pN[i], ";#it{p} (GeV/#it{c});TPC Signal;N_{#sigma}^{TPC}(" + pT[i] + ")", kTH3D, {{1000, 0.001, 20}, {1000, 0, 1000}, {20, -10, 10}}); - makelogaxis(histos.get<TH3>("hexp" + pN[i])); - } - } - - // Filters - CANDIDATE_SELECTION - - Filter trackFilterTOF = (aod::track::tofSignal > 0); // Skip tracks without TOF - using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>>; - void process(TrackCandidates::iterator const& track) - { - // const float mom = track.p(); - const float mom = track.tpcInnerParam(); - histos.fill("htpcsignalEl", mom, track.tpcSignal(), track.tofNSigmaEl()); - histos.fill("htpcsignalMu", mom, track.tpcSignal(), track.tofNSigmaMu()); - histos.fill("htpcsignalPi", mom, track.tpcSignal(), track.tofNSigmaPi()); - histos.fill("htpcsignalKa", mom, track.tpcSignal(), track.tofNSigmaKa()); - histos.fill("htpcsignalPr", mom, track.tpcSignal(), track.tofNSigmaPr()); - histos.fill("htpcsignalDe", mom, track.tpcSignal(), track.tofNSigmaDe()); - histos.fill("htpcsignalTr", mom, track.tpcSignal(), track.tofNSigmaTr()); - histos.fill("htpcsignalHe", mom, track.tpcSignal(), track.tofNSigmaHe()); - histos.fill("htpcsignalAl", mom, track.tpcSignal(), track.tofNSigmaAl()); - } -}; - +constexpr int Np = 9; struct TPCSpectraTask { + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr const char* hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr const char* hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry pt{"pt", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry p{"pt", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); for (int i = 0; i < Np; i++) { - histos.add("p/" + pN[i], pT[i] + ";#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); - histos.add("pt/" + pN[i], pT[i] + ";#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add(hp[i], Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i], Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); } } @@ -112,18 +78,54 @@ struct TPCSpectraTask { const float nsigma[Np] = {track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl()}; - p.fill("Unselected", track.p()); - pt.fill("Unselected", track.pt()); + histos.fill("p/Unselected", track.p()); + histos.fill("pt/Unselected", track.pt()); for (int i = 0; i < Np; i++) { if (abs(nsigma[i]) > nsigmacut.value) { continue; } - p.fill(pN[i], track.p()); - pt.fill(pN[i], track.pt()); + histos.fill(hp[i], track.p()); + histos.fill(hpt[i], track.pt()); } } }; +struct TPCPIDQASignalwTOFTask { + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr const char* htpcsignal[Np] = {"tpcsignal/El", "tpcsignal/Mu", "tpcsignal/Pi", + "tpcsignal/Ka", "tpcsignal/Pr", "tpcsignal/De", + "tpcsignal/Tr", "tpcsignal/He", "tpcsignal/Al"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + for (int i = 0; i < Np; i++) { + histos.add(htpcsignal[i], Form(";#it{p} (GeV/#it{c});TPC Signal;N_{#sigma}^{TPC}(%s)", pT[i]), kTH3D, {{1000, 0.001, 20}, {1000, 0, 1000}, {20, -10, 10}}); + makelogaxis(histos.get<TH3>(htpcsignal[i])); + } + } + + // Filters + CANDIDATE_SELECTION + + Filter trackFilterTOF = (aod::track::tofSignal > 0.f); // Skip tracks without TOF + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::pidRespTOF, aod::TrackSelection>>; + void process(TrackCandidates::iterator const& track) + { + // const float mom = track.p(); + const float mom = track.tpcInnerParam(); + histos.fill(htpcsignal[0], mom, track.tpcSignal(), track.tofNSigmaEl()); + histos.fill(htpcsignal[1], mom, track.tpcSignal(), track.tofNSigmaMu()); + histos.fill(htpcsignal[2], mom, track.tpcSignal(), track.tofNSigmaPi()); + histos.fill(htpcsignal[3], mom, track.tpcSignal(), track.tofNSigmaKa()); + histos.fill(htpcsignal[4], mom, track.tpcSignal(), track.tofNSigmaPr()); + histos.fill(htpcsignal[5], mom, track.tpcSignal(), track.tofNSigmaDe()); + histos.fill(htpcsignal[6], mom, track.tpcSignal(), track.tofNSigmaTr()); + histos.fill(htpcsignal[7], mom, track.tpcSignal(), track.tofNSigmaHe()); + histos.fill(htpcsignal[8], mom, track.tpcSignal(), track.tofNSigmaAl()); + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { int TPCwTOF = cfgc.options().get<int>("add-tof-histos"); diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index 800e629add311..665f9217f0942 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -135,10 +135,18 @@ struct pidTOFTaskBeta { } }; -const int Np = 9; -const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; -const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; struct pidTOFTaskQA { + static constexpr int Np = 9; + static constexpr const char* hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", + "expected/Ka", "expected/Pr", "expected/De", + "expected/Tr", "expected/He", "expected/Al"}; + static constexpr const char* hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", + "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", + "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; + static constexpr const char* hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", + "nsigma/Ka", "nsigma/Pr", "nsigma/De", + "nsigma/Tr", "nsigma/He", "nsigma/Al"}; + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; Configurable<int> nBinsP{"nBinsP", 400, "Number of bins for the momentum"}; @@ -165,22 +173,22 @@ struct pidTOFTaskQA { void init(o2::framework::InitContext&) { // Event properties - histos.add("event/hvertexz", ";Vtx_{z} (cm);Entries", HistType::kTH1F, {{100, -20, 20}}); + histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", HistType::kTH1F, {{100, -20, 20}}); histos.add("event/colltime", ";Collision time (ps);Entries", HistType::kTH1F, {{100, -2000, 2000}}); - histos.add("event/htofsignal", ";#it{p} (GeV/#it{c});TOF Signal", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {10000, 0, 2e6}}); - makelogaxis(histos.get<TH2>("event/htofsignal")); - histos.add("event/htofbeta", ";#it{p} (GeV/#it{c});TOF #beta", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2}}); - makelogaxis(histos.get<TH2>("event/htofbeta")); + histos.add("event/tofsignal", ";#it{p} (GeV/#it{c});TOF Signal", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {10000, 0, 2e6}}); + makelogaxis(histos.get<TH2>("event/tofsignal")); + histos.add("event/tofbeta", ";#it{p} (GeV/#it{c});TOF #beta", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2}}); + makelogaxis(histos.get<TH2>("event/tofbeta")); for (int i = 0; i < Np; i++) { // Exp signal - histos.add("expected/" + pN[i], Form(";#it{p} (GeV/#it{c});t_{exp}(%s)", pT[i].Data()), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2e6}}); - makelogaxis(histos.get<TH2>("expected/" + pN[i])); + histos.add(hexpected[i], Form(";#it{p} (GeV/#it{c});t_{exp}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2e6}}); + makelogaxis(histos.get<TH2>(hexpected[i])); // T-Texp - histos.add("timediff/" + pN[i], Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp}(%s))", pT[i].Data()), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {100, -1000, 1000}}); - makelogaxis(histos.get<TH2>("timediff/" + pN[i])); + histos.add(hexpected_diff[i], Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp}(%s))", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {100, -1000, 1000}}); + makelogaxis(histos.get<TH2>(hexpected_diff[i])); // NSigma - histos.add("nsigma/" + pN[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(%s)", pT[i].Data()), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); - makelogaxis(histos.get<TH2>("nsigma/" + pN[i])); + histos.add(hnsigma[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get<TH2>(hnsigma[i])); } } #undef makelogaxis @@ -197,22 +205,22 @@ struct pidTOFTaskQA { } const float tof = t.tofSignal() - collision.collisionTime(); // - histos.fill("event/htofsignal", t.p(), t.tofSignal()); - histos.fill("event/htofbeta", t.p(), t.beta()); + histos.fill("event/tofsignal", t.p(), t.tofSignal()); + histos.fill("event/tofbeta", t.p(), t.beta()); // const float exp[Np] = {t.tofExpSignalEl(), t.tofExpSignalMu(), t.tofExpSignalPi(), t.tofExpSignalKa(), t.tofExpSignalPr(), t.tofExpSignalDe(), t.tofExpSignalTr(), t.tofExpSignalHe(), t.tofExpSignalAl()}; for (int i = 0; i < Np; i++) { - histos.fill("expected/" + pN[i], t.p(), exp[i]); - histos.fill("timediff/" + pN[i], t.p(), tof - exp[i]); + histos.fill(hexpected[i], t.p(), exp[i]); + histos.fill(hexpected_diff[i], t.p(), tof - exp[i]); } // const float nsigma[Np] = {t.tofNSigmaEl(), t.tofNSigmaMu(), t.tofNSigmaPi(), t.tofNSigmaKa(), t.tofNSigmaPr(), t.tofNSigmaDe(), t.tofNSigmaTr(), t.tofNSigmaHe(), t.tofNSigmaAl()}; for (int i = 0; i < Np; i++) { - histos.fill("nsigma/" + pN[i], t.p(), nsigma[i]); + histos.fill(hnsigma[i], t.p(), nsigma[i]); } } } diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index e068d99c7b9b8..b3a8191c022d6 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -111,10 +111,18 @@ struct pidTPCTask { } }; -const int Np = 9; -const TString pN[Np] = {"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; -const TString pT[Np] = {"#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; struct pidTPCTaskQA { + static constexpr int Np = 9; + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr const char* hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", + "expected/Ka", "expected/Pr", "expected/De", + "expected/Tr", "expected/He", "expected/Al"}; + static constexpr const char* hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", + "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", + "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; + static constexpr const char* hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", + "nsigma/Ka", "nsigma/Pr", "nsigma/De", + "nsigma/Tr", "nsigma/He", "nsigma/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; Configurable<int> nBinsP{"nBinsP", 400, "Number of bins for the momentum"}; @@ -142,19 +150,19 @@ struct pidTPCTaskQA { } // Event properties - histos.add("event/hvertexz", ";Vtx_{z} (cm);Entries", kTH1F, {{100, -20, 20}}); - histos.add("event/htpcsignal", ";#it{p} (GeV/#it{c});TPC Signal", kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); - makelogaxis(histos.get<TH2>("event/htpcsignal")); + histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", kTH1F, {{100, -20, 20}}); + histos.add("event/tpcsignal", ";#it{p} (GeV/#it{c});TPC Signal", kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); + makelogaxis(histos.get<TH2>("event/tpcsignal")); for (int i = 0; i < Np; i++) { // Exp signal - histos.add("expected/" + pN[i], Form(";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_(%s)", pT[i].Data()), kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); - makelogaxis(histos.get<TH2>("expected/" + pN[i])); + histos.add(hexpected[i], Form(";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); + makelogaxis(histos.get<TH2>(hexpected[i])); // Signal - Expected signal - histos.add("expected_diff/" + pN[i], Form(";#it{p} (GeV/#it{c});;d#it{E}/d#it{x} - d#it{E}/d#it{x}(%s)", pT[i].Data()), kTH2F, {{nBinsP, MinP, MaxP}, {1000, -500, 500}}); - makelogaxis(histos.get<TH2>("expected_diff/" + pN[i])); + histos.add(hexpected_diff[i], Form(";#it{p} (GeV/#it{c});;d#it{E}/d#it{x} - d#it{E}/d#it{x}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, -500, 500}}); + makelogaxis(histos.get<TH2>(hexpected_diff[i])); // NSigma - histos.add("nsigma/" + pN[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(%s)", pT[i].Data()), kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); - makelogaxis(histos.get<TH2>("nsigma/" + pN[i])); + histos.add(hnsigma[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get<TH2>(hnsigma[i])); } #undef makelogaxis } @@ -165,21 +173,21 @@ struct pidTPCTaskQA { for (auto t : tracks) { // const float mom = t.p(); const float mom = t.tpcInnerParam(); - histos.fill("event/htpcsignal", mom, t.tpcSignal()); + histos.fill("event/tpcsignal", mom, t.tpcSignal()); // const float exp[Np] = {t.tpcExpSignalEl(), t.tpcExpSignalMu(), t.tpcExpSignalPi(), t.tpcExpSignalKa(), t.tpcExpSignalPr(), t.tpcExpSignalDe(), t.tpcExpSignalTr(), t.tpcExpSignalHe(), t.tpcExpSignalAl()}; for (int i = 0; i < Np; i++) { - histos.fill("expected/" + pN[i], mom, exp[i]); - histos.fill("expected_diff/" + pN[i], mom, t.tpcSignal() - exp[i]); + histos.fill(hexpected[i], mom, exp[i]); + histos.fill(hexpected_diff[i], mom, t.tpcSignal() - exp[i]); } // const float nsigma[Np] = {t.tpcNSigmaEl(), t.tpcNSigmaMu(), t.tpcNSigmaPi(), t.tpcNSigmaKa(), t.tpcNSigmaPr(), t.tpcNSigmaDe(), t.tpcNSigmaTr(), t.tpcNSigmaHe(), t.tpcNSigmaAl()}; for (int i = 0; i < Np; i++) { - histos.fill("nsigma/" + pN[i], t.p(), nsigma[i]); + histos.fill(hnsigma[i], t.p(), nsigma[i]); } } } From cd1421979924907e323f06a13d73e4087f012669 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Mon, 9 Nov 2020 20:00:04 +0100 Subject: [PATCH 1267/1751] TRD fix digit sorting (#4762) --- .../TRD/include/DataFormatsTRD/LinkRecord.h | 46 ++--- .../Detectors/TRD/src/DataFormatsTRDLinkDef.h | 1 + DataFormats/Detectors/TRD/src/LinkRecord.cxx | 21 +- .../TRDWorkflow/TRDTrapSimulatorSpec.h | 1 + .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 186 ++++++------------ 5 files changed, 95 insertions(+), 160 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h index 8b2498de7425e..dccb1a4f73532 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h @@ -23,19 +23,6 @@ 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 @@ -43,27 +30,40 @@ class LinkRecord { using DataRange = o2::dataformats::RangeReference<int>; + struct LinkId { + 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; + }; + }; + }; + public: LinkRecord() = default; - LinkRecord(const uint32_t linkid, int firstentry, int nentries) : mDataRange(firstentry, nentries) { mLinkId.word = linkid; } + LinkRecord(const uint32_t linkid, int firstentry, int nentries) : mDataRange(firstentry, nentries) { mLinkId = 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.word = linkid; } - void setLinkId(const LinkId linkid) { mLinkId.word = linkid.word; } + void setLinkId(const uint32_t linkid) { mLinkId = linkid; } + // void setLinkId(const LinkId linkid) { mLinkId = linkid; } 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); } - const uint32_t getLinkId() { return mLinkId.word; } + const uint32_t getLinkId() { return mLinkId; } //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; } + const uint32_t getSector() { return (mLinkId & 0xf800) >> 11; } + const uint32_t getStack() { return (mLinkId & 0x700) >> 8; } + const uint32_t getLayer() { return (mLinkId & 0xe0) >> 5; } + const uint32_t getSide() { return (mLinkId & 0x10) >> 4; } int getNumberOfObjects() const { return mDataRange.getEntries(); } int getFirstEntry() const { return mDataRange.getFirstEntry(); } static uint32_t getHalfChamberLinkId(uint32_t detector, uint32_t rob); @@ -72,9 +72,9 @@ class LinkRecord void printStream(std::ostream& stream); private: - LinkId mLinkId; + uint16_t mLinkId; DataRange mDataRange; /// Index of the triggering event (event index and first entry in the container) - ClassDefNV(LinkRecord, 2); + ClassDefNV(LinkRecord, 3); }; std::ostream& operator<<(std::ostream& stream, LinkRecord& trg); diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index 4fe89c45df5ff..e21390345f4c7 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -16,6 +16,7 @@ #pragma link C++ class o2::trd::TriggerRecord + ; #pragma link C++ class o2::trd::LinkRecord + ; +#pragma link C++ struct o2::trd::LinkRecord::LinkId + ; #pragma link C++ struct o2::trd::HalfCRUHeader + ; #pragma link C++ struct o2::trd::TrackletHCHeader + ; #pragma link C++ struct o2::trd::TrackletMCMHeader + ; diff --git a/DataFormats/Detectors/TRD/src/LinkRecord.cxx b/DataFormats/Detectors/TRD/src/LinkRecord.cxx index e78b564277dc5..e4d75a231fa5a 100644 --- a/DataFormats/Detectors/TRD/src/LinkRecord.cxx +++ b/DataFormats/Detectors/TRD/src/LinkRecord.cxx @@ -24,27 +24,22 @@ uint32_t LinkRecord::getHalfChamberLinkId(uint32_t detector, uint32_t rob) int stack = (detector % constants::NLAYER); int layer = ((detector % (constants::NLAYER * constants::NSTACK)) / constants::NLAYER); int side = rob % 2; - return getHalfChamberLinkId(sector, stack, layer, side); + return LinkRecord::getHalfChamberLinkId(sector, stack, layer, side); } 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; + LinkRecord tmplinkid; + tmplinkid.setLinkId(sector, stack, layer, side); + return tmplinkid.getLinkId(); } 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; + mLinkId |= sector << 11; + mLinkId |= stack << 8; + mLinkId |= layer << 5; + mLinkId |= side << 4; } void LinkRecord::printStream(std::ostream& stream) diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h index 07db64f44eaa1..f4726390e26b0 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h @@ -65,6 +65,7 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task bool mEnableOnlineGainCorrection{false}; bool mEnableTrapConfigDump{false}; bool mFixTriggerRecords{false}; // shift the trigger record due to its being corrupt on coming in. + bool mDumpTriggerRecords{false}; // display the trigger records. std::vector<Tracklet64> mTracklets; // store of found tracklets std::string mTrapConfigName; // the name of the config to be used. std::string mTrapConfigBaseName = "TRD_test/TrapConfig/"; diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index c4eed5f25ef39..80287c45ecd95 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -21,6 +21,8 @@ #include <unistd.h> // for getppid #include <chrono> #include <gsl/span> +#include <iostream> +#include <fstream> #include "TChain.h" @@ -57,83 +59,13 @@ //#endif ci is failing on this, sort out another time. using namespace o2::framework; +using namespace std::placeholders; // this is for std::bind to build the comparator for the indexed sort of digits. namespace o2 { namespace trd { -bool msgDigitSortComparator(o2::trd::Digit const& a, o2::trd::Digit const& b) -{ - // sort digits. - // order of sort, is time, detector, hlaf chamber index, readout board, mcm. - // the pads wont be in order they are in, in the pad row. - // it however does not matter as all the relevant pads will be loaded into the 8 mcms of the pad row. - // so the shared pad issue is fixed. - FeeParam* fee = FeeParam::instance(); - int rowa = a.getRow(); - int rowb = b.getRow(); - int pada = a.getPad(); - int padb = b.getPad(); - int deta = a.getDetector(); - int detb = b.getDetector(); - double timea = a.getTimeStamp(); - double timeb = b.getTimeStamp(); - int roba = fee->getROBfromPad(rowa, pada); - int robb = fee->getROBfromPad(rowb, padb); - int mcma = fee->getMCMfromPad(rowa, pada); - int mcmb = fee->getMCMfromPad(rowb, padb); - int hcida = deta * 2 + roba % 2; - int hcidb = detb * 2 + robb % 2; - //LOG(info) << "comparing " << rowa << ":" << pada <<":" << roba <<" "<< mcma << " with " << rowb << ":" << padb <<":" << robb <<" "<< mcmb; - if (timea < timeb) { - // LOG(info) << "yip timea < timeb " << timea <<"<" << timeb; - return 1; - } else if (timea == timeb) { - if (hcida < hcidb) { - return 1; - } else { - if (hcida == hcidb) { - if (mcma < mcmb) { - return 1; - } else { - return 0; - } - } else { - return 0; - } - } - return 0; - - /* if (deta < detb) - return 1; - else { - if (deta == detb) { - if(hcida < hcidb) - return 1; - else { - if (roba < robb) - return 1; - else { - if (roba == robb) { - if (mcma < mcmb) - return 1; - else - return 0; - } else - return 0; - } - return 0; - } - return 0; - } - return 0; - } - return 0;*/ - } - return 0; -} - TrapConfig* TRDDPLTrapSimulatorTask::getTrapConfig() { // return an existing TRAPconfig or load it from the CCDB @@ -149,7 +81,7 @@ TrapConfig* TRDDPLTrapSimulatorTask::getTrapConfig() // try to load the requested configuration loadTrapConfig(); //calib. - LOG(info) << "using TRAPconfig :" << mTrapConfig->getConfigName().c_str() << "." << mTrapConfig->getConfigVersion().c_str(); + LOG(info) << "using TRAPconfig :\"" << mTrapConfig->getConfigName().c_str() << "\".\"" << mTrapConfig->getConfigVersion().c_str() << "\""; // we still have to load the gain tables // if the gain filter is active @@ -240,6 +172,7 @@ void TRDDPLTrapSimulatorTask::init(o2::framework::InitContext& ic) mOnlineGainTableName = ic.options().get<std::string>("trd-onlinegaintable"); mRunNumber = ic.options().get<int>("trd-runnum"); mEnableTrapConfigDump = ic.options().get<bool>("trd-dumptrapconfig"); + mDumpTriggerRecords = ic.options().get<bool>("trd-dumptriggerrecords"); mFixTriggerRecords = ic.options().get<bool>("trd-fixtriggerrecord"); //Connect to CCDB for all things needing access to ccdb. auto& ccdbmgr = o2::ccdb::BasicCCDBManager::instance(); @@ -259,27 +192,10 @@ std::string printDigit(o2::trd::Digit& a) bool digitindexcompare(unsigned int A, unsigned int B, const std::vector<o2::trd::Digit>& originalDigits) { - + // sort into ROC:padrow:padcolum const o2::trd::Digit *a, *b; a = &originalDigits[A]; b = &originalDigits[B]; - FeeParam* fee = FeeParam::instance(); - int rowa = a->getRow(); - int rowb = b->getRow(); - int pada = a->getPad(); - int padb = b->getPad(); - double timea = a->getTimeStamp(); - double timeb = b->getTimeStamp(); - int roba = fee->getROBfromPad(rowa, pada); - int robb = fee->getROBfromPad(rowb, padb); - int mcma = fee->getMCMfromPad(rowa, pada); - int mcmb = fee->getMCMfromPad(rowb, padb); - if (a->getTimeStamp() < b->getTimeStamp()) { - return 1; - } - if (a->getTimeStamp() > b->getTimeStamp()) { - return 0; - } // timestamps are equal if (a->getDetector() < b->getDetector()) { return 1; @@ -287,19 +203,19 @@ bool digitindexcompare(unsigned int A, unsigned int B, const std::vector<o2::trd if (a->getDetector() > b->getDetector()) { return 0; } - //detectors are equal - if (roba < robb) { + if (a->getRow() < b->getRow()) { return 1; } - if (roba > robb) { + if (a->getRow() > b->getRow()) { return 0; } - //rob is equal - if (mcma < mcmb) { - return 1; - } else { + if (a->getPad() < b->getPad()) { return 0; } + if (a->getPad() > b->getPad()) { + return 1; + } + return 0; } void TRDDPLTrapSimulatorTask::setTriggerRecord(std::vector<o2::trd::TriggerRecord>& triggerrecord, uint32_t currentrecord, uint64_t recordsize) @@ -368,7 +284,10 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) uint64_t currentTriggerRecord = 0; for (auto& trig : triggerRecords) { - LOG(debug) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); + if (mDumpTriggerRecords) + LOG(info) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); + else + LOG(debug) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); } // fix incoming trigger records if requested. if (mFixTriggerRecords) { @@ -384,7 +303,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) std::vector<unsigned int> msgDigitsIndex; msgDigitsIndex.reserve(msgDigits.size()); - LOG(debug) << "Read in msgDigits with size of : " << msgDigits.size() << " labels contain : " << digitMCLabels.getNElements() << " with and index size of : " << digitMCLabels.getIndexedSize(); + LOG(debug) << "Read in msgDigits with size of : " << msgDigits.size() << " labels contain : " << digitMCLabels.getNElements() << " with and index size of : " << digitMCLabels.getIndexedSize() << " and triggerrecord count of :" << triggerRecords.size(); if (digitMCLabels.getIndexedSize() != msgDigits.size()) { LOG(warn) << "Digits and Labels coming into TrapSimulator are of differing sizes, labels will be jibberish. " << digitMCLabels.getIndexedSize() << "!=" << msgDigits.size(); @@ -408,30 +327,46 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) LOG(debug) << "msgdigitsindex is " << msgDigitsIndex.size(); auto sortstart = std::chrono::high_resolution_clock::now(); - //sort the digits array - std::stable_sort(msgDigits.begin(), msgDigits.end(), msgDigitSortComparator); + //sort the digits array TODO refactor this intoa vector index sort and possibly generalise past merely digits. + for (auto& trig : triggerRecords) { + LOG(debug) << " sorting from index: " << trig.getFirstEntry() << " till " << trig.getNumberOfObjects() + trig.getFirstEntry(); + LOG(debug) << "pre sort"; + for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) + LOG(debug) << "i:" << msgDigitsIndex[i]; + std::stable_sort(std::begin(msgDigitsIndex) + trig.getFirstEntry(), std::begin(msgDigitsIndex) + trig.getNumberOfObjects() + trig.getFirstEntry(), + [msgDigits](auto&& PH1, auto&& PH2) { return digitindexcompare(PH1, PH2, msgDigits); }); + LOG(debug) << "post sort"; + for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) + LOG(debug) << "i:" << i << " = " << msgDigitsIndex[i]; + LOG(debug) << "*****************************************************************"; + } + mSortingTime = std::chrono::high_resolution_clock::now() - sortstart; LOG(debug) << "TRD Digit Sorting took " << mSortingTime.count(); // sort from triggerRecords.getFirstEntry() to triggerRecords.getFirstEntry()+triggerRecords.getNumberOfObjects(); //check the incoming triggerrecords: + int triggerrecordcount = 0; for (auto& trig : triggerRecords) { - LOG(debug) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); + LOG(debug) << "Trigger Record ; " << triggerrecordcount << " = " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); + triggerrecordcount++; } for (auto& trig : trackletTriggerRecords) { LOG(debug) << "Trigger Tracklet Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); } //print digits to check the sorting. - LOG(debug4) << " Digits : "; - for (auto& digit : msgDigits) { - LOG(debug4) << "sorted digit time:" << digit.getTimeStamp() << " detector:row:pad:rob:mcm ::" - << digit.getDetector() << ":" << digit.getRow() << ":" << digit.getPad() << ":" - << mFeeParam->getROBfromPad(digit.getRow(), digit.getPad()) << ":" - << mFeeParam->getMCMfromPad(digit.getRow(), digit.getPad()) - << " LinkId:" << LinkRecord::getHalfChamberLinkId(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << "\t\t SM:stack:layer:side " - << digit.getDetector() / 30 << ":" << Geometry::getStack(digit.getDetector()) - << ":" << Geometry::getLayer(digit.getDetector()) << ":" << FeeParam::instance()->getRobSide(mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) - << " with ORI# : " << mFeeParam->getORI(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) - << " within SM ori#:" << mFeeParam->getORIinSM(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())); + LOG(info) << " Digits : "; + //for (auto& digit : msgDigits) { + for (auto& digitindex : msgDigitsIndex) { + Digit digit = msgDigits[digitindex]; + LOG(debug) << "sorted digit time:" << digit.getTimeStamp() << " detector:row:pad:rob:mcm ::" + << digit.getDetector() << ":" << digit.getRow() << ":" << digit.getPad() << ":" + << mFeeParam->getROBfromPad(digit.getRow(), digit.getPad()) << ":" + << mFeeParam->getMCMfromPad(digit.getRow(), digit.getPad()) + << " LinkId:" << LinkRecord::getHalfChamberLinkId(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << "\t\t SM:stack:layer:side " + << digit.getDetector() / 30 << ":" << Geometry::getStack(digit.getDetector()) + << ":" << Geometry::getLayer(digit.getDetector()) << ":" << FeeParam::instance()->getRobSide(mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) + << " with ORI# : " << mFeeParam->getORI(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) + << " within SM ori#:" << mFeeParam->getORIinSM(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())); } //accounting variables for various things. //TODO make them class members, i dont want to fiddle right now though. @@ -452,15 +387,17 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) uint64_t digitcounter = 0; double b = 0; LOG(debug4) << "now for digit loop "; - for (auto digititerator = msgDigits.begin(); digititerator != msgDigits.end() /* && std::distance(msgDigits.begin(),digititerator)<7*/; ++digititerator) { + for (auto digititerator = msgDigitsIndex.begin(); digititerator != msgDigitsIndex.end() /* && std::distance(msgDigits.begin(),digititerator)<7*/; ++digititerator) { //in here we have an entire padrow which corresponds to 8 TRAPs. //while on a single padrow, populate data structures in the 8 trapsimulator. //on change of padrow // fireup trapsim, do its thing with each 18 sequence of pads data that already exists inside the class from previous iterations of the loop - double digittime = digititerator->getTimeStamp(); - int pad = digititerator->getPad(); - int row = digititerator->getRow(); - int detector = digititerator->getDetector(); + LOG(debug) << "Digit iterator is : " << *digititerator; + Digit* digit = &msgDigits[*digititerator]; + double digittime = digit->getTimeStamp(); + int pad = digit->getPad(); + int row = digit->getRow(); + int detector = digit->getDetector(); int rob = mFeeParam->getROBfromPad(row, pad); int mcm = mFeeParam->getMCMfromPad(row, pad); int trdstack = Geometry::getStack(detector); @@ -472,7 +409,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) << " LinkId:" << LinkRecord::getHalfChamberLinkId(detector, rob) << "\t\t SM:stack:layer:side " << detector / 30 << ":" << trdstack << ":" << trdlayer << ":" << fibreside << " with ORI : " << mFeeParam->getORI(detector, rob) << " and within supermodule ori index:" << mFeeParam->getORIinSM(detector, rob); LOG(debug) << "digit time : " << digittime; - if (digititerator == msgDigits.begin()) { // first time in loop + if (digititerator == msgDigitsIndex.begin()) { // first time in loop oldrow = row; olddetector = detector; } @@ -499,7 +436,6 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) if (olddetector != detector || oldrow != row) { // we have gone over the pad row. //TODO ??? do we need to check for change of time as well? //all data is inside the 8 relavent trapsimulators - LOG(debug) << "digit count in change padrow if statement is : " << std::distance(msgDigits.begin(), digititerator); int preivousrob = mFeeParam->getROBfromPad(oldrow, oldpad); // //fireup Trapsim. auto traploopstart = std::chrono::high_resolution_clock::now(); @@ -611,7 +547,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) } LOG(debug) << "tmplabels for set data : " << tmplabels.size() << " and gslspan digitlabels size of : " << digitslabels.size(); LOG(debug) << " setting data with pad=" << pad << " ti=" << trapindex + 1; - mTrapSimulator[trapindex].setData(adc, digititerator->getADC(), tmplabels); + mTrapSimulator[trapindex].setData(adc, digit->getADC(), tmplabels); // now take care of the case of shared pads (the whole reason for doing this pad row wise). @@ -619,7 +555,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) adc = 20 - (pad % 18) - 1; if (trapindex != 0) { // avoid the case of the first trap chip LOG(debug) << " setting data preceding with pad=" << pad << " ti=" << trapindex - 1; - mTrapSimulator[trapindex - 1].setData(adc, digititerator->getADC(), tmplabels); + mTrapSimulator[trapindex - 1].setData(adc, digit->getADC(), tmplabels); } } if ((pad - 1) % 18 == 0) { // case of pad 17 must shared to next trap chip as adc 20 @@ -627,7 +563,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) adc = 20 - (pad % 18) - 1; if (trapindex + 1 != 8) { // avoid the case of the last trap chip. LOG(debug) << " setting data proceeding with pad=" << pad << " ti=" << trapindex + 1; - mTrapSimulator[trapindex + 1].setData(adc, digititerator->getADC(), tmplabels); + mTrapSimulator[trapindex + 1].setData(adc, digit->getADC(), tmplabels); } } @@ -661,7 +597,8 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) LOG(info) << "Raw data words written = " << mTotalRawWordsWritten << " with a vector size = " << rawdata.size(); } LOG(debug) << "END OF RUN ............."; - + //TODO does anyone care to have the digits to tracklet mapping. Do we then presort the digits inline with the index or send both digits and sorted index. + //TODO is is available for post processing via the debug stream output. pc.outputs().snapshot(Output{"TRD", "TRACKLETS", 0, Lifetime::Timeframe}, trapTrackletsAccum); pc.outputs().snapshot(Output{"TRD", "TRKTRGRD", 0, Lifetime::Timeframe}, trackletTriggerRecords); /*pc.outputs().snapshot(Output{"TRD", "TRKLABELS", 0, Lifetime::Timeframe}, trackletMCLabels); */ @@ -698,6 +635,7 @@ o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec() {"trd-onlinegaintable", VariantType::String, "Krypton_2015-02", {"Online gain table to be use, names found in CCDB, obviously trd-onlinegaincorrection must be set as well."}}, {"trd-debugrejectedtracklets", VariantType::Bool, false, {"Output all MCM where tracklets were not identified"}}, {"trd-dumptrapconfig", VariantType::Bool, false, {"Dump the selected trap configuration at loading time, to text file"}}, + {"trd-dumptriggerrecords", VariantType::Bool, false, {"Dump the trigger record to the default log output"}}, {"trd-runnum", VariantType::Int, 297595, {"Run number to use to anchor simulation to, defaults to 297595"}}}}; }; From cc7814d341a49538341a1055f0be3404d8733127 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 9 Nov 2020 18:58:32 +0100 Subject: [PATCH 1268/1751] GPU: Fix inconsistent usage of maxVDrift for computation of time0 and deltaFwd/deltaBwd --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 5 ++--- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index d6a2fcaf546c6..1534f56ac91ca 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -35,6 +35,7 @@ #include "GPUTPCGMMergedTrackHit.h" #include "GPUTPCGMMergerTypes.h" #include "GPUHostDataTypes.h" +#include "TPCFastTransform.h" #include <atomic> #ifdef WITH_OPENMP @@ -85,7 +86,6 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* auto& gasParam = ParameterGas::Instance(); auto& elParam = ParameterElectronics::Instance(); float vzbin = (elParam.ZbinWidth * gasParam.DriftV); - float vzbinInv = 1.f / vzbin; Mapper& mapper = Mapper::instance(); std::vector<o2::tpc::Digit> gpuDigits[Sector::MAXSECTOR]; @@ -179,7 +179,6 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* clusterOffsetCounter.store(0); constexpr float MinDelta = 0.1; - float maxDriftTime = detParam.TPClength * vzbinInv; #ifdef WITH_OPENMP #pragma omp parallel for if(!outputTracksMCTruth) num_threads(4) @@ -291,7 +290,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* // estimate max/min time increments which still keep track in the physical limits of the TPC auto times = std::minmax(t1, t2); tFwd = times.first - time0; - tBwd = time0 - (times.second - maxDriftTime); + tBwd = time0 - times.second + mTrackingCAO2Interface->getConfig().configCalib.fastTransform->getMaxDriftTime(t1 > t2 ? sector1 : sector2); } } oTrack.setTime0(time0); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 663a80820cd59..b81abd9b52cf6 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -327,7 +327,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, ConstrainSinPhi(); if (!(N + NTolerated >= GPUCA_TRACKLET_SELECTOR_MIN_HITS(mP[4]) && 2 * NTolerated <= CAMath::Max(10, N) && CheckNumericalQuality(covYYUpd))) { - return (false); + return (false); // TODO: NTolerated should never become that large, check what is going wrong! } if (dEdxOut) { From 29d623b9ab4fe330cfac30adcd43939e1996783d Mon Sep 17 00:00:00 2001 From: mbroz84 <michal.broz@cern.ch> Date: Tue, 10 Nov 2020 09:56:04 +0100 Subject: [PATCH 1269/1751] Raw data and CTF for FDD (#4659) * Raw data and CTF for FDD * Raw data and CTF for FDD * Additional CTF stuff * Fix of the CTF test * Clang format --- DataFormats/Detectors/FIT/FDD/CMakeLists.txt | 10 +- .../FIT/FDD/include/DataFormatsFDD/CTF.h | 82 ++++++++ .../FDD/include/DataFormatsFDD/LookUpTable.h | 115 +++++++++++ .../FDD/include/DataFormatsFDD/RawEventData.h | 187 +++++++++++++++++ DataFormats/Detectors/FIT/FDD/src/CTF.cxx | 34 +++ .../FIT/FDD/src/DataFormatsFDDLinkDef.h | 10 + .../Detectors/FIT/FDD/src/RawEventData.cxx | 71 +++++++ Detectors/CTF/CMakeLists.txt | 8 + Detectors/CTF/test/test_ctf_io_fdd.cxx | 146 +++++++++++++ Detectors/CTF/workflow/CMakeLists.txt | 2 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 + Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 3 + .../CTF/workflow/src/ctf-reader-workflow.cxx | 4 + .../FIT/FDD/base/include/FDDBase/Constants.h | 2 + Detectors/FIT/FDD/base/src/Geometry.cxx | 1 - .../FIT/FDD/reconstruction/CMakeLists.txt | 10 +- .../include/FDDReconstruction/CTFCoder.h | 193 ++++++++++++++++++ .../include/FDDReconstruction/ReadRaw.h | 67 ++++++ .../FIT/FDD/reconstruction/src/CTFCoder.cxx | 160 +++++++++++++++ .../src/FDDReconstructionLinkDef.h | 1 + .../FIT/FDD/reconstruction/src/ReadRaw.cxx | 168 +++++++++++++++ Detectors/FIT/FDD/simulation/CMakeLists.txt | 19 +- .../include/FDDSimulation/Digits2Raw.h | 68 ++++++ .../FIT/FDD/simulation/src/Digits2Raw.cxx | 173 ++++++++++++++++ .../FDD/simulation/src/FDDSimulationLinkDef.h | 1 + .../FIT/FDD/simulation/src/digit2raw.cxx | 114 +++++++++++ Detectors/FIT/FDD/workflow/CMakeLists.txt | 23 ++- .../include/FDDWorkflow/EntropyDecoderSpec.h | 47 +++++ .../include/FDDWorkflow/EntropyEncoderSpec.h | 47 +++++ .../include/FDDWorkflow/RecPointWriterSpec.h | 1 - .../FDD/workflow/src/EntropyDecoderSpec.cxx | 79 +++++++ .../FDD/workflow/src/EntropyEncoderSpec.cxx | 78 +++++++ .../workflow/src/digits-reader-workflow.cxx | 45 ++++ .../workflow/src/entropy-encoder-workflow.cxx | 39 ++++ 34 files changed, 2005 insertions(+), 11 deletions(-) create mode 100644 DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/CTF.h create mode 100644 DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/LookUpTable.h create mode 100644 DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/RawEventData.h create mode 100644 DataFormats/Detectors/FIT/FDD/src/CTF.cxx create mode 100644 DataFormats/Detectors/FIT/FDD/src/RawEventData.cxx create mode 100644 Detectors/CTF/test/test_ctf_io_fdd.cxx create mode 100644 Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/CTFCoder.h create mode 100644 Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/ReadRaw.h create mode 100644 Detectors/FIT/FDD/reconstruction/src/CTFCoder.cxx create mode 100644 Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx create mode 100644 Detectors/FIT/FDD/simulation/include/FDDSimulation/Digits2Raw.h create mode 100644 Detectors/FIT/FDD/simulation/src/Digits2Raw.cxx create mode 100644 Detectors/FIT/FDD/simulation/src/digit2raw.cxx create mode 100644 Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyDecoderSpec.h create mode 100644 Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyEncoderSpec.h create mode 100644 Detectors/FIT/FDD/workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/FIT/FDD/workflow/src/EntropyEncoderSpec.cxx create mode 100644 Detectors/FIT/FDD/workflow/src/digits-reader-workflow.cxx create mode 100644 Detectors/FIT/FDD/workflow/src/entropy-encoder-workflow.cxx diff --git a/DataFormats/Detectors/FIT/FDD/CMakeLists.txt b/DataFormats/Detectors/FIT/FDD/CMakeLists.txt index f67ea3bdd2773..86c1eb28335e3 100644 --- a/DataFormats/Detectors/FIT/FDD/CMakeLists.txt +++ b/DataFormats/Detectors/FIT/FDD/CMakeLists.txt @@ -9,7 +9,10 @@ # submit itself to any jurisdiction. o2_add_library(DataFormatsFDD - PUBLIC_LINK_LIBRARIES O2::CommonDataFormat + SOURCES src/RawEventData.cxx + src/CTF.cxx + PUBLIC_LINK_LIBRARIES O2::FDDBase + O2::CommonDataFormat O2::SimulationDataFormat) o2_target_root_dictionary(DataFormatsFDD @@ -17,7 +20,10 @@ o2_target_root_dictionary(DataFormatsFDD include/DataFormatsFDD/ChannelData.h include/DataFormatsFDD/RecPoint.h include/DataFormatsFDD/MCLabel.h - include/DataFormatsFDD/Hit.h) + include/DataFormatsFDD/Hit.h + include/DataFormatsFDD/RawEventData.h + include/DataFormatsFDD/LookUpTable.h + include/DataFormatsFDD/CTF.h) diff --git a/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/CTF.h b/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/CTF.h new file mode 100644 index 0000000000000..a199319242fa0 --- /dev/null +++ b/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/CTF.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 CTF.h +/// \author ruben.shahoyan@cern.ch +/// \brief Definitions for FDD CTF data + +#ifndef O2_FDD_CTF_H +#define O2_FDD_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" + +namespace o2 +{ +namespace fdd +{ + +/// Header for a single CTF +struct CTFHeader { + uint32_t nTriggers = 0; /// number of triggers in TF + uint32_t firstOrbit = 0; /// 1st orbit of TF + uint16_t firstBC = 0; /// 1st BC of TF + + ClassDefNV(CTFHeader, 1); +}; + +/// Intermediate, compressed but not yet entropy-encoded digits +struct CompressedDigits { + + CTFHeader header; + + // BC data + std::vector<uint8_t> trigger; // trigger bits + std::vector<uint16_t> bcInc; // increment in BC if the same orbit, otherwise abs bc + std::vector<uint32_t> orbitInc; // increment in orbit + std::vector<uint8_t> nChan; // number of fired channels + + // channel data + std::vector<uint8_t> idChan; // channels ID: 1st on absolute, then increment + std::vector<int16_t> time; // time + std::vector<int16_t> charge; // Amplitude + std::vector<uint8_t> feeBits; // QTC chain + + CompressedDigits() = default; + + void clear(); + + ClassDefNV(CompressedDigits, 2); +}; + +/// wrapper for the Entropy-encoded clusters of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 8, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { + BLC_trigger, // trigger bits + BLC_bcInc, // increment in BC + BLC_orbitInc, // increment in orbit + BLC_nChan, // number of fired channels + + BLC_idChan, // channels ID: 1st on absolute, then increment + BLC_time, // time + BLC_charge, // amplitude + BLC_feeBits // bits + }; + + ClassDefNV(CTF, 2); +}; + +} // namespace fdd +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/LookUpTable.h b/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/LookUpTable.h new file mode 100644 index 0000000000000..6b5e6707e0e53 --- /dev/null +++ b/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/LookUpTable.h @@ -0,0 +1,115 @@ +// 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 RawEventData.h class for RAW data format +// Alla.Maevskaya +// simple look-up table just to feed digits 2 raw procedure. +//Will be really set after module/electronics connections +// +#ifndef ALICEO2_FDD_LOOKUPTABLE_H_ +#define ALICEO2_FDD_LOOKUPTABLE_H_ +//////////////////////////////////////////////// +// Look Up Table FDD +////////////////////////////////////////////// + +#include <Rtypes.h> +#include <cassert> +#include <iostream> +#include <iomanip> // std::setfill, std::setw - for stream formating +#include <Framework/Logger.h> +#include "FDDBase/Constants.h" + +namespace o2 +{ +namespace fdd +{ + +struct Topo { + int modLink = 0; // Number of Processing Module, associated with GBT link ID + int modCh = 0; // Channel within the Processing Module in range from 0-11 + ClassDefNV(Topo, 1); +}; + +inline bool operator<(Topo const& a, Topo const& b) +{ + return (a.modLink < b.modLink || (a.modLink == b.modLink && a.modCh < b.modCh)); +} + +class LookUpTable +{ + public: + /// + /// Default constructor. + /// It must be kept public for root persistency purposes, + /// but should never be called by the outside world + LookUpTable() = default; + ~LookUpTable() = default; + + explicit LookUpTable(bool fillLinearly) + : mTopoVector(Nmodules * NChPerMod, {0, 0}), + mInvTopo(mTopoVector.size(), 0) + { + if (fillLinearly) { + LOG(INFO) << "Mapping of global channel and (PM, PM channel) pair"; + for (int link = 0; link < Nmodules; ++link) { + for (int ch = 0; ch < NChPerMod; ++ch) { + mTopoVector[link * NChPerMod + ch] = o2::fdd::Topo{link, ch}; + } + } + } else { + // TODO: If needed: implement more realistic splitting: 1 ring -> 1 PM instead of linear + LOG(WARNING) << "Don't use it - not implemented yet."; + } + + // Fill inverted LUT - matters only if LUT is not linear + for (size_t channel = 0; channel < mTopoVector.size(); ++channel) { + mInvTopo[getIdx(mTopoVector[channel].modLink, mTopoVector[channel].modCh)] = channel; + } + } + + int getChannel(int link, int mcp) const { return mInvTopo[getIdx(link, mcp)]; } + int getLink(int channel) const { return mTopoVector[channel].modLink; } + int getModChannel(int channel) const { return mTopoVector[channel].modCh; } + int getTcmLink() const { return Nmodules; } + void printFullMap() const + { + std::cout << "o2::fdd::LookUpTable::printFullMap(): mTopoVector: [globalCh link modCh]" << std::endl; + for (size_t channel = 0; channel < mTopoVector.size(); ++channel) { + std::cout << " " << std::right << std::setw(2) << channel << " "; + std::cout << std::right << std::setw(2) << mTopoVector[channel].modLink << " "; + std::cout << std::right << std::setw(3) << mTopoVector[channel].modCh << std::endl; + } + std::cout << "o2::fdd::LookUpTable::printFullMap(): mInvTopo: [idx globalCh link modCh]" << std::endl; + for (size_t idx = 0; idx < mInvTopo.size(); ++idx) { + std::cout << " " << std::right << std::setw(3) << idx << " "; + std::cout << std::right << std::setw(3) << mInvTopo[idx] << " "; + std::cout << std::right << std::setw(2) << getLinkFromIdx(mInvTopo[idx]) << " "; + std::cout << std::right << std::setw(2) << getModChannelFromIdx(mInvTopo[idx]) << std::endl; + } + } + + private: + std::vector<Topo> mTopoVector; // iterator of each vector element gives the global channel number + std::vector<int> mInvTopo; // each element is an iterator of mTopoVector + + static int getIdx(int link, int modCh) + { + assert(modCh < NChPerMod); + return link * NChPerMod + modCh; + } + static int getLinkFromIdx(int idx) { return idx / NChPerMod; } + static int getModChannelFromIdx(int idx) { return idx % NChPerMod; } + + ClassDefNV(LookUpTable, 1); +}; + +} // namespace fdd +} // namespace o2 +#endif diff --git a/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/RawEventData.h b/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/RawEventData.h new file mode 100644 index 0000000000000..3f8220e4a8f06 --- /dev/null +++ b/DataFormats/Detectors/FIT/FDD/include/DataFormatsFDD/RawEventData.h @@ -0,0 +1,187 @@ +// 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. +// +// Based on the FT0 file RawEventData.h (almost identical except additional printing) by +// Alla.Maevskaya@cern.ch +// with Artur.Furs +// +#ifndef ALICEO2_FDD_RAWEVENTDATA_H_ +#define ALICEO2_FDD_RAWEVENTDATA_H_ + +#include "FDDBase/Constants.h" +#include "DataFormatsFDD/ChannelData.h" +#include "Headers/RAWDataHeader.h" +#include "DataFormatsFDD/LookUpTable.h" +#include <CommonDataFormat/InteractionRecord.h> +#include <Framework/Logger.h> +#include <iostream> +#include <iomanip> +#include <cstring> +#include "Rtypes.h" + +namespace o2 +{ +namespace fdd +{ +struct EventHeader { + static constexpr int PayloadSize = 16; + union { + uint64_t word[2] = {}; + struct { + uint64_t bc : 12; + uint64_t orbit : 32; + uint64_t reservedField1 : 20; + uint64_t reservedField2 : 8; + uint64_t nGBTWords : 4; + uint64_t startDescriptor : 4; + uint64_t reservedField3 : 48; + }; + }; +}; +struct EventData { + union { + uint64_t word = {0}; + struct { + int64_t time : 12; + int64_t charge : 13; + uint64_t numberADC : 1, + isDoubleEvent : 1, + is1TimeLostEvent : 1, + is2TimeLostEvent : 1, + isADCinGate : 1, + isTimeInfoLate : 1, + isAmpHigh : 1, + isEventInTVDC : 1, + isTimeInfoLost : 1, + reservedField : 2, + channelID : 4; + }; + }; + uint64_t word_zeros = 0x0; + static const size_t PayloadSizeSecondWord = 11; + static const size_t PayloadSizeFirstWord = 5; + void generateFlags() + { + numberADC = std::rand() % 2; + isDoubleEvent = 0; + is1TimeLostEvent = 0; + is2TimeLostEvent = 1; + isADCinGate = 0; + isTimeInfoLate = 0; + isAmpHigh = 0; + isEventInTVDC = 1; + isTimeInfoLost = 0; + } +}; + +struct TCMdata { + static constexpr int PayloadSize = 16; + union { + uint64_t word[2] = {0}; + struct { + uint64_t orC : 1, + orA : 1, + sCen : 1, + cen : 1, + vertex : 1, + nChanA : 7, + nChanC : 7; + int64_t amplA : 18, + amplC : 18, + reservedField1 : 1, //56B, PayloadSize1stWord 6 + timeA : 9, + timeC : 9, + reservedField2 : 46; + }; + }; +}; + +class RawEventData +{ + public: + RawEventData() = default; + EventHeader* getEventHeaderPtr() { return &mEventHeader; } + EventData* getEventDataPtr() { return mEventData; } + void print(); + void printHexEventHeader(); + void printHexEventData(uint64_t i); + enum EEventDataBit { kNumberADC, + kIsDoubleEvent, + kIs1TimeLostEvent, + kIs2TimeLostEvent, + kIsADCinGate, + kIsTimeInfoLate, + kIsAmpHigh, + kIsEventInTVDC, + kIsTimeInfoLost }; + const static int gStartDescriptor = 0x0000000f; + + int size() const + { + return 1 + mEventHeader.nGBTWords; // EventHeader + EventData size + } + + std::vector<char> to_vector(bool tcm) + { + constexpr int CRUWordSize = 16; + + std::vector<char> result(size() * CRUWordSize); + char* out = result.data(); + if (!tcm) { + std::memcpy(out, &mEventHeader, EventHeader::PayloadSize); + out += EventHeader::PayloadSize; + LOG(DEBUG) << " Write PM header: nWords: " << (int)mEventHeader.nGBTWords + << " orbit: " << int(mEventHeader.orbit) + << " BC: " << int(mEventHeader.bc) + << " size: " << result.size(); + printHexEventHeader(); + out += CRUWordSize - EventHeader::PayloadSize; // Padding enabled + + for (uint64_t i = 0; i < mEventHeader.nGBTWords; ++i) { + std::memcpy(out, &mEventData[2 * i], EventData::PayloadSizeFirstWord); + out += EventData::PayloadSizeFirstWord; + LOG(DEBUG) << " 1st word: Ch: " << std::setw(2) << mEventData[2 * i].channelID + << " charge: " << std::setw(4) << mEventData[2 * i].charge + << " time: " << std::setw(4) << mEventData[2 * i].time; + std::memcpy(out, &mEventData[2 * i + 1], EventData::PayloadSizeSecondWord); + out += EventData::PayloadSizeSecondWord; + LOG(DEBUG) << " 2nd word: Ch: " << std::setw(2) << mEventData[2 * i + 1].channelID + << " charge: " << std::setw(4) << mEventData[2 * i + 1].charge + << " time: " << std::setw(4) << mEventData[2 * i + 1].time; + + out += CRUWordSize - EventData::PayloadSizeSecondWord - EventData::PayloadSizeFirstWord; + printHexEventData(i); + } + } else { + // TCM data + std::memcpy(out, &mEventHeader, EventHeader::PayloadSize); + out += EventHeader::PayloadSize; + LOG(DEBUG) << " Write TCM header: nWords: " << (int)mEventHeader.nGBTWords + << " orbit: " << int(mEventHeader.orbit) + << " BC: " << int(mEventHeader.bc) + << " size: " << result.size(); + std::memcpy(out, &mTCMdata, sizeof(TCMdata)); + out += sizeof(TCMdata); + // TODO: No TCM payload printing until the meaning of trigger bits and other flags is clarified + } + return result; + } + + public: + EventHeader mEventHeader; + EventData mEventData[NChPerMod]; + TCMdata mTCMdata; + + ClassDefNV(RawEventData, 1); +}; + +} // namespace fdd +} // namespace o2 +#endif diff --git a/DataFormats/Detectors/FIT/FDD/src/CTF.cxx b/DataFormats/Detectors/FIT/FDD/src/CTF.cxx new file mode 100644 index 0000000000000..24724cce55852 --- /dev/null +++ b/DataFormats/Detectors/FIT/FDD/src/CTF.cxx @@ -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. + +#include <stdexcept> +#include <cstring> +#include "Framework/Logger.h" +#include "DataFormatsFDD/CTF.h" + +using namespace o2::fdd; + +///________________________________ +void CompressedDigits::clear() +{ + trigger.clear(); + bcInc.clear(); + orbitInc.clear(); + nChan.clear(); + + idChan.clear(); + time.clear(); + charge.clear(); + feeBits.clear(); + + header.nTriggers = 0; + header.firstOrbit = 0; + header.firstBC = 0; +} diff --git a/DataFormats/Detectors/FIT/FDD/src/DataFormatsFDDLinkDef.h b/DataFormats/Detectors/FIT/FDD/src/DataFormatsFDDLinkDef.h index 054c4a6a7eac2..6f4f3e9fe4554 100644 --- a/DataFormats/Detectors/FIT/FDD/src/DataFormatsFDDLinkDef.h +++ b/DataFormats/Detectors/FIT/FDD/src/DataFormatsFDDLinkDef.h @@ -30,4 +30,14 @@ #pragma link C++ class o2::fdd::RecPoint + ; #pragma link C++ class vector < o2::fdd::RecPoint> + ; +#pragma link C++ class o2::fdd::RawEventData + ; +#pragma link C++ class o2::fdd::EventHeader + ; +#pragma link C++ class o2::fdd::EventData + ; +#pragma link C++ class o2::fdd::TCMdata + ; +#pragma link C++ class o2::fdd::Topo + ; + +#pragma link C++ class o2::fdd::CTFHeader + ; +#pragma link C++ class o2::fdd::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::fdd::CTFHeader, 8, uint32_t> + ; + #endif diff --git a/DataFormats/Detectors/FIT/FDD/src/RawEventData.cxx b/DataFormats/Detectors/FIT/FDD/src/RawEventData.cxx new file mode 100644 index 0000000000000..64c5872e9a0e1 --- /dev/null +++ b/DataFormats/Detectors/FIT/FDD/src/RawEventData.cxx @@ -0,0 +1,71 @@ +// 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 "DataFormatsFDD/RawEventData.h" +#include <sstream> + +using namespace o2::fdd; + +ClassImp(RawEventData); + +void RawEventData::print() +{ + std::cout << "==================Raw event data==================" << std::endl; + std::cout << "##################Header##################" << std::endl; + std::cout << "startDescriptor: " << mEventHeader.startDescriptor << std::endl; + std::cout << "Nchannels: " << mEventHeader.nGBTWords * 2 << std::endl; + std::cout << "BC: " << mEventHeader.bc << std::endl; + std::cout << "Orbit: " << mEventHeader.orbit << std::endl; + std::cout << "##########################################" << std::endl; + std::cout << "###################DATA###################" << std::endl; + for (int iCh = 0; iCh < mEventHeader.nGBTWords * 2; iCh++) { + std::cout << "------------Channel " << mEventData[iCh].channelID << "------------" << std::endl; + std::cout << "Charge: " << mEventData[iCh].charge << std::endl; + std::cout << "Time: " << mEventData[iCh].time << std::endl; + std::cout << "1TimeLostEvent: " << mEventData[iCh].is1TimeLostEvent << std::endl; + std::cout << "2TimeLostEvent: " << mEventData[iCh].is2TimeLostEvent << std::endl; + std::cout << "ADCinGate: " << mEventData[iCh].isADCinGate << std::endl; + std::cout << "AmpHigh: " << mEventData[iCh].isAmpHigh << std::endl; + std::cout << "DoubleEvent: " << mEventData[iCh].isDoubleEvent << std::endl; + std::cout << "EventInTVDC: " << mEventData[iCh].isEventInTVDC << std::endl; + std::cout << "TimeInfoLate: " << mEventData[iCh].isTimeInfoLate << std::endl; + std::cout << "TimeInfoLost: " << mEventData[iCh].isTimeInfoLost << std::endl; + std::cout << "numberADC: " << mEventData[iCh].numberADC << std::endl; + } + std::cout << "##########################################" << std::endl; +} + +void RawEventData::printHexEventHeader() +{ + std::stringstream ssheader; + ssheader << std::setfill('0') << std::setw(16) << std::hex << mEventHeader.word[0] << " " << std::setw(16) << mEventHeader.word[1] << "\n "; + ssheader << std::setw(3) << (0x00000fff & mEventHeader.bc) << " " + << std::setw(8) << (0xffffffff & mEventHeader.orbit) << " " + << std::setw(5) << (0x000fffff & mEventHeader.reservedField1) << " " + << std::setw(2) << (0x000000ff & mEventHeader.reservedField2) << " " + << std::setw(1) << (0x0000000f & mEventHeader.nGBTWords) << " " + << std::setw(1) << (0x0000000f & mEventHeader.startDescriptor) << " " + << std::setw(12) << (0xffffffffffff & mEventHeader.reservedField3); + LOG(DEBUG) << ssheader.str(); +} + +void RawEventData::printHexEventData(uint64_t i) +{ + std::stringstream ssdata; + ssdata << "D0:0x "; + ssdata << std::setfill('0') << std::hex << std::setw(16) << mEventData[2 * i].word << "\n "; + ssdata << std::setw(3) << (0x0fff & mEventData[2 * i].time) << " " + << std::setw(8) << (0x1fff & mEventData[2 * i].charge) << "\n "; + ssdata << "D1:0x "; + ssdata << std::setfill('0') << std::hex << std::setw(16) << mEventData[2 * i + 1].word << "\n "; + ssdata << std::setw(3) << (0x0fff & mEventData[2 * i + 1].time) << " " + << std::setw(8) << (0x1fff & mEventData[2 * i + 1].charge); + LOG(DEBUG) << " | " << ssdata.str(); +} diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index bd94549fcc201..0fd407b3f2099 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -40,6 +40,14 @@ o2_add_test(fv0 SOURCES test/test_ctf_io_fv0.cxx COMPONENT_NAME ctf LABELS ctf) + +o2_add_test(fdd + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::FDDReconstruction + O2::DataFormatsFDD + SOURCES test/test_ctf_io_fdd.cxx + COMPONENT_NAME ctf + LABELS ctf) o2_add_test(tof PUBLIC_LINK_LIBRARIES O2::CTFWorkflow diff --git a/Detectors/CTF/test/test_ctf_io_fdd.cxx b/Detectors/CTF/test/test_ctf_io_fdd.cxx new file mode 100644 index 0000000000000..96b8543e59e6b --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_fdd.cxx @@ -0,0 +1,146 @@ +// 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. + +#define BOOST_TEST_MODULE Test FDDCTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DetectorsCommonDataFormats/NameConf.h" +#include "FDDReconstruction/CTFCoder.h" +#include "FDDBase/Constants.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <cstring> + +using namespace o2::fdd; + +BOOST_AUTO_TEST_CASE(CTFTest) +{ + std::vector<Digit> digits; + std::vector<ChannelData> channels; + + TStopwatch sw; + sw.Start(); + o2::InteractionRecord ir(0, 0); + + for (int idig = 0; idig < 1000; idig++) { + ir += 1 + gRandom->Integer(200); + uint8_t ich = gRandom->Poisson(4); + auto start = channels.size(); + int32_t tMeanA = 0, tMeanC = 0; + int32_t ampTotA = 0, ampTotC = 0; + Triggers trig; + trig.triggersignals = gRandom->Integer(128); + while (ich < Nchannels) { + int16_t t = -2048 + gRandom->Integer(2048 * 2); + uint16_t q = gRandom->Integer(4096); + uint16_t feb = gRandom->Rndm() > 0.5 ? 0 : 1; + channels.emplace_back(ich, t, q, feb); + + if (ich > 7) { + trig.nChanA++; + ampTotA += q; + tMeanA += t; + } else { + trig.nChanC++; + ampTotC += q; + tMeanC += t; + } + ich += 1 + gRandom->Poisson(4); + } + if (trig.nChanA) { + trig.timeA = tMeanA / trig.nChanA; + trig.amplA = ampTotA * 0.125; + } + if (trig.nChanC) { + trig.timeC = tMeanC / trig.nChanC; + trig.amplC = ampTotC * 0.125; // sum/8 + } + + auto end = channels.size(); + digits.emplace_back(start, end - start, ir, trig); + } + + LOG(INFO) << "Generated " << channels.size() << " channels in " << digits.size() << " digits " << sw.CpuTime() << " s"; + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + { + CTFCoder coder; + coder.encode(vec, digits, channels); // compress + } + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + TFile flOut("test_ctf_fdd.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + auto* ctfImage = o2::fdd::CTF::get(vec.data()); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "FDD"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + { + sw.Start(); + TFile flIn("test_ctf_fdd.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + o2::fdd::CTF::readFromTree(vec, *(tree.get()), "FDD"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<Digit> digitsD; + std::vector<ChannelData> channelsD; + + sw.Start(); + const auto ctfImage = o2::fdd::CTF::getImage(vec.data()); + { + CTFCoder coder; + coder.decode(ctfImage, digitsD, channelsD); // decompress + } + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + BOOST_CHECK(digitsD.size() == digits.size()); + BOOST_CHECK(channelsD.size() == channels.size()); + LOG(INFO) << " BOOST_CHECK digitsD.size() " << digitsD.size() << " digits.size() " << digits.size() << " BOOST_CHECK(channelsD.size() " << channelsD.size() << " channels.size()) " << channels.size(); + + for (int i = digits.size(); i--;) { + const auto& dor = digits[i]; + const auto& ddc = digitsD[i]; + BOOST_CHECK(dor.mIntRecord == ddc.mIntRecord); + BOOST_CHECK(dor.ref == ddc.ref); + BOOST_CHECK(dor.mTriggers.nChanA == ddc.mTriggers.nChanA); + BOOST_CHECK(dor.mTriggers.nChanC == ddc.mTriggers.nChanC); + BOOST_CHECK(dor.mTriggers.amplA == ddc.mTriggers.amplA); + BOOST_CHECK(dor.mTriggers.amplC == ddc.mTriggers.amplC); + BOOST_CHECK(dor.mTriggers.timeA == ddc.mTriggers.timeA); + BOOST_CHECK(dor.mTriggers.timeC == ddc.mTriggers.timeC); + BOOST_CHECK(dor.mTriggers.triggersignals == ddc.mTriggers.triggersignals); + } + for (int i = channels.size(); i--;) { + const auto& cor = channels[i]; + const auto& cdc = channelsD[i]; + BOOST_CHECK(cor.mPMNumber == cdc.mPMNumber); + BOOST_CHECK(cor.mTime == cdc.mTime); + BOOST_CHECK(cor.mChargeADC == cdc.mChargeADC); + BOOST_CHECK(cor.mFEEBits == cdc.mFEEBits); + } +} diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index 746e8c12ee2b9..166900fc24e3b 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -18,12 +18,14 @@ o2_add_library(CTFWorkflow O2::DataFormatsTOF O2::DataFormatsFT0 O2::DataFormatsFV0 + O2::DataFormatsFDD O2::DataFormatsMID O2::DataFormatsParameters O2::ITSMFTWorkflow O2::TPCWorkflow O2::FT0Workflow O2::FV0Workflow + O2::FDDWorkflow O2::TOFWorkflow O2::MIDWorkflow O2::EMCALWorkflow diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 2b5edde54d7c7..75f20df01c4db 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -27,6 +27,7 @@ #include "DataFormatsTPC/CTF.h" #include "DataFormatsFT0/CTF.h" #include "DataFormatsFV0/CTF.h" +#include "DataFormatsFDD/CTF.h" #include "DataFormatsTOF/CTF.h" #include "DataFormatsMID/CTF.h" #include "DataFormatsEMCAL/CTF.h" @@ -144,6 +145,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::FDD; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::fdd::CTF)); + o2::fdd::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + det = DetID::TOF; if (detsTF[det]) { auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::tof::CTF)); diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 7b135edc2cfbd..66ae942fa2601 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -24,6 +24,7 @@ #include "DataFormatsTPC/CTF.h" #include "DataFormatsFT0/CTF.h" #include "DataFormatsFV0/CTF.h" +#include "DataFormatsFDD/CTF.h" #include "DataFormatsTOF/CTF.h" #include "DataFormatsMID/CTF.h" #include "DataFormatsEMCAL/CTF.h" @@ -100,6 +101,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) processDet<o2::tof::CTF>(pc, DetID::TOF, header, treeOut.get()); processDet<o2::ft0::CTF>(pc, DetID::FT0, header, treeOut.get()); processDet<o2::fv0::CTF>(pc, DetID::FV0, header, treeOut.get()); + processDet<o2::fdd::CTF>(pc, DetID::FDD, header, treeOut.get()); processDet<o2::mid::CTF>(pc, DetID::MID, header, treeOut.get()); processDet<o2::emcal::CTF>(pc, DetID::EMC, header, treeOut.get()); @@ -169,6 +171,7 @@ void CTFWriterSpec::storeDictionaries() storeDictionary<o2::tof::CTF>(DetID::TOF, header); storeDictionary<o2::ft0::CTF>(DetID::FT0, header); storeDictionary<o2::fv0::CTF>(DetID::FV0, header); + storeDictionary<o2::fdd::CTF>(DetID::FDD, header); storeDictionary<o2::mid::CTF>(DetID::MID, header); storeDictionary<o2::emcal::CTF>(DetID::EMC, header); // close remnants diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index be564efa94034..38d0f730dd141 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -24,6 +24,7 @@ #include "TPCWorkflow/EntropyDecoderSpec.h" #include "FT0Workflow/EntropyDecoderSpec.h" #include "FV0Workflow/EntropyDecoderSpec.h" +#include "FDDWorkflow/EntropyDecoderSpec.h" #include "TOFWorkflowUtils/EntropyDecoderSpec.h" #include "MIDWorkflow/EntropyDecoderSpec.h" #include "EMCALWorkflow/EntropyDecoderSpec.h" @@ -86,6 +87,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets[DetID::FV0]) { specs.push_back(o2::fv0::getEntropyDecoderSpec()); } + if (dets[DetID::FDD]) { + specs.push_back(o2::fdd::getEntropyDecoderSpec()); + } if (dets[DetID::MID]) { specs.push_back(o2::mid::getEntropyDecoderSpec()); } diff --git a/Detectors/FIT/FDD/base/include/FDDBase/Constants.h b/Detectors/FIT/FDD/base/include/FDDBase/Constants.h index dbf0e9557f936..b5ff8e91fbea4 100644 --- a/Detectors/FIT/FDD/base/include/FDDBase/Constants.h +++ b/Detectors/FIT/FDD/base/include/FDDBase/Constants.h @@ -22,6 +22,8 @@ namespace o2 namespace fdd { constexpr short Nchannels = 16; +constexpr short Nmodules = 2; +constexpr short NChPerMod = 8; constexpr short Ntriggers = 5; constexpr float IntTimeRes = 0.4; constexpr float PhotoCathodeEfficiency = 0.18; diff --git a/Detectors/FIT/FDD/base/src/Geometry.cxx b/Detectors/FIT/FDD/base/src/Geometry.cxx index 32babeae94a83..370dd1c226afb 100644 --- a/Detectors/FIT/FDD/base/src/Geometry.cxx +++ b/Detectors/FIT/FDD/base/src/Geometry.cxx @@ -121,7 +121,6 @@ void Geometry::buildGeometry() vFDAarray->AddNode(secFDA, 3, Rz180); // ---------------> x vFDAarray->AddNode(secFDA, 4, Rx180); // 3 | 4 - /// FDD_C in the tunnel new TGeoBBox("shFDCbox", kFDCCellSideX / 2.0, kFDCCellSideY / 2.0, kFDCCelldz / 2.0); diff --git a/Detectors/FIT/FDD/reconstruction/CMakeLists.txt b/Detectors/FIT/FDD/reconstruction/CMakeLists.txt index a613f20a930bd..fe2598fa38f4d 100644 --- a/Detectors/FIT/FDD/reconstruction/CMakeLists.txt +++ b/Detectors/FIT/FDD/reconstruction/CMakeLists.txt @@ -10,8 +10,14 @@ o2_add_library(FDDReconstruction SOURCES src/Reconstructor.cxx - PUBLIC_LINK_LIBRARIES O2::DataFormatsFDD) + src/ReadRaw.cxx + src/CTFCoder.cxx + PUBLIC_LINK_LIBRARIES O2::FDDBase + O2::DataFormatsFDD + O2::DetectorsRaw) o2_target_root_dictionary( FDDReconstruction - HEADERS include/FDDReconstruction/Reconstructor.h) + HEADERS include/FDDReconstruction/Reconstructor.h + include/FDDReconstruction/ReadRaw.h + include/FDDReconstruction/CTFCoder.h) diff --git a/Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/CTFCoder.h b/Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/CTFCoder.h new file mode 100644 index 0000000000000..9d621f75cbbd6 --- /dev/null +++ b/Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/CTFCoder.h @@ -0,0 +1,193 @@ +// 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 CTFCoder.h +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of FDD digits data + +#ifndef O2_FDD_CTFCODER_H +#define O2_FDD_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include "FDDBase/Geometry.h" +#include "DataFormatsFDD/CTF.h" +#include "DataFormatsFDD/Digit.h" +#include "DataFormatsFDD/ChannelData.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" +#include "rANS/rans.h" + +class TTree; + +namespace o2 +{ +namespace fdd +{ + +class CTFCoder : public o2::ctf::CTFCoderBase +{ + public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::FDD) {} + ~CTFCoder() = default; + + /// entropy-encode digits to buffer with CTF + template <typename VEC> + void encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); + + /// entropy decode clusters from buffer with CTF + template <typename VDIG, typename VCHAN> + void decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); + + private: + /// compres digits clusters to CompressedDigits + void compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec); + size_t estimateCompressedSize(const CompressedDigits& cc); + + /// decompress CompressedDigits to digits + template <typename VDIG, typename VCHAN> + void decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec); + + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<Digit>& digitVec, std::vector<ChannelData>& channelVec); + + ClassDefNV(CTFCoder, 1); +}; + +/// entropy-encode clusters to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, // BLC_trigger + MD::EENCODE, // BLC_bcInc + MD::EENCODE, // BLC_orbitInc + MD::EENCODE, // BLC_nChan + + MD::EENCODE, // BLC_idChan + MD::EENCODE, // BLC_time + MD::EENCODE, // BLC_charge + MD::EENCODE // BLC_feeBits + }; + CompressedDigits cd; + compress(cd, digitVec, channelVec); + + // book output size with some margin + auto szIni = estimateCompressedSize(cd); + buff.resize(szIni); + + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(cd.header); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODEFDD(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); + // clang-format off + ENCODEFDD(cd.trigger, CTF::BLC_trigger, 0); + ENCODEFDD(cd.bcInc, CTF::BLC_bcInc, 0); + ENCODEFDD(cd.orbitInc, CTF::BLC_orbitInc, 0); + ENCODEFDD(cd.nChan, CTF::BLC_nChan, 0); + + ENCODEFDD(cd.idChan , CTF::BLC_idChan, 0); + ENCODEFDD(cd.time, CTF::BLC_time, 0); + ENCODEFDD(cd.charge, CTF::BLC_charge, 0); + ENCODEFDD(cd.feeBits, CTF::BLC_feeBits, 0); + // clang-format on + CTF::get(buff.data())->print(getPrefix()); +} + +/// decode entropy-encoded clusters to standard compact clusters +template <typename VDIG, typename VCHAN> +void CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec) +{ + CompressedDigits cd; + cd.header = ec.getHeader(); + ec.print(getPrefix()); +#define DECODEFDD(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) + // clang-format off + DECODEFDD(cd.trigger, CTF::BLC_trigger); + DECODEFDD(cd.bcInc, CTF::BLC_bcInc); + DECODEFDD(cd.orbitInc, CTF::BLC_orbitInc); + DECODEFDD(cd.nChan, CTF::BLC_nChan); + + DECODEFDD(cd.idChan, CTF::BLC_idChan); + DECODEFDD(cd.time, CTF::BLC_time); + DECODEFDD(cd.charge, CTF::BLC_charge); + DECODEFDD(cd.feeBits, CTF::BLC_feeBits); + // clang-format on + // + decompress(cd, digitVec, channelVec); +} + +/// decompress compressed digits to standard digits +template <typename VDIG, typename VCHAN> +void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec) +{ + digitVec.clear(); + channelVec.clear(); + digitVec.reserve(cd.header.nTriggers); + channelVec.reserve(cd.idChan.size()); + + uint32_t firstEntry = 0, clCount = 0, chipCount = 0; + o2::InteractionRecord ir(cd.header.firstBC, cd.header.firstOrbit); + + for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) { + // restore ROFRecord + if (cd.orbitInc[idig]) { // non-0 increment => new orbit + ir.bc = cd.bcInc[idig]; // bcInc has absolute meaning + ir.orbit += cd.orbitInc[idig]; + } else { + ir.bc += cd.bcInc[idig]; + } + Triggers trig; + trig.triggersignals = cd.trigger[idig]; + + firstEntry = channelVec.size(); + uint8_t chID = 0; + int amplA = 0, amplC = 0, timeA = 0, timeC = 0; + for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { + auto icc = channelVec.size(); + const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.time[icc], cd.charge[icc], cd.feeBits[icc]); + // + // rebuild digit + if (chan.mPMNumber > 7) { // A side + amplA += chan.mChargeADC; + timeA += chan.mTime; + trig.nChanA++; + + } else { + amplC += chan.mChargeADC; + timeC += chan.mTime; + trig.nChanC++; + } + } + if (trig.nChanA) { + trig.timeA = timeA / trig.nChanA; + trig.amplA = amplA * 0.125; + } + if (trig.nChanC) { + trig.timeC = timeC / trig.nChanC; + trig.amplC = amplC * 0.125; + } + digitVec.emplace_back(firstEntry, cd.nChan[idig], ir, trig); + } +} + +} // namespace fdd +} // namespace o2 + +#endif // O2_FDD_CTFCODER_H diff --git a/Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/ReadRaw.h b/Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/ReadRaw.h new file mode 100644 index 0000000000000..e5547217f285e --- /dev/null +++ b/Detectors/FIT/FDD/reconstruction/include/FDDReconstruction/ReadRaw.h @@ -0,0 +1,67 @@ +// 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 ReadRaw.h +/// \brief Reads raw data and converts to digits +/// \author Maciej.Slupecki@cern.ch, arvind.khuntia@cern.ch, based on the FT0 code +// RAW data format description: DataFormat/Detectors/FIT/FDD/RawEventData + +#ifndef ALICEO2_FDD_READRAW_H_ +#define ALICEO2_FDD_READRAW_H_ + +#include <fstream> +#include <iostream> +#include <iomanip> +#include <map> +#include <string> +#include <sstream> +#include <vector> +#include "TBranch.h" +#include "TTree.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsFDD/Digit.h" +#include "DataFormatsFDD/ChannelData.h" +#include "DataFormatsFDD/LookUpTable.h" +#include "DataFormatsFDD/RawEventData.h" + +namespace o2 +{ +namespace fdd +{ +class ReadRaw +{ + public: + ReadRaw() = default; + ReadRaw(bool doConversionToDigits, const std::string inputRawFilePath = "fdd.raw", const std::string outputRawFilePath = "fdddigitsFromRaw.root"); + void readRawData(const LookUpTable& lut); + void writeDigits(const std::string& outputDigitsFilePath); + void close(); + + private: + std::ifstream mRawFileIn; + std::map<o2::InteractionRecord, std::vector<ChannelData>> mDigitAccum; // digit accumulator + + template <typename T> + TBranch* getOrMakeBranch(TTree& tree, std::string brname, T* ptr) + { + if (auto br = tree.GetBranch(brname.c_str())) { + br->SetAddress(static_cast<void*>(ptr)); + return br; + } + // otherwise make it + return tree.Branch(brname.c_str(), ptr); + } + + ClassDefNV(ReadRaw, 1); +}; + +} // namespace fdd +} // namespace o2 +#endif diff --git a/Detectors/FIT/FDD/reconstruction/src/CTFCoder.cxx b/Detectors/FIT/FDD/reconstruction/src/CTFCoder.cxx new file mode 100644 index 0000000000000..82050cd60993a --- /dev/null +++ b/Detectors/FIT/FDD/reconstruction/src/CTFCoder.cxx @@ -0,0 +1,160 @@ +// 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 CTFCoder.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of FDD digits data + +#include "FDDReconstruction/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::fdd; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) +{ + ec.appendToTree(tree, mDet.getName()); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, + std::vector<Digit>& digitVec, std::vector<ChannelData>& channelVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, mDet.getName(), entry); + decode(ec, digitVec, channelVec); +} + +///________________________________ +void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec) +{ + // convert digits/channel to their compressed version + cd.clear(); + if (!digitVec.size()) { + return; + } + const auto& dig0 = digitVec[0]; + cd.header.nTriggers = digitVec.size(); + cd.header.firstOrbit = dig0.mIntRecord.orbit; + cd.header.firstBC = dig0.mIntRecord.bc; + + cd.trigger.resize(cd.header.nTriggers); + cd.bcInc.resize(cd.header.nTriggers); + cd.orbitInc.resize(cd.header.nTriggers); + cd.nChan.resize(cd.header.nTriggers); + + cd.idChan.resize(channelVec.size()); + cd.time.resize(channelVec.size()); + cd.charge.resize(channelVec.size()); + cd.feeBits.resize(channelVec.size()); + + uint16_t prevBC = cd.header.firstBC; + uint32_t prevOrbit = cd.header.firstOrbit; + uint32_t ccount = 0; + for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) { + const auto& digit = digitVec[idig]; + const auto chanels = digit.getBunchChannelData(channelVec); // we assume the channels are sorted + + // fill trigger info + cd.trigger[idig] = digit.mTriggers.triggersignals; + if (prevOrbit == digit.mIntRecord.orbit) { + cd.bcInc[idig] = digit.mIntRecord.bc - prevBC; + cd.orbitInc[idig] = 0; + } else { + cd.bcInc[idig] = digit.mIntRecord.bc; + cd.orbitInc[idig] = digit.mIntRecord.orbit - prevOrbit; + } + prevBC = digit.mIntRecord.bc; + prevOrbit = digit.mIntRecord.orbit; + // fill channels info + cd.nChan[idig] = chanels.size(); + if (!cd.nChan[idig]) { + LOG(ERROR) << "Digits with no channels"; + continue; + } + uint8_t prevChan = 0; + for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) { + assert(prevChan <= chanels[ic].mPMNumber); + cd.idChan[ccount] = chanels[ic].mPMNumber - prevChan; + cd.time[ccount] = chanels[ic].mTime; // make sure it fits to short!!! + cd.charge[ccount] = chanels[ic].mChargeADC; // make sure we really need short!!! + cd.feeBits[ccount] = chanels[ic].mFEEBits; + prevChan = chanels[ic].mPMNumber; + ccount++; + } + } +} + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + CompressedDigits cd; // just to get member types +#define MAKECODER(part, slot) createCoder<decltype(part)::value_type>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(cd.trigger, CTF::BLC_trigger); + MAKECODER(cd.bcInc, CTF::BLC_bcInc); + MAKECODER(cd.orbitInc, CTF::BLC_orbitInc); + MAKECODER(cd.nChan, CTF::BLC_nChan); + + MAKECODER(cd.idChan, CTF::BLC_idChan); + MAKECODER(cd.time, CTF::BLC_time); + MAKECODER(cd.charge, CTF::BLC_charge); + MAKECODER(cd.feeBits, CTF::BLC_feeBits); + // clang-format on +} + +///________________________________ +size_t CTFCoder::estimateCompressedSize(const CompressedDigits& cd) +{ + size_t sz = 0; + // clang-format off + // RS FIXME this is very crude estimate, instead, an empirical values should be used +#define VTP(vec) typename std::remove_reference<decltype(vec)>::type::value_type +#define ESTSIZE(vec, slot) mCoders[int(slot)] ? \ + rans::calculateMaxBufferSize(vec.size(), reinterpret_cast<const o2::rans::LiteralEncoder64<VTP(vec)>*>(mCoders[int(slot)].get())->getAlphabetRangeBits(), sizeof(VTP(vec)) ) : vec.size()*sizeof(VTP(vec)) + sz += ESTSIZE(cd.trigger, CTF::BLC_trigger); + sz += ESTSIZE(cd.bcInc, CTF::BLC_bcInc); + sz += ESTSIZE(cd.orbitInc, CTF::BLC_orbitInc); + sz += ESTSIZE(cd.nChan, CTF::BLC_nChan); + + sz += ESTSIZE(cd.idChan, CTF::BLC_idChan); + sz += ESTSIZE(cd.time, CTF::BLC_time); + sz += ESTSIZE(cd.charge, CTF::BLC_charge); + sz += ESTSIZE(cd.feeBits, CTF::BLC_feeBits); + // clang-format on + + LOG(INFO) << "Estimated output size is " << sz << " bytes"; + return sz; +} diff --git a/Detectors/FIT/FDD/reconstruction/src/FDDReconstructionLinkDef.h b/Detectors/FIT/FDD/reconstruction/src/FDDReconstructionLinkDef.h index 864a7a08ccd4c..741a85871df65 100644 --- a/Detectors/FIT/FDD/reconstruction/src/FDDReconstructionLinkDef.h +++ b/Detectors/FIT/FDD/reconstruction/src/FDDReconstructionLinkDef.h @@ -15,5 +15,6 @@ #pragma link off all functions; #pragma link C++ class o2::fdd::Reconstructor + ; +#pragma link C++ class o2::fdd::ReadRaw + ; #endif diff --git a/Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx b/Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx new file mode 100644 index 0000000000000..a7c90eb03713c --- /dev/null +++ b/Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx @@ -0,0 +1,168 @@ +// 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 "FDDReconstruction/ReadRaw.h" +#include "DetectorsRaw/RDHUtils.h" +#include "Framework/Logger.h" +#include "TFile.h" + +using namespace o2::fdd; +using RDHUtils = o2::raw::RDHUtils; + +ClassImp(ReadRaw); + +//_____________________________________________________________________________________ +ReadRaw::ReadRaw(bool doConversionToDigits, const std::string inputRawFilePath, const std::string outputDigitsFilePath) +{ + LOG(INFO) << "o2::fdd::ReadRaw::ReadRaw(): Read Raw file: " << inputRawFilePath.data() << " and convert to: " << outputDigitsFilePath.data(); + mRawFileIn.exceptions(std::ios_base::failbit | std::ios_base::badbit); + mRawFileIn.open(inputRawFilePath, std::fstream::in | std::fstream::binary); + LookUpTable lut(true); + ReadRaw::readRawData(lut); + ReadRaw::writeDigits(outputDigitsFilePath.data()); +} +//_____________________________________________________________________________________ +void ReadRaw::readRawData(const LookUpTable& lut) +{ + LOG(INFO) << "o2::fdd::ReadRaw::readRawData():Start."; + constexpr int CRUWordSize = 16; + o2::header::RAWDataHeader mRDH; + ChannelData chData; // output to store digits + EventHeader eventHeader; // raw data container + TCMdata mTCMdata; // raw data container + EventData eventData[NChPerMod]; // raw data container + + // Get input RAW file size + mRawFileIn.seekg(0, mRawFileIn.end); + long rawFileSize = mRawFileIn.tellg(); + mRawFileIn.seekg(0); + + long posInFile = 0; + while (posInFile < rawFileSize - sizeof(mRDH)) { + // Read contents of the next RDH + mRawFileIn.seekg(posInFile); + mRawFileIn.read(reinterpret_cast<char*>(&mRDH), sizeof(mRDH)); + int nwords = RDHUtils::getMemorySize(mRDH); + int offset = RDHUtils::getOffsetToNext(mRDH); + int link = RDHUtils::getLinkID(mRDH); + posInFile += offset; // posInFile is now prepared for the next iteration of the main loop + + int posPayload = 0; + if (nwords > sizeof(mRDH)) { + // RDHUtils::printRDH(mRDH); + // Read the payload following the RDH (only if there is anything to read) + posPayload = int(sizeof(mRDH)); + + while (posPayload < nwords) { + mRawFileIn.read(reinterpret_cast<char*>(&eventHeader), sizeof(eventHeader)); + posPayload += sizeof(eventHeader); + LOG(DEBUG) << " Read internal EventHeader for link: " << link + << " nWords: " << (int)eventHeader.nGBTWords + << " orbit: " << int(eventHeader.orbit) + << " BC: " << int(eventHeader.bc) + << " posInFile: " << posInFile + << " posPayload: " << posPayload; + o2::InteractionRecord intrec{uint16_t(eventHeader.bc), uint32_t(eventHeader.orbit)}; + + if (link == lut.getTcmLink()) { // is TCM payload + mRawFileIn.read(reinterpret_cast<char*>(&mTCMdata), sizeof(mTCMdata)); + posPayload += sizeof(mTCMdata); + LOG(DEBUG) << " Read TCM: posPayload: " << posPayload + << " posInFile: " << posInFile; + } else { // is PM payload + posPayload += CRUWordSize - o2::fdd::EventHeader::PayloadSize; // padding is enabled + for (int i = 0; i < eventHeader.nGBTWords; ++i) { + mRawFileIn.read(reinterpret_cast<char*>(&eventData[2 * i]), o2::fdd::EventData::PayloadSizeFirstWord); + posPayload += o2::fdd::EventData::PayloadSizeFirstWord; + chData = {Short_t(lut.getChannel(link, int(eventData[2 * i].channelID))), + Float_t(eventData[2 * i].time), + Short_t(eventData[2 * i].charge), 0}; + mDigitAccum[intrec].emplace_back(chData); + LOG(DEBUG) << " Read 1st half-word: (PMchannel, globalChannel, Q, T, posPayload) = " + << std::setw(3) << int(eventData[2 * i].channelID) + << std::setw(4) << lut.getChannel(link, int(eventData[2 * i].channelID)) + << std::setw(5) << int(eventData[2 * i].charge) + << std::setw(5) << float(eventData[2 * i].time) + << std::setw(5) << posPayload; + + Short_t channelIdFirstHalfWord = chData.mPMNumber; + + mRawFileIn.read(reinterpret_cast<char*>(&eventData[2 * i + 1]), EventData::PayloadSizeSecondWord); + posPayload += o2::fdd::EventData::PayloadSizeSecondWord; + chData = {Short_t(lut.getChannel(link, (eventData[2 * i + 1].channelID))), + Float_t(eventData[2 * i + 1].time), + Short_t(eventData[2 * i + 1].charge), 0}; + if (chData.mPMNumber <= channelIdFirstHalfWord) { + // Don't save the second half-word if it is only filled with zeroes (empty-data) + // TODO: Verify if it works correctly with real data from readout + continue; + } + mDigitAccum[intrec].emplace_back(chData); + LOG(DEBUG) << " Read 2nd half-word: (PMchannel, globalChannel, Q, T, posPayload) = " + << std::setw(3) << int(eventData[2 * i + 1].channelID) + << std::setw(4) << lut.getChannel(link, int(eventData[2 * i + 1].channelID)) + << std::setw(5) << int(eventData[2 * i + 1].charge) + << std::setw(5) << float(eventData[2 * i + 1].time) + << std::setw(5) << posPayload; + } + } + } + } + } + close(); + LOG(INFO) << "o2::fdd::ReadRaw::readRawData():Finished."; +} +//_____________________________________________________________________________________ +void ReadRaw::close() +{ + if (mRawFileIn.is_open()) + mRawFileIn.close(); +} +//_____________________________________________________________________________________ +void ReadRaw::writeDigits(const std::string& outputDigitsFilePath) +{ + TFile* outFile = new TFile(outputDigitsFilePath.data(), "RECREATE"); + if (!outFile || outFile->IsZombie()) { + LOG(ERROR) << "Failed to open " << outputDigitsFilePath << " output file"; + } else { + LOG(INFO) << "o2::fdd::ReadRaw::writeDigits(): Opened output file: " << outputDigitsFilePath; + } + TTree* outTree = new TTree("o2sim", "o2sim"); + std::vector<ChannelData> chDataVecTree; + std::vector<Digit> chBcVecTree; + + for (auto& digit : mDigitAccum) { + LOG(DEBUG) << " IR (" << digit.first << ") (i, PMT, Q, T):"; + for (uint16_t i = 0; i < digit.second.size(); i++) { + ChannelData* chd = &(digit.second.at(i)); + LOG(DEBUG) << " " << std::setw(3) << i + << std::setw(4) << chd->mPMNumber + << std::setw(5) << chd->mChargeADC + << std::setw(5) << chd->mTime; + } + + size_t nStored = 0; + size_t first = chDataVecTree.size(); + for (auto& sec : digit.second) { + chDataVecTree.emplace_back(int(sec.mPMNumber), float(sec.mTime), short(sec.mChargeADC), short(0)); + nStored++; + } + chBcVecTree.emplace_back(first, nStored, digit.first, Triggers()); + } + + outTree->Branch("FDDDigit", &chBcVecTree); + outTree->Branch("FDDDigitCh", &chDataVecTree); + outTree->Fill(); + + outFile->cd(); + outTree->Write(); + outFile->Close(); + LOG(INFO) << "o2::fdd::ReadRaw::writeDigits(): Finished converting " << chBcVecTree.size() << " events."; +} diff --git a/Detectors/FIT/FDD/simulation/CMakeLists.txt b/Detectors/FIT/FDD/simulation/CMakeLists.txt index 85bd2f2e602de..e828d6481c0b2 100644 --- a/Detectors/FIT/FDD/simulation/CMakeLists.txt +++ b/Detectors/FIT/FDD/simulation/CMakeLists.txt @@ -11,10 +11,25 @@ o2_add_library(FDDSimulation SOURCES src/Detector.cxx src/Digitizer.cxx - PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::FDDBase O2::DataFormatsFDD + src/Digits2Raw.cxx + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat + O2::FDDBase + O2::DataFormatsFDD + O2::DetectorsRaw ROOT::Physics) o2_target_root_dictionary(FDDSimulation HEADERS include/FDDSimulation/Detector.h include/FDDSimulation/Digitizer.h - include/FDDSimulation/DigitizationParameters.h) + include/FDDSimulation/DigitizationParameters.h + include/FDDSimulation/Digits2Raw.h) + +o2_add_executable(digit2raw + COMPONENT_NAME fdd + SOURCES src/digit2raw.cxx + PUBLIC_LINK_LIBRARIES O2::FDDSimulation + O2::DetectorsRaw + O2::DetectorsCommonDataFormats + O2::CommonUtils + Boost::program_options) + diff --git a/Detectors/FIT/FDD/simulation/include/FDDSimulation/Digits2Raw.h b/Detectors/FIT/FDD/simulation/include/FDDSimulation/Digits2Raw.h new file mode 100644 index 0000000000000..4df9fb96c70fd --- /dev/null +++ b/Detectors/FIT/FDD/simulation/include/FDDSimulation/Digits2Raw.h @@ -0,0 +1,68 @@ +// 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 Digits2Raw.h +/// \brief converts digits to raw format +/// \author Maciej.Slupecki@cern.ch +// based on FV0 + +#ifndef ALICEO2_FDD_DIGITS2RAW_H_ +#define ALICEO2_FDD_DIGITS2RAW_H_ + +#include "Headers/RAWDataHeader.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsFDD/RawEventData.h" +#include "DataFormatsFDD/LookUpTable.h" +#include "DataFormatsFDD/ChannelData.h" +#include "DataFormatsFDD/Digit.h" +#include "DetectorsRaw/HBFUtils.h" +#include "DetectorsRaw/RawFileWriter.h" +#include <FairLogger.h> +#include <TStopwatch.h> +#include <iostream> +#include <string> +#include <vector> +#include <gsl/span> + +namespace o2 +{ +namespace fdd +{ +class Digits2Raw +{ + public: + Digits2Raw() = default; + void readDigits(const std::string& outDir, const std::string& fileDigitsName); + void convertDigits(o2::fdd::Digit bcdigits, + gsl::span<const ChannelData> pmchannels, + const o2::fdd::LookUpTable& lut); + + o2::raw::RawFileWriter& getWriter() { return mWriter; } + void setFilePerLink(bool v) { mOutputPerLink = v; } + bool getFilePerLink() const { return mOutputPerLink; } + + private: + static constexpr uint32_t sTcmLink = 2; + static constexpr uint16_t sCruId = 0; + static constexpr uint32_t sEndPointId = sCruId; + + void makeGBTHeader(EventHeader& eventHeader, int link, o2::InteractionRecord const& mIntRecord); + void fillSecondHalfWordAndAddData(int iChannelPerLink, int prevPmLink, const o2::InteractionRecord& ir); + RawEventData mRawEventData; + o2::raw::RawFileWriter mWriter{"FDD"}; + bool mOutputPerLink = false; + ///////////////////////////////////////////////// + + ClassDefNV(Digits2Raw, 1); +}; + +} // namespace fdd +} // namespace o2 +#endif diff --git a/Detectors/FIT/FDD/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FDD/simulation/src/Digits2Raw.cxx new file mode 100644 index 0000000000000..94fa25500a227 --- /dev/null +++ b/Detectors/FIT/FDD/simulation/src/Digits2Raw.cxx @@ -0,0 +1,173 @@ +// 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. +// +// RAW data format - DataFormat/Detectors/FIT/FDD/RawEventData + +#include "FDDBase/Constants.h" +#include "FDDSimulation/Digits2Raw.h" +#include <TTree.h> +#include <cassert> + +using namespace o2::fdd; + +ClassImp(Digits2Raw); + +//_____________________________________________________________________________________ +void Digits2Raw::readDigits(const std::string& outDir, const std::string& fileDigitsName) +{ + LOG(INFO) << "==============FDD: Digits2Raw::convertDigits" << std::endl; + LookUpTable lut(true); + + std::string outd = outDir; + if (outd.back() != '/') { + outd += '/'; + } + + // Register PM links linearly + for (int iPmLink = 0; iPmLink < Nmodules; ++iPmLink) { + uint16_t feeId = uint16_t(iPmLink); + uint8_t linkId = uint8_t(iPmLink); + std::string outFileLink = mOutputPerLink ? (outd + "fdd_link" + std::to_string(iPmLink) + ".raw") : (outd + "fdd.raw"); + LOG(INFO) << " Register PM link: " << iPmLink << " to file: " << outFileLink; + mWriter.registerLink(feeId, sCruId, linkId, sEndPointId, outFileLink); + } + + // Register TCM link separately + std::string outFileLink = mOutputPerLink ? (outd + "fdd_link" + std::to_string(sTcmLink) + ".raw") : (outd + "fdd.raw"); + LOG(INFO) << " Register TCM link: " << outFileLink; + mWriter.registerLink(uint16_t(sTcmLink), sCruId, sTcmLink, sEndPointId, outFileLink); + + TFile* fdig = TFile::Open(fileDigitsName.data()); + assert(fdig != nullptr); + LOG(INFO) << "Open digits file: " << fileDigitsName.data(); + + TTree* digTree = (TTree*)fdig->Get("o2sim"); + std::vector<o2::fdd::Digit> digitsBC, *fddDigitPtr = &digitsBC; + std::vector<o2::fdd::ChannelData> digitsCh, *fddChDataPtr = &digitsCh; + digTree->SetBranchAddress("FDDDigit", &fddDigitPtr); + digTree->SetBranchAddress("FDDDigitCh", &fddChDataPtr); + + for (int ient = 0; ient < digTree->GetEntries(); ient++) { + digTree->GetEntry(ient); + int nbc = digitsBC.size(); + for (int ibc = 0; ibc < nbc; ibc++) { + auto& bcd = digitsBC[ibc]; + auto channels = bcd.getBunchChannelData(digitsCh); + + if (!channels.empty()) { + LOG(DEBUG); + LOG(INFO) << "o2::fdd::Digits2Raw::readDigits(): Start to convertDigits() at ibc = " << ibc << " " << bcd.mIntRecord + << " iCh0:" << bcd.ref.getFirstEntry() << " nentries:" << bcd.ref.getEntries(); + convertDigits(bcd, channels, lut); + } + } + } +} +//_____________________________________________________________________________________ +void Digits2Raw::convertDigits(o2::fdd::Digit bcdigits, gsl::span<const ChannelData> pmchannels, + const o2::fdd::LookUpTable& lut) +{ + const o2::InteractionRecord intRecord = bcdigits.getIntRecord(); + int prevPmLink = -1; + int iChannelPerLink = 0; + int nch = pmchannels.size(); + + std::stringstream ss; + ss << " Number of channels: " << nch << " (Ch, PMT, Q, T)\n"; + for (int ich = 0; ich < nch; ich++) { + if (pmchannels[ich].mChargeADC != 0) { + ss << " " << std::setw(2) << ich + << std::setw(3) << pmchannels[ich].mPMNumber + << std::setw(5) << pmchannels[ich].mChargeADC + << std::setw(7) << std::setprecision(3) << pmchannels[ich].mTime << "\n"; + } + } + LOG(DEBUG) << ss.str().substr(0, ss.str().size() - 1); + + for (int ich = 0; ich < nch; ich++) { + int nLinkPm = lut.getLink(pmchannels[ich].mPMNumber); + if (nLinkPm != prevPmLink) { + if (prevPmLink >= 0) { + fillSecondHalfWordAndAddData(iChannelPerLink, prevPmLink, intRecord); + } + makeGBTHeader(mRawEventData.mEventHeader, nLinkPm, intRecord); + iChannelPerLink = 0; + prevPmLink = nLinkPm; + } + if (pmchannels[ich].mChargeADC != 0) { + LOG(DEBUG) << " Store data for channel: " << ich << " PmLink = " << nLinkPm << " "; + auto& newData = mRawEventData.mEventData[iChannelPerLink]; + newData.charge = pmchannels[ich].mChargeADC; + newData.time = pmchannels[ich].mTime; + newData.generateFlags(); + newData.channelID = lut.getModChannel(pmchannels[ich].mPMNumber); + iChannelPerLink++; + } + if (ich == nch - 1) { + fillSecondHalfWordAndAddData(iChannelPerLink, prevPmLink, intRecord); + } + } + + // TCM + makeGBTHeader(mRawEventData.mEventHeader, sTcmLink, intRecord); + mRawEventData.mEventHeader.nGBTWords = 1; + auto& tcmdata = mRawEventData.mTCMdata; + tcmdata.vertex = 1; + tcmdata.orA = 1; + tcmdata.orC = 0; + tcmdata.sCen = 0; + tcmdata.cen = 0; + tcmdata.nChanA = 0; + tcmdata.nChanC = 0; + tcmdata.amplA = 0; + tcmdata.amplC = 0; + tcmdata.timeA = 0; + tcmdata.timeC = 0; + + auto data = mRawEventData.to_vector(kTRUE); //for tcm module + uint32_t linkId = uint32_t(sTcmLink); + uint64_t feeId = uint64_t(sTcmLink); + mWriter.addData(feeId, sCruId, linkId, sEndPointId, intRecord, data); + + // fill mEventData[iChannelPerLink] with 0s to flag that this is a dummy data + uint nGBTWords = uint((iChannelPerLink + 1) / 2); + if ((iChannelPerLink % 2) == 1) { + mRawEventData.mEventData[iChannelPerLink] = {}; + } + mRawEventData.mEventHeader.nGBTWords = nGBTWords; + // LOG(DEBUG) << " last link: " << prevPmLink; +} +//_____________________________________________________________________________________ +void Digits2Raw::makeGBTHeader(EventHeader& eventHeader, int link, o2::InteractionRecord const& mIntRecord) +{ + eventHeader.startDescriptor = 0xf; + eventHeader.reservedField1 = 0; + eventHeader.reservedField2 = 0; + eventHeader.reservedField3 = 0; + eventHeader.bc = mIntRecord.bc; + eventHeader.orbit = mIntRecord.orbit; + LOG(DEBUG) << " makeGBTHeader for link: " << link; +} +//_____________________________________________________________________________________ +void Digits2Raw::fillSecondHalfWordAndAddData(int iChannelPerLink, int prevPmLink, const o2::InteractionRecord& ir) +{ + uint nGBTWords = uint((iChannelPerLink + 1) / 2); + if ((iChannelPerLink % 2) == 1) { + mRawEventData.mEventData[iChannelPerLink] = {}; + LOG(DEBUG) << " Fill up empty second half-word."; + } + mRawEventData.mEventHeader.nGBTWords = nGBTWords; + auto data = mRawEventData.to_vector(false); + uint32_t linkId = uint32_t(prevPmLink); + uint64_t feeId = uint64_t(prevPmLink); + mWriter.addData(feeId, sCruId, linkId, sEndPointId, ir, data); + LOG(DEBUG) << " Switch prevPmLink: " << prevPmLink << ". Save data with nGBTWords=" + << nGBTWords << " in header. Last channel: " << iChannelPerLink; +} diff --git a/Detectors/FIT/FDD/simulation/src/FDDSimulationLinkDef.h b/Detectors/FIT/FDD/simulation/src/FDDSimulationLinkDef.h index f1383dd0e33dc..d7ba52a55bf9a 100644 --- a/Detectors/FIT/FDD/simulation/src/FDDSimulationLinkDef.h +++ b/Detectors/FIT/FDD/simulation/src/FDDSimulationLinkDef.h @@ -19,5 +19,6 @@ #pragma link C++ class o2::fdd::Digitizer + ; #pragma link C++ class o2::fdd::DigitizationParameters + ; #pragma link C++ class o2::dataformats::MCTruthContainer < o2::fdd::MCLabel> + ; +#pragma link C++ class o2::fdd::Digits2Raw + ; #endif diff --git a/Detectors/FIT/FDD/simulation/src/digit2raw.cxx b/Detectors/FIT/FDD/simulation/src/digit2raw.cxx new file mode 100644 index 0000000000000..250aecb36059d --- /dev/null +++ b/Detectors/FIT/FDD/simulation/src/digit2raw.cxx @@ -0,0 +1,114 @@ +// 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 digi2raw.cxx +/// \author ruben.shahoyan@cern.ch + +#include <boost/program_options.hpp> +#include <TSystem.h> +#include <TFile.h> +#include <TStopwatch.h> +#include <string> +#include <iomanip> +#include "Framework/Logger.h" +#include "FairLogger.h" +#include "CommonUtils/StringUtils.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "DetectorsRaw/HBFUtils.h" +#include "FDDSimulation/Digits2Raw.h" + +/// MC->raw conversion for FDD + +namespace bpo = boost::program_options; + +void digi2raw(const std::string& inpName, const std::string& outDir, bool filePerLink, uint32_t rdhV = 6, bool noEmptyHBF = false, + int superPageSizeInB = 1024 * 1024); + +int main(int argc, char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + " (Convert FDD digits to CRU raw data)\n"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + // add_option("input-file,i", bpo::value<std::string>()->default_value(o2::base::NameConf::getDigitsFileName(o2::detectors::DetID::FDD)),"input FDD digits file"); // why not used? + add_option("input-file,i", bpo::value<std::string>()->default_value("fdddigits.root"), "input FDD digits file"); + add_option("file-per-link,l", bpo::value<bool>()->default_value(false)->implicit_value(true), "create output file per CRU (default: per layer)"); + add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); + uint32_t defRDH = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>(); + add_option("rdh-version,r", bpo::value<uint32_t>()->default_value(defRDH), "RDH version to use"); + add_option("no-empty-hbf,e", bpo::value<bool>()->default_value(false)->implicit_value(true), "do not create empty HBF pages (except for HBF starting TF)"); + add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help")) { + std::cout << opt_general << std::endl; + exit(0); + } + + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + o2::conf::ConfigurableParam::updateFromString(vm["configKeyValues"].as<std::string>()); + digi2raw(vm["input-file"].as<std::string>(), + vm["output-dir"].as<std::string>(), + vm["file-per-link"].as<bool>(), + vm["rdh-version"].as<uint32_t>(), + vm["no-empty-hbf"].as<bool>()); + + return 0; +} + +void digi2raw(const std::string& inpName, const std::string& outDir, bool filePerLink, uint32_t rdhV, bool noEmptyHBF, int superPageSizeInB) +{ + TStopwatch swTot; + swTot.Start(); + o2::fdd::Digits2Raw m2r; + m2r.setFilePerLink(filePerLink); + auto& wr = m2r.getWriter(); + wr.setSuperPageSize(superPageSizeInB); + wr.useRDHVersion(rdhV); + wr.setDontFillEmptyHBF(noEmptyHBF); + + std::string outDirName(outDir); + if (outDirName.back() != '/') { + outDirName += '/'; + } + // if needed, create output directory + if (gSystem->AccessPathName(outDirName.c_str())) { + if (gSystem->mkdir(outDirName.c_str(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outDirName; + } else { + LOG(INFO) << "created output directory " << outDirName; + } + } + + m2r.readDigits(outDirName, inpName); + wr.writeConfFile(wr.getOrigin().str, "RAWDATA", o2::utils::concat_string(outDirName, wr.getOrigin().str, "raw.cfg")); + //LOG(INFO)<<o2::utils::concat_string(outDirName, wr.getOrigin().str)<<"\n"; + // + swTot.Stop(); + swTot.Print(); +} diff --git a/Detectors/FIT/FDD/workflow/CMakeLists.txt b/Detectors/FIT/FDD/workflow/CMakeLists.txt index 23348ec266640..65cca7cf3aba7 100644 --- a/Detectors/FIT/FDD/workflow/CMakeLists.txt +++ b/Detectors/FIT/FDD/workflow/CMakeLists.txt @@ -9,12 +9,29 @@ # submit itself to any jurisdiction. o2_add_library(FDDWorkflow - SOURCES src/RecoWorkflow.cxx src/DigitReaderSpec.cxx - src/ReconstructorSpec.cxx src/RecPointWriterSpec.cxx + SOURCES src/DigitReaderSpec.cxx + src/EntropyEncoderSpec.cxx + src/EntropyDecoderSpec.cxx + src/RecoWorkflow.cxx + src/ReconstructorSpec.cxx + src/RecPointWriterSpec.cxx src/RecPointReaderSpec.cxx - PUBLIC_LINK_LIBRARIES O2::FDDReconstruction O2::Framework O2::DPLUtils) + PUBLIC_LINK_LIBRARIES O2::FDDReconstruction + O2::Framework + O2::DPLUtils) o2_add_executable(reco-workflow COMPONENT_NAME fdd SOURCES src/fdd-reco-workflow.cxx PUBLIC_LINK_LIBRARIES O2::FDDWorkflow) + +o2_add_executable(entropy-encoder-workflow + SOURCES src/entropy-encoder-workflow.cxx + COMPONENT_NAME fdd + PUBLIC_LINK_LIBRARIES O2::FDDWorkflow) + +o2_add_executable(digit-reader-workflow + SOURCES src/digits-reader-workflow.cxx + COMPONENT_NAME fdd + PUBLIC_LINK_LIBRARIES O2::FDDWorkflow) + diff --git a/Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyDecoderSpec.h b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..4b8b4e5bcd309 --- /dev/null +++ b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyDecoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to FDD digit/channels strean + +#ifndef O2_FDD_ENTROPYDECODER_SPEC +#define O2_FDD_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "FDDReconstruction/CTFCoder.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace fdd +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::fdd::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace fdd +} // namespace o2 + +#endif diff --git a/Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyEncoderSpec.h b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..1a7b131fc45fc --- /dev/null +++ b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/EntropyEncoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert clusters streams to CTF (EncodedBlocks) + +#ifndef O2_FDD_ENTROPYENCODER_SPEC +#define O2_FDD_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> +#include "FDDReconstruction/CTFCoder.h" + +namespace o2 +{ +namespace fdd +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::fdd::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace fdd +} // namespace o2 + +#endif diff --git a/Detectors/FIT/FDD/workflow/include/FDDWorkflow/RecPointWriterSpec.h b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/RecPointWriterSpec.h index 8d9f251bf6b35..7fa95c492eb15 100644 --- a/Detectors/FIT/FDD/workflow/include/FDDWorkflow/RecPointWriterSpec.h +++ b/Detectors/FIT/FDD/workflow/include/FDDWorkflow/RecPointWriterSpec.h @@ -13,7 +13,6 @@ #ifndef O2_FDD_RECPOINTWRITER_H #define O2_FDD_RECPOINTWRITER_H - #include "Framework/DataProcessorSpec.h" using namespace o2::framework; diff --git a/Detectors/FIT/FDD/workflow/src/EntropyDecoderSpec.cxx b/Detectors/FIT/FDD/workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..b0af83a9fbbb4 --- /dev/null +++ b/Detectors/FIT/FDD/workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "FDDWorkflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace fdd +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("fdd-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& digits = pc.outputs().make<std::vector<o2::fdd::Digit>>(OutputRef{"digits"}); + auto& channels = pc.outputs().make<std::vector<o2::fdd::ChannelData>>(OutputRef{"channels"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::fdd::CTF::getImage(buff.data()); + mCTFCoder.decode(ctfImage, digits, channels); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << channels.size() << " FDD channels in " << digits.size() << " digits in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "FDD Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"digits"}, "FDD", "FDDDigit", 0, Lifetime::Timeframe}, + OutputSpec{{"channels"}, "FDD", "FDDDigitCh", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "fdd-entropy-decoder", + Inputs{InputSpec{"ctf", "FDD", "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{{"fdd-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; +} + +} // namespace fdd +} // namespace o2 diff --git a/Detectors/FIT/FDD/workflow/src/EntropyEncoderSpec.cxx b/Detectors/FIT/FDD/workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..b3d9b6b332d97 --- /dev/null +++ b/Detectors/FIT/FDD/workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,78 @@ +// 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 EntropyEncoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "FDDWorkflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace fdd +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("fdd-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto digits = pc.inputs().get<gsl::span<o2::fdd::Digit>>("digits"); + auto channels = pc.inputs().get<gsl::span<o2::fdd::ChannelData>>("channels"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"FDD", "CTFDATA", 0, Lifetime::Timeframe}); + mCTFCoder.encode(buffer, digits, channels); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for FDD in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "FDD Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("digits", "FDD", "FDDDigit", 0, Lifetime::Timeframe); + inputs.emplace_back("channels", "FDD", "FDDDigitCh", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "fdd-entropy-encoder", + inputs, + Outputs{{"FDD", "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{{"fdd-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; +} + +} // namespace fdd +} // namespace o2 diff --git a/Detectors/FIT/FDD/workflow/src/digits-reader-workflow.cxx b/Detectors/FIT/FDD/workflow/src/digits-reader-workflow.cxx new file mode 100644 index 0000000000000..de9c7439b9aac --- /dev/null +++ b/Detectors/FIT/FDD/workflow/src/digits-reader-workflow.cxx @@ -0,0 +1,45 @@ +// 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 digits-reader-workflow.cxx +/// \brief Implementation of FDD digits reader +/// +/// \author ruben.shahoyan@cern.ch + +#include "Framework/CallbackService.h" +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Task.h" +#include "FDDWorkflow/DigitReaderSpec.h" +#include "CommonUtils/ConfigurableParam.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<o2::framework::ConfigParamSpec> options{ + {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}}; + std::string keyvaluehelp("Semicolon separated key=value strings"); + options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(const ConfigContext& ctx) +{ + WorkflowSpec specs; + + DataProcessorSpec producer = o2::fdd::getFDDDigitReaderSpec(ctx.options().get<bool>("disable-mc")); + specs.push_back(producer); + return specs; +} diff --git a/Detectors/FIT/FDD/workflow/src/entropy-encoder-workflow.cxx b/Detectors/FIT/FDD/workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..87a8b05d20357 --- /dev/null +++ b/Detectors/FIT/FDD/workflow/src/entropy-encoder-workflow.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. + +#include "FDDWorkflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::fdd::getEntropyEncoderSpec()); + return wf; +} From 5b5d86000a1dc5bb7bf23e13f309a34a2a55184d Mon Sep 17 00:00:00 2001 From: Nazar <nazar.burmasov@cern.ch> Date: Tue, 10 Nov 2020 13:13:41 +0300 Subject: [PATCH 1270/1751] Added MC events to min/max glob. BC finder (#4802) --- .../AODProducerWorkflowSpec.h | 2 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 38 ++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index c36b47bc2800c..814ead3c15eeb 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -91,7 +91,7 @@ class AODProducerWorkflowDPL : public Task uint64_t maxGlBC = 0; uint64_t minGlBC = INT64_MAX; - void findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC); + void findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC, const std::vector<o2::InteractionTimeRecord>& mcRecords); int64_t getTFNumber(uint64_t firstVtxGlBC, int runNumber); template <typename TracksType, typename TracksCursorType> diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index ccd90acc63d75..70e3f6190ad90 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -44,7 +44,7 @@ using namespace o2::framework; namespace o2::aodproducer { -void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC) +void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC, const std::vector<o2::InteractionTimeRecord>& mcRecords) { for (auto& ft0RecPoint : ft0RecPoints) { uint64_t bc = ft0RecPoint.getInteractionRecord().orbit * o2::constants::lhc::LHCMaxBunches + ft0RecPoint.getInteractionRecord().bc; @@ -66,6 +66,16 @@ void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& f maxGlBC = bc; } } + + for (auto& rec : mcRecords) { + uint64_t bc = rec.bc + rec.orbit * o2::constants::lhc::LHCMaxBunches; + if (minGlBC > bc) { + minGlBC = bc; + } + if (maxGlBC < bc) { + maxGlBC = bc; + } + } } int64_t AODProducerWorkflowDPL::getTFNumber(uint64_t firstVtxGlBC, int runNumber) @@ -259,7 +269,15 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto fddCursor = fddBuilder.cursor<o2::aod::FDDs>(); auto zdcCursor = zdcBuilder.cursor<o2::aod::Zdcs>(); - findMinMaxBc(ft0RecPoints, tracksITSTPC); + o2::steer::MCKinematicsReader mcReader("collisioncontext.root"); + const auto mcContext = mcReader.getDigitizationContext(); + const auto& mcRecords = mcContext->getEventRecords(); + const auto& mcParts = mcContext->getEventParts(); + + LOG(INFO) << "FOUND " << mcRecords.size() << " records"; + LOG(INFO) << "FOUND " << mcParts.size() << " parts"; + + findMinMaxBc(ft0RecPoints, tracksITSTPC, mcRecords); std::map<uint64_t, uint64_t> mGlobBC2BCID; @@ -325,14 +343,6 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) 0.f, 0.f); - o2::steer::MCKinematicsReader mcReader("collisioncontext.root"); - const auto context = mcReader.getDigitizationContext(); - const auto& records = context->getEventRecords(); - const auto& parts = context->getEventParts(); - - LOG(INFO) << "FOUND " << records.size() << " records"; - LOG(INFO) << "FOUND " << parts.size() << " parts"; - // TODO: // figure out generatorID and collision weight int index = 0; @@ -340,11 +350,11 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) float mcColWeight = 1.; // filling mcCollison table - for (auto& rec : records) { + for (auto& rec : mcRecords) { auto time = rec.getTimeNS(); - auto& colparts = parts[index]; - auto eventID = colparts[0].entryID; - auto sourceID = colparts[0].sourceID; + auto& colParts = mcParts[index]; + auto eventID = colParts[0].entryID; + auto sourceID = colParts[0].sourceID; auto& header = mcReader.getMCEventHeader(sourceID, eventID); uint64_t globalBC = rec.bc + rec.orbit * o2::constants::lhc::LHCMaxBunches; mcCollisionsCursor(0, From 6f47deb41cd2b266b7a0dc60ff400458a35fc1ca Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Tue, 10 Nov 2020 13:21:46 +0100 Subject: [PATCH 1271/1751] [QC-471] Do not create a Dispatcher if there are no policies (#4758) --- Utilities/DataSampling/README.md | 1 + Utilities/DataSampling/include/DataSampling/Dispatcher.h | 2 ++ Utilities/DataSampling/src/DataSampling.cxx | 2 +- Utilities/DataSampling/src/Dispatcher.cxx | 4 ++++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Utilities/DataSampling/README.md b/Utilities/DataSampling/README.md index ad9abc8ba2ba5..b417f83beee2c 100644 --- a/Utilities/DataSampling/README.md +++ b/Utilities/DataSampling/README.md @@ -61,6 +61,7 @@ std::vector<DataProcessorSpec> defineDataProcessing(ConfigContext &ctx) ``` Sampled data can be subscribed to by adding `InputSpecs` provided by `std::vector<InputSpec> 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. +If no sampling policies are specified, Dispatcher will not be spawned. 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. diff --git a/Utilities/DataSampling/include/DataSampling/Dispatcher.h b/Utilities/DataSampling/include/DataSampling/Dispatcher.h index 3e2c078d788e6..b342f9478f0e1 100644 --- a/Utilities/DataSampling/include/DataSampling/Dispatcher.h +++ b/Utilities/DataSampling/include/DataSampling/Dispatcher.h @@ -52,6 +52,8 @@ class Dispatcher : public framework::Task /// \brief Register a Data Sampling Policy void registerPolicy(std::unique_ptr<DataSamplingPolicy>&&); + /// \brief Returns the number of registered policies. + size_t numberOfPolicies(); const std::string& getName(); /// \brief Assembles InputSpecs of all registered policies in a single vector, removing overlapping entries. diff --git a/Utilities/DataSampling/src/DataSampling.cxx b/Utilities/DataSampling/src/DataSampling.cxx index f0bc702703793..766dadd9e22b3 100644 --- a/Utilities/DataSampling/src/DataSampling.cxx +++ b/Utilities/DataSampling/src/DataSampling.cxx @@ -75,7 +75,7 @@ void DataSampling::DoGenerateInfrastructure(Dispatcher& dispatcher, WorkflowSpec } } - if (dispatcher.getInputSpecs().size() > 0) { + if (dispatcher.numberOfPolicies() > 0) { DataProcessorSpec spec; spec.name = dispatcher.getName(); spec.inputs = dispatcher.getInputSpecs(); diff --git a/Utilities/DataSampling/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx index 4859d29b0fbc9..df307b007c397 100644 --- a/Utilities/DataSampling/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -258,5 +258,9 @@ framework::Options Dispatcher::getOptions() return options; } +size_t Dispatcher::numberOfPolicies() +{ + return mPolicies.size(); +} } // namespace o2::utilities From 79250b7c9d91265b81d47f36103ce76cff11a4c7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 10 Nov 2020 10:47:47 +0100 Subject: [PATCH 1272/1751] Use 61 as minimum CUDA compute capability to support half precision --- dependencies/FindO2GPU.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 68862e3431089..f552ba605c055 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -64,7 +64,7 @@ if(ENABLE_CUDA) if(CUDA_COMPUTETARGET) set(CMAKE_CUDA_ARCHITECTURES ${CUDA_COMPUTETARGET}) else() - set(CMAKE_CUDA_ARCHITECTURES OFF) + set(CMAKE_CUDA_ARCHITECTURES 61-virtual) endif() set(CUDA_ENABLED ON) From 569752386b84457ccfd2f3369d2a942a44fc53e8 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 10 Nov 2020 13:52:11 +0100 Subject: [PATCH 1273/1751] using histogram registry (#4759) --- Analysis/Core/include/Analysis/PairCuts.h | 54 ++++++++++++++-------- Analysis/Core/src/CorrelationContainer.cxx | 4 +- Analysis/Tasks/PWGCF/correlations.cxx | 23 ++++----- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/Analysis/Core/include/Analysis/PairCuts.h b/Analysis/Core/include/Analysis/PairCuts.h index 59f7519d04d91..f8918b3dcdf05 100644 --- a/Analysis/Core/include/Analysis/PairCuts.h +++ b/Analysis/Core/include/Analysis/PairCuts.h @@ -12,13 +12,20 @@ #define O2_ANALYSIS_PAIRCUTS_H #include <cmath> + #include <TH2F.h> #include <TH3F.h> +#include "Framework/Logger.h" +#include "Framework/HistogramRegistry.h" + // Functions which cut on particle pairs (decays, conversions, two-track cuts) // // Author: Jan Fiete Grosse-Oetringhaus +using namespace o2; +using namespace o2::framework; + class PairCuts { public: @@ -29,22 +36,26 @@ class PairCuts Rho, ParticlesLastEntry }; + void SetHistogramRegistry(HistogramRegistry* registry) { histogramRegistry = registry; } + void SetPairCut(Particle particle, float cut) { + LOGF(info, "Enabled pair cut for %d with value %f", static_cast<int>(particle), cut); mCuts[particle] = cut; - if (mControlConvResoncances == nullptr) { - mControlConvResoncances = new TH2F("ControlConvResoncances", ";id;delta mass", 6, -0.5, 5.5, 500, -0.5, 0.5); + if (histogramRegistry != nullptr && histogramRegistry->contains("ControlConvResonances") == false) { + histogramRegistry->add("ControlConvResonances", "", {HistType::kTH2F, {{6, -0.5, 5.5, "id"}, {500, -0.5, 0.5, "delta mass"}}}); } } void SetTwoTrackCuts(float distance = 0.02f, float radius = 0.8f) { + LOGF(info, "Enabled two-track cut with distance %f and radius %f", distance, radius); mTwoTrackDistance = distance; mTwoTrackRadius = radius; - if (mTwoTrackDistancePt[0] == nullptr) { - mTwoTrackDistancePt[0] = new TH3F("TwoTrackDistancePt[0]", ";#Delta#eta;#Delta#varphi^{*}_{min};#Delta p_{T}", 100, -0.15, 0.15, 100, -0.05, 0.05, 20, 0, 10); - mTwoTrackDistancePt[1] = (TH3F*)mTwoTrackDistancePt[0]->Clone("TwoTrackDistancePt[1]"); + if (histogramRegistry != nullptr && histogramRegistry->contains("TwoTrackDistancePt_0") == false) { + histogramRegistry->add("TwoTrackDistancePt_0", "", {HistType::kTH3F, {{100, -0.15, 0.15, "#Delta#eta"}, {100, -0.05, 0.05, "#Delta#varphi^{*}_{min}"}, {20, 0, 10, "#Delta p_{T}"}}}); + histogramRegistry->addClone("TwoTrackDistancePt_0", "TwoTrackDistancePt_1"); } } @@ -59,8 +70,7 @@ class PairCuts float mTwoTrackDistance = -1; // distance below which the pair is flagged as to be removed float mTwoTrackRadius = 0.8f; // radius at which the two track cuts are applied - TH2F* mControlConvResoncances = nullptr; // control histograms for cuts on conversions and resonances - TH3F* mTwoTrackDistancePt[2] = {nullptr}; // control histograms for two-track efficiency study: dphi*_min vs deta (0 = before cut, 1 = after cut) + HistogramRegistry* histogramRegistry = nullptr; // if set, control histograms are stored here template <typename T> bool conversionCut(T const& track1, T const& track2, Particle conv, double cut); @@ -132,14 +142,18 @@ bool PairCuts::twoTrackCut(T const& track1, T const& track2, int bSign) } } - mTwoTrackDistancePt[0]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + if (histogramRegistry != nullptr) { + histogramRegistry->fill("TwoTrackDistancePt_0", deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + } if (dphistarminabs < mTwoTrackDistance && TMath::Abs(deta) < mTwoTrackDistance) { //LOGF(debug, "Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.charge(), track2.phi2(), track2.pt(), track2.charge(), bSign); return true; } - mTwoTrackDistancePt[1]->Fill(deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + if (histogramRegistry != nullptr) { + histogramRegistry->fill("TwoTrackDistancePt_1", deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + } } } @@ -196,7 +210,11 @@ bool PairCuts::conversionCut(T const& track1, T const& track2, Particle conv, do } massC = getInvMassSquared(track1, massD1, track2, massD2); - mControlConvResoncances->Fill(static_cast<int>(conv), massC - massM * massM); + + if (histogramRegistry != nullptr) { + histogramRegistry->fill("ControlConvResonances", static_cast<int>(conv), massC - massM * massM); + } + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) { return true; } @@ -268,20 +286,20 @@ double PairCuts::getInvMassSquaredFast(T const& track1, double m0_1, T const& tr // fold onto 0...pi float deltaPhi = TMath::Abs(phi1 - phi2); - while (deltaPhi > TMath::TwoPi()) { - deltaPhi -= TMath::TwoPi(); + while (deltaPhi > M_PI * 2) { + deltaPhi -= M_PI * 2; } - if (deltaPhi > TMath::Pi()) { - deltaPhi = TMath::TwoPi() - deltaPhi; + if (deltaPhi > M_PI) { + deltaPhi = M_PI * 2 - deltaPhi; } float cosDeltaPhi = 0; - if (deltaPhi < TMath::Pi() / 3) { + if (deltaPhi < M_PI / 3) { cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; - } else if (deltaPhi < 2 * TMath::Pi() / 3) { - cosDeltaPhi = -(deltaPhi - TMath::Pi() / 2) + 1.0 / 6 * TMath::Power((deltaPhi - TMath::Pi() / 2), 3); + } else if (deltaPhi < 2 * M_PI / 3) { + cosDeltaPhi = -(deltaPhi - M_PI / 2) + 1.0 / 6 * TMath::Power((deltaPhi - M_PI / 2), 3); } else { - cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - TMath::Pi()) * (deltaPhi - TMath::Pi()) - 1.0 / 24.0 * TMath::Power(deltaPhi - TMath::Pi(), 4); + cosDeltaPhi = -1.0 + 1.0 / 2.0 * (deltaPhi - M_PI) * (deltaPhi - M_PI) - 1.0 / 24.0 * TMath::Power(deltaPhi - M_PI, 4); } double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (TMath::Sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0 / tantheta1 / tantheta2))); diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 5a38a00167200..76940b51aa043 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -15,6 +15,7 @@ #include "Analysis/CorrelationContainer.h" #include "Framework/StepTHn.h" +#include "Framework/Logger.h" #include "THnSparse.h" #include "TMath.h" #include "TList.h" @@ -26,9 +27,6 @@ #include "TF1.h" #include "THn.h" -// for LOGF -#include "Framework/AnalysisTask.h" - ClassImp(CorrelationContainer) const Int_t CorrelationContainer::fgkCFSteps = 11; diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index bdfce0e96a85c..21ba374fe4870 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -13,6 +13,7 @@ #include "Framework/ASoAHelpers.h" #include <CCDB/BasicCCDBManager.h> #include "Framework/StepTHn.h" +#include "Framework/HistogramRegistry.h" #include "Analysis/EventSelection.h" #include "Analysis/TrackSelectionTables.h" @@ -63,7 +64,6 @@ struct CorrelationTask { // Output definitions OutputObj<CorrelationContainer> same{"sameEvent"}; OutputObj<CorrelationContainer> mixed{"mixedEvent"}; - //OutputObj<TDirectory> qaOutput{"qa"}; struct Config { bool mPairCuts = false; @@ -71,13 +71,10 @@ struct CorrelationTask { THn* mEfficiencyAssociated = nullptr; } cfg; - // HistogramRegistry registry{"qa", true, { - // {"yields", "centrality vs pT vs eta", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"} }}}, - // {"etaphi", "centrality vs eta vs phi", {HistogramType::kTH3F, { {100, 0, 100, "centrality"}, {100, -2, 2, "#eta"}, {200, 0, 2 * M_PI, "#varphi"} }}} - // }}; - - OutputObj<TH3F> yields{TH3F("yields", "centrality vs pT vs eta", 100, 0, 100, 40, 0, 20, 100, -2, 2)}; - OutputObj<TH3F> etaphi{TH3F("etaphi", "centrality vs eta vs phi", 100, 0, 100, 100, -2, 2, 200, 0, 2 * M_PI)}; + HistogramRegistry registry{"registry", { + {"yields", "centrality vs pT vs eta", {HistType::kTH3F, {{100, 0, 100, "centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}}, // + {"etaphi", "centrality vs eta vs phi", {HistType::kTH3F, {{100, 0, 100, "centrality"}, {100, -2, 2, "#eta"}, {200, 0, 2 * M_PI, "#varphi"}}}} // + }}; PairCuts mPairCuts; @@ -99,6 +96,8 @@ struct CorrelationTask { "p_t_eff: 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0\n" "vertex_eff: 10 | -10, 10\n"; + mPairCuts.SetHistogramRegistry(®istry); + if (cfgPairCutPhoton > 0 || cfgPairCutK0 > 0 || cfgPairCutLambda > 0 || cfgPairCutPhi > 0 || cfgPairCutRho > 0) { mPairCuts.SetPairCut(PairCuts::Photon, cfgPairCutPhoton); mPairCuts.SetPairCut(PairCuts::K0, cfgPairCutK0); @@ -115,7 +114,6 @@ struct CorrelationTask { // --- OBJECT INIT --- same.setObject(new CorrelationContainer("sameEvent", "sameEvent", "NumberDensityPhiCentralityVtx", binning)); mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", "NumberDensityPhiCentralityVtx", binning)); - //qaOutput.setObject(new TDirectory("qa", "qa")); // o2-ccdb-upload -p Users/jgrosseo/correlations/LHC15o -f /tmp/correction_2011_global.root -k correction @@ -182,11 +180,8 @@ struct CorrelationTask { // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); - // control histograms - // ((TH3*) (registry.get("yields").get()))->Fill(centrality, track1.pt(), track1.eta()); - // ((TH3*) (registry.get("etaphi").get()))->Fill(centrality, track1.eta(), track1.phi()); - yields->Fill(centrality, track1.pt(), track1.eta()); - etaphi->Fill(centrality, track1.eta(), track1.phi()); + registry.fill("yields", centrality, track1.pt(), track1.eta()); + registry.fill("etaphi", centrality, track1.eta(), track1.phi()); if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; From b4d753260d04897341f6e090f3b8761405eb3946 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 10 Nov 2020 17:09:51 +0100 Subject: [PATCH 1274/1751] DPL: do proper ZMQ polling to avoid deadlocking (#4804) The correct way to receive messages in an event based ZeroMQ is: * Retrieve the file descriptor (already done) * epoll it / kqueue so that you get notified on READ (already done) * When processing, check if the ZMQ_EVENTS has ZMQ_POLLIN, which was missing. If not, continue. * Call Receive on the socket until you have at least one message the messages Apart from the ZMQ_EVENTS check, which has to happen in any case, the difference with the documentation is that even when you get ZMQ_POLLIN you can still get EAGAIN before actually getting some messages. One needs to handle all the messages before returning on the next EAGAIN. --- Framework/Core/src/DataProcessingDevice.cxx | 54 ++++++++++++++++----- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 23479c1c539c7..01ba3816663dc 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -505,15 +505,45 @@ void DataProcessingDevice::doPrepare(DataProcessorContext& context) if (info.state != InputChannelState::Running) { continue; } - FairMQParts parts; - auto result = context.device->Receive(parts, channel.name, 0, 0); - if (result > 0) { - // Receiving data counts as activity now, so that - // We can make sure we process all the pending - // messages without hanging on the uv_run. - *context.wasActive = true; - DataProcessingDevice::handleData(context, parts, info); + int result = -2; + auto& fairMQChannel = context.device->GetChannel(channel.name, 0); + auto& socket = fairMQChannel.GetSocket(); + uint32_t events; + socket.Events(&events); + if ((events & 1) == 0) { + continue; } + // Notice that there seems to be a difference between the documentation + // of zeromq and the observed behavior. The fact that ZMQ_POLLIN + // is raised does not mean that a message is immediately available to + // read, just that it will be available soon, so the receive can + // still return -2. To avoid this we keep receiving on the socket until + // we get a message, consume all the consecutive messages, and then go back + // to the usual loop. + do { + if (events & 1) { + bool oneMessage = false; + while (true) { + FairMQParts parts; + result = fairMQChannel.Receive(parts, 0); + if (result >= 0) { + // Receiving data counts as activity now, so that + // We can make sure we process all the pending + // messages without hanging on the uv_run. + *context.wasActive = true; + DataProcessingDevice::handleData(context, parts, info); + oneMessage = true; + } else { + if (oneMessage) { + break; + } + } + } + } else { + break; + } + socket.Events(&events); + } while (events & 1); } } @@ -607,8 +637,8 @@ void DataProcessingDevice::handleData(DataProcessorContext& context, FairMQParts // and we do a few stats. We bind parts as a lambda captured variable, rather // than an input, because we do not want the outer loop actually be exposed // to the implementation details of the messaging layer. - auto getInputTypes = [& stats = context.registry->get<DataProcessingStats>(), - &parts, &info]() -> std::optional<std::vector<InputType>> { + auto getInputTypes = [&stats = context.registry->get<DataProcessingStats>(), + &parts, &info, &context]() -> std::optional<std::vector<InputType>> { stats.inputParts = parts.Size(); TracyPlot("messages received", (int64_t)parts.Size()); @@ -623,6 +653,7 @@ void DataProcessingDevice::handleData(DataProcessorContext& context, FairMQParts if (sih) { info.state = sih->state; results[hi] = InputType::SourceInfo; + *context.wasActive = true; continue; } auto dh = o2::header::get<DataHeader*>(parts.At(pi)->GetData()); @@ -654,7 +685,7 @@ void DataProcessingDevice::handleData(DataProcessorContext& context, FairMQParts registry.get<Monitoring>().send(Metric{*context.errorCount, "errors"}.addTag(Key::Subsystem, Value::DPL)); }; - auto handleValidMessages = [&parts, &relayer = *context.relayer, &reportError](std::vector<InputType> const& types) { + auto handleValidMessages = [&parts, &context = context, &relayer = *context.relayer, &reportError](std::vector<InputType> const& types) { // We relay execution to make sure we have a complete set of parts // available. for (size_t pi = 0; pi < (parts.Size() / 2); ++pi) { @@ -670,6 +701,7 @@ void DataProcessingDevice::handleData(DataProcessorContext& context, FairMQParts } } break; case InputType::SourceInfo: { + *context.wasActive = true; } break; case InputType::Invalid: { From 289dedc5217a29875b1cbbddac4a7e4826b01a9a Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 10 Nov 2020 00:05:14 +0100 Subject: [PATCH 1275/1751] add timer for FT0 reconstruction --- .../workflow/include/FT0Workflow/ReconstructionSpec.h | 4 +++- Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx | 11 ++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Detectors/FIT/FT0/workflow/include/FT0Workflow/ReconstructionSpec.h b/Detectors/FIT/FT0/workflow/include/FT0Workflow/ReconstructionSpec.h index e3e6b3da7c62f..fd4af7581eae3 100644 --- a/Detectors/FIT/FT0/workflow/include/FT0Workflow/ReconstructionSpec.h +++ b/Detectors/FIT/FT0/workflow/include/FT0Workflow/ReconstructionSpec.h @@ -17,6 +17,7 @@ #include "Framework/Task.h" #include "FT0Reconstruction/CollisionTimeRecoTask.h" #include "DataFormatsFT0/RecPoints.h" +#include "TStopwatch.h" using namespace o2::framework; @@ -32,14 +33,15 @@ class ReconstructionDPL : public Task ~ReconstructionDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; + void endOfStream(framework::EndOfStreamContext& ec) final; private: - bool mFinished = false; bool mUseMC = true; std::vector<o2::ft0::RecPoints> mRecPoints; std::vector<o2::ft0::ChannelDataFloat> mRecChData; o2::ft0::CollisionTimeRecoTask mReco; o2::header::DataOrigin mOrigin = o2::header::gDataOriginFT0; + TStopwatch mTimer; }; /// create a processor spec diff --git a/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx index a9a39d6aac58c..b659938e87585 100644 --- a/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx @@ -28,11 +28,14 @@ namespace ft0 void ReconstructionDPL::init(InitContext& ic) { + mTimer.Stop(); + mTimer.Reset(); LOG(INFO) << "ReconstructionDPL::init"; } void ReconstructionDPL::run(ProcessingContext& pc) { + mTimer.Start(false); mRecPoints.clear(); auto digits = pc.inputs().get<gsl::span<o2::ft0::Digit>>("digits"); //auto digits = pc.inputs().get<const std::vector<o2::ft0::Digit>>("digits"); @@ -63,7 +66,13 @@ void ReconstructionDPL::run(ProcessingContext& pc) pc.outputs().snapshot(Output{mOrigin, "RECPOINTS", 0, Lifetime::Timeframe}, mRecPoints); pc.outputs().snapshot(Output{mOrigin, "RECCHDATA", 0, Lifetime::Timeframe}, mRecChData); - mFinished = true; + mTimer.Stop(); +} + +void ReconstructionDPL::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "FT0 reconstruction total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } DataProcessorSpec getReconstructionSpec(bool useMC) From 5aa2a8f5d3edcdd93a42f4d84543f1e9d1d1122d Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 10 Nov 2020 00:05:30 +0100 Subject: [PATCH 1276/1751] add timer for MFT reconstruction --- .../MFT/workflow/include/MFTWorkflow/TrackerSpec.h | 3 +++ Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h b/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h index 50624a8de2c76..a18f2f37a766a 100644 --- a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h @@ -19,6 +19,7 @@ #include "Framework/Task.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsITSMFT/TopologyDictionary.h" +#include "TStopwatch.h" namespace o2 { @@ -32,12 +33,14 @@ class TrackerDPL : public o2::framework::Task ~TrackerDPL() override = default; void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(framework::EndOfStreamContext& ec) final; private: bool mUseMC = false; o2::itsmft::TopologyDictionary mDict; std::unique_ptr<o2::parameters::GRPObject> mGRP = nullptr; std::unique_ptr<o2::mft::Tracker> mTracker = nullptr; + TStopwatch mTimer; }; /// create a processor spec diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 41e521f86e263..ba62e01740dea 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -43,6 +43,8 @@ namespace mft void TrackerDPL::init(InitContext& ic) { + mTimer.Stop(); + mTimer.Reset(); auto filename = ic.options().get<std::string>("grp-file"); const auto grp = o2::parameters::GRPObject::loadFrom(filename.c_str()); if (grp) { @@ -74,6 +76,7 @@ void TrackerDPL::init(InitContext& ic) void TrackerDPL::run(ProcessingContext& pc) { + mTimer.Start(false); gsl::span<const unsigned char> patterns = pc.inputs().get<gsl::span<unsigned char>>("patterns"); auto compClusters = pc.inputs().get<const std::vector<o2::itsmft::CompClusterExt>>("compClusters"); auto nTracksLTF = 0; @@ -168,6 +171,13 @@ void TrackerDPL::run(ProcessingContext& pc) pc.outputs().snapshot(Output{"MFT", "TRACKSMCTR", 0, Lifetime::Timeframe}, allTrackLabels); pc.outputs().snapshot(Output{"MFT", "TRACKSMC2ROF", 0, Lifetime::Timeframe}, mc2rofs); } + mTimer.Stop(); +} + +void TrackerDPL::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "MFT Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } DataProcessorSpec getTrackerSpec(bool useMC) From 0d0dcb3bd1d12c0bbc08f508473304d1cddf2879 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 10 Nov 2020 12:51:51 +0100 Subject: [PATCH 1277/1751] TPC entropy decoding timing output added --- .../TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h | 1 + Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h index cbc15618c3f56..f4f7c2d146ebb 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/EntropyDecoderSpec.h @@ -35,6 +35,7 @@ class EntropyDecoderSpec : public o2::framework::Task ~EntropyDecoderSpec() override = default; void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; private: o2::tpc::CTFCoder mCTFCoder; diff --git a/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx b/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx index 0e2a33596045f..b5d97bb2931ff 100644 --- a/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/TPC/workflow/src/EntropyDecoderSpec.cxx @@ -48,6 +48,12 @@ void EntropyDecoderSpec::run(ProcessingContext& pc) << compclusters.size() << " bytes in " << mTimer.CpuTime() - cput << " s"; } +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "TPC Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + DataProcessorSpec getEntropyDecoderSpec() { return DataProcessorSpec{ From 187ffaa3e8db4acab07a8e693556637f064cdd94 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 10 Nov 2020 13:21:17 +0100 Subject: [PATCH 1278/1751] Add timer for TPC CATrackerSpec --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 37d9a9622de7c..bd7597b7a1a1b 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -64,6 +64,7 @@ #include <fcntl.h> #include "GPUReconstructionConvert.h" #include "DetectorsRaw/RDHUtils.h" +#include <TStopwatch.h> using namespace o2::framework; using namespace o2::header; @@ -83,6 +84,8 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config throw std::runtime_error("inconsistent configuration: cluster output is only possible if CA clusterer is activated"); } + static TStopwatch timer; + constexpr static size_t NSectors = Sector::MAXSECTOR; constexpr static size_t NEndpoints = 20; //TODO: get from mapper? using ClusterGroupParser = o2::algorithm::ForwardParser<ClusterGroupHeader>; @@ -229,6 +232,8 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config if (tracker->initialize(config) != 0) { throw std::invalid_argument("GPUCATracking initialization failed"); } + timer.Stop(); + timer.Reset(); } auto& callbacks = ic.services().get<CallbackService>(); @@ -257,10 +262,18 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } }); + // the callback to be set as hook at stop of processing for the framework + auto printTiming = []() { + LOGF(INFO, "TPC CATracker total timing: Cpu: %.3e Real: %.3e s in %d slots", timer.CpuTime(), timer.RealTime(), timer.Counter() - 1); + }; + ic.services().get<CallbackService>().set(CallbackService::Id::Stop, printTiming); + auto processingFct = [processAttributes, specconfig](ProcessingContext& pc) { if (processAttributes->readyToQuit) { return; } + auto cput = timer.CpuTime(); + timer.Start(false); auto& parser = processAttributes->parser; auto& tracker = processAttributes->tracker; auto& verbosity = processAttributes->verbosity; @@ -676,6 +689,8 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } } } + timer.Stop(); + LOG(INFO) << "TPC CATracker time for this TF " << timer.CpuTime() - cput << " s"; }; return processingFct; From 55ba624df8181d2e30696a986f8f8791c77e2fba Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Tue, 10 Nov 2020 09:30:16 +0100 Subject: [PATCH 1279/1751] Fix MID encoding when there are no digits to encode --- Detectors/MUON/MID/Raw/src/Encoder.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Detectors/MUON/MID/Raw/src/Encoder.cxx b/Detectors/MUON/MID/Raw/src/Encoder.cxx index 01ceda0a70737..e203800c20d05 100644 --- a/Detectors/MUON/MID/Raw/src/Encoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Encoder.cxx @@ -101,6 +101,10 @@ void Encoder::writePayload(uint16_t feeId, const InteractionRecord& ir) void Encoder::finalize(bool closeFile) { /// Writes remaining data and closes the file + if (mLastIR.isDummy()) { + mLastIR.bc = mRawWriter.getHBFUtils().bcFirst; + mLastIR.orbit = mRawWriter.getHBFUtils().orbitFirst; + } auto ir = getOrbitIR(mLastIR.orbit); for (uint16_t feeId = 0; feeId < crateparams::sNGBTs; ++feeId) { // Write the last payload From 3ebd4d41c7e70cdd35925d73ce781443a4a0d367 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 10 Nov 2020 22:49:29 +0100 Subject: [PATCH 1280/1751] DPL: for polling after the first EoS --- Framework/Core/src/DataProcessingDevice.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 01ba3816663dc..fb21a635d7769 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -499,6 +499,14 @@ void DataProcessingDevice::doPrepare(DataProcessorContext& context) auto& channel = context.spec->inputChannels[ci]; auto& info = context.state->inputChannelInfos[ci]; + // If at least one channel is complete, we keep polling for the remaining + // stuff. + // FIXME: this is definitely not what we want, but + // it should get the analysis working. + if (info.state == InputChannelState::Completed) { + *context.wasActive = true; + } + if (info.state != InputChannelState::Completed && info.state != InputChannelState::Pull) { context.allDone = false; } From 1b85e1621b6108f4c4a597b105c02cd2976b5178 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 10 Nov 2020 11:40:46 +0100 Subject: [PATCH 1281/1751] GPU: Some cleanup in TPC QA --- .../Standalone/display/GPUDisplayKeys.cxx | 23 +++-- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 91 ++++++++++++++++--- GPU/GPUTracking/Standalone/qa/GPUQA.h | 62 +------------ 3 files changed, 90 insertions(+), 86 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx index e7c85ef06826e..6d453b0af8e69 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplayKeys.cxx @@ -35,7 +35,6 @@ const char* HelpText[] = { "[L] / [K] Draw single collisions (next / previous)", "[C] Colorcode clusters of different collisions", "[v] Hide rejected clusters from tracks", - "[b] Hide all clusters not belonging or related to matched tracks in QA", "[j] Show global tracks as additional segments of final tracks", "[u] Cycle through track filter", "[E] / [G] Extrapolate tracks / loopers", @@ -59,7 +58,8 @@ const char* HelpText[] = { "[ALT] / [CTRL] / [m] Focus camera on origin / orient y-axis upwards (combine with [SHIFT] to lock) / Cycle through modes", "[1] ... [8] / [N] Enable display of clusters, preseeds, seeds, starthits, tracklets, tracks, global tracks, merged tracks / Show assigned clusters in colors" "[F1] / [F2] Enable / disable drawing of TPC / TRD" - // FREE: u + // FREE: b + // Test setting: # --> mHideUnmatchedClusters }; void GPUDisplay::PrintHelp() @@ -218,10 +218,6 @@ void GPUDisplay::HandleKeyRelease(unsigned char key) mHideRejectedClusters ^= 1; SetInfo("Rejected clusters are %s", mHideRejectedClusters ? "hidden" : "shown"); mUpdateDLList = true; - } else if (key == 'b') { - mHideUnmatchedClusters ^= 1; - SetInfo("Unmatched clusters are %s", mHideUnmatchedClusters ? "hidden" : "shown"); - mUpdateDLList = true; } else if (key == 'i') { mProjectXY ^= 1; SetInfo("Projection onto xy plane %s", mProjectXY ? "enabled" : "disabled"); @@ -429,12 +425,15 @@ void GPUDisplay::HandleKeyRelease(unsigned char key) PrintHelp(); SetInfo("Showing help text", 1); } - /*else if (key == '#') - { - mTestSetting++; - SetInfo("Debug test variable set to %d", mTestSetting); - mUpdateDLList = true; - }*/ + /* + else if (key == '#') + { + mTestSetting++; + SetInfo("Debug test variable set to %d", mTestSetting); + // mHideUnmatchedClusters ^= 1; + mUpdateDLList = true; + } + */ } void GPUDisplay::HandleSendKey(int key) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 0aa569f33cb3c..887998f196f28 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -134,6 +134,63 @@ static const GPUSettingsQA& GPUQA_GetConfig(GPUChainTracking* rec) #endif } +static const constexpr bool PLOT_ROOT = 0; +static const constexpr bool FIX_SCALES = 0; +static const constexpr bool PERF_FIGURE = 0; +static const constexpr float FIXED_SCALES_MIN[5] = {-0.05, -0.05, -0.2, -0.2, -0.5}; +static const constexpr float FIXED_SCALES_MAX[5] = {0.4, 0.7, 5, 3, 6.5}; +static const constexpr float LOG_PT_MIN = -1.; + +static constexpr float Y_MAX = 40; +static constexpr float Z_MAX = 100; +static constexpr float PT_MIN = GPUCA_MIN_TRACK_PT_DEFAULT; +static constexpr float PT_MIN2 = 0.1; +static constexpr float PT_MIN_PRIM = 0.1; +static constexpr float PT_MIN_CLUST = GPUCA_MIN_TRACK_PT_DEFAULT; +static constexpr float PT_MAX = 20; +static constexpr float ETA_MAX = 1.5; +static constexpr float ETA_MAX2 = 0.9; + +static constexpr float MIN_WEIGHT_CLS = 40; +static constexpr float FINDABLE_WEIGHT_CLS = 70; + +static constexpr int MC_LABEL_INVALID = -1e9; + +static constexpr bool CLUST_HIST_INT_SUM = false; + +static constexpr const int COLORCOUNT = 12; + +static const constexpr char* EFF_TYPES[4] = {"Rec", "Clone", "Fake", "All"}; +static const constexpr char* FINDABLE_NAMES[2] = {"", "Findable"}; +static const constexpr char* PRIM_NAMES[2] = {"Prim", "Sec"}; +static const constexpr char* PARAMETER_NAMES[5] = {"Y", "Z", "#Phi", "#lambda", "Relative #it{p}_{T}"}; +static const constexpr char* PARAMETER_NAMES_NATIVE[5] = {"Y", "Z", "sin(#Phi)", "tan(#lambda)", "q/#it{p}_{T} (curvature)"}; +static const constexpr char* VSPARAMETER_NAMES[6] = {"Y", "Z", "Phi", "Eta", "Pt", "Pt_log"}; +static const constexpr char* EFF_NAMES[3] = {"Efficiency", "Clone Rate", "Fake Rate"}; +static const constexpr char* EFFICIENCY_TITLES[4] = {"Efficiency (Primary Tracks, Findable)", "Efficiency (Secondary Tracks, Findable)", "Efficiency (Primary Tracks)", "Efficiency (Secondary Tracks)"}; +static const constexpr double SCALE[5] = {10., 10., 1000., 1000., 100.}; +static const constexpr double SCALE_NATIVE[5] = {10., 10., 1000., 1000., 1.}; +static const constexpr char* XAXIS_TITLES[5] = {"#it{y}_{mc} (cm)", "#it{z}_{mc} (cm)", "#Phi_{mc} (rad)", "#eta_{mc}", "#it{p}_{Tmc} (GeV/#it{c})"}; +static const constexpr char* AXIS_TITLES[5] = {"#it{y}-#it{y}_{mc} (mm) (Resolution)", "#it{z}-#it{z}_{mc} (mm) (Resolution)", "#phi-#phi_{mc} (mrad) (Resolution)", "#lambda-#lambda_{mc} (mrad) (Resolution)", "(#it{p}_{T} - #it{p}_{Tmc}) / #it{p}_{Tmc} (%) (Resolution)"}; +static const constexpr char* AXIS_TITLES_NATIVE[5] = {"#it{y}-#it{y}_{mc} (mm) (Resolution)", "#it{z}-#it{z}_{mc} (mm) (Resolution)", "sin(#phi)-sin(#phi_{mc}) (Resolution)", "tan(#lambda)-tan(#lambda_{mc}) (Resolution)", "q*(q/#it{p}_{T} - q/#it{p}_{Tmc}) (Resolution)"}; +static const constexpr char* AXIS_TITLES_PULL[5] = {"#it{y}-#it{y}_{mc}/#sigma_{y} (Pull)", "#it{z}-#it{z}_{mc}/#sigma_{z} (Pull)", "sin(#phi)-sin(#phi_{mc})/#sigma_{sin(#phi)} (Pull)", "tan(#lambda)-tan(#lambda_{mc})/#sigma_{tan(#lambda)} (Pull)", + "q*(q/#it{p}_{T} - q/#it{p}_{Tmc})/#sigma_{q/#it{p}_{T}} (Pull)"}; +static const constexpr char* CLUSTER_NAMES[GPUQA::N_CLS_HIST] = {"Correctly attached clusters", "Fake attached clusters", "Attached + adjacent clusters", "Fake adjacent clusters", "Clusters of reconstructed tracks", "Used in Physics", "Protected", "All clusters"}; +static const constexpr char* CLUSTER_TITLES[GPUQA::N_CLS_TYPE] = {"Clusters Pt Distribution / Attachment", "Clusters Pt Distribution / Attachment (relative to all clusters)", "Clusters Pt Distribution / Attachment (integrated)"}; +static const constexpr char* CLUSTER_NAMES_SHORT[GPUQA::N_CLS_HIST] = {"Attached", "Fake", "AttachAdjacent", "FakeAdjacent", "FoundTracks", "Physics", "Protected", "All"}; +static const constexpr char* CLUSTER_TYPES[GPUQA::N_CLS_TYPE] = {"", "Ratio", "Integral"}; +static const constexpr int COLORS_HEX[COLORCOUNT] = {0xB03030, 0x00A000, 0x0000C0, 0x9400D3, 0x19BBBF, 0xF25900, 0x7F7F7F, 0xFFD700, 0x07F707, 0x07F7F7, 0xF08080, 0x000000}; + +static const constexpr int CONFIG_DASHED_MARKERS = 0; + +static const constexpr float AXES_MIN[5] = {-Y_MAX, -Z_MAX, 0.f, -ETA_MAX, PT_MIN}; +static const constexpr float AXES_MAX[5] = {Y_MAX, Z_MAX, 2.f * M_PI, ETA_MAX, PT_MAX}; +static const constexpr int AXIS_BINS[5] = {51, 51, 144, 31, 50}; +static const constexpr int RES_AXIS_BINS[] = {1017, 113}; // Consecutive bin sizes, histograms are binned down until the maximum entry is 50, each bin size should evenly divide its predecessor. +static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; +static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; +static const constexpr float PULL_AXIS = 10.f; + #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" @@ -654,6 +711,11 @@ void GPUQA::RunQA(bool matchOnly) if (ompError) { return; } + if (QA_TIMING) { + GPUInfo("QA Time: Assign Track Labels:\t\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + } + + // fill cluster attachment status for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if (!track.OK()) { @@ -701,6 +763,7 @@ void GPUQA::RunQA(bool matchOnly) } } } + // fill cluster adjacent status for (unsigned int i = 0; i < GetNMCLabels(); i++) { if (mClusterParam[i].attached == 0 && mClusterParam[i].fakeAttached == 0) { int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; @@ -763,16 +826,14 @@ void GPUQA::RunQA(bool matchOnly) } } } + if (QA_TIMING) { + GPUInfo("QA Time: Cluster attach status:\t\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + } if (matchOnly) { return; } - if (QA_TIMING) { - GPUInfo("QA Time: Assign Track Labels:\t\t%6.0f us", timer.GetCurrentElapsedTime() * 1e6); - } - timer.ResetStart(); - // Recompute fNWeightCls (might have changed after merging events into timeframes) for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) { for (unsigned int i = 0; i < GetNMCTracks(iCol); i++) { @@ -793,10 +854,10 @@ void GPUQA::RunQA(bool matchOnly) } } if (QA_TIMING) { - GPUInfo("QA Time: Compute cluster label weights:\t%6.0f us", timer.GetCurrentElapsedTime() * 1e6); + GPUInfo("QA Time: Compute cluster label weights:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); } - timer.ResetStart(); + // Compute MC Track Parameters for MC Tracks GPUCA_OPENMP(parallel for) for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) { for (unsigned int i = 0; i < GetNMCTracks(iCol); i++) { @@ -817,7 +878,10 @@ void GPUQA::RunQA(bool matchOnly) } } } - // Compute MC Track Parameters for MC Tracks + if (QA_TIMING) { + GPUInfo("QA Time: Compute track mc parameters:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + } + // Fill Efficiency Histograms for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) { for (unsigned int i = 0; i < GetNMCTracks(iCol); i++) { @@ -895,9 +959,8 @@ void GPUQA::RunQA(bool matchOnly) } } if (QA_TIMING) { - GPUInfo("QA Time: Fill efficiency histograms:\t%6.0f us", timer.GetCurrentElapsedTime() * 1e6); + GPUInfo("QA Time: Fill efficiency histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); } - timer.ResetStart(); // Fill Resolution Histograms GPUTPCGMPropagator prop; @@ -1030,9 +1093,8 @@ void GPUQA::RunQA(bool matchOnly) } } if (QA_TIMING) { - GPUInfo("QA Time: Fill resolution histograms:\t%6.0f us", timer.GetCurrentElapsedTime() * 1e6); + GPUInfo("QA Time: Fill resolution histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); } - timer.ResetStart(); // Fill cluster histograms for (unsigned int iTrk = 0; iTrk < mTracking->mIOPtrs.nMergedTracks; iTrk++) { @@ -1256,9 +1318,8 @@ void GPUQA::RunQA(bool matchOnly) } if (QA_TIMING) { - GPUInfo("QA Time: Fill cluster histograms:\t%6.0f us", timer.GetCurrentElapsedTime() * 1e6); + GPUInfo("QA Time: Fill cluster histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); } - timer.ResetStart(); } else if (!mConfig.inputHistogramsOnly) { GPUWarning("No MC information available, only running partial TPC QA!"); } @@ -1335,7 +1396,7 @@ void GPUQA::RunQA(bool matchOnly) } if (QA_TIMING) { - GPUInfo("QA Time: Others:\t%6.0f us", timer.GetCurrentElapsedTime() * 1e6); + GPUInfo("QA Time: Others:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); } // Create CSV DumpTrackHits diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index df2e8b0e4a6eb..99cf7f074e260 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -95,6 +95,9 @@ class GPUQA static bool QAAvailable() { return true; } bool IsInitialized() { return mQAInitialized; } + static constexpr int N_CLS_HIST = 8; + static constexpr int N_CLS_TYPE = 3; + private: struct additionalMCParameters { float pt, phi, theta, eta, nWeightCls; @@ -170,14 +173,6 @@ class GPUQA GPUChainTracking* mTracking; const GPUSettingsQA& mConfig; - //-------------------------: Some compile time settings.... - static const constexpr bool PLOT_ROOT = 0; - static const constexpr bool FIX_SCALES = 0; - static const constexpr bool PERF_FIGURE = 0; - static const constexpr float FIXED_SCALES_MIN[5] = {-0.05, -0.05, -0.2, -0.2, -0.5}; - static const constexpr float FIXED_SCALES_MAX[5] = {0.4, 0.7, 5, 3, 6.5}; - static const constexpr float LOG_PT_MIN = -1.; - const char* str_perf_figure_1 = "ALICE Performance 2018/03/20"; // const char* str_perf_figure_2 = "2015, MC pp, #sqrt{s} = 5.02 TeV"; const char* str_perf_figure_2 = "2015, MC Pb-Pb, #sqrt{s_{NN}} = 5.02 TeV"; @@ -217,8 +212,6 @@ class GPUQA TPad* mPPull[7][5]; TLegend* mLPull[6]; - static constexpr int N_CLS_HIST = 8; - static constexpr int N_CLS_TYPE = 3; enum CL_types { CL_attached = 0, CL_fake = 1, CL_att_adj = 2, @@ -254,57 +247,8 @@ class GPUQA std::vector<std::vector<bool>> mGoodTracks; std::vector<std::vector<bool>> mGoodHits; - static constexpr float Y_MAX = 40; - static constexpr float Z_MAX = 100; - static constexpr float PT_MIN = GPUCA_MIN_TRACK_PT_DEFAULT; - static constexpr float PT_MIN2 = 0.1; - static constexpr float PT_MIN_PRIM = 0.1; - static constexpr float PT_MIN_CLUST = GPUCA_MIN_TRACK_PT_DEFAULT; - static constexpr float PT_MAX = 20; - static constexpr float ETA_MAX = 1.5; - static constexpr float ETA_MAX2 = 0.9; - - static constexpr float MIN_WEIGHT_CLS = 40; - static constexpr float FINDABLE_WEIGHT_CLS = 70; - - static constexpr int MC_LABEL_INVALID = -1e9; - - static constexpr bool CLUST_HIST_INT_SUM = false; - - static constexpr const int COLORCOUNT = 12; Color_t* mColorNums; - static const constexpr char* EFF_TYPES[4] = {"Rec", "Clone", "Fake", "All"}; - static const constexpr char* FINDABLE_NAMES[2] = {"", "Findable"}; - static const constexpr char* PRIM_NAMES[2] = {"Prim", "Sec"}; - static const constexpr char* PARAMETER_NAMES[5] = {"Y", "Z", "#Phi", "#lambda", "Relative #it{p}_{T}"}; - static const constexpr char* PARAMETER_NAMES_NATIVE[5] = {"Y", "Z", "sin(#Phi)", "tan(#lambda)", "q/#it{p}_{T} (curvature)"}; - static const constexpr char* VSPARAMETER_NAMES[6] = {"Y", "Z", "Phi", "Eta", "Pt", "Pt_log"}; - static const constexpr char* EFF_NAMES[3] = {"Efficiency", "Clone Rate", "Fake Rate"}; - static const constexpr char* EFFICIENCY_TITLES[4] = {"Efficiency (Primary Tracks, Findable)", "Efficiency (Secondary Tracks, Findable)", "Efficiency (Primary Tracks)", "Efficiency (Secondary Tracks)"}; - static const constexpr double SCALE[5] = {10., 10., 1000., 1000., 100.}; - static const constexpr double SCALE_NATIVE[5] = {10., 10., 1000., 1000., 1.}; - static const constexpr char* XAXIS_TITLES[5] = {"#it{y}_{mc} (cm)", "#it{z}_{mc} (cm)", "#Phi_{mc} (rad)", "#eta_{mc}", "#it{p}_{Tmc} (GeV/#it{c})"}; - static const constexpr char* AXIS_TITLES[5] = {"#it{y}-#it{y}_{mc} (mm) (Resolution)", "#it{z}-#it{z}_{mc} (mm) (Resolution)", "#phi-#phi_{mc} (mrad) (Resolution)", "#lambda-#lambda_{mc} (mrad) (Resolution)", "(#it{p}_{T} - #it{p}_{Tmc}) / #it{p}_{Tmc} (%) (Resolution)"}; - static const constexpr char* AXIS_TITLES_NATIVE[5] = {"#it{y}-#it{y}_{mc} (mm) (Resolution)", "#it{z}-#it{z}_{mc} (mm) (Resolution)", "sin(#phi)-sin(#phi_{mc}) (Resolution)", "tan(#lambda)-tan(#lambda_{mc}) (Resolution)", "q*(q/#it{p}_{T} - q/#it{p}_{Tmc}) (Resolution)"}; - static const constexpr char* AXIS_TITLES_PULL[5] = {"#it{y}-#it{y}_{mc}/#sigma_{y} (Pull)", "#it{z}-#it{z}_{mc}/#sigma_{z} (Pull)", "sin(#phi)-sin(#phi_{mc})/#sigma_{sin(#phi)} (Pull)", "tan(#lambda)-tan(#lambda_{mc})/#sigma_{tan(#lambda)} (Pull)", - "q*(q/#it{p}_{T} - q/#it{p}_{Tmc})/#sigma_{q/#it{p}_{T}} (Pull)"}; - static const constexpr char* CLUSTER_NAMES[N_CLS_HIST] = {"Correctly attached clusters", "Fake attached clusters", "Attached + adjacent clusters", "Fake adjacent clusters", "Clusters of reconstructed tracks", "Used in Physics", "Protected", "All clusters"}; - static const constexpr char* CLUSTER_TITLES[N_CLS_TYPE] = {"Clusters Pt Distribution / Attachment", "Clusters Pt Distribution / Attachment (relative to all clusters)", "Clusters Pt Distribution / Attachment (integrated)"}; - static const constexpr char* CLUSTER_NAMES_SHORT[N_CLS_HIST] = {"Attached", "Fake", "AttachAdjacent", "FakeAdjacent", "FoundTracks", "Physics", "Protected", "All"}; - static const constexpr char* CLUSTER_TYPES[N_CLS_TYPE] = {"", "Ratio", "Integral"}; - static const constexpr int COLORS_HEX[COLORCOUNT] = {0xB03030, 0x00A000, 0x0000C0, 0x9400D3, 0x19BBBF, 0xF25900, 0x7F7F7F, 0xFFD700, 0x07F707, 0x07F7F7, 0xF08080, 0x000000}; - - static const constexpr int CONFIG_DASHED_MARKERS = 0; - - static const constexpr float AXES_MIN[5] = {-Y_MAX, -Z_MAX, 0.f, -ETA_MAX, PT_MIN}; - static const constexpr float AXES_MAX[5] = {Y_MAX, Z_MAX, 2.f * M_PI, ETA_MAX, PT_MAX}; - static const constexpr int AXIS_BINS[5] = {51, 51, 144, 31, 50}; - static const constexpr int RES_AXIS_BINS[] = {1017, 113}; // Consecutive bin sizes, histograms are binned down until the maximum entry is 50, each bin size should evenly divide its predecessor. - static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; - static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; - static const constexpr float PULL_AXIS = 10.f; - int mMCTrackMin = -1, mMCTrackMax = -1; }; From 880563499c240ad3030abaf833cfc2ac5eaab545 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 10 Nov 2020 15:16:35 +0100 Subject: [PATCH 1282/1751] GPU: Move TPC Standalone QA histograms into an std::vector to enable simple shipping of histograms --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 134 +++++++++++++++--------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 23 +++- 2 files changed, 109 insertions(+), 48 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 887998f196f28..f24b97bd6db90 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -154,8 +154,6 @@ static constexpr float ETA_MAX2 = 0.9; static constexpr float MIN_WEIGHT_CLS = 40; static constexpr float FINDABLE_WEIGHT_CLS = 70; -static constexpr int MC_LABEL_INVALID = -1e9; - static constexpr bool CLUST_HIST_INT_SUM = false; static constexpr const int COLORCOUNT = 12; @@ -249,7 +247,36 @@ inline auto& GPUQA::GetMCTrackObj(T& obj, const GPUQA::mcLabelI_t& l) return obj[l.getEventID()][l.getTrackID()]; } -GPUQA::GPUQA(GPUChainTracking* rec) : mTracking(rec), mConfig(GPUQA_GetConfig(rec)) {} +template <> +auto GPUQA::getHist<TH1F>() +{ + return std::make_pair(&mHist1D, &mHist1D_pos); +} +template <> +auto GPUQA::getHist<TH2F>() +{ + return std::make_pair(&mHist2D, &mHist2D_pos); +} +template <> +auto GPUQA::getHist<TH1D>() +{ + return std::make_pair(&mHist1Dd, &mHist1Dd_pos); +} +template <class T, typename... Args> +void GPUQA::createHist(T*& h, Args... args) +{ + const auto& p = getHist<T>(); + p.first->get()->emplace_back(args...); + p.second->emplace_back(&h); + h = &p.first->get()->back(); +} + +GPUQA::GPUQA(GPUChainTracking* rec) : mTracking(rec), mConfig(GPUQA_GetConfig(rec)) +{ + mHist1D.reset(new std::vector<TH1F>); + mHist2D.reset(new std::vector<TH2F>); + mHist1Dd.reset(new std::vector<TH1D>); +} GPUQA::~GPUQA() = default; @@ -338,22 +365,9 @@ void GPUQA::SetMCTrackRange(int min, int max) int GPUQA::GetMCTrackLabel(unsigned int trackId) const { return (trackId >= mTrackMCLabels.size() ? MC_LABEL_INVALID : mTrackMCLabels[trackId].getTrackID()); } -int GPUQA::InitQA() +int GPUQA::InitQACreateHistograms() { - if (mQAInitialized) { - return 1; - } char name[2048], fname[1024]; - - mColorNums = new Color_t[COLORCOUNT]; - for (int i = 0; i < COLORCOUNT; i++) { - float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; - float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; - float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; - TColor* c = new TColor(10000 + i, f1, f2, f3); - mColorNums[i] = c->GetNumber(); - } - // Create Efficiency Histograms for (int i = 0; i < 4; i++) { for (int j = 0; j < 2; j++) { @@ -362,11 +376,10 @@ int GPUQA::InitQA() for (int m = 0; m < 2; m++) { sprintf(name, "%s%s%s%sVs%s", m ? "eff" : "tracks", EFF_TYPES[i], FINDABLE_NAMES[j], PRIM_NAMES[k], VSPARAMETER_NAMES[l]); if (l == 4) { - double* binsPt = CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4]); - mEff[i][j][k][l][m] = new TH1F(name, name, AXIS_BINS[l], binsPt); - delete[] binsPt; + std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], binsPt.get()); } else { - mEff[i][j][k][l][m] = new TH1F(name, name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]); + createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]); } mEff[i][j][k][l][m]->Sumw2(); } @@ -381,23 +394,21 @@ int GPUQA::InitQA() sprintf(name, "rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); sprintf(fname, "mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - double* binsPt = CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4]); - mRes[i][j][0] = new TH1F(name, name, AXIS_BINS[j], binsPt); - mRes[i][j][1] = new TH1F(fname, fname, AXIS_BINS[j], binsPt); - delete[] binsPt; + std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + createHist(mRes[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); + createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); } else { - mRes[i][j][0] = new TH1F(name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); - mRes[i][j][1] = new TH1F(fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mRes[i][j][0], name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); } sprintf(name, "res_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); const float* axis = mConfig.nativeFitResolutions ? RES_AXES_NATIVE : RES_AXES; const int nbins = i == 4 && mConfig.nativeFitResolutions ? (10 * RES_AXIS_BINS[0]) : RES_AXIS_BINS[0]; if (j == 4) { - double* binsPt = CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4]); - mRes2[i][j] = new TH2F(name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], binsPt); - delete[] binsPt; + std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], binsPt.get()); } else { - mRes2[i][j] = new TH2F(name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); } } } @@ -408,21 +419,19 @@ int GPUQA::InitQA() sprintf(name, "pull_rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); sprintf(fname, "pull_mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - double* binsPt = CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4]); - mPull[i][j][0] = new TH1F(name, name, AXIS_BINS[j], binsPt); - mPull[i][j][1] = new TH1F(fname, fname, AXIS_BINS[j], binsPt); - delete[] binsPt; + std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + createHist(mPull[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); + createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); } else { - mPull[i][j][0] = new TH1F(name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); - mPull[i][j][1] = new TH1F(fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mPull[i][j][0], name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); } sprintf(name, "pull_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - double* binsPt = CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4]); - mPull2[i][j] = new TH2F(name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], binsPt); - delete[] binsPt; + std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], binsPt.get()); } else { - mPull2[i][j] = new TH2F(name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); } } } @@ -432,20 +441,51 @@ int GPUQA::InitQA() int ioffset = i >= (2 * N_CLS_HIST - 1) ? (2 * N_CLS_HIST - 1) : i >= N_CLS_HIST ? N_CLS_HIST : 0; int itype = i >= (2 * N_CLS_HIST - 1) ? 2 : i >= N_CLS_HIST ? 1 : 0; sprintf(name, "clusters%s%s", CLUSTER_NAMES_SHORT[i - ioffset], CLUSTER_TYPES[itype]); - double* binsPt = CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX); - mClusters[i] = new TH1D(name, name, AXIS_BINS[4], binsPt); - delete[] binsPt; + std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; + createHist(mClusters[i], name, name, AXIS_BINS[4], binsPt.get()); } { sprintf(name, "nclusters"); - mNCl = new TH1F(name, name, 160, 0, 159); + createHist(mNCl, name, name, 160, 0, 159); } // Create Tracks Histograms { sprintf(name, "tracks"); - double* binsPt = CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX); - mTracks = new TH1F(name, name, AXIS_BINS[4], binsPt); + std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; + createHist(mTracks, name, name, AXIS_BINS[4], binsPt.get()); + } + + for (unsigned int i = 0; i < mHist1D->size(); i++) { + *mHist1D_pos[i] = &(*mHist1D)[i]; + } + for (unsigned int i = 0; i < mHist2D->size(); i++) { + *mHist2D_pos[i] = &(*mHist2D)[i]; + } + for (unsigned int i = 0; i < mHist1Dd->size(); i++) { + *mHist1Dd_pos[i] = &(*mHist1Dd)[i]; + } + + return 0; +} + +int GPUQA::InitQA() +{ + if (mQAInitialized) { + return 1; + } + + mColorNums = new Color_t[COLORCOUNT]; + for (int i = 0; i < COLORCOUNT; i++) { + float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; + float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; + float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; + TColor* c = new TColor(10000 + i, f1, f2, f3); + mColorNums[i] = c->GetNumber(); + } + + if (InitQACreateHistograms()) { + return 1; } mkdir("plots", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 99cf7f074e260..c9a5aa18badf2 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -60,7 +60,8 @@ class GPUQA #include "GPUTPCDef.h" #include <cmath> - +#include <vector> +#include <memory> #ifdef GPUCA_TPC_GEOMETRY_O2 #include <gsl/span> #endif @@ -80,6 +81,7 @@ class GPUTPCMCInfo; class GPUQA { public: + GPUQA(); GPUQA(GPUChainTracking* rec); ~GPUQA(); @@ -95,9 +97,15 @@ class GPUQA static bool QAAvailable() { return true; } bool IsInitialized() { return mQAInitialized; } + const std::vector<TH1F>& getHistograms1D() const { return mHist1D; } + const std::vector<TH2F>& getHistograms2D() const { return mHist2D; } + const std::vector<TH1D>& getHistograms1Dd() const { return mHist1Dd; } + static constexpr int N_CLS_HIST = 8; static constexpr int N_CLS_TYPE = 3; + static constexpr int MC_LABEL_INVALID = -1e9; + private: struct additionalMCParameters { float pt, phi, theta, eta, nWeightCls; @@ -108,6 +116,8 @@ class GPUQA float pt; }; + int InitQACreateHistograms(); + void SetAxisSize(TH1F* e); void SetLegend(TLegend* l); double* CreateLogAxis(int nbins, float xmin, float xmax); @@ -240,6 +250,17 @@ class GPUQA TPad* mPNCl; TLegend* mLNCl; + std::unique_ptr<std::vector<TH1F>> mHist1D{}; + std::unique_ptr<std::vector<TH2F>> mHist2D{}; + std::unique_ptr<std::vector<TH1D>> mHist1Dd{}; + std::vector<TH1F**> mHist1D_pos{}; + std::vector<TH2F**> mHist2D_pos{}; + std::vector<TH1D**> mHist1Dd_pos{}; + template <class T> + auto getHist(); + template <class T, typename... Args> + void createHist(T*& h, Args... args); + int mNEvents = 0; bool mQAInitialized = false; std::vector<std::vector<int>> mcEffBuffer; From 1cbac88e61bed8b8d32a6785686d3da4ea0e10bb Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 10 Nov 2020 18:00:28 +0100 Subject: [PATCH 1283/1751] GPU: Add TPC Standalone QA mode for producing histograms for QC without writing them to file --- .../Standalone/display/GPUDisplay.cxx | 8 +- .../Standalone/display/GPUDisplay.h | 4 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 348 ++++++++++-------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 13 +- 4 files changed, 212 insertions(+), 161 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 1a5c77b0a5ecb..7aa72568bac25 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -84,12 +84,12 @@ namespace GPUCA_NAMESPACE::gpu extern GPUSettingsStandalone configStandalone; } #endif -static const GPUSettingsDisplay& GPUDisplay_GetConfig(GPUChainTracking* rec) +static const GPUSettingsDisplay& GPUDisplay_GetConfig(GPUChainTracking* chain) { #if !defined(GPUCA_STANDALONE) static GPUSettingsDisplay defaultConfig; - if (rec->mConfigDisplay) { - return *((const GPUSettingsDisplay*)rec->mConfigDisplay); + if (chain->mConfigDisplay) { + return *((const GPUSettingsDisplay*)chain->mConfigDisplay); } else { return defaultConfig; } @@ -99,7 +99,7 @@ static const GPUSettingsDisplay& GPUDisplay_GetConfig(GPUChainTracking* rec) #endif } -GPUDisplay::GPUDisplay(GPUDisplayBackend* backend, GPUChainTracking* rec, GPUQA* qa) : mBackend(backend), mChain(rec), mConfig(GPUDisplay_GetConfig(rec)), mQA(qa), mMerger(rec->GetTPCMerger()) { backend->mDisplay = this; } +GPUDisplay::GPUDisplay(GPUDisplayBackend* backend, GPUChainTracking* chain, GPUQA* qa) : mBackend(backend), mChain(chain), mConfig(GPUDisplay_GetConfig(chain)), mQA(qa), mMerger(chain->GetTPCMerger()) { backend->mDisplay = this; } const GPUParam& GPUDisplay::param() { return mChain->GetParam(); } const GPUTPCTracker& GPUDisplay::sliceTracker(int iSlice) { return mChain->GetTPCSliceTrackers()[iSlice]; } diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.h b/GPU/GPUTracking/Standalone/display/GPUDisplay.h index 8f0efea771780..565b3af52c2e8 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.h @@ -53,7 +53,7 @@ namespace gpu class GPUDisplay { public: - GPUDisplay(GPUDisplayBackend* backend, GPUChainTracking* rec, GPUQA* qa) {} + GPUDisplay(GPUDisplayBackend* backend, GPUChainTracking* chain, GPUQA* qa) {} ~GPUDisplay() = default; GPUDisplay(const GPUDisplay&) = delete; @@ -94,7 +94,7 @@ struct GPUParam; class GPUDisplay { public: - GPUDisplay(GPUDisplayBackend* backend, GPUChainTracking* rec, GPUQA* qa); + GPUDisplay(GPUDisplayBackend* backend, GPUChainTracking* chain, GPUQA* qa); ~GPUDisplay() = default; GPUDisplay(const GPUDisplay&) = delete; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index f24b97bd6db90..91cf458ba05ac 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -119,12 +119,12 @@ namespace GPUCA_NAMESPACE::gpu extern GPUSettingsStandalone configStandalone; } #endif -static const GPUSettingsQA& GPUQA_GetConfig(GPUChainTracking* rec) +static const GPUSettingsQA& GPUQA_GetConfig(GPUChainTracking* chain) { #if !defined(GPUCA_STANDALONE) static GPUSettingsQA defaultConfig; - if (rec->mConfigQA) { - return *((const GPUSettingsQA*)rec->mConfigQA); + if (chain && chain->mConfigQA) { + return *((const GPUSettingsQA*)chain->mConfigQA); } else { return defaultConfig; } @@ -189,6 +189,8 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; +static TCanvas cfit; + #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" @@ -271,11 +273,12 @@ void GPUQA::createHist(T*& h, Args... args) h = &p.first->get()->back(); } -GPUQA::GPUQA(GPUChainTracking* rec) : mTracking(rec), mConfig(GPUQA_GetConfig(rec)) +GPUQA::GPUQA(GPUChainTracking* chain) : mTracking(chain), mConfig(GPUQA_GetConfig(chain)) { mHist1D.reset(new std::vector<TH1F>); mHist2D.reset(new std::vector<TH2F>); mHist1Dd.reset(new std::vector<TH1D>); + mRunForQC = chain == nullptr; } GPUQA::~GPUQA() = default; @@ -475,7 +478,7 @@ int GPUQA::InitQA() return 1; } - mColorNums = new Color_t[COLORCOUNT]; + mColorNums.resize(COLORCOUNT); for (int i = 0; i < COLORCOUNT; i++) { float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; @@ -488,11 +491,13 @@ int GPUQA::InitQA() return 1; } - mkdir("plots", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (!mRunForQC) { + mkdir("plots", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + } #ifdef GPUCA_O2_LIB - TFile* fileSim = new TFile(o2::base::NameConf::getMCKinematicsFileName("o2sim").c_str()); - TTree* treeSim = (TTree*)fileSim->Get("o2sim"); + TFile fileSim(o2::base::NameConf::getMCKinematicsFileName("o2sim").c_str()); + TTree* treeSim = (TTree*)fileSim.Get("o2sim"); std::vector<o2::MCTrack>* tracksX; std::vector<o2::TrackReference>* trackRefsX; if (treeSim == nullptr) { @@ -567,8 +572,7 @@ int GPUQA::InitQA() } } - fileSim->Close(); - delete fileSim; + fileSim.Close(); #endif if (mConfig.matchMCLabels.size()) { @@ -1605,148 +1609,150 @@ int GPUQA::DrawQAHistograms() tout = new TFile(mConfig.output.c_str(), "RECREATE"); } - float legendSpacingString = 0.025; - for (int i = 0; i < ConfigNumInputs; i++) { - GetName(fname, i); - if (strlen(fname) * 0.006 > legendSpacingString) { - legendSpacingString = strlen(fname) * 0.006; + if (!mRunForQC) { + float legendSpacingString = 0.025; + for (int i = 0; i < ConfigNumInputs; i++) { + GetName(fname, i); + if (strlen(fname) * 0.006 > legendSpacingString) { + legendSpacingString = strlen(fname) * 0.006; + } } - } - // Create Canvas / Pads for Efficiency Histograms - for (int ii = 0; ii < 6; ii++) { - int i = ii == 5 ? 4 : ii; - sprintf(fname, "ceff_%d", ii); - sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); - mCEff[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); - mCEff[ii]->cd(); - float dy = 1. / 2.; - mPEff[ii][0] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); - mPEff[ii][0]->Draw(); - mPEff[ii][0]->SetRightMargin(0.04); - mPEff[ii][1] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); - mPEff[ii][1]->Draw(); - mPEff[ii][1]->SetRightMargin(0.04); - mPEff[ii][2] = new TPad("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); - mPEff[ii][2]->Draw(); - mPEff[ii][2]->SetRightMargin(0.04); - mPEff[ii][3] = new TPad("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); - mPEff[ii][3]->Draw(); - mPEff[ii][3]->SetRightMargin(0.04); - mLEff[ii] = new TLegend(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); - SetLegend(mLEff[ii]); - } - - // Create Canvas / Pads for Resolution Histograms - for (int ii = 0; ii < 7; ii++) { - int i = ii == 5 ? 4 : ii; - sprintf(fname, "cres_%d", ii); - if (ii == 6) { - sprintf(name, "Integral Resolution"); - } else { - sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); - } - mCRes[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); - mCRes[ii]->cd(); - gStyle->SetOptFit(1); - - float dy = 1. / 2.; - mPRes[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); - mPRes[ii][3]->Draw(); - mPRes[ii][3]->SetRightMargin(0.04); - mPRes[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); - mPRes[ii][4]->Draw(); - mPRes[ii][4]->SetRightMargin(0.04); - mPRes[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); - mPRes[ii][0]->Draw(); - mPRes[ii][0]->SetRightMargin(0.04); - mPRes[ii][0]->SetLeftMargin(0.15); - mPRes[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); - mPRes[ii][1]->Draw(); - mPRes[ii][1]->SetRightMargin(0.04); - mPRes[ii][1]->SetLeftMargin(0.135); - mPRes[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); - mPRes[ii][2]->Draw(); - mPRes[ii][2]->SetRightMargin(0.06); - mPRes[ii][2]->SetLeftMargin(0.135); - if (ii < 6) { - mLRes[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); - SetLegend(mLRes[ii]); + // Create Canvas / Pads for Efficiency Histograms + for (int ii = 0; ii < 6; ii++) { + int i = ii == 5 ? 4 : ii; + sprintf(fname, "ceff_%d", ii); + sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); + mCEff[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCEff[ii]->cd(); + float dy = 1. / 2.; + mPEff[ii][0] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPEff[ii][0]->Draw(); + mPEff[ii][0]->SetRightMargin(0.04); + mPEff[ii][1] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPEff[ii][1]->Draw(); + mPEff[ii][1]->SetRightMargin(0.04); + mPEff[ii][2] = new TPad("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); + mPEff[ii][2]->Draw(); + mPEff[ii][2]->SetRightMargin(0.04); + mPEff[ii][3] = new TPad("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); + mPEff[ii][3]->Draw(); + mPEff[ii][3]->SetRightMargin(0.04); + mLEff[ii] = new TLegend(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); + SetLegend(mLEff[ii]); } - } - // Create Canvas / Pads for Pull Histograms - for (int ii = 0; ii < 7; ii++) { - int i = ii == 5 ? 4 : ii; - sprintf(fname, "cpull_%d", ii); - if (ii == 6) { - sprintf(name, "Integral Pull"); - } else { - sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); - } - mCPull[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); - mCPull[ii]->cd(); - gStyle->SetOptFit(1); - - float dy = 1. / 2.; - mPPull[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); - mPPull[ii][3]->Draw(); - mPPull[ii][3]->SetRightMargin(0.04); - mPPull[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); - mPPull[ii][4]->Draw(); - mPPull[ii][4]->SetRightMargin(0.04); - mPPull[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); - mPPull[ii][0]->Draw(); - mPPull[ii][0]->SetRightMargin(0.04); - mPPull[ii][0]->SetLeftMargin(0.15); - mPPull[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); - mPPull[ii][1]->Draw(); - mPPull[ii][1]->SetRightMargin(0.04); - mPPull[ii][1]->SetLeftMargin(0.135); - mPPull[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); - mPPull[ii][2]->Draw(); - mPPull[ii][2]->SetRightMargin(0.06); - mPPull[ii][2]->SetLeftMargin(0.135); - if (ii < 6) { - mLPull[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); - SetLegend(mLPull[ii]); + // Create Canvas / Pads for Resolution Histograms + for (int ii = 0; ii < 7; ii++) { + int i = ii == 5 ? 4 : ii; + sprintf(fname, "cres_%d", ii); + if (ii == 6) { + sprintf(name, "Integral Resolution"); + } else { + sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); + } + mCRes[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCRes[ii]->cd(); + gStyle->SetOptFit(1); + + float dy = 1. / 2.; + mPRes[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPRes[ii][3]->Draw(); + mPRes[ii][3]->SetRightMargin(0.04); + mPRes[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPRes[ii][4]->Draw(); + mPRes[ii][4]->SetRightMargin(0.04); + mPRes[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPRes[ii][0]->Draw(); + mPRes[ii][0]->SetRightMargin(0.04); + mPRes[ii][0]->SetLeftMargin(0.15); + mPRes[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPRes[ii][1]->Draw(); + mPRes[ii][1]->SetRightMargin(0.04); + mPRes[ii][1]->SetLeftMargin(0.135); + mPRes[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPRes[ii][2]->Draw(); + mPRes[ii][2]->SetRightMargin(0.06); + mPRes[ii][2]->SetLeftMargin(0.135); + if (ii < 6) { + mLRes[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + SetLegend(mLRes[ii]); + } } - } - // Create Canvas for Cluster Histos - for (int i = 0; i < 3; i++) { - sprintf(fname, "cclust_%d", i); - mCClust[i] = new TCanvas(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); - mCClust[i]->cd(); - mPClust[i] = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); - mPClust[i]->Draw(); - float y1 = i != 1 ? 0.77 : 0.27, y2 = i != 1 ? 0.9 : 0.42; - mLClust[i] = new TLegend(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); - SetLegend(mLClust[i]); - } + // Create Canvas / Pads for Pull Histograms + for (int ii = 0; ii < 7; ii++) { + int i = ii == 5 ? 4 : ii; + sprintf(fname, "cpull_%d", ii); + if (ii == 6) { + sprintf(name, "Integral Pull"); + } else { + sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); + } + mCPull[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCPull[ii]->cd(); + gStyle->SetOptFit(1); + + float dy = 1. / 2.; + mPPull[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPPull[ii][3]->Draw(); + mPPull[ii][3]->SetRightMargin(0.04); + mPPull[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPPull[ii][4]->Draw(); + mPPull[ii][4]->SetRightMargin(0.04); + mPPull[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPPull[ii][0]->Draw(); + mPPull[ii][0]->SetRightMargin(0.04); + mPPull[ii][0]->SetLeftMargin(0.15); + mPPull[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPPull[ii][1]->Draw(); + mPPull[ii][1]->SetRightMargin(0.04); + mPPull[ii][1]->SetLeftMargin(0.135); + mPPull[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPPull[ii][2]->Draw(); + mPPull[ii][2]->SetRightMargin(0.06); + mPPull[ii][2]->SetLeftMargin(0.135); + if (ii < 6) { + mLPull[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + SetLegend(mLPull[ii]); + } + } - // Create Canvas for other histos - { - mCTracks = new TCanvas("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); - mCTracks->cd(); - mPTracks = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); - mPTracks->Draw(); - mLTracks = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); - SetLegend(mLTracks); + // Create Canvas for Cluster Histos + for (int i = 0; i < 3; i++) { + sprintf(fname, "cclust_%d", i); + mCClust[i] = new TCanvas(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); + mCClust[i]->cd(); + mPClust[i] = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPClust[i]->Draw(); + float y1 = i != 1 ? 0.77 : 0.27, y2 = i != 1 ? 0.9 : 0.42; + mLClust[i] = new TLegend(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); + SetLegend(mLClust[i]); + } - mCNCl = new TCanvas("cncl", "Number of clusters per track", 0, 0, 700, 700. * 2. / 3.); - mCNCl->cd(); - mPNCl = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); - mPNCl->Draw(); - mLNCl = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); - SetLegend(mLNCl); - } + // Create Canvas for other histos + { + mCTracks = new TCanvas("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); + mCTracks->cd(); + mPTracks = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPTracks->Draw(); + mLTracks = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + SetLegend(mLTracks); + + mCNCl = new TCanvas("cncl", "Number of clusters per track", 0, 0, 700, 700. * 2. / 3.); + mCNCl->cd(); + mPNCl = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPNCl->Draw(); + mLNCl = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + SetLegend(mLNCl); + } - if (!mConfig.inputHistogramsOnly) { - GPUInfo("QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int)mEff[3][1][0][0][0]->GetEntries(), (int)mEff[3][1][0][3][0]->GetEntries(), (int)mEff[3][1][0][4][0]->GetEntries(), - mEff[0][0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0][0]->GetSumOfWeights()), (int)mEff[3][1][1][0][0]->GetEntries(), (int)mEff[3][1][1][3][0]->GetEntries(), - (int)mEff[3][1][1][4][0]->GetEntries(), mEff[0][0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0][0]->GetSumOfWeights()), mEff[0][1][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0][0]->GetSumOfWeights()), (int)mRes2[0][0]->GetEntries(), - (int)mRes2[0][3]->GetEntries(), (int)mRes2[0][4]->GetEntries()); + if (!mConfig.inputHistogramsOnly) { + GPUInfo("QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int)mEff[3][1][0][0][0]->GetEntries(), (int)mEff[3][1][0][3][0]->GetEntries(), (int)mEff[3][1][0][4][0]->GetEntries(), + mEff[0][0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0][0]->GetSumOfWeights()), (int)mEff[3][1][1][0][0]->GetEntries(), (int)mEff[3][1][1][3][0]->GetEntries(), + (int)mEff[3][1][1][4][0]->GetEntries(), mEff[0][0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0][0]->GetSumOfWeights()), mEff[0][1][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0][0]->GetSumOfWeights()), (int)mRes2[0][0]->GetEntries(), + (int)mRes2[0][3]->GetEntries(), (int)mRes2[0][4]->GetEntries()); + } } // Process / Draw Efficiency Histograms @@ -1795,6 +1801,9 @@ int GPUQA::DrawQAHistograms() e->SetLineColor(mColorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); SetAxisSize(e); + if (mRunForQC) { + continue; + } e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -1805,10 +1814,17 @@ int GPUQA::DrawQAHistograms() mPEff[ii][j]->SetLogx(); } } + if (mRunForQC) { + continue; + } mCEff[ii]->cd(); ChangePadTitleSize(mPEff[ii][j], 0.056); } } + if (mRunForQC) { + continue; + } + mLEff[ii]->Draw(); doPerfFigure(0.2, 0.295, 0.025); @@ -1834,8 +1850,9 @@ int GPUQA::DrawQAHistograms() TPad* pad = p ? mPPull[ii][j] : mPRes[ii][j]; if (!mConfig.inputHistogramsOnly && ii != 5) { - TCanvas cfit; - cfit.cd(); + if (!mRunForQC) { + cfit.cd(); + } TAxis* axis = src->GetYaxis(); int nBins = axis->GetNbins(); @@ -1920,8 +1937,9 @@ int GPUQA::DrawQAHistograms() dstIntegral->SetName(fname); dstIntegral->SetTitle(name); } - pad->cd(); - + if (!mRunForQC) { + pad->cd(); + } int numColor = 0; float tmpMax = -1000.; float tmpMin = 1000.; @@ -1999,6 +2017,10 @@ int GPUQA::DrawQAHistograms() } else if (j < 3) { e->GetYaxis()->SetTitleOffset(1.4); } + if (mRunForQC) { + continue; + } + e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -2011,6 +2033,10 @@ int GPUQA::DrawQAHistograms() } } } + if (mRunForQC) { + continue; + } + if (ii == 5) { pad->SetLogx(); } @@ -2019,6 +2045,10 @@ int GPUQA::DrawQAHistograms() ChangePadTitleSize(pad, 0.056); } } + if (mRunForQC) { + continue; + } + leg->Draw(); doPerfFigure(0.2, 0.295, 0.025); @@ -2068,10 +2098,18 @@ int GPUQA::DrawQAHistograms() if (tout && !mConfig.inputHistogramsOnly && k == 0) { e->Write(); } + if (mRunForQC) { + continue; + } + e->Draw(k == 0 ? "" : "same"); } can->cd(); } + if (mRunForQC) { + continue; + } + can->Print(p ? "plots/pull_integral.pdf" : "plots/res_integral.pdf"); if (mConfig.writeRootFiles) { can->Print(p ? "plots/pull_integral.root" : "plots/res_integral.root"); @@ -2111,7 +2149,7 @@ int GPUQA::DrawQAHistograms() if (!mcAvail) { counts[N_CLS_HIST - 1] = mClusterCounts.nTotal; } - if (counts[N_CLS_HIST - 1]) { + if (counts[N_CLS_HIST - 1] && !mRunForQC) { if (mcAvail) { for (int i = 0; i < N_CLS_HIST; i++) { printf("\t%35s: %'12llu (%6.2f%%)\n", CLUSTER_NAMES[i], counts[i], 100.f * counts[i] / counts[N_CLS_HIST - 1]); @@ -2220,6 +2258,10 @@ int GPUQA::DrawQAHistograms() if (i == 0) { e->GetXaxis()->SetRange(2, AXIS_BINS[4]); } + if (mRunForQC) { + continue; + } + e->Draw(j == end - 1 && k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%s%s", fname, CLUSTER_NAMES[j - begin]); @@ -2230,9 +2272,17 @@ int GPUQA::DrawQAHistograms() TH1* e = reinterpret_cast<TH1F*>(mClusters[begin + CL_att_adj]->Clone()); e->Add(mClusters[begin + CL_prot], -1); e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + if (mRunForQC) { + continue; + } + e->Draw("same"); mLClust[i]->AddEntry(e, "Removed", "l"); } + if (mRunForQC) { + continue; + } + mLClust[i]->Draw(); doPerfFigure(i != 2 ? 0.37 : 0.6, 0.295, 0.030); @@ -2246,7 +2296,7 @@ int GPUQA::DrawQAHistograms() } // Process track histograms - { + if (!mRunForQC) { float tmpMax = 0.; for (int k = 0; k < ConfigNumInputs; k++) { TH1F* e = mTracks; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index c9a5aa18badf2..e37310af68fc1 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -38,7 +38,7 @@ class GPUChainTracking; class GPUQA { public: - GPUQA(GPUChainTracking* rec) {} + GPUQA(GPUChainTracking* chain) {} ~GPUQA() = default; int InitQA() { return 1; } @@ -82,7 +82,7 @@ class GPUQA { public: GPUQA(); - GPUQA(GPUChainTracking* rec); + GPUQA(GPUChainTracking* chain); ~GPUQA(); int InitQA(); @@ -97,9 +97,9 @@ class GPUQA static bool QAAvailable() { return true; } bool IsInitialized() { return mQAInitialized; } - const std::vector<TH1F>& getHistograms1D() const { return mHist1D; } - const std::vector<TH2F>& getHistograms2D() const { return mHist2D; } - const std::vector<TH1D>& getHistograms1Dd() const { return mHist1Dd; } + const std::vector<TH1F>& getHistograms1D() const { return *mHist1D; } + const std::vector<TH2F>& getHistograms2D() const { return *mHist2D; } + const std::vector<TH1D>& getHistograms1Dd() const { return *mHist1Dd; } static constexpr int N_CLS_HIST = 8; static constexpr int N_CLS_TYPE = 3; @@ -182,6 +182,7 @@ class GPUQA GPUChainTracking* mTracking; const GPUSettingsQA& mConfig; + bool mRunForQC; const char* str_perf_figure_1 = "ALICE Performance 2018/03/20"; // const char* str_perf_figure_2 = "2015, MC pp, #sqrt{s} = 5.02 TeV"; @@ -268,7 +269,7 @@ class GPUQA std::vector<std::vector<bool>> mGoodTracks; std::vector<std::vector<bool>> mGoodHits; - Color_t* mColorNums; + std::vector<Color_t> mColorNums; int mMCTrackMin = -1, mMCTrackMax = -1; }; From feb7ae423d604894b43054ac972074ca5e2b122d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 10 Nov 2020 19:21:10 +0100 Subject: [PATCH 1284/1751] TPC Workflow: Add option to send QA data as external input to QC --- .../include/TPCWorkflow/CATrackerSpec.h | 5 ++++ .../include/TPCWorkflow/RecoWorkflow.h | 1 + Detectors/TPC/workflow/src/CATrackerSpec.cxx | 26 +++++++++++++++++++ Detectors/TPC/workflow/src/RecoWorkflow.cxx | 3 ++- .../TPC/workflow/src/tpc-reco-workflow.cxx | 2 +- GPU/GPUTracking/Base/GPUSettingsList.h | 3 ++- GPU/GPUTracking/Interface/GPUO2Interface.cxx | 6 +++++ .../Interface/GPUO2InterfaceConfiguration.h | 11 ++++++++ GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 6 ++--- 9 files changed, 57 insertions(+), 6 deletions(-) diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h index 0be54aaf59818..8f2195dc9eecc 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h @@ -41,6 +41,7 @@ enum struct Operation { OutputCAClusters, // publish the clusters produced by CA clusterer OutputCompClusters, // publish CompClusters container OutputCompClustersFlat, // publish CompClusters container + OutputQA, // Ship QA histograms to QC ProcessMC, // process MC labels SendClustersPerSector, // Send clusters and clusters mc labels per sector Noop, // skip argument on the constructor @@ -88,6 +89,9 @@ struct Config { case Operation::OutputCAClusters: outputCAClusters = true; break; + case Operation::OutputQA: + outputQA = true; + break; case Operation::ProcessMC: processMC = true; break; @@ -116,6 +120,7 @@ struct Config { bool outputCompClusters = false; bool outputCompClustersFlat = false; bool outputCAClusters = false; + bool outputQA = false; bool processMC = false; bool sendClustersPerSector = false; }; diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h b/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h index 100a35e82c0bc..d4140736b0985 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h @@ -60,6 +60,7 @@ enum struct OutputType { Digits, DisableWriter, SendClustersPerSector, ZSRaw, + QA, }; using CompletionPolicyData = std::vector<framework::InputSpec>; diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index bd7597b7a1a1b..97a196aadbc60 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -65,6 +65,10 @@ #include "GPUReconstructionConvert.h" #include "DetectorsRaw/RDHUtils.h" #include <TStopwatch.h> +#include <TObjArray.h> +#include <TH1F.h> +#include <TH2F.h> +#include <TH1D.h> using namespace o2::framework; using namespace o2::header; @@ -154,6 +158,12 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config LOG(INFO) << "GPU device number selected from pipeline id: " << myId << " / " << idMax; } config.configProcessing.runMC = specconfig.processMC; + if (specconfig.outputQA) { + if (!config.configProcessing.runQA) { + config.configQA.forQC = true; + } + config.configProcessing.runQA = true; + } config.configReconstruction.NWaysOuter = true; config.configInterface.outputToExternalBuffers = true; @@ -689,6 +699,19 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } } } + if (specconfig.outputQA) { + TObjArray out; + for (unsigned int i = 0; i < outputRegions.qa.hist1->size(); i++) { + out.Add((TObject*)&(*outputRegions.qa.hist1)[i]); // FIXME: Fundamentally broken, we cannot add the const object, but QC doesn't accept the std::vector + } + for (unsigned int i = 0; i < outputRegions.qa.hist2->size(); i++) { + out.Add((TObject*)&(*outputRegions.qa.hist2)[i]); + } + for (unsigned int i = 0; i < outputRegions.qa.hist3->size(); i++) { + out.Add((TObject*)&(*outputRegions.qa.hist3)[i]); + } + pc.outputs().snapshot({gDataOriginTPC, "TRACKINGQA", 0, Lifetime::Timeframe}, out); + } timer.Stop(); LOG(INFO) << "TPC CATracker time for this TF " << timer.CpuTime() - cput << " s"; }; @@ -789,6 +812,9 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } } } + if (specconfig.outputQA) { + outputSpecs.emplace_back(gDataOriginTPC, "TRACKINGQA", 0, Lifetime::Timeframe); + } return std::move(outputSpecs); }; diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 8c850f3b8c03e..43116540ffed7 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -85,7 +85,7 @@ const std::unordered_map<std::string, OutputType> OutputMap{ {"disable-writer", OutputType::DisableWriter}, {"send-clusters-per-sector", OutputType::SendClustersPerSector}, {"zsraw", OutputType::ZSRaw}, -}; + {"qa", OutputType::QA}}; framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vector<int> const& tpcSectors, std::vector<int> const& laneConfiguration, bool propagateMC, unsigned nLanes, std::string const& cfgInput, std::string const& cfgOutput, @@ -442,6 +442,7 @@ framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vecto produceCompClusters ? ca::Operation::OutputCompClusters : ca::Operation::Noop, runClusterEncoder ? ca::Operation::OutputCompClustersFlat : ca::Operation::Noop, isEnabled(OutputType::SendClustersPerSector) ? ca::Operation::SendClustersPerSector : ca::Operation::Noop, + isEnabled(OutputType::QA) ? ca::Operation::OutputQA : ca::Operation::Noop, isEnabled(OutputType::Clusters) && (caClusterer || decompressTPC) ? ca::Operation::OutputCAClusters : ca::Operation::Noop, }, tpcSectors)); diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index 4f084afa6f527..b10b2c08f5293 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -46,7 +46,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) std::vector<ConfigParamSpec> options{ {"input-type", VariantType::String, "digits", {"digitizer, digits, zsraw, clustershw, clustersnative, compressed-clusters, compressed-clusters-ctf"}}, - {"output-type", VariantType::String, "tracks", {"digits, zsraw, clustershw, clustersnative, tracks, compressed-clusters, encoded-clusters, disable-writer, send-clusters-per-sector"}}, + {"output-type", VariantType::String, "tracks", {"digits, zsraw, clustershw, clustersnative, tracks, compressed-clusters, encoded-clusters, disable-writer, send-clusters-per-sector, qa"}}, {"no-ca-clusterer", VariantType::Bool, false, {"Use HardwareClusterer instead of clusterer of GPUCATracking"}}, {"disable-mc", VariantType::Bool, false, {"disable sending of MC information"}}, //{"tpc-sectors", VariantType::String, "0-35", {"TPC sector range, e.g. 5-7,8,9"}}, diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 572cfc27636b8..c116d67c5ceb1 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -117,7 +117,6 @@ AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan i AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") AddOption(runQA, bool, false, "qa", 'q', "Enable tracking QA", message("Running QA: %s")) -AddOption(QAnoMC, bool, false, "", 0, "Force running QA without MC labels even if present") AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") AddOption(forceMemoryPoolSize, unsigned long, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ul)) AddOption(forceHostMemoryPoolSize, unsigned long, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ul)) @@ -160,6 +159,8 @@ AddOption(writeMCLabels, bool, false, "", 0, "Store mc labels to file for later AddOptionVec(matchMCLabels, const char*, "", 0, "Read labels from files and match them, only process tracks where labels differ") AddOption(matchDisplayMinPt, float, 0, "", 0, "Minimum Pt of a matched track to be displayed") AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") +AddOption(noMC, bool, false, "", 0, "Force running QA without MC labels even if present") +AddOption(forQC, bool, false, "", 0, "Do not write output files but ship histograms for QC") AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 4c65f08a9aaa7..b356e5ba0f32c 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -18,6 +18,7 @@ #include "GPUOutputControl.h" #include "GPUO2InterfaceConfiguration.h" #include "GPUParam.inc" +#include "GPUQA.h" #include <iostream> #include <fstream> #ifdef WITH_OPENMP @@ -159,6 +160,11 @@ int GPUTPCO2Interface::RunTracking(GPUTrackingInOutPointers* data, GPUInterfaceO outputs->clustersNative.size = mOutputClustersNative->EndOfSpace ? 0 : (mChain->mIOPtrs.clustersNative->nClustersTotal * sizeof(*mChain->mIOPtrs.clustersNative->clustersLinear)); outputs->tpcTracks.size = mOutputCompressedClusters->EndOfSpace ? 0 : (size_t)((char*)mOutputCompressedClusters->OutputPtr - (char*)mOutputCompressedClusters->OutputBase); } + if (mConfig->configQA.forQC) { + outputs->qa.hist1 = &mChain->GetQA()->getHistograms1D(); + outputs->qa.hist2 = &mChain->GetQA()->getHistograms2D(); + outputs->qa.hist3 = &mChain->GetQA()->getHistograms1Dd(); + } *data = mChain->mIOPtrs; nEvent++; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h index eac5c9d7363ec..b3ca1cabe5ab0 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h @@ -34,6 +34,10 @@ #include "GPUHostDataTypes.h" #include "DataFormatsTPC/Constants.h" +class TH1F; +class TH1D; +class TH2F; + namespace o2 { namespace tpc @@ -57,11 +61,18 @@ struct GPUInterfaceOutputRegion { std::function<void*(size_t)> allocator = nullptr; }; +struct GPUInterfaceQAOutputs { + const std::vector<TH1F>* hist1; + const std::vector<TH2F>* hist2; + const std::vector<TH1D>* hist3; +}; + struct GPUInterfaceOutputs { GPUInterfaceOutputRegion compressedClusters; GPUInterfaceOutputRegion clustersNative; GPUInterfaceOutputRegion tpcTracks; GPUInterfaceOutputRegion clusterLabels; + GPUInterfaceQAOutputs qa; }; // Full configuration structure with all available settings of GPU... diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 91cf458ba05ac..8d11f67b264ce 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -214,7 +214,7 @@ inline int GPUQA::GetMCLabelCol(unsigned int i, unsigned int j) { return mTracki inline float GPUQA::GetMCLabelWeight(unsigned int i, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return 1; } -inline bool GPUQA::mcPresent() { return !mTracking->GetProcessingSettings().QAnoMC && mTracking->mIOPtrs.clustersNative->clustersMCTruth && mNColTracks.size(); } +inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking->mIOPtrs.clustersNative->clustersMCTruth && mNColTracks.size(); } #define TRACK_EXPECTED_REFERENCE_X 78 #else inline GPUQA::mcLabelI_t::mcLabelI_t(const GPUQA::mcLabel_t& l) : track(l.fMCID) @@ -240,7 +240,7 @@ inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return label.fWeight; } inline int GPUQA::FakeLabelID(int id) { return id < 0 ? id : (-2 - id); } inline int GPUQA::AbsLabelID(int id) { return id >= 0 ? id : (-id - 2); } -inline bool GPUQA::mcPresent() { return !mTracking->GetProcessingSettings().QAnoMC && GetNMCLabels() && GetNMCTracks(0); } +inline bool GPUQA::mcPresent() { return !mConfig.noMC && GetNMCLabels() && GetNMCTracks(0); } #define TRACK_EXPECTED_REFERENCE_X 81 #endif template <class T> @@ -278,7 +278,7 @@ GPUQA::GPUQA(GPUChainTracking* chain) : mTracking(chain), mConfig(GPUQA_GetConfi mHist1D.reset(new std::vector<TH1F>); mHist2D.reset(new std::vector<TH2F>); mHist1Dd.reset(new std::vector<TH1D>); - mRunForQC = chain == nullptr; + mRunForQC = chain == nullptr || mConfig.forQC; } GPUQA::~GPUQA() = default; From 00d0cb22edc31f2015904399f7a286431ee623cd Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 10 Nov 2020 20:46:19 +0100 Subject: [PATCH 1285/1751] GPU: Add TrackingQAInterface to perform postprocessing independently from tracking --- GPU/GPUTracking/CMakeLists.txt | 4 +- GPU/GPUTracking/GPUTrackingLinkDef_O2.h | 1 + .../Interface/GPUO2InterfaceQA.cxx | 32 ++++ GPU/GPUTracking/Interface/GPUO2InterfaceQA.h | 54 +++++++ GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 150 +++++++++++++----- GPU/GPUTracking/Standalone/qa/GPUQA.h | 19 ++- 6 files changed, 212 insertions(+), 48 deletions(-) create mode 100644 GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx create mode 100644 GPU/GPUTracking/Interface/GPUO2InterfaceQA.h diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 7daaa1eceef1b..dec5d3d5686b0 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -135,8 +135,8 @@ set(HDRS_INSTALL # Sources only for O2 if(ALIGPU_BUILD_TYPE STREQUAL "O2") - set(SRCS ${SRCS} Interface/GPUO2Interface.cxx Interface/GPUO2InterfaceRefit.cxx Interface/GPUO2InterfaceConfigurableParam.cxx) - set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h Interface/GPUO2InterfaceRefit.h Interface/GPUO2InterfaceConfigurableParam.h dEdx/TPCdEdxCalibrationSplines.h) + set(SRCS ${SRCS} Interface/GPUO2Interface.cxx Interface/GPUO2InterfaceRefit.cxx Interface/GPUO2InterfaceQA.cxx Interface/GPUO2InterfaceConfigurableParam.cxx) + set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h Interface/GPUO2InterfaceRefit.h Interface/GPUO2InterfaceQA.h Interface/GPUO2InterfaceConfigurableParam.h dEdx/TPCdEdxCalibrationSplines.h) set(HDRS_CINT_O2_ADDITIONAL Base/GPUSettings.h Base/GPUSettingsList.h) # Manual depencies for ROOT dictionary generation endif() diff --git a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h index 93c1c854de59e..fe035e5a71a45 100644 --- a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h +++ b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h @@ -19,6 +19,7 @@ #pragma link C++ class o2::gpu::GPUTPCO2Interface + ; #pragma link C++ class o2::gpu::GPUTPCO2InterfaceRefit + ; +#pragma link C++ class o2::gpu::GPUO2InterfaceQA + ; #pragma link C++ class o2::gpu::TPCdEdxCalibrationSplines + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsO2 + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsRec + ; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx new file mode 100644 index 0000000000000..a30db8bef77a8 --- /dev/null +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx @@ -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. + +/// \file GPUO2InterfaceQA.cxx +/// \author David Rohr + +#include "GPUQA.h" +#include "GPUO2InterfaceQA.h" + +using namespace o2::gpu; +using namespace o2::tpc; + +GPUO2InterfaceQA::GPUO2InterfaceQA(const GPUSettingsQA* config) : mQA(new GPUQA(nullptr, config)) +{ +} + +GPUO2InterfaceQA::~GPUO2InterfaceQA() = default; + +int GPUO2InterfaceQA::postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out) +{ + if (mQA->loadHistograms(in1, in2, in3)) { + return 1; + } + return mQA->DrawQAHistograms(&out); +} diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h new file mode 100644 index 0000000000000..83f0d00e3f018 --- /dev/null +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h @@ -0,0 +1,54 @@ +// 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 GPUO2InterfaceQA.h +/// \author David Rohr + +#ifndef GPUO2INTERFACEQA_H +#define GPUO2INTERFACEQA_H + +// Some defines denoting that we are compiling for O2 +#ifndef HAVE_O2HEADERS +#define HAVE_O2HEADERS +#endif +#ifndef GPUCA_TPC_GEOMETRY_O2 +#define GPUCA_TPC_GEOMETRY_O2 +#endif +#ifndef GPUCA_O2_INTERFACE +#define GPUCA_O2_INTERFACE +#endif + +#include <memory> +#include <vector> + +class TH1F; +class TH1D; +class TH2F; +class TObjArray; + +namespace o2::gpu +{ +class GPUQA; +class GPUSettingsQA; +class GPUO2InterfaceQA +{ + public: + GPUO2InterfaceQA(const GPUSettingsQA* config = nullptr); + ~GPUO2InterfaceQA(); + + // Input might be modified, so we assume non-const. If it is const, a copy should be created before. + int postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out); + + private: + std::unique_ptr<GPUQA> mQA; +}; +} // namespace o2::gpu + +#endif diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 8d11f67b264ce..3ee8e480e2f7f 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -26,6 +26,7 @@ #include "TTree.h" #include "TStyle.h" #include "TLatex.h" +#include "TObjArray.h" #include <sys/stat.h> #include "GPUQA.h" @@ -214,7 +215,7 @@ inline int GPUQA::GetMCLabelCol(unsigned int i, unsigned int j) { return mTracki inline float GPUQA::GetMCLabelWeight(unsigned int i, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return 1; } -inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking->mIOPtrs.clustersNative->clustersMCTruth && mNColTracks.size(); } +inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking && mTracking->mIOPtrs.clustersNative->clustersMCTruth && mNColTracks.size(); } #define TRACK_EXPECTED_REFERENCE_X 78 #else inline GPUQA::mcLabelI_t::mcLabelI_t(const GPUQA::mcLabel_t& l) : track(l.fMCID) @@ -240,7 +241,7 @@ inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return label.fWeight; } inline int GPUQA::FakeLabelID(int id) { return id < 0 ? id : (-2 - id); } inline int GPUQA::AbsLabelID(int id) { return id >= 0 ? id : (-id - 2); } -inline bool GPUQA::mcPresent() { return !mConfig.noMC && GetNMCLabels() && GetNMCTracks(0); } +inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking && GetNMCLabels() && GetNMCTracks(0); } #define TRACK_EXPECTED_REFERENCE_X 81 #endif template <class T> @@ -250,38 +251,51 @@ inline auto& GPUQA::GetMCTrackObj(T& obj, const GPUQA::mcLabelI_t& l) } template <> -auto GPUQA::getHist<TH1F>() +auto GPUQA::getHistArray<TH1F>() { - return std::make_pair(&mHist1D, &mHist1D_pos); + return std::make_pair(mHist1D, &mHist1D_pos); } template <> -auto GPUQA::getHist<TH2F>() +auto GPUQA::getHistArray<TH2F>() { - return std::make_pair(&mHist2D, &mHist2D_pos); + return std::make_pair(mHist2D, &mHist2D_pos); } template <> -auto GPUQA::getHist<TH1D>() +auto GPUQA::getHistArray<TH1D>() { - return std::make_pair(&mHist1Dd, &mHist1Dd_pos); + return std::make_pair(mHist1Dd, &mHist1Dd_pos); } template <class T, typename... Args> -void GPUQA::createHist(T*& h, Args... args) +void GPUQA::createHist(T*& h, const char* name, Args... args) { - const auto& p = getHist<T>(); - p.first->get()->emplace_back(args...); + const auto& p = getHistArray<T>(); + if (mHaveExternalHists) { + if (p.first->size() <= p.second->size()) { + throw std::runtime_error("Incoming histogram array incomplete"); + } + if (strcmp((*p.first)[p.second->size()].GetName(), name)) { + throw std::runtime_error("Incoming histogram has incorrect name"); + } + } else { + p.first->emplace_back(name, args...); + } p.second->emplace_back(&h); - h = &p.first->get()->back(); + h = &p.first->back(); } -GPUQA::GPUQA(GPUChainTracking* chain) : mTracking(chain), mConfig(GPUQA_GetConfig(chain)) +GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)) { - mHist1D.reset(new std::vector<TH1F>); - mHist2D.reset(new std::vector<TH2F>); - mHist1Dd.reset(new std::vector<TH1D>); mRunForQC = chain == nullptr || mConfig.forQC; } -GPUQA::~GPUQA() = default; +GPUQA::~GPUQA() +{ + if (mQAInitialized && !mHaveExternalHists) { + delete mHist1D; + delete mHist2D; + delete mHist1Dd; + } +} inline bool GPUQA::MCComp(const mcLabel_t& a, const mcLabel_t& b) { return (GPUQA::GetMCLabelID(a) > GPUQA::GetMCLabelID(b)); } @@ -384,7 +398,9 @@ int GPUQA::InitQACreateHistograms() } else { createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]); } - mEff[i][j][k][l][m]->Sumw2(); + if (!mHaveExternalHists) { + mEff[i][j][k][l][m]->Sumw2(); + } } } } @@ -472,19 +488,43 @@ int GPUQA::InitQACreateHistograms() return 0; } +int GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3) +{ + if (mQAInitialized) { + return 1; + } + mHist1D = &i1; + mHist2D = &i2; + mHist1Dd = &i3; + mHist1D_pos.clear(); + mHist2D_pos.clear(); + mHist1Dd_pos.clear(); + mHaveExternalHists = true; + if (InitQACreateHistograms()) { + return 1; + } + mQAInitialized = true; + return 0; +} + int GPUQA::InitQA() { if (mQAInitialized) { return 1; } + mHist1D = new std::vector<TH1F>; + mHist2D = new std::vector<TH2F>; + mHist1Dd = new std::vector<TH1D>; + mColorNums.resize(COLORCOUNT); + mColors.reserve(COLORCOUNT); for (int i = 0; i < COLORCOUNT; i++) { float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; - TColor* c = new TColor(10000 + i, f1, f2, f3); - mColorNums[i] = c->GetNumber(); + mColors.emplace_back(10000 + i, f1, f2, f3); + mColorNums[i] = mColors.back().GetNumber(); } if (InitQACreateHistograms()) { @@ -1589,7 +1629,7 @@ T* GPUQA::GetHist(T*& ee, std::vector<TFile*>& tin, int k, int nNewInput) return (e); } -int GPUQA::DrawQAHistograms() +int GPUQA::DrawQAHistograms(TObjArray* qcout) { if (!mQAInitialized) { return 1; @@ -1755,12 +1795,16 @@ int GPUQA::DrawQAHistograms() } } + int flagShowVsPtLog = mRunForQC ? 0 : 1; + // Process / Draw Efficiency Histograms - for (int ii = 0; ii < 6; ii++) { + for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { int i = ii == 5 ? 4 : ii; for (int k = 0; k < ConfigNumInputs; k++) { for (int j = 0; j < 4; j++) { - mPEff[ii][j]->cd(); + if (!mRunForQC) { + mPEff[ii][j]->cd(); + } for (int l = 0; l < 3; l++) { if (k == 0 && mConfig.inputHistogramsOnly == 0 && ii != 5) { if (l == 0) { @@ -1796,14 +1840,17 @@ int GPUQA::DrawQAHistograms() e->GetYaxis()->SetTitle("(Efficiency)"); e->GetXaxis()->SetTitle(XAXIS_TITLES[i]); - e->SetMarkerColor(kBlack); e->SetLineWidth(1); - e->SetLineColor(mColorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); SetAxisSize(e); + if (qcout) { + qcout->Add(e); + } if (mRunForQC) { continue; } + e->SetMarkerColor(kBlack); + e->SetLineColor(mColorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -1839,7 +1886,7 @@ int GPUQA::DrawQAHistograms() TH1D *resIntegral[5] = {}, *pullIntegral[5] = {}; TF1* customGaus = new TF1("G", "[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))"); for (int p = 0; p < 2; p++) { - for (int ii = 0; ii < 6; ii++) { + for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { TCanvas* can = p ? mCPull[ii] : mCRes[ii]; TLegend* leg = p ? mLPull[ii] : mLRes[ii]; int i = ii == 5 ? 4 : ii; @@ -2001,9 +2048,7 @@ int GPUQA::DrawQAHistograms() } e->SetMaximum(tmpMax); e->SetMinimum(tmpMin); - e->SetMarkerColor(kBlack); e->SetLineWidth(1); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); SetAxisSize(e); e->GetYaxis()->SetTitle(p ? AXIS_TITLES_PULL[j] : mConfig.nativeFitResolutions ? AXIS_TITLES_NATIVE[j] : AXIS_TITLES[j]); @@ -2017,10 +2062,15 @@ int GPUQA::DrawQAHistograms() } else if (j < 3) { e->GetYaxis()->SetTitleOffset(1.4); } + if (qcout) { + qcout->Add(e); + } if (mRunForQC) { continue; } + e->SetMarkerColor(kBlack); + e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -2068,7 +2118,9 @@ int GPUQA::DrawQAHistograms() TPad* pad = p ? mPPull[6][i] : mPRes[6][i]; TH1D* hist = p ? pullIntegral[i] : resIntegral[i]; int numColor = 0; - pad->cd(); + if (!mRunForQC) { + pad->cd(); + } if (!mConfig.inputHistogramsOnly && mcAvail) { TH1D* e = hist; e->GetEntries(); @@ -2094,16 +2146,22 @@ int GPUQA::DrawQAHistograms() } e->SetMaximum(tmpMax * 1.02); e->SetMinimum(tmpMax * -0.02); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); if (tout && !mConfig.inputHistogramsOnly && k == 0) { e->Write(); } + if (qcout) { + qcout->Add(e); + } if (mRunForQC) { continue; } + e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); } + if (mRunForQC) { + continue; + } can->cd(); } if (mRunForQC) { @@ -2230,8 +2288,10 @@ int GPUQA::DrawQAHistograms() } for (int i = 0; i < N_CLS_TYPE; i++) { - mPClust[i]->cd(); - mPClust[i]->SetLogx(); + if (!mRunForQC) { + mPClust[i]->cd(); + mPClust[i]->SetLogx(); + } int begin = i == 2 ? (2 * N_CLS_HIST - 1) : i == 1 ? N_CLS_HIST : 0; int end = i == 2 ? (3 * N_CLS_HIST - 1) : i == 1 ? (2 * N_CLS_HIST - 1) : N_CLS_HIST; int numColor = 0; @@ -2251,17 +2311,20 @@ int GPUQA::DrawQAHistograms() e->Write(); } e->SetStats(kFALSE); - e->SetMarkerColor(kBlack); e->SetLineWidth(1); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->SetLineStyle(CONFIG_DASHED_MARKERS ? j + 1 : 1); if (i == 0) { e->GetXaxis()->SetRange(2, AXIS_BINS[4]); } + if (qcout) { + qcout->Add(e); + } if (mRunForQC) { continue; } + e->SetMarkerColor(kBlack); + e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->Draw(j == end - 1 && k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%s%s", fname, CLUSTER_NAMES[j - begin]); @@ -2271,11 +2334,14 @@ int GPUQA::DrawQAHistograms() if (ConfigNumInputs == 1) { TH1* e = reinterpret_cast<TH1F*>(mClusters[begin + CL_att_adj]->Clone()); e->Add(mClusters[begin + CL_prot], -1); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + if (qcout) { + qcout->Add(e); + } if (mRunForQC) { continue; } + e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->Draw("same"); mLClust[i]->AddEntry(e, "Removed", "l"); } @@ -2321,11 +2387,14 @@ int GPUQA::DrawQAHistograms() e->SetMaximum(tmpMax * 1.02); e->SetMinimum(tmpMax * -0.02); e->SetStats(kFALSE); - e->SetMarkerColor(kBlack); e->SetLineWidth(1); - e->SetLineColor(mColorNums[k % COLORCOUNT]); e->GetYaxis()->SetTitle("a.u."); e->GetXaxis()->SetTitle("#it{p}_{Tmc} (GeV/#it{c})"); + if (qcout) { + qcout->Add(e); + } + e->SetMarkerColor(kBlack); + e->SetLineColor(mColorNums[k % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%sTrack Pt", fname); @@ -2360,11 +2429,14 @@ int GPUQA::DrawQAHistograms() e->SetMaximum(tmpMax * 1.02); e->SetMinimum(tmpMax * -0.02); e->SetStats(kFALSE); - e->SetMarkerColor(kBlack); e->SetLineWidth(1); - e->SetLineColor(mColorNums[k % COLORCOUNT]); e->GetYaxis()->SetTitle("a.u."); e->GetXaxis()->SetTitle("NClusters"); + if (qcout) { + qcout->Add(e); + } + e->SetMarkerColor(kBlack); + e->SetLineColor(mColorNums[k % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%sNClusters", fname); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index e37310af68fc1..89dd94c6c9f1e 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -25,6 +25,8 @@ class TPad; class TH1; class TFile; class TH1D; +class TObjArray; +class TColor; typedef short int Color_t; #if !defined(GPUCA_BUILD_QA) || defined(GPUCA_GPUCODE) @@ -82,12 +84,12 @@ class GPUQA { public: GPUQA(); - GPUQA(GPUChainTracking* chain); + GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config = nullptr); ~GPUQA(); int InitQA(); void RunQA(bool matchOnly = false); - int DrawQAHistograms(); + int DrawQAHistograms(TObjArray* qcout = nullptr); void SetMCTrackRange(int min, int max); bool SuppressTrack(int iTrack) const; bool SuppressHit(int iHit) const; @@ -100,6 +102,7 @@ class GPUQA const std::vector<TH1F>& getHistograms1D() const { return *mHist1D; } const std::vector<TH2F>& getHistograms2D() const { return *mHist2D; } const std::vector<TH1D>& getHistograms1Dd() const { return *mHist1Dd; } + int loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3); static constexpr int N_CLS_HIST = 8; static constexpr int N_CLS_TYPE = 3; @@ -251,16 +254,17 @@ class GPUQA TPad* mPNCl; TLegend* mLNCl; - std::unique_ptr<std::vector<TH1F>> mHist1D{}; - std::unique_ptr<std::vector<TH2F>> mHist2D{}; - std::unique_ptr<std::vector<TH1D>> mHist1Dd{}; + std::vector<TH1F>* mHist1D = nullptr; + std::vector<TH2F>* mHist2D = nullptr; + std::vector<TH1D>* mHist1Dd = nullptr; + bool mHaveExternalHists = false; std::vector<TH1F**> mHist1D_pos{}; std::vector<TH2F**> mHist2D_pos{}; std::vector<TH1D**> mHist1Dd_pos{}; template <class T> - auto getHist(); + auto getHistArray(); template <class T, typename... Args> - void createHist(T*& h, Args... args); + void createHist(T*& h, const char* name, Args... args); int mNEvents = 0; bool mQAInitialized = false; @@ -270,6 +274,7 @@ class GPUQA std::vector<std::vector<bool>> mGoodHits; std::vector<Color_t> mColorNums; + std::vector<TColor> mColors; int mMCTrackMin = -1, mMCTrackMax = -1; }; From 658cd1e34abcfa10d552c2631d7773dc12994377 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 10 Nov 2020 22:07:02 +0100 Subject: [PATCH 1286/1751] TPC Workflow: apply postprocessing to TPC QA histograms before shipping as external to QC --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 20 +++++++++++--------- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 97a196aadbc60..bd5be552fabff 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -42,6 +42,7 @@ #include "DetectorsRaw/HBFUtils.h" #include "TPCBase/RDHUtils.h" #include "GPUO2InterfaceConfiguration.h" +#include "GPUO2InterfaceQA.h" #include "TPCCFCalibration.h" #include "GPUDisplayBackend.h" #ifdef GPUCA_BUILD_EVENT_DISPLAY @@ -100,6 +101,8 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config std::unique_ptr<TPCFastTransform> fastTransform; std::unique_ptr<TPCdEdxCalibrationSplines> dEdxSplines; std::unique_ptr<TPCCFCalibration> tpcCalibration; + std::unique_ptr<GPUSettingsQA> qaConfig; + std::unique_ptr<GPUO2InterfaceQA> qa; std::vector<int> clusterOutputIds; unsigned long outputBufferSize = 0; unsigned long tpcSectorMask = 0; @@ -242,6 +245,10 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config if (tracker->initialize(config) != 0) { throw std::invalid_argument("GPUCATracking initialization failed"); } + if (specconfig.outputQA) { + processAttributes->qaConfig.reset(new GPUSettingsQA(config.configQA)); + processAttributes->qa = std::make_unique<GPUO2InterfaceQA>(processAttributes->qaConfig.get()); + } timer.Stop(); timer.Reset(); } @@ -701,15 +708,10 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } if (specconfig.outputQA) { TObjArray out; - for (unsigned int i = 0; i < outputRegions.qa.hist1->size(); i++) { - out.Add((TObject*)&(*outputRegions.qa.hist1)[i]); // FIXME: Fundamentally broken, we cannot add the const object, but QC doesn't accept the std::vector - } - for (unsigned int i = 0; i < outputRegions.qa.hist2->size(); i++) { - out.Add((TObject*)&(*outputRegions.qa.hist2)[i]); - } - for (unsigned int i = 0; i < outputRegions.qa.hist3->size(); i++) { - out.Add((TObject*)&(*outputRegions.qa.hist3)[i]); - } + std::vector<TH1F> copy1 = *outputRegions.qa.hist1; // Internally, this will also be used as output, so we need a non-const copy + std::vector<TH2F> copy2 = *outputRegions.qa.hist2; + std::vector<TH1D> copy3 = *outputRegions.qa.hist3; + processAttributes->qa->postprocess(copy1, copy2, copy3, out); pc.outputs().snapshot({gDataOriginTPC, "TRACKINGQA", 0, Lifetime::Timeframe}, out); } timer.Stop(); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 3ee8e480e2f7f..50d3db0f8569c 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -516,7 +516,7 @@ int GPUQA::InitQA() mHist1D = new std::vector<TH1F>; mHist2D = new std::vector<TH2F>; mHist1Dd = new std::vector<TH1D>; - + mColorNums.resize(COLORCOUNT); mColors.reserve(COLORCOUNT); for (int i = 0; i < COLORCOUNT; i++) { From 2cffd92ab878758542de2c7a253b4e46db691680 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Tue, 10 Nov 2020 20:35:52 +0300 Subject: [PATCH 1287/1751] Residuals: make readability-braces-around-statements happy --- Analysis/Tasks/PWGCF/correlationsFiltered.cxx | 6 +- .../DataFormatsCalibration/MeanVertexObject.h | 6 +- DataFormats/Detectors/EMCAL/src/Cell.cxx | 5 +- DataFormats/Detectors/EMCAL/test/testCell.cxx | 8 ++- Detectors/DCS/src/DCSProcessor.cxx | 24 +++++--- .../FIT/FDD/reconstruction/src/ReadRaw.cxx | 3 +- .../MUON/MCH/Simulation/src/Digitizer.cxx | 3 +- .../include/PHOSSimulation/GeometryParams.h | 12 ++-- .../Raw/include/DetectorsRaw/RawFileReader.h | 5 +- Detectors/TOF/base/src/WindowFiller.cxx | 21 ++++--- .../TOFDigitWriterSplitterSpec.h | 6 +- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 11 ++-- Detectors/ZDC/simulation/src/Detector.cxx | 35 +++++++----- .../EventVisualisationBase/DataInterpreter.h | 3 +- .../Base/src/DataSourceOffline.cxx | 6 +- .../Base/src/GeometryManager.cxx | 6 +- .../src/VisualisationCluster.cxx | 3 +- .../DataConverter/src/VisualisationTrack.cxx | 9 ++- .../Detectors/src/DataInterpreterVSD.cxx | 3 +- .../Detectors/src/DataReaderVSD.cxx | 3 +- EventVisualisation/View/src/EventManager.cxx | 12 ++-- EventVisualisation/View/src/Initializer.cxx | 12 ++-- EventVisualisation/View/src/main.cxx | 6 +- .../AnalysisTools/include/Framework/StepTHn.h | 10 ++-- Framework/AnalysisTools/src/StepTHn.cxx | 57 ++++++++++++------- .../include/Framework/HistogramRegistry.h | 24 +++++--- Framework/Core/src/DataInputDirector.cxx | 6 +- GPU/Common/GPUCommonMath.h | 9 ++- GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 6 +- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 6 +- GPU/TPCFastTransformation/SplineHelper1D.cxx | 12 ++-- .../TPCFastSpaceChargeCorrection.cxx | 6 +- .../TPCFastTransform.cxx | 18 ++++-- .../TPCFastTransformGeo.cxx | 6 +- .../devtools/IrregularSpline1D.cxx | 3 +- .../devtools/IrregularSpline2D3D.h | 3 +- .../IrregularSpline2D3DCalibrator.cxx | 39 ++++++++----- .../devtools/RegularSpline1D.h | 11 ++-- GPU/Utils/FlatObject.h | 15 +++-- Generators/src/DecayerPythia8.cxx | 11 ++-- Generators/src/Generator.cxx | 36 +++++++----- Generators/src/GeneratorFactory.cxx | 6 +- Generators/src/GeneratorFromFile.cxx | 3 +- Generators/src/GeneratorHepMC.cxx | 9 ++- Generators/src/GeneratorPythia6.cxx | 9 ++- Generators/src/GeneratorPythia8.cxx | 12 ++-- Generators/src/PrimaryGenerator.cxx | 12 ++-- Generators/src/TriggerParticle.cxx | 15 +++-- .../src/CPVDigitizerSpec.cxx | 3 +- .../src/EMCALDigitizerSpec.cxx | 9 ++- .../src/PHOSDigitizerSpec.cxx | 3 +- Steer/src/InteractionSampler.cxx | 6 +- Steer/src/O2MCApplication.cxx | 3 +- Utilities/DataSampling/src/Dispatcher.cxx | 3 +- 54 files changed, 379 insertions(+), 200 deletions(-) diff --git a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx index b09d256cc79e8..6b901f88915e5 100644 --- a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx +++ b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx @@ -174,10 +174,12 @@ struct CorrelationTask { } float deltaPhi = track1.phi() - track2.phi(); - if (deltaPhi > 1.5 * TMath::Pi()) + if (deltaPhi > 1.5 * TMath::Pi()) { deltaPhi -= TMath::TwoPi(); - if (deltaPhi < -0.5 * TMath::Pi()) + } + if (deltaPhi < -0.5 * TMath::Pi()) { deltaPhi += TMath::TwoPi(); + } same->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, track1.eta() - track2.eta(), track2.pt(), track1.pt(), centrality, deltaPhi, collision.posZ()); diff --git a/DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h b/DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h index 43f1d2fac2d46..245cdcb2fed24 100644 --- a/DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h +++ b/DataFormats/Calibration/include/DataFormatsCalibration/MeanVertexObject.h @@ -50,8 +50,9 @@ class MeanVertexObject void setZ(float val) { mPos[2] = val; } void setPos(std::array<float, 3> val) { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { mPos[i] = val[i]; + } } float getX() const { return mPos[0]; } @@ -64,8 +65,9 @@ class MeanVertexObject void setSigmaZ(float val) { mSigma[2] = val; } void setSigma(std::array<float, 3> val) { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { mSigma[i] = val[i]; + } } float getSigmaX() const { return mSigma[0]; } diff --git a/DataFormats/Detectors/EMCAL/src/Cell.cxx b/DataFormats/Detectors/EMCAL/src/Cell.cxx index 706f274f0093a..b02533111c925 100644 --- a/DataFormats/Detectors/EMCAL/src/Cell.cxx +++ b/DataFormats/Detectors/EMCAL/src/Cell.cxx @@ -40,10 +40,11 @@ void Cell::setTimeStamp(float timestamp) // truncate: const float TIME_MIN = -1. * TIME_SHIFT, TIME_MAX = TIME_RANGE - TIME_SHIFT; - if (timestamp < TIME_MIN) + if (timestamp < TIME_MIN) { timestamp = TIME_MIN; - else if (timestamp > TIME_MAX) + } else if (timestamp > TIME_MAX) { timestamp = TIME_MAX; + } getDataRepresentation()->mTime = static_cast<uint16_t>((timestamp + TIME_SHIFT) / TIME_RESOLUTION); } diff --git a/DataFormats/Detectors/EMCAL/test/testCell.cxx b/DataFormats/Detectors/EMCAL/test/testCell.cxx index c021523cf387e..f98f0166066be 100644 --- a/DataFormats/Detectors/EMCAL/test/testCell.cxx +++ b/DataFormats/Detectors/EMCAL/test/testCell.cxx @@ -54,15 +54,17 @@ BOOST_AUTO_TEST_CASE(Cell_test) for (auto e : energies) { c.setEnergy(e); - if (e > 16) + if (e > 16) { c.setLowGain(); + } BOOST_CHECK_EQUAL(c.getTower(), 0); BOOST_CHECK_SMALL(double(c.getTimeStamp()), 0.73); BOOST_CHECK_SMALL(e - c.getEnergy(), 0.02); // Require 20 MeV resolution - if (e > 16) + if (e > 16) { BOOST_CHECK_EQUAL(c.getLowGain(), true); - else + } else { BOOST_CHECK_EQUAL(c.getHighGain(), true); + } } c.setEnergy(0); diff --git a/Detectors/DCS/src/DCSProcessor.cxx b/Detectors/DCS/src/DCSProcessor.cxx index 36756e3656d24..3b54607a6e5ee 100644 --- a/Detectors/DCS/src/DCSProcessor.cxx +++ b/Detectors/DCS/src/DCSProcessor.cxx @@ -230,22 +230,30 @@ int DCSProcessor::processMap(const std::unordered_map<DPID, DPVAL>& map, bool is mDpsbinariesmap); if (!isDelta) { - if (foundChars != mPidschars.size()) + if (foundChars != mPidschars.size()) { LOG(INFO) << "Not all expected char-typed DPs found!"; - if (foundInts != mPidsints.size()) + } + if (foundInts != mPidsints.size()) { LOG(INFO) << "Not all expected int-typed DPs found!"; - if (foundDoubles != mPidsdoubles.size()) + } + if (foundDoubles != mPidsdoubles.size()) { LOG(INFO) << "Not all expected double-typed DPs found!"; - if (foundUInts != mPidsUints.size()) + } + if (foundUInts != mPidsUints.size()) { LOG(INFO) << "Not all expected uint-typed DPs found!"; - if (foundBools != mPidsbools.size()) + } + if (foundBools != mPidsbools.size()) { LOG(INFO) << "Not all expected bool-typed DPs found!"; - if (foundStrings != mPidsstrings.size()) + } + if (foundStrings != mPidsstrings.size()) { LOG(INFO) << "Not all expected string-typed DPs found!"; - if (foundTimes != mPidstimes.size()) + } + if (foundTimes != mPidstimes.size()) { LOG(INFO) << "Not all expected time-typed DPs found!"; - if (foundBinaries != mPidsbinaries.size()) + } + if (foundBinaries != mPidsbinaries.size()) { LOG(INFO) << "Not all expected binary-typed DPs found!"; + } } // filling CCDB info to be sent in output diff --git a/Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx b/Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx index a7c90eb03713c..a0935f192141e 100644 --- a/Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx +++ b/Detectors/FIT/FDD/reconstruction/src/ReadRaw.cxx @@ -122,8 +122,9 @@ void ReadRaw::readRawData(const LookUpTable& lut) //_____________________________________________________________________________________ void ReadRaw::close() { - if (mRawFileIn.is_open()) + if (mRawFileIn.is_open()) { mRawFileIn.close(); + } } //_____________________________________________________________________________________ void ReadRaw::writeDigits(const std::string& outputDigitsFilePath) diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index e36dce5060867..9d9b3ccc9ef21 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -103,8 +103,9 @@ void Digitizer::process(const std::vector<Hit> hits, std::vector<Digit>& digits, } //loop over hits //generate noise-only digits - if (mNoise) + if (mNoise) { generateNoiseDigits(); + } fillOutputContainer(digits); provideMC(mcContainer); diff --git a/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h b/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h index 4ad5347afbe77..b4f95f91ac1ed 100644 --- a/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h +++ b/Detectors/PHOS/simulation/include/PHOSSimulation/GeometryParams.h @@ -33,8 +33,9 @@ class GeometryParams final : public TNamed /// get singleton (create if necessary) static GeometryParams* GetInstance(const std::string_view name = "Run2") { - if (!sGeomParam) + if (!sGeomParam) { sGeomParam = new GeometryParams(name); + } return sGeomParam; } @@ -54,14 +55,17 @@ class GeometryParams final : public TNamed void getModuleCenter(int module, float* pos) const { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { pos[i] = mModuleCenter[module][i]; + } } void getModuleAngle(int module, float angle[3][2]) const { - for (int i = 0; i < 3; i++) - for (int ian = 0; ian < 2; ian++) + for (int i = 0; i < 3; i++) { + for (int ian = 0; ian < 2; ian++) { angle[i][ian] = mModuleAngle[module][i][ian]; + } + } } // Return PHOS support geometry parameters float getRailOuterSize(int index) const { return mRailOuterSize[index]; } diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h index 8bc080bf5111e..90b4e769a8656 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileReader.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileReader.h @@ -126,10 +126,11 @@ class RawFileReader LinkBlock(int fid, size_t offs) : offset(offs), fileID(fid) {} void setFlag(uint8_t fl, bool v = true) { - if (v) + if (v) { flags |= fl; - else + } else { flags &= ~fl; + } } bool testFlag(uint8_t fl) const { return (flags & fl) == fl; } void print(const std::string& pref = "") const; diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index 6b8094f6661c7..492bf51a59914 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -111,15 +111,17 @@ void WindowFiller::fillDigitsInStrip(std::vector<Strip>* strips, int channel, in //______________________________________________________________________ void WindowFiller::addCrateHeaderData(unsigned long orbit, int crate, int32_t bc, uint32_t eventCounter) { - if (orbit < mFirstIR.orbit) + if (orbit < mFirstIR.orbit) { return; + } orbit -= mFirstIR.orbit; orbit *= Geo::NWINDOW_IN_ORBIT; // move from orbit to N readout window orbit += (bc + 100) / Geo::BC_IN_WINDOW; // select readout window in the orbit according to the BC (100 shift to avoid border effects) - if (mCrateHeaderData.size() < orbit + 1) + if (mCrateHeaderData.size() < orbit + 1) { mCrateHeaderData.resize(orbit + 1); + } mCrateHeaderData[orbit].bc[crate] = bc; mCrateHeaderData[orbit].eventCounter[crate] = eventCounter; @@ -159,22 +161,27 @@ void WindowFiller::fillOutputContainer(std::vector<Digit>& digits) if (mCrateHeaderData[irow].bc[icrate] == -1) { // crate not read info.setEmptyCrate(icrate); continue; - } else + } else { mDigitHeader.crateSeen(icrate); + } ncratesSeen++; - if (bc_shift == -1 || mCrateHeaderData[irow].bc[icrate] < bc_shift) + if (bc_shift == -1 || mCrateHeaderData[irow].bc[icrate] < bc_shift) { bc_shift = mCrateHeaderData[irow].bc[icrate]; - if (eventcounter == -1 || mCrateHeaderData[irow].eventCounter[icrate] < eventcounter) + } + if (eventcounter == -1 || mCrateHeaderData[irow].eventCounter[icrate] < eventcounter) { eventcounter = mCrateHeaderData[irow].eventCounter[icrate]; + } } mDigitHeader.numCratesSeen(ncratesSeen); - if (bc_shift == -1) + if (bc_shift == -1) { bc_shift = (mReadoutWindowData.size() % Geo::NWINDOW_IN_ORBIT) * Geo::BC_IN_WINDOW; // insert default value - if (eventcounter == -1) + } + if (eventcounter == -1) { eventcounter = mReadoutWindowData.size() % 4096; // insert default value + } } info.setBCData(mFirstIR.orbit + orbit_shift, mFirstIR.bc + bc_shift); diff --git a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h index d03d747cc76cc..432504430afb0 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h @@ -48,8 +48,9 @@ class TOFDigitWriterSplitter : public Task mOutputTree->Branch("TOFDigit", &mPDigits); mOutputTree->Branch("TOFReadoutWindow", &mPROW); mOutputTree->Branch("TOFPatterns", &mPDia); - if (mStoreErrors) + if (mStoreErrors) { mOutputTree->Branch("TOFErrors", &mPErr); + } mNTF = 0; } @@ -141,8 +142,9 @@ DataProcessorSpec getTOFCalibCollectorWriterSpec(int nTF, bool storeErr = false) inputs.emplace_back("rows", o2::header::gDataOriginTOF, "READOUTWINDOW"); inputs.emplace_back("patterns", o2::header::gDataOriginTOF, "PATTERNS"); - if (storeErr) + if (storeErr) { inputs.emplace_back("errors", o2::header::gDataOriginTOF, "ERRORS"); + } std::vector<OutputSpec> outputs; // empty diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 80287c45ecd95..f3655aca05ba9 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -284,10 +284,11 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) uint64_t currentTriggerRecord = 0; for (auto& trig : triggerRecords) { - if (mDumpTriggerRecords) + if (mDumpTriggerRecords) { LOG(info) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); - else + } else { LOG(debug) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); + } } // fix incoming trigger records if requested. if (mFixTriggerRecords) { @@ -331,13 +332,15 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) for (auto& trig : triggerRecords) { LOG(debug) << " sorting from index: " << trig.getFirstEntry() << " till " << trig.getNumberOfObjects() + trig.getFirstEntry(); LOG(debug) << "pre sort"; - for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) + for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) { LOG(debug) << "i:" << msgDigitsIndex[i]; + } std::stable_sort(std::begin(msgDigitsIndex) + trig.getFirstEntry(), std::begin(msgDigitsIndex) + trig.getNumberOfObjects() + trig.getFirstEntry(), [msgDigits](auto&& PH1, auto&& PH2) { return digitindexcompare(PH1, PH2, msgDigits); }); LOG(debug) << "post sort"; - for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) + for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) { LOG(debug) << "i:" << i << " = " << msgDigitsIndex[i]; + } LOG(debug) << "*****************************************************************"; } diff --git a/Detectors/ZDC/simulation/src/Detector.cxx b/Detectors/ZDC/simulation/src/Detector.cxx index 243142bd21da7..4b872f55346db 100644 --- a/Detectors/ZDC/simulation/src/Detector.cxx +++ b/Detectors/ZDC/simulation/src/Detector.cxx @@ -111,8 +111,9 @@ void Detector::InitializeO2Detector() std::string inputDir; const char* aliceO2env = std::getenv("O2_ROOT"); - if (aliceO2env) + if (aliceO2env) { inputDir = std::string(aliceO2env); + } inputDir += "/share/Detectors/ZDC/simulation/data/"; //ZN case loadLightTable(mLightTableZN, 0, ZNRADIUSBINS, inputDir + "light22620362207s"); @@ -206,8 +207,9 @@ void Detector::getDetIDandSecID(TString const& volname, math_utils::Vector3D<flo if (xDet.X() <= 0.) { if (xDet.Y() <= 0.) { sector = Ch1; - } else + } else { sector = Ch3; + } } else { if (xDet.Y() <= 0.) { sector = Ch2; @@ -306,8 +308,9 @@ Bool_t Detector::ProcessHits(FairVolume* v) // If the particle is in a ZN or ZP fiber connected to the common PMT // then the assigned sector is 0 (PMC) NB-> does not work for ZEM - if ((fMC->CurrentMedium() == mMediumPMCid) && (detector != ZEM)) + if ((fMC->CurrentMedium() == mMediumPMCid) && (detector != ZEM)) { sector = 0; + } //printf("ProcessHits: x=(%f, %f, %f) \n",x[0], x[1], x[2]); //printf("\tDET %d SEC %d -> XImpact=(%f, %f, %f)\n",detector,sector, xImp.X(), xImp.Y(), xImp.Z()); @@ -1389,8 +1392,9 @@ void Detector::createCsideBeamLine() if (mTCLIAAPERTURE < 3.5) { boxpar[0] = 5.4 / 2.; boxpar[1] = (3.5 - mTCLIAAPERTURE - mVCollSideCCentreY - 0.7) / 2.; // FIX IT!!!!!!!! - if (boxpar[1] < 0.) + if (boxpar[1] < 0.) { boxpar[1] = 0.; + } boxpar[2] = 124.4 / 2.; TVirtualMC::GetMC()->Gsvolu("QCVC", "BOX ", getMediumID(kGraphite), boxpar, 3); TVirtualMC::GetMC()->Gspos("QCVC", 1, "QE02", -boxpar[0], mTCLIAAPERTURE + mVCollSideCCentreY + boxpar[1], -totLength1 / 2. + 160.8 + 78. + 148. / 2., 0, "ONLY"); // FIX IT!!!!!!!! @@ -2327,19 +2331,22 @@ Bool_t Detector::calculateTableIndexes(int& ibeta, int& iangle, int& iradius) //particle velocity float ptot = TMath::Sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]); float beta = 0.; - if (energy > 0.) + if (energy > 0.) { beta = ptot / energy; + } if (beta >= 0.67) { - if (beta <= 0.75) + if (beta <= 0.75) { ibeta = 0; - else if (beta > 0.75 && beta <= 0.85) + } else if (beta > 0.75 && beta <= 0.85) { ibeta = 1; - else if (beta > 0.85 && beta <= 0.95) + } else if (beta > 0.85 && beta <= 0.95) { ibeta = 2; - else if (beta > 0.95) + } else if (beta > 0.95) { ibeta = 3; - } else + } + } else { return kFALSE; + } //track angle wrt fibre axis (||LHC axis) double umom[3] = {0., 0., 0.}, udet[3] = {0., 0., 0.}; umom[0] = p[0] / ptot; @@ -2348,18 +2355,20 @@ Bool_t Detector::calculateTableIndexes(int& ibeta, int& iangle, int& iradius) fMC->Gmtod(umom, udet, 2); double angleRad = TMath::ACos(udet[2]); double angleDeg = angleRad * kRaddeg; - if (angleDeg < 110.) + if (angleDeg < 110.) { iangle = int(0.5 + angleDeg / 2.); - else + } else { return kFALSE; + } //radius from fibre axis fMC->Gmtod(x, xDet, 1); float radius = 0.; if (TMath::Abs(udet[0]) > 0) { float dcoeff = udet[1] / udet[0]; radius = TMath::Abs((xDet[1] - dcoeff * xDet[0]) / TMath::Sqrt(dcoeff * dcoeff + 1.)); - } else + } else { radius = TMath::Abs(udet[0]); + } iradius = int(radius * 1000. + 1.); //printf("\t beta %f angle %f radius %f\n",beta, angleDeg, radius); return kTRUE; diff --git a/EventVisualisation/Base/include/EventVisualisationBase/DataInterpreter.h b/EventVisualisation/Base/include/EventVisualisationBase/DataInterpreter.h index 6f835909586ef..3568492c0fd98 100644 --- a/EventVisualisation/Base/include/EventVisualisationBase/DataInterpreter.h +++ b/EventVisualisation/Base/include/EventVisualisationBase/DataInterpreter.h @@ -45,11 +45,12 @@ class DataInterpreter virtual ~DataInterpreter() = default; static void removeInstances() { - for (int i = 0; i < EVisualisationGroup::NvisualisationGroups; i++) + for (int i = 0; i < EVisualisationGroup::NvisualisationGroups; i++) { if (instance[i] != nullptr) { delete instance[i]; instance[i] = nullptr; } + } } // Should return visualisation objects for required data type diff --git a/EventVisualisation/Base/src/DataSourceOffline.cxx b/EventVisualisation/Base/src/DataSourceOffline.cxx index 73b76214f96f8..9f5021c9d6759 100644 --- a/EventVisualisation/Base/src/DataSourceOffline.cxx +++ b/EventVisualisation/Base/src/DataSourceOffline.cxx @@ -37,16 +37,18 @@ DataReader* DataSourceOffline::instance[EVisualisationGroup::NvisualisationGroup TObject* DataSourceOffline::getEventData(int no, EVisualisationGroup purpose) { - if (instance[purpose] == nullptr) + if (instance[purpose] == nullptr) { return nullptr; + } return instance[purpose]->getEventData(no); } int DataSourceOffline::GetEventCount() { for (int i = 0; i < EVisualisationGroup::NvisualisationGroups; i++) { - if (instance[i] != nullptr) + if (instance[i] != nullptr) { return instance[i]->GetEventCount(); + } } return 1; }; diff --git a/EventVisualisation/Base/src/GeometryManager.cxx b/EventVisualisation/Base/src/GeometryManager.cxx index 0d61520e7eaee..92c595478c6d6 100644 --- a/EventVisualisation/Base/src/GeometryManager.cxx +++ b/EventVisualisation/Base/src/GeometryManager.cxx @@ -82,8 +82,9 @@ void GeometryManager::drawDeep(TEveGeoShape* geomShape, Color_t color, Char_t tr if (strcmp(geomShape->GetElementName(), "TPC_Drift_1") == 0) { // hack for TPC drift chamber geomShape->SetRnrSelf(kTRUE); - if (color >= 0) + if (color >= 0) { geomShape->SetMainColor(color); + } if (lineColor >= 0) { geomShape->SetLineColor(lineColor); geomShape->SetLineWidth(0.1); @@ -101,8 +102,9 @@ void GeometryManager::drawDeep(TEveGeoShape* geomShape, Color_t color, Char_t tr } } else { geomShape->SetRnrSelf(true); - if (color >= 0) + if (color >= 0) { geomShape->SetMainColor(color); + } if (lineColor >= 0) { geomShape->SetLineColor(lineColor); geomShape->SetLineWidth(0.1); diff --git a/EventVisualisation/DataConverter/src/VisualisationCluster.cxx b/EventVisualisation/DataConverter/src/VisualisationCluster.cxx index d51bb14bf8205..0b287a14a2573 100644 --- a/EventVisualisation/DataConverter/src/VisualisationCluster.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationCluster.cxx @@ -30,8 +30,9 @@ VisualisationCluster::VisualisationCluster(double XYZ[]) void VisualisationCluster::setCoordinates(double xyz[3]) { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { mCoordinates[i] = xyz[i]; + } } } // namespace event_visualisation diff --git a/EventVisualisation/DataConverter/src/VisualisationTrack.cxx b/EventVisualisation/DataConverter/src/VisualisationTrack.cxx index 71891a5376c72..8a64472ed8ef0 100644 --- a/EventVisualisation/DataConverter/src/VisualisationTrack.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationTrack.cxx @@ -65,20 +65,23 @@ void VisualisationTrack::addChild(int childID) void VisualisationTrack::addMomentum(double pxpypz[3]) { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { mMomentum[i] = pxpypz[i]; + } } void VisualisationTrack::addStartCoordinates(double xyz[3]) { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { mStartCoordinates[i] = xyz[i]; + } } void VisualisationTrack::addEndCoordinates(double xyz[3]) { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { mEndCoordinates[i] = xyz[i]; + } } void VisualisationTrack::addPolyPoint(double x, double y, double z) diff --git a/EventVisualisation/Detectors/src/DataInterpreterVSD.cxx b/EventVisualisation/Detectors/src/DataInterpreterVSD.cxx index a826eeeecba00..be63509e60f94 100644 --- a/EventVisualisation/Detectors/src/DataInterpreterVSD.cxx +++ b/EventVisualisation/Detectors/src/DataInterpreterVSD.cxx @@ -43,8 +43,9 @@ DataInterpreterVSD::~DataInterpreterVSD() std::unique_ptr<VisualisationEvent> DataInterpreterVSD::interpretDataForType(TObject* data, EVisualisationDataType type) { - if (mVSD == nullptr) + if (mVSD == nullptr) { mVSD = new TEveVSD; + } this->DropEvent(); // Connect to new event-data. diff --git a/EventVisualisation/Detectors/src/DataReaderVSD.cxx b/EventVisualisation/Detectors/src/DataReaderVSD.cxx index ae940a02445b0..77b902caa1591 100644 --- a/EventVisualisation/Detectors/src/DataReaderVSD.cxx +++ b/EventVisualisation/Detectors/src/DataReaderVSD.cxx @@ -38,8 +38,9 @@ DataReaderVSD::DataReaderVSD() DataReaderVSD::~DataReaderVSD() { if (mEvDirKeys.size() > 0) { - for (auto obj : mEvDirKeys) + for (auto obj : mEvDirKeys) { delete obj; + } mEvDirKeys.clear(); } diff --git a/EventVisualisation/View/src/EventManager.cxx b/EventVisualisation/View/src/EventManager.cxx index bceb60d6a4bb0..15fcdd8cd8b41 100644 --- a/EventVisualisation/View/src/EventManager.cxx +++ b/EventVisualisation/View/src/EventManager.cxx @@ -43,20 +43,24 @@ EventManager* EventManager::instance = nullptr; EventManager& EventManager::getInstance() { - if (instance == nullptr) + if (instance == nullptr) { instance = new EventManager(); + } return *instance; } EventManager::EventManager() : TEveEventManager("Event", "") { LOG(INFO) << "Initializing TEveManager"; - for (unsigned int i = 0; i < elemof(dataInterpreters); i++) + for (unsigned int i = 0; i < elemof(dataInterpreters); i++) { dataInterpreters[i] = nullptr; - for (unsigned int i = 0; i < elemof(dataReaders); i++) + } + for (unsigned int i = 0; i < elemof(dataReaders); i++) { dataReaders[i] = nullptr; - for (unsigned int i = 0; i < elemof(dataTypeLists); i++) + } + for (unsigned int i = 0; i < elemof(dataTypeLists); i++) { dataTypeLists[i] = nullptr; + } } void EventManager::Open() diff --git a/EventVisualisation/View/src/Initializer.cxx b/EventVisualisation/View/src/Initializer.cxx index 0c4a93e759b3c..5df21b9f0fc15 100644 --- a/EventVisualisation/View/src/Initializer.cxx +++ b/EventVisualisation/View/src/Initializer.cxx @@ -108,12 +108,16 @@ void Initializer::setupGeometry() auto multiView = MultiView::getInstance(); //auto geometry_enabled = GeometryManager::getInstance().getR2Geometry()? R2Visualisation:R3Visualisation; for (int iDet = 0; iDet < NvisualisationGroups; ++iDet) { - if (GeometryManager::getInstance().getR2Geometry()) - if (!R2Visualisation[iDet]) + if (GeometryManager::getInstance().getR2Geometry()) { + if (!R2Visualisation[iDet]) { continue; - if (!GeometryManager::getInstance().getR2Geometry()) - if (!R3Visualisation[iDet]) + } + } + if (!GeometryManager::getInstance().getR2Geometry()) { + if (!R3Visualisation[iDet]) { continue; + } + } EVisualisationGroup det = static_cast<EVisualisationGroup>(iDet); string detName = gVisualisationGroupName[det]; diff --git a/EventVisualisation/View/src/main.cxx b/EventVisualisation/View/src/main.cxx index 680a338d032a4..f9d2c57aaf7d0 100644 --- a/EventVisualisation/View/src/main.cxx +++ b/EventVisualisation/View/src/main.cxx @@ -85,8 +85,9 @@ int main(int argc, char** argv) { LOG(INFO) << "Welcome in O2 event visualisation tool"; Options* options = processCommandLine(argc, argv); - if (options == nullptr) + if (options == nullptr) { exit(-1); + } srand(static_cast<unsigned int>(time(nullptr))); @@ -96,8 +97,9 @@ int main(int argc, char** argv) std::array<const char*, 7> keys = {"Gui.DefaultFont", "Gui.MenuFont", "Gui.MenuHiFont", "Gui.DocFixedFont", "Gui.DocPropFont", "Gui.IconFont", "Gui.StatusFont"}; for (const auto& key : keys) { - if (settings.Defined(key)) + if (settings.Defined(key)) { gEnv->SetValue(key, settings.GetValue(key, "")); + } } // create ROOT application environment diff --git a/Framework/AnalysisTools/include/Framework/StepTHn.h b/Framework/AnalysisTools/include/Framework/StepTHn.h index 24f0201d3de1c..33a06d260ef77 100644 --- a/Framework/AnalysisTools/include/Framework/StepTHn.h +++ b/Framework/AnalysisTools/include/Framework/StepTHn.h @@ -146,9 +146,9 @@ void StepTHn::Fill(Int_t istep, const Ts&... valuesAndWeight) bin *= mNbinsCache[i]; Int_t tmpBin = 0; - if (mLastVars[i] == tempArray[i]) + if (mLastVars[i] == tempArray[i]) { tmpBin = mLastBins[i]; - else { + } else { tmpBin = mAxisCache[i]->FindBin(tempArray[i]); mLastBins[i] = tmpBin; mLastVars[i] = tempArray[i]; @@ -156,8 +156,9 @@ void StepTHn::Fill(Int_t istep, const Ts&... valuesAndWeight) //Printf("%d", tmpBin); // under/overflow not supported - if (tmpBin < 1 || tmpBin > mNbinsCache[i]) + if (tmpBin < 1 || tmpBin > mNbinsCache[i]) { return; + } // bins start from 0 here bin += tmpBin - 1; @@ -179,8 +180,9 @@ void StepTHn::Fill(Int_t istep, const Ts&... valuesAndWeight) // TODO probably slow; add StepTHnT::add ? mValues[istep]->SetAt(mValues[istep]->GetAt(bin) + weight, bin); - if (mSumw2[istep]) + if (mSumw2[istep]) { mSumw2[istep]->SetAt(mSumw2[istep]->GetAt(bin) + weight, bin); + } } #endif diff --git a/Framework/AnalysisTools/src/StepTHn.cxx b/Framework/AnalysisTools/src/StepTHn.cxx index 8e99d3cac4db9..9bc3fe8391138 100644 --- a/Framework/AnalysisTools/src/StepTHn.cxx +++ b/Framework/AnalysisTools/src/StepTHn.cxx @@ -71,8 +71,9 @@ StepTHnT<TemplateArray>::StepTHnT(const Char_t* name, const Char_t* title, const Int_t* nBins, std::vector<Double_t> binEdges[], const char** axisTitles) : StepTHn(name, title, nSteps, nAxis, nBins, binEdges, axisTitles) { mNBins = 1; - for (Int_t i = 0; i < mNVars; i++) + for (Int_t i = 0; i < mNVars; i++) { mNBins *= nBins[i]; + } if constexpr (std::is_same_v<TemplateArray, TArrayD>) { mPrototype = new THnSparseD(Form("%s_sparse", name), title, nAxis, nBins); } else { @@ -165,8 +166,9 @@ StepTHn& StepTHn::operator=(const StepTHn& c) { // assigment operator - if (this != &c) + if (this != &c) { ((StepTHn&)c).Copy(*this); + } return *this; } @@ -186,19 +188,22 @@ void StepTHn::Copy(TObject& c) const target.init(); for (Int_t i = 0; i < mNSteps; i++) { - if (mValues[i]) + if (mValues[i]) { target.mValues[i] = createArray(mValues[i]); - else + } else { target.mValues[i] = nullptr; + } - if (mSumw2[i]) + if (mSumw2[i]) { target.mSumw2[i] = createArray(mSumw2[i]); - else + } else { target.mSumw2[i] = nullptr; + } } - if (mPrototype) + if (mPrototype) { target.mPrototype = dynamic_cast<THnSparseF*>(mPrototype->Clone()); + } } template <class TemplateArray> @@ -208,11 +213,13 @@ Long64_t StepTHnT<TemplateArray>::Merge(TCollection* list) // PROOF). // Returns the number of merged objects (including this). - if (!list) + if (!list) { return 0; + } - if (list->IsEmpty()) + if (list->IsEmpty()) { return 1; + } TIterator* iter = list->MakeIterator(); TObject* obj; @@ -221,28 +228,33 @@ Long64_t StepTHnT<TemplateArray>::Merge(TCollection* list) while ((obj = iter->Next())) { StepTHnT<TemplateArray>* entry = dynamic_cast<StepTHnT<TemplateArray>*>(obj); - if (entry == nullptr) + if (entry == nullptr) { continue; + } for (Int_t i = 0; i < mNSteps; i++) { if (entry->mValues[i]) { - if (!mValues[i]) + if (!mValues[i]) { mValues[i] = createArray(); + } auto source = dynamic_cast<TemplateArray*>(entry->mValues[i])->GetArray(); auto target = dynamic_cast<TemplateArray*>(mValues[i])->GetArray(); - for (Long64_t l = 0; l < mNBins; l++) + for (Long64_t l = 0; l < mNBins; l++) { target[l] += source[l]; + } } if (entry->mSumw2[i]) { - if (!mSumw2[i]) + if (!mSumw2[i]) { mSumw2[i] = createArray(); + } auto source = dynamic_cast<TemplateArray*>(entry->mSumw2[i])->GetArray(); auto target = dynamic_cast<TemplateArray*>(mSumw2[i])->GetArray(); - for (Long64_t l = 0; l < mNBins; l++) + for (Long64_t l = 0; l < mNBins; l++) { target[l] += source[l]; + } } } @@ -278,23 +290,27 @@ void StepTHn::createTarget(Int_t step, Bool_t sparse) if (!mTarget) { mTarget = new THnBase*[mNSteps]; - for (Int_t i = 0; i < mNSteps; i++) + for (Int_t i = 0; i < mNSteps; i++) { mTarget[i] = nullptr; + } } - if (mTarget[step]) + if (mTarget[step]) { return; + } TArray* source = mValues[step]; // if mSumw2 is not stored, the sqrt of the number of bin entries in source is filled below; otherwise we use mSumw2 TArray* sourceSumw2 = source; - if (mSumw2[step]) + if (mSumw2[step]) { sourceSumw2 = mSumw2[step]; + } - if (sparse) + if (sparse) { mTarget[step] = THnSparse::CreateSparse(Form("%s_%d", GetName(), step), Form("%s_%d", GetTitle(), step), mPrototype); - else + } else { mTarget[step] = THn::CreateHn(Form("%s_%d", GetName(), step), Form("%s_%d", GetTitle(), step), mPrototype); + } THnBase* target = mTarget[step]; @@ -332,8 +348,9 @@ void StepTHn::createTarget(Int_t step, Bool_t sparse) } } - if (binIdx[0] > nBins[0]) + if (binIdx[0] > nBins[0]) { break; + } } LOGF(info, "Step %d: copied %lld entries out of %lld bins", step, count, getGlobalBinIndex(binIdx)); diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 7232a9e9297c9..2b7d0e3aa1e83 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -225,13 +225,15 @@ struct HistFactory { for (std::size_t i = 0; i < nAxes; i++) { TAxis* axis{getAxis(i, hist)}; if (axis) { - if (histSpec.config.axes[i].title) + if (histSpec.config.axes[i].title) { axis->SetTitle((*histSpec.config.axes[i].title).data()); + } // this helps to have axes not only called 0,1,2... in ndim histos if constexpr (std::is_base_of_v<THnBase, T>) { - if (histSpec.config.axes[i].name) + if (histSpec.config.axes[i].name) { axis->SetName((std::string(axis->GetName()) + "-" + *histSpec.config.axes[i].name).data()); + } } // move the bin edges in case a variable binning was requested @@ -244,8 +246,9 @@ struct HistFactory { } } } - if (histSpec.callSumw2) + if (histSpec.callSumw2) { hist->Sumw2(); + } return hist; } @@ -254,19 +257,21 @@ struct HistFactory { template <typename T> static HistPtr createHistVariant(const HistogramSpec& histSpec) { - if (auto hist = castToVariant(createHist<T>(histSpec))) + if (auto hist = castToVariant(createHist<T>(histSpec))) { return *hist; - else + } else { throw runtime_error("Histogram was not created properly."); + } } // runtime version of the above static HistPtr createHistVariant(const HistogramSpec& histSpec) { - if (histSpec.config.type == HistType::kUndefinedHist) + if (histSpec.config.type == HistType::kUndefinedHist) { throw runtime_error("Histogram type was not specified."); - else + } else { return HistogramCreationCallbacks.at(histSpec.config.type)(histSpec); + } } // helper function to get the axis via index for any type of root histogram @@ -510,10 +515,11 @@ class HistogramRegistry template <typename T> auto& get(char const* const name) { - if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[getHistIndex(name)])) + if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[getHistIndex(name)])) { return *histPtr; - else + } else { throw runtime_error("Histogram type specified in get() does not match actual histogram type!"); + } } /// @return the histogram registered with name @a name diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 09e0479bab585..24dd25cdc7b90 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -46,8 +46,9 @@ void DataInputDescriptor::printOut() LOGP(INFO, " Input files file : {}", getInputfilesFilename()); LOGP(INFO, " File name regex : {}", getFilenamesRegexString()); LOGP(INFO, " Input files : {}", mfilenames.size()); - for (auto fn : mfilenames) + for (auto fn : mfilenames) { LOGP(INFO, " {} {}", fn->fileName, fn->numberOfTimeFrames); + } LOGP(INFO, " Total number of TF: {}", getNumberTimeFrames()); } @@ -599,8 +600,9 @@ void DataInputDirector::printOut() LOGP(INFO, " Default input files file : {}", minputfilesFile); LOGP(INFO, " Default file name regex : {}", mFilenameRegex); LOGP(INFO, " Default file names : {}", mdefaultInputFiles.size()); - for (auto const& fn : mdefaultInputFiles) + for (auto const& fn : mdefaultInputFiles) { LOGP(INFO, " {} {}", fn->fileName, fn->numberOfTimeFrames); + } LOGP(INFO, " Default DataInputDescriptor:"); mdefaultDataInputDescriptor->printOut(); LOGP(INFO, " DataInputDescriptors : {}", getNumberInputDescriptors()); diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 8ca0cb0338ed4..b537a0be067da 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -188,8 +188,9 @@ GPUdi() CONSTEXPR17 T GPUCommonMath::nextMultipleOf(T val) CONSTEXPRIF(I & (I - 1)) { T tmp = val % I; - if (tmp) + if (tmp) { val += I - tmp; + } return val; } else @@ -214,12 +215,14 @@ GPUdi() int GPUCommonMath::Nint(float x) int i; if (x >= 0) { i = int(x + 0.5f); - if (x + 0.5f == float(i) && i & 1) + if (x + 0.5f == float(i) && i & 1) { i--; + } } else { i = int(x - 0.5f); - if (x - 0.5f == float(i) && i & 1) + if (x - 0.5f == float(i) && i & 1) { i++; + } } return i; } diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index 9ca5ca58cc77b..4e1b6fc41a7fd 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -308,8 +308,9 @@ static std::atomic_flag timerFlag; // TODO: Should be a class member not global, GPUReconstructionCPU::timerMeta* GPUReconstructionCPU::insertTimer(unsigned int id, std::string&& name, int J, int num, int type, RecoStep step) { - while (timerFlag.test_and_set()) + while (timerFlag.test_and_set()) { ; + } if (mTimers.size() <= id) { mTimers.resize(id + 1); } @@ -327,8 +328,9 @@ GPUReconstructionCPU::timerMeta* GPUReconstructionCPU::insertTimer(unsigned int GPUReconstructionCPU::timerMeta* GPUReconstructionCPU::getTimerById(unsigned int id) { timerMeta* retVal = nullptr; - while (timerFlag.test_and_set()) + while (timerFlag.test_and_set()) { ; + } if (mTimers.size() > id && mTimers[id]) { retVal = mTimers[id].get(); retVal->count++; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index 8ad930d91fdb4..ea7659578305f 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -337,11 +337,13 @@ GPUd() int GPUTPCGMPropagator::PropagateToXAlphaBz(float posX, float posAlpha, b GPUTPCGMPhysicalTrackModel t0e(mT0); float dLp = 0; - if (t0e.PropagateToXBzLight(posX, Bz, dLp)) + if (t0e.PropagateToXBzLight(posX, Bz, dLp)) { return 1; + } - if (CAMath::Abs(t0e.SinPhi()) >= mMaxSinPhi) + if (CAMath::Abs(t0e.SinPhi()) >= mMaxSinPhi) { return -3; + } return FollowLinearization(t0e, Bz, dLp, inFlyDirection); } diff --git a/GPU/TPCFastTransformation/SplineHelper1D.cxx b/GPU/TPCFastTransformation/SplineHelper1D.cxx index 1d6e0c513d830..d9f4013e4bb3c 100644 --- a/GPU/TPCFastTransformation/SplineHelper1D.cxx +++ b/GPU/TPCFastTransformation/SplineHelper1D.cxx @@ -361,8 +361,9 @@ void SplineHelper1D<DataT>::approximateFunction( const int nPar = mSpline.getNumberOfParameters(1); double b[nPar]; for (int idim = 0; idim < mFdimensions; idim++) { - for (int i = 0; i < nPar; i++) + for (int i = 0; i < nPar; i++) { b[i] = 0.; + } for (int i = 0; i < getNumberOfDataPoints(); ++i) { const DataPoint& p = mDataPoints[i]; @@ -440,14 +441,17 @@ void SplineHelper1D<DataT>::approximateDerivatives( const double* row = mLSMmatrixSvalues.data(); for (int i = 0; i < nKnots; ++i, row += nKnots) { double s[Ndim]; - for (int d = 0; d < Ndim; d++) + for (int d = 0; d < Ndim; d++) { s[d] = 0.; + } for (int j = 0; j < nKnots; ++j) { - for (int d = 0; d < Ndim; d++) + for (int d = 0; d < Ndim; d++) { s[d] += row[j] * Fparameters[2 * j * Ndim + d]; + } } - for (int d = 0; d < Ndim; d++) + for (int d = 0; d < Ndim; d++) { b[i * Ndim + d] -= s[d]; + } } row = mLSMmatrixSderivatives.data(); diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 5bf65cf95d127..8fe26c7bc7acf 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -572,8 +572,9 @@ void TPCFastSpaceChargeCorrection::initInverse(bool prn) } chebFitterV.addMeasurement(cv, dv); } // v - if (prn) + if (prn) { std::cout << "u " << u << " nmeas " << chebFitterV.getNmeasurements() << std::endl; + } if (chebFitterV.getNmeasurements() < 1) { continue; } @@ -735,8 +736,9 @@ double TPCFastSpaceChargeCorrection::testInverse(bool prn) getCorrectionInvUV(slice, row, cu, cv, nu, nv); double d[3] = {nx - cx, nu - u, nv - v}; for (int i = 0; i < 3; i++) { - if (fabs(d[i]) > fabs(maxDrow[i])) + if (fabs(d[i]) > fabs(maxDrow[i])) { maxDrow[i] = d[i]; + } } if (prn && fabs(d[0]) + fabs(d[1]) + fabs(d[2]) > 0.1) { diff --git a/GPU/TPCFastTransformation/TPCFastTransform.cxx b/GPU/TPCFastTransformation/TPCFastTransform.cxx index a3878dbf4360e..4127eb6223692 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransform.cxx @@ -158,11 +158,13 @@ int TPCFastTransform::writeToFile(std::string outFName, std::string name) /// store to file assert(isConstructed()); - if (outFName.empty()) + if (outFName.empty()) { outFName = "tpcFastTransform.root"; + } - if (name.empty()) + if (name.empty()) { name = "TPCFastTransform"; + } TFile outf(outFName.data(), "recreate"); if (outf.IsZombie()) { @@ -171,12 +173,14 @@ int TPCFastTransform::writeToFile(std::string outFName, std::string name) } bool isBufferExternal = !isBufferInternal(); - if (isBufferExternal) + if (isBufferExternal) { adoptInternalBuffer(mFlatBufferPtr); + } outf.WriteObjectAny(this, Class(), name.data()); outf.Close(); - if (isBufferExternal) + if (isBufferExternal) { clearInternalBufferPtr(); + } return 0; } @@ -184,11 +188,13 @@ TPCFastTransform* TPCFastTransform::loadFromFile(std::string inpFName, std::stri { /// load from file - if (inpFName.empty()) + if (inpFName.empty()) { inpFName = "tpcFastTransform.root"; + } - if (name.empty()) + if (name.empty()) { name = "TPCFastTransform"; + } TFile inpf(inpFName.data()); if (inpf.IsZombie()) { diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx index ae09e5f94cee2..f88d192a99598 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx @@ -152,11 +152,13 @@ int TPCFastTransformGeo::test(int slice, int row, float ly, float lz) const int error = 0; - if (!isConstructed()) + if (!isConstructed()) { error = -1; + } - if (mNumberOfRows <= 0 || mNumberOfRows >= MaxNumberOfRows) + if (mNumberOfRows <= 0 || mNumberOfRows >= MaxNumberOfRows) { error = -2; + } float lx = getRowInfo(row).x; float lx1 = 0.f, ly1 = 0.f, lz1 = 0.f; diff --git a/GPU/TPCFastTransformation/devtools/IrregularSpline1D.cxx b/GPU/TPCFastTransformation/devtools/IrregularSpline1D.cxx index ae97939980c2f..7c4deefd01f3f 100644 --- a/GPU/TPCFastTransformation/devtools/IrregularSpline1D.cxx +++ b/GPU/TPCFastTransformation/devtools/IrregularSpline1D.cxx @@ -187,8 +187,9 @@ void IrregularSpline1D::constructRegular(int numberOfKnots) /// \param numberOfKnots Number of knots /// - if (numberOfKnots < 5) + if (numberOfKnots < 5) { numberOfKnots = 5; + } std::vector<float> knots(numberOfKnots); double du = 1. / (numberOfKnots - 1.); diff --git a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h index e0e652717dad2..d4a41935c521c 100644 --- a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h +++ b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h @@ -353,8 +353,9 @@ GPUdi() void IrregularSpline2D3D::getSplineVec(const float* correctedData, float //dataVvec.scatter(dataV, Vc::SimdArray<uint, 12>(Vc::IndexesFromZero)); dataVvec.store(dataV, Vc::Unaligned); - for (unsigned int i = 12; i < 9 + V::size(); i++) // fill not used part of the vector with 0 + for (unsigned int i = 12; i < 9 + V::size(); i++) { // fill not used part of the vector with 0 dataV[i] = 0.f; + } // calculate F values at V==v and U == u V dataU0vec(dataV), dataU1vec(dataV + 3), dataU2vec(dataV + 6), dataU3vec(dataV + 9); diff --git a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx index ec8c4667a0ca6..7696dce156563 100644 --- a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx +++ b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx @@ -38,8 +38,9 @@ void IrregularSpline2D3DCalibrator::setRasterSize(int nKnotsU, int nKnotsV) int n[2] = {nKnotsU, nKnotsV}; for (int uv = 0; uv < 2; ++uv) { - if (n[uv] < mMaxNKnots[uv]) + if (n[uv] < mMaxNKnots[uv]) { n[uv] = mMaxNKnots[uv]; + } } mRaster.constructRegular(n[0], n[1]); @@ -53,8 +54,9 @@ void IrregularSpline2D3DCalibrator::setMaxNKnots(int nKnotsU, int nKnotsV) mMaxNKnots[1] = nKnotsV; for (int uv = 0; uv < 2; ++uv) { - if (mMaxNKnots[uv] < 5) + if (mMaxNKnots[uv] < 5) { mMaxNKnots[uv] = 5; + } } } @@ -88,10 +90,12 @@ void IrregularSpline2D3DCalibrator::startCalibration(std::function<void(float, f double u = i * du; d.rasterKnot = nearbyint(u * (mRaster.getGrid(uv).getNumberOfKnots() - 1)); //std::cout<<"uv "<<uv<<" i "<<d.rasterKnot<<" u "<<u<<std::endl; - if (d.rasterKnot <= lastKnot) + if (d.rasterKnot <= lastKnot) { continue; - if (d.rasterKnot >= mRaster.getGrid(uv).getNumberOfKnots() - 1) + } + if (d.rasterKnot >= mRaster.getGrid(uv).getNumberOfKnots() - 1) { continue; + } mKnots[uv].push_back(d); lastKnot = d.rasterKnot; } @@ -158,8 +162,9 @@ IrregularSpline2D3DCalibrator::Action IrregularSpline2D3DCalibrator::checkAction std::list<KnotData>::iterator next = knot; ++next; if (next != mKnots[uv].end()) { - if (next->rasterKnot <= knot->rasterKnot + 1) + if (next->rasterKnot <= knot->rasterKnot + 1) { isSpaceUp = 0; + } } } @@ -170,13 +175,15 @@ IrregularSpline2D3DCalibrator::Action IrregularSpline2D3DCalibrator::checkAction std::list<KnotData>::iterator prev = knot; if (prev != mKnots[uv].begin()) { --prev; - if (prev->rasterKnot >= knot->rasterKnot - 1) + if (prev->rasterKnot >= knot->rasterKnot - 1) { isSpaceDn = 0; + } } } - if (!isSpaceUp && !isSpaceDn) + if (!isSpaceUp && !isSpaceDn) { return ret; + } // get the area of interest @@ -224,8 +231,9 @@ IrregularSpline2D3DCalibrator::Action IrregularSpline2D3DCalibrator::checkAction int uv = knot->uv; - if (mSpline.getGrid(uv).getNumberOfKnots() <= 5) + if (mSpline.getGrid(uv).getNumberOfKnots() <= 5) { return ret; + } // get the area of interest @@ -289,8 +297,9 @@ bool IrregularSpline2D3DCalibrator::doCalibrationStep() for (int uv = 0; uv < 2; ++uv) { for (std::list<KnotData>::iterator i = mKnots[uv].begin(); i != mKnots[uv].end(); ++i) { Action a = checkActionShift(i); - if (a.cost < bestAction.cost) + if (a.cost < bestAction.cost) { bestAction = a; + } } } @@ -320,8 +329,9 @@ bool IrregularSpline2D3DCalibrator::doCalibrationStep() for (std::list<KnotData>::iterator i = mKnots[uv].begin(); i != mKnots[uv].end(); ++i) { Action a = checkActionRemove(i); - if (a.cost < bestAction.cost) + if (a.cost < bestAction.cost) { bestAction = a; + } } } bestAction.cost = sqrt(bestAction.cost / 3.); @@ -349,8 +359,9 @@ std::unique_ptr<float[]> IrregularSpline2D3DCalibrator::calibrateSpline(Irregula // main method: spline calibration startCalibration(F); - while (doCalibrationStep()) + while (doCalibrationStep()) { ; + } createCurrentSpline(); spline_uv.cloneFromObject(mSpline, nullptr); std::unique_ptr<float[]> tmp(new float[mSpline.getNumberOfKnots()]); @@ -377,8 +388,9 @@ double IrregularSpline2D3DCalibrator::getMaxDeviationLine(const IrregularSpline2 double dy = fy - fy0; double dz = fz - fz0; double d2 = dx * dx + dy * dy + dz * dz; - if (dMax2 < d2) + if (dMax2 < d2) { dMax2 = d2; + } } return dMax2; } @@ -389,8 +401,9 @@ double IrregularSpline2D3DCalibrator::getMaxDeviationArea(const IrregularSpline2 double dMax = 0.; for (int knot = knotFirst; knot <= knotLast; ++knot) { double d = getMaxDeviationLine(spline, data, axis, knot); - if (dMax < d) + if (dMax < d) { dMax = d; + } } return dMax; } diff --git a/GPU/TPCFastTransformation/devtools/RegularSpline1D.h b/GPU/TPCFastTransformation/devtools/RegularSpline1D.h index cacc8a6523e2e..8d2fa51440b1d 100644 --- a/GPU/TPCFastTransformation/devtools/RegularSpline1D.h +++ b/GPU/TPCFastTransformation/devtools/RegularSpline1D.h @@ -141,10 +141,12 @@ inline T RegularSpline1D::getSpline(const T correctedData[], float u) const inline double RegularSpline1D::knotIndexToU(int iknot) const { - if (iknot <= 0) + if (iknot <= 0) { return 0; - if (iknot >= mNumberOfKnots) + } + if (iknot >= mNumberOfKnots) { return 1; + } return iknot / ((double)mNumberOfKnots - 1.); } @@ -152,10 +154,11 @@ inline int RegularSpline1D::getKnotIndex(float u) const { //index is just u elem [0, 1] * numberOfKnots and then floored. (so the "left" coordinate beside u gets chosen) int index = (int)(u * (mNumberOfKnots - 1)); - if (index <= 1) + if (index <= 1) { index = 1; - else if (index >= mNumberOfKnots - 3) + } else if (index >= mNumberOfKnots - 3) { index = mNumberOfKnots - 3; + } return index; } diff --git a/GPU/Utils/FlatObject.h b/GPU/Utils/FlatObject.h index c4896e50c0f8b..3fa85bd81ff03 100644 --- a/GPU/Utils/FlatObject.h +++ b/GPU/Utils/FlatObject.h @@ -407,13 +407,15 @@ inline std::string FlatObject::stressTest(T& obj) /// std::string err; - if (!obj.isConstructed()) + if (!obj.isConstructed()) { return "tested object is not constructed!"; + } T tst; tst.cloneFromObject(obj, nullptr); - if (!tst.isConstructed() || !tst.isBufferInternal()) + if (!tst.isConstructed() || !tst.isBufferInternal()) { return "error at cloneFromObject()!"; + } obj.destroy(); @@ -428,16 +430,19 @@ inline std::string FlatObject::stressTest(T& obj) std::memcpy(buf2, buf1, tst.getFlatBufferSize()); delete[] buf1; - if (tst.isBufferInternal()) + if (tst.isBufferInternal()) { return err = "error, buffer should be external!"; + } tst.adoptInternalBuffer(buf2); - if (!tst.isBufferInternal()) + if (!tst.isBufferInternal()) { return err = "error, buffer should be internal!"; + } obj.cloneFromObject(tst, nullptr); - if (!obj.isBufferInternal()) + if (!obj.isBufferInternal()) { return err = "error, buffer should be internal!"; + } return err; } diff --git a/Generators/src/DecayerPythia8.cxx b/Generators/src/DecayerPythia8.cxx index ec8df5fc3315e..77c4c04cff7b7 100644 --- a/Generators/src/DecayerPythia8.cxx +++ b/Generators/src/DecayerPythia8.cxx @@ -39,8 +39,9 @@ void DecayerPythia8::Init() LOG(INFO) << "Init \'DecayerPythia8\' with following parameters"; LOG(INFO) << param; for (int i = 0; i < 8; ++i) { - if (param.config[i].empty()) + if (param.config[i].empty()) { continue; + } std::string config = gSystem->ExpandPathName(param.config[i].c_str()); LOG(INFO) << "Reading configuration from file: " << config; if (!mPythia.readFile(config, true)) { @@ -54,10 +55,11 @@ void DecayerPythia8::Init() mVerbose = param.verbose; /** show changed particle data **/ - if (param.showChanged) + if (param.showChanged) { mPythia.readString(std::string("Init:showChangedParticleData on")); - else + } else { mPythia.readString(std::string("Init:showChangedParticleData off")); + } /** initialise **/ if (!mPythia.init()) { @@ -76,8 +78,9 @@ void DecayerPythia8::Decay(Int_t pdg, TLorentzVector* lv) mPythia.event.clear(); mPythia.event.append(pdg, 11, 0, 0, lv->Px(), lv->Py(), lv->Pz(), lv->E(), lv->M()); mPythia.moreDecays(); - if (mVerbose) + if (mVerbose) { mPythia.event.list(); + } mPythia.particleData.mayDecay(pdg, mayDecay); // restore mayDecay status } diff --git a/Generators/src/Generator.cxx b/Generators/src/Generator.cxx index 48333a2f3a056..21a1916a7a337 100644 --- a/Generators/src/Generator.cxx +++ b/Generators/src/Generator.cxx @@ -68,21 +68,25 @@ Bool_t mParticles.clear(); /** generate event **/ - if (!generateEvent()) + if (!generateEvent()) { return kFALSE; + } /** import particles **/ - if (!importParticles()) + if (!importParticles()) { return kFALSE; + } /** trigger event **/ - if (triggerEvent()) + if (triggerEvent()) { break; + } } /** add tracks **/ - if (!addTracks(primGen)) + if (!addTracks(primGen)) { return kFALSE; + } /** update header **/ updateHeader(primGen->GetEvent()); @@ -146,36 +150,42 @@ Bool_t /** trigger event **/ /** check trigger presence **/ - if (mTriggers.size() == 0 && mDeepTriggers.size() == 0) + if (mTriggers.size() == 0 && mDeepTriggers.size() == 0) { return kTRUE; + } /** check trigger mode **/ Bool_t triggered; - if (mTriggerMode == kTriggerOFF) + if (mTriggerMode == kTriggerOFF) { return kTRUE; - else if (mTriggerMode == kTriggerOR) + } else if (mTriggerMode == kTriggerOR) { triggered = kFALSE; - else if (mTriggerMode == kTriggerAND) + } else if (mTriggerMode == kTriggerAND) { triggered = kTRUE; - else + } else { return kTRUE; + } /** loop over triggers **/ for (const auto& trigger : mTriggers) { auto retval = trigger(mParticles); - if (mTriggerMode == kTriggerOR) + if (mTriggerMode == kTriggerOR) { triggered |= retval; - if (mTriggerMode == kTriggerAND) + } + if (mTriggerMode == kTriggerAND) { triggered &= retval; + } } /** loop over deep triggers **/ for (const auto& trigger : mDeepTriggers) { auto retval = trigger(mInterface, mInterfaceName); - if (mTriggerMode == kTriggerOR) + if (mTriggerMode == kTriggerOR) { triggered |= retval; - if (mTriggerMode == kTriggerAND) + } + if (mTriggerMode == kTriggerAND) { triggered &= retval; + } } /** return **/ diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index bc74f9f0983fb..9af65cf5a0b72 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -258,10 +258,12 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair return; } generator->setTriggerMode(o2::eventgen::Generator::kTriggerOR); - if (trigger) + if (trigger) { generator->addTrigger(trigger); - if (deeptrigger) + } + if (deeptrigger) { generator->addDeepTrigger(deeptrigger); + } } } diff --git a/Generators/src/GeneratorFromFile.cxx b/Generators/src/GeneratorFromFile.cxx index 1838438aca3fb..a93a750b256f9 100644 --- a/Generators/src/GeneratorFromFile.cxx +++ b/Generators/src/GeneratorFromFile.cxx @@ -40,8 +40,9 @@ GeneratorFromFile::GeneratorFromFile(const char* name) // std::cout << "probing for " << eventstring << "\n"; object = mEventFile->Get(eventstringstr.str().c_str()); // std::cout << "got " << object << "\n"; - if (object != nullptr) + if (object != nullptr) { mEventsAvailable++; + } } while (object != nullptr); LOG(INFO) << "Found " << mEventsAvailable << " events in this file \n"; } diff --git a/Generators/src/GeneratorHepMC.cxx b/Generators/src/GeneratorHepMC.cxx index 47dd365aec2c3..ac0b76c4e666c 100644 --- a/Generators/src/GeneratorHepMC.cxx +++ b/Generators/src/GeneratorHepMC.cxx @@ -61,14 +61,16 @@ GeneratorHepMC::~GeneratorHepMC() { /** default destructor **/ - if (mStream.is_open()) + if (mStream.is_open()) { mStream.close(); + } if (mReader) { mReader->close(); delete mReader; } - if (mEvent) + if (mEvent) { delete mEvent; + } } /*****************************************************************/ @@ -80,8 +82,9 @@ Bool_t GeneratorHepMC::generateEvent() /** clear and read event **/ mEvent->clear(); mReader->read_event(*mEvent); - if (mReader->failed()) + if (mReader->failed()) { return kFALSE; + } /** set units to desired output **/ mEvent->set_units(HepMC3::Units::GEV, HepMC3::Units::MM); diff --git a/Generators/src/GeneratorPythia6.cxx b/Generators/src/GeneratorPythia6.cxx index 3473acf87a957..470d1ecb89e5b 100644 --- a/Generators/src/GeneratorPythia6.cxx +++ b/Generators/src/GeneratorPythia6.cxx @@ -69,18 +69,21 @@ Bool_t GeneratorPythia6::Init() for (std::string line; getline(fin, line);) { /** remove comments **/ line = line.substr(0, line.find_first_of(comment)); - if (line.size() == 0) + if (line.size() == 0) { continue; + } /** remove leading/trailing whitespaces **/ const auto line_begin = line.find_first_not_of(whitespace); const auto line_end = line.find_last_not_of(whitespace); if (line_begin == std::string::npos || - line_end == std::string::npos) + line_end == std::string::npos) { continue; + } const auto line_range = line_end - line_begin + 1; line = line.substr(line_begin, line_range); - if (line.size() == 0) + if (line.size() == 0) { continue; + } /** process command **/ readString(line.c_str()); } diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 23086e5237fe0..0727de5083739 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -120,8 +120,9 @@ Bool_t /** generate event **/ /** generate event **/ - if (!mPythia.next()) + if (!mPythia.next()) { return false; + } #if PYTHIA_VERSION_INTEGER < 8300 /** [NOTE] The issue with large particle production vertex when running @@ -202,8 +203,9 @@ void GeneratorPythia8::updateHeader(FairMCEventHeader* eventHeader) #endif /** set impact parameter if in heavy-ion mode **/ - if (hiinfo) + if (hiinfo) { eventHeader->SetB(hiinfo->b()); + } } /*****************************************************************/ @@ -221,16 +223,18 @@ void GeneratorPythia8::selectFromAncestor(int ancestor, Pythia8::Event& inputEve select = [&](int i) { selected.insert(i); auto dl = inputEvent[i].daughterList(); - for (auto j : dl) + for (auto j : dl) { select(j); + } }; select(ancestor); // map selected particle index to output index std::map<int, int> indexMap; int index = outputEvent.size(); - for (auto i : selected) + for (auto i : selected) { indexMap[i] = index++; + } // adjust mother/daughter indices and append to output event for (auto i : selected) { diff --git a/Generators/src/PrimaryGenerator.cxx b/Generators/src/PrimaryGenerator.cxx index fed6ffb4c1b92..2e76ac6d9a373 100644 --- a/Generators/src/PrimaryGenerator.cxx +++ b/Generators/src/PrimaryGenerator.cxx @@ -40,8 +40,9 @@ PrimaryGenerator::~PrimaryGenerator() mEmbedFile->Close(); delete mEmbedFile; } - if (mEmbedEvent) + if (mEmbedEvent) { delete mEmbedEvent; + } } /*****************************************************************/ @@ -76,8 +77,9 @@ Bool_t PrimaryGenerator::GenerateEvent(FairGenericStack* pStack) /** generate event **/ /** normal generation if no embedding **/ - if (!mEmbedTree) + if (!mEmbedTree) { return FairPrimaryGenerator::GenerateEvent(pStack); + } /** this is for embedding **/ @@ -89,13 +91,15 @@ Bool_t PrimaryGenerator::GenerateEvent(FairGenericStack* pStack) auto genList = GetListOfGenerators(); for (int igen = 0; igen < genList->GetEntries(); ++igen) { auto o2gen = dynamic_cast<Generator*>(genList->At(igen)); - if (o2gen) + if (o2gen) { o2gen->notifyEmbedding(mEmbedEvent); + } } /** generate event **/ - if (!FairPrimaryGenerator::GenerateEvent(pStack)) + if (!FairPrimaryGenerator::GenerateEvent(pStack)) { return kFALSE; + } /** add embedding info to event header **/ auto o2event = dynamic_cast<MCEventHeader*>(fEvent); diff --git a/Generators/src/TriggerParticle.cxx b/Generators/src/TriggerParticle.cxx index ece35bb65b278..dca26f5874a80 100644 --- a/Generators/src/TriggerParticle.cxx +++ b/Generators/src/TriggerParticle.cxx @@ -25,16 +25,21 @@ Trigger TriggerParticle(const TriggerParticleParam& param) LOG(INFO) << param; return [¶m](const std::vector<TParticle>& particles) -> bool { for (const auto& particle : particles) { - if (particle.GetPdgCode() != param.pdg) + if (particle.GetPdgCode() != param.pdg) { continue; - if (particle.Pt() < param.ptMin || particle.Pt() > param.ptMax) + } + if (particle.Pt() < param.ptMin || particle.Pt() > param.ptMax) { continue; - if (particle.Eta() < param.etaMin || particle.Eta() > param.etaMax) + } + if (particle.Eta() < param.etaMin || particle.Eta() > param.etaMax) { continue; - if (particle.Phi() < param.phiMin || particle.Phi() > param.phiMax) + } + if (particle.Phi() < param.phiMin || particle.Phi() > param.phiMax) { continue; - if (particle.Y() < param.yMin || particle.Y() > param.yMax) + } + if (particle.Y() < param.yMin || particle.Y() > param.yMax) { continue; + } return true; /** trigger fired **/ } return false; /** trigger did not fire **/ diff --git a/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.cxx index 488595cbc756e..2621c2355f512 100644 --- a/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/CPVDigitizerSpec.cxx @@ -81,8 +81,9 @@ void DigitizerSpec::retrieveHits(const char* brname, void DigitizerSpec::run(framework::ProcessingContext& pc) { - if (mFinished) + if (mFinished) { return; + } // read collision context from input auto context = pc.inputs().get<o2::steer::DigitizationContext*>("collisioncontext"); diff --git a/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx index e111b2c4dedda..30cf2d36ec786 100644 --- a/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx @@ -48,8 +48,9 @@ void DigitizerSpec::initDigitizerTask(framework::InitContext& ctx) void DigitizerSpec::run(framework::ProcessingContext& ctx) { - if (mFinished) + if (mFinished) { return; + } // read collision context from input auto context = ctx.inputs().get<o2::steer::DigitizationContext*>("collisioncontext"); @@ -58,8 +59,9 @@ void DigitizerSpec::run(framework::ProcessingContext& ctx) LOG(DEBUG) << "GOT " << timesview.size() << " COLLISSION TIMES"; // if there is nothing to do ... return - if (timesview.size() == 0) + if (timesview.size() == 0) { return; + } TStopwatch timer; timer.Start(); @@ -92,8 +94,9 @@ void DigitizerSpec::run(framework::ProcessingContext& ctx) mDigitizer.setEventTime(timesview[collID].getTimeNS()); - if (!mDigitizer.isLive()) + if (!mDigitizer.isLive()) { continue; + } if (mDigitizer.isEmpty()) { mDigitizer.initCycle(); diff --git a/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.cxx index 658ef2efa08bb..fde0562970a56 100644 --- a/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.cxx @@ -75,8 +75,9 @@ void DigitizerSpec::retrieveHits(const char* brname, void DigitizerSpec::run(framework::ProcessingContext& pc) { - if (mFinished) + if (mFinished) { return; + } // read collision context from input auto context = pc.inputs().get<o2::steer::DigitizationContext*>("collisioncontext"); diff --git a/Steer/src/InteractionSampler.cxx b/Steer/src/InteractionSampler.cxx index b9238d1801320..b59cca5c1804d 100644 --- a/Steer/src/InteractionSampler.cxx +++ b/Steer/src/InteractionSampler.cxx @@ -55,16 +55,18 @@ void InteractionSampler::init() // Poisson distribution of number of collisions in the bunch excluding 0 mNCollBCGenerator.initialize([mu]() { int n = 0; - while ((n = gRandom->Poisson(mu)) == 0) + while ((n = gRandom->Poisson(mu)) == 0) { ; + } return n; }); auto trms = mBCTimeRMS; mCollTimeGenerator.initialize([trms]() { float t; // make sure it does not go outside half bunch - while (std::abs(t = gRandom->Gaus(0, trms)) > o2::constants::lhc::LHCBunchSpacingNS / 2.1) + while (std::abs(t = gRandom->Gaus(0, trms)) > o2::constants::lhc::LHCBunchSpacingNS / 2.1) { ; + } return t; }); diff --git a/Steer/src/O2MCApplication.cxx b/Steer/src/O2MCApplication.cxx index 50776cc5db802..57d70317c24c3 100644 --- a/Steer/src/O2MCApplication.cxx +++ b/Steer/src/O2MCApplication.cxx @@ -183,8 +183,9 @@ void O2MCApplicationBase::AddParticles() LOG(INFO) << param; // check if there are PDG codes requested for user decay - if (param.pdglist.empty()) + if (param.pdglist.empty()) { return; + } // loop over PDG codes in the string std::stringstream ss(param.pdglist); diff --git a/Utilities/DataSampling/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx index df307b007c397..e4e434ff66fa8 100644 --- a/Utilities/DataSampling/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -55,8 +55,9 @@ void Dispatcher::init(InitContext& ctx) } else if (ctx.options().isSet("sampling-config-ptree")) { policiesTree = ctx.options().get<boost::property_tree::ptree>("sampling-config-ptree"); mPolicies.clear(); - } else + } else { ; // we use policies declared during workflow init. + } for (auto&& policyConfig : policiesTree) { // we don't want the Dispatcher to exit due to one faulty Policy From 676af9195e55e4ab091c22e4be0727c2272664c4 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 11 Nov 2020 21:57:44 +0100 Subject: [PATCH 1288/1751] DPL: fix naming for internal-dpl-***aod***-index-builder (#4816) We treat `internal-dpl-***aod***` in a special manner when handling socket polling compared to `internal-dpl` which are considered non pollable. This fully explains the recent locking issues. --- Framework/Core/src/WorkflowHelpers.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index c13e614268d5c..bd5ed815c56c4 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -382,7 +382,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext {}}; DataProcessorSpec indexBuilder{ - "internal-dpl-index-builder", + "internal-dpl-aod-index-builder", {}, {}, readers::AODReaderHelpers::indexBuilderCallback(requestedIDXs), From b90cb72aa09057974f01313ed4075bba10d1af82 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 11 Nov 2020 21:59:48 +0100 Subject: [PATCH 1289/1751] Revert "DPL: for polling after the first EoS" (#4817) This reverts commit 3ebd4d41c7e70cdd35925d73ce781443a4a0d367. --- Framework/Core/src/DataProcessingDevice.cxx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index fb21a635d7769..01ba3816663dc 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -499,14 +499,6 @@ void DataProcessingDevice::doPrepare(DataProcessorContext& context) auto& channel = context.spec->inputChannels[ci]; auto& info = context.state->inputChannelInfos[ci]; - // If at least one channel is complete, we keep polling for the remaining - // stuff. - // FIXME: this is definitely not what we want, but - // it should get the analysis working. - if (info.state == InputChannelState::Completed) { - *context.wasActive = true; - } - if (info.state != InputChannelState::Completed && info.state != InputChannelState::Pull) { context.allDone = false; } From 7d69af3de7b2707fa9716344281b0d8eaa405ca0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 11 Nov 2020 14:40:20 +0100 Subject: [PATCH 1290/1751] GPU: Add setter to initialize GPUReconstruction with only the recoStep settings + bz --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 4 ++-- GPU/GPUTracking/Base/GPUReconstruction.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 56945a35b01ef..45982367e2304 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -952,12 +952,12 @@ int GPUReconstruction::ReadSettings(const char* dir) return 0; } -void GPUReconstruction::SetSettings(float solenoidBz) +void GPUReconstruction::SetSettings(float solenoidBz, const GPURecoStepConfiguration* workflow) { GPUSettingsEvent ev; new (&ev) GPUSettingsEvent; ev.solenoidBz = solenoidBz; - SetSettings(&ev, nullptr, nullptr); + SetSettings(&ev, nullptr, nullptr, workflow); } void GPUReconstruction::SetSettings(const GPUSettingsEvent* settings, const GPUSettingsRec* rec, const GPUSettingsProcessing* proc, const GPURecoStepConfiguration* workflow) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.h b/GPU/GPUTracking/Base/GPUReconstruction.h index fbd8ae15da8a5..5bb4f7aa61e6a 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.h +++ b/GPU/GPUTracking/Base/GPUReconstruction.h @@ -226,7 +226,7 @@ class GPUReconstruction const GPUSettingsDeviceBackend& GetDeviceBackendSettings() { return mDeviceBackendSettings; } const GPUSettingsProcessing& GetProcessingSettings() const { return mProcessingSettings; } bool IsInitialized() const { return mInitialized; } - void SetSettings(float solenoidBz); + void SetSettings(float solenoidBz, const GPURecoStepConfiguration* workflow = nullptr); void SetSettings(const GPUSettingsEvent* settings, const GPUSettingsRec* rec = nullptr, const GPUSettingsProcessing* proc = nullptr, const GPURecoStepConfiguration* workflow = nullptr); void SetResetTimers(bool reset) { mProcessingSettings.resetTimers = reset; } // May update also after Init() void SetDebugLevelTmp(int level) { mProcessingSettings.debugLevel = level; } // Temporarily, before calling SetSettings() From 8f41f35c2646793ab2e5ddef445c83c6d849caef Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 12 Nov 2020 11:17:42 +0100 Subject: [PATCH 1291/1751] DPL: fix name of global-analysis-file-sink (#4820) --- Framework/Core/src/CommonDataProcessors.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index cc587aa7b928e..549edb6bfdee9 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -226,7 +226,7 @@ DataProcessorSpec CommonDataProcessors::getOutputObjHistSink(outputObjects const }; DataProcessorSpec spec{ - "internal-dpl-global-analysis-file-sink", + "internal-dpl-aod-global-analysis-file-sink", {InputSpec("x", DataSpecUtils::dataDescriptorMatcherFrom(header::DataOrigin{"ATSK"}))}, Outputs{}, AlgorithmSpec(writerFunction), From b0dac81f4fee625988b69d3919cb26729142be04 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 11 Nov 2020 10:19:49 +0100 Subject: [PATCH 1292/1751] CCDB API: generalization of content retrival (part 1) This commit achieves the following: a) support for cases in which the CCDB server does not serve content directly but redirects to other resources b) support for objects on ALIEN resource Changes are offered only for retrieval of objects via the strongly typed interfaces (no new features for interfaces based on TObject*). A new test is added - querying from a server with ALIEN backend. This concerns: https://alice.its.cern.ch/jira/browse/O2-1809 The PR is potentially incomplete. Further changes in other places or tools likely. --- CCDB/CMakeLists.txt | 6 + CCDB/include/CCDB/CcdbApi.h | 25 ++++ CCDB/src/CcdbApi.cxx | 242 +++++++++++++++++++++----------- CCDB/test/testCcdbApi_alien.cxx | 102 ++++++++++++++ 4 files changed, 292 insertions(+), 83 deletions(-) create mode 100644 CCDB/test/testCcdbApi_alien.cxx diff --git a/CCDB/CMakeLists.txt b/CCDB/CMakeLists.txt index b592cb27d8213..a91a3aa31347e 100644 --- a/CCDB/CMakeLists.txt +++ b/CCDB/CMakeLists.txt @@ -51,6 +51,12 @@ o2_add_test(CcdbApi PUBLIC_LINK_LIBRARIES O2::CCDB LABELS ccdb) +o2_add_test(CcdbApi-Alien + SOURCES test/testCcdbApi_alien.cxx + COMPONENT_NAME ccdb + PUBLIC_LINK_LIBRARIES O2::CCDB + LABELS ccdb) + o2_add_test(BasicCCDBManager SOURCES test/testBasicCCDBManager.cxx COMPONENT_NAME ccdb diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index 7fbf711845636..9b7612caab445 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -25,6 +25,7 @@ #include "CCDB/CcdbObjectInfo.h" class TFile; +class TGrid; namespace o2 { @@ -377,6 +378,26 @@ class CcdbApi //: public DatabaseInterface */ void* extractFromLocalFile(std::string const& filename, TClass const* cl) const; + /** + * Helper function to download binary content from alien:// storage + * @param fullUrl The alien URL + * @param tcl The TClass object describing the serialized type + * @return raw pointer to created object + */ + void* downloadAlienContent(std::string const& fullUrl, TClass* tcl) const; + + // initialize the TGrid (Alien connection) + bool initTGrid() const; + // checks if an alien token is available, required to make a TGrid connection + bool checkAlienToken() const; + + /// Queries the CCDB server and navigates through possible redirects until binary content is found; Retrieves content as instance + /// given by TClass if that is possible. Returns nullptr if something fails... + void* navigateURLsAndRetrieveContent(CURL*, std::string const& url, TClass* cl, std::map<std::string, std::string>* headers) const; + + // helper that interprets a content chunk as TMemFile and extracts the object therefrom + void* interpretAsTMemFileAndExtract(char* contentptr, size_t contentsize, TClass* cl) const; + /** * Initialization of CURL */ @@ -386,6 +407,10 @@ class CcdbApi //: public DatabaseInterface std::string mUrl{}; std::string mSnapshotTopPath{}; bool mInSnapshotMode = false; + mutable std::multimap<std::string, std::string> mHeaderData; //! a "global" internal data structure that can be filled with HTTP header information + // (without need to recreate this structure locally each time) + mutable TGrid* mAlienInstance = nullptr; // a cached connection to TGrid (needed for Alien locations) + bool mHaveAlienToken = false; // stores if an alien token is available ClassDefNV(CcdbApi, 1); }; diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 243e431d0380b..52e61710d0775 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -22,6 +22,7 @@ #include <TMessage.h> #include <sstream> #include <TFile.h> +#include <TGrid.h> #include <TSystem.h> #include <TStreamerInfo.h> #include <TMemFile.h> @@ -70,6 +71,12 @@ void CcdbApi::init(std::string const& host) } else { curlInit(); } + + // find out if we can can in principle connect to Alien + mHaveAlienToken = checkAlienToken(); + if (!mHaveAlienToken) { + LOG(WARN) << "CCDB: Did not find an alien token; Cannot serve objects located on alien://"; + } } /** @@ -391,15 +398,16 @@ std::string CcdbApi::generateFileName(const std::string& inp) namespace { +template <typename MapType = std::map<std::string, std::string>> size_t header_map_callback(char* buffer, size_t size, size_t nitems, void* userdata) { - auto* headers = static_cast<std::map<std::string, std::string>*>(userdata); + auto* headers = static_cast<MapType*>(userdata); auto header = std::string(buffer, size * nitems); std::string::size_type index = header.find(':', 0); if (index != std::string::npos) { - headers->insert(std::make_pair( - boost::algorithm::trim_copy(header.substr(0, index)), - boost::algorithm::trim_copy(header.substr(index + 1)))); + const auto key = boost::algorithm::trim_copy(header.substr(0, index)); + const auto value = boost::algorithm::trim_copy(header.substr(index + 1)); + headers->insert(std::make_pair(key, value)); } return size * nitems; } @@ -458,7 +466,7 @@ TObject* CcdbApi::retrieveFromTFile(std::string const& path, std::map<std::strin // setup curl for headers handling if (headers != nullptr) { list = curl_slist_append(list, ("If-None-Match: " + to_string(timestamp)).c_str()); - curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_map_callback); + curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_map_callback<>); curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, headers); } @@ -643,6 +651,145 @@ void* CcdbApi::extractFromLocalFile(std::string const& filename, TClass const* t return extractFromTFile(f, tcl); } +bool CcdbApi::checkAlienToken() const +{ + // a somewhat weird construction to programmatically find out if we + // have a GRID token; Can be replaced with something more elegant once + // alien-token-info does not ask for passwords interactively + auto returncode = system("timeout 1s timeout 1s alien-token-info &> /dev/null"); + return returncode == 0; +} + +bool CcdbApi::initTGrid() const +{ + if (!mAlienInstance) { + if (mHaveAlienToken) { + mAlienInstance = TGrid::Connect("alien"); + } + } + return mAlienInstance != nullptr; +} + +void* CcdbApi::downloadAlienContent(std::string const& url, TClass* cl) const +{ + if (!initTGrid()) { + return nullptr; + } + auto memfile = TMemFile::Open(url.c_str(), "OPEN"); + if (memfile) { + auto content = extractFromTFile(*memfile, cl); + delete memfile; + return content; + } + return nullptr; +} + +void* CcdbApi::interpretAsTMemFileAndExtract(char* contentptr, size_t contentsize, TClass* tcl) const +{ + void* result = nullptr; + Int_t previousErrorLevel = gErrorIgnoreLevel; + gErrorIgnoreLevel = kFatal; + TMemFile memFile("name", contentptr, contentsize, "READ"); + gErrorIgnoreLevel = previousErrorLevel; + if (!memFile.IsZombie()) { + result = extractFromTFile(memFile, tcl); + if (!result) { + LOG(ERROR) << o2::utils::concat_string("Couldn't retrieve object corresponding to ", tcl->GetName(), " from TFile"); + } + memFile.Close(); + } + return result; +} + +// navigate sequence of URLs until TFile content is found; object is extracted and returned +void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string const& url, TClass* cl, std::map<string, string>* headers) const +{ + // let's see first of all if the url is something specific that curl cannot handle + if (url.find("alien:/", 0) != std::string::npos) { + return downloadAlienContent(url, cl); + } + // add other final cases here + // example root:// + + // otherwise make an HTTP/CURL request + // specify URL to get + curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str()); + // some servers don't like requests that are made without a user-agent + // field, so we provide one + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + // if redirected , we tell libcurl NOT to follow redirection + curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 0L); + curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_map_callback<decltype(mHeaderData)>); + mHeaderData.clear(); + curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void*)&mHeaderData); + + MemoryStruct chunk{(char*)malloc(1), 0}; + + // send all data to this function + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void*)&chunk); + + auto res = curl_easy_perform(curl_handle); + long response_code = -1; + void* content = nullptr; + bool errorflag = false; + bool cachingflag = false; + if (res == CURLE_OK && curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &response_code) == CURLE_OK) { + if (headers) { + for (auto& p : mHeaderData) { + (*headers)[p.first] = p.second; + } + } + if (200 <= response_code && response_code < 300) { + // good response and the content is directly provided and should have been dumped into "chunk" + content = interpretAsTMemFileAndExtract(chunk.memory, chunk.size, cl); + } else if (response_code == 304) { + // this means the object exist but I am not serving + // it since it's already in your possession + + // there is nothing to be done here + cachingflag = true; + } + // this is a more general redirection + else if (300 <= response_code && response_code < 400) { + // we try content locations in order of appearance until one succeeds + // 1st: The "Location" field + // 2nd: Possible "Content-Location" fields + auto tryLocations = [this, &curl_handle, &content, cl](auto range) { + for (auto it = range.first; it != range.second; ++it) { + auto nextlocation = it->second; + LOG(DEBUG) << "Trying content location " << nextlocation; + content = navigateURLsAndRetrieveContent(curl_handle, nextlocation, cl, nullptr); + if (content /* or other success marker in future */) { + break; + } + } + }; + tryLocations(mHeaderData.equal_range("Location")); + if (content == nullptr) { + tryLocations(mHeaderData.equal_range("Content-Location")); + } + } else if (response_code == 404) { + LOG(ERROR) << "Requested resource does not exist"; + errorflag = true; + } else { + errorflag = true; + } + // cleanup + if (chunk.memory != nullptr) { + free(chunk.memory); + } + } else { + LOG(ERROR) << "Curl request to " << url << " failed "; + errorflag = true; + } + // indicate that an error occurred ---> used by caching layers (such as CCDBManager) + if (errorflag && headers) { + (*headers)["Error"] = "An error occurred during retrieval"; + } + return content; +} + void* CcdbApi::retrieveFromTFile(std::type_info const& tinfo, std::string const& path, std::map<std::string, std::string> const& metadata, long timestamp, std::map<std::string, std::string>* headers, std::string const& etag, @@ -655,103 +802,32 @@ void* CcdbApi::retrieveFromTFile(std::type_info const& tinfo, std::string const& return nullptr; } - // Note : based on https://curl.haxx.se/libcurl/c/getinmemory.html - // Thus it does not comply to our coding guidelines as it is a copy paste. - - // Prepare CURL - CURL* curl_handle; - CURLcode res; - struct MemoryStruct chunk { - (char*)malloc(1) /*memory*/, 0 /*size*/ - }; - - /* init the curl session */ - curl_handle = curl_easy_init(); - + CURL* curl_handle = curl_easy_init(); string fullUrl = getFullUrlForRetrieval(curl_handle, path, metadata, timestamp); // if we are in snapshot mode we can simply open the file; extract the object and return if (mInSnapshotMode) { return extractFromLocalFile(fullUrl, tcl); } - /* specify URL to get */ - curl_easy_setopt(curl_handle, CURLOPT_URL, fullUrl.c_str()); - - /* send all data to this function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); - - /* we pass our 'chunk' struct to the callback function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void*)&chunk); - - /* some servers don't like requests that are made without a user-agent - field, so we provide one */ - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); - - /* if redirected , we tell libcurl to follow redirection */ - curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); - + // add some global options to the curl query struct curl_slist* list = nullptr; if (!etag.empty()) { list = curl_slist_append(list, ("If-None-Match: " + etag).c_str()); } - if (!createdNotAfter.empty()) { list = curl_slist_append(list, ("If-Not-After: " + createdNotAfter).c_str()); } - if (!createdNotBefore.empty()) { list = curl_slist_append(list, ("If-Not-Before: " + createdNotBefore).c_str()); } - - // setup curl for headers handling - if (headers != nullptr) { + if (headers) { list = curl_slist_append(list, ("If-None-Match: " + to_string(timestamp)).c_str()); - curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_map_callback); - curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, headers); - } - - if (list) { - curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list); - } - - /* get it! */ - res = curl_easy_perform(curl_handle); - std::string errStr; - void* result = nullptr; - if (res == CURLE_OK) { - long response_code; - res = curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &response_code); - if ((res == CURLE_OK) && (response_code != 404)) { - Int_t previousErrorLevel = gErrorIgnoreLevel; - gErrorIgnoreLevel = kFatal; - TMemFile memFile("name", chunk.memory, chunk.size, "READ"); - gErrorIgnoreLevel = previousErrorLevel; - if (!memFile.IsZombie()) { - result = extractFromTFile(memFile, tcl); - if (!result) { - errStr = o2::utils::concat_string("Couldn't retrieve the object ", path); - LOG(ERROR) << errStr; - } - memFile.Close(); - } else { - LOG(DEBUG) << "Object " << path << " is stored in a TMemFile"; - } - } else { - errStr = o2::utils::concat_string("Invalid URL : ", fullUrl); - LOG(ERROR) << errStr; - } - } else { - errStr = o2::utils::concat_string("curl_easy_perform() failed: ", curl_easy_strerror(res)); - fprintf(stderr, "%s", errStr.c_str()); - } - - if (!errStr.empty() && headers) { - (*headers)["Error"] = errStr; } + curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list); + auto content = navigateURLsAndRetrieveContent(curl_handle, fullUrl, tcl, headers); curl_easy_cleanup(curl_handle); - free(chunk.memory); - return result; + return content; } size_t CurlWrite_CallbackFunc_StdString2(void* contents, size_t size, size_t nmemb, std::string* s) @@ -930,7 +1006,7 @@ std::map<std::string, std::string> CcdbApi::retrieveHeaders(std::string const& p /* get us the resource without a body! */ curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_map_callback); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_map_callback<>); curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headers); // Perform the request, res will get the return code diff --git a/CCDB/test/testCcdbApi_alien.cxx b/CCDB/test/testCcdbApi_alien.cxx new file mode 100644 index 0000000000000..b97b477aa9248 --- /dev/null +++ b/CCDB/test/testCcdbApi_alien.cxx @@ -0,0 +1,102 @@ +// 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. + +/// Ccdb unit tests focusing on alien replicas +/// +/// \file testCcdbApi_alien.cxx +/// \author Sandro Wenzel +/// + +#define BOOST_TEST_MODULE CCDB +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include "CCDB/CcdbApi.h" +#include <TH1.h> +#include <boost/test/unit_test.hpp> +#include <iostream> + +using namespace std; +using namespace o2::ccdb; +namespace utf = boost::unit_test; +namespace tt = boost::test_tools; + +static string ccdbUrl; +bool hostReachable = false; + +/** + * Global fixture, ie general setup and teardown + */ +struct Fixture { + Fixture() + { + CcdbApi api; + ccdbUrl = "http://alice-ccdb.cern.ch"; + api.init(ccdbUrl); + cout << "ccdb url: " << ccdbUrl << endl; + hostReachable = api.isHostReachable(); + cout << "Is host reachable ? --> " << hostReachable << endl; + } +}; +BOOST_GLOBAL_FIXTURE(Fixture); + +/** + * Just an accessor to the hostReachable variable to be used to determine whether tests can be ran or not. + */ +struct if_reachable { + tt::assertion_result operator()(utf::test_unit_id) + { + return hostReachable; + } +}; + +/** + * Fixture for the tests, i.e. code is ran in every test that uses it, i.e. it is like a setup and teardown for tests. + */ +struct test_fixture { + test_fixture() + { + api.init(ccdbUrl); + metadata["Hello"] = "World"; + std::cout << "*** " << boost::unit_test::framework::current_test_case().p_name << " ***" << std::endl; + } + ~test_fixture() = default; + + CcdbApi api; + map<string, string> metadata; +}; + +// handle the case where the object comes from alien and redirect does not work with curl +BOOST_AUTO_TEST_CASE(retrieveTemplated_ALIEN, *utf::precondition(if_reachable())) +{ + test_fixture f; + + // try to retrieve an object from the production instance, including the headers + std::map<std::string, std::string> headers; + std::map<std::string, std::string> meta; + + std::string path("/Users/j/jgrosseo/tutorial/efficiency/simple/1"); + { + auto* object = f.api.retrieveFromTFileAny<TH1>(path, meta, -1, &headers); + BOOST_CHECK(object != nullptr); + LOG(INFO) << headers["Content-Location"]; + if (object) { + BOOST_CHECK(headers.size() > 0); + LOG(INFO) << "Histo name " << object->GetName(); + LOG(INFO) << "Number of bins " << object->GetNbinsX() << " Mean " << object->GetMean(); + } + } + + // it should also work without headers of course + { + auto* object = f.api.retrieveFromTFileAny<TH1>(path, meta); + BOOST_CHECK(object != nullptr); + } +} From a23a0088454746b860005e7f0472ca78f720b99b Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Thu, 12 Nov 2020 13:21:39 +0000 Subject: [PATCH 1293/1751] Add minor comment to TrackSelectionTables.h (#4815) Clarifying the DCA in question is the one to the primary vertex --- Analysis/DataModel/include/Analysis/TrackSelectionTables.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h index 7b9e95162fa10..4d3dcacf6b707 100644 --- a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h +++ b/Analysis/DataModel/include/Analysis/TrackSelectionTables.h @@ -17,6 +17,7 @@ namespace o2::aod { namespace track { +// Columns to store the DCA to the primary vertex DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); From 1cfabfadf4addb77eda313ba18a3ebe6f7a7ea87 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Wed, 4 Nov 2020 16:55:23 +0100 Subject: [PATCH 1294/1751] Add DPL TRD tracking workflow - added reader for TRD tracklets - added TRD tracking as DPL device - added dummy TRD track writer --- Detectors/TRD/workflow/CMakeLists.txt | 15 +- .../TRDWorkflow/TRDGlobalTrackingSpec.h | 51 +++++ .../include/TRDWorkflow/TRDTrackWriterSpec.h | 29 +++ .../include/TRDWorkflow/TRDTrackingWorkflow.h | 28 +++ .../TRDWorkflow/TRDTrackletReaderSpec.h | 57 +++++ .../workflow/src/TRDGlobalTrackingSpec.cxx | 201 ++++++++++++++++++ .../TRD/workflow/src/TRDTrackWriterSpec.cxx | 62 ++++++ .../TRD/workflow/src/TRDTrackingWorkflow.cxx | 44 ++++ .../workflow/src/TRDTrackletReaderSpec.cxx | 91 ++++++++ .../workflow/src/trd-tracking-workflow.cxx | 44 ++++ 10 files changed, 619 insertions(+), 3 deletions(-) create mode 100644 Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h create mode 100644 Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackWriterSpec.h create mode 100644 Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackingWorkflow.h create mode 100644 Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletReaderSpec.h create mode 100644 Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx create mode 100644 Detectors/TRD/workflow/src/TRDTrackWriterSpec.cxx create mode 100644 Detectors/TRD/workflow/src/TRDTrackingWorkflow.cxx create mode 100644 Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx create mode 100644 Detectors/TRD/workflow/src/trd-tracking-workflow.cxx diff --git a/Detectors/TRD/workflow/CMakeLists.txt b/Detectors/TRD/workflow/CMakeLists.txt index 99be830a2f288..63f51b35f743b 100644 --- a/Detectors/TRD/workflow/CMakeLists.txt +++ b/Detectors/TRD/workflow/CMakeLists.txt @@ -8,7 +8,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -#add_compile_options(-O0 -pg -fPIC) +#add_compile_options(-O0 -pg -fPIC) o2_add_library(TRDWorkflow TARGETVARNAME targetName @@ -16,9 +16,13 @@ o2_add_library(TRDWorkflow src/TRDDigitWriterSpec.cxx src/TRDDigitReaderSpec.cxx src/TRDTrackletWriterSpec.cxx + src/TRDTrackletReaderSpec.cxx src/TRDTrapRawWriterSpec.cxx src/TRDTrapSimulatorSpec.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::Steer O2::Algorithm O2::DataFormatsTRD O2::TRDSimulation O2::DetectorsBase O2::SimulationDataFormat O2::TRDBase) + src/TRDGlobalTrackingSpec.cxx + src/TRDTrackWriterSpec.cxx + src/TRDTrackingWorkflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::Steer O2::Algorithm O2::DataFormatsTRD O2::TRDSimulation O2::DetectorsBase O2::SimulationDataFormat O2::TRDBase O2::GPUTracking O2::GlobalTrackingWorkflow) #o2_target_root_dictionary(TRDWorkflow # HEADERS include/TRDWorkflow/TRDTrapSimulatorSpec.h) @@ -33,8 +37,13 @@ o2_add_executable(trap-sim O2::DataFormatsTRD O2::TRDWorkflow) +o2_add_executable(global-tracking + COMPONENT_NAME trd + SOURCES src/trd-tracking-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::TRDWorkflow) + + if (OpenMP_CXX_FOUND) target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) endif() - diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h new file mode 100644 index 0000000000000..2b2976feda84b --- /dev/null +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h @@ -0,0 +1,51 @@ +// 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 TRDGlobalTrackingSpec.h + +#ifndef O2_TRD_GLOBALTRACKING +#define O2_TRD_GLOBALTRACKING + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "TStopwatch.h" + +#include "GPUO2Interface.h" +#include "GPUTRDTracker.h" + +namespace o2 +{ +namespace trd +{ + +class TRDGlobalTracking : public o2::framework::Task +{ + public: + TRDGlobalTracking(bool useMC) : mUseMC(useMC) {} + ~TRDGlobalTracking() override = default; + void init(o2::framework::InitContext& ic) final; + void run(o2::framework::ProcessingContext& pc) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::gpu::GPUTRDTracker* mTracker{nullptr}; ///< TRD tracking engine + o2::gpu::GPUReconstruction* mRec{nullptr}; ///< GPU reconstruction pointer, handles memory for the tracker + o2::gpu::GPUChainTracking* mChainTracking{nullptr}; ///< TRD tracker is run in the tracking chain + bool mUseMC{false}; ///< MC flag + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getTRDGlobalTrackingSpec(bool useMC); + +} // namespace trd +} // namespace o2 + +#endif /* O2_TRD_TRACKLETREADER */ diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackWriterSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackWriterSpec.h new file mode 100644 index 0000000000000..4bacd79c5a014 --- /dev/null +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackWriterSpec.h @@ -0,0 +1,29 @@ +// 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_TRD_TRACK_WRITER_H +#define O2_TRD_TRACK_WRITER_H + +/// @file TRDTrackWriterSpec.h + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +namespace trd +{ + +/// create a processor spec +framework::DataProcessorSpec getTRDTrackWriterSpec(bool useMC); + +} // namespace trd +} // namespace o2 + +#endif diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackingWorkflow.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackingWorkflow.h new file mode 100644 index 0000000000000..1bd9e6e33bd81 --- /dev/null +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackingWorkflow.h @@ -0,0 +1,28 @@ +// 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_TRD_TRACKING_WORKFLOW_H +#define O2_TRD_TRACKING_WORKFLOW_H + +/// @file TRDTrackingWorkflow.h + +#include "Framework/WorkflowSpec.h" + +namespace o2 +{ +namespace trd +{ + +framework::WorkflowSpec getTRDTrackingWorkflow(bool disableRootInp, bool disableRootOut); + +} // namespace trd +} // namespace o2 + +#endif diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletReaderSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletReaderSpec.h new file mode 100644 index 0000000000000..cdc839a2f9e4c --- /dev/null +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletReaderSpec.h @@ -0,0 +1,57 @@ +// 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 TRDTrackletReaderSpec.h + +#ifndef O2_TRD_TRACKLETREADER +#define O2_TRD_TRACKLETREADER + +#include "TFile.h" +#include "TTree.h" + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/TriggerRecord.h" +#include "SimulationDataFormat/MCCompLabel.h" + +namespace o2 +{ +namespace trd +{ + +class TRDTrackletReader : public o2::framework::Task +{ + public: + TRDTrackletReader(bool useMC) : mUseMC(useMC) {} + ~TRDTrackletReader() override = default; + void init(o2::framework::InitContext& ic) final; + void run(o2::framework::ProcessingContext& pc) final; + + private: + void connectTree(const std::string& filename); + bool mUseMC{false}; + std::unique_ptr<TFile> mFile; + std::unique_ptr<TTree> mTree; + std::string mInFileName{"trdtracklets.root"}; + std::string mInTreeName{"o2sim"}; + std::vector<o2::trd::Tracklet64> mTracklets, *mTrackletsPtr = &mTracklets; + std::vector<o2::trd::TriggerRecord> mTriggerRecords, *mTriggerRecordsPtr = &mTriggerRecords; + std::vector<o2::MCCompLabel> mLabels, *mLabelsPtr = &mLabels; +}; + +/// create a processor spec +/// read TRD tracklets from a root file +framework::DataProcessorSpec getTRDTrackletReaderSpec(bool useMC); + +} // namespace trd +} // namespace o2 + +#endif /* O2_TRD_TRACKLETREADER */ diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx new file mode 100644 index 0000000000000..627d2614c95ac --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -0,0 +1,201 @@ +// 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 TRDGlobalTrackingSpec.cxx + +#include "TRDWorkflow/TRDGlobalTrackingSpec.h" + +#include "TRDBase/Geometry.h" + +#include "DetectorsCommonDataFormats/NameConf.h" +#include "CommonConstants/LHCConstants.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/TriggerRecord.h" + +// GPU header +#include "GPUReconstruction.h" +#include "GPUChainTracking.h" +#include "GPUSettings.h" +#include "GPUDataTypes.h" +#include "GPUTRDDef.h" +#include "GPUTRDTrack.h" +#include "GPUTRDTrackletWord.h" +#include "GPUTRDInterfaces.h" +#include "GPUTRDGeometry.h" + +using namespace o2::framework; +using namespace o2::gpu; + +namespace o2 +{ +namespace trd +{ + +void TRDGlobalTracking::init(InitContext& ic) +{ + //-------- init geometry and field --------// + o2::base::GeometryManager::loadGeometry(); + o2::base::Propagator::initFieldFromGRP(o2::base::NameConf::getGRPFileName()); + auto geo = Geometry::instance(); + geo->createPadPlaneArray(); + geo->createClusterMatrixArray(); + const GeometryFlat geoFlat(*geo); + + //-------- init GPU reconstruction --------// + GPUSettingsEvent cfgEvent; // defaults should be ok + GPUSettingsRec cfgRec; // don't care for now, NWaysOuter is set in here for instance + GPUSettingsProcessing cfgDeviceProcessing; // also keep defaults here, or adjust debug level + cfgDeviceProcessing.debugLevel = 5; + GPURecoStepConfiguration cfgRecoStep; + cfgRecoStep.steps = GPUDataTypes::RecoStep::NoRecoStep; + cfgRecoStep.inputs.clear(); + cfgRecoStep.outputs.clear(); + mRec = GPUReconstruction::CreateInstance("CPU", true); + mRec->SetSettings(&cfgEvent, &cfgRec, &cfgDeviceProcessing, &cfgRecoStep); + + mChainTracking = mRec->AddChain<GPUChainTracking>(); + + mTracker = new GPUTRDTracker(); + mTracker->SetNCandidates(1); // must be set before initialization + mTracker->SetProcessPerTimeFrame(); + mTracker->SetNMaxCollisions(1000); // max number of collisions within a time frame which can be processed + + mRec->RegisterGPUProcessor(mTracker, false); + mChainTracking->SetTRDGeometry(&geoFlat); + if (mRec->Init()) { + LOG(FATAL) << "GPUReconstruction could not be initialized"; + } + + // configure the tracker + //mTracker->EnableDebugOutput(); + //mTracker->StartDebugging(); + mTracker->SetPtThreshold(0.5); + mTracker->SetChi2Threshold(15); + mTracker->SetChi2Penalty(12); + mTracker->SetMaxMissingLayers(6); + mTracker->PrintSettings(); + + mTimer.Stop(); + mTimer.Reset(); +} + +void TRDGlobalTracking::run(ProcessingContext& pc) +{ + mTimer.Start(false); + const auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("tpcitstrack"); + const auto trackletsTRD = pc.inputs().get<std::vector<o2::trd::Tracklet64>>("trdtracklets"); + const auto triggerRecords = pc.inputs().get<std::vector<o2::trd::TriggerRecord>>("trdtriggerrec"); + + int nTracks = tracksITSTPC.size(); + int nCollisions = triggerRecords.size(); + int nTracklets = trackletsTRD.size(); + LOGF(INFO, "There are %i tracklets in total from %i trigger records", nTracklets, nCollisions); + + std::vector<float> trdTriggerTimes; + std::vector<int> trdTriggerIndices; + + for (int iEv = 0; iEv < nCollisions; ++iEv) { + const auto& trg = triggerRecords.at(iEv); + int nTrackletsCurrent = trg.getNumberOfObjects(); + int iFirstTracklet = trg.getFirstEntry(); + int64_t evTime = trg.getBCData().toLong() * o2::constants::lhc::LHCBunchSpacingNS; // event time in ns + trdTriggerTimes.push_back(evTime / 1000.); + trdTriggerIndices.push_back(iFirstTracklet); + LOGF(INFO, "Event %i: Occured at %li us after SOR, contains %i tracklets, index of first tracklet is %i", iEv, evTime / 1000, nTrackletsCurrent, iFirstTracklet); + } + + mTracker->Reset(); + + mChainTracking->mIOPtrs.nMergedTracks = nTracks; + mChainTracking->mIOPtrs.nTRDTracklets = nTracklets; + mChainTracking->AllocateIOMemory(); + mRec->PrepareEvent(); + mRec->SetupGPUProcessor(mTracker, true); + + LOG(INFO) << "Start loading input into TRD tracker"; + // load everything into the tracker + for (int iTrk = 0; iTrk < nTracks; ++iTrk) { + const auto& match = tracksITSTPC[iTrk]; + const auto& trk = match.getParamOut(); + GPUTRDTrack trkLoad; + trkLoad.setX(trk.getX()); + trkLoad.setAlpha(trk.getAlpha()); + for (int i = 0; i < 5; ++i) { + trkLoad.setParam(trk.getParam(i), i); + } + for (int i = 0; i < 15; ++i) { + trkLoad.setCov(trk.getCov()[i], i); + } + trkLoad.setTime(match.getTimeMUS().getTimeStamp()); + mTracker->LoadTrack(trkLoad); + LOGF(INFO, "Loaded track %i with time %f", iTrk, trkLoad.getTime()); + } + + for (int iTrklt = 0; iTrklt < nTracklets; ++iTrklt) { + auto trklt = trackletsTRD[iTrklt]; + unsigned int trkltWord = 0; // DUMMY + GPUTRDTrackletWord trkltLoad; + trkltLoad.SetId(iTrklt); + trkltLoad.SetHCId(trklt.getHCID()); + trkltLoad.SetTrackletWord(trkltWord); + if (mTracker->LoadTracklet(trkltLoad) > 0) { + LOG(WARNING) << "Could not load tracklet " << iTrklt; + } + } + mTracker->SetTriggerRecordTimes(&(trdTriggerTimes[0])); + mTracker->SetTriggerRecordIndices(&(trdTriggerIndices[0])); + mTracker->SetNCollisions(nCollisions); + mTracker->DumpTracks(); + mTracker->DoTracking(mChainTracking); + mTracker->DumpTracks(); + + std::vector<GPUTRDTrack> tracksOut; + //tracksOut.resize(mTracker->NTracks()); + std::copy(mTracker->Tracks(), mTracker->Tracks() + mTracker->NTracks(), tracksOut.begin()); + pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MATCHTRD", 0, Lifetime::Timeframe}, tracksOut); + + mTimer.Stop(); +} + +void TRDGlobalTracking::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "TRD global tracking total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getTRDGlobalTrackingSpec(bool useMC) +{ + std::vector<InputSpec> inputs; + std::vector<OutputSpec> outputs; + inputs.emplace_back("tpcitstrack", "GLO", "TPCITS", 0, Lifetime::Timeframe); + inputs.emplace_back("trdtracklets", o2::header::gDataOriginTRD, "TRACKLETS", 0, Lifetime::Timeframe); + inputs.emplace_back("trdtriggerrec", o2::header::gDataOriginTRD, "TRIGGERREC", 0, Lifetime::Timeframe); + + if (useMC) { + LOG(FATAL) << "MC usage must be disabled for this workflow, since it is not yet implemented"; + //inputs.emplace_back("itstracklabel", "GLO", "TPCITS_ITSMC", 0, Lifetime::Timeframe); + //inputs.emplace_back("tpctracklabel", "GLO", "TPCITS_TPCMC", 0, Lifetime::Timeframe); + } + + outputs.emplace_back(o2::header::gDataOriginTRD, "MATCHTRD", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "trd-globaltracking", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<TRDGlobalTracking>(useMC)}, + Options{}}; +} + +} // namespace trd +} // namespace o2 diff --git a/Detectors/TRD/workflow/src/TRDTrackWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDTrackWriterSpec.cxx new file mode 100644 index 0000000000000..f42af52207f57 --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDTrackWriterSpec.cxx @@ -0,0 +1,62 @@ +// 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 TRDTrackWriterSpec.cxx + +#include <vector> +#include "GPUO2Interface.h" +#include "GPUTRDDef.h" +#include "GPUTRDTrack.h" + +#include "DPLUtils/MakeRootTreeWriterSpec.h" + +using namespace o2::framework; +using namespace o2::gpu; + +namespace o2 +{ +namespace trd +{ +template <typename T> +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition<T>; + +DataProcessorSpec getTRDTrackWriterSpec(bool useMC) +{ + // TODO: not clear if the writer is supposed to write MC labels at some point + // this is just a dummy definition for the template branch definition below + // define the correct type and the input specs + using LabelsType = std::vector<int>; + // force, this will disable the branch for now, can be adjusted in the future + useMC = false; + + // A spectator to store the size of the data array for the logger below + auto tracksSize = std::make_shared<int>(); + auto tracksLogger = [tracksSize](std::vector<GPUTRDTrack> const& tracks) { + *tracksSize = tracks.size(); + }; + + return MakeRootTreeWriterSpec("trd-track-writer", + "trdtracks.root", + "tracksTRD", + BranchDefinition<std::vector<GPUTRDTrack>>{InputSpec{"tracks", o2::header::gDataOriginTRD, "MATCHTRD", 0}, + "tracks", + "tracks-branch-name", + 1, + tracksLogger}, + // NOTE: this branch template is to show how the conditional MC labels can + // be defined, the '0' disables the branch for the moment + BranchDefinition<LabelsType>{InputSpec{"matchtpclabels", "GLO", "SOME_LABELS", 0}, + "labels", + (useMC ? 1 : 0), // one branch if mc labels enabled + "labels-branch-name"})(); +} + +} // namespace trd +} // namespace o2 diff --git a/Detectors/TRD/workflow/src/TRDTrackingWorkflow.cxx b/Detectors/TRD/workflow/src/TRDTrackingWorkflow.cxx new file mode 100644 index 0000000000000..4b60307680434 --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDTrackingWorkflow.cxx @@ -0,0 +1,44 @@ +// 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 TRDTrackingWorkflow.cxx + +#include <vector> + +#include "Framework/WorkflowSpec.h" +#include "GlobalTrackingWorkflow/TrackTPCITSReaderSpec.h" +#include "TRDWorkflow/TRDTrackletReaderSpec.h" +#include "TRDWorkflow/TRDGlobalTrackingSpec.h" +#include "TRDWorkflow/TRDTrackWriterSpec.h" + +namespace o2 +{ +namespace trd +{ + +framework::WorkflowSpec getTRDTrackingWorkflow(bool disableRootInp, bool disableRootOut) +{ + framework::WorkflowSpec specs; + bool useMC = false; + if (!disableRootInp) { + specs.emplace_back(o2::globaltracking::getTrackTPCITSReaderSpec(useMC)); + specs.emplace_back(o2::trd::getTRDTrackletReaderSpec(useMC)); + } + + specs.emplace_back(o2::trd::getTRDGlobalTrackingSpec(useMC)); + + if (!disableRootOut) { + specs.emplace_back(o2::trd::getTRDTrackWriterSpec(useMC)); + } + return specs; +} + +} // namespace trd +} // namespace o2 diff --git a/Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx b/Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx new file mode 100644 index 0000000000000..43dffce5552c8 --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx @@ -0,0 +1,91 @@ +// 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 TRDTrackletReaderSpec.cxx + +#include "TRDWorkflow/TRDTrackletReaderSpec.h" + +#include "Headers/DataHeader.h" +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace trd +{ + +void TRDTrackletReader::init(InitContext& ic) +{ + // get the option from the init context + LOG(INFO) << "Init TRD tracklet reader!"; + mInFileName = ic.options().get<std::string>("trd-tracklet-infile"); + mInTreeName = ic.options().get<std::string>("treename"); + connectTree(mInFileName); +} + +void TRDTrackletReader::connectTree(const std::string& filename) +{ + mTree.reset(nullptr); // in case it was already loaded + mFile.reset(TFile::Open(filename.c_str())); + assert(mFile && !mFile->IsZombie()); + mTree.reset((TTree*)mFile->Get(mInTreeName.c_str())); + assert(mTree); + mTree->SetBranchAddress("Tracklet", &mTrackletsPtr); + mTree->SetBranchAddress("TrackTrg", &mTriggerRecordsPtr); + if (mUseMC) { + LOG(FATAL) << "MC information not yet included for TRD tracklets"; + } + LOG(INFO) << "Loaded tree from " << filename << " with " << mTree->GetEntries() << " entries"; +} + +void TRDTrackletReader::run(ProcessingContext& pc) +{ + auto currEntry = mTree->GetReadEntry() + 1; + assert(currEntry < mTree->GetEntries()); // this should not happen + mTree->GetEntry(currEntry); + LOG(INFO) << "Pushing " << mTriggerRecords.size() << " TRD trigger records at entry " << currEntry; + LOG(INFO) << "Pushing " << mTracklets.size() << " TRD tracklets for these trigger records"; + + pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "TRACKLETS", 0, Lifetime::Timeframe}, mTracklets); + pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "TRIGGERREC", 0, Lifetime::Timeframe}, mTriggerRecords); + if (mUseMC) { + LOG(FATAL) << "MC information not yet included for TRD tracklets"; + } + + if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) { + pc.services().get<ControlService>().endOfStream(); + pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); + } +} + +DataProcessorSpec getTRDTrackletReaderSpec(bool useMC) +{ + std::vector<OutputSpec> outputs; + outputs.emplace_back(o2::header::gDataOriginTRD, "TRACKLETS", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTRD, "TRIGGERREC", 0, Lifetime::Timeframe); + if (useMC) { + LOG(FATAL) << "MC information not yet included for TRD tracklets"; + } + + return DataProcessorSpec{ + "TRDTrackletReader", + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask<TRDTrackletReader>(useMC)}, + Options{ + {"trd-tracklet-infile", VariantType::String, "trdtracklets.root", {"Name of the input file"}}, + {"treename", VariantType::String, "o2sim", {"Name of top-level TTree"}}, + }}; +} + +} // namespace trd +} // namespace o2 diff --git a/Detectors/TRD/workflow/src/trd-tracking-workflow.cxx b/Detectors/TRD/workflow/src/trd-tracking-workflow.cxx new file mode 100644 index 0000000000000..4a15ec72aee6f --- /dev/null +++ b/Detectors/TRD/workflow/src/trd-tracking-workflow.cxx @@ -0,0 +1,44 @@ +// 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 "TRDWorkflow/TRDTrackingWorkflow.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + workflowOptions.push_back(ConfigParamSpec{ + "disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input readers"}}); + workflowOptions.push_back(ConfigParamSpec{ + "disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writers"}}); + std::string keyvaluehelp("Semicolon separated key=value strings ..."); + workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); + // write the configuration used for the workflow + o2::conf::ConfigurableParam::writeINI("o2trdtracking-workflow_configuration.ini"); + auto disableRootInp = configcontext.options().get<bool>("disable-root-input"); + auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); + return std::move(o2::trd::getTRDTrackingWorkflow(disableRootInp, disableRootOut)); +} From 8cb13d1940a5e790a8d3942e4fa15683bc79c394 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 5 Nov 2020 13:07:10 +0100 Subject: [PATCH 1295/1751] Tracklet64 is trivially copyable --- DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h | 4 +--- Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index de93a0a31465c..ef4a8f401ed80 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -50,7 +50,7 @@ class Tracklet64 public: Tracklet64() = default; Tracklet64(uint64_t trackletword) { mtrackletWord = trackletword; } - Tracklet64(const Tracklet64& rhs) { mtrackletWord = rhs.getTrackletWord(); }; + Tracklet64(const Tracklet64&) = default; Tracklet64(uint64_t format, uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, uint64_t slope, uint64_t Q0, uint64_t Q1, uint64_t Q2) { @@ -58,7 +58,6 @@ class Tracklet64 } ~Tracklet64() = default; - Tracklet64& operator=(const Tracklet64& o) { return *this; } //TODO convert to the actual number regarding compliments. // ----- Getters for contents of tracklet word ----- @@ -149,7 +148,6 @@ class Tracklet64 protected: uint64_t mtrackletWord; // the 64 bit word holding all the tracklet information for run3. private: - // Tracklet& operator=(const Tracklet &rhs); // not implemented ClassDefNV(Tracklet64, 1); }; diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 627d2614c95ac..8f8af94dd1720 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -93,8 +93,8 @@ void TRDGlobalTracking::run(ProcessingContext& pc) { mTimer.Start(false); const auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("tpcitstrack"); - const auto trackletsTRD = pc.inputs().get<std::vector<o2::trd::Tracklet64>>("trdtracklets"); - const auto triggerRecords = pc.inputs().get<std::vector<o2::trd::TriggerRecord>>("trdtriggerrec"); + const auto trackletsTRD = pc.inputs().get<gsl::span<o2::trd::Tracklet64>>("trdtracklets"); + const auto triggerRecords = pc.inputs().get<gsl::span<o2::trd::TriggerRecord>>("trdtriggerrec"); int nTracks = tracksITSTPC.size(); int nCollisions = triggerRecords.size(); From 6319df8b651a8454b19843b2430edeed29854928 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 10 Nov 2020 13:22:27 +0100 Subject: [PATCH 1296/1751] Add dictionary for GPUTRDTrack messages --- GPU/GPUTracking/CMakeLists.txt | 2 +- GPU/GPUTracking/GPUTrackingLinkDef_O2.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index dec5d3d5686b0..aa55aafe59fec 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -137,7 +137,7 @@ set(HDRS_INSTALL if(ALIGPU_BUILD_TYPE STREQUAL "O2") set(SRCS ${SRCS} Interface/GPUO2Interface.cxx Interface/GPUO2InterfaceRefit.cxx Interface/GPUO2InterfaceQA.cxx Interface/GPUO2InterfaceConfigurableParam.cxx) set(HDRS_CINT_O2 ${HDRS_CINT_O2} Interface/GPUO2Interface.h Interface/GPUO2InterfaceRefit.h Interface/GPUO2InterfaceQA.h Interface/GPUO2InterfaceConfigurableParam.h dEdx/TPCdEdxCalibrationSplines.h) - set(HDRS_CINT_O2_ADDITIONAL Base/GPUSettings.h Base/GPUSettingsList.h) # Manual depencies for ROOT dictionary generation + set(HDRS_CINT_O2_ADDITIONAL Base/GPUSettings.h Base/GPUSettingsList.h TRDTracking/GPUTRDTrack.h) # Manual dependencies for ROOT dictionary generation endif() # Sources for O2 and for Standalone if requested in config file diff --git a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h index fe035e5a71a45..df62b623abb44 100644 --- a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h +++ b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h @@ -26,5 +26,8 @@ #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsProcessing + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsDisplay + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsQA + ; +#pragma link C++ class o2::gpu::trackInterface < o2::dataformats::TrackTPCITS> + ; +#pragma link C++ class o2::gpu::GPUTRDTrack_t < o2::gpu::trackInterface < o2::dataformats::TrackTPCITS>> + ; +#pragma link C++ class std::vector < o2::gpu::GPUTRDTrack_t < o2::gpu::trackInterface < o2::dataformats::TrackTPCITS>>> + ; #endif From 179729cd9346b339fdc2dc2008005ef97085c70f Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 10 Nov 2020 13:39:36 +0100 Subject: [PATCH 1297/1751] Initialize output track vector with correct size --- Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 8f8af94dd1720..7f4b1a28b553e 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -159,8 +159,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) mTracker->DoTracking(mChainTracking); mTracker->DumpTracks(); - std::vector<GPUTRDTrack> tracksOut; - //tracksOut.resize(mTracker->NTracks()); + std::vector<GPUTRDTrack> tracksOut(mTracker->NTracks()); std::copy(mTracker->Tracks(), mTracker->Tracks() + mTracker->NTracks(), tracksOut.begin()); pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "MATCHTRD", 0, Lifetime::Timeframe}, tracksOut); From 13203efc9fc9f3add5247f9e3bcfdb00dd87e78d Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 10 Nov 2020 14:23:56 +0100 Subject: [PATCH 1298/1751] Consistent name for TRD trigger records --- Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 2 +- Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 7f4b1a28b553e..e99015b89a7ca 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -178,7 +178,7 @@ DataProcessorSpec getTRDGlobalTrackingSpec(bool useMC) std::vector<OutputSpec> outputs; inputs.emplace_back("tpcitstrack", "GLO", "TPCITS", 0, Lifetime::Timeframe); inputs.emplace_back("trdtracklets", o2::header::gDataOriginTRD, "TRACKLETS", 0, Lifetime::Timeframe); - inputs.emplace_back("trdtriggerrec", o2::header::gDataOriginTRD, "TRIGGERREC", 0, Lifetime::Timeframe); + inputs.emplace_back("trdtriggerrec", o2::header::gDataOriginTRD, "TRKTRGRD", 0, Lifetime::Timeframe); if (useMC) { LOG(FATAL) << "MC usage must be disabled for this workflow, since it is not yet implemented"; diff --git a/Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx b/Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx index 43dffce5552c8..2f29405c61564 100644 --- a/Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrackletReaderSpec.cxx @@ -56,7 +56,7 @@ void TRDTrackletReader::run(ProcessingContext& pc) LOG(INFO) << "Pushing " << mTracklets.size() << " TRD tracklets for these trigger records"; pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "TRACKLETS", 0, Lifetime::Timeframe}, mTracklets); - pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "TRIGGERREC", 0, Lifetime::Timeframe}, mTriggerRecords); + pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "TRKTRGRD", 0, Lifetime::Timeframe}, mTriggerRecords); if (mUseMC) { LOG(FATAL) << "MC information not yet included for TRD tracklets"; } @@ -71,7 +71,7 @@ DataProcessorSpec getTRDTrackletReaderSpec(bool useMC) { std::vector<OutputSpec> outputs; outputs.emplace_back(o2::header::gDataOriginTRD, "TRACKLETS", 0, Lifetime::Timeframe); - outputs.emplace_back(o2::header::gDataOriginTRD, "TRIGGERREC", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTRD, "TRKTRGRD", 0, Lifetime::Timeframe); if (useMC) { LOG(FATAL) << "MC information not yet included for TRD tracklets"; } From 087339b97d32273cda96c464ecc31701879b01a8 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Tue, 10 Nov 2020 15:13:55 +0100 Subject: [PATCH 1299/1751] Use appropriate name for function --- Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 2 +- GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index e99015b89a7ca..e6f2f5b8a4cc8 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -82,7 +82,7 @@ void TRDGlobalTracking::init(InitContext& ic) mTracker->SetPtThreshold(0.5); mTracker->SetChi2Threshold(15); mTracker->SetChi2Penalty(12); - mTracker->SetMaxMissingLayers(6); + mTracker->SetStopTrkFollowingAfterNMissingLayers(6); mTracker->PrintSettings(); mTimer.Stop(); diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index 53cb1c66df1dd..c7f21a346ce6d 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -152,7 +152,7 @@ class GPUTRDTracker_t : public GPUProcessor GPUd() void SetMaxEta(float maxEta) { mMaxEta = maxEta; } GPUd() void SetChi2Threshold(float chi2) { mMaxChi2 = chi2; } GPUd() void SetChi2Penalty(float chi2) { mChi2Penalty = chi2; } - GPUd() void SetMaxMissingLayers(int ly) { mMaxMissingLy = ly; } + GPUd() void SetStopTrkFollowingAfterNMissingLayers(int ly) { mMaxMissingLy = ly; } GPUd() void SetExtraRoadY(float extraRoadY) { mExtraRoadY = extraRoadY; } GPUd() void SetRoadZ(float roadZ) { mRoadZ = roadZ; } diff --git a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C index 525432e87dab2..d53118770e0d6 100644 --- a/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C +++ b/GPU/GPUTracking/TRDTracking/macros/run_trd_tracker.C @@ -86,7 +86,7 @@ void run_trd_tracker(std::string path = "./", tracker->SetPtThreshold(0.5); tracker->SetChi2Threshold(15); tracker->SetChi2Penalty(12); - tracker->SetMaxMissingLayers(6); + tracker->SetStopTrkFollowingAfterNMissingLayers(6); tracker->PrintSettings(); // load input tracks From 3b79368be8b28ca598dac8eca8f8f782050c0dcd Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Wed, 11 Nov 2020 12:26:44 +0100 Subject: [PATCH 1300/1751] Add flat TRD geometry as member of tracking spec --- .../include/TRDWorkflow/TRDGlobalTrackingSpec.h | 3 ++- Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 12 ++++++++---- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h index 2b2976feda84b..12c21c6ab4792 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h @@ -16,7 +16,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "TStopwatch.h" - +#include "TRDBase/GeometryFlat.h" #include "GPUO2Interface.h" #include "GPUTRDTracker.h" @@ -38,6 +38,7 @@ class TRDGlobalTracking : public o2::framework::Task o2::gpu::GPUTRDTracker* mTracker{nullptr}; ///< TRD tracking engine o2::gpu::GPUReconstruction* mRec{nullptr}; ///< GPU reconstruction pointer, handles memory for the tracker o2::gpu::GPUChainTracking* mChainTracking{nullptr}; ///< TRD tracker is run in the tracking chain + std::unique_ptr<GeometryFlat> mFlatGeo{nullptr}; ///< flat TRD geometry bool mUseMC{false}; ///< MC flag TStopwatch mTimer; }; diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index e6f2f5b8a4cc8..addbf4f694eb7 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -49,7 +49,7 @@ void TRDGlobalTracking::init(InitContext& ic) auto geo = Geometry::instance(); geo->createPadPlaneArray(); geo->createClusterMatrixArray(); - const GeometryFlat geoFlat(*geo); + mFlatGeo = std::make_unique<GeometryFlat>(*geo); //-------- init GPU reconstruction --------// GPUSettingsEvent cfgEvent; // defaults should be ok @@ -71,7 +71,7 @@ void TRDGlobalTracking::init(InitContext& ic) mTracker->SetNMaxCollisions(1000); // max number of collisions within a time frame which can be processed mRec->RegisterGPUProcessor(mTracker, false); - mChainTracking->SetTRDGeometry(&geoFlat); + mChainTracking->SetTRDGeometry(std::move(mFlatGeo)); if (mRec->Init()) { LOG(FATAL) << "GPUReconstruction could not be initialized"; } @@ -124,6 +124,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) LOG(INFO) << "Start loading input into TRD tracker"; // load everything into the tracker + int nTracksLoaded = 0; for (int iTrk = 0; iTrk < nTracks; ++iTrk) { const auto& match = tracksITSTPC[iTrk]; const auto& trk = match.getParamOut(); @@ -137,8 +138,11 @@ void TRDGlobalTracking::run(ProcessingContext& pc) trkLoad.setCov(trk.getCov()[i], i); } trkLoad.setTime(match.getTimeMUS().getTimeStamp()); - mTracker->LoadTrack(trkLoad); - LOGF(INFO, "Loaded track %i with time %f", iTrk, trkLoad.getTime()); + if (mTracker->LoadTrack(trkLoad)) { + continue; + } + ++nTracksLoaded; + LOGF(INFO, "Loaded track %i with time %f", nTracksLoaded, trkLoad.getTime()); } for (int iTrklt = 0; iTrklt < nTracklets; ++iTrklt) { diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index 1e02bdd9cad04..412126e6cda09 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -238,7 +238,8 @@ void GPUTRDTracker_t<TRDTRK, PROP>::DoTracking(GPUChainTracking* chainTracking) } if (!CalculateSpacePoints(iColl)) { - GPUError("Space points for at least one chamber could not be calculated"); + GPUError("Space points for at least one chamber could not be calculated (for interaction %i)", iColl); + break; } } @@ -451,7 +452,7 @@ GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::LoadTrack(const TRDTRK& trk, const int return (1); } if (checkTrack && !CheckTrackTRDCandidate(trk)) { - return 0; + return 2; } #ifdef GPUCA_ALIROOT_LIB new (&mTracks[mNTracks]) TRDTRK(trk); // We need placement new, since the class is virtual From 4d229f56349904e136737b17fc6b3cb55e287f7b Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Wed, 11 Nov 2020 14:46:44 +0100 Subject: [PATCH 1301/1751] Set solenoid field and silence debugging output --- Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index addbf4f694eb7..7750fdd2e05d2 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -52,10 +52,12 @@ void TRDGlobalTracking::init(InitContext& ic) mFlatGeo = std::make_unique<GeometryFlat>(*geo); //-------- init GPU reconstruction --------// - GPUSettingsEvent cfgEvent; // defaults should be ok - GPUSettingsRec cfgRec; // don't care for now, NWaysOuter is set in here for instance - GPUSettingsProcessing cfgDeviceProcessing; // also keep defaults here, or adjust debug level - cfgDeviceProcessing.debugLevel = 5; + GPUSettingsEvent cfgEvent; + cfgEvent.solenoidBz = o2::base::Propagator::Instance()->getNominalBz(); + GPUSettingsRec cfgRec; + cfgRec.NWaysOuter = 1; + GPUSettingsProcessing cfgDeviceProcessing; + cfgDeviceProcessing.debugLevel = -1; // -1 : silent GPURecoStepConfiguration cfgRecoStep; cfgRecoStep.steps = GPUDataTypes::RecoStep::NoRecoStep; cfgRecoStep.inputs.clear(); @@ -77,6 +79,7 @@ void TRDGlobalTracking::init(InitContext& ic) } // configure the tracker + // TODO: these settings will eventually be moved to GPUSettingsRec to be configurable via --configKeyValues //mTracker->EnableDebugOutput(); //mTracker->StartDebugging(); mTracker->SetPtThreshold(0.5); From 3ec3ed0f536de503236085e79063d835c81751b9 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Wed, 11 Nov 2020 14:47:15 +0100 Subject: [PATCH 1302/1751] Throw an error in case too many collisions are contained in a TF --- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 13 +++++++++++++ GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index 412126e6cda09..cb21b7f3fd668 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -1310,6 +1310,19 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::IsGeoFindable(const TRDTRK* t, const return true; } +template <class TRDTRK, class PROP> +GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::SetNCollisions(int nColl) +{ + // Set the number of collisions for a given time frame. + // The number is taken from the TRD trigger records + if (nColl < mNMaxCollisions) { + mNCollisions = nColl; + } else { + GPUError("Cannot process more than %i collisions. The last %i collisions will be dropped", mNMaxCollisions, nColl - mNMaxCollisions); + mNCollisions = mNMaxCollisions; + } +} + #ifndef GPUCA_GPUCODE namespace GPUCA_NAMESPACE { diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index c7f21a346ce6d..b1077ee62d37a 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -140,7 +140,7 @@ class GPUTRDTracker_t : public GPUProcessor // input from TRD trigger record GPUd() void SetNMaxCollisions(int nColl) { mNMaxCollisions = nColl; } // can this be fixed to a sufficiently large value? - GPUd() void SetNCollisions(int nColl) { mNCollisions = nColl; } + GPUd() void SetNCollisions(int nColl); GPUd() void SetTriggerRecordIndices(int* indices) { mTriggerRecordIndices = indices; } GPUd() void SetTriggerRecordTimes(float* times) { mTriggerRecordTimes = times; } From 43d4a97fa368b3873542b1b7296452b0a05882ab Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Thu, 12 Nov 2020 14:11:42 +0100 Subject: [PATCH 1303/1751] Less verbose debug output with standard settings --- .../TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 10 +++++----- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 7750fdd2e05d2..2926e78a6a032 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -114,7 +114,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) int64_t evTime = trg.getBCData().toLong() * o2::constants::lhc::LHCBunchSpacingNS; // event time in ns trdTriggerTimes.push_back(evTime / 1000.); trdTriggerIndices.push_back(iFirstTracklet); - LOGF(INFO, "Event %i: Occured at %li us after SOR, contains %i tracklets, index of first tracklet is %i", iEv, evTime / 1000, nTrackletsCurrent, iFirstTracklet); + LOGF(DEBUG, "Event %i: Occured at %li us after SOR, contains %i tracklets, index of first tracklet is %i", iEv, evTime / 1000, nTrackletsCurrent, iFirstTracklet); } mTracker->Reset(); @@ -125,7 +125,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) mRec->PrepareEvent(); mRec->SetupGPUProcessor(mTracker, true); - LOG(INFO) << "Start loading input into TRD tracker"; + LOG(DEBUG) << "Start loading input into TRD tracker"; // load everything into the tracker int nTracksLoaded = 0; for (int iTrk = 0; iTrk < nTracks; ++iTrk) { @@ -145,7 +145,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) continue; } ++nTracksLoaded; - LOGF(INFO, "Loaded track %i with time %f", nTracksLoaded, trkLoad.getTime()); + LOGF(DEBUG, "Loaded track %i with time %f", nTracksLoaded, trkLoad.getTime()); } for (int iTrklt = 0; iTrklt < nTracklets; ++iTrklt) { @@ -162,9 +162,9 @@ void TRDGlobalTracking::run(ProcessingContext& pc) mTracker->SetTriggerRecordTimes(&(trdTriggerTimes[0])); mTracker->SetTriggerRecordIndices(&(trdTriggerIndices[0])); mTracker->SetNCollisions(nCollisions); - mTracker->DumpTracks(); + //mTracker->DumpTracks(); mTracker->DoTracking(mChainTracking); - mTracker->DumpTracks(); + //mTracker->DumpTracks(); std::vector<GPUTRDTrack> tracksOut(mTracker->NTracks()); std::copy(mTracker->Tracks(), mTracker->Tracks() + mTracker->NTracks(), tracksOut.begin()); diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index cb21b7f3fd668..e44964e171845 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -405,8 +405,7 @@ GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::CheckTrackRefs(const int trackID, boo layer = 5; } if (layer < 0) { - Error("CheckTrackRefs", "No layer can be determined"); - GPUError("x=%f, y=%f, z=%f, layer=%i", xLoc, trackReference->LocalY(), trackReference->Z(), layer); + GPUError("No layer can be determined for x=%f, y=%f, z=%f, layer=%i", xLoc, trackReference->LocalY(), trackReference->Z(), layer); continue; } if (trackReference->TestBits(0x1 << 18)) { @@ -510,7 +509,9 @@ GPUd() int GPUTRDTracker_t<TRDTRK, PROP>::GetCollisionID(float trkTime) const { for (int iColl = 0; iColl < mNCollisions; ++iColl) { if (CAMath::Abs(trkTime - mTriggerRecordTimes[iColl]) < mTimeWindow) { - GPUInfo("TRD info found from interaction %i at %f for track with time %f", iColl, mTriggerRecordTimes[iColl], trkTime); + if (ENABLE_INFO) { + GPUInfo("TRD info found from interaction %i at %f for track with time %f", iColl, mTriggerRecordTimes[iColl], trkTime); + } return iColl; } } @@ -527,7 +528,9 @@ GPUd() void GPUTRDTracker_t<TRDTRK, PROP>::DoTrackingThread(int iTrk, int thread if (mProcessPerTimeFrame) { collisionId = GetCollisionID(mTracks[iTrk].getTime()); if (collisionId < 0) { - GPUInfo("Did not find TRD data for track with t=%f", mTracks[iTrk].getTime()); + if (ENABLE_INFO) { + GPUInfo("Did not find TRD data for track with t=%f", mTracks[iTrk].getTime()); + } // no TRD data available for the bunch crossing this track originates from return; } @@ -689,7 +692,6 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK if (ENABLE_INFO) { GPUInfo("Track propagation failed for track %i candidate %i in layer %i (pt=%f, x=%f, mR[layer]=%f)", iTrack, iCandidate, iLayer, trkWork->getPt(), trkWork->getX(), mR[2 * kNLayers + iLayer]); } - GPUInfo("Propagation failed"); continue; } @@ -698,7 +700,6 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK if (ENABLE_INFO) { GPUInfo("FollowProlongation: Adjusting sector failed for track %i candidate %i in layer %i", iTrack, iCandidate, iLayer); } - GPUInfo("Adjust sector failed"); continue; } @@ -716,7 +717,6 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK if (ENABLE_INFO) { GPUInfo("FollowProlongation: Track out of TRD acceptance with z=%f in layer %i (eta=%f)", trkWork->getZ(), iLayer, trkWork->getEta()); } - GPUInfo("Out of z acceptance"); continue; } From 8914e5100d83c666a91f1bc3b6d65fe9c90ae5be Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 19:17:27 +0100 Subject: [PATCH 1304/1751] Fix missing reference, speed up trap sim by ~100x for Pb-Pb --- Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index f3655aca05ba9..00079d0fce8c9 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -336,7 +336,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) LOG(debug) << "i:" << msgDigitsIndex[i]; } std::stable_sort(std::begin(msgDigitsIndex) + trig.getFirstEntry(), std::begin(msgDigitsIndex) + trig.getNumberOfObjects() + trig.getFirstEntry(), - [msgDigits](auto&& PH1, auto&& PH2) { return digitindexcompare(PH1, PH2, msgDigits); }); + [&msgDigits](auto&& PH1, auto&& PH2) { return digitindexcompare(PH1, PH2, msgDigits); }); LOG(debug) << "post sort"; for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) { LOG(debug) << "i:" << i << " = " << msgDigitsIndex[i]; From c8e3dc676f7172bcd29689fba9288e38bd064139 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Thu, 12 Nov 2020 21:48:55 +0100 Subject: [PATCH 1305/1751] Adjust to production CCDB (#4812) --- Analysis/Tutorials/src/efficiencyGlobal.cxx | 6 +++--- Analysis/Tutorials/src/efficiencyPerRun.cxx | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Analysis/Tutorials/src/efficiencyGlobal.cxx b/Analysis/Tutorials/src/efficiencyGlobal.cxx index f2a02d04b25e0..7f742ca493c2d 100644 --- a/Analysis/Tutorials/src/efficiencyGlobal.cxx +++ b/Analysis/Tutorials/src/efficiencyGlobal.cxx @@ -11,7 +11,7 @@ /// /// \brief This example demonstrates how the CCDB can be used to store an efficiency object which is valid for a full train run /// The objects are uploaded with -/// o2-ccdb-upload -p Users/jgrosseo/efficiency/simple -f eff.root -k efficiency --starttimestamp 1 --endtimestamp 16032093350000 +/// The objects are uploaded with https://alimonitor.cern.ch/ccdb/upload.jsp /// A sufficiently large time stamp interval should be given to span all runs under consideration /// NOTE If an efficiency object per run is needed, please check the example efficiencyPerRun.cxx /// @@ -28,8 +28,8 @@ using namespace o2; struct EfficiencyGlobal { Service<ccdb::BasicCCDBManager> ccdb; - Configurable<std::string> path{"ccdb-path", "Users/jgrosseo/efficiency/simple", "base path to the ccdb object"}; - Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable<std::string> path{"ccdb-path", "Users/j/jgrosseo/tutorial/efficiency/simple", "base path to the ccdb object"}; + Configurable<std::string> url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable<long> nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; OutputObj<TH1F> pt{TH1F("pt", "pt", 20, 0., 10.)}; diff --git a/Analysis/Tutorials/src/efficiencyPerRun.cxx b/Analysis/Tutorials/src/efficiencyPerRun.cxx index 2c8abeefc35e5..72636d35c6f77 100644 --- a/Analysis/Tutorials/src/efficiencyPerRun.cxx +++ b/Analysis/Tutorials/src/efficiencyPerRun.cxx @@ -12,10 +12,9 @@ /// \brief A tutorial task to retrieve objects from CCDB given a run number. /// This example demonstrates how the CCDB can be used to store an efficiency object which is valid only for a specific time /// interval (e.g. for a run) -/// The objects are uploaded with -/// o2-ccdb-upload -p Users/jgrosseo/efficiency/simple -f eff.root -k efficiency --starttimestamp 1 --endtimestamp 16032093350000 +/// The objects are uploaded with https://alimonitor.cern.ch/ccdb/upload.jsp /// Different timestamps intervals can be given. -/// You need to run this with the o2-analysis-timestamps example +/// You need to run this with the o2-analysis-timestamp task /// NOTE If only one efficiency object for all runs is needed, this code is not optimal. In this case please check the example: /// efficiencyGlobal.cxx /// @@ -32,8 +31,8 @@ using namespace o2; struct EfficiencyPerRun { Service<ccdb::BasicCCDBManager> ccdb; - Configurable<std::string> path{"ccdb-path", "Users/jgrosseo/efficiency/simple", "base path to the ccdb object"}; - Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable<std::string> path{"ccdb-path", "Users/j/jgrosseo/tutorial/efficiency/simple", "base path to the ccdb object"}; + Configurable<std::string> url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable<long> nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; OutputObj<TH1F> pt{TH1F("pt", "pt", 20, 0., 10.)}; From bbc7c85547f0601fef726dc4167ef932c69ea96a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 12 Nov 2020 21:50:29 +0100 Subject: [PATCH 1306/1751] DPL: consider internal-dpl-injected devices as real devices (#4825) --- Framework/Core/src/CommonDataProcessors.cxx | 4 ++-- Framework/Core/src/DataProcessingDevice.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 549edb6bfdee9..9951143054ae9 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -486,10 +486,10 @@ DataProcessorSpec CommonDataProcessors::getGlobalFairMQSink(std::vector<InputSpe DataProcessorSpec CommonDataProcessors::getDummySink(std::vector<InputSpec> const& danglingOutputInputs) { return DataProcessorSpec{ - "internal-dpl-dummy-sink", + "internal-dpl-injected-dummy-sink", danglingOutputInputs, Outputs{}, - }; + AlgorithmSpec([](ProcessingContext& ctx) {})}; } } // namespace framework diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 01ba3816663dc..5aac39bb4d3b7 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -319,7 +319,7 @@ void DataProcessingDevice::InitTask() // We add a timer only in case a channel poller is not there. if ((mStatefulProcess != nullptr) || (mStatelessProcess != nullptr)) { for (auto& x : fChannels) { - if ((x.first.rfind("from_internal-dpl", 0) == 0) && (x.first.rfind("from_internal-dpl-aod", 0) != 0)) { + if ((x.first.rfind("from_internal-dpl", 0) == 0) && (x.first.rfind("from_internal-dpl-aod", 0) != 0) && (x.first.rfind("from_internal-dpl-injected", 0)) != 0) { LOG(debug) << x.first << " is an internal channel. Skipping as no input will come from there." << std::endl; continue; } From 233b46066f83db33a3437a028c08651c6dfa19f2 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 12 Nov 2020 21:51:47 +0100 Subject: [PATCH 1307/1751] DPL: improve DataSpecUtils (#4824) --- Framework/Core/src/DataSpecUtils.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index a56b288fa8212..ab36bde400a47 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -269,8 +269,11 @@ bool DataSpecUtils::partialMatch(InputSpec const& input, header::DataOrigin cons bool DataSpecUtils::partialMatch(InputSpec const& input, header::DataDescription const& description) { - auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(input); - return dataType.description == description; + try { + return DataSpecUtils::asConcreteDataDescription(input) == description; + } catch (...) { + return false; + } } bool DataSpecUtils::partialMatch(OutputSpec const& output, header::DataDescription const& description) @@ -400,7 +403,7 @@ ConcreteDataTypeMatcher DataSpecUtils::asConcreteDataTypeMatcher(OutputSpec cons ConcreteDataTypeMatcher DataSpecUtils::asConcreteDataTypeMatcher(InputSpec const& spec) { return std::visit(overloaded{ - [](ConcreteDataMatcher const& concrete) { + [](auto const& concrete) { return ConcreteDataTypeMatcher{concrete.origin, concrete.description}; }, [](DataDescriptorMatcher const& matcher) { @@ -416,7 +419,7 @@ ConcreteDataTypeMatcher DataSpecUtils::asConcreteDataTypeMatcher(InputSpec const header::DataOrigin DataSpecUtils::asConcreteOrigin(InputSpec const& spec) { return std::visit(overloaded{ - [](ConcreteDataMatcher const& concrete) { + [](auto const& concrete) { return concrete.origin; }, [](DataDescriptorMatcher const& matcher) { @@ -432,7 +435,7 @@ header::DataOrigin DataSpecUtils::asConcreteOrigin(InputSpec const& spec) header::DataDescription DataSpecUtils::asConcreteDataDescription(InputSpec const& spec) { return std::visit(overloaded{ - [](ConcreteDataMatcher const& concrete) { + [](auto const& concrete) { return concrete.description; }, [](DataDescriptorMatcher const& matcher) { From bdcc6a46cc762a386da8ce3ca494456c95e7ea25 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 13 Nov 2020 07:16:00 +0100 Subject: [PATCH 1308/1751] DPL: improve forwarding policy (#4609) --- .../include/Framework/runDataProcessing.h | 13 ++++++++- Framework/Core/src/CommonDataProcessors.cxx | 2 +- Framework/Core/src/WorkflowHelpers.cxx | 29 ++++++++++++------- Framework/Core/test/test_WorkflowHelpers.cxx | 12 ++++++-- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 9e47b6757b78b..853735ff13f52 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -127,7 +127,6 @@ int main(int argc, char** argv) UserCustomizationsHelper::userDefinedCustomization(workflowOptions, 0); workflowOptions.push_back(ConfigParamSpec{"readers", VariantType::Int64, 1ll, {"number of parallel readers to use"}}); workflowOptions.push_back(ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}); - workflowOptions.push_back(ConfigParamSpec{"dangling-outputs-policy", VariantType::String, "file", {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}); // options for AOD rate limiting workflowOptions.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::Int64, 0LL, {"Rate limit AOD processing based on memory"}}); @@ -139,6 +138,18 @@ int main(int argc, char** argv) workflowOptions.push_back(ConfigParamSpec{"aod-writer-ntfmerge", VariantType::Int, -1, {"Number of time frames to merge into one file"}}); workflowOptions.push_back(ConfigParamSpec{"aod-writer-keep", VariantType::String, "", {"Comma separated list of ORIGIN/DESCRIPTION/SUBSPECIFICATION:treename:col1/col2/..:filename"}}); + workflowOptions.push_back(ConfigParamSpec{"forwarding-policy", + VariantType::String, + "dangling", + {"Which messages to forward." + " dangling: dangling outputs," + " all: all messages"}}); + workflowOptions.push_back(ConfigParamSpec{"forwarding-destination", + VariantType::String, + "file", + {"Destination for forwarded messages." + " file: write to file," + " fairmq: send to output proxy"}}); std::vector<ChannelConfigurationPolicy> channelPolicies; UserCustomizationsHelper::userDefinedCustomization(channelPolicies, 0); auto defaultChannelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 9951143054ae9..5132375603223 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -480,7 +480,7 @@ DataProcessorSpec CommonDataProcessors::getGlobalFairMQSink(std::vector<InputSpe externalChannelSpec.protocol = ChannelProtocol::IPC; std::string defaultChannelConfig = formatExternalChannelConfiguration(externalChannelSpec); // at some point the formatting tool might add the transport as well so we have to check - return specifyFairMQDeviceOutputProxy("internal-dpl-output-proxy", danglingOutputInputs, defaultChannelConfig.c_str()); + return specifyFairMQDeviceOutputProxy("internal-dpl-injected-output-proxy", danglingOutputInputs, defaultChannelConfig.c_str()); } DataProcessorSpec CommonDataProcessors::getDummySink(std::vector<InputSpec> const& danglingOutputInputs) diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index bd5ed815c56c4..8e517cd2bccd4 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -468,23 +468,32 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); extraSpecs.clear(); - // file sink for notAOD dangling outputs - // select dangling outputs which are not of type AOD - std::vector<InputSpec> outputsInputsDangling; + // Select dangling outputs which are not of type AOD + std::vector<InputSpec> redirectedOutputsInputs; for (auto ii = 0u; ii < outputsInputs.size(); ii++) { - if ((outputTypes[ii] & DANGLING) == DANGLING && (outputTypes[ii] & ANALYSIS) == 0) { - outputsInputsDangling.emplace_back(outputsInputs[ii]); + if (ctx.options().get<std::string>("forwarding-policy") == "none") { + continue; + } + // We forward to the output proxy all the inputs only if they are dangling + // or if the forwarding policy is "proxy". + if (!(outputTypes[ii] & DANGLING) && (ctx.options().get<std::string>("forwarding-policy") != "all")) { + continue; + } + // AODs are skipped in any case. + if ((outputTypes[ii] & ANALYSIS)) { + continue; } + redirectedOutputsInputs.emplace_back(outputsInputs[ii]); } std::vector<InputSpec> unmatched; - if (outputsInputsDangling.size() > 0 && ctx.options().get<std::string>("dangling-outputs-policy") == "file") { - auto fileSink = CommonDataProcessors::getGlobalFileSink(outputsInputsDangling, unmatched); - if (unmatched.size() != outputsInputsDangling.size()) { + if (redirectedOutputsInputs.size() > 0 && ctx.options().get<std::string>("forwarding-destination") == "file") { + auto fileSink = CommonDataProcessors::getGlobalFileSink(redirectedOutputsInputs, unmatched); + if (unmatched.size() != redirectedOutputsInputs.size()) { extraSpecs.push_back(fileSink); } - } else if (outputsInputsDangling.size() > 0 && ctx.options().get<std::string>("dangling-outputs-policy") == "fairmq") { - auto fairMQSink = CommonDataProcessors::getGlobalFairMQSink(outputsInputsDangling); + } else if (redirectedOutputsInputs.size() > 0 && ctx.options().get<std::string>("forwarding-destination") == "fairmq") { + auto fairMQSink = CommonDataProcessors::getGlobalFairMQSink(redirectedOutputsInputs); extraSpecs.push_back(fairMQSink); } if (unmatched.size() > 0) { diff --git a/Framework/Core/test/test_WorkflowHelpers.cxx b/Framework/Core/test/test_WorkflowHelpers.cxx index b3ccd86aac17b..9b9c36a171a12 100644 --- a/Framework/Core/test/test_WorkflowHelpers.cxx +++ b/Framework/Core/test/test_WorkflowHelpers.cxx @@ -29,8 +29,16 @@ std::unique_ptr<ConfigContext> makeEmptyConfigContext() // FIXME: Ugly... We need to fix ownership and make sure the ConfigContext // either owns or shares ownership of the registry. std::vector<std::unique_ptr<ParamRetriever>> retrievers; - static std::vector<ConfigParamSpec> specs; - specs.push_back(ConfigParamSpec{"dangling-outputs-policy", VariantType::String, "file", {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}); + static std::vector<ConfigParamSpec> specs = { + ConfigParamSpec{"forwarding-policy", + VariantType::String, + "dangling", + {""}}, + ConfigParamSpec{"forwarding-destination", + VariantType::String, + "file", + {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}, + }; specs.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::String, "0", {"rate"}}); auto store = std::make_unique<ConfigParamStore>(specs, std::move(retrievers)); store->preload(); From 39a289070e09c99aa4003423e2d11f263c4aa6a4 Mon Sep 17 00:00:00 2001 From: sgorbuno <sergey.gorbunov@fias.uni-frankfurt.de> Date: Thu, 15 Oct 2020 22:23:24 +0000 Subject: [PATCH 1309/1751] new interfaces for 1D and 2D splines, ND splines --- .../TPCFastTransformHelperO2.h | 2 +- .../src/TPCFastTransformHelperO2.cxx | 8 +- .../dEdx/TPCdEdxCalibrationSplines.cxx | 2 +- .../dEdx/TPCdEdxCalibrationSplines.h | 2 +- GPU/TPCFastTransformation/CMakeLists.txt | 11 +- GPU/TPCFastTransformation/Spline.cxx | 23 + GPU/TPCFastTransformation/Spline.h | 117 +++ GPU/TPCFastTransformation/Spline1D.cxx | 495 +----------- GPU/TPCFastTransformation/Spline1D.h | 472 +++-------- GPU/TPCFastTransformation/Spline1DHelper.cxx | 742 ++++++++++++++++++ .../{SplineHelper1D.h => Spline1DHelper.h} | 63 +- GPU/TPCFastTransformation/Spline1DSpec.cxx | 275 +++++++ GPU/TPCFastTransformation/Spline1DSpec.h | 517 ++++++++++++ GPU/TPCFastTransformation/Spline2D.cxx | 488 +----------- GPU/TPCFastTransformation/Spline2D.h | 423 +--------- GPU/TPCFastTransformation/Spline2DHelper.cxx | 484 ++++++++++++ GPU/TPCFastTransformation/Spline2DHelper.h | 153 ++++ GPU/TPCFastTransformation/Spline2DSpec.cxx | 230 ++++++ GPU/TPCFastTransformation/Spline2DSpec.h | 476 +++++++++++ GPU/TPCFastTransformation/SplineHelper.cxx | 544 +++++++++++++ GPU/TPCFastTransformation/SplineHelper.h | 164 ++++ GPU/TPCFastTransformation/SplineHelper1D.cxx | 477 ----------- GPU/TPCFastTransformation/SplineHelper2D.cxx | 213 ----- GPU/TPCFastTransformation/SplineHelper2D.h | 150 ---- GPU/TPCFastTransformation/SplineSpec.cxx | 232 ++++++ GPU/TPCFastTransformation/SplineSpec.h | 557 +++++++++++++ GPU/TPCFastTransformation/SplineUtil.h | 111 +++ .../TPCFastSpaceChargeCorrection.cxx | 20 +- .../TPCFastSpaceChargeCorrection.h | 10 +- .../TPCFastTransform.cxx | 4 - .../TPCFastTransformGeo.cxx | 2 - .../TPCFastTransformManager.cxx | 4 +- .../TPCFastTransformationLinkDef_AliRoot.h | 32 - .../TPCFastTransformationLinkDef_O2.h | 39 +- .../devtools/IrregularSpline2D3D.h | 1 - .../IrregularSpline2D3DCalibrator.cxx | 2 - GPU/TPCFastTransformation/macro/SplineDemo.C | 22 +- .../test/testSplines.cxx | 6 +- 38 files changed, 4854 insertions(+), 2719 deletions(-) create mode 100644 GPU/TPCFastTransformation/Spline.cxx create mode 100644 GPU/TPCFastTransformation/Spline.h create mode 100644 GPU/TPCFastTransformation/Spline1DHelper.cxx rename GPU/TPCFastTransformation/{SplineHelper1D.h => Spline1DHelper.h} (58%) create mode 100644 GPU/TPCFastTransformation/Spline1DSpec.cxx create mode 100644 GPU/TPCFastTransformation/Spline1DSpec.h create mode 100644 GPU/TPCFastTransformation/Spline2DHelper.cxx create mode 100644 GPU/TPCFastTransformation/Spline2DHelper.h create mode 100644 GPU/TPCFastTransformation/Spline2DSpec.cxx create mode 100644 GPU/TPCFastTransformation/Spline2DSpec.h create mode 100644 GPU/TPCFastTransformation/SplineHelper.cxx create mode 100644 GPU/TPCFastTransformation/SplineHelper.h delete mode 100644 GPU/TPCFastTransformation/SplineHelper1D.cxx delete mode 100644 GPU/TPCFastTransformation/SplineHelper2D.cxx delete mode 100644 GPU/TPCFastTransformation/SplineHelper2D.h create mode 100644 GPU/TPCFastTransformation/SplineSpec.cxx create mode 100644 GPU/TPCFastTransformation/SplineSpec.h create mode 100644 GPU/TPCFastTransformation/SplineUtil.h diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/TPCFastTransformHelperO2.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/TPCFastTransformHelperO2.h index c042ac444a65c..1ec1a9c8a155c 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/TPCFastTransformHelperO2.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/TPCFastTransformHelperO2.h @@ -74,7 +74,7 @@ class TPCFastTransformHelperO2 /// initialization void init(); /// get space charge correction in internal TPCFastTransform coordinates su,sv->dx,du,dv - int getSpaceChargeCorrection(int slice, int row, float su, float sv, float& dx, float& du, float& dv); + int getSpaceChargeCorrection(int slice, int row, double su, double sv, double& dx, double& du, double& dv); static TPCFastTransformHelperO2* sInstance; ///< singleton instance bool mIsInitialized = 0; ///< initialization flag diff --git a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx index ce79babfe0b57..e8b5979231b8d 100644 --- a/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx +++ b/Detectors/TPC/reconstruction/src/TPCFastTransformHelperO2.cxx @@ -21,7 +21,7 @@ #include "TPCBase/Sector.h" #include "DataFormatsTPC/Defs.h" #include "TPCFastTransform.h" -#include "SplineHelper2D.h" +#include "Spline2DHelper.h" #include "Riostream.h" #include "FairLogger.h" @@ -266,9 +266,9 @@ int TPCFastTransformHelperO2::updateCalibration(TPCFastTransform& fastTransform, for (int row = 0; row < correction.getGeometry().getNumberOfRows(); row++) { const TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(slice, row); float* data = correction.getSplineData(slice, row); - SplineHelper2D<float> helper; + Spline2DHelper<float> helper; helper.setSpline(spline, 3, 3); - auto F = [&](float su, float sv, float dxuv[3]) { + auto F = [&](double su, double sv, double dxuv[3]) { getSpaceChargeCorrection(slice, row, su, sv, dxuv[0], dxuv[1], dxuv[2]); }; helper.approximateFunction(data, 0., 1., 0., 1., F); @@ -284,7 +284,7 @@ int TPCFastTransformHelperO2::updateCalibration(TPCFastTransform& fastTransform, return 0; } -int TPCFastTransformHelperO2::getSpaceChargeCorrection(int slice, int row, float su, float sv, float& dx, float& du, float& dv) +int TPCFastTransformHelperO2::getSpaceChargeCorrection(int slice, int row, double su, double sv, double& dx, double& du, double& dv) { // get space charge correction in internal TPCFastTransform coordinates su,sv->dx,du,dv diff --git a/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.cxx b/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.cxx index 074b22517fab5..7cf0d7b3608a7 100644 --- a/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.cxx +++ b/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.cxx @@ -183,7 +183,7 @@ void TPCdEdxCalibrationSplines::setDefaultSplines() int offsets1[FSplines]; int offsets2[FSplines]; - auto defaultFnd2D = [&](float x1, float x2, float f[]) { + auto defaultFnd2D = [&](double x1, double x2, double f[]) { f[0] = 1.f; }; diff --git a/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.h b/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.h index 6fd5999d94340..cffd3f7cadccf 100644 --- a/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.h +++ b/GPU/GPUTracking/dEdx/TPCdEdxCalibrationSplines.h @@ -68,7 +68,7 @@ namespace gpu class TPCdEdxCalibrationSplines : public FlatObject { public: - typedef Spline2D<float, 1, 1> SplineType; + typedef Spline2D<float, 1> SplineType; /// _____________ Constructors / destructors __________________________ diff --git a/GPU/TPCFastTransformation/CMakeLists.txt b/GPU/TPCFastTransformation/CMakeLists.txt index 981b20ff8a8d0..1b91851677d6e 100644 --- a/GPU/TPCFastTransformation/CMakeLists.txt +++ b/GPU/TPCFastTransformation/CMakeLists.txt @@ -11,10 +11,15 @@ set(MODULE TPCFastTransformation) set(SRCS + SplineSpec.cxx + Spline.cxx + SplineHelper.cxx + Spline1DSpec.cxx Spline1D.cxx + Spline1DHelper.cxx + Spline2DSpec.cxx Spline2D.cxx - SplineHelper1D.cxx - SplineHelper2D.cxx + Spline2DHelper.cxx ChebyshevFit1D.cxx devtools/IrregularSpline1D.cxx devtools/IrregularSpline2D3D.cxx @@ -26,7 +31,7 @@ set(SRCS ) string(REPLACE ".cxx" ".h" HDRS_CINT_O2 "${SRCS}") -set(HDRS_CINT_O2 ${HDRS_CINT_O2} devtools/RegularSpline1D.h) +set(HDRS_CINT_O2 ${HDRS_CINT_O2} SplineUtil.h devtools/RegularSpline1D.h) if(${ALIGPU_BUILD_TYPE} STREQUAL "O2") o2_add_library(${MODULE} diff --git a/GPU/TPCFastTransformation/Spline.cxx b/GPU/TPCFastTransformation/Spline.cxx new file mode 100644 index 0000000000000..cdebd17ad68f1 --- /dev/null +++ b/GPU/TPCFastTransformation/Spline.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. + +/// \file Spline.cxx +/// \brief Implementation of Spline class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#include "Spline.h" + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +templateClassImp(GPUCA_NAMESPACE::gpu::Spline); +#endif + +template class GPUCA_NAMESPACE::gpu::Spline<float>; +template class GPUCA_NAMESPACE::gpu::Spline<double>; diff --git a/GPU/TPCFastTransformation/Spline.h b/GPU/TPCFastTransformation/Spline.h new file mode 100644 index 0000000000000..c6f3360fa9827 --- /dev/null +++ b/GPU/TPCFastTransformation/Spline.h @@ -0,0 +1,117 @@ +// 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 Spline.h +/// \brief Definition of Spline class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE_H + +#include "SplineSpec.h" + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ +/// +/// The Spline class performs a cubic spline interpolation on an two-dimensional nonunifom grid. +/// The class is an extension of the Spline1D class. +/// See Spline1D.h for more details. +/// +/// The spline S(x) approximates a function F(x):R^n->R^m, +/// with multi-dimensional domain and multi-dimensional codomain. +/// x belongs to [xmin,xmax]. +/// +/// --- Example of creating a spline --- +/// +/// constexpr int nDimX = 2, nDimY = 1; +/// int nKnots[nDimX] = {2, 3}; // 2 x 3 knots +/// int knotsU1[] = {0, 1}; // relative knot positions +/// int knotsU2[] = {0, 2, 5}; +/// int *knotsU[nDimX] = {knotsU1, knotsU2}; +/// +/// o2::gpu::Spline<float, nDimX, nDimY> spline(nKnots, knotsU); +/// +/// auto F = [&](const double x[], double f[]) { +/// f[0] = 1.f + x[0] + x[1] * x[1]; // F(x) +/// }; +/// double xMin[nDimX] = {0.f, 0.f}; +/// double xMax[nDimX] = {1.f, 1.f}; +/// spline.approximateFunction( xMin, xMax, F); // initialize spline to approximate F on [0., 1.]x[0., 1.] area +/// +/// float x[] = {.1, .3}; +/// float S = spline.interpolate(x); // interpolated value at (.1,.3) +/// +/// -- another way to create of the spline is: +/// +/// o2::gpu::Spline<float> spline(nDimX, nDimY, nKnots, knotsU ); +/// spline.interpolate(x, &S); +/// +/// --- See also SplineHelper::test(); +/// + +/// ================================================================================================== +/// +/// Declare the Spline class as a template with two optional parameters. +/// +/// Class specializations depend on the XdimT, YdimT values. They can be found in SplineSpecs.h +/// +/// \param DataT data type: float or double +/// \param XdimT +/// XdimT > 0 : the number of X dimensions is known at the compile time and is equal to XdimT +/// XdimT = 0 : the number of X dimensions will be set in the runtime +/// XdimT < 0 : the number of X dimensions will be set in the runtime, and it will not exceed abs(XdimT) +/// \param YdimT same for the Y dimensions +/// +template <typename DataT, int XdimT = 0, int YdimT = 0> +class Spline + : public SplineSpec<DataT, XdimT, YdimT, SplineUtil::getSpec(XdimT, YdimT)> +{ + typedef SplineContainer<DataT> TVeryBase; + typedef SplineSpec<DataT, XdimT, YdimT, SplineUtil::getSpec(XdimT, YdimT)> TBase; + + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + typedef typename TVeryBase::Knot Knot; + +#if !defined(GPUCA_GPUCODE) + using TBase::TBase; // inherit constructors + + /// Assignment operator + Spline& operator=(const Spline& v) + { + TVeryBase::cloneFromObject(v, nullptr); + return *this; + } +#else + /// Disable constructors for the GPU implementation + Spline() CON_DELETE; + Spline(const Spline&) CON_DELETE; +#endif + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// read a class object from the file + static Spline* readFromFile(TFile& inpf, const char* name) + { + return (Spline*)TVeryBase::readFromFile(inpf, name); + } +#endif + +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline, 0); +#endif +}; + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/TPCFastTransformation/Spline1D.cxx b/GPU/TPCFastTransformation/Spline1D.cxx index 03459763aa6f6..e5bf074ca410f 100644 --- a/GPU/TPCFastTransformation/Spline1D.cxx +++ b/GPU/TPCFastTransformation/Spline1D.cxx @@ -13,504 +13,11 @@ /// /// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation -#include "Rtypes.h" -#endif - #include "Spline1D.h" -#include <cmath> - -#if !defined(GPUCA_GPUCODE) // code invisible on GPU -#include <vector> -#include <algorithm> -#include <iostream> -#endif #if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation -#include "TRandom.h" -#include "Riostream.h" -#include "TMath.h" -#include "SplineHelper1D.h" -#include "TCanvas.h" -#include "TNtuple.h" -#include "TH1.h" -#include "TFile.h" -#include "GPUCommonMath.h" - templateClassImp(GPUCA_NAMESPACE::gpu::Spline1D); - -#endif - -using namespace GPUCA_NAMESPACE::gpu; - -template <typename DataT> -void Spline1D<DataT>::destroy() -{ - /// See FlatObject for description - mNumberOfKnots = 0; - mUmax = 0; - mFdimensions = 0; - mXmin = 0.; - mXtoUscale = 1.; - mUtoKnotMap = nullptr; - mFparameters = nullptr; - FlatObject::destroy(); -} - -#if !defined(GPUCA_GPUCODE) -template <typename DataT> -void Spline1D<DataT>::cloneFromObject(const Spline1D& obj, char* newFlatBufferPtr) -{ - /// See FlatObject for description - const char* oldFlatBufferPtr = obj.mFlatBufferPtr; - FlatObject::cloneFromObject(obj, newFlatBufferPtr); - mNumberOfKnots = obj.mNumberOfKnots; - mUmax = obj.mUmax; - mFdimensions = obj.mFdimensions; - mXmin = obj.mXmin; - mXtoUscale = obj.mXtoUscale; - mUtoKnotMap = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mUtoKnotMap); - mFparameters = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mFparameters); -} - -template <typename DataT> -void Spline1D<DataT>::moveBufferTo(char* newFlatBufferPtr) -{ - /// See FlatObject for description - const char* oldFlatBufferPtr = mFlatBufferPtr; - FlatObject::moveBufferTo(newFlatBufferPtr); - mUtoKnotMap = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, mUtoKnotMap); - mFparameters = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, mFparameters); -} -#endif - -template <typename DataT> -void Spline1D<DataT>::setActualBufferAddress(char* actualFlatBufferPtr) -{ - /// See FlatObject for description - //mUtoKnotMap = FlatObject::relocatePointer(mFlatBufferPtr, actualFlatBufferPtr, mUtoKnotMap); - //mFparameters = FlatObject::relocatePointer(mFlatBufferPtr, actualFlatBufferPtr, mFparameters); - - const int uToKnotMapOffset = mNumberOfKnots * sizeof(Spline1D::Knot); - const int parametersOffset = uToKnotMapOffset + (mUmax + 1) * sizeof(int); - //int bufferSize = parametersOffset + getSizeOfParameters(mFdimensions); - - FlatObject::setActualBufferAddress(actualFlatBufferPtr); - mUtoKnotMap = reinterpret_cast<int*>(mFlatBufferPtr + uToKnotMapOffset); - mFparameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); -} - -template <typename DataT> -void Spline1D<DataT>::setFutureBufferAddress(char* futureFlatBufferPtr) -{ - /// See FlatObject for description - mUtoKnotMap = FlatObject::relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mUtoKnotMap); - mFparameters = FlatObject::relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mFparameters); - FlatObject::setFutureBufferAddress(futureFlatBufferPtr); -} - -#if !defined(GPUCA_GPUCODE) - -template <typename DataT> -void Spline1D<DataT>::recreate(int numberOfKnots, const int inputKnots[], int nFdimensions) -{ - /// Main constructor for an irregular spline - /// - /// Number of created knots may differ from the input values: - /// - Duplicated knots will be deleted - /// - At least 2 knots will be created - /// - /// \param numberOfKnots Number of knots in knots[] array - /// \param knots Array of relative knot positions (integer values) - /// - - FlatObject::startConstruction(); - - std::vector<int> knotU; - - { // sort knots - std::vector<int> tmp; - for (int i = 0; i < numberOfKnots; i++) { - tmp.push_back(inputKnots[i]); - } - std::sort(tmp.begin(), tmp.end()); - - knotU.push_back(0); // first knot at 0 - - for (unsigned int i = 1; i < tmp.size(); ++i) { - int u = tmp[i] - tmp[0]; - if (knotU.back() < u) { // remove duplicated knots - knotU.push_back(u); - } - } - if (knotU.back() < 1) { // at least 2 knots - knotU.push_back(1); - } - } - - mNumberOfKnots = knotU.size(); - mUmax = knotU.back(); - mFdimensions = nFdimensions; - mXmin = 0.; - mXtoUscale = 1.; - - const int uToKnotMapOffset = mNumberOfKnots * sizeof(Spline1D::Knot); - const int parametersOffset = uToKnotMapOffset + (mUmax + 1) * sizeof(int); - const int bufferSize = parametersOffset + getSizeOfParameters(mFdimensions); - - FlatObject::finishConstruction(bufferSize); - - mUtoKnotMap = reinterpret_cast<int*>(mFlatBufferPtr + uToKnotMapOffset); - mFparameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); - - Knot* s = getKnots(); - - for (int i = 0; i < mNumberOfKnots; i++) { - s[i].u = knotU[i]; - } - - for (int i = 0; i < mNumberOfKnots - 1; i++) { - s[i].Li = 1. / (s[i + 1].u - s[i].u); // do division in double - } - - s[mNumberOfKnots - 1].Li = 0.; // the value will not be used, we define it for consistency - - // Set up the map (integer U) -> (knot index) - - int* map = getUtoKnotMap(); - - const int iKnotMax = mNumberOfKnots - 2; - - // - // With iKnotMax=nKnots-2 we map the U==Umax coordinate to the last [nKnots-2, nKnots-1] segment. - // This trick allows one to avoid a special condition for this edge case. - // Any U from [0,Umax] is mapped to some knot_i such, that the next knot_i+1 always exist - // - - for (int u = 0, iKnot = 0; u <= mUmax; u++) { - if ((knotU[iKnot + 1] == u) && (iKnot < iKnotMax)) { - iKnot = iKnot + 1; - } - map[u] = iKnot; - } - - for (int i = 0; i < getNumberOfParameters(mFdimensions); i++) { - mFparameters[i] = 0.f; - } -} - -template <typename DataT> -void Spline1D<DataT>::recreate(int numberOfKnots, int nFdimensions) -{ - /// Constructor for a regular spline - /// \param numberOfKnots Number of knots - - if (numberOfKnots < 2) { - numberOfKnots = 2; - } - - std::vector<int> knots(numberOfKnots); - for (int i = 0; i < numberOfKnots; i++) { - knots[i] = i; - } - recreate(numberOfKnots, knots.data(), nFdimensions); -} - #endif -template <typename DataT> -void Spline1D<DataT>::print() const -{ - printf(" Compact Spline 1D: \n"); - printf(" mNumberOfKnots = %d \n", mNumberOfKnots); - printf(" mUmax = %d\n", mUmax); - printf(" mUtoKnotMap = %p \n", (void*)mUtoKnotMap); - printf(" knots: "); - for (int i = 0; i < mNumberOfKnots; i++) { - printf("%d ", (int)getKnot(i).u); - } - printf("\n"); -} - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) -template <typename DataT> -int Spline1D<DataT>::writeToFile(TFile& outf, const char* name) -{ - /// write a class object to the file - return FlatObject::writeToFile(*this, outf, name); -} - -template <typename DataT> -Spline1D<DataT>* Spline1D<DataT>::readFromFile(TFile& inpf, const char* name) -{ - /// read a class object from the file - return FlatObject::readFromFile<Spline1D<DataT>>(inpf, name); -} - -template <typename DataT> -void Spline1D<DataT>::approximateFunction(DataT xMin, DataT xMax, - std::function<void(DataT x, DataT f[/*mFdimensions*/])> F, - int nAxiliaryDataPoints) -{ - /// Approximate F with this spline - setXrange(xMin, xMax); - SplineHelper1D<DataT> helper; - helper.approximateFunction(*this, xMin, xMax, F, nAxiliaryDataPoints); -} - -template <typename DataT> -int Spline1D<DataT>::test(const bool draw, const bool drawDataPoints) -{ - using namespace std; - - // input function F - - const int Ndim = 5; - const int Fdegree = 4; - double Fcoeff[Ndim][2 * (Fdegree + 1)]; - - auto F = [&](DataT x, DataT f[]) -> void { - double cosx[Fdegree + 1], sinx[Fdegree + 1]; - double xi = 0; - for (int i = 0; i <= Fdegree; i++, xi += x) { - GPUCommonMath::SinCos(xi, sinx[i], cosx[i]); - } - for (int dim = 0; dim < Ndim; dim++) { - f[dim] = 0; // Fcoeff[0]/2; - for (int i = 1; i <= Fdegree; i++) { - f[dim] += Fcoeff[dim][2 * i] * cosx[i] + Fcoeff[dim][2 * i + 1] * sinx[i]; - } - } - }; - - TCanvas* canv = nullptr; - TNtuple* nt = nullptr; - TNtuple* knots = nullptr; - - auto ask = [&]() -> bool { - if (!canv) { - return 0; - } - canv->Update(); - cout << "type 'q ' to exit" << endl; - std::string str; - std::getline(std::cin, str); - return (str != "q" && str != ".q"); - }; - - std::cout << "Test 1D interpolation with the compact spline" << std::endl; - - int nTries = 100; - - if (draw) { - canv = new TCanvas("cQA", "Spline1D QA", 1000, 600); - nTries = 10000; - } - - double statDf1 = 0; - double statDf2 = 0; - double statDf1D = 0; - double statN = 0; - - int seed = 1; - - for (int itry = 0; itry < nTries; itry++) { - - // init random F - for (int dim = 0; dim < Ndim; dim++) { - gRandom->SetSeed(seed++); - for (int i = 0; i < 2 * (Fdegree + 1); i++) { - Fcoeff[dim][i] = gRandom->Uniform(-1, 1); - } - } - - // spline - - int nKnots = 4; - const int uMax = nKnots * 3; - - Spline1D spline1; - int knotsU[nKnots]; - - do { // set knots randomly - knotsU[0] = 0; - double du = 1. * uMax / (nKnots - 1); - for (int i = 1; i < nKnots; i++) { - knotsU[i] = (int)(i * du); // + gRandom->Uniform(-du / 3, du / 3); - } - knotsU[nKnots - 1] = uMax; - spline1.recreate(nKnots, knotsU, Ndim); - if (nKnots != spline1.getNumberOfKnots()) { - cout << "warning: n knots changed during the initialisation " << nKnots - << " -> " << spline1.getNumberOfKnots() << std::endl; - continue; - } - } while (0); - - std::string err = FlatObject::stressTest(spline1); - if (!err.empty()) { - cout << "error at FlatObject functionality: " << err << endl; - return -1; - } else { - // cout << "flat object functionality is ok" << endl; - } - - nKnots = spline1.getNumberOfKnots(); - int nAxiliaryPoints = 1; - Spline1D spline2; //(spline1); - spline2.cloneFromObject(spline1, nullptr); - - spline1.approximateFunction(0., TMath::Pi(), F, nAxiliaryPoints); - - //if (itry == 0) - { - TFile outf("testSpline1D.root", "recreate"); - if (outf.IsZombie()) { - cout << "Failed to open output file testSpline1D.root " << std::endl; - } else { - const char* name = "spline1Dtest"; - spline1.writeToFile(outf, name); - Spline1D<DataT>* p = spline1.readFromFile(outf, name); - if (p == nullptr) { - cout << "Failed to read Spline1D from file testSpline1D.root " << std::endl; - } else { - spline1 = *p; - } - outf.Close(); - } - } - - SplineHelper1D<DataT> helper; - helper.setSpline(spline2, Ndim, nAxiliaryPoints); - helper.approximateFunctionGradually(spline2, 0., TMath::Pi(), F, nAxiliaryPoints); - - // 1-D splines for each dimension - Spline1D splines3[Ndim]; - { - for (int dim = 0; dim < Ndim; dim++) { - auto F3 = [&](DataT u, DataT f[]) -> void { - DataT ff[Ndim]; - F(u, ff); - f[0] = ff[dim]; - }; - splines3[dim].recreate(nKnots, knotsU, 1); - splines3[dim].approximateFunction(0., TMath::Pi(), F3, nAxiliaryPoints); - } - } - - double stepX = 1.e-2; - for (double x = 0; x < TMath::Pi(); x += stepX) { - DataT f[Ndim], s1[Ndim], s2[Ndim]; - F(x, f); - spline1.interpolate(x, s1); - spline2.interpolate(x, s2); - for (int dim = 0; dim < Ndim; dim++) { - statDf1 += (s1[dim] - f[dim]) * (s1[dim] - f[dim]); - statDf2 += (s2[dim] - f[dim]) * (s2[dim] - f[dim]); - DataT s1D = splines3[dim].interpolate(x); - statDf1D += (s1D - s1[dim]) * (s1D - s1[dim]); - } - statN += Ndim; - } - // cout << "std dev : " << sqrt(statDf1 / statN) << std::endl; - - if (draw) { - delete nt; - delete knots; - nt = new TNtuple("nt", "nt", "u:f:s"); - DataT drawMax = -1.e20; - DataT drawMin = 1.e20; - DataT stepX = 1.e-4; - for (double x = 0; x < TMath::Pi(); x += stepX) { - DataT f[Ndim], s[Ndim]; - F(x, f); - spline1.interpolate(x, s); - nt->Fill(spline1.convXtoU(x), f[0], s[0]); - drawMax = std::max(drawMax, std::max(f[0], s[0])); - drawMin = std::min(drawMin, std::min(f[0], s[0])); - } - - nt->SetMarkerStyle(8); - - { - TNtuple* ntRange = new TNtuple("ntRange", "nt", "u:f"); - drawMin -= 0.1 * (drawMax - drawMin); - - ntRange->Fill(0, drawMin); - ntRange->Fill(0, drawMax); - ntRange->Fill(uMax, drawMin); - ntRange->Fill(uMax, drawMax); - ntRange->SetMarkerColor(kWhite); - ntRange->SetMarkerSize(0.1); - ntRange->Draw("f:u", "", ""); - delete ntRange; - } - - nt->SetMarkerColor(kGray); - nt->SetMarkerSize(2.); - nt->Draw("f:u", "", "P,same"); - - nt->SetMarkerSize(.5); - nt->SetMarkerColor(kBlue); - nt->Draw("s:u", "", "P,same"); - - knots = new TNtuple("knots", "knots", "type:u:s"); - for (int i = 0; i < nKnots; i++) { - double u = spline1.getKnot(i).u; - DataT s[Ndim]; - spline1.interpolate(spline1.convUtoX(u), s); - knots->Fill(1, u, s[0]); - } - - knots->SetMarkerStyle(8); - knots->SetMarkerSize(1.5); - knots->SetMarkerColor(kRed); - knots->SetMarkerSize(1.5); - knots->Draw("s:u", "type==1", "same"); // knots - - if (drawDataPoints) { - for (int j = 0; j < helper.getNumberOfDataPoints(); j++) { - const typename SplineHelper1D<DataT>::DataPoint& p = helper.getDataPoint(j); - if (p.isKnot) { - continue; - } - DataT s[Ndim]; - spline1.interpolate(spline1.convUtoX(p.u), s); - knots->Fill(2, p.u, s[0]); - } - knots->SetMarkerColor(kBlack); - knots->SetMarkerSize(1.); - knots->Draw("s:u", "type==2", "same"); // data points - } - - if (!ask()) { - break; - } - } // draw - } - //delete canv; - //delete nt; - //delete knots; - - statDf1 = sqrt(statDf1 / statN); - statDf2 = sqrt(statDf2 / statN); - statDf1D = sqrt(statDf1D / statN); - - cout << "\n std dev for Compact Spline : " << statDf1 << " / " << statDf2 - << std::endl; - cout << " mean difference between 1-D and " << Ndim - << "-D splines : " << statDf1D << std::endl; - - if (statDf1 < 0.05 && statDf2 < 0.06 && statDf1D < 1.e-20) { - cout << "Everything is fine" << endl; - } else { - cout << "Something is wrong!!" << endl; - return -2; - } - return 0; -} - -#endif // GPUCA_ALIGPUCODE - template class GPUCA_NAMESPACE::gpu::Spline1D<float>; -template class GPUCA_NAMESPACE::gpu::Spline1D<double>; +template class GPUCA_NAMESPACE::gpu::Spline1D<double>; \ No newline at end of file diff --git a/GPU/TPCFastTransformation/Spline1D.h b/GPU/TPCFastTransformation/Spline1D.h index 57c53786f9f43..0f3b0ce9a9a0e 100644 --- a/GPU/TPCFastTransformation/Spline1D.h +++ b/GPU/TPCFastTransformation/Spline1D.h @@ -16,458 +16,162 @@ #ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE1D_H #define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE1D_H -#include "GPUCommonDef.h" -#include "FlatObject.h" -#if !defined(GPUCA_GPUCODE) -#include <functional> -#endif - -class TFile; +#include "Spline1DSpec.h" namespace GPUCA_NAMESPACE { namespace gpu { +/// The Spline1D class performs a cubic spline interpolation on a one-dimensional non-uniform grid. /// -/// The Spline1D class performs a cubic spline interpolation on an one-dimensional nonunifom grid. -/// -/// The class is a flat C structure. It inherits from the FlatObjects. +/// The class is a flat C structure. It inherits from the FlatObject. /// No virtual methods, no ROOT types are used. /// /// --- Interpolation --- /// -/// The spline approximates a function F:[xMin,xMax]->R^m +/// The spline S(x) approximates a function F(x):[Xmin,Xmax]->Y +/// X is one-dimensional, Y may be multi-dimensional. /// -/// The function parameter is called X, the function value is called F. F value may be multi-dimensional. -/// The spline value is called S(x). +/// The spline has n knots x_i. The spline value S(x_i) and its derivative S'(x_i) are stored for every knot. +/// Inbetween the knots, S(x) is evaluated via interpolation by 3-rd degree polynomials. /// -/// The interpolation is performed on N knots by 3-rd degree polynoms. -/// It uses spline values S_i and spline derivatives D_i==S'_i at the knots. -/// The polynoms and they first derivatives are always continuous at the knots. -/// Depending on the initialization of the derivatives D_i, the second derivative may or may not be continious. +/// The spline S(x) and its first derivative are continuous. +/// Depending on the initialization of the derivatives S'(x_i), +/// the second derivative may or may not be continuous at the knots. /// /// --- Knots --- /// -/// Knot positions are not completelly irregular. -/// There is an internal scaled coordinate, called U, where all N knots have integer positions: +/// The knots are not entirely irregular. +/// There is an internal scaled coordinate, called U, where all N knots have some integer positions: /// {U0==0, U1, .., Un-1==Umax}. /// It is implemented this way for fast matching of any X value to its neighboring knots. /// -/// For example, three knots with U coordinates U_i={0, 3, 5}, -/// being stretched on the X segment [0., 1.], will have X coordinates X_i={0., 3./5., 1.} +/// For example, three knots with U coordinates u_i={0, 3, 5}, +/// being stretched on the X segment [0., 1.], will have X coordinates x_i={0., 3./5., 1.} /// -/// For a few reasons, it is better to minimize gaps between knots. -/// A spline with knots {0,4,8} is the same as the spline with knots {0,1,2}, -/// but the later one uses less memory. +/// For a few reasons, it is better to keep U-gaps between the knots minimal. +/// A spline with knots u_i={0,1,2} is mathematically the same as the spline with knots u_i={0,2,4}. +/// However, it uses less memory. /// /// The minimal number of knots is 2. /// +/// --- Output dimensionality --- +/// +/// There are two ways to set the dimensionality of Y - either in the constructor or as a template argument: +/// +/// Spline1D<float> s( nYdimensions, nKnots ); +/// Spline1D<float, nYdimensions> s( nKnots ); +/// +/// The second implementation works faster. Use it when nYdimensions is known at the compile time. +/// +/// There is also a variation of the first specification which lets the compiler know +/// the maximal possible number of Y dimensions: +/// +/// Spline1D<float, -nYdimensionsMax> s( nYdimensions, nKnots ); +/// +/// This specification does not allocate any variable-size arrays and therefore compiles for the GPU. +/// /// ---- External storage of spline parameters for a given F --- /// /// One can store all F-dependent spline parameters outside of the spline object -/// and provide them at each call of the interpolation. -/// To do so, create a spline with Fdimentions=0, -/// create F parameters via SplineHelper1D class, and use interpolateU(..) method for interpoltion. +/// and provide them at each interpolation call. +/// To do so, create a spline with nYdimensions=0; create spline parameters for F via Spline1DHelper class; +/// then use special interpolateU(..) methods for the interpolation. /// -/// This feature allows one to use the same spline object for approximation of different functions +/// This feature allows one to use the same spline object for the approximation of different functions /// on the same grid of knots. /// /// ---- Creation of a spline ---- /// -/// The splines are best-fit splines. It means, that spline values S_i and derivatives D_i at knots -/// are calibrated such, that they minimize the integral difference between S(x) and F(x). -/// This integral difference is caluclated at all integer values of U coordinate (in particular, at all knots) -/// and at extra nAxiliaryPoints points between the integers. +/// The spline is supposed to be a best-fit spline, created by the approximateFunction() method. +/// +/// Best-fit means that the spline values S_i and its derivatives D_i at the knots +/// are adjusted to minimize the overall difference between S(x) and F(x). +/// The spline constructed this way is much more accurate than a classical interpolation spline. /// -/// nAxiliaryPoints can be set as a parameter of approximateFunction() method. -/// With nAxiliaryPoints==3 the approximation accuracy is noticeably better than with 1 or 2. +/// The difference to F() is minimized at all integer values of U coordinate (in particular, at all knots) +/// and at extra nAuxiliaryPoints points between the integer numbers. +/// +/// nAuxiliaryPoints is given as a parameter of approximateFunction() method. +/// With nAuxiliaryPoints==3, the approximation accuracy is noticeably better than the one with 1 or 2. /// Higher values usually give a little improvement over 3. /// -/// The value of nAxiliaryPoints has no influence on the interpolation speed, -/// it can only slow down the approximateFunction() method. +/// The number of auxiliary points does not influence the interpolation speed, +/// but a high number can slow down the spline's creation. /// -/// One can also create a spline in a classical way using corresponding method from SplineHelper1D. +/// It is also possible to construct the spline classically - by taking F(x) values only at knots and making +/// the first and the second derivatives of S(x) continuous. Use the corresponding method from Spline1DHelper. /// /// ---- Example of creating a spline ---- /// -/// auto F = [&](float x,float &f) { +/// auto F = [&](double x, double &f) { // a function to be approximated /// f[0] = x*x+3.f; // F(x) /// }; /// -/// const int nKnots=3; -/// int knots[nKnots] = {0, 1, 5}; -/// Spline1D<float> spline( nKnots, knots, 1 ); // prepare memory for 1-dimensional F +/// const int nKnots = 3; +/// +/// int knots[nKnots] = {0, 1, 5}; // relative(!) knot positions /// -/// spline.approximateFunction(0., 1., F); // initialize spline to approximate F on a segment [0., 1.] +/// Spline1D<float,1> spline( nKnots, knots ); // create 1-dimensional spline with the knots /// -/// float f = spline.interpolate(0.2); // interpolated value at x==0.2 +/// spline.approximateFunction(0., 1., F); // let the spline approximate F on a segment [0., 1.] +/// +/// float s = spline.interpolate(0.2); // interpolated value at x==0.2 /// /// --- See also Spline1D::test() method for examples /// + +/// ================================================================================================== +/// +/// Declare the Spline1D class as a template with one optional parameters. +/// +/// Class specializations depend on the XdimT, YdimT values. They can be found in SplineSpecs.h /// -template <typename DataT> -class Spline1D : public FlatObject +/// \param DataT data type: float or double +/// \param YdimT +/// YdimT > 0 : the number of Y dimensions is known at the compile time and is equal to XdimT +/// YdimT = 0 : the number of Y dimensions will be set in the runtime +/// YdimT < 0 : the number of Y dimensions will be set in the runtime, and it will not exceed abs(YdimT) +/// +template <typename DataT, int YdimT = 0> +class Spline1D + : public Spline1DSpec<DataT, YdimT, SplineUtil::getSpec(YdimT)> { - public: - /// - /// \brief The struct Knot represents a knot(i) and the interval [ knot(i), knot(i+1) ] - /// - struct Knot { - DataT u; ///< u coordinate of the knot i (an integer number in float format) - DataT Li; ///< inverse length of the [knot_i, knot_{i+1}] segment ( == 1.f/ a (small) integer number) - }; + typedef Spline1DContainer<DataT> TVeryBase; + typedef Spline1DSpec<DataT, YdimT, SplineUtil::getSpec(YdimT)> TBase; - /// _____________ Version control __________________________ - - /// Version number - GPUhd() static constexpr int getVersion() { return 1; } - - /// _____________ Constructors / destructors __________________________ + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + typedef typename TVeryBase::Knot Knot; #if !defined(GPUCA_GPUCODE) - /// Constructor for a regular spline. - Spline1D(int numberOfKnots = 2, int nFDimensions = 1); - - /// Constructor for an irregular spline. - Spline1D(int numberOfKnots, const int knots[], int nFDimensions); - - /// Copy constructor - Spline1D(const Spline1D&); + using TBase::TBase; // inherit constructors /// Assignment operator - Spline1D& operator=(const Spline1D&); + Spline1D& operator=(const Spline1D& v) + { + TVeryBase::cloneFromObject(v, nullptr); + return *this; + } #else /// Disable constructors for the GPU implementation Spline1D() CON_DELETE; Spline1D(const Spline1D&) CON_DELETE; - Spline1D& operator=(const Spline1D&) CON_DELETE; #endif - /// Destructor - ~Spline1D() CON_DEFAULT; - - /// _______________ Construction interface ________________________ - -#if !defined(GPUCA_GPUCODE) - /// Constructor for a regular spline. - void recreate(int numberOfKnots, int nFDimensions); - - /// Constructor for an irregular spline - void recreate(int numberOfKnots, const int knots[], int nFDimensions); -#endif - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) - /// approximate a function F with this spline. - void approximateFunction(DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[/*mFdimensions*/])> F, - int nAxiliaryDataPoints = 4); -#endif - - /// _______________ Main functionality ________________________ - - /// Get interpolated value for F(x) - GPUhd() void interpolate(DataT x, GPUgeneric() DataT Sx[/*mFdimensions*/]) const; - - /// Get interpolated value for the first dimension of F(x). (Simplified interface for 1D) - GPUhd() DataT interpolate(DataT x) const; - - /// _______________ IO ________________________ - #if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) - /// write a class object to the file - int writeToFile(TFile& outf, const char* name); - /// read a class object from the file - static Spline1D* readFromFile(TFile& inpf, const char* name); -#endif - - /// ================ Expert tools ================================ - - /// Get interpolated value {S(u): 1D -> nFdim} at the segment [knotL, next knotR] - /// using the spline values Sl, Sr and the slopes Dl, Dr - template <typename T> - GPUhd() static void interpolateU(int nFdim, const Knot& knotL, - GPUgeneric() const T Sl[/*nFdim*/], GPUgeneric() const T Dl[/*nFdim*/], - GPUgeneric() const T Sr[/*nFdim*/], GPUgeneric() const T Dr[/*nFdim*/], - DataT u, GPUgeneric() T Su[/*nFdim*/]); - - /// Get interpolated value for an nFdim-dimensional F(u) using spline parameters Fparameters. - /// Fparameters can be created via SplineHelper1D. A border check for u is performed. - GPUhd() void interpolateU(int nFdim, GPUgeneric() const DataT Fparameters[], - DataT u, GPUgeneric() DataT Su[/*nFdim*/]) const; - - /// Get interpolated value for an nFdim-dimensional F(u) using spline parameters Fparameters. - /// Fparameters can be created via SplineHelper1D. No border check for u is performed. - GPUhd() void interpolateUnonSafe(int nFdim, GPUgeneric() const DataT Fparameters[], - DataT u, GPUgeneric() DataT Su[/*nFdim*/]) const; - - /// _______________ Getters ________________________ - - /// Get U coordinate of the last knot - GPUhd() int getUmax() const { return mUmax; } - - /// Get minimal required alignment for the spline parameters - static size_t getParameterAlignmentBytes(int nFdim) - { - size_t s = 2 * sizeof(DataT) * nFdim; - return (s < 16) ? s : 16; - } - - /// Size of the parameter array in bytes - GPUhd() size_t getSizeOfParameters(int nFdim) const + static Spline1D* readFromFile(TFile& inpf, const char* name) { - return sizeof(DataT) * (size_t)getNumberOfParameters(nFdim); + return (Spline1D*)TVeryBase::readFromFile(inpf, name); } - - /// Number of parameters - GPUhd() int getNumberOfParameters(int nFdim) const - { - return (2 * nFdim) * mNumberOfKnots; - } - - /// Get number of knots - GPUhd() int getNumberOfKnots() const { return mNumberOfKnots; } - - /// Get the array of knots - GPUhd() const Spline1D::Knot* getKnots() const { return reinterpret_cast<const Spline1D::Knot*>(mFlatBufferPtr); } - - /// Get i-th knot - GPUhd() const Spline1D::Knot& getKnot(int i) const { return getKnots()[i < 0 ? 0 : (i >= mNumberOfKnots ? mNumberOfKnots - 1 : i)]; } - - /// Get index of an associated knot for a given U coordinate. Performs a border check. - GPUhd() int getKnotIndexU(DataT u) const; - - /// Get number of F dimensions - GPUhd() int getFdimensions() const { return mFdimensions; } - - /// Get number of F parameters - GPUhd() DataT* getFparameters() { return mFparameters; } - - /// Get number of F parameters - GPUhd() const DataT* getFparameters() const { return mFparameters; } - - /// _______________ Getters with no border check ________________________ - - /// Get i-th knot. No border check performed! - GPUhd() const Spline1D::Knot& getKnotNonSafe(int i) const { return getKnots()[i]; } - - /// Get index of an associated knot for a given U coordinate. No border check preformed! - GPUhd() int getKnotIndexUnonSafe(DataT u) const; - - /// _______________ Technical stuff ________________________ - - /// Get a map (integer U -> corresponding knot index) - GPUhd() const int* getUtoKnotMap() const { return mUtoKnotMap; } - - /// Convert X coordinate to U - GPUhd() DataT convXtoU(DataT x) const { return (x - mXmin) * mXtoUscale; } - - /// Convert U coordinate to X - GPUhd() DataT convUtoX(DataT u) const { return mXmin + u / mXtoUscale; } - - /// Get Xmin - GPUhd() DataT getXmin() const { return mXmin; } - - /// Get XtoUscale - GPUhd() DataT getXtoUscale() const { return mXtoUscale; } - - /// Set X range - void setXrange(DataT xMin, DataT xMax); - - /// Print method - void print() const; - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation - /// Test the class functionality - static int test(const bool draw = 0, const bool drawDataPoints = 1); #endif - /// _____________ FlatObject functionality, see FlatObject class for description ____________ - - /// Memory alignment - - using FlatObject::getBufferAlignmentBytes; - using FlatObject::getClassAlignmentBytes; - - /// Construction interface - -#if !defined(GPUCA_GPUCODE) - void cloneFromObject(const Spline1D& obj, char* newFlatBufferPtr); -#endif - void destroy(); - - /// Making the parameter buffer external - - using FlatObject::releaseInternalBuffer; - -#if !defined(GPUCA_GPUCODE) - void moveBufferTo(char* newBufferPtr); -#endif - - /// Moving the class with its external buffer to another location - - void setActualBufferAddress(char* actualFlatBufferPtr); - void setFutureBufferAddress(char* futureFlatBufferPtr); - - private: - /// Non-const accessor to knots array - Spline1D::Knot* getKnots() { return reinterpret_cast<Spline1D::Knot*>(mFlatBufferPtr); } - - /// Non-const accessor to U->knots map - int* getUtoKnotMap() { return mUtoKnotMap; } - - /// _____________ Data members ____________ - - int mNumberOfKnots; ///< n knots on the grid - int mUmax; ///< U of the last knot - DataT mXmin; ///< X of the first knot - DataT mXtoUscale; ///< a scaling factor to convert X to U - int mFdimensions; ///< number of F dimensions - int* mUtoKnotMap; //! (transient!!) pointer to (integer U -> knot index) map inside the mFlatBufferPtr array - DataT* mFparameters; //! (transient!!) F-dependent parameters of the spline #ifndef GPUCA_ALIROOT_LIB - ClassDefNV(Spline1D<DataT>, 1); + ClassDefNV(Spline1D, 0); #endif }; -/// -/// ======================================================================================================== -/// Inline implementations of some methods -/// ======================================================================================================== -/// - -#if !defined(GPUCA_GPUCODE) -template <typename DataT> -Spline1D<DataT>::Spline1D(int numberOfKnots, int nFdimensions) - : FlatObject() -{ - recreate(numberOfKnots, nFdimensions); -} - -template <typename DataT> -Spline1D<DataT>::Spline1D(int numberOfKnots, const int knots[], int nFdimensions) - : FlatObject() -{ - recreate(numberOfKnots, knots, nFdimensions); -} - -template <typename DataT> -Spline1D<DataT>::Spline1D(const Spline1D& spline) - : FlatObject() -{ - cloneFromObject(spline, nullptr); -} - -template <typename DataT> -Spline1D<DataT>& Spline1D<DataT>::operator=(const Spline1D& spline) -{ - cloneFromObject(spline, nullptr); - return *this; -} -#endif - -template <typename DataT> -GPUhd() void Spline1D<DataT>::interpolate(DataT x, GPUgeneric() DataT Sx[/*mFdimensions*/]) const -{ - /// Get interpolated value for F(x) - interpolateU(mFdimensions, mFparameters, convXtoU(x), Sx); -} - -template <typename DataT> -GPUhd() DataT Spline1D<DataT>::interpolate(DataT x) const -{ - /// Simplified interface for 1D: get interpolated value for the first dimension of F(x) - DataT u = convXtoU(x); - int iknot = getKnotIndexU(u); - const DataT* d = mFparameters + (2 * iknot) * mFdimensions; - DataT S = 0.; - interpolateU(1, getKnotNonSafe(iknot), &(d[0]), &(d[mFdimensions]), - &(d[2 * mFdimensions]), &(d[3 * mFdimensions]), u, &S); - return S; -} - -template <typename DataT> -template <typename T> -GPUhd() void Spline1D<DataT>::interpolateU(int nFdim, const Spline1D<DataT>::Knot& knotL, - GPUgeneric() const T Sl[/*nFdim*/], GPUgeneric() const T Dl[/*nFdim*/], - GPUgeneric() const T Sr[/*nFdim*/], GPUgeneric() const T Dr[/*nFdim*/], - DataT u, GPUgeneric() T Su[/*nFdim*/]) -{ - /// A static method. - /// Gives interpolated value of N-dimensional S(u) at u - /// input: Sl,Dl,Sr,Dr[nFdim] - N-dim function values and slopes at knots {knotL,knotR} - /// output: Su[nFdim] - N-dim interpolated value for S(u) - - T uu = T(u - knotL.u); - T li = T(knotL.Li); - T v = uu * li; // scaled u - for (int dim = 0; dim < nFdim; ++dim) { - T df = (Sr[dim] - Sl[dim]) * li; - T a = Dl[dim] + Dr[dim] - df - df; - T b = df - Dl[dim] - a; - Su[dim] = ((a * v + b) * v + Dl[dim]) * uu + Sl[dim]; - } - - /* another way to calculate f(u): - T uu = T(u - knotL.u); - T v = uu * T(knotL.Li); // scaled u - T vm1 = v-1; - T v2 = v * v; - float cSr = v2*(3-2*v); - float cSl = 1-cSr; - float cDl = v*vm1*vm1*knotL.L; - float cDr = v2*vm1*knotL.L; - return cSl*Sl + cSr*Sr + cDl*Dl + cDr*Dr; - */ -} - -template <typename DataT> -GPUhdi() void Spline1D<DataT>::interpolateU(int nFdim, GPUgeneric() const DataT parameters[], DataT u, GPUgeneric() DataT Su[/*nFdim*/]) const -{ - /// Get interpolated value for F(u) using given spline parameters with a border check - int iknot = getKnotIndexU(u); - const DataT* d = parameters + (2 * iknot) * nFdim; - interpolateU(nFdim, getKnotNonSafe(iknot), &(d[0]), &(d[nFdim]), &(d[2 * nFdim]), &(d[3 * nFdim]), u, Su); -} - -template <typename DataT> -GPUhdi() void Spline1D<DataT>::interpolateUnonSafe(int nFdim, GPUgeneric() const DataT parameters[], DataT u, GPUgeneric() DataT Su[/*nFdim*/]) const -{ - /// Get interpolated value for F(u) using given spline parameters without border check - int iknot = getKnotIndexUnonSafe(u); - const DataT* d = parameters + (2 * iknot) * nFdim; - interpolateU(nFdim, getKnotNonSafe(iknot), &(d[0]), &(d[nFdim]), &(d[2 * nFdim]), &(d[3 * nFdim]), u, Su); -} - -template <typename DataT> -GPUhdi() int Spline1D<DataT>::getKnotIndexU(DataT u) const -{ - /// Get i: u is in [knot_i, knot_{i+1}) interval - /// when u is otside of [0, mUmax], return the edge intervals - int iu = (int)u; - if (iu < 0) { - iu = 0; - } - if (iu > mUmax) { - iu = mUmax; - } - return getUtoKnotMap()[iu]; -} - -template <typename DataT> -GPUhdi() int Spline1D<DataT>::getKnotIndexUnonSafe(DataT u) const -{ - /// Get i: u is in [knot_i, knot_{i+1}) interval - /// no border check! u must be in [0,mUmax] - return getUtoKnotMap()[(int)u]; -} - -template <typename DataT> -void Spline1D<DataT>::setXrange(DataT xMin, DataT xMax) -{ - mXmin = xMin; - mXtoUscale = mUmax / (((double)xMax) - xMin); -} - } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/TPCFastTransformation/Spline1DHelper.cxx b/GPU/TPCFastTransformation/Spline1DHelper.cxx new file mode 100644 index 0000000000000..1ffe26fbf006a --- /dev/null +++ b/GPU/TPCFastTransformation/Spline1DHelper.cxx @@ -0,0 +1,742 @@ +// 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 Spline1DHelper.cxx +/// \brief Implementation of Spline1DHelper class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + +#include "Spline1DHelper.h" +#include "TMath.h" +#include "TMatrixD.h" +#include "TVectorD.h" +#include "TDecompBK.h" +#include <vector> + +#include "TRandom.h" +#include "TMath.h" +#include "TCanvas.h" +#include "TNtuple.h" +#include "TFile.h" +#include "GPUCommonMath.h" +#include <iostream> + +templateClassImp(GPUCA_NAMESPACE::gpu::Spline1DHelper); + +using namespace GPUCA_NAMESPACE::gpu; + +template <typename DataT> +Spline1DHelper<DataT>::Spline1DHelper() : mError(), mSpline(), mFdimensions(0) +{ +} + +template <typename DataT> +int Spline1DHelper<DataT>::storeError(int code, const char* msg) +{ + mError = msg; + return code; +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateFunctionClassic(Spline1DContainer<DataT>& spline, + double xMin, double xMax, std::function<void(double x, double f[/*spline.getFdimensions()*/])> F) +{ + /// Create classic spline parameters for a given input function F + /// set slopes at the knots such, that the second derivative of the spline is continious. + + int Ndim = spline.getYdimensions(); + const int nKnots = spline.getNumberOfKnots(); + + TMatrixD A(nKnots, nKnots); + + A.Zero(); + + /* + const Spline1D::Knot& knot0 = spline.getKnot(i); + double x = (u - knot0.u) * knot0.Li; // scaled u + double cS1 = (6 - 12*x)*knot0.Li*knot0.Li; + double cZ0 = (6*x-4)*knot0.Li; + double cZ1 = (6*x-2)*knot0.Li; + // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; + */ + + // second derivative at knot0 is 0 + { + const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(0); + double cZ0 = (-4) * knot0.Li; + double cZ1 = (-2) * knot0.Li; + // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; + A(0, 0) = cZ0; + A(0, 1) = cZ1; + } + + // second derivative at knot nKnots-1 is 0 + { + const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(nKnots - 2); + double cZ0 = (6 - 4) * knot0.Li; + double cZ1 = (6 - 2) * knot0.Li; + // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; + A(nKnots - 1, nKnots - 2) = cZ0; + A(nKnots - 1, nKnots - 1) = cZ1; + } + + // second derivative at other knots is same from the left and from the right + for (int i = 1; i < nKnots - 1; i++) { + const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(i - 1); + double cZ0 = (6 - 4) * knot0.Li; + double cZ1_0 = (6 - 2) * knot0.Li; + // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; + + const typename Spline1D<DataT>::Knot& knot1 = spline.getKnot(i); + double cZ1_1 = (-4) * knot1.Li; + double cZ2 = (-2) * knot1.Li; + // f''(u) = cS2*(f2-f1) + cZ1_1*z1 + cZ2*z2; + A(i, i - 1) = cZ0; + A(i, i) = cZ1_0 - cZ1_1; + A(i, i + 1) = -cZ2; + } + + A.Invert(); + + spline.setXrange(xMin, xMax); + DataT* parameters = spline.getParameters(); + + TVectorD b(nKnots); + b.Zero(); + + double uToXscale = (((double)xMax) - xMin) / spline.getUmax(); + + for (int i = 0; i < nKnots; ++i) { + const typename Spline1D<DataT>::Knot& knot = spline.getKnot(i); + double u = knot.u; + double f[Ndim]; + F(xMin + u * uToXscale, f); + for (int dim = 0; dim < Ndim; dim++) { + parameters[(2 * i) * Ndim + dim] = f[dim]; + } + } + + for (int dim = 0; dim < Ndim; dim++) { + + // second derivative at knot0 is 0 + { + double f0 = parameters[(2 * 0) * Ndim + dim]; + double f1 = parameters[(2 * 1) * Ndim + dim]; + const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(0); + double cS1 = (6) * knot0.Li * knot0.Li; + // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; + b(0) = -cS1 * (f1 - f0); + } + + // second derivative at knot nKnots-1 is 0 + { + double f0 = parameters[2 * (nKnots - 2) * Ndim + dim]; + double f1 = parameters[2 * (nKnots - 1) * Ndim + dim]; + const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(nKnots - 2); + double cS1 = (6 - 12) * knot0.Li * knot0.Li; + // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; + b(nKnots - 1) = -cS1 * (f1 - f0); + } + + // second derivative at other knots is same from the left and from the right + for (int i = 1; i < nKnots - 1; i++) { + double f0 = parameters[2 * (i - 1) * Ndim + dim]; + double f1 = parameters[2 * (i)*Ndim + dim]; + double f2 = parameters[2 * (i + 1) * Ndim + dim]; + const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(i - 1); + double cS1 = (6 - 12) * knot0.Li * knot0.Li; + // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; + + const typename Spline1D<DataT>::Knot& knot1 = spline.getKnot(i); + double cS2 = (6) * knot1.Li * knot1.Li; + // f''(u) = cS2*(f2-f1) + cZ1_1*z1 + cZ2*z2; + b(i) = -cS1 * (f1 - f0) + cS2 * (f2 - f1); + } + + TVectorD c = A * b; + for (int i = 0; i < nKnots; i++) { + parameters[(2 * i + 1) * Ndim + dim] = c[i]; + } + } +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateFunction( + Spline1DContainer<DataT>& spline, double xMin, double xMax, std::function<void(double x, double f[/*spline.getFdimensions()*/])> F, + int nAuxiliaryDataPoints) +{ + /// Create best-fit spline parameters for a given input function F + setSpline(spline, spline.getYdimensions(), nAuxiliaryDataPoints); + approximateFunction(spline.getParameters(), xMin, xMax, F); + spline.setXrange(xMin, xMax); +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateFunctionGradually( + Spline1DContainer<DataT>& spline, double xMin, double xMax, std::function<void(double x, double f[/*spline.getFdimensions()*/])> F, + int nAuxiliaryDataPoints) +{ + /// Create best-fit spline parameters gradually for a given input function F + setSpline(spline, spline.getYdimensions(), nAuxiliaryDataPoints); + approximateFunctionGradually(spline.getParameters(), xMin, xMax, F); + spline.setXrange(xMin, xMax); +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateFunction( + DataT* Sparameters, double xMin, double xMax, std::function<void(double x, double f[])> F) const +{ + /// Create best-fit spline parameters for a given input function F + /// output in Sparameters + std::vector<double> vF(getNumberOfDataPoints() * mFdimensions); + double mUtoXscale = (((double)xMax) - xMin) / mSpline.getUmax(); + for (int i = 0; i < getNumberOfDataPoints(); i++) { + F(xMin + mUtoXscale * mDataPoints[i].u, &vF[i * mFdimensions]); + } + approximateFunction(Sparameters, vF.data()); +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateFunctionGradually( + DataT* Sparameters, double xMin, double xMax, std::function<void(double x, double f[])> F) const +{ + /// Create best-fit spline parameters gradually for a given input function F + /// output in Sparameters + std::vector<double> vF(getNumberOfDataPoints() * mFdimensions); + double mUtoXscale = (((double)xMax) - xMin) / mSpline.getUmax(); + for (int i = 0; i < getNumberOfDataPoints(); i++) { + F(xMin + mUtoXscale * mDataPoints[i].u, &vF[i * mFdimensions]); + } + approximateFunctionGradually(Sparameters, vF.data()); +} + +template <typename DataT> +int Spline1DHelper<DataT>::setSpline( + const Spline1DContainer<DataT>& spline, int nFdimensions, int nAuxiliaryDataPoints) +{ + // Prepare creation of a best-fit spline + // + // Data points will be set at all integer U (that includes all knots), + // plus at nAuxiliaryDataPoints points between the integers. + // + // nAuxiliaryDataPoints must be >= 2 + // + // nAuxiliaryDataPoints==1 is also possible, but there must be at least + // one integer U without a knot, in order to get 2*nKnots data points in total. + // + // The return value is an error index, 0 means no error + + int ret = 0; + + mFdimensions = nFdimensions; + int nPoints = 0; + if (!spline.isConstructed()) { + ret = storeError(-1, "Spline1DHelper<DataT>::setSpline: input spline is not constructed"); + mSpline.recreate(0, 2); + nAuxiliaryDataPoints = 2; + nPoints = 4; + } else { + std::vector<int> knots; + for (int i = 0; i < spline.getNumberOfKnots(); i++) { + knots.push_back(spline.getKnot(i).getU()); + } + mSpline.recreate(0, spline.getNumberOfKnots(), knots.data()); + + nPoints = 1 + mSpline.getUmax() + mSpline.getUmax() * nAuxiliaryDataPoints; + if (nPoints < 2 * mSpline.getNumberOfKnots()) { + nAuxiliaryDataPoints = 2; + nPoints = 1 + mSpline.getUmax() + mSpline.getUmax() * nAuxiliaryDataPoints; + ret = storeError(-3, "Spline1DHelper::setSpline: too few nAuxiliaryDataPoints, increase to 2"); + } + } + + const int nPar = 2 * mSpline.getNumberOfKnots(); // n parameters for 1D + + mDataPoints.resize(nPoints); + double scalePoints2Knots = ((double)mSpline.getUmax()) / (nPoints - 1.); + + for (int i = 0; i < nPoints; ++i) { + DataPoint& p = mDataPoints[i]; + double u = i * scalePoints2Knots; + int iKnot = mSpline.getLeftKnotIndexForU(u); + const typename Spline1D<double>::Knot& knot0 = mSpline.getKnot(iKnot); + const typename Spline1D<double>::Knot& knot1 = mSpline.getKnot(iKnot + 1); + double l = knot1.u - knot0.u; + double s = (u - knot0.u) * knot0.Li; // scaled u + double s2 = s * s; + double sm1 = s - 1.; + + p.iKnot = iKnot; + p.isKnot = 0; + p.u = u; + p.cS1 = s2 * (3. - 2. * s); + p.cS0 = 1. - p.cS1; + p.cZ0 = s * sm1 * sm1 * l; + p.cZ1 = s2 * sm1 * l; + } + + const int nKnots = mSpline.getNumberOfKnots(); + + mKnotDataPoints.resize(nKnots); + + for (int i = 0; i < nKnots; ++i) { + const typename Spline1D<double>::Knot& knot = mSpline.getKnot(i); + int iu = (int)(knot.u + 0.1f); + mKnotDataPoints[i] = iu * (1 + nAuxiliaryDataPoints); + mDataPoints[mKnotDataPoints[i]].isKnot = 1; + } + + TMatrixDSym A(nPar); + A.Zero(); + + for (int i = 0; i < nPoints; ++i) { + DataPoint& p = mDataPoints[i]; + int j = p.iKnot * 2; + A(j + 0, j + 0) += p.cS0 * p.cS0; + A(j + 1, j + 0) += p.cS0 * p.cZ0; + A(j + 2, j + 0) += p.cS0 * p.cS1; + A(j + 3, j + 0) += p.cS0 * p.cZ1; + + A(j + 1, j + 1) += p.cZ0 * p.cZ0; + A(j + 2, j + 1) += p.cZ0 * p.cS1; + A(j + 3, j + 1) += p.cZ0 * p.cZ1; + + A(j + 2, j + 2) += p.cS1 * p.cS1; + A(j + 3, j + 2) += p.cS1 * p.cZ1; + + A(j + 3, j + 3) += p.cZ1 * p.cZ1; + } + + // copy symmetric matrix elements + + for (int i = 0; i < nPar; i++) { + for (int j = i + 1; j < nPar; j++) { + A(i, j) = A(j, i); + } + } + + TMatrixDSym Z(nKnots); + mLSMmatrixSvalues.resize(nKnots * nKnots); + for (int i = 0, k = 0; i < nKnots; i++) { + for (int j = 0; j < nKnots; j++, k++) { + mLSMmatrixSvalues[k] = A(i * 2 + 1, j * 2); + Z(i, j) = A(i * 2 + 1, j * 2 + 1); + } + } + + { + TDecompBK bk(A, 0); + bool ok = bk.Invert(A); + + if (!ok) { + ret = storeError(-4, "Spline1DHelper::setSpline: internal error - can not invert the matrix"); + A.Zero(); + } + mLSMmatrixFull.resize(nPar * nPar); + for (int i = 0, k = 0; i < nPar; i++) { + for (int j = 0; j < nPar; j++, k++) { + mLSMmatrixFull[k] = A(i, j); + } + } + } + + { + TDecompBK bk(Z, 0); + if (!bk.Invert(Z)) { + ret = storeError(-5, "Spline1DHelper::setSpline: internal error - can not invert the matrix"); + Z.Zero(); + } + mLSMmatrixSderivatives.resize(nKnots * nKnots); + for (int i = 0, k = 0; i < nKnots; i++) { + for (int j = 0; j < nKnots; j++, k++) { + mLSMmatrixSderivatives[k] = Z(i, j); + } + } + } + + return ret; +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateFunction( + DataT* Sparameters, + const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const +{ + /// Approximate a function given as an array of values at data points + + const int nPar = 2 * mSpline.getNumberOfKnots(); + double b[nPar]; + for (int idim = 0; idim < mFdimensions; idim++) { + for (int i = 0; i < nPar; i++) { + b[i] = 0.; + } + for (int i = 0; i < getNumberOfDataPoints(); ++i) { + const DataPoint& p = mDataPoints[i]; + double* bb = &(b[p.iKnot * 2]); + double f = (double)DataPointF[i * mFdimensions + idim]; + bb[0] += f * p.cS0; + bb[1] += f * p.cZ0; + bb[2] += f * p.cS1; + bb[3] += f * p.cZ1; + } + + const double* row = mLSMmatrixFull.data(); + + for (int i = 0; i < nPar; i++, row += nPar) { + double s = 0.; + for (int j = 0; j < nPar; j++) { + s += row[j] * b[j]; + } + Sparameters[i * mFdimensions + idim] = (float)s; + } + } +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateFunctionGradually( + DataT* Sparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim */]) const +{ + /// gradually approximate a function given as an array of values at data points + /// output in Sparameters + copySfromDataPoints(Sparameters, DataPointF); + approximateDerivatives(Sparameters, DataPointF); +} + +template <typename DataT> +void Spline1DHelper<DataT>::copySfromDataPoints( + DataT* Sparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const +{ + /// a tool for the gradual approximation: set spline values S_i at knots == function values + /// output in Sparameters + for (int i = 0; i < mSpline.getNumberOfKnots(); ++i) { // set F values at knots + int ip = mKnotDataPoints[i]; + for (int d = 0; d < mFdimensions; d++) { + Sparameters[2 * i * mFdimensions + d] = DataPointF[ip * mFdimensions + d]; + } + } +} + +template <typename DataT> +void Spline1DHelper<DataT>::approximateDerivatives( + DataT* Sparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const +{ + /// a tool for the gradual approximation: + /// calibrate spline derivatives D_i using already calibrated spline values S_i + /// input and output output in Sparameters + + const int nKnots = mSpline.getNumberOfKnots(); + const int Ndim = mFdimensions; + double b[nKnots * mFdimensions]; + for (int i = 0; i < nKnots * Ndim; i++) { + b[i] = 0.; + } + + for (int i = 0; i < getNumberOfDataPoints(); ++i) { + const DataPoint& p = mDataPoints[i]; + if (p.isKnot) { + continue; + } + for (int d = 0; d < Ndim; d++) { + double f = (double)DataPointF[i * Ndim + d]; + b[(p.iKnot + 0) * Ndim + d] += f * p.cZ0; + b[(p.iKnot + 1) * Ndim + d] += f * p.cZ1; + } + } + + const double* row = mLSMmatrixSvalues.data(); + for (int i = 0; i < nKnots; ++i, row += nKnots) { + double s[Ndim]; + for (int d = 0; d < Ndim; d++) { + s[d] = 0.; + } + for (int j = 0; j < nKnots; ++j) { + for (int d = 0; d < Ndim; d++) { + s[d] += row[j] * Sparameters[2 * j * Ndim + d]; + } + } + for (int d = 0; d < Ndim; d++) { + b[i * Ndim + d] -= s[d]; + } + } + + row = mLSMmatrixSderivatives.data(); + for (int i = 0; i < nKnots; ++i, row += nKnots) { + double s[Ndim]; + for (int d = 0; d < Ndim; d++) { + s[d] = 0.; + } + for (int j = 0; j < nKnots; ++j) { + for (int d = 0; d < Ndim; d++) { + s[d] += row[j] * b[j * Ndim + d]; + } + } + for (int d = 0; d < Ndim; d++) { + Sparameters[(2 * i + 1) * Ndim + d] = (float)s[d]; + } + } +} + +template <typename DataT> +int Spline1DHelper<DataT>::test(const bool draw, const bool drawDataPoints) +{ + using namespace std; + + // input function F + + const int Ndim = 5; + const int Fdegree = 4; + double Fcoeff[Ndim][2 * (Fdegree + 1)]; + + auto F = [&](double x, double f[]) -> void { + double cosx[Fdegree + 1], sinx[Fdegree + 1]; + double xi = 0; + for (int i = 0; i <= Fdegree; i++, xi += x) { + GPUCommonMath::SinCos(xi, sinx[i], cosx[i]); + } + for (int dim = 0; dim < Ndim; dim++) { + f[dim] = 0; // Fcoeff[0]/2; + for (int i = 1; i <= Fdegree; i++) { + f[dim] += Fcoeff[dim][2 * i] * cosx[i] + Fcoeff[dim][2 * i + 1] * sinx[i]; + } + } + }; + + TCanvas* canv = nullptr; + TNtuple* nt = nullptr; + TNtuple* knots = nullptr; + + auto ask = [&]() -> bool { + if (!canv) { + return 0; + } + canv->Update(); + cout << "type 'q ' to exit" << endl; + std::string str; + std::getline(std::cin, str); + return (str != "q" && str != ".q"); + }; + + std::cout << "Test 1D interpolation with the compact spline" << std::endl; + + int nTries = 100; + + if (draw) { + canv = new TCanvas("cQA", "Spline1D QA", 1000, 600); + nTries = 10000; + } + + double statDf1 = 0; + double statDf2 = 0; + double statDf1D = 0; + double statN = 0; + + int seed = 1; + + for (int itry = 0; itry < nTries; itry++) { + + // init random F + for (int dim = 0; dim < Ndim; dim++) { + gRandom->SetSeed(seed++); + for (int i = 0; i < 2 * (Fdegree + 1); i++) { + Fcoeff[dim][i] = gRandom->Uniform(-1, 1); + } + } + + // spline + + int nKnots = 4; + const int uMax = nKnots * 3; + + Spline1D<DataT, Ndim> spline1; + int knotsU[nKnots]; + + do { // set knots randomly + knotsU[0] = 0; + double du = 1. * uMax / (nKnots - 1); + for (int i = 1; i < nKnots; i++) { + knotsU[i] = (int)(i * du); // + gRandom->Uniform(-du / 3, du / 3); + } + knotsU[nKnots - 1] = uMax; + spline1.recreate(nKnots, knotsU); + if (nKnots != spline1.getNumberOfKnots()) { + cout << "warning: n knots changed during the initialisation " << nKnots + << " -> " << spline1.getNumberOfKnots() << std::endl; + continue; + } + } while (0); + + std::string err = FlatObject::stressTest(spline1); + if (!err.empty()) { + cout << "error at FlatObject functionality: " << err << endl; + return -1; + } else { + // cout << "flat object functionality is ok" << endl; + } + + nKnots = spline1.getNumberOfKnots(); + int nAuxiliaryPoints = 1; + Spline1D<DataT, Ndim> spline2(spline1); + spline1.approximateFunction(0., TMath::Pi(), F, nAuxiliaryPoints); + //if (itry == 0) + { + TFile outf("testSpline1D.root", "recreate"); + if (outf.IsZombie()) { + cout << "Failed to open output file testSpline1D.root " << std::endl; + } else { + const char* name = "Spline1Dtest"; + spline1.writeToFile(outf, name); + Spline1D<DataT, Ndim>* p = spline1.readFromFile(outf, name); + if (p == nullptr) { + cout << "Failed to read Spline1D from file testSpline1D.root " << std::endl; + } else { + spline1 = *p; + } + outf.Close(); + } + } + + Spline1DHelper<DataT> helper; + helper.setSpline(spline2, Ndim, nAuxiliaryPoints); + helper.approximateFunctionGradually(spline2, 0., TMath::Pi(), F, nAuxiliaryPoints); + + // 1-D splines for each dimension + Spline1D<DataT, 1> splines3[Ndim]; + { + for (int dim = 0; dim < Ndim; dim++) { + auto F3 = [&](double u, double f[]) -> void { + double ff[Ndim]; + F(u, ff); + f[0] = ff[dim]; + }; + splines3[dim].recreate(nKnots, knotsU); + splines3[dim].approximateFunction(0., TMath::Pi(), F3, nAuxiliaryPoints); + } + } + + double stepX = 1.e-2; + for (double x = 0; x < TMath::Pi(); x += stepX) { + double f[Ndim]; + DataT s1[Ndim], s2[Ndim]; + F(x, f); + spline1.interpolate(x, s1); + spline2.interpolate(x, s2); + for (int dim = 0; dim < Ndim; dim++) { + statDf1 += (s1[dim] - f[dim]) * (s1[dim] - f[dim]); + statDf2 += (s2[dim] - f[dim]) * (s2[dim] - f[dim]); + DataT s1D = splines3[dim].interpolate(x); + statDf1D += (s1D - s1[dim]) * (s1D - s1[dim]); + } + statN += Ndim; + } + // cout << "std dev : " << sqrt(statDf1 / statN) << std::endl; + + if (draw) { + delete nt; + delete knots; + nt = new TNtuple("nt", "nt", "u:f:s"); + double drawMax = -1.e20; + double drawMin = 1.e20; + double stepX = 1.e-4; + for (double x = 0; x < TMath::Pi(); x += stepX) { + double f[Ndim]; + DataT s[Ndim]; + F(x, f); + spline1.interpolate(x, s); + nt->Fill(spline1.convXtoU(x), f[0], s[0]); + drawMax = std::max(drawMax, std::max(f[0], (double)s[0])); + drawMin = std::min(drawMin, std::min(f[0], (double)s[0])); + } + + nt->SetMarkerStyle(8); + + { + TNtuple* ntRange = new TNtuple("ntRange", "nt", "u:f"); + drawMin -= 0.1 * (drawMax - drawMin); + + ntRange->Fill(0, drawMin); + ntRange->Fill(0, drawMax); + ntRange->Fill(uMax, drawMin); + ntRange->Fill(uMax, drawMax); + ntRange->SetMarkerColor(kWhite); + ntRange->SetMarkerSize(0.1); + ntRange->Draw("f:u", "", ""); + delete ntRange; + } + + nt->SetMarkerColor(kGray); + nt->SetMarkerSize(2.); + nt->Draw("f:u", "", "P,same"); + + nt->SetMarkerSize(.5); + nt->SetMarkerColor(kBlue); + nt->Draw("s:u", "", "P,same"); + + knots = new TNtuple("knots", "knots", "type:u:s"); + for (int i = 0; i < nKnots; i++) { + double u = spline1.getKnot(i).u; + DataT s[Ndim]; + spline1.interpolate(spline1.convUtoX(u), s); + knots->Fill(1, u, s[0]); + } + + knots->SetMarkerStyle(8); + knots->SetMarkerSize(1.5); + knots->SetMarkerColor(kRed); + knots->SetMarkerSize(1.5); + knots->Draw("s:u", "type==1", "same"); // knots + + if (drawDataPoints) { + for (int j = 0; j < helper.getNumberOfDataPoints(); j++) { + const typename Spline1DHelper<DataT>::DataPoint& p = helper.getDataPoint(j); + if (p.isKnot) { + continue; + } + DataT s[Ndim]; + spline1.interpolate(spline1.convUtoX(p.u), s); + knots->Fill(2, p.u, s[0]); + } + knots->SetMarkerColor(kBlack); + knots->SetMarkerSize(1.); + knots->Draw("s:u", "type==2", "same"); // data points + } + + if (!ask()) { + break; + } + } // draw + } + //delete canv; + //delete nt; + //delete knots; + + statDf1 = sqrt(statDf1 / statN); + statDf2 = sqrt(statDf2 / statN); + statDf1D = sqrt(statDf1D / statN); + + cout << "\n std dev for Compact Spline : " << statDf1 << " / " << statDf2 + << std::endl; + cout << " mean difference between 1-D and " << Ndim + << "-D splines : " << statDf1D << std::endl; + + if (statDf1 < 0.05 && statDf2 < 0.06 && statDf1D < 1.e-20) { + cout << "Everything is fine" << endl; + } else { + cout << "Something is wrong!!" << endl; + return -2; + } + return 0; +} + +template class GPUCA_NAMESPACE::gpu::Spline1DHelper<float>; +template class GPUCA_NAMESPACE::gpu::Spline1DHelper<double>; + +#endif diff --git a/GPU/TPCFastTransformation/SplineHelper1D.h b/GPU/TPCFastTransformation/Spline1DHelper.h similarity index 58% rename from GPU/TPCFastTransformation/SplineHelper1D.h rename to GPU/TPCFastTransformation/Spline1DHelper.h index e6ed084fdc5a1..cb83c13e446d2 100644 --- a/GPU/TPCFastTransformation/SplineHelper1D.h +++ b/GPU/TPCFastTransformation/Spline1DHelper.h @@ -8,13 +8,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file SplineHelper1D.h -/// \brief Definition of SplineHelper1D class +/// \file Spline1DHelper.h +/// \brief Definition of Spline1DHelper class /// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> -#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEHELPER1D_H -#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEHELPER1D_H +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_Spline1DHelper_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_Spline1DHelper_H #include <cmath> #include <vector> @@ -30,10 +30,10 @@ namespace GPUCA_NAMESPACE namespace gpu { /// -/// The SplineHelper1D class is to initialize parameters for Spline1D class +/// The Spline1DHelper class is to initialize parameters for Spline1D class /// template <typename DataT> -class SplineHelper1D +class Spline1DHelper { public: /// @@ -52,63 +52,63 @@ class SplineHelper1D /// _____________ Constructors / destructors __________________________ /// Default constructor - SplineHelper1D(); + Spline1DHelper(); /// Copy constructor: disabled - SplineHelper1D(const SplineHelper1D&) CON_DEFAULT; + Spline1DHelper(const Spline1DHelper&) CON_DEFAULT; /// Assignment operator: disabled - SplineHelper1D& operator=(const SplineHelper1D&) CON_DEFAULT; + Spline1DHelper& operator=(const Spline1DHelper&) CON_DEFAULT; /// Destructor - ~SplineHelper1D() CON_DEFAULT; + ~Spline1DHelper() CON_DEFAULT; /// _______________ Main functionality ________________________ /// Create best-fit spline parameters for a given input function F - void approximateFunction(Spline1D<DataT>& spline, - DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[/*spline.getFdimensions()*/])> F, - int nAxiliaryDataPoints = 4); + void approximateFunction(Spline1DContainer<DataT>& spline, + double xMin, double xMax, std::function<void(double x, double f[/*spline.getFdimensions()*/])> F, + int nAuxiliaryDataPoints = 4); /// Create best-fit spline parameters gradually for a given input function F - void approximateFunctionGradually(Spline1D<DataT>& spline, - DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[/*spline.getFdimensions()*/])> F, - int nAxiliaryDataPoints = 4); + void approximateFunctionGradually(Spline1DContainer<DataT>& spline, + double xMin, double xMax, std::function<void(double x, double f[/*spline.getFdimensions()*/])> F, + int nAuxiliaryDataPoints = 4); /// Create classic spline parameters for a given input function F - void approximateFunctionClassic(Spline1D<DataT>& spline, - DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[/*spline.getFdimensions()*/])> F); + void approximateFunctionClassic(Spline1DContainer<DataT>& spline, + double xMin, double xMax, std::function<void(double x, double f[/*spline.getFdimensions()*/])> F); /// _______________ Interface for a step-wise construction of the best-fit spline ________________________ /// precompute everything needed for the construction - int setSpline(const Spline1D<DataT>& spline, int nFdimensions, int nAxiliaryDataPoints); + int setSpline(const Spline1DContainer<DataT>& spline, int nFdimensions, int nAuxiliaryDataPoints); /// approximate std::function, output in Fparameters - void approximateFunction(DataT* Fparameters, DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[])> F) const; + void approximateFunction(DataT* Fparameters, double xMin, double xMax, std::function<void(double x, double f[])> F) const; /// approximate std::function gradually, output in Fparameters - void approximateFunctionGradually(DataT* Fparameters, DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[])> F) const; + void approximateFunctionGradually(DataT* Fparameters, double xMin, double xMax, std::function<void(double x, double f[])> F) const; /// number of data points int getNumberOfDataPoints() const { return mDataPoints.size(); } /// approximate a function given as an array of values at data points - void approximateFunction(DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; + void approximateFunction(DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; /// gradually approximate a function given as an array of values at data points - void approximateFunctionGradually(DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim */]) const; + void approximateFunctionGradually(DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim */]) const; /// a tool for the gradual approximation: set spline values S_i at knots == function values - void copySfromDataPoints(DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; + void copySfromDataPoints(DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; /// a tool for the gradual approximation: /// calibrate spline derivatives D_i using already calibrated spline values S_i - void approximateDerivatives(DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; + void approximateDerivatives(DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; /// _______________ Utilities ________________________ - const Spline1D<DataT>& getSpline() const { return mSpline; } + const Spline1D<double>& getSpline() const { return mSpline; } int getKnotDataPoint(int iknot) const { return mKnotDataPoints[iknot]; } @@ -117,6 +117,11 @@ class SplineHelper1D /// Gives error string const char* getLastError() const { return mError.c_str(); } +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation + /// Test the Spline1D class functionality + static int test(const bool draw = 0, const bool drawDataPoints = 1); +#endif + private: /// Stores an error message int storeError(int code, const char* msg); @@ -125,13 +130,17 @@ class SplineHelper1D /// helpers for the construction of 1D spline - Spline1D<DataT> mSpline; ///< copy of the spline + Spline1D<double> mSpline; ///< copy of the spline int mFdimensions; ///< n of F dimensions std::vector<DataPoint> mDataPoints; ///< measurement points std::vector<int> mKnotDataPoints; ///< which measurement points are at knots std::vector<double> mLSMmatrixFull; ///< a matrix to convert the measurements into the spline parameters with the LSM method std::vector<double> mLSMmatrixSderivatives; std::vector<double> mLSMmatrixSvalues; + +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline1DHelper, 0); +#endif }; } // namespace gpu diff --git a/GPU/TPCFastTransformation/Spline1DSpec.cxx b/GPU/TPCFastTransformation/Spline1DSpec.cxx new file mode 100644 index 0000000000000..66bd249147e6c --- /dev/null +++ b/GPU/TPCFastTransformation/Spline1DSpec.cxx @@ -0,0 +1,275 @@ +// 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 Spline1DSpec.cxx +/// \brief Implementation of Spline1DContainer & Spline1DSpec classes +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +//#include "Rtypes.h" +#endif + +#include "Spline1DSpec.h" + +#if !defined(GPUCA_GPUCODE) +#include <iostream> +#endif + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#include "Spline1DHelper.h" +#include "TFile.h" +#include "GPUCommonMath.h" +templateClassImp(GPUCA_NAMESPACE::gpu::Spline1DContainer); +templateClassImp(GPUCA_NAMESPACE::gpu::Spline1DSpec); +#endif + +using namespace std; +using namespace GPUCA_NAMESPACE::gpu; + +#if !defined(GPUCA_GPUCODE) + +template <class DataT> +void Spline1DContainer<DataT>::recreate(int nYdim, int numberOfKnots) +{ + /// Constructor for a regular spline + /// \param numberOfKnots Number of knots + + if (numberOfKnots < 2) { + numberOfKnots = 2; + } + + std::vector<int> knots(numberOfKnots); + for (int i = 0; i < numberOfKnots; i++) { + knots[i] = i; + } + recreate(nYdim, numberOfKnots, knots.data()); +} + +template <class DataT> +void Spline1DContainer<DataT>::recreate(int nYdim, int numberOfKnots, const int inputKnots[]) +{ + /// Main constructor for an irregular spline + /// + /// Number of created knots may differ from the input values: + /// - Duplicated knots will be deleted + /// - At least 2 knots will be created + /// + /// \param numberOfKnots Number of knots in knots[] array + /// \param knots Array of relative knot positions (integer values) + /// + + FlatObject::startConstruction(); + + mYdim = (nYdim >= 0) ? nYdim : 0; + + std::vector<int> knotU; + + { // sort knots + std::vector<int> tmp; + for (int i = 0; i < numberOfKnots; i++) { + tmp.push_back(inputKnots[i]); + } + std::sort(tmp.begin(), tmp.end()); + + knotU.push_back(0); // first knot at 0 + + for (unsigned int i = 1; i < tmp.size(); ++i) { + int u = tmp[i] - tmp[0]; + if (knotU.back() < u) { // remove duplicated knots + knotU.push_back(u); + } + } + if (knotU.back() < 1) { // there is only one knot at u=0, add the second one at u=1 + knotU.push_back(1); + } + } + + mNumberOfKnots = knotU.size(); + mUmax = knotU.back(); + mXmin = 0.; + mXtoUscale = 1.; + + const int uToKnotMapOffset = mNumberOfKnots * sizeof(Knot); + int parametersOffset = uToKnotMapOffset + (mUmax + 1) * sizeof(int); + int bufferSize = parametersOffset; + if (mYdim > 0) { + parametersOffset = alignSize(bufferSize, getParameterAlignmentBytes()); + bufferSize = parametersOffset + getSizeOfParameters(); + } + + FlatObject::finishConstruction(bufferSize); + + mUtoKnotMap = reinterpret_cast<int*>(mFlatBufferPtr + uToKnotMapOffset); + mParameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); + + for (int i = 0; i < getNumberOfParameters(); i++) { + mParameters[i] = 0; + } + + Knot* s = getKnots(); + + for (int i = 0; i < mNumberOfKnots; i++) { + s[i].u = knotU[i]; + } + + for (int i = 0; i < mNumberOfKnots - 1; i++) { + s[i].Li = 1. / (s[i + 1].u - s[i].u); // do division in double + } + + s[mNumberOfKnots - 1].Li = 0.; // the value will not be used, we define it for consistency + + // Set up the map (integer U) -> (knot index) + + int* map = getUtoKnotMap(); + + const int iKnotMax = mNumberOfKnots - 2; + + // + // With iKnotMax=nKnots-2 we map the U==Umax coordinate to the last [nKnots-2, nKnots-1] segment. + // This trick allows one to avoid a special condition for this edge case. + // Any U from [0,Umax] is mapped to some knot_i such, that the next knot_i+1 always exist + // + + for (int u = 0, iKnot = 0; u <= mUmax; u++) { + if ((knotU[iKnot + 1] == u) && (iKnot < iKnotMax)) { + iKnot = iKnot + 1; + } + map[u] = iKnot; + } +} + +#endif //GPUCA_GPUCODE + +template <class DataT> +void Spline1DContainer<DataT>::print() const +{ + printf(" Spline 1D: \n"); + printf(" mNumberOfKnots = %d \n", mNumberOfKnots); + printf(" mUmax = %d\n", mUmax); + printf(" mUtoKnotMap = %p \n", (void*)mUtoKnotMap); + printf(" knots: "); + for (int i = 0; i < mNumberOfKnots; i++) { + printf("%d ", (int)getKnot(i).u); + } + printf("\n"); +} + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + +template <class DataT> +void Spline1DContainer<DataT>::approximateFunction( + double xMin, double xMax, + std::function<void(double x, double f[])> F, + int nAxiliaryDataPoints) +{ + /// approximate a function F with this spline + Spline1DHelper<DataT> helper; + helper.approximateFunction(*reinterpret_cast<Spline1D<DataT>*>(this), xMin, xMax, F, nAxiliaryDataPoints); +} + +template <class DataT> +int Spline1DContainer<DataT>::writeToFile(TFile& outf, const char* name) +{ + /// write a class object to the file + return FlatObject::writeToFile(*this, outf, name); +} + +template <class DataT> +Spline1DContainer<DataT>* Spline1DContainer<DataT>::readFromFile( + TFile& inpf, const char* name) +{ + /// read a class object from the file + return FlatObject::readFromFile<Spline1DContainer<DataT>>(inpf, name); +} + +#endif + +#if !defined(GPUCA_GPUCODE) + +template <class DataT> +void Spline1DContainer<DataT>::cloneFromObject(const Spline1DContainer<DataT>& obj, char* newFlatBufferPtr) +{ + /// See FlatObject for description + + const char* oldFlatBufferPtr = obj.mFlatBufferPtr; + FlatObject::cloneFromObject(obj, newFlatBufferPtr); + mYdim = obj.mYdim; + mNumberOfKnots = obj.mNumberOfKnots; + mUmax = obj.mUmax; + mXmin = obj.mXmin; + mXtoUscale = obj.mXtoUscale; + mUtoKnotMap = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mUtoKnotMap); + mParameters = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mParameters); +} + +template <class DataT> +void Spline1DContainer<DataT>::moveBufferTo(char* newFlatBufferPtr) +{ + /// See FlatObject for description + char* oldFlatBufferPtr = mFlatBufferPtr; + FlatObject::moveBufferTo(newFlatBufferPtr); + char* currFlatBufferPtr = mFlatBufferPtr; + mFlatBufferPtr = oldFlatBufferPtr; + setActualBufferAddress(currFlatBufferPtr); +} +#endif // GPUCA_GPUCODE + +template <class DataT> +void Spline1DContainer<DataT>::destroy() +{ + /// See FlatObject for description + mNumberOfKnots = 0; + mUmax = 0; + mYdim = 0; + mXmin = 0.; + mXtoUscale = 1.; + mUtoKnotMap = nullptr; + mParameters = nullptr; + FlatObject::destroy(); +} + +template <class DataT> +void Spline1DContainer<DataT>::setActualBufferAddress(char* actualFlatBufferPtr) +{ + /// See FlatObject for description + + FlatObject::setActualBufferAddress(actualFlatBufferPtr); + + const int uToKnotMapOffset = mNumberOfKnots * sizeof(Knot); + mUtoKnotMap = reinterpret_cast<int*>(mFlatBufferPtr + uToKnotMapOffset); + int parametersOffset = uToKnotMapOffset + (mUmax + 1) * sizeof(int); + if (mYdim > 0) { + parametersOffset = alignSize(parametersOffset, getParameterAlignmentBytes()); + } + mParameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); +} + +template <class DataT> +void Spline1DContainer<DataT>::setFutureBufferAddress(char* futureFlatBufferPtr) +{ + /// See FlatObject for description + mUtoKnotMap = FlatObject::relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mUtoKnotMap); + mParameters = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mParameters); + FlatObject::setFutureBufferAddress(futureFlatBufferPtr); +} + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) +template <class DataT> +int Spline1DContainer<DataT>::test(const bool draw, const bool drawDataPoints) +{ + return Spline1DHelper<DataT>::test(draw, drawDataPoints); +} +#endif // GPUCA_GPUCODE + +template class GPUCA_NAMESPACE::gpu::Spline1DContainer<float>; +template class GPUCA_NAMESPACE::gpu::Spline1DContainer<double>; +template class GPUCA_NAMESPACE::gpu::Spline1DSpec<float, 0, 2>; +template class GPUCA_NAMESPACE::gpu::Spline1DSpec<double, 0, 2>; \ No newline at end of file diff --git a/GPU/TPCFastTransformation/Spline1DSpec.h b/GPU/TPCFastTransformation/Spline1DSpec.h new file mode 100644 index 0000000000000..da9f7facab7fb --- /dev/null +++ b/GPU/TPCFastTransformation/Spline1DSpec.h @@ -0,0 +1,517 @@ +// 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 Spline1DSpec.h +/// \brief Definition of Spline1DSpec class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE1DSPEC_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE1DSPEC_H + +#include "GPUCommonDef.h" +#include "FlatObject.h" +#include "SplineUtil.h" + +#if !defined(GPUCA_GPUCODE) +#include <functional> +#endif + +class TFile; + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ + +/// ================================================================================================== +/// The class Spline1DContainer is a base class of Spline1D. +/// It contains all the class members and those methods which only depends on the DataT data type. +/// It also contains all non-inlined methods with the implementation in Spline1DSpec.cxx file. +/// +/// DataT is a data type, which is supposed to be either double or float. +/// For other possible data types one has to add the corresponding instantiation line +/// at the end of the Spline1DSpec.cxx file +/// +template <typename DataT> +class Spline1DContainer : public FlatObject +{ + public: + /// Named enumeration for the safety level used by some methods + enum SafetyLevel { kNotSafe, + kSafe }; + + /// The struct Knot represents the i-th knot and the segment [knot_i, knot_i+1] + /// + struct Knot { + DataT u; ///< u coordinate of the knot i (an integer number in float format) + DataT Li; ///< inverse length of the [knot_i, knot_{i+1}] segment ( == 1./ a (small) integer ) + /// Get u as an integer + GPUd() int getU() const { return (int)(u + 0.1); } + }; + + /// _____________ Version control __________________________ + + /// Version control + GPUd() static constexpr int getVersion() { return 1; } + + /// _____________ C++ constructors / destructors __________________________ + + /// Default constructor, required by the Root IO + Spline1DContainer() CON_DEFAULT; + + /// Disable all other constructors + Spline1DContainer(const Spline1DContainer&) CON_DELETE; + + /// Destructor + ~Spline1DContainer() CON_DEFAULT; + + /// _______________ Construction interface ________________________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// approximate a function F with this spline + void approximateFunction(double xMin, double xMax, + std::function<void(double x, double f[/*mYdim*/])> F, + int nAuxiliaryDataPoints = 4); +#endif + + /// _______________ IO ________________________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// write a class object to the file + int writeToFile(TFile& outf, const char* name); + + /// read a class object from the file + static Spline1DContainer* readFromFile(TFile& inpf, const char* name); +#endif + + /// _______________ Getters ________________________ + + /// Get U coordinate of the last knot + GPUd() int getUmax() const { return mUmax; } + + /// Get number of Y dimensions + GPUd() int getYdimensions() const { return mYdim; } + + /// Get minimal required alignment for the spline parameters + GPUd() size_t getParameterAlignmentBytes() const + { + size_t s = 2 * sizeof(DataT) * mYdim; + return (s < 16) ? s : 16; + } + + /// Number of parameters + GPUd() int getNumberOfParameters() const { return calcNumberOfParameters(mYdim); } + + /// Size of the parameter array in bytes + GPUd() size_t getSizeOfParameters() const { return sizeof(DataT) * getNumberOfParameters(); } + + /// Get a number of knots + GPUd() int getNumberOfKnots() const { return mNumberOfKnots; } + + /// Get the array of knots + GPUd() const Knot* getKnots() const { return reinterpret_cast<const Knot*>(mFlatBufferPtr); } + + /// Get i-th knot + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() const Knot& getKnot(int i) const + { + if (SafeT == SafetyLevel::kSafe) { + i = (i < 0) ? 0 : (i >= mNumberOfKnots ? mNumberOfKnots - 1 : i); + } + return getKnots()[i]; + } + + /// Get index of an associated knot for a given U coordinate. Performs a boundary check. + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() int getLeftKnotIndexForU(DataT u) const; + + /// Get spline parameters + GPUd() DataT* getParameters() { return mParameters; } + + /// Get spline parameters const + GPUd() const DataT* getParameters() const { return mParameters; } + + /// _______________ Technical stuff ________________________ + + /// Get a map (integer U -> corresponding knot index) + GPUd() const int* getUtoKnotMap() const { return mUtoKnotMap; } + + /// Convert X coordinate to U + GPUd() DataT convXtoU(DataT x) const { return (x - mXmin) * mXtoUscale; } + + /// Convert U coordinate to X + GPUd() DataT convUtoX(DataT u) const { return mXmin + u / mXtoUscale; } + + /// Get Xmin + GPUd() DataT getXmin() const { return mXmin; } + + /// Get XtoUscale + GPUd() DataT getXtoUscale() const { return mXtoUscale; } + + /// Set X range + GPUd() void setXrange(DataT xMin, DataT xMax); + + /// Print method + void print() const; + + /// _______________ Expert tools _______________ + + /// Number of parameters for given Y dimensions + GPUd() int calcNumberOfParameters(int nYdim) const { return (2 * nYdim) * getNumberOfKnots(); } + + ///_______________ Test tools _______________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation + /// Test the class functionality + static int test(const bool draw = 0, const bool drawDataPoints = 1); +#endif + + /// _____________ FlatObject functionality, see FlatObject class for description ____________ + + using FlatObject::getBufferAlignmentBytes; + using FlatObject::getClassAlignmentBytes; + +#if !defined(GPUCA_GPUCODE) + void cloneFromObject(const Spline1DContainer& obj, char* newFlatBufferPtr); + void moveBufferTo(char* newBufferPtr); +#endif + + using FlatObject::releaseInternalBuffer; + + void destroy(); + void setActualBufferAddress(char* actualFlatBufferPtr); + void setFutureBufferAddress(char* futureFlatBufferPtr); + + protected: + /// Non-const accessor to the knots array + Knot* getKnots() { return reinterpret_cast<Knot*>(mFlatBufferPtr); } + + /// Non-const accessor to U->knots map + int* getUtoKnotMap() { return mUtoKnotMap; } + +#if !defined(GPUCA_GPUCODE) + /// Constructor for a regular spline + void recreate(int nYdim, int numberOfKnots); + + /// Constructor for an irregular spline + void recreate(int nYdim, int numberOfKnots, const int knotU[]); +#endif + + /// _____________ Data members ____________ + + int mYdim = 0; ///< dimentionality of F + int mNumberOfKnots = 0; ///< n knots on the grid + int mUmax = 0; ///< U of the last knot + DataT mXmin = 0; ///< X of the first knot + DataT mXtoUscale = 0; ///< a scaling factor to convert X to U + int* mUtoKnotMap = nullptr; //! (transient!!) pointer to (integer U -> knot index) map inside the mFlatBufferPtr array + DataT* mParameters = nullptr; //! (transient!!) pointer to F-dependent parameters inside the mFlatBufferPtr array + +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline1DContainer, 1); +#endif +}; + +template <typename DataT> +template <typename Spline1DContainer<DataT>::SafetyLevel SafeT> +GPUdi() int Spline1DContainer<DataT>::getLeftKnotIndexForU(DataT u) const +{ + /// Get i: u is in [knot_i, knot_{i+1}) segment + /// when u is otside of [0, mUmax], return a corresponding edge segment + int iu = (int)u; + if (SafeT == SafetyLevel::kSafe) { + iu = (iu < 0) ? 0 : (iu > mUmax ? mUmax : iu); + } + return getUtoKnotMap()[iu]; +} + +template <typename DataT> +GPUdi() void Spline1DContainer<DataT>::setXrange(DataT xMin, DataT xMax) +{ + mXmin = xMin; + double l = ((double)xMax) - xMin; + if (l < 1.e-8) { + l = 1.e-8; + } + mXtoUscale = mUmax / l; +} + +/// ================================================================================================== +/// +/// Spline1DSpec class declares different specializations of the Spline1D class. +/// +/// The specializations depend on the value of Spline1D's template parameter YdimT. +/// specializations have different constructors and slightly different declarations of methods. +/// +/// The meaning of the template parameters: +/// +/// \param DataT data type: float or double +/// \param YdimT +/// YdimT > 0 : the number of Y dimensions is known at the compile time and is equal to YdimT +/// YdimT = 0 : the number of Y dimensions will be set in the runtime +/// YdimT < 0 : the number of Y dimensions will be set in the runtime, and it will not exceed abs(XdimT) +/// \param SpecT specialisation number: +/// 0 - a parent class for all other specializations +/// 1 - nYdim>0: nYdim is set at the compile time +/// 2 - nYdim<0: nYdim must be set during runtime +/// 3 - specialization where nYdim==1 (a small add-on on top of the other specs) +/// +template <typename DataT, int YdimT, int SpecT> +class Spline1DSpec; + +/// ================================================================================================== +/// Specialization 0 declares common methods for all other Spline2D specializations. +/// Implementations of the methods may depend on the YdimT value. +/// +template <typename DataT, int YdimT> +class Spline1DSpec<DataT, YdimT, 0> : public Spline1DContainer<DataT> +{ + typedef Spline1DContainer<DataT> TBase; + + public: + typedef typename TBase::SafetyLevel SafetyLevel; + typedef typename TBase::Knot Knot; + + /// _______________ Interpolation math ________________________ + + /// Get interpolated value S(x) + GPUd() void interpolate(DataT x, GPUgeneric() DataT S[/*mYdim*/]) const + { + interpolateU<SafetyLevel::kSafe>(mYdim, mParameters, convXtoU(x), S); + } + + /// Get interpolated value for an nYdim-dimensional S(u) using spline parameters Parameters. + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() void interpolateU(int inpYdim, GPUgeneric() const DataT Parameters[], + DataT u, GPUgeneric() DataT S[/*nYdim*/]) const + { + const auto nYdimTmp = SplineUtil::getNdim<YdimT>(inpYdim); + const auto nYdim = nYdimTmp.get(); + int iknot = TBase::template getLeftKnotIndexForU<SafeT>(u); + const DataT* d = Parameters + (2 * nYdim) * iknot; + interpolateU(nYdim, getKnots()[iknot], &(d[0]), &(d[nYdim]), &(d[2 * nYdim]), &(d[3 * nYdim]), u, S); + } + + /// The main mathematical utility. + /// Get interpolated value {S(u): 1D -> nYdim} at the segment [knotL, next knotR] + /// using the spline values Sl, Sr and the slopes Dl, Dr + template <typename T> + GPUd() void interpolateU(int inpYdim, const Knot& knotL, + GPUgeneric() const T Sl[/*mYdim*/], GPUgeneric() const T Dl[/*mYdim*/], + GPUgeneric() const T Sr[/*mYdim*/], GPUgeneric() const T Dr[/*mYdim*/], + DataT u, GPUgeneric() T S[/*mYdim*/]) const + { + const auto nYdimTmp = SplineUtil::getNdim<YdimT>(inpYdim); + const auto nYdim = nYdimTmp.get(); + T uu = T(u - knotL.u); + T li = T(knotL.Li); + T v = uu * li; // scaled u + for (int dim = 0; dim < nYdim; ++dim) { + T df = (Sr[dim] - Sl[dim]) * li; + T a = Dl[dim] + Dr[dim] - df - df; + T b = df - Dl[dim] - a; + S[dim] = ((a * v + b) * v + Dl[dim]) * uu + Sl[dim]; + } + /* + another way to calculate f(u): + T uu = T(u - knotL.u); + T v = uu * T(knotL.Li); // scaled u + T vm1 = v-1; + T v2 = v * v; + float cSr = v2*(3-2*v); + float cSl = 1-cSr; + float cDl = v*vm1*vm1*knotL.L; + float cDr = v2*vm1*knotL.L; + return cSl*Sl + cSr*Sr + cDl*Dl + cDr*Dr; + */ + } + + using TBase::convXtoU; + using TBase::getKnot; + using TBase::getKnots; + using TBase::getNumberOfKnots; + + protected: + using TBase::mParameters; + using TBase::mYdim; + using TBase::TBase; // inherit constructors and hide them +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline1DSpec, 0); +#endif +}; + +/// ================================================================================================== +/// Specialization 1: YdimT>0 where the number of Y dimensions is taken from template parameters +/// at the compile time +/// +template <typename DataT, int YdimT> +class Spline1DSpec<DataT, YdimT, 1> + : public Spline1DSpec<DataT, YdimT, 0> +{ + typedef Spline1DContainer<DataT> TVeryBase; + typedef Spline1DSpec<DataT, YdimT, 0> TBase; + + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + +#if !defined(GPUCA_GPUCODE) + /// Default constructor + Spline1DSpec() : Spline1DSpec(2) {} + + /// Constructor for a regular spline + Spline1DSpec(int numberOfKnots) : TBase() + { + recreate(numberOfKnots); + } + /// Constructor for an irregular spline + Spline1DSpec(int numberOfKnots, const int knotU[]) + : TBase() + { + recreate(numberOfKnots, knotU); + } + /// Copy constructor + Spline1DSpec(const Spline1DSpec& v) : TBase() + { + TBase::cloneFromObject(v, nullptr); + } + /// Constructor for a regular spline + void recreate(int numberOfKnots) { TBase::recreate(YdimT, numberOfKnots); } + + /// Constructor for an irregular spline + void recreate(int numberOfKnots, const int knotU[]) + { + TBase::recreate(YdimT, numberOfKnots, knotU); + } +#endif + + /// Get number of Y dimensions + GPUd() constexpr int getYdimensions() const { return YdimT; } + + /// Get minimal required alignment for the spline parameters + GPUd() constexpr size_t getParameterAlignmentBytes() const + { + size_t s = 2 * sizeof(DataT) * YdimT; + return (s < 16) ? s : 16; + } + + /// Number of parameters + GPUd() int getNumberOfParameters() const { return (2 * YdimT) * getNumberOfKnots(); } + + /// Size of the parameter array in bytes + GPUd() size_t getSizeOfParameters() const { return (sizeof(DataT) * 2 * YdimT) * getNumberOfKnots(); } + + /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ + + /// Get interpolated value for an YdimT-dimensional S(u) using spline parameters Parameters. + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() void interpolateU(GPUgeneric() const DataT Parameters[], + DataT u, GPUgeneric() DataT S[/*nYdim*/]) const + { + TBase::template interpolateU<SafeT>(YdimT, Parameters, u, S); + } + + /// Get interpolated value for an YdimT-dimensional S(u) at the segment [knotL, next knotR] + /// using the spline values Sl, Sr and the slopes Dl, Dr + template <typename T> + GPUd() void interpolateU(const typename TBase::Knot& knotL, + GPUgeneric() const T Sl[/*mYdim*/], GPUgeneric() const T Dl[/*mYdim*/], + GPUgeneric() const T Sr[/*mYdim*/], GPUgeneric() const T Dr[/*mYdim*/], + DataT u, GPUgeneric() T S[/*mYdim*/]) const + { + TBase::template interpolateU(YdimT, knotL, Sl, Dl, Sr, Dr, u, S); + } + + using TBase::getNumberOfKnots; + + /// _______________ Suppress some parent class methods ________________________ + private: +#if !defined(GPUCA_GPUCODE) + using TBase::recreate; +#endif + using TBase::interpolateU; +}; + +/// ================================================================================================== +/// Specialization 2 (YdimT<=0) where the numbaer of Y dimensions +/// must be set in the runtime via a constructor parameter +/// +template <typename DataT, int YdimT> +class Spline1DSpec<DataT, YdimT, 2> + : public Spline1DSpec<DataT, YdimT, 0> +{ + typedef Spline1DContainer<DataT> TVeryBase; + typedef Spline1DSpec<DataT, YdimT, 0> TBase; + + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + +#if !defined(GPUCA_GPUCODE) + /// Default constructor + Spline1DSpec() : Spline1DSpec(0, 2) {} + + /// Constructor for a regular spline + Spline1DSpec(int nYdim, int numberOfKnots) : TBase() + { + TBase::recreate(nYdim, numberOfKnots); + } + /// Constructor for an irregular spline + Spline1DSpec(int nYdim, int numberOfKnots, const int knotU[]) : TBase() + { + TBase::recreate(nYdim, numberOfKnots, knotU); + } + /// Copy constructor + Spline1DSpec(const Spline1DSpec& v) : TBase() + { + TVeryBase::cloneFromObject(v, nullptr); + } + /// Constructor for a regular spline + void recreate(int nYdim, int numberOfKnots) { TBase::recreate(nYdim, numberOfKnots); } + + /// Constructor for an irregular spline + void recreate(int nYdim, int numberOfKnots, const int knotU[]) + { + TBase::recreate(nYdim, numberOfKnots, knotU); + } +#endif + + /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ + + using TBase::interpolateU; +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline1DSpec, 0); +#endif +}; + +/// ================================================================================================== +/// Specialization 3, where the number of Y dimensions is 1. +/// +template <typename DataT> +class Spline1DSpec<DataT, 1, 3> + : public Spline1DSpec<DataT, 1, SplineUtil::getSpec(999)> +{ + typedef Spline1DSpec<DataT, 1, SplineUtil::getSpec(999)> TBase; + + public: + using TBase::TBase; // inherit constructors + + /// Simplified interface for 1D: return the interpolated value + GPUd() DataT interpolate(DataT x) const + { + DataT S = 0.; + TBase::interpolate(x, &S); + return S; + } +}; + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/TPCFastTransformation/Spline2D.cxx b/GPU/TPCFastTransformation/Spline2D.cxx index a198fc6006179..08f832b408a55 100644 --- a/GPU/TPCFastTransformation/Spline2D.cxx +++ b/GPU/TPCFastTransformation/Spline2D.cxx @@ -13,493 +13,11 @@ /// /// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation -#include "Rtypes.h" -#endif - #include "Spline2D.h" -#if !defined(GPUCA_GPUCODE) -#include <iostream> -#endif - #if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation -#include "TRandom.h" -#include "Riostream.h" -#include "TMath.h" -#include "SplineHelper2D.h" -#include "TCanvas.h" -#include "TNtuple.h" -#include "TFile.h" -#include "GPUCommonMath.h" - -templateClassImp(GPUCA_NAMESPACE::gpu::Spline2DBase); - -#endif - -using namespace std; -using namespace GPUCA_NAMESPACE::gpu; - -template <typename DataT, bool isConsistentT> -Spline2DBase<DataT, isConsistentT>::Spline2DBase(int nDim) - : FlatObject(), mFdim(nDim), mGridU1(), mGridU2(), mFparameters(nullptr) -{ - recreate(2, 2); -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::destroy() -{ - /// See FlatObject for description - mGridU1.destroy(); - mGridU2.destroy(); - FlatObject::destroy(); -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::setActualBufferAddress(char* actualFlatBufferPtr) -{ - /// See FlatObject for description - - FlatObject::setActualBufferAddress(actualFlatBufferPtr); - - const size_t u2Offset = alignSize(mGridU1.getFlatBufferSize(), mGridU2.getBufferAlignmentBytes()); - int parametersOffset = u2Offset; - //int bufferSize = parametersOffset; - mFparameters = nullptr; - - if (isConsistentT) { - parametersOffset = alignSize(u2Offset + mGridU2.getFlatBufferSize(), getParameterAlignmentBytes()); - //bufferSize = parametersOffset + getSizeOfParameters(); - mFparameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); - } - - mGridU1.setActualBufferAddress(mFlatBufferPtr); - mGridU2.setActualBufferAddress(mFlatBufferPtr + u2Offset); -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::setFutureBufferAddress(char* futureFlatBufferPtr) -{ - /// See FlatObject for description - char* bufferU = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mGridU1.getFlatBufferPtr()); - char* bufferV = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mGridU2.getFlatBufferPtr()); - mGridU1.setFutureBufferAddress(bufferU); - mGridU2.setFutureBufferAddress(bufferV); - if (isConsistentT) { - mFparameters = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mFparameters); - } else { - mFparameters = nullptr; - } - FlatObject::setFutureBufferAddress(futureFlatBufferPtr); -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::print() const -{ - printf(" Irregular Spline 2D: \n"); - printf(" grid U1: \n"); - mGridU1.print(); - printf(" grid U2: \n"); - mGridU2.print(); -} - -#if !defined(GPUCA_GPUCODE) -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::cloneFromObject(const Spline2DBase<DataT, isConsistentT>& obj, char* newFlatBufferPtr) -{ - /// See FlatObject for description - if (isConsistentT && mFdim != obj.mFdim) { - assert(0); - return; - } - - const char* oldFlatBufferPtr = obj.mFlatBufferPtr; - - FlatObject::cloneFromObject(obj, newFlatBufferPtr); - - char* bufferU = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mGridU1.getFlatBufferPtr()); - char* bufferV = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mGridU2.getFlatBufferPtr()); - - mGridU1.cloneFromObject(obj.mGridU1, bufferU); - mGridU2.cloneFromObject(obj.mGridU2, bufferV); - - if (isConsistentT) { - mFparameters = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mFparameters); - } else { - mFparameters = nullptr; - } -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::moveBufferTo(char* newFlatBufferPtr) -{ - /// See FlatObject for description - char* oldFlatBufferPtr = mFlatBufferPtr; - FlatObject::moveBufferTo(newFlatBufferPtr); - char* currFlatBufferPtr = mFlatBufferPtr; - mFlatBufferPtr = oldFlatBufferPtr; - setActualBufferAddress(currFlatBufferPtr); -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::recreate( - int numberOfKnotsU1, const int knotsU1[], int numberOfKnotsU2, const int knotsU2[]) -{ - /// Constructor for an irregular spline - - FlatObject::startConstruction(); - - mGridU1.recreate(numberOfKnotsU1, knotsU1, 0); - mGridU2.recreate(numberOfKnotsU2, knotsU2, 0); - - const size_t u2Offset = alignSize(mGridU1.getFlatBufferSize(), mGridU2.getBufferAlignmentBytes()); - int parametersOffset = u2Offset + mGridU2.getFlatBufferSize(); - int bufferSize = parametersOffset; - mFparameters = nullptr; - - if (isConsistentT) { - parametersOffset = alignSize(bufferSize, getParameterAlignmentBytes()); - bufferSize = parametersOffset + getSizeOfParameters(); - } - - FlatObject::finishConstruction(bufferSize); - - mGridU1.moveBufferTo(mFlatBufferPtr); - mGridU2.moveBufferTo(mFlatBufferPtr + u2Offset); - if (isConsistentT) { - mFparameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); - for (int i = 0; i < getNumberOfParameters(); i++) { - mFparameters[i] = 0; - } - } -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::recreate( - int numberOfKnotsU1, int numberOfKnotsU2) -{ - /// Constructor for a regular spline - - FlatObject::startConstruction(); - - mGridU1.recreate(numberOfKnotsU1, 0); - - mGridU2.recreate(numberOfKnotsU2, 0); - - const size_t u2Offset = alignSize(mGridU1.getFlatBufferSize(), mGridU2.getBufferAlignmentBytes()); - int parametersOffset = u2Offset + mGridU2.getFlatBufferSize(); - int bufferSize = parametersOffset; - mFparameters = nullptr; - - if (isConsistentT) { - parametersOffset = alignSize(bufferSize, getParameterAlignmentBytes()); - bufferSize = parametersOffset + getSizeOfParameters(); - } - - FlatObject::finishConstruction(bufferSize); - - mGridU1.moveBufferTo(mFlatBufferPtr); - mGridU2.moveBufferTo(mFlatBufferPtr + u2Offset); - - if (isConsistentT) { - mFparameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); - for (int i = 0; i < getNumberOfParameters(); i++) { - mFparameters[i] = 0; - } - } -} - +templateClassImp(GPUCA_NAMESPACE::gpu::Spline2D); #endif -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) // code invisible on GPU and in the standalone compilation and in AliRoot - -template <typename DataT, bool isConsistentT> -int Spline2DBase<DataT, isConsistentT>::writeToFile(TFile& outf, const char* name) -{ - /// write a class object to the file - return FlatObject::writeToFile(*this, outf, name); -} - -template <typename DataT, bool isConsistentT> -Spline2DBase<DataT, isConsistentT>* Spline2DBase<DataT, isConsistentT>::readFromFile( - TFile& inpf, const char* name) -{ - /// read a class object from the file - return FlatObject::readFromFile<Spline2DBase<DataT, isConsistentT>>(inpf, name); -} - -template <typename DataT, bool isConsistentT> -void Spline2DBase<DataT, isConsistentT>::approximateFunction( - DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(DataT x1, DataT x2, DataT f[])> F, - int nAxiliaryDataPointsU1, int nAxiliaryDataPointsU2) -{ - /// approximate a function F with this spline - SplineHelper2D<DataT> helper; - helper.approximateFunction(*this, x1Min, x1Max, x2Min, x2Max, F, nAxiliaryDataPointsU1, nAxiliaryDataPointsU2); -} - -template <typename DataT, bool isConsistentT> -int Spline2DBase<DataT, isConsistentT>::test(const bool draw, const bool drawDataPoints) -{ - using namespace std; - - const int Ndim = 3; - - const int Fdegree = 4; - - double Fcoeff[Ndim][4 * (Fdegree + 1) * (Fdegree + 1)]; - - constexpr int nKnots = 4; - constexpr int nAxiliaryPoints = 1; - constexpr int uMax = nKnots * 3; - - auto F = [&](DataT u, DataT v, DataT Fuv[]) { - const double scale = TMath::Pi() / uMax; - double uu = u * scale; - double vv = v * scale; - double cosu[Fdegree + 1], sinu[Fdegree + 1], cosv[Fdegree + 1], sinv[Fdegree + 1]; - double ui = 0, vi = 0; - for (int i = 0; i <= Fdegree; i++, ui += uu, vi += vv) { - GPUCommonMath::SinCos(ui, sinu[i], cosu[i]); - GPUCommonMath::SinCos(vi, sinv[i], cosv[i]); - } - for (int dim = 0; dim < Ndim; dim++) { - double f = 0; // Fcoeff[dim][0]/2; - for (int i = 1; i <= Fdegree; i++) { - for (int j = 1; j <= Fdegree; j++) { - double* c = &(Fcoeff[dim][4 * (i * Fdegree + j)]); - f += c[0] * cosu[i] * cosv[j]; - f += c[1] * cosu[i] * sinv[j]; - f += c[2] * sinu[i] * cosv[j]; - f += c[3] * sinu[i] * sinv[j]; - } - } - Fuv[dim] = f; - } - }; - - TCanvas* canv = nullptr; - TNtuple* nt = nullptr; - TNtuple* knots = nullptr; - - auto ask = [&]() -> bool { - if (!canv) { - return 0; - } - canv->Update(); - cout << "type 'q ' to exit" << endl; - std::string str; - std::getline(std::cin, str); - return (str != "q" && str != ".q"); - }; - - std::cout << "Test 2D interpolation with the compact spline" << std::endl; - - int nTries = 10; - - if (draw) { - canv = new TCanvas("cQA", "Spline2D QA", 1500, 800); - nTries = 10000; - } - - long double statDf = 0; - long double statDf1D = 0; - long double statN = 0; - - for (int seed = 1; seed < nTries + 1; seed++) { - //cout << "next try.." << endl; - - gRandom->SetSeed(seed); - - for (int dim = 0; dim < Ndim; dim++) { - for (int i = 0; i < 4 * (Fdegree + 1) * (Fdegree + 1); i++) { - Fcoeff[dim][i] = gRandom->Uniform(-1, 1); - } - } - - Spline2D<DataT, Ndim> spline; - - int knotsU[nKnots], knotsV[nKnots]; - do { - knotsU[0] = 0; - knotsV[0] = 0; - double du = 1. * uMax / (nKnots - 1); - for (int i = 1; i < nKnots; i++) { - knotsU[i] = (int)(i * du); // + gRandom->Uniform(-du / 3, du / 3); - knotsV[i] = (int)(i * du); // + gRandom->Uniform(-du / 3, du / 3); - } - knotsU[nKnots - 1] = uMax; - knotsV[nKnots - 1] = uMax; - spline.recreate(nKnots, knotsU, nKnots, knotsV); - - if (nKnots != spline.getGridU1().getNumberOfKnots() || - nKnots != spline.getGridU2().getNumberOfKnots()) { - cout << "warning: n knots changed during the initialisation " << nKnots - << " -> " << spline.getNumberOfKnots() << std::endl; - continue; - } - } while (0); - - std::string err = FlatObject::stressTest(spline); - if (!err.empty()) { - cout << "error at FlatObject functionality: " << err << endl; - return -1; - } else { - // cout << "flat object functionality is ok" << endl; - } - - // Ndim-D spline - spline.approximateFunction(0., uMax, 0., uMax, F, 4, 4); - - //if (itry == 0) - if (1) { - TFile outf("testSpline2D.root", "recreate"); - if (outf.IsZombie()) { - cout << "Failed to open output file testSpline2D.root " << std::endl; - } else { - const char* name = "spline2Dtest"; - spline.writeToFile(outf, name); - Spline2D<DataT, Ndim>* p = Spline2D<DataT, Ndim>::readFromFile(outf, name); - if (p == nullptr) { - cout << "Failed to read Spline1D from file testSpline1D.root " << std::endl; - } else { - spline = *p; - } - outf.Close(); - } - } - - // 1-D splines for each of Ndim dimensions - - Spline2D<DataT, 1> splines1D[Ndim]; - - for (int dim = 0; dim < Ndim; dim++) { - auto F1 = [&](DataT x1, DataT x2, DataT f[]) { - DataT ff[Ndim]; - F(x1, x2, ff); - f[0] = ff[dim]; - }; - splines1D[dim].recreate(nKnots, knotsU, nKnots, knotsV); - splines1D[dim].approximateFunction(0., uMax, 0., uMax, F1, 4, 4); - } - - double stepU = .1; - for (double u = 0; u < uMax; u += stepU) { - for (double v = 0; v < uMax; v += stepU) { - DataT f[Ndim]; - F(u, v, f); - DataT s[Ndim]; - DataT s1; - spline.interpolate(u, v, s); - for (int dim = 0; dim < Ndim; dim++) { - statDf += (s[dim] - f[dim]) * (s[dim] - f[dim]); - splines1D[dim].interpolate(u, v, &s1); - statDf1D += (s[dim] - s1) * (s[dim] - s1); - } - statN += Ndim; - // cout << u << " " << v << ": f " << f << " s " << s << " df " - // << s - f << " " << sqrt(statDf / statN) << std::endl; - } - } - // cout << "Spline2D standard deviation : " << sqrt(statDf / statN) - // << std::endl; - - if (draw) { - delete nt; - delete knots; - nt = new TNtuple("nt", "nt", "u:v:f:s"); - knots = new TNtuple("knots", "knots", "type:u:v:s"); - double stepU = .3; - for (double u = 0; u < uMax; u += stepU) { - for (double v = 0; v < uMax; v += stepU) { - DataT f[Ndim]; - F(u, v, f); - DataT s[Ndim]; - spline.interpolate(u, v, s); - nt->Fill(u, v, f[0], s[0]); - } - } - nt->SetMarkerStyle(8); - - nt->SetMarkerSize(.5); - nt->SetMarkerColor(kBlue); - nt->Draw("s:u:v", "", ""); - - nt->SetMarkerColor(kGray); - nt->SetMarkerSize(2.); - nt->Draw("f:u:v", "", "same"); - - nt->SetMarkerSize(.5); - nt->SetMarkerColor(kBlue); - nt->Draw("s:u:v", "", "same"); - - for (int i = 0; i < nKnots; i++) { - for (int j = 0; j < nKnots; j++) { - double u = spline.getGridU1().getKnot(i).u; - double v = spline.getGridU2().getKnot(j).u; - DataT s[Ndim]; - spline.interpolate(u, v, s); - knots->Fill(1, u, v, s[0]); - } - } - - knots->SetMarkerStyle(8); - knots->SetMarkerSize(1.5); - knots->SetMarkerColor(kRed); - knots->SetMarkerSize(1.5); - knots->Draw("s:u:v", "type==1", "same"); // knots - - if (drawDataPoints) { - SplineHelper2D<DataT> helper; - helper.setSpline(spline, 4, 4); - for (int ipu = 0; ipu < helper.getHelperU1().getNumberOfDataPoints(); ipu++) { - const typename SplineHelper1D<DataT>::DataPoint& pu = helper.getHelperU1().getDataPoint(ipu); - for (int ipv = 0; ipv < helper.getHelperU2().getNumberOfDataPoints(); ipv++) { - const typename SplineHelper1D<DataT>::DataPoint& pv = helper.getHelperU2().getDataPoint(ipv); - if (pu.isKnot && pv.isKnot) { - continue; - } - DataT s[Ndim]; - spline.interpolate(pu.u, pv.u, s); - knots->Fill(2, pu.u, pv.u, s[0]); - } - } - knots->SetMarkerColor(kBlack); - knots->SetMarkerSize(1.); - knots->Draw("s:u:v", "type==2", "same"); // data points - } - - if (!ask()) { - break; - } - } - } - // delete canv; - // delete nt; - // delete knots; - - statDf = sqrt(statDf / statN); - statDf1D = sqrt(statDf1D / statN); - - cout << "\n std dev for Spline2D : " << statDf << std::endl; - cout << " mean difference between 1-D and " << Ndim - << "-D splines : " << statDf1D << std::endl; - - if (statDf < 0.15 && statDf1D < 1.e-20) { - cout << "Everything is fine" << endl; - } else { - cout << "Something is wrong!!" << endl; - return -2; - } - - return 0; -} - -#endif // GPUCA_GPUCODE - -template class GPUCA_NAMESPACE::gpu::Spline2DBase<float, false>; -template class GPUCA_NAMESPACE::gpu::Spline2DBase<float, true>; -template class GPUCA_NAMESPACE::gpu::Spline2DBase<double, false>; -template class GPUCA_NAMESPACE::gpu::Spline2DBase<double, true>; +template class GPUCA_NAMESPACE::gpu::Spline2D<float>; +template class GPUCA_NAMESPACE::gpu::Spline2D<double>; diff --git a/GPU/TPCFastTransformation/Spline2D.h b/GPU/TPCFastTransformation/Spline2D.h index bc04816f33b9b..cab8865429332 100644 --- a/GPU/TPCFastTransformation/Spline2D.h +++ b/GPU/TPCFastTransformation/Spline2D.h @@ -17,6 +17,7 @@ #define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE2D_H #include "Spline1D.h" +#include "Spline2DSpec.h" #include "FlatObject.h" #include "GPUCommonDef.h" @@ -37,431 +38,75 @@ namespace gpu /// See Spline1D.h for more details. /// /// The spline S(x1,x2) approximates a function F(x1,x2):R^2->R^m, -/// where x1,x2 belong to [x1Min,x1Max] x [x2Min,x2Max]. F value may be multi-dimensional. +/// with 2-dimensional domain and multi-dimensional codomain. +/// x1,x2 belong to [x1min,x1max] x [x2min,x2max]. /// /// --- Example of creating a spline --- /// -/// auto F = [&](float x1, float x2, float f[] ) { +/// auto F = [&](double x1, double x2, double f[] ) { /// f[0] = 1.f + x1 + x2*x2; // F(x1,x2) /// }; /// const int nKnotsU=2; /// const int nKnotsV=3; /// int knotsU[nKnotsU] = {0, 1}; /// int knotsV[nKnotsV] = {0, 2, 5}; -/// Spline2D<float,1> spline(nKnotsU, knotsU, nKnotsV, knotsV ); // prepare memory for 1-dimensional F -/// spline.approximateFunction(0., 1., 0.,1., F); //initialize spline to approximate F on area [0., 1.]x[0., 1.] +/// Spline2D<float,1> spline(nKnotsU, knotsU, nKnotsV, knotsV ); // spline with 1-dimensional codomain +/// spline.approximateFunction(0., 1., 0.,1., F); //initialize spline to approximate F on [0., 1.]x[0., 1.] area /// float S = spline.interpolate(.1, .3 ); // interpolated value at (.1,.3) /// -/// --- See also Spline2D::test(); +/// --- See also Spline2DHelper::test(); /// -/// Base class to store data members and non-inline methods -template <typename DataT, bool isConsistentT> -class Spline2DBase : public FlatObject -{ - public: - /// _____________ Version control __________________________ - - /// Version control - GPUhd() static constexpr int getVersion() { return 1; } - - /// _____________ Constructors / destructors __________________________ - -#if !defined(GPUCA_GPUCODE) - /// constructor && default constructor for the ROOT streamer - Spline2DBase(int nDim = 1); -#else - /// Disable constructors - Spline2DBase() CON_DELETE; -#endif - /// Disable constructors - Spline2DBase(const Spline2DBase&) CON_DELETE; - Spline2DBase& operator=(const Spline2DBase&) CON_DELETE; - - /// Destructor - ~Spline2DBase() CON_DEFAULT; - - /// _______________ Construction interface ________________________ - -#if !defined(GPUCA_GPUCODE) - /// Constructor for a regular spline. - void recreate(int numberOfKnotsU1, int numberOfKnotsU2); - - /// Constructor for an irregular spline - void recreate(int numberOfKnotsU1, const int knotsU1[], int numberOfKnotsU2, const int knotsU2[]); -#endif - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) - /// approximate a function F with this spline. - void approximateFunction(DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(DataT x1, DataT x2, DataT f[])> F, - int nAxiliaryDataPointsU1 = 4, int nAxiliaryDataPointsU2 = 4); -#endif - - /// _______________ IO ________________________ - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) - /// write a class object to the file - int writeToFile(TFile& outf, const char* name); - - /// read a class object from the file - static Spline2DBase* readFromFile(TFile& inpf, const char* name); -#endif - - /// _______________ Getters ________________________ - - /// Get number of F dimensions - GPUhd() int getFdimensions() const { return mFdim; } - - /// - GPUhd() static constexpr bool isConsistent() { return isConsistentT; } - - /// Get minimal required alignment for the spline parameters - GPUhd() static constexpr size_t getParameterAlignmentBytes() { return 16; } - - /// Number of parameters - GPUhd() int getNumberOfParameters() const { return (4 * mFdim) * getNumberOfKnots(); } - - /// Size of the parameter array in bytes - GPUhd() size_t getSizeOfParameters() const { return sizeof(DataT) * getNumberOfParameters(); } - - /// Get number total of knots: UxV - GPUhd() int getNumberOfKnots() const { return mGridU1.getNumberOfKnots() * mGridU2.getNumberOfKnots(); } - - /// Get 1-D grid for U1 coordinate - GPUhd() const Spline1D<DataT>& getGridU1() const { return mGridU1; } - - /// Get 1-D grid for U2 coordinate - GPUhd() const Spline1D<DataT>& getGridU2() const { return mGridU2; } - - /// Get 1-D grid for U1 or U2 coordinate - GPUhd() const Spline1D<DataT>& getGrid(int iu) const { return (iu == 0) ? mGridU1 : mGridU2; } - - /// Get u1,u2 of i-th knot - GPUhd() void getKnotU(int iKnot, DataT& u1, DataT& u2) const; - - /// Get index of a knot (iKnotU1,iKnotU2) - GPUhd() int getKnotIndex(int iKnotU1, int iKnotU2) const; - - /// Get number of F parameters - GPUhd() DataT* getFparameters() { return mFparameters; } - - /// Get number of F parameters - GPUhd() const DataT* getFparameters() const { return mFparameters; } - - /// _______________ Technical stuff ________________________ - - /// Get offset of GridU flat data in the flat buffer - GPUhd() size_t getGridU1Offset() const { return mGridU1.getFlatBufferPtr() - mFlatBufferPtr; } - - /// Get offset of GridU2 flat data in the flat buffer - GPUhd() size_t getGridU2Offset() const { return mGridU2.getFlatBufferPtr() - mFlatBufferPtr; } - - /// Set X range - GPUhd() void setXrange(DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max); - - /// Print method - void print() const; - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation - /// Test the class functionality - static int test(const bool draw = 0, const bool drawDataPoints = 1); -#endif - - /// _____________ FlatObject functionality, see FlatObject class for description ____________ - - using FlatObject::getBufferAlignmentBytes; - using FlatObject::getClassAlignmentBytes; - -#if !defined(GPUCA_GPUCODE) - void cloneFromObject(const Spline2DBase& obj, char* newFlatBufferPtr); - void moveBufferTo(char* newBufferPtr); -#endif - - using FlatObject::releaseInternalBuffer; - - void destroy(); - void setActualBufferAddress(char* actualFlatBufferPtr); - void setFutureBufferAddress(char* futureFlatBufferPtr); - - private: - int mFdim; ///< dimentionality of F - - protected: /// _____________ Data members ____________ - Spline1D<DataT> mGridU1; ///< grid for U axis - Spline1D<DataT> mGridU2; ///< grid for V axis - DataT* mFparameters; //! (transient!!) F-dependent parameters of the spline -#ifndef GPUCA_ALIROOT_LIB - ClassDefNV(Spline2DBase, 1); -#endif -}; - +/// ================================================================================================== +/// +/// Declare the Spline1D class as a template with one optional parameters. /// -/// The main Spline class. Contains constructors and interpolation. +/// Class specializations depend on the XdimT, YdimT values. They can be found in SplineSpecs.h /// -/// F dimensions can be set as a template parameter (faster; the only option for the GPU) -/// or as a constructor parameter (slower; the only option for the ROOT interpretator). -/// In a compiled CPU code one can use both options. +/// \param DataT data type: float or double +/// \param YdimT +/// YdimT > 0 : the number of Y dimensions is known at the compile time and is equal to XdimT +/// YdimT = 0 : the number of Y dimensions will be set in the runtime +/// YdimT < 0 : the number of Y dimensions will be set in the runtime, and it will not exceed abs(YdimT) /// -template <typename DataT, int nFdimT = 0, bool isConsistentT = 1> -class Spline2D : public Spline2DBase<DataT, isConsistentT> +template <typename DataT, int YdimT = 0> +class Spline2D + : public Spline2DSpec<DataT, YdimT, SplineUtil::getSpec(YdimT)> { - public: - typedef Spline2DBase<DataT, isConsistentT> TBase; + typedef Spline2DContainer<DataT> TVeryBase; + typedef Spline2DSpec<DataT, YdimT, SplineUtil::getSpec(YdimT)> TBase; - /// _____________ Constructors / destructors __________________________ + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + typedef typename TVeryBase::Knot Knot; #if !defined(GPUCA_GPUCODE) - - /// Constructor for a regular spline && default constructor - Spline2D(int numberOfKnotsU1 = 2, int numberOfKnotsU2 = 2); - - /// Constructor for an irregular spline - Spline2D(int numberOfKnotsU1, const int knotsU1[], int numberOfKnotsU2, const int knotsU2[]); - - /// Copy constructor - Spline2D(const Spline2D&); + using TBase::TBase; // inherit constructors /// Assignment operator - Spline2D& operator=(const Spline2D&); + Spline2D& operator=(const Spline2D& v) + { + TVeryBase::cloneFromObject(v, nullptr); + return *this; + } #else /// Disable constructors for the GPU implementation Spline2D() CON_DELETE; Spline2D(const Spline2D&) CON_DELETE; - Spline2D& operator=(const Spline2D&) CON_DELETE; #endif - /// Destructor - ~Spline2D() CON_DEFAULT; - - /// _______________ Main functionality ________________________ - - /// Get interpolated value for F(x1,x2) - GPUhd() void interpolate(DataT x1, DataT x2, GPUgeneric() DataT S[]) const; - - /// Get interpolated value for the first dimension of F(x1,x2). (Simplified interface for 1D) - GPUhd() DataT interpolate(DataT x1, DataT x2) const; - - /// Same as interpolate(), but using vectorized calculation. - GPUhd() void interpolateVec(DataT x1, DataT x2, GPUgeneric() DataT S[]) const; - - /// ================ Expert tools ================================ - - /// Get interpolated value for an nFdim-dimensional F(u) using spline parameters Fparameters. - /// Fparameters can be created via SplineHelper2D. - GPUhd() void interpolateU(GPUgeneric() const DataT Fparameters[], - DataT u1, DataT u2, GPUgeneric() DataT Su[]) const; - - /// Same as interpolateU(), but using vectorized calculation. - GPUhd() void interpolateUvec(GPUgeneric() const DataT Fparameters[], - DataT u1, DataT u2, GPUgeneric() DataT Su[]) const; - - /// _______________ IO ________________________ - #if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) - /// write a class object to the file - using TBase::writeToFile; - /// read a class object from the file static Spline2D* readFromFile(TFile& inpf, const char* name) { - return reinterpret_cast<Spline2D*>(TBase::readFromFile(inpf, name)); + return (Spline2D*)TVeryBase::readFromFile(inpf, name); } #endif - /// _______________ Getters ________________________ - - /// Get number of F dimensions. - GPUhd() static constexpr int getFdimensions() { return nFdimT; } - - using TBase::mFparameters; - using TBase::mGridU1; - using TBase::mGridU2; -}; - -/// -/// ======================================================================================================== -/// Inline implementations of some methods -/// ======================================================================================================== -/// - -template <typename DataT, bool isConsistentT> -GPUhdi() void Spline2DBase<DataT, isConsistentT>::getKnotU(int iKnot, DataT& u1, DataT& u2) const -{ - /// Get u1,u2 of i-th knot - int nu1 = mGridU1.getNumberOfKnots(); - int iu2 = iKnot / nu1; - int iu1 = iKnot % nu1; - u1 = mGridU1.getKnot(iu1).u; - u2 = mGridU2.getKnot(iu2).u; -} - -template <typename DataT, bool isConsistentT> -GPUhdi() int Spline2DBase<DataT, isConsistentT>::getKnotIndex(int iKnotU1, int iKnotU2) const -{ - /// Get index of a knot (iKnotU1,iKnotU2) - int nu1 = mGridU1.getNumberOfKnots(); - return nu1 * iKnotU2 + iKnotU1; -} - -template <typename DataT, bool isConsistentT> -GPUhdi() void Spline2DBase<DataT, isConsistentT>::setXrange( - DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max) -{ - mGridU1.setXrange(x1Min, x1Max); - mGridU2.setXrange(x2Min, x2Max); -} - -#if !defined(GPUCA_GPUCODE) - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() Spline2D<DataT, nFdimT, isConsistentT>:: - Spline2D(int numberOfKnotsU1, int numberOfKnotsU2) - : Spline2DBase<DataT, isConsistentT>(nFdimT) -{ - this->recreate(numberOfKnotsU1, numberOfKnotsU2); -} - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() Spline2D<DataT, nFdimT, isConsistentT>:: - Spline2D(int numberOfKnotsU1, const int knotsU1[], - int numberOfKnotsU2, const int knotsU2[]) - : Spline2DBase<DataT, isConsistentT>(nFdimT) -{ - this->recreate(numberOfKnotsU1, knotsU1, numberOfKnotsU2, knotsU2); -} - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() Spline2D<DataT, nFdimT, isConsistentT>:: - Spline2D(const Spline2D& spline) - : Spline2DBase<DataT, isConsistentT>(nFdimT) -{ - this->cloneFromObject(spline, nullptr); -} - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhd() Spline2D<DataT, nFdimT, isConsistentT>& Spline2D<DataT, nFdimT, isConsistentT>:: - operator=(const Spline2D<DataT, nFdimT, isConsistentT>& spline) -{ - this->cloneFromObject(spline, nullptr); - return *this; -} -#endif - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() void Spline2D<DataT, nFdimT, isConsistentT>:: - interpolate(DataT x1, DataT x2, GPUgeneric() DataT S[]) const -{ - /// Get interpolated value for F(x1,x2) - assert(isConsistentT); - if (isConsistentT) { - interpolateU(mFparameters, mGridU1.convXtoU(x1), mGridU2.convXtoU(x2), S); - } else { - for (int i = 0; i < nFdimT; i++) { - S[i] = -1.; - } - } -} - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() DataT Spline2D<DataT, nFdimT, isConsistentT>:: - interpolate(DataT x1, DataT x2) const -{ - /// Simplified interface for 1D: get interpolated value for the first dimension of F(x) - -#if defined(GPUCA_GPUCODE) - DataT S[nFdimT]; // constexpr array size for the GPU compiler -#else - DataT S[getFdimensions()]; -#endif - interpolate(x1, x2, S); - return S[0]; -} - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() void Spline2D<DataT, nFdimT, isConsistentT>::interpolateVec( - DataT x1, DataT x2, GPUgeneric() DataT S[]) const -{ - /// Same as interpolate(), but using vectorized calculation - assert(isConsistentT); - if (isConsistentT) { - interpolateUvec(mFparameters, mGridU1.convXtoU(x1), mGridU2.convXtoU(x2), S); - } else { - for (int i = 0; i < getFdimensions(); i++) { - S[i] = 0.; - } - } -} - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() void Spline2D<DataT, nFdimT, isConsistentT>::interpolateU( - GPUgeneric() const DataT Fparameters[], - DataT u, DataT v, GPUgeneric() DataT S[]) const -{ - /// Get interpolated value for an nFdim-dimensional F(u) using spline parameters Fparameters. - /// Fparameters can be created via SplineHelper2D. - - int nu = mGridU1.getNumberOfKnots(); - int iu = mGridU1.getKnotIndexU(u); - int iv = mGridU2.getKnotIndexU(v); - - const typename Spline1D<DataT>::Knot& knotU = mGridU1.getKnot(iu); - const typename Spline1D<DataT>::Knot& knotV = mGridU2.getKnot(iv); - -#if defined(GPUCA_GPUCODE) // constexpr array size for the GPU compiler - const int nFdim = nFdimT; -#else - const int nFdim = getFdimensions(); +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline2D, 0); #endif - - const int nFdim2 = nFdimT * 2; - const int nFdim4 = nFdimT * 4; - - // X:=Sx, Y:=Sy, Z:=Sz - - const DataT* par00 = Fparameters + (nu * iv + iu) * nFdim4; // values { {X,Y,Z}, {X,Y,Z}'v, {X,Y,Z}'u, {X,Y,Z}''vu } at {u0, v0} - const DataT* par10 = par00 + nFdim4; // values { ... } at {u1, v0} - const DataT* par01 = par00 + nFdim4 * nu; // values { ... } at {u0, v1} - const DataT* par11 = par01 + nFdim4; // values { ... } at {u1, v1} - - DataT Su0[nFdim4]; // values { {X,Y,Z,X'v,Y'v,Z'v}(v0), {X,Y,Z,X'v,Y'v,Z'v}(v1) }, at u0 - DataT Du0[nFdim4]; // derivatives {}'_u at u0 - DataT Su1[nFdim4]; // values { {X,Y,Z,X'v,Y'v,Z'v}(v0), {X,Y,Z,X'v,Y'v,Z'v}(v1) }, at u1 - DataT Du1[nFdim4]; // derivatives {}'_u at u1 - - for (int i = 0; i < nFdim2; i++) { - Su0[i] = par00[i]; - Su0[nFdim2 + i] = par01[i]; - - Du0[i] = par00[nFdim2 + i]; - Du0[nFdim2 + i] = par01[nFdim2 + i]; - - Su1[i] = par10[i]; - Su1[nFdim2 + i] = par11[i]; - - Du1[i] = par10[nFdim2 + i]; - Du1[nFdim2 + i] = par11[nFdim2 + i]; - } - - DataT parU[nFdim4]; // interpolated values { {X,Y,Z,X'v,Y'v,Z'v}(v0), {X,Y,Z,X'v,Y'v,Z'v}(v1) } at u - mGridU1.interpolateU(nFdim4, knotU, Su0, Du0, Su1, Du1, u, parU); - - const DataT* Sv0 = parU + 0; - const DataT* Dv0 = parU + nFdim; - const DataT* Sv1 = parU + nFdim2; - const DataT* Dv1 = parU + nFdim2 + nFdim; - - mGridU2.interpolateU(nFdim, knotV, Sv0, Dv0, Sv1, Dv1, v, S); -} - -template <typename DataT, int nFdimT, bool isConsistentT> -GPUhdi() void Spline2D<DataT, nFdimT, isConsistentT>::interpolateUvec( - GPUgeneric() const DataT Fparameters[], - DataT u1, DataT u2, GPUgeneric() DataT S[]) const -{ - /// Same as interpolateU(), but using vectorized calculation - interpolateU(mFparameters, u1, u2, S); -} +}; } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/TPCFastTransformation/Spline2DHelper.cxx b/GPU/TPCFastTransformation/Spline2DHelper.cxx new file mode 100644 index 0000000000000..cef92f3cac620 --- /dev/null +++ b/GPU/TPCFastTransformation/Spline2DHelper.cxx @@ -0,0 +1,484 @@ +// 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 Spline2DHelper.cxx +/// \brief Implementation of Spline2DHelper class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + +#include "Spline2DHelper.h" +#include "TMath.h" +#include "TMatrixD.h" +#include "TVectorD.h" +#include "TDecompBK.h" + +#include <vector> +#include "TRandom.h" +#include "TMath.h" +#include "TCanvas.h" +#include "TNtuple.h" +#include "TFile.h" +#include "GPUCommonMath.h" +#include <iostream> + +using namespace GPUCA_NAMESPACE::gpu; + +template <typename DataT> +Spline2DHelper<DataT>::Spline2DHelper() : mError(), mFdimensions(0), mHelperU1(), mHelperU2() +{ +} + +template <typename DataT> +int Spline2DHelper<DataT>::storeError(int code, const char* msg) +{ + mError = msg; + return code; +} + +template <typename DataT> +void Spline2DHelper<DataT>::approximateFunction( + DataT* Fparameters, double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(double x1, double x2, double f[/*spline.getYdimensions()*/])> F) const +{ + /// Create best-fit spline parameters for a given input function F + /// output in Fparameters + + std::vector<double> dataPointF(getNumberOfDataPoints() * mFdimensions); + + double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax()); + double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax()); + + for (int iv = 0; iv < getNumberOfDataPointsU2(); iv++) { + double x2 = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2; + for (int iu = 0; iu < getNumberOfDataPointsU1(); iu++) { + double x1 = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1; + F(x1, x2, &dataPointF[(iv * getNumberOfDataPointsU1() + iu) * mFdimensions]); + } + } + approximateFunction(Fparameters, dataPointF.data()); +} + +template <typename DataT> +void Spline2DHelper<DataT>::approximateFunctionBatch( + DataT* Fparameters, double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(const std::vector<double>& x1, const std::vector<double>& x2, std::vector<double> f[/*mFdimensions*/])> F, + unsigned int batchsize) const +{ + /// Create best-fit spline parameters for a given input function F. + /// F calculates values for a batch of points. + /// output in Fparameters + + std::vector<double> dataPointF(getNumberOfDataPoints() * mFdimensions); + + double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax()); + double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax()); + + std::vector<double> x1; + x1.reserve(batchsize); + + std::vector<double> x2; + x2.reserve(batchsize); + + std::vector<int> index; + index.reserve(batchsize); + + std::vector<double> dataPointFTmp[mFdimensions]; + for (unsigned int iDim = 0; iDim < mFdimensions; ++iDim) { + dataPointFTmp[iDim].reserve(batchsize); + } + + unsigned int counter = 0; + for (int iv = 0; iv < getNumberOfDataPointsU2(); iv++) { + double x2Tmp = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2; + for (int iu = 0; iu < getNumberOfDataPointsU1(); iu++) { + double x1Tmp = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1; + x1.emplace_back(x1Tmp); + x2.emplace_back(x2Tmp); + index.emplace_back((iv * getNumberOfDataPointsU1() + iu) * mFdimensions); + ++counter; + + if (counter == batchsize || (iu == (getNumberOfDataPointsU1() - 1) && (iv == (getNumberOfDataPointsU2() - 1)))) { + counter = 0; + F(x1, x2, dataPointFTmp); + unsigned int entries = index.size(); + + for (unsigned int i = 0; i < entries; ++i) { + const unsigned int indexTmp = index[i]; + for (unsigned int iDim = 0; iDim < mFdimensions; ++iDim) { + dataPointF[indexTmp + iDim] = dataPointFTmp[iDim][i]; + } + } + + x1.clear(); + x2.clear(); + index.clear(); + for (unsigned int iDim = 0; iDim < mFdimensions; ++iDim) { + dataPointFTmp[iDim].clear(); + } + } + } + } + approximateFunction(Fparameters, dataPointF.data()); +} + +template <typename DataT> +void Spline2DHelper<DataT>::approximateFunction( + DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const +{ + /// approximate a function given as an array of values at data points + + const int Ndim = mFdimensions; + const int Ndim2 = 2 * Ndim; + const int Ndim3 = 3 * Ndim; + const int Ndim4 = 4 * Ndim; + + int nDataPointsU = getNumberOfDataPointsU1(); + int nDataPointsV = getNumberOfDataPointsU2(); + + int nKnotsU = mHelperU1.getSpline().getNumberOfKnots(); + int nKnotsV = mHelperU2.getSpline().getNumberOfKnots(); + + std::unique_ptr<double[]> rotDataPointF(new double[nDataPointsU * nDataPointsV * Ndim]); // U DataPoints x V DataPoints : rotated DataPointF for one output dimension + std::unique_ptr<double[]> Dv(new double[nKnotsV * nDataPointsU * Ndim]); // V knots x U DataPoints + + std::unique_ptr<DataT[]> parU(new DataT[mHelperU1.getSpline().calcNumberOfParameters(Ndim)]); + std::unique_ptr<DataT[]> parV(new DataT[mHelperU2.getSpline().calcNumberOfParameters(Ndim)]); + + std::unique_ptr<double[]> parUdbl(new double[mHelperU1.getSpline().calcNumberOfParameters(Ndim)]); + std::unique_ptr<double[]> parVdbl(new double[mHelperU2.getSpline().calcNumberOfParameters(Ndim)]); + + // rotated data points (u,v)->(v,u) + + for (int ipu = 0; ipu < nDataPointsU; ipu++) { + for (int ipv = 0; ipv < nDataPointsV; ipv++) { + for (int dim = 0; dim < Ndim; dim++) { + rotDataPointF[Ndim * (ipu * nDataPointsV + ipv) + dim] = DataPointF[Ndim * (ipv * nDataPointsU + ipu) + dim]; + } + } + } + + // get S and S'u at all the knots by interpolating along the U axis + + for (int iKnotV = 0; iKnotV < nKnotsV; ++iKnotV) { + int ipv = mHelperU2.getKnotDataPoint(iKnotV); + const double* DataPointFrow = &(DataPointF[Ndim * ipv * nDataPointsU]); + mHelperU1.approximateFunctionGradually(parU.get(), DataPointFrow); + + for (int i = 0; i < mHelperU1.getSpline().calcNumberOfParameters(Ndim); i++) { + parUdbl[i] = parU[i]; + } + for (int iKnotU = 0; iKnotU < nKnotsU; ++iKnotU) { + DataT* knotPar = &Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU)]; + for (int dim = 0; dim < Ndim; ++dim) { + knotPar[dim] = parU[Ndim * (2 * iKnotU) + dim]; // store S for all the knots + knotPar[Ndim2 + dim] = parU[Ndim * (2 * iKnotU) + Ndim + dim]; // store S'u for all the knots //SG!!! + } + } + + // recalculate F values for all ipu DataPoints at V = ipv + for (int ipu = 0; ipu < nDataPointsU; ipu++) { + double splineF[Ndim]; + double u = mHelperU1.getDataPoint(ipu).u; + mHelperU1.getSpline().interpolateU(Ndim, parUdbl.get(), u, splineF); + for (int dim = 0; dim < Ndim; dim++) { + rotDataPointF[(ipu * nDataPointsV + ipv) * Ndim + dim] = splineF[dim]; + } + } + } + + // calculate S'v at all data points with V == V of a knot + + for (int ipu = 0; ipu < nDataPointsU; ipu++) { + const double* DataPointFcol = &(rotDataPointF[ipu * nDataPointsV * Ndim]); + mHelperU2.approximateFunctionGradually(parV.get(), DataPointFcol); + for (int iKnotV = 0; iKnotV < nKnotsV; iKnotV++) { + for (int dim = 0; dim < Ndim; dim++) { + double dv = parV[(iKnotV * 2 + 1) * Ndim + dim]; + Dv[(iKnotV * nDataPointsU + ipu) * Ndim + dim] = dv; + } + } + } + + // fit S'v and S''_vu at all the knots + + for (int iKnotV = 0; iKnotV < nKnotsV; ++iKnotV) { + const double* Dvrow = &(Dv[iKnotV * nDataPointsU * Ndim]); + mHelperU1.approximateFunction(parU.get(), Dvrow); + for (int iKnotU = 0; iKnotU < nKnotsU; ++iKnotU) { + for (int dim = 0; dim < Ndim; ++dim) { + Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU) + Ndim + dim] = parU[Ndim * 2 * iKnotU + dim]; // store S'v for all the knots + Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU) + Ndim3 + dim] = parU[Ndim * 2 * iKnotU + Ndim + dim]; // store S''vu for all the knots + } + } + } +} + +template <typename DataT> +int Spline2DHelper<DataT>::test(const bool draw, const bool drawDataPoints) +{ + using namespace std; + + const int Ndim = 3; + + const int Fdegree = 4; + + double Fcoeff[Ndim][4 * (Fdegree + 1) * (Fdegree + 1)]; + + constexpr int nKnots = 4; + constexpr int nAuxiliaryPoints = 1; + constexpr int uMax = nKnots * 3; + + auto F = [&](double u, double v, double Fuv[]) { + const double scale = TMath::Pi() / uMax; + double uu = u * scale; + double vv = v * scale; + double cosu[Fdegree + 1], sinu[Fdegree + 1], cosv[Fdegree + 1], sinv[Fdegree + 1]; + double ui = 0, vi = 0; + for (int i = 0; i <= Fdegree; i++, ui += uu, vi += vv) { + GPUCommonMath::SinCos(ui, sinu[i], cosu[i]); + GPUCommonMath::SinCos(vi, sinv[i], cosv[i]); + } + for (int dim = 0; dim < Ndim; dim++) { + double f = 0; // Fcoeff[dim][0]/2; + for (int i = 1; i <= Fdegree; i++) { + for (int j = 1; j <= Fdegree; j++) { + double* c = &(Fcoeff[dim][4 * (i * Fdegree + j)]); + f += c[0] * cosu[i] * cosv[j]; + f += c[1] * cosu[i] * sinv[j]; + f += c[2] * sinu[i] * cosv[j]; + f += c[3] * sinu[i] * sinv[j]; + } + } + Fuv[dim] = f; + } + }; + + TCanvas* canv = nullptr; + TNtuple* nt = nullptr; + TNtuple* knots = nullptr; + + auto ask = [&]() -> bool { + if (!canv) { + return 0; + } + canv->Update(); + cout << "type 'q ' to exit" << endl; + std::string str; + std::getline(std::cin, str); + return (str != "q" && str != ".q"); + }; + + std::cout << "Test 2D interpolation with the compact spline" << std::endl; + + int nTries = 10; + + if (draw) { + canv = new TCanvas("cQA", "Spline2D QA", 1500, 800); + nTries = 10000; + } + + long double statDf = 0; + long double statDf1D = 0; + long double statN = 0; + + for (int seed = 1; seed < nTries + 1; seed++) { + //cout << "next try.." << endl; + + gRandom->SetSeed(seed); + + for (int dim = 0; dim < Ndim; dim++) { + for (int i = 0; i < 4 * (Fdegree + 1) * (Fdegree + 1); i++) { + Fcoeff[dim][i] = gRandom->Uniform(-1, 1); + } + } + + Spline2D<DataT, Ndim> spline; + + int knotsU[nKnots], knotsV[nKnots]; + do { + knotsU[0] = 0; + knotsV[0] = 0; + double du = 1. * uMax / (nKnots - 1); + for (int i = 1; i < nKnots; i++) { + knotsU[i] = (int)(i * du); // + gRandom->Uniform(-du / 3, du / 3); + knotsV[i] = (int)(i * du); // + gRandom->Uniform(-du / 3, du / 3); + } + knotsU[nKnots - 1] = uMax; + knotsV[nKnots - 1] = uMax; + spline.recreate(nKnots, knotsU, nKnots, knotsV); + + if (nKnots != spline.getGridX1().getNumberOfKnots() || + nKnots != spline.getGridX2().getNumberOfKnots()) { + cout << "warning: n knots changed during the initialisation " << nKnots + << " -> " << spline.getNumberOfKnots() << std::endl; + continue; + } + } while (0); + + std::string err = FlatObject::stressTest(spline); + if (!err.empty()) { + cout << "error at FlatObject functionality: " << err << endl; + return -1; + } else { + // cout << "flat object functionality is ok" << endl; + } + + // Ndim-D spline + spline.approximateFunction(0., uMax, 0., uMax, F, 4, 4); + + //if (itry == 0) + if (1) { + TFile outf("testSpline2D.root", "recreate"); + if (outf.IsZombie()) { + cout << "Failed to open output file testSpline2D.root " << std::endl; + } else { + const char* name = "spline2Dtest"; + spline.writeToFile(outf, name); + Spline2D<DataT, Ndim>* p = Spline2D<DataT, Ndim>::readFromFile(outf, name); + if (p == nullptr) { + cout << "Failed to read Spline1DOld from file testSpline1DOld.root " << std::endl; + } else { + spline = *p; + } + outf.Close(); + } + } + + // 1-D splines for each of Ndim dimensions + + Spline2D<DataT, 1> splines1D[Ndim]; + + for (int dim = 0; dim < Ndim; dim++) { + auto F1 = [&](double x1, double x2, double f[]) { + double ff[Ndim]; + F(x1, x2, ff); + f[0] = ff[dim]; + }; + splines1D[dim].recreate(nKnots, knotsU, nKnots, knotsV); + splines1D[dim].approximateFunction(0., uMax, 0., uMax, F1, 4, 4); + } + + double stepU = .1; + for (double u = 0; u < uMax; u += stepU) { + for (double v = 0; v < uMax; v += stepU) { + double f[Ndim]; + F(u, v, f); + DataT s[Ndim]; + spline.interpolate(u, v, s); + for (int dim = 0; dim < Ndim; dim++) { + statDf += (s[dim] - f[dim]) * (s[dim] - f[dim]); + DataT s1 = splines1D[dim].interpolate(u, v); + statDf1D += (s[dim] - s1) * (s[dim] - s1); + } + statN += Ndim; + // cout << u << " " << v << ": f " << f << " s " << s << " df " + // << s - f << " " << sqrt(statDf / statN) << std::endl; + } + } + // cout << "Spline2D standard deviation : " << sqrt(statDf / statN) + // << std::endl; + + if (draw) { + delete nt; + delete knots; + nt = new TNtuple("nt", "nt", "u:v:f:s"); + knots = new TNtuple("knots", "knots", "type:u:v:s"); + double stepU = .3; + for (double u = 0; u < uMax; u += stepU) { + for (double v = 0; v < uMax; v += stepU) { + double f[Ndim]; + F(u, v, f); + DataT s[Ndim]; + spline.interpolate(u, v, s); + nt->Fill(u, v, f[0], s[0]); + } + } + nt->SetMarkerStyle(8); + + nt->SetMarkerSize(.5); + nt->SetMarkerColor(kBlue); + nt->Draw("s:u:v", "", ""); + + nt->SetMarkerColor(kGray); + nt->SetMarkerSize(2.); + nt->Draw("f:u:v", "", "same"); + + nt->SetMarkerSize(.5); + nt->SetMarkerColor(kBlue); + nt->Draw("s:u:v", "", "same"); + + for (int i = 0; i < nKnots; i++) { + for (int j = 0; j < nKnots; j++) { + double u = spline.getGridX1().getKnot(i).u; + double v = spline.getGridX2().getKnot(j).u; + DataT s[Ndim]; + spline.interpolate(u, v, s); + knots->Fill(1, u, v, s[0]); + } + } + + knots->SetMarkerStyle(8); + knots->SetMarkerSize(1.5); + knots->SetMarkerColor(kRed); + knots->SetMarkerSize(1.5); + knots->Draw("s:u:v", "type==1", "same"); // knots + + if (drawDataPoints) { + Spline2DHelper<DataT> helper; + helper.setSpline(spline, 4, 4); + for (int ipu = 0; ipu < helper.getHelperU1().getNumberOfDataPoints(); ipu++) { + const typename Spline1DHelper<DataT>::DataPoint& pu = helper.getHelperU1().getDataPoint(ipu); + for (int ipv = 0; ipv < helper.getHelperU2().getNumberOfDataPoints(); ipv++) { + const typename Spline1DHelper<DataT>::DataPoint& pv = helper.getHelperU2().getDataPoint(ipv); + if (pu.isKnot && pv.isKnot) { + continue; + } + DataT s[Ndim]; + spline.interpolate(pu.u, pv.u, s); + knots->Fill(2, pu.u, pv.u, s[0]); + } + } + knots->SetMarkerColor(kBlack); + knots->SetMarkerSize(1.); + knots->Draw("s:u:v", "type==2", "same"); // data points + } + + if (!ask()) { + break; + } + } + } + // delete canv; + // delete nt; + // delete knots; + + statDf = sqrt(statDf / statN); + statDf1D = sqrt(statDf1D / statN); + + cout << "\n std dev for Spline2D : " << statDf << std::endl; + cout << " mean difference between 1-D and " << Ndim + << "-D splines : " << statDf1D << std::endl; + + if (statDf < 0.15 && statDf1D < 1.e-20) { + cout << "Everything is fine" << endl; + } else { + cout << "Something is wrong!!" << endl; + return -2; + } + + return 0; +} + +template class GPUCA_NAMESPACE::gpu::Spline2DHelper<float>; +template class GPUCA_NAMESPACE::gpu::Spline2DHelper<double>; + +#endif diff --git a/GPU/TPCFastTransformation/Spline2DHelper.h b/GPU/TPCFastTransformation/Spline2DHelper.h new file mode 100644 index 0000000000000..2b59406219144 --- /dev/null +++ b/GPU/TPCFastTransformation/Spline2DHelper.h @@ -0,0 +1,153 @@ +// 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 Spline2DHelper.h +/// \brief Definition of Spline2DHelper class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_Spline2DHelper_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_Spline2DHelper_H + +#include <cmath> +#include <vector> + +#include "GPUCommonDef.h" +#include "GPUCommonRtypes.h" +#include "Spline1D.h" +#include "Spline2D.h" +#include "Spline1DHelper.h" +#include <functional> +#include <string> + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ + +/// +/// The Spline2DHelper class is to initialize Spline* objects +/// +template <typename DataT> +class Spline2DHelper +{ + public: + /// _____________ Constructors / destructors __________________________ + + /// Default constructor + Spline2DHelper(); + + /// Copy constructor: disabled + Spline2DHelper(const Spline2DHelper&) CON_DELETE; + + /// Assignment operator: disabled + Spline2DHelper& operator=(const Spline2DHelper&) CON_DELETE; + + /// Destructor + ~Spline2DHelper() CON_DEFAULT; + + /// _______________ Main functionality ________________________ + + /// Create best-fit spline parameters for a given input function F + void approximateFunction( + Spline2DContainer<DataT>& spline, + double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(double x1, double x2, double f[/*spline.getYdimensions()*/])> F, + int nAuxiliaryDataPointsU1 = 4, int nAuxiliaryDataPointsU2 = 4); + + /// _______________ Interface for a step-wise construction of the best-fit spline ________________________ + + /// precompute everything needed for the construction + int setSpline(const Spline2DContainer<DataT>& spline, int nAuxiliaryPointsU1, int nAuxiliaryPointsU2); + + /// approximate std::function, output in Fparameters + void approximateFunction( + DataT* Fparameters, double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(double x1, double x2, double f[/*mFdimensions*/])> F) const; + + /// approximate std::function, output in Fparameters. F calculates values for a batch of points. + void approximateFunctionBatch( + DataT* Fparameters, double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(const std::vector<double>& x1, const std::vector<double>& x2, std::vector<double> f[/*mFdimensions*/])> F, + unsigned int batchsize) const; + + /// approximate a function given as an array of values at data points + void approximateFunction( + DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; + + int getNumberOfDataPointsU1() const { return mHelperU1.getNumberOfDataPoints(); } + + int getNumberOfDataPointsU2() const { return mHelperU2.getNumberOfDataPoints(); } + + int getNumberOfDataPoints() const { return getNumberOfDataPointsU1() * getNumberOfDataPointsU2(); } + + const Spline1DHelper<DataT>& getHelperU1() const { return mHelperU1; } + const Spline1DHelper<DataT>& getHelperU2() const { return mHelperU2; } + + /// _______________ Utilities ________________________ + + /// Gives error string + const char* getLastError() const { return mError.c_str(); } + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation + /// Test the Spline2D class functionality + static int test(const bool draw = 0, const bool drawDataPoints = 1); +#endif + + private: + /// Stores an error message + int storeError(int code, const char* msg); + + std::string mError = ""; ///< error string + int mFdimensions; ///< n of F dimensions + Spline1DHelper<DataT> mHelperU1; + Spline1DHelper<DataT> mHelperU2; + +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline2DHelper, 0); +#endif +}; + +template <typename DataT> +void Spline2DHelper<DataT>::approximateFunction( + Spline2DContainer<DataT>& spline, + double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(double x1, double x2, double f[/*spline.getYdimensions()*/])> F, + int nAuxiliaryDataPointsU1, int nAuxiliaryDataPointsU2) +{ + /// Create best-fit spline parameters for a given input function F + setSpline(spline, nAuxiliaryDataPointsU1, nAuxiliaryDataPointsU2); + approximateFunction(spline.getParameters(), x1Min, x1Max, x2Min, x2Max, F); + spline.setXrange(x1Min, x1Max, x2Min, x2Max); +} + +template <typename DataT> +int Spline2DHelper<DataT>::setSpline( + const Spline2DContainer<DataT>& spline, int nAuxiliaryPointsU, int nAuxiliaryPointsV) +{ + // Prepare creation of 2D irregular spline + // The should be at least one (better, two) Auxiliary measurements on each segnment between two knots and at least 2*nKnots measurements in total + // Returns 0 when the spline can not be constructed with the given nAuxiliaryPoints + + int ret = 0; + mFdimensions = spline.getYdimensions(); + if (mHelperU1.setSpline(spline.getGridX1(), mFdimensions, nAuxiliaryPointsU) != 0) { + ret = storeError(-2, "Spline2DHelper::setSpline2D: error by setting U axis"); + } + if (mHelperU2.setSpline(spline.getGridX2(), mFdimensions, nAuxiliaryPointsV) != 0) { + ret = storeError(-3, "Spline2DHelper::setSpline2D: error by setting V axis"); + } + return ret; +} + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/TPCFastTransformation/Spline2DSpec.cxx b/GPU/TPCFastTransformation/Spline2DSpec.cxx new file mode 100644 index 0000000000000..0efbb68f78ef9 --- /dev/null +++ b/GPU/TPCFastTransformation/Spline2DSpec.cxx @@ -0,0 +1,230 @@ +// 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 Spline2DSpec.cxx +/// \brief Implementation of Spline2DSpec class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#include "Rtypes.h" +#endif + +#include "Spline2DSpec.h" + +#if !defined(GPUCA_GPUCODE) +#include <iostream> +#endif + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#include "TRandom.h" +#include "Riostream.h" +#include "TMath.h" +#include "Spline2DHelper.h" +#include "TCanvas.h" +#include "TNtuple.h" +#include "TFile.h" +#include "GPUCommonMath.h" + +templateClassImp(GPUCA_NAMESPACE::gpu::Spline2DContainer); +templateClassImp(GPUCA_NAMESPACE::gpu::Spline2DSpec); + +#endif + +using namespace std; +using namespace GPUCA_NAMESPACE::gpu; + +template <typename DataT> +void Spline2DContainer<DataT>::destroy() +{ + /// See FlatObject for description + mGridX1.destroy(); + mGridX2.destroy(); + mYdim = 0; + mParameters = nullptr; + FlatObject::destroy(); +} + +template <typename DataT> +void Spline2DContainer<DataT>::setActualBufferAddress(char* actualFlatBufferPtr) +{ + /// See FlatObject for description + + FlatObject::setActualBufferAddress(actualFlatBufferPtr); + + const size_t u2Offset = alignSize(mGridX1.getFlatBufferSize(), mGridX2.getBufferAlignmentBytes()); + int parametersOffset = u2Offset; + //int bufferSize = parametersOffset; + mParameters = nullptr; + + parametersOffset = alignSize(u2Offset + mGridX2.getFlatBufferSize(), getParameterAlignmentBytes()); + //bufferSize = parametersOffset + getSizeOfParameters(); + mParameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); + + mGridX1.setActualBufferAddress(mFlatBufferPtr); + mGridX2.setActualBufferAddress(mFlatBufferPtr + u2Offset); +} + +template <typename DataT> +void Spline2DContainer<DataT>::setFutureBufferAddress(char* futureFlatBufferPtr) +{ + /// See FlatObject for description + char* bufferU = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mGridX1.getFlatBufferPtr()); + char* bufferV = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mGridX2.getFlatBufferPtr()); + mGridX1.setFutureBufferAddress(bufferU); + mGridX2.setFutureBufferAddress(bufferV); + mParameters = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mParameters); + FlatObject::setFutureBufferAddress(futureFlatBufferPtr); +} + +template <typename DataT> +void Spline2DContainer<DataT>::print() const +{ + printf(" Irregular Spline 2D: \n"); + printf(" grid U1: \n"); + mGridX1.print(); + printf(" grid U2: \n"); + mGridX2.print(); +} + +#if !defined(GPUCA_GPUCODE) + +template <typename DataT> +void Spline2DContainer<DataT>::cloneFromObject(const Spline2DContainer<DataT>& obj, char* newFlatBufferPtr) +{ + /// See FlatObject for description + + const char* oldFlatBufferPtr = obj.mFlatBufferPtr; + + FlatObject::cloneFromObject(obj, newFlatBufferPtr); + + mYdim = obj.mYdim; + char* bufferU = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mGridX1.getFlatBufferPtr()); + char* bufferV = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mGridX2.getFlatBufferPtr()); + + mGridX1.cloneFromObject(obj.mGridX1, bufferU); + mGridX2.cloneFromObject(obj.mGridX2, bufferV); + mParameters = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mParameters); +} + +template <typename DataT> +void Spline2DContainer<DataT>::moveBufferTo(char* newFlatBufferPtr) +{ + /// See FlatObject for description + char* oldFlatBufferPtr = mFlatBufferPtr; + FlatObject::moveBufferTo(newFlatBufferPtr); + char* currFlatBufferPtr = mFlatBufferPtr; + mFlatBufferPtr = oldFlatBufferPtr; + setActualBufferAddress(currFlatBufferPtr); +} + +template <typename DataT> +void Spline2DContainer<DataT>::recreate( + int nYdim, + int numberOfKnotsU1, const int knotsU1[], int numberOfKnotsU2, const int knotsU2[]) +{ + /// Constructor for an irregular spline + + mYdim = nYdim; + FlatObject::startConstruction(); + + mGridX1.recreate(0, numberOfKnotsU1, knotsU1); + mGridX2.recreate(0, numberOfKnotsU2, knotsU2); + + const size_t u2Offset = alignSize(mGridX1.getFlatBufferSize(), mGridX2.getBufferAlignmentBytes()); + int parametersOffset = u2Offset + mGridX2.getFlatBufferSize(); + int bufferSize = parametersOffset; + mParameters = nullptr; + + parametersOffset = alignSize(bufferSize, getParameterAlignmentBytes()); + bufferSize = parametersOffset + getSizeOfParameters(); + + FlatObject::finishConstruction(bufferSize); + + mGridX1.moveBufferTo(mFlatBufferPtr); + mGridX2.moveBufferTo(mFlatBufferPtr + u2Offset); + + mParameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); + for (int i = 0; i < getNumberOfParameters(); i++) { + mParameters[i] = 0; + } +} + +template <typename DataT> +void Spline2DContainer<DataT>::recreate(int nYdim, + int numberOfKnotsU1, int numberOfKnotsU2) +{ + /// Constructor for a regular spline + + mYdim = nYdim; + FlatObject::startConstruction(); + + mGridX1.recreate(0, numberOfKnotsU1); + mGridX2.recreate(0, numberOfKnotsU2); + + const size_t u2Offset = alignSize(mGridX1.getFlatBufferSize(), mGridX2.getBufferAlignmentBytes()); + int parametersOffset = u2Offset + mGridX2.getFlatBufferSize(); + int bufferSize = parametersOffset; + mParameters = nullptr; + + parametersOffset = alignSize(bufferSize, getParameterAlignmentBytes()); + bufferSize = parametersOffset + getSizeOfParameters(); + + FlatObject::finishConstruction(bufferSize); + + mGridX1.moveBufferTo(mFlatBufferPtr); + mGridX2.moveBufferTo(mFlatBufferPtr + u2Offset); + + mParameters = reinterpret_cast<DataT*>(mFlatBufferPtr + parametersOffset); + for (int i = 0; i < getNumberOfParameters(); i++) { + mParameters[i] = 0; + } +} + +#endif // GPUCA_GPUCODE + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation + +template <typename DataT> +void Spline2DContainer<DataT>::approximateFunction( + double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(double x1, double x2, double f[])> F, + int nAuxiliaryDataPointsX1, int nAuxiliaryDataPointsX2) +{ + /// approximate a function F with this spline + Spline2DHelper<DataT> helper; + helper.approximateFunction(*reinterpret_cast<Spline2D<DataT>*>(this), x1Min, x1Max, x2Min, x2Max, F, nAuxiliaryDataPointsX1, nAuxiliaryDataPointsX2); +} + +template <typename DataT> +int Spline2DContainer<DataT>::writeToFile(TFile& outf, const char* name) +{ + /// write a class object to the file + return FlatObject::writeToFile(*this, outf, name); +} + +template <typename DataT> +Spline2DContainer<DataT>* Spline2DContainer<DataT>::readFromFile( + TFile& inpf, const char* name) +{ + /// read a class object from the file + return FlatObject::readFromFile<Spline2DContainer<DataT>>(inpf, name); +} + +template <typename DataT> +int Spline2DContainer<DataT>::test(const bool draw, const bool drawDataPoints) +{ + return Spline2DHelper<DataT>::test(draw, drawDataPoints); +} + +#endif // GPUCA_GPUCODE && !GPUCA_STANDALONE + +template class GPUCA_NAMESPACE::gpu::Spline2DContainer<float>; +template class GPUCA_NAMESPACE::gpu::Spline2DContainer<double>; diff --git a/GPU/TPCFastTransformation/Spline2DSpec.h b/GPU/TPCFastTransformation/Spline2DSpec.h new file mode 100644 index 0000000000000..1a4dbf9412291 --- /dev/null +++ b/GPU/TPCFastTransformation/Spline2DSpec.h @@ -0,0 +1,476 @@ +// 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 Spline2DSpec.h +/// \brief Definition of Spline2DSpec class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE2DSPEC_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE2DSPEC_H + +#include "Spline1D.h" +#include "FlatObject.h" +#include "GPUCommonDef.h" +#include "SplineUtil.h" + +#if !defined(__CINT__) && !defined(__ROOTCINT__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) && defined(__cplusplus) && __cplusplus >= 201703L +#include <Vc/Vc> +#include <Vc/SimdArray> +#endif + +class TFile; + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ + +/// ================================================================================================== +/// The class Spline2DContainer is a base Spline2D class. +/// It contains all the class members and those methods which only depends on the DataT data type. +/// It also contains all non-inlined methods with the implementation in SplineSpec.cxx file. +/// +/// DataT is a data type, which is supposed to be either double or float. +/// For other possible data types one has to add the corresponding instantiation line +/// at the end of the Spline2DSpec.cxx file +/// +template <typename DataT> +class Spline2DContainer : public FlatObject +{ + public: + typedef typename Spline1D<DataT>::SafetyLevel SafetyLevel; + typedef typename Spline1D<DataT>::Knot Knot; + + /// _____________ Version control __________________________ + + /// Version control + GPUd() static constexpr int getVersion() { return (1 << 16) + Spline1D<DataT>::getVersion(); } + + /// _____________ C++ constructors / destructors __________________________ + + /// Default constructor + Spline2DContainer() CON_DEFAULT; + + /// Disable all other constructors + Spline2DContainer(const Spline2DContainer&) CON_DELETE; + + /// Destructor + ~Spline2DContainer() CON_DEFAULT; + + /// _______________ Construction interface ________________________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// approximate a function F with this spline + void approximateFunction(double x1Min, double x1Max, double x2Min, double x2Max, + std::function<void(double x1, double x2, double f[/*mYdim*/])> F, + int nAuxiliaryDataPointsU1 = 4, int nAuxiliaryDataPointsU2 = 4); +#endif + + /// _______________ IO ________________________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// write a class object to the file + int writeToFile(TFile& outf, const char* name); + + /// read a class object from the file + static Spline2DContainer* readFromFile(TFile& inpf, const char* name); +#endif + + /// _______________ Getters ________________________ + + /// Get number of Y dimensions + GPUd() int getYdimensions() const { return mYdim; } + + /// Get minimal required alignment for the spline parameters + GPUd() static constexpr size_t getParameterAlignmentBytes() { return 16; } + + /// Number of parameters + GPUd() int getNumberOfParameters() const { return this->calcNumberOfParameters(mYdim); } + + /// Size of the parameter array in bytes + GPUd() size_t getSizeOfParameters() const { return sizeof(DataT) * this->getNumberOfParameters(); } + + /// Get a number of knots + GPUd() int getNumberOfKnots() const { return mGridX1.getNumberOfKnots() * mGridX2.getNumberOfKnots(); } + + /// Get 1-D grid for the X1 coordinate + GPUd() const Spline1D<DataT>& getGridX1() const { return mGridX1; } + + /// Get 1-D grid for the X2 coordinate + GPUd() const Spline1D<DataT>& getGridX2() const { return mGridX2; } + + /// Get 1-D grid for X1 or X2 coordinate + GPUd() const Spline1D<DataT>& getGrid(int ix) const { return (ix == 0) ? mGridX1 : mGridX2; } + + /// Get (u1,u2) of i-th knot + GPUd() void getKnotU(int iKnot, int& u1, int& u2) const + { + u1 = mGridX1.getKnot(iKnot % mGridX1.getNumberOfKnots()).getU(); + u2 = mGridX2.getKnot(iKnot / mGridX1.getNumberOfKnots()).getU(); + } + + /// Get index of a knot (iKnotX1,iKnotX2) + GPUd() int getKnotIndex(int iKnotX1, int iKnotX2) const + { + return mGridX1.getNumberOfKnots() * iKnotX2 + iKnotX1; + } + + /// Get spline parameters + GPUd() DataT* getParameters() { return mParameters; } + + /// Get spline parameters const + GPUd() const DataT* getParameters() const { return mParameters; } + + /// _______________ Technical stuff ________________________ + + /// Get offset of GridX1 flat data in the flat buffer + GPUd() size_t getGridX1Offset() const { return mGridX1.getFlatBufferPtr() - mFlatBufferPtr; } + + /// Get offset of GridX2 flat data in the flat buffer + GPUd() size_t getGridX2Offset() const { return mGridX2.getFlatBufferPtr() - mFlatBufferPtr; } + + /// Set X range + GPUd() void setXrange(DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max) + { + mGridX1.setXrange(x1Min, x1Max); + mGridX2.setXrange(x2Min, x2Max); + } + + /// Print method + void print() const; + + /// _______________ Expert tools _______________ + + /// Number of parameters for given Y dimensions + GPUd() int calcNumberOfParameters(int nYdim) const { return (4 * nYdim) * getNumberOfKnots(); } + + ///_______________ Test tools _______________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation + /// Test the class functionality + static int test(const bool draw = 0, const bool drawDataPoints = 1); +#endif + + /// _____________ FlatObject functionality, see FlatObject class for description ____________ + + using FlatObject::getBufferAlignmentBytes; + using FlatObject::getClassAlignmentBytes; + +#if !defined(GPUCA_GPUCODE) + void cloneFromObject(const Spline2DContainer& obj, char* newFlatBufferPtr); + void moveBufferTo(char* newBufferPtr); +#endif + + using FlatObject::releaseInternalBuffer; + + void destroy(); + void setActualBufferAddress(char* actualFlatBufferPtr); + void setFutureBufferAddress(char* futureFlatBufferPtr); + + protected: +#if !defined(GPUCA_GPUCODE) + /// Constructor for a regular spline + void recreate(int nYdim, int nKnotsX1, int nKnotsX2); + + /// Constructor for an irregular spline + void recreate(int nYdim, int nKnotsX1, const int knotU1[], int nKnotsX2, const int knotU2[]); +#endif + + /// _____________ Data members ____________ + + int mYdim = 0; ///< dimentionality of F + Spline1D<DataT> mGridX1; ///< grid for U axis + Spline1D<DataT> mGridX2; ///< grid for V axis + DataT* mParameters = nullptr; //! (transient!!) F-dependent parameters of the spline + +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(Spline2DContainer, 1); +#endif +}; + +/// ================================================================================================== +/// +/// Spline2DSpec class declares different specializations of the Spline2D class. +/// They are the same as the Spline1D specializations. (See Spline1DSpec.h) +/// +/// The meaning of the template parameters: +/// +/// \param DataT data type: float or double +/// \param YdimT +/// YdimT > 0 : the number of Y dimensions is known at the compile time and is equal to YdimT +/// YdimT = 0 : the number of Y dimensions will be set in the runtime +/// YdimT < 0 : the number of Y dimensions will be set in the runtime, and it will not exceed abs(XdimT) +/// \param SpecT specialisation number: +/// 0 - a parent class for all other specializations +/// 1 - nYdim>0: nYdim is set at the compile time +/// 2 - nYdim<0: nYdim must be set during runtime +/// 3 - specialization where nYdim==1 (a small add-on on top of the other specs) +/// +template <typename DataT, int YdimT, int SpecT> +class Spline2DSpec; + +/// ================================================================================================== +/// Specialization 0 declares common methods for all other Spline2D specializations. +/// Implementations of the methods may depend on the YdimT value. +/// +template <typename DataT, int YdimT> +class Spline2DSpec<DataT, YdimT, 0> + : public Spline2DContainer<DataT> +{ + typedef Spline2DContainer<DataT> TBase; + + public: + typedef typename TBase::SafetyLevel SafetyLevel; + typedef typename TBase::Knot Knot; + + /// _______________ Interpolation math ________________________ + + /// Get interpolated value S(x) + GPUd() void interpolate(DataT x1, DataT x2, GPUgeneric() DataT S[/*mYdim*/]) const + { + interpolateU<SafetyLevel::kSafe>(mYdim, mParameters, mGridX1.convXtoU(x1), mGridX2.convXtoU(x2), S); + } + + /// Get interpolated value for an inpYdim-dimensional S(u1,u2) using spline parameters Parameters. + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() void interpolateU(int inpYdim, GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT S[/*inpYdim*/]) const + { + + const auto nYdimTmp = SplineUtil::getNdim<YdimT>(inpYdim); + const int nYdim = nYdimTmp.get(); + + const auto maxYdim = SplineUtil::getMaxNdim<YdimT>(inpYdim); + const int maxYdim4 = 4 * maxYdim.get(); + + const auto nYdim2 = nYdim * 2; + const auto nYdim4 = nYdim * 4; + + const float& u = u1; + const float& v = u2; + int nu = mGridX1.getNumberOfKnots(); + int iu = mGridX1.template getLeftKnotIndexForU<SafeT>(u); + int iv = mGridX2.template getLeftKnotIndexForU<SafeT>(v); + + const typename TBase::Knot& knotU = mGridX1.template getKnot<SafetyLevel::kNotSafe>(iu); + const typename TBase::Knot& knotV = mGridX2.template getKnot<SafetyLevel::kNotSafe>(iv); + + const DataT* par00 = Parameters + (nu * iv + iu) * nYdim4; // values { {Y1,Y2,Y3}, {Y1,Y2,Y3}'v, {Y1,Y2,Y3}'u, {Y1,Y2,Y3}''vu } at {u0, v0} + const DataT* par10 = par00 + nYdim4; // values { ... } at {u1, v0} + const DataT* par01 = par00 + nYdim4 * nu; // values { ... } at {u0, v1} + const DataT* par11 = par01 + nYdim4; // values { ... } at {u1, v1} + + DataT Su0[maxYdim4]; // values { {Y1,Y2,Y3,Y1'v,Y2'v,Y3'v}(v0), {Y1,Y2,Y3,Y1'v,Y2'v,Y3'v}(v1) }, at u0 + DataT Du0[maxYdim4]; // derivatives {}'_u at u0 + DataT Su1[maxYdim4]; // values { {Y1,Y2,Y3,Y1'v,Y2'v,Y3'v}(v0), {Y1,Y2,Y3,Y1'v,Y2'v,Y3'v}(v1) }, at u1 + DataT Du1[maxYdim4]; // derivatives {}'_u at u1 + + for (int i = 0; i < nYdim2; i++) { + Su0[i] = par00[i]; + Su0[nYdim2 + i] = par01[i]; + + Du0[i] = par00[nYdim2 + i]; + Du0[nYdim2 + i] = par01[nYdim2 + i]; + + Su1[i] = par10[i]; + Su1[nYdim2 + i] = par11[i]; + + Du1[i] = par10[nYdim2 + i]; + Du1[nYdim2 + i] = par11[nYdim2 + i]; + } + + DataT parU[maxYdim4]; // interpolated values { {Y1,Y2,Y3,Y1'v,Y2'v,Y3'v}(v0), {Y1,Y2,Y3,Y1'v,Y2'v,Y3'v}(v1) } at u + + typedef Spline1DSpec<DataT, 4 * YdimT, 0> TGridX1; + const TGridX1& gridX1 = reinterpret_cast<const TGridX1&>(mGridX1); + + gridX1.interpolateU(nYdim4, knotU, Su0, Du0, Su1, Du1, u, parU); + + const DataT* Sv0 = parU + 0; + const DataT* Dv0 = parU + nYdim; + const DataT* Sv1 = parU + nYdim2; + const DataT* Dv1 = parU + nYdim2 + nYdim; + + typedef Spline1DSpec<DataT, YdimT, 0> TGridX2; + const TGridX2& gridX2 = reinterpret_cast<const TGridX2&>(mGridX2); + gridX2.interpolateU(nYdim, knotV, Sv0, Dv0, Sv1, Dv1, v, S); + } + + protected: + using TBase::mGridX1; + using TBase::mGridX2; + using TBase::mParameters; + using TBase::mYdim; + using TBase::TBase; // inherit constructors and hide them +}; + +/// ================================================================================================== +/// Specialization 1: YdimT>0 where the number of Y dimensions is taken from template parameters +/// at the compile time +/// +template <typename DataT, int YdimT> +class Spline2DSpec<DataT, YdimT, 1> + : public Spline2DSpec<DataT, YdimT, 0> +{ + typedef Spline2DContainer<DataT> TVeryBase; + typedef Spline2DSpec<DataT, YdimT, 0> TBase; + + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + +#if !defined(GPUCA_GPUCODE) + /// Default constructor + Spline2DSpec() : Spline2DSpec(2, 2) {} + + /// Constructor for a regular spline + Spline2DSpec(int nKnotsX1, int nKnotsX2) : TBase() + { + recreate(nKnotsX1, nKnotsX2); + } + /// Constructor for an irregular spline + Spline2DSpec(int nKnotsX1, const int knotU1[], + int nKnotsX2, const int knotU2[]) + : TBase() + { + recreate(nKnotsX1, knotU1, nKnotsX2, knotU2); + } + /// Copy constructor + Spline2DSpec(const Spline2DSpec& v) : TBase() + { + TBase::cloneFromObject(v, nullptr); + } + /// Constructor for a regular spline + void recreate(int nKnotsX1, int nKnotsX2) + { + TBase::recreate(YdimT, nKnotsX1, nKnotsX2); + } + + /// Constructor for an irregular spline + void recreate(int nKnotsX1, const int knotU1[], + int nKnotsX2, const int knotU2[]) + { + TBase::recreate(YdimT, nKnotsX1, knotU1, nKnotsX2, knotU2); + } +#endif + + /// Get number of Y dimensions + GPUd() constexpr int getYdimensions() const { return YdimT; } + + /// Number of parameters + GPUd() int getNumberOfParameters() const { return (4 * YdimT) * getNumberOfKnots(); } + + /// Size of the parameter array in bytes + GPUd() size_t getSizeOfParameters() const { return (sizeof(DataT) * 4 * YdimT) * getNumberOfKnots(); } + + /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ + + /// Get interpolated value for an YdimT-dimensional S(u1,u2) using spline parameters Parameters. + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() void interpolateU(GPUgeneric() const DataT Parameters[], + DataT u1, DataT u2, GPUgeneric() DataT S[/*nYdim*/]) const + { + TBase::template interpolateU<SafeT>(YdimT, Parameters, u1, u2, S); + } + + using TBase::getNumberOfKnots; + + /// _______________ Suppress some parent class methods ________________________ + private: +#if !defined(GPUCA_GPUCODE) + using TBase::recreate; +#endif + using TBase::interpolateU; +}; + +/// ================================================================================================== +/// Specialization 2 (YdimT<=0) where the numbaer of Y dimensions +/// must be set in the runtime via a constructor parameter +/// +template <typename DataT, int YdimT> +class Spline2DSpec<DataT, YdimT, 2> + : public Spline2DSpec<DataT, YdimT, 0> +{ + typedef Spline2DContainer<DataT> TVeryBase; + typedef Spline2DSpec<DataT, YdimT, 0> TBase; + + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + +#if !defined(GPUCA_GPUCODE) + /// Default constructor + Spline2DSpec() : Spline2DSpec(0, 2, 2) {} + + /// Constructor for a regular spline + Spline2DSpec(int nYdim, int nKnotsX1, int nKnotsX2) : TBase() + { + TBase::recreate(nYdim, nKnotsX1, nKnotsX2); + } + + /// Constructor for an irregular spline + Spline2DSpec(int nYdim, int nKnotsX1, const int knotU1[], + int nKnotsX2, const int knotU2[]) : TBase() + { + TBase::recreate(nYdim, nKnotsX1, knotU1, nKnotsX2, knotU2); + } + + /// Copy constructor + Spline2DSpec(const Spline2DSpec& v) : TBase() + { + cloneFromObject(v, nullptr); + } + + /// Constructor for a regular spline + void recreate(int nYdim, int nKnotsX1, int nKnotsX2) + { + TBase::recreate(nYdim, nKnotsX1, nKnotsX2); + } + + /// Constructor for an irregular spline + void recreate(int nYdim, int nKnotsX1, const int knotU1[], + int nKnotsX2, const int knotU2[]) + { + TBase::recreate(nYdim, nKnotsX1, knotU1, nKnotsX2, knotU2); + } +#endif + + /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ + + using TBase::interpolateU; +}; + +/// ================================================================================================== +/// Specialization 3, where the number of Y dimensions is 1. +/// +template <typename DataT> +class Spline2DSpec<DataT, 1, 3> + : public Spline2DSpec<DataT, 1, SplineUtil::getSpec(999)> +{ + typedef Spline2DSpec<DataT, 1, SplineUtil::getSpec(999)> TBase; + + public: + using TBase::TBase; // inherit constructors + + /// Simplified interface for 1D: return the interpolated value + GPUd() DataT interpolate(DataT x1, DataT x2) const + { + DataT S = 0.; + TBase::interpolate(x1, x2, &S); + return S; + } + + // this parent method should be public anyhow, + // but w/o this extra declaration compiler gets confused + using TBase::interpolate; +}; +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/TPCFastTransformation/SplineHelper.cxx b/GPU/TPCFastTransformation/SplineHelper.cxx new file mode 100644 index 0000000000000..5c03c85a0b627 --- /dev/null +++ b/GPU/TPCFastTransformation/SplineHelper.cxx @@ -0,0 +1,544 @@ +// 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 SplineHelper.cxx +/// \brief Implementation of SplineHelper class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + +#include "SplineHelper.h" +#include "Spline2D.h" + +#include "TMath.h" +#include "TMatrixD.h" +#include "TVectorD.h" +#include "TDecompBK.h" + +#include <vector> +#include "TRandom.h" +#include "TMath.h" +#include "TCanvas.h" +#include "TNtuple.h" +#include "TFile.h" +#include "GPUCommonMath.h" +#include <iostream> + +using namespace GPUCA_NAMESPACE::gpu; + +template <typename DataT> +SplineHelper<DataT>::SplineHelper() : mError(), mXdimensions(0), mFdimensions(0), mNumberOfDataPoints(0), mHelpers() +{ +} + +template <typename DataT> +int SplineHelper<DataT>::storeError(int code, const char* msg) +{ + mError = msg; + return code; +} + +//////////////// +// pointstoarray +// HILFSFUNKTION, +template <typename DataT> +int SplineHelper<DataT>::pointstoarray(const int indices[], const int numbers[], int dim) +{ + + int result = 0; + int factor = 1; + for (int i = 0; i < dim; i++) { + result += indices[i] * factor; + factor *= numbers[i]; + } + return result; +} + +//////////////// +//arraytopoints +// HILFSFUNKTION +template <typename DataT> +int SplineHelper<DataT>::arraytopoints(int point, int result[], const int numbers[], int dim) +{ + + if (point == 0) { + for (int i = 0; i < dim; i++) { + result[i] = 0; + } + } else { + int divisor = 1; + int modoperand = 1; + for (int i = 0; i < dim; i++) { + modoperand *= numbers[i]; + result[i] = (int)((point % modoperand) / divisor); + divisor *= numbers[i]; + } + } + return 0; +} + +template <typename DataT> +void SplineHelper<DataT>::approximateFunction( + DataT* Fparameters, const double xMin[/* mXdimensions */], const double xMax[/* mXdimensions */], + std::function<void(const double x[/* mXdimensions */], double f[/* mFdimensions */])> F) const +{ + /// Create best-fit spline parameters for a given input function F + /// output in Fparameter + // TODO: implement + // MY VERSION + //std::cout << "approximateFunction(Fparameters, xMin[],xMax[],F) :" << std::endl; + double scaleX[mXdimensions]; + for (int i = 0; i < mXdimensions; i++) { + scaleX[i] = (xMax[i] - xMin[i]) / ((double)(mHelpers[i].getSpline().getUmax())); + } + + // calculate F-Values at all datapoints: + int nrOfAllPoints = getNumberOfDataPoints(); + std::vector<double> dataPointF(nrOfAllPoints * mFdimensions); + + int nrOfPoints[mXdimensions]; + for (int i = 0; i < mXdimensions; i++) { + nrOfPoints[i] = mHelpers[i].getNumberOfDataPoints(); + } + double x[mXdimensions]; + for (int d = 0; d < nrOfAllPoints; d++) { // for all DataPoints + + int indices[mXdimensions]; + int modoperand = 1; + int divisor = 1; + + // get the DataPoint index + for (int i = 0; i < mXdimensions; i++) { + modoperand *= nrOfPoints[i]; + + indices[i] = (int)((d % modoperand) / divisor); + divisor *= nrOfPoints[i]; + // get the respecting u-values: + x[i] = xMin[i] + mHelpers[i].getDataPoint(indices[i]).u * scaleX[i]; + } + + for (int j = 0; j < mXdimensions; j++) { + F(x, &dataPointF[d * mFdimensions]); + } + + } // end for all DataPoints d + //END MY VERSION + + //std::vector<DataT> dataPointF(getNumberOfDataPoints() * mFdimensions); + //DUMYY VERSION Commented out + /* for (int i = 0; i < getNumberOfDataPoints() * mFdimensions; i++) { + dataPointF[i] = 1.; + } */ + /* + double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax()); + double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax()); + + for (int iv = 0; iv < getNumberOfDataPointsU2(); iv++) { + DataT x2 = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2; + for (int iu = 0; iu < getNumberOfDataPointsU1(); iu++) { + DataT x1 = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1; + F(x1, x2, &dataPointF[(iv * getNumberOfDataPointsU1() + iu) * mFdimensions]); + } + } + */ + approximateFunction(Fparameters, dataPointF.data()); +} + +template <typename DataT> +void SplineHelper<DataT>::approximateFunctionBatch( + DataT* Fparameters, const double xMin[], const double xMax[], + std::function<void(const std::vector<double> x[], std::vector<double> f[/*mFdimensions*/])> F, + unsigned int batchsize) const +{ + /// Create best-fit spline parameters for a given input function F. + /// F calculates values for a batch of points. + /// output in Fparameters + + // TODO: implement later + + std::vector<double> dataPointF(getNumberOfDataPoints() * mFdimensions); + for (int i = 0; i < getNumberOfDataPoints() * mFdimensions; i++) { + dataPointF[i] = 0.; + } + + approximateFunction(Fparameters, dataPointF.data()); +} + +template <typename DataT> +void SplineHelper<DataT>::approximateFunction( + DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const +{ + /// approximate a function given as an array of values at data points + + int numberOfKnots[mXdimensions]; //getting number of Knots for all dimensions into one array + for (int i = 0; i < mXdimensions; i++) { + numberOfKnots[i] = mHelpers[i].getSpline().getNumberOfKnots(); + } + + int numberOfDataPoints[mXdimensions]; // getting number of datapoints (incl knots) in all dimensions into one array + for (int i = 0; i < mXdimensions; i++) { + numberOfDataPoints[i] = mHelpers[i].getNumberOfDataPoints(); + } + + int numberOfAllKnots = 1; // getting Number of all knots for the entire spline + for (int i = 0; i < mXdimensions; i++) { + numberOfAllKnots *= numberOfKnots[i]; + } + // TO BE REMOVED (TEST-OUTPUT): + std::cout << "total number of knots: " << numberOfAllKnots << ", " << std::endl; + + int numberOfAllDataPoints = 1; // getting Number of all Datapoints for the entire spline + for (int i = 0; i < mXdimensions; i++) { + numberOfAllDataPoints *= numberOfDataPoints[i]; + //std::cout << mHelpers[0].getNumberOfDataPoints()<<std::endl; + } + + // TO BE REMOVED TEST: + //std::cout << "total number of DataPoints (including knots): " << numberOfAllDataPoints << ", "<< std::endl; + + int numberOfParameterTypes = (int)(pow(2.0, mXdimensions)); //number of Parameters per Knot + + // TO BE REMOVED TEST: + //std::cout << "number of paramtertypes per knot : " << numberOfParameterTypes << ", "<< std::endl; + + std::unique_ptr<double[]> allParameters[numberOfParameterTypes]; //Array for the different parametertypes s, s'u, s'v, s''uv,... + for (int i = 0; i < numberOfParameterTypes; i++) { + allParameters[i] = std::unique_ptr<double[]>(new double[numberOfAllDataPoints * mFdimensions]); //To-Do:Fdim!! + } + //filling allParameters[0] and FParameters with s: + for (int i = 0; i < numberOfAllDataPoints; i++) { + for (int f = 0; f < mFdimensions; f++) { // for all f-dimensions + allParameters[0][i * mFdimensions + f] = DataPointF[i * mFdimensions + f]; // TO DO - Just get the pointer adress there PLEASE! + } + int p0indices[mXdimensions]; + arraytopoints(i, p0indices, numberOfDataPoints, mXdimensions); + bool isKnot = 1; + for (int j = 0; j < mXdimensions; j++) { // is the current datapoint a knot? + if (!mHelpers[j].getDataPoint(p0indices[j]).isKnot) { + isKnot = 0; + break; + } + } + if (isKnot) { + int knotindices[mXdimensions]; + for (int j = 0; j < mXdimensions; j++) { // calculate KNotindices for all dimensions + //WORKAROUND Getting Knotindices: + knotindices[j] = p0indices[j] / ((numberOfDataPoints[j] - 1) / (numberOfKnots[j] - 1)); + //knotindices[j] = mHelpers[j].getDataPoint(p0indices[j]).iKnot; //in der Annahme der wert ist ein Knotenindex und falls der datapoint ein knoten ist, gibt er seinen eigenen knotenindex zurück + } + // get the knotindexvalue for FParameters: + int knotind = pointstoarray(knotindices, numberOfKnots, mXdimensions); + + for (int f = 0; f < mFdimensions; f++) { // for all f-dimensions get function values into Fparameters + Fparameters[knotind * numberOfParameterTypes * mFdimensions + f] = DataPointF[i * mFdimensions + f]; ///write derivatives in FParameters + } + } // end if isKnot + } //end i (filling DataPointF Values into allParameters[0] and FParameters) + //now: allParameters[0] = dataPointF; + + //Array for input DataPointF-values for Spline1D::approximateFunctionGradually(...); + std::unique_ptr<double[]> dataPointF1D[mXdimensions]; + for (int i = 0; i < mXdimensions; i++) { + dataPointF1D[i] = std::unique_ptr<double[]>(new double[numberOfDataPoints[i] * mFdimensions]); // To-Do:Fdim!! For s and derivetives at all knots. + } + //Array to be filled by Spline1D::approximateFunctionGradually(...); + std::unique_ptr<DataT[]> par[mXdimensions]; + std::unique_ptr<double[]> parD[mXdimensions]; + + for (int i = 0; i < mXdimensions; i++) { + par[i] = std::unique_ptr<DataT[]>(new DataT[numberOfKnots[i] * mFdimensions * 2]); + parD[i] = std::unique_ptr<double[]>(new double[numberOfKnots[i] * mFdimensions * 2]); + } + + //std::cout << "NumberOfParameters: " << mNumberOfParameters <<std::endl; + + //STARTING MAIN-LOOP, for all Parametertypes: + for (int p = 1; p < numberOfParameterTypes; p++) { // p = 1!! Wir kriegen s (p0) durch approximateFunction()oben + int dimension; // find the dimension for approximation + for (int i = (int)(log2f((float)p)); i >= 0; i--) { + if (p % (int)(pow(2.0, i)) == 0) { + dimension = i; + break; + } + } + + int currentDataPointF = p - (int)(pow(2.0, dimension)); + //std::cout << std::endl << "p:" << p << ", dim of approximation: " << dimension << ", based on: " << currentDataPointF << std::endl; + + int nrOf1DSplines = (numberOfAllDataPoints / numberOfDataPoints[dimension]); // number of Splines for Parametertyp p in direction dim + //std::cout << "nr of splines: " << nrOf1DSplines; + + // getting the numbers of Datapoints for all dimension eccept the dimension of interpolation + int currentNumbers[mXdimensions - 1]; + for (int i = 0; i < dimension; i++) { + currentNumbers[i] = numberOfDataPoints[i]; + } + for (int i = dimension; i < mXdimensions - 1; i++) { + currentNumbers[i] = numberOfDataPoints[i + 1]; + } + ///std::cout << " current numbers: "; + for (int i = 0; i < mXdimensions - 1; i++) { + //std::cout << currentNumbers[i] << ","; + } + //std::cout << std::endl; + + //// for all Splines in current dimension: + for (int s = 0; s < nrOf1DSplines; s++) { + int indices[mXdimensions - 1]; + arraytopoints(s, indices, currentNumbers, mXdimensions - 1); + int startpoint[mXdimensions]; //startpoint for the current 1DSpline + for (int i = 0; i < dimension; i++) { + startpoint[i] = indices[i]; + } + startpoint[dimension] = 0; + for (int i = dimension + 1; i < mXdimensions; i++) { + startpoint[i] = indices[i - 1]; + } + // NOW WE HAVE THE DATAPOINTINDICES OF THE CURRENT STARTPOINT IN startpoint-Array. + int startdatapoint = pointstoarray(startpoint, numberOfDataPoints, mXdimensions); + int distance = 1; // distance to the next dataPoint in the array for the current dimension + for (int i = 0; i < dimension; i++) { + distance *= numberOfDataPoints[i]; + } + distance *= mFdimensions; + + for (int i = 0; i < numberOfDataPoints[dimension]; i++) { //Fill the dataPointF1D-Array + for (int f = 0; f < mFdimensions; f++) { + dataPointF1D[dimension][i * mFdimensions + f] = allParameters[currentDataPointF][startdatapoint * mFdimensions + (i * distance + f)]; // uiuiui index kuddelmuddel???!! + } + } + mHelpers[dimension].approximateFunction(par[dimension].get(), dataPointF1D[dimension].get()); + for (int i = 0; i < numberOfKnots[dimension] * mFdimensions * 2; i++) { + parD[dimension][i] = par[dimension][i]; + } + // now we have all s and s' values in par[dimension] + + int redistributionindex[mXdimensions]; + for (int i = 0; i < mXdimensions; i++) { + redistributionindex[i] = startpoint[i]; + } + //redistributing the derivatives at dimension-Knots into array p + for (int i = 0; i < numberOfKnots[dimension]; i++) { //for all dimension-Knots + redistributionindex[dimension] = mHelpers[dimension].getKnotDataPoint(i); //find the indices + int finalposition = pointstoarray(redistributionindex, numberOfDataPoints, mXdimensions); + + for (int f = 0; f < mFdimensions; f++) { + allParameters[p][finalposition * mFdimensions + f] = par[dimension][2 * i * mFdimensions + mFdimensions + f]; + } + + bool isKnot = 1; + for (int j = 0; j < mXdimensions; j++) { //is dataPoint a knot? + if (!mHelpers[j].getDataPoint(redistributionindex[j]).isKnot) { + isKnot = 0; + break; + } //noch mal checken!! Das muss noch anders!! + } + + if (isKnot) { // for all knots + int knotindices[mXdimensions]; + + for (int j = 0; j < mXdimensions; j++) { // calculate Knotindices for all dimensions + knotindices[j] = redistributionindex[j] / ((numberOfDataPoints[j] - 1) / (numberOfKnots[j] - 1)); + //knotindices[j] = mHelpers[j].getDataPoint(redistributionindex[j]).iKnot; //in der Annahme der wert ist ein Knotenindex und falls der datapoint ein knoten ist, gibt er seinen eigenen knotenindex zurück + } + // get the knotindexvalue for FParameters: + int knotind = pointstoarray(knotindices, numberOfKnots, mXdimensions); + for (int f = 0; f < mFdimensions; f++) + Fparameters[knotind * numberOfParameterTypes * mFdimensions + p * mFdimensions + f] = par[dimension][2 * i * mFdimensions + mFdimensions + f]; ///write derivatives in FParameters + } + } // end for all fknots (for redistribution) + + // recalculation: + for (int i = 0; i < numberOfDataPoints[dimension]; i++) { // this is somehow still redundant// TO DO: ONLY PART OF approximateFunction WHERE NDIM is considerd!! + redistributionindex[dimension] = i; // getting current datapointindices + bool isKnot = 1; // check is current datapoint a knot? + for (int j = 0; j < mXdimensions; j++) { + if (!mHelpers[j].getDataPoint(redistributionindex[j]).isKnot) { + isKnot = 0; + break; + } + } + double splineF[mFdimensions]; + double u = mHelpers[dimension].getDataPoint(i).u; + mHelpers[dimension].getSpline().interpolateU(mFdimensions, parD[dimension].get(), u, splineF); //recalculate at all datapoints of dimension + for (int dim = 0; dim < mFdimensions; dim++) { //writing it in allParameters + //std::cout<<allParameters [p-(int)(pow(2.0, dimension))] [(int)(startdatapoint*mFdimensions + i*distance + dim)]<<", "; + allParameters[p - (int)(pow(2.0, dimension))][(int)(startdatapoint * mFdimensions + i * distance + dim)] = splineF[dim]; //write it in the array. + //std::cout<<allParameters [p-(int)(pow(2.0, dimension))] [(int)(startdatapoint*mFdimensions + i*distance + dim)]<<", "; + } + + if (isKnot) { + int knotindices[mXdimensions]; + + for (int j = 0; j < mXdimensions; j++) { // calculate KNotindices for all dimensions + knotindices[j] = redistributionindex[j] / ((numberOfDataPoints[j] - 1) / (numberOfKnots[j] - 1)); + //knotindices[j] = mHelpers[j].getDataPoint(redistributionindex[j]).iKnot; //in der Annahme der wert ist ein Knotenindex und falls der datapoint ein knoten ist, gibt er seinen eigenen knotenindex zurück + } + int currentknotarrayindex = pointstoarray(knotindices, numberOfKnots, mXdimensions); + // getting the recalculated value into FParameters: + for (int f = 0; f < mFdimensions; f++) { + Fparameters[currentknotarrayindex * numberOfParameterTypes * mFdimensions + (p - (int)(pow(2.0, dimension))) * mFdimensions + f] = splineF[f]; + } + } // end if isKnot + } // end recalculation + } //end of all1DSplines + } //end of for parametertypes +} //end of approxymateFunction MYVERSION! + +template <typename DataT> +int SplineHelper<DataT>::test(const bool draw, const bool drawDataPoints) +{ + // Test method + + using namespace std; + + constexpr int nDimX = 2; + constexpr int nDimY = 2; + constexpr int Fdegree = 4; + + double xMin[nDimX]; + double xMax[nDimX]; + int nKnots[nDimX]; + int* knotsU[nDimX]; + int nAxiliaryDatapoints[nDimX]; + + for (int i = 0; i < nDimX; i++) { + xMin[i] = 0.; + xMax[i] = 1.; + nKnots[i] = 4; + knotsU[i] = new int[nKnots[i]]; + nAxiliaryDatapoints[i] = 4; + } + + // Function F + const int nTerms1D = 2 * (Fdegree + 1); + int nFcoeff = nDimY; + for (int i = 0; i < nDimX; i++) { + nFcoeff *= nTerms1D; + } + + double Fcoeff[nFcoeff]; + + auto F = [&](const double x[nDimX], double f[nDimY]) { + double a[nFcoeff]; + a[0] = 1; + int na = 1; + for (int d = 0; d < nDimX; d++) { + double b[nFcoeff]; + int nb = 0; + double t = (x[d] - xMin[d]) * TMath::Pi() / (xMax[d] - xMin[d]); + for (int i = 0; i < nTerms1D; i++) { + double c = (i % 2) ? cos((i / 2) * t) : cos((i / 2) * t); + for (int j = 0; j < na; j++) { + b[nb++] = c * a[j]; + assert(nb <= nFcoeff); + } + } + na = nb; + for (int i = 0; i < nb; i++) { + a[i] = b[i]; + } + } + + double* c = Fcoeff; + for (int dim = 0; dim < nDimY; dim++) { + f[dim] = 0; + for (int i = 0; i < na; i++) { + f[dim] += a[i] * (*c++); + } + } + }; + + auto F2D = [&](double x1, double x2, double f[nDimY]) { + double x[2] = {x1, x2}; + F(x, f); + }; + + for (int seed = 1; seed < 10; seed++) { + + gRandom->SetSeed(seed); + + // getting the coefficents filled randomly + for (int i = 0; i < nFcoeff; i++) { + Fcoeff[i] = gRandom->Uniform(-1, 1); + } + + for (int i = 0; i < nDimX; i++) { + knotsU[i][0] = 0; + for (int j = 1; j < nKnots[i]; j++) { + knotsU[i][j] = j * 4; //+ int(gRandom->Integer(3)) - 1; + } + } + + o2::gpu::Spline<float, nDimX, nDimY> spline(nKnots, knotsU); + o2::gpu::Spline2D<float, nDimY> spline2D(nKnots[0], knotsU[0], nKnots[1], knotsU[1]); + + cout << "mark 1" << std::endl; + spline.approximateFunction(xMin, xMax, F, nAxiliaryDatapoints); + spline2D.approximateFunction(xMin[0], xMax[0], xMin[1], xMax[1], + F2D, nAxiliaryDatapoints[0], nAxiliaryDatapoints[0]); + cout << "mark 2" << std::endl; + + long double statDf = 0; + long double statDf2D = 0; + + long double statN = 0; + + double x[nDimX]; + for (int i = 0; i < nDimX; i++) { + x[i] = xMin[i]; + } + do { + float xf[nDimX]; + float s[nDimY]; + float s2D[nDimY]; + double f[nDimY]; + for (int i = 0; i < nDimX; i++) { + xf[i] = x[i]; + } + F(x, f); + spline.interpolate(xf, s); + spline2D.interpolate(xf[0], xf[1], s2D); + + for (int dim = 0; dim < nDimY; dim++) { + statDf += (s[dim] - f[dim]) * (s[dim] - f[dim]); + statDf2D += (s2D[dim] - f[dim]) * (s2D[dim] - f[dim]); + statN++; + } + int dim = 0; + for (; dim < nDimX; dim++) { + x[dim] += 0.01; + if (x[dim] <= xMax[dim]) { + break; + } + x[dim] = xMin[dim]; + } + if (dim >= nDimX) { + break; + } + } while (1); + + cout << "\n std dev for SplineND : " << sqrt(statDf / statN) << std::endl; + cout << "\n std dev for Spline2D : " << sqrt(statDf2D / statN) << std::endl; + + } // seed + + for (int i = 0; i < nDimX; i++) { + delete[] knotsU[i]; + } + + return 0; +} + +template class GPUCA_NAMESPACE::gpu::SplineHelper<float>; +template class GPUCA_NAMESPACE::gpu::SplineHelper<double>; + +#endif diff --git a/GPU/TPCFastTransformation/SplineHelper.h b/GPU/TPCFastTransformation/SplineHelper.h new file mode 100644 index 0000000000000..fce2ef1aa12e9 --- /dev/null +++ b/GPU/TPCFastTransformation/SplineHelper.h @@ -0,0 +1,164 @@ +// 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 SplineHelper.h +/// \brief Definition of SplineHelper class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEHELPER_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEHELPER_H + +#include <cmath> +#include <vector> + +#include "GPUCommonDef.h" +#include "Rtypes.h" +#include "TString.h" +#include "Spline1D.h" +#include "Spline.h" +#include "Spline1DHelper.h" +#include <functional> + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ + +/// +/// The SplineHelper class is to initialize Spline* objects +/// +template <typename DataT> +class SplineHelper +{ + public: + /// _____________ Constructors / destructors __________________________ + + /// Default constructor + SplineHelper(); + + /// Copy constructor: disabled + SplineHelper(const SplineHelper&) CON_DELETE; + + /// Assignment operator: disabled + SplineHelper& operator=(const SplineHelper&) CON_DELETE; + + /// Destructor + ~SplineHelper() CON_DEFAULT; + + /// _______________ Main functionality ________________________ + + /// Create best-fit spline parameters for a given input function F + void approximateFunction(SplineContainer<DataT>& spline, + const double xMin[/* Xdim */], const double xMax[/* Xdim */], + std::function<void(const double x[/* Xdim */], double f[/* Fdim */])> F, + const int nAxiliaryDataPoints[/* Xdim */] = nullptr); + + /// _______________ Interface for a step-wise construction of the best-fit spline ________________________ + + /// precompute everything needed for the construction + int setSpline(const SplineContainer<DataT>& spline, const int nAxiliaryPoints[/* Xdim */]); + + /// approximate std::function, output in Fparameters + void approximateFunction( + DataT* Fparameters, const double xMin[/* mXdimensions */], const double xMax[/* mXdimensions */], + std::function<void(const double x[/* mXdimensions */], double f[/* mFdimensions */])> F) const; + + /// approximate std::function, output in Fparameters. F calculates values for a batch of points. + void approximateFunctionBatch( + DataT* Fparameters, const double xMin[/* mXdimensions */], const double xMax[/* mXdimensions */], + std::function<void(const std::vector<double> x[/* mXdimensions */], std::vector<double> f[/*mFdimensions*/])> F, + unsigned int batchsize) const; + + /// approximate a function given as an array of values at data points + void approximateFunction( + DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; + + int getNumberOfDataPoints(int dimX) const { return mHelpers[dimX].getNumberOfDataPoints(); } + + int getNumberOfDataPoints() const { return mNumberOfDataPoints; } + + const Spline1DHelper<DataT>& getHelper(int dimX) const { return mHelpers[dimX]; } + + /// _______________ Utilities ________________________ + + /// Gives error string + const char* getLastError() const { return mError.Data(); } + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// Test the Spline class functionality + static int test(const bool draw = 0, const bool drawDataPoints = 1); +#endif + + static int arraytopoints(int point, int result[], const int numbers[], int dim); + + static int pointstoarray(const int indices[], const int numbers[], int dim); + + private: + /// Stores an error message + int storeError(Int_t code, const char* msg); + + TString mError = ""; ///< error string + int mXdimensions; ///< number of X dimensions + int mFdimensions; ///< number of F dimensions + int mNumberOfParameters; ///< number of parameters + int mNumberOfDataPoints; ///< number of data points + std::vector<Spline1DHelper<DataT>> mHelpers; +}; + +template <typename DataT> +void SplineHelper<DataT>::approximateFunction( + SplineContainer<DataT>& spline, + const double xMin[/* Xdim */], const double xMax[/* Xdim */], + std::function<void(const double x[/* Xdim */], double f[/* Fdim */])> F, + const int nAxiliaryDataPoints[/* Xdim */]) +{ + /// Create best-fit spline parameters for a given input function F + setSpline(spline, nAxiliaryDataPoints); + approximateFunction(spline.getParameters(), xMin, xMax, F); + DataT xxMin[spline.getXdimensions()]; + DataT xxMax[spline.getXdimensions()]; + for (int i = 0; i < spline.getXdimensions(); i++) { + xxMin[i] = xMin[i]; + xxMax[i] = xMax[i]; + } + spline.setXrange(xxMin, xxMax); +} + +template <typename DataT> +int SplineHelper<DataT>::setSpline( + const SplineContainer<DataT>& spline, const int nAxiliaryPoints[/* Xdim */]) +{ + // Prepare creation of an irregular spline + // The should be at least one (better, two) axiliary measurements on each segnment between two knots and at least 2*nKnots measurements in total + // Returns 0 when the spline can not be constructed with the given nAxiliaryPoints + + int ret = 0; + mXdimensions = spline.getXdimensions(); + mFdimensions = spline.getYdimensions(); + mNumberOfParameters = spline.getNumberOfParameters(); + mNumberOfDataPoints = 1; + mHelpers.clear(); + mHelpers.resize(mXdimensions); + for (int i = 0; i < mXdimensions; i++) { + int np = (nAxiliaryPoints != nullptr) ? nAxiliaryPoints[i] : 4; + if (mHelpers[i].setSpline(spline.getGrid(i), mFdimensions, np) != 0) { + ret = storeError(-2, "SplineHelper::setSpline: error by setting an axis"); + } + mNumberOfDataPoints *= mHelpers[i].getNumberOfDataPoints(); + } + + return ret; +} + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/TPCFastTransformation/SplineHelper1D.cxx b/GPU/TPCFastTransformation/SplineHelper1D.cxx deleted file mode 100644 index d9f4013e4bb3c..0000000000000 --- a/GPU/TPCFastTransformation/SplineHelper1D.cxx +++ /dev/null @@ -1,477 +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. - -/// \file SplineHelper1D.cxx -/// \brief Implementation of SplineHelper1D class -/// -/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) - -#include "SplineHelper1D.h" -#include "TMath.h" -#include "TMatrixD.h" -#include "TVectorD.h" -#include "TDecompBK.h" - -using namespace GPUCA_NAMESPACE::gpu; - -template <typename DataT> -SplineHelper1D<DataT>::SplineHelper1D() : mError(), mSpline(), mFdimensions(0) -{ -} - -template <typename DataT> -int SplineHelper1D<DataT>::storeError(int code, const char* msg) -{ - mError = msg; - return code; -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateFunctionClassic(Spline1D<DataT>& spline, - DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[/*spline.getFdimensions()*/])> F) -{ - /// Create classic spline parameters for a given input function F - /// set slopes at the knots such, that the second derivative of the spline is continious. - - int Ndim = spline.getFdimensions(); - const int nKnots = spline.getNumberOfKnots(); - - TMatrixD A(nKnots, nKnots); - - A.Zero(); - - /* - const Spline1D::Knot& knot0 = spline.getKnot(i); - double x = (u - knot0.u) * knot0.Li; // scaled u - double cS1 = (6 - 12*x)*knot0.Li*knot0.Li; - double cZ0 = (6*x-4)*knot0.Li; - double cZ1 = (6*x-2)*knot0.Li; - // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; - */ - - // second derivative at knot0 is 0 - { - const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(0); - double cZ0 = (-4) * knot0.Li; - double cZ1 = (-2) * knot0.Li; - // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; - A(0, 0) = cZ0; - A(0, 1) = cZ1; - } - - // second derivative at knot nKnots-1 is 0 - { - const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(nKnots - 2); - double cZ0 = (6 - 4) * knot0.Li; - double cZ1 = (6 - 2) * knot0.Li; - // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; - A(nKnots - 1, nKnots - 2) = cZ0; - A(nKnots - 1, nKnots - 1) = cZ1; - } - - // second derivative at other knots is same from the left and from the right - for (int i = 1; i < nKnots - 1; i++) { - const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(i - 1); - double cZ0 = (6 - 4) * knot0.Li; - double cZ1_0 = (6 - 2) * knot0.Li; - // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; - - const typename Spline1D<DataT>::Knot& knot1 = spline.getKnot(i); - double cZ1_1 = (-4) * knot1.Li; - double cZ2 = (-2) * knot1.Li; - // f''(u) = cS2*(f2-f1) + cZ1_1*z1 + cZ2*z2; - A(i, i - 1) = cZ0; - A(i, i) = cZ1_0 - cZ1_1; - A(i, i + 1) = -cZ2; - } - - A.Invert(); - - spline.setXrange(xMin, xMax); - DataT* parameters = spline.getFparameters(); - - TVectorD b(nKnots); - b.Zero(); - - double uToXscale = (((double)xMax) - xMin) / spline.getUmax(); - - for (int i = 0; i < nKnots; ++i) { - const typename Spline1D<DataT>::Knot& knot = spline.getKnot(i); - double u = knot.u; - DataT f[Ndim]; - F(xMin + u * uToXscale, f); - for (int dim = 0; dim < Ndim; dim++) { - parameters[(2 * i) * Ndim + dim] = f[dim]; - } - } - - for (int dim = 0; dim < Ndim; dim++) { - - // second derivative at knot0 is 0 - { - double f0 = parameters[(2 * 0) * Ndim + dim]; - double f1 = parameters[(2 * 1) * Ndim + dim]; - const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(0); - double cS1 = (6) * knot0.Li * knot0.Li; - // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; - b(0) = -cS1 * (f1 - f0); - } - - // second derivative at knot nKnots-1 is 0 - { - double f0 = parameters[2 * (nKnots - 2) * Ndim + dim]; - double f1 = parameters[2 * (nKnots - 1) * Ndim + dim]; - const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(nKnots - 2); - double cS1 = (6 - 12) * knot0.Li * knot0.Li; - // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; - b(nKnots - 1) = -cS1 * (f1 - f0); - } - - // second derivative at other knots is same from the left and from the right - for (int i = 1; i < nKnots - 1; i++) { - double f0 = parameters[2 * (i - 1) * Ndim + dim]; - double f1 = parameters[2 * (i)*Ndim + dim]; - double f2 = parameters[2 * (i + 1) * Ndim + dim]; - const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(i - 1); - double cS1 = (6 - 12) * knot0.Li * knot0.Li; - // f''(u) = cS1*(f1-f0) + cZ0*z0 + cZ1*z1; - - const typename Spline1D<DataT>::Knot& knot1 = spline.getKnot(i); - double cS2 = (6) * knot1.Li * knot1.Li; - // f''(u) = cS2*(f2-f1) + cZ1_1*z1 + cZ2*z2; - b(i) = -cS1 * (f1 - f0) + cS2 * (f2 - f1); - } - - TVectorD c = A * b; - for (int i = 0; i < nKnots; i++) { - parameters[(2 * i + 1) * Ndim + dim] = c[i]; - } - } -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateFunction( - Spline1D<DataT>& spline, DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[/*spline.getFdimensions()*/])> F, - int nAxiliaryDataPoints) -{ - /// Create best-fit spline parameters for a given input function F - setSpline(spline, spline.getFdimensions(), nAxiliaryDataPoints); - approximateFunction(spline.getFparameters(), xMin, xMax, F); - spline.setXrange(xMin, xMax); -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateFunctionGradually( - Spline1D<DataT>& spline, DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[/*spline.getFdimensions()*/])> F, - int nAxiliaryDataPoints) -{ - /// Create best-fit spline parameters gradually for a given input function F - setSpline(spline, spline.getFdimensions(), nAxiliaryDataPoints); - approximateFunctionGradually(spline.getFparameters(), xMin, xMax, F); - spline.setXrange(xMin, xMax); -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateFunction( - DataT* Fparameters, DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[])> F) const -{ - /// Create best-fit spline parameters for a given input function F - /// output in Fparameters - std::vector<DataT> vF(getNumberOfDataPoints() * mFdimensions); - double mUtoXscale = (((double)xMax) - xMin) / mSpline.getUmax(); - for (int i = 0; i < getNumberOfDataPoints(); i++) { - F(xMin + mUtoXscale * mDataPoints[i].u, &vF[i * mFdimensions]); - } - approximateFunction(Fparameters, vF.data()); -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateFunctionGradually( - DataT* Fparameters, DataT xMin, DataT xMax, std::function<void(DataT x, DataT f[])> F) const -{ - /// Create best-fit spline parameters gradually for a given input function F - /// output in Fparameters - std::vector<DataT> vF(getNumberOfDataPoints() * mFdimensions); - double mUtoXscale = (((double)xMax) - xMin) / mSpline.getUmax(); - for (int i = 0; i < getNumberOfDataPoints(); i++) { - F(xMin + mUtoXscale * mDataPoints[i].u, &vF[i * mFdimensions]); - } - approximateFunctionGradually(Fparameters, vF.data()); -} - -template <typename DataT> -int SplineHelper1D<DataT>::setSpline( - const Spline1D<DataT>& spline, int nFdimensions, int nAxiliaryDataPoints) -{ - // Prepare creation of a best-fit spline - // - // Data points will be set at all integer U (that includes all knots), - // plus at nAxiliaryDataPoints points between the integers. - // - // nAxiliaryDataPoints must be >= 2 - // - // nAxiliaryDataPoints==1 is also possible, but there must be at least - // one integer U without a knot, in order to get 2*nKnots data points in total. - // - // The return value is an error index, 0 means no error - - int ret = 0; - - mSpline.cloneFromObject(spline, nullptr); - mFdimensions = nFdimensions; - int nPoints = 0; - if (!spline.isConstructed()) { - ret = storeError(-1, "SplineHelper1D<DataT>::setSpline: input spline is not constructed"); - mSpline.recreate(2, 0); - nAxiliaryDataPoints = 2; - nPoints = 4; - } else { - mSpline.cloneFromObject(spline, nullptr); - nPoints = 1 + spline.getUmax() + spline.getUmax() * nAxiliaryDataPoints; - if (nPoints < 2 * spline.getNumberOfKnots()) { - nAxiliaryDataPoints = 2; - nPoints = 1 + spline.getUmax() + spline.getUmax() * nAxiliaryDataPoints; - ret = storeError(-3, "SplineHelper1D::setSpline: too few nAxiliaryDataPoints, increase to 2"); - } - } - - const int nPar = mSpline.getNumberOfParameters(1); // n parameters for 1D - - mDataPoints.resize(nPoints); - double scalePoints2Knots = ((double)spline.getUmax()) / (nPoints - 1.); - - for (int i = 0; i < nPoints; ++i) { - DataPoint& p = mDataPoints[i]; - double u = i * scalePoints2Knots; - int iKnot = spline.getKnotIndexU(u); - const typename Spline1D<DataT>::Knot& knot0 = spline.getKnot(iKnot); - const typename Spline1D<DataT>::Knot& knot1 = spline.getKnot(iKnot + 1); - double l = knot1.u - knot0.u; - double s = (u - knot0.u) * knot0.Li; // scaled u - double s2 = s * s; - double sm1 = s - 1.; - - p.iKnot = iKnot; - p.isKnot = 0; - p.u = u; - p.cS1 = s2 * (3. - 2. * s); - p.cS0 = 1. - p.cS1; - p.cZ0 = s * sm1 * sm1 * l; - p.cZ1 = s2 * sm1 * l; - } - - const int nKnots = mSpline.getNumberOfKnots(); - - mKnotDataPoints.resize(nKnots); - - for (int i = 0; i < nKnots; ++i) { - const typename Spline1D<DataT>::Knot& knot = spline.getKnot(i); - int iu = (int)(knot.u + 0.1f); - mKnotDataPoints[i] = iu * (1 + nAxiliaryDataPoints); - mDataPoints[mKnotDataPoints[i]].isKnot = 1; - } - - TMatrixDSym A(nPar); - A.Zero(); - - for (int i = 0; i < nPoints; ++i) { - DataPoint& p = mDataPoints[i]; - int j = p.iKnot * 2; - A(j + 0, j + 0) += p.cS0 * p.cS0; - A(j + 1, j + 0) += p.cS0 * p.cZ0; - A(j + 2, j + 0) += p.cS0 * p.cS1; - A(j + 3, j + 0) += p.cS0 * p.cZ1; - - A(j + 1, j + 1) += p.cZ0 * p.cZ0; - A(j + 2, j + 1) += p.cZ0 * p.cS1; - A(j + 3, j + 1) += p.cZ0 * p.cZ1; - - A(j + 2, j + 2) += p.cS1 * p.cS1; - A(j + 3, j + 2) += p.cS1 * p.cZ1; - - A(j + 3, j + 3) += p.cZ1 * p.cZ1; - } - - // copy symmetric matrix elements - - for (int i = 0; i < nPar; i++) { - for (int j = i + 1; j < nPar; j++) { - A(i, j) = A(j, i); - } - } - - TMatrixDSym Z(nKnots); - mLSMmatrixSvalues.resize(nKnots * nKnots); - for (int i = 0, k = 0; i < nKnots; i++) { - for (int j = 0; j < nKnots; j++, k++) { - mLSMmatrixSvalues[k] = A(i * 2 + 1, j * 2); - Z(i, j) = A(i * 2 + 1, j * 2 + 1); - } - } - - { - TDecompBK bk(A, 0); - bool ok = bk.Invert(A); - - if (!ok) { - ret = storeError(-4, "SplineHelper1D::setSpline: internal error - can not invert the matrix"); - A.Zero(); - } - mLSMmatrixFull.resize(nPar * nPar); - for (int i = 0, k = 0; i < nPar; i++) { - for (int j = 0; j < nPar; j++, k++) { - mLSMmatrixFull[k] = A(i, j); - } - } - } - - { - TDecompBK bk(Z, 0); - if (!bk.Invert(Z)) { - ret = storeError(-5, "SplineHelper1D::setSpline: internal error - can not invert the matrix"); - Z.Zero(); - } - mLSMmatrixSderivatives.resize(nKnots * nKnots); - for (int i = 0, k = 0; i < nKnots; i++) { - for (int j = 0; j < nKnots; j++, k++) { - mLSMmatrixSderivatives[k] = Z(i, j); - } - } - } - - return ret; -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateFunction( - DataT* Fparameters, - const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const -{ - /// Approximate a function given as an array of values at data points - - const int nPar = mSpline.getNumberOfParameters(1); - double b[nPar]; - for (int idim = 0; idim < mFdimensions; idim++) { - for (int i = 0; i < nPar; i++) { - b[i] = 0.; - } - - for (int i = 0; i < getNumberOfDataPoints(); ++i) { - const DataPoint& p = mDataPoints[i]; - double* bb = &(b[p.iKnot * 2]); - double f = (double)DataPointF[i * mFdimensions + idim]; - bb[0] += f * p.cS0; - bb[1] += f * p.cZ0; - bb[2] += f * p.cS1; - bb[3] += f * p.cZ1; - } - - const double* row = mLSMmatrixFull.data(); - - for (int i = 0; i < nPar; i++, row += nPar) { - double s = 0.; - for (int j = 0; j < nPar; j++) { - s += row[j] * b[j]; - } - Fparameters[i * mFdimensions + idim] = (float)s; - } - } -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateFunctionGradually( - DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim */]) const -{ - /// gradually approximate a function given as an array of values at data points - /// output in Fparameters - copySfromDataPoints(Fparameters, DataPointF); - approximateDerivatives(Fparameters, DataPointF); -} - -template <typename DataT> -void SplineHelper1D<DataT>::copySfromDataPoints( - DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const -{ - /// a tool for the gradual approximation: set spline values S_i at knots == function values - /// output in Fparameters - for (int i = 0; i < mSpline.getNumberOfKnots(); ++i) { // set F values at knots - int ip = mKnotDataPoints[i]; - for (int d = 0; d < mFdimensions; d++) { - Fparameters[2 * i * mFdimensions + d] = DataPointF[ip * mFdimensions + d]; - } - } -} - -template <typename DataT> -void SplineHelper1D<DataT>::approximateDerivatives( - DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const -{ - /// a tool for the gradual approximation: - /// calibrate spline derivatives D_i using already calibrated spline values S_i - /// input and output output in Fparameters - - const int nKnots = mSpline.getNumberOfKnots(); - const int Ndim = mFdimensions; - double b[nKnots * mFdimensions]; - for (int i = 0; i < nKnots * Ndim; i++) { - b[i] = 0.; - } - - for (int i = 0; i < getNumberOfDataPoints(); ++i) { - const DataPoint& p = mDataPoints[i]; - if (p.isKnot) { - continue; - } - for (int d = 0; d < Ndim; d++) { - double f = (double)DataPointF[i * Ndim + d]; - b[(p.iKnot + 0) * Ndim + d] += f * p.cZ0; - b[(p.iKnot + 1) * Ndim + d] += f * p.cZ1; - } - } - - const double* row = mLSMmatrixSvalues.data(); - for (int i = 0; i < nKnots; ++i, row += nKnots) { - double s[Ndim]; - for (int d = 0; d < Ndim; d++) { - s[d] = 0.; - } - for (int j = 0; j < nKnots; ++j) { - for (int d = 0; d < Ndim; d++) { - s[d] += row[j] * Fparameters[2 * j * Ndim + d]; - } - } - for (int d = 0; d < Ndim; d++) { - b[i * Ndim + d] -= s[d]; - } - } - - row = mLSMmatrixSderivatives.data(); - for (int i = 0; i < nKnots; ++i, row += nKnots) { - double s[Ndim]; - for (int d = 0; d < Ndim; d++) { - s[d] = 0.; - } - for (int j = 0; j < nKnots; ++j) { - for (int d = 0; d < Ndim; d++) { - s[d] += row[j] * b[j * Ndim + d]; - } - } - for (int d = 0; d < Ndim; d++) { - Fparameters[(2 * i + 1) * Ndim + d] = (float)s[d]; - } - } -} - -template class GPUCA_NAMESPACE::gpu::SplineHelper1D<float>; -template class GPUCA_NAMESPACE::gpu::SplineHelper1D<double>; - -#endif diff --git a/GPU/TPCFastTransformation/SplineHelper2D.cxx b/GPU/TPCFastTransformation/SplineHelper2D.cxx deleted file mode 100644 index 51aee34911eaa..0000000000000 --- a/GPU/TPCFastTransformation/SplineHelper2D.cxx +++ /dev/null @@ -1,213 +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. - -/// \file Spline182.cxx -/// \brief Implementation of SplineHelper2D class -/// -/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> - -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) - -#include "SplineHelper2D.h" -#include "TMath.h" -#include "TMatrixD.h" -#include "TVectorD.h" -#include "TDecompBK.h" - -using namespace GPUCA_NAMESPACE::gpu; - -template <typename DataT> -SplineHelper2D<DataT>::SplineHelper2D() : mError(), mFdimensions(0), mHelperU1(), mHelperU2() -{ -} - -template <typename DataT> -int SplineHelper2D<DataT>::storeError(int code, const char* msg) -{ - mError = msg; - return code; -} - -template <typename DataT> -void SplineHelper2D<DataT>::approximateFunction( - DataT* Fparameters, DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(DataT x1, DataT x2, DataT f[/*spline.getFdimensions()*/])> F) const -{ - /// Create best-fit spline parameters for a given input function F - /// output in Fparameters - - std::vector<DataT> dataPointF(getNumberOfDataPoints() * mFdimensions); - - double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax()); - double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax()); - - for (int iv = 0; iv < getNumberOfDataPointsU2(); iv++) { - DataT x2 = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2; - for (int iu = 0; iu < getNumberOfDataPointsU1(); iu++) { - DataT x1 = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1; - F(x1, x2, &dataPointF[(iv * getNumberOfDataPointsU1() + iu) * mFdimensions]); - } - } - approximateFunction(Fparameters, dataPointF.data()); -} - -template <typename DataT> -void SplineHelper2D<DataT>::approximateFunctionBatch( - DataT* Fparameters, DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(const std::vector<DataT>& x1, const std::vector<DataT>& x2, std::vector<DataT> f[/*mFdimensions*/])> F, - unsigned int batchsize) const -{ - /// Create best-fit spline parameters for a given input function F. - /// F calculates values for a batch of points. - /// output in Fparameters - - std::vector<DataT> dataPointF(getNumberOfDataPoints() * mFdimensions); - - double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax()); - double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax()); - - std::vector<DataT> x1; - x1.reserve(batchsize); - - std::vector<DataT> x2; - x2.reserve(batchsize); - - std::vector<int> index; - index.reserve(batchsize); - - std::vector<DataT> dataPointFTmp[mFdimensions]; - for (unsigned int iDim = 0; iDim < mFdimensions; ++iDim) { - dataPointFTmp[iDim].reserve(batchsize); - } - - unsigned int counter = 0; - for (int iv = 0; iv < getNumberOfDataPointsU2(); iv++) { - DataT x2Tmp = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2; - for (int iu = 0; iu < getNumberOfDataPointsU1(); iu++) { - DataT x1Tmp = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1; - x1.emplace_back(x1Tmp); - x2.emplace_back(x2Tmp); - index.emplace_back((iv * getNumberOfDataPointsU1() + iu) * mFdimensions); - ++counter; - - if (counter == batchsize || (iu == (getNumberOfDataPointsU1() - 1) && (iv == (getNumberOfDataPointsU2() - 1)))) { - counter = 0; - F(x1, x2, dataPointFTmp); - unsigned int entries = index.size(); - - for (unsigned int i = 0; i < entries; ++i) { - const unsigned int indexTmp = index[i]; - for (unsigned int iDim = 0; iDim < mFdimensions; ++iDim) { - dataPointF[indexTmp + iDim] = dataPointFTmp[iDim][i]; - } - } - - x1.clear(); - x2.clear(); - index.clear(); - for (unsigned int iDim = 0; iDim < mFdimensions; ++iDim) { - dataPointFTmp[iDim].clear(); - } - } - } - } - approximateFunction(Fparameters, dataPointF.data()); -} - -template <typename DataT> -void SplineHelper2D<DataT>::approximateFunction( - DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const -{ - /// approximate a function given as an array of values at data points - - const int Ndim = mFdimensions; - const int Ndim2 = 2 * Ndim; - const int Ndim3 = 3 * Ndim; - const int Ndim4 = 4 * Ndim; - - int nDataPointsU = getNumberOfDataPointsU1(); - int nDataPointsV = getNumberOfDataPointsU2(); - - int nKnotsU = mHelperU1.getSpline().getNumberOfKnots(); - int nKnotsV = mHelperU2.getSpline().getNumberOfKnots(); - - std::unique_ptr<DataT[]> rotDataPointF(new DataT[nDataPointsU * nDataPointsV * Ndim]); // U DataPoints x V DataPoints : rotated DataPointF for one output dimension - std::unique_ptr<DataT[]> Dv(new DataT[nKnotsV * nDataPointsU * Ndim]); // V knots x U DataPoints - - std::unique_ptr<DataT[]> parU(new DataT[mHelperU1.getSpline().getNumberOfParameters(Ndim)]); - std::unique_ptr<DataT[]> parV(new DataT[mHelperU2.getSpline().getNumberOfParameters(Ndim)]); - - // rotated data points (u,v)->(v,u) - - for (int ipu = 0; ipu < nDataPointsU; ipu++) { - for (int ipv = 0; ipv < nDataPointsV; ipv++) { - for (int dim = 0; dim < Ndim; dim++) { - rotDataPointF[Ndim * (ipu * nDataPointsV + ipv) + dim] = DataPointF[Ndim * (ipv * nDataPointsU + ipu) + dim]; - } - } - } - - // get S and S'u at all the knots by interpolating along the U axis - - for (int iKnotV = 0; iKnotV < nKnotsV; ++iKnotV) { - int ipv = mHelperU2.getKnotDataPoint(iKnotV); - const DataT* DataPointFrow = &(DataPointF[Ndim * ipv * nDataPointsU]); - mHelperU1.approximateFunctionGradually(parU.get(), DataPointFrow); - - for (int iKnotU = 0; iKnotU < nKnotsU; ++iKnotU) { - DataT* knotPar = &Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU)]; - for (int dim = 0; dim < Ndim; ++dim) { - knotPar[dim] = parU[Ndim * (2 * iKnotU) + dim]; // store S for all the knots - knotPar[Ndim2 + dim] = parU[Ndim * (2 * iKnotU) + Ndim + dim]; // store S'u for all the knots //SG!!! - } - } - - // recalculate F values for all ipu DataPoints at V = ipv - for (int ipu = 0; ipu < nDataPointsU; ipu++) { - DataT splineF[Ndim]; - DataT u = mHelperU1.getDataPoint(ipu).u; - mHelperU1.getSpline().interpolateU(Ndim, parU.get(), u, splineF); - for (int dim = 0; dim < Ndim; dim++) { - rotDataPointF[(ipu * nDataPointsV + ipv) * Ndim + dim] = splineF[dim]; - } - } - } - - // calculate S'v at all data points with V == V of a knot - - for (int ipu = 0; ipu < nDataPointsU; ipu++) { - const DataT* DataPointFcol = &(rotDataPointF[ipu * nDataPointsV * Ndim]); - mHelperU2.approximateFunctionGradually(parV.get(), DataPointFcol); - for (int iKnotV = 0; iKnotV < nKnotsV; iKnotV++) { - for (int dim = 0; dim < Ndim; dim++) { - DataT dv = parV[(iKnotV * 2 + 1) * Ndim + dim]; - Dv[(iKnotV * nDataPointsU + ipu) * Ndim + dim] = dv; - } - } - } - - // fit S'v and S''_vu at all the knots - - for (int iKnotV = 0; iKnotV < nKnotsV; ++iKnotV) { - const DataT* Dvrow = &(Dv[iKnotV * nDataPointsU * Ndim]); - mHelperU1.approximateFunction(parU.get(), Dvrow); - for (int iKnotU = 0; iKnotU < nKnotsU; ++iKnotU) { - for (int dim = 0; dim < Ndim; ++dim) { - Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU) + Ndim + dim] = parU[Ndim * 2 * iKnotU + dim]; // store S'v for all the knots - Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU) + Ndim3 + dim] = parU[Ndim * 2 * iKnotU + Ndim + dim]; // store S''vu for all the knots - } - } - } -} - -template class GPUCA_NAMESPACE::gpu::SplineHelper2D<float>; -template class GPUCA_NAMESPACE::gpu::SplineHelper2D<double>; - -#endif diff --git a/GPU/TPCFastTransformation/SplineHelper2D.h b/GPU/TPCFastTransformation/SplineHelper2D.h deleted file mode 100644 index 23fe726251db1..0000000000000 --- a/GPU/TPCFastTransformation/SplineHelper2D.h +++ /dev/null @@ -1,150 +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. - -/// \file SplineHelper2D.h -/// \brief Definition of SplineHelper2D class -/// -/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> - -#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEHELPER2D_H -#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEHELPER2D_H - -#include <cmath> -#include <vector> - -#include "GPUCommonDef.h" -#include "GPUCommonRtypes.h" -#include "Spline1D.h" -#include "Spline2D.h" -#include "SplineHelper1D.h" -#include <functional> -#include <string> - -namespace GPUCA_NAMESPACE -{ -namespace gpu -{ - -/// -/// The SplineHelper2D class is to initialize Spline* objects -/// -template <typename DataT> -class SplineHelper2D -{ - public: - /// _____________ Constructors / destructors __________________________ - - /// Default constructor - SplineHelper2D(); - - /// Copy constructor: disabled - SplineHelper2D(const SplineHelper2D&) CON_DELETE; - - /// Assignment operator: disabled - SplineHelper2D& operator=(const SplineHelper2D&) CON_DELETE; - - /// Destructor - ~SplineHelper2D() CON_DEFAULT; - - /// _______________ Main functionality ________________________ - - /// Create best-fit spline parameters for a given input function F - template <bool isConsistentT> - void approximateFunction( - Spline2DBase<DataT, isConsistentT>& spline, - DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(DataT x1, DataT x2, DataT f[/*spline.getFdimensions()*/])> F, - int nAxiliaryDataPointsU1 = 4, int nAxiliaryDataPointsU2 = 4); - - /// _______________ Interface for a step-wise construction of the best-fit spline ________________________ - - /// precompute everything needed for the construction - template <bool isConsistentT> - int setSpline(const Spline2DBase<DataT, isConsistentT>& spline, int nAxiliaryPointsU1, int nAxiliaryPointsU2); - - /// approximate std::function, output in Fparameters - void approximateFunction( - DataT* Fparameters, DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(DataT x1, DataT x2, DataT f[/*mFdimensions*/])> F) const; - - /// approximate std::function, output in Fparameters. F calculates values for a batch of points. - void approximateFunctionBatch( - DataT* Fparameters, DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(const std::vector<DataT>& x1, const std::vector<DataT>& x2, std::vector<DataT> f[/*mFdimensions*/])> F, - unsigned int batchsize) const; - - /// approximate a function given as an array of values at data points - void approximateFunction( - DataT* Fparameters, const DataT DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const; - - int getNumberOfDataPointsU1() const { return mHelperU1.getNumberOfDataPoints(); } - - int getNumberOfDataPointsU2() const { return mHelperU2.getNumberOfDataPoints(); } - - int getNumberOfDataPoints() const { return getNumberOfDataPointsU1() * getNumberOfDataPointsU2(); } - - const SplineHelper1D<DataT>& getHelperU1() const { return mHelperU1; } - const SplineHelper1D<DataT>& getHelperU2() const { return mHelperU2; } - - /// _______________ Utilities ________________________ - - /// Gives error string - const char* getLastError() const { return mError.c_str(); } - - private: - /// Stores an error message - int storeError(int code, const char* msg); - - std::string mError = ""; ///< error string - int mFdimensions; ///< n of F dimensions - SplineHelper1D<DataT> mHelperU1; - SplineHelper1D<DataT> mHelperU2; -}; - -template <typename DataT> -template <bool isConsistentT> -void SplineHelper2D<DataT>::approximateFunction( - Spline2DBase<DataT, isConsistentT>& spline, - DataT x1Min, DataT x1Max, DataT x2Min, DataT x2Max, - std::function<void(DataT x1, DataT x2, DataT f[/*spline.getFdimensions()*/])> F, - int nAxiliaryDataPointsU1, int nAxiliaryDataPointsU2) -{ - /// Create best-fit spline parameters for a given input function F - if (spline.isConsistent()) { - setSpline(spline, nAxiliaryDataPointsU1, nAxiliaryDataPointsU2); - approximateFunction(spline.getFparameters(), x1Min, x1Max, x2Min, x2Max, F); - } - spline.setXrange(x1Min, x1Max, x2Min, x2Max); -} - -template <typename DataT> -template <bool isConsistentT> -int SplineHelper2D<DataT>::setSpline( - const Spline2DBase<DataT, isConsistentT>& spline, int nAxiliaryPointsU, int nAxiliaryPointsV) -{ - // Prepare creation of 2D irregular spline - // The should be at least one (better, two) axiliary measurements on each segnment between two knots and at least 2*nKnots measurements in total - // Returns 0 when the spline can not be constructed with the given nAxiliaryPoints - - int ret = 0; - mFdimensions = spline.getFdimensions(); - if (mHelperU1.setSpline(spline.getGridU1(), mFdimensions, nAxiliaryPointsU) != 0) { - ret = storeError(-2, "SplineHelper2D::setSpline2D: error by setting U axis"); - } - if (mHelperU2.setSpline(spline.getGridU2(), mFdimensions, nAxiliaryPointsV) != 0) { - ret = storeError(-3, "SplineHelper2D::setSpline2D: error by setting V axis"); - } - return ret; -} - -} // namespace gpu -} // namespace GPUCA_NAMESPACE - -#endif diff --git a/GPU/TPCFastTransformation/SplineSpec.cxx b/GPU/TPCFastTransformation/SplineSpec.cxx new file mode 100644 index 0000000000000..865da5c42fadc --- /dev/null +++ b/GPU/TPCFastTransformation/SplineSpec.cxx @@ -0,0 +1,232 @@ +// 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 SplineSpec.cxx +/// \brief Implementation of SplineSpec class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#include "Rtypes.h" +#endif + +#include "SplineSpec.h" + +#if !defined(GPUCA_GPUCODE) +#include <iostream> +#endif + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#include "TRandom.h" +#include "Riostream.h" +#include "TMath.h" +#include "SplineHelper.h" +#include "TCanvas.h" +#include "TNtuple.h" +#include "TFile.h" +#include "GPUCommonMath.h" + +templateClassImp(GPUCA_NAMESPACE::gpu::SplineContainer); +templateClassImp(GPUCA_NAMESPACE::gpu::SplineSpec); + +#endif + +using namespace std; +using namespace GPUCA_NAMESPACE::gpu; + +template <typename DataT> +void SplineContainer<DataT>::destroy() +{ + /// See FlatObject for description + mXdim = 0; + mYdim = 0; + mNknots = 0; + mGrid = nullptr; + mParameters = nullptr; + FlatObject::destroy(); +} + +template <typename DataT> +void SplineContainer<DataT>::setActualBufferAddress(char* actualFlatBufferPtr) +{ + /// See FlatObject for description + + FlatObject::setActualBufferAddress(actualFlatBufferPtr); + mGrid = reinterpret_cast<Spline1D<DataT>*>(mFlatBufferPtr); + int offset = sizeof(*mGrid) * mXdim; + for (int i = 0; i < mXdim; i++) { + offset = alignSize(offset, mGrid[i].getBufferAlignmentBytes()); + mGrid[i].setActualBufferAddress(mFlatBufferPtr + offset); + offset += mGrid[i].getFlatBufferSize(); + } + offset = alignSize(offset, getParameterAlignmentBytes()); + mParameters = reinterpret_cast<DataT*>(mFlatBufferPtr + offset); +} + +template <typename DataT> +void SplineContainer<DataT>::setFutureBufferAddress(char* futureFlatBufferPtr) +{ + /// See FlatObject for description + mParameters = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mParameters); + for (int i = 0; i < mXdim; i++) { + char* buffer = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mGrid[i].getFlatBufferPtr()); + mGrid[i].setFutureBufferAddress(buffer); + } + mGrid = relocatePointer(mFlatBufferPtr, futureFlatBufferPtr, mGrid); + FlatObject::setFutureBufferAddress(futureFlatBufferPtr); +} + +template <typename DataT> +void SplineContainer<DataT>::print() const +{ + printf(" Irregular Spline %dD->%dD: \n", mXdim, mYdim); + for (int i = 0; i < mXdim; i++) { + printf(" grid X%d: \n", i); + mGrid[i].print(); + } +} + +#if !defined(GPUCA_GPUCODE) + +template <typename DataT> +void SplineContainer<DataT>::cloneFromObject(const SplineContainer<DataT>& obj, char* newFlatBufferPtr) +{ + /// See FlatObject for description + + const char* oldFlatBufferPtr = obj.mFlatBufferPtr; + FlatObject::cloneFromObject(obj, newFlatBufferPtr); + mXdim = obj.mXdim; + mYdim = obj.mYdim; + mNknots = obj.mNknots; + + Spline1D<DataT>* newGrid = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mGrid); + for (int i = 0; i < mXdim; i++) { + char* buffer = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mGrid[i].getFlatBufferPtr()); + newGrid[i].cloneFromObject(obj.mGrid[i], buffer); + } + mGrid = newGrid; + mParameters = FlatObject::relocatePointer(oldFlatBufferPtr, mFlatBufferPtr, obj.mParameters); +} + +template <typename DataT> +void SplineContainer<DataT>::moveBufferTo(char* newFlatBufferPtr) +{ + /// See FlatObject for description + char* oldFlatBufferPtr = mFlatBufferPtr; + FlatObject::moveBufferTo(newFlatBufferPtr); + char* currFlatBufferPtr = mFlatBufferPtr; + mFlatBufferPtr = oldFlatBufferPtr; + setActualBufferAddress(currFlatBufferPtr); +} + +template <typename DataT> +void SplineContainer<DataT>::recreate( + int nXdim, int nYdim, const int numberOfKnots[/* nXdim */], const int* const knots[/* nXdim */]) +{ + /// Constructor for an irregular spline + + mXdim = nXdim; + mYdim = nYdim; + FlatObject::startConstruction(); + + Spline1D<DataT> vGrids[mXdim]; + + mNknots = 1; + for (int i = 0; i < mXdim; i++) { + if (knots) { + vGrids[i].recreate(0, numberOfKnots[i], knots[i]); + } else if (numberOfKnots) { + vGrids[i].recreate(0, numberOfKnots[i]); + } else { + vGrids[i].recreate(0, 2); + } + mNknots *= vGrids[i].getNumberOfKnots(); + } + + int offset = sizeof(Spline1D<DataT>) * mXdim; + + for (int i = 0; i < mXdim; i++) { + offset = alignSize(offset, vGrids[i].getBufferAlignmentBytes()); + offset += vGrids[i].getFlatBufferSize(); + } + + offset = alignSize(offset, getParameterAlignmentBytes()); + offset += getSizeOfParameters(); + + FlatObject::finishConstruction(offset); + + mGrid = reinterpret_cast<Spline1D<DataT>*>(mFlatBufferPtr); + + offset = sizeof(Spline1D<DataT>) * mXdim; + + for (int i = 0; i < mXdim; i++) { + new (&mGrid[i]) Spline1D<DataT>; // constructor + offset = alignSize(offset, mGrid[i].getBufferAlignmentBytes()); + mGrid[i].cloneFromObject(vGrids[i], mFlatBufferPtr + offset); + offset += mGrid[i].getFlatBufferSize(); + } + + offset = alignSize(offset, getParameterAlignmentBytes()); + mParameters = reinterpret_cast<DataT*>(mFlatBufferPtr + offset); + offset += getSizeOfParameters(); + + for (int i = 0; i < getNumberOfParameters(); i++) { + mParameters[i] = 0; + } +} + +template <typename DataT> +void SplineContainer<DataT>::recreate( + int nXdim, int nYdim, const int numberOfKnots[/* nXdim */]) +{ + /// Constructor for a regular spline + recreate(nXdim, nYdim, numberOfKnots, nullptr); +} + +#endif // GPUCA_GPUCODE + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation + +template <typename DataT> +void SplineContainer<DataT>:: + approximateFunction(const double xMin[/* mXdim */], const double xMax[/* mXdim */], + std::function<void(const double x[/* mXdim */], double f[/*mYdim*/])> F, + const int nAuxiliaryDataPoints[/* mXdim */]) +{ + /// approximate a function F with this spline + SplineHelper<DataT> helper; + helper.approximateFunction(*reinterpret_cast<Spline<DataT>*>(this), xMin, xMax, F, nAuxiliaryDataPoints); +} + +template <typename DataT> +int SplineContainer<DataT>::writeToFile(TFile& outf, const char* name) +{ + /// write a class object to the file + return FlatObject::writeToFile(*this, outf, name); +} + +template <typename DataT> +SplineContainer<DataT>* SplineContainer<DataT>::readFromFile( + TFile& inpf, const char* name) +{ + /// read a class object from the file + return FlatObject::readFromFile<SplineContainer<DataT>>(inpf, name); +} + +template <typename DataT> +int SplineContainer<DataT>::test(const bool draw, const bool drawDataPoints) +{ + return SplineHelper<DataT>::test(draw, drawDataPoints); +} + +#endif // GPUCA_GPUCODE && !GPUCA_STANDALONE + +template class GPUCA_NAMESPACE::gpu::SplineContainer<float>; +template class GPUCA_NAMESPACE::gpu::SplineContainer<double>; diff --git a/GPU/TPCFastTransformation/SplineSpec.h b/GPU/TPCFastTransformation/SplineSpec.h new file mode 100644 index 0000000000000..e18c7ddff456b --- /dev/null +++ b/GPU/TPCFastTransformation/SplineSpec.h @@ -0,0 +1,557 @@ +// 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 SplineSpec.h +/// \brief Definition of SplineSpec class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINESPEC_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINESPEC_H + +#include "Spline1D.h" +#include "FlatObject.h" +#include "GPUCommonDef.h" +#include "SplineUtil.h" + +#if !defined(__CINT__) && !defined(__ROOTCINT__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) && defined(__cplusplus) && __cplusplus >= 201703L +#include <Vc/Vc> +#include <Vc/SimdArray> +#endif + +class TFile; + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ + +/// ================================================================================================== +/// The class SplineContainer is a base Spline class. +/// It contains all the class members and those methods which only depends on the DataT data type. +/// It also contains all non-inlined methods with the implementation in SplineSpec.cxx file. +/// +/// DataT is a data type, which is supposed to be either double or float. +/// For other possible data types one has to add the corresponding instantiation line +/// at the end of the SplineSpec.cxx file +/// +template <typename DataT> +class SplineContainer : public FlatObject +{ + public: + typedef typename Spline1D<DataT>::SafetyLevel SafetyLevel; + typedef typename Spline1D<DataT>::Knot Knot; + + /// _____________ Version control __________________________ + + /// Version control + GPUd() static constexpr int getVersion() { return (1 << 16) + Spline1D<DataT>::getVersion(); } + + /// _____________ C++ constructors / destructors __________________________ + + /// Default constructor + SplineContainer() CON_DEFAULT; + + /// Disable all other constructors + SplineContainer(const SplineContainer&) CON_DELETE; + + /// Destructor + ~SplineContainer() CON_DEFAULT; + + /// _______________ Construction interface ________________________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// approximate a function F with this spline + void approximateFunction(const double xMin[/* mXdim */], const double xMax[/* mXdim */], + std::function<void(const double x[/* mXdim */], double f[/*mYdim*/])> F, + const int nAuxiliaryDataPoints[/* mXdim */] = nullptr); +#endif + + /// _______________ IO ________________________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + /// write a class object to the file + int writeToFile(TFile& outf, const char* name); + + /// read a class object from the file + static SplineContainer* readFromFile(TFile& inpf, const char* name); +#endif + + /// _______________ Getters ________________________ + + /// Get number of X dimensions + GPUd() int getXdimensions() const { return mXdim; } + + /// Get number of Y dimensions + GPUd() int getYdimensions() const { return mYdim; } + + /// Get minimal required alignment for the spline parameters + GPUd() static constexpr size_t getParameterAlignmentBytes() { return 16; } + + /// Number of parameters + GPUd() int getNumberOfParameters() const { return this->calcNumberOfParameters(mYdim); } + + /// Size of the parameter array in bytes + GPUd() size_t getSizeOfParameters() const { return sizeof(DataT) * this->getNumberOfParameters(); } + + /// Get a number of knots + GPUd() int getNumberOfKnots() const { return mNknots; } + + /// Number of parameters per knot + GPUd() int getNumberOfParametersPerKnot() const { return calcNumberOfParametersPerKnot(mYdim); } + + /// Get 1-D grid for dimX dimension + GPUd() const Spline1D<DataT>& getGrid(int dimX) const { return mGrid[dimX]; } + + /// Get u[] coordinate of i-th knot + GPUd() void getKnotU(int iKnot, int u[/* mXdim */]) const; + + /// Get index of a knot (iKnot1,iKnot2,..,iKnotN) + GPUd() int getKnotIndex(const int iKnot[/* mXdim */]) const; + + /// Get spline parameters + GPUd() DataT* getParameters() { return mParameters; } + + /// Get spline parameters const + GPUd() const DataT* getParameters() const { return mParameters; } + + /// _______________ Technical stuff ________________________ + + /// Get offset of Grid[dimX] flat data in the flat buffer + GPUd() size_t getGridOffset(int dimX) const { return mGrid[dimX].getFlatBufferPtr() - mFlatBufferPtr; } + + /// Set X range + void setXrange(const DataT xMin[/* mXdim */], const DataT xMax[/* mXdim */]); + + /// Print method + void print() const; + + /// _______________ Expert tools _______________ + + /// Number of parameters for given Y dimensions + GPUd() int calcNumberOfParameters(int nYdim) const + { + return calcNumberOfParametersPerKnot(nYdim) * getNumberOfKnots(); + } + + /// Number of parameters per knot + GPUd() int calcNumberOfParametersPerKnot(int nYdim) const + { + return (1 << mXdim) * nYdim; // 2^mXdim parameters per Y dimension + } + + ///_______________ Test tools _______________ + +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation + /// Test the class functionality + static int test(const bool draw = 0, const bool drawDataPoints = 1); +#endif + + /// _____________ FlatObject functionality, see FlatObject class for description ____________ + + using FlatObject::getBufferAlignmentBytes; + using FlatObject::getClassAlignmentBytes; + +#if !defined(GPUCA_GPUCODE) + void cloneFromObject(const SplineContainer& obj, char* newFlatBufferPtr); + void moveBufferTo(char* newBufferPtr); +#endif + + using FlatObject::releaseInternalBuffer; + + void destroy(); + void setActualBufferAddress(char* actualFlatBufferPtr); + void setFutureBufferAddress(char* futureFlatBufferPtr); + + protected: +#if !defined(GPUCA_GPUCODE) + /// Constructor for a regular spline + void recreate(int nXdim, int nYdim, const int nKnots[/* nXdim */]); + + /// Constructor for an irregular spline + void recreate(int nXdim, int nYdim, const int nKnots[/* nXdim */], const int* const knotU[/* nXdim */]); +#endif + + /// _____________ Data members ____________ + + int mXdim = 0; ///< dimentionality of X + int mYdim = 0; ///< dimentionality of Y + int mNknots = 0; ///< number of spline knots + + Spline1D<DataT>* mGrid; //! (transient!!) mXdim grids + DataT* mParameters; //! (transient!!) F-dependent parameters of the spline + +#ifndef GPUCA_ALIROOT_LIB + ClassDefNV(SplineContainer, 1); +#endif +}; + +template <typename DataT> +GPUdi() void SplineContainer<DataT>::getKnotU(int iKnot, int u[/* mXdim */]) const +{ + /// Get u[] coordinate of i-th knot + for (int dim = 0; dim < mXdim; dim++) { + int n = mGrid[dim].getNumberOfKnots(); + u[dim] = mGrid[dim].getKnot(iKnot % n).getU(); + iKnot /= n; + } +} + +template <typename DataT> +GPUdi() int SplineContainer<DataT>::getKnotIndex(const int iKnot[/* mXdim */]) const +{ + /// Get index of a knot (iKnot1,iKnot2,..,iKnotN) + int ind = iKnot[0]; + int n = 1; + for (int dim = 1; dim < mXdim; dim++) { + n *= mGrid[dim - 1].getNumberOfKnots(); + ind += n * iKnot[dim]; + } + return ind; +} + +template <typename DataT> +GPUdi() void SplineContainer<DataT>:: + setXrange(const DataT xMin[/* mXdim */], const DataT xMax[/* mXdim */]) +{ + /// Set X range + for (int i = 0; i < mXdim; i++) { + mGrid[i].setXrange(xMin[i], xMax[i]); + } +} + +/// ================================================================================================== +/// +/// SplineSpec class declares different specializations of the Spline class. +/// (See Spline.h for the description.) +/// +/// The specializations depend on the value of Spline's template parameters XdimT and YdimT. +/// specializations have different constructors and slightly different declarations of methods. +/// +/// The meaning of the template parameters: +/// +/// \param DataT data type: float or double +/// \param XdimT +/// XdimT > 0 : the number of X dimensions is known at the compile time and is equal to XdimT +/// XdimT = 0 : the number of X dimensions will be set in the runtime +/// XdimT < 0 : the number of X dimensions will be set in the runtime, and it will not exceed abs(XdimT) +/// \param YdimT same for the X dimensions +/// \param SpecT specialisation number: +/// 0 - a parent class for all other specializations +/// 1 - nXdim>0, nYdim>0: both nXdim and nYdim are set at the compile time +/// 2 - at least one of the dimensions must be set during runtime +/// 3 - specialization where nYdim==1 (a small add-on on top of the other specs) +/// +template <typename DataT, int XdimT, int YdimT, int SpecT> +class SplineSpec; + +/// ================================================================================================== +/// Specialization 0 declares common methods for all other Spline specializations. +/// Implementations of the methods may depend on the YdimT value. +/// +template <typename DataT, int XdimT, int YdimT> +class SplineSpec<DataT, XdimT, YdimT, 0> : public SplineContainer<DataT> +{ + typedef SplineContainer<DataT> TBase; + + public: + typedef typename TBase::SafetyLevel SafetyLevel; + typedef typename TBase::Knot Knot; + + /// _______________ Interpolation math ________________________ + + /// Get interpolated value S(x) + GPUd() void interpolate(const DataT x[/*mXdim*/], GPUgeneric() DataT S[/*mYdim*/]) const + { + const auto nXdimTmp = SplineUtil::getNdim<XdimT>(mXdim); + const auto nXdim = nXdimTmp.get(); + const auto maxXdimTmp = SplineUtil::getMaxNdim<XdimT>(mXdim); + DataT u[maxXdimTmp.get()]; + for (int i = 0; i < nXdim; i++) { + u[i] = mGrid[i].convXtoU(x[i]); + } + interpolateU<SafetyLevel::kSafe>(mXdim, mYdim, mParameters, u, S); + } + + /// Get interpolated value for S(u):inpXdim->inpYdim using spline parameters Parameters + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() void interpolateU(int inpXdim, int inpYdim, GPUgeneric() const DataT Parameters[], + const DataT u[/*inpXdim*/], GPUgeneric() DataT S[/*inpYdim*/]) const + { + const auto nXdimTmp = SplineUtil::getNdim<XdimT>(mXdim); + const auto nXdim = nXdimTmp.get(); + const auto maxXdimTmp = SplineUtil::getMaxNdim<XdimT>(mXdim); + const auto maxXdim = maxXdimTmp.get(); + const auto nYdimTmp = SplineUtil::getNdim<YdimT>(mYdim); + const auto nYdim = nYdimTmp.get(); + const auto maxYdimTmp = SplineUtil::getMaxNdim<XdimT>(mYdim); + const auto maxYdim = maxYdimTmp.get(); + + const auto nParameters = 1 << (2 * nXdim); //total Nr of Parameters necessary for one interpolation + const auto nKnotParametersPerY = 1 << nXdim; // Nr of Parameters per Knot per Y dimension + const auto nKnotParameters = (1 << nXdim) * nYdim; // Nr of Parameters per Knot + + DataT iParameters[(1 << (2 * maxXdim)) * maxYdim]; // Array for all parameters + + //get the indices of the "most left" Knot: + + int indices[maxXdim]; //indices of the 'most left' knot + for (int i = 0; i < nXdim; i++) { + indices[i] = mGrid[i].getLeftKnotIndexForU(u[i]); + } + // get all the needed parameters into one array iParameters[nParameters]: + int indicestmp[maxXdim]; + for (int i = 0; i < nKnotParametersPerY; i++) { // for every necessary Knot + for (int k = 0; k < nXdim; k++) { + indicestmp[k] = indices[k] + (i / (1 << k)) % 2; //get the knot-indices in every dimension (mirrored order binary counting) + } + int index = TBase::getKnotIndex(indicestmp); //get index of the current Knot + + for (int j = 0; j < nKnotParameters; j++) { //and fill the iparameter array with according parameters + iParameters[i * nKnotParameters + j] = Parameters[index * nKnotParameters + j]; + } + } + //now start with the interpolation loop: + + auto maxInterpolations = (1 << (2 * maxXdim - 2)) * maxYdim; + + DataT S0[maxInterpolations]; + DataT D0[maxInterpolations]; + DataT S1[maxInterpolations]; + DataT D1[maxInterpolations]; + + int nrofInterpolations = (1 << (2 * nXdim - 2)) * nYdim; + int nrofKnots = 1 << (nXdim); + + for (int d = 0; d < nXdim; d++) { //for every dimension + DataT* pointer[4] = {S0, D0, S1, D1}; // pointers for interpolation arrays S0, D0, S1, D1 point to Arraystart + for (int i = 0; i < nrofKnots; i++) { //for every knot + for (int j = 0; j < nrofKnots; j++) { // for every parametertype + int pointernr = 2 * (i % 2) + (j % 2); //to which array should it be delivered + for (int k = 0; k < nYdim; k++) { + pointer[pointernr][0] = iParameters[(i * nrofKnots + j) * nYdim + k]; + pointer[pointernr]++; + } + } // end for j (every parametertype) + } // end for i (every knot) + + const typename Spline1D<DataT>::Knot& knotL = mGrid[d].getKnot(indices[d]); + int Ydim = nrofInterpolations; + DataT coordinate = u[d]; + + typedef Spline1DSpec<DataT, YdimT, 0> TGridX; + const TGridX& gridX = *((const TGridX*)&(mGrid[d])); + gridX.interpolateU(Ydim, knotL, S0, D0, S1, D1, coordinate, iParameters); + + nrofInterpolations = nrofInterpolations / 4; + nrofKnots = nrofKnots / 2; + } //end d (every dimension) + + for (int i = 0; i < nYdim; i++) { + S[i] = iParameters[i]; // write into result-array + //std::cout<<iParameters[i] <<", "; + } + } // end interpolateU + + protected: + using TBase::mGrid; + using TBase::mParameters; + using TBase::mXdim; + using TBase::mYdim; + using TBase::TBase; // inherit constructors and hide them +}; + +/// ================================================================================================== +/// Specialization 1: XdimT>0, YdimT>0 where the number of dimensions is taken from template parameters +/// at the compile time +/// +template <typename DataT, int XdimT, int YdimT> +class SplineSpec<DataT, XdimT, YdimT, 1> + : public SplineSpec<DataT, XdimT, YdimT, 0> +{ + typedef SplineContainer<DataT> TVeryBase; + typedef SplineSpec<DataT, XdimT, YdimT, 0> TBase; + + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + +#if !defined(GPUCA_GPUCODE) + /// Default constructor + SplineSpec() : SplineSpec(nullptr) {} + + /// Constructor for a regular spline + SplineSpec(const int nKnots[/*XdimT*/]) : TBase() + { + recreate(nKnots); + } + /// Constructor for an irregular spline + SplineSpec(const int nKnots[/*XdimT*/], const int* const knotU[/*XdimT*/]) + : TBase() + { + recreate(nKnots, knotU); + } + /// Copy constructor + SplineSpec(const SplineSpec& v) : TBase() + { + TBase::cloneFromObject(v, nullptr); + } + /// Constructor for a regular spline + void recreate(const int nKnots[/*XdimT*/]) + { + TBase::recreate(XdimT, YdimT, nKnots); + } + + /// Constructor for an irregular spline + void recreate(const int nKnots[/*XdimT*/], const int* const knotU[/*XdimT*/]) + { + TBase::recreate(XdimT, YdimT, nKnots, knotU); + } +#endif + + /// Get number of X dimensions + GPUd() constexpr int getXdimensions() const { return XdimT; } + + /// Get number of Y dimensions + GPUd() constexpr int getYdimensions() const { return YdimT; } + + /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ + + /// Get interpolated value for an YdimT-dimensional S(u1,u2) using spline parameters Parameters. + template <SafetyLevel SafeT = SafetyLevel::kSafe> + GPUd() void interpolateU(GPUgeneric() const DataT Parameters[], + const DataT u[/*XdimT*/], GPUgeneric() DataT S[/*YdimT*/]) const + { + TBase::template interpolateU<SafeT>(XdimT, YdimT, Parameters, u, S); + } + + /// _______________ Suppress some parent class methods ________________________ + private: +#if !defined(GPUCA_GPUCODE) + using TBase::recreate; +#endif + using TBase::interpolateU; +}; + +/// ================================================================================================== +/// Specialization 2 (XdimT<=0 || YdimT<=0) where at least one of the dimensions +/// must be set in the runtime via a constructor parameter +/// +template <typename DataT, int XdimT, int YdimT> +class SplineSpec<DataT, XdimT, YdimT, 2> + : public SplineSpec<DataT, XdimT, YdimT, 0> +{ + typedef SplineContainer<DataT> TVeryBase; + typedef SplineSpec<DataT, XdimT, YdimT, 0> TBase; + + public: + typedef typename TVeryBase::SafetyLevel SafetyLevel; + +#if !defined(GPUCA_GPUCODE) + /// Default constructor + SplineSpec() : SplineSpec((XdimT > 0 ? XdimT : 0), (YdimT > 0 ? YdimT : 0), nullptr) {} + + /// Constructor for a regular spline + SplineSpec(int nXdim, int nYdim, const int nKnots[/* nXdim */]) : TBase() + { + this->recreate(nXdim, nYdim, nKnots); + } + + /// Constructor for an irregular spline + SplineSpec(int nXdim, int nYdim, const int nKnots[/* nXdim */], const int* const knotU[/* nXdim */]) + : TBase() + { + this->recreate(nXdim, nYdim, nKnots, knotU); + } + + /// Copy constructor + SplineSpec(const SplineSpec& v) : TBase() + { + cloneFromObject(v, nullptr); + } + + /// Constructor for a regular spline + void recreate(int nXdim, int nYdim, const int nKnots[/* nXdim */]) + { + checkDimensions(nXdim, nYdim); + TBase::recreate(nXdim, nYdim, nKnots); + } + + /// Constructor for an irregular spline + void recreate(int nXdim, int nYdim, const int nKnots[/* nXdim */], const int* const knotU[/* nXdim */]) + { + checkDimensions(nXdim, nYdim); + TBase::recreate(nXdim, nYdim, nKnots, knotU); + } + +#endif + + /// _______ Expert tools: interpolation with given nYdim and external Parameters _______ + + using TBase::interpolateU; + + /// Check dimensions + void checkDimensions(int& nXdim, int& nYdim) + { + if (XdimT > 0 && nXdim != XdimT) { + assert(0); + nXdim = XdimT; + } + if (XdimT < 0 && nXdim > abs(XdimT)) { + assert(0); + nXdim = abs(XdimT); + } + if (nXdim < 0) { + assert(0); + nXdim = 0; + } + if (YdimT > 0 && nYdim != YdimT) { + assert(0); + nYdim = YdimT; + } + if (YdimT < 0 && nYdim > abs(YdimT)) { + assert(0); + nYdim = abs(YdimT); + } + if (nYdim < 0) { + assert(0); + nYdim = 0; + } + } +}; + +/// ================================================================================================== +/// Specialization 3 where the number of Y dimensions is 1. +/// +template <typename DataT, int XdimT> +class SplineSpec<DataT, XdimT, 1, 3> + : public SplineSpec<DataT, XdimT, 1, SplineUtil::getSpec(XdimT, 999)> +{ + typedef SplineSpec<DataT, XdimT, 1, SplineUtil::getSpec(XdimT, 999)> TBase; + + public: + using TBase::TBase; // inherit constructors + + /// Simplified interface for 1D: return the interpolated value + GPUd() DataT interpolate(const DataT x[]) const + { + DataT S = 0.; + TBase::interpolate(x, &S); + return S; + } + + // this parent method should be public anyhow, + // but the compiler gets confused w/o this extra declaration + using TBase::interpolate; +}; + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/TPCFastTransformation/SplineUtil.h b/GPU/TPCFastTransformation/SplineUtil.h new file mode 100644 index 0000000000000..0ca3d738f46c7 --- /dev/null +++ b/GPU/TPCFastTransformation/SplineUtil.h @@ -0,0 +1,111 @@ +// 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 SplineSpec.h +/// \brief Definition of SplineSpec class +/// +/// \author Sergey Gorbunov <sergey.gorbunov@cern.ch> + +#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEUTIL_H +#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINEUTIL_H + +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ + +/// ================================================================================================== +/// Utilities for the Spline class +/// +class SplineUtil +{ + public: + /// Calculate a Spline specialization number depending on nXdim, nYdim + /// + static constexpr int getSpec(int nXdim, int nYdim) + { + // List of the Spline class specializations: + // + // 0 - a parent class for other specializations + // 1 - nXdim>0, nYdim>0: both nXdim and nYdim are set at the compile time + // 2 - at least one of the dimensions must be set during runtime + // 3 - specialization where nYdim==1 (a small add-on on top of the other specs) + + if (nYdim == 1) { + return 3; + } + if (nXdim > 0 && nYdim > 0) { + return 1; + } else { + return 2; + } + } + + /// Spline1D & Spline2D specialization number depending on nYdim + /// + static constexpr int getSpec(int nYdim) + { + return getSpec(1, nYdim); + } + + /// abs() as a constexpr method, to make the GPU compiler happy + static constexpr int abs(int v) { return (v >= 0) ? v : -v; } + + /// class lets one to switch between constexpr int ValTrueT and int mValFalse, depending on the ConditionT + template <bool ConditionT, int ValTrueT> + class Switch; + + /// An expression + /// const auto tmp = getNdim<nDimT>(int Ndim); + /// tmp.get(); + /// returns either a constexpr integer NdimT, or an integer Ndim, depending on the (NdimT>0) value + /// (a temporary variable tmp is needed to make the GPU compiler happy) + /// + template <int NdimT> + GPUd() static Switch<(NdimT > 0), NdimT> getNdim(int Ndim) + { + return Switch<(NdimT > 0), NdimT>(Ndim); + } + + /// An expression + /// const auto tmp = getMaxNdim(int Ndim); + /// tmp.get(); + /// returns either a constexpr integer abs(NdimT), or an integer Ndim, depending on the (NdimT!=0) value + /// + template <int NdimT> + GPUd() static Switch<(NdimT != 0), abs(NdimT)> getMaxNdim(int Ndim) + { + return Switch<(NdimT != 0), abs(NdimT)>(Ndim); + } +}; + +template <int ValTrueT> +class SplineUtil::Switch<true, ValTrueT> +{ + public: + GPUd() Switch(int /*valFalse*/) {} + GPUd() static constexpr int get() { return ValTrueT; } +}; + +template <int ValTrueT> +class SplineUtil::Switch<false, ValTrueT> +{ + public: + GPUd() Switch(int valFalse) : mValFalse(valFalse) {} + GPUd() int get() const { return mValFalse; } + + private: + int mValFalse; +}; + +} // namespace gpu +} // namespace GPUCA_NAMESPACE + +#endif diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx index 8fe26c7bc7acf..aed967c972429 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.cxx @@ -19,7 +19,7 @@ #include <iostream> #include <cmath> #include "ChebyshevFit1D.h" -#include "SplineHelper2D.h" +#include "Spline2DHelper.h" #endif using namespace GPUCA_NAMESPACE::gpu; @@ -219,8 +219,8 @@ void TPCFastSpaceChargeCorrection::print() const const SplineType& spline = getSpline(is, ir); const float* d = getSplineData(is, ir); int k = 0; - for (int i = 0; i < spline.getGridU1().getNumberOfKnots(); i++) { - for (int j = 0; j < spline.getGridU2().getNumberOfKnots(); j++, k++) { + for (int i = 0; i < spline.getGridX1().getNumberOfKnots(); i++) { + for (int j = 0; j < spline.getGridX2().getNumberOfKnots(); j++, k++) { std::cout << d[k] << " "; } std::cout << std::endl; @@ -414,8 +414,8 @@ GPUd() void TPCFastSpaceChargeCorrection::setNoCorrection() area.vMax = vLength; area.cvMax = vLength; info.CorrU0 = area.cuMin; - info.scaleCorrUtoGrid = (spline.getGridU1().getNumberOfKnots() - 1) / (area.cuMax - area.cuMin); - info.scaleCorrVtoGrid = (spline.getGridU2().getNumberOfKnots() - 1) / area.cvMax; + info.scaleCorrUtoGrid = (spline.getGridX1().getNumberOfKnots() - 1) / (area.cuMax - area.cuMin); + info.scaleCorrVtoGrid = (spline.getGridX2().getNumberOfKnots() - 1) / area.cvMax; } // row } // slice } @@ -497,8 +497,8 @@ void TPCFastSpaceChargeCorrection::initInverse(bool prn) initMaxDriftLength(prn); - SplineHelper2D<float> helper; - std::vector<float> dataPointF; + Spline2DHelper<float> helper; + std::vector<double> dataPointF; std::vector<float> splineParameters; ChebyshevFit1D chebFitterX, chebFitterU, chebFitterV; @@ -630,8 +630,8 @@ void TPCFastSpaceChargeCorrection::initInverse(bool prn) } SliceRowInfo& info = mSliceRowInfoPtr[slice * mGeo.getNumberOfRows() + row]; info.CorrU0 = area.cuMin; - info.scaleCorrUtoGrid = (spline.getGridU1().getNumberOfKnots() - 1) / (area.cuMax - area.cuMin); - info.scaleCorrVtoGrid = (spline.getGridU2().getNumberOfKnots() - 1) / area.cvMax; + info.scaleCorrUtoGrid = (spline.getGridX1().getNumberOfKnots() - 1) / (area.cuMax - area.cuMin); + info.scaleCorrVtoGrid = (spline.getGridX2().getNumberOfKnots() - 1) / area.cvMax; dataPointF.resize(helper.getNumberOfDataPoints() * 3); @@ -646,7 +646,7 @@ void TPCFastSpaceChargeCorrection::initInverse(bool prn) double dcol = (area.cuMax - area.cuMin) / (helper.getNumberOfDataPointsU1() - 1); for (int iv = 0; iv < helper.getNumberOfDataPointsU2(); iv++) { double cv = iv * drow; - float* dataPointFrow = &dataPointF[iv * helper.getNumberOfDataPointsU1() * 3]; + double* dataPointFrow = &dataPointF[iv * helper.getNumberOfDataPointsU1() * 3]; for (int iu = 0; iu < helper.getNumberOfDataPointsU1(); iu++) { dataPointFrow[iu * 3 + 0] = 0; dataPointFrow[iu * 3 + 1] = 0; diff --git a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h index d1ca35e43357f..b78e5f233c703 100644 --- a/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h +++ b/GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h @@ -64,7 +64,7 @@ class TPCFastSpaceChargeCorrection : public FlatObject float vMax; }; - typedef Spline2D<float, 3, 0> SplineType; + typedef Spline2D<float, 3> SplineType; /// _____________ Constructors / destructors __________________________ @@ -270,8 +270,8 @@ GPUdi() int TPCFastSpaceChargeCorrection::getCorrection(int slice, int row, floa const float* splineData = getSplineData(slice, row); float su = 0, sv = 0; mGeo.convUVtoScaledUV(slice, row, u, v, su, sv); - su *= spline.getGridU1().getUmax(); - sv *= spline.getGridU2().getUmax(); + su *= spline.getGridX1().getUmax(); + sv *= spline.getGridX2().getUmax(); float dxuv[3]; spline.interpolateU(splineData, su, sv, dxuv); dx = dxuv[0]; @@ -285,7 +285,7 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvCorrectedX( { //const RowInfo& rowInfo = getRowInfo(row); const SliceRowInfo& sliceRowInfo = getSliceRowInfo(slice, row); - const Spline2D<float, 1, 0>& spline = reinterpret_cast<const Spline2D<float, 1, 0>&>(getSpline(slice, row)); + const Spline2D<float, 1>& spline = reinterpret_cast<const Spline2D<float, 1>&>(getSpline(slice, row)); const float* splineData = getSplineData(slice, row, 1); float gridU = (cu - sliceRowInfo.CorrU0) * sliceRowInfo.scaleCorrUtoGrid; float gridV = cv * sliceRowInfo.scaleCorrVtoGrid; @@ -299,7 +299,7 @@ GPUdi() void TPCFastSpaceChargeCorrection::getCorrectionInvUV( { //const RowInfo& rowInfo = getRowInfo(row); const SliceRowInfo& sliceRowInfo = getSliceRowInfo(slice, row); - const Spline2D<float, 2, 0>& spline = reinterpret_cast<const Spline2D<float, 2, 0>&>(getSpline(slice, row)); + const Spline2D<float, 2>& spline = reinterpret_cast<const Spline2D<float, 2>&>(getSpline(slice, row)); const float* splineData = getSplineData(slice, row, 2); float gridU = (corrU - sliceRowInfo.CorrU0) * sliceRowInfo.scaleCorrUtoGrid; float gridV = corrV * sliceRowInfo.scaleCorrVtoGrid; diff --git a/GPU/TPCFastTransformation/TPCFastTransform.cxx b/GPU/TPCFastTransformation/TPCFastTransform.cxx index 4127eb6223692..67466abe5b93f 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransform.cxx @@ -161,11 +161,9 @@ int TPCFastTransform::writeToFile(std::string outFName, std::string name) if (outFName.empty()) { outFName = "tpcFastTransform.root"; } - if (name.empty()) { name = "TPCFastTransform"; } - TFile outf(outFName.data(), "recreate"); if (outf.IsZombie()) { LOG(ERROR) << "Failed to open output file " << outFName; @@ -191,11 +189,9 @@ TPCFastTransform* TPCFastTransform::loadFromFile(std::string inpFName, std::stri if (inpFName.empty()) { inpFName = "tpcFastTransform.root"; } - if (name.empty()) { name = "TPCFastTransform"; } - TFile inpf(inpFName.data()); if (inpf.IsZombie()) { LOG(ERROR) << "Failed to open input file " << inpFName; diff --git a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx index f88d192a99598..d8fdf6b73aa0f 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformGeo.cxx @@ -155,11 +155,9 @@ int TPCFastTransformGeo::test(int slice, int row, float ly, float lz) const if (!isConstructed()) { error = -1; } - if (mNumberOfRows <= 0 || mNumberOfRows >= MaxNumberOfRows) { error = -2; } - float lx = getRowInfo(row).x; float lx1 = 0.f, ly1 = 0.f, lz1 = 0.f; float gx = 0.f, gy = 0.f, gz = 0.f; diff --git a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx index 50a066eeeba82..71a606d0ab44c 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx @@ -20,7 +20,7 @@ #include "AliTPCTransform.h" #include "AliTPCcalibDB.h" #include "TPCFastTransform.h" -#include "SplineHelper2D.h" +#include "Spline2DHelper.h" using namespace GPUCA_NAMESPACE::gpu; @@ -280,7 +280,7 @@ int TPCFastTransformManager::updateCalibration(TPCFastTransform& fastTransform, const TPCFastSpaceChargeCorrection::SplineType& spline = correction.getSpline(slice, row); float* data = correction.getSplineData(slice, row); - SplineHelper2D<float> helper; + Spline2DHelper<float> helper; helper.setSpline(spline, 4, 4); auto F = [&](float su, float sv, float dxuv[3]) { float x = rowInfo.x; diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_AliRoot.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_AliRoot.h index e3a1e1149b2ed..d64a7fc0f8fd7 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_AliRoot.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_AliRoot.h @@ -16,37 +16,5 @@ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; -/* -#pragma link C++ nestedclasses; -#pragma link C++ nestedtypedef; - -#pragma link C++ namespace AliGPU::gpu; - -#pragma link C++ class AliGPU::gpu::Spline1D < float> + ; -#pragma link C++ class AliGPU::gpu::Spline1D < double> + ; -#pragma link C++ class AliGPU::gpu::Spline2DBase < float, false> + ; -#pragma link C++ class AliGPU::gpu::Spline2DBase < double, false> + ; -#pragma link C++ class AliGPU::gpu::Spline2DBase < float, true> + ; -#pragma link C++ class AliGPU::gpu::Spline2DBase < double, true> + ; - -#pragma link C++ class AliGPU::gpu::Spline2D < float, 1> - ; - -#pragma link C++ class AliGPU::gpu::SplineHelper1D < float>; -#pragma link C++ class AliGPU::gpu::SplineHelper1D < double>; -#pragma link C++ class AliGPU::gpu::SplineHelper2D < float>; -#pragma link C++ class AliGPU::gpu::SplineHelper2D < double>; - -#pragma link C++ class AliGPU::gpu::RegularSpline1D + ; -#pragma link C++ class AliGPU::gpu::IrregularSpline1D + ; -#pragma link C++ class AliGPU::gpu::IrregularSpline2D3D + ; -#pragma link C++ class AliGPU::gpu::SemiregularSpline2D3D + ; -#pragma link C++ class AliGPU::gpu::IrregularSpline2D3DCalibrator + ; -#pragma link C++ class AliGPU::gpu::TPCFastTransformGeo + ; -#pragma link C++ class AliGPU::gpu::TPCFastTransformGeo::SliceInfo + ; -#pragma link C++ class AliGPU::gpu::TPCFastTransformGeo::RowInfo + ; -#pragma link C++ class AliGPU::gpu::TPCFastTransform + ; - -#pragma link C++ class AliGPU::gpu::TPCFastSpaceChargeCorrection + ; -*/ #endif diff --git a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h index c35b1c2dcdd29..4db934adfbfad 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h +++ b/GPU/TPCFastTransformation/TPCFastTransformationLinkDef_O2.h @@ -20,27 +20,32 @@ #pragma link C++ nestedclasses; #pragma link C++ nestedtypedef; -//#pragma link C++ function o2::gpu::initSplineLibrary; - #pragma link C++ namespace o2::gpu; -//#pragma link C++ namespace o2::gpu::test+; -//#pragma link C++ class o2::gpu::test::A<float>+; +#pragma link C++ class o2::gpu::Spline1DContainer < float> + ; +#pragma link C++ class o2::gpu::Spline1DContainer < double> + ; #pragma link C++ class o2::gpu::Spline1D < float> + ; #pragma link C++ class o2::gpu::Spline1D < double> + ; -#pragma link C++ class o2::gpu::Spline2DBase < float, false> + ; -#pragma link C++ class o2::gpu::Spline2DBase < double, false> + ; -#pragma link C++ class o2::gpu::Spline2DBase < float, true> + ; -#pragma link C++ class o2::gpu::Spline2DBase < double, true> + ; - -#pragma link C++ class o2::gpu::Spline2D < float, 1> - ; - -#pragma link C++ class o2::gpu::SplineHelper1D < float>; -#pragma link C++ class o2::gpu::SplineHelper1D < double>; -#pragma link C++ class o2::gpu::SplineHelper2D < float>; -#pragma link C++ class o2::gpu::SplineHelper2D < double>; - -#pragma link C++ class o2::gpu::ChebyshevFit1D; +#pragma link C++ class o2::gpu::Spline1DHelper < float> + ; +#pragma link C++ class o2::gpu::Spline1DHelper < double> + ; +#pragma link C++ class o2::gpu::Spline1DSpec < float, 0, 2> + ; +#pragma link C++ class o2::gpu::Spline1DSpec < double, 0, 2> + ; + +#pragma link C++ class o2::gpu::Spline2DContainer < float> + ; +#pragma link C++ class o2::gpu::Spline2DContainer < double> + ; +#pragma link C++ class o2::gpu::Spline2D < float> + ; +#pragma link C++ class o2::gpu::Spline2D < double> + ; +#pragma link C++ class o2::gpu::Spline2DHelper < float> + ; +#pragma link C++ class o2::gpu::Spline2DHelper < double> + ; + +#pragma link C++ class o2::gpu::SplineContainer < float> + ; +#pragma link C++ class o2::gpu::SplineContainer < double> + ; +#pragma link C++ class o2::gpu::Spline < float> + ; +#pragma link C++ class o2::gpu::Spline < double> + ; +#pragma link C++ class o2::gpu::SplineHelper < float> + ; +#pragma link C++ class o2::gpu::SplineHelper < double> + ; + +#pragma link C++ class o2::gpu::ChebyshevFit1D + ; #pragma link C++ class o2::gpu::RegularSpline1D + ; #pragma link C++ class o2::gpu::IrregularSpline1D + ; diff --git a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h index d4a41935c521c..7fc312bfc7bcd 100644 --- a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h +++ b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h @@ -356,7 +356,6 @@ GPUdi() void IrregularSpline2D3D::getSplineVec(const float* correctedData, float for (unsigned int i = 12; i < 9 + V::size(); i++) { // fill not used part of the vector with 0 dataV[i] = 0.f; } - // calculate F values at V==v and U == u V dataU0vec(dataV), dataU1vec(dataV + 3), dataU2vec(dataV + 6), dataU3vec(dataV + 9); diff --git a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx index 7696dce156563..a21b7119c95e1 100644 --- a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx +++ b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3DCalibrator.cxx @@ -184,7 +184,6 @@ IrregularSpline2D3DCalibrator::Action IrregularSpline2D3DCalibrator::checkAction if (!isSpaceUp && !isSpaceDn) { return ret; } - // get the area of interest int regionKnotFirst = knot->rasterKnot; @@ -234,7 +233,6 @@ IrregularSpline2D3DCalibrator::Action IrregularSpline2D3DCalibrator::checkAction if (mSpline.getGrid(uv).getNumberOfKnots() <= 5) { return ret; } - // get the area of interest int regionKnotFirst = knot->rasterKnot; diff --git a/GPU/TPCFastTransformation/macro/SplineDemo.C b/GPU/TPCFastTransformation/macro/SplineDemo.C index 9decb4da5a665..c549d2d3d0a53 100644 --- a/GPU/TPCFastTransformation/macro/SplineDemo.C +++ b/GPU/TPCFastTransformation/macro/SplineDemo.C @@ -17,7 +17,7 @@ #include "TLine.h" #include "GPU/Spline1D.h" #include "GPU/IrregularSpline1D.h" -#include "GPU/SplineHelper1D.h" +#include "GPU/Spline1DHelper.h" #include "Math/Functor.h" #include "Math/ChebyshevApprox.h" @@ -28,7 +28,7 @@ int nKnots = 4; static double Fcoeff[2 * (Fdegree + 1)]; -void F(float u, float f[]) +void F(double u, double f[]) { double uu = u * TMath::Pi() / (nKnots - 1); f[0] = 0; //Fcoeff[0]/2; @@ -55,14 +55,14 @@ void F(float u, float f[]) double F1D(double u) { - float f = 0; + double f = 0; F(u, &f); return f; } -float Flocal(float u) +double Flocal(double u) { - float f = 0; + double f = 0; F(u * (nKnots - 1), &f); return f; } @@ -134,11 +134,11 @@ int SplineDemo() Fcoeff[i] = gRandom->Uniform(-1, 1); } - o2::gpu::Spline1D<float> spline(nKnots, 1); + o2::gpu::Spline1D<float, 1> spline(nKnots); spline.approximateFunction(0, nKnots - 1, F, nAxiliaryPoints); - o2::gpu::Spline1D<float> splineClassic(nKnots, 1); - o2::gpu::SplineHelper1D<float> helper; + o2::gpu::Spline1D<float, 1> splineClassic(nKnots); + o2::gpu::Spline1DHelper<float> helper; helper.approximateFunctionClassic(splineClassic, 0, nKnots - 1, F); IrregularSpline1D splineLocal; @@ -169,8 +169,8 @@ int SplineDemo() helper.setSpline(spline, 1, nAxiliaryPoints); for (int j = 0; j < helper.getNumberOfDataPoints(); j++) { - const typename SplineHelper1D<float>::DataPoint& p = helper.getDataPoint(j); - float f0; + const typename Spline1DHelper<float>::DataPoint& p = helper.getDataPoint(j); + double f0; F(p.u, &f0); double fs = spline.interpolate(spline.convUtoX(p.u)); if (p.isKnot) { @@ -210,7 +210,7 @@ int SplineDemo() int statN = 0; for (float s = 0; s < 1. + stepS; s += stepS) { double u = s * (nKnots - 1); - float f0; + double f0; F(u, &f0); double fBestFit = spline.interpolate(spline.convUtoX(u)); double fClass = splineClassic.interpolate(splineClassic.convUtoX(u)); diff --git a/GPU/TPCFastTransformation/test/testSplines.cxx b/GPU/TPCFastTransformation/test/testSplines.cxx index 2774c7911fa14..306cfc1099542 100644 --- a/GPU/TPCFastTransformation/test/testSplines.cxx +++ b/GPU/TPCFastTransformation/test/testSplines.cxx @@ -26,12 +26,10 @@ namespace o2::gpu BOOST_AUTO_TEST_CASE(Spline_test1) { - o2::gpu::Spline1D<float> s1; - int err1 = s1.test(0); + int err1 = o2::gpu::Spline1D<float>::test(0); BOOST_CHECK_MESSAGE(err1 == 0, "test of GPU/TPCFastTransform/Spline1D failed with the error code " << err1); - o2::gpu::Spline2D<float, 1> s2; - int err2 = s2.test(0); + int err2 = o2::gpu::Spline2D<float>::test(0); BOOST_CHECK_MESSAGE(err2 == 0, "test of GPU/TPCFastTransform/Spline2D failed with the error code " << err2); } } // namespace o2::gpu From 1353f43ccaa18b5c643024d5a7f18e518aeebe12 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 11 Nov 2020 19:18:47 +0100 Subject: [PATCH 1310/1751] GPU: Add garbage collection to GPU TPC Standalone QA --- .../GPUTPCCompressionKernels.h | 1 - GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 145 ++++++++++-------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 8 +- 3 files changed, 86 insertions(+), 68 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h index 06fb6a6ffa297..bcee016899094 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h @@ -42,7 +42,6 @@ class GPUTPCCompressionKernels : public GPUKernelTemplate template <int iKernel = defaultKernel> GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); - public: template <int I> class GPUTPCCompressionKernels_Compare { diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 50d3db0f8569c..c8b1600c68750 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -190,8 +190,6 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; -static TCanvas cfit; - #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" @@ -283,7 +281,27 @@ void GPUQA::createHist(T*& h, const char* name, Args... args) h = &p.first->back(); } -GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)) +namespace GPUCA_NAMESPACE::gpu +{ +struct GPUQAGarbageCollection { + std::tuple<std::vector<std::unique_ptr<TCanvas>>, std::vector<std::unique_ptr<TLegend>>, std::vector<std::unique_ptr<TPad>>, std::vector<std::unique_ptr<TLatex>>, std::vector<std::unique_ptr<TH1D>>> v; +}; +} // namespace GPUCA_NAMESPACE::gpu + +template <class T, typename... Args> +T* GPUQA::createGarbageCollected(Args... args) +{ + auto& v = std::get<std::vector<std::unique_ptr<T>>>(mGarbageCollector->v); + v.emplace_back(std::make_unique<T>(args...)); + return v.back().get(); +} +void GPUQA::clearGarbagageCollector() +{ + std::get<std::vector<std::unique_ptr<TPad>>>(mGarbageCollector->v).clear(); // Make sure to depete TPad first due to ROOT ownership (std::tuple has no defined order in its destructor) + std::apply([](auto&&... args) { ((args.clear()), ...); }, mGarbageCollector->v); +} + +GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)), mGarbageCollector(std::make_unique<GPUQAGarbageCollection>()) { mRunForQC = chain == nullptr || mConfig.forQC; } @@ -295,6 +313,7 @@ GPUQA::~GPUQA() delete mHist2D; delete mHist1Dd; } + clearGarbagageCollector(); // Needed to guarantee correct order for ROOT ownership } inline bool GPUQA::MCComp(const mcLabel_t& a, const mcLabel_t& b) { return (GPUQA::GetMCLabelID(a) > GPUQA::GetMCLabelID(b)); } @@ -366,7 +385,7 @@ void GPUQA::doPerfFigure(float x, float y, float size) if (!PERF_FIGURE) { return; } - TLatex* t = new TLatex; + TLatex* t = createGarbageCollected<TLatex>(); t->SetNDC(kTRUE); t->SetTextColor(1); t->SetTextSize(size); @@ -393,7 +412,7 @@ int GPUQA::InitQACreateHistograms() for (int m = 0; m < 2; m++) { sprintf(name, "%s%s%s%sVs%s", m ? "eff" : "tracks", EFF_TYPES[i], FINDABLE_NAMES[j], PRIM_NAMES[k], VSPARAMETER_NAMES[l]); if (l == 4) { - std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], binsPt.get()); } else { createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]); @@ -413,7 +432,7 @@ int GPUQA::InitQACreateHistograms() sprintf(name, "rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); sprintf(fname, "mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; createHist(mRes[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); } else { @@ -424,7 +443,7 @@ int GPUQA::InitQACreateHistograms() const float* axis = mConfig.nativeFitResolutions ? RES_AXES_NATIVE : RES_AXES; const int nbins = i == 4 && mConfig.nativeFitResolutions ? (10 * RES_AXIS_BINS[0]) : RES_AXIS_BINS[0]; if (j == 4) { - std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], binsPt.get()); } else { createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); @@ -438,7 +457,7 @@ int GPUQA::InitQACreateHistograms() sprintf(name, "pull_rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); sprintf(fname, "pull_mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; createHist(mPull[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); } else { @@ -447,7 +466,7 @@ int GPUQA::InitQACreateHistograms() } sprintf(name, "pull_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], binsPt.get()); } else { createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); @@ -460,7 +479,7 @@ int GPUQA::InitQACreateHistograms() int ioffset = i >= (2 * N_CLS_HIST - 1) ? (2 * N_CLS_HIST - 1) : i >= N_CLS_HIST ? N_CLS_HIST : 0; int itype = i >= (2 * N_CLS_HIST - 1) ? 2 : i >= N_CLS_HIST ? 1 : 0; sprintf(name, "clusters%s%s", CLUSTER_NAMES_SHORT[i - ioffset], CLUSTER_TYPES[itype]); - std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; createHist(mClusters[i], name, name, AXIS_BINS[4], binsPt.get()); } { @@ -471,7 +490,7 @@ int GPUQA::InitQACreateHistograms() // Create Tracks Histograms { sprintf(name, "tracks"); - std::unique_ptr<double> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; createHist(mTracks, name, name, AXIS_BINS[4], binsPt.get()); } @@ -617,11 +636,11 @@ int GPUQA::InitQA() if (mConfig.matchMCLabels.size()) { unsigned int nFiles = mConfig.matchMCLabels.size(); - std::vector<TFile*> files(nFiles); + std::vector<std::unique_ptr<TFile>> files; std::vector<std::vector<std::vector<int>>*> labelsBuffer(nFiles); std::vector<std::vector<std::vector<int>>*> effBuffer(nFiles); for (unsigned int i = 0; i < nFiles; i++) { - files[i] = new TFile(mConfig.matchMCLabels[i]); + files.emplace_back(std::make_unique<TFile>(mConfig.matchMCLabels[i])); labelsBuffer[i] = (std::vector<std::vector<int>>*)files[i]->Get("mcLabelBuffer"); effBuffer[i] = (std::vector<std::vector<int>>*)files[i]->Get("mcEffBuffer"); if (labelsBuffer[i] == nullptr || effBuffer[i] == nullptr) { @@ -651,10 +670,6 @@ int GPUQA::InitQA() mGoodTracks[iEvent][k] = labelsOK[abs((*labelsBuffer[0])[iEvent][k])]; } } - - for (unsigned int i = 0; i < nFiles; i++) { - delete files[i]; - } } mQAInitialized = true; return 0; @@ -1618,7 +1633,7 @@ void GPUQA::GetName(char* fname, int k) } template <class T> -T* GPUQA::GetHist(T*& ee, std::vector<TFile*>& tin, int k, int nNewInput) +T* GPUQA::GetHist(T*& ee, std::vector<std::unique_ptr<TFile>>& tin, int k, int nNewInput) { T* e = ee; if ((mConfig.inputHistogramsOnly || k) && (e = dynamic_cast<T*>(tin[k - nNewInput]->Get(e->GetName()))) == nullptr) { @@ -1640,13 +1655,13 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) const int nNewInput = mConfig.inputHistogramsOnly ? 0 : 1; const int ConfigNumInputs = nNewInput + mConfig.compareInputs.size(); - std::vector<TFile*> tin(mConfig.compareInputs.size()); + std::vector<std::unique_ptr<TFile>> tin; for (unsigned int i = 0; i < mConfig.compareInputs.size(); i++) { - tin[i] = new TFile(mConfig.compareInputs[i]); + tin.emplace_back(std::make_unique<TFile>(mConfig.compareInputs[i])); } - TFile* tout = nullptr; + std::unique_ptr<TFile> tout = nullptr; if (mConfig.output.size()) { - tout = new TFile(mConfig.output.c_str(), "RECREATE"); + tout = std::make_unique<TFile>(mConfig.output.c_str(), "RECREATE"); } if (!mRunForQC) { @@ -1663,22 +1678,22 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) int i = ii == 5 ? 4 : ii; sprintf(fname, "ceff_%d", ii); sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); - mCEff[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCEff[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); mCEff[ii]->cd(); float dy = 1. / 2.; - mPEff[ii][0] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPEff[ii][0] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); mPEff[ii][0]->Draw(); mPEff[ii][0]->SetRightMargin(0.04); - mPEff[ii][1] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPEff[ii][1] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); mPEff[ii][1]->Draw(); mPEff[ii][1]->SetRightMargin(0.04); - mPEff[ii][2] = new TPad("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); + mPEff[ii][2] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); mPEff[ii][2]->Draw(); mPEff[ii][2]->SetRightMargin(0.04); - mPEff[ii][3] = new TPad("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); + mPEff[ii][3] = createGarbageCollected<TPad>("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); mPEff[ii][3]->Draw(); mPEff[ii][3]->SetRightMargin(0.04); - mLEff[ii] = new TLegend(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); + mLEff[ii] = createGarbageCollected<TLegend>(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); SetLegend(mLEff[ii]); } @@ -1691,31 +1706,31 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } else { sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); } - mCRes[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCRes[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); mCRes[ii]->cd(); gStyle->SetOptFit(1); float dy = 1. / 2.; - mPRes[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPRes[ii][3] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); mPRes[ii][3]->Draw(); mPRes[ii][3]->SetRightMargin(0.04); - mPRes[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPRes[ii][4] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); mPRes[ii][4]->Draw(); mPRes[ii][4]->SetRightMargin(0.04); - mPRes[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPRes[ii][0] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); mPRes[ii][0]->Draw(); mPRes[ii][0]->SetRightMargin(0.04); mPRes[ii][0]->SetLeftMargin(0.15); - mPRes[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPRes[ii][1] = createGarbageCollected<TPad>("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); mPRes[ii][1]->Draw(); mPRes[ii][1]->SetRightMargin(0.04); mPRes[ii][1]->SetLeftMargin(0.135); - mPRes[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPRes[ii][2] = createGarbageCollected<TPad>("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); mPRes[ii][2]->Draw(); mPRes[ii][2]->SetRightMargin(0.06); mPRes[ii][2]->SetLeftMargin(0.135); if (ii < 6) { - mLRes[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLRes[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLRes[ii]); } } @@ -1729,31 +1744,31 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } else { sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); } - mCPull[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCPull[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); mCPull[ii]->cd(); gStyle->SetOptFit(1); float dy = 1. / 2.; - mPPull[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPPull[ii][3] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); mPPull[ii][3]->Draw(); mPPull[ii][3]->SetRightMargin(0.04); - mPPull[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPPull[ii][4] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); mPPull[ii][4]->Draw(); mPPull[ii][4]->SetRightMargin(0.04); - mPPull[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPPull[ii][0] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); mPPull[ii][0]->Draw(); mPPull[ii][0]->SetRightMargin(0.04); mPPull[ii][0]->SetLeftMargin(0.15); - mPPull[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPPull[ii][1] = createGarbageCollected<TPad>("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); mPPull[ii][1]->Draw(); mPPull[ii][1]->SetRightMargin(0.04); mPPull[ii][1]->SetLeftMargin(0.135); - mPPull[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPPull[ii][2] = createGarbageCollected<TPad>("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); mPPull[ii][2]->Draw(); mPPull[ii][2]->SetRightMargin(0.06); mPPull[ii][2]->SetLeftMargin(0.135); if (ii < 6) { - mLPull[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLPull[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLPull[ii]); } } @@ -1761,29 +1776,29 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas for Cluster Histos for (int i = 0; i < 3; i++) { sprintf(fname, "cclust_%d", i); - mCClust[i] = new TCanvas(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); + mCClust[i] = createGarbageCollected<TCanvas>(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); mCClust[i]->cd(); - mPClust[i] = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPClust[i] = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); mPClust[i]->Draw(); float y1 = i != 1 ? 0.77 : 0.27, y2 = i != 1 ? 0.9 : 0.42; - mLClust[i] = new TLegend(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); + mLClust[i] = createGarbageCollected<TLegend>(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); SetLegend(mLClust[i]); } // Create Canvas for other histos { - mCTracks = new TCanvas("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); + mCTracks = createGarbageCollected<TCanvas>("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); mCTracks->cd(); - mPTracks = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPTracks = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); mPTracks->Draw(); - mLTracks = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLTracks = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLTracks); - mCNCl = new TCanvas("cncl", "Number of clusters per track", 0, 0, 700, 700. * 2. / 3.); + mCNCl = createGarbageCollected<TCanvas>("cncl", "Number of clusters per track", 0, 0, 700, 700. * 2. / 3.); mCNCl->cd(); - mPNCl = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPNCl = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); mPNCl->Draw(); - mLNCl = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLNCl = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLNCl); } @@ -1884,7 +1899,8 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Process / Draw Resolution Histograms TH1D *resIntegral[5] = {}, *pullIntegral[5] = {}; - TF1* customGaus = new TF1("G", "[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))"); + TCanvas* cfit = nullptr; + std::unique_ptr<TF1> customGaus = std::make_unique<TF1>("G", "[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))"); for (int p = 0; p < 2; p++) { for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { TCanvas* can = p ? mCPull[ii] : mCRes[ii]; @@ -1898,7 +1914,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (!mConfig.inputHistogramsOnly && ii != 5) { if (!mRunForQC) { - cfit.cd(); + if (cfit == nullptr) { + cfit = createGarbageCollected<TCanvas>(); + } + cfit->cd(); } TAxis* axis = src->GetYaxis(); @@ -1907,7 +1926,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) for (int bin = 1; bin <= nBins; bin++) { int bin0 = std::max(bin - integ, 0); int bin1 = std::min(bin + integ, nBins); - TH1D* proj = src->ProjectionX("proj", bin0, bin1); + std::unique_ptr<TH1D> proj{src->ProjectionX("proj", bin0, bin1)}; proj->ClearUnderflowAndOverflow(); if (proj->GetEntries()) { unsigned int rebin = 1; @@ -1931,8 +1950,8 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (k && !forceLogLike) { customGaus->SetParameters(fitFunc->GetParameter(0), fitFunc->GetParameter(1), fitFunc->GetParameter(2)); - proj->Fit(customGaus, "sQ"); - fitFunc = customGaus; + proj->Fit(customGaus.get(), "sQ"); + fitFunc = customGaus.get(); } const float sigma = fabs(fitFunc->GetParameter(2)); @@ -1964,7 +1983,6 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) dst[1]->SetBinContent(bin, 0.f); dst[1]->SetBinError(bin, 0.f); } - delete proj; } if (ii == 0) { dstIntegral = src->ProjectionX(mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j], 0, nBins + 1); @@ -1977,7 +1995,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } if (ii == 0) { if (mConfig.inputHistogramsOnly) { - dstIntegral = new TH1D; + dstIntegral = createGarbageCollected<TH1D>(); } sprintf(fname, p ? "IntPull%s" : "IntRes%s", VSPARAMETER_NAMES[j]); sprintf(name, p ? "%s Pull" : "%s Resolution", p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j]); @@ -2109,7 +2127,6 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } } - delete customGaus; // Process Integral Resolution Histogreams for (int p = 0; p < 2; p++) { @@ -2172,11 +2189,6 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (mConfig.writeRootFiles) { can->Print(p ? "plots/pull_integral.root" : "plots/res_integral.root"); } - if (!mConfig.inputHistogramsOnly) { - for (int i = 0; i < 5; i++) { - delete (p ? pullIntegral : resIntegral)[i]; - } - } } // Process Cluster Histograms @@ -2462,11 +2474,12 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (tout) { tout->Close(); - delete tout; } for (unsigned int i = 0; i < mConfig.compareInputs.size(); i++) { tin[i]->Close(); - delete tin[i]; + } + if (!qcout) { + clearGarbagageCollector(); } return (0); } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 89dd94c6c9f1e..3bb06e915ae4e 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -79,6 +79,7 @@ namespace GPUCA_NAMESPACE::gpu { class GPUChainTracking; class GPUTPCMCInfo; +struct GPUQAGarbageCollection; class GPUQA { @@ -129,7 +130,7 @@ class GPUQA void doPerfFigure(float x, float y, float size); void GetName(char* fname, int k); template <class T> - T* GetHist(T*& ee, std::vector<TFile*>& tin, int k, int nNewInput); + T* GetHist(T*& ee, std::vector<std::unique_ptr<TFile>>& tin, int k, int nNewInput); #ifdef GPUCA_TPC_GEOMETRY_O2 using mcLabels_t = gsl::span<const o2::MCCompLabel>; @@ -266,6 +267,11 @@ class GPUQA template <class T, typename... Args> void createHist(T*& h, const char* name, Args... args); + std::unique_ptr<GPUQAGarbageCollection> mGarbageCollector; + template <class T, typename... Args> + T* createGarbageCollected(Args... args); + void clearGarbagageCollector(); + int mNEvents = 0; bool mQAInitialized = false; std::vector<std::vector<int>> mcEffBuffer; From e0281bf13502d2e593b960a6ecb9faae09aa11e3 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 00:21:27 +0100 Subject: [PATCH 1311/1751] GPU QA: Add option to ship TCanvases to QC instead of histograms --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 3 +- GPU/GPUTracking/Base/GPUSettingsList.h | 3 +- GPU/GPUTracking/Interface/GPUO2Interface.cxx | 2 +- .../Interface/GPUO2InterfaceQA.cxx | 5 + GPU/GPUTracking/Interface/GPUO2InterfaceQA.h | 1 + GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 95 +++++++++++-------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 1 + 7 files changed, 70 insertions(+), 40 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index bd5be552fabff..2b16a80d6f4ef 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -163,7 +163,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config config.configProcessing.runMC = specconfig.processMC; if (specconfig.outputQA) { if (!config.configProcessing.runQA) { - config.configQA.forQC = true; + config.configQA.shipToQC = true; } config.configProcessing.runQA = true; } @@ -713,6 +713,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config std::vector<TH1D> copy3 = *outputRegions.qa.hist3; processAttributes->qa->postprocess(copy1, copy2, copy3, out); pc.outputs().snapshot({gDataOriginTPC, "TRACKINGQA", 0, Lifetime::Timeframe}, out); + processAttributes->qa->cleanup(); } timer.Stop(); LOG(INFO) << "TPC CATracker time for this TF " << timer.CpuTime() - cput << " s"; diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index c116d67c5ceb1..34455f08d47ca 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -160,7 +160,8 @@ AddOptionVec(matchMCLabels, const char*, "", 0, "Read labels from files and matc AddOption(matchDisplayMinPt, float, 0, "", 0, "Minimum Pt of a matched track to be displayed") AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") AddOption(noMC, bool, false, "", 0, "Force running QA without MC labels even if present") -AddOption(forQC, bool, false, "", 0, "Do not write output files but ship histograms for QC") +AddOption(shipToQC, bool, false, "", 0, "Do not write output files but ship histograms for QC") +AddOption(shipToQCAsCanvas, bool, false, "", 0, "Send TCanvases with full layout to QC instead of individual histograms") AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index b356e5ba0f32c..2c63a5528ed93 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -160,7 +160,7 @@ int GPUTPCO2Interface::RunTracking(GPUTrackingInOutPointers* data, GPUInterfaceO outputs->clustersNative.size = mOutputClustersNative->EndOfSpace ? 0 : (mChain->mIOPtrs.clustersNative->nClustersTotal * sizeof(*mChain->mIOPtrs.clustersNative->clustersLinear)); outputs->tpcTracks.size = mOutputCompressedClusters->EndOfSpace ? 0 : (size_t)((char*)mOutputCompressedClusters->OutputPtr - (char*)mOutputCompressedClusters->OutputBase); } - if (mConfig->configQA.forQC) { + if (mConfig->configQA.shipToQC) { outputs->qa.hist1 = &mChain->GetQA()->getHistograms1D(); outputs->qa.hist2 = &mChain->GetQA()->getHistograms2D(); outputs->qa.hist3 = &mChain->GetQA()->getHistograms1Dd(); diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx index a30db8bef77a8..31bc68d340edb 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx @@ -30,3 +30,8 @@ int GPUO2InterfaceQA::postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2 } return mQA->DrawQAHistograms(&out); } + +void GPUO2InterfaceQA::cleanup() +{ + mQA->DrawQAHistogramsCleanup(); +} diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h index 83f0d00e3f018..6d75cdb645967 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h @@ -45,6 +45,7 @@ class GPUO2InterfaceQA // Input might be modified, so we assume non-const. If it is const, a copy should be created before. int postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out); + void cleanup(); private: std::unique_ptr<GPUQA> mQA; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index c8b1600c68750..ce87941b99cd2 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -303,7 +303,7 @@ void GPUQA::clearGarbagageCollector() GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)), mGarbageCollector(std::make_unique<GPUQAGarbageCollection>()) { - mRunForQC = chain == nullptr || mConfig.forQC; + mRunForQC = chain == nullptr || mConfig.shipToQC; } GPUQA::~GPUQA() @@ -1644,6 +1644,11 @@ T* GPUQA::GetHist(T*& ee, std::vector<std::unique_ptr<TFile>>& tin, int k, int n return (e); } +void GPUQA::DrawQAHistogramsCleanup() +{ + clearGarbagageCollector(); +} + int GPUQA::DrawQAHistograms(TObjArray* qcout) { if (!mQAInitialized) { @@ -1664,7 +1669,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) tout = std::make_unique<TFile>(mConfig.output.c_str(), "RECREATE"); } - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { float legendSpacingString = 0.025; for (int i = 0; i < ConfigNumInputs; i++) { GetName(fname, i); @@ -1801,23 +1806,23 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) mLNCl = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLNCl); } + } - if (!mConfig.inputHistogramsOnly) { - GPUInfo("QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int)mEff[3][1][0][0][0]->GetEntries(), (int)mEff[3][1][0][3][0]->GetEntries(), (int)mEff[3][1][0][4][0]->GetEntries(), - mEff[0][0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0][0]->GetSumOfWeights()), (int)mEff[3][1][1][0][0]->GetEntries(), (int)mEff[3][1][1][3][0]->GetEntries(), - (int)mEff[3][1][1][4][0]->GetEntries(), mEff[0][0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0][0]->GetSumOfWeights()), mEff[0][1][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0][0]->GetSumOfWeights()), (int)mRes2[0][0]->GetEntries(), - (int)mRes2[0][3]->GetEntries(), (int)mRes2[0][4]->GetEntries()); - } + if (!mRunForQC && !mConfig.inputHistogramsOnly) { + GPUInfo("QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int)mEff[3][1][0][0][0]->GetEntries(), (int)mEff[3][1][0][3][0]->GetEntries(), (int)mEff[3][1][0][4][0]->GetEntries(), + mEff[0][0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0][0]->GetSumOfWeights()), (int)mEff[3][1][1][0][0]->GetEntries(), (int)mEff[3][1][1][3][0]->GetEntries(), + (int)mEff[3][1][1][4][0]->GetEntries(), mEff[0][0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0][0]->GetSumOfWeights()), mEff[0][1][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0][0]->GetSumOfWeights()), (int)mRes2[0][0]->GetEntries(), + (int)mRes2[0][3]->GetEntries(), (int)mRes2[0][4]->GetEntries()); } - int flagShowVsPtLog = mRunForQC ? 0 : 1; + int flagShowVsPtLog = (mRunForQC && !mConfig.shipToQCAsCanvas) ? 0 : 1; // Process / Draw Efficiency Histograms for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { int i = ii == 5 ? 4 : ii; for (int k = 0; k < ConfigNumInputs; k++) { for (int j = 0; j < 4; j++) { - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { mPEff[ii][j]->cd(); } for (int l = 0; l < 3; l++) { @@ -1858,10 +1863,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) e->SetLineWidth(1); e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); SetAxisSize(e); - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } e->SetMarkerColor(kBlack); @@ -1876,21 +1881,26 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) mPEff[ii][j]->SetLogx(); } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } mCEff[ii]->cd(); ChangePadTitleSize(mPEff[ii][j], 0.056); } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } mLEff[ii]->Draw(); + if (mRunForQC) { + if (qcout) { + qcout->Add(mCEff[ii]); + } + continue; + } doPerfFigure(0.2, 0.295, 0.025); - mCEff[ii]->Print(Form("plots/eff_vs_%s.pdf", VSPARAMETER_NAMES[ii])); if (mConfig.writeRootFiles) { mCEff[ii]->Print(Form("plots/eff_vs_%s.root", VSPARAMETER_NAMES[ii])); @@ -1913,12 +1923,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) TPad* pad = p ? mPPull[ii][j] : mPRes[ii][j]; if (!mConfig.inputHistogramsOnly && ii != 5) { - if (!mRunForQC) { - if (cfit == nullptr) { - cfit = createGarbageCollected<TCanvas>(); - } - cfit->cd(); + if (cfit == nullptr) { + cfit = createGarbageCollected<TCanvas>(); } + cfit->cd(); TAxis* axis = src->GetYaxis(); int nBins = axis->GetNbins(); @@ -2002,7 +2010,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) dstIntegral->SetName(fname); dstIntegral->SetTitle(name); } - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { pad->cd(); } int numColor = 0; @@ -2080,10 +2088,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } else if (j < 3) { e->GetYaxis()->SetTitleOffset(1.4); } - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2101,7 +2109,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2113,14 +2121,19 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) ChangePadTitleSize(pad, 0.056); } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } leg->Draw(); + if (mRunForQC) { + if (qcout) { + qcout->Add(can); + } + continue; + } doPerfFigure(0.2, 0.295, 0.025); - can->Print(Form(p ? "plots/pull_vs_%s.pdf" : "plots/res_vs_%s.pdf", VSPARAMETER_NAMES[ii])); if (mConfig.writeRootFiles) { can->Print(Form(p ? "plots/pull_vs_%s.root" : "plots/res_vs_%s.root", VSPARAMETER_NAMES[ii])); @@ -2135,7 +2148,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) TPad* pad = p ? mPPull[6][i] : mPRes[6][i]; TH1D* hist = p ? pullIntegral[i] : resIntegral[i]; int numColor = 0; - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { pad->cd(); } if (!mConfig.inputHistogramsOnly && mcAvail) { @@ -2166,22 +2179,25 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (tout && !mConfig.inputHistogramsOnly && k == 0) { e->Write(); } - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } can->cd(); } if (mRunForQC) { + if (qcout) { + qcout->Add(can); + } continue; } @@ -2300,7 +2316,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } for (int i = 0; i < N_CLS_TYPE; i++) { - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { mPClust[i]->cd(); mPClust[i]->SetLogx(); } @@ -2328,10 +2344,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (i == 0) { e->GetXaxis()->SetRange(2, AXIS_BINS[4]); } - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2346,10 +2362,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (ConfigNumInputs == 1) { TH1* e = reinterpret_cast<TH1F*>(mClusters[begin + CL_att_adj]->Clone()); e->Add(mClusters[begin + CL_prot], -1); - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2357,14 +2373,19 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) e->Draw("same"); mLClust[i]->AddEntry(e, "Removed", "l"); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } mLClust[i]->Draw(); + if (mRunForQC) { + if (qcout) { + qcout->Add(mCClust[i]); + } + continue; + } doPerfFigure(i != 2 ? 0.37 : 0.6, 0.295, 0.030); - mCClust[i]->cd(); mCClust[i]->Print(i == 2 ? "plots/clusters_integral.pdf" : i == 1 ? "plots/clusters_relative.pdf" : "plots/clusters.pdf"); if (mConfig.writeRootFiles) { diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 3bb06e915ae4e..62e65a44dc508 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -91,6 +91,7 @@ class GPUQA int InitQA(); void RunQA(bool matchOnly = false); int DrawQAHistograms(TObjArray* qcout = nullptr); + void DrawQAHistogramsCleanup(); // Needed after call to DrawQAHistograms with qcout != nullptr when GPUSettingsQA.shipToQCAsCanvas = true to clean up the Canvases etc. void SetMCTrackRange(int min, int max); bool SuppressTrack(int iTrack) const; bool SuppressHit(int iHit) const; From 83ceb90e39caeca5fd91d6a49e4b486996e4cb8f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 00:26:59 +0100 Subject: [PATCH 1312/1751] GPU QA: Make color array static since it is constant --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 28 ++++++++++++++++--------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 5 +++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index ce87941b99cd2..748484b0f0b90 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -190,6 +190,22 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; +std::vector<Color_t> GPUQA::mColorNums; +std::vector<TColor> GPUQA::mColors; +int GPUQA::initColors() +{ + mColorNums.resize(COLORCOUNT); + mColors.reserve(COLORCOUNT); + for (int i = 0; i < COLORCOUNT; i++) { + float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; + float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; + float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; + mColors.emplace_back(10000 + i, f1, f2, f3); + mColorNums[i] = mColors.back().GetNumber(); + } + return 0; +} + #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" @@ -303,6 +319,8 @@ void GPUQA::clearGarbagageCollector() GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)), mGarbageCollector(std::make_unique<GPUQAGarbageCollection>()) { + static int initColorsInitialized = initColors(); + (void)initColorsInitialized; mRunForQC = chain == nullptr || mConfig.shipToQC; } @@ -536,16 +554,6 @@ int GPUQA::InitQA() mHist2D = new std::vector<TH2F>; mHist1Dd = new std::vector<TH1D>; - mColorNums.resize(COLORCOUNT); - mColors.reserve(COLORCOUNT); - for (int i = 0; i < COLORCOUNT; i++) { - float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; - float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; - float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; - mColors.emplace_back(10000 + i, f1, f2, f3); - mColorNums[i] = mColors.back().GetNumber(); - } - if (InitQACreateHistograms()) { return 1; } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 62e65a44dc508..d9beaa8b887b1 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -280,8 +280,9 @@ class GPUQA std::vector<std::vector<bool>> mGoodTracks; std::vector<std::vector<bool>> mGoodHits; - std::vector<Color_t> mColorNums; - std::vector<TColor> mColors; + static std::vector<Color_t> mColorNums; + static std::vector<TColor> mColors; + static int initColors(); int mMCTrackMin = -1, mMCTrackMax = -1; }; From de762ab42a9ebbc8bc72e94928021dc74f58de3e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 14:28:57 +0100 Subject: [PATCH 1313/1751] GPU: Remove spurious void* reinterprete cast after config is no nested class anymore --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- GPU/GPUTracking/Global/GPUChainTracking.h | 4 ++-- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 2 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 6caf6545c278a..16c8ef2c9cab2 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -421,7 +421,7 @@ int GPUChainTracking::ForceInitQA() int GPUChainTracking::Finalize() { - if (GetProcessingSettings().runQA && mQA->IsInitialized()) { + if (GetProcessingSettings().runQA && mQA->IsInitialized() && !(mConfigQA && mConfigQA->shipToQC)) { mQA->DrawQAHistograms(); } if (GetProcessingSettings().debugLevel >= 6) { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index d7ae3816579c2..f9cb5022e9830 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -171,8 +171,8 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void SetOutputControlTPCTracks(GPUOutputControl* v) { mOutputTPCTracks = v; } void SetOutputControlClusterLabels(GPUOutputControl* v) { mOutputClusterLabels = v; } - const void* mConfigDisplay = nullptr; // Abstract pointer to Standalone Display Configuration Structure - const void* mConfigQA = nullptr; // Abstract pointer to Standalone QA Configuration Structure + const GPUSettingsDisplay* mConfigDisplay = nullptr; // Abstract pointer to Standalone Display Configuration Structure + const GPUSettingsQA* mConfigQA = nullptr; // Abstract pointer to Standalone QA Configuration Structure protected: struct GPUTrackingFlatObjects : public GPUProcessor { diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 7aa72568bac25..b8f4bb302ceb5 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -89,7 +89,7 @@ static const GPUSettingsDisplay& GPUDisplay_GetConfig(GPUChainTracking* chain) #if !defined(GPUCA_STANDALONE) static GPUSettingsDisplay defaultConfig; if (chain->mConfigDisplay) { - return *((const GPUSettingsDisplay*)chain->mConfigDisplay); + return *chain->mConfigDisplay; } else { return defaultConfig; } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 748484b0f0b90..de5bf2c9c239b 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -125,7 +125,7 @@ static const GPUSettingsQA& GPUQA_GetConfig(GPUChainTracking* chain) #if !defined(GPUCA_STANDALONE) static GPUSettingsQA defaultConfig; if (chain && chain->mConfigQA) { - return *((const GPUSettingsQA*)chain->mConfigQA); + return *chain->mConfigQA; } else { return defaultConfig; } From 417191b1f30a74fe8f694f7ffdfe0666b2b96a0c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 14:35:04 +0100 Subject: [PATCH 1314/1751] GPU: use standard ROOT colors when shipping TCanvas to QC --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 24 ++++++++++++++---------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 1 - 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index de5bf2c9c239b..b9efccec0a614 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -190,21 +190,19 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; -std::vector<Color_t> GPUQA::mColorNums; std::vector<TColor> GPUQA::mColors; int GPUQA::initColors() { - mColorNums.resize(COLORCOUNT); mColors.reserve(COLORCOUNT); for (int i = 0; i < COLORCOUNT; i++) { float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; mColors.emplace_back(10000 + i, f1, f2, f3); - mColorNums[i] = mColors.back().GetNumber(); } return 0; } +static constexpr Color_t defaultColorNUms[COLORCOUNT] = {kRed, kBlue, kGreen, kMagenta, kOrange, kAzure, kBlack, kYellow, kGray, kTeal, kSpring, kPink}; #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" @@ -1662,6 +1660,12 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (!mQAInitialized) { return 1; } + + std::vector<Color_t> colorNums(COLORCOUNT); + for (int i = 0; i < COLORCOUNT; i++) { + colorNums[i] = qcout ? defaultColorNUms[i] : mColors[i].GetNumber(); + } + bool mcAvail = mcPresent(); char name[2048], fname[1024]; @@ -1878,7 +1882,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) continue; } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); + e->SetLineColor(colorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -2104,7 +2108,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -2194,7 +2198,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) continue; } - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); } if (mRunForQC && !mConfig.shipToQCAsCanvas) { @@ -2360,7 +2364,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw(j == end - 1 && k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%s%s", fname, CLUSTER_NAMES[j - begin]); @@ -2377,7 +2381,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) continue; } - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw("same"); mLClust[i]->AddEntry(e, "Removed", "l"); } @@ -2435,7 +2439,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) qcout->Add(e); } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[k % COLORCOUNT]); + e->SetLineColor(colorNums[k % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%sTrack Pt", fname); @@ -2477,7 +2481,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) qcout->Add(e); } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[k % COLORCOUNT]); + e->SetLineColor(colorNums[k % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%sNClusters", fname); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index d9beaa8b887b1..63f24cbf70327 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -280,7 +280,6 @@ class GPUQA std::vector<std::vector<bool>> mGoodTracks; std::vector<std::vector<bool>> mGoodHits; - static std::vector<Color_t> mColorNums; static std::vector<TColor> mColors; static int initColors(); From 332521152cf0b2044b57b323f376d33a7065079a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 15:07:18 +0100 Subject: [PATCH 1315/1751] GPU QA: Use reasonable canvas names --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index b9efccec0a614..7fadcbbe066e0 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -1429,7 +1429,7 @@ void GPUQA::RunQA(bool matchOnly) GPUWarning("No MC information available, only running partial TPC QA!"); } - // Fill other histograms + // Fill track statistic histograms for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if (!track.OK()) { @@ -1693,7 +1693,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas / Pads for Efficiency Histograms for (int ii = 0; ii < 6; ii++) { int i = ii == 5 ? 4 : ii; - sprintf(fname, "ceff_%d", ii); + sprintf(fname, "eff_vs_%s_layout", VSPARAMETER_NAMES[ii]); sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); mCEff[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); mCEff[ii]->cd(); @@ -1717,10 +1717,11 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas / Pads for Resolution Histograms for (int ii = 0; ii < 7; ii++) { int i = ii == 5 ? 4 : ii; - sprintf(fname, "cres_%d", ii); if (ii == 6) { + sprintf(fname, "res_integral_layout"); sprintf(name, "Integral Resolution"); } else { + sprintf(fname, "res_vs_%s_layout", VSPARAMETER_NAMES[ii]); sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); } mCRes[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); @@ -1755,10 +1756,12 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas / Pads for Pull Histograms for (int ii = 0; ii < 7; ii++) { int i = ii == 5 ? 4 : ii; - sprintf(fname, "cpull_%d", ii); + if (ii == 6) { + sprintf(fname, "pull_integral_layout"); sprintf(name, "Integral Pull"); } else { + sprintf(fname, "pull_vs_%s_layout", VSPARAMETER_NAMES[ii]); sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); } mCPull[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); @@ -1792,7 +1795,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas for Cluster Histos for (int i = 0; i < 3; i++) { - sprintf(fname, "cclust_%d", i); + sprintf(fname, "clusters_%s_layout", CLUSTER_TYPES[i]); mCClust[i] = createGarbageCollected<TCanvas>(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); mCClust[i]->cd(); mPClust[i] = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); @@ -1802,8 +1805,8 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) SetLegend(mLClust[i]); } - // Create Canvas for other histos - { + // Create Canvas for track statistic histos + if (!mRunForQC) { mCTracks = createGarbageCollected<TCanvas>("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); mCTracks->cd(); mPTracks = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); @@ -2406,7 +2409,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } - // Process track histograms + // Process track statistic histograms if (!mRunForQC) { float tmpMax = 0.; for (int k = 0; k < ConfigNumInputs; k++) { From 5f5811b4eb6bee891d02b57a20da706f7ba5d6be Mon Sep 17 00:00:00 2001 From: vfeuilla <71069003+vfeuilla@users.noreply.github.com> Date: Fri, 13 Nov 2020 09:12:29 +0100 Subject: [PATCH 1316/1751] Small Updates for dimuon analysis (#4821) * Modifications to include the p x dca variable, used to select muons * Update to allow event and track selection. Same as tableMaker.cxx but without centrality * Updates: - Use of partitions for event selection - addition of the p x dca cut - Use of the kIsMuonSingleLowPt7 trigger --- Analysis/Core/include/Analysis/VarManager.h | 2 + Analysis/Core/src/VarManager.cxx | 2 + .../include/Analysis/ReducedInfoTables.h | 3 +- Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 172 +++++++++++----- Analysis/Tasks/PWGDQ/tableMaker_pp.cxx | 186 +++++++++++++----- .../include/Framework/AnalysisDataModel.h | 10 + 6 files changed, 272 insertions(+), 103 deletions(-) diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 568064a5e5d29..ebe8127dec4c7 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -150,6 +150,7 @@ class VarManager : public TObject kMuonBendingCoor, kMuonNonBendingCoor, kMuonRAtAbsorberEnd, + kMuonPDca, kMuonChi2, kMuonChi2MatchTrigger, kNMuonTrackVariables, @@ -440,6 +441,7 @@ void VarManager::FillTrack(T const& track, float* values) values[kMuonBendingCoor] = track.bendingCoor(); values[kMuonNonBendingCoor] = track.nonBendingCoor(); values[kMuonRAtAbsorberEnd] = track.rAtAbsorberEnd(); + values[kMuonPDca] = track.pDca(); values[kMuonChi2] = track.chi2(); values[kMuonChi2MatchTrigger] = track.chi2MatchTrigger(); } diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 553555f5060b8..211e3a33fb6de 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -216,6 +216,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kMuonNonBendingCoor] = ""; fgVariableNames[kMuonRAtAbsorberEnd] = "R at the end of the absorber"; fgVariableUnits[kMuonRAtAbsorberEnd] = ""; + fgVariableNames[kMuonPDca] = "p x dca"; + fgVariableUnits[kMuonPDca] = "cm x GeV/c"; fgVariableNames[kMuonChi2] = "#chi 2"; fgVariableUnits[kMuonChi2] = ""; fgVariableNames[kMuonChi2MatchTrigger] = "#chi 2 trigger match"; diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 66f047ea2a8bc..2bb1e7d4f617d 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -135,7 +135,8 @@ DECLARE_SOA_TABLE(ReducedMuonsExtended, "AOD", "RTMUONEXTENDED", muon::ThetaX, muon::ThetaY, muon::ZMu, muon::BendingCoor, muon::NonBendingCoor, muon::Chi2, muon::Chi2MatchTrigger, - muon::RAtAbsorberEnd<muon::BendingCoor, muon::NonBendingCoor, muon::ThetaX, muon::ThetaY, muon::ZMu>); + muon::RAtAbsorberEnd<muon::BendingCoor, muon::NonBendingCoor, muon::ThetaX, muon::ThetaY, muon::ZMu>, + muon::PDca<muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY, muon::BendingCoor, muon::NonBendingCoor, muon::ZMu>); // iterators using ReducedTrack = ReducedTracks::iterator; diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx index c5e366856e8c2..07e0865fa411e 100644 --- a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -24,6 +24,7 @@ #include <THashList.h> #include <TString.h> #include <iostream> +#include <vector> using std::cout; using std::endl; @@ -36,6 +37,13 @@ using namespace o2::aod; // Some definitions namespace o2::aod { + +namespace reducedevent +{ +DECLARE_SOA_COLUMN(Category, category, int); +DECLARE_SOA_COLUMN(IsEventSelected, isEventSelected, int); +} // namespace reducedevent + namespace reducedtrack { DECLARE_SOA_COLUMN(IsMuonSelected, isMuonSelected, int); @@ -55,15 +63,19 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt DECLARE_SOA_DYNAMIC_COLUMN(Pmom, pmom, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); } // namespace reducedpair +DECLARE_SOA_TABLE(EventCuts, "AOD", "EVENTCUTS", reducedevent::IsEventSelected); +DECLARE_SOA_TABLE(EventCategories, "AOD", "EVENTCATEGORIES", reducedevent::Category); DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "MUONTRACKCUTS", reducedtrack::IsMuonSelected); } // namespace o2::aod -using MyEvent = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended>::iterator; -using MyEventVtxCov = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>::iterator; +using MyEvents = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended>; +using MyEventsSelected = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::EventCuts>; +using MyEventsVtxCov = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov>; +using MyEventsVtxCovSelected = soa::Join<aod::ReducedEvents, aod::ReducedEventsExtended, aod::ReducedEventsVtxCov, aod::EventCuts>; using MyMuonTracks = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended>; using MyMuonTracksSelected = soa::Join<aod::ReducedMuons, aod::ReducedMuonsExtended, aod::MuonTrackCuts>; -void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TString histClasses); +void DefineHistograms(HistogramManager* 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 @@ -72,13 +84,68 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin // 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 fgEventMuonFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; -constexpr static uint32_t fgMuonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackMuon; +constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; +constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackMuon; + +struct EventSelection { + Produces<aod::EventCuts> eventSel; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; + AnalysisCompositeCut* fEventCut; + + float* fValues; + + void init(o2::framework::InitContext&) + { + fValues = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + + DefineCuts(); + } + + void DefineCuts() + { + fEventCut = new AnalysisCompositeCut(true); + + AnalysisCut* varCut = new AnalysisCut(); + varCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + varCut->AddCut(VarManager::kIsMuonSingleLowPt7, 0.5, 1.5); + + fEventCut->AddCut(varCut); + // TODO: Add more cuts, also enable cuts which are not easily possible via the VarManager (e.g. trigger selections) + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvents::iterator const& event) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); + + VarManager::FillEvent<gkEventFillMap>(event, fValues); + fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event + if (fEventCut->IsSelected(fValues)) { + fHistMan->FillHistClass("Event_AfterCuts", fValues); + eventSel(1); + } else { + eventSel(0); + } + } +}; struct MuonTrackSelection { Produces<aod::MuonTrackCuts> trackSel; - OutputObj<HistogramManager> fHistMan{"output"}; - AnalysisCompositeCut* fMuonCut; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; + AnalysisCompositeCut* fMuonCut23; + AnalysisCompositeCut* fMuonCut310; float* fValues; // array to be used by the VarManager @@ -86,45 +153,58 @@ struct MuonTrackSelection { { fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan = 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 + fOutputList.setObject(fHistMan->GetMainHistogramList()); // provide the list of required variables so that VarManager knows what to fill DefineCuts(); } void DefineCuts() { - fMuonCut = new AnalysisCompositeCut(true); - AnalysisCut kineMuonCut; - kineMuonCut.AddCut(VarManager::kPt, 1.0, 20); - kineMuonCut.AddCut(VarManager::kEta, -4.0, -2.5); - kineMuonCut.AddCut(VarManager::kMuonChi2, 0.0, 1e6); - kineMuonCut.AddCut(VarManager::kMuonRAtAbsorberEnd, 17.6, 89.5); - fMuonCut->AddCut(&kineMuonCut); + fMuonCut23 = new AnalysisCompositeCut(true); + AnalysisCut kineMuonCut23; + kineMuonCut23.AddCut(VarManager::kPt, 1.0, 20); + kineMuonCut23.AddCut(VarManager::kEta, -4.0, -2.5); + kineMuonCut23.AddCut(VarManager::kMuonChi2, 0.0, 1e6); + // The value of sigma_PDCA depends on the postion w.r.t the absorber. For 17.6 < RAbs < 26.5cm, sigma_PDCA = 99 cmxGeV/c. For 26.5 < RAbs < 89.5 cm, sigma_PDCA = 54 + // temporarily not applied + // kineMuonCut23.AddCut(VarManager::kMuonRAtAbsorberEnd, 17.6, 26.5); + // kineMuonCut23.AddCut(VarManager::kMuonPDca, 0.0, 594); // Cut is pDCA < 6*sigma_PDCA + fMuonCut23->AddCut(&kineMuonCut23); + + fMuonCut310 = new AnalysisCompositeCut(true); + AnalysisCut kineMuonCut310; + kineMuonCut310.AddCut(VarManager::kPt, 1.0, 20); + kineMuonCut310.AddCut(VarManager::kEta, -4.0, -2.5); + kineMuonCut310.AddCut(VarManager::kMuonChi2, 0.0, 1e6); + // The value of sigma_PDCA depends on the postion w.r.t the absorber. For 17.6 < RAbs < 26.5cm, sigma_PDCA = 99 cmxGeV/c. For 26.5 < RAbs < 89.5 cm, sigma_PDCA = 54 + // temporarily not applied + // kineMuonCut310.AddCut(VarManager::kMuonRAtAbsorberEnd, 26.5, 89.5); + // kineMuonCut310.AddCut(VarManager::kMuonPDca, 0.0, 324); // Cut is pDCA < 6*sigma_PDCA + fMuonCut310->AddCut(&kineMuonCut310); VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - void process(MyEvent event, MyMuonTracks const& muons) + void process(MyEventsSelected::iterator const& event, MyMuonTracks const& muons) { - 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<fgEventMuonFillMap>(event, fValues); + VarManager::ResetValues(0, VarManager::kNMuonTrackVariables, fValues); + VarManager::FillEvent<gkEventFillMap>(event, fValues); for (auto& muon : muons) { - for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) { - fValues[i] = -9999.0f; - } - VarManager::FillTrack<fgMuonFillMap>(muon, fValues); + //VarManager::ResetValues(VarManager::kNBarrelTrackVariables, VarManager::kNMuonTrackVariables, fValues); + VarManager::FillTrack<gkMuonFillMap>(muon, fValues); fHistMan->FillHistClass("TrackMuon_BeforeCuts", fValues); - if (fMuonCut->IsSelected(fValues)) { + if (fMuonCut23->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); + } else if (fMuonCut310->IsSelected(fValues)) { trackSel(1); fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); } else { @@ -135,37 +215,34 @@ struct MuonTrackSelection { }; struct DileptonMuMu { - OutputObj<HistogramManager> fHistMan{"outputMuons"}; - AnalysisCompositeCut* fEventCut; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; AnalysisCompositeCut* fDiMuonCut; //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition // NOTE TO THE NOTE: a dimuon cut is needed on the rapidity of the pair. So I added one. Hopefully this works + float* fValues; + Partition<MyMuonTracksSelected> posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; Partition<MyMuonTracksSelected> negMuons = aod::reducedtrack::charge < 0 && aod::reducedtrack::isMuonSelected == 1; void init(o2::framework::InitContext&) { + fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); - DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;PairsMuonULS;PairsMuonLSpp;PairsMuonLSnn;"); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + DefineHistograms(fHistMan, "PairsMuonULS;PairsMuonLSpp;PairsMuonLSnn;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); 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); - fDiMuonCut = new AnalysisCompositeCut(true); AnalysisCut* diMuonCut = new AnalysisCut(); diMuonCut->AddCut(VarManager::kRap, 2.5, 4.0); @@ -174,18 +251,15 @@ struct DileptonMuMu { VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - void process(MyEventVtxCov event, MyMuonTracksSelected const& tracks) + void process(MyEventsVtxCovSelected::iterator const& event, MyMuonTracksSelected const& tracks) { - // Reset the VarManager::fgValues array - // The reset can be done selectively, using arguments in the ResetValues() function - VarManager::ResetValues(); - - VarManager::FillEvent<fgEventMuonFillMap>(event); - fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event - if (!fEventCut->IsSelected(VarManager::fgValues)) { + if (!event.isEventSelected()) { return; } - fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars, fValues); + + VarManager::FillEvent<gkEventFillMap>(event, fValues); // same event pairing for muons for (auto& tpos : posMuons) { @@ -217,7 +291,7 @@ struct DileptonMuMu { } }; -void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TString histClasses) +void DefineHistograms(HistogramManager* histMan, TString histClasses) { // // Define here the histograms for all the classes required in analysis. @@ -295,6 +369,7 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin 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); histMan->AddHistogram(classStr.Data(), "RAtAbsorberEnd", "", false, 140, 10, 150, VarManager::kMuonRAtAbsorberEnd); + histMan->AddHistogram(classStr.Data(), "p x dca", "", false, 700, 0.0, 700, VarManager::kMuonRAtAbsorberEnd); } } @@ -312,6 +387,7 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ + adaptAnalysisTask<EventSelection>("my-event-selection"), adaptAnalysisTask<MuonTrackSelection>("muon-track-selection"), adaptAnalysisTask<DileptonMuMu>("dilepton-mumu")}; } diff --git a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx index d629257e4f6cf..e7df44d1ec1d4 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx @@ -21,7 +21,10 @@ #include "Analysis/ReducedInfoTables.h" #include "Analysis/VarManager.h" #include "Analysis/HistogramManager.h" +#include "Analysis/AnalysisCut.h" +#include "Analysis/AnalysisCompositeCut.h" #include "PID/PIDResponse.h" +#include "Analysis/TrackSelectionTables.h" #include <iostream> using std::cout; @@ -32,6 +35,19 @@ using namespace o2::framework; //using namespace o2::framework::expressions; using namespace o2::aod; +using MyEvents = soa::Join<aod::Collisions, aod::EvSels>; +using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::TracksExtended, aod::TrackSelection, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta>; + +// 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 gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; +constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; + struct TableMaker_pp { Produces<ReducedEvents> event; @@ -44,31 +60,71 @@ struct TableMaker_pp { Produces<ReducedMuons> muonBasic; Produces<ReducedMuonsExtended> muonExtended; - OutputObj<HistogramManager> fHistMan{"output"}; + float* fValues; + + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; + + // TODO: Filters should be used to make lowest level selection. The additional more restrictive cuts should be defined via the AnalysisCuts + // TODO: Multiple event selections can be applied and decisions stored in the reducedevent::tag + AnalysisCompositeCut* fEventCut; + // TODO: Multiple track selections can be applied and decisions stored in the reducedtrack::filteringFlags + // Cuts should be defined using Configurables (prepare cut libraries, as discussed in O2 DQ meetings) + AnalysisCompositeCut* fTrackCut; - // 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::BC | VarManager::ObjTypes::Collision; - constexpr static uint32_t fgTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackCov; + // Partition will select fast a group of tracks with basic requirements + // If some of the cuts cannot be included in the Partition expression, add them via AnalysisCut(s) + Partition<MyBarrelTracks> barrelSelectedTracks = o2::aod::track::pt >= 1.0f && nabs(o2::aod::track::eta) <= 0.9f && o2::aod::track::tpcSignal >= 70.0f && o2::aod::track::tpcSignal <= 100.0f && o2::aod::track::tpcChi2NCl < 4.0f && o2::aod::track::itsChi2NCl < 36.0f; + + // TODO a few of the important muon variables in the central data model are dynamic columns so not usable in expressions (e.g. eta, phi) + // Update the data model to have them as expression columns + Partition<aod::Muons> muonSelectedTracks = o2::aod::muon::pt >= 0.5f; // For pp collisions a 0.5 GeV/c pp cuts is defined void init(o2::framework::InitContext&) { + fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); - fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); - + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); - DefineHistograms("Event;"); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + DefineHistograms("Event_BeforeCuts;Event_AfterCuts;TrackBarrel_BeforeCuts;TrackBarrel_AfterCuts"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + DefineCuts(); + } + + void DefineCuts() + { + fEventCut = new AnalysisCompositeCut(true); + AnalysisCut* eventVarCut = new AnalysisCut(); + eventVarCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + eventVarCut->AddCut(VarManager::kIsINT7, 0.5, 1.5); // require kINT7 + fEventCut->AddCut(eventVarCut); + + fTrackCut = new AnalysisCompositeCut(true); + AnalysisCut* trackVarCut = new AnalysisCut(); + //trackVarCut->AddCut(VarManager::kPt, 1.0, 1000.0); + //trackVarCut->AddCut(VarManager::kEta, -0.9, 0.9); + //trackVarCut->AddCut(VarManager::kTPCsignal, 70.0, 100.0); + trackVarCut->AddCut(VarManager::kIsITSrefit, 0.5, 1.5); + trackVarCut->AddCut(VarManager::kIsTPCrefit, 0.5, 1.5); + //trackVarCut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + //trackVarCut->AddCut(VarManager::kITSchi2, 0.1, 36.0); + trackVarCut->AddCut(VarManager::kTPCncls, 100.0, 161.); + + AnalysisCut* pidCut1 = new AnalysisCut(); + TF1* cutLow1 = new TF1("cutLow1", "pol1", 0., 10.); + cutLow1->SetParameters(130., -40.0); + pidCut1->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + + fTrackCut->AddCut(trackVarCut); + fTrackCut->AddCut(pidCut1); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - void process(soa::Join<aod::Collisions, aod::EvSels>::iterator collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov /*, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta*/> const& tracksBarrel) + void process(MyEvents::iterator const& collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs, MyBarrelTracks const& tracksBarrel) { uint64_t tag = 0; uint32_t triggerAliases = 0; @@ -78,66 +134,68 @@ struct TableMaker_pp { } } - VarManager::ResetValues(); - VarManager::FillEvent<fgEventFillMap>(collision); // extract event information and place it in the fgValues array - fHistMan->FillHistClass("Event", VarManager::fgValues); // automatically fill all the histograms in the class Event + VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); + VarManager::FillEvent<gkEventFillMap>(collision, fValues); // extract event information and place it in the fgValues array + fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event + + if (!fEventCut->IsSelected(fValues)) { + return; + } + + fHistMan->FillHistClass("Event_AfterCuts", fValues); event(tag, collision.bc().runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib()); eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), triggerAliases, 0.0f); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); uint64_t trackFilteringTag = 0; - float sinAlpha = 0.f; - float cosAlpha = 0.f; - float globalX = 0.f; - float globalY = 0.f; - float dcaXY = 0.f; - float dcaZ = 0.f; - for (auto& track : tracksBarrel) { - - if (track.pt() < 0.15) { - continue; - } - if (TMath::Abs(track.eta()) > 0.9) { + trackBasic.reserve(barrelSelectedTracks.size()); + trackBarrel.reserve(barrelSelectedTracks.size()); + trackBarrelCov.reserve(barrelSelectedTracks.size()); + trackBarrelPID.reserve(barrelSelectedTracks.size()); + + for (auto& track : barrelSelectedTracks) { + VarManager::FillTrack<gkTrackFillMap>(track, fValues); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + if (!fTrackCut->IsSelected(fValues)) { continue; } + fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); - sinAlpha = sin(track.alpha()); - cosAlpha = cos(track.alpha()); - globalX = track.x() * cosAlpha - track.y() * sinAlpha; - globalY = track.x() * sinAlpha + track.y() * cosAlpha; - - dcaXY = sqrt(pow((globalX - collision.posX()), 2) + - pow((globalY - collision.posY()), 2)); - dcaZ = sqrt(pow(track.z() - collision.posZ(), 2)); - - trackBasic(collision, track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); + if (track.isGlobalTrack()) { + trackFilteringTag |= (uint64_t(1) << 0); + } + if (track.isGlobalTrackSDD()) { + trackFilteringTag |= (uint64_t(1) << 1); + } + trackBasic(event.lastIndex(), track.globalIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.charge()); trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.trdChi2(), track.tofChi2(), - track.length(), dcaXY, dcaZ); + track.length(), track.dcaXY(), track.dcaZ()); trackBarrelCov(track.cYY(), track.cZZ(), track.cSnpSnp(), track.cTglTgl(), track.c1Pt21Pt2()); trackBarrelPID(track.tpcSignal(), - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - //track.tpcNSigmaEl(), track.tpcNSigmaMu(), - //track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - //track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), - //track.tofSignal(), track.beta(), - //track.tofNSigmaEl(), track.tofNSigmaMu(), - //track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - //track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), - //track.trdSignal()); + track.tpcNSigmaEl(), track.tpcNSigmaMu(), + track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), + track.tofSignal(), track.beta(), + track.tofNSigmaEl(), track.tofNSigmaMu(), + track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), + track.trdSignal()); } - for (auto& muon : tracksMuon) { + muonBasic.reserve(muonSelectedTracks.size()); + muonExtended.reserve(muonSelectedTracks.size()); + for (auto& muon : muonSelectedTracks) { // TODO: add proper information for muon tracks - if (muon.bc() != collision.bc()) { + if (muon.bcId() != collision.bcId()) { continue; } + // TODO: the trackFilteringTag will not be needed to encode whether the track is a muon since there is a dedicated table for muons trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track - muonBasic(collision, trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); + muonBasic(event.lastIndex(), trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); } } @@ -169,6 +227,26 @@ struct TableMaker_pp { 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 30, -15., 15., VarManager::kVtxZ, "", "", "", VarManager::kVtxNcontrib); // TProfile3D } + + 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 + + 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(), "TPCncls_Run", "Number of cluster in TPC", true, kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, + 10, -0.5, 159.5, VarManager::kTPCncls, 10, 0., 1., VarManager::kNothing, runsStr.Data()); // 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(), "DCAxy", "DCAxy", false, 100, -3.0, 3.0, VarManager::kTrackDCAxy); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "DCAz", "DCAz", false, 100, -5.0, 5.0, VarManager::kTrackDCAz); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "IsGlobalTrack", "IsGlobalTrack", false, 2, -0.5, 1.5, VarManager::kIsGlobalTrack); // TH1F histogram + fHistMan->AddHistogram(classStr.Data(), "IsGlobalTrackSDD", "IsGlobalTrackSDD", false, 2, -0.5, 1.5, VarManager::kIsGlobalTrackSDD); // TH1F histogram + } + } } // end loop over histogram classes } }; diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index c3a9ff1271b40..6c8d89a7985c2 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -347,6 +347,15 @@ DECLARE_SOA_DYNAMIC_COLUMN(RAtAbsorberEnd, rAtAbsorberEnd, [](float bendingCoor, float rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); return rAtAbsorberEnd; }); +DECLARE_SOA_DYNAMIC_COLUMN(PDca, pDca, [](float inverseBendingMomentum, float thetaX, float thetaY, float bendingCoor, float nonBendingCoor, float zMu) -> float { + // linear extrapolation of the coordinates of the track to the position of the end of the absorber (-505 cm) + float dca = std::sqrt(bendingCoor * bendingCoor + nonBendingCoor * nonBendingCoor + zMu * zMu); + float pz = -std::sqrt(1.0 + std::tan(thetaY) * std::tan(thetaY)) / std::abs(inverseBendingMomentum); + float pt = std::abs(pz) * std::sqrt(std::tan(thetaX) * std::tan(thetaX) + std::tan(thetaY) * std::tan(thetaY)); + float pTot = std::sqrt(pt * pt + pz * pz); + float pDca = pTot * dca; + return pDca; +}); DECLARE_SOA_EXPRESSION_COLUMN(Pt, pt, float, nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) * nsqrt(ntan(aod::muon::thetaX) * ntan(aod::muon::thetaX) + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); DECLARE_SOA_EXPRESSION_COLUMN(Px, px, float, -1.0f * ntan(aod::muon::thetaX) * nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, -1.0f * ntan(aod::muon::thetaY) * nsqrt(1.0f + ntan(aod::muon::thetaY) * ntan(aod::muon::thetaY)) / nabs(aod::muon::inverseBendingMomentum)); @@ -362,6 +371,7 @@ DECLARE_SOA_TABLE_FULL(StoredMuons, "Muons", "AOD", "MUON", muon::Eta<muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY>, muon::Phi<muon::ThetaX, muon::ThetaY>, muon::RAtAbsorberEnd<muon::BendingCoor, muon::NonBendingCoor, muon::ThetaX, muon::ThetaY, muon::ZMu>, + muon::PDca<muon::InverseBendingMomentum, muon::ThetaX, muon::ThetaY, muon::BendingCoor, muon::NonBendingCoor, muon::ZMu>, muon::Charge<muon::InverseBendingMomentum>); DECLARE_SOA_EXTENDED_TABLE(Muons, StoredMuons, "MUON", From 61d783da4fbd991d9a7dcad0ef660a3bec286553 Mon Sep 17 00:00:00 2001 From: Iouri Belikov <iouri.belikov@cern.ch> Date: Thu, 29 Oct 2020 10:16:47 +0100 Subject: [PATCH 1317/1751] Include multi-pixel clusters into the noise calibration --- .../DataFormatsITSMFT/ClusterPattern.h | 2 +- .../DataFormatsITSMFT/TopologyDictionary.h | 2 +- .../ITSMFT/common/src/TopologyDictionary.cxx | 10 +++- .../macros/Calib/MakeNoiseMapFromClusters.C | 51 +++++++++++++++---- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 2 +- .../ITS/reconstruction/src/CookedTracker.cxx | 2 +- Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx | 6 +-- .../common/reconstruction/src/Clusterer.cxx | 11 ++-- 8 files changed, 62 insertions(+), 24 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h index ea03d1496711d..3769e28ddf762 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h @@ -82,7 +82,7 @@ class ClusterPattern /// Sets the whole bitmask: the number of rows, the number of columns and the pattern void setPattern(const unsigned char bitmask[kExtendedPatternBytes]); /// Static: Compute pattern's COG position. Returns the number of fired pixels - static int getCOG(int nRow, int nCol, const unsigned char patt[MaxPatternBytes], float& xCOG, float& zCOG); + static int getCOG(int rowSpan, int colSpan, const unsigned char patt[MaxPatternBytes], float& xCOG, float& zCOG); /// Compute pattern's COG position. Returns the number of fired pixels int getCOG(float& xCOG, float& zCOG) const; diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h index 3110151973538..8668075dc4302 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h @@ -157,7 +157,7 @@ class TopologyDictionary ///Returns the local position of a compact cluster math_utils::Point3D<float> getClusterCoordinates(const CompCluster& cl) const; ///Returns the local position of a compact cluster - static math_utils::Point3D<float> getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt); + static math_utils::Point3D<float> getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt, bool isGroup = true); friend BuildTopologyDictionary; friend LookUp; diff --git a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx index fe5c1a4e2aacd..7a6cb413d671c 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx @@ -135,12 +135,18 @@ math_utils::Point3D<float> TopologyDictionary::getClusterCoordinates(const CompC return locCl; } -math_utils::Point3D<float> TopologyDictionary::getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt) +math_utils::Point3D<float> TopologyDictionary::getClusterCoordinates(const CompCluster& cl, const ClusterPattern& patt, bool isGroup) { + auto refRow = cl.getRow(); + auto refCol = cl.getCol(); float xCOG = 0, zCOG = 0; patt.getCOG(xCOG, zCOG); + if (isGroup) { + refRow -= round(xCOG); + refCol -= round(zCOG); + } math_utils::Point3D<float> locCl; - o2::itsmft::SegmentationAlpide::detectorToLocalUnchecked(cl.getRow() - round(xCOG) + xCOG, cl.getCol() - round(zCOG) + zCOG, locCl); + o2::itsmft::SegmentationAlpide::detectorToLocalUnchecked(refRow + xCOG, refCol + zCOG, locCl); return locCl; } diff --git a/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C index cc5b7967fcbf8..83c91765c85f0 100644 --- a/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C +++ b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C @@ -13,7 +13,7 @@ #endif -void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string output = "noise.root", int threshold = 3) +void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string output = "noise.root", bool only1pix = true) { TFile in(input.data()); if (!in.IsOpen()) { @@ -43,7 +43,6 @@ void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string o2::itsmft::NoiseMap noiseMap(24120); - int n1pix = 0; auto nevents = clusTree->GetEntries(); for (int n = 0; n < nevents; n++) { clusTree->GetEntry(n); @@ -53,23 +52,53 @@ void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string for (const auto& c : clustersInFrame) { if (c.getPatternID() != o2::itsmft::CompCluster::InvalidPatternID) continue; + o2::itsmft::ClusterPattern patt(pattIt); - if (patt.getRowSpan() != 1) - continue; - if (patt.getColumnSpan() != 1) - continue; + auto id = c.getSensorID(); auto row = c.getRow(); auto col = c.getCol(); - noiseMap.increaseNoiseCount(id, row, col); - n1pix++; + auto colSpan = patt.getColumnSpan(); + auto rowSpan = patt.getRowSpan(); + + if ((rowSpan == 1) && (colSpan == 1)) { + noiseMap.increaseNoiseCount(id, row, col); + continue; + } + + if (only1pix) + continue; + + auto nBits = rowSpan * colSpan; + int ic = 0, ir = 0; + for (unsigned int i = 2; i < patt.getUsedBytes() + 2; i++) { + unsigned char tempChar = patt.getByte(i); + int s = 128; // 0b10000000 + while (s > 0) { + if ((tempChar & s) != 0) { + noiseMap.increaseNoiseCount(id, row + ir, col + ic); + } + ic++; + s >>= 1; + if ((ir + 1) * ic == nBits) { + break; + } + if (ic == colSpan) { + ic = 0; + ir++; + } + } + if ((ir + 1) * ic == nBits) { + break; + } + } } } } - int ncalib = noiseMap.dumpAboveThreshold(threshold); - std::cout << "Threshold: " << threshold << " number of pixels: " << ncalib << '\n'; - std::cout << "Number of 1-pixel clusters: " << n1pix << '\n'; + int ncalib = noiseMap.dumpAboveThreshold(3); + std::cout << "Threshold: 3" + << " number of pixels: " << ncalib << '\n'; TFile out(output.data(), "new"); if (!out.IsOpen()) { diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index 226fe7bc37551..a7e7034e3f66c 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -208,7 +208,7 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", auto locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local auto locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); locH.SetXYZ(0.5 * (locH.X() + locHsta.X()), 0.5 * (locH.Y() + locHsta.Y()), 0.5 * (locH.Z() + locHsta.Z())); - const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern); + const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern, false); dX = locH.X() - locC.X(); dZ = locH.Z() - locC.Z(); } else { diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx index b70282cd5416c..0e0303dd97701 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/CookedTracker.cxx @@ -516,7 +516,7 @@ void CookedTracker::process(gsl::span<const o2::itsmft::CompClusterExt> const& c } } else { o2::itsmft::ClusterPattern patt(pattIt); - locXYZ = dict.getClusterCoordinates(comp, patt); + locXYZ = dict.getClusterCoordinates(comp, patt, false); } auto sensorID = comp.getSensorID(); // Inverse transformation to the local --> tracking diff --git a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx index e521443b8da2a..f3cecb7c53944 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx @@ -73,7 +73,7 @@ void ioutils::convertCompactClusters(gsl::span<const itsmft::CompClusterExt> clu } } else { o2::itsmft::ClusterPattern patt(pattIt); - locXYZ = dict.getClusterCoordinates(c, patt); + locXYZ = dict.getClusterCoordinates(c, patt, false); } auto& cl3d = output.emplace_back(c.getSensorID(), geom->getMatrixT2L(c.getSensorID()) ^ locXYZ); // local --> tracking cl3d.setErrors(sigmaY2, sigmaZ2, sigmaYZ); @@ -172,7 +172,7 @@ void ioutils::loadEventData(ROframe& event, gsl::span<const itsmft::CompClusterE } } else { o2::itsmft::ClusterPattern patt(pattIt); - locXYZ = dict.getClusterCoordinates(c, patt); + locXYZ = dict.getClusterCoordinates(c, patt, false); } auto sensorID = c.getSensorID(); // Inverse transformation to the local --> tracking @@ -221,7 +221,7 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g } } else { o2::itsmft::ClusterPattern patt(pattIt); - locXYZ = dict.getClusterCoordinates(c, patt); + locXYZ = dict.getClusterCoordinates(c, patt, false); } auto sensorID = c.getSensorID(); // Inverse transformation to the local --> tracking diff --git a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx index 60bb389ad93ee..741b0fd28d6fc 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx @@ -309,10 +309,13 @@ void Clusterer::ClustererThread::streamCluster(const std::vector<PixelData>& pix } uint16_t pattID = (isHuge || parent->mPattIdConverter.size() == 0) ? CompCluster::InvalidPatternID : parent->mPattIdConverter.findGroupID(rowSpanW, colSpanW, patt); if (pattID == CompCluster::InvalidPatternID || parent->mPattIdConverter.isGroup(pattID)) { - float xCOG = 0., zCOG = 0.; - ClusterPattern::getCOG(rowSpanW, colSpanW, patt, xCOG, zCOG); - rowMin += round(xCOG); - colMin += round(zCOG); + if (pattID != CompCluster::InvalidPatternID) { + //For groupped topologies, the reference pixel is the COG pixel + float xCOG = 0., zCOG = 0.; + ClusterPattern::getCOG(rowSpanW, colSpanW, patt, xCOG, zCOG); + rowMin += round(xCOG); + colMin += round(zCOG); + } if (patternsPtr) { patternsPtr->emplace_back((unsigned char)rowSpanW); patternsPtr->emplace_back((unsigned char)colSpanW); From c004c6c3bbb218a1116dae36e251325471ca5ea9 Mon Sep 17 00:00:00 2001 From: Iouri Belikov <iouri.belikov@cern.ch> Date: Sat, 7 Nov 2020 15:24:36 +0100 Subject: [PATCH 1318/1751] Setting the noise-map threshold in terms of pixel-firing probability --- .../include/DataFormatsITSMFT/NoiseMap.h | 40 ++++++++++++++++++- .../macros/Calib/MakeNoiseMapFromClusters.C | 11 +++-- .../ITSMFTReconstruction/AlpideCoder.h | 13 +----- .../common/reconstruction/src/AlpideCoder.cxx | 1 - 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h index 6c0bbf77d40af..bc3f826145e91 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/NoiseMap.h @@ -87,11 +87,49 @@ class NoiseMap } return n; } + int dumpAboveProbThreshold(float p = 1e-7) const + { + return dumpAboveThreshold(p * mNumOfStrobes); + } + + void applyProbThreshold(float t, long int n) + { + // Remove from the maps all pixels with the firing probability below the threshold + mProbThreshold = t; + mNumOfStrobes = n; + for (auto& map : mNoisyPixels) { + for (auto it = map.begin(); it != map.end();) { + float prob = float(it->second) / mNumOfStrobes; + if (prob < mProbThreshold) { + it = map.erase(it); + } else { + ++it; + } + } + } + } + float getProbThreshold() const { return mProbThreshold; } + long int getNumOfStrobes() const { return mNumOfStrobes; } + + bool isNoisy(int chip, int row, int col) const + { + if (chip > mNoisyPixels.size()) { + return false; + } + auto key = row * 1024 + col; + const auto keyIt = mNoisyPixels[chip].find(key); + if (keyIt != mNoisyPixels[chip].end()) { + return true; + } + return false; + } private: std::vector<std::map<int, int>> mNoisyPixels; ///< Internal noise map representation + long int mNumOfStrobes = 0; ///< Accumulated number of ALPIDE strobes + float mProbThreshold = 0; ///< Probability threshold for noisy pixels - ClassDefNV(NoiseMap, 1); + ClassDefNV(NoiseMap, 2); }; } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C index 83c91765c85f0..07badfbf0888b 100644 --- a/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C +++ b/Detectors/ITSMFT/ITS/macros/Calib/MakeNoiseMapFromClusters.C @@ -13,7 +13,7 @@ #endif -void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string output = "noise.root", bool only1pix = true) +void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string output = "noise.root", bool only1pix = false, float probT = 3e-6) { TFile in(input.data()); if (!in.IsOpen()) { @@ -43,11 +43,13 @@ void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string o2::itsmft::NoiseMap noiseMap(24120); + long int nStrobes = 0; auto nevents = clusTree->GetEntries(); for (int n = 0; n < nevents; n++) { clusTree->GetEntry(n); auto pattIt = patternsPtr->cbegin(); for (const auto& rof : *rofVec) { + nStrobes++; auto clustersInFrame = rof.getROFData(*clusters); for (const auto& c : clustersInFrame) { if (c.getPatternID() != o2::itsmft::CompCluster::InvalidPatternID) @@ -96,8 +98,11 @@ void MakeNoiseMapFromClusters(std::string input = "o2clus_its.root", std::string } } - int ncalib = noiseMap.dumpAboveThreshold(3); - std::cout << "Threshold: 3" + noiseMap.applyProbThreshold(probT, nStrobes); + + int fired = probT * nStrobes; + int ncalib = noiseMap.dumpAboveThreshold(fired); + std::cout << "Probalibity threshold: " << probT << " number of pixels: " << ncalib << '\n'; TFile out(output.data(), "new"); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h index e6aed3815c70c..6a11db0fa8e1a 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h @@ -115,7 +115,6 @@ class AlpideCoder static bool isEmptyChip(uint8_t b) { return (b & CHIPEMPTY) == CHIPEMPTY; } static void setNoisyPixels(const NoiseMap* noise) { mNoisyPixels = noise; } - static void setNoiseThreshold(int t) { mNoiseThreshold = t; } /// decode alpide data for the next non-empty chip from the buffer template <class T, typename CG> @@ -323,13 +322,6 @@ class AlpideCoder // void print() const; void reset(); - // - template <class T> - static int getChipID(T& buffer) - { - uint8_t id = 0; - return (buffer.current(id) && isChipHeaderOrEmpty(id)) ? (id & AlpideCoder::MaskChipID) : -1; - } private: /// Output a non-noisy fired pixel @@ -337,7 +329,7 @@ class AlpideCoder { if (mNoisyPixels) { auto chipID = chipData.getChipID(); - if (mNoisyPixels->getNoiseLevel(chipID, row, col) > mNoiseThreshold) { + if (mNoisyPixels->isNoisy(chipID, row, col)) { return; } } @@ -423,13 +415,12 @@ class AlpideCoder // static const NoiseMap* mNoisyPixels; - static int mNoiseThreshold; // cluster map used for the ENCODING only std::vector<int> mFirstInRow; //! entry of 1st pixel of each non-empty row in the mPix2Encode std::vector<PixLink> mPix2Encode; //! pool of links: fired pixel + index of the next one in the row // - ClassDefNV(AlpideCoder, 2); + ClassDefNV(AlpideCoder, 3); }; } // namespace itsmft diff --git a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx index f9a62ac0667fa..8008767b69d08 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx @@ -18,7 +18,6 @@ using namespace o2::itsmft; const NoiseMap* AlpideCoder::mNoisyPixels = nullptr; -int AlpideCoder::mNoiseThreshold = 3; //_____________________________________ void AlpideCoder::print() const From 30fe1c8c3ec5ed382ddb6389c5fece6c89b22ab1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 13 Nov 2020 14:31:32 +0100 Subject: [PATCH 1319/1751] DPL: introduce --no-cleanup option to avoid cleaning shared memory (#4830) --- Framework/Core/src/DriverInfo.h | 2 ++ Framework/Core/src/runDataProcessing.cxx | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DriverInfo.h b/Framework/Core/src/DriverInfo.h index 972012ce19838..2b2d4b0c8cfbc 100644 --- a/Framework/Core/src/DriverInfo.h +++ b/Framework/Core/src/DriverInfo.h @@ -138,6 +138,8 @@ struct DriverInfo { short tracyPort = 8086; /// Aggregate metrics calculated in the driver itself DeviceMetricsInfo metrics; + /// Skip shared memory cleanup if set + bool noSHMCleanup; }; } // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 079d1e59697f1..9ad45a114f2b7 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -980,7 +980,11 @@ int runStateMachine(DataProcessorSpecs const& workflow, /// Cleanup the shared memory for the uniqueWorkflowId, in /// case we are unlucky and an old one is already present. - cleanupSHM(driverInfo.uniqueWorkflowId); + if (driverInfo.noSHMCleanup) { + LOGP(warning, "Not cleaning up shared memory."); + } else { + cleanupSHM(driverInfo.uniqueWorkflowId); + } /// After INIT we go into RUNNING and eventually to SCHEDULE from /// there and back into running. This is because the general case /// would be that we start an application and then we wait for @@ -1280,7 +1284,11 @@ int runStateMachine(DataProcessorSpecs const& workflow, } LOG(INFO) << "Dumping used configuration in dpl-config.json"; boost::property_tree::write_json("dpl-config.json", finalConfig); - cleanupSHM(driverInfo.uniqueWorkflowId); + if (driverInfo.noSHMCleanup) { + LOGP(warning, "Not cleaning up shared memory."); + } else { + cleanupSHM(driverInfo.uniqueWorkflowId); + } return calculateExitCode(deviceSpecs, infos); } case DriverState::PERFORM_CALLBACKS: @@ -1580,6 +1588,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, ("stop,s", bpo::value<bool>()->zero_tokens()->default_value(false), "stop before device start") // // ("single-step", bpo::value<bool>()->zero_tokens()->default_value(false), "start in single step mode") // // ("batch,b", bpo::value<bool>()->zero_tokens()->default_value(isatty(fileno(stdout)) == 0), "batch processing mode") // // + ("no-cleanup", bpo::value<bool>()->zero_tokens()->default_value(false), "do not cleanup the shm segment") // // ("hostname", bpo::value<std::string>()->default_value("localhost"), "hostname to deploy") // // ("resources", bpo::value<std::string>()->default_value(""), "resources allocated for the workflow") // // ("start-port,p", bpo::value<unsigned short>()->default_value(22000), "start port to allocate") // // @@ -1792,6 +1801,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, driverInfo.argc = argc; driverInfo.argv = argv; driverInfo.batch = varmap["batch"].as<bool>(); + driverInfo.noSHMCleanup = varmap["no-cleanup"].as<bool>(); driverInfo.terminationPolicy = varmap["completion-policy"].as<TerminationPolicy>(); if (varmap["error-policy"].defaulted() && driverInfo.batch == false) { driverInfo.errorPolicy = TerminationPolicy::WAIT; From 97f1b21e875bf6229255382d92abf8463ddcc029 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 13 Nov 2020 12:27:52 +0100 Subject: [PATCH 1320/1751] Fix codechecker error --- .../include/SimulationDataFormat/ConstMCTruthContainer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h index 855ec6f2bf254..f287dd56803b7 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -131,7 +131,7 @@ class ConstMCTruthContainerView public: ConstMCTruthContainerView(gsl::span<const char> const bufferview) : mStorage(bufferview){}; ConstMCTruthContainerView(ConstMCTruthContainer<TruthElement> const& cont) : mStorage(gsl::span<const char>(cont)){}; - ConstMCTruthContainerView() : mStorage(nullptr, (gsl::span<const char>::index_type)0){}; // be explicit that we want nullptr / 0 for an uninitialized container + ConstMCTruthContainerView() : mStorage(nullptr, (gsl::span<const char>::index_type)0) { (void)0; } // be explicit that we want nullptr / 0 for an uninitialized container ConstMCTruthContainerView(const ConstMCTruthContainerView&) = default; // const data access From 9ccc8ffc96c1026bde3f3035bf67d99c255d99e7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 13 Nov 2020 10:41:42 +0100 Subject: [PATCH 1321/1751] GPU: Initialize GPU settings from configKeyValues if compiled in O2 and not set externally --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 14 +++++++++++++- GPU/GPUTracking/Base/GPUSettingsList.h | 2 +- .../Interface/GPUO2InterfaceConfigurableParam.cxx | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 45982367e2304..b4bb8be7dd81c 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -45,6 +45,10 @@ #define GPUCA_LOGGING_PRINTF #include "GPULogging.h" +#ifdef GPUCA_O2_LIB +#include "GPUO2InterfaceConfiguration.h" +#endif + namespace GPUCA_NAMESPACE { namespace gpu @@ -954,10 +958,18 @@ int GPUReconstruction::ReadSettings(const char* dir) void GPUReconstruction::SetSettings(float solenoidBz, const GPURecoStepConfiguration* workflow) { +#ifdef GPUCA_O2_LIB + GPUO2InterfaceConfiguration config; + config.ReadConfigurableParam(); + if (config.configEvent.solenoidBz <= -1e6f) { + config.configEvent.solenoidBz = solenoidBz; + } + SetSettings(&config.configEvent, &config.configReconstruction, &config.configProcessing, workflow); +#else GPUSettingsEvent ev; - new (&ev) GPUSettingsEvent; ev.solenoidBz = solenoidBz; SetSettings(&ev, nullptr, nullptr, workflow); +#endif } void GPUReconstruction::SetSettings(const GPUSettingsEvent* settings, const GPUSettingsRec* rec, const GPUSettingsProcessing* proc, const GPURecoStepConfiguration* workflow) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 34455f08d47ca..ba703182e656e 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -266,7 +266,7 @@ AddSubConfig(GPUSettingsEG, EG) EndConfig() #elif defined(GPUCA_O2_LIB) || defined(GPUCA_O2_INTERFACE) // GPUCA_STANDALONE BeginSubConfig(GPUSettingsO2, global, configStandalone, "O2", 0, "O2 workflow settings") -AddOption(solenoidBz, float, -1000.f, "", 0, "solenoid field strength") +AddOption(solenoidBz, float, -1e6f, "", 0, "solenoid field strength") AddOption(constBz, bool, false, "", 0, "force constant Bz for tests") AddOption(continuousMaxTimeBin, int, 0, "", 0, "maximum time bin of continuous data, 0 for triggered events, -1 for default of 23ms") AddOption(deviceType, std::string, "CPU", "", 0, "Device type, CPU | CUDA | HIP | OCL1 | OCL2") diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx index 6f00ea4431117..55f754a88b4e5 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx @@ -100,7 +100,7 @@ GPUSettingsO2 GPUO2InterfaceConfiguration::ReadConfigurableParam() if (global.continuousMaxTimeBin) { configEvent.continuousMaxTimeBin = global.continuousMaxTimeBin; } - if (global.solenoidBz > -1000.f) { + if (global.solenoidBz > -1e6f) { configEvent.solenoidBz = global.solenoidBz; } if (global.constBz) { From a40e2012af36a66d8733d6e860737d6f6317d762 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 26 Oct 2020 12:35:20 +0100 Subject: [PATCH 1322/1751] Use unique board ID in LocalBoardRO --- .../MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h | 2 +- Detectors/MUON/MID/Raw/include/MIDRaw/CrateMapper.h | 6 +++--- Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx | 4 ++-- Detectors/MUON/MID/Raw/src/CrateMapper.cxx | 2 +- Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx | 4 ++-- Detectors/MUON/MID/Raw/test/testRaw.cxx | 6 ------ 6 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h b/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h index c2ad23e532fcf..2df9b6a7acf49 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/ColumnDataToLocalBoard.h @@ -39,7 +39,7 @@ class ColumnDataToLocalBoard private: bool keepBoard(const LocalBoardRO& loc) const; - std::unordered_map<uint16_t, LocalBoardRO> mLocalBoardsMap{}; /// Map of data per board + std::unordered_map<uint8_t, LocalBoardRO> mLocalBoardsMap{}; /// Map of data per board std::unordered_map<uint16_t, std::vector<LocalBoardRO>> mGBTMap{}; /// Map of data per GBT link CrateMapper mCrateMapper{}; /// Crate mapper Mapping mMapping{}; /// Segmentation diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/CrateMapper.h b/Detectors/MUON/MID/Raw/include/MIDRaw/CrateMapper.h index 2ca9f7ef90cf0..dc6a8bda346f2 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/CrateMapper.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/CrateMapper.h @@ -36,14 +36,14 @@ class CrateMapper static uint8_t getColumnId(uint16_t deBoardId) { return (deBoardId >> 4) & 0x7; } /// Gets the line ID from the DE board ID static uint8_t getLineId(uint16_t deBoardId) { return (deBoardId >> 7) & 0x3; } - uint16_t deLocalBoardToRO(uint8_t deId, uint8_t columnId, uint8_t lineId) const; + uint8_t deLocalBoardToRO(uint8_t deId, uint8_t columnId, uint8_t lineId) const; uint16_t roLocalBoardToDE(uint8_t crateId, uint8_t boardId) const; private: void init(); - std::unordered_map<uint16_t, uint16_t> mROToDEMap; /// Correspondence between RO and DE board - std::unordered_map<uint16_t, uint16_t> mDEToROMap; /// Correspondence between DE and RO board + std::unordered_map<uint8_t, uint16_t> mROToDEMap; /// Correspondence between RO and DE board + std::unordered_map<uint16_t, uint8_t> mDEToROMap; /// Correspondence between DE and RO board }; } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx b/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx index 69b67e7a78457..539f65542d0e5 100644 --- a/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx +++ b/Detectors/MUON/MID/Raw/src/ColumnDataToLocalBoard.cxx @@ -47,7 +47,7 @@ void ColumnDataToLocalBoard::process(gsl::span<const ColumnData> data) auto uniqueLocId = mCrateMapper.deLocalBoardToRO(col.deId, col.columnId, iline); auto& roData = mLocalBoardsMap[uniqueLocId]; roData.statusWord = raw::sSTARTBIT | raw::sCARDTYPE; - roData.boardId = crateparams::getLocId(uniqueLocId); + roData.boardId = uniqueLocId; int ich = detparams::getChamber(col.deId); roData.firedChambers |= (1 << ich); roData.patternsBP[ich] = col.getBendPattern(iline); @@ -60,7 +60,7 @@ void ColumnDataToLocalBoard::process(gsl::span<const ColumnData> data) for (auto& item : mLocalBoardsMap) { if (mDebugMode || keepBoard(item.second)) { auto crateId = crateparams::getCrateId(item.first); - auto feeId = crateparams::makeROId(crateId, crateparams::getGBTIdFromBoardInCrate(item.second.boardId)); + auto feeId = crateparams::makeROId(crateId, crateparams::getGBTIdFromBoardInCrate(crateparams::getLocId(item.second.boardId))); mGBTMap[feeId].emplace_back(item.second); } } diff --git a/Detectors/MUON/MID/Raw/src/CrateMapper.cxx b/Detectors/MUON/MID/Raw/src/CrateMapper.cxx index a691669da7657..6ad86e3680076 100644 --- a/Detectors/MUON/MID/Raw/src/CrateMapper.cxx +++ b/Detectors/MUON/MID/Raw/src/CrateMapper.cxx @@ -130,7 +130,7 @@ void CrateMapper::init() } } -uint16_t CrateMapper::deLocalBoardToRO(uint8_t deId, uint8_t columnId, uint8_t lineId) const +uint8_t CrateMapper::deLocalBoardToRO(uint8_t deId, uint8_t columnId, uint8_t lineId) const { /// Converts the local board ID in in MT11 right to the local board ID in FEE auto item = mDEToROMap.find(deBoardId(detparams::getRPCLine(deId), columnId, lineId)); diff --git a/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx b/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx index 36b00367256f1..617ec58e67f29 100644 --- a/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTUserLogicEncoder.cxx @@ -72,7 +72,7 @@ void GBTUserLogicEncoder::process(gsl::span<const LocalBoardRO> data, const Inte for (auto& loc : data) { for (int ich = 0; ich < 4; ++ich) { if (loc.patternsBP[ich] && loc.patternsNBP[ich]) { - activeBoards |= (1 << (loc.boardId % 8)); + activeBoards |= (1 << (crateparams::getLocId(loc.boardId) % 8)); } } vec.emplace_back(loc); @@ -90,7 +90,7 @@ void GBTUserLogicEncoder::flush(std::vector<char>& buffer, const InteractionReco buffer.emplace_back(loc.statusWord); buffer.emplace_back(loc.triggerWord); addShort(buffer, item.first.bc); - buffer.emplace_back((loc.boardId << 4) | loc.firedChambers); + buffer.emplace_back((crateparams::getLocId(loc.boardId) << 4) | loc.firedChambers); if (raw::isLoc(loc.statusWord)) { for (int ich = 4; ich >= 0; --ich) { if (loc.firedChambers & (1 << ich)) { diff --git a/Detectors/MUON/MID/Raw/test/testRaw.cxx b/Detectors/MUON/MID/Raw/test/testRaw.cxx index 9dc458ac0140d..2859ac6f83b8a 100644 --- a/Detectors/MUON/MID/Raw/test/testRaw.cxx +++ b/Detectors/MUON/MID/Raw/test/testRaw.cxx @@ -153,14 +153,8 @@ BOOST_AUTO_TEST_CASE(ColumnDataConverter) converter.process(item.second); auto firstEntry = outData.size(); for (auto& gbtItem : converter.getData()) { - auto crateId = o2::mid::crateparams::getCrateIdFromROId(gbtItem.first); for (auto& loc : gbtItem.second) { - // The crate ID information is not encoded in the local board information, - // since it is not needed at this level (it is encoded in the feeId) - // However, when we put the info back together, we need to know the crate ID - // So we encode it in the local board ID in the output outData.emplace_back(loc); - outData.back().boardId = o2::mid::crateparams::makeUniqueLocID(crateId, loc.boardId); } rofs.push_back({item.first, inEventType, firstEntry, outData.size() - firstEntry}); } From f8e1c5fb4504d5d349fa5df676d7ea70d2484355 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 21:05:59 +0100 Subject: [PATCH 1323/1751] GPU: Fix AliGPU compilation with AliRoot --- GPU/Common/GPUDefGPUParameters.h | 4 +++- GPU/GPUTracking/Base/GPUDataTypes.h | 2 +- GPU/TPCFastTransformation/Spline.h | 2 +- GPU/TPCFastTransformation/Spline1D.h | 2 +- GPU/TPCFastTransformation/Spline1DHelper.cxx | 2 ++ GPU/TPCFastTransformation/Spline1DHelper.h | 2 +- GPU/TPCFastTransformation/Spline1DSpec.cxx | 4 +++- GPU/TPCFastTransformation/Spline1DSpec.h | 2 +- GPU/TPCFastTransformation/Spline2D.h | 2 +- GPU/TPCFastTransformation/Spline2DHelper.cxx | 2 ++ GPU/TPCFastTransformation/Spline2DHelper.h | 2 +- GPU/TPCFastTransformation/Spline2DSpec.cxx | 2 ++ GPU/TPCFastTransformation/Spline2DSpec.h | 2 +- GPU/TPCFastTransformation/SplineHelper.cxx | 4 ++-- GPU/TPCFastTransformation/SplineSpec.cxx | 2 ++ GPU/TPCFastTransformation/SplineSpec.h | 2 +- GPU/TPCFastTransformation/TPCFastTransformManager.cxx | 2 +- GPU/Utils/FlatObject.h | 2 ++ 18 files changed, 28 insertions(+), 14 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index d1bb0bc16676a..265932ec114aa 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -27,6 +27,7 @@ #include "GPUDefMacros.h" // GPU Run Configuration +#ifdef GPUCA_GPUCODE #if defined(GPUCA_GPUTYPE_VEGA) #define GPUCA_WARP_SIZE 64 #define GPUCA_THREAD_COUNT 256 @@ -196,9 +197,10 @@ #define GPUCA_MERGER_INTERPOLATION_ERROR_TYPE half // #define GPUCA_USE_TEXTURES #elif defined(GPUCA_GPUTYPE_OPENCL) -#elif defined(GPUCA_GPUCODE) +#else #error GPU TYPE NOT SET #endif +#endif // GPUCA_GPUCODE #ifdef GPUCA_GPUCODE // Default settings, if not already set for selected GPU type diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index 7795e7fa6e5e1..521e5b737880e 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -69,7 +69,7 @@ namespace gpu { class TPCFastTransform; class TPCdEdxCalibrationSplines; -class TPCCFCalibration; +struct TPCCFCalibration; } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/TPCFastTransformation/Spline.h b/GPU/TPCFastTransformation/Spline.h index c6f3360fa9827..ef06f560c76e9 100644 --- a/GPU/TPCFastTransformation/Spline.h +++ b/GPU/TPCFastTransformation/Spline.h @@ -98,7 +98,7 @@ class Spline Spline(const Spline&) CON_DELETE; #endif -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) /// read a class object from the file static Spline* readFromFile(TFile& inpf, const char* name) { diff --git a/GPU/TPCFastTransformation/Spline1D.h b/GPU/TPCFastTransformation/Spline1D.h index 0f3b0ce9a9a0e..772231386d112 100644 --- a/GPU/TPCFastTransformation/Spline1D.h +++ b/GPU/TPCFastTransformation/Spline1D.h @@ -159,7 +159,7 @@ class Spline1D Spline1D(const Spline1D&) CON_DELETE; #endif -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) /// read a class object from the file static Spline1D* readFromFile(TFile& inpf, const char* name) { diff --git a/GPU/TPCFastTransformation/Spline1DHelper.cxx b/GPU/TPCFastTransformation/Spline1DHelper.cxx index 1ffe26fbf006a..ac0998fe9529c 100644 --- a/GPU/TPCFastTransformation/Spline1DHelper.cxx +++ b/GPU/TPCFastTransformation/Spline1DHelper.cxx @@ -485,6 +485,7 @@ void Spline1DHelper<DataT>::approximateDerivatives( } } +#ifndef GPUCA_ALIROOT_LIB template <typename DataT> int Spline1DHelper<DataT>::test(const bool draw, const bool drawDataPoints) { @@ -735,6 +736,7 @@ int Spline1DHelper<DataT>::test(const bool draw, const bool drawDataPoints) } return 0; } +#endif template class GPUCA_NAMESPACE::gpu::Spline1DHelper<float>; template class GPUCA_NAMESPACE::gpu::Spline1DHelper<double>; diff --git a/GPU/TPCFastTransformation/Spline1DHelper.h b/GPU/TPCFastTransformation/Spline1DHelper.h index cb83c13e446d2..07dcc8827597e 100644 --- a/GPU/TPCFastTransformation/Spline1DHelper.h +++ b/GPU/TPCFastTransformation/Spline1DHelper.h @@ -117,7 +117,7 @@ class Spline1DHelper /// Gives error string const char* getLastError() const { return mError.c_str(); } -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) // code invisible on GPU and in the standalone compilation /// Test the Spline1D class functionality static int test(const bool draw = 0, const bool drawDataPoints = 1); #endif diff --git a/GPU/TPCFastTransformation/Spline1DSpec.cxx b/GPU/TPCFastTransformation/Spline1DSpec.cxx index 66bd249147e6c..002e9cd173940 100644 --- a/GPU/TPCFastTransformation/Spline1DSpec.cxx +++ b/GPU/TPCFastTransformation/Spline1DSpec.cxx @@ -175,6 +175,7 @@ void Spline1DContainer<DataT>::approximateFunction( helper.approximateFunction(*reinterpret_cast<Spline1D<DataT>*>(this), xMin, xMax, F, nAxiliaryDataPoints); } +#ifndef GPUCA_ALIROOT_LIB template <class DataT> int Spline1DContainer<DataT>::writeToFile(TFile& outf, const char* name) { @@ -190,6 +191,7 @@ Spline1DContainer<DataT>* Spline1DContainer<DataT>::readFromFile( return FlatObject::readFromFile<Spline1DContainer<DataT>>(inpf, name); } +#endif #endif #if !defined(GPUCA_GPUCODE) @@ -261,7 +263,7 @@ void Spline1DContainer<DataT>::setFutureBufferAddress(char* futureFlatBufferPtr) FlatObject::setFutureBufferAddress(futureFlatBufferPtr); } -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) template <class DataT> int Spline1DContainer<DataT>::test(const bool draw, const bool drawDataPoints) { diff --git a/GPU/TPCFastTransformation/Spline1DSpec.h b/GPU/TPCFastTransformation/Spline1DSpec.h index da9f7facab7fb..9b7a3357fd0e6 100644 --- a/GPU/TPCFastTransformation/Spline1DSpec.h +++ b/GPU/TPCFastTransformation/Spline1DSpec.h @@ -169,7 +169,7 @@ class Spline1DContainer : public FlatObject ///_______________ Test tools _______________ -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) // code invisible on GPU and in the standalone compilation /// Test the class functionality static int test(const bool draw = 0, const bool drawDataPoints = 1); #endif diff --git a/GPU/TPCFastTransformation/Spline2D.h b/GPU/TPCFastTransformation/Spline2D.h index cab8865429332..f4dfe34c7b2fc 100644 --- a/GPU/TPCFastTransformation/Spline2D.h +++ b/GPU/TPCFastTransformation/Spline2D.h @@ -95,7 +95,7 @@ class Spline2D Spline2D(const Spline2D&) CON_DELETE; #endif -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) /// read a class object from the file static Spline2D* readFromFile(TFile& inpf, const char* name) { diff --git a/GPU/TPCFastTransformation/Spline2DHelper.cxx b/GPU/TPCFastTransformation/Spline2DHelper.cxx index cef92f3cac620..0833b9e0a3be9 100644 --- a/GPU/TPCFastTransformation/Spline2DHelper.cxx +++ b/GPU/TPCFastTransformation/Spline2DHelper.cxx @@ -222,6 +222,7 @@ void Spline2DHelper<DataT>::approximateFunction( } } +#ifndef GPUCA_ALIROOT_LIB template <typename DataT> int Spline2DHelper<DataT>::test(const bool draw, const bool drawDataPoints) { @@ -477,6 +478,7 @@ int Spline2DHelper<DataT>::test(const bool draw, const bool drawDataPoints) return 0; } +#endif template class GPUCA_NAMESPACE::gpu::Spline2DHelper<float>; template class GPUCA_NAMESPACE::gpu::Spline2DHelper<double>; diff --git a/GPU/TPCFastTransformation/Spline2DHelper.h b/GPU/TPCFastTransformation/Spline2DHelper.h index 2b59406219144..76f11bf8cc709 100644 --- a/GPU/TPCFastTransformation/Spline2DHelper.h +++ b/GPU/TPCFastTransformation/Spline2DHelper.h @@ -96,7 +96,7 @@ class Spline2DHelper /// Gives error string const char* getLastError() const { return mError.c_str(); } -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) // code invisible on GPU and in the standalone compilation /// Test the Spline2D class functionality static int test(const bool draw = 0, const bool drawDataPoints = 1); #endif diff --git a/GPU/TPCFastTransformation/Spline2DSpec.cxx b/GPU/TPCFastTransformation/Spline2DSpec.cxx index 0efbb68f78ef9..7e96f73e6b254 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.cxx +++ b/GPU/TPCFastTransformation/Spline2DSpec.cxx @@ -203,6 +203,7 @@ void Spline2DContainer<DataT>::approximateFunction( helper.approximateFunction(*reinterpret_cast<Spline2D<DataT>*>(this), x1Min, x1Max, x2Min, x2Max, F, nAuxiliaryDataPointsX1, nAuxiliaryDataPointsX2); } +#ifndef GPUCA_ALIROOT_LIB template <typename DataT> int Spline2DContainer<DataT>::writeToFile(TFile& outf, const char* name) { @@ -223,6 +224,7 @@ int Spline2DContainer<DataT>::test(const bool draw, const bool drawDataPoints) { return Spline2DHelper<DataT>::test(draw, drawDataPoints); } +#endif #endif // GPUCA_GPUCODE && !GPUCA_STANDALONE diff --git a/GPU/TPCFastTransformation/Spline2DSpec.h b/GPU/TPCFastTransformation/Spline2DSpec.h index 1a4dbf9412291..68c8518dc81b6 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.h +++ b/GPU/TPCFastTransformation/Spline2DSpec.h @@ -154,7 +154,7 @@ class Spline2DContainer : public FlatObject ///_______________ Test tools _______________ -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) // code invisible on GPU and in the standalone compilation /// Test the class functionality static int test(const bool draw = 0, const bool drawDataPoints = 1); #endif diff --git a/GPU/TPCFastTransformation/SplineHelper.cxx b/GPU/TPCFastTransformation/SplineHelper.cxx index 5c03c85a0b627..2cba30b391468 100644 --- a/GPU/TPCFastTransformation/SplineHelper.cxx +++ b/GPU/TPCFastTransformation/SplineHelper.cxx @@ -478,8 +478,8 @@ int SplineHelper<DataT>::test(const bool draw, const bool drawDataPoints) } } - o2::gpu::Spline<float, nDimX, nDimY> spline(nKnots, knotsU); - o2::gpu::Spline2D<float, nDimY> spline2D(nKnots[0], knotsU[0], nKnots[1], knotsU[1]); + Spline<float, nDimX, nDimY> spline(nKnots, knotsU); + Spline2D<float, nDimY> spline2D(nKnots[0], knotsU[0], nKnots[1], knotsU[1]); cout << "mark 1" << std::endl; spline.approximateFunction(xMin, xMax, F, nAxiliaryDatapoints); diff --git a/GPU/TPCFastTransformation/SplineSpec.cxx b/GPU/TPCFastTransformation/SplineSpec.cxx index 865da5c42fadc..35beb0d3c8417 100644 --- a/GPU/TPCFastTransformation/SplineSpec.cxx +++ b/GPU/TPCFastTransformation/SplineSpec.cxx @@ -205,6 +205,7 @@ void SplineContainer<DataT>:: helper.approximateFunction(*reinterpret_cast<Spline<DataT>*>(this), xMin, xMax, F, nAuxiliaryDataPoints); } +#ifndef GPUCA_ALIROOT_LIB template <typename DataT> int SplineContainer<DataT>::writeToFile(TFile& outf, const char* name) { @@ -225,6 +226,7 @@ int SplineContainer<DataT>::test(const bool draw, const bool drawDataPoints) { return SplineHelper<DataT>::test(draw, drawDataPoints); } +#endif #endif // GPUCA_GPUCODE && !GPUCA_STANDALONE diff --git a/GPU/TPCFastTransformation/SplineSpec.h b/GPU/TPCFastTransformation/SplineSpec.h index e18c7ddff456b..6217415dd7c74 100644 --- a/GPU/TPCFastTransformation/SplineSpec.h +++ b/GPU/TPCFastTransformation/SplineSpec.h @@ -149,7 +149,7 @@ class SplineContainer : public FlatObject ///_______________ Test tools _______________ -#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) && !defined(GPUCA_ALIROOT_LIB) // code invisible on GPU and in the standalone compilation /// Test the class functionality static int test(const bool draw = 0, const bool drawDataPoints = 1); #endif diff --git a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx index 71a606d0ab44c..4fbc08c2e8ba1 100644 --- a/GPU/TPCFastTransformation/TPCFastTransformManager.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransformManager.cxx @@ -282,7 +282,7 @@ int TPCFastTransformManager::updateCalibration(TPCFastTransform& fastTransform, Spline2DHelper<float> helper; helper.setSpline(spline, 4, 4); - auto F = [&](float su, float sv, float dxuv[3]) { + auto F = [&](double su, double sv, double dxuv[3]) { float x = rowInfo.x; // x, u, v cordinates of the knot (local cartesian coord. of slice // towards central electrode ) diff --git a/GPU/Utils/FlatObject.h b/GPU/Utils/FlatObject.h index 3fa85bd81ff03..8077fd18b6912 100644 --- a/GPU/Utils/FlatObject.h +++ b/GPU/Utils/FlatObject.h @@ -316,7 +316,9 @@ class FlatObject char* mFlatBufferContainer = nullptr; //[mFlatBufferSize] Optional container for the flat buffer char* mFlatBufferPtr = nullptr; //! Pointer to the flat buffer +#ifndef GPUCA_ALIROOT_LIB ClassDefNV(FlatObject, 1); +#endif }; /// ======================================================================================================== From 30a71a25a24d0bc382f8484992415160e49881ac Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 21:52:50 +0100 Subject: [PATCH 1324/1751] GPU QA: Apparently one must not delete TColors as this is cleaned up by gROOT... --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 6 +++--- GPU/GPUTracking/Standalone/qa/GPUQA.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 7fadcbbe066e0..7e86f9d9d972d 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -190,7 +190,7 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; -std::vector<TColor> GPUQA::mColors; +std::vector<TColor*> GPUQA::mColors; int GPUQA::initColors() { mColors.reserve(COLORCOUNT); @@ -198,7 +198,7 @@ int GPUQA::initColors() float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; - mColors.emplace_back(10000 + i, f1, f2, f3); + mColors.emplace_back(new TColor(10000 + i, f1, f2, f3)); } return 0; } @@ -1663,7 +1663,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) std::vector<Color_t> colorNums(COLORCOUNT); for (int i = 0; i < COLORCOUNT; i++) { - colorNums[i] = qcout ? defaultColorNUms[i] : mColors[i].GetNumber(); + colorNums[i] = qcout ? defaultColorNUms[i] : mColors[i]->GetNumber(); } bool mcAvail = mcPresent(); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 63f24cbf70327..3fd829fdf19e1 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -280,7 +280,7 @@ class GPUQA std::vector<std::vector<bool>> mGoodTracks; std::vector<std::vector<bool>> mGoodHits; - static std::vector<TColor> mColors; + static std::vector<TColor*> mColors; static int initColors(); int mMCTrackMin = -1, mMCTrackMax = -1; From 94a301e9284f05fa2eb35020fbed52c53313f6c6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 12 Nov 2020 22:34:46 +0100 Subject: [PATCH 1325/1751] GPU: Fix clearing scratch memory also on host side when kept in sync with GPU for standalone event display --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 16c8ef2c9cab2..96839d6841f54 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1557,7 +1557,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() if (GetProcessingSettings().debugLevel >= 3) { GPUInfo("Copying Slice Data to GPU and initializing temporary memory"); } - if (GetProcessingSettings().keepAllMemory && !doSliceDataOnGPU) { + if (GetProcessingSettings().keepDisplayMemory && !doSliceDataOnGPU) { memset((void*)trk.Data().HitWeights(), 0, trkShadow.Data().NumberOfHitsPlusAlign() * sizeof(*trkShadow.Data().HitWeights())); } else { runKernel<GPUMemClean16>(GetGridAutoStep(useStream, RecoStep::TPCSliceTracking), krnlRunRangeNone, {}, trkShadow.Data().HitWeights(), trkShadow.Data().NumberOfHitsPlusAlign() * sizeof(*trkShadow.Data().HitWeights())); From de38ee0af3bcb973f02d2070a5f822312dbf1e93 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 13 Nov 2020 09:16:33 +0100 Subject: [PATCH 1326/1751] GPU: Fix for compilation with HIP --- Common/MathUtils/include/MathUtils/detail/trigonometric.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/MathUtils/include/MathUtils/detail/trigonometric.h b/Common/MathUtils/include/MathUtils/detail/trigonometric.h index d689de575610d..5ea0609af8634 100644 --- a/Common/MathUtils/include/MathUtils/detail/trigonometric.h +++ b/Common/MathUtils/include/MathUtils/detail/trigonometric.h @@ -120,7 +120,7 @@ GPUdi() void sincos(double ang, double& s, double& c) #ifndef GPUCA_GPUCODE_DEVICE template <typename T> -GPUdi() std::tuple<T, T> sincos(T ang) +GPUhdi() std::tuple<T, T> sincos(T ang) { T sin = 0; T cos = 0; From 1d76c89b835f93e0b5e64aa1b7384e805657810f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 13 Nov 2020 09:52:46 +0100 Subject: [PATCH 1327/1751] Fix compile warning --- GPU/Common/GPUCommonMath.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index b537a0be067da..fa6994e757177 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -244,7 +244,7 @@ GPUhdi() void GPUCommonMath::SinCos(float x, float& s, float& c) #elif !defined(GPUCA_GPUCODE_DEVICE) && defined(__GNU_SOURCE__) sincosf(x, &s, &c); #else - CHOICE({s = sin(x); c = cos(x); }, sincosf(x, &s, &c), s = sincos(x, &c)); + CHOICE((void)((s = sinf(x)) + (c = cosf(x))), sincosf(x, &s, &c), s = sincos(x, &c)); #endif } @@ -255,7 +255,7 @@ GPUhdi() void GPUCommonMath::SinCos(double x, double& s, double& c) #elif !defined(GPUCA_GPUCODE_DEVICE) && defined(__GNU_SOURCE__) sincos(x, &s, &c); #else - CHOICE({s = sin(x); c = cos(x); }, sincos(x, &s, &c), s = sincos(x, &c)); + CHOICE((void)((s = sin(x)) + (c = cos(x))), sincos(x, &s, &c), s = sincos(x, &c)); #endif } From 4ec29d1fd56612be7bc4103aa24b78d5bdbbad03 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 13 Nov 2020 09:53:07 +0100 Subject: [PATCH 1328/1751] GPU: Use sincos optimization also on the host --- GPU/Common/GPUCommonMath.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index fa6994e757177..b82e430f807a3 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -241,7 +241,7 @@ GPUhdi() void GPUCommonMath::SinCos(float x, float& s, float& c) { #if !defined(GPUCA_GPUCODE_DEVICE) && defined(__APPLE__) __sincosf(x, &s, &c); -#elif !defined(GPUCA_GPUCODE_DEVICE) && defined(__GNU_SOURCE__) +#elif !defined(GPUCA_GPUCODE_DEVICE) && (defined(__GNU_SOURCE__) || defined(_GNU_SOURCE) || defined(GPUCA_GPUCODE)) sincosf(x, &s, &c); #else CHOICE((void)((s = sinf(x)) + (c = cosf(x))), sincosf(x, &s, &c), s = sincos(x, &c)); @@ -252,7 +252,7 @@ GPUhdi() void GPUCommonMath::SinCos(double x, double& s, double& c) { #if !defined(GPUCA_GPUCODE_DEVICE) && defined(__APPLE__) __sincos(x, &s, &c); -#elif !defined(GPUCA_GPUCODE_DEVICE) && defined(__GNU_SOURCE__) +#elif !defined(GPUCA_GPUCODE_DEVICE) && (defined(__GNU_SOURCE__) || defined(_GNU_SOURCE) || defined(GPUCA_GPUCODE)) sincos(x, &s, &c); #else CHOICE((void)((s = sin(x)) + (c = cos(x))), sincos(x, &s, &c), s = sincos(x, &c)); From 139a20812279014511ddf915546c4cc41f03bbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20von=20Haller?= <barthelemy.von.haller@cern.ch> Date: Mon, 16 Nov 2020 09:54:07 +0100 Subject: [PATCH 1329/1751] [QC-451] Adapt the adapter to the rawFormat 1 of Readout (#4814) --- Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx index 1eee4db1f86ed..4c613af6eb6f1 100644 --- a/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx +++ b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx @@ -25,19 +25,19 @@ static std::atomic<unsigned int> blockId = 0; InjectorFunction dataSamplingReadoutAdapter(OutputSpec const& spec) { return [spec](FairMQDevice& device, FairMQParts& parts, ChannelRetriever channelRetriever) { - for (size_t i = 0; i < parts.Size() / 2; ++i) { + for (size_t i = 0; i < parts.Size(); ++i) { DataHeader dh; ConcreteDataTypeMatcher dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec); dh.dataOrigin = dataType.origin; dh.dataDescription = dataType.description; dh.subSpecification = DataSpecUtils::getOptionalSubSpec(spec).value_or(0xFF); - dh.payloadSize = parts.At(2 * i + 1)->GetSize(); + dh.payloadSize = parts.At(i)->GetSize(); dh.payloadSerializationMethod = o2::header::gSerializationMethodNone; DataProcessingHeader dph{++blockId, 0}; o2::header::Stack headerStack{dh, dph}; - sendOnChannel(device, std::move(headerStack), std::move(parts.At(2 * i + 1)), spec, channelRetriever); + sendOnChannel(device, std::move(headerStack), std::move(parts.At(i)), spec, channelRetriever); } }; } From 8e5b5b1748c50fae9aa2dba6723c05a357619044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20von=20Haller?= <barthelemy.von.haller@cern.ch> Date: Mon, 16 Nov 2020 10:00:19 +0100 Subject: [PATCH 1330/1751] [O2-1749] Forward declare inputrecord (#4783) --- Framework/Core/include/Framework/ProcessingContext.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Framework/Core/include/Framework/ProcessingContext.h b/Framework/Core/include/Framework/ProcessingContext.h index fe85785922ef2..264b0679019f8 100644 --- a/Framework/Core/include/Framework/ProcessingContext.h +++ b/Framework/Core/include/Framework/ProcessingContext.h @@ -10,15 +10,14 @@ #ifndef O2_FRAMEWORK_PROCESSINGCONTEXT_H_ #define O2_FRAMEWORK_PROCESSINGCONTEXT_H_ -#include "Framework/InputRecord.h" - namespace o2::framework { struct ServiceRegistry; struct DataAllocator; +struct InputRecord; -// This is a utility class to reduce the amount of boilerplate when defining +// This is a utility class to reduce the amount of boilerplate when defining // an algorithm. class ProcessingContext { From d5f945ed3c49ab4faa990f6f206d8af28c58e220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Mon, 16 Nov 2020 10:57:49 +0100 Subject: [PATCH 1331/1751] PWGHF: Extend MC gen. matching to N prongs. Improve rec. matching. Add more MC tasks and histograms. (#4829) * Add N-prong MC gen. matching. * Add 3-prong MC tasks. * Check daughter index order. * Use histogram registry in the D0 task. * Add D0 MC histograms. * Check number of daughters in MC rec. matching. * Improve MC rec. matching. Check number of daughters. Check stepdaughters. Check twin daughters. Rearrange checks. * Add MC pseudorapidity histograms. --- Analysis/Core/include/Analysis/RecoDecay.h | 116 ++++++++----- .../include/Analysis/HFSecondaryVertex.h | 21 ++- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 10 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 48 +++++- Analysis/Tasks/PWGHF/taskD0.cxx | 153 +++++++++++++----- 5 files changed, 263 insertions(+), 85 deletions(-) diff --git a/Analysis/Core/include/Analysis/RecoDecay.h b/Analysis/Core/include/Analysis/RecoDecay.h index 39ac36afba093..530b920724d08 100644 --- a/Analysis/Core/include/Analysis/RecoDecay.h +++ b/Analysis/Core/include/Analysis/RecoDecay.h @@ -415,30 +415,72 @@ class RecoDecay template <std::size_t N, typename T, typename U> static bool isMCMatchedDecayRec(const T& particlesMC, const array<U, N>& arrDaughters, int PDGMother, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false) { - LOGF(debug, "isMCMatchedDecayRec: Expected mother PDG: %d", PDGMother); - int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle - array<o2::aod::McParticle, N> arrMothers; // array of mother particles + //Printf("MC Rec.: Expected mother PDG: %d", PDGMother); + int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle + int indexMother = -1; // index of the mother particle + int indexDaughterFirst = -1; // index of the first daughter + int indexDaughterLast = -1; // index of the last daughter + array<int, N> arrDaughtersIndex; // array of daughter indices // loop over daughter particles for (auto iProng = 0; iProng < N; ++iProng) { auto particleI = arrDaughters[iProng].label(); // ith daughter particle + arrDaughtersIndex[iProng] = particleI.globalIndex(); auto indexParticleIMother = particleI.mother0(); if (indexParticleIMother == -1) { + //Printf("MC Rec. rejected: bad mother index: %d", indexParticleIMother); return false; } - // Check mother PDG code. - auto particleIMother = particlesMC.iteratorAt(indexParticleIMother); // mother of the ith daughter - auto PDGParticleIMother = particleIMother.pdgCode(); // PDG code of the mother of the ith daughter - LOGF(debug, "isMCMatchedDecayRec: Daughter %d mother PDG: %d", iProng, PDGParticleIMother); + // Get the mother. + auto particleIMother = particlesMC.iteratorAt(indexParticleIMother); + // Check mother's PDG code. + auto PDGParticleIMother = particleIMother.pdgCode(); // PDG code of the mother of the ith daughter + //Printf("MC Rec.: Daughter %d mother PDG: %d", iProng, PDGParticleIMother); if (PDGParticleIMother != sgn * PDGMother) { if (acceptAntiParticles && iProng == 0 && PDGParticleIMother == -PDGMother) { sgn = -1; // PDG code of the first daughter's mother determines whether the expected mother is a particle or antiparticle. } else { + //Printf("MC Rec. rejected: bad mother PDG: %s%d != %d", acceptAntiParticles ? "abs " : "", PDGParticleIMother, sgn * PDGMother); return false; } } - // Check daughter PDG code. + // Check that all daughters have the same mother. + if (iProng == 0) { + indexMother = indexParticleIMother; + } else if (indexParticleIMother != indexMother) { + //Printf("MC Rec. rejected: different mothers: %d %d", indexMother, indexParticleIMother); + return false; + } + // Set the range of expected daughter indices. + if (iProng == 0) { + indexDaughterFirst = particleIMother.daughter0(); + indexDaughterLast = particleIMother.daughter1(); + // Check the daughter indices. + // Daughter indices are supposed to be consecutive. + if (indexDaughterLast <= indexDaughterFirst || indexDaughterFirst == -1 || indexDaughterLast == -1) { + //Printf("MC Rec. rejected: bad daughter index range: %d-%d", indexDaughterFirst, indexDaughterLast); + return false; + } + // Check the number of daughters. + if (indexDaughterLast - indexDaughterFirst + 1 != N) { + //Printf("MC Rec. rejected: incorrect number of daughters: %d", indexDaughterLast - indexDaughterFirst + 1); + return false; + } + } + // Check that the daughter is not a stepdaughter. + if (arrDaughtersIndex[iProng] < indexDaughterFirst || arrDaughtersIndex[iProng] > indexDaughterLast) { + //Printf("MC Rec. rejected: stepdaughter: %d outside %d-%d", arrDaughtersIndex[iProng], indexDaughterFirst, indexDaughterLast); + return false; + } + // Check that the daughter is not a twin. + for (auto jProng = 0; jProng < iProng; ++jProng) { + if (arrDaughtersIndex[iProng] == arrDaughtersIndex[jProng]) { + //Printf("MC Rec. rejected: twin daughter: %d", arrDaughtersIndex[iProng]); + return false; + } + } + // Check daughter's PDG code. auto PDGParticleI = particleI.pdgCode(); // PDG code of the ith daughter - LOGF(debug, "isMCMatchedDecayRec: Daughter %d PDG: %d", iProng, PDGParticleI); + //Printf("MC Rec: Daughter %d PDG: %d", iProng, PDGParticleI); bool PDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? for (auto iProngCp = 0; iProngCp < N; ++iProngCp) { if (PDGParticleI == sgn * arrPDGDaughters[iProngCp]) { @@ -448,17 +490,11 @@ class RecoDecay } } if (!PDGFound) { - return false; - } - arrMothers[iProng] = particleIMother; - } - // Check that all daughters have the same mother. - for (auto iProng = 1; iProng < N; ++iProng) { - if (arrMothers[iProng] != arrMothers[0]) { + //Printf("MC Rec. rejected: bad daughter PDG: %d", PDGParticleI); return false; } } - LOGF(debug, "isMCMatchedDecayRec: Matched"); + //Printf("MC Rec. accepted: m: %d, d: %d-%d", indexMother, indexDaughterFirst, indexDaughterLast); return true; } @@ -484,36 +520,43 @@ class RecoDecay template <std::size_t N, typename T, typename U> static bool isMCMatchedDecayGen(const T& particlesMC, const U& candidate, int PDGParticle, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false) { - LOGF(debug, "isMCMatchedDecayGen: Expected particle PDG: %d", PDGParticle); + //Printf("MC Gen.: Expected particle PDG: %d", PDGParticle); int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle + int indexDaughterFirst = 0; // index of the first daughter + int indexDaughterLast = 0; // index of the last daughter // Check the PDG code of the particle. auto PDGCandidate = candidate.pdgCode(); - LOGF(debug, "isMCMatchedDecayGen: Candidate PDG: %d", PDGCandidate); + //Printf("MC Gen.: Candidate PDG: %d", PDGCandidate); if (PDGCandidate != PDGParticle) { if (acceptAntiParticles && PDGCandidate == -PDGParticle) { sgn = -1; } else { + //Printf("MC Gen. rejected: bad particle PDG: %s%d != %d", acceptAntiParticles ? "abs " : "", PDGCandidate, sgn * PDGParticle); return false; } } // Check the PDG codes of the decay products. if (N > 1) { - LOGF(debug, "isMCMatchedDecayGen: Checking %d daughters", N); - auto indexCandidateDaughterI = candidate.daughter0(); - for (auto iProng = 0; iProng < N; ++iProng) { - if (iProng == 1) { - indexCandidateDaughterI = candidate.daughter1(); - } - // FIXME: 3-prong decays - //else if (iProng == 2) { - // indexCandidateDaughterI = candidate.daughter2(); - //} - if (indexCandidateDaughterI == -1) { - return false; - } - auto candidateDaughterI = particlesMC.iteratorAt(indexCandidateDaughterI); // ith daughter particle - auto PDGCandidateDaughterI = candidateDaughterI.pdgCode(); // PDG code of the ith daughter - LOGF(debug, "isMCMatchedDecayGen: Daughter %d PDG: %d", iProng, PDGCandidateDaughterI); + //Printf("MC Gen.: Checking %d daughters", N); + // Set the range of expected daughter indices. + indexDaughterFirst = candidate.daughter0(); + indexDaughterLast = candidate.daughter1(); + // Check the daughter indices. + // Daughter indices are supposed to be consecutive. + if (indexDaughterLast <= indexDaughterFirst || indexDaughterFirst == -1 || indexDaughterLast == -1) { + //Printf("MC Gen. rejected: bad daughter index range: %d-%d", indexDaughterFirst, indexDaughterLast); + return false; + } + // Check the number of daughters. + if (indexDaughterLast - indexDaughterFirst + 1 != N) { + //Printf("MC Gen. rejected: incorrect number of daughters: %d", indexDaughterLast - indexDaughterFirst + 1); + return false; + } + // Check daughters' PDG codes. + for (auto indexDaughterI = indexDaughterFirst; indexDaughterI <= indexDaughterLast; ++indexDaughterI) { + auto candidateDaughterI = particlesMC.iteratorAt(indexDaughterI); // ith daughter particle + auto PDGCandidateDaughterI = candidateDaughterI.pdgCode(); // PDG code of the ith daughter + //Printf("MC Gen.: Daughter %d PDG: %d", indexDaughterI, PDGCandidateDaughterI); bool PDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? for (auto iProngCp = 0; iProngCp < N; ++iProngCp) { if (PDGCandidateDaughterI == sgn * arrPDGDaughters[iProngCp]) { @@ -523,11 +566,12 @@ class RecoDecay } } if (!PDGFound) { + //Printf("MC Gen. rejected: bad daughter PDG: %d", PDGCandidateDaughterI); return false; } } } - LOGF(debug, "isMCMatchedDecayGen: Matched"); + //Printf("MC Gen. accepted: m: %d, d: %d-%d", candidate.globalIndex(), indexDaughterFirst, indexDaughterLast); return true; } diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 7637fd5571754..8ee186e65b55d 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -131,8 +131,10 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, [](fl DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m, double mTot, int iProng) { return RecoDecay::CosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); -DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, uint8_t); // Rec MC matching result: 0 - not matched, 1 - matched D0(bar) -DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, uint8_t); // Gen MC matching result: 0 - not matched, 1 - matched D0(bar) +// MC matching result: +// - bit 0: D0(bar) → π± K∓ +DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, uint8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, uint8_t); // generator level // functions for specific particles @@ -252,6 +254,11 @@ DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, 1.f * aod::hf_cand::pyProng0 + 1.f DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1 + 1.f * aod::hf_cand::pzProng2); DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); +// MC matching result: +// - bit 0: D± → π± K∓ π± +// - bit 1: Lc± → p± K∓ π± +DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, uint8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, uint8_t); // generator level // functions for specific particles @@ -281,7 +288,7 @@ auto InvMassDPlus(const T& candidate) return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); } -// Lc+ → p K- π+ +// Lc± → p± K∓ π± template <typename T> auto CtLc(const T& candidate) @@ -347,6 +354,14 @@ DECLARE_SOA_EXTENDED_TABLE_USER(HfCandProng3Ext, HfCandProng3Base, "HFCANDP3EXT" using HfCandProng3 = HfCandProng3Ext; +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfCandProng3MCRec, "AOD", "HFCANDP3MCREC", + hf_cand_prong3::FlagMCMatchRec); + +// table with results of generator level MC matching +DECLARE_SOA_TABLE(HfCandProng3MCGen, "AOD", "HFCANDP3MCGEN", + hf_cand_prong3::FlagMCMatchGen); + } // namespace o2::aod #endif // O2_ANALYSIS_HFSECONDARYVERTEX_H_ diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index f1d6adbad7ec4..bf7b6ee5a4da1 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -146,16 +146,18 @@ struct HFCandidateCreator2ProngMC { { // Match reconstructed candidates. for (auto& candidate : candidates) { - auto isMatchedRec = RecoDecay::isMCMatchedDecayRec( + // D0(bar) → π± K∓ + auto isMatchedRecD0 = RecoDecay::isMCMatchedDecayRec( particlesMC, array{candidate.index0_as<aod::BigTracksMC>(), candidate.index1_as<aod::BigTracksMC>()}, 421, array{+kPiPlus, -kKPlus}, true); - rowMCMatchRec(uint8_t(isMatchedRec)); + rowMCMatchRec(uint8_t(isMatchedRecD0)); } // Match generated particles. for (auto& particle : particlesMC) { - auto isMatchedGen = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 421, array{+kPiPlus, -kKPlus}, true); - rowMCMatchGen(uint8_t(isMatchedGen)); + // D0(bar) → π± K∓ + auto isMatchedGenD0 = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 421, array{+kPiPlus, -kKPlus}, true); + rowMCMatchGen(uint8_t(isMatchedGenD0)); } } }; diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 8eda2e2d7df11..70fc45df35242 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -14,7 +14,6 @@ /// /// \author Vít Kučera <vit.kucera@cern.ch>, CERN -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" #include "Analysis/HFSecondaryVertex.h" @@ -24,6 +23,14 @@ using namespace o2; using namespace o2::framework; +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + ConfigParamSpec optionDoMC{"doMC", VariantType::Bool, false, {"Perform MC matching."}}; + workflowOptions.push_back(optionDoMC); +} + +#include "Framework/runDataProcessing.h" + /// Reconstruction of heavy-flavour 3-prong decay candidates struct HFCandidateCreator3Prong { Produces<aod::HfCandProng3Base> rowCandidateBase; @@ -132,9 +139,44 @@ struct HFCandidateCreator3ProngExpressions { void init(InitContext const&) {} }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +/// Performs MC matching. +struct HFCandidateCreator3ProngMC { + Produces<aod::HfCandProng3MCRec> rowMCMatchRec; + Produces<aod::HfCandProng3MCGen> rowMCMatchGen; + + void process(aod::HfCandProng3 const& candidates, + aod::BigTracksMC const& tracks, + aod::McParticles const& particlesMC) + { + // Match reconstructed candidates. + for (auto& candidate : candidates) { + auto arrayDaughters = array{candidate.index0_as<aod::BigTracksMC>(), candidate.index1_as<aod::BigTracksMC>(), candidate.index2_as<aod::BigTracksMC>()}; + // D± → π± K∓ π± + auto isMatchedRecDPlus = RecoDecay::isMCMatchedDecayRec(particlesMC, arrayDaughters, 411, array{+kPiPlus, -kKPlus, +kPiPlus}, true); + // Lc± → p± K∓ π± + auto isMatchedRecLc = RecoDecay::isMCMatchedDecayRec(particlesMC, std::move(arrayDaughters), 4122, array{+kProton, -kKPlus, +kPiPlus}, true); + rowMCMatchRec(uint8_t(isMatchedRecDPlus + 2 * isMatchedRecLc)); + } + + // Match generated particles. + for (auto& particle : particlesMC) { + // D± → π± K∓ π± + auto isMatchedGenDPlus = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 411, array{+kPiPlus, -kKPlus, +kPiPlus}, true); + // Lc± → p± K∓ π± + auto isMatchedGenLc = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 4122, array{+kProton, -kKPlus, +kPiPlus}, true); + rowMCMatchGen(uint8_t(isMatchedGenDPlus + 2 * isMatchedGenLc)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ + WorkflowSpec workflow{ adaptAnalysisTask<HFCandidateCreator3Prong>("hf-cand-creator-3prong"), adaptAnalysisTask<HFCandidateCreator3ProngExpressions>("hf-cand-creator-3prong-expressions")}; + const bool doMC = cfgc.options().get<bool>("doMC"); + if (doMC) { + workflow.push_back(adaptAnalysisTask<HFCandidateCreator3ProngMC>("hf-cand-creator-3prong-mc")); + } + return workflow; } diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index 13ad591b7f557..2ebaedb605b11 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -14,8 +14,8 @@ /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN /// \author Vít Kučera <vit.kucera@cern.ch>, CERN -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Analysis/HFSecondaryVertex.h" #include "Analysis/HFCandidateSelectionTables.h" @@ -24,63 +24,138 @@ using namespace o2::framework; using namespace o2::aod::hf_cand_prong2; using namespace o2::framework::expressions; +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + ConfigParamSpec optionDoMC{"doMC", VariantType::Bool, false, {"Fill MC histograms."}}; + workflowOptions.push_back(optionDoMC); +} + +#include "Framework/runDataProcessing.h" + /// D0 analysis task struct TaskD0 { - OutputObj<TH1F> hmass{TH1F("hmass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; - OutputObj<TH1F> hptcand{TH1F("hptcand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong0{TH1F("hptprong0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong1{TH1F("hptprong1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "2-prong candidates;decay length (cm);entries", 200, 0., 2.)}; - OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "2-prong candidates;decay length xy (cm);entries", 200, 0., 2.)}; - OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hd0d0{TH1F("hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", 500, -1., 1.)}; - OutputObj<TH1F> hCTS{TH1F("hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", 110, -1.1, 1.1)}; - OutputObj<TH1F> hCt{TH1F("hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", 120, -20., 100.)}; - OutputObj<TH1F> hCPA{TH1F("hCPA", "2-prong candidates;cosine of pointing angle;entries", 110, -1.1, 1.1)}; - OutputObj<TH1F> hEta{TH1F("hEta", "2-prong candidates;candidate #it{#eta};entries", 100, -2., 2.)}; - //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "2-prong candidates;selection status;entries", 5, -0.5, 4.5)}; - OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "2-prong candidates;impact parameter error (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "2-prong candidates;decay length error (cm);entries", 100, 0., 1.)}; - OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", 100, 0., 1.)}; + HistogramRegistry registry{ + "registry", + {{"hmass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}, + {"hptcand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hptprong0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hptprong1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hdeclength", "2-prong candidates;decay length (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, + {"hdeclengthxy", "2-prong candidates;decay length xy (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, + {"hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", {HistType::kTH1F, {{500, -1., 1.}}}}, + {"hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", {HistType::kTH1F, {{120, -20., 100.}}}}, + {"hCPA", "2-prong candidates;cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hEta", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, + {"hselectionstatus", "2-prong candidates;selection status;entries", {HistType::kTH1F, {{5, -0.5, 4.5}}}}, + {"hImpParErr", "2-prong candidates;impact parameter error (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hDecLenErr", "2-prong candidates;decay length error (cm);entries", {HistType::kTH1F, {{100, 0., 1.}}}}, + {"hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", {HistType::kTH1F, {{100, 0., 1.}}}}}}; Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + Configurable<double> cutEtaCandMax{"cutEtaCandMax", -1., "max. cand. pseudorapidity"}; Filter filterSelectCandidates = (aod::hf_selcandidate_d0::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate_d0::isSelD0bar >= d_selectionFlagD0bar); void process(soa::Filtered<soa::Join<aod::HfCandProng2, aod::HFSelD0Candidate>> const& candidates) { + //Printf("Candidates: %d", candidates.size()); for (auto& candidate : candidates) { + if (cutEtaCandMax >= 0. && std::abs(candidate.eta()) > cutEtaCandMax) { + //Printf("Candidate: eta rejection: %g", candidate.eta()); + continue; + } if (candidate.isSelD0() >= d_selectionFlagD0) { - hmass->Fill(InvMassD0(candidate)); + registry.get<TH1>("hmass")->Fill(InvMassD0(candidate)); } if (candidate.isSelD0bar() >= d_selectionFlagD0bar) { - hmass->Fill(InvMassD0bar(candidate)); + registry.get<TH1>("hmass")->Fill(InvMassD0bar(candidate)); } - hptcand->Fill(candidate.pt()); - hptprong0->Fill(candidate.ptProng0()); - hptprong1->Fill(candidate.ptProng1()); - hdeclength->Fill(candidate.decayLength()); - hdeclengthxy->Fill(candidate.decayLengthXY()); - hd0Prong0->Fill(candidate.impactParameter0()); - hd0Prong1->Fill(candidate.impactParameter1()); - hd0d0->Fill(candidate.impactParameterProduct()); - hCTS->Fill(CosThetaStarD0(candidate)); - hCt->Fill(CtD0(candidate)); - hCPA->Fill(candidate.cpa()); - hEta->Fill(candidate.eta()); - //hselectionstatus->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); - hImpParErr->Fill(candidate.errorImpactParameter0()); - hImpParErr->Fill(candidate.errorImpactParameter1()); - hDecLenErr->Fill(candidate.errorDecayLength()); - hDecLenXYErr->Fill(candidate.errorDecayLengthXY()); + registry.get<TH1>("hptcand")->Fill(candidate.pt()); + registry.get<TH1>("hptprong0")->Fill(candidate.ptProng0()); + registry.get<TH1>("hptprong1")->Fill(candidate.ptProng1()); + registry.get<TH1>("hdeclength")->Fill(candidate.decayLength()); + registry.get<TH1>("hdeclengthxy")->Fill(candidate.decayLengthXY()); + registry.get<TH1>("hd0Prong0")->Fill(candidate.impactParameter0()); + registry.get<TH1>("hd0Prong1")->Fill(candidate.impactParameter1()); + registry.get<TH1>("hd0d0")->Fill(candidate.impactParameterProduct()); + registry.get<TH1>("hCTS")->Fill(CosThetaStarD0(candidate)); + registry.get<TH1>("hCt")->Fill(CtD0(candidate)); + registry.get<TH1>("hCPA")->Fill(candidate.cpa()); + registry.get<TH1>("hEta")->Fill(candidate.eta()); + registry.get<TH1>("hselectionstatus")->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); + registry.get<TH1>("hImpParErr")->Fill(candidate.errorImpactParameter0()); + registry.get<TH1>("hImpParErr")->Fill(candidate.errorImpactParameter1()); + registry.get<TH1>("hDecLenErr")->Fill(candidate.errorDecayLength()); + registry.get<TH1>("hDecLenXYErr")->Fill(candidate.errorDecayLengthXY()); } } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +/// Fills MC histograms. +struct TaskD0MC { + HistogramRegistry registry{ + "registry", + {{"hPtRecSig", "2-prong candidates (rec. matched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtRecBg", "2-prong candidates (rec. unmatched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtGen", "2-prong candidates (gen. matched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hCPARecSig", "2-prong candidates (rec. matched);cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hCPARecBg", "2-prong candidates (rec. unmatched);cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hEtaRecSig", "2-prong candidates (rec. matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, + {"hEtaRecBg", "2-prong candidates (rec. unmatched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, + {"hEtaGen", "2-prong candidates (gen. matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}}}; + + Configurable<int> d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; + Configurable<int> d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + Configurable<double> cutEtaCandMax{"cutEtaCandMax", -1., "max. cand. pseudorapidity"}; + + Filter filterSelectCandidates = (aod::hf_selcandidate_d0::isSelD0 >= d_selectionFlagD0 || aod::hf_selcandidate_d0::isSelD0bar >= d_selectionFlagD0bar); + + void process(soa::Filtered<soa::Join<aod::HfCandProng2, aod::HFSelD0Candidate, aod::HfCandProng2MCRec>> const& candidates, + soa::Join<aod::McParticles, aod::HfCandProng2MCGen> const& particlesMC) + { + // MC rec. + //Printf("MC Candidates: %d", candidates.size()); + for (auto& candidate : candidates) { + if (cutEtaCandMax >= 0. && std::abs(candidate.eta()) > cutEtaCandMax) { + //Printf("MC Rec.: eta rejection: %g", candidate.eta()); + continue; + } + if (candidate.flagMCMatchRec() == 1) { + registry.get<TH1>("hPtRecSig")->Fill(candidate.pt()); + registry.get<TH1>("hCPARecSig")->Fill(candidate.cpa()); + registry.get<TH1>("hEtaRecSig")->Fill(candidate.eta()); + } else { + registry.get<TH1>("hPtRecBg")->Fill(candidate.pt()); + registry.get<TH1>("hCPARecBg")->Fill(candidate.cpa()); + registry.get<TH1>("hEtaRecBg")->Fill(candidate.eta()); + } + } + // MC gen. + //Printf("MC Particles: %d", particlesMC.size()); + for (auto& particle : particlesMC) { + if (cutEtaCandMax >= 0. && std::abs(particle.eta()) > cutEtaCandMax) { + //Printf("MC Gen.: eta rejection: %g", particle.eta()); + continue; + } + if (particle.flagMCMatchGen() == 1) { + registry.get<TH1>("hPtGen")->Fill(particle.pt()); + registry.get<TH1>("hEtaGen")->Fill(particle.eta()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ + WorkflowSpec workflow{ adaptAnalysisTask<TaskD0>("hf-task-d0")}; + const bool doMC = cfgc.options().get<bool>("doMC"); + if (doMC) { + workflow.push_back(adaptAnalysisTask<TaskD0MC>("hf-task-d0-mc")); + } + return workflow; } From 1965a555f1ea9b069745d43b550d8304c0328653 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 13 Nov 2020 21:36:37 +0100 Subject: [PATCH 1332/1751] GPU: Unify TPC MC label assignment from copy&paste into templated header --- .../TPC/reconstruction/src/GPUCATracking.cxx | 37 +--- GPU/GPUTracking/CMakeLists.txt | 1 + GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 55 ++---- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 63 ++----- GPU/GPUTracking/Standalone/qa/GPUQA.h | 2 + GPU/GPUTracking/Standalone/qa/GPUQAHelper.h | 167 ++++++++++++++++++ 6 files changed, 210 insertions(+), 115 deletions(-) create mode 100644 GPU/GPUTracking/Standalone/qa/GPUQAHelper.h diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 1534f56ac91ca..8f9a52ab3e55c 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -35,9 +35,11 @@ #include "GPUTPCGMMergedTrackHit.h" #include "GPUTPCGMMergerTypes.h" #include "GPUHostDataTypes.h" +#include "GPUQAHelper.h" #include "TPCFastTransform.h" #include <atomic> +#include <optional> #ifdef WITH_OPENMP #include <omp.h> #endif @@ -180,12 +182,15 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* constexpr float MinDelta = 0.1; + auto labelAssigner = (outputTracksMCTruth && data->clusters->clustersMCTruth) ? std::make_optional(GPUTPCTrkLbl(data->clusters->clustersMCTruth, sTrackMCMaxFake)) : std::nullopt; + #ifdef WITH_OPENMP #pragma omp parallel for if(!outputTracksMCTruth) num_threads(4) #endif for (int iTmp = 0; iTmp < nTracks; iTmp++) { auto& oTrack = (*outputTracks)[iTmp]; const int i = trackSort[iTmp].first; + labelAssigner->reset(); oTrack = TrackTPC(tracks[i].GetParam().GetX(), tracks[i].GetAlpha(), @@ -219,7 +224,6 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* uint8_t* sectorIndexArr = reinterpret_cast<uint8_t*>(clIndArr + nOutCl); uint8_t* rowIndexArr = sectorIndexArr + nOutCl; - std::vector<std::pair<MCCompLabel, unsigned int>> labels; int nOutCl2 = 0; float t1, t2; int sector1, sector2; @@ -248,19 +252,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* sector2 = sector; } if (outputTracksMCTruth && data->clusters->clustersMCTruth) { - for (const auto& element : data->clusters->clustersMCTruth->getLabels(clusterIdGlobal)) { - bool found = false; - for (int l = 0; l < labels.size(); l++) { - if (labels[l].first == element) { - labels[l].second++; - found = true; - break; - } - } - if (!found) { - labels.emplace_back(element, 1); - } - } + labelAssigner->addLabel(clusterIdGlobal); } } @@ -306,22 +298,7 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* } if (outputTracksMCTruth) { - if (labels.size() == 0) { - outputTracksMCTruth->emplace_back(); //default constructor creates NotSet label - } else { - int bestLabelNum = 0, bestLabelCount = 0; - for (int j = 0; j < labels.size(); j++) { - if (labels[j].second > bestLabelCount) { - bestLabelNum = j; - bestLabelCount = labels[j].second; - } - } - MCCompLabel& bestLabel = labels[bestLabelNum].first; - if (bestLabelCount < (1.f - sTrackMCMaxFake) * nOutCl) { - bestLabel.setFakeFlag(); - } - outputTracksMCTruth->emplace_back(bestLabel); - } + outputTracksMCTruth->emplace_back(labelAssigner->computeLabel()); } } outClusRefs->resize(clusterOffsetCounter.load()); // remove overhead diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index aa55aafe59fec..eecf72ce1c48b 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -129,6 +129,7 @@ set(HDRS_INSTALL Merger/GPUTPCGMMergerTypes.h Global/GPUErrorCodes.h Standalone/qconfigoptions.h + Standalone/qa/GPUQAHelper.h Base/GPUSettingsList.h DataCompression/GPUTPCClusterRejection.h ) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index 0238773cd889b..6bb95ab55d02d 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -44,7 +44,7 @@ #if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) || GPUCA_MERGE_LOOPER_MC) #include "AliHLTTPCClusterMCData.h" -#ifdef GPUCA_O2_LIB +#ifdef HAVE_O2HEADERS #include "DataFormatsTPC/ClusterNative.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" @@ -92,6 +92,8 @@ GPUTPCGMMerger::GPUTPCGMMerger() // DEBUG CODE #if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) || GPUCA_MERGE_LOOPER_MC) +#include "GPUQAHelper.h" + void GPUTPCGMMerger::CheckMergedTracks() { std::vector<bool> trkUsed(SliceTrackInfoLocalTotal()); @@ -141,6 +143,17 @@ void GPUTPCGMMerger::CheckMergedTracks() } } +template <class T> +inline const auto* resolveMCLabels(const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* a, const AliHLTTPCClusterMCLabel* b) +{ + return a; +} +template <> +inline const auto* resolveMCLabels<AliHLTTPCClusterMCLabel>(const o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>* a, const AliHLTTPCClusterMCLabel* b) +{ + return b; +} + template <class T, class S> long int GPUTPCGMMerger::GetTrackLabelA(const S& trk) { @@ -152,7 +165,7 @@ long int GPUTPCGMMerger::GetTrackLabelA(const S& trk) } else { nClusters = trk.NClusters(); } - std::vector<long int> labels; + auto acc = GPUTPCTrkLbl<false, GPUTPCTrkLbl_ret>(resolveMCLabels<T>(GetConstantMem()->ioPtrs.clustersNative ? GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth : nullptr, GetConstantMem()->ioPtrs.mcLabelsTPC), 0.5f); for (int i = 0; i < nClusters; i++) { int id; if constexpr (std::is_same<S, GPUTPCGMBorderTrack&>::value) { @@ -166,47 +179,15 @@ long int GPUTPCGMMerger::GetTrackLabelA(const S& trk) } else { id = mClusters[trk.FirstClusterRef() + i].num; } - if constexpr (std::is_same<T, AliHLTTPCClusterMCLabel>::value) { - for (int j = 0; j < 3; j++) { - int label = GetConstantMem()->ioPtrs.mcLabelsTPC[id].fClusterID[j].fMCID; - if (label >= 0) { - labels.push_back(label); - } - } - } else { -#ifdef GPUCA_O2_LIB - for (auto label : GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth->getLabels(id)) { - labels.push_back(label.getTrackEventSourceID()); - } -#endif - } - } - if (labels.size() == 0) { - return (-1); - } - std::sort(labels.begin(), labels.end()); - labels.push_back(-1); - long int bestLabel = -1, curLabel = labels[0]; - int curCount = 1, bestLabelCount = 0; - for (unsigned int i = 1; i < labels.size(); i++) { - if (labels[i] == curLabel) { - curCount++; - } else { - if (curCount > bestLabelCount) { - bestLabelCount = curCount; - bestLabel = curLabel; - } - curLabel = labels[i]; - curCount = 1; - } + acc.addLabel(id); } - return bestLabel; + return acc.computeLabel().id; } template <class S> long int GPUTPCGMMerger::GetTrackLabel(const S& trk) { -#ifdef GPUCA_O2_LIB +#ifdef GPUCA_TPC_GEOMETRY_O2 if (GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth) { return GetTrackLabelA<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>, S>(trk); } else diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 7e86f9d9d972d..b507f0299818b 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -11,6 +11,9 @@ /// \file GPUQA.cxx /// \author David Rohr +#define QA_DEBUG 0 +#define QA_TIMING 0 + #include "Rtypes.h" #include "TH1F.h" @@ -43,9 +46,11 @@ #include "GPUO2DataTypes.h" #include "GPUParam.inc" #include "GPUTPCClusterRejection.h" -#ifdef GPUCA_O2_LIB +#ifdef HAVE_O2HEADERS #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" +#endif +#ifdef GPUCA_O2_LIB #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/TrackReference.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -54,6 +59,7 @@ #include "TParticlePDG.h" #include "TDatabasePDG.h" #endif +#include "GPUQAHelper.h" #include <algorithm> #include <cstdio> @@ -62,9 +68,6 @@ using namespace GPUCA_NAMESPACE::gpu; -#define QA_DEBUG 0 -#define QA_TIMING 0 - #ifdef GPUCA_MERGER_BY_MC_LABEL #define CHECK_CLUSTER_STATE_INIT_LEG_BY_MC() \ if (!unattached && mTrackMCLabels[id].isValid()) { \ @@ -205,9 +208,6 @@ int GPUQA::initColors() static constexpr Color_t defaultColorNUms[COLORCOUNT] = {kRed, kBlue, kGreen, kMagenta, kOrange, kAzure, kBlack, kYellow, kGray, kTeal, kSpring, kPink}; #ifdef GPUCA_TPC_GEOMETRY_O2 -#include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/ConstMCTruthContainer.h" - inline unsigned int GPUQA::GetNMCCollissions() { return mNColTracks.size(); @@ -224,6 +224,7 @@ inline int GPUQA::GetMCLabelID(unsigned int i, unsigned int j) { return mTrackin inline int GPUQA::GetMCLabelID(const mcLabels_t& label, unsigned int j) { return label[j].getTrackID(); } inline int GPUQA::GetMCLabelID(const mcLabel_t& label) { return label.getTrackID(); } inline int GPUQA::GetMCLabelCol(unsigned int i, unsigned int j) { return mTracking->mIOPtrs.clustersNative->clustersMCTruth->getLabels(i)[j].getEventID(); } +inline const auto& GPUQA::GetClusterLabels() { return mTracking->mIOPtrs.clustersNative->clustersMCTruth; } inline float GPUQA::GetMCLabelWeight(unsigned int i, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return 1; } @@ -248,6 +249,7 @@ inline int GPUQA::GetMCLabelID(unsigned int i, unsigned int j) { return mTrackin inline int GPUQA::GetMCLabelID(const mcLabels_t& label, unsigned int j) { return label.fClusterID[j].fMCID; } inline int GPUQA::GetMCLabelID(const mcLabel_t& label) { return label.fMCID; } inline int GPUQA::GetMCLabelCol(unsigned int i, unsigned int j) { return 0; } +inline const auto& GPUQA::GetClusterLabels() { return mTracking->mIOPtrs.mcLabelsTPC; } inline float GPUQA::GetMCLabelWeight(unsigned int i, unsigned int j) { return mTracking->mIOPtrs.mcLabelsTPC[i].fClusterID[j].fWeight; } inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { return label.fClusterID[j].fWeight; } inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return label.fWeight; } @@ -702,7 +704,6 @@ void GPUQA::RunQA(bool matchOnly) } mClusterParam.resize(GetNMCLabels()); memset(mClusterParam.data(), 0, mClusterParam.size() * sizeof(mClusterParam[0])); - mNTotalFakes = 0; HighResTimer timer; mNEvents++; @@ -729,6 +730,8 @@ void GPUQA::RunQA(bool matchOnly) GPUCA_OPENMP(parallel for) #endif for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + auto acc = GPUTPCTrkLbl<true, mcLabelI_t>(GetClusterLabels(), 1.f - mConfig.recThreshold); + acc.reset(); if (ompError) { continue; } @@ -746,6 +749,7 @@ void GPUQA::RunQA(bool matchOnly) ompError = true; break; } + acc.addLabel(hitId); for (int j = 0; j < GetMCLabelNID(hitId); j++) { if (GetMCLabelID(hitId, j) >= (int)GetNMCTracks(GetMCLabelCol(hitId, j))) { GPUError("Invalid label %d > %d (hit %d, label %d, col %d)", GetMCLabelID(hitId, j), GetNMCTracks(GetMCLabelCol(hitId, j)), hitId, j, (int)GetMCLabelCol(hitId, j)); @@ -756,7 +760,6 @@ void GPUQA::RunQA(bool matchOnly) if (QA_DEBUG >= 3 && track.OK()) { GPUInfo("Track %d Cluster %u Label %d: %d (%f)", i, k, j, GetMCLabelID(hitId, j), GetMCLabelWeight(hitId, j)); } - labels.push_back(GetMCLabel(hitId, j)); } } if (ompError) { @@ -766,46 +769,10 @@ void GPUQA::RunQA(bool matchOnly) if (ompError) { continue; } - if (labels.size() == 0) { - mTrackMCLabels[i].setNoise(); - mNTotalFakes++; - continue; - } - std::sort(labels.data(), labels.data() + labels.size(), MCComp); - - mcLabelI_t maxLabel; - mcLabelI_t cur = labels[0]; - float curweight = GetMCLabelWeight(labels[0]); - float maxweight = 0.f; - float sumweight = 0.f; - int curcount = 1, maxcount = 0; - if (QA_DEBUG >= 2 && track.OK()) { - for (unsigned int k = 0; k < labels.size(); k++) { - GPUInfo("\t%d %f", GetMCLabelID(labels[k]), GetMCLabelWeight(labels[k])); - } - } - for (unsigned int k = 1; k <= labels.size(); k++) { - if (k == labels.size() || cur != labels[k]) { - sumweight += curweight; - if (curcount > maxcount) { - maxLabel = cur; - maxcount = curcount; - maxweight = curweight; - } - if (k < labels.size()) { - cur = labels[k]; - curweight = GetMCLabelWeight(labels[k]); - curcount = 1; - } - } else { - curweight += GetMCLabelWeight(labels[k]); - curcount++; - } - } - if (maxcount < mConfig.recThreshold * nClusters) { - maxLabel.setFakeFlag(true); - } + float maxweight, sumweight; + int maxcount; + auto maxLabel = acc.computeLabel(&maxweight, &sumweight, &maxcount); mTrackMCLabels[i] = maxLabel; if (QA_DEBUG && track.OK() && GetNMCTracks(maxLabel.getEventID()) > maxLabel.getTrackID()) { const mcInfo_t& mc = GetMCTrack(maxLabel); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 3fd829fdf19e1..7aca651aecf5a 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -146,6 +146,7 @@ class GPUQA struct mcLabelI_t { int getTrackID() const { return AbsLabelID(track); } int getEventID() const { return 0; } + long int getTrackEventSourceID() const { return getTrackID(); } bool isFake() const { return track < 0; } bool isValid() const { return track != MC_LABEL_INVALID; } void invalidate() { track = MC_LABEL_INVALID; } @@ -181,6 +182,7 @@ class GPUQA float GetMCLabelWeight(unsigned int i, unsigned int j); float GetMCLabelWeight(const mcLabels_t& label, unsigned int j); float GetMCLabelWeight(const mcLabel_t& label); + const auto& GetClusterLabels(); bool mcPresent(); static bool MCComp(const mcLabel_t& a, const mcLabel_t& b); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQAHelper.h b/GPU/GPUTracking/Standalone/qa/GPUQAHelper.h new file mode 100644 index 0000000000000..18499cec90a74 --- /dev/null +++ b/GPU/GPUTracking/Standalone/qa/GPUQAHelper.h @@ -0,0 +1,167 @@ +// 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 GPUQAHelper.h +/// \author David Rohr + +#ifndef GPUQAHELPER_H +#define GPUQAHELPER_H + +#include <utility> +#include <vector> +#include <type_traits> + +struct AliHLTTPCClusterMCWeight; +struct AliHLTTPCClusterMCLabel; + +namespace o2 +{ +class MCCompLabel; +namespace gpu +{ +namespace internal +{ + +template <bool WEIGHT, class T, class S, class U = T> +class GPUTPCTrkLbl +{ + public: + GPUTPCTrkLbl(const S* v, float maxFake = 0.1f) : mClusterLabels(v), mTrackMCMaxFake(maxFake) { mLabels.reserve(5); }; + GPUTPCTrkLbl(const GPUTPCTrkLbl&) = default; + inline void reset() + { + mLabels.clear(); + mNCl = 0; + mTotalWeight = 0.f; + } + inline void addLabel(unsigned int elementId) + { + if constexpr (std::is_same<T, AliHLTTPCClusterMCWeight>::value) { + for (unsigned int i = 0; i < sizeof(mClusterLabels[elementId]) / sizeof(mClusterLabels[elementId].fClusterID[0]); i++) { + const auto& element = mClusterLabels[elementId].fClusterID[i]; + if (element.fMCID >= 0) { + if constexpr (WEIGHT) { + mTotalWeight += element.fWeight; + } + bool found = false; + for (unsigned int l = 0; l < mLabels.size(); l++) { + if (mLabels[l].first.fMCID == element.fMCID) { + mLabels[l].second++; + if constexpr (WEIGHT) { + mLabels[l].first.fWeight += element.fWeight; + } + found = true; + break; + } + } + if (!found) { + mLabels.emplace_back(element, 1); + } + } + } + } else { + for (const auto& element : mClusterLabels->getLabels(elementId)) { + bool found = false; + for (unsigned int l = 0; l < mLabels.size(); l++) { + if (mLabels[l].first == element) { + mLabels[l].second++; + found = true; + break; + } + } + if (!found) { + mLabels.emplace_back(element, 1); + } + } + } + mNCl++; + } + inline U computeLabel(float* labelWeight = nullptr, float* totalWeight = nullptr, int* maxCount = nullptr) + { + if (mLabels.size() == 0) { + return U(); //default constructor creates NotSet label + } else { + unsigned int bestLabelNum = 0, bestLabelCount = 0; + for (unsigned int j = 0; j < mLabels.size(); j++) { + if (mLabels[j].second > bestLabelCount) { + bestLabelNum = j; + bestLabelCount = mLabels[j].second; + } + } + auto& bestLabel = mLabels[bestLabelNum].first; + if constexpr (std::is_same<T, AliHLTTPCClusterMCWeight>::value && WEIGHT) { + *labelWeight = bestLabel.fWeight; + *totalWeight = mTotalWeight; + *maxCount = bestLabelCount; + } else { + (void)labelWeight; + (void)totalWeight; + (void)maxCount; + } + U retVal = bestLabel; + if (bestLabelCount < (1.f - mTrackMCMaxFake) * mNCl) { + retVal.setFakeFlag(); + } + return retVal; + } + } + + private: + const S* mClusterLabels; + std::vector<std::pair<T, unsigned int>> mLabels; + const float mTrackMCMaxFake; + unsigned int mNCl = 0; + float mTotalWeight = 0.f; +}; +} // namespace internal + +struct GPUTPCTrkLbl_ret { + long int id = -1; + GPUTPCTrkLbl_ret() = default; + template <class T> + GPUTPCTrkLbl_ret(T){}; +#ifdef GPUCA_TPC_GEOMETRY_O2 + GPUTPCTrkLbl_ret(const MCCompLabel& a) : id(a.getTrackEventSourceID()){}; +#endif +#ifdef GPUCA_STANDALONE + GPUTPCTrkLbl_ret(const AliHLTTPCClusterMCWeight& a) : id(a.fMCID){}; +#endif + void setFakeFlag() + { + id = -1; + } +}; + +template <bool WEIGHT = false, class U = void, class T, template <class> class S, typename... Args> +static inline auto GPUTPCTrkLbl(const S<T>* x, Args... args) +{ + if constexpr (std::is_same<U, void>::value) { + return internal::GPUTPCTrkLbl<WEIGHT, T, S<T>>(x, args...); + } else { + return internal::GPUTPCTrkLbl<WEIGHT, T, S<T>, U>(x, args...); + } +} + +template <bool WEIGHT = false, class U = void, typename... Args> +static inline auto GPUTPCTrkLbl(const AliHLTTPCClusterMCLabel* x, Args... args) +{ + using S = AliHLTTPCClusterMCLabel; + using T = AliHLTTPCClusterMCWeight; + if constexpr (std::is_same<U, void>::value) { + return internal::GPUTPCTrkLbl<WEIGHT, T, S>(x, args...); + } else { + return internal::GPUTPCTrkLbl<WEIGHT, T, S, U>(x, args...); + } +} + +} // namespace gpu +} // namespace o2 + +#endif From 2c24ac95a0649c006510e645b53d5da6d216fb79 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 14 Nov 2020 01:03:27 +0100 Subject: [PATCH 1333/1751] GPU: Clean up stupid omp error handling, just throw... --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index b507f0299818b..de3993ce76c67 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -724,17 +724,12 @@ void GPUQA::RunQA(bool matchOnly) if (mcAvail) { // Assign Track MC Labels timer.Start(); - bool ompError = false; - #if QA_DEBUG == 0 GPUCA_OPENMP(parallel for) #endif for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { auto acc = GPUTPCTrkLbl<true, mcLabelI_t>(GetClusterLabels(), 1.f - mConfig.recThreshold); acc.reset(); - if (ompError) { - continue; - } int nClusters = 0; const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; std::vector<mcLabel_t> labels; @@ -746,15 +741,13 @@ void GPUQA::RunQA(bool matchOnly) unsigned int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; if (hitId >= GetNMCLabels()) { GPUError("Invalid hit id %u > %d", hitId, GetNMCLabels()); - ompError = true; - break; + throw std::runtime_error("qa error"); } acc.addLabel(hitId); for (int j = 0; j < GetMCLabelNID(hitId); j++) { if (GetMCLabelID(hitId, j) >= (int)GetNMCTracks(GetMCLabelCol(hitId, j))) { GPUError("Invalid label %d > %d (hit %d, label %d, col %d)", GetMCLabelID(hitId, j), GetNMCTracks(GetMCLabelCol(hitId, j)), hitId, j, (int)GetMCLabelCol(hitId, j)); - ompError = true; - break; + throw std::runtime_error("qa error"); } if (GetMCLabelID(hitId, j) >= 0) { if (QA_DEBUG >= 3 && track.OK()) { @@ -762,12 +755,6 @@ void GPUQA::RunQA(bool matchOnly) } } } - if (ompError) { - break; - } - } - if (ompError) { - continue; } float maxweight, sumweight; @@ -780,9 +767,6 @@ void GPUQA::RunQA(bool matchOnly) std::sqrt(mc.pX * mc.pX + mc.pY * mc.pY)); } } - if (ompError) { - return; - } if (QA_TIMING) { GPUInfo("QA Time: Assign Track Labels:\t\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); } From 6a69194892d6524f62e977f0176f436c8fef9ab5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 14 Nov 2020 01:15:38 +0100 Subject: [PATCH 1334/1751] GPU: Use OpenMP firstprivate to avoid recreating the MC label accumulator --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index de3993ce76c67..3907142102bac 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -724,11 +724,11 @@ void GPUQA::RunQA(bool matchOnly) if (mcAvail) { // Assign Track MC Labels timer.Start(); + auto acc = GPUTPCTrkLbl<true, mcLabelI_t>(GetClusterLabels(), 1.f - mConfig.recThreshold); #if QA_DEBUG == 0 - GPUCA_OPENMP(parallel for) + GPUCA_OPENMP(parallel for firstprivate(acc)) #endif for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { - auto acc = GPUTPCTrkLbl<true, mcLabelI_t>(GetClusterLabels(), 1.f - mConfig.recThreshold); acc.reset(); int nClusters = 0; const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; From 5049b3c8298a39f8ecb6a81a044ae76868764dce Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 16 Nov 2020 08:42:21 +0100 Subject: [PATCH 1335/1751] GPU: Fix codechecker warnings about NULL vs nullptr --- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index b8f4bb302ceb5..36c881082954a 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -648,10 +648,10 @@ int GPUDisplay::InitGL_internal() mThreadTracks.resize(mChain->GetProcessingSettings().ompThreads); #ifdef GPUCA_DISPLAY_OPENGL_CORE CHKERR(mVertexShader = glCreateShader(GL_VERTEX_SHADER)); - CHKERR(glShaderSource(mVertexShader, 1, &GPUDisplayShaders::vertexShader, NULL)); + CHKERR(glShaderSource(mVertexShader, 1, &GPUDisplayShaders::vertexShader, nullptr)); CHKERR(glCompileShader(mVertexShader)); CHKERR(mFragmentShader = glCreateShader(GL_FRAGMENT_SHADER)); - CHKERR(glShaderSource(mFragmentShader, 1, &GPUDisplayShaders::fragmentShader, NULL)); + CHKERR(glShaderSource(mFragmentShader, 1, &GPUDisplayShaders::fragmentShader, nullptr)); CHKERR(glCompileShader(mFragmentShader)); CHKERR(mShaderProgram = glCreateProgram()); CHKERR(glAttachShader(mShaderProgram, mVertexShader)); From 72d2aaa7e19934584980ee1388c6abadff2e9747 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 16 Nov 2020 14:18:53 +0100 Subject: [PATCH 1336/1751] DPL: allow GUI to run with an empty workflow (#4836) --- Framework/Core/src/DeviceSpecHelpers.cxx | 1 - Framework/Core/src/WorkflowHelpers.cxx | 5 +++-- Framework/Core/src/WorkflowHelpers.h | 7 ++++++- Framework/Core/src/runDataProcessing.cxx | 20 +++++++++++++++++++- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index f1365407c088a..0cc4ea56c7dea 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -708,7 +708,6 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf // them before assigning to a device. std::vector<OutputSpec> outputs; - WorkflowHelpers::verifyWorkflow(workflow); WorkflowHelpers::constructGraph(workflow, logicalEdges, outputs, availableForwardsInfo); // We need to instanciate one device per (me, timeIndex) in the diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 8e517cd2bccd4..9ace1c786f61f 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -755,10 +755,10 @@ void WorkflowHelpers::sortEdges(std::vector<size_t>& inEdgeIndex, std::sort(outEdgeIndex.begin(), outEdgeIndex.end(), outSorter); } -void WorkflowHelpers::verifyWorkflow(const o2::framework::WorkflowSpec& workflow) +WorkflowParsingState WorkflowHelpers::verifyWorkflow(const o2::framework::WorkflowSpec& workflow) { if (workflow.empty()) { - throw std::runtime_error("Empty workflow!"); + return WorkflowParsingState::Empty; } std::set<std::string> validNames; std::vector<OutputSpec> availableOutputs; @@ -799,6 +799,7 @@ void WorkflowHelpers::verifyWorkflow(const o2::framework::WorkflowSpec& workflow } } } + return WorkflowParsingState::Valid; } using UnifiedDataSpecType = std::variant<InputSpec, OutputSpec>; diff --git a/Framework/Core/src/WorkflowHelpers.h b/Framework/Core/src/WorkflowHelpers.h index 9cb5c46829744..c673b1e9940b0 100644 --- a/Framework/Core/src/WorkflowHelpers.h +++ b/Framework/Core/src/WorkflowHelpers.h @@ -143,6 +143,11 @@ struct OutputObj { bool isdangling; }; +enum struct WorkflowParsingState : int { + Valid, + Empty, +}; + /// A set of internal helper classes to manipulate a Workflow struct WorkflowHelpers { /// Topological sort for a graph of @a nodeCount nodes. @@ -163,7 +168,7 @@ struct WorkflowHelpers { // Helper method to verify that a given workflow is actually valid e.g. that // it contains no empty labels. - static void verifyWorkflow(const WorkflowSpec& workflow); + [[nodiscard]] static WorkflowParsingState verifyWorkflow(const WorkflowSpec& workflow); // Depending on the workflow and the dangling inputs inside it, inject "fake" // devices to mark the fact we might need some extra action to make sure diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 9ad45a114f2b7..bdeed2f1a5e43 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -928,6 +928,8 @@ int runStateMachine(DataProcessorSpecs const& workflow, std::vector<ServicePreSchedule> preScheduleCallbacks; std::vector<ServicePostSchedule> postScheduleCallbacks; + bool guiDeployedOnce = false; + while (true) { // If control forced some transition on us, we push it to the queue. if (driverControl.forcedTransitions.empty() == false) { @@ -1025,6 +1027,10 @@ int runStateMachine(DataProcessorSpecs const& workflow, break; case DriverState::MATERIALISE_WORKFLOW: try { + auto workflowState = WorkflowHelpers::verifyWorkflow(workflow); + if (driverInfo.batch == true && workflowState == WorkflowParsingState::Empty) { + throw runtime_error("Empty workflow provided while running in batch mode."); + } DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(workflow, driverInfo.channelPolicies, driverInfo.completionPolicies, @@ -1063,6 +1069,13 @@ int runStateMachine(DataProcessorSpecs const& workflow, } catch (std::runtime_error& e) { std::cerr << "Invalid workflow: " << e.what() << std::endl; return 1; + } catch (o2::framework::RuntimeErrorRef ref) { + auto& e = o2::framework::error_from_ref(ref); +#ifdef DPL_ENABLE_BACKTRACE + backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); +#endif + std::cerr << "Invalid workflow: " << e.what << std::endl; + return 1; } catch (...) { std::cerr << "Unknown error while materialising workflow"; return 1; @@ -1107,6 +1120,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, guiContext.window = window; gui_timer.data = &guiContext; uv_timer_start(&gui_timer, gui_callback, 0, 20); + guiDeployedOnce = true; } break; case DriverState::SCHEDULE: { @@ -1185,10 +1199,14 @@ int runStateMachine(DataProcessorSpecs const& workflow, driverInfo.states.push_back(DriverState::RUNNING); driverInfo.states.push_back(DriverState::REDEPLOY_GUI); driverInfo.states.push_back(DriverState::SCHEDULE); - } else if (deviceSpecs.size() == 0) { + } else if (deviceSpecs.empty() && driverInfo.batch == true) { LOG(INFO) << "No device resulting from the workflow. Quitting."; // If there are no deviceSpecs, we exit. driverInfo.states.push_back(DriverState::EXIT); + } else if (deviceSpecs.empty() && driverInfo.batch == false && !guiDeployedOnce) { + // In case of an empty workflow, we need to deploy the GUI at least once. + driverInfo.states.push_back(DriverState::RUNNING); + driverInfo.states.push_back(DriverState::REDEPLOY_GUI); } else { driverInfo.states.push_back(DriverState::RUNNING); } From c32c52bbe190d97ed82f97703df33e86a4064096 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 16 Nov 2020 14:55:39 +0100 Subject: [PATCH 1337/1751] Jobutils: Add optional hook for taskwrapper termination --- Utilities/Tools/jobutils.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index ad2a04ecf85bb..5905fb7dc6adc 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -239,6 +239,17 @@ taskwrapper() { trap '' SIGTERM o2_cleanup_shm_files #--> better to register a general trap at EXIT + + # this gives some possibility to customize the wrapper + # and do some special task at the ordinary exit. The hook takes 3 arguments: + # - The original command + # - the logfile + # - the return code from the execution + if [ "${JOBUTILS_JOB_ENDHOOK}" ]; then + hook="${JOBUTILS_JOB_ENDHOOK} '$command' $logfile ${RC}" + eval "${hook}" + fi + return ${RC} } From b1ca20835aa415d8724ddf4ae033fc9c8e667afb Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 12 Nov 2020 13:43:03 +0100 Subject: [PATCH 1338/1751] Decrease verbosity of ITS-TPC matching --- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 50 ++++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index fbd034c487e96..118fb9cd5a5f6 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -1444,7 +1444,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); // rotate to 1 cluster's sector if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; + LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; } @@ -1452,7 +1452,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) // propagate to 1st cluster X if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { - LOG(WARNING) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); + LOG(DEBUG) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); mMatchedTracks.pop_back(); // destroy failed track return false; } @@ -1471,8 +1471,8 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) for (; icl--;) { const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); if (row <= prevrow) { - LOG(WARNING) << "New row/sect " << int(row) << '/' << int(sector) << " is <= the previous " << int(prevrow) - << '/' << int(prevsector) << " TrackID: " << tTPC.sourceID << " Pt:" << tracOut.getPt(); + LOG(DEBUG) << "New row/sect " << int(row) << '/' << int(sector) << " is <= the previous " << int(prevrow) + << '/' << int(prevsector) << " TrackID: " << tTPC.sourceID << " Pt:" << tracOut.getPt(); if (row < prevrow) { break; } else { @@ -1484,21 +1484,21 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) if (prevsector != sector) { prevsector = sector; if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; + LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; } } if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, 10., MatCorrType::USEMatCorrNONE, &trfit.getLTIntegralOut())) { // no material correction! - LOG(INFO) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" - << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); + LOG(DEBUG) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" + << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); mMatchedTracks.pop_back(); // destroy failed track return false; } chi2Out += tracOut.getPredictedChi2(clsYZ, clsCov); if (!tracOut.update(clsYZ, clsCov)) { - LOG(WARNING) << "Update failed at cluster " << icl << ", chi2 =" << chi2Out; + LOG(DEBUG) << "Update failed at cluster " << icl << ", chi2 =" << chi2Out; mMatchedTracks.pop_back(); // destroy failed track return false; } @@ -1637,7 +1637,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime() - timeTB, clsX, clsYZ[0], clsYZ[1]); // rotate to 1 cluster's sector if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; + LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; } @@ -1645,7 +1645,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) // propagate to 1st cluster X if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { - LOG(WARNING) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); + LOG(DEBUG) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); mMatchedTracks.pop_back(); // destroy failed track return false; } @@ -1664,8 +1664,8 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) for (; icl--;) { const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); if (row <= prevrow) { - LOG(WARNING) << "New row/sect " << int(row) << '/' << int(sector) << " is <= the previous " << int(prevrow) - << '/' << int(prevsector) << " TrackID: " << tTPC.sourceID << " Pt:" << tracOut.getPt(); + LOG(DEBUG) << "New row/sect " << int(row) << '/' << int(sector) << " is <= the previous " << int(prevrow) + << '/' << int(prevsector) << " TrackID: " << tTPC.sourceID << " Pt:" << tracOut.getPt(); if (row < prevrow) { break; } else { @@ -1677,21 +1677,21 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) if (prevsector != sector) { prevsector = sector; if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(WARNING) << "Rotation to sector " << int(sector % 18) << " failed"; + LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; mMatchedTracks.pop_back(); // destroy failed track return false; } } if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, 10., MatCorrType::USEMatCorrNONE, &trfit.getLTIntegralOut())) { // no material correction! - LOG(INFO) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" - << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); + LOG(DEBUG) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" + << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); mMatchedTracks.pop_back(); // destroy failed track return false; } chi2Out += tracOut.getPredictedChi2(clsYZ, clsCov); if (!tracOut.update(clsYZ, clsCov)) { - LOG(WARNING) << "Update failed at cluster " << icl << ", chi2 =" << chi2Out; + LOG(DEBUG) << "Update failed at cluster " << icl << ", chi2 =" << chi2Out; mMatchedTracks.pop_back(); // destroy failed track return false; } @@ -1764,14 +1764,14 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo chi2 = 0; icl = nclAcc - 1; - printf("RowsSpan: %d %d | %d clusters of %d\n", rowArr[0], rowArr[icl], nclAcc, tpcTrOrig.getNClusterReferences()); // tmp + // printf("RowsSpan: %d %d | %d clusters of %d\n", rowArr[0], rowArr[icl], nclAcc, tpcTrOrig.getNClusterReferences()); // tmp auto propagator = o2::base::Propagator::Instance(); mTPCTransform->Transform(sectArr[icl], rowArr[icl], clsArr[icl]->getPad(), clsArr[icl]->getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); mTPCClusterParam->GetClusterErrors2(rowArr[icl], clsYZ[1], trcIn.getSnp(), trcIn.getTgl(), clsCov[0], clsCov[2]); uint8_t sectCurr = sectArr[icl]; if (!trcIn.rotate(o2::math_utils::sector2Angle(sectCurr % 18))) { - LOG(WARNING) << "Rotation to sector " << int(sectCurr % 18) << " failed"; + LOG(DEBUG) << "Rotation to sector " << int(sectCurr % 18) << " failed"; return false; } trcIn.setX(clsX); @@ -1786,17 +1786,17 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo if (sectArr[icl] != sectCurr) { sectCurr = sectArr[icl]; if (!trcIn.rotate(o2::math_utils::sector2Angle(sectCurr % 18))) { - LOG(WARNING) << "Rotation to sector " << int(sectCurr % 18) << " failed"; - LOG(WARNING) << trcIn.asString(); + LOG(DEBUG) << "Rotation to sector " << int(sectCurr % 18) << " failed"; + LOG(DEBUG) << trcIn.asString(); return false; } } mTPCTransform->Transform(sectArr[icl], rowArr[icl], clsArr[icl]->getPad(), clsArr[icl]->getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); mTPCClusterParam->GetClusterErrors2(rowArr[icl], clsYZ[1], trcIn.getSnp(), trcIn.getTgl(), clsCov[0], clsCov[2]); if (!propagator->PropagateToXBxByBz(trcIn, clsX, m, TolSNP, 10., MatCorrType::USEMatCorrNONE)) { // no material correction! - LOG(INFO) << "Propagation to cluster at X=" - << clsX << " failed, Xtr=" << trcIn.getX() << " snp=" << trcIn.getSnp() << " pT=" << trcIn.getPt(); - LOG(WARNING) << trcIn.asString(); + LOG(DEBUG) << "Propagation to cluster at X=" + << clsX << " failed, Xtr=" << trcIn.getX() << " snp=" << trcIn.getSnp() << " pT=" << trcIn.getPt(); + LOG(DEBUG) << trcIn.asString(); return false; } chi2 += trcIn.getPredictedChi2(clsYZ, clsCov); @@ -1809,8 +1809,8 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo // propagate to the inner edge of the TPC // Note: it is allowed to not reach the requested radius if (!propagator->PropagateToXBxByBz(trcIn, xTgt, m, MaxSnp, 2., mUseMatCorrFlag)) { - LOG(INFO) << "Propagation to target X=" << xTgt << " failed, Xtr=" << trcIn.getX() << " snp=" << trcIn.getSnp() << " pT=" << trcIn.getPt(); - LOG(WARNING) << trcIn.asString(); + LOG(DEBUG) << "Propagation to target X=" << xTgt << " failed, Xtr=" << trcIn.getX() << " snp=" << trcIn.getSnp() << " pT=" << trcIn.getPt(); + LOG(DEBUG) << trcIn.asString(); return false; } return true; From 8afcdc06a868f95af5f51e26d261c5388216f804 Mon Sep 17 00:00:00 2001 From: akalweit <Alexander.Philipp.Kalweit@cern.ch> Date: Mon, 16 Nov 2020 17:10:02 +0100 Subject: [PATCH 1339/1751] small bugfix (#4835) --- Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx index 89c162cebde29..c95d2d798d03f 100644 --- a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx +++ b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx @@ -53,7 +53,7 @@ struct NucleiSpecraTask { continue; } - hTPCsignal->Fill(track.p(), track.tpcSignal()); + hTPCsignal->Fill(track.tpcInnerParam(), track.tpcSignal()); hMomentum->Fill(track.p()); } } From 16a3069e52440192e702ca545dab5e43ec4a326b Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 26 Oct 2020 15:37:27 +0100 Subject: [PATCH 1340/1751] Simplify MID digits-to-raw workflow --- Detectors/MUON/MID/Workflow/CMakeLists.txt | 3 +- .../include/MIDWorkflow/DigitsToRawWorkflow.h | 29 -------------- .../MID/Workflow/src/DigitsToRawWorkflow.cxx | 38 ------------------- ...-to-raw.cxx => digits-to-raw-workflow.cxx} | 20 ++++------ 4 files changed, 9 insertions(+), 81 deletions(-) delete mode 100644 Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitsToRawWorkflow.h delete mode 100644 Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx rename Detectors/MUON/MID/Workflow/src/{mid-digits-to-raw.cxx => digits-to-raw-workflow.cxx} (67%) diff --git a/Detectors/MUON/MID/Workflow/CMakeLists.txt b/Detectors/MUON/MID/Workflow/CMakeLists.txt index b827dc8e67529..1bb8568e2124d 100644 --- a/Detectors/MUON/MID/Workflow/CMakeLists.txt +++ b/Detectors/MUON/MID/Workflow/CMakeLists.txt @@ -13,7 +13,6 @@ o2_add_library(MIDWorkflow SOURCES src/ClusterizerMCSpec.cxx src/ClusterizerSpec.cxx src/DigitReaderSpec.cxx - src/DigitsToRawWorkflow.cxx src/EntropyDecoderSpec.cxx src/EntropyEncoderSpec.cxx src/RawAggregatorSpec.cxx @@ -40,7 +39,7 @@ o2_add_library(MIDWorkflow o2_add_executable( digits-to-raw-workflow COMPONENT_NAME mid - SOURCES src/mid-digits-to-raw.cxx + SOURCES src/digits-to-raw-workflow.cxx TARGETVARNAME exenameraw PUBLIC_LINK_LIBRARIES O2::MIDWorkflow) diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitsToRawWorkflow.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitsToRawWorkflow.h deleted file mode 100644 index ce30b26368090..0000000000000 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/DigitsToRawWorkflow.h +++ /dev/null @@ -1,29 +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. - -/// \file MIDWorkflow/DigitsToRawWorkflow.h -/// \brief Definition of the reconstruction workflow for MID MC -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 11 April 2019 - -#ifndef O2_MID_DIGITSTORAWWORKFLOWSPEC_H -#define O2_MID_DIGITSTORAWWORKFLOWSPEC_H - -#include "Framework/WorkflowSpec.h" - -namespace o2 -{ -namespace mid -{ -framework::WorkflowSpec getDigitsToRawWorkflow(); -} -} // namespace o2 - -#endif //O2_MID_DIGITSTORAWWORKFLOWSPEC_H diff --git a/Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx b/Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx deleted file mode 100644 index f81520acefbd0..0000000000000 --- a/Detectors/MUON/MID/Workflow/src/DigitsToRawWorkflow.cxx +++ /dev/null @@ -1,38 +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. - -/// \file MID/Workflow/src/DigitsToRawWorkflow.cxx -/// \brief Definition of MID reconstruction workflow for MC -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 27 September 2019 - -#include "MIDWorkflow/DigitsToRawWorkflow.h" - -#include "DPLUtils/Utils.h" -#include "MIDWorkflow/DigitReaderSpec.h" -#include "MIDWorkflow/RawWriterSpec.h" - -namespace of = o2::framework; - -namespace o2 -{ -namespace mid -{ - -of::WorkflowSpec getDigitsToRawWorkflow() -{ - of::WorkflowSpec specs; - - specs.emplace_back(getDigitReaderSpec(false)); - specs.emplace_back(getRawWriterSpec()); - return specs; -} -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/mid-digits-to-raw.cxx b/Detectors/MUON/MID/Workflow/src/digits-to-raw-workflow.cxx similarity index 67% rename from Detectors/MUON/MID/Workflow/src/mid-digits-to-raw.cxx rename to Detectors/MUON/MID/Workflow/src/digits-to-raw-workflow.cxx index 906655715aba6..385d2735373e8 100644 --- a/Detectors/MUON/MID/Workflow/src/mid-digits-to-raw.cxx +++ b/Detectors/MUON/MID/Workflow/src/digits-to-raw-workflow.cxx @@ -15,14 +15,13 @@ #include <string> #include <vector> +#include "Framework/ConfigParamSpec.h" #include "Framework/Variant.h" -#include "CommonUtils/ConfigurableParam.h" -#include "MIDWorkflow/DigitsToRawWorkflow.h" +#include "MIDWorkflow/DigitReaderSpec.h" +#include "MIDWorkflow/RawWriterSpec.h" using namespace o2::framework; -// ------------------------------------------------------------------ - // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { @@ -30,17 +29,14 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); } -// ------------------------------------------------------------------ - -#include "Framework/ConfigParamSpec.h" #include "Framework/runDataProcessing.h" WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { - // Update the (declared) parameters if changed from the command line - o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); - // write the configuration used for the digitizer workflow - o2::conf::ConfigurableParam::writeINI("o2mid-recoflow_configuration.ini"); + WorkflowSpec specs; + + specs.emplace_back(o2::mid::getDigitReaderSpec(false)); + specs.emplace_back(o2::mid::getRawWriterSpec()); - return std::move(o2::mid::getDigitsToRawWorkflow()); + return specs; } From 6d955884b0a2c5f83c592ef11e99add95843feac Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Thu, 12 Nov 2020 15:09:27 +0100 Subject: [PATCH 1341/1751] Remove unused files --- .../MID/Workflow/src/mid-reco-workflow-mc.cxx | 46 ---------------- .../MID/Workflow/src/mid-reco-workflow.cxx | 52 ------------------- 2 files changed, 98 deletions(-) delete mode 100644 Detectors/MUON/MID/Workflow/src/mid-reco-workflow-mc.cxx delete mode 100644 Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx diff --git a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow-mc.cxx b/Detectors/MUON/MID/Workflow/src/mid-reco-workflow-mc.cxx deleted file mode 100644 index 11d63c0d1ee2d..0000000000000 --- a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow-mc.cxx +++ /dev/null @@ -1,46 +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. - -/// \file mid-reco-workflow.cxx -/// \brief MID reconstruction workflow -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 27 September 2019 - -#include <string> -#include <vector> -#include "Framework/Variant.h" -#include "CommonUtils/ConfigurableParam.h" -#include "MIDWorkflow/RecoWorkflowMC.h" - -using namespace o2::framework; - -// ------------------------------------------------------------------ - -// we need to add workflow options before including Framework/runDataProcessing -void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) -{ - std::string keyvaluehelp("Semicolon separated key=value strings ..."); - workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); -} - -// ------------------------------------------------------------------ - -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" - -WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) -{ - // Update the (declared) parameters if changed from the command line - o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); - // write the configuration used for the digitizer workflow - o2::conf::ConfigurableParam::writeINI("o2mid-recoflow_configuration.ini"); - - return std::move(o2::mid::getRecoWorkflowMC()); -} diff --git a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx b/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx deleted file mode 100644 index 493129902dd09..0000000000000 --- a/Detectors/MUON/MID/Workflow/src/mid-reco-workflow.cxx +++ /dev/null @@ -1,52 +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. - -/// \file mid-reco-workflow.cxx -/// \brief MID reconstruction workflow -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 12 June 2019 - -#include <string> -#include <vector> -#include "Framework/Variant.h" -#include "CommonUtils/ConfigurableParam.h" -#include "MIDWorkflow/RecoWorkflow.h" - -using namespace o2::framework; - -// ------------------------------------------------------------------ - -// we need to add workflow options before including Framework/runDataProcessing -void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) -{ - std::vector<ConfigParamSpec> options{ - {"input-ctf", VariantType::Bool, false, {"Input data comes from CTF"}}, - {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}}; - std::swap(workflowOptions, options); - - std::string keyvaluehelp("Semicolon separated key=value strings ..."); - workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); -} - -// ------------------------------------------------------------------ - -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" - -WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) -{ - // Update the (declared) parameters if changed from the command line - o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues")); - // write the configuration used for the digitizer workflow - o2::conf::ConfigurableParam::writeINI("o2mid-recoflow_configuration.ini"); - auto ctf = configcontext.options().get<bool>("input-ctf"); - auto disableRootOut = configcontext.options().get<bool>("disable-root-output"); - return std::move(o2::mid::getRecoWorkflow(ctf, disableRootOut)); -} From 1671a99e4a22f362db46b10ba12a3914b811a908 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Thu, 12 Nov 2020 15:17:57 +0100 Subject: [PATCH 1342/1751] Uniformize reconstruction options to other detectors --- Detectors/MUON/MID/Workflow/README.md | 8 +++----- Detectors/MUON/MID/Workflow/src/reco-workflow.cxx | 12 ++++++------ prodtests/full_system_test.sh | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/README.md b/Detectors/MUON/MID/Workflow/README.md index b42719509a09c..219e5b3a87950 100644 --- a/Detectors/MUON/MID/Workflow/README.md +++ b/Detectors/MUON/MID/Workflow/README.md @@ -28,11 +28,9 @@ o2-sim-digitizer-workflow To reconstruct the MC digits, run: ```bash -o2-mid-digits-reader-workflow | o2-mid-reco-workflow --mc +o2-mid-digits-reader-workflow | o2-mid-reco-workflow ``` -The `--mc` option at the end of the workflow allow to propagate the MC labels up to the tracks. - ### Zero suppression The MID electronics has a default zero suppression mode. Digits are transmitted only if there is at least one strip fired in both the bending and non-bending plane in at least one of the 4 RPCs which are read-out by a local board. @@ -51,7 +49,7 @@ o2-mid-digits-reader-workflow --disable-zero-suppression To reconstruct the raw data (either from converted MC digits or real data), run: ```bash -o2-raw-file-reader-workflow --input-conf MIDraw.cfg | o2-mid-raw-to-digits-workflow | o2-mid-reco-workflow +o2-raw-file-reader-workflow --input-conf MIDraw.cfg | o2-mid-raw-to-digits-workflow | o2-mid-reco-workflow --disable-mc ``` The reconstruction from raw data can also be tested using as input raw data obtained from the MC digits. @@ -73,7 +71,7 @@ The CTF for MID corresponds to the digit. So one can retrieve the digits from the CTF and run the reconstruction with the usual workflow with: ```bash -o2-ctf-reader-workflow --ctf-input o2_ctf_0000000000.root --onlyDet MID | o2-mid-reco-workflow +o2-ctf-reader-workflow --ctf-input o2_ctf_0000000000.root --onlyDet MID | o2-mid-reco-workflow --disable-mc ``` ### Generate CTF diff --git a/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx b/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx index 816abb8917611..bf4a6167ae181 100644 --- a/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/reco-workflow.cxx @@ -35,7 +35,7 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) { std::vector<ConfigParamSpec> options{ - {"mc", VariantType::Bool, false, {"Propagate labels"}}, + {"disable-mc", VariantType::Bool, false, {"Do not propagate MC labels"}}, {"disable-tracking", VariantType::Bool, false, {"Only run clustering"}}, {"disable-root-output", VariantType::Bool, false, {"Do not write output to file"}}}; workflowOptions.insert(workflowOptions.end(), options.begin(), options.end()); @@ -45,14 +45,14 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - bool isMC = cfgc.options().get<bool>("mc"); + bool disableMC = cfgc.options().get<bool>("disable-mc"); bool disableTracking = cfgc.options().get<bool>("disable-tracking"); bool disableFile = cfgc.options().get<bool>("disable-root-output"); WorkflowSpec specs; - specs.emplace_back(isMC ? o2::mid::getClusterizerMCSpec() : o2::mid::getClusterizerSpec()); + specs.emplace_back(disableMC ? o2::mid::getClusterizerSpec() : o2::mid::getClusterizerMCSpec()); if (!disableTracking) { - specs.emplace_back(isMC ? o2::mid::getTrackerMCSpec() : o2::mid::getTrackerSpec()); + specs.emplace_back(disableMC ? o2::mid::getTrackerSpec() : o2::mid::getTrackerMCSpec()); } if (!disableFile) { std::array<o2::header::DataDescription, 2> clusterDescriptions{"CLUSTERS", "TRACKCLUSTERS"}; @@ -69,8 +69,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) MakeRootTreeWriterSpec::BranchDefinition<const char*>{InputSpec{"mid_trackClusters", o2::header::gDataOriginMID, clusterDescriptions[idx]}, clusterBranch[idx]}, MakeRootTreeWriterSpec::BranchDefinition<std::vector<o2::mid::ROFRecord>>{InputSpec{"mid_tracks_rof", o2::header::gDataOriginMID, "TRACKSROF"}, "MIDTrackROF", disableTracking ? 0 : 1}, MakeRootTreeWriterSpec::BranchDefinition<std::vector<o2::mid::ROFRecord>>{InputSpec{"mid_trclus_rof", o2::header::gDataOriginMID, clusterROFDescriptions[idx]}, clusterROFBranch[idx]}, - MakeRootTreeWriterSpec::BranchDefinition<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>{InputSpec{"mid_track_labels", o2::header::gDataOriginMID, "TRACKSLABELS"}, "MIDTrackLabels", (disableTracking || !isMC) ? 0 : 1}, - MakeRootTreeWriterSpec::BranchDefinition<o2::dataformats::MCTruthContainer<o2::mid::MCClusterLabel>>{InputSpec{"mid_trclus_labels", o2::header::gDataOriginMID, clusterLabelDescriptions[idx]}, clusterLabelBranch[idx], (!isMC) ? 0 : 1})()); + MakeRootTreeWriterSpec::BranchDefinition<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>{InputSpec{"mid_track_labels", o2::header::gDataOriginMID, "TRACKSLABELS"}, "MIDTrackLabels", (disableTracking || disableMC) ? 0 : 1}, + MakeRootTreeWriterSpec::BranchDefinition<o2::dataformats::MCTruthContainer<o2::mid::MCClusterLabel>>{InputSpec{"mid_trclus_labels", o2::header::gDataOriginMID, clusterLabelDescriptions[idx]}, clusterLabelBranch[idx], disableMC ? 0 : 1})()); } return specs; diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 24cf2346e0ea8..47a471efd4272 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -89,7 +89,7 @@ o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMC o2-ft0-entropy-encoder-workflow $ARGS_ALL | o2-tpcits-match-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | o2-mid-raw-to-digits-workflow $ARGS_ALL | -o2-mid-reco-workflow $ARGS_ALL --disable-root-output | +o2-mid-reco-workflow $ARGS_ALL --disable-root-output ${NOMCLABELS} | o2-mid-entropy-encoder-workflow $ARGS_ALL | o2-tof-compressor $ARGS_ALL | o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output ${NOMCLABELS} | From de829cc5bcad74fd5fd6eb2cb0900b2b6f0e03f3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 17 Nov 2020 10:18:06 +0100 Subject: [PATCH 1343/1751] DPL: fix for messages >2GB (#4843) --- Framework/Core/src/DataProcessingDevice.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 5aac39bb4d3b7..b47fb52cac873 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -505,7 +505,7 @@ void DataProcessingDevice::doPrepare(DataProcessorContext& context) if (info.state != InputChannelState::Running) { continue; } - int result = -2; + int64_t result = -2; auto& fairMQChannel = context.device->GetChannel(channel.name, 0); auto& socket = fairMQChannel.GetSocket(); uint32_t events; From a6ba52d94aa517fdcc78048010a19bebc9024503 Mon Sep 17 00:00:00 2001 From: Ole Schmidt <ole.schmidt@cern.ch> Date: Mon, 16 Nov 2020 16:12:04 +0100 Subject: [PATCH 1344/1751] Add configurableParam for TRD tracker - GPURecSettings are sorted by parameter type size - parameters are (if possible) directly accessed by the tracker without copying them --- .../workflow/src/TRDGlobalTrackingSpec.cxx | 20 +++----------- GPU/GPUTracking/Base/GPUSettingsList.h | 6 +++++ GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 26 +++++++++---------- GPU/GPUTracking/TRDTracking/GPUTRDTracker.h | 12 --------- 4 files changed, 22 insertions(+), 42 deletions(-) diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 2926e78a6a032..6081c105da61b 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -52,25 +52,19 @@ void TRDGlobalTracking::init(InitContext& ic) mFlatGeo = std::make_unique<GeometryFlat>(*geo); //-------- init GPU reconstruction --------// - GPUSettingsEvent cfgEvent; - cfgEvent.solenoidBz = o2::base::Propagator::Instance()->getNominalBz(); - GPUSettingsRec cfgRec; - cfgRec.NWaysOuter = 1; - GPUSettingsProcessing cfgDeviceProcessing; - cfgDeviceProcessing.debugLevel = -1; // -1 : silent GPURecoStepConfiguration cfgRecoStep; cfgRecoStep.steps = GPUDataTypes::RecoStep::NoRecoStep; cfgRecoStep.inputs.clear(); cfgRecoStep.outputs.clear(); mRec = GPUReconstruction::CreateInstance("CPU", true); - mRec->SetSettings(&cfgEvent, &cfgRec, &cfgDeviceProcessing, &cfgRecoStep); + mRec->SetSettings(o2::base::Propagator::Instance()->getNominalBz(), &cfgRecoStep); mChainTracking = mRec->AddChain<GPUChainTracking>(); mTracker = new GPUTRDTracker(); - mTracker->SetNCandidates(1); // must be set before initialization + mTracker->SetNCandidates(mRec->GetProcessingSettings().trdNCandidates); // must be set before initialization mTracker->SetProcessPerTimeFrame(); - mTracker->SetNMaxCollisions(1000); // max number of collisions within a time frame which can be processed + mTracker->SetNMaxCollisions(mRec->GetProcessingSettings().trdNMaxCollisions); mRec->RegisterGPUProcessor(mTracker, false); mChainTracking->SetTRDGeometry(std::move(mFlatGeo)); @@ -78,14 +72,6 @@ void TRDGlobalTracking::init(InitContext& ic) LOG(FATAL) << "GPUReconstruction could not be initialized"; } - // configure the tracker - // TODO: these settings will eventually be moved to GPUSettingsRec to be configurable via --configKeyValues - //mTracker->EnableDebugOutput(); - //mTracker->StartDebugging(); - mTracker->SetPtThreshold(0.5); - mTracker->SetChi2Threshold(15); - mTracker->SetChi2Penalty(12); - mTracker->SetStopTrkFollowingAfterNMissingLayers(6); mTracker->PrintSettings(); mTimer.Stop(); diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index ba703182e656e..75a7da4f77154 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -47,6 +47,9 @@ AddOptionRTC(TrackReferenceX, float, 1000.f, "", 0, "Transport all tracks to thi AddOptionRTC(tpcZSthreshold, float, 2.0f, "", 0, "Zero-Suppression threshold") AddOptionRTC(tpcTubeChi2, float, 5.f * 5.f, "", 0, "Max chi2 to mark cluster adjacent to track") AddOptionRTC(tpcTubeMaxSize2, float, 2.5f * 2.5f, "", 0, "Square of max tube size (normally derrived from tpcTubeChi2)") +AddOptionRTC(trdMinTrackPt, float, .5f, "", 0, "Min Pt for tracks to be propagated through the TRD") +AddOptionRTC(trdMaxChi2, float, 15.f, "", 0, "Max chi2 for TRD tracklets to be matched to a track") +AddOptionRTC(trdPenaltyChi2, float, 12.f, "", 0, "Chi2 penalty for no available TRD tracklet (effective chi2 cut value)") AddOptionRTC(tpcCFqmaxCutoff, unsigned char, 3, "", 0, "Cluster Finder rejects cluster with qmax below this threshold") AddOptionRTC(tpcCFqtotCutoff, unsigned char, 0, "", 0, "Cluster Finder rejects cluster with qtot below this threshold") AddOptionRTC(tpcCFinnerThreshold, unsigned char, 0, "", 0, "Cluster Finder extends cluster if inner charge above this threshold") @@ -78,6 +81,7 @@ AddOptionRTC(retryRefit, char, 1, "", 0, "Retry refit when fit fails") AddOptionRTC(loopInterpolationInExtraPass, char, -1, "", 0, "Perform loop interpolation in an extra pass") AddOptionRTC(mergerReadFromTrackerDirectly, char, 1, "", 0, "Forward data directly from tracker to merger on GPU") AddOptionRTC(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") +AddOptionRTC(trdStopTrkAfterNMissLy, unsigned char, 6, "", 0, "Abandon track following after N layers without a TRD match") AddCustomCPP(void SetMinTrackPt(float v) { MaxTrackQPt = v > 0.001 ? (1. / v) : (1. / 0.001); }) AddVariable(dummyRTC, float, 0.f) // Ensure non empty struct and proper alignment even if all normal members are constexpr AddHelp("help", 'h') @@ -86,6 +90,8 @@ EndConfig() // Settings steering the processing once the device was selected BeginSubConfig(GPUSettingsProcessing, proc, configStandalone, "PROC", 0, "Processing settings") AddOption(platformNum, int, -1, "", 0, "Platform to use, in case the backend provides multiple platforms (-1 = auto-select)") +AddOption(trdNCandidates, int, 1, "", 0, "Number of branching track candidates for single input track during propagation") +AddOption(trdNMaxCollisions, int, 1000, "", 0, "Maximum number of collisions per TF which the TRD tracker can handle") AddOption(gpuDeviceOnly, bool, false, "", 0, "Use only GPU as device (i.e. no CPU for OpenCL)") AddOption(debugMask, int, -1, "", 0, "Mask for debug output dumps to file") AddOption(comparableDebutOutput, bool, true, "", 0, "Make CPU and GPU debug output comparable (sort / skip concurrent parts)") diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index e44964e171845..ef8b167b85f16 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -105,7 +105,7 @@ void* GPUTRDTracker_t<TRDTRK, PROP>::SetPointersTracks(void* base) } template <class TRDTRK, class PROP> -GPUTRDTracker_t<TRDTRK, PROP>::GPUTRDTracker_t() : mR(nullptr), mIsInitialized(false), mProcessPerTimeFrame(false), mMemoryPermanent(-1), mMemoryTracklets(-1), mMemoryTracks(-1), mNMaxCollisions(1), mNMaxTracks(0), mNMaxSpacePoints(0), mTracks(nullptr), mNCandidates(1), mNCollisions(1), mNTracks(0), mNEvents(0), mTriggerRecordIndices(nullptr), mTriggerRecordTimes(nullptr), mTracklets(nullptr), mMaxThreads(100), mNTracklets(0), mTrackletIndexArray(nullptr), mHypothesis(nullptr), mCandidates(nullptr), mSpacePoints(nullptr), mTrackletLabels(nullptr), mGeo(nullptr), mRPhiA2(0), mRPhiB(0), mRPhiC2(0), mDyA2(0), mDyB(0), mDyC2(0), mAngleToDyA(0), mAngleToDyB(0), mAngleToDyC(0), mDebugOutput(false), mTimeWindow(.1f), mRadialOffset(-0.1), mMinPt(2.f), mMaxEta(0.84f), mExtraRoadY(2.f), mRoadZ(18.f), mMaxChi2(15.0f), mMaxMissingLy(6), mChi2Penalty(12.0f), mZCorrCoefNRC(1.4f), mMCEvent(nullptr), mDebug(new GPUTRDTrackerDebug<TRDTRK>()) +GPUTRDTracker_t<TRDTRK, PROP>::GPUTRDTracker_t() : mR(nullptr), mIsInitialized(false), mProcessPerTimeFrame(false), mMemoryPermanent(-1), mMemoryTracklets(-1), mMemoryTracks(-1), mNMaxCollisions(1), mNMaxTracks(0), mNMaxSpacePoints(0), mTracks(nullptr), mNCandidates(1), mNCollisions(1), mNTracks(0), mNEvents(0), mTriggerRecordIndices(nullptr), mTriggerRecordTimes(nullptr), mTracklets(nullptr), mMaxThreads(100), mNTracklets(0), mTrackletIndexArray(nullptr), mHypothesis(nullptr), mCandidates(nullptr), mSpacePoints(nullptr), mTrackletLabels(nullptr), mGeo(nullptr), mRPhiA2(0), mRPhiB(0), mRPhiC2(0), mDyA2(0), mDyB(0), mDyC2(0), mAngleToDyA(0), mAngleToDyB(0), mAngleToDyC(0), mDebugOutput(false), mTimeWindow(.1f), mRadialOffset(-0.1), mMaxEta(0.84f), mExtraRoadY(2.f), mRoadZ(18.f), mZCorrCoefNRC(1.4f), mMCEvent(nullptr), mDebug(new GPUTRDTrackerDebug<TRDTRK>()) { //-------------------------------------------------------------------- // Default constructor @@ -299,8 +299,8 @@ void GPUTRDTracker_t<TRDTRK, PROP>::PrintSettings() const //-------------------------------------------------------------------- GPUInfo("##############################################################"); GPUInfo("Current settings for GPU TRD tracker:"); - GPUInfo(" mMaxChi2(%.2f), mChi2Penalty(%.2f), nCandidates(%i), maxMissingLayers(%i)", mMaxChi2, mChi2Penalty, mNCandidates, mMaxMissingLy); - GPUInfo(" ptCut = %.2f GeV, abs(eta) < %.2f", mMinPt, mMaxEta); + GPUInfo(" maxChi2(%.2f), chi2Penalty(%.2f), nCandidates(%i), maxMissingLayers(%i)", Param().rec.trdMaxChi2, Param().rec.trdPenaltyChi2, mNCandidates, Param().rec.trdStopTrkAfterNMissLy); + GPUInfo(" ptCut = %.2f GeV, abs(eta) < %.2f", Param().rec.trdMinTrackPt, mMaxEta); GPUInfo("##############################################################"); } @@ -435,7 +435,7 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::CheckTrackTRDCandidate(const TRDTRK& if (CAMath::Abs(trk.getEta()) > mMaxEta) { return false; } - if (trk.getPt() < mMinPt) { + if (trk.getPt() < Param().rec.trdMinTrackPt) { return false; } return true; @@ -778,16 +778,16 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK RecalcTrkltCov(tilt, trkWork->getSnp(), pad->GetRowSize(mTracklets[trkltIdx].GetZbin()), trkltCovTmp); float chi2 = prop->getPredictedChi2(trkltPosTmpYZ, trkltCovTmp); // GPUInfo("layer %i: chi2 = %f", iLayer, chi2); - if (chi2 < mMaxChi2 && CAMath::Abs(GetAngularPull(mSpacePoints[trkltIdx].mDy, trkWork->getSnp())) < 4) { + if (chi2 < Param().rec.trdMaxChi2 && CAMath::Abs(GetAngularPull(mSpacePoints[trkltIdx].mDy, trkWork->getSnp())) < 4) { Hypothesis hypo(trkWork->GetNlayers(), iCandidate, trkltIdx, trkWork->GetChi2() + chi2); InsertHypothesis(hypo, nCurrHypothesis, hypothesisIdxOffset); - } // end tracklet chi2 < mMaxChi2 + } // end tracklet chi2 < Param().rec.trdMaxChi2 } // end tracklet in window } // tracklet loop } // chamber loop // add no update to hypothesis list - Hypothesis hypoNoUpdate(trkWork->GetNlayers(), iCandidate, -1, trkWork->GetChi2() + mChi2Penalty); + Hypothesis hypoNoUpdate(trkWork->GetNlayers(), iCandidate, -1, trkWork->GetChi2() + Param().rec.trdPenaltyChi2); InsertHypothesis(hypoNoUpdate, nCurrHypothesis, hypothesisIdxOffset); isOK = true; } // end candidate loop @@ -853,10 +853,10 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK if (mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId == -1) { // no matching tracklet found if (trkWork->GetIsFindable(iLayer)) { - if (trkWork->GetNmissingConsecLayers(iLayer) > mMaxMissingLy) { + if (trkWork->GetNmissingConsecLayers(iLayer) > Param().rec.trdStopTrkAfterNMissLy) { trkWork->SetIsStopped(); } - trkWork->SetChi2(trkWork->GetChi2() + mChi2Penalty); + trkWork->SetChi2(trkWork->GetChi2() + Param().rec.trdPenaltyChi2); } if (iUpdate == 0 && mNCandidates > 1) { // TODO: is thie really necessary????? CHECK! *t = mCandidates[2 * iUpdate + nextIdx]; @@ -876,9 +876,9 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK if (ENABLE_WARNING) { Warning("FollowProlongation", "Final track propagation for track %i update %i in layer %i failed", iTrack, iUpdate, iLayer); } - trkWork->SetChi2(trkWork->GetChi2() + mChi2Penalty); + trkWork->SetChi2(trkWork->GetChi2() + Param().rec.trdPenaltyChi2); if (trkWork->GetIsFindable(iLayer)) { - if (trkWork->GetNmissingConsecLayers(iLayer) >= mMaxMissingLy) { + if (trkWork->GetNmissingConsecLayers(iLayer) >= Param().rec.trdStopTrkAfterNMissLy) { trkWork->SetIsStopped(); } } @@ -922,9 +922,9 @@ GPUd() bool GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK if (ENABLE_WARNING) { Warning("FollowProlongation", "Failed to update track %i with space point in layer %i", iTrack, iLayer); } - trkWork->SetChi2(trkWork->GetChi2() + mChi2Penalty); + trkWork->SetChi2(trkWork->GetChi2() + Param().rec.trdPenaltyChi2); if (trkWork->GetIsFindable(iLayer)) { - if (trkWork->GetNmissingConsecLayers(iLayer) >= mMaxMissingLy) { + if (trkWork->GetNmissingConsecLayers(iLayer) >= Param().rec.trdStopTrkAfterNMissLy) { trkWork->SetIsStopped(); } } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h index b1077ee62d37a..02739fbdad80b 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.h @@ -148,21 +148,13 @@ class GPUTRDTracker_t : public GPUProcessor GPUd() void SetProcessPerTimeFrame() { mProcessPerTimeFrame = true; } GPUd() void SetMCEvent(AliMCEvent* mc) { mMCEvent = mc; } GPUd() void EnableDebugOutput() { mDebugOutput = true; } - GPUd() void SetPtThreshold(float minPt) { mMinPt = minPt; } GPUd() void SetMaxEta(float maxEta) { mMaxEta = maxEta; } - GPUd() void SetChi2Threshold(float chi2) { mMaxChi2 = chi2; } - GPUd() void SetChi2Penalty(float chi2) { mChi2Penalty = chi2; } - GPUd() void SetStopTrkFollowingAfterNMissingLayers(int ly) { mMaxMissingLy = ly; } GPUd() void SetExtraRoadY(float extraRoadY) { mExtraRoadY = extraRoadY; } GPUd() void SetRoadZ(float roadZ) { mRoadZ = roadZ; } GPUd() AliMCEvent* GetMCEvent() const { return mMCEvent; } GPUd() bool GetIsDebugOutputOn() const { return mDebugOutput; } - GPUd() float GetPtThreshold() const { return mMinPt; } GPUd() float GetMaxEta() const { return mMaxEta; } - GPUd() float GetChi2Threshold() const { return mMaxChi2; } - GPUd() float GetChi2Penalty() const { return mChi2Penalty; } - GPUd() int GetMaxMissingLayers() const { return mMaxMissingLy; } GPUd() int GetNCandidates() const { return mNCandidates; } GPUd() float GetExtraRoadY() const { return mExtraRoadY; } GPUd() float GetRoadZ() const { return mRoadZ; } @@ -215,13 +207,9 @@ class GPUTRDTracker_t : public GPUProcessor bool mDebugOutput; // store debug output float mTimeWindow; // max. deviation of the ITS-TPC track time w.r.t. TRD trigger record time stamp (in us, default is 100 ns) float mRadialOffset; // due to mis-calibration of t0 - float mMinPt; // min pt of TPC tracks for tracking float mMaxEta; // TPC tracks with higher eta are ignored float mExtraRoadY; // addition to search road in r-phi to account for not exact radial match of tracklets and tracks in first iteration float mRoadZ; // in z, a constant search road is used - float mMaxChi2; // max chi2 for tracklets - int mMaxMissingLy; // max number of missing layers per track - float mChi2Penalty; // chi2 added to the track for no update float mZCorrCoefNRC; // tracklet z-position depends linearly on track dip angle AliMCEvent* mMCEvent; //! externaly supplied optional MC event GPUTRDTrackerDebug<TRDTRK>* mDebug; // debug output From a867b5fdadacc1bf81587d80cd2f5232aa609201 Mon Sep 17 00:00:00 2001 From: Mario Sitta <Mario.Sitta@cern.ch> Date: Mon, 16 Nov 2020 22:14:53 +0100 Subject: [PATCH 1345/1751] Swap Y coordinate of MB/OB half staves to match their actual position --- Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx b/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx index 48c4b63d42370..86fa07c29c7a1 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/V3Layer.cxx @@ -491,8 +491,8 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) xpos = (static_cast<TGeoBBox*>(hstaveVol->GetShape()))->GetDX() - sOBHalfStaveXOverlap / 2; // ypos is now a parameter to avoid HS displacement wrt nominal radii ypos = sOBHalfStaveYPos; - staveVol->AddNode(hstaveVol, 0, new TGeoTranslation(-xpos, ypos, 0)); - staveVol->AddNode(hstaveVol, 1, new TGeoTranslation(xpos, ypos + sOBHalfStaveYTrans, 0)); + staveVol->AddNode(hstaveVol, 0, new TGeoTranslation(-xpos, ypos + sOBHalfStaveYTrans, 0)); + staveVol->AddNode(hstaveVol, 1, new TGeoTranslation(xpos, ypos, 0)); mHierarchy[kHalfStave] = 2; // RS mechStaveVol = createSpaceFrameOuterB(); From b284c6428177fdf650e80849b357c1cc809daa2f Mon Sep 17 00:00:00 2001 From: sgorbuno <sergey.gorbunov@fias.uni-frankfurt.de> Date: Mon, 16 Nov 2020 20:46:49 +0000 Subject: [PATCH 1346/1751] fix AliRoot compilation --- GPU/TPCFastTransformation/SplineUtil.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GPU/TPCFastTransformation/SplineUtil.h b/GPU/TPCFastTransformation/SplineUtil.h index 0ca3d738f46c7..78c1c540d2715 100644 --- a/GPU/TPCFastTransformation/SplineUtil.h +++ b/GPU/TPCFastTransformation/SplineUtil.h @@ -38,6 +38,9 @@ class SplineUtil // 2 - at least one of the dimensions must be set during runtime // 3 - specialization where nYdim==1 (a small add-on on top of the other specs) + // calculate it as one return statement to make the AliRoot compiler happy + return (nYdim == 1) ? 3 : ((nXdim > 0 && nYdim > 0) ? 1 : 2); + /* if (nYdim == 1) { return 3; } @@ -46,6 +49,7 @@ class SplineUtil } else { return 2; } + */ } /// Spline1D & Spline2D specialization number depending on nYdim From 8ff2c91c714f14edce88b891c8199fc2054acc06 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Mon, 12 Oct 2020 10:31:09 +0200 Subject: [PATCH 1347/1751] Improve treatment of MID raw data consistency check - Fix problem when data has only response to triggers - Possibility to select a different trigger to decide the MID events to check --- Detectors/MUON/MID/QC/exe/raw-checker.cxx | 7 ++- .../MID/QC/include/MIDQC/GBTRawDataChecker.h | 9 ++- .../MID/QC/include/MIDQC/RawDataChecker.h | 2 + .../MUON/MID/QC/src/GBTRawDataChecker.cxx | 59 +++++++++++-------- Detectors/MUON/MID/QC/src/RawDataChecker.cxx | 8 +++ 5 files changed, 58 insertions(+), 27 deletions(-) diff --git a/Detectors/MUON/MID/QC/exe/raw-checker.cxx b/Detectors/MUON/MID/QC/exe/raw-checker.cxx index 733d8310bafd0..4dc2ccc56502e 100644 --- a/Detectors/MUON/MID/QC/exe/raw-checker.cxx +++ b/Detectors/MUON/MID/QC/exe/raw-checker.cxx @@ -66,6 +66,10 @@ int process(po::variables_map& vm) checker.setElectronicsDelay(electronicsDelay); } + if (vm.count("sync-trigger")) { + checker.setSyncTrigger(vm["sync-trigger"].as<uint32_t>()); + } + if (vm.count("crate-masks-file")) { o2::mid::CrateMasks crateMasks(vm["crate-masks-file"].as<std::string>().c_str()); decoder.setCrateMasks(crateMasks); @@ -165,7 +169,8 @@ int main(int argc, char* argv[]) ("crate-masks-file", po::value<std::string>(),"Filename with crate masks") ("electronics-delay-file", po::value<std::string>(),"Filename with electronics delay") ("output-dir", po::value<std::string>()->default_value(""),"Output directory") - ("bare", po::value<bool>()->implicit_value(true),"Use bare decoder"); + ("bare", po::value<bool>()->implicit_value(true),"Use bare decoder") + ("sync-trigger", po::value<unsigned int>(),"Trigger used for synchronisation (default is orbit 0x1)"); po::options_description hidden("hidden options"); diff --git a/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h b/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h index 38b85395510a8..89f131c6106c9 100644 --- a/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h +++ b/Detectors/MUON/MID/QC/include/MIDQC/GBTRawDataChecker.h @@ -47,6 +47,9 @@ class GBTRawDataChecker /// Sets the delay in the electronics void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } + /// Sets the trigger use to verify if all data of an event where received + void setSyncTrigger(uint32_t syncTrigger) { mSyncTrigger = syncTrigger; } + private: struct Mask { std::array<uint16_t, 4> patternsBP{}; /// Bending plane mask @@ -78,6 +81,7 @@ class GBTRawDataChecker unsigned int getLastCompleteTrigEvent(); bool isCompleteSelfTrigEvent(const o2::InteractionRecord& ir) const; std::string printBoards(const std::vector<LocalBoardRO>& boards) const; + bool runCheckEvents(unsigned int completeMask); void sortEvents(bool isTriggered); std::string mEventDebugMsg{}; /// Debug message for the event @@ -88,6 +92,7 @@ class GBTRawDataChecker uint16_t mFeeId{0}; /// FeeId uint16_t mResetVal{0}; /// Reset value ElectronicsDelay mElectronicsDelay{}; /// Delays in the electronics + uint32_t mSyncTrigger{raw::sORB}; /// Trigger for synchronization std::map<o2::InteractionRecord, uint16_t> mTrigEvents{}; ///! Index of triggered events @@ -100,8 +105,8 @@ class GBTRawDataChecker std::map<o2::InteractionRecord, std::vector<std::pair<uint8_t, size_t>>> mOrderedIndexesTrig{}; ///! Ordered indexes for triggered boards std::map<o2::InteractionRecord, std::vector<std::pair<uint8_t, size_t>>> mOrderedIndexesSelfTrig{}; ///! Ordered indexes for self-triggered boards - std::unordered_map<uint8_t, size_t> mLastIndexTrig{}; ///! Last checked index for triggered boards - std::unordered_map<uint8_t, size_t> mLastIndexSelfTrig{}; ///! Last checked index for self-triggered boards + std::unordered_map<uint8_t, long int> mLastIndexTrig{}; ///! Last checked index for triggered boards + std::unordered_map<uint8_t, long int> mLastIndexSelfTrig{}; ///! Last checked index for self-triggered boards o2::InteractionRecord mLastCompleteIRTrig{}; ///! Last complete IR for triggered boards o2::InteractionRecord mLastCompleteIRSelfTrig{}; ///! Last complete IR for self-triggered boards diff --git a/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h b/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h index d761bde848ee9..231acfa4b603b 100644 --- a/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h +++ b/Detectors/MUON/MID/QC/include/MIDQC/RawDataChecker.h @@ -46,6 +46,8 @@ class RawDataChecker /// Sets the delay in the electronics void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } + void setSyncTrigger(uint32_t syncTrigger); + private: std::array<GBTRawDataChecker, crateparams::sNGBTs> mCheckers{}; /// GBT raw data checker std::string mDebugMsg{}; /// Debug message diff --git a/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx b/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx index d1def0c8d06de..6626df2e11aaf 100644 --- a/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx +++ b/Detectors/MUON/MID/QC/src/GBTRawDataChecker.cxx @@ -267,16 +267,17 @@ bool GBTRawDataChecker::isCompleteSelfTrigEvent(const o2::InteractionRecord& ir) // compared to triggered events. // So, we expect information from a previous orbit after having received an orbit trigger. // Let us check that we have all boards with the same orbit + bool isIncluded = false; for (uint8_t ireg = 8; ireg < 10; ++ireg) { auto item = mBoardsSelfTrig.find(ireg); if (item != mBoardsSelfTrig.end()) { + if (item->second.back().interactionRecord.orbit == ir.orbit) { + return false; + } if (item->second.front().interactionRecord.orbit <= ir.orbit) { isIncluded = true; } - if (item->second.back().interactionRecord.orbit <= ir.orbit) { - return false; - } } } return isIncluded; @@ -304,7 +305,7 @@ unsigned int GBTRawDataChecker::getLastCompleteTrigEvent() for (; trigEventIt != end; ++trigEventIt) { if ((trigEventIt->second & fullMask) == fullMask) { // The trigger events contain the unprocessed events for both triggered and self-triggered events - // These might not be synchronized (typically the latest complete self-triggered events lies behind) + // These might not be synchronized (typically the latest complete self-triggered events lie behind) // If the latest IR in memory is more recent than the current complete event found, // then it means that we need to wait for more HBs. if (mLastCompleteIRTrig.isDummy() || mLastCompleteIRTrig < trigEventIt->first) { @@ -320,6 +321,7 @@ unsigned int GBTRawDataChecker::getLastCompleteTrigEvent() } ++trIt; } + return completeMask; } } @@ -327,6 +329,27 @@ unsigned int GBTRawDataChecker::getLastCompleteTrigEvent() return completeMask; } +bool GBTRawDataChecker::runCheckEvents(unsigned int completeMask) +{ + /// Runs the checker if needed + + bool isOk = true; + + if (completeMask & 0x1) { + sortEvents(true); + isOk &= checkEvents(true); + clearChecked(true, mBoardsSelfTrig.empty()); + } + + if (completeMask & 0x2) { + sortEvents(false); + isOk &= checkEvents(false); + clearChecked(false, true); + } + + return isOk; +} + void GBTRawDataChecker::sortEvents(bool isTriggered) { /// Sorts the event in time @@ -337,7 +360,7 @@ void GBTRawDataChecker::sortEvents(bool isTriggered) orderedIndexes.clear(); lastIndexes.clear(); for (auto& boardItem : boards) { - size_t lastIdx = 0; + long int lastIdx = -1; for (auto boardIt = boardItem.second.begin(), end = boardItem.second.end(); boardIt != end; ++boardIt) { if (boardIt->interactionRecord > lastCompleteTrigEventIR) { break; @@ -418,6 +441,10 @@ bool GBTRawDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl:: // Fill board information for (auto rofIt = rofRecords.begin(); rofIt != rofRecords.end(); ++rofIt) { + if (rofIt->interactionRecord.orbit == 0xffffffff) { + // Protection for event with orbit 0 + continue; + } for (auto locIt = localBoards.begin() + rofIt->firstEntry; locIt != localBoards.begin() + rofIt->firstEntry + rofIt->nEntries; ++locIt) { // Find what page this event corresponds to. // This is useful for debugging. @@ -455,8 +482,8 @@ bool GBTRawDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl:: selfVec.push_back({*locIt, ir, page}); } - // Keep track of the orbit triggers - if (locIt->triggerWord & raw::sORB) { + // Keep track of the trigger chosen for synchronisation + if (locIt->triggerWord & mSyncTrigger) { mTrigEvents[rofIt->interactionRecord] |= (1 << id); mResetVal = rofIt->interactionRecord.bc; } @@ -479,23 +506,7 @@ bool GBTRawDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl:: } // loop on local boards } // loop on ROF records - auto completeMask = getLastCompleteTrigEvent(); - - bool isOk = true; - - if (completeMask & 0x1) { - sortEvents(true); - isOk &= checkEvents(true); - clearChecked(true, mBoardsSelfTrig.empty()); - } - - if (completeMask & 0x2) { - sortEvents(false); - isOk &= checkEvents(false); - clearChecked(false, true); - } - - return isOk; + return runCheckEvents(getLastCompleteTrigEvent()); } void GBTRawDataChecker::clear() diff --git a/Detectors/MUON/MID/QC/src/RawDataChecker.cxx b/Detectors/MUON/MID/QC/src/RawDataChecker.cxx index c8e97e10ad6e4..96d8dba849748 100644 --- a/Detectors/MUON/MID/QC/src/RawDataChecker.cxx +++ b/Detectors/MUON/MID/QC/src/RawDataChecker.cxx @@ -55,6 +55,14 @@ bool RawDataChecker::process(gsl::span<const LocalBoardRO> localBoards, gsl::spa return isOk; } +void RawDataChecker::setSyncTrigger(uint32_t syncTrigger) +{ + /// Sets the trigger use to verify if all data of an event where received + for (auto& checker : mCheckers) { + checker.setSyncTrigger(syncTrigger); + } +} + unsigned int RawDataChecker::getNEventsProcessed() const { /// Gets the number of processed events From 3509818e4bf4d4e88145d9939af81146f121a352 Mon Sep 17 00:00:00 2001 From: sgorbuno <sergey.gorbunov@fias.uni-frankfurt.de> Date: Tue, 17 Nov 2020 15:08:39 +0000 Subject: [PATCH 1348/1751] bugfix in ND splines --- GPU/TPCFastTransformation/SplineHelper.cxx | 2 -- GPU/TPCFastTransformation/SplineSpec.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/GPU/TPCFastTransformation/SplineHelper.cxx b/GPU/TPCFastTransformation/SplineHelper.cxx index 2cba30b391468..2275213de3891 100644 --- a/GPU/TPCFastTransformation/SplineHelper.cxx +++ b/GPU/TPCFastTransformation/SplineHelper.cxx @@ -481,11 +481,9 @@ int SplineHelper<DataT>::test(const bool draw, const bool drawDataPoints) Spline<float, nDimX, nDimY> spline(nKnots, knotsU); Spline2D<float, nDimY> spline2D(nKnots[0], knotsU[0], nKnots[1], knotsU[1]); - cout << "mark 1" << std::endl; spline.approximateFunction(xMin, xMax, F, nAxiliaryDatapoints); spline2D.approximateFunction(xMin[0], xMax[0], xMin[1], xMax[1], F2D, nAxiliaryDatapoints[0], nAxiliaryDatapoints[0]); - cout << "mark 2" << std::endl; long double statDf = 0; long double statDf2D = 0; diff --git a/GPU/TPCFastTransformation/SplineSpec.h b/GPU/TPCFastTransformation/SplineSpec.h index 6217415dd7c74..2a3fc9f90df4a 100644 --- a/GPU/TPCFastTransformation/SplineSpec.h +++ b/GPU/TPCFastTransformation/SplineSpec.h @@ -346,7 +346,7 @@ class SplineSpec<DataT, XdimT, YdimT, 0> : public SplineContainer<DataT> int Ydim = nrofInterpolations; DataT coordinate = u[d]; - typedef Spline1DSpec<DataT, YdimT, 0> TGridX; + typedef Spline1DSpec<DataT, 0, YdimT> TGridX; const TGridX& gridX = *((const TGridX*)&(mGrid[d])); gridX.interpolateU(Ydim, knotL, S0, D0, S1, D1, coordinate, iParameters); From c34a4677cc07b6564236099086666c8a1527b28f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 17 Nov 2020 18:54:07 +0100 Subject: [PATCH 1349/1751] DPL: allow multiple workflows in the same session (#4838) --- Framework/Core/include/Framework/DeviceSpec.h | 1 + Framework/Core/src/DataProcessingDevice.cxx | 8 +-- Framework/Core/src/DeviceSpecHelpers.cxx | 65 +++++++++++-------- Framework/Core/src/DeviceSpecHelpers.h | 10 ++- Framework/Core/src/runDataProcessing.cxx | 3 +- Framework/Core/test/test_DeviceSpec.cxx | 8 +-- 6 files changed, 56 insertions(+), 39 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceSpec.h b/Framework/Core/include/Framework/DeviceSpec.h index 3ba159076b9a8..4497d556d704d 100644 --- a/Framework/Core/include/Framework/DeviceSpec.h +++ b/Framework/Core/include/Framework/DeviceSpec.h @@ -40,6 +40,7 @@ namespace framework struct DeviceSpec { std::string name; std::string id; + std::string channelPrefix; std::vector<InputChannelSpec> inputChannels; std::vector<OutputChannelSpec> outputChannels; std::vector<std::string> arguments; diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index b47fb52cac873..20501791119af 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -275,9 +275,9 @@ void DataProcessingDevice::Init() /// expect them to create any data. for (size_t ci = 0; ci < mSpec.inputChannels.size(); ++ci) { auto& name = mSpec.inputChannels[ci].name; - if (name.find("from_internal-dpl-clock") == 0) { + if (name.find(mSpec.channelPrefix + "from_internal-dpl-clock") == 0) { mState.inputChannelInfos[ci].state = InputChannelState::Pull; - } else if (name.find("from_internal-dpl-ccdb-backend") == 0) { + } else if (name.find(mSpec.channelPrefix + "from_internal-dpl-ccdb-backend") == 0) { mState.inputChannelInfos[ci].state = InputChannelState::Pull; } } @@ -355,11 +355,11 @@ void DataProcessingDevice::InitTask() // devices to allow for enumerations. if (mState.activeInputPollers.empty() && mState.activeTimers.empty() && mState.activeSignals.empty()) { for (auto& x : fChannels) { - if (x.first.rfind("from_internal-dpl", 0) == 0) { + if (x.first.rfind(mSpec.channelPrefix + "from_internal-dpl", 0) == 0) { LOG(debug) << x.first << " is an internal channel. Not polling." << std::endl; continue; } - assert(x.first.rfind("from_" + mSpec.name + "_", 0) == 0); + assert(x.first.rfind(mSpec.channelPrefix + "from_" + mSpec.name + "_", 0) == 0); // We assume there is always a ZeroMQ socket behind. int zmq_fd = 0; size_t zmq_fd_len = sizeof(zmq_fd); diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 0cc4ea56c7dea..a5d7ec81952fe 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -252,6 +252,7 @@ void DeviceSpecHelpers::processOutEdgeActions(std::vector<DeviceSpec>& devices, const std::vector<EdgeAction>& actions, const WorkflowSpec& workflow, const std::vector<OutputSpec>& outputsMatchers, const std::vector<ChannelConfigurationPolicy>& channelPolicies, + std::string const& channelPrefix, ComputingOffer const& defaultOffer) { // The topology cannot be empty or not connected. If that is the case, than @@ -261,7 +262,9 @@ void DeviceSpecHelpers::processOutEdgeActions(std::vector<DeviceSpec>& devices, // Edges are navigated in order for each device, so the device associaited to // an edge is always the last one created. - auto deviceForEdge = [&actions, &workflow, &devices, &logicalEdges, &resourceManager, &defaultOffer](size_t ei, ComputingOffer& acceptedOffer) { + auto deviceForEdge = [&actions, &workflow, &devices, + &logicalEdges, &resourceManager, + &defaultOffer, &channelPrefix](size_t ei, ComputingOffer& acceptedOffer) { auto& edge = logicalEdges[ei]; auto& action = actions[ei]; @@ -293,6 +296,7 @@ void DeviceSpecHelpers::processOutEdgeActions(std::vector<DeviceSpec>& devices, DeviceSpec device; device.name = processor.name; device.id = processor.name; + device.channelPrefix = channelPrefix; if (processor.maxInputTimeslices != 1) { device.id = processor.name + "_t" + std::to_string(edge.producerTimeIndex); } @@ -318,7 +322,7 @@ void DeviceSpecHelpers::processOutEdgeActions(std::vector<DeviceSpec>& devices, if (consumer.maxInputTimeslices != 1) { consumerDeviceId += "_t" + std::to_string(edge.timeIndex); } - channel.name = "from_" + device.id + "_to_" + consumerDeviceId; + channel.name = device.channelPrefix + "from_" + device.id + "_to_" + consumerDeviceId; channel.port = acceptedOffer.startPort + acceptedOffer.rangeSize; channel.hostname = acceptedOffer.hostname; deviceResource.usedPorts += 1; @@ -433,6 +437,7 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices, const std::vector<EdgeAction>& actions, const WorkflowSpec& workflow, std::vector<LogicalForwardInfo> const& availableForwardsInfo, std::vector<ChannelConfigurationPolicy> const& channelPolicies, + std::string const& channelPrefix, ComputingOffer const& defaultOffer) { auto const& constDeviceIndex = deviceIndex; @@ -473,7 +478,9 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices, return lastConsumerSearch->deviceIndex; }; - auto createNewDeviceForEdge = [&workflow, &logicalEdges, &devices, &deviceIndex, &resourceManager, &defaultOffer](size_t ei, ComputingOffer& acceptedOffer) { + auto createNewDeviceForEdge = [&workflow, &logicalEdges, &devices, + &deviceIndex, &resourceManager, &defaultOffer, + &channelPrefix](size_t ei, ComputingOffer& acceptedOffer) { auto& edge = logicalEdges[ei]; if (acceptedOffer.hostname != "") { @@ -500,6 +507,7 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices, DeviceSpec device; device.name = processor.name; device.id = processor.name; + device.channelPrefix = channelPrefix; if (processor.maxInputTimeslices != 1) { device.id += "_t" + std::to_string(edge.timeIndex); } @@ -552,7 +560,7 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices, auto const& producerDevice = devices[pi]; auto& consumerDevice = devices[ci]; InputChannelSpec channel; - channel.name = "from_" + producerDevice.id + "_to_" + consumerDevice.id; + channel.name = producerDevice.channelPrefix + "from_" + producerDevice.id + "_to_" + consumerDevice.id; channel.hostname = producerDevice.resource.hostname; channel.port = port; for (auto& policy : channelPolicies) { @@ -695,7 +703,8 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf ResourceManager& resourceManager, std::string const& uniqueWorkflowId, bool optimizeTopology, - unsigned short resourcesMonitoringInterval) + unsigned short resourcesMonitoringInterval, + std::string const& channelPrefix) { std::vector<LogicalForwardInfo> availableForwardsInfo; @@ -747,13 +756,13 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf defaultOffer.memory /= deviceCount + 1; processOutEdgeActions(devices, deviceIndex, connections, resourceManager, outEdgeIndex, logicalEdges, - outActions, workflow, outputs, channelPolicies, defaultOffer); + outActions, workflow, outputs, channelPolicies, channelPrefix, defaultOffer); // FIXME: is this not the case??? std::sort(connections.begin(), connections.end()); processInEdgeActions(devices, deviceIndex, connections, resourceManager, inEdgeIndex, logicalEdges, - inActions, workflow, availableForwardsInfo, channelPolicies, defaultOffer); + inActions, workflow, availableForwardsInfo, channelPolicies, channelPrefix, defaultOffer); // We apply the completion policies here since this is where we have all the // devices resolved. for (auto& device : devices) { @@ -984,6 +993,7 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, realOdesc.add_options()("shm-throw-bad-alloc", bpo::value<std::string>()); realOdesc.add_options()("shm-segment-id", bpo::value<std::string>()); realOdesc.add_options()("shm-monitor", bpo::value<std::string>()); + realOdesc.add_options()("channel-prefix", bpo::value<std::string>()); realOdesc.add_options()("session", bpo::value<std::string>()); filterArgsFct(expansions.we_wordc, expansions.we_wordv, realOdesc); wordfree(&expansions); @@ -1087,26 +1097,27 @@ boost::program_options::options_description DeviceSpecHelpers::getForwardedDevic // - rate is an option of FairMQ device for ConditionalRun // - child-driver is not a FairMQ device option but used per device to start to process bpo::options_description forwardedDeviceOptions; - forwardedDeviceOptions.add_options() // - ("severity", bpo::value<std::string>()->default_value("info"), "severity level of the log") // - ("plugin,P", bpo::value<std::string>(), "FairMQ plugin list") // - ("plugin-search-path,S", bpo::value<std::string>(), "FairMQ plugins search path") // - ("control-port", bpo::value<std::string>(), "Utility port to be used by O2 Control") // - ("rate", bpo::value<std::string>(), "rate for a data source device (Hz)") // - ("shm-monitor", bpo::value<std::string>(), "whether to use the shared memory monitor") // - ("shm-segment-size", bpo::value<std::string>(), "size of the shared memory segment in bytes") // - ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // - ("shm-zero-segment", bpo::value<std::string>()->default_value("false"), "zero shared memory segment") // - ("shm-throw-bad-alloc", bpo::value<std::string>()->default_value("true"), "throw if insufficient shm memory") // - ("shm-segment-id", bpo::value<std::string>()->default_value("0"), "shm segment id") // - ("environment", bpo::value<std::string>(), "comma separated list of environment variables to set for the device") // - ("post-fork-command", bpo::value<std::string>(), "post fork command to execute (e.g. numactl {pid}") // - ("session", bpo::value<std::string>(), "unique label for the shared memory session") // - ("configuration,cfg", bpo::value<std::string>(), "configuration connection string") // - ("monitoring-backend", bpo::value<std::string>(), "monitoring connection string") // - ("infologger-mode", bpo::value<std::string>(), "INFOLOGGER_MODE override") // - ("infologger-severity", bpo::value<std::string>(), "minimun FairLogger severity which goes to info logger") // - ("child-driver", bpo::value<std::string>(), "external driver to start childs with (e.g. valgrind)"); // + forwardedDeviceOptions.add_options() // + ("severity", bpo::value<std::string>()->default_value("info"), "severity level of the log") // + ("plugin,P", bpo::value<std::string>(), "FairMQ plugin list") // + ("plugin-search-path,S", bpo::value<std::string>(), "FairMQ plugins search path") // + ("control-port", bpo::value<std::string>(), "Utility port to be used by O2 Control") // + ("rate", bpo::value<std::string>(), "rate for a data source device (Hz)") // + ("shm-monitor", bpo::value<std::string>(), "whether to use the shared memory monitor") // + ("channel-prefix", bpo::value<std::string>()->default_value(""), "prefix to use for multiplexing multiple workflows in the same session") // + ("shm-segment-size", bpo::value<std::string>(), "size of the shared memory segment in bytes") // + ("shm-mlock-segment", bpo::value<std::string>()->default_value("false"), "mlock shared memory segment") // + ("shm-zero-segment", bpo::value<std::string>()->default_value("false"), "zero shared memory segment") // + ("shm-throw-bad-alloc", bpo::value<std::string>()->default_value("true"), "throw if insufficient shm memory") // + ("shm-segment-id", bpo::value<std::string>()->default_value("0"), "shm segment id") // + ("environment", bpo::value<std::string>(), "comma separated list of environment variables to set for the device") // + ("post-fork-command", bpo::value<std::string>(), "post fork command to execute (e.g. numactl {pid}") // + ("session", bpo::value<std::string>(), "unique label for the shared memory session") // + ("configuration,cfg", bpo::value<std::string>(), "configuration connection string") // + ("monitoring-backend", bpo::value<std::string>(), "monitoring connection string") // + ("infologger-mode", bpo::value<std::string>(), "INFOLOGGER_MODE override") // + ("infologger-severity", bpo::value<std::string>(), "minimun FairLogger severity which goes to info logger") // + ("child-driver", bpo::value<std::string>(), "external driver to start childs with (e.g. valgrind)"); // return forwardedDeviceOptions; } diff --git a/Framework/Core/src/DeviceSpecHelpers.h b/Framework/Core/src/DeviceSpecHelpers.h index a37c70471e12f..f3c69f8863c0c 100644 --- a/Framework/Core/src/DeviceSpecHelpers.h +++ b/Framework/Core/src/DeviceSpecHelpers.h @@ -50,7 +50,8 @@ struct DeviceSpecHelpers { ResourceManager& resourceManager, std::string const& uniqueWorkflowId, bool optimizeTopology = false, - unsigned short resourcesMonitoringInterval = 0); + unsigned short resourcesMonitoringInterval = 0, + std::string const& channelPrefix = ""); static void dataProcessorSpecs2DeviceSpecs( const WorkflowSpec& workflow, @@ -60,11 +61,12 @@ struct DeviceSpecHelpers { ResourceManager& resourceManager, std::string const& uniqueWorkflowId, bool optimizeTopology = false, - unsigned short resourcesMonitoringInterval = 0) + unsigned short resourcesMonitoringInterval = 0, + std::string const& channelPrefix = "") { std::vector<DispatchPolicy> dispatchPolicies = DispatchPolicy::createDefaultPolicies(); dataProcessorSpecs2DeviceSpecs(workflow, channelPolicies, completionPolicies, - dispatchPolicies, devices, resourceManager, uniqueWorkflowId, optimizeTopology, resourcesMonitoringInterval); + dispatchPolicies, devices, resourceManager, uniqueWorkflowId, optimizeTopology, resourcesMonitoringInterval, channelPrefix); } /// Helper to provide the channel configuration string for an input channel @@ -102,6 +104,7 @@ struct DeviceSpecHelpers { const WorkflowSpec& workflow, const std::vector<OutputSpec>& outputs, std::vector<ChannelConfigurationPolicy> const& channelPolicies, + std::string const& channelPrefix, ComputingOffer const& defaultOffer); /// This takes the list of preprocessed edges of a graph @@ -119,6 +122,7 @@ struct DeviceSpecHelpers { const WorkflowSpec& workflow, const std::vector<LogicalForwardInfo>& availableForwardsInfo, std::vector<ChannelConfigurationPolicy> const& channelPolicies, + std::string const& channelPrefix, ComputingOffer const& defaultOffer); /// return a description of all options to be forwarded to the device diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index bdeed2f1a5e43..bc397fb6c54be 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1039,7 +1039,8 @@ int runStateMachine(DataProcessorSpecs const& workflow, *resourceManager, driverInfo.uniqueWorkflowId, !varmap["no-IPC"].as<bool>(), - driverInfo.resourcesMonitoringInterval); + driverInfo.resourcesMonitoringInterval, + varmap["channel-prefix"].as<std::string>()); metricProcessingCallbacks.clear(); for (auto& device : deviceSpecs) { for (auto& service : device.services) { diff --git a/Framework/Core/test/test_DeviceSpec.cxx b/Framework/Core/test/test_DeviceSpec.cxx index fcf2f096e61d5..de73b4c3c6322 100644 --- a/Framework/Core/test/test_DeviceSpec.cxx +++ b/Framework/Core/test/test_DeviceSpec.cxx @@ -413,7 +413,7 @@ BOOST_AUTO_TEST_CASE(TestOutEdgeProcessingHelpers) defaultOffer.memory = 0.01; DeviceSpecHelpers::processOutEdgeActions(devices, deviceIndex, connections, rm, edgeOutIndex, logicalEdges, - actions, workflow, globalOutputs, channelPolicies, defaultOffer); + actions, workflow, globalOutputs, channelPolicies, "", defaultOffer); std::vector<DeviceId> expectedDeviceIndex = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 1}, {1, 0, 1}, {1, 1, 2}, {1, 1, 2}, {1, 2, 3}, {1, 2, 3}}; BOOST_REQUIRE_EQUAL(devices.size(), 4); // For producers @@ -461,7 +461,7 @@ BOOST_AUTO_TEST_CASE(TestOutEdgeProcessingHelpers) std::sort(connections.begin(), connections.end()); DeviceSpecHelpers::processInEdgeActions(devices, deviceIndex, connections, rm, edgeInIndex, logicalEdges, - inActions, workflow, availableForwardsInfo, channelPolicies, defaultOffer); + inActions, workflow, availableForwardsInfo, channelPolicies, "", defaultOffer); // std::vector<DeviceId> expectedDeviceIndexFinal = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 1}, {1, 0, 1}, {1, 1, 2}, {1, 1, 2}, {1, 2, 3}, {1, 2, 3}, {2, 0, 4}, {2, 1, 5}}; BOOST_REQUIRE_EQUAL(expectedDeviceIndexFinal.size(), deviceIndex.size()); @@ -729,7 +729,7 @@ BOOST_AUTO_TEST_CASE(TestSimpleWildcard) defaultOffer.memory = 0.01; DeviceSpecHelpers::processOutEdgeActions(devices, deviceIndex, connections, rm, edgeOutIndex, logicalEdges, - outActions, workflow, globalOutputs, channelPolicies, defaultOffer); + outActions, workflow, globalOutputs, channelPolicies, "", defaultOffer); BOOST_REQUIRE_EQUAL(devices.size(), 2); // Two devices have outputs: A and Timer BOOST_CHECK_EQUAL(devices[0].name, "A"); @@ -745,7 +745,7 @@ BOOST_AUTO_TEST_CASE(TestSimpleWildcard) std::sort(connections.begin(), connections.end()); DeviceSpecHelpers::processInEdgeActions(devices, deviceIndex, connections, rm, edgeInIndex, logicalEdges, - inActions, workflow, availableForwardsInfo, channelPolicies, defaultOffer); + inActions, workflow, availableForwardsInfo, channelPolicies, "", defaultOffer); BOOST_REQUIRE_EQUAL(devices.size(), 3); // Now we also have B BOOST_CHECK_EQUAL(devices[0].name, "A"); From 2776f73d17ccf98b635fdaee291582b351a78ab5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 17 Nov 2020 18:57:00 +0100 Subject: [PATCH 1350/1751] DPL: workaround cling issue with std::variant (#4848) --- Framework/Core/include/Framework/InputSpec.h | 4 ++++ Framework/Core/include/Framework/OutputSpec.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Framework/Core/include/Framework/InputSpec.h b/Framework/Core/include/Framework/InputSpec.h index d9e3f3201d66d..2a21f9d161b52 100644 --- a/Framework/Core/include/Framework/InputSpec.h +++ b/Framework/Core/include/Framework/InputSpec.h @@ -17,7 +17,9 @@ #include <string> #include <ostream> +#if !defined(__CLING__) && !defined(__ROOTCLING__) #include <variant> +#endif namespace o2::framework { @@ -57,7 +59,9 @@ struct InputSpec { std::string binding; /// The actual matcher for the input spec. +#if !defined(__CLING__) && !defined(__ROOTCLING__) std::variant<ConcreteDataMatcher, data_matcher::DataDescriptorMatcher> matcher; +#endif enum Lifetime lifetime; diff --git a/Framework/Core/include/Framework/OutputSpec.h b/Framework/Core/include/Framework/OutputSpec.h index 8bb008774661e..6f8357c127e37 100644 --- a/Framework/Core/include/Framework/OutputSpec.h +++ b/Framework/Core/include/Framework/OutputSpec.h @@ -14,7 +14,9 @@ #include "Framework/Lifetime.h" #include "Framework/ConcreteDataMatcher.h" +#if !defined(__CLING__) && !defined(__ROOTCLING__) #include <variant> +#endif namespace o2::framework { @@ -28,7 +30,9 @@ struct OutputLabel { /// topology. struct OutputSpec { OutputLabel binding; +#if !defined(__CLING__) && !defined(__ROOTCLING__) std::variant<ConcreteDataMatcher, ConcreteDataTypeMatcher> matcher; +#endif enum Lifetime lifetime = Lifetime::Timeframe; /// Build a fully qualified tuple for the OutputSpec From 7ce6958f27fed1ff4f87b52e7c1774157cd7d4fd Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 17 Nov 2020 19:23:23 +0100 Subject: [PATCH 1351/1751] CCDB-API: tokens are handled differently on GRID (#4853) * CCDB-API: tokens are handled differently on GRID --- CCDB/src/CcdbApi.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 52e61710d0775..d6f6c270e41c2 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -656,6 +656,9 @@ bool CcdbApi::checkAlienToken() const // a somewhat weird construction to programmatically find out if we // have a GRID token; Can be replaced with something more elegant once // alien-token-info does not ask for passwords interactively + if (getenv("JALIEN_TOKEN_CERT")) { + return true; + } auto returncode = system("timeout 1s timeout 1s alien-token-info &> /dev/null"); return returncode == 0; } From 4b2217236986f7c03e11273d3c359240a109bc1b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 14 Nov 2020 13:52:19 +0100 Subject: [PATCH 1352/1751] GPU QA: Split into multiple tasks that can be en/disabled individually --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 12 +- GPU/GPUTracking/Base/GPUSettingsList.h | 3 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- .../Interface/GPUO2InterfaceQA.cxx | 4 +- GPU/GPUTracking/Interface/GPUO2InterfaceQA.h | 2 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 1866 +++++++++-------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 19 +- 7 files changed, 987 insertions(+), 921 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 2b16a80d6f4ef..5a3ccdd611eb2 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -102,6 +102,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config std::unique_ptr<TPCdEdxCalibrationSplines> dEdxSplines; std::unique_ptr<TPCCFCalibration> tpcCalibration; std::unique_ptr<GPUSettingsQA> qaConfig; + int qaTaskMask = 0; std::unique_ptr<GPUO2InterfaceQA> qa; std::vector<int> clusterOutputIds; unsigned long outputBufferSize = 0; @@ -162,10 +163,15 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } config.configProcessing.runMC = specconfig.processMC; if (specconfig.outputQA) { + if (!specconfig.processMC) { + throw std::runtime_error("Need MC information to create QA plots"); + } + config.configQA.shipToQC = true; if (!config.configProcessing.runQA) { - config.configQA.shipToQC = true; + config.configQA.enableLocalOutput = false; + processAttributes->qaTaskMask = 15; + config.configProcessing.runQA = -processAttributes->qaTaskMask; } - config.configProcessing.runQA = true; } config.configReconstruction.NWaysOuter = true; config.configInterface.outputToExternalBuffers = true; @@ -711,7 +717,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config std::vector<TH1F> copy1 = *outputRegions.qa.hist1; // Internally, this will also be used as output, so we need a non-const copy std::vector<TH2F> copy2 = *outputRegions.qa.hist2; std::vector<TH1D> copy3 = *outputRegions.qa.hist3; - processAttributes->qa->postprocess(copy1, copy2, copy3, out); + processAttributes->qa->postprocess(copy1, copy2, copy3, out, processAttributes->qaTaskMask ? processAttributes->qaTaskMask : -1); pc.outputs().snapshot({gDataOriginTPC, "TRACKINGQA", 0, Lifetime::Timeframe}, out); processAttributes->qa->cleanup(); } diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 75a7da4f77154..39d77c565fe8d 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -122,7 +122,7 @@ AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") -AddOption(runQA, bool, false, "qa", 'q', "Enable tracking QA", message("Running QA: %s")) +AddOption(runQA, int, 0, "qa", 'q', "Enable tracking QA (negative number to provide bitmask for QA tasks)", message("Running QA: %d"), def(1)) AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") AddOption(forceMemoryPoolSize, unsigned long, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ul)) AddOption(forceHostMemoryPoolSize, unsigned long, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ul)) @@ -168,6 +168,7 @@ AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") AddOption(noMC, bool, false, "", 0, "Force running QA without MC labels even if present") AddOption(shipToQC, bool, false, "", 0, "Do not write output files but ship histograms for QC") AddOption(shipToQCAsCanvas, bool, false, "", 0, "Send TCanvases with full layout to QC instead of individual histograms") +AddOption(enableLocalOutput, bool, true, "", 0, "Enable normal output to local PDF files / console") AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 96839d6841f54..f25960f404c9a 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2400,7 +2400,7 @@ int GPUChainTracking::RunChain() } const bool needQA = GPUQA::QAAvailable() && (GetProcessingSettings().runQA || (GetProcessingSettings().eventDisplay && mIOPtrs.nMCInfosTPC)); if (needQA && mQA->IsInitialized() == false) { - if (mQA->InitQA()) { + if (mQA->InitQA(GetProcessingSettings().runQA ? -GetProcessingSettings().runQA : -1)) { return 1; } } diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx index 31bc68d340edb..e49456a0fea4c 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx @@ -23,9 +23,9 @@ GPUO2InterfaceQA::GPUO2InterfaceQA(const GPUSettingsQA* config) : mQA(new GPUQA( GPUO2InterfaceQA::~GPUO2InterfaceQA() = default; -int GPUO2InterfaceQA::postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out) +int GPUO2InterfaceQA::postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out, int tasks) { - if (mQA->loadHistograms(in1, in2, in3)) { + if (mQA->loadHistograms(in1, in2, in3, tasks)) { return 1; } return mQA->DrawQAHistograms(&out); diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h index 6d75cdb645967..73d4e4a72da01 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h @@ -44,7 +44,7 @@ class GPUO2InterfaceQA ~GPUO2InterfaceQA(); // Input might be modified, so we assume non-const. If it is const, a copy should be created before. - int postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out); + int postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out, int tasks); void cleanup(); private: diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 3907142102bac..28534cdcf0122 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -321,7 +321,6 @@ GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(c { static int initColorsInitialized = initColors(); (void)initColorsInitialized; - mRunForQC = chain == nullptr || mConfig.shipToQC; } GPUQA::~GPUQA() @@ -422,21 +421,23 @@ int GPUQA::GetMCTrackLabel(unsigned int trackId) const { return (trackId >= mTra int GPUQA::InitQACreateHistograms() { char name[2048], fname[1024]; - // Create Efficiency Histograms - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - for (int l = 0; l < 5; l++) { - for (int m = 0; m < 2; m++) { - sprintf(name, "%s%s%s%sVs%s", m ? "eff" : "tracks", EFF_TYPES[i], FINDABLE_NAMES[j], PRIM_NAMES[k], VSPARAMETER_NAMES[l]); - if (l == 4) { - std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; - createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], binsPt.get()); - } else { - createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]); - } - if (!mHaveExternalHists) { - mEff[i][j][k][l][m]->Sumw2(); + if (mQATasks & taskTrackingEff) { + // Create Efficiency Histograms + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + for (int l = 0; l < 5; l++) { + for (int m = 0; m < 2; m++) { + sprintf(name, "%s%s%s%sVs%s", m ? "eff" : "tracks", EFF_TYPES[i], FINDABLE_NAMES[j], PRIM_NAMES[k], VSPARAMETER_NAMES[l]); + if (l == 4) { + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], binsPt.get()); + } else { + createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]); + } + if (!mHaveExternalHists) { + mEff[i][j][k][l][m]->Sumw2(); + } } } } @@ -445,68 +446,72 @@ int GPUQA::InitQACreateHistograms() } // Create Resolution Histograms - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 5; j++) { - sprintf(name, "rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); - sprintf(fname, "mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); - if (j == 4) { - std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; - createHist(mRes[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); - createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); - } else { - createHist(mRes[i][j][0], name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); - createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); - } - sprintf(name, "res_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); - const float* axis = mConfig.nativeFitResolutions ? RES_AXES_NATIVE : RES_AXES; - const int nbins = i == 4 && mConfig.nativeFitResolutions ? (10 * RES_AXIS_BINS[0]) : RES_AXIS_BINS[0]; - if (j == 4) { - std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; - createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], binsPt.get()); - } else { - createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + if (mQATasks & taskTrackingRes) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + sprintf(name, "rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); + sprintf(fname, "mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); + if (j == 4) { + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + createHist(mRes[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); + createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); + } else { + createHist(mRes[i][j][0], name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + } + sprintf(name, "res_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); + const float* axis = mConfig.nativeFitResolutions ? RES_AXES_NATIVE : RES_AXES; + const int nbins = i == 4 && mConfig.nativeFitResolutions ? (10 * RES_AXIS_BINS[0]) : RES_AXIS_BINS[0]; + if (j == 4) { + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], binsPt.get()); + } else { + createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + } } } } // Create Pull Histograms - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 5; j++) { - sprintf(name, "pull_rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); - sprintf(fname, "pull_mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); - if (j == 4) { - std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; - createHist(mPull[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); - createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); - } else { - createHist(mPull[i][j][0], name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); - createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); - } - sprintf(name, "pull_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); - if (j == 4) { - std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; - createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], binsPt.get()); - } else { - createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + if (mQATasks & taskTrackingResPull) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + sprintf(name, "pull_rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); + sprintf(fname, "pull_mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); + if (j == 4) { + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + createHist(mPull[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); + createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); + } else { + createHist(mPull[i][j][0], name, name, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + } + sprintf(name, "pull_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); + if (j == 4) { + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], binsPt.get()); + } else { + createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); + } } } } // Create Cluster Histograms - for (int i = 0; i < N_CLS_TYPE * N_CLS_HIST - 1; i++) { - int ioffset = i >= (2 * N_CLS_HIST - 1) ? (2 * N_CLS_HIST - 1) : i >= N_CLS_HIST ? N_CLS_HIST : 0; - int itype = i >= (2 * N_CLS_HIST - 1) ? 2 : i >= N_CLS_HIST ? 1 : 0; - sprintf(name, "clusters%s%s", CLUSTER_NAMES_SHORT[i - ioffset], CLUSTER_TYPES[itype]); - std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; - createHist(mClusters[i], name, name, AXIS_BINS[4], binsPt.get()); + if (mQATasks & taskClusterAttach) { + for (int i = 0; i < N_CLS_TYPE * N_CLS_HIST - 1; i++) { + int ioffset = i >= (2 * N_CLS_HIST - 1) ? (2 * N_CLS_HIST - 1) : i >= N_CLS_HIST ? N_CLS_HIST : 0; + int itype = i >= (2 * N_CLS_HIST - 1) ? 2 : i >= N_CLS_HIST ? 1 : 0; + sprintf(name, "clusters%s%s", CLUSTER_NAMES_SHORT[i - ioffset], CLUSTER_TYPES[itype]); + std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; + createHist(mClusters[i], name, name, AXIS_BINS[4], binsPt.get()); + } } - { + + if (mQATasks & taskTrackStatistics) { + // Create Tracks Histograms sprintf(name, "nclusters"); createHist(mNCl, name, name, 160, 0, 159); - } - - // Create Tracks Histograms - { sprintf(name, "tracks"); std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; createHist(mTracks, name, name, AXIS_BINS[4], binsPt.get()); @@ -525,11 +530,17 @@ int GPUQA::InitQACreateHistograms() return 0; } -int GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3) +int GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3, int tasks) { - if (mQAInitialized) { + if (tasks == -1) { + tasks = taskDefaultPostprocess; + } + if (mQAInitialized && (!mHaveExternalHists || tasks != mQATasks)) { return 1; } + if (tasks & taskClusterCounts) { + throw std::runtime_error("Cluster counts impossible with external histograms"); + } mHist1D = &i1; mHist2D = &i2; mHist1Dd = &i3; @@ -537,6 +548,7 @@ int GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vec mHist2D_pos.clear(); mHist1Dd_pos.clear(); mHaveExternalHists = true; + mQATasks = tasks; if (InitQACreateHistograms()) { return 1; } @@ -544,21 +556,25 @@ int GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vec return 0; } -int GPUQA::InitQA() +int GPUQA::InitQA(int tasks) { if (mQAInitialized) { return 1; } + if (tasks == -1) { + tasks = taskDefault; + } mHist1D = new std::vector<TH1F>; mHist2D = new std::vector<TH2F>; mHist1Dd = new std::vector<TH1D>; + mQATasks = tasks; if (InitQACreateHistograms()) { return 1; } - if (!mRunForQC) { + if (mConfig.enableLocalOutput) { mkdir("plots", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } @@ -939,329 +955,396 @@ void GPUQA::RunQA(bool matchOnly) } // Fill Efficiency Histograms - for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) { - for (unsigned int i = 0; i < GetNMCTracks(iCol); i++) { - if ((mMCTrackMin != -1 && (int)i < mMCTrackMin) || (mMCTrackMax != -1 && (int)i >= mMCTrackMax)) { + if (mQATasks & taskTrackingEff) { + for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) { + for (unsigned int i = 0; i < GetNMCTracks(iCol); i++) { + if ((mMCTrackMin != -1 && (int)i < mMCTrackMin) || (mMCTrackMax != -1 && (int)i >= mMCTrackMax)) { + continue; + } + const mcInfo_t& info = GetMCTrack(i, iCol); + const additionalMCParameters& mc2 = mMCParam[iCol][i]; + if (mc2.nWeightCls == 0.f) { + continue; + } + const float& mcpt = mc2.pt; + const float& mcphi = mc2.phi; + const float& mceta = mc2.eta; + + if (info.prim && info.primDaughters) { + continue; + } + if (mc2.nWeightCls < MIN_WEIGHT_CLS) { + continue; + } + int findable = mc2.nWeightCls >= FINDABLE_WEIGHT_CLS; + if (info.pid < 0) { + continue; + } + if (info.charge == 0.f) { + continue; + } + if (mConfig.filterCharge && info.charge * mConfig.filterCharge < 0) { + continue; + } + if (mConfig.filterPID >= 0 && info.pid != mConfig.filterPID) { + continue; + } + + if (fabsf(mceta) > ETA_MAX || mcpt < PT_MIN || mcpt > PT_MAX) { + continue; + } + + float alpha = std::atan2(info.y, info.x); + alpha /= M_PI / 9.f; + alpha = std::floor(alpha); + alpha *= M_PI / 9.f; + alpha += M_PI / 18.f; + + float c = std::cos(alpha); + float s = std::sin(alpha); + float localY = -info.x * s + info.y * c; + + for (int j = 0; j < 4; j++) { + for (int k = 0; k < 2; k++) { + if (k == 0 && findable == 0) { + continue; + } + + int val = (j == 0) ? (mRecTracks[iCol][i] ? 1 : 0) : (j == 1) ? (mRecTracks[iCol][i] ? mRecTracks[iCol][i] - 1 : 0) : (j == 2) ? mFakeTracks[iCol][i] : 1; + + for (int l = 0; l < 5; l++) { + if (info.prim && mcpt < PT_MIN_PRIM) { + continue; + } + if (l != 3 && fabsf(mceta) > ETA_MAX2) { + continue; + } + if (l < 4 && mcpt < 1.f / mConfig.qpt) { + continue; + } + + float pos = l == 0 ? localY : l == 1 ? info.z : l == 2 ? mcphi : l == 3 ? mceta : mcpt; + + mEff[j][k][!info.prim][l][0]->Fill(pos, val); + } + } + } + } + } + if (QA_TIMING) { + GPUInfo("QA Time: Fill efficiency histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + } + } + + // Fill Resolution Histograms + if (mQATasks & (taskTrackingRes | taskTrackingResPull)) { + GPUTPCGMPropagator prop; + prop.SetMaxSinPhi(.999); + prop.SetMaterialTPC(); + prop.SetPolynomialField(&mTracking->GetParam().polynomialField); + prop.SetToyMCEventsFlag(mTracking->GetParam().par.ToyMCEventsFlag); + + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + if (mConfig.writeMCLabels) { + std::vector<int>& labelBuffer = mcLabelBuffer[mNEvents - 1]; + labelBuffer[i] = mTrackMCLabels[i].getTrackID(); + } + if (mTrackMCLabels[i].isFake()) { continue; } - const mcInfo_t& info = GetMCTrack(i, iCol); - const additionalMCParameters& mc2 = mMCParam[iCol][i]; - if (mc2.nWeightCls == 0.f) { + const mcInfo_t& mc1 = GetMCTrack(mTrackMCLabels[i]); + const additionalMCParameters& mc2 = GetMCTrackObj(mMCParam, mTrackMCLabels[i]); + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; + + if ((mMCTrackMin != -1 && mTrackMCLabels[i].getTrackID() < mMCTrackMin) || (mMCTrackMax != -1 && mTrackMCLabels[i].getTrackID() >= mMCTrackMax)) { continue; } - const float& mcpt = mc2.pt; - const float& mcphi = mc2.phi; - const float& mceta = mc2.eta; - if (info.prim && info.primDaughters) { + if (!track.OK()) { continue; } - if (mc2.nWeightCls < MIN_WEIGHT_CLS) { + if (track.MergedLooper()) { continue; } - int findable = mc2.nWeightCls >= FINDABLE_WEIGHT_CLS; - if (info.pid < 0) { + if (fabsf(mc2.eta) > ETA_MAX || mc2.pt < PT_MIN || mc2.pt > PT_MAX) { continue; } - if (info.charge == 0.f) { + if (mc1.charge == 0.f) { continue; } - if (mConfig.filterCharge && info.charge * mConfig.filterCharge < 0) { + if (mc1.pid < 0) { continue; } - if (mConfig.filterPID >= 0 && info.pid != mConfig.filterPID) { + if (mConfig.filterCharge && mc1.charge * mConfig.filterCharge < 0) { continue; } - - if (fabsf(mceta) > ETA_MAX || mcpt < PT_MIN || mcpt > PT_MAX) { + if (mConfig.filterPID >= 0 && mc1.pid != mConfig.filterPID) { continue; } - - float alpha = std::atan2(info.y, info.x); - alpha /= M_PI / 9.f; - alpha = std::floor(alpha); - alpha *= M_PI / 9.f; - alpha += M_PI / 18.f; - - float c = std::cos(alpha); - float s = std::sin(alpha); - float localY = -info.x * s + info.y * c; - - for (int j = 0; j < 4; j++) { - for (int k = 0; k < 2; k++) { - if (k == 0 && findable == 0) { - continue; - } - - int val = (j == 0) ? (mRecTracks[iCol][i] ? 1 : 0) : (j == 1) ? (mRecTracks[iCol][i] ? mRecTracks[iCol][i] - 1 : 0) : (j == 2) ? mFakeTracks[iCol][i] : 1; - - for (int l = 0; l < 5; l++) { - if (info.prim && mcpt < PT_MIN_PRIM) { - continue; - } - if (l != 3 && fabsf(mceta) > ETA_MAX2) { - continue; - } - if (l < 4 && mcpt < 1.f / mConfig.qpt) { - continue; - } - - float pos = l == 0 ? localY : l == 1 ? info.z : l == 2 ? mcphi : l == 3 ? mceta : mcpt; - - mEff[j][k][!info.prim][l][0]->Fill(pos, val); - } - } + if (mc2.nWeightCls < MIN_WEIGHT_CLS) { + continue; + } + if (mConfig.resPrimaries == 1 && (!mc1.prim || mc1.primDaughters)) { + continue; + } else if (mConfig.resPrimaries == 2 && (mc1.prim || mc1.primDaughters)) { + continue; + } + if (GetMCTrackObj(mTrackMCLabelsReverse, mTrackMCLabels[i]) != (int)i) { + continue; } - } - } - if (QA_TIMING) { - GPUInfo("QA Time: Fill efficiency histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); - } - - // Fill Resolution Histograms - GPUTPCGMPropagator prop; - prop.SetMaxSinPhi(.999); - prop.SetMaterialTPC(); - prop.SetPolynomialField(&mTracking->GetParam().polynomialField); - prop.SetToyMCEventsFlag(mTracking->GetParam().par.ToyMCEventsFlag); - - for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { - if (mConfig.writeMCLabels) { - std::vector<int>& labelBuffer = mcLabelBuffer[mNEvents - 1]; - labelBuffer[i] = mTrackMCLabels[i].getTrackID(); - } - if (mTrackMCLabels[i].isFake()) { - continue; - } - const mcInfo_t& mc1 = GetMCTrack(mTrackMCLabels[i]); - const additionalMCParameters& mc2 = GetMCTrackObj(mMCParam, mTrackMCLabels[i]); - const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; - - if ((mMCTrackMin != -1 && mTrackMCLabels[i].getTrackID() < mMCTrackMin) || (mMCTrackMax != -1 && mTrackMCLabels[i].getTrackID() >= mMCTrackMax)) { - continue; - } - - if (!track.OK()) { - continue; - } - if (track.MergedLooper()) { - continue; - } - if (fabsf(mc2.eta) > ETA_MAX || mc2.pt < PT_MIN || mc2.pt > PT_MAX) { - continue; - } - if (mc1.charge == 0.f) { - continue; - } - if (mc1.pid < 0) { - continue; - } - if (mConfig.filterCharge && mc1.charge * mConfig.filterCharge < 0) { - continue; - } - if (mConfig.filterPID >= 0 && mc1.pid != mConfig.filterPID) { - continue; - } - if (mc2.nWeightCls < MIN_WEIGHT_CLS) { - continue; - } - if (mConfig.resPrimaries == 1 && (!mc1.prim || mc1.primDaughters)) { - continue; - } else if (mConfig.resPrimaries == 2 && (mc1.prim || mc1.primDaughters)) { - continue; - } - if (GetMCTrackObj(mTrackMCLabelsReverse, mTrackMCLabels[i]) != (int)i) { - continue; - } - float mclocal[4]; // Rotated x,y,Px,Py mc-coordinates - the MC data should be rotated since the track is propagated best along x - float c = std::cos(track.GetAlpha()); - float s = std::sin(track.GetAlpha()); - float x = mc1.x; - float y = mc1.y; - mclocal[0] = x * c + y * s; - mclocal[1] = -x * s + y * c; - float px = mc1.pX; - float py = mc1.pY; - mclocal[2] = px * c + py * s; - mclocal[3] = -px * s + py * c; + float mclocal[4]; // Rotated x,y,Px,Py mc-coordinates - the MC data should be rotated since the track is propagated best along x + float c = std::cos(track.GetAlpha()); + float s = std::sin(track.GetAlpha()); + float x = mc1.x; + float y = mc1.y; + mclocal[0] = x * c + y * s; + mclocal[1] = -x * s + y * c; + float px = mc1.pX; + float py = mc1.pY; + mclocal[2] = px * c + py * s; + mclocal[3] = -px * s + py * c; - GPUTPCGMTrackParam param = track.GetParam(); + GPUTPCGMTrackParam param = track.GetParam(); - if (mclocal[0] < TRACK_EXPECTED_REFERENCE_X - 3) { - continue; - } - if (mclocal[0] > param.GetX() + 20) { - continue; - } - if (param.GetX() > mConfig.maxResX) { - continue; - } + if (mclocal[0] < TRACK_EXPECTED_REFERENCE_X - 3) { + continue; + } + if (mclocal[0] > param.GetX() + 20) { + continue; + } + if (param.GetX() > mConfig.maxResX) { + continue; + } - float alpha = track.GetAlpha(); - prop.SetTrack(¶m, alpha); - bool inFlyDirection = 0; + float alpha = track.GetAlpha(); + prop.SetTrack(¶m, alpha); + bool inFlyDirection = 0; #ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (mTracking->GetParam().par.continuousMaxTimeBin ? 0 : ((param.Z() - mc1.z) * (param.Z() - mc1.z))) > (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X)) * (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X))) { + if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (mTracking->GetParam().par.continuousMaxTimeBin ? 0 : ((param.Z() - mc1.z) * (param.Z() - mc1.z))) > (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X)) * (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X))) { #else // Consider Z offset (pseudo-tf mc tracks have shifted z) - if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (param.Z() + param.TZOffset() - mc1.z) * (param.Z() + param.TZOffset() - mc1.z) > 25) { // TODO: fix TZOffset + if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (param.Z() + param.TZOffset() - mc1.z) * (param.Z() + param.TZOffset() - mc1.z) > 25) { // TODO: fix TZOffset #endif - continue; - } + continue; + } - if (prop.PropagateToXAlpha(mclocal[0], alpha, inFlyDirection)) { - continue; - } + if (prop.PropagateToXAlpha(mclocal[0], alpha, inFlyDirection)) { + continue; + } #ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || (mTracking->GetParam().par.continuousMaxTimeBin == 0 && fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f))) { // TODO: fix TZOffset here + if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || (mTracking->GetParam().par.continuousMaxTimeBin == 0 && fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f))) { // TODO: fix TZOffset here #else - if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f)) { // TODO: fix TZOffset here + if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f)) { // TODO: fix TZOffset here #endif - continue; - } + continue; + } - float charge = mc1.charge > 0 ? 1.f : -1.f; + float charge = mc1.charge > 0 ? 1.f : -1.f; - float deltaY = param.GetY() - mclocal[1]; - float deltaZ = param.GetZ() + param.TZOffset() - mc1.z; // TODO: fix TZOffset here - float deltaPhiNative = param.GetSinPhi() - mclocal[3] / mc2.pt; - float deltaPhi = std::asin(param.GetSinPhi()) - std::atan2(mclocal[3], mclocal[2]); - float deltaLambdaNative = param.GetDzDs() - mc1.pZ / mc2.pt; - float deltaLambda = std::atan(param.GetDzDs()) - std::atan2(mc1.pZ, mc2.pt); - float deltaPtNative = (param.GetQPt() - charge / mc2.pt) * charge; - float deltaPt = (fabsf(1.f / param.GetQPt()) - mc2.pt) / mc2.pt; + float deltaY = param.GetY() - mclocal[1]; + float deltaZ = param.GetZ() + param.TZOffset() - mc1.z; // TODO: fix TZOffset here + float deltaPhiNative = param.GetSinPhi() - mclocal[3] / mc2.pt; + float deltaPhi = std::asin(param.GetSinPhi()) - std::atan2(mclocal[3], mclocal[2]); + float deltaLambdaNative = param.GetDzDs() - mc1.pZ / mc2.pt; + float deltaLambda = std::atan(param.GetDzDs()) - std::atan2(mc1.pZ, mc2.pt); + float deltaPtNative = (param.GetQPt() - charge / mc2.pt) * charge; + float deltaPt = (fabsf(1.f / param.GetQPt()) - mc2.pt) / mc2.pt; - float paramval[5] = {mclocal[1], mc1.z, mc2.phi, mc2.eta, mc2.pt}; - float resval[5] = {deltaY, deltaZ, mConfig.nativeFitResolutions ? deltaPhiNative : deltaPhi, mConfig.nativeFitResolutions ? deltaLambdaNative : deltaLambda, mConfig.nativeFitResolutions ? deltaPtNative : deltaPt}; - float pullval[5] = {deltaY / std::sqrt(param.GetErr2Y()), deltaZ / std::sqrt(param.GetErr2Z()), deltaPhiNative / std::sqrt(param.GetErr2SinPhi()), deltaLambdaNative / std::sqrt(param.GetErr2DzDs()), deltaPtNative / std::sqrt(param.GetErr2QPt())}; + float paramval[5] = {mclocal[1], mc1.z, mc2.phi, mc2.eta, mc2.pt}; + float resval[5] = {deltaY, deltaZ, mConfig.nativeFitResolutions ? deltaPhiNative : deltaPhi, mConfig.nativeFitResolutions ? deltaLambdaNative : deltaLambda, mConfig.nativeFitResolutions ? deltaPtNative : deltaPt}; + float pullval[5] = {deltaY / std::sqrt(param.GetErr2Y()), deltaZ / std::sqrt(param.GetErr2Z()), deltaPhiNative / std::sqrt(param.GetErr2SinPhi()), deltaLambdaNative / std::sqrt(param.GetErr2DzDs()), deltaPtNative / std::sqrt(param.GetErr2QPt())}; - for (int j = 0; j < 5; j++) { - for (int k = 0; k < 5; k++) { - if (k != 3 && fabsf(mc2.eta) > ETA_MAX2) { - continue; - } - if (k < 4 && mc2.pt < 1.f / mConfig.qpt) { - continue; + for (int j = 0; j < 5; j++) { + for (int k = 0; k < 5; k++) { + if (k != 3 && fabsf(mc2.eta) > ETA_MAX2) { + continue; + } + if (k < 4 && mc2.pt < 1.f / mConfig.qpt) { + continue; + } + if (mQATasks & taskTrackingRes) { + mRes2[j][k]->Fill(resval[j], paramval[k]); + } + if (mQATasks & taskTrackingResPull) { + mPull2[j][k]->Fill(pullval[j], paramval[k]); + } } - mRes2[j][k]->Fill(resval[j], paramval[k]); - mPull2[j][k]->Fill(pullval[j], paramval[k]); } } - } - if (QA_TIMING) { - GPUInfo("QA Time: Fill resolution histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + if (QA_TIMING) { + GPUInfo("QA Time: Fill resolution histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + } } - // Fill cluster histograms - for (unsigned int iTrk = 0; iTrk < mTracking->mIOPtrs.nMergedTracks; iTrk++) { - const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[iTrk]; - if (!track.OK()) { - continue; - } - if (!mTrackMCLabels[iTrk].isValid()) { + if (mQATasks & taskClusterAttach) { + // Fill cluster histograms + for (unsigned int iTrk = 0; iTrk < mTracking->mIOPtrs.nMergedTracks; iTrk++) { + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[iTrk]; + if (!track.OK()) { + continue; + } + if (!mTrackMCLabels[iTrk].isValid()) { + for (unsigned int k = 0; k < track.NClusters(); k++) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + continue; + } + int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; + float totalWeight = 0.; + for (int j = 0; j < GetMCLabelNID(hitId); j++) { + if (GetMCLabelID(hitId, j) >= 0 && GetMCTrackObj(mMCParam, GetMCLabel(hitId, j)).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { + totalWeight += GetMCLabelWeight(hitId, j); + } + } + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[hitId]; + CHECK_CLUSTER_STATE_NOCOUNT(); + if (totalWeight > 0) { + float weight = 1.f / (totalWeight * (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached)); + for (int j = 0; j < GetMCLabelNID(hitId); j++) { + mcLabelI_t label = GetMCLabel(hitId, j); + if (!label.isFake() && GetMCTrackObj(mMCParam, label).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { + float pt = GetMCTrackObj(mMCParam, label).pt; + if (pt < PT_MIN_CLUST) { + pt = PT_MIN_CLUST; + } + mClusters[CL_fake]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); + mClusters[CL_att_adj]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); + if (GetMCTrackObj(mRecTracks, label)) { + mClusters[CL_tracks]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); + } + mClusters[CL_all]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); + if (protect || physics) { + mClusters[CL_prot]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); + } + if (physics) { + mClusters[CL_physics]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); + } + } + } + } else { + float weight = 1.f / (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached); + mClusters[CL_fake]->Fill(0.f, weight); + mClusters[CL_att_adj]->Fill(0.f, weight); + mClusters[CL_all]->Fill(0.f, weight); + mClusterCounts.nUnaccessible += weight; + if (protect || physics) { + mClusters[CL_prot]->Fill(0.f, weight); + } + if (physics) { + mClusters[CL_physics]->Fill(0.f, weight); + } + } + } + continue; + } + mcLabelI_t label = mTrackMCLabels[iTrk]; + if (mMCTrackMin != -1 && (label.getTrackID() < mMCTrackMin || label.getTrackID() >= mMCTrackMax)) { + continue; + } for (unsigned int k = 0; k < track.NClusters(); k++) { if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { continue; } int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; - float totalWeight = 0.; + float pt = GetMCTrackObj(mMCParam, label).pt; + if (pt < PT_MIN_CLUST) { + pt = PT_MIN_CLUST; + } + float weight = 1.f / (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached); + bool correct = false; for (int j = 0; j < GetMCLabelNID(hitId); j++) { - if (GetMCLabelID(hitId, j) >= 0 && GetMCTrackObj(mMCParam, GetMCLabel(hitId, j)).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { - totalWeight += GetMCLabelWeight(hitId, j); + if (label == GetMCLabel(hitId, j)) { + correct = true; + break; } } + if (correct) { + mClusters[CL_attached]->Fill(pt, weight); + mClusters[CL_tracks]->Fill(pt, weight); + } else { + mClusters[CL_fake]->Fill(pt, weight); + } + mClusters[CL_att_adj]->Fill(pt, weight); + mClusters[CL_all]->Fill(pt, weight); int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[hitId]; CHECK_CLUSTER_STATE_NOCOUNT(); - if (totalWeight > 0) { - float weight = 1.f / (totalWeight * (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached)); - for (int j = 0; j < GetMCLabelNID(hitId); j++) { - mcLabelI_t label = GetMCLabel(hitId, j); - if (!label.isFake() && GetMCTrackObj(mMCParam, label).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { - float pt = GetMCTrackObj(mMCParam, label).pt; - if (pt < PT_MIN_CLUST) { - pt = PT_MIN_CLUST; - } - mClusters[CL_fake]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); - mClusters[CL_att_adj]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); - if (GetMCTrackObj(mRecTracks, label)) { - mClusters[CL_tracks]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); - } - mClusters[CL_all]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); - if (protect || physics) { - mClusters[CL_prot]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); - } - if (physics) { - mClusters[CL_physics]->Fill(pt, GetMCLabelWeight(hitId, j) * weight); - } - } - } - } else { - float weight = 1.f / (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached); - mClusters[CL_fake]->Fill(0.f, weight); - mClusters[CL_att_adj]->Fill(0.f, weight); - mClusters[CL_all]->Fill(0.f, weight); - mClusterCounts.nUnaccessible += weight; - if (protect || physics) { - mClusters[CL_prot]->Fill(0.f, weight); - } - if (physics) { - mClusters[CL_physics]->Fill(0.f, weight); - } + if (protect || physics) { + mClusters[CL_prot]->Fill(pt, weight); + } + if (physics) { + mClusters[CL_physics]->Fill(pt, weight); } } - continue; - } - mcLabelI_t label = mTrackMCLabels[iTrk]; - if (mMCTrackMin != -1 && (label.getTrackID() < mMCTrackMin || label.getTrackID() >= mMCTrackMax)) { - continue; } - for (unsigned int k = 0; k < track.NClusters(); k++) { - if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + for (unsigned int i = 0; i < GetNMCLabels(); i++) { + if ((mMCTrackMin != -1 && GetMCLabelID(i, 0) < mMCTrackMin) || (mMCTrackMax != -1 && GetMCLabelID(i, 0) >= mMCTrackMax)) { continue; } - int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; - float pt = GetMCTrackObj(mMCParam, label).pt; - if (pt < PT_MIN_CLUST) { - pt = PT_MIN_CLUST; + if (mClusterParam[i].attached || mClusterParam[i].fakeAttached) { + continue; } - float weight = 1.f / (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached); - bool correct = false; - for (int j = 0; j < GetMCLabelNID(hitId); j++) { - if (label == GetMCLabel(hitId, j)) { - correct = true; - break; + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; + CHECK_CLUSTER_STATE_NOCOUNT(); + if (mClusterParam[i].adjacent) { + int label = mTracking->mIOPtrs.mergedTrackHitAttachment[i] & gputpcgmmergertypes::attachTrackMask; + if (!mTrackMCLabels[label].isValid()) { + float totalWeight = 0.; + for (int j = 0; j < GetMCLabelNID(i); j++) { + mcLabelI_t labelT = GetMCLabel(i, j); + if (!labelT.isFake() && GetMCTrackObj(mMCParam, labelT).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { + totalWeight += GetMCLabelWeight(i, j); + } + } + float weight = 1.f / totalWeight; + if (totalWeight > 0) { + for (int j = 0; j < GetMCLabelNID(i); j++) { + mcLabelI_t labelT = GetMCLabel(i, j); + if (!labelT.isFake() && GetMCTrackObj(mMCParam, labelT).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { + float pt = GetMCTrackObj(mMCParam, labelT).pt; + if (pt < PT_MIN_CLUST) { + pt = PT_MIN_CLUST; + } + if (GetMCTrackObj(mRecTracks, labelT)) { + mClusters[CL_tracks]->Fill(pt, GetMCLabelWeight(i, j) * weight); + } + mClusters[CL_att_adj]->Fill(pt, GetMCLabelWeight(i, j) * weight); + mClusters[CL_fakeAdj]->Fill(pt, GetMCLabelWeight(i, j) * weight); + mClusters[CL_all]->Fill(pt, GetMCLabelWeight(i, j) * weight); + if (protect || physics) { + mClusters[CL_prot]->Fill(pt, GetMCLabelWeight(i, j) * weight); + } + if (physics) { + mClusters[CL_physics]->Fill(pt, GetMCLabelWeight(i, j) * weight); + } + } + } + } else { + mClusters[CL_att_adj]->Fill(0.f, 1.f); + mClusters[CL_fakeAdj]->Fill(0.f, 1.f); + mClusters[CL_all]->Fill(0.f, 1.f); + mClusterCounts.nUnaccessible++; + if (protect || physics) { + mClusters[CL_prot]->Fill(0.f, 1.f); + } + if (physics) { + mClusters[CL_physics]->Fill(0.f, 1.f); + } + } + } else { + float pt = GetMCTrackObj(mMCParam, mTrackMCLabels[label]).pt; + if (pt < PT_MIN_CLUST) { + pt = PT_MIN_CLUST; + } + mClusters[CL_att_adj]->Fill(pt, 1.f); + mClusters[CL_tracks]->Fill(pt, 1.f); + mClusters[CL_all]->Fill(pt, 1.f); + if (protect || physics) { + mClusters[CL_prot]->Fill(pt, 1.f); + } + if (physics) { + mClusters[CL_physics]->Fill(pt, 1.f); + } } - } - if (correct) { - mClusters[CL_attached]->Fill(pt, weight); - mClusters[CL_tracks]->Fill(pt, weight); } else { - mClusters[CL_fake]->Fill(pt, weight); - } - mClusters[CL_att_adj]->Fill(pt, weight); - mClusters[CL_all]->Fill(pt, weight); - int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[hitId]; - CHECK_CLUSTER_STATE_NOCOUNT(); - if (protect || physics) { - mClusters[CL_prot]->Fill(pt, weight); - } - if (physics) { - mClusters[CL_physics]->Fill(pt, weight); - } - } - } - for (unsigned int i = 0; i < GetNMCLabels(); i++) { - if ((mMCTrackMin != -1 && GetMCLabelID(i, 0) < mMCTrackMin) || (mMCTrackMax != -1 && GetMCLabelID(i, 0) >= mMCTrackMax)) { - continue; - } - if (mClusterParam[i].attached || mClusterParam[i].fakeAttached) { - continue; - } - int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; - CHECK_CLUSTER_STATE_NOCOUNT(); - if (mClusterParam[i].adjacent) { - int label = mTracking->mIOPtrs.mergedTrackHitAttachment[i] & gputpcgmmergertypes::attachTrackMask; - if (!mTrackMCLabels[label].isValid()) { float totalWeight = 0.; for (int j = 0; j < GetMCLabelNID(i); j++) { mcLabelI_t labelT = GetMCLabel(i, j); @@ -1269,32 +1352,40 @@ void GPUQA::RunQA(bool matchOnly) totalWeight += GetMCLabelWeight(i, j); } } - float weight = 1.f / totalWeight; if (totalWeight > 0) { for (int j = 0; j < GetMCLabelNID(i); j++) { - mcLabelI_t labelT = GetMCLabel(i, j); - if (!labelT.isFake() && GetMCTrackObj(mMCParam, labelT).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { - float pt = GetMCTrackObj(mMCParam, labelT).pt; + mcLabelI_t label = GetMCLabel(i, j); + if (!label.isFake() && GetMCTrackObj(mMCParam, label).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { + float pt = GetMCTrackObj(mMCParam, label).pt; if (pt < PT_MIN_CLUST) { pt = PT_MIN_CLUST; } - if (GetMCTrackObj(mRecTracks, labelT)) { - mClusters[CL_tracks]->Fill(pt, GetMCLabelWeight(i, j) * weight); + float weight = GetMCLabelWeight(i, j) / totalWeight; + if (mClusterParam[i].fakeAdjacent) { + mClusters[CL_fakeAdj]->Fill(pt, weight); + } + if (mClusterParam[i].fakeAdjacent) { + mClusters[CL_att_adj]->Fill(pt, weight); + } + if (GetMCTrackObj(mRecTracks, label)) { + mClusters[CL_tracks]->Fill(pt, weight); } - mClusters[CL_att_adj]->Fill(pt, GetMCLabelWeight(i, j) * weight); - mClusters[CL_fakeAdj]->Fill(pt, GetMCLabelWeight(i, j) * weight); - mClusters[CL_all]->Fill(pt, GetMCLabelWeight(i, j) * weight); + mClusters[CL_all]->Fill(pt, weight); if (protect || physics) { - mClusters[CL_prot]->Fill(pt, GetMCLabelWeight(i, j) * weight); + mClusters[CL_prot]->Fill(pt, weight); } if (physics) { - mClusters[CL_physics]->Fill(pt, GetMCLabelWeight(i, j) * weight); + mClusters[CL_physics]->Fill(pt, weight); } } } } else { - mClusters[CL_att_adj]->Fill(0.f, 1.f); - mClusters[CL_fakeAdj]->Fill(0.f, 1.f); + if (mClusterParam[i].fakeAdjacent) { + mClusters[CL_fakeAdj]->Fill(0.f, 1.f); + } + if (mClusterParam[i].fakeAdjacent) { + mClusters[CL_att_adj]->Fill(0.f, 1.f); + } mClusters[CL_all]->Fill(0.f, 1.f); mClusterCounts.nUnaccessible++; if (protect || physics) { @@ -1304,149 +1395,88 @@ void GPUQA::RunQA(bool matchOnly) mClusters[CL_physics]->Fill(0.f, 1.f); } } - } else { - float pt = GetMCTrackObj(mMCParam, mTrackMCLabels[label]).pt; - if (pt < PT_MIN_CLUST) { - pt = PT_MIN_CLUST; - } - mClusters[CL_att_adj]->Fill(pt, 1.f); - mClusters[CL_tracks]->Fill(pt, 1.f); - mClusters[CL_all]->Fill(pt, 1.f); - if (protect || physics) { - mClusters[CL_prot]->Fill(pt, 1.f); - } - if (physics) { - mClusters[CL_physics]->Fill(pt, 1.f); - } - } - } else { - float totalWeight = 0.; - for (int j = 0; j < GetMCLabelNID(i); j++) { - mcLabelI_t labelT = GetMCLabel(i, j); - if (!labelT.isFake() && GetMCTrackObj(mMCParam, labelT).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { - totalWeight += GetMCLabelWeight(i, j); - } - } - if (totalWeight > 0) { - for (int j = 0; j < GetMCLabelNID(i); j++) { - mcLabelI_t label = GetMCLabel(i, j); - if (!label.isFake() && GetMCTrackObj(mMCParam, label).pt > GPUCA_MIN_TRACK_PT_DEFAULT) { - float pt = GetMCTrackObj(mMCParam, label).pt; - if (pt < PT_MIN_CLUST) { - pt = PT_MIN_CLUST; - } - float weight = GetMCLabelWeight(i, j) / totalWeight; - if (mClusterParam[i].fakeAdjacent) { - mClusters[CL_fakeAdj]->Fill(pt, weight); - } - if (mClusterParam[i].fakeAdjacent) { - mClusters[CL_att_adj]->Fill(pt, weight); - } - if (GetMCTrackObj(mRecTracks, label)) { - mClusters[CL_tracks]->Fill(pt, weight); - } - mClusters[CL_all]->Fill(pt, weight); - if (protect || physics) { - mClusters[CL_prot]->Fill(pt, weight); - } - if (physics) { - mClusters[CL_physics]->Fill(pt, weight); - } - } - } - } else { - if (mClusterParam[i].fakeAdjacent) { - mClusters[CL_fakeAdj]->Fill(0.f, 1.f); - } - if (mClusterParam[i].fakeAdjacent) { - mClusters[CL_att_adj]->Fill(0.f, 1.f); - } - mClusters[CL_all]->Fill(0.f, 1.f); - mClusterCounts.nUnaccessible++; - if (protect || physics) { - mClusters[CL_prot]->Fill(0.f, 1.f); - } - if (physics) { - mClusters[CL_physics]->Fill(0.f, 1.f); - } } } - } - if (QA_TIMING) { - GPUInfo("QA Time: Fill cluster histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + if (QA_TIMING) { + GPUInfo("QA Time: Fill cluster histograms:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); + } } } else if (!mConfig.inputHistogramsOnly) { GPUWarning("No MC information available, only running partial TPC QA!"); } - // Fill track statistic histograms - for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { - const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; - if (!track.OK()) { - continue; + if (mQATasks & taskTrackStatistics) { + // Fill track statistic histograms + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; + if (!track.OK()) { + continue; + } + mTracks->Fill(1.f / fabsf(track.GetParam().GetQPt())); + mNCl->Fill(track.NClustersFitted()); } - mTracks->Fill(1.f / fabsf(track.GetParam().GetQPt())); - mNCl->Fill(track.NClustersFitted()); } - unsigned int nCl = mTracking->mIOPtrs.clustersNative ? mTracking->mIOPtrs.clustersNative->nClustersTotal : mTracking->GetTPCMerger().NMaxClusters(); - for (unsigned int i = 0; i < nCl; i++) { - int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; - CHECK_CLUSTER_STATE(); + if (mQATasks & taskClusterCounts) { + unsigned int nCl = mTracking->mIOPtrs.clustersNative ? mTracking->mIOPtrs.clustersNative->nClustersTotal : mTracking->GetTPCMerger().NMaxClusters(); + for (unsigned int i = 0; i < nCl; i++) { + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; + CHECK_CLUSTER_STATE(); - if (mcAvail) { - float totalWeight = 0, weight400 = 0, weight40 = 0; - for (int j = 0; j < GetMCLabelNID(i); j++) { - const auto& label = GetMCLabel(i, j); - if (GetMCLabelID(label) >= 0) { - totalWeight += GetMCLabelWeight(label); - if (GetMCTrackObj(mMCParam, label).pt >= 0.4) { - weight400 += GetMCLabelWeight(label); - } - if (GetMCTrackObj(mMCParam, label).pt <= 0.04) { - weight40 += GetMCLabelWeight(label); + if (mcAvail) { + float totalWeight = 0, weight400 = 0, weight40 = 0; + for (int j = 0; j < GetMCLabelNID(i); j++) { + const auto& label = GetMCLabel(i, j); + if (GetMCLabelID(label) >= 0) { + totalWeight += GetMCLabelWeight(label); + if (GetMCTrackObj(mMCParam, label).pt >= 0.4) { + weight400 += GetMCLabelWeight(label); + } + if (GetMCTrackObj(mMCParam, label).pt <= 0.04) { + weight40 += GetMCLabelWeight(label); + } } } - } - if (totalWeight > 0 && 10.f * weight400 >= totalWeight) { - if (!unattached && !protect && !physics) { - mClusterCounts.nFakeRemove400++; - int totalFake = weight400 < 0.9f * totalWeight; - if (totalFake) { - mClusterCounts.nFullFakeRemove400++; + if (totalWeight > 0 && 10.f * weight400 >= totalWeight) { + if (!unattached && !protect && !physics) { + mClusterCounts.nFakeRemove400++; + int totalFake = weight400 < 0.9f * totalWeight; + if (totalFake) { + mClusterCounts.nFullFakeRemove400++; + } + /*printf("Fake removal (%d): Hit %7d, attached %d lowPt %d looper %d tube200 %d highIncl %d tube %d bad %d recPt %7.2f recLabel %6d", totalFake, i, (int) (mClusterParam[i].attached || mClusterParam[i].fakeAttached), + (int) lowPt, (int) ((attach & gputpcgmmergertypes::attachGoodLeg) == 0), (int) ((attach & gputpcgmmergertypes::attachTube) && mev200), + (int) ((attach & gputpcgmmergertypes::attachHighIncl) != 0), (int) ((attach & gputpcgmmergertypes::attachTube) != 0), (int) ((attach & gputpcgmmergertypes::attachGood) == 0), + fabsf(qpt) > 0 ? 1.f / qpt : 0.f, id); + for (int j = 0;j < GetMCLabelNID(i);j++) + { + //if (GetMCLabelID(i, j) < 0) break; + printf(" - label%d %6d weight %5d", j, GetMCLabelID(i, j), (int) GetMCLabelWeight(i, j)); + if (GetMCLabelID(i, j) >= 0) printf(" - pt %7.2f", mMCParam[GetMCLabelID(i, j)].pt); + else printf(" "); + } + printf("\n");*/ } - /*printf("Fake removal (%d): Hit %7d, attached %d lowPt %d looper %d tube200 %d highIncl %d tube %d bad %d recPt %7.2f recLabel %6d", totalFake, i, (int) (mClusterParam[i].attached || mClusterParam[i].fakeAttached), - (int) lowPt, (int) ((attach & gputpcgmmergertypes::attachGoodLeg) == 0), (int) ((attach & gputpcgmmergertypes::attachTube) && mev200), - (int) ((attach & gputpcgmmergertypes::attachHighIncl) != 0), (int) ((attach & gputpcgmmergertypes::attachTube) != 0), (int) ((attach & gputpcgmmergertypes::attachGood) == 0), - fabsf(qpt) > 0 ? 1.f / qpt : 0.f, id); - for (int j = 0;j < GetMCLabelNID(i);j++) - { - //if (GetMCLabelID(i, j) < 0) break; - printf(" - label%d %6d weight %5d", j, GetMCLabelID(i, j), (int) GetMCLabelWeight(i, j)); - if (GetMCLabelID(i, j) >= 0) printf(" - pt %7.2f", mMCParam[GetMCLabelID(i, j)].pt); - else printf(" "); + mClusterCounts.nAbove400++; + } + if (totalWeight > 0 && weight40 >= 0.9 * totalWeight) { + mClusterCounts.nBelow40++; + if (protect || physics) { + mClusterCounts.nFakeProtect40++; } - printf("\n");*/ } - mClusterCounts.nAbove400++; - } - if (totalWeight > 0 && weight40 >= 0.9 * totalWeight) { - mClusterCounts.nBelow40++; - if (protect || physics) { - mClusterCounts.nFakeProtect40++; + } else { + mClusterCounts.nTotal++; + if (physics) { + mClusterCounts.nPhysics++; + } + if (physics || protect) { + mClusterCounts.nProt++; + } + if (unattached) { + mClusterCounts.nUnattached++; } - } - } else { - mClusterCounts.nTotal++; - if (physics) { - mClusterCounts.nPhysics++; - } - if (physics || protect) { - mClusterCounts.nProt++; - } - if (unattached) { - mClusterCounts.nUnattached++; } } } @@ -1632,7 +1662,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) tout = std::make_unique<TFile>(mConfig.output.c_str(), "RECREATE"); } - if (!mRunForQC || mConfig.shipToQCAsCanvas) { + if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) { float legendSpacingString = 0.025; for (int i = 0; i < ConfigNumInputs; i++) { GetName(fname, i); @@ -1642,122 +1672,130 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } // Create Canvas / Pads for Efficiency Histograms - for (int ii = 0; ii < 6; ii++) { - int i = ii == 5 ? 4 : ii; - sprintf(fname, "eff_vs_%s_layout", VSPARAMETER_NAMES[ii]); - sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); - mCEff[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); - mCEff[ii]->cd(); - float dy = 1. / 2.; - mPEff[ii][0] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); - mPEff[ii][0]->Draw(); - mPEff[ii][0]->SetRightMargin(0.04); - mPEff[ii][1] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); - mPEff[ii][1]->Draw(); - mPEff[ii][1]->SetRightMargin(0.04); - mPEff[ii][2] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); - mPEff[ii][2]->Draw(); - mPEff[ii][2]->SetRightMargin(0.04); - mPEff[ii][3] = createGarbageCollected<TPad>("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); - mPEff[ii][3]->Draw(); - mPEff[ii][3]->SetRightMargin(0.04); - mLEff[ii] = createGarbageCollected<TLegend>(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); - SetLegend(mLEff[ii]); + if (mQATasks & taskTrackingEff) { + for (int ii = 0; ii < 6; ii++) { + int i = ii == 5 ? 4 : ii; + sprintf(fname, "eff_vs_%s_layout", VSPARAMETER_NAMES[ii]); + sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); + mCEff[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCEff[ii]->cd(); + float dy = 1. / 2.; + mPEff[ii][0] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPEff[ii][0]->Draw(); + mPEff[ii][0]->SetRightMargin(0.04); + mPEff[ii][1] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPEff[ii][1]->Draw(); + mPEff[ii][1]->SetRightMargin(0.04); + mPEff[ii][2] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); + mPEff[ii][2]->Draw(); + mPEff[ii][2]->SetRightMargin(0.04); + mPEff[ii][3] = createGarbageCollected<TPad>("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); + mPEff[ii][3]->Draw(); + mPEff[ii][3]->SetRightMargin(0.04); + mLEff[ii] = createGarbageCollected<TLegend>(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); + SetLegend(mLEff[ii]); + } } // Create Canvas / Pads for Resolution Histograms - for (int ii = 0; ii < 7; ii++) { - int i = ii == 5 ? 4 : ii; - if (ii == 6) { - sprintf(fname, "res_integral_layout"); - sprintf(name, "Integral Resolution"); - } else { - sprintf(fname, "res_vs_%s_layout", VSPARAMETER_NAMES[ii]); - sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); - } - mCRes[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); - mCRes[ii]->cd(); - gStyle->SetOptFit(1); - - float dy = 1. / 2.; - mPRes[ii][3] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); - mPRes[ii][3]->Draw(); - mPRes[ii][3]->SetRightMargin(0.04); - mPRes[ii][4] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); - mPRes[ii][4]->Draw(); - mPRes[ii][4]->SetRightMargin(0.04); - mPRes[ii][0] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); - mPRes[ii][0]->Draw(); - mPRes[ii][0]->SetRightMargin(0.04); - mPRes[ii][0]->SetLeftMargin(0.15); - mPRes[ii][1] = createGarbageCollected<TPad>("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); - mPRes[ii][1]->Draw(); - mPRes[ii][1]->SetRightMargin(0.04); - mPRes[ii][1]->SetLeftMargin(0.135); - mPRes[ii][2] = createGarbageCollected<TPad>("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); - mPRes[ii][2]->Draw(); - mPRes[ii][2]->SetRightMargin(0.06); - mPRes[ii][2]->SetLeftMargin(0.135); - if (ii < 6) { - mLRes[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); - SetLegend(mLRes[ii]); + if (mQATasks & taskTrackingRes) { + for (int ii = 0; ii < 7; ii++) { + int i = ii == 5 ? 4 : ii; + if (ii == 6) { + sprintf(fname, "res_integral_layout"); + sprintf(name, "Integral Resolution"); + } else { + sprintf(fname, "res_vs_%s_layout", VSPARAMETER_NAMES[ii]); + sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); + } + mCRes[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCRes[ii]->cd(); + gStyle->SetOptFit(1); + + float dy = 1. / 2.; + mPRes[ii][3] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPRes[ii][3]->Draw(); + mPRes[ii][3]->SetRightMargin(0.04); + mPRes[ii][4] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPRes[ii][4]->Draw(); + mPRes[ii][4]->SetRightMargin(0.04); + mPRes[ii][0] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPRes[ii][0]->Draw(); + mPRes[ii][0]->SetRightMargin(0.04); + mPRes[ii][0]->SetLeftMargin(0.15); + mPRes[ii][1] = createGarbageCollected<TPad>("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPRes[ii][1]->Draw(); + mPRes[ii][1]->SetRightMargin(0.04); + mPRes[ii][1]->SetLeftMargin(0.135); + mPRes[ii][2] = createGarbageCollected<TPad>("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPRes[ii][2]->Draw(); + mPRes[ii][2]->SetRightMargin(0.06); + mPRes[ii][2]->SetLeftMargin(0.135); + if (ii < 6) { + mLRes[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + SetLegend(mLRes[ii]); + } } } // Create Canvas / Pads for Pull Histograms - for (int ii = 0; ii < 7; ii++) { - int i = ii == 5 ? 4 : ii; + if (mQATasks & taskTrackingResPull) { + for (int ii = 0; ii < 7; ii++) { + int i = ii == 5 ? 4 : ii; - if (ii == 6) { - sprintf(fname, "pull_integral_layout"); - sprintf(name, "Integral Pull"); - } else { - sprintf(fname, "pull_vs_%s_layout", VSPARAMETER_NAMES[ii]); - sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); - } - mCPull[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); - mCPull[ii]->cd(); - gStyle->SetOptFit(1); - - float dy = 1. / 2.; - mPPull[ii][3] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); - mPPull[ii][3]->Draw(); - mPPull[ii][3]->SetRightMargin(0.04); - mPPull[ii][4] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); - mPPull[ii][4]->Draw(); - mPPull[ii][4]->SetRightMargin(0.04); - mPPull[ii][0] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); - mPPull[ii][0]->Draw(); - mPPull[ii][0]->SetRightMargin(0.04); - mPPull[ii][0]->SetLeftMargin(0.15); - mPPull[ii][1] = createGarbageCollected<TPad>("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); - mPPull[ii][1]->Draw(); - mPPull[ii][1]->SetRightMargin(0.04); - mPPull[ii][1]->SetLeftMargin(0.135); - mPPull[ii][2] = createGarbageCollected<TPad>("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); - mPPull[ii][2]->Draw(); - mPPull[ii][2]->SetRightMargin(0.06); - mPPull[ii][2]->SetLeftMargin(0.135); - if (ii < 6) { - mLPull[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); - SetLegend(mLPull[ii]); + if (ii == 6) { + sprintf(fname, "pull_integral_layout"); + sprintf(name, "Integral Pull"); + } else { + sprintf(fname, "pull_vs_%s_layout", VSPARAMETER_NAMES[ii]); + sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); + } + mCPull[ii] = createGarbageCollected<TCanvas>(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCPull[ii]->cd(); + gStyle->SetOptFit(1); + + float dy = 1. / 2.; + mPPull[ii][3] = createGarbageCollected<TPad>("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPPull[ii][3]->Draw(); + mPPull[ii][3]->SetRightMargin(0.04); + mPPull[ii][4] = createGarbageCollected<TPad>("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPPull[ii][4]->Draw(); + mPPull[ii][4]->SetRightMargin(0.04); + mPPull[ii][0] = createGarbageCollected<TPad>("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPPull[ii][0]->Draw(); + mPPull[ii][0]->SetRightMargin(0.04); + mPPull[ii][0]->SetLeftMargin(0.15); + mPPull[ii][1] = createGarbageCollected<TPad>("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPPull[ii][1]->Draw(); + mPPull[ii][1]->SetRightMargin(0.04); + mPPull[ii][1]->SetLeftMargin(0.135); + mPPull[ii][2] = createGarbageCollected<TPad>("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPPull[ii][2]->Draw(); + mPPull[ii][2]->SetRightMargin(0.06); + mPPull[ii][2]->SetLeftMargin(0.135); + if (ii < 6) { + mLPull[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + SetLegend(mLPull[ii]); + } } } // Create Canvas for Cluster Histos - for (int i = 0; i < 3; i++) { - sprintf(fname, "clusters_%s_layout", CLUSTER_TYPES[i]); - mCClust[i] = createGarbageCollected<TCanvas>(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); - mCClust[i]->cd(); - mPClust[i] = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); - mPClust[i]->Draw(); - float y1 = i != 1 ? 0.77 : 0.27, y2 = i != 1 ? 0.9 : 0.42; - mLClust[i] = createGarbageCollected<TLegend>(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); - SetLegend(mLClust[i]); + if (mQATasks & taskClusterAttach) { + for (int i = 0; i < 3; i++) { + sprintf(fname, "clusters_%s_layout", CLUSTER_TYPES[i]); + mCClust[i] = createGarbageCollected<TCanvas>(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); + mCClust[i]->cd(); + mPClust[i] = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); + mPClust[i]->Draw(); + float y1 = i != 1 ? 0.77 : 0.27, y2 = i != 1 ? 0.9 : 0.42; + mLClust[i] = createGarbageCollected<TLegend>(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); + SetLegend(mLClust[i]); + } } // Create Canvas for track statistic histos - if (!mRunForQC) { + if (mQATasks & taskTrackStatistics) { mCTracks = createGarbageCollected<TCanvas>("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); mCTracks->cd(); mPTracks = createGarbageCollected<TPad>("p0", "", 0.0, 0.0, 1.0, 1.0); @@ -1774,407 +1812,417 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } - if (!mRunForQC && !mConfig.inputHistogramsOnly) { + if (mConfig.enableLocalOutput && !mConfig.inputHistogramsOnly) { GPUInfo("QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int)mEff[3][1][0][0][0]->GetEntries(), (int)mEff[3][1][0][3][0]->GetEntries(), (int)mEff[3][1][0][4][0]->GetEntries(), mEff[0][0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0][0]->GetSumOfWeights()), (int)mEff[3][1][1][0][0]->GetEntries(), (int)mEff[3][1][1][3][0]->GetEntries(), (int)mEff[3][1][1][4][0]->GetEntries(), mEff[0][0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0][0]->GetSumOfWeights()), mEff[0][1][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0][0]->GetSumOfWeights()), (int)mRes2[0][0]->GetEntries(), (int)mRes2[0][3]->GetEntries(), (int)mRes2[0][4]->GetEntries()); } - int flagShowVsPtLog = (mRunForQC && !mConfig.shipToQCAsCanvas) ? 0 : 1; + int flagShowVsPtLog = (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) ? 1 : 0; - // Process / Draw Efficiency Histograms - for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { - int i = ii == 5 ? 4 : ii; - for (int k = 0; k < ConfigNumInputs; k++) { - for (int j = 0; j < 4; j++) { - if (!mRunForQC || mConfig.shipToQCAsCanvas) { - mPEff[ii][j]->cd(); - } - for (int l = 0; l < 3; l++) { - if (k == 0 && mConfig.inputHistogramsOnly == 0 && ii != 5) { - if (l == 0) { - // Divide eff, compute all for fake/clone - mEff[0][j / 2][j % 2][i][1]->Divide(mEff[l][j / 2][j % 2][i][0], mEff[3][j / 2][j % 2][i][0], 1, 1, "B"); - mEff[3][j / 2][j % 2][i][1]->Reset(); // Sum up rec + clone + fake for clone/fake rate - mEff[3][j / 2][j % 2][i][1]->Add(mEff[0][j / 2][j % 2][i][0]); - mEff[3][j / 2][j % 2][i][1]->Add(mEff[1][j / 2][j % 2][i][0]); - mEff[3][j / 2][j % 2][i][1]->Add(mEff[2][j / 2][j % 2][i][0]); - } else { - // Divide fake/clone - mEff[l][j / 2][j % 2][i][1]->Divide(mEff[l][j / 2][j % 2][i][0], mEff[3][j / 2][j % 2][i][1], 1, 1, "B"); - } + if (mQATasks & taskTrackingEff) { + // Process / Draw Efficiency Histograms + for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { + int i = ii == 5 ? 4 : ii; + for (int k = 0; k < ConfigNumInputs; k++) { + for (int j = 0; j < 4; j++) { + if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) { + mPEff[ii][j]->cd(); } + for (int l = 0; l < 3; l++) { + if (k == 0 && mConfig.inputHistogramsOnly == 0 && ii != 5) { + if (l == 0) { + // Divide eff, compute all for fake/clone + mEff[0][j / 2][j % 2][i][1]->Divide(mEff[l][j / 2][j % 2][i][0], mEff[3][j / 2][j % 2][i][0], 1, 1, "B"); + mEff[3][j / 2][j % 2][i][1]->Reset(); // Sum up rec + clone + fake for clone/fake rate + mEff[3][j / 2][j % 2][i][1]->Add(mEff[0][j / 2][j % 2][i][0]); + mEff[3][j / 2][j % 2][i][1]->Add(mEff[1][j / 2][j % 2][i][0]); + mEff[3][j / 2][j % 2][i][1]->Add(mEff[2][j / 2][j % 2][i][0]); + } else { + // Divide fake/clone + mEff[l][j / 2][j % 2][i][1]->Divide(mEff[l][j / 2][j % 2][i][0], mEff[3][j / 2][j % 2][i][1], 1, 1, "B"); + } + } - TH1F* e = mEff[l][j / 2][j % 2][i][1]; + TH1F* e = mEff[l][j / 2][j % 2][i][1]; - e->SetStats(kFALSE); - e->SetMaximum(1.02); - e->SetMinimum(-0.02); - if (!mConfig.inputHistogramsOnly && k == 0) { - if (tout) { - mEff[l][j / 2][j % 2][i][0]->Write(); - e->Write(); - if (l == 2) { - mEff[3][j / 2][j % 2][i][0]->Write(); // Store also all histogram! + e->SetStats(kFALSE); + e->SetMaximum(1.02); + e->SetMinimum(-0.02); + if (!mConfig.inputHistogramsOnly && k == 0) { + if (tout) { + mEff[l][j / 2][j % 2][i][0]->Write(); + e->Write(); + if (l == 2) { + mEff[3][j / 2][j % 2][i][0]->Write(); // Store also all histogram! + } } + } else if (GetHist(e, tin, k, nNewInput) == nullptr) { + continue; } - } else if (GetHist(e, tin, k, nNewInput) == nullptr) { - continue; - } - e->SetTitle(EFFICIENCY_TITLES[j]); - e->GetYaxis()->SetTitle("(Efficiency)"); - e->GetXaxis()->SetTitle(XAXIS_TITLES[i]); + e->SetTitle(EFFICIENCY_TITLES[j]); + e->GetYaxis()->SetTitle("(Efficiency)"); + e->GetXaxis()->SetTitle(XAXIS_TITLES[i]); - e->SetLineWidth(1); - e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); - SetAxisSize(e); - if (qcout && !mConfig.shipToQCAsCanvas) { - qcout->Add(e); + e->SetLineWidth(1); + e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); + SetAxisSize(e); + if (qcout && !mConfig.shipToQCAsCanvas) { + qcout->Add(e); + } + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { + continue; + } + e->SetMarkerColor(kBlack); + e->SetLineColor(colorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); + e->Draw(k || l ? "same" : ""); + if (j == 0) { + GetName(fname, k); + sprintf(name, "%s%s", fname, EFF_NAMES[l]); + mLEff[ii]->AddEntry(e, name, "l"); + } + if (ii == 5) { + mPEff[ii][j]->SetLogx(); + } } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { continue; } - e->SetMarkerColor(kBlack); - e->SetLineColor(colorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); - e->Draw(k || l ? "same" : ""); - if (j == 0) { - GetName(fname, k); - sprintf(name, "%s%s", fname, EFF_NAMES[l]); - mLEff[ii]->AddEntry(e, name, "l"); - } - if (ii == 5) { - mPEff[ii][j]->SetLogx(); - } + mCEff[ii]->cd(); + ChangePadTitleSize(mPEff[ii][j], 0.056); } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { - continue; - } - mCEff[ii]->cd(); - ChangePadTitleSize(mPEff[ii][j], 0.056); } - } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { - continue; - } + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { + continue; + } - mLEff[ii]->Draw(); + mLEff[ii]->Draw(); - if (mRunForQC) { if (qcout) { qcout->Add(mCEff[ii]); } - continue; - } - doPerfFigure(0.2, 0.295, 0.025); - mCEff[ii]->Print(Form("plots/eff_vs_%s.pdf", VSPARAMETER_NAMES[ii])); - if (mConfig.writeRootFiles) { - mCEff[ii]->Print(Form("plots/eff_vs_%s.root", VSPARAMETER_NAMES[ii])); + if (!mConfig.enableLocalOutput) { + continue; + } + doPerfFigure(0.2, 0.295, 0.025); + mCEff[ii]->Print(Form("plots/eff_vs_%s.pdf", VSPARAMETER_NAMES[ii])); + if (mConfig.writeRootFiles) { + mCEff[ii]->Print(Form("plots/eff_vs_%s.root", VSPARAMETER_NAMES[ii])); + } } } - // Process / Draw Resolution Histograms - TH1D *resIntegral[5] = {}, *pullIntegral[5] = {}; - TCanvas* cfit = nullptr; - std::unique_ptr<TF1> customGaus = std::make_unique<TF1>("G", "[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))"); - for (int p = 0; p < 2; p++) { - for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { - TCanvas* can = p ? mCPull[ii] : mCRes[ii]; - TLegend* leg = p ? mLPull[ii] : mLRes[ii]; - int i = ii == 5 ? 4 : ii; - for (int j = 0; j < 5; j++) { - TH2F* src = p ? mPull2[j][i] : mRes2[j][i]; - TH1F** dst = p ? mPull[j][i] : mRes[j][i]; - TH1D*& dstIntegral = p ? pullIntegral[j] : resIntegral[j]; - TPad* pad = p ? mPPull[ii][j] : mPRes[ii][j]; - - if (!mConfig.inputHistogramsOnly && ii != 5) { - if (cfit == nullptr) { - cfit = createGarbageCollected<TCanvas>(); - } - cfit->cd(); - - TAxis* axis = src->GetYaxis(); - int nBins = axis->GetNbins(); - int integ = 1; - for (int bin = 1; bin <= nBins; bin++) { - int bin0 = std::max(bin - integ, 0); - int bin1 = std::min(bin + integ, nBins); - std::unique_ptr<TH1D> proj{src->ProjectionX("proj", bin0, bin1)}; - proj->ClearUnderflowAndOverflow(); - if (proj->GetEntries()) { - unsigned int rebin = 1; - while (proj->GetMaximum() < 50 && rebin < sizeof(RES_AXIS_BINS) / sizeof(RES_AXIS_BINS[0])) { - proj->Rebin(RES_AXIS_BINS[rebin - 1] / RES_AXIS_BINS[rebin]); - rebin++; - } - - if (proj->GetEntries() < 20 || proj->GetRMS() < 0.00001) { - dst[0]->SetBinContent(bin, proj->GetRMS()); - dst[0]->SetBinError(bin, std::sqrt(proj->GetRMS())); - dst[1]->SetBinContent(bin, proj->GetMean()); - dst[1]->SetBinError(bin, std::sqrt(proj->GetRMS())); - } else { - proj->GetXaxis()->SetRangeUser(proj->GetMean() - 6. * proj->GetRMS(), proj->GetMean() + 6. * proj->GetRMS()); - proj->GetXaxis()->SetRangeUser(proj->GetMean() - 3. * proj->GetRMS(), proj->GetMean() + 3. * proj->GetRMS()); - bool forceLogLike = proj->GetMaximum() < 20; - for (int k = forceLogLike ? 2 : 0; k < 3; k++) { - proj->Fit("gaus", forceLogLike || k == 2 ? "sQl" : k ? "sQww" : "sQ"); - TF1* fitFunc = proj->GetFunction("gaus"); - - if (k && !forceLogLike) { - customGaus->SetParameters(fitFunc->GetParameter(0), fitFunc->GetParameter(1), fitFunc->GetParameter(2)); - proj->Fit(customGaus.get(), "sQ"); - fitFunc = customGaus.get(); - } + if (mQATasks & (taskTrackingRes | taskTrackingResPull)) { + // Process / Draw Resolution Histograms + TH1D *resIntegral[5] = {}, *pullIntegral[5] = {}; + TCanvas* cfit = nullptr; + std::unique_ptr<TF1> customGaus = std::make_unique<TF1>("G", "[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))"); + for (int p = 0; p < 2; p++) { + if ((p == 0 && (mQATasks & taskTrackingRes) == 0) || (p == 1 && (mQATasks & taskTrackingResPull) == 0)) { + continue; + } + for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { + TCanvas* can = p ? mCPull[ii] : mCRes[ii]; + TLegend* leg = p ? mLPull[ii] : mLRes[ii]; + int i = ii == 5 ? 4 : ii; + for (int j = 0; j < 5; j++) { + TH2F* src = p ? mPull2[j][i] : mRes2[j][i]; + TH1F** dst = p ? mPull[j][i] : mRes[j][i]; + TH1D*& dstIntegral = p ? pullIntegral[j] : resIntegral[j]; + TPad* pad = p ? mPPull[ii][j] : mPRes[ii][j]; + + if (!mConfig.inputHistogramsOnly && ii != 5) { + if (cfit == nullptr) { + cfit = createGarbageCollected<TCanvas>(); + } + cfit->cd(); + + TAxis* axis = src->GetYaxis(); + int nBins = axis->GetNbins(); + int integ = 1; + for (int bin = 1; bin <= nBins; bin++) { + int bin0 = std::max(bin - integ, 0); + int bin1 = std::min(bin + integ, nBins); + std::unique_ptr<TH1D> proj{src->ProjectionX("proj", bin0, bin1)}; + proj->ClearUnderflowAndOverflow(); + if (proj->GetEntries()) { + unsigned int rebin = 1; + while (proj->GetMaximum() < 50 && rebin < sizeof(RES_AXIS_BINS) / sizeof(RES_AXIS_BINS[0])) { + proj->Rebin(RES_AXIS_BINS[rebin - 1] / RES_AXIS_BINS[rebin]); + rebin++; + } - const float sigma = fabs(fitFunc->GetParameter(2)); - dst[0]->SetBinContent(bin, sigma); - dst[1]->SetBinContent(bin, fitFunc->GetParameter(1)); - dst[0]->SetBinError(bin, fitFunc->GetParError(2)); - dst[1]->SetBinError(bin, fitFunc->GetParError(1)); - - const bool fail1 = sigma <= 0.f; - const bool fail2 = fabs(proj->GetMean() - dst[1]->GetBinContent(bin)) > std::min<float>(p ? PULL_AXIS : mConfig.nativeFitResolutions ? RES_AXES_NATIVE[j] : RES_AXES[j], 3.f * proj->GetRMS()); - const bool fail3 = dst[0]->GetBinContent(bin) > 3.f * proj->GetRMS() || dst[0]->GetBinError(bin) > 1 || dst[1]->GetBinError(bin) > 1; - const bool fail4 = fitFunc->GetParameter(0) < proj->GetMaximum() / 5.; - const bool fail = fail1 || fail2 || fail3 || fail4; - // if (p == 0 && ii == 4 && j == 2) DrawHisto(proj, Form("Hist_bin_%d-%d_vs_%d____%d_%d___%f-%f___%f-%f___%d.pdf", p, j, ii, bin, k, dst[0]->GetBinContent(bin), proj->GetRMS(), dst[1]->GetBinContent(bin), proj->GetMean(), (int) fail), ""); - - if (!fail) { - break; - } else if (k >= 2) { - dst[0]->SetBinContent(bin, proj->GetRMS()); - dst[0]->SetBinError(bin, std::sqrt(proj->GetRMS())); - dst[1]->SetBinContent(bin, proj->GetMean()); - dst[1]->SetBinError(bin, std::sqrt(proj->GetRMS())); + if (proj->GetEntries() < 20 || proj->GetRMS() < 0.00001) { + dst[0]->SetBinContent(bin, proj->GetRMS()); + dst[0]->SetBinError(bin, std::sqrt(proj->GetRMS())); + dst[1]->SetBinContent(bin, proj->GetMean()); + dst[1]->SetBinError(bin, std::sqrt(proj->GetRMS())); + } else { + proj->GetXaxis()->SetRangeUser(proj->GetMean() - 6. * proj->GetRMS(), proj->GetMean() + 6. * proj->GetRMS()); + proj->GetXaxis()->SetRangeUser(proj->GetMean() - 3. * proj->GetRMS(), proj->GetMean() + 3. * proj->GetRMS()); + bool forceLogLike = proj->GetMaximum() < 20; + for (int k = forceLogLike ? 2 : 0; k < 3; k++) { + proj->Fit("gaus", forceLogLike || k == 2 ? "sQl" : k ? "sQww" : "sQ"); + TF1* fitFunc = proj->GetFunction("gaus"); + + if (k && !forceLogLike) { + customGaus->SetParameters(fitFunc->GetParameter(0), fitFunc->GetParameter(1), fitFunc->GetParameter(2)); + proj->Fit(customGaus.get(), "sQ"); + fitFunc = customGaus.get(); + } + + const float sigma = fabs(fitFunc->GetParameter(2)); + dst[0]->SetBinContent(bin, sigma); + dst[1]->SetBinContent(bin, fitFunc->GetParameter(1)); + dst[0]->SetBinError(bin, fitFunc->GetParError(2)); + dst[1]->SetBinError(bin, fitFunc->GetParError(1)); + + const bool fail1 = sigma <= 0.f; + const bool fail2 = fabs(proj->GetMean() - dst[1]->GetBinContent(bin)) > std::min<float>(p ? PULL_AXIS : mConfig.nativeFitResolutions ? RES_AXES_NATIVE[j] : RES_AXES[j], 3.f * proj->GetRMS()); + const bool fail3 = dst[0]->GetBinContent(bin) > 3.f * proj->GetRMS() || dst[0]->GetBinError(bin) > 1 || dst[1]->GetBinError(bin) > 1; + const bool fail4 = fitFunc->GetParameter(0) < proj->GetMaximum() / 5.; + const bool fail = fail1 || fail2 || fail3 || fail4; + // if (p == 0 && ii == 4 && j == 2) DrawHisto(proj, Form("Hist_bin_%d-%d_vs_%d____%d_%d___%f-%f___%f-%f___%d.pdf", p, j, ii, bin, k, dst[0]->GetBinContent(bin), proj->GetRMS(), dst[1]->GetBinContent(bin), proj->GetMean(), (int) fail), ""); + + if (!fail) { + break; + } else if (k >= 2) { + dst[0]->SetBinContent(bin, proj->GetRMS()); + dst[0]->SetBinError(bin, std::sqrt(proj->GetRMS())); + dst[1]->SetBinContent(bin, proj->GetMean()); + dst[1]->SetBinError(bin, std::sqrt(proj->GetRMS())); + } } } + } else { + dst[0]->SetBinContent(bin, 0.f); + dst[0]->SetBinError(bin, 0.f); + dst[1]->SetBinContent(bin, 0.f); + dst[1]->SetBinError(bin, 0.f); + } + } + if (ii == 0) { + dstIntegral = src->ProjectionX(mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j], 0, nBins + 1); + unsigned int rebin = 1; + while (dstIntegral->GetMaximum() < 50 && rebin < sizeof(RES_AXIS_BINS) / sizeof(RES_AXIS_BINS[0])) { + dstIntegral->Rebin(RES_AXIS_BINS[rebin - 1] / RES_AXIS_BINS[rebin]); + rebin++; } - } else { - dst[0]->SetBinContent(bin, 0.f); - dst[0]->SetBinError(bin, 0.f); - dst[1]->SetBinContent(bin, 0.f); - dst[1]->SetBinError(bin, 0.f); } } if (ii == 0) { - dstIntegral = src->ProjectionX(mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j], 0, nBins + 1); - unsigned int rebin = 1; - while (dstIntegral->GetMaximum() < 50 && rebin < sizeof(RES_AXIS_BINS) / sizeof(RES_AXIS_BINS[0])) { - dstIntegral->Rebin(RES_AXIS_BINS[rebin - 1] / RES_AXIS_BINS[rebin]); - rebin++; + if (mConfig.inputHistogramsOnly) { + dstIntegral = createGarbageCollected<TH1D>(); } + sprintf(fname, p ? "IntPull%s" : "IntRes%s", VSPARAMETER_NAMES[j]); + sprintf(name, p ? "%s Pull" : "%s Resolution", p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j]); + dstIntegral->SetName(fname); + dstIntegral->SetTitle(name); } - } - if (ii == 0) { - if (mConfig.inputHistogramsOnly) { - dstIntegral = createGarbageCollected<TH1D>(); + if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) { + pad->cd(); } - sprintf(fname, p ? "IntPull%s" : "IntRes%s", VSPARAMETER_NAMES[j]); - sprintf(name, p ? "%s Pull" : "%s Resolution", p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j]); - dstIntegral->SetName(fname); - dstIntegral->SetTitle(name); - } - if (!mRunForQC || mConfig.shipToQCAsCanvas) { - pad->cd(); - } - int numColor = 0; - float tmpMax = -1000.; - float tmpMin = 1000.; + int numColor = 0; + float tmpMax = -1000.; + float tmpMin = 1000.; - for (int l = 0; l < 2; l++) { - for (int k = 0; k < ConfigNumInputs; k++) { - TH1F* e = dst[l]; - if (GetHist(e, tin, k, nNewInput) == nullptr) { - continue; - } - if (nNewInput && k == 0 && ii != 5) { - if (p == 0) { - e->Scale(mConfig.nativeFitResolutions ? SCALE_NATIVE[j] : SCALE[j]); + for (int l = 0; l < 2; l++) { + for (int k = 0; k < ConfigNumInputs; k++) { + TH1F* e = dst[l]; + if (GetHist(e, tin, k, nNewInput) == nullptr) { + continue; } - } - if (ii == 4) { - e->GetXaxis()->SetRangeUser(0.2, PT_MAX); - } else if (LOG_PT_MIN > 0 && ii == 5) { - e->GetXaxis()->SetRangeUser(LOG_PT_MIN, PT_MAX); - } else if (ii == 5) { - e->GetXaxis()->SetRange(1, 0); - } - e->SetMinimum(-1111); - e->SetMaximum(-1111); + if (nNewInput && k == 0 && ii != 5) { + if (p == 0) { + e->Scale(mConfig.nativeFitResolutions ? SCALE_NATIVE[j] : SCALE[j]); + } + } + if (ii == 4) { + e->GetXaxis()->SetRangeUser(0.2, PT_MAX); + } else if (LOG_PT_MIN > 0 && ii == 5) { + e->GetXaxis()->SetRangeUser(LOG_PT_MIN, PT_MAX); + } else if (ii == 5) { + e->GetXaxis()->SetRange(1, 0); + } + e->SetMinimum(-1111); + e->SetMaximum(-1111); - if (e->GetMaximum() > tmpMax) { - tmpMax = e->GetMaximum(); - } - if (e->GetMinimum() < tmpMin) { - tmpMin = e->GetMinimum(); + if (e->GetMaximum() > tmpMax) { + tmpMax = e->GetMaximum(); + } + if (e->GetMinimum() < tmpMin) { + tmpMin = e->GetMinimum(); + } } } - } - float tmpSpan; - tmpSpan = tmpMax - tmpMin; - tmpMax += tmpSpan * .02; - tmpMin -= tmpSpan * .02; - if (j == 2 && i < 3) { - tmpMax += tmpSpan * 0.13 * ConfigNumInputs; - } + float tmpSpan; + tmpSpan = tmpMax - tmpMin; + tmpMax += tmpSpan * .02; + tmpMin -= tmpSpan * .02; + if (j == 2 && i < 3) { + tmpMax += tmpSpan * 0.13 * ConfigNumInputs; + } - for (int k = 0; k < ConfigNumInputs; k++) { - for (int l = 0; l < 2; l++) { - TH1F* e = dst[l]; - if (!mConfig.inputHistogramsOnly && k == 0) { - sprintf(name, p ? "%s Pull" : "%s Resolution", p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j]); - e->SetTitle(name); - e->SetStats(kFALSE); - if (tout) { - if (l == 0) { - mRes2[j][i]->SetOption("colz"); - mRes2[j][i]->Write(); + for (int k = 0; k < ConfigNumInputs; k++) { + for (int l = 0; l < 2; l++) { + TH1F* e = dst[l]; + if (!mConfig.inputHistogramsOnly && k == 0) { + sprintf(name, p ? "%s Pull" : "%s Resolution", p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j]); + e->SetTitle(name); + e->SetStats(kFALSE); + if (tout) { + if (l == 0) { + mRes2[j][i]->SetOption("colz"); + mRes2[j][i]->Write(); + } + e->Write(); } - e->Write(); + } else if (GetHist(e, tin, k, nNewInput) == nullptr) { + continue; + } + e->SetMaximum(tmpMax); + e->SetMinimum(tmpMin); + e->SetLineWidth(1); + e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); + SetAxisSize(e); + e->GetYaxis()->SetTitle(p ? AXIS_TITLES_PULL[j] : mConfig.nativeFitResolutions ? AXIS_TITLES_NATIVE[j] : AXIS_TITLES[j]); + e->GetXaxis()->SetTitle(XAXIS_TITLES[i]); + if (LOG_PT_MIN > 0 && ii == 5) { + e->GetXaxis()->SetRangeUser(LOG_PT_MIN, PT_MAX); } - } else if (GetHist(e, tin, k, nNewInput) == nullptr) { - continue; - } - e->SetMaximum(tmpMax); - e->SetMinimum(tmpMin); - e->SetLineWidth(1); - e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); - SetAxisSize(e); - e->GetYaxis()->SetTitle(p ? AXIS_TITLES_PULL[j] : mConfig.nativeFitResolutions ? AXIS_TITLES_NATIVE[j] : AXIS_TITLES[j]); - e->GetXaxis()->SetTitle(XAXIS_TITLES[i]); - if (LOG_PT_MIN > 0 && ii == 5) { - e->GetXaxis()->SetRangeUser(LOG_PT_MIN, PT_MAX); - } - if (j == 0) { - e->GetYaxis()->SetTitleOffset(1.5); - } else if (j < 3) { - e->GetYaxis()->SetTitleOffset(1.4); - } - if (qcout && !mConfig.shipToQCAsCanvas) { - qcout->Add(e); - } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { - continue; - } + if (j == 0) { + e->GetYaxis()->SetTitleOffset(1.5); + } else if (j < 3) { + e->GetYaxis()->SetTitleOffset(1.4); + } + if (qcout && !mConfig.shipToQCAsCanvas) { + qcout->Add(e); + } + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { + continue; + } - e->SetMarkerColor(kBlack); - e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); - e->Draw(k || l ? "same" : ""); - if (j == 0) { - GetName(fname, k); - if (p) { - sprintf(name, "%s%s", fname, l ? "Mean" : "Pull"); - } else { - sprintf(name, "%s%s", fname, l ? "Mean" : "Resolution"); + e->SetMarkerColor(kBlack); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); + e->Draw(k || l ? "same" : ""); + if (j == 0) { + GetName(fname, k); + if (p) { + sprintf(name, "%s%s", fname, l ? "Mean" : "Pull"); + } else { + sprintf(name, "%s%s", fname, l ? "Mean" : "Resolution"); + } + leg->AddEntry(e, name, "l"); } - leg->AddEntry(e, name, "l"); } } - } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { - continue; - } + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { + continue; + } - if (ii == 5) { - pad->SetLogx(); + if (ii == 5) { + pad->SetLogx(); + } + can->cd(); + if (j == 4) { + ChangePadTitleSize(pad, 0.056); + } } - can->cd(); - if (j == 4) { - ChangePadTitleSize(pad, 0.056); + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { + continue; } - } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { - continue; - } - leg->Draw(); + leg->Draw(); - if (mRunForQC) { if (qcout) { qcout->Add(can); } - continue; - } - doPerfFigure(0.2, 0.295, 0.025); - can->Print(Form(p ? "plots/pull_vs_%s.pdf" : "plots/res_vs_%s.pdf", VSPARAMETER_NAMES[ii])); - if (mConfig.writeRootFiles) { - can->Print(Form(p ? "plots/pull_vs_%s.root" : "plots/res_vs_%s.root", VSPARAMETER_NAMES[ii])); + if (!mConfig.enableLocalOutput) { + continue; + } + doPerfFigure(0.2, 0.295, 0.025); + can->Print(Form(p ? "plots/pull_vs_%s.pdf" : "plots/res_vs_%s.pdf", VSPARAMETER_NAMES[ii])); + if (mConfig.writeRootFiles) { + can->Print(Form(p ? "plots/pull_vs_%s.root" : "plots/res_vs_%s.root", VSPARAMETER_NAMES[ii])); + } } } - } - // Process Integral Resolution Histogreams - for (int p = 0; p < 2; p++) { - TCanvas* can = p ? mCPull[6] : mCRes[6]; - for (int i = 0; i < 5; i++) { - TPad* pad = p ? mPPull[6][i] : mPRes[6][i]; - TH1D* hist = p ? pullIntegral[i] : resIntegral[i]; - int numColor = 0; - if (!mRunForQC || mConfig.shipToQCAsCanvas) { - pad->cd(); - } - if (!mConfig.inputHistogramsOnly && mcAvail) { - TH1D* e = hist; - e->GetEntries(); - e->Fit("gaus", "sQ"); + // Process Integral Resolution Histogreams + for (int p = 0; p < 2; p++) { + if ((p == 0 && (mQATasks & taskTrackingRes) == 0) || (p == 1 && (mQATasks & taskTrackingResPull) == 0)) { + continue; } - - float tmpMax = 0; - for (int k = 0; k < ConfigNumInputs; k++) { - TH1D* e = hist; - if (GetHist(e, tin, k, nNewInput) == nullptr) { - continue; + TCanvas* can = p ? mCPull[6] : mCRes[6]; + for (int i = 0; i < 5; i++) { + TPad* pad = p ? mPPull[6][i] : mPRes[6][i]; + TH1D* hist = p ? pullIntegral[i] : resIntegral[i]; + int numColor = 0; + if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) { + pad->cd(); } - e->SetMaximum(-1111); - if (e->GetMaximum() > tmpMax) { - tmpMax = e->GetMaximum(); + if (!mConfig.inputHistogramsOnly && mcAvail) { + TH1D* e = hist; + e->GetEntries(); + e->Fit("gaus", "sQ"); } - } - for (int k = 0; k < ConfigNumInputs; k++) { - TH1D* e = hist; - if (GetHist(e, tin, k, nNewInput) == nullptr) { - continue; - } - e->SetMaximum(tmpMax * 1.02); - e->SetMinimum(tmpMax * -0.02); - if (tout && !mConfig.inputHistogramsOnly && k == 0) { - e->Write(); + float tmpMax = 0; + for (int k = 0; k < ConfigNumInputs; k++) { + TH1D* e = hist; + if (GetHist(e, tin, k, nNewInput) == nullptr) { + continue; + } + e->SetMaximum(-1111); + if (e->GetMaximum() > tmpMax) { + tmpMax = e->GetMaximum(); + } } - if (qcout && !mConfig.shipToQCAsCanvas) { - qcout->Add(e); + + for (int k = 0; k < ConfigNumInputs; k++) { + TH1D* e = hist; + if (GetHist(e, tin, k, nNewInput) == nullptr) { + continue; + } + e->SetMaximum(tmpMax * 1.02); + e->SetMinimum(tmpMax * -0.02); + if (tout && !mConfig.inputHistogramsOnly && k == 0) { + e->Write(); + } + if (qcout && !mConfig.shipToQCAsCanvas) { + qcout->Add(e); + } + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { + continue; + } + + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); + e->Draw(k == 0 ? "" : "same"); } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { continue; } - - e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); - e->Draw(k == 0 ? "" : "same"); - } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { - continue; + can->cd(); } - can->cd(); - } - if (mRunForQC) { if (qcout) { qcout->Add(can); } - continue; - } + if (!mConfig.enableLocalOutput) { + continue; + } - can->Print(p ? "plots/pull_integral.pdf" : "plots/res_integral.pdf"); - if (mConfig.writeRootFiles) { - can->Print(p ? "plots/pull_integral.root" : "plots/res_integral.root"); + can->Print(p ? "plots/pull_integral.pdf" : "plots/res_integral.pdf"); + if (mConfig.writeRootFiles) { + can->Print(p ? "plots/pull_integral.root" : "plots/res_integral.root"); + } } } - // Process Cluster Histograms - { + if (mQATasks & taskClusterCounts) { + // Process Cluster Histograms if (mConfig.inputHistogramsOnly == 0) { for (int i = N_CLS_HIST; i < N_CLS_TYPE * N_CLS_HIST - 1; i++) { mClusters[i]->Sumw2(true); @@ -2201,7 +2249,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (!mcAvail) { counts[N_CLS_HIST - 1] = mClusterCounts.nTotal; } - if (counts[N_CLS_HIST - 1] && !mRunForQC) { + if (mConfig.enableLocalOutput && counts[N_CLS_HIST - 1]) { if (mcAvail) { for (int i = 0; i < N_CLS_HIST; i++) { printf("\t%35s: %'12llu (%6.2f%%)\n", CLUSTER_NAMES[i], counts[i], 100.f * counts[i] / counts[N_CLS_HIST - 1]); @@ -2282,7 +2330,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } for (int i = 0; i < N_CLS_TYPE; i++) { - if (!mRunForQC || mConfig.shipToQCAsCanvas) { + if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) { mPClust[i]->cd(); mPClust[i]->SetLogx(); } @@ -2313,7 +2361,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { continue; } @@ -2331,7 +2379,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { continue; } @@ -2339,16 +2387,16 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) e->Draw("same"); mLClust[i]->AddEntry(e, "Removed", "l"); } - if (mRunForQC && !mConfig.shipToQCAsCanvas) { + if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) { continue; } mLClust[i]->Draw(); - if (mRunForQC) { - if (qcout) { - qcout->Add(mCClust[i]); - } + if (qcout) { + qcout->Add(mCClust[i]); + } + if (!mConfig.enableLocalOutput) { continue; } doPerfFigure(i != 2 ? 0.37 : 0.6, 0.295, 0.030); @@ -2360,8 +2408,8 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } - // Process track statistic histograms - if (!mRunForQC) { + if (mQATasks & taskTrackStatistics) { + // Process track statistic histograms float tmpMax = 0.; for (int k = 0; k < ConfigNumInputs; k++) { TH1F* e = mTracks; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 7aca651aecf5a..c8fcd951f6b07 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -43,7 +43,7 @@ class GPUQA GPUQA(GPUChainTracking* chain) {} ~GPUQA() = default; - int InitQA() { return 1; } + int InitQA(int tasks = 0) { return 1; } void RunQA(bool matchOnly = false) {} int DrawQAHistograms() { return 1; } void SetMCTrackRange(int min, int max) {} @@ -88,7 +88,7 @@ class GPUQA GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config = nullptr); ~GPUQA(); - int InitQA(); + int InitQA(int tasks = -1); void RunQA(bool matchOnly = false); int DrawQAHistograms(TObjArray* qcout = nullptr); void DrawQAHistogramsCleanup(); // Needed after call to DrawQAHistograms with qcout != nullptr when GPUSettingsQA.shipToQCAsCanvas = true to clean up the Canvases etc. @@ -104,13 +104,24 @@ class GPUQA const std::vector<TH1F>& getHistograms1D() const { return *mHist1D; } const std::vector<TH2F>& getHistograms2D() const { return *mHist2D; } const std::vector<TH1D>& getHistograms1Dd() const { return *mHist1Dd; } - int loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3); + int loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3, int tasks = -1); static constexpr int N_CLS_HIST = 8; static constexpr int N_CLS_TYPE = 3; static constexpr int MC_LABEL_INVALID = -1e9; + enum QA_TASKS { + taskTrackingEff = 1, + taskTrackingRes = 2, + taskTrackingResPull = 4, + taskClusterAttach = 8, + taskTrackStatistics = 16, + taskClusterCounts = 32, + taskDefault = 63, + taskDefaultPostprocess = 31 + }; + private: struct additionalMCParameters { float pt, phi, theta, eta, nWeightCls; @@ -189,7 +200,6 @@ class GPUQA GPUChainTracking* mTracking; const GPUSettingsQA& mConfig; - bool mRunForQC; const char* str_perf_figure_1 = "ALICE Performance 2018/03/20"; // const char* str_perf_figure_2 = "2015, MC pp, #sqrt{s} = 5.02 TeV"; @@ -277,6 +287,7 @@ class GPUQA int mNEvents = 0; bool mQAInitialized = false; + int mQATasks = 0; std::vector<std::vector<int>> mcEffBuffer; std::vector<std::vector<int>> mcLabelBuffer; std::vector<std::vector<bool>> mGoodTracks; From 0fb01c5301af22d5f735a6f851af61278c868001 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 16 Nov 2020 08:36:07 +0100 Subject: [PATCH 1353/1751] GPU: Support external track arras (+MC labels) as input for TPC Tracking QA --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 +- .../Interface/GPUO2InterfaceQA.cxx | 28 +- GPU/GPUTracking/Interface/GPUO2InterfaceQA.h | 20 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 301 +++++++++++------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 12 +- 5 files changed, 236 insertions(+), 127 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 5a3ccdd611eb2..427a40e2d1c88 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -717,7 +717,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config std::vector<TH1F> copy1 = *outputRegions.qa.hist1; // Internally, this will also be used as output, so we need a non-const copy std::vector<TH2F> copy2 = *outputRegions.qa.hist2; std::vector<TH1D> copy3 = *outputRegions.qa.hist3; - processAttributes->qa->postprocess(copy1, copy2, copy3, out, processAttributes->qaTaskMask ? processAttributes->qaTaskMask : -1); + processAttributes->qa->postprocessExternal(copy1, copy2, copy3, out, processAttributes->qaTaskMask ? processAttributes->qaTaskMask : -1); pc.outputs().snapshot({gDataOriginTPC, "TRACKINGQA", 0, Lifetime::Timeframe}, out); processAttributes->qa->cleanup(); } diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx index e49456a0fea4c..7e354ea2c2d1c 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx @@ -23,7 +23,21 @@ GPUO2InterfaceQA::GPUO2InterfaceQA(const GPUSettingsQA* config) : mQA(new GPUQA( GPUO2InterfaceQA::~GPUO2InterfaceQA() = default; -int GPUO2InterfaceQA::postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out, int tasks) +int GPUO2InterfaceQA::initializeForProcessing(int tasks) +{ + return mQA->InitQA(tasks); +} + +void GPUO2InterfaceQA::runQA(const std::vector<o2::tpc::TrackTPC>* tracksExternal, const std::vector<o2::MCCompLabel>* tracksExtMC, const o2::tpc::ClusterNativeAccess* clNative) +{ + mQA->RunQA(false, tracksExternal, tracksExtMC, clNative); +} +int GPUO2InterfaceQA::postprocess(TObjArray& out) +{ + return mQA->DrawQAHistograms(&out); +} + +int GPUO2InterfaceQA::postprocessExternal(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out, int tasks) { if (mQA->loadHistograms(in1, in2, in3, tasks)) { return 1; @@ -35,3 +49,15 @@ void GPUO2InterfaceQA::cleanup() { mQA->DrawQAHistogramsCleanup(); } + +void GPUO2InterfaceQA::getHists(const std::vector<TH1F>*& h1, const std::vector<TH2F>*& h2, const std::vector<TH1D>*& h3) +{ + h1 = &mQA->getHistograms1D(); + h2 = &mQA->getHistograms2D(); + h3 = &mQA->getHistograms1Dd(); +} + +void GPUO2InterfaceQA::resetHists() +{ + mQA->resetHists(); +} diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h index 73d4e4a72da01..63be5a92141d2 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h @@ -33,6 +33,16 @@ class TH1D; class TH2F; class TObjArray; +namespace o2 +{ +class MCCompLabel; +namespace tpc +{ +class TrackTPC; +struct ClusterNativeAccess; +} // namespace tpc +} // namespace o2 + namespace o2::gpu { class GPUQA; @@ -43,8 +53,16 @@ class GPUO2InterfaceQA GPUO2InterfaceQA(const GPUSettingsQA* config = nullptr); ~GPUO2InterfaceQA(); + int initializeForProcessing(int tasks); // only needed for processing, not for postprocessing + + void runQA(const std::vector<o2::tpc::TrackTPC>* tracksExternal, const std::vector<o2::MCCompLabel>* tracksExtMC, const o2::tpc::ClusterNativeAccess* clNative); + int postprocess(TObjArray& out); + // Input might be modified, so we assume non-const. If it is const, a copy should be created before. - int postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out, int tasks); + int postprocessExternal(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out, int tasks); + + void getHists(const std::vector<TH1F>*& h1, const std::vector<TH2F>*& h2, const std::vector<TH1D>*& h3); + void resetHists(); void cleanup(); private: diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 28534cdcf0122..6b9a4c558cbfd 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -51,6 +51,7 @@ #include "SimulationDataFormat/MCCompLabel.h" #endif #ifdef GPUCA_O2_LIB +#include "DataFormatsTPC/TrackTPC.h" #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/TrackReference.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -213,22 +214,22 @@ inline unsigned int GPUQA::GetNMCCollissions() return mNColTracks.size(); } inline unsigned int GPUQA::GetNMCTracks(int iCol) { return mNColTracks[iCol]; } -inline unsigned int GPUQA::GetNMCLabels() { return mTracking->mIOPtrs.clustersNative->clustersMCTruth ? mTracking->mIOPtrs.clustersNative->clustersMCTruth->getIndexedSize() : 0; } +inline unsigned int GPUQA::GetNMCLabels() { return mClNative->clustersMCTruth ? mClNative->clustersMCTruth->getIndexedSize() : 0; } inline const GPUQA::mcInfo_t& GPUQA::GetMCTrack(unsigned int iTrk, unsigned int iCol) { return mMCInfos[iCol][iTrk]; } inline const GPUQA::mcInfo_t& GPUQA::GetMCTrack(const mcLabel_t& label) { return mMCInfos[label.getEventID()][label.getTrackID()]; } -inline GPUQA::mcLabels_t GPUQA::GetMCLabel(unsigned int i) { return mTracking->mIOPtrs.clustersNative->clustersMCTruth->getLabels(i); } +inline GPUQA::mcLabels_t GPUQA::GetMCLabel(unsigned int i) { return mClNative->clustersMCTruth->getLabels(i); } inline int GPUQA::GetMCLabelNID(const mcLabels_t& label) { return label.size(); } -inline int GPUQA::GetMCLabelNID(unsigned int i) { return mTracking->mIOPtrs.clustersNative->clustersMCTruth->getLabels(i).size(); } -inline GPUQA::mcLabel_t GPUQA::GetMCLabel(unsigned int i, unsigned int j) { return mTracking->mIOPtrs.clustersNative->clustersMCTruth->getLabels(i)[j]; } -inline int GPUQA::GetMCLabelID(unsigned int i, unsigned int j) { return mTracking->mIOPtrs.clustersNative->clustersMCTruth->getLabels(i)[j].getTrackID(); } +inline int GPUQA::GetMCLabelNID(unsigned int i) { return mClNative->clustersMCTruth->getLabels(i).size(); } +inline GPUQA::mcLabel_t GPUQA::GetMCLabel(unsigned int i, unsigned int j) { return mClNative->clustersMCTruth->getLabels(i)[j]; } +inline int GPUQA::GetMCLabelID(unsigned int i, unsigned int j) { return mClNative->clustersMCTruth->getLabels(i)[j].getTrackID(); } inline int GPUQA::GetMCLabelID(const mcLabels_t& label, unsigned int j) { return label[j].getTrackID(); } inline int GPUQA::GetMCLabelID(const mcLabel_t& label) { return label.getTrackID(); } -inline int GPUQA::GetMCLabelCol(unsigned int i, unsigned int j) { return mTracking->mIOPtrs.clustersNative->clustersMCTruth->getLabels(i)[j].getEventID(); } -inline const auto& GPUQA::GetClusterLabels() { return mTracking->mIOPtrs.clustersNative->clustersMCTruth; } +inline int GPUQA::GetMCLabelCol(unsigned int i, unsigned int j) { return mClNative->clustersMCTruth->getLabels(i)[j].getEventID(); } +inline const auto& GPUQA::GetClusterLabels() { return mClNative->clustersMCTruth; } inline float GPUQA::GetMCLabelWeight(unsigned int i, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabels_t& label, unsigned int j) { return 1; } inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return 1; } -inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking && mTracking->mIOPtrs.clustersNative->clustersMCTruth && mNColTracks.size(); } +inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking && mClNative->clustersMCTruth && mNColTracks.size(); } #define TRACK_EXPECTED_REFERENCE_X 78 #else inline GPUQA::mcLabelI_t::mcLabelI_t(const GPUQA::mcLabel_t& l) : track(l.fMCID) @@ -536,7 +537,7 @@ int GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vec tasks = taskDefaultPostprocess; } if (mQAInitialized && (!mHaveExternalHists || tasks != mQATasks)) { - return 1; + throw std::runtime_error("QA not initialized or initialized with different task array"); } if (tasks & taskClusterCounts) { throw std::runtime_error("Cluster counts impossible with external histograms"); @@ -559,7 +560,7 @@ int GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vec int GPUQA::InitQA(int tasks) { if (mQAInitialized) { - return 1; + throw std::runtime_error("QA already initialized"); } if (tasks == -1) { tasks = taskDefault; @@ -699,14 +700,24 @@ int GPUQA::InitQA(int tasks) return 0; } -void GPUQA::RunQA(bool matchOnly) +void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksExternal, const std::vector<o2::MCCompLabel>* tracksExtMC, const o2::tpc::ClusterNativeAccess* clNative) { if (!mQAInitialized) { - return; + throw std::runtime_error("QA not initialized"); + } + if (!clNative && mTracking) { + clNative = mTracking->mIOPtrs.clustersNative; } + mClNative = clNative; // Initialize Arrays - mTrackMCLabels.resize(mTracking->mIOPtrs.nMergedTracks); + if (tracksExternal) { +#ifdef GPUCA_O2_LIB + mTrackMCLabels.resize(tracksExternal->size()); +#endif + } else { + mTrackMCLabels.resize(mTracking->mIOPtrs.nMergedTracks); + } for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) { mTrackMCLabelsReverse[iCol].resize(GetNMCTracks(iCol)); mRecTracks[iCol].resize(GetNMCTracks(iCol)); @@ -718,8 +729,10 @@ void GPUQA::RunQA(bool matchOnly) mTrackMCLabelsReverse[iCol][i] = -1; } } - mClusterParam.resize(GetNMCLabels()); - memset(mClusterParam.data(), 0, mClusterParam.size() * sizeof(mClusterParam[0])); + if (mQATasks & taskClusterAttach) { + mClusterParam.resize(GetNMCLabels()); + memset(mClusterParam.data(), 0, mClusterParam.size() * sizeof(mClusterParam[0])); + } HighResTimer timer; mNEvents++; @@ -740,120 +753,130 @@ void GPUQA::RunQA(bool matchOnly) if (mcAvail) { // Assign Track MC Labels timer.Start(); - auto acc = GPUTPCTrkLbl<true, mcLabelI_t>(GetClusterLabels(), 1.f - mConfig.recThreshold); + if (tracksExternal) { +#ifdef GPUCA_O2_LIB + for (unsigned int i = 0; i < tracksExternal->size(); i++) { + mTrackMCLabels[i] = (*tracksExtMC)[i]; + } +#endif + } else { + auto acc = GPUTPCTrkLbl<true, mcLabelI_t>(GetClusterLabels(), 1.f - mConfig.recThreshold); #if QA_DEBUG == 0 - GPUCA_OPENMP(parallel for firstprivate(acc)) + GPUCA_OPENMP(parallel for firstprivate(acc)) #endif - for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { - acc.reset(); - int nClusters = 0; - const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; - std::vector<mcLabel_t> labels; - for (unsigned int k = 0; k < track.NClusters(); k++) { - if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { - continue; - } - nClusters++; - unsigned int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; - if (hitId >= GetNMCLabels()) { - GPUError("Invalid hit id %u > %d", hitId, GetNMCLabels()); - throw std::runtime_error("qa error"); - } - acc.addLabel(hitId); - for (int j = 0; j < GetMCLabelNID(hitId); j++) { - if (GetMCLabelID(hitId, j) >= (int)GetNMCTracks(GetMCLabelCol(hitId, j))) { - GPUError("Invalid label %d > %d (hit %d, label %d, col %d)", GetMCLabelID(hitId, j), GetNMCTracks(GetMCLabelCol(hitId, j)), hitId, j, (int)GetMCLabelCol(hitId, j)); + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + acc.reset(); + int nClusters = 0; + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; + std::vector<mcLabel_t> labels; + for (unsigned int k = 0; k < track.NClusters(); k++) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + continue; + } + nClusters++; + unsigned int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; + if (hitId >= GetNMCLabels()) { + GPUError("Invalid hit id %u > %d", hitId, GetNMCLabels()); throw std::runtime_error("qa error"); } - if (GetMCLabelID(hitId, j) >= 0) { - if (QA_DEBUG >= 3 && track.OK()) { - GPUInfo("Track %d Cluster %u Label %d: %d (%f)", i, k, j, GetMCLabelID(hitId, j), GetMCLabelWeight(hitId, j)); + acc.addLabel(hitId); + for (int j = 0; j < GetMCLabelNID(hitId); j++) { + if (GetMCLabelID(hitId, j) >= (int)GetNMCTracks(GetMCLabelCol(hitId, j))) { + GPUError("Invalid label %d > %d (hit %d, label %d, col %d)", GetMCLabelID(hitId, j), GetNMCTracks(GetMCLabelCol(hitId, j)), hitId, j, (int)GetMCLabelCol(hitId, j)); + throw std::runtime_error("qa error"); + } + if (GetMCLabelID(hitId, j) >= 0) { + if (QA_DEBUG >= 3 && track.OK()) { + GPUInfo("Track %d Cluster %u Label %d: %d (%f)", i, k, j, GetMCLabelID(hitId, j), GetMCLabelWeight(hitId, j)); + } } } } - } - float maxweight, sumweight; - int maxcount; - auto maxLabel = acc.computeLabel(&maxweight, &sumweight, &maxcount); - mTrackMCLabels[i] = maxLabel; - if (QA_DEBUG && track.OK() && GetNMCTracks(maxLabel.getEventID()) > maxLabel.getTrackID()) { - const mcInfo_t& mc = GetMCTrack(maxLabel); - GPUInfo("Track %d label %d (fake %d) weight %f clusters %d (fitted %d) (%f%% %f%%) Pt %f", i, maxLabel.getTrackID(), (int)(maxLabel.isFake()), maxweight, nClusters, track.NClustersFitted(), 100.f * maxweight / sumweight, 100.f * (float)maxcount / (float)nClusters, - std::sqrt(mc.pX * mc.pX + mc.pY * mc.pY)); + float maxweight, sumweight; + int maxcount; + auto maxLabel = acc.computeLabel(&maxweight, &sumweight, &maxcount); + mTrackMCLabels[i] = maxLabel; + if (QA_DEBUG && track.OK() && GetNMCTracks(maxLabel.getEventID()) > maxLabel.getTrackID()) { + const mcInfo_t& mc = GetMCTrack(maxLabel); + GPUInfo("Track %d label %d (fake %d) weight %f clusters %d (fitted %d) (%f%% %f%%) Pt %f", i, maxLabel.getTrackID(), (int)(maxLabel.isFake()), maxweight, nClusters, track.NClustersFitted(), 100.f * maxweight / sumweight, 100.f * (float)maxcount / (float)nClusters, + std::sqrt(mc.pX * mc.pX + mc.pY * mc.pY)); + } } } if (QA_TIMING) { GPUInfo("QA Time: Assign Track Labels:\t\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); } - // fill cluster attachment status - for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { - const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; - if (!track.OK()) { - continue; - } - if (!mTrackMCLabels[i].isValid()) { - for (unsigned int k = 0; k < track.NClusters(); k++) { - if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { - continue; - } - mClusterParam[mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num].fakeAttached++; + if (mQATasks & taskClusterAttach) { + // fill cluster attachment status + for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; + if (!track.OK()) { + continue; } - continue; - } - mcLabelI_t label = mTrackMCLabels[i]; - if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) { - for (unsigned int k = 0; k < track.NClusters(); k++) { - if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { - continue; - } - int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; - bool correct = false; - for (int j = 0; j < GetMCLabelNID(hitId); j++) { - if (label == GetMCLabel(hitId, j)) { - correct = true; - break; + if (!mTrackMCLabels[i].isValid()) { + for (unsigned int k = 0; k < track.NClusters(); k++) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + continue; } + mClusterParam[mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num].fakeAttached++; } - if (correct) { - mClusterParam[hitId].attached++; - } else { - mClusterParam[hitId].fakeAttached++; - } + continue; } - } - if (mTrackMCLabels[i].isFake()) { - (GetMCTrackObj(mFakeTracks, label))++; - } else if (!track.MergedLooper()) { - GetMCTrackObj(mRecTracks, label)++; + mcLabelI_t label = mTrackMCLabels[i]; if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) { - int& revLabel = GetMCTrackObj(mTrackMCLabelsReverse, label); - if (revLabel == -1 || !mTracking->mIOPtrs.mergedTracks[revLabel].OK() || (mTracking->mIOPtrs.mergedTracks[i].OK() && fabsf(mTracking->mIOPtrs.mergedTracks[i].GetParam().GetZ()) < fabsf(mTracking->mIOPtrs.mergedTracks[revLabel].GetParam().GetZ()))) { - revLabel = i; + for (unsigned int k = 0; k < track.NClusters(); k++) { + if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) { + continue; + } + int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num; + bool correct = false; + for (int j = 0; j < GetMCLabelNID(hitId); j++) { + if (label == GetMCLabel(hitId, j)) { + correct = true; + break; + } + } + if (correct) { + mClusterParam[hitId].attached++; + } else { + mClusterParam[hitId].fakeAttached++; + } } } - } - } - // fill cluster adjacent status - for (unsigned int i = 0; i < GetNMCLabels(); i++) { - if (mClusterParam[i].attached == 0 && mClusterParam[i].fakeAttached == 0) { - int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; - if (attach & gputpcgmmergertypes::attachFlagMask) { - int track = attach & gputpcgmmergertypes::attachTrackMask; - mcLabelI_t trackL = mTrackMCLabels[track]; - bool fake = true; - for (int j = 0; j < GetMCLabelNID(i); j++) { - // GPUInfo("Attach %x Track %d / %d:%d", attach, track, j, GetMCLabelID(i, j)); - if (trackL == GetMCLabel(i, j)) { - fake = false; - break; + if (mTrackMCLabels[i].isFake()) { + (GetMCTrackObj(mFakeTracks, label))++; + } else if (!track.MergedLooper()) { + GetMCTrackObj(mRecTracks, label)++; + if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) { + int& revLabel = GetMCTrackObj(mTrackMCLabelsReverse, label); + if (revLabel == -1 || !mTracking->mIOPtrs.mergedTracks[revLabel].OK() || (mTracking->mIOPtrs.mergedTracks[i].OK() && fabsf(mTracking->mIOPtrs.mergedTracks[i].GetParam().GetZ()) < fabsf(mTracking->mIOPtrs.mergedTracks[revLabel].GetParam().GetZ()))) { + revLabel = i; } } - if (fake) { - mClusterParam[i].fakeAdjacent++; - } else { - mClusterParam[i].adjacent++; + } + } + // fill cluster adjacent status + for (unsigned int i = 0; i < GetNMCLabels(); i++) { + if (mClusterParam[i].attached == 0 && mClusterParam[i].fakeAttached == 0) { + int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; + if (attach & gputpcgmmergertypes::attachFlagMask) { + int track = attach & gputpcgmmergertypes::attachTrackMask; + mcLabelI_t trackL = mTrackMCLabels[track]; + bool fake = true; + for (int j = 0; j < GetMCLabelNID(i); j++) { + // GPUInfo("Attach %x Track %d / %d:%d", attach, track, j, GetMCLabelID(i, j)); + if (trackL == GetMCLabel(i, j)) { + fake = false; + break; + } + } + if (fake) { + mClusterParam[i].fakeAdjacent++; + } else { + mClusterParam[i].adjacent++; + } } } } @@ -1044,7 +1067,7 @@ void GPUQA::RunQA(bool matchOnly) prop.SetPolynomialField(&mTracking->GetParam().polynomialField); prop.SetToyMCEventsFlag(mTracking->GetParam().par.ToyMCEventsFlag); - for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + for (unsigned int i = 0; i < mTrackMCLabels.size(); i++) { if (mConfig.writeMCLabels) { std::vector<int>& labelBuffer = mcLabelBuffer[mNEvents - 1]; labelBuffer[i] = mTrackMCLabels[i].getTrackID(); @@ -1054,16 +1077,16 @@ void GPUQA::RunQA(bool matchOnly) } const mcInfo_t& mc1 = GetMCTrack(mTrackMCLabels[i]); const additionalMCParameters& mc2 = GetMCTrackObj(mMCParam, mTrackMCLabels[i]); - const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; - if ((mMCTrackMin != -1 && mTrackMCLabels[i].getTrackID() < mMCTrackMin) || (mMCTrackMax != -1 && mTrackMCLabels[i].getTrackID() >= mMCTrackMax)) { - continue; - } - - if (!track.OK()) { - continue; + if (!tracksExternal) { + if (!mTracking->mIOPtrs.mergedTracks[i].OK()) { + continue; + } + if (mTracking->mIOPtrs.mergedTracks[i].MergedLooper()) { + continue; + } } - if (track.MergedLooper()) { + if ((mMCTrackMin != -1 && mTrackMCLabels[i].getTrackID() < mMCTrackMin) || (mMCTrackMax != -1 && mTrackMCLabels[i].getTrackID() >= mMCTrackMax)) { continue; } if (fabsf(mc2.eta) > ETA_MAX || mc2.pt < PT_MIN || mc2.pt > PT_MAX) { @@ -1093,9 +1116,27 @@ void GPUQA::RunQA(bool matchOnly) continue; } + GPUTPCGMTrackParam param; + float alpha = 0.f; + if (tracksExternal) { +#ifdef GPUCA_O2_LIB + for (int k = 0; k < 5; k++) { + param.Par()[k] = (*tracksExternal)[i].getParams()[k]; + } + for (int k = 0; k < 15; k++) { + param.Cov()[k] = (*tracksExternal)[i].getCov()[k]; + } + param.X() = (*tracksExternal)[i].getX(); + alpha = (*tracksExternal)[i].getAlpha(); +#endif + } else { + param = mTracking->mIOPtrs.mergedTracks[i].GetParam(); + alpha = mTracking->mIOPtrs.mergedTracks[i].GetAlpha(); + } + float mclocal[4]; // Rotated x,y,Px,Py mc-coordinates - the MC data should be rotated since the track is propagated best along x - float c = std::cos(track.GetAlpha()); - float s = std::sin(track.GetAlpha()); + float c = std::cos(alpha); + float s = std::sin(alpha); float x = mc1.x; float y = mc1.y; mclocal[0] = x * c + y * s; @@ -1105,8 +1146,6 @@ void GPUQA::RunQA(bool matchOnly) mclocal[2] = px * c + py * s; mclocal[3] = -px * s + py * c; - GPUTPCGMTrackParam param = track.GetParam(); - if (mclocal[0] < TRACK_EXPECTED_REFERENCE_X - 3) { continue; } @@ -1117,7 +1156,6 @@ void GPUQA::RunQA(bool matchOnly) continue; } - float alpha = track.GetAlpha(); prop.SetTrack(¶m, alpha); bool inFlyDirection = 0; #ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference @@ -1419,7 +1457,7 @@ void GPUQA::RunQA(bool matchOnly) } if (mQATasks & taskClusterCounts) { - unsigned int nCl = mTracking->mIOPtrs.clustersNative ? mTracking->mIOPtrs.clustersNative->nClustersTotal : mTracking->GetTPCMerger().NMaxClusters(); + unsigned int nCl = clNative ? clNative->nClustersTotal : mTracking->GetTPCMerger().NMaxClusters(); for (unsigned int i = 0; i < nCl; i++) { int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[i]; CHECK_CLUSTER_STATE(); @@ -1636,10 +1674,29 @@ void GPUQA::DrawQAHistogramsCleanup() clearGarbagageCollector(); } +void GPUQA::resetHists() +{ + if (!mQAInitialized) { + throw std::runtime_error("QA not initialized"); + } + if (mHaveExternalHists) { + throw std::runtime_error("Cannot reset external hists"); + } + for (auto& h : *mHist1D) { + h.Reset(); + } + for (auto& h : *mHist2D) { + h.Reset(); + } + for (auto& h : *mHist1Dd) { + h.Reset(); + } +} + int GPUQA::DrawQAHistograms(TObjArray* qcout) { if (!mQAInitialized) { - return 1; + throw std::runtime_error("QA not initialized"); } std::vector<Color_t> colorNums(COLORCOUNT); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index c8fcd951f6b07..fdd95b091dfe7 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -71,7 +71,12 @@ class GPUQA namespace o2 { class MCCompLabel; -} +namespace tpc +{ +class TrackTPC; +struct ClusterNativeAccess; +} // namespace tpc +} // namespace o2 class AliHLTTPCClusterMCLabel; @@ -89,7 +94,7 @@ class GPUQA ~GPUQA(); int InitQA(int tasks = -1); - void RunQA(bool matchOnly = false); + void RunQA(bool matchOnly = false, const std::vector<o2::tpc::TrackTPC>* tracksExternal = nullptr, const std::vector<o2::MCCompLabel>* tracksExtMC = nullptr, const o2::tpc::ClusterNativeAccess* clNative = nullptr); int DrawQAHistograms(TObjArray* qcout = nullptr); void DrawQAHistogramsCleanup(); // Needed after call to DrawQAHistograms with qcout != nullptr when GPUSettingsQA.shipToQCAsCanvas = true to clean up the Canvases etc. void SetMCTrackRange(int min, int max); @@ -104,6 +109,7 @@ class GPUQA const std::vector<TH1F>& getHistograms1D() const { return *mHist1D; } const std::vector<TH2F>& getHistograms2D() const { return *mHist2D; } const std::vector<TH1D>& getHistograms1Dd() const { return *mHist1Dd; } + void resetHists(); int loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3, int tasks = -1); static constexpr int N_CLS_HIST = 8; @@ -297,6 +303,8 @@ class GPUQA static int initColors(); int mMCTrackMin = -1, mMCTrackMax = -1; + + const o2::tpc::ClusterNativeAccess* mClNative; }; inline bool GPUQA::SuppressTrack(int iTrack) const { return (mConfig.matchMCLabels.size() && !mGoodTracks[mNEvents][iTrack]); } From a975fc90a1b096c86f738e3cfa15f7ccaaeccd77 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 17 Nov 2020 11:49:14 +0100 Subject: [PATCH 1354/1751] Add TPC Tracking QC Task --- Detectors/TPC/qc/CMakeLists.txt | 5 +- Detectors/TPC/qc/include/TPCQC/Tracking.h | 90 +++++++++++++++++++++++ Detectors/TPC/qc/src/TPCQCLinkDef.h | 1 + Detectors/TPC/qc/src/Tracking.cxx | 77 +++++++++++++++++++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 Detectors/TPC/qc/include/TPCQC/Tracking.h create mode 100644 Detectors/TPC/qc/src/Tracking.cxx diff --git a/Detectors/TPC/qc/CMakeLists.txt b/Detectors/TPC/qc/CMakeLists.txt index 2f60bf0bcfe8b..ee254b20a9315 100644 --- a/Detectors/TPC/qc/CMakeLists.txt +++ b/Detectors/TPC/qc/CMakeLists.txt @@ -10,16 +10,19 @@ o2_add_library(TPCQC SOURCES src/PID.cxx + src/Tracking.cxx src/Helpers.cxx src/TrackCuts.cxx src/Clusters.cxx src/Tracks.cxx PUBLIC_LINK_LIBRARIES O2::TPCBase - O2::DataFormatsTPC) + O2::DataFormatsTPC + O2::GPUTracking) o2_target_root_dictionary(TPCQC HEADERS include/TPCQC/PID.h + include/TPCQC/Tracking.h include/TPCQC/Helpers.h include/TPCQC/TrackCuts.h include/TPCQC/Clusters.h diff --git a/Detectors/TPC/qc/include/TPCQC/Tracking.h b/Detectors/TPC/qc/include/TPCQC/Tracking.h new file mode 100644 index 0000000000000..59b37d5828ba6 --- /dev/null +++ b/Detectors/TPC/qc/include/TPCQC/Tracking.h @@ -0,0 +1,90 @@ +// 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 Tracking.h +/// @author David Rohr +/// + +#ifndef AliceO2_TPC_QC_TRACKING_H +#define AliceO2_TPC_QC_TRACKING_H + +#include <vector> +#include <memory> + +class TH1F; +class TH2F; +class TH1D; + +//o2 includes +#include "DataFormatsTPC/Defs.h" + +namespace o2 +{ +class MCCompLabel; +namespace gpu +{ +class GPUO2InterfaceQA; +} // namespace gpu +namespace tpc +{ +class TrackTPC; +struct ClusterNativeAccess; + +namespace qc +{ +// Class for tracking QA (efficiency / resolution) +// Some settings can be steered via --configKeyValues: (See GPUSettingsList.h for actual definitions). Relevant QA parameters are: +// "GPU_QA.strict=[bool]" Strict QA mode: Only consider resolution of tracks where the fit ended within 5 cm of the reference, and remove outliers. (Default: true) +// "GPU_QA.qpt=[float]" Set cut for Q/Pt. (Default: 10.0) +// "GPU_QA.recThreshold=[float]" Compute the efficiency including impure tracks with fake contamination. (Default 0.9) +// "GPU_QA.maxResX=[float]" Maxmimum X (~radius) for reconstructed track position to take into accound for resolution QA in cm (Default: no limit) +// "GPU_QA.nativeFitResolutions=[bool]" Create resolution histograms in the native fit units (sin(phi), tan(lambda), Q/Pt) (Default: false) +// "GPU_QA.filterCharge=[int]" Filter for positive (+1) or negative (-1) charge (Default: no filter) +// "GPU_QA.filterPID=[int]" Filter for Particle Type (0 Electron, 1 Muon, 2 Pion, 3 Kaon, 4 Proton) (Default: no filter) + +class Tracking +{ + public: + /// default constructor + Tracking(); + ~Tracking(); + + enum outputModes { + outputMergeable, // output mergeaable histogrems, which can be merged and then postprocessed + outputPostprocessed, // directly postprocess the histograms before merging + outputLayout // arrange postprocessed histograms in predefined layouts + }; + + // Initiaalize + // postprocessOnly = false: initialize to run the full QA via processTracks function. + // postprocessOnly = true : cannot process tracks but only postprocess mergeeablee histogrems in postprocess function, output type must be outputPostprocessed or outputLayout. + void initialize(outputModes outputMode, bool postprocessOnly = false); + + void processTracks(const std::vector<o2::tpc::TrackTPC>* tracks, const std::vector<o2::MCCompLabel>* tracksMC, const o2::tpc::ClusterNativeAccess* clNative, TObjArray* out = nullptr); + int postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out); // Inputs are modified, thus must not be const + + /// Reset all histograms + void resetHistograms(); + + /// get histograms + void getHists(const std::vector<TH1F>*& h1, const std::vector<TH2F>*& h2, const std::vector<TH1D>*& h3) const; + + private: + std::unique_ptr<o2::gpu::GPUO2InterfaceQA> mQA; //! + outputModes mOutputMode; + + ClassDefNV(Tracking, 1) +}; +} // namespace qc +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/qc/src/TPCQCLinkDef.h b/Detectors/TPC/qc/src/TPCQCLinkDef.h index 99cce76f3c5c5..955563373e617 100644 --- a/Detectors/TPC/qc/src/TPCQCLinkDef.h +++ b/Detectors/TPC/qc/src/TPCQCLinkDef.h @@ -15,6 +15,7 @@ #pragma link off all functions; #pragma link C++ class o2::tpc::qc::PID+; +#pragma link C++ class o2::tpc::qc::Tracking + ; #pragma link C++ class o2::tpc::qc::TrackCuts+; #pragma link C++ class o2::tpc::qc::Clusters+; #pragma link C++ class o2::tpc::qc::Tracks+; diff --git a/Detectors/TPC/qc/src/Tracking.cxx b/Detectors/TPC/qc/src/Tracking.cxx new file mode 100644 index 0000000000000..3efd5e8880de2 --- /dev/null +++ b/Detectors/TPC/qc/src/Tracking.cxx @@ -0,0 +1,77 @@ +// 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 Tracking.cxx +/// \author David Rohr + +#define _USE_MATH_DEFINES + +#include <cmath> + +//root includes +#include "TStyle.h" +#include "TFile.h" +#include "TCanvas.h" +#include "TH1F.h" +#include "TH2F.h" +#include "TH1D.h" + +//o2 includes +#include "DataFormatsTPC/TrackTPC.h" +#include "TPCQC/Tracking.h" +#include "GPUO2InterfaceQA.h" +#include "GPUO2InterfaceConfiguration.h" + +ClassImp(o2::tpc::qc::Tracking); + +using namespace o2::tpc::qc; +using namespace o2::gpu; + +Tracking::Tracking() = default; +Tracking::~Tracking() = default; + +static constexpr int QAMODE = 7; + +//______________________________________________________________________________ +void Tracking::initialize(outputModes outputMode, bool postprocessOnly) +{ + mOutputMode = outputMode; + GPUO2InterfaceConfiguration config; + config.configQA.shipToQCAsCanvas = mOutputMode == outputLayout; + mQA = std::make_unique<GPUO2InterfaceQA>(&config.configQA); + if (!postprocessOnly) { + mQA->initializeForProcessing(QAMODE); + } +} + +//______________________________________________________________________________ +void Tracking::resetHistograms() +{ + mQA->resetHists(); +} + +//______________________________________________________________________________ +void Tracking::processTracks(const std::vector<o2::tpc::TrackTPC>* tracks, const std::vector<o2::MCCompLabel>* tracksMC, const o2::tpc::ClusterNativeAccess* clNative, TObjArray* out) +{ + mQA->runQA(tracks, tracksMC, clNative); + if (mOutputMode == outputPostprocessed || mOutputMode == outputLayout) { + mQA->postprocess(*out); + } +} + +int Tracking::postprocess(std::vector<TH1F>& in1, std::vector<TH2F>& in2, std::vector<TH1D>& in3, TObjArray& out) +{ + return mQA->postprocessExternal(in1, in2, in3, out, QAMODE); +} + +void Tracking::getHists(const std::vector<TH1F>*& h1, const std::vector<TH2F>*& h2, const std::vector<TH1D>*& h3) const +{ + mQA->getHists(h1, h2, h3); +} From 50a7aa7e701b4425c0f5a2ced9d8b8c6f55accdb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 17 Nov 2020 21:37:07 +0100 Subject: [PATCH 1355/1751] DPL: fix warnings --- Framework/Core/test/test_WorkflowHelpers.cxx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Framework/Core/test/test_WorkflowHelpers.cxx b/Framework/Core/test/test_WorkflowHelpers.cxx index 9b9c36a171a12..cd0fe6ddadf5d 100644 --- a/Framework/Core/test/test_WorkflowHelpers.cxx +++ b/Framework/Core/test/test_WorkflowHelpers.cxx @@ -53,17 +53,17 @@ BOOST_AUTO_TEST_CASE(TestVerifyWorkflow) using namespace o2::framework; auto checkIncompleteInput = [](WorkflowSpec const& workflow) { // Empty workflows should be invalid. - BOOST_CHECK_THROW(WorkflowHelpers::verifyWorkflow(workflow), std::runtime_error); + BOOST_CHECK_THROW((void)WorkflowHelpers::verifyWorkflow(workflow), std::runtime_error); }; auto checkOk = [](WorkflowSpec const& workflow) { // Empty workflows should be invalid. - BOOST_CHECK_NO_THROW(WorkflowHelpers::verifyWorkflow(workflow)); + BOOST_CHECK_NO_THROW((void)WorkflowHelpers::verifyWorkflow(workflow)); }; auto checkNotOk = [](WorkflowSpec const& workflow) { // Empty workflows should be invalid. - BOOST_CHECK_THROW(WorkflowHelpers::verifyWorkflow(workflow), std::runtime_error); + BOOST_CHECK_THROW((void)WorkflowHelpers::verifyWorkflow(workflow), std::runtime_error); }; // A non fully specified input is an error, given the result is ambiguous. @@ -232,7 +232,8 @@ BOOST_AUTO_TEST_CASE(TestSimpleConnection) std::vector<OutputSpec> outputs; std::vector<LogicalForwardInfo> availableForwardsInfo; - WorkflowHelpers::verifyWorkflow(workflow); + auto result = WorkflowHelpers::verifyWorkflow(workflow); + BOOST_REQUIRE(result == WorkflowParsingState::Valid); auto context = makeEmptyConfigContext(); WorkflowHelpers::injectServiceDevices(workflow, *context); BOOST_CHECK_EQUAL(workflow.size(), 3); @@ -273,7 +274,7 @@ BOOST_AUTO_TEST_CASE(TestSimpleForward) std::vector<DeviceConnectionEdge> logicalEdges; std::vector<OutputSpec> outputs; std::vector<LogicalForwardInfo> availableForwardsInfo; - WorkflowHelpers::verifyWorkflow(workflow); + BOOST_REQUIRE(WorkflowHelpers::verifyWorkflow(workflow) == WorkflowParsingState::Valid); auto context = makeEmptyConfigContext(); WorkflowHelpers::injectServiceDevices(workflow, *context); WorkflowHelpers::constructGraph(workflow, logicalEdges, @@ -330,7 +331,7 @@ BOOST_AUTO_TEST_CASE(TestGraphConstruction) // channels, so that we can construct them before assigning to a device. std::vector<OutputSpec> outputs; - WorkflowHelpers::verifyWorkflow(workflow); + BOOST_REQUIRE(WorkflowHelpers::verifyWorkflow(workflow) == WorkflowParsingState::Valid); auto context = makeEmptyConfigContext(); WorkflowHelpers::injectServiceDevices(workflow, *context); WorkflowHelpers::constructGraph(workflow, logicalEdges, @@ -449,7 +450,7 @@ BOOST_AUTO_TEST_CASE(TestExternalInput) InputSpec{"external", "TST", "A", 0, Lifetime::Timer}}, Outputs{ OutputSpec{"TST", "B"}}}}; - WorkflowHelpers::verifyWorkflow(workflow); + BOOST_REQUIRE(WorkflowHelpers::verifyWorkflow(workflow) == WorkflowParsingState::Valid); std::vector<DeviceConnectionEdge> logicalEdges; std::vector<OutputSpec> outputs; std::vector<LogicalForwardInfo> availableForwardsInfo; @@ -536,7 +537,7 @@ BOOST_AUTO_TEST_CASE(TestOriginWildcard) std::vector<OutputSpec> outputs; std::vector<LogicalForwardInfo> availableForwardsInfo; - WorkflowHelpers::verifyWorkflow(workflow); + BOOST_REQUIRE(WorkflowHelpers::verifyWorkflow(workflow) == WorkflowParsingState::Valid); auto context = makeEmptyConfigContext(); WorkflowHelpers::injectServiceDevices(workflow, *context); BOOST_CHECK_EQUAL(workflow.size(), 3); From a9dae1e68c3155f664d3b30d9dfc9d9238892417 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 17 Nov 2020 13:25:02 +0100 Subject: [PATCH 1356/1751] DPL: check dictionary creation when InputSpec / OutputSpec is included --- Framework/Core/test/TestClasses.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Framework/Core/test/TestClasses.h b/Framework/Core/test/TestClasses.h index 8c6cd9e304dc3..1d6700b72fca3 100644 --- a/Framework/Core/test/TestClasses.h +++ b/Framework/Core/test/TestClasses.h @@ -7,14 +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_TEST_CLASSES_H -#define FRAMEWORK_TEST_CLASSES_H +#ifndef O2_FRAMEWORK_TEST_CLASSES_H_ +#define O2_FRAMEWORK_TEST_CLASSES_H_ #include <Rtypes.h> +#include "Framework/InputSpec.h" +#include "Framework/OutputSpec.h" -namespace o2 -{ -namespace test +namespace o2::test { class TriviallyCopyable @@ -84,6 +84,5 @@ class SimplePODClass ClassDefNV(SimplePODClass, 1); }; -} // namespace test -} // namespace o2 -#endif // FRAMEWORK_TEST_CLASSES_H +} // namespace o2::test +#endif // O2_FRAMEWORK_TEST_CLASSES_H_ From e275e2989a4a48e0b3e173c4b85960bc92d78d88 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 18 Nov 2020 09:14:43 +0100 Subject: [PATCH 1357/1751] GPU: Workaround to compile with AliRoot in release defaults --- GPU/GPUTracking/Base/GPUParam.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index 3c92e1d09f7a2..c1dc43d392e0b 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -54,6 +54,7 @@ struct GPUParam_t { }; } // namespace internal +#if !(defined(__CINT__) || defined(__ROOTCINT__)) || defined(__CLING__) // Hide from ROOT 5 CINT since it triggers a CINT but MEM_CLASS_PRE() struct GPUParam : public internal::GPUParam_t<GPUSettingsRec, GPUSettingsParam> { @@ -84,6 +85,7 @@ struct GPUParam : public internal::GPUParam_t<GPUSettingsRec, GPUSettingsParam> GPUd() void Slice2Global(int iSlice, float x, float y, float z, float* X, float* Y, float* Z) const; GPUd() void Global2Slice(int iSlice, float x, float y, float z, float* X, float* Y, float* Z) const; }; +#endif } // namespace gpu } // namespace GPUCA_NAMESPACE From 1b51b1b40fe0d80e8f9cf569d8b374bfcfec882d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 17 Nov 2020 09:19:32 +0100 Subject: [PATCH 1358/1751] GPU: fix, RTC not usable without C++17 --- GPU/GPUTracking/Standalone/utils/qconfigrtc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GPU/GPUTracking/Standalone/utils/qconfigrtc.h b/GPU/GPUTracking/Standalone/utils/qconfigrtc.h index 0420d4cc66cf4..e389ab6aab484 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfigrtc.h +++ b/GPU/GPUTracking/Standalone/utils/qconfigrtc.h @@ -25,11 +25,15 @@ template <class T> static std::string qConfigPrintRtc(const T& tSrc, bool useConstexpr) { +#if defined(__cplusplus) && __cplusplus >= 201703L std::stringstream out; #define QCONFIG_PRINT_RTC #include "qconfig.h" #undef QCONFIG_PRINT_RTC return out.str(); +#else + throw std::runtime_error("not supported"); +#endif } #define QCONFIG_CONVERT_RTC From 8727301fd5f1d7c074b047a74812f22ffbf37270 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 17 Nov 2020 14:16:32 +0100 Subject: [PATCH 1359/1751] GPU: Remove if constexpr for C++ < 17 --- GPU/Common/GPUCommonDef.h | 3 --- GPU/Common/GPUCommonMath.h | 14 ++++++++------ .../DataCompression/GPUTPCCompressionKernels.cxx | 7 ++----- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/GPU/Common/GPUCommonDef.h b/GPU/Common/GPUCommonDef.h index 73c576144faf7..1eabbfc6c4b58 100644 --- a/GPU/Common/GPUCommonDef.h +++ b/GPU/Common/GPUCommonDef.h @@ -56,17 +56,14 @@ #define CONSTEXPR constexpr #define CONSTEXPRRET CONSTEXPR #if defined(__cplusplus) && __cplusplus >= 201703L - #define CONSTEXPRIF if constexpr #define CONSTEXPR17 constexpr #else - #define CONSTEXPRIF if #define CONSTEXPR17 #endif #else #define CON_DELETE #define CON_DEFAULT #define CONSTEXPR const - #define CONSTEXPRIF if #define CONSTEXPR17 #define CONSTEXPRRET #endif diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index b82e430f807a3..5b57248916ed2 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -148,10 +148,15 @@ class GPUCommonMath GPUd() CONSTEXPR17 static T nextMultipleOf(T val); #ifdef GPUCA_NOCOMPAT + GPUdi() static float Sum2() // Needed for legacy C++, For >=17 the below if constexpr handles the case + { + return 0.f; + } + template <typename... Args> GPUdi() static float Sum2(float w, Args... args) { - if constexpr (sizeof...(Args) == 0) { + if CONSTEXPR17 (sizeof...(Args) == 0) { return w * w; } else { return w * w + Sum2(args...); @@ -185,16 +190,13 @@ typedef GPUCommonMath CAMath; template <int I, class T> GPUdi() CONSTEXPR17 T GPUCommonMath::nextMultipleOf(T val) { - CONSTEXPRIF(I & (I - 1)) - { + if CONSTEXPR17 (I & (I - 1)) { T tmp = val % I; if (tmp) { val += I - tmp; } return val; - } - else - { + } else { return (val + I - 1) & ~(T)(I - 1); } return 0; // BUG: Cuda complains about missing return value with constexpr if diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 63e7087e5ad2e..9fc65c2c9d506 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -339,13 +339,10 @@ GPUdi() GPUTPCCompressionGatherKernels::Vec128* GPUTPCCompressionGatherKernels:: template <typename T, typename S> GPUdi() bool GPUTPCCompressionGatherKernels::isAlignedTo(const S* ptr) { - CONSTEXPRIF(alignof(S) >= alignof(T)) - { + if CONSTEXPR17 (alignof(S) >= alignof(T)) { static_cast<void>(ptr); return true; - } - else - { + } else { return reinterpret_cast<size_t>(ptr) % alignof(T) == 0; } return false; // BUG: Cuda complains about missing return value with constexpr if From 933275aa7f572cc73cd772f2364419a98ec9eaa0 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Nov 2020 11:09:56 +0100 Subject: [PATCH 1360/1751] DPL: more hiding of std::variant from ROOT --- .../include/Framework/DataDescriptorMatcher.h | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/Framework/Core/include/Framework/DataDescriptorMatcher.h b/Framework/Core/include/Framework/DataDescriptorMatcher.h index fc72f5d2f0d8c..829a627ba0254 100644 --- a/Framework/Core/include/Framework/DataDescriptorMatcher.h +++ b/Framework/Core/include/Framework/DataDescriptorMatcher.h @@ -20,14 +20,12 @@ #include <cstdint> #include <iosfwd> #include <string> +#if !defined(__CLING__) && !defined(__ROOTCLING__) #include <variant> +#endif #include <vector> -namespace o2 -{ -namespace framework -{ -namespace data_matcher +namespace o2::framework::data_matcher { /// Marks an empty item in the context @@ -48,7 +46,12 @@ struct ContextRef { /// We do not have any float in the value, because AFAICT there is no need for /// it in the O2 DataHeader, however we could add it later on. struct ContextElement { + +#if !defined(__CLING__) && !defined(__ROOTCLING__) using Value = std::variant<uint32_t, uint64_t, std::string, None>; +#else + using Value = None; +#endif std::string label; /// The name of the variable contained in this element. Value value = None{}; /// The actual contents of the element. }; @@ -115,11 +118,17 @@ class ValueHolder template <typename VISITOR> decltype(auto) visit(VISITOR visitor) const { +#if !defined(__CLING__) && !defined(__ROOTCLING__) return std::visit(visitor, mValue); +#else + return ContextRef{}; +#endif } protected: +#if !defined(__CLING__) && !defined(__ROOTCLING__) std::variant<T, ContextRef> mValue; +#endif }; /// Something which can be matched against a header::DataOrigin @@ -220,8 +229,12 @@ struct DescriptorMatcherTrait<header::DataHeader::SubSpecificationType> { using Matcher = SubSpecificationTypeValueMatcher; }; +#if !defined(__CLING__) && !defined(__ROOTCLING__) class DataDescriptorMatcher; using Node = std::variant<OriginValueMatcher, DescriptionValueMatcher, SubSpecificationTypeValueMatcher, std::unique_ptr<DataDescriptorMatcher>, ConstantValueMatcher, StartTimeValueMatcher>; +#else +using Node = ConstantValueMatcher; +#endif // A matcher for a given O2 Data Model descriptor. We use a variant to hold // the different kind of matchers so that we can have a hierarchy or @@ -276,9 +289,7 @@ class DataDescriptorMatcher Node mRight; }; -} // namespace data_matcher -} // namespace framework -} // namespace o2 +} // namespace o2::framework::data_matcher // This is to work around CLING issues when parsing // GCC 7.3.0 std::variant implementation as described by: From d141d532b9c25cf62dfc4c5402b886a115183428 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Tue, 17 Nov 2020 16:02:31 +0300 Subject: [PATCH 1361/1751] Fix TString::Tokenize-related memleaks --- Analysis/Core/src/HistogramManager.cxx | 10 +++++----- Analysis/Tasks/PWGDQ/dileptonEE.cxx | 2 +- Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 2 +- Analysis/Tasks/PWGDQ/tableMaker.cxx | 2 +- Analysis/Tasks/PWGDQ/tableMaker_pp.cxx | 2 +- Analysis/Tasks/PWGDQ/tableReader.cxx | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Analysis/Core/src/HistogramManager.cxx b/Analysis/Core/src/HistogramManager.cxx index f92ec71d19c80..77e8a8797ad6a 100644 --- a/Analysis/Core/src/HistogramManager.cxx +++ b/Analysis/Core/src/HistogramManager.cxx @@ -149,7 +149,7 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co // tokenize the title string; the user may include in it axis titles which will overwrite the defaults TString titleStr(title); - TObjArray* arr = titleStr.Tokenize(";"); + std::unique_ptr<TObjArray> arr(titleStr.Tokenize(";")); // mark required variables as being used if (varX > kNothing) { fUsedVars[varX] = kTRUE; @@ -364,7 +364,7 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co // tokenize the title string; the user may include in it axis titles which will overwrite the defaults TString titleStr(title); - TObjArray* arr = titleStr.Tokenize(";"); + std::unique_ptr<TObjArray> arr(titleStr.Tokenize(";")); // encode needed variable identifiers in a vector and push it to the std::list corresponding to the current histogram list std::vector<int> varVector; @@ -529,7 +529,7 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co // tokenize the title string; the user may include in it axis titles which will overwrite the defaults TString titleStr(title); - TObjArray* arr = titleStr.Tokenize(";"); + std::unique_ptr<TObjArray> arr(titleStr.Tokenize(";")); if (varW > kNothing) { fUsedVars[varW] = kTRUE; @@ -608,7 +608,7 @@ void HistogramManager::AddHistogram(const char* histClass, const char* hname, co // tokenize the title string; the user may include in it axis titles which will overwrite the defaults TString titleStr(title); - TObjArray* arr = titleStr.Tokenize(";"); + std::unique_ptr<TObjArray> arr(titleStr.Tokenize(";")); if (varW > kNothing) { fUsedVars[varW] = kTRUE; @@ -811,7 +811,7 @@ void HistogramManager::MakeAxisLabels(TAxis* ax, const char* labels) // add bin labels to an axis // TString labelsStr(labels); - TObjArray* arr = labelsStr.Tokenize(";"); + std::unique_ptr<TObjArray> arr(labelsStr.Tokenize(";")); for (int ib = 1; ib <= ax->GetNbins(); ++ib) { if (ib >= arr->GetEntries() + 1) { break; diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx index eaeb00d4575c0..ce0557fc76408 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -277,7 +277,7 @@ void DefineHistograms(o2::framework::OutputObj<HistogramManager> histMan, TStrin } VarManager::SetRunNumbers(kNRuns, runs); - TObjArray* arr = histClasses.Tokenize(";"); + std::unique_ptr<TObjArray> arr(histClasses.Tokenize(";")); for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { TString classStr = arr->At(iclass)->GetName(); diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx index 07e0865fa411e..5ce3dab9755ca 100644 --- a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -306,7 +306,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) } VarManager::SetRunNumbers(kNRuns, runs); - TObjArray* arr = histClasses.Tokenize(";"); + std::unique_ptr<TObjArray> arr(histClasses.Tokenize(";")); for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { TString classStr = arr->At(iclass)->GetName(); diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index d65a471e422fb..e839070c3ebcb 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -210,7 +210,7 @@ struct TableMaker { } VarManager::SetRunNumbers(kNRuns, runs); - TObjArray* arr = histClasses.Tokenize(";"); + std::unique_ptr<TObjArray> arr(histClasses.Tokenize(";")); for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { TString classStr = arr->At(iclass)->GetName(); diff --git a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx index e7df44d1ec1d4..4c9c9dadbb3a4 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx @@ -210,7 +210,7 @@ struct TableMaker_pp { } VarManager::SetRunNumbers(kNRuns, runs); - TObjArray* arr = histClasses.Tokenize(";"); + std::unique_ptr<TObjArray> arr(histClasses.Tokenize(";")); for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { TString classStr = arr->At(iclass)->GetName(); diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index acd92db6fdea5..d7390dc8e44b1 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -537,7 +537,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) } VarManager::SetRunNumbers(kNRuns, runs); - TObjArray* arr = histClasses.Tokenize(";"); + std::unique_ptr<TObjArray> arr(histClasses.Tokenize(";")); for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { TString classStr = arr->At(iclass)->GetName(); From 52d7f21571ae173a29f29725bf5086b6de5bc0f2 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 18 Nov 2020 13:25:05 +0100 Subject: [PATCH 1362/1751] Set T-bias of track T to 0 after fixing TPC electronics bias --- .../Vertexing/include/DetectorsVertexing/PVertexerParams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h index 42c45afdadbe4..fdaa52873dc1e 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -42,7 +42,7 @@ struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParam float maxTError = 0.2; ///< use min of vertex time error or this for nsigma evaluation float minTError = 0.003; ///< don't use error smaller than that (~BC/2/minNContributorsForFT0cut) float nSigmaTimeCut = 4.; ///< eliminate vertex if there is no FT0 signal within this cut - float timeBiasMS = -0.035; ///< relative bias in ms to add to TPCITS-based time stamp + float timeBiasMS = 0; ///< relative bias in ms to add to TPCITS-based time stamp // // stopping condition params From 9f2ef1604c8ab4dabdf7e827c91a2c8de258a5c2 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Nov 2020 12:44:17 +0100 Subject: [PATCH 1363/1751] DPL: Improve partialMatch(OutputSpec...) --- Framework/Core/src/DataSpecUtils.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index ab36bde400a47..0303059f2cec6 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -278,8 +278,11 @@ bool DataSpecUtils::partialMatch(InputSpec const& input, header::DataDescription bool DataSpecUtils::partialMatch(OutputSpec const& output, header::DataDescription const& description) { - auto dataType = DataSpecUtils::asConcreteDataTypeMatcher(output); - return dataType.description == description; + try { + return DataSpecUtils::asConcreteDataTypeMatcher(output).description == description; + } catch (...) { + return false; + } } struct MatcherInfo { From 17c2ece8e7986181e9bd8e8932d4450bc18356f5 Mon Sep 17 00:00:00 2001 From: fcolamar <fabio.colamaria@ba.infn.it> Date: Wed, 18 Nov 2020 18:40:53 +0100 Subject: [PATCH 1364/1751] Added column for Phi to 2- and 3-prong HF candidates (#4856) --- Analysis/Core/include/Analysis/RecoDecay.h | 20 ++++++++++++++++++- .../include/Analysis/HFSecondaryVertex.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Analysis/Core/include/Analysis/RecoDecay.h b/Analysis/Core/include/Analysis/RecoDecay.h index 530b920724d08..4d164452ef6ca 100644 --- a/Analysis/Core/include/Analysis/RecoDecay.h +++ b/Analysis/Core/include/Analysis/RecoDecay.h @@ -169,6 +169,24 @@ class RecoDecay return std::atanh(mom[2] / E(mom, mass)); } + /// Calculates azimuthal angle from x and y momentum components. + /// \param px,py {x, y} momentum components + /// \return azimuthal angle + static double Phi(double px, double py) + { + // phi = pi+TMath::Atan2(-py,-px) + return (double)(o2::constants::math::PI + std::atan2(-py, -px)); + } + + /// Calculates azimuthal angle from 3-(or 2-)momenta. + /// \param args pack of 3-(or 2-)momentum arrays + /// \return azimuthal angle + template <std::size_t N, typename T> + static double Phi(const array<T, N>& vec) + { + return Phi(vec[0], vec[1]); + } + /// Calculates cosine of pointing angle. /// \param posPV {x, y, z} position of the primary vertex /// \param posSV {x, y, z} position of the secondary vertex @@ -521,7 +539,7 @@ class RecoDecay static bool isMCMatchedDecayGen(const T& particlesMC, const U& candidate, int PDGParticle, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false) { //Printf("MC Gen.: Expected particle PDG: %d", PDGParticle); - int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle + int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle int indexDaughterFirst = 0; // index of the first daughter int indexDaughterLast = 0; // index of the last daughter // Check the PDG code of the particle. diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 8ee186e65b55d..c3520064b443f 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -107,6 +107,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) { return RecoD DECLARE_SOA_DYNAMIC_COLUMN(P2, p2, [](float px, float py, float pz) { return RecoDecay::P2(px, py, pz); }); DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, [](float px, float py, float pz) { return array{px, py, pz}; }); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) { return RecoDecay::Eta(array{px, py, pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) { return RecoDecay::Phi(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(Y, y, [](float px, float py, float pz, double m) { return RecoDecay::Y(array{px, py, pz}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(E, e, [](float px, float py, float pz, double m) { return RecoDecay::E(px, py, pz, m); }); DECLARE_SOA_DYNAMIC_COLUMN(E2, e2, [](float px, float py, float pz, double m) { return RecoDecay::E2(px, py, pz, m); }); @@ -228,6 +229,7 @@ DECLARE_SOA_TABLE(HfCandProng2Base, "AOD", "HFCANDP2BASE", hf_cand::CPAXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py>, hf_cand::Ct<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, hf_cand::Eta<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::Phi<hf_cand_prong2::Px, hf_cand_prong2::Py>, hf_cand::Y<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, hf_cand::E<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, hf_cand::E2<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>); @@ -344,6 +346,7 @@ DECLARE_SOA_TABLE(HfCandProng3Base, "AOD", "HFCANDP3BASE", hf_cand::CPAXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py>, hf_cand::Ct<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, hf_cand::Eta<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::Phi<hf_cand_prong3::Px, hf_cand_prong3::Py>, hf_cand::Y<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, hf_cand::E<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, hf_cand::E2<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>); From 3a1a8b3b6d4bf76cf9e45c73d715a2d1b6772999 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 18 Nov 2020 10:14:34 +0100 Subject: [PATCH 1365/1751] Don't use FairLogger directly --- .../include/SimulationDataFormat/DigitizationContext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/DigitizationContext.h b/DataFormats/simulation/include/SimulationDataFormat/DigitizationContext.h index 8fb7aa7ed9756..2371389056c39 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/DigitizationContext.h +++ b/DataFormats/simulation/include/SimulationDataFormat/DigitizationContext.h @@ -18,7 +18,7 @@ #include "CommonDataFormat/BunchFilling.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DataFormatsParameters/GRPObject.h" -#include <FairLogger.h> +#include <GPUCommonLogger.h> namespace o2 { From 60d48b9aa16db053198473521f57f019bb115aeb Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 18 Nov 2020 10:20:31 +0100 Subject: [PATCH 1366/1751] GPU QA: Improve handlling of reference X position for comparison --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 31 +++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 6b9a4c558cbfd..d633204c2d288 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -208,6 +208,7 @@ int GPUQA::initColors() } static constexpr Color_t defaultColorNUms[COLORCOUNT] = {kRed, kBlue, kGreen, kMagenta, kOrange, kAzure, kBlack, kYellow, kGray, kTeal, kSpring, kPink}; +#define TRACK_EXPECTED_REFERENCE_X_DEFAULT 81 #ifdef GPUCA_TPC_GEOMETRY_O2 inline unsigned int GPUQA::GetNMCCollissions() { @@ -257,7 +258,7 @@ inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return label.fWei inline int GPUQA::FakeLabelID(int id) { return id < 0 ? id : (-2 - id); } inline int GPUQA::AbsLabelID(int id) { return id >= 0 ? id : (-id - 2); } inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking && GetNMCLabels() && GetNMCTracks(0); } -#define TRACK_EXPECTED_REFERENCE_X 81 +#define TRACK_EXPECTED_REFERENCE_X TRACK_EXPECTED_REFERENCE_X_DEFAULT #endif template <class T> inline auto& GPUQA::GetMCTrackObj(T& obj, const GPUQA::mcLabelI_t& l) @@ -1158,23 +1159,33 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx prop.SetTrack(¶m, alpha); bool inFlyDirection = 0; -#ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (mTracking->GetParam().par.continuousMaxTimeBin ? 0 : ((param.Z() - mc1.z) * (param.Z() - mc1.z))) > (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X)) * (5 + abs(81 - TRACK_EXPECTED_REFERENCE_X))) { -#else // Consider Z offset (pseudo-tf mc tracks have shifted z) - if (mConfig.strict && (param.X() - mclocal[0]) * (param.X() - mclocal[0]) + (param.Y() - mclocal[1]) * (param.Y() - mclocal[1]) + (param.Z() + param.TZOffset() - mc1.z) * (param.Z() + param.TZOffset() - mc1.z) > 25) { // TODO: fix TZOffset + if (mConfig.strict) { + const float dx = param.X() - std::max<float>(mclocal[0], TRACK_EXPECTED_REFERENCE_X_DEFAULT); // Limit distance check if the O2 MC position is farther inside than the AliRoot MC position. + const float dy = param.Y() - mclocal[1]; +#ifdef GPUCA_TPC_GEOMETRY_O2 + float dz = mTracking->GetParam().par.continuousMaxTimeBin ? 0 : (param.Z() - mc1.z); +#else + float dz = param.Z() + param.TZOffset() - mc1.z; #endif - continue; + if (dx * dx + dy * dy + dz * dz > 5.f * 5.f) { + continue; + } } if (prop.PropagateToXAlpha(mclocal[0], alpha, inFlyDirection)) { continue; } -#ifdef GPUCA_TPC_GEOMETRY_O2 // ignore z here, larger difference in X due to shifted reference - if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || (mTracking->GetParam().par.continuousMaxTimeBin == 0 && fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f))) { // TODO: fix TZOffset here + { + float limit = mConfig.strict ? 1.f : 4.f; + float dy = param.Y() - mclocal[1]; +#ifdef GPUCA_TPC_GEOMETRY_O2 + float dz = mTracking->GetParam().par.continuousMaxTimeBin ? 0 : (param.Z() - mc1.z); #else - if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || fabsf(param.Z() + param.TZOffset() - mc1.z) > (mConfig.strict ? 1.f : 4.f)) { // TODO: fix TZOffset here + float dz = param.Z() + param.TZOffset() - mc1.z; #endif - continue; + if (fabsf(dy) > limit || fabsf(dz) > limit) { + continue; + } } float charge = mc1.charge > 0 ? 1.f : -1.f; From c1ed320bbf10cc6f5d39b41a60313b7b41b759e6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 18 Nov 2020 10:28:52 +0100 Subject: [PATCH 1367/1751] GPU QA: Early reject all mc tracks with primary daughter particles --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index d633204c2d288..fff9cde2d9926 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -994,7 +994,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx const float& mcphi = mc2.phi; const float& mceta = mc2.eta; - if (info.prim && info.primDaughters) { + if (info.primDaughters) { continue; } if (mc2.nWeightCls < MIN_WEIGHT_CLS) { @@ -1079,6 +1079,9 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx const mcInfo_t& mc1 = GetMCTrack(mTrackMCLabels[i]); const additionalMCParameters& mc2 = GetMCTrackObj(mMCParam, mTrackMCLabels[i]); + if (mc1.primDaughters) { + continue; + } if (!tracksExternal) { if (!mTracking->mIOPtrs.mergedTracks[i].OK()) { continue; @@ -1108,9 +1111,9 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx if (mc2.nWeightCls < MIN_WEIGHT_CLS) { continue; } - if (mConfig.resPrimaries == 1 && (!mc1.prim || mc1.primDaughters)) { + if (mConfig.resPrimaries == 1 && !mc1.prim) { continue; - } else if (mConfig.resPrimaries == 2 && (mc1.prim || mc1.primDaughters)) { + } else if (mConfig.resPrimaries == 2 && mc1.prim) { continue; } if (GetMCTrackObj(mTrackMCLabelsReverse, mTrackMCLabels[i]) != (int)i) { From e46db6b5a8411b9493f4c1b0dd7d01ea51576afc Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 18 Nov 2020 09:13:32 +0100 Subject: [PATCH 1368/1751] GPU QA: Load track t0 from collisionContext to compute correct deltaZ in resolution plots --- GPU/GPUTracking/SliceTracker/GPUTPCMCInfo.h | 3 ++ GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 52 ++++++++++++++------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCMCInfo.h b/GPU/GPUTracking/SliceTracker/GPUTPCMCInfo.h index 810ce33f67422..107ef6e472bd1 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCMCInfo.h +++ b/GPU/GPUTracking/SliceTracker/GPUTPCMCInfo.h @@ -30,6 +30,9 @@ struct GPUTPCMCInfo { float pY; float pZ; float genRadius; +#ifdef GPUCA_TPC_GEOMETRY_O2 + float t0; +#endif }; } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index fff9cde2d9926..2cf7826dd72fd 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -49,11 +49,15 @@ #ifdef HAVE_O2HEADERS #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" +#include "TPCFastTransform.h" #endif #ifdef GPUCA_O2_LIB +#include "DetectorsRaw/HBFUtils.h" #include "DataFormatsTPC/TrackTPC.h" +#include "DataFormatsTPC/Constants.h" #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/TrackReference.h" +#include "SimulationDataFormat/DigitizationContext.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsCommonDataFormats/NameConf.h" #include "TPDGCode.h" @@ -599,7 +603,15 @@ int GPUQA::InitQA(int tasks) mMCInfos.resize(nSimEvents); mNColTracks.resize(nSimEvents); std::vector<int> refId; + + auto dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + auto evrec = dc->getEventRecords(); + for (int i = 0; i < nSimEvents; i++) { + auto ir = evrec[i]; + auto ir0 = o2::raw::HBFUtils::Instance().getFirstIRofTF(ir); + float timebin = (float)ir.differenceInBC(ir0) / o2::tpc::constants::LHCBCPERTIMEBIN; + treeSim->GetEntry(i); const std::vector<o2::MCTrack>& tracks = *tracksX; const std::vector<o2::TrackReference>& trackRefs = *trackRefsX; @@ -641,6 +653,7 @@ int GPUQA::InitQA(int tasks) info.prim = 1; info.primDaughters = 0; info.pid = pid; + info.t0 = timebin; if (refId[j] >= 0) { const auto& trkRef = trackRefs[refId[j]]; info.x = trkRef.X(); @@ -1122,6 +1135,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx GPUTPCGMTrackParam param; float alpha = 0.f; + int side; if (tracksExternal) { #ifdef GPUCA_O2_LIB for (int k = 0; k < 5; k++) { @@ -1131,11 +1145,14 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx param.Cov()[k] = (*tracksExternal)[i].getCov()[k]; } param.X() = (*tracksExternal)[i].getX(); + param.TZOffset() = (*tracksExternal)[i].getTime0(); alpha = (*tracksExternal)[i].getAlpha(); + side = (*tracksExternal)[i].hasBothSidesClusters() ? 2 : ((*tracksExternal)[i].hasCSideClusters() ? 1 : 0); #endif } else { param = mTracking->mIOPtrs.mergedTracks[i].GetParam(); alpha = mTracking->mIOPtrs.mergedTracks[i].GetAlpha(); + side = mTracking->mIOPtrs.mergedTracks[i].CCE() ? 2 : (mTracking->mIOPtrs.mergedTracks[i].CSide() ? 1 : 0); } float mclocal[4]; // Rotated x,y,Px,Py mc-coordinates - the MC data should be rotated since the track is propagated best along x @@ -1160,16 +1177,25 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx continue; } + auto getdz = [this, &mclocal, ¶m, &mc1, &side]() { + if (!mTracking->GetParam().par.continuousMaxTimeBin) { + return param.Z() - mc1.z; + } +#ifdef GPUCA_TPC_GEOMETRY_O2 + if (!mTracking->GetParam().par.earlyTpcTransform) { + float shift = side == 2 ? 0 : mTracking->GetTPCTransform()->convDeltaTimeToDeltaZinTimeFrame(side * GPUChainTracking::NSLICES / 2, param.GetTZOffset() - mc1.t0); + return param.GetZ() + shift - mc1.z; + } +#endif + return param.Z() + param.TZOffset() - mc1.z; + }; + prop.SetTrack(¶m, alpha); bool inFlyDirection = 0; if (mConfig.strict) { const float dx = param.X() - std::max<float>(mclocal[0], TRACK_EXPECTED_REFERENCE_X_DEFAULT); // Limit distance check if the O2 MC position is farther inside than the AliRoot MC position. const float dy = param.Y() - mclocal[1]; -#ifdef GPUCA_TPC_GEOMETRY_O2 - float dz = mTracking->GetParam().par.continuousMaxTimeBin ? 0 : (param.Z() - mc1.z); -#else - float dz = param.Z() + param.TZOffset() - mc1.z; -#endif + const float dz = getdz(); if (dx * dx + dy * dy + dz * dz > 5.f * 5.f) { continue; } @@ -1178,23 +1204,13 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx if (prop.PropagateToXAlpha(mclocal[0], alpha, inFlyDirection)) { continue; } - { - float limit = mConfig.strict ? 1.f : 4.f; - float dy = param.Y() - mclocal[1]; -#ifdef GPUCA_TPC_GEOMETRY_O2 - float dz = mTracking->GetParam().par.continuousMaxTimeBin ? 0 : (param.Z() - mc1.z); -#else - float dz = param.Z() + param.TZOffset() - mc1.z; -#endif - if (fabsf(dy) > limit || fabsf(dz) > limit) { - continue; - } + if (fabsf(param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || fabsf(getdz()) > (mConfig.strict ? 1.f : 4.f)) { + continue; } - float charge = mc1.charge > 0 ? 1.f : -1.f; float deltaY = param.GetY() - mclocal[1]; - float deltaZ = param.GetZ() + param.TZOffset() - mc1.z; // TODO: fix TZOffset here + float deltaZ = getdz(); float deltaPhiNative = param.GetSinPhi() - mclocal[3] / mc2.pt; float deltaPhi = std::asin(param.GetSinPhi()) - std::atan2(mclocal[3], mclocal[2]); float deltaLambdaNative = param.GetDzDs() - mc1.pZ / mc2.pt; From 411d66b5a8dfc50c96d88d42d7128bfc608ed439 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 18 Nov 2020 11:01:50 +0100 Subject: [PATCH 1369/1751] GPU QA: Distinguish between primaries and secondaries for O2 input --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 2cf7826dd72fd..19c72101abff1 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -585,6 +585,8 @@ int GPUQA::InitQA(int tasks) } #ifdef GPUCA_O2_LIB + static constexpr float PRIM_MAX_T = 0.01f; + TFile fileSim(o2::base::NameConf::getMCKinematicsFileName("o2sim").c_str()); TTree* treeSim = (TTree*)fileSim.Get("o2sim"); std::vector<o2::MCTrack>* tracksX; @@ -650,8 +652,16 @@ int GPUQA::InitQA(int tasks) } info.charge = particle ? particle->Charge() : 0; - info.prim = 1; + info.prim = trk.T() < PRIM_MAX_T; info.primDaughters = 0; + if (trk.getFirstDaughterTrackId() != -1) { + for (int k = trk.getFirstDaughterTrackId(); k <= trk.getLastDaughterTrackId(); k++) { + if (tracks[k].T() < PRIM_MAX_T) { + info.primDaughters = 1; + break; + } + } + } info.pid = pid; info.t0 = timebin; if (refId[j] >= 0) { From e16f98fdfeae65c158f6bbdb15199ef20b2536f9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 18 Nov 2020 11:33:30 +0100 Subject: [PATCH 1370/1751] GPU QA: Improve selection of clone track to use for resolution histogram --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 19c72101abff1..72cd955acabac 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -46,10 +46,10 @@ #include "GPUO2DataTypes.h" #include "GPUParam.inc" #include "GPUTPCClusterRejection.h" +#include "TPCFastTransform.h" #ifdef HAVE_O2HEADERS #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" -#include "TPCFastTransform.h" #endif #ifdef GPUCA_O2_LIB #include "DetectorsRaw/HBFUtils.h" @@ -875,7 +875,18 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx GetMCTrackObj(mRecTracks, label)++; if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) { int& revLabel = GetMCTrackObj(mTrackMCLabelsReverse, label); - if (revLabel == -1 || !mTracking->mIOPtrs.mergedTracks[revLabel].OK() || (mTracking->mIOPtrs.mergedTracks[i].OK() && fabsf(mTracking->mIOPtrs.mergedTracks[i].GetParam().GetZ()) < fabsf(mTracking->mIOPtrs.mergedTracks[revLabel].GetParam().GetZ()))) { + const auto* trks = mTracking->mIOPtrs.mergedTracks; + bool comp; + if (revLabel == -1) { + comp = true; + } else if (mTracking->GetParam().par.earlyTpcTransform) { + comp = fabsf(trks[i].GetParam().GetZ() + trks[i].GetParam().GetTZOffset()) < fabsf(trks[revLabel].GetParam().GetZ() + trks[revLabel].GetParam().GetTZOffset()); + } else { + float shift1 = mTracking->GetTPCTransform()->convDeltaTimeToDeltaZinTimeFrame(trks[i].CSide() * GPUChainTracking::NSLICES / 2, trks[i].GetParam().GetTZOffset()); + float shift2 = mTracking->GetTPCTransform()->convDeltaTimeToDeltaZinTimeFrame(trks[revLabel].CSide() * GPUChainTracking::NSLICES / 2, trks[revLabel].GetParam().GetTZOffset()); + comp = fabsf(trks[i].GetParam().GetZ() + shift1) < fabsf(trks[revLabel].GetParam().GetZ() + shift2); + } + if (revLabel == -1 || !trks[revLabel].OK() || (trks[i].OK() && comp)) { revLabel = i; } } From 20dd2b5508141e5a03b85f883bf950ade7bafbcd Mon Sep 17 00:00:00 2001 From: vfeuilla <71069003+vfeuilla@users.noreply.github.com> Date: Wed, 18 Nov 2020 19:58:25 +0100 Subject: [PATCH 1371/1751] addition of a TableMaker for Muon Only (#4864) --- Analysis/Tasks/PWGDQ/CMakeLists.txt | 5 + Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx | 172 +++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx diff --git a/Analysis/Tasks/PWGDQ/CMakeLists.txt b/Analysis/Tasks/PWGDQ/CMakeLists.txt index 866d28ff3c8f1..470f00fd682e6 100644 --- a/Analysis/Tasks/PWGDQ/CMakeLists.txt +++ b/Analysis/Tasks/PWGDQ/CMakeLists.txt @@ -22,3 +22,8 @@ o2_add_dpl_workflow(table-maker-pp SOURCES tableMaker_pp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(table-maker-muon-pp + SOURCES tableMakerMuon_pp.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx b/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx new file mode 100644 index 0000000000000..d8fdc7b1c0816 --- /dev/null +++ b/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx @@ -0,0 +1,172 @@ +// 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/Multiplicity.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" +#include "Analysis/TriggerAliases.h" +#include "Analysis/ReducedInfoTables.h" +#include "Analysis/VarManager.h" +#include "Analysis/HistogramManager.h" +#include "Analysis/AnalysisCut.h" +#include "Analysis/AnalysisCompositeCut.h" +#include "PID/PIDResponse.h" +#include "Analysis/TrackSelectionTables.h" +#include <iostream> + +using std::cout; +using std::endl; + +using namespace o2; +using namespace o2::framework; +//using namespace o2::framework::expressions; +using namespace o2::aod; + +using MyEvents = soa::Join<aod::Collisions, aod::EvSels>; + +// 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 gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; + +struct TableMakerMuon_pp { + + Produces<ReducedEvents> event; + Produces<ReducedEventsExtended> eventExtended; + Produces<ReducedEventsVtxCov> eventVtxCov; + Produces<ReducedTracks> trackBasic; + Produces<ReducedMuons> muonBasic; + Produces<ReducedMuonsExtended> muonExtended; + + float* fValues; + + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; + + // TODO: Filters should be used to make lowest level selection. The additional more restrictive cuts should be defined via the AnalysisCuts + // TODO: Multiple event selections can be applied and decisions stored in the reducedevent::tag + AnalysisCompositeCut* fEventCut; + // TODO: Multiple track selections can be applied and decisions stored in the reducedtrack::filteringFlags + + // TODO a few of the important muon variables in the central data model are dynamic columns so not usable in expressions (e.g. eta, phi) + // Update the data model to have them as expression columns + Partition<aod::Muons> muonSelectedTracks = o2::aod::muon::pt >= 0.5f; // For pp collisions a 0.5 GeV/c pp cuts is defined + + void init(o2::framework::InitContext&) + { + fValues = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms("Event_BeforeCuts;Event_AfterCuts;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + DefineCuts(); + } + + void DefineCuts() + { + fEventCut = new AnalysisCompositeCut(true); + AnalysisCut* eventVarCut = new AnalysisCut(); + eventVarCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + eventVarCut->AddCut(VarManager::kIsINT7, 0.5, 1.5); // require kINT7 + fEventCut->AddCut(eventVarCut); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvents::iterator const& collision, aod::MuonClusters const& clustersMuon, aod::Muons const& tracksMuon, aod::BCs const& bcs) + { + uint64_t tag = 0; + uint32_t triggerAliases = 0; + for (int i = 0; i < kNaliases; i++) { + if (collision.alias()[i] > 0) { + triggerAliases |= (uint32_t(1) << i); + } + } + + VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); + VarManager::FillEvent<gkEventFillMap>(collision, fValues); // extract event information and place it in the fgValues array + fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event + + if (!fEventCut->IsSelected(fValues)) { + return; + } + + fHistMan->FillHistClass("Event_AfterCuts", fValues); + + event(tag, collision.bc().runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib()); + eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), triggerAliases, 0.0f); + eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + + uint64_t trackFilteringTag = 0; + + muonBasic.reserve(muonSelectedTracks.size()); + muonExtended.reserve(muonSelectedTracks.size()); + for (auto& muon : muonSelectedTracks) { + // TODO: add proper information for muon tracks + if (muon.bcId() != collision.bcId()) { + continue; + } + // TODO: the trackFilteringTag will not be needed to encode whether the track is a muon since there is a dedicated table for muons + trackFilteringTag |= (uint64_t(1) << 0); // this is a MUON arm track + muonBasic(event.lastIndex(), trackFilteringTag, muon.pt(), muon.eta(), muon.phi(), muon.charge()); + muonExtended(muon.inverseBendingMomentum(), muon.thetaX(), muon.thetaY(), muon.zMu(), muon.bendingCoor(), muon.nonBendingCoor(), muon.chi2(), muon.chi2MatchTrigger()); + } + } + + void DefineHistograms(TString histClasses) + { + 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 + } + } // end loop over histogram classes + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<TableMakerMuon_pp>("table-maker-muon-pp")}; +} From 1b90e5654fee404ebee2bba6e334744e2e7d6faa Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Tue, 10 Nov 2020 17:58:20 +0100 Subject: [PATCH 1372/1751] Use link ID 15 when encoding the MID UL output --- Detectors/MUON/MID/Raw/include/MIDRaw/FEEIdConfig.h | 4 ++++ Detectors/MUON/MID/Raw/src/Encoder.cxx | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/FEEIdConfig.h b/Detectors/MUON/MID/Raw/include/MIDRaw/FEEIdConfig.h index efb24922d6753..6c0f057c4a90c 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/FEEIdConfig.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/FEEIdConfig.h @@ -55,6 +55,10 @@ class FEEIdConfig std::unordered_map<uint32_t, uint16_t> mGBTIdToFeeId; /// Correspondence between GBT Id and FeeId }; +namespace raw +{ +static constexpr uint8_t sUserLogicLinkID = 15; +} } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/Encoder.cxx b/Detectors/MUON/MID/Raw/src/Encoder.cxx index e203800c20d05..97aa55913797e 100644 --- a/Detectors/MUON/MID/Raw/src/Encoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Encoder.cxx @@ -36,7 +36,7 @@ void Encoder::init(const char* filename, bool perLink, int verbosity, bool debug int lcnt = 0; for (auto& gbtId : gbtIds) { auto feeId = mFEEIdConfig.getFeeId(gbtId); - mRawWriter.registerLink(feeId, mFEEIdConfig.getCRUId(gbtId), mFEEIdConfig.getLinkId(gbtId), mFEEIdConfig.getEndPointId(gbtId), perLink ? fmt::format("{:s}_L{:d}.raw", filename, lcnt) : fmt::format("{:s}.raw", filename)); + mRawWriter.registerLink(feeId, mFEEIdConfig.getCRUId(gbtId), raw::sUserLogicLinkID, mFEEIdConfig.getEndPointId(gbtId), perLink ? fmt::format("{:s}_L{:d}.raw", filename, lcnt) : fmt::format("{:s}.raw", filename)); mGBTEncoders[feeId].setFeeId(feeId); mGBTEncoders[feeId].setMask(masks.getMask(feeId)); mGBTIds[feeId] = gbtId; @@ -95,7 +95,7 @@ void Encoder::writePayload(uint16_t feeId, const InteractionRecord& ir) // Then we flush the received data mGBTEncoders[feeId].flush(buf, ir); completeWord(buf); - mRawWriter.addData(feeId, mFEEIdConfig.getCRUId(mGBTIds[feeId]), mFEEIdConfig.getLinkId(mGBTIds[feeId]), mFEEIdConfig.getEndPointId(mGBTIds[feeId]), ir, buf); + mRawWriter.addData(feeId, mFEEIdConfig.getCRUId(mGBTIds[feeId]), raw::sUserLogicLinkID, mFEEIdConfig.getEndPointId(mGBTIds[feeId]), ir, buf); } void Encoder::finalize(bool closeFile) From 03445ae9b9804ff273f8453e7b05957b136b0d91 Mon Sep 17 00:00:00 2001 From: dstocco <diego.stocco@cern.ch> Date: Tue, 27 Oct 2020 14:00:43 +0100 Subject: [PATCH 1373/1751] Hide MID decoder implementation details This allows to chose the decoder at run-time, depending on the data header --- Detectors/MUON/MID/QC/exe/raw-checker.cxx | 76 ++-- Detectors/MUON/MID/Raw/CMakeLists.txt | 3 +- Detectors/MUON/MID/Raw/exe/rawdump.cxx | 57 +-- .../MUON/MID/Raw/include/MIDRaw/Decoder.h | 40 +- .../MID/Raw/include/MIDRaw/ELinkDecoder.h | 70 +++- .../MID/Raw/include/MIDRaw/GBTBareDecoder.h | 75 ---- .../MUON/MID/Raw/include/MIDRaw/GBTDecoder.h | 54 +++ .../MID/Raw/include/MIDRaw/GBTOutputHandler.h | 22 +- .../Raw/include/MIDRaw/GBTUserLogicDecoder.h | 70 ---- Detectors/MUON/MID/Raw/src/Decoder.cxx | 97 +++-- Detectors/MUON/MID/Raw/src/ELinkDecoder.cxx | 67 +++- Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx | 111 ------ Detectors/MUON/MID/Raw/src/GBTDecoder.cxx | 362 ++++++++++++++++++ .../MUON/MID/Raw/src/GBTOutputHandler.cxx | 47 +-- .../MUON/MID/Raw/src/GBTUserLogicDecoder.cxx | 65 ---- Detectors/MUON/MID/Raw/test/bench_Raw.cxx | 24 +- Detectors/MUON/MID/Raw/test/testRaw.cxx | 17 +- .../include/MIDWorkflow/RawDecoderSpec.h | 4 +- .../MUON/MID/Workflow/src/RawDecoderSpec.cxx | 43 +-- .../Workflow/src/raw-to-digits-workflow.cxx | 4 +- 20 files changed, 715 insertions(+), 593 deletions(-) delete mode 100644 Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h create mode 100644 Detectors/MUON/MID/Raw/include/MIDRaw/GBTDecoder.h delete mode 100644 Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h delete mode 100644 Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx create mode 100644 Detectors/MUON/MID/Raw/src/GBTDecoder.cxx delete mode 100644 Detectors/MUON/MID/Raw/src/GBTUserLogicDecoder.cxx diff --git a/Detectors/MUON/MID/QC/exe/raw-checker.cxx b/Detectors/MUON/MID/QC/exe/raw-checker.cxx index 4dc2ccc56502e..da7adc2ed9e1b 100644 --- a/Detectors/MUON/MID/QC/exe/raw-checker.cxx +++ b/Detectors/MUON/MID/QC/exe/raw-checker.cxx @@ -15,13 +15,19 @@ #include <iostream> #include <fstream> +#include <sstream> +#include <string> +#include <vector> #include "boost/program_options.hpp" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsMID/ROFRecord.h" +#include "MIDQC/RawDataChecker.h" #include "MIDRaw/CrateMasks.h" +#include "MIDRaw/Decoder.h" #include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/FEEIdConfig.h" -#include "MIDRaw/Decoder.h" +#include "MIDRaw/LocalBoardRO.h" #include "MIDRaw/RawFileReader.h" -#include "MIDQC/RawDataChecker.h" namespace po = boost::program_options; @@ -48,21 +54,21 @@ std::string getOutFilename(const char* inFilename, const char* outDir) return outFilename; } -template <typename GBTDECODER> int process(po::variables_map& vm) { std::vector<std::string> inputfiles{vm["input"].as<std::vector<std::string>>()}; - o2::mid::Decoder<GBTDECODER> decoder; + std::unique_ptr<o2::mid::Decoder> decoder{nullptr}; o2::mid::RawDataChecker checker; + + o2::mid::FEEIdConfig feeIdConfig; if (vm.count("feeId-config-file")) { - o2::mid::FEEIdConfig feeIdConfig(vm["feeId-config-file"].as<std::string>().c_str()); - decoder.setFeeIdConfig(feeIdConfig); + feeIdConfig = o2::mid::FEEIdConfig(vm["feeId-config-file"].as<std::string>().c_str()); } + o2::mid::ElectronicsDelay electronicsDelay; if (vm.count("electronics-delay-file")) { - o2::mid::ElectronicsDelay electronicsDelay = o2::mid::readElectronicsDelay(vm["electronics-delay-file"].as<std::string>().c_str()); - decoder.setElectronicsDelay(electronicsDelay); + electronicsDelay = o2::mid::readElectronicsDelay(vm["electronics-delay-file"].as<std::string>().c_str()); checker.setElectronicsDelay(electronicsDelay); } @@ -70,14 +76,11 @@ int process(po::variables_map& vm) checker.setSyncTrigger(vm["sync-trigger"].as<uint32_t>()); } + o2::mid::CrateMasks crateMasks; if (vm.count("crate-masks-file")) { - o2::mid::CrateMasks crateMasks(vm["crate-masks-file"].as<std::string>().c_str()); - decoder.setCrateMasks(crateMasks); - checker.init(crateMasks); - } else { - checker.init(o2::mid::CrateMasks()); + crateMasks = o2::mid::CrateMasks(vm["crate-masks-file"].as<std::string>().c_str()); } - decoder.init(true); + checker.init(crateMasks); auto nHBs = vm["nHBs"].as<unsigned long int>(); auto nMaxErrors = vm["max-errors"].as<unsigned long int>(); @@ -106,36 +109,33 @@ int process(po::variables_map& vm) unsigned long int iHB = 0; std::stringstream summary; while (rawFileReader.readHB(vm.count("only-closed-HBs") > 0)) { - decoder.process(rawFileReader.getData()); + if (!decoder) { + auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(rawFileReader.getData().data()); + decoder = o2::mid::createDecoder(*rdhPtr, true, electronicsDelay, crateMasks, feeIdConfig); + } + decoder->process(rawFileReader.getData()); rawFileReader.clear(); size_t offset = data.size(); - data.insert(data.end(), decoder.getData().begin(), decoder.getData().end()); - for (auto& rof : decoder.getROFRecords()) { + data.insert(data.end(), decoder->getData().begin(), decoder->getData().end()); + for (auto& rof : decoder->getROFRecords()) { rofRecords.emplace_back(rof.interactionRecord, rof.eventType, rof.firstEntry + offset, rof.nEntries); } o2::InteractionRecord hb(0, iHB); - hbRecords.emplace_back(hb, o2::mid::EventType::Noise, offset, decoder.getData().size()); + hbRecords.emplace_back(hb, o2::mid::EventType::Noise, offset, decoder->getData().size()); ++iHB; if ((nHBs > 0 && iHB >= nHBs)) { break; } - bool isComplete = true; //(vm.count("bare") && decoder.isComplete()); - // Partial check - if (isComplete) { - // The check assumes that we have all data corresponding to one event. - // However this might not be true since we read one HB at the time. - // So we must test that the event was fully read before running the check. - if (!checker.process(data, rofRecords, hbRecords)) { - outFile << checker.getDebugMessage() << "\n"; - } - data.clear(); - rofRecords.clear(); - hbRecords.clear(); - - if (checker.getNEventsFaulty() >= nMaxErrors) { - summary << "Too many errors found: abort check!\n"; - break; - } + if (!checker.process(data, rofRecords, hbRecords)) { + outFile << checker.getDebugMessage() << "\n"; + } + data.clear(); + rofRecords.clear(); + hbRecords.clear(); + + if (checker.getNEventsFaulty() >= nMaxErrors) { + summary << "Too many errors found: abort check!\n"; + break; } } // Check the remaining data @@ -169,7 +169,6 @@ int main(int argc, char* argv[]) ("crate-masks-file", po::value<std::string>(),"Filename with crate masks") ("electronics-delay-file", po::value<std::string>(),"Filename with electronics delay") ("output-dir", po::value<std::string>()->default_value(""),"Output directory") - ("bare", po::value<bool>()->implicit_value(true),"Use bare decoder") ("sync-trigger", po::value<unsigned int>(),"Trigger used for synchronisation (default is orbit 0x1)"); @@ -197,8 +196,5 @@ int main(int argc, char* argv[]) return 1; } - if (vm.count("bare")) { - return process<o2::mid::GBTBareDecoder>(vm); - } - return process<o2::mid::GBTUserLogicDecoder>(vm); + return process(vm); } diff --git a/Detectors/MUON/MID/Raw/CMakeLists.txt b/Detectors/MUON/MID/Raw/CMakeLists.txt index 714fda4cd856c..93ca140fbaa52 100644 --- a/Detectors/MUON/MID/Raw/CMakeLists.txt +++ b/Detectors/MUON/MID/Raw/CMakeLists.txt @@ -18,9 +18,8 @@ o2_add_library( src/ELinkDecoder.cxx src/Encoder.cxx src/FEEIdConfig.cxx - src/GBTBareDecoder.cxx + src/GBTDecoder.cxx src/GBTOutputHandler.cxx - src/GBTUserLogicDecoder.cxx src/GBTUserLogicEncoder.cxx src/LocalBoardRO.cxx src/DecodedDataAggregator.cxx diff --git a/Detectors/MUON/MID/Raw/exe/rawdump.cxx b/Detectors/MUON/MID/Raw/exe/rawdump.cxx index 3210b66b6c440..e61651bd32cb4 100644 --- a/Detectors/MUON/MID/Raw/exe/rawdump.cxx +++ b/Detectors/MUON/MID/Raw/exe/rawdump.cxx @@ -17,10 +17,7 @@ #include "fmt/format.h" #include "boost/program_options.hpp" #include "DPLUtils/RawParser.h" -#include "MIDRaw/FEEIdConfig.h" #include "MIDRaw/Decoder.h" -#include "MIDRaw/GBTBareDecoder.h" -#include "MIDRaw/GBTUserLogicDecoder.h" #include "MIDRaw/RawFileReader.h" namespace po = boost::program_options; @@ -48,16 +45,13 @@ std::string getOutFilename(const char* inFilename, const char* outDir) return outFilename; } -template <typename GBTDECODER, typename RDH> -void decode(o2::mid::Decoder<GBTDECODER>& decoder, gsl::span<const uint8_t> payload, const RDH& rdh, std::ostream& out) +template <class RDH> +void decode(o2::mid::Decoder& decoder, gsl::span<const uint8_t> payload, const RDH& rdh, std::ostream& out) { decoder.clear(); decoder.process(payload, rdh); - decoder.flush(); for (auto& rof : decoder.getROFRecords()) { - std::stringstream ss; - ss << std::hex << std::showbase << rof.interactionRecord; - out << ss.str() << std::endl; + out << fmt::format("BCid: 0x{:x} Orbit: 0x{:x}", rof.interactionRecord.bc, rof.interactionRecord.orbit) << std::endl; for (auto colIt = decoder.getData().begin() + rof.firstEntry; colIt != decoder.getData().begin() + rof.firstEntry + rof.nEntries; ++colIt) { out << *colIt << std::endl; } @@ -68,7 +62,7 @@ int main(int argc, char* argv[]) { po::variables_map vm; po::options_description generic("Generic options"); - std::string outFilename = "", feeIdConfigFilename = ""; + std::string outFilename = ""; unsigned long int nHBs = 0; unsigned long int firstHB = 0; @@ -80,8 +74,7 @@ int main(int argc, char* argv[]) ("nHBs", po::value<unsigned long int>(&nHBs),"Number of HBs read") ("rdh-only", po::value<bool>()->implicit_value(true),"Only show RDHs") ("decode", po::value<bool>()->implicit_value(true),"Decode output") - ("feeId-config-file", po::value<std::string>(&feeIdConfigFilename),"Filename with crate FEE ID correspondence") - ("bare", po::value<bool>()->implicit_value(true),"Bare decoder"); + ("feeId-config-file", po::value<std::string>()->default_value(""),"Filename with crate FEE ID correspondence"); po::options_description hidden("hidden options"); @@ -110,21 +103,8 @@ int main(int argc, char* argv[]) std::vector<std::string> inputfiles{vm["input"].as<std::vector<std::string>>()}; - bool isBare = (vm.count("bare") > 0); bool runDecoder = (vm.count("decode") > 0); - - o2::mid::Decoder<o2::mid::GBTUserLogicDecoder> ulDecoder; - o2::mid::Decoder<o2::mid::GBTBareDecoder> bareDecoder; - - if (runDecoder) { - if (!feeIdConfigFilename.empty()) { - o2::mid::FEEIdConfig feeIdConfig(feeIdConfigFilename.c_str()); - bareDecoder.setFeeIdConfig(feeIdConfig); - ulDecoder.setFeeIdConfig(feeIdConfig); - } - bareDecoder.init(true); - ulDecoder.init(true); - } + std::unique_ptr<o2::mid::Decoder> decoder{nullptr}; std::ofstream outFile; std::ostream& out = (outFilename.empty()) ? std::cout : (outFile.open(outFilename), outFile); @@ -150,25 +130,30 @@ int main(int argc, char* argv[]) if (it.size() > 0) { gsl::span<const uint8_t> payload(it.data(), it.size()); if (runDecoder) { - if (isBare) { - decode(bareDecoder, payload, *rdhPtr, out); - } else { - decode(ulDecoder, payload, *rdhPtr, out); + if (!decoder) { + decoder = o2::mid::createDecoder(*rdhPtr, true, "", "", vm["feeId-config-file"].as<std::string>().c_str()); } + decode(*decoder, payload, *rdhPtr, out); } else if (!isRdhOnly) { - for (size_t iword = 0; iword < payload.size(); iword += 16) { - auto word = payload.subspan(iword, 16); - for (auto it = word.rbegin(); it != word.rend(); ++it) { - auto ibInWord = word.rend() - it; - if (isBare) { + bool isBare = (o2::raw::RDHUtils::getLinkID(rdhPtr) != o2::mid::raw::sUserLogicLinkID); + size_t wordLength = isBare ? 16 : 32; + for (size_t iword = 0; iword < payload.size(); iword += wordLength) { + auto word = payload.subspan(iword, wordLength); + if (isBare) { + for (auto it = word.rbegin(); it != word.rend(); ++it) { + auto ibInWord = word.rend() - it; if (ibInWord == 4 || ibInWord == 9) { out << " "; } if (ibInWord == 5 || ibInWord == 10) { out << " "; } + out << fmt::format("{:02x}", static_cast<int>(*it)); + } + } else { + for (auto it = word.begin(); it != word.end(); ++it) { + out << fmt::format("{:02x}", static_cast<int>(*it)); } - out << fmt::format("{:02x}", static_cast<int>(*it)); } out << "\n"; } diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h index e3312a6c5aab1..2b5e1ff4fe46b 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/Decoder.h @@ -25,8 +25,7 @@ #include "MIDRaw/CrateParameters.h" #include "MIDRaw/ElectronicsDelay.h" #include "MIDRaw/FEEIdConfig.h" -#include "MIDRaw/GBTBareDecoder.h" -#include "MIDRaw/GBTUserLogicDecoder.h" +#include "MIDRaw/GBTDecoder.h" #include "MIDRaw/LocalBoardRO.h" namespace o2 @@ -34,26 +33,18 @@ namespace o2 namespace mid { -template <typename GBTDECODER> class Decoder { public: - Decoder(); - ~Decoder() = default; - /// Sets the FEE ID config file - void setFeeIdConfig(const FEEIdConfig& feeIdConfig) { mFEEIdConfig = feeIdConfig; } - /// Sets the crate masks - void setCrateMasks(const CrateMasks& masks) { mMasks = masks; } - /// Sets the electronics delays - void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } - void init(bool isDebugMode = false); + Decoder(bool isDebugMode = false, bool isBare = false, const ElectronicsDelay& electronicsDelay = ElectronicsDelay(), const CrateMasks& crateMasks = CrateMasks(), const FEEIdConfig& feeIdConfig = FEEIdConfig()); + virtual ~Decoder() = default; void process(gsl::span<const uint8_t> bytes); - template <typename RDH = o2::header::RAWDataHeader> + template <class RDH> void process(gsl::span<const uint8_t> payload, const RDH& rdh) { /// Processes the page - uint16_t feeId = mFEEIdConfig.getFeeId(o2::raw::RDHUtils::getLinkID(rdh), o2::raw::RDHUtils::getEndPointID(rdh), o2::raw::RDHUtils::getCRUID(rdh)); - mGBTDecoders[feeId].process(payload, o2::raw::RDHUtils::getHeartBeatBC(rdh), o2::raw::RDHUtils::getHeartBeatOrbit(rdh), o2::raw::RDHUtils::getPageCounter(rdh)); + auto feeId = mGetFEEID(rdh); + mGBTDecoders[feeId]->process(payload, o2::raw::RDHUtils::getHeartBeatOrbit(rdh), mData, mROFRecords); } /// Gets the vector of data const std::vector<LocalBoardRO>& getData() const { return mData; } @@ -61,21 +52,22 @@ class Decoder /// Gets the vector of data RO frame records const std::vector<ROFRecord>& getROFRecords() const { return mROFRecords; } - void flush(); - void clear(); - bool isComplete() const; + protected: + /// Gets the feeID + std::function<uint16_t(const o2::header::RDHAny& rdh)> mGetFEEID{[](const o2::header::RDHAny& rdh) { return o2::raw::RDHUtils::getFEEID(rdh); }}; + + std::array<std::unique_ptr<GBTDecoder>, crateparams::sNGBTs> mGBTDecoders{nullptr}; /// GBT decoders private: - std::vector<LocalBoardRO> mData{}; /// Vector of output data - std::vector<ROFRecord> mROFRecords{}; /// List of ROF records - std::array<GBTDECODER, crateparams::sNGBTs> mGBTDecoders{}; /// GBT decoders - FEEIdConfig mFEEIdConfig{}; /// Crate FEEID mapper - CrateMasks mMasks{}; /// Crate masks - ElectronicsDelay mElectronicsDelay{}; /// Delay in the electronics + std::vector<LocalBoardRO> mData{}; /// Vector of output data + std::vector<ROFRecord> mROFRecords{}; /// List of ROF records }; +std::unique_ptr<Decoder> createDecoder(const o2::header::RDHAny& rdh, bool isDebugMode, ElectronicsDelay& electronicsDelay, const CrateMasks& crateMasks, const FEEIdConfig& feeIdConfig); +std::unique_ptr<Decoder> createDecoder(const o2::header::RDHAny& rdh, bool isDebugMode, const char* electronicsDelayFile = "", const char* crateMasksFile = "", const char* feeIdConfigFile = ""); + } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/ELinkDecoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/ELinkDecoder.h index 6d2a081635990..43c2c372f268d 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/ELinkDecoder.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/ELinkDecoder.h @@ -17,6 +17,9 @@ #include <cstdint> #include <vector> +#include <gsl/gsl> + +#include "MIDRaw/LocalBoardRO.h" namespace o2 { @@ -25,29 +28,76 @@ namespace mid class ELinkDecoder { public: - void add(const uint8_t byte); - bool add(const uint8_t byte, uint8_t expectedStart); + /// Adds a byte + inline void add(const uint8_t byte) { mBytes.emplace_back(byte); } + void addAndComputeSize(const uint8_t byte); + template <class ITERATOR> + bool addCore(ITERATOR& it, const ITERATOR& end) + { + /// Adds the first 5 bytes + auto remaining = sMinimumSize - mBytes.size(); + return add(it, end, remaining); + } + template <class ITERATOR> + bool add(ITERATOR& it, const ITERATOR& end) + { + /// Adds the board bytes + auto remaining = mTotalSize - mBytes.size(); + if (add(it, end, remaining)) { + if (mTotalSize == sMinimumSize) { + computeSize(); + remaining = mTotalSize - mBytes.size(); + if (remaining) { + return add(it, end, remaining); + } + } + return true; + } + return false; + } + + /// Adds the first 5 bytes + inline bool addCore(size_t& idx, gsl::span<const uint8_t> payload, size_t step) { return add(idx, payload, sMinimumSize - mBytes.size(), step); } + + bool add(size_t& idx, gsl::span<const uint8_t> payload, size_t step); + + /// Checks if this is a zero + inline bool isZero(uint8_t byte) const { return (mBytes.empty() && (byte & raw::sSTARTBIT) == 0); } + /// Checks if we have all of the information needed for the decoding - bool isComplete() const { return mBytes.size() == mTotalSize; }; + inline bool isComplete() const { return mBytes.size() == mTotalSize; }; /// Gets the status word - uint8_t getStatusWord() const { return mBytes[0]; } + inline uint8_t getStatusWord() const { return mBytes[0]; } /// Gets the trigger word - uint8_t getTriggerWord() const { return mBytes[1]; } + inline uint8_t getTriggerWord() const { return mBytes[1]; } /// Gets the counter - uint16_t getCounter() const { return joinBytes(2); } - // uint16_t getCounter() const { return (mBytes[2] << 8) | mBytes[3]; } + inline uint16_t getCounter() const { return joinBytes(2); } /// Gets the card ID - uint8_t getId() const { return (mBytes[4] >> 4) & 0xF; } + inline uint8_t getId() const { return (mBytes[4] >> 4) & 0xF; } /// Gets the inputs - uint8_t getInputs() const { return (mBytes[4] & 0xF); } + inline uint8_t getInputs() const { return (mBytes[4] & 0xF); } uint16_t getPattern(int cathode, int chamber) const; /// Gets the number of bytes read - size_t getNBytes() const { return mBytes.size(); } + inline size_t getNBytes() const { return mBytes.size(); } void reset(); private: inline uint16_t joinBytes(int idx) const { return (mBytes[idx] << 8 | mBytes[idx + 1]); }; + template <class ITERATOR> + bool add(ITERATOR& it, const ITERATOR& end, size_t nBytes) + { + /// Fills inner bytes vector + auto nToEnd = std::distance(it, end); + auto nAdded = nBytes < nToEnd ? nBytes : nToEnd; + mBytes.insert(mBytes.end(), it, it + nAdded); + it += nAdded; + return (nAdded == nBytes); + } + + bool add(size_t& idx, gsl::span<const uint8_t> payload, size_t nBytes, size_t step); + + void computeSize(); static constexpr size_t sMinimumSize{5}; /// Minimum size of the buffer static constexpr size_t sMaximumSize{21}; /// Maximum size of the buffer diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h deleted file mode 100644 index b53a2701a091e..0000000000000 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTBareDecoder.h +++ /dev/null @@ -1,75 +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. - -/// \file MIDRaw/GBTBareDecoder.h -/// \brief MID GBT decoder without user logic -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 12 March 2020 -#ifndef O2_MID_GBTBAREDECODER_H -#define O2_MID_GBTBAREDECODER_H - -#include <cstdint> -#include <array> -#include <vector> -#include <gsl/gsl> -#include "DataFormatsMID/ROFRecord.h" -#include "MIDRaw/CrateParameters.h" -#include "MIDRaw/ElectronicsDelay.h" -#include "MIDRaw/ELinkDecoder.h" -#include "MIDRaw/GBTOutputHandler.h" -#include "MIDRaw/LocalBoardRO.h" - -namespace o2 -{ -namespace mid -{ -class GBTBareDecoder -{ - public: - void init(uint16_t feeId, uint8_t mask, bool isDebugMode = false); - void process(gsl::span<const uint8_t> bytes, uint16_t bc, uint32_t orbit, uint16_t pageCnt); - /// Gets the vector of data - const std::vector<LocalBoardRO>& getData() const { return mOutputHandler.getData(); } - - /// Gets the vector of data RO frame records - const std::vector<ROFRecord>& getROFRecords() const { return mOutputHandler.getROFRecords(); } - - bool isComplete() const; - - /// Clears the decoded data - void clear() { mOutputHandler.clear(); } - - /// Sets the delay in the electronics - void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mOutputHandler.setElectronicsDelay(electronicsDelay); } - - private: - GBTOutputHandler mOutputHandler{}; /// GBT output handler - uint8_t mMask{0xFF}; /// GBT mask - uint16_t mIsFeeding{0}; /// Flag to check if the e-link is feeding - - std::array<ELinkDecoder, crateparams::sNELinksPerGBT> mELinkDecoders{}; /// E-link decoders - - // Here we are using a function pointer instead of a std::function because it is faster. - // The std::function adds an overhead at each function call, - // which results in a considerable slowing done of the code if the function is executed often - typedef void (GBTOutputHandler::*OnDoneFunction)(size_t, const ELinkDecoder&); - typedef void (GBTBareDecoder::*ProcessFunction)(size_t, uint8_t); - - OnDoneFunction mOnDoneLoc{&GBTOutputHandler::onDoneLoc}; ///! Processes the local board - ProcessFunction mProcessReg{&GBTBareDecoder::processReg}; ///! Processes the regional board - - void processLoc(size_t ilink, uint8_t byte); - void processReg(size_t, uint8_t){}; /// Dummy function. We usually do not process the regional cards, except when we are debugging the code - void processRegDebug(size_t ilink, uint8_t byte); -}; -} // namespace mid -} // namespace o2 - -#endif /* O2_MID_GBTBAREDECODER_H */ diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTDecoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTDecoder.h new file mode 100644 index 0000000000000..60d96fc26b38e --- /dev/null +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTDecoder.h @@ -0,0 +1,54 @@ +// 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 MIDRaw/GBTDecoder.h +/// \brief Class interface for the MID GBT decoder +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 07 November 2020 +#ifndef O2_MID_GBTDECODER_H +#define O2_MID_GBTDECODER_H + +#include <cstdint> +#include <vector> +#include <gsl/gsl> +#include "DetectorsRaw/RDHUtils.h" +#include "Headers/RAWDataHeader.h" +#include "DataFormatsMID/ROFRecord.h" +#include "MIDRaw/ElectronicsDelay.h" +#include "MIDRaw/LocalBoardRO.h" + +namespace o2 +{ +namespace mid +{ + +class GBTDecoder +{ + public: + GBTDecoder(std::function<void(gsl::span<const uint8_t>, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs)> decode) : mDecode(decode) {} + void process(gsl::span<const uint8_t> payload, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs); + + template <class RDH> + void process(gsl::span<const uint8_t> payload, const RDH& rdh, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs) + { + process(payload, o2::raw::RDHUtils::getHeartBeatOrbit(rdh), data, rofs); + } + + protected: + std::function<void(gsl::span<const uint8_t>, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs)> mDecode{nullptr}; +}; + +std::unique_ptr<GBTDecoder> createGBTDecoder(const o2::header::RDHAny& rdh, uint16_t feeId, bool isDebugMode, uint8_t mask, const ElectronicsDelay& electronicsDelay); +std::unique_ptr<GBTDecoder> createGBTDecoder(uint16_t feeId, bool isBare = false, bool isDebugMode = false, uint8_t mask = 0xFF, const ElectronicsDelay& electronicsDelay = ElectronicsDelay()); + +} // namespace mid +} // namespace o2 + +#endif /* O2_MID_GBTDECODER_H */ diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h index e153da3e91536..425d2771e2cf2 100644 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h +++ b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTOutputHandler.h @@ -35,7 +35,7 @@ class GBTOutputHandler /// Sets the FEE Id void setFeeId(uint16_t feeId) { mFeeId = feeId; } - void setIR(uint16_t bc, uint32_t orbit, int pageCnt); + void set(uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs); void onDoneLoc(size_t ilink, const ELinkDecoder& decoder); void onDoneLocDebug(size_t ilink, const ELinkDecoder& decoder); @@ -45,21 +45,13 @@ class GBTOutputHandler /// Sets the delay in the electronics void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mElectronicsDelay = electronicsDelay; } - /// Gets the vector of data - const std::vector<LocalBoardRO>& getData() const { return mData; } - - /// Gets the vector of data RO frame records - const std::vector<ROFRecord>& getROFRecords() const { return mROFRecords; } - - void clear(); - private: - std::vector<LocalBoardRO> mData{}; /// Vector of output data - std::vector<ROFRecord> mROFRecords{}; /// List of ROF records - uint16_t mFeeId{0}; /// FEE ID - InteractionRecord mIRFirstPage{}; /// Interaction record of the first page - uint16_t mReceivedCalibration{0}; /// Word with one bit per e-link indicating if the calibration trigger was received by the e-link - ElectronicsDelay mElectronicsDelay{}; /// Delays in the electronics + std::vector<LocalBoardRO>* mData{nullptr}; ///! Vector of output data. Not owner + std::vector<ROFRecord>* mROFRecords{nullptr}; /// List of ROF records. Not owner + uint16_t mFeeId{0}; /// FEE ID + uint32_t mOrbit{}; /// RDH orbit + uint16_t mReceivedCalibration{0}; /// Word with one bit per e-link indicating if the calibration trigger was received by the e-link + ElectronicsDelay mElectronicsDelay{}; /// Delays in the electronics std::array<InteractionRecord, crateparams::sNELinksPerGBT> mIRs{}; /// Interaction records per link std::array<uint16_t, crateparams::sNELinksPerGBT> mExpectedFETClock{}; /// Expected FET clock diff --git a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h b/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h deleted file mode 100644 index 8899c0176600d..0000000000000 --- a/Detectors/MUON/MID/Raw/include/MIDRaw/GBTUserLogicDecoder.h +++ /dev/null @@ -1,70 +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. - -/// \file MIDRaw/GBTUserLogicDecoder.h -/// \brief MID GBT decoder with user logic zero suppression -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 15 April 2020 -#ifndef O2_MID_GBTUSERLOGICDECODER_H -#define O2_MID_GBTUSERLOGICDECODER_H - -#include <cstdint> -#include <vector> -#include <gsl/gsl> -#include "DetectorsRaw/RDHUtils.h" -#include "DataFormatsMID/ROFRecord.h" -#include "MIDRaw/ElectronicsDelay.h" -#include "MIDRaw/ELinkDecoder.h" -#include "MIDRaw/GBTOutputHandler.h" -#include "MIDRaw/LocalBoardRO.h" - -namespace o2 -{ -namespace mid -{ -class GBTUserLogicDecoder -{ - public: - void init(uint16_t feeId, bool isDebugMode = false); - void process(gsl::span<const uint8_t> bytes, uint16_t bc, uint32_t orbit, uint16_t pageCnt); - template <typename RDH> - void process(gsl::span<const uint8_t> bytes, const RDH& rdh) - { - process(bytes, o2::raw::RDHUtils::getHeartBeatBC(rdh), o2::raw::RDHUtils::getHeartBeatOrbit(rdh), o2::raw::RDHUtils::getPageCounter(rdh)); - } - /// Gets the vector of data - const std::vector<LocalBoardRO>& getData() const { return mOutputHandler.getData(); } - - /// Gets the vector of data RO frame records - const std::vector<ROFRecord>& getROFRecords() const { return mOutputHandler.getROFRecords(); } - - /// Checks that the link has finished reading - bool isComplete() const { return mELinkDecoder.isComplete(); } - - /// Clears the decoded data - void clear() { mOutputHandler.clear(); } - - /// Sets the delay in the electronics - void setElectronicsDelay(const ElectronicsDelay& electronicsDelay) { mOutputHandler.setElectronicsDelay(electronicsDelay); } - - private: - GBTOutputHandler mOutputHandler{}; /// GBT output handler - - ELinkDecoder mELinkDecoder{}; /// E-link decoder - - typedef void (GBTOutputHandler::*OnDoneFunction)(size_t, const ELinkDecoder&); - - OnDoneFunction mOnDoneLoc{&GBTOutputHandler::onDoneLoc}; ///! Processes the local board - OnDoneFunction mOnDoneReg{&GBTOutputHandler::onDoneReg}; ///! Processes the regional board -}; -} // namespace mid -} // namespace o2 - -#endif /* O2_MID_GBTUSERLOGICDECODER_H */ diff --git a/Detectors/MUON/MID/Raw/src/Decoder.cxx b/Detectors/MUON/MID/Raw/src/Decoder.cxx index 9f71c784047ca..146f6c543a3ac 100644 --- a/Detectors/MUON/MID/Raw/src/Decoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Decoder.cxx @@ -23,37 +23,38 @@ namespace o2 namespace mid { -template <typename GBTDECODER> -Decoder<GBTDECODER>::Decoder() : mData(), mROFRecords(), mGBTDecoders(), mFEEIdConfig(), mMasks() +// namespace impl +// { +class FEEIDGetterImpl { - /// Default constructor - init(); + public: + FEEIDGetterImpl(const FEEIdConfig& feeIdConfig) : mFeeIdConfig(feeIdConfig) {} + uint16_t operator()(const o2::header::RDHAny& rdh) { return mFeeIdConfig.getFeeId(o2::raw::RDHUtils::getLinkID(rdh), o2::raw::RDHUtils::getEndPointID(rdh), o2::raw::RDHUtils::getCRUID(rdh)); } + + private: + FEEIdConfig mFeeIdConfig{}; +}; +// } // namespace impl + +Decoder::Decoder(bool isDebugMode, bool isBare, const ElectronicsDelay& electronicsDelay, const CrateMasks& crateMasks, const FEEIdConfig& feeIdConfig) : mData(), mROFRecords(), mGBTDecoders() +{ + /// Constructor + for (uint16_t igbt = 0; igbt < crateparams::sNGBTs; ++igbt) { + mGBTDecoders[igbt] = createGBTDecoder(igbt, isBare, isDebugMode, crateMasks.getMask(igbt), electronicsDelay); + } + if (isBare) { + mGetFEEID = FEEIDGetterImpl(feeIdConfig); + } } -template <typename GBTDECODER> -void Decoder<GBTDECODER>::clear() +void Decoder::clear() { /// Clears the decoded data mData.clear(); mROFRecords.clear(); } -template <typename GBTDECODER> -void Decoder<GBTDECODER>::init(bool isDebugMode) -{ - /// Initializes the decoder - for (uint16_t igbt = 0; igbt < crateparams::sNGBTs; ++igbt) { - if constexpr (std::is_same_v<GBTDECODER, GBTBareDecoder>) { - mGBTDecoders[igbt].init(igbt, mMasks.getMask(igbt), isDebugMode); - } else { - mGBTDecoders[igbt].init(igbt, isDebugMode); - } - mGBTDecoders[igbt].setElectronicsDelay(mElectronicsDelay); - } -} - -template <typename GBTDECODER> -void Decoder<GBTDECODER>::process(gsl::span<const uint8_t> bytes) +void Decoder::process(gsl::span<const uint8_t> bytes) { /// Decodes the buffer clear(); @@ -66,41 +67,37 @@ void Decoder<GBTDECODER>::process(gsl::span<const uint8_t> bytes) auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(it.raw()); process(payload, *rdhPtr); } - flush(); } -template <typename GBTDECODER> -void Decoder<GBTDECODER>::flush() +std::unique_ptr<Decoder> createDecoder(const o2::header::RDHAny& rdh, bool isDebugMode, ElectronicsDelay& electronicsDelay, const CrateMasks& crateMasks, const FEEIdConfig& feeIdConfig) { - /// Flushes the GBT data - for (auto& gbtDec : mGBTDecoders) { - if (!gbtDec.getData().empty()) { - size_t firstEntry = mData.size(); - mData.insert(mData.end(), gbtDec.getData().begin(), gbtDec.getData().end()); - size_t lastRof = mROFRecords.size(); - mROFRecords.insert(mROFRecords.end(), gbtDec.getROFRecords().begin(), gbtDec.getROFRecords().end()); - for (auto rofIt = mROFRecords.begin() + lastRof; rofIt != mROFRecords.end(); ++rofIt) { - rofIt->firstEntry += firstEntry; - } - gbtDec.clear(); - } - } + /// Creates the decoder from the RDH info + bool isBare = (o2::raw::RDHUtils::getLinkID(rdh) != raw::sUserLogicLinkID); + return std::make_unique<Decoder>(isDebugMode, isBare, electronicsDelay, crateMasks); } - -template <typename GBTDECODER> -bool Decoder<GBTDECODER>::isComplete() const +std::unique_ptr<Decoder> createDecoder(const o2::header::RDHAny& rdh, bool isDebugMode, const char* electronicsDelayFile, const char* crateMasksFile, const char* feeIdConfigFile) { - /// Checks that all links have finished reading - for (auto& decoder : mGBTDecoders) { - if (!decoder.isComplete()) { - return false; - } + /// Creates the decoder from the RDH info + o2::mid::ElectronicsDelay electronicsDelay; + std::string filename = electronicsDelayFile; + if (!filename.empty()) { + electronicsDelay = o2::mid::readElectronicsDelay(filename.c_str()); } - return true; -} -template class Decoder<GBTBareDecoder>; -template class Decoder<GBTUserLogicDecoder>; + o2::mid::CrateMasks crateMasks; + filename = crateMasksFile; + if (!filename.empty()) { + crateMasks = o2::mid::CrateMasks(filename.c_str()); + } + + o2::mid::FEEIdConfig feeIdConfig; + filename = feeIdConfigFile; + if (!filename.empty()) { + feeIdConfig = o2::mid::FEEIdConfig(filename.c_str()); + } + + return createDecoder(rdh, isDebugMode, electronicsDelay, crateMasks, feeIdConfig); +} } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/ELinkDecoder.cxx b/Detectors/MUON/MID/Raw/src/ELinkDecoder.cxx index 9ec3c7b9d3c73..c18234952963f 100644 --- a/Detectors/MUON/MID/Raw/src/ELinkDecoder.cxx +++ b/Detectors/MUON/MID/Raw/src/ELinkDecoder.cxx @@ -15,39 +15,66 @@ #include "MIDRaw/ELinkDecoder.h" -#include "MIDRaw/LocalBoardRO.h" - namespace o2 { namespace mid { -void ELinkDecoder::add(uint8_t byte) +bool ELinkDecoder::add(size_t& idx, gsl::span<const uint8_t> payload, size_t nBytes, size_t step) { - /// Adds next byte - mBytes.emplace_back(byte); - if (mBytes.size() == sMinimumSize) { - if (raw::isLoc(mBytes[0])) { - // This is a local card - uint8_t mask = getInputs(); - for (int ich = 0; ich < 4; ++ich) { - if ((mask >> ich) & 0x1) { - // We expect 2 bytes for the BP and 2 for the NBP - mTotalSize += 4; - } + /// Fills inner bytes vector + auto size = payload.size(); + auto end = idx + step * nBytes; + if (size < end) { + end = size; + } + size_t nAdded = 0; + for (; idx < end; idx += step) { + mBytes.emplace_back(payload[idx]); + ++nAdded; + } + return (nAdded == nBytes); +} + +bool ELinkDecoder::add(size_t& idx, gsl::span<const uint8_t> payload, size_t step) +{ + /// Adds the bytes of the board + auto remaining = mTotalSize - mBytes.size(); + if (add(idx, payload, remaining, step)) { + if (mTotalSize == sMinimumSize) { + computeSize(); + remaining = mTotalSize - mBytes.size(); + if (remaining) { + return add(idx, payload, remaining, step); } } + return true; } + return false; } -bool ELinkDecoder::add(uint8_t byte, uint8_t expectedStart) +void ELinkDecoder::addAndComputeSize(uint8_t byte) { - /// Adds next byte, checking the first one - if (mBytes.empty() && (byte & 0xc0) != expectedStart) { - return false; + /// Adds next byte and computes the expected data size + mBytes.emplace_back(byte); + if (mBytes.size() == sMinimumSize) { + computeSize(); + } +} + +void ELinkDecoder::computeSize() +{ + /// Computes the board size + if (raw::isLoc(mBytes[0])) { + // This is a local card + uint8_t mask = getInputs(); + for (int ich = 0; ich < 4; ++ich) { + if ((mask >> ich) & 0x1) { + // We expect 2 bytes for the BP and 2 for the NBP + mTotalSize += 4; + } + } } - add(byte); - return true; } void ELinkDecoder::reset() diff --git a/Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx b/Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx deleted file mode 100644 index c5f2c8bf7177a..0000000000000 --- a/Detectors/MUON/MID/Raw/src/GBTBareDecoder.cxx +++ /dev/null @@ -1,111 +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. - -/// \file MID/Raw/src/GBTBareDecoder.cxx -/// \brief MID GBT decoder without user logic -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 12 March 2020 - -#include "MIDRaw/GBTBareDecoder.h" - -namespace o2 -{ -namespace mid -{ - -void GBTBareDecoder::init(uint16_t feeId, uint8_t mask, bool isDebugMode) -{ - /// Initializes the task - mOutputHandler.setFeeId(feeId); - mMask = mask; - if (isDebugMode) { - mOnDoneLoc = &GBTOutputHandler::onDoneLocDebug; - mProcessReg = &GBTBareDecoder::processRegDebug; - } -} - -void GBTBareDecoder::process(gsl::span<const uint8_t> bytes, uint16_t bc, uint32_t orbit, uint16_t pageCnt) -{ - /// Decodes the buffer - mOutputHandler.setIR(bc, orbit, pageCnt); - - uint8_t byte = 0; - size_t ilink = 0, linkMask = 0, byteOffset = 0; - - for (int ireg = 0; ireg < 2; ++ireg) { - byteOffset = 5 * ireg; - ilink = 8 + ireg; - linkMask = (1 << ilink); - for (size_t idx = byteOffset + 4; idx < bytes.size(); idx += 16) { - byte = bytes[idx]; - if ((mIsFeeding & linkMask) || byte) { - std::invoke(mProcessReg, this, ilink, byte); - } - } - for (int ib = 0; ib < 4; ++ib) { - ilink = ib + 4 * ireg; - linkMask = (1 << ilink); - if (mMask & linkMask) { - for (size_t idx = byteOffset + ib; idx < bytes.size(); idx += 16) { - byte = bytes[idx]; - if ((mIsFeeding & linkMask) || byte) { - processLoc(ilink, byte); - } - } - } - } - } -} - -void GBTBareDecoder::processLoc(size_t ilink, uint8_t byte) -{ - /// Processes the local board information - if (mELinkDecoders[ilink].getNBytes() > 0) { - mELinkDecoders[ilink].add(byte); - if (mELinkDecoders[ilink].isComplete()) { - std::invoke(mOnDoneLoc, mOutputHandler, ilink, mELinkDecoders[ilink]); - mELinkDecoders[ilink].reset(); - mIsFeeding &= (~(1 << ilink)); - } - } else if ((byte & (raw::sSTARTBIT | raw::sCARDTYPE)) == (raw::sSTARTBIT | raw::sCARDTYPE)) { - mELinkDecoders[ilink].add(byte); - mIsFeeding |= (1 << ilink); - } -} - -void GBTBareDecoder::processRegDebug(size_t ilink, uint8_t byte) -{ - /// Processes the regional board information in debug mode - if (mELinkDecoders[ilink].getNBytes() > 0) { - mELinkDecoders[ilink].add(byte); - if (mELinkDecoders[ilink].isComplete()) { - mOutputHandler.onDoneRegDebug(ilink, mELinkDecoders[ilink]); - mELinkDecoders[ilink].reset(); - mIsFeeding &= (~(1 << ilink)); - } - } else if (byte & raw::sSTARTBIT) { - mELinkDecoders[ilink].add(byte); - mIsFeeding |= (1 << ilink); - } -} - -bool GBTBareDecoder::isComplete() const -{ - /// Checks that all links have finished reading - for (auto& elink : mELinkDecoders) { - if (elink.getNBytes() > 0) { - return false; - } - } - return true; -} - -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/GBTDecoder.cxx b/Detectors/MUON/MID/Raw/src/GBTDecoder.cxx new file mode 100644 index 0000000000000..b3c5a84058651 --- /dev/null +++ b/Detectors/MUON/MID/Raw/src/GBTDecoder.cxx @@ -0,0 +1,362 @@ +// 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 MID/Raw/src/GBTDecoder.cxx +/// \brief Class interface for the MID GBT decoder +/// \author Diego Stocco <Diego.Stocco at cern.ch> +/// \date 07 November 2020 + +#include "MIDRaw/GBTDecoder.h" + +#include "MIDRaw/FEEIdConfig.h" +#include "MIDRaw/GBTOutputHandler.h" +#include "MIDRaw/LocalBoardRO.h" + +namespace o2 +{ +namespace mid +{ +namespace impl +{ +class GBTUserLogicDecoderImpl +{ + public: + GBTUserLogicDecoderImpl(uint16_t feeId, bool isDebugMode = false, uint8_t mask = 0xFF, const ElectronicsDelay& electronicsDelay = ElectronicsDelay()) + { + mOutputHandler.setFeeId(feeId); + mOutputHandler.setElectronicsDelay(electronicsDelay); + if (isDebugMode) { + mOnDoneLoc = &GBTOutputHandler::onDoneLocDebug; + mOnDoneReg = &GBTOutputHandler::onDoneRegDebug; + } + } + + void operator()(gsl::span<const uint8_t> payload, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs) + { + /// Decodes the buffer + mOutputHandler.set(orbit, data, rofs); + // for (auto& byte : payload) { + auto it = payload.begin(); + auto end = payload.end(); + while (it != end) { + if (mELinkDecoder.isZero(*it)) { + // The e-link decoder is empty, meaning that we expect a new board. + // The first byte of the board should have the STARTBIT on. + // If this is not the case, we move to the next byte. + // Notice that the payload has zeros until the end of the 256 bits word: + // a) when moving from the regional high to regional low + // b) at the end of the HBF + ++it; + continue; + } + if (mELinkDecoder.add(it, end)) { + if (raw::isLoc(mELinkDecoder.getStatusWord())) { + std::invoke(mOnDoneLoc, mOutputHandler, mELinkDecoder.getId() % 8, mELinkDecoder); + } else { + size_t ilink = 8 + mELinkDecoder.getId() % 8; + if (ilink <= 9) { + std::invoke(mOnDoneReg, mOutputHandler, ilink, mELinkDecoder); + } + } + mELinkDecoder.reset(); + } + } + } + + private: + GBTOutputHandler mOutputHandler{}; /// GBT output handler + ELinkDecoder mELinkDecoder{}; /// E-link decoder + + typedef void (GBTOutputHandler::*OnDoneFunction)(size_t, const ELinkDecoder&); + + OnDoneFunction mOnDoneLoc{&GBTOutputHandler::onDoneLoc}; ///! Processes the local board + OnDoneFunction mOnDoneReg{&GBTOutputHandler::onDoneReg}; ///! Processes the regional board +}; + +class GBTBareDecoderImpl +{ + public: + GBTBareDecoderImpl(uint16_t feeId, bool isDebugMode = false, uint8_t mask = 0xFF, const ElectronicsDelay& electronicsDelay = ElectronicsDelay()) : mIsDebugMode(isDebugMode), mMask(mask) + { + /// Constructor + mOutputHandler.setFeeId(feeId); + mOutputHandler.setElectronicsDelay(electronicsDelay); + if (isDebugMode) { + mOnDoneLoc = &GBTOutputHandler::onDoneLocDebug; + } + } + + void operator()(gsl::span<const uint8_t> payload, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs) + { + /// Decodes the buffer + mOutputHandler.set(orbit, data, rofs); + + uint8_t byte = 0; + size_t ilink = 0, linkMask = 0, byteOffset = 0; + + for (int ireg = 0; ireg < 2; ++ireg) { + byteOffset = 5 * ireg; + if (mIsDebugMode) { + ilink = 8 + ireg; + linkMask = (1 << ilink); + for (size_t idx = byteOffset + 4; idx < payload.size(); idx += 16) { + byte = payload[idx]; + if ((mIsFeeding & linkMask) || byte) { + processRegDebug(ilink, byte); + } + } + } + for (int ib = 0; ib < 4; ++ib) { + ilink = ib + 4 * ireg; + linkMask = (1 << ilink); + if (mMask & linkMask) { + for (size_t idx = byteOffset + ib; idx < payload.size(); idx += 16) { + byte = payload[idx]; + if ((mIsFeeding & linkMask) || byte) { + processLoc(ilink, byte); + } + } + } + } + } + } + + private: + void processLoc(size_t ilink, uint8_t byte) + { + /// Processes the local board information + if (mELinkDecoders[ilink].getNBytes() > 0) { + mELinkDecoders[ilink].addAndComputeSize(byte); + if (mELinkDecoders[ilink].isComplete()) { + std::invoke(mOnDoneLoc, mOutputHandler, ilink, mELinkDecoders[ilink]); + mELinkDecoders[ilink].reset(); + mIsFeeding &= (~(1 << ilink)); + } + } else if ((byte & (raw::sSTARTBIT | raw::sCARDTYPE)) == (raw::sSTARTBIT | raw::sCARDTYPE)) { + mELinkDecoders[ilink].add(byte); + mIsFeeding |= (1 << ilink); + } + } + + void processRegDebug(size_t ilink, uint8_t byte) + { + /// Processes the regional board information in debug mode + if (mELinkDecoders[ilink].getNBytes() > 0) { + mELinkDecoders[ilink].add(byte); + if (mELinkDecoders[ilink].isComplete()) { + mOutputHandler.onDoneRegDebug(ilink, mELinkDecoders[ilink]); + mELinkDecoders[ilink].reset(); + mIsFeeding &= (~(1 << ilink)); + } + } else if (byte & raw::sSTARTBIT) { + mELinkDecoders[ilink].add(byte); + mIsFeeding |= (1 << ilink); + } + } + + bool mIsDebugMode{false}; /// Debug mode + uint8_t mMask{0xFF}; /// GBT mask + uint16_t mIsFeeding{0}; /// Flag to check if the e-link is feeding + GBTOutputHandler mOutputHandler{}; /// GBT output handler + + std::array<ELinkDecoder, crateparams::sNELinksPerGBT> mELinkDecoders{}; /// E-link decoders + + typedef void (GBTOutputHandler::*OnDoneFunction)(size_t, const ELinkDecoder&); + + OnDoneFunction mOnDoneLoc{&GBTOutputHandler::onDoneLoc}; ///! Processes the local board +}; + +/// Alternative bare decoder implementation +/// Data are first ranged per link and then each link is decoded in a similar way to what is done for the user logic +/// CAVEAT: abandoned since filling the vector per link is much slower +/// Kept here for future reference (parallelization?) +class GBTBareDecoderLinkImpl +{ + public: + GBTBareDecoderLinkImpl(uint16_t feeId, bool isDebugMode = false, uint8_t mask = 0xFF, const ElectronicsDelay& electronicsDelay = ElectronicsDelay()) : mIsDebugMode(isDebugMode), mMask(mask) + { + /// Constructor + mOutputHandler.setFeeId(feeId); + mOutputHandler.setElectronicsDelay(electronicsDelay); + mIsDebugMode = isDebugMode; + if (isDebugMode) { + mOnDoneLoc = &GBTOutputHandler::onDoneLocDebug; + } + mLinkPayload.reserve(0x20000); + } + + void operator()(gsl::span<const uint8_t> payload, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs) + { + /// Decodes the buffer + mOutputHandler.set(orbit, data, rofs); + + for (int ireg = 0; ireg < 2; ++ireg) { + size_t byteOffset = 5 * ireg; + + if (mIsDebugMode) { + // Treat regional cards + size_t ilink = 8 + ireg; + mLinkPayload.clear(); + for (size_t idx = byteOffset + 4, end = payload.size(); idx < end; idx += 16) { + mLinkPayload.emplace_back(payload[idx]); + } + auto it = mLinkPayload.begin(); + auto end = mLinkPayload.end(); + while (it != end) { + if (mELinkDecoders[ilink].isZero(*it)) { + ++it; + continue; + } + if (mELinkDecoders[ilink].addCore(it, end)) { + mOutputHandler.onDoneRegDebug(ilink, mELinkDecoders[ilink]); + mELinkDecoders[ilink].reset(); + } + } + } + + // Treat local cards + for (int ib = 0; ib < 4; ++ib) { + size_t ilink = ib + 4 * ireg; + if (mMask & (1 << ilink)) { + mLinkPayload.clear(); + for (size_t idx = byteOffset + ib, end = payload.size(); idx < end; idx += 16) { + mLinkPayload.emplace_back(payload[idx]); + } + auto it = mLinkPayload.begin(); + auto end = mLinkPayload.end(); + while (it != end) { + if (mELinkDecoders[ilink].isZero(*it)) { + ++it; + continue; + } + if (mELinkDecoders[ilink].add(it, end)) { + std::invoke(mOnDoneLoc, mOutputHandler, mELinkDecoders[ilink].getId() % 8, mELinkDecoders[ilink]); + mELinkDecoders[ilink].reset(); + } + } + } + } + } + } + + private: + bool mIsDebugMode{false}; /// Debug mode + uint8_t mMask{0xFF}; /// GBT mask + GBTOutputHandler mOutputHandler{}; /// GBT output handler + + std::array<ELinkDecoder, crateparams::sNELinksPerGBT> mELinkDecoders{}; /// E-link decoders + std::vector<uint8_t> mLinkPayload{}; /// Link payload + + typedef void (GBTOutputHandler::*OnDoneFunction)(size_t, const ELinkDecoder&); + + OnDoneFunction mOnDoneLoc{&GBTOutputHandler::onDoneLoc}; ///! Processes the local board +}; + +/// Alternative implementation of the bare decoder +/// When a start bit is found, we try to add all of the expected bytes. +/// This should in principle allow to avoid performing a check on the expected data size at each newly added byte. +/// But tests show that the implementation is slightly slower than the standard one. +class GBTBareDecoderInsertImpl +{ + public: + GBTBareDecoderInsertImpl(uint16_t feeId, bool isDebugMode = false, uint8_t mask = 0xFF, const ElectronicsDelay& electronicsDelay = ElectronicsDelay()) : mIsDebugMode(isDebugMode), mMask(mask) + { + /// Constructor + mOutputHandler.setFeeId(feeId); + mOutputHandler.setElectronicsDelay(electronicsDelay); + if (isDebugMode) { + mOnDoneLoc = &GBTOutputHandler::onDoneLocDebug; + } + } + + void operator()(gsl::span<const uint8_t> payload, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs) + { + /// Decodes the buffer + mOutputHandler.set(orbit, data, rofs); + + size_t step = 16; + size_t end = payload.size(); + + for (int ireg = 0; ireg < 2; ++ireg) { + size_t byteOffset = 5 * ireg; + + if (mIsDebugMode) { + // Treat regional cards + size_t ilink = 8 + ireg; + size_t idx = byteOffset + 4; + + while (idx < end) { + if (mELinkDecoders[ilink].isZero(payload[idx])) { + idx += step; + } else if (mELinkDecoders[ilink].addCore(idx, payload, step)) { + mOutputHandler.onDoneRegDebug(ilink, mELinkDecoders[ilink]); + mELinkDecoders[ilink].reset(); + } + } + } + + // Treat local cards + for (int ib = 0; ib < 4; ++ib) { + size_t ilink = ib + 4 * ireg; + if (mMask & (1 << ilink)) { + size_t idx = byteOffset + ib; + while (idx < end) { + if (mELinkDecoders[ilink].isZero(payload[idx])) { + idx += step; + } else if (mELinkDecoders[ilink].add(idx, payload, step)) { + std::invoke(mOnDoneLoc, mOutputHandler, mELinkDecoders[ilink].getId() % 8, mELinkDecoders[ilink]); + mELinkDecoders[ilink].reset(); + } + } + } + } + } + } + + private: + uint8_t mMask{0xFF}; /// GBT mask + bool mIsDebugMode{false}; /// Debug mode + GBTOutputHandler mOutputHandler{}; /// GBT output handler + + std::array<ELinkDecoder, crateparams::sNELinksPerGBT> mELinkDecoders{}; /// E-link decoders + + typedef void (GBTOutputHandler::*OnDoneFunction)(size_t, const ELinkDecoder&); + + OnDoneFunction mOnDoneLoc{&GBTOutputHandler::onDoneLoc}; ///! Processes the local board +}; + +} // namespace impl + +void GBTDecoder::process(gsl::span<const uint8_t> payload, uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs) +{ + /// Decodes the data + mDecode(payload, orbit, data, rofs); +} + +std::unique_ptr<GBTDecoder> createGBTDecoder(const o2::header::RDHAny& rdh, uint16_t feeId, bool isDebugMode, uint8_t mask, const ElectronicsDelay& electronicsDelay) +{ + /// Creates the correct implementation of the GBT decoder + if (o2::raw::RDHUtils::getLinkID(rdh) == raw::sUserLogicLinkID) { + return std::make_unique<GBTDecoder>(impl::GBTUserLogicDecoderImpl(feeId, isDebugMode, mask, electronicsDelay)); + } + return std::make_unique<GBTDecoder>(impl::GBTBareDecoderImpl(feeId, isDebugMode, mask, electronicsDelay)); +} + +std::unique_ptr<GBTDecoder> createGBTDecoder(uint16_t feeId, bool isBare, bool isDebugMode, uint8_t mask, const ElectronicsDelay& electronicsDelay) +{ + /// Creates the correct implementation of the GBT decoder + if (isBare) { + return std::make_unique<GBTDecoder>(impl::GBTBareDecoderImpl(feeId, isDebugMode, mask, electronicsDelay)); + } + return std::make_unique<GBTDecoder>(impl::GBTUserLogicDecoderImpl(feeId, isDebugMode, mask, electronicsDelay)); +} + +} // namespace mid +} // namespace o2 diff --git a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx index b65d4b2934061..01b743f88a3c3 100644 --- a/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx +++ b/Detectors/MUON/MID/Raw/src/GBTOutputHandler.cxx @@ -20,19 +20,16 @@ namespace o2 namespace mid { -void GBTOutputHandler::clear() +void GBTOutputHandler::set(uint32_t orbit, std::vector<LocalBoardRO>& data, std::vector<ROFRecord>& rofs) { - /// Rewind bytes - mData.clear(); - mROFRecords.clear(); -} + /// Sets the orbit and the output data vectors + mOrbit = orbit; + mData = &data; + mROFRecords = &rofs; -void GBTOutputHandler::setIR(uint16_t bc, uint32_t orbit, int pageCnt) -{ - /// Sets the interaction record if needed if (mIRs[0].isDummy()) { for (auto& ir : mIRs) { - ir.bc = bc; + ir.bc = 0; // The reset changes depending on the way we synch with the orbit // (see processOrbitTrigger for details) // FIXME: pick one of the two @@ -41,16 +38,6 @@ void GBTOutputHandler::setIR(uint16_t bc, uint32_t orbit, int pageCnt) } mLastClock.fill(constants::lhc::LHCMaxBunches); } - - if (pageCnt == 0) { - // FIXME: in the tests, the BC counter increases at each RDH - // However, the inner clock of the RO is not reset, - // so if we want to have the absolute BC, - // we need to store only the BC counter of the first page. - // Not sure how it will work on data... - mIRFirstPage.bc = bc; - mIRFirstPage.orbit = orbit; - } } bool GBTOutputHandler::checkLoc(size_t ilink, const ELinkDecoder& decoder) @@ -92,7 +79,7 @@ void GBTOutputHandler::processOrbitTrigger(size_t ilink, uint16_t localClock, ui // (CAVEAT: synch is lost if we have lot of data, spanning over two orbits) // FIXME: pick one of the two ++mIRs[ilink].orbit; // orbit increase - // mIRs[ilink] = mIRFirstPage; // reset to RDH + // mIRs[ilink].orbit = mOrbit; // reset to RDH if ((triggerWord & raw::sSOX) == 0) { mLastClock[ilink] = localClock; } @@ -138,14 +125,14 @@ bool GBTOutputHandler::processTrigger(size_t ilink, const ELinkDecoder& decoder, void GBTOutputHandler::addLoc(size_t ilink, const ELinkDecoder& decoder, EventType eventType, uint16_t correctedClock) { /// Adds the local board to the output data vector - auto firstEntry = mData.size(); - mData.push_back({decoder.getStatusWord(), decoder.getTriggerWord(), crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), decoder.getId()), decoder.getInputs()}); + auto firstEntry = mData->size(); + mData->push_back({decoder.getStatusWord(), decoder.getTriggerWord(), crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), decoder.getId()), decoder.getInputs()}); InteractionRecord intRec(mIRs[ilink].bc + correctedClock, mIRs[ilink].orbit); - mROFRecords.emplace_back(intRec, eventType, firstEntry, 1); + mROFRecords->emplace_back(intRec, eventType, firstEntry, 1); for (int ich = 0; ich < 4; ++ich) { - if ((mData.back().firedChambers & (1 << ich))) { - mData.back().patternsBP[ich] = decoder.getPattern(0, ich); - mData.back().patternsNBP[ich] = decoder.getPattern(1, ich); + if ((mData->back().firedChambers & (1 << ich))) { + mData->back().patternsBP[ich] = decoder.getPattern(0, ich); + mData->back().patternsNBP[ich] = decoder.getPattern(1, ich); } } } @@ -171,7 +158,7 @@ void GBTOutputHandler::onDoneLocDebug(size_t ilink, const ELinkDecoder& decoder) // The local clock is increased when receiving an orbit trigger, // but the local counter returned in answering the trigger // belongs to the previous orbit - --mROFRecords.back().interactionRecord.orbit; + --mROFRecords->back().interactionRecord.orbit; } } @@ -182,8 +169,8 @@ void GBTOutputHandler::onDoneRegDebug(size_t ilink, const ELinkDecoder& decoder) uint16_t correctedClock; processTrigger(ilink, decoder, eventType, correctedClock); // If we want to distinguish the two regional e-links, we can use the link ID instead - auto firstEntry = mData.size(); - mData.push_back({decoder.getStatusWord(), decoder.getTriggerWord(), crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), ilink + 8 * (crateparams::getGBTIdInCrate(mFeeId) - 1)), decoder.getInputs()}); + auto firstEntry = mData->size(); + mData->push_back({decoder.getStatusWord(), decoder.getTriggerWord(), crateparams::makeUniqueLocID(crateparams::getCrateIdFromROId(mFeeId), ilink + 8 * (crateparams::getGBTIdInCrate(mFeeId) - 1)), decoder.getInputs()}); auto orbit = (decoder.getTriggerWord() & raw::sORB) ? mIRs[ilink].orbit - 1 : mIRs[ilink].orbit; @@ -202,7 +189,7 @@ void GBTOutputHandler::onDoneRegDebug(size_t ilink, const ELinkDecoder& decoder) // local and regional cards for the checks intRec -= mElectronicsDelay.regToLocal; } - mROFRecords.emplace_back(intRec, eventType, firstEntry, 1); + mROFRecords->emplace_back(intRec, eventType, firstEntry, 1); } } // namespace mid diff --git a/Detectors/MUON/MID/Raw/src/GBTUserLogicDecoder.cxx b/Detectors/MUON/MID/Raw/src/GBTUserLogicDecoder.cxx deleted file mode 100644 index 0e4e78c14dbd2..0000000000000 --- a/Detectors/MUON/MID/Raw/src/GBTUserLogicDecoder.cxx +++ /dev/null @@ -1,65 +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. - -/// \file MID/Raw/src/GBTUserLogicDecoder.cxx -/// \brief MID GBT decoder with user logic zero suppression -/// \author Diego Stocco <Diego.Stocco at cern.ch> -/// \date 15 April 2020 - -#include "MIDRaw/GBTUserLogicDecoder.h" - -namespace o2 -{ -namespace mid -{ - -void GBTUserLogicDecoder::init(uint16_t feeId, bool isDebugMode) -{ - /// Initializes the task - mOutputHandler.setFeeId(feeId); - if (isDebugMode) { - mOnDoneLoc = &GBTOutputHandler::onDoneLocDebug; - mOnDoneReg = &GBTOutputHandler::onDoneRegDebug; - } -} - -void GBTUserLogicDecoder::process(gsl::span<const uint8_t> bytes, uint16_t bc, uint32_t orbit, uint16_t pageCnt) -{ - /// Decodes the buffer - mOutputHandler.setIR(bc, orbit, pageCnt); - - bool isFeeding = false; - for (auto& byte : bytes) { - if (mELinkDecoder.getNBytes() == 0 && (byte & raw::sSTARTBIT) == 0) { - // The e-link decoder is empty, meaning that we expect a new board. - // The first byte of the board should have the STARTBIT on. - // If this is not the case, it means that: - // a) there was a problem in the decoding - // b) we reached the end of the payload (and we have zeros until the end of the 256 bits word) - // In both cases, we need to stop - break; - } - mELinkDecoder.add(byte); - if (mELinkDecoder.isComplete()) { - if (raw::isLoc(mELinkDecoder.getStatusWord())) { - std::invoke(mOnDoneLoc, mOutputHandler, mELinkDecoder.getId() % 8, mELinkDecoder); - } else { - size_t ilink = 8 + mELinkDecoder.getId() % 8; - if (ilink > 9) { - continue; - } - std::invoke(mOnDoneReg, mOutputHandler, 8 + mELinkDecoder.getId() % 8, mELinkDecoder); - } - mELinkDecoder.reset(); - } - } -} -} // namespace mid -} // namespace o2 diff --git a/Detectors/MUON/MID/Raw/test/bench_Raw.cxx b/Detectors/MUON/MID/Raw/test/bench_Raw.cxx index f2a66b98231dd..ebceb7727644e 100644 --- a/Detectors/MUON/MID/Raw/test/bench_Raw.cxx +++ b/Detectors/MUON/MID/Raw/test/bench_Raw.cxx @@ -19,10 +19,11 @@ #include "CommonDataFormat/InteractionRecord.h" #include "DetectorsRaw/RawFileReader.h" #include "DPLUtils/RawParser.h" +#include "DataFormatsMID/ColumnData.h" #include "MIDBase/DetectorParameters.h" #include "MIDRaw/Decoder.h" -#include "MIDRaw/GBTUserLogicDecoder.h" #include "MIDRaw/Encoder.h" +#include "MIDRaw/GBTDecoder.h" o2::mid::ColumnData getColData(uint8_t deId, uint8_t columnId, uint16_t nbp = 0, uint16_t bp1 = 0, uint16_t bp2 = 0, uint16_t bp3 = 0, uint16_t bp4 = 0) { @@ -60,10 +61,11 @@ std::vector<uint8_t> generateTestData(size_t nTF, size_t nDataInTF, size_t nColD auto severity = fair::Logger::GetConsoleSeverity(); fair::Logger::SetConsoleSeverity(fair::Severity::WARNING); - std::string tmpFilename = "tmp_mid_raw.dat"; + std::string tmpFilename = "tmp_mid_raw.raw"; o2::mid::Encoder encoder; encoder.init(tmpFilename.c_str()); - + std::string tmpConfigFilename = "tmp_MIDConfig.cfg"; + encoder.getWriter().writeConfFile("MID", "RAWDATA", tmpConfigFilename.c_str(), false); // Fill TF for (size_t itf = 0; itf < nTF; ++itf) { for (int ilocal = 0; ilocal < nDataInTF; ++ilocal) { @@ -73,8 +75,7 @@ std::vector<uint8_t> generateTestData(size_t nTF, size_t nDataInTF, size_t nColD } encoder.finalize(); - o2::raw::RawFileReader rawReader; - rawReader.addFile(tmpFilename.c_str()); + o2::raw::RawFileReader rawReader(tmpConfigFilename.c_str()); rawReader.init(); size_t nActiveLinks = rawReader.getNLinks() < nLinks ? rawReader.getNLinks() : nLinks; std::vector<char> buffer; @@ -94,6 +95,7 @@ std::vector<uint8_t> generateTestData(size_t nTF, size_t nDataInTF, size_t nColD fair::Logger::SetConsoleSeverity(severity); std::remove(tmpFilename.c_str()); + std::remove(tmpConfigFilename.c_str()); std::vector<uint8_t> data(buffer.size()); memcpy(data.data(), buffer.data(), buffer.size()); @@ -103,7 +105,7 @@ std::vector<uint8_t> generateTestData(size_t nTF, size_t nDataInTF, size_t nColD static void BM_Decoder(benchmark::State& state) { - o2::mid::Decoder<o2::mid::GBTUserLogicDecoder> decoder; + o2::mid::Decoder decoder; int nTF = state.range(0); int nEventPerTF = state.range(1); @@ -122,8 +124,7 @@ static void BM_Decoder(benchmark::State& state) static void BM_GBTDecoder(benchmark::State& state) { - o2::mid::GBTUserLogicDecoder decoder; - decoder.init(0, false); + auto decoder = o2::mid::createGBTDecoder(0); int nTF = state.range(0); int nEventPerTF = state.range(1); @@ -131,9 +132,12 @@ static void BM_GBTDecoder(benchmark::State& state) double num{0}; auto inputData = generateTestData(nTF, nEventPerTF, nFiredPerEvent, 1); + std::vector<o2::mid::LocalBoardRO> data; + std::vector<o2::mid::ROFRecord> rofs; for (auto _ : state) { - decoder.clear(); + data.clear(); + rofs.clear(); o2::framework::RawParser parser(inputData.data(), inputData.size()); for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { if (it.size() == 0) { @@ -141,7 +145,7 @@ static void BM_GBTDecoder(benchmark::State& state) } auto* rdhPtr = it.template get_if<o2::header::RAWDataHeader>(); gsl::span<const uint8_t> payload(it.data(), it.size()); - decoder.process(payload, *rdhPtr); + decoder->process(payload, *rdhPtr, data, rofs); } ++num; } diff --git a/Detectors/MUON/MID/Raw/test/testRaw.cxx b/Detectors/MUON/MID/Raw/test/testRaw.cxx index 2859ac6f83b8a..1951ffc2ee84b 100644 --- a/Detectors/MUON/MID/Raw/test/testRaw.cxx +++ b/Detectors/MUON/MID/Raw/test/testRaw.cxx @@ -32,7 +32,7 @@ #include "MIDRaw/CrateParameters.h" #include "MIDRaw/DecodedDataAggregator.h" #include "MIDRaw/Decoder.h" -#include "MIDRaw/GBTUserLogicDecoder.h" +#include "MIDRaw/GBTDecoder.h" #include "MIDRaw/GBTUserLogicEncoder.h" #include "MIDRaw/Encoder.h" @@ -119,7 +119,7 @@ std::tuple<std::vector<o2::mid::ColumnData>, std::vector<o2::mid::ROFRecord>> en std::remove(tmpFilename.c_str()); std::remove(tmpConfigFilename.c_str()); - o2::mid::Decoder<o2::mid::GBTUserLogicDecoder> decoder; + o2::mid::Decoder decoder; gsl::span<const uint8_t> data(reinterpret_cast<uint8_t*>(buffer.data()), buffer.size()); decoder.process(data); @@ -206,17 +206,18 @@ BOOST_AUTO_TEST_CASE(GBTUserLogicDecoder) rdh.word1 |= (memSize | (memSize << 16)); // Sets the feeId rdh.word0 |= ((5 * 2) << 16); - o2::mid::GBTUserLogicDecoder decoder; - decoder.init(feeId); + auto decoder = o2::mid::createGBTDecoder(feeId); + std::vector<o2::mid::LocalBoardRO> data; + std::vector<o2::mid::ROFRecord> rofs; std::vector<uint8_t> convertedBuffer(buf.size()); memcpy(convertedBuffer.data(), buf.data(), buf.size()); - decoder.process(convertedBuffer, rdh); - BOOST_REQUIRE(decoder.getROFRecords().size() == inData.size()); + decoder->process(convertedBuffer, rdh, data, rofs); + BOOST_REQUIRE(rofs.size() == inData.size()); auto inItMap = inData.begin(); - for (auto rofIt = decoder.getROFRecords().begin(); rofIt != decoder.getROFRecords().end(); ++rofIt) { + for (auto rofIt = rofs.begin(); rofIt != rofs.end(); ++rofIt) { BOOST_TEST(rofIt->interactionRecord.bc == inItMap->first); BOOST_TEST(rofIt->nEntries == inItMap->second.size()); - auto outLoc = decoder.getData().begin() + rofIt->firstEntry; + auto outLoc = data.begin() + rofIt->firstEntry; for (auto inLoc = inItMap->second.begin(); inLoc != inItMap->second.end(); ++inLoc) { BOOST_TEST(inLoc->statusWord == outLoc->statusWord); BOOST_TEST(inLoc->triggerWord == outLoc->triggerWord); diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h index 43c2c58b791bb..84fca6bccc5d7 100644 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h @@ -25,8 +25,8 @@ namespace o2 { namespace mid { -framework::DataProcessorSpec getRawDecoderSpec(bool isBare = false); -framework::DataProcessorSpec getRawDecoderSpec(bool isBare, bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay); +framework::DataProcessorSpec getRawDecoderSpec(bool isDebugMode = false); +framework::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, size_t subSpec = 0); } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx b/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx index 93fbf2bf248f6..307620db2fad3 100644 --- a/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx @@ -20,7 +20,6 @@ #include "Framework/Logger.h" #include "Framework/Output.h" #include "Framework/Task.h" -#include "Framework/WorkflowSpec.h" #include "DPLUtils/DPLRawParser.h" #include "Headers/RDHAny.h" #include "MIDRaw/Decoder.h" @@ -32,25 +31,19 @@ namespace o2 namespace mid { -template <typename GBTDECODER> class RawDecoderDeviceDPL { public: - RawDecoderDeviceDPL<GBTDECODER>(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay) : mIsDebugMode(isDebugMode), mFeeIdConfig(feeIdConfig), mCrateMasks(crateMasks), mElectronicsDelay(electronicsDelay) {} + RawDecoderDeviceDPL(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, header::DataHeader::SubSpecificationType subSpec) : mIsDebugMode(isDebugMode), mFeeIdConfig(feeIdConfig), mCrateMasks(crateMasks), mElectronicsDelay(electronicsDelay), mSubSpec(subSpec) {} void init(of::InitContext& ic) { auto stop = [this]() { - LOG(INFO) << "Capacities: ROFRecords: " << mDecoder.getROFRecords().capacity() << " LocalBoards: " << mDecoder.getData().capacity(); + LOG(INFO) << "Capacities: ROFRecords: " << mDecoder->getROFRecords().capacity() << " LocalBoards: " << mDecoder->getData().capacity(); double scaleFactor = 1.e6 / mNROFs; LOG(INFO) << "Processing time / " << mNROFs << " ROFs: full: " << mTimer.count() * scaleFactor << " us decoding: " << mTimerAlgo.count() * scaleFactor << " us"; }; ic.services().get<of::CallbackService>().set(of::CallbackService::Id::Stop, stop); - - mDecoder.setFeeIdConfig(mFeeIdConfig); - mDecoder.setCrateMasks(mCrateMasks); - - mDecoder.init(mIsDebugMode); } void run(of::ProcessingContext& pc) @@ -58,51 +51,57 @@ class RawDecoderDeviceDPL auto tStart = std::chrono::high_resolution_clock::now(); auto tAlgoStart = std::chrono::high_resolution_clock::now(); - of::DPLRawParser parser(pc.inputs(), of::select("mid_raw:MID/RAWDATA")); + of::DPLRawParser parser(pc.inputs()); + + if (!mDecoder) { + auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(parser.begin().raw()); + mDecoder = createDecoder(*rdhPtr, mIsDebugMode, mElectronicsDelay, mCrateMasks, mFeeIdConfig); + } - mDecoder.clear(); + mDecoder->clear(); for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(it.raw()); gsl::span<const uint8_t> payload(it.data(), it.size()); - mDecoder.process(payload, *rdhPtr); + mDecoder->process(payload, *rdhPtr); } - mDecoder.flush(); mTimerAlgo += std::chrono::high_resolution_clock::now() - tAlgoStart; - pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODED", 0}, mDecoder.getData()); - pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODEDROF", 0}, mDecoder.getROFRecords()); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODED", mSubSpec}, mDecoder->getData()); + pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DECODEDROF", mSubSpec}, mDecoder->getROFRecords()); mTimer += std::chrono::high_resolution_clock::now() - tStart; - mNROFs += mDecoder.getROFRecords().size(); + mNROFs += mDecoder->getROFRecords().size(); } private: - Decoder<GBTDECODER> mDecoder{}; + std::unique_ptr<Decoder> mDecoder{nullptr}; bool mIsDebugMode{false}; FEEIdConfig mFeeIdConfig{}; CrateMasks mCrateMasks{}; ElectronicsDelay mElectronicsDelay{}; + header::DataHeader::SubSpecificationType mSubSpec{0}; std::chrono::duration<double> mTimer{0}; ///< full timer std::chrono::duration<double> mTimerAlgo{0}; ///< algorithm timer unsigned int mNROFs{0}; /// Total number of processed ROFs }; -of::DataProcessorSpec getRawDecoderSpec(bool isBare) +of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode) { - return getRawDecoderSpec(isBare, false, FEEIdConfig(), CrateMasks(), ElectronicsDelay()); + return getRawDecoderSpec(isDebugMode, FEEIdConfig(), CrateMasks(), ElectronicsDelay(), 0); } -of::DataProcessorSpec getRawDecoderSpec(bool isBare, bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay) +of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, size_t subSpec) { + header::DataHeader::SubSpecificationType subSpecType(subSpec); std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_raw", of::ConcreteDataTypeMatcher{header::gDataOriginMID, header::gDataDescriptionRawData}, of::Lifetime::Timeframe}}; - std::vector<of::OutputSpec> outputSpecs{of::OutputSpec{header::gDataOriginMID, "DECODED", 0, of::Lifetime::Timeframe}, of::OutputSpec{header::gDataOriginMID, "DECODEDROF", 0, of::Lifetime::Timeframe}}; + std::vector<of::OutputSpec> outputSpecs{of::OutputSpec{header::gDataOriginMID, "DECODED", subSpecType, of::Lifetime::Timeframe}, of::OutputSpec{header::gDataOriginMID, "DECODEDROF", subSpecType, of::Lifetime::Timeframe}}; return of::DataProcessorSpec{ "MIDRawDecoder", {inputSpecs}, {outputSpecs}, - isBare ? of::adaptFromTask<o2::mid::RawDecoderDeviceDPL<o2::mid::GBTBareDecoder>>(isDebugMode, feeIdConfig, crateMasks, electronicsDelay) : of::adaptFromTask<o2::mid::RawDecoderDeviceDPL<o2::mid::GBTUserLogicDecoder>>(isDebugMode, feeIdConfig, crateMasks, electronicsDelay)}; + of::adaptFromTask<o2::mid::RawDecoderDeviceDPL>(isDebugMode, feeIdConfig, crateMasks, electronicsDelay, subSpecType)}; } } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx b/Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx index 8e9e964b11b0e..9f42c3dc6623d 100644 --- a/Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/raw-to-digits-workflow.cxx @@ -30,7 +30,6 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) {"feeId-config-file", VariantType::String, "", {"Filename with crate FEE ID correspondence"}}, {"crate-masks-file", VariantType::String, "", {"Filename with crate masks"}}, {"electronics-delay-file", VariantType::String, "", {"Filename with electronics delay"}}, - {"bare", VariantType::Bool, false, {"Is bare decoder"}}, {"decode-only", o2::framework::VariantType::Bool, false, {"Output decoded boards instead of digits"}}}; workflowOptions.insert(workflowOptions.end(), options.begin(), options.end()); } @@ -55,11 +54,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) electronicsDelay = o2::mid::readElectronicsDelay(electronicsDelayFilename.c_str()); } - bool isBare = cfgc.options().get<bool>("bare"); bool decodeOnly = cfgc.options().get<bool>("decode-only"); o2::framework::WorkflowSpec specs; - specs.emplace_back(o2::mid::getRawDecoderSpec(isBare, false, feeIdConfig, crateMasks, electronicsDelay)); + specs.emplace_back(o2::mid::getRawDecoderSpec(false, feeIdConfig, crateMasks, electronicsDelay)); if (!decodeOnly) { specs.emplace_back(o2::mid::getRawAggregatorSpec()); } From dedaa7003a8b7ccad51aa5982ac5efb1072af391 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Tue, 27 Oct 2020 12:27:18 +0100 Subject: [PATCH 1374/1751] [rANS] I/O iterators for fusing arrays Implementation and Tests for a pair of input/output iterators that allow to merge or split the values of two iterators efficiently via a user defined transformation function. The flexible desing allows for nesting. * `CombinedInputIterator` is an iterator class respecting the STLs type trait of an InputIterator. It takes two arbitrary input iterators and a user defined transformation function (FP, Functor or lambda). The transformation function is applied when dereferencing the iterator and the result is returned by value. * `CombinedOutputIterator` is an iterator class respecting the STLs type trait of an OutputIterator. It takes two arbitrary output iterators and a user defined transformation function (FP, Functor or lambda). The transformation function is applied during assignment to the dereferenced iterator. Both iterators allow nesting, i.e. it is possible to use a `CombinedInputIterator` as the input for another `CombinedInputIterator` --- Utilities/rANS/CMakeLists.txt | 7 + Utilities/rANS/include/rANS/utils.h | 16 ++ .../include/rANS/utils/CombinedIterator.h | 220 ++++++++++++++++++ .../rANS/test/test_ransCombinedIterator.cxx | 164 +++++++++++++ 4 files changed, 407 insertions(+) create mode 100644 Utilities/rANS/include/rANS/utils.h create mode 100644 Utilities/rANS/include/rANS/utils/CombinedIterator.h create mode 100644 Utilities/rANS/test/test_ransCombinedIterator.cxx diff --git a/Utilities/rANS/CMakeLists.txt b/Utilities/rANS/CMakeLists.txt index 46e86f0cf3767..083673ce7accc 100644 --- a/Utilities/rANS/CMakeLists.txt +++ b/Utilities/rANS/CMakeLists.txt @@ -27,6 +27,13 @@ o2_add_test(FrequencyTable COMPONENT_NAME rANS LABELS utils) +o2_add_test(CombinedIterator + NAME CombinedIterator + SOURCES test/test_ransCombinedIterator.cxx + PUBLIC_LINK_LIBRARIES O2::rANS + COMPONENT_NAME rANS + LABELS utils) + o2_add_executable(rans-encode-decode-8 TARGETVARNAME targetName SOURCES run/bin-encode-decode.cxx diff --git a/Utilities/rANS/include/rANS/utils.h b/Utilities/rANS/include/rANS/utils.h new file mode 100644 index 0000000000000..69517c65be9da --- /dev/null +++ b/Utilities/rANS/include/rANS/utils.h @@ -0,0 +1,16 @@ +// 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 utils.h +/// @author Michael Lettrich +/// @since 2020-11-18 +/// @brief header for utils + +#include "utils/CombinedIterator.h" diff --git a/Utilities/rANS/include/rANS/utils/CombinedIterator.h b/Utilities/rANS/include/rANS/utils/CombinedIterator.h new file mode 100644 index 0000000000000..f1569731e644c --- /dev/null +++ b/Utilities/rANS/include/rANS/utils/CombinedIterator.h @@ -0,0 +1,220 @@ +// 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 CombinedIterator.h +/// \brief +/// \author michael.lettrich@cern.ch + +#ifndef INCLUDE_RANS_UTILS_COMBINEDITERATOR_H_ +#define INCLUDE_RANS_UTILS_COMBINEDITERATOR_H_ + +#include <cstddef> +#include <cassert> +#include <cstdint> +#include <type_traits> +#include <iostream> +#include <iterator> + +namespace o2 +{ +namespace rans +{ +namespace utils +{ + +template <class iterA_T, class iterB_T, class F> +class CombinedInputIterator +{ + using difference_type = std::ptrdiff_t; + using value_type = std::result_of<F(iterA_T, iterB_T)>; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::input_iterator_tag; + + public: + CombinedInputIterator(iterA_T iterA, iterB_T iterB, F functor); + CombinedInputIterator(const CombinedInputIterator& iter) = default; + CombinedInputIterator(CombinedInputIterator&& iter) = default; + CombinedInputIterator& operator=(const CombinedInputIterator& other); + CombinedInputIterator& operator=(CombinedInputIterator&& other) = default; + ~CombinedInputIterator() = default; + + //comparison + bool operator==(const CombinedInputIterator& other) const; + bool operator!=(const CombinedInputIterator& other) const; + + //pointer arithmetics + CombinedInputIterator& operator++(); + CombinedInputIterator operator++(int); + + // dereference + auto operator*() const; + + private: + iterA_T mIterA; + iterB_T mIterB; + F mFunctor; + + public: + friend std::ostream& operator<<(std::ostream& o, const CombinedInputIterator& iter) + { + o << "CombinedInputIterator{iterA: " << &(iter.mIterA) << ", iterB: " << &(iter.mIterB) << "}"; + return o; + } +}; + +template <class iterA_T, class iterB_T, class F> +class CombinedOutputIterator +{ + + class Proxy + { + public: + Proxy(CombinedOutputIterator& iter); + + template <typename value_T> + Proxy& operator=(value_T value); + + private: + CombinedOutputIterator& mIter; + }; + + using difference_type = std::ptrdiff_t; + using value_type = Proxy; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::input_iterator_tag; + + public: + CombinedOutputIterator(iterA_T iterA, iterB_T iterB, F functor); + CombinedOutputIterator(const CombinedOutputIterator& iter) = default; + CombinedOutputIterator(CombinedOutputIterator&& iter) = default; + CombinedOutputIterator& operator=(const CombinedOutputIterator& other); + CombinedOutputIterator& operator=(CombinedOutputIterator&& other) = default; + ~CombinedOutputIterator() = default; + + //pointer arithmetics + CombinedOutputIterator& operator++(); + CombinedOutputIterator operator++(int); + + // dereference + value_type operator*(); + + private: + iterA_T mIterA; + iterB_T mIterB; + F mFunctor; + + public: + friend std::ostream& operator<<(std::ostream& o, const CombinedOutputIterator& iter) + { + o << "CombinedOutputIterator{iterA: " << &(iter.mIterA) << ", iterB: " << &(iter.mIterB) << "}"; + return o; + } +}; + +template <class iterA_T, class iterB_T, class F> +CombinedInputIterator<iterA_T, iterB_T, F>::CombinedInputIterator(iterA_T iterA, iterB_T iterB, F functor) : mIterA(iterA), mIterB(iterB), mFunctor(functor) +{ +} + +template <class iterA_T, class iterB_T, class F> +auto CombinedInputIterator<iterA_T, iterB_T, F>::operator=(const CombinedInputIterator& other) -> CombinedInputIterator& +{ + mIterA = other.mIterA; + mIterB = other.mIterB; +} + +template <class iterA_T, class iterB_T, class F> +inline bool CombinedInputIterator<iterA_T, iterB_T, F>::operator==(const CombinedInputIterator& other) const +{ + return (mIterA == other.mIterA) && (mIterB == other.mIterB); +} + +template <class iterA_T, class iterB_T, class F> +inline bool CombinedInputIterator<iterA_T, iterB_T, F>::operator!=(const CombinedInputIterator& other) const +{ + return !(*this == other); +} + +template <class iterA_T, class iterB_T, class F> +inline auto CombinedInputIterator<iterA_T, iterB_T, F>::operator++() -> CombinedInputIterator& +{ + ++mIterA; + ++mIterB; + return *this; +} + +template <class iterA_T, class iterB_T, class F> +inline auto CombinedInputIterator<iterA_T, iterB_T, F>::operator++(int) -> CombinedInputIterator +{ + auto res = *this; + ++(*this); + return res; +} + +template <class iterA_T, class iterB_T, class F> +inline auto CombinedInputIterator<iterA_T, iterB_T, F>::operator*() const +{ + return mFunctor(mIterA, mIterB); +} + +template <class iterA_T, class iterB_T, class F> +CombinedOutputIterator<iterA_T, iterB_T, F>::CombinedOutputIterator(iterA_T iterA, iterB_T iterB, F functor) : mIterA(iterA), mIterB(iterB), mFunctor(functor) +{ +} + +template <class iterA_T, class iterB_T, class F> +auto CombinedOutputIterator<iterA_T, iterB_T, F>::operator=(const CombinedOutputIterator& other) -> CombinedOutputIterator& +{ + mIterA = other.mIterA; + mIterB = other.mIterB; +} + +template <class iterA_T, class iterB_T, class F> +inline auto CombinedOutputIterator<iterA_T, iterB_T, F>::operator++() -> CombinedOutputIterator& +{ + ++mIterA; + ++mIterB; + return *this; +} + +template <class iterA_T, class iterB_T, class F> +inline auto CombinedOutputIterator<iterA_T, iterB_T, F>::operator++(int) -> CombinedOutputIterator +{ + auto res = *this; + ++(*this); + return res; +} + +template <class iterA_T, class iterB_T, class F> +inline auto CombinedOutputIterator<iterA_T, iterB_T, F>::operator*() -> value_type +{ + return Proxy(*this); +} + +template <class iterA_T, class iterB_T, class F> +CombinedOutputIterator<iterA_T, iterB_T, F>::Proxy::Proxy(CombinedOutputIterator& iter) : mIter(iter) +{ +} + +template <class iterA_T, class iterB_T, class F> +template <typename value_T> +inline auto CombinedOutputIterator<iterA_T, iterB_T, F>::Proxy::operator=(value_T value) -> CombinedOutputIterator::Proxy& +{ + mIter.mFunctor(mIter.mIterA, mIter.mIterB, value); + return *this; +} + +} // namespace utils +} // namespace rans +} // namespace o2 + +#endif /* INCLUDE_RANS_UTILS_COMBINEDITERATOR_H_ */ diff --git a/Utilities/rANS/test/test_ransCombinedIterator.cxx b/Utilities/rANS/test/test_ransCombinedIterator.cxx new file mode 100644 index 0000000000000..e9a14774df33e --- /dev/null +++ b/Utilities/rANS/test/test_ransCombinedIterator.cxx @@ -0,0 +1,164 @@ +// 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 test_ransCombinedIterator.cxx +/// @author michael.lettrich@cern.ch +/// @since 2020-10-28 +/// @brief + +#define BOOST_TEST_MODULE Utility test +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> + +#include "rANS/utils.h" + +struct test_CombninedIteratorFixture { + std::vector<uint16_t> a{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + std::vector<uint16_t> b{a.rbegin(), a.rend()}; + size_t shift = 16; + std::vector<uint32_t> aAndB{0x0001000f, 0x0002000e, 0x0003000d, 0x0004000c, 0x0005000b, + 0x0006000a, 0x00070009, 0x00080008, 0x00090007, 0x000a0006, + 0x000b0005, 0x000c0004, 0x000d0003, 0x000e0002, 0x000f0001}; +}; + +class ReadShiftFunctor +{ + public: + ReadShiftFunctor(size_t shift) : mShift(shift){}; + + template <typename iterA_T, typename iterB_T> + inline uint32_t operator()(iterA_T iterA, iterB_T iterB) const + { + return *iterB + (static_cast<uint32_t>(*iterA) << mShift); + }; + + private: + size_t mShift; +}; + +class WriteShiftFunctor +{ + public: + WriteShiftFunctor(size_t shift) : mShift(shift){}; + + template <typename iterA_T, typename iterB_T> + inline void operator()(iterA_T iterA, iterB_T iterB, uint32_t value) const + { + *iterA = value >> mShift; + *iterB = value & ((1 << mShift) - 1); + }; + + private: + size_t mShift; +}; + +BOOST_FIXTURE_TEST_CASE(test_CombinedInputIteratorBase, test_CombninedIteratorFixture) +{ + + // auto readOP = [](auto iterA, auto iterB) -> uint32_t { + // return *iterB + (static_cast<uint32_t>(*iterA) << 16); + // }; + + ReadShiftFunctor f(shift); + + o2::rans::utils::CombinedInputIterator iter(a.begin(), b.begin(), f); + // test equal + const o2::rans::utils::CombinedInputIterator first(a.begin(), b.begin(), f); + BOOST_CHECK_EQUAL(iter, first); + // test not equal + const o2::rans::utils::CombinedInputIterator second(++(a.begin()), ++(b.begin()), f); + BOOST_CHECK_NE(iter, second); + // test pre increment + ++iter; + BOOST_CHECK_EQUAL(iter, second); + //test postIncrement + iter = first; + BOOST_CHECK_EQUAL(iter++, first); + BOOST_CHECK_EQUAL(iter, second); + //test deref + const uint32_t val = first.operator*(); + BOOST_CHECK_EQUAL(val, aAndB.front()); +} + +BOOST_FIXTURE_TEST_CASE(test_CombinedOutputIteratorBase, test_CombninedIteratorFixture) +{ + std::vector<uint16_t> aOut(2, 0x0); + std::vector<uint16_t> bOut(2, 0x0); + + // auto writeOP = [](auto iterA, auto iterB, uint32_t value) -> void { + // const uint32_t shift = 16; + // *iterA = value >> shift; + // *iterB = value & ((1 << shift) - 1); + // }; + + WriteShiftFunctor f(shift); + + o2::rans::utils::CombinedOutputIterator iter(aOut.begin(), bOut.begin(), f); + + // test deref: + *iter = aAndB[0]; + BOOST_CHECK_EQUAL(aOut[0], a[0]); + BOOST_CHECK_EQUAL(bOut[0], b[0]); + aOut[0] = 0x0; + bOut[0] = 0x0; + + // test pre increment + *(++iter) = aAndB[1]; + BOOST_CHECK_EQUAL(aOut[0], 0); + BOOST_CHECK_EQUAL(bOut[0], 0); + BOOST_CHECK_EQUAL(aOut[1], a[1]); + BOOST_CHECK_EQUAL(bOut[1], b[1]); + aOut.assign(2, 0x0); + bOut.assign(2, 0x0); + iter = o2::rans::utils::CombinedOutputIterator(aOut.begin(), bOut.begin(), f); + + // test post increment + auto preInc = iter++; + *preInc = aAndB[0]; + BOOST_CHECK_EQUAL(aOut[0], a[0]); + BOOST_CHECK_EQUAL(bOut[0], b[0]); + BOOST_CHECK_EQUAL(aOut[1], 0x0); + BOOST_CHECK_EQUAL(bOut[1], 0x0); + aOut.assign(2, 0x0); + bOut.assign(2, 0x0); + *iter = aAndB[1]; + BOOST_CHECK_EQUAL(aOut[0], 0); + BOOST_CHECK_EQUAL(bOut[0], 0); + BOOST_CHECK_EQUAL(aOut[1], a[1]); + BOOST_CHECK_EQUAL(bOut[1], b[1]); +} + +BOOST_FIXTURE_TEST_CASE(test_CombinedInputIteratorReadArray, test_CombninedIteratorFixture) +{ + // auto readOP = [](auto iterA, auto iterB) -> uint32_t { + // return *iterB + (static_cast<uint32_t>(*iterA) << 16); + // }; + ReadShiftFunctor f(shift); + + const o2::rans::utils::CombinedInputIterator begin(a.begin(), b.begin(), f); + const o2::rans::utils::CombinedInputIterator end(a.end(), b.end(), f); + BOOST_CHECK_EQUAL_COLLECTIONS(begin, end, aAndB.begin(), aAndB.end()); +} + +BOOST_FIXTURE_TEST_CASE(test_CombinedOutputIteratorWriteArray, test_CombninedIteratorFixture) +{ + std::vector<uint16_t> aRes(a.size(), 0); + std::vector<uint16_t> bRes(b.size(), 0); + + o2::rans::utils::CombinedOutputIterator iter(aRes.begin(), bRes.begin(), WriteShiftFunctor(shift)); + for (auto input : aAndB) { + *iter++ = input; + } + + BOOST_CHECK_EQUAL_COLLECTIONS(aRes.begin(), aRes.end(), a.begin(), a.end()); + BOOST_CHECK_EQUAL_COLLECTIONS(bRes.begin(), bRes.end(), b.begin(), b.end()); +} From 04e7ab7b53cdc471c08cb2d11c4f36965140988f Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Wed, 18 Nov 2020 19:02:45 +0100 Subject: [PATCH 1375/1751] [rANS] Benchmarks for CombinedIterator Benchmarks to test the performance of `CombinedInputIterator` and `CombinedOutputIterator` vs a brute force copy. --- Utilities/rANS/CMakeLists.txt | 7 ++ .../benchmarks/bench_ransCombinedIterator.cxx | 113 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 Utilities/rANS/benchmarks/bench_ransCombinedIterator.cxx diff --git a/Utilities/rANS/CMakeLists.txt b/Utilities/rANS/CMakeLists.txt index 083673ce7accc..a56d9098ffe49 100644 --- a/Utilities/rANS/CMakeLists.txt +++ b/Utilities/rANS/CMakeLists.txt @@ -13,6 +13,7 @@ o2_add_library(rANS src/FrequencyTable.cxx PUBLIC_LINK_LIBRARIES FairLogger::FairLogger) + o2_add_test(EncodeDecode NAME EncodeDecode SOURCES test/test_ransEncodeDecode.cxx @@ -34,6 +35,12 @@ o2_add_test(CombinedIterator COMPONENT_NAME rANS LABELS utils) +o2_add_executable(CombinedIterator + SOURCES benchmarks/bench_ransCombinedIterator.cxx + COMPONENT_NAME rANS + IS_BENCHMARK + PUBLIC_LINK_LIBRARIES O2::rANS benchmark::benchmark) + o2_add_executable(rans-encode-decode-8 TARGETVARNAME targetName SOURCES run/bin-encode-decode.cxx diff --git a/Utilities/rANS/benchmarks/bench_ransCombinedIterator.cxx b/Utilities/rANS/benchmarks/bench_ransCombinedIterator.cxx new file mode 100644 index 0000000000000..8b3ab59181cd0 --- /dev/null +++ b/Utilities/rANS/benchmarks/bench_ransCombinedIterator.cxx @@ -0,0 +1,113 @@ +// 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 bench_ransCombinedIterator.cxx +/// @author Michael Lettrich +/// @since Nov 18, 2020 +/// @brief + +#include <vector> + +#include <benchmark/benchmark.h> + +#include "rANS/utils.h" + +static void BM_Array_Read_Copy(benchmark::State& state) +{ + std::vector<uint32_t> a(state.range(0), 0x0); + std::vector<uint32_t> b(state.range(0), 0x1); + std::vector<uint32_t> c(state.range(0), 0x0); + for (auto _ : state) { + std::vector<uint32_t> tmp(state.range(0)); + + for (size_t i = 0; i < a.size(); ++i) { + tmp[i] = b[i] + (a[i] << 16); + } + + for (size_t i = 0; i < tmp.size(); ++i) { + c[i] = tmp[i] + 1; + } + } +} + +BENCHMARK(BM_Array_Read_Copy)->RangeMultiplier(2)->Range(10e4, 2 * 10e6); + +static void BM_Array_Read_Iterator(benchmark::State& state) +{ + std::vector<uint32_t> a(state.range(0), 0x0); + std::vector<uint32_t> b(state.range(0), 0x1); + std::vector<uint32_t> c(state.range(0), 0x0); + + for (auto _ : state) { + auto readOP = [](auto iterA, auto iterB) -> uint32_t { + return *iterB + (*iterA << 16); + }; + + const o2::rans::utils::CombinedInputIterator begin(a.begin(), b.begin(), readOP); + const o2::rans::utils::CombinedInputIterator end(a.end(), b.end(), readOP); + + auto cIter = c.begin(); + + for (auto iter = begin; iter != end; ++iter) { + *cIter = *iter + 1; + ++cIter; + } + } +} + +BENCHMARK(BM_Array_Read_Iterator)->RangeMultiplier(2)->Range(10e4, 2 * 10e6); + +static void BM_Array_Write_Copy(benchmark::State& state) +{ + std::vector<uint32_t> a(state.range(0), 0x0); + std::vector<uint32_t> b(state.range(0), 0x0); + std::vector<uint32_t> c(state.range(0), 0x0001000f); + for (auto _ : state) { + std::vector<uint32_t> tmp(state.range(0)); + + for (size_t i = 0; i < c.size(); ++i) { + tmp[i] = c[i] + 1; + } + + for (size_t i = 0; i < a.size(); ++i) { + const uint32_t shift = 16; + a[i] = tmp[i] >> shift; + b[i] = tmp[i] & ((1 << shift) - 1); + } + } +} + +BENCHMARK(BM_Array_Write_Copy)->RangeMultiplier(2)->Range(10e4, 2 * 10e6); + +static void BM_Array_Write_Iterator(benchmark::State& state) +{ + std::vector<uint32_t> a(state.range(0), 0x0); + std::vector<uint32_t> b(state.range(0), 0x0); + std::vector<uint32_t> c(state.range(0), 0x0001000f); + + for (auto _ : state) { + auto writeOP = [](auto iterA, auto iterB, uint32_t value) -> void { + const uint32_t shift = 16; + *iterA = value >> shift; + *iterB = value & ((1 << shift) - 1); + }; + + o2::rans::utils::CombinedOutputIterator out(a.begin(), b.begin(), writeOP); + + for (auto iter = c.begin(); iter != c.end(); ++iter) { + *out = *iter + 1; + ++out; + } + } +} + +BENCHMARK(BM_Array_Write_Iterator)->RangeMultiplier(2)->Range(10e4, 2 * 10e6); + +BENCHMARK_MAIN(); From 51775f85ef8a030f247264eb126e07bde0e947a5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Nov 2020 15:05:20 +0100 Subject: [PATCH 1376/1751] DPL: report how many times we signaled AOD reader --- Framework/Core/src/CommonMessageBackends.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index c2a855820d36c..10bb38a521889 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -231,6 +231,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() } bool done = false; static int stateTransitions = 0; + static int signalsCount = 0; while (!done) { stateMetric(driverMetrics, (uint64_t)(currentState), stateTransitions++); switch (currentState) { @@ -248,7 +249,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() if (specs[di].name == "internal-dpl-aod-reader") { if (di < infos.size()) { kill(infos[di].pid, SIGUSR1); - totalSignalsMetric(driverMetrics, 1, timestamp); + totalSignalsMetric(driverMetrics, signalsCount++, timestamp); } } } @@ -269,7 +270,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() if (specs[di].name == "internal-dpl-aod-reader") { if (di < infos.size()) { kill(infos[di].pid, SIGUSR1); - totalSignalsMetric(driverMetrics, 1, timestamp); + totalSignalsMetric(driverMetrics, signalsCount++, timestamp); } } } From e70609774c640c33ed088437923dc7a98618dbad Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 19 Nov 2020 19:10:58 +0100 Subject: [PATCH 1377/1751] DPL: fix non-updated filledMetrics --- Framework/Core/include/Framework/DeviceMetricsInfo.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/include/Framework/DeviceMetricsInfo.h b/Framework/Core/include/Framework/DeviceMetricsInfo.h index 439537083e373..229fc48721bba 100644 --- a/Framework/Core/include/Framework/DeviceMetricsInfo.h +++ b/Framework/Core/include/Framework/DeviceMetricsInfo.h @@ -190,6 +190,7 @@ struct DeviceMetricsHelper { size_t pos = metric.pos++ % store[metric.storeIdx].size(); metrics.timestamps[metricIndex][pos] = timestamp; store[metric.storeIdx][pos] = value; + metric.filledMetrics++; }; } }; From 230ffebc49a942c3052910fff521d4079fce18a1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 19 Nov 2020 19:14:11 +0100 Subject: [PATCH 1378/1751] DPL: allow dumping driver metrics --- .../Core/src/ResourcesMonitoringHelper.cxx | 43 +++++++++++++++++++ .../Core/src/ResourcesMonitoringHelper.h | 1 + Framework/Core/src/runDataProcessing.cxx | 2 +- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/ResourcesMonitoringHelper.cxx b/Framework/Core/src/ResourcesMonitoringHelper.cxx index 28d90351816f7..495a655867041 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.cxx +++ b/Framework/Core/src/ResourcesMonitoringHelper.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "ResourcesMonitoringHelper.h" +#include "Framework/DeviceMetricsInfo.h" #include <boost/property_tree/json_parser.hpp> #include <fstream> #include <string_view> @@ -18,6 +19,7 @@ using namespace o2::framework; bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetricsInfo>& metrics, + const DeviceMetricsInfo& driverMetrics, const std::vector<DeviceSpec>& specs, std::vector<std::string> const& performanceMetrics) noexcept { @@ -75,6 +77,47 @@ bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetric root.add_child(specs[idx].name, deviceRoot); } + boost::property_tree::ptree driverRoot; + for (const auto& metricLabel : driverMetrics.metricLabelsIdx) { + + //check if we are interested + if (std::find(std::begin(performanceMetrics), std::end(performanceMetrics), metricLabel.label) == std::end(performanceMetrics)) { + continue; + } + + //if so + + boost::property_tree::ptree metricNode; + + switch (driverMetrics.metrics[metricLabel.index].type) { + case MetricType::Int: + metricNode = fillNodeWithValue(driverMetrics, driverMetrics.intMetrics, + metricLabel.index, driverMetrics.metrics[metricLabel.index].storeIdx); + break; + + case MetricType::Float: + metricNode = fillNodeWithValue(driverMetrics, driverMetrics.floatMetrics, + metricLabel.index, driverMetrics.metrics[metricLabel.index].storeIdx); + break; + + case MetricType::String: + metricNode = fillNodeWithValue(driverMetrics, driverMetrics.stringMetrics, + metricLabel.index, driverMetrics.metrics[metricLabel.index].storeIdx); + break; + + case MetricType::Uint64: + metricNode = fillNodeWithValue(driverMetrics, driverMetrics.uint64Metrics, + metricLabel.index, driverMetrics.metrics[metricLabel.index].storeIdx); + break; + + default: + continue; + } + driverRoot.add_child(metricLabel.label, metricNode); + } + + root.add_child("driver", driverRoot); + std::ofstream file("performanceMetrics.json", std::ios::out); if (file.is_open()) { boost::property_tree::json_parser::write_json(file, root); diff --git a/Framework/Core/src/ResourcesMonitoringHelper.h b/Framework/Core/src/ResourcesMonitoringHelper.h index d520f903b8b20..35352fc0eef13 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.h +++ b/Framework/Core/src/ResourcesMonitoringHelper.h @@ -26,6 +26,7 @@ struct ResourcesMonitoringHelper { /// Dump the metrics in @a metrics which match the names specified in @a metricsToDump /// @a specs are the DeviceSpecs associated to the metrics. static bool dumpMetricsToJSON(std::vector<DeviceMetricsInfo> const& metrics, + DeviceMetricsInfo const& driverMetrics, std::vector<DeviceSpec> const& specs, std::vector<std::string> const& metricsToDump) noexcept; static bool isResourcesMonitoringEnabled(unsigned short interval) noexcept { return interval > 0; } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index bc397fb6c54be..afd00fa82be97 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1289,7 +1289,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, LOG(INFO) << "Dumping performance metrics to performanceMetrics.json file"; auto performanceMetrics = o2::monitoring::ProcessMonitor::getAvailableMetricsNames(); performanceMetrics.push_back("arrow-bytes-delta"); - ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, deviceSpecs, performanceMetrics); + ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, driverInfo.metrics, deviceSpecs, performanceMetrics); } // This is a clean exit. Before we do so, if required, // we dump the configuration of all the devices so that From a61a5ecc470bc6a0d07cfdebc3307e76db8f38df Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Nov 2020 12:43:52 +0100 Subject: [PATCH 1379/1751] DPL: fix rate limiting * Avoid signaling the driver to often, unless we are empty. --- Framework/Core/src/AODReaderHelpers.cxx | 1 + Framework/Core/src/CommonMessageBackends.cxx | 43 ++++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index f7300b825bfcb..e938e09d550f0 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -225,6 +225,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() if (!watchdog->update()) { LOGP(INFO, "Run time exceeds run time limit of {} seconds!", watchdog->runTimeLimit); LOGP(INFO, "Stopping reader {} after time frame {}.", device.inputTimesliceId, watchdog->numberTimeFrames - 1); + monitoring.flushBuffer(); didir->closeInputFiles(); control.endOfStream(); control.readyToQuit(QuitRequest::Me); diff --git a/Framework/Core/src/CommonMessageBackends.cxx b/Framework/Core/src/CommonMessageBackends.cxx index 10bb38a521889..001ba31fc4184 100644 --- a/Framework/Core/src/CommonMessageBackends.cxx +++ b/Framework/Core/src/CommonMessageBackends.cxx @@ -92,6 +92,7 @@ enum struct RateLimitingState { BELOW_LIMIT = 3, // New metric received, we are below limit. NEXT_ITERATION_FROM_BELOW = 4, // Iteration when previously in BELOW_LIMIT. ABOVE_LIMIT = 5, // New metric received, we are above limit. + EMPTY = 6, // }; struct RateLimitConfig { @@ -168,6 +169,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() static auto totalMessagesDestroyedMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "total-arrow-messages-destroyed"); static auto totalBytesDeltaMetric = DeviceMetricsHelper::createNumericMetric<int>(driverMetrics, "arrow-bytes-delta"); static auto totalSignalsMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "aod-reader-signals"); + static auto skippedSignalsMetric = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "aod-skipped-signals"); static auto remainingBytes = DeviceMetricsHelper::createNumericMetric<uint64_t>(driverMetrics, "aod-remaining-bytes"); bool changed = false; @@ -180,8 +182,9 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() lastSignalTimestamp = driverMetrics.timestamps[signalIndex][info.pos - 1]; } - size_t lastCreatedBytesTimestamp = 0; - size_t lastDestroyedBytesTimestamp = 0; + size_t lastTimestamp = 0; + size_t firstTimestamp = -1; + size_t lastDecision = 0; for (auto& deviceMetrics : allDeviceMetrics) { { size_t index = DeviceMetricsHelper::metricIdxByName("arrow-bytes-created", deviceMetrics); @@ -191,7 +194,8 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() MetricInfo info = deviceMetrics.metrics.at(index); auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); totalBytesCreated += (int64_t)data.at((info.pos - 1) % data.size()); - lastCreatedBytesTimestamp = deviceMetrics.timestamps[index][info.pos - 1]; + lastTimestamp = std::max(lastTimestamp, deviceMetrics.timestamps[index][info.pos - 1]); + firstTimestamp = std::min(lastTimestamp, firstTimestamp); } } { @@ -202,7 +206,7 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() MetricInfo info = deviceMetrics.metrics.at(index); auto& data = deviceMetrics.uint64Metrics.at(info.storeIdx); totalBytesDestroyed += (int64_t)data.at((info.pos - 1) % data.size()); - lastDestroyedBytesTimestamp = deviceMetrics.timestamps[index][info.pos - 1]; + firstTimestamp = std::min(lastTimestamp, firstTimestamp); } } { @@ -232,6 +236,10 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() bool done = false; static int stateTransitions = 0; static int signalsCount = 0; + static int skippedCount = 0; + static uint64_t now = 0; + static uint64_t lastSignal = 0; + now = uv_hrtime(); while (!done) { stateMetric(driverMetrics, (uint64_t)(currentState), stateTransitions++); switch (currentState) { @@ -247,9 +255,12 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() case RateLimitingState::STARTED: { for (size_t di = 0; di < specs.size(); ++di) { if (specs[di].name == "internal-dpl-aod-reader") { - if (di < infos.size()) { + if (di < infos.size() && (now - lastSignal > 10000000)) { kill(infos[di].pid, SIGUSR1); totalSignalsMetric(driverMetrics, signalsCount++, timestamp); + lastSignal = now; + } else { + skippedSignalsMetric(driverMetrics, skippedCount++, timestamp); } } } @@ -258,19 +269,37 @@ o2::framework::ServiceSpec CommonMessageBackends::arrowBackendSpec() } break; case RateLimitingState::CHANGED: { remainingBytes(driverMetrics, totalBytesCreated <= (totalBytesDestroyed + memLimit) ? (totalBytesDestroyed + memLimit) - totalBytesCreated : 0, timestamp); - if (totalBytesCreated <= (totalBytesDestroyed + memLimit)) { + if (totalBytesCreated <= totalBytesDestroyed) { + currentState = RateLimitingState::EMPTY; + } else if (totalBytesCreated <= (totalBytesDestroyed + memLimit)) { currentState = RateLimitingState::BELOW_LIMIT; } else { currentState = RateLimitingState::ABOVE_LIMIT; } changed = false; } break; - case RateLimitingState::BELOW_LIMIT: { + case RateLimitingState::EMPTY: { for (size_t di = 0; di < specs.size(); ++di) { if (specs[di].name == "internal-dpl-aod-reader") { if (di < infos.size()) { kill(infos[di].pid, SIGUSR1); totalSignalsMetric(driverMetrics, signalsCount++, timestamp); + lastSignal = now; + } + } + } + changed = false; + currentState = RateLimitingState::NEXT_ITERATION_FROM_BELOW; + } + case RateLimitingState::BELOW_LIMIT: { + for (size_t di = 0; di < specs.size(); ++di) { + if (specs[di].name == "internal-dpl-aod-reader") { + if (di < infos.size() && (now - lastSignal > 10000000)) { + kill(infos[di].pid, SIGUSR1); + totalSignalsMetric(driverMetrics, signalsCount++, timestamp); + lastSignal = now; + } else { + skippedSignalsMetric(driverMetrics, skippedCount++, timestamp); } } } From 3313bee2e73eeee9b5ae5c6bffdccea2c5bd5dcc Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Nov 2020 10:59:21 +0100 Subject: [PATCH 1380/1751] DPL: improve documentation --- Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h b/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h index 45f22623ad0f4..0708d37f3c0a1 100644 --- a/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h +++ b/Framework/Core/include/Framework/ExternalFairMQDeviceProxy.h @@ -68,7 +68,7 @@ static auto gDefaultConverter = incrementalConverter(OutputSpec{"TST", "TEST", 0 /// Create a DataProcessorSpec which can be used to inject /// messages in the DPL. -/// @param label is the label of the DataProcessorSpec associated. +/// @param label is the label of the DataProcessorSpec associated and name of the input channel. /// @param outputs is the type of messages which this source produces. /// @param channelConfig is string to be passed to fairmq to create the device. /// notice that the name of the device will be added as the name of the channel if the From fbec88d5d0a26432f97c144e367504a6141e0b5a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 19 Nov 2020 19:55:43 +0100 Subject: [PATCH 1381/1751] GPU: Fix segfault when one TPC sector is empty and data is passed to merger directly without storing intermediate results --- GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx index 5db4985b15cc4..2573fdf702f79 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx @@ -177,9 +177,11 @@ GPUh() int GPUTPCTracker::CheckEmptySlice() // Check if the Slice is empty, if so set the output apropriate and tell the reconstuct procesdure to terminate if (NHitsTotal() < 1) { mCommonMem->nTracks = mCommonMem->nTrackHits = 0; - WriteOutputPrepare(); - mOutput->SetNTracks(0); - mOutput->SetNTrackClusters(0); + if (mOutput) { + WriteOutputPrepare(); + mOutput->SetNTracks(0); + mOutput->SetNTrackClusters(0); + } return 1; } return 0; From 3d2d096ccf9e2814956644d3e627491e49c46a9a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 19 Nov 2020 22:37:53 +0100 Subject: [PATCH 1382/1751] DPL: fix warning in benchmark_WorkflowHelpers.cxx --- Framework/Core/test/benchmark_WorkflowHelpers.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Framework/Core/test/benchmark_WorkflowHelpers.cxx b/Framework/Core/test/benchmark_WorkflowHelpers.cxx index 2eb8f15dea25f..5dd95a5398faa 100644 --- a/Framework/Core/test/benchmark_WorkflowHelpers.cxx +++ b/Framework/Core/test/benchmark_WorkflowHelpers.cxx @@ -56,7 +56,9 @@ static void BM_CreateGraphOverhead(benchmark::State& state) std::vector<OutputSpec> outputs; std::vector<LogicalForwardInfo> availableForwardsInfo; - WorkflowHelpers::verifyWorkflow(workflow); + if (WorkflowHelpers::verifyWorkflow(workflow) != WorkflowParsingState::Valid) { + throw std::runtime_error("Invalid workflow"); + }; auto context = makeEmptyConfigContext(); WorkflowHelpers::injectServiceDevices(workflow, *context); WorkflowHelpers::constructGraph(workflow, @@ -92,7 +94,9 @@ static void BM_CreateGraphReverseOverhead(benchmark::State& state) std::vector<OutputSpec> outputs; std::vector<LogicalForwardInfo> availableForwardsInfo; - WorkflowHelpers::verifyWorkflow(workflow); + if (WorkflowHelpers::verifyWorkflow(workflow) != WorkflowParsingState::Valid) { + throw std::runtime_error("Invalid workflow"); + }; auto context = makeEmptyConfigContext(); WorkflowHelpers::injectServiceDevices(workflow, *context); WorkflowHelpers::constructGraph(workflow, logicalEdges, From 586bcc90133d0ec40fa0b5f72ca1d7d99d50bb35 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 19 Nov 2020 20:33:52 +0100 Subject: [PATCH 1383/1751] GPU Display: Move GL animation config to general GPU configuration as leightweight GL config --- GPU/GPUTracking/Base/GPUSettingsList.h | 30 ++++++++++++++++ .../Standalone/display/GPUDisplay.h | 36 ++----------------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 39d77c565fe8d..1294358d45bfd 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -145,6 +145,35 @@ AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") AddHelp("help", 'h') EndConfig() +// Light settings concerning the event display (can be changed without rebuilding vertices) +BeginSubConfig(GPUSettingsDisplayLight, GLlight, configStandalone, "GL", 'g', "OpenGL display settings") +AddOption(animationMode, int, 0, "", 0, "") +AddOption(smoothPoints, bool, true, "", 0, "Apply smoothing to points") +AddOption(smoothLines, bool, false, "", 0, "Apply smoothing to lines") +AddOption(depthBuffer, bool, false, "", 0, "Enable Z-buffer") +AddOption(drawClusters, bool, true, "", 0, "Highlight clusters") +AddOption(drawLinks, bool, false, "", 0, "Highlight links") +AddOption(drawInitLinks, bool, false, "", 0, "Highlight cleaned-up links") +AddOption(drawSeeds, bool, false, "", 0, "Highlight seeds") +AddOption(drawTracklets, bool, false, "", 0, "Highlight tracklets") +AddOption(drawTracks, bool, false, "", 0, "Highlight sector tracks") +AddOption(drawGlobalTracks, bool, false, "", 0, "Highlight global sector tracks prolonged into adjacent sector") +AddOption(drawFinal, bool, false, "", 0, "Highlight final tracks") +AddOption(excludeClusters, int, 0, "", 0, "Exclude clusters from selected draw objects from display") +AddOption(propagateTracks, int, 0, "", 0, "Propagate final tracks further (inward / outward / show MC tracks)") +AddOption(colorClusters, int, 1, "", 0, "Color clusters belonging to track objects") +AddOption(drawSlice, int, -1, "", 0, "Show individual slice") +AddOption(drawRelatedSlices, int, 0, "", 0, "Show related slices (if drawSlice != -1)") +AddOption(drawGrid, int, 0, "", 0, "Highlight grid") +AddOption(colorCollisions, int, 0, "", 0, "Distinguish collisions in timeframe by color") +AddOption(showCollision, int, -1, "", 0, "Show only individual collision") +AddOption(pointSize, float, 2.0f, "", 0, "Set point size") +AddOption(lineWidth, float, 1.4f, "", 0, "Set line width") +AddOption(drawTPC, bool, true, "", 0, "Enable drawing TPC data") +AddOption(drawTRD, bool, true, "", 0, "Enabale drawing TRD data") +AddHelp("help", 'h') +EndConfig() + // Settings concerning the standalone QA BeginSubConfig(GPUSettingsQA, QA, configStandalone, "QA", 'q', "QA settings") AddOptionVec(compareInputs, const char*, "QAinput", 0, "Read histogram from these input files and include them in the output plots") @@ -269,6 +298,7 @@ AddSubConfig(GPUSettingsProcessing, proc) AddSubConfig(GPUSettingsTF, TF) AddSubConfig(GPUSettingsQA, QA) AddSubConfig(GPUSettingsDisplay, GL) +AddSubConfig(GPUSettingsDisplayLight, GLlight) AddSubConfig(GPUSettingsEG, EG) EndConfig() #elif defined(GPUCA_O2_LIB) || defined(GPUCA_O2_INTERFACE) // GPUCA_STANDALONE diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.h b/GPU/GPUTracking/Standalone/display/GPUDisplay.h index 565b3af52c2e8..81b1fd39b6716 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.h +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.h @@ -138,38 +138,6 @@ class GPUDisplay GLvertex(GLfloat a, GLfloat b, GLfloat c) : x(a), y(b), z(c) {} }; - struct OpenGLConfig { - int animationMode = 0; - - bool smoothPoints = true; - bool smoothLines = false; - bool depthBuffer = false; - - bool drawClusters = true; - bool drawLinks = false; - bool drawSeeds = false; - bool drawInitLinks = false; - bool drawTracklets = false; - bool drawTracks = false; - bool drawGlobalTracks = false; - bool drawFinal = false; - int excludeClusters = 0; - int propagateTracks = 0; - - int colorClusters = 1; - int drawSlice = -1; - int drawRelatedSlices = 0; - int drawGrid = 0; - int colorCollisions = 0; - int showCollision = -1; - - float pointSize = 2.0; - float lineWidth = 1.4; - - bool drawTPC = true; - bool drawTRD = true; - }; - struct DrawArraysIndirectCommand { DrawArraysIndirectCommand(unsigned int a = 0, unsigned int b = 0, unsigned int c = 0, unsigned int d = 0) : count(a), instanceCount(b), first(c), baseInstance(d) {} unsigned int count; @@ -294,7 +262,7 @@ class GPUDisplay GPUDisplayBackend* mBackend; GPUChainTracking* mChain; const GPUSettingsDisplay& mConfig; - OpenGLConfig mCfg; + GPUSettingsDisplayLight mCfg; GPUQA* mQA; const GPUTPCGMMerger& mMerger; qSem mSemLockDisplay; @@ -385,7 +353,7 @@ class GPUDisplay bool mAnimationChangeConfig = true; float mAnimationDelay = 2.f; vecpod<float> mAnimateVectors[9]; - vecpod<OpenGLConfig> mAnimateConfig; + vecpod<GPUSettingsDisplayLight> mAnimateConfig; opengl_spline mAnimationSplines[8]; volatile int mResetScene = 0; From cf7d568fcc9351ddeed9edc488d9f80bdd92bb05 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 19 Nov 2020 22:39:49 +0100 Subject: [PATCH 1384/1751] GPU Display: Add option to tie TPC clusters to nominal x of pad rows --- GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 1294358d45bfd..492c090034501 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -142,6 +142,7 @@ EndConfig() // Settings concerning the event display BeginSubConfig(GPUSettingsDisplay, GL, configStandalone, "GL", 'g', "OpenGL display settings") AddOption(clustersOnly, bool, false, "", 0, "Visualize clusters only") +AddOption(clustersOnNominalRow, bool, false, "", 0, "Show clusters at nominal x of pad row for early-transformed data") AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 36c881082954a..5bf25ea776330 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -1268,6 +1268,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) if (mMerger.Param().par.earlyTpcTransform) { const auto& cl = ioptrs().clusterData[iSlice][i]; cid = cl.id; + row = cl.row; } else { cid = ioptrs().clustersNative->clusterOffset[iSlice][0] + i; while (row < GPUCA_ROW_COUNT && ioptrs().clustersNative->clusterOffset[iSlice][row + 1] <= (unsigned int)cid) { @@ -1282,7 +1283,7 @@ int GPUDisplay::DrawGLScene_internal(bool mixAnimation, float mAnimateTime) float4* ptr = &mGlobalPos[cid]; if (mMerger.Param().par.earlyTpcTransform) { const auto& cl = ioptrs().clusterData[iSlice][i]; - mChain->GetParam().Slice2Global(iSlice, cl.x + mXadd, cl.y, cl.z, &ptr->x, &ptr->y, &ptr->z); + mChain->GetParam().Slice2Global(iSlice, (mConfig.clustersOnNominalRow ? mMerger.Param().tpcGeometry.Row2X(row) : cl.x) + mXadd, cl.y, cl.z, &ptr->x, &ptr->y, &ptr->z); } else { float x, y, z; const auto& cln = ioptrs().clustersNative->clusters[iSlice][0][i]; From 69cd85baa210249309b4e1c3c588781a7de1ad94 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin <andrey.erokhin@cern.ch> Date: Wed, 18 Nov 2020 17:43:39 +0300 Subject: [PATCH 1385/1751] Workaround for readability-braces-around-statements bug --- GPU/GPUTracking/Global/GPUChainTracking.h | 2 +- GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index f9cb5022e9830..6b89f3b25acd3 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -87,7 +87,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega InOutMemory(); ~InOutMemory(); InOutMemory(InOutMemory&&); - InOutMemory& operator=(InOutMemory&&); + InOutMemory& operator=(InOutMemory&&) = default; std::unique_ptr<unsigned long long int[]> tpcZSpages; std::unique_ptr<char[]> tpcZSpagesChar; // Same as above, but as char (needed for reading dumps, but deprecated, since alignment can be wrong) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index e5127f94654b5..9f0bcbb6fc2ec 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -65,7 +65,6 @@ static constexpr char DUMP_HEADER[DUMP_HEADER_SIZE + 1] = "CAv1"; GPUChainTracking::InOutMemory::InOutMemory() = default; GPUChainTracking::InOutMemory::~InOutMemory() = default; GPUChainTracking::InOutMemory::InOutMemory(GPUChainTracking::InOutMemory&&) = default; -GPUChainTracking::InOutMemory& GPUChainTracking::InOutMemory::operator=(GPUChainTracking::InOutMemory&&) = default; void GPUChainTracking::DumpData(const char* filename) { From 86a61acd1e444b2c188a1ac67bad8dba2b9d387a Mon Sep 17 00:00:00 2001 From: Henrique Zanoli <hzanoli@gmail.com> Date: Fri, 20 Nov 2020 09:59:52 +0100 Subject: [PATCH 1386/1751] Add more impact parameter plots for the QA (#4749) * Update Impact Parameter in qa Task * Remove matplotlib options * Move qa task to PWGHF * Fix title formating --- Analysis/Tasks/CMakeLists.txt | 4 - Analysis/Tasks/PWGHF/CMakeLists.txt | 5 + Analysis/Tasks/PWGHF/qaTask.cxx | 420 ++++++++++++++++++++++++++++ Analysis/Tasks/qaTask.cxx | 224 --------------- 4 files changed, 425 insertions(+), 228 deletions(-) create mode 100644 Analysis/Tasks/PWGHF/qaTask.cxx delete mode 100644 Analysis/Tasks/qaTask.cxx diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 44ce185982209..37006fd177484 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -32,10 +32,6 @@ o2_add_dpl_workflow(trackqa PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) -o2_add_dpl_workflow(qatask - SOURCES qaTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore - COMPONENT_NAME Analysis) o2_add_dpl_workflow(pid-tof SOURCES pidTOF.cxx diff --git a/Analysis/Tasks/PWGHF/CMakeLists.txt b/Analysis/Tasks/PWGHF/CMakeLists.txt index 934b0800e2bb2..16e4180937401 100644 --- a/Analysis/Tasks/PWGHF/CMakeLists.txt +++ b/Analysis/Tasks/PWGHF/CMakeLists.txt @@ -8,6 +8,11 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +o2_add_dpl_workflow(qatask + SOURCES qaTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(hf-track-index-skims-creator SOURCES HFTrackIndexSkimsCreator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG diff --git a/Analysis/Tasks/PWGHF/qaTask.cxx b/Analysis/Tasks/PWGHF/qaTask.cxx new file mode 100644 index 0000000000000..b819dcacd6118 --- /dev/null +++ b/Analysis/Tasks/PWGHF/qaTask.cxx @@ -0,0 +1,420 @@ +// 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 Peter Hristov <Peter.Hristov@cern.ch>, CERN +/// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN +/// \author Henrique J C Zanoli <henrique.zanoli@cern.ch>, Utrecht University +/// \author Nicolo' Jacazio <nicolo.jacazio@cern.ch>, CERN + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Analysis/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" + +#include "TH1D.h" + +#include <cmath> +#include <string> +#include <sstream> +#include "boost/algorithm/string.hpp" + +namespace o2fw = o2::framework; +namespace o2exp = o2::framework::expressions; +namespace o2df = o2::dataformats; + +namespace track_utils +{ +/// Converts a angle phi to the -pi to pi range. +double ConvertPhiRange(double phi) +{ + if (phi > M_PI) { + phi -= 2 * M_PI; + } else if (phi < -M_PI) { + phi += 2 * M_PI; + } + + return phi; +} + +/// Determines the impact parameter and its error for a given track. +/// \param track the track to get the impact parameter from. +/// \param primaryVertex the primary vertex of th collision. +/// \param impactParameterRPhi variable to save the impact parameter (in r phi) in micrometers. +/// \param impactParameterRPhiError variable to save the impact parameter (in r phi) error in micrometers. +/// \param impactParameterZ variable to save the impact parameter (in Z) in micrometers. +/// \param impactParameterZError variable to save the impact parameter (in Z) error in micrometers. +template <typename Track> +bool GetImpactParameterAndError(const Track& track, const o2df::VertexBase& primaryVertex, double& impactParameterRPhi, + double& impactParameterRPhiError, double& impactParameterZ, + double& impactParameterErrorZ) +{ + impactParameterRPhi = -999.; + impactParameterRPhiError = -999.; + impactParameterZ = -999; + impactParameterErrorZ = -999; + + o2df::DCA dca; + // FIXME: get this from CCDB + constexpr float magneticField{5.0}; // in kG + auto trackParameter = getTrackParCov(track); + bool propagate = trackParameter.propagateToDCA(primaryVertex, magneticField, &dca); + + constexpr float conversion_to_micrometer = 1000; + if (propagate) { + impactParameterRPhi = conversion_to_micrometer * dca.getY(); + impactParameterRPhiError = conversion_to_micrometer * std::sqrt(dca.getSigmaY2()); + impactParameterZ = conversion_to_micrometer * dca.getZ(); + impactParameterErrorZ = conversion_to_micrometer * std::sqrt(dca.getSigmaZ2()); + } + return propagate; +} +} // namespace track_utils + +namespace o2::qa::features +{ + +/// Class to abstract the naming of a particular feature. It can help you to build the histogram +/// labels in a consistent way and generate the titles. +class Feature +{ + public: + Feature() = default; + Feature(std::string name, std::string unit = "") : mName(std::move(name)), mUnit(std::move(unit)){}; + + /// Returns the feature tagged as MC with no unit. Example: p_{T}^{MC}. + std::string MCRaw() const { return mName + "^{MC}"; }; + + /// Returns the feature tagged as Reconstructed with no unit. Example: p_{T}^{Rec}. + std::string RecRaw() const { return mName + "^{Rec}"; }; + + /// Returns the unit with no brackets. Example: GeV/c. + std::string UnitRaw() const { return mUnit; }; + + /// Returns the name with no units. Example: p_{T}. + std::string NameRaw() const { return mName; }; + + /// Returns the name with the unit. Example: p_{T} [Gev/c]. + std::string Name() const { return mName + Unit(); }; + + /// Returns the name tagged as MC with the unit. Example: p_{T}^{MC} [Gev/c]. + std::string MC() const { return MCRaw() + Unit(); }; + + /// Returns the name tagged as Reconstructed with the unit. Example: p_{T}^{Rec} [Gev/c] + std::string Rec() const { return RecRaw() + Unit(); }; + + /// Returns the name difference between the MC and reconstructed with the unit. + /// Example: p_{T}^{MC} - p_{T}^{Rec} [Gev/c] + std::string MCRecDiff() const { return MCRaw() + " - " + RecRaw() + Unit(); }; + + /// Returns the name difference between the MC and reconstructed divided by the reconstructed. + /// For example: (p_{T}^{MC} - p_{T}^{Rec})/p_{T}^{Rec} + std::string RelativeMCRecDiff() const { return "(" + MCRaw() + " - " + RecRaw() + ")/" + RecRaw(); }; + + /// Returns the unit formatted to be used in the axis. If no unit is present, returns an empty value. + /// Example: [GeV/c] + std::string Unit() const + { + if (UnitRaw().empty()) { + return ""; + } + return " [" + UnitRaw() + "]"; + }; + + operator std::string() { return Name(); } + + private: + const std::string mName; + const std::string mUnit; +}; + +/// Makes a title for an histogram +std::string MakeTitle(std::vector<std::string> axisTitles, const std::string& counts = "Counts") +{ + axisTitles.push_back(counts); + return ";" + boost::algorithm::join(axisTitles, ";"); +} + +Feature Eta("#eta"); +Feature TrackMultiplicity("Track Multiplicity"); +Feature Phi{"#varphi", "rad"}; +Feature Pt("p_{T}", "GeV/c"); +Feature VertexX("X", "cm"); +Feature VertexY("Y", "cm"); +Feature VertexZ("Z", "cm"); +Feature ImpactParameterRPhi("Impact Parameter r#varphi", "#mum"); +Feature ImpactParameterRPhiError("Impact Parameter Error r#varphi", "#mum"); +Feature ImpactParameterZ("Impact Parameter Z", "#mum"); +Feature ImpactParameterZError("Impact Parameter Z Error", "#mum"); +} // namespace o2::qa::features + +namespace qafeat = o2::qa::features; + +/// Task to QA global observables of the event +struct QAGlobalObservables { + o2fw::Configurable<int> nBinsNumberOfTracks{"nBinsNumberOfTracks", 2000, "Number of bins for the Number of Tracks"}; + o2fw::Configurable<int> nBinsVertexPosition{"nBinsPt", 100, "Number of bins for the Vertex Position"}; + + std::array<float, 2> collisionZRange = {-20., 20.}; + std::array<float, 2> collisionXYRange = {-0.01, 0.01}; + + std::array<float, 2> numberOfTracksRange = {0, 400}; + + o2fw::OutputObj<TH1D> eventCount{TH1D("eventCount", qafeat::MakeTitle({"Selected Events"}).c_str(), 2, 0, 2)}; + o2fw::HistogramRegistry histograms{"HistogramsGlobalQA"}; + + void init(o2fw::InitContext&) + { + histograms.add("collision/collisionX", qafeat::MakeTitle({qafeat::VertexX}).c_str(), o2fw::kTH1D, + {{nBinsVertexPosition, collisionXYRange[0], collisionXYRange[1]}}); + + histograms.add("collision/collisionY", qafeat::MakeTitle({qafeat::VertexY}).c_str(), o2fw::kTH1D, + {{nBinsVertexPosition, collisionXYRange[0], collisionXYRange[1]}}); + + histograms.add("collision/collisionZ", qafeat::MakeTitle({qafeat::VertexZ}).c_str(), o2fw::kTH1D, + {{nBinsVertexPosition, collisionZRange[0], collisionZRange[1]}}); + + histograms.add("multiplicity/numberOfTracks", qafeat::MakeTitle({qafeat::TrackMultiplicity}).c_str(), o2fw::kTH1D, + {{nBinsNumberOfTracks, numberOfTracksRange[0], numberOfTracksRange[1]}}); + } + + void process(const o2::aod::Collision& collision, const o2::aod::Tracks& tracks) + { + eventCount->Fill(0); + histograms.fill("collision/collisionX", collision.posX()); + histograms.fill("collision/collisionY", collision.posY()); + histograms.fill("collision/collisionZ", collision.posZ()); + + int nTracks(0); + for (const auto& track : tracks) { + nTracks++; + } + + histograms.fill("multiplicity/numberOfTracks", nTracks); + } +}; + +/// Task to QA the kinematic properties of the tracks +struct QATrackingKine { + o2fw::Configurable<int> nBinsPt{"nBinsPt", 100, "Number of bins for Pt"}; + std::array<double, 2> ptRange = {0, 10.}; + + o2fw::Configurable<int> nBinsPhi{"nBinsPhi", 100, "Number of bins for Phi"}; + + o2fw::Configurable<int> nBinsEta{"nBinsEta", 100, "Number of bins for the eta histogram."}; + std::array<double, 2> etaRange = {-6, 6}; + + o2fw::HistogramRegistry histos{"HistogramsKineQA"}; + + void init(o2fw::InitContext&) + { + histos.add("tracking/pt", qafeat::MakeTitle({qafeat::Pt}).c_str(), o2fw::kTH1D, + {{nBinsPt, ptRange[0], ptRange[1]}}); + histos.add("tracking/eta", qafeat::MakeTitle({qafeat::Eta.NameRaw()}).c_str(), o2fw::kTH1D, + {{nBinsEta, etaRange[0], etaRange[1]}}); + histos.add("tracking/phi", qafeat::MakeTitle({qafeat::Phi}).c_str(), o2fw::kTH1D, {{nBinsPhi, 0, 2 * M_PI}}); + } + + void process(const o2::aod::Track& track) + { + histos.fill("tracking/eta", track.eta()); + histos.fill("tracking/pt", track.pt()); + histos.fill("tracking/phi", track.phi()); + } +}; + +/// Task to evaluate the tracking resolution (Pt, Eta, Phi and impact parameter) +struct QATrackingResolution { + std::vector<double> ptBins = {0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.12, + 0.14, 0.16, 0.18, 0.2, 0.225, 0.25, 0.275, 0.3, 0.35, 0.4, 0.45, 0.5, + 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.5, 3.0, + 3.5, 4., 5., 6., 8., 10., 15., 20., 30., 50., 100.}; + + o2fw::Configurable<int> nBinsEta{"nBinsEta", 60, "Number of bins for the pseudorapidity"}; + std::array<double, 2> etaRange = {-3, 3}; + + o2fw::Configurable<int> nBinsPhi{"nBinsPhi", 50, "Number of bins for Phi"}; + std::array<double, 2> phiRange = {0, 2 * M_PI}; + + o2fw::Configurable<int> nBinsDeltaPt{"nBinsDeltaPt", 100, "Number of bins for the transverse momentum differences"}; + std::array<double, 2> deltaPtRange = {-0.5, 0.5}; + + o2fw::Configurable<int> nBinsDeltaPhi{"nBinsDeltaPhi", 100, "Number of bins for the azimuthal angle differences"}; + std::array<double, 2> deltaPhiRange = {-0.1, 0.1}; + + o2fw::Configurable<int> nBinsDeltaEta{"nBinsDeltaEta", 100, "Number of bins for the pseudorapidity differences"}; + std::array<double, 2> deltaEtaRange = {-0.1, 0.1}; + + o2fw::Configurable<int> nBinsImpactParameter{"nBinsImpactParameter", 1000, "Number of bins for the Impact parameter"}; + + std::array<double, 2> impactParameterRange = {-1500, 1500}; // micrometer + std::array<double, 2> impactParameterResolutionRange = {0, 1000}; // micrometer + + // Registry of histograms + o2fw::HistogramRegistry histos{"HistogramsTrackingResolutionQA"}; + + void init(o2fw::InitContext&) + { + // Histogram axis definitions + + o2fw::AxisSpec ptAxis{ptBins}; + o2fw::AxisSpec deltaPtAxis{nBinsDeltaPt, deltaPtRange[0], deltaPtRange[1]}; + o2fw::AxisSpec deltaPtRelativeAxis{nBinsDeltaPt, deltaPtRange[0], deltaPtRange[1]}; + o2fw::AxisSpec deltaPtAbsoluteRelativeAxis{nBinsDeltaPt, 0., deltaPtRange[1]}; + + o2fw::AxisSpec etaAxis{nBinsEta, etaRange[0], etaRange[1]}; + o2fw::AxisSpec deltaEtaAxis{nBinsDeltaEta, deltaEtaRange[0], deltaEtaRange[1]}; + + o2fw::AxisSpec phiAxis{nBinsPhi, phiRange[0], phiRange[1]}; + o2fw::AxisSpec deltaPhiAxis{nBinsDeltaPhi, deltaPhiRange[0], deltaPhiRange[1]}; + + o2fw::AxisSpec impactParRPhiAxis{nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}; + o2fw::AxisSpec impactParRPhiErrorAxis{nBinsImpactParameter, impactParameterResolutionRange[0], + impactParameterResolutionRange[1]}; + + o2fw::AxisSpec impactParZAxis{nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}; + o2fw::AxisSpec impactParZErrorAxis{nBinsImpactParameter, impactParameterResolutionRange[0], + impactParameterResolutionRange[1]}; + + // Eta + histos.add("eta/etaDiffMCReco", qafeat::MakeTitle({qafeat::Eta.MCRecDiff()}).c_str(), o2fw::kTH1D, {deltaEtaAxis}); + + histos.add("eta/etaDiffMCRecoVsEtaMC", qafeat::MakeTitle({qafeat::Eta.MCRecDiff(), qafeat::Eta.MC()}).c_str(), + o2fw::kTH2D, {deltaEtaAxis, etaAxis}); + + histos.add("eta/etaDiffMCRecoVsEtaReco", qafeat::MakeTitle({qafeat::Eta.MCRecDiff(), qafeat::Eta.Rec()}).c_str(), + o2fw::kTH2D, {deltaEtaAxis, etaAxis}); + + // Phi + histos.add("phi/phiDiffMCRec", qafeat::MakeTitle({qafeat::Phi.MCRecDiff()}).c_str(), o2fw::kTH1D, {deltaPhiAxis}); + + // Pt + histos.add("pt/ptDiffMCRec", qafeat::MakeTitle({qafeat::Pt.MCRecDiff()}).c_str(), o2fw::kTH1D, {deltaPtAxis}); + + histos.add("pt/ptResolution", qafeat::MakeTitle({qafeat::Pt.RelativeMCRecDiff()}).c_str(), o2fw::kTH1D, + {deltaPtRelativeAxis}); + + histos.add("pt/ptResolutionVsPt", qafeat::MakeTitle({qafeat::Pt.Rec(), qafeat::Pt.RelativeMCRecDiff()}).c_str(), + o2fw::kTH2D, {ptAxis, deltaPtAbsoluteRelativeAxis}); + + histos.add("pt/ptResolutionVsEta", qafeat::MakeTitle({qafeat::Eta.Rec(), qafeat::Pt.RelativeMCRecDiff()}).c_str(), + o2fw::kTH2D, {etaAxis, deltaPtAbsoluteRelativeAxis}); + + histos.add("pt/ptResolutionVsPhi", qafeat::MakeTitle({qafeat::Phi.Rec(), qafeat::Pt.RelativeMCRecDiff()}).c_str(), + o2fw::kTH2D, {phiAxis, deltaPtAbsoluteRelativeAxis}); + + // Impact parameters + histos.add("impactParameter/impactParameterRPhiVsPt", + qafeat::MakeTitle({qafeat::Pt.Rec(), qafeat::ImpactParameterRPhi}).c_str(), o2fw::kTH2D, + {ptAxis, impactParRPhiAxis}); + + histos.add("impactParameter/impactParameterRPhiVsEta", + qafeat::MakeTitle({qafeat::Eta.Rec(), qafeat::ImpactParameterRPhi}).c_str(), o2fw::kTH2D, + {etaAxis, impactParRPhiAxis}); + + histos.add("impactParameter/impactParameterRPhiVsPhi", + qafeat::MakeTitle({qafeat::Phi.Rec(), qafeat::ImpactParameterRPhi}).c_str(), o2fw::kTH2D, + {phiAxis, impactParRPhiAxis}); + + histos.add("impactParameter/impactParameterErrorRPhiVsPt", + qafeat::MakeTitle({qafeat::Pt.Rec(), qafeat::ImpactParameterRPhiError}).c_str(), o2fw::kTH2D, + {ptAxis, impactParRPhiErrorAxis}); + + histos.add("impactParameter/impactParameterErrorRPhiVsEta", + qafeat::MakeTitle({qafeat::Eta.Rec(), qafeat::ImpactParameterRPhiError}).c_str(), o2fw::kTH2D, + {etaAxis, impactParRPhiErrorAxis}); + + histos.add("impactParameter/impactParameterErrorRPhiVsPhi", + qafeat::MakeTitle({qafeat::Phi.Rec(), qafeat::ImpactParameterRPhiError}).c_str(), o2fw::kTH2D, + {phiAxis, impactParRPhiErrorAxis}); + + histos.add("impactParameter/impactParameterZVsPt", + qafeat::MakeTitle({qafeat::Pt.Rec(), qafeat::ImpactParameterZ}).c_str(), o2fw::kTH2D, + {ptAxis, impactParZAxis}); + + histos.add("impactParameter/impactParameterZVsEta", + qafeat::MakeTitle({qafeat::Eta.Rec(), qafeat::ImpactParameterZ}).c_str(), o2fw::kTH2D, + {etaAxis, impactParZAxis}); + + histos.add("impactParameter/impactParameterZVsPhi", + qafeat::MakeTitle({qafeat::Phi.Rec(), qafeat::ImpactParameterZ}).c_str(), o2fw::kTH2D, + {phiAxis, impactParZAxis}); + + histos.add("impactParameter/impactParameterErrorZVsPt", + qafeat::MakeTitle({qafeat::Pt.Rec(), qafeat::ImpactParameterZError}).c_str(), o2fw::kTH2D, + {ptAxis, impactParZErrorAxis}); + + histos.add("impactParameter/impactParameterErrorZVsEta", + qafeat::MakeTitle({qafeat::Eta.Rec(), qafeat::ImpactParameterZError}).c_str(), o2fw::kTH2D, + {etaAxis, impactParZErrorAxis}); + + histos.add("impactParameter/impactParameterErrorZVsPhi", + qafeat::MakeTitle({qafeat::Phi.Rec(), qafeat::ImpactParameterZError}).c_str(), o2fw::kTH2D, + {phiAxis, impactParZErrorAxis}); + } + + void process(const o2::soa::Join<o2::aod::Collisions, o2::aod::McCollisionLabels>::iterator& collision, + const o2::soa::Join<o2::aod::Tracks, o2::aod::TracksCov, o2::aod::McTrackLabels>& tracks, + const o2::aod::McParticles& mcParticles, const o2::aod::McCollisions& mcCollisions) + { + const o2df::VertexBase primaryVertex = getPrimaryVertex(collision); + + for (const auto& track : tracks) { + const double deltaPt = track.label().pt() - track.pt(); + histos.fill("pt/ptDiffMCRec", deltaPt); + + const double deltaPtOverPt = deltaPt / track.pt(); + + histos.fill("pt/ptResolution", deltaPtOverPt); + histos.fill("pt/ptResolutionVsPt", track.pt(), std::abs(deltaPtOverPt)); + histos.fill("pt/ptResolutionVsEta", track.eta(), std::abs(deltaPtOverPt)); + histos.fill("pt/ptResolutionVsPhi", track.phi(), std::abs(deltaPtOverPt)); + + const double deltaEta = track.label().eta() - track.eta(); + histos.fill("eta/etaDiffMCReco", deltaEta); + histos.fill("eta/etaDiffMCRecoVsEtaMC", deltaEta, track.label().eta()); + histos.fill("eta/etaDiffMCRecoVsEtaReco", deltaEta, track.eta()); + + const double deltaPhi = track_utils::ConvertPhiRange(track.label().phi() - track.phi()); + histos.fill("phi/phiDiffMCRec", deltaPhi); + + double impactParameterRPhi{-999.}, impactParameterRPhiError{-999.}; + double impactParameterZ{-999.}, impactParameterErrorZ{-999.}; + + const bool propagate = track_utils::GetImpactParameterAndError( + track, primaryVertex, impactParameterRPhi, impactParameterRPhiError, impactParameterZ, impactParameterErrorZ); + + if (propagate) { + histos.fill("impactParameter/impactParameterRPhiVsPt", track.pt(), impactParameterRPhi); + histos.fill("impactParameter/impactParameterRPhiVsEta", track.eta(), impactParameterRPhi); + histos.fill("impactParameter/impactParameterRPhiVsPhi", track.phi(), impactParameterRPhi); + + histos.fill("impactParameter/impactParameterZVsPt", track.pt(), impactParameterZ); + histos.fill("impactParameter/impactParameterZVsEta", track.eta(), impactParameterZ); + histos.fill("impactParameter/impactParameterZVsPhi", track.phi(), impactParameterZ); + + histos.fill("impactParameter/impactParameterErrorRPhiVsPt", track.pt(), impactParameterRPhiError); + histos.fill("impactParameter/impactParameterErrorRPhiVsEta", track.eta(), impactParameterRPhiError); + histos.fill("impactParameter/impactParameterErrorRPhiVsPhi", track.phi(), impactParameterRPhiError); + + histos.fill("impactParameter/impactParameterErrorZVsPt", track.pt(), impactParameterErrorZ); + histos.fill("impactParameter/impactParameterErrorZVsEta", track.eta(), impactParameterErrorZ); + histos.fill("impactParameter/impactParameterErrorZVsPhi", track.phi(), impactParameterErrorZ); + } + } + } +}; + +o2fw::WorkflowSpec defineDataProcessing(o2fw::ConfigContext const&) +{ + return o2fw::WorkflowSpec{o2fw::adaptAnalysisTask<QAGlobalObservables>("qa-global-observables"), + o2fw::adaptAnalysisTask<QATrackingKine>("qa-tracking-kine"), + o2fw::adaptAnalysisTask<QATrackingResolution>("qa-tracking-resolution")}; +} diff --git a/Analysis/Tasks/qaTask.cxx b/Analysis/Tasks/qaTask.cxx deleted file mode 100644 index b6c2b0a641a16..0000000000000 --- a/Analysis/Tasks/qaTask.cxx +++ /dev/null @@ -1,224 +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. -/// \author Peter Hristov <Peter.Hristov@cern.ch>, CERN -/// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN -/// \author Henrique J C Zanoli <henrique.zanoli@cern.ch>, Utrecht University -/// \author Nicolo' Jacazio <nicolo.jacazio@cern.ch>, CERN - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Analysis/trackUtilities.h" -#include "ReconstructionDataFormats/DCA.h" -#include "Analysis/MC.h" - -#include <TH1F.h> -#include <TH2F.h> -#include <cmath> - -namespace o2fw = o2::framework; -namespace o2exp = o2::framework::expressions; -namespace o2df = o2::dataformats; - -namespace track_utils -{ -/// Converts a angle phi to the -pi to pi range. -double ConvertPhiRange(double phi) -{ - if (phi > M_PI) { - phi -= 2 * M_PI; - } else if (phi < -M_PI) { - phi += 2 * M_PI; - } - - return phi; -} - -/// Determines the impact parameter and its error for a given track. -/// \param track the track to get the impact parameter from. -/// \param primaryVertex the primary vertex of th collision. -/// \param impactParameter variable to save the impact parameter in micrometers. -/// \param impactParameterError variable to save the impact parameter error in micrometers. -template <typename Track> -bool GetImpactParameterAndError(const Track& track, const o2df::VertexBase& primaryVertex, double& impactParameter, - double& impactParameterError) -{ - impactParameter = -999.; - impactParameterError = -999.; - - o2df::DCA dca; - // FIXME: get this from CCDB - constexpr float magneticField{5.0}; // in kG - auto trackParameter = getTrackParCov(track); - bool propagate = trackParameter.propagateToDCA(primaryVertex, magneticField, &dca); - - if (propagate) { - impactParameter = 1000 * dca.getY(); - impactParameterError = 1000 * std::sqrt(dca.getSigmaY2()); - } - return propagate; -} -} // namespace track_utils - -/// Task to QA global observables of the event -struct QAGlobalObservables { - std::array<float, 2> collisionPositionRange = {-20., 20.}; - std::array<float, 2> numberOfTracksRange = {0, 2000}; - - o2fw::Configurable<int> nBinsNumberOfTracks{"nBinsNumberOfTracks", 2000, "Number of bins fot the Number of Tracks"}; - - o2fw::Configurable<int> nBinsVertexPosition{"nBinsPt", 100, "Number of bins for the Vertex Position"}; - - o2fw::OutputObj<TH1F> hCollisionX{ - TH1F("collisionX", "; X [cm];Counts", nBinsVertexPosition, collisionPositionRange[0], collisionPositionRange[1])}; - - o2fw::OutputObj<TH1F> hCollisionY{ - TH1F("collisionY", "; Y [cm];Counts", nBinsVertexPosition, collisionPositionRange[0], collisionPositionRange[1])}; - - o2fw::OutputObj<TH1F> hCollisionZ{ - TH1F("collisionZ", "; Z [cm];Counts", nBinsVertexPosition, collisionPositionRange[0], collisionPositionRange[1])}; - - o2fw::OutputObj<TH1F> hNumberOfTracks{TH1F("NumberOfTracks", "; Number of Tracks;Counts", nBinsNumberOfTracks, - numberOfTracksRange[0], numberOfTracksRange[1])}; - - void process(const o2::aod::Collision& collision, const o2::aod::Tracks& tracks) - { - hCollisionX->Fill(collision.posX()); - hCollisionY->Fill(collision.posY()); - hCollisionZ->Fill(collision.posZ()); - - int nTracks(0); - for (const auto& track : tracks) { - nTracks++; - } - hNumberOfTracks->Fill(nTracks); - } -}; - -/// Task to QA the kinematic properties of the tracks -struct QATrackingKine { - o2fw::Configurable<int> nBinsPt{"nBinsPt", 100, "Number of bins for Pt"}; - std::array<double, 2> ptRange = {0, 10.}; - o2fw::Configurable<int> nBinsPhi{"nBinsPhi", 100, "Number of bins for Phi"}; - o2fw::Configurable<int> nBinsEta{"nBinsEta", 100, "Number of bins for the eta histogram."}; - std::array<double, 2> etaRange = {-6, 6}; - - o2fw::OutputObj<TH1F> hPt{TH1F("pt", ";p_{T} [GeV];Counts", nBinsPt, ptRange[0], ptRange[1])}; - o2fw::OutputObj<TH1F> hEta{TH1F("eta", ";#eta;Counts", nBinsEta, etaRange[0], etaRange[1])}; - o2fw::OutputObj<TH1F> hPhi{TH1F("phi", ";#varphi [rad];Counts", nBinsPhi, 0, 2 * M_PI)}; - - void process(const o2::aod::Track& track) - { - hEta->Fill(track.eta()); - hPhi->Fill(track.phi()); - hPt->Fill(track.pt()); - } -}; - -/// Task to evaluate the tracking resolution (Pt, Eta, Phi and impact parameter) -struct QATrackingResolution { - o2fw::Configurable<int> nBinsPtTrack{"nBinsPtTrack", 100, "Number of bins for the transverse momentum"}; - std::array<double, 2> ptRange = {0, 10.}; - - o2fw::Configurable<int> nBinsEta{"nBinsEta", 400, "Number of bins for the pseudorapidity"}; - std::array<double, 2> etaRange = {-6, 6}; - - o2fw::Configurable<int> nBinsDeltaPt{"nBinsDeltaPt", 400, "Number of bins for the transverse momentum differences"}; - - o2fw::Configurable<int> nBinsDeltaPhi{"nBinsPhi", 100, "Number of bins for the azimuthal angle differences"}; - - o2fw::Configurable<int> nBinsDeltaEta{"nBinsDeltaEta", 100, "Number of bins for the pseudorapidity differences"}; - - o2fw::Configurable<int> nBinsImpactParameter{"nBinsImpactParameter", 1000, "Number of bins for the Impact parameter"}; - - std::array<double, 2> impactParameterRange = {-1500, 1500}; // micrometer - std::array<double, 2> impactParameterResolutionRange = {0, 1000}; // micrometer - - // Registry of histograms - o2fw::HistogramRegistry histos{"Histos", {}, o2fw::OutputObjHandlingPolicy::AnalysisObject}; - - void init(o2fw::InitContext&) - { - // Eta - histos.add("Eta/etaDiffMCReco", ";#eta_{MC} - #eta_{Rec}", o2fw::kTH1F, - {{nBinsDeltaEta, -2, 2}}); - histos.add("Eta/etaDiffMCRecoVsEtaMC", ";#eta_{MC} - #eta_{Rec};#eta_{MC}", o2fw::kTH2F, - {{nBinsDeltaEta, -2, 2}, {nBinsEta, etaRange[0], etaRange[1]}}); - histos.add("Eta/etaDiffMCRecoVsEtaReco", ";#eta_{MC} - #eta_{Rec};#eta_{Rec}", o2fw::kTH2F, - {{nBinsDeltaEta, -2, 2}, {nBinsEta, etaRange[0], etaRange[1]}}); - // Phi - histos.add("Phi/phiDiffMCRec", ";#varphi_{MC} - #varphi_{Rec} [rad]", o2fw::kTH1F, - {{nBinsDeltaPhi, -M_PI, M_PI}}); - // Pt - histos.add("Pt/ptDiffMCRec", ";p_{T}_{MC} - p_{T}_{Rec} [GeV/c]", o2fw::kTH1F, - {{nBinsDeltaPt, -2., 2.}}); - histos.add("Pt/ptResolution", ";(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", o2fw::kTH1F, - {{nBinsDeltaPt, -2., 2.}}); - histos.add("Pt/ptResolutionVsPt", ";p_{T} [GeV/c];(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", o2fw::kTH2F, - {{nBinsPtTrack, ptRange[0], ptRange[1]}, {nBinsDeltaPt, 0, 2.}}); - histos.add("Pt/ptResolutionVsEta", ";#eta;(p_{T}_{MC} - p_{T}_{Rec})/(p_{T}_{Rec})", o2fw::kTH2F, - {{nBinsEta, -4., 4.}, {nBinsDeltaPt, -2., 2.}}); - // Impact parameters - histos.add("ImpactParameter/impactParameterVsPt", ";p_{T} [GeV/c];Impact Parameter [{#mu}m]", o2fw::kTH2F, - {{nBinsPtTrack, ptRange[0], ptRange[1]}, {nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}}); - histos.add("ImpactParameter/impactParameterVsEta", "#eta;Impact Parameter [{#mu}m]", o2fw::kTH2F, - {{nBinsEta, etaRange[0], etaRange[1]}, {nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}}); - histos.add("ImpactParameter/impactParameterErrorVsPt", ";p_{T} [GeV/c];Impact Parameter Error [#mum]", o2fw::kTH2F, - {{nBinsPtTrack, ptRange[0], ptRange[1]}, {nBinsImpactParameter, impactParameterRange[0], impactParameterRange[1]}}); - histos.add("ImpactParameter/impactParameterErrorVsEta", ";#eta;Impact Parameter Error [#mum]", o2fw::kTH2F, - {{nBinsEta, etaRange[0], etaRange[1]}, {nBinsImpactParameter, 0, impactParameterRange[1]}}); - } - - void process(const o2::soa::Join<o2::aod::Collisions, o2::aod::McCollisionLabels>::iterator& collision, - const o2::soa::Join<o2::aod::Tracks, o2::aod::TracksCov, o2::aod::McTrackLabels>& tracks, - const o2::aod::McParticles& mcParticles, const o2::aod::McCollisions& mcCollisions) - { - const o2df::VertexBase primaryVertex = getPrimaryVertex(collision); - - for (const auto& track : tracks) { - const double deltaPt = track.label().pt() - track.pt(); - histos.fill("Pt/ptDiffMCRec", deltaPt); - - const double deltaPtOverPt = deltaPt / track.pt(); - histos.fill("Pt/ptResolution", deltaPtOverPt); - histos.fill("Pt/ptResolutionVsPt", track.pt(), abs(deltaPtOverPt)); - histos.fill("Pt/ptResolutionVsEta", track.eta(), abs(deltaPtOverPt)); - - const double deltaEta = track.label().eta() - track.eta(); - histos.fill("Eta/etaDiffMCReco", deltaEta); - histos.fill("Eta/etaDiffMCRecoVsEtaMC", deltaEta, track.label().eta()); - histos.fill("Eta/etaDiffMCRecoVsEtaReco", deltaEta, track.eta()); - - const auto deltaPhi = track_utils::ConvertPhiRange(track.label().phi() - track.phi()); - histos.fill("Phi/phiDiffMCRec", deltaPhi); - - double impactParameter{-999.}; - double impactParameterError{-999.}; - - const bool propagate = - track_utils::GetImpactParameterAndError(track, primaryVertex, impactParameter, impactParameterError); - - if (propagate) { - histos.fill("ImpactParameter/impactParameterVsPt", track.pt(), impactParameter); - histos.fill("ImpactParameter/impactParameterVsEta", track.eta(), impactParameter); - histos.fill("ImpactParameter/impactParameterErrorVsPt", track.pt(), impactParameterError); - histos.fill("ImpactParameter/impactParameterErrorVsEta", track.eta(), impactParameterError); - } - } - } -}; - -o2fw::WorkflowSpec defineDataProcessing(o2fw::ConfigContext const&) -{ - return o2fw::WorkflowSpec{o2fw::adaptAnalysisTask<QAGlobalObservables>("qa-global-observables"), - o2fw::adaptAnalysisTask<QATrackingKine>("qa-tracking-kine"), - o2fw::adaptAnalysisTask<QATrackingResolution>("qa-tracking-resolution")}; -} From 7082d0ad95b23406f353c08e9358e8fcbef9c44e Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 20 Nov 2020 10:31:23 +0100 Subject: [PATCH 1387/1751] DPL Analysis: adapt the internals to Configurable<vector> (#4869) --- .../Tutorials/src/configurableObjects.cxx | 19 ++++ .../include/Framework/ConfigParamRegistry.h | 17 ++++ .../Core/include/Framework/ConfigParamStore.h | 6 ++ .../include/Framework/ConfigParamsHelper.h | 50 +++++++---- Framework/Core/include/Framework/Variant.h | 36 +++++++- Framework/Core/src/AnalysisManagers.h | 2 +- Framework/Core/src/BoostOptionsRetriever.cxx | 2 + Framework/Core/src/ConfigParamsHelper.cxx | 10 ++- Framework/Core/src/DataProcessingDevice.cxx | 51 ++++++++++- Framework/Core/src/DeviceConfigInfo.cxx | 30 ++++--- Framework/Core/src/PropertyTreeHelpers.cxx | 88 ++++++++++++++++--- Framework/Core/src/Variant.cxx | 12 ++- Framework/Core/src/runDataProcessing.cxx | 2 +- Framework/Core/test/test_DeviceConfigInfo.cxx | 42 ++++++++- 14 files changed, 319 insertions(+), 48 deletions(-) diff --git a/Analysis/Tutorials/src/configurableObjects.cxx b/Analysis/Tutorials/src/configurableObjects.cxx index 2cf3dbb035672..036379d192d96 100644 --- a/Analysis/Tutorials/src/configurableObjects.cxx +++ b/Analysis/Tutorials/src/configurableObjects.cxx @@ -12,6 +12,8 @@ #include "Framework/AnalysisDataModel.h" #include "Analysis/configurableCut.h" +#include <sstream> + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -22,10 +24,27 @@ using namespace o2::framework::expressions; struct ConfigurableObjectDemo { Configurable<configurableCut> cut{"cut", {0.5, 1, true}, "generic cut"}; MutableConfigurable<configurableCut> mutable_cut{"mutable_cut", {1., 2, false}, "generic cut"}; + + // note that size is fixed by this declaration - externally supplied vector needs to be the same size! + Configurable<std::vector<int>> array{"array", {1, 2, 3, 4, 5}, "generic array"}; + void init(InitContext const&){}; void process(aod::Collision const&, aod::Tracks const& tracks) { LOGF(INFO, "Cut1: %.3f; Cut2: %.3f", cut, mutable_cut); + auto vec = (std::vector<int>)array; + std::stringstream ss; + ss << "["; + auto count = 0u; + for (auto& entry : vec) { + ss << entry; + if (count < vec.size() - 1) { + ss << ","; + } + ++count; + } + ss << "]"; + LOGF(INFO, "Array: %s", ss.str().c_str()); for (auto& track : tracks) { if (track.globalIndex() % 500 == 0) { std::string decision1; diff --git a/Framework/Core/include/Framework/ConfigParamRegistry.h b/Framework/Core/include/Framework/ConfigParamRegistry.h index f0b96fe8bf75b..8cfa0ee864028 100644 --- a/Framework/Core/include/Framework/ConfigParamRegistry.h +++ b/Framework/Core/include/Framework/ConfigParamRegistry.h @@ -12,6 +12,7 @@ #include "Framework/ParamRetriever.h" #include "Framework/ConfigParamStore.h" +#include "Framework/Traits.h" #include <boost/property_tree/ptree.hpp> #include <memory> @@ -21,6 +22,20 @@ namespace o2::framework { +namespace +{ +template <typename T> +std::vector<T> extractVector(boost::property_tree::ptree& tree) +{ + std::vector<T> result(tree.size()); + auto count = 0u; + for (auto& entry : tree) { + result[count++] = entry.second.get_value<T>(); + } + return result; +} +} // namespace + class ConfigParamStore; /// This provides unified access to the parameters specified in the workflow @@ -63,6 +78,8 @@ class ConfigParamRegistry return mStore->store().get<std::string>(key); } else if constexpr (std::is_same_v<T, std::string_view>) { return std::string_view{mStore->store().get<std::string>(key)}; + } else if constexpr (is_base_of_template<std::vector, T>::value) { + return extractVector<typename T::value_type>(mStore->store().get_child(key)); } else if constexpr (std::is_same_v<T, boost::property_tree::ptree>) { return mStore->store().get_child(key); } else if constexpr (std::is_constructible_v<T, boost::property_tree::ptree>) { diff --git a/Framework/Core/include/Framework/ConfigParamStore.h b/Framework/Core/include/Framework/ConfigParamStore.h index ff775818af844..111725b818432 100644 --- a/Framework/Core/include/Framework/ConfigParamStore.h +++ b/Framework/Core/include/Framework/ConfigParamStore.h @@ -37,6 +37,12 @@ class ConfigParamStore boost::property_tree::ptree& store() { return *mStore; }; boost::property_tree::ptree& provenanceTree() { return *mProvenance; }; + /// Get the specs + std::vector<ConfigParamSpec> const& specs() const + { + return mSpecs; + } + /// Activate the next store void activate(); diff --git a/Framework/Core/include/Framework/ConfigParamsHelper.h b/Framework/Core/include/Framework/ConfigParamsHelper.h index 54c2c28e8cf0a..b48fb0291b1e1 100644 --- a/Framework/Core/include/Framework/ConfigParamsHelper.h +++ b/Framework/Core/include/Framework/ConfigParamsHelper.h @@ -18,9 +18,7 @@ #include <string> #include <type_traits> -namespace o2 -{ -namespace framework +namespace o2::framework { using options_description = boost::program_options::options_description; @@ -101,22 +99,40 @@ struct ConfigParamsHelper { { const char* name = spec.name.c_str(); const char* help = spec.help.c_str(); - using Type = typename variant_type<V>::type; - using BoostType = typename std::conditional<V == VariantType::String, std::string, Type>::type; - auto value = boost::program_options::value<BoostType>(); - if (spec.defaultValue.type() != VariantType::Empty) { - // set the default value if provided in the config spec - value = value->default_value(spec.defaultValue.get<Type>()); - } - if (V == VariantType::Bool) { - // for bool values we also support the zero_token option to make - // the option usable as a single switch - value = value->zero_tokens(); + + if constexpr (V == VariantType::Int || + V == VariantType::Int64 || + V == VariantType::Float || + V == VariantType::Double || + V == VariantType::Bool) { + using Type = typename variant_type<V>::type; + using BoostType = typename std::conditional<V == VariantType::String, std::string, Type>::type; + auto value = boost::program_options::value<BoostType>(); + value = value->default_value(spec.defaultValue.get<BoostType>()); + if constexpr (V == VariantType::Bool) { + // for bool values we also support the zero_token option to make + // the option usable as a single switch + value = value->zero_tokens(); + } + options.add_options()(name, value, help); + } else if constexpr (V == VariantType::ArrayInt || + V == VariantType::ArrayFloat || + V == VariantType::ArrayDouble || + V == VariantType::ArrayBool) { + auto value = boost::program_options::value<std::string>(); + value = value->default_value(spec.defaultValue.asString()); + if constexpr (V != VariantType::String) { + value = value->multitoken(); + } + options.add_options()(name, value, help); + } else { + using Type = typename variant_type<V>::type; + using BoostType = typename std::conditional<V == VariantType::String, std::string, Type>::type; + auto value = boost::program_options::value<BoostType>(); + options.add_options()(name, value, help); } - options.add_options()(name, value, help); } }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif // FRAMEWORK_CONFIGPARAMSHELPER_H diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index f14b2c99ffeb7..7622ef09571c9 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -53,18 +53,50 @@ DECLARE_VARIANT_TRAIT(long int, Int64); DECLARE_VARIANT_TRAIT(long long int, Int64); DECLARE_VARIANT_TRAIT(float, Float); DECLARE_VARIANT_TRAIT(double, Double); +DECLARE_VARIANT_TRAIT(bool, Bool); + DECLARE_VARIANT_TRAIT(const char*, String); DECLARE_VARIANT_TRAIT(char*, String); DECLARE_VARIANT_TRAIT(char* const, String); DECLARE_VARIANT_TRAIT(const char* const, String); DECLARE_VARIANT_TRAIT(std::string_view, String); DECLARE_VARIANT_TRAIT(std::string, String); -DECLARE_VARIANT_TRAIT(bool, Bool); + DECLARE_VARIANT_TRAIT(int*, ArrayInt); DECLARE_VARIANT_TRAIT(float*, ArrayFloat); DECLARE_VARIANT_TRAIT(double*, ArrayDouble); DECLARE_VARIANT_TRAIT(bool*, ArrayBool); +DECLARE_VARIANT_TRAIT(std::vector<int>, ArrayInt); +DECLARE_VARIANT_TRAIT(std::vector<float>, ArrayFloat); +DECLARE_VARIANT_TRAIT(std::vector<double>, ArrayDouble); +DECLARE_VARIANT_TRAIT(std::vector<bool>, ArrayBool); + +template <typename T> +struct variant_array_symbol { + constexpr static char symbol = 'u'; +}; + +template <> +struct variant_array_symbol<int> { + constexpr static char symbol = 'i'; +}; + +template <> +struct variant_array_symbol<float> { + constexpr static char symbol = 'f'; +}; + +template <> +struct variant_array_symbol<double> { + constexpr static char symbol = 'd'; +}; + +template <> +struct variant_array_symbol<bool> { + constexpr static char symbol = 'b'; +}; + template <typename T> inline constexpr VariantType variant_trait_v = variant_trait<T>::value; @@ -84,6 +116,7 @@ DECLARE_VARIANT_TYPE(float, Float); DECLARE_VARIANT_TYPE(double, Double); DECLARE_VARIANT_TYPE(const char*, String); DECLARE_VARIANT_TYPE(bool, Bool); + DECLARE_VARIANT_TYPE(int*, ArrayInt); DECLARE_VARIANT_TYPE(float*, ArrayFloat); DECLARE_VARIANT_TYPE(double*, ArrayDouble); @@ -293,6 +326,7 @@ class Variant VariantType type() const { return mType; } size_t size() const { return mSize; } + std::string asString() const; private: friend std::ostream& operator<<(std::ostream& oss, Variant const& val); diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index c59225b8364d0..f045d07bc8687 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -360,7 +360,7 @@ struct OptionManager<Configurable<T, IP>> { static bool appendOption(std::vector<ConfigParamSpec>& options, Configurable<T, IP>& what) { if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) { - options.emplace_back(ConfigParamSpec{what.name, variant_trait_v<typename std::decay<T>::type>, what.value, {what.help}}); + options.emplace_back(ConfigParamSpec{what.name, variant_trait_v<std::decay_t<T>>, what.value, {what.help}}); } else { auto specs = RootConfigParamHelpers::asConfigParamSpecs<T>(what.name, what.value); options.insert(options.end(), specs.begin(), specs.end()); diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index df87c691a60b3..8128635a5ccc6 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -68,6 +68,8 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> const& specs, case VariantType::ArrayFloat: case VariantType::ArrayDouble: case VariantType::ArrayBool: + options = options(name, bpo::value<std::string>()->multitoken()->default_value(spec.defaultValue.asString(), help)); + break; case VariantType::Unknown: case VariantType::Empty: break; diff --git a/Framework/Core/src/ConfigParamsHelper.cxx b/Framework/Core/src/ConfigParamsHelper.cxx index e41ab45af7bb1..225505734bd4b 100644 --- a/Framework/Core/src/ConfigParamsHelper.cxx +++ b/Framework/Core/src/ConfigParamsHelper.cxx @@ -35,8 +35,6 @@ void ConfigParamsHelper::populateBoostProgramOptions( if (vetos.find_nothrow(spec.name, false)) { continue; } - const char* name = spec.name.c_str(); - const char* help = spec.help.c_str(); switch (spec.type) { // FIXME: Should we handle int and size_t diffently? @@ -60,9 +58,17 @@ void ConfigParamsHelper::populateBoostProgramOptions( addConfigSpecOption<VariantType::Bool>(spec, options); break; case VariantType::ArrayInt: + addConfigSpecOption<VariantType::ArrayInt>(spec, options); + break; case VariantType::ArrayFloat: + addConfigSpecOption<VariantType::ArrayFloat>(spec, options); + break; case VariantType::ArrayDouble: + addConfigSpecOption<VariantType::ArrayDouble>(spec, options); + break; case VariantType::ArrayBool: + addConfigSpecOption<VariantType::ArrayBool>(spec, options); + break; case VariantType::Unknown: case VariantType::Empty: break; diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 20501791119af..1df540d247856 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -55,6 +55,7 @@ #include <unordered_map> #include <uv.h> #include <execinfo.h> +#include <sstream> using namespace o2::framework; using Key = o2::monitoring::tags::Key; @@ -175,6 +176,27 @@ void on_socket_polled(uv_poll_t* poller, int status, int events) // We do nothing, all the logic for now stays in DataProcessingDevice::doRun() } +namespace +{ +template <typename T> +std::string arrayPrinter(boost::property_tree::ptree const& tree) +{ + std::stringstream ss; + int size = tree.size(); + int count = 0; + ss << variant_array_symbol<T>::symbol << "["; + for (auto& element : tree) { + ss << element.second.get_value<T>(); + if (count < size - 1) { + ss << ","; + } + ++count; + } + ss << "]"; + return ss.str(); +} +} // namespace + /// This takes care of initialising the device from its specification. In /// particular it needs to: /// @@ -219,14 +241,13 @@ void DataProcessingDevice::Init() } else { retrievers.emplace_back(std::make_unique<FairOptionsRetriever>(GetConfig())); } - auto configStore = std::move(std::make_unique<ConfigParamStore>(mSpec.options, std::move(retrievers))); + auto configStore = std::make_unique<ConfigParamStore>(mSpec.options, std::move(retrievers)); configStore->preload(); configStore->activate(); using boost::property_tree::ptree; /// Dump the configuration so that we can get it from the driver. for (auto& entry : configStore->store()) { - LOG(INFO) << "[CONFIG] " << entry.first << "=" << configStore->store().get<std::string>(entry.first) << " 1 " << configStore->provenance(entry.first.c_str()); PropertyTreeHelpers::WalkerFunction printer = [&configStore, topLevel = entry.first](ptree const& parent, ptree::path_type childPath, ptree const& child) { // FIXME: not clear why we get invoked for the root entry // and twice for each node. It nevertheless works @@ -236,8 +257,32 @@ void DataProcessingDevice::Init() LOG(INFO) << "[CONFIG] " << topLevel << "." << childPath.dump() << "=" << child.data() << " 1 " << configStore->provenance(topLevel.c_str()); } }; - PropertyTreeHelpers::traverse(entry.second, printer); + + auto spec = std::find_if(configStore->specs().begin(), configStore->specs().end(), [&](auto& x) { return x.name == entry.first; }); + if (spec != configStore->specs().end()) { + switch (spec->type) { + case VariantType::ArrayInt: + LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<int>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); + break; + case VariantType::ArrayFloat: + LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<float>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); + break; + case VariantType::ArrayDouble: + LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<double>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); + break; + case VariantType::ArrayBool: + LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<bool>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); + break; + default: + LOG(INFO) << "[CONFIG] " << entry.first << "=" << configStore->store().get<std::string>(entry.first) << " 1 " << configStore->provenance(entry.first.c_str()); + PropertyTreeHelpers::traverse(entry.second, printer); + } + } else { + LOG(INFO) << "[CONFIG] " << entry.first << "=" << configStore->store().get<std::string>(entry.first) << " 1 " << configStore->provenance(entry.first.c_str()); + PropertyTreeHelpers::traverse(entry.second, printer); + } } + mConfigRegistry = std::make_unique<ConfigParamRegistry>(std::move(configStore)); mExpirationHandlers.clear(); diff --git a/Framework/Core/src/DeviceConfigInfo.cxx b/Framework/Core/src/DeviceConfigInfo.cxx index 62266282d5f89..3c5360a0c36ad 100644 --- a/Framework/Core/src/DeviceConfigInfo.cxx +++ b/Framework/Core/src/DeviceConfigInfo.cxx @@ -10,15 +10,9 @@ #include "Framework/DeviceConfigInfo.h" #include "Framework/DeviceInfo.h" -#include <cassert> -#include <cinttypes> #include <cstdlib> - -#include <algorithm> #include <regex> #include <string_view> -#include <tuple> -#include <iostream> namespace o2::framework { @@ -67,10 +61,26 @@ bool DeviceConfigHelper::processConfig(ParsedConfigMatch& match, match.beginProvenance == nullptr || match.endProvenance == nullptr) { return false; } - info.currentConfig.put(std::string(match.beginKey, match.endKey - match.beginKey), - std::string(match.beginValue, match.endValue - match.beginValue)); - info.currentProvenance.put(std::string(match.beginKey, match.endKey - match.beginKey), - std::string(match.beginProvenance, match.endProvenance - match.beginProvenance)); + auto keyString = std::string(match.beginKey, match.endKey - match.beginKey); + auto valueString = std::string(match.beginValue, match.endValue - match.beginValue); + auto provenanceString = std::string(match.beginProvenance, match.endProvenance - match.beginProvenance); + std::regex fmatch(R"([ifdb]\[.*\])", std::regex_constants::ECMAScript); + std::regex nmatch(R"((?:(?!=,)|(?!=\[))[+-]?\d+\.?\d*(?:[eE][+-]?\d+)?(?=,|\]))", std::regex_constants::ECMAScript); + auto end = std::sregex_iterator(); + auto fmt = std::sregex_iterator(valueString.begin(), valueString.end(), fmatch); + if (fmt != end) { + boost::property_tree::ptree branch; + auto values = std::sregex_iterator(valueString.begin(), valueString.end(), nmatch); + for (auto v = values; v != end; ++v) { + boost::property_tree::ptree leaf; + leaf.put("", v->str()); + branch.push_back(std::make_pair("", leaf)); + } + info.currentConfig.put_child(keyString, branch); + } else { + info.currentConfig.put(keyString, valueString); + } + info.currentProvenance.put(keyString, provenanceString); return true; } diff --git a/Framework/Core/src/PropertyTreeHelpers.cxx b/Framework/Core/src/PropertyTreeHelpers.cxx index 70b9c21fd3d69..4b64081b128a2 100644 --- a/Framework/Core/src/PropertyTreeHelpers.cxx +++ b/Framework/Core/src/PropertyTreeHelpers.cxx @@ -14,6 +14,8 @@ #include <boost/property_tree/ptree.hpp> #include <boost/program_options/variables_map.hpp> +#include <boost/tokenizer.hpp> +#include <boost/lexical_cast.hpp> #include <vector> #include <string> @@ -25,6 +27,16 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s boost::property_tree::ptree& pt, boost::property_tree::ptree& provenance) { + auto addBranch = [&](std::string key, auto* values, size_t size) { + boost::property_tree::ptree branch; + for (auto i = 0u; i < size; ++i) { + boost::property_tree::ptree leaf; + leaf.put("", values[i]); + branch.push_back(std::make_pair("", leaf)); + } + pt.put_child(key, branch); + }; + for (auto& spec : schema) { std::string key = spec.name.substr(0, spec.name.find(",")); try { @@ -50,6 +62,18 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s case VariantType::Bool: pt.put(key, spec.defaultValue.get<bool>()); break; + case VariantType::ArrayInt: + addBranch(key, spec.defaultValue.get<int*>(), spec.defaultValue.size()); + break; + case VariantType::ArrayFloat: + addBranch(key, spec.defaultValue.get<float*>(), spec.defaultValue.size()); + break; + case VariantType::ArrayDouble: + addBranch(key, spec.defaultValue.get<double*>(), spec.defaultValue.size()); + break; + case VariantType::ArrayBool: + addBranch(key, spec.defaultValue.get<bool*>(), spec.defaultValue.size()); + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -66,11 +90,38 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s } } +namespace +{ +template <typename T> +std::vector<T> toVector(std::string const& input) +{ + std::vector<T> result; + //check if the array string has correct array type symbol + assert(input[0] == variant_array_symbol<T>::symbol); + //strip type symbol and parentheses + boost::tokenizer<> tokenizer(input.substr(2, input.size() - 3)); + for (auto it = tokenizer.begin(); it != tokenizer.end(); ++it) { + result.push_back(boost::lexical_cast<T>(*it)); + } + return result; +} +} // namespace + void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, boost::property_tree::ptree& pt, boost::program_options::variables_map const& vmap, boost::property_tree::ptree& provenance) { + auto addBranch = [&](std::string key, auto vector) { + boost::property_tree::ptree branch; + for (auto i = 0u; i < vector.size(); ++i) { + boost::property_tree::ptree leaf; + leaf.put("", vector[i]); + branch.push_back(std::make_pair("", leaf)); + } + pt.put_child(key, branch); + }; + for (auto& spec : schema) { // strip short version to get the correct key std::string key = spec.name.substr(0, spec.name.find(",")); @@ -99,6 +150,26 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, case VariantType::Bool: pt.put(key, vmap[key].as<bool>()); break; + case VariantType::ArrayInt: { + auto v = toVector<int>(vmap[key].as<std::string>()); + addBranch(key, v); + }; + break; + case VariantType::ArrayFloat: { + auto v = toVector<float>(vmap[key].as<std::string>()); + addBranch(key, v); + }; + break; + case VariantType::ArrayDouble: { + auto v = toVector<double>(vmap[key].as<std::string>()); + addBranch(key, v); + }; + break; + case VariantType::ArrayBool: { + auto v = toVector<bool>(vmap[key].as<std::string>()); + addBranch(key, v); + }; + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -148,6 +219,12 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, case VariantType::Bool: pt.put(key, (*it).get_value<bool>()); break; + case VariantType::ArrayInt: + case VariantType::ArrayFloat: + case VariantType::ArrayDouble: + case VariantType::ArrayBool: + pt.put_child(key, *it); + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -186,15 +263,4 @@ void PropertyTreeHelpers::traverse(const boost::property_tree::ptree& parent, Pr traverseRecursive(parent, "", parent, method); } -void PropertyTreeHelpers::merge(boost::property_tree::ptree& dest, - boost::property_tree::ptree const& source, - boost::property_tree::ptree::path_type const& mergePoint) -{ - using boost::property_tree::ptree; - WalkerFunction merge = [&dest, &mergePoint](ptree const& parent, ptree::path_type childPath, ptree const& child) { - dest.put(mergePoint / childPath, child.data()); - }; - traverse(source, merge); -} - } // namespace o2::framework diff --git a/Framework/Core/src/Variant.cxx b/Framework/Core/src/Variant.cxx index 53d75228ef388..c1f9708bed46b 100644 --- a/Framework/Core/src/Variant.cxx +++ b/Framework/Core/src/Variant.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "Framework/Variant.h" #include <iostream> +#include <sstream> namespace o2::framework { @@ -18,12 +19,14 @@ namespace template <typename T> void printArray(std::ostream& oss, T* array, size_t size) { + oss << variant_array_symbol<T>::symbol << "["; for (auto i = 0u; i < size; ++i) { oss << array[i]; if (i < size - 1) { - oss << ", "; + oss << ","; } } + oss << "]"; } } // namespace @@ -69,4 +72,11 @@ std::ostream& operator<<(std::ostream& oss, Variant const& val) return oss; } +std::string Variant::asString() const +{ + std::stringstream ss; + ss << *this; + return ss.str(); +} + } // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index afd00fa82be97..d352d6b6d1a5b 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1299,7 +1299,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, for (size_t di = 0; di < infos.size(); ++di) { auto info = infos[di]; auto spec = deviceSpecs[di]; - PropertyTreeHelpers::merge(finalConfig, info.currentConfig, spec.name); + finalConfig.put_child(spec.name, info.currentConfig); } LOG(INFO) << "Dumping used configuration in dpl-config.json"; boost::property_tree::write_json("dpl-config.json", finalConfig); diff --git a/Framework/Core/test/test_DeviceConfigInfo.cxx b/Framework/Core/test/test_DeviceConfigInfo.cxx index de38eecc02164..190e131d88548 100644 --- a/Framework/Core/test/test_DeviceConfigInfo.cxx +++ b/Framework/Core/test/test_DeviceConfigInfo.cxx @@ -13,10 +13,32 @@ #include "Framework/DeviceConfigInfo.h" #include "Framework/DeviceInfo.h" +#include "Framework/Variant.h" #include <boost/test/unit_test.hpp> +#include <boost/tokenizer.hpp> +#include <boost/lexical_cast.hpp> #include <string_view> +#include <regex> -BOOST_AUTO_TEST_CASE(TestDeviceMetricsInfo) +template <typename T> +std::string arrayPrinter(boost::property_tree::ptree const& tree) +{ + std::stringstream ss; + int size = tree.size(); + int count = 0; + ss << o2::framework::variant_array_symbol<T>::symbol << "["; + for (auto& element : tree) { + ss << element.second.get_value<T>(); + if (count < size - 1) { + ss << ","; + } + ++count; + } + ss << "]"; + return ss.str(); +} + +BOOST_AUTO_TEST_CASE(TestDeviceConfigInfo) { using namespace o2::framework; std::string configString; @@ -76,4 +98,22 @@ BOOST_AUTO_TEST_CASE(TestDeviceMetricsInfo) BOOST_CHECK_EQUAL(result, true); BOOST_CHECK_EQUAL(info.currentConfig.get<std::string>("foo"), "bar"); BOOST_CHECK_EQUAL(info.currentProvenance.get<std::string>("foo"), "prov"); + + // Parse an array + configString = "foo[XX:XX:XX][INFO] [CONFIG] array=i[1,2,3,4] 1789372894 prov\n"; + std::string_view configa{configString.data() + 3, configString.size() - 4}; + result = DeviceConfigHelper::parseConfig(configa, match); + auto valueString = std::string(match.beginValue, match.endValue - match.beginValue); + + BOOST_REQUIRE_EQUAL(result, true); + BOOST_CHECK(strncmp(match.beginKey, "array", 5) == 0); + BOOST_CHECK_EQUAL(match.timestamp, 1789372894); + BOOST_CHECK(strncmp(match.beginValue, "i[1,2,3,4]", 10) == 0); + BOOST_CHECK(strncmp(match.beginProvenance, "prov", 4) == 0); + + // Process a given config entry + result = DeviceConfigHelper::processConfig(match, info); + BOOST_CHECK_EQUAL(result, true); + BOOST_CHECK_EQUAL(info.currentProvenance.get<std::string>("array"), "prov"); + BOOST_CHECK_EQUAL(arrayPrinter<int>(info.currentConfig.get_child("array")), "i[1,2,3,4]"); } From d7fcd3f2fc00a4274504bc2d279e418b424b4b9d Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <chiara.zampolli@cern.ch> Date: Fri, 20 Nov 2020 11:02:53 +0100 Subject: [PATCH 1388/1751] Fixing CCDB filling for DCS processors (#4867) * Fixing CCDB filling for DCS processors * Update DCSDataProcessorSpec.h * Please consider the following formatting changes (#23) Co-authored-by: ALICE Builder <alibuild@users.noreply.github.com> --- .../DCS/testWorkflow/DCSDataProcessorSpec.h | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h index 2f5569106e77c..1f00bcadc8744 100644 --- a/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSDataProcessorSpec.h @@ -93,9 +93,6 @@ class DCSDataProcessor : public o2::framework::Task pidVect.push_back(dpidtmp); mDetectorPid[dpidtmp] = vectDet; - mDCSproc.init(pidVect); - mDCSproc.setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); - mDCSproc.setName("Test0Det"); for (int idet = 0; idet < kNdetectors; idet++) { mDCSprocVect[idet].init(pidVect); mDCSprocVect[idet].setMaxCyclesNoFullMap(ic.options().get<int64_t>("max-cycles-no-full-map")); @@ -107,7 +104,6 @@ class DCSDataProcessor : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final { auto tfid = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; - mDCSproc.setTF(tfid); for (int idet = 0; idet < kNdetectors; idet++) { mDCSprocVect[idet].setTF(tfid); } @@ -275,7 +271,6 @@ class DCSDataProcessor : public o2::framework::Task private: std::unordered_map<DPID, std::vector<int>> mDetectorPid; std::array<DCSProcessor, kNdetectors> mDCSprocVect; - o2::dcs::DCSProcessor mDCSproc; TStopwatch mReceiveBinaryData; TStopwatch mDeltaReceiveBinaryData; TStopwatch mBuildingUnorderedMap; @@ -299,14 +294,16 @@ class DCSDataProcessor : public o2::framework::Task // extract CCDB infos and calibration objects, convert it to TMemFile and send them to the output // copied from LHCClockCalibratorSpec.cxx using clbUtils = o2::calibration::Utils; - const auto& payload = mDCSproc.getCCDBSimpleMovingAverage(); - auto& info = mDCSproc.getCCDBSimpleMovingAverageInfo(); - auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); - LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() - << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); - - output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); - output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); + for (int idet = 0; idet < kNdetectors; idet++) { + const auto& payload = mDCSprocVect[idet].getCCDBSimpleMovingAverage(); + auto& info = mDCSprocVect[idet].getCCDBSimpleMovingAverageInfo(); + auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); + LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); + } } }; // end class } // namespace dcs From 3b42e1c48e3fa3f272e1c1696cda8919154e6895 Mon Sep 17 00:00:00 2001 From: Michael Lettrich <michael.lettrich@cern.ch> Date: Fri, 20 Nov 2020 10:25:49 +0100 Subject: [PATCH 1389/1751] [rANS] Fix: missing return statements --- Utilities/rANS/include/rANS/utils/CombinedIterator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Utilities/rANS/include/rANS/utils/CombinedIterator.h b/Utilities/rANS/include/rANS/utils/CombinedIterator.h index f1569731e644c..46a92d45ccfba 100644 --- a/Utilities/rANS/include/rANS/utils/CombinedIterator.h +++ b/Utilities/rANS/include/rANS/utils/CombinedIterator.h @@ -130,6 +130,7 @@ auto CombinedInputIterator<iterA_T, iterB_T, F>::operator=(const CombinedInputIt { mIterA = other.mIterA; mIterB = other.mIterB; + return *this; } template <class iterA_T, class iterB_T, class F> @@ -176,6 +177,7 @@ auto CombinedOutputIterator<iterA_T, iterB_T, F>::operator=(const CombinedOutput { mIterA = other.mIterA; mIterB = other.mIterB; + return *this; } template <class iterA_T, class iterB_T, class F> From 64c3bed6f49326e5841bc95f9d1903d033e35753 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 20 Nov 2020 08:51:38 +0100 Subject: [PATCH 1390/1751] Fix for reading external Hijing kinematics provided by Andreas Morsch --- Generators/src/GeneratorFromFile.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Generators/src/GeneratorFromFile.cxx b/Generators/src/GeneratorFromFile.cxx index a93a750b256f9..112ea38f7bfc4 100644 --- a/Generators/src/GeneratorFromFile.cxx +++ b/Generators/src/GeneratorFromFile.cxx @@ -14,6 +14,7 @@ #include <TBranch.h> #include <TClonesArray.h> #include <TFile.h> +#include <TMCProcess.h> #include <TParticle.h> #include <TTree.h> #include <sstream> @@ -110,7 +111,7 @@ Bool_t GeneratorFromFile::ReadEvent(FairPrimaryGenerator* primGen) auto isFirstTrackableDescendant = [](TParticle const& p) { const int kTransportBit = BIT(14); // The particle should have not set kDone bit and its status should not exceed 1 - if (p.GetUniqueID() > 0 || !p.TestBit(kTransportBit)) { + if ((p.GetUniqueID() > 0 && p.GetUniqueID() != kPNoProcess) || !p.TestBit(kTransportBit)) { return false; } return true; From 833c1e7b3a3be232448db7060d07e56d938da7ef Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Fri, 20 Nov 2020 10:40:58 -0300 Subject: [PATCH 1391/1751] Changes to strangeness tables: filter at producer level (#4866) * Changes to strangeness tables: filter at producer level, generic analysis tables * Add period in copyright notice... * Add unnecessary braces --- .../include/Analysis/StrangenessTables.h | 28 ++--- Analysis/DataModel/src/aodDataModelGraph.cxx | 1 - Analysis/Tasks/PWGLF/cascadeconsumer.cxx | 18 ++- Analysis/Tasks/PWGLF/cascadefinder.cxx | 46 ++++--- Analysis/Tasks/PWGLF/cascadeproducer.cxx | 18 ++- Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx | 17 ++- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 29 +++-- Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 113 +++++++++++++++--- 8 files changed, 209 insertions(+), 61 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/StrangenessTables.h b/Analysis/DataModel/include/Analysis/StrangenessTables.h index c5983b6fbe335..a56386ef48d3a 100644 --- a/Analysis/DataModel/include/Analysis/StrangenessTables.h +++ b/Analysis/DataModel/include/Analysis/StrangenessTables.h @@ -17,6 +17,11 @@ namespace o2::aod { namespace v0data { +//Needed to have shorter table that does not rely on existing one (filtering!) +DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, FullTracks, "fPosTrackID"); +DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, FullTracks, "fNegTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); + //General V0 properties: position, momentum DECLARE_SOA_COLUMN(PxPos, pxpos, float); DECLARE_SOA_COLUMN(PyPos, pypos, float); @@ -62,6 +67,7 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::v0data::pzpos + 1.f * ao } // namespace v0dataext DECLARE_SOA_TABLE(V0Data, "AOD", "V0DATA", + o2::soa::Index<>, v0data::PosTrackId, v0data::NegTrackId, v0data::CollisionId, v0data::X, v0data::Y, v0data::Z, v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg, @@ -91,16 +97,12 @@ DECLARE_SOA_EXTENDED_TABLE_USER(V0DataExt, V0DataOrigin, "V0DATAEXT", using V0DataFull = V0DataExt; -namespace v0finderdata -{ -DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, FullTracks, "fPosTrackID"); -DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, FullTracks, "fNegTrackID"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace v0finderdata -DECLARE_SOA_TABLE(V0FinderData, "AOD", "V0FINDERDATA", o2::soa::Index<>, v0finderdata::PosTrackId, v0finderdata::NegTrackId, v0finderdata::CollisionId); - namespace cascdata { +//Necessary for full filtering functionality +DECLARE_SOA_INDEX_COLUMN_FULL(V0, v0, int, V0DataExt, "fV0ID"); +DECLARE_SOA_INDEX_COLUMN_FULL(BachTrack, bachTrack, int, FullTracks, "fBachTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //General V0 properties: position, momentum DECLARE_SOA_COLUMN(Charge, charge, int); DECLARE_SOA_COLUMN(PxPos, pxpos, float); @@ -163,6 +165,8 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::cascdata::pzpos + 1.f * } // namespace cascdataext DECLARE_SOA_TABLE(CascData, "AOD", "CASCDATA", + o2::soa::Index<>, cascdata::V0Id, cascdata::BachTrackId, cascdata::CollisionId, + cascdata::Charge, cascdata::X, cascdata::Y, cascdata::Z, cascdata::Xlambda, cascdata::Ylambda, cascdata::Zlambda, @@ -198,14 +202,6 @@ DECLARE_SOA_EXTENDED_TABLE_USER(CascDataExt, CascDataOrigin, "CascDATAEXT", cascdataext::Px, cascdataext::Py, cascdataext::Pz); using CascDataFull = CascDataExt; - -namespace cascfinderdata -{ -DECLARE_SOA_INDEX_COLUMN_FULL(V0, v0, int, V0FinderData, "fV0ID"); -DECLARE_SOA_INDEX_COLUMN_FULL(BachTrack, bachTrack, int, FullTracks, "fBachTrackID"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace cascfinderdata -DECLARE_SOA_TABLE(CascFinderData, "AOD", "CASCFINDERDATA", o2::soa::Index<>, cascfinderdata::V0Id, cascfinderdata::BachTrackId, cascfinderdata::CollisionId); } // namespace o2::aod #endif // O2_ANALYSIS_STRANGENESSTABLES_H_ diff --git a/Analysis/DataModel/src/aodDataModelGraph.cxx b/Analysis/DataModel/src/aodDataModelGraph.cxx index 49454df0cd62a..9670ecdae0947 100644 --- a/Analysis/DataModel/src/aodDataModelGraph.cxx +++ b/Analysis/DataModel/src/aodDataModelGraph.cxx @@ -262,7 +262,6 @@ int main(int, char**) displayEntity<JetConstituents>(); displayEntities<V0s, V0DataFull>(); - displayEntity<V0FinderData>(); displayEntities<Cascades, CascDataFull>(); diff --git a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx index 20f4696379910..5919010b888c9 100644 --- a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx @@ -7,6 +7,20 @@ // 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. +// +// Example cascade analysis task +// ============================= +// +// This code loops over a CascData table and produces some +// standard analysis output. It requires either +// the cascadefinder or the cascadeproducer tasks +// to have been executed in the workflow (before). +// +// Comments, questions, complaints, suggestions? +// Please write to: +// david.dobrigkeit.chinellato@cern.ch +// + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -57,7 +71,7 @@ struct cascadeQA { OutputObj<TH1F> hDCACascDau{TH1F("hDCACascDau", "", 1000, 0.0, 10.0)}; OutputObj<TH1F> hLambdaMass{TH1F("hLambdaMass", "", 1000, 0.0, 10.0)}; - void process(aod::Collision const& collision, soa::Join<aod::Cascades, aod::CascDataExt> const& Cascades) + void process(aod::Collision const& collision, aod::CascDataExt const& Cascades) { for (auto& casc : Cascades) { if (casc.charge() < 0) { //FIXME: could be done better... @@ -107,7 +121,7 @@ struct cascadeconsumer { aod::cascdata::dcabachtopv > dcabachtopv&& aod::cascdata::dcaV0daughters < dcav0dau&& aod::cascdata::dcacascdaughters < dcacascdau; - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::Cascades, aod::CascDataExt>> const& Cascades) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<aod::CascDataExt> const& Cascades) { if (!collision.alias()[kINT7]) { return; diff --git a/Analysis/Tasks/PWGLF/cascadefinder.cxx b/Analysis/Tasks/PWGLF/cascadefinder.cxx index fe786ab62a778..224e5ef253c0c 100644 --- a/Analysis/Tasks/PWGLF/cascadefinder.cxx +++ b/Analysis/Tasks/PWGLF/cascadefinder.cxx @@ -8,7 +8,24 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// This task re-reconstructs the V0s and cascades +// Cascade Finder task +// =================== +// +// This code loops over existing V0s and bachelor tracks and finds +// valid cascade candidates from scratch using a certain set of +// minimum (configurable) selection criteria. +// +// It is different than the producer: the producer merely +// loops over an *existing* list of cascades (V0+bachelor track +// indices) and calculates the corresponding full cascade information +// +// In both cases, any analysis should loop over the "CascData" +// table as that table contains all information. +// +// Comments, questions, complaints, suggestions? +// Please write to: +// david.dobrigkeit.chinellato@cern.ch +// #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -47,8 +64,6 @@ using namespace ROOT::Math; namespace o2::aod { -using V0FinderFull = soa::Join<aod::V0FinderData, aod::V0DataExt>; - namespace cascgoodpostracks { DECLARE_SOA_INDEX_COLUMN_FULL(GoodPosTrack, goodPosTrack, int, FullTracks, "fGoodPosTrackID"); @@ -65,13 +80,13 @@ DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); DECLARE_SOA_TABLE(CascGoodNegTracks, "AOD", "CASCGOODNTRACKS", o2::soa::Index<>, cascgoodnegtracks::GoodNegTrackId, cascgoodnegtracks::CollisionId, cascgoodnegtracks::DCAXY); namespace cascgoodlambdas { -DECLARE_SOA_INDEX_COLUMN_FULL(GoodLambda, goodLambda, int, V0FinderFull, "fGoodLambdaId"); +DECLARE_SOA_INDEX_COLUMN_FULL(GoodLambda, goodLambda, int, V0DataExt, "fGoodLambdaId"); DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace cascgoodlambdas DECLARE_SOA_TABLE(CascGoodLambdas, "AOD", "CASCGOODLAM", o2::soa::Index<>, cascgoodlambdas::GoodLambdaId, cascgoodlambdas::CollisionId); namespace cascgoodantilambdas { -DECLARE_SOA_INDEX_COLUMN_FULL(GoodAntiLambda, goodAntiLambda, int, V0FinderFull, "fGoodAntiLambdaId"); +DECLARE_SOA_INDEX_COLUMN_FULL(GoodAntiLambda, goodAntiLambda, int, V0DataExt, "fGoodAntiLambdaId"); DECLARE_SOA_INDEX_COLUMN(Collision, collision); } // namespace cascgoodantilambdas DECLARE_SOA_TABLE(CascGoodAntiLambdas, "AOD", "CASCGOODALAM", o2::soa::Index<>, cascgoodantilambdas::GoodAntiLambdaId, cascgoodantilambdas::CollisionId); @@ -95,11 +110,13 @@ struct cascadeprefilter { Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodPosTracks = aod::track::signed1Pt > 0.0f && aod::track::dcaXY > dcabachtopv; Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodNegTracks = aod::track::signed1Pt < 0.0f && aod::track::dcaXY < -dcabachtopv; - Partition<soa::Join<aod::V0FinderData, aod::V0DataExt>> goodV0s = aod::v0data::dcapostopv > dcapostopv&& aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + Partition<aod::V0DataExt> goodV0s = aod::v0data::dcapostopv > dcapostopv&& aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + + using FullTracksExt = soa::Join<aod::FullTracks, aod::TracksExtended>; void process(aod::Collision const& collision, - soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks, - soa::Join<aod::V0FinderData, aod::V0DataExt> const& V0s) + FullTracksExt const& tracks, + aod::V0DataExt const& V0s) { for (auto& t0 : goodPosTracks) { if (!(t0.flags() & 0x40)) { @@ -139,7 +156,6 @@ struct cascadeprefilter { struct cascadefinder { Produces<aod::CascData> cascdata; - Produces<aod::CascFinderData> cascfinderdata; OutputObj<TH1F> hCandPerEvent{TH1F("hCandPerEvent", "", 100, 0, 100)}; @@ -155,7 +171,7 @@ struct cascadefinder { //Process: subscribes to a lot of things! void process(aod::Collision const& collision, aod::FullTracks const& tracks, - soa::Join<aod::V0FinderData, aod::V0DataExt> const& V0s, + aod::V0DataExt const& V0s, aod::CascGoodLambdas const& lambdas, aod::CascGoodAntiLambdas const& antiLambdas, aod::CascGoodPosTracks const& pBachtracks, @@ -248,8 +264,8 @@ struct cascadefinder { lNCand++; //If we got here, it means this is a good candidate! - cascfinderdata(v0.globalIndex(), t0.globalIndex(), t0.collisionId()); - cascdata(-1, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], + cascdata(v0.globalIndex(), v0.posTrack().globalIndex(), v0.negTrack().collisionId(), + -1, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], pvecpos[0], pvecpos[1], pvecpos[2], pvecneg[0], pvecneg[1], pvecneg[2], pvecbach[0], pvecbach[1], pvecbach[2], @@ -320,8 +336,8 @@ struct cascadefinder { lNCand++; //If we got here, it means this is a good candidate! - cascfinderdata(v0.globalIndex(), t0.globalIndex(), t0.collisionId()); - cascdata(+1, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], + cascdata(v0.globalIndex(), v0.posTrack().globalIndex(), v0.negTrack().collisionId(), + +1, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], pvecpos[0], pvecpos[1], pvecpos[2], pvecneg[0], pvecneg[1], pvecneg[2], pvecbach[0], pvecbach[1], pvecbach[2], @@ -364,7 +380,7 @@ struct cascadefinderQA { aod::cascdata::dcaV0daughters < dcav0dau&& aod::cascdata::dcacascdaughters < dcacascdau; ///Connect to CascFinderData: newly indexed, note: CascDataExt table incompatible with standard V0 table! - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::CascFinderData, aod::CascDataExt>> const& Cascades) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<aod::CascDataExt> const& Cascades) { if (!collision.alias()[kINT7]) { return; diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx index 90343a61e9d4c..4fdb3fff6251e 100644 --- a/Analysis/Tasks/PWGLF/cascadeproducer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -7,6 +7,21 @@ // 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. +// +// Cascade Producer task +// ===================== +// +// This task loops over an *existing* list of cascades (V0+bachelor track +// indices) and calculates the corresponding full cascade information +// +// Any analysis should loop over the "CascData" +// table as that table contains all information +// +// Comments, questions, complaints, suggestions? +// Please write to: +// david.dobrigkeit.chinellato@cern.ch +// + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -152,7 +167,8 @@ struct cascadeproducer { } //end if cascade recoed } //end if v0 recoed //Fill table, please - cascdata(charge, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], + cascdata(casc.v0().globalIndex(), casc.bachelor().globalIndex(), casc.bachelor().collisionId(), + charge, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], pvecpos[0], pvecpos[1], pvecpos[2], pvecneg[0], pvecneg[1], pvecneg[2], pvecbach[0], pvecbach[1], pvecbach[2], diff --git a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx index cd1b7ed42787a..bd7982a42f063 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx @@ -7,6 +7,19 @@ // 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. +// +// Example V0 analysis task +// ======================== +// +// This code loops over a V0Data table and produces some +// standard analysis output. It requires either +// the lambdakzerofinder or the lambdakzeroproducer tasks +// to have been executed in the workflow (before). +// +// Comments, questions, complaints, suggestions? +// Please write to: +// david.dobrigkeit.chinellato@cern.ch +// #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -50,7 +63,7 @@ struct lambdakzeroQA { OutputObj<TH1F> hDCANegToPV{TH1F("hDCANegToPV", "", 1000, 0.0, 10.0)}; OutputObj<TH1F> hDCAV0Dau{TH1F("hDCAV0Dau", "", 1000, 0.0, 10.0)}; - void process(aod::Collision const& collision, soa::Join<aod::V0s, aod::V0DataExt> const& fullV0s) + void process(aod::Collision const& collision, aod::V0DataExt const& fullV0s) { for (auto& v0 : fullV0s) { hMassLambda->Fill(v0.mLambda()); @@ -82,7 +95,7 @@ struct lambdakzeroconsumer { Filter preFilterV0 = aod::v0data::dcapostopv > dcapostopv&& aod::v0data::dcanegtopv > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<soa::Join<aod::V0s, aod::V0DataExt>> const& fullV0s) + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, soa::Filtered<aod::V0DataExt> const& fullV0s) { if (!collision.alias()[kINT7]) { return; diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index c2d6c0f7455d5..a1b89481d6aaf 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -8,7 +8,24 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// This task re-reconstructs the V0s and cascades +// V0 Finder task +// ============== +// +// This code loops over positive and negative tracks and finds +// valid V0 candidates from scratch using a certain set of +// minimum (configurable) selection criteria. +// +// It is different than the producer: the producer merely +// loops over an *existing* list of V0s (pos+neg track +// indices) and calculates the corresponding full V0 information +// +// In both cases, any analysis should loop over the "V0Data" +// table as that table contains all information. +// +// Comments, questions, complaints, suggestions? +// Please write to: +// david.dobrigkeit.chinellato@cern.ch +// #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -99,7 +116,6 @@ struct lambdakzeroprefilter { struct lambdakzerofinder { Produces<aod::V0Data> v0data; - Produces<aod::V0FinderData> v0finderdata; OutputObj<TH1F> hCandPerEvent{TH1F("hCandPerEvent", "", 1000, 0, 1000)}; @@ -172,8 +188,8 @@ struct lambdakzerofinder { } lNCand++; - v0finderdata(t0.globalIndex(), t1.globalIndex(), t0.collisionId()); - v0data(pos[0], pos[1], pos[2], + v0data(t0.globalIndex(), t1.globalIndex(), t0.collisionId(), + pos[0], pos[1], pos[2], pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], fitter.getChi2AtPCACandidate(), @@ -210,10 +226,9 @@ struct lambdakzerofinderQA { //Filter preFilter2 = aod::v0data::dcanegtopv > dcanegtopv; //Filter preFilter3 = aod::v0data::dcaV0daughters < dcav0dau; - ///Connect to V0FinderData: newly indexed, note: V0DataExt table incompatible with standard V0 table! + ///Connect to V0Data: newly indexed, note: V0DataExt table incompatible with standard V0 table! void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator const& collision, - // soa::Filtered<soa::Join<aod::V0FinderData, aod::V0DataExt>> const& fullV0s) - soa::Join<aod::V0FinderData, aod::V0DataExt> const& fullV0s) + aod::V0DataExt const& fullV0s) { if (!collision.alias()[kINT7]) { return; diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index 7bb8ccd925a67..349ac70069117 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -7,6 +7,21 @@ // 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. +// +// V0 Producer task +// ================ +// +// This task loops over an *existing* list of V0s (neg/pos track +// indices) and calculates the corresponding full V0 information +// +// Any analysis should loop over the "V0Data" +// table as that table contains all information +// +// Comments, questions, complaints, suggestions? +// Please write to: +// david.dobrigkeit.chinellato@cern.ch +// + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -17,6 +32,8 @@ #include "Analysis/RecoDecay.h" #include "Analysis/trackUtilities.h" #include "Analysis/StrangenessTables.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" #include <TFile.h> #include <TH2F.h> @@ -36,6 +53,63 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +//This table stores a filtered list of valid V0 indices +namespace o2::aod +{ +namespace v0goodindices +{ +DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, FullTracks, "fPositiveTrackID"); +DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, FullTracks, "fNegativeTrackID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +} // namespace v0goodindices +DECLARE_SOA_TABLE(V0GoodIndices, "AOD", "V0GOODINDICES", o2::soa::Index<>, + v0goodindices::PosTrackId, v0goodindices::NegTrackId, v0goodindices::CollisionId); +} // namespace o2::aod + +using FullTracksExt = soa::Join<aod::FullTracks, aod::TracksExtended>; + +//This prefilter creates a skimmed list of good V0s to re-reconstruct so that +//CPU is saved in case there are specific selections that are to be done +//Note: more configurables, more options to be added as needed +struct lambdakzeroprefilterpairs { + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<int> mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + Configurable<bool> tpcrefit{"tpcrefit", 1, "demand TPC refit"}; + + Produces<aod::V0GoodIndices> v0goodindices; + + void process(aod::Collision const& collision, aod::V0s const& V0s, + soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) + { + for (auto& V0 : V0s) { + if (tpcrefit) { + if (!(V0.posTrack().flags() & 0x40)) { + continue; //TPC refit + } + if (!(V0.negTrack().flags() & 0x40)) { + continue; //TPC refit + } + } + if (V0.posTrack().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + if (V0.negTrack().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + + if (V0.posTrack_as<FullTracksExt>().dcaXY() < dcapostopv) { + continue; + } + if (V0.negTrack_as<FullTracksExt>().dcaXY() < dcanegtopv) { + continue; + } + + v0goodindices(V0.posTrack().globalIndex(), V0.negTrack().globalIndex(), V0.posTrack().collisionId()); + } + } +}; + /// Cascade builder task: rebuilds cascades struct lambdakzeroproducer { @@ -48,25 +122,18 @@ struct lambdakzeroproducer { Configurable<double> d_bz{"d_bz", -5.0, "bz field"}; Configurable<double> d_UseAbsDCA{"d_UseAbsDCA", kTRUE, "Use Abs DCAs"}; + //Selection criteria + Configurable<double> v0cospa{"v0cospa", 0.995, "V0 CosPA"}; //double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable<float> dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + Configurable<float> v0radius{"v0radius", 5.0, "v0radius"}; + double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); double massKa = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); double massPr = TDatabasePDG::Instance()->GetParticle(kProton)->Mass(); - /// Extracts dca in the XY plane - /// \return dcaXY - template <typename T, typename U> - auto getdcaXY(const T& track, const U& coll) - { - //Calculate DCAs - auto sinAlpha = sin(track.alpha()); - auto cosAlpha = cos(track.alpha()); - auto globalX = track.x() * cosAlpha - track.y() * sinAlpha; - auto globalY = track.x() * sinAlpha + track.y() * cosAlpha; - return sqrt(pow((globalX - coll[0]), 2) + - pow((globalY - coll[1]), 2)); - } + using FullTracksExt = soa::Join<aod::FullTracks, aod::TracksExtended>; - void process(aod::Collision const& collision, aod::V0s const& V0s, aod::FullTracks const& tracks) + void process(aod::Collision const& collision, aod::V0GoodIndices const& V0s, soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { //Define o2 fitter, 2-prong o2::vertexing::DCAFitterN<2> fitter; @@ -102,12 +169,24 @@ struct lambdakzeroproducer { fitter.getTrack(1).getPxPyPzGlo(pvec1); } - v0data(pos[0], pos[1], pos[2], + //Apply selections so a skimmed table is created only + if (fitter.getChi2AtPCACandidate() < dcav0dau) { + continue; + } + + auto V0CosinePA = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, array{pos[0], pos[1], pos[2]}, array{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}); + + if (V0CosinePA < v0cospa) { + continue; + } + + v0data(V0.posTrack().globalIndex(), V0.negTrack().globalIndex(), V0.negTrack().collisionId(), + pos[0], pos[1], pos[2], pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], fitter.getChi2AtPCACandidate(), - getdcaXY(V0.posTrack(), pVtx), - getdcaXY(V0.negTrack(), pVtx)); + V0.posTrack_as<FullTracksExt>().dcaXY(), + V0.negTrack_as<FullTracksExt>().dcaXY()); } } }; From 4f850783bf6b43507883499f4e32bcf6ca7e98a0 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 20 Nov 2020 17:19:24 +0100 Subject: [PATCH 1392/1751] DPL: improve documentation --- Framework/Core/include/Framework/Lifetime.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/Lifetime.h b/Framework/Core/include/Framework/Lifetime.h index 6bad4de842d5e..ad235633b4d8e 100644 --- a/Framework/Core/include/Framework/Lifetime.h +++ b/Framework/Core/include/Framework/Lifetime.h @@ -14,13 +14,19 @@ namespace o2::framework { /// Possible Lifetime of objects being exchanged by the DPL. -/// FIXME: currently only Timeframe behaves as expected. enum struct Lifetime { - Timeframe, + /// A message which is associated to a timeframe. DPL will wait indefinitely for it by default. + Timeframe, + /// Eventually a message whose content is retrieved from CCDB Condition, + /// Do not use for now QA, + /// Do not use for now. Transient, + /// A message which is created whenever a Timer expires Timer, + /// A message which is created immediately, with payload / containing a + /// single value which gets incremented for every / invokation. Enumeration, Signal }; From d1b2b902e1d1283dcc0f83a13abf482c5adb80be Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 20 Nov 2020 17:19:48 +0100 Subject: [PATCH 1393/1751] DPL: introduce Lifetime::Optional If data is present, use simply give the data. If data is not present on input, create a dummy entry. --- Framework/Core/include/Framework/Lifetime.h | 11 +++++- .../Core/include/Framework/LifetimeHelpers.h | 18 +++++---- Framework/Core/src/DeviceSpecHelpers.cxx | 31 ++++++++++++++++ Framework/Core/src/LifetimeHelpers.cxx | 37 ++++++++++++++++--- Framework/Core/src/WorkflowHelpers.cxx | 1 + 5 files changed, 83 insertions(+), 15 deletions(-) diff --git a/Framework/Core/include/Framework/Lifetime.h b/Framework/Core/include/Framework/Lifetime.h index ad235633b4d8e..9f7434aac1017 100644 --- a/Framework/Core/include/Framework/Lifetime.h +++ b/Framework/Core/include/Framework/Lifetime.h @@ -16,7 +16,7 @@ namespace o2::framework /// Possible Lifetime of objects being exchanged by the DPL. enum struct Lifetime { /// A message which is associated to a timeframe. DPL will wait indefinitely for it by default. - Timeframe, + Timeframe, /// Eventually a message whose content is retrieved from CCDB Condition, /// Do not use for now @@ -28,7 +28,14 @@ enum struct Lifetime { /// A message which is created immediately, with payload / containing a /// single value which gets incremented for every / invokation. Enumeration, - Signal + /// A message which is created every time a SIGUSR1 is received. + Signal, + /// An optional message. When data arrives, if not already part of the data, + /// a dummy entry will be generated. + /// This comes handy e.g. to handle Raw Data, since DataDistribution will provide + /// everything in one go so whatever is expected but not there, for whatever reason + /// will be substituted with a dummy entry. + Optional }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/LifetimeHelpers.h b/Framework/Core/include/Framework/LifetimeHelpers.h index 2c358af5a095b..797ac65f68fba 100644 --- a/Framework/Core/include/Framework/LifetimeHelpers.h +++ b/Framework/Core/include/Framework/LifetimeHelpers.h @@ -7,8 +7,8 @@ // 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_LIFETIMEHELPERS_H -#define FRAMEWORK_LIFETIMEHELPERS_H +#ifndef O2_FRAMEWORK_LIFETIMEHELPERS_H_ +#define O2_FRAMEWORK_LIFETIMEHELPERS_H_ #include "Framework/ExpirationHandler.h" #include "Framework/PartRef.h" @@ -17,9 +17,7 @@ #include <functional> #include <string> -namespace o2 -{ -namespace framework +namespace o2::framework { struct ConcreteDataMatcher; @@ -33,6 +31,7 @@ struct LifetimeHelpers { /// Callback which creates a new timeslice as soon as one is available and /// uses an incremental number as timestamp. static ExpirationHandler::Creator enumDrivenCreation(size_t first, size_t last, size_t step, size_t inputTimeslice, size_t maxTimeSliceId); + /// Callback which creates a new timeslice when timer /// expires and there is not a compatible datadriven callback /// available. @@ -78,9 +77,12 @@ struct LifetimeHelpers { /// The payload of each message will contain an incremental number for each /// message being created. static ExpirationHandler::Handler enumerate(ConcreteDataMatcher const& spec, std::string const& sourceChannel); + + /// Create a dummy (empty) message every time a record expires, suing @a spec + /// as content of the payload. + static ExpirationHandler::Handler dummy(ConcreteDataMatcher const& spec, std::string const& sourceChannel); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif // FRAMEWORK_LIFETIMEHELPERS_H +#endif // O2_FRAMEWORK_LIFETIMEHELPERS_H_ diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index a5d7ec81952fe..059837f602409 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -209,6 +209,31 @@ struct ExpirationHandlerHelpers { { return [](DeviceState&, ConfigParamRegistry const&) { return LifetimeHelpers::fetchFromObjectRegistry(); }; } + + /// This behaves as data. I.e. we never create it unless data arrives. + static RouteConfigurator::CreationConfigurator createOptionalConfigurator() + { + return [](DeviceState&, ConfigParamRegistry const&) { return LifetimeHelpers::dataDrivenCreation(); }; + } + + /// This will always exipire an optional record when no data is received. + static RouteConfigurator::DanglingConfigurator danglingOptionalConfigurator() + { + return [](DeviceState&, ConfigParamRegistry const&) { return LifetimeHelpers::expireAlways(); }; + } + + /// When the record expires, simply create a dummy entry. + static RouteConfigurator::ExpirationConfigurator expiringOptionalConfigurator(InputSpec const& spec, std::string const& sourceChannel) + { + auto m = std::get_if<ConcreteDataMatcher>(&spec.matcher); + if (m == nullptr) { + throw runtime_error("InputSpec for Enumeration must be fully qualified"); + } + // We copy the matcher to avoid lifetime issues. + return [matcher = *m, sourceChannel](DeviceState&, ConfigParamRegistry const&) { + return LifetimeHelpers::dummy(matcher, sourceChannel); + }; + } }; /// This creates a string to configure channels of a FairMQDevice @@ -638,6 +663,12 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices, ExpirationHandlerHelpers::danglingTransientConfigurator(), ExpirationHandlerHelpers::expiringTransientConfigurator(inputSpec)}; break; + case Lifetime::Optional: + route.configurator = { + ExpirationHandlerHelpers::createOptionalConfigurator(), + ExpirationHandlerHelpers::danglingOptionalConfigurator(), + ExpirationHandlerHelpers::expiringOptionalConfigurator(inputSpec, sourceChannel)}; + break; default: break; } diff --git a/Framework/Core/src/LifetimeHelpers.cxx b/Framework/Core/src/LifetimeHelpers.cxx index 3bd1b26d390ee..7c9180a61de0e 100644 --- a/Framework/Core/src/LifetimeHelpers.cxx +++ b/Framework/Core/src/LifetimeHelpers.cxx @@ -28,9 +28,7 @@ using namespace o2::header; using namespace fair; -namespace o2 -{ -namespace framework +namespace o2::framework { namespace @@ -303,5 +301,34 @@ ExpirationHandler::Handler LifetimeHelpers::enumerate(ConcreteDataMatcher const& return f; } -} // namespace framework -} // namespace o2 +/// Create a dummy message with the provided ConcreteDataMatcher +ExpirationHandler::Handler LifetimeHelpers::dummy(ConcreteDataMatcher const& matcher, std::string const& sourceChannel) +{ + using counter_t = int64_t; + auto counter = std::make_shared<counter_t>(0); + auto f = [matcher, counter, sourceChannel](ServiceRegistry& services, PartRef& ref, uint64_t timestamp) -> void { + // We should invoke the handler only once. + assert(!ref.header); + assert(!ref.payload); + auto& rawDeviceService = services.get<RawDeviceService>(); + + DataHeader dh; + dh.dataOrigin = matcher.origin; + dh.dataDescription = matcher.description; + dh.subSpecification = matcher.subSpec; + dh.payloadSize = 0; + dh.payloadSerializationMethod = gSerializationMethodNone; + + DataProcessingHeader dph{timestamp, 1}; + + auto&& transport = rawDeviceService.device()->GetChannel(sourceChannel, 0).Transport(); + auto channelAlloc = o2::pmr::getTransportAllocator(transport); + auto header = o2::pmr::getMessage(o2::header::Stack{channelAlloc, dh, dph}); + ref.header = std::move(header); + auto payload = rawDeviceService.device()->NewMessage(0); + ref.payload = std::move(payload); + }; + return f; +} + +} // namespace o2::framework diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 9ace1c786f61f..fce333dd5171d 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -323,6 +323,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext case Lifetime::QA: case Lifetime::Transient: case Lifetime::Timeframe: + case Lifetime::Optional: break; } if (DataSpecUtils::partialMatch(input, header::DataOrigin{"AOD"})) { From 45be73c66d1231f7be67a9695f738e0ec3195efa Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Sat, 21 Nov 2020 22:22:57 +0100 Subject: [PATCH 1394/1751] CcdbApi improvements * fix memory bug occurring on MacOS BigSur + Ubuntu * optimization of location search loop * use new better alien-token-info (no timeout needed anymore) --- CCDB/src/CcdbApi.cxx | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index d6f6c270e41c2..428994666408f 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -659,7 +659,7 @@ bool CcdbApi::checkAlienToken() const if (getenv("JALIEN_TOKEN_CERT")) { return true; } - auto returncode = system("timeout 1s timeout 1s alien-token-info &> /dev/null"); + auto returncode = system("alien-token-info > /dev/null 2> /dev/null"); return returncode == 0; } @@ -757,20 +757,30 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con else if (300 <= response_code && response_code < 400) { // we try content locations in order of appearance until one succeeds // 1st: The "Location" field - // 2nd: Possible "Content-Location" fields - auto tryLocations = [this, &curl_handle, &content, cl](auto range) { + // 2nd: Possible "Content-Location" fields - Location field + std::vector<std::string> locs; + auto iter = mHeaderData.find("Location"); + if (iter != mHeaderData.end()) { + locs.push_back(iter->second); + } + // add alternative locations (not yet included) + auto iter2 = mHeaderData.find("Content-Location"); + if (iter2 != mHeaderData.end()) { + auto range = mHeaderData.equal_range("Content-Location"); for (auto it = range.first; it != range.second; ++it) { - auto nextlocation = it->second; - LOG(DEBUG) << "Trying content location " << nextlocation; - content = navigateURLsAndRetrieveContent(curl_handle, nextlocation, cl, nullptr); + if (std::find(locs.begin(), locs.end(), it->second) == locs.end()) { + locs.push_back(it->second); + } + } + } + for (auto& l : locs) { + if (l.size() > 0) { + LOG(DEBUG) << "Trying content location " << l; + content = navigateURLsAndRetrieveContent(curl_handle, l, cl, nullptr); if (content /* or other success marker in future */) { break; } } - }; - tryLocations(mHeaderData.equal_range("Location")); - if (content == nullptr) { - tryLocations(mHeaderData.equal_range("Content-Location")); } } else if (response_code == 404) { LOG(ERROR) << "Requested resource does not exist"; From 859c35c5313efe6bf6ec40ad24acccb73bde3468 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 22 Nov 2020 16:44:53 +0100 Subject: [PATCH 1395/1751] DPL: fix DDS config generation with empty --channel-prefix (#4887) --- Framework/Core/src/DDSConfigHelpers.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Framework/Core/src/DDSConfigHelpers.cxx b/Framework/Core/src/DDSConfigHelpers.cxx index d2d76ccbd7a6a..83e6d36edfdc9 100644 --- a/Framework/Core/src/DDSConfigHelpers.cxx +++ b/Framework/Core/src/DDSConfigHelpers.cxx @@ -46,6 +46,13 @@ void dumpDeviceSpec2DDS(std::ostream& out, ai++; continue; } + // If channel-prefix is empty do not print it out + if (strcmp(arg, "--channel-prefix") == 0 && + ai + 1 < execution.args.size() && + *execution.args[ai + 1] == 0) { + ai++; + continue; + } out << arg << " "; } out << "--plugin-search-path $FAIRMQ_ROOT/lib --plugin dds"; From 20e3e5b6d23a825f7a52550049687b6feee591e7 Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Sun, 22 Nov 2020 17:18:33 -0300 Subject: [PATCH 1396/1751] Casc producer now able to filter (#4888) --- Analysis/Tasks/PWGLF/cascadefinder.cxx | 7 + Analysis/Tasks/PWGLF/cascadeproducer.cxx | 127 ++++++++++++++++--- Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 8 ++ 3 files changed, 124 insertions(+), 18 deletions(-) diff --git a/Analysis/Tasks/PWGLF/cascadefinder.cxx b/Analysis/Tasks/PWGLF/cascadefinder.cxx index 224e5ef253c0c..4ee368dc41d15 100644 --- a/Analysis/Tasks/PWGLF/cascadefinder.cxx +++ b/Analysis/Tasks/PWGLF/cascadefinder.cxx @@ -97,6 +97,7 @@ struct cascadeprefilter { Configurable<int> mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; Configurable<float> dcav0topv{"dcav0topv", .1, "DCA V0 To PV"}; Configurable<double> cospaV0{"cospaV0", .98, "CosPA V0"}; + Configurable<double> v0radius{"v0radius", 0.9, "v0radius"}; Configurable<float> lambdamasswindow{"lambdamasswindow", .006, "Distance from Lambda mass"}; Configurable<float> dcav0dau{"dcav0dau", .6, "DCA V0 Daughters"}; Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; @@ -143,6 +144,12 @@ struct cascadeprefilter { if (v0.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < dcav0topv) { continue; } + if (v0.dcaV0daughters() > dcav0dau) { + continue; + } + if (v0.v0radius() < v0radius) { + continue; + } if (fabs(v0.mLambda() - 1.116) < lambdamasswindow) { cascGoodLambdas(v0.globalIndex(), v0.collisionId()); diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx index 4fdb3fff6251e..8cf1076b778a4 100644 --- a/Analysis/Tasks/PWGLF/cascadeproducer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -17,6 +17,14 @@ // Any analysis should loop over the "CascData" // table as that table contains all information // +// WARNING: adding filters to the producer IS NOT +// equivalent to re-running the finders. This will only +// ever produce *tighter* selection sections. It is your +// responsibility to check if, by setting a loose filter +// setting, you are going into a region in which no +// candidates exist because the original indices were generated +// using tigher selections. +// // Comments, questions, complaints, suggestions? // Please write to: // david.dobrigkeit.chinellato@cern.ch @@ -31,6 +39,8 @@ #include "ReconstructionDataFormats/Track.h" #include "Analysis/RecoDecay.h" #include "Analysis/trackUtilities.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" #include "Analysis/StrangenessTables.h" #include <TFile.h> @@ -51,6 +61,94 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +namespace o2::aod +{ + +namespace cascgood +{ +DECLARE_SOA_INDEX_COLUMN_FULL(V0, v0, int, V0DataExt, "fV0Id"); +DECLARE_SOA_INDEX_COLUMN_FULL(Bachelor, bachelor, int, FullTracks, "fTracksID"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +} // namespace cascgood +DECLARE_SOA_TABLE(CascGood, "AOD", "CASCGOOD", o2::soa::Index<>, + cascgood::V0Id, cascgood::BachelorId, + cascgood::CollisionId); +} // namespace o2::aod + +using FullTracksExt = soa::Join<aod::FullTracks, aod::TracksExtended>; + +//This prefilter creates a skimmed list of good V0s to re-reconstruct so that +//CPU is saved in case there are specific selections that are to be done +//Note: more configurables, more options to be added as needed +struct cascadeprefilterpairs { + Configurable<int> mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + Configurable<float> dcav0topv{"dcav0topv", .1, "DCA V0 To PV"}; + Configurable<double> cospaV0{"cospaV0", .98, "CosPA V0"}; + Configurable<float> lambdamasswindow{"lambdamasswindow", .006, "Distance from Lambda mass"}; + Configurable<float> dcav0dau{"dcav0dau", .6, "DCA V0 Daughters"}; + Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + Configurable<float> dcabachtopv{"dcabachtopv", .1, "DCA Bach To PV"}; + Configurable<bool> tpcrefit{"tpcrefit", 1, "demand TPC refit"}; + Configurable<double> v0radius{"v0radius", 0.9, "v0radius"}; + + Produces<aod::CascGood> cascgood; + void process(aod::Collision const& collision, aod::V0DataExt const& V0s, aod::Cascades const& Cascades, + soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) + { + for (auto& casc : Cascades) { + //Single-track properties filter + if (tpcrefit) { + if (!(casc.v0().posTrack().flags() & 0x40)) { + continue; //TPC refit + } + if (!(casc.v0().negTrack().flags() & 0x40)) { + continue; //TPC refit + } + if (!(casc.bachelor().flags() & 0x40)) { + continue; //TPC refit + } + } + if (casc.v0().posTrack().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + if (casc.v0().negTrack().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + if (casc.bachelor().tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + if (casc.v0().posTrack_as<FullTracksExt>().dcaXY() < dcapostopv) { + continue; + } + if (casc.v0().negTrack_as<FullTracksExt>().dcaXY() < dcanegtopv) { + continue; + } + if (casc.bachelor_as<FullTracksExt>().dcaXY() < dcabachtopv) { + continue; + } + + //V0 selections + if (fabs(casc.v0_as<o2::aod::V0DataExt>().mLambda() - 1.116) > lambdamasswindow && fabs(casc.v0_as<o2::aod::V0DataExt>().mAntiLambda() - 1.116) > lambdamasswindow) { + continue; + } + if (casc.v0_as<o2::aod::V0DataExt>().dcaV0daughters() > dcav0dau) { + continue; + } + if (casc.v0_as<o2::aod::V0DataExt>().v0radius() < v0radius) { + continue; + } + if (casc.v0_as<o2::aod::V0DataExt>().v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cospaV0) { + continue; + } + if (casc.v0_as<o2::aod::V0DataExt>().dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < dcav0topv) { + continue; + } + cascgood(casc.v0().globalIndex(), casc.bachelor().globalIndex(), casc.bachelor().collisionId()); + } + } +}; + /// Cascade builder task: rebuilds cascades struct cascadeproducer { Produces<aod::CascData> cascdata; @@ -62,21 +160,7 @@ struct cascadeproducer { Configurable<double> d_bz{"d_bz", -5.0, "bz field"}; Configurable<double> d_UseAbsDCA{"d_UseAbsDCA", kTRUE, "Use Abs DCAs"}; - /// Extracts dca in the XY plane - /// \return dcaXY - template <typename T, typename U> - auto getdcaXY(const T& track, const U& coll) - { - //Calculate DCAs - auto sinAlpha = sin(track.alpha()); - auto cosAlpha = cos(track.alpha()); - auto globalX = track.x() * cosAlpha - track.y() * sinAlpha; - auto globalY = track.x() * sinAlpha + track.y() * cosAlpha; - return sqrt(pow((globalX - coll[0]), 2) + - pow((globalY - coll[1]), 2)); - } - - void process(aod::Collision const& collision, aod::V0s const& V0s, aod::Cascades const& Cascades, aod::FullTracks const& trackss) + void process(aod::Collision const& collision, aod::V0DataExt const& V0s, aod::CascGood const& Cascades, aod::FullTracks const& tracks) { //Define o2 fitter, 2-prong o2::vertexing::DCAFitterN<2> fitterV0, fitterCasc; @@ -173,15 +257,22 @@ struct cascadeproducer { pvecneg[0], pvecneg[1], pvecneg[2], pvecbach[0], pvecbach[1], pvecbach[2], fitterV0.getChi2AtPCACandidate(), fitterCasc.getChi2AtPCACandidate(), - getdcaXY(casc.v0().posTrack(), pVtx), - getdcaXY(casc.v0().negTrack(), pVtx), - getdcaXY(casc.bachelor(), pVtx)); + casc.v0().posTrack_as<FullTracksExt>().dcaXY(), + casc.v0().negTrack_as<FullTracksExt>().dcaXY(), + casc.bachelor_as<FullTracksExt>().dcaXY()); } } }; +/// Extends the v0data table with expression columns +struct cascprodinitializer { + Spawns<aod::V0DataExt> v0dataext; + void init(InitContext const&) {} +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ + adaptAnalysisTask<cascprodinitializer>("lf-cascprodinitializer"), adaptAnalysisTask<cascadeproducer>("lf-cascadeproducer")}; } diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index 349ac70069117..b3b330ff366dc 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -17,6 +17,14 @@ // Any analysis should loop over the "V0Data" // table as that table contains all information // +// WARNING: adding filters to the producer IS NOT +// equivalent to re-running the finders. This will only +// ever produce *tighter* selection sections. It is your +// responsibility to check if, by setting a loose filter +// setting, you are going into a region in which no +// candidates exist because the original indices were generated +// using tigher selections. +// // Comments, questions, complaints, suggestions? // Please write to: // david.dobrigkeit.chinellato@cern.ch From f47c6ea038d43fdcb0037509a8da13c6e1ebbf90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Sun, 22 Nov 2020 21:18:59 +0100 Subject: [PATCH 1397/1751] Add histogram on vertex covariance matrix (#4883) --- Analysis/Tasks/PWGHF/qaTask.cxx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Analysis/Tasks/PWGHF/qaTask.cxx b/Analysis/Tasks/PWGHF/qaTask.cxx index b819dcacd6118..a65c1da80e821 100644 --- a/Analysis/Tasks/PWGHF/qaTask.cxx +++ b/Analysis/Tasks/PWGHF/qaTask.cxx @@ -26,6 +26,7 @@ #include <sstream> #include "boost/algorithm/string.hpp" +using namespace o2::framework; namespace o2fw = o2::framework; namespace o2exp = o2::framework::expressions; namespace o2df = o2::dataformats; @@ -183,6 +184,18 @@ struct QAGlobalObservables { histograms.add("multiplicity/numberOfTracks", qafeat::MakeTitle({qafeat::TrackMultiplicity}).c_str(), o2fw::kTH1D, {{nBinsNumberOfTracks, numberOfTracksRange[0], numberOfTracksRange[1]}}); + + // covariance histograms + histograms.add("Covariance/xx", "xx;Cov_{xx} [cm]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/xy", "xy;Cov_{xy} [cm]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/xz", "xz;Cov_{xz} [cm]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/yy", "yy;Cov_{yy} [cm]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/yz", "yz;Cov_{yz} [cm]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/zz", "zz;Cov_{zz} [cm]", kTH1D, {{200, -0.1, 0.1}}); + + // quality histograms + histograms.add("Quality/Chi2", "#Chi^{2};#Chi^{2}", kTH1D, {{100, 0, 10}}); + histograms.add("Quality/Contributors", "Contributors;Contributors", kTH1D, {{100, 0, 100}}); } void process(const o2::aod::Collision& collision, const o2::aod::Tracks& tracks) @@ -198,6 +211,18 @@ struct QAGlobalObservables { } histograms.fill("multiplicity/numberOfTracks", nTracks); + + // fill covariance variables + histograms.fill("Covariance/xx", collision.covXX()); + histograms.fill("Covariance/xy", collision.covXY()); + histograms.fill("Covariance/xz", collision.covXZ()); + histograms.fill("Covariance/yy", collision.covYY()); + histograms.fill("Covariance/yz", collision.covYZ()); + histograms.fill("Covariance/zz", collision.covZZ()); + + // fill quality variables + histograms.fill("Quality/Chi2", collision.chi2()); + histograms.fill("Quality/Contributors", collision.numContrib()); } }; From 807d607a9bff7f638c87cddf705b36a46e431be9 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 20 Nov 2020 17:49:37 +0100 Subject: [PATCH 1398/1751] MCKinematicsReader: API to fetch TrackReferences --- Steer/include/Steer/MCKinematicsReader.h | 22 ++++++++++++++++++++++ Steer/src/MCKinematicsReader.cxx | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/Steer/include/Steer/MCKinematicsReader.h b/Steer/include/Steer/MCKinematicsReader.h index f73497fbff6f6..2a6cacea6a73b 100644 --- a/Steer/include/Steer/MCKinematicsReader.h +++ b/Steer/include/Steer/MCKinematicsReader.h @@ -12,6 +12,8 @@ #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCEventHeader.h" +#include "SimulationDataFormat/TrackReference.h" +#include "SimulationDataFormat/MCTruthContainer.h" #include <vector> class TChain; @@ -79,6 +81,11 @@ class MCKinematicsReader /// get all mothers/daughters of the given label + /// return all track references associated to a source/event/track + gsl::span<o2::TrackReference> getTrackRefs(int source, int event, int track) const; + /// return all track references associated to a event/track (when initialized from kinematics directly) + gsl::span<o2::TrackReference> getTrackRefs(int event, int track) const; + /// retrieves the MCEventHeader for a given eventID and sourceID o2::dataformats::MCEventHeader const& getMCEventHeader(int source, int event) const; @@ -90,6 +97,7 @@ class MCKinematicsReader private: void loadTracksForSource(int source) const; void loadHeadersForSource(int source) const; + void loadTrackRefsForSource(int source) const; DigitizationContext const* mDigitizationContext = nullptr; @@ -99,6 +107,7 @@ class MCKinematicsReader // a vector of tracks foreach source and each collision mutable std::vector<std::vector<std::vector<o2::MCTrack>>> mTracks; // the in-memory track container mutable std::vector<std::vector<o2::dataformats::MCEventHeader>> mHeaders; // the in-memory header container + mutable std::vector<std::vector<o2::dataformats::MCTruthContainer<o2::TrackReference>>> mTrackRefs; // the in-memory track ref container bool mInitialized = false; // whether initialized }; @@ -145,5 +154,18 @@ inline o2::dataformats::MCEventHeader const& MCKinematicsReader::getMCEventHeade return mHeaders.at(source)[event]; } +inline gsl::span<o2::TrackReference> MCKinematicsReader::getTrackRefs(int source, int event, int track) const +{ + if (mTrackRefs[source].size() == 0) { + loadTrackRefsForSource(source); + } + return mTrackRefs[source][event].getLabels(track); +} + +inline gsl::span<o2::TrackReference> MCKinematicsReader::getTrackRefs(int event, int track) const +{ + return getTrackRefs(0, event, track); +} + } // namespace steer } // namespace o2 diff --git a/Steer/src/MCKinematicsReader.cxx b/Steer/src/MCKinematicsReader.cxx index a77089db29172..f75289f367521 100644 --- a/Steer/src/MCKinematicsReader.cxx +++ b/Steer/src/MCKinematicsReader.cxx @@ -56,6 +56,26 @@ void MCKinematicsReader::loadHeadersForSource(int source) const } } +void MCKinematicsReader::loadTrackRefsForSource(int source) const +{ + auto chain = mInputChains[source]; + if (chain) { + // todo: get name from NameConfig + auto br = chain->GetBranch("IndexedTrackRefs"); + if (br) { + o2::dataformats::MCTruthContainer<o2::TrackReference>* refs = nullptr; + br->SetAddress(&refs); + mTrackRefs[source].resize(br->GetEntries()); + for (int event = 0; event < br->GetEntries(); ++event) { + br->GetEntry(event); + mTrackRefs[source][event] = *refs; + } + } else { + LOG(WARN) << "IndexedTrackRefs branch not found"; + } + } +} + bool MCKinematicsReader::initFromDigitContext(std::string_view name) { if (mInitialized) { @@ -76,6 +96,7 @@ bool MCKinematicsReader::initFromDigitContext(std::string_view name) // load the kinematics information mTracks.resize(mInputChains.size()); mHeaders.resize(mInputChains.size()); + mTrackRefs.resize(mInputChains.size()); // actual loading will be done only if someone asks // the first time for a particular source ... @@ -93,6 +114,7 @@ bool MCKinematicsReader::initFromKinematics(std::string_view name) mInputChains.back()->AddFile(o2::base::NameConf::getMCKinematicsFileName(name.data()).c_str()); mTracks.resize(1); mHeaders.resize(1); + mTrackRefs.resize(1); mInitialized = true; return true; From 35c28fe78fbec20d703b67bb2670b8cf0181c82b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 23 Nov 2020 13:04:22 +0100 Subject: [PATCH 1399/1751] DPL: report metrics by device id, not device role (#4896) --- Framework/Core/src/ResourcesMonitoringHelper.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/ResourcesMonitoringHelper.cxx b/Framework/Core/src/ResourcesMonitoringHelper.cxx index 495a655867041..8aa1600d2eac9 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.cxx +++ b/Framework/Core/src/ResourcesMonitoringHelper.cxx @@ -74,7 +74,7 @@ bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetric deviceRoot.add_child(metricLabel.label, metricNode); } - root.add_child(specs[idx].name, deviceRoot); + root.add_child(specs[idx].id, deviceRoot); } boost::property_tree::ptree driverRoot; From 7a1d030e56a72555c4c245cf7766899b26b762dc Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 23 Nov 2020 13:04:54 +0100 Subject: [PATCH 1400/1751] DPL: drop check of InputSpec.h in dictionaries until we understand what it going on. (#4894) --- Framework/Core/test/TestClasses.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Framework/Core/test/TestClasses.h b/Framework/Core/test/TestClasses.h index 1d6700b72fca3..992499ae586a8 100644 --- a/Framework/Core/test/TestClasses.h +++ b/Framework/Core/test/TestClasses.h @@ -11,7 +11,6 @@ #define O2_FRAMEWORK_TEST_CLASSES_H_ #include <Rtypes.h> -#include "Framework/InputSpec.h" #include "Framework/OutputSpec.h" namespace o2::test From 76ae79e5ea8c1edb8df2ef41c6d5e2b52475bb34 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 23 Nov 2020 10:50:17 +0100 Subject: [PATCH 1401/1751] Add getter to return full underlying truth array --- .../include/SimulationDataFormat/MCTruthContainer.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h index cf39f7aa3a8e8..506f24b56897a 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h @@ -140,6 +140,11 @@ class MCTruthContainer size_t getIndexedSize() const { return mHeaderArray.size(); } // return the number of elements managed in this container size_t getNElements() const { return mTruthArray.size(); } + // return unterlaying vector of elements + const std::vector<TruthElement>& getTruthArray() const + { + return mTruthArray; + } // get individual "view" container for a given data index // the caller can do modifications on this view (such as sorting) From 702ba8e61f7e605dbab731c49e73084c6ad878a2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 23 Nov 2020 10:50:31 +0100 Subject: [PATCH 1402/1751] Add some additional getters to MCKinematicsReader --- Steer/include/Steer/MCKinematicsReader.h | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Steer/include/Steer/MCKinematicsReader.h b/Steer/include/Steer/MCKinematicsReader.h index 2a6cacea6a73b..8b6bc1cb63cb3 100644 --- a/Steer/include/Steer/MCKinematicsReader.h +++ b/Steer/include/Steer/MCKinematicsReader.h @@ -83,12 +83,20 @@ class MCKinematicsReader /// return all track references associated to a source/event/track gsl::span<o2::TrackReference> getTrackRefs(int source, int event, int track) const; + /// return all track references associated to a source/event + const std::vector<o2::TrackReference>& getTrackRefsByEvent(int source, int event) const; /// return all track references associated to a event/track (when initialized from kinematics directly) gsl::span<o2::TrackReference> getTrackRefs(int event, int track) const; /// retrieves the MCEventHeader for a given eventID and sourceID o2::dataformats::MCEventHeader const& getMCEventHeader(int source, int event) const; + /// Get number of sources + size_t getNSources() const; + + /// Get number of events + size_t getNEvents(int source) const; + DigitizationContext const* getDigitizationContext() const { return mDigitizationContext; @@ -162,10 +170,31 @@ inline gsl::span<o2::TrackReference> MCKinematicsReader::getTrackRefs(int source return mTrackRefs[source][event].getLabels(track); } +inline const std::vector<o2::TrackReference>& MCKinematicsReader::getTrackRefsByEvent(int source, int event) const +{ + if (mTrackRefs[source].size() == 0) { + loadTrackRefsForSource(source); + } + return mTrackRefs[source][event].getTruthArray(); +} + inline gsl::span<o2::TrackReference> MCKinematicsReader::getTrackRefs(int event, int track) const { return getTrackRefs(0, event, track); } +inline size_t MCKinematicsReader::getNSources() const +{ + return mTracks.size(); +} + +inline size_t MCKinematicsReader::getNEvents(int source) const +{ + if (mTracks[source].size() == 0) { + loadTracksForSource(source); + } + return mTracks[source].size(); +} + } // namespace steer } // namespace o2 From 3875102d1da0952a1ecc8b606ef69dcdcbc60ee4 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 23 Nov 2020 10:04:34 +0100 Subject: [PATCH 1403/1751] GPU: Set correct ASM language for assembler files during GPU compilation --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 5 +++-- GPU/GPUTracking/Base/opencl/CMakeLists.txt | 3 ++- GPU/GPUTracking/Base/opencl2/CMakeLists.txt | 7 ++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index dae17401295c2..8ec7ef7ce6b87 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -20,6 +20,7 @@ set(HDRS GPUReconstructionCUDA.h GPUReconstructionCUDAInternals.h GPUReconstruct # -------------------------------- Prepare RTC ------------------------------------------------------- if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") + enable_language(ASM) if(ALIGPU_BUILD_TYPE STREQUAL "O2") set(defineIncludeSrc "O2::${MODULE}") else() @@ -92,7 +93,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") ${CURTC_BIN}.src.S PROPERTIES LANGUAGE - CXX + ASM OBJECT_DEPENDS "${CURTC_BIN}.src;${GPUDIR}/Standalone/makefiles/include.S") @@ -100,7 +101,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") ${CURTC_BIN}.command.S PROPERTIES LANGUAGE - CXX + ASM ) set(SRCS ${SRCS} ${CURTC_BIN}.src.S ${CURTC_BIN}.command.S) diff --git a/GPU/GPUTracking/Base/opencl/CMakeLists.txt b/GPU/GPUTracking/Base/opencl/CMakeLists.txt index 85cfa1577f15f..342aa4d3527ce 100644 --- a/GPU/GPUTracking/Base/opencl/CMakeLists.txt +++ b/GPU/GPUTracking/Base/opencl/CMakeLists.txt @@ -9,6 +9,7 @@ # submit itself to any jurisdiction. set(MODULE GPUTrackingOCL) +enable_language(ASM) # AMD APP SDK required for OpenCL tracker as it's using specific extensions # (currently) not provided by other vendors @@ -78,7 +79,7 @@ set_source_files_properties( ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionOCLCode.S PROPERTIES LANGUAGE - CXX + ASM OBJECT_DEPENDS "${CL_BIN};${GPUDIR}/Standalone/makefiles/include.S") diff --git a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt index df3dc5eb959d4..da8f89a2113e2 100644 --- a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt +++ b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt @@ -9,6 +9,7 @@ # submit itself to any jurisdiction. set(MODULE GPUTrackingOCL2) +enable_language(ASM) if(DEFINED OCL2_GPUTARGET) set(TMP_TARGET "(AMDGPU Target ${OCL2_GPUTARGET})") @@ -68,7 +69,7 @@ if(OPENCL2_ENABLED_AMD) # BUILD OpenCL2 binaries for AMD target ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionOCLCode.amd.S PROPERTIES LANGUAGE - CXX + ASM OBJECT_DEPENDS "${CL_BIN}.amd;${GPUDIR}/Standalone/makefiles/include.S") @@ -108,7 +109,7 @@ if(OPENCL2_ENABLED_SPIRV) # BUILD OpenCL2 intermediate code for SPIR-V target ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionOCLCode.spirv.S PROPERTIES LANGUAGE - CXX + ASM OBJECT_DEPENDS "${CL_BIN}.spirv;${GPUDIR}/Standalone/makefiles/include.S") @@ -140,7 +141,7 @@ if(OPENCL2_ENABLED) # BUILD OpenCL2 source code for runtime compilation target ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionOCLCode.src.S PROPERTIES LANGUAGE - CXX + ASM OBJECT_DEPENDS "${CL_BIN}.src;${GPUDIR}/Standalone/makefiles/include.S") From f3ad61b2d4ac888f9cd4b737c09a7de6108fff58 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 23 Nov 2020 15:34:14 +0100 Subject: [PATCH 1404/1751] Taskwrapper: Timeout handling + other improvements * allow to specify timeout per task * allow to specify additional log files to supervise/check for failure indication --- Utilities/Tools/jobutils.sh | 51 ++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index 5905fb7dc6adc..00aca143530c5 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -59,17 +59,23 @@ childprocs() { fi } +taskwrapper_cleanup() { + MOTHERPID=$1 + SIGNAL=${2:-SIGTERM} + for p in $(childprocs ${MOTHERPID}); do + echo "killing child $p" + kill -s ${SIGNAL} $p 2> /dev/null + done + sleep 2 + # remove leftover shm files + o2_cleanup_shm_files +} + taskwrapper_cleanup_handler() { PID=$1 SIGNAL=$2 echo "CLEANUP HANDLER FOR PROCESS ${PID} AND SIGNAL ${SIGNAL}" - PROCS=$(childprocs ${PID}) - # make sure to bring down everything, including all kids - for p in ${PROCS}; do - echo "killing ${p}" - kill -s ${SIGNAL} ${p} 2> /dev/null - done - o2_cleanup_shm_files + taskwrapper_cleanup ${PID} ${SIGNAL} # I prefer to exit the current job completely exit 1 } @@ -90,6 +96,8 @@ taskwrapper() { shift 1 local command="$*" + STARTTIME=$SECONDS + # launch the actual command in the background echo "Launching task: ${command} &> $logfile &" # the command might be a complex block: For the timing measurement below @@ -159,10 +167,10 @@ taskwrapper() { -e \"Assertion.*failed\" \ -e \"There was a crash.\"" - grepcommand="grep -H ${pattern} $logfile >> encountered_exceptions_list 2>/dev/null" + grepcommand="grep -H ${pattern} $logfile ${JOBUTILS_JOB_SUPERVISEDFILES} >> encountered_exceptions_list 2>/dev/null" eval ${grepcommand} - grepcommand="grep -h --count ${pattern} $logfile 2>/dev/null" + grepcommand="grep -h --count ${pattern} $logfile ${JOBUTILS_JOB_SUPERVISEDFILES} 2>/dev/null" # using eval here since otherwise the pattern is translated to a # a weirdly quoted stringlist RC=$(eval ${grepcommand}) @@ -183,15 +191,7 @@ taskwrapper() { sleep 2 - # query processes still alive and terminate them - for p in $(childprocs ${PID}); do - echo "killing child $p" - kill -9 $p 2> /dev/null - done - sleep 2 - - # remove leftover shm files - o2_cleanup_shm_files + taskwrapper_cleanup ${PID} SIGKILL RC_ACUM=$((RC_ACUM+1)) [ ! "${JOBUTILS_KEEPJOBSCRIPT}" ] && rm ${SCRIPTNAME} 2> /dev/null @@ -214,6 +214,21 @@ taskwrapper() { let cpucounter=cpucounter+1 fi + # a good moment to check for jobs timeout (or other resources) + if [ "$JOBUTILS_JOB_TIMEOUT" ]; then + $(awk -v S="${SECONDS}" -v T="${JOBUTILS_JOB_TIMEOUT}" -v START="${STARTTIME}" '//{} END{if((S-START)>T){exit 1;} exit 0;}' < /dev/null) + if [ "$?" = "1" ]; then + echo "task timeout reached .. killing all processes"; + taskwrapper_cleanup $PID SIGKILL + # call a more specialized hook for this?? + if [ "${JOBUTILS_JOB_FAILUREHOOK}" ]; then + hook="${JOBUTILS_JOB_FAILUREHOOK} '$command' $logfile" + eval "${hook}" + fi + return 1 + fi + fi + # sleep for some time (can be customized for power user) sleep ${JOBUTILS_WRAPPER_SLEEP:-5} done From aec3bf51e261ba02714f05ac3d9fa905fe32349c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 23 Nov 2020 11:18:18 +0100 Subject: [PATCH 1405/1751] AlpideCoder: skip chips with all hits masked as noise --- .../include/ITSMFTReconstruction/AlpideCoder.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h index 6a11db0fa8e1a..57de757a01253 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h @@ -192,6 +192,12 @@ class AlpideCoder addHit(chipData, rightColHits[ihr], colDPrev); } } + if (!chipData.getData().size() && !chipData.isErrorSet()) { + nRightCHits = 0; + colDPrev = 0xffff; + chipData.clear(); + continue; + } break; } From 6ec20e5ce98fa84aef9b1fcb3f3bfb35b6b0a9a2 Mon Sep 17 00:00:00 2001 From: Jan Fiete Grosse-Oetringhaus <jgrosseo@cern.ch> Date: Mon, 23 Nov 2020 14:46:02 +0100 Subject: [PATCH 1406/1751] avoid non constexpr string lookups only needed for current version of histogram registry --- Analysis/Tasks/PWGCF/correlations.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index 21ba374fe4870..1986267c1d911 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -176,12 +176,16 @@ struct CorrelationTask { } } + // NOTE remove when HistogramRegistry uses constexpr strings for lookup + auto& yields = registry.get<TH3>("yields"); + auto& etaphi = registry.get<TH3>("etaphi"); + for (auto& track1 : tracks) { // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); - registry.fill("yields", centrality, track1.pt(), track1.eta()); - registry.fill("etaphi", centrality, track1.eta(), track1.phi()); + yields->Fill(centrality, track1.pt(), track1.eta()); + etaphi->Fill(centrality, track1.eta(), track1.phi()); if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; From 17cc9cf372bbff5bcf06e297e9cac62fe7a09aa5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 23 Nov 2020 13:50:18 +0100 Subject: [PATCH 1407/1751] DPL: allow Lifetime::Optional to work with ORIGIN/DESCRIPTION --- Framework/Core/src/DeviceSpecHelpers.cxx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 059837f602409..56c1b8cefb743 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -225,14 +225,19 @@ struct ExpirationHandlerHelpers { /// When the record expires, simply create a dummy entry. static RouteConfigurator::ExpirationConfigurator expiringOptionalConfigurator(InputSpec const& spec, std::string const& sourceChannel) { - auto m = std::get_if<ConcreteDataMatcher>(&spec.matcher); - if (m == nullptr) { - throw runtime_error("InputSpec for Enumeration must be fully qualified"); + try { + ConcreteDataMatcher concrete = DataSpecUtils::asConcreteDataMatcher(spec); + return [concrete, sourceChannel](DeviceState&, ConfigParamRegistry const&) { + return LifetimeHelpers::dummy(concrete, sourceChannel); + }; + } catch (...) { + ConcreteDataTypeMatcher dataType = DataSpecUtils::asConcreteDataTypeMatcher(spec); + ConcreteDataMatcher concrete{dataType.origin, dataType.description, 0xdeadbeef}; + return [concrete, sourceChannel](DeviceState&, ConfigParamRegistry const&) { + return LifetimeHelpers::dummy(concrete, sourceChannel); + }; } // We copy the matcher to avoid lifetime issues. - return [matcher = *m, sourceChannel](DeviceState&, ConfigParamRegistry const&) { - return LifetimeHelpers::dummy(matcher, sourceChannel); - }; } }; From 4b52c75126239b8488b10f238bd3c0945009c536 Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Wed, 18 Nov 2020 12:24:20 +0100 Subject: [PATCH 1408/1751] [DCS] Ensure DataPointCompositeObject is trivially copyable and add a getValue free function --- .../DetectorsDCS/DataPointCompositeObject.h | 21 +++++++ .../DCS/src/DataPointCompositeObject.cxx | 58 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h b/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h index fea0bab7dfca0..c2b5f848bb858 100644 --- a/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h +++ b/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h @@ -254,8 +254,29 @@ struct alignas(128) DataPointCompositeObject final { (char*)&dpcom.data.payload_pt1, 56); } } + + /** + * The destructor for DataPointCompositeObject so it is not deleted + * and thus DataPointCompositeObject is trivially copyable + */ + ~DataPointCompositeObject() noexcept = default; ClassDefNV(DataPointCompositeObject, 1); }; + +/** + * Return the value contained in the DataPointCompositeObject, if possible. + * + * @tparam T the expected type of the value + * + * @param dpcom the DataPointCompositeObject the value is extracted from + * + * @returns the value of the data point + * + * @throws if the DeliveryType of the data point is not compatible with T + */ +template <typename T> +T getValue(const DataPointCompositeObject& dpcom); + } // namespace dcs } // namespace o2 diff --git a/Detectors/DCS/src/DataPointCompositeObject.cxx b/Detectors/DCS/src/DataPointCompositeObject.cxx index 93aaa674bb2ef..4ace9a61b62b5 100644 --- a/Detectors/DCS/src/DataPointCompositeObject.cxx +++ b/Detectors/DCS/src/DataPointCompositeObject.cxx @@ -13,3 +13,61 @@ using namespace o2::dcs; ClassImp(DataPointCompositeObject); + +namespace o2::dcs +{ +template<typename T, o2::dcs::DeliveryType dt> +T getValueImpl(const DataPointCompositeObject& dpcom) { +union Converter { + uint64_t raw_data; + T t_value; +}; + if (dpcom.id.get_type() != dt) { + throw std::runtime_error("DPCOM is of unexpected type " + o2::dcs::show(dt)); + } + Converter converter; + converter.raw_data = dpcom.data.payload_pt1; + return converter.t_value; +} + +// only specialize the getValue function for the types we support : +// +// - double +// - uint32_t +// - int32_t +// - char +// - bool + +// template<> +// double getValueImpl<double,DeliveryType::RAW_DOUBLE>(const DataPointCompositeObject&); +// +template<> +double getValue(const DataPointCompositeObject& dpcom) +{ + return getValueImpl<double,DeliveryType::RAW_DOUBLE>(dpcom); +} + +template <> +uint32_t getValue(const DataPointCompositeObject& dpcom) +{ + return getValueImpl<uint32_t,DeliveryType::RAW_UINT>(dpcom); +} + +template <> +int32_t getValue(const DataPointCompositeObject& dpcom) +{ + return getValueImpl<int32_t,DeliveryType::RAW_INT>(dpcom); +} + +template <> +char getValue(const DataPointCompositeObject& dpcom) +{ + return getValueImpl<char,DeliveryType::RAW_CHAR>(dpcom); +} + +template <> +bool getValue(const DataPointCompositeObject& dpcom) +{ + return getValueImpl<bool,DeliveryType::RAW_BOOL>(dpcom); +} +} // namespace o2::dcs From 388d5ce3c5e15071b4b1a61097f317804b307100 Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Wed, 18 Nov 2020 12:27:42 +0100 Subject: [PATCH 1409/1751] [DCS] Make DataPointValue streamable and macOS compatible --- Detectors/DCS/include/DetectorsDCS/DataPointValue.h | 2 +- Detectors/DCS/src/DetectorsDCSLinkDef.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointValue.h b/Detectors/DCS/include/DetectorsDCS/DataPointValue.h index c32c4e04128b8..6bf7f490d3fac 100644 --- a/Detectors/DCS/include/DetectorsDCS/DataPointValue.h +++ b/Detectors/DCS/include/DetectorsDCS/DataPointValue.h @@ -459,7 +459,7 @@ struct alignas(64) DataPointValue final { */ inline std::unique_ptr<std::string> get_timestamp() const noexcept { -#ifdef __linux__ +#if defined(__linux__) || defined(__APPLE__) // time_t should be uint64_t (compatible) on 64-bit Linux platforms: char buffer[17]; std::time_t ts((uint64_t)sec); diff --git a/Detectors/DCS/src/DetectorsDCSLinkDef.h b/Detectors/DCS/src/DetectorsDCSLinkDef.h index 5f53e7757a349..476dde0b3609c 100644 --- a/Detectors/DCS/src/DetectorsDCSLinkDef.h +++ b/Detectors/DCS/src/DetectorsDCSLinkDef.h @@ -15,7 +15,7 @@ #pragma link off all functions; #pragma link C++ struct o2::dcs::DataPointCompositeObject + ; -#pragma link C++ class o2::dcs::DataPointIdentifier + ; +#pragma link C++ struct o2::dcs::DataPointIdentifier + ; #pragma link C++ struct o2::dcs::DataPointValue + ; #pragma link C++ class o2::dcs::DCSProcessor + ; #pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue> + ; From aa9ffbe50ae8de49bc15e7e3e7fc81f601c81a02 Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Wed, 18 Nov 2020 12:28:10 +0100 Subject: [PATCH 1410/1751] [DCS] Add helper functions to generate (random) DCS data points. The main functions are `o2::dcs::generateRandomDataPoints` and `o2::dcs::expandAliases`, the latter being used to create easily large lists of data point aliases from basic patterns. For instance the compact description "DET/Crate[0..3]/Channel[000.042]/[iMon,vMon]" would be expanded to 344 (4x43x2) aliases. --- Detectors/DCS/CMakeLists.txt | 85 ++++++--- Detectors/DCS/README.md | 20 +++ .../DCS/include/DetectorsDCS/AliasExpander.h | 69 +++++++ .../include/DetectorsDCS/DataPointCreator.h | 47 +++++ .../include/DetectorsDCS/DataPointGenerator.h | 43 +++++ Detectors/DCS/src/AliasExpander.cxx | 145 +++++++++++++++ .../DCS/src/DataPointCompositeObject.cxx | 42 +++-- Detectors/DCS/src/DataPointCreator.cxx | 66 +++++++ Detectors/DCS/src/DataPointGenerator.cxx | 124 +++++++++++++ Detectors/DCS/src/DetectorsDCSLinkDef.h | 2 +- Detectors/DCS/test/testAliasExpander.cxx | 127 +++++++++++++ Detectors/DCS/test/testDataPointGenerator.cxx | 81 +++++++++ Detectors/DCS/test/testDataPointTypes.cxx | 39 ++++ .../testWorkflow/DCSRandomDataGeneratorSpec.h | 170 ++++++++++++++++++ Detectors/DCS/testWorkflow/README.md | 6 + .../testWorkflow/dcs-random-data-workflow.cxx | 43 +++++ Detectors/README.md | 1 + 17 files changed, 1065 insertions(+), 45 deletions(-) create mode 100644 Detectors/DCS/README.md create mode 100644 Detectors/DCS/include/DetectorsDCS/AliasExpander.h create mode 100644 Detectors/DCS/include/DetectorsDCS/DataPointCreator.h create mode 100644 Detectors/DCS/include/DetectorsDCS/DataPointGenerator.h create mode 100644 Detectors/DCS/src/AliasExpander.cxx create mode 100644 Detectors/DCS/src/DataPointCreator.cxx create mode 100644 Detectors/DCS/src/DataPointGenerator.cxx create mode 100644 Detectors/DCS/test/testAliasExpander.cxx create mode 100644 Detectors/DCS/test/testDataPointGenerator.cxx create mode 100644 Detectors/DCS/test/testDataPointTypes.cxx create mode 100644 Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h create mode 100644 Detectors/DCS/testWorkflow/README.md create mode 100644 Detectors/DCS/testWorkflow/dcs-random-data-workflow.cxx diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt index 1d037f297f6da..5c03ffb6ff1a1 100644 --- a/Detectors/DCS/CMakeLists.txt +++ b/Detectors/DCS/CMakeLists.txt @@ -8,35 +8,64 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_library(DetectorsDCS - TARGETVARNAME targetName - SOURCES src/Clock.cxx - src/DataPointCompositeObject.cxx - src/DataPointIdentifier.cxx - src/DataPointValue.cxx - src/DeliveryType.cxx - src/GenericFunctions.cxx - src/StringUtils.cxx - src/DCSProcessor.cxx - PUBLIC_LINK_LIBRARIES O2::Headers - O2::CommonUtils - O2::CCDB - O2::DetectorsCalibration - ms_gsl::ms_gsl) +o2_add_library( + DetectorsDCS + TARGETVARNAME targetName + SOURCES src/AliasExpander.cxx + src/DCSProcessor.cxx + src/DataPointCompositeObject.cxx + src/DataPointCreator.cxx + src/DataPointGenerator.cxx + src/DataPointIdentifier.cxx + src/DataPointValue.cxx + src/DeliveryType.cxx + src/GenericFunctions.cxx + src/StringUtils.cxx + src/Clock.cxx + PUBLIC_LINK_LIBRARIES O2::Headers O2::CommonUtils O2::CCDB + O2::DetectorsCalibration ms_gsl::ms_gsl) -o2_target_root_dictionary(DetectorsDCS - HEADERS include/DetectorsDCS/DataPointCompositeObject.h - include/DetectorsDCS/DataPointIdentifier.h - include/DetectorsDCS/DataPointValue.h - include/DetectorsDCS/DCSProcessor.h) +o2_target_root_dictionary( + DetectorsDCS + HEADERS include/DetectorsDCS/DataPointCompositeObject.h + include/DetectorsDCS/DataPointIdentifier.h + include/DetectorsDCS/DataPointValue.h + include/DetectorsDCS/DCSProcessor.h) -o2_add_executable(dcs-data-workflow - COMPONENT_NAME dcs - SOURCES testWorkflow/dcs-data-workflow.cxx - PUBLIC_LINK_LIBRARIES O2::Framework - O2::DetectorsDCS) +o2_add_executable( + data-workflow + COMPONENT_NAME dcs + SOURCES testWorkflow/dcs-data-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) -if (OpenMP_CXX_FOUND) - target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) - target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) +o2_add_executable( + random-data-workflow + COMPONENT_NAME dcs + SOURCES testWorkflow/dcs-random-data-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) + +if(OpenMP_CXX_FOUND) + target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) + target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) +endif() + +if(BUILD_TESTING) + o2_add_test( + data-point-types + SOURCES test/testDataPointTypes.cxx + COMPONENT_NAME dcs + LABELS "dcs" + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) + o2_add_test( + alias-expander + SOURCES test/testAliasExpander.cxx + COMPONENT_NAME dcs + LABELS "dcs" + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) + o2_add_test( + data-point-generator + SOURCES test/testDataPointGenerator.cxx + COMPONENT_NAME dcs + LABELS "dcs" + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) endif() diff --git a/Detectors/DCS/README.md b/Detectors/DCS/README.md new file mode 100644 index 0000000000000..13cf1eebe53b2 --- /dev/null +++ b/Detectors/DCS/README.md @@ -0,0 +1,20 @@ +<!-- doxy +\page refDetectorsDCS DCS +/doxy --> + +# Export of DCS to CCDB + +To be written + +# Generating DCS aliases + +For test purposes, DCS aliases can be generated making use of the helper +function `generateRandomDataPoints`. For example : + +```c++ +#include "DetectorsDCS/DataPointGenerator.h" +std::vector<std::string> patterns = { "DET/HV/Crate[0.9]/Channel[00.42]/vMon" }; +auto dps = o2::dcs::generateRandomDataPoints(patterns,0.0,1200.0); +``` + +would generate 420 data points. diff --git a/Detectors/DCS/include/DetectorsDCS/AliasExpander.h b/Detectors/DCS/include/DetectorsDCS/AliasExpander.h new file mode 100644 index 0000000000000..ac2ea2486e92b --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/AliasExpander.h @@ -0,0 +1,69 @@ +// 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_DCS_ALIAS_EXPANDER_H +#define O2_DCS_ALIAS_EXPANDER_H + +#include <vector> +#include <string> + +namespace o2::dcs +{ +/** + * expandAlias converts a single pattern into a list of strings. + * + * @param pattern a pattern is made of a number of "XX[YY]" blocks (at least one) + * + * where : + * - XX is any text + * - YY describes either a integral range or a textual list + * + * An integral range is [a..b] where the formatting of the biggest of the + * two integers a and b dictates, by default, the formatting of the output + * alias. For instance [0..3] is expanded to the set 0,1,2,3 while [00..03] + * is expanded to 00,01,02,03. If you want more control on the formatting, + * you can use a python/fmt format {} e.g. [0..15{:d}] would yields 0,1, + * 2,...,14,15 simply (no 0 filling). + * + * A textual list is simply a list of values separated by commas, + * e.g. "vMon,iMon" + * + * @returns a vector of strings containing all the possible expansions of + * the pattern. That vector is not guaranteed to be sorted. + * + * For example, pattern=DET[A,B]/Channel[000,002]/[iMon,vMon] yields : + * + * - DETA/Channel000/iMon + * - DETA/Channel001/iMon + * - DETA/Channel002/iMon + * - DETA/Channel000/vMon + * - DETA/Channel001/vMon + * - DETA/Channel002/vMon + * - DETB/Channel000/iMon + * - DETB/Channel001/iMon + * - DETB/Channel002/iMon + * - DETB/Channel000/vMon + * - DETB/Channel001/vMon + * - DETB/Channel002/vMon + +*/ +std::vector<std::string> expandAlias(const std::string& pattern); + +/** expandAliases converts a list of patterns into a list of strings. + * + * each input pattern is treated by expandAlias() + * + * @returns a _sorted_ vector of strings containing all the possible + * expansions of the pattern. + */ +std::vector<std::string> expandAliases(const std::vector<std::string>& patternedAliases); +} // namespace o2::dcs + +#endif diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointCreator.h b/Detectors/DCS/include/DetectorsDCS/DataPointCreator.h new file mode 100644 index 0000000000000..4c63e96108d15 --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/DataPointCreator.h @@ -0,0 +1,47 @@ +// 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_DCS_DATAPOINT_CREATOR_H +#define O2_DCS_DATAPOINT_CREATOR_H + +#include "DataPointCompositeObject.h" + +namespace o2::dcs +{ +/** + * createDataPointCompositeObject is a convenience function to + * simplify the creation of a DataPointCompositeObject. + * + * @param alias the DataPoint alias name (max 56 characters) + * @param val the value of the datapoint + * @param flags value for ADAPOS flags. + * @param milliseconds value for milliseconds. + * @param seconds value for seconds. + * + * @returns a DataPointCompositeObject + * + * The actual DeliveryType of the returned + * DataPointCompositeObject is deduced from the type of val. + * + * Note that only a few relevant specialization are actually provided + * + * - T=int32_t : DeliveryType = RAW_INT + * - T=uint32_t : DeliveryType = RAW_UINT + * - T=double : DeliveryType = RAW_DOUBLE + * - T=bool : DeliveryType = RAW_BOOL + * - T=char : DeliveryType = RAW_CHAR + * - T=std::string : DeliveryType = RAW_STRING + * + */ +template <typename T> +o2::dcs::DataPointCompositeObject createDataPointCompositeObject(const std::string& alias, T val, uint32_t seconds, uint16_t msec, uint16_t flags = 0); +} // namespace o2::dcs + +#endif diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointGenerator.h b/Detectors/DCS/include/DetectorsDCS/DataPointGenerator.h new file mode 100644 index 0000000000000..5b3bcc180dcb2 --- /dev/null +++ b/Detectors/DCS/include/DetectorsDCS/DataPointGenerator.h @@ -0,0 +1,43 @@ +// 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_DCS_DATAPOINT_GENERATOR_H +#define O2_DCS_DATAPOINT_GENERATOR_H + +#include "DetectorsDCS/DeliveryType.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include <vector> + +namespace o2::dcs +{ +/** +* Generate random data points, uniformly distributed between two values. +* +* @tparam T the type of value of the data points to be generated. Only +* a few types are supported : double, uint32_t, int32_t, char, bool +* +* @param aliases the list of aliases to be generated. Those can use +* patterns that will be expanded, @see AliasExpander +* @param minValue the minimum value of the values to be generated +* @param maxValue the maximum value of the values to be generated +* @param refDate the date to be associated with all data points +* in `%Y-%b-%d %H:%M:%S` format. If refDate="" the current date is used. +* +* @returns a vector of DataPointCompositeObject objects +*/ +template <typename T> +std::vector<DataPointCompositeObject> generateRandomDataPoints(const std::vector<std::string>& aliases, + T min, + T max, + std::string refDate = ""); + +} // namespace o2::dcs + +#endif diff --git a/Detectors/DCS/src/AliasExpander.cxx b/Detectors/DCS/src/AliasExpander.cxx new file mode 100644 index 0000000000000..e2f7448ad5696 --- /dev/null +++ b/Detectors/DCS/src/AliasExpander.cxx @@ -0,0 +1,145 @@ +// 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 "DetectorsDCS/AliasExpander.h" +#include <fmt/format.h> +#include <sstream> + +namespace +{ + +std::vector<std::string> splitString(const std::string& src, char delim) +{ + std::stringstream ss(src); + std::string token; + std::vector<std::string> tokens; + + while (std::getline(ss, token, delim)) { + if (!token.empty()) { + tokens.push_back(std::move(token)); + } + } + + return tokens; +} + +std::vector<std::string> extractList(const std::string& slist) +{ + auto dots = slist.find(","); + if (dots == std::string::npos) { + return {}; + } + return splitString(slist, ','); +} + +std::vector<std::string> extractRange(std::string range) +{ + auto dots = range.find(".."); + if (dots == std::string::npos) { + return extractList(range); + } + + auto braceStart = range.find("{"); + auto braceEnd = range.find("}"); + + if ( + (braceStart != std::string::npos && + braceEnd == std::string::npos) || + (braceStart == std::string::npos && + braceEnd != std::string::npos)) { + // incomplete custom pattern + return {}; + } + + std::string intFormat; + std::string sa, sb; + + if (braceStart != std::string::npos && + braceEnd != std::string::npos) { + intFormat = range.substr(braceStart, braceEnd - braceStart + 1); + range.erase(braceStart, braceEnd); + dots = range.find(".."); + sa = range.substr(0, dots); + sb = range.substr(dots + 2); + } else { + sa = range.substr(0, dots); + sb = range.substr(dots + 2); + auto size = std::max(sa.size(), sb.size()); + intFormat = "{:" + fmt::format("0{}d", size) + "}"; + } + + auto a = std::stoi(sa); + auto b = std::stoi(sb); + std::vector<std::string> result; + + for (auto i = a; i <= b; i++) { + auto substituted = fmt::format(intFormat, i); + result.push_back(substituted); + } + return result; +} +} // namespace + +namespace o2::dcs +{ +std::vector<std::string> expandAlias(const std::string& pattern) +{ + auto leftBracket = pattern.find("["); + auto rightBracket = pattern.find("]"); + + // no bracket at all -> return pattern simply + if (leftBracket == std::string::npos && rightBracket == std::string::npos) { + return {pattern}; + } + + // no matching bracket -> wrong pattern -> return nothing + if ((leftBracket == std::string::npos && + rightBracket != std::string::npos) || + (leftBracket != std::string::npos && + rightBracket == std::string::npos)) { + return {}; + } + auto rangeStr = pattern.substr(leftBracket + 1, rightBracket - leftBracket - 1); + + auto range = extractRange(rangeStr); + + // incorrect range -> return nothing + if (range.empty()) { + return {}; + } + + auto newPattern = pattern.substr(0, leftBracket) + + "{:s}" + + pattern.substr(rightBracket + 1); + + std::vector<std::string> result; + + for (auto r : range) { + auto substituted = fmt::format(newPattern, r); + result.emplace_back(substituted); + } + + return o2::dcs::expandAliases(result); +} + +std::vector<std::string> expandAliases(const std::vector<std::string>& patternedAliases) +{ + std::vector<std::string> result; + + for (auto a : patternedAliases) { + auto e = expandAlias(a); + result.insert(result.end(), e.begin(), e.end()); + } + // sort to get a predictable result + std::sort(result.begin(), result.end()); + + return result; +} +} // namespace o2::dcs diff --git a/Detectors/DCS/src/DataPointCompositeObject.cxx b/Detectors/DCS/src/DataPointCompositeObject.cxx index 4ace9a61b62b5..2ec290215f0ad 100644 --- a/Detectors/DCS/src/DataPointCompositeObject.cxx +++ b/Detectors/DCS/src/DataPointCompositeObject.cxx @@ -16,12 +16,13 @@ ClassImp(DataPointCompositeObject); namespace o2::dcs { -template<typename T, o2::dcs::DeliveryType dt> -T getValueImpl(const DataPointCompositeObject& dpcom) { -union Converter { - uint64_t raw_data; - T t_value; -}; +template <typename T, o2::dcs::DeliveryType dt> +T getValueImpl(const DataPointCompositeObject& dpcom) +{ + union Converter { + uint64_t raw_data; + T t_value; + }; if (dpcom.id.get_type() != dt) { throw std::runtime_error("DPCOM is of unexpected type " + o2::dcs::show(dt)); } @@ -35,39 +36,48 @@ union Converter { // - double // - uint32_t // - int32_t -// - char +// - char // - bool - -// template<> -// double getValueImpl<double,DeliveryType::RAW_DOUBLE>(const DataPointCompositeObject&); // -template<> +// - string + +template <> double getValue(const DataPointCompositeObject& dpcom) { - return getValueImpl<double,DeliveryType::RAW_DOUBLE>(dpcom); + return getValueImpl<double, DeliveryType::RAW_DOUBLE>(dpcom); } template <> uint32_t getValue(const DataPointCompositeObject& dpcom) { - return getValueImpl<uint32_t,DeliveryType::RAW_UINT>(dpcom); + return getValueImpl<uint32_t, DeliveryType::RAW_UINT>(dpcom); } template <> int32_t getValue(const DataPointCompositeObject& dpcom) { - return getValueImpl<int32_t,DeliveryType::RAW_INT>(dpcom); + return getValueImpl<int32_t, DeliveryType::RAW_INT>(dpcom); } template <> char getValue(const DataPointCompositeObject& dpcom) { - return getValueImpl<char,DeliveryType::RAW_CHAR>(dpcom); + return getValueImpl<char, DeliveryType::RAW_CHAR>(dpcom); } template <> bool getValue(const DataPointCompositeObject& dpcom) { - return getValueImpl<bool,DeliveryType::RAW_BOOL>(dpcom); + return getValueImpl<bool, DeliveryType::RAW_BOOL>(dpcom); +} + +template <> +std::string getValue(const DataPointCompositeObject& dpcom) +{ + if (dpcom.id.get_type() != o2::dcs::DeliveryType::RAW_STRING) { + throw std::runtime_error("DPCOM is of unexpected type " + o2::dcs::show(dpcom.id.get_type())); + } + return std::string((char*)&dpcom.data.payload_pt1); } + } // namespace o2::dcs diff --git a/Detectors/DCS/src/DataPointCreator.cxx b/Detectors/DCS/src/DataPointCreator.cxx new file mode 100644 index 0000000000000..6b11d76a7675e --- /dev/null +++ b/Detectors/DCS/src/DataPointCreator.cxx @@ -0,0 +1,66 @@ +// 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 "DetectorsDCS/DataPointCreator.h" + +namespace +{ +o2::dcs::DataPointCompositeObject createDPCOM(const std::string& alias, const uint64_t* val, uint32_t seconds, uint16_t msec, uint16_t flags, o2::dcs::DeliveryType dt) +{ + auto dpid = o2::dcs::DataPointIdentifier(alias, dt); + auto dpval = o2::dcs::DataPointValue( + flags, + msec, + seconds, + val, + dt); + return o2::dcs::DataPointCompositeObject(dpid, dpval); +} +} // namespace + +namespace o2::dcs +{ +template <> +DataPointCompositeObject createDataPointCompositeObject(const std::string& alias, double val, uint32_t seconds, uint16_t msec, uint16_t flags) +{ + return createDPCOM(alias, reinterpret_cast<const uint64_t*>(&val), seconds, msec, flags, DeliveryType::RAW_DOUBLE); +} + +template <> +DataPointCompositeObject createDataPointCompositeObject(const std::string& alias, int32_t val, uint32_t seconds, uint16_t msec, uint16_t flags) +{ + return createDPCOM(alias, reinterpret_cast<const uint64_t*>(&val), seconds, msec, flags, DeliveryType::RAW_INT); +} + +template <> +DataPointCompositeObject createDataPointCompositeObject(const std::string& alias, uint32_t val, uint32_t seconds, uint16_t msec, uint16_t flags) +{ + return createDPCOM(alias, reinterpret_cast<const uint64_t*>(&val), seconds, msec, flags, DeliveryType::RAW_UINT); +} + +template <> +DataPointCompositeObject createDataPointCompositeObject(const std::string& alias, char val, uint32_t seconds, uint16_t msec, uint16_t flags) +{ + return createDPCOM(alias, reinterpret_cast<const uint64_t*>(&val), seconds, msec, flags, DeliveryType::RAW_CHAR); +} + +template <> +DataPointCompositeObject createDataPointCompositeObject(const std::string& alias, bool val, uint32_t seconds, uint16_t msec, uint16_t flags) +{ + return createDPCOM(alias, reinterpret_cast<const uint64_t*>(&val), seconds, msec, flags, DeliveryType::RAW_BOOL); +} + +template <> +DataPointCompositeObject createDataPointCompositeObject(const std::string& alias, std::string val, uint32_t seconds, uint16_t msec, uint16_t flags) +{ + return createDPCOM(alias, reinterpret_cast<const uint64_t*>(val.c_str()), seconds, msec, flags, DeliveryType::RAW_STRING); +} + +} // namespace o2::dcs diff --git a/Detectors/DCS/src/DataPointGenerator.cxx b/Detectors/DCS/src/DataPointGenerator.cxx new file mode 100644 index 0000000000000..062d996452798 --- /dev/null +++ b/Detectors/DCS/src/DataPointGenerator.cxx @@ -0,0 +1,124 @@ +// 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 "DetectorsDCS/AliasExpander.h" +#include "DetectorsDCS/DataPointGenerator.h" +#include "DetectorsDCS/DataPointCreator.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/StringUtils.h" +#include <fmt/format.h> +#include <random> +#include <utility> +#include <type_traits> +#include <cstdint> + +namespace +{ +std::pair<uint32_t, uint16_t> getDate(const std::string& refDate) +{ + uint32_t seconds; + if (refDate.empty()) { + auto current = std::time(nullptr); + auto t = std::localtime(¤t); + uint32_t seconds = mktime(t); + } else { + std::tm t{}; + std::istringstream ss(refDate); + ss >> std::get_time(&t, "%Y-%b-%d %H:%M:%S"); + seconds = mktime(&t); + } + uint16_t msec = 5; + return std::make_pair(seconds, msec); +} + +} // namespace + +namespace o2::dcs +{ + +//std::enable_if_t<std::is_arithmetic<T>::value, bool> = true> + +template <typename T> +std::vector<o2::dcs::DataPointCompositeObject> + generateRandomDataPoints(const std::vector<std::string>& aliases, + T minValue, T maxValue, std::string refDate) +{ + std::vector<o2::dcs::DataPointCompositeObject> dpcoms; + static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type"); + typedef typename std::conditional<std::is_integral<T>::value, + std::uniform_int_distribution<T>, + std::uniform_real_distribution<T>>::type distType; + + std::random_device rd; + std::mt19937 mt(rd()); + distType dist{minValue, maxValue}; + auto [seconds, msec] = getDate(refDate); + for (auto alias : expandAliases(aliases)) { + auto value = dist(mt); + dpcoms.emplace_back(o2::dcs::createDataPointCompositeObject(alias, value, seconds, msec)); + } + return dpcoms; +} + +// only specialize the functions for the types we support : +// +// - double +// - uint32_t +// - int32_t +// - char +// - bool +// +// - std::string + +template std::vector<o2::dcs::DataPointCompositeObject> generateRandomDataPoints<double>(const std::vector<std::string>& aliases, double minValue, double maxValue, std::string); + +template std::vector<o2::dcs::DataPointCompositeObject> generateRandomDataPoints<uint32_t>(const std::vector<std::string>& aliases, uint32_t minValue, uint32_t maxValue, std::string); + +template std::vector<o2::dcs::DataPointCompositeObject> generateRandomDataPoints<int32_t>(const std::vector<std::string>& aliases, int32_t minValue, int32_t maxValue, std::string); + +template std::vector<o2::dcs::DataPointCompositeObject> generateRandomDataPoints<char>(const std::vector<std::string>& aliases, char minValue, char maxValue, std::string); + +/** Need a specific specialization for bool as got into trouble compiling uniform_int_distribution<bool> + * on some platform (e.g. CC7). + */ +template <> +std::vector<o2::dcs::DataPointCompositeObject> generateRandomDataPoints<bool>(const std::vector<std::string>& aliases, bool minValue, bool maxValue, std::string refDate) +{ + std::vector<o2::dcs::DataPointCompositeObject> dpcoms; + std::random_device rd; + std::mt19937 mt(rd()); + std::uniform_int_distribution dist{0, 1}; + auto [seconds, msec] = getDate(refDate); + for (auto alias : expandAliases(aliases)) { + bool value = dist(mt); + dpcoms.emplace_back(o2::dcs::createDataPointCompositeObject(alias, value, seconds, msec)); + } + return dpcoms; +} + +/** + * Generate data points of type string, where each string is random, with + * a length between the length of the two input strings (minLength,maxLength) + */ +template <> +std::vector<o2::dcs::DataPointCompositeObject> generateRandomDataPoints<std::string>(const std::vector<std::string>& aliases, std::string minLength, std::string maxLength, std::string refDate) +{ + std::vector<o2::dcs::DataPointCompositeObject> dpcoms; + std::random_device rd; + std::mt19937 mt(rd()); + std::uniform_int_distribution<std::string::size_type> dist{minLength.size(), maxLength.size()}; + auto [seconds, msec] = getDate(refDate); + for (auto alias : expandAliases(aliases)) { + auto value = o2::dcs::random_string2(dist(mt)); + dpcoms.emplace_back(o2::dcs::createDataPointCompositeObject(alias, value, seconds, msec)); + } + return dpcoms; +} +} // namespace o2::dcs diff --git a/Detectors/DCS/src/DetectorsDCSLinkDef.h b/Detectors/DCS/src/DetectorsDCSLinkDef.h index 476dde0b3609c..5f53e7757a349 100644 --- a/Detectors/DCS/src/DetectorsDCSLinkDef.h +++ b/Detectors/DCS/src/DetectorsDCSLinkDef.h @@ -15,7 +15,7 @@ #pragma link off all functions; #pragma link C++ struct o2::dcs::DataPointCompositeObject + ; -#pragma link C++ struct o2::dcs::DataPointIdentifier + ; +#pragma link C++ class o2::dcs::DataPointIdentifier + ; #pragma link C++ struct o2::dcs::DataPointValue + ; #pragma link C++ class o2::dcs::DCSProcessor + ; #pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue> + ; diff --git a/Detectors/DCS/test/testAliasExpander.cxx b/Detectors/DCS/test/testAliasExpander.cxx new file mode 100644 index 0000000000000..549a7a69cda65 --- /dev/null +++ b/Detectors/DCS/test/testAliasExpander.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. + +#define BOOST_TEST_MODULE Test DCS AliasExpander +#define BOOST_TEST_MAIN + +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> +#include <boost/test/data/test_case.hpp> +#include <iostream> +#include "DetectorsDCS/AliasExpander.h" + +BOOST_AUTO_TEST_CASE(ExpandAliasesIsNoopWhenNoPatternGiven) +{ + std::vector<std::string> aliases = o2::dcs::expandAliases({"ab"}); + + std::vector<std::string> expected = {"ab"}; + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); +} + +BOOST_AUTO_TEST_CASE(ExpandAliasesReturnsEmptyVectorWhenPatternIsIncorrect) +{ + std::vector<std::string> aliases = o2::dcs::expandAliases({"ab[c"}); + + std::vector<std::string> expected = {}; + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); + + aliases = o2::dcs::expandAliases({"ab]c"}); + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); + + aliases = o2::dcs::expandAliases({"ab[1.2]c"}); + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); +} + +BOOST_AUTO_TEST_CASE(ExpandAliasesWithIntegerRange) +{ + std::vector<std::string> aliases = o2::dcs::expandAliases({"a[1..2]bcde[99..101]toto"}); + + std::vector<std::string> expected = { + "a1bcde099toto", + "a1bcde100toto", + "a1bcde101toto", + "a2bcde099toto", + "a2bcde100toto", + "a2bcde101toto"}; + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); +} + +BOOST_AUTO_TEST_CASE(ExpandAliasesWithIntegerRangeWithCustomFormat) +{ + std::vector<std::string> aliases = o2::dcs::expandAliases({"a[1..3{:03d}]"}); + + std::vector<std::string> expected = { + "a001", + "a002", + "a003"}; + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); +} + +BOOST_AUTO_TEST_CASE(ExpandAliasesWithIntegerRangeWithCustomFormatBis) +{ + std::vector<std::string> aliases = o2::dcs::expandAliases({"a[1..3{:d}]"}); + + std::vector<std::string> expected = { + "a1", + "a2", + "a3"}; + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); +} + +BOOST_AUTO_TEST_CASE(ExpandAliasesWithStringList) +{ + std::vector<std::string> aliases = o2::dcs::expandAliases({"a[1..2]bcde[99..101][toto,titi,tata]"}); + + std::vector<std::string> expected = { + "a1bcde099tata", + "a1bcde099titi", + "a1bcde099toto", + "a1bcde100tata", + "a1bcde100titi", + "a1bcde100toto", + "a1bcde101tata", + "a1bcde101titi", + "a1bcde101toto", + "a2bcde099tata", + "a2bcde099titi", + "a2bcde099toto", + "a2bcde100tata", + "a2bcde100titi", + "a2bcde100toto", + "a2bcde101tata", + "a2bcde101titi", + "a2bcde101toto", + }; + + BOOST_TEST(aliases == expected, boost::test_tools::per_element()); +} + +BOOST_AUTO_TEST_CASE(ExpandMch) +{ + std::vector<std::string> aliases = o2::dcs::expandAliases( + {"MchHvLvLeft/Chamber[00..03]Left/Quad1Sect[0..2].actual.[vMon,iMon]", + "MchHvLvLeft/Chamber[00..03]Left/Quad2Sect[0..2].actual.[vMon,iMon]", + "MchHvLvLeft/Chamber[04..09]Left/Slat[00..08].actual.[vMon,iMon]", + "MchHvLvLeft/Chamber[06..09]Left/Slat[09..12].actual.[vMon,iMon]", + "MchHvLvRight/Chamber[00..03]Right/Quad0Sect[0..2].actual.[vMon,iMon]", + "MchHvLvRight/Chamber[00..03]Right/Quad3Sect[0..2].actual.[vMon,iMon]", + "MchHvLvRight/Chamber[04..09]Right/Slat[00..08].actual.[vMon,iMon]", + "MchHvLvRight/Chamber[06..09]Right/Slat[09..12].actual.[vMon,iMon]"}); + + BOOST_TEST(aliases.size(), 376); +} diff --git a/Detectors/DCS/test/testDataPointGenerator.cxx b/Detectors/DCS/test/testDataPointGenerator.cxx new file mode 100644 index 0000000000000..367e52dc14558 --- /dev/null +++ b/Detectors/DCS/test/testDataPointGenerator.cxx @@ -0,0 +1,81 @@ +// 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. + +#define BOOST_TEST_MODULE Test DCS DataPointGenerator +#define BOOST_TEST_MAIN + +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> +#include <boost/test/data/test_case.hpp> +#include <iostream> +#include "DetectorsDCS/DataPointGenerator.h" +#include <algorithm> + +BOOST_AUTO_TEST_CASE(GenerateDouble) +{ + double fmin = 1620.0; + double fmax = 1710.5; + auto fbi = o2::dcs::generateRandomDataPoints({"TST/SECTOR[00..06]/CRATE[0..3]/voltage"}, fmin, fmax, "2022-November-18 12:34:56"); + + BOOST_CHECK_EQUAL(fbi.size(), 28); + + for (auto dp : fbi) { + BOOST_CHECK_EQUAL(dp.id.get_type(), o2::dcs::DeliveryType::RAW_DOUBLE); + double value = o2::dcs::getValue<double>(dp); + BOOST_CHECK(value >= fmin && value <= fmax); + } +} + +BOOST_AUTO_TEST_CASE(GenerateInt) +{ + uint32_t imin = 0; + uint32_t imax = 3; + auto fbi = o2::dcs::generateRandomDataPoints({"TST/SECTOR[00..06]/CRATE[0..3]/current"}, imin, imax, "2022-November-18 12:34:56"); + + BOOST_CHECK_EQUAL(fbi.size(), 28); + + for (auto dp : fbi) { + BOOST_CHECK_EQUAL(dp.id.get_type(), o2::dcs::DeliveryType::RAW_UINT); + double value = o2::dcs::getValue<uint32_t>(dp); + BOOST_CHECK(value >= imin && value <= imax); + BOOST_CHECK_THROW(o2::dcs::getValue<double>(dp), std::runtime_error); + BOOST_CHECK_THROW(o2::dcs::getValue<int32_t>(dp), std::runtime_error); + } +} + +BOOST_AUTO_TEST_CASE(GenerateBool) +{ + auto fbi = o2::dcs::generateRandomDataPoints<bool>({"TST/SECTOR[00..06]/status"}, 0, 1, "2022-November-18 12:34:56"); + + BOOST_CHECK_EQUAL(fbi.size(), 7); + + for (auto dp : fbi) { + BOOST_CHECK_EQUAL(dp.id.get_type(), o2::dcs::DeliveryType::RAW_BOOL); + BOOST_CHECK_NO_THROW(o2::dcs::getValue<bool>(dp)); + BOOST_CHECK_THROW(o2::dcs::getValue<int>(dp), std::runtime_error); + } +} + +BOOST_AUTO_TEST_CASE(GenerateString) +{ + auto fbi = o2::dcs::generateRandomDataPoints<std::string>({"TST/SECTOR[00..06]/name"}, "123", "1234567", "2022-November-18 12:34:56"); + + BOOST_CHECK_EQUAL(fbi.size(), 7); + + for (auto dp : fbi) { + BOOST_CHECK_EQUAL(dp.id.get_type(), o2::dcs::DeliveryType::RAW_STRING); + BOOST_CHECK_NO_THROW(o2::dcs::getValue<std::string>(dp)); + BOOST_CHECK_THROW(o2::dcs::getValue<int>(dp), std::runtime_error); + auto value = o2::dcs::getValue<std::string>(dp); + BOOST_CHECK(value.size() >= 3); + BOOST_CHECK(value.size() <= 7); + } +} diff --git a/Detectors/DCS/test/testDataPointTypes.cxx b/Detectors/DCS/test/testDataPointTypes.cxx new file mode 100644 index 0000000000000..91c1db1def7c2 --- /dev/null +++ b/Detectors/DCS/test/testDataPointTypes.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. + +#include <type_traits> +#define BOOST_TEST_MODULE Test DetectorsDCS DataPoints +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "Framework/TypeTraits.h" +#include <vector> +#include <list> +#include <gsl/gsl> +#include <boost/mpl/list.hpp> + +typedef boost::mpl::list<o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue, o2::dcs::DataPointCompositeObject> testTypes; + +BOOST_AUTO_TEST_CASE_TEMPLATE(DataPointCompositeObjectTypeTraits, T, testTypes) +{ + BOOST_CHECK_EQUAL(std::is_trivially_copyable<T>::value, true); + BOOST_CHECK_EQUAL(std::is_polymorphic<T>::value, false); + BOOST_CHECK_EQUAL(std::is_pointer<T>::value, false); + BOOST_CHECK_EQUAL(o2::framework::is_forced_non_messageable<T>::value, false); +} + +BOOST_AUTO_TEST_CASE(DataPointsAreMessageable) +{ + BOOST_CHECK_EQUAL(o2::framework::is_messageable<o2::dcs::DataPointIdentifier>::value, true); + BOOST_CHECK_EQUAL(o2::framework::is_messageable<o2::dcs::DataPointValue>::value, true); + BOOST_CHECK_EQUAL(o2::framework::is_messageable<o2::dcs::DataPointCompositeObject>::value, true); +} diff --git a/Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h new file mode 100644 index 0000000000000..9874df180c2dc --- /dev/null +++ b/Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h @@ -0,0 +1,170 @@ +// 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_DCS_RANDOM_DATA_GENERATOR_SPEC_H +#define O2_DCS_RANDOM_DATA_GENERATOR_SPEC_H + +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/DataPointGenerator.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/DeviceSpec.h" +#include "Framework/Logger.h" +#include "Framework/Task.h" +#include <random> +#include <variant> +#include <string> + +using namespace o2::framework; + +namespace +{ +/* + * A compact representation a group of alias to be generated + */ +template <typename T> +struct DataPointHint { + std::string aliasPattern; // alias pattern e.g. DET/HV/Crate[0..2]/Channel[000..012]/vMon + T minValue; // minimum value to generate + T maxValue; // maximum value to generate +}; + +using HintType = std::variant<DataPointHint<double>, + DataPointHint<uint32_t>, + DataPointHint<int32_t>, + DataPointHint<char>, + DataPointHint<bool>, + DataPointHint<std::string>>; + +/** generate random integers uniformly distributed within a range. + * + * @param size the number of integers to generate + * @param min the minimum value to be generated + * @param max the maximum value to be generated + * + * @returns a vector of integers + */ +std::vector<int> generateIntegers(size_t size, int min, int max) +{ + std::uniform_int_distribution<int> distribution(min, max); + std::mt19937 generator; + std::vector<int> data(size); + std::generate(data.begin(), data.end(), [&]() { return distribution(generator); }); + return data; +} + +/** generate DCS data points. + * + * @param hints vector of HintType describing what to generate + * @param fraction fraction of the generated aliases that are returned (1.0 by default) + * + * @returns a vector of DataPointCompositeObjects + */ +std::vector<o2::dcs::DataPointCompositeObject> generate(const std::vector<HintType> hints, + float fraction = 1.0) +{ + std::vector<o2::dcs::DataPointCompositeObject> dataPoints; + + auto GenerateVisitor = [](const auto& t) { + return o2::dcs::generateRandomDataPoints({t.aliasPattern}, t.minValue, t.maxValue); + }; + + for (const auto& hint : hints) { + auto dpcoms = std::visit(GenerateVisitor, hint); + for (auto dp : dpcoms) { + dataPoints.push_back(dp); + } + } + if (fraction < 1.0) { + auto indices = generateIntegers(fraction * dataPoints.size(), 0, dataPoints.size() - 1); + auto tmp = dataPoints; + dataPoints.clear(); + for (auto i : indices) { + dataPoints.push_back(tmp[i]); + } + } + return dataPoints; +} + +/** + * DCSRandomDataGenerator is an example device that generates random + * DCS Data Points. + * + * The actual description of what is generated is hard-coded in + * the init() method. + */ +class DCSRandomDataGenerator : public o2::framework::Task +{ + using DPID = o2::dcs::DataPointIdentifier; + using DPVAL = o2::dcs::DataPointValue; + using DPCOM = o2::dcs::DataPointCompositeObject; + + public: + void init(o2::framework::InitContext& ic) final + { + mMaxTF = ic.options().get<int64_t>("max-timeframes"); + mDeltaFraction = ic.options().get<float>("delta-fraction"); + mMaxCyclesNoFullMap = ic.options().get<int64_t>("max-cycles-no-full-map"); + + // create the list of DataPointHints to be used by the generator + mDataPointHints.emplace_back(DataPointHint<char>{"TestChar_0", 'A', 'z'}); + mDataPointHints.emplace_back(DataPointHint<double>{"TestDouble_[0..3]", 0, 1700}); + mDataPointHints.emplace_back(DataPointHint<int32_t>{"TestInt_[0..50000{:d}]", 0, 1234}); + mDataPointHints.emplace_back(DataPointHint<bool>{"TestBool_[00..03]", 0, 1}); + mDataPointHints.emplace_back(DataPointHint<std::string>{"TestString_0", "ABC", "ABCDEF"}); + } + + void run(o2::framework::ProcessingContext& pc) final + { + auto input = pc.inputs().begin(); + uint64_t tfid = o2::header::get<o2::framework::DataProcessingHeader*>((*input).header)->startTime; + if (tfid >= mMaxTF) { + LOG(INFO) << "Data generator reached TF " << tfid << ", stopping"; + pc.services().get<o2::framework::ControlService>().endOfStream(); + pc.services().get<o2::framework::ControlService>().readyToQuit(o2::framework::QuitRequest::Me); + } + + bool generateFBI = (mTFs % mMaxCyclesNoFullMap == 0); + // fraction is one if we generate FBI (Full Buffer Image) + float fraction = (generateFBI ? 1.0 : mDeltaFraction); + + auto dpcoms = generate(mDataPointHints, fraction); + + // the output must always get both FBI and Delta, but one of them is empty. + std::vector<o2::dcs::DataPointCompositeObject> empty; + pc.outputs().snapshot(Output{"DCS", "DATAPOINTS", 0, Lifetime::Timeframe}, generateFBI ? dpcoms : empty); + pc.outputs().snapshot(Output{"DCS", "DATAPOINTSdelta", 0, Lifetime::Timeframe}, generateFBI ? empty : dpcoms); + mTFs++; + } + + private: + uint64_t mMaxTF; + uint64_t mTFs = 0; + uint64_t mMaxCyclesNoFullMap; + float mDeltaFraction; + std::vector<HintType> mDataPointHints; +}; + +} // namespace + +DataProcessorSpec getDCSRandomDataGeneratorSpec() +{ + return DataProcessorSpec{ + "dcs-random-data-generator", + Inputs{}, + Outputs{{{"outputDCS"}, "DCS", "DATAPOINTS"}, {{"outputDCSdelta"}, "DCS", "DATAPOINTSdelta"}}, + AlgorithmSpec{adaptFromTask<DCSRandomDataGenerator>()}, + Options{ + {"max-timeframes", VariantType::Int64, 99999999999ll, {"max TimeFrames to generate"}}, + {"delta-fraction", VariantType::Float, 0.05f, {"fraction of data points to put in the delta"}}, + {"max-cycles-no-full-map", VariantType::Int64, 6000ll, {"max num of cycles between the sending of 2 full maps"}}}}; +} + +#endif diff --git a/Detectors/DCS/testWorkflow/README.md b/Detectors/DCS/testWorkflow/README.md new file mode 100644 index 0000000000000..2c4b879ab56eb --- /dev/null +++ b/Detectors/DCS/testWorkflow/README.md @@ -0,0 +1,6 @@ +Local example workflow with local CCDB (running on port 6464) : + +```shell +o2-dcs-random-data-workflow --max-timeframes=10 | +o2-calibration-ccdb-populator-workflow --ccdb-path http://localhost:6464 +``` diff --git a/Detectors/DCS/testWorkflow/dcs-random-data-workflow.cxx b/Detectors/DCS/testWorkflow/dcs-random-data-workflow.cxx new file mode 100644 index 0000000000000..3f1539fb63e49 --- /dev/null +++ b/Detectors/DCS/testWorkflow/dcs-random-data-workflow.cxx @@ -0,0 +1,43 @@ +// 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 "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "Framework/TypeTraits.h" +#include <unordered_map> +namespace o2::framework +{ +template <> +struct has_root_dictionary<std::unordered_map<o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue>, void> : std::true_type { +}; +} // namespace o2::framework +#include "Framework/DataProcessorSpec.h" +#include "DCSRandomDataGeneratorSpec.h" +#include "DCSDataProcessorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getDCSRandomDataGeneratorSpec()); + specs.emplace_back(getDCSDataProcessorSpec()); + return specs; +} diff --git a/Detectors/README.md b/Detectors/README.md index 3be3ed677ae60..89114fd394a66 100644 --- a/Detectors/README.md +++ b/Detectors/README.md @@ -19,6 +19,7 @@ This module contains the following submodules: * \subpage refDetectorsCPV * \subpage refDetectorsCTF * \subpage refDetectorsEMCAL +* \subpage refDetectorsDCS * \subpage refDetectorsFIT * \subpage refDetectorsHMPID * \subpage refDetectorsITSMFT From 50125c67d122ecb5e046484861dc1ab95f5f4c66 Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Mon, 23 Nov 2020 15:17:38 +0100 Subject: [PATCH 1411/1751] Add dictionary info for expandAlias(es) functions --- Detectors/DCS/src/DetectorsDCSLinkDef.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/DCS/src/DetectorsDCSLinkDef.h b/Detectors/DCS/src/DetectorsDCSLinkDef.h index 5f53e7757a349..da9a282797cba 100644 --- a/Detectors/DCS/src/DetectorsDCSLinkDef.h +++ b/Detectors/DCS/src/DetectorsDCSLinkDef.h @@ -19,5 +19,7 @@ #pragma link C++ struct o2::dcs::DataPointValue + ; #pragma link C++ class o2::dcs::DCSProcessor + ; #pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue> + ; +#pragma link C++ function o2::dcs::expandAlias(const std::string&); +#pragma link C++ function o2::dcs::expandAliases(const std::vector<std::string>&); #endif From a073cfe878e09e08b343d351196d7ba4435e4fdb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 24 Nov 2020 09:28:18 +0100 Subject: [PATCH 1412/1751] DPL: do not crash when --dump-workflow-file is used --- Framework/Core/src/runDataProcessing.cxx | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index d352d6b6d1a5b..c50cb00d38a9a 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1293,16 +1293,21 @@ int runStateMachine(DataProcessorSpecs const& workflow, } // This is a clean exit. Before we do so, if required, // we dump the configuration of all the devices so that - // we can reuse it - boost::property_tree::ptree finalConfig; - assert(infos.size() == deviceSpecs.size()); - for (size_t di = 0; di < infos.size(); ++di) { - auto info = infos[di]; - auto spec = deviceSpecs[di]; - finalConfig.put_child(spec.name, info.currentConfig); + // we can reuse it. Notice we do not dump anything if + // the workflow was not really run. + // NOTE: is this really what we want? should we run + // SCHEDULE and dump the full configuration as well? + if (!infos.empty()) { + boost::property_tree::ptree finalConfig; + assert(infos.size() == deviceSpecs.size()); + for (size_t di = 0; di < infos.size(); ++di) { + auto info = infos[di]; + auto spec = deviceSpecs[di]; + finalConfig.put_child(spec.name, info.currentConfig); + } + LOG(INFO) << "Dumping used configuration in dpl-config.json"; + boost::property_tree::write_json("dpl-config.json", finalConfig); } - LOG(INFO) << "Dumping used configuration in dpl-config.json"; - boost::property_tree::write_json("dpl-config.json", finalConfig); if (driverInfo.noSHMCleanup) { LOGP(warning, "Not cleaning up shared memory."); } else { From e409c40d25eb7b9ede3d186536e5d3f3a3a295f3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 24 Nov 2020 10:59:54 +0100 Subject: [PATCH 1413/1751] DPL Analysis: add metrics for bytes read --- Framework/Core/src/AODReaderHelpers.cxx | 16 +++++++++++++--- Framework/Core/src/runDataProcessing.cxx | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index e938e09d550f0..a472f157ea60a 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -243,6 +243,8 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() // loop over requested tables TTree* tr = nullptr; bool first = true; + static size_t totalSizeUncompressed = 0; + static size_t totalSizeCompressed = 0; for (auto route : requestedTables) { // create header @@ -285,19 +287,27 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() auto& t2t = outputs.make<TreeToTable>(o); // add branches to read + // fill the table + auto colnames = aod::datamodel::getColumnNames(dh); if (colnames.size() == 0) { + totalSizeCompressed += tr->GetZipBytes(); + totalSizeUncompressed += tr->GetTotBytes(); t2t.addAllColumns(tr); } else { - for (auto colname : colnames) { + for (auto& colname : colnames) { + TBranch* branch = tr->GetBranch(colname.c_str()); + totalSizeCompressed += branch->GetZipBytes("*"); + totalSizeUncompressed += branch->GetTotBytes("*"); t2t.addColumn(colname.c_str()); } } - - // fill the table t2t.fill(tr); + first = false; } + monitoring.send(Metric{(uint64_t)totalSizeUncompressed, "aod-bytes-read-uncompressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)totalSizeCompressed, "aod-bytes-read-compressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); // save file number and time frame *fileCounter = (fcnt - device.inputTimesliceId) / device.maxInputTimeslices; diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index c50cb00d38a9a..ebdc1e9e03001 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1289,6 +1289,8 @@ int runStateMachine(DataProcessorSpecs const& workflow, LOG(INFO) << "Dumping performance metrics to performanceMetrics.json file"; auto performanceMetrics = o2::monitoring::ProcessMonitor::getAvailableMetricsNames(); performanceMetrics.push_back("arrow-bytes-delta"); + performanceMetrics.push_back("aod-bytes-read-uncompressed"); + performanceMetrics.push_back("aod-bytes-read-compressed"); ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, driverInfo.metrics, deviceSpecs, performanceMetrics); } // This is a clean exit. Before we do so, if required, From 2c42d3dea64b083043f4c0a36ced86f36dc6502c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 24 Nov 2020 14:23:03 +0100 Subject: [PATCH 1414/1751] CcdbApi: A little bit of thread safety --- CCDB/include/CCDB/CcdbApi.h | 2 -- CCDB/src/CcdbApi.cxx | 23 ++++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index 9b7612caab445..f4f196daf2702 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -407,8 +407,6 @@ class CcdbApi //: public DatabaseInterface std::string mUrl{}; std::string mSnapshotTopPath{}; bool mInSnapshotMode = false; - mutable std::multimap<std::string, std::string> mHeaderData; //! a "global" internal data structure that can be filled with HTTP header information - // (without need to recreate this structure locally each time) mutable TGrid* mAlienInstance = nullptr; // a cached connection to TGrid (needed for Alien locations) bool mHaveAlienToken = false; // stores if an alien token is available diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 428994666408f..67af9af6e638f 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -707,6 +707,11 @@ void* CcdbApi::interpretAsTMemFileAndExtract(char* contentptr, size_t contentsiz // navigate sequence of URLs until TFile content is found; object is extracted and returned void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string const& url, TClass* cl, std::map<string, string>* headers) const { + // a global internal data structure that can be filled with HTTP header information + // static --> to avoid frequent alloc/dealloc as optimization + // not sure if thread_local takes away that benefit + static thread_local std::multimap<std::string, std::string> headerData; + // let's see first of all if the url is something specific that curl cannot handle if (url.find("alien:/", 0) != std::string::npos) { return downloadAlienContent(url, cl); @@ -722,9 +727,9 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); // if redirected , we tell libcurl NOT to follow redirection curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 0L); - curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_map_callback<decltype(mHeaderData)>); - mHeaderData.clear(); - curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void*)&mHeaderData); + curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_map_callback<decltype(headerData)>); + headerData.clear(); + curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void*)&headerData); MemoryStruct chunk{(char*)malloc(1), 0}; @@ -739,7 +744,7 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con bool cachingflag = false; if (res == CURLE_OK && curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &response_code) == CURLE_OK) { if (headers) { - for (auto& p : mHeaderData) { + for (auto& p : headerData) { (*headers)[p.first] = p.second; } } @@ -759,14 +764,14 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con // 1st: The "Location" field // 2nd: Possible "Content-Location" fields - Location field std::vector<std::string> locs; - auto iter = mHeaderData.find("Location"); - if (iter != mHeaderData.end()) { + auto iter = headerData.find("Location"); + if (iter != headerData.end()) { locs.push_back(iter->second); } // add alternative locations (not yet included) - auto iter2 = mHeaderData.find("Content-Location"); - if (iter2 != mHeaderData.end()) { - auto range = mHeaderData.equal_range("Content-Location"); + auto iter2 = headerData.find("Content-Location"); + if (iter2 != headerData.end()) { + auto range = headerData.equal_range("Content-Location"); for (auto it = range.first; it != range.second; ++it) { if (std::find(locs.begin(), locs.end(), it->second) == locs.end()) { locs.push_back(it->second); From 7990fe2d0ca10902fc67506af619006562fdfe7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Tue, 24 Nov 2020 17:45:25 +0100 Subject: [PATCH 1415/1751] Fix unit in axis title (#4889) --- Analysis/Tasks/PWGHF/qaTask.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Analysis/Tasks/PWGHF/qaTask.cxx b/Analysis/Tasks/PWGHF/qaTask.cxx index a65c1da80e821..805eb4b444500 100644 --- a/Analysis/Tasks/PWGHF/qaTask.cxx +++ b/Analysis/Tasks/PWGHF/qaTask.cxx @@ -186,12 +186,12 @@ struct QAGlobalObservables { {{nBinsNumberOfTracks, numberOfTracksRange[0], numberOfTracksRange[1]}}); // covariance histograms - histograms.add("Covariance/xx", "xx;Cov_{xx} [cm]", kTH1D, {{200, -0.1, 0.1}}); - histograms.add("Covariance/xy", "xy;Cov_{xy} [cm]", kTH1D, {{200, -0.1, 0.1}}); - histograms.add("Covariance/xz", "xz;Cov_{xz} [cm]", kTH1D, {{200, -0.1, 0.1}}); - histograms.add("Covariance/yy", "yy;Cov_{yy} [cm]", kTH1D, {{200, -0.1, 0.1}}); - histograms.add("Covariance/yz", "yz;Cov_{yz} [cm]", kTH1D, {{200, -0.1, 0.1}}); - histograms.add("Covariance/zz", "zz;Cov_{zz} [cm]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/xx", "xx;Cov_{xx} [cm^{2}]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/xy", "xy;Cov_{xy} [cm^{2}]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/xz", "xz;Cov_{xz} [cm^{2}]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/yy", "yy;Cov_{yy} [cm^{2}]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/yz", "yz;Cov_{yz} [cm^{2}]", kTH1D, {{200, -0.1, 0.1}}); + histograms.add("Covariance/zz", "zz;Cov_{zz} [cm^{2}]", kTH1D, {{200, -0.1, 0.1}}); // quality histograms histograms.add("Quality/Chi2", "#Chi^{2};#Chi^{2}", kTH1D, {{100, 0, 10}}); From 8f422b6dd8a524d510523aa34b5779482fcba4b9 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 24 Nov 2020 10:42:28 +0100 Subject: [PATCH 1416/1751] Indexed access to track references only via MCKinematicsReader Simplify processing of track references during transport simulation with benefit of less storage/less IO/less merging logic. Instead, build indexed access to track references in the background of MCKinematicsReader which should be the default path to read such information anyway. --- .../DetectorsCommonDataFormats/SimTraits.h | 2 +- .../include/SimulationDataFormat/Stack.h | 3 -- DataFormats/simulation/src/Stack.cxx | 11 ------ Steer/include/Steer/MCKinematicsReader.h | 11 +++--- Steer/src/MCKinematicsReader.cxx | 39 +++++++++++++++---- Steer/src/O2MCApplication.cxx | 1 - macro/duplicateHits.C | 1 - run/CMakeLists.txt | 4 +- run/O2HitMerger.h | 9 ----- run/checkStack.cxx | 38 ++++++++---------- 10 files changed, 58 insertions(+), 61 deletions(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h index 332f8a42010be..3c408b12bef84 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h @@ -97,7 +97,7 @@ class SimTraits // branches that are related to kinematics and general event information static inline const std::vector<std::string> KINEMATICSBRANCHES = - {"MCTrack", "MCEventHeader", "TrackRefs", "IndexedTrackRefs"}; + {"MCTrack", "MCEventHeader", "TrackRefs"}; ClassDefNV(SimTraits, 1); }; diff --git a/DataFormats/simulation/include/SimulationDataFormat/Stack.h b/DataFormats/simulation/include/SimulationDataFormat/Stack.h index 6f4f6f9f1358c..a373787c481cd 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/Stack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/Stack.h @@ -18,7 +18,6 @@ #include "DetectorsCommonDataFormats/DetID.h" #include "FairGenericStack.h" #include "SimulationDataFormat/MCTrack.h" -#include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/TrackReference.h" #include "SimulationDataFormat/MCEventStats.h" #include "Rtypes.h" @@ -284,8 +283,6 @@ class Stack : public FairGenericStack // storage for track references std::vector<o2::TrackReference>* mTrackRefs = nullptr; //! - o2::dataformats::MCTruthContainer<o2::TrackReference>* mIndexedTrackRefs = nullptr; //! - /// a pointer to the current MCEventStats object o2::dataformats::MCEventStats* mMCEventStats = nullptr; //! diff --git a/DataFormats/simulation/src/Stack.cxx b/DataFormats/simulation/src/Stack.cxx index 49e3c5ebe1732..fbda8cb8f73b7 100644 --- a/DataFormats/simulation/src/Stack.cxx +++ b/DataFormats/simulation/src/Stack.cxx @@ -72,7 +72,6 @@ Stack::Stack(Int_t size) mMinHits(1), mEnergyCut(0.), mTrackRefs(new std::vector<o2::TrackReference>), - mIndexedTrackRefs(new typename std::remove_pointer<decltype(mIndexedTrackRefs)>::type), mIsG4Like(false) { auto vmc = TVirtualMC::GetMC(); @@ -518,14 +517,6 @@ void Stack::UpdateTrackIndex(TRefArray* detList) return a.getTrackID() < b.getTrackID(); }); - // make final indexed container for track references - // fill empty - for (auto& ref : *mTrackRefs) { - if (ref.getTrackID() >= 0) { - mIndexedTrackRefs->addElement(ref.getTrackID(), ref); - } - } - for (auto det : mActiveDetectors) { // update the track indices by delegating to specialized detector functions det->updateHitTrackIndices(mIndexMap); @@ -553,7 +544,6 @@ void Stack::Reset() mNumberOfPrimariesPopped = 0; mPrimaryParticles.clear(); mTrackRefs->clear(); - mIndexedTrackRefs->clear(); mTrackIDtoParticlesEntry.clear(); mHitCounter = 0; } @@ -562,7 +552,6 @@ void Stack::Register() { FairRootManager::Instance()->RegisterAny("MCTrack", mTracks, kTRUE); FairRootManager::Instance()->RegisterAny("TrackRefs", mTrackRefs, kTRUE); - FairRootManager::Instance()->RegisterAny("IndexedTrackRefs", mIndexedTrackRefs, kTRUE); } void Stack::Print(Int_t iVerbose) const diff --git a/Steer/include/Steer/MCKinematicsReader.h b/Steer/include/Steer/MCKinematicsReader.h index 8b6bc1cb63cb3..e83099b65818b 100644 --- a/Steer/include/Steer/MCKinematicsReader.h +++ b/Steer/include/Steer/MCKinematicsReader.h @@ -106,6 +106,7 @@ class MCKinematicsReader void loadTracksForSource(int source) const; void loadHeadersForSource(int source) const; void loadTrackRefsForSource(int source) const; + void initIndexedTrackRefs(std::vector<o2::TrackReference>& refs, o2::dataformats::MCTruthContainer<o2::TrackReference>& indexedrefs) const; DigitizationContext const* mDigitizationContext = nullptr; @@ -115,7 +116,7 @@ class MCKinematicsReader // a vector of tracks foreach source and each collision mutable std::vector<std::vector<std::vector<o2::MCTrack>>> mTracks; // the in-memory track container mutable std::vector<std::vector<o2::dataformats::MCEventHeader>> mHeaders; // the in-memory header container - mutable std::vector<std::vector<o2::dataformats::MCTruthContainer<o2::TrackReference>>> mTrackRefs; // the in-memory track ref container + mutable std::vector<std::vector<o2::dataformats::MCTruthContainer<o2::TrackReference>>> mIndexedTrackRefs; // the in-memory track ref container bool mInitialized = false; // whether initialized }; @@ -164,18 +165,18 @@ inline o2::dataformats::MCEventHeader const& MCKinematicsReader::getMCEventHeade inline gsl::span<o2::TrackReference> MCKinematicsReader::getTrackRefs(int source, int event, int track) const { - if (mTrackRefs[source].size() == 0) { + if (mIndexedTrackRefs[source].size() == 0) { loadTrackRefsForSource(source); } - return mTrackRefs[source][event].getLabels(track); + return mIndexedTrackRefs[source][event].getLabels(track); } inline const std::vector<o2::TrackReference>& MCKinematicsReader::getTrackRefsByEvent(int source, int event) const { - if (mTrackRefs[source].size() == 0) { + if (mIndexedTrackRefs[source].size() == 0) { loadTrackRefsForSource(source); } - return mTrackRefs[source][event].getTruthArray(); + return mIndexedTrackRefs[source][event].getTruthArray(); } inline gsl::span<o2::TrackReference> MCKinematicsReader::getTrackRefs(int event, int track) const diff --git a/Steer/src/MCKinematicsReader.cxx b/Steer/src/MCKinematicsReader.cxx index f75289f367521..293513d8a8ef6 100644 --- a/Steer/src/MCKinematicsReader.cxx +++ b/Steer/src/MCKinematicsReader.cxx @@ -11,12 +11,32 @@ #include "DetectorsCommonDataFormats/NameConf.h" #include "Steer/MCKinematicsReader.h" #include "SimulationDataFormat/MCEventHeader.h" +#include "SimulationDataFormat/TrackReference.h" #include <TChain.h> #include <vector> #include "FairLogger.h" using namespace o2::steer; +void MCKinematicsReader::initIndexedTrackRefs(std::vector<o2::TrackReference>& refs, o2::dataformats::MCTruthContainer<o2::TrackReference>& indexedrefs) const +{ + // sort trackrefs according to track index then according to track length + std::sort(refs.begin(), refs.end(), [](const o2::TrackReference& a, const o2::TrackReference& b) { + if (a.getTrackID() == b.getTrackID()) { + return a.getLength() < b.getLength(); + } + return a.getTrackID() < b.getTrackID(); + }); + + // make final indexed container for track references + indexedrefs.clear(); + for (auto& ref : refs) { + if (ref.getTrackID() >= 0) { + indexedrefs.addElement(ref.getTrackID(), ref); + } + } +} + void MCKinematicsReader::loadTracksForSource(int source) const { auto chain = mInputChains[source]; @@ -61,17 +81,22 @@ void MCKinematicsReader::loadTrackRefsForSource(int source) const auto chain = mInputChains[source]; if (chain) { // todo: get name from NameConfig - auto br = chain->GetBranch("IndexedTrackRefs"); + auto br = chain->GetBranch("TrackRefs"); if (br) { - o2::dataformats::MCTruthContainer<o2::TrackReference>* refs = nullptr; + std::vector<o2::TrackReference>* refs = nullptr; br->SetAddress(&refs); - mTrackRefs[source].resize(br->GetEntries()); + mIndexedTrackRefs[source].resize(br->GetEntries()); for (int event = 0; event < br->GetEntries(); ++event) { br->GetEntry(event); - mTrackRefs[source][event] = *refs; + if (refs) { + // we convert the original flat vector into an indexed structure + initIndexedTrackRefs(*refs, mIndexedTrackRefs[source][event]); + delete refs; + refs = nullptr; + } } } else { - LOG(WARN) << "IndexedTrackRefs branch not found"; + LOG(WARN) << "TrackRefs branch not found"; } } } @@ -96,7 +121,7 @@ bool MCKinematicsReader::initFromDigitContext(std::string_view name) // load the kinematics information mTracks.resize(mInputChains.size()); mHeaders.resize(mInputChains.size()); - mTrackRefs.resize(mInputChains.size()); + mIndexedTrackRefs.resize(mInputChains.size()); // actual loading will be done only if someone asks // the first time for a particular source ... @@ -114,7 +139,7 @@ bool MCKinematicsReader::initFromKinematics(std::string_view name) mInputChains.back()->AddFile(o2::base::NameConf::getMCKinematicsFileName(name.data()).c_str()); mTracks.resize(1); mHeaders.resize(1); - mTrackRefs.resize(1); + mIndexedTrackRefs.resize(1); mInitialized = true; return true; diff --git a/Steer/src/O2MCApplication.cxx b/Steer/src/O2MCApplication.cxx index 57d70317c24c3..f31ea54e84679 100644 --- a/Steer/src/O2MCApplication.cxx +++ b/Steer/src/O2MCApplication.cxx @@ -248,7 +248,6 @@ void O2MCApplication::SendData() attachSubEventInfo(simdataparts, *mSubEventInfo); auto tracks = attachBranch<std::vector<o2::MCTrack>>("MCTrack", *mSimDataChannel, simdataparts); attachBranch<std::vector<o2::TrackReference>>("TrackRefs", *mSimDataChannel, simdataparts); - attachBranch<o2::dataformats::MCTruthContainer<o2::TrackReference>>("IndexedTrackRefs", *mSimDataChannel, simdataparts); assert(tracks->size() == mSubEventInfo->npersistenttracks); for (auto det : listActiveDetectors) { diff --git a/macro/duplicateHits.C b/macro/duplicateHits.C index 3dbe8511b958c..2acfbedd419e0 100644 --- a/macro/duplicateHits.C +++ b/macro/duplicateHits.C @@ -172,7 +172,6 @@ void duplicateHits(const char* filebase = "o2sim", const char* newfilebase = "o2 duplicate<o2::dataformats::MCEventHeader>(kintree, "MCEventHeader.", newkintree, factor); // TODO: fix EventIDs in the newly created MCEventHeaders duplicate<o2::TrackReference>(kintree, "TrackRefs", newkintree, factor); - duplicate<o2::dataformats::MCTruthContainer<o2::TrackReference>>(kintree, "IndexedTrackRefs", newkintree, factor); newkintree->Write(); // duplicating hits diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index 5ad1e169afb20..f1e0bfadcaa14 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -167,7 +167,7 @@ o2_add_test(CheckStackG4 NAME o2sim_checksimkinematics_G4 WORKING_DIRECTORY ${SIMTESTDIR} COMMAND_LINE_ARGS o2simG4 - PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::Steer NO_BOOST_TEST LABELS "g4;sim;long") @@ -206,7 +206,7 @@ o2_add_test(CheckStackG3 NAME o2sim_checksimkinematics_G3 WORKING_DIRECTORY ${SIMTESTDIR} COMMAND_LINE_ARGS o2simG3 - PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::Steer NO_BOOST_TEST LABELS "g3;sim;long") diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 1815fe4ed5eff..36ddc26c5ff24 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -262,7 +262,6 @@ class O2HitMerger : public FairMQDevice fillSubEventInfoEntry(info); consumeData<std::vector<o2::MCTrack>>(info.eventID, "MCTrack", data, index); consumeData<std::vector<o2::TrackReference>>(info.eventID, "TrackRefs", data, index); - consumeData<o2::dataformats::MCTruthContainer<o2::TrackReference>>(info.eventID, "IndexedTrackRefs", data, index); while (index < data.Size()) { consumeHits(info.eventID, data, index); } @@ -325,13 +324,6 @@ class O2HitMerger : public FairMQDevice { std::copy(from.begin(), from.end(), std::back_inserter(to)); } - // specialization for o2::MCTruthContainer<S> - template <typename S> - void backInsert(o2::dataformats::MCTruthContainer<S> const& from, - o2::dataformats::MCTruthContainer<S>& to) - { - to.mergeAtBack(from); - } void reorderAndMergeMCTRacks(TTree& origin, TTree& target, const std::vector<int>& nprimaries, const std::vector<int>& nsubevents) { @@ -610,7 +602,6 @@ class O2HitMerger : public FairMQDevice reorderAndMergeMCTRacks(*tree, *mOutTree, nprimaries, subevOrdered); Int_t ioffset = 0; remapTrackIdsAndMerge<std::vector<o2::TrackReference>>("TrackRefs", *tree, *mOutTree, trackoffsets, nprimaries, subevOrdered); - merge<o2::dataformats::MCTruthContainer<o2::TrackReference>>("IndexedTrackRefs", *tree, *mOutTree); // c) do the merge procedure for all hits ... delegate this to detector specific functions // since they know about types; number of branches; etc. diff --git a/run/checkStack.cxx b/run/checkStack.cxx index 42c3dd0c53900..79da689a4eeb4 100644 --- a/run/checkStack.cxx +++ b/run/checkStack.cxx @@ -15,6 +15,7 @@ #include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/Stack.h" #include "SimulationDataFormat/TrackReference.h" +#include "Steer/MCKinematicsReader.h" #include "TFile.h" #include "TTree.h" #ifdef NDEBUG @@ -46,16 +47,13 @@ int main(int argc, char** argv) assert(refbr); refbr->SetAddress(&trackrefs); - o2::dataformats::MCTruthContainer<o2::TrackReference>* indexedtrackrefs = nullptr; - auto irefbr = tr->GetBranch("IndexedTrackRefs"); - irefbr->SetAddress(&indexedtrackrefs); + o2::steer::MCKinematicsReader mcreader(nameprefix, o2::steer::MCKinematicsReader::Mode::kMCKine); - for (int i = 0; i < mcbr->GetEntries(); ++i) { - mcbr->GetEntry(i); - refbr->GetEntry(i); - irefbr->GetEntry(i); - LOG(DEBUG) << "-- Entry --" << i << "\n"; - LOG(DEBUG) << "Have " << mctracks->size() << " tracks \n"; + for (int eventID = 0; eventID < mcbr->GetEntries(); ++eventID) { + mcbr->GetEntry(eventID); + refbr->GetEntry(eventID); + LOG(DEBUG) << "-- Entry --" << eventID; + LOG(DEBUG) << "Have " << mctracks->size() << " tracks"; int ti = 0; // record tracks that left a hit in TPC @@ -68,24 +66,22 @@ int main(int argc, char** argv) if (t.leftTrace(o2::detectors::DetID::TPC)) { trackidsinTPC.emplace_back(ti); } - LOG(DEBUG) << " track " << ti << "\t" << t.getMotherTrackId() << " hits " << t.hasHits() << "\n"; + LOG(DEBUG) << " track " << ti << "\t" << t.getMotherTrackId() << " hits " << t.hasHits(); ti++; } - LOG(DEBUG) << "Have " << trackidsinTPC.size() << " tracks with hits in TPC\n"; - LOG(DEBUG) << "Have " << trackrefs->size() << " track refs \n"; - LOG(DEBUG) << "Have " << indexedtrackrefs->getIndexedSize() << " mapped tracks\n"; - LOG(DEBUG) << "Have " << indexedtrackrefs->getNElements() << " track refs\n"; + LOG(DEBUG) << "Have " << trackidsinTPC.size() << " tracks with hits in TPC"; + LOG(DEBUG) << "Have " << trackrefs->size() << " track refs"; + // check correct working of MCKinematicsReader bool havereferences = trackrefs->size(); if (havereferences) { - for (auto& i : trackidsinTPC) { - auto labels = indexedtrackrefs->getLabels(i); - assert(labels.size() > 0); - LOG(DEBUG) << " Track " << i << " has " << labels.size() << " TrackRefs " - << "\n"; - for (int j = 0; j < labels.size(); ++j) { - LOG(DEBUG) << labels[j]; + for (auto& trackID : trackidsinTPC) { + auto trackrefs = mcreader.getTrackRefs(eventID, trackID); + assert(trackrefs.size() > 0); + LOG(DEBUG) << " Track " << trackID << " has " << trackrefs.size() << " TrackRefs"; + for (auto& ref : trackrefs) { + assert(ref.getTrackID() == trackID); } } } From d26468badfb282ed0f4b85e279e795d2856a496b Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 24 Nov 2020 11:51:13 +0100 Subject: [PATCH 1417/1751] Add missing include --- DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h | 1 + 1 file changed, 1 insertion(+) diff --git a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h index 4ecf56013a65a..25cc2274e3dec 100644 --- a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h +++ b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h @@ -33,6 +33,7 @@ #pragma link C++ class vector < o2::ft0::ChannelDataFloat> + ; #pragma link C++ class o2::ft0::MCLabel + ; +#include "SimulationDataFormat/MCTruthContainer.h" #pragma link C++ class o2::dataformats::MCTruthContainer < o2::ft0::MCLabel> + ; #pragma link C++ class o2::ft0::HitType + ; From f2db4809ff043d87b7e92bbcd6e5724e44a3df0d Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaya@cern.ch> Date: Tue, 24 Nov 2020 19:19:46 +0100 Subject: [PATCH 1418/1751] add EventStatusWord to CTF and minor fix (#4911) * add EventStatusWord to CTF * minor fix --- .../FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h | 6 ++++- .../include/FT0Reconstruction/CTFCoder.h | 22 +++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h index 407fba225fc1d..5bb219a4b657e 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h @@ -55,6 +55,10 @@ class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> // put here code for raw data checking void sanityCheck(bool& flag) { + if (DataBlockWrapper<RawDataPM>::mNelements == 0) { + flag = false; + return; + } if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) { DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling } @@ -105,4 +109,4 @@ class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, R } // namespace ft0 } // namespace o2 -#endif \ No newline at end of file +#endif diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index c6a922c529244..3e34be0154560 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -164,18 +164,18 @@ void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& cha const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtcChain[icc]); // // rebuild digit - if (std::abs(chan.CFDTime) < Geometry::mTime_trg_gate) { - if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side - amplA += chan.QTCAmpl; - timeA += chan.CFDTime; - trig.nChanA++; - - } else { - amplC += chan.QTCAmpl; - timeC += chan.CFDTime; - trig.nChanC++; - } + // if (std::abs(chan.CFDTime) < Geometry::mTime_trg_gate) { + if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side + amplA += chan.QTCAmpl; + timeA += chan.CFDTime; + trig.nChanA++; + + } else { + amplC += chan.QTCAmpl; + timeC += chan.CFDTime; + trig.nChanC++; } + // } } if (trig.nChanA) { trig.timeA = timeA / trig.nChanA; From 0b66d7fa7daadf5a2bd5e3662524d1c9d72e610f Mon Sep 17 00:00:00 2001 From: Nazar Burmasov <nazar.burmasov@cern.ch> Date: Wed, 25 Nov 2020 00:54:28 +0300 Subject: [PATCH 1419/1751] Switched from ITS-TPC tracks to vertices in minBC/maxBC finder function. Adapted event selection and multiplicity tasks for Run 3. (#4905) * Switched from ITS-TPC tracks to vertices in minBC/maxBC finder function * Adapted event selection and multiplicity tasks for Run 3 --- .../include/Analysis/EventSelection.h | 29 ++--- Analysis/Tasks/CMakeLists.txt | 2 +- Analysis/Tasks/eventSelection.cxx | 109 ++++++++++++++++-- Analysis/Tasks/eventSelectionQa.cxx | 11 +- Analysis/Tasks/multiplicityQa.cxx | 16 ++- Analysis/Tasks/multiplicityTable.cxx | 61 +++++++++- .../AODProducerWorkflowSpec.h | 4 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 33 +++--- 8 files changed, 219 insertions(+), 46 deletions(-) diff --git a/Analysis/DataModel/include/Analysis/EventSelection.h b/Analysis/DataModel/include/Analysis/EventSelection.h index 198db13e00b7a..fee80c47b7094 100644 --- a/Analysis/DataModel/include/Analysis/EventSelection.h +++ b/Analysis/DataModel/include/Analysis/EventSelection.h @@ -19,18 +19,19 @@ namespace evsel { // TODO bool arrays are not supported? Storing in int32 for the moment DECLARE_SOA_COLUMN(Alias, alias, int32_t[kNaliases]); -DECLARE_SOA_COLUMN(BBT0A, bbT0A, bool); // beam-beam time in T0A -DECLARE_SOA_COLUMN(BBT0C, bbT0C, bool); // beam-beam time in T0C -DECLARE_SOA_COLUMN(BBV0A, bbV0A, bool); // beam-beam time in V0A -DECLARE_SOA_COLUMN(BBV0C, bbV0C, bool); // beam-beam time in V0C -DECLARE_SOA_COLUMN(BGV0A, bgV0A, bool); // beam-gas time in V0A -DECLARE_SOA_COLUMN(BGV0C, bgV0C, bool); // beam-gas time in V0C -DECLARE_SOA_COLUMN(BBZNA, bbZNA, bool); // beam-beam time in ZNA -DECLARE_SOA_COLUMN(BBZNC, bbZNC, bool); // beam-beam time in ZNC -DECLARE_SOA_COLUMN(BBFDA, bbFDA, bool); // beam-beam time in FDA -DECLARE_SOA_COLUMN(BBFDC, bbFDC, bool); // beam-beam time in FDC -DECLARE_SOA_COLUMN(BGFDA, bgFDA, bool); // beam-gas time in FDA -DECLARE_SOA_COLUMN(BGFDC, bgFDC, bool); // beam-gas time in FDC +DECLARE_SOA_COLUMN(BBT0A, bbT0A, bool); // beam-beam time in T0A +DECLARE_SOA_COLUMN(BBT0C, bbT0C, bool); // beam-beam time in T0C +DECLARE_SOA_COLUMN(BBV0A, bbV0A, bool); // beam-beam time in V0A +DECLARE_SOA_COLUMN(BBV0C, bbV0C, bool); // beam-beam time in V0C +DECLARE_SOA_COLUMN(BGV0A, bgV0A, bool); // beam-gas time in V0A +DECLARE_SOA_COLUMN(BGV0C, bgV0C, bool); // beam-gas time in V0C +DECLARE_SOA_COLUMN(BBZNA, bbZNA, bool); // beam-beam time in ZNA +DECLARE_SOA_COLUMN(BBZNC, bbZNC, bool); // beam-beam time in ZNC +DECLARE_SOA_COLUMN(BBFDA, bbFDA, bool); // beam-beam time in FDA +DECLARE_SOA_COLUMN(BBFDC, bbFDC, bool); // beam-beam time in FDC +DECLARE_SOA_COLUMN(BGFDA, bgFDA, bool); // beam-gas time in FDA +DECLARE_SOA_COLUMN(BGFDC, bgFDC, bool); // beam-gas time in FDC +DECLARE_SOA_COLUMN(FoundFT0, foundFT0, int64_t); // the nearest FT0 signal DECLARE_SOA_DYNAMIC_COLUMN(SEL7, sel7, [](bool bbV0A, bool bbV0C, bool bbZNA, bool bbZNC) -> bool { return bbV0A && bbV0C && bbZNA && bbZNC; }); DECLARE_SOA_DYNAMIC_COLUMN(SEL8, sel8, [](bool bbT0A, bool bbT0C, bool bbZNA, bool bbZNC) -> bool { return bbT0A && bbT0C && bbZNA && bbZNC; }); } // namespace evsel @@ -39,7 +40,9 @@ DECLARE_SOA_TABLE(EvSels, "AOD", "EVSEL", evsel::BBT0A, evsel::BBT0C, evsel::BBV0A, evsel::BBV0C, evsel::BGV0A, evsel::BGV0C, evsel::BBZNA, evsel::BBZNC, evsel::BBFDA, evsel::BBFDC, evsel::BGFDA, evsel::BGFDC, - evsel::SEL7<evsel::BBV0A, evsel::BBV0C, evsel::BBZNA, evsel::BBZNC>); + evsel::SEL7<evsel::BBV0A, evsel::BBV0C, evsel::BBZNA, evsel::BBZNC>, + evsel::SEL8<evsel::BBT0A, evsel::BBT0C, evsel::BBZNA, evsel::BBZNC>, + evsel::FoundFT0); using EvSel = EvSels::iterator; } // namespace o2::aod diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 37006fd177484..662a3090d1ec0 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -50,7 +50,7 @@ o2_add_dpl_workflow(validation o2_add_dpl_workflow(event-selection SOURCES eventSelection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::CCDB O2::CommonConstants COMPONENT_NAME Analysis) o2_add_dpl_workflow(event-selection-qa diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index 084ec4dc02404..f0b83b41a3053 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -7,15 +7,25 @@ // 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/ConfigParamSpec.h" + +using namespace o2; +using namespace o2::framework; + +// custom configurable for switching between run2 and run3 selection types +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{"selection-run", VariantType::Int, 2, {"selection type: 2 - run 2, 3 - run 3"}}); +} + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Analysis/EventSelection.h" #include "Analysis/TriggerAliases.h" #include <CCDB/BasicCCDBManager.h> - -using namespace o2; -using namespace o2::framework; +#include "CommonConstants/LHCConstants.h" struct EvSelParameters { // time-of-flight offset @@ -123,12 +133,97 @@ struct EventSelectionTask { } // Fill event selection columns - evsel(alias, bbT0A, bbT0C, bbV0A, bbV0C, bgV0A, bgV0C, bbZNA, bbZNC, bbFDA, bbFDC, bgFDA, bgFDC); + int64_t foundFT0 = -1; // this column is not used in run2 analysis + evsel(alias, bbT0A, bbT0C, bbV0A, bbV0C, bgV0A, bgV0C, bbZNA, bbZNC, bbFDA, bbFDC, bgFDA, bgFDC, foundFT0); } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +// helper table and task for BCs<-->FT0s matching +namespace o2::aod { - return WorkflowSpec{ - adaptAnalysisTask<EventSelectionTask>("event-selection")}; +DECLARE_SOA_INDEX_TABLE_USER(SparseBCsFT0s, BCs, "MA_SP_BCS_FT0S", o2::aod::indices::BCId, o2::aod::indices::FT0Id); } + +struct EventSelectionTaskRun3Helper { + Builds<aod::SparseBCsFT0s> matchedBCsFT0s; + void process(aod::BCs, aod::FT0s) + { + } +}; + +struct EventSelectionTaskRun3 { + Produces<aod::EvSels> evsel; + + EvSelParameters par; + + void process(aod::Collision const& collision, aod::SparseBCsFT0s const& matchedBCsFT0s, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FT0s const& ft0s, aod::FDDs const& fdds) + { + // calculating [minBC, maxBC] range for a collision + int deltaBC = std::ceil(collision.collisionTimeRes() / o2::constants::lhc::LHCBunchSpacingNS * 4); + int64_t colBC = collision.bc().globalBC(); + int64_t maxColBC = colBC + deltaBC; + int64_t minColBC = colBC - deltaBC; + + int64_t minFt0Dist = INT32_MAX; + int64_t foundFT0 = -1; + float timeA = -999.f; + float timeC = -999.f; + + // calculating BCID iteration range + int64_t minGlobalBC = bcs.begin().globalBC(); + int64_t maxGlobalBC = bcs.iteratorAt(bcs.size() - 1).globalBC(); + int64_t startIt = minColBC - minGlobalBC; + int64_t endIt = maxColBC - minGlobalBC; + + // iterating only through relevant BCIDs and + // searching for the nearest FT0 + for (int64_t i = startIt; i <= endIt; i++) { + auto matched = matchedBCsFT0s.iteratorAt(i); + if (matched.has_ft0() == false) { + continue; + } + auto bc = bcs.iteratorAt(i); + int64_t ft0BC = bc.globalBC(); + int64_t ft0Dist = abs(ft0BC - colBC); + if (ft0Dist < minFt0Dist) { + minFt0Dist = ft0Dist; + foundFT0 = matched.ft0().globalIndex(); + } + } + + if (minFt0Dist != INT32_MAX) { + auto ft0 = ft0s.iteratorAt(foundFT0); + timeA = ft0.timeA(); + timeC = ft0.timeC(); + } + + bool bbZNA = 1; + bool bbZNC = 1; + bool bbV0A = 0; + bool bbV0C = 0; + bool bgV0A = 0; + bool bgV0C = 0; + bool bbFDA = 0; + bool bbFDC = 0; + bool bgFDA = 0; + bool bgFDC = 0; + bool bbT0A = timeA > par.fT0ABBlower && timeA < par.fT0ABBupper; + bool bbT0C = timeC > par.fT0CBBlower && timeC < par.fT0CBBupper; + + int32_t alias[kNaliases] = {0}; + // Fill event selection columns + // saving FT0 row index (foundFT0) for further analysis + evsel(alias, bbT0A, bbT0C, bbV0A, bbV0C, bgV0A, bgV0C, bbZNA, bbZNC, bbFDA, bbFDC, bgFDA, bgFDC, foundFT0); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& ctx) +{ + if (ctx.options().get<int>("selection-run") == 2) { + return WorkflowSpec{adaptAnalysisTask<EventSelectionTask>("event-selection")}; + } else { + return WorkflowSpec{ + adaptAnalysisTask<EventSelectionTaskRun3Helper>("event-selection-helper"), + adaptAnalysisTask<EventSelectionTaskRun3>("event-selection")}; + } +} \ No newline at end of file diff --git a/Analysis/Tasks/eventSelectionQa.cxx b/Analysis/Tasks/eventSelectionQa.cxx index 3b629d5f95d58..95a2d55000c35 100644 --- a/Analysis/Tasks/eventSelectionQa.cxx +++ b/Analysis/Tasks/eventSelectionQa.cxx @@ -89,6 +89,7 @@ struct EventSelectionTask { OutputObj<TH1F> hTimeFDCacc{TH1F("hTimeFDCacc", "", 1000, -100., 100.)}; Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; + Configurable<int> selection{"sel", 7, "trigger: 7 - sel7, 8 - sel8"}; void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& col, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::FT0s ft0s, aod::FDDs fdds) { @@ -113,10 +114,18 @@ struct EventSelectionTask { hTimeFDAall->Fill(fdd.timeA()); hTimeFDCall->Fill(fdd.timeC()); - if (!col.sel7()) { + if (selection == 7 && !col.sel7()) { return; } + if (selection == 8 && !col.sel8()) { + return; + } + + if (selection != 7 && selection != 8) { + LOGF(fatal, "Unknown selection type! Use `--sel 7` or `--sel 8`"); + } + hTimeV0Aacc->Fill(fv0a.time()); hTimeV0Cacc->Fill(fv0c.time()); hTimeZNAacc->Fill(zdc.timeZNA()); diff --git a/Analysis/Tasks/multiplicityQa.cxx b/Analysis/Tasks/multiplicityQa.cxx index c3332b31d505e..e1e031f0e3b2c 100644 --- a/Analysis/Tasks/multiplicityQa.cxx +++ b/Analysis/Tasks/multiplicityQa.cxx @@ -27,15 +27,27 @@ struct MultiplicityQaTask { OutputObj<TProfile> hMultNtrackletsVsV0M{TProfile("hMultNtrackletsVsV0M", "", 50000, 0., 50000.)}; + Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; + Configurable<int> selection{"sel", 7, "trigger: 7 - sel7, 8 - sel8"}; + void process(soa::Join<aod::Collisions, aod::EvSels, aod::Mults>::iterator const& col) { - if (!col.alias()[kINT7]) { + if (!isMC && !col.alias()[kINT7]) { return; } - if (!col.sel7()) { + + if (selection == 7 && !col.sel7()) { return; } + if (selection == 8 && !col.sel8()) { + return; + } + + if (selection != 7 && selection != 8) { + LOGF(fatal, "Unknown selection type! Use `--sel 7` or `--sel 8`"); + } + LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multV0M=%5.0f multT0A=%5.0f multT0C=%5.0f multT0M=%5.0f", col.multV0A(), col.multV0C(), col.multV0M(), col.multT0A(), col.multT0C(), col.multT0M()); // fill calibration histos hMultV0M->Fill(col.multV0M()); diff --git a/Analysis/Tasks/multiplicityTable.cxx b/Analysis/Tasks/multiplicityTable.cxx index e79d2f70e21a6..bab242d959868 100644 --- a/Analysis/Tasks/multiplicityTable.cxx +++ b/Analysis/Tasks/multiplicityTable.cxx @@ -7,14 +7,23 @@ // 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/ConfigParamSpec.h" + +using namespace o2; +using namespace o2::framework; + +// custom configurable for switching between run2 and run3 selection types +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{"selection-run", VariantType::Int, 2, {"selection type: 2 - run 2, 3 - run 3"}}); +} + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Analysis/EventSelection.h" #include "Analysis/Multiplicity.h" #include "iostream" -using namespace o2; -using namespace o2::framework; struct MultiplicityTableTaskIndexed { Produces<aod::Mults> mult; @@ -61,8 +70,50 @@ struct MultiplicityTableTaskIndexed { } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +struct MultiplicityTableTaskRun3 { + Produces<aod::Mults> mult; + Partition<aod::Tracks> tracklets = (aod::track::trackType == static_cast<uint8_t>(o2::aod::track::TrackTypeEnum::Run2Tracklet)); + + void process(soa::Join<aod::Collisions, aod::EvSels> const& collisions, aod::Tracks const& tracks, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FT0s const& ft0s) + { + for (auto& collision : collisions) { + float multV0A = -1.f; + float multV0C = -1.f; + float multT0A = -1.f; + float multT0C = -1.f; + float multZNA = -1.f; + float multZNC = -1.f; + int multTracklets = tracklets.size(); + + const float* aAmplitudesA; + const float* aAmplitudesC; + + // using FT0 row index from event selection task + int64_t foundFT0 = collision.foundFT0(); + + if (foundFT0 != -1) { + auto ft0 = ft0s.iteratorAt(foundFT0); + aAmplitudesA = ft0.amplitudeA(); + aAmplitudesC = ft0.amplitudeC(); + for (int i = 0; i < 96; i++) { + multT0A += aAmplitudesA[i]; + } + for (int i = 0; i < 112; i++) { + multT0C += aAmplitudesC[i]; + } + } + + LOGF(debug, "multV0A=%5.0f multV0C=%5.0f multT0A=%5.0f multT0C=%5.0f multZNA=%6.0f multZNC=%6.0f multTracklets=%i", multV0A, multV0C, multT0A, multT0C, multZNA, multZNC, multTracklets); + mult(multV0A, multV0C, multT0A, multT0C, multZNA, multZNC, multTracklets); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& ctx) { - return WorkflowSpec{ - adaptAnalysisTask<MultiplicityTableTaskIndexed>("multiplicity-table")}; + if (ctx.options().get<int>("selection-run") == 2) { + return WorkflowSpec{adaptAnalysisTask<MultiplicityTableTaskIndexed>("multiplicity-table")}; + } else { + return WorkflowSpec{adaptAnalysisTask<MultiplicityTableTaskRun3>("multiplicity-table")}; + } } diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 814ead3c15eeb..90254eeb2b660 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -18,7 +18,7 @@ #include "Framework/AnalysisHelpers.h" #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" -#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h" #include "TStopwatch.h" #include <CCDB/BasicCCDBManager.h> #include <string> @@ -91,7 +91,7 @@ class AODProducerWorkflowDPL : public Task uint64_t maxGlBC = 0; uint64_t minGlBC = INT64_MAX; - void findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC, const std::vector<o2::InteractionTimeRecord>& mcRecords); + void findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::vertexing::PVertex>& primVertices, const std::vector<o2::InteractionTimeRecord>& mcRecords); int64_t getTFNumber(uint64_t firstVtxGlBC, int runNumber); template <typename TracksType, typename TracksCursorType> diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 70e3f6190ad90..1b8075fb7a72a 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -44,7 +44,7 @@ using namespace o2::framework; namespace o2::aodproducer { -void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::dataformats::TrackTPCITS>& tracksITSTPC, const std::vector<o2::InteractionTimeRecord>& mcRecords) +void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::vertexing::PVertex>& primVertices, const std::vector<o2::InteractionTimeRecord>& mcRecords) { for (auto& ft0RecPoint : ft0RecPoints) { uint64_t bc = ft0RecPoint.getInteractionRecord().orbit * o2::constants::lhc::LHCMaxBunches + ft0RecPoint.getInteractionRecord().bc; @@ -56,14 +56,16 @@ void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& f } } - for (auto& trackITSTPC : tracksITSTPC) { - Double_t timeStamp = trackITSTPC.getTimeMUS().getTimeStamp() * 1.E3; // mus to ns - uint64_t bc = (uint64_t)(timeStamp / o2::constants::lhc::LHCBunchSpacingNS); - if (minGlBC > bc) { - minGlBC = bc; + for (auto& vertex : primVertices) { + const InteractionRecord& colIRMin = vertex.getIRMin(); + const InteractionRecord& colIRMax = vertex.getIRMax(); + uint64_t colBCMin = colIRMin.orbit * o2::constants::lhc::LHCMaxBunches + colIRMin.bc; + uint64_t colBCMax = colIRMax.orbit * o2::constants::lhc::LHCMaxBunches + colIRMax.bc; + if (minGlBC > colBCMin) { + minGlBC = colBCMin; } - if (maxGlBC < bc) { - maxGlBC = bc; + if (maxGlBC < colBCMax) { + maxGlBC = colBCMax; } } @@ -242,9 +244,9 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("tracksITSTPC"); auto tracksTPC = pc.inputs().get<gsl::span<o2::tpc::TrackTPC>>("trackTPC"); - LOG(INFO) << "FOUND " << tracksTPC.size() << " TPC tracks"; - LOG(INFO) << "FOUND " << tracksITS.size() << " ITS tracks"; - LOG(INFO) << "FOUND " << tracksITSTPC.size() << " ITCTPC tracks"; + LOG(DEBUG) << "FOUND " << tracksTPC.size() << " TPC tracks"; + LOG(DEBUG) << "FOUND " << tracksITS.size() << " ITS tracks"; + LOG(DEBUG) << "FOUND " << tracksITSTPC.size() << " ITCTPC tracks"; auto& bcBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "BC"}); auto& collisionsBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "COLLISION"}); @@ -254,8 +256,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto& timeFrameNumberBuilder = pc.outputs().make<uint64_t>(Output{"TFN", "TFNumber"}); auto& fv0aBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0A"}); - auto& fv0cBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0C"}); auto& fddBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FDD"}); + auto& fv0cBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0C"}); auto& zdcBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "ZDC"}); auto bcCursor = bcBuilder.cursor<o2::aod::BCs>(); @@ -274,10 +276,10 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) const auto& mcRecords = mcContext->getEventRecords(); const auto& mcParts = mcContext->getEventParts(); - LOG(INFO) << "FOUND " << mcRecords.size() << " records"; - LOG(INFO) << "FOUND " << mcParts.size() << " parts"; + LOG(DEBUG) << "FOUND " << mcRecords.size() << " records"; + LOG(DEBUG) << "FOUND " << mcParts.size() << " parts"; - findMinMaxBc(ft0RecPoints, tracksITSTPC, mcRecords); + findMinMaxBc(ft0RecPoints, primVertices, mcRecords); std::map<uint64_t, uint64_t> mGlobBC2BCID; @@ -435,6 +437,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) timeStamp.getTimeStamp(), timeStamp.getTimeStampError(), collisionTimeMask); + auto trackRef = primVer2TRefs[collisionID]; int start = trackRef.getFirstEntryOfSource(0); int ntracks = trackRef.getEntriesOfSource(0); From 6782c63186552bf1b0e5903000263a41851556aa Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 25 Nov 2020 00:14:39 +0100 Subject: [PATCH 1420/1751] DPL Analysis: actually delete a tree once done --- Framework/Core/src/AODReaderHelpers.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index a472f157ea60a..ca773afc0afae 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -303,6 +303,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() } } t2t.fill(tr); + delete tr; first = false; } From 2bd11f5855b911b2527043781d6bbb5b0feca799 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 25 Nov 2020 07:05:25 +0100 Subject: [PATCH 1421/1751] DPL Analysis: add metric for read calls (#4913) * DPL Analysis: add metric for read calls * Update DataInputDirector.h --- Framework/Core/src/AODReaderHelpers.cxx | 11 +++++++++++ Framework/Core/src/runDataProcessing.cxx | 1 + 2 files changed, 12 insertions(+) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index ca773afc0afae..9a0289a955596 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -245,6 +245,8 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() bool first = true; static size_t totalSizeUncompressed = 0; static size_t totalSizeCompressed = 0; + static size_t totalReadCalls = 0; + for (auto route : requestedTables) { // create header @@ -252,6 +254,11 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() auto dh = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); // create a TreeToTable object + auto info = didir->getFileFolder(dh, fcnt, ntf); + size_t before = 0; + if (info.file) { + info.file->GetReadCalls(); + } tr = didir->getDataTree(dh, fcnt, ntf); if (!tr) { if (first) { @@ -303,12 +310,16 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() } } t2t.fill(tr); + if (info.file) { + totalReadCalls += info.file->GetReadCalls() - before; + } delete tr; first = false; } monitoring.send(Metric{(uint64_t)totalSizeUncompressed, "aod-bytes-read-uncompressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); monitoring.send(Metric{(uint64_t)totalSizeCompressed, "aod-bytes-read-compressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)totalReadCalls, "aod-total-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); // save file number and time frame *fileCounter = (fcnt - device.inputTimesliceId) / device.maxInputTimeslices; diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index ebdc1e9e03001..3bfcb3d8b2dde 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1291,6 +1291,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, performanceMetrics.push_back("arrow-bytes-delta"); performanceMetrics.push_back("aod-bytes-read-uncompressed"); performanceMetrics.push_back("aod-bytes-read-compressed"); + performanceMetrics.push_back("aod-total-read-calls"); ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, driverInfo.metrics, deviceSpecs, performanceMetrics); } // This is a clean exit. Before we do so, if required, From 33a1ea90b3bd69884d4bc8ecac5b948d4a9fea60 Mon Sep 17 00:00:00 2001 From: frmanso <manso@clermont.in2p3.fr> Date: Wed, 25 Nov 2020 08:43:34 +0100 Subject: [PATCH 1422/1751] MFT cooling pipes between disks and patch panel (#4837) * MFT cooling pipes between disks and patch panel --- .../MFT/base/include/MFTBase/HeatExchanger.h | 1 + .../ITSMFT/MFT/base/src/HeatExchanger.cxx | 446 ++++++++++++++++++ 2 files changed, 447 insertions(+) diff --git a/Detectors/ITSMFT/MFT/base/include/MFTBase/HeatExchanger.h b/Detectors/ITSMFT/MFT/base/include/MFTBase/HeatExchanger.h index 6cff3879dc02b..c6794a1311ed3 100644 --- a/Detectors/ITSMFT/MFT/base/include/MFTBase/HeatExchanger.h +++ b/Detectors/ITSMFT/MFT/base/include/MFTBase/HeatExchanger.h @@ -42,6 +42,7 @@ class HeatExchanger void createHalfDisk3(Int_t half); void createHalfDisk4(Int_t half); void createManifold(Int_t disk); + void createCoolingPipes(Int_t half, Int_t disk); Double_t getWaterRadius() { return mRWater; } void setWaterRadius(Double_t& Rwater) { mRWater = Rwater; } diff --git a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx index b674159cdb603..334073c572f4a 100644 --- a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx @@ -1408,6 +1408,7 @@ void HeatExchanger::createHalfDisk0(Int_t half) mHalfDisk->AddNode(rohacellPlate, 1, transformation); createManifold(disk); + createCoolingPipes(half, disk); } //_____________________________________________________________________________ @@ -1957,6 +1958,7 @@ void HeatExchanger::createHalfDisk1(Int_t half) mHalfDisk->AddNode(rohacellPlate, 2, transformation); createManifold(disk); + createCoolingPipes(half, disk); } //_____________________________________________________________________________ @@ -2612,6 +2614,7 @@ void HeatExchanger::createHalfDisk2(Int_t half) mHalfDisk->AddNode(rohacellPlate, 2, transformation); createManifold(disk); + createCoolingPipes(half, disk); } //_____________________________________________________________________________ @@ -3160,6 +3163,7 @@ void HeatExchanger::createHalfDisk3(Int_t half) mHalfDisk->AddNode(rohacellPlate, 2, transformation); createManifold(disk); + createCoolingPipes(half, disk); } //_____________________________________________________________________________ @@ -3712,6 +3716,448 @@ void HeatExchanger::createHalfDisk4(Int_t half) mHalfDisk->AddNode(rohacellPlate, 2, transformation); createManifold(disk); + createCoolingPipes(half, disk); +} + +//_____________________________________________________________________________ +void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) +{ + mPipe = gGeoManager->GetMedium("MFT_Polyurethane$"); + mWater = gGeoManager->GetMedium("MFT_Water$"); + Float_t length1; + Float_t length2; + Float_t rin; + Float_t rout; + TGeoVolume* Tube1 = nullptr; + TGeoVolume* Torus1 = nullptr; + TGeoVolume* TubeW1 = nullptr; + TGeoVolume* TorusW1 = nullptr; + TGeoRotation* rTorus1 = nullptr; + TGeoCombiTrans* transfoTorus1 = nullptr; + Float_t radius1; + //----------------------------------------------------------------- + if (disk == 0 || disk == 1 || disk == 2) { + auto* mCoolingPipe1 = new TGeoVolumeAssembly(Form("cooling_pipe1_H%d", half)); + if (disk == 0) { + length1 = 1.3; + } + if (disk == 1) { + length1 = 0.87; + } + if (disk == 2) { + length1 = 0.45; + } + rin = 0.25 / 2; + rout = 0.4 / 2; + Tube1 = gGeoManager->MakeTube(Form("Tube1_H%d_D%d", half, disk), mPipe, rin, rout, length1 / 2); + TubeW1 = gGeoManager->MakeTube(Form("TubeW1_H%d_D%d", half, disk), mWater, 0., rin, length1 / 2); + TGeoTranslation* tTube1 = new TGeoTranslation(0.0, 0.0, 0.0); + tTube1->RegisterYourself(); + + radius1 = 0.4; + Torus1 = gGeoManager->MakeTorus(Form("Torus1_H%d_D%d", half, disk), mPipe, radius1, rin, rout, 0., 90.); + TorusW1 = gGeoManager->MakeTorus(Form("TorusW1_H%d_D%d", half, disk), mWater, radius1, 0., rin, 0., 90.); + rTorus1 = new TGeoRotation("rotationTorus1", 0.0, 90.0, 0.0); + rTorus1->RegisterYourself(); + transfoTorus1 = new TGeoCombiTrans(-radius1, 0., length1 / 2, rTorus1); + transfoTorus1->RegisterYourself(); + + if (disk == 0) { + length2 = 7.9; + } + if (disk == 1) { + length2 = 4.1; + } + if (disk == 2) { + length2 = 0.2; + } + TGeoVolume* Tube2 = gGeoManager->MakeTube(Form("Tube2_H%d_D%d", half, disk), mPipe, rin, rout, length2 / 2); + TGeoVolume* TubeW2 = gGeoManager->MakeTube(Form("TubeW2_H%d_D%d", half, disk), mWater, 0., rin, length2 / 2); + TGeoRotation* rTube2 = new TGeoRotation("rotationTube2", 90.0, 90.0, 0.0); + rTube2->RegisterYourself(); + TGeoCombiTrans* transfoTube2 = new TGeoCombiTrans(-length2 / 2 - radius1, 0., length1 / 2 + radius1, rTube2); + transfoTube2->RegisterYourself(); + + Float_t radius2 = 4.; + if (disk == 2) { + radius2 = 3.5; + } + TGeoVolume* Torus2 = gGeoManager->MakeTorus(Form("Torus2_H%d_D%d", half, disk), mPipe, radius2, rin, rout, 0., -90.); + TGeoVolume* TorusW2 = gGeoManager->MakeTorus(Form("TorusW2_H%d_D%d", half, disk), mWater, radius2, 0., rin, 0., -90.); + TGeoRotation* rTorus2 = new TGeoRotation("rotationTorus2", 180.0, 0.0, 0.0); + rTorus2->RegisterYourself(); + TGeoCombiTrans* transfoTorus2 = new TGeoCombiTrans(-length2 - radius1, -radius2, length1 / 2 + radius1, rTorus2); + transfoTorus2->RegisterYourself(); + + Float_t length3; + if (disk == 0) { + length3 = 4.18; + } + if (disk == 1) { + length3 = 4.10; + } + if (disk == 2) { + length3 = 4.54; + } + TGeoVolume* Tube3 = gGeoManager->MakeTube(Form("Tube3_H%d_D%d", half, disk), mPipe, rin, rout, length3 / 2); + TGeoVolume* TubeW3 = gGeoManager->MakeTube(Form("TubeW3_H%d_D%d", half, disk), mWater, 0., rin, length3 / 2); + TGeoRotation* rTube3 = new TGeoRotation("rotationTube3", 0.0, -90.0, 0.0); + rTube3->RegisterYourself(); + TGeoCombiTrans* transfoTube3 = new TGeoCombiTrans(-length2 - radius2 - radius1, -radius2 - length3 / 2, length1 / 2 + radius1, rTube3); + transfoTube3->RegisterYourself(); + + Float_t length4 = 14.0; // one single pipe instead of 3 pipes coming from the 3 first disks + Float_t rin4 = 0.216; + Float_t rout4 = 0.346; + TGeoVolume* Tube4 = gGeoManager->MakeTube(Form("Tube4_H%d_D%d", half, disk), mPipe, rin4, rout4, length4 / 2); + TGeoVolume* TubeW4 = gGeoManager->MakeTube(Form("TubeW4_H%d_D%d", half, disk), mWater, 0., rin4, length4 / 2); + Float_t theta4 = 8.0; // angle from the "horizontal" plane x,z + Float_t phi4 = 47.0; // "azimutal" angle + TGeoRotation* rTube4 = new TGeoRotation("rotationTube4", 90.0 + theta4, 90.0 + phi4, 0.0); + rTube4->RegisterYourself(); + // next line, the x and z axis are reversed in the location... + TGeoCombiTrans* transfoTube4 = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.5, -radius2 - length3 / 2 - 2.95, length1 / 2 + radius1 + 3.80, rTube4); + transfoTube4->RegisterYourself(); + + Float_t length5 = 16.5; // one single pipe instead of 3 pipes coming from the 3 first disks + Double_t theta = 180. * TMath::Pi() / 180.; + Double_t phi = 0. * TMath::Pi() / 180.; + Double_t nlow[3]; + nlow[0] = TMath::Sin(theta) * TMath::Cos(phi); + nlow[1] = TMath::Sin(theta) * TMath::Sin(phi); + nlow[2] = TMath::Cos(theta); + theta = 36. * TMath::Pi() / 180.; + phi = 270. * TMath::Pi() / 180.; + Double_t nhi[3]; + nhi[0] = TMath::Sin(theta) * TMath::Cos(phi); + nhi[1] = TMath::Sin(theta) * TMath::Sin(phi); + nhi[2] = TMath::Cos(theta); + Float_t rin5 = 0.278; + Float_t rout5 = 0.447; + TGeoVolume* Tube5 = gGeoManager->MakeCtub(Form("Tube5_H%d_D%d", half, disk), mPipe, rin5, rout5, length5 / 2, 0., 360., nlow[0], nlow[1], nlow[2], nhi[0], nhi[1], nhi[2]); + TGeoVolume* TubeW5 = gGeoManager->MakeCtub(Form("TubeW5_H%d_D%d", half, disk), mWater, 0., rin5, length5 / 2, 0., 360., nlow[0], nlow[1], nlow[2], nhi[0], nhi[1], nhi[2]); + Float_t theta5 = 11.0; // angle from the "horizontal" plane x,z + Float_t phi5 = 9.0; // "azimutal" angle + TGeoRotation* rTube5 = new TGeoRotation("rotationTube5", 90.0 + theta5, 90.0 + phi5, 0.0); + rTube5->RegisterYourself(); + TGeoCombiTrans* transfoTube5 = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.4 - TMath::Cos(phi4 * TMath::DegToRad()) * length4 / 2 - TMath::Cos(phi5 * TMath::DegToRad()) * length5 / 2, + -radius2 - length3 / 2 - 2.6 - TMath::Sin(theta4 * TMath::DegToRad()) * length4 / 2 - TMath::Sin(theta5 * TMath::DegToRad()) * length5 / 2, + length1 / 2 + radius1 + 3.8 + TMath::Sin(phi4 * TMath::DegToRad()) * length4 / 2 + TMath::Sin(phi5 * TMath::DegToRad()) * length5 / 2, rTube5); + transfoTube5->RegisterYourself(); + + Tube1->SetLineColor(kGray); + Torus1->SetLineColor(kGray); + Tube2->SetLineColor(kGray); + Torus2->SetLineColor(kGray); + Tube3->SetLineColor(kGray); + Tube4->SetLineColor(kGray); + Tube5->SetLineColor(kGray); + + mCoolingPipe1->AddNode(Tube1, 1, tTube1); + mCoolingPipe1->AddNode(Torus1, 1, transfoTorus1); + mCoolingPipe1->AddNode(Tube2, 1, transfoTube2); + mCoolingPipe1->AddNode(Torus2, 1, transfoTorus2); + mCoolingPipe1->AddNode(Tube3, 1, transfoTube3); + mCoolingPipe1->AddNode(TubeW1, 1, tTube1); + mCoolingPipe1->AddNode(TorusW1, 1, transfoTorus1); + mCoolingPipe1->AddNode(TubeW2, 1, transfoTube2); + mCoolingPipe1->AddNode(TorusW2, 1, transfoTorus2); + mCoolingPipe1->AddNode(TubeW3, 1, transfoTube3); + + if (disk == 0) { // to create only one time Tube4 and Tube5 + mCoolingPipe1->AddNode(Tube4, 1, transfoTube4); + mCoolingPipe1->AddNode(Tube5, 1, transfoTube5); + mCoolingPipe1->AddNode(TubeW4, 1, transfoTube4); + mCoolingPipe1->AddNode(TubeW5, 1, transfoTube5); + } + + //----------------------------------------------------------------- + auto* mCoolingPipe2 = new TGeoVolumeAssembly(Form("cooling_pipe2_H%d_D%d", half, disk)); + TGeoVolume* Tube1p = gGeoManager->MakeTube(Form("Tube1p_H%d_D%d", half, disk), mPipe, rin, rout, length1 / 2); + TGeoVolume* Torus1p = gGeoManager->MakeTorus(Form("Torus1p_H%d_D%d", half, disk), mPipe, radius1, rin, rout, 0., 90.); + TGeoVolume* Tube2p = gGeoManager->MakeTube(Form("Tube2p_H%d_D%d", half, disk), mPipe, rin, rout, length2 / 2); + TGeoVolume* Torus2p = gGeoManager->MakeTorus(Form("Torus2p_H%d_D%d", half, disk), mPipe, radius2, rin, rout, 0., 90.); + TGeoVolume* Tube3p = gGeoManager->MakeTube(Form("Tube3p_H%d_D%d", half, disk), mPipe, rin, rout, length3 / 2); + TGeoVolume* TubeW1p = gGeoManager->MakeTube(Form("TubeW1p_H%d_D%d", half, disk), mWater, 0., rin, length1 / 2); + TGeoVolume* TorusW1p = gGeoManager->MakeTorus(Form("TorusW1p_H%d_D%d", half, disk), mWater, radius1, 0., rin, 0., 90.); + TGeoVolume* TubeW2p = gGeoManager->MakeTube(Form("TubeW2p_H%d_D%d", half, disk), mWater, 0., rin, length2 / 2); + TGeoVolume* TorusW2p = gGeoManager->MakeTorus(Form("TorusW2p_H%d_D%d", half, disk), mWater, radius2, 0., rin, 0., 90.); + TGeoVolume* TubeW3p = gGeoManager->MakeTube(Form("TubeW3p_H%d_D%d", half, disk), mWater, 0., rin, length3 / 2); + + TGeoRotation* rTorus2p = new TGeoRotation("rotationTorus2p", 180.0, 0.0, 0.0); + rTorus2p->RegisterYourself(); + TGeoCombiTrans* transfoTorus2p = new TGeoCombiTrans(-length2 - radius1, radius2, length1 / 2 + radius1, rTorus2p); + transfoTorus2p->RegisterYourself(); + TGeoCombiTrans* transfoTube3p = new TGeoCombiTrans(-length2 - radius2 - radius1, radius2 + length3 / 2, length1 / 2 + radius1, rTube3); + transfoTube3p->RegisterYourself(); + TGeoRotation* rTube4p = new TGeoRotation(Form("rotationTube4p_H%d_D%d", half, disk), 90.0 - theta4, phi4 - 90.0, 0.0); + rTube4p->RegisterYourself(); + TGeoCombiTrans* transfoTube4p = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.5, radius2 + length3 / 2 + 2.95, length1 / 2 + radius1 + 3.80, rTube4p); + transfoTube4p->RegisterYourself(); + + Tube1p->SetLineColor(kGray); + Torus1p->SetLineColor(kGray); + Tube2p->SetLineColor(kGray); + Torus2p->SetLineColor(kGray); + Tube3p->SetLineColor(kGray); + + mCoolingPipe2->AddNode(Tube1p, 1, tTube1); + mCoolingPipe2->AddNode(Torus1p, 1, transfoTorus1); + mCoolingPipe2->AddNode(Tube2p, 1, transfoTube2); + mCoolingPipe2->AddNode(Torus2p, 1, transfoTorus2p); + mCoolingPipe2->AddNode(Tube3p, 1, transfoTube3p); + mCoolingPipe2->AddNode(TubeW1p, 1, tTube1); + mCoolingPipe2->AddNode(TorusW1p, 1, transfoTorus1); + mCoolingPipe2->AddNode(TubeW2p, 1, transfoTube2); + mCoolingPipe2->AddNode(TorusW2p, 1, transfoTorus2p); + mCoolingPipe2->AddNode(TubeW3p, 1, transfoTube3p); + if (disk == 0) { + mCoolingPipe2->AddNode(Tube4, 1, transfoTube4p); + theta = 180. * TMath::Pi() / 180.; + phi = 0. * TMath::Pi() / 180.; + nlow[0] = TMath::Sin(theta) * TMath::Cos(phi); + nlow[1] = TMath::Sin(theta) * TMath::Sin(phi); + nlow[2] = TMath::Cos(theta); + theta = -36. * TMath::Pi() / 180.; + phi = 270. * TMath::Pi() / 180.; + nhi[0] = TMath::Sin(theta) * TMath::Cos(phi); + nhi[1] = TMath::Sin(theta) * TMath::Sin(phi); + nhi[2] = TMath::Cos(theta); + TGeoVolume* Tube5p = gGeoManager->MakeCtub(Form("Tube5p_H%d_D%d", half, disk), mPipe, rin5, rout5, length5 / 2, 0., 360., nlow[0], nlow[1], nlow[2], nhi[0], nhi[1], nhi[2]); + Float_t theta5 = 11.0; // angle from the "horizontal" plane x,z + Float_t phi5 = 9.0; // "azimutal" angle + TGeoRotation* rTube5p = new TGeoRotation("rotationTube5p", -90.0 - theta5, -(90.0 + phi5), 0.0); + rTube5p->RegisterYourself(); + TGeoCombiTrans* transfoTube5p; + transfoTube5p = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.4 - TMath::Cos(phi4 * TMath::DegToRad()) * length4 / 2 - TMath::Cos(phi5 * TMath::DegToRad()) * length5 / 2, + radius2 + length3 / 2 + 2.6 + TMath::Sin(theta4 * TMath::DegToRad()) * length4 / 2 + TMath::Sin(theta5 * TMath::DegToRad()) * length5 / 2, + length1 / 2 + radius1 + 3.8 + TMath::Sin(phi4 * TMath::DegToRad()) * length4 / 2 + TMath::Sin(phi5 * TMath::DegToRad()) * length5 / 2, rTube5p); + transfoTube5p->RegisterYourself(); + Tube5p->SetLineColor(kGray); + mCoolingPipe2->AddNode(Tube5p, 1, transfoTube5p); + } + TGeoCombiTrans* transfoCoolingPipe1 = nullptr; + TGeoCombiTrans* transfoCoolingPipe2 = nullptr; + + TGeoRotation* rotation1 = new TGeoRotation("rotation1", 90., 90., 90.); + rotation1->RegisterYourself(); + // 0.75 = Y location from manifold line 836 + transfoCoolingPipe1 = new TGeoCombiTrans(13.8 + length1 / 2, 0.75, 0.0, rotation1); + transfoCoolingPipe1->RegisterYourself(); + TGeoRotation* rotation2 = new TGeoRotation("rotation2", 90., 90., 90.); + rotation2->RegisterYourself(); + transfoCoolingPipe2 = new TGeoCombiTrans(13.8 + length1 / 2, -0.75, 0.0, rotation2); + transfoCoolingPipe2->RegisterYourself(); + mHalfDisk->AddNode(mCoolingPipe1, 1, transfoCoolingPipe1); + mHalfDisk->AddNode(mCoolingPipe2, 1, transfoCoolingPipe2); + } + //================================================================= + //================================================================= + if (disk == 3) { + // One diagonal side + auto* mCoolingPipe3 = new TGeoVolumeAssembly(Form("cooling_pipe3_H%d_D%d", half, disk)); + Float_t length1_3 = 2.; + TGeoVolume* Tube1_3 = gGeoManager->MakeTube(Form("Tube1_3_H%d_D%d", half, disk), mPipe, rin, rout, length1_3 / 2); + TGeoTranslation* tTube1_3 = new TGeoTranslation(0.0, 0.0, 0.0); + tTube1_3->RegisterYourself(); + Float_t radius1_3 = 0.4; + TGeoVolume* Torus1_3 = gGeoManager->MakeTorus(Form("Torus1_3_H%d_D%d", half, disk), mPipe, radius1_3, rin, rout, 0., 90.); + TGeoRotation* rTorus1_3 = new TGeoRotation("rotationTorus1_3", 90.0, 90.0, 0.0); + rTorus1_3->RegisterYourself(); + TGeoCombiTrans* transfoTorus1_3 = new TGeoCombiTrans(0.0, -radius1_3, length1_3 / 2, rTorus1_3); + transfoTorus1_3->RegisterYourself(); + + Float_t length2_3; + if (disk == 3) { + length2_3 = 9.89; + } + TGeoVolume* Tube2_3 = gGeoManager->MakeTube(Form("Tube2_3_H%d_D%d", half, disk), mPipe, rin, rout, length2_3 / 2); + TGeoRotation* rTube2_3 = new TGeoRotation("rotationTube2_3", 180.0, 90.0, 90.0); + rTube2_3->RegisterYourself(); + TGeoCombiTrans* transfoTube2_3 = new TGeoCombiTrans(0., -length2_3 / 2 - radius1_3, length1_3 / 2 + radius1_3, rTube2_3); + transfoTube2_3->RegisterYourself(); + TGeoVolume* Torus2_3 = gGeoManager->MakeTorus(Form("Torus2_3_H%d_D%d", half, disk), mPipe, radius1_3, rin, rout, 0., 90.); + TGeoRotation* rTorus2_3 = new TGeoRotation("rotationTorus2_3", 90.0, 90.0, 180.0); + rTorus2_3->RegisterYourself(); + TGeoCombiTrans* transfoTorus2_3 = new TGeoCombiTrans(0.0, -length2_3 - radius1_3, length1_3 / 2 + radius1_3 + radius1_3, rTorus2_3); + transfoTorus2_3->RegisterYourself(); + + Float_t length3_3; + if (disk == 3) { + length3_3 = 4.73; + } + TGeoVolume* Tube3_3 = gGeoManager->MakeTube(Form("Tube3_3_H%d_D%d", half, disk), mPipe, rin, rout, length3_3 / 2); + TGeoRotation* rTube3_3 = new TGeoRotation("rotationTube3_3", 0.0, 0.0, 0.0); + rTube3_3->RegisterYourself(); + TGeoCombiTrans* transfoTube3_3 = new TGeoCombiTrans(0., -length2_3 - radius1_3 - radius1_3, length1_3 / 2 + radius1_3 + radius1_3 + length3_3 / 2, rTube3_3); + transfoTube3_3->RegisterYourself(); + + Tube1_3->SetLineColor(kGray); + Torus1_3->SetLineColor(kGray); + Tube2_3->SetLineColor(kGray); + Torus2_3->SetLineColor(kGray); + Tube3_3->SetLineColor(kGray); + + mCoolingPipe3->AddNode(Tube1_3, 1, tTube1_3); + mCoolingPipe3->AddNode(Torus1_3, 1, transfoTorus1_3); + mCoolingPipe3->AddNode(Tube2_3, 1, transfoTube2_3); + mCoolingPipe3->AddNode(Torus2_3, 1, transfoTorus2_3); + mCoolingPipe3->AddNode(Tube3_3, 1, transfoTube3_3); + + TGeoCombiTrans* transfoCoolingPipe3_3 = nullptr; + TGeoRotation* rotation3_3 = new TGeoRotation("rotation3_3", 90., 90., 80.); + rotation3_3->RegisterYourself(); + transfoCoolingPipe3_3 = new TGeoCombiTrans(17. + length1_3 / 2, 0.75, 0.0, rotation3_3); + + // ------------------Other diagonal side + auto* mCoolingPipe4 = new TGeoVolumeAssembly(Form("cooling_pipe4_H%d_D%d", half, disk)); + + TGeoVolume* Tube1p_3 = gGeoManager->MakeTube(Form("Tube1p_3_H%d_D%d", half, disk), mPipe, rin, rout, length1_3 / 2); + TGeoVolume* Torus1p_3 = gGeoManager->MakeTorus(Form("Torus1p_3_H%d_D%d", half, disk), mPipe, radius1_3, rin, rout, 0., 90.); + TGeoVolume* Tube2p_3 = gGeoManager->MakeTube(Form("Tube2p_3_H%d_D%d", half, disk), mPipe, rin, rout, length2_3 / 2); + TGeoVolume* Torus2p_3 = gGeoManager->MakeTorus(Form("Torus2p_3_H%d_D%d", half, disk), mPipe, radius1_3, rin, rout, 0., 90.); + TGeoVolume* Tube3p_3 = gGeoManager->MakeTube(Form("Tube3p_3_H%d_D%d", half, disk), mPipe, rin, rout, length3_3 / 2); + TGeoVolume* TubeW1p_3 = gGeoManager->MakeTube(Form("TubeW1p_3_H%d_D%d", half, disk), mWater, 0, rin, length1_3 / 2); + TGeoVolume* TorusW1p_3 = gGeoManager->MakeTorus(Form("TorusW1p_3_H%d_D%d", half, disk), mWater, radius1_3, 0., rin, 0., 90.); + TGeoVolume* TubeW2p_3 = gGeoManager->MakeTube(Form("TubeW2p_3_H%d_D%d", half, disk), mWater, 0., rin, length2_3 / 2); + TGeoVolume* TorusW2p_3 = gGeoManager->MakeTorus(Form("TorusW2p_3_H%d_D%d", half, disk), mWater, radius1_3, 0., rin, 0., 90.); + TGeoVolume* TubeW3p_3 = gGeoManager->MakeTube(Form("TubeW3p_3_H%d_D%d", half, disk), mWater, 0., rin, length3_3 / 2); + + Tube1p_3->SetLineColor(kGray); + Torus1p_3->SetLineColor(kGray); + Tube2p_3->SetLineColor(kGray); + Torus2p_3->SetLineColor(kGray); + Tube3p_3->SetLineColor(kGray); + + mCoolingPipe4->AddNode(Tube1p_3, 1, tTube1_3); + mCoolingPipe4->AddNode(Torus1p_3, 1, transfoTorus1_3); + mCoolingPipe4->AddNode(Tube2p_3, 1, transfoTube2_3); + mCoolingPipe4->AddNode(Torus2p_3, 1, transfoTorus2_3); + mCoolingPipe4->AddNode(Tube3p_3, 1, transfoTube3_3); + mCoolingPipe4->AddNode(TubeW1p_3, 1, tTube1_3); + mCoolingPipe4->AddNode(TorusW1p_3, 1, transfoTorus1_3); + mCoolingPipe4->AddNode(TubeW2p_3, 1, transfoTube2_3); + mCoolingPipe4->AddNode(TorusW2p_3, 1, transfoTorus2_3); + mCoolingPipe4->AddNode(TubeW3p_3, 1, transfoTube3_3); + + TGeoCombiTrans* transfoCoolingPipe4_3 = nullptr; + TGeoRotation* rotation4_3 = new TGeoRotation("rotation4_3", 90., 90., -80.); + rotation4_3->RegisterYourself(); + transfoCoolingPipe4_3 = new TGeoCombiTrans(17. + length1_3 / 2, -0.75, 0.0, rotation4_3); + transfoCoolingPipe4_3->RegisterYourself(); + + mHalfDisk->AddNode(mCoolingPipe3, 1, transfoCoolingPipe3_3); + mHalfDisk->AddNode(mCoolingPipe4, 1, transfoCoolingPipe4_3); + } + //================================================================= + if (disk == 4) { + // One diagonal side + auto* mCoolingPipe3 = new TGeoVolumeAssembly(Form("cooling_pipe3_H%d_D%d", half, disk)); + Float_t length1_4 = 2.; + TGeoVolume* Tube1_4 = gGeoManager->MakeTube(Form("Tube1_4_H%d_D%d", half, disk), mPipe, rin, rout, length1_4 / 2); + TGeoVolume* TubeW1_4 = gGeoManager->MakeTube(Form("TubeW1_4_H%d_D%d", half, disk), mWater, 0., rin, length1_4 / 2); + TGeoTranslation* tTube1_4 = new TGeoTranslation(0.0, 0.0, 0.0); + tTube1_4->RegisterYourself(); + + Float_t radius1_4 = 0.4; + TGeoVolume* Torus1_4 = gGeoManager->MakeTorus(Form("Torus1_4_H%d_D%d", half, disk), mPipe, radius1_4, rin, rout, 0., 90.); + TGeoVolume* TorusW1_4 = gGeoManager->MakeTorus(Form("TorusW1_4_H%d_D%d", half, disk), mWater, radius1_4, 0., rin, 0., 90.); + TGeoRotation* rTorus1_4 = new TGeoRotation("rotationTorus1_4", 90.0, 90.0, 0.0); + rTorus1_4->RegisterYourself(); + TGeoCombiTrans* transfoTorus1_4 = new TGeoCombiTrans(0.0, -radius1_4, length1_4 / 2, rTorus1_4); + transfoTorus1_4->RegisterYourself(); + + Float_t length2_4; + if (disk == 4) { + length2_4 = 10.57; + } + TGeoVolume* Tube2_4 = gGeoManager->MakeTube("Tube2_4", mPipe, rin, rout, length2_4 / 2); + TGeoVolume* TubeW2_4 = gGeoManager->MakeTube("TubeW2_4", mPipe, 0., rin, length2_4 / 2); + TGeoRotation* rTube2_4 = new TGeoRotation("rotationTube2_4", 180.0, 90.0, 90.0); + rTube2_4->RegisterYourself(); + TGeoCombiTrans* transfoTube2_4 = new TGeoCombiTrans(0., -length2_4 / 2 - radius1_4, length1_4 / 2 + radius1_4, rTube2_4); + transfoTube2_4->RegisterYourself(); + + TGeoVolume* Torus2_4 = gGeoManager->MakeTorus(Form("Torus2_4_H%d_D%d", half, disk), mPipe, radius1_4, rin, rout, 0., 90.); + TGeoVolume* TorusW2_4 = gGeoManager->MakeTorus(Form("TorusW2_4_H%d_D%d", half, disk), mWater, radius1_4, 0., rin, 0., 90.); + TGeoRotation* rTorus2_4 = new TGeoRotation("rotationTorus2_4", 90.0, 90.0, 180.0); + rTorus2_4->RegisterYourself(); + TGeoCombiTrans* transfoTorus2_4 = new TGeoCombiTrans(0.0, -length2_4 - radius1_4, length1_4 / 2 + radius1_4 + radius1_4, rTorus2_4); + transfoTorus2_4->RegisterYourself(); + + Float_t length3_4; + if (disk == 4) { + length3_4 = 5.41; + } + TGeoVolume* Tube3_4 = gGeoManager->MakeTube(Form("Tube3_4_H%d_D%d", half, disk), mPipe, rin, rout, length3_4 / 2); + TGeoVolume* TubeW3_4 = gGeoManager->MakeTube(Form("TubeW3_4_H%d_D%d", half, disk), mWater, 0., rin, length3_4 / 2); + TGeoRotation* rTube3_4 = new TGeoRotation("rotationTube3_4", 0.0, 0.0, 0.0); + rTube3_4->RegisterYourself(); + TGeoCombiTrans* transfoTube3_4 = new TGeoCombiTrans(0., -length2_4 - radius1_4 - radius1_4, length1_4 / 2 + radius1_4 + radius1_4 + length3_4 / 2, rTube3_4); + transfoTube3_4->RegisterYourself(); + + Tube1_4->SetLineColor(kGray); + Torus1_4->SetLineColor(kGray); + Tube2_4->SetLineColor(kGray); + Torus2_4->SetLineColor(kGray); + Tube3_4->SetLineColor(kGray); + + mCoolingPipe3->AddNode(Tube1_4, 1, tTube1_4); + mCoolingPipe3->AddNode(Torus1_4, 1, transfoTorus1_4); + mCoolingPipe3->AddNode(Tube2_4, 1, transfoTube2_4); + mCoolingPipe3->AddNode(Torus2_4, 1, transfoTorus2_4); + mCoolingPipe3->AddNode(Tube3_4, 1, transfoTube3_4); + mCoolingPipe3->AddNode(TubeW1_4, 1, tTube1_4); + mCoolingPipe3->AddNode(TorusW1_4, 1, transfoTorus1_4); + mCoolingPipe3->AddNode(TubeW2_4, 1, transfoTube2_4); + mCoolingPipe3->AddNode(TorusW2_4, 1, transfoTorus2_4); + mCoolingPipe3->AddNode(TubeW3_4, 1, transfoTube3_4); + + TGeoCombiTrans* transfoCoolingPipe3_4 = nullptr; + TGeoRotation* rotation3_4 = new TGeoRotation("rotation3_4", 90., 90., 100.); + rotation3_4->RegisterYourself(); + transfoCoolingPipe3_4 = new TGeoCombiTrans(17. + length1_4 / 2, 0.75, 0.0, rotation3_4); + transfoCoolingPipe3_4->RegisterYourself(); + // ------------------Other diagonal side + auto* mCoolingPipe4 = new TGeoVolumeAssembly(Form("cooling_pipe4_H%d_D%d", half, disk)); + TGeoVolume* Tube1p_4 = gGeoManager->MakeTube(Form("Tube1p_4_H%d_D%d", half, disk), mPipe, rin, rout, length1_4 / 2); + TGeoVolume* Torus1p_4 = gGeoManager->MakeTorus(Form("Torus1p_4_H%d_D%d", half, disk), mPipe, radius1_4, rin, rout, 0., 90.); + TGeoVolume* Tube2p_4 = gGeoManager->MakeTube(Form("Tube2p_4_H%d_D%d", half, disk), mPipe, rin, rout, length2_4 / 2); + TGeoVolume* Torus2p_4 = gGeoManager->MakeTorus(Form("Torus2p_4_H%d_D%d", half, disk), mPipe, radius1_4, rin, rout, 0., 90.); + TGeoVolume* Tube3p_4 = gGeoManager->MakeTube(Form("Tube3p_4_H%d_D%d", half, disk), mPipe, rin, rout, length3_4 / 2); + TGeoVolume* TubeW1p_4 = gGeoManager->MakeTube(Form("TubeW1p_4_H%d_D%d", half, disk), mWater, 0., rin, length1_4 / 2); + TGeoVolume* TorusW1p_4 = gGeoManager->MakeTorus(Form("TorusW1p_4_H%d_D%d", half, disk), mWater, radius1_4, 0., rin, 0., 90.); + TGeoVolume* TubeW2p_4 = gGeoManager->MakeTube(Form("TubeW2p_4_H%d_D%d", half, disk), mWater, 0., rin, length2_4 / 2); + TGeoVolume* TorusW2p_4 = gGeoManager->MakeTorus(Form("TorusW2p_4_H%d_D%d", half, disk), mWater, radius1_4, 0., rin, 0., 90.); + TGeoVolume* TubeW3p_4 = gGeoManager->MakeTube(Form("TubeW3p_4_H%d_D%d", half, disk), mWater, 0., rin, length3_4 / 2); + + Tube1p_4->SetLineColor(kGray); + Torus1p_4->SetLineColor(kGray); + Tube2p_4->SetLineColor(kGray); + Torus2p_4->SetLineColor(kGray); + Tube3p_4->SetLineColor(kGray); + + mCoolingPipe4->AddNode(Tube1p_4, 1, tTube1_4); + mCoolingPipe4->AddNode(Torus1p_4, 1, transfoTorus1_4); + mCoolingPipe4->AddNode(Tube2p_4, 1, transfoTube2_4); + mCoolingPipe4->AddNode(Torus2p_4, 1, transfoTorus2_4); + mCoolingPipe4->AddNode(Tube3p_4, 1, transfoTube3_4); + mCoolingPipe4->AddNode(TubeW1p_4, 1, tTube1_4); + mCoolingPipe4->AddNode(TorusW1p_4, 1, transfoTorus1_4); + mCoolingPipe4->AddNode(TubeW2p_4, 1, transfoTube2_4); + mCoolingPipe4->AddNode(TorusW2p_4, 1, transfoTorus2_4); + mCoolingPipe4->AddNode(TubeW3p_4, 1, transfoTube3_4); + + TGeoCombiTrans* transfoCoolingPipe4_4 = nullptr; + TGeoRotation* rotation4_4 = new TGeoRotation("rotation4_4", 90., 90., -100.); + rotation4_4->RegisterYourself(); + transfoCoolingPipe4_4 = new TGeoCombiTrans(17. + length1_4 / 2, -0.75, 0.0, rotation4_4); + transfoCoolingPipe4_4->RegisterYourself(); + + mHalfDisk->AddNode(mCoolingPipe3, 1, transfoCoolingPipe3_4); + mHalfDisk->AddNode(mCoolingPipe4, 1, transfoCoolingPipe4_4); + } + //================================================================= } //_____________________________________________________________________________ From 58f3c0950a57b55f358453fa17e4b1e0df21b44e Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Wed, 25 Nov 2020 08:44:31 +0100 Subject: [PATCH 1423/1751] TOF clusterizer improved (#4892) * fix for TOF ncrates counter * fix in TOF decoding to get the end of TF * fix in clusterization to start TOF time from FirstIR * fix in TOF clusterizer * add TOF cluster info for tuning with cosmics * fix checks --- .../TOF/include/DataFormatsTOF/Cluster.h | 14 ++++++++++- DataFormats/Detectors/TOF/src/Cluster.cxx | 8 ++++++ Detectors/TOF/base/include/TOFBase/Digit.h | 6 ++--- .../include/TOFReconstruction/Clusterer.h | 6 ++--- .../TOF/reconstruction/src/Clusterer.cxx | 25 ++++++++++++++----- .../TOF/reconstruction/src/DataReader.cxx | 2 +- .../TOFDigitWriterSplitterSpec.h | 10 ++++++-- .../workflow/src/CompressedDecodingTask.cxx | 2 +- .../TOF/workflow/src/DigitReaderSpec.cxx | 2 +- .../TOF/workflow/src/TOFClusterWriterSpec.cxx | 4 +-- .../TOF/workflow/src/TOFClusterizerSpec.cxx | 21 +++++++++------- 11 files changed, 71 insertions(+), 29 deletions(-) diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h index 35126f49cb32f..0658241c7841e 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/Cluster.h @@ -19,6 +19,8 @@ #include <TMath.h> #include <cstdlib> #include "CommonConstants/LHCConstants.h" +#include <vector> +#include "Rtypes.h" namespace o2 { @@ -110,6 +112,11 @@ class Cluster : public o2::BaseCluster<float> int getBC() const { return int(mTimeRaw * BC_TIME_INPS_INV); } + void setDigitInfo(int idig, int ch, double t, float tot); + int getDigitInfoCH(int idig) const { return mDigitInfoCh[idig]; } + double getDigitInfoT(int idig) const { return mDigitInfoT[idig]; } + float getDigitInfoTOT(int idig) const { return mDigitInfoTOT[idig]; } + private: friend class boost::serialization::access; @@ -123,7 +130,12 @@ class Cluster : public o2::BaseCluster<float> float mPhi = PhiOutOfRange; //! phi coordinate int mEntryInTree; //! index of the entry in the tree from which we read the cluster - ClassDefNV(Cluster, 3); + // add extra info to trace all digit infos (for commissioning phase) + int mDigitInfoCh[6] = {0, 0, 0, 0, 0, 0}; + double mDigitInfoT[6] = {0., 0., 0., 0., 0., 0.}; + float mDigitInfoTOT[6] = {0., 0., 0., 0., 0., 0.}; + + ClassDefNV(Cluster, 4); }; std::ostream& operator<<(std::ostream& os, Cluster& c); diff --git a/DataFormats/Detectors/TOF/src/Cluster.cxx b/DataFormats/Detectors/TOF/src/Cluster.cxx index f2a0b0ea67f13..1bf4096bef7fc 100644 --- a/DataFormats/Detectors/TOF/src/Cluster.cxx +++ b/DataFormats/Detectors/TOF/src/Cluster.cxx @@ -72,3 +72,11 @@ std::ostream& operator<<(std::ostream& os, Cluster& c) os << " TOF cluster: raw time = " << std::scientific << c.getTimeRaw() << ", time = " << std::scientific << c.getTime() << ", Tot = " << std::scientific << c.getTot() << ", L0L1Latency = " << c.getL0L1Latency() << ", deltaBC = " << c.getDeltaBC() << ", R = " << c.getR() << ", mPhi = " << c.getPhi() << ", Number of contributingChannels = " << c.getNumOfContributingChannels() << "\n"; return os; } + +//______________________________________________________________________ +void Cluster::setDigitInfo(int idig, int ch, double t, float tot) +{ + mDigitInfoCh[idig] = ch; + mDigitInfoT[idig] = t; + mDigitInfoTOT[idig] = tot; +} diff --git a/Detectors/TOF/base/include/TOFBase/Digit.h b/Detectors/TOF/base/include/TOFBase/Digit.h index ae07cb36e175f..a777a989995bd 100644 --- a/Detectors/TOF/base/include/TOFBase/Digit.h +++ b/Detectors/TOF/base/include/TOFBase/Digit.h @@ -68,7 +68,7 @@ class Digit Bool_t isUsedInCluster() const { return mIsUsedInCluster; } - void setIsUsedInCluster() { mIsUsedInCluster = kTRUE; } + void setIsUsedInCluster(bool val = true) { mIsUsedInCluster = val; } Int_t getElectronicIndex() const { return mElectronIndex; } void setElectronicIndex(Int_t ind) { mElectronIndex = ind; } @@ -188,13 +188,13 @@ struct ReadoutWindowData { struct DigitHeader { int mCountsCrate[Geo::kNCrate] = {0}; - int mNumberOfCrates[Geo::kNCrate] = {0}; + int mNumberOfCrates[Geo::kNCrate + 1] = {0}; int mCountsRow = 0; void clear() { memset(mCountsCrate, 0, Geo::kNCrate * 4); - memset(mNumberOfCrates, 0, Geo::kNCrate * 4); + memset(mNumberOfCrates, 0, (Geo::kNCrate + 1) * 4); mCountsRow = 0; } DigitHeader() { clear(); } diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h index 3049a955c8e26..7bab6b0bef59a 100644 --- a/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/Clusterer.h @@ -51,8 +51,8 @@ class Clusterer mCalibApi = calibApi; } - void setFirstOrbit(uint32_t orb); - uint32_t getFirstOrbit() const { return mFirstOrbit; } + void setFirstOrbit(uint64_t orb); + uint64_t getFirstOrbit() const { return mFirstOrbit; } private: void calibrateStrip(); @@ -68,7 +68,7 @@ class Clusterer void addContributingDigit(Digit* dig); void buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth); CalibApi* mCalibApi = nullptr; //! calib api to handle the TOF calibration - uint32_t mFirstOrbit = 0; //! 1st orbit of the TF + uint64_t mFirstOrbit = 0; //! 1st orbit of the TF uint64_t mBCOffset = 0; //! 1st orbit of the TF converted to BCs }; diff --git a/Detectors/TOF/reconstruction/src/Clusterer.cxx b/Detectors/TOF/reconstruction/src/Clusterer.cxx index ccaa484954303..60fd6594588a8 100644 --- a/Detectors/TOF/reconstruction/src/Clusterer.cxx +++ b/Detectors/TOF/reconstruction/src/Clusterer.cxx @@ -100,7 +100,7 @@ void Clusterer::processStrip(std::vector<Cluster>& clusters, MCLabelContainer co // check if the TOF time are close enough to be merged; if not, it means that nothing else will contribute to the cluster (since digits are ordered in time) double timeDigNext = digNext->getCalibratedTime(); // in ps LOG(DEBUG) << "Time difference = " << timeDigNext - timeDig; - if (timeDigNext - timeDig > 500 /*in ps*/) { + if (timeDigNext - timeDig > 5000 /*in ps*/) { // to be change to 500 ps break; } digNext->getPhiAndEtaIndex(iphi2, ieta2); @@ -179,6 +179,8 @@ void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth) //setL0L1Latency(); // to be filled (maybe) //setDeltaBC(); // to be filled (maybe) + c.setDigitInfo(0, mContributingDigit[0]->getChannel(), mContributingDigit[0]->getCalibratedTime(), mContributingDigit[0]->getTOT() * Geo::TOTBIN_NS); + int chan1, chan2; int phi1, phi2; int eta1, eta2; @@ -191,6 +193,9 @@ void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth) mContributingDigit[idig]->getPhiAndEtaIndex(phi2, eta2); deltaPhi = phi1 - phi2; deltaEta = eta1 - eta2; + + bool isOk = true; + if (deltaPhi == 1) { // the digit is to the LEFT of the cluster; let's check about UP/DOWN/Same Line if (deltaEta == 1) { // the digit is DOWN LEFT wrt the cluster mask = Cluster::kDownLeft; @@ -212,13 +217,18 @@ void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth) mask = Cluster::kDown; } else if (deltaEta == -1) { // the digit is UP wrt the cluster mask = Cluster::kUp; - } else { // impossible!! + } else { // same channel! LOG(DEBUG) << " Check what is going on, the digit you are trying to merge to the cluster must be in a different channels... "; } - } else { // impossible!!! We checked above... - LOG(DEBUG) << " Check what is going on, the digit you are trying to merge to the cluster is too far from the cluster, you should have not got here... "; + } else { // |delataphi| > 1 + isOk = false; + mContributingDigit[idig]->setIsUsedInCluster(false); + } + + if (isOk) { + c.setDigitInfo(c.getNumOfContributingChannels(), mContributingDigit[idig]->getChannel(), mContributingDigit[idig]->getCalibratedTime(), mContributingDigit[idig]->getTOT() * Geo::TOTBIN_NS); + c.addBitInContributingChannels(mask); } - c.addBitInContributingChannels(mask); } // filling the MC labels of this cluster; the first will be those of the main digit; then the others @@ -226,6 +236,9 @@ void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth) int lbl = mClsLabels->getIndexedSize(); // this should correspond to the number of digits also; //printf("lbl = %d\n", lbl); for (int i = 0; i < mNumberOfContributingDigits; i++) { + if (!mContributingDigit[i]->isUsedInCluster()) { + continue; + } //printf("contributing digit = %d\n", i); int digitLabel = mContributingDigit[i]->getLabel(); //printf("digitLabel = %d\n", digitLabel); @@ -264,7 +277,7 @@ void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth) } //_____________________________________________________________________ -void Clusterer::setFirstOrbit(uint32_t orb) +void Clusterer::setFirstOrbit(uint64_t orb) { mFirstOrbit = orb; mBCOffset = orb * o2::constants::lhc::LHCMaxBunches; diff --git a/Detectors/TOF/reconstruction/src/DataReader.cxx b/Detectors/TOF/reconstruction/src/DataReader.cxx index 8057f86fbeebd..e8f55bda34e6a 100644 --- a/Detectors/TOF/reconstruction/src/DataReader.cxx +++ b/Detectors/TOF/reconstruction/src/DataReader.cxx @@ -50,7 +50,7 @@ Bool_t DigitDataReader::getNextStripData(StripData& stripData) // sorting the digits of the current strip according to the TDC std::sort(stripData.digits.begin(), stripData.digits.end(), - [](const Digit& a, const Digit& b) { return a.getTDC() < b.getTDC(); }); + [](const Digit& a, const Digit& b) { if(a.getBC() != b.getBC()){ return a.getBC() < b.getBC();} return a.getTDC() < b.getTDC(); }); return kTRUE; } diff --git a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h index 432504430afb0..848078cc7be95 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h @@ -14,6 +14,8 @@ /// @file TOFDigitWriterSplitterSpec.h /// @brief Device to write to tree the information for TOF time slewing calibration. +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "TOFBase/Digit.h" @@ -35,12 +37,14 @@ class TOFDigitWriterSplitter : public Task using ErrorType = std::vector<uint64_t>; using HeaderType = o2::tof::DigitHeader; + std::string mBaseName; + public: TOFDigitWriterSplitter(int nTF, bool storeErr = false) : mTFthr(nTF), mStoreErrors(storeErr) {} void createAndOpenFileAndTree() { - TString filename = TString::Format("tofdigits_%d.root", mCount); + TString filename = TString::Format("%s_%06d.root", mBaseName.c_str(), mCount); LOG(DEBUG) << "opening file " << filename.Data(); mfileOut.reset(TFile::Open(TString::Format("%s", filename.Data()), "RECREATE")); mOutputTree = std::make_unique<TTree>("o2sim", "Tree with TOF digits"); @@ -57,6 +61,8 @@ class TOFDigitWriterSplitter : public Task void init(o2::framework::InitContext& ic) final { + mBaseName = ic.options().get<std::string>("output-base-name"); + mCount = 0; createAndOpenFileAndTree(); } @@ -153,7 +159,7 @@ DataProcessorSpec getTOFCalibCollectorWriterSpec(int nTF, bool storeErr = false) inputs, outputs, AlgorithmSpec{adaptFromTask<o2::tof::TOFDigitWriterSplitter>(nTF, storeErr)}, - Options{}}; + Options{{"output-base-name", VariantType::String, "tofdigits", {"Name of the input file (root extension will be added)"}}}}; } } // namespace framework diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index e6bb8ee347c7b..59b2e4d7c139f 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -157,7 +157,7 @@ void CompressedDecodingTask::run(ProcessingContext& pc) } } - if ((mNCrateOpenTF == 72 || mConetMode) && mNCrateOpenTF == mNCrateCloseTF) { + if ((mNCrateOpenTF > 0 || mConetMode) && mNCrateOpenTF == mNCrateCloseTF) { mHasToBePosted = true; } diff --git a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx index 66081b514dff6..a987aa493515c 100644 --- a/Detectors/TOF/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/TOF/workflow/src/DigitReaderSpec.cxx @@ -70,7 +70,7 @@ void DigitReader::run(ProcessingContext& pc) static o2::parameters::GRPObject::ROMode roMode = o2::parameters::GRPObject::CONTINUOUS; - LOG(INFO) << "TOF: Sending ROMode= " << roMode << " to GRPUpdater"; + LOG(DEBUG) << "TOF: Sending ROMode= " << roMode << " to GRPUpdater"; pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ROMode", 0, Lifetime::Timeframe}, roMode); } else { LOG(ERROR) << "Cannot read the TOF digits !"; diff --git a/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx b/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx index 9141c68c7ee59..9c12d5b16ad78 100644 --- a/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFClusterWriterSpec.cxx @@ -32,10 +32,10 @@ DataProcessorSpec getTOFClusterWriterSpec(bool useMC) { // Spectators for logging auto logger = [](OutputType const& indata) { - LOG(INFO) << "RECEIVED CLUSTERS SIZE " << indata.size(); + LOG(DEBUG) << "RECEIVED CLUSTERS SIZE " << indata.size(); }; auto loggerMCLabels = [](LabelsType const& labeldata) { - LOG(INFO) << "TOF GOT " << labeldata.getNElements() << " LABELS "; + LOG(DEBUG) << "TOF GOT " << labeldata.getNElements() << " LABELS "; }; return MakeRootTreeWriterSpec("TOFClusterWriter", "tofclusters.root", diff --git a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx index 550e56690aacc..aa6c2ef71a633 100644 --- a/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFClusterizerSpec.cxx @@ -62,16 +62,19 @@ class TOFDPLClustererTask auto digits = pc.inputs().get<gsl::span<o2::tof::Digit>>("tofdigits"); auto row = pc.inputs().get<std::vector<o2::tof::ReadoutWindowData>*>("readoutwin"); - auto header = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("tofdigits").header); - mClusterer.setFirstOrbit(header->firstTForbit); + //auto header = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("tofdigits").header); + + if (row->size() > 0) { + mClusterer.setFirstOrbit(row->at(0).mFirstIR.orbit); + } //RSTODO: below is a hack, to remove once the framework will start propagating the header.firstTForbit //Here I extract the orbit/BC from the abs.BC, since the triggerer orbit/bunch are not set. Then why they are needed? - if (digits.size()) { - auto bcabs = digits[0].getBC(); - auto ir0 = o2::raw::HBFUtils::Instance().getFirstIRofTF({uint16_t(bcabs % Geo::BC_IN_ORBIT), uint32_t(bcabs / Geo::BC_IN_ORBIT)}); - mClusterer.setFirstOrbit(ir0.orbit); - } + // if (digits.size()) { + // auto bcabs = digits[0].getBC(); + // auto ir0 = o2::raw::HBFUtils::Instance().getFirstIRofTF({uint16_t(bcabs % Geo::BC_IN_ORBIT), uint32_t(bcabs / Geo::BC_IN_ORBIT)}); + // mClusterer.setFirstOrbit(ir0.orbit); + // } auto labelvector = std::make_shared<std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>>(); if (mUseMC) { @@ -125,8 +128,8 @@ class TOFDPLClustererTask mClusterer.process(mReader, mClustersArray, nullptr); } } - LOG(INFO) << "TOF CLUSTERER : TRANSFORMED " << digits.size() - << " DIGITS TO " << mClustersArray.size() << " CLUSTERS"; + LOG(DEBUG) << "TOF CLUSTERER : TRANSFORMED " << digits.size() + << " DIGITS TO " << mClustersArray.size() << " CLUSTERS"; // send clusters pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CLUSTERS", 0, Lifetime::Timeframe}, mClustersArray); From 0b14c71fd7085c5e0818dbe59d1486c7637f5a02 Mon Sep 17 00:00:00 2001 From: knopers8 <piotr.jan.konopka@cern.ch> Date: Wed, 25 Nov 2020 11:47:24 +0100 Subject: [PATCH 1424/1751] [QC-391] Support TGraphs and TProfiles in Mergers (#4844) TProfiles were actually supported, because they inherit TH1, but I've added a test. --- Utilities/Mergers/src/MergerAlgorithm.cxx | 3 ++ Utilities/Mergers/test/test_Algorithm.cxx | 34 +++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/Utilities/Mergers/src/MergerAlgorithm.cxx b/Utilities/Mergers/src/MergerAlgorithm.cxx index 6b0d263bd46ac..7ababdb1571db 100644 --- a/Utilities/Mergers/src/MergerAlgorithm.cxx +++ b/Utilities/Mergers/src/MergerAlgorithm.cxx @@ -24,6 +24,7 @@ #include <TTree.h> #include <THnSparse.h> #include <TObjArray.h> +#include <TGraph.h> namespace o2::mergers::algorithm { @@ -81,6 +82,8 @@ void merge(TObject* const target, TObject* const other) errorCode = reinterpret_cast<THnBase*>(target)->Merge(&otherCollection); } else if (target->InheritsFrom(TTree::Class())) { errorCode = reinterpret_cast<TTree*>(target)->Merge(&otherCollection); + } else if (target->InheritsFrom(TGraph::Class())) { + errorCode = reinterpret_cast<TGraph*>(target)->Merge(&otherCollection); } else { throw std::runtime_error("Object with type '" + std::string(target->ClassName()) + "' is not one of the mergeable types."); } diff --git a/Utilities/Mergers/test/test_Algorithm.cxx b/Utilities/Mergers/test/test_Algorithm.cxx index 0082b4e381efb..c9648b8cef10e 100644 --- a/Utilities/Mergers/test/test_Algorithm.cxx +++ b/Utilities/Mergers/test/test_Algorithm.cxx @@ -32,6 +32,8 @@ #include <TTree.h> #include <THnSparse.h> #include <TF1.h> +#include <TGraph.h> +#include <TProfile.h> //using namespace o2::framework; using namespace o2::mergers; @@ -189,6 +191,38 @@ BOOST_AUTO_TEST_CASE(MergerSingularObjects) delete other; delete target; } + { + constexpr Int_t points = 5; + Double_t x1[] = {0, 1, 2, 3, 4}; + Double_t y1[] = {0, 1, 2, 3, 4}; + Double_t x2[] = {5, 6, 7, 8, 9}; + Double_t y2[] = {5, 6, 7, 8, 9}; + + TGraph* target = new TGraph(points, x1, y1); + TGraph* other = new TGraph(points, x2, y2); + + BOOST_CHECK_NO_THROW(algorithm::merge(target, other)); + BOOST_CHECK_EQUAL(target->GetN(), 2 * points); + + delete other; + delete target; + } + { + auto target = new TProfile("hprof1", "hprof1", bins, min, max, min, max); + target->Fill(2, 2, 1); + auto other = new TProfile("hprof2", "hprof2", bins, min, max, min, max); + other->Fill(5, 5, 1); + + BOOST_CHECK_NO_THROW(algorithm::merge(target, other)); + BOOST_CHECK_EQUAL(target->GetEntries(), 2); + BOOST_CHECK_EQUAL(target->GetBinContent(target->FindBin(0)), 0); + BOOST_CHECK_EQUAL(target->GetBinContent(target->FindBin(1)), 0); + BOOST_CHECK_CLOSE(target->GetBinContent(target->FindBin(2)), 2, 0.001); + BOOST_CHECK_CLOSE(target->GetBinContent(target->FindBin(5)), 5, 0.001); + + delete other; + delete target; + } { auto* target = new CustomMergeableTObject("obj1", 123); auto* other = new CustomMergeableTObject("obj2", 321); From 68f2bc5ba1f32218ad133237c7d461b5204950ab Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 25 Nov 2020 12:09:44 +0100 Subject: [PATCH 1425/1751] Update code-formatting.yml (#4919) --- .github/workflows/code-formatting.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index d663eac1a2fae..317b5a46e2d20 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -37,6 +37,7 @@ jobs: BASE_COMMIT=$(git merge-base HEAD ${{ 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/') + [ "X$COMMIT_FILES" = X ] && { echo "No files to check" ; exit 0; } RESULT_OUTPUT="$(git-clang-format-8 --commit $BASE_COMMIT --diff --binary `which clang-format-8` $COMMIT_FILES)" for x in $COMMIT_FILES; do From c7d8a0066caeb0b26ab62dc7169a34f05f7866af Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 25 Nov 2020 12:19:14 +0100 Subject: [PATCH 1426/1751] DPL: avoid segmentation violation when infos is empty (#4916) --- Framework/Core/src/runDataProcessing.cxx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 3bfcb3d8b2dde..9690acd5d2671 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1300,17 +1300,18 @@ int runStateMachine(DataProcessorSpecs const& workflow, // the workflow was not really run. // NOTE: is this really what we want? should we run // SCHEDULE and dump the full configuration as well? - if (!infos.empty()) { - boost::property_tree::ptree finalConfig; - assert(infos.size() == deviceSpecs.size()); - for (size_t di = 0; di < infos.size(); ++di) { - auto info = infos[di]; - auto spec = deviceSpecs[di]; - finalConfig.put_child(spec.name, info.currentConfig); - } - LOG(INFO) << "Dumping used configuration in dpl-config.json"; - boost::property_tree::write_json("dpl-config.json", finalConfig); + if (infos.empty()) { + return 0; + } + boost::property_tree::ptree finalConfig; + assert(infos.size() == deviceSpecs.size()); + for (size_t di = 0; di < infos.size(); ++di) { + auto info = infos[di]; + auto spec = deviceSpecs[di]; + finalConfig.put_child(spec.name, info.currentConfig); } + LOG(INFO) << "Dumping used configuration in dpl-config.json"; + boost::property_tree::write_json("dpl-config.json", finalConfig); if (driverInfo.noSHMCleanup) { LOGP(warning, "Not cleaning up shared memory."); } else { From 37b849b4d4e6536e0652d05a83acfb590d5aca73 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 23 Nov 2020 11:33:10 +0100 Subject: [PATCH 1427/1751] GPU QA: Use MCKinematicsReader to obtain MC truth --- GPU/GPUTracking/CMakeLists.txt | 1 + GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 21 +++++---------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index eecf72ce1c48b..a3c60e6277e6d 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -259,6 +259,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") O2::TPCFastTransformation O2::DetectorsRaw ${DEBUGGUI_TARGET} + O2::Steer PUBLIC_INCLUDE_DIRECTORIES SliceTracker Base TPCConvert diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 72cd955acabac..d50ed90fb108e 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -60,6 +60,7 @@ #include "SimulationDataFormat/DigitizationContext.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsCommonDataFormats/NameConf.h" +#include "Steer/MCKinematicsReader.h" #include "TPDGCode.h" #include "TParticlePDG.h" #include "TDatabasePDG.h" @@ -587,17 +588,8 @@ int GPUQA::InitQA(int tasks) #ifdef GPUCA_O2_LIB static constexpr float PRIM_MAX_T = 0.01f; - TFile fileSim(o2::base::NameConf::getMCKinematicsFileName("o2sim").c_str()); - TTree* treeSim = (TTree*)fileSim.Get("o2sim"); - std::vector<o2::MCTrack>* tracksX; - std::vector<o2::TrackReference>* trackRefsX; - if (treeSim == nullptr) { - throw std::runtime_error("Error reading o2sim tree"); - } - treeSim->SetBranchAddress("MCTrack", &tracksX); - treeSim->SetBranchAddress("TrackRefs", &trackRefsX); - - int nSimEvents = treeSim->GetEntries(); + o2::steer::MCKinematicsReader mcReader("collisioncontext.root"); + int nSimEvents = mcReader.getNEvents(0); mTrackMCLabelsReverse.resize(nSimEvents); mRecTracks.resize(nSimEvents); mFakeTracks.resize(nSimEvents); @@ -614,9 +606,8 @@ int GPUQA::InitQA(int tasks) auto ir0 = o2::raw::HBFUtils::Instance().getFirstIRofTF(ir); float timebin = (float)ir.differenceInBC(ir0) / o2::tpc::constants::LHCBCPERTIMEBIN; - treeSim->GetEntry(i); - const std::vector<o2::MCTrack>& tracks = *tracksX; - const std::vector<o2::TrackReference>& trackRefs = *trackRefsX; + const std::vector<o2::MCTrack>& tracks = mcReader.getTracks(0, i); + const std::vector<o2::TrackReference>& trackRefs = mcReader.getTrackRefsByEvent(0, i); refId.resize(tracks.size()); std::fill(refId.begin(), refId.end(), -1); @@ -679,8 +670,6 @@ int GPUQA::InitQA(int tasks) } } } - - fileSim.Close(); #endif if (mConfig.matchMCLabels.size()) { From ed73bf883b0f8619246d98fe04deaad0be38b8a8 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 25 Nov 2020 11:49:26 +0100 Subject: [PATCH 1428/1751] GPU: Add missing configKeyValues dictionary --- GPU/GPUTracking/GPUTrackingLinkDef_O2.h | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h index df62b623abb44..104303af7cff6 100644 --- a/GPU/GPUTracking/GPUTrackingLinkDef_O2.h +++ b/GPU/GPUTracking/GPUTrackingLinkDef_O2.h @@ -25,6 +25,7 @@ #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsRec + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsProcessing + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsDisplay + ; +#pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsDisplayLight + ; #pragma link C++ class o2::gpu::GPUConfigurableParamGPUSettingsQA + ; #pragma link C++ class o2::gpu::trackInterface < o2::dataformats::TrackTPCITS> + ; #pragma link C++ class o2::gpu::GPUTRDTrack_t < o2::gpu::trackInterface < o2::dataformats::TrackTPCITS>> + ; From 40f6fce55686b729836985c7aa5a3d7d3cdf219b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 25 Nov 2020 14:12:43 +0100 Subject: [PATCH 1429/1751] DPL: fix compilation of DPL_ENABLE_BACKTRACE (#4921) --- Framework/Core/src/runDataProcessing.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 9690acd5d2671..8507335cdb53b 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1071,11 +1071,11 @@ int runStateMachine(DataProcessorSpecs const& workflow, std::cerr << "Invalid workflow: " << e.what() << std::endl; return 1; } catch (o2::framework::RuntimeErrorRef ref) { - auto& e = o2::framework::error_from_ref(ref); + auto& err = o2::framework::error_from_ref(ref); #ifdef DPL_ENABLE_BACKTRACE backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); #endif - std::cerr << "Invalid workflow: " << e.what << std::endl; + std::cerr << "Invalid workflow: " << err.what << std::endl; return 1; } catch (...) { std::cerr << "Unknown error while materialising workflow"; From 6e6a1ebebb774c414ae5a57ded7eaf2c382492d8 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <bogdan.vulpescu@clermont.in2p3.fr> Date: Wed, 25 Nov 2020 16:40:13 +0100 Subject: [PATCH 1430/1751] MFT: speed-up the tracking (#4903) --- .../MFT/tracking/include/MFTTracking/Cell.h | 20 +- .../tracking/include/MFTTracking/Cluster.h | 7 +- .../tracking/include/MFTTracking/Constants.h | 10 +- .../tracking/include/MFTTracking/ROframe.h | 82 +- .../MFT/tracking/include/MFTTracking/Road.h | 76 +- .../tracking/include/MFTTracking/TrackCA.h | 101 +- .../tracking/include/MFTTracking/Tracker.h | 162 +--- Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx | 20 +- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 905 +++++++----------- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 3 +- 10 files changed, 520 insertions(+), 866 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h index 68b6a47150fe4..90fc28dee34a4 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h @@ -30,6 +30,7 @@ class Cell final { public: Cell(); + /// layer1, layer2, clsLayer1, clsLayer2, cellId; set level = 1 Cell(const Int_t, const Int_t, const Int_t, const Int_t, const Int_t); const Int_t getFirstLayerId() const; @@ -51,6 +52,23 @@ class Cell final const UChar_t getNLeftNeighbours() const { return mNLeftNeighbours; } const UChar_t getNRightNeighbours() const { return mNRightNeighbours; } + void setCoordinates(Float_t* coord) + { + mCoord[0] = coord[0]; // X1 + mCoord[1] = coord[1]; // Y1 + mCoord[2] = coord[2]; // Z1 + mCoord[3] = coord[3]; // X2 + mCoord[4] = coord[4]; // Y2 + mCoord[5] = coord[5]; // Z2 + } + + const Float_t getX1() const { return mCoord[0]; } + const Float_t getY1() const { return mCoord[1]; } + const Float_t getZ1() const { return mCoord[2]; } + const Float_t getX2() const { return mCoord[3]; } + const Float_t getY2() const { return mCoord[4]; } + const Float_t getZ2() const { return mCoord[5]; } + private: const Int_t mFirstLayerId; const Int_t mSecondLayerId; @@ -64,6 +82,7 @@ class Cell final UChar_t mNRightNeighbours; std::array<std::pair<Int_t, Int_t>, constants::mft::MaxCellNeighbours> mLeftNeighbours; std::array<std::pair<Int_t, Int_t>, constants::mft::MaxCellNeighbours> mRightNeighbours; + Float_t mCoord[6]; }; inline Cell::Cell() @@ -93,7 +112,6 @@ inline Cell::Cell(const Int_t firstLayerId, const Int_t secondLayerId, const Int mNLeftNeighbours{0}, mNRightNeighbours{0} { - // Nothing to do } inline const Int_t Cell::getFirstLayerId() const { return mFirstLayerId; } diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index 851151caa71a2..7b31d12f5c83b 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -34,16 +34,21 @@ struct Cluster : public o2::BaseCluster<float> { clusterId{id}, indexTableBin{bin}, sigmaX2{sigX2}, - sigmaY2{sigY2} {}; + sigmaY2{sigY2}, + isUsed{false} {}; Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t index); Cluster(const Int_t layerIndex, const Cluster& other); + void setUsed(Bool_t bval) { isUsed = bval; } + const Bool_t getUsed() { return isUsed; } + Float_t phiCoordinate; Float_t rCoordinate; Int_t clusterId; Int_t indexTableBin; Float_t sigmaX2; Float_t sigmaY2; + Bool_t isUsed; }; } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h index 26a1f51555f1a..244746300beaf 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h @@ -47,7 +47,10 @@ constexpr std::array<Float_t, LayersNumber> InverseLayerZCoordinate() { return std::array<Float_t, LayersNumber>{-1. / 45.3, -1. / 46.7, -1. / 48.6, -1. / 50.0, -1. / 52.4, -1. / 53.8, -1. / 67.7, -1. / 69.1, -1. / 76.1, -1. / 77.5}; } -constexpr Int_t MinTrackPoints{4}; +constexpr Int_t MinTrackPointsLTF{5}; +constexpr Int_t MinTrackPointsCA{4}; +constexpr Int_t MinTrackStationsLTF{4}; +constexpr Int_t MinTrackStationsCA{4}; constexpr Int_t MaxTrackPoints{20}; constexpr Float_t LTFclsRCut{0.0100}; constexpr Float_t ROADclsRCut{0.0400}; @@ -65,6 +68,11 @@ constexpr Float_t PhiMax{o2::constants::math::TwoPI}; // [rad] constexpr Int_t RBins{50}; constexpr Int_t PhiBins{50}; +constexpr Int_t RPhiBins{RBins * PhiBins}; + +constexpr Float_t PhiBinSize{(PhiMax - PhiMin) / PhiBins}; +constexpr Float_t RBinSize{(RMax - RMin) / RBins}; + constexpr Float_t InversePhiBinSize{PhiBins / (PhiMax - PhiMin)}; constexpr Float_t InverseRBinSize{RBins / (RMax - RMin)}; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h index f6f0b039a8ad8..b5a5e8696d1db 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h @@ -48,57 +48,48 @@ class ROframe final void setROFrameId(const Int_t rofid) { mROframeId = rofid; } - const std::array<std::vector<Cluster>, constants::mft::LayersNumber>& getClusters() const { return mClusters; } - const std::vector<Cluster>& getClustersInLayer(Int_t layerId) const { return mClusters[layerId]; } + std::vector<Cluster>& getClustersInLayer(Int_t layerId) { return mClusters[layerId]; } - const MCCompLabel& getClusterLabels(Int_t layerId, const Cluster& cl) const { return mClusterLabels[layerId][cl.clusterId]; } const MCCompLabel& getClusterLabels(Int_t layerId, const Int_t clusterId) const { return mClusterLabels[layerId][clusterId]; } - const std::map<Int_t, std::pair<Int_t, Int_t>>& getClusterBinIndexRange(Int_t layerId) const { return mClusterBinIndexRange[layerId]; } + const std::array<std::pair<Int_t, Int_t>, constants::index_table::RPhiBins>& getClusterBinIndexRange(Int_t layerId) const { return mClusterBinIndexRange[layerId]; } + const Int_t getClusterExternalIndex(Int_t layerId, const Int_t clusterId) const { return mClusterExternalIndices[layerId][clusterId]; } - const std::array<std::vector<Cell>, constants::mft::LayersNumber>& getCells() const; - const std::vector<Cell>& getCellsInLayer(Int_t layerId) const { return mCells[layerId]; } std::vector<TrackLTF>& getTracksLTF(); TrackLTF& getCurrentTrackLTF(); - void removeCurrentTrackLTF(); - Road& getCurrentRoad(); - void removeCurrentRoad(); - std::vector<Road>& getRoads(); + std::vector<TrackCA>& getTracksCA(); TrackCA& getCurrentTrackCA(); - void removeCurrentTrackCA(); - template <typename... T> - void addClusterToLayer(Int_t layer, T&&... args); + Road& getCurrentRoad(); template <typename... T> - void addCellToLayer(Int_t layer, T&&... args); + void addClusterToLayer(Int_t layer, T&&... args); void addClusterLabelToLayer(Int_t layer, const MCCompLabel label); void addClusterExternalIndexToLayer(Int_t layer, const Int_t idx); - void addClusterBinIndexRangeToLayer(Int_t layer, const std::pair<Int_t, std::pair<Int_t, Int_t>> range); + void addTrackLTF() { mTracksLTF.emplace_back(); } - void addTrackCA(); + void addTrackCA(const Int_t); + void addRoad(); - void initialise(); - void sortClusters(); + void initialize(); - Bool_t isClusterUsed(Int_t layer, Int_t clusterId) const; - void markUsedCluster(Int_t layer, Int_t clusterId); + void sortClusters(); void clear(); + const Int_t getNClustersInLayer(Int_t layerId) const { return mClusters[layerId].size(); } + private: Int_t mROframeId; std::array<std::vector<Cluster>, constants::mft::LayersNumber> mClusters; std::array<std::vector<MCCompLabel>, constants::mft::LayersNumber> mClusterLabels; std::array<std::vector<Int_t>, constants::mft::LayersNumber> mClusterExternalIndices; - std::array<std::map<Int_t, std::pair<Int_t, Int_t>>, constants::mft::LayersNumber> mClusterBinIndexRange; - std::array<std::vector<Bool_t>, constants::mft::LayersNumber> mUsedClusters; - std::array<std::vector<Cell>, constants::mft::LayersNumber> mCells; + std::array<std::array<std::pair<Int_t, Int_t>, constants::index_table::RPhiBins>, constants::mft::LayersNumber> mClusterBinIndexRange; std::vector<TrackLTF> mTracksLTF; std::vector<TrackCA> mTracksCA; std::vector<Road> mRoads; @@ -117,34 +108,11 @@ inline void ROframe::addClusterExternalIndexToLayer(Int_t layer, const Int_t idx mClusterExternalIndices[layer].push_back(idx); } -inline void ROframe::addClusterBinIndexRangeToLayer(Int_t layer, const std::pair<Int_t, std::pair<Int_t, Int_t>> range) -{ - mClusterBinIndexRange[layer].insert(range); -} - -template <typename... T> -void ROframe::addCellToLayer(Int_t layer, T&&... values) -{ - mCells[layer].emplace_back(layer, std::forward<T>(values)...); -} - -inline Bool_t ROframe::isClusterUsed(Int_t layer, Int_t clusterId) const -{ - return mUsedClusters[layer][clusterId]; -} - -inline void ROframe::markUsedCluster(Int_t layer, Int_t clusterId) { mUsedClusters[layer][clusterId] = kTRUE; } - inline TrackLTF& ROframe::getCurrentTrackLTF() { return mTracksLTF.back(); } -inline void ROframe::removeCurrentTrackLTF() -{ - mTracksLTF.pop_back(); -} - inline std::vector<TrackLTF>& ROframe::getTracksLTF() { return mTracksLTF; @@ -153,7 +121,6 @@ inline std::vector<TrackLTF>& ROframe::getTracksLTF() inline void ROframe::addRoad() { mRoads.emplace_back(); - mRoads.back().setRoadId(mRoads.size() - 1); } inline Road& ROframe::getCurrentRoad() @@ -161,28 +128,16 @@ inline Road& ROframe::getCurrentRoad() return mRoads.back(); } -inline void ROframe::removeCurrentRoad() -{ - mRoads.pop_back(); -} - -inline std::vector<Road>& ROframe::getRoads() +inline void ROframe::addTrackCA(const Int_t roadId) { - return mRoads; + mTracksCA.emplace_back(); } -inline void ROframe::addTrackCA() { mTracksCA.emplace_back(); } - inline TrackCA& ROframe::getCurrentTrackCA() { return mTracksCA.back(); } -inline void ROframe::removeCurrentTrackCA() -{ - mTracksCA.pop_back(); -} - inline std::vector<TrackCA>& ROframe::getTracksCA() { return mTracksCA; @@ -194,8 +149,9 @@ inline void ROframe::clear() mClusters[iLayer].clear(); mClusterLabels[iLayer].clear(); mClusterExternalIndices[iLayer].clear(); - mClusterBinIndexRange[iLayer].clear(); - mCells[iLayer].clear(); + for (Int_t iBin = 0; iBin < constants::index_table::RPhiBins; ++iBin) { + mClusterBinIndexRange[iLayer][iBin] = std::pair<Int_t, Int_t>(0, -1); + } } mTracksLTF.clear(); mTracksCA.clear(); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h index c458549c4bdad..76efc41e89ac5 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h @@ -17,7 +17,6 @@ #include "MFTTracking/Cell.h" #include "MFTTracking/Constants.h" -#include "SimulationDataFormat/MCCompLabel.h" namespace o2 { @@ -28,88 +27,59 @@ class Road final { public: Road(); - void setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint); + + void setPoint(const Int_t layer, const Int_t clusterId) + { + mClusterId[layer].push_back(clusterId); + } + void setRoadId(const Int_t id) { mRoadId = id; } const Int_t getRoadId() const { return mRoadId; } - void setNDisks(const Int_t nd) { mNDisks = nd; } - const Int_t getNDisks() const { return mNDisks; } - const Int_t getNPoints() const { return mNPoints; } + const Int_t getNPointsInLayer(Int_t layer) const; + void getLength(Int_t& layer1, Int_t& layer2) const; - void setHasTracksCA() { mHasTracksCA = kTRUE; } - const Bool_t hasTracksCA() const; - const std::vector<Float_t>& getXCoordinatesInLayer(Int_t layer) const { return mX[layer]; } - const std::vector<Float_t>& getYCoordinatesInLayer(Int_t layer) const { return mY[layer]; } - const std::vector<Float_t>& getZCoordinatesInLayer(Int_t layer) const { return mZ[layer]; } const std::vector<Int_t>& getClustersIdInLayer(Int_t layer) const { return mClusterId[layer]; } - const std::vector<MCCompLabel>& getMCCompLabelsInLayer(Int_t layer) const { return mMCCompLabel[layer]; } template <typename... T> - void addCellToLayer(Int_t layer, T&&... args); + Cell& addCellInLayer(Int_t layer, T&&... args); + + std::vector<Cell>& getCellsInLayer(Int_t); - const std::vector<Cell>& getCellsInLayer(Int_t) const; void addLeftNeighbourToCell(const Int_t, const Int_t, const Int_t, const Int_t); void addRightNeighbourToCell(const Int_t, const Int_t, const Int_t, const Int_t); + void incrementCellLevel(const Int_t, const Int_t); void updateCellLevel(const Int_t, const Int_t); + + void setCellLevel(const Int_t, const Int_t, const Int_t); const Int_t getCellLevel(const Int_t, const Int_t) const; - const Bool_t isCellUsed(const Int_t, const Int_t) const; void setCellUsed(const Int_t, const Int_t, const Bool_t); - void setCellLevel(const Int_t, const Int_t, const Int_t); + const Bool_t isCellUsed(const Int_t, const Int_t) const; private: Int_t mRoadId; - Int_t mNDisks; - Int_t mNPoints; - Bool_t mHasTracksCA; - std::array<std::vector<Float_t>, constants::mft::LayersNumber> mX; - std::array<std::vector<Float_t>, constants::mft::LayersNumber> mY; - std::array<std::vector<Float_t>, constants::mft::LayersNumber> mZ; std::array<std::vector<Int_t>, constants::mft::LayersNumber> mClusterId; - std::array<std::vector<MCCompLabel>, constants::mft::LayersNumber> mMCCompLabel; std::array<std::vector<Cell>, (constants::mft::LayersNumber - 1)> mCell; }; inline Road::Road() - : mRoadId{0}, - mNDisks{0}, - mNPoints{0} + : mRoadId{0} { // Nothing to do } -inline void Road::setPoint(const Float_t x, const Float_t y, const Float_t z, const Int_t layer, const Int_t clusterId, const MCCompLabel label, Bool_t& newPoint) -{ - if (!newPoint) { - if (!mZ.empty()) { - mX[layer].pop_back(); - mY[layer].pop_back(); - mZ[layer].pop_back(); - mClusterId[layer].pop_back(); - mMCCompLabel[layer].pop_back(); - } - } else { // end replace point - newPoint = kFALSE; - } - mX[layer].push_back(x); - mY[layer].push_back(y); - mZ[layer].push_back(z); - mClusterId[layer].push_back(clusterId); - mMCCompLabel[layer].emplace_back(label); - ++mNPoints; -} - inline const Int_t Road::getNPointsInLayer(Int_t layer) const { - return mX[layer].size(); + return mClusterId[layer].size(); } inline void Road::getLength(Int_t& layer1, Int_t& layer2) const { layer1 = -1, layer2 = 10; for (Int_t layer = 0; layer < constants::mft::LayersNumber; ++layer) { - if (mX[layer].size() > 0) { + if (mClusterId[layer].size() > 0) { if (layer1 < 0) { layer1 = layer; } @@ -118,18 +88,14 @@ inline void Road::getLength(Int_t& layer1, Int_t& layer2) const } } -inline const Bool_t Road::hasTracksCA() const -{ - return mHasTracksCA; -} - template <typename... T> -void Road::addCellToLayer(Int_t layer, T&&... values) +Cell& Road::addCellInLayer(Int_t layer, T&&... values) { mCell[layer].emplace_back(layer, std::forward<T>(values)...); + return mCell[layer].back(); } -inline const std::vector<Cell>& Road::getCellsInLayer(Int_t layer) const +inline std::vector<Cell>& Road::getCellsInLayer(Int_t layer) { return mCell[layer]; } diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h index 779c75efe27f5..8dc5a213314c0 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackCA.h @@ -41,7 +41,7 @@ class TrackLTF : public TrackMFTExt const std::array<Int_t, constants::mft::LayersNumber>& getLayers() const { return mLayer; } const std::array<Int_t, constants::mft::LayersNumber>& getClustersId() const { return mClusterId; } const std::array<MCCompLabel, constants::mft::LayersNumber>& getMCCompLabels() const { return mMCCompLabels; } - void setPoint(const Cluster, const Int_t layer, const Int_t clusterId, const MCCompLabel label, const Int_t extClsIndex, Bool_t& newPoint); + void setPoint(const Cluster& cl, const Int_t layer, const Int_t clusterId, const MCCompLabel label, const Int_t extClsIndex); void sort(); @@ -54,97 +54,50 @@ class TrackLTF : public TrackMFTExt std::array<Int_t, constants::mft::LayersNumber> mLayer; std::array<Int_t, constants::mft::LayersNumber> mClusterId; std::array<MCCompLabel, constants::mft::LayersNumber> mMCCompLabels; + + ClassDefNV(TrackLTF, 10); }; //_________________________________________________________________________________________________ class TrackCA : public TrackLTF { public: - TrackCA() = default; + TrackCA() + { + TrackLTF(); + this->setCA(true); + } TrackCA(const TrackCA& t) = default; ~TrackCA() = default; - void addCell(const Int_t, const Int_t); - void removeLastCell(Int_t&, Int_t&); - const Int_t getNCells() const { return mNCells; } - void setRoadId(const Int_t rid) { mRoadId = rid; } - const Int_t getRoadId() const { return mRoadId; } - void setChiSquareZX(const Float_t chisq) { mChiSquareZX = chisq; } - void setChiSquareZY(const Float_t chisq) { mChiSquareZY = chisq; } - const Float_t getChiSquareZX() const { return mChiSquareZX; } - const Float_t getChiSquareZY() const { return mChiSquareZY; } - - const std::array<Int_t, constants::mft::LayersNumber>& getCellsLayer() const { return mCellLayer; } - const std::array<Int_t, constants::mft::LayersNumber>& getCellsId() const { return mCellId; } private: - Int_t mNCells{0}; - Int_t mRoadId{-1}; - Float_t mChiSquareZX{0.}; - Float_t mChiSquareZY{0.}; - - std::array<Int_t, constants::mft::LayersNumber> mCellLayer; - std::array<Int_t, constants::mft::LayersNumber> mCellId; - ClassDefNV(TrackCA, 2); + ClassDefNV(TrackCA, 10); }; //_________________________________________________________________________________________________ -inline void TrackCA::addCell(const Int_t layer, const Int_t cellId) -{ - mCellLayer[mNCells] = layer; - mCellId[mNCells] = cellId; - mNCells++; -} - -//_________________________________________________________________________________________________ -inline void TrackCA::removeLastCell(Int_t& layer, Int_t& cellId) +inline void TrackLTF::setPoint(const Cluster& cl, const Int_t layer, const Int_t clusterId, const MCCompLabel label, const Int_t extClsIndex) { - layer = mCellLayer[mNCells - 1]; - cellId = mCellId[mNCells - 1]; - auto nPoints = getNumberOfPoints(); - if (nPoints == 2) { // we have only a single cell in the track - setNumberOfPoints(--nPoints); - } - setNumberOfPoints(--nPoints); - mNCells--; -} - -//_________________________________________________________________________________________________ -inline void TrackLTF::setPoint(const Cluster cl, const Int_t layer, const Int_t clusterId, const MCCompLabel label, const Int_t extClsIndex, Bool_t& newPoint) -{ - auto nPoints = getNumberOfPoints(); - if (newPoint) { - if (nPoints > 0) { - if (mZ[nPoints - 1] == cl.getZ()) { - LOG(WARN) << "MFT TrackLTF: skipping setPoint (1 cluster per layer!)"; - return; - } - } - if (nPoints > constants::mft::LayersNumber) { - LOG(WARN) << "MFT TrackLTF Overflow"; + if (nPoints > 0) { + if (mZ[nPoints - 1] == cl.getZ()) { + LOG(WARN) << "MFT TrackLTF: skipping setPoint (1 cluster per layer!)"; return; } - mX[nPoints] = cl.getX(); - mY[nPoints] = cl.getY(); - mZ[nPoints] = cl.getZ(); - mSigmaX2[nPoints] = cl.sigmaX2; - mSigmaY2[nPoints] = cl.sigmaY2; - mLayer[nPoints] = layer; - mClusterId[nPoints] = clusterId; - mMCCompLabels[nPoints] = label; - setExternalClusterIndex(nPoints, extClsIndex); - setNumberOfPoints(nPoints + 1); - } else { - mX[nPoints] = cl.getX(); - mY[nPoints] = cl.getY(); - mZ[nPoints] = cl.getZ(); - mSigmaX2[nPoints] = cl.sigmaX2; - mSigmaY2[nPoints] = cl.sigmaY2; - mLayer[nPoints] = layer; - mClusterId[nPoints] = clusterId; - mMCCompLabels[nPoints] = label; - setExternalClusterIndex(nPoints, extClsIndex); } + if (nPoints > constants::mft::LayersNumber) { + LOG(WARN) << "MFT TrackLTF Overflow"; + return; + } + mX[nPoints] = cl.getX(); + mY[nPoints] = cl.getY(); + mZ[nPoints] = cl.getZ(); + mSigmaX2[nPoints] = cl.sigmaX2; + mSigmaY2[nPoints] = cl.sigmaY2; + mLayer[nPoints] = layer; + mClusterId[nPoints] = clusterId; + mMCCompLabels[nPoints] = label; + setExternalClusterIndex(nPoints, extClsIndex); + setNumberOfPoints(nPoints + 1); } //_________________________________________________________________________________________________ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 45b0fc2792eba..b5764ad749b9c 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -26,6 +26,9 @@ #include "SimulationDataFormat/MCTruthContainer.h" #include "DataFormatsParameters/GRPObject.h" +// BV +#include "TStopwatch.h" + namespace o2 { namespace mft @@ -58,12 +61,14 @@ class Tracker void setROFrame(std::uint32_t f) { mROFrame = f; } std::uint32_t getROFrame() const { return mROFrame; } + // BV + void initialize(); + private: void findTracks(ROframe&); void findTracksLTF(ROframe&); void findTracksCA(ROframe&); - void computeCells(ROframe&); - void computeCellsInRoad(Road&); + void computeCellsInRoad(ROframe&); void runForwardInRoad(ROframe&); void runBackwardInRoad(ROframe&); void updateCellStatusInRoad(Road&); @@ -72,14 +77,11 @@ class Tracker const Int_t isDiskFace(Int_t layer) const { return (layer % 2); } const Float_t getDistanceToSeed(const Cluster&, const Cluster&, const Cluster&) const; - void getRPhiProjectionBin(const Cluster&, const Int_t, const Int_t, Int_t&, Int_t&) const; - Bool_t getBinClusterRange(const ROframe&, const Int_t, const Int_t, Int_t&, Int_t&) const; - const Float_t getCellDeviation(const ROframe&, const Cell&, const Cell&) const; - const Bool_t getCellsConnect(const ROframe&, const Cell&, const Cell&) const; - const Float_t getCellChisquare(ROframe&, const Cell&) const; - const Bool_t addCellToCurrentTrackCA(const Int_t, const Int_t, ROframe&); - - const Bool_t LinearRegression(Int_t, Float_t*, Float_t*, Float_t*, Float_t&, Float_t&, Float_t&, Float_t&, Float_t&, Int_t skip = -1) const; + void getBinClusterRange(const ROframe&, const Int_t, const Int_t, Int_t&, Int_t&) const; + const Float_t getCellDeviation(const Cell&, const Cell&) const; + const Bool_t getCellsConnect(const Cell&, const Cell&) const; + void addCellToCurrentTrackCA(const Int_t, const Int_t, ROframe&); + void addCellToCurrentRoad(ROframe&, const Int_t, const Int_t, const Int_t, const Int_t, Int_t&); Float_t mBz = 5.f; std::uint32_t mROFrame = 0; @@ -92,6 +94,14 @@ class Tracker Int_t mMaxCellLevel = 0; bool mUseMC = false; + + std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::RPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBinsS; + std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::RPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBins; + + struct TrackElement { + Int_t layer; + Int_t idInLayer; + }; }; //_________________________________________________________________________________________________ @@ -99,91 +109,36 @@ inline const Float_t Tracker::getDistanceToSeed(const Cluster& cluster1, const C { // the seed is between "cluster1" and "cluster2" and cuts the plane // of the "cluster" at a distance dR from it - Float_t dxSeed, dySeed, dzSeed, dz, dR, xSeed, ySeed; + Float_t dxSeed, dySeed, dzSeed, invdzSeed, dz, dR, xSeed, ySeed; dxSeed = cluster2.getX() - cluster1.getX(); dySeed = cluster2.getY() - cluster1.getY(); dzSeed = cluster2.getZ() - cluster1.getZ(); dz = cluster.getZ() - cluster1.getZ(); - xSeed = cluster1.getX() + dxSeed * dz / dzSeed; - ySeed = cluster1.getY() + dySeed * dz / dzSeed; + invdzSeed = dz / dzSeed; + xSeed = cluster1.getX() + dxSeed * invdzSeed; + ySeed = cluster1.getY() + dySeed * invdzSeed; dR = std::sqrt((cluster.getX() - xSeed) * (cluster.getX() - xSeed) + (cluster.getY() - ySeed) * (cluster.getY() - ySeed)); return dR; } //_________________________________________________________________________________________________ -inline void Tracker::getRPhiProjectionBin(const Cluster& cluster1, const Int_t layer1, const Int_t layer, Int_t& binR_proj, Int_t& binPhi_proj) const -{ - Float_t dz, x_proj, y_proj, r_proj, phi_proj; - dz = constants::mft::LayerZCoordinate()[layer] - constants::mft::LayerZCoordinate()[layer1]; - x_proj = cluster1.getX() + dz * cluster1.getX() * constants::mft::InverseLayerZCoordinate()[layer1]; - y_proj = cluster1.getY() + dz * cluster1.getY() * constants::mft::InverseLayerZCoordinate()[layer1]; - auto clsPoint2D = math_utils::Point2D<Float_t>(x_proj, y_proj); - r_proj = clsPoint2D.R(); - phi_proj = clsPoint2D.Phi(); - o2::math_utils::bringTo02PiGen(phi_proj); - binR_proj = constants::index_table::getRBinIndex(r_proj); - binPhi_proj = constants::index_table::getPhiBinIndex(phi_proj); - return; -} - -//_________________________________________________________________________________________________ -inline Bool_t Tracker::getBinClusterRange(const ROframe& event, const Int_t layer, const Int_t bin, Int_t& clsMinIndex, Int_t& clsMaxIndex) const +inline void Tracker::getBinClusterRange(const ROframe& event, const Int_t layer, const Int_t bin, Int_t& clsMinIndex, Int_t& clsMaxIndex) const { - const auto pair2 = event.getClusterBinIndexRange(layer).find(bin); - if (pair2 == event.getClusterBinIndexRange(layer).end()) { - return kFALSE; - } - Int_t binIndex = pair2->first; - // get the range in ordered cluster index within this bin - std::pair<Int_t, Int_t> pair1 = pair2->second; - clsMinIndex = pair1.first; - clsMaxIndex = pair1.second; - return kTRUE; + const auto& pair = event.getClusterBinIndexRange(layer)[bin]; + clsMinIndex = pair.first; + clsMaxIndex = pair.second; } //_________________________________________________________________________________________________ -inline const Float_t Tracker::getCellDeviation(const ROframe& event, const Cell& cell1, const Cell& cell2) const +inline const Float_t Tracker::getCellDeviation(const Cell& cell1, const Cell& cell2) const { - Int_t cell1layer1 = cell1.getFirstLayerId(); - Int_t cell1layer2 = cell1.getSecondLayerId(); - - Int_t cell2layer1 = cell2.getFirstLayerId(); - Int_t cell2layer2 = cell2.getSecondLayerId(); - - Int_t cell1cls1 = cell1.getFirstClusterIndex(); - Int_t cell1cls2 = cell1.getSecondClusterIndex(); - - Int_t cell2cls1 = cell2.getFirstClusterIndex(); - Int_t cell2cls2 = cell2.getSecondClusterIndex(); - - auto cluster11 = event.getClustersInLayer(cell1layer1)[cell1cls1]; - auto cluster12 = event.getClustersInLayer(cell1layer2)[cell1cls2]; - auto cluster21 = event.getClustersInLayer(cell2layer1)[cell2cls1]; - auto cluster22 = event.getClustersInLayer(cell2layer2)[cell2cls2]; + Float_t cell1dx = cell1.getX2() - cell1.getX1(); + Float_t cell1dy = cell1.getY2() - cell1.getY1(); + Float_t cell1dz = cell1.getZ2() - cell1.getZ1(); - Float_t cell1x1 = cluster11.getX(); - Float_t cell1y1 = cluster11.getY(); - Float_t cell1z1 = cluster11.getZ(); - - Float_t cell1x2 = cluster12.getX(); - Float_t cell1y2 = cluster12.getY(); - Float_t cell1z2 = cluster12.getZ(); - - Float_t cell2x1 = cluster21.getX(); - Float_t cell2y1 = cluster21.getY(); - Float_t cell2z1 = cluster21.getZ(); - - Float_t cell2x2 = cluster22.getX(); - Float_t cell2y2 = cluster22.getY(); - Float_t cell2z2 = cluster22.getZ(); - - Float_t cell1dx = cell1x2 - cell1x1; - Float_t cell1dy = cell1y2 - cell1y1; - Float_t cell1dz = cell1z2 - cell1z1; - - Float_t cell2dx = cell2x2 - cell2x1; - Float_t cell2dy = cell2y2 - cell2y1; - Float_t cell2dz = cell2z2 - cell2z1; + Float_t cell2dx = cell2.getX2() - cell2.getX1(); + Float_t cell2dy = cell2.getY2() - cell2.getY1(); + Float_t cell2dz = cell2.getZ2() - cell2.getZ1(); Float_t cell1mod = std::sqrt(cell1dx * cell1dx + cell1dy * cell1dy + cell1dz * cell1dz); Float_t cell2mod = std::sqrt(cell2dx * cell2dx + cell2dy * cell2dy + cell2dz * cell2dz); @@ -194,49 +149,12 @@ inline const Float_t Tracker::getCellDeviation(const ROframe& event, const Cell& } //_________________________________________________________________________________________________ -inline const Bool_t Tracker::getCellsConnect(const ROframe& event, const Cell& cell1, const Cell& cell2) const +inline const Bool_t Tracker::getCellsConnect(const Cell& cell1, const Cell& cell2) const { - Int_t cell1layer1 = cell1.getFirstLayerId(); - Int_t cell1layer2 = cell1.getSecondLayerId(); - - Int_t cell2layer1 = cell2.getFirstLayerId(); - Int_t cell2layer2 = cell2.getSecondLayerId(); - - Int_t cell1cls1 = cell1.getFirstClusterIndex(); - Int_t cell1cls2 = cell1.getSecondClusterIndex(); - - Int_t cell2cls1 = cell2.getFirstClusterIndex(); - Int_t cell2cls2 = cell2.getSecondClusterIndex(); - - auto cluster11 = event.getClustersInLayer(cell1layer1)[cell1cls1]; - auto cluster12 = event.getClustersInLayer(cell1layer2)[cell1cls2]; - auto cluster21 = event.getClustersInLayer(cell2layer1)[cell2cls1]; - auto cluster22 = event.getClustersInLayer(cell2layer2)[cell2cls2]; - - Float_t cell1x1 = cluster11.getX(); - Float_t cell1y1 = cluster11.getY(); - //Float_t cell1z1 = cluster11.getZ(); - - Float_t cell1x2 = cluster12.getX(); - Float_t cell1y2 = cluster12.getY(); - //Float_t cell1z2 = cluster12.getZ(); - - Float_t cell2x1 = cluster21.getX(); - Float_t cell2y1 = cluster21.getY(); - //Float_t cell2z1 = cluster21.getZ(); - - Float_t cell2x2 = cluster22.getX(); - Float_t cell2y2 = cluster22.getY(); - //Float_t cell2z2 = cluster22.getZ(); - - Float_t cell1dx = cell1x2 - cell1x1; - Float_t cell1dy = cell1y2 - cell1y1; - //Float_t cell1dz = cell1z2 - cell1z1; - - Float_t cell2dx = cell2x2 - cell2x1; - Float_t cell2dy = cell2y2 - cell2y1; - //Float_t cell2dz = cell2z2 - cell2z1; - + Float_t cell1x2 = cell1.getX2(); + Float_t cell1y2 = cell1.getY2(); + Float_t cell2x1 = cell2.getX1(); + Float_t cell2y1 = cell2.getY1(); Float_t dx = cell1x2 - cell2x1; Float_t dy = cell1y2 - cell2y1; Float_t dr = std::sqrt(dx * dx + dy * dy); diff --git a/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx b/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx index 78aedf7fea6d3..21b1ae72a27a7 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/ROframe.cxx @@ -33,14 +33,9 @@ Int_t ROframe::getTotalClusters() const return Int_t(totalClusters); } -void ROframe::initialise() +void ROframe::initialize() { sortClusters(); - - for (Int_t layer = 0; layer < constants::mft::LayersNumber; ++layer) { - mUsedClusters[layer].clear(); - mUsedClusters[layer].resize(mClusters[layer].size(), kFALSE); - } } void ROframe::sortClusters() @@ -55,7 +50,7 @@ void ROframe::sortClusters() sort(mClusters[iLayer].begin(), mClusters[iLayer].end(), [](Cluster& c1, Cluster& c2) { return c1.indexTableBin < c2.indexTableBin; }); // find the cluster local index range in each bin - // index = element position vector in the vector + // index = element position in the vector nClsInLayer = mClusters[iLayer].size(); binPrevIndex = mClusters[iLayer].at(0).indexTableBin; clsMinIndex = 0; @@ -63,16 +58,19 @@ void ROframe::sortClusters() if (mClusters[iLayer].at(jClsLayer).indexTableBin == binPrevIndex) { continue; } + clsMaxIndex = jClsLayer - 1; - std::pair<Int_t, Int_t> pair1(clsMinIndex, clsMaxIndex); - mClusterBinIndexRange[iLayer].insert(std::pair<Int_t, std::pair<Int_t, Int_t>>(binPrevIndex, pair1)); + + mClusterBinIndexRange[iLayer][binPrevIndex] = std::pair<Int_t, Int_t>(clsMinIndex, clsMaxIndex); + binPrevIndex = mClusters[iLayer].at(jClsLayer).indexTableBin; clsMinIndex = jClsLayer; } // clusters + // last cluster clsMaxIndex = jClsLayer - 1; - std::pair<Int_t, Int_t> pair1(clsMinIndex, clsMaxIndex); - mClusterBinIndexRange[iLayer].insert(std::pair<Int_t, std::pair<Int_t, Int_t>>(binPrevIndex, pair1)); + + mClusterBinIndexRange[iLayer][binPrevIndex] = std::pair<Int_t, Int_t>(clsMinIndex, clsMaxIndex); } // layers } diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index acc564d173544..bf8e7c23f2f11 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -40,6 +40,87 @@ void Tracker::setBz(Float_t bz) mTrackFitter->setBz(bz); } +//_________________________________________________________________________________________________ +void Tracker::initialize() +{ + /// calculate Look-Up-Table of the R-Phi bins projection from one layer to another + /// layer1 + global R-Phi bin index ---> layer2 + R bin index + Phi bin index + + Float_t dz, x, y, r, phi, x_proj, y_proj, r_proj, phi_proj; + Int_t binIndex1, binIndex2, binIndex2S, binR_proj, binPhi_proj; + + for (Int_t layer1 = 0; layer1 < (constants::mft::LayersNumber - 1); ++layer1) { + + for (Int_t iRBin = 0; iRBin < constants::index_table::RBins; ++iRBin) { + + r = (iRBin + 0.5) * constants::index_table::RBinSize + constants::index_table::RMin; + + for (Int_t iPhiBin = 0; iPhiBin < constants::index_table::PhiBins; ++iPhiBin) { + + phi = (iPhiBin + 0.5) * constants::index_table::PhiBinSize + constants::index_table::PhiMin; + + binIndex1 = constants::index_table::getBinIndex(iRBin, iPhiBin); + + x = r * TMath::Cos(phi); + y = r * TMath::Sin(phi); + + for (Int_t layer2 = (layer1 + 1); layer2 < constants::mft::LayersNumber; ++layer2) { + + dz = constants::mft::LayerZCoordinate()[layer2] - constants::mft::LayerZCoordinate()[layer1]; + x_proj = x + dz * x * constants::mft::InverseLayerZCoordinate()[layer1]; + y_proj = y + dz * y * constants::mft::InverseLayerZCoordinate()[layer1]; + auto clsPoint2D = math_utils::Point2D<Float_t>(x_proj, y_proj); + r_proj = clsPoint2D.R(); + phi_proj = clsPoint2D.Phi(); + o2::math_utils::bringTo02PiGen(phi_proj); + + binR_proj = constants::index_table::getRBinIndex(r_proj); + binPhi_proj = constants::index_table::getPhiBinIndex(phi_proj); + + int binRS, binPhiS; + int binhwS = constants::index_table::LTFseed2BinWin / 2; + for (Int_t iR = 0; iR < constants::index_table::LTFseed2BinWin; ++iR) { + binRS = binR_proj + (iR - binhwS); + if (binRS < 0) { + continue; + } + + for (Int_t iPhi = 0; iPhi < constants::index_table::LTFseed2BinWin; ++iPhi) { + binPhiS = binPhi_proj + (iPhi - binhwS); + if (binPhiS < 0) { + continue; + } + + binIndex2S = constants::index_table::getBinIndex(binRS, binPhiS); + mBinsS[layer1][layer2 - 1][binIndex1].emplace_back(binIndex2S); + } + } + + int binR, binPhi; + int binhw = constants::index_table::LTFinterBinWin / 2; + for (Int_t iR = 0; iR < constants::index_table::LTFinterBinWin; ++iR) { + binR = binR_proj + (iR - binhw); + if (binR < 0) { + continue; + } + + for (Int_t iPhi = 0; iPhi < constants::index_table::LTFinterBinWin; ++iPhi) { + binPhi = binPhi_proj + (iPhi - binhw); + if (binPhi < 0) { + continue; + } + + binIndex2 = constants::index_table::getBinIndex(binR, binPhi); + mBins[layer1][layer2 - 1][binIndex1].emplace_back(binIndex2); + } + } + + } // end loop layer2 + } // end loop PhiBinIndex + } // end loop RBinIndex + } // end loop layer1 +} + //_________________________________________________________________________________________________ void Tracker::clustersToTracks(ROframe& event, std::ostream& timeBenchmarkOutputStream) { @@ -57,49 +138,6 @@ void Tracker::findTracks(ROframe& event) findTracksCA(event); } -//_________________________________________________________________________________________________ -void Tracker::computeCells(ROframe& event) -{ - MCCompLabel mcCompLabel; - Int_t layer1, layer2; - Int_t nClsInLayer1, nClsInLayer2; - Int_t disk1, disk2; - Int_t binR_proj, binPhi_proj, bin; - Int_t binIndex, clsMinIndex, clsMaxIndex; - std::array<Int_t, 3> binsR, binsPhi; - Int_t cellId = 0; - for (layer1 = 0; layer1 < (constants::mft::LayersNumber - 1); ++layer1) { - nClsInLayer1 = event.getClustersInLayer(layer1).size(); - disk1 = layer1 / 2; - layer2 = layer1 + 1; // only (L+1) tracklets ! - disk2 = layer2 / 2; - nClsInLayer2 = event.getClustersInLayer(layer2).size(); - for (Int_t clsLayer1 = 0; clsLayer1 < nClsInLayer1; ++clsLayer1) { - const Cluster& cluster1 = event.getClustersInLayer(layer1).at(clsLayer1); - // project to next layer and get the bin index in R and Phi - getRPhiProjectionBin(cluster1, layer1, layer2, binR_proj, binPhi_proj); - // define the search window in bins x bins (3x3, 5x5, etc.) - for (Int_t i = 0; i < constants::index_table::LTFinterBinWin; ++i) { - binsR[i] = binR_proj + (i - constants::index_table::LTFinterBinWin / 2); - binsPhi[i] = binPhi_proj + (i - constants::index_table::LTFinterBinWin / 2); - } - // loop over the bins in the search window - for (auto binR : binsR) { - for (auto binPhi : binsPhi) { - // the global bin index - bin = constants::index_table::getBinIndex(binR, binPhi); - if (!getBinClusterRange(event, layer2, bin, clsMinIndex, clsMaxIndex)) { - continue; - } - for (Int_t clsLayer2 = clsMinIndex; clsLayer2 <= clsMaxIndex; ++clsLayer2) { - event.addCellToLayer(layer1, layer2, clsLayer1, clsLayer2, cellId++); - } // end clusters bin layer2 - } // end binPhi - } // end binR - } // end clusters layer1 - } // end layers -} - //_________________________________________________________________________________________________ void Tracker::findTracksLTF(ROframe& event) { @@ -107,170 +145,139 @@ void Tracker::findTracksLTF(ROframe& event) MCCompLabel mcCompLabel; Int_t layer1, layer2, nPointDisks; - Int_t nClsInLayer1, nClsInLayer2, nClsInLayer; Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; Int_t extClsIndex; Float_t dR, dRmin, dRcut = constants::mft::LTFclsRCut; - std::vector<Int_t> binsR, binsPhi, binsRS, binsPhiS; - Bool_t hasDisk[constants::mft::DisksNumber], newPoint, seed = kTRUE; + Bool_t hasDisk[constants::mft::DisksNumber], newPoint, seed; - binsRS.resize(constants::index_table::LTFseed2BinWin); - binsPhiS.resize(constants::index_table::LTFseed2BinWin); + Int_t clsLayer1, clsLayer2, clsLayer; - binsR.resize(constants::index_table::LTFinterBinWin); - binsPhi.resize(constants::index_table::LTFinterBinWin); + Int_t nPoints; + TrackElement trackPoints[constants::mft::LayersNumber]; Int_t step = 0; - + seed = kTRUE; layer1 = 0; while (seed) { - if (step == 0) { - layer2 = constants::mft::LayersNumber - 1; - } else { - layer2--; - } - + layer2 = (step == 0) ? (constants::mft::LayersNumber - 1) : (layer2 - 1); step++; - if (layer2 < layer1 + (constants::mft::MinTrackPoints - 1)) { + if (layer2 < layer1 + (constants::mft::MinTrackPointsLTF - 1)) { ++layer1; - if (layer1 > (constants::mft::LayersNumber - (constants::mft::MinTrackPoints - 1))) { + if (layer1 > (constants::mft::LayersNumber - (constants::mft::MinTrackPointsLTF - 1))) { break; } step = 0; continue; } - nClsInLayer1 = event.getClustersInLayer(layer1).size(); - nClsInLayer2 = event.getClustersInLayer(layer2).size(); - - for (Int_t clsLayer1 = 0; clsLayer1 < nClsInLayer1; ++clsLayer1) { - if (event.isClusterUsed(layer1, clsLayer1)) { + for (std::vector<Cluster>::iterator it1 = event.getClustersInLayer(layer1).begin(); it1 != event.getClustersInLayer(layer1).end(); ++it1) { + Cluster& cluster1 = *it1; + if (cluster1.getUsed()) { continue; } - const Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; - - // project to the second seed layer and get the bin index in R and Phi - getRPhiProjectionBin(cluster1, layer1, layer2, binR_proj, binPhi_proj); - // define the search window in bins x bins (3x3, 5x5, etc.) - for (Int_t i = 0; i < constants::index_table::LTFseed2BinWin; ++i) { - binsRS[i] = binR_proj + (i - constants::index_table::LTFseed2BinWin / 2); - binsPhiS[i] = binPhi_proj + (i - constants::index_table::LTFseed2BinWin / 2); - } + clsLayer1 = it1 - event.getClustersInLayer(layer1).begin(); + // loop over the bins in the search window - for (auto binRS : binsRS) { - for (auto binPhiS : binsPhiS) { - // the global bin index - bin = constants::index_table::getBinIndex(binRS, binPhiS); - if (!getBinClusterRange(event, layer2, bin, clsMinIndexS, clsMaxIndexS)) { + for (auto& binS : mBinsS[layer1][layer2 - 1][cluster1.indexTableBin]) { + + getBinClusterRange(event, layer2, binS, clsMinIndexS, clsMaxIndexS); + + for (std::vector<Cluster>::iterator it2 = (event.getClustersInLayer(layer2).begin() + clsMinIndexS); it2 != (event.getClustersInLayer(layer2).begin() + clsMaxIndexS + 1); ++it2) { + Cluster& cluster2 = *it2; + if (cluster2.getUsed()) { continue; } - for (Int_t clsLayer2 = clsMinIndexS; clsLayer2 <= clsMaxIndexS; ++clsLayer2) { - if (event.isClusterUsed(layer2, clsLayer2)) { - continue; - } - const Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; + clsLayer2 = it2 - event.getClustersInLayer(layer2).begin(); - for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { - hasDisk[i] = kFALSE; - } + // start a TrackLTF + nPoints = 0; - hasDisk[layer1 / 2] = kTRUE; - hasDisk[layer2 / 2] = kTRUE; + // add the first seed point + trackPoints[nPoints].layer = layer1; + trackPoints[nPoints].idInLayer = clsLayer1; + nPoints++; - // start a track LTF - event.addTrackLTF(); + // intermediate layers + for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { - // add the first seed-point - mcCompLabel = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); newPoint = kTRUE; - extClsIndex = event.getClusterExternalIndex(layer1, cluster1.clusterId); - event.getCurrentTrackLTF().setPoint(cluster1, layer1, clsLayer1, mcCompLabel, extClsIndex, newPoint); - for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { + // loop over the bins in the search window + dRmin = dRcut; + for (auto& bin : mBins[layer1][layer - 1][cluster1.indexTableBin]) { - nClsInLayer = event.getClustersInLayer(layer).size(); + getBinClusterRange(event, layer, bin, clsMinIndex, clsMaxIndex); - newPoint = kTRUE; - - // project to the intermediate layer and get the bin index in R and Phi - getRPhiProjectionBin(cluster1, layer1, layer, binR_proj, binPhi_proj); + for (std::vector<Cluster>::iterator it = (event.getClustersInLayer(layer).begin() + clsMinIndex); it != (event.getClustersInLayer(layer).begin() + clsMaxIndex + 1); ++it) { + Cluster& cluster = *it; + if (cluster.getUsed()) { + continue; + } + clsLayer = it - event.getClustersInLayer(layer).begin(); - // define the search window in bins x bins (3x3, 5x5, etc.) - for (Int_t i = 0; i < constants::index_table::LTFinterBinWin; ++i) { - binsR[i] = binR_proj + (i - constants::index_table::LTFinterBinWin / 2); - binsPhi[i] = binPhi_proj + (i - constants::index_table::LTFinterBinWin / 2); - } - // loop over the bins in the search window - dRmin = dRcut; - for (auto binR : binsR) { - for (auto binPhi : binsPhi) { - // the global bin index - bin = constants::index_table::getBinIndex(binR, binPhi); - if (!getBinClusterRange(event, layer, bin, clsMinIndex, clsMaxIndex)) { - continue; - } - for (Int_t clsLayer = clsMinIndex; clsLayer <= clsMaxIndex; ++clsLayer) { - if (event.isClusterUsed(layer, clsLayer)) { - continue; - } - const Cluster& cluster = event.getClustersInLayer(layer)[clsLayer]; - - dR = getDistanceToSeed(cluster1, cluster2, cluster); - // retain the closest point within a radius dRcut - if (dR >= dRmin) { - continue; - } - dRmin = dR; - - hasDisk[layer / 2] = kTRUE; - mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); - extClsIndex = event.getClusterExternalIndex(layer, cluster.clusterId); - event.getCurrentTrackLTF().setPoint(cluster, layer, clsLayer, mcCompLabel, extClsIndex, newPoint); - // retain only the closest point in DistanceToSeed - newPoint = false; - } // end clusters bin intermediate layer - } // end intermediate layers - } // end binPhi - } // end binR - - // add the second seed-point - mcCompLabel = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); - newPoint = kTRUE; - extClsIndex = event.getClusterExternalIndex(layer2, cluster2.clusterId); - event.getCurrentTrackLTF().setPoint(cluster2, layer2, clsLayer2, mcCompLabel, extClsIndex, newPoint); + dR = getDistanceToSeed(cluster1, cluster2, cluster); + // retain the closest point within a radius dRcut + if (dR >= dRmin) { + continue; + } + dRmin = dR; - // keep only tracks fulfilling the minimum length condition - if (event.getCurrentTrackLTF().getNumberOfPoints() < constants::mft::MinTrackPoints) { - event.removeCurrentTrackLTF(); - continue; - } - nPointDisks = 0; - for (Int_t disk = 0; disk < (constants::mft::DisksNumber); ++disk) { - if (hasDisk[disk]) { - ++nPointDisks; - } - } - if (nPointDisks < constants::mft::MinTrackPoints) { - event.removeCurrentTrackLTF(); - continue; + if (newPoint) { + trackPoints[nPoints].layer = layer; + trackPoints[nPoints].idInLayer = clsLayer; + nPoints++; + } + // retain only the closest point in DistanceToSeed + newPoint = false; + } // end clusters bin intermediate layer + } // end intermediate layers + } // end binRPhi + + // add the second seed point + trackPoints[nPoints].layer = layer2; + trackPoints[nPoints].idInLayer = clsLayer2; + nPoints++; + + // keep only tracks fulfilling the minimum length condition + if (nPoints < constants::mft::MinTrackPointsLTF) { + continue; + } + for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { + hasDisk[i] = kFALSE; + } + for (Int_t point = 0; point < nPoints; ++point) { + auto layer = trackPoints[point].layer; + hasDisk[layer / 2] = kTRUE; + } + nPointDisks = 0; + for (Int_t disk = 0; disk < (constants::mft::DisksNumber); ++disk) { + if (hasDisk[disk]) { + ++nPointDisks; } + } + if (nPointDisks < constants::mft::MinTrackStationsLTF) { + continue; + } + // add a new TrackLTF + event.addTrackLTF(); + for (Int_t point = 0; point < nPoints; ++point) { + auto layer = trackPoints[point].layer; + auto clsLayer = trackPoints[point].idInLayer; + Cluster& cluster = event.getClustersInLayer(layer)[clsLayer]; + mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); + extClsIndex = event.getClusterExternalIndex(layer, cluster.clusterId); + event.getCurrentTrackLTF().setPoint(cluster, layer, clsLayer, mcCompLabel, extClsIndex); // mark the used clusters - //Int_t lay, layMin = 10, layMax = -1; - for (Int_t point = 0; point < event.getCurrentTrackLTF().getNumberOfPoints(); ++point) { - event.markUsedCluster(event.getCurrentTrackLTF().getLayers()[point], event.getCurrentTrackLTF().getClustersId()[point]); - //lay = event.getCurrentTrackLTF().getLayers()[point]; - //layMin = (lay < layMin) ? lay : layMin; - //layMax = (lay > layMax) ? lay : layMax; - } - } // end seed clusters bin layer2 - } // end binPhi - } // end binR - } // end clusters layer1 + cluster.setUsed(true); + } + } // end seed clusters bin layer2 + } // end binRPhi + } // end clusters layer1 } // end seeding } @@ -286,175 +293,158 @@ void Tracker::findTracksCA(ROframe& event) // 3 with 8, 9 Int_t layer1Min = 0, layer1Max = 3; Int_t layer2Min[4] = {6, 6, 8, 8}; - Int_t layer2Max[4] = {9, 9, 9, 9}; + constexpr Int_t layer2Max = constants::mft::LayersNumber - 1; MCCompLabel mcCompLabel; Int_t roadId, nPointDisks; - Int_t nClsInLayer1, nClsInLayer2, nClsInLayer; Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; Float_t dR, dRcut = constants::mft::ROADclsRCut; - std::vector<Int_t> binsR, binsPhi, binsRS, binsPhiS; - Bool_t hasDisk[constants::mft::DisksNumber], newPoint; + Bool_t hasDisk[constants::mft::DisksNumber]; - binsRS.resize(constants::index_table::LTFseed2BinWin); - binsPhiS.resize(constants::index_table::LTFseed2BinWin); + Int_t clsLayer1, clsLayer2, clsLayer; - binsR.resize(constants::index_table::LTFinterBinWin); - binsPhi.resize(constants::index_table::LTFinterBinWin); + Int_t nPoints; + TrackElement roadPoints[10 * constants::mft::LayersNumber]; roadId = 0; for (Int_t layer1 = layer1Min; layer1 <= layer1Max; ++layer1) { - nClsInLayer1 = event.getClustersInLayer(layer1).size(); - - for (Int_t layer2 = layer2Max[layer1]; layer2 >= layer2Min[layer1]; --layer2) { - - nClsInLayer2 = event.getClustersInLayer(layer2).size(); + for (Int_t layer2 = layer2Max; layer2 >= layer2Min[layer1]; --layer2) { - for (Int_t clsLayer1 = 0; clsLayer1 < nClsInLayer1; ++clsLayer1) { - - if (event.isClusterUsed(layer1, clsLayer1)) { + for (std::vector<Cluster>::iterator it1 = event.getClustersInLayer(layer1).begin(); it1 != event.getClustersInLayer(layer1).end(); ++it1) { + Cluster& cluster1 = *it1; + if (cluster1.getUsed()) { continue; } - const Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; - - // project to the second seed layer and get the bin index in R and Phi - getRPhiProjectionBin(cluster1, layer1, layer2, binR_proj, binPhi_proj); - // define the search window in bins x bins (3x3, 5x5, etc.) - for (Int_t i = 0; i < constants::index_table::LTFseed2BinWin; ++i) { - binsRS[i] = binR_proj + (i - constants::index_table::LTFseed2BinWin / 2); - binsPhiS[i] = binPhi_proj + (i - constants::index_table::LTFseed2BinWin / 2); - } + clsLayer1 = it1 - event.getClustersInLayer(layer1).begin(); // loop over the bins in the search window - for (auto binRS : binsRS) { - for (auto binPhiS : binsPhiS) { - // the global bin index - bin = constants::index_table::getBinIndex(binRS, binPhiS); - if (!getBinClusterRange(event, layer2, bin, clsMinIndexS, clsMaxIndexS)) { + for (auto& binS : mBinsS[layer1][layer2 - 1][cluster1.indexTableBin]) { + + getBinClusterRange(event, layer2, binS, clsMinIndexS, clsMaxIndexS); + + for (std::vector<Cluster>::iterator it2 = (event.getClustersInLayer(layer2).begin() + clsMinIndexS); it2 != (event.getClustersInLayer(layer2).begin() + clsMaxIndexS + 1); ++it2) { + Cluster& cluster2 = *it2; + if (cluster2.getUsed()) { continue; } - for (Int_t clsLayer2 = clsMinIndexS; clsLayer2 <= clsMaxIndexS; ++clsLayer2) { - if (event.isClusterUsed(layer2, clsLayer2)) { - continue; - } - const Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; + clsLayer2 = it2 - event.getClustersInLayer(layer2).begin(); - for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { - hasDisk[i] = kFALSE; - } + // start a road + nPoints = 0; - hasDisk[layer1 / 2] = kTRUE; - hasDisk[layer2 / 2] = kTRUE; + // add the first seed point + roadPoints[nPoints].layer = layer1; + roadPoints[nPoints].idInLayer = clsLayer1; + nPoints++; - // start a road - event.addRoad(); + for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { - // add the 1st/2nd road points - mcCompLabel = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); - newPoint = kTRUE; - event.getCurrentRoad().setPoint(cluster1.getX(), cluster1.getY(), cluster1.getZ(), layer1, clsLayer1, mcCompLabel, newPoint); + // loop over the bins in the search window + for (auto& bin : mBins[layer1][layer - 1][cluster1.indexTableBin]) { - for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { + getBinClusterRange(event, layer, bin, clsMinIndex, clsMaxIndex); - nClsInLayer = event.getClustersInLayer(layer).size(); + for (std::vector<Cluster>::iterator it = (event.getClustersInLayer(layer).begin() + clsMinIndex); it != (event.getClustersInLayer(layer).begin() + clsMaxIndex + 1); ++it) { + Cluster& cluster = *it; + if (cluster.getUsed()) { + continue; + } + clsLayer = it - event.getClustersInLayer(layer).begin(); - // project to the intermediate layer and get the bin index in R and Phi - getRPhiProjectionBin(cluster1, layer1, layer, binR_proj, binPhi_proj); - // define the search window in bins x bins (3x3, 5x5, etc.) - for (Int_t i = 0; i < constants::index_table::LTFinterBinWin; ++i) { - binsR[i] = binR_proj + (i - constants::index_table::LTFinterBinWin / 2); - binsPhi[i] = binPhi_proj + (i - constants::index_table::LTFinterBinWin / 2); - } + dR = getDistanceToSeed(cluster1, cluster2, cluster); + // add all points within a radius dRcut + if (dR >= dRcut) { + continue; + } + roadPoints[nPoints].layer = layer; + roadPoints[nPoints].idInLayer = clsLayer; + nPoints++; - // loop over the bins in the search window - for (auto binR : binsR) { - for (auto binPhi : binsPhi) { - // the global bin index - bin = constants::index_table::getBinIndex(binR, binPhi); - if (!getBinClusterRange(event, layer, bin, clsMinIndex, clsMaxIndex)) { - continue; - } - for (Int_t clsLayer = clsMinIndex; clsLayer <= clsMaxIndex; ++clsLayer) { - if (event.isClusterUsed(layer, clsLayer)) { - continue; - } - const Cluster& cluster = event.getClustersInLayer(layer)[clsLayer]; - - dR = getDistanceToSeed(cluster1, cluster2, cluster); - // add all points within a radius dRcut - if (dR >= dRcut) { - continue; - } - hasDisk[layer / 2] = kTRUE; - mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); - newPoint = kTRUE; - event.getCurrentRoad().setPoint(cluster.getX(), cluster.getY(), cluster.getZ(), layer, clsLayer, mcCompLabel, newPoint); - - } // end clusters bin intermediate layer - } // end intermediate layers - } // end binPhi - } // end binR - - // add the second seed-point - mcCompLabel = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); - newPoint = kTRUE; - event.getCurrentRoad().setPoint(cluster2.getX(), cluster2.getY(), cluster2.getZ(), layer2, clsLayer2, mcCompLabel, newPoint); - - // keep only roads fulfilling the minimum length condition - if (event.getCurrentRoad().getNPoints() < constants::mft::MinTrackPoints) { - event.removeCurrentRoad(); - continue; - } - nPointDisks = 0; - for (Int_t disk = 0; disk < (constants::mft::DisksNumber); ++disk) { - if (hasDisk[disk]) { - ++nPointDisks; - } - } - if (nPointDisks < constants::mft::MinTrackPoints) { - event.removeCurrentRoad(); - continue; + } // end clusters bin intermediate layer + } // end intermediate layers + } // end binR + + // add the second seed point + roadPoints[nPoints].layer = layer2; + roadPoints[nPoints].idInLayer = clsLayer2; + nPoints++; + + // keep only roads fulfilling the minimum length condition + if (nPoints < constants::mft::MinTrackPointsCA) { + continue; + } + for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { + hasDisk[i] = kFALSE; + } + for (Int_t point = 0; point < nPoints; ++point) { + auto layer = roadPoints[point].layer; + hasDisk[layer / 2] = kTRUE; + } + nPointDisks = 0; + for (Int_t disk = 0; disk < (constants::mft::DisksNumber); ++disk) { + if (hasDisk[disk]) { + ++nPointDisks; } - event.getCurrentRoad().setNDisks(nPointDisks); - event.getCurrentRoad().setRoadId(roadId); - ++roadId; - - computeCellsInRoad(event.getCurrentRoad()); - runForwardInRoad(event); - runBackwardInRoad(event); - - } // end clusters bin layer2 - } // end binPhiS - } // end binRS - } // end clusters in layer1 - } // end layer2 - } // end layer1 + } + if (nPointDisks < constants::mft::MinTrackStationsCA) { + continue; + } + + event.addRoad(); + for (Int_t point = 0; point < nPoints; ++point) { + auto layer = roadPoints[point].layer; + auto clsLayer = roadPoints[point].idInLayer; + event.getCurrentRoad().setPoint(layer, clsLayer); + } + event.getCurrentRoad().setRoadId(roadId); + ++roadId; + + computeCellsInRoad(event); + runForwardInRoad(event); + runBackwardInRoad(event); + + } // end clusters in layer2 + } // end binRPhi + } // end clusters in layer1 + } // end layer2 + } // end layer1 } //_________________________________________________________________________________________________ -void Tracker::computeCellsInRoad(Road& road) +void Tracker::computeCellsInRoad(ROframe& event) { Int_t layer1, layer1min, layer1max, layer2, layer2min, layer2max; Int_t nPtsInLayer1, nPtsInLayer2; Int_t clsLayer1, clsLayer2; + Int_t cellId; Bool_t noCell; + Road& road = event.getCurrentRoad(); + road.getLength(layer1min, layer1max); --layer1max; - Int_t cellId = 0; for (layer1 = layer1min; layer1 <= layer1max; ++layer1) { + + cellId = 0; + layer2min = layer1 + 1; layer2max = std::min(layer1 + (constants::mft::DisksNumber - isDiskFace(layer1)), constants::mft::LayersNumber - 1); + nPtsInLayer1 = road.getNPointsInLayer(layer1); + for (Int_t point1 = 0; point1 < nPtsInLayer1; ++point1) { + clsLayer1 = road.getClustersIdInLayer(layer1)[point1]; + layer2 = layer2min; + noCell = kTRUE; while (noCell && (layer2 <= layer2max)) { + nPtsInLayer2 = road.getNPointsInLayer(layer2); /* if (nPtsInLayer2 > 1) { @@ -462,12 +452,15 @@ void Tracker::computeCellsInRoad(Road& road) } */ for (Int_t point2 = 0; point2 < nPtsInLayer2; ++point2) { + clsLayer2 = road.getClustersIdInLayer(layer2)[point2]; + noCell = kFALSE; // create a cell - road.addCellToLayer(layer1, layer2, clsLayer1, clsLayer2, cellId++); + addCellToCurrentRoad(event, layer1, layer2, clsLayer1, clsLayer2, cellId); } // end points in layer2 ++layer2; + } // end while(noCell && (layer2 <= layer2max)) } // end points in layer1 } // end layer1 @@ -491,30 +484,27 @@ void Tracker::runForwardInRoad(ROframe& event) for (layerL = 0; layerL < (constants::mft::LayersNumber - 2); ++layerL) { for (icellL = 0; icellL < road.getCellsInLayer(layerL).size(); ++icellL) { - const Cell& cellL = road.getCellsInLayer(layerL)[icellL]; - if (cellL.getLevel() == 0) { - continue; - } + Cell& cellL = road.getCellsInLayer(layerL)[icellL]; layerR = cellL.getSecondLayerId(); - if (layerR >= (constants::mft::LayersNumber - 1)) { + + if (layerR == (constants::mft::LayersNumber - 1)) { continue; } for (icellR = 0; icellR < road.getCellsInLayer(layerR).size(); ++icellR) { - const Cell& cellR = road.getCellsInLayer(layerR)[icellR]; - if (cellR.getLevel() == 0) { - continue; - } - if ((cellL.getLevel() == cellR.getLevel()) && getCellsConnect(event, cellL, cellR)) { + Cell& cellR = road.getCellsInLayer(layerR)[icellR]; + + if ((cellL.getLevel() == cellR.getLevel()) && getCellsConnect(cellL, cellR)) { if (iter == 1) { road.addRightNeighbourToCell(layerL, icellL, layerR, icellR); road.addLeftNeighbourToCell(layerR, icellR, layerL, icellL); } road.incrementCellLevel(layerR, icellR); levelChange = kTRUE; + } // end matching cells } // end loop cellR } // end loop cellL @@ -534,9 +524,10 @@ void Tracker::runBackwardInRoad(ROframe& event) Bool_t addCellToNewTrack, hasDisk[constants::mft::DisksNumber]; - Int_t iSelectChisquare, iSelectDeviation, lastCellLayer, lastCellId; - Int_t icell, layerC, cellIdC, nPointDisks; - Float_t chisquarePrev, deviationPrev, deviation, chisquare; + Int_t lastCellLayer, lastCellId, icell; + Int_t cellId, layerC, cellIdC, layerRC, cellIdRC, layerL, cellIdL; + Int_t nPointDisks; + Float_t deviationPrev, deviation; // start layer Int_t minLayer = 6; @@ -544,97 +535,72 @@ void Tracker::runBackwardInRoad(ROframe& event) Road& road = event.getCurrentRoad(); + Int_t nCells; + TrackElement trackCells[constants::mft::LayersNumber - 1]; + for (Int_t layer = maxLayer; layer >= minLayer; --layer) { - for (icell = 0; icell < road.getCellsInLayer(layer).size(); ++icell) { - if (road.getCellLevel(layer, icell) == 0) { - continue; - } - if (road.isCellUsed(layer, icell)) { + for (cellId = 0; cellId < road.getCellsInLayer(layer).size(); ++cellId) { + + if (road.isCellUsed(layer, cellId)) { continue; } - if (road.getCellLevel(layer, icell) < (constants::mft::MinTrackPoints - 1)) { + if (road.getCellLevel(layer, cellId) < (constants::mft::MinTrackPointsCA - 1)) { continue; } - // start a track CA - event.addTrackCA(); - event.getCurrentTrackCA().setRoadId(road.getRoadId()); - event.getCurrentTrackCA().setCA(); - if (addCellToCurrentTrackCA(layer, icell, event)) { - road.setCellUsed(layer, icell, kTRUE); - } + // start a TrackCA + nCells = 0; + + trackCells[nCells].layer = layer; + trackCells[nCells].idInLayer = cellId; + nCells++; - // add cells to new track + // add cells to the new track addCellToNewTrack = kTRUE; while (addCellToNewTrack) { - Int_t layerRC = event.getCurrentTrackCA().getCellsLayer()[event.getCurrentTrackCA().getNCells() - 1]; - Int_t cellIdRC = event.getCurrentTrackCA().getCellsId()[event.getCurrentTrackCA().getNCells() - 1]; - const Cell& cellRC = road.getCellsInLayer(layerRC)[cellIdRC]; - addCellToNewTrack = kFALSE; - // find the left neighbor giving the smalles chisquare - iSelectChisquare = 0; - chisquarePrev = 0.; + layerRC = trackCells[nCells - 1].layer; + cellIdRC = trackCells[nCells - 1].idInLayer; - // ... or + const Cell& cellRC = road.getCellsInLayer(layerRC)[cellIdRC]; - // find the left neighbor giving the smallest deviation - iSelectDeviation = 0; - deviationPrev = -1.; + addCellToNewTrack = kFALSE; // loop over left neighbours deviationPrev = o2::constants::math::TwoPI; - chisquarePrev = 1.E5; for (Int_t iLN = 0; iLN < cellRC.getNLeftNeighbours(); ++iLN) { + auto leftNeighbour = cellRC.getLeftNeighbours()[iLN]; - Int_t layerL = leftNeighbour.first; - Int_t cellIdL = leftNeighbour.second; + layerL = leftNeighbour.first; + cellIdL = leftNeighbour.second; const Cell& cellL = road.getCellsInLayer(layerL)[cellIdL]; - if (road.getCellLevel(layerL, cellIdL) == 0) { - continue; - } if (road.isCellUsed(layerL, cellIdL)) { continue; } if (road.getCellLevel(layerL, cellIdL) != (road.getCellLevel(layerRC, cellIdRC) - 1)) { continue; } - /* - // ... smallest deviation - deviation = getCellDeviation(event, cellL, cellRC); + + deviation = getCellDeviation(cellL, cellRC); + if (deviation < deviationPrev) { + deviationPrev = deviation; - if (leftNeighbour != cellRC.getLeftNeighbours().front()) { - event.getCurrentTrackCA().removeLastCell(lastCellLayer, lastCellId); - road.setCellUsed(lastCellLayer, lastCellId, kFALSE); - road.setCellLevel(lastCellLayer, lastCellId, 1); - } - if (addCellToCurrentTrackCA(layerL, cellIdL, event)) { - addCellToNewTrack = kTRUE; - road.setCellUsed(layerL, cellIdL, kTRUE); - } - } - */ - // ... smallest chisquare - chisquare = getCellChisquare(event, cellL); - if (chisquare > 0.0 && chisquare < chisquarePrev) { - chisquarePrev = chisquare; if (leftNeighbour != cellRC.getLeftNeighbours().front()) { - event.getCurrentTrackCA().removeLastCell(lastCellLayer, lastCellId); - road.setCellUsed(lastCellLayer, lastCellId, kFALSE); - road.setCellLevel(lastCellLayer, lastCellId, 1); - } - if (addCellToCurrentTrackCA(layerL, cellIdL, event)) { - addCellToNewTrack = kTRUE; - road.setCellUsed(layerL, cellIdL, kTRUE); - } else { - //LOG(INFO) << "***** Failed to add cell to the current CA track! *****\n"; + // delete the last added cell + nCells--; } + + trackCells[nCells].layer = layerL; + trackCells[nCells].idInLayer = cellIdL; + nCells++; + + addCellToNewTrack = kTRUE; } } // end loop left neighbour @@ -644,36 +610,39 @@ void Tracker::runBackwardInRoad(ROframe& event) for (Int_t i = 0; i < (constants::mft::DisksNumber); ++i) { hasDisk[i] = kFALSE; } - for (icell = 0; icell < event.getCurrentTrackCA().getNCells(); ++icell) { - layerC = event.getCurrentTrackCA().getCellsLayer()[icell]; - cellIdC = event.getCurrentTrackCA().getCellsId()[icell]; - const Cell& cellC = road.getCellsInLayer(layerC)[cellIdC]; - hasDisk[cellC.getFirstLayerId() / 2] = kTRUE; - hasDisk[cellC.getSecondLayerId() / 2] = kTRUE; + + layerC = trackCells[0].layer; + cellIdC = trackCells[0].idInLayer; + const Cell& cellC = event.getCurrentRoad().getCellsInLayer(layerC)[cellIdC]; + hasDisk[cellC.getSecondLayerId() / 2] = kTRUE; + for (icell = 0; icell < nCells; ++icell) { + layerC = trackCells[icell].layer; + cellIdC = trackCells[icell].idInLayer; + hasDisk[layerC / 2] = kTRUE; } + nPointDisks = 0; for (Int_t disk = 0; disk < (constants::mft::DisksNumber); ++disk) { if (hasDisk[disk]) { ++nPointDisks; } } - if (nPointDisks < constants::mft::MinTrackPoints) { - for (icell = 0; icell < event.getCurrentTrackCA().getNCells(); ++icell) { - layerC = event.getCurrentTrackCA().getCellsLayer()[icell]; - cellIdC = event.getCurrentTrackCA().getCellsId()[icell]; - road.setCellUsed(layerC, cellIdC, kFALSE); - road.setCellLevel(layerC, cellIdC, 1); - } - event.removeCurrentTrackCA(); + + if (nPointDisks < constants::mft::MinTrackStationsCA) { continue; } - // marked the used clusters - for (icell = 0; icell < event.getCurrentTrackCA().getNCells(); ++icell) { - layerC = event.getCurrentTrackCA().getCellsLayer()[icell]; - cellIdC = event.getCurrentTrackCA().getCellsId()[icell]; + + // add a new TrackCA + event.addTrackCA(road.getRoadId()); + for (icell = 0; icell < nCells; ++icell) { + layerC = trackCells[icell].layer; + cellIdC = trackCells[icell].idInLayer; + addCellToCurrentTrackCA(layerC, cellIdC, event); + road.setCellUsed(layerC, cellIdC, kTRUE); + // marked the used clusters const Cell& cellC = event.getCurrentRoad().getCellsInLayer(layerC)[cellIdC]; - event.markUsedCluster(cellC.getFirstLayerId(), cellC.getFirstClusterIndex()); - event.markUsedCluster(cellC.getSecondLayerId(), cellC.getSecondClusterIndex()); + event.getClustersInLayer(cellC.getFirstLayerId())[cellC.getFirstClusterIndex()].setUsed(true); + event.getClustersInLayer(cellC.getSecondLayerId())[cellC.getSecondClusterIndex()].setUsed(true); } } // end loop cells } // end loop start layer @@ -691,47 +660,29 @@ void Tracker::updateCellStatusInRoad(Road& road) } //_________________________________________________________________________________________________ -const Float_t Tracker::getCellChisquare(ROframe& event, const Cell& cell) const +void Tracker::addCellToCurrentRoad(ROframe& event, const Int_t layer1, const Int_t layer2, const Int_t clsLayer1, const Int_t clsLayer2, Int_t& cellId) { - // returns the new chisquare of the previous cells plus the new one - TrackCA& trackCA = event.getCurrentTrackCA(); - const Int_t layer2 = cell.getSecondLayerId(); - const Int_t cls2Id = cell.getSecondClusterIndex(); - const Cluster& cluster2 = event.getClustersInLayer(layer2)[cls2Id]; + Road& road = event.getCurrentRoad(); - Float_t x[constants::mft::MaxTrackPoints], y[constants::mft::MaxTrackPoints], z[constants::mft::MaxTrackPoints], err[constants::mft::MaxTrackPoints]; - Int_t point; + Cell& cell = road.addCellInLayer(layer1, layer2, clsLayer1, clsLayer2, cellId); - for (point = 0; point < trackCA.getNumberOfPoints(); ++point) { - x[point] = trackCA.getXCoordinates()[point]; - y[point] = trackCA.getYCoordinates()[point]; - z[point] = trackCA.getZCoordinates()[point]; - err[point] = constants::mft::Resolution; // FIXME - } - x[point] = cluster2.getX(); - y[point] = cluster2.getY(); - z[point] = cluster2.getZ(); - err[point] = constants::mft::Resolution; // FIXME - - // linear regression in the plane z:x - // x = zxApar * z + zxBpar - Float_t zxApar, zxBpar, zxAparErr, zxBparErr, chisqZX = 0.0; - if (!LinearRegression(trackCA.getNumberOfPoints() + 1, z, x, err, zxApar, zxAparErr, zxBpar, zxBparErr, chisqZX)) { - return -1.0; - } - // linear regression in the plane z:y - // y = zyApar * z + zyBpar - Float_t zyApar, zyBpar, zyAparErr, zyBparErr, chisqZY = 0.0; - if (!LinearRegression(trackCA.getNumberOfPoints() + 1, z, y, err, zyApar, zyAparErr, zyBpar, zyBparErr, chisqZY)) { - return -1.0; - } + Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; + Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; + + Float_t coord[6]; + coord[0] = cluster1.getX(); + coord[1] = cluster1.getY(); + coord[2] = cluster1.getZ(); + coord[3] = cluster2.getX(); + coord[4] = cluster2.getY(); + coord[5] = cluster2.getZ(); - Int_t nDegFree = 2 * (trackCA.getNumberOfPoints() + 1) - 4; - return (chisqZX + chisqZY) / (Float_t)nDegFree; + cell.setCoordinates(coord); + cellId++; } //_________________________________________________________________________________________________ -const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t cellId, ROframe& event) +void Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t cellId, ROframe& event) { TrackCA& trackCA = event.getCurrentTrackCA(); Road& road = event.getCurrentRoad(); @@ -740,141 +691,21 @@ const Bool_t Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t ce const Int_t clsLayer1 = cell.getFirstClusterIndex(); const Int_t clsLayer2 = cell.getSecondClusterIndex(); - const Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; - const Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; - - if (trackCA.getNumberOfPoints() > 0) { - const Float_t xLast = trackCA.getXCoordinates()[trackCA.getNumberOfPoints() - 1]; - const Float_t yLast = trackCA.getYCoordinates()[trackCA.getNumberOfPoints() - 1]; - Float_t dx = xLast - cluster2.getX(); - Float_t dy = yLast - cluster2.getY(); - Float_t dr = std::sqrt(dx * dx + dy * dy); - if (dr > constants::mft::Resolution) { - return kFALSE; - } - } + Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; + Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; MCCompLabel mcCompLabel1 = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); MCCompLabel mcCompLabel2 = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); - Bool_t newPoint; Int_t extClsIndex; if (trackCA.getNumberOfPoints() == 0) { - newPoint = kTRUE; extClsIndex = event.getClusterExternalIndex(layer2, cluster2.clusterId); - trackCA.setPoint(cluster2, layer2, clsLayer2, mcCompLabel2, extClsIndex, newPoint); + trackCA.setPoint(cluster2, layer2, clsLayer2, mcCompLabel2, extClsIndex); } - newPoint = kTRUE; extClsIndex = event.getClusterExternalIndex(layer1, cluster1.clusterId); - trackCA.setPoint(cluster1, layer1, clsLayer1, mcCompLabel1, extClsIndex, newPoint); - - trackCA.addCell(layer1, cellId); - - // update the chisquare - if (trackCA.getNumberOfPoints() == 2) { - trackCA.setChiSquareZX(0.0); - trackCA.setChiSquareZY(0.0); - return kTRUE; - } - - Float_t x[constants::mft::MaxTrackPoints], y[constants::mft::MaxTrackPoints], z[constants::mft::MaxTrackPoints], err[constants::mft::MaxTrackPoints]; - for (Int_t point = 0; point < trackCA.getNumberOfPoints(); ++point) { - x[point] = trackCA.getXCoordinates()[point]; - y[point] = trackCA.getYCoordinates()[point]; - z[point] = trackCA.getZCoordinates()[point]; - err[point] = constants::mft::Resolution; // FIXME - } - - // linear regression in the plane z:x - // x = zxApar * z + zxBpar - Float_t zxApar, zxBpar, zxAparErr, zxBparErr, chisqZX = 0.0; - if (LinearRegression(trackCA.getNumberOfPoints(), z, x, err, zxApar, zxAparErr, zxBpar, zxBparErr, chisqZX)) { - trackCA.setChiSquareZX(chisqZX); - } else { - return kFALSE; - } - - // linear regression in the plane z:y - // y = zyApar * z + zyBpar - Float_t zyApar, zyBpar, zyAparErr, zyBparErr, chisqZY = 0.0; - if (LinearRegression(trackCA.getNumberOfPoints(), z, y, err, zyApar, zyAparErr, zyBpar, zyBparErr, chisqZY)) { - trackCA.setChiSquareZY(chisqZY); - } else { - return kFALSE; - } - - return kTRUE; -} - -const Bool_t Tracker::LinearRegression(Int_t npoints, Float_t* x, Float_t* y, Float_t* yerr, Float_t& apar, Float_t& aparerr, Float_t& bpar, Float_t& bparerr, Float_t& chisq, Int_t skippoint) const -{ - // y = apar * x + bpar - - // work with only part of the points - Float_t xCl[constants::mft::MaxTrackPoints], yCl[constants::mft::MaxTrackPoints], yClErr[constants::mft::MaxTrackPoints]; - Int_t ipoints = 0; - for (Int_t i = 0; i < npoints; ++i) { - if (i == skippoint) { - continue; - } - xCl[ipoints] = x[i]; - yCl[ipoints] = y[i]; - yClErr[ipoints] = yerr[i]; - ipoints++; - } - - // calculate the regression parameters - Float_t S1, SXY, SX, SY, SXX, SsXY, SsXX, SsYY, Xm, Ym, s, delta, difx; - S1 = SXY = SX = SY = SXX = 0.0; - SsXX = SsYY = SsXY = Xm = Ym = 0.0; - difx = 0.; - for (Int_t i = 0; i < ipoints; ++i) { - S1 += 1.0 / (yClErr[i] * yClErr[i]); - SXY += xCl[i] * yCl[i] / (yClErr[i] * yClErr[i]); - SX += xCl[i] / (yClErr[i] * yClErr[i]); - SY += yCl[i] / (yClErr[i] * yClErr[i]); - SXX += xCl[i] * xCl[i] / (yClErr[i] * yClErr[i]); - if (i > 0) { - difx += TMath::Abs(xCl[i] - xCl[i - 1]); - } - Xm += xCl[i]; - Ym += yCl[i]; - SsXX += xCl[i] * xCl[i]; - SsYY += yCl[i] * yCl[i]; - SsXY += xCl[i] * yCl[i]; - } - delta = SXX * S1 - SX * SX; - if (delta == 0.) { - return kFALSE; - } - apar = (SXY * S1 - SX * SY) / delta; - bpar = (SY * SXX - SX * SXY) / delta; - - // calculate the chisquare - chisq = 0.0; - for (Int_t i = 0; i < ipoints; ++i) { - chisq += (yCl[i] - (apar * xCl[i] + bpar)) * (yCl[i] - (apar * xCl[i] + bpar)) / (yerr[i] * yerr[i]); - } - - // calculate the errors of the regression parameters - Ym /= (Float_t)ipoints; - Xm /= (Float_t)ipoints; - SsYY -= (Float_t)ipoints * (Ym * Ym); - SsXX -= (Float_t)ipoints * (Xm * Xm); - SsXY -= (Float_t)ipoints * (Ym * Xm); - Float_t eps = 1.E-24; - if ((ipoints > 2) && (TMath::Abs(difx) > eps) && ((SsYY - (SsXY * SsXY) / SsXX) > 0.0)) { - s = std::sqrt((SsYY - (SsXY * SsXY) / SsXX) / (ipoints - 2)); - bparerr = s * std::sqrt(1. / (Float_t)ipoints + (Xm * Xm) / SsXX); - aparerr = s / std::sqrt(SsXX); - } else { - bparerr = 0.; - aparerr = 0.; - } - - return kTRUE; + trackCA.setPoint(cluster1, layer1, clsLayer1, mcCompLabel1, extClsIndex); } //_________________________________________________________________________________________________ diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index ba62e01740dea..e9a40ba29ac0a 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -60,6 +60,7 @@ void TrackerDPL::init(InitContext& ic) mTracker = std::make_unique<o2::mft::Tracker>(mUseMC); double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT mTracker->setBz(field->getBz(centerMFT)); + mTracker->initialize(); } else { throw std::runtime_error(o2::utils::concat_string("Cannot retrieve GRP from the ", filename)); } @@ -134,7 +135,7 @@ void TrackerDPL::run(ProcessingContext& pc) int nclUsed = ioutils::loadROFrameData(rof, event, compClusters, pattIt, mDict, labels); if (nclUsed) { event.setROFrameId(roFrame); - event.initialise(); + event.initialize(); LOG(INFO) << "ROframe: " << roFrame << ", clusters loaded : " << nclUsed; mTracker->setROFrame(roFrame); mTracker->clustersToTracks(event); From 4adfa838d7fa71ac579c2de9d41cdec639cfa118 Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Wed, 25 Nov 2020 20:44:27 +0100 Subject: [PATCH 1431/1751] Example of partitions inside process (#4918) --- Analysis/Tutorials/src/partitions.cxx | 18 +++++++++++++++++- .../Core/include/Framework/AnalysisHelpers.h | 7 +++++++ Framework/Core/include/Framework/Expressions.h | 4 +++- Framework/Core/src/Expressions.cxx | 11 ++++++++--- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Analysis/Tutorials/src/partitions.cxx b/Analysis/Tutorials/src/partitions.cxx index 6479356a48cfa..e80fd07da5b58 100644 --- a/Analysis/Tutorials/src/partitions.cxx +++ b/Analysis/Tutorials/src/partitions.cxx @@ -59,8 +59,24 @@ struct ATask { } }; +// Partition inside process +// Caveat: partitioned table cannot be passed as const& to process() +struct BTask { + void process(aod::Collisions const& collisions, aod::Tracks& tracks) + { + for (auto& c : collisions) { + Partition<aod::Tracks> groupedTracks = aod::track::collisionId == c.globalIndex(); + groupedTracks.bindTable(tracks); + for (auto& t : groupedTracks) { + LOGF(INFO, "collision global index: %d grouped track collision id: %d", c.globalIndex(), t.collisionId()); + } + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask<ATask>("consume-tracks")}; + adaptAnalysisTask<ATask>("consume-tracks"), + adaptAnalysisTask<BTask>("partition-in-process")}; } diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 0745170ebf804..a6376e57e0cf1 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -486,6 +486,13 @@ struct Partition { { } + void bindTable(T& table) + { + mFiltered.reset(getTableFromFilter(table, filter)); + bindExternalIndices(&table); + getBoundToExternalIndices(table); + } + void setTable(const T& table) { mFiltered.reset(getTableFromFilter(table, filter)); diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index 743ae75ba974a..fc13daea14375 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -56,7 +56,7 @@ struct LiteralStorage { using stored_pack = framework::pack<T...>; }; -using LiteralValue = LiteralStorage<int, bool, float, double, uint8_t>; +using LiteralValue = LiteralStorage<int, bool, float, double, uint8_t, int64_t>; template <typename T> constexpr auto selectArrowType() @@ -73,6 +73,8 @@ constexpr auto selectArrowType() return atype::INT8; } else if constexpr (std::is_same_v<T, uint16_t>) { return atype::INT16; + } else if constexpr (std::is_same_v<T, int64_t>) { + return atype::INT64; } else if constexpr (std::is_same_v<T, uint8_t>) { return atype::UINT8; } else { diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 94f63dd75353b..60323a1305d95 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -67,6 +67,8 @@ std::shared_ptr<arrow::DataType> concreteArrowType(atype::type type) return arrow::int16(); case atype::INT32: return arrow::int32(); + case atype::INT64: + return arrow::int64(); case atype::FLOAT: return arrow::float32(); case atype::DOUBLE: @@ -268,8 +270,8 @@ Operations createOperations(Filter const& expression) return t1; } - if (t1 == atype::INT32 || t1 == atype::INT8 || t1 == atype::INT16 || t1 == atype::UINT8) { - if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::UINT8) { + if (t1 == atype::INT32 || t1 == atype::INT8 || t1 == atype::INT16 || t1 == atype::INT64 || t1 == atype::UINT8) { + if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::INT64 || t2 == atype::UINT8) { return atype::FLOAT; } if (t2 == atype::FLOAT) { @@ -280,7 +282,7 @@ Operations createOperations(Filter const& expression) } } if (t1 == atype::FLOAT) { - if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::UINT8) { + if (t2 == atype::INT32 || t2 == atype::INT8 || t2 == atype::INT16 || t2 == atype::INT64 || t2 == atype::UINT8) { return atype::FLOAT; } if (t2 == atype::DOUBLE) { @@ -451,6 +453,9 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, if (content.index() == 4) { return gandiva::TreeExprBuilder::MakeLiteral(std::get<uint8_t>(content)); } + if (content.index() == 5) { + return gandiva::TreeExprBuilder::MakeLiteral(std::get<int64_t>(content)); + } throw runtime_error("Malformed LiteralNode"); } From 8e53c85c6f28f5f78fd4ffa741dd13a7a68f3aae Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Wed, 18 Nov 2020 14:48:37 +0100 Subject: [PATCH 1432/1751] First version of dcs-proxy. how to run: o2-dpl-dcs-proxy --dcs-proxy '--channel-config "name=dcs-proxy,type=pull,method=connect,address=tcp://10.11.28.22:60000,rateLogging=1,transport=zeromq"' -b Intermediate commit remove dcs-proxy from Framework folder forgotten CMakeLists lamdba function 0 lambda function - part 1 dcs2dpl injector function (#24) Co-authored-by: shahoian <ruben.shahoyan@cern.ch> Capturing by copy and not reference add verbosity flag to dcs-proxy + misc fixes (#25) Co-authored-by: shahoian <ruben.shahoyan@cern.ch> Adding a DCS consumer, to be attached to the proxy for tests extra fixes + debug mode to have it running (#26) Co-authored-by: shahoian <ruben.shahoyan@cern.ch> Adding subSpec and LifeTime to InputSpec Fixing after rebase Few fixes. Please consider the following formatting changes (#28) make code-checker happy --- Detectors/DCS/CMakeLists.txt | 15 ++ Detectors/DCS/testWorkflow/DCSConsumerSpec.h | 88 +++++++++++ .../DCS/testWorkflow/DCStoDPLconverter.h | 140 ++++++++++++++++++ .../testWorkflow/dcs-data-client-workflow.cxx | 34 +++++ Detectors/DCS/testWorkflow/dcs-proxy.cxx | 82 ++++++++++ 5 files changed, 359 insertions(+) create mode 100644 Detectors/DCS/testWorkflow/DCSConsumerSpec.h create mode 100644 Detectors/DCS/testWorkflow/DCStoDPLconverter.h create mode 100644 Detectors/DCS/testWorkflow/dcs-data-client-workflow.cxx create mode 100644 Detectors/DCS/testWorkflow/dcs-proxy.cxx diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt index 5c03ffb6ff1a1..82e52dc169480 100644 --- a/Detectors/DCS/CMakeLists.txt +++ b/Detectors/DCS/CMakeLists.txt @@ -8,6 +8,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +# add_compile_options(-O0 -g -fPIC) + o2_add_library( DetectorsDCS TARGETVARNAME targetName @@ -44,6 +46,19 @@ o2_add_executable( SOURCES testWorkflow/dcs-random-data-workflow.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) +o2_add_executable( + proxy + COMPONENT_NAME dcs + SOURCES testWorkflow/dcs-proxy.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::DetectorsDCS) + +o2_add_executable( + data-client + COMPONENT_NAME dcs + SOURCES testWorkflow/dcs-data-client-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DetectorsDCS) + if(OpenMP_CXX_FOUND) target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) diff --git a/Detectors/DCS/testWorkflow/DCSConsumerSpec.h b/Detectors/DCS/testWorkflow/DCSConsumerSpec.h new file mode 100644 index 0000000000000..9485e3d5c1488 --- /dev/null +++ b/Detectors/DCS/testWorkflow/DCSConsumerSpec.h @@ -0,0 +1,88 @@ +// 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_DCS_CONSUMER_H +#define O2_DCS_CONSUMER_H + +/// @file DCSConsumerSpec.h +/// @brief Consumer of DPs coming from DCS server; it is just +/// to check that we receive and pack the data correctly + +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "Framework/DeviceSpec.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" +#include "Framework/DataSpecUtils.h" + +using namespace o2::framework; +namespace o2h = o2::header; + +namespace o2 +{ +namespace dcs +{ +class DCSConsumer : public o2::framework::Task +{ + + using DPCOM = o2::dcs::DataPointCompositeObject; + + public: + void init(o2::framework::InitContext& ic) final + { + } + + void run(o2::framework::ProcessingContext& pc) final + { + + uint64_t tfid; + for (auto& input : pc.inputs()) { + tfid = header::get<o2::framework::DataProcessingHeader*>(input.header)->startTime; + LOG(DEBUG) << "tfid = " << tfid; + break; // we break because one input is enough to get the TF ID + } + + LOG(DEBUG) << "TF: " << tfid << " --> reading binary blob..."; + mTFs++; + auto vect = pc.inputs().get<gsl::span<DPCOM>>("COMMONDPs"); + LOG(INFO) << "vector has " << vect.size() << " Data Points inside"; + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + + LOG(INFO) << "Number of processed TFs = " << mTFs; + } + + private: + uint64_t mTFs = 0; +}; + +} // namespace dcs + +namespace framework +{ + +DataProcessorSpec getDCSConsumerSpec() +{ + return DataProcessorSpec{ + "dcs-consumer", + Inputs{{"COMMONDPs", "DCS", "COMMON", 0, Lifetime::Timeframe}}, + Outputs{}, + AlgorithmSpec{adaptFromTask<o2::dcs::DCSConsumer>()}, + Options{}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/DCS/testWorkflow/DCStoDPLconverter.h b/Detectors/DCS/testWorkflow/DCStoDPLconverter.h new file mode 100644 index 0000000000000..abca7b51716c6 --- /dev/null +++ b/Detectors/DCS/testWorkflow/DCStoDPLconverter.h @@ -0,0 +1,140 @@ +// 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_DCS_TO_DPL_CONVERTER +#define O2_DCS_TO_DPL_CONVERTER + +#include "Framework/DataSpecUtils.h" +#include "Framework/ExternalFairMQDeviceProxy.h" +#include <fairmq/FairMQParts.h> +#include <fairmq/FairMQDevice.h> +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include <unordered_map> +#include <functional> +#include <string_view> + +namespace o2h = o2::header; +namespace o2f = o2::framework; + +// we need to provide hash function for the DataDescription +namespace std +{ +template <> +struct hash<o2h::DataDescription> { + std::size_t operator()(const o2h::DataDescription& d) const noexcept + { + return std::hash<std::string_view>{}({d.str, size_t(d.size)}); + } +}; +} // namespace std + +namespace o2 +{ +namespace dcs +{ +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; +using DPCOM = o2::dcs::DataPointCompositeObject; + +/// A callback function to retrieve the FairMQChannel name to be used for sending +/// messages of the specified OutputSpec + +o2f::InjectorFunction dcs2dpl(std::unordered_map<DPID, o2h::DataDescription>& dpid2group, uint64_t startTime, uint64_t step, bool verbose = false) +{ + + auto timesliceId = std::make_shared<size_t>(startTime); + return [dpid2group, timesliceId, step, verbose](FairMQDevice& device, FairMQParts& parts, o2f::ChannelRetriever channelRetriever) { + static std::unordered_map<DPID, DPCOM> cache; // will keep only the latest measurement in the 1-second wide window for each DPID + static auto timer = std::chrono::high_resolution_clock::now(); + + LOG(DEBUG) << "In lambda function: ********* Size of unordered_map (--> number of defined groups) = " << dpid2group.size(); + // We first iterate over the parts of the received message + for (size_t i = 0; i < parts.Size(); ++i) { // DCS sends only 1 part, but we should be able to receive more + auto nDPCOM = parts.At(i)->GetSize() / sizeof(DPCOM); // number of DPCOM in current part + for (size_t j = 0; j < nDPCOM; j++) { + DPCOM src; + memcpy(&src, reinterpret_cast<char*>(parts.At(i)->GetData()) + j * sizeof(DPCOM), sizeof(DPCOM)); + // const auto* src = reinterpret_cast<const DPCOM*>(parts.At(i)->GetData()) + j; + // do we want to check if this DP was requested ? + auto mapEl = dpid2group.find(src.id); + if (verbose) { + LOG(INFO) << "Received DP " << src.id << " (data = " << src.data << "), matched to output-> " << (mapEl == dpid2group.end() ? "none " : mapEl->second.as<std::string>()); + } + if (mapEl != dpid2group.end()) { + auto& dst = cache[src.id]; // this is needed in case in the 1s window we get a new value for the same DP + memcpy(&dst, &src, sizeof(DPCOM)); + } + } + } + + auto timerNow = std::chrono::high_resolution_clock::now(); + std::chrono::duration<double, std::ratio<1>> duration = timerNow - timer; + if (duration.count() > 1) { //did we accumulate for 1 sec? + *timesliceId += step; // we increment only if we send something + std::unordered_map<o2h::DataDescription, vector<DPCOM>, std::hash<o2h::DataDescription>> outputs; + // in the cache we have the final values of the DPs that we should put in the output + // distribute DPs over the vectors for each requested output + for (auto& it : cache) { + auto mapEl = dpid2group.find(it.first); + if (mapEl != dpid2group.end()) { + outputs[mapEl->second].push_back(it.second); + } + } + + // create and send output messages + for (auto& it : outputs) { + o2h::DataHeader hdr(it.first, "DCS", 0); + o2f::OutputSpec outsp{hdr.dataOrigin, hdr.dataDescription, hdr.subSpecification}; + if (it.second.empty()) { + LOG(WARNING) << "No data for OutputSpec " << outsp; + continue; + } + auto channel = channelRetriever(outsp, *timesliceId); + if (channel.empty()) { + LOG(WARNING) << "No output channel found for OutputSpec " << outsp << ", discarding its data"; + it.second.clear(); + continue; + } + + hdr.tfCounter = *timesliceId; // this also + hdr.payloadSerializationMethod = o2h::gSerializationMethodNone; + hdr.splitPayloadParts = 1; + hdr.splitPayloadIndex = 1; + hdr.payloadSize = it.second.size() * sizeof(DPCOM); + hdr.firstTForbit = 0; // this should be irrelevant for DCS + o2h::Stack headerStack{hdr, o2::framework::DataProcessingHeader{*timesliceId, 0}}; + auto fmqFactory = device.GetChannel(channel).Transport(); + auto hdMessage = fmqFactory->CreateMessage(headerStack.size(), fair::mq::Alignment{64}); + auto plMessage = fmqFactory->CreateMessage(hdr.payloadSize, fair::mq::Alignment{64}); + memcpy(hdMessage->GetData(), headerStack.data(), headerStack.size()); + memcpy(plMessage->GetData(), it.second.data(), hdr.payloadSize); + if (verbose) { + LOG(INFO) << "Pushing " << it.second.size() << " DPs to output " << it.first.as<std::string>() << " for TimeSlice " << *timesliceId; + hdr.print(); + } + it.second.clear(); + FairMQParts outParts; + outParts.AddPart(std::move(hdMessage)); + outParts.AddPart(std::move(plMessage)); + o2f::sendOnChannel(device, outParts, channel); + } + + timer = timerNow; + cache.clear(); + } + }; +} + +} // namespace dcs +} // namespace o2 + +#endif /* O2_DCS_TO_DPL_CONVERTER_H */ diff --git a/Detectors/DCS/testWorkflow/dcs-data-client-workflow.cxx b/Detectors/DCS/testWorkflow/dcs-data-client-workflow.cxx new file mode 100644 index 0000000000000..5f6eb0337f4b0 --- /dev/null +++ b/Detectors/DCS/testWorkflow/dcs-data-client-workflow.cxx @@ -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. + +#include "Framework/TypeTraits.h" +#include "Framework/DataSpecUtils.h" + +#include "Framework/DataProcessorSpec.h" +#include "DCSConsumerSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getDCSConsumerSpec()); + return specs; +} diff --git a/Detectors/DCS/testWorkflow/dcs-proxy.cxx b/Detectors/DCS/testWorkflow/dcs-proxy.cxx new file mode 100644 index 0000000000000..04f2df7105857 --- /dev/null +++ b/Detectors/DCS/testWorkflow/dcs-proxy.cxx @@ -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. + +// example to run: +// o2-dcs-proxy --dcs-proxy '--channel-config "name=dcs-proxy,type=pull,method=connect,address=tcp://10.11.28.22:60000,rateLogging=1,transport=zeromq"' -b + +#include "Framework/WorkflowSpec.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/ControlService.h" +#include "Framework/Logger.h" +#include "Framework/Lifetime.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/ExternalFairMQDeviceProxy.h" +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DeliveryType.h" +#include "DCStoDPLconverter.h" +#include <vector> +#include <unordered_map> + +using namespace o2::framework; +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; +using DeliveryType = o2::dcs::DeliveryType; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back( + ConfigParamSpec{"verbose", VariantType::Bool, false, {"verbose output"}}); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& config) +{ + + bool verbose = config.options().get<bool>("verbose"); + DPID dpidtmp; + + std::unordered_map<DPID, o2h::DataDescription> dpid2DataDesc; + DPID::FILL(dpidtmp, "ADAPOS_LG/TEST_000100", DeliveryType::RAW_STRING); + dpid2DataDesc[dpidtmp] = "COMMON"; // i.e. this will go to {DCS/COMMON/0} OutputSpec + DPID::FILL(dpidtmp, "ADAPOS_LG/TEST_000110", DeliveryType::RAW_STRING); + dpid2DataDesc[dpidtmp] = "COMMON"; + DPID::FILL(dpidtmp, "ADAPOS_LG/TEST_000200", DeliveryType::RAW_STRING); + dpid2DataDesc[dpidtmp] = "COMMON1"; + DPID::FILL(dpidtmp, "ADAPOS_LG/TEST_000240", DeliveryType::RAW_INT); + dpid2DataDesc[dpidtmp] = "COMMON1"; + + // RS: here we should complete the attribution of different DPs to different outputs + // ... + + // now collect all required outputs to define OutputSpecs for specifyExternalFairMQDeviceProxy + std::unordered_map<o2h::DataDescription, int, std::hash<o2h::DataDescription>> outMap; + for (auto itdp : dpid2DataDesc) { + outMap[itdp.second]++; + } + + Outputs dcsOutputs; + for (auto itout : outMap) { + dcsOutputs.emplace_back("DCS", itout.first, 0, Lifetime::Timeframe); + } + + DataProcessorSpec dcsProxy = specifyExternalFairMQDeviceProxy( + "dcs-proxy", + std::move(dcsOutputs), + "type=pull,method=connect,address=tcp://aldcsadaposactor:60000,rateLogging=1,transport=zeromq", + dcs2dpl(dpid2DataDesc, 0, 1, verbose)); + + WorkflowSpec workflow; + workflow.emplace_back(dcsProxy); + return workflow; +} From 7573cc5756243d880174485a64630550494ad2e6 Mon Sep 17 00:00:00 2001 From: mfasel <markus.fasel@cern.ch> Date: Tue, 24 Nov 2020 15:53:23 +0100 Subject: [PATCH 1433/1751] [EMCAL-610] Fix channel header in payload encoding - Channel header must be marked with bit 30, otherwise the decoder will not find any channel - Swap fields for bunch size and start time (first bunch size, then start time) - Add bunch header size (2) to bunch size - Skip encoding of channels with no bunches - Skip encoding of SRUs with no channels --- .../reconstruction/macros/RawFitterTESTs.C | 7 +++- .../include/EMCALSimulation/RawWriter.h | 2 +- Detectors/EMCAL/simulation/src/RawWriter.cxx | 32 ++++++++++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C index e5106ef2971e6..2979b0e698289 100644 --- a/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C +++ b/Detectors/EMCAL/reconstruction/macros/RawFitterTESTs.C @@ -43,6 +43,7 @@ void RawFitterTESTs(const char* filename = "") inputDir += "/share/Detectors/EMC/files/"; inputfile = inputDir + "emcal.raw"; } + std::cout << "Using input file " << inputfile << std::endl; o2::raw::RawFileReader reader; reader.setDefaultDataOrigin(o2::header::gDataOriginEMC); @@ -64,6 +65,7 @@ void RawFitterTESTs(const char* filename = "") break; } std::vector<char> dataBuffer; // where to put extracted data + std::cout << "Next iteration: Number of links: " << reader.getNLinks() << std::endl; for (int il = 0; il < reader.getNLinks(); il++) { auto& link = reader.getLink(il); std::cout << "Decoding link " << il << std::endl; @@ -84,14 +86,17 @@ void RawFitterTESTs(const char* filename = "") // use the altro decoder to decode the raw data, and extract the RCU trailer o2::emcal::AltroDecoder decoder(parser); + std::cout << "Decoding" << std::endl; decoder.decode(); std::cout << decoder.getRCUTrailer() << std::endl; + std::cout << "Found number of channels: " << decoder.getChannels().size() << std::endl; // Loop over all the channels for (auto& chan : decoder.getChannels()) { - + std::cout << "processing next channel idx " << chan.getChannelIndex() << ", " << chan.getHardwareAddress() << std::endl; // define the conatiner for the fit results, and perform the raw fitting using the stadnard raw fitter + continue; o2::emcal::CaloFitResults fitResults = RawFitter.evaluate(chan.getBunches(), 0, 0); // print the fit output diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h index 1ba5f43562e16..974c749f7ab7a 100644 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h +++ b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h @@ -58,7 +58,7 @@ union ChannelHeader { uint32_t mPayloadSize : 10; ///< Bits 16 - 25: Payload size uint32_t mZero1 : 3; ///< Bits 26 - 28: zeroed uint32_t mBadChannel : 1; ///< Bit 29: Bad channel status - uint32_t mZero2 : 2; ///< Bits 30 - 31: zeroed + uint32_t mHeaderBits : 2; ///< Bits 30 - 31: channel header bits (1) }; }; diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index 674ba68aa408d..cafe1f64c57a6 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -121,15 +121,30 @@ bool RawWriter::processTrigger(const o2::emcal::TriggerRecord& trg) std::vector<int> rawbunches; for (auto& bunch : findBunches(channel.mDigits)) { + rawbunches.push_back(bunch.mADCs.size() + 2); // add 2 words for header information rawbunches.push_back(bunch.mStarttime); - rawbunches.push_back(bunch.mADCs.size()); for (auto adc : bunch.mADCs) { rawbunches.push_back(adc); } } + if (!rawbunches.size()) { + continue; + } auto encodedbunches = encodeBunchData(rawbunches); - auto chanhead = createChannelHeader(hwaddress, encodedbunches.size() * 3 - 2, false); /// bad channel status eventually to be added later + auto chanhead = createChannelHeader(hwaddress, rawbunches.size(), false); /// bad channel status eventually to be added later char* chanheadwords = reinterpret_cast<char*>(&chanhead); + uint32_t* testheader = reinterpret_cast<uint32_t*>(chanheadwords); + if ((*testheader >> 30) & 1) { + // header pattern found, check that the payload size is properly reflecting the number of words + uint32_t payloadsizeRead = ((*testheader >> 16) & 0x3FF); + uint32_t nwordsRead = (payloadsizeRead + 2) / 3; + if (encodedbunches.size() != nwordsRead) { + LOG(ERROR) << "Mismatch in number of 32-bit words, encoded " << encodedbunches.size() << ", recalculated " << nwordsRead << std::endl; + LOG(ERROR) << "Payload size: " << payloadsizeRead << ", number of words: " << rawbunches.size() << ", encodeed words " << encodedbunches.size() << ", calculated words " << nwordsRead << std::endl; + } + } else { + LOG(ERROR) << "Header without header bit detected ..." << std::endl; + } for (int iword = 0; iword < sizeof(ChannelHeader) / sizeof(char); iword++) { payload.emplace_back(chanheadwords[iword]); } @@ -139,6 +154,10 @@ bool RawWriter::processTrigger(const o2::emcal::TriggerRecord& trg) } } + if (!payload.size()) { + continue; + } + // Create RCU trailer auto trailerwords = createRCUTrailer(payload.size() / 4, 16, 16, 100., 0.); for (auto word : trailerwords) { @@ -239,15 +258,17 @@ std::vector<int> RawWriter::encodeBunchData(const std::vector<int>& data) currentword.mWord2 = adc; break; }; - if (wordnumber == 2) { + wordnumber++; + if (wordnumber == 3) { // start new word; encoded.push_back(currentword.mDataWord); currentword.mDataWord = 0; wordnumber = 0; - } else { - wordnumber++; } } + if (wordnumber) { + encoded.push_back(currentword.mDataWord); + } return encoded; } @@ -257,6 +278,7 @@ ChannelHeader RawWriter::createChannelHeader(int hardwareAddress, int payloadSiz header.mHardwareAddress = hardwareAddress; header.mPayloadSize = payloadSize; header.mBadChannel = isBadChannel ? 1 : 0; + header.mHeaderBits = 1; return header; } From 8482866c056f82c7bc7c1ee13407442276f2e9ad Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 26 Nov 2020 10:04:21 +0100 Subject: [PATCH 1434/1751] Pure generator kinematics simulation example Based on transport configuration. --- doc/DetectorSimulation.md | 1 + .../only_primarykine.ini | 20 +++++++++++++++++++ run/SimExamples/JustPrimaryKinematics/run.sh | 8 ++++++++ run/SimExamples/README.md | 1 + 4 files changed, 30 insertions(+) create mode 100644 run/SimExamples/JustPrimaryKinematics/only_primarykine.ini create mode 100644 run/SimExamples/JustPrimaryKinematics/run.sh diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index de89e32b973e4..e0249053a4fd1 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -454,6 +454,7 @@ Other helpful resources are the scripts used for regression testing in [prodtest | [AliRoot_AMPT](../run/SimExamples/AliRoot_AMPT) | Example showing how to use AMPT from AliRoot for event generation | | [Adaptive_Pythia8](../run/SimExamples/Adaptive_Pythia8) | Complex example showing **generator configuration for embedding** that cat adapt the response based on the background event | | [Signal_ImpactB](../run/SimExamples/Signal_ImpactB) | Example showing **generator configuration for embedding** that cat adapt to the impact parameter of the background event | +| [PrimaryKinematics](../run/SimExamples/JustPrimaryKinematics) | Example showing how to obtain only primary kinematics via transport configuration | | [HepMC_STARlight](../run/SimExamples/HepMC_STARlight) | Simple example showing **generator configuration** that runs a standalone `STARlight` generation that couples to the `o2` via a `HepMC` file | | [Jet_Embedding_Pythia](../run/SimExamples/Jet_Embedding_Pythia8) | Complex example showing **generator configuration**, **digitization embedding**, **MCTrack access** | | [sim_challenge.sh](../prodtests/sim_challenge.sh) | Basic example doing a **simple transport, digitization, reconstruction pipeline** on the full dectector. All stages use parallelism. | diff --git a/run/SimExamples/JustPrimaryKinematics/only_primarykine.ini b/run/SimExamples/JustPrimaryKinematics/only_primarykine.ini new file mode 100644 index 0000000000000..43daa9f866da4 --- /dev/null +++ b/run/SimExamples/JustPrimaryKinematics/only_primarykine.ini @@ -0,0 +1,20 @@ +[SimCutParams] +maxRTracking=2 +maxAbsZTracking=2 +ZmaxA=2 +ZmaxC=2 +[GlobalSimProcs] +PAIR=0 +COMP=0 +PHOT=0 +PFIS=0 +DRAY=0 +ANNI=0 +BREM=0 +HADR=0 +MUNU=0 +DCAY=0 +LOSS=0 +MULS=0 +CKOV=0 + diff --git a/run/SimExamples/JustPrimaryKinematics/run.sh b/run/SimExamples/JustPrimaryKinematics/run.sh new file mode 100644 index 0000000000000..eea02105c1a51 --- /dev/null +++ b/run/SimExamples/JustPrimaryKinematics/run.sh @@ -0,0 +1,8 @@ +# A very simple example, showing how to configure o2-sim to skip +# transport/physics and save just the originally generated event. +# While this can be achieved in potentially many ways, the example is instructive +# to demonstrate the configuration mechanism in general. +# Here the mechanism is to switch off physics in the configuration file and set very +# tight geometry cuts so that Geant will not do work. + +o2-sim -n 10 -g pythia8 -m CAVE --configFile only_kine.ini diff --git a/run/SimExamples/README.md b/run/SimExamples/README.md index d589dc43a1115..484ba32ac38ef 100644 --- a/run/SimExamples/README.md +++ b/run/SimExamples/README.md @@ -15,4 +15,5 @@ * \subpage refrunSimExamplesJet_Embedding_Pythia8 * \subpage refrunSimExamplesStepMonitoringSimple1 * \subpage refrunSimExamplesForceDecay_Lambda_Neutron_Dalitz +* \subpage refrunSimExamplesJustPrimaryKinematics /doxy --> From 16847da5cad9a6d293c65af5e822743f77a0e335 Mon Sep 17 00:00:00 2001 From: arvindkhuntia <akhuntia@cern.ch> Date: Wed, 18 Nov 2020 18:23:19 +0100 Subject: [PATCH 1435/1751] [FV0] Trigger in digits --- .../FIT/FV0/include/DataFormatsFV0/BCData.h | 40 ++++++++++++++++++- .../FIT/FV0/src/DataFormatsFV0LinkDef.h | 2 + Detectors/CTF/test/test_ctf_io_fv0.cxx | 4 +- .../include/FV0Reconstruction/CTFCoder.h | 3 +- .../FIT/FV0/reconstruction/src/ReadRaw.cxx | 3 +- .../include/FV0Simulation/FV0DigParam.h | 3 ++ .../FIT/FV0/simulation/src/Digitizer.cxx | 34 ++++++++++++---- .../src/FV0DigitizerSpec.cxx | 12 ++++-- 8 files changed, 86 insertions(+), 15 deletions(-) diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h index 238ddf2551072..9843afb2c9393 100644 --- a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h @@ -26,21 +26,59 @@ namespace fv0 { class ChannelData; +struct Triggers { + enum { + bitMinBias, + bitMinBiasInner, + bitMinBiasOuter, + bitHighMult + }; + uint8_t triggerSignals = 0; // V0 trigger signals + int8_t nChanA = 0; // number of fired channels [A side] + int32_t amplA = -1000; // sum amplitude [A side] + Triggers() = default; + + Triggers(uint8_t signals, int8_t chanA, int32_t amplASum) + { + triggerSignals = signals; + nChanA = chanA; + amplA = amplASum; + } + + bool getIsMinBias() const { return (triggerSignals & (1 << bitMinBias)) != 0; } + bool getIsMinBiasInner() const { return (triggerSignals & (1 << bitMinBiasInner)) != 0; } + bool getIsMinBiasOuter() const { return (triggerSignals & (1 << bitMinBiasOuter)) != 0; } + bool getIsHighMult() const { return (triggerSignals & (1 << bitHighMult)) != 0; } + + void setTriggers(Bool_t isMinBias, Bool_t isMinBiasInner, Bool_t isMinBiasOuter, Bool_t isHighMult, int8_t chanA, int32_t amplASum) + { + triggerSignals = (isMinBias << bitMinBias) | (isMinBiasInner << bitMinBiasInner) | (isMinBiasOuter << bitMinBiasOuter) | (isHighMult << bitHighMult); + nChanA = chanA; + amplA = amplASum; + } + + ClassDefNV(Triggers, 1); +}; + struct BCData { /// we are going to refer to at most 48 channels, so 6 bits for the number of channels and 26 for the reference o2::dataformats::RangeRefComp<6> ref; o2::InteractionRecord ir; + Triggers mTriggers; BCData() = default; - BCData(int first, int ne, o2::InteractionRecord iRec) + BCData(int first, int ne, o2::InteractionRecord iRec, const Triggers& chTrig) { ref.setFirstEntry(first); ref.setEntries(ne); ir = iRec; + mTriggers = chTrig; } gsl::span<const ChannelData> getBunchChannelData(const gsl::span<const ChannelData> tfdata) const; const o2::InteractionRecord& getIntRecord() const { return ir; }; + Triggers getTriggers() const { return mTriggers; } + void setTriggers(Triggers triggers) { mTriggers = triggers; }; void print() const; ClassDefNV(BCData, 1); diff --git a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h index baa12012401b6..b22a7f68daecb 100644 --- a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h +++ b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h @@ -20,7 +20,9 @@ #pragma link C++ class o2::fv0::ChannelData + ; #pragma link C++ class o2::fv0::BCData + ; +#pragma link C++ class o2::fv0::Triggers + ; #pragma link C++ class std::vector < o2::fv0::ChannelData> + ; +#pragma link C++ class std::vector < o2::fv0::Triggers> + ; #pragma link C++ class std::vector < o2::fv0::BCData> + ; #pragma link C++ class o2::fv0::RawEventData + ; diff --git a/Detectors/CTF/test/test_ctf_io_fv0.cxx b/Detectors/CTF/test/test_ctf_io_fv0.cxx index 3e395de8ec7c7..efa49d28e37e9 100644 --- a/Detectors/CTF/test/test_ctf_io_fv0.cxx +++ b/Detectors/CTF/test/test_ctf_io_fv0.cxx @@ -27,6 +27,7 @@ BOOST_AUTO_TEST_CASE(CTFTest) { std::vector<BCData> digits; std::vector<ChannelData> channels; + Triggers trigger; // TODO: Actual values are not set TStopwatch sw; sw.Start(); @@ -44,7 +45,8 @@ BOOST_AUTO_TEST_CASE(CTFTest) ich += 1 + gRandom->Poisson(10); } auto end = channels.size(); - digits.emplace_back(start, end - start, ir); + + digits.emplace_back(start, end - start, ir, trigger); } LOG(INFO) << "Generated " << channels.size() << " channels in " << digits.size() << " digits " << sw.CpuTime() << " s"; diff --git a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h index 4b60fd86d1271..ae14872cc13d2 100644 --- a/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FV0/reconstruction/include/FV0Reconstruction/CTFCoder.h @@ -154,7 +154,8 @@ void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& cha auto icc = channelVec.size(); const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.time[icc], cd.charge[icc]); } - digitVec.emplace_back(firstEntry, cd.nChan[idig], ir); + Triggers triggers; // TODO: Actual values are not set + digitVec.emplace_back(firstEntry, cd.nChan[idig], ir, triggers); } } diff --git a/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx b/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx index db2dd6e2c33ca..aa71f667104a5 100644 --- a/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx +++ b/Detectors/FIT/FV0/reconstruction/src/ReadRaw.cxx @@ -154,7 +154,8 @@ void ReadRaw::writeDigits(const std::string& outputDigitsFilePath) chDataVecTree.emplace_back(int(sec.pmtNumber), float(sec.time), Short_t(sec.chargeAdc)); nStored++; } - chBcVecTree.emplace_back(first, nStored, digit.first); + Triggers triggers; // TODO: Actual values are not set + chBcVecTree.emplace_back(first, nStored, digit.first, triggers); } outTree->Branch("FV0DigitBC", &chBcVecTree); diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h index 0901ff3c1b0ee..96d9055b60d3b 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/FV0DigParam.h @@ -46,6 +46,9 @@ struct FV0DigParam : public o2::conf::ConfigurableParamHelper<FV0DigParam> { int avgNumberPhElectronPerMip = 201; // avg number of photo-electrons per MIP float globalTimeOfFlight = 315.0 / o2::constants::physics::LightSpeedCm2NS; //TODO check the correct value for distance of FV0 to IP + ///Parameters for trigger simulation + int adcChargeHighMultTh = 3.0 * 498; //threshold value of ADC charge for high multiplicity trigger + O2ParamDef(FV0DigParam, "FV0DigParam"); }; } // namespace fv0 diff --git a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx index c457619ef529a..406d9a15c6a17 100644 --- a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx @@ -33,7 +33,6 @@ void Digitizer::clear() void Digitizer::init() { LOG(INFO) << "V0Digitizer::init -> start = "; - mNBins = FV0DigParam::Instance().waveformNbins; //Will be computed using detector set-up from CDB mBinSize = FV0DigParam::Instance().waveformBinWidth; //Will be set-up from CDB @@ -104,7 +103,6 @@ void Digitizer::process(const std::vector<o2::fv0::Hit>& hits, std::vector<o2::f } else { iChannelPerCell = 2; // not a ring 5 cell -> don't repeat the loop } - Double_t const nPhotons = hitEdep * DP::N_PHOTONS_PER_MEV; float const nPhE = SimulateLightYield(detId, nPhotons); float mipFraction = float(nPhE / FV0DigParam::Instance().avgNumberPhElectronPerMip); @@ -113,7 +111,6 @@ void Digitizer::process(const std::vector<o2::fv0::Hit>& hits, std::vector<o2::f o2::InteractionTimeRecord irHit(timeHit); std::array<o2::InteractionRecord, NBC2Cache> cachedIR; int nCachedIR = 0; - for (int i = BCCacheMin; i < BCCacheMax + 1; i++) { double tNS = timeHit + o2::constants::lhc::LHCBunchSpacingNS * i; cachedIR[nCachedIR].setFromNS(tNS); @@ -198,6 +195,10 @@ void Digitizer::storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsB int first = digitsCh.size(); size_t nStored = 0; double totalCharge = 0; + double totalChargeAllRing = 0; + double nSignalInner = 0; + double nSignalOuter = 0; + for (int iPmt = 0; iPmt < Constants::nFv0Channels; iPmt++) { double cfdWithOffset = SimulateTimeCfd(bc.mPmtChargeVsTime[iPmt]); double cfdZero = cfdWithOffset - FV0DigParam::Instance().avgCfdTimeForMip; @@ -205,10 +206,9 @@ void Digitizer::storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsB if (cfdZero < -FV0DigParam::Instance().cfdCheckWindow || cfdZero > FV0DigParam::Instance().cfdCheckWindow) { continue; } - - //LOG(INFO) << "time inside analyse and store =========> " << cfdZero <<" detid "<<iPmt; float charge = IntegrateCharge(bc.mPmtChargeVsTime[iPmt]); totalCharge += charge; + totalChargeAllRing += charge; totalCharge *= DP::INV_CHARGE_PER_ADC; cfdZero *= DP::INV_TIME_PER_TDCCHANNEL; @@ -216,9 +216,29 @@ void Digitizer::storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsB static_cast<short int>(std::round(totalCharge))); totalCharge = 0; ++nStored; + //---trigger--- + if (iPmt < 25) { + nSignalInner++; + } else { + nSignalOuter++; + } } + if (nStored < 1) { + return; + } + totalChargeAllRing *= DP::INV_CHARGE_PER_ADC; + //LOG(INFO)<<"Total charge ADC " <<totalChargeAllRing ; + ///Triggers for FV0 + bool isMinBias, isMinBiasInner, isMinBiasOuter, isHighMult; + isMinBias = nStored > 0; + isMinBiasInner = nSignalInner > 0; //ring 1,2 and 3 + isMinBiasOuter = nSignalOuter > 0; //ring 4 and 5 + isHighMult = totalChargeAllRing > FV0DigParam::Instance().adcChargeHighMultTh; + + Triggers triggers; + triggers.setTriggers(isMinBias, isMinBiasInner, isMinBiasOuter, isHighMult, nStored, totalChargeAllRing); int nBC = digitsBC.size(); - digitsBC.emplace_back(first, nStored, bc); + digitsBC.emplace_back(first, nStored, bc, triggers); for (const auto& lbl : bc.labels) { labels.addElement(nBC, lbl); } @@ -341,4 +361,4 @@ o2::fv0::Digitizer::BCCache* Digitizer::getBCCache(const o2::InteractionRecord& } } return nullptr; -} \ No newline at end of file +} diff --git a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx index 7e501e6f2ed81..5d2c651f5e492 100644 --- a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx @@ -50,6 +50,7 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer { LOG(INFO) << "FV0DPLDigitizerTask:init"; mDigitizer.init(); + mDisableQED = ic.options().get<bool>("disable-qed"); //TODO: QED implementation to be tested } void run(framework::ProcessingContext& pc) @@ -62,11 +63,12 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer // read collision context from input auto context = pc.inputs().get<o2::steer::DigitizationContext*>("collisioncontext"); context->initSimChains(o2::detectors::DetID::FV0, mSimChains); + const bool withQED = context->isQEDProvided() && !mDisableQED; //TODO: QED implementation to be tested mDigitizer.setTimeStamp(context->getGRP().getTimeStart()); - auto& irecords = context->getEventRecords(); - auto& eventParts = context->getEventParts(); + auto& irecords = context->getEventRecords(withQED); //TODO: QED implementation to be tested + auto& eventParts = context->getEventParts(withQED); //TODO: QED implementation to be tested // loop over all composite collisions given from context // (aka loop over all the interaction records) @@ -122,6 +124,7 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer // RS: at the moment using hardcoded flag for continuous readout o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::CONTINUOUS; // readout mode + bool mDisableQED = false; }; o2::framework::DataProcessorSpec getFV0DigitizerSpec(int channel, bool mctruth) @@ -146,8 +149,9 @@ o2::framework::DataProcessorSpec getFV0DigitizerSpec(int channel, bool mctruth) outputs, AlgorithmSpec{adaptFromTask<FV0DPLDigitizerTask>()}, - - Options{{"pileup", VariantType::Int, 1, {"whether to run in continuous time mode"}}}}; + Options{{"pileup", VariantType::Int, 1, {"whether to run in continuous time mode"}}, + {"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}}; + //Options{{"pileup", VariantType::Int, 1, {"whether to run in continuous time mode"}}}}; } } // end namespace fv0 From febbfb13c92fa1fbb6d103d04abd15172c41ef59 Mon Sep 17 00:00:00 2001 From: manso <manso@clermont.in2p3.fr> Date: Wed, 25 Nov 2020 21:04:13 +0100 Subject: [PATCH 1436/1751] PSU cooling pipes to the patch panel --- .../ITSMFT/MFT/base/src/PowerSupplyUnit.cxx | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx index e780b4bacd467..3d03a37899054 100644 --- a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx +++ b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx @@ -46,6 +46,7 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() TGeoMedium* kMedPeek = gGeoManager->GetMedium("MFT_PEEK$"); TGeoMedium* kMed_Water = gGeoManager->GetMedium("MFT_Water$"); TGeoMedium* kMedAlu = gGeoManager->GetMedium("MFT_Alu$"); + TGeoMedium* kMedPolyPipe = gGeoManager->GetMedium("MFT_Polyimide$"); TGeoVolumeAssembly* mHalfPSU = new TGeoVolumeAssembly("PSU"); @@ -396,11 +397,51 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() combtrans_water_pipe_straight_tube_side_left2->RegisterYourself(); combtrans_water_pipe_straight_tube_side_right2->RegisterYourself(); + //==================== PIPE - connection to the patch panel ====================== + TGeoTorus* pipe_side_torus_left3 = new TGeoTorus("pipe_side_torus_left3", water_pipe_side_position_radius, water_pipe_inner_radius, water_pipe_outer_radius, 0, 90); + TGeoRotation* rotate_water_torus_left3 = new TGeoRotation("rotate_water_torus_left3", -90, 90, 0); + TGeoCombiTrans* combtrans_water_torus_left3 = new TGeoCombiTrans("combtrans_water_torus_left3", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2 + water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - 2 * water_pipe_straight_tube_side2_length, -water_pipe_side_position_radius, rotate_water_torus_left3); + combtrans_water_torus_left3->RegisterYourself(); + Float_t water_pipe_straight_tube_side3_length = 6; + TGeoTubeSeg* pipe_straight_tube_left3 = new TGeoTubeSeg("pipe_straight_tube_left3", water_pipe_inner_radius, water_pipe_outer_radius, water_pipe_straight_tube_side3_length, 0, 360); + TGeoRotation* rotate_water_straight_tube_left3 = new TGeoRotation("rotate_water_straight_tube_left3", 0, 0, 0); + TGeoCombiTrans* combtrans_water_straight_tube_side_left3 = new TGeoCombiTrans("combtrans_water_straight_tube_side_left3", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2 + water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - 2 * water_pipe_straight_tube_side2_length - water_pipe_side_position_radius, -water_pipe_straight_tube_side3_length - water_pipe_side_position_radius, rotate_water_straight_tube_left3); + combtrans_water_straight_tube_side_left3->RegisterYourself(); + + TGeoTorus* pipe_side_torus_rigth3 = new TGeoTorus("pipe_side_torus_rigth3", water_pipe_side_position_radius, water_pipe_inner_radius, water_pipe_outer_radius, 0, 90); + TGeoRotation* rotate_water_torus_rigth3 = new TGeoRotation("rotate_water_torus_rigth3", -90, 90, 0); + TGeoCombiTrans* combtrans_water_torus_rigth3 = new TGeoCombiTrans("combtrans_water_torus_rigth3", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2 - water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - 2 * water_pipe_straight_tube_side2_length, -water_pipe_side_position_radius, rotate_water_torus_rigth3); + combtrans_water_torus_rigth3->RegisterYourself(); + + TGeoTubeSeg* pipe_straight_tube_rigth3 = new TGeoTubeSeg("pipe_straight_tube_rigth3", 0, water_pipe_inner_radius, water_pipe_straight_tube_side3_length, 0, 360); + TGeoRotation* rotate_water_straight_tube_rigth3 = new TGeoRotation("rotate_water_straight_tube_rigth3", 0, 0, 0); + TGeoCombiTrans* combtrans_water_straight_tube_side_rigth3 = new TGeoCombiTrans("combtrans_water_straight_tube_side_rigth3", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2 - water_pipe_side_position_radius, + -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - 2 * water_pipe_straight_tube_side2_length - water_pipe_side_position_radius, -water_pipe_straight_tube_side3_length - water_pipe_side_position_radius, rotate_water_straight_tube_rigth3); + combtrans_water_straight_tube_side_rigth3->RegisterYourself(); + + TGeoCompositeShape* water_pipe_toPatchPanel = new TGeoCompositeShape("water_pipe_toPatchPanel", + "pipe_straight_tube_left3:combtrans_water_straight_tube_side_left3" + " + pipe_side_torus_left3:combtrans_water_torus_left3" + " + pipe_straight_tube_rigth3:combtrans_water_straight_tube_side_rigth3" + " + pipe_side_torus_rigth3:combtrans_water_torus_rigth3"); + TGeoVolume* poly_pipe = new TGeoVolume("poly_pipe_toPatchPanel", water_pipe_toPatchPanel, kMedPolyPipe); + poly_pipe->SetLineColor(kGray); + mHalfPSU->AddNode(poly_pipe, 1, nullptr); + + //================================================== + TGeoCompositeShape* water_pipe_shape = new TGeoCompositeShape("water_pipe_shape", "water_pipe_main_torus + water_pipe_side_torus_left1:trans_water_pipe_side_torus_left1 + water_pipe_side_torus_right1:trans_water_pipe_side_torus_right1" " + water_pipe_straight_tube_side1:combtrans_rotated_water_pipe_straight_tube_side1_left + water_pipe_straight_tube_side1:combtrans_rotated_water_pipe_straight_tube_side1_right" " + water_pipe_side_torus_left2:trans_water_pipe_side_torus_left2 + water_pipe_side_torus_right2:trans_water_pipe_side_torus_right2" - " + water_pipe_straight_tube_side2:combtrans_water_pipe_straight_tube_side_left2 + water_pipe_straight_tube_side2:combtrans_water_pipe_straight_tube_side_right2"); + " + water_pipe_straight_tube_side2:combtrans_water_pipe_straight_tube_side_left2 + water_pipe_straight_tube_side2:combtrans_water_pipe_straight_tube_side_right2" + " + pipe_straight_tube_left3:combtrans_water_straight_tube_side_left3" + " + pipe_side_torus_left3:combtrans_water_torus_left3" + " + pipe_straight_tube_rigth3:combtrans_water_straight_tube_side_rigth3" + " + pipe_side_torus_rigth3:combtrans_water_torus_rigth3"); TGeoVolume* water_pipe = new TGeoVolume("water_pipe", water_pipe_shape, kMedAlu); water_pipe->SetLineColor(kGray); @@ -449,11 +490,22 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() combtrans_water_straight_tube_side_left2->RegisterYourself(); combtrans_water_straight_tube_side_right2->RegisterYourself(); + //============ WATER, Connecting to the Patch Panel =============== + TGeoTorus* water_side_torus_left3 = new TGeoTorus("water_side_torus_left3", water_pipe_side_position_radius, 0, water_pipe_inner_radius, 0, 90); + TGeoTubeSeg* water_straight_tube_left3 = new TGeoTubeSeg("water_straight_tube_left3", 0, water_pipe_inner_radius, water_pipe_straight_tube_side3_length, 0, 360); + TGeoTorus* water_side_torus_rigth3 = new TGeoTorus("water_side_torus_rigth3", water_pipe_side_position_radius, 0, water_pipe_inner_radius, 0, 90); + TGeoTubeSeg* water_straight_tube_rigth3 = new TGeoTubeSeg("water_straight_tube_rigth3", 0, water_pipe_inner_radius, water_pipe_straight_tube_side3_length, 0, 360); + //================================================================== + TGeoCompositeShape* water_shape = new TGeoCompositeShape("water_shape", "water_main_torus + water_side_torus_left1:trans_water_side_torus_left1 + water_side_torus_right1:trans_water_side_torus_right1" " + water_straight_tube_side1:combtrans_rotated_water_straight_tube_side1_left + water_straight_tube_side1:combtrans_rotated_water_straight_tube_side1_right" " + water_side_torus_left2:trans_water_side_torus_left2 + water_side_torus_right2:trans_water_side_torus_right2" - " + water_straight_tube_side2:combtrans_water_straight_tube_side_left2 + water_straight_tube_side2:combtrans_water_straight_tube_side_right2"); + " + water_straight_tube_side2:combtrans_water_straight_tube_side_left2 + water_straight_tube_side2:combtrans_water_straight_tube_side_right2" + " + water_straight_tube_left3:combtrans_water_straight_tube_side_left3" + " + water_side_torus_left3:combtrans_water_torus_left3" + " + water_straight_tube_rigth3:combtrans_water_straight_tube_side_rigth3" + " + water_side_torus_rigth3:combtrans_water_torus_rigth3"); TGeoVolume* water = new TGeoVolume("water", water_shape, kMed_Water); water->SetLineColor(kBlue); From 5c2a367deb797297d8297256f461193fbb589a86 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Thu, 26 Nov 2020 21:47:31 +0100 Subject: [PATCH 1437/1751] DPL: add helpers for compile-time strings (#4923) --- .../Core/include/Framework/StringHelpers.h | 38 +++++++++++++++++++ Framework/Core/test/test_StringHelpers.cxx | 23 ++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/StringHelpers.h b/Framework/Core/include/Framework/StringHelpers.h index 778aba4efa3e7..d58187031d06b 100644 --- a/Framework/Core/include/Framework/StringHelpers.h +++ b/Framework/Core/include/Framework/StringHelpers.h @@ -12,6 +12,7 @@ #define O2_FRAMEWORK_STRINGHELPERS_H_ #include <cstdint> +#include <utility> // CRC32 Table (zlib polynomial) static constexpr uint32_t crc_table[256] = {0x0L, 0x77073096L, 0xee0e612cL, @@ -73,4 +74,41 @@ constexpr uint32_t compile_time_hash(char const* str) return crc32(str, static_cast<int>(__builtin_strlen(str)) - 1) ^ 0xFFFFFFFF; } +template <int N> +constexpr uint32_t compile_time_hash_from_literal(const char (&str)[N]) +{ + return crc32(str, N - 2) ^ 0xFFFFFFFF; +} + +template <char... chars> +struct ConstStr { + static constexpr char str[] = {chars..., '\0'}; + static constexpr uint32_t hash = compile_time_hash_from_literal(str); + static constexpr uint32_t idx = hash & 0x1FF; +}; + +template <typename T, std::size_t... Is> +constexpr auto as_chars_impl(std::index_sequence<Is...>) +{ + return ConstStr<T::str()[Is]...>{}; +} + +template <typename T> +constexpr auto as_chars() +{ + return as_chars_impl<T>( + std::make_index_sequence<sizeof(T::str()) - 1>{}); +} + +#define CONST_STR(literal) \ + [] { \ + struct literal_to_chars { \ + static constexpr decltype(auto) str() \ + { \ + return literal; \ + } \ + }; \ + return as_chars<literal_to_chars>(); \ + }() + #endif // O2_FRAMEWORK_STRINGHELPERS_H diff --git a/Framework/Core/test/test_StringHelpers.cxx b/Framework/Core/test/test_StringHelpers.cxx index ee03e585f46ca..d866082b4ecd6 100644 --- a/Framework/Core/test/test_StringHelpers.cxx +++ b/Framework/Core/test/test_StringHelpers.cxx @@ -11,8 +11,9 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK -#include "Framework/StringHelpers.h" #include <boost/test/unit_test.hpp> +#include "Framework/StringHelpers.h" +#include <iostream> BOOST_AUTO_TEST_CASE(StringHelpersHash) { @@ -22,3 +23,23 @@ BOOST_AUTO_TEST_CASE(StringHelpersHash) BOOST_CHECK_EQUAL(compile_time_hash(cs), compile_time_hash("test-string")); BOOST_CHECK_EQUAL(compile_time_hash(s.c_str()), compile_time_hash(cs)); } + +template <typename T> +void printString(const T& constStr) +{ + std::cout << "ConstStr:" << std::endl; + std::cout << "str -> " << constStr.str << std::endl; + std::cout << "hash -> " << constStr.hash << std::endl; + std::cout << "idx -> " << constStr.idx << std::endl; +}; + +BOOST_AUTO_TEST_CASE(StringHelpersConstStr) +{ + printString(CONST_STR("this/is/a/histogram")); + + auto myConstStr = CONST_STR("helloWorld"); + printString(myConstStr); + static_assert(std::is_same_v<decltype(myConstStr), ConstStr<'h', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'>>); + static_assert(myConstStr.hash == (uint32_t)942280617); + BOOST_CHECK_EQUAL(myConstStr.hash, compile_time_hash("helloWorld")); +} From f0b1395ca7f6569dfa78dbe3f99db58c471399f2 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Fri, 27 Nov 2020 09:40:21 +0100 Subject: [PATCH 1438/1751] Revert "add EventStatusWord to CTF and minor fix (#4911)" This reverts commit f2db4809ff043d87b7e92bbcd6e5724e44a3df0d. This commit broke the unit test Detectors/CTF/test/test_ctf_io_ft0.cxx which unfortunately was not spotted/executed in the CI. --- .../FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h | 6 +---- .../include/FT0Reconstruction/CTFCoder.h | 22 +++++++++---------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h index 5bb219a4b657e..407fba225fc1d 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h @@ -55,10 +55,6 @@ class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> // put here code for raw data checking void sanityCheck(bool& flag) { - if (DataBlockWrapper<RawDataPM>::mNelements == 0) { - flag = false; - return; - } if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) { DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling } @@ -109,4 +105,4 @@ class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, R } // namespace ft0 } // namespace o2 -#endif +#endif \ No newline at end of file diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h index 3e34be0154560..c6a922c529244 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/CTFCoder.h @@ -164,18 +164,18 @@ void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& cha const auto& chan = channelVec.emplace_back((chID += cd.idChan[icc]), cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtcChain[icc]); // // rebuild digit - // if (std::abs(chan.CFDTime) < Geometry::mTime_trg_gate) { - if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side - amplA += chan.QTCAmpl; - timeA += chan.CFDTime; - trig.nChanA++; - - } else { - amplC += chan.QTCAmpl; - timeC += chan.CFDTime; - trig.nChanC++; + if (std::abs(chan.CFDTime) < Geometry::mTime_trg_gate) { + if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side + amplA += chan.QTCAmpl; + timeA += chan.CFDTime; + trig.nChanA++; + + } else { + amplC += chan.QTCAmpl; + timeC += chan.CFDTime; + trig.nChanC++; + } } - // } } if (trig.nChanA) { trig.timeA = timeA / trig.nChanA; From 5dfcf63a80e3db967695317d16fbcf58dee37962 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <mpuccio@users.noreply.github.com> Date: Fri, 27 Nov 2020 16:39:57 +0100 Subject: [PATCH 1439/1751] ITS tracking works on generic N layers (#4511) * ITS tracking works on generic N layers * Reconstructing successfully Run5 simulation * Add macro to run the tracking for ALICE3 * Add alice3 tracking macro in cmakelists * Fix computeLayerTracklets * Remove unused vector for unsorted clusters * Add check to skip uninteresting rof * Fix memory in pp, add performance studies to macro * Make ITS CUDA tracker compile * Please consider the following formatting changes * Fix GPU tracker traits * Please consider the following formatting changes * Fix GPU vertexer compilation * Please consider the following formatting changes * Further vertexer fixes * Fix getBinsRect call * Fix dynamic memory allocation * Use the vertexer version of getBinsRect * Move headers in cxx to please ocl * Make codechecker happy (...) Co-authored-by: Fabio Catalano <fabio.catalano@cern.ch> Co-authored-by: ALICE Action Bot <alibuild@cern.ch> --- .../ITS/include/DataFormatsITS/TrackITS.h | 10 +- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 2 +- .../include/ITStrackingCUDA/DeviceStoreNV.h | 71 ++--- .../ITStrackingCUDA/DeviceStoreVertexerGPU.h | 2 +- .../ITStrackingCUDA/PrimaryVertexContextNV.h | 57 ++-- .../include/ITStrackingCUDA/TrackerTraitsNV.h | 2 +- .../ITStrackingCUDA/VertexerTraitsGPU.h | 4 +- .../ITS/tracking/cuda/src/DeviceStoreNV.cu | 30 +- .../cuda/src/DeviceStoreVertexerGPU.cu | 4 +- .../ITS/tracking/cuda/src/TrackerTraitsNV.cu | 87 ++++-- .../tracking/cuda/src/VertexerTraitsGPU.cu | 34 ++- .../tracking/include/ITStracking/Cluster.h | 9 +- .../include/ITStracking/Configuration.h | 69 ++--- .../tracking/include/ITStracking/Constants.h | 59 ++-- .../tracking/include/ITStracking/IOUtils.h | 3 +- .../include/ITStracking/IndexTableUtils.h | 67 +++-- .../ITStracking/PrimaryVertexContext.h | 97 ++----- .../tracking/include/ITStracking/ROframe.h | 26 +- .../ITS/tracking/include/ITStracking/Road.h | 4 +- .../include/ITStracking/TrackerTraits.h | 19 +- .../include/ITStracking/TrackerTraitsCPU.h | 2 +- .../include/ITStracking/VertexerTraits.h | 58 ++-- Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx | 21 +- Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx | 134 ++------- .../ITS/tracking/src/PrimaryVertexContext.cxx | 70 +++-- Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx | 6 +- Detectors/ITSMFT/ITS/tracking/src/Road.cxx | 4 +- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 135 ++++----- .../ITS/tracking/src/TrackerTraitsCPU.cxx | 49 +++- .../ITS/tracking/src/VertexerTraits.cxx | 51 ++-- .../ITS/workflow/src/CookedTrackerSpec.cxx | 2 +- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 2 +- GPU/GPUTracking/Global/GPUChainITS.cxx | 8 +- GPU/GPUTracking/Global/GPUChainITS.h | 4 +- GPU/GPUTracking/ITS/GPUITSFitter.h | 11 +- GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx | 8 +- macro/CMakeLists.txt | 6 + macro/run_primary_vertexer_ITS.C | 2 +- macro/run_trac_alice3.C | 263 ++++++++++++++++++ macro/run_trac_ca_its.C | 12 +- macro/run_trac_its.C | 2 +- 41 files changed, 905 insertions(+), 601 deletions(-) create mode 100644 macro/run_trac_alice3.C diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index a178a662b8796..2bed2f9be28be 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -37,7 +37,7 @@ class TrackITS : public o2::track::TrackParCov public: using o2::track::TrackParCov::TrackParCov; // inherit base constructors - static constexpr int MaxClusters = 7; + static constexpr int MaxClusters = 16; TrackITS() = default; TrackITS(const TrackITS& t) = default; @@ -87,7 +87,7 @@ class TrackITS : public o2::track::TrackParCov o2::track::TrackParCov& getParamOut() { return mParamOut; } const o2::track::TrackParCov& getParamOut() const { return mParamOut; } - void setPattern(uint8_t p) { mPattern = p; } + void setPattern(uint16_t p) { mPattern = p; } int getPattern() const { return mPattern; } bool hasHitOnLayer(int i) { return mPattern & (0x1 << i); } @@ -95,7 +95,7 @@ class TrackITS : public o2::track::TrackParCov o2::track::TrackParCov mParamOut; ///< parameter at largest radius ClusRefs mClusRef; ///< references on clusters float mChi2 = 0.; ///< Chi2 for this track - uint8_t mPattern = 0; ///< layers pattern + uint16_t mPattern = 0; ///< layers pattern ClassDefNV(TrackITS, 4); }; @@ -104,7 +104,7 @@ class TrackITSExt : public TrackITS { ///< heavy version of TrackITS, with clusters embedded public: - static constexpr int MaxClusters = 7; + static constexpr int MaxClusters = 16; /// Prepare for overlaps and new detector configurations using TrackITS::TrackITS; // inherit base constructors TrackITSExt(o2::track::TrackParCov&& parCov, short ncl, float chi2, @@ -132,7 +132,7 @@ class TrackITSExt : public TrackITS } private: - std::array<int, MaxClusters> mIndex = {-1}; ///< Indices of associated clusters + std::array<int, MaxClusters> mIndex = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; ///< Indices of associated clusters ClassDefNV(TrackITSExt, 2); }; } // namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 5465d25b3ab33..7315b166edf54 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -19,7 +19,7 @@ o2_add_library(ITStracking src/Label.cxx src/PrimaryVertexContext.cxx src/Road.cxx - src/StandaloneDebugger.cxx + # src/StandaloneDebugger.cxx src/Tracker.cxx src/TrackerTraitsCPU.cxx src/TrackingConfigParam.cxx diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h index d5e38ff3b6319..32485259f7980 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h @@ -29,6 +29,7 @@ namespace o2 { namespace its { + namespace GPU { @@ -38,83 +39,83 @@ class DeviceStoreNV final DeviceStoreNV(); UniquePointer<DeviceStoreNV> initialise(const float3&, - const std::array<std::vector<Cluster>, constants::its::LayersNumber>&, - const std::array<std::vector<Tracklet>, constants::its::TrackletsPerRoad>&, - const std::array<std::vector<Cell>, constants::its::CellsPerRoad>&, - const std::array<std::vector<int>, constants::its::CellsPerRoad - 1>&, - const std::array<float, constants::its::LayersNumber>&, - const std::array<float, constants::its::LayersNumber>&); + const std::array<std::vector<Cluster>, constants::its2::LayersNumber>&, + const std::array<std::vector<Tracklet>, constants::its2::TrackletsPerRoad>&, + const std::array<std::vector<Cell>, constants::its2::CellsPerRoad>&, + const std::array<std::vector<int>, constants::its2::CellsPerRoad - 1>&, + const std::array<float, constants::its2::LayersNumber>&, + const std::array<float, constants::its2::LayersNumber>&); GPU_DEVICE const float3& getPrimaryVertex(); - GPU_HOST_DEVICE Array<Vector<Cluster>, constants::its::LayersNumber>& getClusters(); - GPU_DEVICE Array<Array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, - constants::its::TrackletsPerRoad>& + GPU_HOST_DEVICE Array<Vector<Cluster>, constants::its2::LayersNumber>& getClusters(); + GPU_DEVICE Array<Array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, + constants::its2::TrackletsPerRoad>& getIndexTables(); - GPU_HOST_DEVICE Array<Vector<Tracklet>, constants::its::TrackletsPerRoad>& getTracklets(); - GPU_HOST_DEVICE Array<Vector<int>, constants::its::CellsPerRoad>& getTrackletsLookupTable(); - GPU_HOST_DEVICE Array<Vector<int>, constants::its::CellsPerRoad>& getTrackletsPerClusterTable(); - GPU_HOST_DEVICE Array<Vector<Cell>, constants::its::CellsPerRoad>& getCells(); - GPU_HOST_DEVICE Array<Vector<int>, constants::its::CellsPerRoad - 1>& getCellsLookupTable(); - GPU_HOST_DEVICE Array<Vector<int>, constants::its::CellsPerRoad - 1>& getCellsPerTrackletTable(); - Array<Vector<int>, constants::its::CellsPerRoad>& getTempTableArray(); + GPU_HOST_DEVICE Array<Vector<Tracklet>, constants::its2::TrackletsPerRoad>& getTracklets(); + GPU_HOST_DEVICE Array<Vector<int>, constants::its2::CellsPerRoad>& getTrackletsLookupTable(); + GPU_HOST_DEVICE Array<Vector<int>, constants::its2::CellsPerRoad>& getTrackletsPerClusterTable(); + GPU_HOST_DEVICE Array<Vector<Cell>, constants::its2::CellsPerRoad>& getCells(); + GPU_HOST_DEVICE Array<Vector<int>, constants::its2::CellsPerRoad - 1>& getCellsLookupTable(); + GPU_HOST_DEVICE Array<Vector<int>, constants::its2::CellsPerRoad - 1>& getCellsPerTrackletTable(); + Array<Vector<int>, constants::its2::CellsPerRoad>& getTempTableArray(); GPU_HOST_DEVICE float getRmin(int layer); GPU_HOST_DEVICE float getRmax(int layer); private: UniquePointer<float3> mPrimaryVertex; - Array<Vector<Cluster>, constants::its::LayersNumber> mClusters; - Array<float, constants::its::LayersNumber> mRmin; - Array<float, constants::its::LayersNumber> mRmax; - Array<Array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, constants::its::TrackletsPerRoad> + Array<Vector<Cluster>, constants::its2::LayersNumber> mClusters; + Array<float, constants::its2::LayersNumber> mRmin; + Array<float, constants::its2::LayersNumber> mRmax; + Array<Array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, constants::its2::TrackletsPerRoad> mIndexTables; - Array<Vector<Tracklet>, constants::its::TrackletsPerRoad> mTracklets; - Array<Vector<int>, constants::its::CellsPerRoad> mTrackletsLookupTable; - Array<Vector<int>, constants::its::CellsPerRoad> mTrackletsPerClusterTable; - Array<Vector<Cell>, constants::its::CellsPerRoad> mCells; - Array<Vector<int>, constants::its::CellsPerRoad - 1> mCellsLookupTable; - Array<Vector<int>, constants::its::CellsPerRoad - 1> mCellsPerTrackletTable; + Array<Vector<Tracklet>, constants::its2::TrackletsPerRoad> mTracklets; + Array<Vector<int>, constants::its2::CellsPerRoad> mTrackletsLookupTable; + Array<Vector<int>, constants::its2::CellsPerRoad> mTrackletsPerClusterTable; + Array<Vector<Cell>, constants::its2::CellsPerRoad> mCells; + Array<Vector<int>, constants::its2::CellsPerRoad - 1> mCellsLookupTable; + Array<Vector<int>, constants::its2::CellsPerRoad - 1> mCellsPerTrackletTable; }; GPU_DEVICE inline const float3& DeviceStoreNV::getPrimaryVertex() { return *mPrimaryVertex; } -GPU_HOST_DEVICE inline Array<Vector<Cluster>, constants::its::LayersNumber>& DeviceStoreNV::getClusters() +GPU_HOST_DEVICE inline Array<Vector<Cluster>, constants::its2::LayersNumber>& DeviceStoreNV::getClusters() { return mClusters; } -GPU_DEVICE inline Array<Array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, - constants::its::TrackletsPerRoad>& +GPU_DEVICE inline Array<Array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, + constants::its2::TrackletsPerRoad>& DeviceStoreNV::getIndexTables() { return mIndexTables; } -GPU_DEVICE inline Array<Vector<Tracklet>, constants::its::TrackletsPerRoad>& DeviceStoreNV::getTracklets() +GPU_DEVICE inline Array<Vector<Tracklet>, constants::its2::TrackletsPerRoad>& DeviceStoreNV::getTracklets() { return mTracklets; } -GPU_DEVICE inline Array<Vector<int>, constants::its::CellsPerRoad>& DeviceStoreNV::getTrackletsLookupTable() +GPU_DEVICE inline Array<Vector<int>, constants::its2::CellsPerRoad>& DeviceStoreNV::getTrackletsLookupTable() { return mTrackletsLookupTable; } -GPU_DEVICE inline Array<Vector<int>, constants::its::CellsPerRoad>& DeviceStoreNV::getTrackletsPerClusterTable() +GPU_DEVICE inline Array<Vector<int>, constants::its2::CellsPerRoad>& DeviceStoreNV::getTrackletsPerClusterTable() { return mTrackletsPerClusterTable; } -GPU_HOST_DEVICE inline Array<Vector<Cell>, constants::its::CellsPerRoad>& DeviceStoreNV::getCells() +GPU_HOST_DEVICE inline Array<Vector<Cell>, constants::its2::CellsPerRoad>& DeviceStoreNV::getCells() { return mCells; } -GPU_HOST_DEVICE inline Array<Vector<int>, constants::its::CellsPerRoad - 1>& DeviceStoreNV::getCellsLookupTable() +GPU_HOST_DEVICE inline Array<Vector<int>, constants::its2::CellsPerRoad - 1>& DeviceStoreNV::getCellsLookupTable() { return mCellsLookupTable; } -GPU_HOST_DEVICE inline Array<Vector<int>, constants::its::CellsPerRoad - 1>& +GPU_HOST_DEVICE inline Array<Vector<int>, constants::its2::CellsPerRoad - 1>& DeviceStoreNV::getCellsPerTrackletTable() { return mCellsPerTrackletTable; diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h index 6bf180fcb93ad..255eb952e96ff 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h @@ -57,7 +57,7 @@ class DeviceStoreVertexerGPU final ~DeviceStoreVertexerGPU() = default; UniquePointer<DeviceStoreVertexerGPU> initialise(const std::array<std::vector<Cluster>, constants::its::LayersNumberVertexer>&, - const std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, + const std::array<std::array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, constants::its::LayersNumberVertexer>&); // RO APIs diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h index d5d3493a52292..dac80e224b7b8 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h @@ -38,28 +38,28 @@ class PrimaryVertexContextNV final : public PrimaryVertexContext PrimaryVertexContextNV() = default; virtual ~PrimaryVertexContextNV() = default; - virtual void initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its::LayersNumber>& cl, - const std::array<float, 3>& pv, const int iteration); + void initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its2::LayersNumber>& cl, + const std::array<float, 3>& pv, const int iteration); GPU::DeviceStoreNV& getDeviceContext(); - GPU::Array<GPU::Vector<Cluster>, constants::its::LayersNumber>& getDeviceClusters(); - GPU::Array<GPU::Vector<Tracklet>, constants::its::TrackletsPerRoad>& getDeviceTracklets(); - GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad>& getDeviceTrackletsLookupTable(); - GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad>& getDeviceTrackletsPerClustersTable(); - GPU::Array<GPU::Vector<Cell>, constants::its::CellsPerRoad>& getDeviceCells(); - GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad - 1>& getDeviceCellsLookupTable(); - GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad - 1>& getDeviceCellsPerTrackletTable(); - std::array<GPU::Vector<int>, constants::its::CellsPerRoad>& getTempTableArray(); - std::array<GPU::Vector<Tracklet>, constants::its::CellsPerRoad>& getTempTrackletArray(); - std::array<GPU::Vector<Cell>, constants::its::CellsPerRoad - 1>& getTempCellArray(); + GPU::Array<GPU::Vector<Cluster>, constants::its2::LayersNumber>& getDeviceClusters(); + GPU::Array<GPU::Vector<Tracklet>, constants::its2::TrackletsPerRoad>& getDeviceTracklets(); + GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& getDeviceTrackletsLookupTable(); + GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& getDeviceTrackletsPerClustersTable(); + GPU::Array<GPU::Vector<Cell>, constants::its2::CellsPerRoad>& getDeviceCells(); + GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& getDeviceCellsLookupTable(); + GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& getDeviceCellsPerTrackletTable(); + std::array<GPU::Vector<int>, constants::its2::CellsPerRoad>& getTempTableArray(); + std::array<GPU::Vector<Tracklet>, constants::its2::CellsPerRoad>& getTempTrackletArray(); + std::array<GPU::Vector<Cell>, constants::its2::CellsPerRoad - 1>& getTempCellArray(); void updateDeviceContext(); private: GPU::DeviceStoreNV mGPUContext; GPU::UniquePointer<GPU::DeviceStoreNV> mGPUContextDevicePointer; - std::array<GPU::Vector<int>, constants::its::CellsPerRoad> mTempTableArray; - std::array<GPU::Vector<Tracklet>, constants::its::CellsPerRoad> mTempTrackletArray; - std::array<GPU::Vector<Cell>, constants::its::CellsPerRoad - 1> mTempCellArray; + std::array<GPU::Vector<int>, constants::its2::CellsPerRoad> mTempTableArray; + std::array<GPU::Vector<Tracklet>, constants::its2::CellsPerRoad> mTempTrackletArray; + std::array<GPU::Vector<Cell>, constants::its2::CellsPerRoad - 1> mTempCellArray; }; inline GPU::DeviceStoreNV& PrimaryVertexContextNV::getDeviceContext() @@ -67,54 +67,54 @@ inline GPU::DeviceStoreNV& PrimaryVertexContextNV::getDeviceContext() return *mGPUContextDevicePointer; } -inline GPU::Array<GPU::Vector<Cluster>, constants::its::LayersNumber>& PrimaryVertexContextNV::getDeviceClusters() +inline GPU::Array<GPU::Vector<Cluster>, constants::its2::LayersNumber>& PrimaryVertexContextNV::getDeviceClusters() { return mGPUContext.getClusters(); } -inline GPU::Array<GPU::Vector<Tracklet>, constants::its::TrackletsPerRoad>& PrimaryVertexContextNV::getDeviceTracklets() +inline GPU::Array<GPU::Vector<Tracklet>, constants::its2::TrackletsPerRoad>& PrimaryVertexContextNV::getDeviceTracklets() { return mGPUContext.getTracklets(); } -inline GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad>& PrimaryVertexContextNV::getDeviceTrackletsLookupTable() +inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceTrackletsLookupTable() { return mGPUContext.getTrackletsLookupTable(); } -inline GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad>& +inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceTrackletsPerClustersTable() { return mGPUContext.getTrackletsPerClusterTable(); } -inline GPU::Array<GPU::Vector<Cell>, constants::its::CellsPerRoad>& PrimaryVertexContextNV::getDeviceCells() +inline GPU::Array<GPU::Vector<Cell>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceCells() { return mGPUContext.getCells(); } -inline GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad - 1>& PrimaryVertexContextNV::getDeviceCellsLookupTable() +inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getDeviceCellsLookupTable() { return mGPUContext.getCellsLookupTable(); } -inline GPU::Array<GPU::Vector<int>, constants::its::CellsPerRoad - 1>& +inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getDeviceCellsPerTrackletTable() { return mGPUContext.getCellsPerTrackletTable(); } -inline std::array<GPU::Vector<int>, constants::its::CellsPerRoad>& PrimaryVertexContextNV::getTempTableArray() +inline std::array<GPU::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getTempTableArray() { return mTempTableArray; } -inline std::array<GPU::Vector<Tracklet>, constants::its::CellsPerRoad>& PrimaryVertexContextNV::getTempTrackletArray() +inline std::array<GPU::Vector<Tracklet>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getTempTrackletArray() { return mTempTrackletArray; } -inline std::array<GPU::Vector<Cell>, constants::its::CellsPerRoad - 1>& PrimaryVertexContextNV::getTempCellArray() +inline std::array<GPU::Vector<Cell>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getTempCellArray() { return mTempCellArray; } @@ -124,11 +124,12 @@ inline void PrimaryVertexContextNV::updateDeviceContext() mGPUContextDevicePointer = GPU::UniquePointer<GPU::DeviceStoreNV>{mGPUContext}; } -inline void PrimaryVertexContextNV::initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its::LayersNumber>& cl, +inline void PrimaryVertexContextNV::initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its2::LayersNumber>& cl, const std::array<float, 3>& pv, const int iteration) { - this->PrimaryVertexContext::initialise(memParam, cl, pv, iteration); - mGPUContextDevicePointer = mGPUContext.initialise(mPrimaryVertex, mClusters, mTracklets, mCells, mCellsLookupTable, mMinR, mMaxR); + ///TODO: to be re-enabled in the future + // this->PrimaryVertexContext::initialise(memParam, cl, pv, iteration); + // mGPUContextDevicePointer = mGPUContext.initialise(mPrimaryVertex, mClusters, mTracklets, mCells, mCellsLookupTable, mMinR, mMaxR); } } // namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h index ea90e52114428..e3dbd233c7d96 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h @@ -34,7 +34,7 @@ class TrackerTraitsNV : public TrackerTraits void computeLayerCells() final; void computeLayerTracklets() final; - void refitTracks(const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks) final; + void refitTracks(const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks); }; extern "C" TrackerTraits* createTrackerTraitsNV(); diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h index a3447e55c586f..4f218e9ada8d4 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h @@ -37,7 +37,7 @@ namespace its { class ROframe; -using constants::index_table::InversePhiBinSize; +using constants::its2::InversePhiBinSize; class VertexerTraitsGPU : public VertexerTraits { @@ -69,7 +69,7 @@ class VertexerTraitsGPU : public VertexerTraits inline GPUd() const int2 VertexerTraitsGPU::getBinsPhiRectWindow(const Cluster& currentCluster, float phiCut) { // This function returns the lowest PhiBin and the number of phi bins to be spanned, In the form int2{phiBinLow, PhiBinSpan} - const int phiBinMin{index_table_utils::getPhiBinIndex( + const int phiBinMin{constants::its2::getPhiBinIndex( math_utils::getNormalizedPhiCoordinate(currentCluster.phiCoordinate - phiCut))}; const int phiBinSpan{static_cast<int>(MATH_CEIL(phiCut * InversePhiBinSize))}; return int2{phiBinMin, phiBinSpan}; diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu index 14eb74ff41bde..c0152ab12a8bc 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu @@ -57,7 +57,7 @@ __device__ void fillIndexTables(GPU::DeviceStoreNV& primaryVertexContext, const if (currentClusterIndex == nextLayerClustersNum - 1) { - for (int iBin{currentBinIndex + 1}; iBin <= o2::its::constants::index_table::ZBins * o2::its::constants::index_table::PhiBins; + for (int iBin{currentBinIndex + 1}; iBin <= o2::its::constants::its2::ZBins * o2::its::constants::its2::PhiBins; iBin++) { primaryVertexContext.getIndexTables()[layerIndex][iBin] = nextLayerClustersNum; @@ -96,12 +96,12 @@ __global__ void fillDeviceStructures(GPU::DeviceStoreNV& primaryVertexContext, c { fillIndexTables(primaryVertexContext, layerIndex); - if (layerIndex < o2::its::constants::its::CellsPerRoad) { + if (layerIndex < o2::its::constants::its2::CellsPerRoad) { fillTrackletsPerClusterTables(primaryVertexContext, layerIndex); } - if (layerIndex < o2::its::constants::its::CellsPerRoad - 1) { + if (layerIndex < o2::its::constants::its2::CellsPerRoad - 1) { fillCellsPerClusterTables(primaryVertexContext, layerIndex); } @@ -121,34 +121,34 @@ DeviceStoreNV::DeviceStoreNV() } UniquePointer<DeviceStoreNV> DeviceStoreNV::initialise(const float3& primaryVertex, - const std::array<std::vector<Cluster>, constants::its::LayersNumber>& clusters, - const std::array<std::vector<Tracklet>, constants::its::TrackletsPerRoad>& tracklets, - const std::array<std::vector<Cell>, constants::its::CellsPerRoad>& cells, - const std::array<std::vector<int>, constants::its::CellsPerRoad - 1>& cellsLookupTable, - const std::array<float, constants::its::LayersNumber>& rmin, - const std::array<float, constants::its::LayersNumber>& rmax) + const std::array<std::vector<Cluster>, constants::its2::LayersNumber>& clusters, + const std::array<std::vector<Tracklet>, constants::its2::TrackletsPerRoad>& tracklets, + const std::array<std::vector<Cell>, constants::its2::CellsPerRoad>& cells, + const std::array<std::vector<int>, constants::its2::CellsPerRoad - 1>& cellsLookupTable, + const std::array<float, constants::its2::LayersNumber>& rmin, + const std::array<float, constants::its2::LayersNumber>& rmax) { mPrimaryVertex = UniquePointer<float3>{primaryVertex}; - for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::LayersNumber; ++iLayer) { this->mRmin[iLayer] = rmin[iLayer]; this->mRmax[iLayer] = rmax[iLayer]; this->mClusters[iLayer] = Vector<Cluster>{&clusters[iLayer][0], static_cast<int>(clusters[iLayer].size())}; - if (iLayer < constants::its::TrackletsPerRoad) { + if (iLayer < constants::its2::TrackletsPerRoad) { this->mTracklets[iLayer].reset(tracklets[iLayer].capacity()); } - if (iLayer < constants::its::CellsPerRoad) { + if (iLayer < constants::its2::CellsPerRoad) { this->mTrackletsLookupTable[iLayer].reset(static_cast<int>(clusters[iLayer + 1].size())); this->mTrackletsPerClusterTable[iLayer].reset(static_cast<int>(clusters[iLayer + 1].size())); this->mCells[iLayer].reset(static_cast<int>(cells[iLayer].capacity())); } - if (iLayer < constants::its::CellsPerRoad - 1) { + if (iLayer < constants::its2::CellsPerRoad - 1) { this->mCellsLookupTable[iLayer].reset(static_cast<int>(cellsLookupTable[iLayer].size())); this->mCellsPerTrackletTable[iLayer].reset(static_cast<int>(cellsLookupTable[iLayer].size())); @@ -157,9 +157,9 @@ UniquePointer<DeviceStoreNV> DeviceStoreNV::initialise(const float3& primaryVert UniquePointer<DeviceStoreNV> gpuContextDevicePointer{*this}; - std::array<Stream, constants::its::LayersNumber> streamArray; + std::array<Stream, constants::its2::LayersNumber> streamArray; - for (int iLayer{0}; iLayer < constants::its::TrackletsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::TrackletsPerRoad; ++iLayer) { const int nextLayerClustersNum = static_cast<int>(clusters[iLayer + 1].size()); diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu index cdcec77a16029..4c113d77e0ffd 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu @@ -47,7 +47,7 @@ DeviceStoreVertexerGPU::DeviceStoreVertexerGPU() mBeamPosition = Vector<float>{2, 2}; for (int iTable{0}; iTable < 2; ++iTable) { - mIndexTables[iTable] = Vector<int>{constants::index_table::ZBins * constants::index_table::PhiBins + 1}; // 2*20*20+1 * sizeof(int) = 802B + mIndexTables[iTable] = Vector<int>{constants::its2::ZBins * constants::its2::PhiBins + 1}; // 2*20*20+1 * sizeof(int) = 802B } for (int iLayer{0}; iLayer < constants::its::LayersNumberVertexer; ++iLayer) { // 4e4 * 3 * sizof(Cluster) = 3.36MB mClusters[iLayer] = Vector<Cluster>{mGPUConf.clustersPerLayerCapacity, mGPUConf.clustersPerLayerCapacity}; @@ -68,7 +68,7 @@ DeviceStoreVertexerGPU::DeviceStoreVertexerGPU() } // namespace GPU UniquePointer<DeviceStoreVertexerGPU> DeviceStoreVertexerGPU::initialise(const std::array<std::vector<Cluster>, constants::its::LayersNumberVertexer>& clusters, - const std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, + const std::array<std::array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, constants::its::LayersNumberVertexer>& indexTables) { #ifdef _ALLOW_DEBUG_TREES_ITS_ diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu index 186f0b25ead9a..c81a2c149b37c 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu @@ -37,10 +37,52 @@ namespace o2 { namespace its { + +using namespace constants::its2; +GPU_DEVICE const int4 getBinsRect(const Cluster& currentCluster, const int layerIndex, + const float z1, const float z2, float maxdeltaz, float maxdeltaphi) +{ + const float zRangeMin = gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; + const float phiRangeMin = currentCluster.phiCoordinate - maxdeltaphi; + const float zRangeMax = gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; + const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; + + if (zRangeMax < -LayersZCoordinate()[layerIndex + 1] || + zRangeMin > LayersZCoordinate()[layerIndex + 1] || zRangeMin > zRangeMax) { + + return getEmptyBinsRect(); + } + + return int4{gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), + getPhiBinIndex(phiRangeMin), + gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), + getPhiBinIndex(phiRangeMax)}; +} + namespace GPU { -__constant__ TrackingParameters kTrkPar; +struct StaticTrackingParameters { + StaticTrackingParameters& operator=(const StaticTrackingParameters& t); + + int CellMinimumLevel(); + + /// General parameters + int ClusterSharing = 0; + int MinTrackLength = 7; + /// Trackleting cuts + float TrackletMaxDeltaPhi = 0.3f; + float TrackletMaxDeltaZ[constants::its2::TrackletsPerRoad] = {0.1f, 0.1f, 0.3f, 0.3f, 0.3f, 0.3f}; + /// Cell finding cuts + float CellMaxDeltaTanLambda = 0.025f; + float CellMaxDCA[constants::its2::CellsPerRoad] = {0.05f, 0.04f, 0.05f, 0.2f, 0.4f}; + float CellMaxDeltaPhi = 0.14f; + float CellMaxDeltaZ[constants::its2::CellsPerRoad] = {0.2f, 0.4f, 0.5f, 0.6f, 3.0f}; + /// Neighbour finding cuts + float NeighbourMaxDeltaCurvature[constants::its2::CellsPerRoad - 1] = {0.008f, 0.0025f, 0.003f, 0.0035f}; + float NeighbourMaxDeltaN[constants::its2::CellsPerRoad - 1] = {0.002f, 0.0090f, 0.002f, 0.005f}; +}; +__constant__ StaticTrackingParameters kTrkPar; __device__ void computeLayerTracklets(DeviceStoreNV& devStore, const int layerIndex, Vector<Tracklet>& trackletsVector) @@ -62,8 +104,8 @@ __device__ void computeLayerTracklets(DeviceStoreNV& devStore, const int layerIn const float zAtRmin{tanLambda * (devStore.getRmin(layerIndex + 1) - currentCluster.rCoordinate) + currentCluster.zCoordinate}; const float zAtRmax{tanLambda * (devStore.getRmax(layerIndex + 1) - currentCluster.rCoordinate) + currentCluster.zCoordinate}; - const int4 selectedBinsRect{TrackerTraits::getBinsRect(currentCluster, layerIndex, zAtRmin, zAtRmax, - kTrkPar.TrackletMaxDeltaZ[layerIndex], kTrkPar.TrackletMaxDeltaPhi)}; + const int4 selectedBinsRect{getBinsRect(currentCluster, layerIndex, zAtRmin, zAtRmax, + kTrkPar.TrackletMaxDeltaZ[layerIndex], kTrkPar.TrackletMaxDeltaPhi)}; if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) { @@ -72,13 +114,13 @@ __device__ void computeLayerTracklets(DeviceStoreNV& devStore, const int layerIn if (phiBinsNum < 0) { - phiBinsNum += constants::index_table::PhiBins; + phiBinsNum += constants::its2::PhiBins; } for (int iPhiBin{selectedBinsRect.y}, iPhiCount{0}; iPhiCount < phiBinsNum; - iPhiBin = ++iPhiBin == constants::index_table::PhiBins ? 0 : iPhiBin, iPhiCount++) { + iPhiBin = ++iPhiBin == constants::its2::PhiBins ? 0 : iPhiBin, iPhiCount++) { - const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect.x, iPhiBin)}; + const int firstBinIndex{constants::its2::getBinIndex(selectedBinsRect.x, iPhiBin)}; const int firstRowClusterIndex = devStore.getIndexTables()[layerIndex][firstBinIndex]; const int maxRowClusterIndex = devStore.getIndexTables()[layerIndex][{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1}]; @@ -282,12 +324,12 @@ void TrackerTraitsNV::computeLayerTracklets() { PrimaryVertexContextNV* primaryVertexContext = static_cast<PrimaryVertexContextNV*>(mPrimaryVertexContext); - cudaMemcpyToSymbol(GPU::kTrkPar, &mTrkParams, sizeof(TrackingParameters)); - std::array<size_t, constants::its::CellsPerRoad> tempSize; - std::array<int, constants::its::CellsPerRoad> trackletsNum; - std::array<GPU::Stream, constants::its::TrackletsPerRoad> streamArray; + // cudaMemcpyToSymbol(GPU::kTrkPar, &mTrkParams, sizeof(TrackingParameters)); + std::array<size_t, constants::its2::CellsPerRoad> tempSize; + std::array<int, constants::its2::CellsPerRoad> trackletsNum; + std::array<GPU::Stream, constants::its2::TrackletsPerRoad> streamArray; - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad; ++iLayer) { tempSize[iLayer] = 0; primaryVertexContext->getTempTrackletArray()[iLayer].reset( @@ -303,7 +345,7 @@ void TrackerTraitsNV::computeLayerTracklets() cudaDeviceSynchronize(); - for (int iLayer{0}; iLayer < constants::its::TrackletsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::TrackletsPerRoad; ++iLayer) { const GPU::DeviceProperties& deviceProperties = GPU::Context::getInstance().getDeviceProperties(); const int clustersNum{static_cast<int>(primaryVertexContext->getClusters()[iLayer].size())}; @@ -335,7 +377,7 @@ void TrackerTraitsNV::computeLayerTracklets() cudaDeviceSynchronize(); - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad; ++iLayer) { trackletsNum[iLayer] = primaryVertexContext->getTempTrackletArray()[iLayer].getSizeFromDevice(); if (trackletsNum[iLayer] == 0) { @@ -371,12 +413,12 @@ void TrackerTraitsNV::computeLayerCells() { PrimaryVertexContextNV* primaryVertexContext = static_cast<PrimaryVertexContextNV*>(mPrimaryVertexContext); - std::array<size_t, constants::its::CellsPerRoad - 1> tempSize; - std::array<int, constants::its::CellsPerRoad - 1> trackletsNum; - std::array<int, constants::its::CellsPerRoad - 1> cellsNum; - std::array<GPU::Stream, constants::its::CellsPerRoad> streamArray; + std::array<size_t, constants::its2::CellsPerRoad - 1> tempSize; + std::array<int, constants::its2::CellsPerRoad - 1> trackletsNum; + std::array<int, constants::its2::CellsPerRoad - 1> cellsNum; + std::array<GPU::Stream, constants::its2::CellsPerRoad> streamArray; - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad - 1; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad - 1; ++iLayer) { tempSize[iLayer] = 0; trackletsNum[iLayer] = primaryVertexContext->getDeviceTracklets()[iLayer + 1].getSizeFromDevice(); @@ -394,7 +436,7 @@ void TrackerTraitsNV::computeLayerCells() cudaDeviceSynchronize(); - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad; ++iLayer) { const GPU::DeviceProperties& deviceProperties = GPU::Context::getInstance().getDeviceProperties(); const int trackletsSize = primaryVertexContext->getDeviceTracklets()[iLayer].getSizeFromDevice(); if (trackletsSize == 0) { @@ -428,7 +470,7 @@ void TrackerTraitsNV::computeLayerCells() cudaDeviceSynchronize(); - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad - 1; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad - 1; ++iLayer) { cellsNum[iLayer] = primaryVertexContext->getTempCellArray()[iLayer].getSizeFromDevice(); if (cellsNum[iLayer] == 0) { continue; @@ -460,7 +502,7 @@ void TrackerTraitsNV::computeLayerCells() cudaDeviceSynchronize(); - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad; ++iLayer) { int cellsSize = 0; if (iLayer == 0) { @@ -493,7 +535,8 @@ void TrackerTraitsNV::refitTracks(const std::array<std::vector<TrackingFrameInfo for (int iLayer = 0; iLayer < 7; iLayer++) { clusters[iLayer] = pvctx->getDeviceClusters()[iLayer].get(); } - mChainRunITSTrackFit(*mChain, mPrimaryVertexContext->getRoads(), clusters, cells, tf, tracks); + //TODO: restore this + // mChainRunITSTrackFit(*mChain, mPrimaryVertexContext->getRoads(), clusters, cells, tf, tracks); } } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu index 790a7b9f5b3bb..9b34edeecd800 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu @@ -37,16 +37,31 @@ namespace o2 namespace its { -using constants::index_table::PhiBins; -using constants::index_table::ZBins; -using constants::its::LayersRCoordinate; -using constants::its::LayersZCoordinate; using constants::its::VertexerHistogramVolume; using constants::math::TwoPi; -using index_table_utils::getPhiBinIndex; -using index_table_utils::getZBinIndex; using math_utils::getNormalizedPhiCoordinate; +using namespace constants::its2; +GPU_DEVICE const int4 getBinsRect(const Cluster& currentCluster, const int layerIndex, + const float z1, float maxdeltaz, float maxdeltaphi) +{ + const float zRangeMin = z1 - maxdeltaz; + const float phiRangeMin = currentCluster.phiCoordinate - maxdeltaphi; + const float zRangeMax = z1 + maxdeltaz; + const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; + + if (zRangeMax < -LayersZCoordinate()[layerIndex + 1] || + zRangeMin > LayersZCoordinate()[layerIndex + 1] || zRangeMin > zRangeMax) { + + return getEmptyBinsRect(); + } + + return int4{gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), + getPhiBinIndex(phiRangeMin), + gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), + getPhiBinIndex(phiRangeMax)}; +} + GPUh() void gpuThrowOnError() { cudaError_t error = cudaGetLastError(); @@ -82,7 +97,8 @@ void VertexerTraitsGPU::initialise(ROframe* event) { reset(); arrangeClusters(event); - mStoreVertexerGPUPtr = mStoreVertexerGPU.initialise(mClusters, mIndexTables); + //TODO: restore this + // mStoreVertexerGPUPtr = mStoreVertexerGPU.initialise(mClusters, mIndexTables); } namespace GPU @@ -147,7 +163,7 @@ GPUg() void trackleterKernel( const size_t stride{currentClusterIndex * store.getConfig().maxTrackletsPerCluster}; const Cluster& currentCluster = store.getClusters()[1][currentClusterIndex]; // assign-constructor may be a problem, check const VertexerLayerName adjacentLayerIndex{layerOrder == TrackletingLayerOrder::fromInnermostToMiddleLayer ? VertexerLayerName::innermostLayer : VertexerLayerName::outerLayer}; - const int4 selectedBinsRect{VertexerTraits::getBinsRect(currentCluster, static_cast<int>(adjacentLayerIndex), 0.f, 50.f, phiCut / 2)}; + const int4 selectedBinsRect{getBinsRect(currentCluster, static_cast<int>(adjacentLayerIndex), 0.f, 50.f, phiCut / 2)}; if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) { int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; if (phiBinsNum < 0) { @@ -155,7 +171,7 @@ GPUg() void trackleterKernel( } const size_t nClustersAdjacentLayer = store.getClusters()[static_cast<int>(adjacentLayerIndex)].size(); for (size_t iPhiBin{(size_t)selectedBinsRect.y}, iPhiCount{0}; iPhiCount < (size_t)phiBinsNum; iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) { - const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect.x, iPhiBin)}; + const int firstBinIndex{constants::its2::getBinIndex(selectedBinsRect.x, iPhiBin)}; const int firstRowClusterIndex{store.getIndexTable(adjacentLayerIndex)[firstBinIndex]}; const int maxRowClusterIndex{store.getIndexTable(adjacentLayerIndex)[firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1]}; for (size_t iAdjacentCluster{(size_t)firstRowClusterIndex}; iAdjacentCluster < (size_t)maxRowClusterIndex && iAdjacentCluster < nClustersAdjacentLayer; ++iAdjacentCluster) { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h index 68c09dc52f5a5..9c2d7b7fe9f40 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h @@ -21,19 +21,20 @@ #include "ITStracking/Definitions.h" #include "ITStracking/MathUtils.h" -#include "ITStracking/IndexTableUtils.h" namespace o2 { namespace its { +class IndexTableUtils; + struct Cluster final { Cluster() = default; Cluster(const float x, const float y, const float z, const int idx); - Cluster(const int, const Cluster&); - Cluster(const int, const float3&, const Cluster&); - void Init(const int, const float3&, const Cluster&); + Cluster(const int, const IndexTableUtils& utils, const Cluster&); + Cluster(const int, const float3&, const IndexTableUtils& utils, const Cluster&); + void Init(const int, const float3&, const IndexTableUtils& utils, const Cluster&); float xCoordinate; // = -999.f; float yCoordinate; // = -999.f; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 2951da3b81ae3..671804e39b3b2 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -15,10 +15,12 @@ #ifndef TRACKINGITSU_INCLUDE_CONFIGURATION_H_ #define TRACKINGITSU_INCLUDE_CONFIGURATION_H_ +#ifndef GPUCA_GPUCODE_DEVICE #include <array> #include <climits> #include <vector> #include <cmath> +#endif #include "ITStracking/Constants.h" @@ -44,32 +46,40 @@ class Configuration : public Param }; struct TrackingParameters { - TrackingParameters& operator=(const TrackingParameters& t); + TrackingParameters& operator=(const TrackingParameters& t) = default; int CellMinimumLevel(); + int CellsPerRoad() const { return NLayers - 2; } + int TrackletsPerRoad() const { return NLayers - 1; } + + int NLayers = 7; + std::vector<float> LayerZ = {16.333f + 1, 16.333f + 1, 16.333f + 1, 42.140f + 1, 42.140f + 1, 73.745f + 1, 73.745f + 1}; + std::vector<float> LayerRadii = {2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; + int ZBins{256}; + int PhiBins{128}; /// General parameters int ClusterSharing = 0; int MinTrackLength = 7; /// Trackleting cuts float TrackletMaxDeltaPhi = 0.3f; - float TrackletMaxDeltaZ[constants::its::TrackletsPerRoad] = {0.1f, 0.1f, 0.3f, 0.3f, 0.3f, 0.3f}; + std::vector<float> TrackletMaxDeltaZ = {0.1f, 0.1f, 0.3f, 0.3f, 0.3f, 0.3f}; /// Cell finding cuts float CellMaxDeltaTanLambda = 0.025f; - float CellMaxDCA[constants::its::CellsPerRoad] = {0.05f, 0.04f, 0.05f, 0.2f, 0.4f}; + std::vector<float> CellMaxDCA = {0.05f, 0.04f, 0.05f, 0.2f, 0.4f}; float CellMaxDeltaPhi = 0.14f; - float CellMaxDeltaZ[constants::its::CellsPerRoad] = {0.2f, 0.4f, 0.5f, 0.6f, 3.0f}; + std::vector<float> CellMaxDeltaZ = {0.2f, 0.4f, 0.5f, 0.6f, 3.0f}; /// Neighbour finding cuts - float NeighbourMaxDeltaCurvature[constants::its::CellsPerRoad - 1] = {0.008f, 0.0025f, 0.003f, 0.0035f}; - float NeighbourMaxDeltaN[constants::its::CellsPerRoad - 1] = {0.002f, 0.0090f, 0.002f, 0.005f}; + std::vector<float> NeighbourMaxDeltaCurvature = {0.008f, 0.0025f, 0.003f, 0.0035f}; + std::vector<float> NeighbourMaxDeltaN = {0.002f, 0.0090f, 0.002f, 0.005f}; }; struct MemoryParameters { /// Memory coefficients - MemoryParameters& operator=(const MemoryParameters& t); + MemoryParameters& operator=(const MemoryParameters& t) = default; int MemoryOffset = 256; - float CellsMemoryCoefficients[constants::its::CellsPerRoad] = {2.3208e-08f, 2.104e-08f, 1.6432e-08f, 1.2412e-08f, 1.3543e-08f}; - float TrackletsMemoryCoefficients[constants::its::TrackletsPerRoad] = {0.0016353f, 0.0013627f, 0.000984f, 0.00078135f, 0.00057934f, 0.00052217f}; + std::vector<float> CellsMemoryCoefficients = {2.3208e-08f, 2.104e-08f, 1.6432e-08f, 1.2412e-08f, 1.3543e-08f}; + std::vector<float> TrackletsMemoryCoefficients = {0.0016353f, 0.0013627f, 0.000984f, 0.00078135f, 0.00057934f, 0.00052217f}; }; inline int TrackingParameters::CellMinimumLevel() @@ -77,43 +87,12 @@ inline int TrackingParameters::CellMinimumLevel() return MinTrackLength - constants::its::ClustersPerCell + 1; } -inline TrackingParameters& TrackingParameters::operator=(const TrackingParameters& t) -{ - this->ClusterSharing = t.ClusterSharing; - this->MinTrackLength = t.MinTrackLength; - /// Trackleting cuts - this->TrackletMaxDeltaPhi = t.TrackletMaxDeltaPhi; - for (int iT = 0; iT < constants::its::TrackletsPerRoad; ++iT) { - this->TrackletMaxDeltaZ[iT] = t.TrackletMaxDeltaZ[iT]; - } - /// Cell finding cuts - this->CellMaxDeltaTanLambda = t.CellMaxDeltaTanLambda; - this->CellMaxDeltaPhi = t.CellMaxDeltaPhi; - for (int iC = 0; iC < constants::its::CellsPerRoad; ++iC) { - this->CellMaxDCA[iC] = t.CellMaxDCA[iC]; - this->CellMaxDeltaZ[iC] = t.CellMaxDeltaZ[iC]; - } - /// Neighbour finding cuts - for (int iC = 0; iC < constants::its::CellsPerRoad - 1; ++iC) { - this->NeighbourMaxDeltaCurvature[iC] = t.NeighbourMaxDeltaCurvature[iC]; - this->NeighbourMaxDeltaN[iC] = t.NeighbourMaxDeltaN[iC]; - } - return *this; -} - -inline MemoryParameters& MemoryParameters::operator=(const MemoryParameters& t) -{ - this->MemoryOffset = t.MemoryOffset; - for (int iC = 0; iC < constants::its::CellsPerRoad; ++iC) { - this->CellsMemoryCoefficients[iC] = t.CellsMemoryCoefficients[iC]; - } - for (int iT = 0; iT < constants::its::TrackletsPerRoad; ++iT) { - this->TrackletsMemoryCoefficients[iT] = t.TrackletsMemoryCoefficients[iT]; - } - return *this; -} - struct VertexingParameters { + std::vector<float> LayerZ = {16.333f + 1, 16.333f + 1, 16.333f + 1, 42.140f + 1, 42.140f + 1, 73.745f + 1, 73.745f + 1}; + std::vector<float> LayerRadii = {2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; + int ZBins{256}; + int PhiBins{128}; + float zCut = 0.002f; //0.002f float phiCut = 0.005f; //0.005f float pairCut = 0.04f; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index e6353c9cae8af..40cdc77f185c5 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -21,6 +21,7 @@ #endif #include "ITStracking/Definitions.h" +#include "GPUCommonMath.h" namespace o2 { @@ -41,14 +42,23 @@ constexpr float FloatMinThreshold{1e-20f}; namespace its { -constexpr int LayersNumber{7}; constexpr int LayersNumberVertexer{3}; -constexpr int TrackletsPerRoad{LayersNumber - 1}; -constexpr int CellsPerRoad{LayersNumber - 2}; constexpr int ClustersPerCell{3}; constexpr int UnusedIndex{-1}; constexpr float Resolution{0.0005f}; +GPU_HOST_DEVICE constexpr GPUArray<float, 3> VertexerHistogramVolume() +{ + return GPUArray<float, 3>{{1.98, 1.98, 40.f}}; +} +} // namespace its + +namespace its2 +{ +constexpr int LayersNumber{7}; +constexpr int TrackletsPerRoad{LayersNumber - 1}; +constexpr int CellsPerRoad{LayersNumber - 2}; + GPU_HOST_DEVICE constexpr GPUArray<float, LayersNumber> LayersZCoordinate() { constexpr double s = 1.; // safety margin @@ -58,25 +68,42 @@ GPU_HOST_DEVICE constexpr GPUArray<float, LayersNumber> LayersRCoordinate() { return GPUArray<float, LayersNumber>{{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}}; } -GPU_HOST_DEVICE constexpr GPUArray<float, 3> VertexerHistogramVolume() + +constexpr int ZBins{256}; +constexpr int PhiBins{128}; +constexpr float InversePhiBinSize{PhiBins / constants::math::TwoPi}; +GPU_HOST_DEVICE constexpr GPUArray<float, LayersNumber> InverseZBinSize() { - return GPUArray<float, 3>{{1.98, 1.98, 40.f}}; + constexpr auto zSize = LayersZCoordinate(); + return GPUArray<float, LayersNumber>{{0.5f * ZBins / (zSize[0]), 0.5f * ZBins / (zSize[1]), 0.5f * ZBins / (zSize[2]), + 0.5f * ZBins / (zSize[3]), 0.5f * ZBins / (zSize[4]), 0.5f * ZBins / (zSize[5]), + 0.5f * ZBins / (zSize[6])}}; +} +inline float getInverseZCoordinate(const int layerIndex) +{ + return 0.5f * ZBins / LayersZCoordinate()[layerIndex]; } -} // namespace its -namespace index_table +GPU_HOST_DEVICE inline int getZBinIndex(const int layerIndex, const float zCoordinate) { -constexpr int ZBins{256}; -constexpr int PhiBins{128}; -constexpr float InversePhiBinSize{constants::index_table::PhiBins / constants::math::TwoPi}; -GPU_HOST_DEVICE constexpr GPUArray<float, its::LayersNumber> InverseZBinSize() + return (zCoordinate + LayersZCoordinate()[layerIndex]) * + InverseZBinSize()[layerIndex]; +} + +GPU_HOST_DEVICE inline int getPhiBinIndex(const float currentPhi) { - constexpr auto zSize = its::LayersZCoordinate(); - return GPUArray<float, its::LayersNumber>{{0.5f * ZBins / (zSize[0]), 0.5f * ZBins / (zSize[1]), 0.5f * ZBins / (zSize[2]), - 0.5f * ZBins / (zSize[3]), 0.5f * ZBins / (zSize[4]), 0.5f * ZBins / (zSize[5]), - 0.5f * ZBins / (zSize[6])}}; + return (currentPhi * InversePhiBinSize); } -} // namespace index_table + +GPU_HOST_DEVICE inline int getBinIndex(const int zIndex, const int phiIndex) +{ + return gpu::GPUCommonMath::Min(phiIndex * ZBins + zIndex, + ZBins * PhiBins - 1); +} + +GPU_HOST_DEVICE constexpr int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } + +} // namespace its2 namespace pdgcodes { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h index 8afe8dbbe4b78..621052f088f91 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h @@ -55,7 +55,6 @@ constexpr float DefClusErrorCol = o2::itsmft::SegmentationAlpide::PitchCol * 0.5 constexpr float DefClusError2Row = DefClusErrorRow * DefClusErrorRow; constexpr float DefClusError2Col = DefClusErrorCol * DefClusErrorCol; -void loadConfigurations(const std::string&); std::vector<ROframe> loadEventData(const std::string&); void loadEventData(ROframe& events, gsl::span<const itsmft::CompClusterExt> clusters, gsl::span<const unsigned char>::iterator& pattIt, const itsmft::TopologyDictionary& dict, @@ -63,7 +62,7 @@ void loadEventData(ROframe& events, gsl::span<const itsmft::CompClusterExt> clus int loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& events, gsl::span<const itsmft::CompClusterExt> clusters, gsl::span<const unsigned char>::iterator& pattIt, const itsmft::TopologyDictionary& dict, const dataformats::MCTruthContainer<MCCompLabel>* mClsLabels = nullptr); -void generateSimpleData(ROframe& event, const int phiDivs, const int zDivs); +// void generateSimpleData(ROframe& event, const int phiDivs, const int zDivs); void convertCompactClusters(gsl::span<const itsmft::CompClusterExt> clusters, gsl::span<const unsigned char>::iterator& pattIt, diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h index 228defce3b650..034994ca898f5 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h @@ -22,6 +22,7 @@ #endif #include "ITStracking/Constants.h" +#include "ITStracking/Configuration.h" #include "ITStracking/Definitions.h" #include "GPUCommonMath.h" #include "GPUCommonDef.h" @@ -31,42 +32,64 @@ namespace o2 namespace its { -namespace index_table_utils +class IndexTableUtils { -float getInverseZBinSize(const int); -GPUhdi() int getZBinIndex(const int, const float); -GPUhdi() int getPhiBinIndex(const float); -GPUhdi() int getBinIndex(const int, const int); -GPUhdi() int countRowSelectedBins( - const GPUArray<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>&, const int, const int, - const int); -} // namespace index_table_utils + public: + template <class T> + void setTrackingParameters(const T& params); + float getInverseZCoordinate(const int layerIndex) const; + GPUhdi() int getZBinIndex(const int, const float) const; + GPUhdi() int getPhiBinIndex(const float) const; + GPUhdi() int getBinIndex(const int, const int) const; + GPUhdi() int countRowSelectedBins(const int*, const int, const int, const int) const; -inline float getInverseZCoordinate(const int layerIndex) + GPUhdi() int getNzBins() const { return mNzBins; } + GPUhdi() int getNphiBins() const { return mNphiBins; } + GPUhdi() float getLayerZ(int i) const { return mLayerZ[i]; } + + private: + int mNzBins = 0; + int mNphiBins = 0; + float mInversePhiBinSize = 0.f; + std::vector<float> mLayerZ; + std::vector<float> mInverseZBinSize; +}; + +template <class T> +inline void IndexTableUtils::setTrackingParameters(const T& params) +{ + mInversePhiBinSize = params.PhiBins / constants::math::TwoPi; + mInverseZBinSize.resize(params.LayerZ.size()); + mNzBins = params.ZBins; + mNphiBins = params.PhiBins; + mLayerZ = params.LayerZ; + for (unsigned int iL{0}; iL < mInverseZBinSize.size(); ++iL) { + mInverseZBinSize[iL] = 0.5f * params.ZBins / params.LayerZ[iL]; + } +} + +inline float IndexTableUtils::getInverseZCoordinate(const int layerIndex) const { - return 0.5f * constants::index_table::ZBins / constants::its::LayersZCoordinate()[layerIndex]; + return 0.5f * mNzBins / mLayerZ[layerIndex]; } -GPUhdi() int index_table_utils::getZBinIndex(const int layerIndex, const float zCoordinate) +GPUhdi() int IndexTableUtils::getZBinIndex(const int layerIndex, const float zCoordinate) const { - return (zCoordinate + constants::its::LayersZCoordinate()[layerIndex]) * - constants::index_table::InverseZBinSize()[layerIndex]; + return (zCoordinate + mLayerZ[layerIndex]) * mInverseZBinSize[layerIndex]; } -GPUhdi() int index_table_utils::getPhiBinIndex(const float currentPhi) +GPUhdi() int IndexTableUtils::getPhiBinIndex(const float currentPhi) const { - return (currentPhi * constants::index_table::InversePhiBinSize); + return (currentPhi * mInversePhiBinSize); } -GPUhdi() int index_table_utils::getBinIndex(const int zIndex, const int phiIndex) +GPUhdi() int IndexTableUtils::getBinIndex(const int zIndex, const int phiIndex) const { - return gpu::GPUCommonMath::Min(phiIndex * constants::index_table::ZBins + zIndex, - constants::index_table::ZBins * constants::index_table::PhiBins - 1); + return gpu::GPUCommonMath::Min(phiIndex * mNzBins + zIndex, mNzBins * mNphiBins - 1); } -GPUhdi() int index_table_utils::countRowSelectedBins( - const GPUArray<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>& indexTable, - const int phiBinIndex, const int minZBinIndex, const int maxZBinIndex) +GPUhdi() int IndexTableUtils::countRowSelectedBins(const int* indexTable, const int phiBinIndex, + const int minZBinIndex, const int maxZBinIndex) const { const int firstBinIndex{getBinIndex(minZBinIndex, phiBinIndex)}; const int maxBinIndex{firstBinIndex + maxZBinIndex - minZBinIndex + 1}; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h index 3c363c4d7219f..112c3fe77d3dd 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h @@ -24,6 +24,7 @@ #include "ITStracking/Configuration.h" #include "ITStracking/Constants.h" #include "ITStracking/Definitions.h" +#include "ITStracking/IndexTableUtils.h" #include "ITStracking/Road.h" #include "ITStracking/Tracklet.h" @@ -42,99 +43,55 @@ class PrimaryVertexContext PrimaryVertexContext(const PrimaryVertexContext&) = delete; PrimaryVertexContext& operator=(const PrimaryVertexContext&) = delete; - virtual void initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its::LayersNumber>& cl, - const std::array<float, 3>& pv, const int iteration); - const float3& getPrimaryVertex() const; - std::array<std::vector<Cluster>, constants::its::LayersNumber>& getClusters(); - std::array<std::vector<Cell>, constants::its::CellsPerRoad>& getCells(); - std::array<std::vector<int>, constants::its::CellsPerRoad - 1>& getCellsLookupTable(); - std::array<std::vector<std::vector<int>>, constants::its::CellsPerRoad - 1>& getCellsNeighbours(); - std::vector<Road>& getRoads(); + virtual void initialise(const MemoryParameters& memParam, const TrackingParameters& trkParam, + const std::vector<std::vector<Cluster>>& cl, const std::array<float, 3>& pv, const int iteration); + const float3& getPrimaryVertex() const { return mPrimaryVertex; } + auto& getClusters() { return mClusters; } + auto& getCells() { return mCells; } + auto& getCellsLookupTable() { return mCellsLookupTable; } + auto& getCellsNeighbours() { return mCellsNeighbours; } + auto& getRoads() { return mRoads; } float getMinR(int layer) { return mMinR[layer]; } float getMaxR(int layer) { return mMaxR[layer]; } - bool isClusterUsed(int layer, int clusterId) const; + bool isClusterUsed(int layer, int clusterId) const { return mUsedClusters[layer][clusterId]; } void markUsedCluster(int layer, int clusterId); - std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, - constants::its::TrackletsPerRoad>& - getIndexTables(); - std::array<std::vector<Tracklet>, constants::its::TrackletsPerRoad>& getTracklets(); - std::array<std::vector<int>, constants::its::CellsPerRoad>& getTrackletsLookupTable(); + auto& getIndexTables() { return mIndexTables; } + auto& getTracklets() { return mTracklets; } + auto& getTrackletsLookupTable() { return mTrackletsLookupTable; } void initialiseRoadLabels(); void setRoadLabel(int i, const unsigned long long& lab, bool fake); const unsigned long long& getRoadLabel(int i) const; bool isRoadFake(int i) const; + IndexTableUtils mIndexTableUtils; + protected: float3 mPrimaryVertex; - std::array<float, constants::its::LayersNumber> mMinR; - std::array<float, constants::its::LayersNumber> mMaxR; - std::array<std::vector<Cluster>, constants::its::LayersNumber> mUnsortedClusters; - std::array<std::vector<Cluster>, constants::its::LayersNumber> mClusters; - std::array<std::vector<bool>, constants::its::LayersNumber> mUsedClusters; - std::array<std::vector<Cell>, constants::its::CellsPerRoad> mCells; - std::array<std::vector<int>, constants::its::CellsPerRoad - 1> mCellsLookupTable; - std::array<std::vector<std::vector<int>>, constants::its::CellsPerRoad - 1> mCellsNeighbours; + std::vector<float> mMinR; + std::vector<float> mMaxR; + std::vector<std::vector<Cluster>> mClusters; + std::vector<std::vector<bool>> mUsedClusters; + std::vector<std::vector<Cell>> mCells; + std::vector<std::vector<int>> mCellsLookupTable; + std::vector<std::vector<std::vector<int>>> mCellsNeighbours; std::vector<Road> mRoads; - std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, - constants::its::TrackletsPerRoad> - mIndexTables; - std::array<std::vector<Tracklet>, constants::its::TrackletsPerRoad> mTracklets; - std::array<std::vector<int>, constants::its::CellsPerRoad> mTrackletsLookupTable; + // std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, + // constants::its::TrackletsPerRoad> + std::vector<std::vector<int>> mIndexTables; + std::vector<std::vector<Tracklet>> mTracklets; + std::vector<std::vector<int>> mTrackletsLookupTable; std::vector<std::pair<unsigned long long, bool>> mRoadLabels; }; -inline const float3& PrimaryVertexContext::getPrimaryVertex() const { return mPrimaryVertex; } - -inline std::array<std::vector<Cluster>, constants::its::LayersNumber>& PrimaryVertexContext::getClusters() -{ - return mClusters; -} - -inline std::array<std::vector<Cell>, constants::its::CellsPerRoad>& PrimaryVertexContext::getCells() { return mCells; } - -inline std::array<std::vector<int>, constants::its::CellsPerRoad - 1>& PrimaryVertexContext::getCellsLookupTable() -{ - return mCellsLookupTable; -} - -inline std::array<std::vector<std::vector<int>>, constants::its::CellsPerRoad - 1>& - PrimaryVertexContext::getCellsNeighbours() -{ - return mCellsNeighbours; -} - -inline std::vector<Road>& PrimaryVertexContext::getRoads() { return mRoads; } - -inline bool PrimaryVertexContext::isClusterUsed(int layer, int clusterId) const -{ - return mUsedClusters[layer][clusterId]; -} inline void PrimaryVertexContext::markUsedCluster(int layer, int clusterId) { mUsedClusters[layer][clusterId] = true; } -inline std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, - constants::its::TrackletsPerRoad>& - PrimaryVertexContext::getIndexTables() -{ - return mIndexTables; -} - -inline std::array<std::vector<Tracklet>, constants::its::TrackletsPerRoad>& PrimaryVertexContext::getTracklets() -{ - return mTracklets; -} - -inline std::array<std::vector<int>, constants::its::CellsPerRoad>& PrimaryVertexContext::getTrackletsLookupTable() -{ - return mTrackletsLookupTable; -} - inline void PrimaryVertexContext::initialiseRoadLabels() { mRoadLabels.clear(); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h index 99c1578540e4d..45ba3e4498ce3 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h @@ -38,7 +38,7 @@ using Vertex = o2::dataformats::Vertex<o2::dataformats::TimeStamp<int>>; class ROframe final { public: - ROframe(int ROframeId); + ROframe(int ROframeId, int nLayers); int getROFrameId() const; const float3& getPrimaryVertex(const int) const; int getPrimaryVerticesNum() const; @@ -49,10 +49,10 @@ class ROframe final int getTotalClusters() const; bool empty() const; - const std::array<std::vector<Cluster>, constants::its::LayersNumber>& getClusters() const; + const auto& getClusters() const { return mClusters; } const std::vector<Cluster>& getClustersOnLayer(int layerId) const; const std::vector<TrackingFrameInfo>& getTrackingFrameInfoOnLayer(int layerId) const; - const std::array<std::vector<TrackingFrameInfo>, constants::its::LayersNumber>& getTrackingFrameInfo() const; + const auto& getTrackingFrameInfo() const { return mTrackingFrameInfo; } const TrackingFrameInfo& getClusterTrackingFrameInfo(int layerId, const Cluster& cl) const; const MCCompLabel& getClusterLabels(int layerId, const Cluster& cl) const; @@ -73,10 +73,10 @@ class ROframe final private: const int mROframeId; std::vector<float3> mPrimaryVertices; - std::array<std::vector<Cluster>, constants::its::LayersNumber> mClusters; - std::array<std::vector<TrackingFrameInfo>, constants::its::LayersNumber> mTrackingFrameInfo; - std::array<std::vector<MCCompLabel>, constants::its::LayersNumber> mClusterLabels; - std::array<std::vector<int>, constants::its::LayersNumber> mClusterExternalIndices; + std::vector<std::vector<Cluster>> mClusters; + std::vector<std::vector<TrackingFrameInfo>> mTrackingFrameInfo; + std::vector<std::vector<MCCompLabel>> mClusterLabels; + std::vector<std::vector<int>> mClusterExternalIndices; }; inline int ROframe::getROFrameId() const { return mROframeId; } @@ -87,11 +87,6 @@ inline int ROframe::getPrimaryVerticesNum() const { return mPrimaryVertices.size inline bool ROframe::empty() const { return getTotalClusters() == 0; } -inline const std::array<std::vector<Cluster>, constants::its::LayersNumber>& ROframe::getClusters() const -{ - return mClusters; -} - inline const std::vector<Cluster>& ROframe::getClustersOnLayer(int layerId) const { return mClusters[layerId]; @@ -102,11 +97,6 @@ inline const std::vector<TrackingFrameInfo>& ROframe::getTrackingFrameInfoOnLaye return mTrackingFrameInfo[layerId]; } -inline const std::array<std::vector<TrackingFrameInfo>, constants::its::LayersNumber>& ROframe::getTrackingFrameInfo() const -{ - return mTrackingFrameInfo; -} - inline const TrackingFrameInfo& ROframe::getClusterTrackingFrameInfo(int layerId, const Cluster& cl) const { return mTrackingFrameInfo[layerId][cl.clusterId]; @@ -157,7 +147,7 @@ inline void ROframe::addClusterExternalIndexToLayer(int layer, const int idx) inline void ROframe::clear() { - for (int iL = 0; iL < constants::its::LayersNumber; ++iL) { + for (unsigned int iL = 0; iL < mClusters.size(); ++iL) { mClusters[iL].clear(); mTrackingFrameInfo[iL].clear(); mClusterLabels[iL].clear(); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h index 9650eb9fa9ab7..04946fad243e7 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h @@ -43,8 +43,10 @@ class Road final void resetRoad(); void addCell(int, int); + static constexpr int mMaxRoadSize = 13; + private: - int mCellIds[constants::its::CellsPerRoad]; + int mCellIds[mMaxRoadSize]; int mRoadSize; int mLabel; bool mIsFakeRoad; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 65500276c3374..913cc5dc805ac 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -41,7 +41,7 @@ namespace its { class TrackITSExt; -typedef std::function<int(o2::gpu::GPUChainITS&, std::vector<Road>& roads, std::array<const Cluster*, 7>, std::array<const Cell*, 5>, const std::array<std::vector<TrackingFrameInfo>, 7>&, std::vector<TrackITSExt>&)> FuncRunITSTrackFit_t; +typedef std::function<int(o2::gpu::GPUChainITS&, std::vector<Road>& roads, std::vector<const Cluster*>&, std::vector<const Cell*>&, const std::vector<std::vector<TrackingFrameInfo>>&, std::vector<TrackITSExt>&)> FuncRunITSTrackFit_t; class TrackerTraits { @@ -49,7 +49,7 @@ class TrackerTraits virtual ~TrackerTraits() = default; GPU_HOST_DEVICE static constexpr int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } - GPU_DEVICE static const int4 getBinsRect(const Cluster&, const int, const float, const float, float maxdeltaz, float maxdeltaphi); + GPU_DEVICE const int4 getBinsRect(const Cluster&, const int, const float, const float, float maxdeltaz, float maxdeltaphi); void SetRecoChain(o2::gpu::GPUChainITS* chain, FuncRunITSTrackFit_t&& funcRunITSTrackFit) { @@ -59,7 +59,7 @@ class TrackerTraits virtual void computeLayerTracklets(){}; virtual void computeLayerCells(){}; - virtual void refitTracks(const std::array<std::vector<TrackingFrameInfo>, 7>&, std::vector<TrackITSExt>&){}; + virtual void refitTracks(const std::vector<std::vector<TrackingFrameInfo>>&, std::vector<TrackITSExt>&){}; void UpdateTrackingParameters(const TrackingParameters& trkPar); PrimaryVertexContext* getPrimaryVertexContext() { return mPrimaryVertexContext; } @@ -85,16 +85,17 @@ inline GPU_DEVICE const int4 TrackerTraits::getBinsRect(const Cluster& currentCl const float zRangeMax = gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; - if (zRangeMax < -constants::its::LayersZCoordinate()[layerIndex + 1] || - zRangeMin > constants::its::LayersZCoordinate()[layerIndex + 1] || zRangeMin > zRangeMax) { + if (zRangeMax < -mTrkParams.LayerZ[layerIndex + 1] || + zRangeMin > mTrkParams.LayerZ[layerIndex + 1] || zRangeMin > zRangeMax) { return getEmptyBinsRect(); } - return int4{gpu::GPUCommonMath::Max(0, index_table_utils::getZBinIndex(layerIndex + 1, zRangeMin)), - index_table_utils::getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMin)), - gpu::GPUCommonMath::Min(constants::index_table::ZBins - 1, index_table_utils::getZBinIndex(layerIndex + 1, zRangeMax)), - index_table_utils::getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMax))}; + const IndexTableUtils& utils{mPrimaryVertexContext->mIndexTableUtils}; + return int4{gpu::GPUCommonMath::Max(0, utils.getZBinIndex(layerIndex + 1, zRangeMin)), + utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMin)), + gpu::GPUCommonMath::Min(mTrkParams.ZBins - 1, utils.getZBinIndex(layerIndex + 1, zRangeMax)), + utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMax))}; } } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraitsCPU.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraitsCPU.h index 865ae121abe04..a43fc44b28ef1 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraitsCPU.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraitsCPU.h @@ -44,7 +44,7 @@ class TrackerTraitsCPU : public TrackerTraits void computeLayerCells() final; void computeLayerTracklets() final; - void refitTracks(const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks) final; + void refitTracks(const std::vector<std::vector<TrackingFrameInfo>>& tf, std::vector<TrackITSExt>& tracks) final; protected: std::vector<std::vector<Tracklet>> mTracklets; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index be341b69a39a3..97e1dcde9cf52 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -23,6 +23,7 @@ #include "ITStracking/Configuration.h" #include "ITStracking/ClusterLines.h" #include "ITStracking/Definitions.h" +#include "ITStracking/IndexTableUtils.h" #ifdef _ALLOW_DEBUG_TREES_ITS_ #include "ITStracking/StandaloneDebugger.h" #endif @@ -45,8 +46,6 @@ namespace its class ROframe; -using constants::index_table::PhiBins; -using constants::index_table::ZBins; using constants::its::LayersNumberVertexer; struct lightVertex { @@ -106,8 +105,11 @@ class VertexerTraits { return int4{0, 0, 0, 0}; } - GPUhd() static const int4 getBinsRect(const Cluster&, const int, const float, float maxdeltaz, float maxdeltaphi); - GPUhd() static const int2 getPhiBins(float phi, float deltaPhi); + GPUhd() const int4 getBinsRect(const Cluster&, const int, const float, float maxdeltaz, float maxdeltaphi); + GPUhd() const int2 getPhiBins(float phi, float deltaPhi); + + GPUhd() static const int4 getBinsRect(const Cluster&, const int, const float, float maxdeltaz, float maxdeltaphi, const IndexTableUtils&); + GPUhd() static const int2 getPhiBins(float phi, float deltaPhi, const IndexTableUtils&); // virtual vertexer interface virtual void reset(); @@ -128,8 +130,9 @@ class VertexerTraits void updateVertexingParameters(const VertexingParameters& vrtPar); VertexingParameters getVertexingParameters() const { return mVrtParams; } - static const std::vector<std::pair<int, int>> selectClusters(const std::array<int, ZBins * PhiBins + 1>& indexTable, - const std::array<int, 4>& selectedBinsRect); + static const std::vector<std::pair<int, int>> selectClusters(const int* indexTable, + const std::array<int, 4>& selectedBinsRect, + const IndexTableUtils& utils); std::vector<lightVertex> getVertices() const { return mVertices; } // utils @@ -160,7 +163,8 @@ class VertexerTraits #endif VertexingParameters mVrtParams; - std::array<std::array<int, ZBins * PhiBins + 1>, LayersNumberVertexer> mIndexTables; + IndexTableUtils mIndexTableUtils; + std::array<std::vector<int>, LayersNumberVertexer> mIndexTables; std::vector<lightVertex> mVertices; // Frame related quantities @@ -177,6 +181,9 @@ class VertexerTraits inline void VertexerTraits::initialise(ROframe* event) { reset(); + if (!mIndexTableUtils.getNzBins()) { + updateVertexingParameters(mVrtParams); + } arrangeClusters(event); setIsGPU(false); } @@ -189,32 +196,51 @@ inline void VertexerTraits::setIsGPU(const unsigned char isgpu) inline void VertexerTraits::updateVertexingParameters(const VertexingParameters& vrtPar) { mVrtParams = vrtPar; + mIndexTableUtils.setTrackingParameters(vrtPar); + mVrtParams.phiSpan = static_cast<int>(std::ceil(mIndexTableUtils.getNphiBins() * mVrtParams.phiCut / + constants::math::TwoPi)); + mVrtParams.zSpan = static_cast<int>(std::ceil(mVrtParams.zCut * mIndexTableUtils.getInverseZCoordinate(0))); + for (auto& table : mIndexTables) { + table.resize(mIndexTableUtils.getNphiBins() * mIndexTableUtils.getNzBins() + 1, 0); + } } GPUhdi() const int2 VertexerTraits::getPhiBins(float phi, float dPhi) { - return int2{index_table_utils::getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phi - dPhi)), - index_table_utils::getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phi + dPhi))}; + return VertexerTraits::getPhiBins(phi, dPhi, mIndexTableUtils); +} + +GPUhdi() const int2 VertexerTraits::getPhiBins(float phi, float dPhi, const IndexTableUtils& utils) +{ + return int2{utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phi - dPhi)), + utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phi + dPhi))}; } GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, - const float directionZIntersection, float maxdeltaz, float maxdeltaphi) + const float directionZIntersection, float maxdeltaz, float maxdeltaphi, + const IndexTableUtils& utils) { const float zRangeMin = directionZIntersection - 2 * maxdeltaz; const float phiRangeMin = currentCluster.phiCoordinate - maxdeltaphi; const float zRangeMax = directionZIntersection + 2 * maxdeltaz; const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; - if (zRangeMax < -constants::its::LayersZCoordinate()[layerIndex + 1] || - zRangeMin > constants::its::LayersZCoordinate()[layerIndex + 1] || zRangeMin > zRangeMax) { + if (zRangeMax < -utils.getLayerZ(layerIndex + 1) || + zRangeMin > utils.getLayerZ(layerIndex + 1) || zRangeMin > zRangeMax) { return getEmptyBinsRect(); } - return int4{gpu::GPUCommonMath::Max(0, index_table_utils::getZBinIndex(layerIndex + 1, zRangeMin)), - index_table_utils::getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMin)), - gpu::GPUCommonMath::Min(constants::index_table::ZBins - 1, index_table_utils::getZBinIndex(layerIndex + 1, zRangeMax)), - index_table_utils::getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMax))}; + return int4{gpu::GPUCommonMath::Max(0, utils.getZBinIndex(layerIndex + 1, zRangeMin)), + utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMin)), + gpu::GPUCommonMath::Min(utils.getNzBins() - 1, utils.getZBinIndex(layerIndex + 1, zRangeMax)), + utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMax))}; +} + +GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, + const float directionZIntersection, float maxdeltaz, float maxdeltaphi) +{ + return VertexerTraits::getBinsRect(currentCluster, layerIndex, directionZIntersection, maxdeltaz, maxdeltaphi, mIndexTableUtils); } // debug diff --git a/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx b/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx index ed96496fcfb6e..7f6b4e49d2c79 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx @@ -13,9 +13,8 @@ /// #include "ITStracking/Cluster.h" - -#include "ITStracking/IndexTableUtils.h" #include "ITStracking/MathUtils.h" +#include "ITStracking/IndexTableUtils.h" namespace o2 { @@ -38,21 +37,21 @@ Cluster::Cluster(const float x, const float y, const float z, const int index) // Nothing to do } -Cluster::Cluster(const int layerIndex, const Cluster& other) +Cluster::Cluster(const int layerIndex, const IndexTableUtils& utils, const Cluster& other) : xCoordinate{other.xCoordinate}, yCoordinate{other.yCoordinate}, zCoordinate{other.zCoordinate}, phiCoordinate{getNormalizedPhiCoordinate(calculatePhiCoordinate(other.xCoordinate, other.yCoordinate))}, rCoordinate{calculateRCoordinate(other.xCoordinate, other.yCoordinate)}, clusterId{other.clusterId}, - indexTableBinIndex{index_table_utils::getBinIndex(index_table_utils::getZBinIndex(layerIndex, zCoordinate), - index_table_utils::getPhiBinIndex(phiCoordinate))} + indexTableBinIndex{utils.getBinIndex(utils.getZBinIndex(layerIndex, zCoordinate), + utils.getPhiBinIndex(phiCoordinate))} //, montecarloId{ other.montecarloId } { // Nothing to do } -Cluster::Cluster(const int layerIndex, const float3& primaryVertex, const Cluster& other) +Cluster::Cluster(const int layerIndex, const float3& primaryVertex, const IndexTableUtils& utils, const Cluster& other) : xCoordinate{other.xCoordinate}, yCoordinate{other.yCoordinate}, zCoordinate{other.zCoordinate}, @@ -60,13 +59,13 @@ Cluster::Cluster(const int layerIndex, const float3& primaryVertex, const Cluste calculatePhiCoordinate(xCoordinate - primaryVertex.x, yCoordinate - primaryVertex.y))}, rCoordinate{calculateRCoordinate(xCoordinate - primaryVertex.x, yCoordinate - primaryVertex.y)}, clusterId{other.clusterId}, - indexTableBinIndex{index_table_utils::getBinIndex(index_table_utils::getZBinIndex(layerIndex, zCoordinate), - index_table_utils::getPhiBinIndex(phiCoordinate))} + indexTableBinIndex{utils.getBinIndex(utils.getZBinIndex(layerIndex, zCoordinate), + utils.getPhiBinIndex(phiCoordinate))} { // Nothing to do } -void Cluster::Init(const int layerIndex, const float3& primaryVertex, const Cluster& other) +void Cluster::Init(const int layerIndex, const float3& primaryVertex, const IndexTableUtils& utils, const Cluster& other) { xCoordinate = other.xCoordinate; yCoordinate = other.yCoordinate; @@ -75,8 +74,8 @@ void Cluster::Init(const int layerIndex, const float3& primaryVertex, const Clus calculatePhiCoordinate(xCoordinate - primaryVertex.x, yCoordinate - primaryVertex.y)); rCoordinate = calculateRCoordinate(xCoordinate - primaryVertex.x, yCoordinate - primaryVertex.y); clusterId = other.clusterId; - indexTableBinIndex = index_table_utils::getBinIndex(index_table_utils::getZBinIndex(layerIndex, zCoordinate), - index_table_utils::getPhiBinIndex(phiCoordinate)); + indexTableBinIndex = utils.getBinIndex(utils.getZBinIndex(layerIndex, zCoordinate), + utils.getPhiBinIndex(phiCoordinate)); } TrackingFrameInfo::TrackingFrameInfo(float x, float y, float z, float xTF, float alpha, GPUArray<float, 2>&& posTF, diff --git a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx index f3cecb7c53944..e21d75cf2adb2 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx @@ -38,9 +38,6 @@ constexpr int PrimaryVertexLayerId{-1}; constexpr int EventLabelsSeparator{-1}; } // namespace -using o2::its::constants::its::LayersRCoordinate; -using o2::its::constants::its::LayersZCoordinate; - namespace o2 { namespace its @@ -80,18 +77,6 @@ void ioutils::convertCompactClusters(gsl::span<const itsmft::CompClusterExt> clu } } -void ioutils::loadConfigurations(const std::string& fileName) -{ - if (!fileName.empty()) { - std::ifstream inputStream; - inputStream.open(fileName); - nlohmann::json j; - inputStream >> j; - static_cast<TrackingParameters&>(Configuration<TrackingParameters>::getInstance()) = j.at("TrackingParameters").get<TrackingParameters>(); - //static_cast<IndexTableParameters&>(Configuration<IndexTableParameters>::getInstance()) = j.at("IndexTableParameters").get<IndexTableParameters>(); - } -} - std::vector<ROframe> ioutils::loadEventData(const std::string& fileName) { std::vector<ROframe> events{}; @@ -114,7 +99,7 @@ std::vector<ROframe> ioutils::loadEventData(const std::string& fileName) if (layerId == PrimaryVertexLayerId) { if (clusterId != 0) { - events.emplace_back(events.size()); + events.emplace_back(events.size(), 7); } events.back().addPrimaryVertex(xCoordinate, yCoordinate, zCoordinate); @@ -244,33 +229,33 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g return clusters_in_frame.size(); } -void ioutils::generateSimpleData(ROframe& event, const int phiDivs, const int zDivs = 1) -{ - const float angleOffset = constants::math::TwoPi / static_cast<float>(phiDivs); - // Maximum z allowed on innermost layer should be: ~9,75 - const float zOffsetFirstLayer = (zDivs == 1) ? 0 : 1.5 * (LayersZCoordinate()[6] * LayersRCoordinate()[0]) / (LayersRCoordinate()[6] * (static_cast<float>(zDivs) - 1)); - std::vector<float> x, y; - std::array<std::vector<float>, 7> z; - for (size_t j{0}; j < zDivs; ++j) { - for (size_t i{0}; i < phiDivs; ++i) { - x.emplace_back(cos(i * angleOffset + 0.001)); // put an epsilon to move from periods (e.g. 20 clusters vs 20 cells) - y.emplace_back(sin(i * angleOffset + 0.001)); - const float zFirstLayer{-static_cast<float>((zDivs - 1.) / 2.) * zOffsetFirstLayer + zOffsetFirstLayer * static_cast<float>(j)}; - z[0].emplace_back(zFirstLayer); - for (size_t iLayer{1}; iLayer < constants::its::LayersNumber; ++iLayer) { - z[iLayer].emplace_back(zFirstLayer * LayersRCoordinate()[iLayer] / LayersRCoordinate()[0]); - } - } - } - - for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { - for (int i = 0; i < phiDivs * zDivs; i++) { - o2::MCCompLabel label{i, 0, 0, false}; - event.addClusterLabelToLayer(iLayer, label); //last argument : label, goes into mClustersLabel - event.addClusterToLayer(iLayer, LayersRCoordinate()[iLayer] * x[i], LayersRCoordinate()[iLayer] * y[i], z[iLayer][i], i); //uses 1st constructor for clusters - } - } -} +// void ioutils::generateSimpleData(ROframe& event, const int phiDivs, const int zDivs = 1) +// { +// const float angleOffset = constants::math::TwoPi / static_cast<float>(phiDivs); +// // Maximum z allowed on innermost layer should be: ~9,75 +// const float zOffsetFirstLayer = (zDivs == 1) ? 0 : 1.5 * (LayersZCoordinate()[6] * LayersRCoordinate()[0]) / (LayersRCoordinate()[6] * (static_cast<float>(zDivs) - 1)); +// std::vector<float> x, y; +// std::array<std::vector<float>, 7> z; +// for (size_t j{0}; j < zDivs; ++j) { +// for (size_t i{0}; i < phiDivs; ++i) { +// x.emplace_back(cos(i * angleOffset + 0.001)); // put an epsilon to move from periods (e.g. 20 clusters vs 20 cells) +// y.emplace_back(sin(i * angleOffset + 0.001)); +// const float zFirstLayer{-static_cast<float>((zDivs - 1.) / 2.) * zOffsetFirstLayer + zOffsetFirstLayer * static_cast<float>(j)}; +// z[0].emplace_back(zFirstLayer); +// for (size_t iLayer{1}; iLayer < 7; ++iLayer) { +// z[iLayer].emplace_back(zFirstLayer * LayersRCoordinate()[iLayer] / LayersRCoordinate()[0]); +// } +// } +// } + +// for (int iLayer{0}; iLayer < 7; ++iLayer) { +// for (int i = 0; i < phiDivs * zDivs; i++) { +// o2::MCCompLabel label{i, 0, 0, false}; +// event.addClusterLabelToLayer(iLayer, label); //last argument : label, goes into mClustersLabel +// event.addClusterToLayer(iLayer, LayersRCoordinate()[iLayer] * x[i], LayersRCoordinate()[iLayer] * y[i], z[iLayer][i], i); //uses 1st constructor for clusters +// } +// } +// } std::vector<std::unordered_map<int, Label>> ioutils::loadLabels(const int eventsNum, const std::string& fileName) { @@ -364,70 +349,7 @@ void ioutils::writeRoadsReport(std::ofstream& correctRoadsOutputStream, std::ofs } } -void to_json(nlohmann::json& j, const TrackingParameters& par) -{ - std::array<float, constants::its::TrackletsPerRoad> tmpTrackletMaxDeltaZ; - std::copy(par.TrackletMaxDeltaZ, par.TrackletMaxDeltaZ + tmpTrackletMaxDeltaZ.size(), tmpTrackletMaxDeltaZ.begin()); - std::array<float, constants::its::CellsPerRoad> tmpCellMaxDCA; - std::copy(par.CellMaxDCA, par.CellMaxDCA + tmpCellMaxDCA.size(), tmpCellMaxDCA.begin()); - std::array<float, constants::its::CellsPerRoad> tmpCellMaxDeltaZ; - std::copy(par.CellMaxDeltaZ, par.CellMaxDeltaZ + tmpCellMaxDeltaZ.size(), tmpCellMaxDeltaZ.begin()); - std::array<float, constants::its::CellsPerRoad - 1> tmpNeighbourMaxDeltaCurvature; - std::copy(par.NeighbourMaxDeltaCurvature, par.NeighbourMaxDeltaCurvature + tmpNeighbourMaxDeltaCurvature.size(), tmpNeighbourMaxDeltaCurvature.begin()); - std::array<float, constants::its::CellsPerRoad - 1> tmpNeighbourMaxDeltaN; - std::copy(par.NeighbourMaxDeltaN, par.NeighbourMaxDeltaN + tmpNeighbourMaxDeltaN.size(), tmpNeighbourMaxDeltaN.begin()); - j = nlohmann::json{ - {"ClusterSharing", par.ClusterSharing}, - {"MinTrackLength", par.MinTrackLength}, - {"TrackletMaxDeltaPhi", par.TrackletMaxDeltaPhi}, - {"TrackletMaxDeltaZ", tmpTrackletMaxDeltaZ}, - {"CellMaxDeltaTanLambda", par.CellMaxDeltaTanLambda}, - {"CellMaxDCA", tmpCellMaxDCA}, - {"CellMaxDeltaPhi", par.CellMaxDeltaPhi}, - {"CellMaxDeltaZ", tmpCellMaxDeltaZ}, - {"NeighbourMaxDeltaCurvature", tmpNeighbourMaxDeltaCurvature}, - {"NeighbourMaxDeltaN", tmpNeighbourMaxDeltaN}}; -} - -void from_json(const nlohmann::json& j, TrackingParameters& par) -{ - par.ClusterSharing = j.at("ClusterSharing").get<int>(); - par.MinTrackLength = j.at("MinTrackLength").get<int>(); - par.TrackletMaxDeltaPhi = j.at("TrackletMaxDeltaPhi").get<float>(); - par.CellMaxDeltaTanLambda = j.at("CellMaxDeltaTanLambda").get<float>(); - par.CellMaxDeltaPhi = j.at("CellMaxDeltaPhi").get<float>(); - auto tmpTrackletMaxDeltaZ = j.at("TrackletMaxDeltaZ").get<std::array<float, constants::its::TrackletsPerRoad>>(); - std::copy(tmpTrackletMaxDeltaZ.begin(), tmpTrackletMaxDeltaZ.end(), par.TrackletMaxDeltaZ); - auto tmpCellMaxDCA = j.at("CellMaxDCA").get<std::array<float, constants::its::CellsPerRoad>>(); - std::copy(tmpCellMaxDCA.begin(), tmpCellMaxDCA.end(), par.CellMaxDCA); - auto tmpCellMaxDeltaZ = j.at("CellMaxDeltaZ").get<std::array<float, constants::its::CellsPerRoad>>(); - std::copy(tmpCellMaxDCA.begin(), tmpCellMaxDeltaZ.end(), par.CellMaxDeltaZ); - auto tmpNeighbourMaxDeltaCurvature = j.at("NeighbourMaxDeltaCurvature").get<std::array<float, constants::its::CellsPerRoad - 1>>(); - std::copy(tmpNeighbourMaxDeltaCurvature.begin(), tmpNeighbourMaxDeltaCurvature.end(), par.NeighbourMaxDeltaCurvature); - auto tmpNeighbourMaxDeltaN = j.at("NeighbourMaxDeltaN").get<std::array<float, constants::its::CellsPerRoad - 1>>(); - std::copy(tmpNeighbourMaxDeltaN.begin(), tmpNeighbourMaxDeltaN.end(), par.NeighbourMaxDeltaN); -} -void to_json(nlohmann::json& j, const MemoryParameters& par) -{ - std::array<float, constants::its::CellsPerRoad> tmpCellsMemoryCoefficients; - std::copy(par.CellsMemoryCoefficients, par.CellsMemoryCoefficients + tmpCellsMemoryCoefficients.size(), tmpCellsMemoryCoefficients.begin()); - std::array<float, constants::its::TrackletsPerRoad> tmpTrackletsMemoryCoefficients; - std::copy(par.TrackletsMemoryCoefficients, par.TrackletsMemoryCoefficients + tmpTrackletsMemoryCoefficients.size(), tmpTrackletsMemoryCoefficients.begin()); - j = nlohmann::json{ - {"MemoryOffset", par.MemoryOffset}, - {"CellsMemoryCoefficients", tmpCellsMemoryCoefficients}, - {"TrackletsMemoryCoefficients", tmpTrackletsMemoryCoefficients}}; -} - -void from_json(const nlohmann::json& j, MemoryParameters& par) -{ - par.MemoryOffset = j.at("MemoryOffset").get<int>(); - auto tmpCellsMemoryCoefficients = j.at("CellsMemoryCoefficients").get<std::array<float, constants::its::CellsPerRoad>>(); - std::copy(tmpCellsMemoryCoefficients.begin(), tmpCellsMemoryCoefficients.end(), par.CellsMemoryCoefficients); - auto tmpTrackletsMemoryCoefficients = j.at("TrackletsMemoryCoefficients").get<std::array<float, constants::its::TrackletsPerRoad>>(); - std::copy(tmpTrackletsMemoryCoefficients.begin(), tmpTrackletsMemoryCoefficients.end(), par.TrackletsMemoryCoefficients); -} } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx index d4dcbe5f36fc9..c984d560588ac 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx @@ -21,8 +21,8 @@ namespace o2 namespace its { -void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its::LayersNumber>& cl, - const std::array<float, 3>& pVtx, const int iteration) +void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const TrackingParameters& trkParam, + const std::vector<std::vector<Cluster>>& cl, const std::array<float, 3>& pVtx, const int iteration) { struct ClusterHelper { @@ -38,7 +38,20 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st std::vector<ClusterHelper> cHelper; - for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { + mMinR.resize(trkParam.NLayers, 10000.); + mMaxR.resize(trkParam.NLayers, -1.); + mClusters.resize(trkParam.NLayers); + mUsedClusters.resize(trkParam.NLayers); + mCells.resize(trkParam.CellsPerRoad()); + mCellsLookupTable.resize(trkParam.CellsPerRoad() - 1); + mCellsNeighbours.resize(trkParam.CellsPerRoad() - 1); + mIndexTables.resize(trkParam.TrackletsPerRoad(), std::vector<int>(trkParam.ZBins * trkParam.PhiBins + 1, 0)); + mTracklets.resize(trkParam.TrackletsPerRoad()); + mTrackletsLookupTable.resize(trkParam.CellsPerRoad()); + mIndexTableUtils.setTrackingParameters(trkParam); + + std::vector<int> clsPerBin(trkParam.PhiBins * trkParam.ZBins, 0); + for (unsigned int iLayer{0}; iLayer < mClusters.size(); ++iLayer) { const auto& currentLayer{cl[iLayer]}; const int clustersNum{static_cast<int>(currentLayer.size())}; @@ -48,11 +61,7 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st mUsedClusters[iLayer].clear(); mUsedClusters[iLayer].resize(clustersNum, false); - constexpr int _size = constants::index_table::PhiBins * constants::index_table::ZBins; - std::array<int, _size> clsPerBin; - for (int iB{0}; iB < _size; ++iB) { - clsPerBin[iB] = 0; - } + std::fill(clsPerBin.begin(), clsPerBin.end(), 0); cHelper.clear(); cHelper.resize(clustersNum); @@ -66,8 +75,9 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st float x = c.xCoordinate - mPrimaryVertex.x; float y = c.yCoordinate - mPrimaryVertex.y; float phi = math_utils::calculatePhiCoordinate(x, y); - int bin = index_table_utils::getBinIndex(index_table_utils::getZBinIndex(iLayer, c.zCoordinate), - index_table_utils::getPhiBinIndex(phi)); + const int zBin{mIndexTableUtils.getZBinIndex(iLayer, c.zCoordinate)}; + int bin = mIndexTableUtils.getBinIndex(zBin, mIndexTableUtils.getPhiBinIndex(phi)); + CA_DEBUGGER(assert(zBin > 0)); h.phi = phi; h.r = math_utils::calculateRCoordinate(x, y); mMinR[iLayer] = gpu::GPUCommonMath::Min(h.r, mMinR[iLayer]); @@ -76,9 +86,9 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st h.ind = clsPerBin[bin]++; } - std::array<int, _size> lutPerBin; + std::vector<int> lutPerBin(clsPerBin.size()); lutPerBin[0] = 0; - for (int iB{1}; iB < _size; ++iB) { + for (unsigned int iB{1}; iB < lutPerBin.size(); ++iB) { lutPerBin[iB] = lutPerBin[iB - 1] + clsPerBin[iB - 1]; } @@ -92,10 +102,10 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st } if (iLayer > 0) { - for (int iB{0}; iB < _size; ++iB) { + for (unsigned int iB{0}; iB < clsPerBin.size(); ++iB) { mIndexTables[iLayer - 1][iB] = lutPerBin[iB]; } - for (int iB{_size}; iB < (int)mIndexTables[iLayer - 1].size(); iB++) { + for (auto iB{clsPerBin.size()}; iB < (int)mIndexTables[iLayer - 1].size(); iB++) { mIndexTables[iLayer - 1][iB] = clustersNum; } } @@ -104,8 +114,8 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st mRoads.clear(); - for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { - if (iLayer < constants::its::CellsPerRoad) { + for (unsigned int iLayer{0}; iLayer < mClusters.size(); ++iLayer) { + if (iLayer < mCells.size()) { mCells[iLayer].clear(); float cellsMemorySize = memParam.MemoryOffset + @@ -118,32 +128,32 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const st } } - if (iLayer < constants::its::CellsPerRoad - 1) { + if (iLayer < mCells.size() - 1) { mCellsLookupTable[iLayer].clear(); - mCellsLookupTable[iLayer].resize( - std::max(cl[iLayer + 1].size(), cl[iLayer + 2].size()) + - std::ceil((memParam.TrackletsMemoryCoefficients[iLayer + 1] * - cl[iLayer + 1].size()) * - cl[iLayer + 2].size()), - constants::its::UnusedIndex); + mCellsLookupTable[iLayer].resize(memParam.MemoryOffset + + std::max(cl[iLayer + 1].size(), cl[iLayer + 2].size()) + + std::ceil((memParam.TrackletsMemoryCoefficients[iLayer + 1] * + cl[iLayer + 1].size()) * + cl[iLayer + 2].size()), + constants::its::UnusedIndex); mCellsNeighbours[iLayer].clear(); } } - for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { - if (iLayer < constants::its::TrackletsPerRoad) { + for (unsigned int iLayer{0}; iLayer < mClusters.size(); ++iLayer) { + if (iLayer < mTracklets.size()) { mTracklets[iLayer].clear(); - float trackletsMemorySize = - std::max(cl[iLayer].size(), cl[iLayer + 1].size()) + - std::ceil((memParam.TrackletsMemoryCoefficients[iLayer] * cl[iLayer].size()) * - cl[iLayer + 1].size()); + float trackletsMemorySize = memParam.MemoryOffset + + std::max(cl[iLayer].size(), cl[iLayer + 1].size()) + + std::ceil((memParam.TrackletsMemoryCoefficients[iLayer] * cl[iLayer].size()) * + cl[iLayer + 1].size()); if (trackletsMemorySize > mTracklets[iLayer].capacity()) { mTracklets[iLayer].reserve(trackletsMemorySize); } } - if (iLayer < constants::its::CellsPerRoad) { + if (iLayer < mCells.size()) { mTrackletsLookupTable[iLayer].clear(); mTrackletsLookupTable[iLayer].resize(cl[iLayer + 1].size(), constants::its::UnusedIndex); } diff --git a/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx b/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx index e4375d1caafb9..76ba90171c3cf 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx @@ -21,8 +21,12 @@ namespace o2 namespace its { -ROframe::ROframe(const int ROframeId) : mROframeId{ROframeId} +ROframe::ROframe(int ROframeId, int nLayers) : mROframeId{ROframeId} { + mClusters.resize(nLayers); + mTrackingFrameInfo.resize(nLayers); + mClusterLabels.resize(nLayers); + mClusterExternalIndices.resize(nLayers); } void ROframe::addPrimaryVertex(const float xCoordinate, const float yCoordinate, const float zCoordinate) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Road.cxx b/Detectors/ITSMFT/ITS/tracking/src/Road.cxx index da5748bbcd75a..facb1f43fa1e2 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Road.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Road.cxx @@ -13,6 +13,8 @@ /// #include "ITStracking/Road.h" +#include <cassert> +#include <iostream> namespace o2 { @@ -25,7 +27,7 @@ Road::Road(int cellLayer, int cellId) : Road() { addCell(cellLayer, cellId); } void Road::resetRoad() { - for (int i = 0; i < constants::its::CellsPerRoad; i++) { + for (int i = 0; i < mMaxRoadSize; i++) { mCellIds[i] = constants::its::UnusedIndex; } mRoadSize = 0; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 1aa9483d6f84b..721fa617051b5 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -57,12 +57,21 @@ void Tracker::clustersToTracks(const ROframe& event, std::ostream& timeBenchmark float total{0.f}; for (int iteration = 0; iteration < mTrkParams.size(); ++iteration) { + + int numCls = 0; + for (unsigned int iLayer{0}; iLayer < mTrkParams[iteration].NLayers; ++iLayer) { + numCls += event.getClusters()[iLayer].size(); + } + if (numCls < mTrkParams[iteration].MinTrackLength) { + continue; + } + mTraits->UpdateTrackingParameters(mTrkParams[iteration]); /// Ugly hack -> Unifiy float3 definition in CPU and CUDA/HIP code int pass = iteration + iVertex; /// Do not reinitialise the context if we analyse pile-up events std::array<float, 3> pV = {event.getPrimaryVertex(iVertex).x, event.getPrimaryVertex(iVertex).y, event.getPrimaryVertex(iVertex).z}; total += evaluateTask(&Tracker::initialisePrimaryVertexContext, "Context initialisation", - timeBenchmarkOutputStream, mMemParams[iteration], event.getClusters(), pV, pass); + timeBenchmarkOutputStream, mMemParams[iteration], mTrkParams[iteration], event.getClusters(), pV, pass); total += evaluateTask(&Tracker::computeTracklets, "Tracklet finding", timeBenchmarkOutputStream); total += evaluateTask(&Tracker::computeCells, "Cell finding", timeBenchmarkOutputStream); total += evaluateTask(&Tracker::findCellsNeighbours, "Neighbour finding", timeBenchmarkOutputStream, iteration); @@ -93,7 +102,7 @@ void Tracker::computeCells() void Tracker::findCellsNeighbours(int& iteration) { - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad - 1; ++iLayer) { + for (int iLayer{0}; iLayer < mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) { if (mPrimaryVertexContext->getCells()[iLayer + 1].empty() || mPrimaryVertexContext->getCellsLookupTable()[iLayer].empty()) { @@ -101,6 +110,8 @@ void Tracker::findCellsNeighbours(int& iteration) } int layerCellsNum{static_cast<int>(mPrimaryVertexContext->getCells()[iLayer].size())}; + const int nextLayerCellsNum{static_cast<int>(mPrimaryVertexContext->getCells()[iLayer + 1].size())}; + mPrimaryVertexContext->getCellsNeighbours()[iLayer].resize(nextLayerCellsNum); for (int iCell{0}; iCell < layerCellsNum; ++iCell) { @@ -111,16 +122,13 @@ void Tracker::findCellsNeighbours(int& iteration) mPrimaryVertexContext->getCells()[iLayer + 1][nextLayerFirstCellIndex].getFirstTrackletIndex() == nextLayerTrackletIndex) { - const int nextLayerCellsNum{static_cast<int>(mPrimaryVertexContext->getCells()[iLayer + 1].size())}; - mPrimaryVertexContext->getCellsNeighbours()[iLayer].resize(nextLayerCellsNum); - - for (int iNextLayerCell{nextLayerFirstCellIndex}; - iNextLayerCell < nextLayerCellsNum && - mPrimaryVertexContext->getCells()[iLayer + 1][iNextLayerCell].getFirstTrackletIndex() == - nextLayerTrackletIndex; - ++iNextLayerCell) { + for (int iNextLayerCell{nextLayerFirstCellIndex}; iNextLayerCell < nextLayerCellsNum; ++iNextLayerCell) { Cell& nextCell{mPrimaryVertexContext->getCells()[iLayer + 1][iNextLayerCell]}; + if (nextCell.getFirstTrackletIndex() != nextLayerTrackletIndex) { + break; + } + const float3 currentCellNormalVector{currentCell.getNormalVectorCoordinates()}; const float3 nextCellNormalVector{nextCell.getNormalVectorCoordinates()}; const float3 normalVectorsDeltaVector{currentCellNormalVector.x - nextCellNormalVector.x, @@ -152,11 +160,11 @@ void Tracker::findCellsNeighbours(int& iteration) void Tracker::findRoads(int& iteration) { - for (int iLevel{constants::its::CellsPerRoad}; iLevel >= mTrkParams[iteration].CellMinimumLevel(); --iLevel) { + for (int iLevel{mTrkParams[iteration].CellsPerRoad()}; iLevel >= mTrkParams[iteration].CellMinimumLevel(); --iLevel) { CA_DEBUGGER(int nRoads = -mPrimaryVertexContext->getRoads().size()); const int minimumLevel{iLevel - 1}; - for (int iLayer{constants::its::CellsPerRoad - 1}; iLayer >= minimumLevel; --iLayer) { + for (int iLayer{mTrkParams[iteration].CellsPerRoad() - 1}; iLayer >= minimumLevel; --iLayer) { const int levelCellsNum{static_cast<int>(mPrimaryVertexContext->getCells()[iLayer].size())}; @@ -218,19 +226,19 @@ void Tracker::findTracks(const ROframe& event) std::vector<TrackITSExt> tracks; tracks.reserve(mPrimaryVertexContext->getRoads().size()); #ifdef CA_DEBUG - std::array<int, 4> roadCounters{0, 0, 0, 0}; - std::array<int, 4> fitCounters{0, 0, 0, 0}; - std::array<int, 4> backpropagatedCounters{0, 0, 0, 0}; - std::array<int, 4> refitCounters{0, 0, 0, 0}; - std::array<int, 4> nonsharingCounters{0, 0, 0, 0}; + std::vector<int> roadCounters(mTrkParams[0].NLayers - 3, 0); + std::vector<int> fitCounters(mTrkParams[0].NLayers - 3, 0); + std::vector<int> backpropagatedCounters(mTrkParams[0].NLayers - 3, 0); + std::vector<int> refitCounters(mTrkParams[0].NLayers - 3, 0); + std::vector<int> nonsharingCounters(mTrkParams[0].NLayers - 3, 0); #endif for (auto& road : mPrimaryVertexContext->getRoads()) { - std::array<int, 7> clusters{constants::its::UnusedIndex, constants::its::UnusedIndex, constants::its::UnusedIndex, constants::its::UnusedIndex, constants::its::UnusedIndex, constants::its::UnusedIndex, constants::its::UnusedIndex}; + std::vector<int> clusters(mTrkParams[0].NLayers, constants::its::UnusedIndex); int lastCellLevel = constants::its::UnusedIndex; CA_DEBUGGER(int nClusters = 2); - for (int iCell{0}; iCell < constants::its::CellsPerRoad; ++iCell) { + for (int iCell{0}; iCell < mTrkParams[0].CellsPerRoad(); ++iCell) { const int cellIndex = road[iCell]; if (cellIndex == constants::its::UnusedIndex) { continue; @@ -271,20 +279,20 @@ void Tracker::findTracks(const ROframe& event) for (size_t iC = 0; iC < clusters.size(); ++iC) { temporaryTrack.setExternalClusterIndex(iC, clusters[iC], clusters[iC] != constants::its::UnusedIndex); } - bool fitSuccess = fitTrack(event, temporaryTrack, constants::its::LayersNumber - 4, -1, -1); + bool fitSuccess = fitTrack(event, temporaryTrack, mTrkParams[0].NLayers - 4, -1, -1); if (!fitSuccess) { continue; } CA_DEBUGGER(fitCounters[nClusters - 4]++); temporaryTrack.resetCovariance(); - fitSuccess = fitTrack(event, temporaryTrack, 0, constants::its::LayersNumber, 1); + fitSuccess = fitTrack(event, temporaryTrack, 0, mTrkParams[0].NLayers, 1); if (!fitSuccess) { continue; } CA_DEBUGGER(backpropagatedCounters[nClusters - 4]++); temporaryTrack.getParamOut() = temporaryTrack; temporaryTrack.resetCovariance(); - fitSuccess = fitTrack(event, temporaryTrack, constants::its::LayersNumber - 1, -1, -1); + fitSuccess = fitTrack(event, temporaryTrack, mTrkParams[0].NLayers - 1, -1, -1); if (!fitSuccess) { continue; } @@ -298,19 +306,19 @@ void Tracker::findTracks(const ROframe& event) [](TrackITSExt& track1, TrackITSExt& track2) { return track1.isBetter(track2, 1.e6f); }); #ifdef CA_DEBUG - std::array<int, 26> sharingMatrix{0}; - int prevNclusters = 7; - auto cumulativeIndex = [](int ncl) -> int { - constexpr int idx[5] = {0, 5, 11, 18, 26}; - return idx[ncl - 4]; - }; - std::array<int, 4> xcheckCounters{0}; + // std::array<int, 26> sharingMatrix{0}; + // int prevNclusters = 7; + // auto cumulativeIndex = [](int ncl) -> int { + // constexpr int idx[5] = {0, 5, 11, 18, 26}; + // return idx[ncl - 4]; + // }; + // std::array<int, 4> xcheckCounters{0}; #endif for (auto& track : tracks) { CA_DEBUGGER(int nClusters = 0); int nShared = 0; - for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { + for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { if (track.getClusterIndex(iLayer) == constants::its::UnusedIndex) { continue; } @@ -318,24 +326,24 @@ void Tracker::findTracks(const ROframe& event) CA_DEBUGGER(nClusters++); } -#ifdef CA_DEBUG - assert(nClusters == track.getNumberOfClusters()); - xcheckCounters[nClusters - 4]++; - assert(nShared <= nClusters); - sharingMatrix[cumulativeIndex(nClusters) + nShared]++; -#endif + // #ifdef CA_DEBUG + // assert(nClusters == track.getNumberOfClusters()); + // xcheckCounters[nClusters - 4]++; + // assert(nShared <= nClusters); + // sharingMatrix[cumulativeIndex(nClusters) + nShared]++; + // #endif if (nShared > mTrkParams[0].ClusterSharing) { continue; } -#ifdef CA_DEBUG - nonsharingCounters[nClusters - 4]++; - assert(nClusters <= prevNclusters); - prevNclusters = nClusters; -#endif + // #ifdef CA_DEBUG + // nonsharingCounters[nClusters - 4]++; + // assert(nClusters <= prevNclusters); + // prevNclusters = nClusters; + // #endif - for (int iLayer{0}; iLayer < constants::its::LayersNumber; ++iLayer) { + for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { if (track.getClusterIndex(iLayer) == constants::its::UnusedIndex) { continue; } @@ -365,26 +373,26 @@ void Tracker::findTracks(const ROframe& event) std::cout << count << "\t"; std::cout << std::endl; - std::cout << "+++ Cross check counters for 4, 5, 6 and 7 clusters:\t"; - for (size_t iCount = 0; iCount < refitCounters.size(); ++iCount) { - std::cout << xcheckCounters[iCount] << "\t"; - //assert(refitCounters[iCount] == xcheckCounters[iCount]); - } - std::cout << std::endl; - - std::cout << "+++ Nonsharing candidates with 4, 5, 6 and 7 clusters:\t"; - for (int count : nonsharingCounters) - std::cout << count << "\t"; - std::cout << std::endl; - - std::cout << "+++ Sharing matrix:\n"; - for (int iCl = 4; iCl <= 7; ++iCl) { - std::cout << "+++ "; - for (int iSh = cumulativeIndex(iCl); iSh < cumulativeIndex(iCl + 1); ++iSh) { - std::cout << sharingMatrix[iSh] << "\t"; - } - std::cout << std::endl; - } + // std::cout << "+++ Cross check counters for 4, 5, 6 and 7 clusters:\t"; + // for (size_t iCount = 0; iCount < refitCounters.size(); ++iCount) { + // std::cout << xcheckCounters[iCount] << "\t"; + // //assert(refitCounters[iCount] == xcheckCounters[iCount]); + // } + // std::cout << std::endl; + + // std::cout << "+++ Nonsharing candidates with 4, 5, 6 and 7 clusters:\t"; + // for (int count : nonsharingCounters) + // std::cout << count << "\t"; + // std::cout << std::endl; + + // std::cout << "+++ Sharing matrix:\n"; + // for (int iCl = 4; iCl <= 7; ++iCl) { + // std::cout << "+++ "; + // for (int iSh = cumulativeIndex(iCl); iSh < cumulativeIndex(iCl + 1); ++iSh) { + // std::cout << sharingMatrix[iSh] << "\t"; + // } + // std::cout << std::endl; + // } #endif } @@ -477,7 +485,7 @@ void Tracker::computeRoadsMClabels(const ROframe& event) bool isFakeRoad{false}; bool isFirstRoadCell{true}; - for (int iCell{0}; iCell < constants::its::CellsPerRoad; ++iCell) { + for (int iCell{0}; iCell < mTrkParams[0].CellsPerRoad(); ++iCell) { const int currentCellIndex{currentRoad[iCell]}; if (currentCellIndex == constants::its::UnusedIndex) { @@ -554,7 +562,6 @@ void Tracker::computeTracksMClabels(const ROframe& event) if (index == constants::its::UnusedIndex) { continue; } - const MCCompLabel& currentLabel = event.getClusterLabels(iCluster, index); if (currentLabel == maxOccurrencesValue) { ++count; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx index 5925a66c7a204..b8c7299134bcf 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx @@ -34,9 +34,9 @@ namespace its void TrackerTraitsCPU::computeLayerTracklets() { PrimaryVertexContext* primaryVertexContext = mPrimaryVertexContext; - for (int iLayer{0}; iLayer < constants::its::TrackletsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < mTrkParams.TrackletsPerRoad(); ++iLayer) { if (primaryVertexContext->getClusters()[iLayer].empty() || primaryVertexContext->getClusters()[iLayer + 1].empty()) { - return; + continue; } const float3& primaryVertex = primaryVertexContext->getPrimaryVertex(); @@ -67,12 +67,12 @@ void TrackerTraitsCPU::computeLayerTracklets() int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; if (phiBinsNum < 0) { - phiBinsNum += constants::index_table::PhiBins; + phiBinsNum += mTrkParams.PhiBins; } for (int iPhiBin{selectedBinsRect.y}, iPhiCount{0}; iPhiCount < phiBinsNum; - iPhiBin = ++iPhiBin == constants::index_table::PhiBins ? 0 : iPhiBin, iPhiCount++) { - const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect.x, iPhiBin)}; + iPhiBin = ++iPhiBin == mTrkParams.PhiBins ? 0 : iPhiBin, iPhiCount++) { + const int firstBinIndex{primaryVertexContext->mIndexTableUtils.getBinIndex(selectedBinsRect.x, iPhiBin)}; const int maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1}; const int firstRowClusterIndex = primaryVertexContext->getIndexTables()[iLayer][firstBinIndex]; const int maxRowClusterIndex = primaryVertexContext->getIndexTables()[iLayer][maxBinIndex]; @@ -80,6 +80,10 @@ void TrackerTraitsCPU::computeLayerTracklets() for (int iNextLayerCluster{firstRowClusterIndex}; iNextLayerCluster < maxRowClusterIndex; ++iNextLayerCluster) { + if (iNextLayerCluster >= primaryVertexContext->getClusters()[iLayer + 1].size()) { + break; + } + const Cluster& nextCluster{primaryVertexContext->getClusters()[iLayer + 1][iNextLayerCluster]}; if (primaryVertexContext->isClusterUsed(iLayer + 1, nextCluster.clusterId)) { @@ -107,13 +111,25 @@ void TrackerTraitsCPU::computeLayerTracklets() } } } + if (iLayer > 0 && iLayer < mTrkParams.TrackletsPerRoad() - 1 && + primaryVertexContext->getTracklets()[iLayer].size() > primaryVertexContext->getCellsLookupTable()[iLayer - 1].size()) { + std::cout << "**** FATAL: not enough memory in the CellsLookupTable, increase the tracklet memory coefficients ****" << std::endl; + exit(1); + } + } +#ifdef CA_DEBUG + std::cout << "+++ Number of tracklets per layer: "; + for (int iLayer{0}; iLayer < mTrkParams.TrackletsPerRoad(); ++iLayer) { + std::cout << primaryVertexContext->getTracklets()[iLayer].size() << "\t"; } + std::cout << std::endl; +#endif } void TrackerTraitsCPU::computeLayerCells() { PrimaryVertexContext* primaryVertexContext = mPrimaryVertexContext; - for (int iLayer{0}; iLayer < constants::its::CellsPerRoad; ++iLayer) { + for (int iLayer{0}; iLayer < mTrkParams.CellsPerRoad(); ++iLayer) { if (primaryVertexContext->getTracklets()[iLayer + 1].empty() || primaryVertexContext->getTracklets()[iLayer].empty()) { @@ -229,17 +245,24 @@ void TrackerTraitsCPU::computeLayerCells() } } } +#ifdef CA_DEBUG + std::cout << "+++ Number of cells per layer: "; + for (int iLayer{0}; iLayer < mTrkParams.CellsPerRoad(); ++iLayer) { + std::cout << primaryVertexContext->getCells()[iLayer].size() << "\t"; + } + std::cout << std::endl; +#endif } -void TrackerTraitsCPU::refitTracks(const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks) +void TrackerTraitsCPU::refitTracks(const std::vector<std::vector<TrackingFrameInfo>>& tf, std::vector<TrackITSExt>& tracks) { - std::array<const Cell*, 5> cells; - for (int iLayer = 0; iLayer < 5; iLayer++) { - cells[iLayer] = mPrimaryVertexContext->getCells()[iLayer].data(); + std::vector<const Cell*> cells; + for (int iLayer = 0; iLayer < mTrkParams.CellsPerRoad(); iLayer++) { + cells.push_back(mPrimaryVertexContext->getCells()[iLayer].data()); } - std::array<const Cluster*, 7> clusters; - for (int iLayer = 0; iLayer < 7; iLayer++) { - clusters[iLayer] = mPrimaryVertexContext->getClusters()[iLayer].data(); + std::vector<const Cluster*> clusters; + for (int iLayer = 0; iLayer < mTrkParams.NLayers; iLayer++) { + clusters.push_back(mPrimaryVertexContext->getClusters()[iLayer].data()); } mChainRunITSTrackFit(*mChain, mPrimaryVertexContext->getRoads(), clusters, cells, tf, tracks); } diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index b5b843f33e24e..b407d2059acaf 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -37,31 +37,30 @@ namespace o2 namespace its { using boost::histogram::indexed; -using constants::index_table::PhiBins; -using constants::index_table::ZBins; -using constants::its::LayersRCoordinate; -using constants::its::LayersZCoordinate; using constants::math::TwoPi; -using index_table_utils::getZBinIndex; void trackleterKernelSerial( const std::vector<Cluster>& clustersNextLayer, // 0 2 const std::vector<Cluster>& clustersCurrentLayer, // 1 1 - const std::array<int, ZBins * PhiBins + 1>& indexTableNext, + const int* indexTableNext, const unsigned char pairOfLayers, const float phiCut, std::vector<Tracklet>& Tracklets, std::vector<int>& foundTracklets, + const IndexTableUtils& utils, // const ROframe* evt = nullptr, const int maxTrackletsPerCluster = static_cast<int>(2e3)) { + const int PhiBins{utils.getNphiBins()}; + const int ZBins{utils.getNzBins()}; + foundTracklets.resize(clustersCurrentLayer.size(), 0); // loop on layer1 clusters for (unsigned int iCurrentLayerClusterIndex{0}; iCurrentLayerClusterIndex < clustersCurrentLayer.size(); ++iCurrentLayerClusterIndex) { int storedTracklets{0}; const Cluster currentCluster{clustersCurrentLayer[iCurrentLayerClusterIndex]}; const int layerIndex{pairOfLayers == LAYER0_TO_LAYER1 ? 0 : 2}; - const int4 selectedBinsRect{VertexerTraits::getBinsRect(currentCluster, layerIndex, 0.f, 50.f, phiCut / 2)}; + const int4 selectedBinsRect{VertexerTraits::getBinsRect(currentCluster, layerIndex, 0.f, 50.f, phiCut / 2, utils)}; if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) { int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; if (phiBinsNum < 0) { @@ -69,7 +68,7 @@ void trackleterKernelSerial( } // loop on phi bins next layer for (int iPhiBin{selectedBinsRect.y}, iPhiCount{0}; iPhiCount < phiBinsNum; iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) { - const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect.x, iPhiBin)}; + const int firstBinIndex{utils.getBinIndex(selectedBinsRect.x, iPhiBin)}; const int firstRowClusterIndex{indexTableNext[firstBinIndex]}; const int maxRowClusterIndex{indexTableNext[firstBinIndex + ZBins]}; // loop on clusters next layer @@ -150,9 +149,6 @@ VertexerTraits::VertexerTraits() : mAverageClustersRadii{std::array<float, 3>{0. VertexerTraits::VertexerTraits() : mAverageClustersRadii{std::array<float, 3>{0.f, 0.f, 0.f}}, mMaxDirectorCosine3{0.f} { - mVrtParams.phiSpan = static_cast<int>(std::ceil(constants::index_table::PhiBins * mVrtParams.phiCut / - constants::math::TwoPi)); - mVrtParams.zSpan = static_cast<int>(std::ceil(mVrtParams.zCut * constants::index_table::InverseZBinSize()[0])); } #endif @@ -169,7 +165,7 @@ void VertexerTraits::reset() { for (int iLayer{0}; iLayer < constants::its::LayersNumberVertexer; ++iLayer) { mClusters[iLayer].clear(); - mIndexTables[iLayer].fill(0); + std::fill(mIndexTables[iLayer].begin(), mIndexTables[iLayer].end(), 0); } mTracklets.clear(); @@ -193,6 +189,7 @@ std::vector<int> VertexerTraits::getMClabelsLayer(const int layer) const void VertexerTraits::arrangeClusters(ROframe* event) { + const auto& LayersZCoordinate = mVrtParams.LayerZ; mEvent = event; for (int iLayer{0}; iLayer < constants::its::LayersNumberVertexer; ++iLayer) { const auto& currentLayer{event->getClustersOnLayer(iLayer)}; @@ -202,7 +199,7 @@ void VertexerTraits::arrangeClusters(ROframe* event) mClusters[iLayer].reserve(clustersNum); } for (unsigned int iCluster{0}; iCluster < clustersNum; ++iCluster) { - mClusters[iLayer].emplace_back(iLayer, currentLayer.at(iCluster)); + mClusters[iLayer].emplace_back(iLayer, mIndexTableUtils, currentLayer.at(iCluster)); mAverageClustersRadii[iLayer] += mClusters[iLayer].back().rCoordinate; } mAverageClustersRadii[iLayer] *= 1.f / clustersNum; @@ -221,7 +218,7 @@ void VertexerTraits::arrangeClusters(ROframe* event) previousBinIndex = currentBinIndex; } } - for (int iBin{previousBinIndex + 1}; iBin <= ZBins * PhiBins; iBin++) { + for (int iBin{previousBinIndex + 1}; iBin <= mIndexTableUtils.getNzBins() * mIndexTableUtils.getNphiBins(); iBin++) { mIndexTables[iLayer][iBin] = static_cast<int>(clustersNum); } } @@ -229,25 +226,25 @@ void VertexerTraits::arrangeClusters(ROframe* event) mDeltaRadii10 = mAverageClustersRadii[1] - mAverageClustersRadii[0]; mDeltaRadii21 = mAverageClustersRadii[2] - mAverageClustersRadii[1]; mMaxDirectorCosine3 = - LayersZCoordinate()[2] / std::sqrt(LayersZCoordinate()[2] * LayersZCoordinate()[2] + - (mDeltaRadii10 + mDeltaRadii21) * (mDeltaRadii10 + mDeltaRadii21)); + LayersZCoordinate[2] / std::hypot(LayersZCoordinate[2], mDeltaRadii10 + mDeltaRadii21); } -const std::vector<std::pair<int, int>> VertexerTraits::selectClusters(const std::array<int, ZBins * PhiBins + 1>& indexTable, - const std::array<int, 4>& selectedBinsRect) +const std::vector<std::pair<int, int>> VertexerTraits::selectClusters(const int* indexTable, + const std::array<int, 4>& selectedBinsRect, + const IndexTableUtils& utils) { std::vector<std::pair<int, int>> filteredBins{}; int phiBinsNum{selectedBinsRect[3] - selectedBinsRect[1] + 1}; if (phiBinsNum < 0) { - phiBinsNum += PhiBins; + phiBinsNum += utils.getNphiBins(); } filteredBins.reserve(phiBinsNum); for (int iPhiBin{selectedBinsRect[1]}, iPhiCount{0}; iPhiCount < phiBinsNum; - iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) { - const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect[0], iPhiBin)}; + iPhiBin = ++iPhiBin == utils.getNphiBins() ? 0 : iPhiBin, iPhiCount++) { + const int firstBinIndex{utils.getBinIndex(selectedBinsRect[0], iPhiBin)}; filteredBins.emplace_back( indexTable[firstBinIndex], - index_table_utils::countRowSelectedBins(indexTable, iPhiBin, selectedBinsRect[0], selectedBinsRect[2])); + utils.countRowSelectedBins(indexTable, iPhiBin, selectedBinsRect[0], selectedBinsRect[2])); } return filteredBins; } @@ -312,20 +309,22 @@ void VertexerTraits::computeTracklets() trackleterKernelSerial( mClusters[0], mClusters[1], - mIndexTables[0], + mIndexTables[0].data(), LAYER0_TO_LAYER1, mVrtParams.phiCut, mComb01, - mFoundTracklets01); + mFoundTracklets01, + mIndexTableUtils); trackleterKernelSerial( mClusters[2], mClusters[1], - mIndexTables[2], + mIndexTables[2].data(), LAYER1_TO_LAYER2, mVrtParams.phiCut, mComb12, - mFoundTracklets12); + mFoundTracklets12, + mIndexTableUtils); #ifdef _ALLOW_DEBUG_TREES_ITS_ if (isDebugFlag(VertexerDebug::CombinatoricsTreeAll)) { diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index c27ac26b4a6cf..1103157c3adbf 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -119,7 +119,7 @@ void CookedTrackerDPL::run(ProcessingContext& pc) o2::its::VertexerTraits vertexerTraits; o2::its::Vertexer vertexer(&vertexerTraits); - o2::its::ROframe event(0); + o2::its::ROframe event(0, 7); auto& vertROFvec = pc.outputs().make<std::vector<o2::itsmft::ROFRecord>>(Output{"ITS", "VERTICESROF", 0, Lifetime::Timeframe}); auto& vertices = pc.outputs().make<std::vector<Vertex>>(Output{"ITS", "VERTICES", 0, Lifetime::Timeframe}); diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 47bfbdc8c93de..7f29a4bb0e0cb 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -130,7 +130,7 @@ void TrackerDPL::run(ProcessingContext& pc) auto& vertices = pc.outputs().make<std::vector<Vertex>>(Output{"ITS", "VERTICES", 0, Lifetime::Timeframe}); std::uint32_t roFrame = 0; - ROframe event(0); + ROframe event(0, 7); bool continuous = mGRP->isDetContinuousReadOut("ITS"); LOG(INFO) << "ITSTracker RO: continuous=" << continuous; diff --git a/GPU/GPUTracking/Global/GPUChainITS.cxx b/GPU/GPUTracking/Global/GPUChainITS.cxx index c828884b69328..a6db94b02b007 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.cxx +++ b/GPU/GPUTracking/Global/GPUChainITS.cxx @@ -70,13 +70,13 @@ int GPUChainITS::Finalize() { return 0; } int GPUChainITS::RunChain() { return 0; } -int GPUChainITS::PrepareAndRunITSTrackFit(std::vector<Road>& roads, std::array<const Cluster*, 7> clusters, std::array<const Cell*, 5> cells, const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks) +int GPUChainITS::PrepareAndRunITSTrackFit(std::vector<o2::its::Road>& roads, std::vector<const o2::its::Cluster*>& clusters, std::vector<const o2::its::Cell*>& cells, const std::vector<std::vector<o2::its::TrackingFrameInfo>>& tf, std::vector<o2::its::TrackITSExt>& tracks) { mRec->PrepareEvent(); return RunITSTrackFit(roads, clusters, cells, tf, tracks); } -int GPUChainITS::RunITSTrackFit(std::vector<Road>& roads, std::array<const Cluster*, 7> clusters, std::array<const Cell*, 5> cells, const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks) +int GPUChainITS::RunITSTrackFit(std::vector<o2::its::Road>& roads, std::vector<const o2::its::Cluster*>& clusters, std::vector<const o2::its::Cell*>& cells, const std::vector<std::vector<o2::its::TrackingFrameInfo>>& tf, std::vector<o2::its::TrackITSExt>& tracks) { auto threadContext = GetThreadContext(); bool doGPU = GetRecoStepsGPU() & RecoStep::ITSTracking; @@ -85,7 +85,7 @@ int GPUChainITS::RunITSTrackFit(std::vector<Road>& roads, std::array<const Clust Fitter.clearMemory(); Fitter.SetNumberOfRoads(roads.size()); - for (int i = 0; i < 7; i++) { + for (int i = 0; i < clusters.size(); i++) { Fitter.SetNumberTF(i, tf[i].size()); } Fitter.SetMaxData(processors()->ioPtrs); @@ -93,7 +93,7 @@ int GPUChainITS::RunITSTrackFit(std::vector<Road>& roads, std::array<const Clust std::copy(cells.begin(), cells.end(), Fitter.cells()); SetupGPUProcessor(&Fitter, true); std::copy(roads.begin(), roads.end(), Fitter.roads()); - for (int i = 0; i < 7; i++) { + for (int i = 0; i < clusters.size(); i++) { std::copy(tf[i].begin(), tf[i].end(), Fitter.trackingFrame()[i]); } diff --git a/GPU/GPUTracking/Global/GPUChainITS.h b/GPU/GPUTracking/Global/GPUChainITS.h index f9583aee00042..c6504c48ce13a 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.h +++ b/GPU/GPUTracking/Global/GPUChainITS.h @@ -40,8 +40,8 @@ class GPUChainITS : public GPUChain int RunChain() override; void MemorySize(size_t& gpuMem, size_t& pageLockedHostMem) override; - int PrepareAndRunITSTrackFit(std::vector<o2::its::Road>& roads, std::array<const o2::its::Cluster*, 7> clusters, std::array<const o2::its::Cell*, 5> cells, const std::array<std::vector<o2::its::TrackingFrameInfo>, 7>& tf, std::vector<o2::its::TrackITSExt>& tracks); - int RunITSTrackFit(std::vector<o2::its::Road>& roads, std::array<const o2::its::Cluster*, 7> clusters, std::array<const o2::its::Cell*, 5> cells, const std::array<std::vector<o2::its::TrackingFrameInfo>, 7>& tf, std::vector<o2::its::TrackITSExt>& tracks); + int PrepareAndRunITSTrackFit(std::vector<o2::its::Road>& roads, std::vector<const o2::its::Cluster*>& clusters, std::vector<const o2::its::Cell*>& cells, const std::vector<std::vector<o2::its::TrackingFrameInfo>>& tf, std::vector<o2::its::TrackITSExt>& tracks); + int RunITSTrackFit(std::vector<o2::its::Road>& roads, std::vector<const o2::its::Cluster*>& clusters, std::vector<const o2::its::Cell*>& cells, const std::vector<std::vector<o2::its::TrackingFrameInfo>>& tf, std::vector<o2::its::TrackITSExt>& tracks); o2::its::TrackerTraits* GetITSTrackerTraits(); o2::its::VertexerTraits* GetITSVertexerTraits(); diff --git a/GPU/GPUTracking/ITS/GPUITSFitter.h b/GPU/GPUTracking/ITS/GPUITSFitter.h index c45efa0048adf..fc27cc985808a 100644 --- a/GPU/GPUTracking/ITS/GPUITSFitter.h +++ b/GPU/GPUTracking/ITS/GPUITSFitter.h @@ -56,6 +56,8 @@ class GPUITSFitter : public GPUProcessor { return mMemory->mNumberOfTracks; } + GPUd() void SetNumberOfLayers(int i) { mNumberOfLayers = i; } + GPUd() int NumberOfLayers() { return mNumberOfLayers; } GPUd() void SetNumberTF(int i, int v) { mNTF[i] = v; } GPUd() o2::its::TrackingFrameInfo** trackingFrame() { @@ -77,16 +79,17 @@ class GPUITSFitter : public GPUProcessor }; protected: + int mNumberOfLayers; int mNumberOfRoads = 0; int mNMaxTracks = 0; - int mNTF[7] = {}; + int* mNTF = nullptr; Memory* mMemory = nullptr; o2::its::Road* mRoads = nullptr; - o2::its::TrackingFrameInfo* mTF[7] = {}; + o2::its::TrackingFrameInfo** mTF = {nullptr}; GPUITSTrack* mTracks = nullptr; - const o2::its::Cluster* mClusterPtrs[7]; - const o2::its::Cell* mCellPtrs[5]; + const o2::its::Cluster** mClusterPtrs; + const o2::its::Cell** mCellPtrs; short mMemoryResInput = -1; short mMemoryResTracks = -1; diff --git a/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx b/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx index 0e3fba8649e41..67360fbb49ed9 100644 --- a/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx +++ b/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx @@ -78,7 +78,7 @@ GPUdii() void GPUITSFitterKernel::Thread<0>(int nBlocks, int nThreads, int iBloc int lastCellLevel = o2::its::constants::its::UnusedIndex; CA_DEBUGGER(int nClusters = 2); - for (int iCell{0}; iCell < o2::its::constants::its::CellsPerRoad; ++iCell) { + for (int iCell{0}; iCell < Fitter.NumberOfLayers() - 2; ++iCell) { const int cellIndex = road[iCell]; if (cellIndex == o2::its::constants::its::UnusedIndex) { continue; @@ -164,13 +164,13 @@ GPUdii() void GPUITSFitterKernel::Thread<0>(int nBlocks, int nThreads, int iBloc for (size_t iC = 0; iC < 7; ++iC) { temporaryTrack.mClusters[iC] = clusters[iC]; } - bool fitSuccess = fitTrack(Fitter, prop, temporaryTrack, o2::its::constants::its::LayersNumber - 4, -1, -1); + bool fitSuccess = fitTrack(Fitter, prop, temporaryTrack, Fitter.NumberOfLayers() - 4, -1, -1); if (!fitSuccess) { continue; } CA_DEBUGGER(fitCounters[nClusters - 4]++); temporaryTrack.ResetCovariance(); - fitSuccess = fitTrack(Fitter, prop, temporaryTrack, 0, o2::its::constants::its::LayersNumber, 1); + fitSuccess = fitTrack(Fitter, prop, temporaryTrack, 0, Fitter.NumberOfLayers(), 1); if (!fitSuccess) { continue; } @@ -184,7 +184,7 @@ GPUdii() void GPUITSFitterKernel::Thread<0>(int nBlocks, int nThreads, int iBloc temporaryTrack.mOuterParam.X = temporaryTrack.X(); temporaryTrack.mOuterParam.alpha = prop.GetAlpha(); temporaryTrack.ResetCovariance(); - fitSuccess = fitTrack(Fitter, prop, temporaryTrack, o2::its::constants::its::LayersNumber - 1, -1, -1); + fitSuccess = fitTrack(Fitter, prop, temporaryTrack, Fitter.NumberOfLayers() - 1, -1, -1); if (!fitSuccess) { continue; } diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index b98d5319126c6..7baa6029f5a2f 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -53,6 +53,7 @@ install(FILES CheckDigits_mft.C run_rawdecoding_mft.C run_trac_ca_its.C run_trac_its.C + run_trac_alice3.C CreateBCPattern.C DESTINATION share/macro/) @@ -380,6 +381,11 @@ o2_add_test_root_macro(run_trac_its.C O2::SimulationDataFormat LABELS its) +# FIXME: move to subsystem dir +o2_add_test_root_macro(run_trac_alice3.C + PUBLIC_LINK_LIBRARIES O2::GPUTracking + LABELS its COMPILE_ONLY) + # # NOTE: commented out until unit testing reenabled FIXME : re-enable or delete ? # diff --git a/macro/run_primary_vertexer_ITS.C b/macro/run_primary_vertexer_ITS.C index 1a9e8f122f7fc..fc0599a84ae91 100644 --- a/macro/run_primary_vertexer_ITS.C +++ b/macro/run_primary_vertexer_ITS.C @@ -170,7 +170,7 @@ int run_primary_vertexer_ITS(const GPUDataTypes::DeviceType dtype = GPUDataTypes for (size_t iROfCount{static_cast<size_t>(startAt)}; iROfCount < static_cast<size_t>(stopAt); ++iROfCount) { auto& rof = (*rofs)[iROfCount]; - o2::its::ROframe frame(iROfCount); // to get meaningful roframeId + o2::its::ROframe frame(iROfCount, 7); // to get meaningful roframeId std::cout << "ROframe: " << iROfCount << std::endl; auto it = pattIt; diff --git a/macro/run_trac_alice3.C b/macro/run_trac_alice3.C new file mode 100644 index 0000000000000..b38c9c2918e1e --- /dev/null +++ b/macro/run_trac_alice3.C @@ -0,0 +1,263 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include <string> + +#include <TFile.h> +#include <TChain.h> +#include <TH2D.h> +#include <TBranch.h> +#include <TRandom3.h> +#include <TGeoGlobalMagField.h> +#include <vector> + +#include "DataFormatsITSMFT/ROFRecord.h" +#include "ITSMFTSimulation/Hit.h" +#include "ITStracking/Configuration.h" +#include "ITStracking/IOUtils.h" +#include "ITStracking/Tracker.h" +#include "ITStracking/TrackerTraitsCPU.h" +#include "ITStracking/Vertexer.h" +#include "DataFormatsITSMFT/Cluster.h" +#include "DataFormatsITSMFT/TopologyDictionary.h" +#include "DataFormatsITSMFT/CompCluster.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "SimulationDataFormat/MCTrack.h" +#include "MathUtils/Cartesian3D.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Vertex.h" + +#endif + +using o2::its::MemoryParameters; +using o2::its::TrackingParameters; +using o2::itsmft::Hit; +using std::string; + +constexpr bool kUseSmearing{false}; + +struct particle { + int pdg = 0; + int nLayers = 0; + float pt; + float eta; + float phi; + float recoPt; + float recoEta; + float energyFirst; + float energyLast; + int isReco = 0; // 0 = no, 1 = good, 2 = fake +}; + +float getDetLengthFromEta(const float eta, const float radius) +{ + return 10. * (10. + radius * std::cos(2 * std::atan(std::exp(-eta)))); +} + +void run_trac_alice3(const string hitsFileName = "o2sim_HitsIT4.root") +{ + + TChain mcTree("o2sim"); + mcTree.AddFile("o2sim_Kine.root"); + mcTree.SetBranchStatus("*", 0); //disable all branches + mcTree.SetBranchStatus("MCTrack*", 1); + + std::vector<o2::MCTrack>* mcArr = nullptr; + mcTree.SetBranchAddress("MCTrack", &mcArr); + + o2::its::Vertexer vertexer(new o2::its::VertexerTraits()); + TChain itsHits("o2sim"); + + itsHits.AddFile(hitsFileName.data()); + + o2::its::Tracker tracker(new o2::its::TrackerTraitsCPU()); + tracker.setBz(5.f); + + std::uint32_t roFrame; + std::vector<Hit>* hits = nullptr; + itsHits.SetBranchAddress("IT4Hit", &hits); + + std::vector<TrackingParameters> trackParams(4); + trackParams[0].NLayers = 10; + trackParams[0].MinTrackLength = 10; + + std::vector<float> LayerRadii = {1.8f, 2.4f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}; + std::vector<float> LayerZ(10); + for (int i{0}; i < 10; ++i) + LayerZ[i] = getDetLengthFromEta(1.44, LayerRadii[i]) + 1.; + std::vector<float> TrackletMaxDeltaZ = {0.1f, 0.1f, 0.3f, 0.3f, 0.3f, 0.3f, 0.5f, 0.5f, 0.5f}; + std::vector<float> CellMaxDCA = {0.05f, 0.04f, 0.05f, 0.2f, 0.4f, 0.5f, 0.5f, 0.5f}; + std::vector<float> CellMaxDeltaZ = {0.2f, 0.4f, 0.5f, 0.6f, 3.0f, 3.0f, 3.0f, 3.0f}; + std::vector<float> NeighbourMaxDeltaCurvature = {0.008f, 0.0025f, 0.003f, 0.0035f, 0.004f, 0.004f, 0.005f}; + std::vector<float> NeighbourMaxDeltaN = {0.002f, 0.0090f, 0.002f, 0.005f, 0.005f, 0.005f, 0.005f}; + + trackParams[0].LayerRadii = LayerRadii; + trackParams[0].LayerZ = LayerZ; + trackParams[0].TrackletMaxDeltaPhi = 0.3; + trackParams[0].CellMaxDeltaPhi = 0.15; + trackParams[0].CellMaxDeltaTanLambda = 0.03; + trackParams[0].TrackletMaxDeltaZ = TrackletMaxDeltaZ; + trackParams[0].CellMaxDCA = CellMaxDCA; + trackParams[0].CellMaxDeltaZ = CellMaxDeltaZ; + trackParams[0].NeighbourMaxDeltaCurvature = NeighbourMaxDeltaCurvature; + trackParams[0].NeighbourMaxDeltaN = NeighbourMaxDeltaN; + + std::vector<MemoryParameters> memParams(4); + std::vector<float> CellsMemoryCoefficients = {2.3208e-08f * 20, 2.104e-08f * 20, 1.6432e-08f * 20, 1.2412e-08f * 20, 1.3543e-08f * 20, 1.5e-08f * 20, 1.6e-08f * 20, 1.7e-08f * 20}; + std::vector<float> TrackletsMemoryCoefficients = {0.0016353f * 1000, 0.0013627f * 1000, 0.000984f * 1000, 0.00078135f * 1000, 0.00057934f * 1000, 0.00052217f * 1000, 0.00052217f * 1000, 0.00052217f * 1000, 0.00052217f * 1000}; + memParams[0].CellsMemoryCoefficients = CellsMemoryCoefficients; + memParams[0].TrackletsMemoryCoefficients = TrackletsMemoryCoefficients; + memParams[0].MemoryOffset = 8000; + + for (int i = 1; i < 4; ++i) { + memParams[i] = memParams[i - 1]; + trackParams[i] = trackParams[i - 1]; + // trackParams[i].MinTrackLength -= 2; + trackParams[i].TrackletMaxDeltaPhi *= 3; + trackParams[i].CellMaxDeltaPhi *= 3; + trackParams[i].CellMaxDeltaTanLambda *= 3; + for (auto& val : trackParams[i].TrackletMaxDeltaZ) + val *= 3; + for (auto& val : trackParams[i].CellMaxDCA) + val *= 3; + for (auto& val : trackParams[i].CellMaxDeltaZ) + val *= 3; + for (auto& val : trackParams[i].NeighbourMaxDeltaCurvature) + val *= 3; + for (auto& val : trackParams[i].NeighbourMaxDeltaN) + val *= 3; + } + + tracker.setParameters(memParams, trackParams); + + constexpr int nBins = 100; + constexpr float minPt = 0.01; + constexpr float maxPt = 10; + double newBins[nBins + 1]; + newBins[0] = minPt; + double factor = pow(maxPt / minPt, 1. / nBins); + for (int i = 1; i <= nBins; i++) { + newBins[i] = factor * newBins[i - 1]; + } + + TH1D genH("gen", ";#it{p}_{T} (GeV/#it{c});", nBins, newBins); + TH1D recH("rec", "Efficiency;#it{p}_{T} (GeV/#it{c});", nBins, newBins); + TH1D fakH("fak", "Fake rate;#it{p}_{T} (GeV/#it{c});", nBins, newBins); + TH2D deltaPt("deltapt", ";#it{p}_{T} (GeV/#it{c});#Delta#it{p}_{T} (GeV/#it{c});", nBins, newBins, 100, -0.1, 0.1); + TH2D dcaxy("dcaxy", ";#it{p}_{T} (GeV/#it{c});DCA_{xy} (#mum);", nBins, newBins, 200, -200, 200); + TH2D dcaz("dcaz", ";#it{p}_{T} (GeV/#it{c});DCA_{z} (#mum);", nBins, newBins, 200, -200, 200); + TH2D deltaE("deltaE", ";#it{p}_{T} (GeV/#it{c});#DeltaE (MeV);", nBins, newBins, 200, 0, 100); + + Point3D<float> pos{0.f, 0.f, 0.f}; + const std::array<float, 6> cov{1.e-4, 0., 0., 1.e-4, 0., 1.e-4}; + o2::dataformats::VertexBase vtx(pos, cov); + o2::dataformats::DCA dca; + + for (int iEvent{0}; iEvent < itsHits.GetEntriesFast(); ++iEvent) { + std::cout << "*************** Event " << iEvent << " ***************" << std::endl; + itsHits.GetEntry(iEvent); + mcTree.GetEvent(iEvent); + o2::its::ROframe event{iEvent, 10}; + + int id{0}; + std::map<int, particle> mapPDG; + for (auto& hit : *hits) { + const int layer{hit.GetDetectorID()}; + float xyz[3]{hit.GetX(), hit.GetY(), hit.GetZ()}; + float r{std::hypot(xyz[0], xyz[1])}; + float phi{std::atan2(-xyz[1], -xyz[0]) + o2::its::constants::math::Pi}; + + if (kUseSmearing) { + phi = gRandom->Gaus(phi, std::asin(0.0005f / r)); + xyz[0] = r * std::cos(phi); + xyz[1] = r * std::sin(phi); + xyz[2] = gRandom->Gaus(xyz[2], 0.0005f); + } + + event.addTrackingFrameInfoToLayer(layer, xyz[0], xyz[1], xyz[2], r, phi, std::array<float, 2>{0.f, xyz[2]}, + std::array<float, 3>{0.0005f * 0.0005f, 0.f, 0.0005f * 0.0005f}); + event.addClusterToLayer(layer, xyz[0], xyz[1], xyz[2], event.getClustersOnLayer(layer).size()); + event.addClusterLabelToLayer(layer, o2::MCCompLabel(hit.GetTrackID(), iEvent, iEvent, false)); + event.addClusterExternalIndexToLayer(layer, id++); + if (mapPDG.find(hit.GetTrackID()) == mapPDG.end()) { + mapPDG[hit.GetTrackID()] = particle(); + mapPDG[hit.GetTrackID()].nLayers |= 1 << layer; + mapPDG[hit.GetTrackID()].pt = std::hypot(hit.GetPx(), hit.GetPy()); + if (hit.GetTrackID() < mcArr->size()) { + auto part = mcArr->at(hit.GetTrackID()); + mapPDG[hit.GetTrackID()].energyFirst = part.GetEnergy(); + mapPDG[hit.GetTrackID()].pdg = part.GetPdgCode(); + mapPDG[hit.GetTrackID()].pt = part.GetPt(); + mapPDG[hit.GetTrackID()].eta = part.GetEta(); + mapPDG[hit.GetTrackID()].phi = part.GetPhi(); + } + } else { + mapPDG[hit.GetTrackID()].nLayers |= 1 << layer; + mapPDG[hit.GetTrackID()].energyLast = hit.GetE(); + } + } + roFrame = iEvent; + + vertexer.clustersToVertices(event); + int nPart10layers{0}; + for (auto& part : mapPDG) { + if (part.second.nLayers == 0x3FF) { + nPart10layers++; + genH.Fill(part.second.pt); + deltaE.Fill(part.second.pt, 1000 * (part.second.energyFirst - part.second.energyLast)); + } + } + tracker.clustersToTracks(event); + auto& tracks = tracker.getTracks(); + auto& tracksLabels = tracker.getTrackLabels(); + std::cout << "**** " << nPart10layers << " particles with 10 layers " << tracks.size() << " tracks" << std::endl; + int good{0}; + for (unsigned int i{0}; i < tracks.size(); ++i) { + auto& lab = tracksLabels[i]; + auto& track = tracks[i]; + int trackID = std::abs(lab.getTrackID()); + if (mapPDG.find(trackID) != mapPDG.end()) { + if (!mapPDG[trackID].pdg) + std::cout << "strange" << std::endl; + mapPDG[trackID].isReco = lab.isFake() ? 2 : 1; + mapPDG[trackID].recoPt = track.getPt(); + mapPDG[trackID].recoEta = track.getEta(); + (lab.isFake() ? fakH : recH).Fill(mapPDG[trackID].pt); + deltaPt.Fill(mapPDG[trackID].pt, (mapPDG[trackID].pt - mapPDG[trackID].recoPt) / mapPDG[trackID].pt); + if (!track.propagateToDCA(vtx, tracker.getBz(), &dca)) { + std::cout << "Propagation failed." << std::endl; + } else { + dcaxy.Fill(mapPDG[trackID].pt, dca.getY() * 1.e4); + dcaz.Fill(mapPDG[trackID].pt, dca.getZ() * 1.e4); + } + } + } + } + + TH1D dcaxy_res(recH); + dcaxy_res.Reset(); + dcaxy_res.SetNameTitle("dcaxy_res", ";#it{p}_{T} (GeV/#it{c});#sigma(DCA_{xy}) (#mum);"); + TH1D dcaz_res(recH); + dcaz_res.Reset(); + dcaz_res.SetNameTitle("dcaz_res", ";#it{p}_{T} (GeV/#it{c});#sigma(DCA_{z}) (#mum);"); + for (int i = 1; i <= nBins; ++i) { + auto proj = dcaxy.ProjectionY(Form("xy%i", i), i, i); + dcaxy_res.SetBinContent(i, proj->GetStdDev()); + dcaxy_res.SetBinError(i, proj->GetStdDevError()); + proj = dcaz.ProjectionY(Form("z%i", i), i, i); + dcaz_res.SetBinContent(i, proj->GetStdDev()); + dcaz_res.SetBinError(i, proj->GetStdDevError()); + } + + TFile output("output.root", "recreate"); + recH.Divide(&genH); + fakH.Divide(&genH); + recH.Write(); + fakH.SetLineColor(kRed); + fakH.Write(); + genH.Write(); + deltaPt.Write(); + dcaxy.Write(); + dcaz.Write(); + dcaz_res.Write(); + dcaxy_res.Write(); + deltaE.Write(); +} diff --git a/macro/run_trac_ca_its.C b/macro/run_trac_ca_its.C index b29671c2772b7..04213bbb1946f 100644 --- a/macro/run_trac_ca_its.C +++ b/macro/run_trac_ca_its.C @@ -63,13 +63,13 @@ void run_trac_ca_its(std::string path = "./", gSystem->Load("libO2ITStracking.so"); //std::unique_ptr<GPUReconstruction> rec(GPUReconstruction::CreateInstance()); - std::unique_ptr<GPUReconstruction> rec(GPUReconstruction::CreateInstance("CUDA", true)); // for GPU with CUDA - auto* chainITS = rec->AddChain<GPUChainITS>(); - rec->Init(); + // std::unique_ptr<GPUReconstruction> rec(GPUReconstruction::CreateInstance("CUDA", true)); // for GPU with CUDA + // auto* chainITS = rec->AddChain<GPUChainITS>(); + // rec->Init(); - o2::its::Tracker tracker(chainITS->GetITSTrackerTraits()); - //o2::its::Tracker tracker(new o2::its::TrackerTraitsCPU()); - o2::its::ROframe event(0); + // o2::its::Tracker tracker(chainITS->GetITSTrackerTraits()); + o2::its::Tracker tracker(new o2::its::TrackerTraitsCPU()); + o2::its::ROframe event(0, 7); if (path.back() != '/') { path += '/'; diff --git a/macro/run_trac_its.C b/macro/run_trac_its.C index d1272e1df3445..252db1a899072 100644 --- a/macro/run_trac_its.C +++ b/macro/run_trac_its.C @@ -166,7 +166,7 @@ void run_trac_its(std::string path = "./", std::string outputfile = "o2trac_its. o2::its::VertexerTraits vertexerTraits; o2::its::Vertexer vertexer(&vertexerTraits); - o2::its::ROframe event(0); + o2::its::ROframe event(0, 7); gsl::span<const unsigned char> patt(patterns->data(), patterns->size()); auto pattIt = patt.begin(); From 23b8f8337f37bf0a28b4c2f736a51511fb805e81 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 28 Nov 2020 09:12:29 +0100 Subject: [PATCH 1440/1751] Fix macro/run_trac_alice3.C compilation (#4939) --- macro/run_trac_alice3.C | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/macro/run_trac_alice3.C b/macro/run_trac_alice3.C index b38c9c2918e1e..c98e0950c3d2b 100644 --- a/macro/run_trac_alice3.C +++ b/macro/run_trac_alice3.C @@ -8,7 +8,7 @@ #include <TRandom3.h> #include <TGeoGlobalMagField.h> #include <vector> - +#include <Math/Point3Dfwd.h> #include "DataFormatsITSMFT/ROFRecord.h" #include "ITSMFTSimulation/Hit.h" #include "ITStracking/Configuration.h" @@ -21,10 +21,9 @@ #include "DataFormatsITSMFT/CompCluster.h" #include "DetectorsCommonDataFormats/DetID.h" #include "SimulationDataFormat/MCTrack.h" -#include "MathUtils/Cartesian3D.h" +#include "MathUtils/Cartesian.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/Vertex.h" - #endif using o2::its::MemoryParameters; @@ -146,7 +145,7 @@ void run_trac_alice3(const string hitsFileName = "o2sim_HitsIT4.root") TH2D dcaz("dcaz", ";#it{p}_{T} (GeV/#it{c});DCA_{z} (#mum);", nBins, newBins, 200, -200, 200); TH2D deltaE("deltaE", ";#it{p}_{T} (GeV/#it{c});#DeltaE (MeV);", nBins, newBins, 200, 0, 100); - Point3D<float> pos{0.f, 0.f, 0.f}; + ROOT::Math::XYZPointF pos{0.f, 0.f, 0.f}; const std::array<float, 6> cov{1.e-4, 0., 0., 1.e-4, 0., 1.e-4}; o2::dataformats::VertexBase vtx(pos, cov); o2::dataformats::DCA dca; From 34bc49576f92bd09c777dc5f069a98f85956cc9c Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez@cern.ch> Date: Sat, 28 Nov 2020 15:52:16 +0100 Subject: [PATCH 1441/1751] Moving the configuration parameters to a TFolder OutputObj (#4937) To temporarily circumvent the issue of TParameter with TList --- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 59 +++++++++++++-------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index 327802d5bdadf..a75a189dc4318 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -20,6 +20,7 @@ #include <TParameter.h> #include <TList.h> #include <TDirectory.h> +#include <TFolder.h> #include <TH1.h> #include <TH2.h> #include <TH3.h> @@ -301,6 +302,7 @@ struct DptDptCorrelationsFilterAnalysisTask { "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TFolder> fConfOutput{"DptDptCorrelationsGlobalConfiguration", OutputObjHandlingPolicy::AnalysisObject}; Produces<aod::AcceptedEvents> acceptedevents; Produces<aod::ScannedTracks> scannedtracks; @@ -334,16 +336,21 @@ struct DptDptCorrelationsFilterAnalysisTask { /* if the system type is not known at this time, we have to put the initalization somewhere else */ fSystem = getSystemType(); + /* create the configuration folder which will own the task configuration parameters */ + TFolder* fOutputFolder = new TFolder("DptDptCorrelationsGlobalConfigurationFolder", "DptDptCorrelationsGlobalConfigurationFolder"); + fOutputFolder->SetOwner(true); + fConfOutput.setObject(fOutputFolder); + + /* incorporate configuration parameters to the output */ + fOutputFolder->Add(new TParameter<Int_t>("TrackType", cfgTrackType, 'f')); + fOutputFolder->Add(new TParameter<Int_t>("TrackOneCharge", cfgTrackOneCharge, 'f')); + fOutputFolder->Add(new TParameter<Int_t>("TrackTwoCharge", cfgTrackTwoCharge, 'f')); + /* create the output list which will own the task histograms */ TList* fOutputList = new TList(); fOutputList->SetOwner(true); fOutput.setObject(fOutputList); - /* incorporate configuration parameters to the output */ - fOutputList->Add(new TParameter<Int_t>("TrackType", cfgTrackType, 'f')); - fOutputList->Add(new TParameter<Int_t>("TrackOneCharge", cfgTrackOneCharge, 'f')); - fOutputList->Add(new TParameter<Int_t>("TrackTwoCharge", cfgTrackTwoCharge, 'f')); - /* create the histograms */ if (fSystem > kPbp) { fhCentMultB = new TH1F("CentralityB", "Centrality before cut; centrality (%)", 100, 0, 100); @@ -463,6 +470,7 @@ struct DptDptCorrelationsTask { "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj<TFolder> fConfOutput{"DptDptCorrelationsConfiguration", OutputObjHandlingPolicy::AnalysisObject}; Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); @@ -477,6 +485,7 @@ struct DptDptCorrelationsTask { {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}, OutputObj<TList> _fOutput = {"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}, + OutputObj<TFolder> _fConfOutput = {"DptDptCorrelationsConfiguration", OutputObjHandlingPolicy::AnalysisObject}, Filter _onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE), Filter _onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)), Partition<aod::FilteredTracks> _Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE, @@ -486,6 +495,7 @@ struct DptDptCorrelationsTask { cfgProcessPairs(_cfgProcessPairs), cfgBinning(_cfgBinning), fOutput(_fOutput), + fConfOutput(_fConfOutput), onlyacceptedevents((aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE) and (aod::dptdptcorrelations::centmult > fCentMultMin) and (aod::dptdptcorrelations::centmult < fCentMultMax)), onlyacceptedtracks((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)), Tracks1(aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE), @@ -516,30 +526,35 @@ struct DptDptCorrelationsTask { etabinwidth = (etaup - etalow) / float(etabins); phibinwidth = (phiup - philow) / float(phibins); - /* create the output list which will own the task histograms */ - TList* fOutputList = new TList(); - fOutputList->SetOwner(true); - fOutput.setObject(fOutputList); + /* create the configuration folder which will own the task configuration parameters */ + TFolder* fOutputFolder = new TFolder("DptDptCorrelationsConfigurationFolder", "DptDptCorrelationsConfigurationFolder"); + fOutputFolder->SetOwner(true); + fConfOutput.setObject(fOutputFolder); /* incorporate configuration parameters to the output */ - fOutputList->Add(new TParameter<Int_t>("NoBinsVertexZ", zvtxbins, 'f')); - fOutputList->Add(new TParameter<Int_t>("NoBinsPt", ptbins, 'f')); - fOutputList->Add(new TParameter<Int_t>("NoBinsEta", etabins, 'f')); - fOutputList->Add(new TParameter<Int_t>("NoBinsPhi", phibins, 'f')); - fOutputList->Add(new TParameter<Double_t>("MinVertexZ", zvtxlow, 'f')); - fOutputList->Add(new TParameter<Double_t>("MaxVertexZ", zvtxup, 'f')); - fOutputList->Add(new TParameter<Double_t>("MinPt", ptlow, 'f')); - fOutputList->Add(new TParameter<Double_t>("MaxPt", ptup, 'f')); - fOutputList->Add(new TParameter<Double_t>("MinEta", etalow, 'f')); - fOutputList->Add(new TParameter<Double_t>("MaxEta", etaup, 'f')); - fOutputList->Add(new TParameter<Double_t>("MinPhi", philow, 'f')); - fOutputList->Add(new TParameter<Double_t>("MaxPhi", phiup, 'f')); - fOutputList->Add(new TParameter<Double_t>("PhiBinShift", phibinshift, 'f')); + fOutputFolder->Add(new TParameter<Int_t>("NoBinsVertexZ", zvtxbins, 'f')); + fOutputFolder->Add(new TParameter<Int_t>("NoBinsPt", ptbins, 'f')); + fOutputFolder->Add(new TParameter<Int_t>("NoBinsEta", etabins, 'f')); + fOutputFolder->Add(new TParameter<Int_t>("NoBinsPhi", phibins, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MinVertexZ", zvtxlow, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MaxVertexZ", zvtxup, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MinPt", ptlow, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MaxPt", ptup, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MinEta", etalow, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MaxEta", etaup, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MinPhi", philow, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("MaxPhi", phiup, 'f')); + fOutputFolder->Add(new TParameter<Double_t>("PhiBinShift", phibinshift, 'f')); /* after the parameters dump the proper phi limits are set according to the phi shift */ phiup = phiup - phibinwidth * phibinshift; philow = philow - phibinwidth * phibinshift; + /* create the output list which will own the task histograms */ + TList* fOutputList = new TList(); + fOutputList->SetOwner(true); + fOutput.setObject(fOutputList); + /* create the histograms */ Bool_t oldstatus = TH1::AddDirectoryStatus(); TH1::AddDirectory(kFALSE); From 71f34092d1fc30cf831ca5986fc203f3840b447a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 28 Nov 2020 18:00:12 +0100 Subject: [PATCH 1442/1751] Exclude testCcdbApi_alien.cxx (#4941) Breaks when an alien token is not found. --- CCDB/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CCDB/CMakeLists.txt b/CCDB/CMakeLists.txt index a91a3aa31347e..e6a985ea19d2b 100644 --- a/CCDB/CMakeLists.txt +++ b/CCDB/CMakeLists.txt @@ -51,11 +51,11 @@ o2_add_test(CcdbApi PUBLIC_LINK_LIBRARIES O2::CCDB LABELS ccdb) -o2_add_test(CcdbApi-Alien - SOURCES test/testCcdbApi_alien.cxx - COMPONENT_NAME ccdb - PUBLIC_LINK_LIBRARIES O2::CCDB - LABELS ccdb) +#o2_add_test(CcdbApi-Alien +# SOURCES test/testCcdbApi_alien.cxx +# COMPONENT_NAME ccdb +# PUBLIC_LINK_LIBRARIES O2::CCDB +# LABELS ccdb) o2_add_test(BasicCCDBManager SOURCES test/testBasicCCDBManager.cxx From 08580537dec94d1371e4cbe0dbbc8259a9cef77e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 29 Nov 2020 10:43:56 +0100 Subject: [PATCH 1443/1751] Add missing library to run_trac_alice3.C (#4943) --- macro/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index 7baa6029f5a2f..2a7d5c91295dc 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -383,7 +383,7 @@ o2_add_test_root_macro(run_trac_its.C # FIXME: move to subsystem dir o2_add_test_root_macro(run_trac_alice3.C - PUBLIC_LINK_LIBRARIES O2::GPUTracking + PUBLIC_LINK_LIBRARIES O2::GPUTracking O2::ITSMFTSimulation LABELS its COMPILE_ONLY) # From d7756ccdeaaf042d363128c1c3ed32ef2f0adaca Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaya@cern.ch> Date: Sun, 29 Nov 2020 14:07:46 +0100 Subject: [PATCH 1444/1751] Fixed unit test Detectors/CTF/test/test_ctf_io_ft0.cxx (#4938) * add EventStatusWord to CTF * fix unitest * minor fix * clang format * clang format --- .../Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h | 2 +- Detectors/CTF/test/test_ctf_io_ft0.cxx | 9 +++++---- Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h | 6 +++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h index 25cc2274e3dec..752734fdbf382 100644 --- a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h +++ b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h @@ -47,6 +47,6 @@ #pragma link C++ class o2::ft0::CTFHeader + ; #pragma link C++ class o2::ft0::CompressedDigits + ; #pragma link C++ class o2::ft0::CTF + ; -#pragma link C++ class o2::ctf::EncodedBlocks < o2::ft0::CTFHeader, 8, uint32_t> + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::ft0::CTFHeader, 9, uint32_t> + ; #endif diff --git a/Detectors/CTF/test/test_ctf_io_ft0.cxx b/Detectors/CTF/test/test_ctf_io_ft0.cxx index 6570f7a02363e..a870b6549b16f 100644 --- a/Detectors/CTF/test/test_ctf_io_ft0.cxx +++ b/Detectors/CTF/test/test_ctf_io_ft0.cxx @@ -26,7 +26,6 @@ BOOST_AUTO_TEST_CASE(CTFTest) { std::vector<Digit> digits; std::vector<ChannelData> channels; - TStopwatch sw; sw.Start(); o2::InteractionRecord ir(0, 0); @@ -39,6 +38,7 @@ BOOST_AUTO_TEST_CASE(CTFTest) auto start = channels.size(); int32_t tMeanA = 0, tMeanC = 0; int32_t ampTotA = 0, ampTotC = 0; + uint8_t eventFlag = 10; Triggers trig; trig.triggersignals = gRandom->Integer(128); while (ich < MAXChan) { @@ -69,6 +69,7 @@ BOOST_AUTO_TEST_CASE(CTFTest) } auto end = channels.size(); digits.emplace_back(start, end - start, ir, trig, idig); + digits[idig].setEventStatus(eventFlag); } LOG(INFO) << "Generated " << channels.size() << " channels in " << digits.size() << " digits " << sw.CpuTime() << " s"; @@ -121,13 +122,13 @@ BOOST_AUTO_TEST_CASE(CTFTest) BOOST_CHECK(digitsD.size() == digits.size()); BOOST_CHECK(channelsD.size() == channels.size()); - LOG(INFO) << " BOOST_CHECK digitsD.size() " << digitsD.size() << " digits.size() " << digits.size() << " BOOST_CHECK(channelsD.size() " << channelsD.size() << " channels.size()) " << channels.size(); + LOG(DEBUG) << " BOOST_CHECK digitsD.size() " << digitsD.size() << " digits.size() " << digits.size() << " BOOST_CHECK(channelsD.size() " << channelsD.size() << " channels.size()) " << channels.size(); for (int i = digits.size(); i--;) { const auto& dor = digits[i]; const auto& ddc = digitsD[i]; - LOG(INFO) << " dor " << dor.mTriggers.nChanA << " " << dor.mTriggers.nChanC << " " << dor.mTriggers.amplA << " " << dor.mTriggers.amplC; - LOG(INFO) << " ddc " << ddc.mTriggers.nChanA << " " << ddc.mTriggers.nChanC << " " << ddc.mTriggers.amplA << " " << ddc.mTriggers.amplC; + LOG(DEBUG) << " dor " << dor.mTriggers.nChanA << " " << dor.mTriggers.nChanC << " " << dor.mTriggers.amplA << " " << dor.mTriggers.amplC; + LOG(DEBUG) << " ddc " << ddc.mTriggers.nChanA << " " << ddc.mTriggers.nChanC << " " << ddc.mTriggers.amplA << " " << ddc.mTriggers.amplC; BOOST_CHECK(dor.mIntRecord == ddc.mIntRecord); BOOST_CHECK(dor.mTriggers.nChanA == ddc.mTriggers.nChanA); diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h index 407fba225fc1d..5bb219a4b657e 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/DataBlockFT0.h @@ -55,6 +55,10 @@ class DataBlockPM : public DataBlockBase<DataBlockPM, RawHeaderPM, RawDataPM> // put here code for raw data checking void sanityCheck(bool& flag) { + if (DataBlockWrapper<RawDataPM>::mNelements == 0) { + flag = false; + return; + } if (DataBlockWrapper<RawDataPM>::mNelements % 2 == 0 && DataBlockWrapper<RawDataPM>::mData[DataBlockWrapper<RawDataPM>::mNelements - 1].channelID == 0) { DataBlockWrapper<RawDataPM>::mNelements--; //in case of half GBT-word filling } @@ -105,4 +109,4 @@ class DataBlockTCMext : public DataBlockBase<DataBlockTCMext, RawHeaderTCMext, R } // namespace ft0 } // namespace o2 -#endif \ No newline at end of file +#endif From a810af67fef7ae9769a272c53fb91fbaf9e1ed2d Mon Sep 17 00:00:00 2001 From: vfeuilla <71069003+vfeuilla@users.noreply.github.com> Date: Mon, 30 Nov 2020 08:13:04 +0100 Subject: [PATCH 1445/1751] Quick fix: change of trigger (#4932) Changing the trigger to kIsMuonUnlikeLowPt7, corresponding to CMUL7, which is the one used in dimuon analysis --- Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx index 5ce3dab9755ca..b6892f396099c 100644 --- a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -116,7 +116,7 @@ struct EventSelection { AnalysisCut* varCut = new AnalysisCut(); varCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); - varCut->AddCut(VarManager::kIsMuonSingleLowPt7, 0.5, 1.5); + varCut->AddCut(VarManager::kIsMuonUnlikeLowPt7, 0.5, 1.5); fEventCut->AddCut(varCut); // TODO: Add more cuts, also enable cuts which are not easily possible via the VarManager (e.g. trigger selections) From da9fe7180427a91b85e673cf7d5095b72b2a981a Mon Sep 17 00:00:00 2001 From: Jochen Klein <jochen.klein@cern.ch> Date: Thu, 26 Nov 2020 11:45:47 +0100 Subject: [PATCH 1446/1751] Fix geometry with ENABLE_UPGRADES - use new beampipe only when IT3 or IT4 are activated --- macro/build_geometry.C | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/macro/build_geometry.C b/macro/build_geometry.C index 60f63e53834ff..8e24bfb5853ee 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -127,7 +127,11 @@ void build_geometry(FairRunSim* run = nullptr) // beam pipe if (isActivated("PIPE")) { #ifdef ENABLE_UPGRADES - run->AddModule(new o2::passive::Pipe("PIPE", "Beam pipe", 1.6f, 0.05)); + if (isActivated("IT3") || isActivated("IT4")) { + run->AddModule(new o2::passive::Pipe("PIPE", "Beam pipe", 1.6f, 0.05)); + } else { + run->AddModule(new o2::passive::Pipe("PIPE", "Beam pipe")); + } #else run->AddModule(new o2::passive::Pipe("PIPE", "Beam pipe")); #endif From e496b024d3c4ce33a532ee79a408903b794987b9 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Sun, 29 Nov 2020 17:05:35 +0100 Subject: [PATCH 1447/1751] Revert "Exclude testCcdbApi_alien.cxx (#4941)" This reverts commit 71f34092d1fc30cf831ca5986fc203f3840b447a. --- CCDB/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CCDB/CMakeLists.txt b/CCDB/CMakeLists.txt index e6a985ea19d2b..a91a3aa31347e 100644 --- a/CCDB/CMakeLists.txt +++ b/CCDB/CMakeLists.txt @@ -51,11 +51,11 @@ o2_add_test(CcdbApi PUBLIC_LINK_LIBRARIES O2::CCDB LABELS ccdb) -#o2_add_test(CcdbApi-Alien -# SOURCES test/testCcdbApi_alien.cxx -# COMPONENT_NAME ccdb -# PUBLIC_LINK_LIBRARIES O2::CCDB -# LABELS ccdb) +o2_add_test(CcdbApi-Alien + SOURCES test/testCcdbApi_alien.cxx + COMPONENT_NAME ccdb + PUBLIC_LINK_LIBRARIES O2::CCDB + LABELS ccdb) o2_add_test(BasicCCDBManager SOURCES test/testBasicCCDBManager.cxx From 0cf8b27f618bd5b7ace910809a75ebadae6acd59 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 30 Nov 2020 14:36:05 +0100 Subject: [PATCH 1448/1751] Revert "Workaround for readability-braces-around-statements bug" This reverts commit 69cd85baa210249309b4e1c3c588781a7de1ad94. --- GPU/GPUTracking/Global/GPUChainTracking.h | 2 +- GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 6b89f3b25acd3..f9cb5022e9830 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -87,7 +87,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega InOutMemory(); ~InOutMemory(); InOutMemory(InOutMemory&&); - InOutMemory& operator=(InOutMemory&&) = default; + InOutMemory& operator=(InOutMemory&&); std::unique_ptr<unsigned long long int[]> tpcZSpages; std::unique_ptr<char[]> tpcZSpagesChar; // Same as above, but as char (needed for reading dumps, but deprecated, since alignment can be wrong) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index 9f0bcbb6fc2ec..e5127f94654b5 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -65,6 +65,7 @@ static constexpr char DUMP_HEADER[DUMP_HEADER_SIZE + 1] = "CAv1"; GPUChainTracking::InOutMemory::InOutMemory() = default; GPUChainTracking::InOutMemory::~InOutMemory() = default; GPUChainTracking::InOutMemory::InOutMemory(GPUChainTracking::InOutMemory&&) = default; +GPUChainTracking::InOutMemory& GPUChainTracking::InOutMemory::operator=(GPUChainTracking::InOutMemory&&) = default; void GPUChainTracking::DumpData(const char* filename) { From 703dc344c1852954644bd1557a8c969ba90425cc Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 30 Nov 2020 14:37:53 +0100 Subject: [PATCH 1449/1751] GPU: Disable clang-tidy on this line since it triggers a false positive --- GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index e5127f94654b5..ed94ad362d9c3 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -65,7 +65,7 @@ static constexpr char DUMP_HEADER[DUMP_HEADER_SIZE + 1] = "CAv1"; GPUChainTracking::InOutMemory::InOutMemory() = default; GPUChainTracking::InOutMemory::~InOutMemory() = default; GPUChainTracking::InOutMemory::InOutMemory(GPUChainTracking::InOutMemory&&) = default; -GPUChainTracking::InOutMemory& GPUChainTracking::InOutMemory::operator=(GPUChainTracking::InOutMemory&&) = default; +GPUChainTracking::InOutMemory& GPUChainTracking::InOutMemory::operator=(GPUChainTracking::InOutMemory&&) = default; // NOLINT: False positive in clang-tidy void GPUChainTracking::DumpData(const char* filename) { From 3f1f50ebc2d654da5c29cbc464541a43a031686a Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 30 Nov 2020 01:22:16 +0400 Subject: [PATCH 1450/1751] Use InputRecordWalker to scan all EMC links --- Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index 9a4b6b1dea0a2..02edf76d04207 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -13,6 +13,7 @@ #include "CommonDataFormat/InteractionRecord.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/InputRecordWalker.h" #include "Framework/ControlService.h" #include "Framework/WorkflowSpec.h" #include "DataFormatsEMCAL/EMCALBlockHeader.h" @@ -68,8 +69,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) std::map<o2::InteractionRecord, std::shared_ptr<std::vector<o2::emcal::Cell>>> cellBuffer; // Internal cell buffer int firstEntry = 0; - for (const auto& rawData : ctx.inputs()) { - + for (const auto& rawData : framework::InputRecordWalker(ctx.inputs())) { //o2::emcal::RawReaderMemory<o2::header::RAWDataHeaderV4> rawreader(gsl::span(rawData.payload, o2::framework::DataRefUtils::getPayloadSize(rawData))); o2::emcal::RawReaderMemory rawreader(o2::framework::DataRefUtils::as<const char>(rawData)); From ddcda5b3e0e6e91790dcc3552ba06b5a1183e7c3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 30 Nov 2020 20:34:54 +0100 Subject: [PATCH 1451/1751] DPL Analysis: disable TTreeCache (#4954) Seems to save around 30MB of RSS with the same number of reads. --- Framework/Core/src/AODReaderHelpers.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 9a0289a955596..5b7ebb5ba3e05 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -283,6 +283,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() throw std::runtime_error("Processing is stopped!"); } } + tr->SetCacheSize(0); if (first) { timeFrameNumber = didir->getTimeFrameNumber(dh, fcnt, ntf); auto o = Output(TFNumberHeader); From cab9211f388800813acf7fda5e22a179f347f7cd Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <maximiliano.puccio@cern.ch> Date: Mon, 30 Nov 2020 18:38:43 +0100 Subject: [PATCH 1452/1751] Fix hip compilation for ITS vertexer --- .../ITStrackingHIP/DeviceStoreVertexerHIP.h | 2 +- .../ITStrackingHIP/VertexerTraitsHIP.h | 4 +- .../hip/src/DeviceStoreVertexerHIP.hip.cxx | 4 +- .../hip/src/VertexerTraitsHIP.hip.cxx | 37 ++++++++++++++----- .../tracking/include/ITStracking/Constants.h | 17 +++++---- 5 files changed, 42 insertions(+), 22 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h index 8b41060de7728..417eb965c8c20 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h @@ -55,7 +55,7 @@ class DeviceStoreVertexerHIP final ~DeviceStoreVertexerHIP() = default; UniquePointer<DeviceStoreVertexerHIP> initialise(const std::array<std::vector<Cluster>, constants::its::LayersNumberVertexer>&, - const std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, + const std::array<std::array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, constants::its::LayersNumberVertexer>&); // RO APIs diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h index 355b1243c127f..6ba9d8e08bb1e 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h @@ -37,7 +37,7 @@ namespace its { class ROframe; -using constants::index_table::InversePhiBinSize; +using constants::its2::InversePhiBinSize; class VertexerTraitsHIP : public VertexerTraits { @@ -73,7 +73,7 @@ class VertexerTraitsHIP : public VertexerTraits GPUdi() const int2 VertexerTraitsHIP::getBinsPhiRectWindow(const Cluster& currentCluster, float phiCut) { // This function returns the lowest PhiBin and the number of phi bins to be spanned, In the form int2{phiBinLow, PhiBinSpan} - const int phiBinMin{index_table_utils::getPhiBinIndex( + const int phiBinMin{constants::its2::getPhiBinIndex( math_utils::getNormalizedPhiCoordinate(currentCluster.phiCoordinate - phiCut))}; const int phiBinSpan{static_cast<int>(MATH_CEIL(phiCut * InversePhiBinSize))}; return int2{phiBinMin, phiBinSpan}; diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx index 39a05cfecb033..b0546b19da72e 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx @@ -47,7 +47,7 @@ DeviceStoreVertexerHIP::DeviceStoreVertexerHIP() mBeamPosition = VectorHIP<float>{2, 2}; for (int iTable{0}; iTable < 2; ++iTable) { - mIndexTables[iTable] = VectorHIP<int>{constants::index_table::ZBins * constants::index_table::PhiBins + 1}; // 2*20*20+1 * sizeof(int) = 802B + mIndexTables[iTable] = VectorHIP<int>{constants::its2::ZBins * constants::its2::PhiBins + 1}; // 2*20*20+1 * sizeof(int) = 802B } for (int iLayer{0}; iLayer < constants::its::LayersNumberVertexer; ++iLayer) { // 4e4 * 3 * sizof(Cluster) = 3.36MB mClusters[iLayer] = VectorHIP<Cluster>{mGPUConf.clustersPerLayerCapacity, mGPUConf.clustersPerLayerCapacity}; @@ -68,7 +68,7 @@ DeviceStoreVertexerHIP::DeviceStoreVertexerHIP() } // namespace GPU UniquePointer<DeviceStoreVertexerHIP> DeviceStoreVertexerHIP::initialise(const std::array<std::vector<Cluster>, constants::its::LayersNumberVertexer>& clusters, - const std::array<std::array<int, constants::index_table::ZBins * constants::index_table::PhiBins + 1>, + const std::array<std::array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, constants::its::LayersNumberVertexer>& indexTables) { #ifdef _ALLOW_DEBUG_TREES_ITS_ diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx index 425d7c04d98d5..b159d3f758935 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx @@ -34,16 +34,35 @@ namespace o2 namespace its { -using constants::index_table::PhiBins; -using constants::index_table::ZBins; -using constants::its::LayersRCoordinate; -using constants::its::LayersZCoordinate; using constants::its::VertexerHistogramVolume; +using constants::its2::getPhiBinIndex; +using constants::its2::getZBinIndex; +using constants::its2::LayersRCoordinate; +using constants::its2::LayersZCoordinate; +using constants::its2::PhiBins; +using constants::its2::ZBins; using constants::math::TwoPi; -using index_table_utils::getPhiBinIndex; -using index_table_utils::getZBinIndex; using math_utils::getNormalizedPhiCoordinate; +GPUhd() const int4 getBinsRect(const Cluster& currentCluster, const int layerIndex, + const float z1, float maxdeltaz, float maxdeltaphi) +{ + const float zRangeMin = z1 - maxdeltaz; + const float phiRangeMin = currentCluster.phiCoordinate - maxdeltaphi; + const float zRangeMax = z1 + maxdeltaz; + const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; + + if (zRangeMax < -LayersZCoordinate()[layerIndex + 1] || + zRangeMin > LayersZCoordinate()[layerIndex + 1] || zRangeMin > zRangeMax) { + return constants::its2::getEmptyBinsRect(); + } + + return int4{gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), + getPhiBinIndex(phiRangeMin), + gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), + getPhiBinIndex(phiRangeMax)}; +} + GPUh() void gpuThrowOnError() { hipError_t error = hipGetLastError(); @@ -79,7 +98,7 @@ void VertexerTraitsHIP::initialise(ROframe* event) { reset(); arrangeClusters(event); - mStoreVertexerGPUPtr = mStoreVertexerGPU.initialise(mClusters, mIndexTables); + // mStoreVertexerGPUPtr = mStoreVertexerGPU.initialise(mClusters, mIndexTables); } namespace GPU @@ -144,7 +163,7 @@ GPUg() void trackleterKernel( const unsigned int stride{currentClusterIndex * store->getConfig().maxTrackletsPerCluster}; const Cluster& currentCluster = store->getClusters()[1][currentClusterIndex]; // assign-constructor may be a problem, check const VertexerLayerName adjacentLayerIndex{layerOrder == TrackletingLayerOrder::fromInnermostToMiddleLayer ? VertexerLayerName::innermostLayer : VertexerLayerName::outerLayer}; - const int4 selectedBinsRect{VertexerTraits::getBinsRect(currentCluster, static_cast<int>(adjacentLayerIndex), 0.f, 50.f, phiCut / 2)}; + const int4 selectedBinsRect{getBinsRect(currentCluster, static_cast<int>(adjacentLayerIndex), 0.f, 50.f, phiCut / 2)}; if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) { int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; if (phiBinsNum < 0) { @@ -152,7 +171,7 @@ GPUg() void trackleterKernel( } const int nClustersAdjacentLayer = store->getClusters()[static_cast<int>(adjacentLayerIndex)].size(); for (size_t iPhiBin{static_cast<size_t>(selectedBinsRect.y)}, iPhiCount{0}; (int)iPhiCount < phiBinsNum; iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) { - const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect.x, iPhiBin)}; + const int firstBinIndex{constants::its2::getBinIndex(selectedBinsRect.x, iPhiBin)}; const int firstRowClusterIndex{store->getIndexTable(adjacentLayerIndex)[firstBinIndex]}; const int maxRowClusterIndex{store->getIndexTable(adjacentLayerIndex)[firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1]}; for (int iAdjacentCluster{firstRowClusterIndex}; iAdjacentCluster < maxRowClusterIndex && iAdjacentCluster < nClustersAdjacentLayer; ++iAdjacentCluster) { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index 40cdc77f185c5..a14feb19203dc 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -22,6 +22,7 @@ #include "ITStracking/Definitions.h" #include "GPUCommonMath.h" +#include "GPUCommonDef.h" namespace o2 { @@ -47,7 +48,7 @@ constexpr int ClustersPerCell{3}; constexpr int UnusedIndex{-1}; constexpr float Resolution{0.0005f}; -GPU_HOST_DEVICE constexpr GPUArray<float, 3> VertexerHistogramVolume() +GPUhdi() constexpr GPUArray<float, 3> VertexerHistogramVolume() { return GPUArray<float, 3>{{1.98, 1.98, 40.f}}; } @@ -59,12 +60,12 @@ constexpr int LayersNumber{7}; constexpr int TrackletsPerRoad{LayersNumber - 1}; constexpr int CellsPerRoad{LayersNumber - 2}; -GPU_HOST_DEVICE constexpr GPUArray<float, LayersNumber> LayersZCoordinate() +GPUhdi() constexpr GPUArray<float, LayersNumber> LayersZCoordinate() { constexpr double s = 1.; // safety margin return GPUArray<float, LayersNumber>{{16.333f + s, 16.333f + s, 16.333f + s, 42.140f + s, 42.140f + s, 73.745f + s, 73.745f + s}}; } -GPU_HOST_DEVICE constexpr GPUArray<float, LayersNumber> LayersRCoordinate() +GPUhdi() constexpr GPUArray<float, LayersNumber> LayersRCoordinate() { return GPUArray<float, LayersNumber>{{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}}; } @@ -72,7 +73,7 @@ GPU_HOST_DEVICE constexpr GPUArray<float, LayersNumber> LayersRCoordinate() constexpr int ZBins{256}; constexpr int PhiBins{128}; constexpr float InversePhiBinSize{PhiBins / constants::math::TwoPi}; -GPU_HOST_DEVICE constexpr GPUArray<float, LayersNumber> InverseZBinSize() +GPUhdi() constexpr GPUArray<float, LayersNumber> InverseZBinSize() { constexpr auto zSize = LayersZCoordinate(); return GPUArray<float, LayersNumber>{{0.5f * ZBins / (zSize[0]), 0.5f * ZBins / (zSize[1]), 0.5f * ZBins / (zSize[2]), @@ -84,24 +85,24 @@ inline float getInverseZCoordinate(const int layerIndex) return 0.5f * ZBins / LayersZCoordinate()[layerIndex]; } -GPU_HOST_DEVICE inline int getZBinIndex(const int layerIndex, const float zCoordinate) +GPUhdi() int getZBinIndex(const int layerIndex, const float zCoordinate) { return (zCoordinate + LayersZCoordinate()[layerIndex]) * InverseZBinSize()[layerIndex]; } -GPU_HOST_DEVICE inline int getPhiBinIndex(const float currentPhi) +GPUhdi() int getPhiBinIndex(const float currentPhi) { return (currentPhi * InversePhiBinSize); } -GPU_HOST_DEVICE inline int getBinIndex(const int zIndex, const int phiIndex) +GPUhdi() int getBinIndex(const int zIndex, const int phiIndex) { return gpu::GPUCommonMath::Min(phiIndex * ZBins + zIndex, ZBins * PhiBins - 1); } -GPU_HOST_DEVICE constexpr int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } +GPUhdi() constexpr int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } } // namespace its2 From 8e9fde097acf5bc741bada210584e866adbc8049 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 30 Nov 2020 08:51:19 +0100 Subject: [PATCH 1453/1751] SpaceCharge: avoid copy/return by reference --- .../TPC/simulation/include/TPCSimulation/SpaceCharge.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h b/Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h index 63dbcef7983db..8b68c733b3766 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h @@ -163,9 +163,9 @@ class SpaceCharge double getVoxelSizePhi() const { return mVoxelSizePhi; } double getVoxelSizeR() const { return mVoxelSizeR; } double getVoxelSizeZ() const { return mVoxelSizeZ; } - std::vector<double> getCoordinatesPhi() const { return mCoordPhi; } - std::vector<double> getCoordinatesR() const { return mCoordR; } - std::vector<double> getCoordinatesZ() const { return mCoordZ; } + std::vector<double> const& getCoordinatesPhi() const { return mCoordPhi; } + std::vector<double> const& getCoordinatesR() const { return mCoordR; } + std::vector<double> const& getCoordinatesZ() const { return mCoordZ; } void setUseIrregularLUTs(int useIrrLUTs); void setUseFastDistIntegration(int useFastInt); From d9eacea6f6c9aea052139780c4b1a89c710d5533 Mon Sep 17 00:00:00 2001 From: ppillot <pillot@subatech.in2p3.fr> Date: Thu, 5 Nov 2020 11:37:01 +0100 Subject: [PATCH 1454/1751] add some linkup --- Detectors/MUON/MCH/Workflow/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/MUON/MCH/Workflow/README.md b/Detectors/MUON/MCH/Workflow/README.md index 1ed6fd6dd6bd8..9e6c8fb179ded 100644 --- a/Detectors/MUON/MCH/Workflow/README.md +++ b/Detectors/MUON/MCH/Workflow/README.md @@ -119,7 +119,7 @@ where `tracks.in` is a binary file with the same format as the one written by th Send the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) in two separate messages with the data description "TRACKS" and "TRACKCLUSTERS", respectively. -Option `--forTrackFitter` allows to send the messages with the data description "TRACKSIN" and "TRACKCLUSTERSIN", respectively, as expected by the workflow `o2-mch-tracks-to-tracks-workflow` described below. +Option `--forTrackFitter` allows to send the messages with the data description "TRACKSIN" and "TRACKCLUSTERSIN", respectively, as expected by the workflow [o2-mch-tracks-to-tracks-workflow](#track-fitter). ### Vertex sampler @@ -146,12 +146,12 @@ If no binary file is provided, the vertex is always set to (0,0,0). `o2-mch-tracks-sink-workflow --outfile "tracks.out"` -Take as input the list of tracks at vertex (`TrackAtVtxStruct` as described above), the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description "TRACKSATVERTEX", "TRACKS" and "TRACKCLUSTERS", respectively, and write them in the binary file `tracks.out` with the following format: +Take as input the list of tracks at vertex ([TrackAtVtxStruct](#track-extrapolation-to-vertex)), the list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) and the list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) of the current event with the data description "TRACKSATVERTEX", "TRACKS" and "TRACKCLUSTERS", respectively, and write them in the binary file `tracks.out` with the following format: * number of tracks at vertex (int) * number of MCH tracks (int) * number of associated clusters (int) -* list of tracks at vertex (`TrackAtVtxStruct` as described above) +* list of tracks at vertex ([TrackAtVtxStruct](#track-extrapolation-to-vertex)) * list of MCH tracks ([TrackMCH](../../../../DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/TrackMCH.h)) * list of associated clusters ([ClusterStruct](../Base/include/MCHBase/ClusterBlock.h)) From b43bc19d5b361d8d02797adfd4302365c5e6333a Mon Sep 17 00:00:00 2001 From: ppillot <pillot@subatech.in2p3.fr> Date: Mon, 30 Nov 2020 14:45:24 +0100 Subject: [PATCH 1455/1751] enable track refinement with different cluster resolution --- .../include/MCHTracking/TrackExtrap.h | 2 +- .../include/MCHTracking/TrackFinder.h | 22 +++++- .../include/MCHTracking/TrackFinderOriginal.h | 27 +++++-- .../include/MCHTracking/TrackFitter.h | 23 +++++- .../MUON/MCH/Tracking/src/TrackFinder.cxx | 53 ++++++++++--- .../MCH/Tracking/src/TrackFinderOriginal.cxx | 76 ++++++++++++++----- .../MUON/MCH/Tracking/src/TrackFitter.cxx | 40 +++++++--- .../MCH/Workflow/src/ClusterSamplerSpec.cxx | 4 - .../Workflow/src/TrackFinderOriginalSpec.cxx | 4 + .../MUON/MCH/Workflow/src/TrackFinderSpec.cxx | 4 + 10 files changed, 198 insertions(+), 57 deletions(-) diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackExtrap.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackExtrap.h index 659f6fe0f68b7..431353bb27249 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackExtrap.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackExtrap.h @@ -46,7 +46,7 @@ class TrackExtrap static bool isFieldON() { return sFieldON; } /// Switch to Runge-Kutta extrapolation v2 - static void useExtrapV2() { sExtrapV2 = true; } + static void useExtrapV2(bool extrapV2 = true) { sExtrapV2 = extrapV2; } static double getImpactParamFromBendingMomentum(double bendingMomentum); static double getBendingMomentumFromImpactParam(double impactParam); diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinder.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinder.h index 6970810810665..1680b9eae2165 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinder.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinder.h @@ -52,6 +52,9 @@ class TrackFinder /// set the flag to try to find more track candidates starting from 1 cluster in each of station (1..) 4 and 5 void findMoreTrackCandidates(bool moreCandidates) { mMoreCandidates = moreCandidates; } + /// set the flag to refine the tracks in the end using cluster resolution + void refineTracks(bool refine) { mRefineTracks = refine; } + /// set the debug level defining the verbosity void debug(int debugLevel) { mDebugLevel = debugLevel; } @@ -80,6 +83,8 @@ class TrackFinder void removeConnectedTracks(int stMin, int stMax); + void refineTracks(); + void finalize(); void createTrack(const Cluster& cl1, const Cluster& cl2); @@ -113,6 +118,15 @@ class TrackFinder /// return the chamber to which this plane belong to int getChamberId(int plane) { return (plane < 8) ? plane / 2 : 4 + (plane - 8) / 4; } + /// return the chamber resolution square in x direction + static constexpr double chamberResolutionX2() { return SChamberResolutionX * SChamberResolutionX; } + /// return the chamber resolution square in y direction + static constexpr double chamberResolutionY2() { return SChamberResolutionY * SChamberResolutionY; } + + /// chamber resolution in x direction used as cluster resolution during tracking + static constexpr double SChamberResolutionX = 0.2; + /// chamber resolution in y direction used as cluster resolution during tracking + static constexpr double SChamberResolutionY = 0.2; /// sigma cut to select clusters (local chi2) and tracks (global chi2) during tracking static constexpr double SSigmaCutForTracking = 5.; /// sigma cut to select clusters (local chi2) and tracks (global chi2) during improvement @@ -125,8 +139,8 @@ class TrackFinder static constexpr double SBendingVertexDispersion = 70.; ///< vertex dispersion (cm) in bending plane static constexpr double SMinBendingMomentum = 0.8; ///< minimum value (GeV/c) of momentum in bending plane /// z position of the chambers - static constexpr float SDefaultChamberZ[10] = {-526.16, -545.24, -676.4, -695.4, -967.5, - -998.5, -1276.5, -1307.5, -1406.6, -1437.6}; + static constexpr double SDefaultChamberZ[10] = {-526.16, -545.24, -676.4, -695.4, -967.5, + -998.5, -1276.5, -1307.5, -1406.6, -1437.6}; /// default chamber thickness in X0 for reconstruction static constexpr double SChamberThicknessInX0[10] = {0.065, 0.065, 0.075, 0.075, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035}; @@ -142,7 +156,8 @@ class TrackFinder double mMaxMCSAngle2[10]{}; ///< maximum angle dispersion due to MCS - bool mMoreCandidates = false; ///< try to find more track candidates starting from 1 cluster in each of station (1..) 4 and 5 + bool mMoreCandidates = false; ///< find more track candidates starting from 1 cluster in each of station (1..) 4 and 5 + bool mRefineTracks = true; ///< refine the tracks in the end using cluster resolution int mDebugLevel = 0; ///< debug level defining the verbosity @@ -155,6 +170,7 @@ class TrackFinder std::chrono::duration<double> mTimeFollowTracks{}; ///< timer std::chrono::duration<double> mTimeImproveTracks{}; ///< timer std::chrono::duration<double> mTimeCleanTracks{}; ///< timer + std::chrono::duration<double> mTimeRefineTracks{}; ///< timer }; } // namespace mch diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinderOriginal.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinderOriginal.h index f2c412c65d0a4..bfe1145b373a2 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinderOriginal.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFinderOriginal.h @@ -45,6 +45,9 @@ class TrackFinderOriginal /// set the flag to try to find more track candidates starting from 1 cluster in each of station (1..) 4 and 5 void findMoreTrackCandidates(bool moreCandidates) { mMoreCandidates = moreCandidates; } + /// set the flag to refine the tracks in the end using cluster resolution + void refineTracks(bool refine) { mRefineTracks = refine; } + /// set the debug level defining the verbosity void debug(int debugLevel) { mDebugLevel = debugLevel; } @@ -70,6 +73,7 @@ class TrackFinderOriginal std::list<Track>::iterator recoverTrack(std::list<Track>::iterator& itTrack, int nextStation); bool completeTracks(); void improveTracks(); + void refineTracks(); void finalize(); uint8_t requestedStationMask() const; int getTrackIndex(const std::list<Track>::iterator& itCurrentTrack) const; @@ -78,24 +82,33 @@ class TrackFinderOriginal template <class... Args> void print(Args... args) const; + /// return the chamber resolution square in x direction + static constexpr double chamberResolutionX2() { return SChamberResolutionX * SChamberResolutionX; } + /// return the chamber resolution square in y direction + static constexpr double chamberResolutionY2() { return SChamberResolutionY * SChamberResolutionY; } + + /// chamber resolution in x direction used as cluster resolution during tracking + static constexpr double SChamberResolutionX = 0.2; + /// chamber resolution in y direction used as cluster resolution during tracking + static constexpr double SChamberResolutionY = 0.2; /// sigma cut to select clusters (local chi2) and tracks (global chi2) during tracking static constexpr double SSigmaCutForTracking = 5.; /// sigma cut to select clusters (local chi2) and tracks (global chi2) during improvement static constexpr double SSigmaCutForImprovement = 4.; - ///< maximum distance to the track to search for compatible cluster(s) in non bending direction + /// maximum distance to the track to search for compatible cluster(s) in non bending direction static constexpr double SMaxNonBendingDistanceToTrack = 1.; - ///< maximum distance to the track to search for compatible cluster(s) in bending direction + /// maximum distance to the track to search for compatible cluster(s) in bending direction static constexpr double SMaxBendingDistanceToTrack = 1.; static constexpr double SNonBendingVertexDispersion = 70.; ///< vertex dispersion (cm) in non bending plane static constexpr double SBendingVertexDispersion = 70.; ///< vertex dispersion (cm) in bending plane static constexpr double SMinBendingMomentum = 0.8; ///< minimum value (GeV/c) of momentum in bending plane /// z position of the chambers - static constexpr float SDefaultChamberZ[10] = {-526.16, -545.24, -676.4, -695.4, -967.5, - -998.5, -1276.5, -1307.5, -1406.6, -1437.6}; + static constexpr double SDefaultChamberZ[10] = {-526.16, -545.24, -676.4, -695.4, -967.5, + -998.5, -1276.5, -1307.5, -1406.6, -1437.6}; /// default chamber thickness in X0 for reconstruction static constexpr double SChamberThicknessInX0[10] = {0.065, 0.065, 0.075, 0.075, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035}; - ///< if true, at least one cluster in the station is requested to validate the track + /// if true, at least one cluster in the station is requested to validate the track static constexpr bool SRequestStation[5] = {true, true, true, true, true}; TrackFitter mTrackFitter{}; /// track fitter @@ -105,7 +118,8 @@ class TrackFinderOriginal double mMaxMCSAngle2[10]{}; ///< maximum angle dispersion due to MCS - bool mMoreCandidates = false; ///< try to find more track candidates starting from 1 cluster in each of station (1..) 4 and 5 + bool mMoreCandidates = false; ///< find more track candidates starting from 1 cluster in each of station (1..) 4 and 5 + bool mRefineTracks = true; ///< refine the tracks in the end using cluster resolution int mDebugLevel = 0; ///< debug level defining the verbosity @@ -119,6 +133,7 @@ class TrackFinderOriginal std::chrono::duration<double> mTimeCompleteTracks{}; ///< timer std::chrono::duration<double> mTimeImproveTracks{}; ///< timer std::chrono::duration<double> mTimeCleanTracks{}; ///< timer + std::chrono::duration<double> mTimeRefineTracks{}; ///< timer }; } // namespace mch diff --git a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFitter.h b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFitter.h index 1f95cd4d25385..2e523540f7a22 100644 --- a/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFitter.h +++ b/Detectors/MUON/MCH/Tracking/include/MCHTracking/TrackFitter.h @@ -44,6 +44,13 @@ class TrackFitter /// Return the smoother enable/disable flag bool isSmootherEnabled() { return mSmooth; } + /// Use the own resolution of each cluster during the fit (default) + void useClusterResolution() { mUseChamberResolution = false; } + /// Use the chamber resolution instead of cluster resolution during the fit + void useChamberResolution() { mUseChamberResolution = true; } + // Set the chamber resolution in x and y directions + void setChamberResolution(double ex, double ey); + void fit(Track& track, bool smooth = true, bool finalize = true, std::list<TrackParam>::reverse_iterator* itStartingParam = nullptr); @@ -61,15 +68,27 @@ class TrackFitter static constexpr double SMaxChi2 = 2.e10; ///< maximum chi2 above which the track can be considered as abnormal static constexpr double SBendingVertexDispersion = 70.; ///< vertex dispersion (cm) in bending plane /// z position of the chambers - static constexpr float SDefaultChamberZ[10] = {-526.16, -545.24, -676.4, -695.4, -967.5, - -998.5, -1276.5, -1307.5, -1406.6, -1437.6}; + static constexpr double SDefaultChamberZ[10] = {-526.16, -545.24, -676.4, -695.4, -967.5, + -998.5, -1276.5, -1307.5, -1406.6, -1437.6}; /// default chamber thickness in X0 for reconstruction static constexpr double SChamberThicknessInX0[10] = {0.065, 0.065, 0.075, 0.075, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035}; bool mSmooth = false; ///< switch ON/OFF the smoother + + bool mUseChamberResolution = false; ///< switch between using chamber or cluster resolution + double mChamberResolutionX2 = 0.04; ///< chamber resolution square in x direction + double mChamberResolutionY2 = 0.04; ///< chamber resolution square in y direction }; +//_________________________________________________________________________________________________ +inline void TrackFitter::setChamberResolution(double ex, double ey) +{ + /// Set the chamber resolution in x and y directions + mChamberResolutionX2 = ex * ex; + mChamberResolutionY2 = ey * ey; +} + } // namespace mch } // namespace o2 diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx index c5db52bf5246c..19c5177a68165 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx @@ -33,7 +33,7 @@ namespace mch using namespace std; -constexpr float TrackFinder::SDefaultChamberZ[10]; +constexpr double TrackFinder::SDefaultChamberZ[10]; constexpr double TrackFinder::SChamberThicknessInX0[10]; constexpr bool TrackFinder::SRequestStation[5]; constexpr int TrackFinder::SNDE[10]; @@ -49,6 +49,9 @@ void TrackFinder::init(float l3Current, float dipoleCurrent) // enable the track smoother mTrackFitter.smoothTracks(true); + // set the chamber resolution used for fitting the tracks during the tracking + mTrackFitter.setChamberResolution(SChamberResolutionX, SChamberResolutionY); + // use the Runge-Kutta extrapolation v2 TrackExtrap::useExtrapV2(); @@ -147,6 +150,9 @@ const std::list<Track>& TrackFinder::findTracks(const std::unordered_map<int, st } } + // use the chamber resolution when fitting the tracks during the tracking + mTrackFitter.useChamberResolution(); + // find track candidates on stations 4 and 5 auto tStart = std::chrono::high_resolution_clock::now(); findTrackCandidates(); @@ -181,14 +187,22 @@ const std::list<Track>& TrackFinder::findTracks(const std::unordered_map<int, st tEnd = std::chrono::high_resolution_clock::now(); mTimeImproveTracks += tEnd - tStart; - // Remove connected tracks in stations(1..) 3, 4 and 5 + // remove connected tracks in stations(1..) 3, 4 and 5 tStart = std::chrono::high_resolution_clock::now(); removeConnectedTracks(2, 4); tEnd = std::chrono::high_resolution_clock::now(); mTimeCleanTracks += tEnd - tStart; - // Set the final track parameters and covariances - finalize(); + // refine the tracks using cluster resolution or just finalize them + if (mRefineTracks) { + tStart = std::chrono::high_resolution_clock::now(); + mTrackFitter.useClusterResolution(); + refineTracks(); + tEnd = std::chrono::high_resolution_clock::now(); + mTimeRefineTracks += tEnd - tStart; + } else { + finalize(); + } return mTracks; } @@ -628,7 +642,7 @@ std::list<Track>::iterator TrackFinder::findTrackCandidates(int plane1, int plan // check if non bending impact parameter is within tolerances double nonBendingSlope = (cluster1.getX() - cluster2.getX()) / dZ; double nonBendingImpactParam = TMath::Abs(cluster1.getX() - cluster1.getZ() * nonBendingSlope); - double nonBendingImpactParamErr = TMath::Sqrt((z1 * z1 * cluster2.getEx2() + z2 * z2 * cluster1.getEx2()) / dZ / dZ + impactMCS2); + double nonBendingImpactParamErr = TMath::Sqrt((z1 * z1 * chamberResolutionX2() + z2 * z2 * chamberResolutionX2()) / dZ / dZ + impactMCS2); if ((nonBendingImpactParam - SSigmaCutForTracking * nonBendingImpactParamErr) > (3. * SNonBendingVertexDispersion)) { continue; } @@ -637,7 +651,7 @@ std::list<Track>::iterator TrackFinder::findTrackCandidates(int plane1, int plan if (TrackExtrap::isFieldON()) { // depending whether the field is ON or OFF // check if bending momentum is within tolerances double bendingImpactParam = cluster1.getY() - cluster1.getZ() * bendingSlope; - double bendingImpactParamErr2 = (z1 * z1 * cluster2.getEy2() + z2 * z2 * cluster1.getEy2()) / dZ / dZ + impactMCS2; + double bendingImpactParamErr2 = (z1 * z1 * chamberResolutionY2() + z2 * z2 * chamberResolutionY2()) / dZ / dZ + impactMCS2; double bendingMomentum = TMath::Abs(TrackExtrap::getBendingMomentumFromImpactParam(bendingImpactParam)); double bendingMomentumErr = TMath::Sqrt((bendingVertexDispersion2 + bendingImpactParamErr2) / bendingImpactParam / bendingImpactParam + 0.01) * bendingMomentum; if ((bendingMomentum + 3. * bendingMomentumErr) < SMinBendingMomentum) { @@ -646,7 +660,7 @@ std::list<Track>::iterator TrackFinder::findTrackCandidates(int plane1, int plan } else { // or check if bending impact parameter is within tolerances double bendingImpactParam = TMath::Abs(cluster1.getY() - cluster1.getZ() * bendingSlope); - double bendingImpactParamErr = TMath::Sqrt((z1 * z1 * cluster2.getEy2() + z2 * z2 * cluster1.getEy2()) / dZ / dZ + impactMCS2); + double bendingImpactParamErr = TMath::Sqrt((z1 * z1 * chamberResolutionY2() + z2 * z2 * chamberResolutionY2()) / dZ / dZ + impactMCS2); if ((bendingImpactParam - SSigmaCutForTracking * bendingImpactParamErr) > (3. * SBendingVertexDispersion)) { continue; } @@ -1222,6 +1236,22 @@ void TrackFinder::removeConnectedTracks(int stMin, int stMax) } } +//_________________________________________________________________________________________________ +void TrackFinder::refineTracks() +{ + /// Refit, smooth and finalize the reconstructed tracks + + for (auto itTrack = mTracks.begin(); itTrack != mTracks.end();) { + try { + mTrackFitter.fit(*itTrack); + ++itTrack; + } catch (exception const&) { + print("refineTracks: removing candidate at position #", getTrackIndex(itTrack)); + itTrack = mTracks.erase(itTrack); + } + } +} + //_________________________________________________________________________________________________ void TrackFinder::finalize() { @@ -1489,8 +1519,8 @@ bool TrackFinder::tryOneClusterFast(const TrackParam& param, const Cluster& clus double dX = cluster.getX() - (param.getNonBendingCoor() + param.getNonBendingSlope() * dZ); double dY = cluster.getY() - (param.getBendingCoor() + param.getBendingSlope() * dZ); const TMatrixD& paramCov = param.getCovariances(); - double errX2 = paramCov(0, 0) + dZ * dZ * paramCov(1, 1) + 2. * dZ * paramCov(0, 1) + cluster.getEx2(); - double errY2 = paramCov(2, 2) + dZ * dZ * paramCov(3, 3) + 2. * dZ * paramCov(2, 3) + cluster.getEy2(); + double errX2 = paramCov(0, 0) + dZ * dZ * paramCov(1, 1) + 2. * dZ * paramCov(0, 1) + chamberResolutionX2(); + double errY2 = paramCov(2, 2) + dZ * dZ * paramCov(3, 3) + 2. * dZ * paramCov(2, 3) + chamberResolutionY2(); double dXmax = SSigmaCutForTracking * TMath::Sqrt(2. * errX2) + SMaxNonBendingDistanceToTrack; double dYmax = SSigmaCutForTracking * TMath::Sqrt(2. * errY2) + SMaxBendingDistanceToTrack; @@ -1524,8 +1554,8 @@ double TrackFinder::tryOneCluster(const TrackParam& param, const Cluster& cluste // Combine the cluster and track resolutions and covariances const TMatrixD& paramCov = paramAtCluster.getCovariances(); - double sigmaX2 = paramCov(0, 0) + cluster.getEx2(); - double sigmaY2 = paramCov(2, 2) + cluster.getEy2(); + double sigmaX2 = paramCov(0, 0) + chamberResolutionX2(); + double sigmaY2 = paramCov(2, 2) + chamberResolutionY2(); double covXY = paramCov(0, 2); double det = sigmaX2 * sigmaY2 - covXY * covXY; @@ -1635,6 +1665,7 @@ void TrackFinder::printTimers() const LOG(INFO) << "followTracks duration = " << mTimeFollowTracks.count() << " s"; LOG(INFO) << "improveTracks duration = " << mTimeImproveTracks.count() << " s"; LOG(INFO) << "removeConnectedTracks duration = " << mTimeCleanTracks.count() << " s"; + LOG(INFO) << "refineTracks duration = " << mTimeRefineTracks.count() << " s"; } } // namespace mch diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx index 2af108313e62d..b032bb5813e37 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx @@ -32,7 +32,7 @@ namespace mch using namespace std; -constexpr float TrackFinderOriginal::SDefaultChamberZ[10]; +constexpr double TrackFinderOriginal::SDefaultChamberZ[10]; constexpr double TrackFinderOriginal::SChamberThicknessInX0[10]; constexpr bool TrackFinderOriginal::SRequestStation[5]; @@ -47,6 +47,9 @@ void TrackFinderOriginal::init(float l3Current, float dipoleCurrent) // Enable the track smoother mTrackFitter.smoothTracks(true); + // Set the chamber resolution used for fitting the tracks during the tracking + mTrackFitter.setChamberResolution(SChamberResolutionX, SChamberResolutionY); + // Set the maximum MCS angle in chamber from the minimum acceptable momentum TrackParam param{}; double inverseBendingP = (SMinBendingMomentum > 0.) ? 1. / SMinBendingMomentum : 1.; @@ -59,12 +62,15 @@ void TrackFinderOriginal::init(float l3Current, float dipoleCurrent) //_________________________________________________________________________________________________ const std::list<Track>& TrackFinderOriginal::findTracks(const std::array<std::list<Cluster>, 10>* clusters) { - /// Run the orginal track finder algorithm + /// Run the original track finder algorithm print("\n------------------ Start the original track finder ------------------"); mClusters = clusters; mTracks.clear(); + // Use the chamber resolution when fitting the tracks during the tracking + mTrackFitter.useChamberResolution(); + // Look for candidates from clusters in stations(1..) 4 and 5 print("\n--> Step 1: find track candidates\n"); auto tStart = std::chrono::high_resolution_clock::now(); @@ -117,13 +123,18 @@ const std::list<Track>& TrackFinderOriginal::findTracks(const std::array<std::li tEnd = std::chrono::high_resolution_clock::now(); mTimeCleanTracks += tEnd - tStart; - // Set the final track parameters and covariances - finalize(); + // Refine the tracks using cluster resolution or just finalize them + if (mRefineTracks) { + tStart = std::chrono::high_resolution_clock::now(); + mTrackFitter.useClusterResolution(); + refineTracks(); + tEnd = std::chrono::high_resolution_clock::now(); + mTimeRefineTracks += tEnd - tStart; + } else { + finalize(); + } printTracks(); - /* - // Refit the reconstructed tracks with a different resolution for mono-cathod clusters - discardMonoCathodClusters(); -*/ + return mTracks; } @@ -304,7 +315,7 @@ std::list<Track>::iterator TrackFinderOriginal::findTrackCandidates(int ch1, int // check if non bending impact parameter is within tolerances double nonBendingSlope = (cluster1.getX() - cluster2.getX()) / dZ; double nonBendingImpactParam = TMath::Abs(cluster1.getX() - cluster1.getZ() * nonBendingSlope); - double nonBendingImpactParamErr = TMath::Sqrt((z1 * z1 * cluster2.getEx2() + z2 * z2 * cluster1.getEx2()) / dZ / dZ + impactMCS2); + double nonBendingImpactParamErr = TMath::Sqrt((z1 * z1 * chamberResolutionX2() + z2 * z2 * chamberResolutionX2()) / dZ / dZ + impactMCS2); if ((nonBendingImpactParam - SSigmaCutForTracking * nonBendingImpactParamErr) > (3. * SNonBendingVertexDispersion)) { continue; } @@ -313,7 +324,7 @@ std::list<Track>::iterator TrackFinderOriginal::findTrackCandidates(int ch1, int if (TrackExtrap::isFieldON()) { // depending whether the field is ON or OFF // check if bending momentum is within tolerances double bendingImpactParam = cluster1.getY() - cluster1.getZ() * bendingSlope; - double bendingImpactParamErr2 = (z1 * z1 * cluster2.getEy2() + z2 * z2 * cluster1.getEy2()) / dZ / dZ + impactMCS2; + double bendingImpactParamErr2 = (z1 * z1 * chamberResolutionY2() + z2 * z2 * chamberResolutionY2()) / dZ / dZ + impactMCS2; double bendingMomentum = TMath::Abs(TrackExtrap::getBendingMomentumFromImpactParam(bendingImpactParam)); double bendingMomentumErr = TMath::Sqrt((bendingVertexDispersion2 + bendingImpactParamErr2) / bendingImpactParam / bendingImpactParam + 0.01) * bendingMomentum; if ((bendingMomentum + 3. * bendingMomentumErr) < SMinBendingMomentum) { @@ -322,7 +333,7 @@ std::list<Track>::iterator TrackFinderOriginal::findTrackCandidates(int ch1, int } else { // or check if bending impact parameter is within tolerances double bendingImpactParam = TMath::Abs(cluster1.getY() - cluster1.getZ() * bendingSlope); - double bendingImpactParamErr = TMath::Sqrt((z1 * z1 * cluster2.getEy2() + z2 * z2 * cluster1.getEy2()) / dZ / dZ + impactMCS2); + double bendingImpactParamErr = TMath::Sqrt((z1 * z1 * chamberResolutionY2() + z2 * z2 * chamberResolutionY2()) / dZ / dZ + impactMCS2); if ((bendingImpactParam - SSigmaCutForTracking * bendingImpactParamErr) > (3. * SBendingVertexDispersion)) { continue; } @@ -402,15 +413,15 @@ void TrackFinderOriginal::createTrack(const Cluster& cl1, const Cluster& cl2) TMatrixD paramCov(5, 5); paramCov.Zero(); // Non bending plane - double cl1Ex2 = cl1.getEx2(); - double cl2Ex2 = cl2.getEx2(); + double cl1Ex2 = chamberResolutionX2(); + double cl2Ex2 = chamberResolutionX2(); paramCov(0, 0) = cl1Ex2; paramCov(0, 1) = cl1Ex2 / dZ; paramCov(1, 0) = paramCov(0, 1); paramCov(1, 1) = (cl1Ex2 + cl2Ex2) / dZ / dZ; // Bending plane - double cl1Ey2 = cl1.getEy2(); - double cl2Ey2 = cl2.getEy2(); + double cl1Ey2 = chamberResolutionY2(); + double cl2Ey2 = chamberResolutionY2(); paramCov(2, 2) = cl1Ey2; paramCov(2, 3) = cl1Ey2 / dZ; paramCov(3, 2) = paramCov(2, 3); @@ -913,8 +924,8 @@ bool TrackFinderOriginal::tryOneClusterFast(const TrackParam& param, const Clust double dX = cluster.getX() - (param.getNonBendingCoor() + param.getNonBendingSlope() * dZ); double dY = cluster.getY() - (param.getBendingCoor() + param.getBendingSlope() * dZ); const TMatrixD& paramCov = param.getCovariances(); - double errX2 = paramCov(0, 0) + dZ * dZ * paramCov(1, 1) + 2. * dZ * paramCov(0, 1) + cluster.getEx2(); - double errY2 = paramCov(2, 2) + dZ * dZ * paramCov(3, 3) + 2. * dZ * paramCov(2, 3) + cluster.getEy2(); + double errX2 = paramCov(0, 0) + dZ * dZ * paramCov(1, 1) + 2. * dZ * paramCov(0, 1) + chamberResolutionX2(); + double errY2 = paramCov(2, 2) + dZ * dZ * paramCov(3, 3) + 2. * dZ * paramCov(2, 3) + chamberResolutionY2(); double dXmax = SSigmaCutForTracking * TMath::Sqrt(2. * errX2) + SMaxNonBendingDistanceToTrack; double dYmax = SSigmaCutForTracking * TMath::Sqrt(2. * errY2) + SMaxBendingDistanceToTrack; @@ -949,8 +960,8 @@ double TrackFinderOriginal::tryOneCluster(const TrackParam& param, const Cluster // Combine the cluster and track resolutions and covariances const TMatrixD& paramCov = paramAtCluster.getCovariances(); - double sigmaX2 = paramCov(0, 0) + cluster.getEx2(); - double sigmaY2 = paramCov(2, 2) + cluster.getEy2(); + double sigmaX2 = paramCov(0, 0) + chamberResolutionX2(); + double sigmaY2 = paramCov(2, 2) + chamberResolutionY2(); double covXY = paramCov(0, 2); double det = sigmaX2 * sigmaY2 - covXY * covXY; @@ -994,7 +1005,7 @@ void TrackFinderOriginal::updateTrack(Track& track, TrackParam& trackParamAtClus const Cluster* cluster1(trackParamAtCluster1.getClusterPtr()); double deltaX = trackParamAtCluster1.getNonBendingCoor() - cluster1->getX(); double deltaY = trackParamAtCluster1.getBendingCoor() - cluster1->getY(); - double localChi2 = deltaX * deltaX / cluster1->getEx2() + deltaY * deltaY / cluster1->getEy2(); + double localChi2 = deltaX * deltaX / chamberResolutionX2() + deltaY * deltaY / chamberResolutionY2(); trackParamAtCluster1.setLocalChi2(localChi2); // Compute the local chi2 at cluster2 @@ -1003,7 +1014,7 @@ void TrackFinderOriginal::updateTrack(Track& track, TrackParam& trackParamAtClus TrackExtrap::extrapToZ(&extrapTrackParamAtCluster2, trackParamAtCluster2.getZ()); deltaX = extrapTrackParamAtCluster2.getNonBendingCoor() - cluster2->getX(); deltaY = extrapTrackParamAtCluster2.getBendingCoor() - cluster2->getY(); - localChi2 = deltaX * deltaX / cluster2->getEx2() + deltaY * deltaY / cluster2->getEy2(); + localChi2 = deltaX * deltaX / chamberResolutionX2() + deltaY * deltaY / chamberResolutionY2(); trackParamAtCluster2.setLocalChi2(localChi2); // Add the parameters at the new clusters @@ -1260,6 +1271,28 @@ void TrackFinderOriginal::improveTracks() } } +//_________________________________________________________________________________________________ +void TrackFinderOriginal::refineTracks() +{ + /// Refit, improve and finalize the reconstructed tracks + + print("Refine tracks"); + + for (auto itTrack = mTracks.begin(); itTrack != mTracks.end();) { + try { + mTrackFitter.fit(*itTrack, false); + ++itTrack; + } catch (exception const&) { + print("Removing candidate at position #", getTrackIndex(itTrack)); + itTrack = mTracks.erase(itTrack); + } + } + + improveTracks(); + + finalize(); +} + //_________________________________________________________________________________________________ void TrackFinderOriginal::finalize() { @@ -1375,6 +1408,7 @@ void TrackFinderOriginal::printTimers() const LOG(INFO) << "completeTracks duration = " << mTimeCompleteTracks.count() << " s"; LOG(INFO) << "improveTracks duration = " << mTimeImproveTracks.count() << " s"; LOG(INFO) << "removeConnectedTracks duration = " << mTimeCleanTracks.count() << " s"; + LOG(INFO) << "refineTracks duration = " << mTimeRefineTracks.count() << " s"; } } // namespace mch diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx index c845c2b8279cb..312c5ab4c7c91 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFitter.cxx @@ -30,7 +30,7 @@ namespace mch using namespace std; -constexpr float TrackFitter::SDefaultChamberZ[10]; +constexpr double TrackFitter::SDefaultChamberZ[10]; constexpr double TrackFitter::SChamberThicknessInX0[10]; //_________________________________________________________________________________________________ @@ -117,14 +117,26 @@ void TrackFitter::initTrack(const Cluster& cl1, const Cluster& cl2, TrackParam& // compute the track parameter covariances at the last cluster (as if the other clusters did not exist) TMatrixD lastParamCov(5, 5); lastParamCov.Zero(); + double cl1Ey2(0.); + if (mUseChamberResolution) { + // Non bending plane + lastParamCov(0, 0) = mChamberResolutionX2; + lastParamCov(1, 1) = (1000. * mChamberResolutionX2 + lastParamCov(0, 0)) / dZ / dZ; + // Bending plane + lastParamCov(2, 2) = mChamberResolutionY2; + cl1Ey2 = mChamberResolutionY2; + } else { + // Non bending plane + lastParamCov(0, 0) = cl2.getEx2(); + lastParamCov(1, 1) = (1000. * cl1.getEx2() + lastParamCov(0, 0)) / dZ / dZ; + // Bending plane + lastParamCov(2, 2) = cl2.getEy2(); + cl1Ey2 = cl1.getEy2(); + } // Non bending plane - lastParamCov(0, 0) = cl2.getEx2(); lastParamCov(0, 1) = -lastParamCov(0, 0) / dZ; lastParamCov(1, 0) = lastParamCov(0, 1); - lastParamCov(1, 1) = (1000. * cl1.getEx2() + lastParamCov(0, 0)) / dZ / dZ; // Bending plane - double cl1Ey2 = cl1.getEy2(); - lastParamCov(2, 2) = cl2.getEy2(); lastParamCov(2, 3) = -lastParamCov(2, 2) / dZ; lastParamCov(3, 2) = lastParamCov(2, 3); lastParamCov(3, 3) = (1000. * cl1Ey2 + lastParamCov(2, 2)) / dZ / dZ; @@ -267,8 +279,13 @@ void TrackFitter::runKalmanFilter(TrackParam& trackParam) // compute the new cluster weight (U) TMatrixD clusterWeight(5, 5); clusterWeight.Zero(); - clusterWeight(0, 0) = 1. / cluster->getEx2(); - clusterWeight(2, 2) = 1. / cluster->getEy2(); + if (mUseChamberResolution) { + clusterWeight(0, 0) = 1. / mChamberResolutionX2; + clusterWeight(2, 2) = 1. / mChamberResolutionY2; + } else { + clusterWeight(0, 0) = 1. / cluster->getEx2(); + clusterWeight(2, 2) = 1. / cluster->getEy2(); + } // compute the new parameters covariance matrix ((W+U)^-1) TMatrixD newParamCov(paramWeight, TMatrixD::kPlus, clusterWeight); @@ -345,10 +362,15 @@ void TrackFitter::runSmoother(const TrackParam& previousParam, TrackParam& param // compute weight of smoothed residual: W(k n) = (clusterCov - C(k n))^-1 TMatrixD smoothResidualWeight(2, 2); - smoothResidualWeight(0, 0) = cluster->getEx2() - smoothCovariances(0, 0); + if (mUseChamberResolution) { + smoothResidualWeight(0, 0) = mChamberResolutionX2 - smoothCovariances(0, 0); + smoothResidualWeight(1, 1) = mChamberResolutionY2 - smoothCovariances(2, 2); + } else { + smoothResidualWeight(0, 0) = cluster->getEx2() - smoothCovariances(0, 0); + smoothResidualWeight(1, 1) = cluster->getEy2() - smoothCovariances(2, 2); + } smoothResidualWeight(0, 1) = -smoothCovariances(0, 2); smoothResidualWeight(1, 0) = -smoothCovariances(2, 0); - smoothResidualWeight(1, 1) = cluster->getEy2() - smoothCovariances(2, 2); if (smoothResidualWeight.Determinant() != 0) { smoothResidualWeight.Invert(); } else { diff --git a/Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx b/Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx index 77ae8cdcac199..58b89e1da2b44 100644 --- a/Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx @@ -88,10 +88,6 @@ class ClusterSamplerTask // fill clusters in O2 format, if any if (nClusters > 0) { mInputFile.read(reinterpret_cast<char*>(clusters.data()), clusters.size_bytes()); - for (auto& cluster : clusters) { - cluster.ex = 0.2f; - cluster.ey = 0.2f; - } } else { LOG(INFO) << "event is empty"; } diff --git a/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx index a30b8b8027cbe..ead732c2302a0 100644 --- a/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx @@ -63,6 +63,9 @@ class TrackFinderTask auto moreCandidates = ic.options().get<bool>("moreCandidates"); mTrackFinder.findMoreTrackCandidates(moreCandidates); + auto refineTracks = !ic.options().get<bool>("noRefinement"); + mTrackFinder.refineTracks(refineTracks); + auto debugLevel = ic.options().get<int>("debug"); mTrackFinder.debug(debugLevel); @@ -142,6 +145,7 @@ o2::framework::DataProcessorSpec getTrackFinderOriginalSpec() Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}, {"moreCandidates", VariantType::Bool, false, {"Find more track candidates"}}, + {"noRefinement", VariantType::Bool, false, {"Disable the track refinement"}}, {"debug", VariantType::Int, 0, {"debug level"}}}}; } diff --git a/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx index 430be7df506d4..62ecc54218e46 100644 --- a/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx @@ -63,6 +63,9 @@ class TrackFinderTask auto moreCandidates = ic.options().get<bool>("moreCandidates"); mTrackFinder.findMoreTrackCandidates(moreCandidates); + auto refineTracks = !ic.options().get<bool>("noRefinement"); + mTrackFinder.refineTracks(refineTracks); + auto debugLevel = ic.options().get<int>("debug"); mTrackFinder.debug(debugLevel); @@ -142,6 +145,7 @@ o2::framework::DataProcessorSpec getTrackFinderSpec() Options{{"l3Current", VariantType::Float, -30000.0f, {"L3 current"}}, {"dipoleCurrent", VariantType::Float, -6000.0f, {"Dipole current"}}, {"moreCandidates", VariantType::Bool, false, {"Find more track candidates"}}, + {"noRefinement", VariantType::Bool, false, {"Disable the track refinement"}}, {"debug", VariantType::Int, 0, {"debug level"}}}}; } From 15ee39c521ac97c2408f059050a296f75b59268f Mon Sep 17 00:00:00 2001 From: Jochen Klein <jochen.klein@cern.ch> Date: Mon, 30 Nov 2020 08:25:09 +0100 Subject: [PATCH 1456/1751] Fix find_package for MS GSL - pass $MS_GSL_ROOT as HINTS in order to take precedence over system paths --- dependencies/Findms_gsl.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/Findms_gsl.cmake b/dependencies/Findms_gsl.cmake index b3098d1468197..64ae38d326701 100644 --- a/dependencies/Findms_gsl.cmake +++ b/dependencies/Findms_gsl.cmake @@ -9,7 +9,7 @@ # submit itself to any jurisdiction. find_path(MS_GSL_INCLUDE_DIR gsl/gsl PATH_SUFFIXES ms_gsl/include include - PATHS $ENV{MS_GSL_ROOT}) + HINTS $ENV{MS_GSL_ROOT}) if(NOT MS_GSL_INCLUDE_DIR) set(MS_GSL_FOUND FALSE) From 4007a6b8c652e5e58e2e6f008b5249971242e65b Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 26 Nov 2020 13:06:28 +0100 Subject: [PATCH 1457/1751] o2-sim kinematics as event generator Allows reading events from existing O2 kinematics. Here, foremost, this achieves a possibility to split event generation and transport into different stages (using the same tool), in the following sense: ``` o2-sim -n 100 -g pythia8 + no-transport options // generate 100 pythia8 events o2-sim -g extgenO2 -n 100 --extKinFile o2sim_Kine.root // continue transport on these events. ``` A possible use case is embedding: Signal simulation could continue based on background events without having to wait for full background transport. Later on, the same mechanism -- with some modification and careful state handling -- might achieve a stop/go at a more general level (for example splitting the transport in multiple stages) --- .../include/SimulationDataFormat/MCTrack.h | 14 +++- .../SimulationDataFormat/ParticleStatus.h | 23 ++++++ .../include/SimulationDataFormat/Stack.h | 6 +- .../include/Generators/GeneratorFromFile.h | 28 +++++++ Generators/src/GeneratorFactory.cxx | 6 ++ Generators/src/GeneratorFromFile.cxx | 78 +++++++++++++++++++ Generators/src/GeneratorsLinkDef.h | 1 + 7 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h index c333bd3e624d9..18e5cb7da3619 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h @@ -15,6 +15,7 @@ #ifndef ALICEO2_DATA_MCTRACK_H_ #define ALICEO2_DATA_MCTRACK_H_ +#include "SimulationDataFormat/ParticleStatus.h" #include "DetectorsCommonDataFormats/DetID.h" #include "Rtypes.h" #include "TDatabasePDG.h" @@ -184,6 +185,14 @@ class MCTrackT /// get the production process (id) of this track int getProcess() const { return ((PropEncoding)mProp).process; } + void setToBeDone(bool f) + { + auto prop = ((PropEncoding)mProp); + prop.toBeDone = f; + mProp = prop.i; + } + bool getToBeDone() const { return ((PropEncoding)mProp).toBeDone; } + /// get the string representation of the production process const char* getProdProcessAsString() const; @@ -216,7 +225,8 @@ class MCTrackT struct { int storage : 1; // encoding whether to store this track to the output int process : 6; // encoding process that created this track (enough to store TMCProcess from ROOT) - int hitmask : 25; // encoding hits per detector + int hitmask : 24; // encoding hits per detector + int toBeDone : 1; // whether this (still) needs tracking --> we might more complete information to cover full ParticleStatus space }; }; @@ -305,6 +315,8 @@ inline MCTrackT<T>::MCTrackT(const TParticle& part) { // our convention is to communicate the process as (part) of the unique ID setProcess(part.GetUniqueID()); + // extract toBeDone flag + setToBeDone(part.TestBit(ParticleStatus::kToBeDone)); } template <typename T> diff --git a/DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h b/DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h new file mode 100644 index 0000000000000..e73202342bde2 --- /dev/null +++ b/DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h @@ -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. + +#ifndef ALICEO2_SIMDATA_PARTICLESTATUS_H_ +#define ALICEO2_SIMDATA_PARTICLESTATUS_H_ + +#include "TParticle.h" + +/// enumeration to define status bits for particles in simulation +enum ParticleStatus { kKeep = BIT(14), + kDaughters = BIT(15), + kToBeDone = BIT(16), + kPrimary = BIT(17), + kTransport = BIT(18) }; + +#endif diff --git a/DataFormats/simulation/include/SimulationDataFormat/Stack.h b/DataFormats/simulation/include/SimulationDataFormat/Stack.h index a373787c481cd..c63cb67e526d1 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/Stack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/Stack.h @@ -20,6 +20,7 @@ #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/TrackReference.h" #include "SimulationDataFormat/MCEventStats.h" +#include "SimulationDataFormat/ParticleStatus.h" #include "Rtypes.h" #include "TParticle.h" @@ -54,11 +55,6 @@ namespace data /// The storage of secondaries can be switched off. /// The storage of all mothers can be switched off. /// By default, the minimal number of hits is 1 and the energy cut is 0. -enum ParticleStatus { kKeep = BIT(14), - kDaughters = BIT(15), - kToBeDone = BIT(16), - kPrimary = BIT(17), - kTransport = BIT(18) }; class Stack : public FairGenericStack { public: diff --git a/Generators/include/Generators/GeneratorFromFile.h b/Generators/include/Generators/GeneratorFromFile.h index 42038353e5937..1c7f3eac878e3 100644 --- a/Generators/include/Generators/GeneratorFromFile.h +++ b/Generators/include/Generators/GeneratorFromFile.h @@ -58,6 +58,34 @@ class GeneratorFromFile : public FairGenerator ClassDefOverride(GeneratorFromFile, 1); }; +/// This class implements a generic FairGenerator which +/// reads the particles from an external O2 sim kinematics file. +class GeneratorFromO2Kine : public FairGenerator +{ + public: + GeneratorFromO2Kine() = default; + GeneratorFromO2Kine(const char* name); + + // the FairGenerator interface methods + + /** Generates (or reads) one event and adds the tracks to the + ** injected primary generator instance. + ** @param primGen pointer to the primary FairPrimaryGenerator + **/ + bool ReadEvent(FairPrimaryGenerator* primGen) override; + + // Set from which event to start + void SetStartEvent(int start); + + private: + TFile* mEventFile = nullptr; //! the file containing the persistent events + TBranch* mEventBranch = nullptr; //! the branch containing the persistent events + int mEventCounter = 0; + int mEventsAvailable = 0; + bool mSkipNonTrackable = true; //! whether to pass non-trackable (decayed particles) to the MC stack + ClassDefOverride(GeneratorFromO2Kine, 1); +}; + } // end namespace eventgen } // end namespace o2 diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index 9af65cf5a0b72..2edbff92e826c 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -136,6 +136,12 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair extGen->SetStartEvent(conf.getStartEvent()); primGen->AddGenerator(extGen); LOG(INFO) << "using external kinematics"; + } else if (genconfig.compare("extkinO2") == 0) { + // external kinematics from previous O2 output + auto extGen = new o2::eventgen::GeneratorFromO2Kine(conf.getExtKinematicsFileName().c_str()); + extGen->SetStartEvent(conf.getStartEvent()); + primGen->AddGenerator(extGen); + LOG(INFO) << "using external O2 kinematics"; #ifdef GENERATORS_WITH_HEPMC3 } else if (genconfig.compare("hepmc") == 0) { // external HepMC file diff --git a/Generators/src/GeneratorFromFile.cxx b/Generators/src/GeneratorFromFile.cxx index 112ea38f7bfc4..9531c4c3435e4 100644 --- a/Generators/src/GeneratorFromFile.cxx +++ b/Generators/src/GeneratorFromFile.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "Generators/GeneratorFromFile.h" +#include "SimulationDataFormat/MCTrack.h" #include <FairLogger.h> #include <FairPrimaryGenerator.h> #include <TBranch.h> @@ -154,7 +155,84 @@ Bool_t GeneratorFromFile::ReadEvent(FairPrimaryGenerator* primGen) return kFALSE; } +// based on O2 kinematics + +GeneratorFromO2Kine::GeneratorFromO2Kine(const char* name) +{ + mEventFile = TFile::Open(name); + if (mEventFile == nullptr) { + LOG(FATAL) << "EventFile " << name << " not found"; + return; + } + // the kinematics will be stored inside a branch MCTrack + // different events are stored inside different entries + auto tree = (TTree*)mEventFile->Get("o2sim"); + if (tree) { + mEventBranch = tree->GetBranch("MCTrack"); + if (mEventBranch) { + mEventsAvailable = mEventBranch->GetEntries(); + LOG(INFO) << "Found " << mEventsAvailable << " events in this file"; + return; + } + } + LOG(ERROR) << "Problem reading events from file " << name; +} + +void GeneratorFromO2Kine::SetStartEvent(int start) +{ + if (start < mEventsAvailable) { + mEventCounter = start; + } else { + LOG(ERROR) << "start event bigger than available events\n"; + } +} + +Bool_t GeneratorFromO2Kine::ReadEvent(FairPrimaryGenerator* primGen) +{ + // NOTE: This should be usable with kinematics files without secondaries + // It might need some adjustment to make it work with secondaries or to continue + // from a kinematics snapshot + + if (mEventCounter < mEventsAvailable) { + int particlecounter = 0; + + std::vector<o2::MCTrack>* tracks = nullptr; + mEventBranch->SetAddress(&tracks); + mEventBranch->GetEntry(mEventCounter); + + for (auto& p : *tracks) { + auto pdgid = p.GetPdgCode(); + auto px = p.Px(); + auto py = p.Py(); + auto pz = p.Pz(); + auto vx = p.Vx(); + auto vy = p.Vy(); + auto vz = p.Vz(); + auto parent = -1; // --> check this !!! + auto e = p.GetEnergy(); + auto tof = p.T(); + auto weight = 1.; // p.GetWeight() ??; + auto wanttracking = p.getToBeDone(); + LOG(DEBUG) << "Putting primary " << pdgid; + primGen->AddTrack(pdgid, px, py, pz, vx, vy, vz, parent, wanttracking, e, tof, weight); + particlecounter++; + } + mEventCounter++; + + if (tracks) { + delete tracks; + } + + LOG(INFO) << "Event generator put " << particlecounter << " on stack"; + return kTRUE; + } else { + LOG(ERROR) << "GeneratorFromO2Kine: Ran out of events\n"; + } + return kFALSE; +} + } // namespace eventgen } // end namespace o2 ClassImp(o2::eventgen::GeneratorFromFile); +ClassImp(o2::eventgen::GeneratorFromO2Kine); diff --git a/Generators/src/GeneratorsLinkDef.h b/Generators/src/GeneratorsLinkDef.h index 25632f549ff8d..646e8d0576256 100644 --- a/Generators/src/GeneratorsLinkDef.h +++ b/Generators/src/GeneratorsLinkDef.h @@ -47,6 +47,7 @@ #pragma link C++ class o2::eventgen::GeneratorFactory + ; #endif #pragma link C++ class o2::eventgen::GeneratorFromFile + ; +#pragma link C++ class o2::eventgen::GeneratorFromO2Kine + ; #pragma link C++ class o2::PDG + ; #pragma link C++ class o2::eventgen::PrimaryGenerator + ; From 3d5d3322e2c67a1c27a1fbc69d74f4babcd63396 Mon Sep 17 00:00:00 2001 From: David Dobrigkeit Chinellato <david.dobrigkeit.chinellato@cern.ch> Date: Thu, 26 Nov 2020 17:00:26 +0100 Subject: [PATCH 1458/1751] Add adapt... call --- Analysis/Tasks/PWGLF/cascadeproducer.cxx | 1 + Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 1 + 2 files changed, 2 insertions(+) diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx index 8cf1076b778a4..2b9a7f844ae9b 100644 --- a/Analysis/Tasks/PWGLF/cascadeproducer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -274,5 +274,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<cascprodinitializer>("lf-cascprodinitializer"), + adaptAnalysisTask<cascadeprefilterpairs>("lf-cascadeprefilterpairs"), adaptAnalysisTask<cascadeproducer>("lf-cascadeproducer")}; } diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index b3b330ff366dc..d8784c85308c3 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -202,5 +202,6 @@ struct lambdakzeroproducer { WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ + adaptAnalysisTask<lambdakzeroprefilterpairs>("lf-lambdakzeroprefilterpairs"), adaptAnalysisTask<lambdakzeroproducer>("lf-lambdakzeroproducer")}; } From e2ebeef16524dbfe0083c6f9786c84f4cfbf1d83 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 30 Nov 2020 22:57:11 +0100 Subject: [PATCH 1459/1751] Fix compiler warnings --- .../cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h | 8 ++++---- .../cuda/include/ITStrackingCUDA/TrackerTraitsNV.h | 2 +- Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu | 2 +- .../ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx | 2 +- Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h index dac80e224b7b8..0b812088fb302 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h @@ -38,8 +38,8 @@ class PrimaryVertexContextNV final : public PrimaryVertexContext PrimaryVertexContextNV() = default; virtual ~PrimaryVertexContextNV() = default; - void initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its2::LayersNumber>& cl, - const std::array<float, 3>& pv, const int iteration); + void initialise(const MemoryParameters& memParam, const TrackingParameters& trkParam, + const std::vector<std::vector<Cluster>>& cl, const std::array<float, 3>& pv, const int iteration) override; GPU::DeviceStoreNV& getDeviceContext(); GPU::Array<GPU::Vector<Cluster>, constants::its2::LayersNumber>& getDeviceClusters(); @@ -124,8 +124,8 @@ inline void PrimaryVertexContextNV::updateDeviceContext() mGPUContextDevicePointer = GPU::UniquePointer<GPU::DeviceStoreNV>{mGPUContext}; } -inline void PrimaryVertexContextNV::initialise(const MemoryParameters& memParam, const std::array<std::vector<Cluster>, constants::its2::LayersNumber>& cl, - const std::array<float, 3>& pv, const int iteration) +inline void PrimaryVertexContextNV::initialise(const MemoryParameters& memParam, const TrackingParameters& trkParam, + const std::vector<std::vector<Cluster>>& cl, const std::array<float, 3>& pv, const int iteration) { ///TODO: to be re-enabled in the future // this->PrimaryVertexContext::initialise(memParam, cl, pv, iteration); diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h index e3dbd233c7d96..cba3765ebb86e 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h @@ -34,7 +34,7 @@ class TrackerTraitsNV : public TrackerTraits void computeLayerCells() final; void computeLayerTracklets() final; - void refitTracks(const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks); + void refitTracks(const std::vector<std::vector<TrackingFrameInfo>>& tf, std::vector<TrackITSExt>& tracks) override; }; extern "C" TrackerTraits* createTrackerTraitsNV(); diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu index c81a2c149b37c..7fd97cc71788e 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu @@ -523,7 +523,7 @@ void TrackerTraitsNV::computeLayerCells() } } -void TrackerTraitsNV::refitTracks(const std::array<std::vector<TrackingFrameInfo>, 7>& tf, std::vector<TrackITSExt>& tracks) +void TrackerTraitsNV::refitTracks(const std::vector<std::vector<TrackingFrameInfo>>& tf, std::vector<TrackITSExt>& tracks) { PrimaryVertexContextNV* pvctx = static_cast<PrimaryVertexContextNV*>(mPrimaryVertexContext); diff --git a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx index c984d560588ac..12e69222e0653 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx @@ -105,7 +105,7 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const Tr for (unsigned int iB{0}; iB < clsPerBin.size(); ++iB) { mIndexTables[iLayer - 1][iB] = lutPerBin[iB]; } - for (auto iB{clsPerBin.size()}; iB < (int)mIndexTables[iLayer - 1].size(); iB++) { + for (auto iB{clsPerBin.size()}; iB < mIndexTables[iLayer - 1].size(); iB++) { mIndexTables[iLayer - 1][iB] = clustersNum; } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx index b8c7299134bcf..8dcb743d14e25 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx @@ -80,7 +80,7 @@ void TrackerTraitsCPU::computeLayerTracklets() for (int iNextLayerCluster{firstRowClusterIndex}; iNextLayerCluster < maxRowClusterIndex; ++iNextLayerCluster) { - if (iNextLayerCluster >= primaryVertexContext->getClusters()[iLayer + 1].size()) { + if (iNextLayerCluster >= (int)primaryVertexContext->getClusters()[iLayer + 1].size()) { break; } From 62ca78f2d775c6e4147b6e9c2a160b7e3c3b44de Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 30 Nov 2020 23:19:14 +0400 Subject: [PATCH 1460/1751] EMC fix: check bunchIndex validity before using it --- Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx b/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx index 102185633b6de..115d6b64e515b 100644 --- a/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx +++ b/Detectors/EMCAL/reconstruction/src/CaloRawFitterStandard.cxx @@ -62,7 +62,7 @@ CaloFitResults CaloRawFitterStandard::evaluate(const std::vector<Bunch>& bunchli auto [nsamples, bunchIndex, ampEstimate, maxADC, timeEstimate, pedEstimate, first, last] = preFitEvaluateSamples(bunchlist, altrocfg1, altrocfg2, mAmpCut); - if (ampEstimate >= mAmpCut) { + if (bunchIndex >= 0 && ampEstimate >= mAmpCut) { time = timeEstimate; int timebinOffset = bunchlist.at(bunchIndex).getStartTime() - (bunchlist.at(bunchIndex).getBunchLength() - 1); amp = ampEstimate; From 39927406293999496261379c426d7f587f775918 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 30 Nov 2020 14:46:03 +0100 Subject: [PATCH 1461/1751] GPU: Fix printout of config option when option is std::string --- GPU/GPUTracking/Base/GPUSettingsList.h | 8 ++++---- GPU/GPUTracking/Standalone/utils/qconfig.cxx | 13 +++---------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 492c090034501..743d1d94553af 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -108,7 +108,7 @@ AddOption(tpccfGatherKernel, bool, true, "", 0, "Use a kernel instead of the DMA AddOption(doublePipelineClusterizer, bool, true, "", 0, "Include the input data of the clusterizer in the double-pipeline") AddOption(deviceNum, int, -1, "gpuDevice", 0, "Set GPU device to use (-1: automatic, -2: for round-robin usage in timeslice-pipeline)") AddOption(globalInitMutex, bool, false, "", 0, "Use global mutex to synchronize initialization of multiple GPU instances") -AddOption(ompThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %d OMP threads")) +AddOption(ompThreads, int, -1, "omp", 't', "Number of OMP threads to run (-1: all)", min(-1), message("Using %s OMP threads")) AddOption(nDeviceHelperThreads, int, 1, "", 0, "Number of CPU helper threads for CPU processing") AddOption(nStreams, int, 8, "", 0, "Number of GPU streams / command queues") AddOption(trackletConstructorInPipeline, int, -1, "", 0, "Run tracklet constructor in the pipeline") @@ -122,7 +122,7 @@ AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") -AddOption(runQA, int, 0, "qa", 'q', "Enable tracking QA (negative number to provide bitmask for QA tasks)", message("Running QA: %d"), def(1)) +AddOption(runQA, int, 0, "qa", 'q', "Enable tracking QA (negative number to provide bitmask for QA tasks)", message("Running QA: %s"), def(1)) AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") AddOption(forceMemoryPoolSize, unsigned long, 1, "memSize", 0, "Force size of allocated GPU / page locked host memory", min(0ul)) AddOption(forceHostMemoryPoolSize, unsigned long, 0, "hostMemSize", 0, "Force size of allocated host page locked host memory (overriding memSize)", min(0ul)) @@ -263,8 +263,8 @@ AddOption(EventsDir, const char*, "pp", "events", 'e', "Directory with events to AddOption(eventDisplay, int, 0, "display", 'd', "Show standalone event display", def(1)) //1: default display (Windows / X11), 2: glut, 3: glfw AddOption(eventGenerator, bool, false, "", 0, "Run event generator") AddOption(cont, bool, false, "", 0, "Process continuous timeframe data") -AddOption(outputcontrolmem, unsigned long, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ul), message("Using %lld bytes as output memory")) -AddOption(inputcontrolmem, unsigned long, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ul), message("Using %lld bytes as input memory")) +AddOption(outputcontrolmem, unsigned long, 0, "outputMemory", 0, "Use predefined output buffer of this size", min(0ul), message("Using %s bytes as output memory")) +AddOption(inputcontrolmem, unsigned long, 0, "inputMemory", 0, "Use predefined input buffer of this size", min(0ul), message("Using %s bytes as input memory")) AddOption(cpuAffinity, int, -1, "", 0, "Pin CPU affinity to this CPU core", min(-1)) AddOption(fifoScheduler, bool, false, "", 0, "Use FIFO realtime scheduler", message("Setting FIFO scheduler: %s")) AddOption(fpe, bool, true, "", 0, "Trap on floating point exceptions") diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index bc943254a8b6f..083b7da828040 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -452,16 +452,9 @@ template <typename T> inline void qAddOptionMessage(qConfigSettings<T>& settings, T& ref) { if (settings.message) { - printf(settings.message, ref); - printf("\n"); - } -} -template <> -inline void qAddOptionMessage<bool>(qConfigSettings<bool>& settings, bool& ref) -{ - if (settings.message) { - printf(settings.message, ref ? "ON" : "OFF"); - printf("\n"); + std::string tmp = print_type(ref); + std::string msg = std::string(settings.message) + "\n"; + printf(msg.c_str(), tmp.c_str()); } } From 0b90de755a59bd959c8d94ee010ab4041061ee2a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 30 Nov 2020 14:46:55 +0100 Subject: [PATCH 1462/1751] GPU: Clean up some includes, don't include GPUDataTypes.h in the baseclass --- GPU/GPUTracking/Base/GPUO2DataTypes.h | 1 + GPU/GPUTracking/Base/GPUReconstruction.h | 1 - GPU/GPUTracking/Base/GPUReconstructionIncludes.h | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUO2DataTypes.h b/GPU/GPUTracking/Base/GPUO2DataTypes.h index 8d359abf4b1d3..40d814e6a764d 100644 --- a/GPU/GPUTracking/Base/GPUO2DataTypes.h +++ b/GPU/GPUTracking/Base/GPUO2DataTypes.h @@ -18,6 +18,7 @@ #if defined(HAVE_O2HEADERS) && (!defined(__OPENCL__) || defined(__OPENCLCPP__)) #include "DataFormatsTPC/ClusterNative.h" +#include "DataFormatsTPC/Digit.h" #include "DetectorsBase/MatLayerCylSet.h" #include "TRDBase/GeometryFlat.h" #else diff --git a/GPU/GPUTracking/Base/GPUReconstruction.h b/GPU/GPUTracking/Base/GPUReconstruction.h index 5bb4f7aa61e6a..474862b5c91f6 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.h +++ b/GPU/GPUTracking/Base/GPUReconstruction.h @@ -30,7 +30,6 @@ #include "GPUMemoryResource.h" #include "GPUConstantMem.h" #include "GPUTPCSliceOutput.h" -#include "GPUDataTypes.h" #include "GPULogging.h" namespace o2 diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h index 0a7a34e089ad2..04409ce27c7e0 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h @@ -23,6 +23,7 @@ #include "GPUDef.h" #include "GPULogging.h" +#include "GPUDataTypes.h" #include <iostream> #include <fstream> From d1987ba46eb4e8a94f33f7651320bb6142650457 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 30 Nov 2020 14:47:12 +0100 Subject: [PATCH 1463/1751] GPU: Add option to compile standalone benchmark with clang --- GPU/GPUTracking/Standalone/CMakeLists.txt | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 0168de0e5c4ad..0f459ad379ab4 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -23,6 +23,18 @@ if(NOT EXISTS "${CMAKE_BINARY_DIR}/config.cmake") file(COPY "${CMAKE_SOURCE_DIR}/cmake/config.cmake" DESTINATION "${CMAKE_BINARY_DIR}") endif() include("${CMAKE_BINARY_DIR}/config.cmake") +if(DEFINED CONFIG_COMPILER) + if(CONFIG_COMPILER STREQUAL "clang") + set(CMAKE_C_COMPILER "clang") + set(CMAKE_CXX_COMPILER "clang++") + elseif(CONFIG_COMPILER STREQUAL "gcc") + set(CMAKE_C_COMPILER "gcc") + set(CMAKE_CXX_COMPILER "c++") + else() + set(CMAKE_C_COMPILER "${CONFIG_COMPILER}") + set(CMAKE_CXX_COMPILER "${CONFIG_COMPILER}") + endif() +endif() # Set Build and Compiler settings set(ALIGPU_BUILD_TYPE "Standalone") @@ -35,7 +47,10 @@ if(BUILD_DEBUG) set(CMAKE_CXX_FLAGS "-O0 -ggdb") set(CMAKE_BUILD_TYPE DEBUG) else() - set(CMAKE_CXX_FLAGS "-O3 -march=native -ggdb -minline-all-stringops -ftracer -funroll-loops -fprefetch-loop-arrays -ffast-math -fno-stack-protector") + set(CMAKE_CXX_FLAGS "-O3 -march=native -ggdb -minline-all-stringops -funroll-loops -ffast-math -fno-stack-protector") + if (NOT CMAKE_CXX_COMPILER STREQUAL "clang++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftracer -fprefetch-loop-arrays") + endif() set(CMAKE_RELEASE_TYPE RELEASE) add_definitions(-DNDEBUG) endif() @@ -229,6 +244,10 @@ endif() if(OpenMP_CXX_FOUND) target_link_libraries(ca PUBLIC OpenMP::OpenMP_CXX) + if (CMAKE_CXX_COMPILER STREQUAL "clang++") + target_link_libraries(ca PUBLIC -fopenmp) + target_link_libraries(GPUTracking PUBLIC -fopenmp) + endif() endif() # Installation From 2660684730f44728ebebcce104f42f9ce060a5a9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 30 Nov 2020 15:26:10 +0100 Subject: [PATCH 1464/1751] GPU: Fix compiler warnings reported by clang --- GPU/GPUTracking/Base/GPUDataTypes.h | 4 ++-- GPU/GPUTracking/Base/GPUReconstruction.cxx | 3 +++ GPU/GPUTracking/Base/GPUReconstruction.h | 6 +++--- GPU/GPUTracking/Base/GPUReconstructionConvert.h | 6 +++--- GPU/GPUTracking/Global/GPUChainITS.cxx | 4 ++-- GPU/GPUTracking/Global/GPUChainITS.h | 4 ++-- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- GPU/GPUTracking/Global/GPUChainTracking.h | 2 +- GPU/GPUTracking/Global/GPUTrackingInputProvider.h | 2 +- GPU/GPUTracking/Standalone/CMakeLists.txt | 2 +- .../3rdparty/{ => HandMadeMath}/HandMadeMathImpl.cxx | 0 GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 4 ++-- GPU/GPUTracking/Standalone/qa/GPUQA.h | 4 ++-- GPU/GPUTracking/Standalone/qa/genEvents.cxx | 2 +- GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx | 5 +++-- GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h | 1 - 16 files changed, 27 insertions(+), 24 deletions(-) rename GPU/GPUTracking/Standalone/display/3rdparty/{ => HandMadeMath}/HandMadeMathImpl.cxx (100%) diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index 521e5b737880e..06b61a85d27cc 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -27,7 +27,7 @@ #ifdef GPUCA_NOCOMPAT #include "GPUTRDDef.h" -class AliHLTTPCClusterMCLabel; +struct AliHLTTPCClusterMCLabel; struct AliHLTTPCRawCluster; namespace o2 { @@ -97,7 +97,7 @@ class GPUTPCGMMergedTrack; struct GPUTPCGMMergedTrackHit; struct GPUTPCGMMergedTrackHitXYZ; class GPUTRDTrackletWord; -class GPUTPCMCInfo; +struct GPUTPCMCInfo; struct GPUTPCClusterData; struct GPUTRDTrackletLabels; struct GPUTPCDigitsMCInput; diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index b4bb8be7dd81c..1c4fdf78573ba 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -1003,6 +1003,9 @@ void GPUReconstruction::SetInputControl(void* ptr, size_t size) mInputControl.set(ptr, size); } +GPUReconstruction::GPUThreadContext::GPUThreadContext() = default; +GPUReconstruction::GPUThreadContext::~GPUThreadContext() = default; + std::unique_ptr<GPUReconstruction::GPUThreadContext> GPUReconstruction::GetThreadContext() { return std::unique_ptr<GPUReconstruction::GPUThreadContext>(new GPUThreadContext); } GPUReconstruction* GPUReconstruction::CreateInstance(DeviceType type, bool forceType, GPUReconstruction* master) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.h b/GPU/GPUTracking/Base/GPUReconstruction.h index 474862b5c91f6..f61f7366b9739 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.h +++ b/GPU/GPUTracking/Base/GPUReconstruction.h @@ -46,7 +46,7 @@ namespace GPUCA_NAMESPACE namespace gpu { class GPUChain; -class GPUMemorySizeScalers; +struct GPUMemorySizeScalers; struct GPUReconstructionPipelineContext; class GPUReconstruction @@ -278,8 +278,8 @@ class GPUReconstruction class GPUThreadContext { public: - GPUThreadContext() = default; - virtual ~GPUThreadContext() = default; + GPUThreadContext(); + virtual ~GPUThreadContext(); }; virtual std::unique_ptr<GPUThreadContext> GetThreadContext(); diff --git a/GPU/GPUTracking/Base/GPUReconstructionConvert.h b/GPU/GPUTracking/Base/GPUReconstructionConvert.h index 56799c160da23..255b36e90dac4 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionConvert.h +++ b/GPU/GPUTracking/Base/GPUReconstructionConvert.h @@ -32,14 +32,14 @@ class RawFileWriter; } // namespace raw } // namespace o2 -class AliHLTTPCRawCluster; +struct AliHLTTPCRawCluster; namespace GPUCA_NAMESPACE { namespace gpu { -class GPUParam; -class GPUTPCClusterData; +struct GPUParam; +struct GPUTPCClusterData; class TPCFastTransform; struct GPUTrackingInOutDigits; struct GPUTrackingInOutZS; diff --git a/GPU/GPUTracking/Global/GPUChainITS.cxx b/GPU/GPUTracking/Global/GPUChainITS.cxx index a6db94b02b007..7552684f255d4 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.cxx +++ b/GPU/GPUTracking/Global/GPUChainITS.cxx @@ -85,7 +85,7 @@ int GPUChainITS::RunITSTrackFit(std::vector<o2::its::Road>& roads, std::vector<c Fitter.clearMemory(); Fitter.SetNumberOfRoads(roads.size()); - for (int i = 0; i < clusters.size(); i++) { + for (unsigned int i = 0; i < clusters.size(); i++) { Fitter.SetNumberTF(i, tf[i].size()); } Fitter.SetMaxData(processors()->ioPtrs); @@ -93,7 +93,7 @@ int GPUChainITS::RunITSTrackFit(std::vector<o2::its::Road>& roads, std::vector<c std::copy(cells.begin(), cells.end(), Fitter.cells()); SetupGPUProcessor(&Fitter, true); std::copy(roads.begin(), roads.end(), Fitter.roads()); - for (int i = 0; i < clusters.size(); i++) { + for (unsigned int i = 0; i < clusters.size(); i++) { std::copy(tf[i].begin(), tf[i].end(), Fitter.trackingFrame()[i]); } diff --git a/GPU/GPUTracking/Global/GPUChainITS.h b/GPU/GPUTracking/Global/GPUChainITS.h index c6504c48ce13a..6dcf2d37b3b53 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.h +++ b/GPU/GPUTracking/Global/GPUChainITS.h @@ -17,10 +17,10 @@ #include "GPUChain.h" namespace o2::its { -class Cluster; +struct Cluster; class Road; class Cell; -class TrackingFrameInfo; +struct TrackingFrameInfo; class TrackITSExt; } // namespace o2::its diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index f25960f404c9a..5104ccb9a012f 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1891,7 +1891,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) for (unsigned int i = 0; i < NSLICES; i++) { GPUTPCTracker& trk = processors()->tpcTrackers[i]; TransferMemoryResourcesToHost(RecoStep::NoRecoStep, &trk); - auto sorter = [&trk](GPUTPCTrack& trk1, GPUTPCTrack& trk2) { + auto sorter = [](GPUTPCTrack& trk1, GPUTPCTrack& trk2) { if (trk1.NHits() == trk2.NHits()) { return trk1.Param().Y() > trk2.Param().Y(); } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index f9cb5022e9830..61e942cf1544e 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -59,7 +59,7 @@ class GPUTRDGeometry; class TPCFastTransform; class TPCdEdxCalibrationSplines; class GPUTrackingInputProvider; -class GPUChainTrackingFinalContext; +struct GPUChainTrackingFinalContext; struct GPUTPCCFChainContext; class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelegateBase diff --git a/GPU/GPUTracking/Global/GPUTrackingInputProvider.h b/GPU/GPUTracking/Global/GPUTrackingInputProvider.h index 247250c08ff8d..621f2271823cd 100644 --- a/GPU/GPUTracking/Global/GPUTrackingInputProvider.h +++ b/GPU/GPUTracking/Global/GPUTrackingInputProvider.h @@ -31,7 +31,7 @@ namespace GPUCA_NAMESPACE namespace gpu { -class GPUTrackingInOutZS; +struct GPUTrackingInOutZS; class GPUTrackingInputProvider : public GPUProcessor { diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 0f459ad379ab4..04361760182b6 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -223,7 +223,7 @@ if(BUILD_EVENT_DISPLAY) target_sources(GPUTracking PRIVATE display/3rdparty/gl3w.c) target_compile_definitions(GPUTracking PUBLIC GPUCA_DISPLAY_GL3W) endif() - target_sources(GPUTracking PRIVATE display/3rdparty/HandMadeMathImpl.cxx) + target_sources(GPUTracking PRIVATE display/3rdparty/HandMadeMath/HandMadeMathImpl.cxx) target_include_directories(GPUTracking SYSTEM PUBLIC display/3rdparty) endif() diff --git a/GPU/GPUTracking/Standalone/display/3rdparty/HandMadeMathImpl.cxx b/GPU/GPUTracking/Standalone/display/3rdparty/HandMadeMath/HandMadeMathImpl.cxx similarity index 100% rename from GPU/GPUTracking/Standalone/display/3rdparty/HandMadeMathImpl.cxx rename to GPU/GPUTracking/Standalone/display/3rdparty/HandMadeMath/HandMadeMathImpl.cxx diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index d50ed90fb108e..6f3670db34718 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -810,7 +810,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx int maxcount; auto maxLabel = acc.computeLabel(&maxweight, &sumweight, &maxcount); mTrackMCLabels[i] = maxLabel; - if (QA_DEBUG && track.OK() && GetNMCTracks(maxLabel.getEventID()) > maxLabel.getTrackID()) { + if (QA_DEBUG && track.OK() && GetNMCTracks(maxLabel.getEventID()) > (unsigned int)maxLabel.getTrackID()) { const mcInfo_t& mc = GetMCTrack(maxLabel); GPUInfo("Track %d label %d (fake %d) weight %f clusters %d (fitted %d) (%f%% %f%%) Pt %f", i, maxLabel.getTrackID(), (int)(maxLabel.isFake()), maxweight, nClusters, track.NClustersFitted(), 100.f * maxweight / sumweight, 100.f * (float)maxcount / (float)nClusters, std::sqrt(mc.pX * mc.pX + mc.pY * mc.pY)); @@ -1187,7 +1187,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx continue; } - auto getdz = [this, &mclocal, ¶m, &mc1, &side]() { + auto getdz = [this, ¶m, &mc1, &side]() { if (!mTracking->GetParam().par.continuousMaxTimeBin) { return param.Z() - mc1.z; } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index fdd95b091dfe7..8df5717537f2a 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -78,12 +78,12 @@ struct ClusterNativeAccess; } // namespace tpc } // namespace o2 -class AliHLTTPCClusterMCLabel; +struct AliHLTTPCClusterMCLabel; namespace GPUCA_NAMESPACE::gpu { class GPUChainTracking; -class GPUTPCMCInfo; +struct GPUTPCMCInfo; struct GPUQAGarbageCollection; class GPUQA diff --git a/GPU/GPUTracking/Standalone/qa/genEvents.cxx b/GPU/GPUTracking/Standalone/qa/genEvents.cxx index 914adcef3a8e8..4c99df72b8b46 100644 --- a/GPU/GPUTracking/Standalone/qa/genEvents.cxx +++ b/GPU/GPUTracking/Standalone/qa/genEvents.cxx @@ -91,7 +91,7 @@ double genEvents::GetGaus(double sigma) double x = 0; do { x = gRandom->Gaus(0., sigma); - if (fabsf(x) <= 3.5 * sigma) { + if (fabs(x) <= 3.5 * sigma) { break; } } while (1); diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx index ef8b167b85f16..49dbfb3390e8c 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx +++ b/GPU/GPUTracking/TRDTracking/GPUTRDTracker.cxx @@ -44,9 +44,9 @@ class GPUTPCGMPolynomialField; #include "TDatabasePDG.h" #include "AliMCParticle.h" #include "AliMCEvent.h" -static const float piMass = TDatabasePDG::Instance()->GetParticle(211)->Mass(); +//static const float piMass = TDatabasePDG::Instance()->GetParticle(211)->Mass(); #else -static const float piMass = 0.139f; +//static const float piMass = 0.139f; #endif #include "GPUChainTracking.h" @@ -267,6 +267,7 @@ void GPUTRDTracker_t<TRDTRK, PROP>::DoTracking(GPUChainTracking* chainTracking) } auto duration = std::chrono::high_resolution_clock::now() - timeStart; + (void)duration; // suppress warning about unused variable /* std::cout << "---> -----> -------> ---------> "; std::cout << "Time for event " << mNEvents << ": " << std::chrono::duration_cast<std::chrono::microseconds>(duration).count() << " us "; diff --git a/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h b/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h index be03655206c6b..309bdcf4cb569 100644 --- a/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h +++ b/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h @@ -287,7 +287,6 @@ inline void SemiregularSpline2D3D::correctEdges(T* data) const } { // ==== high edge of V ==== - const RegularSpline1D& gridU = getGridU(nv - 4); int nu = getGridU(nv - 1).getNumberOfKnots(); for (int iu = 0; iu < nu; iu++) { From cea7f0d788d55433d13c52a329d3abd49d59aeeb Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 1 Dec 2020 11:37:16 +0100 Subject: [PATCH 1465/1751] Unit test for EMC CCDB and CcdbApi fix Fixes https://alice.its.cern.ch/jira/browse/QC-501 --- CCDB/CMakeLists.txt | 6 ++ CCDB/src/CcdbApi.cxx | 14 ++++- CCDB/test/testCcdbApi_EMC.cxx | 101 ++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 CCDB/test/testCcdbApi_EMC.cxx diff --git a/CCDB/CMakeLists.txt b/CCDB/CMakeLists.txt index a91a3aa31347e..8be5917fb7330 100644 --- a/CCDB/CMakeLists.txt +++ b/CCDB/CMakeLists.txt @@ -57,6 +57,12 @@ o2_add_test(CcdbApi-Alien PUBLIC_LINK_LIBRARIES O2::CCDB LABELS ccdb) +o2_add_test(CcdbApi-EMC + SOURCES test/testCcdbApi_EMC.cxx + COMPONENT_NAME ccdb + PUBLIC_LINK_LIBRARIES O2::CCDB + LABELS ccdb) + o2_add_test(BasicCCDBManager SOURCES test/testBasicCCDBManager.cxx COMPONENT_NAME ccdb diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 67af9af6e638f..5bbe6bf085a04 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -763,10 +763,20 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con // we try content locations in order of appearance until one succeeds // 1st: The "Location" field // 2nd: Possible "Content-Location" fields - Location field + + // some locations are relative to the main server so we need to fix/complement them + auto complement_Location = [this](std::string const& loc) { + if (loc[0] == '/') { + // if it's just a path (noticed by trailing '/' we prepend the server url + return getURL() + loc; + } + return loc; + }; + std::vector<std::string> locs; auto iter = headerData.find("Location"); if (iter != headerData.end()) { - locs.push_back(iter->second); + locs.push_back(complement_Location(iter->second)); } // add alternative locations (not yet included) auto iter2 = headerData.find("Content-Location"); @@ -774,7 +784,7 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con auto range = headerData.equal_range("Content-Location"); for (auto it = range.first; it != range.second; ++it) { if (std::find(locs.begin(), locs.end(), it->second) == locs.end()) { - locs.push_back(it->second); + locs.push_back(complement_Location(it->second)); } } } diff --git a/CCDB/test/testCcdbApi_EMC.cxx b/CCDB/test/testCcdbApi_EMC.cxx new file mode 100644 index 0000000000000..5b15259ccd396 --- /dev/null +++ b/CCDB/test/testCcdbApi_EMC.cxx @@ -0,0 +1,101 @@ +// 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. + +/// Ccdb unit tests focusing on EMC setup +/// +/// \author Sandro Wenzel +/// + +#define BOOST_TEST_MODULE CCDB +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include "CCDB/CcdbApi.h" +#include <TH1.h> +#include <boost/test/unit_test.hpp> +#include <iostream> + +using namespace std; +using namespace o2::ccdb; +namespace utf = boost::unit_test; +namespace tt = boost::test_tools; + +static string ccdbUrl; +bool hostReachable = false; + +/** + * Global fixture, ie general setup and teardown + */ +struct Fixture { + Fixture() + { + CcdbApi api; + ccdbUrl = "http://emcccdb-test.cern.ch:8080"; + api.init(ccdbUrl); + cout << "ccdb url: " << ccdbUrl << endl; + hostReachable = api.isHostReachable(); + cout << "Is host reachable ? --> " << hostReachable << endl; + } +}; +BOOST_GLOBAL_FIXTURE(Fixture); + +/** + * Just an accessor to the hostReachable variable to be used to determine whether tests can be ran or not. + */ +struct if_reachable { + tt::assertion_result operator()(utf::test_unit_id) + { + return hostReachable; + } +}; + +/** + * Fixture for the tests, i.e. code is ran in every test that uses it, i.e. it is like a setup and teardown for tests. + */ +struct test_fixture { + test_fixture() + { + api.init(ccdbUrl); + metadata["Hello"] = "World"; + std::cout << "*** " << boost::unit_test::framework::current_test_case().p_name << " ***" << std::endl; + } + ~test_fixture() = default; + + CcdbApi api; + map<string, string> metadata; +}; + +// handle the case where the object comes from alien and redirect does not work with curl +BOOST_AUTO_TEST_CASE(retrieveTemplated_ALIEN, *utf::precondition(if_reachable())) +{ + test_fixture f; + + // try to retrieve an object from the production instance, including the headers + std::map<std::string, std::string> headers; + std::map<std::string, std::string> meta; + + std::string path("/qc/EMC/MO/CellTask/digitOccupancyEMC/1606419105647"); + { + auto* object = f.api.retrieveFromTFileAny<TH1>(path, meta, -1, &headers); + BOOST_CHECK(object != nullptr); + LOG(INFO) << headers["Content-Location"]; + if (object) { + BOOST_CHECK(headers.size() > 0); + LOG(INFO) << "Histo name " << object->GetName(); + LOG(INFO) << "Number of bins " << object->GetNbinsX() << " Mean " << object->GetMean(); + } + } + + // it should also work without headers of course + { + auto* object = f.api.retrieveFromTFileAny<TH1>(path, meta); + BOOST_CHECK(object != nullptr); + } +} From 346676d4d0910bc3e0ede24eeddb9925fdbaaf05 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 1 Dec 2020 16:04:13 +0100 Subject: [PATCH 1466/1751] Remove tmp test Removing tmp test for EMC-CCDB as it was primarily made to reproduce a problem and making sure it was fixed. I think we don't want to query too many different servers in our tests, as they also introduce external noise. --- CCDB/CMakeLists.txt | 6 -- CCDB/test/testCcdbApi_EMC.cxx | 101 ---------------------------------- 2 files changed, 107 deletions(-) delete mode 100644 CCDB/test/testCcdbApi_EMC.cxx diff --git a/CCDB/CMakeLists.txt b/CCDB/CMakeLists.txt index 8be5917fb7330..a91a3aa31347e 100644 --- a/CCDB/CMakeLists.txt +++ b/CCDB/CMakeLists.txt @@ -57,12 +57,6 @@ o2_add_test(CcdbApi-Alien PUBLIC_LINK_LIBRARIES O2::CCDB LABELS ccdb) -o2_add_test(CcdbApi-EMC - SOURCES test/testCcdbApi_EMC.cxx - COMPONENT_NAME ccdb - PUBLIC_LINK_LIBRARIES O2::CCDB - LABELS ccdb) - o2_add_test(BasicCCDBManager SOURCES test/testBasicCCDBManager.cxx COMPONENT_NAME ccdb diff --git a/CCDB/test/testCcdbApi_EMC.cxx b/CCDB/test/testCcdbApi_EMC.cxx deleted file mode 100644 index 5b15259ccd396..0000000000000 --- a/CCDB/test/testCcdbApi_EMC.cxx +++ /dev/null @@ -1,101 +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. - -/// Ccdb unit tests focusing on EMC setup -/// -/// \author Sandro Wenzel -/// - -#define BOOST_TEST_MODULE CCDB -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK - -#include "CCDB/CcdbApi.h" -#include <TH1.h> -#include <boost/test/unit_test.hpp> -#include <iostream> - -using namespace std; -using namespace o2::ccdb; -namespace utf = boost::unit_test; -namespace tt = boost::test_tools; - -static string ccdbUrl; -bool hostReachable = false; - -/** - * Global fixture, ie general setup and teardown - */ -struct Fixture { - Fixture() - { - CcdbApi api; - ccdbUrl = "http://emcccdb-test.cern.ch:8080"; - api.init(ccdbUrl); - cout << "ccdb url: " << ccdbUrl << endl; - hostReachable = api.isHostReachable(); - cout << "Is host reachable ? --> " << hostReachable << endl; - } -}; -BOOST_GLOBAL_FIXTURE(Fixture); - -/** - * Just an accessor to the hostReachable variable to be used to determine whether tests can be ran or not. - */ -struct if_reachable { - tt::assertion_result operator()(utf::test_unit_id) - { - return hostReachable; - } -}; - -/** - * Fixture for the tests, i.e. code is ran in every test that uses it, i.e. it is like a setup and teardown for tests. - */ -struct test_fixture { - test_fixture() - { - api.init(ccdbUrl); - metadata["Hello"] = "World"; - std::cout << "*** " << boost::unit_test::framework::current_test_case().p_name << " ***" << std::endl; - } - ~test_fixture() = default; - - CcdbApi api; - map<string, string> metadata; -}; - -// handle the case where the object comes from alien and redirect does not work with curl -BOOST_AUTO_TEST_CASE(retrieveTemplated_ALIEN, *utf::precondition(if_reachable())) -{ - test_fixture f; - - // try to retrieve an object from the production instance, including the headers - std::map<std::string, std::string> headers; - std::map<std::string, std::string> meta; - - std::string path("/qc/EMC/MO/CellTask/digitOccupancyEMC/1606419105647"); - { - auto* object = f.api.retrieveFromTFileAny<TH1>(path, meta, -1, &headers); - BOOST_CHECK(object != nullptr); - LOG(INFO) << headers["Content-Location"]; - if (object) { - BOOST_CHECK(headers.size() > 0); - LOG(INFO) << "Histo name " << object->GetName(); - LOG(INFO) << "Number of bins " << object->GetNbinsX() << " Mean " << object->GetMean(); - } - } - - // it should also work without headers of course - { - auto* object = f.api.retrieveFromTFileAny<TH1>(path, meta); - BOOST_CHECK(object != nullptr); - } -} From b6174e77c612e2b130aec38fe417c6a842dde33c Mon Sep 17 00:00:00 2001 From: Jan Fiete Grosse-Oetringhaus <jgrosseo@cern.ch> Date: Tue, 1 Dec 2020 13:08:03 +0100 Subject: [PATCH 1467/1751] keeping first error message (for Grid harvesting) --- Framework/Core/include/Framework/DeviceInfo.h | 1 + Framework/Core/src/runDataProcessing.cxx | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/DeviceInfo.h b/Framework/Core/include/Framework/DeviceInfo.h index 3cf0e1c46e105..f103484ef4322 100644 --- a/Framework/Core/include/Framework/DeviceInfo.h +++ b/Framework/Core/include/Framework/DeviceInfo.h @@ -45,6 +45,7 @@ struct DeviceInfo { /// A circular buffer for the severity of each of the entries /// in the circular buffer associated to the device. std::vector<LogParsingHelpers::LogLevel> historyLevel; + std::string firstError; std::string lastError; /// An unterminated string which is not ready to be printed yet std::string unprinted; diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 8507335cdb53b..839d7e6648999 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -283,7 +283,7 @@ int calculateExitCode(DeviceSpecs& deviceSpecs, DeviceInfos& infos) auto& spec = deviceSpecs[di]; if (exitCode == 0 && info.maxLogLevel >= LogParsingHelpers::LogLevel::Error) { LOG(ERROR) << "SEVERE: Device " << spec.name << " (" << info.pid << ") had at least one " - << "message above severity ERROR: " << std::regex_replace(info.lastError, regexp, ""); + << "message above severity ERROR: " << std::regex_replace(info.firstError, regexp, ""); exitCode = 1; } } @@ -699,6 +699,9 @@ LogProcessingState processChildrenOutput(DriverInfo& driverInfo, } if (logLevel == LogParsingHelpers::LogLevel::Error) { info.lastError = token; + if (info.firstError.empty()) { + info.firstError = token; + } } s.remove_prefix(pos + delimiter.length()); } From d8fd25c8463e0b0a93da8d1d0b47c853b8e682e4 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 1 Dec 2020 10:36:21 +0100 Subject: [PATCH 1468/1751] Fix MCTrack::isPrimary and generation from O2 kinematics --- .../simulation/include/SimulationDataFormat/MCTrack.h | 11 ++++++----- Generators/src/GeneratorFromFile.cxx | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h index 18e5cb7da3619..307e398453884 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTrack.h @@ -61,7 +61,8 @@ class MCTrackT Int_t GetPdgCode() const { return mPdgCode; } Int_t getMotherTrackId() const { return mMotherTrackId; } Int_t getSecondMotherTrackId() const { return mSecondMotherTrackId; } - bool isSecondary() const { return mMotherTrackId != -1; } + bool isPrimary() const { return getProcess() == TMCProcess::kPPrimary; } + bool isSecondary() const { return !isPrimary(); } Int_t getFirstDaughterTrackId() const { return mFirstDaughterTrackId; } Int_t getLastDaughterTrackId() const { return mLastDaughterTrackId; } Double_t GetStartVertexMomentumX() const { return mStartVertexMomentumX; } @@ -207,11 +208,11 @@ class MCTrackT Int_t mPdgCode; /// Index of mother tracks - Int_t mMotherTrackId; - Int_t mSecondMotherTrackId; + Int_t mMotherTrackId = -1; + Int_t mSecondMotherTrackId = -1; - Int_t mFirstDaughterTrackId; - Int_t mLastDaughterTrackId; + Int_t mFirstDaughterTrackId = -1; + Int_t mLastDaughterTrackId = -1; // hitmask stored as an int // if bit i is set it means that this track left a trace in detector i // we should have sizeof(int) < o2::base::DetId::nDetectors diff --git a/Generators/src/GeneratorFromFile.cxx b/Generators/src/GeneratorFromFile.cxx index 9531c4c3435e4..2afa5699798e3 100644 --- a/Generators/src/GeneratorFromFile.cxx +++ b/Generators/src/GeneratorFromFile.cxx @@ -208,7 +208,7 @@ Bool_t GeneratorFromO2Kine::ReadEvent(FairPrimaryGenerator* primGen) auto vx = p.Vx(); auto vy = p.Vy(); auto vz = p.Vz(); - auto parent = -1; // --> check this !!! + auto parent = p.getMotherTrackId(); auto e = p.GetEnergy(); auto tof = p.T(); auto weight = 1.; // p.GetWeight() ??; From 299529a9c22ef45b62dcc498e1b9f7e4bf00b8c8 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 1 Dec 2020 10:38:34 +0100 Subject: [PATCH 1469/1751] Extend simulatin example: Test generation from previous kinematics --- run/SimExamples/JustPrimaryKinematics/run.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/run/SimExamples/JustPrimaryKinematics/run.sh b/run/SimExamples/JustPrimaryKinematics/run.sh index eea02105c1a51..018df38f10976 100644 --- a/run/SimExamples/JustPrimaryKinematics/run.sh +++ b/run/SimExamples/JustPrimaryKinematics/run.sh @@ -5,4 +5,10 @@ # Here the mechanism is to switch off physics in the configuration file and set very # tight geometry cuts so that Geant will not do work. -o2-sim -n 10 -g pythia8 -m CAVE --configFile only_kine.ini +# first stage --> produce events using Pythia8 (no transport) +o2-sim -n 10 -g pythia8 -m CAVE --configFile only_primarykine.ini + +# second stage --> read back events from O2 kine (no transport) +o2-sim -n 10 -g extkinO2 --extKinFile o2sim_Kine.root -m CAVE --configFile only_primarykine.ini -o o2sim2 + +# ideally here, both kinematics files should be identical From eeaa474a0058ad2e80eff56b0aef45927c0e7589 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 1 Dec 2020 20:37:57 +0400 Subject: [PATCH 1470/1751] Fix: use p.vertex.Z instead of meanVtx.Z in cos_pointing angle calculation --- Detectors/Vertexing/src/SVertexer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index cd659acee7e81..b6e8a52e1af05 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -167,7 +167,7 @@ void SVertexer::process(const gsl::span<const PVertex>& vertices, // primary v continue; } // check cos of pointing angle - float dz = v0pos[2] - mMeanVertex.getZ(), cosPointingAngle = (prodXY + dz * pV0[2]) / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + float dz = v0pos[2] - pv.getZ(), cosPointingAngle = (prodXY + dz * pV0[2]) / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); if (cosPointingAngle < mMinCosPointingAngle) { if (ambiguousV0) { continue; // no need to check this pair wrt other vertices From 6f936ff16b05c333c0f24d02a473814b61c75440 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 1 Dec 2020 20:51:55 +0100 Subject: [PATCH 1471/1751] Update DetectorSimulation.md --- doc/DetectorSimulation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index e0249053a4fd1..e3a5647ea026b 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -441,6 +441,8 @@ for (int pos = 0; pos < alldigits.size(); ++pos) { } } ``` +Note, that one can also access kinematics directly after the transport simulation. +In this case, one needs to initialize the MCKinematicsReader in a different mode. # Simulation tutorials/examples <a name="Examples"></a> From 83c1a60ded559110bc9750c4b37753ac73d4b3c4 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 1 Dec 2020 21:07:04 +0100 Subject: [PATCH 1472/1751] DPL Analysis: report bytes read in kB (#4957) --- Framework/Core/src/AODReaderHelpers.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 5b7ebb5ba3e05..6e179e0da719f 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -318,8 +318,8 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() first = false; } - monitoring.send(Metric{(uint64_t)totalSizeUncompressed, "aod-bytes-read-uncompressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - monitoring.send(Metric{(uint64_t)totalSizeCompressed, "aod-bytes-read-compressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)totalSizeUncompressed / 1000, "aod-bytes-read-uncompressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)totalSizeCompressed / 1000, "aod-bytes-read-compressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); monitoring.send(Metric{(uint64_t)totalReadCalls, "aod-total-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); // save file number and time frame From 4e8c968c9e8cf2f915d4c3550ad67b183db59b18 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 1 Dec 2020 21:55:31 +0100 Subject: [PATCH 1473/1751] Move Doxygen to Github actions (#4969) --- .github/workflows/doxygen.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/doxygen.yml diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml new file mode 100644 index 0000000000000..a39f2925b672e --- /dev/null +++ b/.github/workflows/doxygen.yml @@ -0,0 +1,17 @@ +name: Build Documentation + +on: + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Install doxygen + run: sudo apt-get install doxygen doxygen-doc doxygen-latex doxygen-gui graphviz cmake + - name: Install doxygen + run: | + cat > CMakeLists.txt <<\EOF + add_subdirectory(doc) + EOF + cmake . + make doc From 2a2ea15420e7b21e4dc93dbbfadf0e3019aff2dd Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 1 Dec 2020 21:58:04 +0100 Subject: [PATCH 1474/1751] Install with -y --- .github/workflows/doxygen.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index a39f2925b672e..e576e4a77ff58 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Install doxygen - run: sudo apt-get install doxygen doxygen-doc doxygen-latex doxygen-gui graphviz cmake + run: sudo apt-get install -y doxygen doxygen-doc doxygen-latex doxygen-gui graphviz cmake - name: Install doxygen run: | cat > CMakeLists.txt <<\EOF From ec5eb1f1f3b41716183787ece4cbafbfc0e63e6e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 1 Dec 2020 22:01:30 +0100 Subject: [PATCH 1475/1751] Update doxygen.yml --- .github/workflows/doxygen.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index e576e4a77ff58..066943d456dd3 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -7,7 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Install doxygen - run: sudo apt-get install -y doxygen doxygen-doc doxygen-latex doxygen-gui graphviz cmake + run: | + sudo apt-get update -y + sudo apt-get install -y doxygen doxygen-doc doxygen-latex doxygen-gui graphviz cmake - name: Install doxygen run: | cat > CMakeLists.txt <<\EOF From 2f2a644713fe45854a28e94321f1019d99f1384d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 1 Dec 2020 22:09:49 +0100 Subject: [PATCH 1476/1751] Update doxygen.yml --- .github/workflows/doxygen.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 066943d456dd3..e05316740a93f 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -10,6 +10,9 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y doxygen doxygen-doc doxygen-latex doxygen-gui graphviz cmake + - uses: actions/checkout@v2 + with: + ref: "dev" - name: Install doxygen run: | cat > CMakeLists.txt <<\EOF From 80faf705037a2fe6514fc96c1e763473ec5ba432 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 1 Dec 2020 22:30:58 +0100 Subject: [PATCH 1477/1751] Update doxygen.yml --- .github/workflows/doxygen.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index e05316740a93f..bb3b08ea69aab 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -20,3 +20,9 @@ jobs: EOF cmake . make doc + git add doc/html + git config --global user.email "github-action-bot@example.com" + git config --global user.name "GitHub Action Bot" + git commit -m "Updated README" -a || echo "No changes to commit" + git push origin `git subtree split --prefix doc/html dev`:refs/heads/gh-pages --force + From 16e8aa6709c9a7bb9df98dad56bb207e401d0190 Mon Sep 17 00:00:00 2001 From: saganatt <mkabus@cern.ch> Date: Tue, 1 Dec 2020 23:28:07 +0100 Subject: [PATCH 1478/1751] Fixed OutputObj sink to process custom TList correctly (#4945) --- Analysis/Tutorials/src/histogramRegistry.cxx | 32 ++++++++++++++++++- .../Core/include/Framework/AnalysisHelpers.h | 9 ++++-- .../include/Framework/HistogramRegistry.h | 2 +- .../Core/include/Framework/OutputObjHeader.h | 11 ++++++- Framework/Core/src/CommonDataProcessors.cxx | 7 ++-- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index fdecd0a8596c3..e32172e286021 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -12,6 +12,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/HistogramRegistry.h" #include <TH1F.h> +#include <TParameter.h> #include <cmath> @@ -212,6 +213,34 @@ struct ETask { } }; +struct FTask { + Configurable<int> cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = global tracks FB96"}; + OutputObj<TList> fOutput{"TListForTests", OutputObjHandlingPolicy::AnalysisObject, OutputObjSourceType::OutputObjSource}; + HistogramRegistry registry{ + "registry", + { + {"eta", "#eta", {HistType::kTH1F, {{102, -2.01, 2.01}}}}, // + {"phi", "#varphi", {HistType::kTH1F, {{100, 0., 2. * M_PI}}}} // + } // + }; + + void init(InitContext const&) + { + TList* fOutputList = new TList(); + fOutputList->SetOwner(true); + fOutput.setObject(fOutputList); + fOutputList->Add(new TParameter<Int_t>("TrackType", cfgTrackType, 'f')); + } + + void process(aod::Tracks const& tracks) + { + for (auto& track : tracks) { + registry.get<TH1>("eta")->Fill(track.eta()); + registry.get<TH1>("phi")->Fill(track.phi()); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ @@ -219,5 +248,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) adaptAnalysisTask<ATask>("eta-and-phi-histograms"), adaptAnalysisTask<BTask>("filtered-histograms"), adaptAnalysisTask<CTask>("dimension-test"), - adaptAnalysisTask<DTask>("realistic-example")}; + adaptAnalysisTask<DTask>("realistic-example"), + adaptAnalysisTask<FTask>("tlist-test")}; } diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index a6376e57e0cf1..169deddc8a512 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -367,18 +367,20 @@ template <typename T> struct OutputObj { using obj_t = T; - OutputObj(T&& t, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) + OutputObj(T&& t, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, OutputObjSourceType sourceType_ = OutputObjSourceType::OutputObjSource) : object(std::make_shared<T>(t)), label(t.GetName()), policy{policy_}, + sourceType{sourceType_}, mTaskHash{0} { } - OutputObj(std::string const& label_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject) + OutputObj(std::string const& label_, OutputObjHandlingPolicy policy_ = OutputObjHandlingPolicy::AnalysisObject, OutputObjSourceType sourceType_ = OutputObjSourceType::OutputObjSource) : object(nullptr), label(label_), policy{policy_}, + sourceType{sourceType_}, mTaskHash{0} { } @@ -439,12 +441,13 @@ struct OutputObj { OutputRef ref() { return OutputRef{std::string{label}, 0, - o2::header::Stack{OutputObjHeader{policy, mTaskHash}}}; + o2::header::Stack{OutputObjHeader{policy, sourceType, mTaskHash}}}; } std::shared_ptr<T> object; std::string label; OutputObjHandlingPolicy policy; + OutputObjSourceType sourceType; uint32_t mTaskHash; }; diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 2b7d0e3aa1e83..bbccb3faad4d5 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -539,7 +539,7 @@ class HistogramRegistry OutputRef ref() { - return OutputRef{std::string{mName}, 0, o2::header::Stack{OutputObjHeader{mPolicy, mTaskHash}}}; + return OutputRef{std::string{mName}, 0, o2::header::Stack{OutputObjHeader{mPolicy, OutputObjSourceType::HistogramRegistrySource, mTaskHash}}}; } void setHash(uint32_t hash) diff --git a/Framework/Core/include/Framework/OutputObjHeader.h b/Framework/Core/include/Framework/OutputObjHeader.h index ba539382db286..e31bee11eb302 100644 --- a/Framework/Core/include/Framework/OutputObjHeader.h +++ b/Framework/Core/include/Framework/OutputObjHeader.h @@ -26,6 +26,12 @@ enum OutputObjHandlingPolicy : unsigned int { numPolicies }; +enum OutputObjSourceType : unsigned int { + OutputObjSource, + HistogramRegistrySource, + numTypes +}; + /// @struct OutputObjHeader /// @brief O2 header for OutputObj metadata struct OutputObjHeader : public BaseHeader { @@ -33,15 +39,18 @@ struct OutputObjHeader : public BaseHeader { constexpr static const o2::header::HeaderType sHeaderType = "OutObjMD"; constexpr static const o2::header::SerializationMethod sSerializationMethod = o2::header::gSerializationMethodNone; OutputObjHandlingPolicy mPolicy; + OutputObjSourceType mSourceType; uint32_t mTaskHash; constexpr OutputObjHeader() : BaseHeader(sizeof(OutputObjHeader), sHeaderType, sSerializationMethod, sVersion), mPolicy{OutputObjHandlingPolicy::AnalysisObject}, + mSourceType{OutputObjSourceType::OutputObjSource}, mTaskHash{0} {} - constexpr OutputObjHeader(OutputObjHandlingPolicy policy, uint32_t hash) + constexpr OutputObjHeader(OutputObjHandlingPolicy policy, OutputObjSourceType sourceType, uint32_t hash) : BaseHeader(sizeof(OutputObjHeader), sHeaderType, sSerializationMethod, sVersion), mPolicy{policy}, + mSourceType{sourceType}, mTaskHash{hash} {} constexpr OutputObjHeader(OutputObjHeader const&) = default; }; diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 5132375603223..50cae08dd1c46 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -60,6 +60,7 @@ struct InputObjectRoute { std::string directory; uint32_t taskHash; OutputObjHandlingPolicy policy; + OutputObjSourceType sourceType; }; struct InputObject { @@ -123,8 +124,7 @@ DataProcessorSpec CommonDataProcessors::getOutputObjHistSink(outputObjects const }; TDirectory* currentDir = f[route.policy]->GetDirectory(currentDirectory.c_str()); - TNamed* named = static_cast<TNamed*>(entry.obj); - if (named->InheritsFrom(TList::Class())) { + if (route.sourceType == OutputObjSourceType::HistogramRegistrySource) { TList* outputList = (TList*)entry.obj; outputList->SetOwner(false); @@ -185,6 +185,7 @@ DataProcessorSpec CommonDataProcessors::getOutputObjHistSink(outputObjects const } auto policy = objh->mPolicy; + auto sourceType = objh->mSourceType; auto hash = objh->mTaskHash; obj.obj = tm.ReadObjectAny(obj.kind); @@ -207,7 +208,7 @@ DataProcessorSpec CommonDataProcessors::getOutputObjHistSink(outputObjects const return; } auto nameHash = compile_time_hash(obj.name.c_str()); - InputObjectRoute key{obj.name, nameHash, taskname, hash, policy}; + InputObjectRoute key{obj.name, nameHash, taskname, hash, policy, sourceType}; auto existing = std::find_if(inputObjects->begin(), inputObjects->end(), [&](auto&& x) { return (x.first.uniqueId == nameHash) && (x.first.taskHash == hash); }); if (existing == inputObjects->end()) { inputObjects->push_back(std::make_pair(key, obj)); From 779b8b893d2c74d4618ed0b0a80fe1e94233a14e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:40:43 +0100 Subject: [PATCH 1479/1751] Update doxygen.yml --- .github/workflows/doxygen.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index bb3b08ea69aab..5cd4f583d275c 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -1,6 +1,9 @@ name: Build Documentation on: + push: + branches: + - 'dev' workflow_dispatch: jobs: build: From 570d47d3b25765d608f6524b0915c864d504af24 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 2 Dec 2020 07:37:17 +0100 Subject: [PATCH 1480/1751] DPL Analysis: tweak ROOT caching and prefetching (#4973) This tweaks the cache and Readahead buffer of ROOT to minimize the number of ReadCalls. --- Framework/Core/src/AODReaderHelpers.cxx | 6 +++++- Framework/Core/src/DataInputDirector.cxx | 1 + Framework/Core/src/TableTreeHelpers.cxx | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 6e179e0da719f..bbea0b177e852 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -33,6 +33,8 @@ #include <ROOT/RDataFrame.hxx> #include <TGrid.h> #include <TFile.h> +#include <TTreeCache.h> +#include <TTreePerfStats.h> #include <arrow/ipc/reader.h> #include <arrow/ipc/writer.h> @@ -283,7 +285,8 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() throw std::runtime_error("Processing is stopped!"); } } - tr->SetCacheSize(0); + TTreePerfStats ps("ioperf", tr); + if (first) { timeFrameNumber = didir->getTimeFrameNumber(dh, fcnt, ntf); auto o = Output(TFNumberHeader); @@ -314,6 +317,7 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() if (info.file) { totalReadCalls += info.file->GetReadCalls() - before; } + monitoring.send(Metric{(double)ps.GetReadCalls(), "aod-tree-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); delete tr; first = false; diff --git a/Framework/Core/src/DataInputDirector.cxx b/Framework/Core/src/DataInputDirector.cxx index 24dd25cdc7b90..e5143a10637d8 100644 --- a/Framework/Core/src/DataInputDirector.cxx +++ b/Framework/Core/src/DataInputDirector.cxx @@ -102,6 +102,7 @@ bool DataInputDescriptor::setFile(int counter) if (!mcurrentFile) { throw std::runtime_error(fmt::format("Couldn't open file \"{}\"!", filename)); } + mcurrentFile->SetReadaheadSize(50 * 1024 * 1024); // get the directory names if (mfilenames[counter]->numberOfTimeFrames <= 0) { diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 6f0537fdfdbf1..cdd9054b0f90f 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -863,7 +863,10 @@ void TreeToTable::fill(TTree* tree) std::vector<std::unique_ptr<ColumnIterator>> columnIterators; TTreeReader treeReader{tree}; + tree->SetCacheSize(50000000); + tree->SetClusterPrefetch(true); for (auto&& columnName : mColumnNames) { + tree->AddBranchToCache(columnName.c_str(), true); auto colit = std::make_unique<ColumnIterator>(treeReader, columnName.c_str()); auto stat = colit->getStatus(); if (!stat) { @@ -871,6 +874,7 @@ void TreeToTable::fill(TTree* tree) } columnIterators.push_back(std::move(colit)); } + tree->StopCacheLearningPhase(); auto numEntries = treeReader.GetEntries(true); for (auto&& column : columnIterators) { From dd41db2609994e3119ecc384799089d2229a7f58 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 1 Dec 2020 18:38:30 +0400 Subject: [PATCH 1481/1751] Add ITS/MFT trigger counter to link statistics --- .../include/ITSMFTReconstruction/DecodingStat.h | 6 ++++-- .../reconstruction/include/ITSMFTReconstruction/GBTLink.h | 2 ++ Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h index f93d17141eb28..260160052ab2d 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h @@ -138,20 +138,22 @@ struct GBTLinkDecodingStat { uint32_t ruLinkID = 0; // Link ID within RU // Note: packet here is meant as a group of CRU pages belonging to the same trigger - uint32_t nPackets = 0; // total number of packets + uint32_t nPackets = 0; // total number of packets (RDH pages) + uint32_t nTriggers = 0; // total number of triggers (ROFs) std::array<uint32_t, NErrorsDefined> errorCounts = {}; // error counters std::array<uint32_t, GBTDataTrailer::MaxStateCombinations> packetStates = {}; // packet status from the trailer void clear() { nPackets = 0; + nTriggers = 0; errorCounts.fill(0); packetStates.fill(0); } void print(bool skipEmpty = true) const; - ClassDefNV(GBTLinkDecodingStat, 1); + ClassDefNV(GBTLinkDecodingStat, 2); }; } // namespace itsmft diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h index f8e459f31d407..c38aae4d8e215 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.h @@ -249,6 +249,7 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) printTrigger(gbtTrg); } GBTLINK_DECODE_ERRORCHECK(errRes, checkErrorsTriggerWord(gbtTrg)); + statistics.nTriggers++; if (gbtTrg->noData) { // emtpy trigger return status; } @@ -309,6 +310,7 @@ GBTLink::CollectedDataStatus GBTLink::collectROFCableData(const Mapping& chmap) ir = RDHUtils::getTriggerIR(*lastRDH); trigger = RDHUtils::getTriggerType(*lastRDH); } + return (status = DataSeen); } diff --git a/Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx b/Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx index 270b6bd129c44..295a458cc9a46 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/DecodingStat.cxx @@ -52,7 +52,7 @@ void GBTLinkDecodingStat::print(bool skipEmpty) const for (int i = NErrorsDefined; i--;) { nErr += errorCounts[i]; } - LOGF(INFO, "GBTLink#0x%d Packet States Statistics (total packets: %d)", ruLinkID, nPackets); + LOGF(INFO, "GBTLink#0x%d Packet States Statistics (total packets: %d, triggers: %d)", ruLinkID, nPackets, nTriggers); for (int i = 0; i < GBTDataTrailer::MaxStateCombinations; i++) { if (packetStates[i]) { std::bitset<GBTDataTrailer::NStatesDefined> patt(i); From b182217b466f8dbe7a8442d34dc2393f16e7dca6 Mon Sep 17 00:00:00 2001 From: peressounko <Dmitri.Peressounko@Cern.ch> Date: Wed, 2 Dec 2020 10:26:44 +0300 Subject: [PATCH 1482/1751] Code to write and reconstruct raw data analysis (#4953) * Raw data analysis * clanged * Revert * executable added * Exception handling improved * Exception handling improved * allow split raw output Co-authored-by: Dmitri Peresunko <Dmitri.Peresunko@cern.ch> --- Detectors/PHOS/base/CMakeLists.txt | 7 +- Detectors/PHOS/base/files/Mod0RCU0.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod0RCU1.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod0RCU2.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod0RCU3.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod1RCU0.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod1RCU1.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod1RCU2.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod1RCU3.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod2RCU0.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod2RCU1.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod2RCU2.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod2RCU3.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod3RCU0.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod3RCU1.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod3RCU2.data | 2050 +++++++++++++++++ Detectors/PHOS/base/files/Mod3RCU3.data | 2050 +++++++++++++++++ .../PHOS/base/include/PHOSBase/Mapping.h | 85 + .../base/include/PHOSBase/PHOSSimParams.h | 13 + .../PHOS/base/include/PHOSBase/RCUTrailer.h | 185 ++ Detectors/PHOS/base/src/Geometry.cxx | 33 +- Detectors/PHOS/base/src/Mapping.cxx | 166 ++ Detectors/PHOS/base/src/RCUTrailer.cxx | 240 ++ Detectors/PHOS/reconstruction/CMakeLists.txt | 26 +- .../include/PHOSReconstruction/AltroDecoder.h | 138 ++ .../include/PHOSReconstruction/Bunch.h | 103 + .../PHOSReconstruction/CaloRawFitter.h | 113 + .../include/PHOSReconstruction/Channel.h | 160 ++ .../include/PHOSReconstruction/RawBuffer.h | 89 + .../PHOSReconstruction/RawDecodingError.h | 85 + .../PHOSReconstruction/RawHeaderStream.h | 38 + .../include/PHOSReconstruction/RawPayload.h | 89 + .../PHOSReconstruction/RawReaderError.h | 53 + .../PHOSReconstruction/RawReaderMemory.h | 129 ++ .../PHOS/reconstruction/run/rawReaderFile.cxx | 119 + .../PHOS/reconstruction/src/AltroDecoder.cxx | 116 + Detectors/PHOS/reconstruction/src/Bunch.cxx | 18 + .../PHOS/reconstruction/src/CaloRawFitter.cxx | 323 +++ Detectors/PHOS/reconstruction/src/Channel.cxx | 46 + .../PHOS/reconstruction/src/RawBuffer.cxx | 74 + .../reconstruction/src/RawHeaderStream.cxx | 106 + .../PHOS/reconstruction/src/RawPayload.cxx | 32 + .../reconstruction/src/RawReaderMemory.cxx | 190 ++ Detectors/PHOS/simulation/CMakeLists.txt | 15 +- .../include/PHOSSimulation/RawWriter.h | 124 + Detectors/PHOS/simulation/src/Digitizer.cxx | 5 +- .../simulation/src/PHOSSimulationLinkDef.h | 1 + Detectors/PHOS/simulation/src/RawCreator.cxx | 108 + Detectors/PHOS/simulation/src/RawWriter.cxx | 364 +++ Detectors/PHOS/workflow/CMakeLists.txt | 9 +- .../PHOSWorkflow/RawToCellConverterSpec.h | 84 + .../include/PHOSWorkflow/RawWriterSpec.h | 71 + .../PHOS/workflow/src/CellConverterSpec.cxx | 11 +- .../PHOS/workflow/src/ClusterizerSpec.cxx | 4 +- .../workflow/src/RawToCellConverterSpec.cxx | 269 +++ Detectors/PHOS/workflow/src/RawWriterSpec.cxx | 70 + Detectors/PHOS/workflow/src/RecoWorkflow.cxx | 159 +- 57 files changed, 36734 insertions(+), 136 deletions(-) create mode 100644 Detectors/PHOS/base/files/Mod0RCU0.data create mode 100644 Detectors/PHOS/base/files/Mod0RCU1.data create mode 100644 Detectors/PHOS/base/files/Mod0RCU2.data create mode 100644 Detectors/PHOS/base/files/Mod0RCU3.data create mode 100644 Detectors/PHOS/base/files/Mod1RCU0.data create mode 100644 Detectors/PHOS/base/files/Mod1RCU1.data create mode 100644 Detectors/PHOS/base/files/Mod1RCU2.data create mode 100644 Detectors/PHOS/base/files/Mod1RCU3.data create mode 100644 Detectors/PHOS/base/files/Mod2RCU0.data create mode 100644 Detectors/PHOS/base/files/Mod2RCU1.data create mode 100644 Detectors/PHOS/base/files/Mod2RCU2.data create mode 100644 Detectors/PHOS/base/files/Mod2RCU3.data create mode 100644 Detectors/PHOS/base/files/Mod3RCU0.data create mode 100644 Detectors/PHOS/base/files/Mod3RCU1.data create mode 100644 Detectors/PHOS/base/files/Mod3RCU2.data create mode 100644 Detectors/PHOS/base/files/Mod3RCU3.data create mode 100644 Detectors/PHOS/base/include/PHOSBase/Mapping.h create mode 100644 Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h create mode 100644 Detectors/PHOS/base/src/Mapping.cxx create mode 100644 Detectors/PHOS/base/src/RCUTrailer.cxx create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/Bunch.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/CaloRawFitter.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/Channel.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawBuffer.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawDecodingError.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawHeaderStream.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderError.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h create mode 100644 Detectors/PHOS/reconstruction/run/rawReaderFile.cxx create mode 100644 Detectors/PHOS/reconstruction/src/AltroDecoder.cxx create mode 100644 Detectors/PHOS/reconstruction/src/Bunch.cxx create mode 100644 Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx create mode 100644 Detectors/PHOS/reconstruction/src/Channel.cxx create mode 100644 Detectors/PHOS/reconstruction/src/RawBuffer.cxx create mode 100644 Detectors/PHOS/reconstruction/src/RawHeaderStream.cxx create mode 100644 Detectors/PHOS/reconstruction/src/RawPayload.cxx create mode 100644 Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx create mode 100644 Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h create mode 100644 Detectors/PHOS/simulation/src/RawCreator.cxx create mode 100644 Detectors/PHOS/simulation/src/RawWriter.cxx create mode 100644 Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h create mode 100644 Detectors/PHOS/workflow/include/PHOSWorkflow/RawWriterSpec.h create mode 100644 Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx create mode 100644 Detectors/PHOS/workflow/src/RawWriterSpec.cxx diff --git a/Detectors/PHOS/base/CMakeLists.txt b/Detectors/PHOS/base/CMakeLists.txt index 7c95cac985a23..cd8ee57bc8a17 100644 --- a/Detectors/PHOS/base/CMakeLists.txt +++ b/Detectors/PHOS/base/CMakeLists.txt @@ -12,10 +12,15 @@ o2_add_library(PHOSBase SOURCES src/Geometry.cxx src/Hit.cxx src/PHOSSimParams.cxx + src/RCUTrailer.cxx + src/Mapping.cxx PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::SimConfig) o2_target_root_dictionary(PHOSBase HEADERS include/PHOSBase/Geometry.h include/PHOSBase/Hit.h - include/PHOSBase/PHOSSimParams.h) + include/PHOSBase/PHOSSimParams.h + include/PHOSBase/RCUTrailer.h + include/PHOSBase/Mapping.h) +o2_data_file(COPY files DESTINATION Detectors/PHOS) diff --git a/Detectors/PHOS/base/files/Mod0RCU0.data b/Detectors/PHOS/base/files/Mod0RCU0.data new file mode 100644 index 0000000000000..4739df6e3e61e --- /dev/null +++ b/Detectors/PHOS/base/files/Mod0RCU0.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 0 0 2 + 1 0 1 2 + 2 0 2 2 + 3 0 3 2 + 4 0 4 2 + 5 0 5 2 + 6 0 6 2 + 7 0 7 2 + 8 0 8 2 + 9 0 9 2 + 10 0 10 2 + 11 0 11 2 + 12 0 12 2 + 13 0 13 2 + 14 0 14 2 + 15 0 15 2 + 16 0 16 2 + 17 0 17 2 + 18 0 18 2 + 19 0 19 2 + 20 0 20 2 + 21 0 21 2 + 22 0 22 2 + 23 0 23 2 + 24 0 24 2 + 25 0 25 2 + 26 0 26 2 + 27 0 27 2 + 28 0 28 2 + 29 0 29 2 + 30 0 30 2 + 31 0 31 2 + 32 0 32 2 + 33 0 33 2 + 34 0 34 2 + 35 0 35 2 + 36 0 36 2 + 37 0 37 2 + 38 0 38 2 + 39 0 39 2 + 40 0 40 2 + 41 0 41 2 + 42 0 42 2 + 43 0 43 2 + 44 0 44 2 + 45 0 45 2 + 46 0 46 2 + 47 0 47 2 + 48 0 48 2 + 49 0 49 2 + 50 0 50 2 + 51 0 51 2 + 52 0 52 2 + 53 0 53 2 + 54 0 54 2 + 55 0 55 2 + 56 0 56 2 + 57 0 57 2 + 58 0 58 2 + 59 0 59 2 + 60 0 60 2 + 61 0 61 2 + 62 0 62 2 + 63 0 63 2 + 64 0 64 2 + 65 0 65 2 + 66 0 66 2 + 67 0 67 2 + 68 0 68 2 + 69 0 69 2 + 70 0 70 2 + 71 0 71 2 + 72 0 72 2 + 73 0 73 2 + 74 0 74 2 + 75 0 75 2 + 76 0 76 2 + 77 0 77 2 + 78 0 78 2 + 79 0 79 2 + 80 0 80 2 + 81 0 81 2 + 82 0 82 2 + 83 0 83 2 + 84 0 84 2 + 85 0 85 2 + 86 0 86 2 + 87 0 87 2 + 88 0 88 2 + 89 0 89 2 + 90 0 90 2 + 91 0 91 2 + 92 0 92 2 + 93 0 93 2 + 94 0 94 2 + 95 0 95 2 + 96 0 96 2 + 97 0 97 2 + 98 0 98 2 + 99 0 99 2 + 100 0 100 2 + 101 0 101 2 + 102 0 102 2 + 103 0 103 2 + 104 0 104 2 + 105 0 105 2 + 106 0 106 2 + 107 0 107 2 + 108 0 108 2 + 109 0 109 2 + 110 0 110 2 + 111 0 111 2 + 112 0 112 2 + 113 0 113 2 + 114 0 114 2 + 115 0 115 2 + 116 0 116 2 + 117 0 117 2 + 118 0 118 2 + 119 0 119 2 + 120 0 120 2 + 121 0 121 2 + 122 0 122 2 + 123 0 123 2 + 124 0 124 2 + 125 0 125 2 + 126 0 126 2 + 127 0 127 2 +2048 0 2048 2 +2049 0 2049 2 +2050 0 2050 2 +2051 0 2051 2 +2052 0 2052 2 +2053 0 2053 2 +2054 0 2054 2 +2055 0 2055 2 +2056 0 2056 2 +2057 0 2057 2 +2058 0 2058 2 +2059 0 2059 2 +2060 0 2060 2 +2061 0 2061 2 +2062 0 2062 2 +2063 0 2063 2 +2064 0 2064 2 +2065 0 2065 2 +2066 0 2066 2 +2067 0 2067 2 +2068 0 2068 2 +2069 0 2069 2 +2070 0 2070 2 +2071 0 2071 2 +2072 0 2072 2 +2073 0 2073 2 +2074 0 2074 2 +2075 0 2075 2 +2076 0 2076 2 +2077 0 2077 2 +2078 0 2078 2 +2079 0 2079 2 +2080 0 2080 2 +2081 0 2081 2 +2082 0 2082 2 +2083 0 2083 2 +2084 0 2084 2 +2085 0 2085 2 +2086 0 2086 2 +2087 0 2087 2 +2088 0 2088 2 +2089 0 2089 2 +2090 0 2090 2 +2091 0 2091 2 +2092 0 2092 2 +2093 0 2093 2 +2094 0 2094 2 +2095 0 2095 2 +2096 0 2096 2 +2097 0 2097 2 +2098 0 2098 2 +2099 0 2099 2 +2100 0 2100 2 +2101 0 2101 2 +2102 0 2102 2 +2103 0 2103 2 +2104 0 2104 2 +2105 0 2105 2 +2106 0 2106 2 +2107 0 2107 2 +2108 0 2108 2 +2109 0 2109 2 +2110 0 2110 2 +2111 0 2111 2 +2112 0 2112 2 +2113 0 2113 2 +2114 0 2114 2 +2115 0 2115 2 +2116 0 2116 2 +2117 0 2117 2 +2118 0 2118 2 +2119 0 2119 2 +2120 0 2120 2 +2121 0 2121 2 +2122 0 2122 2 +2123 0 2123 2 +2124 0 2124 2 +2125 0 2125 2 +2126 0 2126 2 +2127 0 2127 2 +2128 0 2128 2 +2129 0 2129 2 +2130 0 2130 2 +2131 0 2131 2 +2132 0 2132 2 +2133 0 2133 2 +2134 0 2134 2 +2135 0 2135 2 +2136 0 2136 2 +2137 0 2137 2 +2138 0 2138 2 +2139 0 2139 2 +2140 0 2140 2 +2141 0 2141 2 +2142 0 2142 2 +2143 0 2143 2 +2144 0 2144 2 +2145 0 2145 2 +2146 0 2146 2 +2147 0 2147 2 +2148 0 2148 2 +2149 0 2149 2 +2150 0 2150 2 +2151 0 2151 2 +2152 0 2152 2 +2153 0 2153 2 +2154 0 2154 2 +2155 0 2155 2 +2156 0 2156 2 +2157 0 2157 2 +2158 0 2158 2 +2159 0 2159 2 +2160 0 2160 2 +2161 0 2161 2 +2162 0 2162 2 +2163 0 2163 2 +2164 0 2164 2 +2165 0 2165 2 +2166 0 2166 2 +2167 0 2167 2 +2168 0 2168 2 +2169 0 2169 2 +2170 0 2170 2 +2171 0 2171 2 +2172 0 2172 2 +2173 0 2173 2 +2174 0 2174 2 +2175 0 2175 2 + 128 11 29 0 + 129 11 29 1 + 130 11 28 0 + 131 11 28 1 + 132 10 29 0 + 133 10 29 1 + 134 10 28 0 + 135 10 28 1 + 136 8 28 1 + 137 8 28 0 + 138 8 29 1 + 139 8 29 0 + 140 9 28 1 + 141 9 28 0 + 142 9 29 1 + 143 9 29 0 + 160 3 28 0 + 161 3 28 1 + 162 3 29 0 + 163 3 29 1 + 164 2 28 0 + 165 2 28 1 + 166 2 29 0 + 167 2 29 1 + 168 0 29 1 + 169 0 29 0 + 170 0 28 1 + 171 0 28 0 + 172 1 29 1 + 173 1 29 0 + 174 1 28 1 + 175 1 28 0 + 176 4 28 0 + 177 4 28 1 + 178 4 29 0 + 179 4 29 1 + 180 5 28 0 + 181 5 28 1 + 182 5 29 0 + 183 5 29 1 + 184 7 29 1 + 185 7 29 0 + 186 7 28 1 + 187 7 28 0 + 188 6 29 1 + 189 6 29 0 + 190 6 28 1 + 191 6 28 0 + 192 12 29 0 + 193 12 29 1 + 194 12 28 0 + 195 12 28 1 + 196 13 29 0 + 197 13 29 1 + 198 13 28 0 + 199 13 28 1 + 200 15 28 1 + 201 15 28 0 + 202 15 29 1 + 203 15 29 0 + 204 14 28 1 + 205 14 28 0 + 206 14 29 1 + 207 14 29 0 + 256 11 31 0 + 257 11 31 1 + 258 11 30 0 + 259 11 30 1 + 260 10 31 0 + 261 10 31 1 + 262 10 30 0 + 263 10 30 1 + 264 8 30 1 + 265 8 30 0 + 266 8 31 1 + 267 8 31 0 + 268 9 30 1 + 269 9 30 0 + 270 9 31 1 + 271 9 31 0 + 288 3 30 0 + 289 3 30 1 + 290 3 31 0 + 291 3 31 1 + 292 2 30 0 + 293 2 30 1 + 294 2 31 0 + 295 2 31 1 + 296 0 31 1 + 297 0 31 0 + 298 0 30 1 + 299 0 30 0 + 300 1 31 1 + 301 1 31 0 + 302 1 30 1 + 303 1 30 0 + 304 4 30 0 + 305 4 30 1 + 306 4 31 0 + 307 4 31 1 + 308 5 30 0 + 309 5 30 1 + 310 5 31 0 + 311 5 31 1 + 312 7 31 1 + 313 7 31 0 + 314 7 30 1 + 315 7 30 0 + 316 6 31 1 + 317 6 31 0 + 318 6 30 1 + 319 6 30 0 + 320 12 31 0 + 321 12 31 1 + 322 12 30 0 + 323 12 30 1 + 324 13 31 0 + 325 13 31 1 + 326 13 30 0 + 327 13 30 1 + 328 15 30 1 + 329 15 30 0 + 330 15 31 1 + 331 15 31 0 + 332 14 30 1 + 333 14 30 0 + 334 14 31 1 + 335 14 31 0 + 384 11 33 0 + 385 11 33 1 + 386 11 32 0 + 387 11 32 1 + 388 10 33 0 + 389 10 33 1 + 390 10 32 0 + 391 10 32 1 + 392 8 32 1 + 393 8 32 0 + 394 8 33 1 + 395 8 33 0 + 396 9 32 1 + 397 9 32 0 + 398 9 33 1 + 399 9 33 0 + 416 3 32 0 + 417 3 32 1 + 418 3 33 0 + 419 3 33 1 + 420 2 32 0 + 421 2 32 1 + 422 2 33 0 + 423 2 33 1 + 424 0 33 1 + 425 0 33 0 + 426 0 32 1 + 427 0 32 0 + 428 1 33 1 + 429 1 33 0 + 430 1 32 1 + 431 1 32 0 + 432 4 32 0 + 433 4 32 1 + 434 4 33 0 + 435 4 33 1 + 436 5 32 0 + 437 5 32 1 + 438 5 33 0 + 439 5 33 1 + 440 7 33 1 + 441 7 33 0 + 442 7 32 1 + 443 7 32 0 + 444 6 33 1 + 445 6 33 0 + 446 6 32 1 + 447 6 32 0 + 448 12 33 0 + 449 12 33 1 + 450 12 32 0 + 451 12 32 1 + 452 13 33 0 + 453 13 33 1 + 454 13 32 0 + 455 13 32 1 + 456 15 32 1 + 457 15 32 0 + 458 15 33 1 + 459 15 33 0 + 460 14 32 1 + 461 14 32 0 + 462 14 33 1 + 463 14 33 0 + 512 11 35 0 + 513 11 35 1 + 514 11 34 0 + 515 11 34 1 + 516 10 35 0 + 517 10 35 1 + 518 10 34 0 + 519 10 34 1 + 520 8 34 1 + 521 8 34 0 + 522 8 35 1 + 523 8 35 0 + 524 9 34 1 + 525 9 34 0 + 526 9 35 1 + 527 9 35 0 + 544 3 34 0 + 545 3 34 1 + 546 3 35 0 + 547 3 35 1 + 548 2 34 0 + 549 2 34 1 + 550 2 35 0 + 551 2 35 1 + 552 0 35 1 + 553 0 35 0 + 554 0 34 1 + 555 0 34 0 + 556 1 35 1 + 557 1 35 0 + 558 1 34 1 + 559 1 34 0 + 560 4 34 0 + 561 4 34 1 + 562 4 35 0 + 563 4 35 1 + 564 5 34 0 + 565 5 34 1 + 566 5 35 0 + 567 5 35 1 + 568 7 35 1 + 569 7 35 0 + 570 7 34 1 + 571 7 34 0 + 572 6 35 1 + 573 6 35 0 + 574 6 34 1 + 575 6 34 0 + 576 12 35 0 + 577 12 35 1 + 578 12 34 0 + 579 12 34 1 + 580 13 35 0 + 581 13 35 1 + 582 13 34 0 + 583 13 34 1 + 584 15 34 1 + 585 15 34 0 + 586 15 35 1 + 587 15 35 0 + 588 14 34 1 + 589 14 34 0 + 590 14 35 1 + 591 14 35 0 + 640 11 37 0 + 641 11 37 1 + 642 11 36 0 + 643 11 36 1 + 644 10 37 0 + 645 10 37 1 + 646 10 36 0 + 647 10 36 1 + 648 8 36 1 + 649 8 36 0 + 650 8 37 1 + 651 8 37 0 + 652 9 36 1 + 653 9 36 0 + 654 9 37 1 + 655 9 37 0 + 672 3 36 0 + 673 3 36 1 + 674 3 37 0 + 675 3 37 1 + 676 2 36 0 + 677 2 36 1 + 678 2 37 0 + 679 2 37 1 + 680 0 37 1 + 681 0 37 0 + 682 0 36 1 + 683 0 36 0 + 684 1 37 1 + 685 1 37 0 + 686 1 36 1 + 687 1 36 0 + 688 4 36 0 + 689 4 36 1 + 690 4 37 0 + 691 4 37 1 + 692 5 36 0 + 693 5 36 1 + 694 5 37 0 + 695 5 37 1 + 696 7 37 1 + 697 7 37 0 + 698 7 36 1 + 699 7 36 0 + 700 6 37 1 + 701 6 37 0 + 702 6 36 1 + 703 6 36 0 + 704 12 37 0 + 705 12 37 1 + 706 12 36 0 + 707 12 36 1 + 708 13 37 0 + 709 13 37 1 + 710 13 36 0 + 711 13 36 1 + 712 15 36 1 + 713 15 36 0 + 714 15 37 1 + 715 15 37 0 + 716 14 36 1 + 717 14 36 0 + 718 14 37 1 + 719 14 37 0 + 768 11 39 0 + 769 11 39 1 + 770 11 38 0 + 771 11 38 1 + 772 10 39 0 + 773 10 39 1 + 774 10 38 0 + 775 10 38 1 + 776 8 38 1 + 777 8 38 0 + 778 8 39 1 + 779 8 39 0 + 780 9 38 1 + 781 9 38 0 + 782 9 39 1 + 783 9 39 0 + 800 3 38 0 + 801 3 38 1 + 802 3 39 0 + 803 3 39 1 + 804 2 38 0 + 805 2 38 1 + 806 2 39 0 + 807 2 39 1 + 808 0 39 1 + 809 0 39 0 + 810 0 38 1 + 811 0 38 0 + 812 1 39 1 + 813 1 39 0 + 814 1 38 1 + 815 1 38 0 + 816 4 38 0 + 817 4 38 1 + 818 4 39 0 + 819 4 39 1 + 820 5 38 0 + 821 5 38 1 + 822 5 39 0 + 823 5 39 1 + 824 7 39 1 + 825 7 39 0 + 826 7 38 1 + 827 7 38 0 + 828 6 39 1 + 829 6 39 0 + 830 6 38 1 + 831 6 38 0 + 832 12 39 0 + 833 12 39 1 + 834 12 38 0 + 835 12 38 1 + 836 13 39 0 + 837 13 39 1 + 838 13 38 0 + 839 13 38 1 + 840 15 38 1 + 841 15 38 0 + 842 15 39 1 + 843 15 39 0 + 844 14 38 1 + 845 14 38 0 + 846 14 39 1 + 847 14 39 0 + 896 11 41 0 + 897 11 41 1 + 898 11 40 0 + 899 11 40 1 + 900 10 41 0 + 901 10 41 1 + 902 10 40 0 + 903 10 40 1 + 904 8 40 1 + 905 8 40 0 + 906 8 41 1 + 907 8 41 0 + 908 9 40 1 + 909 9 40 0 + 910 9 41 1 + 911 9 41 0 + 928 3 40 0 + 929 3 40 1 + 930 3 41 0 + 931 3 41 1 + 932 2 40 0 + 933 2 40 1 + 934 2 41 0 + 935 2 41 1 + 936 0 41 1 + 937 0 41 0 + 938 0 40 1 + 939 0 40 0 + 940 1 41 1 + 941 1 41 0 + 942 1 40 1 + 943 1 40 0 + 944 4 40 0 + 945 4 40 1 + 946 4 41 0 + 947 4 41 1 + 948 5 40 0 + 949 5 40 1 + 950 5 41 0 + 951 5 41 1 + 952 7 41 1 + 953 7 41 0 + 954 7 40 1 + 955 7 40 0 + 956 6 41 1 + 957 6 41 0 + 958 6 40 1 + 959 6 40 0 + 960 12 41 0 + 961 12 41 1 + 962 12 40 0 + 963 12 40 1 + 964 13 41 0 + 965 13 41 1 + 966 13 40 0 + 967 13 40 1 + 968 15 40 1 + 969 15 40 0 + 970 15 41 1 + 971 15 41 0 + 972 14 40 1 + 973 14 40 0 + 974 14 41 1 + 975 14 41 0 +1024 11 43 0 +1025 11 43 1 +1026 11 42 0 +1027 11 42 1 +1028 10 43 0 +1029 10 43 1 +1030 10 42 0 +1031 10 42 1 +1032 8 42 1 +1033 8 42 0 +1034 8 43 1 +1035 8 43 0 +1036 9 42 1 +1037 9 42 0 +1038 9 43 1 +1039 9 43 0 +1056 3 42 0 +1057 3 42 1 +1058 3 43 0 +1059 3 43 1 +1060 2 42 0 +1061 2 42 1 +1062 2 43 0 +1063 2 43 1 +1064 0 43 1 +1065 0 43 0 +1066 0 42 1 +1067 0 42 0 +1068 1 43 1 +1069 1 43 0 +1070 1 42 1 +1071 1 42 0 +1072 4 42 0 +1073 4 42 1 +1074 4 43 0 +1075 4 43 1 +1076 5 42 0 +1077 5 42 1 +1078 5 43 0 +1079 5 43 1 +1080 7 43 1 +1081 7 43 0 +1082 7 42 1 +1083 7 42 0 +1084 6 43 1 +1085 6 43 0 +1086 6 42 1 +1087 6 42 0 +1088 12 43 0 +1089 12 43 1 +1090 12 42 0 +1091 12 42 1 +1092 13 43 0 +1093 13 43 1 +1094 13 42 0 +1095 13 42 1 +1096 15 42 1 +1097 15 42 0 +1098 15 43 1 +1099 15 43 0 +1100 14 42 1 +1101 14 42 0 +1102 14 43 1 +1103 14 43 0 +1152 11 45 0 +1153 11 45 1 +1154 11 44 0 +1155 11 44 1 +1156 10 45 0 +1157 10 45 1 +1158 10 44 0 +1159 10 44 1 +1160 8 44 1 +1161 8 44 0 +1162 8 45 1 +1163 8 45 0 +1164 9 44 1 +1165 9 44 0 +1166 9 45 1 +1167 9 45 0 +1184 3 44 0 +1185 3 44 1 +1186 3 45 0 +1187 3 45 1 +1188 2 44 0 +1189 2 44 1 +1190 2 45 0 +1191 2 45 1 +1192 0 45 1 +1193 0 45 0 +1194 0 44 1 +1195 0 44 0 +1196 1 45 1 +1197 1 45 0 +1198 1 44 1 +1199 1 44 0 +1200 4 44 0 +1201 4 44 1 +1202 4 45 0 +1203 4 45 1 +1204 5 44 0 +1205 5 44 1 +1206 5 45 0 +1207 5 45 1 +1208 7 45 1 +1209 7 45 0 +1210 7 44 1 +1211 7 44 0 +1212 6 45 1 +1213 6 45 0 +1214 6 44 1 +1215 6 44 0 +1216 12 45 0 +1217 12 45 1 +1218 12 44 0 +1219 12 44 1 +1220 13 45 0 +1221 13 45 1 +1222 13 44 0 +1223 13 44 1 +1224 15 44 1 +1225 15 44 0 +1226 15 45 1 +1227 15 45 0 +1228 14 44 1 +1229 14 44 0 +1230 14 45 1 +1231 14 45 0 +1280 11 47 0 +1281 11 47 1 +1282 11 46 0 +1283 11 46 1 +1284 10 47 0 +1285 10 47 1 +1286 10 46 0 +1287 10 46 1 +1288 8 46 1 +1289 8 46 0 +1290 8 47 1 +1291 8 47 0 +1292 9 46 1 +1293 9 46 0 +1294 9 47 1 +1295 9 47 0 +1312 3 46 0 +1313 3 46 1 +1314 3 47 0 +1315 3 47 1 +1316 2 46 0 +1317 2 46 1 +1318 2 47 0 +1319 2 47 1 +1320 0 47 1 +1321 0 47 0 +1322 0 46 1 +1323 0 46 0 +1324 1 47 1 +1325 1 47 0 +1326 1 46 1 +1327 1 46 0 +1328 4 46 0 +1329 4 46 1 +1330 4 47 0 +1331 4 47 1 +1332 5 46 0 +1333 5 46 1 +1334 5 47 0 +1335 5 47 1 +1336 7 47 1 +1337 7 47 0 +1338 7 46 1 +1339 7 46 0 +1340 6 47 1 +1341 6 47 0 +1342 6 46 1 +1343 6 46 0 +1344 12 47 0 +1345 12 47 1 +1346 12 46 0 +1347 12 46 1 +1348 13 47 0 +1349 13 47 1 +1350 13 46 0 +1351 13 46 1 +1352 15 46 1 +1353 15 46 0 +1354 15 47 1 +1355 15 47 0 +1356 14 46 1 +1357 14 46 0 +1358 14 47 1 +1359 14 47 0 +1408 11 49 0 +1409 11 49 1 +1410 11 48 0 +1411 11 48 1 +1412 10 49 0 +1413 10 49 1 +1414 10 48 0 +1415 10 48 1 +1416 8 48 1 +1417 8 48 0 +1418 8 49 1 +1419 8 49 0 +1420 9 48 1 +1421 9 48 0 +1422 9 49 1 +1423 9 49 0 +1440 3 48 0 +1441 3 48 1 +1442 3 49 0 +1443 3 49 1 +1444 2 48 0 +1445 2 48 1 +1446 2 49 0 +1447 2 49 1 +1448 0 49 1 +1449 0 49 0 +1450 0 48 1 +1451 0 48 0 +1452 1 49 1 +1453 1 49 0 +1454 1 48 1 +1455 1 48 0 +1456 4 48 0 +1457 4 48 1 +1458 4 49 0 +1459 4 49 1 +1460 5 48 0 +1461 5 48 1 +1462 5 49 0 +1463 5 49 1 +1464 7 49 1 +1465 7 49 0 +1466 7 48 1 +1467 7 48 0 +1468 6 49 1 +1469 6 49 0 +1470 6 48 1 +1471 6 48 0 +1472 12 49 0 +1473 12 49 1 +1474 12 48 0 +1475 12 48 1 +1476 13 49 0 +1477 13 49 1 +1478 13 48 0 +1479 13 48 1 +1480 15 48 1 +1481 15 48 0 +1482 15 49 1 +1483 15 49 0 +1484 14 48 1 +1485 14 48 0 +1486 14 49 1 +1487 14 49 0 +1536 11 51 0 +1537 11 51 1 +1538 11 50 0 +1539 11 50 1 +1540 10 51 0 +1541 10 51 1 +1542 10 50 0 +1543 10 50 1 +1544 8 50 1 +1545 8 50 0 +1546 8 51 1 +1547 8 51 0 +1548 9 50 1 +1549 9 50 0 +1550 9 51 1 +1551 9 51 0 +1568 3 50 0 +1569 3 50 1 +1570 3 51 0 +1571 3 51 1 +1572 2 50 0 +1573 2 50 1 +1574 2 51 0 +1575 2 51 1 +1576 0 51 1 +1577 0 51 0 +1578 0 50 1 +1579 0 50 0 +1580 1 51 1 +1581 1 51 0 +1582 1 50 1 +1583 1 50 0 +1584 4 50 0 +1585 4 50 1 +1586 4 51 0 +1587 4 51 1 +1588 5 50 0 +1589 5 50 1 +1590 5 51 0 +1591 5 51 1 +1592 7 51 1 +1593 7 51 0 +1594 7 50 1 +1595 7 50 0 +1596 6 51 1 +1597 6 51 0 +1598 6 50 1 +1599 6 50 0 +1600 12 51 0 +1601 12 51 1 +1602 12 50 0 +1603 12 50 1 +1604 13 51 0 +1605 13 51 1 +1606 13 50 0 +1607 13 50 1 +1608 15 50 1 +1609 15 50 0 +1610 15 51 1 +1611 15 51 0 +1612 14 50 1 +1613 14 50 0 +1614 14 51 1 +1615 14 51 0 +1664 11 53 0 +1665 11 53 1 +1666 11 52 0 +1667 11 52 1 +1668 10 53 0 +1669 10 53 1 +1670 10 52 0 +1671 10 52 1 +1672 8 52 1 +1673 8 52 0 +1674 8 53 1 +1675 8 53 0 +1676 9 52 1 +1677 9 52 0 +1678 9 53 1 +1679 9 53 0 +1696 3 52 0 +1697 3 52 1 +1698 3 53 0 +1699 3 53 1 +1700 2 52 0 +1701 2 52 1 +1702 2 53 0 +1703 2 53 1 +1704 0 53 1 +1705 0 53 0 +1706 0 52 1 +1707 0 52 0 +1708 1 53 1 +1709 1 53 0 +1710 1 52 1 +1711 1 52 0 +1712 4 52 0 +1713 4 52 1 +1714 4 53 0 +1715 4 53 1 +1716 5 52 0 +1717 5 52 1 +1718 5 53 0 +1719 5 53 1 +1720 7 53 1 +1721 7 53 0 +1722 7 52 1 +1723 7 52 0 +1724 6 53 1 +1725 6 53 0 +1726 6 52 1 +1727 6 52 0 +1728 12 53 0 +1729 12 53 1 +1730 12 52 0 +1731 12 52 1 +1732 13 53 0 +1733 13 53 1 +1734 13 52 0 +1735 13 52 1 +1736 15 52 1 +1737 15 52 0 +1738 15 53 1 +1739 15 53 0 +1740 14 52 1 +1741 14 52 0 +1742 14 53 1 +1743 14 53 0 +1792 11 55 0 +1793 11 55 1 +1794 11 54 0 +1795 11 54 1 +1796 10 55 0 +1797 10 55 1 +1798 10 54 0 +1799 10 54 1 +1800 8 54 1 +1801 8 54 0 +1802 8 55 1 +1803 8 55 0 +1804 9 54 1 +1805 9 54 0 +1806 9 55 1 +1807 9 55 0 +1824 3 54 0 +1825 3 54 1 +1826 3 55 0 +1827 3 55 1 +1828 2 54 0 +1829 2 54 1 +1830 2 55 0 +1831 2 55 1 +1832 0 55 1 +1833 0 55 0 +1834 0 54 1 +1835 0 54 0 +1836 1 55 1 +1837 1 55 0 +1838 1 54 1 +1839 1 54 0 +1840 4 54 0 +1841 4 54 1 +1842 4 55 0 +1843 4 55 1 +1844 5 54 0 +1845 5 54 1 +1846 5 55 0 +1847 5 55 1 +1848 7 55 1 +1849 7 55 0 +1850 7 54 1 +1851 7 54 0 +1852 6 55 1 +1853 6 55 0 +1854 6 54 1 +1855 6 54 0 +1856 12 55 0 +1857 12 55 1 +1858 12 54 0 +1859 12 54 1 +1860 13 55 0 +1861 13 55 1 +1862 13 54 0 +1863 13 54 1 +1864 15 54 1 +1865 15 54 0 +1866 15 55 1 +1867 15 55 0 +1868 14 54 1 +1869 14 54 0 +1870 14 55 1 +1871 14 55 0 +2176 11 27 0 +2177 11 27 1 +2178 11 26 0 +2179 11 26 1 +2180 10 27 0 +2181 10 27 1 +2182 10 26 0 +2183 10 26 1 +2184 8 26 1 +2185 8 26 0 +2186 8 27 1 +2187 8 27 0 +2188 9 26 1 +2189 9 26 0 +2190 9 27 1 +2191 9 27 0 +2208 3 26 0 +2209 3 26 1 +2210 3 27 0 +2211 3 27 1 +2212 2 26 0 +2213 2 26 1 +2214 2 27 0 +2215 2 27 1 +2216 0 27 1 +2217 0 27 0 +2218 0 26 1 +2219 0 26 0 +2220 1 27 1 +2221 1 27 0 +2222 1 26 1 +2223 1 26 0 +2224 4 26 0 +2225 4 26 1 +2226 4 27 0 +2227 4 27 1 +2228 5 26 0 +2229 5 26 1 +2230 5 27 0 +2231 5 27 1 +2232 7 27 1 +2233 7 27 0 +2234 7 26 1 +2235 7 26 0 +2236 6 27 1 +2237 6 27 0 +2238 6 26 1 +2239 6 26 0 +2240 12 27 0 +2241 12 27 1 +2242 12 26 0 +2243 12 26 1 +2244 13 27 0 +2245 13 27 1 +2246 13 26 0 +2247 13 26 1 +2248 15 26 1 +2249 15 26 0 +2250 15 27 1 +2251 15 27 0 +2252 14 26 1 +2253 14 26 0 +2254 14 27 1 +2255 14 27 0 +2304 11 25 0 +2305 11 25 1 +2306 11 24 0 +2307 11 24 1 +2308 10 25 0 +2309 10 25 1 +2310 10 24 0 +2311 10 24 1 +2312 8 24 1 +2313 8 24 0 +2314 8 25 1 +2315 8 25 0 +2316 9 24 1 +2317 9 24 0 +2318 9 25 1 +2319 9 25 0 +2336 3 24 0 +2337 3 24 1 +2338 3 25 0 +2339 3 25 1 +2340 2 24 0 +2341 2 24 1 +2342 2 25 0 +2343 2 25 1 +2344 0 25 1 +2345 0 25 0 +2346 0 24 1 +2347 0 24 0 +2348 1 25 1 +2349 1 25 0 +2350 1 24 1 +2351 1 24 0 +2352 4 24 0 +2353 4 24 1 +2354 4 25 0 +2355 4 25 1 +2356 5 24 0 +2357 5 24 1 +2358 5 25 0 +2359 5 25 1 +2360 7 25 1 +2361 7 25 0 +2362 7 24 1 +2363 7 24 0 +2364 6 25 1 +2365 6 25 0 +2366 6 24 1 +2367 6 24 0 +2368 12 25 0 +2369 12 25 1 +2370 12 24 0 +2371 12 24 1 +2372 13 25 0 +2373 13 25 1 +2374 13 24 0 +2375 13 24 1 +2376 15 24 1 +2377 15 24 0 +2378 15 25 1 +2379 15 25 0 +2380 14 24 1 +2381 14 24 0 +2382 14 25 1 +2383 14 25 0 +2432 11 23 0 +2433 11 23 1 +2434 11 22 0 +2435 11 22 1 +2436 10 23 0 +2437 10 23 1 +2438 10 22 0 +2439 10 22 1 +2440 8 22 1 +2441 8 22 0 +2442 8 23 1 +2443 8 23 0 +2444 9 22 1 +2445 9 22 0 +2446 9 23 1 +2447 9 23 0 +2464 3 22 0 +2465 3 22 1 +2466 3 23 0 +2467 3 23 1 +2468 2 22 0 +2469 2 22 1 +2470 2 23 0 +2471 2 23 1 +2472 0 23 1 +2473 0 23 0 +2474 0 22 1 +2475 0 22 0 +2476 1 23 1 +2477 1 23 0 +2478 1 22 1 +2479 1 22 0 +2480 4 22 0 +2481 4 22 1 +2482 4 23 0 +2483 4 23 1 +2484 5 22 0 +2485 5 22 1 +2486 5 23 0 +2487 5 23 1 +2488 7 23 1 +2489 7 23 0 +2490 7 22 1 +2491 7 22 0 +2492 6 23 1 +2493 6 23 0 +2494 6 22 1 +2495 6 22 0 +2496 12 23 0 +2497 12 23 1 +2498 12 22 0 +2499 12 22 1 +2500 13 23 0 +2501 13 23 1 +2502 13 22 0 +2503 13 22 1 +2504 15 22 1 +2505 15 22 0 +2506 15 23 1 +2507 15 23 0 +2508 14 22 1 +2509 14 22 0 +2510 14 23 1 +2511 14 23 0 +2560 11 21 0 +2561 11 21 1 +2562 11 20 0 +2563 11 20 1 +2564 10 21 0 +2565 10 21 1 +2566 10 20 0 +2567 10 20 1 +2568 8 20 1 +2569 8 20 0 +2570 8 21 1 +2571 8 21 0 +2572 9 20 1 +2573 9 20 0 +2574 9 21 1 +2575 9 21 0 +2592 3 20 0 +2593 3 20 1 +2594 3 21 0 +2595 3 21 1 +2596 2 20 0 +2597 2 20 1 +2598 2 21 0 +2599 2 21 1 +2600 0 21 1 +2601 0 21 0 +2602 0 20 1 +2603 0 20 0 +2604 1 21 1 +2605 1 21 0 +2606 1 20 1 +2607 1 20 0 +2608 4 20 0 +2609 4 20 1 +2610 4 21 0 +2611 4 21 1 +2612 5 20 0 +2613 5 20 1 +2614 5 21 0 +2615 5 21 1 +2616 7 21 1 +2617 7 21 0 +2618 7 20 1 +2619 7 20 0 +2620 6 21 1 +2621 6 21 0 +2622 6 20 1 +2623 6 20 0 +2624 12 21 0 +2625 12 21 1 +2626 12 20 0 +2627 12 20 1 +2628 13 21 0 +2629 13 21 1 +2630 13 20 0 +2631 13 20 1 +2632 15 20 1 +2633 15 20 0 +2634 15 21 1 +2635 15 21 0 +2636 14 20 1 +2637 14 20 0 +2638 14 21 1 +2639 14 21 0 +2688 11 19 0 +2689 11 19 1 +2690 11 18 0 +2691 11 18 1 +2692 10 19 0 +2693 10 19 1 +2694 10 18 0 +2695 10 18 1 +2696 8 18 1 +2697 8 18 0 +2698 8 19 1 +2699 8 19 0 +2700 9 18 1 +2701 9 18 0 +2702 9 19 1 +2703 9 19 0 +2720 3 18 0 +2721 3 18 1 +2722 3 19 0 +2723 3 19 1 +2724 2 18 0 +2725 2 18 1 +2726 2 19 0 +2727 2 19 1 +2728 0 19 1 +2729 0 19 0 +2730 0 18 1 +2731 0 18 0 +2732 1 19 1 +2733 1 19 0 +2734 1 18 1 +2735 1 18 0 +2736 4 18 0 +2737 4 18 1 +2738 4 19 0 +2739 4 19 1 +2740 5 18 0 +2741 5 18 1 +2742 5 19 0 +2743 5 19 1 +2744 7 19 1 +2745 7 19 0 +2746 7 18 1 +2747 7 18 0 +2748 6 19 1 +2749 6 19 0 +2750 6 18 1 +2751 6 18 0 +2752 12 19 0 +2753 12 19 1 +2754 12 18 0 +2755 12 18 1 +2756 13 19 0 +2757 13 19 1 +2758 13 18 0 +2759 13 18 1 +2760 15 18 1 +2761 15 18 0 +2762 15 19 1 +2763 15 19 0 +2764 14 18 1 +2765 14 18 0 +2766 14 19 1 +2767 14 19 0 +2816 11 17 0 +2817 11 17 1 +2818 11 16 0 +2819 11 16 1 +2820 10 17 0 +2821 10 17 1 +2822 10 16 0 +2823 10 16 1 +2824 8 16 1 +2825 8 16 0 +2826 8 17 1 +2827 8 17 0 +2828 9 16 1 +2829 9 16 0 +2830 9 17 1 +2831 9 17 0 +2848 3 16 0 +2849 3 16 1 +2850 3 17 0 +2851 3 17 1 +2852 2 16 0 +2853 2 16 1 +2854 2 17 0 +2855 2 17 1 +2856 0 17 1 +2857 0 17 0 +2858 0 16 1 +2859 0 16 0 +2860 1 17 1 +2861 1 17 0 +2862 1 16 1 +2863 1 16 0 +2864 4 16 0 +2865 4 16 1 +2866 4 17 0 +2867 4 17 1 +2868 5 16 0 +2869 5 16 1 +2870 5 17 0 +2871 5 17 1 +2872 7 17 1 +2873 7 17 0 +2874 7 16 1 +2875 7 16 0 +2876 6 17 1 +2877 6 17 0 +2878 6 16 1 +2879 6 16 0 +2880 12 17 0 +2881 12 17 1 +2882 12 16 0 +2883 12 16 1 +2884 13 17 0 +2885 13 17 1 +2886 13 16 0 +2887 13 16 1 +2888 15 16 1 +2889 15 16 0 +2890 15 17 1 +2891 15 17 0 +2892 14 16 1 +2893 14 16 0 +2894 14 17 1 +2895 14 17 0 +2944 11 15 0 +2945 11 15 1 +2946 11 14 0 +2947 11 14 1 +2948 10 15 0 +2949 10 15 1 +2950 10 14 0 +2951 10 14 1 +2952 8 14 1 +2953 8 14 0 +2954 8 15 1 +2955 8 15 0 +2956 9 14 1 +2957 9 14 0 +2958 9 15 1 +2959 9 15 0 +2976 3 14 0 +2977 3 14 1 +2978 3 15 0 +2979 3 15 1 +2980 2 14 0 +2981 2 14 1 +2982 2 15 0 +2983 2 15 1 +2984 0 15 1 +2985 0 15 0 +2986 0 14 1 +2987 0 14 0 +2988 1 15 1 +2989 1 15 0 +2990 1 14 1 +2991 1 14 0 +2992 4 14 0 +2993 4 14 1 +2994 4 15 0 +2995 4 15 1 +2996 5 14 0 +2997 5 14 1 +2998 5 15 0 +2999 5 15 1 +3000 7 15 1 +3001 7 15 0 +3002 7 14 1 +3003 7 14 0 +3004 6 15 1 +3005 6 15 0 +3006 6 14 1 +3007 6 14 0 +3008 12 15 0 +3009 12 15 1 +3010 12 14 0 +3011 12 14 1 +3012 13 15 0 +3013 13 15 1 +3014 13 14 0 +3015 13 14 1 +3016 15 14 1 +3017 15 14 0 +3018 15 15 1 +3019 15 15 0 +3020 14 14 1 +3021 14 14 0 +3022 14 15 1 +3023 14 15 0 +3072 11 13 0 +3073 11 13 1 +3074 11 12 0 +3075 11 12 1 +3076 10 13 0 +3077 10 13 1 +3078 10 12 0 +3079 10 12 1 +3080 8 12 1 +3081 8 12 0 +3082 8 13 1 +3083 8 13 0 +3084 9 12 1 +3085 9 12 0 +3086 9 13 1 +3087 9 13 0 +3104 3 12 0 +3105 3 12 1 +3106 3 13 0 +3107 3 13 1 +3108 2 12 0 +3109 2 12 1 +3110 2 13 0 +3111 2 13 1 +3112 0 13 1 +3113 0 13 0 +3114 0 12 1 +3115 0 12 0 +3116 1 13 1 +3117 1 13 0 +3118 1 12 1 +3119 1 12 0 +3120 4 12 0 +3121 4 12 1 +3122 4 13 0 +3123 4 13 1 +3124 5 12 0 +3125 5 12 1 +3126 5 13 0 +3127 5 13 1 +3128 7 13 1 +3129 7 13 0 +3130 7 12 1 +3131 7 12 0 +3132 6 13 1 +3133 6 13 0 +3134 6 12 1 +3135 6 12 0 +3136 12 13 0 +3137 12 13 1 +3138 12 12 0 +3139 12 12 1 +3140 13 13 0 +3141 13 13 1 +3142 13 12 0 +3143 13 12 1 +3144 15 12 1 +3145 15 12 0 +3146 15 13 1 +3147 15 13 0 +3148 14 12 1 +3149 14 12 0 +3150 14 13 1 +3151 14 13 0 +3200 11 11 0 +3201 11 11 1 +3202 11 10 0 +3203 11 10 1 +3204 10 11 0 +3205 10 11 1 +3206 10 10 0 +3207 10 10 1 +3208 8 10 1 +3209 8 10 0 +3210 8 11 1 +3211 8 11 0 +3212 9 10 1 +3213 9 10 0 +3214 9 11 1 +3215 9 11 0 +3232 3 10 0 +3233 3 10 1 +3234 3 11 0 +3235 3 11 1 +3236 2 10 0 +3237 2 10 1 +3238 2 11 0 +3239 2 11 1 +3240 0 11 1 +3241 0 11 0 +3242 0 10 1 +3243 0 10 0 +3244 1 11 1 +3245 1 11 0 +3246 1 10 1 +3247 1 10 0 +3248 4 10 0 +3249 4 10 1 +3250 4 11 0 +3251 4 11 1 +3252 5 10 0 +3253 5 10 1 +3254 5 11 0 +3255 5 11 1 +3256 7 11 1 +3257 7 11 0 +3258 7 10 1 +3259 7 10 0 +3260 6 11 1 +3261 6 11 0 +3262 6 10 1 +3263 6 10 0 +3264 12 11 0 +3265 12 11 1 +3266 12 10 0 +3267 12 10 1 +3268 13 11 0 +3269 13 11 1 +3270 13 10 0 +3271 13 10 1 +3272 15 10 1 +3273 15 10 0 +3274 15 11 1 +3275 15 11 0 +3276 14 10 1 +3277 14 10 0 +3278 14 11 1 +3279 14 11 0 +3328 11 9 0 +3329 11 9 1 +3330 11 8 0 +3331 11 8 1 +3332 10 9 0 +3333 10 9 1 +3334 10 8 0 +3335 10 8 1 +3336 8 8 1 +3337 8 8 0 +3338 8 9 1 +3339 8 9 0 +3340 9 8 1 +3341 9 8 0 +3342 9 9 1 +3343 9 9 0 +3360 3 8 0 +3361 3 8 1 +3362 3 9 0 +3363 3 9 1 +3364 2 8 0 +3365 2 8 1 +3366 2 9 0 +3367 2 9 1 +3368 0 9 1 +3369 0 9 0 +3370 0 8 1 +3371 0 8 0 +3372 1 9 1 +3373 1 9 0 +3374 1 8 1 +3375 1 8 0 +3376 4 8 0 +3377 4 8 1 +3378 4 9 0 +3379 4 9 1 +3380 5 8 0 +3381 5 8 1 +3382 5 9 0 +3383 5 9 1 +3384 7 9 1 +3385 7 9 0 +3386 7 8 1 +3387 7 8 0 +3388 6 9 1 +3389 6 9 0 +3390 6 8 1 +3391 6 8 0 +3392 12 9 0 +3393 12 9 1 +3394 12 8 0 +3395 12 8 1 +3396 13 9 0 +3397 13 9 1 +3398 13 8 0 +3399 13 8 1 +3400 15 8 1 +3401 15 8 0 +3402 15 9 1 +3403 15 9 0 +3404 14 8 1 +3405 14 8 0 +3406 14 9 1 +3407 14 9 0 +3456 11 7 0 +3457 11 7 1 +3458 11 6 0 +3459 11 6 1 +3460 10 7 0 +3461 10 7 1 +3462 10 6 0 +3463 10 6 1 +3464 8 6 1 +3465 8 6 0 +3466 8 7 1 +3467 8 7 0 +3468 9 6 1 +3469 9 6 0 +3470 9 7 1 +3471 9 7 0 +3488 3 6 0 +3489 3 6 1 +3490 3 7 0 +3491 3 7 1 +3492 2 6 0 +3493 2 6 1 +3494 2 7 0 +3495 2 7 1 +3496 0 7 1 +3497 0 7 0 +3498 0 6 1 +3499 0 6 0 +3500 1 7 1 +3501 1 7 0 +3502 1 6 1 +3503 1 6 0 +3504 4 6 0 +3505 4 6 1 +3506 4 7 0 +3507 4 7 1 +3508 5 6 0 +3509 5 6 1 +3510 5 7 0 +3511 5 7 1 +3512 7 7 1 +3513 7 7 0 +3514 7 6 1 +3515 7 6 0 +3516 6 7 1 +3517 6 7 0 +3518 6 6 1 +3519 6 6 0 +3520 12 7 0 +3521 12 7 1 +3522 12 6 0 +3523 12 6 1 +3524 13 7 0 +3525 13 7 1 +3526 13 6 0 +3527 13 6 1 +3528 15 6 1 +3529 15 6 0 +3530 15 7 1 +3531 15 7 0 +3532 14 6 1 +3533 14 6 0 +3534 14 7 1 +3535 14 7 0 +3584 11 5 0 +3585 11 5 1 +3586 11 4 0 +3587 11 4 1 +3588 10 5 0 +3589 10 5 1 +3590 10 4 0 +3591 10 4 1 +3592 8 4 1 +3593 8 4 0 +3594 8 5 1 +3595 8 5 0 +3596 9 4 1 +3597 9 4 0 +3598 9 5 1 +3599 9 5 0 +3616 3 4 0 +3617 3 4 1 +3618 3 5 0 +3619 3 5 1 +3620 2 4 0 +3621 2 4 1 +3622 2 5 0 +3623 2 5 1 +3624 0 5 1 +3625 0 5 0 +3626 0 4 1 +3627 0 4 0 +3628 1 5 1 +3629 1 5 0 +3630 1 4 1 +3631 1 4 0 +3632 4 4 0 +3633 4 4 1 +3634 4 5 0 +3635 4 5 1 +3636 5 4 0 +3637 5 4 1 +3638 5 5 0 +3639 5 5 1 +3640 7 5 1 +3641 7 5 0 +3642 7 4 1 +3643 7 4 0 +3644 6 5 1 +3645 6 5 0 +3646 6 4 1 +3647 6 4 0 +3648 12 5 0 +3649 12 5 1 +3650 12 4 0 +3651 12 4 1 +3652 13 5 0 +3653 13 5 1 +3654 13 4 0 +3655 13 4 1 +3656 15 4 1 +3657 15 4 0 +3658 15 5 1 +3659 15 5 0 +3660 14 4 1 +3661 14 4 0 +3662 14 5 1 +3663 14 5 0 +3712 11 3 0 +3713 11 3 1 +3714 11 2 0 +3715 11 2 1 +3716 10 3 0 +3717 10 3 1 +3718 10 2 0 +3719 10 2 1 +3720 8 2 1 +3721 8 2 0 +3722 8 3 1 +3723 8 3 0 +3724 9 2 1 +3725 9 2 0 +3726 9 3 1 +3727 9 3 0 +3744 3 2 0 +3745 3 2 1 +3746 3 3 0 +3747 3 3 1 +3748 2 2 0 +3749 2 2 1 +3750 2 3 0 +3751 2 3 1 +3752 0 3 1 +3753 0 3 0 +3754 0 2 1 +3755 0 2 0 +3756 1 3 1 +3757 1 3 0 +3758 1 2 1 +3759 1 2 0 +3760 4 2 0 +3761 4 2 1 +3762 4 3 0 +3763 4 3 1 +3764 5 2 0 +3765 5 2 1 +3766 5 3 0 +3767 5 3 1 +3768 7 3 1 +3769 7 3 0 +3770 7 2 1 +3771 7 2 0 +3772 6 3 1 +3773 6 3 0 +3774 6 2 1 +3775 6 2 0 +3776 12 3 0 +3777 12 3 1 +3778 12 2 0 +3779 12 2 1 +3780 13 3 0 +3781 13 3 1 +3782 13 2 0 +3783 13 2 1 +3784 15 2 1 +3785 15 2 0 +3786 15 3 1 +3787 15 3 0 +3788 14 2 1 +3789 14 2 0 +3790 14 3 1 +3791 14 3 0 +3840 11 1 0 +3841 11 1 1 +3842 11 0 0 +3843 11 0 1 +3844 10 1 0 +3845 10 1 1 +3846 10 0 0 +3847 10 0 1 +3848 8 0 1 +3849 8 0 0 +3850 8 1 1 +3851 8 1 0 +3852 9 0 1 +3853 9 0 0 +3854 9 1 1 +3855 9 1 0 +3872 3 0 0 +3873 3 0 1 +3874 3 1 0 +3875 3 1 1 +3876 2 0 0 +3877 2 0 1 +3878 2 1 0 +3879 2 1 1 +3880 0 1 1 +3881 0 1 0 +3882 0 0 1 +3883 0 0 0 +3884 1 1 1 +3885 1 1 0 +3886 1 0 1 +3887 1 0 0 +3888 4 0 0 +3889 4 0 1 +3890 4 1 0 +3891 4 1 1 +3892 5 0 0 +3893 5 0 1 +3894 5 1 0 +3895 5 1 1 +3896 7 1 1 +3897 7 1 0 +3898 7 0 1 +3899 7 0 0 +3900 6 1 1 +3901 6 1 0 +3902 6 0 1 +3903 6 0 0 +3904 12 1 0 +3905 12 1 1 +3906 12 0 0 +3907 12 0 1 +3908 13 1 0 +3909 13 1 1 +3910 13 0 0 +3911 13 0 1 +3912 15 0 1 +3913 15 0 0 +3914 15 1 1 +3915 15 1 0 +3916 14 0 1 +3917 14 0 0 +3918 14 1 1 +3919 14 1 0 diff --git a/Detectors/PHOS/base/files/Mod0RCU1.data b/Detectors/PHOS/base/files/Mod0RCU1.data new file mode 100644 index 0000000000000..db125226496cf --- /dev/null +++ b/Detectors/PHOS/base/files/Mod0RCU1.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 1 0 2 + 1 1 1 2 + 2 1 2 2 + 3 1 3 2 + 4 1 4 2 + 5 1 5 2 + 6 1 6 2 + 7 1 7 2 + 8 1 8 2 + 9 1 9 2 + 10 1 10 2 + 11 1 11 2 + 12 1 12 2 + 13 1 13 2 + 14 1 14 2 + 15 1 15 2 + 16 1 16 2 + 17 1 17 2 + 18 1 18 2 + 19 1 19 2 + 20 1 20 2 + 21 1 21 2 + 22 1 22 2 + 23 1 23 2 + 24 1 24 2 + 25 1 25 2 + 26 1 26 2 + 27 1 27 2 + 28 1 28 2 + 29 1 29 2 + 30 1 30 2 + 31 1 31 2 + 32 1 32 2 + 33 1 33 2 + 34 1 34 2 + 35 1 35 2 + 36 1 36 2 + 37 1 37 2 + 38 1 38 2 + 39 1 39 2 + 40 1 40 2 + 41 1 41 2 + 42 1 42 2 + 43 1 43 2 + 44 1 44 2 + 45 1 45 2 + 46 1 46 2 + 47 1 47 2 + 48 1 48 2 + 49 1 49 2 + 50 1 50 2 + 51 1 51 2 + 52 1 52 2 + 53 1 53 2 + 54 1 54 2 + 55 1 55 2 + 56 1 56 2 + 57 1 57 2 + 58 1 58 2 + 59 1 59 2 + 60 1 60 2 + 61 1 61 2 + 62 1 62 2 + 63 1 63 2 + 64 1 64 2 + 65 1 65 2 + 66 1 66 2 + 67 1 67 2 + 68 1 68 2 + 69 1 69 2 + 70 1 70 2 + 71 1 71 2 + 72 1 72 2 + 73 1 73 2 + 74 1 74 2 + 75 1 75 2 + 76 1 76 2 + 77 1 77 2 + 78 1 78 2 + 79 1 79 2 + 80 1 80 2 + 81 1 81 2 + 82 1 82 2 + 83 1 83 2 + 84 1 84 2 + 85 1 85 2 + 86 1 86 2 + 87 1 87 2 + 88 1 88 2 + 89 1 89 2 + 90 1 90 2 + 91 1 91 2 + 92 1 92 2 + 93 1 93 2 + 94 1 94 2 + 95 1 95 2 + 96 1 96 2 + 97 1 97 2 + 98 1 98 2 + 99 1 99 2 + 100 1 100 2 + 101 1 101 2 + 102 1 102 2 + 103 1 103 2 + 104 1 104 2 + 105 1 105 2 + 106 1 106 2 + 107 1 107 2 + 108 1 108 2 + 109 1 109 2 + 110 1 110 2 + 111 1 111 2 + 112 1 112 2 + 113 1 113 2 + 114 1 114 2 + 115 1 115 2 + 116 1 116 2 + 117 1 117 2 + 118 1 118 2 + 119 1 119 2 + 120 1 120 2 + 121 1 121 2 + 122 1 122 2 + 123 1 123 2 + 124 1 124 2 + 125 1 125 2 + 126 1 126 2 + 127 1 127 2 +2048 1 2048 2 +2049 1 2049 2 +2050 1 2050 2 +2051 1 2051 2 +2052 1 2052 2 +2053 1 2053 2 +2054 1 2054 2 +2055 1 2055 2 +2056 1 2056 2 +2057 1 2057 2 +2058 1 2058 2 +2059 1 2059 2 +2060 1 2060 2 +2061 1 2061 2 +2062 1 2062 2 +2063 1 2063 2 +2064 1 2064 2 +2065 1 2065 2 +2066 1 2066 2 +2067 1 2067 2 +2068 1 2068 2 +2069 1 2069 2 +2070 1 2070 2 +2071 1 2071 2 +2072 1 2072 2 +2073 1 2073 2 +2074 1 2074 2 +2075 1 2075 2 +2076 1 2076 2 +2077 1 2077 2 +2078 1 2078 2 +2079 1 2079 2 +2080 1 2080 2 +2081 1 2081 2 +2082 1 2082 2 +2083 1 2083 2 +2084 1 2084 2 +2085 1 2085 2 +2086 1 2086 2 +2087 1 2087 2 +2088 1 2088 2 +2089 1 2089 2 +2090 1 2090 2 +2091 1 2091 2 +2092 1 2092 2 +2093 1 2093 2 +2094 1 2094 2 +2095 1 2095 2 +2096 1 2096 2 +2097 1 2097 2 +2098 1 2098 2 +2099 1 2099 2 +2100 1 2100 2 +2101 1 2101 2 +2102 1 2102 2 +2103 1 2103 2 +2104 1 2104 2 +2105 1 2105 2 +2106 1 2106 2 +2107 1 2107 2 +2108 1 2108 2 +2109 1 2109 2 +2110 1 2110 2 +2111 1 2111 2 +2112 1 2112 2 +2113 1 2113 2 +2114 1 2114 2 +2115 1 2115 2 +2116 1 2116 2 +2117 1 2117 2 +2118 1 2118 2 +2119 1 2119 2 +2120 1 2120 2 +2121 1 2121 2 +2122 1 2122 2 +2123 1 2123 2 +2124 1 2124 2 +2125 1 2125 2 +2126 1 2126 2 +2127 1 2127 2 +2128 1 2128 2 +2129 1 2129 2 +2130 1 2130 2 +2131 1 2131 2 +2132 1 2132 2 +2133 1 2133 2 +2134 1 2134 2 +2135 1 2135 2 +2136 1 2136 2 +2137 1 2137 2 +2138 1 2138 2 +2139 1 2139 2 +2140 1 2140 2 +2141 1 2141 2 +2142 1 2142 2 +2143 1 2143 2 +2144 1 2144 2 +2145 1 2145 2 +2146 1 2146 2 +2147 1 2147 2 +2148 1 2148 2 +2149 1 2149 2 +2150 1 2150 2 +2151 1 2151 2 +2152 1 2152 2 +2153 1 2153 2 +2154 1 2154 2 +2155 1 2155 2 +2156 1 2156 2 +2157 1 2157 2 +2158 1 2158 2 +2159 1 2159 2 +2160 1 2160 2 +2161 1 2161 2 +2162 1 2162 2 +2163 1 2163 2 +2164 1 2164 2 +2165 1 2165 2 +2166 1 2166 2 +2167 1 2167 2 +2168 1 2168 2 +2169 1 2169 2 +2170 1 2170 2 +2171 1 2171 2 +2172 1 2172 2 +2173 1 2173 2 +2174 1 2174 2 +2175 1 2175 2 + 128 27 29 0 + 129 27 29 1 + 130 27 28 0 + 131 27 28 1 + 132 26 29 0 + 133 26 29 1 + 134 26 28 0 + 135 26 28 1 + 136 24 28 1 + 137 24 28 0 + 138 24 29 1 + 139 24 29 0 + 140 25 28 1 + 141 25 28 0 + 142 25 29 1 + 143 25 29 0 + 160 19 28 0 + 161 19 28 1 + 162 19 29 0 + 163 19 29 1 + 164 18 28 0 + 165 18 28 1 + 166 18 29 0 + 167 18 29 1 + 168 16 29 1 + 169 16 29 0 + 170 16 28 1 + 171 16 28 0 + 172 17 29 1 + 173 17 29 0 + 174 17 28 1 + 175 17 28 0 + 176 20 28 0 + 177 20 28 1 + 178 20 29 0 + 179 20 29 1 + 180 21 28 0 + 181 21 28 1 + 182 21 29 0 + 183 21 29 1 + 184 23 29 1 + 185 23 29 0 + 186 23 28 1 + 187 23 28 0 + 188 22 29 1 + 189 22 29 0 + 190 22 28 1 + 191 22 28 0 + 192 28 29 0 + 193 28 29 1 + 194 28 28 0 + 195 28 28 1 + 196 29 29 0 + 197 29 29 1 + 198 29 28 0 + 199 29 28 1 + 200 31 28 1 + 201 31 28 0 + 202 31 29 1 + 203 31 29 0 + 204 30 28 1 + 205 30 28 0 + 206 30 29 1 + 207 30 29 0 + 256 27 31 0 + 257 27 31 1 + 258 27 30 0 + 259 27 30 1 + 260 26 31 0 + 261 26 31 1 + 262 26 30 0 + 263 26 30 1 + 264 24 30 1 + 265 24 30 0 + 266 24 31 1 + 267 24 31 0 + 268 25 30 1 + 269 25 30 0 + 270 25 31 1 + 271 25 31 0 + 288 19 30 0 + 289 19 30 1 + 290 19 31 0 + 291 19 31 1 + 292 18 30 0 + 293 18 30 1 + 294 18 31 0 + 295 18 31 1 + 296 16 31 1 + 297 16 31 0 + 298 16 30 1 + 299 16 30 0 + 300 17 31 1 + 301 17 31 0 + 302 17 30 1 + 303 17 30 0 + 304 20 30 0 + 305 20 30 1 + 306 20 31 0 + 307 20 31 1 + 308 21 30 0 + 309 21 30 1 + 310 21 31 0 + 311 21 31 1 + 312 23 31 1 + 313 23 31 0 + 314 23 30 1 + 315 23 30 0 + 316 22 31 1 + 317 22 31 0 + 318 22 30 1 + 319 22 30 0 + 320 28 31 0 + 321 28 31 1 + 322 28 30 0 + 323 28 30 1 + 324 29 31 0 + 325 29 31 1 + 326 29 30 0 + 327 29 30 1 + 328 31 30 1 + 329 31 30 0 + 330 31 31 1 + 331 31 31 0 + 332 30 30 1 + 333 30 30 0 + 334 30 31 1 + 335 30 31 0 + 384 27 33 0 + 385 27 33 1 + 386 27 32 0 + 387 27 32 1 + 388 26 33 0 + 389 26 33 1 + 390 26 32 0 + 391 26 32 1 + 392 24 32 1 + 393 24 32 0 + 394 24 33 1 + 395 24 33 0 + 396 25 32 1 + 397 25 32 0 + 398 25 33 1 + 399 25 33 0 + 416 19 32 0 + 417 19 32 1 + 418 19 33 0 + 419 19 33 1 + 420 18 32 0 + 421 18 32 1 + 422 18 33 0 + 423 18 33 1 + 424 16 33 1 + 425 16 33 0 + 426 16 32 1 + 427 16 32 0 + 428 17 33 1 + 429 17 33 0 + 430 17 32 1 + 431 17 32 0 + 432 20 32 0 + 433 20 32 1 + 434 20 33 0 + 435 20 33 1 + 436 21 32 0 + 437 21 32 1 + 438 21 33 0 + 439 21 33 1 + 440 23 33 1 + 441 23 33 0 + 442 23 32 1 + 443 23 32 0 + 444 22 33 1 + 445 22 33 0 + 446 22 32 1 + 447 22 32 0 + 448 28 33 0 + 449 28 33 1 + 450 28 32 0 + 451 28 32 1 + 452 29 33 0 + 453 29 33 1 + 454 29 32 0 + 455 29 32 1 + 456 31 32 1 + 457 31 32 0 + 458 31 33 1 + 459 31 33 0 + 460 30 32 1 + 461 30 32 0 + 462 30 33 1 + 463 30 33 0 + 512 27 35 0 + 513 27 35 1 + 514 27 34 0 + 515 27 34 1 + 516 26 35 0 + 517 26 35 1 + 518 26 34 0 + 519 26 34 1 + 520 24 34 1 + 521 24 34 0 + 522 24 35 1 + 523 24 35 0 + 524 25 34 1 + 525 25 34 0 + 526 25 35 1 + 527 25 35 0 + 544 19 34 0 + 545 19 34 1 + 546 19 35 0 + 547 19 35 1 + 548 18 34 0 + 549 18 34 1 + 550 18 35 0 + 551 18 35 1 + 552 16 35 1 + 553 16 35 0 + 554 16 34 1 + 555 16 34 0 + 556 17 35 1 + 557 17 35 0 + 558 17 34 1 + 559 17 34 0 + 560 20 34 0 + 561 20 34 1 + 562 20 35 0 + 563 20 35 1 + 564 21 34 0 + 565 21 34 1 + 566 21 35 0 + 567 21 35 1 + 568 23 35 1 + 569 23 35 0 + 570 23 34 1 + 571 23 34 0 + 572 22 35 1 + 573 22 35 0 + 574 22 34 1 + 575 22 34 0 + 576 28 35 0 + 577 28 35 1 + 578 28 34 0 + 579 28 34 1 + 580 29 35 0 + 581 29 35 1 + 582 29 34 0 + 583 29 34 1 + 584 31 34 1 + 585 31 34 0 + 586 31 35 1 + 587 31 35 0 + 588 30 34 1 + 589 30 34 0 + 590 30 35 1 + 591 30 35 0 + 640 27 37 0 + 641 27 37 1 + 642 27 36 0 + 643 27 36 1 + 644 26 37 0 + 645 26 37 1 + 646 26 36 0 + 647 26 36 1 + 648 24 36 1 + 649 24 36 0 + 650 24 37 1 + 651 24 37 0 + 652 25 36 1 + 653 25 36 0 + 654 25 37 1 + 655 25 37 0 + 672 19 36 0 + 673 19 36 1 + 674 19 37 0 + 675 19 37 1 + 676 18 36 0 + 677 18 36 1 + 678 18 37 0 + 679 18 37 1 + 680 16 37 1 + 681 16 37 0 + 682 16 36 1 + 683 16 36 0 + 684 17 37 1 + 685 17 37 0 + 686 17 36 1 + 687 17 36 0 + 688 20 36 0 + 689 20 36 1 + 690 20 37 0 + 691 20 37 1 + 692 21 36 0 + 693 21 36 1 + 694 21 37 0 + 695 21 37 1 + 696 23 37 1 + 697 23 37 0 + 698 23 36 1 + 699 23 36 0 + 700 22 37 1 + 701 22 37 0 + 702 22 36 1 + 703 22 36 0 + 704 28 37 0 + 705 28 37 1 + 706 28 36 0 + 707 28 36 1 + 708 29 37 0 + 709 29 37 1 + 710 29 36 0 + 711 29 36 1 + 712 31 36 1 + 713 31 36 0 + 714 31 37 1 + 715 31 37 0 + 716 30 36 1 + 717 30 36 0 + 718 30 37 1 + 719 30 37 0 + 768 27 39 0 + 769 27 39 1 + 770 27 38 0 + 771 27 38 1 + 772 26 39 0 + 773 26 39 1 + 774 26 38 0 + 775 26 38 1 + 776 24 38 1 + 777 24 38 0 + 778 24 39 1 + 779 24 39 0 + 780 25 38 1 + 781 25 38 0 + 782 25 39 1 + 783 25 39 0 + 800 19 38 0 + 801 19 38 1 + 802 19 39 0 + 803 19 39 1 + 804 18 38 0 + 805 18 38 1 + 806 18 39 0 + 807 18 39 1 + 808 16 39 1 + 809 16 39 0 + 810 16 38 1 + 811 16 38 0 + 812 17 39 1 + 813 17 39 0 + 814 17 38 1 + 815 17 38 0 + 816 20 38 0 + 817 20 38 1 + 818 20 39 0 + 819 20 39 1 + 820 21 38 0 + 821 21 38 1 + 822 21 39 0 + 823 21 39 1 + 824 23 39 1 + 825 23 39 0 + 826 23 38 1 + 827 23 38 0 + 828 22 39 1 + 829 22 39 0 + 830 22 38 1 + 831 22 38 0 + 832 28 39 0 + 833 28 39 1 + 834 28 38 0 + 835 28 38 1 + 836 29 39 0 + 837 29 39 1 + 838 29 38 0 + 839 29 38 1 + 840 31 38 1 + 841 31 38 0 + 842 31 39 1 + 843 31 39 0 + 844 30 38 1 + 845 30 38 0 + 846 30 39 1 + 847 30 39 0 + 896 27 41 0 + 897 27 41 1 + 898 27 40 0 + 899 27 40 1 + 900 26 41 0 + 901 26 41 1 + 902 26 40 0 + 903 26 40 1 + 904 24 40 1 + 905 24 40 0 + 906 24 41 1 + 907 24 41 0 + 908 25 40 1 + 909 25 40 0 + 910 25 41 1 + 911 25 41 0 + 928 19 40 0 + 929 19 40 1 + 930 19 41 0 + 931 19 41 1 + 932 18 40 0 + 933 18 40 1 + 934 18 41 0 + 935 18 41 1 + 936 16 41 1 + 937 16 41 0 + 938 16 40 1 + 939 16 40 0 + 940 17 41 1 + 941 17 41 0 + 942 17 40 1 + 943 17 40 0 + 944 20 40 0 + 945 20 40 1 + 946 20 41 0 + 947 20 41 1 + 948 21 40 0 + 949 21 40 1 + 950 21 41 0 + 951 21 41 1 + 952 23 41 1 + 953 23 41 0 + 954 23 40 1 + 955 23 40 0 + 956 22 41 1 + 957 22 41 0 + 958 22 40 1 + 959 22 40 0 + 960 28 41 0 + 961 28 41 1 + 962 28 40 0 + 963 28 40 1 + 964 29 41 0 + 965 29 41 1 + 966 29 40 0 + 967 29 40 1 + 968 31 40 1 + 969 31 40 0 + 970 31 41 1 + 971 31 41 0 + 972 30 40 1 + 973 30 40 0 + 974 30 41 1 + 975 30 41 0 +1024 27 43 0 +1025 27 43 1 +1026 27 42 0 +1027 27 42 1 +1028 26 43 0 +1029 26 43 1 +1030 26 42 0 +1031 26 42 1 +1032 24 42 1 +1033 24 42 0 +1034 24 43 1 +1035 24 43 0 +1036 25 42 1 +1037 25 42 0 +1038 25 43 1 +1039 25 43 0 +1056 19 42 0 +1057 19 42 1 +1058 19 43 0 +1059 19 43 1 +1060 18 42 0 +1061 18 42 1 +1062 18 43 0 +1063 18 43 1 +1064 16 43 1 +1065 16 43 0 +1066 16 42 1 +1067 16 42 0 +1068 17 43 1 +1069 17 43 0 +1070 17 42 1 +1071 17 42 0 +1072 20 42 0 +1073 20 42 1 +1074 20 43 0 +1075 20 43 1 +1076 21 42 0 +1077 21 42 1 +1078 21 43 0 +1079 21 43 1 +1080 23 43 1 +1081 23 43 0 +1082 23 42 1 +1083 23 42 0 +1084 22 43 1 +1085 22 43 0 +1086 22 42 1 +1087 22 42 0 +1088 28 43 0 +1089 28 43 1 +1090 28 42 0 +1091 28 42 1 +1092 29 43 0 +1093 29 43 1 +1094 29 42 0 +1095 29 42 1 +1096 31 42 1 +1097 31 42 0 +1098 31 43 1 +1099 31 43 0 +1100 30 42 1 +1101 30 42 0 +1102 30 43 1 +1103 30 43 0 +1152 27 45 0 +1153 27 45 1 +1154 27 44 0 +1155 27 44 1 +1156 26 45 0 +1157 26 45 1 +1158 26 44 0 +1159 26 44 1 +1160 24 44 1 +1161 24 44 0 +1162 24 45 1 +1163 24 45 0 +1164 25 44 1 +1165 25 44 0 +1166 25 45 1 +1167 25 45 0 +1184 19 44 0 +1185 19 44 1 +1186 19 45 0 +1187 19 45 1 +1188 18 44 0 +1189 18 44 1 +1190 18 45 0 +1191 18 45 1 +1192 16 45 1 +1193 16 45 0 +1194 16 44 1 +1195 16 44 0 +1196 17 45 1 +1197 17 45 0 +1198 17 44 1 +1199 17 44 0 +1200 20 44 0 +1201 20 44 1 +1202 20 45 0 +1203 20 45 1 +1204 21 44 0 +1205 21 44 1 +1206 21 45 0 +1207 21 45 1 +1208 23 45 1 +1209 23 45 0 +1210 23 44 1 +1211 23 44 0 +1212 22 45 1 +1213 22 45 0 +1214 22 44 1 +1215 22 44 0 +1216 28 45 0 +1217 28 45 1 +1218 28 44 0 +1219 28 44 1 +1220 29 45 0 +1221 29 45 1 +1222 29 44 0 +1223 29 44 1 +1224 31 44 1 +1225 31 44 0 +1226 31 45 1 +1227 31 45 0 +1228 30 44 1 +1229 30 44 0 +1230 30 45 1 +1231 30 45 0 +1280 27 47 0 +1281 27 47 1 +1282 27 46 0 +1283 27 46 1 +1284 26 47 0 +1285 26 47 1 +1286 26 46 0 +1287 26 46 1 +1288 24 46 1 +1289 24 46 0 +1290 24 47 1 +1291 24 47 0 +1292 25 46 1 +1293 25 46 0 +1294 25 47 1 +1295 25 47 0 +1312 19 46 0 +1313 19 46 1 +1314 19 47 0 +1315 19 47 1 +1316 18 46 0 +1317 18 46 1 +1318 18 47 0 +1319 18 47 1 +1320 16 47 1 +1321 16 47 0 +1322 16 46 1 +1323 16 46 0 +1324 17 47 1 +1325 17 47 0 +1326 17 46 1 +1327 17 46 0 +1328 20 46 0 +1329 20 46 1 +1330 20 47 0 +1331 20 47 1 +1332 21 46 0 +1333 21 46 1 +1334 21 47 0 +1335 21 47 1 +1336 23 47 1 +1337 23 47 0 +1338 23 46 1 +1339 23 46 0 +1340 22 47 1 +1341 22 47 0 +1342 22 46 1 +1343 22 46 0 +1344 28 47 0 +1345 28 47 1 +1346 28 46 0 +1347 28 46 1 +1348 29 47 0 +1349 29 47 1 +1350 29 46 0 +1351 29 46 1 +1352 31 46 1 +1353 31 46 0 +1354 31 47 1 +1355 31 47 0 +1356 30 46 1 +1357 30 46 0 +1358 30 47 1 +1359 30 47 0 +1408 27 49 0 +1409 27 49 1 +1410 27 48 0 +1411 27 48 1 +1412 26 49 0 +1413 26 49 1 +1414 26 48 0 +1415 26 48 1 +1416 24 48 1 +1417 24 48 0 +1418 24 49 1 +1419 24 49 0 +1420 25 48 1 +1421 25 48 0 +1422 25 49 1 +1423 25 49 0 +1440 19 48 0 +1441 19 48 1 +1442 19 49 0 +1443 19 49 1 +1444 18 48 0 +1445 18 48 1 +1446 18 49 0 +1447 18 49 1 +1448 16 49 1 +1449 16 49 0 +1450 16 48 1 +1451 16 48 0 +1452 17 49 1 +1453 17 49 0 +1454 17 48 1 +1455 17 48 0 +1456 20 48 0 +1457 20 48 1 +1458 20 49 0 +1459 20 49 1 +1460 21 48 0 +1461 21 48 1 +1462 21 49 0 +1463 21 49 1 +1464 23 49 1 +1465 23 49 0 +1466 23 48 1 +1467 23 48 0 +1468 22 49 1 +1469 22 49 0 +1470 22 48 1 +1471 22 48 0 +1472 28 49 0 +1473 28 49 1 +1474 28 48 0 +1475 28 48 1 +1476 29 49 0 +1477 29 49 1 +1478 29 48 0 +1479 29 48 1 +1480 31 48 1 +1481 31 48 0 +1482 31 49 1 +1483 31 49 0 +1484 30 48 1 +1485 30 48 0 +1486 30 49 1 +1487 30 49 0 +1536 27 51 0 +1537 27 51 1 +1538 27 50 0 +1539 27 50 1 +1540 26 51 0 +1541 26 51 1 +1542 26 50 0 +1543 26 50 1 +1544 24 50 1 +1545 24 50 0 +1546 24 51 1 +1547 24 51 0 +1548 25 50 1 +1549 25 50 0 +1550 25 51 1 +1551 25 51 0 +1568 19 50 0 +1569 19 50 1 +1570 19 51 0 +1571 19 51 1 +1572 18 50 0 +1573 18 50 1 +1574 18 51 0 +1575 18 51 1 +1576 16 51 1 +1577 16 51 0 +1578 16 50 1 +1579 16 50 0 +1580 17 51 1 +1581 17 51 0 +1582 17 50 1 +1583 17 50 0 +1584 20 50 0 +1585 20 50 1 +1586 20 51 0 +1587 20 51 1 +1588 21 50 0 +1589 21 50 1 +1590 21 51 0 +1591 21 51 1 +1592 23 51 1 +1593 23 51 0 +1594 23 50 1 +1595 23 50 0 +1596 22 51 1 +1597 22 51 0 +1598 22 50 1 +1599 22 50 0 +1600 28 51 0 +1601 28 51 1 +1602 28 50 0 +1603 28 50 1 +1604 29 51 0 +1605 29 51 1 +1606 29 50 0 +1607 29 50 1 +1608 31 50 1 +1609 31 50 0 +1610 31 51 1 +1611 31 51 0 +1612 30 50 1 +1613 30 50 0 +1614 30 51 1 +1615 30 51 0 +1664 27 53 0 +1665 27 53 1 +1666 27 52 0 +1667 27 52 1 +1668 26 53 0 +1669 26 53 1 +1670 26 52 0 +1671 26 52 1 +1672 24 52 1 +1673 24 52 0 +1674 24 53 1 +1675 24 53 0 +1676 25 52 1 +1677 25 52 0 +1678 25 53 1 +1679 25 53 0 +1696 19 52 0 +1697 19 52 1 +1698 19 53 0 +1699 19 53 1 +1700 18 52 0 +1701 18 52 1 +1702 18 53 0 +1703 18 53 1 +1704 16 53 1 +1705 16 53 0 +1706 16 52 1 +1707 16 52 0 +1708 17 53 1 +1709 17 53 0 +1710 17 52 1 +1711 17 52 0 +1712 20 52 0 +1713 20 52 1 +1714 20 53 0 +1715 20 53 1 +1716 21 52 0 +1717 21 52 1 +1718 21 53 0 +1719 21 53 1 +1720 23 53 1 +1721 23 53 0 +1722 23 52 1 +1723 23 52 0 +1724 22 53 1 +1725 22 53 0 +1726 22 52 1 +1727 22 52 0 +1728 28 53 0 +1729 28 53 1 +1730 28 52 0 +1731 28 52 1 +1732 29 53 0 +1733 29 53 1 +1734 29 52 0 +1735 29 52 1 +1736 31 52 1 +1737 31 52 0 +1738 31 53 1 +1739 31 53 0 +1740 30 52 1 +1741 30 52 0 +1742 30 53 1 +1743 30 53 0 +1792 27 55 0 +1793 27 55 1 +1794 27 54 0 +1795 27 54 1 +1796 26 55 0 +1797 26 55 1 +1798 26 54 0 +1799 26 54 1 +1800 24 54 1 +1801 24 54 0 +1802 24 55 1 +1803 24 55 0 +1804 25 54 1 +1805 25 54 0 +1806 25 55 1 +1807 25 55 0 +1824 19 54 0 +1825 19 54 1 +1826 19 55 0 +1827 19 55 1 +1828 18 54 0 +1829 18 54 1 +1830 18 55 0 +1831 18 55 1 +1832 16 55 1 +1833 16 55 0 +1834 16 54 1 +1835 16 54 0 +1836 17 55 1 +1837 17 55 0 +1838 17 54 1 +1839 17 54 0 +1840 20 54 0 +1841 20 54 1 +1842 20 55 0 +1843 20 55 1 +1844 21 54 0 +1845 21 54 1 +1846 21 55 0 +1847 21 55 1 +1848 23 55 1 +1849 23 55 0 +1850 23 54 1 +1851 23 54 0 +1852 22 55 1 +1853 22 55 0 +1854 22 54 1 +1855 22 54 0 +1856 28 55 0 +1857 28 55 1 +1858 28 54 0 +1859 28 54 1 +1860 29 55 0 +1861 29 55 1 +1862 29 54 0 +1863 29 54 1 +1864 31 54 1 +1865 31 54 0 +1866 31 55 1 +1867 31 55 0 +1868 30 54 1 +1869 30 54 0 +1870 30 55 1 +1871 30 55 0 +2176 27 27 0 +2177 27 27 1 +2178 27 26 0 +2179 27 26 1 +2180 26 27 0 +2181 26 27 1 +2182 26 26 0 +2183 26 26 1 +2184 24 26 1 +2185 24 26 0 +2186 24 27 1 +2187 24 27 0 +2188 25 26 1 +2189 25 26 0 +2190 25 27 1 +2191 25 27 0 +2208 19 26 0 +2209 19 26 1 +2210 19 27 0 +2211 19 27 1 +2212 18 26 0 +2213 18 26 1 +2214 18 27 0 +2215 18 27 1 +2216 16 27 1 +2217 16 27 0 +2218 16 26 1 +2219 16 26 0 +2220 17 27 1 +2221 17 27 0 +2222 17 26 1 +2223 17 26 0 +2224 20 26 0 +2225 20 26 1 +2226 20 27 0 +2227 20 27 1 +2228 21 26 0 +2229 21 26 1 +2230 21 27 0 +2231 21 27 1 +2232 23 27 1 +2233 23 27 0 +2234 23 26 1 +2235 23 26 0 +2236 22 27 1 +2237 22 27 0 +2238 22 26 1 +2239 22 26 0 +2240 28 27 0 +2241 28 27 1 +2242 28 26 0 +2243 28 26 1 +2244 29 27 0 +2245 29 27 1 +2246 29 26 0 +2247 29 26 1 +2248 31 26 1 +2249 31 26 0 +2250 31 27 1 +2251 31 27 0 +2252 30 26 1 +2253 30 26 0 +2254 30 27 1 +2255 30 27 0 +2304 27 25 0 +2305 27 25 1 +2306 27 24 0 +2307 27 24 1 +2308 26 25 0 +2309 26 25 1 +2310 26 24 0 +2311 26 24 1 +2312 24 24 1 +2313 24 24 0 +2314 24 25 1 +2315 24 25 0 +2316 25 24 1 +2317 25 24 0 +2318 25 25 1 +2319 25 25 0 +2336 19 24 0 +2337 19 24 1 +2338 19 25 0 +2339 19 25 1 +2340 18 24 0 +2341 18 24 1 +2342 18 25 0 +2343 18 25 1 +2344 16 25 1 +2345 16 25 0 +2346 16 24 1 +2347 16 24 0 +2348 17 25 1 +2349 17 25 0 +2350 17 24 1 +2351 17 24 0 +2352 20 24 0 +2353 20 24 1 +2354 20 25 0 +2355 20 25 1 +2356 21 24 0 +2357 21 24 1 +2358 21 25 0 +2359 21 25 1 +2360 23 25 1 +2361 23 25 0 +2362 23 24 1 +2363 23 24 0 +2364 22 25 1 +2365 22 25 0 +2366 22 24 1 +2367 22 24 0 +2368 28 25 0 +2369 28 25 1 +2370 28 24 0 +2371 28 24 1 +2372 29 25 0 +2373 29 25 1 +2374 29 24 0 +2375 29 24 1 +2376 31 24 1 +2377 31 24 0 +2378 31 25 1 +2379 31 25 0 +2380 30 24 1 +2381 30 24 0 +2382 30 25 1 +2383 30 25 0 +2432 27 23 0 +2433 27 23 1 +2434 27 22 0 +2435 27 22 1 +2436 26 23 0 +2437 26 23 1 +2438 26 22 0 +2439 26 22 1 +2440 24 22 1 +2441 24 22 0 +2442 24 23 1 +2443 24 23 0 +2444 25 22 1 +2445 25 22 0 +2446 25 23 1 +2447 25 23 0 +2464 19 22 0 +2465 19 22 1 +2466 19 23 0 +2467 19 23 1 +2468 18 22 0 +2469 18 22 1 +2470 18 23 0 +2471 18 23 1 +2472 16 23 1 +2473 16 23 0 +2474 16 22 1 +2475 16 22 0 +2476 17 23 1 +2477 17 23 0 +2478 17 22 1 +2479 17 22 0 +2480 20 22 0 +2481 20 22 1 +2482 20 23 0 +2483 20 23 1 +2484 21 22 0 +2485 21 22 1 +2486 21 23 0 +2487 21 23 1 +2488 23 23 1 +2489 23 23 0 +2490 23 22 1 +2491 23 22 0 +2492 22 23 1 +2493 22 23 0 +2494 22 22 1 +2495 22 22 0 +2496 28 23 0 +2497 28 23 1 +2498 28 22 0 +2499 28 22 1 +2500 29 23 0 +2501 29 23 1 +2502 29 22 0 +2503 29 22 1 +2504 31 22 1 +2505 31 22 0 +2506 31 23 1 +2507 31 23 0 +2508 30 22 1 +2509 30 22 0 +2510 30 23 1 +2511 30 23 0 +2560 27 21 0 +2561 27 21 1 +2562 27 20 0 +2563 27 20 1 +2564 26 21 0 +2565 26 21 1 +2566 26 20 0 +2567 26 20 1 +2568 24 20 1 +2569 24 20 0 +2570 24 21 1 +2571 24 21 0 +2572 25 20 1 +2573 25 20 0 +2574 25 21 1 +2575 25 21 0 +2592 19 20 0 +2593 19 20 1 +2594 19 21 0 +2595 19 21 1 +2596 18 20 0 +2597 18 20 1 +2598 18 21 0 +2599 18 21 1 +2600 16 21 1 +2601 16 21 0 +2602 16 20 1 +2603 16 20 0 +2604 17 21 1 +2605 17 21 0 +2606 17 20 1 +2607 17 20 0 +2608 20 20 0 +2609 20 20 1 +2610 20 21 0 +2611 20 21 1 +2612 21 20 0 +2613 21 20 1 +2614 21 21 0 +2615 21 21 1 +2616 23 21 1 +2617 23 21 0 +2618 23 20 1 +2619 23 20 0 +2620 22 21 1 +2621 22 21 0 +2622 22 20 1 +2623 22 20 0 +2624 28 21 0 +2625 28 21 1 +2626 28 20 0 +2627 28 20 1 +2628 29 21 0 +2629 29 21 1 +2630 29 20 0 +2631 29 20 1 +2632 31 20 1 +2633 31 20 0 +2634 31 21 1 +2635 31 21 0 +2636 30 20 1 +2637 30 20 0 +2638 30 21 1 +2639 30 21 0 +2688 27 19 0 +2689 27 19 1 +2690 27 18 0 +2691 27 18 1 +2692 26 19 0 +2693 26 19 1 +2694 26 18 0 +2695 26 18 1 +2696 24 18 1 +2697 24 18 0 +2698 24 19 1 +2699 24 19 0 +2700 25 18 1 +2701 25 18 0 +2702 25 19 1 +2703 25 19 0 +2720 19 18 0 +2721 19 18 1 +2722 19 19 0 +2723 19 19 1 +2724 18 18 0 +2725 18 18 1 +2726 18 19 0 +2727 18 19 1 +2728 16 19 1 +2729 16 19 0 +2730 16 18 1 +2731 16 18 0 +2732 17 19 1 +2733 17 19 0 +2734 17 18 1 +2735 17 18 0 +2736 20 18 0 +2737 20 18 1 +2738 20 19 0 +2739 20 19 1 +2740 21 18 0 +2741 21 18 1 +2742 21 19 0 +2743 21 19 1 +2744 23 19 1 +2745 23 19 0 +2746 23 18 1 +2747 23 18 0 +2748 22 19 1 +2749 22 19 0 +2750 22 18 1 +2751 22 18 0 +2752 28 19 0 +2753 28 19 1 +2754 28 18 0 +2755 28 18 1 +2756 29 19 0 +2757 29 19 1 +2758 29 18 0 +2759 29 18 1 +2760 31 18 1 +2761 31 18 0 +2762 31 19 1 +2763 31 19 0 +2764 30 18 1 +2765 30 18 0 +2766 30 19 1 +2767 30 19 0 +2816 27 17 0 +2817 27 17 1 +2818 27 16 0 +2819 27 16 1 +2820 26 17 0 +2821 26 17 1 +2822 26 16 0 +2823 26 16 1 +2824 24 16 1 +2825 24 16 0 +2826 24 17 1 +2827 24 17 0 +2828 25 16 1 +2829 25 16 0 +2830 25 17 1 +2831 25 17 0 +2848 19 16 0 +2849 19 16 1 +2850 19 17 0 +2851 19 17 1 +2852 18 16 0 +2853 18 16 1 +2854 18 17 0 +2855 18 17 1 +2856 16 17 1 +2857 16 17 0 +2858 16 16 1 +2859 16 16 0 +2860 17 17 1 +2861 17 17 0 +2862 17 16 1 +2863 17 16 0 +2864 20 16 0 +2865 20 16 1 +2866 20 17 0 +2867 20 17 1 +2868 21 16 0 +2869 21 16 1 +2870 21 17 0 +2871 21 17 1 +2872 23 17 1 +2873 23 17 0 +2874 23 16 1 +2875 23 16 0 +2876 22 17 1 +2877 22 17 0 +2878 22 16 1 +2879 22 16 0 +2880 28 17 0 +2881 28 17 1 +2882 28 16 0 +2883 28 16 1 +2884 29 17 0 +2885 29 17 1 +2886 29 16 0 +2887 29 16 1 +2888 31 16 1 +2889 31 16 0 +2890 31 17 1 +2891 31 17 0 +2892 30 16 1 +2893 30 16 0 +2894 30 17 1 +2895 30 17 0 +2944 27 15 0 +2945 27 15 1 +2946 27 14 0 +2947 27 14 1 +2948 26 15 0 +2949 26 15 1 +2950 26 14 0 +2951 26 14 1 +2952 24 14 1 +2953 24 14 0 +2954 24 15 1 +2955 24 15 0 +2956 25 14 1 +2957 25 14 0 +2958 25 15 1 +2959 25 15 0 +2976 19 14 0 +2977 19 14 1 +2978 19 15 0 +2979 19 15 1 +2980 18 14 0 +2981 18 14 1 +2982 18 15 0 +2983 18 15 1 +2984 16 15 1 +2985 16 15 0 +2986 16 14 1 +2987 16 14 0 +2988 17 15 1 +2989 17 15 0 +2990 17 14 1 +2991 17 14 0 +2992 20 14 0 +2993 20 14 1 +2994 20 15 0 +2995 20 15 1 +2996 21 14 0 +2997 21 14 1 +2998 21 15 0 +2999 21 15 1 +3000 23 15 1 +3001 23 15 0 +3002 23 14 1 +3003 23 14 0 +3004 22 15 1 +3005 22 15 0 +3006 22 14 1 +3007 22 14 0 +3008 28 15 0 +3009 28 15 1 +3010 28 14 0 +3011 28 14 1 +3012 29 15 0 +3013 29 15 1 +3014 29 14 0 +3015 29 14 1 +3016 31 14 1 +3017 31 14 0 +3018 31 15 1 +3019 31 15 0 +3020 30 14 1 +3021 30 14 0 +3022 30 15 1 +3023 30 15 0 +3072 27 13 0 +3073 27 13 1 +3074 27 12 0 +3075 27 12 1 +3076 26 13 0 +3077 26 13 1 +3078 26 12 0 +3079 26 12 1 +3080 24 12 1 +3081 24 12 0 +3082 24 13 1 +3083 24 13 0 +3084 25 12 1 +3085 25 12 0 +3086 25 13 1 +3087 25 13 0 +3104 19 12 0 +3105 19 12 1 +3106 19 13 0 +3107 19 13 1 +3108 18 12 0 +3109 18 12 1 +3110 18 13 0 +3111 18 13 1 +3112 16 13 1 +3113 16 13 0 +3114 16 12 1 +3115 16 12 0 +3116 17 13 1 +3117 17 13 0 +3118 17 12 1 +3119 17 12 0 +3120 20 12 0 +3121 20 12 1 +3122 20 13 0 +3123 20 13 1 +3124 21 12 0 +3125 21 12 1 +3126 21 13 0 +3127 21 13 1 +3128 23 13 1 +3129 23 13 0 +3130 23 12 1 +3131 23 12 0 +3132 22 13 1 +3133 22 13 0 +3134 22 12 1 +3135 22 12 0 +3136 28 13 0 +3137 28 13 1 +3138 28 12 0 +3139 28 12 1 +3140 29 13 0 +3141 29 13 1 +3142 29 12 0 +3143 29 12 1 +3144 31 12 1 +3145 31 12 0 +3146 31 13 1 +3147 31 13 0 +3148 30 12 1 +3149 30 12 0 +3150 30 13 1 +3151 30 13 0 +3200 27 11 0 +3201 27 11 1 +3202 27 10 0 +3203 27 10 1 +3204 26 11 0 +3205 26 11 1 +3206 26 10 0 +3207 26 10 1 +3208 24 10 1 +3209 24 10 0 +3210 24 11 1 +3211 24 11 0 +3212 25 10 1 +3213 25 10 0 +3214 25 11 1 +3215 25 11 0 +3232 19 10 0 +3233 19 10 1 +3234 19 11 0 +3235 19 11 1 +3236 18 10 0 +3237 18 10 1 +3238 18 11 0 +3239 18 11 1 +3240 16 11 1 +3241 16 11 0 +3242 16 10 1 +3243 16 10 0 +3244 17 11 1 +3245 17 11 0 +3246 17 10 1 +3247 17 10 0 +3248 20 10 0 +3249 20 10 1 +3250 20 11 0 +3251 20 11 1 +3252 21 10 0 +3253 21 10 1 +3254 21 11 0 +3255 21 11 1 +3256 23 11 1 +3257 23 11 0 +3258 23 10 1 +3259 23 10 0 +3260 22 11 1 +3261 22 11 0 +3262 22 10 1 +3263 22 10 0 +3264 28 11 0 +3265 28 11 1 +3266 28 10 0 +3267 28 10 1 +3268 29 11 0 +3269 29 11 1 +3270 29 10 0 +3271 29 10 1 +3272 31 10 1 +3273 31 10 0 +3274 31 11 1 +3275 31 11 0 +3276 30 10 1 +3277 30 10 0 +3278 30 11 1 +3279 30 11 0 +3328 27 9 0 +3329 27 9 1 +3330 27 8 0 +3331 27 8 1 +3332 26 9 0 +3333 26 9 1 +3334 26 8 0 +3335 26 8 1 +3336 24 8 1 +3337 24 8 0 +3338 24 9 1 +3339 24 9 0 +3340 25 8 1 +3341 25 8 0 +3342 25 9 1 +3343 25 9 0 +3360 19 8 0 +3361 19 8 1 +3362 19 9 0 +3363 19 9 1 +3364 18 8 0 +3365 18 8 1 +3366 18 9 0 +3367 18 9 1 +3368 16 9 1 +3369 16 9 0 +3370 16 8 1 +3371 16 8 0 +3372 17 9 1 +3373 17 9 0 +3374 17 8 1 +3375 17 8 0 +3376 20 8 0 +3377 20 8 1 +3378 20 9 0 +3379 20 9 1 +3380 21 8 0 +3381 21 8 1 +3382 21 9 0 +3383 21 9 1 +3384 23 9 1 +3385 23 9 0 +3386 23 8 1 +3387 23 8 0 +3388 22 9 1 +3389 22 9 0 +3390 22 8 1 +3391 22 8 0 +3392 28 9 0 +3393 28 9 1 +3394 28 8 0 +3395 28 8 1 +3396 29 9 0 +3397 29 9 1 +3398 29 8 0 +3399 29 8 1 +3400 31 8 1 +3401 31 8 0 +3402 31 9 1 +3403 31 9 0 +3404 30 8 1 +3405 30 8 0 +3406 30 9 1 +3407 30 9 0 +3456 27 7 0 +3457 27 7 1 +3458 27 6 0 +3459 27 6 1 +3460 26 7 0 +3461 26 7 1 +3462 26 6 0 +3463 26 6 1 +3464 24 6 1 +3465 24 6 0 +3466 24 7 1 +3467 24 7 0 +3468 25 6 1 +3469 25 6 0 +3470 25 7 1 +3471 25 7 0 +3488 19 6 0 +3489 19 6 1 +3490 19 7 0 +3491 19 7 1 +3492 18 6 0 +3493 18 6 1 +3494 18 7 0 +3495 18 7 1 +3496 16 7 1 +3497 16 7 0 +3498 16 6 1 +3499 16 6 0 +3500 17 7 1 +3501 17 7 0 +3502 17 6 1 +3503 17 6 0 +3504 20 6 0 +3505 20 6 1 +3506 20 7 0 +3507 20 7 1 +3508 21 6 0 +3509 21 6 1 +3510 21 7 0 +3511 21 7 1 +3512 23 7 1 +3513 23 7 0 +3514 23 6 1 +3515 23 6 0 +3516 22 7 1 +3517 22 7 0 +3518 22 6 1 +3519 22 6 0 +3520 28 7 0 +3521 28 7 1 +3522 28 6 0 +3523 28 6 1 +3524 29 7 0 +3525 29 7 1 +3526 29 6 0 +3527 29 6 1 +3528 31 6 1 +3529 31 6 0 +3530 31 7 1 +3531 31 7 0 +3532 30 6 1 +3533 30 6 0 +3534 30 7 1 +3535 30 7 0 +3584 27 5 0 +3585 27 5 1 +3586 27 4 0 +3587 27 4 1 +3588 26 5 0 +3589 26 5 1 +3590 26 4 0 +3591 26 4 1 +3592 24 4 1 +3593 24 4 0 +3594 24 5 1 +3595 24 5 0 +3596 25 4 1 +3597 25 4 0 +3598 25 5 1 +3599 25 5 0 +3616 19 4 0 +3617 19 4 1 +3618 19 5 0 +3619 19 5 1 +3620 18 4 0 +3621 18 4 1 +3622 18 5 0 +3623 18 5 1 +3624 16 5 1 +3625 16 5 0 +3626 16 4 1 +3627 16 4 0 +3628 17 5 1 +3629 17 5 0 +3630 17 4 1 +3631 17 4 0 +3632 20 4 0 +3633 20 4 1 +3634 20 5 0 +3635 20 5 1 +3636 21 4 0 +3637 21 4 1 +3638 21 5 0 +3639 21 5 1 +3640 23 5 1 +3641 23 5 0 +3642 23 4 1 +3643 23 4 0 +3644 22 5 1 +3645 22 5 0 +3646 22 4 1 +3647 22 4 0 +3648 28 5 0 +3649 28 5 1 +3650 28 4 0 +3651 28 4 1 +3652 29 5 0 +3653 29 5 1 +3654 29 4 0 +3655 29 4 1 +3656 31 4 1 +3657 31 4 0 +3658 31 5 1 +3659 31 5 0 +3660 30 4 1 +3661 30 4 0 +3662 30 5 1 +3663 30 5 0 +3712 27 3 0 +3713 27 3 1 +3714 27 2 0 +3715 27 2 1 +3716 26 3 0 +3717 26 3 1 +3718 26 2 0 +3719 26 2 1 +3720 24 2 1 +3721 24 2 0 +3722 24 3 1 +3723 24 3 0 +3724 25 2 1 +3725 25 2 0 +3726 25 3 1 +3727 25 3 0 +3744 19 2 0 +3745 19 2 1 +3746 19 3 0 +3747 19 3 1 +3748 18 2 0 +3749 18 2 1 +3750 18 3 0 +3751 18 3 1 +3752 16 3 1 +3753 16 3 0 +3754 16 2 1 +3755 16 2 0 +3756 17 3 1 +3757 17 3 0 +3758 17 2 1 +3759 17 2 0 +3760 20 2 0 +3761 20 2 1 +3762 20 3 0 +3763 20 3 1 +3764 21 2 0 +3765 21 2 1 +3766 21 3 0 +3767 21 3 1 +3768 23 3 1 +3769 23 3 0 +3770 23 2 1 +3771 23 2 0 +3772 22 3 1 +3773 22 3 0 +3774 22 2 1 +3775 22 2 0 +3776 28 3 0 +3777 28 3 1 +3778 28 2 0 +3779 28 2 1 +3780 29 3 0 +3781 29 3 1 +3782 29 2 0 +3783 29 2 1 +3784 31 2 1 +3785 31 2 0 +3786 31 3 1 +3787 31 3 0 +3788 30 2 1 +3789 30 2 0 +3790 30 3 1 +3791 30 3 0 +3840 27 1 0 +3841 27 1 1 +3842 27 0 0 +3843 27 0 1 +3844 26 1 0 +3845 26 1 1 +3846 26 0 0 +3847 26 0 1 +3848 24 0 1 +3849 24 0 0 +3850 24 1 1 +3851 24 1 0 +3852 25 0 1 +3853 25 0 0 +3854 25 1 1 +3855 25 1 0 +3872 19 0 0 +3873 19 0 1 +3874 19 1 0 +3875 19 1 1 +3876 18 0 0 +3877 18 0 1 +3878 18 1 0 +3879 18 1 1 +3880 16 1 1 +3881 16 1 0 +3882 16 0 1 +3883 16 0 0 +3884 17 1 1 +3885 17 1 0 +3886 17 0 1 +3887 17 0 0 +3888 20 0 0 +3889 20 0 1 +3890 20 1 0 +3891 20 1 1 +3892 21 0 0 +3893 21 0 1 +3894 21 1 0 +3895 21 1 1 +3896 23 1 1 +3897 23 1 0 +3898 23 0 1 +3899 23 0 0 +3900 22 1 1 +3901 22 1 0 +3902 22 0 1 +3903 22 0 0 +3904 28 1 0 +3905 28 1 1 +3906 28 0 0 +3907 28 0 1 +3908 29 1 0 +3909 29 1 1 +3910 29 0 0 +3911 29 0 1 +3912 31 0 1 +3913 31 0 0 +3914 31 1 1 +3915 31 1 0 +3916 30 0 1 +3917 30 0 0 +3918 30 1 1 +3919 30 1 0 diff --git a/Detectors/PHOS/base/files/Mod0RCU2.data b/Detectors/PHOS/base/files/Mod0RCU2.data new file mode 100644 index 0000000000000..21de94d7ace53 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod0RCU2.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 2 0 2 + 1 2 1 2 + 2 2 2 2 + 3 2 3 2 + 4 2 4 2 + 5 2 5 2 + 6 2 6 2 + 7 2 7 2 + 8 2 8 2 + 9 2 9 2 + 10 2 10 2 + 11 2 11 2 + 12 2 12 2 + 13 2 13 2 + 14 2 14 2 + 15 2 15 2 + 16 2 16 2 + 17 2 17 2 + 18 2 18 2 + 19 2 19 2 + 20 2 20 2 + 21 2 21 2 + 22 2 22 2 + 23 2 23 2 + 24 2 24 2 + 25 2 25 2 + 26 2 26 2 + 27 2 27 2 + 28 2 28 2 + 29 2 29 2 + 30 2 30 2 + 31 2 31 2 + 32 2 32 2 + 33 2 33 2 + 34 2 34 2 + 35 2 35 2 + 36 2 36 2 + 37 2 37 2 + 38 2 38 2 + 39 2 39 2 + 40 2 40 2 + 41 2 41 2 + 42 2 42 2 + 43 2 43 2 + 44 2 44 2 + 45 2 45 2 + 46 2 46 2 + 47 2 47 2 + 48 2 48 2 + 49 2 49 2 + 50 2 50 2 + 51 2 51 2 + 52 2 52 2 + 53 2 53 2 + 54 2 54 2 + 55 2 55 2 + 56 2 56 2 + 57 2 57 2 + 58 2 58 2 + 59 2 59 2 + 60 2 60 2 + 61 2 61 2 + 62 2 62 2 + 63 2 63 2 + 64 2 64 2 + 65 2 65 2 + 66 2 66 2 + 67 2 67 2 + 68 2 68 2 + 69 2 69 2 + 70 2 70 2 + 71 2 71 2 + 72 2 72 2 + 73 2 73 2 + 74 2 74 2 + 75 2 75 2 + 76 2 76 2 + 77 2 77 2 + 78 2 78 2 + 79 2 79 2 + 80 2 80 2 + 81 2 81 2 + 82 2 82 2 + 83 2 83 2 + 84 2 84 2 + 85 2 85 2 + 86 2 86 2 + 87 2 87 2 + 88 2 88 2 + 89 2 89 2 + 90 2 90 2 + 91 2 91 2 + 92 2 92 2 + 93 2 93 2 + 94 2 94 2 + 95 2 95 2 + 96 2 96 2 + 97 2 97 2 + 98 2 98 2 + 99 2 99 2 + 100 2 100 2 + 101 2 101 2 + 102 2 102 2 + 103 2 103 2 + 104 2 104 2 + 105 2 105 2 + 106 2 106 2 + 107 2 107 2 + 108 2 108 2 + 109 2 109 2 + 110 2 110 2 + 111 2 111 2 + 112 2 112 2 + 113 2 113 2 + 114 2 114 2 + 115 2 115 2 + 116 2 116 2 + 117 2 117 2 + 118 2 118 2 + 119 2 119 2 + 120 2 120 2 + 121 2 121 2 + 122 2 122 2 + 123 2 123 2 + 124 2 124 2 + 125 2 125 2 + 126 2 126 2 + 127 2 127 2 +2048 2 2048 2 +2049 2 2049 2 +2050 2 2050 2 +2051 2 2051 2 +2052 2 2052 2 +2053 2 2053 2 +2054 2 2054 2 +2055 2 2055 2 +2056 2 2056 2 +2057 2 2057 2 +2058 2 2058 2 +2059 2 2059 2 +2060 2 2060 2 +2061 2 2061 2 +2062 2 2062 2 +2063 2 2063 2 +2064 2 2064 2 +2065 2 2065 2 +2066 2 2066 2 +2067 2 2067 2 +2068 2 2068 2 +2069 2 2069 2 +2070 2 2070 2 +2071 2 2071 2 +2072 2 2072 2 +2073 2 2073 2 +2074 2 2074 2 +2075 2 2075 2 +2076 2 2076 2 +2077 2 2077 2 +2078 2 2078 2 +2079 2 2079 2 +2080 2 2080 2 +2081 2 2081 2 +2082 2 2082 2 +2083 2 2083 2 +2084 2 2084 2 +2085 2 2085 2 +2086 2 2086 2 +2087 2 2087 2 +2088 2 2088 2 +2089 2 2089 2 +2090 2 2090 2 +2091 2 2091 2 +2092 2 2092 2 +2093 2 2093 2 +2094 2 2094 2 +2095 2 2095 2 +2096 2 2096 2 +2097 2 2097 2 +2098 2 2098 2 +2099 2 2099 2 +2100 2 2100 2 +2101 2 2101 2 +2102 2 2102 2 +2103 2 2103 2 +2104 2 2104 2 +2105 2 2105 2 +2106 2 2106 2 +2107 2 2107 2 +2108 2 2108 2 +2109 2 2109 2 +2110 2 2110 2 +2111 2 2111 2 +2112 2 2112 2 +2113 2 2113 2 +2114 2 2114 2 +2115 2 2115 2 +2116 2 2116 2 +2117 2 2117 2 +2118 2 2118 2 +2119 2 2119 2 +2120 2 2120 2 +2121 2 2121 2 +2122 2 2122 2 +2123 2 2123 2 +2124 2 2124 2 +2125 2 2125 2 +2126 2 2126 2 +2127 2 2127 2 +2128 2 2128 2 +2129 2 2129 2 +2130 2 2130 2 +2131 2 2131 2 +2132 2 2132 2 +2133 2 2133 2 +2134 2 2134 2 +2135 2 2135 2 +2136 2 2136 2 +2137 2 2137 2 +2138 2 2138 2 +2139 2 2139 2 +2140 2 2140 2 +2141 2 2141 2 +2142 2 2142 2 +2143 2 2143 2 +2144 2 2144 2 +2145 2 2145 2 +2146 2 2146 2 +2147 2 2147 2 +2148 2 2148 2 +2149 2 2149 2 +2150 2 2150 2 +2151 2 2151 2 +2152 2 2152 2 +2153 2 2153 2 +2154 2 2154 2 +2155 2 2155 2 +2156 2 2156 2 +2157 2 2157 2 +2158 2 2158 2 +2159 2 2159 2 +2160 2 2160 2 +2161 2 2161 2 +2162 2 2162 2 +2163 2 2163 2 +2164 2 2164 2 +2165 2 2165 2 +2166 2 2166 2 +2167 2 2167 2 +2168 2 2168 2 +2169 2 2169 2 +2170 2 2170 2 +2171 2 2171 2 +2172 2 2172 2 +2173 2 2173 2 +2174 2 2174 2 +2175 2 2175 2 + 128 43 29 0 + 129 43 29 1 + 130 43 28 0 + 131 43 28 1 + 132 42 29 0 + 133 42 29 1 + 134 42 28 0 + 135 42 28 1 + 136 40 28 1 + 137 40 28 0 + 138 40 29 1 + 139 40 29 0 + 140 41 28 1 + 141 41 28 0 + 142 41 29 1 + 143 41 29 0 + 160 35 28 0 + 161 35 28 1 + 162 35 29 0 + 163 35 29 1 + 164 34 28 0 + 165 34 28 1 + 166 34 29 0 + 167 34 29 1 + 168 32 29 1 + 169 32 29 0 + 170 32 28 1 + 171 32 28 0 + 172 33 29 1 + 173 33 29 0 + 174 33 28 1 + 175 33 28 0 + 176 36 28 0 + 177 36 28 1 + 178 36 29 0 + 179 36 29 1 + 180 37 28 0 + 181 37 28 1 + 182 37 29 0 + 183 37 29 1 + 184 39 29 1 + 185 39 29 0 + 186 39 28 1 + 187 39 28 0 + 188 38 29 1 + 189 38 29 0 + 190 38 28 1 + 191 38 28 0 + 192 44 29 0 + 193 44 29 1 + 194 44 28 0 + 195 44 28 1 + 196 45 29 0 + 197 45 29 1 + 198 45 28 0 + 199 45 28 1 + 200 47 28 1 + 201 47 28 0 + 202 47 29 1 + 203 47 29 0 + 204 46 28 1 + 205 46 28 0 + 206 46 29 1 + 207 46 29 0 + 256 43 31 0 + 257 43 31 1 + 258 43 30 0 + 259 43 30 1 + 260 42 31 0 + 261 42 31 1 + 262 42 30 0 + 263 42 30 1 + 264 40 30 1 + 265 40 30 0 + 266 40 31 1 + 267 40 31 0 + 268 41 30 1 + 269 41 30 0 + 270 41 31 1 + 271 41 31 0 + 288 35 30 0 + 289 35 30 1 + 290 35 31 0 + 291 35 31 1 + 292 34 30 0 + 293 34 30 1 + 294 34 31 0 + 295 34 31 1 + 296 32 31 1 + 297 32 31 0 + 298 32 30 1 + 299 32 30 0 + 300 33 31 1 + 301 33 31 0 + 302 33 30 1 + 303 33 30 0 + 304 36 30 0 + 305 36 30 1 + 306 36 31 0 + 307 36 31 1 + 308 37 30 0 + 309 37 30 1 + 310 37 31 0 + 311 37 31 1 + 312 39 31 1 + 313 39 31 0 + 314 39 30 1 + 315 39 30 0 + 316 38 31 1 + 317 38 31 0 + 318 38 30 1 + 319 38 30 0 + 320 44 31 0 + 321 44 31 1 + 322 44 30 0 + 323 44 30 1 + 324 45 31 0 + 325 45 31 1 + 326 45 30 0 + 327 45 30 1 + 328 47 30 1 + 329 47 30 0 + 330 47 31 1 + 331 47 31 0 + 332 46 30 1 + 333 46 30 0 + 334 46 31 1 + 335 46 31 0 + 384 43 33 0 + 385 43 33 1 + 386 43 32 0 + 387 43 32 1 + 388 42 33 0 + 389 42 33 1 + 390 42 32 0 + 391 42 32 1 + 392 40 32 1 + 393 40 32 0 + 394 40 33 1 + 395 40 33 0 + 396 41 32 1 + 397 41 32 0 + 398 41 33 1 + 399 41 33 0 + 416 35 32 0 + 417 35 32 1 + 418 35 33 0 + 419 35 33 1 + 420 34 32 0 + 421 34 32 1 + 422 34 33 0 + 423 34 33 1 + 424 32 33 1 + 425 32 33 0 + 426 32 32 1 + 427 32 32 0 + 428 33 33 1 + 429 33 33 0 + 430 33 32 1 + 431 33 32 0 + 432 36 32 0 + 433 36 32 1 + 434 36 33 0 + 435 36 33 1 + 436 37 32 0 + 437 37 32 1 + 438 37 33 0 + 439 37 33 1 + 440 39 33 1 + 441 39 33 0 + 442 39 32 1 + 443 39 32 0 + 444 38 33 1 + 445 38 33 0 + 446 38 32 1 + 447 38 32 0 + 448 44 33 0 + 449 44 33 1 + 450 44 32 0 + 451 44 32 1 + 452 45 33 0 + 453 45 33 1 + 454 45 32 0 + 455 45 32 1 + 456 47 32 1 + 457 47 32 0 + 458 47 33 1 + 459 47 33 0 + 460 46 32 1 + 461 46 32 0 + 462 46 33 1 + 463 46 33 0 + 512 43 35 0 + 513 43 35 1 + 514 43 34 0 + 515 43 34 1 + 516 42 35 0 + 517 42 35 1 + 518 42 34 0 + 519 42 34 1 + 520 40 34 1 + 521 40 34 0 + 522 40 35 1 + 523 40 35 0 + 524 41 34 1 + 525 41 34 0 + 526 41 35 1 + 527 41 35 0 + 544 35 34 0 + 545 35 34 1 + 546 35 35 0 + 547 35 35 1 + 548 34 34 0 + 549 34 34 1 + 550 34 35 0 + 551 34 35 1 + 552 32 35 1 + 553 32 35 0 + 554 32 34 1 + 555 32 34 0 + 556 33 35 1 + 557 33 35 0 + 558 33 34 1 + 559 33 34 0 + 560 36 34 0 + 561 36 34 1 + 562 36 35 0 + 563 36 35 1 + 564 37 34 0 + 565 37 34 1 + 566 37 35 0 + 567 37 35 1 + 568 39 35 1 + 569 39 35 0 + 570 39 34 1 + 571 39 34 0 + 572 38 35 1 + 573 38 35 0 + 574 38 34 1 + 575 38 34 0 + 576 44 35 0 + 577 44 35 1 + 578 44 34 0 + 579 44 34 1 + 580 45 35 0 + 581 45 35 1 + 582 45 34 0 + 583 45 34 1 + 584 47 34 1 + 585 47 34 0 + 586 47 35 1 + 587 47 35 0 + 588 46 34 1 + 589 46 34 0 + 590 46 35 1 + 591 46 35 0 + 640 43 37 0 + 641 43 37 1 + 642 43 36 0 + 643 43 36 1 + 644 42 37 0 + 645 42 37 1 + 646 42 36 0 + 647 42 36 1 + 648 40 36 1 + 649 40 36 0 + 650 40 37 1 + 651 40 37 0 + 652 41 36 1 + 653 41 36 0 + 654 41 37 1 + 655 41 37 0 + 672 35 36 0 + 673 35 36 1 + 674 35 37 0 + 675 35 37 1 + 676 34 36 0 + 677 34 36 1 + 678 34 37 0 + 679 34 37 1 + 680 32 37 1 + 681 32 37 0 + 682 32 36 1 + 683 32 36 0 + 684 33 37 1 + 685 33 37 0 + 686 33 36 1 + 687 33 36 0 + 688 36 36 0 + 689 36 36 1 + 690 36 37 0 + 691 36 37 1 + 692 37 36 0 + 693 37 36 1 + 694 37 37 0 + 695 37 37 1 + 696 39 37 1 + 697 39 37 0 + 698 39 36 1 + 699 39 36 0 + 700 38 37 1 + 701 38 37 0 + 702 38 36 1 + 703 38 36 0 + 704 44 37 0 + 705 44 37 1 + 706 44 36 0 + 707 44 36 1 + 708 45 37 0 + 709 45 37 1 + 710 45 36 0 + 711 45 36 1 + 712 47 36 1 + 713 47 36 0 + 714 47 37 1 + 715 47 37 0 + 716 46 36 1 + 717 46 36 0 + 718 46 37 1 + 719 46 37 0 + 768 43 39 0 + 769 43 39 1 + 770 43 38 0 + 771 43 38 1 + 772 42 39 0 + 773 42 39 1 + 774 42 38 0 + 775 42 38 1 + 776 40 38 1 + 777 40 38 0 + 778 40 39 1 + 779 40 39 0 + 780 41 38 1 + 781 41 38 0 + 782 41 39 1 + 783 41 39 0 + 800 35 38 0 + 801 35 38 1 + 802 35 39 0 + 803 35 39 1 + 804 34 38 0 + 805 34 38 1 + 806 34 39 0 + 807 34 39 1 + 808 32 39 1 + 809 32 39 0 + 810 32 38 1 + 811 32 38 0 + 812 33 39 1 + 813 33 39 0 + 814 33 38 1 + 815 33 38 0 + 816 36 38 0 + 817 36 38 1 + 818 36 39 0 + 819 36 39 1 + 820 37 38 0 + 821 37 38 1 + 822 37 39 0 + 823 37 39 1 + 824 39 39 1 + 825 39 39 0 + 826 39 38 1 + 827 39 38 0 + 828 38 39 1 + 829 38 39 0 + 830 38 38 1 + 831 38 38 0 + 832 44 39 0 + 833 44 39 1 + 834 44 38 0 + 835 44 38 1 + 836 45 39 0 + 837 45 39 1 + 838 45 38 0 + 839 45 38 1 + 840 47 38 1 + 841 47 38 0 + 842 47 39 1 + 843 47 39 0 + 844 46 38 1 + 845 46 38 0 + 846 46 39 1 + 847 46 39 0 + 896 43 41 0 + 897 43 41 1 + 898 43 40 0 + 899 43 40 1 + 900 42 41 0 + 901 42 41 1 + 902 42 40 0 + 903 42 40 1 + 904 40 40 1 + 905 40 40 0 + 906 40 41 1 + 907 40 41 0 + 908 41 40 1 + 909 41 40 0 + 910 41 41 1 + 911 41 41 0 + 928 35 40 0 + 929 35 40 1 + 930 35 41 0 + 931 35 41 1 + 932 34 40 0 + 933 34 40 1 + 934 34 41 0 + 935 34 41 1 + 936 32 41 1 + 937 32 41 0 + 938 32 40 1 + 939 32 40 0 + 940 33 41 1 + 941 33 41 0 + 942 33 40 1 + 943 33 40 0 + 944 36 40 0 + 945 36 40 1 + 946 36 41 0 + 947 36 41 1 + 948 37 40 0 + 949 37 40 1 + 950 37 41 0 + 951 37 41 1 + 952 39 41 1 + 953 39 41 0 + 954 39 40 1 + 955 39 40 0 + 956 38 41 1 + 957 38 41 0 + 958 38 40 1 + 959 38 40 0 + 960 44 41 0 + 961 44 41 1 + 962 44 40 0 + 963 44 40 1 + 964 45 41 0 + 965 45 41 1 + 966 45 40 0 + 967 45 40 1 + 968 47 40 1 + 969 47 40 0 + 970 47 41 1 + 971 47 41 0 + 972 46 40 1 + 973 46 40 0 + 974 46 41 1 + 975 46 41 0 +1024 43 43 0 +1025 43 43 1 +1026 43 42 0 +1027 43 42 1 +1028 42 43 0 +1029 42 43 1 +1030 42 42 0 +1031 42 42 1 +1032 40 42 1 +1033 40 42 0 +1034 40 43 1 +1035 40 43 0 +1036 41 42 1 +1037 41 42 0 +1038 41 43 1 +1039 41 43 0 +1056 35 42 0 +1057 35 42 1 +1058 35 43 0 +1059 35 43 1 +1060 34 42 0 +1061 34 42 1 +1062 34 43 0 +1063 34 43 1 +1064 32 43 1 +1065 32 43 0 +1066 32 42 1 +1067 32 42 0 +1068 33 43 1 +1069 33 43 0 +1070 33 42 1 +1071 33 42 0 +1072 36 42 0 +1073 36 42 1 +1074 36 43 0 +1075 36 43 1 +1076 37 42 0 +1077 37 42 1 +1078 37 43 0 +1079 37 43 1 +1080 39 43 1 +1081 39 43 0 +1082 39 42 1 +1083 39 42 0 +1084 38 43 1 +1085 38 43 0 +1086 38 42 1 +1087 38 42 0 +1088 44 43 0 +1089 44 43 1 +1090 44 42 0 +1091 44 42 1 +1092 45 43 0 +1093 45 43 1 +1094 45 42 0 +1095 45 42 1 +1096 47 42 1 +1097 47 42 0 +1098 47 43 1 +1099 47 43 0 +1100 46 42 1 +1101 46 42 0 +1102 46 43 1 +1103 46 43 0 +1152 43 45 0 +1153 43 45 1 +1154 43 44 0 +1155 43 44 1 +1156 42 45 0 +1157 42 45 1 +1158 42 44 0 +1159 42 44 1 +1160 40 44 1 +1161 40 44 0 +1162 40 45 1 +1163 40 45 0 +1164 41 44 1 +1165 41 44 0 +1166 41 45 1 +1167 41 45 0 +1184 35 44 0 +1185 35 44 1 +1186 35 45 0 +1187 35 45 1 +1188 34 44 0 +1189 34 44 1 +1190 34 45 0 +1191 34 45 1 +1192 32 45 1 +1193 32 45 0 +1194 32 44 1 +1195 32 44 0 +1196 33 45 1 +1197 33 45 0 +1198 33 44 1 +1199 33 44 0 +1200 36 44 0 +1201 36 44 1 +1202 36 45 0 +1203 36 45 1 +1204 37 44 0 +1205 37 44 1 +1206 37 45 0 +1207 37 45 1 +1208 39 45 1 +1209 39 45 0 +1210 39 44 1 +1211 39 44 0 +1212 38 45 1 +1213 38 45 0 +1214 38 44 1 +1215 38 44 0 +1216 44 45 0 +1217 44 45 1 +1218 44 44 0 +1219 44 44 1 +1220 45 45 0 +1221 45 45 1 +1222 45 44 0 +1223 45 44 1 +1224 47 44 1 +1225 47 44 0 +1226 47 45 1 +1227 47 45 0 +1228 46 44 1 +1229 46 44 0 +1230 46 45 1 +1231 46 45 0 +1280 43 47 0 +1281 43 47 1 +1282 43 46 0 +1283 43 46 1 +1284 42 47 0 +1285 42 47 1 +1286 42 46 0 +1287 42 46 1 +1288 40 46 1 +1289 40 46 0 +1290 40 47 1 +1291 40 47 0 +1292 41 46 1 +1293 41 46 0 +1294 41 47 1 +1295 41 47 0 +1312 35 46 0 +1313 35 46 1 +1314 35 47 0 +1315 35 47 1 +1316 34 46 0 +1317 34 46 1 +1318 34 47 0 +1319 34 47 1 +1320 32 47 1 +1321 32 47 0 +1322 32 46 1 +1323 32 46 0 +1324 33 47 1 +1325 33 47 0 +1326 33 46 1 +1327 33 46 0 +1328 36 46 0 +1329 36 46 1 +1330 36 47 0 +1331 36 47 1 +1332 37 46 0 +1333 37 46 1 +1334 37 47 0 +1335 37 47 1 +1336 39 47 1 +1337 39 47 0 +1338 39 46 1 +1339 39 46 0 +1340 38 47 1 +1341 38 47 0 +1342 38 46 1 +1343 38 46 0 +1344 44 47 0 +1345 44 47 1 +1346 44 46 0 +1347 44 46 1 +1348 45 47 0 +1349 45 47 1 +1350 45 46 0 +1351 45 46 1 +1352 47 46 1 +1353 47 46 0 +1354 47 47 1 +1355 47 47 0 +1356 46 46 1 +1357 46 46 0 +1358 46 47 1 +1359 46 47 0 +1408 43 49 0 +1409 43 49 1 +1410 43 48 0 +1411 43 48 1 +1412 42 49 0 +1413 42 49 1 +1414 42 48 0 +1415 42 48 1 +1416 40 48 1 +1417 40 48 0 +1418 40 49 1 +1419 40 49 0 +1420 41 48 1 +1421 41 48 0 +1422 41 49 1 +1423 41 49 0 +1440 35 48 0 +1441 35 48 1 +1442 35 49 0 +1443 35 49 1 +1444 34 48 0 +1445 34 48 1 +1446 34 49 0 +1447 34 49 1 +1448 32 49 1 +1449 32 49 0 +1450 32 48 1 +1451 32 48 0 +1452 33 49 1 +1453 33 49 0 +1454 33 48 1 +1455 33 48 0 +1456 36 48 0 +1457 36 48 1 +1458 36 49 0 +1459 36 49 1 +1460 37 48 0 +1461 37 48 1 +1462 37 49 0 +1463 37 49 1 +1464 39 49 1 +1465 39 49 0 +1466 39 48 1 +1467 39 48 0 +1468 38 49 1 +1469 38 49 0 +1470 38 48 1 +1471 38 48 0 +1472 44 49 0 +1473 44 49 1 +1474 44 48 0 +1475 44 48 1 +1476 45 49 0 +1477 45 49 1 +1478 45 48 0 +1479 45 48 1 +1480 47 48 1 +1481 47 48 0 +1482 47 49 1 +1483 47 49 0 +1484 46 48 1 +1485 46 48 0 +1486 46 49 1 +1487 46 49 0 +1536 43 51 0 +1537 43 51 1 +1538 43 50 0 +1539 43 50 1 +1540 42 51 0 +1541 42 51 1 +1542 42 50 0 +1543 42 50 1 +1544 40 50 1 +1545 40 50 0 +1546 40 51 1 +1547 40 51 0 +1548 41 50 1 +1549 41 50 0 +1550 41 51 1 +1551 41 51 0 +1568 35 50 0 +1569 35 50 1 +1570 35 51 0 +1571 35 51 1 +1572 34 50 0 +1573 34 50 1 +1574 34 51 0 +1575 34 51 1 +1576 32 51 1 +1577 32 51 0 +1578 32 50 1 +1579 32 50 0 +1580 33 51 1 +1581 33 51 0 +1582 33 50 1 +1583 33 50 0 +1584 36 50 0 +1585 36 50 1 +1586 36 51 0 +1587 36 51 1 +1588 37 50 0 +1589 37 50 1 +1590 37 51 0 +1591 37 51 1 +1592 39 51 1 +1593 39 51 0 +1594 39 50 1 +1595 39 50 0 +1596 38 51 1 +1597 38 51 0 +1598 38 50 1 +1599 38 50 0 +1600 44 51 0 +1601 44 51 1 +1602 44 50 0 +1603 44 50 1 +1604 45 51 0 +1605 45 51 1 +1606 45 50 0 +1607 45 50 1 +1608 47 50 1 +1609 47 50 0 +1610 47 51 1 +1611 47 51 0 +1612 46 50 1 +1613 46 50 0 +1614 46 51 1 +1615 46 51 0 +1664 43 53 0 +1665 43 53 1 +1666 43 52 0 +1667 43 52 1 +1668 42 53 0 +1669 42 53 1 +1670 42 52 0 +1671 42 52 1 +1672 40 52 1 +1673 40 52 0 +1674 40 53 1 +1675 40 53 0 +1676 41 52 1 +1677 41 52 0 +1678 41 53 1 +1679 41 53 0 +1696 35 52 0 +1697 35 52 1 +1698 35 53 0 +1699 35 53 1 +1700 34 52 0 +1701 34 52 1 +1702 34 53 0 +1703 34 53 1 +1704 32 53 1 +1705 32 53 0 +1706 32 52 1 +1707 32 52 0 +1708 33 53 1 +1709 33 53 0 +1710 33 52 1 +1711 33 52 0 +1712 36 52 0 +1713 36 52 1 +1714 36 53 0 +1715 36 53 1 +1716 37 52 0 +1717 37 52 1 +1718 37 53 0 +1719 37 53 1 +1720 39 53 1 +1721 39 53 0 +1722 39 52 1 +1723 39 52 0 +1724 38 53 1 +1725 38 53 0 +1726 38 52 1 +1727 38 52 0 +1728 44 53 0 +1729 44 53 1 +1730 44 52 0 +1731 44 52 1 +1732 45 53 0 +1733 45 53 1 +1734 45 52 0 +1735 45 52 1 +1736 47 52 1 +1737 47 52 0 +1738 47 53 1 +1739 47 53 0 +1740 46 52 1 +1741 46 52 0 +1742 46 53 1 +1743 46 53 0 +1792 43 55 0 +1793 43 55 1 +1794 43 54 0 +1795 43 54 1 +1796 42 55 0 +1797 42 55 1 +1798 42 54 0 +1799 42 54 1 +1800 40 54 1 +1801 40 54 0 +1802 40 55 1 +1803 40 55 0 +1804 41 54 1 +1805 41 54 0 +1806 41 55 1 +1807 41 55 0 +1824 35 54 0 +1825 35 54 1 +1826 35 55 0 +1827 35 55 1 +1828 34 54 0 +1829 34 54 1 +1830 34 55 0 +1831 34 55 1 +1832 32 55 1 +1833 32 55 0 +1834 32 54 1 +1835 32 54 0 +1836 33 55 1 +1837 33 55 0 +1838 33 54 1 +1839 33 54 0 +1840 36 54 0 +1841 36 54 1 +1842 36 55 0 +1843 36 55 1 +1844 37 54 0 +1845 37 54 1 +1846 37 55 0 +1847 37 55 1 +1848 39 55 1 +1849 39 55 0 +1850 39 54 1 +1851 39 54 0 +1852 38 55 1 +1853 38 55 0 +1854 38 54 1 +1855 38 54 0 +1856 44 55 0 +1857 44 55 1 +1858 44 54 0 +1859 44 54 1 +1860 45 55 0 +1861 45 55 1 +1862 45 54 0 +1863 45 54 1 +1864 47 54 1 +1865 47 54 0 +1866 47 55 1 +1867 47 55 0 +1868 46 54 1 +1869 46 54 0 +1870 46 55 1 +1871 46 55 0 +2176 43 27 0 +2177 43 27 1 +2178 43 26 0 +2179 43 26 1 +2180 42 27 0 +2181 42 27 1 +2182 42 26 0 +2183 42 26 1 +2184 40 26 1 +2185 40 26 0 +2186 40 27 1 +2187 40 27 0 +2188 41 26 1 +2189 41 26 0 +2190 41 27 1 +2191 41 27 0 +2208 35 26 0 +2209 35 26 1 +2210 35 27 0 +2211 35 27 1 +2212 34 26 0 +2213 34 26 1 +2214 34 27 0 +2215 34 27 1 +2216 32 27 1 +2217 32 27 0 +2218 32 26 1 +2219 32 26 0 +2220 33 27 1 +2221 33 27 0 +2222 33 26 1 +2223 33 26 0 +2224 36 26 0 +2225 36 26 1 +2226 36 27 0 +2227 36 27 1 +2228 37 26 0 +2229 37 26 1 +2230 37 27 0 +2231 37 27 1 +2232 39 27 1 +2233 39 27 0 +2234 39 26 1 +2235 39 26 0 +2236 38 27 1 +2237 38 27 0 +2238 38 26 1 +2239 38 26 0 +2240 44 27 0 +2241 44 27 1 +2242 44 26 0 +2243 44 26 1 +2244 45 27 0 +2245 45 27 1 +2246 45 26 0 +2247 45 26 1 +2248 47 26 1 +2249 47 26 0 +2250 47 27 1 +2251 47 27 0 +2252 46 26 1 +2253 46 26 0 +2254 46 27 1 +2255 46 27 0 +2304 43 25 0 +2305 43 25 1 +2306 43 24 0 +2307 43 24 1 +2308 42 25 0 +2309 42 25 1 +2310 42 24 0 +2311 42 24 1 +2312 40 24 1 +2313 40 24 0 +2314 40 25 1 +2315 40 25 0 +2316 41 24 1 +2317 41 24 0 +2318 41 25 1 +2319 41 25 0 +2336 35 24 0 +2337 35 24 1 +2338 35 25 0 +2339 35 25 1 +2340 34 24 0 +2341 34 24 1 +2342 34 25 0 +2343 34 25 1 +2344 32 25 1 +2345 32 25 0 +2346 32 24 1 +2347 32 24 0 +2348 33 25 1 +2349 33 25 0 +2350 33 24 1 +2351 33 24 0 +2352 36 24 0 +2353 36 24 1 +2354 36 25 0 +2355 36 25 1 +2356 37 24 0 +2357 37 24 1 +2358 37 25 0 +2359 37 25 1 +2360 39 25 1 +2361 39 25 0 +2362 39 24 1 +2363 39 24 0 +2364 38 25 1 +2365 38 25 0 +2366 38 24 1 +2367 38 24 0 +2368 44 25 0 +2369 44 25 1 +2370 44 24 0 +2371 44 24 1 +2372 45 25 0 +2373 45 25 1 +2374 45 24 0 +2375 45 24 1 +2376 47 24 1 +2377 47 24 0 +2378 47 25 1 +2379 47 25 0 +2380 46 24 1 +2381 46 24 0 +2382 46 25 1 +2383 46 25 0 +2432 43 23 0 +2433 43 23 1 +2434 43 22 0 +2435 43 22 1 +2436 42 23 0 +2437 42 23 1 +2438 42 22 0 +2439 42 22 1 +2440 40 22 1 +2441 40 22 0 +2442 40 23 1 +2443 40 23 0 +2444 41 22 1 +2445 41 22 0 +2446 41 23 1 +2447 41 23 0 +2464 35 22 0 +2465 35 22 1 +2466 35 23 0 +2467 35 23 1 +2468 34 22 0 +2469 34 22 1 +2470 34 23 0 +2471 34 23 1 +2472 32 23 1 +2473 32 23 0 +2474 32 22 1 +2475 32 22 0 +2476 33 23 1 +2477 33 23 0 +2478 33 22 1 +2479 33 22 0 +2480 36 22 0 +2481 36 22 1 +2482 36 23 0 +2483 36 23 1 +2484 37 22 0 +2485 37 22 1 +2486 37 23 0 +2487 37 23 1 +2488 39 23 1 +2489 39 23 0 +2490 39 22 1 +2491 39 22 0 +2492 38 23 1 +2493 38 23 0 +2494 38 22 1 +2495 38 22 0 +2496 44 23 0 +2497 44 23 1 +2498 44 22 0 +2499 44 22 1 +2500 45 23 0 +2501 45 23 1 +2502 45 22 0 +2503 45 22 1 +2504 47 22 1 +2505 47 22 0 +2506 47 23 1 +2507 47 23 0 +2508 46 22 1 +2509 46 22 0 +2510 46 23 1 +2511 46 23 0 +2560 43 21 0 +2561 43 21 1 +2562 43 20 0 +2563 43 20 1 +2564 42 21 0 +2565 42 21 1 +2566 42 20 0 +2567 42 20 1 +2568 40 20 1 +2569 40 20 0 +2570 40 21 1 +2571 40 21 0 +2572 41 20 1 +2573 41 20 0 +2574 41 21 1 +2575 41 21 0 +2592 35 20 0 +2593 35 20 1 +2594 35 21 0 +2595 35 21 1 +2596 34 20 0 +2597 34 20 1 +2598 34 21 0 +2599 34 21 1 +2600 32 21 1 +2601 32 21 0 +2602 32 20 1 +2603 32 20 0 +2604 33 21 1 +2605 33 21 0 +2606 33 20 1 +2607 33 20 0 +2608 36 20 0 +2609 36 20 1 +2610 36 21 0 +2611 36 21 1 +2612 37 20 0 +2613 37 20 1 +2614 37 21 0 +2615 37 21 1 +2616 39 21 1 +2617 39 21 0 +2618 39 20 1 +2619 39 20 0 +2620 38 21 1 +2621 38 21 0 +2622 38 20 1 +2623 38 20 0 +2624 44 21 0 +2625 44 21 1 +2626 44 20 0 +2627 44 20 1 +2628 45 21 0 +2629 45 21 1 +2630 45 20 0 +2631 45 20 1 +2632 47 20 1 +2633 47 20 0 +2634 47 21 1 +2635 47 21 0 +2636 46 20 1 +2637 46 20 0 +2638 46 21 1 +2639 46 21 0 +2688 43 19 0 +2689 43 19 1 +2690 43 18 0 +2691 43 18 1 +2692 42 19 0 +2693 42 19 1 +2694 42 18 0 +2695 42 18 1 +2696 40 18 1 +2697 40 18 0 +2698 40 19 1 +2699 40 19 0 +2700 41 18 1 +2701 41 18 0 +2702 41 19 1 +2703 41 19 0 +2720 35 18 0 +2721 35 18 1 +2722 35 19 0 +2723 35 19 1 +2724 34 18 0 +2725 34 18 1 +2726 34 19 0 +2727 34 19 1 +2728 32 19 1 +2729 32 19 0 +2730 32 18 1 +2731 32 18 0 +2732 33 19 1 +2733 33 19 0 +2734 33 18 1 +2735 33 18 0 +2736 36 18 0 +2737 36 18 1 +2738 36 19 0 +2739 36 19 1 +2740 37 18 0 +2741 37 18 1 +2742 37 19 0 +2743 37 19 1 +2744 39 19 1 +2745 39 19 0 +2746 39 18 1 +2747 39 18 0 +2748 38 19 1 +2749 38 19 0 +2750 38 18 1 +2751 38 18 0 +2752 44 19 0 +2753 44 19 1 +2754 44 18 0 +2755 44 18 1 +2756 45 19 0 +2757 45 19 1 +2758 45 18 0 +2759 45 18 1 +2760 47 18 1 +2761 47 18 0 +2762 47 19 1 +2763 47 19 0 +2764 46 18 1 +2765 46 18 0 +2766 46 19 1 +2767 46 19 0 +2816 43 17 0 +2817 43 17 1 +2818 43 16 0 +2819 43 16 1 +2820 42 17 0 +2821 42 17 1 +2822 42 16 0 +2823 42 16 1 +2824 40 16 1 +2825 40 16 0 +2826 40 17 1 +2827 40 17 0 +2828 41 16 1 +2829 41 16 0 +2830 41 17 1 +2831 41 17 0 +2848 35 16 0 +2849 35 16 1 +2850 35 17 0 +2851 35 17 1 +2852 34 16 0 +2853 34 16 1 +2854 34 17 0 +2855 34 17 1 +2856 32 17 1 +2857 32 17 0 +2858 32 16 1 +2859 32 16 0 +2860 33 17 1 +2861 33 17 0 +2862 33 16 1 +2863 33 16 0 +2864 36 16 0 +2865 36 16 1 +2866 36 17 0 +2867 36 17 1 +2868 37 16 0 +2869 37 16 1 +2870 37 17 0 +2871 37 17 1 +2872 39 17 1 +2873 39 17 0 +2874 39 16 1 +2875 39 16 0 +2876 38 17 1 +2877 38 17 0 +2878 38 16 1 +2879 38 16 0 +2880 44 17 0 +2881 44 17 1 +2882 44 16 0 +2883 44 16 1 +2884 45 17 0 +2885 45 17 1 +2886 45 16 0 +2887 45 16 1 +2888 47 16 1 +2889 47 16 0 +2890 47 17 1 +2891 47 17 0 +2892 46 16 1 +2893 46 16 0 +2894 46 17 1 +2895 46 17 0 +2944 43 15 0 +2945 43 15 1 +2946 43 14 0 +2947 43 14 1 +2948 42 15 0 +2949 42 15 1 +2950 42 14 0 +2951 42 14 1 +2952 40 14 1 +2953 40 14 0 +2954 40 15 1 +2955 40 15 0 +2956 41 14 1 +2957 41 14 0 +2958 41 15 1 +2959 41 15 0 +2976 35 14 0 +2977 35 14 1 +2978 35 15 0 +2979 35 15 1 +2980 34 14 0 +2981 34 14 1 +2982 34 15 0 +2983 34 15 1 +2984 32 15 1 +2985 32 15 0 +2986 32 14 1 +2987 32 14 0 +2988 33 15 1 +2989 33 15 0 +2990 33 14 1 +2991 33 14 0 +2992 36 14 0 +2993 36 14 1 +2994 36 15 0 +2995 36 15 1 +2996 37 14 0 +2997 37 14 1 +2998 37 15 0 +2999 37 15 1 +3000 39 15 1 +3001 39 15 0 +3002 39 14 1 +3003 39 14 0 +3004 38 15 1 +3005 38 15 0 +3006 38 14 1 +3007 38 14 0 +3008 44 15 0 +3009 44 15 1 +3010 44 14 0 +3011 44 14 1 +3012 45 15 0 +3013 45 15 1 +3014 45 14 0 +3015 45 14 1 +3016 47 14 1 +3017 47 14 0 +3018 47 15 1 +3019 47 15 0 +3020 46 14 1 +3021 46 14 0 +3022 46 15 1 +3023 46 15 0 +3072 43 13 0 +3073 43 13 1 +3074 43 12 0 +3075 43 12 1 +3076 42 13 0 +3077 42 13 1 +3078 42 12 0 +3079 42 12 1 +3080 40 12 1 +3081 40 12 0 +3082 40 13 1 +3083 40 13 0 +3084 41 12 1 +3085 41 12 0 +3086 41 13 1 +3087 41 13 0 +3104 35 12 0 +3105 35 12 1 +3106 35 13 0 +3107 35 13 1 +3108 34 12 0 +3109 34 12 1 +3110 34 13 0 +3111 34 13 1 +3112 32 13 1 +3113 32 13 0 +3114 32 12 1 +3115 32 12 0 +3116 33 13 1 +3117 33 13 0 +3118 33 12 1 +3119 33 12 0 +3120 36 12 0 +3121 36 12 1 +3122 36 13 0 +3123 36 13 1 +3124 37 12 0 +3125 37 12 1 +3126 37 13 0 +3127 37 13 1 +3128 39 13 1 +3129 39 13 0 +3130 39 12 1 +3131 39 12 0 +3132 38 13 1 +3133 38 13 0 +3134 38 12 1 +3135 38 12 0 +3136 44 13 0 +3137 44 13 1 +3138 44 12 0 +3139 44 12 1 +3140 45 13 0 +3141 45 13 1 +3142 45 12 0 +3143 45 12 1 +3144 47 12 1 +3145 47 12 0 +3146 47 13 1 +3147 47 13 0 +3148 46 12 1 +3149 46 12 0 +3150 46 13 1 +3151 46 13 0 +3200 43 11 0 +3201 43 11 1 +3202 43 10 0 +3203 43 10 1 +3204 42 11 0 +3205 42 11 1 +3206 42 10 0 +3207 42 10 1 +3208 40 10 1 +3209 40 10 0 +3210 40 11 1 +3211 40 11 0 +3212 41 10 1 +3213 41 10 0 +3214 41 11 1 +3215 41 11 0 +3232 35 10 0 +3233 35 10 1 +3234 35 11 0 +3235 35 11 1 +3236 34 10 0 +3237 34 10 1 +3238 34 11 0 +3239 34 11 1 +3240 32 11 1 +3241 32 11 0 +3242 32 10 1 +3243 32 10 0 +3244 33 11 1 +3245 33 11 0 +3246 33 10 1 +3247 33 10 0 +3248 36 10 0 +3249 36 10 1 +3250 36 11 0 +3251 36 11 1 +3252 37 10 0 +3253 37 10 1 +3254 37 11 0 +3255 37 11 1 +3256 39 11 1 +3257 39 11 0 +3258 39 10 1 +3259 39 10 0 +3260 38 11 1 +3261 38 11 0 +3262 38 10 1 +3263 38 10 0 +3264 44 11 0 +3265 44 11 1 +3266 44 10 0 +3267 44 10 1 +3268 45 11 0 +3269 45 11 1 +3270 45 10 0 +3271 45 10 1 +3272 47 10 1 +3273 47 10 0 +3274 47 11 1 +3275 47 11 0 +3276 46 10 1 +3277 46 10 0 +3278 46 11 1 +3279 46 11 0 +3328 43 9 0 +3329 43 9 1 +3330 43 8 0 +3331 43 8 1 +3332 42 9 0 +3333 42 9 1 +3334 42 8 0 +3335 42 8 1 +3336 40 8 1 +3337 40 8 0 +3338 40 9 1 +3339 40 9 0 +3340 41 8 1 +3341 41 8 0 +3342 41 9 1 +3343 41 9 0 +3360 35 8 0 +3361 35 8 1 +3362 35 9 0 +3363 35 9 1 +3364 34 8 0 +3365 34 8 1 +3366 34 9 0 +3367 34 9 1 +3368 32 9 1 +3369 32 9 0 +3370 32 8 1 +3371 32 8 0 +3372 33 9 1 +3373 33 9 0 +3374 33 8 1 +3375 33 8 0 +3376 36 8 0 +3377 36 8 1 +3378 36 9 0 +3379 36 9 1 +3380 37 8 0 +3381 37 8 1 +3382 37 9 0 +3383 37 9 1 +3384 39 9 1 +3385 39 9 0 +3386 39 8 1 +3387 39 8 0 +3388 38 9 1 +3389 38 9 0 +3390 38 8 1 +3391 38 8 0 +3392 44 9 0 +3393 44 9 1 +3394 44 8 0 +3395 44 8 1 +3396 45 9 0 +3397 45 9 1 +3398 45 8 0 +3399 45 8 1 +3400 47 8 1 +3401 47 8 0 +3402 47 9 1 +3403 47 9 0 +3404 46 8 1 +3405 46 8 0 +3406 46 9 1 +3407 46 9 0 +3456 43 7 0 +3457 43 7 1 +3458 43 6 0 +3459 43 6 1 +3460 42 7 0 +3461 42 7 1 +3462 42 6 0 +3463 42 6 1 +3464 40 6 1 +3465 40 6 0 +3466 40 7 1 +3467 40 7 0 +3468 41 6 1 +3469 41 6 0 +3470 41 7 1 +3471 41 7 0 +3488 35 6 0 +3489 35 6 1 +3490 35 7 0 +3491 35 7 1 +3492 34 6 0 +3493 34 6 1 +3494 34 7 0 +3495 34 7 1 +3496 32 7 1 +3497 32 7 0 +3498 32 6 1 +3499 32 6 0 +3500 33 7 1 +3501 33 7 0 +3502 33 6 1 +3503 33 6 0 +3504 36 6 0 +3505 36 6 1 +3506 36 7 0 +3507 36 7 1 +3508 37 6 0 +3509 37 6 1 +3510 37 7 0 +3511 37 7 1 +3512 39 7 1 +3513 39 7 0 +3514 39 6 1 +3515 39 6 0 +3516 38 7 1 +3517 38 7 0 +3518 38 6 1 +3519 38 6 0 +3520 44 7 0 +3521 44 7 1 +3522 44 6 0 +3523 44 6 1 +3524 45 7 0 +3525 45 7 1 +3526 45 6 0 +3527 45 6 1 +3528 47 6 1 +3529 47 6 0 +3530 47 7 1 +3531 47 7 0 +3532 46 6 1 +3533 46 6 0 +3534 46 7 1 +3535 46 7 0 +3584 43 5 0 +3585 43 5 1 +3586 43 4 0 +3587 43 4 1 +3588 42 5 0 +3589 42 5 1 +3590 42 4 0 +3591 42 4 1 +3592 40 4 1 +3593 40 4 0 +3594 40 5 1 +3595 40 5 0 +3596 41 4 1 +3597 41 4 0 +3598 41 5 1 +3599 41 5 0 +3616 35 4 0 +3617 35 4 1 +3618 35 5 0 +3619 35 5 1 +3620 34 4 0 +3621 34 4 1 +3622 34 5 0 +3623 34 5 1 +3624 32 5 1 +3625 32 5 0 +3626 32 4 1 +3627 32 4 0 +3628 33 5 1 +3629 33 5 0 +3630 33 4 1 +3631 33 4 0 +3632 36 4 0 +3633 36 4 1 +3634 36 5 0 +3635 36 5 1 +3636 37 4 0 +3637 37 4 1 +3638 37 5 0 +3639 37 5 1 +3640 39 5 1 +3641 39 5 0 +3642 39 4 1 +3643 39 4 0 +3644 38 5 1 +3645 38 5 0 +3646 38 4 1 +3647 38 4 0 +3648 44 5 0 +3649 44 5 1 +3650 44 4 0 +3651 44 4 1 +3652 45 5 0 +3653 45 5 1 +3654 45 4 0 +3655 45 4 1 +3656 47 4 1 +3657 47 4 0 +3658 47 5 1 +3659 47 5 0 +3660 46 4 1 +3661 46 4 0 +3662 46 5 1 +3663 46 5 0 +3712 43 3 0 +3713 43 3 1 +3714 43 2 0 +3715 43 2 1 +3716 42 3 0 +3717 42 3 1 +3718 42 2 0 +3719 42 2 1 +3720 40 2 1 +3721 40 2 0 +3722 40 3 1 +3723 40 3 0 +3724 41 2 1 +3725 41 2 0 +3726 41 3 1 +3727 41 3 0 +3744 35 2 0 +3745 35 2 1 +3746 35 3 0 +3747 35 3 1 +3748 34 2 0 +3749 34 2 1 +3750 34 3 0 +3751 34 3 1 +3752 32 3 1 +3753 32 3 0 +3754 32 2 1 +3755 32 2 0 +3756 33 3 1 +3757 33 3 0 +3758 33 2 1 +3759 33 2 0 +3760 36 2 0 +3761 36 2 1 +3762 36 3 0 +3763 36 3 1 +3764 37 2 0 +3765 37 2 1 +3766 37 3 0 +3767 37 3 1 +3768 39 3 1 +3769 39 3 0 +3770 39 2 1 +3771 39 2 0 +3772 38 3 1 +3773 38 3 0 +3774 38 2 1 +3775 38 2 0 +3776 44 3 0 +3777 44 3 1 +3778 44 2 0 +3779 44 2 1 +3780 45 3 0 +3781 45 3 1 +3782 45 2 0 +3783 45 2 1 +3784 47 2 1 +3785 47 2 0 +3786 47 3 1 +3787 47 3 0 +3788 46 2 1 +3789 46 2 0 +3790 46 3 1 +3791 46 3 0 +3840 43 1 0 +3841 43 1 1 +3842 43 0 0 +3843 43 0 1 +3844 42 1 0 +3845 42 1 1 +3846 42 0 0 +3847 42 0 1 +3848 40 0 1 +3849 40 0 0 +3850 40 1 1 +3851 40 1 0 +3852 41 0 1 +3853 41 0 0 +3854 41 1 1 +3855 41 1 0 +3872 35 0 0 +3873 35 0 1 +3874 35 1 0 +3875 35 1 1 +3876 34 0 0 +3877 34 0 1 +3878 34 1 0 +3879 34 1 1 +3880 32 1 1 +3881 32 1 0 +3882 32 0 1 +3883 32 0 0 +3884 33 1 1 +3885 33 1 0 +3886 33 0 1 +3887 33 0 0 +3888 36 0 0 +3889 36 0 1 +3890 36 1 0 +3891 36 1 1 +3892 37 0 0 +3893 37 0 1 +3894 37 1 0 +3895 37 1 1 +3896 39 1 1 +3897 39 1 0 +3898 39 0 1 +3899 39 0 0 +3900 38 1 1 +3901 38 1 0 +3902 38 0 1 +3903 38 0 0 +3904 44 1 0 +3905 44 1 1 +3906 44 0 0 +3907 44 0 1 +3908 45 1 0 +3909 45 1 1 +3910 45 0 0 +3911 45 0 1 +3912 47 0 1 +3913 47 0 0 +3914 47 1 1 +3915 47 1 0 +3916 46 0 1 +3917 46 0 0 +3918 46 1 1 +3919 46 1 0 diff --git a/Detectors/PHOS/base/files/Mod0RCU3.data b/Detectors/PHOS/base/files/Mod0RCU3.data new file mode 100644 index 0000000000000..43bd76fc42791 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod0RCU3.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 3 0 2 + 1 3 1 2 + 2 3 2 2 + 3 3 3 2 + 4 3 4 2 + 5 3 5 2 + 6 3 6 2 + 7 3 7 2 + 8 3 8 2 + 9 3 9 2 + 10 3 10 2 + 11 3 11 2 + 12 3 12 2 + 13 3 13 2 + 14 3 14 2 + 15 3 15 2 + 16 3 16 2 + 17 3 17 2 + 18 3 18 2 + 19 3 19 2 + 20 3 20 2 + 21 3 21 2 + 22 3 22 2 + 23 3 23 2 + 24 3 24 2 + 25 3 25 2 + 26 3 26 2 + 27 3 27 2 + 28 3 28 2 + 29 3 29 2 + 30 3 30 2 + 31 3 31 2 + 32 3 32 2 + 33 3 33 2 + 34 3 34 2 + 35 3 35 2 + 36 3 36 2 + 37 3 37 2 + 38 3 38 2 + 39 3 39 2 + 40 3 40 2 + 41 3 41 2 + 42 3 42 2 + 43 3 43 2 + 44 3 44 2 + 45 3 45 2 + 46 3 46 2 + 47 3 47 2 + 48 3 48 2 + 49 3 49 2 + 50 3 50 2 + 51 3 51 2 + 52 3 52 2 + 53 3 53 2 + 54 3 54 2 + 55 3 55 2 + 56 3 56 2 + 57 3 57 2 + 58 3 58 2 + 59 3 59 2 + 60 3 60 2 + 61 3 61 2 + 62 3 62 2 + 63 3 63 2 + 64 3 64 2 + 65 3 65 2 + 66 3 66 2 + 67 3 67 2 + 68 3 68 2 + 69 3 69 2 + 70 3 70 2 + 71 3 71 2 + 72 3 72 2 + 73 3 73 2 + 74 3 74 2 + 75 3 75 2 + 76 3 76 2 + 77 3 77 2 + 78 3 78 2 + 79 3 79 2 + 80 3 80 2 + 81 3 81 2 + 82 3 82 2 + 83 3 83 2 + 84 3 84 2 + 85 3 85 2 + 86 3 86 2 + 87 3 87 2 + 88 3 88 2 + 89 3 89 2 + 90 3 90 2 + 91 3 91 2 + 92 3 92 2 + 93 3 93 2 + 94 3 94 2 + 95 3 95 2 + 96 3 96 2 + 97 3 97 2 + 98 3 98 2 + 99 3 99 2 + 100 3 100 2 + 101 3 101 2 + 102 3 102 2 + 103 3 103 2 + 104 3 104 2 + 105 3 105 2 + 106 3 106 2 + 107 3 107 2 + 108 3 108 2 + 109 3 109 2 + 110 3 110 2 + 111 3 111 2 + 112 3 112 2 + 113 3 113 2 + 114 3 114 2 + 115 3 115 2 + 116 3 116 2 + 117 3 117 2 + 118 3 118 2 + 119 3 119 2 + 120 3 120 2 + 121 3 121 2 + 122 3 122 2 + 123 3 123 2 + 124 3 124 2 + 125 3 125 2 + 126 3 126 2 + 127 3 127 2 +2048 3 2048 2 +2049 3 2049 2 +2050 3 2050 2 +2051 3 2051 2 +2052 3 2052 2 +2053 3 2053 2 +2054 3 2054 2 +2055 3 2055 2 +2056 3 2056 2 +2057 3 2057 2 +2058 3 2058 2 +2059 3 2059 2 +2060 3 2060 2 +2061 3 2061 2 +2062 3 2062 2 +2063 3 2063 2 +2064 3 2064 2 +2065 3 2065 2 +2066 3 2066 2 +2067 3 2067 2 +2068 3 2068 2 +2069 3 2069 2 +2070 3 2070 2 +2071 3 2071 2 +2072 3 2072 2 +2073 3 2073 2 +2074 3 2074 2 +2075 3 2075 2 +2076 3 2076 2 +2077 3 2077 2 +2078 3 2078 2 +2079 3 2079 2 +2080 3 2080 2 +2081 3 2081 2 +2082 3 2082 2 +2083 3 2083 2 +2084 3 2084 2 +2085 3 2085 2 +2086 3 2086 2 +2087 3 2087 2 +2088 3 2088 2 +2089 3 2089 2 +2090 3 2090 2 +2091 3 2091 2 +2092 3 2092 2 +2093 3 2093 2 +2094 3 2094 2 +2095 3 2095 2 +2096 3 2096 2 +2097 3 2097 2 +2098 3 2098 2 +2099 3 2099 2 +2100 3 2100 2 +2101 3 2101 2 +2102 3 2102 2 +2103 3 2103 2 +2104 3 2104 2 +2105 3 2105 2 +2106 3 2106 2 +2107 3 2107 2 +2108 3 2108 2 +2109 3 2109 2 +2110 3 2110 2 +2111 3 2111 2 +2112 3 2112 2 +2113 3 2113 2 +2114 3 2114 2 +2115 3 2115 2 +2116 3 2116 2 +2117 3 2117 2 +2118 3 2118 2 +2119 3 2119 2 +2120 3 2120 2 +2121 3 2121 2 +2122 3 2122 2 +2123 3 2123 2 +2124 3 2124 2 +2125 3 2125 2 +2126 3 2126 2 +2127 3 2127 2 +2128 3 2128 2 +2129 3 2129 2 +2130 3 2130 2 +2131 3 2131 2 +2132 3 2132 2 +2133 3 2133 2 +2134 3 2134 2 +2135 3 2135 2 +2136 3 2136 2 +2137 3 2137 2 +2138 3 2138 2 +2139 3 2139 2 +2140 3 2140 2 +2141 3 2141 2 +2142 3 2142 2 +2143 3 2143 2 +2144 3 2144 2 +2145 3 2145 2 +2146 3 2146 2 +2147 3 2147 2 +2148 3 2148 2 +2149 3 2149 2 +2150 3 2150 2 +2151 3 2151 2 +2152 3 2152 2 +2153 3 2153 2 +2154 3 2154 2 +2155 3 2155 2 +2156 3 2156 2 +2157 3 2157 2 +2158 3 2158 2 +2159 3 2159 2 +2160 3 2160 2 +2161 3 2161 2 +2162 3 2162 2 +2163 3 2163 2 +2164 3 2164 2 +2165 3 2165 2 +2166 3 2166 2 +2167 3 2167 2 +2168 3 2168 2 +2169 3 2169 2 +2170 3 2170 2 +2171 3 2171 2 +2172 3 2172 2 +2173 3 2173 2 +2174 3 2174 2 +2175 3 2175 2 + 128 59 29 0 + 129 59 29 1 + 130 59 28 0 + 131 59 28 1 + 132 58 29 0 + 133 58 29 1 + 134 58 28 0 + 135 58 28 1 + 136 56 28 1 + 137 56 28 0 + 138 56 29 1 + 139 56 29 0 + 140 57 28 1 + 141 57 28 0 + 142 57 29 1 + 143 57 29 0 + 160 51 28 0 + 161 51 28 1 + 162 51 29 0 + 163 51 29 1 + 164 50 28 0 + 165 50 28 1 + 166 50 29 0 + 167 50 29 1 + 168 48 29 1 + 169 48 29 0 + 170 48 28 1 + 171 48 28 0 + 172 49 29 1 + 173 49 29 0 + 174 49 28 1 + 175 49 28 0 + 176 52 28 0 + 177 52 28 1 + 178 52 29 0 + 179 52 29 1 + 180 53 28 0 + 181 53 28 1 + 182 53 29 0 + 183 53 29 1 + 184 55 29 1 + 185 55 29 0 + 186 55 28 1 + 187 55 28 0 + 188 54 29 1 + 189 54 29 0 + 190 54 28 1 + 191 54 28 0 + 192 60 29 0 + 193 60 29 1 + 194 60 28 0 + 195 60 28 1 + 196 61 29 0 + 197 61 29 1 + 198 61 28 0 + 199 61 28 1 + 200 63 28 1 + 201 63 28 0 + 202 63 29 1 + 203 63 29 0 + 204 62 28 1 + 205 62 28 0 + 206 62 29 1 + 207 62 29 0 + 256 59 31 0 + 257 59 31 1 + 258 59 30 0 + 259 59 30 1 + 260 58 31 0 + 261 58 31 1 + 262 58 30 0 + 263 58 30 1 + 264 56 30 1 + 265 56 30 0 + 266 56 31 1 + 267 56 31 0 + 268 57 30 1 + 269 57 30 0 + 270 57 31 1 + 271 57 31 0 + 288 51 30 0 + 289 51 30 1 + 290 51 31 0 + 291 51 31 1 + 292 50 30 0 + 293 50 30 1 + 294 50 31 0 + 295 50 31 1 + 296 48 31 1 + 297 48 31 0 + 298 48 30 1 + 299 48 30 0 + 300 49 31 1 + 301 49 31 0 + 302 49 30 1 + 303 49 30 0 + 304 52 30 0 + 305 52 30 1 + 306 52 31 0 + 307 52 31 1 + 308 53 30 0 + 309 53 30 1 + 310 53 31 0 + 311 53 31 1 + 312 55 31 1 + 313 55 31 0 + 314 55 30 1 + 315 55 30 0 + 316 54 31 1 + 317 54 31 0 + 318 54 30 1 + 319 54 30 0 + 320 60 31 0 + 321 60 31 1 + 322 60 30 0 + 323 60 30 1 + 324 61 31 0 + 325 61 31 1 + 326 61 30 0 + 327 61 30 1 + 328 63 30 1 + 329 63 30 0 + 330 63 31 1 + 331 63 31 0 + 332 62 30 1 + 333 62 30 0 + 334 62 31 1 + 335 62 31 0 + 384 59 33 0 + 385 59 33 1 + 386 59 32 0 + 387 59 32 1 + 388 58 33 0 + 389 58 33 1 + 390 58 32 0 + 391 58 32 1 + 392 56 32 1 + 393 56 32 0 + 394 56 33 1 + 395 56 33 0 + 396 57 32 1 + 397 57 32 0 + 398 57 33 1 + 399 57 33 0 + 416 51 32 0 + 417 51 32 1 + 418 51 33 0 + 419 51 33 1 + 420 50 32 0 + 421 50 32 1 + 422 50 33 0 + 423 50 33 1 + 424 48 33 1 + 425 48 33 0 + 426 48 32 1 + 427 48 32 0 + 428 49 33 1 + 429 49 33 0 + 430 49 32 1 + 431 49 32 0 + 432 52 32 0 + 433 52 32 1 + 434 52 33 0 + 435 52 33 1 + 436 53 32 0 + 437 53 32 1 + 438 53 33 0 + 439 53 33 1 + 440 55 33 1 + 441 55 33 0 + 442 55 32 1 + 443 55 32 0 + 444 54 33 1 + 445 54 33 0 + 446 54 32 1 + 447 54 32 0 + 448 60 33 0 + 449 60 33 1 + 450 60 32 0 + 451 60 32 1 + 452 61 33 0 + 453 61 33 1 + 454 61 32 0 + 455 61 32 1 + 456 63 32 1 + 457 63 32 0 + 458 63 33 1 + 459 63 33 0 + 460 62 32 1 + 461 62 32 0 + 462 62 33 1 + 463 62 33 0 + 512 59 35 0 + 513 59 35 1 + 514 59 34 0 + 515 59 34 1 + 516 58 35 0 + 517 58 35 1 + 518 58 34 0 + 519 58 34 1 + 520 56 34 1 + 521 56 34 0 + 522 56 35 1 + 523 56 35 0 + 524 57 34 1 + 525 57 34 0 + 526 57 35 1 + 527 57 35 0 + 544 51 34 0 + 545 51 34 1 + 546 51 35 0 + 547 51 35 1 + 548 50 34 0 + 549 50 34 1 + 550 50 35 0 + 551 50 35 1 + 552 48 35 1 + 553 48 35 0 + 554 48 34 1 + 555 48 34 0 + 556 49 35 1 + 557 49 35 0 + 558 49 34 1 + 559 49 34 0 + 560 52 34 0 + 561 52 34 1 + 562 52 35 0 + 563 52 35 1 + 564 53 34 0 + 565 53 34 1 + 566 53 35 0 + 567 53 35 1 + 568 55 35 1 + 569 55 35 0 + 570 55 34 1 + 571 55 34 0 + 572 54 35 1 + 573 54 35 0 + 574 54 34 1 + 575 54 34 0 + 576 60 35 0 + 577 60 35 1 + 578 60 34 0 + 579 60 34 1 + 580 61 35 0 + 581 61 35 1 + 582 61 34 0 + 583 61 34 1 + 584 63 34 1 + 585 63 34 0 + 586 63 35 1 + 587 63 35 0 + 588 62 34 1 + 589 62 34 0 + 590 62 35 1 + 591 62 35 0 + 640 59 37 0 + 641 59 37 1 + 642 59 36 0 + 643 59 36 1 + 644 58 37 0 + 645 58 37 1 + 646 58 36 0 + 647 58 36 1 + 648 56 36 1 + 649 56 36 0 + 650 56 37 1 + 651 56 37 0 + 652 57 36 1 + 653 57 36 0 + 654 57 37 1 + 655 57 37 0 + 672 51 36 0 + 673 51 36 1 + 674 51 37 0 + 675 51 37 1 + 676 50 36 0 + 677 50 36 1 + 678 50 37 0 + 679 50 37 1 + 680 48 37 1 + 681 48 37 0 + 682 48 36 1 + 683 48 36 0 + 684 49 37 1 + 685 49 37 0 + 686 49 36 1 + 687 49 36 0 + 688 52 36 0 + 689 52 36 1 + 690 52 37 0 + 691 52 37 1 + 692 53 36 0 + 693 53 36 1 + 694 53 37 0 + 695 53 37 1 + 696 55 37 1 + 697 55 37 0 + 698 55 36 1 + 699 55 36 0 + 700 54 37 1 + 701 54 37 0 + 702 54 36 1 + 703 54 36 0 + 704 60 37 0 + 705 60 37 1 + 706 60 36 0 + 707 60 36 1 + 708 61 37 0 + 709 61 37 1 + 710 61 36 0 + 711 61 36 1 + 712 63 36 1 + 713 63 36 0 + 714 63 37 1 + 715 63 37 0 + 716 62 36 1 + 717 62 36 0 + 718 62 37 1 + 719 62 37 0 + 768 59 39 0 + 769 59 39 1 + 770 59 38 0 + 771 59 38 1 + 772 58 39 0 + 773 58 39 1 + 774 58 38 0 + 775 58 38 1 + 776 56 38 1 + 777 56 38 0 + 778 56 39 1 + 779 56 39 0 + 780 57 38 1 + 781 57 38 0 + 782 57 39 1 + 783 57 39 0 + 800 51 38 0 + 801 51 38 1 + 802 51 39 0 + 803 51 39 1 + 804 50 38 0 + 805 50 38 1 + 806 50 39 0 + 807 50 39 1 + 808 48 39 1 + 809 48 39 0 + 810 48 38 1 + 811 48 38 0 + 812 49 39 1 + 813 49 39 0 + 814 49 38 1 + 815 49 38 0 + 816 52 38 0 + 817 52 38 1 + 818 52 39 0 + 819 52 39 1 + 820 53 38 0 + 821 53 38 1 + 822 53 39 0 + 823 53 39 1 + 824 55 39 1 + 825 55 39 0 + 826 55 38 1 + 827 55 38 0 + 828 54 39 1 + 829 54 39 0 + 830 54 38 1 + 831 54 38 0 + 832 60 39 0 + 833 60 39 1 + 834 60 38 0 + 835 60 38 1 + 836 61 39 0 + 837 61 39 1 + 838 61 38 0 + 839 61 38 1 + 840 63 38 1 + 841 63 38 0 + 842 63 39 1 + 843 63 39 0 + 844 62 38 1 + 845 62 38 0 + 846 62 39 1 + 847 62 39 0 + 896 59 41 0 + 897 59 41 1 + 898 59 40 0 + 899 59 40 1 + 900 58 41 0 + 901 58 41 1 + 902 58 40 0 + 903 58 40 1 + 904 56 40 1 + 905 56 40 0 + 906 56 41 1 + 907 56 41 0 + 908 57 40 1 + 909 57 40 0 + 910 57 41 1 + 911 57 41 0 + 928 51 40 0 + 929 51 40 1 + 930 51 41 0 + 931 51 41 1 + 932 50 40 0 + 933 50 40 1 + 934 50 41 0 + 935 50 41 1 + 936 48 41 1 + 937 48 41 0 + 938 48 40 1 + 939 48 40 0 + 940 49 41 1 + 941 49 41 0 + 942 49 40 1 + 943 49 40 0 + 944 52 40 0 + 945 52 40 1 + 946 52 41 0 + 947 52 41 1 + 948 53 40 0 + 949 53 40 1 + 950 53 41 0 + 951 53 41 1 + 952 55 41 1 + 953 55 41 0 + 954 55 40 1 + 955 55 40 0 + 956 54 41 1 + 957 54 41 0 + 958 54 40 1 + 959 54 40 0 + 960 60 41 0 + 961 60 41 1 + 962 60 40 0 + 963 60 40 1 + 964 61 41 0 + 965 61 41 1 + 966 61 40 0 + 967 61 40 1 + 968 63 40 1 + 969 63 40 0 + 970 63 41 1 + 971 63 41 0 + 972 62 40 1 + 973 62 40 0 + 974 62 41 1 + 975 62 41 0 +1024 59 43 0 +1025 59 43 1 +1026 59 42 0 +1027 59 42 1 +1028 58 43 0 +1029 58 43 1 +1030 58 42 0 +1031 58 42 1 +1032 56 42 1 +1033 56 42 0 +1034 56 43 1 +1035 56 43 0 +1036 57 42 1 +1037 57 42 0 +1038 57 43 1 +1039 57 43 0 +1056 51 42 0 +1057 51 42 1 +1058 51 43 0 +1059 51 43 1 +1060 50 42 0 +1061 50 42 1 +1062 50 43 0 +1063 50 43 1 +1064 48 43 1 +1065 48 43 0 +1066 48 42 1 +1067 48 42 0 +1068 49 43 1 +1069 49 43 0 +1070 49 42 1 +1071 49 42 0 +1072 52 42 0 +1073 52 42 1 +1074 52 43 0 +1075 52 43 1 +1076 53 42 0 +1077 53 42 1 +1078 53 43 0 +1079 53 43 1 +1080 55 43 1 +1081 55 43 0 +1082 55 42 1 +1083 55 42 0 +1084 54 43 1 +1085 54 43 0 +1086 54 42 1 +1087 54 42 0 +1088 60 43 0 +1089 60 43 1 +1090 60 42 0 +1091 60 42 1 +1092 61 43 0 +1093 61 43 1 +1094 61 42 0 +1095 61 42 1 +1096 63 42 1 +1097 63 42 0 +1098 63 43 1 +1099 63 43 0 +1100 62 42 1 +1101 62 42 0 +1102 62 43 1 +1103 62 43 0 +1152 59 45 0 +1153 59 45 1 +1154 59 44 0 +1155 59 44 1 +1156 58 45 0 +1157 58 45 1 +1158 58 44 0 +1159 58 44 1 +1160 56 44 1 +1161 56 44 0 +1162 56 45 1 +1163 56 45 0 +1164 57 44 1 +1165 57 44 0 +1166 57 45 1 +1167 57 45 0 +1184 51 44 0 +1185 51 44 1 +1186 51 45 0 +1187 51 45 1 +1188 50 44 0 +1189 50 44 1 +1190 50 45 0 +1191 50 45 1 +1192 48 45 1 +1193 48 45 0 +1194 48 44 1 +1195 48 44 0 +1196 49 45 1 +1197 49 45 0 +1198 49 44 1 +1199 49 44 0 +1200 52 44 0 +1201 52 44 1 +1202 52 45 0 +1203 52 45 1 +1204 53 44 0 +1205 53 44 1 +1206 53 45 0 +1207 53 45 1 +1208 55 45 1 +1209 55 45 0 +1210 55 44 1 +1211 55 44 0 +1212 54 45 1 +1213 54 45 0 +1214 54 44 1 +1215 54 44 0 +1216 60 45 0 +1217 60 45 1 +1218 60 44 0 +1219 60 44 1 +1220 61 45 0 +1221 61 45 1 +1222 61 44 0 +1223 61 44 1 +1224 63 44 1 +1225 63 44 0 +1226 63 45 1 +1227 63 45 0 +1228 62 44 1 +1229 62 44 0 +1230 62 45 1 +1231 62 45 0 +1280 59 47 0 +1281 59 47 1 +1282 59 46 0 +1283 59 46 1 +1284 58 47 0 +1285 58 47 1 +1286 58 46 0 +1287 58 46 1 +1288 56 46 1 +1289 56 46 0 +1290 56 47 1 +1291 56 47 0 +1292 57 46 1 +1293 57 46 0 +1294 57 47 1 +1295 57 47 0 +1312 51 46 0 +1313 51 46 1 +1314 51 47 0 +1315 51 47 1 +1316 50 46 0 +1317 50 46 1 +1318 50 47 0 +1319 50 47 1 +1320 48 47 1 +1321 48 47 0 +1322 48 46 1 +1323 48 46 0 +1324 49 47 1 +1325 49 47 0 +1326 49 46 1 +1327 49 46 0 +1328 52 46 0 +1329 52 46 1 +1330 52 47 0 +1331 52 47 1 +1332 53 46 0 +1333 53 46 1 +1334 53 47 0 +1335 53 47 1 +1336 55 47 1 +1337 55 47 0 +1338 55 46 1 +1339 55 46 0 +1340 54 47 1 +1341 54 47 0 +1342 54 46 1 +1343 54 46 0 +1344 60 47 0 +1345 60 47 1 +1346 60 46 0 +1347 60 46 1 +1348 61 47 0 +1349 61 47 1 +1350 61 46 0 +1351 61 46 1 +1352 63 46 1 +1353 63 46 0 +1354 63 47 1 +1355 63 47 0 +1356 62 46 1 +1357 62 46 0 +1358 62 47 1 +1359 62 47 0 +1408 59 49 0 +1409 59 49 1 +1410 59 48 0 +1411 59 48 1 +1412 58 49 0 +1413 58 49 1 +1414 58 48 0 +1415 58 48 1 +1416 56 48 1 +1417 56 48 0 +1418 56 49 1 +1419 56 49 0 +1420 57 48 1 +1421 57 48 0 +1422 57 49 1 +1423 57 49 0 +1440 51 48 0 +1441 51 48 1 +1442 51 49 0 +1443 51 49 1 +1444 50 48 0 +1445 50 48 1 +1446 50 49 0 +1447 50 49 1 +1448 48 49 1 +1449 48 49 0 +1450 48 48 1 +1451 48 48 0 +1452 49 49 1 +1453 49 49 0 +1454 49 48 1 +1455 49 48 0 +1456 52 48 0 +1457 52 48 1 +1458 52 49 0 +1459 52 49 1 +1460 53 48 0 +1461 53 48 1 +1462 53 49 0 +1463 53 49 1 +1464 55 49 1 +1465 55 49 0 +1466 55 48 1 +1467 55 48 0 +1468 54 49 1 +1469 54 49 0 +1470 54 48 1 +1471 54 48 0 +1472 60 49 0 +1473 60 49 1 +1474 60 48 0 +1475 60 48 1 +1476 61 49 0 +1477 61 49 1 +1478 61 48 0 +1479 61 48 1 +1480 63 48 1 +1481 63 48 0 +1482 63 49 1 +1483 63 49 0 +1484 62 48 1 +1485 62 48 0 +1486 62 49 1 +1487 62 49 0 +1536 59 51 0 +1537 59 51 1 +1538 59 50 0 +1539 59 50 1 +1540 58 51 0 +1541 58 51 1 +1542 58 50 0 +1543 58 50 1 +1544 56 50 1 +1545 56 50 0 +1546 56 51 1 +1547 56 51 0 +1548 57 50 1 +1549 57 50 0 +1550 57 51 1 +1551 57 51 0 +1568 51 50 0 +1569 51 50 1 +1570 51 51 0 +1571 51 51 1 +1572 50 50 0 +1573 50 50 1 +1574 50 51 0 +1575 50 51 1 +1576 48 51 1 +1577 48 51 0 +1578 48 50 1 +1579 48 50 0 +1580 49 51 1 +1581 49 51 0 +1582 49 50 1 +1583 49 50 0 +1584 52 50 0 +1585 52 50 1 +1586 52 51 0 +1587 52 51 1 +1588 53 50 0 +1589 53 50 1 +1590 53 51 0 +1591 53 51 1 +1592 55 51 1 +1593 55 51 0 +1594 55 50 1 +1595 55 50 0 +1596 54 51 1 +1597 54 51 0 +1598 54 50 1 +1599 54 50 0 +1600 60 51 0 +1601 60 51 1 +1602 60 50 0 +1603 60 50 1 +1604 61 51 0 +1605 61 51 1 +1606 61 50 0 +1607 61 50 1 +1608 63 50 1 +1609 63 50 0 +1610 63 51 1 +1611 63 51 0 +1612 62 50 1 +1613 62 50 0 +1614 62 51 1 +1615 62 51 0 +1664 59 53 0 +1665 59 53 1 +1666 59 52 0 +1667 59 52 1 +1668 58 53 0 +1669 58 53 1 +1670 58 52 0 +1671 58 52 1 +1672 56 52 1 +1673 56 52 0 +1674 56 53 1 +1675 56 53 0 +1676 57 52 1 +1677 57 52 0 +1678 57 53 1 +1679 57 53 0 +1696 51 52 0 +1697 51 52 1 +1698 51 53 0 +1699 51 53 1 +1700 50 52 0 +1701 50 52 1 +1702 50 53 0 +1703 50 53 1 +1704 48 53 1 +1705 48 53 0 +1706 48 52 1 +1707 48 52 0 +1708 49 53 1 +1709 49 53 0 +1710 49 52 1 +1711 49 52 0 +1712 52 52 0 +1713 52 52 1 +1714 52 53 0 +1715 52 53 1 +1716 53 52 0 +1717 53 52 1 +1718 53 53 0 +1719 53 53 1 +1720 55 53 1 +1721 55 53 0 +1722 55 52 1 +1723 55 52 0 +1724 54 53 1 +1725 54 53 0 +1726 54 52 1 +1727 54 52 0 +1728 60 53 0 +1729 60 53 1 +1730 60 52 0 +1731 60 52 1 +1732 61 53 0 +1733 61 53 1 +1734 61 52 0 +1735 61 52 1 +1736 63 52 1 +1737 63 52 0 +1738 63 53 1 +1739 63 53 0 +1740 62 52 1 +1741 62 52 0 +1742 62 53 1 +1743 62 53 0 +1792 59 55 0 +1793 59 55 1 +1794 59 54 0 +1795 59 54 1 +1796 58 55 0 +1797 58 55 1 +1798 58 54 0 +1799 58 54 1 +1800 56 54 1 +1801 56 54 0 +1802 56 55 1 +1803 56 55 0 +1804 57 54 1 +1805 57 54 0 +1806 57 55 1 +1807 57 55 0 +1824 51 54 0 +1825 51 54 1 +1826 51 55 0 +1827 51 55 1 +1828 50 54 0 +1829 50 54 1 +1830 50 55 0 +1831 50 55 1 +1832 48 55 1 +1833 48 55 0 +1834 48 54 1 +1835 48 54 0 +1836 49 55 1 +1837 49 55 0 +1838 49 54 1 +1839 49 54 0 +1840 52 54 0 +1841 52 54 1 +1842 52 55 0 +1843 52 55 1 +1844 53 54 0 +1845 53 54 1 +1846 53 55 0 +1847 53 55 1 +1848 55 55 1 +1849 55 55 0 +1850 55 54 1 +1851 55 54 0 +1852 54 55 1 +1853 54 55 0 +1854 54 54 1 +1855 54 54 0 +1856 60 55 0 +1857 60 55 1 +1858 60 54 0 +1859 60 54 1 +1860 61 55 0 +1861 61 55 1 +1862 61 54 0 +1863 61 54 1 +1864 63 54 1 +1865 63 54 0 +1866 63 55 1 +1867 63 55 0 +1868 62 54 1 +1869 62 54 0 +1870 62 55 1 +1871 62 55 0 +2176 59 27 0 +2177 59 27 1 +2178 59 26 0 +2179 59 26 1 +2180 58 27 0 +2181 58 27 1 +2182 58 26 0 +2183 58 26 1 +2184 56 26 1 +2185 56 26 0 +2186 56 27 1 +2187 56 27 0 +2188 57 26 1 +2189 57 26 0 +2190 57 27 1 +2191 57 27 0 +2208 51 26 0 +2209 51 26 1 +2210 51 27 0 +2211 51 27 1 +2212 50 26 0 +2213 50 26 1 +2214 50 27 0 +2215 50 27 1 +2216 48 27 1 +2217 48 27 0 +2218 48 26 1 +2219 48 26 0 +2220 49 27 1 +2221 49 27 0 +2222 49 26 1 +2223 49 26 0 +2224 52 26 0 +2225 52 26 1 +2226 52 27 0 +2227 52 27 1 +2228 53 26 0 +2229 53 26 1 +2230 53 27 0 +2231 53 27 1 +2232 55 27 1 +2233 55 27 0 +2234 55 26 1 +2235 55 26 0 +2236 54 27 1 +2237 54 27 0 +2238 54 26 1 +2239 54 26 0 +2240 60 27 0 +2241 60 27 1 +2242 60 26 0 +2243 60 26 1 +2244 61 27 0 +2245 61 27 1 +2246 61 26 0 +2247 61 26 1 +2248 63 26 1 +2249 63 26 0 +2250 63 27 1 +2251 63 27 0 +2252 62 26 1 +2253 62 26 0 +2254 62 27 1 +2255 62 27 0 +2304 59 25 0 +2305 59 25 1 +2306 59 24 0 +2307 59 24 1 +2308 58 25 0 +2309 58 25 1 +2310 58 24 0 +2311 58 24 1 +2312 56 24 1 +2313 56 24 0 +2314 56 25 1 +2315 56 25 0 +2316 57 24 1 +2317 57 24 0 +2318 57 25 1 +2319 57 25 0 +2336 51 24 0 +2337 51 24 1 +2338 51 25 0 +2339 51 25 1 +2340 50 24 0 +2341 50 24 1 +2342 50 25 0 +2343 50 25 1 +2344 48 25 1 +2345 48 25 0 +2346 48 24 1 +2347 48 24 0 +2348 49 25 1 +2349 49 25 0 +2350 49 24 1 +2351 49 24 0 +2352 52 24 0 +2353 52 24 1 +2354 52 25 0 +2355 52 25 1 +2356 53 24 0 +2357 53 24 1 +2358 53 25 0 +2359 53 25 1 +2360 55 25 1 +2361 55 25 0 +2362 55 24 1 +2363 55 24 0 +2364 54 25 1 +2365 54 25 0 +2366 54 24 1 +2367 54 24 0 +2368 60 25 0 +2369 60 25 1 +2370 60 24 0 +2371 60 24 1 +2372 61 25 0 +2373 61 25 1 +2374 61 24 0 +2375 61 24 1 +2376 63 24 1 +2377 63 24 0 +2378 63 25 1 +2379 63 25 0 +2380 62 24 1 +2381 62 24 0 +2382 62 25 1 +2383 62 25 0 +2432 59 23 0 +2433 59 23 1 +2434 59 22 0 +2435 59 22 1 +2436 58 23 0 +2437 58 23 1 +2438 58 22 0 +2439 58 22 1 +2440 56 22 1 +2441 56 22 0 +2442 56 23 1 +2443 56 23 0 +2444 57 22 1 +2445 57 22 0 +2446 57 23 1 +2447 57 23 0 +2464 51 22 0 +2465 51 22 1 +2466 51 23 0 +2467 51 23 1 +2468 50 22 0 +2469 50 22 1 +2470 50 23 0 +2471 50 23 1 +2472 48 23 1 +2473 48 23 0 +2474 48 22 1 +2475 48 22 0 +2476 49 23 1 +2477 49 23 0 +2478 49 22 1 +2479 49 22 0 +2480 52 22 0 +2481 52 22 1 +2482 52 23 0 +2483 52 23 1 +2484 53 22 0 +2485 53 22 1 +2486 53 23 0 +2487 53 23 1 +2488 55 23 1 +2489 55 23 0 +2490 55 22 1 +2491 55 22 0 +2492 54 23 1 +2493 54 23 0 +2494 54 22 1 +2495 54 22 0 +2496 60 23 0 +2497 60 23 1 +2498 60 22 0 +2499 60 22 1 +2500 61 23 0 +2501 61 23 1 +2502 61 22 0 +2503 61 22 1 +2504 63 22 1 +2505 63 22 0 +2506 63 23 1 +2507 63 23 0 +2508 62 22 1 +2509 62 22 0 +2510 62 23 1 +2511 62 23 0 +2560 59 21 0 +2561 59 21 1 +2562 59 20 0 +2563 59 20 1 +2564 58 21 0 +2565 58 21 1 +2566 58 20 0 +2567 58 20 1 +2568 56 20 1 +2569 56 20 0 +2570 56 21 1 +2571 56 21 0 +2572 57 20 1 +2573 57 20 0 +2574 57 21 1 +2575 57 21 0 +2592 51 20 0 +2593 51 20 1 +2594 51 21 0 +2595 51 21 1 +2596 50 20 0 +2597 50 20 1 +2598 50 21 0 +2599 50 21 1 +2600 48 21 1 +2601 48 21 0 +2602 48 20 1 +2603 48 20 0 +2604 49 21 1 +2605 49 21 0 +2606 49 20 1 +2607 49 20 0 +2608 52 20 0 +2609 52 20 1 +2610 52 21 0 +2611 52 21 1 +2612 53 20 0 +2613 53 20 1 +2614 53 21 0 +2615 53 21 1 +2616 55 21 1 +2617 55 21 0 +2618 55 20 1 +2619 55 20 0 +2620 54 21 1 +2621 54 21 0 +2622 54 20 1 +2623 54 20 0 +2624 60 21 0 +2625 60 21 1 +2626 60 20 0 +2627 60 20 1 +2628 61 21 0 +2629 61 21 1 +2630 61 20 0 +2631 61 20 1 +2632 63 20 1 +2633 63 20 0 +2634 63 21 1 +2635 63 21 0 +2636 62 20 1 +2637 62 20 0 +2638 62 21 1 +2639 62 21 0 +2688 59 19 0 +2689 59 19 1 +2690 59 18 0 +2691 59 18 1 +2692 58 19 0 +2693 58 19 1 +2694 58 18 0 +2695 58 18 1 +2696 56 18 1 +2697 56 18 0 +2698 56 19 1 +2699 56 19 0 +2700 57 18 1 +2701 57 18 0 +2702 57 19 1 +2703 57 19 0 +2720 51 18 0 +2721 51 18 1 +2722 51 19 0 +2723 51 19 1 +2724 50 18 0 +2725 50 18 1 +2726 50 19 0 +2727 50 19 1 +2728 48 19 1 +2729 48 19 0 +2730 48 18 1 +2731 48 18 0 +2732 49 19 1 +2733 49 19 0 +2734 49 18 1 +2735 49 18 0 +2736 52 18 0 +2737 52 18 1 +2738 52 19 0 +2739 52 19 1 +2740 53 18 0 +2741 53 18 1 +2742 53 19 0 +2743 53 19 1 +2744 55 19 1 +2745 55 19 0 +2746 55 18 1 +2747 55 18 0 +2748 54 19 1 +2749 54 19 0 +2750 54 18 1 +2751 54 18 0 +2752 60 19 0 +2753 60 19 1 +2754 60 18 0 +2755 60 18 1 +2756 61 19 0 +2757 61 19 1 +2758 61 18 0 +2759 61 18 1 +2760 63 18 1 +2761 63 18 0 +2762 63 19 1 +2763 63 19 0 +2764 62 18 1 +2765 62 18 0 +2766 62 19 1 +2767 62 19 0 +2816 59 17 0 +2817 59 17 1 +2818 59 16 0 +2819 59 16 1 +2820 58 17 0 +2821 58 17 1 +2822 58 16 0 +2823 58 16 1 +2824 56 16 1 +2825 56 16 0 +2826 56 17 1 +2827 56 17 0 +2828 57 16 1 +2829 57 16 0 +2830 57 17 1 +2831 57 17 0 +2848 51 16 0 +2849 51 16 1 +2850 51 17 0 +2851 51 17 1 +2852 50 16 0 +2853 50 16 1 +2854 50 17 0 +2855 50 17 1 +2856 48 17 1 +2857 48 17 0 +2858 48 16 1 +2859 48 16 0 +2860 49 17 1 +2861 49 17 0 +2862 49 16 1 +2863 49 16 0 +2864 52 16 0 +2865 52 16 1 +2866 52 17 0 +2867 52 17 1 +2868 53 16 0 +2869 53 16 1 +2870 53 17 0 +2871 53 17 1 +2872 55 17 1 +2873 55 17 0 +2874 55 16 1 +2875 55 16 0 +2876 54 17 1 +2877 54 17 0 +2878 54 16 1 +2879 54 16 0 +2880 60 17 0 +2881 60 17 1 +2882 60 16 0 +2883 60 16 1 +2884 61 17 0 +2885 61 17 1 +2886 61 16 0 +2887 61 16 1 +2888 63 16 1 +2889 63 16 0 +2890 63 17 1 +2891 63 17 0 +2892 62 16 1 +2893 62 16 0 +2894 62 17 1 +2895 62 17 0 +2944 59 15 0 +2945 59 15 1 +2946 59 14 0 +2947 59 14 1 +2948 58 15 0 +2949 58 15 1 +2950 58 14 0 +2951 58 14 1 +2952 56 14 1 +2953 56 14 0 +2954 56 15 1 +2955 56 15 0 +2956 57 14 1 +2957 57 14 0 +2958 57 15 1 +2959 57 15 0 +2976 51 14 0 +2977 51 14 1 +2978 51 15 0 +2979 51 15 1 +2980 50 14 0 +2981 50 14 1 +2982 50 15 0 +2983 50 15 1 +2984 48 15 1 +2985 48 15 0 +2986 48 14 1 +2987 48 14 0 +2988 49 15 1 +2989 49 15 0 +2990 49 14 1 +2991 49 14 0 +2992 52 14 0 +2993 52 14 1 +2994 52 15 0 +2995 52 15 1 +2996 53 14 0 +2997 53 14 1 +2998 53 15 0 +2999 53 15 1 +3000 55 15 1 +3001 55 15 0 +3002 55 14 1 +3003 55 14 0 +3004 54 15 1 +3005 54 15 0 +3006 54 14 1 +3007 54 14 0 +3008 60 15 0 +3009 60 15 1 +3010 60 14 0 +3011 60 14 1 +3012 61 15 0 +3013 61 15 1 +3014 61 14 0 +3015 61 14 1 +3016 63 14 1 +3017 63 14 0 +3018 63 15 1 +3019 63 15 0 +3020 62 14 1 +3021 62 14 0 +3022 62 15 1 +3023 62 15 0 +3072 59 13 0 +3073 59 13 1 +3074 59 12 0 +3075 59 12 1 +3076 58 13 0 +3077 58 13 1 +3078 58 12 0 +3079 58 12 1 +3080 56 12 1 +3081 56 12 0 +3082 56 13 1 +3083 56 13 0 +3084 57 12 1 +3085 57 12 0 +3086 57 13 1 +3087 57 13 0 +3104 51 12 0 +3105 51 12 1 +3106 51 13 0 +3107 51 13 1 +3108 50 12 0 +3109 50 12 1 +3110 50 13 0 +3111 50 13 1 +3112 48 13 1 +3113 48 13 0 +3114 48 12 1 +3115 48 12 0 +3116 49 13 1 +3117 49 13 0 +3118 49 12 1 +3119 49 12 0 +3120 52 12 0 +3121 52 12 1 +3122 52 13 0 +3123 52 13 1 +3124 53 12 0 +3125 53 12 1 +3126 53 13 0 +3127 53 13 1 +3128 55 13 1 +3129 55 13 0 +3130 55 12 1 +3131 55 12 0 +3132 54 13 1 +3133 54 13 0 +3134 54 12 1 +3135 54 12 0 +3136 60 13 0 +3137 60 13 1 +3138 60 12 0 +3139 60 12 1 +3140 61 13 0 +3141 61 13 1 +3142 61 12 0 +3143 61 12 1 +3144 63 12 1 +3145 63 12 0 +3146 63 13 1 +3147 63 13 0 +3148 62 12 1 +3149 62 12 0 +3150 62 13 1 +3151 62 13 0 +3200 59 11 0 +3201 59 11 1 +3202 59 10 0 +3203 59 10 1 +3204 58 11 0 +3205 58 11 1 +3206 58 10 0 +3207 58 10 1 +3208 56 10 1 +3209 56 10 0 +3210 56 11 1 +3211 56 11 0 +3212 57 10 1 +3213 57 10 0 +3214 57 11 1 +3215 57 11 0 +3232 51 10 0 +3233 51 10 1 +3234 51 11 0 +3235 51 11 1 +3236 50 10 0 +3237 50 10 1 +3238 50 11 0 +3239 50 11 1 +3240 48 11 1 +3241 48 11 0 +3242 48 10 1 +3243 48 10 0 +3244 49 11 1 +3245 49 11 0 +3246 49 10 1 +3247 49 10 0 +3248 52 10 0 +3249 52 10 1 +3250 52 11 0 +3251 52 11 1 +3252 53 10 0 +3253 53 10 1 +3254 53 11 0 +3255 53 11 1 +3256 55 11 1 +3257 55 11 0 +3258 55 10 1 +3259 55 10 0 +3260 54 11 1 +3261 54 11 0 +3262 54 10 1 +3263 54 10 0 +3264 60 11 0 +3265 60 11 1 +3266 60 10 0 +3267 60 10 1 +3268 61 11 0 +3269 61 11 1 +3270 61 10 0 +3271 61 10 1 +3272 63 10 1 +3273 63 10 0 +3274 63 11 1 +3275 63 11 0 +3276 62 10 1 +3277 62 10 0 +3278 62 11 1 +3279 62 11 0 +3328 59 9 0 +3329 59 9 1 +3330 59 8 0 +3331 59 8 1 +3332 58 9 0 +3333 58 9 1 +3334 58 8 0 +3335 58 8 1 +3336 56 8 1 +3337 56 8 0 +3338 56 9 1 +3339 56 9 0 +3340 57 8 1 +3341 57 8 0 +3342 57 9 1 +3343 57 9 0 +3360 51 8 0 +3361 51 8 1 +3362 51 9 0 +3363 51 9 1 +3364 50 8 0 +3365 50 8 1 +3366 50 9 0 +3367 50 9 1 +3368 48 9 1 +3369 48 9 0 +3370 48 8 1 +3371 48 8 0 +3372 49 9 1 +3373 49 9 0 +3374 49 8 1 +3375 49 8 0 +3376 52 8 0 +3377 52 8 1 +3378 52 9 0 +3379 52 9 1 +3380 53 8 0 +3381 53 8 1 +3382 53 9 0 +3383 53 9 1 +3384 55 9 1 +3385 55 9 0 +3386 55 8 1 +3387 55 8 0 +3388 54 9 1 +3389 54 9 0 +3390 54 8 1 +3391 54 8 0 +3392 60 9 0 +3393 60 9 1 +3394 60 8 0 +3395 60 8 1 +3396 61 9 0 +3397 61 9 1 +3398 61 8 0 +3399 61 8 1 +3400 63 8 1 +3401 63 8 0 +3402 63 9 1 +3403 63 9 0 +3404 62 8 1 +3405 62 8 0 +3406 62 9 1 +3407 62 9 0 +3456 59 7 0 +3457 59 7 1 +3458 59 6 0 +3459 59 6 1 +3460 58 7 0 +3461 58 7 1 +3462 58 6 0 +3463 58 6 1 +3464 56 6 1 +3465 56 6 0 +3466 56 7 1 +3467 56 7 0 +3468 57 6 1 +3469 57 6 0 +3470 57 7 1 +3471 57 7 0 +3488 51 6 0 +3489 51 6 1 +3490 51 7 0 +3491 51 7 1 +3492 50 6 0 +3493 50 6 1 +3494 50 7 0 +3495 50 7 1 +3496 48 7 1 +3497 48 7 0 +3498 48 6 1 +3499 48 6 0 +3500 49 7 1 +3501 49 7 0 +3502 49 6 1 +3503 49 6 0 +3504 52 6 0 +3505 52 6 1 +3506 52 7 0 +3507 52 7 1 +3508 53 6 0 +3509 53 6 1 +3510 53 7 0 +3511 53 7 1 +3512 55 7 1 +3513 55 7 0 +3514 55 6 1 +3515 55 6 0 +3516 54 7 1 +3517 54 7 0 +3518 54 6 1 +3519 54 6 0 +3520 60 7 0 +3521 60 7 1 +3522 60 6 0 +3523 60 6 1 +3524 61 7 0 +3525 61 7 1 +3526 61 6 0 +3527 61 6 1 +3528 63 6 1 +3529 63 6 0 +3530 63 7 1 +3531 63 7 0 +3532 62 6 1 +3533 62 6 0 +3534 62 7 1 +3535 62 7 0 +3584 59 5 0 +3585 59 5 1 +3586 59 4 0 +3587 59 4 1 +3588 58 5 0 +3589 58 5 1 +3590 58 4 0 +3591 58 4 1 +3592 56 4 1 +3593 56 4 0 +3594 56 5 1 +3595 56 5 0 +3596 57 4 1 +3597 57 4 0 +3598 57 5 1 +3599 57 5 0 +3616 51 4 0 +3617 51 4 1 +3618 51 5 0 +3619 51 5 1 +3620 50 4 0 +3621 50 4 1 +3622 50 5 0 +3623 50 5 1 +3624 48 5 1 +3625 48 5 0 +3626 48 4 1 +3627 48 4 0 +3628 49 5 1 +3629 49 5 0 +3630 49 4 1 +3631 49 4 0 +3632 52 4 0 +3633 52 4 1 +3634 52 5 0 +3635 52 5 1 +3636 53 4 0 +3637 53 4 1 +3638 53 5 0 +3639 53 5 1 +3640 55 5 1 +3641 55 5 0 +3642 55 4 1 +3643 55 4 0 +3644 54 5 1 +3645 54 5 0 +3646 54 4 1 +3647 54 4 0 +3648 60 5 0 +3649 60 5 1 +3650 60 4 0 +3651 60 4 1 +3652 61 5 0 +3653 61 5 1 +3654 61 4 0 +3655 61 4 1 +3656 63 4 1 +3657 63 4 0 +3658 63 5 1 +3659 63 5 0 +3660 62 4 1 +3661 62 4 0 +3662 62 5 1 +3663 62 5 0 +3712 59 3 0 +3713 59 3 1 +3714 59 2 0 +3715 59 2 1 +3716 58 3 0 +3717 58 3 1 +3718 58 2 0 +3719 58 2 1 +3720 56 2 1 +3721 56 2 0 +3722 56 3 1 +3723 56 3 0 +3724 57 2 1 +3725 57 2 0 +3726 57 3 1 +3727 57 3 0 +3744 51 2 0 +3745 51 2 1 +3746 51 3 0 +3747 51 3 1 +3748 50 2 0 +3749 50 2 1 +3750 50 3 0 +3751 50 3 1 +3752 48 3 1 +3753 48 3 0 +3754 48 2 1 +3755 48 2 0 +3756 49 3 1 +3757 49 3 0 +3758 49 2 1 +3759 49 2 0 +3760 52 2 0 +3761 52 2 1 +3762 52 3 0 +3763 52 3 1 +3764 53 2 0 +3765 53 2 1 +3766 53 3 0 +3767 53 3 1 +3768 55 3 1 +3769 55 3 0 +3770 55 2 1 +3771 55 2 0 +3772 54 3 1 +3773 54 3 0 +3774 54 2 1 +3775 54 2 0 +3776 60 3 0 +3777 60 3 1 +3778 60 2 0 +3779 60 2 1 +3780 61 3 0 +3781 61 3 1 +3782 61 2 0 +3783 61 2 1 +3784 63 2 1 +3785 63 2 0 +3786 63 3 1 +3787 63 3 0 +3788 62 2 1 +3789 62 2 0 +3790 62 3 1 +3791 62 3 0 +3840 59 1 0 +3841 59 1 1 +3842 59 0 0 +3843 59 0 1 +3844 58 1 0 +3845 58 1 1 +3846 58 0 0 +3847 58 0 1 +3848 56 0 1 +3849 56 0 0 +3850 56 1 1 +3851 56 1 0 +3852 57 0 1 +3853 57 0 0 +3854 57 1 1 +3855 57 1 0 +3872 51 0 0 +3873 51 0 1 +3874 51 1 0 +3875 51 1 1 +3876 50 0 0 +3877 50 0 1 +3878 50 1 0 +3879 50 1 1 +3880 48 1 1 +3881 48 1 0 +3882 48 0 1 +3883 48 0 0 +3884 49 1 1 +3885 49 1 0 +3886 49 0 1 +3887 49 0 0 +3888 52 0 0 +3889 52 0 1 +3890 52 1 0 +3891 52 1 1 +3892 53 0 0 +3893 53 0 1 +3894 53 1 0 +3895 53 1 1 +3896 55 1 1 +3897 55 1 0 +3898 55 0 1 +3899 55 0 0 +3900 54 1 1 +3901 54 1 0 +3902 54 0 1 +3903 54 0 0 +3904 60 1 0 +3905 60 1 1 +3906 60 0 0 +3907 60 0 1 +3908 61 1 0 +3909 61 1 1 +3910 61 0 0 +3911 61 0 1 +3912 63 0 1 +3913 63 0 0 +3914 63 1 1 +3915 63 1 0 +3916 62 0 1 +3917 62 0 0 +3918 62 1 1 +3919 62 1 0 diff --git a/Detectors/PHOS/base/files/Mod1RCU0.data b/Detectors/PHOS/base/files/Mod1RCU0.data new file mode 100644 index 0000000000000..4739df6e3e61e --- /dev/null +++ b/Detectors/PHOS/base/files/Mod1RCU0.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 0 0 2 + 1 0 1 2 + 2 0 2 2 + 3 0 3 2 + 4 0 4 2 + 5 0 5 2 + 6 0 6 2 + 7 0 7 2 + 8 0 8 2 + 9 0 9 2 + 10 0 10 2 + 11 0 11 2 + 12 0 12 2 + 13 0 13 2 + 14 0 14 2 + 15 0 15 2 + 16 0 16 2 + 17 0 17 2 + 18 0 18 2 + 19 0 19 2 + 20 0 20 2 + 21 0 21 2 + 22 0 22 2 + 23 0 23 2 + 24 0 24 2 + 25 0 25 2 + 26 0 26 2 + 27 0 27 2 + 28 0 28 2 + 29 0 29 2 + 30 0 30 2 + 31 0 31 2 + 32 0 32 2 + 33 0 33 2 + 34 0 34 2 + 35 0 35 2 + 36 0 36 2 + 37 0 37 2 + 38 0 38 2 + 39 0 39 2 + 40 0 40 2 + 41 0 41 2 + 42 0 42 2 + 43 0 43 2 + 44 0 44 2 + 45 0 45 2 + 46 0 46 2 + 47 0 47 2 + 48 0 48 2 + 49 0 49 2 + 50 0 50 2 + 51 0 51 2 + 52 0 52 2 + 53 0 53 2 + 54 0 54 2 + 55 0 55 2 + 56 0 56 2 + 57 0 57 2 + 58 0 58 2 + 59 0 59 2 + 60 0 60 2 + 61 0 61 2 + 62 0 62 2 + 63 0 63 2 + 64 0 64 2 + 65 0 65 2 + 66 0 66 2 + 67 0 67 2 + 68 0 68 2 + 69 0 69 2 + 70 0 70 2 + 71 0 71 2 + 72 0 72 2 + 73 0 73 2 + 74 0 74 2 + 75 0 75 2 + 76 0 76 2 + 77 0 77 2 + 78 0 78 2 + 79 0 79 2 + 80 0 80 2 + 81 0 81 2 + 82 0 82 2 + 83 0 83 2 + 84 0 84 2 + 85 0 85 2 + 86 0 86 2 + 87 0 87 2 + 88 0 88 2 + 89 0 89 2 + 90 0 90 2 + 91 0 91 2 + 92 0 92 2 + 93 0 93 2 + 94 0 94 2 + 95 0 95 2 + 96 0 96 2 + 97 0 97 2 + 98 0 98 2 + 99 0 99 2 + 100 0 100 2 + 101 0 101 2 + 102 0 102 2 + 103 0 103 2 + 104 0 104 2 + 105 0 105 2 + 106 0 106 2 + 107 0 107 2 + 108 0 108 2 + 109 0 109 2 + 110 0 110 2 + 111 0 111 2 + 112 0 112 2 + 113 0 113 2 + 114 0 114 2 + 115 0 115 2 + 116 0 116 2 + 117 0 117 2 + 118 0 118 2 + 119 0 119 2 + 120 0 120 2 + 121 0 121 2 + 122 0 122 2 + 123 0 123 2 + 124 0 124 2 + 125 0 125 2 + 126 0 126 2 + 127 0 127 2 +2048 0 2048 2 +2049 0 2049 2 +2050 0 2050 2 +2051 0 2051 2 +2052 0 2052 2 +2053 0 2053 2 +2054 0 2054 2 +2055 0 2055 2 +2056 0 2056 2 +2057 0 2057 2 +2058 0 2058 2 +2059 0 2059 2 +2060 0 2060 2 +2061 0 2061 2 +2062 0 2062 2 +2063 0 2063 2 +2064 0 2064 2 +2065 0 2065 2 +2066 0 2066 2 +2067 0 2067 2 +2068 0 2068 2 +2069 0 2069 2 +2070 0 2070 2 +2071 0 2071 2 +2072 0 2072 2 +2073 0 2073 2 +2074 0 2074 2 +2075 0 2075 2 +2076 0 2076 2 +2077 0 2077 2 +2078 0 2078 2 +2079 0 2079 2 +2080 0 2080 2 +2081 0 2081 2 +2082 0 2082 2 +2083 0 2083 2 +2084 0 2084 2 +2085 0 2085 2 +2086 0 2086 2 +2087 0 2087 2 +2088 0 2088 2 +2089 0 2089 2 +2090 0 2090 2 +2091 0 2091 2 +2092 0 2092 2 +2093 0 2093 2 +2094 0 2094 2 +2095 0 2095 2 +2096 0 2096 2 +2097 0 2097 2 +2098 0 2098 2 +2099 0 2099 2 +2100 0 2100 2 +2101 0 2101 2 +2102 0 2102 2 +2103 0 2103 2 +2104 0 2104 2 +2105 0 2105 2 +2106 0 2106 2 +2107 0 2107 2 +2108 0 2108 2 +2109 0 2109 2 +2110 0 2110 2 +2111 0 2111 2 +2112 0 2112 2 +2113 0 2113 2 +2114 0 2114 2 +2115 0 2115 2 +2116 0 2116 2 +2117 0 2117 2 +2118 0 2118 2 +2119 0 2119 2 +2120 0 2120 2 +2121 0 2121 2 +2122 0 2122 2 +2123 0 2123 2 +2124 0 2124 2 +2125 0 2125 2 +2126 0 2126 2 +2127 0 2127 2 +2128 0 2128 2 +2129 0 2129 2 +2130 0 2130 2 +2131 0 2131 2 +2132 0 2132 2 +2133 0 2133 2 +2134 0 2134 2 +2135 0 2135 2 +2136 0 2136 2 +2137 0 2137 2 +2138 0 2138 2 +2139 0 2139 2 +2140 0 2140 2 +2141 0 2141 2 +2142 0 2142 2 +2143 0 2143 2 +2144 0 2144 2 +2145 0 2145 2 +2146 0 2146 2 +2147 0 2147 2 +2148 0 2148 2 +2149 0 2149 2 +2150 0 2150 2 +2151 0 2151 2 +2152 0 2152 2 +2153 0 2153 2 +2154 0 2154 2 +2155 0 2155 2 +2156 0 2156 2 +2157 0 2157 2 +2158 0 2158 2 +2159 0 2159 2 +2160 0 2160 2 +2161 0 2161 2 +2162 0 2162 2 +2163 0 2163 2 +2164 0 2164 2 +2165 0 2165 2 +2166 0 2166 2 +2167 0 2167 2 +2168 0 2168 2 +2169 0 2169 2 +2170 0 2170 2 +2171 0 2171 2 +2172 0 2172 2 +2173 0 2173 2 +2174 0 2174 2 +2175 0 2175 2 + 128 11 29 0 + 129 11 29 1 + 130 11 28 0 + 131 11 28 1 + 132 10 29 0 + 133 10 29 1 + 134 10 28 0 + 135 10 28 1 + 136 8 28 1 + 137 8 28 0 + 138 8 29 1 + 139 8 29 0 + 140 9 28 1 + 141 9 28 0 + 142 9 29 1 + 143 9 29 0 + 160 3 28 0 + 161 3 28 1 + 162 3 29 0 + 163 3 29 1 + 164 2 28 0 + 165 2 28 1 + 166 2 29 0 + 167 2 29 1 + 168 0 29 1 + 169 0 29 0 + 170 0 28 1 + 171 0 28 0 + 172 1 29 1 + 173 1 29 0 + 174 1 28 1 + 175 1 28 0 + 176 4 28 0 + 177 4 28 1 + 178 4 29 0 + 179 4 29 1 + 180 5 28 0 + 181 5 28 1 + 182 5 29 0 + 183 5 29 1 + 184 7 29 1 + 185 7 29 0 + 186 7 28 1 + 187 7 28 0 + 188 6 29 1 + 189 6 29 0 + 190 6 28 1 + 191 6 28 0 + 192 12 29 0 + 193 12 29 1 + 194 12 28 0 + 195 12 28 1 + 196 13 29 0 + 197 13 29 1 + 198 13 28 0 + 199 13 28 1 + 200 15 28 1 + 201 15 28 0 + 202 15 29 1 + 203 15 29 0 + 204 14 28 1 + 205 14 28 0 + 206 14 29 1 + 207 14 29 0 + 256 11 31 0 + 257 11 31 1 + 258 11 30 0 + 259 11 30 1 + 260 10 31 0 + 261 10 31 1 + 262 10 30 0 + 263 10 30 1 + 264 8 30 1 + 265 8 30 0 + 266 8 31 1 + 267 8 31 0 + 268 9 30 1 + 269 9 30 0 + 270 9 31 1 + 271 9 31 0 + 288 3 30 0 + 289 3 30 1 + 290 3 31 0 + 291 3 31 1 + 292 2 30 0 + 293 2 30 1 + 294 2 31 0 + 295 2 31 1 + 296 0 31 1 + 297 0 31 0 + 298 0 30 1 + 299 0 30 0 + 300 1 31 1 + 301 1 31 0 + 302 1 30 1 + 303 1 30 0 + 304 4 30 0 + 305 4 30 1 + 306 4 31 0 + 307 4 31 1 + 308 5 30 0 + 309 5 30 1 + 310 5 31 0 + 311 5 31 1 + 312 7 31 1 + 313 7 31 0 + 314 7 30 1 + 315 7 30 0 + 316 6 31 1 + 317 6 31 0 + 318 6 30 1 + 319 6 30 0 + 320 12 31 0 + 321 12 31 1 + 322 12 30 0 + 323 12 30 1 + 324 13 31 0 + 325 13 31 1 + 326 13 30 0 + 327 13 30 1 + 328 15 30 1 + 329 15 30 0 + 330 15 31 1 + 331 15 31 0 + 332 14 30 1 + 333 14 30 0 + 334 14 31 1 + 335 14 31 0 + 384 11 33 0 + 385 11 33 1 + 386 11 32 0 + 387 11 32 1 + 388 10 33 0 + 389 10 33 1 + 390 10 32 0 + 391 10 32 1 + 392 8 32 1 + 393 8 32 0 + 394 8 33 1 + 395 8 33 0 + 396 9 32 1 + 397 9 32 0 + 398 9 33 1 + 399 9 33 0 + 416 3 32 0 + 417 3 32 1 + 418 3 33 0 + 419 3 33 1 + 420 2 32 0 + 421 2 32 1 + 422 2 33 0 + 423 2 33 1 + 424 0 33 1 + 425 0 33 0 + 426 0 32 1 + 427 0 32 0 + 428 1 33 1 + 429 1 33 0 + 430 1 32 1 + 431 1 32 0 + 432 4 32 0 + 433 4 32 1 + 434 4 33 0 + 435 4 33 1 + 436 5 32 0 + 437 5 32 1 + 438 5 33 0 + 439 5 33 1 + 440 7 33 1 + 441 7 33 0 + 442 7 32 1 + 443 7 32 0 + 444 6 33 1 + 445 6 33 0 + 446 6 32 1 + 447 6 32 0 + 448 12 33 0 + 449 12 33 1 + 450 12 32 0 + 451 12 32 1 + 452 13 33 0 + 453 13 33 1 + 454 13 32 0 + 455 13 32 1 + 456 15 32 1 + 457 15 32 0 + 458 15 33 1 + 459 15 33 0 + 460 14 32 1 + 461 14 32 0 + 462 14 33 1 + 463 14 33 0 + 512 11 35 0 + 513 11 35 1 + 514 11 34 0 + 515 11 34 1 + 516 10 35 0 + 517 10 35 1 + 518 10 34 0 + 519 10 34 1 + 520 8 34 1 + 521 8 34 0 + 522 8 35 1 + 523 8 35 0 + 524 9 34 1 + 525 9 34 0 + 526 9 35 1 + 527 9 35 0 + 544 3 34 0 + 545 3 34 1 + 546 3 35 0 + 547 3 35 1 + 548 2 34 0 + 549 2 34 1 + 550 2 35 0 + 551 2 35 1 + 552 0 35 1 + 553 0 35 0 + 554 0 34 1 + 555 0 34 0 + 556 1 35 1 + 557 1 35 0 + 558 1 34 1 + 559 1 34 0 + 560 4 34 0 + 561 4 34 1 + 562 4 35 0 + 563 4 35 1 + 564 5 34 0 + 565 5 34 1 + 566 5 35 0 + 567 5 35 1 + 568 7 35 1 + 569 7 35 0 + 570 7 34 1 + 571 7 34 0 + 572 6 35 1 + 573 6 35 0 + 574 6 34 1 + 575 6 34 0 + 576 12 35 0 + 577 12 35 1 + 578 12 34 0 + 579 12 34 1 + 580 13 35 0 + 581 13 35 1 + 582 13 34 0 + 583 13 34 1 + 584 15 34 1 + 585 15 34 0 + 586 15 35 1 + 587 15 35 0 + 588 14 34 1 + 589 14 34 0 + 590 14 35 1 + 591 14 35 0 + 640 11 37 0 + 641 11 37 1 + 642 11 36 0 + 643 11 36 1 + 644 10 37 0 + 645 10 37 1 + 646 10 36 0 + 647 10 36 1 + 648 8 36 1 + 649 8 36 0 + 650 8 37 1 + 651 8 37 0 + 652 9 36 1 + 653 9 36 0 + 654 9 37 1 + 655 9 37 0 + 672 3 36 0 + 673 3 36 1 + 674 3 37 0 + 675 3 37 1 + 676 2 36 0 + 677 2 36 1 + 678 2 37 0 + 679 2 37 1 + 680 0 37 1 + 681 0 37 0 + 682 0 36 1 + 683 0 36 0 + 684 1 37 1 + 685 1 37 0 + 686 1 36 1 + 687 1 36 0 + 688 4 36 0 + 689 4 36 1 + 690 4 37 0 + 691 4 37 1 + 692 5 36 0 + 693 5 36 1 + 694 5 37 0 + 695 5 37 1 + 696 7 37 1 + 697 7 37 0 + 698 7 36 1 + 699 7 36 0 + 700 6 37 1 + 701 6 37 0 + 702 6 36 1 + 703 6 36 0 + 704 12 37 0 + 705 12 37 1 + 706 12 36 0 + 707 12 36 1 + 708 13 37 0 + 709 13 37 1 + 710 13 36 0 + 711 13 36 1 + 712 15 36 1 + 713 15 36 0 + 714 15 37 1 + 715 15 37 0 + 716 14 36 1 + 717 14 36 0 + 718 14 37 1 + 719 14 37 0 + 768 11 39 0 + 769 11 39 1 + 770 11 38 0 + 771 11 38 1 + 772 10 39 0 + 773 10 39 1 + 774 10 38 0 + 775 10 38 1 + 776 8 38 1 + 777 8 38 0 + 778 8 39 1 + 779 8 39 0 + 780 9 38 1 + 781 9 38 0 + 782 9 39 1 + 783 9 39 0 + 800 3 38 0 + 801 3 38 1 + 802 3 39 0 + 803 3 39 1 + 804 2 38 0 + 805 2 38 1 + 806 2 39 0 + 807 2 39 1 + 808 0 39 1 + 809 0 39 0 + 810 0 38 1 + 811 0 38 0 + 812 1 39 1 + 813 1 39 0 + 814 1 38 1 + 815 1 38 0 + 816 4 38 0 + 817 4 38 1 + 818 4 39 0 + 819 4 39 1 + 820 5 38 0 + 821 5 38 1 + 822 5 39 0 + 823 5 39 1 + 824 7 39 1 + 825 7 39 0 + 826 7 38 1 + 827 7 38 0 + 828 6 39 1 + 829 6 39 0 + 830 6 38 1 + 831 6 38 0 + 832 12 39 0 + 833 12 39 1 + 834 12 38 0 + 835 12 38 1 + 836 13 39 0 + 837 13 39 1 + 838 13 38 0 + 839 13 38 1 + 840 15 38 1 + 841 15 38 0 + 842 15 39 1 + 843 15 39 0 + 844 14 38 1 + 845 14 38 0 + 846 14 39 1 + 847 14 39 0 + 896 11 41 0 + 897 11 41 1 + 898 11 40 0 + 899 11 40 1 + 900 10 41 0 + 901 10 41 1 + 902 10 40 0 + 903 10 40 1 + 904 8 40 1 + 905 8 40 0 + 906 8 41 1 + 907 8 41 0 + 908 9 40 1 + 909 9 40 0 + 910 9 41 1 + 911 9 41 0 + 928 3 40 0 + 929 3 40 1 + 930 3 41 0 + 931 3 41 1 + 932 2 40 0 + 933 2 40 1 + 934 2 41 0 + 935 2 41 1 + 936 0 41 1 + 937 0 41 0 + 938 0 40 1 + 939 0 40 0 + 940 1 41 1 + 941 1 41 0 + 942 1 40 1 + 943 1 40 0 + 944 4 40 0 + 945 4 40 1 + 946 4 41 0 + 947 4 41 1 + 948 5 40 0 + 949 5 40 1 + 950 5 41 0 + 951 5 41 1 + 952 7 41 1 + 953 7 41 0 + 954 7 40 1 + 955 7 40 0 + 956 6 41 1 + 957 6 41 0 + 958 6 40 1 + 959 6 40 0 + 960 12 41 0 + 961 12 41 1 + 962 12 40 0 + 963 12 40 1 + 964 13 41 0 + 965 13 41 1 + 966 13 40 0 + 967 13 40 1 + 968 15 40 1 + 969 15 40 0 + 970 15 41 1 + 971 15 41 0 + 972 14 40 1 + 973 14 40 0 + 974 14 41 1 + 975 14 41 0 +1024 11 43 0 +1025 11 43 1 +1026 11 42 0 +1027 11 42 1 +1028 10 43 0 +1029 10 43 1 +1030 10 42 0 +1031 10 42 1 +1032 8 42 1 +1033 8 42 0 +1034 8 43 1 +1035 8 43 0 +1036 9 42 1 +1037 9 42 0 +1038 9 43 1 +1039 9 43 0 +1056 3 42 0 +1057 3 42 1 +1058 3 43 0 +1059 3 43 1 +1060 2 42 0 +1061 2 42 1 +1062 2 43 0 +1063 2 43 1 +1064 0 43 1 +1065 0 43 0 +1066 0 42 1 +1067 0 42 0 +1068 1 43 1 +1069 1 43 0 +1070 1 42 1 +1071 1 42 0 +1072 4 42 0 +1073 4 42 1 +1074 4 43 0 +1075 4 43 1 +1076 5 42 0 +1077 5 42 1 +1078 5 43 0 +1079 5 43 1 +1080 7 43 1 +1081 7 43 0 +1082 7 42 1 +1083 7 42 0 +1084 6 43 1 +1085 6 43 0 +1086 6 42 1 +1087 6 42 0 +1088 12 43 0 +1089 12 43 1 +1090 12 42 0 +1091 12 42 1 +1092 13 43 0 +1093 13 43 1 +1094 13 42 0 +1095 13 42 1 +1096 15 42 1 +1097 15 42 0 +1098 15 43 1 +1099 15 43 0 +1100 14 42 1 +1101 14 42 0 +1102 14 43 1 +1103 14 43 0 +1152 11 45 0 +1153 11 45 1 +1154 11 44 0 +1155 11 44 1 +1156 10 45 0 +1157 10 45 1 +1158 10 44 0 +1159 10 44 1 +1160 8 44 1 +1161 8 44 0 +1162 8 45 1 +1163 8 45 0 +1164 9 44 1 +1165 9 44 0 +1166 9 45 1 +1167 9 45 0 +1184 3 44 0 +1185 3 44 1 +1186 3 45 0 +1187 3 45 1 +1188 2 44 0 +1189 2 44 1 +1190 2 45 0 +1191 2 45 1 +1192 0 45 1 +1193 0 45 0 +1194 0 44 1 +1195 0 44 0 +1196 1 45 1 +1197 1 45 0 +1198 1 44 1 +1199 1 44 0 +1200 4 44 0 +1201 4 44 1 +1202 4 45 0 +1203 4 45 1 +1204 5 44 0 +1205 5 44 1 +1206 5 45 0 +1207 5 45 1 +1208 7 45 1 +1209 7 45 0 +1210 7 44 1 +1211 7 44 0 +1212 6 45 1 +1213 6 45 0 +1214 6 44 1 +1215 6 44 0 +1216 12 45 0 +1217 12 45 1 +1218 12 44 0 +1219 12 44 1 +1220 13 45 0 +1221 13 45 1 +1222 13 44 0 +1223 13 44 1 +1224 15 44 1 +1225 15 44 0 +1226 15 45 1 +1227 15 45 0 +1228 14 44 1 +1229 14 44 0 +1230 14 45 1 +1231 14 45 0 +1280 11 47 0 +1281 11 47 1 +1282 11 46 0 +1283 11 46 1 +1284 10 47 0 +1285 10 47 1 +1286 10 46 0 +1287 10 46 1 +1288 8 46 1 +1289 8 46 0 +1290 8 47 1 +1291 8 47 0 +1292 9 46 1 +1293 9 46 0 +1294 9 47 1 +1295 9 47 0 +1312 3 46 0 +1313 3 46 1 +1314 3 47 0 +1315 3 47 1 +1316 2 46 0 +1317 2 46 1 +1318 2 47 0 +1319 2 47 1 +1320 0 47 1 +1321 0 47 0 +1322 0 46 1 +1323 0 46 0 +1324 1 47 1 +1325 1 47 0 +1326 1 46 1 +1327 1 46 0 +1328 4 46 0 +1329 4 46 1 +1330 4 47 0 +1331 4 47 1 +1332 5 46 0 +1333 5 46 1 +1334 5 47 0 +1335 5 47 1 +1336 7 47 1 +1337 7 47 0 +1338 7 46 1 +1339 7 46 0 +1340 6 47 1 +1341 6 47 0 +1342 6 46 1 +1343 6 46 0 +1344 12 47 0 +1345 12 47 1 +1346 12 46 0 +1347 12 46 1 +1348 13 47 0 +1349 13 47 1 +1350 13 46 0 +1351 13 46 1 +1352 15 46 1 +1353 15 46 0 +1354 15 47 1 +1355 15 47 0 +1356 14 46 1 +1357 14 46 0 +1358 14 47 1 +1359 14 47 0 +1408 11 49 0 +1409 11 49 1 +1410 11 48 0 +1411 11 48 1 +1412 10 49 0 +1413 10 49 1 +1414 10 48 0 +1415 10 48 1 +1416 8 48 1 +1417 8 48 0 +1418 8 49 1 +1419 8 49 0 +1420 9 48 1 +1421 9 48 0 +1422 9 49 1 +1423 9 49 0 +1440 3 48 0 +1441 3 48 1 +1442 3 49 0 +1443 3 49 1 +1444 2 48 0 +1445 2 48 1 +1446 2 49 0 +1447 2 49 1 +1448 0 49 1 +1449 0 49 0 +1450 0 48 1 +1451 0 48 0 +1452 1 49 1 +1453 1 49 0 +1454 1 48 1 +1455 1 48 0 +1456 4 48 0 +1457 4 48 1 +1458 4 49 0 +1459 4 49 1 +1460 5 48 0 +1461 5 48 1 +1462 5 49 0 +1463 5 49 1 +1464 7 49 1 +1465 7 49 0 +1466 7 48 1 +1467 7 48 0 +1468 6 49 1 +1469 6 49 0 +1470 6 48 1 +1471 6 48 0 +1472 12 49 0 +1473 12 49 1 +1474 12 48 0 +1475 12 48 1 +1476 13 49 0 +1477 13 49 1 +1478 13 48 0 +1479 13 48 1 +1480 15 48 1 +1481 15 48 0 +1482 15 49 1 +1483 15 49 0 +1484 14 48 1 +1485 14 48 0 +1486 14 49 1 +1487 14 49 0 +1536 11 51 0 +1537 11 51 1 +1538 11 50 0 +1539 11 50 1 +1540 10 51 0 +1541 10 51 1 +1542 10 50 0 +1543 10 50 1 +1544 8 50 1 +1545 8 50 0 +1546 8 51 1 +1547 8 51 0 +1548 9 50 1 +1549 9 50 0 +1550 9 51 1 +1551 9 51 0 +1568 3 50 0 +1569 3 50 1 +1570 3 51 0 +1571 3 51 1 +1572 2 50 0 +1573 2 50 1 +1574 2 51 0 +1575 2 51 1 +1576 0 51 1 +1577 0 51 0 +1578 0 50 1 +1579 0 50 0 +1580 1 51 1 +1581 1 51 0 +1582 1 50 1 +1583 1 50 0 +1584 4 50 0 +1585 4 50 1 +1586 4 51 0 +1587 4 51 1 +1588 5 50 0 +1589 5 50 1 +1590 5 51 0 +1591 5 51 1 +1592 7 51 1 +1593 7 51 0 +1594 7 50 1 +1595 7 50 0 +1596 6 51 1 +1597 6 51 0 +1598 6 50 1 +1599 6 50 0 +1600 12 51 0 +1601 12 51 1 +1602 12 50 0 +1603 12 50 1 +1604 13 51 0 +1605 13 51 1 +1606 13 50 0 +1607 13 50 1 +1608 15 50 1 +1609 15 50 0 +1610 15 51 1 +1611 15 51 0 +1612 14 50 1 +1613 14 50 0 +1614 14 51 1 +1615 14 51 0 +1664 11 53 0 +1665 11 53 1 +1666 11 52 0 +1667 11 52 1 +1668 10 53 0 +1669 10 53 1 +1670 10 52 0 +1671 10 52 1 +1672 8 52 1 +1673 8 52 0 +1674 8 53 1 +1675 8 53 0 +1676 9 52 1 +1677 9 52 0 +1678 9 53 1 +1679 9 53 0 +1696 3 52 0 +1697 3 52 1 +1698 3 53 0 +1699 3 53 1 +1700 2 52 0 +1701 2 52 1 +1702 2 53 0 +1703 2 53 1 +1704 0 53 1 +1705 0 53 0 +1706 0 52 1 +1707 0 52 0 +1708 1 53 1 +1709 1 53 0 +1710 1 52 1 +1711 1 52 0 +1712 4 52 0 +1713 4 52 1 +1714 4 53 0 +1715 4 53 1 +1716 5 52 0 +1717 5 52 1 +1718 5 53 0 +1719 5 53 1 +1720 7 53 1 +1721 7 53 0 +1722 7 52 1 +1723 7 52 0 +1724 6 53 1 +1725 6 53 0 +1726 6 52 1 +1727 6 52 0 +1728 12 53 0 +1729 12 53 1 +1730 12 52 0 +1731 12 52 1 +1732 13 53 0 +1733 13 53 1 +1734 13 52 0 +1735 13 52 1 +1736 15 52 1 +1737 15 52 0 +1738 15 53 1 +1739 15 53 0 +1740 14 52 1 +1741 14 52 0 +1742 14 53 1 +1743 14 53 0 +1792 11 55 0 +1793 11 55 1 +1794 11 54 0 +1795 11 54 1 +1796 10 55 0 +1797 10 55 1 +1798 10 54 0 +1799 10 54 1 +1800 8 54 1 +1801 8 54 0 +1802 8 55 1 +1803 8 55 0 +1804 9 54 1 +1805 9 54 0 +1806 9 55 1 +1807 9 55 0 +1824 3 54 0 +1825 3 54 1 +1826 3 55 0 +1827 3 55 1 +1828 2 54 0 +1829 2 54 1 +1830 2 55 0 +1831 2 55 1 +1832 0 55 1 +1833 0 55 0 +1834 0 54 1 +1835 0 54 0 +1836 1 55 1 +1837 1 55 0 +1838 1 54 1 +1839 1 54 0 +1840 4 54 0 +1841 4 54 1 +1842 4 55 0 +1843 4 55 1 +1844 5 54 0 +1845 5 54 1 +1846 5 55 0 +1847 5 55 1 +1848 7 55 1 +1849 7 55 0 +1850 7 54 1 +1851 7 54 0 +1852 6 55 1 +1853 6 55 0 +1854 6 54 1 +1855 6 54 0 +1856 12 55 0 +1857 12 55 1 +1858 12 54 0 +1859 12 54 1 +1860 13 55 0 +1861 13 55 1 +1862 13 54 0 +1863 13 54 1 +1864 15 54 1 +1865 15 54 0 +1866 15 55 1 +1867 15 55 0 +1868 14 54 1 +1869 14 54 0 +1870 14 55 1 +1871 14 55 0 +2176 11 27 0 +2177 11 27 1 +2178 11 26 0 +2179 11 26 1 +2180 10 27 0 +2181 10 27 1 +2182 10 26 0 +2183 10 26 1 +2184 8 26 1 +2185 8 26 0 +2186 8 27 1 +2187 8 27 0 +2188 9 26 1 +2189 9 26 0 +2190 9 27 1 +2191 9 27 0 +2208 3 26 0 +2209 3 26 1 +2210 3 27 0 +2211 3 27 1 +2212 2 26 0 +2213 2 26 1 +2214 2 27 0 +2215 2 27 1 +2216 0 27 1 +2217 0 27 0 +2218 0 26 1 +2219 0 26 0 +2220 1 27 1 +2221 1 27 0 +2222 1 26 1 +2223 1 26 0 +2224 4 26 0 +2225 4 26 1 +2226 4 27 0 +2227 4 27 1 +2228 5 26 0 +2229 5 26 1 +2230 5 27 0 +2231 5 27 1 +2232 7 27 1 +2233 7 27 0 +2234 7 26 1 +2235 7 26 0 +2236 6 27 1 +2237 6 27 0 +2238 6 26 1 +2239 6 26 0 +2240 12 27 0 +2241 12 27 1 +2242 12 26 0 +2243 12 26 1 +2244 13 27 0 +2245 13 27 1 +2246 13 26 0 +2247 13 26 1 +2248 15 26 1 +2249 15 26 0 +2250 15 27 1 +2251 15 27 0 +2252 14 26 1 +2253 14 26 0 +2254 14 27 1 +2255 14 27 0 +2304 11 25 0 +2305 11 25 1 +2306 11 24 0 +2307 11 24 1 +2308 10 25 0 +2309 10 25 1 +2310 10 24 0 +2311 10 24 1 +2312 8 24 1 +2313 8 24 0 +2314 8 25 1 +2315 8 25 0 +2316 9 24 1 +2317 9 24 0 +2318 9 25 1 +2319 9 25 0 +2336 3 24 0 +2337 3 24 1 +2338 3 25 0 +2339 3 25 1 +2340 2 24 0 +2341 2 24 1 +2342 2 25 0 +2343 2 25 1 +2344 0 25 1 +2345 0 25 0 +2346 0 24 1 +2347 0 24 0 +2348 1 25 1 +2349 1 25 0 +2350 1 24 1 +2351 1 24 0 +2352 4 24 0 +2353 4 24 1 +2354 4 25 0 +2355 4 25 1 +2356 5 24 0 +2357 5 24 1 +2358 5 25 0 +2359 5 25 1 +2360 7 25 1 +2361 7 25 0 +2362 7 24 1 +2363 7 24 0 +2364 6 25 1 +2365 6 25 0 +2366 6 24 1 +2367 6 24 0 +2368 12 25 0 +2369 12 25 1 +2370 12 24 0 +2371 12 24 1 +2372 13 25 0 +2373 13 25 1 +2374 13 24 0 +2375 13 24 1 +2376 15 24 1 +2377 15 24 0 +2378 15 25 1 +2379 15 25 0 +2380 14 24 1 +2381 14 24 0 +2382 14 25 1 +2383 14 25 0 +2432 11 23 0 +2433 11 23 1 +2434 11 22 0 +2435 11 22 1 +2436 10 23 0 +2437 10 23 1 +2438 10 22 0 +2439 10 22 1 +2440 8 22 1 +2441 8 22 0 +2442 8 23 1 +2443 8 23 0 +2444 9 22 1 +2445 9 22 0 +2446 9 23 1 +2447 9 23 0 +2464 3 22 0 +2465 3 22 1 +2466 3 23 0 +2467 3 23 1 +2468 2 22 0 +2469 2 22 1 +2470 2 23 0 +2471 2 23 1 +2472 0 23 1 +2473 0 23 0 +2474 0 22 1 +2475 0 22 0 +2476 1 23 1 +2477 1 23 0 +2478 1 22 1 +2479 1 22 0 +2480 4 22 0 +2481 4 22 1 +2482 4 23 0 +2483 4 23 1 +2484 5 22 0 +2485 5 22 1 +2486 5 23 0 +2487 5 23 1 +2488 7 23 1 +2489 7 23 0 +2490 7 22 1 +2491 7 22 0 +2492 6 23 1 +2493 6 23 0 +2494 6 22 1 +2495 6 22 0 +2496 12 23 0 +2497 12 23 1 +2498 12 22 0 +2499 12 22 1 +2500 13 23 0 +2501 13 23 1 +2502 13 22 0 +2503 13 22 1 +2504 15 22 1 +2505 15 22 0 +2506 15 23 1 +2507 15 23 0 +2508 14 22 1 +2509 14 22 0 +2510 14 23 1 +2511 14 23 0 +2560 11 21 0 +2561 11 21 1 +2562 11 20 0 +2563 11 20 1 +2564 10 21 0 +2565 10 21 1 +2566 10 20 0 +2567 10 20 1 +2568 8 20 1 +2569 8 20 0 +2570 8 21 1 +2571 8 21 0 +2572 9 20 1 +2573 9 20 0 +2574 9 21 1 +2575 9 21 0 +2592 3 20 0 +2593 3 20 1 +2594 3 21 0 +2595 3 21 1 +2596 2 20 0 +2597 2 20 1 +2598 2 21 0 +2599 2 21 1 +2600 0 21 1 +2601 0 21 0 +2602 0 20 1 +2603 0 20 0 +2604 1 21 1 +2605 1 21 0 +2606 1 20 1 +2607 1 20 0 +2608 4 20 0 +2609 4 20 1 +2610 4 21 0 +2611 4 21 1 +2612 5 20 0 +2613 5 20 1 +2614 5 21 0 +2615 5 21 1 +2616 7 21 1 +2617 7 21 0 +2618 7 20 1 +2619 7 20 0 +2620 6 21 1 +2621 6 21 0 +2622 6 20 1 +2623 6 20 0 +2624 12 21 0 +2625 12 21 1 +2626 12 20 0 +2627 12 20 1 +2628 13 21 0 +2629 13 21 1 +2630 13 20 0 +2631 13 20 1 +2632 15 20 1 +2633 15 20 0 +2634 15 21 1 +2635 15 21 0 +2636 14 20 1 +2637 14 20 0 +2638 14 21 1 +2639 14 21 0 +2688 11 19 0 +2689 11 19 1 +2690 11 18 0 +2691 11 18 1 +2692 10 19 0 +2693 10 19 1 +2694 10 18 0 +2695 10 18 1 +2696 8 18 1 +2697 8 18 0 +2698 8 19 1 +2699 8 19 0 +2700 9 18 1 +2701 9 18 0 +2702 9 19 1 +2703 9 19 0 +2720 3 18 0 +2721 3 18 1 +2722 3 19 0 +2723 3 19 1 +2724 2 18 0 +2725 2 18 1 +2726 2 19 0 +2727 2 19 1 +2728 0 19 1 +2729 0 19 0 +2730 0 18 1 +2731 0 18 0 +2732 1 19 1 +2733 1 19 0 +2734 1 18 1 +2735 1 18 0 +2736 4 18 0 +2737 4 18 1 +2738 4 19 0 +2739 4 19 1 +2740 5 18 0 +2741 5 18 1 +2742 5 19 0 +2743 5 19 1 +2744 7 19 1 +2745 7 19 0 +2746 7 18 1 +2747 7 18 0 +2748 6 19 1 +2749 6 19 0 +2750 6 18 1 +2751 6 18 0 +2752 12 19 0 +2753 12 19 1 +2754 12 18 0 +2755 12 18 1 +2756 13 19 0 +2757 13 19 1 +2758 13 18 0 +2759 13 18 1 +2760 15 18 1 +2761 15 18 0 +2762 15 19 1 +2763 15 19 0 +2764 14 18 1 +2765 14 18 0 +2766 14 19 1 +2767 14 19 0 +2816 11 17 0 +2817 11 17 1 +2818 11 16 0 +2819 11 16 1 +2820 10 17 0 +2821 10 17 1 +2822 10 16 0 +2823 10 16 1 +2824 8 16 1 +2825 8 16 0 +2826 8 17 1 +2827 8 17 0 +2828 9 16 1 +2829 9 16 0 +2830 9 17 1 +2831 9 17 0 +2848 3 16 0 +2849 3 16 1 +2850 3 17 0 +2851 3 17 1 +2852 2 16 0 +2853 2 16 1 +2854 2 17 0 +2855 2 17 1 +2856 0 17 1 +2857 0 17 0 +2858 0 16 1 +2859 0 16 0 +2860 1 17 1 +2861 1 17 0 +2862 1 16 1 +2863 1 16 0 +2864 4 16 0 +2865 4 16 1 +2866 4 17 0 +2867 4 17 1 +2868 5 16 0 +2869 5 16 1 +2870 5 17 0 +2871 5 17 1 +2872 7 17 1 +2873 7 17 0 +2874 7 16 1 +2875 7 16 0 +2876 6 17 1 +2877 6 17 0 +2878 6 16 1 +2879 6 16 0 +2880 12 17 0 +2881 12 17 1 +2882 12 16 0 +2883 12 16 1 +2884 13 17 0 +2885 13 17 1 +2886 13 16 0 +2887 13 16 1 +2888 15 16 1 +2889 15 16 0 +2890 15 17 1 +2891 15 17 0 +2892 14 16 1 +2893 14 16 0 +2894 14 17 1 +2895 14 17 0 +2944 11 15 0 +2945 11 15 1 +2946 11 14 0 +2947 11 14 1 +2948 10 15 0 +2949 10 15 1 +2950 10 14 0 +2951 10 14 1 +2952 8 14 1 +2953 8 14 0 +2954 8 15 1 +2955 8 15 0 +2956 9 14 1 +2957 9 14 0 +2958 9 15 1 +2959 9 15 0 +2976 3 14 0 +2977 3 14 1 +2978 3 15 0 +2979 3 15 1 +2980 2 14 0 +2981 2 14 1 +2982 2 15 0 +2983 2 15 1 +2984 0 15 1 +2985 0 15 0 +2986 0 14 1 +2987 0 14 0 +2988 1 15 1 +2989 1 15 0 +2990 1 14 1 +2991 1 14 0 +2992 4 14 0 +2993 4 14 1 +2994 4 15 0 +2995 4 15 1 +2996 5 14 0 +2997 5 14 1 +2998 5 15 0 +2999 5 15 1 +3000 7 15 1 +3001 7 15 0 +3002 7 14 1 +3003 7 14 0 +3004 6 15 1 +3005 6 15 0 +3006 6 14 1 +3007 6 14 0 +3008 12 15 0 +3009 12 15 1 +3010 12 14 0 +3011 12 14 1 +3012 13 15 0 +3013 13 15 1 +3014 13 14 0 +3015 13 14 1 +3016 15 14 1 +3017 15 14 0 +3018 15 15 1 +3019 15 15 0 +3020 14 14 1 +3021 14 14 0 +3022 14 15 1 +3023 14 15 0 +3072 11 13 0 +3073 11 13 1 +3074 11 12 0 +3075 11 12 1 +3076 10 13 0 +3077 10 13 1 +3078 10 12 0 +3079 10 12 1 +3080 8 12 1 +3081 8 12 0 +3082 8 13 1 +3083 8 13 0 +3084 9 12 1 +3085 9 12 0 +3086 9 13 1 +3087 9 13 0 +3104 3 12 0 +3105 3 12 1 +3106 3 13 0 +3107 3 13 1 +3108 2 12 0 +3109 2 12 1 +3110 2 13 0 +3111 2 13 1 +3112 0 13 1 +3113 0 13 0 +3114 0 12 1 +3115 0 12 0 +3116 1 13 1 +3117 1 13 0 +3118 1 12 1 +3119 1 12 0 +3120 4 12 0 +3121 4 12 1 +3122 4 13 0 +3123 4 13 1 +3124 5 12 0 +3125 5 12 1 +3126 5 13 0 +3127 5 13 1 +3128 7 13 1 +3129 7 13 0 +3130 7 12 1 +3131 7 12 0 +3132 6 13 1 +3133 6 13 0 +3134 6 12 1 +3135 6 12 0 +3136 12 13 0 +3137 12 13 1 +3138 12 12 0 +3139 12 12 1 +3140 13 13 0 +3141 13 13 1 +3142 13 12 0 +3143 13 12 1 +3144 15 12 1 +3145 15 12 0 +3146 15 13 1 +3147 15 13 0 +3148 14 12 1 +3149 14 12 0 +3150 14 13 1 +3151 14 13 0 +3200 11 11 0 +3201 11 11 1 +3202 11 10 0 +3203 11 10 1 +3204 10 11 0 +3205 10 11 1 +3206 10 10 0 +3207 10 10 1 +3208 8 10 1 +3209 8 10 0 +3210 8 11 1 +3211 8 11 0 +3212 9 10 1 +3213 9 10 0 +3214 9 11 1 +3215 9 11 0 +3232 3 10 0 +3233 3 10 1 +3234 3 11 0 +3235 3 11 1 +3236 2 10 0 +3237 2 10 1 +3238 2 11 0 +3239 2 11 1 +3240 0 11 1 +3241 0 11 0 +3242 0 10 1 +3243 0 10 0 +3244 1 11 1 +3245 1 11 0 +3246 1 10 1 +3247 1 10 0 +3248 4 10 0 +3249 4 10 1 +3250 4 11 0 +3251 4 11 1 +3252 5 10 0 +3253 5 10 1 +3254 5 11 0 +3255 5 11 1 +3256 7 11 1 +3257 7 11 0 +3258 7 10 1 +3259 7 10 0 +3260 6 11 1 +3261 6 11 0 +3262 6 10 1 +3263 6 10 0 +3264 12 11 0 +3265 12 11 1 +3266 12 10 0 +3267 12 10 1 +3268 13 11 0 +3269 13 11 1 +3270 13 10 0 +3271 13 10 1 +3272 15 10 1 +3273 15 10 0 +3274 15 11 1 +3275 15 11 0 +3276 14 10 1 +3277 14 10 0 +3278 14 11 1 +3279 14 11 0 +3328 11 9 0 +3329 11 9 1 +3330 11 8 0 +3331 11 8 1 +3332 10 9 0 +3333 10 9 1 +3334 10 8 0 +3335 10 8 1 +3336 8 8 1 +3337 8 8 0 +3338 8 9 1 +3339 8 9 0 +3340 9 8 1 +3341 9 8 0 +3342 9 9 1 +3343 9 9 0 +3360 3 8 0 +3361 3 8 1 +3362 3 9 0 +3363 3 9 1 +3364 2 8 0 +3365 2 8 1 +3366 2 9 0 +3367 2 9 1 +3368 0 9 1 +3369 0 9 0 +3370 0 8 1 +3371 0 8 0 +3372 1 9 1 +3373 1 9 0 +3374 1 8 1 +3375 1 8 0 +3376 4 8 0 +3377 4 8 1 +3378 4 9 0 +3379 4 9 1 +3380 5 8 0 +3381 5 8 1 +3382 5 9 0 +3383 5 9 1 +3384 7 9 1 +3385 7 9 0 +3386 7 8 1 +3387 7 8 0 +3388 6 9 1 +3389 6 9 0 +3390 6 8 1 +3391 6 8 0 +3392 12 9 0 +3393 12 9 1 +3394 12 8 0 +3395 12 8 1 +3396 13 9 0 +3397 13 9 1 +3398 13 8 0 +3399 13 8 1 +3400 15 8 1 +3401 15 8 0 +3402 15 9 1 +3403 15 9 0 +3404 14 8 1 +3405 14 8 0 +3406 14 9 1 +3407 14 9 0 +3456 11 7 0 +3457 11 7 1 +3458 11 6 0 +3459 11 6 1 +3460 10 7 0 +3461 10 7 1 +3462 10 6 0 +3463 10 6 1 +3464 8 6 1 +3465 8 6 0 +3466 8 7 1 +3467 8 7 0 +3468 9 6 1 +3469 9 6 0 +3470 9 7 1 +3471 9 7 0 +3488 3 6 0 +3489 3 6 1 +3490 3 7 0 +3491 3 7 1 +3492 2 6 0 +3493 2 6 1 +3494 2 7 0 +3495 2 7 1 +3496 0 7 1 +3497 0 7 0 +3498 0 6 1 +3499 0 6 0 +3500 1 7 1 +3501 1 7 0 +3502 1 6 1 +3503 1 6 0 +3504 4 6 0 +3505 4 6 1 +3506 4 7 0 +3507 4 7 1 +3508 5 6 0 +3509 5 6 1 +3510 5 7 0 +3511 5 7 1 +3512 7 7 1 +3513 7 7 0 +3514 7 6 1 +3515 7 6 0 +3516 6 7 1 +3517 6 7 0 +3518 6 6 1 +3519 6 6 0 +3520 12 7 0 +3521 12 7 1 +3522 12 6 0 +3523 12 6 1 +3524 13 7 0 +3525 13 7 1 +3526 13 6 0 +3527 13 6 1 +3528 15 6 1 +3529 15 6 0 +3530 15 7 1 +3531 15 7 0 +3532 14 6 1 +3533 14 6 0 +3534 14 7 1 +3535 14 7 0 +3584 11 5 0 +3585 11 5 1 +3586 11 4 0 +3587 11 4 1 +3588 10 5 0 +3589 10 5 1 +3590 10 4 0 +3591 10 4 1 +3592 8 4 1 +3593 8 4 0 +3594 8 5 1 +3595 8 5 0 +3596 9 4 1 +3597 9 4 0 +3598 9 5 1 +3599 9 5 0 +3616 3 4 0 +3617 3 4 1 +3618 3 5 0 +3619 3 5 1 +3620 2 4 0 +3621 2 4 1 +3622 2 5 0 +3623 2 5 1 +3624 0 5 1 +3625 0 5 0 +3626 0 4 1 +3627 0 4 0 +3628 1 5 1 +3629 1 5 0 +3630 1 4 1 +3631 1 4 0 +3632 4 4 0 +3633 4 4 1 +3634 4 5 0 +3635 4 5 1 +3636 5 4 0 +3637 5 4 1 +3638 5 5 0 +3639 5 5 1 +3640 7 5 1 +3641 7 5 0 +3642 7 4 1 +3643 7 4 0 +3644 6 5 1 +3645 6 5 0 +3646 6 4 1 +3647 6 4 0 +3648 12 5 0 +3649 12 5 1 +3650 12 4 0 +3651 12 4 1 +3652 13 5 0 +3653 13 5 1 +3654 13 4 0 +3655 13 4 1 +3656 15 4 1 +3657 15 4 0 +3658 15 5 1 +3659 15 5 0 +3660 14 4 1 +3661 14 4 0 +3662 14 5 1 +3663 14 5 0 +3712 11 3 0 +3713 11 3 1 +3714 11 2 0 +3715 11 2 1 +3716 10 3 0 +3717 10 3 1 +3718 10 2 0 +3719 10 2 1 +3720 8 2 1 +3721 8 2 0 +3722 8 3 1 +3723 8 3 0 +3724 9 2 1 +3725 9 2 0 +3726 9 3 1 +3727 9 3 0 +3744 3 2 0 +3745 3 2 1 +3746 3 3 0 +3747 3 3 1 +3748 2 2 0 +3749 2 2 1 +3750 2 3 0 +3751 2 3 1 +3752 0 3 1 +3753 0 3 0 +3754 0 2 1 +3755 0 2 0 +3756 1 3 1 +3757 1 3 0 +3758 1 2 1 +3759 1 2 0 +3760 4 2 0 +3761 4 2 1 +3762 4 3 0 +3763 4 3 1 +3764 5 2 0 +3765 5 2 1 +3766 5 3 0 +3767 5 3 1 +3768 7 3 1 +3769 7 3 0 +3770 7 2 1 +3771 7 2 0 +3772 6 3 1 +3773 6 3 0 +3774 6 2 1 +3775 6 2 0 +3776 12 3 0 +3777 12 3 1 +3778 12 2 0 +3779 12 2 1 +3780 13 3 0 +3781 13 3 1 +3782 13 2 0 +3783 13 2 1 +3784 15 2 1 +3785 15 2 0 +3786 15 3 1 +3787 15 3 0 +3788 14 2 1 +3789 14 2 0 +3790 14 3 1 +3791 14 3 0 +3840 11 1 0 +3841 11 1 1 +3842 11 0 0 +3843 11 0 1 +3844 10 1 0 +3845 10 1 1 +3846 10 0 0 +3847 10 0 1 +3848 8 0 1 +3849 8 0 0 +3850 8 1 1 +3851 8 1 0 +3852 9 0 1 +3853 9 0 0 +3854 9 1 1 +3855 9 1 0 +3872 3 0 0 +3873 3 0 1 +3874 3 1 0 +3875 3 1 1 +3876 2 0 0 +3877 2 0 1 +3878 2 1 0 +3879 2 1 1 +3880 0 1 1 +3881 0 1 0 +3882 0 0 1 +3883 0 0 0 +3884 1 1 1 +3885 1 1 0 +3886 1 0 1 +3887 1 0 0 +3888 4 0 0 +3889 4 0 1 +3890 4 1 0 +3891 4 1 1 +3892 5 0 0 +3893 5 0 1 +3894 5 1 0 +3895 5 1 1 +3896 7 1 1 +3897 7 1 0 +3898 7 0 1 +3899 7 0 0 +3900 6 1 1 +3901 6 1 0 +3902 6 0 1 +3903 6 0 0 +3904 12 1 0 +3905 12 1 1 +3906 12 0 0 +3907 12 0 1 +3908 13 1 0 +3909 13 1 1 +3910 13 0 0 +3911 13 0 1 +3912 15 0 1 +3913 15 0 0 +3914 15 1 1 +3915 15 1 0 +3916 14 0 1 +3917 14 0 0 +3918 14 1 1 +3919 14 1 0 diff --git a/Detectors/PHOS/base/files/Mod1RCU1.data b/Detectors/PHOS/base/files/Mod1RCU1.data new file mode 100644 index 0000000000000..db125226496cf --- /dev/null +++ b/Detectors/PHOS/base/files/Mod1RCU1.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 1 0 2 + 1 1 1 2 + 2 1 2 2 + 3 1 3 2 + 4 1 4 2 + 5 1 5 2 + 6 1 6 2 + 7 1 7 2 + 8 1 8 2 + 9 1 9 2 + 10 1 10 2 + 11 1 11 2 + 12 1 12 2 + 13 1 13 2 + 14 1 14 2 + 15 1 15 2 + 16 1 16 2 + 17 1 17 2 + 18 1 18 2 + 19 1 19 2 + 20 1 20 2 + 21 1 21 2 + 22 1 22 2 + 23 1 23 2 + 24 1 24 2 + 25 1 25 2 + 26 1 26 2 + 27 1 27 2 + 28 1 28 2 + 29 1 29 2 + 30 1 30 2 + 31 1 31 2 + 32 1 32 2 + 33 1 33 2 + 34 1 34 2 + 35 1 35 2 + 36 1 36 2 + 37 1 37 2 + 38 1 38 2 + 39 1 39 2 + 40 1 40 2 + 41 1 41 2 + 42 1 42 2 + 43 1 43 2 + 44 1 44 2 + 45 1 45 2 + 46 1 46 2 + 47 1 47 2 + 48 1 48 2 + 49 1 49 2 + 50 1 50 2 + 51 1 51 2 + 52 1 52 2 + 53 1 53 2 + 54 1 54 2 + 55 1 55 2 + 56 1 56 2 + 57 1 57 2 + 58 1 58 2 + 59 1 59 2 + 60 1 60 2 + 61 1 61 2 + 62 1 62 2 + 63 1 63 2 + 64 1 64 2 + 65 1 65 2 + 66 1 66 2 + 67 1 67 2 + 68 1 68 2 + 69 1 69 2 + 70 1 70 2 + 71 1 71 2 + 72 1 72 2 + 73 1 73 2 + 74 1 74 2 + 75 1 75 2 + 76 1 76 2 + 77 1 77 2 + 78 1 78 2 + 79 1 79 2 + 80 1 80 2 + 81 1 81 2 + 82 1 82 2 + 83 1 83 2 + 84 1 84 2 + 85 1 85 2 + 86 1 86 2 + 87 1 87 2 + 88 1 88 2 + 89 1 89 2 + 90 1 90 2 + 91 1 91 2 + 92 1 92 2 + 93 1 93 2 + 94 1 94 2 + 95 1 95 2 + 96 1 96 2 + 97 1 97 2 + 98 1 98 2 + 99 1 99 2 + 100 1 100 2 + 101 1 101 2 + 102 1 102 2 + 103 1 103 2 + 104 1 104 2 + 105 1 105 2 + 106 1 106 2 + 107 1 107 2 + 108 1 108 2 + 109 1 109 2 + 110 1 110 2 + 111 1 111 2 + 112 1 112 2 + 113 1 113 2 + 114 1 114 2 + 115 1 115 2 + 116 1 116 2 + 117 1 117 2 + 118 1 118 2 + 119 1 119 2 + 120 1 120 2 + 121 1 121 2 + 122 1 122 2 + 123 1 123 2 + 124 1 124 2 + 125 1 125 2 + 126 1 126 2 + 127 1 127 2 +2048 1 2048 2 +2049 1 2049 2 +2050 1 2050 2 +2051 1 2051 2 +2052 1 2052 2 +2053 1 2053 2 +2054 1 2054 2 +2055 1 2055 2 +2056 1 2056 2 +2057 1 2057 2 +2058 1 2058 2 +2059 1 2059 2 +2060 1 2060 2 +2061 1 2061 2 +2062 1 2062 2 +2063 1 2063 2 +2064 1 2064 2 +2065 1 2065 2 +2066 1 2066 2 +2067 1 2067 2 +2068 1 2068 2 +2069 1 2069 2 +2070 1 2070 2 +2071 1 2071 2 +2072 1 2072 2 +2073 1 2073 2 +2074 1 2074 2 +2075 1 2075 2 +2076 1 2076 2 +2077 1 2077 2 +2078 1 2078 2 +2079 1 2079 2 +2080 1 2080 2 +2081 1 2081 2 +2082 1 2082 2 +2083 1 2083 2 +2084 1 2084 2 +2085 1 2085 2 +2086 1 2086 2 +2087 1 2087 2 +2088 1 2088 2 +2089 1 2089 2 +2090 1 2090 2 +2091 1 2091 2 +2092 1 2092 2 +2093 1 2093 2 +2094 1 2094 2 +2095 1 2095 2 +2096 1 2096 2 +2097 1 2097 2 +2098 1 2098 2 +2099 1 2099 2 +2100 1 2100 2 +2101 1 2101 2 +2102 1 2102 2 +2103 1 2103 2 +2104 1 2104 2 +2105 1 2105 2 +2106 1 2106 2 +2107 1 2107 2 +2108 1 2108 2 +2109 1 2109 2 +2110 1 2110 2 +2111 1 2111 2 +2112 1 2112 2 +2113 1 2113 2 +2114 1 2114 2 +2115 1 2115 2 +2116 1 2116 2 +2117 1 2117 2 +2118 1 2118 2 +2119 1 2119 2 +2120 1 2120 2 +2121 1 2121 2 +2122 1 2122 2 +2123 1 2123 2 +2124 1 2124 2 +2125 1 2125 2 +2126 1 2126 2 +2127 1 2127 2 +2128 1 2128 2 +2129 1 2129 2 +2130 1 2130 2 +2131 1 2131 2 +2132 1 2132 2 +2133 1 2133 2 +2134 1 2134 2 +2135 1 2135 2 +2136 1 2136 2 +2137 1 2137 2 +2138 1 2138 2 +2139 1 2139 2 +2140 1 2140 2 +2141 1 2141 2 +2142 1 2142 2 +2143 1 2143 2 +2144 1 2144 2 +2145 1 2145 2 +2146 1 2146 2 +2147 1 2147 2 +2148 1 2148 2 +2149 1 2149 2 +2150 1 2150 2 +2151 1 2151 2 +2152 1 2152 2 +2153 1 2153 2 +2154 1 2154 2 +2155 1 2155 2 +2156 1 2156 2 +2157 1 2157 2 +2158 1 2158 2 +2159 1 2159 2 +2160 1 2160 2 +2161 1 2161 2 +2162 1 2162 2 +2163 1 2163 2 +2164 1 2164 2 +2165 1 2165 2 +2166 1 2166 2 +2167 1 2167 2 +2168 1 2168 2 +2169 1 2169 2 +2170 1 2170 2 +2171 1 2171 2 +2172 1 2172 2 +2173 1 2173 2 +2174 1 2174 2 +2175 1 2175 2 + 128 27 29 0 + 129 27 29 1 + 130 27 28 0 + 131 27 28 1 + 132 26 29 0 + 133 26 29 1 + 134 26 28 0 + 135 26 28 1 + 136 24 28 1 + 137 24 28 0 + 138 24 29 1 + 139 24 29 0 + 140 25 28 1 + 141 25 28 0 + 142 25 29 1 + 143 25 29 0 + 160 19 28 0 + 161 19 28 1 + 162 19 29 0 + 163 19 29 1 + 164 18 28 0 + 165 18 28 1 + 166 18 29 0 + 167 18 29 1 + 168 16 29 1 + 169 16 29 0 + 170 16 28 1 + 171 16 28 0 + 172 17 29 1 + 173 17 29 0 + 174 17 28 1 + 175 17 28 0 + 176 20 28 0 + 177 20 28 1 + 178 20 29 0 + 179 20 29 1 + 180 21 28 0 + 181 21 28 1 + 182 21 29 0 + 183 21 29 1 + 184 23 29 1 + 185 23 29 0 + 186 23 28 1 + 187 23 28 0 + 188 22 29 1 + 189 22 29 0 + 190 22 28 1 + 191 22 28 0 + 192 28 29 0 + 193 28 29 1 + 194 28 28 0 + 195 28 28 1 + 196 29 29 0 + 197 29 29 1 + 198 29 28 0 + 199 29 28 1 + 200 31 28 1 + 201 31 28 0 + 202 31 29 1 + 203 31 29 0 + 204 30 28 1 + 205 30 28 0 + 206 30 29 1 + 207 30 29 0 + 256 27 31 0 + 257 27 31 1 + 258 27 30 0 + 259 27 30 1 + 260 26 31 0 + 261 26 31 1 + 262 26 30 0 + 263 26 30 1 + 264 24 30 1 + 265 24 30 0 + 266 24 31 1 + 267 24 31 0 + 268 25 30 1 + 269 25 30 0 + 270 25 31 1 + 271 25 31 0 + 288 19 30 0 + 289 19 30 1 + 290 19 31 0 + 291 19 31 1 + 292 18 30 0 + 293 18 30 1 + 294 18 31 0 + 295 18 31 1 + 296 16 31 1 + 297 16 31 0 + 298 16 30 1 + 299 16 30 0 + 300 17 31 1 + 301 17 31 0 + 302 17 30 1 + 303 17 30 0 + 304 20 30 0 + 305 20 30 1 + 306 20 31 0 + 307 20 31 1 + 308 21 30 0 + 309 21 30 1 + 310 21 31 0 + 311 21 31 1 + 312 23 31 1 + 313 23 31 0 + 314 23 30 1 + 315 23 30 0 + 316 22 31 1 + 317 22 31 0 + 318 22 30 1 + 319 22 30 0 + 320 28 31 0 + 321 28 31 1 + 322 28 30 0 + 323 28 30 1 + 324 29 31 0 + 325 29 31 1 + 326 29 30 0 + 327 29 30 1 + 328 31 30 1 + 329 31 30 0 + 330 31 31 1 + 331 31 31 0 + 332 30 30 1 + 333 30 30 0 + 334 30 31 1 + 335 30 31 0 + 384 27 33 0 + 385 27 33 1 + 386 27 32 0 + 387 27 32 1 + 388 26 33 0 + 389 26 33 1 + 390 26 32 0 + 391 26 32 1 + 392 24 32 1 + 393 24 32 0 + 394 24 33 1 + 395 24 33 0 + 396 25 32 1 + 397 25 32 0 + 398 25 33 1 + 399 25 33 0 + 416 19 32 0 + 417 19 32 1 + 418 19 33 0 + 419 19 33 1 + 420 18 32 0 + 421 18 32 1 + 422 18 33 0 + 423 18 33 1 + 424 16 33 1 + 425 16 33 0 + 426 16 32 1 + 427 16 32 0 + 428 17 33 1 + 429 17 33 0 + 430 17 32 1 + 431 17 32 0 + 432 20 32 0 + 433 20 32 1 + 434 20 33 0 + 435 20 33 1 + 436 21 32 0 + 437 21 32 1 + 438 21 33 0 + 439 21 33 1 + 440 23 33 1 + 441 23 33 0 + 442 23 32 1 + 443 23 32 0 + 444 22 33 1 + 445 22 33 0 + 446 22 32 1 + 447 22 32 0 + 448 28 33 0 + 449 28 33 1 + 450 28 32 0 + 451 28 32 1 + 452 29 33 0 + 453 29 33 1 + 454 29 32 0 + 455 29 32 1 + 456 31 32 1 + 457 31 32 0 + 458 31 33 1 + 459 31 33 0 + 460 30 32 1 + 461 30 32 0 + 462 30 33 1 + 463 30 33 0 + 512 27 35 0 + 513 27 35 1 + 514 27 34 0 + 515 27 34 1 + 516 26 35 0 + 517 26 35 1 + 518 26 34 0 + 519 26 34 1 + 520 24 34 1 + 521 24 34 0 + 522 24 35 1 + 523 24 35 0 + 524 25 34 1 + 525 25 34 0 + 526 25 35 1 + 527 25 35 0 + 544 19 34 0 + 545 19 34 1 + 546 19 35 0 + 547 19 35 1 + 548 18 34 0 + 549 18 34 1 + 550 18 35 0 + 551 18 35 1 + 552 16 35 1 + 553 16 35 0 + 554 16 34 1 + 555 16 34 0 + 556 17 35 1 + 557 17 35 0 + 558 17 34 1 + 559 17 34 0 + 560 20 34 0 + 561 20 34 1 + 562 20 35 0 + 563 20 35 1 + 564 21 34 0 + 565 21 34 1 + 566 21 35 0 + 567 21 35 1 + 568 23 35 1 + 569 23 35 0 + 570 23 34 1 + 571 23 34 0 + 572 22 35 1 + 573 22 35 0 + 574 22 34 1 + 575 22 34 0 + 576 28 35 0 + 577 28 35 1 + 578 28 34 0 + 579 28 34 1 + 580 29 35 0 + 581 29 35 1 + 582 29 34 0 + 583 29 34 1 + 584 31 34 1 + 585 31 34 0 + 586 31 35 1 + 587 31 35 0 + 588 30 34 1 + 589 30 34 0 + 590 30 35 1 + 591 30 35 0 + 640 27 37 0 + 641 27 37 1 + 642 27 36 0 + 643 27 36 1 + 644 26 37 0 + 645 26 37 1 + 646 26 36 0 + 647 26 36 1 + 648 24 36 1 + 649 24 36 0 + 650 24 37 1 + 651 24 37 0 + 652 25 36 1 + 653 25 36 0 + 654 25 37 1 + 655 25 37 0 + 672 19 36 0 + 673 19 36 1 + 674 19 37 0 + 675 19 37 1 + 676 18 36 0 + 677 18 36 1 + 678 18 37 0 + 679 18 37 1 + 680 16 37 1 + 681 16 37 0 + 682 16 36 1 + 683 16 36 0 + 684 17 37 1 + 685 17 37 0 + 686 17 36 1 + 687 17 36 0 + 688 20 36 0 + 689 20 36 1 + 690 20 37 0 + 691 20 37 1 + 692 21 36 0 + 693 21 36 1 + 694 21 37 0 + 695 21 37 1 + 696 23 37 1 + 697 23 37 0 + 698 23 36 1 + 699 23 36 0 + 700 22 37 1 + 701 22 37 0 + 702 22 36 1 + 703 22 36 0 + 704 28 37 0 + 705 28 37 1 + 706 28 36 0 + 707 28 36 1 + 708 29 37 0 + 709 29 37 1 + 710 29 36 0 + 711 29 36 1 + 712 31 36 1 + 713 31 36 0 + 714 31 37 1 + 715 31 37 0 + 716 30 36 1 + 717 30 36 0 + 718 30 37 1 + 719 30 37 0 + 768 27 39 0 + 769 27 39 1 + 770 27 38 0 + 771 27 38 1 + 772 26 39 0 + 773 26 39 1 + 774 26 38 0 + 775 26 38 1 + 776 24 38 1 + 777 24 38 0 + 778 24 39 1 + 779 24 39 0 + 780 25 38 1 + 781 25 38 0 + 782 25 39 1 + 783 25 39 0 + 800 19 38 0 + 801 19 38 1 + 802 19 39 0 + 803 19 39 1 + 804 18 38 0 + 805 18 38 1 + 806 18 39 0 + 807 18 39 1 + 808 16 39 1 + 809 16 39 0 + 810 16 38 1 + 811 16 38 0 + 812 17 39 1 + 813 17 39 0 + 814 17 38 1 + 815 17 38 0 + 816 20 38 0 + 817 20 38 1 + 818 20 39 0 + 819 20 39 1 + 820 21 38 0 + 821 21 38 1 + 822 21 39 0 + 823 21 39 1 + 824 23 39 1 + 825 23 39 0 + 826 23 38 1 + 827 23 38 0 + 828 22 39 1 + 829 22 39 0 + 830 22 38 1 + 831 22 38 0 + 832 28 39 0 + 833 28 39 1 + 834 28 38 0 + 835 28 38 1 + 836 29 39 0 + 837 29 39 1 + 838 29 38 0 + 839 29 38 1 + 840 31 38 1 + 841 31 38 0 + 842 31 39 1 + 843 31 39 0 + 844 30 38 1 + 845 30 38 0 + 846 30 39 1 + 847 30 39 0 + 896 27 41 0 + 897 27 41 1 + 898 27 40 0 + 899 27 40 1 + 900 26 41 0 + 901 26 41 1 + 902 26 40 0 + 903 26 40 1 + 904 24 40 1 + 905 24 40 0 + 906 24 41 1 + 907 24 41 0 + 908 25 40 1 + 909 25 40 0 + 910 25 41 1 + 911 25 41 0 + 928 19 40 0 + 929 19 40 1 + 930 19 41 0 + 931 19 41 1 + 932 18 40 0 + 933 18 40 1 + 934 18 41 0 + 935 18 41 1 + 936 16 41 1 + 937 16 41 0 + 938 16 40 1 + 939 16 40 0 + 940 17 41 1 + 941 17 41 0 + 942 17 40 1 + 943 17 40 0 + 944 20 40 0 + 945 20 40 1 + 946 20 41 0 + 947 20 41 1 + 948 21 40 0 + 949 21 40 1 + 950 21 41 0 + 951 21 41 1 + 952 23 41 1 + 953 23 41 0 + 954 23 40 1 + 955 23 40 0 + 956 22 41 1 + 957 22 41 0 + 958 22 40 1 + 959 22 40 0 + 960 28 41 0 + 961 28 41 1 + 962 28 40 0 + 963 28 40 1 + 964 29 41 0 + 965 29 41 1 + 966 29 40 0 + 967 29 40 1 + 968 31 40 1 + 969 31 40 0 + 970 31 41 1 + 971 31 41 0 + 972 30 40 1 + 973 30 40 0 + 974 30 41 1 + 975 30 41 0 +1024 27 43 0 +1025 27 43 1 +1026 27 42 0 +1027 27 42 1 +1028 26 43 0 +1029 26 43 1 +1030 26 42 0 +1031 26 42 1 +1032 24 42 1 +1033 24 42 0 +1034 24 43 1 +1035 24 43 0 +1036 25 42 1 +1037 25 42 0 +1038 25 43 1 +1039 25 43 0 +1056 19 42 0 +1057 19 42 1 +1058 19 43 0 +1059 19 43 1 +1060 18 42 0 +1061 18 42 1 +1062 18 43 0 +1063 18 43 1 +1064 16 43 1 +1065 16 43 0 +1066 16 42 1 +1067 16 42 0 +1068 17 43 1 +1069 17 43 0 +1070 17 42 1 +1071 17 42 0 +1072 20 42 0 +1073 20 42 1 +1074 20 43 0 +1075 20 43 1 +1076 21 42 0 +1077 21 42 1 +1078 21 43 0 +1079 21 43 1 +1080 23 43 1 +1081 23 43 0 +1082 23 42 1 +1083 23 42 0 +1084 22 43 1 +1085 22 43 0 +1086 22 42 1 +1087 22 42 0 +1088 28 43 0 +1089 28 43 1 +1090 28 42 0 +1091 28 42 1 +1092 29 43 0 +1093 29 43 1 +1094 29 42 0 +1095 29 42 1 +1096 31 42 1 +1097 31 42 0 +1098 31 43 1 +1099 31 43 0 +1100 30 42 1 +1101 30 42 0 +1102 30 43 1 +1103 30 43 0 +1152 27 45 0 +1153 27 45 1 +1154 27 44 0 +1155 27 44 1 +1156 26 45 0 +1157 26 45 1 +1158 26 44 0 +1159 26 44 1 +1160 24 44 1 +1161 24 44 0 +1162 24 45 1 +1163 24 45 0 +1164 25 44 1 +1165 25 44 0 +1166 25 45 1 +1167 25 45 0 +1184 19 44 0 +1185 19 44 1 +1186 19 45 0 +1187 19 45 1 +1188 18 44 0 +1189 18 44 1 +1190 18 45 0 +1191 18 45 1 +1192 16 45 1 +1193 16 45 0 +1194 16 44 1 +1195 16 44 0 +1196 17 45 1 +1197 17 45 0 +1198 17 44 1 +1199 17 44 0 +1200 20 44 0 +1201 20 44 1 +1202 20 45 0 +1203 20 45 1 +1204 21 44 0 +1205 21 44 1 +1206 21 45 0 +1207 21 45 1 +1208 23 45 1 +1209 23 45 0 +1210 23 44 1 +1211 23 44 0 +1212 22 45 1 +1213 22 45 0 +1214 22 44 1 +1215 22 44 0 +1216 28 45 0 +1217 28 45 1 +1218 28 44 0 +1219 28 44 1 +1220 29 45 0 +1221 29 45 1 +1222 29 44 0 +1223 29 44 1 +1224 31 44 1 +1225 31 44 0 +1226 31 45 1 +1227 31 45 0 +1228 30 44 1 +1229 30 44 0 +1230 30 45 1 +1231 30 45 0 +1280 27 47 0 +1281 27 47 1 +1282 27 46 0 +1283 27 46 1 +1284 26 47 0 +1285 26 47 1 +1286 26 46 0 +1287 26 46 1 +1288 24 46 1 +1289 24 46 0 +1290 24 47 1 +1291 24 47 0 +1292 25 46 1 +1293 25 46 0 +1294 25 47 1 +1295 25 47 0 +1312 19 46 0 +1313 19 46 1 +1314 19 47 0 +1315 19 47 1 +1316 18 46 0 +1317 18 46 1 +1318 18 47 0 +1319 18 47 1 +1320 16 47 1 +1321 16 47 0 +1322 16 46 1 +1323 16 46 0 +1324 17 47 1 +1325 17 47 0 +1326 17 46 1 +1327 17 46 0 +1328 20 46 0 +1329 20 46 1 +1330 20 47 0 +1331 20 47 1 +1332 21 46 0 +1333 21 46 1 +1334 21 47 0 +1335 21 47 1 +1336 23 47 1 +1337 23 47 0 +1338 23 46 1 +1339 23 46 0 +1340 22 47 1 +1341 22 47 0 +1342 22 46 1 +1343 22 46 0 +1344 28 47 0 +1345 28 47 1 +1346 28 46 0 +1347 28 46 1 +1348 29 47 0 +1349 29 47 1 +1350 29 46 0 +1351 29 46 1 +1352 31 46 1 +1353 31 46 0 +1354 31 47 1 +1355 31 47 0 +1356 30 46 1 +1357 30 46 0 +1358 30 47 1 +1359 30 47 0 +1408 27 49 0 +1409 27 49 1 +1410 27 48 0 +1411 27 48 1 +1412 26 49 0 +1413 26 49 1 +1414 26 48 0 +1415 26 48 1 +1416 24 48 1 +1417 24 48 0 +1418 24 49 1 +1419 24 49 0 +1420 25 48 1 +1421 25 48 0 +1422 25 49 1 +1423 25 49 0 +1440 19 48 0 +1441 19 48 1 +1442 19 49 0 +1443 19 49 1 +1444 18 48 0 +1445 18 48 1 +1446 18 49 0 +1447 18 49 1 +1448 16 49 1 +1449 16 49 0 +1450 16 48 1 +1451 16 48 0 +1452 17 49 1 +1453 17 49 0 +1454 17 48 1 +1455 17 48 0 +1456 20 48 0 +1457 20 48 1 +1458 20 49 0 +1459 20 49 1 +1460 21 48 0 +1461 21 48 1 +1462 21 49 0 +1463 21 49 1 +1464 23 49 1 +1465 23 49 0 +1466 23 48 1 +1467 23 48 0 +1468 22 49 1 +1469 22 49 0 +1470 22 48 1 +1471 22 48 0 +1472 28 49 0 +1473 28 49 1 +1474 28 48 0 +1475 28 48 1 +1476 29 49 0 +1477 29 49 1 +1478 29 48 0 +1479 29 48 1 +1480 31 48 1 +1481 31 48 0 +1482 31 49 1 +1483 31 49 0 +1484 30 48 1 +1485 30 48 0 +1486 30 49 1 +1487 30 49 0 +1536 27 51 0 +1537 27 51 1 +1538 27 50 0 +1539 27 50 1 +1540 26 51 0 +1541 26 51 1 +1542 26 50 0 +1543 26 50 1 +1544 24 50 1 +1545 24 50 0 +1546 24 51 1 +1547 24 51 0 +1548 25 50 1 +1549 25 50 0 +1550 25 51 1 +1551 25 51 0 +1568 19 50 0 +1569 19 50 1 +1570 19 51 0 +1571 19 51 1 +1572 18 50 0 +1573 18 50 1 +1574 18 51 0 +1575 18 51 1 +1576 16 51 1 +1577 16 51 0 +1578 16 50 1 +1579 16 50 0 +1580 17 51 1 +1581 17 51 0 +1582 17 50 1 +1583 17 50 0 +1584 20 50 0 +1585 20 50 1 +1586 20 51 0 +1587 20 51 1 +1588 21 50 0 +1589 21 50 1 +1590 21 51 0 +1591 21 51 1 +1592 23 51 1 +1593 23 51 0 +1594 23 50 1 +1595 23 50 0 +1596 22 51 1 +1597 22 51 0 +1598 22 50 1 +1599 22 50 0 +1600 28 51 0 +1601 28 51 1 +1602 28 50 0 +1603 28 50 1 +1604 29 51 0 +1605 29 51 1 +1606 29 50 0 +1607 29 50 1 +1608 31 50 1 +1609 31 50 0 +1610 31 51 1 +1611 31 51 0 +1612 30 50 1 +1613 30 50 0 +1614 30 51 1 +1615 30 51 0 +1664 27 53 0 +1665 27 53 1 +1666 27 52 0 +1667 27 52 1 +1668 26 53 0 +1669 26 53 1 +1670 26 52 0 +1671 26 52 1 +1672 24 52 1 +1673 24 52 0 +1674 24 53 1 +1675 24 53 0 +1676 25 52 1 +1677 25 52 0 +1678 25 53 1 +1679 25 53 0 +1696 19 52 0 +1697 19 52 1 +1698 19 53 0 +1699 19 53 1 +1700 18 52 0 +1701 18 52 1 +1702 18 53 0 +1703 18 53 1 +1704 16 53 1 +1705 16 53 0 +1706 16 52 1 +1707 16 52 0 +1708 17 53 1 +1709 17 53 0 +1710 17 52 1 +1711 17 52 0 +1712 20 52 0 +1713 20 52 1 +1714 20 53 0 +1715 20 53 1 +1716 21 52 0 +1717 21 52 1 +1718 21 53 0 +1719 21 53 1 +1720 23 53 1 +1721 23 53 0 +1722 23 52 1 +1723 23 52 0 +1724 22 53 1 +1725 22 53 0 +1726 22 52 1 +1727 22 52 0 +1728 28 53 0 +1729 28 53 1 +1730 28 52 0 +1731 28 52 1 +1732 29 53 0 +1733 29 53 1 +1734 29 52 0 +1735 29 52 1 +1736 31 52 1 +1737 31 52 0 +1738 31 53 1 +1739 31 53 0 +1740 30 52 1 +1741 30 52 0 +1742 30 53 1 +1743 30 53 0 +1792 27 55 0 +1793 27 55 1 +1794 27 54 0 +1795 27 54 1 +1796 26 55 0 +1797 26 55 1 +1798 26 54 0 +1799 26 54 1 +1800 24 54 1 +1801 24 54 0 +1802 24 55 1 +1803 24 55 0 +1804 25 54 1 +1805 25 54 0 +1806 25 55 1 +1807 25 55 0 +1824 19 54 0 +1825 19 54 1 +1826 19 55 0 +1827 19 55 1 +1828 18 54 0 +1829 18 54 1 +1830 18 55 0 +1831 18 55 1 +1832 16 55 1 +1833 16 55 0 +1834 16 54 1 +1835 16 54 0 +1836 17 55 1 +1837 17 55 0 +1838 17 54 1 +1839 17 54 0 +1840 20 54 0 +1841 20 54 1 +1842 20 55 0 +1843 20 55 1 +1844 21 54 0 +1845 21 54 1 +1846 21 55 0 +1847 21 55 1 +1848 23 55 1 +1849 23 55 0 +1850 23 54 1 +1851 23 54 0 +1852 22 55 1 +1853 22 55 0 +1854 22 54 1 +1855 22 54 0 +1856 28 55 0 +1857 28 55 1 +1858 28 54 0 +1859 28 54 1 +1860 29 55 0 +1861 29 55 1 +1862 29 54 0 +1863 29 54 1 +1864 31 54 1 +1865 31 54 0 +1866 31 55 1 +1867 31 55 0 +1868 30 54 1 +1869 30 54 0 +1870 30 55 1 +1871 30 55 0 +2176 27 27 0 +2177 27 27 1 +2178 27 26 0 +2179 27 26 1 +2180 26 27 0 +2181 26 27 1 +2182 26 26 0 +2183 26 26 1 +2184 24 26 1 +2185 24 26 0 +2186 24 27 1 +2187 24 27 0 +2188 25 26 1 +2189 25 26 0 +2190 25 27 1 +2191 25 27 0 +2208 19 26 0 +2209 19 26 1 +2210 19 27 0 +2211 19 27 1 +2212 18 26 0 +2213 18 26 1 +2214 18 27 0 +2215 18 27 1 +2216 16 27 1 +2217 16 27 0 +2218 16 26 1 +2219 16 26 0 +2220 17 27 1 +2221 17 27 0 +2222 17 26 1 +2223 17 26 0 +2224 20 26 0 +2225 20 26 1 +2226 20 27 0 +2227 20 27 1 +2228 21 26 0 +2229 21 26 1 +2230 21 27 0 +2231 21 27 1 +2232 23 27 1 +2233 23 27 0 +2234 23 26 1 +2235 23 26 0 +2236 22 27 1 +2237 22 27 0 +2238 22 26 1 +2239 22 26 0 +2240 28 27 0 +2241 28 27 1 +2242 28 26 0 +2243 28 26 1 +2244 29 27 0 +2245 29 27 1 +2246 29 26 0 +2247 29 26 1 +2248 31 26 1 +2249 31 26 0 +2250 31 27 1 +2251 31 27 0 +2252 30 26 1 +2253 30 26 0 +2254 30 27 1 +2255 30 27 0 +2304 27 25 0 +2305 27 25 1 +2306 27 24 0 +2307 27 24 1 +2308 26 25 0 +2309 26 25 1 +2310 26 24 0 +2311 26 24 1 +2312 24 24 1 +2313 24 24 0 +2314 24 25 1 +2315 24 25 0 +2316 25 24 1 +2317 25 24 0 +2318 25 25 1 +2319 25 25 0 +2336 19 24 0 +2337 19 24 1 +2338 19 25 0 +2339 19 25 1 +2340 18 24 0 +2341 18 24 1 +2342 18 25 0 +2343 18 25 1 +2344 16 25 1 +2345 16 25 0 +2346 16 24 1 +2347 16 24 0 +2348 17 25 1 +2349 17 25 0 +2350 17 24 1 +2351 17 24 0 +2352 20 24 0 +2353 20 24 1 +2354 20 25 0 +2355 20 25 1 +2356 21 24 0 +2357 21 24 1 +2358 21 25 0 +2359 21 25 1 +2360 23 25 1 +2361 23 25 0 +2362 23 24 1 +2363 23 24 0 +2364 22 25 1 +2365 22 25 0 +2366 22 24 1 +2367 22 24 0 +2368 28 25 0 +2369 28 25 1 +2370 28 24 0 +2371 28 24 1 +2372 29 25 0 +2373 29 25 1 +2374 29 24 0 +2375 29 24 1 +2376 31 24 1 +2377 31 24 0 +2378 31 25 1 +2379 31 25 0 +2380 30 24 1 +2381 30 24 0 +2382 30 25 1 +2383 30 25 0 +2432 27 23 0 +2433 27 23 1 +2434 27 22 0 +2435 27 22 1 +2436 26 23 0 +2437 26 23 1 +2438 26 22 0 +2439 26 22 1 +2440 24 22 1 +2441 24 22 0 +2442 24 23 1 +2443 24 23 0 +2444 25 22 1 +2445 25 22 0 +2446 25 23 1 +2447 25 23 0 +2464 19 22 0 +2465 19 22 1 +2466 19 23 0 +2467 19 23 1 +2468 18 22 0 +2469 18 22 1 +2470 18 23 0 +2471 18 23 1 +2472 16 23 1 +2473 16 23 0 +2474 16 22 1 +2475 16 22 0 +2476 17 23 1 +2477 17 23 0 +2478 17 22 1 +2479 17 22 0 +2480 20 22 0 +2481 20 22 1 +2482 20 23 0 +2483 20 23 1 +2484 21 22 0 +2485 21 22 1 +2486 21 23 0 +2487 21 23 1 +2488 23 23 1 +2489 23 23 0 +2490 23 22 1 +2491 23 22 0 +2492 22 23 1 +2493 22 23 0 +2494 22 22 1 +2495 22 22 0 +2496 28 23 0 +2497 28 23 1 +2498 28 22 0 +2499 28 22 1 +2500 29 23 0 +2501 29 23 1 +2502 29 22 0 +2503 29 22 1 +2504 31 22 1 +2505 31 22 0 +2506 31 23 1 +2507 31 23 0 +2508 30 22 1 +2509 30 22 0 +2510 30 23 1 +2511 30 23 0 +2560 27 21 0 +2561 27 21 1 +2562 27 20 0 +2563 27 20 1 +2564 26 21 0 +2565 26 21 1 +2566 26 20 0 +2567 26 20 1 +2568 24 20 1 +2569 24 20 0 +2570 24 21 1 +2571 24 21 0 +2572 25 20 1 +2573 25 20 0 +2574 25 21 1 +2575 25 21 0 +2592 19 20 0 +2593 19 20 1 +2594 19 21 0 +2595 19 21 1 +2596 18 20 0 +2597 18 20 1 +2598 18 21 0 +2599 18 21 1 +2600 16 21 1 +2601 16 21 0 +2602 16 20 1 +2603 16 20 0 +2604 17 21 1 +2605 17 21 0 +2606 17 20 1 +2607 17 20 0 +2608 20 20 0 +2609 20 20 1 +2610 20 21 0 +2611 20 21 1 +2612 21 20 0 +2613 21 20 1 +2614 21 21 0 +2615 21 21 1 +2616 23 21 1 +2617 23 21 0 +2618 23 20 1 +2619 23 20 0 +2620 22 21 1 +2621 22 21 0 +2622 22 20 1 +2623 22 20 0 +2624 28 21 0 +2625 28 21 1 +2626 28 20 0 +2627 28 20 1 +2628 29 21 0 +2629 29 21 1 +2630 29 20 0 +2631 29 20 1 +2632 31 20 1 +2633 31 20 0 +2634 31 21 1 +2635 31 21 0 +2636 30 20 1 +2637 30 20 0 +2638 30 21 1 +2639 30 21 0 +2688 27 19 0 +2689 27 19 1 +2690 27 18 0 +2691 27 18 1 +2692 26 19 0 +2693 26 19 1 +2694 26 18 0 +2695 26 18 1 +2696 24 18 1 +2697 24 18 0 +2698 24 19 1 +2699 24 19 0 +2700 25 18 1 +2701 25 18 0 +2702 25 19 1 +2703 25 19 0 +2720 19 18 0 +2721 19 18 1 +2722 19 19 0 +2723 19 19 1 +2724 18 18 0 +2725 18 18 1 +2726 18 19 0 +2727 18 19 1 +2728 16 19 1 +2729 16 19 0 +2730 16 18 1 +2731 16 18 0 +2732 17 19 1 +2733 17 19 0 +2734 17 18 1 +2735 17 18 0 +2736 20 18 0 +2737 20 18 1 +2738 20 19 0 +2739 20 19 1 +2740 21 18 0 +2741 21 18 1 +2742 21 19 0 +2743 21 19 1 +2744 23 19 1 +2745 23 19 0 +2746 23 18 1 +2747 23 18 0 +2748 22 19 1 +2749 22 19 0 +2750 22 18 1 +2751 22 18 0 +2752 28 19 0 +2753 28 19 1 +2754 28 18 0 +2755 28 18 1 +2756 29 19 0 +2757 29 19 1 +2758 29 18 0 +2759 29 18 1 +2760 31 18 1 +2761 31 18 0 +2762 31 19 1 +2763 31 19 0 +2764 30 18 1 +2765 30 18 0 +2766 30 19 1 +2767 30 19 0 +2816 27 17 0 +2817 27 17 1 +2818 27 16 0 +2819 27 16 1 +2820 26 17 0 +2821 26 17 1 +2822 26 16 0 +2823 26 16 1 +2824 24 16 1 +2825 24 16 0 +2826 24 17 1 +2827 24 17 0 +2828 25 16 1 +2829 25 16 0 +2830 25 17 1 +2831 25 17 0 +2848 19 16 0 +2849 19 16 1 +2850 19 17 0 +2851 19 17 1 +2852 18 16 0 +2853 18 16 1 +2854 18 17 0 +2855 18 17 1 +2856 16 17 1 +2857 16 17 0 +2858 16 16 1 +2859 16 16 0 +2860 17 17 1 +2861 17 17 0 +2862 17 16 1 +2863 17 16 0 +2864 20 16 0 +2865 20 16 1 +2866 20 17 0 +2867 20 17 1 +2868 21 16 0 +2869 21 16 1 +2870 21 17 0 +2871 21 17 1 +2872 23 17 1 +2873 23 17 0 +2874 23 16 1 +2875 23 16 0 +2876 22 17 1 +2877 22 17 0 +2878 22 16 1 +2879 22 16 0 +2880 28 17 0 +2881 28 17 1 +2882 28 16 0 +2883 28 16 1 +2884 29 17 0 +2885 29 17 1 +2886 29 16 0 +2887 29 16 1 +2888 31 16 1 +2889 31 16 0 +2890 31 17 1 +2891 31 17 0 +2892 30 16 1 +2893 30 16 0 +2894 30 17 1 +2895 30 17 0 +2944 27 15 0 +2945 27 15 1 +2946 27 14 0 +2947 27 14 1 +2948 26 15 0 +2949 26 15 1 +2950 26 14 0 +2951 26 14 1 +2952 24 14 1 +2953 24 14 0 +2954 24 15 1 +2955 24 15 0 +2956 25 14 1 +2957 25 14 0 +2958 25 15 1 +2959 25 15 0 +2976 19 14 0 +2977 19 14 1 +2978 19 15 0 +2979 19 15 1 +2980 18 14 0 +2981 18 14 1 +2982 18 15 0 +2983 18 15 1 +2984 16 15 1 +2985 16 15 0 +2986 16 14 1 +2987 16 14 0 +2988 17 15 1 +2989 17 15 0 +2990 17 14 1 +2991 17 14 0 +2992 20 14 0 +2993 20 14 1 +2994 20 15 0 +2995 20 15 1 +2996 21 14 0 +2997 21 14 1 +2998 21 15 0 +2999 21 15 1 +3000 23 15 1 +3001 23 15 0 +3002 23 14 1 +3003 23 14 0 +3004 22 15 1 +3005 22 15 0 +3006 22 14 1 +3007 22 14 0 +3008 28 15 0 +3009 28 15 1 +3010 28 14 0 +3011 28 14 1 +3012 29 15 0 +3013 29 15 1 +3014 29 14 0 +3015 29 14 1 +3016 31 14 1 +3017 31 14 0 +3018 31 15 1 +3019 31 15 0 +3020 30 14 1 +3021 30 14 0 +3022 30 15 1 +3023 30 15 0 +3072 27 13 0 +3073 27 13 1 +3074 27 12 0 +3075 27 12 1 +3076 26 13 0 +3077 26 13 1 +3078 26 12 0 +3079 26 12 1 +3080 24 12 1 +3081 24 12 0 +3082 24 13 1 +3083 24 13 0 +3084 25 12 1 +3085 25 12 0 +3086 25 13 1 +3087 25 13 0 +3104 19 12 0 +3105 19 12 1 +3106 19 13 0 +3107 19 13 1 +3108 18 12 0 +3109 18 12 1 +3110 18 13 0 +3111 18 13 1 +3112 16 13 1 +3113 16 13 0 +3114 16 12 1 +3115 16 12 0 +3116 17 13 1 +3117 17 13 0 +3118 17 12 1 +3119 17 12 0 +3120 20 12 0 +3121 20 12 1 +3122 20 13 0 +3123 20 13 1 +3124 21 12 0 +3125 21 12 1 +3126 21 13 0 +3127 21 13 1 +3128 23 13 1 +3129 23 13 0 +3130 23 12 1 +3131 23 12 0 +3132 22 13 1 +3133 22 13 0 +3134 22 12 1 +3135 22 12 0 +3136 28 13 0 +3137 28 13 1 +3138 28 12 0 +3139 28 12 1 +3140 29 13 0 +3141 29 13 1 +3142 29 12 0 +3143 29 12 1 +3144 31 12 1 +3145 31 12 0 +3146 31 13 1 +3147 31 13 0 +3148 30 12 1 +3149 30 12 0 +3150 30 13 1 +3151 30 13 0 +3200 27 11 0 +3201 27 11 1 +3202 27 10 0 +3203 27 10 1 +3204 26 11 0 +3205 26 11 1 +3206 26 10 0 +3207 26 10 1 +3208 24 10 1 +3209 24 10 0 +3210 24 11 1 +3211 24 11 0 +3212 25 10 1 +3213 25 10 0 +3214 25 11 1 +3215 25 11 0 +3232 19 10 0 +3233 19 10 1 +3234 19 11 0 +3235 19 11 1 +3236 18 10 0 +3237 18 10 1 +3238 18 11 0 +3239 18 11 1 +3240 16 11 1 +3241 16 11 0 +3242 16 10 1 +3243 16 10 0 +3244 17 11 1 +3245 17 11 0 +3246 17 10 1 +3247 17 10 0 +3248 20 10 0 +3249 20 10 1 +3250 20 11 0 +3251 20 11 1 +3252 21 10 0 +3253 21 10 1 +3254 21 11 0 +3255 21 11 1 +3256 23 11 1 +3257 23 11 0 +3258 23 10 1 +3259 23 10 0 +3260 22 11 1 +3261 22 11 0 +3262 22 10 1 +3263 22 10 0 +3264 28 11 0 +3265 28 11 1 +3266 28 10 0 +3267 28 10 1 +3268 29 11 0 +3269 29 11 1 +3270 29 10 0 +3271 29 10 1 +3272 31 10 1 +3273 31 10 0 +3274 31 11 1 +3275 31 11 0 +3276 30 10 1 +3277 30 10 0 +3278 30 11 1 +3279 30 11 0 +3328 27 9 0 +3329 27 9 1 +3330 27 8 0 +3331 27 8 1 +3332 26 9 0 +3333 26 9 1 +3334 26 8 0 +3335 26 8 1 +3336 24 8 1 +3337 24 8 0 +3338 24 9 1 +3339 24 9 0 +3340 25 8 1 +3341 25 8 0 +3342 25 9 1 +3343 25 9 0 +3360 19 8 0 +3361 19 8 1 +3362 19 9 0 +3363 19 9 1 +3364 18 8 0 +3365 18 8 1 +3366 18 9 0 +3367 18 9 1 +3368 16 9 1 +3369 16 9 0 +3370 16 8 1 +3371 16 8 0 +3372 17 9 1 +3373 17 9 0 +3374 17 8 1 +3375 17 8 0 +3376 20 8 0 +3377 20 8 1 +3378 20 9 0 +3379 20 9 1 +3380 21 8 0 +3381 21 8 1 +3382 21 9 0 +3383 21 9 1 +3384 23 9 1 +3385 23 9 0 +3386 23 8 1 +3387 23 8 0 +3388 22 9 1 +3389 22 9 0 +3390 22 8 1 +3391 22 8 0 +3392 28 9 0 +3393 28 9 1 +3394 28 8 0 +3395 28 8 1 +3396 29 9 0 +3397 29 9 1 +3398 29 8 0 +3399 29 8 1 +3400 31 8 1 +3401 31 8 0 +3402 31 9 1 +3403 31 9 0 +3404 30 8 1 +3405 30 8 0 +3406 30 9 1 +3407 30 9 0 +3456 27 7 0 +3457 27 7 1 +3458 27 6 0 +3459 27 6 1 +3460 26 7 0 +3461 26 7 1 +3462 26 6 0 +3463 26 6 1 +3464 24 6 1 +3465 24 6 0 +3466 24 7 1 +3467 24 7 0 +3468 25 6 1 +3469 25 6 0 +3470 25 7 1 +3471 25 7 0 +3488 19 6 0 +3489 19 6 1 +3490 19 7 0 +3491 19 7 1 +3492 18 6 0 +3493 18 6 1 +3494 18 7 0 +3495 18 7 1 +3496 16 7 1 +3497 16 7 0 +3498 16 6 1 +3499 16 6 0 +3500 17 7 1 +3501 17 7 0 +3502 17 6 1 +3503 17 6 0 +3504 20 6 0 +3505 20 6 1 +3506 20 7 0 +3507 20 7 1 +3508 21 6 0 +3509 21 6 1 +3510 21 7 0 +3511 21 7 1 +3512 23 7 1 +3513 23 7 0 +3514 23 6 1 +3515 23 6 0 +3516 22 7 1 +3517 22 7 0 +3518 22 6 1 +3519 22 6 0 +3520 28 7 0 +3521 28 7 1 +3522 28 6 0 +3523 28 6 1 +3524 29 7 0 +3525 29 7 1 +3526 29 6 0 +3527 29 6 1 +3528 31 6 1 +3529 31 6 0 +3530 31 7 1 +3531 31 7 0 +3532 30 6 1 +3533 30 6 0 +3534 30 7 1 +3535 30 7 0 +3584 27 5 0 +3585 27 5 1 +3586 27 4 0 +3587 27 4 1 +3588 26 5 0 +3589 26 5 1 +3590 26 4 0 +3591 26 4 1 +3592 24 4 1 +3593 24 4 0 +3594 24 5 1 +3595 24 5 0 +3596 25 4 1 +3597 25 4 0 +3598 25 5 1 +3599 25 5 0 +3616 19 4 0 +3617 19 4 1 +3618 19 5 0 +3619 19 5 1 +3620 18 4 0 +3621 18 4 1 +3622 18 5 0 +3623 18 5 1 +3624 16 5 1 +3625 16 5 0 +3626 16 4 1 +3627 16 4 0 +3628 17 5 1 +3629 17 5 0 +3630 17 4 1 +3631 17 4 0 +3632 20 4 0 +3633 20 4 1 +3634 20 5 0 +3635 20 5 1 +3636 21 4 0 +3637 21 4 1 +3638 21 5 0 +3639 21 5 1 +3640 23 5 1 +3641 23 5 0 +3642 23 4 1 +3643 23 4 0 +3644 22 5 1 +3645 22 5 0 +3646 22 4 1 +3647 22 4 0 +3648 28 5 0 +3649 28 5 1 +3650 28 4 0 +3651 28 4 1 +3652 29 5 0 +3653 29 5 1 +3654 29 4 0 +3655 29 4 1 +3656 31 4 1 +3657 31 4 0 +3658 31 5 1 +3659 31 5 0 +3660 30 4 1 +3661 30 4 0 +3662 30 5 1 +3663 30 5 0 +3712 27 3 0 +3713 27 3 1 +3714 27 2 0 +3715 27 2 1 +3716 26 3 0 +3717 26 3 1 +3718 26 2 0 +3719 26 2 1 +3720 24 2 1 +3721 24 2 0 +3722 24 3 1 +3723 24 3 0 +3724 25 2 1 +3725 25 2 0 +3726 25 3 1 +3727 25 3 0 +3744 19 2 0 +3745 19 2 1 +3746 19 3 0 +3747 19 3 1 +3748 18 2 0 +3749 18 2 1 +3750 18 3 0 +3751 18 3 1 +3752 16 3 1 +3753 16 3 0 +3754 16 2 1 +3755 16 2 0 +3756 17 3 1 +3757 17 3 0 +3758 17 2 1 +3759 17 2 0 +3760 20 2 0 +3761 20 2 1 +3762 20 3 0 +3763 20 3 1 +3764 21 2 0 +3765 21 2 1 +3766 21 3 0 +3767 21 3 1 +3768 23 3 1 +3769 23 3 0 +3770 23 2 1 +3771 23 2 0 +3772 22 3 1 +3773 22 3 0 +3774 22 2 1 +3775 22 2 0 +3776 28 3 0 +3777 28 3 1 +3778 28 2 0 +3779 28 2 1 +3780 29 3 0 +3781 29 3 1 +3782 29 2 0 +3783 29 2 1 +3784 31 2 1 +3785 31 2 0 +3786 31 3 1 +3787 31 3 0 +3788 30 2 1 +3789 30 2 0 +3790 30 3 1 +3791 30 3 0 +3840 27 1 0 +3841 27 1 1 +3842 27 0 0 +3843 27 0 1 +3844 26 1 0 +3845 26 1 1 +3846 26 0 0 +3847 26 0 1 +3848 24 0 1 +3849 24 0 0 +3850 24 1 1 +3851 24 1 0 +3852 25 0 1 +3853 25 0 0 +3854 25 1 1 +3855 25 1 0 +3872 19 0 0 +3873 19 0 1 +3874 19 1 0 +3875 19 1 1 +3876 18 0 0 +3877 18 0 1 +3878 18 1 0 +3879 18 1 1 +3880 16 1 1 +3881 16 1 0 +3882 16 0 1 +3883 16 0 0 +3884 17 1 1 +3885 17 1 0 +3886 17 0 1 +3887 17 0 0 +3888 20 0 0 +3889 20 0 1 +3890 20 1 0 +3891 20 1 1 +3892 21 0 0 +3893 21 0 1 +3894 21 1 0 +3895 21 1 1 +3896 23 1 1 +3897 23 1 0 +3898 23 0 1 +3899 23 0 0 +3900 22 1 1 +3901 22 1 0 +3902 22 0 1 +3903 22 0 0 +3904 28 1 0 +3905 28 1 1 +3906 28 0 0 +3907 28 0 1 +3908 29 1 0 +3909 29 1 1 +3910 29 0 0 +3911 29 0 1 +3912 31 0 1 +3913 31 0 0 +3914 31 1 1 +3915 31 1 0 +3916 30 0 1 +3917 30 0 0 +3918 30 1 1 +3919 30 1 0 diff --git a/Detectors/PHOS/base/files/Mod1RCU2.data b/Detectors/PHOS/base/files/Mod1RCU2.data new file mode 100644 index 0000000000000..21de94d7ace53 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod1RCU2.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 2 0 2 + 1 2 1 2 + 2 2 2 2 + 3 2 3 2 + 4 2 4 2 + 5 2 5 2 + 6 2 6 2 + 7 2 7 2 + 8 2 8 2 + 9 2 9 2 + 10 2 10 2 + 11 2 11 2 + 12 2 12 2 + 13 2 13 2 + 14 2 14 2 + 15 2 15 2 + 16 2 16 2 + 17 2 17 2 + 18 2 18 2 + 19 2 19 2 + 20 2 20 2 + 21 2 21 2 + 22 2 22 2 + 23 2 23 2 + 24 2 24 2 + 25 2 25 2 + 26 2 26 2 + 27 2 27 2 + 28 2 28 2 + 29 2 29 2 + 30 2 30 2 + 31 2 31 2 + 32 2 32 2 + 33 2 33 2 + 34 2 34 2 + 35 2 35 2 + 36 2 36 2 + 37 2 37 2 + 38 2 38 2 + 39 2 39 2 + 40 2 40 2 + 41 2 41 2 + 42 2 42 2 + 43 2 43 2 + 44 2 44 2 + 45 2 45 2 + 46 2 46 2 + 47 2 47 2 + 48 2 48 2 + 49 2 49 2 + 50 2 50 2 + 51 2 51 2 + 52 2 52 2 + 53 2 53 2 + 54 2 54 2 + 55 2 55 2 + 56 2 56 2 + 57 2 57 2 + 58 2 58 2 + 59 2 59 2 + 60 2 60 2 + 61 2 61 2 + 62 2 62 2 + 63 2 63 2 + 64 2 64 2 + 65 2 65 2 + 66 2 66 2 + 67 2 67 2 + 68 2 68 2 + 69 2 69 2 + 70 2 70 2 + 71 2 71 2 + 72 2 72 2 + 73 2 73 2 + 74 2 74 2 + 75 2 75 2 + 76 2 76 2 + 77 2 77 2 + 78 2 78 2 + 79 2 79 2 + 80 2 80 2 + 81 2 81 2 + 82 2 82 2 + 83 2 83 2 + 84 2 84 2 + 85 2 85 2 + 86 2 86 2 + 87 2 87 2 + 88 2 88 2 + 89 2 89 2 + 90 2 90 2 + 91 2 91 2 + 92 2 92 2 + 93 2 93 2 + 94 2 94 2 + 95 2 95 2 + 96 2 96 2 + 97 2 97 2 + 98 2 98 2 + 99 2 99 2 + 100 2 100 2 + 101 2 101 2 + 102 2 102 2 + 103 2 103 2 + 104 2 104 2 + 105 2 105 2 + 106 2 106 2 + 107 2 107 2 + 108 2 108 2 + 109 2 109 2 + 110 2 110 2 + 111 2 111 2 + 112 2 112 2 + 113 2 113 2 + 114 2 114 2 + 115 2 115 2 + 116 2 116 2 + 117 2 117 2 + 118 2 118 2 + 119 2 119 2 + 120 2 120 2 + 121 2 121 2 + 122 2 122 2 + 123 2 123 2 + 124 2 124 2 + 125 2 125 2 + 126 2 126 2 + 127 2 127 2 +2048 2 2048 2 +2049 2 2049 2 +2050 2 2050 2 +2051 2 2051 2 +2052 2 2052 2 +2053 2 2053 2 +2054 2 2054 2 +2055 2 2055 2 +2056 2 2056 2 +2057 2 2057 2 +2058 2 2058 2 +2059 2 2059 2 +2060 2 2060 2 +2061 2 2061 2 +2062 2 2062 2 +2063 2 2063 2 +2064 2 2064 2 +2065 2 2065 2 +2066 2 2066 2 +2067 2 2067 2 +2068 2 2068 2 +2069 2 2069 2 +2070 2 2070 2 +2071 2 2071 2 +2072 2 2072 2 +2073 2 2073 2 +2074 2 2074 2 +2075 2 2075 2 +2076 2 2076 2 +2077 2 2077 2 +2078 2 2078 2 +2079 2 2079 2 +2080 2 2080 2 +2081 2 2081 2 +2082 2 2082 2 +2083 2 2083 2 +2084 2 2084 2 +2085 2 2085 2 +2086 2 2086 2 +2087 2 2087 2 +2088 2 2088 2 +2089 2 2089 2 +2090 2 2090 2 +2091 2 2091 2 +2092 2 2092 2 +2093 2 2093 2 +2094 2 2094 2 +2095 2 2095 2 +2096 2 2096 2 +2097 2 2097 2 +2098 2 2098 2 +2099 2 2099 2 +2100 2 2100 2 +2101 2 2101 2 +2102 2 2102 2 +2103 2 2103 2 +2104 2 2104 2 +2105 2 2105 2 +2106 2 2106 2 +2107 2 2107 2 +2108 2 2108 2 +2109 2 2109 2 +2110 2 2110 2 +2111 2 2111 2 +2112 2 2112 2 +2113 2 2113 2 +2114 2 2114 2 +2115 2 2115 2 +2116 2 2116 2 +2117 2 2117 2 +2118 2 2118 2 +2119 2 2119 2 +2120 2 2120 2 +2121 2 2121 2 +2122 2 2122 2 +2123 2 2123 2 +2124 2 2124 2 +2125 2 2125 2 +2126 2 2126 2 +2127 2 2127 2 +2128 2 2128 2 +2129 2 2129 2 +2130 2 2130 2 +2131 2 2131 2 +2132 2 2132 2 +2133 2 2133 2 +2134 2 2134 2 +2135 2 2135 2 +2136 2 2136 2 +2137 2 2137 2 +2138 2 2138 2 +2139 2 2139 2 +2140 2 2140 2 +2141 2 2141 2 +2142 2 2142 2 +2143 2 2143 2 +2144 2 2144 2 +2145 2 2145 2 +2146 2 2146 2 +2147 2 2147 2 +2148 2 2148 2 +2149 2 2149 2 +2150 2 2150 2 +2151 2 2151 2 +2152 2 2152 2 +2153 2 2153 2 +2154 2 2154 2 +2155 2 2155 2 +2156 2 2156 2 +2157 2 2157 2 +2158 2 2158 2 +2159 2 2159 2 +2160 2 2160 2 +2161 2 2161 2 +2162 2 2162 2 +2163 2 2163 2 +2164 2 2164 2 +2165 2 2165 2 +2166 2 2166 2 +2167 2 2167 2 +2168 2 2168 2 +2169 2 2169 2 +2170 2 2170 2 +2171 2 2171 2 +2172 2 2172 2 +2173 2 2173 2 +2174 2 2174 2 +2175 2 2175 2 + 128 43 29 0 + 129 43 29 1 + 130 43 28 0 + 131 43 28 1 + 132 42 29 0 + 133 42 29 1 + 134 42 28 0 + 135 42 28 1 + 136 40 28 1 + 137 40 28 0 + 138 40 29 1 + 139 40 29 0 + 140 41 28 1 + 141 41 28 0 + 142 41 29 1 + 143 41 29 0 + 160 35 28 0 + 161 35 28 1 + 162 35 29 0 + 163 35 29 1 + 164 34 28 0 + 165 34 28 1 + 166 34 29 0 + 167 34 29 1 + 168 32 29 1 + 169 32 29 0 + 170 32 28 1 + 171 32 28 0 + 172 33 29 1 + 173 33 29 0 + 174 33 28 1 + 175 33 28 0 + 176 36 28 0 + 177 36 28 1 + 178 36 29 0 + 179 36 29 1 + 180 37 28 0 + 181 37 28 1 + 182 37 29 0 + 183 37 29 1 + 184 39 29 1 + 185 39 29 0 + 186 39 28 1 + 187 39 28 0 + 188 38 29 1 + 189 38 29 0 + 190 38 28 1 + 191 38 28 0 + 192 44 29 0 + 193 44 29 1 + 194 44 28 0 + 195 44 28 1 + 196 45 29 0 + 197 45 29 1 + 198 45 28 0 + 199 45 28 1 + 200 47 28 1 + 201 47 28 0 + 202 47 29 1 + 203 47 29 0 + 204 46 28 1 + 205 46 28 0 + 206 46 29 1 + 207 46 29 0 + 256 43 31 0 + 257 43 31 1 + 258 43 30 0 + 259 43 30 1 + 260 42 31 0 + 261 42 31 1 + 262 42 30 0 + 263 42 30 1 + 264 40 30 1 + 265 40 30 0 + 266 40 31 1 + 267 40 31 0 + 268 41 30 1 + 269 41 30 0 + 270 41 31 1 + 271 41 31 0 + 288 35 30 0 + 289 35 30 1 + 290 35 31 0 + 291 35 31 1 + 292 34 30 0 + 293 34 30 1 + 294 34 31 0 + 295 34 31 1 + 296 32 31 1 + 297 32 31 0 + 298 32 30 1 + 299 32 30 0 + 300 33 31 1 + 301 33 31 0 + 302 33 30 1 + 303 33 30 0 + 304 36 30 0 + 305 36 30 1 + 306 36 31 0 + 307 36 31 1 + 308 37 30 0 + 309 37 30 1 + 310 37 31 0 + 311 37 31 1 + 312 39 31 1 + 313 39 31 0 + 314 39 30 1 + 315 39 30 0 + 316 38 31 1 + 317 38 31 0 + 318 38 30 1 + 319 38 30 0 + 320 44 31 0 + 321 44 31 1 + 322 44 30 0 + 323 44 30 1 + 324 45 31 0 + 325 45 31 1 + 326 45 30 0 + 327 45 30 1 + 328 47 30 1 + 329 47 30 0 + 330 47 31 1 + 331 47 31 0 + 332 46 30 1 + 333 46 30 0 + 334 46 31 1 + 335 46 31 0 + 384 43 33 0 + 385 43 33 1 + 386 43 32 0 + 387 43 32 1 + 388 42 33 0 + 389 42 33 1 + 390 42 32 0 + 391 42 32 1 + 392 40 32 1 + 393 40 32 0 + 394 40 33 1 + 395 40 33 0 + 396 41 32 1 + 397 41 32 0 + 398 41 33 1 + 399 41 33 0 + 416 35 32 0 + 417 35 32 1 + 418 35 33 0 + 419 35 33 1 + 420 34 32 0 + 421 34 32 1 + 422 34 33 0 + 423 34 33 1 + 424 32 33 1 + 425 32 33 0 + 426 32 32 1 + 427 32 32 0 + 428 33 33 1 + 429 33 33 0 + 430 33 32 1 + 431 33 32 0 + 432 36 32 0 + 433 36 32 1 + 434 36 33 0 + 435 36 33 1 + 436 37 32 0 + 437 37 32 1 + 438 37 33 0 + 439 37 33 1 + 440 39 33 1 + 441 39 33 0 + 442 39 32 1 + 443 39 32 0 + 444 38 33 1 + 445 38 33 0 + 446 38 32 1 + 447 38 32 0 + 448 44 33 0 + 449 44 33 1 + 450 44 32 0 + 451 44 32 1 + 452 45 33 0 + 453 45 33 1 + 454 45 32 0 + 455 45 32 1 + 456 47 32 1 + 457 47 32 0 + 458 47 33 1 + 459 47 33 0 + 460 46 32 1 + 461 46 32 0 + 462 46 33 1 + 463 46 33 0 + 512 43 35 0 + 513 43 35 1 + 514 43 34 0 + 515 43 34 1 + 516 42 35 0 + 517 42 35 1 + 518 42 34 0 + 519 42 34 1 + 520 40 34 1 + 521 40 34 0 + 522 40 35 1 + 523 40 35 0 + 524 41 34 1 + 525 41 34 0 + 526 41 35 1 + 527 41 35 0 + 544 35 34 0 + 545 35 34 1 + 546 35 35 0 + 547 35 35 1 + 548 34 34 0 + 549 34 34 1 + 550 34 35 0 + 551 34 35 1 + 552 32 35 1 + 553 32 35 0 + 554 32 34 1 + 555 32 34 0 + 556 33 35 1 + 557 33 35 0 + 558 33 34 1 + 559 33 34 0 + 560 36 34 0 + 561 36 34 1 + 562 36 35 0 + 563 36 35 1 + 564 37 34 0 + 565 37 34 1 + 566 37 35 0 + 567 37 35 1 + 568 39 35 1 + 569 39 35 0 + 570 39 34 1 + 571 39 34 0 + 572 38 35 1 + 573 38 35 0 + 574 38 34 1 + 575 38 34 0 + 576 44 35 0 + 577 44 35 1 + 578 44 34 0 + 579 44 34 1 + 580 45 35 0 + 581 45 35 1 + 582 45 34 0 + 583 45 34 1 + 584 47 34 1 + 585 47 34 0 + 586 47 35 1 + 587 47 35 0 + 588 46 34 1 + 589 46 34 0 + 590 46 35 1 + 591 46 35 0 + 640 43 37 0 + 641 43 37 1 + 642 43 36 0 + 643 43 36 1 + 644 42 37 0 + 645 42 37 1 + 646 42 36 0 + 647 42 36 1 + 648 40 36 1 + 649 40 36 0 + 650 40 37 1 + 651 40 37 0 + 652 41 36 1 + 653 41 36 0 + 654 41 37 1 + 655 41 37 0 + 672 35 36 0 + 673 35 36 1 + 674 35 37 0 + 675 35 37 1 + 676 34 36 0 + 677 34 36 1 + 678 34 37 0 + 679 34 37 1 + 680 32 37 1 + 681 32 37 0 + 682 32 36 1 + 683 32 36 0 + 684 33 37 1 + 685 33 37 0 + 686 33 36 1 + 687 33 36 0 + 688 36 36 0 + 689 36 36 1 + 690 36 37 0 + 691 36 37 1 + 692 37 36 0 + 693 37 36 1 + 694 37 37 0 + 695 37 37 1 + 696 39 37 1 + 697 39 37 0 + 698 39 36 1 + 699 39 36 0 + 700 38 37 1 + 701 38 37 0 + 702 38 36 1 + 703 38 36 0 + 704 44 37 0 + 705 44 37 1 + 706 44 36 0 + 707 44 36 1 + 708 45 37 0 + 709 45 37 1 + 710 45 36 0 + 711 45 36 1 + 712 47 36 1 + 713 47 36 0 + 714 47 37 1 + 715 47 37 0 + 716 46 36 1 + 717 46 36 0 + 718 46 37 1 + 719 46 37 0 + 768 43 39 0 + 769 43 39 1 + 770 43 38 0 + 771 43 38 1 + 772 42 39 0 + 773 42 39 1 + 774 42 38 0 + 775 42 38 1 + 776 40 38 1 + 777 40 38 0 + 778 40 39 1 + 779 40 39 0 + 780 41 38 1 + 781 41 38 0 + 782 41 39 1 + 783 41 39 0 + 800 35 38 0 + 801 35 38 1 + 802 35 39 0 + 803 35 39 1 + 804 34 38 0 + 805 34 38 1 + 806 34 39 0 + 807 34 39 1 + 808 32 39 1 + 809 32 39 0 + 810 32 38 1 + 811 32 38 0 + 812 33 39 1 + 813 33 39 0 + 814 33 38 1 + 815 33 38 0 + 816 36 38 0 + 817 36 38 1 + 818 36 39 0 + 819 36 39 1 + 820 37 38 0 + 821 37 38 1 + 822 37 39 0 + 823 37 39 1 + 824 39 39 1 + 825 39 39 0 + 826 39 38 1 + 827 39 38 0 + 828 38 39 1 + 829 38 39 0 + 830 38 38 1 + 831 38 38 0 + 832 44 39 0 + 833 44 39 1 + 834 44 38 0 + 835 44 38 1 + 836 45 39 0 + 837 45 39 1 + 838 45 38 0 + 839 45 38 1 + 840 47 38 1 + 841 47 38 0 + 842 47 39 1 + 843 47 39 0 + 844 46 38 1 + 845 46 38 0 + 846 46 39 1 + 847 46 39 0 + 896 43 41 0 + 897 43 41 1 + 898 43 40 0 + 899 43 40 1 + 900 42 41 0 + 901 42 41 1 + 902 42 40 0 + 903 42 40 1 + 904 40 40 1 + 905 40 40 0 + 906 40 41 1 + 907 40 41 0 + 908 41 40 1 + 909 41 40 0 + 910 41 41 1 + 911 41 41 0 + 928 35 40 0 + 929 35 40 1 + 930 35 41 0 + 931 35 41 1 + 932 34 40 0 + 933 34 40 1 + 934 34 41 0 + 935 34 41 1 + 936 32 41 1 + 937 32 41 0 + 938 32 40 1 + 939 32 40 0 + 940 33 41 1 + 941 33 41 0 + 942 33 40 1 + 943 33 40 0 + 944 36 40 0 + 945 36 40 1 + 946 36 41 0 + 947 36 41 1 + 948 37 40 0 + 949 37 40 1 + 950 37 41 0 + 951 37 41 1 + 952 39 41 1 + 953 39 41 0 + 954 39 40 1 + 955 39 40 0 + 956 38 41 1 + 957 38 41 0 + 958 38 40 1 + 959 38 40 0 + 960 44 41 0 + 961 44 41 1 + 962 44 40 0 + 963 44 40 1 + 964 45 41 0 + 965 45 41 1 + 966 45 40 0 + 967 45 40 1 + 968 47 40 1 + 969 47 40 0 + 970 47 41 1 + 971 47 41 0 + 972 46 40 1 + 973 46 40 0 + 974 46 41 1 + 975 46 41 0 +1024 43 43 0 +1025 43 43 1 +1026 43 42 0 +1027 43 42 1 +1028 42 43 0 +1029 42 43 1 +1030 42 42 0 +1031 42 42 1 +1032 40 42 1 +1033 40 42 0 +1034 40 43 1 +1035 40 43 0 +1036 41 42 1 +1037 41 42 0 +1038 41 43 1 +1039 41 43 0 +1056 35 42 0 +1057 35 42 1 +1058 35 43 0 +1059 35 43 1 +1060 34 42 0 +1061 34 42 1 +1062 34 43 0 +1063 34 43 1 +1064 32 43 1 +1065 32 43 0 +1066 32 42 1 +1067 32 42 0 +1068 33 43 1 +1069 33 43 0 +1070 33 42 1 +1071 33 42 0 +1072 36 42 0 +1073 36 42 1 +1074 36 43 0 +1075 36 43 1 +1076 37 42 0 +1077 37 42 1 +1078 37 43 0 +1079 37 43 1 +1080 39 43 1 +1081 39 43 0 +1082 39 42 1 +1083 39 42 0 +1084 38 43 1 +1085 38 43 0 +1086 38 42 1 +1087 38 42 0 +1088 44 43 0 +1089 44 43 1 +1090 44 42 0 +1091 44 42 1 +1092 45 43 0 +1093 45 43 1 +1094 45 42 0 +1095 45 42 1 +1096 47 42 1 +1097 47 42 0 +1098 47 43 1 +1099 47 43 0 +1100 46 42 1 +1101 46 42 0 +1102 46 43 1 +1103 46 43 0 +1152 43 45 0 +1153 43 45 1 +1154 43 44 0 +1155 43 44 1 +1156 42 45 0 +1157 42 45 1 +1158 42 44 0 +1159 42 44 1 +1160 40 44 1 +1161 40 44 0 +1162 40 45 1 +1163 40 45 0 +1164 41 44 1 +1165 41 44 0 +1166 41 45 1 +1167 41 45 0 +1184 35 44 0 +1185 35 44 1 +1186 35 45 0 +1187 35 45 1 +1188 34 44 0 +1189 34 44 1 +1190 34 45 0 +1191 34 45 1 +1192 32 45 1 +1193 32 45 0 +1194 32 44 1 +1195 32 44 0 +1196 33 45 1 +1197 33 45 0 +1198 33 44 1 +1199 33 44 0 +1200 36 44 0 +1201 36 44 1 +1202 36 45 0 +1203 36 45 1 +1204 37 44 0 +1205 37 44 1 +1206 37 45 0 +1207 37 45 1 +1208 39 45 1 +1209 39 45 0 +1210 39 44 1 +1211 39 44 0 +1212 38 45 1 +1213 38 45 0 +1214 38 44 1 +1215 38 44 0 +1216 44 45 0 +1217 44 45 1 +1218 44 44 0 +1219 44 44 1 +1220 45 45 0 +1221 45 45 1 +1222 45 44 0 +1223 45 44 1 +1224 47 44 1 +1225 47 44 0 +1226 47 45 1 +1227 47 45 0 +1228 46 44 1 +1229 46 44 0 +1230 46 45 1 +1231 46 45 0 +1280 43 47 0 +1281 43 47 1 +1282 43 46 0 +1283 43 46 1 +1284 42 47 0 +1285 42 47 1 +1286 42 46 0 +1287 42 46 1 +1288 40 46 1 +1289 40 46 0 +1290 40 47 1 +1291 40 47 0 +1292 41 46 1 +1293 41 46 0 +1294 41 47 1 +1295 41 47 0 +1312 35 46 0 +1313 35 46 1 +1314 35 47 0 +1315 35 47 1 +1316 34 46 0 +1317 34 46 1 +1318 34 47 0 +1319 34 47 1 +1320 32 47 1 +1321 32 47 0 +1322 32 46 1 +1323 32 46 0 +1324 33 47 1 +1325 33 47 0 +1326 33 46 1 +1327 33 46 0 +1328 36 46 0 +1329 36 46 1 +1330 36 47 0 +1331 36 47 1 +1332 37 46 0 +1333 37 46 1 +1334 37 47 0 +1335 37 47 1 +1336 39 47 1 +1337 39 47 0 +1338 39 46 1 +1339 39 46 0 +1340 38 47 1 +1341 38 47 0 +1342 38 46 1 +1343 38 46 0 +1344 44 47 0 +1345 44 47 1 +1346 44 46 0 +1347 44 46 1 +1348 45 47 0 +1349 45 47 1 +1350 45 46 0 +1351 45 46 1 +1352 47 46 1 +1353 47 46 0 +1354 47 47 1 +1355 47 47 0 +1356 46 46 1 +1357 46 46 0 +1358 46 47 1 +1359 46 47 0 +1408 43 49 0 +1409 43 49 1 +1410 43 48 0 +1411 43 48 1 +1412 42 49 0 +1413 42 49 1 +1414 42 48 0 +1415 42 48 1 +1416 40 48 1 +1417 40 48 0 +1418 40 49 1 +1419 40 49 0 +1420 41 48 1 +1421 41 48 0 +1422 41 49 1 +1423 41 49 0 +1440 35 48 0 +1441 35 48 1 +1442 35 49 0 +1443 35 49 1 +1444 34 48 0 +1445 34 48 1 +1446 34 49 0 +1447 34 49 1 +1448 32 49 1 +1449 32 49 0 +1450 32 48 1 +1451 32 48 0 +1452 33 49 1 +1453 33 49 0 +1454 33 48 1 +1455 33 48 0 +1456 36 48 0 +1457 36 48 1 +1458 36 49 0 +1459 36 49 1 +1460 37 48 0 +1461 37 48 1 +1462 37 49 0 +1463 37 49 1 +1464 39 49 1 +1465 39 49 0 +1466 39 48 1 +1467 39 48 0 +1468 38 49 1 +1469 38 49 0 +1470 38 48 1 +1471 38 48 0 +1472 44 49 0 +1473 44 49 1 +1474 44 48 0 +1475 44 48 1 +1476 45 49 0 +1477 45 49 1 +1478 45 48 0 +1479 45 48 1 +1480 47 48 1 +1481 47 48 0 +1482 47 49 1 +1483 47 49 0 +1484 46 48 1 +1485 46 48 0 +1486 46 49 1 +1487 46 49 0 +1536 43 51 0 +1537 43 51 1 +1538 43 50 0 +1539 43 50 1 +1540 42 51 0 +1541 42 51 1 +1542 42 50 0 +1543 42 50 1 +1544 40 50 1 +1545 40 50 0 +1546 40 51 1 +1547 40 51 0 +1548 41 50 1 +1549 41 50 0 +1550 41 51 1 +1551 41 51 0 +1568 35 50 0 +1569 35 50 1 +1570 35 51 0 +1571 35 51 1 +1572 34 50 0 +1573 34 50 1 +1574 34 51 0 +1575 34 51 1 +1576 32 51 1 +1577 32 51 0 +1578 32 50 1 +1579 32 50 0 +1580 33 51 1 +1581 33 51 0 +1582 33 50 1 +1583 33 50 0 +1584 36 50 0 +1585 36 50 1 +1586 36 51 0 +1587 36 51 1 +1588 37 50 0 +1589 37 50 1 +1590 37 51 0 +1591 37 51 1 +1592 39 51 1 +1593 39 51 0 +1594 39 50 1 +1595 39 50 0 +1596 38 51 1 +1597 38 51 0 +1598 38 50 1 +1599 38 50 0 +1600 44 51 0 +1601 44 51 1 +1602 44 50 0 +1603 44 50 1 +1604 45 51 0 +1605 45 51 1 +1606 45 50 0 +1607 45 50 1 +1608 47 50 1 +1609 47 50 0 +1610 47 51 1 +1611 47 51 0 +1612 46 50 1 +1613 46 50 0 +1614 46 51 1 +1615 46 51 0 +1664 43 53 0 +1665 43 53 1 +1666 43 52 0 +1667 43 52 1 +1668 42 53 0 +1669 42 53 1 +1670 42 52 0 +1671 42 52 1 +1672 40 52 1 +1673 40 52 0 +1674 40 53 1 +1675 40 53 0 +1676 41 52 1 +1677 41 52 0 +1678 41 53 1 +1679 41 53 0 +1696 35 52 0 +1697 35 52 1 +1698 35 53 0 +1699 35 53 1 +1700 34 52 0 +1701 34 52 1 +1702 34 53 0 +1703 34 53 1 +1704 32 53 1 +1705 32 53 0 +1706 32 52 1 +1707 32 52 0 +1708 33 53 1 +1709 33 53 0 +1710 33 52 1 +1711 33 52 0 +1712 36 52 0 +1713 36 52 1 +1714 36 53 0 +1715 36 53 1 +1716 37 52 0 +1717 37 52 1 +1718 37 53 0 +1719 37 53 1 +1720 39 53 1 +1721 39 53 0 +1722 39 52 1 +1723 39 52 0 +1724 38 53 1 +1725 38 53 0 +1726 38 52 1 +1727 38 52 0 +1728 44 53 0 +1729 44 53 1 +1730 44 52 0 +1731 44 52 1 +1732 45 53 0 +1733 45 53 1 +1734 45 52 0 +1735 45 52 1 +1736 47 52 1 +1737 47 52 0 +1738 47 53 1 +1739 47 53 0 +1740 46 52 1 +1741 46 52 0 +1742 46 53 1 +1743 46 53 0 +1792 43 55 0 +1793 43 55 1 +1794 43 54 0 +1795 43 54 1 +1796 42 55 0 +1797 42 55 1 +1798 42 54 0 +1799 42 54 1 +1800 40 54 1 +1801 40 54 0 +1802 40 55 1 +1803 40 55 0 +1804 41 54 1 +1805 41 54 0 +1806 41 55 1 +1807 41 55 0 +1824 35 54 0 +1825 35 54 1 +1826 35 55 0 +1827 35 55 1 +1828 34 54 0 +1829 34 54 1 +1830 34 55 0 +1831 34 55 1 +1832 32 55 1 +1833 32 55 0 +1834 32 54 1 +1835 32 54 0 +1836 33 55 1 +1837 33 55 0 +1838 33 54 1 +1839 33 54 0 +1840 36 54 0 +1841 36 54 1 +1842 36 55 0 +1843 36 55 1 +1844 37 54 0 +1845 37 54 1 +1846 37 55 0 +1847 37 55 1 +1848 39 55 1 +1849 39 55 0 +1850 39 54 1 +1851 39 54 0 +1852 38 55 1 +1853 38 55 0 +1854 38 54 1 +1855 38 54 0 +1856 44 55 0 +1857 44 55 1 +1858 44 54 0 +1859 44 54 1 +1860 45 55 0 +1861 45 55 1 +1862 45 54 0 +1863 45 54 1 +1864 47 54 1 +1865 47 54 0 +1866 47 55 1 +1867 47 55 0 +1868 46 54 1 +1869 46 54 0 +1870 46 55 1 +1871 46 55 0 +2176 43 27 0 +2177 43 27 1 +2178 43 26 0 +2179 43 26 1 +2180 42 27 0 +2181 42 27 1 +2182 42 26 0 +2183 42 26 1 +2184 40 26 1 +2185 40 26 0 +2186 40 27 1 +2187 40 27 0 +2188 41 26 1 +2189 41 26 0 +2190 41 27 1 +2191 41 27 0 +2208 35 26 0 +2209 35 26 1 +2210 35 27 0 +2211 35 27 1 +2212 34 26 0 +2213 34 26 1 +2214 34 27 0 +2215 34 27 1 +2216 32 27 1 +2217 32 27 0 +2218 32 26 1 +2219 32 26 0 +2220 33 27 1 +2221 33 27 0 +2222 33 26 1 +2223 33 26 0 +2224 36 26 0 +2225 36 26 1 +2226 36 27 0 +2227 36 27 1 +2228 37 26 0 +2229 37 26 1 +2230 37 27 0 +2231 37 27 1 +2232 39 27 1 +2233 39 27 0 +2234 39 26 1 +2235 39 26 0 +2236 38 27 1 +2237 38 27 0 +2238 38 26 1 +2239 38 26 0 +2240 44 27 0 +2241 44 27 1 +2242 44 26 0 +2243 44 26 1 +2244 45 27 0 +2245 45 27 1 +2246 45 26 0 +2247 45 26 1 +2248 47 26 1 +2249 47 26 0 +2250 47 27 1 +2251 47 27 0 +2252 46 26 1 +2253 46 26 0 +2254 46 27 1 +2255 46 27 0 +2304 43 25 0 +2305 43 25 1 +2306 43 24 0 +2307 43 24 1 +2308 42 25 0 +2309 42 25 1 +2310 42 24 0 +2311 42 24 1 +2312 40 24 1 +2313 40 24 0 +2314 40 25 1 +2315 40 25 0 +2316 41 24 1 +2317 41 24 0 +2318 41 25 1 +2319 41 25 0 +2336 35 24 0 +2337 35 24 1 +2338 35 25 0 +2339 35 25 1 +2340 34 24 0 +2341 34 24 1 +2342 34 25 0 +2343 34 25 1 +2344 32 25 1 +2345 32 25 0 +2346 32 24 1 +2347 32 24 0 +2348 33 25 1 +2349 33 25 0 +2350 33 24 1 +2351 33 24 0 +2352 36 24 0 +2353 36 24 1 +2354 36 25 0 +2355 36 25 1 +2356 37 24 0 +2357 37 24 1 +2358 37 25 0 +2359 37 25 1 +2360 39 25 1 +2361 39 25 0 +2362 39 24 1 +2363 39 24 0 +2364 38 25 1 +2365 38 25 0 +2366 38 24 1 +2367 38 24 0 +2368 44 25 0 +2369 44 25 1 +2370 44 24 0 +2371 44 24 1 +2372 45 25 0 +2373 45 25 1 +2374 45 24 0 +2375 45 24 1 +2376 47 24 1 +2377 47 24 0 +2378 47 25 1 +2379 47 25 0 +2380 46 24 1 +2381 46 24 0 +2382 46 25 1 +2383 46 25 0 +2432 43 23 0 +2433 43 23 1 +2434 43 22 0 +2435 43 22 1 +2436 42 23 0 +2437 42 23 1 +2438 42 22 0 +2439 42 22 1 +2440 40 22 1 +2441 40 22 0 +2442 40 23 1 +2443 40 23 0 +2444 41 22 1 +2445 41 22 0 +2446 41 23 1 +2447 41 23 0 +2464 35 22 0 +2465 35 22 1 +2466 35 23 0 +2467 35 23 1 +2468 34 22 0 +2469 34 22 1 +2470 34 23 0 +2471 34 23 1 +2472 32 23 1 +2473 32 23 0 +2474 32 22 1 +2475 32 22 0 +2476 33 23 1 +2477 33 23 0 +2478 33 22 1 +2479 33 22 0 +2480 36 22 0 +2481 36 22 1 +2482 36 23 0 +2483 36 23 1 +2484 37 22 0 +2485 37 22 1 +2486 37 23 0 +2487 37 23 1 +2488 39 23 1 +2489 39 23 0 +2490 39 22 1 +2491 39 22 0 +2492 38 23 1 +2493 38 23 0 +2494 38 22 1 +2495 38 22 0 +2496 44 23 0 +2497 44 23 1 +2498 44 22 0 +2499 44 22 1 +2500 45 23 0 +2501 45 23 1 +2502 45 22 0 +2503 45 22 1 +2504 47 22 1 +2505 47 22 0 +2506 47 23 1 +2507 47 23 0 +2508 46 22 1 +2509 46 22 0 +2510 46 23 1 +2511 46 23 0 +2560 43 21 0 +2561 43 21 1 +2562 43 20 0 +2563 43 20 1 +2564 42 21 0 +2565 42 21 1 +2566 42 20 0 +2567 42 20 1 +2568 40 20 1 +2569 40 20 0 +2570 40 21 1 +2571 40 21 0 +2572 41 20 1 +2573 41 20 0 +2574 41 21 1 +2575 41 21 0 +2592 35 20 0 +2593 35 20 1 +2594 35 21 0 +2595 35 21 1 +2596 34 20 0 +2597 34 20 1 +2598 34 21 0 +2599 34 21 1 +2600 32 21 1 +2601 32 21 0 +2602 32 20 1 +2603 32 20 0 +2604 33 21 1 +2605 33 21 0 +2606 33 20 1 +2607 33 20 0 +2608 36 20 0 +2609 36 20 1 +2610 36 21 0 +2611 36 21 1 +2612 37 20 0 +2613 37 20 1 +2614 37 21 0 +2615 37 21 1 +2616 39 21 1 +2617 39 21 0 +2618 39 20 1 +2619 39 20 0 +2620 38 21 1 +2621 38 21 0 +2622 38 20 1 +2623 38 20 0 +2624 44 21 0 +2625 44 21 1 +2626 44 20 0 +2627 44 20 1 +2628 45 21 0 +2629 45 21 1 +2630 45 20 0 +2631 45 20 1 +2632 47 20 1 +2633 47 20 0 +2634 47 21 1 +2635 47 21 0 +2636 46 20 1 +2637 46 20 0 +2638 46 21 1 +2639 46 21 0 +2688 43 19 0 +2689 43 19 1 +2690 43 18 0 +2691 43 18 1 +2692 42 19 0 +2693 42 19 1 +2694 42 18 0 +2695 42 18 1 +2696 40 18 1 +2697 40 18 0 +2698 40 19 1 +2699 40 19 0 +2700 41 18 1 +2701 41 18 0 +2702 41 19 1 +2703 41 19 0 +2720 35 18 0 +2721 35 18 1 +2722 35 19 0 +2723 35 19 1 +2724 34 18 0 +2725 34 18 1 +2726 34 19 0 +2727 34 19 1 +2728 32 19 1 +2729 32 19 0 +2730 32 18 1 +2731 32 18 0 +2732 33 19 1 +2733 33 19 0 +2734 33 18 1 +2735 33 18 0 +2736 36 18 0 +2737 36 18 1 +2738 36 19 0 +2739 36 19 1 +2740 37 18 0 +2741 37 18 1 +2742 37 19 0 +2743 37 19 1 +2744 39 19 1 +2745 39 19 0 +2746 39 18 1 +2747 39 18 0 +2748 38 19 1 +2749 38 19 0 +2750 38 18 1 +2751 38 18 0 +2752 44 19 0 +2753 44 19 1 +2754 44 18 0 +2755 44 18 1 +2756 45 19 0 +2757 45 19 1 +2758 45 18 0 +2759 45 18 1 +2760 47 18 1 +2761 47 18 0 +2762 47 19 1 +2763 47 19 0 +2764 46 18 1 +2765 46 18 0 +2766 46 19 1 +2767 46 19 0 +2816 43 17 0 +2817 43 17 1 +2818 43 16 0 +2819 43 16 1 +2820 42 17 0 +2821 42 17 1 +2822 42 16 0 +2823 42 16 1 +2824 40 16 1 +2825 40 16 0 +2826 40 17 1 +2827 40 17 0 +2828 41 16 1 +2829 41 16 0 +2830 41 17 1 +2831 41 17 0 +2848 35 16 0 +2849 35 16 1 +2850 35 17 0 +2851 35 17 1 +2852 34 16 0 +2853 34 16 1 +2854 34 17 0 +2855 34 17 1 +2856 32 17 1 +2857 32 17 0 +2858 32 16 1 +2859 32 16 0 +2860 33 17 1 +2861 33 17 0 +2862 33 16 1 +2863 33 16 0 +2864 36 16 0 +2865 36 16 1 +2866 36 17 0 +2867 36 17 1 +2868 37 16 0 +2869 37 16 1 +2870 37 17 0 +2871 37 17 1 +2872 39 17 1 +2873 39 17 0 +2874 39 16 1 +2875 39 16 0 +2876 38 17 1 +2877 38 17 0 +2878 38 16 1 +2879 38 16 0 +2880 44 17 0 +2881 44 17 1 +2882 44 16 0 +2883 44 16 1 +2884 45 17 0 +2885 45 17 1 +2886 45 16 0 +2887 45 16 1 +2888 47 16 1 +2889 47 16 0 +2890 47 17 1 +2891 47 17 0 +2892 46 16 1 +2893 46 16 0 +2894 46 17 1 +2895 46 17 0 +2944 43 15 0 +2945 43 15 1 +2946 43 14 0 +2947 43 14 1 +2948 42 15 0 +2949 42 15 1 +2950 42 14 0 +2951 42 14 1 +2952 40 14 1 +2953 40 14 0 +2954 40 15 1 +2955 40 15 0 +2956 41 14 1 +2957 41 14 0 +2958 41 15 1 +2959 41 15 0 +2976 35 14 0 +2977 35 14 1 +2978 35 15 0 +2979 35 15 1 +2980 34 14 0 +2981 34 14 1 +2982 34 15 0 +2983 34 15 1 +2984 32 15 1 +2985 32 15 0 +2986 32 14 1 +2987 32 14 0 +2988 33 15 1 +2989 33 15 0 +2990 33 14 1 +2991 33 14 0 +2992 36 14 0 +2993 36 14 1 +2994 36 15 0 +2995 36 15 1 +2996 37 14 0 +2997 37 14 1 +2998 37 15 0 +2999 37 15 1 +3000 39 15 1 +3001 39 15 0 +3002 39 14 1 +3003 39 14 0 +3004 38 15 1 +3005 38 15 0 +3006 38 14 1 +3007 38 14 0 +3008 44 15 0 +3009 44 15 1 +3010 44 14 0 +3011 44 14 1 +3012 45 15 0 +3013 45 15 1 +3014 45 14 0 +3015 45 14 1 +3016 47 14 1 +3017 47 14 0 +3018 47 15 1 +3019 47 15 0 +3020 46 14 1 +3021 46 14 0 +3022 46 15 1 +3023 46 15 0 +3072 43 13 0 +3073 43 13 1 +3074 43 12 0 +3075 43 12 1 +3076 42 13 0 +3077 42 13 1 +3078 42 12 0 +3079 42 12 1 +3080 40 12 1 +3081 40 12 0 +3082 40 13 1 +3083 40 13 0 +3084 41 12 1 +3085 41 12 0 +3086 41 13 1 +3087 41 13 0 +3104 35 12 0 +3105 35 12 1 +3106 35 13 0 +3107 35 13 1 +3108 34 12 0 +3109 34 12 1 +3110 34 13 0 +3111 34 13 1 +3112 32 13 1 +3113 32 13 0 +3114 32 12 1 +3115 32 12 0 +3116 33 13 1 +3117 33 13 0 +3118 33 12 1 +3119 33 12 0 +3120 36 12 0 +3121 36 12 1 +3122 36 13 0 +3123 36 13 1 +3124 37 12 0 +3125 37 12 1 +3126 37 13 0 +3127 37 13 1 +3128 39 13 1 +3129 39 13 0 +3130 39 12 1 +3131 39 12 0 +3132 38 13 1 +3133 38 13 0 +3134 38 12 1 +3135 38 12 0 +3136 44 13 0 +3137 44 13 1 +3138 44 12 0 +3139 44 12 1 +3140 45 13 0 +3141 45 13 1 +3142 45 12 0 +3143 45 12 1 +3144 47 12 1 +3145 47 12 0 +3146 47 13 1 +3147 47 13 0 +3148 46 12 1 +3149 46 12 0 +3150 46 13 1 +3151 46 13 0 +3200 43 11 0 +3201 43 11 1 +3202 43 10 0 +3203 43 10 1 +3204 42 11 0 +3205 42 11 1 +3206 42 10 0 +3207 42 10 1 +3208 40 10 1 +3209 40 10 0 +3210 40 11 1 +3211 40 11 0 +3212 41 10 1 +3213 41 10 0 +3214 41 11 1 +3215 41 11 0 +3232 35 10 0 +3233 35 10 1 +3234 35 11 0 +3235 35 11 1 +3236 34 10 0 +3237 34 10 1 +3238 34 11 0 +3239 34 11 1 +3240 32 11 1 +3241 32 11 0 +3242 32 10 1 +3243 32 10 0 +3244 33 11 1 +3245 33 11 0 +3246 33 10 1 +3247 33 10 0 +3248 36 10 0 +3249 36 10 1 +3250 36 11 0 +3251 36 11 1 +3252 37 10 0 +3253 37 10 1 +3254 37 11 0 +3255 37 11 1 +3256 39 11 1 +3257 39 11 0 +3258 39 10 1 +3259 39 10 0 +3260 38 11 1 +3261 38 11 0 +3262 38 10 1 +3263 38 10 0 +3264 44 11 0 +3265 44 11 1 +3266 44 10 0 +3267 44 10 1 +3268 45 11 0 +3269 45 11 1 +3270 45 10 0 +3271 45 10 1 +3272 47 10 1 +3273 47 10 0 +3274 47 11 1 +3275 47 11 0 +3276 46 10 1 +3277 46 10 0 +3278 46 11 1 +3279 46 11 0 +3328 43 9 0 +3329 43 9 1 +3330 43 8 0 +3331 43 8 1 +3332 42 9 0 +3333 42 9 1 +3334 42 8 0 +3335 42 8 1 +3336 40 8 1 +3337 40 8 0 +3338 40 9 1 +3339 40 9 0 +3340 41 8 1 +3341 41 8 0 +3342 41 9 1 +3343 41 9 0 +3360 35 8 0 +3361 35 8 1 +3362 35 9 0 +3363 35 9 1 +3364 34 8 0 +3365 34 8 1 +3366 34 9 0 +3367 34 9 1 +3368 32 9 1 +3369 32 9 0 +3370 32 8 1 +3371 32 8 0 +3372 33 9 1 +3373 33 9 0 +3374 33 8 1 +3375 33 8 0 +3376 36 8 0 +3377 36 8 1 +3378 36 9 0 +3379 36 9 1 +3380 37 8 0 +3381 37 8 1 +3382 37 9 0 +3383 37 9 1 +3384 39 9 1 +3385 39 9 0 +3386 39 8 1 +3387 39 8 0 +3388 38 9 1 +3389 38 9 0 +3390 38 8 1 +3391 38 8 0 +3392 44 9 0 +3393 44 9 1 +3394 44 8 0 +3395 44 8 1 +3396 45 9 0 +3397 45 9 1 +3398 45 8 0 +3399 45 8 1 +3400 47 8 1 +3401 47 8 0 +3402 47 9 1 +3403 47 9 0 +3404 46 8 1 +3405 46 8 0 +3406 46 9 1 +3407 46 9 0 +3456 43 7 0 +3457 43 7 1 +3458 43 6 0 +3459 43 6 1 +3460 42 7 0 +3461 42 7 1 +3462 42 6 0 +3463 42 6 1 +3464 40 6 1 +3465 40 6 0 +3466 40 7 1 +3467 40 7 0 +3468 41 6 1 +3469 41 6 0 +3470 41 7 1 +3471 41 7 0 +3488 35 6 0 +3489 35 6 1 +3490 35 7 0 +3491 35 7 1 +3492 34 6 0 +3493 34 6 1 +3494 34 7 0 +3495 34 7 1 +3496 32 7 1 +3497 32 7 0 +3498 32 6 1 +3499 32 6 0 +3500 33 7 1 +3501 33 7 0 +3502 33 6 1 +3503 33 6 0 +3504 36 6 0 +3505 36 6 1 +3506 36 7 0 +3507 36 7 1 +3508 37 6 0 +3509 37 6 1 +3510 37 7 0 +3511 37 7 1 +3512 39 7 1 +3513 39 7 0 +3514 39 6 1 +3515 39 6 0 +3516 38 7 1 +3517 38 7 0 +3518 38 6 1 +3519 38 6 0 +3520 44 7 0 +3521 44 7 1 +3522 44 6 0 +3523 44 6 1 +3524 45 7 0 +3525 45 7 1 +3526 45 6 0 +3527 45 6 1 +3528 47 6 1 +3529 47 6 0 +3530 47 7 1 +3531 47 7 0 +3532 46 6 1 +3533 46 6 0 +3534 46 7 1 +3535 46 7 0 +3584 43 5 0 +3585 43 5 1 +3586 43 4 0 +3587 43 4 1 +3588 42 5 0 +3589 42 5 1 +3590 42 4 0 +3591 42 4 1 +3592 40 4 1 +3593 40 4 0 +3594 40 5 1 +3595 40 5 0 +3596 41 4 1 +3597 41 4 0 +3598 41 5 1 +3599 41 5 0 +3616 35 4 0 +3617 35 4 1 +3618 35 5 0 +3619 35 5 1 +3620 34 4 0 +3621 34 4 1 +3622 34 5 0 +3623 34 5 1 +3624 32 5 1 +3625 32 5 0 +3626 32 4 1 +3627 32 4 0 +3628 33 5 1 +3629 33 5 0 +3630 33 4 1 +3631 33 4 0 +3632 36 4 0 +3633 36 4 1 +3634 36 5 0 +3635 36 5 1 +3636 37 4 0 +3637 37 4 1 +3638 37 5 0 +3639 37 5 1 +3640 39 5 1 +3641 39 5 0 +3642 39 4 1 +3643 39 4 0 +3644 38 5 1 +3645 38 5 0 +3646 38 4 1 +3647 38 4 0 +3648 44 5 0 +3649 44 5 1 +3650 44 4 0 +3651 44 4 1 +3652 45 5 0 +3653 45 5 1 +3654 45 4 0 +3655 45 4 1 +3656 47 4 1 +3657 47 4 0 +3658 47 5 1 +3659 47 5 0 +3660 46 4 1 +3661 46 4 0 +3662 46 5 1 +3663 46 5 0 +3712 43 3 0 +3713 43 3 1 +3714 43 2 0 +3715 43 2 1 +3716 42 3 0 +3717 42 3 1 +3718 42 2 0 +3719 42 2 1 +3720 40 2 1 +3721 40 2 0 +3722 40 3 1 +3723 40 3 0 +3724 41 2 1 +3725 41 2 0 +3726 41 3 1 +3727 41 3 0 +3744 35 2 0 +3745 35 2 1 +3746 35 3 0 +3747 35 3 1 +3748 34 2 0 +3749 34 2 1 +3750 34 3 0 +3751 34 3 1 +3752 32 3 1 +3753 32 3 0 +3754 32 2 1 +3755 32 2 0 +3756 33 3 1 +3757 33 3 0 +3758 33 2 1 +3759 33 2 0 +3760 36 2 0 +3761 36 2 1 +3762 36 3 0 +3763 36 3 1 +3764 37 2 0 +3765 37 2 1 +3766 37 3 0 +3767 37 3 1 +3768 39 3 1 +3769 39 3 0 +3770 39 2 1 +3771 39 2 0 +3772 38 3 1 +3773 38 3 0 +3774 38 2 1 +3775 38 2 0 +3776 44 3 0 +3777 44 3 1 +3778 44 2 0 +3779 44 2 1 +3780 45 3 0 +3781 45 3 1 +3782 45 2 0 +3783 45 2 1 +3784 47 2 1 +3785 47 2 0 +3786 47 3 1 +3787 47 3 0 +3788 46 2 1 +3789 46 2 0 +3790 46 3 1 +3791 46 3 0 +3840 43 1 0 +3841 43 1 1 +3842 43 0 0 +3843 43 0 1 +3844 42 1 0 +3845 42 1 1 +3846 42 0 0 +3847 42 0 1 +3848 40 0 1 +3849 40 0 0 +3850 40 1 1 +3851 40 1 0 +3852 41 0 1 +3853 41 0 0 +3854 41 1 1 +3855 41 1 0 +3872 35 0 0 +3873 35 0 1 +3874 35 1 0 +3875 35 1 1 +3876 34 0 0 +3877 34 0 1 +3878 34 1 0 +3879 34 1 1 +3880 32 1 1 +3881 32 1 0 +3882 32 0 1 +3883 32 0 0 +3884 33 1 1 +3885 33 1 0 +3886 33 0 1 +3887 33 0 0 +3888 36 0 0 +3889 36 0 1 +3890 36 1 0 +3891 36 1 1 +3892 37 0 0 +3893 37 0 1 +3894 37 1 0 +3895 37 1 1 +3896 39 1 1 +3897 39 1 0 +3898 39 0 1 +3899 39 0 0 +3900 38 1 1 +3901 38 1 0 +3902 38 0 1 +3903 38 0 0 +3904 44 1 0 +3905 44 1 1 +3906 44 0 0 +3907 44 0 1 +3908 45 1 0 +3909 45 1 1 +3910 45 0 0 +3911 45 0 1 +3912 47 0 1 +3913 47 0 0 +3914 47 1 1 +3915 47 1 0 +3916 46 0 1 +3917 46 0 0 +3918 46 1 1 +3919 46 1 0 diff --git a/Detectors/PHOS/base/files/Mod1RCU3.data b/Detectors/PHOS/base/files/Mod1RCU3.data new file mode 100644 index 0000000000000..43bd76fc42791 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod1RCU3.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 3 0 2 + 1 3 1 2 + 2 3 2 2 + 3 3 3 2 + 4 3 4 2 + 5 3 5 2 + 6 3 6 2 + 7 3 7 2 + 8 3 8 2 + 9 3 9 2 + 10 3 10 2 + 11 3 11 2 + 12 3 12 2 + 13 3 13 2 + 14 3 14 2 + 15 3 15 2 + 16 3 16 2 + 17 3 17 2 + 18 3 18 2 + 19 3 19 2 + 20 3 20 2 + 21 3 21 2 + 22 3 22 2 + 23 3 23 2 + 24 3 24 2 + 25 3 25 2 + 26 3 26 2 + 27 3 27 2 + 28 3 28 2 + 29 3 29 2 + 30 3 30 2 + 31 3 31 2 + 32 3 32 2 + 33 3 33 2 + 34 3 34 2 + 35 3 35 2 + 36 3 36 2 + 37 3 37 2 + 38 3 38 2 + 39 3 39 2 + 40 3 40 2 + 41 3 41 2 + 42 3 42 2 + 43 3 43 2 + 44 3 44 2 + 45 3 45 2 + 46 3 46 2 + 47 3 47 2 + 48 3 48 2 + 49 3 49 2 + 50 3 50 2 + 51 3 51 2 + 52 3 52 2 + 53 3 53 2 + 54 3 54 2 + 55 3 55 2 + 56 3 56 2 + 57 3 57 2 + 58 3 58 2 + 59 3 59 2 + 60 3 60 2 + 61 3 61 2 + 62 3 62 2 + 63 3 63 2 + 64 3 64 2 + 65 3 65 2 + 66 3 66 2 + 67 3 67 2 + 68 3 68 2 + 69 3 69 2 + 70 3 70 2 + 71 3 71 2 + 72 3 72 2 + 73 3 73 2 + 74 3 74 2 + 75 3 75 2 + 76 3 76 2 + 77 3 77 2 + 78 3 78 2 + 79 3 79 2 + 80 3 80 2 + 81 3 81 2 + 82 3 82 2 + 83 3 83 2 + 84 3 84 2 + 85 3 85 2 + 86 3 86 2 + 87 3 87 2 + 88 3 88 2 + 89 3 89 2 + 90 3 90 2 + 91 3 91 2 + 92 3 92 2 + 93 3 93 2 + 94 3 94 2 + 95 3 95 2 + 96 3 96 2 + 97 3 97 2 + 98 3 98 2 + 99 3 99 2 + 100 3 100 2 + 101 3 101 2 + 102 3 102 2 + 103 3 103 2 + 104 3 104 2 + 105 3 105 2 + 106 3 106 2 + 107 3 107 2 + 108 3 108 2 + 109 3 109 2 + 110 3 110 2 + 111 3 111 2 + 112 3 112 2 + 113 3 113 2 + 114 3 114 2 + 115 3 115 2 + 116 3 116 2 + 117 3 117 2 + 118 3 118 2 + 119 3 119 2 + 120 3 120 2 + 121 3 121 2 + 122 3 122 2 + 123 3 123 2 + 124 3 124 2 + 125 3 125 2 + 126 3 126 2 + 127 3 127 2 +2048 3 2048 2 +2049 3 2049 2 +2050 3 2050 2 +2051 3 2051 2 +2052 3 2052 2 +2053 3 2053 2 +2054 3 2054 2 +2055 3 2055 2 +2056 3 2056 2 +2057 3 2057 2 +2058 3 2058 2 +2059 3 2059 2 +2060 3 2060 2 +2061 3 2061 2 +2062 3 2062 2 +2063 3 2063 2 +2064 3 2064 2 +2065 3 2065 2 +2066 3 2066 2 +2067 3 2067 2 +2068 3 2068 2 +2069 3 2069 2 +2070 3 2070 2 +2071 3 2071 2 +2072 3 2072 2 +2073 3 2073 2 +2074 3 2074 2 +2075 3 2075 2 +2076 3 2076 2 +2077 3 2077 2 +2078 3 2078 2 +2079 3 2079 2 +2080 3 2080 2 +2081 3 2081 2 +2082 3 2082 2 +2083 3 2083 2 +2084 3 2084 2 +2085 3 2085 2 +2086 3 2086 2 +2087 3 2087 2 +2088 3 2088 2 +2089 3 2089 2 +2090 3 2090 2 +2091 3 2091 2 +2092 3 2092 2 +2093 3 2093 2 +2094 3 2094 2 +2095 3 2095 2 +2096 3 2096 2 +2097 3 2097 2 +2098 3 2098 2 +2099 3 2099 2 +2100 3 2100 2 +2101 3 2101 2 +2102 3 2102 2 +2103 3 2103 2 +2104 3 2104 2 +2105 3 2105 2 +2106 3 2106 2 +2107 3 2107 2 +2108 3 2108 2 +2109 3 2109 2 +2110 3 2110 2 +2111 3 2111 2 +2112 3 2112 2 +2113 3 2113 2 +2114 3 2114 2 +2115 3 2115 2 +2116 3 2116 2 +2117 3 2117 2 +2118 3 2118 2 +2119 3 2119 2 +2120 3 2120 2 +2121 3 2121 2 +2122 3 2122 2 +2123 3 2123 2 +2124 3 2124 2 +2125 3 2125 2 +2126 3 2126 2 +2127 3 2127 2 +2128 3 2128 2 +2129 3 2129 2 +2130 3 2130 2 +2131 3 2131 2 +2132 3 2132 2 +2133 3 2133 2 +2134 3 2134 2 +2135 3 2135 2 +2136 3 2136 2 +2137 3 2137 2 +2138 3 2138 2 +2139 3 2139 2 +2140 3 2140 2 +2141 3 2141 2 +2142 3 2142 2 +2143 3 2143 2 +2144 3 2144 2 +2145 3 2145 2 +2146 3 2146 2 +2147 3 2147 2 +2148 3 2148 2 +2149 3 2149 2 +2150 3 2150 2 +2151 3 2151 2 +2152 3 2152 2 +2153 3 2153 2 +2154 3 2154 2 +2155 3 2155 2 +2156 3 2156 2 +2157 3 2157 2 +2158 3 2158 2 +2159 3 2159 2 +2160 3 2160 2 +2161 3 2161 2 +2162 3 2162 2 +2163 3 2163 2 +2164 3 2164 2 +2165 3 2165 2 +2166 3 2166 2 +2167 3 2167 2 +2168 3 2168 2 +2169 3 2169 2 +2170 3 2170 2 +2171 3 2171 2 +2172 3 2172 2 +2173 3 2173 2 +2174 3 2174 2 +2175 3 2175 2 + 128 59 29 0 + 129 59 29 1 + 130 59 28 0 + 131 59 28 1 + 132 58 29 0 + 133 58 29 1 + 134 58 28 0 + 135 58 28 1 + 136 56 28 1 + 137 56 28 0 + 138 56 29 1 + 139 56 29 0 + 140 57 28 1 + 141 57 28 0 + 142 57 29 1 + 143 57 29 0 + 160 51 28 0 + 161 51 28 1 + 162 51 29 0 + 163 51 29 1 + 164 50 28 0 + 165 50 28 1 + 166 50 29 0 + 167 50 29 1 + 168 48 29 1 + 169 48 29 0 + 170 48 28 1 + 171 48 28 0 + 172 49 29 1 + 173 49 29 0 + 174 49 28 1 + 175 49 28 0 + 176 52 28 0 + 177 52 28 1 + 178 52 29 0 + 179 52 29 1 + 180 53 28 0 + 181 53 28 1 + 182 53 29 0 + 183 53 29 1 + 184 55 29 1 + 185 55 29 0 + 186 55 28 1 + 187 55 28 0 + 188 54 29 1 + 189 54 29 0 + 190 54 28 1 + 191 54 28 0 + 192 60 29 0 + 193 60 29 1 + 194 60 28 0 + 195 60 28 1 + 196 61 29 0 + 197 61 29 1 + 198 61 28 0 + 199 61 28 1 + 200 63 28 1 + 201 63 28 0 + 202 63 29 1 + 203 63 29 0 + 204 62 28 1 + 205 62 28 0 + 206 62 29 1 + 207 62 29 0 + 256 59 31 0 + 257 59 31 1 + 258 59 30 0 + 259 59 30 1 + 260 58 31 0 + 261 58 31 1 + 262 58 30 0 + 263 58 30 1 + 264 56 30 1 + 265 56 30 0 + 266 56 31 1 + 267 56 31 0 + 268 57 30 1 + 269 57 30 0 + 270 57 31 1 + 271 57 31 0 + 288 51 30 0 + 289 51 30 1 + 290 51 31 0 + 291 51 31 1 + 292 50 30 0 + 293 50 30 1 + 294 50 31 0 + 295 50 31 1 + 296 48 31 1 + 297 48 31 0 + 298 48 30 1 + 299 48 30 0 + 300 49 31 1 + 301 49 31 0 + 302 49 30 1 + 303 49 30 0 + 304 52 30 0 + 305 52 30 1 + 306 52 31 0 + 307 52 31 1 + 308 53 30 0 + 309 53 30 1 + 310 53 31 0 + 311 53 31 1 + 312 55 31 1 + 313 55 31 0 + 314 55 30 1 + 315 55 30 0 + 316 54 31 1 + 317 54 31 0 + 318 54 30 1 + 319 54 30 0 + 320 60 31 0 + 321 60 31 1 + 322 60 30 0 + 323 60 30 1 + 324 61 31 0 + 325 61 31 1 + 326 61 30 0 + 327 61 30 1 + 328 63 30 1 + 329 63 30 0 + 330 63 31 1 + 331 63 31 0 + 332 62 30 1 + 333 62 30 0 + 334 62 31 1 + 335 62 31 0 + 384 59 33 0 + 385 59 33 1 + 386 59 32 0 + 387 59 32 1 + 388 58 33 0 + 389 58 33 1 + 390 58 32 0 + 391 58 32 1 + 392 56 32 1 + 393 56 32 0 + 394 56 33 1 + 395 56 33 0 + 396 57 32 1 + 397 57 32 0 + 398 57 33 1 + 399 57 33 0 + 416 51 32 0 + 417 51 32 1 + 418 51 33 0 + 419 51 33 1 + 420 50 32 0 + 421 50 32 1 + 422 50 33 0 + 423 50 33 1 + 424 48 33 1 + 425 48 33 0 + 426 48 32 1 + 427 48 32 0 + 428 49 33 1 + 429 49 33 0 + 430 49 32 1 + 431 49 32 0 + 432 52 32 0 + 433 52 32 1 + 434 52 33 0 + 435 52 33 1 + 436 53 32 0 + 437 53 32 1 + 438 53 33 0 + 439 53 33 1 + 440 55 33 1 + 441 55 33 0 + 442 55 32 1 + 443 55 32 0 + 444 54 33 1 + 445 54 33 0 + 446 54 32 1 + 447 54 32 0 + 448 60 33 0 + 449 60 33 1 + 450 60 32 0 + 451 60 32 1 + 452 61 33 0 + 453 61 33 1 + 454 61 32 0 + 455 61 32 1 + 456 63 32 1 + 457 63 32 0 + 458 63 33 1 + 459 63 33 0 + 460 62 32 1 + 461 62 32 0 + 462 62 33 1 + 463 62 33 0 + 512 59 35 0 + 513 59 35 1 + 514 59 34 0 + 515 59 34 1 + 516 58 35 0 + 517 58 35 1 + 518 58 34 0 + 519 58 34 1 + 520 56 34 1 + 521 56 34 0 + 522 56 35 1 + 523 56 35 0 + 524 57 34 1 + 525 57 34 0 + 526 57 35 1 + 527 57 35 0 + 544 51 34 0 + 545 51 34 1 + 546 51 35 0 + 547 51 35 1 + 548 50 34 0 + 549 50 34 1 + 550 50 35 0 + 551 50 35 1 + 552 48 35 1 + 553 48 35 0 + 554 48 34 1 + 555 48 34 0 + 556 49 35 1 + 557 49 35 0 + 558 49 34 1 + 559 49 34 0 + 560 52 34 0 + 561 52 34 1 + 562 52 35 0 + 563 52 35 1 + 564 53 34 0 + 565 53 34 1 + 566 53 35 0 + 567 53 35 1 + 568 55 35 1 + 569 55 35 0 + 570 55 34 1 + 571 55 34 0 + 572 54 35 1 + 573 54 35 0 + 574 54 34 1 + 575 54 34 0 + 576 60 35 0 + 577 60 35 1 + 578 60 34 0 + 579 60 34 1 + 580 61 35 0 + 581 61 35 1 + 582 61 34 0 + 583 61 34 1 + 584 63 34 1 + 585 63 34 0 + 586 63 35 1 + 587 63 35 0 + 588 62 34 1 + 589 62 34 0 + 590 62 35 1 + 591 62 35 0 + 640 59 37 0 + 641 59 37 1 + 642 59 36 0 + 643 59 36 1 + 644 58 37 0 + 645 58 37 1 + 646 58 36 0 + 647 58 36 1 + 648 56 36 1 + 649 56 36 0 + 650 56 37 1 + 651 56 37 0 + 652 57 36 1 + 653 57 36 0 + 654 57 37 1 + 655 57 37 0 + 672 51 36 0 + 673 51 36 1 + 674 51 37 0 + 675 51 37 1 + 676 50 36 0 + 677 50 36 1 + 678 50 37 0 + 679 50 37 1 + 680 48 37 1 + 681 48 37 0 + 682 48 36 1 + 683 48 36 0 + 684 49 37 1 + 685 49 37 0 + 686 49 36 1 + 687 49 36 0 + 688 52 36 0 + 689 52 36 1 + 690 52 37 0 + 691 52 37 1 + 692 53 36 0 + 693 53 36 1 + 694 53 37 0 + 695 53 37 1 + 696 55 37 1 + 697 55 37 0 + 698 55 36 1 + 699 55 36 0 + 700 54 37 1 + 701 54 37 0 + 702 54 36 1 + 703 54 36 0 + 704 60 37 0 + 705 60 37 1 + 706 60 36 0 + 707 60 36 1 + 708 61 37 0 + 709 61 37 1 + 710 61 36 0 + 711 61 36 1 + 712 63 36 1 + 713 63 36 0 + 714 63 37 1 + 715 63 37 0 + 716 62 36 1 + 717 62 36 0 + 718 62 37 1 + 719 62 37 0 + 768 59 39 0 + 769 59 39 1 + 770 59 38 0 + 771 59 38 1 + 772 58 39 0 + 773 58 39 1 + 774 58 38 0 + 775 58 38 1 + 776 56 38 1 + 777 56 38 0 + 778 56 39 1 + 779 56 39 0 + 780 57 38 1 + 781 57 38 0 + 782 57 39 1 + 783 57 39 0 + 800 51 38 0 + 801 51 38 1 + 802 51 39 0 + 803 51 39 1 + 804 50 38 0 + 805 50 38 1 + 806 50 39 0 + 807 50 39 1 + 808 48 39 1 + 809 48 39 0 + 810 48 38 1 + 811 48 38 0 + 812 49 39 1 + 813 49 39 0 + 814 49 38 1 + 815 49 38 0 + 816 52 38 0 + 817 52 38 1 + 818 52 39 0 + 819 52 39 1 + 820 53 38 0 + 821 53 38 1 + 822 53 39 0 + 823 53 39 1 + 824 55 39 1 + 825 55 39 0 + 826 55 38 1 + 827 55 38 0 + 828 54 39 1 + 829 54 39 0 + 830 54 38 1 + 831 54 38 0 + 832 60 39 0 + 833 60 39 1 + 834 60 38 0 + 835 60 38 1 + 836 61 39 0 + 837 61 39 1 + 838 61 38 0 + 839 61 38 1 + 840 63 38 1 + 841 63 38 0 + 842 63 39 1 + 843 63 39 0 + 844 62 38 1 + 845 62 38 0 + 846 62 39 1 + 847 62 39 0 + 896 59 41 0 + 897 59 41 1 + 898 59 40 0 + 899 59 40 1 + 900 58 41 0 + 901 58 41 1 + 902 58 40 0 + 903 58 40 1 + 904 56 40 1 + 905 56 40 0 + 906 56 41 1 + 907 56 41 0 + 908 57 40 1 + 909 57 40 0 + 910 57 41 1 + 911 57 41 0 + 928 51 40 0 + 929 51 40 1 + 930 51 41 0 + 931 51 41 1 + 932 50 40 0 + 933 50 40 1 + 934 50 41 0 + 935 50 41 1 + 936 48 41 1 + 937 48 41 0 + 938 48 40 1 + 939 48 40 0 + 940 49 41 1 + 941 49 41 0 + 942 49 40 1 + 943 49 40 0 + 944 52 40 0 + 945 52 40 1 + 946 52 41 0 + 947 52 41 1 + 948 53 40 0 + 949 53 40 1 + 950 53 41 0 + 951 53 41 1 + 952 55 41 1 + 953 55 41 0 + 954 55 40 1 + 955 55 40 0 + 956 54 41 1 + 957 54 41 0 + 958 54 40 1 + 959 54 40 0 + 960 60 41 0 + 961 60 41 1 + 962 60 40 0 + 963 60 40 1 + 964 61 41 0 + 965 61 41 1 + 966 61 40 0 + 967 61 40 1 + 968 63 40 1 + 969 63 40 0 + 970 63 41 1 + 971 63 41 0 + 972 62 40 1 + 973 62 40 0 + 974 62 41 1 + 975 62 41 0 +1024 59 43 0 +1025 59 43 1 +1026 59 42 0 +1027 59 42 1 +1028 58 43 0 +1029 58 43 1 +1030 58 42 0 +1031 58 42 1 +1032 56 42 1 +1033 56 42 0 +1034 56 43 1 +1035 56 43 0 +1036 57 42 1 +1037 57 42 0 +1038 57 43 1 +1039 57 43 0 +1056 51 42 0 +1057 51 42 1 +1058 51 43 0 +1059 51 43 1 +1060 50 42 0 +1061 50 42 1 +1062 50 43 0 +1063 50 43 1 +1064 48 43 1 +1065 48 43 0 +1066 48 42 1 +1067 48 42 0 +1068 49 43 1 +1069 49 43 0 +1070 49 42 1 +1071 49 42 0 +1072 52 42 0 +1073 52 42 1 +1074 52 43 0 +1075 52 43 1 +1076 53 42 0 +1077 53 42 1 +1078 53 43 0 +1079 53 43 1 +1080 55 43 1 +1081 55 43 0 +1082 55 42 1 +1083 55 42 0 +1084 54 43 1 +1085 54 43 0 +1086 54 42 1 +1087 54 42 0 +1088 60 43 0 +1089 60 43 1 +1090 60 42 0 +1091 60 42 1 +1092 61 43 0 +1093 61 43 1 +1094 61 42 0 +1095 61 42 1 +1096 63 42 1 +1097 63 42 0 +1098 63 43 1 +1099 63 43 0 +1100 62 42 1 +1101 62 42 0 +1102 62 43 1 +1103 62 43 0 +1152 59 45 0 +1153 59 45 1 +1154 59 44 0 +1155 59 44 1 +1156 58 45 0 +1157 58 45 1 +1158 58 44 0 +1159 58 44 1 +1160 56 44 1 +1161 56 44 0 +1162 56 45 1 +1163 56 45 0 +1164 57 44 1 +1165 57 44 0 +1166 57 45 1 +1167 57 45 0 +1184 51 44 0 +1185 51 44 1 +1186 51 45 0 +1187 51 45 1 +1188 50 44 0 +1189 50 44 1 +1190 50 45 0 +1191 50 45 1 +1192 48 45 1 +1193 48 45 0 +1194 48 44 1 +1195 48 44 0 +1196 49 45 1 +1197 49 45 0 +1198 49 44 1 +1199 49 44 0 +1200 52 44 0 +1201 52 44 1 +1202 52 45 0 +1203 52 45 1 +1204 53 44 0 +1205 53 44 1 +1206 53 45 0 +1207 53 45 1 +1208 55 45 1 +1209 55 45 0 +1210 55 44 1 +1211 55 44 0 +1212 54 45 1 +1213 54 45 0 +1214 54 44 1 +1215 54 44 0 +1216 60 45 0 +1217 60 45 1 +1218 60 44 0 +1219 60 44 1 +1220 61 45 0 +1221 61 45 1 +1222 61 44 0 +1223 61 44 1 +1224 63 44 1 +1225 63 44 0 +1226 63 45 1 +1227 63 45 0 +1228 62 44 1 +1229 62 44 0 +1230 62 45 1 +1231 62 45 0 +1280 59 47 0 +1281 59 47 1 +1282 59 46 0 +1283 59 46 1 +1284 58 47 0 +1285 58 47 1 +1286 58 46 0 +1287 58 46 1 +1288 56 46 1 +1289 56 46 0 +1290 56 47 1 +1291 56 47 0 +1292 57 46 1 +1293 57 46 0 +1294 57 47 1 +1295 57 47 0 +1312 51 46 0 +1313 51 46 1 +1314 51 47 0 +1315 51 47 1 +1316 50 46 0 +1317 50 46 1 +1318 50 47 0 +1319 50 47 1 +1320 48 47 1 +1321 48 47 0 +1322 48 46 1 +1323 48 46 0 +1324 49 47 1 +1325 49 47 0 +1326 49 46 1 +1327 49 46 0 +1328 52 46 0 +1329 52 46 1 +1330 52 47 0 +1331 52 47 1 +1332 53 46 0 +1333 53 46 1 +1334 53 47 0 +1335 53 47 1 +1336 55 47 1 +1337 55 47 0 +1338 55 46 1 +1339 55 46 0 +1340 54 47 1 +1341 54 47 0 +1342 54 46 1 +1343 54 46 0 +1344 60 47 0 +1345 60 47 1 +1346 60 46 0 +1347 60 46 1 +1348 61 47 0 +1349 61 47 1 +1350 61 46 0 +1351 61 46 1 +1352 63 46 1 +1353 63 46 0 +1354 63 47 1 +1355 63 47 0 +1356 62 46 1 +1357 62 46 0 +1358 62 47 1 +1359 62 47 0 +1408 59 49 0 +1409 59 49 1 +1410 59 48 0 +1411 59 48 1 +1412 58 49 0 +1413 58 49 1 +1414 58 48 0 +1415 58 48 1 +1416 56 48 1 +1417 56 48 0 +1418 56 49 1 +1419 56 49 0 +1420 57 48 1 +1421 57 48 0 +1422 57 49 1 +1423 57 49 0 +1440 51 48 0 +1441 51 48 1 +1442 51 49 0 +1443 51 49 1 +1444 50 48 0 +1445 50 48 1 +1446 50 49 0 +1447 50 49 1 +1448 48 49 1 +1449 48 49 0 +1450 48 48 1 +1451 48 48 0 +1452 49 49 1 +1453 49 49 0 +1454 49 48 1 +1455 49 48 0 +1456 52 48 0 +1457 52 48 1 +1458 52 49 0 +1459 52 49 1 +1460 53 48 0 +1461 53 48 1 +1462 53 49 0 +1463 53 49 1 +1464 55 49 1 +1465 55 49 0 +1466 55 48 1 +1467 55 48 0 +1468 54 49 1 +1469 54 49 0 +1470 54 48 1 +1471 54 48 0 +1472 60 49 0 +1473 60 49 1 +1474 60 48 0 +1475 60 48 1 +1476 61 49 0 +1477 61 49 1 +1478 61 48 0 +1479 61 48 1 +1480 63 48 1 +1481 63 48 0 +1482 63 49 1 +1483 63 49 0 +1484 62 48 1 +1485 62 48 0 +1486 62 49 1 +1487 62 49 0 +1536 59 51 0 +1537 59 51 1 +1538 59 50 0 +1539 59 50 1 +1540 58 51 0 +1541 58 51 1 +1542 58 50 0 +1543 58 50 1 +1544 56 50 1 +1545 56 50 0 +1546 56 51 1 +1547 56 51 0 +1548 57 50 1 +1549 57 50 0 +1550 57 51 1 +1551 57 51 0 +1568 51 50 0 +1569 51 50 1 +1570 51 51 0 +1571 51 51 1 +1572 50 50 0 +1573 50 50 1 +1574 50 51 0 +1575 50 51 1 +1576 48 51 1 +1577 48 51 0 +1578 48 50 1 +1579 48 50 0 +1580 49 51 1 +1581 49 51 0 +1582 49 50 1 +1583 49 50 0 +1584 52 50 0 +1585 52 50 1 +1586 52 51 0 +1587 52 51 1 +1588 53 50 0 +1589 53 50 1 +1590 53 51 0 +1591 53 51 1 +1592 55 51 1 +1593 55 51 0 +1594 55 50 1 +1595 55 50 0 +1596 54 51 1 +1597 54 51 0 +1598 54 50 1 +1599 54 50 0 +1600 60 51 0 +1601 60 51 1 +1602 60 50 0 +1603 60 50 1 +1604 61 51 0 +1605 61 51 1 +1606 61 50 0 +1607 61 50 1 +1608 63 50 1 +1609 63 50 0 +1610 63 51 1 +1611 63 51 0 +1612 62 50 1 +1613 62 50 0 +1614 62 51 1 +1615 62 51 0 +1664 59 53 0 +1665 59 53 1 +1666 59 52 0 +1667 59 52 1 +1668 58 53 0 +1669 58 53 1 +1670 58 52 0 +1671 58 52 1 +1672 56 52 1 +1673 56 52 0 +1674 56 53 1 +1675 56 53 0 +1676 57 52 1 +1677 57 52 0 +1678 57 53 1 +1679 57 53 0 +1696 51 52 0 +1697 51 52 1 +1698 51 53 0 +1699 51 53 1 +1700 50 52 0 +1701 50 52 1 +1702 50 53 0 +1703 50 53 1 +1704 48 53 1 +1705 48 53 0 +1706 48 52 1 +1707 48 52 0 +1708 49 53 1 +1709 49 53 0 +1710 49 52 1 +1711 49 52 0 +1712 52 52 0 +1713 52 52 1 +1714 52 53 0 +1715 52 53 1 +1716 53 52 0 +1717 53 52 1 +1718 53 53 0 +1719 53 53 1 +1720 55 53 1 +1721 55 53 0 +1722 55 52 1 +1723 55 52 0 +1724 54 53 1 +1725 54 53 0 +1726 54 52 1 +1727 54 52 0 +1728 60 53 0 +1729 60 53 1 +1730 60 52 0 +1731 60 52 1 +1732 61 53 0 +1733 61 53 1 +1734 61 52 0 +1735 61 52 1 +1736 63 52 1 +1737 63 52 0 +1738 63 53 1 +1739 63 53 0 +1740 62 52 1 +1741 62 52 0 +1742 62 53 1 +1743 62 53 0 +1792 59 55 0 +1793 59 55 1 +1794 59 54 0 +1795 59 54 1 +1796 58 55 0 +1797 58 55 1 +1798 58 54 0 +1799 58 54 1 +1800 56 54 1 +1801 56 54 0 +1802 56 55 1 +1803 56 55 0 +1804 57 54 1 +1805 57 54 0 +1806 57 55 1 +1807 57 55 0 +1824 51 54 0 +1825 51 54 1 +1826 51 55 0 +1827 51 55 1 +1828 50 54 0 +1829 50 54 1 +1830 50 55 0 +1831 50 55 1 +1832 48 55 1 +1833 48 55 0 +1834 48 54 1 +1835 48 54 0 +1836 49 55 1 +1837 49 55 0 +1838 49 54 1 +1839 49 54 0 +1840 52 54 0 +1841 52 54 1 +1842 52 55 0 +1843 52 55 1 +1844 53 54 0 +1845 53 54 1 +1846 53 55 0 +1847 53 55 1 +1848 55 55 1 +1849 55 55 0 +1850 55 54 1 +1851 55 54 0 +1852 54 55 1 +1853 54 55 0 +1854 54 54 1 +1855 54 54 0 +1856 60 55 0 +1857 60 55 1 +1858 60 54 0 +1859 60 54 1 +1860 61 55 0 +1861 61 55 1 +1862 61 54 0 +1863 61 54 1 +1864 63 54 1 +1865 63 54 0 +1866 63 55 1 +1867 63 55 0 +1868 62 54 1 +1869 62 54 0 +1870 62 55 1 +1871 62 55 0 +2176 59 27 0 +2177 59 27 1 +2178 59 26 0 +2179 59 26 1 +2180 58 27 0 +2181 58 27 1 +2182 58 26 0 +2183 58 26 1 +2184 56 26 1 +2185 56 26 0 +2186 56 27 1 +2187 56 27 0 +2188 57 26 1 +2189 57 26 0 +2190 57 27 1 +2191 57 27 0 +2208 51 26 0 +2209 51 26 1 +2210 51 27 0 +2211 51 27 1 +2212 50 26 0 +2213 50 26 1 +2214 50 27 0 +2215 50 27 1 +2216 48 27 1 +2217 48 27 0 +2218 48 26 1 +2219 48 26 0 +2220 49 27 1 +2221 49 27 0 +2222 49 26 1 +2223 49 26 0 +2224 52 26 0 +2225 52 26 1 +2226 52 27 0 +2227 52 27 1 +2228 53 26 0 +2229 53 26 1 +2230 53 27 0 +2231 53 27 1 +2232 55 27 1 +2233 55 27 0 +2234 55 26 1 +2235 55 26 0 +2236 54 27 1 +2237 54 27 0 +2238 54 26 1 +2239 54 26 0 +2240 60 27 0 +2241 60 27 1 +2242 60 26 0 +2243 60 26 1 +2244 61 27 0 +2245 61 27 1 +2246 61 26 0 +2247 61 26 1 +2248 63 26 1 +2249 63 26 0 +2250 63 27 1 +2251 63 27 0 +2252 62 26 1 +2253 62 26 0 +2254 62 27 1 +2255 62 27 0 +2304 59 25 0 +2305 59 25 1 +2306 59 24 0 +2307 59 24 1 +2308 58 25 0 +2309 58 25 1 +2310 58 24 0 +2311 58 24 1 +2312 56 24 1 +2313 56 24 0 +2314 56 25 1 +2315 56 25 0 +2316 57 24 1 +2317 57 24 0 +2318 57 25 1 +2319 57 25 0 +2336 51 24 0 +2337 51 24 1 +2338 51 25 0 +2339 51 25 1 +2340 50 24 0 +2341 50 24 1 +2342 50 25 0 +2343 50 25 1 +2344 48 25 1 +2345 48 25 0 +2346 48 24 1 +2347 48 24 0 +2348 49 25 1 +2349 49 25 0 +2350 49 24 1 +2351 49 24 0 +2352 52 24 0 +2353 52 24 1 +2354 52 25 0 +2355 52 25 1 +2356 53 24 0 +2357 53 24 1 +2358 53 25 0 +2359 53 25 1 +2360 55 25 1 +2361 55 25 0 +2362 55 24 1 +2363 55 24 0 +2364 54 25 1 +2365 54 25 0 +2366 54 24 1 +2367 54 24 0 +2368 60 25 0 +2369 60 25 1 +2370 60 24 0 +2371 60 24 1 +2372 61 25 0 +2373 61 25 1 +2374 61 24 0 +2375 61 24 1 +2376 63 24 1 +2377 63 24 0 +2378 63 25 1 +2379 63 25 0 +2380 62 24 1 +2381 62 24 0 +2382 62 25 1 +2383 62 25 0 +2432 59 23 0 +2433 59 23 1 +2434 59 22 0 +2435 59 22 1 +2436 58 23 0 +2437 58 23 1 +2438 58 22 0 +2439 58 22 1 +2440 56 22 1 +2441 56 22 0 +2442 56 23 1 +2443 56 23 0 +2444 57 22 1 +2445 57 22 0 +2446 57 23 1 +2447 57 23 0 +2464 51 22 0 +2465 51 22 1 +2466 51 23 0 +2467 51 23 1 +2468 50 22 0 +2469 50 22 1 +2470 50 23 0 +2471 50 23 1 +2472 48 23 1 +2473 48 23 0 +2474 48 22 1 +2475 48 22 0 +2476 49 23 1 +2477 49 23 0 +2478 49 22 1 +2479 49 22 0 +2480 52 22 0 +2481 52 22 1 +2482 52 23 0 +2483 52 23 1 +2484 53 22 0 +2485 53 22 1 +2486 53 23 0 +2487 53 23 1 +2488 55 23 1 +2489 55 23 0 +2490 55 22 1 +2491 55 22 0 +2492 54 23 1 +2493 54 23 0 +2494 54 22 1 +2495 54 22 0 +2496 60 23 0 +2497 60 23 1 +2498 60 22 0 +2499 60 22 1 +2500 61 23 0 +2501 61 23 1 +2502 61 22 0 +2503 61 22 1 +2504 63 22 1 +2505 63 22 0 +2506 63 23 1 +2507 63 23 0 +2508 62 22 1 +2509 62 22 0 +2510 62 23 1 +2511 62 23 0 +2560 59 21 0 +2561 59 21 1 +2562 59 20 0 +2563 59 20 1 +2564 58 21 0 +2565 58 21 1 +2566 58 20 0 +2567 58 20 1 +2568 56 20 1 +2569 56 20 0 +2570 56 21 1 +2571 56 21 0 +2572 57 20 1 +2573 57 20 0 +2574 57 21 1 +2575 57 21 0 +2592 51 20 0 +2593 51 20 1 +2594 51 21 0 +2595 51 21 1 +2596 50 20 0 +2597 50 20 1 +2598 50 21 0 +2599 50 21 1 +2600 48 21 1 +2601 48 21 0 +2602 48 20 1 +2603 48 20 0 +2604 49 21 1 +2605 49 21 0 +2606 49 20 1 +2607 49 20 0 +2608 52 20 0 +2609 52 20 1 +2610 52 21 0 +2611 52 21 1 +2612 53 20 0 +2613 53 20 1 +2614 53 21 0 +2615 53 21 1 +2616 55 21 1 +2617 55 21 0 +2618 55 20 1 +2619 55 20 0 +2620 54 21 1 +2621 54 21 0 +2622 54 20 1 +2623 54 20 0 +2624 60 21 0 +2625 60 21 1 +2626 60 20 0 +2627 60 20 1 +2628 61 21 0 +2629 61 21 1 +2630 61 20 0 +2631 61 20 1 +2632 63 20 1 +2633 63 20 0 +2634 63 21 1 +2635 63 21 0 +2636 62 20 1 +2637 62 20 0 +2638 62 21 1 +2639 62 21 0 +2688 59 19 0 +2689 59 19 1 +2690 59 18 0 +2691 59 18 1 +2692 58 19 0 +2693 58 19 1 +2694 58 18 0 +2695 58 18 1 +2696 56 18 1 +2697 56 18 0 +2698 56 19 1 +2699 56 19 0 +2700 57 18 1 +2701 57 18 0 +2702 57 19 1 +2703 57 19 0 +2720 51 18 0 +2721 51 18 1 +2722 51 19 0 +2723 51 19 1 +2724 50 18 0 +2725 50 18 1 +2726 50 19 0 +2727 50 19 1 +2728 48 19 1 +2729 48 19 0 +2730 48 18 1 +2731 48 18 0 +2732 49 19 1 +2733 49 19 0 +2734 49 18 1 +2735 49 18 0 +2736 52 18 0 +2737 52 18 1 +2738 52 19 0 +2739 52 19 1 +2740 53 18 0 +2741 53 18 1 +2742 53 19 0 +2743 53 19 1 +2744 55 19 1 +2745 55 19 0 +2746 55 18 1 +2747 55 18 0 +2748 54 19 1 +2749 54 19 0 +2750 54 18 1 +2751 54 18 0 +2752 60 19 0 +2753 60 19 1 +2754 60 18 0 +2755 60 18 1 +2756 61 19 0 +2757 61 19 1 +2758 61 18 0 +2759 61 18 1 +2760 63 18 1 +2761 63 18 0 +2762 63 19 1 +2763 63 19 0 +2764 62 18 1 +2765 62 18 0 +2766 62 19 1 +2767 62 19 0 +2816 59 17 0 +2817 59 17 1 +2818 59 16 0 +2819 59 16 1 +2820 58 17 0 +2821 58 17 1 +2822 58 16 0 +2823 58 16 1 +2824 56 16 1 +2825 56 16 0 +2826 56 17 1 +2827 56 17 0 +2828 57 16 1 +2829 57 16 0 +2830 57 17 1 +2831 57 17 0 +2848 51 16 0 +2849 51 16 1 +2850 51 17 0 +2851 51 17 1 +2852 50 16 0 +2853 50 16 1 +2854 50 17 0 +2855 50 17 1 +2856 48 17 1 +2857 48 17 0 +2858 48 16 1 +2859 48 16 0 +2860 49 17 1 +2861 49 17 0 +2862 49 16 1 +2863 49 16 0 +2864 52 16 0 +2865 52 16 1 +2866 52 17 0 +2867 52 17 1 +2868 53 16 0 +2869 53 16 1 +2870 53 17 0 +2871 53 17 1 +2872 55 17 1 +2873 55 17 0 +2874 55 16 1 +2875 55 16 0 +2876 54 17 1 +2877 54 17 0 +2878 54 16 1 +2879 54 16 0 +2880 60 17 0 +2881 60 17 1 +2882 60 16 0 +2883 60 16 1 +2884 61 17 0 +2885 61 17 1 +2886 61 16 0 +2887 61 16 1 +2888 63 16 1 +2889 63 16 0 +2890 63 17 1 +2891 63 17 0 +2892 62 16 1 +2893 62 16 0 +2894 62 17 1 +2895 62 17 0 +2944 59 15 0 +2945 59 15 1 +2946 59 14 0 +2947 59 14 1 +2948 58 15 0 +2949 58 15 1 +2950 58 14 0 +2951 58 14 1 +2952 56 14 1 +2953 56 14 0 +2954 56 15 1 +2955 56 15 0 +2956 57 14 1 +2957 57 14 0 +2958 57 15 1 +2959 57 15 0 +2976 51 14 0 +2977 51 14 1 +2978 51 15 0 +2979 51 15 1 +2980 50 14 0 +2981 50 14 1 +2982 50 15 0 +2983 50 15 1 +2984 48 15 1 +2985 48 15 0 +2986 48 14 1 +2987 48 14 0 +2988 49 15 1 +2989 49 15 0 +2990 49 14 1 +2991 49 14 0 +2992 52 14 0 +2993 52 14 1 +2994 52 15 0 +2995 52 15 1 +2996 53 14 0 +2997 53 14 1 +2998 53 15 0 +2999 53 15 1 +3000 55 15 1 +3001 55 15 0 +3002 55 14 1 +3003 55 14 0 +3004 54 15 1 +3005 54 15 0 +3006 54 14 1 +3007 54 14 0 +3008 60 15 0 +3009 60 15 1 +3010 60 14 0 +3011 60 14 1 +3012 61 15 0 +3013 61 15 1 +3014 61 14 0 +3015 61 14 1 +3016 63 14 1 +3017 63 14 0 +3018 63 15 1 +3019 63 15 0 +3020 62 14 1 +3021 62 14 0 +3022 62 15 1 +3023 62 15 0 +3072 59 13 0 +3073 59 13 1 +3074 59 12 0 +3075 59 12 1 +3076 58 13 0 +3077 58 13 1 +3078 58 12 0 +3079 58 12 1 +3080 56 12 1 +3081 56 12 0 +3082 56 13 1 +3083 56 13 0 +3084 57 12 1 +3085 57 12 0 +3086 57 13 1 +3087 57 13 0 +3104 51 12 0 +3105 51 12 1 +3106 51 13 0 +3107 51 13 1 +3108 50 12 0 +3109 50 12 1 +3110 50 13 0 +3111 50 13 1 +3112 48 13 1 +3113 48 13 0 +3114 48 12 1 +3115 48 12 0 +3116 49 13 1 +3117 49 13 0 +3118 49 12 1 +3119 49 12 0 +3120 52 12 0 +3121 52 12 1 +3122 52 13 0 +3123 52 13 1 +3124 53 12 0 +3125 53 12 1 +3126 53 13 0 +3127 53 13 1 +3128 55 13 1 +3129 55 13 0 +3130 55 12 1 +3131 55 12 0 +3132 54 13 1 +3133 54 13 0 +3134 54 12 1 +3135 54 12 0 +3136 60 13 0 +3137 60 13 1 +3138 60 12 0 +3139 60 12 1 +3140 61 13 0 +3141 61 13 1 +3142 61 12 0 +3143 61 12 1 +3144 63 12 1 +3145 63 12 0 +3146 63 13 1 +3147 63 13 0 +3148 62 12 1 +3149 62 12 0 +3150 62 13 1 +3151 62 13 0 +3200 59 11 0 +3201 59 11 1 +3202 59 10 0 +3203 59 10 1 +3204 58 11 0 +3205 58 11 1 +3206 58 10 0 +3207 58 10 1 +3208 56 10 1 +3209 56 10 0 +3210 56 11 1 +3211 56 11 0 +3212 57 10 1 +3213 57 10 0 +3214 57 11 1 +3215 57 11 0 +3232 51 10 0 +3233 51 10 1 +3234 51 11 0 +3235 51 11 1 +3236 50 10 0 +3237 50 10 1 +3238 50 11 0 +3239 50 11 1 +3240 48 11 1 +3241 48 11 0 +3242 48 10 1 +3243 48 10 0 +3244 49 11 1 +3245 49 11 0 +3246 49 10 1 +3247 49 10 0 +3248 52 10 0 +3249 52 10 1 +3250 52 11 0 +3251 52 11 1 +3252 53 10 0 +3253 53 10 1 +3254 53 11 0 +3255 53 11 1 +3256 55 11 1 +3257 55 11 0 +3258 55 10 1 +3259 55 10 0 +3260 54 11 1 +3261 54 11 0 +3262 54 10 1 +3263 54 10 0 +3264 60 11 0 +3265 60 11 1 +3266 60 10 0 +3267 60 10 1 +3268 61 11 0 +3269 61 11 1 +3270 61 10 0 +3271 61 10 1 +3272 63 10 1 +3273 63 10 0 +3274 63 11 1 +3275 63 11 0 +3276 62 10 1 +3277 62 10 0 +3278 62 11 1 +3279 62 11 0 +3328 59 9 0 +3329 59 9 1 +3330 59 8 0 +3331 59 8 1 +3332 58 9 0 +3333 58 9 1 +3334 58 8 0 +3335 58 8 1 +3336 56 8 1 +3337 56 8 0 +3338 56 9 1 +3339 56 9 0 +3340 57 8 1 +3341 57 8 0 +3342 57 9 1 +3343 57 9 0 +3360 51 8 0 +3361 51 8 1 +3362 51 9 0 +3363 51 9 1 +3364 50 8 0 +3365 50 8 1 +3366 50 9 0 +3367 50 9 1 +3368 48 9 1 +3369 48 9 0 +3370 48 8 1 +3371 48 8 0 +3372 49 9 1 +3373 49 9 0 +3374 49 8 1 +3375 49 8 0 +3376 52 8 0 +3377 52 8 1 +3378 52 9 0 +3379 52 9 1 +3380 53 8 0 +3381 53 8 1 +3382 53 9 0 +3383 53 9 1 +3384 55 9 1 +3385 55 9 0 +3386 55 8 1 +3387 55 8 0 +3388 54 9 1 +3389 54 9 0 +3390 54 8 1 +3391 54 8 0 +3392 60 9 0 +3393 60 9 1 +3394 60 8 0 +3395 60 8 1 +3396 61 9 0 +3397 61 9 1 +3398 61 8 0 +3399 61 8 1 +3400 63 8 1 +3401 63 8 0 +3402 63 9 1 +3403 63 9 0 +3404 62 8 1 +3405 62 8 0 +3406 62 9 1 +3407 62 9 0 +3456 59 7 0 +3457 59 7 1 +3458 59 6 0 +3459 59 6 1 +3460 58 7 0 +3461 58 7 1 +3462 58 6 0 +3463 58 6 1 +3464 56 6 1 +3465 56 6 0 +3466 56 7 1 +3467 56 7 0 +3468 57 6 1 +3469 57 6 0 +3470 57 7 1 +3471 57 7 0 +3488 51 6 0 +3489 51 6 1 +3490 51 7 0 +3491 51 7 1 +3492 50 6 0 +3493 50 6 1 +3494 50 7 0 +3495 50 7 1 +3496 48 7 1 +3497 48 7 0 +3498 48 6 1 +3499 48 6 0 +3500 49 7 1 +3501 49 7 0 +3502 49 6 1 +3503 49 6 0 +3504 52 6 0 +3505 52 6 1 +3506 52 7 0 +3507 52 7 1 +3508 53 6 0 +3509 53 6 1 +3510 53 7 0 +3511 53 7 1 +3512 55 7 1 +3513 55 7 0 +3514 55 6 1 +3515 55 6 0 +3516 54 7 1 +3517 54 7 0 +3518 54 6 1 +3519 54 6 0 +3520 60 7 0 +3521 60 7 1 +3522 60 6 0 +3523 60 6 1 +3524 61 7 0 +3525 61 7 1 +3526 61 6 0 +3527 61 6 1 +3528 63 6 1 +3529 63 6 0 +3530 63 7 1 +3531 63 7 0 +3532 62 6 1 +3533 62 6 0 +3534 62 7 1 +3535 62 7 0 +3584 59 5 0 +3585 59 5 1 +3586 59 4 0 +3587 59 4 1 +3588 58 5 0 +3589 58 5 1 +3590 58 4 0 +3591 58 4 1 +3592 56 4 1 +3593 56 4 0 +3594 56 5 1 +3595 56 5 0 +3596 57 4 1 +3597 57 4 0 +3598 57 5 1 +3599 57 5 0 +3616 51 4 0 +3617 51 4 1 +3618 51 5 0 +3619 51 5 1 +3620 50 4 0 +3621 50 4 1 +3622 50 5 0 +3623 50 5 1 +3624 48 5 1 +3625 48 5 0 +3626 48 4 1 +3627 48 4 0 +3628 49 5 1 +3629 49 5 0 +3630 49 4 1 +3631 49 4 0 +3632 52 4 0 +3633 52 4 1 +3634 52 5 0 +3635 52 5 1 +3636 53 4 0 +3637 53 4 1 +3638 53 5 0 +3639 53 5 1 +3640 55 5 1 +3641 55 5 0 +3642 55 4 1 +3643 55 4 0 +3644 54 5 1 +3645 54 5 0 +3646 54 4 1 +3647 54 4 0 +3648 60 5 0 +3649 60 5 1 +3650 60 4 0 +3651 60 4 1 +3652 61 5 0 +3653 61 5 1 +3654 61 4 0 +3655 61 4 1 +3656 63 4 1 +3657 63 4 0 +3658 63 5 1 +3659 63 5 0 +3660 62 4 1 +3661 62 4 0 +3662 62 5 1 +3663 62 5 0 +3712 59 3 0 +3713 59 3 1 +3714 59 2 0 +3715 59 2 1 +3716 58 3 0 +3717 58 3 1 +3718 58 2 0 +3719 58 2 1 +3720 56 2 1 +3721 56 2 0 +3722 56 3 1 +3723 56 3 0 +3724 57 2 1 +3725 57 2 0 +3726 57 3 1 +3727 57 3 0 +3744 51 2 0 +3745 51 2 1 +3746 51 3 0 +3747 51 3 1 +3748 50 2 0 +3749 50 2 1 +3750 50 3 0 +3751 50 3 1 +3752 48 3 1 +3753 48 3 0 +3754 48 2 1 +3755 48 2 0 +3756 49 3 1 +3757 49 3 0 +3758 49 2 1 +3759 49 2 0 +3760 52 2 0 +3761 52 2 1 +3762 52 3 0 +3763 52 3 1 +3764 53 2 0 +3765 53 2 1 +3766 53 3 0 +3767 53 3 1 +3768 55 3 1 +3769 55 3 0 +3770 55 2 1 +3771 55 2 0 +3772 54 3 1 +3773 54 3 0 +3774 54 2 1 +3775 54 2 0 +3776 60 3 0 +3777 60 3 1 +3778 60 2 0 +3779 60 2 1 +3780 61 3 0 +3781 61 3 1 +3782 61 2 0 +3783 61 2 1 +3784 63 2 1 +3785 63 2 0 +3786 63 3 1 +3787 63 3 0 +3788 62 2 1 +3789 62 2 0 +3790 62 3 1 +3791 62 3 0 +3840 59 1 0 +3841 59 1 1 +3842 59 0 0 +3843 59 0 1 +3844 58 1 0 +3845 58 1 1 +3846 58 0 0 +3847 58 0 1 +3848 56 0 1 +3849 56 0 0 +3850 56 1 1 +3851 56 1 0 +3852 57 0 1 +3853 57 0 0 +3854 57 1 1 +3855 57 1 0 +3872 51 0 0 +3873 51 0 1 +3874 51 1 0 +3875 51 1 1 +3876 50 0 0 +3877 50 0 1 +3878 50 1 0 +3879 50 1 1 +3880 48 1 1 +3881 48 1 0 +3882 48 0 1 +3883 48 0 0 +3884 49 1 1 +3885 49 1 0 +3886 49 0 1 +3887 49 0 0 +3888 52 0 0 +3889 52 0 1 +3890 52 1 0 +3891 52 1 1 +3892 53 0 0 +3893 53 0 1 +3894 53 1 0 +3895 53 1 1 +3896 55 1 1 +3897 55 1 0 +3898 55 0 1 +3899 55 0 0 +3900 54 1 1 +3901 54 1 0 +3902 54 0 1 +3903 54 0 0 +3904 60 1 0 +3905 60 1 1 +3906 60 0 0 +3907 60 0 1 +3908 61 1 0 +3909 61 1 1 +3910 61 0 0 +3911 61 0 1 +3912 63 0 1 +3913 63 0 0 +3914 63 1 1 +3915 63 1 0 +3916 62 0 1 +3917 62 0 0 +3918 62 1 1 +3919 62 1 0 diff --git a/Detectors/PHOS/base/files/Mod2RCU0.data b/Detectors/PHOS/base/files/Mod2RCU0.data new file mode 100644 index 0000000000000..4739df6e3e61e --- /dev/null +++ b/Detectors/PHOS/base/files/Mod2RCU0.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 0 0 2 + 1 0 1 2 + 2 0 2 2 + 3 0 3 2 + 4 0 4 2 + 5 0 5 2 + 6 0 6 2 + 7 0 7 2 + 8 0 8 2 + 9 0 9 2 + 10 0 10 2 + 11 0 11 2 + 12 0 12 2 + 13 0 13 2 + 14 0 14 2 + 15 0 15 2 + 16 0 16 2 + 17 0 17 2 + 18 0 18 2 + 19 0 19 2 + 20 0 20 2 + 21 0 21 2 + 22 0 22 2 + 23 0 23 2 + 24 0 24 2 + 25 0 25 2 + 26 0 26 2 + 27 0 27 2 + 28 0 28 2 + 29 0 29 2 + 30 0 30 2 + 31 0 31 2 + 32 0 32 2 + 33 0 33 2 + 34 0 34 2 + 35 0 35 2 + 36 0 36 2 + 37 0 37 2 + 38 0 38 2 + 39 0 39 2 + 40 0 40 2 + 41 0 41 2 + 42 0 42 2 + 43 0 43 2 + 44 0 44 2 + 45 0 45 2 + 46 0 46 2 + 47 0 47 2 + 48 0 48 2 + 49 0 49 2 + 50 0 50 2 + 51 0 51 2 + 52 0 52 2 + 53 0 53 2 + 54 0 54 2 + 55 0 55 2 + 56 0 56 2 + 57 0 57 2 + 58 0 58 2 + 59 0 59 2 + 60 0 60 2 + 61 0 61 2 + 62 0 62 2 + 63 0 63 2 + 64 0 64 2 + 65 0 65 2 + 66 0 66 2 + 67 0 67 2 + 68 0 68 2 + 69 0 69 2 + 70 0 70 2 + 71 0 71 2 + 72 0 72 2 + 73 0 73 2 + 74 0 74 2 + 75 0 75 2 + 76 0 76 2 + 77 0 77 2 + 78 0 78 2 + 79 0 79 2 + 80 0 80 2 + 81 0 81 2 + 82 0 82 2 + 83 0 83 2 + 84 0 84 2 + 85 0 85 2 + 86 0 86 2 + 87 0 87 2 + 88 0 88 2 + 89 0 89 2 + 90 0 90 2 + 91 0 91 2 + 92 0 92 2 + 93 0 93 2 + 94 0 94 2 + 95 0 95 2 + 96 0 96 2 + 97 0 97 2 + 98 0 98 2 + 99 0 99 2 + 100 0 100 2 + 101 0 101 2 + 102 0 102 2 + 103 0 103 2 + 104 0 104 2 + 105 0 105 2 + 106 0 106 2 + 107 0 107 2 + 108 0 108 2 + 109 0 109 2 + 110 0 110 2 + 111 0 111 2 + 112 0 112 2 + 113 0 113 2 + 114 0 114 2 + 115 0 115 2 + 116 0 116 2 + 117 0 117 2 + 118 0 118 2 + 119 0 119 2 + 120 0 120 2 + 121 0 121 2 + 122 0 122 2 + 123 0 123 2 + 124 0 124 2 + 125 0 125 2 + 126 0 126 2 + 127 0 127 2 +2048 0 2048 2 +2049 0 2049 2 +2050 0 2050 2 +2051 0 2051 2 +2052 0 2052 2 +2053 0 2053 2 +2054 0 2054 2 +2055 0 2055 2 +2056 0 2056 2 +2057 0 2057 2 +2058 0 2058 2 +2059 0 2059 2 +2060 0 2060 2 +2061 0 2061 2 +2062 0 2062 2 +2063 0 2063 2 +2064 0 2064 2 +2065 0 2065 2 +2066 0 2066 2 +2067 0 2067 2 +2068 0 2068 2 +2069 0 2069 2 +2070 0 2070 2 +2071 0 2071 2 +2072 0 2072 2 +2073 0 2073 2 +2074 0 2074 2 +2075 0 2075 2 +2076 0 2076 2 +2077 0 2077 2 +2078 0 2078 2 +2079 0 2079 2 +2080 0 2080 2 +2081 0 2081 2 +2082 0 2082 2 +2083 0 2083 2 +2084 0 2084 2 +2085 0 2085 2 +2086 0 2086 2 +2087 0 2087 2 +2088 0 2088 2 +2089 0 2089 2 +2090 0 2090 2 +2091 0 2091 2 +2092 0 2092 2 +2093 0 2093 2 +2094 0 2094 2 +2095 0 2095 2 +2096 0 2096 2 +2097 0 2097 2 +2098 0 2098 2 +2099 0 2099 2 +2100 0 2100 2 +2101 0 2101 2 +2102 0 2102 2 +2103 0 2103 2 +2104 0 2104 2 +2105 0 2105 2 +2106 0 2106 2 +2107 0 2107 2 +2108 0 2108 2 +2109 0 2109 2 +2110 0 2110 2 +2111 0 2111 2 +2112 0 2112 2 +2113 0 2113 2 +2114 0 2114 2 +2115 0 2115 2 +2116 0 2116 2 +2117 0 2117 2 +2118 0 2118 2 +2119 0 2119 2 +2120 0 2120 2 +2121 0 2121 2 +2122 0 2122 2 +2123 0 2123 2 +2124 0 2124 2 +2125 0 2125 2 +2126 0 2126 2 +2127 0 2127 2 +2128 0 2128 2 +2129 0 2129 2 +2130 0 2130 2 +2131 0 2131 2 +2132 0 2132 2 +2133 0 2133 2 +2134 0 2134 2 +2135 0 2135 2 +2136 0 2136 2 +2137 0 2137 2 +2138 0 2138 2 +2139 0 2139 2 +2140 0 2140 2 +2141 0 2141 2 +2142 0 2142 2 +2143 0 2143 2 +2144 0 2144 2 +2145 0 2145 2 +2146 0 2146 2 +2147 0 2147 2 +2148 0 2148 2 +2149 0 2149 2 +2150 0 2150 2 +2151 0 2151 2 +2152 0 2152 2 +2153 0 2153 2 +2154 0 2154 2 +2155 0 2155 2 +2156 0 2156 2 +2157 0 2157 2 +2158 0 2158 2 +2159 0 2159 2 +2160 0 2160 2 +2161 0 2161 2 +2162 0 2162 2 +2163 0 2163 2 +2164 0 2164 2 +2165 0 2165 2 +2166 0 2166 2 +2167 0 2167 2 +2168 0 2168 2 +2169 0 2169 2 +2170 0 2170 2 +2171 0 2171 2 +2172 0 2172 2 +2173 0 2173 2 +2174 0 2174 2 +2175 0 2175 2 + 128 11 29 0 + 129 11 29 1 + 130 11 28 0 + 131 11 28 1 + 132 10 29 0 + 133 10 29 1 + 134 10 28 0 + 135 10 28 1 + 136 8 28 1 + 137 8 28 0 + 138 8 29 1 + 139 8 29 0 + 140 9 28 1 + 141 9 28 0 + 142 9 29 1 + 143 9 29 0 + 160 3 28 0 + 161 3 28 1 + 162 3 29 0 + 163 3 29 1 + 164 2 28 0 + 165 2 28 1 + 166 2 29 0 + 167 2 29 1 + 168 0 29 1 + 169 0 29 0 + 170 0 28 1 + 171 0 28 0 + 172 1 29 1 + 173 1 29 0 + 174 1 28 1 + 175 1 28 0 + 176 4 28 0 + 177 4 28 1 + 178 4 29 0 + 179 4 29 1 + 180 5 28 0 + 181 5 28 1 + 182 5 29 0 + 183 5 29 1 + 184 7 29 1 + 185 7 29 0 + 186 7 28 1 + 187 7 28 0 + 188 6 29 1 + 189 6 29 0 + 190 6 28 1 + 191 6 28 0 + 192 12 29 0 + 193 12 29 1 + 194 12 28 0 + 195 12 28 1 + 196 13 29 0 + 197 13 29 1 + 198 13 28 0 + 199 13 28 1 + 200 15 28 1 + 201 15 28 0 + 202 15 29 1 + 203 15 29 0 + 204 14 28 1 + 205 14 28 0 + 206 14 29 1 + 207 14 29 0 + 256 11 31 0 + 257 11 31 1 + 258 11 30 0 + 259 11 30 1 + 260 10 31 0 + 261 10 31 1 + 262 10 30 0 + 263 10 30 1 + 264 8 30 1 + 265 8 30 0 + 266 8 31 1 + 267 8 31 0 + 268 9 30 1 + 269 9 30 0 + 270 9 31 1 + 271 9 31 0 + 288 3 30 0 + 289 3 30 1 + 290 3 31 0 + 291 3 31 1 + 292 2 30 0 + 293 2 30 1 + 294 2 31 0 + 295 2 31 1 + 296 0 31 1 + 297 0 31 0 + 298 0 30 1 + 299 0 30 0 + 300 1 31 1 + 301 1 31 0 + 302 1 30 1 + 303 1 30 0 + 304 4 30 0 + 305 4 30 1 + 306 4 31 0 + 307 4 31 1 + 308 5 30 0 + 309 5 30 1 + 310 5 31 0 + 311 5 31 1 + 312 7 31 1 + 313 7 31 0 + 314 7 30 1 + 315 7 30 0 + 316 6 31 1 + 317 6 31 0 + 318 6 30 1 + 319 6 30 0 + 320 12 31 0 + 321 12 31 1 + 322 12 30 0 + 323 12 30 1 + 324 13 31 0 + 325 13 31 1 + 326 13 30 0 + 327 13 30 1 + 328 15 30 1 + 329 15 30 0 + 330 15 31 1 + 331 15 31 0 + 332 14 30 1 + 333 14 30 0 + 334 14 31 1 + 335 14 31 0 + 384 11 33 0 + 385 11 33 1 + 386 11 32 0 + 387 11 32 1 + 388 10 33 0 + 389 10 33 1 + 390 10 32 0 + 391 10 32 1 + 392 8 32 1 + 393 8 32 0 + 394 8 33 1 + 395 8 33 0 + 396 9 32 1 + 397 9 32 0 + 398 9 33 1 + 399 9 33 0 + 416 3 32 0 + 417 3 32 1 + 418 3 33 0 + 419 3 33 1 + 420 2 32 0 + 421 2 32 1 + 422 2 33 0 + 423 2 33 1 + 424 0 33 1 + 425 0 33 0 + 426 0 32 1 + 427 0 32 0 + 428 1 33 1 + 429 1 33 0 + 430 1 32 1 + 431 1 32 0 + 432 4 32 0 + 433 4 32 1 + 434 4 33 0 + 435 4 33 1 + 436 5 32 0 + 437 5 32 1 + 438 5 33 0 + 439 5 33 1 + 440 7 33 1 + 441 7 33 0 + 442 7 32 1 + 443 7 32 0 + 444 6 33 1 + 445 6 33 0 + 446 6 32 1 + 447 6 32 0 + 448 12 33 0 + 449 12 33 1 + 450 12 32 0 + 451 12 32 1 + 452 13 33 0 + 453 13 33 1 + 454 13 32 0 + 455 13 32 1 + 456 15 32 1 + 457 15 32 0 + 458 15 33 1 + 459 15 33 0 + 460 14 32 1 + 461 14 32 0 + 462 14 33 1 + 463 14 33 0 + 512 11 35 0 + 513 11 35 1 + 514 11 34 0 + 515 11 34 1 + 516 10 35 0 + 517 10 35 1 + 518 10 34 0 + 519 10 34 1 + 520 8 34 1 + 521 8 34 0 + 522 8 35 1 + 523 8 35 0 + 524 9 34 1 + 525 9 34 0 + 526 9 35 1 + 527 9 35 0 + 544 3 34 0 + 545 3 34 1 + 546 3 35 0 + 547 3 35 1 + 548 2 34 0 + 549 2 34 1 + 550 2 35 0 + 551 2 35 1 + 552 0 35 1 + 553 0 35 0 + 554 0 34 1 + 555 0 34 0 + 556 1 35 1 + 557 1 35 0 + 558 1 34 1 + 559 1 34 0 + 560 4 34 0 + 561 4 34 1 + 562 4 35 0 + 563 4 35 1 + 564 5 34 0 + 565 5 34 1 + 566 5 35 0 + 567 5 35 1 + 568 7 35 1 + 569 7 35 0 + 570 7 34 1 + 571 7 34 0 + 572 6 35 1 + 573 6 35 0 + 574 6 34 1 + 575 6 34 0 + 576 12 35 0 + 577 12 35 1 + 578 12 34 0 + 579 12 34 1 + 580 13 35 0 + 581 13 35 1 + 582 13 34 0 + 583 13 34 1 + 584 15 34 1 + 585 15 34 0 + 586 15 35 1 + 587 15 35 0 + 588 14 34 1 + 589 14 34 0 + 590 14 35 1 + 591 14 35 0 + 640 11 37 0 + 641 11 37 1 + 642 11 36 0 + 643 11 36 1 + 644 10 37 0 + 645 10 37 1 + 646 10 36 0 + 647 10 36 1 + 648 8 36 1 + 649 8 36 0 + 650 8 37 1 + 651 8 37 0 + 652 9 36 1 + 653 9 36 0 + 654 9 37 1 + 655 9 37 0 + 672 3 36 0 + 673 3 36 1 + 674 3 37 0 + 675 3 37 1 + 676 2 36 0 + 677 2 36 1 + 678 2 37 0 + 679 2 37 1 + 680 0 37 1 + 681 0 37 0 + 682 0 36 1 + 683 0 36 0 + 684 1 37 1 + 685 1 37 0 + 686 1 36 1 + 687 1 36 0 + 688 4 36 0 + 689 4 36 1 + 690 4 37 0 + 691 4 37 1 + 692 5 36 0 + 693 5 36 1 + 694 5 37 0 + 695 5 37 1 + 696 7 37 1 + 697 7 37 0 + 698 7 36 1 + 699 7 36 0 + 700 6 37 1 + 701 6 37 0 + 702 6 36 1 + 703 6 36 0 + 704 12 37 0 + 705 12 37 1 + 706 12 36 0 + 707 12 36 1 + 708 13 37 0 + 709 13 37 1 + 710 13 36 0 + 711 13 36 1 + 712 15 36 1 + 713 15 36 0 + 714 15 37 1 + 715 15 37 0 + 716 14 36 1 + 717 14 36 0 + 718 14 37 1 + 719 14 37 0 + 768 11 39 0 + 769 11 39 1 + 770 11 38 0 + 771 11 38 1 + 772 10 39 0 + 773 10 39 1 + 774 10 38 0 + 775 10 38 1 + 776 8 38 1 + 777 8 38 0 + 778 8 39 1 + 779 8 39 0 + 780 9 38 1 + 781 9 38 0 + 782 9 39 1 + 783 9 39 0 + 800 3 38 0 + 801 3 38 1 + 802 3 39 0 + 803 3 39 1 + 804 2 38 0 + 805 2 38 1 + 806 2 39 0 + 807 2 39 1 + 808 0 39 1 + 809 0 39 0 + 810 0 38 1 + 811 0 38 0 + 812 1 39 1 + 813 1 39 0 + 814 1 38 1 + 815 1 38 0 + 816 4 38 0 + 817 4 38 1 + 818 4 39 0 + 819 4 39 1 + 820 5 38 0 + 821 5 38 1 + 822 5 39 0 + 823 5 39 1 + 824 7 39 1 + 825 7 39 0 + 826 7 38 1 + 827 7 38 0 + 828 6 39 1 + 829 6 39 0 + 830 6 38 1 + 831 6 38 0 + 832 12 39 0 + 833 12 39 1 + 834 12 38 0 + 835 12 38 1 + 836 13 39 0 + 837 13 39 1 + 838 13 38 0 + 839 13 38 1 + 840 15 38 1 + 841 15 38 0 + 842 15 39 1 + 843 15 39 0 + 844 14 38 1 + 845 14 38 0 + 846 14 39 1 + 847 14 39 0 + 896 11 41 0 + 897 11 41 1 + 898 11 40 0 + 899 11 40 1 + 900 10 41 0 + 901 10 41 1 + 902 10 40 0 + 903 10 40 1 + 904 8 40 1 + 905 8 40 0 + 906 8 41 1 + 907 8 41 0 + 908 9 40 1 + 909 9 40 0 + 910 9 41 1 + 911 9 41 0 + 928 3 40 0 + 929 3 40 1 + 930 3 41 0 + 931 3 41 1 + 932 2 40 0 + 933 2 40 1 + 934 2 41 0 + 935 2 41 1 + 936 0 41 1 + 937 0 41 0 + 938 0 40 1 + 939 0 40 0 + 940 1 41 1 + 941 1 41 0 + 942 1 40 1 + 943 1 40 0 + 944 4 40 0 + 945 4 40 1 + 946 4 41 0 + 947 4 41 1 + 948 5 40 0 + 949 5 40 1 + 950 5 41 0 + 951 5 41 1 + 952 7 41 1 + 953 7 41 0 + 954 7 40 1 + 955 7 40 0 + 956 6 41 1 + 957 6 41 0 + 958 6 40 1 + 959 6 40 0 + 960 12 41 0 + 961 12 41 1 + 962 12 40 0 + 963 12 40 1 + 964 13 41 0 + 965 13 41 1 + 966 13 40 0 + 967 13 40 1 + 968 15 40 1 + 969 15 40 0 + 970 15 41 1 + 971 15 41 0 + 972 14 40 1 + 973 14 40 0 + 974 14 41 1 + 975 14 41 0 +1024 11 43 0 +1025 11 43 1 +1026 11 42 0 +1027 11 42 1 +1028 10 43 0 +1029 10 43 1 +1030 10 42 0 +1031 10 42 1 +1032 8 42 1 +1033 8 42 0 +1034 8 43 1 +1035 8 43 0 +1036 9 42 1 +1037 9 42 0 +1038 9 43 1 +1039 9 43 0 +1056 3 42 0 +1057 3 42 1 +1058 3 43 0 +1059 3 43 1 +1060 2 42 0 +1061 2 42 1 +1062 2 43 0 +1063 2 43 1 +1064 0 43 1 +1065 0 43 0 +1066 0 42 1 +1067 0 42 0 +1068 1 43 1 +1069 1 43 0 +1070 1 42 1 +1071 1 42 0 +1072 4 42 0 +1073 4 42 1 +1074 4 43 0 +1075 4 43 1 +1076 5 42 0 +1077 5 42 1 +1078 5 43 0 +1079 5 43 1 +1080 7 43 1 +1081 7 43 0 +1082 7 42 1 +1083 7 42 0 +1084 6 43 1 +1085 6 43 0 +1086 6 42 1 +1087 6 42 0 +1088 12 43 0 +1089 12 43 1 +1090 12 42 0 +1091 12 42 1 +1092 13 43 0 +1093 13 43 1 +1094 13 42 0 +1095 13 42 1 +1096 15 42 1 +1097 15 42 0 +1098 15 43 1 +1099 15 43 0 +1100 14 42 1 +1101 14 42 0 +1102 14 43 1 +1103 14 43 0 +1152 11 45 0 +1153 11 45 1 +1154 11 44 0 +1155 11 44 1 +1156 10 45 0 +1157 10 45 1 +1158 10 44 0 +1159 10 44 1 +1160 8 44 1 +1161 8 44 0 +1162 8 45 1 +1163 8 45 0 +1164 9 44 1 +1165 9 44 0 +1166 9 45 1 +1167 9 45 0 +1184 3 44 0 +1185 3 44 1 +1186 3 45 0 +1187 3 45 1 +1188 2 44 0 +1189 2 44 1 +1190 2 45 0 +1191 2 45 1 +1192 0 45 1 +1193 0 45 0 +1194 0 44 1 +1195 0 44 0 +1196 1 45 1 +1197 1 45 0 +1198 1 44 1 +1199 1 44 0 +1200 4 44 0 +1201 4 44 1 +1202 4 45 0 +1203 4 45 1 +1204 5 44 0 +1205 5 44 1 +1206 5 45 0 +1207 5 45 1 +1208 7 45 1 +1209 7 45 0 +1210 7 44 1 +1211 7 44 0 +1212 6 45 1 +1213 6 45 0 +1214 6 44 1 +1215 6 44 0 +1216 12 45 0 +1217 12 45 1 +1218 12 44 0 +1219 12 44 1 +1220 13 45 0 +1221 13 45 1 +1222 13 44 0 +1223 13 44 1 +1224 15 44 1 +1225 15 44 0 +1226 15 45 1 +1227 15 45 0 +1228 14 44 1 +1229 14 44 0 +1230 14 45 1 +1231 14 45 0 +1280 11 47 0 +1281 11 47 1 +1282 11 46 0 +1283 11 46 1 +1284 10 47 0 +1285 10 47 1 +1286 10 46 0 +1287 10 46 1 +1288 8 46 1 +1289 8 46 0 +1290 8 47 1 +1291 8 47 0 +1292 9 46 1 +1293 9 46 0 +1294 9 47 1 +1295 9 47 0 +1312 3 46 0 +1313 3 46 1 +1314 3 47 0 +1315 3 47 1 +1316 2 46 0 +1317 2 46 1 +1318 2 47 0 +1319 2 47 1 +1320 0 47 1 +1321 0 47 0 +1322 0 46 1 +1323 0 46 0 +1324 1 47 1 +1325 1 47 0 +1326 1 46 1 +1327 1 46 0 +1328 4 46 0 +1329 4 46 1 +1330 4 47 0 +1331 4 47 1 +1332 5 46 0 +1333 5 46 1 +1334 5 47 0 +1335 5 47 1 +1336 7 47 1 +1337 7 47 0 +1338 7 46 1 +1339 7 46 0 +1340 6 47 1 +1341 6 47 0 +1342 6 46 1 +1343 6 46 0 +1344 12 47 0 +1345 12 47 1 +1346 12 46 0 +1347 12 46 1 +1348 13 47 0 +1349 13 47 1 +1350 13 46 0 +1351 13 46 1 +1352 15 46 1 +1353 15 46 0 +1354 15 47 1 +1355 15 47 0 +1356 14 46 1 +1357 14 46 0 +1358 14 47 1 +1359 14 47 0 +1408 11 49 0 +1409 11 49 1 +1410 11 48 0 +1411 11 48 1 +1412 10 49 0 +1413 10 49 1 +1414 10 48 0 +1415 10 48 1 +1416 8 48 1 +1417 8 48 0 +1418 8 49 1 +1419 8 49 0 +1420 9 48 1 +1421 9 48 0 +1422 9 49 1 +1423 9 49 0 +1440 3 48 0 +1441 3 48 1 +1442 3 49 0 +1443 3 49 1 +1444 2 48 0 +1445 2 48 1 +1446 2 49 0 +1447 2 49 1 +1448 0 49 1 +1449 0 49 0 +1450 0 48 1 +1451 0 48 0 +1452 1 49 1 +1453 1 49 0 +1454 1 48 1 +1455 1 48 0 +1456 4 48 0 +1457 4 48 1 +1458 4 49 0 +1459 4 49 1 +1460 5 48 0 +1461 5 48 1 +1462 5 49 0 +1463 5 49 1 +1464 7 49 1 +1465 7 49 0 +1466 7 48 1 +1467 7 48 0 +1468 6 49 1 +1469 6 49 0 +1470 6 48 1 +1471 6 48 0 +1472 12 49 0 +1473 12 49 1 +1474 12 48 0 +1475 12 48 1 +1476 13 49 0 +1477 13 49 1 +1478 13 48 0 +1479 13 48 1 +1480 15 48 1 +1481 15 48 0 +1482 15 49 1 +1483 15 49 0 +1484 14 48 1 +1485 14 48 0 +1486 14 49 1 +1487 14 49 0 +1536 11 51 0 +1537 11 51 1 +1538 11 50 0 +1539 11 50 1 +1540 10 51 0 +1541 10 51 1 +1542 10 50 0 +1543 10 50 1 +1544 8 50 1 +1545 8 50 0 +1546 8 51 1 +1547 8 51 0 +1548 9 50 1 +1549 9 50 0 +1550 9 51 1 +1551 9 51 0 +1568 3 50 0 +1569 3 50 1 +1570 3 51 0 +1571 3 51 1 +1572 2 50 0 +1573 2 50 1 +1574 2 51 0 +1575 2 51 1 +1576 0 51 1 +1577 0 51 0 +1578 0 50 1 +1579 0 50 0 +1580 1 51 1 +1581 1 51 0 +1582 1 50 1 +1583 1 50 0 +1584 4 50 0 +1585 4 50 1 +1586 4 51 0 +1587 4 51 1 +1588 5 50 0 +1589 5 50 1 +1590 5 51 0 +1591 5 51 1 +1592 7 51 1 +1593 7 51 0 +1594 7 50 1 +1595 7 50 0 +1596 6 51 1 +1597 6 51 0 +1598 6 50 1 +1599 6 50 0 +1600 12 51 0 +1601 12 51 1 +1602 12 50 0 +1603 12 50 1 +1604 13 51 0 +1605 13 51 1 +1606 13 50 0 +1607 13 50 1 +1608 15 50 1 +1609 15 50 0 +1610 15 51 1 +1611 15 51 0 +1612 14 50 1 +1613 14 50 0 +1614 14 51 1 +1615 14 51 0 +1664 11 53 0 +1665 11 53 1 +1666 11 52 0 +1667 11 52 1 +1668 10 53 0 +1669 10 53 1 +1670 10 52 0 +1671 10 52 1 +1672 8 52 1 +1673 8 52 0 +1674 8 53 1 +1675 8 53 0 +1676 9 52 1 +1677 9 52 0 +1678 9 53 1 +1679 9 53 0 +1696 3 52 0 +1697 3 52 1 +1698 3 53 0 +1699 3 53 1 +1700 2 52 0 +1701 2 52 1 +1702 2 53 0 +1703 2 53 1 +1704 0 53 1 +1705 0 53 0 +1706 0 52 1 +1707 0 52 0 +1708 1 53 1 +1709 1 53 0 +1710 1 52 1 +1711 1 52 0 +1712 4 52 0 +1713 4 52 1 +1714 4 53 0 +1715 4 53 1 +1716 5 52 0 +1717 5 52 1 +1718 5 53 0 +1719 5 53 1 +1720 7 53 1 +1721 7 53 0 +1722 7 52 1 +1723 7 52 0 +1724 6 53 1 +1725 6 53 0 +1726 6 52 1 +1727 6 52 0 +1728 12 53 0 +1729 12 53 1 +1730 12 52 0 +1731 12 52 1 +1732 13 53 0 +1733 13 53 1 +1734 13 52 0 +1735 13 52 1 +1736 15 52 1 +1737 15 52 0 +1738 15 53 1 +1739 15 53 0 +1740 14 52 1 +1741 14 52 0 +1742 14 53 1 +1743 14 53 0 +1792 11 55 0 +1793 11 55 1 +1794 11 54 0 +1795 11 54 1 +1796 10 55 0 +1797 10 55 1 +1798 10 54 0 +1799 10 54 1 +1800 8 54 1 +1801 8 54 0 +1802 8 55 1 +1803 8 55 0 +1804 9 54 1 +1805 9 54 0 +1806 9 55 1 +1807 9 55 0 +1824 3 54 0 +1825 3 54 1 +1826 3 55 0 +1827 3 55 1 +1828 2 54 0 +1829 2 54 1 +1830 2 55 0 +1831 2 55 1 +1832 0 55 1 +1833 0 55 0 +1834 0 54 1 +1835 0 54 0 +1836 1 55 1 +1837 1 55 0 +1838 1 54 1 +1839 1 54 0 +1840 4 54 0 +1841 4 54 1 +1842 4 55 0 +1843 4 55 1 +1844 5 54 0 +1845 5 54 1 +1846 5 55 0 +1847 5 55 1 +1848 7 55 1 +1849 7 55 0 +1850 7 54 1 +1851 7 54 0 +1852 6 55 1 +1853 6 55 0 +1854 6 54 1 +1855 6 54 0 +1856 12 55 0 +1857 12 55 1 +1858 12 54 0 +1859 12 54 1 +1860 13 55 0 +1861 13 55 1 +1862 13 54 0 +1863 13 54 1 +1864 15 54 1 +1865 15 54 0 +1866 15 55 1 +1867 15 55 0 +1868 14 54 1 +1869 14 54 0 +1870 14 55 1 +1871 14 55 0 +2176 11 27 0 +2177 11 27 1 +2178 11 26 0 +2179 11 26 1 +2180 10 27 0 +2181 10 27 1 +2182 10 26 0 +2183 10 26 1 +2184 8 26 1 +2185 8 26 0 +2186 8 27 1 +2187 8 27 0 +2188 9 26 1 +2189 9 26 0 +2190 9 27 1 +2191 9 27 0 +2208 3 26 0 +2209 3 26 1 +2210 3 27 0 +2211 3 27 1 +2212 2 26 0 +2213 2 26 1 +2214 2 27 0 +2215 2 27 1 +2216 0 27 1 +2217 0 27 0 +2218 0 26 1 +2219 0 26 0 +2220 1 27 1 +2221 1 27 0 +2222 1 26 1 +2223 1 26 0 +2224 4 26 0 +2225 4 26 1 +2226 4 27 0 +2227 4 27 1 +2228 5 26 0 +2229 5 26 1 +2230 5 27 0 +2231 5 27 1 +2232 7 27 1 +2233 7 27 0 +2234 7 26 1 +2235 7 26 0 +2236 6 27 1 +2237 6 27 0 +2238 6 26 1 +2239 6 26 0 +2240 12 27 0 +2241 12 27 1 +2242 12 26 0 +2243 12 26 1 +2244 13 27 0 +2245 13 27 1 +2246 13 26 0 +2247 13 26 1 +2248 15 26 1 +2249 15 26 0 +2250 15 27 1 +2251 15 27 0 +2252 14 26 1 +2253 14 26 0 +2254 14 27 1 +2255 14 27 0 +2304 11 25 0 +2305 11 25 1 +2306 11 24 0 +2307 11 24 1 +2308 10 25 0 +2309 10 25 1 +2310 10 24 0 +2311 10 24 1 +2312 8 24 1 +2313 8 24 0 +2314 8 25 1 +2315 8 25 0 +2316 9 24 1 +2317 9 24 0 +2318 9 25 1 +2319 9 25 0 +2336 3 24 0 +2337 3 24 1 +2338 3 25 0 +2339 3 25 1 +2340 2 24 0 +2341 2 24 1 +2342 2 25 0 +2343 2 25 1 +2344 0 25 1 +2345 0 25 0 +2346 0 24 1 +2347 0 24 0 +2348 1 25 1 +2349 1 25 0 +2350 1 24 1 +2351 1 24 0 +2352 4 24 0 +2353 4 24 1 +2354 4 25 0 +2355 4 25 1 +2356 5 24 0 +2357 5 24 1 +2358 5 25 0 +2359 5 25 1 +2360 7 25 1 +2361 7 25 0 +2362 7 24 1 +2363 7 24 0 +2364 6 25 1 +2365 6 25 0 +2366 6 24 1 +2367 6 24 0 +2368 12 25 0 +2369 12 25 1 +2370 12 24 0 +2371 12 24 1 +2372 13 25 0 +2373 13 25 1 +2374 13 24 0 +2375 13 24 1 +2376 15 24 1 +2377 15 24 0 +2378 15 25 1 +2379 15 25 0 +2380 14 24 1 +2381 14 24 0 +2382 14 25 1 +2383 14 25 0 +2432 11 23 0 +2433 11 23 1 +2434 11 22 0 +2435 11 22 1 +2436 10 23 0 +2437 10 23 1 +2438 10 22 0 +2439 10 22 1 +2440 8 22 1 +2441 8 22 0 +2442 8 23 1 +2443 8 23 0 +2444 9 22 1 +2445 9 22 0 +2446 9 23 1 +2447 9 23 0 +2464 3 22 0 +2465 3 22 1 +2466 3 23 0 +2467 3 23 1 +2468 2 22 0 +2469 2 22 1 +2470 2 23 0 +2471 2 23 1 +2472 0 23 1 +2473 0 23 0 +2474 0 22 1 +2475 0 22 0 +2476 1 23 1 +2477 1 23 0 +2478 1 22 1 +2479 1 22 0 +2480 4 22 0 +2481 4 22 1 +2482 4 23 0 +2483 4 23 1 +2484 5 22 0 +2485 5 22 1 +2486 5 23 0 +2487 5 23 1 +2488 7 23 1 +2489 7 23 0 +2490 7 22 1 +2491 7 22 0 +2492 6 23 1 +2493 6 23 0 +2494 6 22 1 +2495 6 22 0 +2496 12 23 0 +2497 12 23 1 +2498 12 22 0 +2499 12 22 1 +2500 13 23 0 +2501 13 23 1 +2502 13 22 0 +2503 13 22 1 +2504 15 22 1 +2505 15 22 0 +2506 15 23 1 +2507 15 23 0 +2508 14 22 1 +2509 14 22 0 +2510 14 23 1 +2511 14 23 0 +2560 11 21 0 +2561 11 21 1 +2562 11 20 0 +2563 11 20 1 +2564 10 21 0 +2565 10 21 1 +2566 10 20 0 +2567 10 20 1 +2568 8 20 1 +2569 8 20 0 +2570 8 21 1 +2571 8 21 0 +2572 9 20 1 +2573 9 20 0 +2574 9 21 1 +2575 9 21 0 +2592 3 20 0 +2593 3 20 1 +2594 3 21 0 +2595 3 21 1 +2596 2 20 0 +2597 2 20 1 +2598 2 21 0 +2599 2 21 1 +2600 0 21 1 +2601 0 21 0 +2602 0 20 1 +2603 0 20 0 +2604 1 21 1 +2605 1 21 0 +2606 1 20 1 +2607 1 20 0 +2608 4 20 0 +2609 4 20 1 +2610 4 21 0 +2611 4 21 1 +2612 5 20 0 +2613 5 20 1 +2614 5 21 0 +2615 5 21 1 +2616 7 21 1 +2617 7 21 0 +2618 7 20 1 +2619 7 20 0 +2620 6 21 1 +2621 6 21 0 +2622 6 20 1 +2623 6 20 0 +2624 12 21 0 +2625 12 21 1 +2626 12 20 0 +2627 12 20 1 +2628 13 21 0 +2629 13 21 1 +2630 13 20 0 +2631 13 20 1 +2632 15 20 1 +2633 15 20 0 +2634 15 21 1 +2635 15 21 0 +2636 14 20 1 +2637 14 20 0 +2638 14 21 1 +2639 14 21 0 +2688 11 19 0 +2689 11 19 1 +2690 11 18 0 +2691 11 18 1 +2692 10 19 0 +2693 10 19 1 +2694 10 18 0 +2695 10 18 1 +2696 8 18 1 +2697 8 18 0 +2698 8 19 1 +2699 8 19 0 +2700 9 18 1 +2701 9 18 0 +2702 9 19 1 +2703 9 19 0 +2720 3 18 0 +2721 3 18 1 +2722 3 19 0 +2723 3 19 1 +2724 2 18 0 +2725 2 18 1 +2726 2 19 0 +2727 2 19 1 +2728 0 19 1 +2729 0 19 0 +2730 0 18 1 +2731 0 18 0 +2732 1 19 1 +2733 1 19 0 +2734 1 18 1 +2735 1 18 0 +2736 4 18 0 +2737 4 18 1 +2738 4 19 0 +2739 4 19 1 +2740 5 18 0 +2741 5 18 1 +2742 5 19 0 +2743 5 19 1 +2744 7 19 1 +2745 7 19 0 +2746 7 18 1 +2747 7 18 0 +2748 6 19 1 +2749 6 19 0 +2750 6 18 1 +2751 6 18 0 +2752 12 19 0 +2753 12 19 1 +2754 12 18 0 +2755 12 18 1 +2756 13 19 0 +2757 13 19 1 +2758 13 18 0 +2759 13 18 1 +2760 15 18 1 +2761 15 18 0 +2762 15 19 1 +2763 15 19 0 +2764 14 18 1 +2765 14 18 0 +2766 14 19 1 +2767 14 19 0 +2816 11 17 0 +2817 11 17 1 +2818 11 16 0 +2819 11 16 1 +2820 10 17 0 +2821 10 17 1 +2822 10 16 0 +2823 10 16 1 +2824 8 16 1 +2825 8 16 0 +2826 8 17 1 +2827 8 17 0 +2828 9 16 1 +2829 9 16 0 +2830 9 17 1 +2831 9 17 0 +2848 3 16 0 +2849 3 16 1 +2850 3 17 0 +2851 3 17 1 +2852 2 16 0 +2853 2 16 1 +2854 2 17 0 +2855 2 17 1 +2856 0 17 1 +2857 0 17 0 +2858 0 16 1 +2859 0 16 0 +2860 1 17 1 +2861 1 17 0 +2862 1 16 1 +2863 1 16 0 +2864 4 16 0 +2865 4 16 1 +2866 4 17 0 +2867 4 17 1 +2868 5 16 0 +2869 5 16 1 +2870 5 17 0 +2871 5 17 1 +2872 7 17 1 +2873 7 17 0 +2874 7 16 1 +2875 7 16 0 +2876 6 17 1 +2877 6 17 0 +2878 6 16 1 +2879 6 16 0 +2880 12 17 0 +2881 12 17 1 +2882 12 16 0 +2883 12 16 1 +2884 13 17 0 +2885 13 17 1 +2886 13 16 0 +2887 13 16 1 +2888 15 16 1 +2889 15 16 0 +2890 15 17 1 +2891 15 17 0 +2892 14 16 1 +2893 14 16 0 +2894 14 17 1 +2895 14 17 0 +2944 11 15 0 +2945 11 15 1 +2946 11 14 0 +2947 11 14 1 +2948 10 15 0 +2949 10 15 1 +2950 10 14 0 +2951 10 14 1 +2952 8 14 1 +2953 8 14 0 +2954 8 15 1 +2955 8 15 0 +2956 9 14 1 +2957 9 14 0 +2958 9 15 1 +2959 9 15 0 +2976 3 14 0 +2977 3 14 1 +2978 3 15 0 +2979 3 15 1 +2980 2 14 0 +2981 2 14 1 +2982 2 15 0 +2983 2 15 1 +2984 0 15 1 +2985 0 15 0 +2986 0 14 1 +2987 0 14 0 +2988 1 15 1 +2989 1 15 0 +2990 1 14 1 +2991 1 14 0 +2992 4 14 0 +2993 4 14 1 +2994 4 15 0 +2995 4 15 1 +2996 5 14 0 +2997 5 14 1 +2998 5 15 0 +2999 5 15 1 +3000 7 15 1 +3001 7 15 0 +3002 7 14 1 +3003 7 14 0 +3004 6 15 1 +3005 6 15 0 +3006 6 14 1 +3007 6 14 0 +3008 12 15 0 +3009 12 15 1 +3010 12 14 0 +3011 12 14 1 +3012 13 15 0 +3013 13 15 1 +3014 13 14 0 +3015 13 14 1 +3016 15 14 1 +3017 15 14 0 +3018 15 15 1 +3019 15 15 0 +3020 14 14 1 +3021 14 14 0 +3022 14 15 1 +3023 14 15 0 +3072 11 13 0 +3073 11 13 1 +3074 11 12 0 +3075 11 12 1 +3076 10 13 0 +3077 10 13 1 +3078 10 12 0 +3079 10 12 1 +3080 8 12 1 +3081 8 12 0 +3082 8 13 1 +3083 8 13 0 +3084 9 12 1 +3085 9 12 0 +3086 9 13 1 +3087 9 13 0 +3104 3 12 0 +3105 3 12 1 +3106 3 13 0 +3107 3 13 1 +3108 2 12 0 +3109 2 12 1 +3110 2 13 0 +3111 2 13 1 +3112 0 13 1 +3113 0 13 0 +3114 0 12 1 +3115 0 12 0 +3116 1 13 1 +3117 1 13 0 +3118 1 12 1 +3119 1 12 0 +3120 4 12 0 +3121 4 12 1 +3122 4 13 0 +3123 4 13 1 +3124 5 12 0 +3125 5 12 1 +3126 5 13 0 +3127 5 13 1 +3128 7 13 1 +3129 7 13 0 +3130 7 12 1 +3131 7 12 0 +3132 6 13 1 +3133 6 13 0 +3134 6 12 1 +3135 6 12 0 +3136 12 13 0 +3137 12 13 1 +3138 12 12 0 +3139 12 12 1 +3140 13 13 0 +3141 13 13 1 +3142 13 12 0 +3143 13 12 1 +3144 15 12 1 +3145 15 12 0 +3146 15 13 1 +3147 15 13 0 +3148 14 12 1 +3149 14 12 0 +3150 14 13 1 +3151 14 13 0 +3200 11 11 0 +3201 11 11 1 +3202 11 10 0 +3203 11 10 1 +3204 10 11 0 +3205 10 11 1 +3206 10 10 0 +3207 10 10 1 +3208 8 10 1 +3209 8 10 0 +3210 8 11 1 +3211 8 11 0 +3212 9 10 1 +3213 9 10 0 +3214 9 11 1 +3215 9 11 0 +3232 3 10 0 +3233 3 10 1 +3234 3 11 0 +3235 3 11 1 +3236 2 10 0 +3237 2 10 1 +3238 2 11 0 +3239 2 11 1 +3240 0 11 1 +3241 0 11 0 +3242 0 10 1 +3243 0 10 0 +3244 1 11 1 +3245 1 11 0 +3246 1 10 1 +3247 1 10 0 +3248 4 10 0 +3249 4 10 1 +3250 4 11 0 +3251 4 11 1 +3252 5 10 0 +3253 5 10 1 +3254 5 11 0 +3255 5 11 1 +3256 7 11 1 +3257 7 11 0 +3258 7 10 1 +3259 7 10 0 +3260 6 11 1 +3261 6 11 0 +3262 6 10 1 +3263 6 10 0 +3264 12 11 0 +3265 12 11 1 +3266 12 10 0 +3267 12 10 1 +3268 13 11 0 +3269 13 11 1 +3270 13 10 0 +3271 13 10 1 +3272 15 10 1 +3273 15 10 0 +3274 15 11 1 +3275 15 11 0 +3276 14 10 1 +3277 14 10 0 +3278 14 11 1 +3279 14 11 0 +3328 11 9 0 +3329 11 9 1 +3330 11 8 0 +3331 11 8 1 +3332 10 9 0 +3333 10 9 1 +3334 10 8 0 +3335 10 8 1 +3336 8 8 1 +3337 8 8 0 +3338 8 9 1 +3339 8 9 0 +3340 9 8 1 +3341 9 8 0 +3342 9 9 1 +3343 9 9 0 +3360 3 8 0 +3361 3 8 1 +3362 3 9 0 +3363 3 9 1 +3364 2 8 0 +3365 2 8 1 +3366 2 9 0 +3367 2 9 1 +3368 0 9 1 +3369 0 9 0 +3370 0 8 1 +3371 0 8 0 +3372 1 9 1 +3373 1 9 0 +3374 1 8 1 +3375 1 8 0 +3376 4 8 0 +3377 4 8 1 +3378 4 9 0 +3379 4 9 1 +3380 5 8 0 +3381 5 8 1 +3382 5 9 0 +3383 5 9 1 +3384 7 9 1 +3385 7 9 0 +3386 7 8 1 +3387 7 8 0 +3388 6 9 1 +3389 6 9 0 +3390 6 8 1 +3391 6 8 0 +3392 12 9 0 +3393 12 9 1 +3394 12 8 0 +3395 12 8 1 +3396 13 9 0 +3397 13 9 1 +3398 13 8 0 +3399 13 8 1 +3400 15 8 1 +3401 15 8 0 +3402 15 9 1 +3403 15 9 0 +3404 14 8 1 +3405 14 8 0 +3406 14 9 1 +3407 14 9 0 +3456 11 7 0 +3457 11 7 1 +3458 11 6 0 +3459 11 6 1 +3460 10 7 0 +3461 10 7 1 +3462 10 6 0 +3463 10 6 1 +3464 8 6 1 +3465 8 6 0 +3466 8 7 1 +3467 8 7 0 +3468 9 6 1 +3469 9 6 0 +3470 9 7 1 +3471 9 7 0 +3488 3 6 0 +3489 3 6 1 +3490 3 7 0 +3491 3 7 1 +3492 2 6 0 +3493 2 6 1 +3494 2 7 0 +3495 2 7 1 +3496 0 7 1 +3497 0 7 0 +3498 0 6 1 +3499 0 6 0 +3500 1 7 1 +3501 1 7 0 +3502 1 6 1 +3503 1 6 0 +3504 4 6 0 +3505 4 6 1 +3506 4 7 0 +3507 4 7 1 +3508 5 6 0 +3509 5 6 1 +3510 5 7 0 +3511 5 7 1 +3512 7 7 1 +3513 7 7 0 +3514 7 6 1 +3515 7 6 0 +3516 6 7 1 +3517 6 7 0 +3518 6 6 1 +3519 6 6 0 +3520 12 7 0 +3521 12 7 1 +3522 12 6 0 +3523 12 6 1 +3524 13 7 0 +3525 13 7 1 +3526 13 6 0 +3527 13 6 1 +3528 15 6 1 +3529 15 6 0 +3530 15 7 1 +3531 15 7 0 +3532 14 6 1 +3533 14 6 0 +3534 14 7 1 +3535 14 7 0 +3584 11 5 0 +3585 11 5 1 +3586 11 4 0 +3587 11 4 1 +3588 10 5 0 +3589 10 5 1 +3590 10 4 0 +3591 10 4 1 +3592 8 4 1 +3593 8 4 0 +3594 8 5 1 +3595 8 5 0 +3596 9 4 1 +3597 9 4 0 +3598 9 5 1 +3599 9 5 0 +3616 3 4 0 +3617 3 4 1 +3618 3 5 0 +3619 3 5 1 +3620 2 4 0 +3621 2 4 1 +3622 2 5 0 +3623 2 5 1 +3624 0 5 1 +3625 0 5 0 +3626 0 4 1 +3627 0 4 0 +3628 1 5 1 +3629 1 5 0 +3630 1 4 1 +3631 1 4 0 +3632 4 4 0 +3633 4 4 1 +3634 4 5 0 +3635 4 5 1 +3636 5 4 0 +3637 5 4 1 +3638 5 5 0 +3639 5 5 1 +3640 7 5 1 +3641 7 5 0 +3642 7 4 1 +3643 7 4 0 +3644 6 5 1 +3645 6 5 0 +3646 6 4 1 +3647 6 4 0 +3648 12 5 0 +3649 12 5 1 +3650 12 4 0 +3651 12 4 1 +3652 13 5 0 +3653 13 5 1 +3654 13 4 0 +3655 13 4 1 +3656 15 4 1 +3657 15 4 0 +3658 15 5 1 +3659 15 5 0 +3660 14 4 1 +3661 14 4 0 +3662 14 5 1 +3663 14 5 0 +3712 11 3 0 +3713 11 3 1 +3714 11 2 0 +3715 11 2 1 +3716 10 3 0 +3717 10 3 1 +3718 10 2 0 +3719 10 2 1 +3720 8 2 1 +3721 8 2 0 +3722 8 3 1 +3723 8 3 0 +3724 9 2 1 +3725 9 2 0 +3726 9 3 1 +3727 9 3 0 +3744 3 2 0 +3745 3 2 1 +3746 3 3 0 +3747 3 3 1 +3748 2 2 0 +3749 2 2 1 +3750 2 3 0 +3751 2 3 1 +3752 0 3 1 +3753 0 3 0 +3754 0 2 1 +3755 0 2 0 +3756 1 3 1 +3757 1 3 0 +3758 1 2 1 +3759 1 2 0 +3760 4 2 0 +3761 4 2 1 +3762 4 3 0 +3763 4 3 1 +3764 5 2 0 +3765 5 2 1 +3766 5 3 0 +3767 5 3 1 +3768 7 3 1 +3769 7 3 0 +3770 7 2 1 +3771 7 2 0 +3772 6 3 1 +3773 6 3 0 +3774 6 2 1 +3775 6 2 0 +3776 12 3 0 +3777 12 3 1 +3778 12 2 0 +3779 12 2 1 +3780 13 3 0 +3781 13 3 1 +3782 13 2 0 +3783 13 2 1 +3784 15 2 1 +3785 15 2 0 +3786 15 3 1 +3787 15 3 0 +3788 14 2 1 +3789 14 2 0 +3790 14 3 1 +3791 14 3 0 +3840 11 1 0 +3841 11 1 1 +3842 11 0 0 +3843 11 0 1 +3844 10 1 0 +3845 10 1 1 +3846 10 0 0 +3847 10 0 1 +3848 8 0 1 +3849 8 0 0 +3850 8 1 1 +3851 8 1 0 +3852 9 0 1 +3853 9 0 0 +3854 9 1 1 +3855 9 1 0 +3872 3 0 0 +3873 3 0 1 +3874 3 1 0 +3875 3 1 1 +3876 2 0 0 +3877 2 0 1 +3878 2 1 0 +3879 2 1 1 +3880 0 1 1 +3881 0 1 0 +3882 0 0 1 +3883 0 0 0 +3884 1 1 1 +3885 1 1 0 +3886 1 0 1 +3887 1 0 0 +3888 4 0 0 +3889 4 0 1 +3890 4 1 0 +3891 4 1 1 +3892 5 0 0 +3893 5 0 1 +3894 5 1 0 +3895 5 1 1 +3896 7 1 1 +3897 7 1 0 +3898 7 0 1 +3899 7 0 0 +3900 6 1 1 +3901 6 1 0 +3902 6 0 1 +3903 6 0 0 +3904 12 1 0 +3905 12 1 1 +3906 12 0 0 +3907 12 0 1 +3908 13 1 0 +3909 13 1 1 +3910 13 0 0 +3911 13 0 1 +3912 15 0 1 +3913 15 0 0 +3914 15 1 1 +3915 15 1 0 +3916 14 0 1 +3917 14 0 0 +3918 14 1 1 +3919 14 1 0 diff --git a/Detectors/PHOS/base/files/Mod2RCU1.data b/Detectors/PHOS/base/files/Mod2RCU1.data new file mode 100644 index 0000000000000..db125226496cf --- /dev/null +++ b/Detectors/PHOS/base/files/Mod2RCU1.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 1 0 2 + 1 1 1 2 + 2 1 2 2 + 3 1 3 2 + 4 1 4 2 + 5 1 5 2 + 6 1 6 2 + 7 1 7 2 + 8 1 8 2 + 9 1 9 2 + 10 1 10 2 + 11 1 11 2 + 12 1 12 2 + 13 1 13 2 + 14 1 14 2 + 15 1 15 2 + 16 1 16 2 + 17 1 17 2 + 18 1 18 2 + 19 1 19 2 + 20 1 20 2 + 21 1 21 2 + 22 1 22 2 + 23 1 23 2 + 24 1 24 2 + 25 1 25 2 + 26 1 26 2 + 27 1 27 2 + 28 1 28 2 + 29 1 29 2 + 30 1 30 2 + 31 1 31 2 + 32 1 32 2 + 33 1 33 2 + 34 1 34 2 + 35 1 35 2 + 36 1 36 2 + 37 1 37 2 + 38 1 38 2 + 39 1 39 2 + 40 1 40 2 + 41 1 41 2 + 42 1 42 2 + 43 1 43 2 + 44 1 44 2 + 45 1 45 2 + 46 1 46 2 + 47 1 47 2 + 48 1 48 2 + 49 1 49 2 + 50 1 50 2 + 51 1 51 2 + 52 1 52 2 + 53 1 53 2 + 54 1 54 2 + 55 1 55 2 + 56 1 56 2 + 57 1 57 2 + 58 1 58 2 + 59 1 59 2 + 60 1 60 2 + 61 1 61 2 + 62 1 62 2 + 63 1 63 2 + 64 1 64 2 + 65 1 65 2 + 66 1 66 2 + 67 1 67 2 + 68 1 68 2 + 69 1 69 2 + 70 1 70 2 + 71 1 71 2 + 72 1 72 2 + 73 1 73 2 + 74 1 74 2 + 75 1 75 2 + 76 1 76 2 + 77 1 77 2 + 78 1 78 2 + 79 1 79 2 + 80 1 80 2 + 81 1 81 2 + 82 1 82 2 + 83 1 83 2 + 84 1 84 2 + 85 1 85 2 + 86 1 86 2 + 87 1 87 2 + 88 1 88 2 + 89 1 89 2 + 90 1 90 2 + 91 1 91 2 + 92 1 92 2 + 93 1 93 2 + 94 1 94 2 + 95 1 95 2 + 96 1 96 2 + 97 1 97 2 + 98 1 98 2 + 99 1 99 2 + 100 1 100 2 + 101 1 101 2 + 102 1 102 2 + 103 1 103 2 + 104 1 104 2 + 105 1 105 2 + 106 1 106 2 + 107 1 107 2 + 108 1 108 2 + 109 1 109 2 + 110 1 110 2 + 111 1 111 2 + 112 1 112 2 + 113 1 113 2 + 114 1 114 2 + 115 1 115 2 + 116 1 116 2 + 117 1 117 2 + 118 1 118 2 + 119 1 119 2 + 120 1 120 2 + 121 1 121 2 + 122 1 122 2 + 123 1 123 2 + 124 1 124 2 + 125 1 125 2 + 126 1 126 2 + 127 1 127 2 +2048 1 2048 2 +2049 1 2049 2 +2050 1 2050 2 +2051 1 2051 2 +2052 1 2052 2 +2053 1 2053 2 +2054 1 2054 2 +2055 1 2055 2 +2056 1 2056 2 +2057 1 2057 2 +2058 1 2058 2 +2059 1 2059 2 +2060 1 2060 2 +2061 1 2061 2 +2062 1 2062 2 +2063 1 2063 2 +2064 1 2064 2 +2065 1 2065 2 +2066 1 2066 2 +2067 1 2067 2 +2068 1 2068 2 +2069 1 2069 2 +2070 1 2070 2 +2071 1 2071 2 +2072 1 2072 2 +2073 1 2073 2 +2074 1 2074 2 +2075 1 2075 2 +2076 1 2076 2 +2077 1 2077 2 +2078 1 2078 2 +2079 1 2079 2 +2080 1 2080 2 +2081 1 2081 2 +2082 1 2082 2 +2083 1 2083 2 +2084 1 2084 2 +2085 1 2085 2 +2086 1 2086 2 +2087 1 2087 2 +2088 1 2088 2 +2089 1 2089 2 +2090 1 2090 2 +2091 1 2091 2 +2092 1 2092 2 +2093 1 2093 2 +2094 1 2094 2 +2095 1 2095 2 +2096 1 2096 2 +2097 1 2097 2 +2098 1 2098 2 +2099 1 2099 2 +2100 1 2100 2 +2101 1 2101 2 +2102 1 2102 2 +2103 1 2103 2 +2104 1 2104 2 +2105 1 2105 2 +2106 1 2106 2 +2107 1 2107 2 +2108 1 2108 2 +2109 1 2109 2 +2110 1 2110 2 +2111 1 2111 2 +2112 1 2112 2 +2113 1 2113 2 +2114 1 2114 2 +2115 1 2115 2 +2116 1 2116 2 +2117 1 2117 2 +2118 1 2118 2 +2119 1 2119 2 +2120 1 2120 2 +2121 1 2121 2 +2122 1 2122 2 +2123 1 2123 2 +2124 1 2124 2 +2125 1 2125 2 +2126 1 2126 2 +2127 1 2127 2 +2128 1 2128 2 +2129 1 2129 2 +2130 1 2130 2 +2131 1 2131 2 +2132 1 2132 2 +2133 1 2133 2 +2134 1 2134 2 +2135 1 2135 2 +2136 1 2136 2 +2137 1 2137 2 +2138 1 2138 2 +2139 1 2139 2 +2140 1 2140 2 +2141 1 2141 2 +2142 1 2142 2 +2143 1 2143 2 +2144 1 2144 2 +2145 1 2145 2 +2146 1 2146 2 +2147 1 2147 2 +2148 1 2148 2 +2149 1 2149 2 +2150 1 2150 2 +2151 1 2151 2 +2152 1 2152 2 +2153 1 2153 2 +2154 1 2154 2 +2155 1 2155 2 +2156 1 2156 2 +2157 1 2157 2 +2158 1 2158 2 +2159 1 2159 2 +2160 1 2160 2 +2161 1 2161 2 +2162 1 2162 2 +2163 1 2163 2 +2164 1 2164 2 +2165 1 2165 2 +2166 1 2166 2 +2167 1 2167 2 +2168 1 2168 2 +2169 1 2169 2 +2170 1 2170 2 +2171 1 2171 2 +2172 1 2172 2 +2173 1 2173 2 +2174 1 2174 2 +2175 1 2175 2 + 128 27 29 0 + 129 27 29 1 + 130 27 28 0 + 131 27 28 1 + 132 26 29 0 + 133 26 29 1 + 134 26 28 0 + 135 26 28 1 + 136 24 28 1 + 137 24 28 0 + 138 24 29 1 + 139 24 29 0 + 140 25 28 1 + 141 25 28 0 + 142 25 29 1 + 143 25 29 0 + 160 19 28 0 + 161 19 28 1 + 162 19 29 0 + 163 19 29 1 + 164 18 28 0 + 165 18 28 1 + 166 18 29 0 + 167 18 29 1 + 168 16 29 1 + 169 16 29 0 + 170 16 28 1 + 171 16 28 0 + 172 17 29 1 + 173 17 29 0 + 174 17 28 1 + 175 17 28 0 + 176 20 28 0 + 177 20 28 1 + 178 20 29 0 + 179 20 29 1 + 180 21 28 0 + 181 21 28 1 + 182 21 29 0 + 183 21 29 1 + 184 23 29 1 + 185 23 29 0 + 186 23 28 1 + 187 23 28 0 + 188 22 29 1 + 189 22 29 0 + 190 22 28 1 + 191 22 28 0 + 192 28 29 0 + 193 28 29 1 + 194 28 28 0 + 195 28 28 1 + 196 29 29 0 + 197 29 29 1 + 198 29 28 0 + 199 29 28 1 + 200 31 28 1 + 201 31 28 0 + 202 31 29 1 + 203 31 29 0 + 204 30 28 1 + 205 30 28 0 + 206 30 29 1 + 207 30 29 0 + 256 27 31 0 + 257 27 31 1 + 258 27 30 0 + 259 27 30 1 + 260 26 31 0 + 261 26 31 1 + 262 26 30 0 + 263 26 30 1 + 264 24 30 1 + 265 24 30 0 + 266 24 31 1 + 267 24 31 0 + 268 25 30 1 + 269 25 30 0 + 270 25 31 1 + 271 25 31 0 + 288 19 30 0 + 289 19 30 1 + 290 19 31 0 + 291 19 31 1 + 292 18 30 0 + 293 18 30 1 + 294 18 31 0 + 295 18 31 1 + 296 16 31 1 + 297 16 31 0 + 298 16 30 1 + 299 16 30 0 + 300 17 31 1 + 301 17 31 0 + 302 17 30 1 + 303 17 30 0 + 304 20 30 0 + 305 20 30 1 + 306 20 31 0 + 307 20 31 1 + 308 21 30 0 + 309 21 30 1 + 310 21 31 0 + 311 21 31 1 + 312 23 31 1 + 313 23 31 0 + 314 23 30 1 + 315 23 30 0 + 316 22 31 1 + 317 22 31 0 + 318 22 30 1 + 319 22 30 0 + 320 28 31 0 + 321 28 31 1 + 322 28 30 0 + 323 28 30 1 + 324 29 31 0 + 325 29 31 1 + 326 29 30 0 + 327 29 30 1 + 328 31 30 1 + 329 31 30 0 + 330 31 31 1 + 331 31 31 0 + 332 30 30 1 + 333 30 30 0 + 334 30 31 1 + 335 30 31 0 + 384 27 33 0 + 385 27 33 1 + 386 27 32 0 + 387 27 32 1 + 388 26 33 0 + 389 26 33 1 + 390 26 32 0 + 391 26 32 1 + 392 24 32 1 + 393 24 32 0 + 394 24 33 1 + 395 24 33 0 + 396 25 32 1 + 397 25 32 0 + 398 25 33 1 + 399 25 33 0 + 416 19 32 0 + 417 19 32 1 + 418 19 33 0 + 419 19 33 1 + 420 18 32 0 + 421 18 32 1 + 422 18 33 0 + 423 18 33 1 + 424 16 33 1 + 425 16 33 0 + 426 16 32 1 + 427 16 32 0 + 428 17 33 1 + 429 17 33 0 + 430 17 32 1 + 431 17 32 0 + 432 20 32 0 + 433 20 32 1 + 434 20 33 0 + 435 20 33 1 + 436 21 32 0 + 437 21 32 1 + 438 21 33 0 + 439 21 33 1 + 440 23 33 1 + 441 23 33 0 + 442 23 32 1 + 443 23 32 0 + 444 22 33 1 + 445 22 33 0 + 446 22 32 1 + 447 22 32 0 + 448 28 33 0 + 449 28 33 1 + 450 28 32 0 + 451 28 32 1 + 452 29 33 0 + 453 29 33 1 + 454 29 32 0 + 455 29 32 1 + 456 31 32 1 + 457 31 32 0 + 458 31 33 1 + 459 31 33 0 + 460 30 32 1 + 461 30 32 0 + 462 30 33 1 + 463 30 33 0 + 512 27 35 0 + 513 27 35 1 + 514 27 34 0 + 515 27 34 1 + 516 26 35 0 + 517 26 35 1 + 518 26 34 0 + 519 26 34 1 + 520 24 34 1 + 521 24 34 0 + 522 24 35 1 + 523 24 35 0 + 524 25 34 1 + 525 25 34 0 + 526 25 35 1 + 527 25 35 0 + 544 19 34 0 + 545 19 34 1 + 546 19 35 0 + 547 19 35 1 + 548 18 34 0 + 549 18 34 1 + 550 18 35 0 + 551 18 35 1 + 552 16 35 1 + 553 16 35 0 + 554 16 34 1 + 555 16 34 0 + 556 17 35 1 + 557 17 35 0 + 558 17 34 1 + 559 17 34 0 + 560 20 34 0 + 561 20 34 1 + 562 20 35 0 + 563 20 35 1 + 564 21 34 0 + 565 21 34 1 + 566 21 35 0 + 567 21 35 1 + 568 23 35 1 + 569 23 35 0 + 570 23 34 1 + 571 23 34 0 + 572 22 35 1 + 573 22 35 0 + 574 22 34 1 + 575 22 34 0 + 576 28 35 0 + 577 28 35 1 + 578 28 34 0 + 579 28 34 1 + 580 29 35 0 + 581 29 35 1 + 582 29 34 0 + 583 29 34 1 + 584 31 34 1 + 585 31 34 0 + 586 31 35 1 + 587 31 35 0 + 588 30 34 1 + 589 30 34 0 + 590 30 35 1 + 591 30 35 0 + 640 27 37 0 + 641 27 37 1 + 642 27 36 0 + 643 27 36 1 + 644 26 37 0 + 645 26 37 1 + 646 26 36 0 + 647 26 36 1 + 648 24 36 1 + 649 24 36 0 + 650 24 37 1 + 651 24 37 0 + 652 25 36 1 + 653 25 36 0 + 654 25 37 1 + 655 25 37 0 + 672 19 36 0 + 673 19 36 1 + 674 19 37 0 + 675 19 37 1 + 676 18 36 0 + 677 18 36 1 + 678 18 37 0 + 679 18 37 1 + 680 16 37 1 + 681 16 37 0 + 682 16 36 1 + 683 16 36 0 + 684 17 37 1 + 685 17 37 0 + 686 17 36 1 + 687 17 36 0 + 688 20 36 0 + 689 20 36 1 + 690 20 37 0 + 691 20 37 1 + 692 21 36 0 + 693 21 36 1 + 694 21 37 0 + 695 21 37 1 + 696 23 37 1 + 697 23 37 0 + 698 23 36 1 + 699 23 36 0 + 700 22 37 1 + 701 22 37 0 + 702 22 36 1 + 703 22 36 0 + 704 28 37 0 + 705 28 37 1 + 706 28 36 0 + 707 28 36 1 + 708 29 37 0 + 709 29 37 1 + 710 29 36 0 + 711 29 36 1 + 712 31 36 1 + 713 31 36 0 + 714 31 37 1 + 715 31 37 0 + 716 30 36 1 + 717 30 36 0 + 718 30 37 1 + 719 30 37 0 + 768 27 39 0 + 769 27 39 1 + 770 27 38 0 + 771 27 38 1 + 772 26 39 0 + 773 26 39 1 + 774 26 38 0 + 775 26 38 1 + 776 24 38 1 + 777 24 38 0 + 778 24 39 1 + 779 24 39 0 + 780 25 38 1 + 781 25 38 0 + 782 25 39 1 + 783 25 39 0 + 800 19 38 0 + 801 19 38 1 + 802 19 39 0 + 803 19 39 1 + 804 18 38 0 + 805 18 38 1 + 806 18 39 0 + 807 18 39 1 + 808 16 39 1 + 809 16 39 0 + 810 16 38 1 + 811 16 38 0 + 812 17 39 1 + 813 17 39 0 + 814 17 38 1 + 815 17 38 0 + 816 20 38 0 + 817 20 38 1 + 818 20 39 0 + 819 20 39 1 + 820 21 38 0 + 821 21 38 1 + 822 21 39 0 + 823 21 39 1 + 824 23 39 1 + 825 23 39 0 + 826 23 38 1 + 827 23 38 0 + 828 22 39 1 + 829 22 39 0 + 830 22 38 1 + 831 22 38 0 + 832 28 39 0 + 833 28 39 1 + 834 28 38 0 + 835 28 38 1 + 836 29 39 0 + 837 29 39 1 + 838 29 38 0 + 839 29 38 1 + 840 31 38 1 + 841 31 38 0 + 842 31 39 1 + 843 31 39 0 + 844 30 38 1 + 845 30 38 0 + 846 30 39 1 + 847 30 39 0 + 896 27 41 0 + 897 27 41 1 + 898 27 40 0 + 899 27 40 1 + 900 26 41 0 + 901 26 41 1 + 902 26 40 0 + 903 26 40 1 + 904 24 40 1 + 905 24 40 0 + 906 24 41 1 + 907 24 41 0 + 908 25 40 1 + 909 25 40 0 + 910 25 41 1 + 911 25 41 0 + 928 19 40 0 + 929 19 40 1 + 930 19 41 0 + 931 19 41 1 + 932 18 40 0 + 933 18 40 1 + 934 18 41 0 + 935 18 41 1 + 936 16 41 1 + 937 16 41 0 + 938 16 40 1 + 939 16 40 0 + 940 17 41 1 + 941 17 41 0 + 942 17 40 1 + 943 17 40 0 + 944 20 40 0 + 945 20 40 1 + 946 20 41 0 + 947 20 41 1 + 948 21 40 0 + 949 21 40 1 + 950 21 41 0 + 951 21 41 1 + 952 23 41 1 + 953 23 41 0 + 954 23 40 1 + 955 23 40 0 + 956 22 41 1 + 957 22 41 0 + 958 22 40 1 + 959 22 40 0 + 960 28 41 0 + 961 28 41 1 + 962 28 40 0 + 963 28 40 1 + 964 29 41 0 + 965 29 41 1 + 966 29 40 0 + 967 29 40 1 + 968 31 40 1 + 969 31 40 0 + 970 31 41 1 + 971 31 41 0 + 972 30 40 1 + 973 30 40 0 + 974 30 41 1 + 975 30 41 0 +1024 27 43 0 +1025 27 43 1 +1026 27 42 0 +1027 27 42 1 +1028 26 43 0 +1029 26 43 1 +1030 26 42 0 +1031 26 42 1 +1032 24 42 1 +1033 24 42 0 +1034 24 43 1 +1035 24 43 0 +1036 25 42 1 +1037 25 42 0 +1038 25 43 1 +1039 25 43 0 +1056 19 42 0 +1057 19 42 1 +1058 19 43 0 +1059 19 43 1 +1060 18 42 0 +1061 18 42 1 +1062 18 43 0 +1063 18 43 1 +1064 16 43 1 +1065 16 43 0 +1066 16 42 1 +1067 16 42 0 +1068 17 43 1 +1069 17 43 0 +1070 17 42 1 +1071 17 42 0 +1072 20 42 0 +1073 20 42 1 +1074 20 43 0 +1075 20 43 1 +1076 21 42 0 +1077 21 42 1 +1078 21 43 0 +1079 21 43 1 +1080 23 43 1 +1081 23 43 0 +1082 23 42 1 +1083 23 42 0 +1084 22 43 1 +1085 22 43 0 +1086 22 42 1 +1087 22 42 0 +1088 28 43 0 +1089 28 43 1 +1090 28 42 0 +1091 28 42 1 +1092 29 43 0 +1093 29 43 1 +1094 29 42 0 +1095 29 42 1 +1096 31 42 1 +1097 31 42 0 +1098 31 43 1 +1099 31 43 0 +1100 30 42 1 +1101 30 42 0 +1102 30 43 1 +1103 30 43 0 +1152 27 45 0 +1153 27 45 1 +1154 27 44 0 +1155 27 44 1 +1156 26 45 0 +1157 26 45 1 +1158 26 44 0 +1159 26 44 1 +1160 24 44 1 +1161 24 44 0 +1162 24 45 1 +1163 24 45 0 +1164 25 44 1 +1165 25 44 0 +1166 25 45 1 +1167 25 45 0 +1184 19 44 0 +1185 19 44 1 +1186 19 45 0 +1187 19 45 1 +1188 18 44 0 +1189 18 44 1 +1190 18 45 0 +1191 18 45 1 +1192 16 45 1 +1193 16 45 0 +1194 16 44 1 +1195 16 44 0 +1196 17 45 1 +1197 17 45 0 +1198 17 44 1 +1199 17 44 0 +1200 20 44 0 +1201 20 44 1 +1202 20 45 0 +1203 20 45 1 +1204 21 44 0 +1205 21 44 1 +1206 21 45 0 +1207 21 45 1 +1208 23 45 1 +1209 23 45 0 +1210 23 44 1 +1211 23 44 0 +1212 22 45 1 +1213 22 45 0 +1214 22 44 1 +1215 22 44 0 +1216 28 45 0 +1217 28 45 1 +1218 28 44 0 +1219 28 44 1 +1220 29 45 0 +1221 29 45 1 +1222 29 44 0 +1223 29 44 1 +1224 31 44 1 +1225 31 44 0 +1226 31 45 1 +1227 31 45 0 +1228 30 44 1 +1229 30 44 0 +1230 30 45 1 +1231 30 45 0 +1280 27 47 0 +1281 27 47 1 +1282 27 46 0 +1283 27 46 1 +1284 26 47 0 +1285 26 47 1 +1286 26 46 0 +1287 26 46 1 +1288 24 46 1 +1289 24 46 0 +1290 24 47 1 +1291 24 47 0 +1292 25 46 1 +1293 25 46 0 +1294 25 47 1 +1295 25 47 0 +1312 19 46 0 +1313 19 46 1 +1314 19 47 0 +1315 19 47 1 +1316 18 46 0 +1317 18 46 1 +1318 18 47 0 +1319 18 47 1 +1320 16 47 1 +1321 16 47 0 +1322 16 46 1 +1323 16 46 0 +1324 17 47 1 +1325 17 47 0 +1326 17 46 1 +1327 17 46 0 +1328 20 46 0 +1329 20 46 1 +1330 20 47 0 +1331 20 47 1 +1332 21 46 0 +1333 21 46 1 +1334 21 47 0 +1335 21 47 1 +1336 23 47 1 +1337 23 47 0 +1338 23 46 1 +1339 23 46 0 +1340 22 47 1 +1341 22 47 0 +1342 22 46 1 +1343 22 46 0 +1344 28 47 0 +1345 28 47 1 +1346 28 46 0 +1347 28 46 1 +1348 29 47 0 +1349 29 47 1 +1350 29 46 0 +1351 29 46 1 +1352 31 46 1 +1353 31 46 0 +1354 31 47 1 +1355 31 47 0 +1356 30 46 1 +1357 30 46 0 +1358 30 47 1 +1359 30 47 0 +1408 27 49 0 +1409 27 49 1 +1410 27 48 0 +1411 27 48 1 +1412 26 49 0 +1413 26 49 1 +1414 26 48 0 +1415 26 48 1 +1416 24 48 1 +1417 24 48 0 +1418 24 49 1 +1419 24 49 0 +1420 25 48 1 +1421 25 48 0 +1422 25 49 1 +1423 25 49 0 +1440 19 48 0 +1441 19 48 1 +1442 19 49 0 +1443 19 49 1 +1444 18 48 0 +1445 18 48 1 +1446 18 49 0 +1447 18 49 1 +1448 16 49 1 +1449 16 49 0 +1450 16 48 1 +1451 16 48 0 +1452 17 49 1 +1453 17 49 0 +1454 17 48 1 +1455 17 48 0 +1456 20 48 0 +1457 20 48 1 +1458 20 49 0 +1459 20 49 1 +1460 21 48 0 +1461 21 48 1 +1462 21 49 0 +1463 21 49 1 +1464 23 49 1 +1465 23 49 0 +1466 23 48 1 +1467 23 48 0 +1468 22 49 1 +1469 22 49 0 +1470 22 48 1 +1471 22 48 0 +1472 28 49 0 +1473 28 49 1 +1474 28 48 0 +1475 28 48 1 +1476 29 49 0 +1477 29 49 1 +1478 29 48 0 +1479 29 48 1 +1480 31 48 1 +1481 31 48 0 +1482 31 49 1 +1483 31 49 0 +1484 30 48 1 +1485 30 48 0 +1486 30 49 1 +1487 30 49 0 +1536 27 51 0 +1537 27 51 1 +1538 27 50 0 +1539 27 50 1 +1540 26 51 0 +1541 26 51 1 +1542 26 50 0 +1543 26 50 1 +1544 24 50 1 +1545 24 50 0 +1546 24 51 1 +1547 24 51 0 +1548 25 50 1 +1549 25 50 0 +1550 25 51 1 +1551 25 51 0 +1568 19 50 0 +1569 19 50 1 +1570 19 51 0 +1571 19 51 1 +1572 18 50 0 +1573 18 50 1 +1574 18 51 0 +1575 18 51 1 +1576 16 51 1 +1577 16 51 0 +1578 16 50 1 +1579 16 50 0 +1580 17 51 1 +1581 17 51 0 +1582 17 50 1 +1583 17 50 0 +1584 20 50 0 +1585 20 50 1 +1586 20 51 0 +1587 20 51 1 +1588 21 50 0 +1589 21 50 1 +1590 21 51 0 +1591 21 51 1 +1592 23 51 1 +1593 23 51 0 +1594 23 50 1 +1595 23 50 0 +1596 22 51 1 +1597 22 51 0 +1598 22 50 1 +1599 22 50 0 +1600 28 51 0 +1601 28 51 1 +1602 28 50 0 +1603 28 50 1 +1604 29 51 0 +1605 29 51 1 +1606 29 50 0 +1607 29 50 1 +1608 31 50 1 +1609 31 50 0 +1610 31 51 1 +1611 31 51 0 +1612 30 50 1 +1613 30 50 0 +1614 30 51 1 +1615 30 51 0 +1664 27 53 0 +1665 27 53 1 +1666 27 52 0 +1667 27 52 1 +1668 26 53 0 +1669 26 53 1 +1670 26 52 0 +1671 26 52 1 +1672 24 52 1 +1673 24 52 0 +1674 24 53 1 +1675 24 53 0 +1676 25 52 1 +1677 25 52 0 +1678 25 53 1 +1679 25 53 0 +1696 19 52 0 +1697 19 52 1 +1698 19 53 0 +1699 19 53 1 +1700 18 52 0 +1701 18 52 1 +1702 18 53 0 +1703 18 53 1 +1704 16 53 1 +1705 16 53 0 +1706 16 52 1 +1707 16 52 0 +1708 17 53 1 +1709 17 53 0 +1710 17 52 1 +1711 17 52 0 +1712 20 52 0 +1713 20 52 1 +1714 20 53 0 +1715 20 53 1 +1716 21 52 0 +1717 21 52 1 +1718 21 53 0 +1719 21 53 1 +1720 23 53 1 +1721 23 53 0 +1722 23 52 1 +1723 23 52 0 +1724 22 53 1 +1725 22 53 0 +1726 22 52 1 +1727 22 52 0 +1728 28 53 0 +1729 28 53 1 +1730 28 52 0 +1731 28 52 1 +1732 29 53 0 +1733 29 53 1 +1734 29 52 0 +1735 29 52 1 +1736 31 52 1 +1737 31 52 0 +1738 31 53 1 +1739 31 53 0 +1740 30 52 1 +1741 30 52 0 +1742 30 53 1 +1743 30 53 0 +1792 27 55 0 +1793 27 55 1 +1794 27 54 0 +1795 27 54 1 +1796 26 55 0 +1797 26 55 1 +1798 26 54 0 +1799 26 54 1 +1800 24 54 1 +1801 24 54 0 +1802 24 55 1 +1803 24 55 0 +1804 25 54 1 +1805 25 54 0 +1806 25 55 1 +1807 25 55 0 +1824 19 54 0 +1825 19 54 1 +1826 19 55 0 +1827 19 55 1 +1828 18 54 0 +1829 18 54 1 +1830 18 55 0 +1831 18 55 1 +1832 16 55 1 +1833 16 55 0 +1834 16 54 1 +1835 16 54 0 +1836 17 55 1 +1837 17 55 0 +1838 17 54 1 +1839 17 54 0 +1840 20 54 0 +1841 20 54 1 +1842 20 55 0 +1843 20 55 1 +1844 21 54 0 +1845 21 54 1 +1846 21 55 0 +1847 21 55 1 +1848 23 55 1 +1849 23 55 0 +1850 23 54 1 +1851 23 54 0 +1852 22 55 1 +1853 22 55 0 +1854 22 54 1 +1855 22 54 0 +1856 28 55 0 +1857 28 55 1 +1858 28 54 0 +1859 28 54 1 +1860 29 55 0 +1861 29 55 1 +1862 29 54 0 +1863 29 54 1 +1864 31 54 1 +1865 31 54 0 +1866 31 55 1 +1867 31 55 0 +1868 30 54 1 +1869 30 54 0 +1870 30 55 1 +1871 30 55 0 +2176 27 27 0 +2177 27 27 1 +2178 27 26 0 +2179 27 26 1 +2180 26 27 0 +2181 26 27 1 +2182 26 26 0 +2183 26 26 1 +2184 24 26 1 +2185 24 26 0 +2186 24 27 1 +2187 24 27 0 +2188 25 26 1 +2189 25 26 0 +2190 25 27 1 +2191 25 27 0 +2208 19 26 0 +2209 19 26 1 +2210 19 27 0 +2211 19 27 1 +2212 18 26 0 +2213 18 26 1 +2214 18 27 0 +2215 18 27 1 +2216 16 27 1 +2217 16 27 0 +2218 16 26 1 +2219 16 26 0 +2220 17 27 1 +2221 17 27 0 +2222 17 26 1 +2223 17 26 0 +2224 20 26 0 +2225 20 26 1 +2226 20 27 0 +2227 20 27 1 +2228 21 26 0 +2229 21 26 1 +2230 21 27 0 +2231 21 27 1 +2232 23 27 1 +2233 23 27 0 +2234 23 26 1 +2235 23 26 0 +2236 22 27 1 +2237 22 27 0 +2238 22 26 1 +2239 22 26 0 +2240 28 27 0 +2241 28 27 1 +2242 28 26 0 +2243 28 26 1 +2244 29 27 0 +2245 29 27 1 +2246 29 26 0 +2247 29 26 1 +2248 31 26 1 +2249 31 26 0 +2250 31 27 1 +2251 31 27 0 +2252 30 26 1 +2253 30 26 0 +2254 30 27 1 +2255 30 27 0 +2304 27 25 0 +2305 27 25 1 +2306 27 24 0 +2307 27 24 1 +2308 26 25 0 +2309 26 25 1 +2310 26 24 0 +2311 26 24 1 +2312 24 24 1 +2313 24 24 0 +2314 24 25 1 +2315 24 25 0 +2316 25 24 1 +2317 25 24 0 +2318 25 25 1 +2319 25 25 0 +2336 19 24 0 +2337 19 24 1 +2338 19 25 0 +2339 19 25 1 +2340 18 24 0 +2341 18 24 1 +2342 18 25 0 +2343 18 25 1 +2344 16 25 1 +2345 16 25 0 +2346 16 24 1 +2347 16 24 0 +2348 17 25 1 +2349 17 25 0 +2350 17 24 1 +2351 17 24 0 +2352 20 24 0 +2353 20 24 1 +2354 20 25 0 +2355 20 25 1 +2356 21 24 0 +2357 21 24 1 +2358 21 25 0 +2359 21 25 1 +2360 23 25 1 +2361 23 25 0 +2362 23 24 1 +2363 23 24 0 +2364 22 25 1 +2365 22 25 0 +2366 22 24 1 +2367 22 24 0 +2368 28 25 0 +2369 28 25 1 +2370 28 24 0 +2371 28 24 1 +2372 29 25 0 +2373 29 25 1 +2374 29 24 0 +2375 29 24 1 +2376 31 24 1 +2377 31 24 0 +2378 31 25 1 +2379 31 25 0 +2380 30 24 1 +2381 30 24 0 +2382 30 25 1 +2383 30 25 0 +2432 27 23 0 +2433 27 23 1 +2434 27 22 0 +2435 27 22 1 +2436 26 23 0 +2437 26 23 1 +2438 26 22 0 +2439 26 22 1 +2440 24 22 1 +2441 24 22 0 +2442 24 23 1 +2443 24 23 0 +2444 25 22 1 +2445 25 22 0 +2446 25 23 1 +2447 25 23 0 +2464 19 22 0 +2465 19 22 1 +2466 19 23 0 +2467 19 23 1 +2468 18 22 0 +2469 18 22 1 +2470 18 23 0 +2471 18 23 1 +2472 16 23 1 +2473 16 23 0 +2474 16 22 1 +2475 16 22 0 +2476 17 23 1 +2477 17 23 0 +2478 17 22 1 +2479 17 22 0 +2480 20 22 0 +2481 20 22 1 +2482 20 23 0 +2483 20 23 1 +2484 21 22 0 +2485 21 22 1 +2486 21 23 0 +2487 21 23 1 +2488 23 23 1 +2489 23 23 0 +2490 23 22 1 +2491 23 22 0 +2492 22 23 1 +2493 22 23 0 +2494 22 22 1 +2495 22 22 0 +2496 28 23 0 +2497 28 23 1 +2498 28 22 0 +2499 28 22 1 +2500 29 23 0 +2501 29 23 1 +2502 29 22 0 +2503 29 22 1 +2504 31 22 1 +2505 31 22 0 +2506 31 23 1 +2507 31 23 0 +2508 30 22 1 +2509 30 22 0 +2510 30 23 1 +2511 30 23 0 +2560 27 21 0 +2561 27 21 1 +2562 27 20 0 +2563 27 20 1 +2564 26 21 0 +2565 26 21 1 +2566 26 20 0 +2567 26 20 1 +2568 24 20 1 +2569 24 20 0 +2570 24 21 1 +2571 24 21 0 +2572 25 20 1 +2573 25 20 0 +2574 25 21 1 +2575 25 21 0 +2592 19 20 0 +2593 19 20 1 +2594 19 21 0 +2595 19 21 1 +2596 18 20 0 +2597 18 20 1 +2598 18 21 0 +2599 18 21 1 +2600 16 21 1 +2601 16 21 0 +2602 16 20 1 +2603 16 20 0 +2604 17 21 1 +2605 17 21 0 +2606 17 20 1 +2607 17 20 0 +2608 20 20 0 +2609 20 20 1 +2610 20 21 0 +2611 20 21 1 +2612 21 20 0 +2613 21 20 1 +2614 21 21 0 +2615 21 21 1 +2616 23 21 1 +2617 23 21 0 +2618 23 20 1 +2619 23 20 0 +2620 22 21 1 +2621 22 21 0 +2622 22 20 1 +2623 22 20 0 +2624 28 21 0 +2625 28 21 1 +2626 28 20 0 +2627 28 20 1 +2628 29 21 0 +2629 29 21 1 +2630 29 20 0 +2631 29 20 1 +2632 31 20 1 +2633 31 20 0 +2634 31 21 1 +2635 31 21 0 +2636 30 20 1 +2637 30 20 0 +2638 30 21 1 +2639 30 21 0 +2688 27 19 0 +2689 27 19 1 +2690 27 18 0 +2691 27 18 1 +2692 26 19 0 +2693 26 19 1 +2694 26 18 0 +2695 26 18 1 +2696 24 18 1 +2697 24 18 0 +2698 24 19 1 +2699 24 19 0 +2700 25 18 1 +2701 25 18 0 +2702 25 19 1 +2703 25 19 0 +2720 19 18 0 +2721 19 18 1 +2722 19 19 0 +2723 19 19 1 +2724 18 18 0 +2725 18 18 1 +2726 18 19 0 +2727 18 19 1 +2728 16 19 1 +2729 16 19 0 +2730 16 18 1 +2731 16 18 0 +2732 17 19 1 +2733 17 19 0 +2734 17 18 1 +2735 17 18 0 +2736 20 18 0 +2737 20 18 1 +2738 20 19 0 +2739 20 19 1 +2740 21 18 0 +2741 21 18 1 +2742 21 19 0 +2743 21 19 1 +2744 23 19 1 +2745 23 19 0 +2746 23 18 1 +2747 23 18 0 +2748 22 19 1 +2749 22 19 0 +2750 22 18 1 +2751 22 18 0 +2752 28 19 0 +2753 28 19 1 +2754 28 18 0 +2755 28 18 1 +2756 29 19 0 +2757 29 19 1 +2758 29 18 0 +2759 29 18 1 +2760 31 18 1 +2761 31 18 0 +2762 31 19 1 +2763 31 19 0 +2764 30 18 1 +2765 30 18 0 +2766 30 19 1 +2767 30 19 0 +2816 27 17 0 +2817 27 17 1 +2818 27 16 0 +2819 27 16 1 +2820 26 17 0 +2821 26 17 1 +2822 26 16 0 +2823 26 16 1 +2824 24 16 1 +2825 24 16 0 +2826 24 17 1 +2827 24 17 0 +2828 25 16 1 +2829 25 16 0 +2830 25 17 1 +2831 25 17 0 +2848 19 16 0 +2849 19 16 1 +2850 19 17 0 +2851 19 17 1 +2852 18 16 0 +2853 18 16 1 +2854 18 17 0 +2855 18 17 1 +2856 16 17 1 +2857 16 17 0 +2858 16 16 1 +2859 16 16 0 +2860 17 17 1 +2861 17 17 0 +2862 17 16 1 +2863 17 16 0 +2864 20 16 0 +2865 20 16 1 +2866 20 17 0 +2867 20 17 1 +2868 21 16 0 +2869 21 16 1 +2870 21 17 0 +2871 21 17 1 +2872 23 17 1 +2873 23 17 0 +2874 23 16 1 +2875 23 16 0 +2876 22 17 1 +2877 22 17 0 +2878 22 16 1 +2879 22 16 0 +2880 28 17 0 +2881 28 17 1 +2882 28 16 0 +2883 28 16 1 +2884 29 17 0 +2885 29 17 1 +2886 29 16 0 +2887 29 16 1 +2888 31 16 1 +2889 31 16 0 +2890 31 17 1 +2891 31 17 0 +2892 30 16 1 +2893 30 16 0 +2894 30 17 1 +2895 30 17 0 +2944 27 15 0 +2945 27 15 1 +2946 27 14 0 +2947 27 14 1 +2948 26 15 0 +2949 26 15 1 +2950 26 14 0 +2951 26 14 1 +2952 24 14 1 +2953 24 14 0 +2954 24 15 1 +2955 24 15 0 +2956 25 14 1 +2957 25 14 0 +2958 25 15 1 +2959 25 15 0 +2976 19 14 0 +2977 19 14 1 +2978 19 15 0 +2979 19 15 1 +2980 18 14 0 +2981 18 14 1 +2982 18 15 0 +2983 18 15 1 +2984 16 15 1 +2985 16 15 0 +2986 16 14 1 +2987 16 14 0 +2988 17 15 1 +2989 17 15 0 +2990 17 14 1 +2991 17 14 0 +2992 20 14 0 +2993 20 14 1 +2994 20 15 0 +2995 20 15 1 +2996 21 14 0 +2997 21 14 1 +2998 21 15 0 +2999 21 15 1 +3000 23 15 1 +3001 23 15 0 +3002 23 14 1 +3003 23 14 0 +3004 22 15 1 +3005 22 15 0 +3006 22 14 1 +3007 22 14 0 +3008 28 15 0 +3009 28 15 1 +3010 28 14 0 +3011 28 14 1 +3012 29 15 0 +3013 29 15 1 +3014 29 14 0 +3015 29 14 1 +3016 31 14 1 +3017 31 14 0 +3018 31 15 1 +3019 31 15 0 +3020 30 14 1 +3021 30 14 0 +3022 30 15 1 +3023 30 15 0 +3072 27 13 0 +3073 27 13 1 +3074 27 12 0 +3075 27 12 1 +3076 26 13 0 +3077 26 13 1 +3078 26 12 0 +3079 26 12 1 +3080 24 12 1 +3081 24 12 0 +3082 24 13 1 +3083 24 13 0 +3084 25 12 1 +3085 25 12 0 +3086 25 13 1 +3087 25 13 0 +3104 19 12 0 +3105 19 12 1 +3106 19 13 0 +3107 19 13 1 +3108 18 12 0 +3109 18 12 1 +3110 18 13 0 +3111 18 13 1 +3112 16 13 1 +3113 16 13 0 +3114 16 12 1 +3115 16 12 0 +3116 17 13 1 +3117 17 13 0 +3118 17 12 1 +3119 17 12 0 +3120 20 12 0 +3121 20 12 1 +3122 20 13 0 +3123 20 13 1 +3124 21 12 0 +3125 21 12 1 +3126 21 13 0 +3127 21 13 1 +3128 23 13 1 +3129 23 13 0 +3130 23 12 1 +3131 23 12 0 +3132 22 13 1 +3133 22 13 0 +3134 22 12 1 +3135 22 12 0 +3136 28 13 0 +3137 28 13 1 +3138 28 12 0 +3139 28 12 1 +3140 29 13 0 +3141 29 13 1 +3142 29 12 0 +3143 29 12 1 +3144 31 12 1 +3145 31 12 0 +3146 31 13 1 +3147 31 13 0 +3148 30 12 1 +3149 30 12 0 +3150 30 13 1 +3151 30 13 0 +3200 27 11 0 +3201 27 11 1 +3202 27 10 0 +3203 27 10 1 +3204 26 11 0 +3205 26 11 1 +3206 26 10 0 +3207 26 10 1 +3208 24 10 1 +3209 24 10 0 +3210 24 11 1 +3211 24 11 0 +3212 25 10 1 +3213 25 10 0 +3214 25 11 1 +3215 25 11 0 +3232 19 10 0 +3233 19 10 1 +3234 19 11 0 +3235 19 11 1 +3236 18 10 0 +3237 18 10 1 +3238 18 11 0 +3239 18 11 1 +3240 16 11 1 +3241 16 11 0 +3242 16 10 1 +3243 16 10 0 +3244 17 11 1 +3245 17 11 0 +3246 17 10 1 +3247 17 10 0 +3248 20 10 0 +3249 20 10 1 +3250 20 11 0 +3251 20 11 1 +3252 21 10 0 +3253 21 10 1 +3254 21 11 0 +3255 21 11 1 +3256 23 11 1 +3257 23 11 0 +3258 23 10 1 +3259 23 10 0 +3260 22 11 1 +3261 22 11 0 +3262 22 10 1 +3263 22 10 0 +3264 28 11 0 +3265 28 11 1 +3266 28 10 0 +3267 28 10 1 +3268 29 11 0 +3269 29 11 1 +3270 29 10 0 +3271 29 10 1 +3272 31 10 1 +3273 31 10 0 +3274 31 11 1 +3275 31 11 0 +3276 30 10 1 +3277 30 10 0 +3278 30 11 1 +3279 30 11 0 +3328 27 9 0 +3329 27 9 1 +3330 27 8 0 +3331 27 8 1 +3332 26 9 0 +3333 26 9 1 +3334 26 8 0 +3335 26 8 1 +3336 24 8 1 +3337 24 8 0 +3338 24 9 1 +3339 24 9 0 +3340 25 8 1 +3341 25 8 0 +3342 25 9 1 +3343 25 9 0 +3360 19 8 0 +3361 19 8 1 +3362 19 9 0 +3363 19 9 1 +3364 18 8 0 +3365 18 8 1 +3366 18 9 0 +3367 18 9 1 +3368 16 9 1 +3369 16 9 0 +3370 16 8 1 +3371 16 8 0 +3372 17 9 1 +3373 17 9 0 +3374 17 8 1 +3375 17 8 0 +3376 20 8 0 +3377 20 8 1 +3378 20 9 0 +3379 20 9 1 +3380 21 8 0 +3381 21 8 1 +3382 21 9 0 +3383 21 9 1 +3384 23 9 1 +3385 23 9 0 +3386 23 8 1 +3387 23 8 0 +3388 22 9 1 +3389 22 9 0 +3390 22 8 1 +3391 22 8 0 +3392 28 9 0 +3393 28 9 1 +3394 28 8 0 +3395 28 8 1 +3396 29 9 0 +3397 29 9 1 +3398 29 8 0 +3399 29 8 1 +3400 31 8 1 +3401 31 8 0 +3402 31 9 1 +3403 31 9 0 +3404 30 8 1 +3405 30 8 0 +3406 30 9 1 +3407 30 9 0 +3456 27 7 0 +3457 27 7 1 +3458 27 6 0 +3459 27 6 1 +3460 26 7 0 +3461 26 7 1 +3462 26 6 0 +3463 26 6 1 +3464 24 6 1 +3465 24 6 0 +3466 24 7 1 +3467 24 7 0 +3468 25 6 1 +3469 25 6 0 +3470 25 7 1 +3471 25 7 0 +3488 19 6 0 +3489 19 6 1 +3490 19 7 0 +3491 19 7 1 +3492 18 6 0 +3493 18 6 1 +3494 18 7 0 +3495 18 7 1 +3496 16 7 1 +3497 16 7 0 +3498 16 6 1 +3499 16 6 0 +3500 17 7 1 +3501 17 7 0 +3502 17 6 1 +3503 17 6 0 +3504 20 6 0 +3505 20 6 1 +3506 20 7 0 +3507 20 7 1 +3508 21 6 0 +3509 21 6 1 +3510 21 7 0 +3511 21 7 1 +3512 23 7 1 +3513 23 7 0 +3514 23 6 1 +3515 23 6 0 +3516 22 7 1 +3517 22 7 0 +3518 22 6 1 +3519 22 6 0 +3520 28 7 0 +3521 28 7 1 +3522 28 6 0 +3523 28 6 1 +3524 29 7 0 +3525 29 7 1 +3526 29 6 0 +3527 29 6 1 +3528 31 6 1 +3529 31 6 0 +3530 31 7 1 +3531 31 7 0 +3532 30 6 1 +3533 30 6 0 +3534 30 7 1 +3535 30 7 0 +3584 27 5 0 +3585 27 5 1 +3586 27 4 0 +3587 27 4 1 +3588 26 5 0 +3589 26 5 1 +3590 26 4 0 +3591 26 4 1 +3592 24 4 1 +3593 24 4 0 +3594 24 5 1 +3595 24 5 0 +3596 25 4 1 +3597 25 4 0 +3598 25 5 1 +3599 25 5 0 +3616 19 4 0 +3617 19 4 1 +3618 19 5 0 +3619 19 5 1 +3620 18 4 0 +3621 18 4 1 +3622 18 5 0 +3623 18 5 1 +3624 16 5 1 +3625 16 5 0 +3626 16 4 1 +3627 16 4 0 +3628 17 5 1 +3629 17 5 0 +3630 17 4 1 +3631 17 4 0 +3632 20 4 0 +3633 20 4 1 +3634 20 5 0 +3635 20 5 1 +3636 21 4 0 +3637 21 4 1 +3638 21 5 0 +3639 21 5 1 +3640 23 5 1 +3641 23 5 0 +3642 23 4 1 +3643 23 4 0 +3644 22 5 1 +3645 22 5 0 +3646 22 4 1 +3647 22 4 0 +3648 28 5 0 +3649 28 5 1 +3650 28 4 0 +3651 28 4 1 +3652 29 5 0 +3653 29 5 1 +3654 29 4 0 +3655 29 4 1 +3656 31 4 1 +3657 31 4 0 +3658 31 5 1 +3659 31 5 0 +3660 30 4 1 +3661 30 4 0 +3662 30 5 1 +3663 30 5 0 +3712 27 3 0 +3713 27 3 1 +3714 27 2 0 +3715 27 2 1 +3716 26 3 0 +3717 26 3 1 +3718 26 2 0 +3719 26 2 1 +3720 24 2 1 +3721 24 2 0 +3722 24 3 1 +3723 24 3 0 +3724 25 2 1 +3725 25 2 0 +3726 25 3 1 +3727 25 3 0 +3744 19 2 0 +3745 19 2 1 +3746 19 3 0 +3747 19 3 1 +3748 18 2 0 +3749 18 2 1 +3750 18 3 0 +3751 18 3 1 +3752 16 3 1 +3753 16 3 0 +3754 16 2 1 +3755 16 2 0 +3756 17 3 1 +3757 17 3 0 +3758 17 2 1 +3759 17 2 0 +3760 20 2 0 +3761 20 2 1 +3762 20 3 0 +3763 20 3 1 +3764 21 2 0 +3765 21 2 1 +3766 21 3 0 +3767 21 3 1 +3768 23 3 1 +3769 23 3 0 +3770 23 2 1 +3771 23 2 0 +3772 22 3 1 +3773 22 3 0 +3774 22 2 1 +3775 22 2 0 +3776 28 3 0 +3777 28 3 1 +3778 28 2 0 +3779 28 2 1 +3780 29 3 0 +3781 29 3 1 +3782 29 2 0 +3783 29 2 1 +3784 31 2 1 +3785 31 2 0 +3786 31 3 1 +3787 31 3 0 +3788 30 2 1 +3789 30 2 0 +3790 30 3 1 +3791 30 3 0 +3840 27 1 0 +3841 27 1 1 +3842 27 0 0 +3843 27 0 1 +3844 26 1 0 +3845 26 1 1 +3846 26 0 0 +3847 26 0 1 +3848 24 0 1 +3849 24 0 0 +3850 24 1 1 +3851 24 1 0 +3852 25 0 1 +3853 25 0 0 +3854 25 1 1 +3855 25 1 0 +3872 19 0 0 +3873 19 0 1 +3874 19 1 0 +3875 19 1 1 +3876 18 0 0 +3877 18 0 1 +3878 18 1 0 +3879 18 1 1 +3880 16 1 1 +3881 16 1 0 +3882 16 0 1 +3883 16 0 0 +3884 17 1 1 +3885 17 1 0 +3886 17 0 1 +3887 17 0 0 +3888 20 0 0 +3889 20 0 1 +3890 20 1 0 +3891 20 1 1 +3892 21 0 0 +3893 21 0 1 +3894 21 1 0 +3895 21 1 1 +3896 23 1 1 +3897 23 1 0 +3898 23 0 1 +3899 23 0 0 +3900 22 1 1 +3901 22 1 0 +3902 22 0 1 +3903 22 0 0 +3904 28 1 0 +3905 28 1 1 +3906 28 0 0 +3907 28 0 1 +3908 29 1 0 +3909 29 1 1 +3910 29 0 0 +3911 29 0 1 +3912 31 0 1 +3913 31 0 0 +3914 31 1 1 +3915 31 1 0 +3916 30 0 1 +3917 30 0 0 +3918 30 1 1 +3919 30 1 0 diff --git a/Detectors/PHOS/base/files/Mod2RCU2.data b/Detectors/PHOS/base/files/Mod2RCU2.data new file mode 100644 index 0000000000000..21de94d7ace53 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod2RCU2.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 2 0 2 + 1 2 1 2 + 2 2 2 2 + 3 2 3 2 + 4 2 4 2 + 5 2 5 2 + 6 2 6 2 + 7 2 7 2 + 8 2 8 2 + 9 2 9 2 + 10 2 10 2 + 11 2 11 2 + 12 2 12 2 + 13 2 13 2 + 14 2 14 2 + 15 2 15 2 + 16 2 16 2 + 17 2 17 2 + 18 2 18 2 + 19 2 19 2 + 20 2 20 2 + 21 2 21 2 + 22 2 22 2 + 23 2 23 2 + 24 2 24 2 + 25 2 25 2 + 26 2 26 2 + 27 2 27 2 + 28 2 28 2 + 29 2 29 2 + 30 2 30 2 + 31 2 31 2 + 32 2 32 2 + 33 2 33 2 + 34 2 34 2 + 35 2 35 2 + 36 2 36 2 + 37 2 37 2 + 38 2 38 2 + 39 2 39 2 + 40 2 40 2 + 41 2 41 2 + 42 2 42 2 + 43 2 43 2 + 44 2 44 2 + 45 2 45 2 + 46 2 46 2 + 47 2 47 2 + 48 2 48 2 + 49 2 49 2 + 50 2 50 2 + 51 2 51 2 + 52 2 52 2 + 53 2 53 2 + 54 2 54 2 + 55 2 55 2 + 56 2 56 2 + 57 2 57 2 + 58 2 58 2 + 59 2 59 2 + 60 2 60 2 + 61 2 61 2 + 62 2 62 2 + 63 2 63 2 + 64 2 64 2 + 65 2 65 2 + 66 2 66 2 + 67 2 67 2 + 68 2 68 2 + 69 2 69 2 + 70 2 70 2 + 71 2 71 2 + 72 2 72 2 + 73 2 73 2 + 74 2 74 2 + 75 2 75 2 + 76 2 76 2 + 77 2 77 2 + 78 2 78 2 + 79 2 79 2 + 80 2 80 2 + 81 2 81 2 + 82 2 82 2 + 83 2 83 2 + 84 2 84 2 + 85 2 85 2 + 86 2 86 2 + 87 2 87 2 + 88 2 88 2 + 89 2 89 2 + 90 2 90 2 + 91 2 91 2 + 92 2 92 2 + 93 2 93 2 + 94 2 94 2 + 95 2 95 2 + 96 2 96 2 + 97 2 97 2 + 98 2 98 2 + 99 2 99 2 + 100 2 100 2 + 101 2 101 2 + 102 2 102 2 + 103 2 103 2 + 104 2 104 2 + 105 2 105 2 + 106 2 106 2 + 107 2 107 2 + 108 2 108 2 + 109 2 109 2 + 110 2 110 2 + 111 2 111 2 + 112 2 112 2 + 113 2 113 2 + 114 2 114 2 + 115 2 115 2 + 116 2 116 2 + 117 2 117 2 + 118 2 118 2 + 119 2 119 2 + 120 2 120 2 + 121 2 121 2 + 122 2 122 2 + 123 2 123 2 + 124 2 124 2 + 125 2 125 2 + 126 2 126 2 + 127 2 127 2 +2048 2 2048 2 +2049 2 2049 2 +2050 2 2050 2 +2051 2 2051 2 +2052 2 2052 2 +2053 2 2053 2 +2054 2 2054 2 +2055 2 2055 2 +2056 2 2056 2 +2057 2 2057 2 +2058 2 2058 2 +2059 2 2059 2 +2060 2 2060 2 +2061 2 2061 2 +2062 2 2062 2 +2063 2 2063 2 +2064 2 2064 2 +2065 2 2065 2 +2066 2 2066 2 +2067 2 2067 2 +2068 2 2068 2 +2069 2 2069 2 +2070 2 2070 2 +2071 2 2071 2 +2072 2 2072 2 +2073 2 2073 2 +2074 2 2074 2 +2075 2 2075 2 +2076 2 2076 2 +2077 2 2077 2 +2078 2 2078 2 +2079 2 2079 2 +2080 2 2080 2 +2081 2 2081 2 +2082 2 2082 2 +2083 2 2083 2 +2084 2 2084 2 +2085 2 2085 2 +2086 2 2086 2 +2087 2 2087 2 +2088 2 2088 2 +2089 2 2089 2 +2090 2 2090 2 +2091 2 2091 2 +2092 2 2092 2 +2093 2 2093 2 +2094 2 2094 2 +2095 2 2095 2 +2096 2 2096 2 +2097 2 2097 2 +2098 2 2098 2 +2099 2 2099 2 +2100 2 2100 2 +2101 2 2101 2 +2102 2 2102 2 +2103 2 2103 2 +2104 2 2104 2 +2105 2 2105 2 +2106 2 2106 2 +2107 2 2107 2 +2108 2 2108 2 +2109 2 2109 2 +2110 2 2110 2 +2111 2 2111 2 +2112 2 2112 2 +2113 2 2113 2 +2114 2 2114 2 +2115 2 2115 2 +2116 2 2116 2 +2117 2 2117 2 +2118 2 2118 2 +2119 2 2119 2 +2120 2 2120 2 +2121 2 2121 2 +2122 2 2122 2 +2123 2 2123 2 +2124 2 2124 2 +2125 2 2125 2 +2126 2 2126 2 +2127 2 2127 2 +2128 2 2128 2 +2129 2 2129 2 +2130 2 2130 2 +2131 2 2131 2 +2132 2 2132 2 +2133 2 2133 2 +2134 2 2134 2 +2135 2 2135 2 +2136 2 2136 2 +2137 2 2137 2 +2138 2 2138 2 +2139 2 2139 2 +2140 2 2140 2 +2141 2 2141 2 +2142 2 2142 2 +2143 2 2143 2 +2144 2 2144 2 +2145 2 2145 2 +2146 2 2146 2 +2147 2 2147 2 +2148 2 2148 2 +2149 2 2149 2 +2150 2 2150 2 +2151 2 2151 2 +2152 2 2152 2 +2153 2 2153 2 +2154 2 2154 2 +2155 2 2155 2 +2156 2 2156 2 +2157 2 2157 2 +2158 2 2158 2 +2159 2 2159 2 +2160 2 2160 2 +2161 2 2161 2 +2162 2 2162 2 +2163 2 2163 2 +2164 2 2164 2 +2165 2 2165 2 +2166 2 2166 2 +2167 2 2167 2 +2168 2 2168 2 +2169 2 2169 2 +2170 2 2170 2 +2171 2 2171 2 +2172 2 2172 2 +2173 2 2173 2 +2174 2 2174 2 +2175 2 2175 2 + 128 43 29 0 + 129 43 29 1 + 130 43 28 0 + 131 43 28 1 + 132 42 29 0 + 133 42 29 1 + 134 42 28 0 + 135 42 28 1 + 136 40 28 1 + 137 40 28 0 + 138 40 29 1 + 139 40 29 0 + 140 41 28 1 + 141 41 28 0 + 142 41 29 1 + 143 41 29 0 + 160 35 28 0 + 161 35 28 1 + 162 35 29 0 + 163 35 29 1 + 164 34 28 0 + 165 34 28 1 + 166 34 29 0 + 167 34 29 1 + 168 32 29 1 + 169 32 29 0 + 170 32 28 1 + 171 32 28 0 + 172 33 29 1 + 173 33 29 0 + 174 33 28 1 + 175 33 28 0 + 176 36 28 0 + 177 36 28 1 + 178 36 29 0 + 179 36 29 1 + 180 37 28 0 + 181 37 28 1 + 182 37 29 0 + 183 37 29 1 + 184 39 29 1 + 185 39 29 0 + 186 39 28 1 + 187 39 28 0 + 188 38 29 1 + 189 38 29 0 + 190 38 28 1 + 191 38 28 0 + 192 44 29 0 + 193 44 29 1 + 194 44 28 0 + 195 44 28 1 + 196 45 29 0 + 197 45 29 1 + 198 45 28 0 + 199 45 28 1 + 200 47 28 1 + 201 47 28 0 + 202 47 29 1 + 203 47 29 0 + 204 46 28 1 + 205 46 28 0 + 206 46 29 1 + 207 46 29 0 + 256 43 31 0 + 257 43 31 1 + 258 43 30 0 + 259 43 30 1 + 260 42 31 0 + 261 42 31 1 + 262 42 30 0 + 263 42 30 1 + 264 40 30 1 + 265 40 30 0 + 266 40 31 1 + 267 40 31 0 + 268 41 30 1 + 269 41 30 0 + 270 41 31 1 + 271 41 31 0 + 288 35 30 0 + 289 35 30 1 + 290 35 31 0 + 291 35 31 1 + 292 34 30 0 + 293 34 30 1 + 294 34 31 0 + 295 34 31 1 + 296 32 31 1 + 297 32 31 0 + 298 32 30 1 + 299 32 30 0 + 300 33 31 1 + 301 33 31 0 + 302 33 30 1 + 303 33 30 0 + 304 36 30 0 + 305 36 30 1 + 306 36 31 0 + 307 36 31 1 + 308 37 30 0 + 309 37 30 1 + 310 37 31 0 + 311 37 31 1 + 312 39 31 1 + 313 39 31 0 + 314 39 30 1 + 315 39 30 0 + 316 38 31 1 + 317 38 31 0 + 318 38 30 1 + 319 38 30 0 + 320 44 31 0 + 321 44 31 1 + 322 44 30 0 + 323 44 30 1 + 324 45 31 0 + 325 45 31 1 + 326 45 30 0 + 327 45 30 1 + 328 47 30 1 + 329 47 30 0 + 330 47 31 1 + 331 47 31 0 + 332 46 30 1 + 333 46 30 0 + 334 46 31 1 + 335 46 31 0 + 384 43 33 0 + 385 43 33 1 + 386 43 32 0 + 387 43 32 1 + 388 42 33 0 + 389 42 33 1 + 390 42 32 0 + 391 42 32 1 + 392 40 32 1 + 393 40 32 0 + 394 40 33 1 + 395 40 33 0 + 396 41 32 1 + 397 41 32 0 + 398 41 33 1 + 399 41 33 0 + 416 35 32 0 + 417 35 32 1 + 418 35 33 0 + 419 35 33 1 + 420 34 32 0 + 421 34 32 1 + 422 34 33 0 + 423 34 33 1 + 424 32 33 1 + 425 32 33 0 + 426 32 32 1 + 427 32 32 0 + 428 33 33 1 + 429 33 33 0 + 430 33 32 1 + 431 33 32 0 + 432 36 32 0 + 433 36 32 1 + 434 36 33 0 + 435 36 33 1 + 436 37 32 0 + 437 37 32 1 + 438 37 33 0 + 439 37 33 1 + 440 39 33 1 + 441 39 33 0 + 442 39 32 1 + 443 39 32 0 + 444 38 33 1 + 445 38 33 0 + 446 38 32 1 + 447 38 32 0 + 448 44 33 0 + 449 44 33 1 + 450 44 32 0 + 451 44 32 1 + 452 45 33 0 + 453 45 33 1 + 454 45 32 0 + 455 45 32 1 + 456 47 32 1 + 457 47 32 0 + 458 47 33 1 + 459 47 33 0 + 460 46 32 1 + 461 46 32 0 + 462 46 33 1 + 463 46 33 0 + 512 43 35 0 + 513 43 35 1 + 514 43 34 0 + 515 43 34 1 + 516 42 35 0 + 517 42 35 1 + 518 42 34 0 + 519 42 34 1 + 520 40 34 1 + 521 40 34 0 + 522 40 35 1 + 523 40 35 0 + 524 41 34 1 + 525 41 34 0 + 526 41 35 1 + 527 41 35 0 + 544 35 34 0 + 545 35 34 1 + 546 35 35 0 + 547 35 35 1 + 548 34 34 0 + 549 34 34 1 + 550 34 35 0 + 551 34 35 1 + 552 32 35 1 + 553 32 35 0 + 554 32 34 1 + 555 32 34 0 + 556 33 35 1 + 557 33 35 0 + 558 33 34 1 + 559 33 34 0 + 560 36 34 0 + 561 36 34 1 + 562 36 35 0 + 563 36 35 1 + 564 37 34 0 + 565 37 34 1 + 566 37 35 0 + 567 37 35 1 + 568 39 35 1 + 569 39 35 0 + 570 39 34 1 + 571 39 34 0 + 572 38 35 1 + 573 38 35 0 + 574 38 34 1 + 575 38 34 0 + 576 44 35 0 + 577 44 35 1 + 578 44 34 0 + 579 44 34 1 + 580 45 35 0 + 581 45 35 1 + 582 45 34 0 + 583 45 34 1 + 584 47 34 1 + 585 47 34 0 + 586 47 35 1 + 587 47 35 0 + 588 46 34 1 + 589 46 34 0 + 590 46 35 1 + 591 46 35 0 + 640 43 37 0 + 641 43 37 1 + 642 43 36 0 + 643 43 36 1 + 644 42 37 0 + 645 42 37 1 + 646 42 36 0 + 647 42 36 1 + 648 40 36 1 + 649 40 36 0 + 650 40 37 1 + 651 40 37 0 + 652 41 36 1 + 653 41 36 0 + 654 41 37 1 + 655 41 37 0 + 672 35 36 0 + 673 35 36 1 + 674 35 37 0 + 675 35 37 1 + 676 34 36 0 + 677 34 36 1 + 678 34 37 0 + 679 34 37 1 + 680 32 37 1 + 681 32 37 0 + 682 32 36 1 + 683 32 36 0 + 684 33 37 1 + 685 33 37 0 + 686 33 36 1 + 687 33 36 0 + 688 36 36 0 + 689 36 36 1 + 690 36 37 0 + 691 36 37 1 + 692 37 36 0 + 693 37 36 1 + 694 37 37 0 + 695 37 37 1 + 696 39 37 1 + 697 39 37 0 + 698 39 36 1 + 699 39 36 0 + 700 38 37 1 + 701 38 37 0 + 702 38 36 1 + 703 38 36 0 + 704 44 37 0 + 705 44 37 1 + 706 44 36 0 + 707 44 36 1 + 708 45 37 0 + 709 45 37 1 + 710 45 36 0 + 711 45 36 1 + 712 47 36 1 + 713 47 36 0 + 714 47 37 1 + 715 47 37 0 + 716 46 36 1 + 717 46 36 0 + 718 46 37 1 + 719 46 37 0 + 768 43 39 0 + 769 43 39 1 + 770 43 38 0 + 771 43 38 1 + 772 42 39 0 + 773 42 39 1 + 774 42 38 0 + 775 42 38 1 + 776 40 38 1 + 777 40 38 0 + 778 40 39 1 + 779 40 39 0 + 780 41 38 1 + 781 41 38 0 + 782 41 39 1 + 783 41 39 0 + 800 35 38 0 + 801 35 38 1 + 802 35 39 0 + 803 35 39 1 + 804 34 38 0 + 805 34 38 1 + 806 34 39 0 + 807 34 39 1 + 808 32 39 1 + 809 32 39 0 + 810 32 38 1 + 811 32 38 0 + 812 33 39 1 + 813 33 39 0 + 814 33 38 1 + 815 33 38 0 + 816 36 38 0 + 817 36 38 1 + 818 36 39 0 + 819 36 39 1 + 820 37 38 0 + 821 37 38 1 + 822 37 39 0 + 823 37 39 1 + 824 39 39 1 + 825 39 39 0 + 826 39 38 1 + 827 39 38 0 + 828 38 39 1 + 829 38 39 0 + 830 38 38 1 + 831 38 38 0 + 832 44 39 0 + 833 44 39 1 + 834 44 38 0 + 835 44 38 1 + 836 45 39 0 + 837 45 39 1 + 838 45 38 0 + 839 45 38 1 + 840 47 38 1 + 841 47 38 0 + 842 47 39 1 + 843 47 39 0 + 844 46 38 1 + 845 46 38 0 + 846 46 39 1 + 847 46 39 0 + 896 43 41 0 + 897 43 41 1 + 898 43 40 0 + 899 43 40 1 + 900 42 41 0 + 901 42 41 1 + 902 42 40 0 + 903 42 40 1 + 904 40 40 1 + 905 40 40 0 + 906 40 41 1 + 907 40 41 0 + 908 41 40 1 + 909 41 40 0 + 910 41 41 1 + 911 41 41 0 + 928 35 40 0 + 929 35 40 1 + 930 35 41 0 + 931 35 41 1 + 932 34 40 0 + 933 34 40 1 + 934 34 41 0 + 935 34 41 1 + 936 32 41 1 + 937 32 41 0 + 938 32 40 1 + 939 32 40 0 + 940 33 41 1 + 941 33 41 0 + 942 33 40 1 + 943 33 40 0 + 944 36 40 0 + 945 36 40 1 + 946 36 41 0 + 947 36 41 1 + 948 37 40 0 + 949 37 40 1 + 950 37 41 0 + 951 37 41 1 + 952 39 41 1 + 953 39 41 0 + 954 39 40 1 + 955 39 40 0 + 956 38 41 1 + 957 38 41 0 + 958 38 40 1 + 959 38 40 0 + 960 44 41 0 + 961 44 41 1 + 962 44 40 0 + 963 44 40 1 + 964 45 41 0 + 965 45 41 1 + 966 45 40 0 + 967 45 40 1 + 968 47 40 1 + 969 47 40 0 + 970 47 41 1 + 971 47 41 0 + 972 46 40 1 + 973 46 40 0 + 974 46 41 1 + 975 46 41 0 +1024 43 43 0 +1025 43 43 1 +1026 43 42 0 +1027 43 42 1 +1028 42 43 0 +1029 42 43 1 +1030 42 42 0 +1031 42 42 1 +1032 40 42 1 +1033 40 42 0 +1034 40 43 1 +1035 40 43 0 +1036 41 42 1 +1037 41 42 0 +1038 41 43 1 +1039 41 43 0 +1056 35 42 0 +1057 35 42 1 +1058 35 43 0 +1059 35 43 1 +1060 34 42 0 +1061 34 42 1 +1062 34 43 0 +1063 34 43 1 +1064 32 43 1 +1065 32 43 0 +1066 32 42 1 +1067 32 42 0 +1068 33 43 1 +1069 33 43 0 +1070 33 42 1 +1071 33 42 0 +1072 36 42 0 +1073 36 42 1 +1074 36 43 0 +1075 36 43 1 +1076 37 42 0 +1077 37 42 1 +1078 37 43 0 +1079 37 43 1 +1080 39 43 1 +1081 39 43 0 +1082 39 42 1 +1083 39 42 0 +1084 38 43 1 +1085 38 43 0 +1086 38 42 1 +1087 38 42 0 +1088 44 43 0 +1089 44 43 1 +1090 44 42 0 +1091 44 42 1 +1092 45 43 0 +1093 45 43 1 +1094 45 42 0 +1095 45 42 1 +1096 47 42 1 +1097 47 42 0 +1098 47 43 1 +1099 47 43 0 +1100 46 42 1 +1101 46 42 0 +1102 46 43 1 +1103 46 43 0 +1152 43 45 0 +1153 43 45 1 +1154 43 44 0 +1155 43 44 1 +1156 42 45 0 +1157 42 45 1 +1158 42 44 0 +1159 42 44 1 +1160 40 44 1 +1161 40 44 0 +1162 40 45 1 +1163 40 45 0 +1164 41 44 1 +1165 41 44 0 +1166 41 45 1 +1167 41 45 0 +1184 35 44 0 +1185 35 44 1 +1186 35 45 0 +1187 35 45 1 +1188 34 44 0 +1189 34 44 1 +1190 34 45 0 +1191 34 45 1 +1192 32 45 1 +1193 32 45 0 +1194 32 44 1 +1195 32 44 0 +1196 33 45 1 +1197 33 45 0 +1198 33 44 1 +1199 33 44 0 +1200 36 44 0 +1201 36 44 1 +1202 36 45 0 +1203 36 45 1 +1204 37 44 0 +1205 37 44 1 +1206 37 45 0 +1207 37 45 1 +1208 39 45 1 +1209 39 45 0 +1210 39 44 1 +1211 39 44 0 +1212 38 45 1 +1213 38 45 0 +1214 38 44 1 +1215 38 44 0 +1216 44 45 0 +1217 44 45 1 +1218 44 44 0 +1219 44 44 1 +1220 45 45 0 +1221 45 45 1 +1222 45 44 0 +1223 45 44 1 +1224 47 44 1 +1225 47 44 0 +1226 47 45 1 +1227 47 45 0 +1228 46 44 1 +1229 46 44 0 +1230 46 45 1 +1231 46 45 0 +1280 43 47 0 +1281 43 47 1 +1282 43 46 0 +1283 43 46 1 +1284 42 47 0 +1285 42 47 1 +1286 42 46 0 +1287 42 46 1 +1288 40 46 1 +1289 40 46 0 +1290 40 47 1 +1291 40 47 0 +1292 41 46 1 +1293 41 46 0 +1294 41 47 1 +1295 41 47 0 +1312 35 46 0 +1313 35 46 1 +1314 35 47 0 +1315 35 47 1 +1316 34 46 0 +1317 34 46 1 +1318 34 47 0 +1319 34 47 1 +1320 32 47 1 +1321 32 47 0 +1322 32 46 1 +1323 32 46 0 +1324 33 47 1 +1325 33 47 0 +1326 33 46 1 +1327 33 46 0 +1328 36 46 0 +1329 36 46 1 +1330 36 47 0 +1331 36 47 1 +1332 37 46 0 +1333 37 46 1 +1334 37 47 0 +1335 37 47 1 +1336 39 47 1 +1337 39 47 0 +1338 39 46 1 +1339 39 46 0 +1340 38 47 1 +1341 38 47 0 +1342 38 46 1 +1343 38 46 0 +1344 44 47 0 +1345 44 47 1 +1346 44 46 0 +1347 44 46 1 +1348 45 47 0 +1349 45 47 1 +1350 45 46 0 +1351 45 46 1 +1352 47 46 1 +1353 47 46 0 +1354 47 47 1 +1355 47 47 0 +1356 46 46 1 +1357 46 46 0 +1358 46 47 1 +1359 46 47 0 +1408 43 49 0 +1409 43 49 1 +1410 43 48 0 +1411 43 48 1 +1412 42 49 0 +1413 42 49 1 +1414 42 48 0 +1415 42 48 1 +1416 40 48 1 +1417 40 48 0 +1418 40 49 1 +1419 40 49 0 +1420 41 48 1 +1421 41 48 0 +1422 41 49 1 +1423 41 49 0 +1440 35 48 0 +1441 35 48 1 +1442 35 49 0 +1443 35 49 1 +1444 34 48 0 +1445 34 48 1 +1446 34 49 0 +1447 34 49 1 +1448 32 49 1 +1449 32 49 0 +1450 32 48 1 +1451 32 48 0 +1452 33 49 1 +1453 33 49 0 +1454 33 48 1 +1455 33 48 0 +1456 36 48 0 +1457 36 48 1 +1458 36 49 0 +1459 36 49 1 +1460 37 48 0 +1461 37 48 1 +1462 37 49 0 +1463 37 49 1 +1464 39 49 1 +1465 39 49 0 +1466 39 48 1 +1467 39 48 0 +1468 38 49 1 +1469 38 49 0 +1470 38 48 1 +1471 38 48 0 +1472 44 49 0 +1473 44 49 1 +1474 44 48 0 +1475 44 48 1 +1476 45 49 0 +1477 45 49 1 +1478 45 48 0 +1479 45 48 1 +1480 47 48 1 +1481 47 48 0 +1482 47 49 1 +1483 47 49 0 +1484 46 48 1 +1485 46 48 0 +1486 46 49 1 +1487 46 49 0 +1536 43 51 0 +1537 43 51 1 +1538 43 50 0 +1539 43 50 1 +1540 42 51 0 +1541 42 51 1 +1542 42 50 0 +1543 42 50 1 +1544 40 50 1 +1545 40 50 0 +1546 40 51 1 +1547 40 51 0 +1548 41 50 1 +1549 41 50 0 +1550 41 51 1 +1551 41 51 0 +1568 35 50 0 +1569 35 50 1 +1570 35 51 0 +1571 35 51 1 +1572 34 50 0 +1573 34 50 1 +1574 34 51 0 +1575 34 51 1 +1576 32 51 1 +1577 32 51 0 +1578 32 50 1 +1579 32 50 0 +1580 33 51 1 +1581 33 51 0 +1582 33 50 1 +1583 33 50 0 +1584 36 50 0 +1585 36 50 1 +1586 36 51 0 +1587 36 51 1 +1588 37 50 0 +1589 37 50 1 +1590 37 51 0 +1591 37 51 1 +1592 39 51 1 +1593 39 51 0 +1594 39 50 1 +1595 39 50 0 +1596 38 51 1 +1597 38 51 0 +1598 38 50 1 +1599 38 50 0 +1600 44 51 0 +1601 44 51 1 +1602 44 50 0 +1603 44 50 1 +1604 45 51 0 +1605 45 51 1 +1606 45 50 0 +1607 45 50 1 +1608 47 50 1 +1609 47 50 0 +1610 47 51 1 +1611 47 51 0 +1612 46 50 1 +1613 46 50 0 +1614 46 51 1 +1615 46 51 0 +1664 43 53 0 +1665 43 53 1 +1666 43 52 0 +1667 43 52 1 +1668 42 53 0 +1669 42 53 1 +1670 42 52 0 +1671 42 52 1 +1672 40 52 1 +1673 40 52 0 +1674 40 53 1 +1675 40 53 0 +1676 41 52 1 +1677 41 52 0 +1678 41 53 1 +1679 41 53 0 +1696 35 52 0 +1697 35 52 1 +1698 35 53 0 +1699 35 53 1 +1700 34 52 0 +1701 34 52 1 +1702 34 53 0 +1703 34 53 1 +1704 32 53 1 +1705 32 53 0 +1706 32 52 1 +1707 32 52 0 +1708 33 53 1 +1709 33 53 0 +1710 33 52 1 +1711 33 52 0 +1712 36 52 0 +1713 36 52 1 +1714 36 53 0 +1715 36 53 1 +1716 37 52 0 +1717 37 52 1 +1718 37 53 0 +1719 37 53 1 +1720 39 53 1 +1721 39 53 0 +1722 39 52 1 +1723 39 52 0 +1724 38 53 1 +1725 38 53 0 +1726 38 52 1 +1727 38 52 0 +1728 44 53 0 +1729 44 53 1 +1730 44 52 0 +1731 44 52 1 +1732 45 53 0 +1733 45 53 1 +1734 45 52 0 +1735 45 52 1 +1736 47 52 1 +1737 47 52 0 +1738 47 53 1 +1739 47 53 0 +1740 46 52 1 +1741 46 52 0 +1742 46 53 1 +1743 46 53 0 +1792 43 55 0 +1793 43 55 1 +1794 43 54 0 +1795 43 54 1 +1796 42 55 0 +1797 42 55 1 +1798 42 54 0 +1799 42 54 1 +1800 40 54 1 +1801 40 54 0 +1802 40 55 1 +1803 40 55 0 +1804 41 54 1 +1805 41 54 0 +1806 41 55 1 +1807 41 55 0 +1824 35 54 0 +1825 35 54 1 +1826 35 55 0 +1827 35 55 1 +1828 34 54 0 +1829 34 54 1 +1830 34 55 0 +1831 34 55 1 +1832 32 55 1 +1833 32 55 0 +1834 32 54 1 +1835 32 54 0 +1836 33 55 1 +1837 33 55 0 +1838 33 54 1 +1839 33 54 0 +1840 36 54 0 +1841 36 54 1 +1842 36 55 0 +1843 36 55 1 +1844 37 54 0 +1845 37 54 1 +1846 37 55 0 +1847 37 55 1 +1848 39 55 1 +1849 39 55 0 +1850 39 54 1 +1851 39 54 0 +1852 38 55 1 +1853 38 55 0 +1854 38 54 1 +1855 38 54 0 +1856 44 55 0 +1857 44 55 1 +1858 44 54 0 +1859 44 54 1 +1860 45 55 0 +1861 45 55 1 +1862 45 54 0 +1863 45 54 1 +1864 47 54 1 +1865 47 54 0 +1866 47 55 1 +1867 47 55 0 +1868 46 54 1 +1869 46 54 0 +1870 46 55 1 +1871 46 55 0 +2176 43 27 0 +2177 43 27 1 +2178 43 26 0 +2179 43 26 1 +2180 42 27 0 +2181 42 27 1 +2182 42 26 0 +2183 42 26 1 +2184 40 26 1 +2185 40 26 0 +2186 40 27 1 +2187 40 27 0 +2188 41 26 1 +2189 41 26 0 +2190 41 27 1 +2191 41 27 0 +2208 35 26 0 +2209 35 26 1 +2210 35 27 0 +2211 35 27 1 +2212 34 26 0 +2213 34 26 1 +2214 34 27 0 +2215 34 27 1 +2216 32 27 1 +2217 32 27 0 +2218 32 26 1 +2219 32 26 0 +2220 33 27 1 +2221 33 27 0 +2222 33 26 1 +2223 33 26 0 +2224 36 26 0 +2225 36 26 1 +2226 36 27 0 +2227 36 27 1 +2228 37 26 0 +2229 37 26 1 +2230 37 27 0 +2231 37 27 1 +2232 39 27 1 +2233 39 27 0 +2234 39 26 1 +2235 39 26 0 +2236 38 27 1 +2237 38 27 0 +2238 38 26 1 +2239 38 26 0 +2240 44 27 0 +2241 44 27 1 +2242 44 26 0 +2243 44 26 1 +2244 45 27 0 +2245 45 27 1 +2246 45 26 0 +2247 45 26 1 +2248 47 26 1 +2249 47 26 0 +2250 47 27 1 +2251 47 27 0 +2252 46 26 1 +2253 46 26 0 +2254 46 27 1 +2255 46 27 0 +2304 43 25 0 +2305 43 25 1 +2306 43 24 0 +2307 43 24 1 +2308 42 25 0 +2309 42 25 1 +2310 42 24 0 +2311 42 24 1 +2312 40 24 1 +2313 40 24 0 +2314 40 25 1 +2315 40 25 0 +2316 41 24 1 +2317 41 24 0 +2318 41 25 1 +2319 41 25 0 +2336 35 24 0 +2337 35 24 1 +2338 35 25 0 +2339 35 25 1 +2340 34 24 0 +2341 34 24 1 +2342 34 25 0 +2343 34 25 1 +2344 32 25 1 +2345 32 25 0 +2346 32 24 1 +2347 32 24 0 +2348 33 25 1 +2349 33 25 0 +2350 33 24 1 +2351 33 24 0 +2352 36 24 0 +2353 36 24 1 +2354 36 25 0 +2355 36 25 1 +2356 37 24 0 +2357 37 24 1 +2358 37 25 0 +2359 37 25 1 +2360 39 25 1 +2361 39 25 0 +2362 39 24 1 +2363 39 24 0 +2364 38 25 1 +2365 38 25 0 +2366 38 24 1 +2367 38 24 0 +2368 44 25 0 +2369 44 25 1 +2370 44 24 0 +2371 44 24 1 +2372 45 25 0 +2373 45 25 1 +2374 45 24 0 +2375 45 24 1 +2376 47 24 1 +2377 47 24 0 +2378 47 25 1 +2379 47 25 0 +2380 46 24 1 +2381 46 24 0 +2382 46 25 1 +2383 46 25 0 +2432 43 23 0 +2433 43 23 1 +2434 43 22 0 +2435 43 22 1 +2436 42 23 0 +2437 42 23 1 +2438 42 22 0 +2439 42 22 1 +2440 40 22 1 +2441 40 22 0 +2442 40 23 1 +2443 40 23 0 +2444 41 22 1 +2445 41 22 0 +2446 41 23 1 +2447 41 23 0 +2464 35 22 0 +2465 35 22 1 +2466 35 23 0 +2467 35 23 1 +2468 34 22 0 +2469 34 22 1 +2470 34 23 0 +2471 34 23 1 +2472 32 23 1 +2473 32 23 0 +2474 32 22 1 +2475 32 22 0 +2476 33 23 1 +2477 33 23 0 +2478 33 22 1 +2479 33 22 0 +2480 36 22 0 +2481 36 22 1 +2482 36 23 0 +2483 36 23 1 +2484 37 22 0 +2485 37 22 1 +2486 37 23 0 +2487 37 23 1 +2488 39 23 1 +2489 39 23 0 +2490 39 22 1 +2491 39 22 0 +2492 38 23 1 +2493 38 23 0 +2494 38 22 1 +2495 38 22 0 +2496 44 23 0 +2497 44 23 1 +2498 44 22 0 +2499 44 22 1 +2500 45 23 0 +2501 45 23 1 +2502 45 22 0 +2503 45 22 1 +2504 47 22 1 +2505 47 22 0 +2506 47 23 1 +2507 47 23 0 +2508 46 22 1 +2509 46 22 0 +2510 46 23 1 +2511 46 23 0 +2560 43 21 0 +2561 43 21 1 +2562 43 20 0 +2563 43 20 1 +2564 42 21 0 +2565 42 21 1 +2566 42 20 0 +2567 42 20 1 +2568 40 20 1 +2569 40 20 0 +2570 40 21 1 +2571 40 21 0 +2572 41 20 1 +2573 41 20 0 +2574 41 21 1 +2575 41 21 0 +2592 35 20 0 +2593 35 20 1 +2594 35 21 0 +2595 35 21 1 +2596 34 20 0 +2597 34 20 1 +2598 34 21 0 +2599 34 21 1 +2600 32 21 1 +2601 32 21 0 +2602 32 20 1 +2603 32 20 0 +2604 33 21 1 +2605 33 21 0 +2606 33 20 1 +2607 33 20 0 +2608 36 20 0 +2609 36 20 1 +2610 36 21 0 +2611 36 21 1 +2612 37 20 0 +2613 37 20 1 +2614 37 21 0 +2615 37 21 1 +2616 39 21 1 +2617 39 21 0 +2618 39 20 1 +2619 39 20 0 +2620 38 21 1 +2621 38 21 0 +2622 38 20 1 +2623 38 20 0 +2624 44 21 0 +2625 44 21 1 +2626 44 20 0 +2627 44 20 1 +2628 45 21 0 +2629 45 21 1 +2630 45 20 0 +2631 45 20 1 +2632 47 20 1 +2633 47 20 0 +2634 47 21 1 +2635 47 21 0 +2636 46 20 1 +2637 46 20 0 +2638 46 21 1 +2639 46 21 0 +2688 43 19 0 +2689 43 19 1 +2690 43 18 0 +2691 43 18 1 +2692 42 19 0 +2693 42 19 1 +2694 42 18 0 +2695 42 18 1 +2696 40 18 1 +2697 40 18 0 +2698 40 19 1 +2699 40 19 0 +2700 41 18 1 +2701 41 18 0 +2702 41 19 1 +2703 41 19 0 +2720 35 18 0 +2721 35 18 1 +2722 35 19 0 +2723 35 19 1 +2724 34 18 0 +2725 34 18 1 +2726 34 19 0 +2727 34 19 1 +2728 32 19 1 +2729 32 19 0 +2730 32 18 1 +2731 32 18 0 +2732 33 19 1 +2733 33 19 0 +2734 33 18 1 +2735 33 18 0 +2736 36 18 0 +2737 36 18 1 +2738 36 19 0 +2739 36 19 1 +2740 37 18 0 +2741 37 18 1 +2742 37 19 0 +2743 37 19 1 +2744 39 19 1 +2745 39 19 0 +2746 39 18 1 +2747 39 18 0 +2748 38 19 1 +2749 38 19 0 +2750 38 18 1 +2751 38 18 0 +2752 44 19 0 +2753 44 19 1 +2754 44 18 0 +2755 44 18 1 +2756 45 19 0 +2757 45 19 1 +2758 45 18 0 +2759 45 18 1 +2760 47 18 1 +2761 47 18 0 +2762 47 19 1 +2763 47 19 0 +2764 46 18 1 +2765 46 18 0 +2766 46 19 1 +2767 46 19 0 +2816 43 17 0 +2817 43 17 1 +2818 43 16 0 +2819 43 16 1 +2820 42 17 0 +2821 42 17 1 +2822 42 16 0 +2823 42 16 1 +2824 40 16 1 +2825 40 16 0 +2826 40 17 1 +2827 40 17 0 +2828 41 16 1 +2829 41 16 0 +2830 41 17 1 +2831 41 17 0 +2848 35 16 0 +2849 35 16 1 +2850 35 17 0 +2851 35 17 1 +2852 34 16 0 +2853 34 16 1 +2854 34 17 0 +2855 34 17 1 +2856 32 17 1 +2857 32 17 0 +2858 32 16 1 +2859 32 16 0 +2860 33 17 1 +2861 33 17 0 +2862 33 16 1 +2863 33 16 0 +2864 36 16 0 +2865 36 16 1 +2866 36 17 0 +2867 36 17 1 +2868 37 16 0 +2869 37 16 1 +2870 37 17 0 +2871 37 17 1 +2872 39 17 1 +2873 39 17 0 +2874 39 16 1 +2875 39 16 0 +2876 38 17 1 +2877 38 17 0 +2878 38 16 1 +2879 38 16 0 +2880 44 17 0 +2881 44 17 1 +2882 44 16 0 +2883 44 16 1 +2884 45 17 0 +2885 45 17 1 +2886 45 16 0 +2887 45 16 1 +2888 47 16 1 +2889 47 16 0 +2890 47 17 1 +2891 47 17 0 +2892 46 16 1 +2893 46 16 0 +2894 46 17 1 +2895 46 17 0 +2944 43 15 0 +2945 43 15 1 +2946 43 14 0 +2947 43 14 1 +2948 42 15 0 +2949 42 15 1 +2950 42 14 0 +2951 42 14 1 +2952 40 14 1 +2953 40 14 0 +2954 40 15 1 +2955 40 15 0 +2956 41 14 1 +2957 41 14 0 +2958 41 15 1 +2959 41 15 0 +2976 35 14 0 +2977 35 14 1 +2978 35 15 0 +2979 35 15 1 +2980 34 14 0 +2981 34 14 1 +2982 34 15 0 +2983 34 15 1 +2984 32 15 1 +2985 32 15 0 +2986 32 14 1 +2987 32 14 0 +2988 33 15 1 +2989 33 15 0 +2990 33 14 1 +2991 33 14 0 +2992 36 14 0 +2993 36 14 1 +2994 36 15 0 +2995 36 15 1 +2996 37 14 0 +2997 37 14 1 +2998 37 15 0 +2999 37 15 1 +3000 39 15 1 +3001 39 15 0 +3002 39 14 1 +3003 39 14 0 +3004 38 15 1 +3005 38 15 0 +3006 38 14 1 +3007 38 14 0 +3008 44 15 0 +3009 44 15 1 +3010 44 14 0 +3011 44 14 1 +3012 45 15 0 +3013 45 15 1 +3014 45 14 0 +3015 45 14 1 +3016 47 14 1 +3017 47 14 0 +3018 47 15 1 +3019 47 15 0 +3020 46 14 1 +3021 46 14 0 +3022 46 15 1 +3023 46 15 0 +3072 43 13 0 +3073 43 13 1 +3074 43 12 0 +3075 43 12 1 +3076 42 13 0 +3077 42 13 1 +3078 42 12 0 +3079 42 12 1 +3080 40 12 1 +3081 40 12 0 +3082 40 13 1 +3083 40 13 0 +3084 41 12 1 +3085 41 12 0 +3086 41 13 1 +3087 41 13 0 +3104 35 12 0 +3105 35 12 1 +3106 35 13 0 +3107 35 13 1 +3108 34 12 0 +3109 34 12 1 +3110 34 13 0 +3111 34 13 1 +3112 32 13 1 +3113 32 13 0 +3114 32 12 1 +3115 32 12 0 +3116 33 13 1 +3117 33 13 0 +3118 33 12 1 +3119 33 12 0 +3120 36 12 0 +3121 36 12 1 +3122 36 13 0 +3123 36 13 1 +3124 37 12 0 +3125 37 12 1 +3126 37 13 0 +3127 37 13 1 +3128 39 13 1 +3129 39 13 0 +3130 39 12 1 +3131 39 12 0 +3132 38 13 1 +3133 38 13 0 +3134 38 12 1 +3135 38 12 0 +3136 44 13 0 +3137 44 13 1 +3138 44 12 0 +3139 44 12 1 +3140 45 13 0 +3141 45 13 1 +3142 45 12 0 +3143 45 12 1 +3144 47 12 1 +3145 47 12 0 +3146 47 13 1 +3147 47 13 0 +3148 46 12 1 +3149 46 12 0 +3150 46 13 1 +3151 46 13 0 +3200 43 11 0 +3201 43 11 1 +3202 43 10 0 +3203 43 10 1 +3204 42 11 0 +3205 42 11 1 +3206 42 10 0 +3207 42 10 1 +3208 40 10 1 +3209 40 10 0 +3210 40 11 1 +3211 40 11 0 +3212 41 10 1 +3213 41 10 0 +3214 41 11 1 +3215 41 11 0 +3232 35 10 0 +3233 35 10 1 +3234 35 11 0 +3235 35 11 1 +3236 34 10 0 +3237 34 10 1 +3238 34 11 0 +3239 34 11 1 +3240 32 11 1 +3241 32 11 0 +3242 32 10 1 +3243 32 10 0 +3244 33 11 1 +3245 33 11 0 +3246 33 10 1 +3247 33 10 0 +3248 36 10 0 +3249 36 10 1 +3250 36 11 0 +3251 36 11 1 +3252 37 10 0 +3253 37 10 1 +3254 37 11 0 +3255 37 11 1 +3256 39 11 1 +3257 39 11 0 +3258 39 10 1 +3259 39 10 0 +3260 38 11 1 +3261 38 11 0 +3262 38 10 1 +3263 38 10 0 +3264 44 11 0 +3265 44 11 1 +3266 44 10 0 +3267 44 10 1 +3268 45 11 0 +3269 45 11 1 +3270 45 10 0 +3271 45 10 1 +3272 47 10 1 +3273 47 10 0 +3274 47 11 1 +3275 47 11 0 +3276 46 10 1 +3277 46 10 0 +3278 46 11 1 +3279 46 11 0 +3328 43 9 0 +3329 43 9 1 +3330 43 8 0 +3331 43 8 1 +3332 42 9 0 +3333 42 9 1 +3334 42 8 0 +3335 42 8 1 +3336 40 8 1 +3337 40 8 0 +3338 40 9 1 +3339 40 9 0 +3340 41 8 1 +3341 41 8 0 +3342 41 9 1 +3343 41 9 0 +3360 35 8 0 +3361 35 8 1 +3362 35 9 0 +3363 35 9 1 +3364 34 8 0 +3365 34 8 1 +3366 34 9 0 +3367 34 9 1 +3368 32 9 1 +3369 32 9 0 +3370 32 8 1 +3371 32 8 0 +3372 33 9 1 +3373 33 9 0 +3374 33 8 1 +3375 33 8 0 +3376 36 8 0 +3377 36 8 1 +3378 36 9 0 +3379 36 9 1 +3380 37 8 0 +3381 37 8 1 +3382 37 9 0 +3383 37 9 1 +3384 39 9 1 +3385 39 9 0 +3386 39 8 1 +3387 39 8 0 +3388 38 9 1 +3389 38 9 0 +3390 38 8 1 +3391 38 8 0 +3392 44 9 0 +3393 44 9 1 +3394 44 8 0 +3395 44 8 1 +3396 45 9 0 +3397 45 9 1 +3398 45 8 0 +3399 45 8 1 +3400 47 8 1 +3401 47 8 0 +3402 47 9 1 +3403 47 9 0 +3404 46 8 1 +3405 46 8 0 +3406 46 9 1 +3407 46 9 0 +3456 43 7 0 +3457 43 7 1 +3458 43 6 0 +3459 43 6 1 +3460 42 7 0 +3461 42 7 1 +3462 42 6 0 +3463 42 6 1 +3464 40 6 1 +3465 40 6 0 +3466 40 7 1 +3467 40 7 0 +3468 41 6 1 +3469 41 6 0 +3470 41 7 1 +3471 41 7 0 +3488 35 6 0 +3489 35 6 1 +3490 35 7 0 +3491 35 7 1 +3492 34 6 0 +3493 34 6 1 +3494 34 7 0 +3495 34 7 1 +3496 32 7 1 +3497 32 7 0 +3498 32 6 1 +3499 32 6 0 +3500 33 7 1 +3501 33 7 0 +3502 33 6 1 +3503 33 6 0 +3504 36 6 0 +3505 36 6 1 +3506 36 7 0 +3507 36 7 1 +3508 37 6 0 +3509 37 6 1 +3510 37 7 0 +3511 37 7 1 +3512 39 7 1 +3513 39 7 0 +3514 39 6 1 +3515 39 6 0 +3516 38 7 1 +3517 38 7 0 +3518 38 6 1 +3519 38 6 0 +3520 44 7 0 +3521 44 7 1 +3522 44 6 0 +3523 44 6 1 +3524 45 7 0 +3525 45 7 1 +3526 45 6 0 +3527 45 6 1 +3528 47 6 1 +3529 47 6 0 +3530 47 7 1 +3531 47 7 0 +3532 46 6 1 +3533 46 6 0 +3534 46 7 1 +3535 46 7 0 +3584 43 5 0 +3585 43 5 1 +3586 43 4 0 +3587 43 4 1 +3588 42 5 0 +3589 42 5 1 +3590 42 4 0 +3591 42 4 1 +3592 40 4 1 +3593 40 4 0 +3594 40 5 1 +3595 40 5 0 +3596 41 4 1 +3597 41 4 0 +3598 41 5 1 +3599 41 5 0 +3616 35 4 0 +3617 35 4 1 +3618 35 5 0 +3619 35 5 1 +3620 34 4 0 +3621 34 4 1 +3622 34 5 0 +3623 34 5 1 +3624 32 5 1 +3625 32 5 0 +3626 32 4 1 +3627 32 4 0 +3628 33 5 1 +3629 33 5 0 +3630 33 4 1 +3631 33 4 0 +3632 36 4 0 +3633 36 4 1 +3634 36 5 0 +3635 36 5 1 +3636 37 4 0 +3637 37 4 1 +3638 37 5 0 +3639 37 5 1 +3640 39 5 1 +3641 39 5 0 +3642 39 4 1 +3643 39 4 0 +3644 38 5 1 +3645 38 5 0 +3646 38 4 1 +3647 38 4 0 +3648 44 5 0 +3649 44 5 1 +3650 44 4 0 +3651 44 4 1 +3652 45 5 0 +3653 45 5 1 +3654 45 4 0 +3655 45 4 1 +3656 47 4 1 +3657 47 4 0 +3658 47 5 1 +3659 47 5 0 +3660 46 4 1 +3661 46 4 0 +3662 46 5 1 +3663 46 5 0 +3712 43 3 0 +3713 43 3 1 +3714 43 2 0 +3715 43 2 1 +3716 42 3 0 +3717 42 3 1 +3718 42 2 0 +3719 42 2 1 +3720 40 2 1 +3721 40 2 0 +3722 40 3 1 +3723 40 3 0 +3724 41 2 1 +3725 41 2 0 +3726 41 3 1 +3727 41 3 0 +3744 35 2 0 +3745 35 2 1 +3746 35 3 0 +3747 35 3 1 +3748 34 2 0 +3749 34 2 1 +3750 34 3 0 +3751 34 3 1 +3752 32 3 1 +3753 32 3 0 +3754 32 2 1 +3755 32 2 0 +3756 33 3 1 +3757 33 3 0 +3758 33 2 1 +3759 33 2 0 +3760 36 2 0 +3761 36 2 1 +3762 36 3 0 +3763 36 3 1 +3764 37 2 0 +3765 37 2 1 +3766 37 3 0 +3767 37 3 1 +3768 39 3 1 +3769 39 3 0 +3770 39 2 1 +3771 39 2 0 +3772 38 3 1 +3773 38 3 0 +3774 38 2 1 +3775 38 2 0 +3776 44 3 0 +3777 44 3 1 +3778 44 2 0 +3779 44 2 1 +3780 45 3 0 +3781 45 3 1 +3782 45 2 0 +3783 45 2 1 +3784 47 2 1 +3785 47 2 0 +3786 47 3 1 +3787 47 3 0 +3788 46 2 1 +3789 46 2 0 +3790 46 3 1 +3791 46 3 0 +3840 43 1 0 +3841 43 1 1 +3842 43 0 0 +3843 43 0 1 +3844 42 1 0 +3845 42 1 1 +3846 42 0 0 +3847 42 0 1 +3848 40 0 1 +3849 40 0 0 +3850 40 1 1 +3851 40 1 0 +3852 41 0 1 +3853 41 0 0 +3854 41 1 1 +3855 41 1 0 +3872 35 0 0 +3873 35 0 1 +3874 35 1 0 +3875 35 1 1 +3876 34 0 0 +3877 34 0 1 +3878 34 1 0 +3879 34 1 1 +3880 32 1 1 +3881 32 1 0 +3882 32 0 1 +3883 32 0 0 +3884 33 1 1 +3885 33 1 0 +3886 33 0 1 +3887 33 0 0 +3888 36 0 0 +3889 36 0 1 +3890 36 1 0 +3891 36 1 1 +3892 37 0 0 +3893 37 0 1 +3894 37 1 0 +3895 37 1 1 +3896 39 1 1 +3897 39 1 0 +3898 39 0 1 +3899 39 0 0 +3900 38 1 1 +3901 38 1 0 +3902 38 0 1 +3903 38 0 0 +3904 44 1 0 +3905 44 1 1 +3906 44 0 0 +3907 44 0 1 +3908 45 1 0 +3909 45 1 1 +3910 45 0 0 +3911 45 0 1 +3912 47 0 1 +3913 47 0 0 +3914 47 1 1 +3915 47 1 0 +3916 46 0 1 +3917 46 0 0 +3918 46 1 1 +3919 46 1 0 diff --git a/Detectors/PHOS/base/files/Mod2RCU3.data b/Detectors/PHOS/base/files/Mod2RCU3.data new file mode 100644 index 0000000000000..43bd76fc42791 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod2RCU3.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 3 0 2 + 1 3 1 2 + 2 3 2 2 + 3 3 3 2 + 4 3 4 2 + 5 3 5 2 + 6 3 6 2 + 7 3 7 2 + 8 3 8 2 + 9 3 9 2 + 10 3 10 2 + 11 3 11 2 + 12 3 12 2 + 13 3 13 2 + 14 3 14 2 + 15 3 15 2 + 16 3 16 2 + 17 3 17 2 + 18 3 18 2 + 19 3 19 2 + 20 3 20 2 + 21 3 21 2 + 22 3 22 2 + 23 3 23 2 + 24 3 24 2 + 25 3 25 2 + 26 3 26 2 + 27 3 27 2 + 28 3 28 2 + 29 3 29 2 + 30 3 30 2 + 31 3 31 2 + 32 3 32 2 + 33 3 33 2 + 34 3 34 2 + 35 3 35 2 + 36 3 36 2 + 37 3 37 2 + 38 3 38 2 + 39 3 39 2 + 40 3 40 2 + 41 3 41 2 + 42 3 42 2 + 43 3 43 2 + 44 3 44 2 + 45 3 45 2 + 46 3 46 2 + 47 3 47 2 + 48 3 48 2 + 49 3 49 2 + 50 3 50 2 + 51 3 51 2 + 52 3 52 2 + 53 3 53 2 + 54 3 54 2 + 55 3 55 2 + 56 3 56 2 + 57 3 57 2 + 58 3 58 2 + 59 3 59 2 + 60 3 60 2 + 61 3 61 2 + 62 3 62 2 + 63 3 63 2 + 64 3 64 2 + 65 3 65 2 + 66 3 66 2 + 67 3 67 2 + 68 3 68 2 + 69 3 69 2 + 70 3 70 2 + 71 3 71 2 + 72 3 72 2 + 73 3 73 2 + 74 3 74 2 + 75 3 75 2 + 76 3 76 2 + 77 3 77 2 + 78 3 78 2 + 79 3 79 2 + 80 3 80 2 + 81 3 81 2 + 82 3 82 2 + 83 3 83 2 + 84 3 84 2 + 85 3 85 2 + 86 3 86 2 + 87 3 87 2 + 88 3 88 2 + 89 3 89 2 + 90 3 90 2 + 91 3 91 2 + 92 3 92 2 + 93 3 93 2 + 94 3 94 2 + 95 3 95 2 + 96 3 96 2 + 97 3 97 2 + 98 3 98 2 + 99 3 99 2 + 100 3 100 2 + 101 3 101 2 + 102 3 102 2 + 103 3 103 2 + 104 3 104 2 + 105 3 105 2 + 106 3 106 2 + 107 3 107 2 + 108 3 108 2 + 109 3 109 2 + 110 3 110 2 + 111 3 111 2 + 112 3 112 2 + 113 3 113 2 + 114 3 114 2 + 115 3 115 2 + 116 3 116 2 + 117 3 117 2 + 118 3 118 2 + 119 3 119 2 + 120 3 120 2 + 121 3 121 2 + 122 3 122 2 + 123 3 123 2 + 124 3 124 2 + 125 3 125 2 + 126 3 126 2 + 127 3 127 2 +2048 3 2048 2 +2049 3 2049 2 +2050 3 2050 2 +2051 3 2051 2 +2052 3 2052 2 +2053 3 2053 2 +2054 3 2054 2 +2055 3 2055 2 +2056 3 2056 2 +2057 3 2057 2 +2058 3 2058 2 +2059 3 2059 2 +2060 3 2060 2 +2061 3 2061 2 +2062 3 2062 2 +2063 3 2063 2 +2064 3 2064 2 +2065 3 2065 2 +2066 3 2066 2 +2067 3 2067 2 +2068 3 2068 2 +2069 3 2069 2 +2070 3 2070 2 +2071 3 2071 2 +2072 3 2072 2 +2073 3 2073 2 +2074 3 2074 2 +2075 3 2075 2 +2076 3 2076 2 +2077 3 2077 2 +2078 3 2078 2 +2079 3 2079 2 +2080 3 2080 2 +2081 3 2081 2 +2082 3 2082 2 +2083 3 2083 2 +2084 3 2084 2 +2085 3 2085 2 +2086 3 2086 2 +2087 3 2087 2 +2088 3 2088 2 +2089 3 2089 2 +2090 3 2090 2 +2091 3 2091 2 +2092 3 2092 2 +2093 3 2093 2 +2094 3 2094 2 +2095 3 2095 2 +2096 3 2096 2 +2097 3 2097 2 +2098 3 2098 2 +2099 3 2099 2 +2100 3 2100 2 +2101 3 2101 2 +2102 3 2102 2 +2103 3 2103 2 +2104 3 2104 2 +2105 3 2105 2 +2106 3 2106 2 +2107 3 2107 2 +2108 3 2108 2 +2109 3 2109 2 +2110 3 2110 2 +2111 3 2111 2 +2112 3 2112 2 +2113 3 2113 2 +2114 3 2114 2 +2115 3 2115 2 +2116 3 2116 2 +2117 3 2117 2 +2118 3 2118 2 +2119 3 2119 2 +2120 3 2120 2 +2121 3 2121 2 +2122 3 2122 2 +2123 3 2123 2 +2124 3 2124 2 +2125 3 2125 2 +2126 3 2126 2 +2127 3 2127 2 +2128 3 2128 2 +2129 3 2129 2 +2130 3 2130 2 +2131 3 2131 2 +2132 3 2132 2 +2133 3 2133 2 +2134 3 2134 2 +2135 3 2135 2 +2136 3 2136 2 +2137 3 2137 2 +2138 3 2138 2 +2139 3 2139 2 +2140 3 2140 2 +2141 3 2141 2 +2142 3 2142 2 +2143 3 2143 2 +2144 3 2144 2 +2145 3 2145 2 +2146 3 2146 2 +2147 3 2147 2 +2148 3 2148 2 +2149 3 2149 2 +2150 3 2150 2 +2151 3 2151 2 +2152 3 2152 2 +2153 3 2153 2 +2154 3 2154 2 +2155 3 2155 2 +2156 3 2156 2 +2157 3 2157 2 +2158 3 2158 2 +2159 3 2159 2 +2160 3 2160 2 +2161 3 2161 2 +2162 3 2162 2 +2163 3 2163 2 +2164 3 2164 2 +2165 3 2165 2 +2166 3 2166 2 +2167 3 2167 2 +2168 3 2168 2 +2169 3 2169 2 +2170 3 2170 2 +2171 3 2171 2 +2172 3 2172 2 +2173 3 2173 2 +2174 3 2174 2 +2175 3 2175 2 + 128 59 29 0 + 129 59 29 1 + 130 59 28 0 + 131 59 28 1 + 132 58 29 0 + 133 58 29 1 + 134 58 28 0 + 135 58 28 1 + 136 56 28 1 + 137 56 28 0 + 138 56 29 1 + 139 56 29 0 + 140 57 28 1 + 141 57 28 0 + 142 57 29 1 + 143 57 29 0 + 160 51 28 0 + 161 51 28 1 + 162 51 29 0 + 163 51 29 1 + 164 50 28 0 + 165 50 28 1 + 166 50 29 0 + 167 50 29 1 + 168 48 29 1 + 169 48 29 0 + 170 48 28 1 + 171 48 28 0 + 172 49 29 1 + 173 49 29 0 + 174 49 28 1 + 175 49 28 0 + 176 52 28 0 + 177 52 28 1 + 178 52 29 0 + 179 52 29 1 + 180 53 28 0 + 181 53 28 1 + 182 53 29 0 + 183 53 29 1 + 184 55 29 1 + 185 55 29 0 + 186 55 28 1 + 187 55 28 0 + 188 54 29 1 + 189 54 29 0 + 190 54 28 1 + 191 54 28 0 + 192 60 29 0 + 193 60 29 1 + 194 60 28 0 + 195 60 28 1 + 196 61 29 0 + 197 61 29 1 + 198 61 28 0 + 199 61 28 1 + 200 63 28 1 + 201 63 28 0 + 202 63 29 1 + 203 63 29 0 + 204 62 28 1 + 205 62 28 0 + 206 62 29 1 + 207 62 29 0 + 256 59 31 0 + 257 59 31 1 + 258 59 30 0 + 259 59 30 1 + 260 58 31 0 + 261 58 31 1 + 262 58 30 0 + 263 58 30 1 + 264 56 30 1 + 265 56 30 0 + 266 56 31 1 + 267 56 31 0 + 268 57 30 1 + 269 57 30 0 + 270 57 31 1 + 271 57 31 0 + 288 51 30 0 + 289 51 30 1 + 290 51 31 0 + 291 51 31 1 + 292 50 30 0 + 293 50 30 1 + 294 50 31 0 + 295 50 31 1 + 296 48 31 1 + 297 48 31 0 + 298 48 30 1 + 299 48 30 0 + 300 49 31 1 + 301 49 31 0 + 302 49 30 1 + 303 49 30 0 + 304 52 30 0 + 305 52 30 1 + 306 52 31 0 + 307 52 31 1 + 308 53 30 0 + 309 53 30 1 + 310 53 31 0 + 311 53 31 1 + 312 55 31 1 + 313 55 31 0 + 314 55 30 1 + 315 55 30 0 + 316 54 31 1 + 317 54 31 0 + 318 54 30 1 + 319 54 30 0 + 320 60 31 0 + 321 60 31 1 + 322 60 30 0 + 323 60 30 1 + 324 61 31 0 + 325 61 31 1 + 326 61 30 0 + 327 61 30 1 + 328 63 30 1 + 329 63 30 0 + 330 63 31 1 + 331 63 31 0 + 332 62 30 1 + 333 62 30 0 + 334 62 31 1 + 335 62 31 0 + 384 59 33 0 + 385 59 33 1 + 386 59 32 0 + 387 59 32 1 + 388 58 33 0 + 389 58 33 1 + 390 58 32 0 + 391 58 32 1 + 392 56 32 1 + 393 56 32 0 + 394 56 33 1 + 395 56 33 0 + 396 57 32 1 + 397 57 32 0 + 398 57 33 1 + 399 57 33 0 + 416 51 32 0 + 417 51 32 1 + 418 51 33 0 + 419 51 33 1 + 420 50 32 0 + 421 50 32 1 + 422 50 33 0 + 423 50 33 1 + 424 48 33 1 + 425 48 33 0 + 426 48 32 1 + 427 48 32 0 + 428 49 33 1 + 429 49 33 0 + 430 49 32 1 + 431 49 32 0 + 432 52 32 0 + 433 52 32 1 + 434 52 33 0 + 435 52 33 1 + 436 53 32 0 + 437 53 32 1 + 438 53 33 0 + 439 53 33 1 + 440 55 33 1 + 441 55 33 0 + 442 55 32 1 + 443 55 32 0 + 444 54 33 1 + 445 54 33 0 + 446 54 32 1 + 447 54 32 0 + 448 60 33 0 + 449 60 33 1 + 450 60 32 0 + 451 60 32 1 + 452 61 33 0 + 453 61 33 1 + 454 61 32 0 + 455 61 32 1 + 456 63 32 1 + 457 63 32 0 + 458 63 33 1 + 459 63 33 0 + 460 62 32 1 + 461 62 32 0 + 462 62 33 1 + 463 62 33 0 + 512 59 35 0 + 513 59 35 1 + 514 59 34 0 + 515 59 34 1 + 516 58 35 0 + 517 58 35 1 + 518 58 34 0 + 519 58 34 1 + 520 56 34 1 + 521 56 34 0 + 522 56 35 1 + 523 56 35 0 + 524 57 34 1 + 525 57 34 0 + 526 57 35 1 + 527 57 35 0 + 544 51 34 0 + 545 51 34 1 + 546 51 35 0 + 547 51 35 1 + 548 50 34 0 + 549 50 34 1 + 550 50 35 0 + 551 50 35 1 + 552 48 35 1 + 553 48 35 0 + 554 48 34 1 + 555 48 34 0 + 556 49 35 1 + 557 49 35 0 + 558 49 34 1 + 559 49 34 0 + 560 52 34 0 + 561 52 34 1 + 562 52 35 0 + 563 52 35 1 + 564 53 34 0 + 565 53 34 1 + 566 53 35 0 + 567 53 35 1 + 568 55 35 1 + 569 55 35 0 + 570 55 34 1 + 571 55 34 0 + 572 54 35 1 + 573 54 35 0 + 574 54 34 1 + 575 54 34 0 + 576 60 35 0 + 577 60 35 1 + 578 60 34 0 + 579 60 34 1 + 580 61 35 0 + 581 61 35 1 + 582 61 34 0 + 583 61 34 1 + 584 63 34 1 + 585 63 34 0 + 586 63 35 1 + 587 63 35 0 + 588 62 34 1 + 589 62 34 0 + 590 62 35 1 + 591 62 35 0 + 640 59 37 0 + 641 59 37 1 + 642 59 36 0 + 643 59 36 1 + 644 58 37 0 + 645 58 37 1 + 646 58 36 0 + 647 58 36 1 + 648 56 36 1 + 649 56 36 0 + 650 56 37 1 + 651 56 37 0 + 652 57 36 1 + 653 57 36 0 + 654 57 37 1 + 655 57 37 0 + 672 51 36 0 + 673 51 36 1 + 674 51 37 0 + 675 51 37 1 + 676 50 36 0 + 677 50 36 1 + 678 50 37 0 + 679 50 37 1 + 680 48 37 1 + 681 48 37 0 + 682 48 36 1 + 683 48 36 0 + 684 49 37 1 + 685 49 37 0 + 686 49 36 1 + 687 49 36 0 + 688 52 36 0 + 689 52 36 1 + 690 52 37 0 + 691 52 37 1 + 692 53 36 0 + 693 53 36 1 + 694 53 37 0 + 695 53 37 1 + 696 55 37 1 + 697 55 37 0 + 698 55 36 1 + 699 55 36 0 + 700 54 37 1 + 701 54 37 0 + 702 54 36 1 + 703 54 36 0 + 704 60 37 0 + 705 60 37 1 + 706 60 36 0 + 707 60 36 1 + 708 61 37 0 + 709 61 37 1 + 710 61 36 0 + 711 61 36 1 + 712 63 36 1 + 713 63 36 0 + 714 63 37 1 + 715 63 37 0 + 716 62 36 1 + 717 62 36 0 + 718 62 37 1 + 719 62 37 0 + 768 59 39 0 + 769 59 39 1 + 770 59 38 0 + 771 59 38 1 + 772 58 39 0 + 773 58 39 1 + 774 58 38 0 + 775 58 38 1 + 776 56 38 1 + 777 56 38 0 + 778 56 39 1 + 779 56 39 0 + 780 57 38 1 + 781 57 38 0 + 782 57 39 1 + 783 57 39 0 + 800 51 38 0 + 801 51 38 1 + 802 51 39 0 + 803 51 39 1 + 804 50 38 0 + 805 50 38 1 + 806 50 39 0 + 807 50 39 1 + 808 48 39 1 + 809 48 39 0 + 810 48 38 1 + 811 48 38 0 + 812 49 39 1 + 813 49 39 0 + 814 49 38 1 + 815 49 38 0 + 816 52 38 0 + 817 52 38 1 + 818 52 39 0 + 819 52 39 1 + 820 53 38 0 + 821 53 38 1 + 822 53 39 0 + 823 53 39 1 + 824 55 39 1 + 825 55 39 0 + 826 55 38 1 + 827 55 38 0 + 828 54 39 1 + 829 54 39 0 + 830 54 38 1 + 831 54 38 0 + 832 60 39 0 + 833 60 39 1 + 834 60 38 0 + 835 60 38 1 + 836 61 39 0 + 837 61 39 1 + 838 61 38 0 + 839 61 38 1 + 840 63 38 1 + 841 63 38 0 + 842 63 39 1 + 843 63 39 0 + 844 62 38 1 + 845 62 38 0 + 846 62 39 1 + 847 62 39 0 + 896 59 41 0 + 897 59 41 1 + 898 59 40 0 + 899 59 40 1 + 900 58 41 0 + 901 58 41 1 + 902 58 40 0 + 903 58 40 1 + 904 56 40 1 + 905 56 40 0 + 906 56 41 1 + 907 56 41 0 + 908 57 40 1 + 909 57 40 0 + 910 57 41 1 + 911 57 41 0 + 928 51 40 0 + 929 51 40 1 + 930 51 41 0 + 931 51 41 1 + 932 50 40 0 + 933 50 40 1 + 934 50 41 0 + 935 50 41 1 + 936 48 41 1 + 937 48 41 0 + 938 48 40 1 + 939 48 40 0 + 940 49 41 1 + 941 49 41 0 + 942 49 40 1 + 943 49 40 0 + 944 52 40 0 + 945 52 40 1 + 946 52 41 0 + 947 52 41 1 + 948 53 40 0 + 949 53 40 1 + 950 53 41 0 + 951 53 41 1 + 952 55 41 1 + 953 55 41 0 + 954 55 40 1 + 955 55 40 0 + 956 54 41 1 + 957 54 41 0 + 958 54 40 1 + 959 54 40 0 + 960 60 41 0 + 961 60 41 1 + 962 60 40 0 + 963 60 40 1 + 964 61 41 0 + 965 61 41 1 + 966 61 40 0 + 967 61 40 1 + 968 63 40 1 + 969 63 40 0 + 970 63 41 1 + 971 63 41 0 + 972 62 40 1 + 973 62 40 0 + 974 62 41 1 + 975 62 41 0 +1024 59 43 0 +1025 59 43 1 +1026 59 42 0 +1027 59 42 1 +1028 58 43 0 +1029 58 43 1 +1030 58 42 0 +1031 58 42 1 +1032 56 42 1 +1033 56 42 0 +1034 56 43 1 +1035 56 43 0 +1036 57 42 1 +1037 57 42 0 +1038 57 43 1 +1039 57 43 0 +1056 51 42 0 +1057 51 42 1 +1058 51 43 0 +1059 51 43 1 +1060 50 42 0 +1061 50 42 1 +1062 50 43 0 +1063 50 43 1 +1064 48 43 1 +1065 48 43 0 +1066 48 42 1 +1067 48 42 0 +1068 49 43 1 +1069 49 43 0 +1070 49 42 1 +1071 49 42 0 +1072 52 42 0 +1073 52 42 1 +1074 52 43 0 +1075 52 43 1 +1076 53 42 0 +1077 53 42 1 +1078 53 43 0 +1079 53 43 1 +1080 55 43 1 +1081 55 43 0 +1082 55 42 1 +1083 55 42 0 +1084 54 43 1 +1085 54 43 0 +1086 54 42 1 +1087 54 42 0 +1088 60 43 0 +1089 60 43 1 +1090 60 42 0 +1091 60 42 1 +1092 61 43 0 +1093 61 43 1 +1094 61 42 0 +1095 61 42 1 +1096 63 42 1 +1097 63 42 0 +1098 63 43 1 +1099 63 43 0 +1100 62 42 1 +1101 62 42 0 +1102 62 43 1 +1103 62 43 0 +1152 59 45 0 +1153 59 45 1 +1154 59 44 0 +1155 59 44 1 +1156 58 45 0 +1157 58 45 1 +1158 58 44 0 +1159 58 44 1 +1160 56 44 1 +1161 56 44 0 +1162 56 45 1 +1163 56 45 0 +1164 57 44 1 +1165 57 44 0 +1166 57 45 1 +1167 57 45 0 +1184 51 44 0 +1185 51 44 1 +1186 51 45 0 +1187 51 45 1 +1188 50 44 0 +1189 50 44 1 +1190 50 45 0 +1191 50 45 1 +1192 48 45 1 +1193 48 45 0 +1194 48 44 1 +1195 48 44 0 +1196 49 45 1 +1197 49 45 0 +1198 49 44 1 +1199 49 44 0 +1200 52 44 0 +1201 52 44 1 +1202 52 45 0 +1203 52 45 1 +1204 53 44 0 +1205 53 44 1 +1206 53 45 0 +1207 53 45 1 +1208 55 45 1 +1209 55 45 0 +1210 55 44 1 +1211 55 44 0 +1212 54 45 1 +1213 54 45 0 +1214 54 44 1 +1215 54 44 0 +1216 60 45 0 +1217 60 45 1 +1218 60 44 0 +1219 60 44 1 +1220 61 45 0 +1221 61 45 1 +1222 61 44 0 +1223 61 44 1 +1224 63 44 1 +1225 63 44 0 +1226 63 45 1 +1227 63 45 0 +1228 62 44 1 +1229 62 44 0 +1230 62 45 1 +1231 62 45 0 +1280 59 47 0 +1281 59 47 1 +1282 59 46 0 +1283 59 46 1 +1284 58 47 0 +1285 58 47 1 +1286 58 46 0 +1287 58 46 1 +1288 56 46 1 +1289 56 46 0 +1290 56 47 1 +1291 56 47 0 +1292 57 46 1 +1293 57 46 0 +1294 57 47 1 +1295 57 47 0 +1312 51 46 0 +1313 51 46 1 +1314 51 47 0 +1315 51 47 1 +1316 50 46 0 +1317 50 46 1 +1318 50 47 0 +1319 50 47 1 +1320 48 47 1 +1321 48 47 0 +1322 48 46 1 +1323 48 46 0 +1324 49 47 1 +1325 49 47 0 +1326 49 46 1 +1327 49 46 0 +1328 52 46 0 +1329 52 46 1 +1330 52 47 0 +1331 52 47 1 +1332 53 46 0 +1333 53 46 1 +1334 53 47 0 +1335 53 47 1 +1336 55 47 1 +1337 55 47 0 +1338 55 46 1 +1339 55 46 0 +1340 54 47 1 +1341 54 47 0 +1342 54 46 1 +1343 54 46 0 +1344 60 47 0 +1345 60 47 1 +1346 60 46 0 +1347 60 46 1 +1348 61 47 0 +1349 61 47 1 +1350 61 46 0 +1351 61 46 1 +1352 63 46 1 +1353 63 46 0 +1354 63 47 1 +1355 63 47 0 +1356 62 46 1 +1357 62 46 0 +1358 62 47 1 +1359 62 47 0 +1408 59 49 0 +1409 59 49 1 +1410 59 48 0 +1411 59 48 1 +1412 58 49 0 +1413 58 49 1 +1414 58 48 0 +1415 58 48 1 +1416 56 48 1 +1417 56 48 0 +1418 56 49 1 +1419 56 49 0 +1420 57 48 1 +1421 57 48 0 +1422 57 49 1 +1423 57 49 0 +1440 51 48 0 +1441 51 48 1 +1442 51 49 0 +1443 51 49 1 +1444 50 48 0 +1445 50 48 1 +1446 50 49 0 +1447 50 49 1 +1448 48 49 1 +1449 48 49 0 +1450 48 48 1 +1451 48 48 0 +1452 49 49 1 +1453 49 49 0 +1454 49 48 1 +1455 49 48 0 +1456 52 48 0 +1457 52 48 1 +1458 52 49 0 +1459 52 49 1 +1460 53 48 0 +1461 53 48 1 +1462 53 49 0 +1463 53 49 1 +1464 55 49 1 +1465 55 49 0 +1466 55 48 1 +1467 55 48 0 +1468 54 49 1 +1469 54 49 0 +1470 54 48 1 +1471 54 48 0 +1472 60 49 0 +1473 60 49 1 +1474 60 48 0 +1475 60 48 1 +1476 61 49 0 +1477 61 49 1 +1478 61 48 0 +1479 61 48 1 +1480 63 48 1 +1481 63 48 0 +1482 63 49 1 +1483 63 49 0 +1484 62 48 1 +1485 62 48 0 +1486 62 49 1 +1487 62 49 0 +1536 59 51 0 +1537 59 51 1 +1538 59 50 0 +1539 59 50 1 +1540 58 51 0 +1541 58 51 1 +1542 58 50 0 +1543 58 50 1 +1544 56 50 1 +1545 56 50 0 +1546 56 51 1 +1547 56 51 0 +1548 57 50 1 +1549 57 50 0 +1550 57 51 1 +1551 57 51 0 +1568 51 50 0 +1569 51 50 1 +1570 51 51 0 +1571 51 51 1 +1572 50 50 0 +1573 50 50 1 +1574 50 51 0 +1575 50 51 1 +1576 48 51 1 +1577 48 51 0 +1578 48 50 1 +1579 48 50 0 +1580 49 51 1 +1581 49 51 0 +1582 49 50 1 +1583 49 50 0 +1584 52 50 0 +1585 52 50 1 +1586 52 51 0 +1587 52 51 1 +1588 53 50 0 +1589 53 50 1 +1590 53 51 0 +1591 53 51 1 +1592 55 51 1 +1593 55 51 0 +1594 55 50 1 +1595 55 50 0 +1596 54 51 1 +1597 54 51 0 +1598 54 50 1 +1599 54 50 0 +1600 60 51 0 +1601 60 51 1 +1602 60 50 0 +1603 60 50 1 +1604 61 51 0 +1605 61 51 1 +1606 61 50 0 +1607 61 50 1 +1608 63 50 1 +1609 63 50 0 +1610 63 51 1 +1611 63 51 0 +1612 62 50 1 +1613 62 50 0 +1614 62 51 1 +1615 62 51 0 +1664 59 53 0 +1665 59 53 1 +1666 59 52 0 +1667 59 52 1 +1668 58 53 0 +1669 58 53 1 +1670 58 52 0 +1671 58 52 1 +1672 56 52 1 +1673 56 52 0 +1674 56 53 1 +1675 56 53 0 +1676 57 52 1 +1677 57 52 0 +1678 57 53 1 +1679 57 53 0 +1696 51 52 0 +1697 51 52 1 +1698 51 53 0 +1699 51 53 1 +1700 50 52 0 +1701 50 52 1 +1702 50 53 0 +1703 50 53 1 +1704 48 53 1 +1705 48 53 0 +1706 48 52 1 +1707 48 52 0 +1708 49 53 1 +1709 49 53 0 +1710 49 52 1 +1711 49 52 0 +1712 52 52 0 +1713 52 52 1 +1714 52 53 0 +1715 52 53 1 +1716 53 52 0 +1717 53 52 1 +1718 53 53 0 +1719 53 53 1 +1720 55 53 1 +1721 55 53 0 +1722 55 52 1 +1723 55 52 0 +1724 54 53 1 +1725 54 53 0 +1726 54 52 1 +1727 54 52 0 +1728 60 53 0 +1729 60 53 1 +1730 60 52 0 +1731 60 52 1 +1732 61 53 0 +1733 61 53 1 +1734 61 52 0 +1735 61 52 1 +1736 63 52 1 +1737 63 52 0 +1738 63 53 1 +1739 63 53 0 +1740 62 52 1 +1741 62 52 0 +1742 62 53 1 +1743 62 53 0 +1792 59 55 0 +1793 59 55 1 +1794 59 54 0 +1795 59 54 1 +1796 58 55 0 +1797 58 55 1 +1798 58 54 0 +1799 58 54 1 +1800 56 54 1 +1801 56 54 0 +1802 56 55 1 +1803 56 55 0 +1804 57 54 1 +1805 57 54 0 +1806 57 55 1 +1807 57 55 0 +1824 51 54 0 +1825 51 54 1 +1826 51 55 0 +1827 51 55 1 +1828 50 54 0 +1829 50 54 1 +1830 50 55 0 +1831 50 55 1 +1832 48 55 1 +1833 48 55 0 +1834 48 54 1 +1835 48 54 0 +1836 49 55 1 +1837 49 55 0 +1838 49 54 1 +1839 49 54 0 +1840 52 54 0 +1841 52 54 1 +1842 52 55 0 +1843 52 55 1 +1844 53 54 0 +1845 53 54 1 +1846 53 55 0 +1847 53 55 1 +1848 55 55 1 +1849 55 55 0 +1850 55 54 1 +1851 55 54 0 +1852 54 55 1 +1853 54 55 0 +1854 54 54 1 +1855 54 54 0 +1856 60 55 0 +1857 60 55 1 +1858 60 54 0 +1859 60 54 1 +1860 61 55 0 +1861 61 55 1 +1862 61 54 0 +1863 61 54 1 +1864 63 54 1 +1865 63 54 0 +1866 63 55 1 +1867 63 55 0 +1868 62 54 1 +1869 62 54 0 +1870 62 55 1 +1871 62 55 0 +2176 59 27 0 +2177 59 27 1 +2178 59 26 0 +2179 59 26 1 +2180 58 27 0 +2181 58 27 1 +2182 58 26 0 +2183 58 26 1 +2184 56 26 1 +2185 56 26 0 +2186 56 27 1 +2187 56 27 0 +2188 57 26 1 +2189 57 26 0 +2190 57 27 1 +2191 57 27 0 +2208 51 26 0 +2209 51 26 1 +2210 51 27 0 +2211 51 27 1 +2212 50 26 0 +2213 50 26 1 +2214 50 27 0 +2215 50 27 1 +2216 48 27 1 +2217 48 27 0 +2218 48 26 1 +2219 48 26 0 +2220 49 27 1 +2221 49 27 0 +2222 49 26 1 +2223 49 26 0 +2224 52 26 0 +2225 52 26 1 +2226 52 27 0 +2227 52 27 1 +2228 53 26 0 +2229 53 26 1 +2230 53 27 0 +2231 53 27 1 +2232 55 27 1 +2233 55 27 0 +2234 55 26 1 +2235 55 26 0 +2236 54 27 1 +2237 54 27 0 +2238 54 26 1 +2239 54 26 0 +2240 60 27 0 +2241 60 27 1 +2242 60 26 0 +2243 60 26 1 +2244 61 27 0 +2245 61 27 1 +2246 61 26 0 +2247 61 26 1 +2248 63 26 1 +2249 63 26 0 +2250 63 27 1 +2251 63 27 0 +2252 62 26 1 +2253 62 26 0 +2254 62 27 1 +2255 62 27 0 +2304 59 25 0 +2305 59 25 1 +2306 59 24 0 +2307 59 24 1 +2308 58 25 0 +2309 58 25 1 +2310 58 24 0 +2311 58 24 1 +2312 56 24 1 +2313 56 24 0 +2314 56 25 1 +2315 56 25 0 +2316 57 24 1 +2317 57 24 0 +2318 57 25 1 +2319 57 25 0 +2336 51 24 0 +2337 51 24 1 +2338 51 25 0 +2339 51 25 1 +2340 50 24 0 +2341 50 24 1 +2342 50 25 0 +2343 50 25 1 +2344 48 25 1 +2345 48 25 0 +2346 48 24 1 +2347 48 24 0 +2348 49 25 1 +2349 49 25 0 +2350 49 24 1 +2351 49 24 0 +2352 52 24 0 +2353 52 24 1 +2354 52 25 0 +2355 52 25 1 +2356 53 24 0 +2357 53 24 1 +2358 53 25 0 +2359 53 25 1 +2360 55 25 1 +2361 55 25 0 +2362 55 24 1 +2363 55 24 0 +2364 54 25 1 +2365 54 25 0 +2366 54 24 1 +2367 54 24 0 +2368 60 25 0 +2369 60 25 1 +2370 60 24 0 +2371 60 24 1 +2372 61 25 0 +2373 61 25 1 +2374 61 24 0 +2375 61 24 1 +2376 63 24 1 +2377 63 24 0 +2378 63 25 1 +2379 63 25 0 +2380 62 24 1 +2381 62 24 0 +2382 62 25 1 +2383 62 25 0 +2432 59 23 0 +2433 59 23 1 +2434 59 22 0 +2435 59 22 1 +2436 58 23 0 +2437 58 23 1 +2438 58 22 0 +2439 58 22 1 +2440 56 22 1 +2441 56 22 0 +2442 56 23 1 +2443 56 23 0 +2444 57 22 1 +2445 57 22 0 +2446 57 23 1 +2447 57 23 0 +2464 51 22 0 +2465 51 22 1 +2466 51 23 0 +2467 51 23 1 +2468 50 22 0 +2469 50 22 1 +2470 50 23 0 +2471 50 23 1 +2472 48 23 1 +2473 48 23 0 +2474 48 22 1 +2475 48 22 0 +2476 49 23 1 +2477 49 23 0 +2478 49 22 1 +2479 49 22 0 +2480 52 22 0 +2481 52 22 1 +2482 52 23 0 +2483 52 23 1 +2484 53 22 0 +2485 53 22 1 +2486 53 23 0 +2487 53 23 1 +2488 55 23 1 +2489 55 23 0 +2490 55 22 1 +2491 55 22 0 +2492 54 23 1 +2493 54 23 0 +2494 54 22 1 +2495 54 22 0 +2496 60 23 0 +2497 60 23 1 +2498 60 22 0 +2499 60 22 1 +2500 61 23 0 +2501 61 23 1 +2502 61 22 0 +2503 61 22 1 +2504 63 22 1 +2505 63 22 0 +2506 63 23 1 +2507 63 23 0 +2508 62 22 1 +2509 62 22 0 +2510 62 23 1 +2511 62 23 0 +2560 59 21 0 +2561 59 21 1 +2562 59 20 0 +2563 59 20 1 +2564 58 21 0 +2565 58 21 1 +2566 58 20 0 +2567 58 20 1 +2568 56 20 1 +2569 56 20 0 +2570 56 21 1 +2571 56 21 0 +2572 57 20 1 +2573 57 20 0 +2574 57 21 1 +2575 57 21 0 +2592 51 20 0 +2593 51 20 1 +2594 51 21 0 +2595 51 21 1 +2596 50 20 0 +2597 50 20 1 +2598 50 21 0 +2599 50 21 1 +2600 48 21 1 +2601 48 21 0 +2602 48 20 1 +2603 48 20 0 +2604 49 21 1 +2605 49 21 0 +2606 49 20 1 +2607 49 20 0 +2608 52 20 0 +2609 52 20 1 +2610 52 21 0 +2611 52 21 1 +2612 53 20 0 +2613 53 20 1 +2614 53 21 0 +2615 53 21 1 +2616 55 21 1 +2617 55 21 0 +2618 55 20 1 +2619 55 20 0 +2620 54 21 1 +2621 54 21 0 +2622 54 20 1 +2623 54 20 0 +2624 60 21 0 +2625 60 21 1 +2626 60 20 0 +2627 60 20 1 +2628 61 21 0 +2629 61 21 1 +2630 61 20 0 +2631 61 20 1 +2632 63 20 1 +2633 63 20 0 +2634 63 21 1 +2635 63 21 0 +2636 62 20 1 +2637 62 20 0 +2638 62 21 1 +2639 62 21 0 +2688 59 19 0 +2689 59 19 1 +2690 59 18 0 +2691 59 18 1 +2692 58 19 0 +2693 58 19 1 +2694 58 18 0 +2695 58 18 1 +2696 56 18 1 +2697 56 18 0 +2698 56 19 1 +2699 56 19 0 +2700 57 18 1 +2701 57 18 0 +2702 57 19 1 +2703 57 19 0 +2720 51 18 0 +2721 51 18 1 +2722 51 19 0 +2723 51 19 1 +2724 50 18 0 +2725 50 18 1 +2726 50 19 0 +2727 50 19 1 +2728 48 19 1 +2729 48 19 0 +2730 48 18 1 +2731 48 18 0 +2732 49 19 1 +2733 49 19 0 +2734 49 18 1 +2735 49 18 0 +2736 52 18 0 +2737 52 18 1 +2738 52 19 0 +2739 52 19 1 +2740 53 18 0 +2741 53 18 1 +2742 53 19 0 +2743 53 19 1 +2744 55 19 1 +2745 55 19 0 +2746 55 18 1 +2747 55 18 0 +2748 54 19 1 +2749 54 19 0 +2750 54 18 1 +2751 54 18 0 +2752 60 19 0 +2753 60 19 1 +2754 60 18 0 +2755 60 18 1 +2756 61 19 0 +2757 61 19 1 +2758 61 18 0 +2759 61 18 1 +2760 63 18 1 +2761 63 18 0 +2762 63 19 1 +2763 63 19 0 +2764 62 18 1 +2765 62 18 0 +2766 62 19 1 +2767 62 19 0 +2816 59 17 0 +2817 59 17 1 +2818 59 16 0 +2819 59 16 1 +2820 58 17 0 +2821 58 17 1 +2822 58 16 0 +2823 58 16 1 +2824 56 16 1 +2825 56 16 0 +2826 56 17 1 +2827 56 17 0 +2828 57 16 1 +2829 57 16 0 +2830 57 17 1 +2831 57 17 0 +2848 51 16 0 +2849 51 16 1 +2850 51 17 0 +2851 51 17 1 +2852 50 16 0 +2853 50 16 1 +2854 50 17 0 +2855 50 17 1 +2856 48 17 1 +2857 48 17 0 +2858 48 16 1 +2859 48 16 0 +2860 49 17 1 +2861 49 17 0 +2862 49 16 1 +2863 49 16 0 +2864 52 16 0 +2865 52 16 1 +2866 52 17 0 +2867 52 17 1 +2868 53 16 0 +2869 53 16 1 +2870 53 17 0 +2871 53 17 1 +2872 55 17 1 +2873 55 17 0 +2874 55 16 1 +2875 55 16 0 +2876 54 17 1 +2877 54 17 0 +2878 54 16 1 +2879 54 16 0 +2880 60 17 0 +2881 60 17 1 +2882 60 16 0 +2883 60 16 1 +2884 61 17 0 +2885 61 17 1 +2886 61 16 0 +2887 61 16 1 +2888 63 16 1 +2889 63 16 0 +2890 63 17 1 +2891 63 17 0 +2892 62 16 1 +2893 62 16 0 +2894 62 17 1 +2895 62 17 0 +2944 59 15 0 +2945 59 15 1 +2946 59 14 0 +2947 59 14 1 +2948 58 15 0 +2949 58 15 1 +2950 58 14 0 +2951 58 14 1 +2952 56 14 1 +2953 56 14 0 +2954 56 15 1 +2955 56 15 0 +2956 57 14 1 +2957 57 14 0 +2958 57 15 1 +2959 57 15 0 +2976 51 14 0 +2977 51 14 1 +2978 51 15 0 +2979 51 15 1 +2980 50 14 0 +2981 50 14 1 +2982 50 15 0 +2983 50 15 1 +2984 48 15 1 +2985 48 15 0 +2986 48 14 1 +2987 48 14 0 +2988 49 15 1 +2989 49 15 0 +2990 49 14 1 +2991 49 14 0 +2992 52 14 0 +2993 52 14 1 +2994 52 15 0 +2995 52 15 1 +2996 53 14 0 +2997 53 14 1 +2998 53 15 0 +2999 53 15 1 +3000 55 15 1 +3001 55 15 0 +3002 55 14 1 +3003 55 14 0 +3004 54 15 1 +3005 54 15 0 +3006 54 14 1 +3007 54 14 0 +3008 60 15 0 +3009 60 15 1 +3010 60 14 0 +3011 60 14 1 +3012 61 15 0 +3013 61 15 1 +3014 61 14 0 +3015 61 14 1 +3016 63 14 1 +3017 63 14 0 +3018 63 15 1 +3019 63 15 0 +3020 62 14 1 +3021 62 14 0 +3022 62 15 1 +3023 62 15 0 +3072 59 13 0 +3073 59 13 1 +3074 59 12 0 +3075 59 12 1 +3076 58 13 0 +3077 58 13 1 +3078 58 12 0 +3079 58 12 1 +3080 56 12 1 +3081 56 12 0 +3082 56 13 1 +3083 56 13 0 +3084 57 12 1 +3085 57 12 0 +3086 57 13 1 +3087 57 13 0 +3104 51 12 0 +3105 51 12 1 +3106 51 13 0 +3107 51 13 1 +3108 50 12 0 +3109 50 12 1 +3110 50 13 0 +3111 50 13 1 +3112 48 13 1 +3113 48 13 0 +3114 48 12 1 +3115 48 12 0 +3116 49 13 1 +3117 49 13 0 +3118 49 12 1 +3119 49 12 0 +3120 52 12 0 +3121 52 12 1 +3122 52 13 0 +3123 52 13 1 +3124 53 12 0 +3125 53 12 1 +3126 53 13 0 +3127 53 13 1 +3128 55 13 1 +3129 55 13 0 +3130 55 12 1 +3131 55 12 0 +3132 54 13 1 +3133 54 13 0 +3134 54 12 1 +3135 54 12 0 +3136 60 13 0 +3137 60 13 1 +3138 60 12 0 +3139 60 12 1 +3140 61 13 0 +3141 61 13 1 +3142 61 12 0 +3143 61 12 1 +3144 63 12 1 +3145 63 12 0 +3146 63 13 1 +3147 63 13 0 +3148 62 12 1 +3149 62 12 0 +3150 62 13 1 +3151 62 13 0 +3200 59 11 0 +3201 59 11 1 +3202 59 10 0 +3203 59 10 1 +3204 58 11 0 +3205 58 11 1 +3206 58 10 0 +3207 58 10 1 +3208 56 10 1 +3209 56 10 0 +3210 56 11 1 +3211 56 11 0 +3212 57 10 1 +3213 57 10 0 +3214 57 11 1 +3215 57 11 0 +3232 51 10 0 +3233 51 10 1 +3234 51 11 0 +3235 51 11 1 +3236 50 10 0 +3237 50 10 1 +3238 50 11 0 +3239 50 11 1 +3240 48 11 1 +3241 48 11 0 +3242 48 10 1 +3243 48 10 0 +3244 49 11 1 +3245 49 11 0 +3246 49 10 1 +3247 49 10 0 +3248 52 10 0 +3249 52 10 1 +3250 52 11 0 +3251 52 11 1 +3252 53 10 0 +3253 53 10 1 +3254 53 11 0 +3255 53 11 1 +3256 55 11 1 +3257 55 11 0 +3258 55 10 1 +3259 55 10 0 +3260 54 11 1 +3261 54 11 0 +3262 54 10 1 +3263 54 10 0 +3264 60 11 0 +3265 60 11 1 +3266 60 10 0 +3267 60 10 1 +3268 61 11 0 +3269 61 11 1 +3270 61 10 0 +3271 61 10 1 +3272 63 10 1 +3273 63 10 0 +3274 63 11 1 +3275 63 11 0 +3276 62 10 1 +3277 62 10 0 +3278 62 11 1 +3279 62 11 0 +3328 59 9 0 +3329 59 9 1 +3330 59 8 0 +3331 59 8 1 +3332 58 9 0 +3333 58 9 1 +3334 58 8 0 +3335 58 8 1 +3336 56 8 1 +3337 56 8 0 +3338 56 9 1 +3339 56 9 0 +3340 57 8 1 +3341 57 8 0 +3342 57 9 1 +3343 57 9 0 +3360 51 8 0 +3361 51 8 1 +3362 51 9 0 +3363 51 9 1 +3364 50 8 0 +3365 50 8 1 +3366 50 9 0 +3367 50 9 1 +3368 48 9 1 +3369 48 9 0 +3370 48 8 1 +3371 48 8 0 +3372 49 9 1 +3373 49 9 0 +3374 49 8 1 +3375 49 8 0 +3376 52 8 0 +3377 52 8 1 +3378 52 9 0 +3379 52 9 1 +3380 53 8 0 +3381 53 8 1 +3382 53 9 0 +3383 53 9 1 +3384 55 9 1 +3385 55 9 0 +3386 55 8 1 +3387 55 8 0 +3388 54 9 1 +3389 54 9 0 +3390 54 8 1 +3391 54 8 0 +3392 60 9 0 +3393 60 9 1 +3394 60 8 0 +3395 60 8 1 +3396 61 9 0 +3397 61 9 1 +3398 61 8 0 +3399 61 8 1 +3400 63 8 1 +3401 63 8 0 +3402 63 9 1 +3403 63 9 0 +3404 62 8 1 +3405 62 8 0 +3406 62 9 1 +3407 62 9 0 +3456 59 7 0 +3457 59 7 1 +3458 59 6 0 +3459 59 6 1 +3460 58 7 0 +3461 58 7 1 +3462 58 6 0 +3463 58 6 1 +3464 56 6 1 +3465 56 6 0 +3466 56 7 1 +3467 56 7 0 +3468 57 6 1 +3469 57 6 0 +3470 57 7 1 +3471 57 7 0 +3488 51 6 0 +3489 51 6 1 +3490 51 7 0 +3491 51 7 1 +3492 50 6 0 +3493 50 6 1 +3494 50 7 0 +3495 50 7 1 +3496 48 7 1 +3497 48 7 0 +3498 48 6 1 +3499 48 6 0 +3500 49 7 1 +3501 49 7 0 +3502 49 6 1 +3503 49 6 0 +3504 52 6 0 +3505 52 6 1 +3506 52 7 0 +3507 52 7 1 +3508 53 6 0 +3509 53 6 1 +3510 53 7 0 +3511 53 7 1 +3512 55 7 1 +3513 55 7 0 +3514 55 6 1 +3515 55 6 0 +3516 54 7 1 +3517 54 7 0 +3518 54 6 1 +3519 54 6 0 +3520 60 7 0 +3521 60 7 1 +3522 60 6 0 +3523 60 6 1 +3524 61 7 0 +3525 61 7 1 +3526 61 6 0 +3527 61 6 1 +3528 63 6 1 +3529 63 6 0 +3530 63 7 1 +3531 63 7 0 +3532 62 6 1 +3533 62 6 0 +3534 62 7 1 +3535 62 7 0 +3584 59 5 0 +3585 59 5 1 +3586 59 4 0 +3587 59 4 1 +3588 58 5 0 +3589 58 5 1 +3590 58 4 0 +3591 58 4 1 +3592 56 4 1 +3593 56 4 0 +3594 56 5 1 +3595 56 5 0 +3596 57 4 1 +3597 57 4 0 +3598 57 5 1 +3599 57 5 0 +3616 51 4 0 +3617 51 4 1 +3618 51 5 0 +3619 51 5 1 +3620 50 4 0 +3621 50 4 1 +3622 50 5 0 +3623 50 5 1 +3624 48 5 1 +3625 48 5 0 +3626 48 4 1 +3627 48 4 0 +3628 49 5 1 +3629 49 5 0 +3630 49 4 1 +3631 49 4 0 +3632 52 4 0 +3633 52 4 1 +3634 52 5 0 +3635 52 5 1 +3636 53 4 0 +3637 53 4 1 +3638 53 5 0 +3639 53 5 1 +3640 55 5 1 +3641 55 5 0 +3642 55 4 1 +3643 55 4 0 +3644 54 5 1 +3645 54 5 0 +3646 54 4 1 +3647 54 4 0 +3648 60 5 0 +3649 60 5 1 +3650 60 4 0 +3651 60 4 1 +3652 61 5 0 +3653 61 5 1 +3654 61 4 0 +3655 61 4 1 +3656 63 4 1 +3657 63 4 0 +3658 63 5 1 +3659 63 5 0 +3660 62 4 1 +3661 62 4 0 +3662 62 5 1 +3663 62 5 0 +3712 59 3 0 +3713 59 3 1 +3714 59 2 0 +3715 59 2 1 +3716 58 3 0 +3717 58 3 1 +3718 58 2 0 +3719 58 2 1 +3720 56 2 1 +3721 56 2 0 +3722 56 3 1 +3723 56 3 0 +3724 57 2 1 +3725 57 2 0 +3726 57 3 1 +3727 57 3 0 +3744 51 2 0 +3745 51 2 1 +3746 51 3 0 +3747 51 3 1 +3748 50 2 0 +3749 50 2 1 +3750 50 3 0 +3751 50 3 1 +3752 48 3 1 +3753 48 3 0 +3754 48 2 1 +3755 48 2 0 +3756 49 3 1 +3757 49 3 0 +3758 49 2 1 +3759 49 2 0 +3760 52 2 0 +3761 52 2 1 +3762 52 3 0 +3763 52 3 1 +3764 53 2 0 +3765 53 2 1 +3766 53 3 0 +3767 53 3 1 +3768 55 3 1 +3769 55 3 0 +3770 55 2 1 +3771 55 2 0 +3772 54 3 1 +3773 54 3 0 +3774 54 2 1 +3775 54 2 0 +3776 60 3 0 +3777 60 3 1 +3778 60 2 0 +3779 60 2 1 +3780 61 3 0 +3781 61 3 1 +3782 61 2 0 +3783 61 2 1 +3784 63 2 1 +3785 63 2 0 +3786 63 3 1 +3787 63 3 0 +3788 62 2 1 +3789 62 2 0 +3790 62 3 1 +3791 62 3 0 +3840 59 1 0 +3841 59 1 1 +3842 59 0 0 +3843 59 0 1 +3844 58 1 0 +3845 58 1 1 +3846 58 0 0 +3847 58 0 1 +3848 56 0 1 +3849 56 0 0 +3850 56 1 1 +3851 56 1 0 +3852 57 0 1 +3853 57 0 0 +3854 57 1 1 +3855 57 1 0 +3872 51 0 0 +3873 51 0 1 +3874 51 1 0 +3875 51 1 1 +3876 50 0 0 +3877 50 0 1 +3878 50 1 0 +3879 50 1 1 +3880 48 1 1 +3881 48 1 0 +3882 48 0 1 +3883 48 0 0 +3884 49 1 1 +3885 49 1 0 +3886 49 0 1 +3887 49 0 0 +3888 52 0 0 +3889 52 0 1 +3890 52 1 0 +3891 52 1 1 +3892 53 0 0 +3893 53 0 1 +3894 53 1 0 +3895 53 1 1 +3896 55 1 1 +3897 55 1 0 +3898 55 0 1 +3899 55 0 0 +3900 54 1 1 +3901 54 1 0 +3902 54 0 1 +3903 54 0 0 +3904 60 1 0 +3905 60 1 1 +3906 60 0 0 +3907 60 0 1 +3908 61 1 0 +3909 61 1 1 +3910 61 0 0 +3911 61 0 1 +3912 63 0 1 +3913 63 0 0 +3914 63 1 1 +3915 63 1 0 +3916 62 0 1 +3917 62 0 0 +3918 62 1 1 +3919 62 1 0 diff --git a/Detectors/PHOS/base/files/Mod3RCU0.data b/Detectors/PHOS/base/files/Mod3RCU0.data new file mode 100644 index 0000000000000..4739df6e3e61e --- /dev/null +++ b/Detectors/PHOS/base/files/Mod3RCU0.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 0 0 2 + 1 0 1 2 + 2 0 2 2 + 3 0 3 2 + 4 0 4 2 + 5 0 5 2 + 6 0 6 2 + 7 0 7 2 + 8 0 8 2 + 9 0 9 2 + 10 0 10 2 + 11 0 11 2 + 12 0 12 2 + 13 0 13 2 + 14 0 14 2 + 15 0 15 2 + 16 0 16 2 + 17 0 17 2 + 18 0 18 2 + 19 0 19 2 + 20 0 20 2 + 21 0 21 2 + 22 0 22 2 + 23 0 23 2 + 24 0 24 2 + 25 0 25 2 + 26 0 26 2 + 27 0 27 2 + 28 0 28 2 + 29 0 29 2 + 30 0 30 2 + 31 0 31 2 + 32 0 32 2 + 33 0 33 2 + 34 0 34 2 + 35 0 35 2 + 36 0 36 2 + 37 0 37 2 + 38 0 38 2 + 39 0 39 2 + 40 0 40 2 + 41 0 41 2 + 42 0 42 2 + 43 0 43 2 + 44 0 44 2 + 45 0 45 2 + 46 0 46 2 + 47 0 47 2 + 48 0 48 2 + 49 0 49 2 + 50 0 50 2 + 51 0 51 2 + 52 0 52 2 + 53 0 53 2 + 54 0 54 2 + 55 0 55 2 + 56 0 56 2 + 57 0 57 2 + 58 0 58 2 + 59 0 59 2 + 60 0 60 2 + 61 0 61 2 + 62 0 62 2 + 63 0 63 2 + 64 0 64 2 + 65 0 65 2 + 66 0 66 2 + 67 0 67 2 + 68 0 68 2 + 69 0 69 2 + 70 0 70 2 + 71 0 71 2 + 72 0 72 2 + 73 0 73 2 + 74 0 74 2 + 75 0 75 2 + 76 0 76 2 + 77 0 77 2 + 78 0 78 2 + 79 0 79 2 + 80 0 80 2 + 81 0 81 2 + 82 0 82 2 + 83 0 83 2 + 84 0 84 2 + 85 0 85 2 + 86 0 86 2 + 87 0 87 2 + 88 0 88 2 + 89 0 89 2 + 90 0 90 2 + 91 0 91 2 + 92 0 92 2 + 93 0 93 2 + 94 0 94 2 + 95 0 95 2 + 96 0 96 2 + 97 0 97 2 + 98 0 98 2 + 99 0 99 2 + 100 0 100 2 + 101 0 101 2 + 102 0 102 2 + 103 0 103 2 + 104 0 104 2 + 105 0 105 2 + 106 0 106 2 + 107 0 107 2 + 108 0 108 2 + 109 0 109 2 + 110 0 110 2 + 111 0 111 2 + 112 0 112 2 + 113 0 113 2 + 114 0 114 2 + 115 0 115 2 + 116 0 116 2 + 117 0 117 2 + 118 0 118 2 + 119 0 119 2 + 120 0 120 2 + 121 0 121 2 + 122 0 122 2 + 123 0 123 2 + 124 0 124 2 + 125 0 125 2 + 126 0 126 2 + 127 0 127 2 +2048 0 2048 2 +2049 0 2049 2 +2050 0 2050 2 +2051 0 2051 2 +2052 0 2052 2 +2053 0 2053 2 +2054 0 2054 2 +2055 0 2055 2 +2056 0 2056 2 +2057 0 2057 2 +2058 0 2058 2 +2059 0 2059 2 +2060 0 2060 2 +2061 0 2061 2 +2062 0 2062 2 +2063 0 2063 2 +2064 0 2064 2 +2065 0 2065 2 +2066 0 2066 2 +2067 0 2067 2 +2068 0 2068 2 +2069 0 2069 2 +2070 0 2070 2 +2071 0 2071 2 +2072 0 2072 2 +2073 0 2073 2 +2074 0 2074 2 +2075 0 2075 2 +2076 0 2076 2 +2077 0 2077 2 +2078 0 2078 2 +2079 0 2079 2 +2080 0 2080 2 +2081 0 2081 2 +2082 0 2082 2 +2083 0 2083 2 +2084 0 2084 2 +2085 0 2085 2 +2086 0 2086 2 +2087 0 2087 2 +2088 0 2088 2 +2089 0 2089 2 +2090 0 2090 2 +2091 0 2091 2 +2092 0 2092 2 +2093 0 2093 2 +2094 0 2094 2 +2095 0 2095 2 +2096 0 2096 2 +2097 0 2097 2 +2098 0 2098 2 +2099 0 2099 2 +2100 0 2100 2 +2101 0 2101 2 +2102 0 2102 2 +2103 0 2103 2 +2104 0 2104 2 +2105 0 2105 2 +2106 0 2106 2 +2107 0 2107 2 +2108 0 2108 2 +2109 0 2109 2 +2110 0 2110 2 +2111 0 2111 2 +2112 0 2112 2 +2113 0 2113 2 +2114 0 2114 2 +2115 0 2115 2 +2116 0 2116 2 +2117 0 2117 2 +2118 0 2118 2 +2119 0 2119 2 +2120 0 2120 2 +2121 0 2121 2 +2122 0 2122 2 +2123 0 2123 2 +2124 0 2124 2 +2125 0 2125 2 +2126 0 2126 2 +2127 0 2127 2 +2128 0 2128 2 +2129 0 2129 2 +2130 0 2130 2 +2131 0 2131 2 +2132 0 2132 2 +2133 0 2133 2 +2134 0 2134 2 +2135 0 2135 2 +2136 0 2136 2 +2137 0 2137 2 +2138 0 2138 2 +2139 0 2139 2 +2140 0 2140 2 +2141 0 2141 2 +2142 0 2142 2 +2143 0 2143 2 +2144 0 2144 2 +2145 0 2145 2 +2146 0 2146 2 +2147 0 2147 2 +2148 0 2148 2 +2149 0 2149 2 +2150 0 2150 2 +2151 0 2151 2 +2152 0 2152 2 +2153 0 2153 2 +2154 0 2154 2 +2155 0 2155 2 +2156 0 2156 2 +2157 0 2157 2 +2158 0 2158 2 +2159 0 2159 2 +2160 0 2160 2 +2161 0 2161 2 +2162 0 2162 2 +2163 0 2163 2 +2164 0 2164 2 +2165 0 2165 2 +2166 0 2166 2 +2167 0 2167 2 +2168 0 2168 2 +2169 0 2169 2 +2170 0 2170 2 +2171 0 2171 2 +2172 0 2172 2 +2173 0 2173 2 +2174 0 2174 2 +2175 0 2175 2 + 128 11 29 0 + 129 11 29 1 + 130 11 28 0 + 131 11 28 1 + 132 10 29 0 + 133 10 29 1 + 134 10 28 0 + 135 10 28 1 + 136 8 28 1 + 137 8 28 0 + 138 8 29 1 + 139 8 29 0 + 140 9 28 1 + 141 9 28 0 + 142 9 29 1 + 143 9 29 0 + 160 3 28 0 + 161 3 28 1 + 162 3 29 0 + 163 3 29 1 + 164 2 28 0 + 165 2 28 1 + 166 2 29 0 + 167 2 29 1 + 168 0 29 1 + 169 0 29 0 + 170 0 28 1 + 171 0 28 0 + 172 1 29 1 + 173 1 29 0 + 174 1 28 1 + 175 1 28 0 + 176 4 28 0 + 177 4 28 1 + 178 4 29 0 + 179 4 29 1 + 180 5 28 0 + 181 5 28 1 + 182 5 29 0 + 183 5 29 1 + 184 7 29 1 + 185 7 29 0 + 186 7 28 1 + 187 7 28 0 + 188 6 29 1 + 189 6 29 0 + 190 6 28 1 + 191 6 28 0 + 192 12 29 0 + 193 12 29 1 + 194 12 28 0 + 195 12 28 1 + 196 13 29 0 + 197 13 29 1 + 198 13 28 0 + 199 13 28 1 + 200 15 28 1 + 201 15 28 0 + 202 15 29 1 + 203 15 29 0 + 204 14 28 1 + 205 14 28 0 + 206 14 29 1 + 207 14 29 0 + 256 11 31 0 + 257 11 31 1 + 258 11 30 0 + 259 11 30 1 + 260 10 31 0 + 261 10 31 1 + 262 10 30 0 + 263 10 30 1 + 264 8 30 1 + 265 8 30 0 + 266 8 31 1 + 267 8 31 0 + 268 9 30 1 + 269 9 30 0 + 270 9 31 1 + 271 9 31 0 + 288 3 30 0 + 289 3 30 1 + 290 3 31 0 + 291 3 31 1 + 292 2 30 0 + 293 2 30 1 + 294 2 31 0 + 295 2 31 1 + 296 0 31 1 + 297 0 31 0 + 298 0 30 1 + 299 0 30 0 + 300 1 31 1 + 301 1 31 0 + 302 1 30 1 + 303 1 30 0 + 304 4 30 0 + 305 4 30 1 + 306 4 31 0 + 307 4 31 1 + 308 5 30 0 + 309 5 30 1 + 310 5 31 0 + 311 5 31 1 + 312 7 31 1 + 313 7 31 0 + 314 7 30 1 + 315 7 30 0 + 316 6 31 1 + 317 6 31 0 + 318 6 30 1 + 319 6 30 0 + 320 12 31 0 + 321 12 31 1 + 322 12 30 0 + 323 12 30 1 + 324 13 31 0 + 325 13 31 1 + 326 13 30 0 + 327 13 30 1 + 328 15 30 1 + 329 15 30 0 + 330 15 31 1 + 331 15 31 0 + 332 14 30 1 + 333 14 30 0 + 334 14 31 1 + 335 14 31 0 + 384 11 33 0 + 385 11 33 1 + 386 11 32 0 + 387 11 32 1 + 388 10 33 0 + 389 10 33 1 + 390 10 32 0 + 391 10 32 1 + 392 8 32 1 + 393 8 32 0 + 394 8 33 1 + 395 8 33 0 + 396 9 32 1 + 397 9 32 0 + 398 9 33 1 + 399 9 33 0 + 416 3 32 0 + 417 3 32 1 + 418 3 33 0 + 419 3 33 1 + 420 2 32 0 + 421 2 32 1 + 422 2 33 0 + 423 2 33 1 + 424 0 33 1 + 425 0 33 0 + 426 0 32 1 + 427 0 32 0 + 428 1 33 1 + 429 1 33 0 + 430 1 32 1 + 431 1 32 0 + 432 4 32 0 + 433 4 32 1 + 434 4 33 0 + 435 4 33 1 + 436 5 32 0 + 437 5 32 1 + 438 5 33 0 + 439 5 33 1 + 440 7 33 1 + 441 7 33 0 + 442 7 32 1 + 443 7 32 0 + 444 6 33 1 + 445 6 33 0 + 446 6 32 1 + 447 6 32 0 + 448 12 33 0 + 449 12 33 1 + 450 12 32 0 + 451 12 32 1 + 452 13 33 0 + 453 13 33 1 + 454 13 32 0 + 455 13 32 1 + 456 15 32 1 + 457 15 32 0 + 458 15 33 1 + 459 15 33 0 + 460 14 32 1 + 461 14 32 0 + 462 14 33 1 + 463 14 33 0 + 512 11 35 0 + 513 11 35 1 + 514 11 34 0 + 515 11 34 1 + 516 10 35 0 + 517 10 35 1 + 518 10 34 0 + 519 10 34 1 + 520 8 34 1 + 521 8 34 0 + 522 8 35 1 + 523 8 35 0 + 524 9 34 1 + 525 9 34 0 + 526 9 35 1 + 527 9 35 0 + 544 3 34 0 + 545 3 34 1 + 546 3 35 0 + 547 3 35 1 + 548 2 34 0 + 549 2 34 1 + 550 2 35 0 + 551 2 35 1 + 552 0 35 1 + 553 0 35 0 + 554 0 34 1 + 555 0 34 0 + 556 1 35 1 + 557 1 35 0 + 558 1 34 1 + 559 1 34 0 + 560 4 34 0 + 561 4 34 1 + 562 4 35 0 + 563 4 35 1 + 564 5 34 0 + 565 5 34 1 + 566 5 35 0 + 567 5 35 1 + 568 7 35 1 + 569 7 35 0 + 570 7 34 1 + 571 7 34 0 + 572 6 35 1 + 573 6 35 0 + 574 6 34 1 + 575 6 34 0 + 576 12 35 0 + 577 12 35 1 + 578 12 34 0 + 579 12 34 1 + 580 13 35 0 + 581 13 35 1 + 582 13 34 0 + 583 13 34 1 + 584 15 34 1 + 585 15 34 0 + 586 15 35 1 + 587 15 35 0 + 588 14 34 1 + 589 14 34 0 + 590 14 35 1 + 591 14 35 0 + 640 11 37 0 + 641 11 37 1 + 642 11 36 0 + 643 11 36 1 + 644 10 37 0 + 645 10 37 1 + 646 10 36 0 + 647 10 36 1 + 648 8 36 1 + 649 8 36 0 + 650 8 37 1 + 651 8 37 0 + 652 9 36 1 + 653 9 36 0 + 654 9 37 1 + 655 9 37 0 + 672 3 36 0 + 673 3 36 1 + 674 3 37 0 + 675 3 37 1 + 676 2 36 0 + 677 2 36 1 + 678 2 37 0 + 679 2 37 1 + 680 0 37 1 + 681 0 37 0 + 682 0 36 1 + 683 0 36 0 + 684 1 37 1 + 685 1 37 0 + 686 1 36 1 + 687 1 36 0 + 688 4 36 0 + 689 4 36 1 + 690 4 37 0 + 691 4 37 1 + 692 5 36 0 + 693 5 36 1 + 694 5 37 0 + 695 5 37 1 + 696 7 37 1 + 697 7 37 0 + 698 7 36 1 + 699 7 36 0 + 700 6 37 1 + 701 6 37 0 + 702 6 36 1 + 703 6 36 0 + 704 12 37 0 + 705 12 37 1 + 706 12 36 0 + 707 12 36 1 + 708 13 37 0 + 709 13 37 1 + 710 13 36 0 + 711 13 36 1 + 712 15 36 1 + 713 15 36 0 + 714 15 37 1 + 715 15 37 0 + 716 14 36 1 + 717 14 36 0 + 718 14 37 1 + 719 14 37 0 + 768 11 39 0 + 769 11 39 1 + 770 11 38 0 + 771 11 38 1 + 772 10 39 0 + 773 10 39 1 + 774 10 38 0 + 775 10 38 1 + 776 8 38 1 + 777 8 38 0 + 778 8 39 1 + 779 8 39 0 + 780 9 38 1 + 781 9 38 0 + 782 9 39 1 + 783 9 39 0 + 800 3 38 0 + 801 3 38 1 + 802 3 39 0 + 803 3 39 1 + 804 2 38 0 + 805 2 38 1 + 806 2 39 0 + 807 2 39 1 + 808 0 39 1 + 809 0 39 0 + 810 0 38 1 + 811 0 38 0 + 812 1 39 1 + 813 1 39 0 + 814 1 38 1 + 815 1 38 0 + 816 4 38 0 + 817 4 38 1 + 818 4 39 0 + 819 4 39 1 + 820 5 38 0 + 821 5 38 1 + 822 5 39 0 + 823 5 39 1 + 824 7 39 1 + 825 7 39 0 + 826 7 38 1 + 827 7 38 0 + 828 6 39 1 + 829 6 39 0 + 830 6 38 1 + 831 6 38 0 + 832 12 39 0 + 833 12 39 1 + 834 12 38 0 + 835 12 38 1 + 836 13 39 0 + 837 13 39 1 + 838 13 38 0 + 839 13 38 1 + 840 15 38 1 + 841 15 38 0 + 842 15 39 1 + 843 15 39 0 + 844 14 38 1 + 845 14 38 0 + 846 14 39 1 + 847 14 39 0 + 896 11 41 0 + 897 11 41 1 + 898 11 40 0 + 899 11 40 1 + 900 10 41 0 + 901 10 41 1 + 902 10 40 0 + 903 10 40 1 + 904 8 40 1 + 905 8 40 0 + 906 8 41 1 + 907 8 41 0 + 908 9 40 1 + 909 9 40 0 + 910 9 41 1 + 911 9 41 0 + 928 3 40 0 + 929 3 40 1 + 930 3 41 0 + 931 3 41 1 + 932 2 40 0 + 933 2 40 1 + 934 2 41 0 + 935 2 41 1 + 936 0 41 1 + 937 0 41 0 + 938 0 40 1 + 939 0 40 0 + 940 1 41 1 + 941 1 41 0 + 942 1 40 1 + 943 1 40 0 + 944 4 40 0 + 945 4 40 1 + 946 4 41 0 + 947 4 41 1 + 948 5 40 0 + 949 5 40 1 + 950 5 41 0 + 951 5 41 1 + 952 7 41 1 + 953 7 41 0 + 954 7 40 1 + 955 7 40 0 + 956 6 41 1 + 957 6 41 0 + 958 6 40 1 + 959 6 40 0 + 960 12 41 0 + 961 12 41 1 + 962 12 40 0 + 963 12 40 1 + 964 13 41 0 + 965 13 41 1 + 966 13 40 0 + 967 13 40 1 + 968 15 40 1 + 969 15 40 0 + 970 15 41 1 + 971 15 41 0 + 972 14 40 1 + 973 14 40 0 + 974 14 41 1 + 975 14 41 0 +1024 11 43 0 +1025 11 43 1 +1026 11 42 0 +1027 11 42 1 +1028 10 43 0 +1029 10 43 1 +1030 10 42 0 +1031 10 42 1 +1032 8 42 1 +1033 8 42 0 +1034 8 43 1 +1035 8 43 0 +1036 9 42 1 +1037 9 42 0 +1038 9 43 1 +1039 9 43 0 +1056 3 42 0 +1057 3 42 1 +1058 3 43 0 +1059 3 43 1 +1060 2 42 0 +1061 2 42 1 +1062 2 43 0 +1063 2 43 1 +1064 0 43 1 +1065 0 43 0 +1066 0 42 1 +1067 0 42 0 +1068 1 43 1 +1069 1 43 0 +1070 1 42 1 +1071 1 42 0 +1072 4 42 0 +1073 4 42 1 +1074 4 43 0 +1075 4 43 1 +1076 5 42 0 +1077 5 42 1 +1078 5 43 0 +1079 5 43 1 +1080 7 43 1 +1081 7 43 0 +1082 7 42 1 +1083 7 42 0 +1084 6 43 1 +1085 6 43 0 +1086 6 42 1 +1087 6 42 0 +1088 12 43 0 +1089 12 43 1 +1090 12 42 0 +1091 12 42 1 +1092 13 43 0 +1093 13 43 1 +1094 13 42 0 +1095 13 42 1 +1096 15 42 1 +1097 15 42 0 +1098 15 43 1 +1099 15 43 0 +1100 14 42 1 +1101 14 42 0 +1102 14 43 1 +1103 14 43 0 +1152 11 45 0 +1153 11 45 1 +1154 11 44 0 +1155 11 44 1 +1156 10 45 0 +1157 10 45 1 +1158 10 44 0 +1159 10 44 1 +1160 8 44 1 +1161 8 44 0 +1162 8 45 1 +1163 8 45 0 +1164 9 44 1 +1165 9 44 0 +1166 9 45 1 +1167 9 45 0 +1184 3 44 0 +1185 3 44 1 +1186 3 45 0 +1187 3 45 1 +1188 2 44 0 +1189 2 44 1 +1190 2 45 0 +1191 2 45 1 +1192 0 45 1 +1193 0 45 0 +1194 0 44 1 +1195 0 44 0 +1196 1 45 1 +1197 1 45 0 +1198 1 44 1 +1199 1 44 0 +1200 4 44 0 +1201 4 44 1 +1202 4 45 0 +1203 4 45 1 +1204 5 44 0 +1205 5 44 1 +1206 5 45 0 +1207 5 45 1 +1208 7 45 1 +1209 7 45 0 +1210 7 44 1 +1211 7 44 0 +1212 6 45 1 +1213 6 45 0 +1214 6 44 1 +1215 6 44 0 +1216 12 45 0 +1217 12 45 1 +1218 12 44 0 +1219 12 44 1 +1220 13 45 0 +1221 13 45 1 +1222 13 44 0 +1223 13 44 1 +1224 15 44 1 +1225 15 44 0 +1226 15 45 1 +1227 15 45 0 +1228 14 44 1 +1229 14 44 0 +1230 14 45 1 +1231 14 45 0 +1280 11 47 0 +1281 11 47 1 +1282 11 46 0 +1283 11 46 1 +1284 10 47 0 +1285 10 47 1 +1286 10 46 0 +1287 10 46 1 +1288 8 46 1 +1289 8 46 0 +1290 8 47 1 +1291 8 47 0 +1292 9 46 1 +1293 9 46 0 +1294 9 47 1 +1295 9 47 0 +1312 3 46 0 +1313 3 46 1 +1314 3 47 0 +1315 3 47 1 +1316 2 46 0 +1317 2 46 1 +1318 2 47 0 +1319 2 47 1 +1320 0 47 1 +1321 0 47 0 +1322 0 46 1 +1323 0 46 0 +1324 1 47 1 +1325 1 47 0 +1326 1 46 1 +1327 1 46 0 +1328 4 46 0 +1329 4 46 1 +1330 4 47 0 +1331 4 47 1 +1332 5 46 0 +1333 5 46 1 +1334 5 47 0 +1335 5 47 1 +1336 7 47 1 +1337 7 47 0 +1338 7 46 1 +1339 7 46 0 +1340 6 47 1 +1341 6 47 0 +1342 6 46 1 +1343 6 46 0 +1344 12 47 0 +1345 12 47 1 +1346 12 46 0 +1347 12 46 1 +1348 13 47 0 +1349 13 47 1 +1350 13 46 0 +1351 13 46 1 +1352 15 46 1 +1353 15 46 0 +1354 15 47 1 +1355 15 47 0 +1356 14 46 1 +1357 14 46 0 +1358 14 47 1 +1359 14 47 0 +1408 11 49 0 +1409 11 49 1 +1410 11 48 0 +1411 11 48 1 +1412 10 49 0 +1413 10 49 1 +1414 10 48 0 +1415 10 48 1 +1416 8 48 1 +1417 8 48 0 +1418 8 49 1 +1419 8 49 0 +1420 9 48 1 +1421 9 48 0 +1422 9 49 1 +1423 9 49 0 +1440 3 48 0 +1441 3 48 1 +1442 3 49 0 +1443 3 49 1 +1444 2 48 0 +1445 2 48 1 +1446 2 49 0 +1447 2 49 1 +1448 0 49 1 +1449 0 49 0 +1450 0 48 1 +1451 0 48 0 +1452 1 49 1 +1453 1 49 0 +1454 1 48 1 +1455 1 48 0 +1456 4 48 0 +1457 4 48 1 +1458 4 49 0 +1459 4 49 1 +1460 5 48 0 +1461 5 48 1 +1462 5 49 0 +1463 5 49 1 +1464 7 49 1 +1465 7 49 0 +1466 7 48 1 +1467 7 48 0 +1468 6 49 1 +1469 6 49 0 +1470 6 48 1 +1471 6 48 0 +1472 12 49 0 +1473 12 49 1 +1474 12 48 0 +1475 12 48 1 +1476 13 49 0 +1477 13 49 1 +1478 13 48 0 +1479 13 48 1 +1480 15 48 1 +1481 15 48 0 +1482 15 49 1 +1483 15 49 0 +1484 14 48 1 +1485 14 48 0 +1486 14 49 1 +1487 14 49 0 +1536 11 51 0 +1537 11 51 1 +1538 11 50 0 +1539 11 50 1 +1540 10 51 0 +1541 10 51 1 +1542 10 50 0 +1543 10 50 1 +1544 8 50 1 +1545 8 50 0 +1546 8 51 1 +1547 8 51 0 +1548 9 50 1 +1549 9 50 0 +1550 9 51 1 +1551 9 51 0 +1568 3 50 0 +1569 3 50 1 +1570 3 51 0 +1571 3 51 1 +1572 2 50 0 +1573 2 50 1 +1574 2 51 0 +1575 2 51 1 +1576 0 51 1 +1577 0 51 0 +1578 0 50 1 +1579 0 50 0 +1580 1 51 1 +1581 1 51 0 +1582 1 50 1 +1583 1 50 0 +1584 4 50 0 +1585 4 50 1 +1586 4 51 0 +1587 4 51 1 +1588 5 50 0 +1589 5 50 1 +1590 5 51 0 +1591 5 51 1 +1592 7 51 1 +1593 7 51 0 +1594 7 50 1 +1595 7 50 0 +1596 6 51 1 +1597 6 51 0 +1598 6 50 1 +1599 6 50 0 +1600 12 51 0 +1601 12 51 1 +1602 12 50 0 +1603 12 50 1 +1604 13 51 0 +1605 13 51 1 +1606 13 50 0 +1607 13 50 1 +1608 15 50 1 +1609 15 50 0 +1610 15 51 1 +1611 15 51 0 +1612 14 50 1 +1613 14 50 0 +1614 14 51 1 +1615 14 51 0 +1664 11 53 0 +1665 11 53 1 +1666 11 52 0 +1667 11 52 1 +1668 10 53 0 +1669 10 53 1 +1670 10 52 0 +1671 10 52 1 +1672 8 52 1 +1673 8 52 0 +1674 8 53 1 +1675 8 53 0 +1676 9 52 1 +1677 9 52 0 +1678 9 53 1 +1679 9 53 0 +1696 3 52 0 +1697 3 52 1 +1698 3 53 0 +1699 3 53 1 +1700 2 52 0 +1701 2 52 1 +1702 2 53 0 +1703 2 53 1 +1704 0 53 1 +1705 0 53 0 +1706 0 52 1 +1707 0 52 0 +1708 1 53 1 +1709 1 53 0 +1710 1 52 1 +1711 1 52 0 +1712 4 52 0 +1713 4 52 1 +1714 4 53 0 +1715 4 53 1 +1716 5 52 0 +1717 5 52 1 +1718 5 53 0 +1719 5 53 1 +1720 7 53 1 +1721 7 53 0 +1722 7 52 1 +1723 7 52 0 +1724 6 53 1 +1725 6 53 0 +1726 6 52 1 +1727 6 52 0 +1728 12 53 0 +1729 12 53 1 +1730 12 52 0 +1731 12 52 1 +1732 13 53 0 +1733 13 53 1 +1734 13 52 0 +1735 13 52 1 +1736 15 52 1 +1737 15 52 0 +1738 15 53 1 +1739 15 53 0 +1740 14 52 1 +1741 14 52 0 +1742 14 53 1 +1743 14 53 0 +1792 11 55 0 +1793 11 55 1 +1794 11 54 0 +1795 11 54 1 +1796 10 55 0 +1797 10 55 1 +1798 10 54 0 +1799 10 54 1 +1800 8 54 1 +1801 8 54 0 +1802 8 55 1 +1803 8 55 0 +1804 9 54 1 +1805 9 54 0 +1806 9 55 1 +1807 9 55 0 +1824 3 54 0 +1825 3 54 1 +1826 3 55 0 +1827 3 55 1 +1828 2 54 0 +1829 2 54 1 +1830 2 55 0 +1831 2 55 1 +1832 0 55 1 +1833 0 55 0 +1834 0 54 1 +1835 0 54 0 +1836 1 55 1 +1837 1 55 0 +1838 1 54 1 +1839 1 54 0 +1840 4 54 0 +1841 4 54 1 +1842 4 55 0 +1843 4 55 1 +1844 5 54 0 +1845 5 54 1 +1846 5 55 0 +1847 5 55 1 +1848 7 55 1 +1849 7 55 0 +1850 7 54 1 +1851 7 54 0 +1852 6 55 1 +1853 6 55 0 +1854 6 54 1 +1855 6 54 0 +1856 12 55 0 +1857 12 55 1 +1858 12 54 0 +1859 12 54 1 +1860 13 55 0 +1861 13 55 1 +1862 13 54 0 +1863 13 54 1 +1864 15 54 1 +1865 15 54 0 +1866 15 55 1 +1867 15 55 0 +1868 14 54 1 +1869 14 54 0 +1870 14 55 1 +1871 14 55 0 +2176 11 27 0 +2177 11 27 1 +2178 11 26 0 +2179 11 26 1 +2180 10 27 0 +2181 10 27 1 +2182 10 26 0 +2183 10 26 1 +2184 8 26 1 +2185 8 26 0 +2186 8 27 1 +2187 8 27 0 +2188 9 26 1 +2189 9 26 0 +2190 9 27 1 +2191 9 27 0 +2208 3 26 0 +2209 3 26 1 +2210 3 27 0 +2211 3 27 1 +2212 2 26 0 +2213 2 26 1 +2214 2 27 0 +2215 2 27 1 +2216 0 27 1 +2217 0 27 0 +2218 0 26 1 +2219 0 26 0 +2220 1 27 1 +2221 1 27 0 +2222 1 26 1 +2223 1 26 0 +2224 4 26 0 +2225 4 26 1 +2226 4 27 0 +2227 4 27 1 +2228 5 26 0 +2229 5 26 1 +2230 5 27 0 +2231 5 27 1 +2232 7 27 1 +2233 7 27 0 +2234 7 26 1 +2235 7 26 0 +2236 6 27 1 +2237 6 27 0 +2238 6 26 1 +2239 6 26 0 +2240 12 27 0 +2241 12 27 1 +2242 12 26 0 +2243 12 26 1 +2244 13 27 0 +2245 13 27 1 +2246 13 26 0 +2247 13 26 1 +2248 15 26 1 +2249 15 26 0 +2250 15 27 1 +2251 15 27 0 +2252 14 26 1 +2253 14 26 0 +2254 14 27 1 +2255 14 27 0 +2304 11 25 0 +2305 11 25 1 +2306 11 24 0 +2307 11 24 1 +2308 10 25 0 +2309 10 25 1 +2310 10 24 0 +2311 10 24 1 +2312 8 24 1 +2313 8 24 0 +2314 8 25 1 +2315 8 25 0 +2316 9 24 1 +2317 9 24 0 +2318 9 25 1 +2319 9 25 0 +2336 3 24 0 +2337 3 24 1 +2338 3 25 0 +2339 3 25 1 +2340 2 24 0 +2341 2 24 1 +2342 2 25 0 +2343 2 25 1 +2344 0 25 1 +2345 0 25 0 +2346 0 24 1 +2347 0 24 0 +2348 1 25 1 +2349 1 25 0 +2350 1 24 1 +2351 1 24 0 +2352 4 24 0 +2353 4 24 1 +2354 4 25 0 +2355 4 25 1 +2356 5 24 0 +2357 5 24 1 +2358 5 25 0 +2359 5 25 1 +2360 7 25 1 +2361 7 25 0 +2362 7 24 1 +2363 7 24 0 +2364 6 25 1 +2365 6 25 0 +2366 6 24 1 +2367 6 24 0 +2368 12 25 0 +2369 12 25 1 +2370 12 24 0 +2371 12 24 1 +2372 13 25 0 +2373 13 25 1 +2374 13 24 0 +2375 13 24 1 +2376 15 24 1 +2377 15 24 0 +2378 15 25 1 +2379 15 25 0 +2380 14 24 1 +2381 14 24 0 +2382 14 25 1 +2383 14 25 0 +2432 11 23 0 +2433 11 23 1 +2434 11 22 0 +2435 11 22 1 +2436 10 23 0 +2437 10 23 1 +2438 10 22 0 +2439 10 22 1 +2440 8 22 1 +2441 8 22 0 +2442 8 23 1 +2443 8 23 0 +2444 9 22 1 +2445 9 22 0 +2446 9 23 1 +2447 9 23 0 +2464 3 22 0 +2465 3 22 1 +2466 3 23 0 +2467 3 23 1 +2468 2 22 0 +2469 2 22 1 +2470 2 23 0 +2471 2 23 1 +2472 0 23 1 +2473 0 23 0 +2474 0 22 1 +2475 0 22 0 +2476 1 23 1 +2477 1 23 0 +2478 1 22 1 +2479 1 22 0 +2480 4 22 0 +2481 4 22 1 +2482 4 23 0 +2483 4 23 1 +2484 5 22 0 +2485 5 22 1 +2486 5 23 0 +2487 5 23 1 +2488 7 23 1 +2489 7 23 0 +2490 7 22 1 +2491 7 22 0 +2492 6 23 1 +2493 6 23 0 +2494 6 22 1 +2495 6 22 0 +2496 12 23 0 +2497 12 23 1 +2498 12 22 0 +2499 12 22 1 +2500 13 23 0 +2501 13 23 1 +2502 13 22 0 +2503 13 22 1 +2504 15 22 1 +2505 15 22 0 +2506 15 23 1 +2507 15 23 0 +2508 14 22 1 +2509 14 22 0 +2510 14 23 1 +2511 14 23 0 +2560 11 21 0 +2561 11 21 1 +2562 11 20 0 +2563 11 20 1 +2564 10 21 0 +2565 10 21 1 +2566 10 20 0 +2567 10 20 1 +2568 8 20 1 +2569 8 20 0 +2570 8 21 1 +2571 8 21 0 +2572 9 20 1 +2573 9 20 0 +2574 9 21 1 +2575 9 21 0 +2592 3 20 0 +2593 3 20 1 +2594 3 21 0 +2595 3 21 1 +2596 2 20 0 +2597 2 20 1 +2598 2 21 0 +2599 2 21 1 +2600 0 21 1 +2601 0 21 0 +2602 0 20 1 +2603 0 20 0 +2604 1 21 1 +2605 1 21 0 +2606 1 20 1 +2607 1 20 0 +2608 4 20 0 +2609 4 20 1 +2610 4 21 0 +2611 4 21 1 +2612 5 20 0 +2613 5 20 1 +2614 5 21 0 +2615 5 21 1 +2616 7 21 1 +2617 7 21 0 +2618 7 20 1 +2619 7 20 0 +2620 6 21 1 +2621 6 21 0 +2622 6 20 1 +2623 6 20 0 +2624 12 21 0 +2625 12 21 1 +2626 12 20 0 +2627 12 20 1 +2628 13 21 0 +2629 13 21 1 +2630 13 20 0 +2631 13 20 1 +2632 15 20 1 +2633 15 20 0 +2634 15 21 1 +2635 15 21 0 +2636 14 20 1 +2637 14 20 0 +2638 14 21 1 +2639 14 21 0 +2688 11 19 0 +2689 11 19 1 +2690 11 18 0 +2691 11 18 1 +2692 10 19 0 +2693 10 19 1 +2694 10 18 0 +2695 10 18 1 +2696 8 18 1 +2697 8 18 0 +2698 8 19 1 +2699 8 19 0 +2700 9 18 1 +2701 9 18 0 +2702 9 19 1 +2703 9 19 0 +2720 3 18 0 +2721 3 18 1 +2722 3 19 0 +2723 3 19 1 +2724 2 18 0 +2725 2 18 1 +2726 2 19 0 +2727 2 19 1 +2728 0 19 1 +2729 0 19 0 +2730 0 18 1 +2731 0 18 0 +2732 1 19 1 +2733 1 19 0 +2734 1 18 1 +2735 1 18 0 +2736 4 18 0 +2737 4 18 1 +2738 4 19 0 +2739 4 19 1 +2740 5 18 0 +2741 5 18 1 +2742 5 19 0 +2743 5 19 1 +2744 7 19 1 +2745 7 19 0 +2746 7 18 1 +2747 7 18 0 +2748 6 19 1 +2749 6 19 0 +2750 6 18 1 +2751 6 18 0 +2752 12 19 0 +2753 12 19 1 +2754 12 18 0 +2755 12 18 1 +2756 13 19 0 +2757 13 19 1 +2758 13 18 0 +2759 13 18 1 +2760 15 18 1 +2761 15 18 0 +2762 15 19 1 +2763 15 19 0 +2764 14 18 1 +2765 14 18 0 +2766 14 19 1 +2767 14 19 0 +2816 11 17 0 +2817 11 17 1 +2818 11 16 0 +2819 11 16 1 +2820 10 17 0 +2821 10 17 1 +2822 10 16 0 +2823 10 16 1 +2824 8 16 1 +2825 8 16 0 +2826 8 17 1 +2827 8 17 0 +2828 9 16 1 +2829 9 16 0 +2830 9 17 1 +2831 9 17 0 +2848 3 16 0 +2849 3 16 1 +2850 3 17 0 +2851 3 17 1 +2852 2 16 0 +2853 2 16 1 +2854 2 17 0 +2855 2 17 1 +2856 0 17 1 +2857 0 17 0 +2858 0 16 1 +2859 0 16 0 +2860 1 17 1 +2861 1 17 0 +2862 1 16 1 +2863 1 16 0 +2864 4 16 0 +2865 4 16 1 +2866 4 17 0 +2867 4 17 1 +2868 5 16 0 +2869 5 16 1 +2870 5 17 0 +2871 5 17 1 +2872 7 17 1 +2873 7 17 0 +2874 7 16 1 +2875 7 16 0 +2876 6 17 1 +2877 6 17 0 +2878 6 16 1 +2879 6 16 0 +2880 12 17 0 +2881 12 17 1 +2882 12 16 0 +2883 12 16 1 +2884 13 17 0 +2885 13 17 1 +2886 13 16 0 +2887 13 16 1 +2888 15 16 1 +2889 15 16 0 +2890 15 17 1 +2891 15 17 0 +2892 14 16 1 +2893 14 16 0 +2894 14 17 1 +2895 14 17 0 +2944 11 15 0 +2945 11 15 1 +2946 11 14 0 +2947 11 14 1 +2948 10 15 0 +2949 10 15 1 +2950 10 14 0 +2951 10 14 1 +2952 8 14 1 +2953 8 14 0 +2954 8 15 1 +2955 8 15 0 +2956 9 14 1 +2957 9 14 0 +2958 9 15 1 +2959 9 15 0 +2976 3 14 0 +2977 3 14 1 +2978 3 15 0 +2979 3 15 1 +2980 2 14 0 +2981 2 14 1 +2982 2 15 0 +2983 2 15 1 +2984 0 15 1 +2985 0 15 0 +2986 0 14 1 +2987 0 14 0 +2988 1 15 1 +2989 1 15 0 +2990 1 14 1 +2991 1 14 0 +2992 4 14 0 +2993 4 14 1 +2994 4 15 0 +2995 4 15 1 +2996 5 14 0 +2997 5 14 1 +2998 5 15 0 +2999 5 15 1 +3000 7 15 1 +3001 7 15 0 +3002 7 14 1 +3003 7 14 0 +3004 6 15 1 +3005 6 15 0 +3006 6 14 1 +3007 6 14 0 +3008 12 15 0 +3009 12 15 1 +3010 12 14 0 +3011 12 14 1 +3012 13 15 0 +3013 13 15 1 +3014 13 14 0 +3015 13 14 1 +3016 15 14 1 +3017 15 14 0 +3018 15 15 1 +3019 15 15 0 +3020 14 14 1 +3021 14 14 0 +3022 14 15 1 +3023 14 15 0 +3072 11 13 0 +3073 11 13 1 +3074 11 12 0 +3075 11 12 1 +3076 10 13 0 +3077 10 13 1 +3078 10 12 0 +3079 10 12 1 +3080 8 12 1 +3081 8 12 0 +3082 8 13 1 +3083 8 13 0 +3084 9 12 1 +3085 9 12 0 +3086 9 13 1 +3087 9 13 0 +3104 3 12 0 +3105 3 12 1 +3106 3 13 0 +3107 3 13 1 +3108 2 12 0 +3109 2 12 1 +3110 2 13 0 +3111 2 13 1 +3112 0 13 1 +3113 0 13 0 +3114 0 12 1 +3115 0 12 0 +3116 1 13 1 +3117 1 13 0 +3118 1 12 1 +3119 1 12 0 +3120 4 12 0 +3121 4 12 1 +3122 4 13 0 +3123 4 13 1 +3124 5 12 0 +3125 5 12 1 +3126 5 13 0 +3127 5 13 1 +3128 7 13 1 +3129 7 13 0 +3130 7 12 1 +3131 7 12 0 +3132 6 13 1 +3133 6 13 0 +3134 6 12 1 +3135 6 12 0 +3136 12 13 0 +3137 12 13 1 +3138 12 12 0 +3139 12 12 1 +3140 13 13 0 +3141 13 13 1 +3142 13 12 0 +3143 13 12 1 +3144 15 12 1 +3145 15 12 0 +3146 15 13 1 +3147 15 13 0 +3148 14 12 1 +3149 14 12 0 +3150 14 13 1 +3151 14 13 0 +3200 11 11 0 +3201 11 11 1 +3202 11 10 0 +3203 11 10 1 +3204 10 11 0 +3205 10 11 1 +3206 10 10 0 +3207 10 10 1 +3208 8 10 1 +3209 8 10 0 +3210 8 11 1 +3211 8 11 0 +3212 9 10 1 +3213 9 10 0 +3214 9 11 1 +3215 9 11 0 +3232 3 10 0 +3233 3 10 1 +3234 3 11 0 +3235 3 11 1 +3236 2 10 0 +3237 2 10 1 +3238 2 11 0 +3239 2 11 1 +3240 0 11 1 +3241 0 11 0 +3242 0 10 1 +3243 0 10 0 +3244 1 11 1 +3245 1 11 0 +3246 1 10 1 +3247 1 10 0 +3248 4 10 0 +3249 4 10 1 +3250 4 11 0 +3251 4 11 1 +3252 5 10 0 +3253 5 10 1 +3254 5 11 0 +3255 5 11 1 +3256 7 11 1 +3257 7 11 0 +3258 7 10 1 +3259 7 10 0 +3260 6 11 1 +3261 6 11 0 +3262 6 10 1 +3263 6 10 0 +3264 12 11 0 +3265 12 11 1 +3266 12 10 0 +3267 12 10 1 +3268 13 11 0 +3269 13 11 1 +3270 13 10 0 +3271 13 10 1 +3272 15 10 1 +3273 15 10 0 +3274 15 11 1 +3275 15 11 0 +3276 14 10 1 +3277 14 10 0 +3278 14 11 1 +3279 14 11 0 +3328 11 9 0 +3329 11 9 1 +3330 11 8 0 +3331 11 8 1 +3332 10 9 0 +3333 10 9 1 +3334 10 8 0 +3335 10 8 1 +3336 8 8 1 +3337 8 8 0 +3338 8 9 1 +3339 8 9 0 +3340 9 8 1 +3341 9 8 0 +3342 9 9 1 +3343 9 9 0 +3360 3 8 0 +3361 3 8 1 +3362 3 9 0 +3363 3 9 1 +3364 2 8 0 +3365 2 8 1 +3366 2 9 0 +3367 2 9 1 +3368 0 9 1 +3369 0 9 0 +3370 0 8 1 +3371 0 8 0 +3372 1 9 1 +3373 1 9 0 +3374 1 8 1 +3375 1 8 0 +3376 4 8 0 +3377 4 8 1 +3378 4 9 0 +3379 4 9 1 +3380 5 8 0 +3381 5 8 1 +3382 5 9 0 +3383 5 9 1 +3384 7 9 1 +3385 7 9 0 +3386 7 8 1 +3387 7 8 0 +3388 6 9 1 +3389 6 9 0 +3390 6 8 1 +3391 6 8 0 +3392 12 9 0 +3393 12 9 1 +3394 12 8 0 +3395 12 8 1 +3396 13 9 0 +3397 13 9 1 +3398 13 8 0 +3399 13 8 1 +3400 15 8 1 +3401 15 8 0 +3402 15 9 1 +3403 15 9 0 +3404 14 8 1 +3405 14 8 0 +3406 14 9 1 +3407 14 9 0 +3456 11 7 0 +3457 11 7 1 +3458 11 6 0 +3459 11 6 1 +3460 10 7 0 +3461 10 7 1 +3462 10 6 0 +3463 10 6 1 +3464 8 6 1 +3465 8 6 0 +3466 8 7 1 +3467 8 7 0 +3468 9 6 1 +3469 9 6 0 +3470 9 7 1 +3471 9 7 0 +3488 3 6 0 +3489 3 6 1 +3490 3 7 0 +3491 3 7 1 +3492 2 6 0 +3493 2 6 1 +3494 2 7 0 +3495 2 7 1 +3496 0 7 1 +3497 0 7 0 +3498 0 6 1 +3499 0 6 0 +3500 1 7 1 +3501 1 7 0 +3502 1 6 1 +3503 1 6 0 +3504 4 6 0 +3505 4 6 1 +3506 4 7 0 +3507 4 7 1 +3508 5 6 0 +3509 5 6 1 +3510 5 7 0 +3511 5 7 1 +3512 7 7 1 +3513 7 7 0 +3514 7 6 1 +3515 7 6 0 +3516 6 7 1 +3517 6 7 0 +3518 6 6 1 +3519 6 6 0 +3520 12 7 0 +3521 12 7 1 +3522 12 6 0 +3523 12 6 1 +3524 13 7 0 +3525 13 7 1 +3526 13 6 0 +3527 13 6 1 +3528 15 6 1 +3529 15 6 0 +3530 15 7 1 +3531 15 7 0 +3532 14 6 1 +3533 14 6 0 +3534 14 7 1 +3535 14 7 0 +3584 11 5 0 +3585 11 5 1 +3586 11 4 0 +3587 11 4 1 +3588 10 5 0 +3589 10 5 1 +3590 10 4 0 +3591 10 4 1 +3592 8 4 1 +3593 8 4 0 +3594 8 5 1 +3595 8 5 0 +3596 9 4 1 +3597 9 4 0 +3598 9 5 1 +3599 9 5 0 +3616 3 4 0 +3617 3 4 1 +3618 3 5 0 +3619 3 5 1 +3620 2 4 0 +3621 2 4 1 +3622 2 5 0 +3623 2 5 1 +3624 0 5 1 +3625 0 5 0 +3626 0 4 1 +3627 0 4 0 +3628 1 5 1 +3629 1 5 0 +3630 1 4 1 +3631 1 4 0 +3632 4 4 0 +3633 4 4 1 +3634 4 5 0 +3635 4 5 1 +3636 5 4 0 +3637 5 4 1 +3638 5 5 0 +3639 5 5 1 +3640 7 5 1 +3641 7 5 0 +3642 7 4 1 +3643 7 4 0 +3644 6 5 1 +3645 6 5 0 +3646 6 4 1 +3647 6 4 0 +3648 12 5 0 +3649 12 5 1 +3650 12 4 0 +3651 12 4 1 +3652 13 5 0 +3653 13 5 1 +3654 13 4 0 +3655 13 4 1 +3656 15 4 1 +3657 15 4 0 +3658 15 5 1 +3659 15 5 0 +3660 14 4 1 +3661 14 4 0 +3662 14 5 1 +3663 14 5 0 +3712 11 3 0 +3713 11 3 1 +3714 11 2 0 +3715 11 2 1 +3716 10 3 0 +3717 10 3 1 +3718 10 2 0 +3719 10 2 1 +3720 8 2 1 +3721 8 2 0 +3722 8 3 1 +3723 8 3 0 +3724 9 2 1 +3725 9 2 0 +3726 9 3 1 +3727 9 3 0 +3744 3 2 0 +3745 3 2 1 +3746 3 3 0 +3747 3 3 1 +3748 2 2 0 +3749 2 2 1 +3750 2 3 0 +3751 2 3 1 +3752 0 3 1 +3753 0 3 0 +3754 0 2 1 +3755 0 2 0 +3756 1 3 1 +3757 1 3 0 +3758 1 2 1 +3759 1 2 0 +3760 4 2 0 +3761 4 2 1 +3762 4 3 0 +3763 4 3 1 +3764 5 2 0 +3765 5 2 1 +3766 5 3 0 +3767 5 3 1 +3768 7 3 1 +3769 7 3 0 +3770 7 2 1 +3771 7 2 0 +3772 6 3 1 +3773 6 3 0 +3774 6 2 1 +3775 6 2 0 +3776 12 3 0 +3777 12 3 1 +3778 12 2 0 +3779 12 2 1 +3780 13 3 0 +3781 13 3 1 +3782 13 2 0 +3783 13 2 1 +3784 15 2 1 +3785 15 2 0 +3786 15 3 1 +3787 15 3 0 +3788 14 2 1 +3789 14 2 0 +3790 14 3 1 +3791 14 3 0 +3840 11 1 0 +3841 11 1 1 +3842 11 0 0 +3843 11 0 1 +3844 10 1 0 +3845 10 1 1 +3846 10 0 0 +3847 10 0 1 +3848 8 0 1 +3849 8 0 0 +3850 8 1 1 +3851 8 1 0 +3852 9 0 1 +3853 9 0 0 +3854 9 1 1 +3855 9 1 0 +3872 3 0 0 +3873 3 0 1 +3874 3 1 0 +3875 3 1 1 +3876 2 0 0 +3877 2 0 1 +3878 2 1 0 +3879 2 1 1 +3880 0 1 1 +3881 0 1 0 +3882 0 0 1 +3883 0 0 0 +3884 1 1 1 +3885 1 1 0 +3886 1 0 1 +3887 1 0 0 +3888 4 0 0 +3889 4 0 1 +3890 4 1 0 +3891 4 1 1 +3892 5 0 0 +3893 5 0 1 +3894 5 1 0 +3895 5 1 1 +3896 7 1 1 +3897 7 1 0 +3898 7 0 1 +3899 7 0 0 +3900 6 1 1 +3901 6 1 0 +3902 6 0 1 +3903 6 0 0 +3904 12 1 0 +3905 12 1 1 +3906 12 0 0 +3907 12 0 1 +3908 13 1 0 +3909 13 1 1 +3910 13 0 0 +3911 13 0 1 +3912 15 0 1 +3913 15 0 0 +3914 15 1 1 +3915 15 1 0 +3916 14 0 1 +3917 14 0 0 +3918 14 1 1 +3919 14 1 0 diff --git a/Detectors/PHOS/base/files/Mod3RCU1.data b/Detectors/PHOS/base/files/Mod3RCU1.data new file mode 100644 index 0000000000000..db125226496cf --- /dev/null +++ b/Detectors/PHOS/base/files/Mod3RCU1.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 1 0 2 + 1 1 1 2 + 2 1 2 2 + 3 1 3 2 + 4 1 4 2 + 5 1 5 2 + 6 1 6 2 + 7 1 7 2 + 8 1 8 2 + 9 1 9 2 + 10 1 10 2 + 11 1 11 2 + 12 1 12 2 + 13 1 13 2 + 14 1 14 2 + 15 1 15 2 + 16 1 16 2 + 17 1 17 2 + 18 1 18 2 + 19 1 19 2 + 20 1 20 2 + 21 1 21 2 + 22 1 22 2 + 23 1 23 2 + 24 1 24 2 + 25 1 25 2 + 26 1 26 2 + 27 1 27 2 + 28 1 28 2 + 29 1 29 2 + 30 1 30 2 + 31 1 31 2 + 32 1 32 2 + 33 1 33 2 + 34 1 34 2 + 35 1 35 2 + 36 1 36 2 + 37 1 37 2 + 38 1 38 2 + 39 1 39 2 + 40 1 40 2 + 41 1 41 2 + 42 1 42 2 + 43 1 43 2 + 44 1 44 2 + 45 1 45 2 + 46 1 46 2 + 47 1 47 2 + 48 1 48 2 + 49 1 49 2 + 50 1 50 2 + 51 1 51 2 + 52 1 52 2 + 53 1 53 2 + 54 1 54 2 + 55 1 55 2 + 56 1 56 2 + 57 1 57 2 + 58 1 58 2 + 59 1 59 2 + 60 1 60 2 + 61 1 61 2 + 62 1 62 2 + 63 1 63 2 + 64 1 64 2 + 65 1 65 2 + 66 1 66 2 + 67 1 67 2 + 68 1 68 2 + 69 1 69 2 + 70 1 70 2 + 71 1 71 2 + 72 1 72 2 + 73 1 73 2 + 74 1 74 2 + 75 1 75 2 + 76 1 76 2 + 77 1 77 2 + 78 1 78 2 + 79 1 79 2 + 80 1 80 2 + 81 1 81 2 + 82 1 82 2 + 83 1 83 2 + 84 1 84 2 + 85 1 85 2 + 86 1 86 2 + 87 1 87 2 + 88 1 88 2 + 89 1 89 2 + 90 1 90 2 + 91 1 91 2 + 92 1 92 2 + 93 1 93 2 + 94 1 94 2 + 95 1 95 2 + 96 1 96 2 + 97 1 97 2 + 98 1 98 2 + 99 1 99 2 + 100 1 100 2 + 101 1 101 2 + 102 1 102 2 + 103 1 103 2 + 104 1 104 2 + 105 1 105 2 + 106 1 106 2 + 107 1 107 2 + 108 1 108 2 + 109 1 109 2 + 110 1 110 2 + 111 1 111 2 + 112 1 112 2 + 113 1 113 2 + 114 1 114 2 + 115 1 115 2 + 116 1 116 2 + 117 1 117 2 + 118 1 118 2 + 119 1 119 2 + 120 1 120 2 + 121 1 121 2 + 122 1 122 2 + 123 1 123 2 + 124 1 124 2 + 125 1 125 2 + 126 1 126 2 + 127 1 127 2 +2048 1 2048 2 +2049 1 2049 2 +2050 1 2050 2 +2051 1 2051 2 +2052 1 2052 2 +2053 1 2053 2 +2054 1 2054 2 +2055 1 2055 2 +2056 1 2056 2 +2057 1 2057 2 +2058 1 2058 2 +2059 1 2059 2 +2060 1 2060 2 +2061 1 2061 2 +2062 1 2062 2 +2063 1 2063 2 +2064 1 2064 2 +2065 1 2065 2 +2066 1 2066 2 +2067 1 2067 2 +2068 1 2068 2 +2069 1 2069 2 +2070 1 2070 2 +2071 1 2071 2 +2072 1 2072 2 +2073 1 2073 2 +2074 1 2074 2 +2075 1 2075 2 +2076 1 2076 2 +2077 1 2077 2 +2078 1 2078 2 +2079 1 2079 2 +2080 1 2080 2 +2081 1 2081 2 +2082 1 2082 2 +2083 1 2083 2 +2084 1 2084 2 +2085 1 2085 2 +2086 1 2086 2 +2087 1 2087 2 +2088 1 2088 2 +2089 1 2089 2 +2090 1 2090 2 +2091 1 2091 2 +2092 1 2092 2 +2093 1 2093 2 +2094 1 2094 2 +2095 1 2095 2 +2096 1 2096 2 +2097 1 2097 2 +2098 1 2098 2 +2099 1 2099 2 +2100 1 2100 2 +2101 1 2101 2 +2102 1 2102 2 +2103 1 2103 2 +2104 1 2104 2 +2105 1 2105 2 +2106 1 2106 2 +2107 1 2107 2 +2108 1 2108 2 +2109 1 2109 2 +2110 1 2110 2 +2111 1 2111 2 +2112 1 2112 2 +2113 1 2113 2 +2114 1 2114 2 +2115 1 2115 2 +2116 1 2116 2 +2117 1 2117 2 +2118 1 2118 2 +2119 1 2119 2 +2120 1 2120 2 +2121 1 2121 2 +2122 1 2122 2 +2123 1 2123 2 +2124 1 2124 2 +2125 1 2125 2 +2126 1 2126 2 +2127 1 2127 2 +2128 1 2128 2 +2129 1 2129 2 +2130 1 2130 2 +2131 1 2131 2 +2132 1 2132 2 +2133 1 2133 2 +2134 1 2134 2 +2135 1 2135 2 +2136 1 2136 2 +2137 1 2137 2 +2138 1 2138 2 +2139 1 2139 2 +2140 1 2140 2 +2141 1 2141 2 +2142 1 2142 2 +2143 1 2143 2 +2144 1 2144 2 +2145 1 2145 2 +2146 1 2146 2 +2147 1 2147 2 +2148 1 2148 2 +2149 1 2149 2 +2150 1 2150 2 +2151 1 2151 2 +2152 1 2152 2 +2153 1 2153 2 +2154 1 2154 2 +2155 1 2155 2 +2156 1 2156 2 +2157 1 2157 2 +2158 1 2158 2 +2159 1 2159 2 +2160 1 2160 2 +2161 1 2161 2 +2162 1 2162 2 +2163 1 2163 2 +2164 1 2164 2 +2165 1 2165 2 +2166 1 2166 2 +2167 1 2167 2 +2168 1 2168 2 +2169 1 2169 2 +2170 1 2170 2 +2171 1 2171 2 +2172 1 2172 2 +2173 1 2173 2 +2174 1 2174 2 +2175 1 2175 2 + 128 27 29 0 + 129 27 29 1 + 130 27 28 0 + 131 27 28 1 + 132 26 29 0 + 133 26 29 1 + 134 26 28 0 + 135 26 28 1 + 136 24 28 1 + 137 24 28 0 + 138 24 29 1 + 139 24 29 0 + 140 25 28 1 + 141 25 28 0 + 142 25 29 1 + 143 25 29 0 + 160 19 28 0 + 161 19 28 1 + 162 19 29 0 + 163 19 29 1 + 164 18 28 0 + 165 18 28 1 + 166 18 29 0 + 167 18 29 1 + 168 16 29 1 + 169 16 29 0 + 170 16 28 1 + 171 16 28 0 + 172 17 29 1 + 173 17 29 0 + 174 17 28 1 + 175 17 28 0 + 176 20 28 0 + 177 20 28 1 + 178 20 29 0 + 179 20 29 1 + 180 21 28 0 + 181 21 28 1 + 182 21 29 0 + 183 21 29 1 + 184 23 29 1 + 185 23 29 0 + 186 23 28 1 + 187 23 28 0 + 188 22 29 1 + 189 22 29 0 + 190 22 28 1 + 191 22 28 0 + 192 28 29 0 + 193 28 29 1 + 194 28 28 0 + 195 28 28 1 + 196 29 29 0 + 197 29 29 1 + 198 29 28 0 + 199 29 28 1 + 200 31 28 1 + 201 31 28 0 + 202 31 29 1 + 203 31 29 0 + 204 30 28 1 + 205 30 28 0 + 206 30 29 1 + 207 30 29 0 + 256 27 31 0 + 257 27 31 1 + 258 27 30 0 + 259 27 30 1 + 260 26 31 0 + 261 26 31 1 + 262 26 30 0 + 263 26 30 1 + 264 24 30 1 + 265 24 30 0 + 266 24 31 1 + 267 24 31 0 + 268 25 30 1 + 269 25 30 0 + 270 25 31 1 + 271 25 31 0 + 288 19 30 0 + 289 19 30 1 + 290 19 31 0 + 291 19 31 1 + 292 18 30 0 + 293 18 30 1 + 294 18 31 0 + 295 18 31 1 + 296 16 31 1 + 297 16 31 0 + 298 16 30 1 + 299 16 30 0 + 300 17 31 1 + 301 17 31 0 + 302 17 30 1 + 303 17 30 0 + 304 20 30 0 + 305 20 30 1 + 306 20 31 0 + 307 20 31 1 + 308 21 30 0 + 309 21 30 1 + 310 21 31 0 + 311 21 31 1 + 312 23 31 1 + 313 23 31 0 + 314 23 30 1 + 315 23 30 0 + 316 22 31 1 + 317 22 31 0 + 318 22 30 1 + 319 22 30 0 + 320 28 31 0 + 321 28 31 1 + 322 28 30 0 + 323 28 30 1 + 324 29 31 0 + 325 29 31 1 + 326 29 30 0 + 327 29 30 1 + 328 31 30 1 + 329 31 30 0 + 330 31 31 1 + 331 31 31 0 + 332 30 30 1 + 333 30 30 0 + 334 30 31 1 + 335 30 31 0 + 384 27 33 0 + 385 27 33 1 + 386 27 32 0 + 387 27 32 1 + 388 26 33 0 + 389 26 33 1 + 390 26 32 0 + 391 26 32 1 + 392 24 32 1 + 393 24 32 0 + 394 24 33 1 + 395 24 33 0 + 396 25 32 1 + 397 25 32 0 + 398 25 33 1 + 399 25 33 0 + 416 19 32 0 + 417 19 32 1 + 418 19 33 0 + 419 19 33 1 + 420 18 32 0 + 421 18 32 1 + 422 18 33 0 + 423 18 33 1 + 424 16 33 1 + 425 16 33 0 + 426 16 32 1 + 427 16 32 0 + 428 17 33 1 + 429 17 33 0 + 430 17 32 1 + 431 17 32 0 + 432 20 32 0 + 433 20 32 1 + 434 20 33 0 + 435 20 33 1 + 436 21 32 0 + 437 21 32 1 + 438 21 33 0 + 439 21 33 1 + 440 23 33 1 + 441 23 33 0 + 442 23 32 1 + 443 23 32 0 + 444 22 33 1 + 445 22 33 0 + 446 22 32 1 + 447 22 32 0 + 448 28 33 0 + 449 28 33 1 + 450 28 32 0 + 451 28 32 1 + 452 29 33 0 + 453 29 33 1 + 454 29 32 0 + 455 29 32 1 + 456 31 32 1 + 457 31 32 0 + 458 31 33 1 + 459 31 33 0 + 460 30 32 1 + 461 30 32 0 + 462 30 33 1 + 463 30 33 0 + 512 27 35 0 + 513 27 35 1 + 514 27 34 0 + 515 27 34 1 + 516 26 35 0 + 517 26 35 1 + 518 26 34 0 + 519 26 34 1 + 520 24 34 1 + 521 24 34 0 + 522 24 35 1 + 523 24 35 0 + 524 25 34 1 + 525 25 34 0 + 526 25 35 1 + 527 25 35 0 + 544 19 34 0 + 545 19 34 1 + 546 19 35 0 + 547 19 35 1 + 548 18 34 0 + 549 18 34 1 + 550 18 35 0 + 551 18 35 1 + 552 16 35 1 + 553 16 35 0 + 554 16 34 1 + 555 16 34 0 + 556 17 35 1 + 557 17 35 0 + 558 17 34 1 + 559 17 34 0 + 560 20 34 0 + 561 20 34 1 + 562 20 35 0 + 563 20 35 1 + 564 21 34 0 + 565 21 34 1 + 566 21 35 0 + 567 21 35 1 + 568 23 35 1 + 569 23 35 0 + 570 23 34 1 + 571 23 34 0 + 572 22 35 1 + 573 22 35 0 + 574 22 34 1 + 575 22 34 0 + 576 28 35 0 + 577 28 35 1 + 578 28 34 0 + 579 28 34 1 + 580 29 35 0 + 581 29 35 1 + 582 29 34 0 + 583 29 34 1 + 584 31 34 1 + 585 31 34 0 + 586 31 35 1 + 587 31 35 0 + 588 30 34 1 + 589 30 34 0 + 590 30 35 1 + 591 30 35 0 + 640 27 37 0 + 641 27 37 1 + 642 27 36 0 + 643 27 36 1 + 644 26 37 0 + 645 26 37 1 + 646 26 36 0 + 647 26 36 1 + 648 24 36 1 + 649 24 36 0 + 650 24 37 1 + 651 24 37 0 + 652 25 36 1 + 653 25 36 0 + 654 25 37 1 + 655 25 37 0 + 672 19 36 0 + 673 19 36 1 + 674 19 37 0 + 675 19 37 1 + 676 18 36 0 + 677 18 36 1 + 678 18 37 0 + 679 18 37 1 + 680 16 37 1 + 681 16 37 0 + 682 16 36 1 + 683 16 36 0 + 684 17 37 1 + 685 17 37 0 + 686 17 36 1 + 687 17 36 0 + 688 20 36 0 + 689 20 36 1 + 690 20 37 0 + 691 20 37 1 + 692 21 36 0 + 693 21 36 1 + 694 21 37 0 + 695 21 37 1 + 696 23 37 1 + 697 23 37 0 + 698 23 36 1 + 699 23 36 0 + 700 22 37 1 + 701 22 37 0 + 702 22 36 1 + 703 22 36 0 + 704 28 37 0 + 705 28 37 1 + 706 28 36 0 + 707 28 36 1 + 708 29 37 0 + 709 29 37 1 + 710 29 36 0 + 711 29 36 1 + 712 31 36 1 + 713 31 36 0 + 714 31 37 1 + 715 31 37 0 + 716 30 36 1 + 717 30 36 0 + 718 30 37 1 + 719 30 37 0 + 768 27 39 0 + 769 27 39 1 + 770 27 38 0 + 771 27 38 1 + 772 26 39 0 + 773 26 39 1 + 774 26 38 0 + 775 26 38 1 + 776 24 38 1 + 777 24 38 0 + 778 24 39 1 + 779 24 39 0 + 780 25 38 1 + 781 25 38 0 + 782 25 39 1 + 783 25 39 0 + 800 19 38 0 + 801 19 38 1 + 802 19 39 0 + 803 19 39 1 + 804 18 38 0 + 805 18 38 1 + 806 18 39 0 + 807 18 39 1 + 808 16 39 1 + 809 16 39 0 + 810 16 38 1 + 811 16 38 0 + 812 17 39 1 + 813 17 39 0 + 814 17 38 1 + 815 17 38 0 + 816 20 38 0 + 817 20 38 1 + 818 20 39 0 + 819 20 39 1 + 820 21 38 0 + 821 21 38 1 + 822 21 39 0 + 823 21 39 1 + 824 23 39 1 + 825 23 39 0 + 826 23 38 1 + 827 23 38 0 + 828 22 39 1 + 829 22 39 0 + 830 22 38 1 + 831 22 38 0 + 832 28 39 0 + 833 28 39 1 + 834 28 38 0 + 835 28 38 1 + 836 29 39 0 + 837 29 39 1 + 838 29 38 0 + 839 29 38 1 + 840 31 38 1 + 841 31 38 0 + 842 31 39 1 + 843 31 39 0 + 844 30 38 1 + 845 30 38 0 + 846 30 39 1 + 847 30 39 0 + 896 27 41 0 + 897 27 41 1 + 898 27 40 0 + 899 27 40 1 + 900 26 41 0 + 901 26 41 1 + 902 26 40 0 + 903 26 40 1 + 904 24 40 1 + 905 24 40 0 + 906 24 41 1 + 907 24 41 0 + 908 25 40 1 + 909 25 40 0 + 910 25 41 1 + 911 25 41 0 + 928 19 40 0 + 929 19 40 1 + 930 19 41 0 + 931 19 41 1 + 932 18 40 0 + 933 18 40 1 + 934 18 41 0 + 935 18 41 1 + 936 16 41 1 + 937 16 41 0 + 938 16 40 1 + 939 16 40 0 + 940 17 41 1 + 941 17 41 0 + 942 17 40 1 + 943 17 40 0 + 944 20 40 0 + 945 20 40 1 + 946 20 41 0 + 947 20 41 1 + 948 21 40 0 + 949 21 40 1 + 950 21 41 0 + 951 21 41 1 + 952 23 41 1 + 953 23 41 0 + 954 23 40 1 + 955 23 40 0 + 956 22 41 1 + 957 22 41 0 + 958 22 40 1 + 959 22 40 0 + 960 28 41 0 + 961 28 41 1 + 962 28 40 0 + 963 28 40 1 + 964 29 41 0 + 965 29 41 1 + 966 29 40 0 + 967 29 40 1 + 968 31 40 1 + 969 31 40 0 + 970 31 41 1 + 971 31 41 0 + 972 30 40 1 + 973 30 40 0 + 974 30 41 1 + 975 30 41 0 +1024 27 43 0 +1025 27 43 1 +1026 27 42 0 +1027 27 42 1 +1028 26 43 0 +1029 26 43 1 +1030 26 42 0 +1031 26 42 1 +1032 24 42 1 +1033 24 42 0 +1034 24 43 1 +1035 24 43 0 +1036 25 42 1 +1037 25 42 0 +1038 25 43 1 +1039 25 43 0 +1056 19 42 0 +1057 19 42 1 +1058 19 43 0 +1059 19 43 1 +1060 18 42 0 +1061 18 42 1 +1062 18 43 0 +1063 18 43 1 +1064 16 43 1 +1065 16 43 0 +1066 16 42 1 +1067 16 42 0 +1068 17 43 1 +1069 17 43 0 +1070 17 42 1 +1071 17 42 0 +1072 20 42 0 +1073 20 42 1 +1074 20 43 0 +1075 20 43 1 +1076 21 42 0 +1077 21 42 1 +1078 21 43 0 +1079 21 43 1 +1080 23 43 1 +1081 23 43 0 +1082 23 42 1 +1083 23 42 0 +1084 22 43 1 +1085 22 43 0 +1086 22 42 1 +1087 22 42 0 +1088 28 43 0 +1089 28 43 1 +1090 28 42 0 +1091 28 42 1 +1092 29 43 0 +1093 29 43 1 +1094 29 42 0 +1095 29 42 1 +1096 31 42 1 +1097 31 42 0 +1098 31 43 1 +1099 31 43 0 +1100 30 42 1 +1101 30 42 0 +1102 30 43 1 +1103 30 43 0 +1152 27 45 0 +1153 27 45 1 +1154 27 44 0 +1155 27 44 1 +1156 26 45 0 +1157 26 45 1 +1158 26 44 0 +1159 26 44 1 +1160 24 44 1 +1161 24 44 0 +1162 24 45 1 +1163 24 45 0 +1164 25 44 1 +1165 25 44 0 +1166 25 45 1 +1167 25 45 0 +1184 19 44 0 +1185 19 44 1 +1186 19 45 0 +1187 19 45 1 +1188 18 44 0 +1189 18 44 1 +1190 18 45 0 +1191 18 45 1 +1192 16 45 1 +1193 16 45 0 +1194 16 44 1 +1195 16 44 0 +1196 17 45 1 +1197 17 45 0 +1198 17 44 1 +1199 17 44 0 +1200 20 44 0 +1201 20 44 1 +1202 20 45 0 +1203 20 45 1 +1204 21 44 0 +1205 21 44 1 +1206 21 45 0 +1207 21 45 1 +1208 23 45 1 +1209 23 45 0 +1210 23 44 1 +1211 23 44 0 +1212 22 45 1 +1213 22 45 0 +1214 22 44 1 +1215 22 44 0 +1216 28 45 0 +1217 28 45 1 +1218 28 44 0 +1219 28 44 1 +1220 29 45 0 +1221 29 45 1 +1222 29 44 0 +1223 29 44 1 +1224 31 44 1 +1225 31 44 0 +1226 31 45 1 +1227 31 45 0 +1228 30 44 1 +1229 30 44 0 +1230 30 45 1 +1231 30 45 0 +1280 27 47 0 +1281 27 47 1 +1282 27 46 0 +1283 27 46 1 +1284 26 47 0 +1285 26 47 1 +1286 26 46 0 +1287 26 46 1 +1288 24 46 1 +1289 24 46 0 +1290 24 47 1 +1291 24 47 0 +1292 25 46 1 +1293 25 46 0 +1294 25 47 1 +1295 25 47 0 +1312 19 46 0 +1313 19 46 1 +1314 19 47 0 +1315 19 47 1 +1316 18 46 0 +1317 18 46 1 +1318 18 47 0 +1319 18 47 1 +1320 16 47 1 +1321 16 47 0 +1322 16 46 1 +1323 16 46 0 +1324 17 47 1 +1325 17 47 0 +1326 17 46 1 +1327 17 46 0 +1328 20 46 0 +1329 20 46 1 +1330 20 47 0 +1331 20 47 1 +1332 21 46 0 +1333 21 46 1 +1334 21 47 0 +1335 21 47 1 +1336 23 47 1 +1337 23 47 0 +1338 23 46 1 +1339 23 46 0 +1340 22 47 1 +1341 22 47 0 +1342 22 46 1 +1343 22 46 0 +1344 28 47 0 +1345 28 47 1 +1346 28 46 0 +1347 28 46 1 +1348 29 47 0 +1349 29 47 1 +1350 29 46 0 +1351 29 46 1 +1352 31 46 1 +1353 31 46 0 +1354 31 47 1 +1355 31 47 0 +1356 30 46 1 +1357 30 46 0 +1358 30 47 1 +1359 30 47 0 +1408 27 49 0 +1409 27 49 1 +1410 27 48 0 +1411 27 48 1 +1412 26 49 0 +1413 26 49 1 +1414 26 48 0 +1415 26 48 1 +1416 24 48 1 +1417 24 48 0 +1418 24 49 1 +1419 24 49 0 +1420 25 48 1 +1421 25 48 0 +1422 25 49 1 +1423 25 49 0 +1440 19 48 0 +1441 19 48 1 +1442 19 49 0 +1443 19 49 1 +1444 18 48 0 +1445 18 48 1 +1446 18 49 0 +1447 18 49 1 +1448 16 49 1 +1449 16 49 0 +1450 16 48 1 +1451 16 48 0 +1452 17 49 1 +1453 17 49 0 +1454 17 48 1 +1455 17 48 0 +1456 20 48 0 +1457 20 48 1 +1458 20 49 0 +1459 20 49 1 +1460 21 48 0 +1461 21 48 1 +1462 21 49 0 +1463 21 49 1 +1464 23 49 1 +1465 23 49 0 +1466 23 48 1 +1467 23 48 0 +1468 22 49 1 +1469 22 49 0 +1470 22 48 1 +1471 22 48 0 +1472 28 49 0 +1473 28 49 1 +1474 28 48 0 +1475 28 48 1 +1476 29 49 0 +1477 29 49 1 +1478 29 48 0 +1479 29 48 1 +1480 31 48 1 +1481 31 48 0 +1482 31 49 1 +1483 31 49 0 +1484 30 48 1 +1485 30 48 0 +1486 30 49 1 +1487 30 49 0 +1536 27 51 0 +1537 27 51 1 +1538 27 50 0 +1539 27 50 1 +1540 26 51 0 +1541 26 51 1 +1542 26 50 0 +1543 26 50 1 +1544 24 50 1 +1545 24 50 0 +1546 24 51 1 +1547 24 51 0 +1548 25 50 1 +1549 25 50 0 +1550 25 51 1 +1551 25 51 0 +1568 19 50 0 +1569 19 50 1 +1570 19 51 0 +1571 19 51 1 +1572 18 50 0 +1573 18 50 1 +1574 18 51 0 +1575 18 51 1 +1576 16 51 1 +1577 16 51 0 +1578 16 50 1 +1579 16 50 0 +1580 17 51 1 +1581 17 51 0 +1582 17 50 1 +1583 17 50 0 +1584 20 50 0 +1585 20 50 1 +1586 20 51 0 +1587 20 51 1 +1588 21 50 0 +1589 21 50 1 +1590 21 51 0 +1591 21 51 1 +1592 23 51 1 +1593 23 51 0 +1594 23 50 1 +1595 23 50 0 +1596 22 51 1 +1597 22 51 0 +1598 22 50 1 +1599 22 50 0 +1600 28 51 0 +1601 28 51 1 +1602 28 50 0 +1603 28 50 1 +1604 29 51 0 +1605 29 51 1 +1606 29 50 0 +1607 29 50 1 +1608 31 50 1 +1609 31 50 0 +1610 31 51 1 +1611 31 51 0 +1612 30 50 1 +1613 30 50 0 +1614 30 51 1 +1615 30 51 0 +1664 27 53 0 +1665 27 53 1 +1666 27 52 0 +1667 27 52 1 +1668 26 53 0 +1669 26 53 1 +1670 26 52 0 +1671 26 52 1 +1672 24 52 1 +1673 24 52 0 +1674 24 53 1 +1675 24 53 0 +1676 25 52 1 +1677 25 52 0 +1678 25 53 1 +1679 25 53 0 +1696 19 52 0 +1697 19 52 1 +1698 19 53 0 +1699 19 53 1 +1700 18 52 0 +1701 18 52 1 +1702 18 53 0 +1703 18 53 1 +1704 16 53 1 +1705 16 53 0 +1706 16 52 1 +1707 16 52 0 +1708 17 53 1 +1709 17 53 0 +1710 17 52 1 +1711 17 52 0 +1712 20 52 0 +1713 20 52 1 +1714 20 53 0 +1715 20 53 1 +1716 21 52 0 +1717 21 52 1 +1718 21 53 0 +1719 21 53 1 +1720 23 53 1 +1721 23 53 0 +1722 23 52 1 +1723 23 52 0 +1724 22 53 1 +1725 22 53 0 +1726 22 52 1 +1727 22 52 0 +1728 28 53 0 +1729 28 53 1 +1730 28 52 0 +1731 28 52 1 +1732 29 53 0 +1733 29 53 1 +1734 29 52 0 +1735 29 52 1 +1736 31 52 1 +1737 31 52 0 +1738 31 53 1 +1739 31 53 0 +1740 30 52 1 +1741 30 52 0 +1742 30 53 1 +1743 30 53 0 +1792 27 55 0 +1793 27 55 1 +1794 27 54 0 +1795 27 54 1 +1796 26 55 0 +1797 26 55 1 +1798 26 54 0 +1799 26 54 1 +1800 24 54 1 +1801 24 54 0 +1802 24 55 1 +1803 24 55 0 +1804 25 54 1 +1805 25 54 0 +1806 25 55 1 +1807 25 55 0 +1824 19 54 0 +1825 19 54 1 +1826 19 55 0 +1827 19 55 1 +1828 18 54 0 +1829 18 54 1 +1830 18 55 0 +1831 18 55 1 +1832 16 55 1 +1833 16 55 0 +1834 16 54 1 +1835 16 54 0 +1836 17 55 1 +1837 17 55 0 +1838 17 54 1 +1839 17 54 0 +1840 20 54 0 +1841 20 54 1 +1842 20 55 0 +1843 20 55 1 +1844 21 54 0 +1845 21 54 1 +1846 21 55 0 +1847 21 55 1 +1848 23 55 1 +1849 23 55 0 +1850 23 54 1 +1851 23 54 0 +1852 22 55 1 +1853 22 55 0 +1854 22 54 1 +1855 22 54 0 +1856 28 55 0 +1857 28 55 1 +1858 28 54 0 +1859 28 54 1 +1860 29 55 0 +1861 29 55 1 +1862 29 54 0 +1863 29 54 1 +1864 31 54 1 +1865 31 54 0 +1866 31 55 1 +1867 31 55 0 +1868 30 54 1 +1869 30 54 0 +1870 30 55 1 +1871 30 55 0 +2176 27 27 0 +2177 27 27 1 +2178 27 26 0 +2179 27 26 1 +2180 26 27 0 +2181 26 27 1 +2182 26 26 0 +2183 26 26 1 +2184 24 26 1 +2185 24 26 0 +2186 24 27 1 +2187 24 27 0 +2188 25 26 1 +2189 25 26 0 +2190 25 27 1 +2191 25 27 0 +2208 19 26 0 +2209 19 26 1 +2210 19 27 0 +2211 19 27 1 +2212 18 26 0 +2213 18 26 1 +2214 18 27 0 +2215 18 27 1 +2216 16 27 1 +2217 16 27 0 +2218 16 26 1 +2219 16 26 0 +2220 17 27 1 +2221 17 27 0 +2222 17 26 1 +2223 17 26 0 +2224 20 26 0 +2225 20 26 1 +2226 20 27 0 +2227 20 27 1 +2228 21 26 0 +2229 21 26 1 +2230 21 27 0 +2231 21 27 1 +2232 23 27 1 +2233 23 27 0 +2234 23 26 1 +2235 23 26 0 +2236 22 27 1 +2237 22 27 0 +2238 22 26 1 +2239 22 26 0 +2240 28 27 0 +2241 28 27 1 +2242 28 26 0 +2243 28 26 1 +2244 29 27 0 +2245 29 27 1 +2246 29 26 0 +2247 29 26 1 +2248 31 26 1 +2249 31 26 0 +2250 31 27 1 +2251 31 27 0 +2252 30 26 1 +2253 30 26 0 +2254 30 27 1 +2255 30 27 0 +2304 27 25 0 +2305 27 25 1 +2306 27 24 0 +2307 27 24 1 +2308 26 25 0 +2309 26 25 1 +2310 26 24 0 +2311 26 24 1 +2312 24 24 1 +2313 24 24 0 +2314 24 25 1 +2315 24 25 0 +2316 25 24 1 +2317 25 24 0 +2318 25 25 1 +2319 25 25 0 +2336 19 24 0 +2337 19 24 1 +2338 19 25 0 +2339 19 25 1 +2340 18 24 0 +2341 18 24 1 +2342 18 25 0 +2343 18 25 1 +2344 16 25 1 +2345 16 25 0 +2346 16 24 1 +2347 16 24 0 +2348 17 25 1 +2349 17 25 0 +2350 17 24 1 +2351 17 24 0 +2352 20 24 0 +2353 20 24 1 +2354 20 25 0 +2355 20 25 1 +2356 21 24 0 +2357 21 24 1 +2358 21 25 0 +2359 21 25 1 +2360 23 25 1 +2361 23 25 0 +2362 23 24 1 +2363 23 24 0 +2364 22 25 1 +2365 22 25 0 +2366 22 24 1 +2367 22 24 0 +2368 28 25 0 +2369 28 25 1 +2370 28 24 0 +2371 28 24 1 +2372 29 25 0 +2373 29 25 1 +2374 29 24 0 +2375 29 24 1 +2376 31 24 1 +2377 31 24 0 +2378 31 25 1 +2379 31 25 0 +2380 30 24 1 +2381 30 24 0 +2382 30 25 1 +2383 30 25 0 +2432 27 23 0 +2433 27 23 1 +2434 27 22 0 +2435 27 22 1 +2436 26 23 0 +2437 26 23 1 +2438 26 22 0 +2439 26 22 1 +2440 24 22 1 +2441 24 22 0 +2442 24 23 1 +2443 24 23 0 +2444 25 22 1 +2445 25 22 0 +2446 25 23 1 +2447 25 23 0 +2464 19 22 0 +2465 19 22 1 +2466 19 23 0 +2467 19 23 1 +2468 18 22 0 +2469 18 22 1 +2470 18 23 0 +2471 18 23 1 +2472 16 23 1 +2473 16 23 0 +2474 16 22 1 +2475 16 22 0 +2476 17 23 1 +2477 17 23 0 +2478 17 22 1 +2479 17 22 0 +2480 20 22 0 +2481 20 22 1 +2482 20 23 0 +2483 20 23 1 +2484 21 22 0 +2485 21 22 1 +2486 21 23 0 +2487 21 23 1 +2488 23 23 1 +2489 23 23 0 +2490 23 22 1 +2491 23 22 0 +2492 22 23 1 +2493 22 23 0 +2494 22 22 1 +2495 22 22 0 +2496 28 23 0 +2497 28 23 1 +2498 28 22 0 +2499 28 22 1 +2500 29 23 0 +2501 29 23 1 +2502 29 22 0 +2503 29 22 1 +2504 31 22 1 +2505 31 22 0 +2506 31 23 1 +2507 31 23 0 +2508 30 22 1 +2509 30 22 0 +2510 30 23 1 +2511 30 23 0 +2560 27 21 0 +2561 27 21 1 +2562 27 20 0 +2563 27 20 1 +2564 26 21 0 +2565 26 21 1 +2566 26 20 0 +2567 26 20 1 +2568 24 20 1 +2569 24 20 0 +2570 24 21 1 +2571 24 21 0 +2572 25 20 1 +2573 25 20 0 +2574 25 21 1 +2575 25 21 0 +2592 19 20 0 +2593 19 20 1 +2594 19 21 0 +2595 19 21 1 +2596 18 20 0 +2597 18 20 1 +2598 18 21 0 +2599 18 21 1 +2600 16 21 1 +2601 16 21 0 +2602 16 20 1 +2603 16 20 0 +2604 17 21 1 +2605 17 21 0 +2606 17 20 1 +2607 17 20 0 +2608 20 20 0 +2609 20 20 1 +2610 20 21 0 +2611 20 21 1 +2612 21 20 0 +2613 21 20 1 +2614 21 21 0 +2615 21 21 1 +2616 23 21 1 +2617 23 21 0 +2618 23 20 1 +2619 23 20 0 +2620 22 21 1 +2621 22 21 0 +2622 22 20 1 +2623 22 20 0 +2624 28 21 0 +2625 28 21 1 +2626 28 20 0 +2627 28 20 1 +2628 29 21 0 +2629 29 21 1 +2630 29 20 0 +2631 29 20 1 +2632 31 20 1 +2633 31 20 0 +2634 31 21 1 +2635 31 21 0 +2636 30 20 1 +2637 30 20 0 +2638 30 21 1 +2639 30 21 0 +2688 27 19 0 +2689 27 19 1 +2690 27 18 0 +2691 27 18 1 +2692 26 19 0 +2693 26 19 1 +2694 26 18 0 +2695 26 18 1 +2696 24 18 1 +2697 24 18 0 +2698 24 19 1 +2699 24 19 0 +2700 25 18 1 +2701 25 18 0 +2702 25 19 1 +2703 25 19 0 +2720 19 18 0 +2721 19 18 1 +2722 19 19 0 +2723 19 19 1 +2724 18 18 0 +2725 18 18 1 +2726 18 19 0 +2727 18 19 1 +2728 16 19 1 +2729 16 19 0 +2730 16 18 1 +2731 16 18 0 +2732 17 19 1 +2733 17 19 0 +2734 17 18 1 +2735 17 18 0 +2736 20 18 0 +2737 20 18 1 +2738 20 19 0 +2739 20 19 1 +2740 21 18 0 +2741 21 18 1 +2742 21 19 0 +2743 21 19 1 +2744 23 19 1 +2745 23 19 0 +2746 23 18 1 +2747 23 18 0 +2748 22 19 1 +2749 22 19 0 +2750 22 18 1 +2751 22 18 0 +2752 28 19 0 +2753 28 19 1 +2754 28 18 0 +2755 28 18 1 +2756 29 19 0 +2757 29 19 1 +2758 29 18 0 +2759 29 18 1 +2760 31 18 1 +2761 31 18 0 +2762 31 19 1 +2763 31 19 0 +2764 30 18 1 +2765 30 18 0 +2766 30 19 1 +2767 30 19 0 +2816 27 17 0 +2817 27 17 1 +2818 27 16 0 +2819 27 16 1 +2820 26 17 0 +2821 26 17 1 +2822 26 16 0 +2823 26 16 1 +2824 24 16 1 +2825 24 16 0 +2826 24 17 1 +2827 24 17 0 +2828 25 16 1 +2829 25 16 0 +2830 25 17 1 +2831 25 17 0 +2848 19 16 0 +2849 19 16 1 +2850 19 17 0 +2851 19 17 1 +2852 18 16 0 +2853 18 16 1 +2854 18 17 0 +2855 18 17 1 +2856 16 17 1 +2857 16 17 0 +2858 16 16 1 +2859 16 16 0 +2860 17 17 1 +2861 17 17 0 +2862 17 16 1 +2863 17 16 0 +2864 20 16 0 +2865 20 16 1 +2866 20 17 0 +2867 20 17 1 +2868 21 16 0 +2869 21 16 1 +2870 21 17 0 +2871 21 17 1 +2872 23 17 1 +2873 23 17 0 +2874 23 16 1 +2875 23 16 0 +2876 22 17 1 +2877 22 17 0 +2878 22 16 1 +2879 22 16 0 +2880 28 17 0 +2881 28 17 1 +2882 28 16 0 +2883 28 16 1 +2884 29 17 0 +2885 29 17 1 +2886 29 16 0 +2887 29 16 1 +2888 31 16 1 +2889 31 16 0 +2890 31 17 1 +2891 31 17 0 +2892 30 16 1 +2893 30 16 0 +2894 30 17 1 +2895 30 17 0 +2944 27 15 0 +2945 27 15 1 +2946 27 14 0 +2947 27 14 1 +2948 26 15 0 +2949 26 15 1 +2950 26 14 0 +2951 26 14 1 +2952 24 14 1 +2953 24 14 0 +2954 24 15 1 +2955 24 15 0 +2956 25 14 1 +2957 25 14 0 +2958 25 15 1 +2959 25 15 0 +2976 19 14 0 +2977 19 14 1 +2978 19 15 0 +2979 19 15 1 +2980 18 14 0 +2981 18 14 1 +2982 18 15 0 +2983 18 15 1 +2984 16 15 1 +2985 16 15 0 +2986 16 14 1 +2987 16 14 0 +2988 17 15 1 +2989 17 15 0 +2990 17 14 1 +2991 17 14 0 +2992 20 14 0 +2993 20 14 1 +2994 20 15 0 +2995 20 15 1 +2996 21 14 0 +2997 21 14 1 +2998 21 15 0 +2999 21 15 1 +3000 23 15 1 +3001 23 15 0 +3002 23 14 1 +3003 23 14 0 +3004 22 15 1 +3005 22 15 0 +3006 22 14 1 +3007 22 14 0 +3008 28 15 0 +3009 28 15 1 +3010 28 14 0 +3011 28 14 1 +3012 29 15 0 +3013 29 15 1 +3014 29 14 0 +3015 29 14 1 +3016 31 14 1 +3017 31 14 0 +3018 31 15 1 +3019 31 15 0 +3020 30 14 1 +3021 30 14 0 +3022 30 15 1 +3023 30 15 0 +3072 27 13 0 +3073 27 13 1 +3074 27 12 0 +3075 27 12 1 +3076 26 13 0 +3077 26 13 1 +3078 26 12 0 +3079 26 12 1 +3080 24 12 1 +3081 24 12 0 +3082 24 13 1 +3083 24 13 0 +3084 25 12 1 +3085 25 12 0 +3086 25 13 1 +3087 25 13 0 +3104 19 12 0 +3105 19 12 1 +3106 19 13 0 +3107 19 13 1 +3108 18 12 0 +3109 18 12 1 +3110 18 13 0 +3111 18 13 1 +3112 16 13 1 +3113 16 13 0 +3114 16 12 1 +3115 16 12 0 +3116 17 13 1 +3117 17 13 0 +3118 17 12 1 +3119 17 12 0 +3120 20 12 0 +3121 20 12 1 +3122 20 13 0 +3123 20 13 1 +3124 21 12 0 +3125 21 12 1 +3126 21 13 0 +3127 21 13 1 +3128 23 13 1 +3129 23 13 0 +3130 23 12 1 +3131 23 12 0 +3132 22 13 1 +3133 22 13 0 +3134 22 12 1 +3135 22 12 0 +3136 28 13 0 +3137 28 13 1 +3138 28 12 0 +3139 28 12 1 +3140 29 13 0 +3141 29 13 1 +3142 29 12 0 +3143 29 12 1 +3144 31 12 1 +3145 31 12 0 +3146 31 13 1 +3147 31 13 0 +3148 30 12 1 +3149 30 12 0 +3150 30 13 1 +3151 30 13 0 +3200 27 11 0 +3201 27 11 1 +3202 27 10 0 +3203 27 10 1 +3204 26 11 0 +3205 26 11 1 +3206 26 10 0 +3207 26 10 1 +3208 24 10 1 +3209 24 10 0 +3210 24 11 1 +3211 24 11 0 +3212 25 10 1 +3213 25 10 0 +3214 25 11 1 +3215 25 11 0 +3232 19 10 0 +3233 19 10 1 +3234 19 11 0 +3235 19 11 1 +3236 18 10 0 +3237 18 10 1 +3238 18 11 0 +3239 18 11 1 +3240 16 11 1 +3241 16 11 0 +3242 16 10 1 +3243 16 10 0 +3244 17 11 1 +3245 17 11 0 +3246 17 10 1 +3247 17 10 0 +3248 20 10 0 +3249 20 10 1 +3250 20 11 0 +3251 20 11 1 +3252 21 10 0 +3253 21 10 1 +3254 21 11 0 +3255 21 11 1 +3256 23 11 1 +3257 23 11 0 +3258 23 10 1 +3259 23 10 0 +3260 22 11 1 +3261 22 11 0 +3262 22 10 1 +3263 22 10 0 +3264 28 11 0 +3265 28 11 1 +3266 28 10 0 +3267 28 10 1 +3268 29 11 0 +3269 29 11 1 +3270 29 10 0 +3271 29 10 1 +3272 31 10 1 +3273 31 10 0 +3274 31 11 1 +3275 31 11 0 +3276 30 10 1 +3277 30 10 0 +3278 30 11 1 +3279 30 11 0 +3328 27 9 0 +3329 27 9 1 +3330 27 8 0 +3331 27 8 1 +3332 26 9 0 +3333 26 9 1 +3334 26 8 0 +3335 26 8 1 +3336 24 8 1 +3337 24 8 0 +3338 24 9 1 +3339 24 9 0 +3340 25 8 1 +3341 25 8 0 +3342 25 9 1 +3343 25 9 0 +3360 19 8 0 +3361 19 8 1 +3362 19 9 0 +3363 19 9 1 +3364 18 8 0 +3365 18 8 1 +3366 18 9 0 +3367 18 9 1 +3368 16 9 1 +3369 16 9 0 +3370 16 8 1 +3371 16 8 0 +3372 17 9 1 +3373 17 9 0 +3374 17 8 1 +3375 17 8 0 +3376 20 8 0 +3377 20 8 1 +3378 20 9 0 +3379 20 9 1 +3380 21 8 0 +3381 21 8 1 +3382 21 9 0 +3383 21 9 1 +3384 23 9 1 +3385 23 9 0 +3386 23 8 1 +3387 23 8 0 +3388 22 9 1 +3389 22 9 0 +3390 22 8 1 +3391 22 8 0 +3392 28 9 0 +3393 28 9 1 +3394 28 8 0 +3395 28 8 1 +3396 29 9 0 +3397 29 9 1 +3398 29 8 0 +3399 29 8 1 +3400 31 8 1 +3401 31 8 0 +3402 31 9 1 +3403 31 9 0 +3404 30 8 1 +3405 30 8 0 +3406 30 9 1 +3407 30 9 0 +3456 27 7 0 +3457 27 7 1 +3458 27 6 0 +3459 27 6 1 +3460 26 7 0 +3461 26 7 1 +3462 26 6 0 +3463 26 6 1 +3464 24 6 1 +3465 24 6 0 +3466 24 7 1 +3467 24 7 0 +3468 25 6 1 +3469 25 6 0 +3470 25 7 1 +3471 25 7 0 +3488 19 6 0 +3489 19 6 1 +3490 19 7 0 +3491 19 7 1 +3492 18 6 0 +3493 18 6 1 +3494 18 7 0 +3495 18 7 1 +3496 16 7 1 +3497 16 7 0 +3498 16 6 1 +3499 16 6 0 +3500 17 7 1 +3501 17 7 0 +3502 17 6 1 +3503 17 6 0 +3504 20 6 0 +3505 20 6 1 +3506 20 7 0 +3507 20 7 1 +3508 21 6 0 +3509 21 6 1 +3510 21 7 0 +3511 21 7 1 +3512 23 7 1 +3513 23 7 0 +3514 23 6 1 +3515 23 6 0 +3516 22 7 1 +3517 22 7 0 +3518 22 6 1 +3519 22 6 0 +3520 28 7 0 +3521 28 7 1 +3522 28 6 0 +3523 28 6 1 +3524 29 7 0 +3525 29 7 1 +3526 29 6 0 +3527 29 6 1 +3528 31 6 1 +3529 31 6 0 +3530 31 7 1 +3531 31 7 0 +3532 30 6 1 +3533 30 6 0 +3534 30 7 1 +3535 30 7 0 +3584 27 5 0 +3585 27 5 1 +3586 27 4 0 +3587 27 4 1 +3588 26 5 0 +3589 26 5 1 +3590 26 4 0 +3591 26 4 1 +3592 24 4 1 +3593 24 4 0 +3594 24 5 1 +3595 24 5 0 +3596 25 4 1 +3597 25 4 0 +3598 25 5 1 +3599 25 5 0 +3616 19 4 0 +3617 19 4 1 +3618 19 5 0 +3619 19 5 1 +3620 18 4 0 +3621 18 4 1 +3622 18 5 0 +3623 18 5 1 +3624 16 5 1 +3625 16 5 0 +3626 16 4 1 +3627 16 4 0 +3628 17 5 1 +3629 17 5 0 +3630 17 4 1 +3631 17 4 0 +3632 20 4 0 +3633 20 4 1 +3634 20 5 0 +3635 20 5 1 +3636 21 4 0 +3637 21 4 1 +3638 21 5 0 +3639 21 5 1 +3640 23 5 1 +3641 23 5 0 +3642 23 4 1 +3643 23 4 0 +3644 22 5 1 +3645 22 5 0 +3646 22 4 1 +3647 22 4 0 +3648 28 5 0 +3649 28 5 1 +3650 28 4 0 +3651 28 4 1 +3652 29 5 0 +3653 29 5 1 +3654 29 4 0 +3655 29 4 1 +3656 31 4 1 +3657 31 4 0 +3658 31 5 1 +3659 31 5 0 +3660 30 4 1 +3661 30 4 0 +3662 30 5 1 +3663 30 5 0 +3712 27 3 0 +3713 27 3 1 +3714 27 2 0 +3715 27 2 1 +3716 26 3 0 +3717 26 3 1 +3718 26 2 0 +3719 26 2 1 +3720 24 2 1 +3721 24 2 0 +3722 24 3 1 +3723 24 3 0 +3724 25 2 1 +3725 25 2 0 +3726 25 3 1 +3727 25 3 0 +3744 19 2 0 +3745 19 2 1 +3746 19 3 0 +3747 19 3 1 +3748 18 2 0 +3749 18 2 1 +3750 18 3 0 +3751 18 3 1 +3752 16 3 1 +3753 16 3 0 +3754 16 2 1 +3755 16 2 0 +3756 17 3 1 +3757 17 3 0 +3758 17 2 1 +3759 17 2 0 +3760 20 2 0 +3761 20 2 1 +3762 20 3 0 +3763 20 3 1 +3764 21 2 0 +3765 21 2 1 +3766 21 3 0 +3767 21 3 1 +3768 23 3 1 +3769 23 3 0 +3770 23 2 1 +3771 23 2 0 +3772 22 3 1 +3773 22 3 0 +3774 22 2 1 +3775 22 2 0 +3776 28 3 0 +3777 28 3 1 +3778 28 2 0 +3779 28 2 1 +3780 29 3 0 +3781 29 3 1 +3782 29 2 0 +3783 29 2 1 +3784 31 2 1 +3785 31 2 0 +3786 31 3 1 +3787 31 3 0 +3788 30 2 1 +3789 30 2 0 +3790 30 3 1 +3791 30 3 0 +3840 27 1 0 +3841 27 1 1 +3842 27 0 0 +3843 27 0 1 +3844 26 1 0 +3845 26 1 1 +3846 26 0 0 +3847 26 0 1 +3848 24 0 1 +3849 24 0 0 +3850 24 1 1 +3851 24 1 0 +3852 25 0 1 +3853 25 0 0 +3854 25 1 1 +3855 25 1 0 +3872 19 0 0 +3873 19 0 1 +3874 19 1 0 +3875 19 1 1 +3876 18 0 0 +3877 18 0 1 +3878 18 1 0 +3879 18 1 1 +3880 16 1 1 +3881 16 1 0 +3882 16 0 1 +3883 16 0 0 +3884 17 1 1 +3885 17 1 0 +3886 17 0 1 +3887 17 0 0 +3888 20 0 0 +3889 20 0 1 +3890 20 1 0 +3891 20 1 1 +3892 21 0 0 +3893 21 0 1 +3894 21 1 0 +3895 21 1 1 +3896 23 1 1 +3897 23 1 0 +3898 23 0 1 +3899 23 0 0 +3900 22 1 1 +3901 22 1 0 +3902 22 0 1 +3903 22 0 0 +3904 28 1 0 +3905 28 1 1 +3906 28 0 0 +3907 28 0 1 +3908 29 1 0 +3909 29 1 1 +3910 29 0 0 +3911 29 0 1 +3912 31 0 1 +3913 31 0 0 +3914 31 1 1 +3915 31 1 0 +3916 30 0 1 +3917 30 0 0 +3918 30 1 1 +3919 30 1 0 diff --git a/Detectors/PHOS/base/files/Mod3RCU2.data b/Detectors/PHOS/base/files/Mod3RCU2.data new file mode 100644 index 0000000000000..21de94d7ace53 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod3RCU2.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 2 0 2 + 1 2 1 2 + 2 2 2 2 + 3 2 3 2 + 4 2 4 2 + 5 2 5 2 + 6 2 6 2 + 7 2 7 2 + 8 2 8 2 + 9 2 9 2 + 10 2 10 2 + 11 2 11 2 + 12 2 12 2 + 13 2 13 2 + 14 2 14 2 + 15 2 15 2 + 16 2 16 2 + 17 2 17 2 + 18 2 18 2 + 19 2 19 2 + 20 2 20 2 + 21 2 21 2 + 22 2 22 2 + 23 2 23 2 + 24 2 24 2 + 25 2 25 2 + 26 2 26 2 + 27 2 27 2 + 28 2 28 2 + 29 2 29 2 + 30 2 30 2 + 31 2 31 2 + 32 2 32 2 + 33 2 33 2 + 34 2 34 2 + 35 2 35 2 + 36 2 36 2 + 37 2 37 2 + 38 2 38 2 + 39 2 39 2 + 40 2 40 2 + 41 2 41 2 + 42 2 42 2 + 43 2 43 2 + 44 2 44 2 + 45 2 45 2 + 46 2 46 2 + 47 2 47 2 + 48 2 48 2 + 49 2 49 2 + 50 2 50 2 + 51 2 51 2 + 52 2 52 2 + 53 2 53 2 + 54 2 54 2 + 55 2 55 2 + 56 2 56 2 + 57 2 57 2 + 58 2 58 2 + 59 2 59 2 + 60 2 60 2 + 61 2 61 2 + 62 2 62 2 + 63 2 63 2 + 64 2 64 2 + 65 2 65 2 + 66 2 66 2 + 67 2 67 2 + 68 2 68 2 + 69 2 69 2 + 70 2 70 2 + 71 2 71 2 + 72 2 72 2 + 73 2 73 2 + 74 2 74 2 + 75 2 75 2 + 76 2 76 2 + 77 2 77 2 + 78 2 78 2 + 79 2 79 2 + 80 2 80 2 + 81 2 81 2 + 82 2 82 2 + 83 2 83 2 + 84 2 84 2 + 85 2 85 2 + 86 2 86 2 + 87 2 87 2 + 88 2 88 2 + 89 2 89 2 + 90 2 90 2 + 91 2 91 2 + 92 2 92 2 + 93 2 93 2 + 94 2 94 2 + 95 2 95 2 + 96 2 96 2 + 97 2 97 2 + 98 2 98 2 + 99 2 99 2 + 100 2 100 2 + 101 2 101 2 + 102 2 102 2 + 103 2 103 2 + 104 2 104 2 + 105 2 105 2 + 106 2 106 2 + 107 2 107 2 + 108 2 108 2 + 109 2 109 2 + 110 2 110 2 + 111 2 111 2 + 112 2 112 2 + 113 2 113 2 + 114 2 114 2 + 115 2 115 2 + 116 2 116 2 + 117 2 117 2 + 118 2 118 2 + 119 2 119 2 + 120 2 120 2 + 121 2 121 2 + 122 2 122 2 + 123 2 123 2 + 124 2 124 2 + 125 2 125 2 + 126 2 126 2 + 127 2 127 2 +2048 2 2048 2 +2049 2 2049 2 +2050 2 2050 2 +2051 2 2051 2 +2052 2 2052 2 +2053 2 2053 2 +2054 2 2054 2 +2055 2 2055 2 +2056 2 2056 2 +2057 2 2057 2 +2058 2 2058 2 +2059 2 2059 2 +2060 2 2060 2 +2061 2 2061 2 +2062 2 2062 2 +2063 2 2063 2 +2064 2 2064 2 +2065 2 2065 2 +2066 2 2066 2 +2067 2 2067 2 +2068 2 2068 2 +2069 2 2069 2 +2070 2 2070 2 +2071 2 2071 2 +2072 2 2072 2 +2073 2 2073 2 +2074 2 2074 2 +2075 2 2075 2 +2076 2 2076 2 +2077 2 2077 2 +2078 2 2078 2 +2079 2 2079 2 +2080 2 2080 2 +2081 2 2081 2 +2082 2 2082 2 +2083 2 2083 2 +2084 2 2084 2 +2085 2 2085 2 +2086 2 2086 2 +2087 2 2087 2 +2088 2 2088 2 +2089 2 2089 2 +2090 2 2090 2 +2091 2 2091 2 +2092 2 2092 2 +2093 2 2093 2 +2094 2 2094 2 +2095 2 2095 2 +2096 2 2096 2 +2097 2 2097 2 +2098 2 2098 2 +2099 2 2099 2 +2100 2 2100 2 +2101 2 2101 2 +2102 2 2102 2 +2103 2 2103 2 +2104 2 2104 2 +2105 2 2105 2 +2106 2 2106 2 +2107 2 2107 2 +2108 2 2108 2 +2109 2 2109 2 +2110 2 2110 2 +2111 2 2111 2 +2112 2 2112 2 +2113 2 2113 2 +2114 2 2114 2 +2115 2 2115 2 +2116 2 2116 2 +2117 2 2117 2 +2118 2 2118 2 +2119 2 2119 2 +2120 2 2120 2 +2121 2 2121 2 +2122 2 2122 2 +2123 2 2123 2 +2124 2 2124 2 +2125 2 2125 2 +2126 2 2126 2 +2127 2 2127 2 +2128 2 2128 2 +2129 2 2129 2 +2130 2 2130 2 +2131 2 2131 2 +2132 2 2132 2 +2133 2 2133 2 +2134 2 2134 2 +2135 2 2135 2 +2136 2 2136 2 +2137 2 2137 2 +2138 2 2138 2 +2139 2 2139 2 +2140 2 2140 2 +2141 2 2141 2 +2142 2 2142 2 +2143 2 2143 2 +2144 2 2144 2 +2145 2 2145 2 +2146 2 2146 2 +2147 2 2147 2 +2148 2 2148 2 +2149 2 2149 2 +2150 2 2150 2 +2151 2 2151 2 +2152 2 2152 2 +2153 2 2153 2 +2154 2 2154 2 +2155 2 2155 2 +2156 2 2156 2 +2157 2 2157 2 +2158 2 2158 2 +2159 2 2159 2 +2160 2 2160 2 +2161 2 2161 2 +2162 2 2162 2 +2163 2 2163 2 +2164 2 2164 2 +2165 2 2165 2 +2166 2 2166 2 +2167 2 2167 2 +2168 2 2168 2 +2169 2 2169 2 +2170 2 2170 2 +2171 2 2171 2 +2172 2 2172 2 +2173 2 2173 2 +2174 2 2174 2 +2175 2 2175 2 + 128 43 29 0 + 129 43 29 1 + 130 43 28 0 + 131 43 28 1 + 132 42 29 0 + 133 42 29 1 + 134 42 28 0 + 135 42 28 1 + 136 40 28 1 + 137 40 28 0 + 138 40 29 1 + 139 40 29 0 + 140 41 28 1 + 141 41 28 0 + 142 41 29 1 + 143 41 29 0 + 160 35 28 0 + 161 35 28 1 + 162 35 29 0 + 163 35 29 1 + 164 34 28 0 + 165 34 28 1 + 166 34 29 0 + 167 34 29 1 + 168 32 29 1 + 169 32 29 0 + 170 32 28 1 + 171 32 28 0 + 172 33 29 1 + 173 33 29 0 + 174 33 28 1 + 175 33 28 0 + 176 36 28 0 + 177 36 28 1 + 178 36 29 0 + 179 36 29 1 + 180 37 28 0 + 181 37 28 1 + 182 37 29 0 + 183 37 29 1 + 184 39 29 1 + 185 39 29 0 + 186 39 28 1 + 187 39 28 0 + 188 38 29 1 + 189 38 29 0 + 190 38 28 1 + 191 38 28 0 + 192 44 29 0 + 193 44 29 1 + 194 44 28 0 + 195 44 28 1 + 196 45 29 0 + 197 45 29 1 + 198 45 28 0 + 199 45 28 1 + 200 47 28 1 + 201 47 28 0 + 202 47 29 1 + 203 47 29 0 + 204 46 28 1 + 205 46 28 0 + 206 46 29 1 + 207 46 29 0 + 256 43 31 0 + 257 43 31 1 + 258 43 30 0 + 259 43 30 1 + 260 42 31 0 + 261 42 31 1 + 262 42 30 0 + 263 42 30 1 + 264 40 30 1 + 265 40 30 0 + 266 40 31 1 + 267 40 31 0 + 268 41 30 1 + 269 41 30 0 + 270 41 31 1 + 271 41 31 0 + 288 35 30 0 + 289 35 30 1 + 290 35 31 0 + 291 35 31 1 + 292 34 30 0 + 293 34 30 1 + 294 34 31 0 + 295 34 31 1 + 296 32 31 1 + 297 32 31 0 + 298 32 30 1 + 299 32 30 0 + 300 33 31 1 + 301 33 31 0 + 302 33 30 1 + 303 33 30 0 + 304 36 30 0 + 305 36 30 1 + 306 36 31 0 + 307 36 31 1 + 308 37 30 0 + 309 37 30 1 + 310 37 31 0 + 311 37 31 1 + 312 39 31 1 + 313 39 31 0 + 314 39 30 1 + 315 39 30 0 + 316 38 31 1 + 317 38 31 0 + 318 38 30 1 + 319 38 30 0 + 320 44 31 0 + 321 44 31 1 + 322 44 30 0 + 323 44 30 1 + 324 45 31 0 + 325 45 31 1 + 326 45 30 0 + 327 45 30 1 + 328 47 30 1 + 329 47 30 0 + 330 47 31 1 + 331 47 31 0 + 332 46 30 1 + 333 46 30 0 + 334 46 31 1 + 335 46 31 0 + 384 43 33 0 + 385 43 33 1 + 386 43 32 0 + 387 43 32 1 + 388 42 33 0 + 389 42 33 1 + 390 42 32 0 + 391 42 32 1 + 392 40 32 1 + 393 40 32 0 + 394 40 33 1 + 395 40 33 0 + 396 41 32 1 + 397 41 32 0 + 398 41 33 1 + 399 41 33 0 + 416 35 32 0 + 417 35 32 1 + 418 35 33 0 + 419 35 33 1 + 420 34 32 0 + 421 34 32 1 + 422 34 33 0 + 423 34 33 1 + 424 32 33 1 + 425 32 33 0 + 426 32 32 1 + 427 32 32 0 + 428 33 33 1 + 429 33 33 0 + 430 33 32 1 + 431 33 32 0 + 432 36 32 0 + 433 36 32 1 + 434 36 33 0 + 435 36 33 1 + 436 37 32 0 + 437 37 32 1 + 438 37 33 0 + 439 37 33 1 + 440 39 33 1 + 441 39 33 0 + 442 39 32 1 + 443 39 32 0 + 444 38 33 1 + 445 38 33 0 + 446 38 32 1 + 447 38 32 0 + 448 44 33 0 + 449 44 33 1 + 450 44 32 0 + 451 44 32 1 + 452 45 33 0 + 453 45 33 1 + 454 45 32 0 + 455 45 32 1 + 456 47 32 1 + 457 47 32 0 + 458 47 33 1 + 459 47 33 0 + 460 46 32 1 + 461 46 32 0 + 462 46 33 1 + 463 46 33 0 + 512 43 35 0 + 513 43 35 1 + 514 43 34 0 + 515 43 34 1 + 516 42 35 0 + 517 42 35 1 + 518 42 34 0 + 519 42 34 1 + 520 40 34 1 + 521 40 34 0 + 522 40 35 1 + 523 40 35 0 + 524 41 34 1 + 525 41 34 0 + 526 41 35 1 + 527 41 35 0 + 544 35 34 0 + 545 35 34 1 + 546 35 35 0 + 547 35 35 1 + 548 34 34 0 + 549 34 34 1 + 550 34 35 0 + 551 34 35 1 + 552 32 35 1 + 553 32 35 0 + 554 32 34 1 + 555 32 34 0 + 556 33 35 1 + 557 33 35 0 + 558 33 34 1 + 559 33 34 0 + 560 36 34 0 + 561 36 34 1 + 562 36 35 0 + 563 36 35 1 + 564 37 34 0 + 565 37 34 1 + 566 37 35 0 + 567 37 35 1 + 568 39 35 1 + 569 39 35 0 + 570 39 34 1 + 571 39 34 0 + 572 38 35 1 + 573 38 35 0 + 574 38 34 1 + 575 38 34 0 + 576 44 35 0 + 577 44 35 1 + 578 44 34 0 + 579 44 34 1 + 580 45 35 0 + 581 45 35 1 + 582 45 34 0 + 583 45 34 1 + 584 47 34 1 + 585 47 34 0 + 586 47 35 1 + 587 47 35 0 + 588 46 34 1 + 589 46 34 0 + 590 46 35 1 + 591 46 35 0 + 640 43 37 0 + 641 43 37 1 + 642 43 36 0 + 643 43 36 1 + 644 42 37 0 + 645 42 37 1 + 646 42 36 0 + 647 42 36 1 + 648 40 36 1 + 649 40 36 0 + 650 40 37 1 + 651 40 37 0 + 652 41 36 1 + 653 41 36 0 + 654 41 37 1 + 655 41 37 0 + 672 35 36 0 + 673 35 36 1 + 674 35 37 0 + 675 35 37 1 + 676 34 36 0 + 677 34 36 1 + 678 34 37 0 + 679 34 37 1 + 680 32 37 1 + 681 32 37 0 + 682 32 36 1 + 683 32 36 0 + 684 33 37 1 + 685 33 37 0 + 686 33 36 1 + 687 33 36 0 + 688 36 36 0 + 689 36 36 1 + 690 36 37 0 + 691 36 37 1 + 692 37 36 0 + 693 37 36 1 + 694 37 37 0 + 695 37 37 1 + 696 39 37 1 + 697 39 37 0 + 698 39 36 1 + 699 39 36 0 + 700 38 37 1 + 701 38 37 0 + 702 38 36 1 + 703 38 36 0 + 704 44 37 0 + 705 44 37 1 + 706 44 36 0 + 707 44 36 1 + 708 45 37 0 + 709 45 37 1 + 710 45 36 0 + 711 45 36 1 + 712 47 36 1 + 713 47 36 0 + 714 47 37 1 + 715 47 37 0 + 716 46 36 1 + 717 46 36 0 + 718 46 37 1 + 719 46 37 0 + 768 43 39 0 + 769 43 39 1 + 770 43 38 0 + 771 43 38 1 + 772 42 39 0 + 773 42 39 1 + 774 42 38 0 + 775 42 38 1 + 776 40 38 1 + 777 40 38 0 + 778 40 39 1 + 779 40 39 0 + 780 41 38 1 + 781 41 38 0 + 782 41 39 1 + 783 41 39 0 + 800 35 38 0 + 801 35 38 1 + 802 35 39 0 + 803 35 39 1 + 804 34 38 0 + 805 34 38 1 + 806 34 39 0 + 807 34 39 1 + 808 32 39 1 + 809 32 39 0 + 810 32 38 1 + 811 32 38 0 + 812 33 39 1 + 813 33 39 0 + 814 33 38 1 + 815 33 38 0 + 816 36 38 0 + 817 36 38 1 + 818 36 39 0 + 819 36 39 1 + 820 37 38 0 + 821 37 38 1 + 822 37 39 0 + 823 37 39 1 + 824 39 39 1 + 825 39 39 0 + 826 39 38 1 + 827 39 38 0 + 828 38 39 1 + 829 38 39 0 + 830 38 38 1 + 831 38 38 0 + 832 44 39 0 + 833 44 39 1 + 834 44 38 0 + 835 44 38 1 + 836 45 39 0 + 837 45 39 1 + 838 45 38 0 + 839 45 38 1 + 840 47 38 1 + 841 47 38 0 + 842 47 39 1 + 843 47 39 0 + 844 46 38 1 + 845 46 38 0 + 846 46 39 1 + 847 46 39 0 + 896 43 41 0 + 897 43 41 1 + 898 43 40 0 + 899 43 40 1 + 900 42 41 0 + 901 42 41 1 + 902 42 40 0 + 903 42 40 1 + 904 40 40 1 + 905 40 40 0 + 906 40 41 1 + 907 40 41 0 + 908 41 40 1 + 909 41 40 0 + 910 41 41 1 + 911 41 41 0 + 928 35 40 0 + 929 35 40 1 + 930 35 41 0 + 931 35 41 1 + 932 34 40 0 + 933 34 40 1 + 934 34 41 0 + 935 34 41 1 + 936 32 41 1 + 937 32 41 0 + 938 32 40 1 + 939 32 40 0 + 940 33 41 1 + 941 33 41 0 + 942 33 40 1 + 943 33 40 0 + 944 36 40 0 + 945 36 40 1 + 946 36 41 0 + 947 36 41 1 + 948 37 40 0 + 949 37 40 1 + 950 37 41 0 + 951 37 41 1 + 952 39 41 1 + 953 39 41 0 + 954 39 40 1 + 955 39 40 0 + 956 38 41 1 + 957 38 41 0 + 958 38 40 1 + 959 38 40 0 + 960 44 41 0 + 961 44 41 1 + 962 44 40 0 + 963 44 40 1 + 964 45 41 0 + 965 45 41 1 + 966 45 40 0 + 967 45 40 1 + 968 47 40 1 + 969 47 40 0 + 970 47 41 1 + 971 47 41 0 + 972 46 40 1 + 973 46 40 0 + 974 46 41 1 + 975 46 41 0 +1024 43 43 0 +1025 43 43 1 +1026 43 42 0 +1027 43 42 1 +1028 42 43 0 +1029 42 43 1 +1030 42 42 0 +1031 42 42 1 +1032 40 42 1 +1033 40 42 0 +1034 40 43 1 +1035 40 43 0 +1036 41 42 1 +1037 41 42 0 +1038 41 43 1 +1039 41 43 0 +1056 35 42 0 +1057 35 42 1 +1058 35 43 0 +1059 35 43 1 +1060 34 42 0 +1061 34 42 1 +1062 34 43 0 +1063 34 43 1 +1064 32 43 1 +1065 32 43 0 +1066 32 42 1 +1067 32 42 0 +1068 33 43 1 +1069 33 43 0 +1070 33 42 1 +1071 33 42 0 +1072 36 42 0 +1073 36 42 1 +1074 36 43 0 +1075 36 43 1 +1076 37 42 0 +1077 37 42 1 +1078 37 43 0 +1079 37 43 1 +1080 39 43 1 +1081 39 43 0 +1082 39 42 1 +1083 39 42 0 +1084 38 43 1 +1085 38 43 0 +1086 38 42 1 +1087 38 42 0 +1088 44 43 0 +1089 44 43 1 +1090 44 42 0 +1091 44 42 1 +1092 45 43 0 +1093 45 43 1 +1094 45 42 0 +1095 45 42 1 +1096 47 42 1 +1097 47 42 0 +1098 47 43 1 +1099 47 43 0 +1100 46 42 1 +1101 46 42 0 +1102 46 43 1 +1103 46 43 0 +1152 43 45 0 +1153 43 45 1 +1154 43 44 0 +1155 43 44 1 +1156 42 45 0 +1157 42 45 1 +1158 42 44 0 +1159 42 44 1 +1160 40 44 1 +1161 40 44 0 +1162 40 45 1 +1163 40 45 0 +1164 41 44 1 +1165 41 44 0 +1166 41 45 1 +1167 41 45 0 +1184 35 44 0 +1185 35 44 1 +1186 35 45 0 +1187 35 45 1 +1188 34 44 0 +1189 34 44 1 +1190 34 45 0 +1191 34 45 1 +1192 32 45 1 +1193 32 45 0 +1194 32 44 1 +1195 32 44 0 +1196 33 45 1 +1197 33 45 0 +1198 33 44 1 +1199 33 44 0 +1200 36 44 0 +1201 36 44 1 +1202 36 45 0 +1203 36 45 1 +1204 37 44 0 +1205 37 44 1 +1206 37 45 0 +1207 37 45 1 +1208 39 45 1 +1209 39 45 0 +1210 39 44 1 +1211 39 44 0 +1212 38 45 1 +1213 38 45 0 +1214 38 44 1 +1215 38 44 0 +1216 44 45 0 +1217 44 45 1 +1218 44 44 0 +1219 44 44 1 +1220 45 45 0 +1221 45 45 1 +1222 45 44 0 +1223 45 44 1 +1224 47 44 1 +1225 47 44 0 +1226 47 45 1 +1227 47 45 0 +1228 46 44 1 +1229 46 44 0 +1230 46 45 1 +1231 46 45 0 +1280 43 47 0 +1281 43 47 1 +1282 43 46 0 +1283 43 46 1 +1284 42 47 0 +1285 42 47 1 +1286 42 46 0 +1287 42 46 1 +1288 40 46 1 +1289 40 46 0 +1290 40 47 1 +1291 40 47 0 +1292 41 46 1 +1293 41 46 0 +1294 41 47 1 +1295 41 47 0 +1312 35 46 0 +1313 35 46 1 +1314 35 47 0 +1315 35 47 1 +1316 34 46 0 +1317 34 46 1 +1318 34 47 0 +1319 34 47 1 +1320 32 47 1 +1321 32 47 0 +1322 32 46 1 +1323 32 46 0 +1324 33 47 1 +1325 33 47 0 +1326 33 46 1 +1327 33 46 0 +1328 36 46 0 +1329 36 46 1 +1330 36 47 0 +1331 36 47 1 +1332 37 46 0 +1333 37 46 1 +1334 37 47 0 +1335 37 47 1 +1336 39 47 1 +1337 39 47 0 +1338 39 46 1 +1339 39 46 0 +1340 38 47 1 +1341 38 47 0 +1342 38 46 1 +1343 38 46 0 +1344 44 47 0 +1345 44 47 1 +1346 44 46 0 +1347 44 46 1 +1348 45 47 0 +1349 45 47 1 +1350 45 46 0 +1351 45 46 1 +1352 47 46 1 +1353 47 46 0 +1354 47 47 1 +1355 47 47 0 +1356 46 46 1 +1357 46 46 0 +1358 46 47 1 +1359 46 47 0 +1408 43 49 0 +1409 43 49 1 +1410 43 48 0 +1411 43 48 1 +1412 42 49 0 +1413 42 49 1 +1414 42 48 0 +1415 42 48 1 +1416 40 48 1 +1417 40 48 0 +1418 40 49 1 +1419 40 49 0 +1420 41 48 1 +1421 41 48 0 +1422 41 49 1 +1423 41 49 0 +1440 35 48 0 +1441 35 48 1 +1442 35 49 0 +1443 35 49 1 +1444 34 48 0 +1445 34 48 1 +1446 34 49 0 +1447 34 49 1 +1448 32 49 1 +1449 32 49 0 +1450 32 48 1 +1451 32 48 0 +1452 33 49 1 +1453 33 49 0 +1454 33 48 1 +1455 33 48 0 +1456 36 48 0 +1457 36 48 1 +1458 36 49 0 +1459 36 49 1 +1460 37 48 0 +1461 37 48 1 +1462 37 49 0 +1463 37 49 1 +1464 39 49 1 +1465 39 49 0 +1466 39 48 1 +1467 39 48 0 +1468 38 49 1 +1469 38 49 0 +1470 38 48 1 +1471 38 48 0 +1472 44 49 0 +1473 44 49 1 +1474 44 48 0 +1475 44 48 1 +1476 45 49 0 +1477 45 49 1 +1478 45 48 0 +1479 45 48 1 +1480 47 48 1 +1481 47 48 0 +1482 47 49 1 +1483 47 49 0 +1484 46 48 1 +1485 46 48 0 +1486 46 49 1 +1487 46 49 0 +1536 43 51 0 +1537 43 51 1 +1538 43 50 0 +1539 43 50 1 +1540 42 51 0 +1541 42 51 1 +1542 42 50 0 +1543 42 50 1 +1544 40 50 1 +1545 40 50 0 +1546 40 51 1 +1547 40 51 0 +1548 41 50 1 +1549 41 50 0 +1550 41 51 1 +1551 41 51 0 +1568 35 50 0 +1569 35 50 1 +1570 35 51 0 +1571 35 51 1 +1572 34 50 0 +1573 34 50 1 +1574 34 51 0 +1575 34 51 1 +1576 32 51 1 +1577 32 51 0 +1578 32 50 1 +1579 32 50 0 +1580 33 51 1 +1581 33 51 0 +1582 33 50 1 +1583 33 50 0 +1584 36 50 0 +1585 36 50 1 +1586 36 51 0 +1587 36 51 1 +1588 37 50 0 +1589 37 50 1 +1590 37 51 0 +1591 37 51 1 +1592 39 51 1 +1593 39 51 0 +1594 39 50 1 +1595 39 50 0 +1596 38 51 1 +1597 38 51 0 +1598 38 50 1 +1599 38 50 0 +1600 44 51 0 +1601 44 51 1 +1602 44 50 0 +1603 44 50 1 +1604 45 51 0 +1605 45 51 1 +1606 45 50 0 +1607 45 50 1 +1608 47 50 1 +1609 47 50 0 +1610 47 51 1 +1611 47 51 0 +1612 46 50 1 +1613 46 50 0 +1614 46 51 1 +1615 46 51 0 +1664 43 53 0 +1665 43 53 1 +1666 43 52 0 +1667 43 52 1 +1668 42 53 0 +1669 42 53 1 +1670 42 52 0 +1671 42 52 1 +1672 40 52 1 +1673 40 52 0 +1674 40 53 1 +1675 40 53 0 +1676 41 52 1 +1677 41 52 0 +1678 41 53 1 +1679 41 53 0 +1696 35 52 0 +1697 35 52 1 +1698 35 53 0 +1699 35 53 1 +1700 34 52 0 +1701 34 52 1 +1702 34 53 0 +1703 34 53 1 +1704 32 53 1 +1705 32 53 0 +1706 32 52 1 +1707 32 52 0 +1708 33 53 1 +1709 33 53 0 +1710 33 52 1 +1711 33 52 0 +1712 36 52 0 +1713 36 52 1 +1714 36 53 0 +1715 36 53 1 +1716 37 52 0 +1717 37 52 1 +1718 37 53 0 +1719 37 53 1 +1720 39 53 1 +1721 39 53 0 +1722 39 52 1 +1723 39 52 0 +1724 38 53 1 +1725 38 53 0 +1726 38 52 1 +1727 38 52 0 +1728 44 53 0 +1729 44 53 1 +1730 44 52 0 +1731 44 52 1 +1732 45 53 0 +1733 45 53 1 +1734 45 52 0 +1735 45 52 1 +1736 47 52 1 +1737 47 52 0 +1738 47 53 1 +1739 47 53 0 +1740 46 52 1 +1741 46 52 0 +1742 46 53 1 +1743 46 53 0 +1792 43 55 0 +1793 43 55 1 +1794 43 54 0 +1795 43 54 1 +1796 42 55 0 +1797 42 55 1 +1798 42 54 0 +1799 42 54 1 +1800 40 54 1 +1801 40 54 0 +1802 40 55 1 +1803 40 55 0 +1804 41 54 1 +1805 41 54 0 +1806 41 55 1 +1807 41 55 0 +1824 35 54 0 +1825 35 54 1 +1826 35 55 0 +1827 35 55 1 +1828 34 54 0 +1829 34 54 1 +1830 34 55 0 +1831 34 55 1 +1832 32 55 1 +1833 32 55 0 +1834 32 54 1 +1835 32 54 0 +1836 33 55 1 +1837 33 55 0 +1838 33 54 1 +1839 33 54 0 +1840 36 54 0 +1841 36 54 1 +1842 36 55 0 +1843 36 55 1 +1844 37 54 0 +1845 37 54 1 +1846 37 55 0 +1847 37 55 1 +1848 39 55 1 +1849 39 55 0 +1850 39 54 1 +1851 39 54 0 +1852 38 55 1 +1853 38 55 0 +1854 38 54 1 +1855 38 54 0 +1856 44 55 0 +1857 44 55 1 +1858 44 54 0 +1859 44 54 1 +1860 45 55 0 +1861 45 55 1 +1862 45 54 0 +1863 45 54 1 +1864 47 54 1 +1865 47 54 0 +1866 47 55 1 +1867 47 55 0 +1868 46 54 1 +1869 46 54 0 +1870 46 55 1 +1871 46 55 0 +2176 43 27 0 +2177 43 27 1 +2178 43 26 0 +2179 43 26 1 +2180 42 27 0 +2181 42 27 1 +2182 42 26 0 +2183 42 26 1 +2184 40 26 1 +2185 40 26 0 +2186 40 27 1 +2187 40 27 0 +2188 41 26 1 +2189 41 26 0 +2190 41 27 1 +2191 41 27 0 +2208 35 26 0 +2209 35 26 1 +2210 35 27 0 +2211 35 27 1 +2212 34 26 0 +2213 34 26 1 +2214 34 27 0 +2215 34 27 1 +2216 32 27 1 +2217 32 27 0 +2218 32 26 1 +2219 32 26 0 +2220 33 27 1 +2221 33 27 0 +2222 33 26 1 +2223 33 26 0 +2224 36 26 0 +2225 36 26 1 +2226 36 27 0 +2227 36 27 1 +2228 37 26 0 +2229 37 26 1 +2230 37 27 0 +2231 37 27 1 +2232 39 27 1 +2233 39 27 0 +2234 39 26 1 +2235 39 26 0 +2236 38 27 1 +2237 38 27 0 +2238 38 26 1 +2239 38 26 0 +2240 44 27 0 +2241 44 27 1 +2242 44 26 0 +2243 44 26 1 +2244 45 27 0 +2245 45 27 1 +2246 45 26 0 +2247 45 26 1 +2248 47 26 1 +2249 47 26 0 +2250 47 27 1 +2251 47 27 0 +2252 46 26 1 +2253 46 26 0 +2254 46 27 1 +2255 46 27 0 +2304 43 25 0 +2305 43 25 1 +2306 43 24 0 +2307 43 24 1 +2308 42 25 0 +2309 42 25 1 +2310 42 24 0 +2311 42 24 1 +2312 40 24 1 +2313 40 24 0 +2314 40 25 1 +2315 40 25 0 +2316 41 24 1 +2317 41 24 0 +2318 41 25 1 +2319 41 25 0 +2336 35 24 0 +2337 35 24 1 +2338 35 25 0 +2339 35 25 1 +2340 34 24 0 +2341 34 24 1 +2342 34 25 0 +2343 34 25 1 +2344 32 25 1 +2345 32 25 0 +2346 32 24 1 +2347 32 24 0 +2348 33 25 1 +2349 33 25 0 +2350 33 24 1 +2351 33 24 0 +2352 36 24 0 +2353 36 24 1 +2354 36 25 0 +2355 36 25 1 +2356 37 24 0 +2357 37 24 1 +2358 37 25 0 +2359 37 25 1 +2360 39 25 1 +2361 39 25 0 +2362 39 24 1 +2363 39 24 0 +2364 38 25 1 +2365 38 25 0 +2366 38 24 1 +2367 38 24 0 +2368 44 25 0 +2369 44 25 1 +2370 44 24 0 +2371 44 24 1 +2372 45 25 0 +2373 45 25 1 +2374 45 24 0 +2375 45 24 1 +2376 47 24 1 +2377 47 24 0 +2378 47 25 1 +2379 47 25 0 +2380 46 24 1 +2381 46 24 0 +2382 46 25 1 +2383 46 25 0 +2432 43 23 0 +2433 43 23 1 +2434 43 22 0 +2435 43 22 1 +2436 42 23 0 +2437 42 23 1 +2438 42 22 0 +2439 42 22 1 +2440 40 22 1 +2441 40 22 0 +2442 40 23 1 +2443 40 23 0 +2444 41 22 1 +2445 41 22 0 +2446 41 23 1 +2447 41 23 0 +2464 35 22 0 +2465 35 22 1 +2466 35 23 0 +2467 35 23 1 +2468 34 22 0 +2469 34 22 1 +2470 34 23 0 +2471 34 23 1 +2472 32 23 1 +2473 32 23 0 +2474 32 22 1 +2475 32 22 0 +2476 33 23 1 +2477 33 23 0 +2478 33 22 1 +2479 33 22 0 +2480 36 22 0 +2481 36 22 1 +2482 36 23 0 +2483 36 23 1 +2484 37 22 0 +2485 37 22 1 +2486 37 23 0 +2487 37 23 1 +2488 39 23 1 +2489 39 23 0 +2490 39 22 1 +2491 39 22 0 +2492 38 23 1 +2493 38 23 0 +2494 38 22 1 +2495 38 22 0 +2496 44 23 0 +2497 44 23 1 +2498 44 22 0 +2499 44 22 1 +2500 45 23 0 +2501 45 23 1 +2502 45 22 0 +2503 45 22 1 +2504 47 22 1 +2505 47 22 0 +2506 47 23 1 +2507 47 23 0 +2508 46 22 1 +2509 46 22 0 +2510 46 23 1 +2511 46 23 0 +2560 43 21 0 +2561 43 21 1 +2562 43 20 0 +2563 43 20 1 +2564 42 21 0 +2565 42 21 1 +2566 42 20 0 +2567 42 20 1 +2568 40 20 1 +2569 40 20 0 +2570 40 21 1 +2571 40 21 0 +2572 41 20 1 +2573 41 20 0 +2574 41 21 1 +2575 41 21 0 +2592 35 20 0 +2593 35 20 1 +2594 35 21 0 +2595 35 21 1 +2596 34 20 0 +2597 34 20 1 +2598 34 21 0 +2599 34 21 1 +2600 32 21 1 +2601 32 21 0 +2602 32 20 1 +2603 32 20 0 +2604 33 21 1 +2605 33 21 0 +2606 33 20 1 +2607 33 20 0 +2608 36 20 0 +2609 36 20 1 +2610 36 21 0 +2611 36 21 1 +2612 37 20 0 +2613 37 20 1 +2614 37 21 0 +2615 37 21 1 +2616 39 21 1 +2617 39 21 0 +2618 39 20 1 +2619 39 20 0 +2620 38 21 1 +2621 38 21 0 +2622 38 20 1 +2623 38 20 0 +2624 44 21 0 +2625 44 21 1 +2626 44 20 0 +2627 44 20 1 +2628 45 21 0 +2629 45 21 1 +2630 45 20 0 +2631 45 20 1 +2632 47 20 1 +2633 47 20 0 +2634 47 21 1 +2635 47 21 0 +2636 46 20 1 +2637 46 20 0 +2638 46 21 1 +2639 46 21 0 +2688 43 19 0 +2689 43 19 1 +2690 43 18 0 +2691 43 18 1 +2692 42 19 0 +2693 42 19 1 +2694 42 18 0 +2695 42 18 1 +2696 40 18 1 +2697 40 18 0 +2698 40 19 1 +2699 40 19 0 +2700 41 18 1 +2701 41 18 0 +2702 41 19 1 +2703 41 19 0 +2720 35 18 0 +2721 35 18 1 +2722 35 19 0 +2723 35 19 1 +2724 34 18 0 +2725 34 18 1 +2726 34 19 0 +2727 34 19 1 +2728 32 19 1 +2729 32 19 0 +2730 32 18 1 +2731 32 18 0 +2732 33 19 1 +2733 33 19 0 +2734 33 18 1 +2735 33 18 0 +2736 36 18 0 +2737 36 18 1 +2738 36 19 0 +2739 36 19 1 +2740 37 18 0 +2741 37 18 1 +2742 37 19 0 +2743 37 19 1 +2744 39 19 1 +2745 39 19 0 +2746 39 18 1 +2747 39 18 0 +2748 38 19 1 +2749 38 19 0 +2750 38 18 1 +2751 38 18 0 +2752 44 19 0 +2753 44 19 1 +2754 44 18 0 +2755 44 18 1 +2756 45 19 0 +2757 45 19 1 +2758 45 18 0 +2759 45 18 1 +2760 47 18 1 +2761 47 18 0 +2762 47 19 1 +2763 47 19 0 +2764 46 18 1 +2765 46 18 0 +2766 46 19 1 +2767 46 19 0 +2816 43 17 0 +2817 43 17 1 +2818 43 16 0 +2819 43 16 1 +2820 42 17 0 +2821 42 17 1 +2822 42 16 0 +2823 42 16 1 +2824 40 16 1 +2825 40 16 0 +2826 40 17 1 +2827 40 17 0 +2828 41 16 1 +2829 41 16 0 +2830 41 17 1 +2831 41 17 0 +2848 35 16 0 +2849 35 16 1 +2850 35 17 0 +2851 35 17 1 +2852 34 16 0 +2853 34 16 1 +2854 34 17 0 +2855 34 17 1 +2856 32 17 1 +2857 32 17 0 +2858 32 16 1 +2859 32 16 0 +2860 33 17 1 +2861 33 17 0 +2862 33 16 1 +2863 33 16 0 +2864 36 16 0 +2865 36 16 1 +2866 36 17 0 +2867 36 17 1 +2868 37 16 0 +2869 37 16 1 +2870 37 17 0 +2871 37 17 1 +2872 39 17 1 +2873 39 17 0 +2874 39 16 1 +2875 39 16 0 +2876 38 17 1 +2877 38 17 0 +2878 38 16 1 +2879 38 16 0 +2880 44 17 0 +2881 44 17 1 +2882 44 16 0 +2883 44 16 1 +2884 45 17 0 +2885 45 17 1 +2886 45 16 0 +2887 45 16 1 +2888 47 16 1 +2889 47 16 0 +2890 47 17 1 +2891 47 17 0 +2892 46 16 1 +2893 46 16 0 +2894 46 17 1 +2895 46 17 0 +2944 43 15 0 +2945 43 15 1 +2946 43 14 0 +2947 43 14 1 +2948 42 15 0 +2949 42 15 1 +2950 42 14 0 +2951 42 14 1 +2952 40 14 1 +2953 40 14 0 +2954 40 15 1 +2955 40 15 0 +2956 41 14 1 +2957 41 14 0 +2958 41 15 1 +2959 41 15 0 +2976 35 14 0 +2977 35 14 1 +2978 35 15 0 +2979 35 15 1 +2980 34 14 0 +2981 34 14 1 +2982 34 15 0 +2983 34 15 1 +2984 32 15 1 +2985 32 15 0 +2986 32 14 1 +2987 32 14 0 +2988 33 15 1 +2989 33 15 0 +2990 33 14 1 +2991 33 14 0 +2992 36 14 0 +2993 36 14 1 +2994 36 15 0 +2995 36 15 1 +2996 37 14 0 +2997 37 14 1 +2998 37 15 0 +2999 37 15 1 +3000 39 15 1 +3001 39 15 0 +3002 39 14 1 +3003 39 14 0 +3004 38 15 1 +3005 38 15 0 +3006 38 14 1 +3007 38 14 0 +3008 44 15 0 +3009 44 15 1 +3010 44 14 0 +3011 44 14 1 +3012 45 15 0 +3013 45 15 1 +3014 45 14 0 +3015 45 14 1 +3016 47 14 1 +3017 47 14 0 +3018 47 15 1 +3019 47 15 0 +3020 46 14 1 +3021 46 14 0 +3022 46 15 1 +3023 46 15 0 +3072 43 13 0 +3073 43 13 1 +3074 43 12 0 +3075 43 12 1 +3076 42 13 0 +3077 42 13 1 +3078 42 12 0 +3079 42 12 1 +3080 40 12 1 +3081 40 12 0 +3082 40 13 1 +3083 40 13 0 +3084 41 12 1 +3085 41 12 0 +3086 41 13 1 +3087 41 13 0 +3104 35 12 0 +3105 35 12 1 +3106 35 13 0 +3107 35 13 1 +3108 34 12 0 +3109 34 12 1 +3110 34 13 0 +3111 34 13 1 +3112 32 13 1 +3113 32 13 0 +3114 32 12 1 +3115 32 12 0 +3116 33 13 1 +3117 33 13 0 +3118 33 12 1 +3119 33 12 0 +3120 36 12 0 +3121 36 12 1 +3122 36 13 0 +3123 36 13 1 +3124 37 12 0 +3125 37 12 1 +3126 37 13 0 +3127 37 13 1 +3128 39 13 1 +3129 39 13 0 +3130 39 12 1 +3131 39 12 0 +3132 38 13 1 +3133 38 13 0 +3134 38 12 1 +3135 38 12 0 +3136 44 13 0 +3137 44 13 1 +3138 44 12 0 +3139 44 12 1 +3140 45 13 0 +3141 45 13 1 +3142 45 12 0 +3143 45 12 1 +3144 47 12 1 +3145 47 12 0 +3146 47 13 1 +3147 47 13 0 +3148 46 12 1 +3149 46 12 0 +3150 46 13 1 +3151 46 13 0 +3200 43 11 0 +3201 43 11 1 +3202 43 10 0 +3203 43 10 1 +3204 42 11 0 +3205 42 11 1 +3206 42 10 0 +3207 42 10 1 +3208 40 10 1 +3209 40 10 0 +3210 40 11 1 +3211 40 11 0 +3212 41 10 1 +3213 41 10 0 +3214 41 11 1 +3215 41 11 0 +3232 35 10 0 +3233 35 10 1 +3234 35 11 0 +3235 35 11 1 +3236 34 10 0 +3237 34 10 1 +3238 34 11 0 +3239 34 11 1 +3240 32 11 1 +3241 32 11 0 +3242 32 10 1 +3243 32 10 0 +3244 33 11 1 +3245 33 11 0 +3246 33 10 1 +3247 33 10 0 +3248 36 10 0 +3249 36 10 1 +3250 36 11 0 +3251 36 11 1 +3252 37 10 0 +3253 37 10 1 +3254 37 11 0 +3255 37 11 1 +3256 39 11 1 +3257 39 11 0 +3258 39 10 1 +3259 39 10 0 +3260 38 11 1 +3261 38 11 0 +3262 38 10 1 +3263 38 10 0 +3264 44 11 0 +3265 44 11 1 +3266 44 10 0 +3267 44 10 1 +3268 45 11 0 +3269 45 11 1 +3270 45 10 0 +3271 45 10 1 +3272 47 10 1 +3273 47 10 0 +3274 47 11 1 +3275 47 11 0 +3276 46 10 1 +3277 46 10 0 +3278 46 11 1 +3279 46 11 0 +3328 43 9 0 +3329 43 9 1 +3330 43 8 0 +3331 43 8 1 +3332 42 9 0 +3333 42 9 1 +3334 42 8 0 +3335 42 8 1 +3336 40 8 1 +3337 40 8 0 +3338 40 9 1 +3339 40 9 0 +3340 41 8 1 +3341 41 8 0 +3342 41 9 1 +3343 41 9 0 +3360 35 8 0 +3361 35 8 1 +3362 35 9 0 +3363 35 9 1 +3364 34 8 0 +3365 34 8 1 +3366 34 9 0 +3367 34 9 1 +3368 32 9 1 +3369 32 9 0 +3370 32 8 1 +3371 32 8 0 +3372 33 9 1 +3373 33 9 0 +3374 33 8 1 +3375 33 8 0 +3376 36 8 0 +3377 36 8 1 +3378 36 9 0 +3379 36 9 1 +3380 37 8 0 +3381 37 8 1 +3382 37 9 0 +3383 37 9 1 +3384 39 9 1 +3385 39 9 0 +3386 39 8 1 +3387 39 8 0 +3388 38 9 1 +3389 38 9 0 +3390 38 8 1 +3391 38 8 0 +3392 44 9 0 +3393 44 9 1 +3394 44 8 0 +3395 44 8 1 +3396 45 9 0 +3397 45 9 1 +3398 45 8 0 +3399 45 8 1 +3400 47 8 1 +3401 47 8 0 +3402 47 9 1 +3403 47 9 0 +3404 46 8 1 +3405 46 8 0 +3406 46 9 1 +3407 46 9 0 +3456 43 7 0 +3457 43 7 1 +3458 43 6 0 +3459 43 6 1 +3460 42 7 0 +3461 42 7 1 +3462 42 6 0 +3463 42 6 1 +3464 40 6 1 +3465 40 6 0 +3466 40 7 1 +3467 40 7 0 +3468 41 6 1 +3469 41 6 0 +3470 41 7 1 +3471 41 7 0 +3488 35 6 0 +3489 35 6 1 +3490 35 7 0 +3491 35 7 1 +3492 34 6 0 +3493 34 6 1 +3494 34 7 0 +3495 34 7 1 +3496 32 7 1 +3497 32 7 0 +3498 32 6 1 +3499 32 6 0 +3500 33 7 1 +3501 33 7 0 +3502 33 6 1 +3503 33 6 0 +3504 36 6 0 +3505 36 6 1 +3506 36 7 0 +3507 36 7 1 +3508 37 6 0 +3509 37 6 1 +3510 37 7 0 +3511 37 7 1 +3512 39 7 1 +3513 39 7 0 +3514 39 6 1 +3515 39 6 0 +3516 38 7 1 +3517 38 7 0 +3518 38 6 1 +3519 38 6 0 +3520 44 7 0 +3521 44 7 1 +3522 44 6 0 +3523 44 6 1 +3524 45 7 0 +3525 45 7 1 +3526 45 6 0 +3527 45 6 1 +3528 47 6 1 +3529 47 6 0 +3530 47 7 1 +3531 47 7 0 +3532 46 6 1 +3533 46 6 0 +3534 46 7 1 +3535 46 7 0 +3584 43 5 0 +3585 43 5 1 +3586 43 4 0 +3587 43 4 1 +3588 42 5 0 +3589 42 5 1 +3590 42 4 0 +3591 42 4 1 +3592 40 4 1 +3593 40 4 0 +3594 40 5 1 +3595 40 5 0 +3596 41 4 1 +3597 41 4 0 +3598 41 5 1 +3599 41 5 0 +3616 35 4 0 +3617 35 4 1 +3618 35 5 0 +3619 35 5 1 +3620 34 4 0 +3621 34 4 1 +3622 34 5 0 +3623 34 5 1 +3624 32 5 1 +3625 32 5 0 +3626 32 4 1 +3627 32 4 0 +3628 33 5 1 +3629 33 5 0 +3630 33 4 1 +3631 33 4 0 +3632 36 4 0 +3633 36 4 1 +3634 36 5 0 +3635 36 5 1 +3636 37 4 0 +3637 37 4 1 +3638 37 5 0 +3639 37 5 1 +3640 39 5 1 +3641 39 5 0 +3642 39 4 1 +3643 39 4 0 +3644 38 5 1 +3645 38 5 0 +3646 38 4 1 +3647 38 4 0 +3648 44 5 0 +3649 44 5 1 +3650 44 4 0 +3651 44 4 1 +3652 45 5 0 +3653 45 5 1 +3654 45 4 0 +3655 45 4 1 +3656 47 4 1 +3657 47 4 0 +3658 47 5 1 +3659 47 5 0 +3660 46 4 1 +3661 46 4 0 +3662 46 5 1 +3663 46 5 0 +3712 43 3 0 +3713 43 3 1 +3714 43 2 0 +3715 43 2 1 +3716 42 3 0 +3717 42 3 1 +3718 42 2 0 +3719 42 2 1 +3720 40 2 1 +3721 40 2 0 +3722 40 3 1 +3723 40 3 0 +3724 41 2 1 +3725 41 2 0 +3726 41 3 1 +3727 41 3 0 +3744 35 2 0 +3745 35 2 1 +3746 35 3 0 +3747 35 3 1 +3748 34 2 0 +3749 34 2 1 +3750 34 3 0 +3751 34 3 1 +3752 32 3 1 +3753 32 3 0 +3754 32 2 1 +3755 32 2 0 +3756 33 3 1 +3757 33 3 0 +3758 33 2 1 +3759 33 2 0 +3760 36 2 0 +3761 36 2 1 +3762 36 3 0 +3763 36 3 1 +3764 37 2 0 +3765 37 2 1 +3766 37 3 0 +3767 37 3 1 +3768 39 3 1 +3769 39 3 0 +3770 39 2 1 +3771 39 2 0 +3772 38 3 1 +3773 38 3 0 +3774 38 2 1 +3775 38 2 0 +3776 44 3 0 +3777 44 3 1 +3778 44 2 0 +3779 44 2 1 +3780 45 3 0 +3781 45 3 1 +3782 45 2 0 +3783 45 2 1 +3784 47 2 1 +3785 47 2 0 +3786 47 3 1 +3787 47 3 0 +3788 46 2 1 +3789 46 2 0 +3790 46 3 1 +3791 46 3 0 +3840 43 1 0 +3841 43 1 1 +3842 43 0 0 +3843 43 0 1 +3844 42 1 0 +3845 42 1 1 +3846 42 0 0 +3847 42 0 1 +3848 40 0 1 +3849 40 0 0 +3850 40 1 1 +3851 40 1 0 +3852 41 0 1 +3853 41 0 0 +3854 41 1 1 +3855 41 1 0 +3872 35 0 0 +3873 35 0 1 +3874 35 1 0 +3875 35 1 1 +3876 34 0 0 +3877 34 0 1 +3878 34 1 0 +3879 34 1 1 +3880 32 1 1 +3881 32 1 0 +3882 32 0 1 +3883 32 0 0 +3884 33 1 1 +3885 33 1 0 +3886 33 0 1 +3887 33 0 0 +3888 36 0 0 +3889 36 0 1 +3890 36 1 0 +3891 36 1 1 +3892 37 0 0 +3893 37 0 1 +3894 37 1 0 +3895 37 1 1 +3896 39 1 1 +3897 39 1 0 +3898 39 0 1 +3899 39 0 0 +3900 38 1 1 +3901 38 1 0 +3902 38 0 1 +3903 38 0 0 +3904 44 1 0 +3905 44 1 1 +3906 44 0 0 +3907 44 0 1 +3908 45 1 0 +3909 45 1 1 +3910 45 0 0 +3911 45 0 1 +3912 47 0 1 +3913 47 0 0 +3914 47 1 1 +3915 47 1 0 +3916 46 0 1 +3917 46 0 0 +3918 46 1 1 +3919 46 1 0 diff --git a/Detectors/PHOS/base/files/Mod3RCU3.data b/Detectors/PHOS/base/files/Mod3RCU3.data new file mode 100644 index 0000000000000..43bd76fc42791 --- /dev/null +++ b/Detectors/PHOS/base/files/Mod3RCU3.data @@ -0,0 +1,2050 @@ +2048 +3919 + 0 3 0 2 + 1 3 1 2 + 2 3 2 2 + 3 3 3 2 + 4 3 4 2 + 5 3 5 2 + 6 3 6 2 + 7 3 7 2 + 8 3 8 2 + 9 3 9 2 + 10 3 10 2 + 11 3 11 2 + 12 3 12 2 + 13 3 13 2 + 14 3 14 2 + 15 3 15 2 + 16 3 16 2 + 17 3 17 2 + 18 3 18 2 + 19 3 19 2 + 20 3 20 2 + 21 3 21 2 + 22 3 22 2 + 23 3 23 2 + 24 3 24 2 + 25 3 25 2 + 26 3 26 2 + 27 3 27 2 + 28 3 28 2 + 29 3 29 2 + 30 3 30 2 + 31 3 31 2 + 32 3 32 2 + 33 3 33 2 + 34 3 34 2 + 35 3 35 2 + 36 3 36 2 + 37 3 37 2 + 38 3 38 2 + 39 3 39 2 + 40 3 40 2 + 41 3 41 2 + 42 3 42 2 + 43 3 43 2 + 44 3 44 2 + 45 3 45 2 + 46 3 46 2 + 47 3 47 2 + 48 3 48 2 + 49 3 49 2 + 50 3 50 2 + 51 3 51 2 + 52 3 52 2 + 53 3 53 2 + 54 3 54 2 + 55 3 55 2 + 56 3 56 2 + 57 3 57 2 + 58 3 58 2 + 59 3 59 2 + 60 3 60 2 + 61 3 61 2 + 62 3 62 2 + 63 3 63 2 + 64 3 64 2 + 65 3 65 2 + 66 3 66 2 + 67 3 67 2 + 68 3 68 2 + 69 3 69 2 + 70 3 70 2 + 71 3 71 2 + 72 3 72 2 + 73 3 73 2 + 74 3 74 2 + 75 3 75 2 + 76 3 76 2 + 77 3 77 2 + 78 3 78 2 + 79 3 79 2 + 80 3 80 2 + 81 3 81 2 + 82 3 82 2 + 83 3 83 2 + 84 3 84 2 + 85 3 85 2 + 86 3 86 2 + 87 3 87 2 + 88 3 88 2 + 89 3 89 2 + 90 3 90 2 + 91 3 91 2 + 92 3 92 2 + 93 3 93 2 + 94 3 94 2 + 95 3 95 2 + 96 3 96 2 + 97 3 97 2 + 98 3 98 2 + 99 3 99 2 + 100 3 100 2 + 101 3 101 2 + 102 3 102 2 + 103 3 103 2 + 104 3 104 2 + 105 3 105 2 + 106 3 106 2 + 107 3 107 2 + 108 3 108 2 + 109 3 109 2 + 110 3 110 2 + 111 3 111 2 + 112 3 112 2 + 113 3 113 2 + 114 3 114 2 + 115 3 115 2 + 116 3 116 2 + 117 3 117 2 + 118 3 118 2 + 119 3 119 2 + 120 3 120 2 + 121 3 121 2 + 122 3 122 2 + 123 3 123 2 + 124 3 124 2 + 125 3 125 2 + 126 3 126 2 + 127 3 127 2 +2048 3 2048 2 +2049 3 2049 2 +2050 3 2050 2 +2051 3 2051 2 +2052 3 2052 2 +2053 3 2053 2 +2054 3 2054 2 +2055 3 2055 2 +2056 3 2056 2 +2057 3 2057 2 +2058 3 2058 2 +2059 3 2059 2 +2060 3 2060 2 +2061 3 2061 2 +2062 3 2062 2 +2063 3 2063 2 +2064 3 2064 2 +2065 3 2065 2 +2066 3 2066 2 +2067 3 2067 2 +2068 3 2068 2 +2069 3 2069 2 +2070 3 2070 2 +2071 3 2071 2 +2072 3 2072 2 +2073 3 2073 2 +2074 3 2074 2 +2075 3 2075 2 +2076 3 2076 2 +2077 3 2077 2 +2078 3 2078 2 +2079 3 2079 2 +2080 3 2080 2 +2081 3 2081 2 +2082 3 2082 2 +2083 3 2083 2 +2084 3 2084 2 +2085 3 2085 2 +2086 3 2086 2 +2087 3 2087 2 +2088 3 2088 2 +2089 3 2089 2 +2090 3 2090 2 +2091 3 2091 2 +2092 3 2092 2 +2093 3 2093 2 +2094 3 2094 2 +2095 3 2095 2 +2096 3 2096 2 +2097 3 2097 2 +2098 3 2098 2 +2099 3 2099 2 +2100 3 2100 2 +2101 3 2101 2 +2102 3 2102 2 +2103 3 2103 2 +2104 3 2104 2 +2105 3 2105 2 +2106 3 2106 2 +2107 3 2107 2 +2108 3 2108 2 +2109 3 2109 2 +2110 3 2110 2 +2111 3 2111 2 +2112 3 2112 2 +2113 3 2113 2 +2114 3 2114 2 +2115 3 2115 2 +2116 3 2116 2 +2117 3 2117 2 +2118 3 2118 2 +2119 3 2119 2 +2120 3 2120 2 +2121 3 2121 2 +2122 3 2122 2 +2123 3 2123 2 +2124 3 2124 2 +2125 3 2125 2 +2126 3 2126 2 +2127 3 2127 2 +2128 3 2128 2 +2129 3 2129 2 +2130 3 2130 2 +2131 3 2131 2 +2132 3 2132 2 +2133 3 2133 2 +2134 3 2134 2 +2135 3 2135 2 +2136 3 2136 2 +2137 3 2137 2 +2138 3 2138 2 +2139 3 2139 2 +2140 3 2140 2 +2141 3 2141 2 +2142 3 2142 2 +2143 3 2143 2 +2144 3 2144 2 +2145 3 2145 2 +2146 3 2146 2 +2147 3 2147 2 +2148 3 2148 2 +2149 3 2149 2 +2150 3 2150 2 +2151 3 2151 2 +2152 3 2152 2 +2153 3 2153 2 +2154 3 2154 2 +2155 3 2155 2 +2156 3 2156 2 +2157 3 2157 2 +2158 3 2158 2 +2159 3 2159 2 +2160 3 2160 2 +2161 3 2161 2 +2162 3 2162 2 +2163 3 2163 2 +2164 3 2164 2 +2165 3 2165 2 +2166 3 2166 2 +2167 3 2167 2 +2168 3 2168 2 +2169 3 2169 2 +2170 3 2170 2 +2171 3 2171 2 +2172 3 2172 2 +2173 3 2173 2 +2174 3 2174 2 +2175 3 2175 2 + 128 59 29 0 + 129 59 29 1 + 130 59 28 0 + 131 59 28 1 + 132 58 29 0 + 133 58 29 1 + 134 58 28 0 + 135 58 28 1 + 136 56 28 1 + 137 56 28 0 + 138 56 29 1 + 139 56 29 0 + 140 57 28 1 + 141 57 28 0 + 142 57 29 1 + 143 57 29 0 + 160 51 28 0 + 161 51 28 1 + 162 51 29 0 + 163 51 29 1 + 164 50 28 0 + 165 50 28 1 + 166 50 29 0 + 167 50 29 1 + 168 48 29 1 + 169 48 29 0 + 170 48 28 1 + 171 48 28 0 + 172 49 29 1 + 173 49 29 0 + 174 49 28 1 + 175 49 28 0 + 176 52 28 0 + 177 52 28 1 + 178 52 29 0 + 179 52 29 1 + 180 53 28 0 + 181 53 28 1 + 182 53 29 0 + 183 53 29 1 + 184 55 29 1 + 185 55 29 0 + 186 55 28 1 + 187 55 28 0 + 188 54 29 1 + 189 54 29 0 + 190 54 28 1 + 191 54 28 0 + 192 60 29 0 + 193 60 29 1 + 194 60 28 0 + 195 60 28 1 + 196 61 29 0 + 197 61 29 1 + 198 61 28 0 + 199 61 28 1 + 200 63 28 1 + 201 63 28 0 + 202 63 29 1 + 203 63 29 0 + 204 62 28 1 + 205 62 28 0 + 206 62 29 1 + 207 62 29 0 + 256 59 31 0 + 257 59 31 1 + 258 59 30 0 + 259 59 30 1 + 260 58 31 0 + 261 58 31 1 + 262 58 30 0 + 263 58 30 1 + 264 56 30 1 + 265 56 30 0 + 266 56 31 1 + 267 56 31 0 + 268 57 30 1 + 269 57 30 0 + 270 57 31 1 + 271 57 31 0 + 288 51 30 0 + 289 51 30 1 + 290 51 31 0 + 291 51 31 1 + 292 50 30 0 + 293 50 30 1 + 294 50 31 0 + 295 50 31 1 + 296 48 31 1 + 297 48 31 0 + 298 48 30 1 + 299 48 30 0 + 300 49 31 1 + 301 49 31 0 + 302 49 30 1 + 303 49 30 0 + 304 52 30 0 + 305 52 30 1 + 306 52 31 0 + 307 52 31 1 + 308 53 30 0 + 309 53 30 1 + 310 53 31 0 + 311 53 31 1 + 312 55 31 1 + 313 55 31 0 + 314 55 30 1 + 315 55 30 0 + 316 54 31 1 + 317 54 31 0 + 318 54 30 1 + 319 54 30 0 + 320 60 31 0 + 321 60 31 1 + 322 60 30 0 + 323 60 30 1 + 324 61 31 0 + 325 61 31 1 + 326 61 30 0 + 327 61 30 1 + 328 63 30 1 + 329 63 30 0 + 330 63 31 1 + 331 63 31 0 + 332 62 30 1 + 333 62 30 0 + 334 62 31 1 + 335 62 31 0 + 384 59 33 0 + 385 59 33 1 + 386 59 32 0 + 387 59 32 1 + 388 58 33 0 + 389 58 33 1 + 390 58 32 0 + 391 58 32 1 + 392 56 32 1 + 393 56 32 0 + 394 56 33 1 + 395 56 33 0 + 396 57 32 1 + 397 57 32 0 + 398 57 33 1 + 399 57 33 0 + 416 51 32 0 + 417 51 32 1 + 418 51 33 0 + 419 51 33 1 + 420 50 32 0 + 421 50 32 1 + 422 50 33 0 + 423 50 33 1 + 424 48 33 1 + 425 48 33 0 + 426 48 32 1 + 427 48 32 0 + 428 49 33 1 + 429 49 33 0 + 430 49 32 1 + 431 49 32 0 + 432 52 32 0 + 433 52 32 1 + 434 52 33 0 + 435 52 33 1 + 436 53 32 0 + 437 53 32 1 + 438 53 33 0 + 439 53 33 1 + 440 55 33 1 + 441 55 33 0 + 442 55 32 1 + 443 55 32 0 + 444 54 33 1 + 445 54 33 0 + 446 54 32 1 + 447 54 32 0 + 448 60 33 0 + 449 60 33 1 + 450 60 32 0 + 451 60 32 1 + 452 61 33 0 + 453 61 33 1 + 454 61 32 0 + 455 61 32 1 + 456 63 32 1 + 457 63 32 0 + 458 63 33 1 + 459 63 33 0 + 460 62 32 1 + 461 62 32 0 + 462 62 33 1 + 463 62 33 0 + 512 59 35 0 + 513 59 35 1 + 514 59 34 0 + 515 59 34 1 + 516 58 35 0 + 517 58 35 1 + 518 58 34 0 + 519 58 34 1 + 520 56 34 1 + 521 56 34 0 + 522 56 35 1 + 523 56 35 0 + 524 57 34 1 + 525 57 34 0 + 526 57 35 1 + 527 57 35 0 + 544 51 34 0 + 545 51 34 1 + 546 51 35 0 + 547 51 35 1 + 548 50 34 0 + 549 50 34 1 + 550 50 35 0 + 551 50 35 1 + 552 48 35 1 + 553 48 35 0 + 554 48 34 1 + 555 48 34 0 + 556 49 35 1 + 557 49 35 0 + 558 49 34 1 + 559 49 34 0 + 560 52 34 0 + 561 52 34 1 + 562 52 35 0 + 563 52 35 1 + 564 53 34 0 + 565 53 34 1 + 566 53 35 0 + 567 53 35 1 + 568 55 35 1 + 569 55 35 0 + 570 55 34 1 + 571 55 34 0 + 572 54 35 1 + 573 54 35 0 + 574 54 34 1 + 575 54 34 0 + 576 60 35 0 + 577 60 35 1 + 578 60 34 0 + 579 60 34 1 + 580 61 35 0 + 581 61 35 1 + 582 61 34 0 + 583 61 34 1 + 584 63 34 1 + 585 63 34 0 + 586 63 35 1 + 587 63 35 0 + 588 62 34 1 + 589 62 34 0 + 590 62 35 1 + 591 62 35 0 + 640 59 37 0 + 641 59 37 1 + 642 59 36 0 + 643 59 36 1 + 644 58 37 0 + 645 58 37 1 + 646 58 36 0 + 647 58 36 1 + 648 56 36 1 + 649 56 36 0 + 650 56 37 1 + 651 56 37 0 + 652 57 36 1 + 653 57 36 0 + 654 57 37 1 + 655 57 37 0 + 672 51 36 0 + 673 51 36 1 + 674 51 37 0 + 675 51 37 1 + 676 50 36 0 + 677 50 36 1 + 678 50 37 0 + 679 50 37 1 + 680 48 37 1 + 681 48 37 0 + 682 48 36 1 + 683 48 36 0 + 684 49 37 1 + 685 49 37 0 + 686 49 36 1 + 687 49 36 0 + 688 52 36 0 + 689 52 36 1 + 690 52 37 0 + 691 52 37 1 + 692 53 36 0 + 693 53 36 1 + 694 53 37 0 + 695 53 37 1 + 696 55 37 1 + 697 55 37 0 + 698 55 36 1 + 699 55 36 0 + 700 54 37 1 + 701 54 37 0 + 702 54 36 1 + 703 54 36 0 + 704 60 37 0 + 705 60 37 1 + 706 60 36 0 + 707 60 36 1 + 708 61 37 0 + 709 61 37 1 + 710 61 36 0 + 711 61 36 1 + 712 63 36 1 + 713 63 36 0 + 714 63 37 1 + 715 63 37 0 + 716 62 36 1 + 717 62 36 0 + 718 62 37 1 + 719 62 37 0 + 768 59 39 0 + 769 59 39 1 + 770 59 38 0 + 771 59 38 1 + 772 58 39 0 + 773 58 39 1 + 774 58 38 0 + 775 58 38 1 + 776 56 38 1 + 777 56 38 0 + 778 56 39 1 + 779 56 39 0 + 780 57 38 1 + 781 57 38 0 + 782 57 39 1 + 783 57 39 0 + 800 51 38 0 + 801 51 38 1 + 802 51 39 0 + 803 51 39 1 + 804 50 38 0 + 805 50 38 1 + 806 50 39 0 + 807 50 39 1 + 808 48 39 1 + 809 48 39 0 + 810 48 38 1 + 811 48 38 0 + 812 49 39 1 + 813 49 39 0 + 814 49 38 1 + 815 49 38 0 + 816 52 38 0 + 817 52 38 1 + 818 52 39 0 + 819 52 39 1 + 820 53 38 0 + 821 53 38 1 + 822 53 39 0 + 823 53 39 1 + 824 55 39 1 + 825 55 39 0 + 826 55 38 1 + 827 55 38 0 + 828 54 39 1 + 829 54 39 0 + 830 54 38 1 + 831 54 38 0 + 832 60 39 0 + 833 60 39 1 + 834 60 38 0 + 835 60 38 1 + 836 61 39 0 + 837 61 39 1 + 838 61 38 0 + 839 61 38 1 + 840 63 38 1 + 841 63 38 0 + 842 63 39 1 + 843 63 39 0 + 844 62 38 1 + 845 62 38 0 + 846 62 39 1 + 847 62 39 0 + 896 59 41 0 + 897 59 41 1 + 898 59 40 0 + 899 59 40 1 + 900 58 41 0 + 901 58 41 1 + 902 58 40 0 + 903 58 40 1 + 904 56 40 1 + 905 56 40 0 + 906 56 41 1 + 907 56 41 0 + 908 57 40 1 + 909 57 40 0 + 910 57 41 1 + 911 57 41 0 + 928 51 40 0 + 929 51 40 1 + 930 51 41 0 + 931 51 41 1 + 932 50 40 0 + 933 50 40 1 + 934 50 41 0 + 935 50 41 1 + 936 48 41 1 + 937 48 41 0 + 938 48 40 1 + 939 48 40 0 + 940 49 41 1 + 941 49 41 0 + 942 49 40 1 + 943 49 40 0 + 944 52 40 0 + 945 52 40 1 + 946 52 41 0 + 947 52 41 1 + 948 53 40 0 + 949 53 40 1 + 950 53 41 0 + 951 53 41 1 + 952 55 41 1 + 953 55 41 0 + 954 55 40 1 + 955 55 40 0 + 956 54 41 1 + 957 54 41 0 + 958 54 40 1 + 959 54 40 0 + 960 60 41 0 + 961 60 41 1 + 962 60 40 0 + 963 60 40 1 + 964 61 41 0 + 965 61 41 1 + 966 61 40 0 + 967 61 40 1 + 968 63 40 1 + 969 63 40 0 + 970 63 41 1 + 971 63 41 0 + 972 62 40 1 + 973 62 40 0 + 974 62 41 1 + 975 62 41 0 +1024 59 43 0 +1025 59 43 1 +1026 59 42 0 +1027 59 42 1 +1028 58 43 0 +1029 58 43 1 +1030 58 42 0 +1031 58 42 1 +1032 56 42 1 +1033 56 42 0 +1034 56 43 1 +1035 56 43 0 +1036 57 42 1 +1037 57 42 0 +1038 57 43 1 +1039 57 43 0 +1056 51 42 0 +1057 51 42 1 +1058 51 43 0 +1059 51 43 1 +1060 50 42 0 +1061 50 42 1 +1062 50 43 0 +1063 50 43 1 +1064 48 43 1 +1065 48 43 0 +1066 48 42 1 +1067 48 42 0 +1068 49 43 1 +1069 49 43 0 +1070 49 42 1 +1071 49 42 0 +1072 52 42 0 +1073 52 42 1 +1074 52 43 0 +1075 52 43 1 +1076 53 42 0 +1077 53 42 1 +1078 53 43 0 +1079 53 43 1 +1080 55 43 1 +1081 55 43 0 +1082 55 42 1 +1083 55 42 0 +1084 54 43 1 +1085 54 43 0 +1086 54 42 1 +1087 54 42 0 +1088 60 43 0 +1089 60 43 1 +1090 60 42 0 +1091 60 42 1 +1092 61 43 0 +1093 61 43 1 +1094 61 42 0 +1095 61 42 1 +1096 63 42 1 +1097 63 42 0 +1098 63 43 1 +1099 63 43 0 +1100 62 42 1 +1101 62 42 0 +1102 62 43 1 +1103 62 43 0 +1152 59 45 0 +1153 59 45 1 +1154 59 44 0 +1155 59 44 1 +1156 58 45 0 +1157 58 45 1 +1158 58 44 0 +1159 58 44 1 +1160 56 44 1 +1161 56 44 0 +1162 56 45 1 +1163 56 45 0 +1164 57 44 1 +1165 57 44 0 +1166 57 45 1 +1167 57 45 0 +1184 51 44 0 +1185 51 44 1 +1186 51 45 0 +1187 51 45 1 +1188 50 44 0 +1189 50 44 1 +1190 50 45 0 +1191 50 45 1 +1192 48 45 1 +1193 48 45 0 +1194 48 44 1 +1195 48 44 0 +1196 49 45 1 +1197 49 45 0 +1198 49 44 1 +1199 49 44 0 +1200 52 44 0 +1201 52 44 1 +1202 52 45 0 +1203 52 45 1 +1204 53 44 0 +1205 53 44 1 +1206 53 45 0 +1207 53 45 1 +1208 55 45 1 +1209 55 45 0 +1210 55 44 1 +1211 55 44 0 +1212 54 45 1 +1213 54 45 0 +1214 54 44 1 +1215 54 44 0 +1216 60 45 0 +1217 60 45 1 +1218 60 44 0 +1219 60 44 1 +1220 61 45 0 +1221 61 45 1 +1222 61 44 0 +1223 61 44 1 +1224 63 44 1 +1225 63 44 0 +1226 63 45 1 +1227 63 45 0 +1228 62 44 1 +1229 62 44 0 +1230 62 45 1 +1231 62 45 0 +1280 59 47 0 +1281 59 47 1 +1282 59 46 0 +1283 59 46 1 +1284 58 47 0 +1285 58 47 1 +1286 58 46 0 +1287 58 46 1 +1288 56 46 1 +1289 56 46 0 +1290 56 47 1 +1291 56 47 0 +1292 57 46 1 +1293 57 46 0 +1294 57 47 1 +1295 57 47 0 +1312 51 46 0 +1313 51 46 1 +1314 51 47 0 +1315 51 47 1 +1316 50 46 0 +1317 50 46 1 +1318 50 47 0 +1319 50 47 1 +1320 48 47 1 +1321 48 47 0 +1322 48 46 1 +1323 48 46 0 +1324 49 47 1 +1325 49 47 0 +1326 49 46 1 +1327 49 46 0 +1328 52 46 0 +1329 52 46 1 +1330 52 47 0 +1331 52 47 1 +1332 53 46 0 +1333 53 46 1 +1334 53 47 0 +1335 53 47 1 +1336 55 47 1 +1337 55 47 0 +1338 55 46 1 +1339 55 46 0 +1340 54 47 1 +1341 54 47 0 +1342 54 46 1 +1343 54 46 0 +1344 60 47 0 +1345 60 47 1 +1346 60 46 0 +1347 60 46 1 +1348 61 47 0 +1349 61 47 1 +1350 61 46 0 +1351 61 46 1 +1352 63 46 1 +1353 63 46 0 +1354 63 47 1 +1355 63 47 0 +1356 62 46 1 +1357 62 46 0 +1358 62 47 1 +1359 62 47 0 +1408 59 49 0 +1409 59 49 1 +1410 59 48 0 +1411 59 48 1 +1412 58 49 0 +1413 58 49 1 +1414 58 48 0 +1415 58 48 1 +1416 56 48 1 +1417 56 48 0 +1418 56 49 1 +1419 56 49 0 +1420 57 48 1 +1421 57 48 0 +1422 57 49 1 +1423 57 49 0 +1440 51 48 0 +1441 51 48 1 +1442 51 49 0 +1443 51 49 1 +1444 50 48 0 +1445 50 48 1 +1446 50 49 0 +1447 50 49 1 +1448 48 49 1 +1449 48 49 0 +1450 48 48 1 +1451 48 48 0 +1452 49 49 1 +1453 49 49 0 +1454 49 48 1 +1455 49 48 0 +1456 52 48 0 +1457 52 48 1 +1458 52 49 0 +1459 52 49 1 +1460 53 48 0 +1461 53 48 1 +1462 53 49 0 +1463 53 49 1 +1464 55 49 1 +1465 55 49 0 +1466 55 48 1 +1467 55 48 0 +1468 54 49 1 +1469 54 49 0 +1470 54 48 1 +1471 54 48 0 +1472 60 49 0 +1473 60 49 1 +1474 60 48 0 +1475 60 48 1 +1476 61 49 0 +1477 61 49 1 +1478 61 48 0 +1479 61 48 1 +1480 63 48 1 +1481 63 48 0 +1482 63 49 1 +1483 63 49 0 +1484 62 48 1 +1485 62 48 0 +1486 62 49 1 +1487 62 49 0 +1536 59 51 0 +1537 59 51 1 +1538 59 50 0 +1539 59 50 1 +1540 58 51 0 +1541 58 51 1 +1542 58 50 0 +1543 58 50 1 +1544 56 50 1 +1545 56 50 0 +1546 56 51 1 +1547 56 51 0 +1548 57 50 1 +1549 57 50 0 +1550 57 51 1 +1551 57 51 0 +1568 51 50 0 +1569 51 50 1 +1570 51 51 0 +1571 51 51 1 +1572 50 50 0 +1573 50 50 1 +1574 50 51 0 +1575 50 51 1 +1576 48 51 1 +1577 48 51 0 +1578 48 50 1 +1579 48 50 0 +1580 49 51 1 +1581 49 51 0 +1582 49 50 1 +1583 49 50 0 +1584 52 50 0 +1585 52 50 1 +1586 52 51 0 +1587 52 51 1 +1588 53 50 0 +1589 53 50 1 +1590 53 51 0 +1591 53 51 1 +1592 55 51 1 +1593 55 51 0 +1594 55 50 1 +1595 55 50 0 +1596 54 51 1 +1597 54 51 0 +1598 54 50 1 +1599 54 50 0 +1600 60 51 0 +1601 60 51 1 +1602 60 50 0 +1603 60 50 1 +1604 61 51 0 +1605 61 51 1 +1606 61 50 0 +1607 61 50 1 +1608 63 50 1 +1609 63 50 0 +1610 63 51 1 +1611 63 51 0 +1612 62 50 1 +1613 62 50 0 +1614 62 51 1 +1615 62 51 0 +1664 59 53 0 +1665 59 53 1 +1666 59 52 0 +1667 59 52 1 +1668 58 53 0 +1669 58 53 1 +1670 58 52 0 +1671 58 52 1 +1672 56 52 1 +1673 56 52 0 +1674 56 53 1 +1675 56 53 0 +1676 57 52 1 +1677 57 52 0 +1678 57 53 1 +1679 57 53 0 +1696 51 52 0 +1697 51 52 1 +1698 51 53 0 +1699 51 53 1 +1700 50 52 0 +1701 50 52 1 +1702 50 53 0 +1703 50 53 1 +1704 48 53 1 +1705 48 53 0 +1706 48 52 1 +1707 48 52 0 +1708 49 53 1 +1709 49 53 0 +1710 49 52 1 +1711 49 52 0 +1712 52 52 0 +1713 52 52 1 +1714 52 53 0 +1715 52 53 1 +1716 53 52 0 +1717 53 52 1 +1718 53 53 0 +1719 53 53 1 +1720 55 53 1 +1721 55 53 0 +1722 55 52 1 +1723 55 52 0 +1724 54 53 1 +1725 54 53 0 +1726 54 52 1 +1727 54 52 0 +1728 60 53 0 +1729 60 53 1 +1730 60 52 0 +1731 60 52 1 +1732 61 53 0 +1733 61 53 1 +1734 61 52 0 +1735 61 52 1 +1736 63 52 1 +1737 63 52 0 +1738 63 53 1 +1739 63 53 0 +1740 62 52 1 +1741 62 52 0 +1742 62 53 1 +1743 62 53 0 +1792 59 55 0 +1793 59 55 1 +1794 59 54 0 +1795 59 54 1 +1796 58 55 0 +1797 58 55 1 +1798 58 54 0 +1799 58 54 1 +1800 56 54 1 +1801 56 54 0 +1802 56 55 1 +1803 56 55 0 +1804 57 54 1 +1805 57 54 0 +1806 57 55 1 +1807 57 55 0 +1824 51 54 0 +1825 51 54 1 +1826 51 55 0 +1827 51 55 1 +1828 50 54 0 +1829 50 54 1 +1830 50 55 0 +1831 50 55 1 +1832 48 55 1 +1833 48 55 0 +1834 48 54 1 +1835 48 54 0 +1836 49 55 1 +1837 49 55 0 +1838 49 54 1 +1839 49 54 0 +1840 52 54 0 +1841 52 54 1 +1842 52 55 0 +1843 52 55 1 +1844 53 54 0 +1845 53 54 1 +1846 53 55 0 +1847 53 55 1 +1848 55 55 1 +1849 55 55 0 +1850 55 54 1 +1851 55 54 0 +1852 54 55 1 +1853 54 55 0 +1854 54 54 1 +1855 54 54 0 +1856 60 55 0 +1857 60 55 1 +1858 60 54 0 +1859 60 54 1 +1860 61 55 0 +1861 61 55 1 +1862 61 54 0 +1863 61 54 1 +1864 63 54 1 +1865 63 54 0 +1866 63 55 1 +1867 63 55 0 +1868 62 54 1 +1869 62 54 0 +1870 62 55 1 +1871 62 55 0 +2176 59 27 0 +2177 59 27 1 +2178 59 26 0 +2179 59 26 1 +2180 58 27 0 +2181 58 27 1 +2182 58 26 0 +2183 58 26 1 +2184 56 26 1 +2185 56 26 0 +2186 56 27 1 +2187 56 27 0 +2188 57 26 1 +2189 57 26 0 +2190 57 27 1 +2191 57 27 0 +2208 51 26 0 +2209 51 26 1 +2210 51 27 0 +2211 51 27 1 +2212 50 26 0 +2213 50 26 1 +2214 50 27 0 +2215 50 27 1 +2216 48 27 1 +2217 48 27 0 +2218 48 26 1 +2219 48 26 0 +2220 49 27 1 +2221 49 27 0 +2222 49 26 1 +2223 49 26 0 +2224 52 26 0 +2225 52 26 1 +2226 52 27 0 +2227 52 27 1 +2228 53 26 0 +2229 53 26 1 +2230 53 27 0 +2231 53 27 1 +2232 55 27 1 +2233 55 27 0 +2234 55 26 1 +2235 55 26 0 +2236 54 27 1 +2237 54 27 0 +2238 54 26 1 +2239 54 26 0 +2240 60 27 0 +2241 60 27 1 +2242 60 26 0 +2243 60 26 1 +2244 61 27 0 +2245 61 27 1 +2246 61 26 0 +2247 61 26 1 +2248 63 26 1 +2249 63 26 0 +2250 63 27 1 +2251 63 27 0 +2252 62 26 1 +2253 62 26 0 +2254 62 27 1 +2255 62 27 0 +2304 59 25 0 +2305 59 25 1 +2306 59 24 0 +2307 59 24 1 +2308 58 25 0 +2309 58 25 1 +2310 58 24 0 +2311 58 24 1 +2312 56 24 1 +2313 56 24 0 +2314 56 25 1 +2315 56 25 0 +2316 57 24 1 +2317 57 24 0 +2318 57 25 1 +2319 57 25 0 +2336 51 24 0 +2337 51 24 1 +2338 51 25 0 +2339 51 25 1 +2340 50 24 0 +2341 50 24 1 +2342 50 25 0 +2343 50 25 1 +2344 48 25 1 +2345 48 25 0 +2346 48 24 1 +2347 48 24 0 +2348 49 25 1 +2349 49 25 0 +2350 49 24 1 +2351 49 24 0 +2352 52 24 0 +2353 52 24 1 +2354 52 25 0 +2355 52 25 1 +2356 53 24 0 +2357 53 24 1 +2358 53 25 0 +2359 53 25 1 +2360 55 25 1 +2361 55 25 0 +2362 55 24 1 +2363 55 24 0 +2364 54 25 1 +2365 54 25 0 +2366 54 24 1 +2367 54 24 0 +2368 60 25 0 +2369 60 25 1 +2370 60 24 0 +2371 60 24 1 +2372 61 25 0 +2373 61 25 1 +2374 61 24 0 +2375 61 24 1 +2376 63 24 1 +2377 63 24 0 +2378 63 25 1 +2379 63 25 0 +2380 62 24 1 +2381 62 24 0 +2382 62 25 1 +2383 62 25 0 +2432 59 23 0 +2433 59 23 1 +2434 59 22 0 +2435 59 22 1 +2436 58 23 0 +2437 58 23 1 +2438 58 22 0 +2439 58 22 1 +2440 56 22 1 +2441 56 22 0 +2442 56 23 1 +2443 56 23 0 +2444 57 22 1 +2445 57 22 0 +2446 57 23 1 +2447 57 23 0 +2464 51 22 0 +2465 51 22 1 +2466 51 23 0 +2467 51 23 1 +2468 50 22 0 +2469 50 22 1 +2470 50 23 0 +2471 50 23 1 +2472 48 23 1 +2473 48 23 0 +2474 48 22 1 +2475 48 22 0 +2476 49 23 1 +2477 49 23 0 +2478 49 22 1 +2479 49 22 0 +2480 52 22 0 +2481 52 22 1 +2482 52 23 0 +2483 52 23 1 +2484 53 22 0 +2485 53 22 1 +2486 53 23 0 +2487 53 23 1 +2488 55 23 1 +2489 55 23 0 +2490 55 22 1 +2491 55 22 0 +2492 54 23 1 +2493 54 23 0 +2494 54 22 1 +2495 54 22 0 +2496 60 23 0 +2497 60 23 1 +2498 60 22 0 +2499 60 22 1 +2500 61 23 0 +2501 61 23 1 +2502 61 22 0 +2503 61 22 1 +2504 63 22 1 +2505 63 22 0 +2506 63 23 1 +2507 63 23 0 +2508 62 22 1 +2509 62 22 0 +2510 62 23 1 +2511 62 23 0 +2560 59 21 0 +2561 59 21 1 +2562 59 20 0 +2563 59 20 1 +2564 58 21 0 +2565 58 21 1 +2566 58 20 0 +2567 58 20 1 +2568 56 20 1 +2569 56 20 0 +2570 56 21 1 +2571 56 21 0 +2572 57 20 1 +2573 57 20 0 +2574 57 21 1 +2575 57 21 0 +2592 51 20 0 +2593 51 20 1 +2594 51 21 0 +2595 51 21 1 +2596 50 20 0 +2597 50 20 1 +2598 50 21 0 +2599 50 21 1 +2600 48 21 1 +2601 48 21 0 +2602 48 20 1 +2603 48 20 0 +2604 49 21 1 +2605 49 21 0 +2606 49 20 1 +2607 49 20 0 +2608 52 20 0 +2609 52 20 1 +2610 52 21 0 +2611 52 21 1 +2612 53 20 0 +2613 53 20 1 +2614 53 21 0 +2615 53 21 1 +2616 55 21 1 +2617 55 21 0 +2618 55 20 1 +2619 55 20 0 +2620 54 21 1 +2621 54 21 0 +2622 54 20 1 +2623 54 20 0 +2624 60 21 0 +2625 60 21 1 +2626 60 20 0 +2627 60 20 1 +2628 61 21 0 +2629 61 21 1 +2630 61 20 0 +2631 61 20 1 +2632 63 20 1 +2633 63 20 0 +2634 63 21 1 +2635 63 21 0 +2636 62 20 1 +2637 62 20 0 +2638 62 21 1 +2639 62 21 0 +2688 59 19 0 +2689 59 19 1 +2690 59 18 0 +2691 59 18 1 +2692 58 19 0 +2693 58 19 1 +2694 58 18 0 +2695 58 18 1 +2696 56 18 1 +2697 56 18 0 +2698 56 19 1 +2699 56 19 0 +2700 57 18 1 +2701 57 18 0 +2702 57 19 1 +2703 57 19 0 +2720 51 18 0 +2721 51 18 1 +2722 51 19 0 +2723 51 19 1 +2724 50 18 0 +2725 50 18 1 +2726 50 19 0 +2727 50 19 1 +2728 48 19 1 +2729 48 19 0 +2730 48 18 1 +2731 48 18 0 +2732 49 19 1 +2733 49 19 0 +2734 49 18 1 +2735 49 18 0 +2736 52 18 0 +2737 52 18 1 +2738 52 19 0 +2739 52 19 1 +2740 53 18 0 +2741 53 18 1 +2742 53 19 0 +2743 53 19 1 +2744 55 19 1 +2745 55 19 0 +2746 55 18 1 +2747 55 18 0 +2748 54 19 1 +2749 54 19 0 +2750 54 18 1 +2751 54 18 0 +2752 60 19 0 +2753 60 19 1 +2754 60 18 0 +2755 60 18 1 +2756 61 19 0 +2757 61 19 1 +2758 61 18 0 +2759 61 18 1 +2760 63 18 1 +2761 63 18 0 +2762 63 19 1 +2763 63 19 0 +2764 62 18 1 +2765 62 18 0 +2766 62 19 1 +2767 62 19 0 +2816 59 17 0 +2817 59 17 1 +2818 59 16 0 +2819 59 16 1 +2820 58 17 0 +2821 58 17 1 +2822 58 16 0 +2823 58 16 1 +2824 56 16 1 +2825 56 16 0 +2826 56 17 1 +2827 56 17 0 +2828 57 16 1 +2829 57 16 0 +2830 57 17 1 +2831 57 17 0 +2848 51 16 0 +2849 51 16 1 +2850 51 17 0 +2851 51 17 1 +2852 50 16 0 +2853 50 16 1 +2854 50 17 0 +2855 50 17 1 +2856 48 17 1 +2857 48 17 0 +2858 48 16 1 +2859 48 16 0 +2860 49 17 1 +2861 49 17 0 +2862 49 16 1 +2863 49 16 0 +2864 52 16 0 +2865 52 16 1 +2866 52 17 0 +2867 52 17 1 +2868 53 16 0 +2869 53 16 1 +2870 53 17 0 +2871 53 17 1 +2872 55 17 1 +2873 55 17 0 +2874 55 16 1 +2875 55 16 0 +2876 54 17 1 +2877 54 17 0 +2878 54 16 1 +2879 54 16 0 +2880 60 17 0 +2881 60 17 1 +2882 60 16 0 +2883 60 16 1 +2884 61 17 0 +2885 61 17 1 +2886 61 16 0 +2887 61 16 1 +2888 63 16 1 +2889 63 16 0 +2890 63 17 1 +2891 63 17 0 +2892 62 16 1 +2893 62 16 0 +2894 62 17 1 +2895 62 17 0 +2944 59 15 0 +2945 59 15 1 +2946 59 14 0 +2947 59 14 1 +2948 58 15 0 +2949 58 15 1 +2950 58 14 0 +2951 58 14 1 +2952 56 14 1 +2953 56 14 0 +2954 56 15 1 +2955 56 15 0 +2956 57 14 1 +2957 57 14 0 +2958 57 15 1 +2959 57 15 0 +2976 51 14 0 +2977 51 14 1 +2978 51 15 0 +2979 51 15 1 +2980 50 14 0 +2981 50 14 1 +2982 50 15 0 +2983 50 15 1 +2984 48 15 1 +2985 48 15 0 +2986 48 14 1 +2987 48 14 0 +2988 49 15 1 +2989 49 15 0 +2990 49 14 1 +2991 49 14 0 +2992 52 14 0 +2993 52 14 1 +2994 52 15 0 +2995 52 15 1 +2996 53 14 0 +2997 53 14 1 +2998 53 15 0 +2999 53 15 1 +3000 55 15 1 +3001 55 15 0 +3002 55 14 1 +3003 55 14 0 +3004 54 15 1 +3005 54 15 0 +3006 54 14 1 +3007 54 14 0 +3008 60 15 0 +3009 60 15 1 +3010 60 14 0 +3011 60 14 1 +3012 61 15 0 +3013 61 15 1 +3014 61 14 0 +3015 61 14 1 +3016 63 14 1 +3017 63 14 0 +3018 63 15 1 +3019 63 15 0 +3020 62 14 1 +3021 62 14 0 +3022 62 15 1 +3023 62 15 0 +3072 59 13 0 +3073 59 13 1 +3074 59 12 0 +3075 59 12 1 +3076 58 13 0 +3077 58 13 1 +3078 58 12 0 +3079 58 12 1 +3080 56 12 1 +3081 56 12 0 +3082 56 13 1 +3083 56 13 0 +3084 57 12 1 +3085 57 12 0 +3086 57 13 1 +3087 57 13 0 +3104 51 12 0 +3105 51 12 1 +3106 51 13 0 +3107 51 13 1 +3108 50 12 0 +3109 50 12 1 +3110 50 13 0 +3111 50 13 1 +3112 48 13 1 +3113 48 13 0 +3114 48 12 1 +3115 48 12 0 +3116 49 13 1 +3117 49 13 0 +3118 49 12 1 +3119 49 12 0 +3120 52 12 0 +3121 52 12 1 +3122 52 13 0 +3123 52 13 1 +3124 53 12 0 +3125 53 12 1 +3126 53 13 0 +3127 53 13 1 +3128 55 13 1 +3129 55 13 0 +3130 55 12 1 +3131 55 12 0 +3132 54 13 1 +3133 54 13 0 +3134 54 12 1 +3135 54 12 0 +3136 60 13 0 +3137 60 13 1 +3138 60 12 0 +3139 60 12 1 +3140 61 13 0 +3141 61 13 1 +3142 61 12 0 +3143 61 12 1 +3144 63 12 1 +3145 63 12 0 +3146 63 13 1 +3147 63 13 0 +3148 62 12 1 +3149 62 12 0 +3150 62 13 1 +3151 62 13 0 +3200 59 11 0 +3201 59 11 1 +3202 59 10 0 +3203 59 10 1 +3204 58 11 0 +3205 58 11 1 +3206 58 10 0 +3207 58 10 1 +3208 56 10 1 +3209 56 10 0 +3210 56 11 1 +3211 56 11 0 +3212 57 10 1 +3213 57 10 0 +3214 57 11 1 +3215 57 11 0 +3232 51 10 0 +3233 51 10 1 +3234 51 11 0 +3235 51 11 1 +3236 50 10 0 +3237 50 10 1 +3238 50 11 0 +3239 50 11 1 +3240 48 11 1 +3241 48 11 0 +3242 48 10 1 +3243 48 10 0 +3244 49 11 1 +3245 49 11 0 +3246 49 10 1 +3247 49 10 0 +3248 52 10 0 +3249 52 10 1 +3250 52 11 0 +3251 52 11 1 +3252 53 10 0 +3253 53 10 1 +3254 53 11 0 +3255 53 11 1 +3256 55 11 1 +3257 55 11 0 +3258 55 10 1 +3259 55 10 0 +3260 54 11 1 +3261 54 11 0 +3262 54 10 1 +3263 54 10 0 +3264 60 11 0 +3265 60 11 1 +3266 60 10 0 +3267 60 10 1 +3268 61 11 0 +3269 61 11 1 +3270 61 10 0 +3271 61 10 1 +3272 63 10 1 +3273 63 10 0 +3274 63 11 1 +3275 63 11 0 +3276 62 10 1 +3277 62 10 0 +3278 62 11 1 +3279 62 11 0 +3328 59 9 0 +3329 59 9 1 +3330 59 8 0 +3331 59 8 1 +3332 58 9 0 +3333 58 9 1 +3334 58 8 0 +3335 58 8 1 +3336 56 8 1 +3337 56 8 0 +3338 56 9 1 +3339 56 9 0 +3340 57 8 1 +3341 57 8 0 +3342 57 9 1 +3343 57 9 0 +3360 51 8 0 +3361 51 8 1 +3362 51 9 0 +3363 51 9 1 +3364 50 8 0 +3365 50 8 1 +3366 50 9 0 +3367 50 9 1 +3368 48 9 1 +3369 48 9 0 +3370 48 8 1 +3371 48 8 0 +3372 49 9 1 +3373 49 9 0 +3374 49 8 1 +3375 49 8 0 +3376 52 8 0 +3377 52 8 1 +3378 52 9 0 +3379 52 9 1 +3380 53 8 0 +3381 53 8 1 +3382 53 9 0 +3383 53 9 1 +3384 55 9 1 +3385 55 9 0 +3386 55 8 1 +3387 55 8 0 +3388 54 9 1 +3389 54 9 0 +3390 54 8 1 +3391 54 8 0 +3392 60 9 0 +3393 60 9 1 +3394 60 8 0 +3395 60 8 1 +3396 61 9 0 +3397 61 9 1 +3398 61 8 0 +3399 61 8 1 +3400 63 8 1 +3401 63 8 0 +3402 63 9 1 +3403 63 9 0 +3404 62 8 1 +3405 62 8 0 +3406 62 9 1 +3407 62 9 0 +3456 59 7 0 +3457 59 7 1 +3458 59 6 0 +3459 59 6 1 +3460 58 7 0 +3461 58 7 1 +3462 58 6 0 +3463 58 6 1 +3464 56 6 1 +3465 56 6 0 +3466 56 7 1 +3467 56 7 0 +3468 57 6 1 +3469 57 6 0 +3470 57 7 1 +3471 57 7 0 +3488 51 6 0 +3489 51 6 1 +3490 51 7 0 +3491 51 7 1 +3492 50 6 0 +3493 50 6 1 +3494 50 7 0 +3495 50 7 1 +3496 48 7 1 +3497 48 7 0 +3498 48 6 1 +3499 48 6 0 +3500 49 7 1 +3501 49 7 0 +3502 49 6 1 +3503 49 6 0 +3504 52 6 0 +3505 52 6 1 +3506 52 7 0 +3507 52 7 1 +3508 53 6 0 +3509 53 6 1 +3510 53 7 0 +3511 53 7 1 +3512 55 7 1 +3513 55 7 0 +3514 55 6 1 +3515 55 6 0 +3516 54 7 1 +3517 54 7 0 +3518 54 6 1 +3519 54 6 0 +3520 60 7 0 +3521 60 7 1 +3522 60 6 0 +3523 60 6 1 +3524 61 7 0 +3525 61 7 1 +3526 61 6 0 +3527 61 6 1 +3528 63 6 1 +3529 63 6 0 +3530 63 7 1 +3531 63 7 0 +3532 62 6 1 +3533 62 6 0 +3534 62 7 1 +3535 62 7 0 +3584 59 5 0 +3585 59 5 1 +3586 59 4 0 +3587 59 4 1 +3588 58 5 0 +3589 58 5 1 +3590 58 4 0 +3591 58 4 1 +3592 56 4 1 +3593 56 4 0 +3594 56 5 1 +3595 56 5 0 +3596 57 4 1 +3597 57 4 0 +3598 57 5 1 +3599 57 5 0 +3616 51 4 0 +3617 51 4 1 +3618 51 5 0 +3619 51 5 1 +3620 50 4 0 +3621 50 4 1 +3622 50 5 0 +3623 50 5 1 +3624 48 5 1 +3625 48 5 0 +3626 48 4 1 +3627 48 4 0 +3628 49 5 1 +3629 49 5 0 +3630 49 4 1 +3631 49 4 0 +3632 52 4 0 +3633 52 4 1 +3634 52 5 0 +3635 52 5 1 +3636 53 4 0 +3637 53 4 1 +3638 53 5 0 +3639 53 5 1 +3640 55 5 1 +3641 55 5 0 +3642 55 4 1 +3643 55 4 0 +3644 54 5 1 +3645 54 5 0 +3646 54 4 1 +3647 54 4 0 +3648 60 5 0 +3649 60 5 1 +3650 60 4 0 +3651 60 4 1 +3652 61 5 0 +3653 61 5 1 +3654 61 4 0 +3655 61 4 1 +3656 63 4 1 +3657 63 4 0 +3658 63 5 1 +3659 63 5 0 +3660 62 4 1 +3661 62 4 0 +3662 62 5 1 +3663 62 5 0 +3712 59 3 0 +3713 59 3 1 +3714 59 2 0 +3715 59 2 1 +3716 58 3 0 +3717 58 3 1 +3718 58 2 0 +3719 58 2 1 +3720 56 2 1 +3721 56 2 0 +3722 56 3 1 +3723 56 3 0 +3724 57 2 1 +3725 57 2 0 +3726 57 3 1 +3727 57 3 0 +3744 51 2 0 +3745 51 2 1 +3746 51 3 0 +3747 51 3 1 +3748 50 2 0 +3749 50 2 1 +3750 50 3 0 +3751 50 3 1 +3752 48 3 1 +3753 48 3 0 +3754 48 2 1 +3755 48 2 0 +3756 49 3 1 +3757 49 3 0 +3758 49 2 1 +3759 49 2 0 +3760 52 2 0 +3761 52 2 1 +3762 52 3 0 +3763 52 3 1 +3764 53 2 0 +3765 53 2 1 +3766 53 3 0 +3767 53 3 1 +3768 55 3 1 +3769 55 3 0 +3770 55 2 1 +3771 55 2 0 +3772 54 3 1 +3773 54 3 0 +3774 54 2 1 +3775 54 2 0 +3776 60 3 0 +3777 60 3 1 +3778 60 2 0 +3779 60 2 1 +3780 61 3 0 +3781 61 3 1 +3782 61 2 0 +3783 61 2 1 +3784 63 2 1 +3785 63 2 0 +3786 63 3 1 +3787 63 3 0 +3788 62 2 1 +3789 62 2 0 +3790 62 3 1 +3791 62 3 0 +3840 59 1 0 +3841 59 1 1 +3842 59 0 0 +3843 59 0 1 +3844 58 1 0 +3845 58 1 1 +3846 58 0 0 +3847 58 0 1 +3848 56 0 1 +3849 56 0 0 +3850 56 1 1 +3851 56 1 0 +3852 57 0 1 +3853 57 0 0 +3854 57 1 1 +3855 57 1 0 +3872 51 0 0 +3873 51 0 1 +3874 51 1 0 +3875 51 1 1 +3876 50 0 0 +3877 50 0 1 +3878 50 1 0 +3879 50 1 1 +3880 48 1 1 +3881 48 1 0 +3882 48 0 1 +3883 48 0 0 +3884 49 1 1 +3885 49 1 0 +3886 49 0 1 +3887 49 0 0 +3888 52 0 0 +3889 52 0 1 +3890 52 1 0 +3891 52 1 1 +3892 53 0 0 +3893 53 0 1 +3894 53 1 0 +3895 53 1 1 +3896 55 1 1 +3897 55 1 0 +3898 55 0 1 +3899 55 0 0 +3900 54 1 1 +3901 54 1 0 +3902 54 0 1 +3903 54 0 0 +3904 60 1 0 +3905 60 1 1 +3906 60 0 0 +3907 60 0 1 +3908 61 1 0 +3909 61 1 1 +3910 61 0 0 +3911 61 0 1 +3912 63 0 1 +3913 63 0 0 +3914 63 1 1 +3915 63 1 0 +3916 62 0 1 +3917 62 0 0 +3918 62 1 1 +3919 62 1 0 diff --git a/Detectors/PHOS/base/include/PHOSBase/Mapping.h b/Detectors/PHOS/base/include/PHOSBase/Mapping.h new file mode 100644 index 0000000000000..f298728a3217d --- /dev/null +++ b/Detectors/PHOS/base/include/PHOSBase/Mapping.h @@ -0,0 +1,85 @@ +// 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 Mapping +/// \brief Checks validity of hardware address (HW) and transform it to digit AbsId index +/// +/// \author Dmitri Peresunko +/// \since Jan.2020 +/// + +#ifndef PHOSMAPPING_H_ +#define PHOSMAPPING_H_ + +#include <string_view> +#include <vector> +#include <utility> +#include "Rtypes.h" + +namespace o2 +{ + +namespace phos +{ + +class Mapping +{ + public: + enum ErrorStatus { kOK, + kWrongDDL, + kWrongHWAddress, + kWrongAbsId, + kWrongCaloFlag, + kNotInitialized }; + static constexpr short NCHANNELS = 14337; ///< Number of channels starting from 1 + static constexpr short NHWPERDDL = 2048; ///< Number of HW addressed per DDL + static constexpr short NDDL = 14; ///< Total number of DDLs + + enum CaloFlag { kHighGain, + kLowGain, + kTRU }; + + Mapping() = default; + Mapping(std::basic_string_view<char> path); + ~Mapping() = default; + + /// \brief convert hardware address to absId and caloFlag + ErrorStatus hwToAbsId(short ddl, short hw, short& absId, CaloFlag& caloFlag); + /// \brief convert absId and caloflag to hardware address and ddl + ErrorStatus absIdTohw(short absId, short caloFlag, short& ddl, short& hwAddr); + + /// \brief convert ddl number to crorc and link number (TODO!!!) + void ddlToCrorcLink(short iddl, short& crorc, short& link) + { + crorc = iddl / 8; + link = iddl % 8; + } + + ErrorStatus setMapping(); + + protected: + /// \brief Construct vector for conversion only if necessary + ErrorStatus constructAbsToHWMatrix(); + + private: + std::string mPath = ""; ///< path to mapping files + bool mInitialized = false; ///< If conversion tables created + bool mInvInitialized = false; ///< If inverse conversion tables created + short mAbsId[NDDL][NHWPERDDL] = {0}; ///< Conversion table (ddl,branch,fec,chip,channel) to absId + CaloFlag mCaloFlag[NDDL][NHWPERDDL] = {kTRU}; ///< Conversion table (ddl,branch,fec,chip,channel) to absId + short mAbsToHW[NCHANNELS][3][2] = {0}; ///< Conversion table (AbsId,caloFlag) to pair (ddl, hw address) + + ClassDefNV(Mapping, 1); +}; // End of Mapping + +} // namespace phos + +} // namespace o2 +#endif diff --git a/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h b/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h index ceb1c49ed22eb..3fc9478608242 100644 --- a/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h +++ b/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h @@ -50,6 +50,19 @@ struct PHOSSimParams : public o2::conf::ConfigurableParamHelper<PHOSSimParams> { float mMinNoiseTime = -200.; ///< minimum time in noise channels (in ns) float mMaxNoiseTime = 2000.; ///< minimum time in noise channels (in ns) + //Parameters used in Raw simulation + float mSampleDecayTime = 0.047619048; ///< Time parameter in Gamma2 function (1/tau, 100.e-9/2.1e-6) + + // //Parameters used in raw data reconstruction + // bool mSubtractPedestal = false ; ///< subtract pedestals + // bool mCreateSampleQualityOutput = false ; ///< Create stream of sample quality + // bool mApplyBadMap = false ; ///< Apply bad map in sample fitting + // short mZeroSuppression = 5; ///< Zero suppression in ADC counts + // short mMaxSampleLength = 35; ///< Maximal length of sample + // short mChiMinCut = 0 ; ///< Minimal cut on sample quality + // short mChiMaxCut = 1000; ///< Maximal cut on sample quality + // std::string mFitterVersion = "default"; ///< version of raw fitter to be used + //Parameters used in clusterization float mLogWeight = 4.5; ///< Cutoff used in log. weight calculation float mDigitMinEnergy = 0.010; ///< Minimal energy of digits to be used in cluster (GeV) diff --git a/Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h b/Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h new file mode 100644 index 0000000000000..67ac6374685d1 --- /dev/null +++ b/Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h @@ -0,0 +1,185 @@ +// 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_PHOS_RCUTRAILER_H +#define ALICEO2_PHOS_RCUTRAILER_H + +#include <exception> +#include <iosfwd> +#include <string> +#include <cstdint> +#include <gsl/span> +#include "Rtypes.h" + +namespace o2 +{ + +namespace phos +{ + +/// \class RCUTrailer +/// \brief Information stored in the RCU trailer +/// \ingroup PHOSbase +/// +/// The RCU trailer can be found at the end of +/// the payload and contains general information +/// sent by the SRU. +class RCUTrailer +{ + public: + /// \class Error + /// \brief Error handling of the + class Error : public std::exception + { + public: + /// \enum ErrorType_t + /// \brief Error codes for different error types + enum class ErrorType_t { + DECODING_INVALID, ///< Invalid words during decoding + SIZE_INVALID, ///< Invalid trailer size + SAMPLINGFREQ_INVALID, ///< Invalid sampling frequency + L1PHASE_INVALID ///< Invalid L1 phase + }; + + /// \brief Constructor + /// \param errtype Code of the error type + /// \param message corresponding error message + /// + /// Initializing the error with error code and message. + /// To be called when the exception is raised. + Error(ErrorType_t errtype, const char* message) : mErrorType(errtype), mErrorMessage(message) {} + + /// \brief Destructor + ~Error() noexcept override = default; + + /// \brief Access to the error message + /// \return Error message related to the exception type + const char* what() const noexcept override { return mErrorMessage.data(); } + + /// \brief Access to error code + /// \return Error code of the exception type + ErrorType_t getErrorType() const noexcept { return mErrorType; } + + private: + ErrorType_t mErrorType; ///< Type of the error + std::string mErrorMessage; ///< Error Message + }; + + /// \brief Constructor + RCUTrailer() = default; + + /// \brief destructor + ~RCUTrailer() = default; + + /// \brief Reset the RCU trailer + /// + /// Setting all values to 0 + void reset(); + + /// \brief Prints the contents of the RCU trailer data + /// \param stream stream the trailer has to be put on + void printStream(std::ostream& stream) const; + + /// \brief Decode RCU trailer from the 32-bit words in the raw buffer + /// \param buffer Raw buffer from which to read the trailer + /// + /// Read the RCU trailer according to the RCU formware version + /// specified in CDH. + void constructFromRawPayload(const gsl::span<const uint32_t> payloadwords); + + unsigned int getFECErrorsA() const { return mFECERRA; } + unsigned int getFECErrorsB() const { return mFECERRB; } + unsigned short getErrorsG2() const { return mERRREG2; } + unsigned int getErrorsG3() const { return mERRREG3; } + unsigned short getActiveFECsA() const { return mActiveFECsA; } + unsigned short getActiveFECsB() const { return mActiveFECsB; } + unsigned int getAltroCFGReg1() const { return mAltroCFG1; } + unsigned int getAltroCFGReg2() const { return mAltroCFG2; } + int getRCUID() const { return mRCUId; } + unsigned int getTrailerSize() const { return mTrailerSize; } + unsigned int getPayloadSize() const { return mPayloadSize; } + unsigned char getFirmwareVersion() const { return mFirmwareVersion; } + + unsigned short getNumberOfChannelAddressMismatch() const { return (mERRREG3 & 0xFFF); } + unsigned short getNumberOfChannelLengthMismatch() const { return ((mERRREG3 >> 12) & 0x1FFF); } + unsigned char getBaselineCorrection() const { return mAltroCFG1 & 0xF; } + bool getPolarity() const { return (mAltroCFG1 >> 4) & 0x1; } + unsigned char getNumberOfPresamples() const { return (mAltroCFG1 >> 5) & 0x3; } + unsigned char getNumberOfPostsamples() const { return (mAltroCFG1 >> 7) & 0xF; } + bool hasSecondBaselineCorr() const { return (mAltroCFG1 >> 11) & 0x1; } + unsigned char getGlitchFilter() const { return (mAltroCFG1 >> 12) & 0x3; } + unsigned char getNumberOfNonZeroSuppressedPostsamples() const { return (mAltroCFG1 >> 14) & 0x7; } + unsigned char getNumberOfNonZeroSuppressedPresamples() const { return (mAltroCFG1 >> 17) & 0x3; } + bool hasZeroSuppression() const { return (mAltroCFG1 >> 19) & 0x1; } + bool getNumberOfAltroBuffers() const { return (mAltroCFG2 >> 24) & 0x1; } + unsigned char getNumberOfPretriggerSamples() const { return (mAltroCFG2 >> 20) & 0xF; } + unsigned short getNumberOfSamplesPerChannel() const { return (mAltroCFG2 >> 10) & 0x3FF; } + bool isSparseReadout() const { return (mAltroCFG2 >> 9) & 0x1; } + + /// \brief Access to the sampling time + /// \return Sampling time in seconds. + /// \throw Error if the RCU trailer was not properly initializied + double getTimeSample() const; + + /// \brief set time sample + /// \param timesample Time sample (in ns) + void setTimeSample(double timesample); + + /// \brief Access to the L1 phase + /// \return L1 phase w.r.t to the LHC clock + double getL1Phase() const; + + /// \brief Set the L1 phase + /// \param l1phase L1 phase (in ns) + void setL1Phase(double l1phase); + + void setFECErrorsA(unsigned int value) { mFECERRA = value; } + void setFECErrorsB(unsigned int value) { mFECERRB = value; } + void setErrorsG2(unsigned short value) { mERRREG2 = value; } + void setErrorsG3(unsigned int value) { mERRREG3 = value; } + void setActiveFECsA(unsigned short value) { mActiveFECsA = value; } + void setActiveFECsB(unsigned short value) { mActiveFECsB = value; } + void setAltroCFGReg1(unsigned int value) { mAltroCFG1 = value; } + void setAltroCFGReg2(unsigned int value) { mAltroCFG2 = value; } + void setFirmwareVersion(unsigned char version) { mFirmwareVersion = version; } + void setPayloadSize(unsigned int size) { mPayloadSize = size; } + + /// \brief checlks whether the RCU trailer is initialzied + /// \return True if the trailer is initialized, false otherwise + bool isInitialized() const { return mIsInitialized; } + + std::vector<uint32_t> encode() const; + + static RCUTrailer constructFromPayloadWords(const gsl::span<const uint32_t> payloadwords); + + private: + int mRCUId = -1; ///< current RCU identifier + unsigned char mFirmwareVersion = 0; ///< RCU firmware version + unsigned int mTrailerSize = 0; ///< Size of the trailer (in number of 32 bit words) + unsigned int mPayloadSize = 0; ///< Size of the payload (in nunber of 32 bit words) + unsigned int mFECERRA = 0; ///< contains errors related to ALTROBUS transactions + unsigned int mFECERRB = 0; ///< contains errors related to ALTROBUS transactions + unsigned short mERRREG2 = 0; ///< contains errors related to ALTROBUS transactions or trailer of ALTRO channel block + unsigned int mERRREG3 = 0; ///< contains number of altro channels skipped due to an address mismatch + unsigned short mActiveFECsA = 0; ///< bit pattern of active FECs in branch A + unsigned short mActiveFECsB = 0; ///< bit pattern of active FECs in branch B + unsigned int mAltroCFG1 = 0; ///< ALTROCFG1 register + unsigned int mAltroCFG2 = 0; ///< ALTROCFG2 and ALTROIF register + bool mIsInitialized = false; ///< Flag whether RCU trailer is initialized for the given raw event + + ClassDefNV(RCUTrailer, 1); +}; + +std::ostream& operator<<(std::ostream& stream, const RCUTrailer& trailer); + +} // namespace phos + +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/PHOS/base/src/Geometry.cxx b/Detectors/PHOS/base/src/Geometry.cxx index fd625a50e1e5c..49d4c2cfe4247 100644 --- a/Detectors/PHOS/base/src/Geometry.cxx +++ b/Detectors/PHOS/base/src/Geometry.cxx @@ -19,19 +19,14 @@ Geometry* Geometry::sGeom = nullptr; Geometry::Geometry(const std::string_view name) : mGeoName(name) {} -// static Geometry* Geometry::GetInstance(const std::string_view name) -// { -// if(sGeom){ -// if(sGeom->GetName()==name){ -// return sGeom; -// } -// else{ -// delete sGeom ; -// } -// } -// sGeom = new Geometry(name) ; -// return sGeom; -// } +// module numbering: +// start from module 0 (non-existing), 1 (half-module), 2 (bottom),... 4(highest) +// absId: +// start from 1 till 5*64*56. Numbering in each module starts at bottom left and first go in z direction: +// 56 112 3584 +// ... ... ... +// 1 57 ...3529 +// relid[3]: (module number[0...4], iphi[1...64], iz[1...56]) short Geometry::relToAbsId(char moduleNumber, int strip, int cell) { @@ -45,7 +40,7 @@ short Geometry::relToAbsId(char moduleNumber, int strip, int cell) short row = nStrpZ - (strip - 1) % nStrpZ; short col = (int)std::ceil((float)strip / (nStrpZ)) - 1; - return (moduleNumber - 1) * nCrystalsInModule + row * 2 + (col * nCellsXInStrip + (cell - 1) / 2) * nZ - + return moduleNumber * nCrystalsInModule + row * 2 + (col * nCellsXInStrip + (cell - 1) / 2) * nZ - (cell & 1 ? 1 : 0); } @@ -60,7 +55,7 @@ bool Geometry::absToRelNumbering(short absId, char* relid) short phosmodulenumber = (absId - 1) / (nZ * nPhi); - relid[0] = phosmodulenumber + 1; + relid[0] = phosmodulenumber; absId -= phosmodulenumber * nPhi * nZ; relid[1] = 1 + (absId - 1) / nZ; relid[2] = absId - (relid[1] - 1) * nZ; @@ -72,7 +67,7 @@ char Geometry::absIdToModule(short absId) const short nZ = 56; const short nPhi = 64; - return 1 + (absId - 1) / (nZ * nPhi); + return (absId - 1) / (nZ * nPhi); } int Geometry::areNeighbours(short absId1, short absId2) @@ -131,9 +126,9 @@ bool Geometry::relToAbsNumbering(const char* relId, short& absId) const short nPhi = 64; // nStripZ * nCellsZInStrip absId = - (relId[0] - 1) * nPhi * nZ + // the offset of PHOS modules - (relId[1] - 1) * nZ + // the offset along phi - relId[2]; // the offset along z + relId[0] * nPhi * nZ + // the offset of PHOS modules + (relId[1] - 1) * nZ + // the offset along phi + relId[2]; // the offset along z return true; } diff --git a/Detectors/PHOS/base/src/Mapping.cxx b/Detectors/PHOS/base/src/Mapping.cxx new file mode 100644 index 0000000000000..24468b1c56830 --- /dev/null +++ b/Detectors/PHOS/base/src/Mapping.cxx @@ -0,0 +1,166 @@ +// 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 Mapping.cxx +/// \author Dmitri Peresunko + +#include <fstream> +#include "TSystem.h" +#include "FairLogger.h" +#include "PHOSBase/Mapping.h" +#include "PHOSBase/Geometry.h" + +using namespace o2::phos; + +Mapping::Mapping(std::basic_string_view<char> path) : mPath(path), + mInitialized(false) +{ +} +//_______________________________________________________ +Mapping::ErrorStatus Mapping::hwToAbsId(short ddl, short hwAddr, short& absId, CaloFlag& caloFlag) +{ + + if (!mInitialized) { + LOG(ERROR) << "Mapping not initialized"; + return kNotInitialized; + } + + if (ddl < 0 || ddl > 14) { + return kWrongDDL; + } + if (hwAddr < 0 || hwAddr >= NHWPERDDL) { + return kWrongHWAddress; + } + + //transform + absId = mAbsId[ddl][hwAddr]; + caloFlag = mCaloFlag[ddl][hwAddr]; + + if (absId > NCHANNELS) { + absId = 0; + return kWrongHWAddress; + } + return kOK; +} +//_______________________________________________________ +Mapping::ErrorStatus Mapping::absIdTohw(short absId, short caloFlag, short& ddl, short& hwAddr) +{ + + if (absId < 0 || absId > NCHANNELS) { + ddl = 0; + hwAddr = 0; + return kWrongAbsId; + } + if (caloFlag < 0 || caloFlag > 2) { + ddl = 0; + hwAddr = 0; + return kWrongCaloFlag; + } + + if (!mInitialized) { + LOG(ERROR) << "Mapping not initialized"; + return kNotInitialized; + } + + ddl = mAbsToHW[absId][caloFlag][0]; + hwAddr = mAbsToHW[absId][caloFlag][1]; + return kOK; +} +//_______________________________________________________ +Mapping::ErrorStatus Mapping::setMapping() +{ + //Read mapping from data files a-la Run2 + + o2::phos::Geometry* geom = o2::phos::Geometry::GetInstance(); + + std::string p; + if (mPath.empty()) { //use default path + p = gSystem->Getenv("O2_ROOT"); + p += "/share/Detectors/PHOS/files"; + } else { + p = mPath.data(); + } + + for (short m = 0; m < 4; m++) { //modules + for (short i = 0; i < 4; i++) { //RCU + if (m == 0 && (i < 2)) + continue; //half of module: only RCU 2,3 + + short numberOfChannels = 0; + short maxHWAddress = 0; + char fname[255]; + snprintf(fname, 255, "%s/Mod%dRCU%d.data", p.data(), m, i); + std::ifstream* fIn = new std::ifstream(fname); + if (!*fIn) { + LOG(FATAL) << "Missing mapping file " << p << "/Mod" << m << "RCU" << i << ".data"; + return kNotInitialized; + } + if (!(*fIn >> numberOfChannels)) { + LOG(FATAL) << "Syntax of mapping file " << p << "/Mod" << m << "RCU" << i << ".data is wrong: no numberOfChannels"; + return kNotInitialized; + } + if (numberOfChannels != NHWPERDDL) { + LOG(FATAL) << "Unexpected number of channels: " << numberOfChannels << " expecting " << NHWPERDDL << " file " << p << "/Mod" << m << "RCU" << i << ".data is wrong: no numberOfChannels"; + return kNotInitialized; + } + if (!(*fIn >> maxHWAddress)) { + LOG(FATAL) << "Syntax of mapping file " << p << "/Mod" << m << "RCU" << i << ".data is wrong: no maxHWAddress"; + return kNotInitialized; + } + + for (short ich = 0; ich < numberOfChannels; ich++) { // 1792 = 2*896 channels connected to each RCU + int hwAddress; + if (!(*fIn >> hwAddress)) { + LOG(FATAL) << "Syntax of mapping file " << p << "/Mod" << m << "RCU" << i << ".data is wrong: no HWadd for ch " << ich; + return kNotInitialized; + } + if (hwAddress > maxHWAddress) { + LOG(FATAL) << "Hardware (ALTRO) adress (" << hwAddress << ") outside the range (0 -> " << maxHWAddress << ") !"; + return kNotInitialized; + } + int row, col, caloFlag; + if (!(*fIn >> row >> col >> caloFlag)) { + LOG(FATAL) << "Syntax of mapping file " << p << "/Mod" << m << "RCU" << i << ".data is wrong: no (raw col caloFlag)"; + return kNotInitialized; + } + + if (caloFlag < 0 || caloFlag > 2) { + LOG(FATAL) << "Wrong CaloFlag value found (" << caloFlag << "). Should be 0, 1, 2 !"; + return kNotInitialized; + } + + //convert ddl, col,raw caloFlag to AbsId + // Converts the absolute numbering into the following array + // relid[0] = PHOS Module number + // relid[1] = Row number inside a PHOS module (Phi coordinate) + // relid[2] = Column number inside a PHOS module (Z coordinate) + short ddl = 4 * m + i - 2; + + char relid[3] = {(char)m, (char)row, (char)col}; + short absId; + geom->relToAbsNumbering(relid, absId); + + if (ddl < 0 || ddl >= NDDL) { + LOG(FATAL) << "Wrong ddl address found (" << ddl << "). Module= " << m << " RCU =" << i; + return kNotInitialized; + } + + mAbsId[ddl][hwAddress] = absId; + mCaloFlag[ddl][hwAddress] = (CaloFlag)caloFlag; + + mAbsToHW[absId][caloFlag][0] = ddl; + mAbsToHW[absId][caloFlag][1] = hwAddress; + } + fIn->close(); + } //RCU + } // module + mInitialized = true; + return kOK; +} diff --git a/Detectors/PHOS/base/src/RCUTrailer.cxx b/Detectors/PHOS/base/src/RCUTrailer.cxx new file mode 100644 index 0000000000000..0c841f7f767b7 --- /dev/null +++ b/Detectors/PHOS/base/src/RCUTrailer.cxx @@ -0,0 +1,240 @@ +// 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 <cfloat> +#include <cmath> +#include <iostream> +#include <fmt/format.h> +#include "CommonConstants/LHCConstants.h" +#include "PHOSBase/RCUTrailer.h" + +using namespace o2::phos; + +void RCUTrailer::reset() +{ + mRCUId = -1; + mFirmwareVersion = 0; + mTrailerSize = 0; + mPayloadSize = 0; + mFECERRA = 0; + mFECERRB = 0; + mERRREG2 = 0; + mERRREG3 = 0; + mActiveFECsA = 0; + mActiveFECsB = 0; + mAltroCFG1 = 0; + mAltroCFG2 = 0; + mIsInitialized = false; +} + +void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payloadwords) +{ + reset(); + int index = payloadwords.size(); + auto word = payloadwords[--index]; + if ((word >> 30) != 3) { + throw Error(Error::ErrorType_t::DECODING_INVALID, "Last RCU trailer word not found!"); + } + mFirmwareVersion = (word >> 16) & 0xFF; + + mRCUId = (int)((word >> 7) & 0x1FF); + int trailerSize = (word & 0x7F); + + if (trailerSize < 2) { + throw Error(Error::ErrorType_t::SIZE_INVALID, fmt::format("Invalid trailer size found (%d bytes) !", trailerSize * 4).data()); + } + mTrailerSize = trailerSize; + + trailerSize -= 2; // Cut first and last trailer words as they are handled separately + for (; trailerSize > 0; trailerSize--) { + word = payloadwords[--index]; + if ((word >> 30) != 2) { + std::cerr << "Missing RCU trailer identifier pattern!\n"; + continue; + } + int parCode = (word >> 26) & 0xF; + int parData = word & 0x3FFFFFF; + switch (parCode) { + case 1: + // ERR_REG1 + mFECERRA = ((parData >> 13) & 0x1FFF) << 7; + mFECERRB = ((parData & 0x1FFF)) << 7; + break; + case 2: + // ERR_REG2 + mERRREG2 = parData & 0x1FF; + break; + case 3: + // ERR_REG3 + mERRREG3 = parData & 0x1FFFFFF; + break; + case 4: + // FEC_RO_A + mActiveFECsA = parData & 0xFFFF; + break; + case 5: + // FEC_RO_B + mActiveFECsB = parData & 0xFFFF; + break; + case 6: + // RDO_CFG1 + mAltroCFG1 = parData & 0xFFFFF; + break; + case 7: + // RDO_CFG2 + mAltroCFG2 = parData & 0x1FFFFFF; + break; + default: + std::cerr << "Undefined parameter code " << parCode << ", ignore it !\n"; + break; + } + } + mPayloadSize = payloadwords[--index] & 0x3FFFFFF; + mIsInitialized = true; +} + +double RCUTrailer::getTimeSample() const +{ + unsigned char fq = (mAltroCFG2 >> 5) & 0xF; + double tSample; + switch (fq) { + case 0: + // 20 MHz + tSample = 2.0; + break; + case 1: + // 10 Mhz + tSample = 4.0; + break; + case 2: + // 5 MHz + tSample = 8.; + break; + default: + throw Error(Error::ErrorType_t::SAMPLINGFREQ_INVALID, fmt::format("Invalid sampling frequency value %d !", int(fq)).data()); + } + + return tSample * o2::constants::lhc::LHCBunchSpacingNS * 1.e-9; +} + +void RCUTrailer::setTimeSample(double timesample) +{ + int fq = 0; + if (std::abs(timesample - 50) < DBL_EPSILON) { + fq = 0; + } else if (std::abs(timesample - 100) < DBL_EPSILON) { + fq = 1; + } else if (std::abs(timesample - 200) < DBL_EPSILON) { + fq = 2; + } else { + throw Error(Error::ErrorType_t::SAMPLINGFREQ_INVALID, fmt::format("invalid time sample: %f", timesample).data()); + } + mAltroCFG2 = (mAltroCFG2 & 0x1F) | fq << 5; +} + +double RCUTrailer::getL1Phase() const +{ + double tSample = getTimeSample(), + phase = ((double)(mAltroCFG2 & 0x1F)) * o2::constants::lhc::LHCBunchSpacingNS * 1.e-9; + if (phase >= tSample) { + throw Error(Error::ErrorType_t::L1PHASE_INVALID, fmt::format("Invalid L1 trigger phase (%e s (phase) >= %e s (sampling time)) !", phase, tSample).data()); + } + return phase; +} + +void RCUTrailer::setL1Phase(double l1phase) +{ + int phase = l1phase / 25.; + mAltroCFG2 = (mAltroCFG2 & 0x1E0) | phase; +} + +std::vector<uint32_t> RCUTrailer::encode() const +{ + std::vector<uint32_t> encoded; + encoded.emplace_back(mPayloadSize | 2 << 30); + encoded.emplace_back(mAltroCFG2 | 7 << 26 | 2 << 30); + encoded.emplace_back(mAltroCFG1 | 6 << 26 | 2 << 30); + encoded.emplace_back(mActiveFECsB | 5 << 26 | 2 << 30); + encoded.emplace_back(mActiveFECsA | 4 << 26 | 2 << 30); + encoded.emplace_back(mERRREG3 | 3 << 26 | 2 << 30); + encoded.emplace_back(mERRREG2 | 2 << 26 | 2 << 30); + encoded.emplace_back(mFECERRB >> 7 | (mFECERRA >> 7) << 13 | 1 << 26 | 2 << 30); + + uint32_t lasttrailerword = 3 << 30 | mFirmwareVersion << 16 | mRCUId << 7 | (encoded.size() + 1); + encoded.emplace_back(lasttrailerword); + + return encoded; +} + +void RCUTrailer::printStream(std::ostream& stream) const +{ + std::vector<std::string> errors; + double timesample = -1., l1phase = -1.; + try { + timesample = getTimeSample(); + } catch (Error& e) { + errors.push_back(e.what()); + } + try { + l1phase = getL1Phase(); + } catch (Error& e) { + errors.push_back(e.what()); + } + + stream << "RCU trailer (Format version 2):\n" + << "==================================================\n" + << "RCU ID: " << mRCUId << "\n" + << "Firmware version: " << int(mFirmwareVersion) << "\n" + << "Trailer size: " << mTrailerSize << "\n" + << "Payload size: " << mPayloadSize << "\n" + << "FECERRA: 0x" << std::hex << mFECERRA << "\n" + << "FECERRB: 0x" << std::hex << mFECERRB << "\n" + << "ERRREG2: 0x" << std::hex << mERRREG2 << "\n" + << "#channels skipped due to address mismatch: " << std::dec << getNumberOfChannelAddressMismatch() << "\n" + << "#channels skipped due to bad block length: " << std::dec << getNumberOfChannelLengthMismatch() << "\n" + << "Active FECs (branch A): 0x" << std::hex << mActiveFECsA << "\n" + << "Active FECs (branch B): 0x" << std::hex << mActiveFECsB << "\n" + << "Baseline corr: 0x" << std::hex << int(getBaselineCorrection()) << "\n" + << "Number of presamples: " << std::dec << int(getNumberOfPresamples()) << "\n" + << "Number of postsamples: " << std::dec << int(getNumberOfPostsamples()) << "\n" + << "Second baseline corr: " << (hasSecondBaselineCorr() ? "yes" : "no") << "\n" + << "GlitchFilter: " << std::dec << int(getGlitchFilter()) << "\n" + << "Number of non-ZS postsamples: " << std::dec << int(getNumberOfNonZeroSuppressedPostsamples()) << "\n" + << "Number of non-ZS presamples: " << std::dec << int(getNumberOfNonZeroSuppressedPresamples()) << "\n" + << "Number of ALTRO buffers: " << std::dec << getNumberOfAltroBuffers() << "\n" + << "Number of pretrigger samples: " << std::dec << int(getNumberOfPretriggerSamples()) << "\n" + << "Number of samples per channel: " << std::dec << getNumberOfSamplesPerChannel() << "\n" + << "Sparse readout: " << (isSparseReadout() ? "yes" : "no") << "\n" + << "AltroCFG1: 0x" << std::hex << mAltroCFG1 << "\n" + << "AltroCFG2: 0x" << std::hex << mAltroCFG2 << "\n" + << "Sampling time: " << std::scientific << timesample << " s\n" + << "L1 Phase: " << std::scientific << l1phase << " s\n" + << std::dec << std::fixed; + if (errors.size()) { + stream << "Errors: \n" + << "-------------------------------------------------\n"; + for (const auto& e : errors) { + stream << e << "\n"; + } + } + stream << "==================================================\n"; +} + +RCUTrailer RCUTrailer::constructFromPayloadWords(const gsl::span<const uint32_t> payloadwords) +{ + RCUTrailer result; + result.constructFromRawPayload(payloadwords); + return result; +} + +std::ostream& o2::phos::operator<<(std::ostream& stream, const o2::phos::RCUTrailer& trailer) +{ + trailer.printStream(stream); + return stream; +} diff --git a/Detectors/PHOS/reconstruction/CMakeLists.txt b/Detectors/PHOS/reconstruction/CMakeLists.txt index bf49c5acffe09..76f315acaf49a 100644 --- a/Detectors/PHOS/reconstruction/CMakeLists.txt +++ b/Detectors/PHOS/reconstruction/CMakeLists.txt @@ -11,11 +11,35 @@ o2_add_library(PHOSReconstruction SOURCES src/Clusterer.cxx src/FullCluster.cxx + src/RawReaderMemory.cxx + src/RawBuffer.cxx + src/RawHeaderStream.cxx + src/RawPayload.cxx + src/AltroDecoder.cxx + src/Bunch.cxx + src/Channel.cxx + src/CaloRawFitter.cxx PUBLIC_LINK_LIBRARIES O2::PHOSBase O2::PHOSCalib O2::DataFormatsPHOS + O2::DetectorsRaw AliceO2::InfoLogger) o2_target_root_dictionary(PHOSReconstruction - HEADERS include/PHOSReconstruction/Clusterer.h + HEADERS include/PHOSReconstruction/RawReaderMemory.h + include/PHOSReconstruction/RawBuffer.h + include/PHOSReconstruction/RawHeaderStream.h + include/PHOSReconstruction/RawPayload.h + include/PHOSReconstruction/RawReaderError.h + include/PHOSReconstruction/Bunch.h + include/PHOSReconstruction/RawDecodingError.h + include/PHOSReconstruction/AltroDecoder.h + include/PHOSReconstruction/Channel.h + include/PHOSReconstruction/CaloRawFitter.h + include/PHOSReconstruction/Clusterer.h include/PHOSReconstruction/FullCluster.h) +o2_add_executable(rawreader-file + COMPONENT_NAME phos + PUBLIC_LINK_LIBRARIES O2::PHOSReconstruction + SOURCES run/rawReaderFile.cxx) + diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h new file mode 100644 index 0000000000000..b2a68b40f740f --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h @@ -0,0 +1,138 @@ +// 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_PHOS_ALTRODECODER_H +#define ALICEO2_PHOS_ALTRODECODER_H + +#include <iosfwd> +#include <gsl/span> +#include <string> +#include "PHOSBase/RCUTrailer.h" +#include "PHOSReconstruction/Bunch.h" +#include "PHOSReconstruction/Channel.h" +#include "PHOSReconstruction/RawReaderMemory.h" + +namespace o2 +{ +namespace phos +{ + +/// \class AltroDecoderError +/// \brief Error handling of the ALTRO Decoder +/// \ingroup EMCALreconstruction +class AltroDecoderError : public std::exception +{ + public: + enum ErrorType_t { + kOK, ///< NoError + RCU_TRAILER_ERROR, ///< RCU trailer cannot be decoded or invalid + RCU_VERSION_ERROR, ///< RCU trailer version not matching with the version in the raw header + RCU_TRAILER_SIZE_ERROR, ///< RCU trailer size length + ALTRO_BUNCH_HEADER_ERROR, ///< ALTRO bunch header cannot be decoded or is invalid + ALTRO_BUNCH_LENGTH_ERROR, ///< ALTRO bunch has incorrect length + ALTRO_PAYLOAD_ERROR, ///< ALTRO payload cannot be decoded + ALTRO_MAPPING_ERROR, ///< Incorrect ALTRO channel mapping + CHANNEL_ERROR ///< Channels not initialized + }; + + /// \brief Constructor + /// + /// Defining error code and error message. To be called when the + /// exception is thrown + AltroDecoderError(ErrorType_t errtype, const char* message) : mErrorType(errtype), mErrorMessage(message) {} + + /// \brief Destructor + ~AltroDecoderError() noexcept override = default; + + /// \brief Access to error message cnnected to the error + /// \return Error message + const char* what() const noexcept override { return mErrorMessage.data(); } + + /// \brief Access to the error type connected to the erro + /// \return Error type + const ErrorType_t getErrorType() const noexcept { return mErrorType; } + + private: + ErrorType_t mErrorType; ///< Code of the decoding error type + std::string mErrorMessage; ///< Message connected to the error type +}; + +/// \class AltroDecoder +/// \brief Decoder of the ALTRO data in the raw page +/// \ingroup PHOSreconstruction +/// \author Dmitri Peresunko aftesr Markus Fasel +/// \since Sept, 2020 +/// +/// This is a base class for reading raw data digits in Altro format. +/// The class is able to read the RCU v3 and above formats. +/// The main difference between the format V3 and older ones is in +/// the coding of the 10-bit Altro payload words. In V3 3 10-bit words +/// are coded in one 32-bit word. The bits 30 and 31 are used to identify +/// the payload, altro header and RCU trailer contents. +/// +/// Based on AliAltroRawStreamV3 and AliCaloRawStreamV3 by C. Cheshkov + +class AltroDecoder +{ + public: + /// \brief Constructor + /// \param reader Raw reader instance to be decoded + AltroDecoder(RawReaderMemory& reader); + + /// \brief Destructor + ~AltroDecoder() = default; + + /// \brief Decode the ALTRO stream + /// \throw AltroDecoderError if the RCUTrailer or ALTRO payload cannot be decoded + /// + /// Decoding and checking the RCUTtrailer and + /// all channels and bunches in the ALTRO stream. + /// After successfull decoding the Decoder can provide + /// a reference to the RCU trailer and a vector + /// with the decoded chanenels, each containing + /// its bunches. + AltroDecoderError::ErrorType_t decode(); + + /// \brief Get reference to the RCU trailer object + /// \return const reference to the RCU trailer + /// \throw AltroDecoderError with type RCU_TRAILER_ERROR if the RCU trailer was not initialized + const RCUTrailer& getRCUTrailer() const; + + /// \brief Get the reference to the channel container + /// \return Reference to the channel container + /// \throw AltroDecoderError with CHANNEL_ERROR if the channel container was not initialized for the current event + const std::vector<Channel>& getChannels() const; + + /// \brief Read RCU trailer for the current event in the raw buffer + void readRCUTrailer(); + + /// \brief Read channels for the current event in the raw buffer + void readChannels(); + + private: + /// \brief run checks on the RCU trailer + /// \throw Error if the RCU trailer has inconsistencies + /// + /// Performing various consistency checks on the RCU trailer + /// In case of failure an exception is thrown. + void checkRCUTrailer(); + + RawReaderMemory& mRawReader; ///< underlying raw reader + RCUTrailer mRCUTrailer; ///< RCU trailer + std::vector<Channel> mChannels; ///< vector of channels in the raw stream + bool mChannelsInitialized = false; ///< check whether the channels are initialized + + ClassDefNV(AltroDecoder, 1); +}; + +} // namespace phos + +} // namespace o2 + +#endif diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/Bunch.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/Bunch.h new file mode 100644 index 0000000000000..afda162577293 --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/Bunch.h @@ -0,0 +1,103 @@ +// 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_PHOS_BUNCH_H +#define ALICEO2_PHOS_BUNCH_H + +#include <cstdint> +#include <vector> +#include <gsl/span> +#include "Rtypes.h" + +namespace o2 +{ + +namespace phos +{ +/// \class Bunch +/// \brief ALTRO bunch information +/// \ingroup PHOSreconstruction +/// +/// The bunch contains the ADC values of a given +/// data bunch for a channel in the ALTRO stream. +/// The ADC values are stored in reversed order in +/// time both in the ALTRO stream and in the bunch +/// object. +/// +/// For iteration one should assume that the end time +/// is 0, however it can also be larger than 0. In this +/// case the first value has to be mapped to the end timebin +/// and the last value to the start timebin, still iterating +/// only over the number of samples. +class Bunch +{ + public: + /// \brief Constructor + Bunch() = default; + + /// \brief Initialize the bunch with start time and bunch length + /// \param length Length of the bunch + /// \param start Start time of the bunch + Bunch(uint8_t length, uint8_t start) : mBunchLength(length), mStartTime(start), mADC() {} + + /// \brief + ~Bunch() = default; + + /// \brief Add ADC value to the bunch + /// \param adc Next ADC value + /// + /// ADC values are stored in reversed order. The next ADC value + /// has to be earlier in time compared to the previous one. + void addADC(uint16_t adc) { mADC.emplace_back(adc); } + + /// \brief Initialize the ADC values in the bunch from a range + /// \param range Range of ADC values + /// + /// The ADC values are stored in reversed order in time. Therefore + /// the last entry is the one earliest in time. + void initFromRange(gsl::span<uint16_t> range); + + /// \brief Get range of ADC values in the bunch + /// \return ADC values in the bunch + /// + /// The ADC values are stored in reversed order in time. Therefore + /// the last entry is the one earliest in time. + const std::vector<uint16_t>& getADC() const { return mADC; } + + /// \brief Get the length of the bunch (number of time bins) + /// \return Length of the bunch + uint8_t getBunchLength() const { return mBunchLength; } + + /// \brief Get the start time bin + /// \return Start timebin + /// + /// The start timebin is the higher of the two, + /// the samples are in reversed order. + uint8_t getStartTime() const { return mStartTime; } + + /// \brief Get the end time bin + /// \return End timebin + /// + /// The end timebin is the lower of the two, + /// the samples are in reversed order. + uint8_t getEndTime() const { return mStartTime - mBunchLength + 1; } + + private: + uint8_t mBunchLength = 0; ///< Number of ADC samples in buffer + uint8_t mStartTime = 0; ///< Start timebin (larger time bin, samples are in reversed order) + std::vector<uint16_t> mADC; ///< ADC samples in bunch + + ClassDefNV(Bunch, 1); +}; + +} // namespace phos + +} // namespace o2 + +#endif diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CaloRawFitter.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CaloRawFitter.h new file mode 100644 index 0000000000000..4e2f9171c0e9d --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CaloRawFitter.h @@ -0,0 +1,113 @@ +// 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 CaloRawFitter +/// \brief Raw data fitting: extraction amplitude and time +/// +/// Extraction of amplitude and time +/// from CALO raw data using fast k-level approach or +/// least square fit with Gamma2 function +/// +/// \author Dmitri Peresunko +/// \since Jan.2020 +/// + +#ifndef PHOSRAWFITTER_H_ +#define PHOSRAWFITTER_H_ +class Bunch; + +namespace o2 +{ + +namespace phos +{ + +class CaloRawFitter +{ + + public: + enum FitStatus { kOK, + kNotEvaluated, + kEmptyBunch, + kOverflow, + kSpike, + kNoTime, + kFitFailed, + kBadPedestal, + kManyBunches }; + + public: + /// \brief Constructor + CaloRawFitter() = default; + + /// \brief Destructor + ~CaloRawFitter() = default; + + /// \brief Evaluation Amplitude and TOF + /// return status -1: not evaluated/empty bunch; + /// 0: OK; + /// 1: overflow; + /// 4: single spikes + /// 3: too large RMS; + FitStatus evaluate(const std::vector<Bunch>& bunchvector); + + /// \brief Set HighGain/LowGain channel to performe or not fit of saturated samples + void setLowGain(bool isLow = false) { mLowGain = isLow; } + + /// \brief estimate and subtract pedestals from pre-samples + void setPedSubtract(bool toSubtruct = false) { mPedSubtract = toSubtruct; } + + /// \brief amplitude in last fitted sample + float getAmp(int is) { return mAmp[is]; } + + /// \brief Chi2/NDF of last performed fit + float getChi2(int is) const { return mChi2[is]; } + + /// \brief time in last fitted sample + float getTime(int is) { return mTime[is]; } + + /// \brief is last fitted sample has overflow + bool isOverflow(int is) { return mOverflow[is]; } + + /// \brief Forse perform fitting + /// Make fit for any sample, not only saturated LowGain samples as by default + void forseFitting(bool toRunFit = true) { makeFit = toRunFit; } + + /// \brief Number of fit samples (normaly 1, more in case of pileup, noise etc) + short getNsamples() { return mAmp.size(); } + + /// \brief Set analysis of pedestal run + /// Analyze pedestal run, i.e. calculate mean and RMS of pedestals instead of Amp and Time + void setPedestal() { mPedestalRun = true; } + + protected: + FitStatus evalKLevel(const Bunch& b); + + FitStatus fitGamma2(const Bunch& b); + + private: + bool makeFit = false; ///< run (slow) fit with Gamma2 or use fast evaluation with k-level + bool mLowGain = false; ///< is current bunch from LowGain channel + bool mPedSubtract = false; ///< should one evaluate and subtract pedestals + bool mPedestalRun = false; ///< analyze as pedestal run + std::vector<bool> mOverflow; ///< is last sample saturated + FitStatus mStatus = kNotEvaluated; ///< status of last evaluated sample: -1: not yet evaluated; 0: OK; 1: overflow; 2: too large RMS; 3: single spikes + short mMaxSample = 0; ///< maximal sample + std::vector<float> mAmp; ///< amplitude of last processed sample + std::vector<float> mTime; ///< time of last processed sample + std::vector<float> mChi2; ///< chi2 calculated in last fit + + ClassDefNV(CaloRawFitter, 1); +}; // End of CaloRawFitter + +} // namespace phos + +} // namespace o2 +#endif diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/Channel.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/Channel.h new file mode 100644 index 0000000000000..4ce48c910cf0a --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/Channel.h @@ -0,0 +1,160 @@ +// 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_PHOS_CHANNEL_H +#define ALICEO2_PHOS_CHANNEL_H + +#include <cstdint> +#include <exception> +#include <vector> +#include "Rtypes.h" +#include "PHOSReconstruction/Bunch.h" + +namespace o2 +{ + +namespace phos +{ + +/// \class Channel +/// \brief ALTRO channel representation +/// \ingroup PHOSreconstruction +/// +/// The channel contains information about +/// a hardware channel in the raw stream. Those +/// information are: +/// - Hardware address +/// - Size of the payload of all bunches in the channel +/// as total number of 10-bit words +/// - Channel status (good or bad) +/// In addition it contains the data of all bunches in the +/// raw stream. +/// +/// The hardware address itself encods +/// - Branch ID (bit 12) +/// - FEC ID (bits 7-10) +/// - ALTRO ID (bits 4-6) +/// - Channel ID (bits 0-3) +class Channel +{ + public: + /// \class HardwareAddressError + /// \brief Handling of uninitialized hardware addresses + class HardwareAddressError : public std::exception + { + public: + /// \brief Constructor + HardwareAddressError() = default; + + /// \brief Destructor + ~HardwareAddressError() noexcept override = default; + + /// \brief Access to error message + /// \return error message + const char* what() const noexcept override + { + return "Hardware address not initialized"; + } + }; + + /// \brief Dummy constructor + Channel() = default; + + /// \brief Constructor initializing hardware address and payload size + /// \param hardwareAddress Harware address + /// \param payloadSize Size of the payload + Channel(int32_t hardwareAddress, uint8_t payloadSize) : mHardwareAddress(hardwareAddress), + mPayloadSize(payloadSize), + mBunches() + { + } + + /// \brief Destructor + ~Channel() = default; + + /// \brief Check whether the channel is bad + /// \return true if the channel is bad, false otherwise + bool isBadChannel() const { return mBadChannel; } + + /// \brief Get the full hardware address + /// \return Hardware address + /// + /// The hardware address contains: + /// - Branch ID (bit 12) + /// - FEC ID (bits 7-10) + /// - ALTRO ID (bits 4-6) + /// - Channel ID (bits 0-3) + uint16_t getHardwareAddress() const { return mHardwareAddress; } + + /// \brief Get the size of the payload + /// \return Size of the payload as number of 10-bit samples (1/3rd words) + uint8_t getPayloadSize() const { return mPayloadSize; } + + /// \brief Get list of bunches in the channel + /// \return List of bunches + const std::vector<Bunch>& getBunches() const { return mBunches; } + + /// \brief Provide the branch index for the current hardware address + /// \return RCU branch index (0 or 1) + /// \throw HadrwareAddressError in case the hardware address is not initialized + int getBranchIndex() const; + + /// \brief Provide the front-end card index for the current hardware address + /// \return Front-end card index for the current hardware address + /// \throw HadrwareAddressError in case the hardware address is not initialized + int getFECIndex() const; + + /// \brief Provide the altro chip index for the current hardware address + /// \return Altro chip index for the current hardware address + /// \throw HadrwareAddressError in case the hardware address is not initialized + int getAltroIndex() const; + + /// \brief Provide the channel index for the current hardware address + /// \return Channel index for the current hardware address + /// \throw HadrwareAddressError in case the hardware address is not initialized + int getChannelIndex() const; + + /// \brief Add bunch to the channel + /// \param bunch Bunch to be added + /// + /// This function will copy the bunch information to the + /// object, which might be expensive. Better use the + /// function createBunch. + void addBunch(const Bunch& bunch) { mBunches.emplace_back(bunch); } + + /// \brief Set the hardware address + /// \param hardwareAddress Hardware address + void setHardwareAddress(uint16_t hardwareAddress) { mHardwareAddress = hardwareAddress; } + + /// \brief Set the size of the payload in number of 10-bit words + /// \param payloadSize Size of the payload + void setPayloadSize(uint8_t payloadSize) { mPayloadSize = payloadSize; } + + /// \brief Mark the channel status + /// \param badchannel Bad channel status (true if bad) + void setBadChannel(bool badchannel) { mBadChannel = badchannel; } + + /// \brief Create and initialize a new bunch and return reference to it + /// \param bunchlength Length of the bunch + /// \param starttime Start time of the bunch + Bunch& createBunch(uint8_t bunchlength, uint8_t starttime); + + private: + int32_t mHardwareAddress = -1; ///< Hardware address + uint8_t mPayloadSize = 0; ///< Payload size + bool mBadChannel; ///< Bad channel status + std::vector<Bunch> mBunches; ///< Bunches in channel; + + ClassDefNV(Channel, 1); +}; + +} // namespace phos +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawBuffer.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawBuffer.h new file mode 100644 index 0000000000000..734632a1e3fee --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawBuffer.h @@ -0,0 +1,89 @@ +// 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_PHOS_RAWBUFFER_H +#define ALICEO2_PHOS_RAWBUFFER_H + +#include <array> +#include <cstdint> +#include <iosfwd> +#include <gsl/span> + +namespace o2 +{ +namespace phos +{ + +/// \class RawBuffer +/// \brief Buffer for PHOS raw pages +/// \ingroup PHOSreconstruction +/// \author Dmitri Peresunko after Markus Fasel +/// \since Sept, 2020 +class RawBuffer +{ + public: + RawBuffer() = default; + ~RawBuffer() = default; + + void reset() { mCurrentDataWord = 0; } + + /// \brief Flush the buffer + /// Does not overwrite the word buffer but just resets the counter and iterator + void flush(); + + /// \brief Read page from stream + /// \param in Input file stream + /// \param payloadsize Number of char words in payload + /// Read a whole superpage from the raw stream + /// and convert the bitwise representation directly + /// into 32 bit words + void readFromStream(std::istream& in, uint32_t payloadsize); + + /// \brief Read page from raw memory buffer + /// \param rawmemory Raw memory buffer (as char words) with size of the payload from the raw data header + /// Converts the char word raw memory buffer of a pages into + /// into the 32 bit word buffer + void readFromMemoryBuffer(const gsl::span<const char> rawmemory); + + /// \brief Get the number of data words read for the superpage + /// \return Number of data words in the superpage + int getNDataWords() const { return mNDataWords; } + + /// \brief Get the next data word in the superpage + /// \return next data word in the superpage + /// \throw std::runtime_error if there exists no next data word + uint32_t getNextDataWord(); + + /// \brief Get the data word at a given index + /// \param index index of the word in the buffer + /// \return word at requested index + /// \throw std::runtime_error if the index is out-of-range + uint32_t getWord(int index) const; + + /// \brief Get all data words from the raw buffer + /// \return Span with data words in the buffer (removing trailing null entries) + const gsl::span<const uint32_t> getDataWords() const { return gsl::span<const uint32_t>(mDataWords.data(), mNDataWords); } + + /// \brief Check whether the next data word exists + /// \return True if more data words exist, false otherwise + /// Check is done starting from the current position + /// of the iterator + bool hasNext() const { return mCurrentDataWord < mNDataWords; } + + private: + std::array<uint32_t, 2048> mDataWords; ///< Data words in one superpage + int mNDataWords = 0; ///< Number of data words read from superpage + int mCurrentDataWord = 0; ///< Iterator over words in superpage +}; + +} // namespace phos + +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawDecodingError.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawDecodingError.h new file mode 100644 index 0000000000000..11e53aa22faff --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawDecodingError.h @@ -0,0 +1,85 @@ +// 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_PHOS_RAWDECODINGERROR_H +#define ALICEO2_PHOS_RAWDECODINGERROR_H + +#include <exception> + +namespace o2 +{ + +namespace phos +{ + +/// \class RawDecodingError +/// \brief Error handling of the raw reader +/// \ingroup PHOSreconstruction +/// +/// The following error types are defined: +/// - Page not found +/// - Raw header decoding error +/// - Payload decoding error +class RawDecodingError : public std::exception +{ + public: + /// \enum ErrorType_t + /// \brief Codes for different error types + enum class ErrorType_t { + PAGE_NOTFOUND, ///< Page was not found (page index outside range) + HEADER_DECODING, ///< Header cannot be decoded (format incorrect) + PAYLOAD_DECODING, ///< Payload cannot be decoded (format incorrect) + HEADER_INVALID, ///< Header in memory not belonging to requested superpage + PAYLOAD_INVALID, ///< Payload in memory not belonging to requested superpage + }; + + /// \brief Constructor + /// \param errtype Identifier code of the error type + /// + /// Constructing the error with error code. To be called when the + /// exception is thrown. + RawDecodingError(ErrorType_t errtype) : mErrorType(errtype) + { + } + + /// \brief destructor + ~RawDecodingError() noexcept override = default; + + /// \brief Providing error message of the exception + /// \return Error message of the exception + const char* what() const noexcept override + { + switch (mErrorType) { + case ErrorType_t::PAGE_NOTFOUND: + return "Page with requested index not found"; + case ErrorType_t::HEADER_DECODING: + return "RDH of page cannot be decoded"; + case ErrorType_t::PAYLOAD_DECODING: + return "Payload of page cannot be decoded"; + case ErrorType_t::HEADER_INVALID: + return "Access to header not belonging to requested superpage"; + case ErrorType_t::PAYLOAD_INVALID: + return "Access to payload not belonging to requested superpage"; + }; + return "Undefined error"; + } + + /// \brief Get the type identifier of the error handled with this exception + /// \return Error code of the exception + ErrorType_t getErrorType() const { return mErrorType; } + + private: + ErrorType_t mErrorType; ///< Type of the error +}; + +} // namespace phos + +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawHeaderStream.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawHeaderStream.h new file mode 100644 index 0000000000000..f96d478dc84fe --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawHeaderStream.h @@ -0,0 +1,38 @@ +// 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 RawHeaderStream.h +/// \brief Input stream operators for raw header 4 and 5 from binary file +/// +/// Helpers to define input stream operator for raw headers v4 and v5 from +/// binary file input stream, used in RawReaderFile + +#ifndef ALICEO2_PHOS_RAWHEADERSTREAM_H +#define ALICEO2_PHOS_RAWHEADERSTREAM_H + +#include <iosfwd> +#include "Headers/RAWDataHeader.h" + +namespace o2 +{ + +namespace phos +{ + +std::istream& operator>>(std::istream& stream, o2::header::RAWDataHeaderV4& header); +std::istream& operator>>(std::istream& stream, o2::header::RAWDataHeaderV5& header); + +std::ostream& operator<<(std::ostream& stream, const o2::header::RAWDataHeaderV4& header); +std::ostream& operator<<(std::ostream& stream, const o2::header::RAWDataHeaderV5& header); + +} // namespace phos + +} // namespace o2 +#endif diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h new file mode 100644 index 0000000000000..05089de373b96 --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h @@ -0,0 +1,89 @@ +// 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_PHOS_RAWPAYLOAD_H +#define ALICEO2_PHOS_RAWPAYLOAD_H + +#include <cstdint> +#include <vector> +#include <gsl/span> +#include "Rtypes.h" + +namespace o2 +{ + +namespace phos +{ + +/// \class RawPayload +/// \brief Class for raw payload excluding raw data headers from one or multiple DMA pages +/// \ingroup PHOSreconstruction +/// \author Markus Fasel <markus.fasel@cern.ch>, Oak Ridge National Laboratory +/// \since Nov 14, 2019 +/// +/// Container of 32-bit words in the current payload which can come from a single DMA page +/// or, in case the payload had to be split into multiple pages due to exceeding of the +/// page size, from multiple DMA pages. A page counter provides the amount of DMA pages +/// contributing to the current payload. +class RawPayload +{ + public: + /// \brief Constructor + RawPayload() = default; + + /// \brief Constructor + /// \param payloadwords Payload words of one or multiple pages + /// \param numpages Number of DMA pages contributing to the payload + RawPayload(const gsl::span<const uint32_t> payloadwords, int numpages); + + /// \brief Destructor + ~RawPayload() = default; + + /// \brief Set the number of pages contributing to the current payload + /// \param numpages Number of DMA pages contributing to the payload + void setNumberOfPages(int numpages) { mNumberOfPages = numpages; } + + /// \brief Append many words to the current payload (usually of a given DMA page) + /// \param payloadwords Payload words to be appened to the current payload + void appendPayloadWords(const gsl::span<const uint32_t> payloadwords); + + /// \brief Append single payload word to the current payload + /// \param payloadword Payload word to be appended to the current payload + void appendPayloadWord(uint32_t payloadword) { mPayloadWords.emplace_back(payloadword); }; + + /// \brief Increase the page counter of the current payload + void increasePageCount() { mNumberOfPages++; } + + /// \brief Get the payload words (as 32 bit words) contributing to the current payload + /// \return Words of the current payload + const std::vector<uint32_t>& getPayloadWords() const { return mPayloadWords; } + + /// \brief Get the number of pages contributing to the payload + /// \return Number of pages + int getNumberOfPages() const { return mNumberOfPages; } + + /// \brief Resetting payload words and page counter + void reset(); + + /// \brief Get the size of the payload + /// \return Size of the payload + int getPayloadSize() const { return mPayloadWords.size() * sizeof(uint32_t); } + + private: + std::vector<uint32_t> mPayloadWords; ///< Payload words (excluding raw header) + int mNumberOfPages; ///< Number of DMA pages + + ClassDefNV(RawPayload, 1); +}; + +} // namespace phos + +} // namespace o2 +#endif diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderError.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderError.h new file mode 100644 index 0000000000000..1663145e510e7 --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderError.h @@ -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. +#ifndef ALICEO2_PHOS_RAWREADERERROR_H +#define ALICEO2_PHOS_RAWREADERERROR_H + +namespace o2 +{ + +namespace phos +{ + +/// \class RawReaderError +/// \brief Error occured during reasing raw data +/// \ingroup PHOSReconstruction +/// +/// Error contains DDL number, FEE, chip, channel number if possible and error code + +class RawReaderError +{ + public: + /// \brief Constructor + RawReaderError() = default; + + /// \brief Constructor + RawReaderError(char ddl, char fec, char err) : mDDL(ddl), mFEC(fec), mErr(err) {} + + /// \brief destructor + ~RawReaderError() = default; + + char getDDL() { return mDDL; } + char getFEC() { return mDDL; } + char getError() { return mErr; } + + private: + char mDDL = 0; + char mFEC = 0; + char mErr = 0; + + ClassDefNV(RawReaderError, 1); +}; + +} // namespace phos + +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h new file mode 100644 index 0000000000000..937410a3a9a2a --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h @@ -0,0 +1,129 @@ +// 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_PHOS_RAWREADERMEMORY_H +#define ALICEO2_PHOS_RAWREADERMEMORY_H + +#include <gsl/span> +#include <Rtypes.h> + +#include "PHOSBase/RCUTrailer.h" +#include "PHOSReconstruction/RawBuffer.h" +#include "PHOSReconstruction/RawPayload.h" +#include "Headers/RAWDataHeader.h" +#include "Headers/RDHAny.h" + +namespace o2 +{ + +namespace phos +{ + +/// \class RawReaderMemory +/// \brief Reader for raw data produced by the Readout application in in-memory format +/// \ingroup PHOSreconstruction +/// \author Dmitri Peresunko after Markus Fasel +/// \since Sept. 25, 2020 +/// +/// +class RawReaderMemory +{ + public: + /// \brief Constructor + RawReaderMemory(const gsl::span<const char> rawmemory); + + /// \brief Destructor + ~RawReaderMemory() = default; + + /// \brief set new raw memory chunk + /// \param rawmemory New raw memory chunk + void setRawMemory(const gsl::span<const char> rawmemory); + + /// \brief Read next payload from the stream + /// + /// Read the next pages until the stop bit is found. + void next(); + + /// \brief Read the next page from the stream (single DMA page) + /// \param resetPayload If true the raw payload is reset + /// \throw Error if the page cannot be read or header or payload cannot be deocded + /// + /// Function reading a single DMA page from the stream. It is called + /// inside the next() function for reading payload from multiple DMA + /// pages. As the function cannot handle payload from multiple pages + /// it should not be called directly by the user. + void nextPage(bool resetPayload = true); + + /// \brief Read page with a given index + /// \param page Index of the page to be decoded + /// \throw RawDecodingError if the page cannot be read or header or payload cannot be deocded + /// + /// The reader will try to read the page with a certain index. In + /// case the page cannot be decoded (page index outside range, + /// decoding of header or payload failed), and excpetion is raised. + void readPage(int page); + + /// \brief access to the raw header of the current page + /// \return Raw header of the current page + /// \throw RawDecodingError with HEADER_INVALID if the header was not decoded + const o2::header::RDHAny& getRawHeader() const; + + /// \brief access to the raw buffer (single DMA page) + /// \return Raw buffer of the current page + /// \throw Error with PAYLOAD_INCALID if payload was not decoded + const RawBuffer& getRawBuffer() const; + + /// \brief access to the full raw payload (single or multiple DMA pages) + /// \return Raw Payload of the data until the stop bit is received. + const RawPayload& getPayload() const { return mRawPayload; } + + /// \brief Return size of the payload + /// \return size of the payload + int getPayloadSize() const { return mRawPayload.getPayloadSize(); } + + /// \brief get the size of the file in bytes + /// \return size of the file in byte + int getFileSize() const noexcept { return mRawMemoryBuffer.size(); } + + /// \brief get the number of pages in the file + /// \return number of pages in the file + int getNumberOfPages() const noexcept { return mNumData; } + + /// \brief check if more pages are available in the raw file + /// \return true if there is a next page + bool hasNext() const { return mCurrentPosition < mRawMemoryBuffer.size(); } + + protected: + /// \brief Initialize the raw stream + /// + /// Rewind stream to the first entry + void init(); + + o2::header::RDHAny decodeRawHeader(const void* headerwords); + + private: + gsl::span<const char> mRawMemoryBuffer; ///< Memory block with multiple DMA pages + RawBuffer mRawBuffer; ///< Raw buffer + o2::header::RDHAny mRawHeader; ///< Raw header + RawPayload mRawPayload; ///< Raw payload (can consist of multiple pages) + RCUTrailer mCurrentTrailer; ///< RCU trailer + uint64_t mTrailerPayloadWords = 0; ///< Payload words in common trailer + int mCurrentPosition = 0; ///< Current page in file + int mNumData = 0; ///< Number of pages + bool mRawHeaderInitialized = false; ///< RDH for current page initialized + bool mPayloadInitialized = false; ///< Payload for current page initialized + + ClassDefNV(RawReaderMemory, 1); +}; + +} // namespace phos + +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx b/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx new file mode 100644 index 0000000000000..3de33ebc1d7ee --- /dev/null +++ b/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx @@ -0,0 +1,119 @@ +// 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 rawReaderFileNew.cxx +/// \author Markus Fasel <markus.fasel@cern.ch>, Oak Ridge National Laboratory + +#include <iostream> +#include <boost/program_options.hpp> + +#include "DetectorsRaw/RawFileReader.h" +#include "PHOSReconstruction/AltroDecoder.h" +#include "PHOSReconstruction/RawReaderMemory.h" +#include "FairLogger.h" + +namespace bpo = boost::program_options; +//using namespace o2::phos; + +int main(int argc, char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + " <cmds/options>\n" + " Tool will decode the DDLx data for PHOS 0\n" + "Commands / Options"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + add_option("verbose,v", bpo::value<uint32_t>()->default_value(0), "Select verbosity level [0 = no output]"); + add_option("version", "Print version information"); + add_option("input-file,i", bpo::value<std::string>()->required(), "Specifies input file."); + add_option("debug,d", bpo::value<uint32_t>()->default_value(0), "Select debug output level [0 = no debug output]"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help") || argc == 1) { + std::cout << opt_general << std::endl; + exit(0); + } + + if (vm.count("version")) { + //std::cout << GitInfo(); + exit(0); + } + + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + + auto rawfilename = vm["input-file"].as<std::string>(); + + o2::raw::RawFileReader reader; + reader.setDefaultDataOrigin(o2::header::gDataOriginPHS); + reader.setDefaultDataDescription(o2::header::gDataDescriptionRawData); + reader.setDefaultReadoutCardType(o2::raw::RawFileReader::RORC); + reader.addFile(rawfilename); + reader.init(); + + while (1) { + int tfID = reader.getNextTFToRead(); + if (tfID >= reader.getNTimeFrames()) { + LOG(INFO) << "nothing left to read after " << tfID << " TFs read"; + break; + } + std::vector<char> dataBuffer; // where to put extracted data + for (int il = 0; il < reader.getNLinks(); il++) { + auto& link = reader.getLink(il); + std::cout << "Decoding link " << il << std::endl; + + auto sz = link.getNextTFSize(); // size in bytes needed for the next TF of this link + dataBuffer.resize(sz); + link.readNextTF(dataBuffer.data()); + + // Parse + o2::phos::RawReaderMemory parser(dataBuffer); + while (parser.hasNext()) { + parser.next(); + // Exclude STU DDLs + if (o2::raw::RDHUtils::getFEEID(parser.getRawHeader()) >= 40) + continue; + o2::phos::AltroDecoder decoder(parser); + decoder.decode(); + + std::cout << decoder.getRCUTrailer() << std::endl; + for (auto& chan : decoder.getChannels()) { + std::cout << "Hw address: " << chan.getHardwareAddress() << std::endl; + for (auto& bunch : chan.getBunches()) { + std::cout << "BunchLength: " << int(bunch.getBunchLength()) << std::endl; + auto adcs = bunch.getADC(); + int time = bunch.getStartTime(); + for (int i = adcs.size() - 1; i >= 0; i--) { + std::cout << "Timebin " << time << ", ADC " << adcs[i] << std::endl; + time--; + } + } + } + } + } + reader.setNextTFToRead(++tfID); + } +} \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx new file mode 100644 index 0000000000000..e30f4fe8cbf3f --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx @@ -0,0 +1,116 @@ +// 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 <cstring> +#include <boost/format.hpp> +#include "InfoLogger/InfoLogger.hxx" +#include "PHOSReconstruction/AltroDecoder.h" +#include "PHOSReconstruction/RawReaderMemory.h" + +#include "DetectorsRaw/RDHUtils.h" +#include <FairLogger.h> + +using namespace o2::phos; + +AltroDecoder::AltroDecoder(RawReaderMemory& reader) : mRawReader(reader), + mRCUTrailer(), + mChannels(), + mChannelsInitialized(false) +{ +} + +AltroDecoderError::ErrorType_t AltroDecoder::decode() +{ + try { + readRCUTrailer(); + } catch (RCUTrailer::Error& e) { + LOG(ERROR) << "RCU trailer error" << (int)e.getErrorType(); + return AltroDecoderError::RCU_TRAILER_ERROR; + } + //TODO checkRCUTrailer(); + try { + readChannels(); + } catch (AltroDecoderError::ErrorType_t e) { + LOG(ERROR) << "Altro decoding error " << e; + return e; + } + return AltroDecoderError::kOK; +} + +void AltroDecoder::readRCUTrailer() +{ + try { + auto payloadwordsOrig = mRawReader.getPayload().getPayloadWords(); + gsl::span<const uint32_t> payloadwords(payloadwordsOrig.data(), payloadwordsOrig.size()); + mRCUTrailer.constructFromRawPayload(payloadwords); + } catch (RCUTrailer::Error& e) { + throw e; + } +} + +void AltroDecoder::checkRCUTrailer() +{ +} + +void AltroDecoder::readChannels() +{ + mChannelsInitialized = false; + mChannels.clear(); + int currentpos = 0; + auto& buffer = mRawReader.getPayload().getPayloadWords(); + while (currentpos < buffer.size() - mRCUTrailer.getTrailerSize()) { + auto currentword = buffer[currentpos++]; + if (currentword >> 30 != 1) { + continue; + } + // starting a new channel + mChannels.emplace_back(currentword & 0xFFF, (currentword >> 16) & 0x3FF); + auto& currentchannel = mChannels.back(); + /// decode all words for channel + int numberofwords = (currentchannel.getPayloadSize() + 2) / 3; + std::vector<uint16_t> bunchwords; + for (int iword = 0; iword < numberofwords; iword++) { + currentword = buffer[currentpos++]; + if ((currentword >> 30) != 0) { + LOG(ERROR) << "Unexpected end of payload in altro channel payload! FEE=" << o2::raw::RDHUtils::getFEEID(mRawReader.getRawHeader()) + << ", Address=0x" << std::hex << currentchannel.getHardwareAddress() << ", word=0x" << currentword << std::dec; + currentpos--; + continue; + } + bunchwords.push_back((currentword >> 20) & 0x3FF); + bunchwords.push_back((currentword >> 10) & 0x3FF); + bunchwords.push_back(currentword & 0x3FF); + } + + // decode bunches + int currentsample = 0; + while (currentsample < currentchannel.getPayloadSize()) { + int bunchlength = bunchwords[currentsample] - 2, // remove words for bunchlength and starttime + starttime = bunchwords[currentsample + 1]; + auto& currentbunch = currentchannel.createBunch(bunchlength, starttime); + currentbunch.initFromRange(gsl::span<uint16_t>(&bunchwords[currentsample + 2], std::min((unsigned long)bunchlength, bunchwords.size() - currentsample - 2))); + currentsample += bunchlength + 2; + } + } + mChannelsInitialized = true; +} + +const RCUTrailer& AltroDecoder::getRCUTrailer() const +{ + if (!mRCUTrailer.isInitialized()) + throw AltroDecoderError::ErrorType_t::RCU_TRAILER_ERROR; // "RCU trailer was not initialized"); + return mRCUTrailer; +} + +const std::vector<Channel>& AltroDecoder::getChannels() const +{ + if (!mChannelsInitialized) + throw AltroDecoderError::ErrorType_t::CHANNEL_ERROR; // "Channels not initizalized"); + return mChannels; +} diff --git a/Detectors/PHOS/reconstruction/src/Bunch.cxx b/Detectors/PHOS/reconstruction/src/Bunch.cxx new file mode 100644 index 0000000000000..898efa85db74a --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/Bunch.cxx @@ -0,0 +1,18 @@ +// 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 "PHOSReconstruction/Bunch.h" + +using namespace o2::phos; + +void Bunch::initFromRange(gsl::span<uint16_t> adcs) +{ + for (auto adcval : adcs) + mADC.emplace_back(adcval); +} \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx b/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx new file mode 100644 index 0000000000000..3b78eae95be70 --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx @@ -0,0 +1,323 @@ +// 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 CaloRawFitter.cxx +/// \author Dmitri Peresunko + +#include "FairLogger.h" +#include <gsl/span> + +// ROOT sytem +#include "PHOSReconstruction/Bunch.h" +#include "PHOSReconstruction/CaloRawFitter.h" + +using namespace o2::phos; + +CaloRawFitter::FitStatus CaloRawFitter::evaluate(const std::vector<Bunch>& bunchlist) +{ + + mAmp.clear(); // used as mean in this mode + mTime.clear(); // used as RMS in pedestal mode + mChi2.clear(); // used as mean in this mode + + //Pedestal analysis mode + if (mPedestalRun) { + int nPed = 0; + float mean = 0.; + float rms = 0.; + for (auto b : bunchlist) { + const std::vector<uint16_t>& signal = b.getADC(); + for (std::vector<uint16_t>::const_reverse_iterator it = signal.rbegin(); it != signal.rend(); ++it) { + uint16_t a = *it; + mean += a; + rms += a * a; + ++nPed; + } + if (nPed > 0) { + mean /= nPed; + rms = rms / nPed - mean * mean; + if (rms > 0.) { + rms = sqrt(rms); + } + } + } + mAmp.push_back(mean); + mTime.push_back(rms); + mStatus = kOK; + return kOK; + } + + for (auto b : bunchlist) { + // Extract amplitude and time using maximum and k-level methods + FitStatus s = evalKLevel(b); + mStatus = s; + + // If this is Low Gain channel or explicitely requested, fit sample with Gamma2 function + if (makeFit || (mLowGain && s == kOverflow)) { + FitStatus s2 = fitGamma2(b); + } + //TODO: should we have separate status: overflow & fit OK, and overflow & fit failed, etc? + } + return mStatus; +} + +CaloRawFitter::FitStatus CaloRawFitter::evalKLevel(const Bunch& b) //const ushort *signal, int sigStart, int sigLength) +{ + // Calculate signal parameters (energy, time, quality) from array of samples + // Energy is a maximum sample minus pedestal 9 + // Time is the first time bin + // Signal overflows is there are at least 3 samples of the same amplitude above 900 + + float amp = 0.; + float time = 0.; + bool overflow = false; + + int sigLength = b.getBunchLength(); + if (sigLength == 0) { + return kEmptyBunch; + } + + const short kSpikeThreshold = 100; //Single spike >100 ADC channels + const float kBaseLine = 1.0; //TODO: set from config + const int kPreSamples = 10; //TODO: set from config + + float pedMean = 0; + float pedRMS = 0; + int nPed = 0; + mMaxSample = 0; + int nMax = 0; //number of consequitive maximal samples + bool spike = false; + + const std::vector<uint16_t>& signal = b.getADC(); + + int ap = -1, app = -1; //remember previous values to evaluate spikes + + for (std::vector<uint16_t>::const_reverse_iterator it = signal.rbegin(); it != signal.rend(); ++it) { + uint16_t a = *it; + if (mPedSubtract) { + if (nPed < kPreSamples) { //inverse signal time order + nPed++; + pedMean += a; + pedRMS += a * a; + } + } + if (a > mMaxSample) { + mMaxSample = a; + nMax = 0; + } + if (a == mMaxSample) + nMax++; + //check if there is a spike + if (app >= 0 && ap >= 0) { + spike |= (2 * ap - (a + app) > 2 * kSpikeThreshold); + } + app = ap; + ap = a; + } + amp = (float)mMaxSample; + + if (spike) { + mAmp.push_back(amp); + mTime.push_back(b.getStartTime() - 2); + mOverflow.push_back(false); + return kSpike; + } + + if (mMaxSample > 900 && nMax > 2) + overflow = true; + + float pedestal = 0; + if (mPedSubtract) { + if (nPed > 0) { + pedRMS = (pedRMS - pedMean * pedMean / nPed) / nPed; + if (pedRMS > 0.) + pedRMS = sqrt(pedRMS); + pedestal = pedMean / nPed; + } else { + mAmp.push_back(0); + mTime.push_back(b.getStartTime() - 2); + mOverflow.push_back(false); + return kBadPedestal; + } + } + + amp -= pedestal; + if (amp < kBaseLine) + amp = 0; + + //Evaluate time + time = b.getStartTime() - 2; + const int nLine = 6; //Parameters of fitting + const float eMinTOF = 10.; //Choosed from beam-test and cosmic analyis + const float kAmp = 0.35; //Result slightly depends on them, so no getters + // Avoid too low peak: + if (amp < eMinTOF) { + mAmp.push_back(amp); + mTime.push_back(time); + mOverflow.push_back(false); + return kNoTime; //use estimated time + } + + // Find index posK (kLevel is a level of "timestamp" point Tk): + int posK = sigLength - 1; //last point before crossing k-level + float levelK = pedestal + kAmp * amp; + while (signal[posK] <= levelK && posK >= 0) { + posK--; + } + posK++; + + if (posK == 0 || posK == sigLength - 1) { + mAmp.push_back(amp); + mTime.push_back(time); + mOverflow.push_back(false); + return kNoTime; // + } + + // Find crossing point by solving linear equation (least squares method) + int np = 0; + int iup = posK - 1; + int idn = posK; + Double_t sx = 0., sy = 0., sxx = 0., sxy = 0.; + Double_t x, y; + + while (np < nLine) { + //point above crossing point + if (iup >= 0) { + x = sigLength - iup - 1; + y = signal[iup]; + sx += x; + sy += y; + sxx += (x * x); + sxy += (x * y); + np++; + iup--; + } + //Point below crossing point + if (idn < sigLength) { + if (signal[idn] < pedestal) { + idn = sigLength - 1; //do not scan further + idn++; + continue; + } + x = sigLength - idn - 1; + y = signal[idn]; + sx += x; + sy += y; + sxx += (x * x); + sxy += (x * y); + np++; + idn++; + } + if (idn >= sigLength && iup < 0) { + break; //can not fit futher + } + } + + Double_t det = np * sxx - sx * sx; + if (det == 0) { + mAmp.push_back(amp); + mTime.push_back(time); + mOverflow.push_back(false); + return kNoTime; + } + if (np == 0) { + mAmp.push_back(amp); + mTime.push_back(time); + mOverflow.push_back(false); + return kEmptyBunch; + } + Double_t c1 = (np * sxy - sx * sy) / det; //slope + Double_t c0 = (sy - c1 * sx) / np; //offset + if (c1 == 0) { + mAmp.push_back(amp); + mTime.push_back(time); + mOverflow.push_back(false); + return kNoTime; + } + + // Find where the line cross kLevel: + time += (levelK - c0) / c1 - 5.; //5: mean offset between k-Level and start times + + mAmp.push_back(amp); + mTime.push_back(time); + if (overflow) { + mOverflow.push_back(true); + return kOverflow; + } else { + mOverflow.push_back(false); + return kOK; + } +} + +CaloRawFitter::FitStatus CaloRawFitter::fitGamma2(const Bunch& b) +{ + // Fit bunch with gamma2 function + // TODO!!! validate method + //initial values + float A = mAmp.back(); + float t0 = mTime.back(); + const std::vector<uint16_t>& signal = b.getADC(); + uint16_t tsart = b.getStartTime(); + + const float alpha = 17.; //Decay time in units of 100ns //TODO!!! to be adjusted + const float kEpsilon = 1.e-6; //Accuracy of fit //TODO!!! to be adjusted + const int nIter = 10; //Maximal number of iterations //TODO!!! to be adjusted + + float chi2 = 0; + float derT = 0, derTprev = 0.; + float stepT = 0.1; + int iter = 0, i = 0; + do { + chi2 = 0.; + derTprev = derT; + derT = 0.; + i = 0; + float sA = 0., sB = 0.; + std::vector<uint16_t>::const_reverse_iterator it = signal.rbegin(); + while (it != signal.rend()) { + uint16_t si = *it; + float ti = tsart + i - t0; + it++; + i++; + if (mOverflow.back() && si == mMaxSample) { //do not fit saturated samples + continue; + } + float fi = ti * ti * exp(-ti * alpha); + chi2 += (si - A * fi) * (si - A * fi); + sA += si * fi; + sB += fi * fi; + if (ti != 0.) { + derT += (2. / ti - alpha) * fi * (A * fi - si); + } + } + derT *= A; + //calculate time step and next time + if (derTprev != 0. && derT - derTprev != 0.) { + stepT = derT / (derT - derTprev) * stepT; + } + derTprev = derT; + t0 -= stepT; + if (sB > 0.) { + A = sA / sB; + } + } while (fabs(stepT) > kEpsilon && iter < nIter); // if time step is too small, stop + + if (iter >= nIter) { //Fit did not converge, keep old A and t0. + return kFitFailed; + } + + if (i > 0) { //chi2/NDF + chi2 /= i; + } + + mTime.back() = t0; + mAmp.back() = A; + return kOK; +} diff --git a/Detectors/PHOS/reconstruction/src/Channel.cxx b/Detectors/PHOS/reconstruction/src/Channel.cxx new file mode 100644 index 0000000000000..a621cb3b97966 --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/Channel.cxx @@ -0,0 +1,46 @@ +// 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 "PHOSReconstruction/Channel.h" + +using namespace o2::phos; + +int Channel::getBranchIndex() const +{ + if (mHardwareAddress == -1) + throw HardwareAddressError(); + return ((mHardwareAddress >> 11) & 0x1); +} + +int Channel::getFECIndex() const +{ + if (mHardwareAddress == -1) + throw HardwareAddressError(); + return ((mHardwareAddress >> 7) & 0xF); +} + +Int_t Channel::getAltroIndex() const +{ + if (mHardwareAddress == -1) + throw HardwareAddressError(); + return ((mHardwareAddress >> 4) & 0x7); +} + +Int_t Channel::getChannelIndex() const +{ + if (mHardwareAddress == -1) + throw HardwareAddressError(); + return (mHardwareAddress & 0xF); +} + +Bunch& Channel::createBunch(uint8_t bunchlength, uint8_t starttime) +{ + mBunches.emplace_back(bunchlength, starttime); + return mBunches.back(); +} \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/src/RawBuffer.cxx b/Detectors/PHOS/reconstruction/src/RawBuffer.cxx new file mode 100644 index 0000000000000..1172aebd70894 --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/RawBuffer.cxx @@ -0,0 +1,74 @@ +// 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 <fstream> +#include <iostream> +#include <cstring> +#include <FairLogger.h> +#include "PHOSReconstruction/RawBuffer.h" + +using namespace o2::phos; + +void RawBuffer::flush() +{ + mCurrentDataWord = 0; + mNDataWords = 0; + memset(mDataWords.data(), 0, sizeof(uint32_t) * mDataWords.size()); +} + +void RawBuffer::readFromStream(std::istream& in, uint32_t payloadsize) +{ + flush(); + uint32_t word(0); + auto address = reinterpret_cast<char*>(&word); + int nbyte = 0; + while (nbyte < payloadsize) { + in.read(address, sizeof(word)); + nbyte += sizeof(word); + if ((word & 0xFFFFFF) == 0x1d3082) { + LOG(ERROR) << "Found stop word" << std::endl; + // Termination word + // should normally not be decoded in case the payload size + // is determined correctly + break; + } + mDataWords[mNDataWords++] = word; + } +} + +void RawBuffer::readFromMemoryBuffer(const gsl::span<const char> rawmemory) +{ + flush(); + auto address = reinterpret_cast<const uint32_t*>(rawmemory.data()); + for (auto iword = 0; iword < rawmemory.size() / sizeof(uint32_t); iword++) { + // Run2 code, probably not needed for run3 + // if ((address[iword] & 0xFFF) == 0x082) { + // Termination word + // should normally not be decoded in case the payload size + // is determined correctly + //std::cout << "Found termination word" << std::endl; + //break; + // } + mDataWords[mNDataWords++] = address[iword]; + } +} + +uint32_t RawBuffer::getWord(int index) const +{ + if (index >= mNDataWords) + throw std::runtime_error("Index out of range"); + return mDataWords[index]; +} + +uint32_t RawBuffer::getNextDataWord() +{ + if (!hasNext()) + throw std::runtime_error("No more data words in buffer"); + return mDataWords[mCurrentDataWord++]; +} diff --git a/Detectors/PHOS/reconstruction/src/RawHeaderStream.cxx b/Detectors/PHOS/reconstruction/src/RawHeaderStream.cxx new file mode 100644 index 0000000000000..59714a5293d82 --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/RawHeaderStream.cxx @@ -0,0 +1,106 @@ +// 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 <fstream> +#include <iostream> +#include "PHOSReconstruction/RawHeaderStream.h" + +std::istream& o2::phos::operator>>(std::istream& stream, o2::header::RAWDataHeaderV4& header) +{ + //std::cout << "called, 10 words" << std::endl; + using wordtype = uint64_t; + constexpr int RAWHEADERWORDS = sizeof(header) / sizeof(wordtype); + wordtype message[RAWHEADERWORDS]; + auto address = reinterpret_cast<char*>(message); + for (int i = 0; i < RAWHEADERWORDS; i++) { + stream.read(address + i * sizeof(wordtype) / sizeof(char), sizeof(message[i])); + //std::cout << "Word " << i << ": " << std::hex << message[i] << std::dec << std::endl; + } + header.word0 = message[0]; + header.word1 = message[1]; + header.word2 = message[2]; + header.word3 = message[3]; + header.word4 = message[4]; + header.word5 = message[5]; + header.word6 = message[6]; + header.word7 = message[7]; + return stream; +} + +std::istream& o2::phos::operator>>(std::istream& stream, o2::header::RAWDataHeaderV5& header) +{ + //std::cout << "called, 10 words" << std::endl; + using wordtype = uint64_t; + constexpr int RAWHEADERWORDS = sizeof(header) / sizeof(wordtype); + wordtype message[RAWHEADERWORDS]; + auto address = reinterpret_cast<char*>(message); + for (int i = 0; i < RAWHEADERWORDS; i++) { + stream.read(address + i * sizeof(wordtype) / sizeof(char), sizeof(message[i])); + //std::cout << "Word " << i << ": " << std::hex << message[i] << std::dec << std::endl; + } + header.word0 = message[0]; + header.word1 = message[1]; + header.word2 = message[2]; + header.word3 = message[3]; + header.word4 = message[4]; + header.word5 = message[5]; + header.word6 = message[6]; + header.word7 = message[7]; + return stream; +} + +std::ostream& o2::phos::operator<<(std::ostream& stream, const o2::header::RAWDataHeaderV4& header) +{ + stream << "Raw data header V4:\n" + << " Word0 " << header.word0 << " (0x" << std::hex << header.word0 << std::dec << ")\n" + << " Version: " << header.version << "\n" + << " Header size: " << header.headerSize << "\n" + << " Block length: " << header.blockLength << "\n" + << " FEE ID: " << header.feeId << "\n" + << " Priority: " << header.priority << "\n" + << " Word1 " << header.word1 << " (0x" << std::hex << header.word1 << std::dec << ")\n" + << " Offset to next: " << header.offsetToNext << "\n" + << " Payload size (B):" << header.memorySize << "\n" + << " Packet counter: " << static_cast<int>(header.packetCounter) << "\n" + << " Link ID: " << static_cast<int>(header.linkID) << "\n" + << " Card ID: " << header.cruID << "\n" + << " Endpoint: " << static_cast<int>(header.endPointID) << "\n" + << " Word2 " << header.word2 << " (0x" << std::hex << header.word2 << std::dec << ")\n" + << " Trigger orbit: " << header.triggerOrbit << "\n" + << " Heartbeat orbit: " << header.heartbeatOrbit << "\n" + << " Word3 " << header.word3 << " (0x" << std::hex << header.word3 << std::dec << ")\n" + << " Word4 " << header.word4 << " (0x" << std::hex << header.word4 << std::dec << ")\n" + << " Trigger BC: " << header.triggerBC << "\n" + << " Heartbeat BC: " << header.heartbeatBC << "\n" + << " Trigger Type: " << header.triggerType << "\n" + << " Word5 " << header.word5 << " (0x" << std::hex << header.word5 << std::dec << ")\n" + << " Word6 " << header.word6 << " (0x" << std::hex << header.word6 << std::dec << ")\n" + << " Detector Field: " << header.detectorField << "\n" + << " PAR: " << header.par << "\n" + << " STOP: " << header.stop << "\n" + << " Page count: " << header.pageCnt << "\n" + << " Word7 " << header.word7 << " (0x" << std::hex << header.word7 << std::dec << ")\n" + << "End header\n"; + return stream; +} + +std::ostream& o2::phos::operator<<(std::ostream& stream, const o2::header::RAWDataHeaderV5& header) +{ + stream << "Raw data header V5:\n" + << " Word0 " << header.word0 << " (0x" << std::hex << header.word0 << std::dec << ")\n" + << " Word1 " << header.word1 << " (0x" << std::hex << header.word1 << std::dec << ")\n" + << " Word2 " << header.word2 << " (0x" << std::hex << header.word2 << std::dec << ")\n" + << " Word3 " << header.word3 << " (0x" << std::hex << header.word3 << std::dec << ")\n" + << " Word4 " << header.word4 << " (0x" << std::hex << header.word4 << std::dec << ")\n" + << " Word5 " << header.word5 << " (0x" << std::hex << header.word5 << std::dec << ")\n" + << " Word6 " << header.word6 << " (0x" << std::hex << header.word6 << std::dec << ")\n" + << " Word7 " << header.word7 << " (0x" << std::hex << header.word7 << std::dec << ")\n" + << "End header\n"; + return stream; +} \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/src/RawPayload.cxx b/Detectors/PHOS/reconstruction/src/RawPayload.cxx new file mode 100644 index 0000000000000..2bb2b08d86dcb --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/RawPayload.cxx @@ -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. + +#include "PHOSReconstruction/RawPayload.h" + +using namespace o2::phos; + +RawPayload::RawPayload(gsl::span<const uint32_t> payloadwords, int numpages) : mPayloadWords(payloadwords.size()), + mNumberOfPages(numpages) +{ + for (auto word : payloadwords) + mPayloadWords.emplace_back(word); +} + +void RawPayload::appendPayloadWords(const gsl::span<const uint32_t> payloadwords) +{ + for (auto word : payloadwords) + mPayloadWords.emplace_back(word); +} + +void RawPayload::reset() +{ + mPayloadWords.clear(); + mNumberOfPages = 0; +} diff --git a/Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx b/Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx new file mode 100644 index 0000000000000..f7e9c47bd8e89 --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx @@ -0,0 +1,190 @@ +// 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 <sstream> +#include <string> +#include "PHOSReconstruction/RawReaderMemory.h" +#include "PHOSReconstruction/RawDecodingError.h" +#include "DetectorsRaw/RDHUtils.h" + +using namespace o2::phos; + +using RDHDecoder = o2::raw::RDHUtils; + +RawReaderMemory::RawReaderMemory(gsl::span<const char> rawmemory) : mRawMemoryBuffer(rawmemory) +{ + init(); +} + +void RawReaderMemory::setRawMemory(const gsl::span<const char> rawmemory) +{ + mRawMemoryBuffer = rawmemory; + init(); +} + +o2::header::RDHAny RawReaderMemory::decodeRawHeader(const void* payloadwords) +{ + auto headerversion = RDHDecoder::getVersion(payloadwords); + if (headerversion == 4) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV4*>(payloadwords)); + } else if (headerversion == 5) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV5*>(payloadwords)); + } else if (headerversion == 6) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV6*>(payloadwords)); + } + throw RawDecodingError::ErrorType_t::HEADER_DECODING; +} + +void RawReaderMemory::init() +{ + mCurrentPosition = 0; + mRawHeaderInitialized = false; + mPayloadInitialized = false; + mRawBuffer.flush(); + mNumData = mRawMemoryBuffer.size() / 8192; // assume fixed 8 kB pages +} + +void RawReaderMemory::next() +{ + mRawPayload.reset(); + mCurrentTrailer.reset(); + bool isDataTerminated = false; + do { + try { + nextPage(false); + } catch (RawDecodingError::ErrorType_t e) { + throw e; + } + if (hasNext()) { + auto nextheader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + // check continuing payload based on the bc/orbit ID + auto currentbc = RDHDecoder::getTriggerBC(mRawHeader), + nextbc = RDHDecoder::getTriggerBC(nextheader); + auto currentorbit = RDHDecoder::getTriggerOrbit(mRawHeader), + nextorbit = RDHDecoder::getTriggerOrbit(nextheader); + if (currentbc != nextbc || currentorbit != nextorbit) { + isDataTerminated = true; + } else { + auto nextpagecounter = RDHDecoder::getPageCounter(nextheader); + if (nextpagecounter == 0) { + isDataTerminated = true; + } else { + isDataTerminated = false; + } + } + } else { + isDataTerminated = true; + } + // Check if the data continues + } while (!isDataTerminated); + // add combined trailer to payload + mRawPayload.appendPayloadWords(mCurrentTrailer.encode()); +} + +void RawReaderMemory::nextPage(bool doResetPayload) +{ + if (!hasNext()) { + throw RawDecodingError::ErrorType_t::PAGE_NOTFOUND; + } + if (doResetPayload) { + mRawPayload.reset(); + } + mRawHeaderInitialized = false; + mPayloadInitialized = false; + // Read header + try { + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + if (RDHDecoder::getOffsetToNext(mRawHeader) == RDHDecoder::getHeaderSize(mRawHeader)) { + // No Payload - jump to next rawheader + // This will eventually move, depending on whether for events without payload in the SRU we send the RCU trailer + mCurrentPosition += RDHDecoder::getHeaderSize(mRawHeader); + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + } + mRawHeaderInitialized = true; + } catch (...) { + throw RawDecodingError::ErrorType_t::HEADER_DECODING; + } + if (mCurrentPosition + RDHDecoder::getMemorySize(mRawHeader) > mRawMemoryBuffer.size()) { + // Payload incomplete + throw RawDecodingError::ErrorType_t::PAYLOAD_DECODING; + } else { + mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + mCurrentPosition + RDHDecoder::getHeaderSize(mRawHeader), RDHDecoder::getMemorySize(mRawHeader) - RDHDecoder::getHeaderSize(mRawHeader))); + + // Read off and chop trailer + // + // Every page gets a trailer. The trailers from the single pages need to be removed. + // There will be a combined trailer which keeps the sum of the payloads for all trailers. + // This will be appended to the chopped payload. + int tralersize = 0; + if (!mCurrentTrailer.isInitialized()) { + try { + mCurrentTrailer.constructFromPayloadWords(mRawBuffer.getDataWords()); + } catch (...) { + throw RawDecodingError::ErrorType_t::HEADER_DECODING; + } + tralersize = mCurrentTrailer.getTrailerSize(); + } else { + RCUTrailer trailer; + try { + trailer.constructFromPayloadWords(mRawBuffer.getDataWords()); + } catch (...) { + throw RawDecodingError::ErrorType_t::HEADER_INVALID; + } + + mCurrentTrailer.setPayloadSize(mCurrentTrailer.getPayloadSize() + trailer.getPayloadSize()); + tralersize = trailer.getTrailerSize(); + } + + gsl::span<const uint32_t> payloadWithoutTrailer(mRawBuffer.getDataWords().data(), mRawBuffer.getDataWords().size() - tralersize); + + mRawPayload.appendPayloadWords(payloadWithoutTrailer); + mRawPayload.increasePageCount(); + } + mCurrentPosition += RDHDecoder::getOffsetToNext(mRawHeader); /// Assume fixed 8 kB page size +} + +void RawReaderMemory::readPage(int page) +{ + int currentposition = 8192 * page; + if (currentposition >= mRawMemoryBuffer.size()) { + throw RawDecodingError::ErrorType_t::PAGE_NOTFOUND; + } + mRawHeaderInitialized = false; + mPayloadInitialized = false; + // Read header + try { + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + mRawHeaderInitialized = true; + } catch (...) { + throw RawDecodingError::ErrorType_t::HEADER_DECODING; + } + if (currentposition + RDHDecoder::getHeaderSize(mRawHeader) + RDHDecoder::getMemorySize(mRawHeader) >= mRawMemoryBuffer.size()) { + // Payload incomplete + throw RawDecodingError::ErrorType_t::PAYLOAD_DECODING; + } else { + mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + currentposition + RDHDecoder::getHeaderSize(mRawHeader), RDHDecoder::getMemorySize(mRawHeader))); + } +} + +const o2::header::RDHAny& RawReaderMemory::getRawHeader() const +{ + if (!mRawHeaderInitialized) { + throw RawDecodingError::ErrorType_t::HEADER_INVALID; + } + return mRawHeader; +} + +const RawBuffer& RawReaderMemory::getRawBuffer() const +{ + if (!mPayloadInitialized) { + throw RawDecodingError::ErrorType_t::PAYLOAD_INVALID; + } + return mRawBuffer; +} diff --git a/Detectors/PHOS/simulation/CMakeLists.txt b/Detectors/PHOS/simulation/CMakeLists.txt index a7dc3a7ef4095..fc4ce4e851b50 100644 --- a/Detectors/PHOS/simulation/CMakeLists.txt +++ b/Detectors/PHOS/simulation/CMakeLists.txt @@ -12,14 +12,25 @@ o2_add_library(PHOSSimulation SOURCES src/Detector.cxx src/GeometryParams.cxx src/Digitizer.cxx + src/RawWriter.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::DataFormatsPHOS O2::PHOSBase - O2::PHOSCalib) + O2::PHOSCalib + O2::SimConfig + O2::SimulationDataFormat + O2::Headers + O2::DetectorsRaw) o2_target_root_dictionary(PHOSSimulation HEADERS include/PHOSSimulation/Detector.h include/PHOSSimulation/GeometryParams.h - include/PHOSSimulation/Digitizer.h) + include/PHOSSimulation/Digitizer.h + include/PHOSSimulation/RawWriter.h) +o2_add_executable(digi2raw + COMPONENT_NAME phos + PUBLIC_LINK_LIBRARIES O2::PHOSSimulation + SOURCES src/RawCreator.cxx) + o2_data_file(COPY data DESTINATION Detectors/PHS/simulation) diff --git a/Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h b/Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h new file mode 100644 index 0000000000000..194d0d29d25c4 --- /dev/null +++ b/Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h @@ -0,0 +1,124 @@ +// 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_PHOS_RAWWRITER_H +#define ALICEO2_PHOS_RAWWRITER_H + +#include <gsl/span> + +#include <array> +#include <fstream> +#include <memory> +#include <string> +#include <map> +#include <vector> + +#include "Rtypes.h" + +#include "DetectorsRaw/RawFileWriter.h" +#include "PHOSBase/Mapping.h" +#include "DataFormatsPHOS/Digit.h" +#include "DataFormatsPHOS/TriggerRecord.h" +#include "PHOSCalib/CalibParams.h" + +namespace o2 +{ + +namespace phos +{ + +static constexpr short kNPHOSSAMPLES = 15; ///< Maximal number of samples in altro +static constexpr short kOVERFLOW = 970; ///< Overflow level: 1023-pedestal~50 +static constexpr float kPHOSTIMETICK = 100.e-9; ///< PHOS sampling time step + +struct AltroBunch { + int mStarttime; + std::vector<int> mADCs; +}; + +struct SRUDigitContainer { + int mSRUid; + std::map<short, std::vector<o2::phos::Digit*>> mChannels; +}; + +union ChannelHeader { + uint32_t mDataWord; + struct { + uint32_t mHardwareAddress : 16; ///< Bits 0 - 15: Hardware address + uint32_t mPayloadSize : 10; ///< Bits 16 - 25: Payload size + uint32_t mZero1 : 3; ///< Bits 26 - 28: zeroed + uint32_t mBadChannel : 1; ///< Bit 29: Bad channel status + uint32_t mZero2 : 2; ///< Bits 30 - 31: zeroed + }; +}; + +union CaloBunchWord { + uint32_t mDataWord; + struct { + uint32_t mWord2 : 10; ///< Bits 0 - 9 : Word 2 + uint32_t mWord1 : 10; ///< Bits 10 - 19 : Word 1 + uint32_t mWord0 : 10; ///< Bits 20 - 29 : Word 0 + uint32_t mZero : 2; ///< Bits 30 - 31 : zeroed + }; +}; + +class RawWriter +{ + public: + enum class FileFor_t { + kFullDet, + kLink + }; + RawWriter() = default; + RawWriter(const char* outputdir) { setOutputLocation(outputdir); } + ~RawWriter() = default; + + o2::raw::RawFileWriter& getWriter() const { return *mRawWriter; } + + void setOutputLocation(const char* outputdir) { mOutputLocation = outputdir; } + void setFileFor(FileFor_t filefor) { mFileFor = filefor; } + + void init(); + void digitsToRaw(gsl::span<o2::phos::Digit> digits, gsl::span<o2::phos::TriggerRecord> triggers); + bool processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, const o2::phos::TriggerRecord& trg); + + int carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data, + const char* ptr, int maxSize, int splitID, + std::vector<char>& trailer, std::vector<char>& header) const; + + protected: + void createRawBunches(const std::vector<o2::phos::Digit*>& digits, std::vector<o2::phos::AltroBunch>& bunchHG, + std::vector<o2::phos::AltroBunch>& bunchLG, bool& isLGFilled); + + std::vector<int> encodeBunchData(const std::vector<int>& data); + void fillGamma2(float amp, float time, short* samples); + // std::tuple<int, int, int> getOnlineID(int towerID); + // std::tuple<int, int> getLinkAssignment(int ddlID); + + ChannelHeader createChannelHeader(int hardwareAddress, int payloadSize); + std::vector<char> createRCUTrailer(int payloadsize, int feca, int fecb, double timesample, double l1phase); + + private: + FileFor_t mFileFor = FileFor_t::kFullDet; ///< Granularity of the output files + std::string mOutputLocation = "./"; ///< Rawfile name + std::unique_ptr<o2::phos::Mapping> mMapping; ///< Mapping handler + const CalibParams* mCalibParams = nullptr; ///< PHOS calibration + gsl::span<o2::phos::Digit> mDigits; ///< Digits input vector - must be in digitized format including the time response + std::vector<SRUDigitContainer> mSRUdata; ///< Internal helper of digits assigned to SRUs + std::unique_ptr<o2::raw::RawFileWriter> mRawWriter; ///< Raw writer + + ClassDefNV(RawWriter, 1); +}; + +} // namespace phos + +} // namespace o2 + +#endif diff --git a/Detectors/PHOS/simulation/src/Digitizer.cxx b/Detectors/PHOS/simulation/src/Digitizer.cxx index 630e31b2367c5..7f85fb83d06ba 100644 --- a/Detectors/PHOS/simulation/src/Digitizer.cxx +++ b/Detectors/PHOS/simulation/src/Digitizer.cxx @@ -85,7 +85,10 @@ void Digitizer::process(const std::vector<Hit>* hitsBg, const std::vector<Hit>* } Int_t nTotCells = mGeometry->getTotalNCells(); - for (short absId = 1; absId < nTotCells; absId++) { + + short start = 64 * 56 + 32 * 56 + 1; //first digit in half-mod 1 + char relid[3]; + for (short absId = start; absId < nTotCells; absId++) { // If signal exist in this cell, add noise to it, otherwise just create noise digit if (absId == hitAbsId) { diff --git a/Detectors/PHOS/simulation/src/PHOSSimulationLinkDef.h b/Detectors/PHOS/simulation/src/PHOSSimulationLinkDef.h index c6017f6b1148b..e6f39d31db820 100644 --- a/Detectors/PHOS/simulation/src/PHOSSimulationLinkDef.h +++ b/Detectors/PHOS/simulation/src/PHOSSimulationLinkDef.h @@ -18,5 +18,6 @@ #pragma link C++ class o2::phos::GeometryParams + ; #pragma link C++ class o2::base::DetImpl < o2::phos::Detector> + ; #pragma link C++ class o2::phos::Digitizer + ; +#pragma link C++ class o2::phos::RawWriter + ; #endif diff --git a/Detectors/PHOS/simulation/src/RawCreator.cxx b/Detectors/PHOS/simulation/src/RawCreator.cxx new file mode 100644 index 0000000000000..d70a7c011dd21 --- /dev/null +++ b/Detectors/PHOS/simulation/src/RawCreator.cxx @@ -0,0 +1,108 @@ +// 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 <memory> +#include <string> +#include <vector> +#include "Framework/Logger.h" + +#include <boost/program_options.hpp> + +#include <TFile.h> +#include <TTree.h> +#include <TTreeReader.h> +#include <TSystem.h> + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/StringUtils.h" +#include "DataFormatsPHOS/Digit.h" +#include "DataFormatsPHOS/TriggerRecord.h" +#include "PHOSBase/Geometry.h" +#include "PHOSSimulation/RawWriter.h" + +namespace bpo = boost::program_options; + +int main(int argc, const char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + " <cmds/options>\n" + " Tool will encode phos raw data from input file\n" + "Commands / Options"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + add_option("verbose,v", bpo::value<uint32_t>()->default_value(0), "Select verbosity level [0 = no output]"); + add_option("input-file,i", bpo::value<std::string>()->default_value("phosdigits.root"), "Specifies digit input file."); + add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,subdet,link"); + add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); + add_option("debug,d", bpo::value<uint32_t>()->default_value(0), "Select debug output level [0 = no debug output]"); + add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help") || argc == 1) { + std::cout << opt_general << std::endl; + exit(0); + } + + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + + o2::conf::ConfigurableParam::updateFromString(vm["configKeyValues"].as<std::string>()); + + auto digitfilename = vm["input-file"].as<std::string>(), + outputdir = vm["output-dir"].as<std::string>(), + filefor = vm["file-for"].as<std::string>(); + + // if needed, create output directory + if (gSystem->AccessPathName(outputdir.c_str())) { + if (gSystem->mkdir(outputdir.c_str(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outputdir; + } else { + LOG(INFO) << "created output directory " << outputdir; + } + } + + std::unique_ptr<TFile> digitfile(TFile::Open(digitfilename.data(), "READ")); + auto treereader = std::make_unique<TTreeReader>(static_cast<TTree*>(digitfile->Get("o2sim"))); + TTreeReaderValue<std::vector<o2::phos::Digit>> digitbranch(*treereader, "PHOSDigit"); + TTreeReaderValue<std::vector<o2::phos::TriggerRecord>> triggerbranch(*treereader, "PHOSDigitTrigRecords"); + + o2::phos::RawWriter::FileFor_t granularity = o2::phos::RawWriter::FileFor_t::kFullDet; + if (filefor == "all") { + granularity = o2::phos::RawWriter::FileFor_t::kFullDet; + } else if (filefor == "link") { + granularity = o2::phos::RawWriter::FileFor_t::kLink; + } + + o2::phos::RawWriter rawwriter; + rawwriter.setOutputLocation(outputdir.data()); + rawwriter.setFileFor(granularity); + rawwriter.init(); + + // Loop over all entries in the tree, where each tree entry corresponds to a time frame + for (auto en : *treereader) { + rawwriter.digitsToRaw(*digitbranch, *triggerbranch); + } + rawwriter.getWriter().writeConfFile("PHS", "RAWDATA", o2::utils::concat_string(outputdir, "/PHSraw.cfg")); +} diff --git a/Detectors/PHOS/simulation/src/RawWriter.cxx b/Detectors/PHOS/simulation/src/RawWriter.cxx new file mode 100644 index 0000000000000..a17c00886240c --- /dev/null +++ b/Detectors/PHOS/simulation/src/RawWriter.cxx @@ -0,0 +1,364 @@ +// 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 "FairLogger.h" + +#include <fmt/core.h> +#include <gsl/span> +#include <TSystem.h> +#include "PHOSBase/RCUTrailer.h" +#include "PHOSSimulation/RawWriter.h" +#include "PHOSBase/PHOSSimParams.h" +#include "CCDB/CcdbApi.h" + +using namespace o2::phos; + +void RawWriter::init() +{ + mRawWriter = std::make_unique<o2::raw::RawFileWriter>(o2::header::gDataOriginPHS, false); + mRawWriter->setCarryOverCallBack(this); + mRawWriter->setApplyCarryOverToLastPage(true); + + // initialize mapping + if (!mMapping) { + mMapping = std::unique_ptr<o2::phos::Mapping>(new o2::phos::Mapping()); + if (!mMapping) { + LOG(ERROR) << "Failed to initialize mapping"; + } + if (mMapping->setMapping() != o2::phos::Mapping::kOK) { + LOG(ERROR) << "Failed to construct mapping"; + } + } + + for (auto iddl = 0; iddl < o2::phos::Mapping::NDDL; iddl++) { + // For PHOS set + std::string rawfilename = mOutputLocation; + switch (mFileFor) { + case FileFor_t::kFullDet: + rawfilename += "/phos.raw"; + break; + case FileFor_t::kLink: + rawfilename += fmt::format("/phos_{:d}.raw", iddl); + } + short crorc, link; + mMapping->ddlToCrorcLink(iddl, crorc, link); + mRawWriter->registerLink(iddl, crorc, link, 0, rawfilename.data()); + } + + // initialize containers for SRU + for (auto isru = 0; isru < o2::phos::Mapping::NDDL; isru++) { + SRUDigitContainer srucont; + srucont.mSRUid = isru; + mSRUdata.push_back(srucont); + } +} + +void RawWriter::digitsToRaw(gsl::span<o2::phos::Digit> digitsbranch, gsl::span<o2::phos::TriggerRecord> triggerbranch) +{ + if (!mCalibParams) { + if (o2::phos::PHOSSimParams::Instance().mCCDBPath.compare("localtest") == 0) { + mCalibParams = new CalibParams(1); // test default calibration + LOG(INFO) << "[RawWriter] No reading calibration from ccdb requested, set default"; + } else { + LOG(INFO) << "[RawWriter] getting calibration object from ccdb"; + o2::ccdb::CcdbApi ccdb; + std::map<std::string, std::string> metadata; + ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation + auto tr = triggerbranch.begin(); + double eventTime = -1; + // if(tr!=triggerbranch.end()){ + // eventTime = (*tr).getBCData().getTimeNS() ; + // } + mCalibParams = ccdb.retrieveFromTFileAny<o2::phos::CalibParams>("PHOS/Calib", metadata, eventTime); + if (!mCalibParams) { + LOG(FATAL) << "[RawWriter] can not get calibration object from ccdb"; + } + } + } + + for (auto trg : triggerbranch) { + processTrigger(digitsbranch, trg); + } +} + +bool RawWriter::processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, const o2::phos::TriggerRecord& trg) +{ + auto srucont = mSRUdata.begin(); + while (srucont != mSRUdata.end()) { + srucont->mChannels.clear(); + srucont++; + } + std::vector<o2::phos::Digit*>* digitsList; + for (auto& dig : gsl::span(digitsbranch.data() + trg.getFirstEntry(), trg.getNumberOfObjects())) { + short absId = dig.getAbsId(); + short ddl, hwAddrHG; + //get ddl and High Gain hw addresses + if (mMapping->absIdTohw(absId, 0, ddl, hwAddrHG) != o2::phos::Mapping::kOK) { + LOG(ERROR) << "Wrong AbsId" << absId; + } + + //Collect possible several digits (signal+pileup) into one map record + auto celldata = mSRUdata[ddl].mChannels.find(absId); + if (celldata == mSRUdata[ddl].mChannels.end()) { + const auto it = mSRUdata[ddl].mChannels.insert(celldata, {absId, std::vector<o2::phos::Digit*>()}); + it->second.push_back(&dig); + } else { + celldata->second.push_back(&dig); + } + } + + // Create and fill DMA pages for each channel + std::vector<int> rawbunches; + std::vector<char> payload; + std::vector<AltroBunch> rawbunchesHG, rawbunchesLG; + + for (srucont = mSRUdata.begin(); srucont != mSRUdata.end(); srucont++) { + short ddl = srucont->mSRUid; + payload.clear(); + + for (auto ch = srucont->mChannels.cbegin(); ch != srucont->mChannels.cend(); ch++) { + // Find out hardware address of the channel + + bool isLGfilled = 0; + createRawBunches(ch->second, rawbunchesHG, rawbunchesLG, isLGfilled); + + short hwAddrHG; //High gain always filled + if (mMapping->absIdTohw(ch->first, 0, ddl, hwAddrHG) != o2::phos::Mapping::kOK) { + LOG(ERROR) << "Wrong AbsId" << ch->first; + } + + rawbunches.clear(); + for (auto& bunch : rawbunchesHG) { + rawbunches.push_back(bunch.mADCs.size() + 2); + rawbunches.push_back(bunch.mStarttime); + for (auto adc : bunch.mADCs) { + rawbunches.push_back(adc); + } + } + if (!rawbunches.size()) { + continue; + } + + auto encodedbunches = encodeBunchData(rawbunches); + auto chanhead = createChannelHeader(hwAddrHG, rawbunches.size()); + char* chanheadwords = reinterpret_cast<char*>(&chanhead); + + for (int iword = 0; iword < sizeof(ChannelHeader) / sizeof(char); iword++) { + payload.emplace_back(chanheadwords[iword]); + } + char* channelwords = reinterpret_cast<char*>(encodedbunches.data()); + for (auto iword = 0; iword < encodedbunches.size() * sizeof(int) / sizeof(char); iword++) { + payload.emplace_back(channelwords[iword]); + } + + if (isLGfilled) { //fill both HighGain, and LowGain channels in case of saturation + short hwAddrLG; //High gain always filled + if (mMapping->absIdTohw(ch->first, 1, ddl, hwAddrLG) != o2::phos::Mapping::kOK) { + LOG(ERROR) << "Wrong AbsId" << ch->first; + } + + rawbunches.clear(); + for (auto& bunch : rawbunchesHG) { + rawbunches.push_back(bunch.mADCs.size() + 2); + rawbunches.push_back(bunch.mStarttime); + for (auto adc : bunch.mADCs) { + rawbunches.push_back(adc); + } + } + + encodedbunches = encodeBunchData(rawbunches); + chanhead = createChannelHeader(hwAddrLG, encodedbunches.size() * 3 - 2); + chanheadwords = reinterpret_cast<char*>(&chanhead); + for (int iword = 0; iword < sizeof(ChannelHeader) / sizeof(char); iword++) { + payload.emplace_back(chanheadwords[iword]); + } + channelwords = reinterpret_cast<char*>(encodedbunches.data()); + for (auto iword = 0; iword < encodedbunches.size() * sizeof(int) / sizeof(char); iword++) { + payload.emplace_back(channelwords[iword]); + } + } + } + + // Create RCU trailer + auto trailerwords = createRCUTrailer(payload.size() / 4, 16, 16, 100., 0.); + for (auto word : trailerwords) { + payload.emplace_back(word); + } + + // register output data + LOG(DEBUG1) << "Adding payload with size " << payload.size() << " (" << payload.size() / 4 << " ALTRO words)"; + + short crorc, link; + mMapping->ddlToCrorcLink(ddl, crorc, link); + mRawWriter->addData(ddl, crorc, link, 0, trg.getBCData(), payload); + } + return true; +} + +void RawWriter::createRawBunches(const std::vector<o2::phos::Digit*>& channelDigits, std::vector<o2::phos::AltroBunch>& bunchHG, + std::vector<o2::phos::AltroBunch>& bunchLG, bool& isLGFilled) +{ + + isLGFilled = false; + short samples[kNPHOSSAMPLES] = {0}; + float hglgratio = 16.; + for (auto dig : channelDigits) { + //Convert energy and time to ADC counts and time ticks + float ampADC = dig->getAmplitude() / mCalibParams->getGain(dig->getAbsId()); + if (ampADC > kOVERFLOW) { //High Gain in saturation, fill also Low Gain + isLGFilled = true; + } + float timeTicks = dig->getTimeStamp(); + //If LowGain will be used, apply LG time decalibration (HG will be omitted in this case in rec.) + if (isLGFilled) { + timeTicks += mCalibParams->getLGTimeCalib(dig->getAbsId()); + hglgratio = mCalibParams->getHGLGRatio(dig->getAbsId()); + } else { + timeTicks += mCalibParams->getHGTimeCalib(dig->getAbsId()); + } + timeTicks /= kPHOSTIMETICK; + //Add to current sample contribution from digit + fillGamma2(ampADC, timeTicks, samples); + } + + //reduce samples below ZS and fill output + short zs = (short)o2::phos::PHOSSimParams::Instance().mZSthreshold; + bunchHG.clear(); + AltroBunch currentBunch; + //Note reverse time order + for (int i = kNPHOSSAMPLES - 1; i--;) { + if (samples[i] > zs) { + currentBunch.mADCs.emplace_back(std::min(kOVERFLOW, samples[i])); + } else { //end of sample? + if (currentBunch.mADCs.size()) { + currentBunch.mStarttime = i + 1; + bunchHG.push_back(currentBunch); + currentBunch.mADCs.clear(); + } + } + } + if (isLGFilled) { + bunchLG.clear(); + currentBunch.mADCs.clear(); + for (int i = kNPHOSSAMPLES - 1; i--;) { + if (samples[i] > zs * hglgratio) { + currentBunch.mADCs.emplace_back(std::min(kOVERFLOW, short(samples[i] / hglgratio))); + } else { //end of sample? + if (currentBunch.mADCs.size()) { + currentBunch.mStarttime = i + 1; + bunchLG.push_back(currentBunch); + currentBunch.mADCs.clear(); + } + } + } + } +} + +void RawWriter::fillGamma2(float amp, float time, short* samples) +{ + //Simulate Gamma2 signal added to current sample in PHOS + float alpha = o2::phos::PHOSSimParams::Instance().mSampleDecayTime; + + for (int i = 0; i < kNPHOSSAMPLES; i++) { + float x = alpha * (i - time); + float y = 0.25 * amp * x * x * std::exp(2. - x); //0.25*exp(-2) normalization to unity + samples[i] += short(y); + } +} + +std::vector<int> RawWriter::encodeBunchData(const std::vector<int>& data) +{ + std::vector<int> encoded; + CaloBunchWord currentword; + currentword.mDataWord = 0; + int wordnumber = 0; + for (auto adc : data) { + switch (wordnumber) { + case 0: + currentword.mWord0 = adc; + break; + case 1: + currentword.mWord1 = adc; + break; + case 2: + currentword.mWord2 = adc; + break; + }; + wordnumber++; + if (wordnumber == 3) { + // start new word; + encoded.push_back(currentword.mDataWord); + currentword.mDataWord = 0; + wordnumber = 0; + } + } + if (wordnumber) { + encoded.push_back(currentword.mDataWord); + } + return encoded; +} + +ChannelHeader RawWriter::createChannelHeader(int hardwareAddress, int payloadSize) +{ + ChannelHeader header; + header.mDataWord = 0; + header.mHardwareAddress = hardwareAddress; + header.mPayloadSize = payloadSize; + header.mZero2 = 1; //mark channel header + return header; +} + +std::vector<char> RawWriter::createRCUTrailer(int payloadsize, int feca, int fecb, double timesample, double l1phase) +{ + RCUTrailer trailer; + trailer.setActiveFECsA(feca); + trailer.setActiveFECsB(fecb); + trailer.setPayloadSize(payloadsize); + trailer.setL1Phase(l1phase); + trailer.setTimeSample(timesample); + auto trailerwords = trailer.encode(); + std::vector<char> encoded(trailerwords.size() * sizeof(uint32_t)); + memcpy(encoded.data(), trailerwords.data(), trailerwords.size() * sizeof(uint32_t)); + return encoded; +} + +int RawWriter::carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data, + const char* ptr, int maxSize, int splitID, + std::vector<char>& trailer, std::vector<char>& header) const +{ + int offs = ptr - &data[0]; // offset wrt the head of the payload + // make sure ptr and end of the suggested block are within the payload + assert(offs >= 0 && size_t(offs + maxSize) <= data.size()); + + // Read trailer template from the end of payload + gsl::span<const uint32_t> payloadwords(reinterpret_cast<const uint32_t*>(data.data()), data.size() / sizeof(uint32_t)); + auto rcutrailer = RCUTrailer::constructFromPayloadWords(payloadwords); + + int sizeNoTrailer = maxSize - rcutrailer.getTrailerSize() * sizeof(uint32_t); + // calculate payload size for RCU trailer: + // assume actualsize is in byte + // Payload size is defined as the number of 32-bit payload words + // -> actualSize to be converted to size of 32 bit words + auto payloadsize = sizeNoTrailer / sizeof(uint32_t); + rcutrailer.setPayloadSize(payloadsize); + auto trailerwords = rcutrailer.encode(); + trailer.resize(trailerwords.size() * sizeof(uint32_t)); + memcpy(trailer.data(), trailerwords.data(), trailer.size()); + // Size to return differs between intermediate pages and last page + // - intermediate page: Size of the trailer needs to be removed as the trailer gets appended + // - last page: Size of the trailer needs to be included as the trailer gets replaced + int bytesLeft = data.size() - (ptr - &data[0]); + bool lastPage = bytesLeft <= maxSize; + int actualSize = maxSize; + if (!lastPage) { + actualSize = sizeNoTrailer; + } + return actualSize; +} diff --git a/Detectors/PHOS/workflow/CMakeLists.txt b/Detectors/PHOS/workflow/CMakeLists.txt index 788527d945d91..87ea0be400524 100644 --- a/Detectors/PHOS/workflow/CMakeLists.txt +++ b/Detectors/PHOS/workflow/CMakeLists.txt @@ -12,10 +12,17 @@ o2_add_library(PHOSWorkflow SOURCES src/RecoWorkflow.cxx src/PublisherSpec.cxx src/CellConverterSpec.cxx + src/RawToCellConverterSpec.cxx src/ClusterizerSpec.cxx src/DigitsPrinterSpec.cxx + src/RawWriterSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsPHOS - O2::DPLUtils O2::PHOSBase O2::PHOSCalib O2::PHOSSimulation O2::PHOSReconstruction O2::Algorithm) + O2::DPLUtils + O2::PHOSBase + O2::PHOSCalib + O2::PHOSSimulation + O2::PHOSReconstruction + O2::Algorithm) o2_add_executable(reco-workflow COMPONENT_NAME phos diff --git a/Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h b/Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h new file mode 100644 index 0000000000000..9afc397c98464 --- /dev/null +++ b/Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h @@ -0,0 +1,84 @@ +// 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 <vector> + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "DataFormatsPHOS/Cell.h" +#include "DataFormatsPHOS/TriggerRecord.h" +#include "PHOSBase/Mapping.h" +#include "PHOSReconstruction/CaloRawFitter.h" +#include "PHOSReconstruction/RawReaderError.h" + +namespace o2 +{ + +namespace phos +{ + +namespace reco_workflow +{ + +/// \class RawToCellConverterSpec +/// \brief Coverter task for Raw data to PHOS cells +/// \author Dmitri Peresunko NRC KI +/// \since Sept., 2020 +/// +class RawToCellConverterSpec : public framework::Task +{ + public: + /// \brief Constructor + /// \param propagateMC If true the MCTruthContainer is propagated to the output + RawToCellConverterSpec() : framework::Task(){}; + + /// \brief Destructor + ~RawToCellConverterSpec() override = default; + + /// \brief Initializing the RawToCellConverterSpec + /// \param ctx Init context + void init(framework::InitContext& ctx) final; + + /// \brief Run conversion of raw data to cells + /// \param ctx Processing context + /// + /// The following branches are linked: + /// Input RawData: {"ROUT", "RAWDATA", 0, Lifetime::Timeframe} + /// Output cells: {"PHS", "CELLS", 0, Lifetime::Timeframe} + /// Output cells trigger record: {"PHS", "CELLSTR", 0, Lifetime::Timeframe} + /// Output HW errors: {"PHS", "RAWHWERRORS", 0, Lifetime::Timeframe} + void run(framework::ProcessingContext& ctx) final; + + protected: + /// \brief simple check of HW address + char CheckHWAddress(short ddl, short hwAddress, short& fee); + + private: + bool mFillChi2 = false; ///< Fill output with quality of samples + bool mCombineGHLG = true; ///< Combine or not HG and LG channels (def: combine, LED runs: not combine) + bool mPedestalRun = false; ///< Analyze pedestal run (calculate pedestal mean and RMS) + std::unique_ptr<o2::phos::Mapping> mMapping = nullptr; ///!<! Mapping + std::unique_ptr<o2::phos::CaloRawFitter> mRawFitter; ///!<! Raw fitter + std::vector<o2::phos::Cell> mOutputCells; ///< Container with output cells + std::vector<o2::phos::TriggerRecord> mOutputTriggerRecords; ///< Container with output cells + std::vector<o2::phos::RawReaderError> mOutputHWErrors; ///< Errors occured in reading data + std::vector<short> mOutputFitChi; ///< Raw sample fit quality +}; + +/// \brief Creating DataProcessorSpec for the PHOS Cell Converter Spec +/// +/// Refer to RawToCellConverterSpec::run for input and output specs +framework::DataProcessorSpec getRawToCellConverterSpec(); + +} // namespace reco_workflow + +} // namespace phos + +} // namespace o2 diff --git a/Detectors/PHOS/workflow/include/PHOSWorkflow/RawWriterSpec.h b/Detectors/PHOS/workflow/include/PHOSWorkflow/RawWriterSpec.h new file mode 100644 index 0000000000000..2712177c38600 --- /dev/null +++ b/Detectors/PHOS/workflow/include/PHOSWorkflow/RawWriterSpec.h @@ -0,0 +1,71 @@ +// 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 <vector> + +#include "Framework/DataProcessorSpec.h" +#include "PHOSSimulation/RawWriter.h" +#include "Framework/Task.h" + +namespace o2 +{ + +namespace phos +{ + +namespace reco_workflow +{ + +/// \class RawWriterSpec +/// \brief Coverter task for PHOS digits to raw +/// \author Dmitri Peresunko after Markus Fasel +/// \since Nov.20, 2020 +/// +/// Task converting a vector of PHOS digits to raw file +class RawWriterSpec : public framework::Task +{ + public: + /// \brief Constructor + /// \param propagateMC If true the MCTruthContainer is propagated to the output + RawWriterSpec() : framework::Task(){}; + + /// \brief Destructor + ~RawWriterSpec() override = default; + + /// \brief Initializing the RawWriterSpec + /// \param ctx Init context + void init(framework::InitContext& ctx) final; + + /// \brief Run conversion of digits to cells + /// \param ctx Processing context + /// + /// Converting the input vector of o2::phos::Digit to + /// file with raw data + /// + /// The following branches are linked: + /// Input digits: {"PHS", "DIGITS", 0, Lifetime::Timeframe} + /// Input digit trigger records: {"PHS", "DIGITTRS", 0, Lifetime::Timeframe} + void run(framework::ProcessingContext& ctx) final; + + private: + o2::phos::RawWriter* mRawWriter = nullptr; +}; + +/// \brief Creating DataProcessorSpec for the PHOS Cell Converter Spec +/// \param propagateMC If true the MC truth container is propagated to the output +/// +/// Refer to RawWriterSpec::run for input and output specs +framework::DataProcessorSpec getRawWriterSpec(); + +} // namespace reco_workflow + +} // namespace phos + +} // namespace o2 diff --git a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx index d3c9ced7ef8c0..3d08cc1e8919c 100644 --- a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx +++ b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx @@ -24,7 +24,7 @@ using namespace o2::phos::reco_workflow; void CellConverterSpec::init(framework::InitContext& ctx) { - LOG(DEBUG) << "[PHOSCellConverter - init] Initialize converter " << (mPropagateMC ? "with" : "without") << " MC truth container"; + LOG(INFO) << "[PHOSCellConverter - init] Initialize converter " << (mPropagateMC ? "with" : "without") << " MC truth container"; } void CellConverterSpec::run(framework::ProcessingContext& ctx) @@ -38,7 +38,6 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); return; } - LOG(INFO) << "Had Payload"; mOutputCells.clear(); mOutputCellTrigRecs.clear(); @@ -113,8 +112,8 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLS", 0, o2::framework::Lifetime::Timeframe}, mOutputCells); ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLTRIGREC", 0, o2::framework::Lifetime::Timeframe}, mOutputCellTrigRecs); if (mPropagateMC) { - ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthCont); - ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthMap); + //ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthCont); + //ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthMap); } LOG(INFO) << "Finished "; ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); @@ -130,8 +129,8 @@ o2::framework::DataProcessorSpec o2::phos::reco_workflow::getCellConverterSpec(b outputs.emplace_back("PHS", "CELLTRIGREC", 0, o2::framework::Lifetime::Timeframe); if (propagateMC) { inputs.emplace_back("digitsmctr", "PHS", "DIGITSMCTR", 0, o2::framework::Lifetime::Timeframe); - outputs.emplace_back("PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe); - outputs.emplace_back("PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe); + //outputs.emplace_back("PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe); + //outputs.emplace_back("PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe); } return o2::framework::DataProcessorSpec{"PHOSCellConverterSpec", inputs, diff --git a/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx b/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx index 5654e58927bc5..6c20378e450a6 100644 --- a/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx +++ b/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx @@ -107,8 +107,8 @@ o2::framework::DataProcessorSpec o2::phos::reco_workflow::getCellClusterizerSpec inputs.emplace_back("cells", o2::header::gDataOriginPHS, "CELLS", 0, o2::framework::Lifetime::Timeframe); inputs.emplace_back("cellTriggerRecords", o2::header::gDataOriginPHS, "CELLTRIGREC", 0, o2::framework::Lifetime::Timeframe); if (propagateMC) { - inputs.emplace_back("cellsmctr", "PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe); - inputs.emplace_back("cellssmcmap", "PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe); + //inputs.emplace_back("cellsmctr", "PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe); + //inputs.emplace_back("cellssmcmap", "PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe); } outputs.emplace_back("PHS", "CLUSTERS", 0, o2::framework::Lifetime::Timeframe); outputs.emplace_back("PHS", "CLUSTERTRIGRECS", 0, o2::framework::Lifetime::Timeframe); diff --git a/Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx b/Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx new file mode 100644 index 0000000000000..3c4ff13a388fc --- /dev/null +++ b/Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx @@ -0,0 +1,269 @@ +// 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 <string> +#include "FairLogger.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" +#include "DataFormatsPHOS/PHOSBlockHeader.h" +#include "DataFormatsPHOS/TriggerRecord.h" +#include "DetectorsRaw/RDHUtils.h" +#include "Framework/InputRecordWalker.h" +#include "PHOSBase/Mapping.h" +#include "PHOSReconstruction/Bunch.h" +#include "PHOSReconstruction/CaloRawFitter.h" +#include "PHOSReconstruction/AltroDecoder.h" +#include "PHOSReconstruction/RawDecodingError.h" +#include "PHOSWorkflow/RawToCellConverterSpec.h" + +using namespace o2::phos::reco_workflow; + +void RawToCellConverterSpec::init(framework::InitContext& ctx) +{ + LOG(DEBUG) << "Initialize converter "; + + auto path = ctx.options().get<std::string>("mappingpath"); + if (!mMapping) { + mMapping = std::unique_ptr<o2::phos::Mapping>(new o2::phos::Mapping(path)); + if (!mMapping) { + LOG(ERROR) << "Failed to initialize mapping"; + } + if (mMapping->setMapping() != o2::phos::Mapping::kOK) { + LOG(ERROR) << "Failed to construct mapping"; + } + } + + auto fitmethod = ctx.options().get<std::string>("fitmethod"); + if (fitmethod == "default") { + LOG(INFO) << "Using default raw fitter"; + mRawFitter = std::unique_ptr<o2::phos::CaloRawFitter>(new o2::phos::CaloRawFitter); + //TODO: Configure parameters of fitter from options + // mRawFitter->setAmpCut(mNoiseThreshold); + // mRawFitter->setL1Phase(0.); + } + + mFillChi2 = (ctx.options().get<std::string>("fillchi2").compare("on") == 0); + if (mFillChi2) { + LOG(INFO) << "Fit quality output will be filled"; + } + + mCombineGHLG = (ctx.options().get<std::string>("keepGHLG").compare("on") != 0); + if (!mCombineGHLG) { + LOG(INFO) << "Both HighGain and LowGain will be kept"; + } + + mPedestalRun = (ctx.options().get<std::string>("pedestal").find("on") != std::string::npos); + if (mPedestalRun) { + mRawFitter->setPedestal(); + LOG(INFO) << "Pedestal run will be processed"; + } +} + +void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) +{ + // Cache cells from bunch crossings as the component reads timeframes from many links consecutively + std::map<o2::InteractionRecord, std::shared_ptr<std::vector<o2::phos::Cell>>> cellBuffer; // Internal cell buffer + int firstEntry = 0; + mOutputHWErrors.clear(); + if (mFillChi2) { + mOutputFitChi.clear(); + } + + for (const auto& rawData : framework::InputRecordWalker(ctx.inputs())) { + + o2::phos::RawReaderMemory rawreader(o2::framework::DataRefUtils::as<const char>(rawData)); + // loop over all the DMA pages + while (rawreader.hasNext()) { + try { + rawreader.next(); + } catch (RawDecodingError::ErrorType_t e) { + LOG(ERROR) << "Raw decoding error " << (int)e; + //add error list + mOutputHWErrors.emplace_back(14, (int)e, 1); //Put general errors to non-existing DDL14 + //if problem in header, abandon this page + if (e == RawDecodingError::ErrorType_t::PAGE_NOTFOUND || + e == RawDecodingError::ErrorType_t::HEADER_DECODING || + e == RawDecodingError::ErrorType_t::HEADER_INVALID) { + break; + } + //if problem in payload, try to continue + continue; + } + auto& header = rawreader.getRawHeader(); + auto triggerBC = o2::raw::RDHUtils::getTriggerBC(header); + auto triggerOrbit = o2::raw::RDHUtils::getTriggerOrbit(header); + auto ddl = o2::raw::RDHUtils::getFEEID(header); + + o2::InteractionRecord currentIR(triggerBC, triggerOrbit); + std::shared_ptr<std::vector<o2::phos::Cell>> currentCellContainer; + auto found = cellBuffer.find(currentIR); + if (found == cellBuffer.end()) { + currentCellContainer = std::make_shared<std::vector<o2::phos::Cell>>(); + cellBuffer[currentIR] = currentCellContainer; + } else { + currentCellContainer = found->second; + } + if (ddl > o2::phos::Mapping::NDDL) { //only 14 correct DDLs + LOG(ERROR) << "DDL=" << ddl; + mOutputHWErrors.emplace_back(15, 16, char(ddl)); //Add non-existing DDL as DDL 15 + continue; //skip STU ddl + } + // use the altro decoder to decode the raw data, and extract the RCU trailer + o2::phos::AltroDecoder decoder(rawreader); + AltroDecoderError::ErrorType_t err = decoder.decode(); + + if (err != AltroDecoderError::kOK) { + //TODO handle severe errors + //TODO: probably careful conversion of decoder errors to Fitter errors? + char e = (char)err; + mOutputHWErrors.emplace_back(ddl, 16, e); //assign general header errors to non-existing FEE 16 + } + // Loop over all the channels + for (auto& chan : decoder.getChannels()) { + + short absId; + Mapping::CaloFlag caloFlag; + + short fee; + char e2 = CheckHWAddress(ddl, chan.getHardwareAddress(), fee); + if (e2) { + mOutputHWErrors.emplace_back(ddl, fee, e2); + continue; + } + Mapping::ErrorStatus s = mMapping->hwToAbsId(ddl, chan.getHardwareAddress(), absId, caloFlag); + if (s != Mapping::ErrorStatus::kOK) { + mOutputHWErrors.emplace_back(ddl, 15, (char)s); //use non-existing FEE 15 for general errors + continue; + } + if (caloFlag != Mapping::kTRU) { //HighGain or LowGain + CaloRawFitter::FitStatus fitResults = mRawFitter->evaluate(chan.getBunches()); + if (mFillChi2) { + for (int is = 0; is < mRawFitter->getNsamples(); is++) { + if (!mRawFitter->isOverflow(is)) { //Overflow is will show wrong chi2 + short chiAddr = absId; + chiAddr |= caloFlag << 14; + mOutputFitChi.emplace_back(chiAddr); + mOutputFitChi.emplace_back(short(mRawFitter->getChi2(is))); + } + } + } + if (fitResults == CaloRawFitter::FitStatus::kOK) { + //TODO: which results should be accepted? full configurable list + for (int is = 0; is < mRawFitter->getNsamples(); is++) { + if (!mRawFitter->isOverflow(is) || caloFlag != o2::phos::Mapping::kHighGain) { //do not use HighGain if sample saturated. In LG special fitting is used + currentCellContainer->emplace_back(absId, mRawFitter->getAmp(is), mRawFitter->getTime(is), (ChannelType_t)caloFlag); + } + } + } + } + } + } //RawReader::hasNext + } + + // Loop over BCs, sort cells with increasing cell ID and write to output containers + mOutputCells.clear(); + mOutputTriggerRecords.clear(); + for (auto [bc, cells] : cellBuffer) { + int prevCellSize = mOutputCells.size(); + if (cells->size()) { + // Sort cells according to cell ID + std::sort(cells->begin(), cells->end(), [](o2::phos::Cell& lhs, o2::phos::Cell& rhs) { return lhs.getAbsId() < rhs.getAbsId(); }); + + if (mCombineGHLG && !mPedestalRun) { // combine for normal data, do not combine e.g. for LED run and pedestal + //Combine HG and LG sells + //Should be next to each other after sorting + auto it1 = cells->begin(); + auto it2 = cells->begin(); + it2++; + while (it1 != cells->end()) { + if (it2 != cells->end()) { + if ((*it1).getAbsId() == (*it2).getAbsId()) { //HG and LG channels, if both, copy only HG as more precise + if ((*it1).getType() == o2::phos::HIGH_GAIN) { + mOutputCells.push_back(*it1); + } else { + mOutputCells.push_back(*it2); + } + ++it1; //yes increase twice + ++it2; + } else { //no double cells, copy this one + mOutputCells.push_back(*it1); + } + } else { //just copy last one + mOutputCells.push_back(*it1); + } + ++it1; + ++it2; + } + } else { + for (auto cell : *cells) { + mOutputCells.push_back(cell); + } + } + } + + mOutputTriggerRecords.emplace_back(bc, mOutputCells.size(), mOutputCells.size() - prevCellSize); + } + cellBuffer.clear(); + + LOG(INFO) << "[PHOSRawToCellConverter - run] Writing " << mOutputCells.size() << " cells ..."; + ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLS", 0, o2::framework::Lifetime::Timeframe}, mOutputCells); + ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLTRIGREC", 0, o2::framework::Lifetime::Timeframe}, mOutputTriggerRecords); + ctx.outputs().snapshot(o2::framework::Output{"PHS", "RAWHWERRORS", 0, o2::framework::Lifetime::Timeframe}, mOutputHWErrors); + if (mFillChi2) { + ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLFITQA", 0, o2::framework::Lifetime::Timeframe}, mOutputFitChi); + } +} + +char RawToCellConverterSpec::CheckHWAddress(short ddl, short hwAddr, short& fee) +{ + + if (ddl < 0 || ddl > o2::phos::Mapping::NDDL) { + return (char)4; + } + // short chan = hwAddr & 0xf; + short chip = hwAddr >> 4 & 0x7; + short fec = hwAddr >> 7 & 0xf; + short branch = hwAddr >> 11 & 0x1; + + if (branch < 0 || branch > 1) { + return (char)1; + } + if (fec < 0 || fec > 15) { + return (char)2; + } + if (fec != 0 && (chip < 0 || chip > 4 || chip == 1)) { //Do not check for TRU (fec=0) + return (char)3; + } + return (char)0; +} + +o2::framework::DataProcessorSpec o2::phos::reco_workflow::getRawToCellConverterSpec() +{ + std::vector<o2::framework::InputSpec> inputs; + inputs.emplace_back("RAWDATA", o2::framework::ConcreteDataTypeMatcher{"PHS", "RAWDATA"}, o2::framework::Lifetime::Timeframe); + + std::vector<o2::framework::OutputSpec> outputs; + outputs.emplace_back("PHS", "CELLS", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("PHS", "CELLTRIGREC", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("PHS", "RAWHWERRORS", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("PHS", "CELLFITQA", 0, o2::framework::Lifetime::Timeframe); + + return o2::framework::DataProcessorSpec{"PHOSRawToCellConverterSpec", + inputs, // o2::framework::select("A:PHS/RAWDATA"), + outputs, + o2::framework::adaptFromTask<o2::phos::reco_workflow::RawToCellConverterSpec>(), + o2::framework::Options{ + {"fitmethod", o2::framework::VariantType::String, "default", {"Fit method (default or fast)"}}, + {"mappingpath", o2::framework::VariantType::String, "", {"Path to mapping files"}}, + {"fillchi2", o2::framework::VariantType::String, "off", {"Fill sample qualities on/off"}}, + {"keepGHLG", o2::framework::VariantType::String, "off", {"keep HighGain and Low Gain signals on/off"}}, + {"pedestal", o2::framework::VariantType::String, "off", {"Analyze as pedestal run on/off"}}}}; +} diff --git a/Detectors/PHOS/workflow/src/RawWriterSpec.cxx b/Detectors/PHOS/workflow/src/RawWriterSpec.cxx new file mode 100644 index 0000000000000..e26bdce955fed --- /dev/null +++ b/Detectors/PHOS/workflow/src/RawWriterSpec.cxx @@ -0,0 +1,70 @@ +// 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 "FairLogger.h" + +/// \file PHOS/Workflow/src/RawWriterSpec.cxx +/// \brief Digits to raw converter spec for PHOS +/// \author Dmitri Peresunko <Dmitri.Peresunko at cern.ch> +/// \date 20 Nov 2020 + +#include "PHOSWorkflow/RawWriterSpec.h" +#include "Framework/RootSerializationSupport.h" +#include "DataFormatsPHOS/Digit.h" +#include "Framework/ControlService.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "PHOSSimulation/RawWriter.h" +#include "DataFormatsPHOS/PHOSBlockHeader.h" +#include "Framework/ConfigParamRegistry.h" + +using namespace o2::phos::reco_workflow; + +void RawWriterSpec::init(framework::InitContext& ctx) +{ + + auto rawdir = ctx.options().get<std::string>("rawpath"); + + LOG(INFO) << "[PHOSRawWriter - init] Initialize raw writer "; + if (!mRawWriter) { + mRawWriter = new o2::phos::RawWriter(); + mRawWriter->setOutputLocation(rawdir.data()); + mRawWriter->init(); + } +} + +void RawWriterSpec::run(framework::ProcessingContext& ctx) +{ + LOG(DEBUG) << "[PHOSRawWriter - run] called"; + + auto digits = ctx.inputs().get<std::vector<o2::phos::Digit>>("digits"); + auto digitsTR = ctx.inputs().get<std::vector<o2::phos::TriggerRecord>>("digitTriggerRecords"); + LOG(INFO) << "[PHOSRawWriter - run] Received " << digits.size() << " digits and " << digitsTR.size() << " TriggerRecords"; + + mRawWriter->digitsToRaw(digits, digitsTR); + LOG(INFO) << "[PHOSRawWriter - run] Finished "; + + //flash and close output files + mRawWriter->getWriter().close(); + ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); +} + +o2::framework::DataProcessorSpec o2::phos::reco_workflow::getRawWriterSpec() +{ + std::vector<o2::framework::InputSpec> inputs; + std::vector<o2::framework::OutputSpec> outputs; + inputs.emplace_back("digits", o2::header::gDataOriginPHS, "DIGITS", 0, o2::framework::Lifetime::Timeframe); + inputs.emplace_back("digitTriggerRecords", o2::header::gDataOriginPHS, "DIGITTRIGREC", 0, o2::framework::Lifetime::Timeframe); + return o2::framework::DataProcessorSpec{"PHOSRawWriterSpec", + inputs, + outputs, + o2::framework::adaptFromTask<o2::phos::reco_workflow::RawWriterSpec>(), + o2::framework::Options{ + {"rawpath", o2::framework::VariantType::String, "./", {"path to write raw"}}, + }}; +} diff --git a/Detectors/PHOS/workflow/src/RecoWorkflow.cxx b/Detectors/PHOS/workflow/src/RecoWorkflow.cxx index cc925c40d7011..c2c1cd9c43334 100644 --- a/Detectors/PHOS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/PHOS/workflow/src/RecoWorkflow.cxx @@ -26,7 +26,8 @@ #include "PHOSWorkflow/ClusterizerSpec.h" #include "PHOSWorkflow/DigitsPrinterSpec.h" #include "PHOSWorkflow/PublisherSpec.h" -//#include "PHOSWorkflow/RawWriterSpec.h" +#include "PHOSWorkflow/RawToCellConverterSpec.h" +#include "PHOSWorkflow/RawWriterSpec.h" #include "Framework/DataSpecUtils.h" #include "SimulationDataFormat/MCTruthContainer.h" @@ -83,54 +84,72 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, // specs.emplace_back(o2::phos::reco_workflow::getRawWriterSpec()); // } - if (inputType == InputType::Digits) { - specs.emplace_back(o2::phos::getPublisherSpec(PublisherConf{ - "phos-digit-reader", - "o2sim", - {"digitbranch", "PHOSDigit", "Digit branch"}, - {"digittrigger", "PHOSDigitTrigRecords", "TrigRecords branch"}, - {"mcbranch", "PHOSDigitMCTruth", "MC label branch"}, - {"mcmapbranch", "", "Dummy branch"}, - o2::framework::OutputSpec{"PHS", "DIGITS"}, - o2::framework::OutputSpec{"PHS", "DIGITTRIGREC"}, - o2::framework::OutputSpec{"PHS", "DIGITSMCTR"}, - o2::framework::OutputSpec{"PHS", ""}}, // it empty, do not create - propagateMC, false)); + if (inputType == InputType::Raw) { + //no explicit raw reader - if (enableDigitsPrinter) { - specs.emplace_back(o2::phos::reco_workflow::getPhosDigitsPrinterSpec()); + if (isEnabled(OutputType::Cells)) { + specs.emplace_back(o2::phos::reco_workflow::getRawToCellConverterSpec()); } + } + if (inputType == InputType::Digits) { if (isEnabled(OutputType::Cells)) { + specs.emplace_back(o2::phos::getPublisherSpec(PublisherConf{ + "phos-digit-reader", + "o2sim", + {"digitbranch", "PHOSDigit", "Digit branch"}, + {"digittrigger", "PHOSDigitTrigRecords", "TrigRecords branch"}, + {"mcbranch", "PHOSDigitMCTruth", "MC label branch"}, + {"mcmapbranch", "", "Dummy branch"}, + o2::framework::OutputSpec{"PHS", "DIGITS"}, + o2::framework::OutputSpec{"PHS", "DIGITTRIGREC"}, + o2::framework::OutputSpec{"PHS", "DIGITSMCTR"}, + o2::framework::OutputSpec{"PHS", ""}}, // it empty, do not create + propagateMC, false)); // add converter for cells specs.emplace_back(o2::phos::reco_workflow::getCellConverterSpec(propagateMC)); } if (isEnabled(OutputType::Clusters)) { + specs.emplace_back(o2::phos::getPublisherSpec(PublisherConf{ + "phos-digit-reader", + "o2sim", + {"digitbranch", "PHOSDigit", "Digit branch"}, + {"digittrigger", "PHOSDigitTrigRecords", "TrigRecords branch"}, + {"mcbranch", "PHOSDigitMCTruth", "MC label branch"}, + {"mcmapbranch", "", "Dummy branch"}, + o2::framework::OutputSpec{"PHS", "DIGITS"}, + o2::framework::OutputSpec{"PHS", "DIGITTRIGREC"}, + o2::framework::OutputSpec{"PHS", "DIGITSMCTR"}, + o2::framework::OutputSpec{"PHS", ""}}, // it empty, do not create + propagateMC, false)); // add clusterizer specs.emplace_back(o2::phos::reco_workflow::getClusterizerSpec(propagateMC)); } - // if (isEnabled(OutputType::Raw)) { - // // add Raw encoder - // specs.emplace_back(o2::phos::reco_workflow::getRawWriterSpec()); - // } + if (enableDigitsPrinter) { + specs.emplace_back(o2::phos::reco_workflow::getPhosDigitsPrinterSpec()); + } + + if (isEnabled(OutputType::Raw)) { + specs.emplace_back(o2::phos::getPublisherSpec(PublisherConf{ + "phos-digit-reader", + "o2sim", + {"digitbranch", "PHOSDigit", "Digit branch"}, + {"digittrigger", "PHOSDigitTrigRecords", "TrigRecords branch"}, + {"mcbranch", "PHOSDigitMCTruth", "Dummy branch"}, + {"mcmapbranch", "", "Dummy branch"}, + o2::framework::OutputSpec{"PHS", "DIGITS"}, + o2::framework::OutputSpec{"PHS", "DIGITTRIGREC"}, + o2::framework::OutputSpec{"PHS", "DIGITSMCTR"}, + o2::framework::OutputSpec{"PHS", ""}}, // it empty, do not create + false, false)); + // add Raw encoder + specs.emplace_back(o2::phos::reco_workflow::getRawWriterSpec()); + } } if (inputType == InputType::Cells) { - specs.emplace_back(o2::phos::getPublisherSpec(PublisherConf{ - "phos-cell-reader", - "o2sim", - {"cellbranch", "PHSCell", "Cells branch"}, - {"celltrigger", "PHSCellTR", "TrigRecords branch"}, - {"mcbranch", "PHSCellMCTruth", "MC label branch"}, - {"mcmapbranch", "PHSCellMCMap", "MC label map branch"}, - o2::framework::OutputSpec{"PHS", "CELLS"}, - o2::framework::OutputSpec{"PHS", "CELLTRIGREC"}, - o2::framework::OutputSpec{"PHS", "CELLSMCTR"}, - o2::framework::OutputSpec{"PHS", "CELLSMCMAP"}}, - propagateMC, true)); - if (isEnabled(OutputType::Clusters)) { // add clusterizer specs.emplace_back(o2::phos::reco_workflow::getCellClusterizerSpec(propagateMC)); @@ -156,57 +175,10 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, return std::make_tuple(o2::framework::MakeRootTreeWriterSpec::TerminationCondition::Action::DoProcessing, false); }; - // auto makeWriterSpec = [propagateMC, checkReady](const char* processName, - // const char* defaultFileName, - // const char* defaultTreeName, - // bool createMCMap, - // auto&& databranch, - // auto&& datatrbranch, - // auto&& mcbranch=nullptr, - // auto&& mcmapbranch=nullptr) { - // // depending on the MC propagation flag, the RootTreeWriter spec is created with two - // // or one branch definition - // if (propagateMC) { - // if(createMCMap){ - // return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, - // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - // std::move(databranch), - // std::move(datatrbranch), - // std::move(mcbranch), - // std::move(mcmapbranch))); - // } - // else{ - // return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, - // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - // std::move(databranch), - // std::move(datatrbranch), - // std::move(mcbranch))); - // } - // } - // else{ - // return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, - // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - // std::move(databranch), - // std::move(datatrbranch))); - // } - // }; - - // if (isEnabled(OutputType::Raw)) { - // using RawOutputType = std::vector<o2::phos::Raw>; - // specs.push_back(makeWriterSpec("phos-raw-writer", - // inputType == InputType::Digits ? "phos-raw.root" : "phosrawcells.root", - // "o2sim", - // BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "PHS", "RAW", 0}, - // "PHSRaw", - // "raw-branch-name"}, - // BranchDefinition<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>>{o2::framework::InputSpec{"mc", "PHS", "RAWMCTR", 0}, - // "PHSRawMCTruth", - // "rawmc-branch-name"})()); - // } - if (isEnabled(OutputType::Digits)) { using DigitOutputType = std::vector<o2::phos::Digit>; using DTROutputType = std::vector<o2::phos::TriggerRecord>; + using MCLabelContainer = o2::dataformats::MCTruthContainer<o2::phos::MCLabel>; specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("phos-digits-writer", "phosdigits.root", "o2sim", -1, @@ -217,28 +189,9 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, BranchDefinition<DTROutputType>{o2::framework::InputSpec{"data", "PHS", "DIGITTRIGREC", 0}, "PHSDigTR", "digittr-branch-name"}, - BranchDefinition<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>>{o2::framework::InputSpec{"mc", "PHS", "DIGITSMCTR", 0}, - "PHSDigitMCTruth", - "digitmc-branch-name"})()); - } - - if (isEnabled(OutputType::Cells)) { - using CellOutputType = std::vector<o2::phos::Cell>; - using CTROutputType = std::vector<o2::phos::TriggerRecord>; - specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("phos-cells-writer", "phoscells.root", "o2sim", -1, - o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - BranchDefinition<CellOutputType>{o2::framework::InputSpec{"data", "PHS", "CELLS", 0}, - "PHSCell", - "cell-branch-name"}, - BranchDefinition<CTROutputType>{o2::framework::InputSpec{"data", "PHS", "CELLTRIGREC", 0}, - "PHSCellTR", - "celltr-branch-name"}, - BranchDefinition<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>>{o2::framework::InputSpec{"mc", "PHS", "CELLSMCTR", 0}, - "PHSCellMCTruth", - "cellmc-branch-name"}, - BranchDefinition<std::vector<uint>>{o2::framework::InputSpec{"mcmap", "PHS", "CELLSMCMAP", 0}, - "PHSCellMCMAP", - "cellmcmap-branch-name"})()); + BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "PHS", "DIGITSMCTR", 0}, + "PHSDigitMCTruth", + "digitmc-branch-name"})()); } if (isEnabled(OutputType::Clusters)) { From 176183c87588199e473798cae44e72cbb0193730 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Wed, 2 Dec 2020 08:38:04 +0100 Subject: [PATCH 1483/1751] First commit of the DQ FilterPP, CutsLibrary and HistogramsLibrary (#4902) --- Analysis/Core/include/Analysis/VarManager.h | 44 ++- Analysis/Core/src/VarManager.cxx | 2 + .../include/Analysis/ReducedInfoTables.h | 8 + Analysis/Tasks/PWGDQ/CMakeLists.txt | 15 +- Analysis/Tasks/PWGDQ/CutsLibrary.h | 194 ++++++++++ Analysis/Tasks/PWGDQ/HistogramsLibrary.h | 126 ++++++ Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h | 13 + Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 6 +- Analysis/Tasks/PWGDQ/filterPP.cxx | 359 ++++++++++++++++++ 9 files changed, 743 insertions(+), 24 deletions(-) create mode 100644 Analysis/Tasks/PWGDQ/CutsLibrary.h create mode 100644 Analysis/Tasks/PWGDQ/HistogramsLibrary.h create mode 100644 Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h create mode 100644 Analysis/Tasks/PWGDQ/filterPP.cxx diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index ebe8127dec4c7..10681af192486 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -59,6 +59,12 @@ class VarManager : public TObject Pair = BIT(11) }; + enum PairCandidateType { + kJpsiToEE, // J/psi -> e+ e- + kJpsiToMuMu, // J/psi -> mu+ mu- + kNMaxCandidateTypes + }; + public: enum Variables { kNothing = -1, @@ -209,13 +215,21 @@ class VarManager : public TObject } static void SetRunNumbers(int n, int* runs); + static int GetNRuns() + { + return fgRunMap.size(); + } + static TString GetRunStr() + { + return fgRunStr; + } template <uint32_t fillMap, typename T> static void FillEvent(T const& event, float* values = nullptr); template <uint32_t fillMap, typename T> static void FillTrack(T const& track, float* values = nullptr); template <typename T> - static void FillPair(T const& t1, T const& t2, float* values = nullptr); + static void FillPair(T const& t1, T const& t2, float* values = nullptr, PairCandidateType pairType = kJpsiToEE); template <typename T1, typename T2> static void FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values = nullptr, float hadronMass = 0.0f); @@ -231,6 +245,7 @@ class VarManager : public TObject static void SetVariableDependencies(); // toggle those variables on which other used variables might depend static std::map<int, int> fgRunMap; // map of runs to be used in histogram axes + static TString fgRunStr; // semi-colon separated list of runs, to be used for histogram axis labels static void FillEventDerived(float* values = nullptr); static void FillTrackDerived(float* values = nullptr); @@ -454,32 +469,21 @@ void VarManager::FillTrack(T const& track, float* values) } template <typename T> -void VarManager::FillPair(T const& t1, T const& t2, float* values) +void VarManager::FillPair(T const& t1, T const& t2, float* values, PairCandidateType pairType) { if (!values) { values = fgValues; } - float mass1 = fgkElectronMass; - float mass2 = fgkElectronMass; - - bool isMuon1 = t1.filteringFlags() & (1 << 0); - bool isMuon2 = t2.filteringFlags() & (1 << 0); - - if (isMuon1) { - mass1 = fgkMuonMass; - } else { - mass1 = fgkElectronMass; - } - - if (isMuon2) { - mass2 = fgkMuonMass; - } else { - mass2 = fgkElectronMass; + float m1 = fgkElectronMass; + float m2 = fgkElectronMass; + if (pairType == kJpsiToMuMu) { + m1 = fgkMuonMass; + m2 = fgkMuonMass; } - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), mass1); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), mass2); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), m2); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; values[kMass] = v12.M(); values[kPt] = v12.Pt(); diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 211e3a33fb6de..31e20f0e91104 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -19,6 +19,7 @@ TString VarManager::fgVariableUnits[VarManager::kNVars] = {""}; bool VarManager::fgUsedVars[VarManager::kNVars] = {kFALSE}; float VarManager::fgValues[VarManager::kNVars] = {0.0}; std::map<int, int> VarManager::fgRunMap; +TString VarManager::fgRunStr = ""; //__________________________________________________________________ VarManager::VarManager() : TObject() @@ -66,6 +67,7 @@ void VarManager::SetRunNumbers(int n, int* runs) // for (int i = 0; i < n; ++i) { fgRunMap[runs[i]] = i + 1; + fgRunStr += Form("%d;", runs[i]); } } diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 2bb1e7d4f617d..cd047877470c2 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -24,6 +24,14 @@ namespace o2::aod { + +namespace dqppfilter +{ +DECLARE_SOA_COLUMN(EventFilter, eventFilter, uint64_t); +} +// Table to be used for storing event-level decisions (DQ high level triggers) +DECLARE_SOA_TABLE(DQEventFilter, "AOD", "EVENTFILTER", dqppfilter::EventFilter); + namespace reducedevent { diff --git a/Analysis/Tasks/PWGDQ/CMakeLists.txt b/Analysis/Tasks/PWGDQ/CMakeLists.txt index 470f00fd682e6..fa46f30e0675c 100644 --- a/Analysis/Tasks/PWGDQ/CMakeLists.txt +++ b/Analysis/Tasks/PWGDQ/CMakeLists.txt @@ -1,3 +1,11 @@ +o2_add_library(PWGDQCore + SOURCES + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore) + +o2_target_root_dictionary(PWGDQCore + HEADERS CutsLibrary.h HistogramsLibrary.h + LINKDEF PWGDQCoreLinkDef.h) + o2_add_dpl_workflow(table-maker SOURCES tableMaker.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore @@ -22,7 +30,12 @@ o2_add_dpl_workflow(table-maker-pp SOURCES tableMaker_pp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore COMPONENT_NAME Analysis) - + +o2_add_dpl_workflow(dq-filter-pp + SOURCES filterPP.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(table-maker-muon-pp SOURCES tableMakerMuon_pp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore diff --git a/Analysis/Tasks/PWGDQ/CutsLibrary.h b/Analysis/Tasks/PWGDQ/CutsLibrary.h new file mode 100644 index 0000000000000..87423e236ffb9 --- /dev/null +++ b/Analysis/Tasks/PWGDQ/CutsLibrary.h @@ -0,0 +1,194 @@ +// 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 "Analysis/AnalysisCut.h" +#include "Analysis/AnalysisCompositeCut.h" +#include "Analysis/VarManager.h" + +namespace o2::aod +{ +namespace dqcuts +{ +AnalysisCompositeCut* GetCompositeCut(const char* cutName); +AnalysisCut* GetAnalysisCut(const char* cutName); +} // namespace dqcuts +} // namespace o2::aod + +AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) +{ + // + // define composie cuts, typically combinations of all the ingredients needed for a full cut + // + // TODO: Agree on some conventions for the naming + // Possibly think of possible customization of the predefined cuts + + AnalysisCompositeCut* cut = new AnalysisCompositeCut(cutName, cutName); + std::string nameStr = cutName; + + if (!nameStr.compare("jpsiKineAndQuality")) { + cut->AddCut(GetAnalysisCut("jpsiStandardKine")); + cut->AddCut(GetAnalysisCut("electronStandardQuality")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrack")); + return cut; + } + + if (!nameStr.compare("jpsiPID1")) { + cut->AddCut(GetAnalysisCut("jpsiStandardKine")); + cut->AddCut(GetAnalysisCut("electronStandardQuality")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrack")); + cut->AddCut(GetAnalysisCut("electronPID1")); + return cut; + } + + if (!nameStr.compare("jpsiPID2")) { + cut->AddCut(GetAnalysisCut("jpsiStandardKine")); + cut->AddCut(GetAnalysisCut("electronStandardQuality")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrack")); + cut->AddCut(GetAnalysisCut("electronPID2")); + return cut; + } + + if (!nameStr.compare("pairNoCut")) { + cut->AddCut(GetAnalysisCut("pairNoCut")); + return cut; + } + + if (!nameStr.compare("pairMassLow")) { + cut->AddCut(GetAnalysisCut("pairMassLow")); + return cut; + } + + if (!nameStr.compare("pairJpsi")) { + cut->AddCut(GetAnalysisCut("pairJpsi")); + return cut; + } + + if (!nameStr.compare("pairPsi2S")) { + cut->AddCut(GetAnalysisCut("pairPsi2S")); + return cut; + } + + if (!nameStr.compare("pairUpsilon")) { + cut->AddCut(GetAnalysisCut("pairUpsilon")); + return cut; + } + + if (!nameStr.compare("pairJpsiLowPt1")) { + cut->AddCut(GetAnalysisCut("pairJpsi")); + cut->AddCut(GetAnalysisCut("pairPtLow1")); + return cut; + } + + if (!nameStr.compare("pairJpsiLowPt2")) { + cut->AddCut(GetAnalysisCut("pairJpsi")); + cut->AddCut(GetAnalysisCut("pairPtLow2")); + return cut; + } + + delete cut; + return nullptr; +} + +AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) +{ + // + // define here cuts which are likely to be used often + // + AnalysisCut* cut = new AnalysisCut(cutName, cutName); + std::string nameStr = cutName; + + if (!nameStr.compare("eventStandard")) { + cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + cut->AddCut(VarManager::kIsINT7, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("int7vtxZ5")) { + cut->AddCut(VarManager::kVtxZ, -5.0, 5.0); + cut->AddCut(VarManager::kIsINT7, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("jpsiStandardKine")) { + cut->AddCut(VarManager::kPt, 1.0, 1000.0); + cut->AddCut(VarManager::kEta, -0.9, 0.9); + return cut; + } + + if (!nameStr.compare("electronStandardQuality")) { + cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); + cut->AddCut(VarManager::kIsITSrefit, 0.5, 1.5); + cut->AddCut(VarManager::kIsTPCrefit, 0.5, 1.5); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kITSchi2, 0.1, 36.0); + cut->AddCut(VarManager::kTPCncls, 100.0, 161.); + return cut; + } + + if (!nameStr.compare("standardPrimaryTrack")) { + cut->AddCut(VarManager::kTrackDCAxy, -1.0, 1.0); + cut->AddCut(VarManager::kTrackDCAz, -3.0, 3.0); + return cut; + } + + TF1* cutLow1 = new TF1("cutLow1", "pol1", 0., 10.); + cutLow1->SetParameters(130., -40.0); + if (!nameStr.compare("electronPID1")) { + cut->AddCut(VarManager::kTPCsignal, 70., 100.); + cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + return cut; + } + + if (!nameStr.compare("electronPID2")) { + cut->AddCut(VarManager::kTPCsignal, 73., 100.); + cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + return cut; + } + + if (!nameStr.compare("pairNoCut")) { + cut->AddCut(VarManager::kMass, 0.0, 1000.0); + return cut; + } + + if (!nameStr.compare("pairMassLow")) { + cut->AddCut(VarManager::kMass, 2.5, 1000.0); + return cut; + } + + if (!nameStr.compare("pairJpsi")) { + cut->AddCut(VarManager::kMass, 2.8, 3.3); + return cut; + } + + if (!nameStr.compare("pairPsi2S")) { + cut->AddCut(VarManager::kMass, 3.4, 3.9); + return cut; + } + + if (!nameStr.compare("pairUpsilon")) { + cut->AddCut(VarManager::kMass, 8.0, 11.0); + return cut; + } + + if (!nameStr.compare("pairPtLow1")) { + cut->AddCut(VarManager::kPt, 2.0, 1000.0); + return cut; + } + + if (!nameStr.compare("pairPtLow2")) { + cut->AddCut(VarManager::kPt, 5.0, 1000.0); + return cut; + } + + delete cut; + return nullptr; +} diff --git a/Analysis/Tasks/PWGDQ/HistogramsLibrary.h b/Analysis/Tasks/PWGDQ/HistogramsLibrary.h new file mode 100644 index 0000000000000..03c7ce56950e2 --- /dev/null +++ b/Analysis/Tasks/PWGDQ/HistogramsLibrary.h @@ -0,0 +1,126 @@ +// 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 "Analysis/HistogramManager.h" +#include "Analysis/VarManager.h" + +namespace o2::aod +{ +namespace dqhistograms +{ +void DefineHistograms(HistogramManager* hm, const char* histClass, const char* groupName, const char* subGroupName = ""); +} +} // namespace o2::aod + +void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* histClass, const char* groupName, const char* subGroupName) +{ + // + // Add a predefined group of histograms to the HistogramManager hm and histogram class histClass + // NOTE: The groupName and subGroupName arguments may contain several keywords, but the user should take care of + // ambiguities. TODO: fix it! + // NOTE: All of the histograms which match any of the group or subgroup names will be added to the same histogram class !! + // So one has to make sure not to mix e.g. event-wise with track-wise histograms + // NOTE: The subgroup name can be empty. In this case just a minimal set of histograms corresponding to the group name will be defined + // + TString groupStr = groupName; + groupStr.ToLower(); + TString subGroupStr = subGroupName; + subGroupStr.ToLower(); + if (groupStr.Contains("event")) { + hm->AddHistogram(histClass, "VtxZ", "Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ); + + if (subGroupStr.Contains("trigger")) { + hm->AddHistogram(histClass, "IsINT7", "Is INT7", false, 2, -0.5, 1.5, VarManager::kIsINT7); + hm->AddHistogram(histClass, "IsINT7inMUON", "INT7inMUON", false, 2, -0.5, 1.5, VarManager::kIsINT7inMUON); + hm->AddHistogram(histClass, "IsMuonSingleLowPt7", "Is MuonSingleLowPt7", false, 2, -0.5, 1.5, VarManager::kIsMuonSingleLowPt7); + hm->AddHistogram(histClass, "IsMuonUnlikeLowPt7", "Is MuonUnlikeLowPt7", false, 2, -0.5, 1.5, VarManager::kIsMuonUnlikeLowPt7); + hm->AddHistogram(histClass, "IsMuonLikeLowPt7", "Is MuonLikeLowPt7", false, 2, -0.5, 1.5, VarManager::kIsMuonLikeLowPt7); + } + if (subGroupStr.Contains("vtx")) { + hm->AddHistogram(histClass, "VtxX", "Vtx X", false, 100, -0.5, 0.5, VarManager::kVtxX); + hm->AddHistogram(histClass, "VtxY", "Vtx Y", false, 100, -0.5, 0.5, VarManager::kVtxY); + hm->AddHistogram(histClass, "VtxYVtxX", "Vtx Y vs Vtx X", false, 50, -0.5, 0.5, VarManager::kVtxX, 50, -0.5, 0.5, VarManager::kVtxY); + } + if (subGroupStr.Contains("vtxpp")) { + hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); + } + if (subGroupStr.Contains("vtxPbPb")) { + hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 20000.0, VarManager::kVtxNcontrib); + } + if (subGroupStr.Contains("cent")) { + hm->AddHistogram(histClass, "CentV0M", "CentV0M", false, 100, 0., 100., VarManager::kCentVZERO); + hm->AddHistogram(histClass, "CentV0M_vtxZ", "CentV0M vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ, 20, 0., 100., VarManager::kCentVZERO); + } + } + + if (groupStr.Contains("track")) { + hm->AddHistogram(histClass, "Pt", "p_{T} distribution", false, 200, 0.0, 20.0, VarManager::kPt); + hm->AddHistogram(histClass, "Eta", "#eta distribution", false, 500, -5.0, 5.0, VarManager::kEta); + hm->AddHistogram(histClass, "Phi", "#varphi distribution", false, 500, -6.3, 6.3, VarManager::kPhi); + + if (subGroupStr.Contains("kine")) { + hm->AddHistogram(histClass, "Phi_Eta", "#phi vs #eta distribution", false, 200, -5.0, 5.0, VarManager::kEta, 200, -6.3, 6.3, VarManager::kPhi); + hm->AddHistogram(histClass, "Eta_Pt", "", false, 20, -1.0, 1.0, VarManager::kEta, 100, 0.0, 20.0, VarManager::kPt); + hm->AddHistogram(histClass, "Px", "p_{x} distribution", false, 200, 0.0, 20.0, VarManager::kPx); + hm->AddHistogram(histClass, "Py", "p_{y} distribution", false, 200, 0.0, 20.0, VarManager::kPy); + hm->AddHistogram(histClass, "Pz", "p_{z} distribution", false, 200, 0.0, 20.0, VarManager::kPz); + } + if (subGroupStr.Contains("its")) { + hm->AddHistogram(histClass, "ITSncls", "Number of cluster in ITS", false, 8, -0.5, 7.5, VarManager::kITSncls); + hm->AddHistogram(histClass, "ITSchi2", "ITS chi2", false, 100, 0.0, 50.0, VarManager::kITSchi2); + hm->AddHistogram(histClass, "IsITSrefit", "", false, 2, -0.5, 1.5, VarManager::kIsITSrefit); + hm->AddHistogram(histClass, "IsSPDany", "", false, 2, -0.5, 1.5, VarManager::kIsSPDany); + } + if (subGroupStr.Contains("tpc")) { + hm->AddHistogram(histClass, "TPCncls", "Number of cluster in TPC", false, 160, -0.5, 159.5, VarManager::kTPCncls); + hm->AddHistogram(histClass, "TPCncls_Run", "Number of cluster in TPC", true, VarManager::GetNRuns(), 0.5, 0.5 + VarManager::GetNRuns(), VarManager::kRunId, + 10, -0.5, 159.5, VarManager::kTPCncls, 10, 0., 1., VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "IsTPCrefit", "", false, 2, -0.5, 1.5, VarManager::kIsTPCrefit); + hm->AddHistogram(histClass, "TPCchi2", "TPC chi2", false, 100, 0.0, 10.0, VarManager::kTPCchi2); + } + if (subGroupStr.Contains("tpcpid")) { + hm->AddHistogram(histClass, "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, 0.0, 200., VarManager::kTPCsignal); + } + if (subGroupStr.Contains("dca")) { + hm->AddHistogram(histClass, "DCAxy", "DCAxy", false, 100, -3.0, 3.0, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "DCAz", "DCAz", false, 100, -5.0, 5.0, VarManager::kTrackDCAz); + } + if (subGroupStr.Contains("muon")) { + hm->AddHistogram(histClass, "InvBendingMom", "", false, 100, 0.0, 1.0, VarManager::kMuonInvBendingMomentum); + hm->AddHistogram(histClass, "ThetaX", "", false, 100, -1.0, 1.0, VarManager::kMuonThetaX); + hm->AddHistogram(histClass, "ThetaY", "", false, 100, -2.0, 2.0, VarManager::kMuonThetaY); + hm->AddHistogram(histClass, "ZMu", "", false, 100, -30.0, 30.0, VarManager::kMuonZMu); + hm->AddHistogram(histClass, "BendingCoor", "", false, 100, 0.32, 0.35, VarManager::kMuonBendingCoor); + hm->AddHistogram(histClass, "NonBendingCoor", "", false, 100, 0.065, 0.07, VarManager::kMuonNonBendingCoor); + hm->AddHistogram(histClass, "Chi2", "", false, 100, 0.0, 200.0, VarManager::kMuonChi2); + hm->AddHistogram(histClass, "Chi2MatchTrigger", "", false, 100, 0.0, 20.0, VarManager::kMuonChi2MatchTrigger); + hm->AddHistogram(histClass, "RAtAbsorberEnd", "", false, 140, 10, 150, VarManager::kMuonRAtAbsorberEnd); + hm->AddHistogram(histClass, "p x dca", "", false, 700, 0.0, 700, VarManager::kMuonRAtAbsorberEnd); + } + } + + if (groupStr.Contains("pair")) { + hm->AddHistogram(histClass, "Mass", "", false, 125, 0.0, 5.0, VarManager::kMass); + hm->AddHistogram(histClass, "Mass_Pt", "", false, 125, 0.0, 5.0, VarManager::kMass, 100, 0.0, 20.0, VarManager::kPt); + hm->AddHistogram(histClass, "Eta_Pt", "", false, 125, -2.0, 2.0, VarManager::kEta, 100, 0.0, 20.0, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_VtxZ", "", true, 30, -15.0, 15.0, VarManager::kVtxZ, 100, 0.0, 20.0, VarManager::kMass); + } + + if (groupStr.Contains("pair-hadron-mass")) { + hm->AddHistogram(histClass, "Mass_Pt", "", false, 40, 0.0, 20.0, VarManager::kPairMass, 40, 0.0, 20.0, VarManager::kPairPt); + } + + if (groupStr.Contains("pair-hadron-correlation")) { + hm->AddHistogram(histClass, "DeltaEta_DeltaPhi", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhi); + hm->AddHistogram(histClass, "DeltaEta_DeltaPhiSym", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhiSym); + } +} diff --git a/Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h b/Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h new file mode 100644 index 0000000000000..d2769ae13ba53 --- /dev/null +++ b/Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h @@ -0,0 +1,13 @@ +// 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. + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx index b6892f396099c..b496f88e43cd9 100644 --- a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -265,14 +265,14 @@ struct DileptonMuMu { 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); + VarManager::FillPair(tpos, tneg, nullptr, VarManager::kJpsiToMuMu); if (!fDiMuonCut->IsSelected(VarManager::fgValues)) { return; } fHistMan->FillHistClass("PairsMuonULS", VarManager::fgValues); } for (auto tpos2 = tpos + 1; tpos2 != posMuons.end(); ++tpos2) { // ++ pairs - VarManager::FillPair(tpos, tpos2); + VarManager::FillPair(tpos, tpos2, nullptr, VarManager::kJpsiToMuMu); if (!fDiMuonCut->IsSelected(VarManager::fgValues)) { return; } @@ -281,7 +281,7 @@ struct DileptonMuMu { } for (auto tneg : negMuons) { // -- pairs for (auto tneg2 = tneg + 1; tneg2 != negMuons.end(); ++tneg2) { - VarManager::FillPair(tneg, tneg2); + VarManager::FillPair(tneg, tneg2, nullptr, VarManager::kJpsiToMuMu); if (!fDiMuonCut->IsSelected(VarManager::fgValues)) { return; } diff --git a/Analysis/Tasks/PWGDQ/filterPP.cxx b/Analysis/Tasks/PWGDQ/filterPP.cxx new file mode 100644 index 0000000000000..f03fde06261c3 --- /dev/null +++ b/Analysis/Tasks/PWGDQ/filterPP.cxx @@ -0,0 +1,359 @@ +// 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/Multiplicity.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" +#include "Analysis/TriggerAliases.h" +#include "Analysis/ReducedInfoTables.h" +#include "Analysis/VarManager.h" +#include "Analysis/HistogramManager.h" +#include "Analysis/AnalysisCut.h" +#include "Analysis/AnalysisCompositeCut.h" +#include "CutsLibrary.h" +#include "HistogramsLibrary.h" +#include "PID/PIDResponse.h" +#include "Analysis/TrackSelectionTables.h" +#include <TH1F.h> +#include <TH2I.h> +#include <TMath.h> +#include <THashList.h> +#include <TString.h> +#include <iostream> +#include <vector> +#include <memory> +#include <cstring> + +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 dqppfilter +{ +DECLARE_SOA_COLUMN(IsDQEventSelected, isDQEventSelected, int); +DECLARE_SOA_COLUMN(IsBarrelSelected, isBarrelSelected, uint8_t); +} // namespace dqppfilter + +DECLARE_SOA_TABLE(DQEventCuts, "AOD", "DQEVENTCUTS", dqppfilter::IsDQEventSelected); +DECLARE_SOA_TABLE(DQBarrelTrackCuts, "AOD", "DQBARRELCUTS", dqppfilter::IsBarrelSelected); +} // namespace o2::aod + +using MyEvents = soa::Join<aod::Collisions, aod::EvSels>; +using MyEventsSelected = soa::Join<aod::Collisions, aod::EvSels, aod::DQEventCuts>; +using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::TracksExtended, aod::TrackSelection, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta>; +using MyBarrelTracksSelected = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::TracksExtended, aod::TrackSelection, aod::pidRespTPC, aod::pidRespTOF, aod::pidRespTOFbeta, aod::DQBarrelTrackCuts>; + +constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; +constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; + +void DefineHistograms(HistogramManager* histMan, TString histClasses); + +struct EventSelectionTask { + Produces<aod::DQEventCuts> eventSel; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; + AnalysisCompositeCut fEventCut{true}; + + float* fValues; + + Configurable<std::string> fConfigCuts{"cfgEventCuts", "eventStandard", "Comma separated list of event cuts; multiple cuts are applied with a logical AND"}; + + void init(o2::framework::InitContext&) + { + fValues = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + + DefineCuts(); + } + + void DefineCuts() + { + // default cut is "eventStandard" (kINT7 and vtxZ selection) + TString cutNamesStr = fConfigCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr<TObjArray> objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fEventCut.AddCut(dqcuts::GetAnalysisCut(objArray->At(icut)->GetName())); + } + } + + // NOTE: Additional cuts to those specified via the Configurable may still be added + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvents::iterator const& event, aod::BCs const& bcs) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNEventWiseVariables, fValues); + + VarManager::FillEvent<gkEventFillMap>(event, fValues); + fHistMan->FillHistClass("Event_BeforeCuts", fValues); // automatically fill all the histograms in the class Event + if (fEventCut.IsSelected(fValues)) { + fHistMan->FillHistClass("Event_AfterCuts", fValues); + eventSel(1); + } else { + eventSel(0); + } + } +}; + +struct BarrelTrackSelectionTask { + Produces<aod::DQBarrelTrackCuts> trackSel; + OutputObj<THashList> fOutputList{"output"}; + HistogramManager* fHistMan; + std::vector<AnalysisCompositeCut> fTrackCuts; + + float* fValues; // array to be used by the VarManager + + Configurable<std::string> fConfigCuts{"cfgBarrelTrackCuts", "jpsiPID1", "Comma separated list of barrel track cuts"}; + + void init(o2::framework::InitContext&) + { + DefineCuts(); + + fValues = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + TString cutNames = "TrackBarrel_BeforeCuts;"; + for (int i = 0; i < fTrackCuts.size(); i++) { + cutNames += Form("TrackBarrel_%s;", fTrackCuts[i].GetName()); + } + + DefineHistograms(fHistMan, cutNames.Data()); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + void DefineCuts() + { + // available cuts: jpsiKineAndQuality, jpsiPID1, jpsiPID2 + TString cutNamesStr = fConfigCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr<TObjArray> objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fTrackCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + + // NOTE: Additional cuts to those specified via the Configurable may still be added + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvents::iterator const& event, MyBarrelTracks const& tracks, aod::BCs const& bcs) + { + uint8_t filterMap = uint8_t(0); + trackSel.reserve(tracks.size()); + + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables, fValues); + // fill event information which might be needed in histograms that combine track and event properties + VarManager::FillEvent<gkEventFillMap>(event, fValues); + + for (auto& track : tracks) { + filterMap = uint8_t(0); + // TODO: if a condition on the event selection is applied, the histogram output is missing + VarManager::FillTrack<gkTrackFillMap>(track, fValues); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + int i = 0; + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { + if ((*cut).IsSelected(fValues)) { + filterMap |= (uint8_t(1) << i); + fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut).GetName()), fValues); + } + } + trackSel(filterMap); + } + } +}; + +struct FilterPPTask { + Produces<aod::DQEventFilter> eventFilter; + OutputObj<THashList> fOutputList{"output"}; + OutputObj<TH2I> fStats{"stats"}; + HistogramManager* fHistMan; + std::vector<AnalysisCompositeCut> fPairCuts; + + float* fValues; + + Partition<MyBarrelTracksSelected> posTracks = aod::track::signed1Pt > 0.0f && aod::dqppfilter::isBarrelSelected > uint8_t(0); + Partition<MyBarrelTracksSelected> negTracks = aod::track::signed1Pt < 0.0f && aod::dqppfilter::isBarrelSelected > uint8_t(0); + + Configurable<std::string> fConfigTrackCuts{"cfgBarrelTrackCuts", "jpsiPID1", "Comma separated list of barrel track cuts"}; + Configurable<std::string> fConfigPairCuts{"cfgPairCuts", "pairMassLow", "Comma separated list of pair cuts"}; + + int fNTrackCuts; + int fNPairCuts; + TObjArray* fTrkCutsNameArray; + + void DefineCuts() + { + // available pair cuts in CutsLibrary: pairNoCut,pairMassLow,pairJpsi,pairPsi2S,pairUpsilon,pairJpsiPtLow1, pairJpsiPtLow2 + TString pairCutNamesStr = fConfigPairCuts.value; + std::unique_ptr<TObjArray> objArray(pairCutNamesStr.Tokenize(",")); + fNPairCuts = objArray->GetEntries(); + if (fNPairCuts) { + for (int icut = 0; icut < fNPairCuts; ++icut) { + fPairCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + + // NOTE: Additional cuts to those specified via the Configurable may still be added + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void init(o2::framework::InitContext&) + { + DefineCuts(); + + fValues = new float[VarManager::kNVars]; + + // initialize the variable manager + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // configure histograms + TString trackCutNamesStr = fConfigTrackCuts.value; + fTrkCutsNameArray = trackCutNamesStr.Tokenize(","); + fNTrackCuts = fTrkCutsNameArray->GetEntries(); + TString histNames = ""; + for (int i = 0; i < fNTrackCuts; i++) { + histNames += Form("PairsBarrelPM_%s;", fTrkCutsNameArray->At(i)->GetName()); + } + DefineHistograms(fHistMan, histNames.Data()); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + + // configure the stats histogram + fStats.setObject(new TH2I("stats", "stats", fNPairCuts, -0.5, -0.5 + fNPairCuts, fNTrackCuts, -0.5, -0.5 + fNTrackCuts)); + for (int i = 0; i < fNPairCuts; ++i) { + fStats->GetXaxis()->SetBinLabel(i + 1, fPairCuts[i].GetName()); + } + for (int i = 0; i < fNTrackCuts; ++i) { + fStats->GetYaxis()->SetBinLabel(i + 1, fTrkCutsNameArray->At(i)->GetName()); + } + } + + void process(MyEventsSelected::iterator const& event, MyBarrelTracksSelected const& tracks, aod::BCs const& bcs) + { + uint64_t filter = 0; + + if (event.isDQEventSelected() == 1) { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars, fValues); + VarManager::FillEvent<gkEventFillMap>(event, fValues); + + uint8_t* pairsCount = new uint8_t[fNPairCuts * fNTrackCuts]; + for (int i = 0; i < fNPairCuts * fNTrackCuts; i++) { + pairsCount[i] = 0; + } + + uint8_t cutFilter = 0; + for (auto tpos : posTracks) { + for (auto tneg : negTracks) { // +- pairs + cutFilter = tpos.isBarrelSelected() & tneg.isBarrelSelected(); + if (!cutFilter) { // the tracks must have at least one filter bit in common to continue + continue; + } + VarManager::FillPair(tpos, tneg, fValues); // compute pair quantities + for (int i = 0; i < fNTrackCuts; ++i) { + if (!(cutFilter & (uint8_t(1) << i))) { + continue; + } + fHistMan->FillHistClass(Form("PairsBarrelPM_%s", fTrkCutsNameArray->At(i)->GetName()), fValues); + int j = 0; + for (auto cut = fPairCuts.begin(); cut != fPairCuts.end(); cut++, j++) { + if ((*cut).IsSelected(fValues)) { + pairsCount[j + i * fNPairCuts] += 1; + } + } + } + } + } + + for (int i = 0; i < fNTrackCuts; i++) { + for (int j = 0; j < fNPairCuts; j++) { + if (pairsCount[j + i * fNPairCuts] > 0) { + filter |= (uint64_t(1) << (j + i * fNPairCuts)); + fStats->Fill(j, i); + } + } + } + delete[] pairsCount; + } + eventFilter(filter); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<EventSelectionTask>("dq-event-selection"), + adaptAnalysisTask<BarrelTrackSelectionTask>("dq-barrel-track-selection"), + adaptAnalysisTask<FilterPPTask>("dq-ppFilter")}; +} + +void DefineHistograms(HistogramManager* 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 ";" + // NOTE: Additional histograms to those predefined in the library can be added here !! + const int kNRuns = 25; + int runs[kNRuns] = { + 285009, 285011, 285012, 285013, 285014, 285015, 285064, 285065, 285066, 285106, + 285108, 285125, 285127, 285165, 285200, 285202, 285203, 285222, 285224, 285327, + 285328, 285347, 285364, 285365, 285396}; + VarManager::SetRunNumbers(kNRuns, runs); + + std::unique_ptr<TObjArray> objArray(histClasses.Tokenize(";")); + for (Int_t iclass = 0; iclass < objArray->GetEntries(); ++iclass) { + TString classStr = objArray->At(iclass)->GetName(); + histMan->AddHistClass(classStr.Data()); + + if (classStr.Contains("Event")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "event", "trigger,vtxPbPb"); + } + + if (classStr.Contains("Track")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "its,tpcpid,dca"); + } + + if (classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair"); + } + } +} From 4fd3147c6202f5221a2119c5be4f90b9673467fe Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 2 Dec 2020 08:39:31 +0100 Subject: [PATCH 1484/1751] DPL Analysis: easy way to filter a table on the fly (#4929) --- Analysis/Tutorials/src/associatedExample.cxx | 34 +++++++++++++++++-- .../Tutorials/src/histogramsFullTracks.cxx | 2 +- Framework/Core/include/Framework/ASoA.h | 22 ++++++++---- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/Analysis/Tutorials/src/associatedExample.cxx b/Analysis/Tutorials/src/associatedExample.cxx index 6ac8e1225467c..19c171fb6fba7 100644 --- a/Analysis/Tutorials/src/associatedExample.cxx +++ b/Analysis/Tutorials/src/associatedExample.cxx @@ -75,7 +75,7 @@ struct BTask { struct TTask { using myCol = soa::Join<aod::Collisions, aod::CollisionsExtra>; expressions::Filter multfilter = aod::collision::mult > 10; - void process(soa::Filtered<soa::Join<aod::Collisions, aod::CollisionsExtra>>::iterator const& col, aod::Tracks const& tracks) + void process(soa::Filtered<myCol>::iterator const& col, aod::Tracks const& tracks) { LOGF(INFO, "[direct] ID: %d; %d == %d", col.globalIndex(), col.mult(), tracks.size()); if (tracks.size() > 0) { @@ -85,11 +85,41 @@ struct TTask { } }; +struct ZTask { + using myCol = soa::Join<aod::Collisions, aod::CollisionsExtra>; + + void process(myCol const& collisions, aod::Tracks const& tracks) + { + auto multbin0_10 = collisions.select(aod::collision::mult >= 0 && aod::collision::mult < 10); + auto multbin10_30 = collisions.select(aod::collision::mult >= 10 && aod::collision::mult < 30); + auto multbin30_100 = collisions.select(aod::collision::mult >= 30 && aod::collision::mult < 100); + + LOGF(INFO, "Bin 0-10"); + for (auto& col : multbin0_10) { + auto groupedTracks = tracks.select(aod::track::collisionId == col.globalIndex()); + LOGF(INFO, "Collision %d; Ntrk = %d vs %d", col.globalIndex(), col.mult(), groupedTracks.size()); + } + + LOGF(INFO, "Bin 10-30"); + for (auto& col : multbin10_30) { + auto groupedTracks = tracks.select(aod::track::collisionId == col.globalIndex()); + LOGF(INFO, "Collision %d; Ntrk = %d vs %d", col.globalIndex(), col.mult(), groupedTracks.size()); + } + + LOGF(INFO, "Bin 30-100"); + for (auto& col : multbin30_100) { + auto groupedTracks = tracks.select(aod::track::collisionId == col.globalIndex()); + LOGF(INFO, "Collision %d; Ntrk = %d vs %d", col.globalIndex(), col.mult(), groupedTracks.size()); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ adaptAnalysisTask<ATask>("produce-etaphi"), adaptAnalysisTask<BTask>("consume-etaphi"), adaptAnalysisTask<MTask>("produce-mult"), - adaptAnalysisTask<TTask>("consume-mult")}; + adaptAnalysisTask<TTask>("consume-mult"), + adaptAnalysisTask<ZTask>("partition-mult")}; } diff --git a/Analysis/Tutorials/src/histogramsFullTracks.cxx b/Analysis/Tutorials/src/histogramsFullTracks.cxx index 3dab7398facdf..f264ce8cf7361 100644 --- a/Analysis/Tutorials/src/histogramsFullTracks.cxx +++ b/Analysis/Tutorials/src/histogramsFullTracks.cxx @@ -19,7 +19,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct ATask { - OutputObj<TH2F> etaClsH{TH2F("eta_vs_cls", "eta_vs_cls", 102, -2.01, 2.01, 160, -0.5, 159.5)}; + OutputObj<TH2F> etaClsH{TH2F("eta_vs_cls", "#eta vs N_{cls}", 102, -2.01, 2.01, 160, -0.5, 159.5)}; void process(aod::FullTracks const& tracks) { diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index a31588e003489..3a9e89267416a 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -808,6 +808,17 @@ static constexpr auto extractBindings(framework::pack<Is...>) return framework::pack<typename Is::binding_t...>{}; } +template <typename T> +class Filtered; + +template <typename T> +auto select(T const& t, framework::expressions::Filter&& f) +{ + return Filtered<T>({t.asArrowTable()}, framework::expressions::createExpressionTree( + framework::expressions::createOperations(f), + t.asArrowTable()->schema())); +} + /// A Table class which observes an arrow::Table and provides /// It is templated on a set of Column / DynamicColumn types. template <typename... C> @@ -1000,6 +1011,11 @@ class Table mBegin.bindExternalIndices(current...); } + auto select(framework::expressions::Filter&& f) const + { + return o2::soa::select(*this, std::forward<framework::expressions::Filter>(f)); + } + private: template <typename T> arrow::ChunkedArray* lookupColumn() @@ -1762,12 +1778,6 @@ class Filtered<Filtered<T>> : public FilteredPolicy<typename T::table_t> template <typename T> using is_soa_filtered_t = typename framework::is_base_of_template<soa::FilteredPolicy, T>; -template <typename T> -auto filter(T&& t, framework::expressions::Filter const& expr) -{ - return Filtered<T>(t.asArrowTable(), expr); -} - /// Template for building an index table to access matching rows from non- /// joinable, but compatible tables, e.g. Collisions and ZDCs. /// First argument is the key table (BCs for the Collisions+ZDCs case), the rest From a46f769fde248d60127db6302ba343c04726cf34 Mon Sep 17 00:00:00 2001 From: Nazar Burmasov <nazar.burmasov@cern.ch> Date: Wed, 2 Dec 2020 10:41:29 +0300 Subject: [PATCH 1485/1751] Adding McParticles and McTrackLabels to the converter (#4933) * Filling MC particles and MC track labels into tables * Small fix for tpcChi2NCl and several fixes for McTrackLabels * Accounting for different sources in MC + some fixes --- .../AODProducerWorkflowSpec.h | 18 ++ Detectors/AOD/src/AODProducerWorkflow.cxx | 2 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 186 ++++++++++++++++-- 3 files changed, 184 insertions(+), 22 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 90254eeb2b660..dea495c5af03a 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -73,6 +73,24 @@ using TracksTable = o2::soa::Table<o2::aod::track::CollisionId, o2::aod::track::TrackEtaEMCAL, o2::aod::track::TrackPhiEMCAL>; +using MCParticlesTable = o2::soa::Table<o2::aod::mcparticle::McCollisionId, + o2::aod::mcparticle::PdgCode, + o2::aod::mcparticle::StatusCode, + o2::aod::mcparticle::Flags, + o2::aod::mcparticle::Mother0, + o2::aod::mcparticle::Mother1, + o2::aod::mcparticle::Daughter0, + o2::aod::mcparticle::Daughter1, + o2::aod::mcparticle::Weight, + o2::aod::mcparticle::Px, + o2::aod::mcparticle::Py, + o2::aod::mcparticle::Pz, + o2::aod::mcparticle::E, + o2::aod::mcparticle::Vx, + o2::aod::mcparticle::Vy, + o2::aod::mcparticle::Vz, + o2::aod::mcparticle::Vt>; + class AODProducerWorkflowDPL : public Task { public: diff --git a/Detectors/AOD/src/AODProducerWorkflow.cxx b/Detectors/AOD/src/AODProducerWorkflow.cxx index 51a46f46f5cd0..5925e6362234c 100644 --- a/Detectors/AOD/src/AODProducerWorkflow.cxx +++ b/Detectors/AOD/src/AODProducerWorkflow.cxx @@ -35,7 +35,7 @@ framework::WorkflowSpec getAODProducerWorkflow() { // TODO: // switch to configurable parameters (?) - bool useMC = false; + bool useMC = true; // FIXME: // switch (?) from o2::ft0::getReconstructionSpec to RecPointReader diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 1b8075fb7a72a..8f8c6c3048806 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -31,6 +31,7 @@ #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "SimulationDataFormat/DigitizationContext.h" +#include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCEventHeader.h" #include "SimulationDataFormat/MCTruthContainer.h" @@ -158,9 +159,7 @@ void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vect itsClusterMap = itsTrack.getPattern(); }, [&](o2::tpc::TrackTPC tpcTrack) { - tpcChi2NCl = tpcTrack.getChi2(); - // FIXME: - // what values to fill here? + tpcChi2NCl = tpcTrack.getNClusters() ? tpcTrack.getChi2() / tpcTrack.getNClusters() : 0; tpcSignal = tpcTrack.getdEdx().dEdxTotTPC; tpcNClsFindable = tpcTrack.getNClusters(); }, @@ -243,6 +242,10 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto tracksITS = pc.inputs().get<gsl::span<o2::its::TrackITS>>("trackITS"); auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("tracksITSTPC"); auto tracksTPC = pc.inputs().get<gsl::span<o2::tpc::TrackTPC>>("trackTPC"); + auto tracksTPCMCTruth = pc.inputs().get<gsl::span<o2::MCCompLabel>>("trackTPCMCTruth"); + auto tracksITSMCTruth = pc.inputs().get<gsl::span<o2::MCCompLabel>>("trackITSMCTruth"); + auto tracksITSTPC_ITSMC = pc.inputs().get<gsl::span<o2::MCCompLabel>>("tracksITSTPC_ITSMC"); + auto tracksITSTPC_TPCMC = pc.inputs().get<gsl::span<o2::MCCompLabel>>("tracksITSTPC_TPCMC"); LOG(DEBUG) << "FOUND " << tracksTPC.size() << " TPC tracks"; LOG(DEBUG) << "FOUND " << tracksITS.size() << " ITS tracks"; @@ -253,6 +256,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto& ft0Builder = pc.outputs().make<TableBuilder>(Output{"AOD", "FT0"}); auto& mcCollisionsBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "MCCOLLISION"}); auto& tracksBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "TRACK"}); + auto& mcParticlesBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "MCPARTICLE"}); + auto& mcTrackLabelBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "MCTRACKLABEL"}); auto& timeFrameNumberBuilder = pc.outputs().make<uint64_t>(Output{"TFN", "TFNumber"}); auto& fv0aBuilder = pc.outputs().make<TableBuilder>(Output{"AOD", "FV0A"}); @@ -265,6 +270,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto ft0Cursor = ft0Builder.cursor<o2::aod::FT0s>(); auto mcCollisionsCursor = mcCollisionsBuilder.cursor<o2::aod::McCollisions>(); auto tracksCursor = tracksBuilder.cursor<o2::aodproducer::TracksTable>(); + auto mcParticlesCursor = mcParticlesBuilder.cursor<o2::aodproducer::MCParticlesTable>(); + auto mcTrackLabelCursor = mcTrackLabelBuilder.cursor<o2::aod::McTrackLabels>(); auto fv0aCursor = fv0aBuilder.cursor<o2::aod::FV0As>(); auto fv0cCursor = fv0cBuilder.cursor<o2::aod::FV0Cs>(); @@ -346,31 +353,83 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) 0.f); // TODO: - // figure out generatorID and collision weight - int index = 0; - int generatorID = 0; + // figure out collision weight float mcColWeight = 1.; // filling mcCollison table + int index = 0; for (auto& rec : mcRecords) { auto time = rec.getTimeNS(); - auto& colParts = mcParts[index]; - auto eventID = colParts[0].entryID; - auto sourceID = colParts[0].sourceID; - auto& header = mcReader.getMCEventHeader(sourceID, eventID); uint64_t globalBC = rec.bc + rec.orbit * o2::constants::lhc::LHCMaxBunches; - mcCollisionsCursor(0, - mGlobBC2BCID.at(globalBC), - generatorID, - header.GetX(), - header.GetY(), - header.GetZ(), - time, - mcColWeight, - header.GetB()); + auto& colParts = mcParts[index]; + for (int i = 0; i < colParts.size(); i++) { + auto eventID = colParts[i].entryID; + auto sourceID = colParts[i].sourceID; + // FIXME: + // use generators' names for generatorIDs (?) + short generatorID = sourceID; + auto& header = mcReader.getMCEventHeader(sourceID, eventID); + mcCollisionsCursor(0, + mGlobBC2BCID.at(globalBC), + generatorID, + header.GetX(), + header.GetY(), + header.GetZ(), + time, + mcColWeight, + header.GetB()); + } index++; } + // tracks --> mc particles + // std::map<<sourceID, eventID, trackID>, McParticles::Index> + std::map<std::tuple<uint32_t, uint32_t, uint32_t>, uint32_t> mIDsToIndex; + + // filling mcparticle table + uint32_t mcParticlesIndex = 0; + for (int sourceID = 0; sourceID < mcReader.getNSources(); sourceID++) { + for (int mcEventID = 0; mcEventID < mcReader.getNEvents(sourceID); mcEventID++) { + std::vector<MCTrack> const& mcParticles = mcReader.getTracks(sourceID, mcEventID); + + // TODO + // *fill dummy columns + // *mother/daughter IDs need to be recalculated before storing into table + int statusCode = 0; + uint8_t flags = 0; + float weight = 0.f; + int mother0 = 0; + int mother1 = 0; + int daughter0 = 0; + int daughter1 = 0; + + int mcTrackID = 0; + for (auto& mcParticle : mcParticles) { + mcParticlesCursor(0, + mcEventID, + mcParticle.GetPdgCode(), + statusCode, + flags, + mother0, + mother1, + daughter0, + daughter1, + weight, + (float)mcParticle.Px(), + (float)mcParticle.Py(), + (float)mcParticle.Pz(), + (float)mcParticle.GetEnergy(), + (float)mcParticle.Vx(), + (float)mcParticle.Vy(), + (float)mcParticle.Vz(), + (float)mcParticle.T()); + mIDsToIndex[std::make_tuple(sourceID, mcEventID, mcTrackID)] = mcParticlesIndex; + mcTrackID++; + mcParticlesIndex++; + } + } + } + // vector of FT0 amplitudes std::vector<float> vAmplitudes(208, 0.); // filling FT0 table @@ -411,7 +470,9 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // mus to ns // FIXME: // should use IRMin and IRMax for globalBC calculation - uint64_t globalBC = tsTimeStamp / o2::constants::lhc::LHCBunchSpacingNS; + uint64_t globalBC = std::round(tsTimeStamp / o2::constants::lhc::LHCBunchSpacingNS); + + LOG(DEBUG) << globalBC << " " << tsTimeStamp; if (collisionID == 0) { firstVtxGlBC = globalBC; @@ -461,15 +522,92 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) collisionID++; } - // filling tracks tables + // filling tracks tables and track label table + + // labelMask (temporary) usage: + // bit 13 -- ITS and TPC labels are not equal + // bit 14 -- isNoise() == true + // bit 15 -- isFake() == true + if (mFillTracksITS) { fillTracksTable(tracksITS, vCollRefsITS, tracksCursor, o2::vertexing::GIndex::Source::ITS); // fTrackType = 1 + for (auto& mcTruthITS : tracksITSMCTruth) { + uint32_t labelID = std::numeric_limits<uint32_t>::max(); + // TODO: + // fill label mask + uint16_t labelMask = 0; + int nEventsITS = mcReader.getNEvents(mcTruthITS.getSourceID()); + if (mcTruthITS.getEventID() < mcReader.getNEvents(mcTruthITS.getSourceID())) { + labelID = mIDsToIndex.at(std::make_tuple(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); + } + if (mcTruthITS.isFake()) { + labelMask |= (0x1 << 15); + } + if (mcTruthITS.isNoise()) { + labelMask |= (0x1 << 14); + } + mcTrackLabelCursor(0, + labelID, + labelMask); + } } + if (mFillTracksTPC) { fillTracksTable(tracksTPC, vCollRefsTPC, tracksCursor, o2::vertexing::GIndex::Source::TPC); // fTrackType = 2 + for (auto& mcTruthTPC : tracksTPCMCTruth) { + uint32_t labelID = std::numeric_limits<uint32_t>::max(); + // TODO: + // fill label mask + uint16_t labelMask = 0; + int nEventsTPC = mcReader.getNEvents(mcTruthTPC.getSourceID()); + if (mcTruthTPC.getEventID() < nEventsTPC) { + labelID = mIDsToIndex.at(std::make_tuple(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); + } + if (mcTruthTPC.isFake()) { + labelMask |= (0x1 << 15); + } + if (mcTruthTPC.isNoise()) { + labelMask |= (0x1 << 14); + } + mcTrackLabelCursor(0, + labelID, + labelMask); + } } + if (mFillTracksITSTPC) { fillTracksTable(tracksITSTPC, vCollRefsTPCITS, tracksCursor, o2::vertexing::GIndex::Source::TPCITS); // fTrackType = 0 + for (int i = 0; i < tracksITSTPC.size(); i++) { + auto& mcTruthITS = tracksITSTPC_ITSMC[i]; + auto& mcTruthTPC = tracksITSTPC_TPCMC[i]; + uint32_t labelID = std::numeric_limits<uint32_t>::max(); + uint32_t labelITS = std::numeric_limits<uint32_t>::max(); + uint32_t labelTPC = std::numeric_limits<uint32_t>::max(); + // TODO: + // fill label mask + // currently using label mask to indicate labelITS != labelTPC + uint16_t labelMask = 0; + int nEventsITS = mcReader.getNEvents(mcTruthITS.getSourceID()); + int nEventsTPC = mcReader.getNEvents(mcTruthTPC.getSourceID()); + if (mcTruthITS.getEventID() < nEventsITS && mcTruthTPC.getEventID() < nEventsTPC) { + labelITS = mIDsToIndex.at(std::make_tuple(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); + labelTPC = mIDsToIndex.at(std::make_tuple(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); + labelID = labelITS; + } + if (mcTruthITS.isFake() || mcTruthTPC.isFake()) { + labelMask |= (0x1 << 15); + } + if (mcTruthITS.isNoise() || mcTruthTPC.isNoise()) { + labelMask |= (0x1 << 14); + } + if (labelITS != labelTPC) { + LOG(DEBUG) << "ITS-TPC MCTruth: labelIDs do not match at " << i; + labelMask |= (0x1 << 13); + } + mcTrackLabelCursor(0, + labelID, + labelMask); + } } timeFrameNumberBuilder = getTFNumber(firstVtxGlBC, runNumber); @@ -496,12 +634,18 @@ DataProcessorSpec getAODProducerWorkflowSpec() inputs.emplace_back("trackITS", "ITS", "TRACKS", 0, Lifetime::Timeframe); inputs.emplace_back("tracksITSTPC", "GLO", "TPCITS", 0, Lifetime::Timeframe); inputs.emplace_back("trackTPC", "TPC", "TRACKS", 0, Lifetime::Timeframe); + inputs.emplace_back("trackTPCMCTruth", "TPC", "TRACKSMCLBL", 0, Lifetime::Timeframe); + inputs.emplace_back("trackITSMCTruth", "ITS", "TRACKSMCTR", 0, Lifetime::Timeframe); + inputs.emplace_back("tracksITSTPC_ITSMC", "GLO", "TPCITS_ITSMC", 0, Lifetime::Timeframe); + inputs.emplace_back("tracksITSTPC_TPCMC", "GLO", "TPCITS_TPCMC", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2bc"}, "AOD", "BC", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2collision"}, "AOD", "COLLISION", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2ft0"}, "AOD", "FT0", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2mccollision"}, "AOD", "MCCOLLISION", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2track"}, "AOD", "TRACK", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2mcparticle"}, "AOD", "MCPARTICLE", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2mctracklabel"}, "AOD", "MCTRACKLABEL", 0, Lifetime::Timeframe); outputs.emplace_back(OutputSpec{"TFN", "TFNumber"}); // TODO: From 13a4a37282c5b295836bd49de89b6577921622bc Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Wed, 2 Dec 2020 08:44:04 +0100 Subject: [PATCH 1486/1751] DPL Analysis: ability to Join with index tables (#4940) --- Analysis/Tutorials/src/ZDCVZeroIteration.cxx | 32 +++++++++++--------- Framework/Core/include/Framework/ASoA.h | 27 ++++++++++++++--- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx index fc89aca047b3c..c786524dcd142 100644 --- a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx +++ b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx @@ -64,20 +64,22 @@ struct IterateV0Tracks { }; // IterateV0Tracks with join. Desired version for good readability -// using CollisionMatchedRun2Sparse = soa::Join<aod::Run2MatchedSparse, aod::Collisions>::iterator; -// struct IterateV0Tracks2 { -// void process(CollisionMatchedRun2Sparse const& m, aod::FV0As const&, aod::Tracks const& tracks) -// { -// LOGF(INFO, "Vertex = %f. %d tracks", m.posZ(), tracks.size()); -// LOGF(INFO, "Vertex = %f. %d tracks", m.collision().posZ(), tracks.size()); -// if (m.has_fv0a()) { -// auto v0a = m.fv0a(); -// LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); -// } else { -// LOGF(INFO, "No V0A info"); -// } -// } -// }; +// NOTE: index table needs to be always last argument +// NOTE: subsribing to Collisions separately will lead to a circular dependency +// due to forwarding +using CollisionMatchedRun2Sparse = soa::Join<aod::Collisions, aod::Run2MatchedSparse>::iterator; +struct IterateV0Tracks2 { + void process(CollisionMatchedRun2Sparse const& m, aod::FV0As const&, aod::Tracks const& tracks) + { + LOGF(INFO, "Vertex = %f. %d tracks", m.posZ(), tracks.size()); + if (m.has_fv0a()) { + auto v0a = m.fv0a(); + LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); + } else { + LOGF(INFO, "No V0A info"); + } + } +}; // This example accesses V0 and ZDC information struct IterateV0ZDC { @@ -104,7 +106,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) adaptAnalysisTask<IterateV0>("iterate-v0"), adaptAnalysisTask<IterateV0Exclusive>("iterate-v0-exclusive"), adaptAnalysisTask<IterateV0Tracks>("iterate-v0-tracks"), - // adaptAnalysisTask<IterateV0Tracks2>("iterate-v0-tracks2"), + adaptAnalysisTask<IterateV0Tracks2>("iterate-v0-tracks2"), adaptAnalysisTask<IterateV0ZDC>("iterate-v0-zdc"), }; } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 3a9e89267416a..208a4668784ac 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -74,6 +74,12 @@ constexpr bool is_type_spawnable_v = false; template <typename T> constexpr bool is_type_spawnable_v<T, std::void_t<decltype(sizeof(typename T::spawnable_t))>> = true; +template <typename T, typename = void> +constexpr bool is_index_table_v = false; + +template <typename T> +constexpr bool is_index_table_v<T, std::void_t<decltype(sizeof(typename T::indexing_t))>> = true; + template <typename T, typename TLambda> void call_if_has_originals(TLambda&& lambda) { @@ -100,7 +106,7 @@ constexpr auto make_originals_from_type() } else if constexpr (is_type_with_originals_v<typename decayed::table_t>) { return typename decayed::table_t::originals{}; } else if constexpr (is_type_with_parent_v<decayed>) { - return make_originals_from_type(decayed::parent_t); + return make_originals_from_type<typename decayed::parent_t>(); } else { return framework::pack<decayed>{}; } @@ -1022,11 +1028,11 @@ class Table { if constexpr (T::persistent::value) { auto label = T::columnLabel(); - auto index = mTable->schema()->GetFieldIndex(label); - if (index == -1) { + auto index = mTable->schema()->GetAllFieldIndices(label); + if (index.empty() == true) { throw runtime_error_f("Unable to find column with label %s", label); } - return mTable->column(index).get(); + return mTable->column(index[0]).get(); } else { return nullptr; } @@ -1070,12 +1076,23 @@ class TableMetadata static std::string sourceSpec() { return fmt::format("{}/{}/{}", INHERIT::mLabel, INHERIT::mOrigin, INHERIT::mDescription); }; }; +/// Helper template to define universal join +template <typename Key, typename H, typename... Ts> +struct IndexTable; + template <typename... C1, typename... C2> constexpr auto joinTables(o2::soa::Table<C1...> const& t1, o2::soa::Table<C2...> const& t2) { return o2::soa::Table<C1..., C2...>(ArrowHelpers::joinTables({t1.asArrowTable(), t2.asArrowTable()})); } +// special case for appending an index +template <typename... C1, typename Key, typename H, typename... C2> +constexpr auto joinTables(o2::soa::Table<C1...> const& t1, o2::soa::IndexTable<Key, H, C2...> const& t2) +{ + return joinTables(t1, o2::soa::Table<H, C2...>{t2.asArrowTable()}); +} + template <typename T, typename... C, typename... O> constexpr auto joinLeft(T const& t1, o2::soa::Table<C...> const& t2, framework::pack<O...>) { @@ -1786,6 +1803,8 @@ using is_soa_filtered_t = typename framework::is_base_of_template<soa::FilteredP template <typename Key, typename H, typename... Ts> struct IndexTable : Table<soa::Index<>, H, Ts...> { using base_t = Table<soa::Index<>, H, Ts...>; + using table_t = base_t; + using safe_base_t = Table<H, Ts...>; using indexing_t = Key; using first_t = typename H::binding_t; using rest_t = framework::pack<typename Ts::binding_t...>; From 8de0a6228fcc6894947dee0eeb088a9fe250c913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <vit.kucera@cern.ch> Date: Wed, 2 Dec 2020 08:45:55 +0100 Subject: [PATCH 1487/1751] RecoDecay + PWGHF: Extend MC matching to support multi-stage decays and better particle origin tracking. (#4947) * Search mother iteratively. * Search final daughters recursively. Improve logging. * Support single-daughter decays. * Search daughters recursively in gen. matching. * Add option to set maximum depth to get daughters. * Add depth in matching. Match direct decays by default. Get final daughters by default. * Make a separate function getMother. * Get mother only for the first prong. Simplify rec. checks. * Return index of matched rec. mother. * Store antiparticle information in the table. * Define values for decay types. * Disable log messages. * Improve documentation. Clang format. --- Analysis/Core/include/Analysis/RecoDecay.h | 346 +++++++++++++----- .../include/Analysis/HFSecondaryVertex.h | 23 +- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 26 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 38 +- Analysis/Tasks/PWGHF/taskD0.cxx | 4 +- 5 files changed, 318 insertions(+), 119 deletions(-) diff --git a/Analysis/Core/include/Analysis/RecoDecay.h b/Analysis/Core/include/Analysis/RecoDecay.h index 4d164452ef6ca..db22e655a3e4b 100644 --- a/Analysis/Core/include/Analysis/RecoDecay.h +++ b/Analysis/Core/include/Analysis/RecoDecay.h @@ -423,109 +423,245 @@ class RecoDecay return newMass; } - /// Check whether the reconstructed decay candidate is the expected decay. + /// Finds the mother of an MC particle by looking for the expected PDG code in the mother chain. + /// \param particlesMC table with MC particles + /// \param particle MC particle + /// \param PDGMother expected mother PDG code + /// \param acceptAntiParticles switch to accept the antiparticle of the expected mother + /// \param sign antiparticle indicator of the found mother w.r.t. PDGMother; 1 if particle, -1 if antiparticle, 0 if mother not found + /// \return index of the mother particle if found, -1 otherwise + template <typename T, typename U> + static int getMother(const T& particlesMC, const U& particle, int PDGMother, bool acceptAntiParticles = false, int8_t* sign = nullptr) + { + int8_t sgn = 0; // 1 if the expected mother is particle, -1 if antiparticle (w.r.t. PDGMother) + int indexMother = -1; // index of the final matched mother, if found + auto particleMother = particle; // Initialise loop over mothers. + int stage = 0; // mother tree level (just for debugging) + if (sign) { + *sign = sgn; + } + while (particleMother.mother0() > -1) { + auto indexMotherTmp = particleMother.mother0(); + particleMother = particlesMC.iteratorAt(indexMotherTmp); + // Check mother's PDG code. + auto PDGParticleIMother = particleMother.pdgCode(); // PDG code of the mother + //printf("getMother: "); + //for (int i = stage; i < 0; i++) // Indent to make the tree look nice. + // printf(" "); + //printf("Stage %d: Mother PDG: %d\n", stage, PDGParticleIMother); + if (PDGParticleIMother == PDGMother) { // exact PDG match + sgn = 1; + indexMother = indexMotherTmp; + break; + } else if (acceptAntiParticles && PDGParticleIMother == -PDGMother) { // antiparticle PDG match + sgn = -1; + indexMother = indexMotherTmp; + break; + } + stage--; + } + if (sign) { + *sign = sgn; + } + return indexMother; + } + + /// Gets the complete list of indices of final-state daughters of an MC particle. + /// \param particlesMC table with MC particles + /// \param index index of the MC particle + /// \param list vector where the indices of final-state daughters will be added + /// \param arrPDGFinal array of PDG codes of particles to be considered final + /// \param depthMax maximum decay tree level; Daughters at this level (or beyond) will be considered final. If -1, all levels are considered. + /// \param stage decay tree level; If different from 0, the particle itself will be added in the list in case it has no daughters. + /// \note Final state is defined as particles from arrPDGFinal plus final daughters of any other decay branch. + template <std::size_t N, typename T> + static void getDaughters(const T& particlesMC, + int index, + std::vector<int>* list, + const array<int, N>& arrPDGFinal, + int depthMax = -1, + int8_t stage = 0) + { + if (index <= -1) { + //Printf("getDaughters: Error: No particle: index %d", index); + return; + } + if (!list) { + //Printf("getDaughters: Error: No list!"); + return; + } + // Get the particle. + auto particle = particlesMC.iteratorAt(index); + bool isFinal = false; // Flag to indicate the end of recursion + if (depthMax > -1 && stage >= depthMax) { // Maximum depth has been reached (or exceeded). + isFinal = true; + } + // Get the range of daughter indices. + int indexDaughterFirst = particle.daughter0(); + int indexDaughterLast = particle.daughter1(); + // Check whether there are any daughters. + if (!isFinal && indexDaughterFirst <= -1 && indexDaughterLast <= -1) { + // If the original particle has no daughters, we do nothing and exit. + if (stage == 0) { + //Printf("getDaughters: No daughters of %d", index); + return; + } + // If this is not the original particle, we are at the end of this branch and this particle is final. + isFinal = true; + } + // If the particle has daughters but is considered to be final, we label it as final. + auto PDGParticle = particle.pdgCode(); + if (!isFinal) { + for (auto PDGi : arrPDGFinal) { + if (std::abs(PDGParticle) == std::abs(PDGi)) { // Accept antiparticles. + isFinal = true; + break; + } + } + } + // If the particle is labelled as final, we add this particle in the list of final daughters and exit. + if (isFinal) { + //printf("getDaughters: "); + //for (int i = 0; i < stage; i++) // Indent to make the tree look nice. + // printf(" "); + //printf("Stage %d: Adding %d (PDG %d) as final daughter.\n", stage, index, PDGParticle); + list->push_back(index); + return; + } + // If we are here, we have to follow the daughter tree. + //printf("getDaughters: "); + //for (int i = 0; i < stage; i++) // Indent to make the tree look nice. + // printf(" "); + //printf("Stage %d: %d (PDG %d) -> %d-%d\n", stage, index, PDGParticle, indexDaughterFirst, indexDaughterLast); + // Call itself to get daughters of daughters recursively. + // Get daughters of the first daughter. + if (indexDaughterFirst > -1) { + getDaughters(particlesMC, indexDaughterFirst, list, arrPDGFinal, depthMax, stage + 1); + } + // Get daughters of the daughters in between if any. + // Daughter indices are supposed to be consecutive and in increasing order. + // Reverse order means two daughters. + if (indexDaughterFirst > -1 && indexDaughterLast > -1) { + for (auto iD = indexDaughterFirst + 1; iD < indexDaughterLast; ++iD) { + getDaughters(particlesMC, iD, list, arrPDGFinal, depthMax, stage + 1); + } + } + // Get daughters of the last daughter if different from the first one. + // Same indices indicate a single daughter. + if (indexDaughterLast > -1 && indexDaughterLast != indexDaughterFirst) { + getDaughters(particlesMC, indexDaughterLast, list, arrPDGFinal, depthMax, stage + 1); + } + } + + /// Checks whether the reconstructed decay candidate is the expected decay. /// \param particlesMC table with MC particles /// \param arrDaughters array of candidate daughters /// \param PDGMother expected mother PDG code /// \param arrPDGDaughters array of expected daughter PDG codes /// \param acceptAntiParticles switch to accept the antiparticle version of the expected decay - /// \return true if PDG codes of the mother and daughters are correct, false otherwise + /// \param sign antiparticle indicator of the found mother w.r.t. PDGMother; 1 if particle, -1 if antiparticle, 0 if mother not found + /// \param depthMax maximum decay tree level to check; Daughters up to this level will be considered. If -1, all levels are considered. + /// \return index of the mother particle if the mother and daughters are correct, -1 otherwise template <std::size_t N, typename T, typename U> - static bool isMCMatchedDecayRec(const T& particlesMC, const array<U, N>& arrDaughters, int PDGMother, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false) + static int getMatchedMCRec(const T& particlesMC, const array<U, N>& arrDaughters, int PDGMother, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false, int8_t* sign = nullptr, int depthMax = 1) { - //Printf("MC Rec.: Expected mother PDG: %d", PDGMother); - int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle + //Printf("MC Rec: Expected mother PDG: %d", PDGMother); + int8_t sgn = 0; // 1 if the expected mother is particle, -1 if antiparticle (w.r.t. PDGMother) int indexMother = -1; // index of the mother particle - int indexDaughterFirst = -1; // index of the first daughter - int indexDaughterLast = -1; // index of the last daughter - array<int, N> arrDaughtersIndex; // array of daughter indices - // loop over daughter particles + std::vector<int> arrAllDaughtersIndex; // vector of indices of all daughters of the mother of the first provided daughter + array<int, N> arrDaughtersIndex; // array of indices of provided daughters + if (sign) { + *sign = sgn; + } + // Loop over decay candidate prongs for (auto iProng = 0; iProng < N; ++iProng) { auto particleI = arrDaughters[iProng].label(); // ith daughter particle arrDaughtersIndex[iProng] = particleI.globalIndex(); - auto indexParticleIMother = particleI.mother0(); - if (indexParticleIMother == -1) { - //Printf("MC Rec. rejected: bad mother index: %d", indexParticleIMother); - return false; - } - // Get the mother. - auto particleIMother = particlesMC.iteratorAt(indexParticleIMother); - // Check mother's PDG code. - auto PDGParticleIMother = particleIMother.pdgCode(); // PDG code of the mother of the ith daughter - //Printf("MC Rec.: Daughter %d mother PDG: %d", iProng, PDGParticleIMother); - if (PDGParticleIMother != sgn * PDGMother) { - if (acceptAntiParticles && iProng == 0 && PDGParticleIMother == -PDGMother) { - sgn = -1; // PDG code of the first daughter's mother determines whether the expected mother is a particle or antiparticle. - } else { - //Printf("MC Rec. rejected: bad mother PDG: %s%d != %d", acceptAntiParticles ? "abs " : "", PDGParticleIMother, sgn * PDGMother); - return false; - } - } - // Check that all daughters have the same mother. + // Get the list of daughter indices from the mother of the first prong. if (iProng == 0) { - indexMother = indexParticleIMother; - } else if (indexParticleIMother != indexMother) { - //Printf("MC Rec. rejected: different mothers: %d %d", indexMother, indexParticleIMother); - return false; - } - // Set the range of expected daughter indices. - if (iProng == 0) { - indexDaughterFirst = particleIMother.daughter0(); - indexDaughterLast = particleIMother.daughter1(); + // Get the mother index and its sign. + // PDG code of the first daughter's mother determines whether the expected mother is a particle or antiparticle. + indexMother = getMother(particlesMC, particleI, PDGMother, acceptAntiParticles, &sgn); + // Check whether mother was found. + if (indexMother <= -1) { + //Printf("MC Rec: Rejected: bad mother index or PDG"); + return -1; + } + //Printf("MC Rec: Good mother: %d", indexMother); + auto particleMother = particlesMC.iteratorAt(indexMother); + int indexDaughterFirst = particleMother.daughter0(); // index of the first direct daughter + int indexDaughterLast = particleMother.daughter1(); // index of the last direct daughter // Check the daughter indices. - // Daughter indices are supposed to be consecutive. - if (indexDaughterLast <= indexDaughterFirst || indexDaughterFirst == -1 || indexDaughterLast == -1) { - //Printf("MC Rec. rejected: bad daughter index range: %d-%d", indexDaughterFirst, indexDaughterLast); - return false; + if (indexDaughterFirst <= -1 && indexDaughterLast <= -1) { + //Printf("MC Rec: Rejected: bad daughter index range: %d-%d", indexDaughterFirst, indexDaughterLast); + return -1; } - // Check the number of daughters. - if (indexDaughterLast - indexDaughterFirst + 1 != N) { - //Printf("MC Rec. rejected: incorrect number of daughters: %d", indexDaughterLast - indexDaughterFirst + 1); - return false; + // Check that the number of direct daughters is not larger than the number of expected final daughters. + if (indexDaughterFirst > -1 && indexDaughterLast > -1 && indexDaughterLast - indexDaughterFirst + 1 > N) { + //Printf("MC Rec: Rejected: too many direct daughters: %d (expected %d final)", indexDaughterLast - indexDaughterFirst + 1, N); + return -1; + } + // Get the list of actual final daughters. + getDaughters(particlesMC, indexMother, &arrAllDaughtersIndex, arrPDGDaughters, depthMax); + //printf("MC Rec: Mother %d has %d final daughters:", indexMother, arrAllDaughtersIndex.size()); + //for (auto i : arrAllDaughtersIndex) { + // printf(" %d", i); + //} + //printf("\n"); + // Check whether the number of actual final daughters is equal to the number of expected final daughters (i.e. the number of provided prongs). + if (arrAllDaughtersIndex.size() != N) { + //Printf("MC Rec: Rejected: incorrect number of final daughters: %d (expected %d)", arrAllDaughtersIndex.size(), N); + return -1; } } - // Check that the daughter is not a stepdaughter. - if (arrDaughtersIndex[iProng] < indexDaughterFirst || arrDaughtersIndex[iProng] > indexDaughterLast) { - //Printf("MC Rec. rejected: stepdaughter: %d outside %d-%d", arrDaughtersIndex[iProng], indexDaughterFirst, indexDaughterLast); - return false; - } - // Check that the daughter is not a twin. - for (auto jProng = 0; jProng < iProng; ++jProng) { - if (arrDaughtersIndex[iProng] == arrDaughtersIndex[jProng]) { - //Printf("MC Rec. rejected: twin daughter: %d", arrDaughtersIndex[iProng]); - return false; + // Check that the daughter is in the list of final daughters. + // (Check that the daughter is not a stepdaughter, i.e. particle pointing to the mother while not being its daughter.) + bool isDaughterFound = false; // Is the index of this prong among the remaining expected indices of daughters? + for (auto iD = 0; iD < arrAllDaughtersIndex.size(); ++iD) { + if (arrDaughtersIndex[iProng] == arrAllDaughtersIndex[iD]) { + arrAllDaughtersIndex[iD] = -1; // Remove this index from the array of expected daughters. (Rejects twin daughters, i.e. particle considered twice as a daughter.) + isDaughterFound = true; + break; } } + if (!isDaughterFound) { + //Printf("MC Rec: Rejected: bad daughter index: %d not in the list of final daughters", arrDaughtersIndex[iProng]); + return -1; + } // Check daughter's PDG code. auto PDGParticleI = particleI.pdgCode(); // PDG code of the ith daughter //Printf("MC Rec: Daughter %d PDG: %d", iProng, PDGParticleI); - bool PDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? + bool isPDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? for (auto iProngCp = 0; iProngCp < N; ++iProngCp) { if (PDGParticleI == sgn * arrPDGDaughters[iProngCp]) { arrPDGDaughters[iProngCp] = 0; // Remove this PDG code from the array of expected ones. - PDGFound = true; + isPDGFound = true; break; } } - if (!PDGFound) { - //Printf("MC Rec. rejected: bad daughter PDG: %d", PDGParticleI); - return false; + if (!isPDGFound) { + //Printf("MC Rec: Rejected: bad daughter PDG: %d", PDGParticleI); + return -1; } } - //Printf("MC Rec. accepted: m: %d, d: %d-%d", indexMother, indexDaughterFirst, indexDaughterLast); - return true; + //Printf("MC Rec: Accepted: m: %d", indexMother); + if (sign) { + *sign = sgn; + } + return indexMother; } - /// Check whether the MC particle is the expected one. + /// Checks whether the MC particle is the expected one. /// \param particlesMC table with MC particles /// \param candidate candidate MC particle /// \param PDGParticle expected particle PDG code /// \param acceptAntiParticles switch to accept the antiparticle /// \return true if PDG code of the particle is correct, false otherwise template <typename T, typename U> - static bool isMCMatchedDecayGen(const T& particlesMC, const U& candidate, int PDGParticle, bool acceptAntiParticles = false) + static int isMatchedMCGen(const T& particlesMC, const U& candidate, int PDGParticle, bool acceptAntiParticles = false) { - return isMCMatchedDecayGen(particlesMC, candidate, PDGParticle, array{0}, acceptAntiParticles); + array<int, 0> arrPDGDaughters; + return isMatchedMCGen(particlesMC, candidate, PDGParticle, std::move(arrPDGDaughters), acceptAntiParticles); } /// Check whether the MC particle is the expected one and whether it decayed via the expected decay channel. @@ -534,62 +670,80 @@ class RecoDecay /// \param PDGParticle expected particle PDG code /// \param arrPDGDaughters array of expected PDG codes of daughters /// \param acceptAntiParticles switch to accept the antiparticle + /// \param sign antiparticle indicator of the candidate w.r.t. PDGParticle; 1 if particle, -1 if antiparticle, 0 if not matched + /// \param depthMax maximum decay tree level to check; Daughters up to this level will be considered. If -1, all levels are considered. /// \return true if PDG codes of the particle and its daughters are correct, false otherwise template <std::size_t N, typename T, typename U> - static bool isMCMatchedDecayGen(const T& particlesMC, const U& candidate, int PDGParticle, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false) + static bool isMatchedMCGen(const T& particlesMC, const U& candidate, int PDGParticle, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false, int8_t* sign = nullptr, int depthMax = 1) { - //Printf("MC Gen.: Expected particle PDG: %d", PDGParticle); - int sgn = 1; // 1 if the expected mother is particle, -1 if antiparticle - int indexDaughterFirst = 0; // index of the first daughter - int indexDaughterLast = 0; // index of the last daughter + //Printf("MC Gen: Expected particle PDG: %d", PDGParticle); + int8_t sgn = 0; // 1 if the expected mother is particle, -1 if antiparticle (w.r.t. PDGParticle) + if (sign) { + *sign = sgn; + } // Check the PDG code of the particle. auto PDGCandidate = candidate.pdgCode(); - //Printf("MC Gen.: Candidate PDG: %d", PDGCandidate); - if (PDGCandidate != PDGParticle) { - if (acceptAntiParticles && PDGCandidate == -PDGParticle) { - sgn = -1; - } else { - //Printf("MC Gen. rejected: bad particle PDG: %s%d != %d", acceptAntiParticles ? "abs " : "", PDGCandidate, sgn * PDGParticle); - return false; - } + //Printf("MC Gen: Candidate PDG: %d", PDGCandidate); + if (PDGCandidate == PDGParticle) { // exact PDG match + sgn = 1; + } else if (acceptAntiParticles && PDGCandidate == -PDGParticle) { // antiparticle PDG match + sgn = -1; + } + if (sgn == 0) { + //Printf("MC Gen: Rejected: bad particle PDG: %s%d != %d", acceptAntiParticles ? "abs " : "", PDGCandidate, std::abs(PDGParticle)); + return false; } // Check the PDG codes of the decay products. - if (N > 1) { - //Printf("MC Gen.: Checking %d daughters", N); - // Set the range of expected daughter indices. - indexDaughterFirst = candidate.daughter0(); - indexDaughterLast = candidate.daughter1(); + if (N > 0) { + //Printf("MC Gen: Checking %d daughters", N); + std::vector<int> arrAllDaughtersIndex; // vector of indices of all daughters + int indexDaughterFirst = candidate.daughter0(); // index of the first direct daughter + int indexDaughterLast = candidate.daughter1(); // index of the last direct daughter // Check the daughter indices. - // Daughter indices are supposed to be consecutive. - if (indexDaughterLast <= indexDaughterFirst || indexDaughterFirst == -1 || indexDaughterLast == -1) { - //Printf("MC Gen. rejected: bad daughter index range: %d-%d", indexDaughterFirst, indexDaughterLast); + if (indexDaughterFirst <= -1 && indexDaughterLast <= -1) { + //Printf("MC Gen: Rejected: bad daughter index range: %d-%d", indexDaughterFirst, indexDaughterLast); return false; } - // Check the number of daughters. - if (indexDaughterLast - indexDaughterFirst + 1 != N) { - //Printf("MC Gen. rejected: incorrect number of daughters: %d", indexDaughterLast - indexDaughterFirst + 1); + // Check that the number of direct daughters is not larger than the number of expected final daughters. + if (indexDaughterFirst > -1 && indexDaughterLast > -1 && indexDaughterLast - indexDaughterFirst + 1 > N) { + //Printf("MC Gen: Rejected: too many direct daughters: %d (expected %d final)", indexDaughterLast - indexDaughterFirst + 1, N); + return false; + } + // Get the list of actual final daughters. + getDaughters(particlesMC, candidate.globalIndex(), &arrAllDaughtersIndex, arrPDGDaughters, depthMax); + //printf("MC Gen: Mother %d has %d final daughters:", candidate.globalIndex(), arrAllDaughtersIndex.size()); + //for (auto i : arrAllDaughtersIndex) { + // printf(" %d", i); + //} + //printf("\n"); + // Check whether the number of final daughters is equal to the required number. + if (arrAllDaughtersIndex.size() != N) { + //Printf("MC Gen: Rejected: incorrect number of final daughters: %d (expected %d)", arrAllDaughtersIndex.size(), N); return false; } // Check daughters' PDG codes. - for (auto indexDaughterI = indexDaughterFirst; indexDaughterI <= indexDaughterLast; ++indexDaughterI) { + for (auto indexDaughterI : arrAllDaughtersIndex) { auto candidateDaughterI = particlesMC.iteratorAt(indexDaughterI); // ith daughter particle auto PDGCandidateDaughterI = candidateDaughterI.pdgCode(); // PDG code of the ith daughter - //Printf("MC Gen.: Daughter %d PDG: %d", indexDaughterI, PDGCandidateDaughterI); - bool PDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? + //Printf("MC Gen: Daughter %d PDG: %d", indexDaughterI, PDGCandidateDaughterI); + bool isPDGFound = false; // Is the PDG code of this daughter among the remaining expected PDG codes? for (auto iProngCp = 0; iProngCp < N; ++iProngCp) { if (PDGCandidateDaughterI == sgn * arrPDGDaughters[iProngCp]) { arrPDGDaughters[iProngCp] = 0; // Remove this PDG code from the array of expected ones. - PDGFound = true; + isPDGFound = true; break; } } - if (!PDGFound) { - //Printf("MC Gen. rejected: bad daughter PDG: %d", PDGCandidateDaughterI); + if (!isPDGFound) { + //Printf("MC Gen: Rejected: bad daughter PDG: %d", PDGCandidateDaughterI); return false; } } } - //Printf("MC Gen. accepted: m: %d, d: %d-%d", candidate.globalIndex(), indexDaughterFirst, indexDaughterLast); + //Printf("MC Gen: Accepted: m: %d", candidate.globalIndex()); + if (sign) { + *sign = sgn; + } return true; } diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index c3520064b443f..26a16a6e7d52c 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -133,9 +133,12 @@ DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m, double mTot, int iProng) { return RecoDecay::CosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); // MC matching result: -// - bit 0: D0(bar) → π± K∓ -DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, uint8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, uint8_t); // generator level +// - ±D0ToPiK: D0(bar) → π± K∓ +DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, int8_t); // generator level + +// mapping of decay types +enum DecayType { D0ToPiK = 1 }; // functions for specific particles @@ -257,10 +260,14 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::hf_cand::pzProng0 + 1.f DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); // MC matching result: -// - bit 0: D± → π± K∓ π± -// - bit 1: Lc± → p± K∓ π± -DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, uint8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, uint8_t); // generator level +// - ±DPlusToPiKPi: D± → π± K∓ π± +// - ±LcToPKPi: Λc± → p± K∓ π± +DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMCMatchGen, flagMCMatchGen, int8_t); // generator level + +// mapping of decay types +enum DecayType { DPlusToPiKPi = 1, + LcToPKPi }; // functions for specific particles @@ -290,7 +297,7 @@ auto InvMassDPlus(const T& candidate) return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); } -// Lc± → p± K∓ π± +// Λc± → p± K∓ π± template <typename T> auto CtLc(const T& candidate) diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index bf7b6ee5a4da1..a62b5b9c9ce55 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -22,6 +22,7 @@ using namespace o2; using namespace o2::framework; +using namespace o2::aod::hf_cand_prong2; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { @@ -144,20 +145,35 @@ struct HFCandidateCreator2ProngMC { aod::BigTracksMC const& tracks, aod::McParticles const& particlesMC) { + int8_t sign = 0; + int8_t result = 0; + // Match reconstructed candidates. for (auto& candidate : candidates) { + //Printf("New rec. candidate"); + result = 0; + // D0(bar) → π± K∓ - auto isMatchedRecD0 = RecoDecay::isMCMatchedDecayRec( + //Printf("Checking D0(bar) → π± K∓"); + auto indexRecD0 = RecoDecay::getMatchedMCRec( particlesMC, array{candidate.index0_as<aod::BigTracksMC>(), candidate.index1_as<aod::BigTracksMC>()}, - 421, array{+kPiPlus, -kKPlus}, true); - rowMCMatchRec(uint8_t(isMatchedRecD0)); + 421, array{+kPiPlus, -kKPlus}, true, &sign); + result += sign * D0ToPiK * int8_t(indexRecD0 > -1); + + rowMCMatchRec(result); } // Match generated particles. for (auto& particle : particlesMC) { + //Printf("New gen. candidate"); + result = 0; + // D0(bar) → π± K∓ - auto isMatchedGenD0 = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 421, array{+kPiPlus, -kKPlus}, true); - rowMCMatchGen(uint8_t(isMatchedGenD0)); + //Printf("Checking D0(bar) → π± K∓"); + auto isMatchedGenD0 = RecoDecay::isMatchedMCGen(particlesMC, particle, 421, array{+kPiPlus, -kKPlus}, true, &sign); + result += sign * D0ToPiK * int8_t(isMatchedGenD0); + + rowMCMatchGen(result); } } }; diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 70fc45df35242..9ea2145c15e35 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -22,6 +22,7 @@ using namespace o2; using namespace o2::framework; +using namespace o2::aod::hf_cand_prong3; void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { @@ -148,23 +149,44 @@ struct HFCandidateCreator3ProngMC { aod::BigTracksMC const& tracks, aod::McParticles const& particlesMC) { + int8_t sign = 0; + int8_t result = 0; + // Match reconstructed candidates. for (auto& candidate : candidates) { + //Printf("New rec. candidate"); + result = 0; auto arrayDaughters = array{candidate.index0_as<aod::BigTracksMC>(), candidate.index1_as<aod::BigTracksMC>(), candidate.index2_as<aod::BigTracksMC>()}; + // D± → π± K∓ π± - auto isMatchedRecDPlus = RecoDecay::isMCMatchedDecayRec(particlesMC, arrayDaughters, 411, array{+kPiPlus, -kKPlus, +kPiPlus}, true); - // Lc± → p± K∓ π± - auto isMatchedRecLc = RecoDecay::isMCMatchedDecayRec(particlesMC, std::move(arrayDaughters), 4122, array{+kProton, -kKPlus, +kPiPlus}, true); - rowMCMatchRec(uint8_t(isMatchedRecDPlus + 2 * isMatchedRecLc)); + //Printf("Checking D± → π± K∓ π±"); + auto indexRecDPlus = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, 411, array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign); + result += sign * DPlusToPiKPi * int8_t(indexRecDPlus > -1); + + // Λc± → p± K∓ π± + //Printf("Checking Λc± → p± K∓ π±"); + auto indexRecLc = RecoDecay::getMatchedMCRec(particlesMC, std::move(arrayDaughters), 4122, array{+kProton, -kKPlus, +kPiPlus}, true, &sign); + result += sign * LcToPKPi * int8_t(indexRecLc > -1); + + rowMCMatchRec(result); } // Match generated particles. for (auto& particle : particlesMC) { + //Printf("New gen. candidate"); + result = 0; + // D± → π± K∓ π± - auto isMatchedGenDPlus = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 411, array{+kPiPlus, -kKPlus, +kPiPlus}, true); - // Lc± → p± K∓ π± - auto isMatchedGenLc = RecoDecay::isMCMatchedDecayGen(particlesMC, particle, 4122, array{+kProton, -kKPlus, +kPiPlus}, true); - rowMCMatchGen(uint8_t(isMatchedGenDPlus + 2 * isMatchedGenLc)); + //Printf("Checking D± → π± K∓ π±"); + auto isMatchedGenDPlus = RecoDecay::isMatchedMCGen(particlesMC, particle, 411, array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign); + result += sign * DPlusToPiKPi * int8_t(isMatchedGenDPlus); + + // Λc± → p± K∓ π± + //Printf("Checking Λc± → p± K∓ π±"); + auto isMatchedGenLc = RecoDecay::isMatchedMCGen(particlesMC, particle, 4122, array{+kProton, -kKPlus, +kPiPlus}, true, &sign); + result += sign * LcToPKPi * int8_t(isMatchedGenLc); + + rowMCMatchGen(result); } } }; diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index 2ebaedb605b11..cccc6c5f1b08a 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -124,7 +124,7 @@ struct TaskD0MC { //Printf("MC Rec.: eta rejection: %g", candidate.eta()); continue; } - if (candidate.flagMCMatchRec() == 1) { + if (std::abs(candidate.flagMCMatchRec()) == D0ToPiK) { registry.get<TH1>("hPtRecSig")->Fill(candidate.pt()); registry.get<TH1>("hCPARecSig")->Fill(candidate.cpa()); registry.get<TH1>("hEtaRecSig")->Fill(candidate.eta()); @@ -141,7 +141,7 @@ struct TaskD0MC { //Printf("MC Gen.: eta rejection: %g", particle.eta()); continue; } - if (particle.flagMCMatchGen() == 1) { + if (std::abs(particle.flagMCMatchGen()) == D0ToPiK) { registry.get<TH1>("hPtGen")->Fill(particle.pt()); registry.get<TH1>("hEtaGen")->Fill(particle.eta()); } From 5effbf39f94222f0465c4e764bb09db709d13f69 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 2 Dec 2020 09:15:03 +0100 Subject: [PATCH 1488/1751] DPL: add type trait helper for compile-time strings (#4936) --- Framework/Core/include/Framework/StringHelpers.h | 15 +++++++++++++++ Framework/Core/test/test_StringHelpers.cxx | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/Framework/Core/include/Framework/StringHelpers.h b/Framework/Core/include/Framework/StringHelpers.h index d58187031d06b..7bd1f17760b2b 100644 --- a/Framework/Core/include/Framework/StringHelpers.h +++ b/Framework/Core/include/Framework/StringHelpers.h @@ -13,6 +13,7 @@ #include <cstdint> #include <utility> +#include <type_traits> // CRC32 Table (zlib polynomial) static constexpr uint32_t crc_table[256] = {0x0L, 0x77073096L, 0xee0e612cL, @@ -87,6 +88,20 @@ struct ConstStr { static constexpr uint32_t idx = hash & 0x1FF; }; +template <typename> +struct is_const_str : std::false_type { +}; + +template <char... chars> +struct is_const_str<ConstStr<chars...>> : std::true_type { +}; + +template <typename T> +constexpr bool is_const_str_v(T) +{ + return is_const_str<T>::value; +} + template <typename T, std::size_t... Is> constexpr auto as_chars_impl(std::index_sequence<Is...>) { diff --git a/Framework/Core/test/test_StringHelpers.cxx b/Framework/Core/test/test_StringHelpers.cxx index d866082b4ecd6..9e79f05ec005b 100644 --- a/Framework/Core/test/test_StringHelpers.cxx +++ b/Framework/Core/test/test_StringHelpers.cxx @@ -27,6 +27,8 @@ BOOST_AUTO_TEST_CASE(StringHelpersHash) template <typename T> void printString(const T& constStr) { + static_assert(is_const_str<T>::value, "This function can only print compile-time strings!"); + std::cout << "ConstStr:" << std::endl; std::cout << "str -> " << constStr.str << std::endl; std::cout << "hash -> " << constStr.hash << std::endl; @@ -42,4 +44,8 @@ BOOST_AUTO_TEST_CASE(StringHelpersConstStr) static_assert(std::is_same_v<decltype(myConstStr), ConstStr<'h', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'>>); static_assert(myConstStr.hash == (uint32_t)942280617); BOOST_CHECK_EQUAL(myConstStr.hash, compile_time_hash("helloWorld")); + + if constexpr (is_const_str_v(myConstStr)) { + std::cout << "myConstStr is a compile-time string" << std::endl; + } } From da6a51f557f2b4086b06274099315a571614d768 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 2 Dec 2020 09:41:25 +0100 Subject: [PATCH 1489/1751] Drop .travis.yml Doxygen now runs in Github Actions --- .travis.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0616499ab1d76..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -sudo: false -matrix: - fast_finish: true - # Note: Workaround travis-ci/travis-ci#4681 - # Exclude default job which lacks our included environment variables. - exclude: - - os: linux - - env: - include: - - os: linux - dist: bionic - env: JOB=doxygen - addons: - apt: - packages: - - doxygen - - doxygen-doc - - doxygen-latex - - doxygen-gui - - graphviz - - cmake - script: | - cat > CMakeLists.txt <<\EOF - add_subdirectory(doc) - EOF - cmake . - make doc - deploy: - provider: pages - skip_cleanup: true - github_token: $GITHUB_API_TOKEN # Set in travis-ci.org dashboard - local_dir: doc/html - on: - branch: dev From e93e4acf9392470bc3304cccf7c23c3a7d882af0 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 2 Dec 2020 00:32:39 +0100 Subject: [PATCH 1490/1751] Add some scripts related to running the full system test --- prodtests/CMakeLists.txt | 4 + .../full-system-test/datadistribution.sh | 27 ++++++ prodtests/full-system-test/dpl-workflow.sh | 94 +++++++++++++++++++ prodtests/full-system-test/raw-reader.sh | 13 +++ prodtests/full-system-test/setenv.sh | 29 ++++++ prodtests/full-system-test/start_tmux.sh | 31 ++++++ 6 files changed, 198 insertions(+) create mode 100755 prodtests/full-system-test/datadistribution.sh create mode 100755 prodtests/full-system-test/dpl-workflow.sh create mode 100755 prodtests/full-system-test/raw-reader.sh create mode 100755 prodtests/full-system-test/setenv.sh create mode 100755 prodtests/full-system-test/start_tmux.sh diff --git a/prodtests/CMakeLists.txt b/prodtests/CMakeLists.txt index 1401750c63abb..34deddb802429 100644 --- a/prodtests/CMakeLists.txt +++ b/prodtests/CMakeLists.txt @@ -12,3 +12,7 @@ install(PROGRAMS sim_performance_test.sh sim_challenge.sh check_embedding_pileup.sh produce_QEDhits.sh full_system_test.sh DESTINATION prodtests) +install(DIRECTORY full-system-test + DESTINATION prodtests + PATTERN * + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) diff --git a/prodtests/full-system-test/datadistribution.sh b/prodtests/full-system-test/datadistribution.sh new file mode 100755 index 0000000000000..77e0c939006b8 --- /dev/null +++ b/prodtests/full-system-test/datadistribution.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +MYDIR="$(dirname $(readlink -f $0))" +source $MYDIR/setenv.sh + +if [ "0$ALIENVLVL" == "0" ]; then + eval "`alienv shell-helper`" + alienv --no-refresh load DataDistribution/latest +fi + +export DATADIST_SHM_DELAY=10 +export TF_DIR=./raw/timeframe +export TFRATE=$(awk "BEGIN {printf \"%.6f\",1/$NTIMEFRAMES}") + +ARGS_ALL="--session default --severity $SEVERITY --shm-segment-size $SHMSIZE --no-cleanup" + +StfBuilder --id stfb --session default --transport shmem \ + --dpl-channel-name dpl-chan --channel-config "name=dpl-chan,type=push,method=bind,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=1" \ + --data-source-dir ${TF_DIR} \ + --data-source-rate=0.01 \ + --data-source-repeat \ + --data-source-regionsize=${DDSHMSIZE} \ + --data-source-headersize=1024 \ + --data-source-enable \ + --data-source-preread 5 \ + --severity debug \ + ${ARGS_ALL} diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh new file mode 100755 index 0000000000000..1883d3ce80aff --- /dev/null +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +MYDIR="$(dirname $(readlink -f $0))" +source $MYDIR/setenv.sh + +if [ "0$ALIENVLVL" == "0" ]; then + eval "`alienv shell-helper`" + alienv --no-refresh load O2/latest +fi + +ARGS_ALL="--session default --severity $SEVERITY --shm-segment-id $NUMAID --shm-throw-bad-alloc 0 --shm-segment-size $SHMSIZE" + +if [ $EXTINPUT == 1 ] || [ $NUMAGPUIDS == 1 ]; then + ARGS_ALL+=" --no-cleanup" +fi + +if [ $EXTINPUT == 1 ]; then + CMD_X="B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA" + CMD_Y="name=readout-proxy,type=pull,method=connect,address=ipc://@stfb-to-dpl$1,transport=shmem,rateLogging=0" + CMD_INPUT="o2-dpl-raw-proxy $ARGS_ALL --dataspec $CMD_X --channel-config $CMD_Y" +else + CMD_X="HBFUtils.nHBFPerTF=$NHBPERTF;" + CMD_INPUT="o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues $CMD_X --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg" +fi + +if [ $CREATECTFDICT == 1 ]; then + CMD_DICT="o2-ctf-writer-workflow $ARGS_ALL --output-type dict --save-dict-after 1 --onlyDet ITS,MFT,TPC,TOF,FT0,MID" +else + CMD_DICT=cat +fi + +if [ $SYNCMODE == 1 ]; then + CFG_X="fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500" + ITS_CONFIG="--configKeyValues $CFG_X" + TPC_CONFIG="GPU_global.synchronousProcessing=1;" +else + ITS_CONFIG= + TPC_CONFIG= +fi +TPC_CONFIG2= + +if [ $GPUTYPE == "HIP" ]; then + if [ $NUMAID == 0 ] || [ $NUMAGPUIDS == 0 ]; then + export TIMESLICEOFFSET=0 + else + export TIMESLICEOFFSET=$NGPUS + fi + TPC_CONFIG+="GPU_proc.deviceNum=0;GPU_global.mutexMemReg=true;" + CFG_Y="ROCR_VISIBLE_DEVICES={timeslice${TIMESLICEOFFSET}}" + TPC_CONFIG2+=" --environment $CFG_Y" + export HSA_NO_SCRATCH_RECLAIM=1 + #export HSA_TOOLS_LIB=/opt/rocm/lib/librocm-debug-agent.so.2 +else + TPC_CONFIG+="GPU_proc.deviceNum=-2;" +fi + +if [ $GPUTYPE != "CPU" ]; then + TPC_CONFIG+="GPU_proc.forceMemoryPoolSize=$GPUMEMSIZE;" + if [ $HOSTMEMSIZE == "0" ]; then + HOSTMEMSIZE=$(( 1 << 30 )) + fi +fi +if [ $HOSTMEMSIZE != "0" ]; then + TPC_CONFIG+="GPU_proc.forceHostMemoryPoolSize=$HOSTMEMSIZE;" +fi + +if [ $EPNPIPELINES == 1 ]; then + N_TPCENT=$(($(expr 7 \* $NGPUS / 4) > 0 ? $(expr 7 \* $NGPUS / 4) : 1)) + N_TPCITS=$(($(expr 7 \* $NGPUS / 4) > 0 ? $(expr 7 \* $NGPUS / 4) : 1)) + N_ITSDEC=$(($(expr 3 \* $NGPUS / 4) > 0 ? $(expr 3 \* $NGPUS / 4) : 1)) +else + N_TPCENT=1 + N_TPCITS=1 + N_ITSDEC=1 +fi + +$CMD_INPUT | \ +o2-itsmft-stf-decoder-workflow $ARGS_ALL --pipeline its-stf-decoder:$N_ITSDEC | \ +o2-itsmft-stf-decoder-workflow $ARGS_ALL --runmft true | \ +o2-its-reco-workflow $ARGS_ALL --trackerCA $DISABLE_MC --clusters-from-upstream --disable-root-output --entropy-encoding $ITS_CONFIG | \ +o2-itsmft-entropy-encoder-workflow $ARGS_ALL --runmft true | \ +o2-tpc-reco-workflow ${ARGS_ALL/--severity $SEVERITY/--severity $SEVERITY_TPC} --input-type=zsraw $DISABLE_MC --output-type tracks,clusters,encoded-clusters,disable-writer --pipeline tpc-tracker:$NGPUS,tpc-entropy-encoder:$N_TPCENT $TPC_CONFIG2 --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF;GPU_global.deviceType=$GPUTYPE;GPU_proc.debugLevel=0;$TPC_CONFIG" | \ +o2-tpcits-match-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC --pipeline itstpc-track-matcher:$N_TPCITS | \ +o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | \ +o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC | \ +o2-ft0-entropy-encoder-workflow $ARGS_ALL | \ +o2-mid-raw-to-digits-workflow $ARGS_ALL | \ +o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC | \ +o2-mid-entropy-encoder-workflow $ARGS_ALL | \ +o2-tof-compressor $ARGS_ALL | \ +o2-tof-reco-workflow $ARGS_ALL --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output $DISABLE_MC | \ +o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input | \ +$CMD_DICT | \ +o2-dpl-run $ARGS_ALL $GLOBALDPLOPT --run diff --git a/prodtests/full-system-test/raw-reader.sh b/prodtests/full-system-test/raw-reader.sh new file mode 100755 index 0000000000000..eb3e6f7aba98f --- /dev/null +++ b/prodtests/full-system-test/raw-reader.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [ "0$ALIENVLVL" == "0" ]; then + eval "`alienv shell-helper`" + alienv --no-refresh load O2/latest +fi + +MYDIR="$(dirname $(readlink -f $0))" +source $MYDIR/setenv.sh + +ARGS_ALL="--session default --severity $SEVERITY --shm-throw-bad-alloc 0 --shm-segment-size $SHMSIZE --no-cleanup" + +o2-raw-file-reader-workflow $ARGS_ALL --loop $NTIMEFRAMES --delay $TFDELAY --input-conf rawAll.cfg --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF;" --max-tf 0 --raw-channel-config "name=dpl-chan,type=push,method=bind,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0" diff --git a/prodtests/full-system-test/setenv.sh b/prodtests/full-system-test/setenv.sh new file mode 100755 index 0000000000000..51833d529cb06 --- /dev/null +++ b/prodtests/full-system-test/setenv.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Make sure we can open sufficiently many files / allocate enough memory +ulimit -n 4096 || ulimit -l unlimited || ulimit -m unlimited || ulimit -l unlimited +if [ $? != 0 ]; then + echo Error setting ulimits + exit 1 +fi + +if [ -z "$NTIMEFRAMES" ]; then export NTIMEFRAMES=1; fi # Number of time frames to process +if [ -z "$TFDELAY" ]; then export TFDELAY=100; fi # Delay in seconds between publishing time frames +if [ -z "$NGPUS" ]; then export NGPUS=1; fi # Number of GPUs to use, data distributed round-robin +if [ -z "$GPUTYPE" ]; then export GPUTYPE=CPU; fi # GPU Tracking backend to use, can be CPU / CUDA / HIP / OCL / OCL2 +if [ -z "$SHMSIZE" ]; then export SHMSIZE=$(( 128 << 30 )); fi # Size of shared memory for messages +if [ -z "$DDSHMSIZE" ]; then export DDSHMSIZE=$(( 32 << 10 )); fi # Size of shared memory for DD Input +if [ -z "$GPUMEMSIZE" ]; then export GPUMEMSIZE=$(( 13 << 30 )); fi # Size of allocated GPU memory (if GPUTYPE != CPU) +if [ -z "$HOSTMEMSIZE" ]; then export HOSTMEMSIZE=0; fi # Size of allocated host memory for GPU reconstruction (0 = default) +if [ -z "$CREATECTFDICT" ]; then export CREATECTFDICT=0; fi # Create CTF dictionary +if [ -z "$SYNCMODE" ]; then export SYNCMODE=0; fi # Run only reconstruction steps of the synchronous reconstruction +if [ -z "$NUMAID" ]; then export NUMAID=0; fi # SHM segment id to use for shipping data as well as set of GPUs to use (use 0 / 1 for 2 NUMA domains) +if [ -z "$NUMAGPUIDS" ]; then export NUMAGPUIDS=0; fi # NUMAID-aware GPU id selection +if [ -z "$EXTINPUT" ]; then export EXTINPUT=0; fi # Receive input from raw FMQ channel instead of running o2-raw-file-reader +if [ -z "$NHBPERTF" ]; then export NHBPERTF=128; fi # Time frame length (in HBF) +if [ -z "$GLOBALDPLOPT" ]; then export GLOBALDPLOPT=; fi # Global DPL workflow options appended at the end +if [ -z "$EPNPIPELINES" ]; then export EPNPIPELINES=0; fi # Set default EPN pipeline multiplicities +if [ -z "$SEVERITY" ]; then export SEVERITY="info"; fi # Log verbosity + +SEVERITY_TPC="info" # overrides severity for the tpc workflow +DISABLE_MC="--disable-mc" diff --git a/prodtests/full-system-test/start_tmux.sh b/prodtests/full-system-test/start_tmux.sh new file mode 100755 index 0000000000000..95db0c7175cd0 --- /dev/null +++ b/prodtests/full-system-test/start_tmux.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +if [ "0$1" == "0" ]; then + echo Please indicate whether to start with raw-reader [rr] or with DataDistribution [dd] + exit 1 +fi + +MYDIR="$(dirname $(readlink -f $0))" +source $MYDIR/setenv.sh + +# This sets up the hardcoded configuration to run the full system workflow on the EPN +export NGPUS=4 +export GPUTYPE=HIP +export SHMSIZE=$(( 128 << 30 )) +export NUMAGPUIDS=1 +export EXTINPUT=1 +export EPNPIPELINES=1 +export SYNCMODE=1 + +if [ $1 == "dd" ]; then + export CMD=datadistribution.sh +else + export CMD=raw-reader.sh +fi + +rm -f /dev/shm/*fmq* + +tmux \ + new-session "NUMAID=0 numactl --membind 0 --cpunodebind 0 $MYDIR/dpl-workflow.sh" \; \ + split-window "NUMAID=1 numactl --membind 1 --cpunodebind 1 $MYDIR/dpl-workflow.sh" \; \ + split-window "sleep 30; numactl --cpunodebind 0 --interleave=all $MYDIR/$CMD" From 4155d5685b6df5e362815e71a17123f042596d71 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 2 Dec 2020 11:55:54 +0100 Subject: [PATCH 1491/1751] Use full-system-test/dpl-workflow.sh in full-system-test.sh --- prodtests/full_system_test.sh | 41 +++++++++++++++-------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 47a471efd4272..c4faf0d63dc62 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -8,7 +8,7 @@ # Note that this might require a production server to run. # # This script needs some binary objects (for the moment): -# - matbud.root + ITSdictionary.bin + ctf_dictionary.root +# - matbud.root + ITSdictionary.bin # # authors: D. Rohr / S. Wenzel @@ -47,7 +47,7 @@ echo "versions,${TAG} alidist=\"${ALIDISTCOMMIT}\",O2=\"${O2COMMIT}\" " > ${METR ulimit -n 4096 # Make sure we can open sufficiently many files -mkdir qed +mkdir -p qed cd qed taskwrapper qedsim.log o2-sim -j $NJOBS -n$NEventsQED -m PIPE ITS MFT FT0 FV0 -g extgen --configKeyValues '"GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-5;QEDGenParam.yMax=6;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;Diamond.width[2]=6."' cd .. @@ -56,7 +56,7 @@ GLOBALDPLOPT="-b --monitoring-backend no-op://" taskwrapper sim.log o2-sim -n $NEvents --skipModules ZDC --configKeyValues "Diamond.width[2]=6." -g pythia8hi -j $NJOBS taskwrapper digi.log o2-sim-digitizer-workflow -n $NEvents --simPrefixQED qed/o2sim --qed-x-section-ratio 3735 ${NOMCLABELS} --firstOrbit 0 --firstBC 0 --skipDet TRD --tpc-lanes $((NJOBS < 36 ? NJOBS : 36)) --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} taskwrapper digiTRD.log o2-sim-digitizer-workflow -n $NEvents --simPrefixQED qed/o2sim --qed-x-section-ratio 3735 ${NOMCLABELS} --firstOrbit 0 --firstBC 0 --onlyDet TRD --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} --incontext collisioncontext.root --configKeyValues "TRDSimParams.digithreads=${NJOBS}" -mkdir raw +mkdir -p raw taskwrapper itsraw.log o2-its-digi2raw --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/ITS taskwrapper mftraw.log o2-mft-digi2raw --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/MFT taskwrapper ft0raw.log o2-ft0-digi2raw --file-per-link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/FT0 @@ -71,30 +71,24 @@ for STAGE in "NOGPU" "WITHGPU"; do ARGS_ALL="--session default" DICTCREATION="" if [[ "$STAGE" = "WITHGPU" ]]; then - TPC_GPU_OPT="GPU_proc.deviceNum=0;GPU_global.deviceType=CUDA;GPU_proc.forceMemoryPoolSize=6000000000;GPU_proc.forceHostMemoryPoolSize=3000000000" + export CREATECTFDICT=0 + export GPUTYPE=CUDA + export GPUMEMSIZE=6000000000 + export HOSTMEMSIZE=1000000000 + export SYNCMODE=1 else - TPC_GPU_OPT="GPU_proc.forceHostMemoryPoolSize=${TPCTRACKERSCRATCHMEMORY}" - DICTCREATION=" | o2-ctf-writer-workflow $ARGS_ALL --output-type dict --save-dict-after 1 --onlyDet ITS,MFT,TPC,TOF,FT0,MID " + export CREATECTFDICT=1 + export GPUTYPE=CPU + export SYNCMODE=0 + export HOSTMEMSIZE=$TPCTRACKERSCRATCHMEMORY fi + export SHMSIZE + export NTIMEFRAMES + export TFDELAY + export GLOBALDPLOPT logfile=reco_${STAGE}.log - taskwrapper ${logfile} "o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | -o2-itsmft-stf-decoder-workflow $ARGS_ALL | -o2-itsmft-stf-decoder-workflow $ARGS_ALL --runmft true | -o2-its-reco-workflow $ARGS_ALL --trackerCA ${NOMCLABELS} --clusters-from-upstream --disable-root-output --entropy-encoding --configKeyValues \"fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500\" | -o2-itsmft-entropy-encoder-workflow $ARGS_ALL --runmft true | -o2-tpc-reco-workflow $ARGS_ALL --input-type=zsraw ${NOMCLABELS} --output-type tracks,clusters,encoded-clusters,disable-writer --configKeyValues \"HBFUtils.nHBFPerTF=128;${TPC_GPU_OPT}\" | -o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | -o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | -o2-ft0-entropy-encoder-workflow $ARGS_ALL | -o2-tpcits-match-workflow $ARGS_ALL --disable-root-input --disable-root-output ${NOMCLABELS} | -o2-mid-raw-to-digits-workflow $ARGS_ALL | -o2-mid-reco-workflow $ARGS_ALL --disable-root-output ${NOMCLABELS} | -o2-mid-entropy-encoder-workflow $ARGS_ALL | -o2-tof-compressor $ARGS_ALL | -o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=128\" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output ${NOMCLABELS} | -o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input ${DICTCREATION} --shm-segment-size $SHMSIZE ${GLOBALDPLOPT}" - + taskwrapper ${logfile} "$O2_ROOT/prodtests/full-system-test/dpl-workflow.sh" # --- record interesting metrics to monitor ---- # boolean flag indicating if workflow completed successfully at all @@ -121,4 +115,3 @@ o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable echo "tpcclusters_${STAGE},${TAG} value=${tpcclusters}" >> ${METRICFILE} fi done - From 287e22943b7d661459cbcee4617325fa4a4bd9d3 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <felix.weiglhofer@gmail.com> Date: Thu, 26 Nov 2020 11:11:51 +0000 Subject: [PATCH 1492/1751] TPCClusterFinder: Rename TPCCalibration class to TPCPadGainCalib. --- .../reconstruction/test/testGPUCATracking.cxx | 6 +++--- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 10 +++++----- GPU/GPUTracking/Base/GPUConstantMem.h | 2 +- GPU/GPUTracking/Base/GPUDataTypes.h | 4 ++-- GPU/GPUTracking/CMakeLists.txt | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 10 +++++----- GPU/GPUTracking/Global/GPUChainTracking.h | 6 +++--- GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 12 ++++++------ GPU/GPUTracking/Interface/GPUO2Interface.cxx | 2 +- .../TPCClusterFinder/GPUTPCCFPeakFinder.cxx | 2 +- .../TPCClusterFinder/GPUTPCClusterFinder.h | 4 ++-- ...PCCFCalibration.cxx => TPCPadGainCalib.cxx} | 8 ++++---- .../{TPCCFCalibration.h => TPCPadGainCalib.h} | 18 +++++++++--------- 13 files changed, 43 insertions(+), 43 deletions(-) rename GPU/GPUTracking/TPCClusterFinder/{TPCCFCalibration.cxx => TPCPadGainCalib.cxx} (83%) rename GPU/GPUTracking/TPCClusterFinder/{TPCCFCalibration.h => TPCPadGainCalib.h} (89%) diff --git a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx index 46a6c19a0bcf0..db914eb39ca69 100644 --- a/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/test/testGPUCATracking.cxx @@ -27,7 +27,7 @@ #include "TPCFastTransform.h" #include "TPCdEdxCalibrationSplines.h" #include "GPUO2InterfaceConfiguration.h" -#include "TPCCFCalibration.h" +#include "TPCPadGainCalib.h" using namespace o2::gpu; @@ -77,8 +77,8 @@ BOOST_AUTO_TEST_CASE(CATracking_test1) config.configCalib.fastTransform = fastTransform.get(); std::unique_ptr<o2::gpu::TPCdEdxCalibrationSplines> dEdxSplines(new TPCdEdxCalibrationSplines); config.configCalib.dEdxSplines = dEdxSplines.get(); - std::unique_ptr<TPCCFCalibration> tpcCalibration(new TPCCFCalibration{}); - config.configCalib.tpcCalibration = tpcCalibration.get(); + std::unique_ptr<TPCPadGainCalib> gainCalib(new TPCPadGainCalib{}); + config.configCalib.tpcPadGain = gainCalib.get(); tracker.initialize(config); std::vector<ClusterNativeContainer> cont(constants::MAXGLOBALPADROW); diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 427a40e2d1c88..297b436e4c2d3 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -43,7 +43,7 @@ #include "TPCBase/RDHUtils.h" #include "GPUO2InterfaceConfiguration.h" #include "GPUO2InterfaceQA.h" -#include "TPCCFCalibration.h" +#include "TPCPadGainCalib.h" #include "GPUDisplayBackend.h" #ifdef GPUCA_BUILD_EVENT_DISPLAY #include "GPUDisplayBackendGlfw.h" @@ -100,7 +100,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config std::unique_ptr<GPUDisplayBackend> displayBackend; std::unique_ptr<TPCFastTransform> fastTransform; std::unique_ptr<TPCdEdxCalibrationSplines> dEdxSplines; - std::unique_ptr<TPCCFCalibration> tpcCalibration; + std::unique_ptr<TPCPadGainCalib> tpcPadGainCalib; std::unique_ptr<GPUSettingsQA> qaConfig; int qaTaskMask = 0; std::unique_ptr<GPUO2InterfaceQA> qa; @@ -230,14 +230,14 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config if (boost::filesystem::exists(confParam.gainCalibFile)) { LOG(INFO) << "Loading tpc gain correction from file " << confParam.gainCalibFile; const auto* gainMap = o2::tpc::utils::readCalPads(confParam.gainCalibFile, "GainMap")[0]; - processAttributes->tpcCalibration.reset(new TPCCFCalibration{*gainMap}); + processAttributes->tpcPadGainCalib.reset(new TPCPadGainCalib{*gainMap}); } else { if (not confParam.gainCalibFile.empty()) { LOG(WARN) << "Couldn't find tpc gain correction file " << confParam.gainCalibFile << ". Not applying any gain correction."; } - processAttributes->tpcCalibration.reset(new TPCCFCalibration{}); + processAttributes->tpcPadGainCalib.reset(new TPCPadGainCalib{}); } - config.configCalib.tpcCalibration = processAttributes->tpcCalibration.get(); + config.configCalib.tpcPadGain = processAttributes->tpcPadGainCalib.get(); // Sample code what needs to be done for the TRD Geometry, when we extend this to TRD tracking. /*o2::base::GeometryManager::loadGeometry(); diff --git a/GPU/GPUTracking/Base/GPUConstantMem.h b/GPU/GPUTracking/Base/GPUConstantMem.h index 115e957ee08b1..d498be62793b1 100644 --- a/GPU/GPUTracking/Base/GPUConstantMem.h +++ b/GPU/GPUTracking/Base/GPUConstantMem.h @@ -136,7 +136,7 @@ GPUdi() void GPUProcessor::raiseError(unsigned int code, unsigned int param1, un #if defined(GPUCA_NOCOMPAT_ALLCINT) && (!defined(GPUCA_GPULIBRARY) || !defined(GPUCA_ALIROOT_LIB)) && defined(HAVE_O2HEADERS) GPUd() float GPUTPCClusterFinder::getGainCorrection(tpccf::Row row, tpccf::Pad pad) const { - return GetConstantMem()->calibObjects.tpcCalibration->getGainCorrection(mISlice, row, pad); + return GetConstantMem()->calibObjects.tpcPadGain->getGainCorrection(mISlice, row, pad); } #endif diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index 06b61a85d27cc..c948f43e8bbe0 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -69,7 +69,7 @@ namespace gpu { class TPCFastTransform; class TPCdEdxCalibrationSplines; -struct TPCCFCalibration; +struct TPCPadGainCalib; } // namespace gpu } // namespace GPUCA_NAMESPACE @@ -175,7 +175,7 @@ struct GPUCalibObjectsTemplate { typename S<o2::base::MatLayerCylSet>::type* matLUT = nullptr; typename S<o2::trd::GeometryFlat>::type* trdGeometry = nullptr; typename S<TPCdEdxCalibrationSplines>::type* dEdxSplines = nullptr; - typename S<TPCCFCalibration>::type* tpcCalibration = nullptr; + typename S<TPCPadGainCalib>::type* tpcPadGain = nullptr; }; typedef GPUCalibObjectsTemplate<DefaultPtr> GPUCalibObjects; typedef GPUCalibObjectsTemplate<ConstPtr> GPUCalibObjectsConst; diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index a3c60e6277e6d..adead49fe7227 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -172,7 +172,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) TPCClusterFinder/GPUTPCCFMCLabelFlattener.cxx TPCClusterFinder/GPUTPCCFDecodeZS.cxx TPCClusterFinder/GPUTPCCFGather.cxx - TPCClusterFinder/TPCCFCalibration.cxx + TPCClusterFinder/TPCPadGainCalib.cxx dEdx/TPCdEdxCalibrationSplines.cxx Refit/GPUTrackingRefit.cxx) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 5104ccb9a012f..717a9d25236fd 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -255,7 +255,7 @@ bool GPUChainTracking::ValidateSteps() GPUError("Cannot run dE/dx without calibration splines"); return false; } - if ((GetRecoSteps() & GPUDataTypes::RecoStep::TPCClusterFinding) && processors()->calibObjects.tpcCalibration == nullptr) { + if ((GetRecoSteps() & GPUDataTypes::RecoStep::TPCClusterFinding) && processors()->calibObjects.tpcPadGain == nullptr) { GPUError("Cannot run gain calibration without calibration object"); return false; } @@ -383,8 +383,8 @@ int GPUChainTracking::Init() memcpy((void*)mFlatObjectsShadow.mCalibObjects.trdGeometry, (const void*)processors()->calibObjects.trdGeometry, sizeof(*processors()->calibObjects.trdGeometry)); mFlatObjectsShadow.mCalibObjects.trdGeometry->clearInternalBufferPtr(); } - if (processors()->calibObjects.tpcCalibration) { - memcpy((void*)mFlatObjectsShadow.mCalibObjects.tpcCalibration, (const void*)processors()->calibObjects.tpcCalibration, sizeof(*processors()->calibObjects.tpcCalibration)); + if (processors()->calibObjects.tpcPadGain) { + memcpy((void*)mFlatObjectsShadow.mCalibObjects.tpcPadGain, (const void*)processors()->calibObjects.tpcPadGain, sizeof(*processors()->calibObjects.tpcPadGain)); } #endif TransferMemoryResourceLinkToGPU(RecoStep::NoRecoStep, mFlatObjectsShadow.mMemoryResFlat); @@ -439,8 +439,8 @@ void* GPUChainTracking::GPUTrackingFlatObjects::SetPointersFlatObjects(void* mem computePointerWithAlignment(mem, mCalibObjects.fastTransform, 1); computePointerWithAlignment(mem, mTpcTransformBuffer, mChainTracking->GetTPCTransform()->getFlatBufferSize()); } - if (mChainTracking->GetTPCCalibration()) { - computePointerWithAlignment(mem, mCalibObjects.tpcCalibration, 1); + if (mChainTracking->GetTPCPadGainCalib()) { + computePointerWithAlignment(mem, mCalibObjects.tpcPadGain, 1); } #ifdef HAVE_O2HEADERS if (mChainTracking->GetdEdxSplines()) { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 61e942cf1544e..3d93cb85a080d 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -152,7 +152,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega // Getters / setters for parameters const TPCFastTransform* GetTPCTransform() const { return processors()->calibObjects.fastTransform; } - const TPCCFCalibration* GetTPCCalibration() const { return processors()->calibObjects.tpcCalibration; } + const TPCPadGainCalib* GetTPCPadGainCalib() const { return processors()->calibObjects.tpcPadGain; } const TPCdEdxCalibrationSplines* GetdEdxSplines() const { return processors()->calibObjects.dEdxSplines; } const o2::base::MatLayerCylSet* GetMatLUT() const { return processors()->calibObjects.matLUT; } const GPUTRDGeometry* GetTRDGeometry() const { return (GPUTRDGeometry*)processors()->calibObjects.trdGeometry; } @@ -161,7 +161,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void SetMatLUT(std::unique_ptr<o2::base::MatLayerCylSet>&& lut); void SetTRDGeometry(std::unique_ptr<o2::trd::GeometryFlat>&& geo); void SetTPCFastTransform(const TPCFastTransform* tpcFastTransform) { processors()->calibObjects.fastTransform = tpcFastTransform; } - void SetTPCCFCalibration(const TPCCFCalibration* tpcCalibration) { processors()->calibObjects.tpcCalibration = tpcCalibration; } + void SetTPCPadGainCalib(const TPCPadGainCalib* tpcPadGainCalib) { processors()->calibObjects.tpcPadGain = tpcPadGainCalib; } void SetdEdxSplines(const TPCdEdxCalibrationSplines* dEdxSplines) { processors()->calibObjects.dEdxSplines = dEdxSplines; } void SetMatLUT(const o2::base::MatLayerCylSet* lut) { processors()->calibObjects.matLUT = lut; } void SetTRDGeometry(const o2::trd::GeometryFlat* geo) { processors()->calibObjects.trdGeometry = geo; } @@ -231,7 +231,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega // Ptr to detector / calibration objects std::unique_ptr<TPCFastTransform> mTPCFastTransformU; // Global TPC fast transformation object - std::unique_ptr<TPCCFCalibration> mTPCCalibrationU; // TPC gain calibration and cluster finder parameters + std::unique_ptr<TPCPadGainCalib> mTPCPadGainCalibU; // TPC gain calibration and cluster finder parameters std::unique_ptr<TPCdEdxCalibrationSplines> mdEdxSplinesU; // TPC dEdx calibration splines std::unique_ptr<o2::base::MatLayerCylSet> mMatLUTU; // Material Lookup Table std::unique_ptr<o2::trd::GeometryFlat> mTRDGeometryU; // TRD Geometry diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index ed94ad362d9c3..e688512a832a7 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -224,10 +224,10 @@ void GPUChainTracking::DumpSettings(const char* dir) f += "tpctransform.dump"; DumpFlatObjectToFile(processors()->calibObjects.fastTransform, f.c_str()); } - if (processors()->calibObjects.tpcCalibration != nullptr) { + if (processors()->calibObjects.tpcPadGain != nullptr) { f = dir; - f += "tpccalibration.dump"; - DumpStructToFile(processors()->calibObjects.tpcCalibration, f.c_str()); + f += "tpcpadgaincalib.dump"; + DumpStructToFile(processors()->calibObjects.tpcPadGain, f.c_str()); } #ifdef HAVE_O2HEADERS if (processors()->calibObjects.dEdxSplines != nullptr) { @@ -257,9 +257,9 @@ void GPUChainTracking::ReadSettings(const char* dir) mTPCFastTransformU = ReadFlatObjectFromFile<TPCFastTransform>(f.c_str()); processors()->calibObjects.fastTransform = mTPCFastTransformU.get(); f = dir; - f += "tpccalibration.dump"; - mTPCCalibrationU = ReadStructFromFile<TPCCFCalibration>(f.c_str()); - processors()->calibObjects.tpcCalibration = mTPCCalibrationU.get(); + f += "tpcpadgaincalib.dump"; + mTPCPadGainCalibU = ReadStructFromFile<TPCPadGainCalib>(f.c_str()); + processors()->calibObjects.tpcPadGain = mTPCPadGainCalibU.get(); #ifdef HAVE_O2HEADERS f = dir; f += "dedxsplines.dump"; diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 2c63a5528ed93..d5df395ed5d21 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -53,7 +53,7 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) } mRec->SetSettings(&mConfig->configEvent, &mConfig->configReconstruction, &mConfig->configProcessing, &mConfig->configWorkflow); mChain->SetTPCFastTransform(mConfig->configCalib.fastTransform); - mChain->SetTPCCFCalibration(mConfig->configCalib.tpcCalibration); + mChain->SetTPCPadGainCalib(mConfig->configCalib.tpcPadGain); mChain->SetdEdxSplines(mConfig->configCalib.dEdxSplines); mChain->SetMatLUT(mConfig->configCalib.matLUT); mChain->SetTRDGeometry(mConfig->configCalib.trdGeometry); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx index 0f22cd47aca72..7678c68ce1224 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx @@ -16,7 +16,7 @@ #include "Array2D.h" #include "CfUtils.h" #include "PackedCharge.h" -#include "TPCCFCalibration.h" +#include "TPCPadGainCalib.h" using namespace GPUCA_NAMESPACE::gpu; using namespace GPUCA_NAMESPACE::gpu::tpccf; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index abec35440f3a5..90237b7fe47ea 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -18,7 +18,7 @@ #include "GPUProcessor.h" #include "GPUDataTypes.h" #include "CfFragment.h" -#include "TPCCFCalibration.h" +#include "TPCPadGainCalib.h" namespace o2 { @@ -44,7 +44,7 @@ class Digit; namespace GPUCA_NAMESPACE::gpu { struct GPUTPCClusterMCInterim; -struct TPCCFCalibration; +struct TPCPadGainCalib; struct ChargePos; diff --git a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.cxx b/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.cxx similarity index 83% rename from GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.cxx rename to GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.cxx index 0f260cb76ee5b..a2cad4760ada0 100644 --- a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.cxx @@ -8,10 +8,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file TPCCFCalibration.cxx +/// \file TPCPadGainCalib.cxx /// \author Felix Weiglhofer -#include "TPCCFCalibration.h" +#include "TPCPadGainCalib.h" #include "GPUTPCGeometry.h" #include "DataFormatsTPC/Constants.h" @@ -19,7 +19,7 @@ using namespace GPUCA_NAMESPACE::gpu; -TPCCFCalibration::TPCCFCalibration() +TPCPadGainCalib::TPCPadGainCalib() { GPUTPCGeometry geo{}; int offset = 0; @@ -29,7 +29,7 @@ TPCCFCalibration::TPCCFCalibration() } } -TPCCFCalibration::TPCCFCalibration(const o2::tpc::CalDet<float>& gainMap) : TPCCFCalibration() +TPCPadGainCalib::TPCPadGainCalib(const o2::tpc::CalDet<float>& gainMap) : TPCPadGainCalib() { for (int sector = 0; sector < o2::tpc::constants::MAXSECTOR; sector++) { for (int p = 0; p < TPC_PADS_IN_SECTOR; p++) { diff --git a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h b/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.h similarity index 89% rename from GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h rename to GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.h index 71ffd48e93f27..40b975eef2369 100644 --- a/GPU/GPUTracking/TPCClusterFinder/TPCCFCalibration.h +++ b/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.h @@ -8,11 +8,11 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file TPCCFCalibration.h +/// \file TPCPadGainCalib.h /// \author Felix Weiglhofer -#ifndef O2_GPU_TPC_CF_CALIBRATION_H -#define O2_GPU_TPC_CF_CALIBRATION_H +#ifndef O2_GPU_TPC_PAD_GAIN_CALIB_H +#define O2_GPU_TPC_PAD_GAIN_CALIB_H #include "clusterFinderDefs.h" #include "GPUCommonMath.h" @@ -40,11 +40,11 @@ struct TPCPadGainCorrectionStepNum<unsigned short> { static constexpr int value = 65534; }; -struct TPCCFCalibration { +struct TPCPadGainCalib { public: #ifndef GPUCA_GPUCODE - TPCCFCalibration(); - TPCCFCalibration(const o2::tpc::CalDet<float>&); + TPCPadGainCalib(); + TPCPadGainCalib(const o2::tpc::CalDet<float>&); #endif // Deal with pad gain correction from here on @@ -60,7 +60,7 @@ struct TPCCFCalibration { private: template <typename T = unsigned short> - class PadGainCorrection + class SectorPadGainCorrection { public: @@ -68,7 +68,7 @@ struct TPCCFCalibration { constexpr static float MaxCorrectionFactor = 2.f; constexpr static int NumOfSteps = TPCPadGainCorrectionStepNum<T>::value; - GPUdi() PadGainCorrection() + GPUdi() SectorPadGainCorrection() { reset(); } @@ -119,7 +119,7 @@ struct TPCCFCalibration { }; unsigned short mPadOffsetPerRow[TPC_NUM_OF_ROWS]; - PadGainCorrection<unsigned short> mGainCorrection[TPC_SECTORS]; + SectorPadGainCorrection<unsigned short> mGainCorrection[TPC_SECTORS]; GPUdi() unsigned short globalPad(tpccf::Row row, tpccf::Pad pad) const { From de481aaed1a6a1fa09b22dfa9ef2b7c9d53e2f60 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 2 Dec 2020 15:53:09 +0100 Subject: [PATCH 1493/1751] GPU Config: Add short/unsigned short as possible configuration value type --- GPU/GPUTracking/Standalone/utils/qconfig.cxx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/GPU/GPUTracking/Standalone/utils/qconfig.cxx b/GPU/GPUTracking/Standalone/utils/qconfig.cxx index 083b7da828040..7489f5c416b62 100644 --- a/GPU/GPUTracking/Standalone/utils/qconfig.cxx +++ b/GPU/GPUTracking/Standalone/utils/qconfig.cxx @@ -374,6 +374,24 @@ inline int qAddOptionType<unsigned int>(qConfigSettings<unsigned int>& settings, settings.doDefault); } template <> +inline int qAddOptionType<short>(qConfigSettings<short>& settings, short& ref, int& i, const char** argv, const int argc, short /*def*/) +{ + return qAddOptionGeneric<short>( + settings, ref, i, argv, argc, settings.set, [](const char* a) -> short { + return atoi(a); + }, + settings.doDefault); +} +template <> +inline int qAddOptionType<unsigned short>(qConfigSettings<unsigned short>& settings, unsigned short& ref, int& i, const char** argv, const int argc, unsigned short /*def*/) +{ + return qAddOptionGeneric<unsigned short>( + settings, ref, i, argv, argc, settings.set, [](const char* a) -> unsigned short { + return strtoul(a, nullptr, 0); + }, + settings.doDefault); +} +template <> inline int qAddOptionType<long>(qConfigSettings<long>& settings, long& ref, int& i, const char** argv, const int argc, long /*def*/) { return qAddOptionGeneric<long>( From 92023d81e454b2d8450e816cf19786e0f35f6a4e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 2 Dec 2020 15:54:37 +0100 Subject: [PATCH 1494/1751] GPU: Use make depend before normal make for standalone benchmark to avoid cmake IMPLICIT_DEPENDS problem --- GPU/GPUTracking/Standalone/cmake/makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Standalone/cmake/makefile b/GPU/GPUTracking/Standalone/cmake/makefile index d640ad8fa4552..698f0f58d3b20 100644 --- a/GPU/GPUTracking/Standalone/cmake/makefile +++ b/GPU/GPUTracking/Standalone/cmake/makefile @@ -1,4 +1,5 @@ all: + +$(MAKE) -C build depend +$(MAKE) -C build install clean: From e1df1e5839fff7f0e22bd2fd37aedd37705bc921 Mon Sep 17 00:00:00 2001 From: Timo Wilken <timo.wilken@cern.ch> Date: Wed, 2 Dec 2020 20:12:25 +0000 Subject: [PATCH 1495/1751] Fix clean-test.yml: need apt update (#4974) --- .github/workflows/clean-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clean-test.yml b/.github/workflows/clean-test.yml index 69b73d51ab3d5..270ea519191e2 100644 --- a/.github/workflows/clean-test.yml +++ b/.github/workflows/clean-test.yml @@ -28,7 +28,8 @@ jobs: python-version: 3.7 - name: Install ali-bot run: | - sudo apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev + sudo apt-get update -y + sudo apt-get install -y libsasl2-dev python-dev libldap2-dev libssl-dev python -m pip install --upgrade pip pip install git+https://github.com/alisw/ali-bot@master - uses: octokit/graphql-action@v2.x From 246ad97f976cf447d52c52bb3402d8151e28b87f Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Wed, 2 Dec 2020 21:13:27 +0100 Subject: [PATCH 1496/1751] DPL: add compile-time string concat and support std::string_view (#4975) --- .../Core/include/Framework/StringHelpers.h | 57 +++++++++++++++---- Framework/Core/test/test_StringHelpers.cxx | 18 ++++++ 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/Framework/Core/include/Framework/StringHelpers.h b/Framework/Core/include/Framework/StringHelpers.h index 7bd1f17760b2b..159d1bbf6ff42 100644 --- a/Framework/Core/include/Framework/StringHelpers.h +++ b/Framework/Core/include/Framework/StringHelpers.h @@ -14,6 +14,7 @@ #include <cstdint> #include <utility> #include <type_traits> +#include <string_view> // CRC32 Table (zlib polynomial) static constexpr uint32_t crc_table[256] = {0x0L, 0x77073096L, 0xee0e612cL, @@ -102,6 +103,15 @@ constexpr bool is_const_str_v(T) return is_const_str<T>::value; } +template <char... chars1, char... chars2> +constexpr auto operator+(const ConstStr<chars1...>&, const ConstStr<chars2...>&) +{ + return ConstStr<chars1..., chars2...>{}; +} + +namespace const_str_details +{ + template <typename T, std::size_t... Is> constexpr auto as_chars_impl(std::index_sequence<Is...>) { @@ -112,18 +122,45 @@ template <typename T> constexpr auto as_chars() { return as_chars_impl<T>( - std::make_index_sequence<sizeof(T::str()) - 1>{}); + std::make_index_sequence<T::size() - 1>{}); +} + +template <int N> +constexpr const char* const get_str(const char (&str)[N]) +{ + return str; +} + +template <int N> +constexpr const int get_size(const char (&str)[N]) +{ + return N; +} + +constexpr const char* const get_str(const std::string_view& str) +{ + return str.data(); +} + +constexpr const int get_size(const std::string_view& str) +{ + return str.size() + 1; } +} // namespace const_str_details -#define CONST_STR(literal) \ - [] { \ - struct literal_to_chars { \ - static constexpr decltype(auto) str() \ - { \ - return literal; \ - } \ - }; \ - return as_chars<literal_to_chars>(); \ +#define CONST_STR(literal) \ + [] { \ + struct literal_to_chars { \ + static constexpr decltype(auto) str() \ + { \ + return const_str_details::get_str(literal); \ + } \ + static constexpr decltype(auto) size() \ + { \ + return const_str_details::get_size(literal); \ + } \ + }; \ + return const_str_details::as_chars<literal_to_chars>(); \ }() #endif // O2_FRAMEWORK_STRINGHELPERS_H diff --git a/Framework/Core/test/test_StringHelpers.cxx b/Framework/Core/test/test_StringHelpers.cxx index 9e79f05ec005b..d5500f66d7e35 100644 --- a/Framework/Core/test/test_StringHelpers.cxx +++ b/Framework/Core/test/test_StringHelpers.cxx @@ -48,4 +48,22 @@ BOOST_AUTO_TEST_CASE(StringHelpersConstStr) if constexpr (is_const_str_v(myConstStr)) { std::cout << "myConstStr is a compile-time string" << std::endl; } + + auto myConstStr2 = CONST_STR("hello") + CONST_STR("Universe"); + printString(myConstStr2); + static_assert(std::is_same_v<decltype(myConstStr2), ConstStr<'h', 'e', 'l', 'l', 'o', 'U', 'n', 'i', 'v', 'e', 'r', 's', 'e'>>); + + enum ParticleSpecies { + kPion, + kKaon + }; + static constexpr std::string_view hist[] = {"ptDist", "etaDist"}; + static constexpr std::string_view particleSuffix[] = {"_pions", "_kaons"}; + + printString(CONST_STR(hist[0]) + CONST_STR(particleSuffix[kPion])); + printString(CONST_STR(hist[0]) + CONST_STR(particleSuffix[kKaon])); + printString(CONST_STR(hist[1]) + CONST_STR(particleSuffix[kPion])); + printString(CONST_STR(hist[1]) + CONST_STR(particleSuffix[kKaon])); + + BOOST_CHECK_EQUAL(CONST_STR(hist[0]).hash, CONST_STR("ptDist").hash); } From 2acbe99ec52bf46b0734a3c02dc9f15f00d64332 Mon Sep 17 00:00:00 2001 From: nzardosh <nima.zardoshti@cern.ch> Date: Wed, 2 Dec 2020 22:30:15 +0100 Subject: [PATCH 1497/1751] HF PreSelection Changes (#4873) --- Analysis/Core/CMakeLists.txt | 2 + .../Core/include/Analysis/HFConfigurables.h | 61 ++ Analysis/Core/src/AnalysisCoreLinkDef.h | 1 + Analysis/Core/src/HFConfigurables.cxx | 14 + .../include/Analysis/HFSecondaryVertex.h | 22 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 765 +++++++++++++----- 6 files changed, 642 insertions(+), 223 deletions(-) create mode 100644 Analysis/Core/include/Analysis/HFConfigurables.h create mode 100644 Analysis/Core/src/HFConfigurables.cxx diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index 63d608698c184..f931540f2cb3e 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -16,6 +16,7 @@ o2_add_library(AnalysisCore src/AnalysisCut.cxx src/AnalysisCompositeCut.cxx src/TriggerAliases.cxx + src/HFConfigurables.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisTools) o2_target_root_dictionary(AnalysisCore @@ -28,6 +29,7 @@ o2_target_root_dictionary(AnalysisCore include/Analysis/AnalysisCompositeCut.h include/Analysis/TriggerAliases.h include/Analysis/MC.h + include/Analysis/HFConfigurables.h LINKDEF src/AnalysisCoreLinkDef.h) if(FastJet_FOUND) diff --git a/Analysis/Core/include/Analysis/HFConfigurables.h b/Analysis/Core/include/Analysis/HFConfigurables.h new file mode 100644 index 0000000000000..ead5dde738c3d --- /dev/null +++ b/Analysis/Core/include/Analysis/HFConfigurables.h @@ -0,0 +1,61 @@ +// 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. + +// HF Configurable Classes +// +// Authors: Nima Zardoshti + +#ifndef O2_ANALYSIS_HFCONFIGURABLES_H +#define O2_ANALYSIS_HFCONFIGURABLES_H + +#include <TMath.h> + +class HFTrackIndexSkimsCreatorConfigs +{ + public: + HFTrackIndexSkimsCreatorConfigs() = default; + ~HFTrackIndexSkimsCreatorConfigs() = default; + + // 2-prong cuts D0 + double mPtD0Min = 0.; + double mInvMassD0Min = 1.46; + double mInvMassD0Max = 2.26; + double mCPAD0Min = 0.75; + double mImpParProductD0Max = -0.00005; + // 2-prong cuts Jpsi + double mPtJpsiMin = 0.; + double mInvMassJpsiMin = 2.5; + double mInvMassJpsiMax = 4.1; + double mCPAJpsiMin = -2; + double mImpParProductJpsiMax = 1000.; + // 3-prong cuts - D+ + double mPtDPlusMin = 0.; + double mInvMassDPlusMin = 1.7; + double mInvMassDPlusMax = 2.05; + double mCPADPlusMin = 0.5; + double mDecLenDPlusMin = 0.; + // 3-prong cuts - Lc + double mPtLcMin = 0.; + double mInvMassLcMin = 2.1; + double mInvMassLcMax = 2.5; + double mCPALcMin = 0.5; + double mDecLenLcMin = 0.; + // 3-prong cuts - Ds + double mPtDsMin = 0.; + double mInvMassDsMin = 1.7; + double mInvMassDsMax = 2.2; + double mCPADsMin = 0.5; + double mDecLenDsMin = 0.; + + private: + ClassDef(HFTrackIndexSkimsCreatorConfigs, 1); +}; + +#endif diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index ed2833df8a9f0..c550c9a41d98a 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -20,3 +20,4 @@ #pragma link C++ class HistogramManager + ; #pragma link C++ class AnalysisCut + ; #pragma link C++ class AnalysisCompositeCut + ; +#pragma link C++ class HFTrackIndexSkimsCreatorConfigs + ; diff --git a/Analysis/Core/src/HFConfigurables.cxx b/Analysis/Core/src/HFConfigurables.cxx new file mode 100644 index 0000000000000..fb283c8145718 --- /dev/null +++ b/Analysis/Core/src/HFConfigurables.cxx @@ -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. + +// HF Configurable Classes +// +// Authors: Nima Zardoshti +#include "Analysis/HFConfigurables.h" diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 26a16a6e7d52c..58d6a1b9076bc 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -25,15 +25,13 @@ namespace o2::aod { namespace hf_seltrack { -DECLARE_SOA_COLUMN(IsSel2Prong, isSel2Prong, int); -DECLARE_SOA_COLUMN(IsSel3Prong, isSel3Prong, int); +DECLARE_SOA_COLUMN(IsSelProng, isSelProng, int); DECLARE_SOA_COLUMN(DCAPrim0, dcaPrim0, float); DECLARE_SOA_COLUMN(DCAPrim1, dcaPrim1, float); } // namespace hf_seltrack DECLARE_SOA_TABLE(HFSelTrack, "AOD", "HFSELTRACK", - hf_seltrack::IsSel2Prong, - hf_seltrack::IsSel3Prong, + hf_seltrack::IsSelProng, hf_seltrack::DCAPrim0, hf_seltrack::DCAPrim1); @@ -50,6 +48,13 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, BigTracks, "fIndex1"); DECLARE_SOA_INDEX_COLUMN_FULL(Index2, index2, int, BigTracks, "fIndex2"); DECLARE_SOA_INDEX_COLUMN_FULL(Index3, index3, int, BigTracks, "fIndex3"); DECLARE_SOA_COLUMN(HFflag, hfflag, uint8_t); + +DECLARE_SOA_COLUMN(D0ToKPiFlag, d0ToKPiFlag, uint8_t); +DECLARE_SOA_COLUMN(JpsiToEEFlag, jpsiToEEFlag, uint8_t); + +DECLARE_SOA_COLUMN(DPlusPiKPiFlag, dPlusPiKPiFlag, uint8_t); +DECLARE_SOA_COLUMN(LcPKPiFlag, lcPKPiFlag, uint8_t); +DECLARE_SOA_COLUMN(DsKKPiFlag, dsKKPiFlag, uint8_t); } // namespace hf_track_index DECLARE_SOA_TABLE(HfTrackIndexProng2, "AOD", "HFTRACKIDXP2", @@ -57,12 +62,21 @@ DECLARE_SOA_TABLE(HfTrackIndexProng2, "AOD", "HFTRACKIDXP2", hf_track_index::Index1Id, hf_track_index::HFflag); +DECLARE_SOA_TABLE(HfCutStatusProng2, "AOD", "HFCUTSTATUSP2", + hf_track_index::D0ToKPiFlag, + hf_track_index::JpsiToEEFlag); + DECLARE_SOA_TABLE(HfTrackIndexProng3, "AOD", "HFTRACKIDXP3", hf_track_index::Index0Id, hf_track_index::Index1Id, hf_track_index::Index2Id, hf_track_index::HFflag); +DECLARE_SOA_TABLE(HfCutStatusProng3, "AOD", "HFCUTSTATUSP3", + hf_track_index::DPlusPiKPiFlag, + hf_track_index::LcPKPiFlag, + hf_track_index::DsKKPiFlag); + // general decay properties namespace hf_cand { diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index f203f9c6e9d17..8fc8e9261a6a6 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -13,12 +13,17 @@ /// /// \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN /// \author Vít Kučera <vit.kucera@cern.ch>, CERN +/// \author Nima Zardoshti <nima.zardoshti@cern.ch>, CERN #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" #include "Analysis/HFSecondaryVertex.h" #include "Analysis/trackUtilities.h" +#include "Analysis/HFConfigurables.h" +//#include "Analysis/Centrality.h" +#include "Framework/HistogramRegistry.h" +#include <algorithm> using namespace o2; using namespace o2::framework; @@ -32,99 +37,105 @@ struct SelectTracks { Configurable<double> d_bz{"d_bz", 5., "bz field"}; // quality cut Configurable<bool> doCutQuality{"doCutQuality", true, "apply quality cuts"}; - Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, "min. number of TPC clusters"}; + Configurable<int> d_tpcnclsfound{"d_tpcnclsfound", 70, ">= min. number of TPC clusters needed"}; // 2-prong cuts - Configurable<double> ptmintrack_2prong{"ptmintrack_2prong", -1., "min. track pT"}; - Configurable<double> dcatoprimxymin_2prong{"dcatoprimxymin_2prong", 0., "min. DCAXY to prim. vtx."}; - Configurable<double> etamax_2prong{"etamax_2prong", 999., "max. pseudorapidity"}; + Configurable<double> ptmintrack_2prong{"ptmintrack_2prong", -1., "min. track pT for 2 prong candidate"}; + Configurable<double> dcatoprimxy_2prong_maxpt{"dcatoprimxymin_2prong_minpt", 2., "max pt cut for min. DCAXY to prim. vtx. for 2 prong candidate"}; + Configurable<double> dcatoprimxymin_2prong{"dcatoprimxymin_2prong", 0., "min. DCAXY to prim. vtx. for 2 prong candidate"}; + Configurable<double> dcatoprimxymax_2prong{"dcatoprimxymax_2prong", 1.0, "max. DCAXY to prim. vtx. for 2 prong candidate"}; + Configurable<double> etamax_2prong{"etamax_2prong", 4., "max. pseudorapidity for 2 prong candidate"}; // 3-prong cuts - Configurable<double> ptmintrack_3prong{"ptmintrack_3prong", -1., "min. track pT"}; - Configurable<double> dcatoprimxymin_3prong{"dcatoprimxymin_3prong", 0., "min. DCAXY to prim. vtx."}; - Configurable<double> etamax_3prong{"etamax_3prong", 999., "max. pseudorapidity"}; - - OutputObj<TH1F> hpt_nocuts{TH1F("hpt_nocuts", "all tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", 100, 0., 10.)}; - // 2-prong histograms - OutputObj<TH1F> hpt_cuts_2prong{TH1F("hpt_cuts_2prong", "tracks selected for 2-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hdcatoprimxy_cuts_2prong{TH1F("hdcatoprimxy_cuts_2prong", "tracks selected for 2-prong vertexing;DCAxy to prim. vtx. (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> heta_cuts_2prong{TH1F("heta_cuts_2prong", "tracks selected for 2-prong vertexing;#it{#eta};entries", 100, -1., 1.)}; - // 3-prong histograms - OutputObj<TH1F> hpt_cuts_3prong{TH1F("hpt_cuts_3prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hdcatoprimxy_cuts_3prong{TH1F("hdcatoprimxy_cuts_3prong", "tracks selected for 3-prong vertexing;DCAxy to prim. vtx. (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> heta_cuts_3prong{TH1F("heta_cuts_3prong", "tracks selected for 3-prong vertexing;#it{#eta};entries", 100, -1., 1.)}; + Configurable<double> ptmintrack_3prong{"ptmintrack_3prong", -1., "min. track pT for 3 prong candidate"}; + Configurable<double> dcatoprimxy_3prong_maxpt{"dcatoprimxy_3prong_minpt", 2., "max pt cut for min. DCAXY to prim. vtx. for 3 prong candidate"}; + Configurable<double> dcatoprimxymin_3prong{"dcatoprimxymin_3prong", 0., "min. DCAXY to prim. vtx. for 3 prong candidate"}; + Configurable<double> dcatoprimxymax_3prong{"dcatoprimxymax_3prong", 1.0, "max. DCAXY to prim. vtx. for 3 prong candidate"}; + Configurable<double> etamax_3prong{"etamax_3prong", 4., "max. pseudorapidity for 3 prong candidate"}; + + HistogramRegistry registry{ + "registry", + {{"hpt_nocuts", "all tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 100.}}}}, + // 2-prong histograms + {"hpt_cuts_2prong", "tracks selected for 2-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 100.}}}}, + {"hdcatoprimxy_cuts_2prong", "tracks selected for 2-prong vertexing;DCAxy to prim. vtx. (cm);entries", {HistType::kTH1F, {{static_cast<int>(1.2 * dcatoprimxymax_2prong * 100), -1.2 * dcatoprimxymax_2prong, 1.2 * dcatoprimxymax_2prong}}}}, + {"heta_cuts_2prong", "tracks selected for 2-prong vertexing;#it{#eta};entries", {HistType::kTH1F, {{static_cast<int>(1.2 * etamax_2prong * 100), -1.2 * etamax_2prong, 1.2 * etamax_2prong}}}}, + // 3-prong histograms + {"hpt_cuts_3prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 100.}}}}, + {"hdcatoprimxy_cuts_3prong", "tracks selected for 3-prong vertexing;DCAxy to prim. vtx. (cm);entries", {HistType::kTH1F, {{static_cast<int>(1.2 * dcatoprimxymax_3prong) * 100, -1.2 * dcatoprimxymax_3prong, 1.2 * dcatoprimxymax_3prong}}}}, + {"heta_cuts_3prong", "tracks selected for 3-prong vertexing;#it{#eta};entries", {HistType::kTH1F, {{static_cast<int>(1.2 * etamax_3prong * 100), -1.2 * etamax_3prong, 1.2 * etamax_3prong}}}}}}; void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra> const& tracks) { math_utils::Point3D<float> vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); for (auto& track : tracks) { - int status_2prong = 1; // selection flag - int status_3prong = 1; // selection flag + int status_prong = 3; // selection flag , 2 bits on + + auto trackPt = track.pt(); if (b_dovalplots) { - hpt_nocuts->Fill(track.pt()); + registry.get<TH1>("hpt_nocuts")->Fill(trackPt); } // pT cut - if (track.pt() < ptmintrack_2prong) { - status_2prong = 0; + if (trackPt < ptmintrack_2prong) { + status_prong = status_prong & ~(1 << 0); // the bitwise operation & ~(1 << n) will set the nth bit to 0 } - if (track.pt() < ptmintrack_3prong) { - status_3prong = 0; + if (trackPt < ptmintrack_3prong) { + status_prong = status_prong & ~(1 << 1); } + auto trackEta = track.eta(); // eta cut - if (status_2prong && abs(track.eta()) > etamax_2prong) { - status_2prong = 0; + if ((status_prong & (1 << 0)) && abs(trackEta) > etamax_2prong) { + status_prong = status_prong & ~(1 << 0); } - if (status_3prong && abs(track.eta()) > etamax_3prong) { - status_3prong = 0; + if ((status_prong & (1 << 1)) && abs(trackEta) > etamax_3prong) { + status_prong = status_prong & ~(1 << 1); } // quality cut - if (doCutQuality && (status_2prong || status_3prong)) { + if (doCutQuality && status_prong > 0) { // FIXME to make a more complete selection e.g track.flags() & o2::aod::track::TPCrefit && track.flags() & o2::aod::track::GoldenChi2 && UChar_t clustermap = track.itsClusterMap(); - bool isselected = track.tpcNClsFound() >= d_tpcnclsfound && - track.flags() & o2::aod::track::ITSrefit && - (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)); - if (!isselected) { - status_2prong = 0; - status_3prong = 0; + if (!(track.tpcNClsFound() >= d_tpcnclsfound && + track.flags() & o2::aod::track::ITSrefit && + (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)))) { + status_prong = 0; } } // DCA cut array<float, 2> dca; - if (status_2prong || status_3prong) { + if (status_prong > 0) { + double dcatoprimxymin_2prong_ptdep = dcatoprimxymin_2prong * TMath::Max(0., (1 - TMath::Floor(trackPt / dcatoprimxy_2prong_maxpt))); + double dcatoprimxymin_3prong_ptdep = dcatoprimxymin_3prong * TMath::Max(0., (1 - TMath::Floor(trackPt / dcatoprimxy_3prong_maxpt))); auto trackparvar0 = getTrackParCov(track); - bool isprop = trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.); // get impact parameters - if (!isprop) { - status_2prong = 0; - status_3prong = 0; + if (!trackparvar0.propagateParamToDCA(vtxXYZ, d_bz, &dca, 100.)) { // get impact parameters + status_prong = 0; } - if (status_2prong && abs(dca[0]) < dcatoprimxymin_2prong) { - status_2prong = 0; + if ((status_prong & (1 << 0)) && (abs(dca[0]) < dcatoprimxymin_2prong_ptdep || abs(dca[0]) > dcatoprimxymax_2prong)) { + status_prong = status_prong & ~(1 << 0); } - if (status_3prong && abs(dca[0]) < dcatoprimxymin_3prong) { - status_3prong = 0; + if ((status_prong & (1 << 1)) && (abs(dca[0]) < dcatoprimxymin_3prong_ptdep || abs(dca[0]) > dcatoprimxymax_3prong)) { + status_prong = status_prong & ~(1 << 1); } } // fill histograms if (b_dovalplots) { - if (status_2prong == 1) { - hpt_cuts_2prong->Fill(track.pt()); - hdcatoprimxy_cuts_2prong->Fill(dca[0]); - heta_cuts_2prong->Fill(track.eta()); + if (status_prong & (1 << 0)) { + registry.get<TH1>("hpt_cuts_2prong")->Fill(trackPt); + registry.get<TH1>("hdcatoprimxy_cuts_2prong")->Fill(dca[0]); + registry.get<TH1>("heta_cuts_2prong")->Fill(trackEta); } - if (status_3prong == 1) { - hpt_cuts_3prong->Fill(track.pt()); - hdcatoprimxy_cuts_3prong->Fill(dca[0]); - heta_cuts_3prong->Fill(track.eta()); + if (status_prong & (1 << 1)) { + registry.get<TH1>("hpt_cuts_3prong")->Fill(trackPt); + registry.get<TH1>("hdcatoprimxy_cuts_3prong")->Fill(dca[0]); + registry.get<TH1>("heta_cuts_3prong")->Fill(trackEta); } } // fill table row - rowSelectedTrack(status_2prong, status_3prong, dca[0], dca[1]); + rowSelectedTrack(status_prong, dca[0], dca[1]); } } }; @@ -132,68 +143,79 @@ struct SelectTracks { /// Pre-selection of 2-prong and 3-prong secondary vertices struct HFTrackIndexSkimsCreator { Produces<aod::HfTrackIndexProng2> rowTrackIndexProng2; + Produces<aod::HfCutStatusProng2> rowProng2CutStatus; Produces<aod::HfTrackIndexProng3> rowTrackIndexProng3; + Produces<aod::HfCutStatusProng3> rowProng3CutStatus; + //Configurable<int> nCollsMax{"nCollsMax", -1, "Max collisions per file"}; //can be added to run over limited collisions per file - for tesing purposes Configurable<bool> b_dovalplots{"b_dovalplots", true, "fill histograms"}; Configurable<int> do3prong{"do3prong", 0, "do 3 prong"}; // event selection Configurable<int> triggerindex{"triggerindex", -1, "trigger index"}; // vertexing parameters - Configurable<double> d_bz{"d_bz", 5., "magnetic field"}; + Configurable<double> d_bz{"d_bz", 5., "magnetic field kG"}; Configurable<bool> b_propdca{"b_propdca", true, "create tracks version propagated to PCA"}; Configurable<double> d_maxr{"d_maxr", 200., "reject PCA's above this radius"}; Configurable<double> d_maxdzini{"d_maxdzini", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; Configurable<double> d_minparamchange{"d_minparamchange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable<double> d_minrelchi2change{"d_minrelchi2change", 0.9, "stop iterations if chi2/chi2old > this"}; - // 2-prong cuts - Configurable<double> cut2ProngPtCandMin{"cut2ProngPtCandMin", -1., "min. pT of the 2-prong candidate"}; - Configurable<double> cut2ProngInvMassD0Min{"cut2ProngInvMassD0Min", -1., "min. D0 candidate invariant mass"}; - Configurable<double> cut2ProngInvMassD0Max{"cut2ProngInvMassD0Max", -1., "max. D0 candidate invariant mass"}; - Configurable<double> cut2ProngCPAMin{"cut2ProngCPAMin", -2., "min. cosine of pointing angle"}; - Configurable<double> cut2ProngImpParProductMax{"cut2ProngImpParProductMax", 100., "max. product of imp. par. of D0 candidate prongs"}; - // 3-prong cuts - Configurable<double> cut3ProngPtCandMin{"cut3ProngPtCandMin", -1., "min. pT of the 3-prong candidate"}; - Configurable<double> cut3ProngInvMassDPlusMin{"cut3ProngInvMassDPlusMin", 1.5, "min. D+ candidate invariant mass"}; - Configurable<double> cut3ProngInvMassDPlusMax{"cut3ProngInvMassDPlusMax", 2.1, "min. D+ candidate invariant mass"}; - Configurable<double> cut3ProngCPAMin{"cut3ProngCPAMin", -2., "min. cosine of pointing angle"}; - Configurable<double> cut3ProngDecLenMin{"cut3ProngDecLenMin", -1., "min. decay length"}; - - // 2-prong histograms - OutputObj<TH1F> hvtx2_x{TH1F("hvtx2_x", "2-prong candidates;#it{x}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx2_y{TH1F("hvtx2_y", "2-prong candidates;#it{y}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx2_z{TH1F("hvtx2_z", "2-prong candidates;#it{z}_{sec. vtx.} (cm);entries", 1000, -20., 20.)}; - OutputObj<TH1F> hmass2{TH1F("hmass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; - // 3-prong histograms - OutputObj<TH1F> hvtx3_x{TH1F("hvtx3_x", "3-prong candidates;#it{x}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx3_y{TH1F("hvtx3_y", "3-prong candidates;#it{y}_{sec. vtx.} (cm);entries", 1000, -2., 2.)}; - OutputObj<TH1F> hvtx3_z{TH1F("hvtx3_z", "3-prong candidates;#it{z}_{sec. vtx.} (cm);entries", 1000, -20., 20.)}; - OutputObj<TH1F> hmass3{TH1F("hmass3", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 2.1)}; - - /* - // Counter histograms - OutputObj<TH2F> hNCand2ProngVsNTracks{TH2F("hNCand2ProngVsNTracks", "2-prong candidates;# of tracks;# of candidates;entries", 1000, 0., 1000., 1000, 0., 10000.)}; - OutputObj<TH2F> hNCand3ProngVsNTracks{TH2F("hNCand3ProngVsNTracks", "3-prong candidates;# of tracks;# of candidates;entries", 1000, 0., 1000., 1000, 0., 10000.)}; - OutputObj<TH1F> hNCand2Prong{TH1F("hNCand2Prong", "2-prong candidates;# of candidates;entries", 1000, 0., 10000.)}; - OutputObj<TH1F> hNCand3Prong{TH1F("hNCand3Prong", "3-prong candidates;# of candidates;entries", 1000, 0., 10000.)}; - OutputObj<TH1F> hNTracks{TH1F("hNTracks", ";# of tracks;entries", 1000, 0., 1000.)}; - */ - - Filter filterSelectTracks = (aod::hf_seltrack::isSel2Prong == 1); + Configurable<HFTrackIndexSkimsCreatorConfigs> configs{"configs", {}, "configurables"}; + Configurable<bool> b_debug{"b_debug", false, "debug mode"}; + + HistogramRegistry registry{ + "registry", + {{"hNTracks", ";# of tracks;entries", {HistType::kTH1F, {{2500, 0., 25000.}}}}, + //2prong histograms + {"hvtx2_x", "2-prong candidates;#it{x}_{sec. vtx.} (cm);entries", {HistType::kTH1F, {{1000, -2., 2.}}}}, + {"hvtx2_y", "2-prong candidates;#it{y}_{sec. vtx.} (cm);entries", {HistType::kTH1F, {{1000, -2., 2.}}}}, + {"hvtx2_z", "2-prong candidates;#it{z}_{sec. vtx.} (cm);entries", {HistType::kTH1F, {{1000, -20., 20.}}}}, + {"hNCand2Prong", "2-prong candidates preselected;# of candidates;entries", {HistType::kTH1F, {{2000, 0., 200000.}}}}, + {"hNCand2ProngVsNTracks", "2-prong candidates preselected;# of selected tracks;# of candidates;entries", {HistType::kTH2F, {{2500, 0., 25000.}, {2000, 0., 200000.}}}}, + {"hmassD0", "D0 candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}, + {"hmassJpsi", "Jpsi candidates;inv. mass (e+ e-) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}, + //3prong histograms + {"hvtx3_x", "3-prong candidates;#it{x}_{sec. vtx.} (cm);entries", {HistType::kTH1F, {{1000, -2., 2.}}}}, + {"hvtx3_y", "3-prong candidates;#it{y}_{sec. vtx.} (cm);entries", {HistType::kTH1F, {{1000, -2., 2.}}}}, + {"hvtx3_z", "3-prong candidates;#it{z}_{sec. vtx.} (cm);entries", {HistType::kTH1F, {{1000, -20., 20.}}}}, + {"hNCand3Prong", "3-prong candidates preselected;# of candidates;entries", {HistType::kTH1F, {{5000, 0., 500000.}}}}, + {"hNCand3ProngVsNTracks", "3-prong candidates preselected;# of selected tracks;# of candidates;entries", {HistType::kTH2F, {{2500, 0., 25000.}, {5000, 0., 500000.}}}}, + {"hmassDPlus", "D+ candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}, + {"hmassLc", "Lc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}, + {"hmassDs", "Ds candidates;inv. mass (K K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}}}; + + Filter filterSelectTracks = (aod::hf_seltrack::isSelProng > 0); using SelectedTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksCov, aod::TracksExtra, aod::HFSelTrack>>; + // FIXME //Partition<SelectedTracks> tracksPos = aod::track::signed1Pt > 0.f; //Partition<SelectedTracks> tracksNeg = aod::track::signed1Pt < 0.f; double massPi = RecoDecay::getMassPDG(kPiPlus); double massK = RecoDecay::getMassPDG(kKPlus); - double mass2PiK{0.}; - double mass2KPi{0.}; - double mass3PiKPi{0.}; + double massProton = RecoDecay::getMassPDG(kProton); + double massElectron = RecoDecay::getMassPDG(kElectron); - void process(aod::Collision const& collision, - aod::BCs const& bcs, - SelectedTracks const& tracks) + // int nColls{0}; //can be added to run over limited collisions per file - for tesing purposes + + void process( //soa::Join<aod::Collisions, aod::Cents>::iterator const& collision, //FIXME add centrality when option for variations to the process function appears + aod::Collision const& collision, + aod::BCs const& bcs, + SelectedTracks const& tracks) { + + //can be added to run over limited collisions per file - for tesing purposes + /* + if (nCollsMax > -1){ + if (nColls == nCollMax){ + return; + //can be added to run over limited collisions per file - for tesing purposes + } + nColls++; + } + */ + + //auto centrality = collision.centV0M(); //FIXME add centrality when option for variations to the process function appears + int trigindex = int{triggerindex}; if (trigindex != -1) { uint64_t triggerMask = collision.bc().triggerMask(); @@ -203,6 +225,60 @@ struct HFTrackIndexSkimsCreator { } } + //FIXME move above process function + const int n2ProngDecays = 2; //number of two prong hadron types + const int n3ProngDecays = 3; //number of three prong hadron types + int n2ProngBit = TMath::Power(2, n2ProngDecays) - 1; //bit value for 2 prongs candidates where each candidiate is one bit and they are all set it 1 + int n3ProngBit = TMath::Power(2, n3ProngDecays) - 1; //bit value for 3 prongs candidates where each candidiate is one bit and they are all set it 1 + + //retrieve cuts from json - to be made pT dependent when option appears in json + const int nCuts2Prong = 4; //how mant different selections are made on 2 prongs + double cut2ProngPtCandMin[n2ProngDecays] = {configs->mPtD0Min, configs->mPtJpsiMin}; + double cut2ProngInvMassCandMin[n2ProngDecays] = {configs->mInvMassD0Min, configs->mInvMassJpsiMin}; + double cut2ProngInvMassCandMax[n2ProngDecays] = {configs->mInvMassD0Max, configs->mInvMassJpsiMax}; + double cut2ProngCPACandMin[n2ProngDecays] = {configs->mCPAD0Min, configs->mCPAJpsiMin}; + double cut2ProngImpParProductCandMax[n2ProngDecays] = {configs->mImpParProductD0Max, configs->mImpParProductJpsiMax}; + + const int nCuts3Prong = 4; //how mant different selections are made on 3 prongs + double cut3ProngPtCandMin[n3ProngDecays] = {configs->mPtDPlusMin, configs->mPtLcMin, configs->mPtDsMin}; + double cut3ProngInvMassCandMin[n3ProngDecays] = {configs->mInvMassDPlusMin, configs->mInvMassLcMin, configs->mInvMassDsMin}; + double cut3ProngInvMassCandMax[n3ProngDecays] = {configs->mInvMassDPlusMax, configs->mInvMassLcMax, configs->mInvMassDsMax}; + double cut3ProngCPACandMin[n3ProngDecays] = {configs->mCPADPlusMin, configs->mCPALcMin, configs->mCPADsMin}; + double cut3ProngDecLenCandMin[n3ProngDecays] = {configs->mDecLenDPlusMin, configs->mDecLenLcMin, configs->mDecLenDsMin}; + + bool cutStatus2Prong[n2ProngDecays][nCuts2Prong]; + bool cutStatus3Prong[n3ProngDecays][nCuts3Prong]; + int nCutStatus2ProngBit = TMath::Power(2, nCuts2Prong) - 1; //bit value for selection status for each 2 prongs candidate where each selection is one bit and they are all set it 1 + int nCutStatus3ProngBit = TMath::Power(2, nCuts3Prong) - 1; //bit value for selection status for each 2 prongs candidate where each selection is one bit and they are all set it 1 + + //set mass hypothesis 1 for 2 prong + auto arr2Mass1 = array{ + array{massPi, massK}, + array{massElectron, massElectron}}; + + //set mass hypothesis 2 for 2 prong + auto arr2Mass2 = array{ + array{massK, massPi}, + array{massElectron, massElectron}}; + + //set mass hypothesis 1 for 3 prong + auto arr3Mass1 = array{ + array{massPi, massK, massPi}, + array{massProton, massK, massPi}, + array{massK, massK, massPi}}; + + //set mass hypothesis 2 for 3 prong + auto arr3Mass2 = array{ + array{massPi, massK, massPi}, + array{massPi, massK, massProton}, + array{massPi, massK, massK}}; + + double mass2ProngHypo1[n2ProngDecays]; + double mass2ProngHypo2[n2ProngDecays]; + + double mass3ProngHypo1[n3ProngDecays]; + double mass3ProngHypo2[n3ProngDecays]; + // 2-prong vertex fitter o2::vertexing::DCAFitterN<2> df2; df2.setBz(d_bz); @@ -223,8 +299,9 @@ struct HFTrackIndexSkimsCreator { df3.setMinRelChi2Change(d_minrelchi2change); df3.setUseAbsDCA(true); - //auto nCand2 = rowTrackIndexProng2.lastIndex(); - //auto nCand3 = rowTrackIndexProng3.lastIndex(); + //used to calculate number of candidiates per event + auto nCand2 = rowTrackIndexProng2.lastIndex(); + auto nCand3 = rowTrackIndexProng3.lastIndex(); // first loop over positive tracks //for (auto trackPos1 = tracksPos.begin(); trackPos1 != tracksPos.end(); ++trackPos1) { @@ -232,6 +309,14 @@ struct HFTrackIndexSkimsCreator { if (trackPos1.signed1Pt() < 0) { continue; } + bool sel2ProngStatus = true; + bool sel3ProngStatusPos1 = trackPos1.isSelProng() & (1 << 1); + if (!(trackPos1.isSelProng() & (1 << 0))) { + sel2ProngStatus = false; + } + if (!sel2ProngStatus && !sel3ProngStatusPos1) { + continue; + } auto trackParVarPos1 = getTrackParCov(trackPos1); @@ -241,85 +326,152 @@ struct HFTrackIndexSkimsCreator { if (trackNeg1.signed1Pt() > 0) { continue; } + bool sel3ProngStatusNeg1 = trackNeg1.isSelProng() & (1 << 1); + if (sel2ProngStatus && !(trackNeg1.isSelProng() & (1 << 0))) { + sel2ProngStatus = false; + } + if (!sel2ProngStatus && !sel3ProngStatusNeg1) { + continue; + } auto trackParVarNeg1 = getTrackParCov(trackNeg1); - auto pVecCandProng2 = array{trackPos1.px() + trackNeg1.px(), - trackPos1.py() + trackNeg1.py(), - trackPos1.pz() + trackNeg1.pz()}; - bool isSelectedCand2Prong = true; - - // candidate pT cut - if (RecoDecay::Pt(pVecCandProng2) < cut2ProngPtCandMin) { - isSelectedCand2Prong = false; - } - if (isSelectedCand2Prong) { - // reconstruct the 2-prong secondary vertex - if (df2.process(trackParVarPos1, trackParVarNeg1) == 0) { - continue; - } + int isSelected2ProngCand = n2ProngBit; //bitmap for checking status of two-prong candidates (1 is true, 0 is rejected) - // imp. par. product cut - if (isSelectedCand2Prong && cut2ProngImpParProductMax < 100.) { - if (trackPos1.dcaPrim0() * trackNeg1.dcaPrim0() > cut2ProngImpParProductMax) { - isSelectedCand2Prong = false; + if (b_debug) { + for (int n2 = 0; n2 < n2ProngDecays; n2++) { + for (int n2cut = 0; n2cut < nCuts2Prong; n2cut++) { + cutStatus2Prong[n2][n2cut] = true; } } - - // get secondary vertex - const auto& secondaryVertex2 = df2.getPCACandidate(); - // get track momenta - array<float, 3> pvec0; - array<float, 3> pvec1; - df2.getTrack(0).getPxPyPzGlo(pvec0); - df2.getTrack(1).getPxPyPzGlo(pvec1); - - // CPA cut - if (isSelectedCand2Prong && cut2ProngCPAMin > -2.) { - pVecCandProng2 = RecoDecay::PVec(pvec0, pvec1); - auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex2, pVecCandProng2); - if (cpa < cut2ProngCPAMin) { - isSelectedCand2Prong = false; + } + int iDebugCut = 0; + + // 2prong invariant-mass cut + if (sel2ProngStatus > 0) { + auto arrMom = array{ + array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, + array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}}; + for (int n2 = 0; n2 < n2ProngDecays; n2++) { + mass2ProngHypo1[n2] = RecoDecay::M(arrMom, arr2Mass1[n2]); + mass2ProngHypo2[n2] = RecoDecay::M(arrMom, arr2Mass2[n2]); + if ((b_debug || (isSelected2ProngCand & 1 << n2)) && cut2ProngInvMassCandMin[n2] >= 0. && cut2ProngInvMassCandMax[n2] > 0.) { //no need to check isSelected2Prong but to avoid mistakes + if ((mass2ProngHypo1[n2] < cut2ProngInvMassCandMin[n2] || mass2ProngHypo1[n2] >= cut2ProngInvMassCandMax[n2]) && + (mass2ProngHypo2[n2] < cut2ProngInvMassCandMin[n2] || mass2ProngHypo2[n2] >= cut2ProngInvMassCandMax[n2])) { + isSelected2ProngCand = isSelected2ProngCand & ~(1 << n2); + if (b_debug) { + cutStatus2Prong[n2][iDebugCut] = false; + } + } } } + iDebugCut++; - if (isSelectedCand2Prong) { - // calculate invariant masses - auto arrMom = array{pvec0, pvec1}; - mass2PiK = RecoDecay::M(arrMom, array{massPi, massK}); - mass2KPi = RecoDecay::M(arrMom, array{massK, massPi}); - } + //secondary vertex reconstruction and further 2 prong selections + if (isSelected2ProngCand > 0 && df2.process(trackParVarPos1, trackParVarNeg1) > 0) { //should it be this or > 0 or are they equivalent + // get secondary vertex + const auto& secondaryVertex2 = df2.getPCACandidate(); + // get track momenta + array<float, 3> pvec0; + array<float, 3> pvec1; + df2.getTrack(0).getPxPyPzGlo(pvec0); + df2.getTrack(1).getPxPyPzGlo(pvec1); + + auto pVecCandProng2 = RecoDecay::PVec(pvec0, pvec1); - // invariant-mass cut - if (isSelectedCand2Prong && cut2ProngInvMassD0Min >= 0. && cut2ProngInvMassD0Max > 0.) { - if ((mass2PiK < cut2ProngInvMassD0Min || mass2PiK > cut2ProngInvMassD0Max) && - (mass2KPi < cut2ProngInvMassD0Min || mass2KPi > cut2ProngInvMassD0Max)) { - isSelectedCand2Prong = false; + // candidate pT cut + if ((b_debug || isSelected2ProngCand > 0) && (std::count_if(std::begin(cut2ProngPtCandMin), std::end(cut2ProngPtCandMin), [](double d) { return d >= 0.; }) > 0)) { + double cand2ProngPt = RecoDecay::Pt(pVecCandProng2); + for (int n2 = 0; n2 < n2ProngDecays; n2++) { + if ((b_debug || (isSelected2ProngCand & 1 << n2)) && cand2ProngPt < cut2ProngPtCandMin[n2]) { + isSelected2ProngCand = isSelected2ProngCand & ~(1 << n2); + if (b_debug) { + cutStatus2Prong[n2][iDebugCut] = false; + } + } + } } - } + iDebugCut++; + + // imp. par. product cut + if ((b_debug || isSelected2ProngCand > 0) && (std::count_if(std::begin(cut2ProngImpParProductCandMax), std::end(cut2ProngImpParProductCandMax), [](double d) { return d < 100.; }) > 0)) { + auto impParProduct = trackPos1.dcaPrim0() * trackNeg1.dcaPrim0(); + for (int n2 = 0; n2 < n2ProngDecays; n2++) { + if ((b_debug || (isSelected2ProngCand & 1 << n2)) && impParProduct > cut2ProngImpParProductCandMax[n2]) { + isSelected2ProngCand = isSelected2ProngCand & ~(1 << n2); + if (b_debug) { + cutStatus2Prong[n2][iDebugCut] = false; + } + } + } + } + iDebugCut++; - if (isSelectedCand2Prong) { - // fill table row - rowTrackIndexProng2(trackPos1.globalIndex(), - trackNeg1.globalIndex(), 1); + // CPA cut + if ((b_debug || isSelected2ProngCand > 0) && (std::count_if(std::begin(cut2ProngCPACandMin), std::end(cut2ProngCPACandMin), [](double d) { return d > -2.; }) > 0)) { + auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex2, pVecCandProng2); + for (int n2 = 0; n2 < n2ProngDecays; n2++) { + if ((b_debug || (isSelected2ProngCand & 1 << n2)) && cpa < cut2ProngCPACandMin[n2]) { + isSelected2ProngCand = isSelected2ProngCand & ~(1 << n2); + if (b_debug) { + cutStatus2Prong[n2][iDebugCut] = false; + } + } + } + } + iDebugCut++; + + if (isSelected2ProngCand > 0) { + // fill table row + rowTrackIndexProng2(trackPos1.globalIndex(), + trackNeg1.globalIndex(), isSelected2ProngCand); + if (b_debug) { + int Prong2CutStatus[n2ProngDecays]; + for (int n2 = 0; n2 < n2ProngDecays; n2++) { + Prong2CutStatus[n2] = nCutStatus2ProngBit; + for (int n2cut = 0; n2cut < nCuts2Prong; n2cut++) { + if (!cutStatus2Prong[n2][n2cut]) { + Prong2CutStatus[n2] = Prong2CutStatus[n2] & ~(1 << n2cut); + } + } + } + rowProng2CutStatus(Prong2CutStatus[0], Prong2CutStatus[1]); //FIXME when we can do this by looping over n2ProngDecays + } - // fill histograms - if (b_dovalplots) { - hvtx2_x->Fill(secondaryVertex2[0]); - hvtx2_y->Fill(secondaryVertex2[1]); - hvtx2_z->Fill(secondaryVertex2[2]); - hmass2->Fill(mass2PiK); - hmass2->Fill(mass2KPi); + // fill histograms + if (b_dovalplots) { + + registry.get<TH1>("hvtx2_x")->Fill(secondaryVertex2[0]); + registry.get<TH1>("hvtx2_y")->Fill(secondaryVertex2[1]); + registry.get<TH1>("hvtx2_z")->Fill(secondaryVertex2[2]); + arrMom = array{pvec0, pvec1}; + for (int n2 = 0; n2 < n2ProngDecays; n2++) { + if (isSelected2ProngCand & 1 << n2) { + if ((cut2ProngInvMassCandMin[n2] < 0. && cut2ProngInvMassCandMax[n2] <= 0.) || (mass2ProngHypo1[n2] >= cut2ProngInvMassCandMin[n2] && mass2ProngHypo1[n2] < cut2ProngInvMassCandMax[n2])) { + mass2ProngHypo1[n2] = RecoDecay::M(arrMom, arr2Mass1[n2]); + if (n2 == 0) { + registry.get<TH1>("hmassD0")->Fill(mass2ProngHypo1[n2]); + } + if (n2 == 1) { + registry.get<TH1>("hmassJpsi")->Fill(mass2ProngHypo1[n2]); + } + } + if ((cut2ProngInvMassCandMin[n2] < 0. && cut2ProngInvMassCandMax[n2] <= 0.) || (mass2ProngHypo2[n2] >= cut2ProngInvMassCandMin[n2] && mass2ProngHypo2[n2] < cut2ProngInvMassCandMax[n2])) { + mass2ProngHypo2[n2] = RecoDecay::M(arrMom, arr2Mass2[n2]); + if (n2 == 0) { + registry.get<TH1>("hmassD0")->Fill(mass2ProngHypo1[n2]); + } + } + } + } + } } } } // 3-prong vertex reconstruction if (do3prong == 1) { - if (trackPos1.isSel3Prong() == 0) { - continue; - } - if (trackNeg1.isSel3Prong() == 0) { + if (!sel3ProngStatusPos1 || !sel3ProngStatusNeg1) { continue; } @@ -329,36 +481,50 @@ struct HFTrackIndexSkimsCreator { if (trackPos2.signed1Pt() < 0) { continue; } - if (trackPos2.isSel3Prong() == 0) { + if (!(trackPos2.isSelProng() & (1 << 1))) { continue; } - auto pVecCandProng3Pos = RecoDecay::PVec(pVecCandProng2, array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}); + int isSelected3ProngCand = n3ProngBit; - // candidate pT cut - if (RecoDecay::Pt(pVecCandProng3Pos) < cut3ProngPtCandMin) { - continue; + if (b_debug) { + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + for (int n3cut = 0; n3cut < nCuts3Prong; n3cut++) { + cutStatus3Prong[n3][n3cut] = true; + } + } } - - // invariant-mass cut - if (cut3ProngInvMassDPlusMin >= 0. && cut3ProngInvMassDPlusMax > 0.) { - // calculate invariant mass - auto arr3Mom = array{ - array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, - array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, - array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - if (mass3PiKPi < cut3ProngInvMassDPlusMin || mass3PiKPi > cut3ProngInvMassDPlusMax) { - continue; + int iDebugCut = 0; + + // 3prong invariant-mass cut + auto arr3Mom = array{ + array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, + array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, + array{trackPos2.px(), trackPos2.py(), trackPos2.pz()}}; + + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + mass3ProngHypo1[n3] = RecoDecay::M(arr3Mom, arr3Mass1[n3]); + mass3ProngHypo2[n3] = RecoDecay::M(arr3Mom, arr3Mass2[n3]); + if ((isSelected3ProngCand & 1 << n3) && cut3ProngInvMassCandMin[n3] >= 0. && cut3ProngInvMassCandMax[n3] > 0.) { + if ((mass3ProngHypo1[n3] < cut3ProngInvMassCandMin[n3] || mass3ProngHypo1[n3] >= cut3ProngInvMassCandMax[n3]) && + (mass3ProngHypo2[n3] < cut3ProngInvMassCandMin[n3] || mass3ProngHypo2[n3] >= cut3ProngInvMassCandMax[n3])) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } } } + if (!b_debug && isSelected3ProngCand == 0) { + continue; + } + iDebugCut++; // reconstruct the 3-prong secondary vertex auto trackParVarPos2 = getTrackParCov(trackPos2); if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) { continue; } - // get secondary vertex const auto& secondaryVertex3 = df3.getPCACandidate(); // get track momenta @@ -369,36 +535,109 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); + auto pVecCandProng3Pos = RecoDecay::PVec(pvec0, pvec1, pvec2); + + // candidate pT cut + if (std::count_if(std::begin(cut3ProngPtCandMin), std::end(cut3ProngPtCandMin), [](double d) { return d >= 0.; }) > 0) { + double cand3ProngPt = RecoDecay::Pt(pVecCandProng3Pos); + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if (cand3ProngPt < cut3ProngPtCandMin[n3]) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + } + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } + if (!b_debug && isSelected3ProngCand == 0) { + continue; //this and all further instances should be changed if 4 track loop is added + } + } + iDebugCut++; + // CPA cut - if (cut3ProngCPAMin > -2.) { - pVecCandProng3Pos = RecoDecay::PVec(pvec0, pvec1, pvec2); + if (std::count_if(std::begin(cut3ProngCPACandMin), std::end(cut3ProngCPACandMin), [](double d) { return d > -2.; }) > 0) { auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3, pVecCandProng3Pos); - if (cpa < cut3ProngCPAMin) { + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if ((isSelected3ProngCand & 1 << n3) && cpa < cut3ProngCPACandMin[n3]) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + } + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } + if (!b_debug && isSelected3ProngCand == 0) { continue; } } + iDebugCut++; // decay length cut - if (cut3ProngDecLenMin > 0.) { + if (std::count_if(std::begin(cut3ProngDecLenCandMin), std::end(cut3ProngDecLenCandMin), [](double d) { return d > 0.; }) > 0) { auto decayLength = RecoDecay::distance(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3); - if (decayLength < cut3ProngDecLenMin) { + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if ((isSelected3ProngCand & 1 << n3) && decayLength < cut3ProngDecLenCandMin[n3]) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } + } + if (!b_debug && isSelected3ProngCand == 0) { continue; } } + iDebugCut++; // fill table row rowTrackIndexProng3(trackPos1.globalIndex(), trackNeg1.globalIndex(), - trackPos2.globalIndex(), 2); + trackPos2.globalIndex(), isSelected3ProngCand); + + if (b_debug) { + int Prong3CutStatus[n3ProngDecays]; + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + Prong3CutStatus[n3] = nCutStatus3ProngBit; + for (int n3cut = 0; n3cut < nCuts3Prong; n3cut++) { + if (!cutStatus3Prong[n3][n3cut]) { + Prong3CutStatus[n3] = Prong3CutStatus[n3] & ~(1 << n3cut); + } + } + } + rowProng3CutStatus(Prong3CutStatus[0], Prong3CutStatus[1], Prong3CutStatus[2]); //FIXME when we can do this by looping over n3ProngDecays + } // fill histograms if (b_dovalplots) { - hvtx3_x->Fill(secondaryVertex3[0]); - hvtx3_y->Fill(secondaryVertex3[1]); - hvtx3_z->Fill(secondaryVertex3[2]); - // calculate invariant mass - hmass3->Fill(RecoDecay::M(array{pvec0, pvec1, pvec2}, array{massPi, massK, massPi})); + registry.get<TH1>("hvtx3_x")->Fill(secondaryVertex3[0]); + registry.get<TH1>("hvtx3_y")->Fill(secondaryVertex3[1]); + registry.get<TH1>("hvtx3_z")->Fill(secondaryVertex3[2]); + arr3Mom = array{pvec0, pvec1, pvec2}; + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if (isSelected3ProngCand & 1 << n3) { + if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo1[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo1[n3] < cut3ProngInvMassCandMax[n3])) { + mass3ProngHypo1[n3] = RecoDecay::M(arr3Mom, arr3Mass1[n3]); + if (n3 == 0) { + registry.get<TH1>("hmassDPlus")->Fill(mass3ProngHypo1[n3]); + } + if (n3 == 1) { + registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo1[n3]); + } + if (n3 == 2) { + registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo1[n3]); + } + } + if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo2[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo2[n3] < cut3ProngInvMassCandMax[n3])) { + mass3ProngHypo2[n3] = RecoDecay::M(arr3Mom, arr3Mass2[n3]); + if (n3 == 1) { + registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo2[n3]); + } + if (n3 == 2) { + registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo2[n3]); + } + } + } + } } } @@ -408,29 +647,44 @@ struct HFTrackIndexSkimsCreator { if (trackNeg2.signed1Pt() > 0) { continue; } - if (trackNeg2.isSel3Prong() == 0) { + if (!(trackNeg2.isSelProng() & (1 << 1))) { continue; } - auto pVecCandProng3Neg = RecoDecay::PVec(pVecCandProng2, array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}); + int isSelected3ProngCand = n3ProngBit; - // candidate pT cut - if (RecoDecay::Pt(pVecCandProng3Neg) < cut3ProngPtCandMin) { - continue; + if (b_debug) { + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + for (int n3cut = 0; n3cut < nCuts3Prong; n3cut++) { + cutStatus3Prong[n3][n3cut] = true; + } + } } - - // invariant-mass cut - if (cut3ProngInvMassDPlusMin >= 0. && cut3ProngInvMassDPlusMax > 0.) { - // calculate invariant mass - auto arr3Mom = array{ - array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, - array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, - array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}}; - mass3PiKPi = RecoDecay::M(std::move(arr3Mom), array{massPi, massK, massPi}); - if (mass3PiKPi < cut3ProngInvMassDPlusMin || mass3PiKPi > cut3ProngInvMassDPlusMax) { - continue; + int iDebugCut = 0; + + // 3prong invariant-mass cut + auto arr3Mom = array{ + array{trackNeg1.px(), trackNeg1.py(), trackNeg1.pz()}, + array{trackPos1.px(), trackPos1.py(), trackPos1.pz()}, + array{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}}; + + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + mass3ProngHypo1[n3] = RecoDecay::M(arr3Mom, arr3Mass1[n3]); + mass3ProngHypo2[n3] = RecoDecay::M(arr3Mom, arr3Mass2[n3]); + if ((isSelected3ProngCand & 1 << n3) && cut3ProngInvMassCandMin[n3] >= 0. && cut3ProngInvMassCandMax[n3] > 0.) { + if ((mass3ProngHypo1[n3] < cut3ProngInvMassCandMin[n3] || mass3ProngHypo1[n3] >= cut3ProngInvMassCandMax[n3]) && + (mass3ProngHypo2[n3] < cut3ProngInvMassCandMin[n3] || mass3ProngHypo2[n3] >= cut3ProngInvMassCandMax[n3])) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } } } + if (!b_debug && isSelected3ProngCand == 0) { + continue; + } + iDebugCut++; // reconstruct the 3-prong secondary vertex auto trackParVarNeg2 = getTrackParCov(trackNeg2); @@ -448,51 +702,124 @@ struct HFTrackIndexSkimsCreator { df3.getTrack(1).getPxPyPzGlo(pvec1); df3.getTrack(2).getPxPyPzGlo(pvec2); + auto pVecCandProng3Neg = RecoDecay::PVec(pvec0, pvec1, pvec2); + + // candidate pT cut + if (std::count_if(std::begin(cut3ProngPtCandMin), std::end(cut3ProngPtCandMin), [](double d) { return d >= 0.; }) > 0) { + double cand3ProngPt = RecoDecay::Pt(pVecCandProng3Neg); + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if (cand3ProngPt < cut3ProngPtCandMin[n3]) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } + } + if (!b_debug && isSelected3ProngCand == 0) { + continue; + } + } + iDebugCut++; + // CPA cut - if (cut3ProngCPAMin > -2.) { - pVecCandProng3Neg = RecoDecay::PVec(pvec0, pvec1, pvec2); + if (std::count_if(std::begin(cut3ProngCPACandMin), std::end(cut3ProngCPACandMin), [](double d) { return d > -2.; }) > 0) { auto cpa = RecoDecay::CPA(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3, pVecCandProng3Neg); - if (cpa < cut3ProngCPAMin) { + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if ((isSelected3ProngCand & 1 << n3) && cpa < cut3ProngCPACandMin[n3]) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } + } + if (!b_debug && isSelected3ProngCand == 0) { continue; } } + iDebugCut++; // decay length cut - if (cut3ProngDecLenMin > 0.) { + if (std::count_if(std::begin(cut3ProngDecLenCandMin), std::end(cut3ProngDecLenCandMin), [](double d) { return d > 0.; }) > 0) { auto decayLength = RecoDecay::distance(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex3); - if (decayLength < cut3ProngDecLenMin) { + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if ((isSelected3ProngCand & 1 << n3) && decayLength < cut3ProngDecLenCandMin[n3]) { + isSelected3ProngCand = isSelected3ProngCand & ~(1 << n3); + if (b_debug) { + cutStatus3Prong[n3][iDebugCut] = false; + } + } + } + if (!b_debug && isSelected3ProngCand == 0) { continue; } } + iDebugCut++; // fill table row rowTrackIndexProng3(trackNeg1.globalIndex(), trackPos1.globalIndex(), - trackNeg2.globalIndex(), 2); + trackNeg2.globalIndex(), isSelected3ProngCand); + + if (b_debug) { + int Prong3CutStatus[n3ProngDecays]; + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + Prong3CutStatus[n3] = nCutStatus3ProngBit; + for (int n3cut = 0; n3cut < nCuts3Prong; n3cut++) { + if (!cutStatus3Prong[n3][n3cut]) { + Prong3CutStatus[n3] = Prong3CutStatus[n3] & ~(1 << n3cut); + } + } + } + rowProng3CutStatus(Prong3CutStatus[0], Prong3CutStatus[1], Prong3CutStatus[2]); //FIXME when we can do this by looping over n3ProngDecays + } // fill histograms if (b_dovalplots) { - hvtx3_x->Fill(secondaryVertex3[0]); - hvtx3_y->Fill(secondaryVertex3[1]); - hvtx3_z->Fill(secondaryVertex3[2]); - // calculate invariant mass - hmass3->Fill(RecoDecay::M(array{pvec0, pvec1, pvec2}, array{massPi, massK, massPi})); + registry.get<TH1>("hvtx3_x")->Fill(secondaryVertex3[0]); + registry.get<TH1>("hvtx3_y")->Fill(secondaryVertex3[1]); + registry.get<TH1>("hvtx3_z")->Fill(secondaryVertex3[2]); + arr3Mom = array{pvec0, pvec1, pvec2}; + for (int n3 = 0; n3 < n3ProngDecays; n3++) { + if (isSelected3ProngCand & 1 << n3) { + if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo1[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo1[n3] < cut3ProngInvMassCandMax[n3])) { + mass3ProngHypo1[n3] = RecoDecay::M(arr3Mom, arr3Mass1[n3]); + if (n3 == 0) { + registry.get<TH1>("hmassDPlus")->Fill(mass3ProngHypo1[n3]); + } + if (n3 == 1) { + registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo1[n3]); + } + if (n3 == 2) { + registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo1[n3]); + } + } + if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo2[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo2[n3] < cut3ProngInvMassCandMax[n3])) { + mass3ProngHypo2[n3] = RecoDecay::M(arr3Mom, arr3Mass2[n3]); + if (n3 == 1) { + registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo2[n3]); + } + if (n3 == 2) { + registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo2[n3]); + } + } + } + } } } } } } - /* - auto nTracks = tracks.size(); // number of tracks in this collision + + auto nTracks = tracks.size(); // number of tracks passing 2 and 3 prong selection in this collision nCand2 = rowTrackIndexProng2.lastIndex() - nCand2; // number of 2-prong candidates in this collision nCand3 = rowTrackIndexProng3.lastIndex() - nCand3; // number of 3-prong candidates in this collision - hNTracks->Fill(nTracks); - hNCand2Prong->Fill(nCand2); - hNCand3Prong->Fill(nCand3); - hNCand2ProngVsNTracks->Fill(nTracks, nCand2); - hNCand3ProngVsNTracks->Fill(nTracks, nCand3); - */ + + registry.get<TH1>("hNTracks")->Fill(nTracks); + registry.get<TH1>("hNCand2Prong")->Fill(nCand2); + registry.get<TH1>("hNCand3Prong")->Fill(nCand3); + registry.get<TH2>("hNCand2ProngVsNTracks")->Fill(nTracks, nCand2); + registry.get<TH2>("hNCand3ProngVsNTracks")->Fill(nTracks, nCand3); } }; From 8bcd6da8fc8e398f8ac155ca3a8fce3cba14d659 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 2 Dec 2020 20:45:42 +0400 Subject: [PATCH 1498/1751] PHOS CTF writing/reading --- DataFormats/Detectors/PHOS/CMakeLists.txt | 5 +- .../PHOS/include/DataFormatsPHOS/CTF.h | 57 ++++++ .../PHOS/include/DataFormatsPHOS/Cell.h | 18 ++ DataFormats/Detectors/PHOS/src/CTF.cxx | 15 ++ .../PHOS/src/DataFormatsPHOSLinkDef.h | 4 + Detectors/CTF/CMakeLists.txt | 8 + Detectors/CTF/test/test_ctf_io_phos.cxx | 119 +++++++++++ Detectors/CTF/workflow/CMakeLists.txt | 1 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 + Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 3 + .../CTF/workflow/src/ctf-reader-workflow.cxx | 4 + Detectors/PHOS/reconstruction/CMakeLists.txt | 6 +- .../include/PHOSReconstruction/CTFCoder.h | 153 ++++++++++++++ .../include/PHOSReconstruction/CTFHelper.h | 193 ++++++++++++++++++ .../PHOS/reconstruction/src/CTFCoder.cxx | 76 +++++++ .../PHOS/reconstruction/src/CTFHelper.cxx | 15 ++ Detectors/PHOS/workflow/CMakeLists.txt | 7 + .../include/PHOSWorkflow/EntropyDecoderSpec.h | 47 +++++ .../include/PHOSWorkflow/EntropyEncoderSpec.h | 47 +++++ .../PHOS/workflow/src/EntropyDecoderSpec.cxx | 79 +++++++ .../PHOS/workflow/src/EntropyEncoderSpec.cxx | 79 +++++++ .../workflow/src/entropy-encoder-workflow.cxx | 39 ++++ 22 files changed, 981 insertions(+), 2 deletions(-) create mode 100644 DataFormats/Detectors/PHOS/include/DataFormatsPHOS/CTF.h create mode 100644 DataFormats/Detectors/PHOS/src/CTF.cxx create mode 100644 Detectors/CTF/test/test_ctf_io_phos.cxx create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFCoder.h create mode 100644 Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFHelper.h create mode 100644 Detectors/PHOS/reconstruction/src/CTFCoder.cxx create mode 100644 Detectors/PHOS/reconstruction/src/CTFHelper.cxx create mode 100644 Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyDecoderSpec.h create mode 100644 Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyEncoderSpec.h create mode 100644 Detectors/PHOS/workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/PHOS/workflow/src/EntropyEncoderSpec.cxx create mode 100644 Detectors/PHOS/workflow/src/entropy-encoder-workflow.cxx diff --git a/DataFormats/Detectors/PHOS/CMakeLists.txt b/DataFormats/Detectors/PHOS/CMakeLists.txt index e38d682a52a4f..3284e9df89663 100644 --- a/DataFormats/Detectors/PHOS/CMakeLists.txt +++ b/DataFormats/Detectors/PHOS/CMakeLists.txt @@ -15,6 +15,7 @@ o2_add_library(DataFormatsPHOS src/Cluster.cxx src/MCLabel.cxx src/TriggerRecord.cxx + src/CTF.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::MathUtils @@ -29,7 +30,9 @@ o2_target_root_dictionary(DataFormatsPHOS include/DataFormatsPHOS/Digit.h include/DataFormatsPHOS/Cluster.h include/DataFormatsPHOS/MCLabel.h - include/DataFormatsPHOS/TriggerRecord.h) + include/DataFormatsPHOS/TriggerRecord.h + include/DataFormatsPHOS/CTF.h + ) o2_add_test(Cell SOURCES test/testCell.cxx COMPONENT_NAME DataFormats-PHOS diff --git a/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/CTF.h b/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/CTF.h new file mode 100644 index 0000000000000..ee9300a01972c --- /dev/null +++ b/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/CTF.h @@ -0,0 +1,57 @@ +// 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 CTF.h +/// \author ruben.shahoyan@cern.ch +/// \brief Definitions for PHOS CTF data + +#ifndef O2_PHS_CTF_H +#define O2_PHS_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" +#include "DataFormatsPHOS/TriggerRecord.h" +#include "DataFormatsPHOS/Cell.h" + +namespace o2 +{ +namespace phos +{ + +/// Header for a single CTF +struct CTFHeader { + uint32_t nTriggers = 0; /// number of triggers + uint32_t nCells = 0; /// number of referred cells + uint32_t firstOrbit = 0; /// orbit of 1st trigger + uint16_t firstBC = 0; /// bc of 1st trigger + + ClassDefNV(CTFHeader, 1); +}; + +/// wrapper for the Entropy-encoded triggers and cells of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 7, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { BLC_bcIncTrig, + BLC_orbitIncTrig, + BLC_entriesTrig, + BLC_packedID, + BLC_time, + BLC_energy, + BLC_status + }; + ClassDefNV(CTF, 1); +}; + +} // namespace phos +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Cell.h b/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Cell.h index 6069a6e1b2fc1..7c36191dbe91f 100644 --- a/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Cell.h +++ b/DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Cell.h @@ -71,6 +71,24 @@ class Cell void PrintStream(std::ostream& stream) const; + // raw access for CTF encoding + uint16_t getPackedID() const { return getLong() & 0x3fff; } + void setPackedID(uint16_t v) { mBits = (getLong() & 0xffffffc000) + (v & 0x3fff); } + + uint16_t getPackedTime() const { return (getLong() >> 14) & 0x3ff; } + void setPackedTime(uint16_t v) { mBits = (getLong() & 0xffff003fff) + (uint64_t(v & 0x3ff) << 14); } + + uint16_t getPackedEnergy() const { return (getLong() >> 24) & 0x7fff; } + void setPackedEnergy(uint16_t v) { mBits = (getLong() & 0x8000ffffff) + (uint64_t(v & 0x7fff) << 24); } + + uint8_t getPackedCellStatus() const { return mBits[39]; } + void setPackedCellStatus(uint8_t v) { mBits[39] = v ? true : false; } + + void setPacked(uint16_t id, uint16_t t, uint16_t en, uint16_t status) + { + mBits = uint64_t(id & 0x3fff) + (uint64_t(t & 0x3ff) << 14) + (uint64_t(en & 0x7fff) << 24) + (uint64_t(status & 0x1) << 39); + } + private: std::bitset<40> mBits; diff --git a/DataFormats/Detectors/PHOS/src/CTF.cxx b/DataFormats/Detectors/PHOS/src/CTF.cxx new file mode 100644 index 0000000000000..d7cda37769955 --- /dev/null +++ b/DataFormats/Detectors/PHOS/src/CTF.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 <stdexcept> +#include <cstring> +#include "DataFormatsPHOS/CTF.h" + +using namespace o2::phos; diff --git a/DataFormats/Detectors/PHOS/src/DataFormatsPHOSLinkDef.h b/DataFormats/Detectors/PHOS/src/DataFormatsPHOSLinkDef.h index d0cc6c80fb182..5e5046fed4b74 100644 --- a/DataFormats/Detectors/PHOS/src/DataFormatsPHOSLinkDef.h +++ b/DataFormats/Detectors/PHOS/src/DataFormatsPHOSLinkDef.h @@ -29,4 +29,8 @@ // For channel type in digits and cells #pragma link C++ enum o2::phos::ChannelType_t + ; +#pragma link C++ struct o2::phos::CTFHeader + ; +#pragma link C++ struct o2::phos::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::phos::CTFHeader, 7, uint32_t> + ; + #endif diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index 0fd407b3f2099..4daff377c664c 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -73,3 +73,11 @@ o2_add_test(emcal SOURCES test/test_ctf_io_emcal.cxx COMPONENT_NAME ctf LABELS ctf) + +o2_add_test(phos + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::DataFormatsEMCAL + O2::PHOSReconstruction + SOURCES test/test_ctf_io_phos.cxx + COMPONENT_NAME ctf + LABELS ctf) diff --git a/Detectors/CTF/test/test_ctf_io_phos.cxx b/Detectors/CTF/test/test_ctf_io_phos.cxx new file mode 100644 index 0000000000000..964eca2dcaa5d --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_phos.cxx @@ -0,0 +1,119 @@ +// 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. + +#define BOOST_TEST_MODULE Test PHSCTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DetectorsCommonDataFormats/NameConf.h" +#include "PHOSReconstruction/CTFCoder.h" +#include "DataFormatsPHOS/CTF.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <TSystem.h> +#include <cstring> + +using namespace o2::phos; + +BOOST_AUTO_TEST_CASE(CTFTest) +{ + std::vector<TriggerRecord> triggers; + std::vector<Cell> cells; + TStopwatch sw; + sw.Start(); + o2::InteractionRecord ir(0, 0); + for (int irof = 0; irof < 1000; irof++) { + ir += 1 + gRandom->Integer(200); + + auto start = cells.size(); + int n = 1 + gRandom->Poisson(100); + for (int i = n; i--;) { + ChannelType_t tp = gRandom->Rndm() > 0.5 ? TRU : (gRandom->Rndm() > 0.5 ? HIGH_GAIN : LOW_GAIN); + uint16_t id = tp == TRU ? 3000 : gRandom->Integer(kNmaxCell); + float timeCell = gRandom->Rndm() * 3.00e-07 - 0.3e-9; + float en = gRandom->Rndm() * 160.; + cells.emplace_back(id, en, timeCell, tp); + } + triggers.emplace_back(ir, start, cells.size() - start); + } + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + { + CTFCoder coder; + coder.encode(vec, triggers, cells); // compress + } + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + auto* ctfImage = o2::phos::CTF::get(vec.data()); + TFile flOut("test_ctf_phos.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "PHS"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + { + sw.Start(); + TFile flIn("test_ctf_phos.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + o2::phos::CTF::readFromTree(vec, *(tree.get()), "PHS"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<TriggerRecord> triggersD; + std::vector<Cell> cellsD; + + sw.Start(); + const auto ctfImage = o2::phos::CTF::getImage(vec.data()); + { + CTFCoder coder; + coder.decode(ctfImage, triggersD, cellsD); // decompress + } + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + BOOST_CHECK(triggersD.size() == triggers.size()); + BOOST_CHECK(cellsD.size() == cells.size()); + LOG(INFO) << " BOOST_CHECK triggersD.size() " << triggersD.size() << " triggers.size() " << triggers.size() + << " BOOST_CHECK(cellsD.size() " << cellsD.size() << " cells.size()) " << cells.size(); + + for (size_t i = 0; i < triggers.size(); i++) { + const auto& dor = triggers[i]; + const auto& ddc = triggersD[i]; + LOG(DEBUG) << " Orig.TriggerRecord " << i << " " << dor.getBCData() << " " << dor.getFirstEntry() << " " << dor.getNumberOfObjects(); + LOG(DEBUG) << " Deco.TriggerRecord " << i << " " << ddc.getBCData() << " " << ddc.getFirstEntry() << " " << ddc.getNumberOfObjects(); + + BOOST_CHECK(dor.getBCData() == ddc.getBCData()); + BOOST_CHECK(dor.getNumberOfObjects() == ddc.getNumberOfObjects()); + BOOST_CHECK(dor.getFirstEntry() == dor.getFirstEntry()); + } + + for (size_t i = 0; i < cells.size(); i++) { + const auto& cor = cells[i]; + const auto& cdc = cellsD[i]; + BOOST_CHECK(cor.getPackedID() == cdc.getPackedID()); + BOOST_CHECK(cor.getPackedTime() == cdc.getPackedTime()); + BOOST_CHECK(cor.getPackedEnergy() == cdc.getPackedEnergy()); + BOOST_CHECK(cor.getPackedCellStatus() == cdc.getPackedCellStatus()); + } +} diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index 166900fc24e3b..1bb7896c3dd2c 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -29,6 +29,7 @@ o2_add_library(CTFWorkflow O2::TOFWorkflow O2::MIDWorkflow O2::EMCALWorkflow + O2::PHOSWorkflow O2::Algorithm O2::CommonUtils) diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 75f20df01c4db..1021128026b1f 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -31,6 +31,7 @@ #include "DataFormatsTOF/CTF.h" #include "DataFormatsMID/CTF.h" #include "DataFormatsEMCAL/CTF.h" +#include "DataFormatsPHOS/CTF.h" #include "Algorithm/RangeTokenizer.h" using namespace o2::framework; @@ -173,6 +174,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::PHS; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::phos::CTF)); + o2::phos::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + mTimer.Stop(); LOG(INFO) << "Read CTF " << inputFile << " in " << mTimer.CpuTime() - cput << " s"; diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 66ae942fa2601..fefaa596bb84b 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -28,6 +28,7 @@ #include "DataFormatsTOF/CTF.h" #include "DataFormatsMID/CTF.h" #include "DataFormatsEMCAL/CTF.h" +#include "DataFormatsPHOS/CTF.h" using namespace o2::framework; @@ -104,6 +105,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) processDet<o2::fdd::CTF>(pc, DetID::FDD, header, treeOut.get()); processDet<o2::mid::CTF>(pc, DetID::MID, header, treeOut.get()); processDet<o2::emcal::CTF>(pc, DetID::EMC, header, treeOut.get()); + processDet<o2::phos::CTF>(pc, DetID::PHS, header, treeOut.get()); mTimer.Stop(); @@ -174,6 +176,7 @@ void CTFWriterSpec::storeDictionaries() storeDictionary<o2::fdd::CTF>(DetID::FDD, header); storeDictionary<o2::mid::CTF>(DetID::MID, header); storeDictionary<o2::emcal::CTF>(DetID::EMC, header); + storeDictionary<o2::phos::CTF>(DetID::PHS, header); // close remnants if (mDictTreeOut) { closeDictionaryTreeAndFile(header); diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index 38d0f730dd141..b99922a7d02ac 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -28,6 +28,7 @@ #include "TOFWorkflowUtils/EntropyDecoderSpec.h" #include "MIDWorkflow/EntropyDecoderSpec.h" #include "EMCALWorkflow/EntropyDecoderSpec.h" +#include "PHOSWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -96,6 +97,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets[DetID::EMC]) { specs.push_back(o2::emcal::getEntropyDecoderSpec()); } + if (dets[DetID::PHS]) { + specs.push_back(o2::phos::getEntropyDecoderSpec()); + } return std::move(specs); } diff --git a/Detectors/PHOS/reconstruction/CMakeLists.txt b/Detectors/PHOS/reconstruction/CMakeLists.txt index 76f315acaf49a..c46283b9d756a 100644 --- a/Detectors/PHOS/reconstruction/CMakeLists.txt +++ b/Detectors/PHOS/reconstruction/CMakeLists.txt @@ -19,11 +19,15 @@ o2_add_library(PHOSReconstruction src/Bunch.cxx src/Channel.cxx src/CaloRawFitter.cxx + src/CTFCoder.cxx + src/CTFHelper.cxx PUBLIC_LINK_LIBRARIES O2::PHOSBase O2::PHOSCalib O2::DataFormatsPHOS O2::DetectorsRaw - AliceO2::InfoLogger) + AliceO2::InfoLogger + O2::rANS + ms_gsl::ms_gsl) o2_target_root_dictionary(PHOSReconstruction HEADERS include/PHOSReconstruction/RawReaderMemory.h diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFCoder.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFCoder.h new file mode 100644 index 0000000000000..27969fd577b8e --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFCoder.h @@ -0,0 +1,153 @@ +// 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 CTFCoder.h +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of PHOS data + +#ifndef O2_PHOS_CTFCODER_H +#define O2_PHOS_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include <array> +#include "DataFormatsPHOS/CTF.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" +#include "rANS/rans.h" +#include "PHOSReconstruction/CTFHelper.h" + +class TTree; + +namespace o2 +{ +namespace phos +{ + +class CTFCoder : public o2::ctf::CTFCoderBase +{ + public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::PHS) {} + ~CTFCoder() = default; + + /// entropy-encode data to buffer with CTF + template <typename VEC> + void encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cell>& cellData); + + /// entropy decode data from buffer with CTF + template <typename VTRG, typename VCELL> + void decode(const CTF::base& ec, VTRG& trigVec, VCELL& cellVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); + + private: + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Cell>& cellVec); +}; + +/// entropy-encode clusters to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cell>& cellData) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, // BLC_bcIncTrig + MD::EENCODE, // BLC_orbitIncTrig + MD::EENCODE, // BLC_entriesTrig + MD::EENCODE, // BLC_packedID + MD::EENCODE, // BLC_time + MD::EENCODE, // BLC_energy + MD::EENCODE // BLC_status + }; + + CTFHelper helper(trigData, cellData); + + // book output size with some margin + auto szIni = sizeof(CTFHeader) + helper.getSize() / 4; // will be autoexpanded if needed + buff.resize(szIni); + + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(helper.createHeader()); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODEPHS(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); + // clang-format off + ENCODEPHS(helper.begin_bcIncTrig(), helper.end_bcIncTrig(), CTF::BLC_bcIncTrig, 0); + ENCODEPHS(helper.begin_orbitIncTrig(), helper.end_orbitIncTrig(), CTF::BLC_orbitIncTrig, 0); + ENCODEPHS(helper.begin_entriesTrig(), helper.end_entriesTrig(), CTF::BLC_entriesTrig, 0); + + ENCODEPHS(helper.begin_packedID(), helper.end_packedID(), CTF::BLC_packedID, 0); + ENCODEPHS(helper.begin_time(), helper.end_time(), CTF::BLC_time, 0); + ENCODEPHS(helper.begin_energy(), helper.end_energy(), CTF::BLC_energy, 0); + ENCODEPHS(helper.begin_status(), helper.end_status(), CTF::BLC_status, 0); + // clang-format on + CTF::get(buff.data())->print(getPrefix()); +} + +/// decode entropy-encoded clusters to standard compact clusters +template <typename VTRG, typename VCELL> +void CTFCoder::decode(const CTF::base& ec, VTRG& trigVec, VCELL& cellVec) +{ + auto header = ec.getHeader(); + ec.print(getPrefix()); + std::vector<uint16_t> bcInc, entries, energy, cellTime, packedID; + std::vector<uint32_t> orbitInc; + std::vector<uint8_t> status; + +#define DECODEPHOS(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) + // clang-format off + DECODEPHOS(bcInc, CTF::BLC_bcIncTrig); + DECODEPHOS(orbitInc, CTF::BLC_orbitIncTrig); + DECODEPHOS(entries, CTF::BLC_entriesTrig); + DECODEPHOS(packedID, CTF::BLC_packedID); + + DECODEPHOS(cellTime, CTF::BLC_time); + DECODEPHOS(energy, CTF::BLC_energy); + DECODEPHOS(status, CTF::BLC_status); + // clang-format on + // + trigVec.clear(); + cellVec.clear(); + trigVec.reserve(header.nTriggers); + status.reserve(header.nCells); + + uint32_t firstEntry = 0, cellCount = 0; + o2::InteractionRecord ir(header.firstBC, header.firstOrbit); + + Cell cell; + for (uint32_t itrig = 0; itrig < header.nTriggers; itrig++) { + // restore TrigRecord + if (orbitInc[itrig]) { // non-0 increment => new orbit + ir.bc = bcInc[itrig]; // bcInc has absolute meaning + ir.orbit += orbitInc[itrig]; + } else { + ir.bc += bcInc[itrig]; + } + + firstEntry = cellVec.size(); + for (uint16_t ic = 0; ic < entries[itrig]; ic++) { + cell.setPacked(packedID[cellCount], cellTime[cellCount], energy[cellCount], status[cellCount]); + cellVec.emplace_back(cell); + cellCount++; + } + trigVec.emplace_back(ir, firstEntry, entries[itrig]); + } + assert(cellCount == header.nCells); +} + +} // namespace phos +} // namespace o2 + +#endif // O2_PHOS_CTFCODER_H diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFHelper.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFHelper.h new file mode 100644 index 0000000000000..9a127b4f00b8f --- /dev/null +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFHelper.h @@ -0,0 +1,193 @@ +// 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 CTFHelper.h +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for PHOS CTF creation + +#ifndef O2_PHOS_CTF_HELPER_H +#define O2_PHOS_CTF_HELPER_H + +#include "DataFormatsPHOS/CTF.h" +#include <gsl/span> + +namespace o2 +{ +namespace phos +{ + +class CTFHelper +{ + + public: + CTFHelper(const gsl::span<const TriggerRecord>& trgData, const gsl::span<const Cell>& cellData) + : mTrigData(trgData), mCellData(cellData) {} + + CTFHeader createHeader() + { + CTFHeader h{uint32_t(mTrigData.size()), uint32_t(mCellData.size()), 0, 0}; + if (mTrigData.size()) { + h.firstOrbit = mTrigData[0].getBCData().orbit; + h.firstBC = mTrigData[0].getBCData().bc; + } + return h; + } + + size_t getSize() const { return mTrigData.size() * sizeof(TriggerRecord) + mCellData.size() * sizeof(Cell); } + + //>>> =========================== ITERATORS ======================================== + + template <typename I, typename D, typename T> + class _Iter + { + public: + using difference_type = int64_t; + using value_type = T; + using pointer = const T*; + using reference = const T&; + using iterator_category = std::random_access_iterator_tag; + + _Iter(const gsl::span<const D>& data, bool end = false) : mData(data), mIndex(end ? data.size() : 0){}; + _Iter() = default; + + const I& operator++() + { + ++mIndex; + return (I&)(*this); + } + + const I& operator--() + { + mIndex--; + return (I&)(*this); + } + + difference_type operator-(const I& other) const { return mIndex - other.mIndex; } + + difference_type operator-(size_t idx) const { return mIndex - idx; } + + const I& operator-(size_t idx) + { + mIndex -= idx; + return (I&)(*this); + } + + bool operator!=(const I& other) const { return mIndex != other.mIndex; } + bool operator==(const I& other) const { return mIndex == other.mIndex; } + bool operator>(const I& other) const { return mIndex > other.mIndex; } + bool operator<(const I& other) const { return mIndex < other.mIndex; } + + protected: + gsl::span<const D> mData{}; + size_t mIndex = 0; + }; + + //_______________________________________________ + // BC difference wrt previous if in the same orbit, otherwise the abs.value. + // For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_bcIncTrig : public _Iter<Iter_bcIncTrig, TriggerRecord, uint16_t> + { + public: + using _Iter<Iter_bcIncTrig, TriggerRecord, uint16_t>::_Iter; + value_type operator*() const + { + if (mIndex) { + if (mData[mIndex].getBCData().orbit == mData[mIndex - 1].getBCData().orbit) { + return mData[mIndex].getBCData().bc - mData[mIndex - 1].getBCData().bc; + } else { + return mData[mIndex].getBCData().bc; + } + } + return 0; + } + }; + + //_______________________________________________ + // Orbit difference wrt previous. For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_orbitIncTrig : public _Iter<Iter_orbitIncTrig, TriggerRecord, uint32_t> + { + public: + using _Iter<Iter_orbitIncTrig, TriggerRecord, uint32_t>::_Iter; + value_type operator*() const { return mIndex ? mData[mIndex].getBCData().orbit - mData[mIndex - 1].getBCData().orbit : 0; } + }; + + //_______________________________________________ + // Number of cells for trigger + class Iter_entriesTrig : public _Iter<Iter_entriesTrig, TriggerRecord, uint16_t> + { + public: + using _Iter<Iter_entriesTrig, TriggerRecord, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getNumberOfObjects(); } + }; + + //_______________________________________________ + class Iter_packedID : public _Iter<Iter_packedID, Cell, uint16_t> + { + public: + using _Iter<Iter_packedID, Cell, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedID(); } + }; + + //_______________________________________________ + class Iter_time : public _Iter<Iter_time, Cell, uint16_t> + { + public: + using _Iter<Iter_time, Cell, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedTime(); } + }; + + //_______________________________________________ + class Iter_energy : public _Iter<Iter_energy, Cell, uint16_t> + { + public: + using _Iter<Iter_energy, Cell, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedEnergy(); } + }; + + //_______________________________________________ + class Iter_status : public _Iter<Iter_status, Cell, uint8_t> + { + public: + using _Iter<Iter_status, Cell, uint8_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedCellStatus(); } + }; + + //<<< =========================== ITERATORS ======================================== + + Iter_bcIncTrig begin_bcIncTrig() const { return Iter_bcIncTrig(mTrigData, false); } + Iter_bcIncTrig end_bcIncTrig() const { return Iter_bcIncTrig(mTrigData, true); } + + Iter_orbitIncTrig begin_orbitIncTrig() const { return Iter_orbitIncTrig(mTrigData, false); } + Iter_orbitIncTrig end_orbitIncTrig() const { return Iter_orbitIncTrig(mTrigData, true); } + + Iter_entriesTrig begin_entriesTrig() const { return Iter_entriesTrig(mTrigData, false); } + Iter_entriesTrig end_entriesTrig() const { return Iter_entriesTrig(mTrigData, true); } + + Iter_packedID begin_packedID() const { return Iter_packedID(mCellData, false); } + Iter_packedID end_packedID() const { return Iter_packedID(mCellData, true); } + + Iter_time begin_time() const { return Iter_time(mCellData, false); } + Iter_time end_time() const { return Iter_time(mCellData, true); } + + Iter_energy begin_energy() const { return Iter_energy(mCellData, false); } + Iter_energy end_energy() const { return Iter_energy(mCellData, true); } + + Iter_status begin_status() const { return Iter_status(mCellData, false); } + Iter_status end_status() const { return Iter_status(mCellData, true); } + + private: + const gsl::span<const o2::phos::TriggerRecord> mTrigData; + const gsl::span<const o2::phos::Cell> mCellData; +}; + +} // namespace phos +} // namespace o2 + +#endif diff --git a/Detectors/PHOS/reconstruction/src/CTFCoder.cxx b/Detectors/PHOS/reconstruction/src/CTFCoder.cxx new file mode 100644 index 0000000000000..921dfb1de8f83 --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/CTFCoder.cxx @@ -0,0 +1,76 @@ +// 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 CTFCoder.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of PHOS data + +#include "PHOSReconstruction/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::phos; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) +{ + ec.appendToTree(tree, mDet.getName()); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Cell>& cellVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, mDet.getName(), entry); + decode(ec, trigVec, cellVec); +} + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + // just to get types + uint16_t bcInc = 0, entries = 0, cellTime = 0, energy = 0, packedid = 0; + uint32_t orbitInc = 0; + uint8_t status = 0; +#define MAKECODER(part, slot) createCoder<decltype(part)>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(bcInc, CTF::BLC_bcIncTrig); + MAKECODER(orbitInc, CTF::BLC_orbitIncTrig); + MAKECODER(entries, CTF::BLC_entriesTrig); + MAKECODER(packedid, CTF::BLC_packedID); + MAKECODER(cellTime, CTF::BLC_time); + MAKECODER(energy, CTF::BLC_energy); + MAKECODER(status, CTF::BLC_status); + // clang-format on +} diff --git a/Detectors/PHOS/reconstruction/src/CTFHelper.cxx b/Detectors/PHOS/reconstruction/src/CTFHelper.cxx new file mode 100644 index 0000000000000..d682ddea97349 --- /dev/null +++ b/Detectors/PHOS/reconstruction/src/CTFHelper.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. + +/// \file CTFHelper.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for PHOS CTF creation + +#include "PHOSReconstruction/CTFHelper.h" diff --git a/Detectors/PHOS/workflow/CMakeLists.txt b/Detectors/PHOS/workflow/CMakeLists.txt index 87ea0be400524..7d19c6fabaf48 100644 --- a/Detectors/PHOS/workflow/CMakeLists.txt +++ b/Detectors/PHOS/workflow/CMakeLists.txt @@ -16,6 +16,8 @@ o2_add_library(PHOSWorkflow src/ClusterizerSpec.cxx src/DigitsPrinterSpec.cxx src/RawWriterSpec.cxx + src/EntropyEncoderSpec.cxx + src/EntropyDecoderSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsPHOS O2::DPLUtils O2::PHOSBase @@ -28,3 +30,8 @@ o2_add_executable(reco-workflow COMPONENT_NAME phos SOURCES src/phos-reco-workflow.cxx PUBLIC_LINK_LIBRARIES O2::PHOSWorkflow) + +o2_add_executable(entropy-encoder-workflow + COMPONENT_NAME phos + SOURCES src/entropy-encoder-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::PHOSWorkflow) diff --git a/Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyDecoderSpec.h b/Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..386a70bf596ce --- /dev/null +++ b/Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyDecoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to PHOS digit/channels strean + +#ifndef O2_PHOS_ENTROPYDECODER_SPEC +#define O2_PHOS_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "PHOSReconstruction/CTFCoder.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace phos +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::phos::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace phos +} // namespace o2 + +#endif diff --git a/Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyEncoderSpec.h b/Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..a61197a8a4ed6 --- /dev/null +++ b/Detectors/PHOS/workflow/include/PHOSWorkflow/EntropyEncoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert PHOS data to CTF (EncodedBlocks) + +#ifndef O2_PHOS_ENTROPYENCODER_SPEC +#define O2_PHOS_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> +#include "PHOSReconstruction/CTFCoder.h" + +namespace o2 +{ +namespace phos +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::phos::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace phos +} // namespace o2 + +#endif diff --git a/Detectors/PHOS/workflow/src/EntropyDecoderSpec.cxx b/Detectors/PHOS/workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..0726b61363ab7 --- /dev/null +++ b/Detectors/PHOS/workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "PHOSWorkflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace phos +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("phos-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& triggers = pc.outputs().make<std::vector<TriggerRecord>>(OutputRef{"triggers"}); + auto& cells = pc.outputs().make<std::vector<Cell>>(OutputRef{"cells"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::phos::CTF::getImage(buff.data()); + mCTFCoder.decode(ctfImage, triggers, cells); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << cells.size() << " PHOS cells in " << triggers.size() << " triggers in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "PHOS Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"triggers"}, "PHS", "CELLTRIGREC", 0, Lifetime::Timeframe}, + OutputSpec{{"cells"}, "PHS", "CELLS", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "phos-entropy-decoder", + Inputs{InputSpec{"ctf", "PHS", "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{{"phos-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; +} + +} // namespace phos +} // namespace o2 diff --git a/Detectors/PHOS/workflow/src/EntropyEncoderSpec.cxx b/Detectors/PHOS/workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..0c5a4b8d6119c --- /dev/null +++ b/Detectors/PHOS/workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyEncoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "PHOSWorkflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace phos +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("phos-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto triggers = pc.inputs().get<gsl::span<TriggerRecord>>("triggers"); + auto cells = pc.inputs().get<gsl::span<Cell>>("cells"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"PHS", "CTFDATA", 0, Lifetime::Timeframe}); + mCTFCoder.encode(buffer, triggers, cells); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + // eeb->print(); + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for PHOS in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "PHOS Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("triggers", "PHS", "CELLTRIGREC", 0, Lifetime::Timeframe); + inputs.emplace_back("cells", "PHS", "CELLS", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "phos-entropy-encoder", + inputs, + Outputs{{"PHS", "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{{"phos-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; +} + +} // namespace phos +} // namespace o2 diff --git a/Detectors/PHOS/workflow/src/entropy-encoder-workflow.cxx b/Detectors/PHOS/workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..e59400287359a --- /dev/null +++ b/Detectors/PHOS/workflow/src/entropy-encoder-workflow.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. + +#include "PHOSWorkflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::phos::getEntropyEncoderSpec()); + return wf; +} From 0ce13da48b9e9c998d45d6841ff94053be6daf28 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Wed, 2 Dec 2020 21:02:29 +0400 Subject: [PATCH 1499/1751] suppress non-existing option file-for subdet --- Detectors/PHOS/simulation/src/RawCreator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/PHOS/simulation/src/RawCreator.cxx b/Detectors/PHOS/simulation/src/RawCreator.cxx index d70a7c011dd21..dedf754d0b26e 100644 --- a/Detectors/PHOS/simulation/src/RawCreator.cxx +++ b/Detectors/PHOS/simulation/src/RawCreator.cxx @@ -45,7 +45,7 @@ int main(int argc, const char** argv) add_option("help,h", "Print this help message"); add_option("verbose,v", bpo::value<uint32_t>()->default_value(0), "Select verbosity level [0 = no output]"); add_option("input-file,i", bpo::value<std::string>()->default_value("phosdigits.root"), "Specifies digit input file."); - add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,subdet,link"); + add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,link"); add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); add_option("debug,d", bpo::value<uint32_t>()->default_value(0), "Select debug output level [0 = no debug output]"); add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); From 513c301471267c2a7856c9cb179accae0920e0f0 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Thu, 3 Dec 2020 09:37:54 +0100 Subject: [PATCH 1500/1751] Updating index tutorials, including compatible BCs (#4875) --- Analysis/Tutorials/CMakeLists.txt | 5 + Analysis/Tutorials/src/ZDCVZeroIteration.cxx | 75 ++++++------- Analysis/Tutorials/src/compatibleBCs.cxx | 102 ++++++++++++++++++ Analysis/Tutorials/src/muonIteration.cxx | 6 +- Framework/Core/include/Framework/ASoA.h | 13 +++ .../include/Framework/AnalysisDataModel.h | 14 ++- Framework/Core/src/AODReaderHelpers.cxx | 8 +- 7 files changed, 170 insertions(+), 53 deletions(-) create mode 100644 Analysis/Tutorials/src/compatibleBCs.cxx diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index d5689d3068466..07edbd72dd749 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -167,3 +167,8 @@ o2_add_dpl_workflow(efficiency-global SOURCES src/efficiencyGlobal.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(compatible-bcs + SOURCES src/compatibleBCs.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx index c786524dcd142..a4fbc3eda0dcd 100644 --- a/Analysis/Tutorials/src/ZDCVZeroIteration.cxx +++ b/Analysis/Tutorials/src/ZDCVZeroIteration.cxx @@ -15,20 +15,22 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// This task shows how to access the ZDC and FV0A information which belongs to a collision +// These example tasks show how to access the ZDC and FV0A information which belongs to a collision // The association is made through the BC column (and in Run 3 may not be unique!) -// This example access the collisions and the related FV0A information. -// Note that one has to subscribe to aod::Collisions const& and aod::FV0As const& to load -// the relevant data even if you access the data itself through m.collision() and m.fv0a() +// This example accesses the collisions and the related FV0A information. +// Note that one has to subscribe to aod::FV0As const& to load +// the relevant data even if you access the data itself through collisionMatched.fv0a() // Here the "sparse" matcher is used which means, there can be collisions without FV0A information -// To find out, m.has_fv0a() has to be called. Otherwise m.fv0a() will fail. +// To find out, collisionMatched.has_fv0a() has to be called. Otherwise collisionMatched.fv0a() will fail. +// NOTE: subscribing to Collisions separately will lead to a circular dependency due to forwarding + struct IterateV0 { - void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::FV0As const&) + void process(aod::CollisionMatchedRun2Sparse const& collisionMatched, aod::FV0As const&) { - LOGF(INFO, "Vertex = %f", m.collision().posZ()); - if (m.has_fv0a()) { - auto v0a = m.fv0a(); + LOGF(INFO, "Vertex = %f", collisionMatched.posZ()); + if (collisionMatched.has_fv0a()) { + auto v0a = collisionMatched.fv0a(); LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); } else { LOGF(INFO, "No V0A info"); @@ -36,44 +38,28 @@ struct IterateV0 { } }; -// This example is identical to IterateV0, but uses the exclusive match. This means that lines where any -// of the tables asked for in Run2MatchedExclusive (see AnalysisDataModel.h) are missing are not listed. +// This example is identical to IterateV0, but uses the exclusive match. This means that collisions where any +// of the tables asked for in Run2MatchedExclusive (see AnalysisDataModel.h) are missing are not there. +// Therefore, the syntax is more complicated because we cannot join against Collision +// (the tables have different number of entries) // Only to be used if one is sure that all your events have the desired information struct IterateV0Exclusive { - void process(aod::Run2MatchedExclusive::iterator const& m, aod::Collisions const&, aod::FV0As const&) + void process(aod::Run2MatchedExclusive::iterator const& matcher, aod::Collisions const&, aod::FV0As const&) { - LOGF(INFO, "Vertex = %f", m.collision().posZ()); - auto v0a = m.fv0a(); - LOGF(info, "V0: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); + LOGF(INFO, "Vertex = %f", matcher.collision().posZ()); + auto fv0a = matcher.fv0a(); + LOGF(info, "V0: %f %f", fv0a.amplitude()[0], fv0a.amplitude()[1]); } }; // This example builds on IterateV0 and in addition accesses also the tracks grouped to the specific collision. -// The tracks are directly access through its pointer. +// The tracks are directly accessed through its pointer as usual struct IterateV0Tracks { - void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::FV0As const&, aod::Tracks const& tracks) - { - LOGF(INFO, "Vertex = %f. %d tracks", m.collision().posZ(), tracks.size()); - if (m.has_fv0a()) { - auto v0a = m.fv0a(); - LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); - } else { - LOGF(INFO, "No V0A info"); - } - } -}; - -// IterateV0Tracks with join. Desired version for good readability -// NOTE: index table needs to be always last argument -// NOTE: subsribing to Collisions separately will lead to a circular dependency -// due to forwarding -using CollisionMatchedRun2Sparse = soa::Join<aod::Collisions, aod::Run2MatchedSparse>::iterator; -struct IterateV0Tracks2 { - void process(CollisionMatchedRun2Sparse const& m, aod::FV0As const&, aod::Tracks const& tracks) + void process(aod::CollisionMatchedRun2Sparse const& collisionMatched, aod::FV0As const&, aod::Tracks const& tracks) { - LOGF(INFO, "Vertex = %f. %d tracks", m.posZ(), tracks.size()); - if (m.has_fv0a()) { - auto v0a = m.fv0a(); + LOGF(INFO, "Vertex = %f. %d tracks", collisionMatched.posZ(), tracks.size()); + if (collisionMatched.has_fv0a()) { + auto v0a = collisionMatched.fv0a(); LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); } else { LOGF(INFO, "No V0A info"); @@ -83,17 +69,17 @@ struct IterateV0Tracks2 { // This example accesses V0 and ZDC information struct IterateV0ZDC { - void process(aod::Run2MatchedSparse::iterator const& m, aod::Collisions const&, aod::FV0As const&, aod::Zdcs const&) + void process(aod::CollisionMatchedRun2Sparse const& collisionMatched, aod::FV0As const&, aod::Zdcs const&) { - LOGF(INFO, "Vertex = %f", m.collision().posZ()); - if (m.has_fv0a()) { - auto v0a = m.fv0a(); + LOGF(INFO, "Vertex = %f", collisionMatched.posZ()); + if (collisionMatched.has_fv0a()) { + auto v0a = collisionMatched.fv0a(); LOGF(info, "V0A: %f %f", v0a.amplitude()[0], v0a.amplitude()[1]); } else { LOGF(INFO, "No V0A info"); } - if (m.has_zdc()) { - LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", m.zdc().energyZEM1(), m.zdc().energyZEM2()); + if (collisionMatched.has_zdc()) { + LOGF(INFO, "ZDC: E1 = %.3f; E2 = %.3f", collisionMatched.zdc().energyZEM1(), collisionMatched.zdc().energyZEM2()); } else { LOGF(INFO, "No ZDC info"); } @@ -106,7 +92,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) adaptAnalysisTask<IterateV0>("iterate-v0"), adaptAnalysisTask<IterateV0Exclusive>("iterate-v0-exclusive"), adaptAnalysisTask<IterateV0Tracks>("iterate-v0-tracks"), - adaptAnalysisTask<IterateV0Tracks2>("iterate-v0-tracks2"), adaptAnalysisTask<IterateV0ZDC>("iterate-v0-zdc"), }; } diff --git a/Analysis/Tutorials/src/compatibleBCs.cxx b/Analysis/Tutorials/src/compatibleBCs.cxx new file mode 100644 index 0000000000000..05e653fd31465 --- /dev/null +++ b/Analysis/Tutorials/src/compatibleBCs.cxx @@ -0,0 +1,102 @@ +// 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 "CommonConstants/LHCConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// In Run 3 the association between collisions and bunch crossings is not unique as the time of a collision vertex +// is derived from the track information themselves. + +template <typename T> +T getCompatibleBCs(aod::Collision const& collision, T const& bcs) +{ + auto bcIter = collision.bc_as<T>(); + + // due to the filling scheme the most probably BC may not be the one estimated from the collision time + uint64_t mostProbableBC = bcIter.globalBC(); + uint64_t meanBC = mostProbableBC - std::lround(collision.collisionTime() / (o2::constants::lhc::LHCBunchSpacingNS / 1000)); + int deltaBC = std::ceil(collision.collisionTimeRes() / (o2::constants::lhc::LHCBunchSpacingNS / 1000) * 4); + + LOGF(INFO, "BC range: %llu - %llu", meanBC - deltaBC, meanBC + deltaBC); + + // find slice of BCs table with BC in [meanBC - deltaBC, meanBC + deltaBC] + int64_t maxBCId = bcIter.globalIndex(); + int moveCount = 0; // optimize to avoid to re-create the iterator + while (bcIter != bcs.end() && bcIter.globalBC() <= meanBC + deltaBC && bcIter.globalBC() >= meanBC - deltaBC) { + LOGF(DEBUG, "Table id %d BC %llu", bcIter.globalIndex(), bcIter.globalBC()); + maxBCId = bcIter.globalIndex(); + ++bcIter; + ++moveCount; + } + + bcIter.moveByIndex(-moveCount); // Move back to original position + int64_t minBCId = collision.bcId(); + while (bcIter != bcs.begin() && bcIter.globalBC() <= meanBC + deltaBC && bcIter.globalBC() >= meanBC - deltaBC) { + LOGF(DEBUG, "Table id %d BC %llu", bcIter.globalIndex(), bcIter.globalBC()); + minBCId = bcIter.globalIndex(); + --bcIter; + } + + LOGF(INFO, "Will consider BC entries from %d to %d", minBCId, maxBCId); + + return T{{bcs.asArrowTable()->Slice(minBCId, maxBCId - minBCId + 1)}, (uint64_t)minBCId}; +} + +// Example 1 (academic, because it is not enough to just access the BC table): +// This task shows how to loop over the bunch crossings which are compatible with the estimated collision time. +struct CompatibleBCs { + void process(aod::Collision const& collision, aod::BCs const& bcs) + { + LOGF(INFO, "Vertex with most probably BC %llu and collision time %f +- %f ps", collision.bc().globalBC(), collision.collisionTime(), collision.collisionTimeRes()); + + auto bcSlice = getCompatibleBCs(collision, bcs); + + for (auto& bc : bcSlice) { + LOGF(info, "This collision may belong to BC %lld", bc.globalBC()); + } + } +}; + +// Example 2: +// Using getCompatibleBCs to retrieve the entries of several tables linked through the BC table (here FT0 and FV0A) +// and making sure that one has the direct association between them +// Note that one has to subscribe to aod::FT0s and aod::FV0As to load +// the relevant data even if you access the data itself through m.ft0() and m.fv0a() +struct CompatibleT0V0A { + void process(aod::Collision const& collision, soa::Join<aod::BCs, aod::Run3MatchedToBCSparse> const& bct0s, aod::FT0s& ft0s, aod::FV0As& fv0as) + { + // NOTE collision.bc() causes SEGV here because we have only subscribed to BCs joined, therefore: + auto bc = collision.bc_as<soa::Join<aod::BCs, aod::Run3MatchedToBCSparse>>(); + LOGF(INFO, "Vertex with most probable BC %llu and collision time %f +- %f ps", bc.globalBC(), collision.collisionTime(), collision.collisionTimeRes()); + + auto bcSlice = getCompatibleBCs(collision, bct0s); + // TODO move to getCompatibleBCs + bcSlice.bindExternalIndices(&ft0s, &fv0as); + + for (auto& bc : bcSlice) { + if (bc.has_ft0() && bc.has_fv0a()) { + LOGF(info, "This collision may belong to BC %lld and has T0 timeA: %f and V0A time: %f", bc.globalBC(), bc.ft0().timeA(), bc.fv0a().time()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<CompatibleBCs>("compatible-bcs"), + adaptAnalysisTask<CompatibleT0V0A>("compatible-t0-v0a"), + }; +} diff --git a/Analysis/Tutorials/src/muonIteration.cxx b/Analysis/Tutorials/src/muonIteration.cxx index 509fdb88b6ea4..e32237a006229 100644 --- a/Analysis/Tutorials/src/muonIteration.cxx +++ b/Analysis/Tutorials/src/muonIteration.cxx @@ -17,15 +17,13 @@ using namespace o2::framework::expressions; // This task shows how to access the Muons belong to a collision // The association is made through the BC column (and in Run 3 may not be unique!) -// To run this workflow, the o2-analysis-run(2,3)-matcher has to be run as well. -// Example: o2-analysis-run2-matcher --aod-file AO2D.root | o2-analysistutorial-muon-iteration // // Note that one has to subscribe to aod::Collisions const& to load // the relevant data even if you access the data itself through m.collision() // This uses the exclusive matcher, so you only get BCs which have a collision // If you want also BCs without collision, see the example IterateMuonsSparse below struct IterateMuons { - void process(aod::BCCollisionsExclusive::iterator const& m, aod::Collisions const&, aod::Muons const& muons) + void process(aod::MatchedBCCollisionsExclusive::iterator const& m, aod::Collisions const&, aod::Muons const& muons) { LOGF(INFO, "Vertex = %f has %d muons", m.collision().posZ(), muons.size()); for (auto& muon : muons) { @@ -37,7 +35,7 @@ struct IterateMuons { // This uses the sparase matcher, so you also get BCs without a collision. // You need to check with m.has_collision() struct IterateMuonsSparse { - void process(aod::BCCollisionsSparse::iterator const& m, aod::Collisions const&, aod::Muons const& muons) + void process(aod::MatchedBCCollisionsSparse::iterator const& m, aod::Collisions const&, aod::Muons const& muons) { if (m.has_collision()) { LOGF(INFO, "Vertex = %f has %d muons", m.collision().posZ(), muons.size()); diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 208a4668784ac..5262f42247f05 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -697,6 +697,19 @@ struct RowViewCore : public IP, C... { return copy; } + RowViewCore& operator--() + { + this->moveByIndex(-1); + return *this; + } + + RowViewCore operator--(int) + { + RowViewCore<IP, C...> copy = *this; + this->operator--(); + return copy; + } + /// Allow incrementing by more than one the iterator RowViewCore operator+(int64_t inc) const { diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 6c8d89a7985c2..fe08af8f20b56 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -617,6 +617,7 @@ DECLARE_SOA_INDEX_COLUMN(FT0, ft0); DECLARE_SOA_INDEX_COLUMN(FDD, fdd); } // namespace indices +// First entry: Collision #define INDEX_LIST_RUN2 indices::CollisionId, indices::ZdcId, indices::BCId, indices::FT0Id, indices::FV0AId, indices::FV0CId, indices::FDDId DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run2MatchedExclusive, BCs, "MA_RN2_EX", INDEX_LIST_RUN2); DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); @@ -625,8 +626,17 @@ DECLARE_SOA_INDEX_TABLE(Run2MatchedSparse, BCs, "MA_RN2_SP", INDEX_LIST_RUN2); DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run3MatchedExclusive, BCs, "MA_RN3_EX", INDEX_LIST_RUN3); DECLARE_SOA_INDEX_TABLE(Run3MatchedSparse, BCs, "MA_RN3_SP", INDEX_LIST_RUN3); -DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(BCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); -DECLARE_SOA_INDEX_TABLE(BCCollisionsSparse, BCs, "MA_BCCOL_SP", indices::BCId, indices::CollisionId); +// First entry: BC +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(MatchedBCCollisionsExclusive, BCs, "MA_BCCOL_EX", indices::BCId, indices::CollisionId); +DECLARE_SOA_INDEX_TABLE(MatchedBCCollisionsSparse, BCs, "MA_BCCOL_SP", indices::BCId, indices::CollisionId); + +DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(Run3MatchedToBCExclusive, BCs, "MA_RN3_BC_EX", indices::BCId, indices::ZdcId, indices::FT0Id, indices::FV0AId, indices::FDDId); +DECLARE_SOA_INDEX_TABLE(Run3MatchedToBCSparse, BCs, "MA_RN3_BC_SP", indices::BCId, indices::ZdcId, indices::FT0Id, indices::FV0AId, indices::FDDId); + +// Joins with collisions (only for sparse ones) +// NOTE: index table needs to be always last argument +using CollisionMatchedRun2Sparse = soa::Join<Collisions, Run2MatchedSparse>::iterator; +using CollisionMatchedRun3Sparse = soa::Join<Collisions, Run3MatchedSparse>::iterator; } // namespace aod diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index bbea0b177e852..dff636309a7e7 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -119,9 +119,13 @@ AlgorithmSpec AODReaderHelpers::indexBuilderCallback(std::vector<InputSpec> requ } else if (description == header::DataDescription{"MA_RN3_SP"}) { outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedSparseMetadata{})); } else if (description == header::DataDescription{"MA_BCCOL_EX"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsExclusiveMetadata{})); + outputs.adopt(Output{origin, description}, maker(o2::aod::MatchedBCCollisionsExclusiveMetadata{})); } else if (description == header::DataDescription{"MA_BCCOL_SP"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::BCCollisionsSparseMetadata{})); + outputs.adopt(Output{origin, description}, maker(o2::aod::MatchedBCCollisionsSparseMetadata{})); + } else if (description == header::DataDescription{"MA_RN3_BC_SP"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedToBCSparseMetadata{})); + } else if (description == header::DataDescription{"MA_RN3_BC_EX"}) { + outputs.adopt(Output{origin, description}, maker(o2::aod::Run3MatchedToBCExclusiveMetadata{})); } else { throw std::runtime_error("Not an index table"); } From 42b0ae3f68636203eb547dd046a3c1e962ed9e24 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 3 Dec 2020 09:55:32 +0100 Subject: [PATCH 1501/1751] DPL Analysis: metric for files opened (#4971) --- Framework/Core/src/AODReaderHelpers.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index dff636309a7e7..653cd01dbbb24 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -245,6 +245,12 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() int fcnt = (*fileCounter * device.maxInputTimeslices) + device.inputTimesliceId; int ntf = *numTF + 1; monitoring.send(Metric{(uint64_t)ntf, "tf-sent"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + static int currentFileCounter = -1; + static int filesProcessed = 0; + if (currentFileCounter != *fileCounter) { + currentFileCounter = *fileCounter; + monitoring.send(Metric{(uint64_t)++filesProcessed, "files-opened"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + } // loop over requested tables TTree* tr = nullptr; From 949d94fd627706d0d24823028f575f436b37ac2b Mon Sep 17 00:00:00 2001 From: Michael Lettrich <MichaelLettrich@users.noreply.github.com> Date: Thu, 3 Dec 2020 10:01:42 +0100 Subject: [PATCH 1502/1751] (O2-1813)[GPU] Rename double overloads for math functions (#4871) * [GPU] Rename double overloads for math functions * GPU: Workaround for long-standing OpenCL template issuee * Fix for opencl compilation Co-authored-by: David Rohr <github@jwdt.org> Co-authored-by: David Rohr <drohr@jwdt.org> --- Common/MathUtils/include/MathUtils/Utils.h | 4 +-- .../include/MathUtils/detail/trigonometric.h | 26 ++++++++++++++----- GPU/Common/GPUCommonMath.h | 11 ++++---- GPU/TPCFastTransformation/Spline1DHelper.cxx | 2 +- GPU/TPCFastTransformation/Spline2DHelper.cxx | 4 +-- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index d8c4061b4667a..4b656580d5a5a 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -106,12 +106,12 @@ inline void bringToPMPid(double& phi) GPUdi() void sincos(float ang, float& s, float& c) { - detail::sincos(ang, s, c); + detail::sincos<float>(ang, s, c); } GPUdi() void sincosd(double ang, double& s, double& c) { - detail::sincos(ang, s, c); + detail::sincos<double>(ang, s, c); } #ifndef GPUCA_GPUCODE_DEVICE diff --git a/Common/MathUtils/include/MathUtils/detail/trigonometric.h b/Common/MathUtils/include/MathUtils/detail/trigonometric.h index 5ea0609af8634..aa8a0dc891bb7 100644 --- a/Common/MathUtils/include/MathUtils/detail/trigonometric.h +++ b/Common/MathUtils/include/MathUtils/detail/trigonometric.h @@ -107,14 +107,16 @@ inline void bringToPMPiGen(T& phi) phi = toPMPiGen<T>(phi); } -GPUdi() void sincos(float ang, float& s, float& c) +template <typename T> +GPUdi() void sincos(T ang, GPUgeneric() T& s, GPUgeneric() T& c) { - o2::gpu::GPUCommonMath::SinCos(ang, s, c); + return o2::gpu::GPUCommonMath::SinCos(ang, s, c); } -GPUdi() void sincos(double ang, double& s, double& c) +template <> +GPUdi() void sincos(double ang, GPUgeneric() double& s, GPUgeneric() double& c) { - o2::gpu::GPUCommonMath::SinCos(ang, s, c); + return o2::gpu::GPUCommonMath::SinCosd(ang, s, c); } #ifndef GPUCA_GPUCODE_DEVICE @@ -124,7 +126,7 @@ GPUhdi() std::tuple<T, T> sincos(T ang) { T sin = 0; T cos = 0; - o2::gpu::GPUCommonMath::SinCos(ang, sin, cos); + sincos<T>(ang, sin, cos); return std::make_tuple(sin, cos); } @@ -194,6 +196,18 @@ inline T angle2Alpha(T phi) return sector2Angle<T>(angle2Sector<T>(phi)); } +template <typename T> +GPUhdi() T copysign(T x, T y) +{ + return o2::gpu::GPUCommonMath::Copysign(x, y); +} + +template <> +GPUhdi() double copysign(double x, double y) +{ + return o2::gpu::GPUCommonMath::Copysignd(x, y); +} + template <typename T> GPUhdi() T fastATan2(T y, T x) { @@ -233,7 +247,7 @@ GPUhdi() T fastATan2(T y, T x) }; // fast atan2(y,x) for any angle [-Pi,Pi] - return o2::gpu::GPUCommonMath::Copysign(atan2P(o2::gpu::GPUCommonMath::Abs(y), x), y); + return copysign<T>(atan2P(o2::gpu::GPUCommonMath::Abs(y), x), y); } } // namespace detail diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 5b57248916ed2..22b33479b952d 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -62,10 +62,10 @@ class GPUCommonMath GPUd() static float Sin(float x); GPUd() static float Cos(float x); GPUhdni() static void SinCos(float x, float& s, float& c); - GPUhdni() static void SinCos(double x, double& s, double& c); + GPUhdni() static void SinCosd(double x, double& s, double& c); GPUd() static float Tan(float x); GPUhdni() static float Copysign(float x, float y); - GPUhdni() static double Copysign(double x, double y); + GPUhdni() static double Copysignd(double x, double y); GPUd() static float TwoPi() { return 6.28319f; } GPUd() static float Pi() { return 3.1415926535897f; } GPUd() static int Nint(float x); @@ -250,7 +250,7 @@ GPUhdi() void GPUCommonMath::SinCos(float x, float& s, float& c) #endif } -GPUhdi() void GPUCommonMath::SinCos(double x, double& s, double& c) +GPUhdi() void GPUCommonMath::SinCosd(double x, double& s, double& c) { #if !defined(GPUCA_GPUCODE_DEVICE) && defined(__APPLE__) __sincos(x, &s, &c); @@ -280,7 +280,8 @@ GPUdi() unsigned int GPUCommonMath::Clz(unsigned int x) GPUdi() unsigned int GPUCommonMath::Popcount(unsigned int x) { #if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__)) && (!defined(__OPENCL__) /*|| defined(__OPENCLCPP__)*/) // TODO: remove OPENCLCPP workaround when reported SPIR-V bug is fixed - return CHOICE(__builtin_popcount(x), __popc(x), __builtin_popcount(x)); // use builtin if available + // use builtin if available + return CHOICE(__builtin_popcount(x), __popc(x), __builtin_popcount(x)); #else unsigned int retVal = 0; for (int i = 0; i < 32; i++) { @@ -400,7 +401,7 @@ GPUhdi() float GPUCommonMath::Copysign(float x, float y) #endif // GPUCA_GPUCODE } -GPUhdi() double GPUCommonMath::Copysign(double x, double y) +GPUhdi() double GPUCommonMath::Copysignd(double x, double y) { #if defined(__OPENCLCPP__) return copysign(x, y); diff --git a/GPU/TPCFastTransformation/Spline1DHelper.cxx b/GPU/TPCFastTransformation/Spline1DHelper.cxx index ac0998fe9529c..72840fa10a1ee 100644 --- a/GPU/TPCFastTransformation/Spline1DHelper.cxx +++ b/GPU/TPCFastTransformation/Spline1DHelper.cxx @@ -501,7 +501,7 @@ int Spline1DHelper<DataT>::test(const bool draw, const bool drawDataPoints) double cosx[Fdegree + 1], sinx[Fdegree + 1]; double xi = 0; for (int i = 0; i <= Fdegree; i++, xi += x) { - GPUCommonMath::SinCos(xi, sinx[i], cosx[i]); + GPUCommonMath::SinCosd(xi, sinx[i], cosx[i]); } for (int dim = 0; dim < Ndim; dim++) { f[dim] = 0; // Fcoeff[0]/2; diff --git a/GPU/TPCFastTransformation/Spline2DHelper.cxx b/GPU/TPCFastTransformation/Spline2DHelper.cxx index 0833b9e0a3be9..580db36949067 100644 --- a/GPU/TPCFastTransformation/Spline2DHelper.cxx +++ b/GPU/TPCFastTransformation/Spline2DHelper.cxx @@ -245,8 +245,8 @@ int Spline2DHelper<DataT>::test(const bool draw, const bool drawDataPoints) double cosu[Fdegree + 1], sinu[Fdegree + 1], cosv[Fdegree + 1], sinv[Fdegree + 1]; double ui = 0, vi = 0; for (int i = 0; i <= Fdegree; i++, ui += uu, vi += vv) { - GPUCommonMath::SinCos(ui, sinu[i], cosu[i]); - GPUCommonMath::SinCos(vi, sinv[i], cosv[i]); + GPUCommonMath::SinCosd(ui, sinu[i], cosu[i]); + GPUCommonMath::SinCosd(vi, sinv[i], cosv[i]); } for (int dim = 0; dim < Ndim; dim++) { double f = 0; // Fcoeff[dim][0]/2; From 60b41a1de4ccc20a31d75a57edd69709c201556f Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <9267733+fweig@users.noreply.github.com> Date: Thu, 3 Dec 2020 10:02:14 +0100 Subject: [PATCH 1503/1751] TPCClusterFinder: Add optional filter for noisy pads. (#4850) * TPCClusterFinder: Add optional step to check if pads have lost baseline. * fixfelix Co-authored-by: David Rohr <drohr@jwdt.org> --- GPU/Common/GPUDefGPUParameters.h | 1 + .../Base/GPUReconstructionIncludesDevice.h | 1 + .../Base/GPUReconstructionKernels.h | 1 + GPU/GPUTracking/Base/GPUSettingsList.h | 3 + GPU/GPUTracking/CMakeLists.txt | 1 + GPU/GPUTracking/Global/GPUChainTracking.cxx | 14 +++- GPU/GPUTracking/TPCClusterFinder/CfFragment.h | 15 ++++ .../GPUTPCCFCheckPadBaseline.cxx | 80 +++++++++++++++++++ .../GPUTPCCFCheckPadBaseline.h | 75 +++++++++++++++++ .../TPCClusterFinder/GPUTPCCFPeakFinder.cxx | 10 ++- .../TPCClusterFinder/GPUTPCCFPeakFinder.h | 2 +- .../TPCClusterFinder/GPUTPCClusterFinder.cxx | 1 + .../TPCClusterFinder/GPUTPCClusterFinder.h | 4 + .../GPUTPCClusterFinderKernels.h | 1 + .../TPCClusterFinder/TPCPadGainCalib.h | 9 ++- 15 files changed, 209 insertions(+), 9 deletions(-) create mode 100644 GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.cxx create mode 100644 GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.h diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 265932ec114aa..3d5151b0c4d63 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -352,6 +352,7 @@ #define GPUCA_THREAD_COUNT_SCAN 512 // TODO: WARNING!!! Must not be GPUTYPE-dependent right now! // TODO: Fix! +#define GPUCA_LB_GPUTPCCFCheckPadBaseline GPUCA_WARP_SIZE #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillIndexMap GPUCA_LB_CLUSTER_FINDER #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillFromDigits GPUCA_LB_CLUSTER_FINDER #define GPUCA_LB_GPUTPCCFChargeMapFiller_findFragmentStart GPUCA_LB_CLUSTER_FINDER diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h index a6aa6d19e8245..2a38c3f5a2ef9 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h @@ -77,6 +77,7 @@ using namespace GPUCA_NAMESPACE::gpu; #include "GPUTPCCFClusterizer.cxx" #include "GPUTPCCFDeconvolution.cxx" #include "GPUTPCCFMCLabelFlattener.cxx" +#include "GPUTPCCFCheckPadBaseline.cxx" #include "GPUTPCCFDecodeZS.cxx" #include "GPUTPCCFGather.cxx" diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index 5f8bca44375db..904b798debb6d 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -70,6 +70,7 @@ GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered64 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered128 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, multiBlock ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTPCCFCheckPadBaseline ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillIndexMap ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillFromDigits ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, findFragmentStart ), (single), (, char setPositions), (, setPositions)) diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 743d1d94553af..6b385d6d97c56 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -50,6 +50,9 @@ AddOptionRTC(tpcTubeMaxSize2, float, 2.5f * 2.5f, "", 0, "Square of max tube siz AddOptionRTC(trdMinTrackPt, float, .5f, "", 0, "Min Pt for tracks to be propagated through the TRD") AddOptionRTC(trdMaxChi2, float, 15.f, "", 0, "Max chi2 for TRD tracklets to be matched to a track") AddOptionRTC(trdPenaltyChi2, float, 12.f, "", 0, "Chi2 penalty for no available TRD tracklet (effective chi2 cut value)") +AddOptionRTC(noisyPadsQuickCheck, unsigned char, 1, "", 0, "Only check first fragment for noisy pads instead of all fragments (when test is enabled).") +AddOptionRTC(maxTimeBinAboveThresholdIn1000Bin, unsigned short, 500, "", 0, "Except pad from cluster finding if total number of charges in a fragment is above this baseline (disable = 0)") +AddOptionRTC(maxConsecTimeBinAboveThreshold, unsigned short, 200, "", 0, "Except pad from cluster finding if number of consecutive charges in a fragment is above this baseline (disable = 0)") AddOptionRTC(tpcCFqmaxCutoff, unsigned char, 3, "", 0, "Cluster Finder rejects cluster with qmax below this threshold") AddOptionRTC(tpcCFqtotCutoff, unsigned char, 0, "", 0, "Cluster Finder rejects cluster with qtot below this threshold") AddOptionRTC(tpcCFinnerThreshold, unsigned char, 0, "", 0, "Cluster Finder extends cluster if inner charge above this threshold") diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index adead49fe7227..434cff83d29ba 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -163,6 +163,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) TPCClusterFinder/GPUTPCClusterFinder.cxx TPCClusterFinder/ClusterAccumulator.cxx TPCClusterFinder/MCLabelAccumulator.cxx + TPCClusterFinder/GPUTPCCFCheckPadBaseline.cxx TPCClusterFinder/GPUTPCCFStreamCompaction.cxx TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx TPCClusterFinder/GPUTPCCFPeakFinder.cxx diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 717a9d25236fd..265c08efd9473 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1162,6 +1162,10 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) using PeakMapType = decltype(*clustererShadow.mPpeakMap); runKernel<GPUMemClean16>(GetGridAutoStep(lane, RecoStep::TPCClusterFinding), krnlRunRangeNone, {}, clustererShadow.mPchargeMap, TPCMapMemoryLayout<ChargeMapType>::items() * sizeof(ChargeMapType)); runKernel<GPUMemClean16>(GetGridAutoStep(lane, RecoStep::TPCClusterFinding), krnlRunRangeNone, {}, clustererShadow.mPpeakMap, TPCMapMemoryLayout<PeakMapType>::items() * sizeof(PeakMapType)); + if (fragment.index == 0) { + using HasLostBaselineType = decltype(*clustererShadow.mPpadHasLostBaseline); + runKernel<GPUMemClean16>(GetGridAutoStep(lane, RecoStep::TPCClusterFinding), krnlRunRangeNone, {}, clustererShadow.mPpadHasLostBaseline, TPC_PADS_IN_SECTOR * sizeof(HasLostBaselineType)); + } DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Zeroed Charges"); if (mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice]) { @@ -1221,6 +1225,14 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::fillIndexMap>(GetGrid(clusterer.mPmemory->counters.nDigitsInFragment, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}); } + bool checkForNoisyPads = (rec()->GetParam().rec.maxTimeBinAboveThresholdIn1000Bin > 0) || (rec()->GetParam().rec.maxConsecTimeBinAboveThreshold > 0); + checkForNoisyPads &= (rec()->GetParam().rec.noisyPadsQuickCheck ? fragment.index == 0 : true); + + if (checkForNoisyPads) { + int nBlocks = TPC_PADS_IN_SECTOR / GPUTPCCFCheckPadBaseline::getPadsPerBlock(doGPU); + runKernel<GPUTPCCFCheckPadBaseline>(GetGridBlk(nBlocks, lane), {iSlice}, {}); + } + runKernel<GPUTPCCFPeakFinder>(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpPeaks, *mDebugFile); @@ -1310,7 +1322,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) transferRunning[lane] = 1; } - if (not propagateMCLabels) { + if (not propagateMCLabels || clusterer.mPmemory->counters.nClusters == 0) { continue; } diff --git a/GPU/GPUTracking/TPCClusterFinder/CfFragment.h b/GPU/GPUTracking/TPCClusterFinder/CfFragment.h index 2d1574a98ad34..dd338ba77aab3 100644 --- a/GPU/GPUTracking/TPCClusterFinder/CfFragment.h +++ b/GPU/GPUTracking/TPCClusterFinder/CfFragment.h @@ -72,6 +72,21 @@ struct CfFragment { return (hasBacklog ? t < OverlapTimebins : false) || (hasFuture ? t >= (length - OverlapTimebins) : false); } + GPUdi() tpccf::TPCFragmentTime lengthWithoutOverlap() const + { + return length - (hasBacklog ? OverlapTimebins : 0) - (hasFuture ? OverlapTimebins : 0); + } + + GPUdi() tpccf::TPCFragmentTime firstNonOverlapTimeBin() const + { + return (hasBacklog ? OverlapTimebins : 0); + } + + GPUdi() tpccf::TPCFragmentTime lastNonOverlapTimeBin() const + { + return length - (hasFuture ? OverlapTimebins : 0); + } + GPUdi() tpccf::TPCFragmentTime toLocal(tpccf::TPCTime t) const { return t - first(); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.cxx new file mode 100644 index 0000000000000..d78ddf4a5e083 --- /dev/null +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.cxx @@ -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. + +/// \file GPUTPCCFCheckPadBaseline.h +/// \author Felix Weiglhofer + +#include "GPUTPCCFCheckPadBaseline.h" +#include "Array2D.h" +#include "PackedCharge.h" +#include "clusterFinderDefs.h" + +using namespace GPUCA_NAMESPACE::gpu; +using namespace GPUCA_NAMESPACE::gpu::tpccf; + +template <> +GPUd() void GPUTPCCFCheckPadBaseline::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer) +{ + static_assert(TPC_MAX_FRAGMENT_LEN % NumOfCachedTimebins == 0); + + Array2D<PackedCharge> chargeMap(reinterpret_cast<PackedCharge*>(clusterer.mPchargeMap)); + + int totalCharges = 0; + int consecCharges = 0; + int maxConsecCharges = 0; + + int localPadId = iThread / NumOfCachedTimebins; + int localTimeBin = iThread % NumOfCachedTimebins; + bool handlePad = localTimeBin == 0; + int basePad = iBlock * PadsPerBlock; + + CfFragment& fragment = clusterer.mPmemory->fragment; + + ChargePos basePos = padToChargePos(basePad + localPadId, clusterer); + + for (tpccf::TPCFragmentTime t = localTimeBin + fragment.firstNonOverlapTimeBin(); t < fragment.lastNonOverlapTimeBin(); t += NumOfCachedTimebins) { + ChargePos pos = basePos.delta({0, t}); + smem.charges[localPadId][localTimeBin] = (pos.valid()) ? chargeMap[pos].unpack() : 0; + GPUbarrierWarp(); + if (handlePad) { + for (int i = 0; i < NumOfCachedTimebins; i++) { + Charge q = smem.charges[localPadId][i]; + totalCharges += (q > 0); + consecCharges = (q > 0) ? consecCharges + 1 : 0; + maxConsecCharges = CAMath::Max(consecCharges, maxConsecCharges); + } + } + } + + GPUbarrierWarp(); + + if (handlePad) { + int totalChargesBaseline = clusterer.Param().rec.maxTimeBinAboveThresholdIn1000Bin * fragment.lengthWithoutOverlap() / 1000; + int consecChargesBaseline = clusterer.Param().rec.maxConsecTimeBinAboveThreshold; + bool hasLostBaseline = (totalChargesBaseline > 0 && totalCharges >= totalChargesBaseline) || (consecChargesBaseline > 0 && maxConsecCharges >= consecChargesBaseline); + clusterer.mPpadHasLostBaseline[basePad + localPadId] |= hasLostBaseline; + } +} + +GPUd() ChargePos GPUTPCCFCheckPadBaseline::padToChargePos(int pad, const GPUTPCClusterFinder& clusterer) +{ + const GPUTPCGeometry& geo = clusterer.Param().tpcGeometry; + + int padOffset = 0; + for (Row r = 0; r < TPC_NUM_OF_ROWS; r++) { + int padInRow = pad - padOffset; + if (0 <= padInRow && padInRow < geo.NPads(r)) { + return ChargePos{r, Pad(padInRow), 0}; + } + padOffset += geo.NPads(r); + } + + return ChargePos{0, 0, INVALID_TIME_BIN}; +} diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.h new file mode 100644 index 0000000000000..0a0efee0c957c --- /dev/null +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFCheckPadBaseline.h @@ -0,0 +1,75 @@ +// 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 GPUTPCCFCheckPadBaseline.h +/// \author Felix Weiglhofer + +#ifndef O2_GPU_GPU_TPC_CF_CHECK_PAD_BASELINE_H +#define O2_GPU_GPU_TPC_CF_CHECK_PAD_BASELINE_H + +#include "GPUGeneralKernels.h" +#include "GPUConstantMem.h" + +#include "clusterFinderDefs.h" + +namespace GPUCA_NAMESPACE::gpu +{ + +class GPUTPCCFCheckPadBaseline : public GPUKernelTemplate +{ + + private: + // Only use these constants on device side... + // Use getPadsPerBlock() for host side + enum { + PadsPerBlockGPU = 4, // Number of pads in a single cache line + PadsPerBlockCPU = 1, +#ifdef GPUCA_GPUCODE + PadsPerBlock = PadsPerBlockGPU, +#else + PadsPerBlock = PadsPerBlockCPU, +#endif + NumOfCachedTimebins = GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCCFCheckPadBaseline) / PadsPerBlock, + }; + + public: + struct GPUSharedMemory { + tpccf::Charge charges[PadsPerBlock][NumOfCachedTimebins]; + }; + +#ifdef HAVE_O2HEADERS + typedef GPUTPCClusterFinder processorType; + GPUhdi() static processorType* Processor(GPUConstantMem& processors) + { + return processors.tpcClusterer; + } +#endif + + GPUhdi() CONSTEXPR static GPUDataTypes::RecoStep GetRecoStep() + { + return GPUDataTypes::RecoStep::TPCClusterFinding; + } + + // Use this to get num of pads per block on host side. Can't use constant there. + static int getPadsPerBlock(bool isGPU) + { + return (isGPU) ? PadsPerBlockGPU : PadsPerBlockCPU; + } + + template <int iKernel = defaultKernel> + GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer); + + private: + GPUd() static ChargePos padToChargePos(int pad, const GPUTPCClusterFinder&); +}; + +} // namespace GPUCA_NAMESPACE::gpu + +#endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx index 7678c68ce1224..e812f5e00fb2d 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx @@ -26,7 +26,7 @@ GPUdii() void GPUTPCCFPeakFinder::Thread<0>(int nBlocks, int nThreads, int iBloc { Array2D<PackedCharge> chargeMap(reinterpret_cast<PackedCharge*>(clusterer.mPchargeMap)); Array2D<uchar> isPeakMap(clusterer.mPpeakMap); - findPeaksImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions, clusterer.Param().rec, clusterer.mPisPeak, isPeakMap); + findPeaksImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, chargeMap, clusterer.mPpadHasLostBaseline, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions, clusterer.Param().rec, *clusterer.GetConstantMem()->calibObjects.tpcPadGain, clusterer.mPisPeak, isPeakMap); } GPUdii() bool GPUTPCCFPeakFinder::isPeak( @@ -91,9 +91,11 @@ GPUdii() bool GPUTPCCFPeakFinder::isPeak( GPUd() void GPUTPCCFPeakFinder::findPeaksImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, const Array2D<PackedCharge>& chargeMap, + const uchar* padHasLostBaseline, const ChargePos* positions, SizeT digitnum, const GPUSettingsRec& calib, + const TPCPadGainCalib& gainCorrection, // Only used for globalPad() function uchar* isPeakPredicate, Array2D<uchar>& peakMap) { @@ -105,8 +107,10 @@ GPUd() void GPUTPCCFPeakFinder::findPeaksImpl(int nBlocks, int nThreads, int iBl ChargePos pos = positions[CAMath::Min(idx, (SizeT)(digitnum - 1))]; Charge charge = pos.valid() ? chargeMap[pos].unpack() : Charge(0); - uchar peak; - peak = isPeak(smem, charge, pos, SCRATCH_PAD_SEARCH_N, chargeMap, calib, smem.posBcast, smem.buf); + bool hasLostBaseline = padHasLostBaseline[gainCorrection.globalPad(pos.row(), pos.pad())]; + charge = (hasLostBaseline) ? 0.f : charge; + + uchar peak = isPeak(smem, charge, pos, SCRATCH_PAD_SEARCH_N, chargeMap, calib, smem.posBcast, smem.buf); // Exit early if dummy. See comment above. bool iamDummy = (idx >= digitnum); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h index 54d878d012562..e6107af137313 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.h @@ -52,7 +52,7 @@ class GPUTPCCFPeakFinder : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUd() void findPeaksImpl(int, int, int, int, GPUSharedMemory&, const Array2D<PackedCharge>&, const ChargePos*, tpccf::SizeT, const GPUSettingsRec&, uchar*, Array2D<uchar>&); + static GPUd() void findPeaksImpl(int, int, int, int, GPUSharedMemory&, const Array2D<PackedCharge>&, const uchar*, const ChargePos*, tpccf::SizeT, const GPUSettingsRec&, const TPCPadGainCalib&, uchar*, Array2D<uchar>&); static GPUd() bool isPeak(GPUSharedMemory&, tpccf::Charge, const ChargePos&, ushort, const Array2D<PackedCharge>&, const GPUSettingsRec&, ChargePos*, PackedCharge*); }; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx index bab748e6f44b6..37d35ebcb149e 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx @@ -75,6 +75,7 @@ void* GPUTPCClusterFinder::SetPointersOutput(void* mem) void* GPUTPCClusterFinder::SetPointersScratch(void* mem) { + computePointerWithAlignment(mem, mPpadHasLostBaseline, TPC_PADS_IN_SECTOR); computePointerWithAlignment(mem, mPpositions, mNMaxDigitsFragment); computePointerWithAlignment(mem, mPpeakPositions, mNMaxPeaks); computePointerWithAlignment(mem, mPfilteredPeakPositions, mNMaxClusters); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index 90237b7fe47ea..944c2be4de71c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -48,6 +48,8 @@ struct TPCPadGainCalib; struct ChargePos; +class GPUTPCGeometry; + class GPUTPCClusterFinder : public GPUProcessor { public: @@ -96,6 +98,7 @@ class GPUTPCClusterFinder : public GPUProcessor unsigned char* mPzs = nullptr; ZSOffset* mPzsOffsets = nullptr; MinMaxCN* mMinMaxCN = nullptr; + unsigned char* mPpadHasLostBaseline = nullptr; tpc::Digit* mPdigits = nullptr; // input digits, only set if ZS is skipped ChargePos* mPpositions = nullptr; ChargePos* mPpeakPositions = nullptr; @@ -136,6 +139,7 @@ class GPUTPCClusterFinder : public GPUProcessor short mOutputId = -1; GPUdi() float getGainCorrection(tpccf::Row, tpccf::Pad) const; + GPUdi() const GPUTPCGeometry* getGeometry() const; #ifndef GPUCA_GPUCODE void DumpDigits(std::ostream& out); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderKernels.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderKernels.h index e2298ad4e683a..2f0e5fe4166bb 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderKernels.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderKernels.h @@ -22,6 +22,7 @@ #include "GPUTPCCFStreamCompaction.h" #include "GPUTPCCFClusterizer.h" #include "GPUTPCCFMCLabelFlattener.h" +#include "GPUTPCCFCheckPadBaseline.h" #include "GPUTPCCFDecodeZS.h" #include "GPUTPCCFGather.h" diff --git a/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.h b/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.h index 40b975eef2369..cf26ef5e0168e 100644 --- a/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.h +++ b/GPU/GPUTracking/TPCClusterFinder/TPCPadGainCalib.h @@ -58,6 +58,11 @@ struct TPCPadGainCalib { return mGainCorrection[sector].get(globalPad(row, pad)); } + GPUdi() unsigned short globalPad(tpccf::Row row, tpccf::Pad pad) const + { + return mPadOffsetPerRow[row] + pad; + } + private: template <typename T = unsigned short> class SectorPadGainCorrection @@ -121,10 +126,6 @@ struct TPCPadGainCalib { unsigned short mPadOffsetPerRow[TPC_NUM_OF_ROWS]; SectorPadGainCorrection<unsigned short> mGainCorrection[TPC_SECTORS]; - GPUdi() unsigned short globalPad(tpccf::Row row, tpccf::Pad pad) const - { - return mPadOffsetPerRow[row] + pad; - } }; } // namespace GPUCA_NAMESPACE::gpu From b29e0e92977baaf3123fa478bcd98c6c02522229 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 1 Dec 2020 15:34:17 +0100 Subject: [PATCH 1504/1751] Include cpulimit tool Include cpulimit tool from commit f4d2682804931 https://github.com/opsengine/cpulimit for easy distribution/use within O2. --- Utilities/Tools/CMakeLists.txt | 1 + Utilities/Tools/cpulimit/.clang-format | 2 + Utilities/Tools/cpulimit/CMakeLists.txt | 15 + Utilities/Tools/cpulimit/README | 2 + Utilities/Tools/cpulimit/cpulimit.c | 530 ++++++++++++++++++ Utilities/Tools/cpulimit/list.c | 148 +++++ Utilities/Tools/cpulimit/list.h | 138 +++++ Utilities/Tools/cpulimit/memrchr.c | 38 ++ Utilities/Tools/cpulimit/process_group.c | 205 +++++++ Utilities/Tools/cpulimit/process_group.h | 55 ++ Utilities/Tools/cpulimit/process_iterator.c | 49 ++ Utilities/Tools/cpulimit/process_iterator.h | 97 ++++ .../Tools/cpulimit/process_iterator_apple.c | 148 +++++ .../Tools/cpulimit/process_iterator_freebsd.c | 119 ++++ .../Tools/cpulimit/process_iterator_linux.c | 181 ++++++ 15 files changed, 1728 insertions(+) create mode 100644 Utilities/Tools/cpulimit/.clang-format create mode 100644 Utilities/Tools/cpulimit/CMakeLists.txt create mode 100644 Utilities/Tools/cpulimit/README create mode 100644 Utilities/Tools/cpulimit/cpulimit.c create mode 100644 Utilities/Tools/cpulimit/list.c create mode 100644 Utilities/Tools/cpulimit/list.h create mode 100644 Utilities/Tools/cpulimit/memrchr.c create mode 100644 Utilities/Tools/cpulimit/process_group.c create mode 100644 Utilities/Tools/cpulimit/process_group.h create mode 100644 Utilities/Tools/cpulimit/process_iterator.c create mode 100644 Utilities/Tools/cpulimit/process_iterator.h create mode 100644 Utilities/Tools/cpulimit/process_iterator_apple.c create mode 100644 Utilities/Tools/cpulimit/process_iterator_freebsd.c create mode 100644 Utilities/Tools/cpulimit/process_iterator_linux.c diff --git a/Utilities/Tools/CMakeLists.txt b/Utilities/Tools/CMakeLists.txt index b8c1346d84d49..aa9a9ba83a6a0 100644 --- a/Utilities/Tools/CMakeLists.txt +++ b/Utilities/Tools/CMakeLists.txt @@ -8,6 +8,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +add_subdirectory(cpulimit) install(PROGRAMS monitor-mem.sh DESTINATION share/scripts/) install(PROGRAMS jobutils.sh DESTINATION share/scripts/) diff --git a/Utilities/Tools/cpulimit/.clang-format b/Utilities/Tools/cpulimit/.clang-format new file mode 100644 index 0000000000000..a43d914ec38dd --- /dev/null +++ b/Utilities/Tools/cpulimit/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: false \ No newline at end of file diff --git a/Utilities/Tools/cpulimit/CMakeLists.txt b/Utilities/Tools/cpulimit/CMakeLists.txt new file mode 100644 index 0000000000000..deeb42e6726ed --- /dev/null +++ b/Utilities/Tools/cpulimit/CMakeLists.txt @@ -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. + +add_executable(cpulimit + cpulimit.c list.c process_group.c process_iterator.c) +target_compile_definitions(cpulimit PUBLIC _GNU_SOURCE) + +install(TARGETS cpulimit DESTINATION share/scripts/) diff --git a/Utilities/Tools/cpulimit/README b/Utilities/Tools/cpulimit/README new file mode 100644 index 0000000000000..20f543f9491ee --- /dev/null +++ b/Utilities/Tools/cpulimit/README @@ -0,0 +1,2 @@ +These sources have been copied from https://github.com/opsengine/cpulimit +commit f4d2682804931e. \ No newline at end of file diff --git a/Utilities/Tools/cpulimit/cpulimit.c b/Utilities/Tools/cpulimit/cpulimit.c new file mode 100644 index 0000000000000..50eabeacf2144 --- /dev/null +++ b/Utilities/Tools/cpulimit/cpulimit.c @@ -0,0 +1,530 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ************************************************************** + * + * This is a simple program to limit the cpu usage of a process + * If you modify this code, send me a copy please + * + * Get the latest version at: http://github.com/opsengine/cpulimit + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <getopt.h> +#include <time.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/sysctl.h> +#include <sys/resource.h> +#include <sys/types.h> +#include <sys/wait.h> + +#ifdef __APPLE__ || __FREEBSD__ +#include <libgen.h> +#endif + +#include "process_group.h" +#include "list.h" + +#ifdef HAVE_SYS_SYSINFO_H +#include <sys/sysinfo.h> +#endif + +#ifdef __APPLE__ +#include "memrchr.c" +#endif + +//some useful macro +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +//control time slot in microseconds +//each slot is splitted in a working slice and a sleeping slice +//TODO: make it adaptive, based on the actual system load +#define TIME_SLOT 100000 + +#define MAX_PRIORITY -10 + +/* GLOBAL VARIABLES */ + +//the "family" +struct process_group pgroup; +//pid of cpulimit +pid_t cpulimit_pid; +//name of this program (maybe cpulimit...) +char *program_name; + +//number of cpu +int NCPU; + +/* CONFIGURATION VARIABLES */ + +//verbose mode +int verbose = 0; +//lazy mode (exits if there is no process) +int lazy = 0; + +//SIGINT and SIGTERM signal handler +static void quit(int sig) +{ + //let all the processes continue if stopped + struct list_node *node = NULL; + if (pgroup.proclist != NULL) + { + for (node = pgroup.proclist->first; node != NULL; node = node->next) { + struct process *p = (struct process*)(node->data); + kill(p->pid, SIGCONT); + } + close_process_group(&pgroup); + } + //fix ^C little problem + printf("\r"); + fflush(stdout); + exit(0); +} + +//return t1-t2 in microseconds (no overflow checks, so better watch out!) +static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2) +{ + return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec); +} + +static void print_usage(FILE *stream, int exit_code) +{ + fprintf(stream, "Usage: %s [OPTIONS...] TARGET\n", program_name); + fprintf(stream, " OPTIONS\n"); + fprintf(stream, " -l, --limit=N percentage of cpu allowed from 0 to %d (required)\n", 100*NCPU); + fprintf(stream, " -v, --verbose show control statistics\n"); + fprintf(stream, " -z, --lazy exit if there is no target process, or if it dies\n"); + fprintf(stream, " -i, --include-children limit also the children processes\n"); + fprintf(stream, " -h, --help display this help and exit\n"); + fprintf(stream, " TARGET must be exactly one of these:\n"); + fprintf(stream, " -p, --pid=N pid of the process (implies -z)\n"); + fprintf(stream, " -e, --exe=FILE name of the executable program file or path name\n"); + fprintf(stream, " COMMAND [ARGS] run this command and limit it (implies -z)\n"); + fprintf(stream, "\nReport bugs to <marlonx80@hotmail.com>.\n"); + exit(exit_code); +} + +static void increase_priority() { + //find the best available nice value + int old_priority = getpriority(PRIO_PROCESS, 0); + int priority = old_priority; + while (setpriority(PRIO_PROCESS, 0, priority-1) == 0 && priority>MAX_PRIORITY) { + priority--; + } + if (priority != old_priority) { + if (verbose) printf("Priority changed to %d\n", priority); + } + else { + if (verbose) printf("Warning: Cannot change priority. Run as root or renice for best results.\n"); + } +} + +/* Get the number of CPUs */ +static int get_ncpu() { + int ncpu; +#ifdef _SC_NPROCESSORS_ONLN + ncpu = sysconf(_SC_NPROCESSORS_ONLN); +#elif defined __APPLE__ + int mib[2] = {CTL_HW, HW_NCPU}; + size_t len = sizeof(ncpu); + sysctl(mib, 2, &ncpu, &len, NULL, 0); +#elif defined _GNU_SOURCE + ncpu = get_nprocs(); +#else + ncpu = -1; +#endif + return ncpu; +} + +int get_pid_max() +{ +#ifdef __linux__ + //read /proc/sys/kernel/pid_max + static char buffer[1024]; + FILE *fd = fopen("/proc/sys/kernel/pid_max", "r"); + if (fd==NULL) return -1; + if (fgets(buffer, sizeof(buffer), fd)==NULL) { + fclose(fd); + return -1; + } + fclose(fd); + return atoi(buffer); +#elif defined __FreeBSD__ + return 99998; +#elif defined __APPLE__ + return 99998; +#endif +} + +void limit_process(pid_t pid, double limit, int include_children) +{ + //slice of the slot in which the process is allowed to run + struct timespec twork; + //slice of the slot in which the process is stopped + struct timespec tsleep; + //when the last twork has started + struct timeval startwork; + //when the last twork has finished + struct timeval endwork; + //initialization + memset(&twork, 0, sizeof(struct timespec)); + memset(&tsleep, 0, sizeof(struct timespec)); + memset(&startwork, 0, sizeof(struct timeval)); + memset(&endwork, 0, sizeof(struct timeval)); + //last working time in microseconds + unsigned long workingtime = 0; + //generic list item + struct list_node *node; + //counter + int c = 0; + + //get a better priority + increase_priority(); + + //build the family + init_process_group(&pgroup, pid, include_children); + + if (verbose) printf("Members in the process group owned by %d: %d\n", pgroup.target_pid, pgroup.proclist->count); + + //rate at which we are keeping active the processes (range 0-1) + //1 means that the process are using all the twork slice + double workingrate = -1; + while(1) { + update_process_group(&pgroup); + + if (pgroup.proclist->count==0) { + if (verbose) printf("No more processes.\n"); + break; + } + + //total cpu actual usage (range 0-1) + //1 means that the processes are using 100% cpu + double pcpu = -1; + + //estimate how much the controlled processes are using the cpu in the working interval + for (node = pgroup.proclist->first; node != NULL; node = node->next) { + struct process *proc = (struct process*)(node->data); + if (proc->cpu_usage < 0) { + continue; + } + if (pcpu < 0) pcpu = 0; + pcpu += proc->cpu_usage; + } + + //adjust work and sleep time slices + if (pcpu < 0) { + //it's the 1st cycle, initialize workingrate + pcpu = limit; + workingrate = limit; + twork.tv_nsec = TIME_SLOT * limit * 1000; + } + else { + //adjust workingrate + workingrate = MIN(workingrate / pcpu * limit, 1); + twork.tv_nsec = TIME_SLOT * 1000 * workingrate; + } + tsleep.tv_nsec = TIME_SLOT * 1000 - twork.tv_nsec; + + if (verbose) { + if (c%200==0) + printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n"); + if (c%10==0 && c>0) + printf("%0.2lf%%\t%6ld us\t%6ld us\t%0.2lf%%\n", pcpu*100, twork.tv_nsec/1000, tsleep.tv_nsec/1000, workingrate*100); + } + + //resume processes + node = pgroup.proclist->first; + while (node != NULL) + { + struct list_node *next_node = node->next; + struct process *proc = (struct process*)(node->data); + if (kill(proc->pid,SIGCONT) != 0) { + //process is dead, remove it from family + if (verbose) fprintf(stderr, "SIGCONT failed. Process %d dead!\n", proc->pid); + //remove process from group + delete_node(pgroup.proclist, node); + remove_process(&pgroup, proc->pid); + } + node = next_node; + } + + //now processes are free to run (same working slice for all) + gettimeofday(&startwork, NULL); + nanosleep(&twork, NULL); + gettimeofday(&endwork, NULL); + workingtime = timediff(&endwork, &startwork); + + long delay = workingtime - twork.tv_nsec/1000; + if (c>0 && delay>10000) { + //delay is too much! signal to user? + //fprintf(stderr, "%d %ld us\n", c, delay); + } + + if (tsleep.tv_nsec>0) { + //stop processes only if tsleep>0 + node = pgroup.proclist->first; + while (node != NULL) + { + struct list_node *next_node = node->next; + struct process *proc = (struct process*)(node->data); + if (kill(proc->pid,SIGSTOP)!=0) { + //process is dead, remove it from family + if (verbose) fprintf(stderr, "SIGSTOP failed. Process %d dead!\n", proc->pid); + //remove process from group + delete_node(pgroup.proclist, node); + remove_process(&pgroup, proc->pid); + } + node = next_node; + } + //now the processes are sleeping + nanosleep(&tsleep,NULL); + } + c++; + } + close_process_group(&pgroup); +} + +int main(int argc, char **argv) { + //argument variables + const char *exe = NULL; + int perclimit = 0; + int exe_ok = 0; + int pid_ok = 0; + int limit_ok = 0; + pid_t pid = 0; + int include_children = 0; + + //get program name + char *p = (char*)memrchr(argv[0], (unsigned int)'/', strlen(argv[0])); + program_name = p==NULL ? argv[0] : (p+1); + //get current pid + cpulimit_pid = getpid(); + //get cpu count + NCPU = get_ncpu(); + + //parse arguments + int next_option; + int option_index = 0; + //A string listing valid short options letters + const char* short_options = "+p:e:l:vzih"; + //An array describing valid long options + const struct option long_options[] = { + { "pid", required_argument, NULL, 'p' }, + { "exe", required_argument, NULL, 'e' }, + { "limit", required_argument, NULL, 'l' }, + { "verbose", no_argument, NULL, 'v' }, + { "lazy", no_argument, NULL, 'z' }, + { "include-children", no_argument, NULL, 'i' }, + { "help", no_argument, NULL, 'h' }, + { 0, 0, 0, 0 } + }; + + do { + next_option = getopt_long(argc, argv, short_options,long_options, &option_index); + switch(next_option) { + case 'p': + pid = atoi(optarg); + pid_ok = 1; + break; + case 'e': + exe = optarg; + exe_ok = 1; + break; + case 'l': + perclimit = atoi(optarg); + limit_ok = 1; + break; + case 'v': + verbose = 1; + break; + case 'z': + lazy = 1; + break; + case 'i': + include_children = 1; + break; + case 'h': + print_usage(stdout, 1); + break; + case '?': + print_usage(stderr, 1); + break; + case -1: + break; + default: + abort(); + } + } while(next_option != -1); + + if (pid_ok && (pid <= 1 || pid >= get_pid_max())) { + fprintf(stderr,"Error: Invalid value for argument PID\n"); + print_usage(stderr, 1); + exit(1); + } + if (pid != 0) { + lazy = 1; + } + + if (!limit_ok) { + fprintf(stderr,"Error: You must specify a cpu limit percentage\n"); + print_usage(stderr, 1); + exit(1); + } + double limit = perclimit / 100.0; + if (limit<0 || limit >NCPU) { + fprintf(stderr,"Error: limit must be in the range 0-%d00\n", NCPU); + print_usage(stderr, 1); + exit(1); + } + + int command_mode = optind < argc; + if (exe_ok + pid_ok + command_mode == 0) { + fprintf(stderr,"Error: You must specify one target process, either by name, pid, or command line\n"); + print_usage(stderr, 1); + exit(1); + } + + if (exe_ok + pid_ok + command_mode > 1) { + fprintf(stderr,"Error: You must specify exactly one target process, either by name, pid, or command line\n"); + print_usage(stderr, 1); + exit(1); + } + + //all arguments are ok! + signal(SIGINT, quit); + signal(SIGTERM, quit); + + //print the number of available cpu + if (verbose) printf("%d cpu detected\n", NCPU); + + if (command_mode) { + int i; + //executable file + const char *cmd = argv[optind]; + //command line arguments + char **cmd_args = (char**)malloc((argc-optind + 1) * sizeof(char*)); + if (cmd_args==NULL) exit(2); + for (i=0; i<argc-optind; i++) { + cmd_args[i] = argv[i+optind]; + } + cmd_args[i] = NULL; + + if (verbose) { + printf("Running command: '%s", cmd); + for (i=1; i<argc-optind; i++) { + printf(" %s", cmd_args[i]); + } + printf("'\n"); + } + + int child = fork(); + if (child < 0) { + exit(EXIT_FAILURE); + } + else if (child == 0) { + //target process code + int ret = execvp(cmd, cmd_args); + //if we are here there was an error, show it + perror("Error"); + exit(ret); + } + else { + //parent code + free(cmd_args); + int limiter = fork(); + if (limiter < 0) { + exit(EXIT_FAILURE); + } + else if (limiter > 0) { + //parent + int status_process; + int status_limiter; + waitpid(child, &status_process, 0); + waitpid(limiter, &status_limiter, 0); + if (WIFEXITED(status_process)) { + if (verbose) printf("Process %d terminated with exit status %d\n", child, (int)WEXITSTATUS(status_process)); + exit(WEXITSTATUS(status_process)); + } + printf("Process %d terminated abnormally\n", child); + exit(status_process); + } + else { + //limiter code + if (verbose) printf("Limiting process %d\n",child); + limit_process(child, limit, include_children); + exit(0); + } + } + } + + while(1) { + //look for the target process..or wait for it + pid_t ret = 0; + if (pid_ok) { + //search by pid + ret = find_process_by_pid(pid); + if (ret == 0) { + printf("No process found\n"); + } + else if (ret < 0) { + printf("Process found but you aren't allowed to control it\n"); + } + } + else { + //search by file or path name + ret = find_process_by_name(exe); + if (ret == 0) { + printf("No process found\n"); + } + else if (ret < 0) { + printf("Process found but you aren't allowed to control it\n"); + } + else { + pid = ret; + } + } + if (ret > 0) { + if (ret == cpulimit_pid) { + printf("Target process %d is cpulimit itself! Aborting because it makes no sense\n", ret); + exit(1); + } + printf("Process %d found\n", pid); + //control + limit_process(pid, limit, include_children); + } + if (lazy) break; + sleep(2); + }; + + exit(0); +} diff --git a/Utilities/Tools/cpulimit/list.c b/Utilities/Tools/cpulimit/list.c new file mode 100644 index 0000000000000..2a78358a994a6 --- /dev/null +++ b/Utilities/Tools/cpulimit/list.c @@ -0,0 +1,148 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <stdlib.h> +#include <string.h> + +#include "list.h" + +#define EMPTYLIST NULL + +void init_list(struct list *l,int keysize) { + l->first=l->last=NULL; + l->keysize=keysize; + l->count=0; +} + +struct list_node *add_elem(struct list *l,void *elem) { + struct list_node *newnode=(struct list_node*)malloc(sizeof(struct list_node)); + newnode->data=elem; + newnode->previous=l->last; + newnode->next=NULL; + if (l->count==0) { + l->first=l->last=newnode; + } + else { + l->last->next=newnode; + l->last=newnode; + } + l->count++; + return newnode; +} + +void delete_node(struct list *l,struct list_node *node) { + if (l->count==1) { + l->first=l->last=NULL; + } + else if (node==l->first) { + node->next->previous=NULL; + l->first=node->next; + } + else if (node==l->last) { + node->previous->next=NULL; + l->last=node->previous; + } + else { + node->previous->next=node->next; + node->next->previous=node->previous; + } + l->count--; + free(node); +} + +void destroy_node(struct list *l,struct list_node *node) { + free(node->data); + node->data=NULL; + delete_node(l,node); +} + +int is_empty_list(struct list *l) { + return (l->count==0?TRUE:FALSE); +} + +int get_list_count(struct list *l) { + return l->count; +} + +void *first_elem(struct list *l) { + return l->first->data; +} + +struct list_node *first_node(struct list *l) { + return l->first; +} + +void *last_elem(struct list *l) { + return l->last->data; +} + +struct list_node *last_node(struct list *l) { + return l->last; +} + +struct list_node *xlocate_node(struct list *l,void *elem,int offset,int length) { + struct list_node *tmp; + tmp=l->first; + while(tmp!=NULL) { + if(!memcmp((char*)tmp->data+offset,elem,length==0?l->keysize:length)) return (tmp); + tmp=tmp->next; + } + return EMPTYLIST; +} + +struct list_node *locate_node(struct list *l,void *elem) { + return(xlocate_node(l,elem,0,0)); +} + +void *xlocate_elem(struct list *l,void *elem,int offset,int length) { + struct list_node *node=xlocate_node(l,elem,offset,length); + return(node==NULL?NULL:node->data); +} + +void *locate_elem(struct list *l,void *elem) { + return(xlocate_elem(l,elem,0,0)); +} + +void clear_list(struct list *l) { + while(l->first!=EMPTYLIST) { + struct list_node *tmp; + tmp=l->first; + l->first=l->first->next; + free(tmp); + tmp=NULL; + } + l->last=EMPTYLIST; + l->count=0; +} + +void destroy_list(struct list *l) { + while(l->first!=EMPTYLIST) { + struct list_node *tmp; + tmp=l->first; + l->first=l->first->next; + free(tmp->data); + tmp->data=NULL; + free(tmp); + tmp=NULL; + } + l->last=EMPTYLIST; + l->count=0; +} diff --git a/Utilities/Tools/cpulimit/list.h b/Utilities/Tools/cpulimit/list.h new file mode 100644 index 0000000000000..0b43a2b39c0f3 --- /dev/null +++ b/Utilities/Tools/cpulimit/list.h @@ -0,0 +1,138 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __LIST__ + +#define __LIST__ + +#ifndef TRUE + #define TRUE 1 + #define FALSE 0 +#endif + +struct list_node { + //pointer to the content of the node + void *data; + //pointer to previous node + struct list_node *previous; + //pointer to next node + struct list_node *next; +}; + +struct list { + //first node + struct list_node *first; + //last node + struct list_node *last; + //size of the search key in bytes + int keysize; + //element count + int count; +}; + +/* + * Initialize a list, with a specified key size + */ +void init_list(struct list *l,int keysize); + +/* + * Add a new element at the end of the list + * return the pointer to the new node + */ +struct list_node *add_elem(struct list *l,void *elem); + +/* + * Delete a node + */ +void delete_node(struct list *l,struct list_node *node); + +/* + * Delete a node from the list, even the content pointed by it + * Use only when the content is a dynamically allocated pointer + */ +void destroy_node(struct list *l,struct list_node *node); + +/* + * Check whether a list is empty or not + */ +int is_empty_list(struct list *l); + +/* + * Return the element count of the list + */ +int get_list_count(struct list *l); + +/* + * Return the first element (content of the node) from the list + */ +void *first_elem(struct list *l); + +/* + * Return the first node from the list + */ +struct list_node *first_node(struct list *l); + +/* + * Return the last element (content of the node) from the list + */ +void *last_elem(struct list *l); + +/* + * Return the last node from the list + */ +struct list_node *last_node(struct list *l); + +/* + * Search an element of the list by content + * the comparison is done from the specified offset and for a specified length + * if offset=0, the comparison starts from the address pointed by data + * if length=0, default keysize is used for length + * if the element is found, return the node address + * else return NULL + */ +struct list_node *xlocate_node(struct list *l,void *elem,int offset,int length); + +/* + * The same of xlocate_node(), but return the content of the node + */ +void *xlocate_elem(struct list *l,void *elem,int offset,int length); + +/* + * The same of calling xlocate_node() with offset=0 and length=0 + */ +struct list_node *locate_node(struct list *l,void *elem); + +/* + * The same of locate_node, but return the content of the node + */ +void *locate_elem(struct list *l,void *elem); + +/* + * Delete all the elements in the list + */ +void clear_list(struct list *l); + +/* + * Delete every element in the list, and free the memory pointed by all the node data + */ +void destroy_list(struct list *l); + +#endif diff --git a/Utilities/Tools/cpulimit/memrchr.c b/Utilities/Tools/cpulimit/memrchr.c new file mode 100644 index 0000000000000..1f3787020afad --- /dev/null +++ b/Utilities/Tools/cpulimit/memrchr.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +/* + * Reverse memchr() + * Find the last occurrence of 'c' in the buffer 's' of size 'n'. + */ +void * +memrchr(s, c, n) + const void *s; + int c; + size_t n; +{ + if (n != 0) { + const unsigned char *cp; + cp = (unsigned char *)s + n; + do { + if (*(--cp) == (unsigned char)c) + return((void *)cp); + } while (--n != 0); + } + return((void *)0); +} diff --git a/Utilities/Tools/cpulimit/process_group.c b/Utilities/Tools/cpulimit/process_group.c new file mode 100644 index 0000000000000..06d73a6f3541c --- /dev/null +++ b/Utilities/Tools/cpulimit/process_group.c @@ -0,0 +1,205 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <sys/time.h> +#include <signal.h> + +#include <assert.h> + +#include "process_iterator.h" +#include "process_group.h" +#include "list.h" + +// look for a process by pid +// search_pid : pid of the wanted process +// return: pid of the found process, if successful +// negative pid, if the process does not exist or if the signal fails +int find_process_by_pid(pid_t pid) +{ + return (kill(pid,0)==0) ? pid : -pid; +} + +// look for a process with a given name +// process: the name of the wanted process. it can be an absolute path name to the executable file +// or just the file name +// return: pid of the found process, if it is found +// 0, if it's not found +// negative pid, if it is found but it's not possible to control it +int find_process_by_name(const char *process_name) +{ + //pid of the target process + pid_t pid = -1; + + //process iterator + struct process_iterator it; + struct process proc; + struct process_filter filter; + filter.pid = 0; + filter.include_children = 0; + init_process_iterator(&it, &filter); + while (get_next_process(&it, &proc) != -1) + { + //process found + if (strncmp(basename(proc.command), process_name, strlen(process_name))==0 && kill(pid,SIGCONT)==0) { + //process is ok! + pid = proc.pid; + break; + } + } + if (close_process_iterator(&it) != 0) exit(1); + if (pid >= 0) { + //ok, the process was found + return pid; + } + else { + //process not found + return 0; + } +} + +int init_process_group(struct process_group *pgroup, int target_pid, int include_children) +{ + //hashtable initialization + memset(&pgroup->proctable, 0, sizeof(pgroup->proctable)); + pgroup->target_pid = target_pid; + pgroup->include_children = include_children; + pgroup->proclist = (struct list*)malloc(sizeof(struct list)); + init_list(pgroup->proclist, 4); + memset(&pgroup->last_update, 0, sizeof(pgroup->last_update)); + update_process_group(pgroup); + return 0; +} + +int close_process_group(struct process_group *pgroup) +{ + int i; + int size = sizeof(pgroup->proctable) / sizeof(struct process*); + for (i=0; i<size; i++) { + if (pgroup->proctable[i] != NULL) { + //free() history for each process + destroy_list(pgroup->proctable[i]); + free(pgroup->proctable[i]); + pgroup->proctable[i] = NULL; + } + } + clear_list(pgroup->proclist); + free(pgroup->proclist); + pgroup->proclist = NULL; + return 0; +} + +void remove_terminated_processes(struct process_group *pgroup) +{ + //TODO +} + +//return t1-t2 in microseconds (no overflow checks, so better watch out!) +static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2) +{ + return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec); +} + +//parameter in range 0-1 +#define ALFA 0.08 +#define MIN_DT 20 + +void update_process_group(struct process_group *pgroup) +{ + struct process_iterator it; + struct process tmp_process; + struct process_filter filter; + struct timeval now; + gettimeofday(&now, NULL); + //time elapsed from previous sample (in ms) + long dt = timediff(&now, &pgroup->last_update) / 1000; + filter.pid = pgroup->target_pid; + filter.include_children = pgroup->include_children; + init_process_iterator(&it, &filter); + clear_list(pgroup->proclist); + init_list(pgroup->proclist, 4); + + while (get_next_process(&it, &tmp_process) != -1) + { +// struct timeval t; +// gettimeofday(&t, NULL); +// printf("T=%ld.%ld PID=%d PPID=%d START=%d CPUTIME=%d\n", t.tv_sec, t.tv_usec, tmp_process.pid, tmp_process.ppid, tmp_process.starttime, tmp_process.cputime); + int hashkey = pid_hashfn(tmp_process.pid); + if (pgroup->proctable[hashkey] == NULL) + { + //empty bucket + pgroup->proctable[hashkey] = malloc(sizeof(struct list)); + struct process *new_process = malloc(sizeof(struct process)); + tmp_process.cpu_usage = -1; + memcpy(new_process, &tmp_process, sizeof(struct process)); + init_list(pgroup->proctable[hashkey], 4); + add_elem(pgroup->proctable[hashkey], new_process); + add_elem(pgroup->proclist, new_process); + } + else + { + //existing bucket + struct process *p = (struct process*)locate_elem(pgroup->proctable[hashkey], &tmp_process); + if (p == NULL) + { + //process is new. add it + struct process *new_process = malloc(sizeof(struct process)); + tmp_process.cpu_usage = -1; + memcpy(new_process, &tmp_process, sizeof(struct process)); + add_elem(pgroup->proctable[hashkey], new_process); + add_elem(pgroup->proclist, new_process); + } + else + { + assert(tmp_process.pid == p->pid); + assert(tmp_process.starttime == p->starttime); + add_elem(pgroup->proclist, p); + if (dt < MIN_DT) continue; + //process exists. update CPU usage + double sample = 1.0 * (tmp_process.cputime - p->cputime) / dt; + if (p->cpu_usage == -1) { + //initialization + p->cpu_usage = sample; + } + else { + //usage adjustment + p->cpu_usage = (1.0-ALFA) * p->cpu_usage + ALFA * sample; + } + p->cputime = tmp_process.cputime; + } + } + } + close_process_iterator(&it); + if (dt < MIN_DT) return; + pgroup->last_update = now; +} + +int remove_process(struct process_group *pgroup, int pid) +{ + int hashkey = pid_hashfn(pid); + if (pgroup->proctable[hashkey] == NULL) return 1; //nothing to delete + struct list_node *node = (struct list_node*)locate_node(pgroup->proctable[hashkey], &pid); + if (node == NULL) return 2; + delete_node(pgroup->proctable[hashkey], node); + return 0; +} diff --git a/Utilities/Tools/cpulimit/process_group.h b/Utilities/Tools/cpulimit/process_group.h new file mode 100644 index 0000000000000..5a5b581554a80 --- /dev/null +++ b/Utilities/Tools/cpulimit/process_group.h @@ -0,0 +1,55 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __PROCESS_GROUP_H + +#define __PROCESS_GROUP_H + +#include "process_iterator.h" + +#include "list.h" + +#define PIDHASH_SZ 1024 +#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) + +struct process_group +{ + //hashtable with all the processes (array of struct list of struct process) + struct list *proctable[PIDHASH_SZ]; + struct list *proclist; + pid_t target_pid; + int include_children; + struct timeval last_update; +}; + +int init_process_group(struct process_group *pgroup, int target_pid, int include_children); + +void update_process_group(struct process_group *pgroup); + +int close_process_group(struct process_group *pgroup); + +int find_process_by_pid(pid_t pid); + +int find_process_by_name(const char *process_name); + +int remove_process(struct process_group *pgroup, int pid); + +#endif diff --git a/Utilities/Tools/cpulimit/process_iterator.c b/Utilities/Tools/cpulimit/process_iterator.c new file mode 100644 index 0000000000000..8b4019d237f2b --- /dev/null +++ b/Utilities/Tools/cpulimit/process_iterator.c @@ -0,0 +1,49 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef __APPLE__ +#include <sys/procfs.h> +#endif +#include <time.h> +#include "process_iterator.h" + +//See this link to port to other systems: http://www.steve.org.uk/Reference/Unix/faq_8.html#SEC85 + +#ifdef __linux__ + +#include "process_iterator_linux.c" + +#elif defined __FreeBSD__ + +#include "process_iterator_freebsd.c" + +#elif defined __APPLE__ + +#include "process_iterator_apple.c" + +#else + +#error Platform not supported + +#endif diff --git a/Utilities/Tools/cpulimit/process_iterator.h b/Utilities/Tools/cpulimit/process_iterator.h new file mode 100644 index 0000000000000..70520b68a6e88 --- /dev/null +++ b/Utilities/Tools/cpulimit/process_iterator.h @@ -0,0 +1,97 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __PROCESS_ITERATOR_H + +#define __PROCESS_ITERATOR_H + +#include <unistd.h> +#include <limits.h> +#include <dirent.h> + +//USER_HZ detection, from openssl code +#ifndef HZ +# if defined(_SC_CLK_TCK) \ + && (!defined(OPENSSL_SYS_VMS) || __CTRL_VER >= 70000000) +# define HZ ((double)sysconf(_SC_CLK_TCK)) +# else +# ifndef CLK_TCK +# ifndef _BSD_CLK_TCK_ /* FreeBSD hack */ +# define HZ 100.0 +# else /* _BSD_CLK_TCK_ */ +# define HZ ((double)_BSD_CLK_TCK_) +# endif +# else /* CLK_TCK */ +# define HZ ((double)CLK_TCK) +# endif +# endif +#endif + +#ifdef __FreeBSD__ +#include <kvm.h> +#endif + +// process descriptor +struct process { + //pid of the process + pid_t pid; + //ppid of the process + pid_t ppid; + //start time (unix timestamp) + int starttime; + //cputime used by the process (in milliseconds) + int cputime; + //actual cpu usage estimation (value in range 0-1) + double cpu_usage; + //absolute path of the executable file + char command[PATH_MAX+1]; +}; + +struct process_filter { + int pid; + int include_children; + char program_name[PATH_MAX+1]; +}; + +struct process_iterator { +#ifdef __linux__ + DIR *dip; + int boot_time; +#elif defined __FreeBSD__ + kvm_t *kd; + struct kinfo_proc *procs; + int count; + int i; +#elif defined __APPLE__ + int i; + int count; + int *pidlist; +#endif + struct process_filter *filter; +}; + +int init_process_iterator(struct process_iterator *i, struct process_filter *filter); + +int get_next_process(struct process_iterator *i, struct process *p); + +int close_process_iterator(struct process_iterator *i); + +#endif diff --git a/Utilities/Tools/cpulimit/process_iterator_apple.c b/Utilities/Tools/cpulimit/process_iterator_apple.c new file mode 100644 index 0000000000000..b878ed8c9a946 --- /dev/null +++ b/Utilities/Tools/cpulimit/process_iterator_apple.c @@ -0,0 +1,148 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Author: Simon Sigurdhsson + * + */ + +#include <errno.h> +#include <stdio.h> +#include <libproc.h> + +int unique_nonzero_ints(int* arr_in, int len_in, int* arr_out) { + int* source = arr_in; + if (arr_out == NULL) return -1; + if (arr_in == arr_out) { + source = malloc(sizeof(int)*len_in); + memcpy(source, arr_in, sizeof(int)*len_in); + memset(arr_out, -1, sizeof(int)*len_in); + } + int len_out = 0; + int i, j; + for (i=0; i<len_in; i++) { + int found = 0; + if (source[i] == 0) continue; + for (j=0; !found && j<len_out; j++) { + found = (source[i] == arr_out[j]) ? 1 : 0; + } + if (!found) { + arr_out[len_out++] = source[i]; + } + } + if (arr_in == arr_out) { + free(source); + } + return len_out-1; +} + +int init_process_iterator(struct process_iterator *it, struct process_filter *filter) { + it->i = 0; + /* Find out how much to allocate for it->pidlist */ + if ((it->count = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0)) <= 0) { + fprintf(stderr, "proc_listpids: %s\n", strerror(errno)); + return -1; + } + /* Allocate and populate it->pidlist */ + if ((it->pidlist = (int *)malloc((it->count)*sizeof(int))) == NULL) { + fprintf(stderr, "malloc: %s\n", strerror(errno)); + } + if ((it->count = proc_listpids(PROC_ALL_PIDS, 0, it->pidlist, it->count)) <= 0) { + fprintf(stderr, "proc_listpids: %s\n", strerror(errno)); + return -1; + } + it->count = unique_nonzero_ints(it->pidlist, it->count, it->pidlist); + it->filter = filter; + return 0; +} + +static int pti2proc(struct proc_taskallinfo *ti, struct process *process) { + int bytes; + process->pid = ti->pbsd.pbi_pid; + process->ppid = ti->pbsd.pbi_ppid; + process->starttime = ti->pbsd.pbi_start_tvsec; + process->cputime = (ti->ptinfo.pti_total_user + ti->ptinfo.pti_total_system) / 1000000; + bytes = strlen(ti->pbsd.pbi_comm); + memcpy(process->command, ti->pbsd.pbi_comm, (bytes < PATH_MAX ? bytes : PATH_MAX) + 1); + return 0; +} + +static int get_process_pti(pid_t pid, struct proc_taskallinfo *ti) { + int bytes; + bytes = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, ti, sizeof(*ti)); + if (bytes <= 0) { + if (!(errno & (EPERM | ESRCH))) { + fprintf(stderr, "proc_pidinfo: %s\n", strerror(errno)); + } + return -1; + } else if (bytes < sizeof(ti)) { + fprintf(stderr, "proc_pidinfo: too few bytes; expected %ld, got %d\n", sizeof(ti), bytes); + return -1; + } + return 0; +} + +int get_next_process(struct process_iterator *it, struct process *p) { + if (it->i == it->count) return -1; + if (it->filter->pid != 0 && !it->filter->include_children) { + struct proc_taskallinfo ti; + if (get_process_pti(it->filter->pid, &ti) != 0) { + it->i = it->count = 0; + return -1; + } + it->i = it->count = 1; + return pti2proc(&ti, p); + } + while (it->i < it->count) { + struct proc_taskallinfo ti; + if (get_process_pti(it->pidlist[it->i], &ti) != 0) { + it->i++; + continue; + } + if (ti.pbsd.pbi_flags & PROC_FLAG_SYSTEM) { + it->i++; + continue; + } + if (it->filter->pid != 0 && it->filter->include_children) { + pti2proc(&ti, p); + it->i++; + if (p->pid != it->pidlist[it->i - 1]) // I don't know why this can happen + continue; + if (p->pid != it->filter->pid && p->ppid != it->filter->pid) + continue; + return 0; + } + else if (it->filter->pid == 0) + { + pti2proc(&ti, p); + it->i++; + return 0; + } + } + return -1; +} + +int close_process_iterator(struct process_iterator *it) { + free(it->pidlist); + it->pidlist = NULL; + it->filter = NULL; + it->count = 0; + it->i = 0; + return 0; +} diff --git a/Utilities/Tools/cpulimit/process_iterator_freebsd.c b/Utilities/Tools/cpulimit/process_iterator_freebsd.c new file mode 100644 index 0000000000000..a6381123e1251 --- /dev/null +++ b/Utilities/Tools/cpulimit/process_iterator_freebsd.c @@ -0,0 +1,119 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <sys/sysctl.h> +#include <sys/user.h> +#include <fcntl.h> +#include <paths.h> + +int init_process_iterator(struct process_iterator *it, struct process_filter *filter) { + char errbuf[_POSIX2_LINE_MAX]; + it->i = 0; + /* Open the kvm interface, get a descriptor */ + if ((it->kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) { + fprintf(stderr, "kvm_open: %s\n", errbuf); + return -1; + } + /* Get the list of processes. */ + if ((it->procs = kvm_getprocs(it->kd, KERN_PROC_PROC, 0, &it->count)) == NULL) { + kvm_close(it->kd); +// fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(it->kd)); + return -1; + } + it->filter = filter; + return 0; +} + +static int kproc2proc(kvm_t *kd, struct kinfo_proc *kproc, struct process *proc) +{ + proc->pid = kproc->ki_pid; + proc->ppid = kproc->ki_ppid; + proc->cputime = kproc->ki_runtime / 1000; + proc->starttime = kproc->ki_start.tv_sec; + char **args = kvm_getargv(kd, kproc, sizeof(proc->command)); + if (args == NULL) return -1; + memcpy(proc->command, args[0], strlen(args[0]) + 1); + return 0; +} + +static int get_single_process(kvm_t *kd, pid_t pid, struct process *process) +{ + int count; + struct kinfo_proc *kproc = kvm_getprocs(kd, KERN_PROC_PID, pid, &count); + if (count == 0 || kproc == NULL) + { +// fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd)); + return -1; + } + kproc2proc(kd, kproc, process); + return 0; +} + +int get_next_process(struct process_iterator *it, struct process *p) { + if (it->i == it->count) + { + return -1; + } + if (it->filter->pid != 0 && !it->filter->include_children) + { + if (get_single_process(it->kd, it->filter->pid, p) != 0) + { + it->i = it->count = 0; + return -1; + } + it->i = it->count = 1; + return 0; + } + while (it->i < it->count) + { + struct kinfo_proc *kproc = &(it->procs[it->i]); + if (kproc->ki_flag & P_SYSTEM) + { + // skip system processes + it->i++; + continue; + } + if (it->filter->pid != 0 && it->filter->include_children) + { + kproc2proc(it->kd, kproc, p); + it->i++; + if (p->pid != it->filter->pid && p->ppid != it->filter->pid) + continue; + return 0; + } + else if (it->filter->pid == 0) + { + kproc2proc(it->kd, kproc, p); + it->i++; + return 0; + } + } + return -1; +} + +int close_process_iterator(struct process_iterator *it) { + if (kvm_close(it->kd) == -1) { + fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(it->kd)); + return -1; + } + return 0; +} + diff --git a/Utilities/Tools/cpulimit/process_iterator_linux.c b/Utilities/Tools/cpulimit/process_iterator_linux.c new file mode 100644 index 0000000000000..c8cdd07adcbe9 --- /dev/null +++ b/Utilities/Tools/cpulimit/process_iterator_linux.c @@ -0,0 +1,181 @@ +/** + * + * cpulimit - a CPU limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <sys/vfs.h> + +static int get_boot_time() +{ + int uptime = 0; + FILE *fp = fopen ("/proc/uptime", "r"); + if (fp != NULL) + { + char buf[BUFSIZ]; + char *b = fgets(buf, BUFSIZ, fp); + if (b == buf) + { + char *end_ptr; + double upsecs = strtod(buf, &end_ptr); + uptime = (int)upsecs; + } + fclose (fp); + } + time_t now = time(NULL); + return now - uptime; +} + +static int check_proc() +{ + struct statfs mnt; + if (statfs("/proc", &mnt) < 0) + return 0; + if (mnt.f_type!=0x9fa0) + return 0; + return 1; +} + +int init_process_iterator(struct process_iterator *it, struct process_filter *filter) +{ + if (!check_proc()) { + fprintf(stderr, "procfs is not mounted!\nAborting\n"); + exit(-2); + } + //open a directory stream to /proc directory + if ((it->dip = opendir("/proc")) == NULL) + { + perror("opendir"); + return -1; + } + it->filter = filter; + it->boot_time = get_boot_time(); + return 0; +} + +static int read_process_info(pid_t pid, struct process *p) +{ + static char buffer[1024]; + static char statfile[32]; + static char exefile[1024]; + p->pid = pid; + //read stat file + sprintf(statfile, "/proc/%d/stat", p->pid); + FILE *fd = fopen(statfile, "r"); + if (fd==NULL) return -1; + if (fgets(buffer, sizeof(buffer), fd)==NULL) { + fclose(fd); + return -1; + } + fclose(fd); + char *token = strtok(buffer, " "); + int i; + for (i=0; i<3; i++) token = strtok(NULL, " "); + p->ppid = atoi(token); + for (i=0; i<10; i++) + token = strtok(NULL, " "); + p->cputime = atoi(token) * 1000 / HZ; + token = strtok(NULL, " "); + p->cputime += atoi(token) * 1000 / HZ; + for (i=0; i<7; i++) + token = strtok(NULL, " "); + p->starttime = atoi(token) / sysconf(_SC_CLK_TCK); + //read command line + sprintf(exefile,"/proc/%d/cmdline", p->pid); + fd = fopen(exefile, "r"); + if (fgets(buffer, sizeof(buffer), fd)==NULL) { + fclose(fd); + return -1; + } + fclose(fd); + strcpy(p->command, buffer); + return 0; +} + +static pid_t getppid_of(pid_t pid) +{ + char statfile[20]; + char buffer[1024]; + sprintf(statfile, "/proc/%d/stat", pid); + FILE *fd = fopen(statfile, "r"); + if (fd==NULL) return -1; + if (fgets(buffer, sizeof(buffer), fd)==NULL) { + fclose(fd); + return -1; + } + fclose(fd); + char *token = strtok(buffer, " "); + int i; + for (i=0; i<3; i++) token = strtok(NULL, " "); + return atoi(token); +} + +static int is_child_of(pid_t child_pid, pid_t parent_pid) +{ + int ppid = child_pid; + while(ppid > 1 && ppid != parent_pid) { + ppid = getppid_of(ppid); + } + return ppid == parent_pid; +} + +int get_next_process(struct process_iterator *it, struct process *p) +{ + if (it->dip == NULL) + { + //end of processes + return -1; + } + if (it->filter->pid != 0 && !it->filter->include_children) + { + int ret = read_process_info(it->filter->pid, p); + //p->starttime += it->boot_time; + closedir(it->dip); + it->dip = NULL; + if (ret != 0) return -1; + return 0; + } + struct dirent *dit = NULL; + //read in from /proc and seek for process dirs + while ((dit = readdir(it->dip)) != NULL) { + if(strtok(dit->d_name, "0123456789") != NULL) + continue; + p->pid = atoi(dit->d_name); + if (it->filter->pid != 0 && it->filter->pid != p->pid && !is_child_of(p->pid, it->filter->pid)) continue; + read_process_info(p->pid, p); + //p->starttime += it->boot_time; + break; + } + if (dit == NULL) + { + //end of processes + closedir(it->dip); + it->dip = NULL; + return -1; + } + return 0; +} + +int close_process_iterator(struct process_iterator *it) { + if (it->dip != NULL && closedir(it->dip) == -1) { + perror("closedir"); + return 1; + } + it->dip = NULL; + return 0; +} From 35967c544411284e40335d3845102f570f636ecc Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 2 Dec 2020 08:55:52 +0100 Subject: [PATCH 1505/1751] Fix compiler warning on MacOS --- Utilities/Tools/cpulimit/cpulimit.c | 2 +- Utilities/Tools/cpulimit/process_group.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Utilities/Tools/cpulimit/cpulimit.c b/Utilities/Tools/cpulimit/cpulimit.c index 50eabeacf2144..42d7ca2807384 100644 --- a/Utilities/Tools/cpulimit/cpulimit.c +++ b/Utilities/Tools/cpulimit/cpulimit.c @@ -43,7 +43,7 @@ #include <sys/types.h> #include <sys/wait.h> -#ifdef __APPLE__ || __FREEBSD__ +#if defined(__APPLE__) || defined(__FREEBSD__) #include <libgen.h> #endif diff --git a/Utilities/Tools/cpulimit/process_group.c b/Utilities/Tools/cpulimit/process_group.c index 06d73a6f3541c..98b6b5ed54c25 100644 --- a/Utilities/Tools/cpulimit/process_group.c +++ b/Utilities/Tools/cpulimit/process_group.c @@ -19,6 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#if defined(__APPLE__) || defined(__FREEBSD__) +#include <libgen.h> +#endif + #include <string.h> #include <stdlib.h> #include <limits.h> From 4d6fb61c645c0d5807d8518716636cb6c6b68115 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 1 Dec 2020 15:36:00 +0100 Subject: [PATCH 1506/1751] Improvements to taskwrapper * More direct CPU monitoring: - calc CPU usage directly in script * Prototypic possibility to limit the total CPU load of a task running within taskwrapper by using cpulimit (adaptively). This may be useful for several reasons. Here, it started as an investigation to prevent CPU spikes from workflows when running on single-core queues (until DPL has it's own way of forcing single-core). Or one might just want to emulate the constraints of a GRID multicore queue locally. By default the feature is switched off. It can be enabled via environment variables. For example ``` JOBUTILS_LIMITLOAD=300 taskwrapper task1.log task1 ``` will constrain task1 to using ~3 full CPU cores. The regulation mechanism is quite simplistic but should be enough to demonstrate the feature. --- Utilities/Tools/jobutils.sh | 99 ++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 11 deletions(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index 00aca143530c5..d5d9239accee6 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -13,8 +13,11 @@ # This file contains a couple of utility functions for reuse # in shell job scripts (such as on the GRID). # In order to use these functions in scripts, this file needs to be -# simply sourced into the target script. +# simply sourced into the target script. The script needs bash versions > 4 +# TODOs: +# -harmonize use of bc/awk for calculations +# -harmonize coding style for variables o2_cleanup_shm_files() { # check if we have lsof (otherwise we do nothing) @@ -91,6 +94,8 @@ taskwrapper_cleanup_handler() { # (until DPL offers signal handling and automatic shutdown) # - possibility to provide user hooks for "start" and "failure" # - possibility to skip (jump over) job alltogether +# - possibility to define timeout +# - possibility to control/limit the CPU load taskwrapper() { local logfile=$1 shift 1 @@ -141,7 +146,7 @@ taskwrapper() { finalcommand="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh ${TIMECOMMAND} './${SCRIPTNAME}'" fi echo "Running: ${finalcommand}" > ${logfile} - eval ${finalcommand} >> ${logfile} 2>&1 & + eval ${finalcommand} >> ${logfile} 2>&1 & disown # THE NEXT PART IS THE SUPERVISION PART # get the PID @@ -151,7 +156,9 @@ taskwrapper() { trap "taskwrapper_cleanup_handler ${PID} SIGTERM" SIGTERM cpucounter=1 + NLOGICALCPUS=$(getNumberOfLogicalCPUCores) + reduction_factor=1 while [ 1 ]; do # We don't like to see critical problems in the log file. @@ -202,21 +209,83 @@ taskwrapper() { ps -p $PID > /dev/null [ $? == 1 ] && break - if [ "${JOBUTILS_MONITORCPU}" ]; then + if [ "${JOBUTILS_MONITORCPU}" ] || [ "${JOBUTILS_LIMITLOAD}" ]; then + # NOTE: The following section is "a bit" compute intensive and currently not optimized + # A careful evaluation of awk vs bc or other tools might be needed -- or a move to a more + # system oriented language/tool + + for p in $limitPIDs; do + wait ${p} + done + # get some CPU usage statistics per process --> actual usage can be calculated thereafter - for p in $(childprocs ${PID}); do - total=`awk 'BEGIN{s=0}/cpu /{for (i=1;i<=NF;i++) s+=$i;} END {print s}' /proc/stat` - utime=`awk '//{print $14}' /proc/${p}/stat 2> /dev/null` - stime=`awk '//{print $15}' /proc/${p}/stat 2> /dev/null` - name=`awk '//{print $2}' /proc/${p}/stat 2> /dev/null` - echo "${cpucounter} ${p} ${total} ${utime} ${stime} ${name}" >> ${logfile}_cpuusage + total=`awk 'BEGIN{s=0}/cpu /{for (i=1;i<=NF;i++) s+=$i;} END {print s}' /proc/stat` + previous_total=${current_total} + current_total=${total} + # quickly fetch the data + childpids=$(childprocs ${PID}) + + for p in $childpids; do + while read -r name utime stime; do + echo "${cpucounter} ${p} ${total} ${utime} ${stime} ${name}" >> ${logfile}_cpuusage + previous[$p]=${current[$p]} + current[$p]=${utime} + name[$p]=${name} + done <<<$(awk '//{print $2" "$14" "$15}' /proc/${p}/stat 2>/dev/null) done + # do some calculations based on the data + totalCPU=0 # actual CPU load measured + totalCPU_unlimited=0 # extrapolated unlimited CPU load + line="" + for p in $childpids; do + C=${current[$p]} + P=${previous[$p]} + CT=${total} + PT=${previous_total} + # echo "${p} : current ${C} previous ${P} ${CT} ${PT}" + thisCPU[$p]=$(awk -v "c=${C}" -v "p=${P}" -v "ct=${CT}" -v "pt=${PT}" -v "ncpu=${NLOGICALCPUS}" 'BEGIN { print 100.*ncpu*(c-p)/(ct-pt); }') + line="${line} $p:${thisCPU[$p]}" + totalCPU=$(awk -v "t=${totalCPU}" -v "this=${thisCPU[$p]}" 'BEGIN { print (t + this); }') + previousfactor=1 + [ ${waslimited[$p]} ] && previousfactor=${reduction_factor} + totalCPU_unlimited=$(awk -v "t=${totalCPU_unlimited}" -v "this=${thisCPU[$p]}" -v f="${previousfactor}" 'BEGIN { print (t + this/f); }') + # echo "CPU last time window ${p} : ${thisCPU[$p]}" + done + + echo "${line}" + echo "${cpucounter} totalCPU = ${totalCPU} -- without limitation ${totalCPU_unlimited}" + # We can check if the total load is above a resource limit + # And take corrective actions if we extend by 10% + limitPIDs="" + unset waslimited + if (( $(echo "${totalCPU_unlimited} > 1.1*${JOBUTILS_LIMITLOAD}" | bc -l) )); then + # we reduce each pid proportionally for the time until the next check and record the reduction factor in place + oldreduction=${reduction_factor} + reduction_factor=$(awk -v limit="${JOBUTILS_LIMITLOAD}" -v cur="${totalCPU_unlimited}" 'BEGIN{ print limit/cur;}') + echo "APPLYING REDUCTION = ${reduction_factor}" + + for p in $childpids; do + cpulim=$(awk -v a="${thisCPU[${p}]}" -v newr="${reduction_factor}" -v oldr="${oldreduction}" 'BEGIN { r=(a/oldr)*newr; print r; if(r > 0.05) {exit 0;} exit 1; }') + if [ $? = "0" ]; then + # we only apply to jobs above a certain threshold + echo "Setting CPU lim for job ${p} / ${name[$p]} to ${cpulim}"; + + timeout ${JOBUTILS_WRAPPER_SLEEP} ${O2_ROOT}/share/scripts/cpulimit -l ${cpulim} -p ${p} > /dev/null 2> /dev/null & disown + proc=$! + limitPIDs="${limitPIDs} ${proc}" + waslimited[$p]=1 + fi + done + else + echo "RESETING REDUCTION = 1" + reduction_factor=1. + fi let cpucounter=cpucounter+1 fi # a good moment to check for jobs timeout (or other resources) if [ "$JOBUTILS_JOB_TIMEOUT" ]; then - $(awk -v S="${SECONDS}" -v T="${JOBUTILS_JOB_TIMEOUT}" -v START="${STARTTIME}" '//{} END{if((S-START)>T){exit 1;} exit 0;}' < /dev/null) + $(awk -v S="${SECONDS}" -v T="${JOBUTILS_JOB_TIMEOUT}" -v START="${STARTTIME}" 'BEGIN {if((S-START)>T){exit 1;} exit 0;}') if [ "$?" = "1" ]; then echo "task timeout reached .. killing all processes"; taskwrapper_cleanup $PID SIGKILL @@ -230,7 +299,7 @@ taskwrapper() { fi # sleep for some time (can be customized for power user) - sleep ${JOBUTILS_WRAPPER_SLEEP:-5} + sleep ${JOBUTILS_WRAPPER_SLEEP:-10} done # wait for PID and fetch return code @@ -281,3 +350,11 @@ getNumberOfPhysicalCPUCores() { echo "${N}" } +getNumberOfLogicalCPUCores() { + if [ "$(uname)" == "Darwin" ]; then + echo $(sysctl -n hw.logicalcpu) + else + # Do something under GNU/Linux platform + echo $(grep "processor" /proc/cpuinfo | wc -l) + fi +} From 8dc46a7d0f6f9f4c073b0305b75f7f38a4aeb20a Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Wed, 2 Dec 2020 14:15:38 +0100 Subject: [PATCH 1507/1751] Allow some executables to not follow the convention. That list should be kept extremely short, of course. Also amended the list of known subsystems to reduce the number of (harmless but annoying) warnings. --- tests/ensure-executable-naming-convention.sh.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/ensure-executable-naming-convention.sh.in b/tests/ensure-executable-naming-convention.sh.in index 9e6d6a1b73c02..5eb64dd0f5af3 100755 --- a/tests/ensure-executable-naming-convention.sh.in +++ b/tests/ensure-executable-naming-convention.sh.in @@ -28,6 +28,7 @@ RE_IS_BENCH="^o2-bench" RE_START_WITH_O2_OR_TEST="^o2-" RE_ONLY_LOWER_CASE_OR_DASH_OR_COMMA="^[a-z0-9]([a-z0-9\.]+|-)+[a-z0-9]$" RE_SUBSYSTEM="(o2)-([a-z,0-9]+)+" # o2-subsystem +RE_EXEMPTION="cpulimit" KNOWN_GROUPS="alicehlt \ analysis aod d0 simple \ @@ -40,7 +41,10 @@ fit its mch mid tpc \ tpcits \ flp heartbeat message epn \ mergers \ -subframebuilder sync timeframe framework" +subframebuilder sync timeframe framework \ +analysistutorial tof trd phos mft mchmapping mchraw \ +calibration fdd ft0 fv0 rans raw secondary \ +cpv ctf dpl emcal dcs itsmft primary reco pidparam" [[ -d @CMAKE_RUNTIME_OUTPUT_DIRECTORY@ ]] || exit 0 @@ -50,6 +54,7 @@ for F in *; do [[ -x $F && -f $F ]] || continue [[ $F =~ $RE_IS_TEST ]] && continue # convention for tests is yet to come [[ $F =~ $RE_IS_BENCH ]] && continue # convention for tests is yet to come + [[ $F =~ $RE_EXEMPTION ]] && continue # allow special executables to not follow the convention [[ ! $F =~ $RE_START_WITH_O2_OR_TEST ]] && error_msg $F "does not start with o2-" [[ ! $F =~ $RE_ONLY_LOWER_CASE_OR_DASH_OR_COMMA ]] && error_msg $F "should only contains lowercase letters, numbers, or dashes" [[ $F =~ $RE_SUBSYSTEM ]] && SUBSYSTEM=${BASH_REMATCH[2]} From 3d7b52c634772984544842869dd7a8e89a43c703 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 26 Nov 2020 10:30:21 +0100 Subject: [PATCH 1508/1751] Move ConfigurableMacroHelper plugin service helper in CommonUtils --- Common/Utils/CMakeLists.txt | 3 ++- .../include/CommonUtils}/ConfigurationMacroHelper.h | 10 +++++----- Generators/CMakeLists.txt | 1 - Generators/src/GeneratorFactory.cxx | 8 ++++---- Generators/src/GeneratorPythia8.cxx | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) rename {Generators/include/Generators => Common/Utils/include/CommonUtils}/ConfigurationMacroHelper.h (92%) diff --git a/Common/Utils/CMakeLists.txt b/Common/Utils/CMakeLists.txt index 2a1d6a4d1416a..6d1e55db08166 100644 --- a/Common/Utils/CMakeLists.txt +++ b/Common/Utils/CMakeLists.txt @@ -27,7 +27,8 @@ o2_target_root_dictionary(CommonUtils include/CommonUtils/ValueMonitor.h include/CommonUtils/MemFileHelper.h include/CommonUtils/ConfigurableParam.h - include/CommonUtils/ConfigurableParamHelper.h) + include/CommonUtils/ConfigurableParamHelper.h + include/CommonUtils/ConfigurationMacroHelper.h) o2_add_test(TreeStream COMPONENT_NAME CommonUtils diff --git a/Generators/include/Generators/ConfigurationMacroHelper.h b/Common/Utils/include/CommonUtils/ConfigurationMacroHelper.h similarity index 92% rename from Generators/include/Generators/ConfigurationMacroHelper.h rename to Common/Utils/include/CommonUtils/ConfigurationMacroHelper.h index cc34961d33445..58bc912a9990f 100644 --- a/Generators/include/Generators/ConfigurationMacroHelper.h +++ b/Common/Utils/include/CommonUtils/ConfigurationMacroHelper.h @@ -10,8 +10,8 @@ /// \author R+Preghenella - February 2020 -#ifndef ALICEO2_EVENTGEN_CONFIGURATIONMACRO_H_ -#define ALICEO2_EVENTGEN_CONFIGURATIONMACRO_H_ +#ifndef ALICEO2_CONF_CONFIGURATIONMACRO_H_ +#define ALICEO2_CONF_CONFIGURATIONMACRO_H_ #include "FairLogger.h" #include "TROOT.h" @@ -22,7 +22,7 @@ namespace o2 { -namespace eventgen +namespace conf { template <typename T> @@ -67,7 +67,7 @@ T GetFromMacro(const std::string& file, const std::string& funcname, const std:: return *ptr; } -} // namespace eventgen +} // namespace conf } // namespace o2 -#endif /* ALICEO2_EVENTGEN_CONFIGURATIONMACRO_H_ */ +#endif /* ALICEO2_CONF_CONFIGURATIONMACRO_H_ */ diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index 7985ed8283501..d839826bdfb6a 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -73,7 +73,6 @@ set(headers include/Generators/InteractionDiamondParam.h include/Generators/TriggerExternalParam.h include/Generators/TriggerParticleParam.h - include/Generators/ConfigurationMacroHelper.h include/Generators/BoxGunParam.h include/Generators/QEDGenParam.h include/Generators/GenCosmicsParam.h) diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index 2edbff92e826c..5f95a117f0320 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -35,7 +35,7 @@ #include <Generators/TriggerParticle.h> #include <Generators/TriggerExternalParam.h> #include <Generators/TriggerParticleParam.h> -#include "Generators/ConfigurationMacroHelper.h" +#include "CommonUtils/ConfigurationMacroHelper.h" #include "TRandom.h" @@ -205,7 +205,7 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair LOG(INFO) << params; auto extgen_filename = params.fileName; auto extgen_func = params.funcName; - auto extgen = GetFromMacro<FairGenerator*>(extgen_filename, extgen_func, "FairGenerator*", "extgen"); + auto extgen = o2::conf::GetFromMacro<FairGenerator*>(extgen_filename, extgen_func, "FairGenerator*", "extgen"); if (!extgen) { LOG(FATAL) << "Failed to retrieve \'extgen\': problem with configuration "; } @@ -243,10 +243,10 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair LOG(INFO) << params; auto external_trigger_filename = params.fileName; auto external_trigger_func = params.funcName; - trigger = GetFromMacro<o2::eventgen::Trigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::Trigger", "trigger"); + trigger = o2::conf::GetFromMacro<o2::eventgen::Trigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::Trigger", "trigger"); if (!trigger) { LOG(INFO) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type" << std::endl; - deeptrigger = GetFromMacro<o2::eventgen::DeepTrigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::DeepTrigger", "deeptrigger"); + deeptrigger = o2::conf::GetFromMacro<o2::eventgen::DeepTrigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::DeepTrigger", "deeptrigger"); } if (!trigger && !deeptrigger) { LOG(FATAL) << "Failed to retrieve \'external trigger\': problem with configuration "; diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 0727de5083739..344fdb8461fe1 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -12,7 +12,7 @@ #include "Generators/GeneratorPythia8.h" #include "Generators/GeneratorPythia8Param.h" -#include "Generators/ConfigurationMacroHelper.h" +#include "CommonUtils/ConfigurationMacroHelper.h" #include "FairLogger.h" #include "TParticle.h" #include "FairMCEventHeader.h" @@ -82,7 +82,7 @@ Bool_t GeneratorPythia8::Init() /** user hooks via configuration macro **/ if (!mHooksFileName.empty()) { LOG(INFO) << "Applying \'Pythia8\' user hooks: " << mHooksFileName << " -> " << mHooksFuncName; - auto hooks = GetFromMacro<Pythia8::UserHooks*>(mHooksFileName, mHooksFuncName, "Pythia8::UserHooks*", "pythia8_user_hooks"); + auto hooks = o2::conf::GetFromMacro<Pythia8::UserHooks*>(mHooksFileName, mHooksFuncName, "Pythia8::UserHooks*", "pythia8_user_hooks"); if (!hooks) { LOG(FATAL) << "Failed to init \'Pythia8\': problem with user hooks configuration "; return false; From 7a436e0458f764ac80d03734ec05c019ddf74fce Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Wed, 25 Nov 2020 16:56:38 +0100 Subject: [PATCH 1509/1751] Initial concept of selective tracking with configurable param settings --- .../SimulationDataFormat/ParticleStatus.h | 3 +- .../include/SimulationDataFormat/Stack.h | 5 +++ .../include/SimulationDataFormat/StackParam.h | 4 ++ DataFormats/simulation/src/Stack.cxx | 43 ++++++++++++++++++- doc/DetectorSimulation.md | 1 + run/SimExamples/README.md | 1 + run/SimExamples/Selective_Tranport/run.sh | 32 ++++++++++++++ run/SimExamples/Selective_Tranport/sim.ini | 5 +++ .../Selective_Tranport/transportPDG.macro | 7 +++ 9 files changed, 98 insertions(+), 3 deletions(-) create mode 100755 run/SimExamples/Selective_Tranport/run.sh create mode 100644 run/SimExamples/Selective_Tranport/sim.ini create mode 100644 run/SimExamples/Selective_Tranport/transportPDG.macro diff --git a/DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h b/DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h index e73202342bde2..798ff293178f4 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h +++ b/DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h @@ -18,6 +18,7 @@ enum ParticleStatus { kKeep = BIT(14), kDaughters = BIT(15), kToBeDone = BIT(16), kPrimary = BIT(17), - kTransport = BIT(18) }; + kTransport = BIT(18), + kInhibited = BIT(19) }; #endif diff --git a/DataFormats/simulation/include/SimulationDataFormat/Stack.h b/DataFormats/simulation/include/SimulationDataFormat/Stack.h index c63cb67e526d1..585119aa7c1f1 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/Stack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/Stack.h @@ -28,6 +28,7 @@ #include <memory> #include <stack> #include <utility> +#include <functional> class TClonesArray; class TRefArray; @@ -220,6 +221,8 @@ class Stack : public FairGenericStack /// update values in the current event header void updateEventStats(); + typedef std::function<bool(const TParticle& p)> TransportFcn; + private: /// STL stack (FILO) used to handle the TParticles for tracking /// stack entries refer to @@ -276,6 +279,8 @@ class Stack : public FairGenericStack bool mIsExternalMode = false; // is stack an external factory or directly used inside simulation? + TransportFcn mTransportPrimary = [](const TParticle& p) { return false; }; //! a function to inhibit the tracking of a particle + // storage for track references std::vector<o2::TrackReference>* mTrackRefs = nullptr; //! diff --git a/DataFormats/simulation/include/SimulationDataFormat/StackParam.h b/DataFormats/simulation/include/SimulationDataFormat/StackParam.h index 7c58b5327cf24..d5e940381039b 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/StackParam.h +++ b/DataFormats/simulation/include/SimulationDataFormat/StackParam.h @@ -23,6 +23,10 @@ namespace sim struct StackParam : public o2::conf::ConfigurableParamHelper<StackParam> { bool storeSecondaries = true; bool pruneKine = true; + std::string transportPrimary = "all"; + std::string transportPrimaryFileName = ""; + std::string transportPrimaryFuncName = ""; + bool transportPrimaryInvert = false; // boilerplate stuff + make principal key "Stack" O2ParamDef(StackParam, "Stack"); diff --git a/DataFormats/simulation/src/Stack.cxx b/DataFormats/simulation/src/Stack.cxx index fbda8cb8f73b7..eb609059725fc 100644 --- a/DataFormats/simulation/src/Stack.cxx +++ b/DataFormats/simulation/src/Stack.cxx @@ -22,6 +22,8 @@ #include "FairLogger.h" // for FairLogger #include "FairRootManager.h" #include "SimulationDataFormat/BaseHits.h" +#include "SimulationDataFormat/StackParam.h" +#include "CommonUtils/ConfigurationMacroHelper.h" #include "TLorentzVector.h" // for TLorentzVector #include "TParticle.h" // for TParticle @@ -78,6 +80,38 @@ Stack::Stack(Int_t size) if (vmc && strcmp(vmc->GetName(), "TGeant4") == 0) { mIsG4Like = true; } + + auto& param = o2::sim::StackParam::Instance(); + LOG(INFO) << param; + TransportFcn transportPrimary; + if (param.transportPrimary.compare("none") == 0) { + transportPrimary = [](const TParticle& p) { + return false; + }; + } else if (param.transportPrimary.compare("all") == 0) { + transportPrimary = [](const TParticle& p) { + return true; + }; + } else if (param.transportPrimary.compare("barrel") == 0) { + transportPrimary = [](const TParticle& p) { + return (std::fabs(p.Eta()) < 2.0); + }; + } else if (param.transportPrimary.compare("external") == 0) { + transportPrimary = o2::conf::GetFromMacro<o2::data::Stack::TransportFcn>(param.transportPrimaryFileName, + param.transportPrimaryFuncName, + "o2::data::Stack::TransportFcn", "stack_transport_primary"); + if (!mTransportPrimary) { + LOG(FATAL) << "Failed to retrieve external \'transportPrimary\' function: problem with configuration "; + } + } else { + LOG(FATAL) << "unsupported \'trasportPrimary\' mode: " << param.transportPrimary; + } + + if (param.transportPrimaryInvert) { + mTransportPrimary = [transportPrimary](const TParticle& p) { return !transportPrimary; }; + } else { + mTransportPrimary = transportPrimary; + } } Stack::Stack(const Stack& rhs) @@ -189,8 +223,13 @@ void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px p.SetBit(ParticleStatus::kKeep); p.SetBit(ParticleStatus::kPrimary); if (toBeDone == 1) { - p.SetBit(ParticleStatus::kToBeDone, 1); - mNumberOfPrimariesforTracking++; + if (mTransportPrimary(p)) { + p.SetBit(ParticleStatus::kToBeDone, 1); + mNumberOfPrimariesforTracking++; + } else { + p.SetBit(ParticleStatus::kToBeDone, 0); + p.SetBit(ParticleStatus::kInhibited, 1); + } } else { p.SetBit(ParticleStatus::kToBeDone, 0); } diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index e3a5647ea026b..246ebc34a7894 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -459,5 +459,6 @@ Other helpful resources are the scripts used for regression testing in [prodtest | [PrimaryKinematics](../run/SimExamples/JustPrimaryKinematics) | Example showing how to obtain only primary kinematics via transport configuration | | [HepMC_STARlight](../run/SimExamples/HepMC_STARlight) | Simple example showing **generator configuration** that runs a standalone `STARlight` generation that couples to the `o2` via a `HepMC` file | | [Jet_Embedding_Pythia](../run/SimExamples/Jet_Embedding_Pythia8) | Complex example showing **generator configuration**, **digitization embedding**, **MCTrack access** | +| [Selective_Transport](../run/SimExamples/Selective_Transport) | Simple example showing how to run simulation transporting only a custumisable set of particles | | [sim_challenge.sh](../prodtests/sim_challenge.sh) | Basic example doing a **simple transport, digitization, reconstruction pipeline** on the full dectector. All stages use parallelism. | | [sim_performance.sh](../prodtests/sim_performance_test.sh) | Basic example for serial transport and linearized digitization sequence (one detector after the other). Serves as standard performance candle. | diff --git a/run/SimExamples/README.md b/run/SimExamples/README.md index 484ba32ac38ef..59edafc399c0d 100644 --- a/run/SimExamples/README.md +++ b/run/SimExamples/README.md @@ -16,4 +16,5 @@ * \subpage refrunSimExamplesStepMonitoringSimple1 * \subpage refrunSimExamplesForceDecay_Lambda_Neutron_Dalitz * \subpage refrunSimExamplesJustPrimaryKinematics +* \subpage refrunSimExamplesSelective_Transport /doxy --> diff --git a/run/SimExamples/Selective_Tranport/run.sh b/run/SimExamples/Selective_Tranport/run.sh new file mode 100755 index 0000000000000..ab1e51310bb1b --- /dev/null +++ b/run/SimExamples/Selective_Tranport/run.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# +# This is a simulation example showing how to run simulation and selectively +# transport particles through the detector geometry according to configurable settings +# +# The simulation uses Pythia8 pp generator with default settings. +# The specific settings of the simulation are defined in the sim.ini file. +# +# Only the parameters for the selective particle transport are adjusted, namely +# ``` +# [Stack] +# transportPrimary=external +# transportPrimaryFileName=transportPDG.macro +# transportPrimaryFuncName=transportPDG(321) +# transportPrimaryInvert=false +# ``` +# +# `transportPrimary` defines the mode of selection, `external` means that the definition is loaded from a plugin macro +# defined by the function call `transportPrimaryFuncName` from the file `transportPrimaryFileName`. +# `transportPrimaryInvert` allows one to invert the definition, hence to inhibit transport for the selected particles. +# + +set -x + +MODULES="PIPE ITS TPC" +EVENTS=100 +NWORKERS=8 + +o2-sim -j ${NWORKERS} -n ${EVENTS} -g pythia8 -m ${MODULES} -o step1 \ + --configFile sim.ini \ + > logstep1 2>&1 + diff --git a/run/SimExamples/Selective_Tranport/sim.ini b/run/SimExamples/Selective_Tranport/sim.ini new file mode 100644 index 0000000000000..c445eca8c3098 --- /dev/null +++ b/run/SimExamples/Selective_Tranport/sim.ini @@ -0,0 +1,5 @@ +[Stack] +transportPrimary=external +transportPrimaryFileName=transportPDG.macro +transportPrimaryFuncName=transportPDG(321) +transportPrimaryInvert=false diff --git a/run/SimExamples/Selective_Tranport/transportPDG.macro b/run/SimExamples/Selective_Tranport/transportPDG.macro new file mode 100644 index 0000000000000..7e3fa34ceffa1 --- /dev/null +++ b/run/SimExamples/Selective_Tranport/transportPDG.macro @@ -0,0 +1,7 @@ +o2::data::Stack::TransportFcn +transportPDG(int pdg = 321) +{ + return [pdg](const TParticle& p) -> bool { + return p.GetPdgCode() == pdg; + }; +} From 36ee9aa9afb6aca548eea8781c0d29bf598c9050 Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Fri, 27 Nov 2020 17:36:34 +0100 Subject: [PATCH 1510/1751] [MCH] Move geometry into its own package. And split it into Creator, Transformer and Test parts. This commit is massive because a lot of files were moved around, sorry about that. It does add *one* new feature : the ability to read geometry transformations from a json file, and to create such a file from a geometry.root file using the o2-mch-convert-geometry executable. --- Detectors/MUON/MCH/Base/src/MCHBaseLinkDef.h | 2 +- Detectors/MUON/MCH/CMakeLists.txt | 1 + Detectors/MUON/MCH/Geometry/CMakeLists.txt | 16 + .../MUON/MCH/Geometry/Creator/CMakeLists.txt | 26 + Detectors/MUON/MCH/Geometry/Creator/README.md | 9 + .../include/MCHGeometryCreator/Geometry.h | 60 + .../MCH/Geometry/Creator/src/Geometry.cxx | 139 + .../Creator/src/MCHGeometryCreatorLinkDef.h | 23 + .../Creator}/src/Materials.cxx | 0 .../Creator}/src/Materials.h | 16 +- .../Creator}/src/Station1Geometry.cxx | 0 .../Creator}/src/Station1Geometry.h | 13 +- .../Creator}/src/Station2Geometry.cxx | 0 .../Creator}/src/Station2Geometry.h | 14 +- .../Creator}/src/Station345Geometry.cxx | 0 .../Creator}/src/Station345Geometry.h | 12 +- Detectors/MUON/MCH/Geometry/README.md | 15 + .../MUON/MCH/Geometry/Test/CMakeLists.txt | 44 + .../Test/Helpers.cxx} | 54 +- Detectors/MUON/MCH/Geometry/Test/LinkDef.h | 29 + Detectors/MUON/MCH/Geometry/Test/README.md | 13 + .../Test}/drawMCHGeometry.C | 2 +- .../Geometry/Test/ideal-geometry-aliroot.json | 2224 ++++++++++++++++ .../MCH/Geometry/Test/ideal-geometry-o2.json | 2272 +++++++++++++++++ .../Test/include/MCHGeometryTest/Helpers.h} | 23 +- .../macros => Geometry/Test}/rootlogon.C | 0 .../Test/testGeometryCreator.cxx} | 151 +- .../Geometry/Test/testGeometryTransformer.cxx | 227 ++ .../MCH/Geometry/Transformer/CMakeLists.txt | 22 + .../MUON/MCH/Geometry/Transformer/README.md | 26 + .../MCHGeometryTransformer/Transformations.h | 73 + .../MCHGeometryTransformer/VolumePaths.h | 22 + .../Transformer/src/Transformations.cxx | 153 ++ .../Transformer/src/VolumePaths.cxx} | 170 +- .../Transformer/src/convert-geometry.cxx | 200 ++ Detectors/MUON/MCH/README.md | 1 + Detectors/MUON/MCH/Simulation/CMakeLists.txt | 19 +- .../include/MCHSimulation/Geometry.h | 44 - .../MUON/MCH/Simulation/src/Detector.cxx | 8 +- .../MUON/MCH/Simulation/src/Digitizer.cxx | 10 +- .../MCH/Simulation/src/MCHSimulationLinkDef.h | 19 +- .../MUON/MCH/Simulation/test/CMakeLists.txt | 36 +- .../MCH/Simulation/test/testDigitMerging.cxx | 7 +- .../MCH/Simulation/test/testDigitization.cxx | 19 +- .../Simulation/test/testRegularGeometry.cxx | 42 + .../MUON/MCH/Simulation/test/testResponse.cxx | 2 + cmake/O2RootMacroExclusionList.cmake | 2 +- 47 files changed, 5729 insertions(+), 531 deletions(-) create mode 100644 Detectors/MUON/MCH/Geometry/CMakeLists.txt create mode 100644 Detectors/MUON/MCH/Geometry/Creator/CMakeLists.txt create mode 100644 Detectors/MUON/MCH/Geometry/Creator/README.md create mode 100644 Detectors/MUON/MCH/Geometry/Creator/include/MCHGeometryCreator/Geometry.h create mode 100644 Detectors/MUON/MCH/Geometry/Creator/src/Geometry.cxx create mode 100644 Detectors/MUON/MCH/Geometry/Creator/src/MCHGeometryCreatorLinkDef.h rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Materials.cxx (100%) rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Materials.h (83%) rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Station1Geometry.cxx (100%) rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Station1Geometry.h (79%) rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Station2Geometry.cxx (100%) rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Station2Geometry.h (79%) rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Station345Geometry.cxx (100%) rename Detectors/MUON/MCH/{Simulation => Geometry/Creator}/src/Station345Geometry.h (83%) create mode 100644 Detectors/MUON/MCH/Geometry/README.md create mode 100644 Detectors/MUON/MCH/Geometry/Test/CMakeLists.txt rename Detectors/MUON/MCH/{Simulation/src/GeometryTest.cxx => Geometry/Test/Helpers.cxx} (80%) create mode 100644 Detectors/MUON/MCH/Geometry/Test/LinkDef.h create mode 100644 Detectors/MUON/MCH/Geometry/Test/README.md rename Detectors/MUON/MCH/{Simulation/macros => Geometry/Test}/drawMCHGeometry.C (74%) create mode 100644 Detectors/MUON/MCH/Geometry/Test/ideal-geometry-aliroot.json create mode 100644 Detectors/MUON/MCH/Geometry/Test/ideal-geometry-o2.json rename Detectors/MUON/MCH/{Simulation/include/MCHSimulation/GeometryTest.h => Geometry/Test/include/MCHGeometryTest/Helpers.h} (78%) rename Detectors/MUON/MCH/{Simulation/macros => Geometry/Test}/rootlogon.C (100%) rename Detectors/MUON/MCH/{Simulation/test/testGeometry.cxx => Geometry/Test/testGeometryCreator.cxx} (70%) create mode 100644 Detectors/MUON/MCH/Geometry/Test/testGeometryTransformer.cxx create mode 100644 Detectors/MUON/MCH/Geometry/Transformer/CMakeLists.txt create mode 100644 Detectors/MUON/MCH/Geometry/Transformer/README.md create mode 100644 Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/Transformations.h create mode 100644 Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/VolumePaths.h create mode 100644 Detectors/MUON/MCH/Geometry/Transformer/src/Transformations.cxx rename Detectors/MUON/MCH/{Simulation/src/Geometry.cxx => Geometry/Transformer/src/VolumePaths.cxx} (67%) create mode 100644 Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx delete mode 100644 Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h create mode 100644 Detectors/MUON/MCH/Simulation/test/testRegularGeometry.cxx diff --git a/Detectors/MUON/MCH/Base/src/MCHBaseLinkDef.h b/Detectors/MUON/MCH/Base/src/MCHBaseLinkDef.h index b2afadd958883..3519cd9ed1239 100644 --- a/Detectors/MUON/MCH/Base/src/MCHBaseLinkDef.h +++ b/Detectors/MUON/MCH/Base/src/MCHBaseLinkDef.h @@ -18,6 +18,6 @@ #pragma link C++ namespace o2::mch; #pragma link C++ class o2::mch::Digit + ; -#pragma link C++ class std::vector < o2::mch::Digit> + ; +#pragma link C++ class std::vector < o2::mch::Digit > +; #endif diff --git a/Detectors/MUON/MCH/CMakeLists.txt b/Detectors/MUON/MCH/CMakeLists.txt index a4cf37dfb10d3..b9d77796fc981 100644 --- a/Detectors/MUON/MCH/CMakeLists.txt +++ b/Detectors/MUON/MCH/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory(Base) add_subdirectory(Contour) add_subdirectory(Mapping) add_subdirectory(PreClustering) +add_subdirectory(Geometry) add_subdirectory(Clustering) add_subdirectory(Simulation) add_subdirectory(Tracking) diff --git a/Detectors/MUON/MCH/Geometry/CMakeLists.txt b/Detectors/MUON/MCH/Geometry/CMakeLists.txt new file mode 100644 index 0000000000000..404d396bf2574 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/CMakeLists.txt @@ -0,0 +1,16 @@ +# 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. + +add_subdirectory(Transformer) +add_subdirectory(Creator) +if (BUILD_TESTING) +add_subdirectory(Test) +endif() + diff --git a/Detectors/MUON/MCH/Geometry/Creator/CMakeLists.txt b/Detectors/MUON/MCH/Geometry/Creator/CMakeLists.txt new file mode 100644 index 0000000000000..2790fdf26d6eb --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Creator/CMakeLists.txt @@ -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. + +o2_add_library( + MCHGeometryCreator + SOURCES src/Geometry.cxx + src/Materials.cxx + src/Materials.h + src/Station1Geometry.cxx + src/Station1Geometry.h + src/Station2Geometry.cxx + src/Station2Geometry.h + src/Station345Geometry.cxx + src/Station345Geometry.h + PUBLIC_LINK_LIBRARIES ROOT::Geom RapidJSON::RapidJSON + O2::MCHGeometryTransformer O2::DetectorsBase) + +o2_target_root_dictionary(MCHGeometryCreator + HEADERS include/MCHGeometryCreator/Geometry.h) diff --git a/Detectors/MUON/MCH/Geometry/Creator/README.md b/Detectors/MUON/MCH/Geometry/Creator/README.md new file mode 100644 index 0000000000000..619b98b3e666d --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Creator/README.md @@ -0,0 +1,9 @@ +<!-- doxy +\page refDetectorsMUONMCHGeometryCreator Creation +/doxy --> + +# MUON MCH Geometry Creator + +This package hosts the functions to create, from scratch, the TGeo-based + geometry for MCH. + diff --git a/Detectors/MUON/MCH/Geometry/Creator/include/MCHGeometryCreator/Geometry.h b/Detectors/MUON/MCH/Geometry/Creator/include/MCHGeometryCreator/Geometry.h new file mode 100644 index 0000000000000..b645386c8b668 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Creator/include/MCHGeometryCreator/Geometry.h @@ -0,0 +1,60 @@ +// 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 Geometry.h +/// @brief Interface for MCH geometry creation + +#ifndef O2_MCH_GEOMETRY_CREATOR_GEOMETRY_H +#define O2_MCH_GEOMETRY_CREATOR_GEOMETRY_H + +#include <vector> +#include <iostream> + +class TGeoVolume; +class TGeoManager; + +namespace o2::mch::geo +{ + +/** createGeometry creates MCH geometry. + * + * Geometry comprises volumes, materials and alignable volumes. + * + * Note that the geometry of stations 1 and 2 is attached to volume YOUT1 + * if it exist, or to topVolume otherwise. + * + * Geometry for stations 3, 4 and 5 are always attached to topVolume. + * + * @param topVolume the volume the MCH geometry is attached topVolume + */ +void createGeometry(TGeoManager& geom, TGeoVolume& topVolume); + +/** get a list of MCH sensitive volumes. + * @returns a vector of all the MCH volumes that participate in the + * particle tracking (in the transport sense). + */ +std::vector<TGeoVolume*> getSensitiveVolumes(); + +/** Add alignable MCH volumes to the global geometry. + * + * Creates entries for alignable volumes associating symbolic volume + * names with corresponding volume paths. + * + * @warning It also closes the geometry if it is not yet closed. + * + * @param geoManager the (global) TGeoManager instance, which thus + * must exist before calling this function. + * + */ +void addAlignableVolumes(TGeoManager& geom); + +} // namespace o2::mch::geo + +#endif diff --git a/Detectors/MUON/MCH/Geometry/Creator/src/Geometry.cxx b/Detectors/MUON/MCH/Geometry/Creator/src/Geometry.cxx new file mode 100644 index 0000000000000..d1d019f9a03fb --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Creator/src/Geometry.cxx @@ -0,0 +1,139 @@ +// 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 "MCHGeometryCreator/Geometry.h" +#include "MCHGeometryTransformer/VolumePaths.h" +#include "Station1Geometry.h" +#include "Station2Geometry.h" +#include "Station345Geometry.h" +#include "Materials.h" +#include <iostream> +#include <TGeoPhysicalNode.h> +#include <fmt/format.h> +#include "TGeoVolume.h" +#include "TGeoManager.h" +#include "Framework/Logger.h" + +namespace impl +{ +void addAlignableVolumesHalfChamber(TGeoManager& geom, int hc, std::string& parent) +{ + // + // Add alignable volumes for a half chamber and its daughters + // + std::vector<std::vector<int>> DEofHC{{100, 103}, + {101, 102}, + {200, 203}, + {201, 202}, + {300, 303}, + {301, 302}, + {400, 403}, + {401, 402}, + {500, 501, 502, 503, 504, 514, 515, 516, 517}, + {505, 506, 507, 508, 509, 510, 511, 512, 513}, + {600, 601, 602, 603, 604, 614, 615, 616, 617}, + {605, 606, 607, 608, 609, 610, 611, 612, 613}, + {700, 701, 702, 703, 704, 705, 706, 720, 721, 722, 723, 724, 725}, + {707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719}, + {800, 801, 802, 803, 804, 805, 806, 820, 821, 822, 823, 824, 825}, + {807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819}, + {900, 901, 902, 903, 904, 905, 906, 920, 921, 922, 923, 924, 925}, + {907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919}, + {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1020, 1021, 1022, 1023, 1024, 1025}, + {1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019}}; + + for (int i = 0; i < DEofHC[hc].size(); i++) { + std::string volPathName = o2::mch::geo::volumePathName(DEofHC[hc][i]); + + TString path = Form("%s%s", parent.c_str(), volPathName.c_str()); + TString sname = Form("MCH/HC%d/DE%d", hc, DEofHC[hc][i]); + + LOG(DEBUG) << "Add " << sname << " <-> " << path; + + if (!geom.SetAlignableEntry(sname.Data(), path.Data())) { + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } + } + + return; +} + +} // namespace impl + +namespace o2::mch::geo +{ + +void createGeometry(TGeoManager& geom, TGeoVolume& topVolume) +{ + createMaterials(); + + auto volYOUT1 = geom.GetVolume("YOUT1"); + + createStation1Geometry((volYOUT1) ? *volYOUT1 : topVolume); + createStation2Geometry((volYOUT1) ? *volYOUT1 : topVolume); + + createStation345Geometry(topVolume); +} + +std::vector<TGeoVolume*> getSensitiveVolumes() +{ + auto st1 = getStation1SensitiveVolumes(); + auto st2 = getStation2SensitiveVolumes(); + auto st345 = getStation345SensitiveVolumes(); + + auto vol = st1; + vol.insert(vol.end(), st2.begin(), st2.end()); + vol.insert(vol.end(), st345.begin(), st345.end()); + + return vol; +} + +void addAlignableVolumes(TGeoManager& geom) +{ + if (!geom.IsClosed()) { + geom.CloseGeometry(); + } + + LOG(INFO) << "Add MCH alignable volumes"; + + for (int hc = 0; hc < 20; hc++) { + int nCh = hc / 2 + 1; + + std::string volPathName = geom.GetTopVolume()->GetName(); + + if (nCh <= 4 && geom.GetVolume("YOUT1")) { + volPathName += "/YOUT1_1/"; + } else if ((nCh == 5 || nCh == 6) && geom.GetVolume("DDIP")) { + volPathName += "/DDIP_1/"; + } else if (nCh >= 7 && geom.GetVolume("YOUT2")) { + volPathName += "/YOUT2_1/"; + } else { + volPathName += "/"; + } + + std::string path = fmt::format("{0}SC{1}{2}{3}_{4}", volPathName.c_str(), nCh < 10 ? "0" : "", nCh, hc % 2 ? "O" : "I", hc); + std::string sname = fmt::format("MCH/HC{}", hc); + + LOG(DEBUG) << sname << " <-> " << path; + + auto ae = geom.SetAlignableEntry(sname.c_str(), path.c_str()); + if (!ae) { + LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; + } + + Int_t lastUID = 0; + + impl::addAlignableVolumesHalfChamber(geom, hc, volPathName); + } + + return; +} + +} // namespace o2::mch::geo diff --git a/Detectors/MUON/MCH/Geometry/Creator/src/MCHGeometryCreatorLinkDef.h b/Detectors/MUON/MCH/Geometry/Creator/src/MCHGeometryCreatorLinkDef.h new file mode 100644 index 0000000000000..e08a6167bd921 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Creator/src/MCHGeometryCreatorLinkDef.h @@ -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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ namespace o2::mch::geo; + +#pragma link C++ function o2::mch::geo::addAlignableVolumes; +#pragma link C++ function o2::mch::geo::createGeometry; +#pragma link C++ function o2::mch::geo::getSensitiveVolumes; + +#endif diff --git a/Detectors/MUON/MCH/Simulation/src/Materials.cxx b/Detectors/MUON/MCH/Geometry/Creator/src/Materials.cxx similarity index 100% rename from Detectors/MUON/MCH/Simulation/src/Materials.cxx rename to Detectors/MUON/MCH/Geometry/Creator/src/Materials.cxx diff --git a/Detectors/MUON/MCH/Simulation/src/Materials.h b/Detectors/MUON/MCH/Geometry/Creator/src/Materials.h similarity index 83% rename from Detectors/MUON/MCH/Simulation/src/Materials.h rename to Detectors/MUON/MCH/Geometry/Creator/src/Materials.h index acb3480688326..ed7b94881b0c4 100644 --- a/Detectors/MUON/MCH/Simulation/src/Materials.h +++ b/Detectors/MUON/MCH/Geometry/Creator/src/Materials.h @@ -13,15 +13,12 @@ /// \author Florian Damas <florian.damas@cern.ch> /// \date 22 march 2018 -#ifndef O2_MCH_SIMULATION_MATERIALS_H -#define O2_MCH_SIMULATION_MATERIALS_H +#ifndef O2_MCH_GEOMETRY_CREATOR_MATERIALS_H +#define O2_MCH_GEOMETRY_CREATOR_MATERIALS_H -#include <TGeoMedium.h> +class TGeoMedium; -namespace o2 -{ - -namespace mch +namespace o2::mch { enum Medium { @@ -48,7 +45,6 @@ TGeoMedium* assertMedium(int imed); void createMaterials(); -} // namespace mch -} // namespace o2 +} // namespace o2::mch -#endif // O2_MCH_SIMULATION_MATERIALS_H +#endif diff --git a/Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx b/Detectors/MUON/MCH/Geometry/Creator/src/Station1Geometry.cxx similarity index 100% rename from Detectors/MUON/MCH/Simulation/src/Station1Geometry.cxx rename to Detectors/MUON/MCH/Geometry/Creator/src/Station1Geometry.cxx diff --git a/Detectors/MUON/MCH/Simulation/src/Station1Geometry.h b/Detectors/MUON/MCH/Geometry/Creator/src/Station1Geometry.h similarity index 79% rename from Detectors/MUON/MCH/Simulation/src/Station1Geometry.h rename to Detectors/MUON/MCH/Geometry/Creator/src/Station1Geometry.h index 5137e1bf93a93..8018515a0e448 100644 --- a/Detectors/MUON/MCH/Simulation/src/Station1Geometry.h +++ b/Detectors/MUON/MCH/Geometry/Creator/src/Station1Geometry.h @@ -13,22 +13,19 @@ /// \author Florian Damas <florian.damas@cern.ch> /// \date 16 mai 2018 -#ifndef O2_MCH_SIMULATION_STATION1GEOMETRY_H -#define O2_MCH_SIMULATION_STATION1GEOMETRY_H +#ifndef O2_MCH_GEOMETRY_CREATOR_STATION1GEOMETRY_H +#define O2_MCH_GEOMETRY_CREATOR_STATION1GEOMETRY_H #include <vector> class TGeoVolume; -namespace o2 -{ -namespace mch +namespace o2::mch { void createStation1Geometry(TGeoVolume& topVolume); std::vector<TGeoVolume*> getStation1SensitiveVolumes(); -} // namespace mch -} // namespace o2 -#endif // O2_MCH_SIMULATION_STATION1GEOMETRY_H +} // namespace o2::mch +#endif diff --git a/Detectors/MUON/MCH/Simulation/src/Station2Geometry.cxx b/Detectors/MUON/MCH/Geometry/Creator/src/Station2Geometry.cxx similarity index 100% rename from Detectors/MUON/MCH/Simulation/src/Station2Geometry.cxx rename to Detectors/MUON/MCH/Geometry/Creator/src/Station2Geometry.cxx diff --git a/Detectors/MUON/MCH/Simulation/src/Station2Geometry.h b/Detectors/MUON/MCH/Geometry/Creator/src/Station2Geometry.h similarity index 79% rename from Detectors/MUON/MCH/Simulation/src/Station2Geometry.h rename to Detectors/MUON/MCH/Geometry/Creator/src/Station2Geometry.h index ad87a22be83f9..da9a1921430d0 100644 --- a/Detectors/MUON/MCH/Simulation/src/Station2Geometry.h +++ b/Detectors/MUON/MCH/Geometry/Creator/src/Station2Geometry.h @@ -13,22 +13,18 @@ /// \author Florian Damas <florian.damas@cern.ch> /// \date 23 mai 2018 -#ifndef O2_MCH_SIMULATION_STATION2GEOMETRY_H -#define O2_MCH_SIMULATION_STATION2GEOMETRY_H +#ifndef O2_MCH_GEOMETRY_CREATOR_STATION2GEOMETRY_H +#define O2_MCH_GEOMETRY_CREATOR_STATION2GEOMETRY_H #include <vector> class TGeoVolume; -namespace o2 +namespace o2::mch { -namespace mch -{ - void createStation2Geometry(TGeoVolume& topVolume); std::vector<TGeoVolume*> getStation2SensitiveVolumes(); -} // namespace mch -} // namespace o2 -#endif // O2_MCH_SIMULATION_STATION2GEOMETRY_H +} // namespace o2::mch +#endif diff --git a/Detectors/MUON/MCH/Simulation/src/Station345Geometry.cxx b/Detectors/MUON/MCH/Geometry/Creator/src/Station345Geometry.cxx similarity index 100% rename from Detectors/MUON/MCH/Simulation/src/Station345Geometry.cxx rename to Detectors/MUON/MCH/Geometry/Creator/src/Station345Geometry.cxx diff --git a/Detectors/MUON/MCH/Simulation/src/Station345Geometry.h b/Detectors/MUON/MCH/Geometry/Creator/src/Station345Geometry.h similarity index 83% rename from Detectors/MUON/MCH/Simulation/src/Station345Geometry.h rename to Detectors/MUON/MCH/Geometry/Creator/src/Station345Geometry.h index f538dd240d4ce..9e25c100f796b 100644 --- a/Detectors/MUON/MCH/Simulation/src/Station345Geometry.h +++ b/Detectors/MUON/MCH/Geometry/Creator/src/Station345Geometry.h @@ -13,22 +13,18 @@ /// \author Florian Damas <florian.damas@cern.ch> /// \date 22 march 2018 -#ifndef O2_MCH_SIMULATION_STATION345GEOMETRY_H -#define O2_MCH_SIMULATION_STATION345GEOMETRY_H +#ifndef O2_MCH_GEOMETRY_CREATOR_STATION345GEOMETRY_H +#define O2_MCH_GEOMETRY_CREATOR_STATION345GEOMETRY_H #include <vector> class TGeoVolume; -namespace o2 +namespace o2::mch { -namespace mch -{ - void createStation345Geometry(TGeoVolume& topVolume); std::vector<TGeoVolume*> getStation345SensitiveVolumes(); -} // namespace mch -} // namespace o2 +} // namespace o2::mch #endif diff --git a/Detectors/MUON/MCH/Geometry/README.md b/Detectors/MUON/MCH/Geometry/README.md new file mode 100644 index 0000000000000..7ceb822f51c85 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/README.md @@ -0,0 +1,15 @@ +<!-- doxy +\page refDetectorsMUONMCHGeometry Geometry +/doxy --> + +# MUON MCH Geometry + +The Geometry package is split in two parts : the [creation part](./Creator) (to +be used only for simulation) and the [transformation part](./Transformer) (to +be used from both simulation and reconstruction). + +<!-- doxy +\subpage refDetectorsMUONMCHGeometryTransformer +\subpage refDetectorsMUONMCHGeometryCreator +\subpage refDetectorsMUONMCHGeometryTest +/doxy --> diff --git a/Detectors/MUON/MCH/Geometry/Test/CMakeLists.txt b/Detectors/MUON/MCH/Geometry/Test/CMakeLists.txt new file mode 100644 index 0000000000000..b654993ec641a --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Test/CMakeLists.txt @@ -0,0 +1,44 @@ +# 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_library( + MCHGeometryTest + SOURCES Helpers.cxx + PUBLIC_LINK_LIBRARIES O2::MCHGeometryCreator) + +o2_target_root_dictionary(MCHGeometryTest HEADERS include/MCHGeometryTest/Helpers.h LINKDEF LinkDef.h) + +o2_add_test( + geometry-creator + COMPONENT_NAME mch + SOURCES testGeometryCreator.cxx + PUBLIC_LINK_LIBRARIES O2::MCHGeometryTest + LABELS muon mch) + +o2_add_test( + geometry-transformer NAME mch/geometry-transformer + COMPONENT_NAME mch + SOURCES testGeometryTransformer.cxx + PUBLIC_LINK_LIBRARIES O2::MCHGeometryTest + COMMAND_LINE_ARGS ${CMAKE_CURRENT_LIST_DIR}/ideal-geometry-o2.json + LABELS muon mch) + +o2_add_test( + geometry-transformer-legacy NAME mch/geometry-transformer-legacy + COMPONENT_NAME mch + SOURCES testGeometryTransformer.cxx + PUBLIC_LINK_LIBRARIES O2::MCHGeometryTest + COMMAND_LINE_ARGS ${CMAKE_CURRENT_LIST_DIR}/ideal-geometry-aliroot.json + LABELS muon mch) + +o2_add_test_root_macro( + drawMCHGeometry.C + PUBLIC_LINK_LIBRARIES O2::MCHGeometryCreator O2::MathUtils + LABELS muon mch) diff --git a/Detectors/MUON/MCH/Simulation/src/GeometryTest.cxx b/Detectors/MUON/MCH/Geometry/Test/Helpers.cxx similarity index 80% rename from Detectors/MUON/MCH/Simulation/src/GeometryTest.cxx rename to Detectors/MUON/MCH/Geometry/Test/Helpers.cxx index 42aa7dc8302b0..d5a3530be4be9 100644 --- a/Detectors/MUON/MCH/Simulation/src/GeometryTest.cxx +++ b/Detectors/MUON/MCH/Geometry/Test/Helpers.cxx @@ -8,27 +8,20 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "MCHSimulation/GeometryTest.h" - #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/MaterialManager.h" -#include "MCHSimulation/Geometry.h" +#include "MCHGeometryCreator/Geometry.h" +#include "MCHGeometryTest/Helpers.h" +#include "MCHGeometryTransformer/Transformations.h" #include "Math/GenVector/Cartesian3D.h" +#include "TGLRnrCtx.h" +#include "TGLViewer.h" #include "TGeoManager.h" #include "TGeoVolume.h" #include "TH2F.h" -#include <iostream> #include "TPRegexp.h" -#include "TGLViewer.h" -#include "TGLRnrCtx.h" #include "TVirtualPad.h" -#include "DetectorsPassive/Cave.h" -#include "DetectorsPassive/Dipole.h" -#include "DetectorsPassive/Absorber.h" -#include "DetectorsPassive/Compensator.h" -#include "DetectorsPassive/Shil.h" -#include "DetectorsPassive/Pipe.h" -#include "MCHSimulation/Detector.h" +#include <iostream> namespace o2 { @@ -117,37 +110,7 @@ void createStandaloneGeometry() TGeoManager* g = new TGeoManager("MCH-ONLY", "ALICE MCH Standalone Geometry"); TGeoVolume* top = createAirVacuumCave("cave"); g->SetTopVolume(top); - o2::mch::createGeometry(*top); -} - -void createRegularGeometry() -{ - if (gGeoManager && gGeoManager->GetTopVolume()) { - std::cerr << "Can only call this function with an empty geometry, i.e. gGeoManager==nullptr " - << " or gGeoManager->GetTopVolume()==nullptr\n"; - } - TGeoManager* g = new TGeoManager("MCH-BASICS", "ALICE MCH Regular Geometry"); - o2::passive::Cave("CAVE", "Cave (for MCH Basics)").ConstructGeometry(); - o2::passive::Dipole("DIPO", "Alice Dipole (for MCH Basics)").ConstructGeometry(); - o2::passive::Compensator("COMP", "Alice Compensator Dipole (for MCH Basics)").ConstructGeometry(); - o2::passive::Pipe("PIPE", "Beam pipe (for MCH Basics)").ConstructGeometry(); - o2::passive::Shil("SHIL", "Small angle beam shield (for MCH Basics)").ConstructGeometry(); - o2::passive::Absorber("ABSO", "Absorber (for MCH Basics)").ConstructGeometry(); - o2::mch::Detector(true).ConstructGeometry(); -} - -void addAlignableVolumes() -{ - if (!gGeoManager) { - std::cerr << "gGeoManager == nullptr, must create a geometry first\n"; - return; - } - // If not closed, we need to close it - if (!gGeoManager->IsClosed()) { - gGeoManager->CloseGeometry(); - } - // Then add the alignable volumes - o2::mch::Detector(true).addAlignableVolumes(); + o2::mch::geo::createGeometry(*g, *top); } void setVolumeVisibility(const char* pattern, bool visible, bool visibleDaughters) @@ -258,7 +221,8 @@ TH2* getRadio(int detElemId, float xmin, float ymin, float xmax, float ymax, flo } TH2* hmatb = new TH2F("hmatb", "hmatb", (int)((xmax - xmin) / xstep), xmin, xmax, (int)((ymax - ymin) / ystep), ymin, ymax); - auto t = o2::mch::getTransformation(detElemId, *gGeoManager); + auto transformation = o2::mch::geo::transformationFromTGeoManager(*gGeoManager); + auto t = transformation(detElemId); auto normal = getNormalVector(t); diff --git a/Detectors/MUON/MCH/Geometry/Test/LinkDef.h b/Detectors/MUON/MCH/Geometry/Test/LinkDef.h new file mode 100644 index 0000000000000..c51f6bec0eb82 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Test/LinkDef.h @@ -0,0 +1,29 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ namespace o2::mch::test; + +#pragma link C++ class o2::mch::test::Dummy; + +#pragma link C++ function o2::mch::test::createStandaloneGeometry; +#pragma link C++ function o2::mch::test::createRegularGeometry; +#pragma link C++ function o2::mch::test::drawGeometry; +#pragma link C++ function o2::mch::test::getRadio; +#pragma link C++ function o2::mch::test::showGeometryAsTextTree; +#pragma link C++ function o2::mch::test::setVolumeVisibility; +#pragma link C++ function o2::mch::test::setVolumeColor; + +#endif diff --git a/Detectors/MUON/MCH/Geometry/Test/README.md b/Detectors/MUON/MCH/Geometry/Test/README.md new file mode 100644 index 0000000000000..2ccf93b48c1fa --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Test/README.md @@ -0,0 +1,13 @@ +<!-- doxy +\page refDetectorsMUONMCHGeometryTest Test +/doxy --> + +# MCH Geometry Helpers + +The [MCHGeometryTest](./include/MCHGeometryTest/Helpers.h) library offers a few +utility functions to help debug the MCH geometry : [draw +it](./drawMCHGeometry.C), dump it as text, create a standalone version of it +(i.e. without other ALICE volumes) + +Also provides a `getRadio` function to get a radiation length plot of a given +detection element. diff --git a/Detectors/MUON/MCH/Simulation/macros/drawMCHGeometry.C b/Detectors/MUON/MCH/Geometry/Test/drawMCHGeometry.C similarity index 74% rename from Detectors/MUON/MCH/Simulation/macros/drawMCHGeometry.C rename to Detectors/MUON/MCH/Geometry/Test/drawMCHGeometry.C index 82b56b2fafbdd..80235f0bb4ff6 100644 --- a/Detectors/MUON/MCH/Simulation/macros/drawMCHGeometry.C +++ b/Detectors/MUON/MCH/Geometry/Test/drawMCHGeometry.C @@ -1,5 +1,5 @@ #if !defined(__CLING__) || defined(__ROOTCLING__) -#include "MCHSimulation/GeometryTest.h" +#include "MCHGeometryTest/Helpers.h" #endif void drawMCHGeometry() diff --git a/Detectors/MUON/MCH/Geometry/Test/ideal-geometry-aliroot.json b/Detectors/MUON/MCH/Geometry/Test/ideal-geometry-aliroot.json new file mode 100644 index 0000000000000..e12ccadb6d8cd --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Test/ideal-geometry-aliroot.json @@ -0,0 +1,2224 @@ +{ + "alignables": [ + { + "symname": "/MUON/GM0", + "transform": { + "tx": 0, + "ty": 0, + "tz": -526.1599731445312, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "symname": "/MUON/GM1", + "transform": { + "tx": 0, + "ty": 0, + "tz": -545.239990234375, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "symname": "/MUON/GM2", + "transform": { + "tx": 0, + "ty": 0, + "tz": -676.4000244140625, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "symname": "/MUON/GM3", + "transform": { + "tx": 0, + "ty": 0, + "tz": -695.4000244140625, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "symname": "/MUON/GM4", + "transform": { + "tx": 0, + "ty": -0.16628965477512675, + "tz": -967.4988477676281, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM5", + "transform": { + "tx": 0, + "ty": 0.16628965477512675, + "tz": -967.5011522323719, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM6", + "transform": { + "tx": 0, + "ty": -0.16628965477512675, + "tz": -998.4988477676281, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM7", + "transform": { + "tx": 0, + "ty": 0.16628965477512675, + "tz": -998.5011522323719, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM8", + "transform": { + "tx": 0, + "ty": -0.16628965477512675, + "tz": -1276.4988477676281, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM9", + "transform": { + "tx": 0, + "ty": 0.16628965477512675, + "tz": -1276.5011522323719, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM10", + "transform": { + "tx": 0, + "ty": -0.16628965477512675, + "tz": -1307.4988477676281, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM11", + "transform": { + "tx": 0, + "ty": 0.16628965477512675, + "tz": -1307.5011522323719, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM12", + "transform": { + "tx": 0, + "ty": -0.16628965477512675, + "tz": -1406.5988233535656, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM13", + "transform": { + "tx": 0, + "ty": 0.16628965477512675, + "tz": -1406.6011278183094, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM14", + "transform": { + "tx": 0, + "ty": -0.16628965477512675, + "tz": -1437.5988233535656, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "symname": "/MUON/GM15", + "transform": { + "tx": 0, + "ty": 0.16628965477512675, + "tz": -1437.6011278183094, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 100, + "symname": "/MUON/GM0/DE100", + "transform": { + "tx": 0.185, + "ty": -0.52, + "tz": -529.9099731445312, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 101, + "symname": "/MUON/GM0/DE101", + "transform": { + "tx": -0.185, + "ty": -0.52, + "tz": -522.4099731445312, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 102, + "symname": "/MUON/GM0/DE102", + "transform": { + "tx": -0.185, + "ty": 0.52, + "tz": -529.9099731445312, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 103, + "symname": "/MUON/GM0/DE103", + "transform": { + "tx": 0.185, + "ty": 0.52, + "tz": -522.4099731445312, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 200, + "symname": "/MUON/GM1/DE200", + "transform": { + "tx": 0.185, + "ty": -0.52, + "tz": -548.989990234375, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 201, + "symname": "/MUON/GM1/DE201", + "transform": { + "tx": -0.185, + "ty": -0.52, + "tz": -541.489990234375, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 202, + "symname": "/MUON/GM1/DE202", + "transform": { + "tx": -0.185, + "ty": 0.52, + "tz": -548.989990234375, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 203, + "symname": "/MUON/GM1/DE203", + "transform": { + "tx": 0.185, + "ty": 0.52, + "tz": -541.489990234375, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 300, + "symname": "/MUON/GM2/DE300", + "transform": { + "tx": 0, + "ty": 0, + "tz": -679.8000245094299, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 301, + "symname": "/MUON/GM2/DE301", + "transform": { + "tx": 0, + "ty": 0, + "tz": -673.0000243186951, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 302, + "symname": "/MUON/GM2/DE302", + "transform": { + "tx": 0, + "ty": 0, + "tz": -679.8000245094299, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 303, + "symname": "/MUON/GM2/DE303", + "transform": { + "tx": 0, + "ty": 0, + "tz": -673.0000243186951, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 400, + "symname": "/MUON/GM3/DE400", + "transform": { + "tx": 0, + "ty": 0, + "tz": -698.8000245094299, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 401, + "symname": "/MUON/GM3/DE401", + "transform": { + "tx": 0, + "ty": 0, + "tz": -692.0000243186951, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 402, + "symname": "/MUON/GM3/DE402", + "transform": { + "tx": 0, + "ty": 0, + "tz": -698.8000245094299, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": true + }, + { + "deid": 403, + "symname": "/MUON/GM3/DE403", + "transform": { + "tx": 0, + "ty": 0, + "tz": -692.0000243186951, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": true + }, + { + "deid": 500, + "symname": "/MUON/GM4/DE500", + "transform": { + "tx": 81.25, + "ty": -0.003464367807815144, + "tz": -955.7499759951589, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 501, + "symname": "/MUON/GM4/DE501", + "transform": { + "tx": 81.25, + "ty": 37.68204556750454, + "tz": -964.2730202422136, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 502, + "symname": "/MUON/GM4/DE502", + "transform": { + "tx": 81.25, + "ty": 75.48928617018588, + "tz": -956.7962150731191, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 503, + "symname": "/MUON/GM4/DE503", + "transform": { + "tx": 61.25, + "ty": 112.67484792951139, + "tz": -965.3123306374202, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 504, + "symname": "/MUON/GM4/DE504", + "transform": { + "tx": 41.25, + "ty": 146.48246879531905, + "tz": -957.7800955305386, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 505, + "symname": "/MUON/GM5/DE505", + "transform": { + "tx": -41.25, + "ty": 146.48939753093464, + "tz": -981.2801435402207, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 506, + "symname": "/MUON/GM5/DE506", + "transform": { + "tx": -61.25, + "ty": 112.90349620482719, + "tz": -972.8139149569315, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 507, + "symname": "/MUON/GM5/DE507", + "transform": { + "tx": -81.25, + "ty": 75.49621490580152, + "tz": -980.2962630828013, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 508, + "symname": "/MUON/GM5/DE508", + "transform": { + "tx": -81.25, + "ty": 37.91069384282034, + "tz": -971.7746045617249, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 509, + "symname": "/MUON/GM5/DE509", + "transform": { + "tx": -81.25, + "ty": 0.003464367807815144, + "tz": -979.2500240048411, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 510, + "symname": "/MUON/GM5/DE510", + "transform": { + "tx": -81.25, + "ty": -37.68204556750454, + "tz": -970.7269797577864, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 511, + "symname": "/MUON/GM5/DE511", + "transform": { + "tx": -81.25, + "ty": -75.48928617018588, + "tz": -978.2037849268809, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 512, + "symname": "/MUON/GM5/DE512", + "transform": { + "tx": -61.25, + "ty": -112.67484792951139, + "tz": -969.6876693625798, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 513, + "symname": "/MUON/GM5/DE513", + "transform": { + "tx": -41.25, + "ty": -146.48246879531905, + "tz": -977.2199044694614, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 514, + "symname": "/MUON/GM4/DE514", + "transform": { + "tx": 41.25, + "ty": -146.48939753093464, + "tz": -953.7198564597793, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 515, + "symname": "/MUON/GM4/DE515", + "transform": { + "tx": 61.25, + "ty": -112.90349620482719, + "tz": -962.1860850430685, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 516, + "symname": "/MUON/GM4/DE516", + "transform": { + "tx": 81.25, + "ty": -75.49621490580152, + "tz": -954.7037369171987, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 517, + "symname": "/MUON/GM4/DE517", + "transform": { + "tx": 81.25, + "ty": -37.91069384282034, + "tz": -963.2253954382751, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 600, + "symname": "/MUON/GM6/DE600", + "transform": { + "tx": 81.25, + "ty": -0.003464367807815144, + "tz": -986.7499759951589, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 601, + "symname": "/MUON/GM6/DE601", + "transform": { + "tx": 81.25, + "ty": 37.68204556750454, + "tz": -995.2730202422136, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 602, + "symname": "/MUON/GM6/DE602", + "transform": { + "tx": 81.25, + "ty": 75.48928617018588, + "tz": -987.7962150731191, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 603, + "symname": "/MUON/GM6/DE603", + "transform": { + "tx": 61.25, + "ty": 112.67484792951139, + "tz": -996.3123306374202, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 604, + "symname": "/MUON/GM6/DE604", + "transform": { + "tx": 41.25, + "ty": 146.48246879531905, + "tz": -988.7800955305386, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 605, + "symname": "/MUON/GM7/DE605", + "transform": { + "tx": -41.25, + "ty": 146.48939753093464, + "tz": -1012.2801435402207, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 606, + "symname": "/MUON/GM7/DE606", + "transform": { + "tx": -61.25, + "ty": 112.90349620482719, + "tz": -1003.8139149569315, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 607, + "symname": "/MUON/GM7/DE607", + "transform": { + "tx": -81.25, + "ty": 75.49621490580152, + "tz": -1011.2962630828013, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 608, + "symname": "/MUON/GM7/DE608", + "transform": { + "tx": -81.25, + "ty": 37.91069384282034, + "tz": -1002.7746045617249, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 609, + "symname": "/MUON/GM7/DE609", + "transform": { + "tx": -81.25, + "ty": 0.003464367807815144, + "tz": -1010.2500240048411, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 610, + "symname": "/MUON/GM7/DE610", + "transform": { + "tx": -81.25, + "ty": -37.68204556750454, + "tz": -1001.7269797577864, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 611, + "symname": "/MUON/GM7/DE611", + "transform": { + "tx": -81.25, + "ty": -75.48928617018588, + "tz": -1009.2037849268809, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 612, + "symname": "/MUON/GM7/DE612", + "transform": { + "tx": -61.25, + "ty": -112.67484792951139, + "tz": -1000.6876693625798, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 613, + "symname": "/MUON/GM7/DE613", + "transform": { + "tx": -41.25, + "ty": -146.48246879531905, + "tz": -1008.2199044694614, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 614, + "symname": "/MUON/GM6/DE614", + "transform": { + "tx": 41.25, + "ty": -146.48939753093464, + "tz": -984.7198564597793, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 615, + "symname": "/MUON/GM6/DE615", + "transform": { + "tx": 61.25, + "ty": -112.90349620482719, + "tz": -993.1860850430685, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 616, + "symname": "/MUON/GM6/DE616", + "transform": { + "tx": 81.25, + "ty": -75.49621490580152, + "tz": -985.7037369171987, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 617, + "symname": "/MUON/GM6/DE617", + "transform": { + "tx": 81.25, + "ty": -37.91069384282034, + "tz": -994.2253954382751, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 700, + "symname": "/MUON/GM8/DE700", + "transform": { + "tx": 140, + "ty": 0, + "tz": -1264.5, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 701, + "symname": "/MUON/GM8/DE701", + "transform": { + "tx": 121.25, + "ty": 38.07854431768339, + "tz": -1273.5285392470098, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 702, + "symname": "/MUON/GM8/DE702", + "transform": { + "tx": 101.25, + "ty": 72.5930350970798, + "tz": -1265.5060524959688, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 703, + "symname": "/MUON/GM8/DE703", + "transform": { + "tx": 101.25, + "ty": 109.07173075714752, + "tz": -1274.5124197572914, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 704, + "symname": "/MUON/GM8/DE704", + "transform": { + "tx": 81.25, + "ty": 138.48670131804144, + "tz": -1266.4192597655297, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 705, + "symname": "/MUON/GM8/DE705", + "transform": { + "tx": 61.25, + "ty": 175.36536009609583, + "tz": -1275.4311700364894, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 706, + "symname": "/MUON/GM8/DE706", + "transform": { + "tx": 41.25, + "ty": 204.08040855067148, + "tz": -1267.3283099628795, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 707, + "symname": "/MUON/GM9/DE707", + "transform": { + "tx": -41.25, + "ty": 204.08040855067148, + "tz": -1291.3283099628795, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 708, + "symname": "/MUON/GM9/DE708", + "transform": { + "tx": -61.25, + "ty": 175.60093710702725, + "tz": -1282.4328023656828, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 709, + "symname": "/MUON/GM9/DE709", + "transform": { + "tx": -81.25, + "ty": 138.48670131804144, + "tz": -1290.4192597655297, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 710, + "symname": "/MUON/GM9/DE710", + "transform": { + "tx": -101.25, + "ty": 109.30730776807894, + "tz": -1281.5140520864848, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 711, + "symname": "/MUON/GM9/DE711", + "transform": { + "tx": -101.25, + "ty": 72.5930350970798, + "tz": -1289.5060524959688, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 712, + "symname": "/MUON/GM9/DE712", + "transform": { + "tx": -121.25, + "ty": 38.314121328614824, + "tz": -1280.5301715762032, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 713, + "symname": "/MUON/GM9/DE713", + "transform": { + "tx": -140, + "ty": 0, + "tz": -1288.5, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 714, + "symname": "/MUON/GM9/DE714", + "transform": { + "tx": -121.25, + "ty": -38.07854431768339, + "tz": -1279.4714607529902, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 715, + "symname": "/MUON/GM9/DE715", + "transform": { + "tx": -101.25, + "ty": -72.5930350970798, + "tz": -1287.4939475040312, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 716, + "symname": "/MUON/GM9/DE716", + "transform": { + "tx": -101.25, + "ty": -109.07173075714752, + "tz": -1278.4875802427086, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 717, + "symname": "/MUON/GM9/DE717", + "transform": { + "tx": -81.25, + "ty": -138.48670131804144, + "tz": -1286.5807402344703, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 718, + "symname": "/MUON/GM9/DE718", + "transform": { + "tx": -61.25, + "ty": -175.36536009609583, + "tz": -1277.5688299635106, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 719, + "symname": "/MUON/GM9/DE719", + "transform": { + "tx": -41.25, + "ty": -204.08040855067148, + "tz": -1285.6716900371205, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 720, + "symname": "/MUON/GM8/DE720", + "transform": { + "tx": 41.25, + "ty": -204.08040855067148, + "tz": -1261.6716900371205, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 721, + "symname": "/MUON/GM8/DE721", + "transform": { + "tx": 61.25, + "ty": -175.60093710702725, + "tz": -1270.5671976343172, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 722, + "symname": "/MUON/GM8/DE722", + "transform": { + "tx": 81.25, + "ty": -138.48670131804144, + "tz": -1262.5807402344703, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 723, + "symname": "/MUON/GM8/DE723", + "transform": { + "tx": 101.25, + "ty": -109.30730776807894, + "tz": -1271.4859479135152, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 724, + "symname": "/MUON/GM8/DE724", + "transform": { + "tx": 101.25, + "ty": -72.5930350970798, + "tz": -1263.4939475040312, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 725, + "symname": "/MUON/GM8/DE725", + "transform": { + "tx": 121.25, + "ty": -38.314121328614824, + "tz": -1272.4698284237968, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 800, + "symname": "/MUON/GM10/DE800", + "transform": { + "tx": 140, + "ty": 0, + "tz": -1295.5, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 801, + "symname": "/MUON/GM10/DE801", + "transform": { + "tx": 121.25, + "ty": 38.07854431768339, + "tz": -1304.5285392470098, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 802, + "symname": "/MUON/GM10/DE802", + "transform": { + "tx": 101.25, + "ty": 76.04270077880811, + "tz": -1296.553860729427, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 803, + "symname": "/MUON/GM10/DE803", + "transform": { + "tx": 101.25, + "ty": 113.4713097976769, + "tz": -1305.5733926518537, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 804, + "symname": "/MUON/GM10/DE804", + "transform": { + "tx": 81.25, + "ty": 142.986269230902, + "tz": -1297.4816183860703, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 805, + "symname": "/MUON/GM10/DE805", + "transform": { + "tx": 61.25, + "ty": 179.86492800895635, + "tz": -1306.49352865703, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 806, + "symname": "/MUON/GM10/DE806", + "transform": { + "tx": 41.25, + "ty": 208.57997646353203, + "tz": -1298.3906685834202, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 807, + "symname": "/MUON/GM11/DE807", + "transform": { + "tx": -41.25, + "ty": 208.57997646353203, + "tz": -1322.3906685834202, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 808, + "symname": "/MUON/GM11/DE808", + "transform": { + "tx": -61.25, + "ty": 180.10050501988778, + "tz": -1313.4951609862237, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 809, + "symname": "/MUON/GM11/DE809", + "transform": { + "tx": -81.25, + "ty": 142.986269230902, + "tz": -1321.4816183860703, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 810, + "symname": "/MUON/GM11/DE810", + "transform": { + "tx": -101.25, + "ty": 113.70688680860832, + "tz": -1312.5750249810471, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 811, + "symname": "/MUON/GM11/DE811", + "transform": { + "tx": -101.25, + "ty": 76.04270077880811, + "tz": -1320.553860729427, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 812, + "symname": "/MUON/GM11/DE812", + "transform": { + "tx": -121.25, + "ty": 38.314121328614824, + "tz": -1311.5301715762032, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 813, + "symname": "/MUON/GM11/DE813", + "transform": { + "tx": -140, + "ty": 0, + "tz": -1319.5, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 814, + "symname": "/MUON/GM11/DE814", + "transform": { + "tx": -121.25, + "ty": -38.07854431768339, + "tz": -1310.4714607529902, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 815, + "symname": "/MUON/GM11/DE815", + "transform": { + "tx": -101.25, + "ty": -76.04270077880811, + "tz": -1318.446139270573, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 816, + "symname": "/MUON/GM11/DE816", + "transform": { + "tx": -101.25, + "ty": -113.4713097976769, + "tz": -1309.4266073481463, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 817, + "symname": "/MUON/GM11/DE817", + "transform": { + "tx": -81.25, + "ty": -142.986269230902, + "tz": -1317.5183816139297, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 818, + "symname": "/MUON/GM11/DE818", + "transform": { + "tx": -61.25, + "ty": -179.86492800895635, + "tz": -1308.50647134297, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 819, + "symname": "/MUON/GM11/DE819", + "transform": { + "tx": -41.25, + "ty": -208.57997646353203, + "tz": -1316.6093314165798, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 820, + "symname": "/MUON/GM10/DE820", + "transform": { + "tx": 41.25, + "ty": -208.57997646353203, + "tz": -1292.6093314165798, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 821, + "symname": "/MUON/GM10/DE821", + "transform": { + "tx": 61.25, + "ty": -180.10050501988778, + "tz": -1301.5048390137763, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 822, + "symname": "/MUON/GM10/DE822", + "transform": { + "tx": 81.25, + "ty": -142.986269230902, + "tz": -1293.5183816139297, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 823, + "symname": "/MUON/GM10/DE823", + "transform": { + "tx": 101.25, + "ty": -113.70688680860832, + "tz": -1302.4249750189529, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 824, + "symname": "/MUON/GM10/DE824", + "transform": { + "tx": 101.25, + "ty": -76.04270077880811, + "tz": -1294.446139270573, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 825, + "symname": "/MUON/GM10/DE825", + "transform": { + "tx": 121.25, + "ty": -38.314121328614824, + "tz": -1303.4698284237968, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 900, + "symname": "/MUON/GM12/DE900", + "transform": { + "tx": 140, + "ty": 0, + "tz": -1394.5999755859375, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 901, + "symname": "/MUON/GM12/DE901", + "transform": { + "tx": 121.25, + "ty": 38.07854431768339, + "tz": -1403.6285148329473, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 902, + "symname": "/MUON/GM12/DE902", + "transform": { + "tx": 121.25, + "ty": 76.09269902930468, + "tz": -1395.6545292312157, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 903, + "symname": "/MUON/GM12/DE903", + "transform": { + "tx": 121.25, + "ty": 113.57129867000808, + "tz": -1404.6747539637695, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 904, + "symname": "/MUON/GM12/DE904", + "transform": { + "tx": 101.25, + "ty": 150.9855010759874, + "tz": -1396.692453741858, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 905, + "symname": "/MUON/GM12/DE905", + "transform": { + "tx": 81.25, + "ty": 187.91415810453836, + "tz": -1405.705056928669, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 906, + "symname": "/MUON/GM12/DE906", + "transform": { + "tx": 61.25, + "ty": 224.77841789836523, + "tz": -1397.7151351610146, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 907, + "symname": "/MUON/GM13/DE907", + "transform": { + "tx": -61.25, + "ty": 224.77841789836523, + "tz": -1421.7151351610146, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 908, + "symname": "/MUON/GM13/DE908", + "transform": { + "tx": -81.25, + "ty": 188.14973511546978, + "tz": -1412.7066892578623, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 909, + "symname": "/MUON/GM13/DE909", + "transform": { + "tx": -101.25, + "ty": 150.9855010759874, + "tz": -1420.692453741858, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 910, + "symname": "/MUON/GM13/DE910", + "transform": { + "tx": -121.25, + "ty": 113.8068756809395, + "tz": -1411.6763862929631, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 911, + "symname": "/MUON/GM13/DE911", + "transform": { + "tx": -121.25, + "ty": 76.09269902930468, + "tz": -1419.6545292312157, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 912, + "symname": "/MUON/GM13/DE912", + "transform": { + "tx": -121.25, + "ty": 38.314121328614824, + "tz": -1410.6301471621407, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 913, + "symname": "/MUON/GM13/DE913", + "transform": { + "tx": -140, + "ty": 0, + "tz": -1418.5999755859375, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 914, + "symname": "/MUON/GM13/DE914", + "transform": { + "tx": -121.25, + "ty": -38.07854431768339, + "tz": -1409.5714363389277, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 915, + "symname": "/MUON/GM13/DE915", + "transform": { + "tx": -121.25, + "ty": -76.09269902930468, + "tz": -1417.5454219406593, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 916, + "symname": "/MUON/GM13/DE916", + "transform": { + "tx": -121.25, + "ty": -113.57129867000808, + "tz": -1408.5251972081055, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 917, + "symname": "/MUON/GM13/DE917", + "transform": { + "tx": -101.25, + "ty": -150.9855010759874, + "tz": -1416.507497430017, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 918, + "symname": "/MUON/GM13/DE918", + "transform": { + "tx": -81.25, + "ty": -187.91415810453836, + "tz": -1407.494894243206, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 919, + "symname": "/MUON/GM13/DE919", + "transform": { + "tx": -61.25, + "ty": -224.77841789836523, + "tz": -1415.4848160108604, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 920, + "symname": "/MUON/GM12/DE920", + "transform": { + "tx": 61.25, + "ty": -224.77841789836523, + "tz": -1391.4848160108604, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 921, + "symname": "/MUON/GM12/DE921", + "transform": { + "tx": 81.25, + "ty": -188.14973511546978, + "tz": -1400.4932619140127, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 922, + "symname": "/MUON/GM12/DE922", + "transform": { + "tx": 101.25, + "ty": -150.9855010759874, + "tz": -1392.507497430017, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 923, + "symname": "/MUON/GM12/DE923", + "transform": { + "tx": 121.25, + "ty": -113.8068756809395, + "tz": -1401.5235648789119, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 924, + "symname": "/MUON/GM12/DE924", + "transform": { + "tx": 121.25, + "ty": -76.09269902930468, + "tz": -1393.5454219406593, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 925, + "symname": "/MUON/GM12/DE925", + "transform": { + "tx": 121.25, + "ty": -38.314121328614824, + "tz": -1402.5698040097343, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1000, + "symname": "/MUON/GM14/DE1000", + "transform": { + "tx": 140, + "ty": 0, + "tz": -1425.5999755859375, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1001, + "symname": "/MUON/GM14/DE1001", + "transform": { + "tx": 121.25, + "ty": 38.07854431768339, + "tz": -1434.6285148329473, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1002, + "symname": "/MUON/GM14/DE1002", + "transform": { + "tx": 121.25, + "ty": 76.09269902930468, + "tz": -1426.6545292312157, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1003, + "symname": "/MUON/GM14/DE1003", + "transform": { + "tx": 121.25, + "ty": 113.57129867000808, + "tz": -1435.6747539637695, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1004, + "symname": "/MUON/GM14/DE1004", + "transform": { + "tx": 101.25, + "ty": 150.9855010759874, + "tz": -1427.692453741858, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1005, + "symname": "/MUON/GM14/DE1005", + "transform": { + "tx": 81.25, + "ty": 187.91415810453836, + "tz": -1436.705056928669, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1006, + "symname": "/MUON/GM14/DE1006", + "transform": { + "tx": 61.25, + "ty": 224.77841789836523, + "tz": -1428.7151351610146, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1007, + "symname": "/MUON/GM15/DE1007", + "transform": { + "tx": -61.25, + "ty": 224.77841789836523, + "tz": -1452.7151351610146, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1008, + "symname": "/MUON/GM15/DE1008", + "transform": { + "tx": -81.25, + "ty": 188.14973511546978, + "tz": -1443.7066892578623, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1009, + "symname": "/MUON/GM15/DE1009", + "transform": { + "tx": -101.25, + "ty": 150.9855010759874, + "tz": -1451.692453741858, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1010, + "symname": "/MUON/GM15/DE1010", + "transform": { + "tx": -121.25, + "ty": 113.8068756809395, + "tz": -1442.6763862929631, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1011, + "symname": "/MUON/GM15/DE1011", + "transform": { + "tx": -121.25, + "ty": 76.09269902930468, + "tz": -1450.6545292312157, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1012, + "symname": "/MUON/GM15/DE1012", + "transform": { + "tx": -121.25, + "ty": 38.314121328614824, + "tz": -1441.6301471621407, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1013, + "symname": "/MUON/GM15/DE1013", + "transform": { + "tx": -140, + "ty": 0, + "tz": -1449.5999755859375, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1014, + "symname": "/MUON/GM15/DE1014", + "transform": { + "tx": -121.25, + "ty": -38.07854431768339, + "tz": -1440.5714363389277, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1015, + "symname": "/MUON/GM15/DE1015", + "transform": { + "tx": -121.25, + "ty": -76.09269902930468, + "tz": -1448.5454219406593, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1016, + "symname": "/MUON/GM15/DE1016", + "transform": { + "tx": -121.25, + "ty": -113.57129867000808, + "tz": -1439.5251972081055, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1017, + "symname": "/MUON/GM15/DE1017", + "transform": { + "tx": -101.25, + "ty": -150.9855010759874, + "tz": -1447.507497430017, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1018, + "symname": "/MUON/GM15/DE1018", + "transform": { + "tx": -81.25, + "ty": -187.91415810453836, + "tz": -1438.494894243206, + "yaw": -180, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1019, + "symname": "/MUON/GM15/DE1019", + "transform": { + "tx": -61.25, + "ty": -224.77841789836523, + "tz": -1446.4848160108604, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1020, + "symname": "/MUON/GM14/DE1020", + "transform": { + "tx": 61.25, + "ty": -224.77841789836523, + "tz": -1422.4848160108604, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1021, + "symname": "/MUON/GM14/DE1021", + "transform": { + "tx": 81.25, + "ty": -188.14973511546978, + "tz": -1431.4932619140127, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1022, + "symname": "/MUON/GM14/DE1022", + "transform": { + "tx": 101.25, + "ty": -150.9855010759874, + "tz": -1423.507497430017, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1023, + "symname": "/MUON/GM14/DE1023", + "transform": { + "tx": 121.25, + "ty": -113.8068756809395, + "tz": -1432.5235648789119, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + }, + { + "deid": 1024, + "symname": "/MUON/GM14/DE1024", + "transform": { + "tx": 121.25, + "ty": -76.09269902930468, + "tz": -1424.5454219406593, + "yaw": -0, + "pitch": 0, + "roll": 179.2059999704361 + }, + "aligned": true + }, + { + "deid": 1025, + "symname": "/MUON/GM14/DE1025", + "transform": { + "tx": 121.25, + "ty": -38.314121328614824, + "tz": -1433.5698040097343, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000295639039 + }, + "aligned": true + } + ] +} diff --git a/Detectors/MUON/MCH/Geometry/Test/ideal-geometry-o2.json b/Detectors/MUON/MCH/Geometry/Test/ideal-geometry-o2.json new file mode 100644 index 0000000000000..a385539ed7e07 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Test/ideal-geometry-o2.json @@ -0,0 +1,2272 @@ +{ + "alignables": [ + { + "symname": "MCH/HC0", + "transform": { + "tx": 0, + "ty": 0, + "tz": -526.1599731445312, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC1", + "transform": { + "tx": 0, + "ty": 0, + "tz": -526.1599731445312, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC2", + "transform": { + "tx": 0, + "ty": 0, + "tz": -545.239990234375, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC3", + "transform": { + "tx": 0, + "ty": 0, + "tz": -545.239990234375, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC4", + "transform": { + "tx": 0, + "ty": 0, + "tz": -676.4, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC5", + "transform": { + "tx": 0, + "ty": 0, + "tz": -676.4, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC6", + "transform": { + "tx": 0, + "ty": 0, + "tz": -695.4, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC7", + "transform": { + "tx": 0, + "ty": 0, + "tz": -695.4, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "symname": "MCH/HC8", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -959.75, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC9", + "transform": { + "tx": 0, + "ty": 0.1074, + "tz": -975.25, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC10", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -990.75, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC11", + "transform": { + "tx": 0, + "ty": 0.1074, + "tz": -1006.25, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC12", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1259.75, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC13", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1284.25, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC14", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1299.75, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC15", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1315.25, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC16", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1398.85, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC17", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1414.35, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC18", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1429.85, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "symname": "MCH/HC19", + "transform": { + "tx": 0, + "ty": -0.1074, + "tz": -1445.35, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 100, + "symname": "MCH/HC0/DE100", + "transform": { + "tx": 0.1850000023841858, + "ty": -0.5199999809265137, + "tz": -529.9099731445312, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 101, + "symname": "MCH/HC1/DE101", + "transform": { + "tx": -0.1850000023841858, + "ty": -0.5199999809265137, + "tz": -522.4099731445312, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 102, + "symname": "MCH/HC1/DE102", + "transform": { + "tx": -0.1850000023841858, + "ty": 0.5199999809265137, + "tz": -529.9099731445312, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 103, + "symname": "MCH/HC0/DE103", + "transform": { + "tx": 0.1850000023841858, + "ty": 0.5199999809265137, + "tz": -522.4099731445312, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 200, + "symname": "MCH/HC2/DE200", + "transform": { + "tx": 0.1850000023841858, + "ty": -0.5199999809265137, + "tz": -548.989990234375, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 201, + "symname": "MCH/HC3/DE201", + "transform": { + "tx": -0.1850000023841858, + "ty": -0.5199999809265137, + "tz": -541.489990234375, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 202, + "symname": "MCH/HC3/DE202", + "transform": { + "tx": -0.1850000023841858, + "ty": 0.5199999809265137, + "tz": -548.989990234375, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 203, + "symname": "MCH/HC2/DE203", + "transform": { + "tx": 0.1850000023841858, + "ty": 0.5199999809265137, + "tz": -541.489990234375, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 300, + "symname": "MCH/HC4/DE300", + "transform": { + "tx": 0, + "ty": 0, + "tz": -680.3, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 301, + "symname": "MCH/HC5/DE301", + "transform": { + "tx": 0, + "ty": 0, + "tz": -672.5, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 302, + "symname": "MCH/HC5/DE302", + "transform": { + "tx": 0, + "ty": 0, + "tz": -680.3, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 303, + "symname": "MCH/HC4/DE303", + "transform": { + "tx": 0, + "ty": 0, + "tz": -672.5, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 400, + "symname": "MCH/HC6/DE400", + "transform": { + "tx": 0, + "ty": 0, + "tz": -699.3, + "yaw": -0, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 401, + "symname": "MCH/HC7/DE401", + "transform": { + "tx": 0, + "ty": 0, + "tz": -691.5, + "yaw": -180, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 402, + "symname": "MCH/HC7/DE402", + "transform": { + "tx": 0, + "ty": 0, + "tz": -699.3, + "yaw": -180, + "pitch": 0, + "roll": -0 + }, + "aligned": false + }, + { + "deid": 403, + "symname": "MCH/HC6/DE403", + "transform": { + "tx": 0, + "ty": 0, + "tz": -691.5, + "yaw": -0, + "pitch": 0, + "roll": -180 + }, + "aligned": false + }, + { + "deid": 500, + "symname": "MCH/HC8/DE500", + "transform": { + "tx": 81.25, + "ty": -0.05197011713870941, + "tz": -955.7503840774286, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 501, + "symname": "MCH/HC8/DE501", + "transform": { + "tx": 81.25, + "ty": 37.63354058543762, + "tz": -964.2734283156105, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 502, + "symname": "MCH/HC8/DE502", + "transform": { + "tx": 81.25, + "ty": 75.44078042139485, + "tz": -956.7966231164355, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 503, + "symname": "MCH/HC8/DE503", + "transform": { + "tx": 61.25, + "ty": 112.62633913364976, + "tz": -965.3127386192597, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 504, + "symname": "MCH/HC8/DE504", + "transform": { + "tx": 41.25, + "ty": 146.43396304703566, + "tz": -957.7805035372235, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 505, + "symname": "MCH/HC9/DE505", + "transform": { + "tx": -41.25, + "ty": 146.5379032813131, + "tz": -981.2797353823661, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 506, + "symname": "MCH/HC9/DE506", + "transform": { + "tx": -61.25, + "ty": 112.95199889937234, + "tz": -972.8135067741171, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 507, + "symname": "MCH/HC9/DE507", + "transform": { + "tx": -81.25, + "ty": 75.54472065567226, + "tz": -980.2958549615781, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 508, + "symname": "MCH/HC9/DE508", + "transform": { + "tx": -81.25, + "ty": 37.9592003511602, + "tz": -971.7741964704679, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 509, + "symname": "MCH/HC9/DE509", + "transform": { + "tx": -81.25, + "ty": 0.05197011713870941, + "tz": -979.2496159225714, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 510, + "symname": "MCH/HC9/DE510", + "transform": { + "tx": -81.25, + "ty": -37.63354058543762, + "tz": -970.7265716843895, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 511, + "symname": "MCH/HC9/DE511", + "transform": { + "tx": -81.25, + "ty": -75.44078042139485, + "tz": -978.2033768835645, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 512, + "symname": "MCH/HC9/DE512", + "transform": { + "tx": -61.25, + "ty": -112.62633913364976, + "tz": -969.6872613807403, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 513, + "symname": "MCH/HC9/DE513", + "transform": { + "tx": -41.25, + "ty": -146.43396304703566, + "tz": -977.2194964627765, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 514, + "symname": "MCH/HC8/DE514", + "transform": { + "tx": 41.25, + "ty": -146.5379032813131, + "tz": -953.7202646176339, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 515, + "symname": "MCH/HC8/DE515", + "transform": { + "tx": 61.25, + "ty": -112.95199889937234, + "tz": -962.1864932258829, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 516, + "symname": "MCH/HC8/DE516", + "transform": { + "tx": 81.25, + "ty": -75.54472065567226, + "tz": -954.7041450384219, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 517, + "symname": "MCH/HC8/DE517", + "transform": { + "tx": 81.25, + "ty": -37.9592003511602, + "tz": -963.2258035295321, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 600, + "symname": "MCH/HC10/DE600", + "transform": { + "tx": 81.25, + "ty": -0.05197011713870941, + "tz": -986.7503840774286, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 601, + "symname": "MCH/HC10/DE601", + "transform": { + "tx": 81.25, + "ty": 37.63354058543762, + "tz": -995.2734283156105, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 602, + "symname": "MCH/HC10/DE602", + "transform": { + "tx": 81.25, + "ty": 75.44078042139485, + "tz": -987.7966231164355, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 603, + "symname": "MCH/HC10/DE603", + "transform": { + "tx": 61.25, + "ty": 112.62633913364976, + "tz": -996.3127386192597, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 604, + "symname": "MCH/HC10/DE604", + "transform": { + "tx": 41.25, + "ty": 146.43396304703566, + "tz": -988.7805035372235, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 605, + "symname": "MCH/HC11/DE605", + "transform": { + "tx": -41.25, + "ty": 146.5379032813131, + "tz": -1012.2797353823661, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 606, + "symname": "MCH/HC11/DE606", + "transform": { + "tx": -61.25, + "ty": 112.95199889937234, + "tz": -1003.8135067741171, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 607, + "symname": "MCH/HC11/DE607", + "transform": { + "tx": -81.25, + "ty": 75.54472065567226, + "tz": -1011.2958549615781, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 608, + "symname": "MCH/HC11/DE608", + "transform": { + "tx": -81.25, + "ty": 37.9592003511602, + "tz": -1002.7741964704679, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 609, + "symname": "MCH/HC11/DE609", + "transform": { + "tx": -81.25, + "ty": 0.05197011713870941, + "tz": -1010.2496159225714, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 610, + "symname": "MCH/HC11/DE610", + "transform": { + "tx": -81.25, + "ty": -37.63354058543762, + "tz": -1001.7265716843895, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 611, + "symname": "MCH/HC11/DE611", + "transform": { + "tx": -81.25, + "ty": -75.44078042139485, + "tz": -1009.2033768835645, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 612, + "symname": "MCH/HC11/DE612", + "transform": { + "tx": -61.25, + "ty": -112.62633913364976, + "tz": -1000.6872613807403, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 613, + "symname": "MCH/HC11/DE613", + "transform": { + "tx": -41.25, + "ty": -146.43396304703566, + "tz": -1008.2194964627765, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 614, + "symname": "MCH/HC10/DE614", + "transform": { + "tx": 41.25, + "ty": -146.5379032813131, + "tz": -984.7202646176339, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 615, + "symname": "MCH/HC10/DE615", + "transform": { + "tx": 61.25, + "ty": -112.95199889937234, + "tz": -993.1864932258829, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 616, + "symname": "MCH/HC10/DE616", + "transform": { + "tx": 81.25, + "ty": -75.54472065567226, + "tz": -985.7041450384219, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 617, + "symname": "MCH/HC10/DE617", + "transform": { + "tx": 81.25, + "ty": -37.9592003511602, + "tz": -994.2258035295321, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 700, + "symname": "MCH/HC12/DE700", + "transform": { + "tx": 140, + "ty": -0.04850574945987875, + "tz": -1255.500408082268, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 701, + "symname": "MCH/HC12/DE701", + "transform": { + "tx": 121.25, + "ty": 38.03003781001593, + "tz": -1264.5289472990573, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 702, + "symname": "MCH/HC12/DE702", + "transform": { + "tx": 101.25, + "ty": 72.54452324520946, + "tz": -1256.5064604562003, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 703, + "symname": "MCH/HC12/DE703", + "transform": { + "tx": 101.25, + "ty": 109.02322043565675, + "tz": -1265.5128277198453, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 704, + "symname": "MCH/HC12/DE704", + "transform": { + "tx": 81.25, + "ty": 138.43819556957186, + "tz": -1257.4196677763402, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 705, + "symname": "MCH/HC12/DE705", + "transform": { + "tx": 61.25, + "ty": 175.31685435227624, + "tz": -1266.4315780282711, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 706, + "symname": "MCH/HC12/DE706", + "transform": { + "tx": 41.25, + "ty": 204.43185829199854, + "tz": -1258.3342608435514, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 707, + "symname": "MCH/HC13/DE707", + "transform": { + "tx": -41.25, + "ty": 204.31406979091827, + "tz": -1291.3334446790154, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 708, + "symname": "MCH/HC13/DE708", + "transform": { + "tx": -61.25, + "ty": 175.4346428533565, + "tz": -1282.4323941928071, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 709, + "symname": "MCH/HC13/DE709", + "transform": { + "tx": -81.25, + "ty": 138.3204070684916, + "tz": -1290.4188516118043, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 710, + "symname": "MCH/HC13/DE710", + "transform": { + "tx": -101.25, + "ty": 109.141008936737, + "tz": -1281.5136438843813, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 711, + "symname": "MCH/HC13/DE711", + "transform": { + "tx": -101.25, + "ty": 72.42673474412922, + "tz": -1289.5056442916643, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 712, + "symname": "MCH/HC13/DE712", + "transform": { + "tx": -121.25, + "ty": 38.147826311096175, + "tz": -1280.5297634635933, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 713, + "symname": "MCH/HC13/DE713", + "transform": { + "tx": -140, + "ty": -0.16629425054012126, + "tz": -1288.499591917732, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 714, + "symname": "MCH/HC13/DE714", + "transform": { + "tx": -121.25, + "ty": -38.24483781001593, + "tz": -1279.4710527009427, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 715, + "symname": "MCH/HC13/DE715", + "transform": { + "tx": -101.25, + "ty": -72.75932324520946, + "tz": -1287.4935395437997, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 716, + "symname": "MCH/HC13/DE716", + "transform": { + "tx": -101.25, + "ty": -109.23802043565675, + "tz": -1278.4871722801547, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 717, + "symname": "MCH/HC13/DE717", + "transform": { + "tx": -81.25, + "ty": -138.65299556957189, + "tz": -1286.5803322236598, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 718, + "symname": "MCH/HC13/DE718", + "transform": { + "tx": -61.25, + "ty": -175.53165435227626, + "tz": -1277.5684219717289, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 719, + "symname": "MCH/HC13/DE719", + "transform": { + "tx": -41.25, + "ty": -204.64665829199856, + "tz": -1285.6657391564486, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 720, + "symname": "MCH/HC12/DE720", + "transform": { + "tx": 41.25, + "ty": -204.5288697909183, + "tz": -1252.6665553209846, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 721, + "symname": "MCH/HC12/DE721", + "transform": { + "tx": 61.25, + "ty": -175.64944285335653, + "tz": -1261.5676058071929, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 722, + "symname": "MCH/HC12/DE722", + "transform": { + "tx": 81.25, + "ty": -138.53520706849162, + "tz": -1253.5811483881957, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 723, + "symname": "MCH/HC12/DE723", + "transform": { + "tx": 101.25, + "ty": -109.35580893673699, + "tz": -1262.4863561156187, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 724, + "symname": "MCH/HC12/DE724", + "transform": { + "tx": 101.25, + "ty": -72.64153474412922, + "tz": -1254.4943557083357, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 725, + "symname": "MCH/HC12/DE725", + "transform": { + "tx": 121.25, + "ty": -38.36262631109617, + "tz": -1263.4702365364067, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 800, + "symname": "MCH/HC14/DE800", + "transform": { + "tx": 140, + "ty": -0.04850574945987875, + "tz": -1295.500408082268, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 801, + "symname": "MCH/HC14/DE801", + "transform": { + "tx": 121.25, + "ty": 38.03003781001593, + "tz": -1304.5289472990573, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 802, + "symname": "MCH/HC14/DE802", + "transform": { + "tx": 101.25, + "ty": 75.99419197842722, + "tz": -1296.5542687301684, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 803, + "symname": "MCH/HC14/DE803", + "transform": { + "tx": 101.25, + "ty": 113.42279795048519, + "tz": -1305.5738005909927, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 804, + "symname": "MCH/HC14/DE804", + "transform": { + "tx": 81.25, + "ty": 142.9377634824646, + "tz": -1297.4820263945592, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 805, + "symname": "MCH/HC14/DE805", + "transform": { + "tx": 61.25, + "ty": 179.81642226516897, + "tz": -1306.49393664649, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 806, + "symname": "MCH/HC14/DE806", + "transform": { + "tx": 41.25, + "ty": 208.53146461263412, + "tz": -1298.3910764734842, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 807, + "symname": "MCH/HC15/DE807", + "transform": { + "tx": -41.25, + "ty": 208.41367611155385, + "tz": -1322.3902603089484, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 808, + "symname": "MCH/HC15/DE808", + "transform": { + "tx": -61.25, + "ty": 179.93421076624924, + "tz": -1313.494752811026, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 809, + "symname": "MCH/HC15/DE809", + "transform": { + "tx": -81.25, + "ty": 142.81997498138432, + "tz": -1321.4812102300232, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 810, + "symname": "MCH/HC15/DE810", + "transform": { + "tx": -101.25, + "ty": 113.54058645156543, + "tz": -1312.5746167555287, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 811, + "symname": "MCH/HC15/DE811", + "transform": { + "tx": -101.25, + "ty": 75.87640347734698, + "tz": -1320.5534525656324, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 812, + "symname": "MCH/HC15/DE812", + "transform": { + "tx": -121.25, + "ty": 38.147826311096175, + "tz": -1311.5297634635933, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 813, + "symname": "MCH/HC15/DE813", + "transform": { + "tx": -140, + "ty": -0.16629425054012126, + "tz": -1319.499591917732, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 814, + "symname": "MCH/HC15/DE814", + "transform": { + "tx": -121.25, + "ty": -38.24483781001593, + "tz": -1310.4710527009427, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 815, + "symname": "MCH/HC15/DE815", + "transform": { + "tx": -101.25, + "ty": -76.20899197842722, + "tz": -1318.4457312698316, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 816, + "symname": "MCH/HC15/DE816", + "transform": { + "tx": -101.25, + "ty": -113.63759795048519, + "tz": -1309.4261994090073, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 817, + "symname": "MCH/HC15/DE817", + "transform": { + "tx": -81.25, + "ty": -143.15256348246461, + "tz": -1317.5179736054408, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 818, + "symname": "MCH/HC15/DE818", + "transform": { + "tx": -61.25, + "ty": -180.031222265169, + "tz": -1308.50606335351, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 819, + "symname": "MCH/HC15/DE819", + "transform": { + "tx": -41.25, + "ty": -208.74626461263415, + "tz": -1316.6089235265158, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 820, + "symname": "MCH/HC14/DE820", + "transform": { + "tx": 41.25, + "ty": -208.62847611155388, + "tz": -1292.6097396910516, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 821, + "symname": "MCH/HC14/DE821", + "transform": { + "tx": 61.25, + "ty": -180.14901076624926, + "tz": -1301.505247188974, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 822, + "symname": "MCH/HC14/DE822", + "transform": { + "tx": 81.25, + "ty": -143.03477498138434, + "tz": -1293.5187897699768, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 823, + "symname": "MCH/HC14/DE823", + "transform": { + "tx": 101.25, + "ty": -113.75538645156543, + "tz": -1302.4253832444713, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 824, + "symname": "MCH/HC14/DE824", + "transform": { + "tx": 101.25, + "ty": -76.09120347734698, + "tz": -1294.4465474343676, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 825, + "symname": "MCH/HC14/DE825", + "transform": { + "tx": 121.25, + "ty": -38.36262631109617, + "tz": -1303.4702365364067, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 900, + "symname": "MCH/HC16/DE900", + "transform": { + "tx": 140, + "ty": -0.04850574945987875, + "tz": -1394.600408082268, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 901, + "symname": "MCH/HC16/DE901", + "transform": { + "tx": 121.25, + "ty": 38.03003781001593, + "tz": -1403.6289472990572, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 902, + "symname": "MCH/HC16/DE902", + "transform": { + "tx": 121.25, + "ty": 76.04418717745936, + "tz": -1395.654961603704, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 903, + "symname": "MCH/HC16/DE903", + "transform": { + "tx": 121.25, + "ty": 113.52278834854948, + "tz": -1404.6751863380641, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 904, + "symname": "MCH/HC16/DE904", + "transform": { + "tx": 101.25, + "ty": 150.93699532760724, + "tz": -1396.6928861602817, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 905, + "symname": "MCH/HC16/DE905", + "transform": { + "tx": 81.25, + "ty": 187.86564930934375, + "tz": -1405.7054892857484, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 906, + "symname": "MCH/HC16/DE906", + "transform": { + "tx": 61.25, + "ty": 224.72990909904797, + "tz": -1397.7155674990724, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 907, + "symname": "MCH/HC17/DE907", + "transform": { + "tx": -61.25, + "ty": 224.6121205979677, + "tz": -1421.7147513345365, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 908, + "symname": "MCH/HC17/DE908", + "transform": { + "tx": -81.25, + "ty": 187.98343781042402, + "tz": -1412.7063054502844, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 909, + "symname": "MCH/HC17/DE909", + "transform": { + "tx": -101.25, + "ty": 150.81920682652697, + "tz": -1420.6920699957457, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 910, + "symname": "MCH/HC17/DE910", + "transform": { + "tx": -121.25, + "ty": 113.64057684962972, + "tz": -1411.6760025026, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 911, + "symname": "MCH/HC17/DE911", + "transform": { + "tx": -121.25, + "ty": 75.92639867637912, + "tz": -1419.654145439168, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 912, + "symname": "MCH/HC17/DE912", + "transform": { + "tx": -121.25, + "ty": 38.147826311096175, + "tz": -1410.6297634635932, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 913, + "symname": "MCH/HC17/DE913", + "transform": { + "tx": -140, + "ty": -0.16629425054012126, + "tz": -1418.599591917732, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 914, + "symname": "MCH/HC17/DE914", + "transform": { + "tx": -121.25, + "ty": -38.24483781001593, + "tz": -1409.5710527009426, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 915, + "symname": "MCH/HC17/DE915", + "transform": { + "tx": -121.25, + "ty": -76.25898717745936, + "tz": -1417.545038396296, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 916, + "symname": "MCH/HC17/DE916", + "transform": { + "tx": -121.25, + "ty": -113.73758834854948, + "tz": -1408.5248136619357, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 917, + "symname": "MCH/HC17/DE917", + "transform": { + "tx": -101.25, + "ty": -151.15179532760726, + "tz": -1416.5071138397182, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 918, + "symname": "MCH/HC17/DE918", + "transform": { + "tx": -81.25, + "ty": -188.08044930934378, + "tz": -1407.4945107142514, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 919, + "symname": "MCH/HC17/DE919", + "transform": { + "tx": -61.25, + "ty": -224.944709099048, + "tz": -1415.4844325009274, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 920, + "symname": "MCH/HC16/DE920", + "transform": { + "tx": 61.25, + "ty": -224.82692059796773, + "tz": -1391.4852486654634, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 921, + "symname": "MCH/HC16/DE921", + "transform": { + "tx": 81.25, + "ty": -188.19823781042405, + "tz": -1400.4936945497154, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 922, + "symname": "MCH/HC16/DE922", + "transform": { + "tx": 101.25, + "ty": -151.034006826527, + "tz": -1392.5079300042541, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 923, + "symname": "MCH/HC16/DE923", + "transform": { + "tx": 121.25, + "ty": -113.85537684962972, + "tz": -1401.5239974973997, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 924, + "symname": "MCH/HC16/DE924", + "transform": { + "tx": 121.25, + "ty": -76.14119867637912, + "tz": -1393.545854560832, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 925, + "symname": "MCH/HC16/DE925", + "transform": { + "tx": 121.25, + "ty": -38.36262631109617, + "tz": -1402.5702365364066, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1000, + "symname": "MCH/HC18/DE1000", + "transform": { + "tx": 140, + "ty": -0.04850574945987875, + "tz": -1425.600408082268, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1001, + "symname": "MCH/HC18/DE1001", + "transform": { + "tx": 121.25, + "ty": 38.03003781001593, + "tz": -1434.6289472990572, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1002, + "symname": "MCH/HC18/DE1002", + "transform": { + "tx": 121.25, + "ty": 76.04418717745936, + "tz": -1426.654961603704, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1003, + "symname": "MCH/HC18/DE1003", + "transform": { + "tx": 121.25, + "ty": 113.52278834854948, + "tz": -1435.6751863380641, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1004, + "symname": "MCH/HC18/DE1004", + "transform": { + "tx": 101.25, + "ty": 150.93699532760724, + "tz": -1427.6928861602817, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1005, + "symname": "MCH/HC18/DE1005", + "transform": { + "tx": 81.25, + "ty": 187.86564930934375, + "tz": -1436.7054892857484, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1006, + "symname": "MCH/HC18/DE1006", + "transform": { + "tx": 61.25, + "ty": 224.72990909904797, + "tz": -1428.7155674990724, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1007, + "symname": "MCH/HC19/DE1007", + "transform": { + "tx": -61.25, + "ty": 224.6121205979677, + "tz": -1452.7147513345365, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1008, + "symname": "MCH/HC19/DE1008", + "transform": { + "tx": -81.25, + "ty": 187.98343781042402, + "tz": -1443.7063054502844, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1009, + "symname": "MCH/HC19/DE1009", + "transform": { + "tx": -101.25, + "ty": 150.81920682652697, + "tz": -1451.6920699957457, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1010, + "symname": "MCH/HC19/DE1010", + "transform": { + "tx": -121.25, + "ty": 113.64057684962972, + "tz": -1442.6760025026, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1011, + "symname": "MCH/HC19/DE1011", + "transform": { + "tx": -121.25, + "ty": 75.92639867637912, + "tz": -1450.654145439168, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1012, + "symname": "MCH/HC19/DE1012", + "transform": { + "tx": -121.25, + "ty": 38.147826311096175, + "tz": -1441.6297634635932, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1013, + "symname": "MCH/HC19/DE1013", + "transform": { + "tx": -140, + "ty": -0.16629425054012126, + "tz": -1449.599591917732, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1014, + "symname": "MCH/HC19/DE1014", + "transform": { + "tx": -121.25, + "ty": -38.24483781001593, + "tz": -1440.5710527009426, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1015, + "symname": "MCH/HC19/DE1015", + "transform": { + "tx": -121.25, + "ty": -76.25898717745936, + "tz": -1448.545038396296, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1016, + "symname": "MCH/HC19/DE1016", + "transform": { + "tx": -121.25, + "ty": -113.73758834854948, + "tz": -1439.5248136619357, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1017, + "symname": "MCH/HC19/DE1017", + "transform": { + "tx": -101.25, + "ty": -151.15179532760726, + "tz": -1447.5071138397182, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1018, + "symname": "MCH/HC19/DE1018", + "transform": { + "tx": -81.25, + "ty": -188.08044930934378, + "tz": -1438.4945107142514, + "yaw": -180, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1019, + "symname": "MCH/HC19/DE1019", + "transform": { + "tx": -61.25, + "ty": -224.944709099048, + "tz": -1446.4844325009274, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1020, + "symname": "MCH/HC18/DE1020", + "transform": { + "tx": 61.25, + "ty": -224.82692059796773, + "tz": -1422.4852486654634, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1021, + "symname": "MCH/HC18/DE1021", + "transform": { + "tx": 81.25, + "ty": -188.19823781042405, + "tz": -1431.4936945497154, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1022, + "symname": "MCH/HC18/DE1022", + "transform": { + "tx": 101.25, + "ty": -151.034006826527, + "tz": -1423.5079300042541, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1023, + "symname": "MCH/HC18/DE1023", + "transform": { + "tx": 121.25, + "ty": -113.85537684962972, + "tz": -1432.5239974973997, + "yaw": -0, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + }, + { + "deid": 1024, + "symname": "MCH/HC18/DE1024", + "transform": { + "tx": 121.25, + "ty": -76.14119867637912, + "tz": -1424.545854560832, + "yaw": -0, + "pitch": 0, + "roll": 179.20600000000002 + }, + "aligned": false + }, + { + "deid": 1025, + "symname": "MCH/HC18/DE1025", + "transform": { + "tx": 121.25, + "ty": -38.36262631109617, + "tz": -1433.5702365364066, + "yaw": -180, + "pitch": 0, + "roll": -0.7940000000000002 + }, + "aligned": false + } + ] +} diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/GeometryTest.h b/Detectors/MUON/MCH/Geometry/Test/include/MCHGeometryTest/Helpers.h similarity index 78% rename from Detectors/MUON/MCH/Simulation/include/MCHSimulation/GeometryTest.h rename to Detectors/MUON/MCH/Geometry/Test/include/MCHGeometryTest/Helpers.h index 52815f9d5e14b..9ab8c9bd52cd2 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/GeometryTest.h +++ b/Detectors/MUON/MCH/Geometry/Test/include/MCHGeometryTest/Helpers.h @@ -8,33 +8,20 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_MCH_SIMULATION_GEOMETRYTEST_H -#define O2_MCH_SIMULATION_GEOMETRYTEST_H +#ifndef O2_MCH_GEOMETRY_TEST_HELPERS_H +#define O2_MCH_GEOMETRY_TEST_HELPERS_H #include <iostream> class TH2; -namespace o2 -{ -namespace mch -{ -namespace test +namespace o2::mch::test { /// creates MCH geometry from scratch (i.e. from a null TGeoManager) /// usefull for tests or drawing for instance. void createStandaloneGeometry(); -/// creates MCH geometry with the beam shielding and the dipole -/// from scratch (i.e. from a null TGeoManager). -/// usefull for tests. -void createRegularGeometry(); - -/// creates MCH regular geometry and adds alignable volumes -/// useull for tests. -void addAlignableVolumes(); - /// tree like textual dump of the geometry nodes void showGeometryAsTextTree(const char* fromPath = "", int maxdepth = 2, std::ostream& out = std::cout); @@ -58,8 +45,6 @@ class Dummy { // to force Root produce a dictionary for namespace test (seems it is doing it fully if there are only functions in the namespace) }; -} // namespace test -} // namespace mch -} // namespace o2 +} // namespace o2::mch::test #endif diff --git a/Detectors/MUON/MCH/Simulation/macros/rootlogon.C b/Detectors/MUON/MCH/Geometry/Test/rootlogon.C similarity index 100% rename from Detectors/MUON/MCH/Simulation/macros/rootlogon.C rename to Detectors/MUON/MCH/Geometry/Test/rootlogon.C diff --git a/Detectors/MUON/MCH/Simulation/test/testGeometry.cxx b/Detectors/MUON/MCH/Geometry/Test/testGeometryCreator.cxx similarity index 70% rename from Detectors/MUON/MCH/Simulation/test/testGeometry.cxx rename to Detectors/MUON/MCH/Geometry/Test/testGeometryCreator.cxx index bb8a8a583f2d4..af0fe9ebdb581 100644 --- a/Detectors/MUON/MCH/Simulation/test/testGeometry.cxx +++ b/Detectors/MUON/MCH/Geometry/Test/testGeometryCreator.cxx @@ -17,13 +17,11 @@ #include <boost/test/unit_test.hpp> -#include "MCHMappingInterface/CathodeSegmentation.h" -#include "MCHSimulation/Geometry.h" -#include "MCHSimulation/GeometryTest.h" +#include "MCHGeometryCreator/Geometry.h" +#include "MCHGeometryTest/Helpers.h" #include "TGeoManager.h" #include "boost/format.hpp" #include <boost/test/data/test_case.hpp> -#include <fstream> #include <iomanip> #include <iostream> #include <fmt/format.h> @@ -34,17 +32,10 @@ struct GEOMETRY { GEOMETRY() { if (!gGeoManager) { - std::string param = boost::unit_test::framework::master_test_suite().argv[1]; - if (param == "standalone") { - o2::mch::test::createStandaloneGeometry(); - } else if (param == "regular") { - o2::mch::test::createRegularGeometry(); - } else { - throw std::invalid_argument(fmt::format("only possible argument value are 'regular' or 'standalone', not {}", param.c_str())); - } - o2::mch::test::addAlignableVolumes(); + o2::mch::test::createStandaloneGeometry(); + o2::mch::geo::addAlignableVolumes(*gGeoManager); } - } + }; }; const std::array<std::string, 8> quadrantChamberNames{"SC01I", "SC01O", "SC02I", "SC02O", "SC03I", "SC03O", @@ -75,9 +66,7 @@ const std::vector<std::vector<std::string>> deSymNames{ {"DE1000", "DE1001", "DE1002", "DE1003", "DE1004", "DE1005", "DE1006", "DE1020", "DE1021", "DE1022", "DE1023", "DE1024", "DE1025"}, {"DE1007", "DE1008", "DE1009", "DE1010", "DE1011", "DE1012", "DE1013", "DE1014", "DE1015", "DE1016", "DE1017", "DE1018", "DE1019"}}; -BOOST_AUTO_TEST_SUITE(o2_mch_simulation) - -BOOST_FIXTURE_TEST_SUITE(geometrytransformer, GEOMETRY) +BOOST_FIXTURE_TEST_SUITE(geometrycreator, GEOMETRY) BOOST_AUTO_TEST_CASE(CanGetAllChambers) { @@ -162,135 +151,8 @@ BOOST_AUTO_TEST_CASE(GetDetElemVolumePath, *boost::unit_test::disabled() * boost BOOST_CHECK_EQUAL(codeLines.size(), 156); } -BOOST_AUTO_TEST_CASE(GetTransformationMustNotThrowForValidDetElemId) -{ - BOOST_REQUIRE(gGeoManager != nullptr); - - o2::mch::mapping::forEachDetectionElement([](int detElemId) { - BOOST_CHECK_NO_THROW((o2::mch::getTransformation(detElemId, *gGeoManager))); - }); -} - -struct CoarseLocation { - bool isRight; - bool isTop; -}; - -constexpr CoarseLocation topRight{true, true}; -constexpr CoarseLocation topLeft{false, true}; -constexpr CoarseLocation bottomRight{true, false}; -constexpr CoarseLocation bottomLeft{false, false}; - -std::string asString(const CoarseLocation& q) -{ - std::string s = q.isTop ? "TOP" : "BOTTOM"; - s += q.isRight ? "RIGHT" : "LEFT"; - return s; -} - -bool operator==(const CoarseLocation& a, const CoarseLocation& b) -{ - return a.isRight == b.isRight && a.isTop == b.isTop; -} - -CoarseLocation getDetElemCoarseLocation(int detElemId) -{ - auto t = o2::mch::getTransformation(detElemId, *gGeoManager); - o2::math_utils::Point3D<double> localTestPos{0.0, 0.0, 0.0}; // slat center - - if (detElemId < 500) { - // in the rough ballpark of the center - // of the quadrants - localTestPos.SetXYZ(60, 60, 0); - } - - // for slats around the middle (y closest to 0) we have to be a bit - // more precise, so take a given pad reference, chosen to be - // the most top right or most top left pad - - switch (detElemId) { - case 500: - case 509: - localTestPos.SetXYZ(-72.50, 19.75, 0.0); // ds 107 - break; - case 600: - case 609: - localTestPos.SetXYZ(-77.50, 19.75, 0.0); // ds 108 - break; - case 700: - case 713: - case 800: - case 813: - case 900: - case 913: - case 1000: - case 1013: - localTestPos.SetXYZ(95.0, -19.75, 0); // ds 104 - break; - } - o2::math_utils::Point3D<double> master; - - t.LocalToMaster(localTestPos, master); - bool right = master.x() > 10.; - bool top = master.y() > -10.; - - return CoarseLocation{right, top}; -} - -void setExpectation(int firstDeId, int lastDeId, CoarseLocation q, std::map<int, CoarseLocation>& expected) -{ - for (int deid = firstDeId; deid <= lastDeId; deid++) { - expected.emplace(deid, q); - } -} - -BOOST_AUTO_TEST_CASE(DetectionElementMustBeInTheRightCoarseLocation) -{ - std::map<int, CoarseLocation> expected; - - for (int i = 0; i < 4; i++) { - expected[100 + i * 100] = topRight; - expected[101 + i * 100] = topLeft; - expected[102 + i * 100] = bottomLeft; - expected[103 + i * 100] = bottomRight; - } - - // note that by convention we consider slats in the middle to be "top" - for (int i = 0; i < 2; i++) { - setExpectation(500 + i * 100, 504 + i * 100, topRight, expected); - setExpectation(505 + i * 100, 509 + i * 100, topLeft, expected); - setExpectation(510 + i * 100, 513 + i * 100, bottomLeft, expected); - setExpectation(514 + i * 100, 517 + i * 100, bottomRight, expected); - } - - for (int i = 0; i < 4; i++) { - setExpectation(700 + i * 100, 706 + i * 100, topRight, expected); - setExpectation(707 + i * 100, 713 + i * 100, topLeft, expected); - setExpectation(714 + i * 100, 719 + i * 100, bottomLeft, expected); - setExpectation(720 + i * 100, 725 + i * 100, bottomRight, expected); - } - - o2::mch::mapping::forEachDetectionElement([&expected](int detElemId) { - if (expected.find(detElemId) == expected.end()) { - std::cout << "got no expectation for DE=" << detElemId << "\n"; - return; - } - BOOST_TEST_INFO(fmt::format("DeId {}", detElemId)); - BOOST_CHECK_EQUAL(asString(getDetElemCoarseLocation(detElemId)), asString(expected[detElemId])); - }); -} - BOOST_AUTO_TEST_CASE(TextualTreeDump) { - std::string param = boost::unit_test::framework::master_test_suite().argv[1]; - if (param != "standalone") { - // no point in checking the full hierarchy and have this test - // depending on all the details of the geometry of all detectors, - // so this test only makes sense for standalone geometry - BOOST_CHECK(true); - return; - } - const std::string expected = R"(cave_1 ├──SC01I_0 @@ -508,4 +370,3 @@ BOOST_AUTO_TEST_CASE(GetAlignableDetectionElements) } } BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() diff --git a/Detectors/MUON/MCH/Geometry/Test/testGeometryTransformer.cxx b/Detectors/MUON/MCH/Geometry/Test/testGeometryTransformer.cxx new file mode 100644 index 0000000000000..1f915f6ac282c --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Test/testGeometryTransformer.cxx @@ -0,0 +1,227 @@ +// 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 Laurent Aphecetche + +#define BOOST_TEST_MODULE Test MCHSimulation GeometryTransformer +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> + +#include "MCHGeometryCreator/Geometry.h" +#include "MCHGeometryTest/Helpers.h" +#include "MCHGeometryTransformer/Transformations.h" +#include "TGeoManager.h" +#include "boost/format.hpp" +#include <boost/test/data/test_case.hpp> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <fmt/format.h> +#include <random> + +namespace bdata = boost::unit_test::data; + +BOOST_TEST_DONT_PRINT_LOG_VALUE(o2::mch::geo::TransformationCreator) + +constexpr int ntrans{2}; + +o2::mch::geo::TransformationCreator transformation(int i) +{ + static std::vector<o2::mch::geo::TransformationCreator> vtrans; + + BOOST_REQUIRE(boost::unit_test::framework::master_test_suite().argc == 2); + + if (vtrans.empty()) { + if (!gGeoManager) { + o2::mch::test::createStandaloneGeometry(); + o2::mch::geo::addAlignableVolumes(*gGeoManager); + } + BOOST_TEST_REQUIRE(boost::unit_test::framework::master_test_suite().argc == 2); + std::string jsonInput = boost::unit_test::framework::master_test_suite().argv[1]; + std::ifstream in(jsonInput); + vtrans = { + o2::mch::geo::transformationFromJSON(in), + o2::mch::geo::transformationFromTGeoManager(*gGeoManager)}; + } + return vtrans[i]; +} + +constexpr double rad2deg = 180.0 / 3.14159265358979323846; +constexpr double deg2rad = 3.14159265358979323846 / 180.0; + +void dumpMat(gsl::span<double> m) +{ + std::cout << fmt::format( + "{:7.3f} {:7.3f} {:7.3f}\n" + "{:7.3f} {:7.3f} {:7.3f}\n" + "{:7.3f} {:7.3f} {:7.3f}\n", + m[0], m[1], m[2], + m[3], m[4], m[5], + m[6], m[7], m[8]); +} + +BOOST_DATA_TEST_CASE(GetTransformationMustNotThrowForValidDetElemId, bdata::xrange(ntrans), tindex) +{ + for (auto detElemId : o2::mch::geo::allDeIds) { + BOOST_REQUIRE_NO_THROW((transformation(tindex))(detElemId)); + } +} + +BOOST_DATA_TEST_CASE(GetTransformationMustThrowForInvalidDetElemId, bdata::xrange(ntrans), tindex) +{ + const auto someInvalidDetElemIds = {99, 105, 1026}; + + for (auto detElemId : someInvalidDetElemIds) { + BOOST_CHECK_THROW((transformation(tindex)(detElemId)), std::runtime_error); + } +} + +struct CoarseLocation { + bool isRight; + bool isTop; +}; + +constexpr CoarseLocation topRight{true, true}; +constexpr CoarseLocation topLeft{false, true}; +constexpr CoarseLocation bottomRight{true, false}; +constexpr CoarseLocation bottomLeft{false, false}; + +std::string asString(const CoarseLocation& q) +{ + std::string s = q.isTop ? "TOP" : "BOTTOM"; + s += q.isRight ? "RIGHT" : "LEFT"; + return s; +} + +bool operator==(const CoarseLocation& a, const CoarseLocation& b) +{ + return a.isRight == b.isRight && a.isTop == b.isTop; +} + +CoarseLocation getDetElemCoarseLocation(int detElemId, o2::mch::geo::TransformationCreator transformation) +{ + auto t = transformation(detElemId); + + o2::math_utils::Point3D<double> localTestPos{0.0, 0.0, 0.0}; // slat center + + if (detElemId < 500) { + // in the rough ballpark of the center + // of the quadrants + localTestPos.SetXYZ(60, 60, 0); + } + + // for slats around the middle (y closest to 0) we have to be a bit + // more precise, so take a given pad reference, chosen to be + // the most top right or most top left pad + + switch (detElemId) { + case 500: + case 509: + localTestPos.SetXYZ(-72.50, 19.75, 0.0); // ds 107 + break; + case 600: + case 609: + localTestPos.SetXYZ(-77.50, 19.75, 0.0); // ds 108 + break; + case 700: + case 713: + case 800: + case 813: + case 900: + case 913: + case 1000: + case 1013: + localTestPos.SetXYZ(95.0, -19.75, 0); // ds 104 + break; + } + o2::math_utils::Point3D<double> master; + + t.LocalToMaster(localTestPos, master); + bool right = master.x() > 10.; + bool top = master.y() > -10.; + + return CoarseLocation{right, top}; +} + +void setExpectation(int firstDeId, int lastDeId, CoarseLocation q, std::map<int, CoarseLocation>& expected) +{ + for (int deid = firstDeId; deid <= lastDeId; deid++) { + expected.emplace(deid, q); + } +} + +BOOST_DATA_TEST_CASE(DetectionElementMustBeInTheRightCoarseLocation, bdata::xrange(ntrans), tindex) +{ + std::map<int, CoarseLocation> expected; + + for (int i = 0; i < 4; i++) { + expected[100 + i * 100] = topRight; + expected[101 + i * 100] = topLeft; + expected[102 + i * 100] = bottomLeft; + expected[103 + i * 100] = bottomRight; + } + + // note that by convention we consider slats in the middle to be "top" + for (int i = 0; i < 2; i++) { + setExpectation(500 + i * 100, 504 + i * 100, topRight, expected); + setExpectation(505 + i * 100, 509 + i * 100, topLeft, expected); + setExpectation(510 + i * 100, 513 + i * 100, bottomLeft, expected); + setExpectation(514 + i * 100, 517 + i * 100, bottomRight, expected); + } + + for (int i = 0; i < 4; i++) { + setExpectation(700 + i * 100, 706 + i * 100, topRight, expected); + setExpectation(707 + i * 100, 713 + i * 100, topLeft, expected); + setExpectation(714 + i * 100, 719 + i * 100, bottomLeft, expected); + setExpectation(720 + i * 100, 725 + i * 100, bottomRight, expected); + } + + for (auto detElemId : o2::mch::geo::allDeIds) { + if (expected.find(detElemId) == expected.end()) { + std::cout << "got no expectation for DE=" << detElemId << "\n"; + return; + } + BOOST_TEST_INFO_SCOPE(fmt::format("DeId {}", detElemId)); + BOOST_CHECK_EQUAL(asString(getDetElemCoarseLocation(detElemId, transformation(tindex))), asString(expected[detElemId])); + }; +} + +BOOST_AUTO_TEST_CASE(Angle2Matrix2Angle) +{ + std::random_device rd; + std::mt19937 mt(rd()); + std::vector<std::tuple<double, double, double>> testAngles; + int n{100}; + + testAngles.resize(n); + constexpr double pi = 3.14159265358979323846; + std::uniform_real_distribution<double> dist{-pi / 2.0, pi / 2.0}; + std::uniform_real_distribution<double> dist2{-pi, pi}; + std::generate(testAngles.begin(), testAngles.end(), [&dist, &dist2, &mt] { + return std::tuple<double, double, double>{dist2(mt), dist(mt), dist2(mt)}; + }); + + testAngles.emplace_back(-pi, pi / 2.0, 0); + for (auto a : testAngles) { + auto [yaw, pitch, roll] = a; + auto m = o2::mch::geo::angles2matrix(yaw, pitch, roll); + auto [y, p, r] = o2::mch::geo::matrix2angles(m); + BOOST_TEST_INFO_SCOPE(fmt::format( + " input yaw {:7.2f} pitch {:7.2f} roll {:7.2f}\n" + "output yaw {:7.2f} pitch {:7.2f} roll {:7.2f}\n", + yaw, pitch, roll, + y, p, r)); + BOOST_CHECK_CLOSE(y, yaw, 1E-6); + BOOST_CHECK_CLOSE(p, pitch, 1E-6); + BOOST_CHECK_CLOSE(r, roll, 1E-6); + } +} diff --git a/Detectors/MUON/MCH/Geometry/Transformer/CMakeLists.txt b/Detectors/MUON/MCH/Geometry/Transformer/CMakeLists.txt new file mode 100644 index 0000000000000..c2d5a03164308 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Transformer/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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_library( + MCHGeometryTransformer + SOURCES src/Transformations.cxx src/VolumePaths.cxx + PUBLIC_LINK_LIBRARIES ROOT::Geom O2::MathUtils ms_gsl::ms_gsl + RapidJSON::RapidJSON) + +o2_add_executable( + convert-geometry + SOURCES src/convert-geometry.cxx + PUBLIC_LINK_LIBRARIES ROOT::Geom ms_gsl::ms_gsl Boost::program_options + O2::MCHGeometryTransformer + COMPONENT_NAME mch) diff --git a/Detectors/MUON/MCH/Geometry/Transformer/README.md b/Detectors/MUON/MCH/Geometry/Transformer/README.md new file mode 100644 index 0000000000000..5e394b82e47b9 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Transformer/README.md @@ -0,0 +1,26 @@ +<!-- doxy +\page refDetectorsMUONMCHGeometryTransformer Transformations +/doxy --> + +# MCH Geometry Transformations + +Here you will find functions to perform transformations on MCH geometry : local +to global, global to local, and various (mis)alignement ones. + +# MCH Transformations in JSON format + +Also available is a CLI utility to extract MCH transformations (rotations and +translations) from a Root geometry file and export them in JSON format : + +```shell +o2-mch-convert-geometry --geom o2sim_geometry.root > geom.json +``` + +The JSON output can be manipulated (like any other json file) with e.g. [jq](https://stedolan.github.io/jq/) + +For instance, to sort the output per detection element id : + +```shell +cat output.json | jq '.alignables|=sort_by(.deid)' +``` + diff --git a/Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/Transformations.h b/Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/Transformations.h new file mode 100644 index 0000000000000..16e56d6bac296 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/Transformations.h @@ -0,0 +1,73 @@ +// 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. +/// get the local-to-global transformation for a given detection element + +#ifndef O2_MCH_GEOMETRY_TRANSFORMER_TRANSFORMATIONS_H +#define O2_MCH_GEOMETRY_TRANSFORMER_TRANSFORMATIONS_H + +#include "MathUtils/Cartesian.h" +#include <array> +#include <tuple> +#include <gsl/span> +#include <functional> + +class TGeoManager; + +namespace o2::mch::geo +{ + +/** A geometry transformation creator must be able to + * create a transformation for any valid MCH detection element id. + * + * That transformation is used to convert coordinates from local + * (x,y in detection element plane) to global (x,y,z in Alice Coordinate + * System) and vice-versa + * + * @param detElemId must be a valid detection element + * @param geo a reference to a GeoManager that must contain MCH volumes + * + * @throw if detElemId is not valid + */ +using TransformationCreator = std::function<o2::math_utils::Transform3D(int detElemId)>; + +/** Tranformation creator using TGeoManager. + * + * @param geo a reference to a GeoManager that must contain MCH volumes + */ +TransformationCreator transformationFromTGeoManager(const TGeoManager& geo); + +TransformationCreator transformationFromJSON(std::istream& in); + +/** The list of detection element identifiers for MCH + */ +extern std::array<int, 156> allDeIds; + +/** Convert the 3 Tait–Bryan angles (yaw,pitch,roll) into the 9 matrix + * elements of a rotation matrix. + * + * @param yaw rotation around z-axis, in radian + * @param pitch rotation around y'-axis (new y-axis resulting from yaw + * rotation), in radian + * @param roll rotation around x''-axis (new x-axis resulting from yaw + * and pitch rotations), in radian + */ +std::array<double, 9> angles2matrix(double yaw, double pitch, double roll); + +/** Convert the 9 matrix elements of a rotation matrix + * into 3 Tait-Bryan angles (yaw,pitch,roll). + * + * @param rot a 9-elements vector + * @returns a tuple of the 3 angles <yaw,pitch,roll>. The angles are + * expressed in radian + */ +std::tuple<double, double, double> matrix2angles(gsl::span<double> rot); +} // namespace o2::mch::geo + +#endif diff --git a/Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/VolumePaths.h b/Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/VolumePaths.h new file mode 100644 index 0000000000000..edf1630976ffe --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Transformer/include/MCHGeometryTransformer/VolumePaths.h @@ -0,0 +1,22 @@ +// 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. +/// get the local-to-global transformation for a given detection element + +#ifndef O2_MCH_GEOMETRY_TRANSFORMER_VOLUME_PATHS_H +#define O2_MCH_GEOMETRY_TRANSFORMER_VOLUME_PATHS_H + +#include <string> + +namespace o2::mch::geo +{ +std::string volumePathName(int deId); +} + +#endif diff --git a/Detectors/MUON/MCH/Geometry/Transformer/src/Transformations.cxx b/Detectors/MUON/MCH/Geometry/Transformer/src/Transformations.cxx new file mode 100644 index 0000000000000..448ea24a7580e --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Transformer/src/Transformations.cxx @@ -0,0 +1,153 @@ +// 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 "MCHGeometryTransformer/Transformations.h" +#include "MCHGeometryTransformer/VolumePaths.h" +#include <array> +#include <string> +#include <vector> +#include <TGeoManager.h> +#include <TGeoMatrix.h> +#include <rapidjson/document.h> +#include <rapidjson/istreamwrapper.h> +#include <fmt/format.h> +namespace o2::mch::geo +{ + +std::array<int, 156> allDeIds = { + 100, 101, 102, 103, + 200, 201, 202, 203, + 300, 301, 302, 303, + 400, 401, 402, 403, + 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, + 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, + 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, + 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, + 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, + 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025}; + +TransformationCreator transformationFromTGeoManager(const TGeoManager& geo) +{ + return [&geo](int detElemId) -> o2::math_utils::Transform3D { + if (std::find(begin(allDeIds), end(allDeIds), detElemId) == end(allDeIds)) { + throw std::runtime_error("Wrong detection element Id"); + } + + std::string volPathName = geo.GetTopVolume()->GetName(); + + int nCh = detElemId / 100; + + if (nCh <= 4 && geo.GetVolume("YOUT1")) { + volPathName += "/YOUT1_1/"; + } else if ((nCh == 5 || nCh == 6) && geo.GetVolume("DDIP")) { + volPathName += "/DDIP_1/"; + } else if (nCh >= 7 && geo.GetVolume("YOUT2")) { + volPathName += "/YOUT2_1/"; + } else { + volPathName += "/"; + } + + volPathName += volumePathName(detElemId); + + TGeoNavigator* navig = gGeoManager->GetCurrentNavigator(); + + if (!navig->cd(volPathName.c_str())) { + throw std::runtime_error("could not get to volPathName=" + volPathName); + } + + return o2::math_utils::Transform3D{*(navig->GetCurrentMatrix())}; + }; +} + +TransformationCreator transformationFromJSON(std::istream& in) +{ + rapidjson::IStreamWrapper isw(in); + + rapidjson::Document d; + d.ParseStream(isw); + + rapidjson::Value& alignables = d["alignables"]; + assert(alignables.IsArray()); + + std::map<int, std::tuple<double, double, double>> angles; + std::map<int, std::tuple<double, double, double>> translations; + + // loop over json document and extract Tait-Bryan angles (yaw,pitch,roll) + // as well as translation vector (tx,ty,tz) + // for each detection element + + constexpr double deg2rad = 3.14159265358979323846 / 180.0; + + for (auto& al : alignables.GetArray()) { + auto itr = al.FindMember("deid"); + if (itr != al.MemberEnd()) { + int deid = itr->value.GetInt(); + auto t = al["transform"].GetObject(); + angles[deid] = { + deg2rad * t["yaw"].GetDouble(), + deg2rad * t["pitch"].GetDouble(), + deg2rad * t["roll"].GetDouble()}; + translations[deid] = { + t["tx"].GetDouble(), + t["ty"].GetDouble(), + t["tz"].GetDouble()}; + } + } + + return [angles, translations](int detElemId) -> o2::math_utils::Transform3D { + if (std::find(begin(allDeIds), end(allDeIds), detElemId) == end(allDeIds)) { + throw std::runtime_error("Wrong detection element Id"); + } + auto [yaw, pitch, roll] = angles.at(detElemId); + auto [tx, ty, tz] = translations.at(detElemId); + double tr[3] = {tx, ty, tz}; + // get the angles, convert them to a matrix and build a Transform3D + // from it + auto rot = o2::mch::geo::angles2matrix(yaw, pitch, roll); + TGeoHMatrix m; + m.SetRotation(&rot[0]); + m.SetTranslation(tr); + return o2::math_utils::Transform3D(m); + }; +} // namespace o2::mch::geo + +std::array<double, 9> angles2matrix(double yaw, double pitch, double roll) +{ + std::array<double, 9> rot; + + double sinpsi = std::sin(roll); + double cospsi = std::cos(roll); + double sinthe = std::sin(pitch); + double costhe = std::cos(pitch); + double sinphi = std::sin(yaw); + double cosphi = std::cos(yaw); + rot[0] = costhe * cosphi; + rot[1] = -costhe * sinphi; + rot[2] = sinthe; + rot[3] = sinpsi * sinthe * cosphi + cospsi * sinphi; + rot[4] = -sinpsi * sinthe * sinphi + cospsi * cosphi; + rot[5] = -costhe * sinpsi; + rot[6] = -cospsi * sinthe * cosphi + sinpsi * sinphi; + rot[7] = cospsi * sinthe * sinphi + sinpsi * cosphi; + rot[8] = costhe * cospsi; + return rot; +} + +std::tuple<double, double, double> matrix2angles(gsl::span<double> rot) +{ + double roll = std::atan2(-rot[5], rot[8]); + double pitch = std::asin(rot[2]); + double yaw = std::atan2(-rot[1], rot[0]); + return std::make_tuple(yaw, + pitch, + roll); +} + +} // namespace o2::mch::geo diff --git a/Detectors/MUON/MCH/Simulation/src/Geometry.cxx b/Detectors/MUON/MCH/Geometry/Transformer/src/VolumePaths.cxx similarity index 67% rename from Detectors/MUON/MCH/Simulation/src/Geometry.cxx rename to Detectors/MUON/MCH/Geometry/Transformer/src/VolumePaths.cxx index a5f6a82541f78..da07e7db7127f 100644 --- a/Detectors/MUON/MCH/Simulation/src/Geometry.cxx +++ b/Detectors/MUON/MCH/Geometry/Transformer/src/VolumePaths.cxx @@ -8,52 +8,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "MCHSimulation/Geometry.h" +#include "MCHGeometryTransformer/VolumePaths.h" -#include "Station1Geometry.h" -#include "Station2Geometry.h" -#include "Station345Geometry.h" -#include "Materials.h" -#include <iostream> -#include <fmt/format.h> -#include "TGeoVolume.h" -#include "TGeoManager.h" -#include "Framework/Logger.h" - -namespace o2 -{ -namespace mch -{ -void createGeometry(TGeoVolume& topVolume) -{ - createMaterials(); - - auto volYOUT1 = gGeoManager->GetVolume("YOUT1"); - - createStation1Geometry((volYOUT1) ? *volYOUT1 : topVolume); - createStation2Geometry((volYOUT1) ? *volYOUT1 : topVolume); - - createStation345Geometry(topVolume); -} - -std::vector<TGeoVolume*> getSensitiveVolumes() -{ - auto st1 = getStation1SensitiveVolumes(); - auto st2 = getStation2SensitiveVolumes(); - auto st345 = getStation345SensitiveVolumes(); - - auto vol = st1; - vol.insert(vol.end(), st2.begin(), st2.end()); - vol.insert(vol.end(), st345.begin(), st345.end()); - - return vol; -} - -namespace impl +namespace o2::mch::geo { // return the path of the mother volume of detElemId, relative to MCH geometry // (i.e. excluding general top node) -std::string getVolumePathName(int detElemId) +std::string volumePathName(int detElemId) { std::string vp{"incorrect detElemId"}; @@ -528,127 +489,4 @@ std::string getVolumePathName(int detElemId) return vp; } - -void addAlignableVolumesHalfChamber(int hc, std::string& parent) -{ - // - // Add alignable volumes for a half chamber and its daughters - // - std::vector<std::vector<int>> DEofHC{{100, 103}, - {101, 102}, - {200, 203}, - {201, 202}, - {300, 303}, - {301, 302}, - {400, 403}, - {401, 402}, - {500, 501, 502, 503, 504, 514, 515, 516, 517}, - {505, 506, 507, 508, 509, 510, 511, 512, 513}, - {600, 601, 602, 603, 604, 614, 615, 616, 617}, - {605, 606, 607, 608, 609, 610, 611, 612, 613}, - {700, 701, 702, 703, 704, 705, 706, 720, 721, 722, 723, 724, 725}, - {707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719}, - {800, 801, 802, 803, 804, 805, 806, 820, 821, 822, 823, 824, 825}, - {807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819}, - {900, 901, 902, 903, 904, 905, 906, 920, 921, 922, 923, 924, 925}, - {907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919}, - {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1020, 1021, 1022, 1023, 1024, 1025}, - {1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019}}; - - for (int i = 0; i < DEofHC[hc].size(); i++) { - std::string volPathName = impl::getVolumePathName(DEofHC[hc][i]); - - TString path = Form("%s%s", parent.c_str(), volPathName.c_str()); - TString sname = Form("MCH/HC%d/DE%d", hc, DEofHC[hc][i]); - - LOG(DEBUG) << "Add " << sname << " <-> " << path; - - if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) { - LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; - } - } - - return; -} - -} // namespace impl - -o2::math_utils::Transform3D getTransformation(int detElemId, const TGeoManager& geo) -{ - - int nCh = detElemId / 100; - - if (nCh < 1 || nCh > 10) { - throw std::runtime_error("Wrong detection element Id"); - } - - std::string volPathName = geo.GetTopVolume()->GetName(); - - if (nCh <= 4 && geo.GetVolume("YOUT1")) { - volPathName += "/YOUT1_1/"; - } else if ((nCh == 5 || nCh == 6) && geo.GetVolume("DDIP")) { - volPathName += "/DDIP_1/"; - } else if (nCh >= 7 && geo.GetVolume("YOUT2")) { - volPathName += "/YOUT2_1/"; - } else { - volPathName += "/"; - } - - volPathName += impl::getVolumePathName(detElemId); - - TGeoNavigator* navig = gGeoManager->GetCurrentNavigator(); - - if (!navig->cd(volPathName.c_str())) { - throw std::runtime_error("could not get to volPathName=" + volPathName); - } - - return o2::math_utils::Transform3D{*(navig->GetCurrentMatrix())}; -} - -void addAlignableVolumesMCH() -{ - // - // Creates entries for alignable volumes associating the symbolic volume - // name with the corresponding volume path. - // - - LOG(INFO) << "Add MCH alignable volumes"; - - for (int hc = 0; hc < 20; hc++) { - int nCh = hc / 2 + 1; - - if (nCh < 1 || nCh > 10) { - throw std::runtime_error("Wrong detection element Id"); - } - - std::string volPathName = gGeoManager->GetTopVolume()->GetName(); - - if (nCh <= 4 && gGeoManager->GetVolume("YOUT1")) { - volPathName += "/YOUT1_1/"; - } else if ((nCh == 5 || nCh == 6) && gGeoManager->GetVolume("DDIP")) { - volPathName += "/DDIP_1/"; - } else if (nCh >= 7 && gGeoManager->GetVolume("YOUT2")) { - volPathName += "/YOUT2_1/"; - } else { - volPathName += "/"; - } - - std::string path = fmt::format("{0}SC{1}{2}{3}_{4}", volPathName.c_str(), nCh < 10 ? "0" : "", nCh, hc % 2 ? "O" : "I", hc); - std::string sname = fmt::format("MCH/HC{}", hc); - - LOG(DEBUG) << sname << " <-> " << path; - - if (!gGeoManager->SetAlignableEntry(sname.c_str(), path.c_str())) { - LOG(FATAL) << "Unable to set alignable entry ! " << sname << " : " << path; - } - - Int_t lastUID = 0; - - impl::addAlignableVolumesHalfChamber(hc, volPathName); - } - - return; -} - -} // namespace mch -} // namespace o2 +} // namespace o2::mch::geo diff --git a/Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx b/Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx new file mode 100644 index 0000000000000..d7f6c9bb6fec3 --- /dev/null +++ b/Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx @@ -0,0 +1,200 @@ +#include <boost/program_options.hpp> +#include <iostream> +#include <stdexcept> +#include <TGeoManager.h> +#include <TFile.h> +#include <sstream> +#include <tuple> +#include <vector> +#include <string> +#include "TGeoPhysicalNode.h" +#include <rapidjson/document.h> +#include <rapidjson/ostreamwrapper.h> +#include <rapidjson/stringbuffer.h> +#include <rapidjson/writer.h> +#include <gsl/span> +#include <cmath> +#include <array> +#include "MCHGeometryTransformer/Transformations.h" + +namespace po = boost::program_options; + +std::vector<std::string> splitString(const std::string& src, char delim) +{ + std::stringstream ss(src); + std::string token; + std::vector<std::string> tokens; + + while (std::getline(ss, token, delim)) { + if (!token.empty()) { + tokens.push_back(std::move(token)); + } + } + + return tokens; +} + +TGeoManager* readFromFile(std::string filename) +{ + TFile* f = TFile::Open(filename.c_str()); + if (f->IsZombie()) { + throw std::runtime_error("can not open " + filename); + } + + auto possibleGeoNames = {"ALICE", "FAIRGeom", "MCH-ONLY", "MCH-BASICS"}; + + TGeoManager* geo{nullptr}; + + for (auto name : possibleGeoNames) { + geo = static_cast<TGeoManager*>(f->Get(name)); + if (geo) { + break; + } + } + if (!geo) { + f->ls(); + throw std::runtime_error("could not find ALICE geometry (using ALICE or FAIRGeom names)"); + } + return geo; +} + +template <typename WRITER> +void matrix2json(const TGeoHMatrix& matrix, WRITER& w) +{ + + constexpr double rad2deg = 180.0 / 3.14159265358979323846; + + const Double_t* t = matrix.GetTranslation(); + const Double_t* m = matrix.GetRotationMatrix(); + gsl::span<double> mat(const_cast<double*>(m), 9); + auto [yaw, pitch, roll] = o2::mch::geo::matrix2angles(mat); + w.Key("tx"); + w.Double(t[0]); + w.Key("ty"); + w.Double(t[1]); + w.Key("tz"); + w.Double(t[2]); + w.Key("yaw"); + w.Double(rad2deg * yaw); + w.Key("pitch"); + w.Double(rad2deg * pitch); + w.Key("roll"); + w.Double(rad2deg * roll); +} + +std::tuple<bool, uint16_t> isMCH(std::string alignableName) +{ + auto parts = splitString(alignableName, '/'); + bool aliroot = parts[0] == "MUON"; + bool o2 = parts[0] == "MCH"; + if (!o2 && !aliroot) { + return {false, 0}; + } + auto id = std::stoi(parts[1].substr(2)); + bool ok = (aliroot && (id <= 15)) || (o2 && (id <= 19)); + uint16_t deId{0}; + if (ok && parts.size() > 2) { + deId = std::stoi(parts[2].substr(2)); + } + return {ok, deId}; +} + +template <typename WRITER> +void writeMatrix(const char* name, const TGeoHMatrix* matrix, WRITER& w) +{ + if (matrix) { + w.Key(name); + w.StartObject(); + matrix2json(*matrix, w); + w.EndObject(); + } +} + +/** convert geometry into a json document. + */ +void convertGeom(const TGeoManager& geom) +{ + rapidjson::OStreamWrapper osw(std::cout); + rapidjson::Writer<rapidjson::OStreamWrapper> writer(osw); + + writer.StartObject(); + writer.Key("alignables"); + writer.StartArray(); + + for (auto i = 0; i < geom.GetNAlignable(); i++) { + auto ae = geom.GetAlignableEntry(i); + std::string symname = ae->GetName(); + auto [mch, deId] = isMCH(symname); + if (!mch) { + continue; + } + writer.StartObject(); + if (deId > 0) { + writer.Key("deid"); + writer.Int(deId); + } + writer.Key("symname"); + writer.String(symname.c_str()); + auto matrix = ae->GetMatrix(); + bool aligned{true}; + if (!matrix) { + matrix = ae->GetGlobalOrig(); + aligned = false; + } + writeMatrix("transform", matrix, writer); + writer.Key("aligned"); + writer.Bool(aligned); + writer.EndObject(); + } + writer.EndArray(); + writer.EndObject(); +} + +int main(int argc, char** argv) +{ + po::variables_map vm; + po::options_description options; + + // clang-format off + options.add_options() + ("help,h","help") + ("geom",po::value<std::string>()->required(),"geometry.root file"); + // clang-format on + + po::options_description cmdline; + cmdline.add(options); + + po::store(po::command_line_parser(argc, argv).options(cmdline).run(), vm); + + if (vm.count("help")) { + std::cout << "This program extract MCH geometry transformation from " + "a geometry root file and write them in json format.\n"; + std::cout << "\n"; + std::cout << options << "\n"; + std::cout << "\n"; + std::cout << "Note that the json format can then be further manipulated using e.g." + "the jq utility\n"; + std::cout << "For instance sorting by deid:\n"; + std::cout << "cat output.json | jq '.alignables|=sort_by(.deid)'\n"; + std::cout << "\n"; + return 2; + } + + try { + po::notify(vm); + } catch (boost::program_options::error& e) { + std::cout << "Error: " << e.what() << "\n"; + std::cout << options << "\n"; + exit(1); + } + + TGeoManager* geom = readFromFile(vm["geom"].as<std::string>()); + + if (geom) { + convertGeom(*geom); + return 0; + } else { + return 3; + } + return 0; +} diff --git a/Detectors/MUON/MCH/README.md b/Detectors/MUON/MCH/README.md index 6f2ebf1975925..07fd2af3abda9 100644 --- a/Detectors/MUON/MCH/README.md +++ b/Detectors/MUON/MCH/README.md @@ -13,4 +13,5 @@ This is a top page for the MCH detector documentation. \subpage refDetectorsMUONMCHMapping \subpage refDetectorsMUONMCHTracking \subpage refDetectorsMUONMCHWorkflow +\subpage refDetectorsMUONMCHGeometry /doxy --> diff --git a/Detectors/MUON/MCH/Simulation/CMakeLists.txt b/Detectors/MUON/MCH/Simulation/CMakeLists.txt index 3cc9ca36c5694..0952360e2f5cb 100644 --- a/Detectors/MUON/MCH/Simulation/CMakeLists.txt +++ b/Detectors/MUON/MCH/Simulation/CMakeLists.txt @@ -11,30 +11,18 @@ o2_add_library(MCHSimulation SOURCES src/Detector.cxx src/Digitizer.cxx - src/Geometry.cxx - src/GeometryTest.cxx src/Hit.cxx - src/Materials.cxx - src/Materials.h - src/Response.cxx - src/Station1Geometry.cxx - src/Station1Geometry.h - src/Station2Geometry.cxx - src/Station2Geometry.h - src/Station345Geometry.cxx - src/Station345Geometry.h src/Stepper.cxx src/Stepper.h + src/Response.cxx PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::MCHBase O2::DetectorsPassive O2::MCHMappingImpl4 O2::DetectorsBase - RapidJSON::RapidJSON) + O2::MCHGeometryCreator) o2_target_root_dictionary(MCHSimulation HEADERS include/MCHSimulation/Detector.h include/MCHSimulation/Digitizer.h - include/MCHSimulation/Geometry.h - include/MCHSimulation/GeometryTest.h include/MCHSimulation/Hit.h include/MCHSimulation/Response.h) @@ -42,7 +30,4 @@ o2_data_file(COPY data DESTINATION Detectors/MCH/simulation) if(BUILD_TESTING) add_subdirectory(test) - o2_add_test_root_macro(macros/drawMCHGeometry.C - PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase - LABELS "muon;mch") endif() diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h deleted file mode 100644 index 4857f8a3032cd..0000000000000 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Geometry.h +++ /dev/null @@ -1,44 +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. - -/// @file Geometry.h -/// @brief Interface for MCH geometry creation - -#ifndef O2_MCH_SIMULATION_GEOMETRY_H -#define O2_MCH_SIMULATION_GEOMETRY_H - -#include <vector> -#include <iostream> -#include "MathUtils/Cartesian.h" - -class TGeoVolume; -class TGeoManager; - -namespace o2 -{ -namespace mch -{ - -/// createGeometry creates MCH geometry and attach it to existing topVolume -void createGeometry(TGeoVolume& topVolume); - -/// get a list of MCH sensitive volumes -std::vector<TGeoVolume*> getSensitiveVolumes(); - -/// Add alignable mch volumes -void addAlignableVolumesMCH(); - -/// get the local-to-global transformation for a given detection element -o2::math_utils::Transform3D getTransformation(int detElemId, const TGeoManager& geo); - -} // namespace mch -} // namespace o2 - -#endif // O2_MCH_SIMULATION_GEOMETRY_H diff --git a/Detectors/MUON/MCH/Simulation/src/Detector.cxx b/Detectors/MUON/MCH/Simulation/src/Detector.cxx index 6d244e77a4151..e77e6930837d4 100644 --- a/Detectors/MUON/MCH/Simulation/src/Detector.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Detector.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. #include "MCHSimulation/Detector.h" -#include "MCHSimulation/Geometry.h" +#include "MCHGeometryCreator/Geometry.h" #include "SimulationDataFormat/Stack.h" #include "Stepper.h" #include "TGeoManager.h" @@ -42,7 +42,7 @@ Detector::~Detector() void Detector::defineSensitiveVolumes() { - for (auto* vol : getSensitiveVolumes()) { + for (auto* vol : geo::getSensitiveVolumes()) { AddSensitiveVolume(vol); } } @@ -58,7 +58,7 @@ void Detector::ConstructGeometry() if (!top) { throw std::runtime_error("Cannot create MCH geometry without a top volume"); } - createGeometry(*top); + geo::createGeometry(*gGeoManager, *top); } void Detector::addAlignableVolumes() const @@ -66,7 +66,7 @@ void Detector::addAlignableVolumes() const if (!gGeoManager) { throw std::runtime_error("Cannot add alignable volumes without TGeoManager"); } - addAlignableVolumesMCH(); + geo::addAlignableVolumes(*gGeoManager); } Bool_t Detector::ProcessHits(FairVolume* v) diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index 9d9b3ccc9ef21..555add712a184 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -11,7 +11,8 @@ #include "MCHSimulation/Digitizer.h" #include "MCHMappingInterface/Segmentation.h" -#include "MCHSimulation/Geometry.h" +#include "MCHGeometryCreator/Geometry.h" +#include "MCHGeometryTransformer/Transformations.h" #include "MCHSimulation/Response.h" #include "TGeoManager.h" #include "TMath.h" @@ -124,7 +125,8 @@ int Digitizer::processHit(const Hit& hit, int detID, int event_time) auto time = event_time & int(hit.GetTime() / 25.); //transformation from global to local - auto t = o2::mch::getTransformation(detID, *gGeoManager); + auto transformation = o2::mch::geo::transformationFromTGeoManager(*gGeoManager); + auto t = transformation(detID); math_utils::Point3D<float> lpos; t.MasterToLocal(pos, lpos); @@ -185,7 +187,7 @@ int Digitizer::processHit(const Hit& hit, int detID, int event_time) void Digitizer::generateNoiseDigits() { - o2::mch::mapping::forEachDetectionElement([& digits = this->mDigits, &normProbNoise = this->mNormProbNoise, + o2::mch::mapping::forEachDetectionElement([&digits = this->mDigits, &normProbNoise = this->mNormProbNoise, &eventTime = this->mEventTime, &eventID = this->mEventID, &srcID = this->mSrcID, &mcTruthOutputContainer = this->mMCTruthOutputContainer](int detID) { auto& seg = segmentation(detID); @@ -211,7 +213,7 @@ void Digitizer::mergeDigits() { std::vector<int> indices(mDigits.size()); std::iota(begin(indices), end(indices), 0); - std::sort(indices.begin(), indices.end(), [& digits = this->mDigits, this](int a, int b) { + std::sort(indices.begin(), indices.end(), [&digits = this->mDigits, this](int a, int b) { return (getGlobalDigit(digits[a].getDetID(), digits[a].getPadID()) < getGlobalDigit(digits[b].getDetID(), digits[b].getPadID())); }); diff --git a/Detectors/MUON/MCH/Simulation/src/MCHSimulationLinkDef.h b/Detectors/MUON/MCH/Simulation/src/MCHSimulationLinkDef.h index 723051d17c642..c359a98595f53 100644 --- a/Detectors/MUON/MCH/Simulation/src/MCHSimulationLinkDef.h +++ b/Detectors/MUON/MCH/Simulation/src/MCHSimulationLinkDef.h @@ -16,25 +16,10 @@ #pragma link C++ namespace o2; #pragma link C++ namespace o2::mch; -#pragma link C++ namespace o2::mch::test; -#pragma link C++ class o2::mch::test::Dummy; #pragma link C++ class o2::mch::Detector + ; #pragma link C++ class o2::mch::Hit + ; -#pragma link C++ class std::vector < o2::mch::Hit> + ; -#pragma link C++ class o2::base::DetImpl < o2::mch::Detector> + ; - -#pragma link C++ function o2::mch::addAlignableVolumesMCH; -#pragma link C++ function o2::mch::createGeometry; -#pragma link C++ function o2::mch::getSensitiveVolumes; - -#pragma link C++ function o2::mch::test::addAlignableVolumes; -#pragma link C++ function o2::mch::test::createStandaloneGeometry; -#pragma link C++ function o2::mch::test::createRegularGeometry; -#pragma link C++ function o2::mch::test::drawGeometry; -#pragma link C++ function o2::mch::test::getRadio; -#pragma link C++ function o2::mch::test::showGeometryAsTextTree; -#pragma link C++ function o2::mch::test::setVolumeVisibility; -#pragma link C++ function o2::mch::test::setVolumeColor; +#pragma link C++ class std::vector < o2::mch::Hit > +; +#pragma link C++ class o2::base::DetImpl < o2::mch::Detector > +; #endif diff --git a/Detectors/MUON/MCH/Simulation/test/CMakeLists.txt b/Detectors/MUON/MCH/Simulation/test/CMakeLists.txt index 9e0508c8e0d5b..8a7129866b533 100644 --- a/Detectors/MUON/MCH/Simulation/test/CMakeLists.txt +++ b/Detectors/MUON/MCH/Simulation/test/CMakeLists.txt @@ -8,28 +8,30 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_test(geometry-standalone - NAME o2-test-mch-geometry-standalone +o2_add_test(digit-merging COMPONENT_NAME mch - SOURCES testGeometry.cxx - PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase - COMMAND_LINE_ARGS standalone + SOURCES testDigitMerging.cxx DigitMerging.cxx + PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase O2::DetectorsPassive LABELS muon mch sim) -o2_add_test(geometry-regular - NAME o2-test-mch-geometry-regular - COMPONENT_NAME mch - SOURCES testGeometry.cxx - PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase - COMMAND_LINE_ARGS regular - LABELS muon mch sim) +# o2_add_test(digitization +# COMPONENT_NAME mch +# SOURCES testDigitization.cxx +# PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase O2::DetectorsPassive +# LABELS muon mch long sim) +# +# o2_add_test(response +# COMPONENT_NAME mch +# SOURCES testResponse.cxx +# PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase O2::DetectorsPassive +# LABELS muon mch sim) -o2_add_test(simulation +o2_add_test(regular-geometry COMPONENT_NAME mch - SOURCES testDigitMerging.cxx DigitMerging.cxx - testDigitization.cxx testResponse.cxx - PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase - LABELS muon mch long sim) + SOURCES + testRegularGeometry.cxx + PUBLIC_LINK_LIBRARIES O2::MCHSimulation O2::MCHBase O2::DetectorsPassive + LABELS muon mch sim) if(benchmark_FOUND) o2_add_executable( diff --git a/Detectors/MUON/MCH/Simulation/test/testDigitMerging.cxx b/Detectors/MUON/MCH/Simulation/test/testDigitMerging.cxx index 9fde668423ca0..2c6b1d763472d 100644 --- a/Detectors/MUON/MCH/Simulation/test/testDigitMerging.cxx +++ b/Detectors/MUON/MCH/Simulation/test/testDigitMerging.cxx @@ -8,9 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test MCHSimulation Digitization +#define BOOST_TEST_MODULE Test MCHSimulation DigitMerging #define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MAIN #include <boost/test/unit_test.hpp> @@ -25,8 +24,6 @@ using o2::mch::Digit; -BOOST_AUTO_TEST_SUITE(o2_mch_simulation) - std::vector<Digit> createNonOverlappingDigits() { return std::vector<Digit>{ @@ -102,5 +99,3 @@ BOOST_DATA_TEST_CASE(DigitMerging, boost::unit_test::data::make(mergingFunctions auto m = mergingFunction(createOverlappingDigits(), createLabelsOverlappingDigits()); BOOST_CHECK(std::is_permutation(m.begin(), m.end(), expected().begin())); } - -BOOST_AUTO_TEST_SUITE_END() diff --git a/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx b/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx index 5bde3ab89b307..ebd63b59f1e44 100644 --- a/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx +++ b/Detectors/MUON/MCH/Simulation/test/testDigitization.cxx @@ -11,20 +11,22 @@ /// \brief This task tests the Digitizer and the Response of the MCH digitization /// \author Michael Winn, DPhN/IRFU/CEA, michael.winn@cern.ch +#define BOOST_TEST_MODULE Test MCHSimulation Digitization #define BOOST_TEST_DYN_LINK #include <boost/test/unit_test.hpp> -#include "TGeoManager.h" #include "MCHBase/Digit.h" +#include "MCHGeometryTransformer/Transformations.h" +#include "MCHMappingInterface/Segmentation.h" #include "MCHSimulation/Digitizer.h" +#include "MCHGeometryCreator/Geometry.h" +#include "MCHGeometryCreator/GeometryTest.h" #include "MCHSimulation/Hit.h" -#include "MCHSimulation/Geometry.h" -#include "MCHSimulation/GeometryTest.h" -#include "MCHMappingInterface/Segmentation.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "TGeoManager.h" +#include "TGeoManager.h" #include "boost/format.hpp" #include <boost/test/data/test_case.hpp> @@ -49,8 +51,6 @@ o2::math_utils::Point3D<float> exitPoint2(-49.2965, 28.8806, -1441.75); /// A couple of values are filled into Hits and we check whether we get reproducible output in terms of digits /// and MClabels -BOOST_AUTO_TEST_SUITE(o2_mch_simulation) - BOOST_FIXTURE_TEST_SUITE(digitization, GEOMETRY) BOOST_TEST_DECORATOR(*boost::unit_test::disabled()) @@ -82,6 +82,8 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) int digitcounter2 = 0; int count = 0; + auto transformation = o2::mch::geo::transformationFromTGeoManager(*gGeoManager); + for (auto& digit : digits) { int padid = digit.getPadID(); @@ -98,7 +100,7 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) double padsizeX = seg1.padSizeX(padid); double padposY = seg1.padPositionY(padid); double padsizeY = seg1.padSizeY(padid); - auto t = o2::mch::getTransformation(detElemId1, *gGeoManager); + auto t = transformation(detElemId1); o2::math_utils::Point3D<float> pos(hits.at(0).GetX(), hits.at(0).GetY(), hits.at(0).GetZ()); o2::math_utils::Point3D<float> lpos; @@ -117,7 +119,7 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) double padsizeX = seg2.padSizeX(padid); double padposY = seg2.padPositionY(padid); double padsizeY = seg2.padSizeY(padid); - auto t = o2::mch::getTransformation(detElemId2, *gGeoManager); + auto t = transformation(detElemId2); o2::math_utils::Point3D<float> pos(hits.at(1).GetX(), hits.at(1).GetY(), hits.at(1).GetZ()); o2::math_utils::Point3D<float> lpos; @@ -204,4 +206,3 @@ BOOST_AUTO_TEST_CASE(mergingDigitizer) } //testing BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() diff --git a/Detectors/MUON/MCH/Simulation/test/testRegularGeometry.cxx b/Detectors/MUON/MCH/Simulation/test/testRegularGeometry.cxx new file mode 100644 index 0000000000000..271aae7060603 --- /dev/null +++ b/Detectors/MUON/MCH/Simulation/test/testRegularGeometry.cxx @@ -0,0 +1,42 @@ +// 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. + +#define BOOST_TEST_MODULE Test MCHSimulation RegularGeometry +#define BOOST_TEST_DYN_LINK + +#include <boost/test/unit_test.hpp> +#include "DetectorsPassive/Absorber.h" +#include "DetectorsPassive/Cave.h" +#include "DetectorsPassive/Compensator.h" +#include "DetectorsPassive/Dipole.h" +#include "DetectorsPassive/Pipe.h" +#include "DetectorsPassive/Shil.h" +#include "MCHSimulation/Detector.h" +#include "TGeoManager.h" +#include <boost/test/data/test_case.hpp> +#include <fstream> +#include <iomanip> +#include <iostream> + +BOOST_AUTO_TEST_CASE(DoNotThrow) +{ + if (gGeoManager && gGeoManager->GetTopVolume()) { + std::cerr << "Can only call this function with an empty geometry, i.e. gGeoManager==nullptr " + << " or gGeoManager->GetTopVolume()==nullptr\n"; + } + TGeoManager* g = new TGeoManager("MCH-BASICS", "ALICE MCH Regular Geometry"); + o2::passive::Cave("CAVE", "Cave (for MCH Basics)").ConstructGeometry(); + o2::passive::Dipole("DIPO", "Alice Dipole (for MCH Basics)").ConstructGeometry(); + o2::passive::Compensator("COMP", "Alice Compensator Dipole (for MCH Basics)").ConstructGeometry(); + o2::passive::Pipe("PIPE", "Beam pipe (for MCH Basics)").ConstructGeometry(); + o2::passive::Shil("SHIL", "Small angle beam shield (for MCH Basics)").ConstructGeometry(); + o2::passive::Absorber("ABSO", "Absorber (for MCH Basics)").ConstructGeometry(); + BOOST_CHECK_NO_THROW((o2::mch::Detector(true).ConstructGeometry())); +} diff --git a/Detectors/MUON/MCH/Simulation/test/testResponse.cxx b/Detectors/MUON/MCH/Simulation/test/testResponse.cxx index d87a52b10cdc6..2acddbf5f0e5e 100644 --- a/Detectors/MUON/MCH/Simulation/test/testResponse.cxx +++ b/Detectors/MUON/MCH/Simulation/test/testResponse.cxx @@ -11,7 +11,9 @@ /// \brief This task tests of the Response of the MCH digitization /// \author Michael Winn, DPhN/IRFU/CEA, michael.winn@cern.ch +#define BOOST_TEST_MODULE Test MCHSimulation Response #define BOOST_TEST_DYN_LINK + #include <boost/test/unit_test.hpp> #include <memory> #include <vector> diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 933546715c67d..890840ad40e7a 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -19,7 +19,7 @@ include(O2GetListOfMacros) list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Detectors/ITSMFT/ITS/macros/test/CheckLUtime.C # temporary exclude until fix for full Clusters elimination Detectors/ITSMFT/ITS/macros/test/dictionary_integrity_test.C # temporary exclude until fix for full Clusters elimination - Detectors/MUON/MCH/Simulation/macros/rootlogon.C + Detectors/MUON/MCH/Geometry/Test/rootlogon.C Detectors/Passive/macro/PutFrameInTop.C Detectors/TPC/reconstruction/macro/addInclude.C Detectors/TPC/reconstruction/macro/getTPCTransformationExample.C From 61e930761d2f19dadd0db74d5a7dba3b395e24fd Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Mon, 30 Nov 2020 13:58:12 +0100 Subject: [PATCH 1511/1751] clang-format --- Detectors/MUON/MCH/Simulation/src/Digitizer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx index 555add712a184..8ea0b4514f99b 100644 --- a/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Digitizer.cxx @@ -187,7 +187,7 @@ int Digitizer::processHit(const Hit& hit, int detID, int event_time) void Digitizer::generateNoiseDigits() { - o2::mch::mapping::forEachDetectionElement([&digits = this->mDigits, &normProbNoise = this->mNormProbNoise, + o2::mch::mapping::forEachDetectionElement([& digits = this->mDigits, &normProbNoise = this->mNormProbNoise, &eventTime = this->mEventTime, &eventID = this->mEventID, &srcID = this->mSrcID, &mcTruthOutputContainer = this->mMCTruthOutputContainer](int detID) { auto& seg = segmentation(detID); @@ -213,7 +213,7 @@ void Digitizer::mergeDigits() { std::vector<int> indices(mDigits.size()); std::iota(begin(indices), end(indices), 0); - std::sort(indices.begin(), indices.end(), [&digits = this->mDigits, this](int a, int b) { + std::sort(indices.begin(), indices.end(), [& digits = this->mDigits, this](int a, int b) { return (getGlobalDigit(digits[a].getDetID(), digits[a].getPadID()) < getGlobalDigit(digits[b].getDetID(), digits[b].getPadID())); }); From d9f3e47b4331b880f227b7256347a29bf2c38a2a Mon Sep 17 00:00:00 2001 From: Laurent Aphecetche <laurent.aphecetche@gmail.com> Date: Wed, 2 Dec 2020 14:30:54 +0100 Subject: [PATCH 1512/1751] Add missing copyright --- .../MCH/Geometry/Transformer/src/convert-geometry.cxx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx b/Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx index d7f6c9bb6fec3..59e1b5ea85766 100644 --- a/Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx +++ b/Detectors/MUON/MCH/Geometry/Transformer/src/convert-geometry.cxx @@ -1,3 +1,13 @@ +// 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 <boost/program_options.hpp> #include <iostream> #include <stdexcept> From 20759741c5a2ea87b08f9142ddd9a3e7e297e63f Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Thu, 26 Nov 2020 14:20:22 +0100 Subject: [PATCH 1513/1751] fix for TOF calib info and TOF workflow --- .../include/DataFormatsTOF/CalibTimeSlewingParamTOF.h | 3 ++- .../Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx | 9 +++++---- .../tofworkflow/src/tof-reco-workflow.cxx | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h index 89d0da80cd279..ba15203e7781f 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/CalibTimeSlewingParamTOF.h @@ -82,11 +82,12 @@ class CalibTimeSlewingParamTOF private: // TOF channel calibrations std::array<std::array<int, NCHANNELXSECTOR>, NSECTORS> mChannelStart; ///< array with the index of the first element of a channel in the time slewing vector (per sector) + std::array<std::array<float, NCHANNELXSECTOR>, NSECTORS> mGlobalOffset; ///< array with the sigma of the peak std::array<std::vector<std::pair<unsigned short, short>>, NSECTORS> mTimeSlewing; ///< array of sector vectors; first element of the pair is TOT (in ps), second is t-texp_pi (in ps) std::array<std::array<float, NCHANNELXSECTOR>, NSECTORS> mFractionUnderPeak; ///< array with the fraction of entries below the peak std::array<std::array<float, NCHANNELXSECTOR>, NSECTORS> mSigmaPeak; ///< array with the sigma of the peak - ClassDefNV(CalibTimeSlewingParamTOF, 1); // class for TOF time slewing params + ClassDefNV(CalibTimeSlewingParamTOF, 2); // class for TOF time slewing params }; } // namespace dataformats } // namespace o2 diff --git a/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx b/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx index 2e7980dd0d9f8..f58e815f5d171 100644 --- a/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx +++ b/DataFormats/Detectors/TOF/src/CalibTimeSlewingParamTOF.cxx @@ -64,7 +64,7 @@ float CalibTimeSlewingParamTOF::evalTimeSlewing(int channel, float totIn) const } if (totIn == 0) { - return (float)((mTimeSlewing[sector])[n].second); + return (float)((mTimeSlewing[sector])[n].second + mGlobalOffset[sector][channel]); } // we convert tot from ns to ps and to unsigned short @@ -80,13 +80,13 @@ float CalibTimeSlewingParamTOF::evalTimeSlewing(int channel, float totIn) const } if (n == nstop - 1) { - return (float)((mTimeSlewing[sector])[n].second); // use the last value stored for that channel + return (float)((mTimeSlewing[sector])[n].second + mGlobalOffset[sector][channel]); // use the last value stored for that channel } float w1 = (float)(tot - (mTimeSlewing[sector])[n].first); float w2 = (float)((mTimeSlewing[sector])[n + 1].first - tot); - return (float)(((mTimeSlewing[sector])[n].second * w2 + (mTimeSlewing[sector])[n + 1].second * w1) / ((mTimeSlewing[sector])[n + 1].first - (mTimeSlewing[sector])[n].first)); + return (float)(mGlobalOffset[sector][channel] + (((mTimeSlewing[sector])[n].second * w2 + (mTimeSlewing[sector])[n + 1].second * w1) / ((mTimeSlewing[sector])[n + 1].first - (mTimeSlewing[sector])[n].first))); } //______________________________________________ @@ -114,10 +114,11 @@ void CalibTimeSlewingParamTOF::addTimeSlewingInfo(int channel, float tot, float // printf("DBG: fill channel %i\n",currentch); // set also all the previous ones which were not filled mChannelStart[sector][currentch] = (mTimeSlewing[sector]).size(); + mGlobalOffset[sector][currentch] = time; currentch--; } // printf("DBG: emplace back (%f,%f)\n",tot,time); - (mTimeSlewing[sector]).emplace_back((unsigned short)(tot * 1000), (short)time); + (mTimeSlewing[sector]).emplace_back((unsigned short)(tot * 1000), (short)(time - mGlobalOffset[sector][currentch])); } //______________________________________________ diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index c924950007c7c..38ce122bc96bf 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -171,7 +171,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) LOG(INFO) << "TOF disable-row-writing = " << disableROWwriting; LOG(INFO) << "TOF write-decoding-errors = " << writeerr; - if (clusterinput) { + if (clusterinput && !disableRootInput) { LOG(INFO) << "Insert TOF Cluster Reader"; specs.emplace_back(o2::tof::getClusterReaderSpec(useMC)); } else if (dgtinput) { @@ -197,7 +197,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } } - if (!clusterinput && writecluster) { + if (!clusterinput && writecluster && !disableRootOutput) { LOG(INFO) << "Insert TOF Clusterizer"; specs.emplace_back(o2::tof::getTOFClusterizerSpec(useMC, useCCDB)); if (writecluster && !disableRootOutput) { @@ -222,7 +222,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) LOG(INFO) << "Insert TOF Matched Info Writer"; specs.emplace_back(o2::tof::getTOFMatchedWriterSpec(useMC)); } - if (writecalib) { + if (writecalib && !disableRootOutput) { LOG(INFO) << "Insert TOF Calib Info Writer"; specs.emplace_back(o2::tof::getTOFCalibWriterSpec()); } From 71d52972e14bd30f4ceb6f20d58da7d536de3b3b Mon Sep 17 00:00:00 2001 From: Francesco Noferini <noferini@bo.infn.it> Date: Thu, 26 Nov 2020 14:34:00 +0100 Subject: [PATCH 1514/1751] add TOF Cluster writer for commissioning --- .../tofworkflow/src/tof-reco-workflow.cxx | 2 +- Detectors/TOF/workflow/CMakeLists.txt | 5 + .../TOFClusterWriterSplitterSpec.h | 132 ++++++++++++++++++ .../TOFDigitWriterSplitterSpec.h | 2 +- .../src/cluster-writer-commissioning.cxx | 38 +++++ .../src/digit-writer-commissioning.cxx | 2 +- 6 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterWriterSplitterSpec.h create mode 100644 Detectors/TOF/workflow/src/cluster-writer-commissioning.cxx diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 38ce122bc96bf..7e053e518f18b 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -197,7 +197,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } } - if (!clusterinput && writecluster && !disableRootOutput) { + if (!clusterinput && writecluster) { LOG(INFO) << "Insert TOF Clusterizer"; specs.emplace_back(o2::tof::getTOFClusterizerSpec(useMC, useCCDB)); if (writecluster && !disableRootOutput) { diff --git a/Detectors/TOF/workflow/CMakeLists.txt b/Detectors/TOF/workflow/CMakeLists.txt index 567c372173917..0c932834b9c4e 100644 --- a/Detectors/TOF/workflow/CMakeLists.txt +++ b/Detectors/TOF/workflow/CMakeLists.txt @@ -31,3 +31,8 @@ o2_add_executable(digit-writer-workflow SOURCES src/digit-writer-commissioning.cxx COMPONENT_NAME tof PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils) + +o2_add_executable(cluster-writer-workflow + SOURCES src/cluster-writer-commissioning.cxx + COMPONENT_NAME tof + PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils) diff --git a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterWriterSplitterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterWriterSplitterSpec.h new file mode 100644 index 0000000000000..eecb8c842fc70 --- /dev/null +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFClusterWriterSplitterSpec.h @@ -0,0 +1,132 @@ +// 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_TOFCLUSTER_SPLITTER_WRITER_H +#define O2_TOFCLUSTER_SPLITTER_WRITER_H + +/// @file TOFClusterWriterSplitterSpec.h +/// @brief Device to write to tree the information for TOF time slewing calibration. + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "DataFormatsTOF/Cluster.h" +#include "Framework/Logger.h" +#include <TTree.h> +#include <TFile.h> +#include <gsl/span> + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ +class TOFClusterWriterSplitter : public Task +{ + using OutputType = std::vector<o2::tof::Cluster>; + + std::string mBaseName; + + public: + TOFClusterWriterSplitter(int nTF) : mTFthr(nTF) {} + + void createAndOpenFileAndTree() + { + TString filename = TString::Format("%s_%06d.root", mBaseName.c_str(), mCount); + LOG(DEBUG) << "opening file " << filename.Data(); + mfileOut.reset(TFile::Open(TString::Format("%s", filename.Data()), "RECREATE")); + mOutputTree = std::make_unique<TTree>("o2sim", "Tree with TOF clusters"); + mOutputTree->Branch("TOFCluster", &mPClusters); + + mNTF = 0; + } + + void init(o2::framework::InitContext& ic) final + { + mBaseName = ic.options().get<std::string>("output-base-name"); + + mCount = 0; + createAndOpenFileAndTree(); + } + + void run(o2::framework::ProcessingContext& pc) final + { + auto clusters = pc.inputs().get<OutputType>("clusters"); + mPClusters = &clusters; + mOutputTree->Fill(); + + mNTF++; + + if (mNTF >= mTFthr) { + sendOutput(); + } + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + mIsEndOfStream = true; + sendOutput(); + } + + private: + int mCount = 0; // how many times we filled the tree + int mNTF = 0; + int mTFthr = 1; + bool mIsEndOfStream = false; + OutputType mClusters; + const OutputType* mPClusters = &mClusters; + + std::unique_ptr<TTree> mOutputTree; ///< tree for the collected calib tof info + std::unique_ptr<TFile> mfileOut = nullptr; // file in which to write the output + + //________________________________________________________________ + void sendOutput() + { + // This is to fill the tree. + // One file with an empty tree will be created at the end, because we have to have a + // tree opened before processing, since we do not know a priori if something else + // will still come. The size of this extra file is ~6.5 kB + + mfileOut->cd(); + mOutputTree->Write(); + mOutputTree.reset(); + mfileOut.reset(); + mCount++; + if (!mIsEndOfStream) { + createAndOpenFileAndTree(); + } + } +}; +} // namespace tof + +namespace framework +{ + +DataProcessorSpec getTOFClusterWriterSplitterSpec(int nTF) +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("clusters", o2::header::gDataOriginTOF, "CLUSTERS"); + + std::vector<OutputSpec> outputs; // empty + + return DataProcessorSpec{ + "tof-cluster-splitter-writer", + inputs, + outputs, + AlgorithmSpec{adaptFromTask<o2::tof::TOFClusterWriterSplitter>(nTF)}, + Options{{"output-base-name", VariantType::String, "tofclusters", {"Name of the input file (root extension will be added)"}}}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h index 848078cc7be95..8311733203f0f 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h +++ b/Detectors/TOF/workflow/include/TOFWorkflowUtils/TOFDigitWriterSplitterSpec.h @@ -140,7 +140,7 @@ class TOFDigitWriterSplitter : public Task namespace framework { -DataProcessorSpec getTOFCalibCollectorWriterSpec(int nTF, bool storeErr = false) +DataProcessorSpec getTOFDigitWriterSplitterSpec(int nTF, bool storeErr = false) { std::vector<InputSpec> inputs; inputs.emplace_back("header", o2::header::gDataOriginTOF, "DIGITHEADER"); diff --git a/Detectors/TOF/workflow/src/cluster-writer-commissioning.cxx b/Detectors/TOF/workflow/src/cluster-writer-commissioning.cxx new file mode 100644 index 0000000000000..b304e2d0003be --- /dev/null +++ b/Detectors/TOF/workflow/src/cluster-writer-commissioning.cxx @@ -0,0 +1,38 @@ +// 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 "TOFWorkflowUtils/TOFClusterWriterSplitterSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + workflowOptions.push_back(ConfigParamSpec{"ntf", o2::framework::VariantType::Int, 1, {"number of timeframe written for output file"}}); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + auto ntf = cfgc.options().get<int>("ntf"); + wf.emplace_back(o2::framework::getTOFClusterWriterSplitterSpec(ntf)); + + return wf; +} diff --git a/Detectors/TOF/workflow/src/digit-writer-commissioning.cxx b/Detectors/TOF/workflow/src/digit-writer-commissioning.cxx index a42cd1fef3046..86751ea43fa24 100644 --- a/Detectors/TOF/workflow/src/digit-writer-commissioning.cxx +++ b/Detectors/TOF/workflow/src/digit-writer-commissioning.cxx @@ -34,6 +34,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // Update the (declared) parameters if changed from the command line auto ntf = cfgc.options().get<int>("ntf"); auto write_err = cfgc.options().get<bool>("write-decoding-errors"); - wf.emplace_back(o2::framework::getTOFCalibCollectorWriterSpec(ntf, write_err)); + wf.emplace_back(o2::framework::getTOFDigitWriterSplitterSpec(ntf, write_err)); return wf; } From a920f45d58f9f95345ee3688336c81a07c98c7ef Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 2 Dec 2020 10:36:24 +0100 Subject: [PATCH 1515/1751] Generators: Remove unused/deprecated code --- .../include/Generators/Pythia6Generator.h | 128 ------------ .../include/Generators/Pythia8Generator.h | 87 -------- Generators/src/Pythia6Generator.cxx | 146 ------------- Generators/src/Pythia8Generator.cxx | 196 ------------------ 4 files changed, 557 deletions(-) delete mode 100644 Generators/include/Generators/Pythia6Generator.h delete mode 100644 Generators/include/Generators/Pythia8Generator.h delete mode 100644 Generators/src/Pythia6Generator.cxx delete mode 100644 Generators/src/Pythia8Generator.cxx diff --git a/Generators/include/Generators/Pythia6Generator.h b/Generators/include/Generators/Pythia6Generator.h deleted file mode 100644 index 9dd94f2ff714e..0000000000000 --- a/Generators/include/Generators/Pythia6Generator.h +++ /dev/null @@ -1,128 +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. - -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence version 3 (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ -// ------------------------------------------------------------------------- -// ----- M. Al-Turany June 2014 ----- -// ------------------------------------------------------------------------- - -// ------------------------------------------------------------------------- -// ----- Pythia6Generator header file ----- -// ----- Created 08/08/08 by S. Spataro ----- -// ------------------------------------------------------------------------- - -/** Pythia6Generator.h - *@author S.Spataro <spataro@to.infn.it> - * - The Pythia6Generator reads a Pythia6 input file. The file must contain - for each event a header line of the format: - - [start] -1 20 - 3 -2212 0 0 0 0 0.00000000E+00 0.00000000E+00 0.14000000E+02 0.14031406E+02 0.93827000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 2212 0 0 0 0 0.00000000E+00 0.00000000E+00 -0.13444107E-16 0.93827000E+00 0.93827000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 -2 1 0 0 0 -0.70661074E+00 -0.81156104E+00 0.49379331E+01 0.50538217E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 2 2 0 0 0 -0.79043780E+00 0.32642680E+00 0.10299757E+01 0.13387293E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 -2 3 0 0 0 -0.70661074E+00 -0.81156104E+00 0.49379331E+01 0.50538217E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 2 4 0 0 0 -0.79043780E+00 0.32642680E+00 0.10299757E+01 0.13387293E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 23 5 6 0 0 -0.14970485E+01 -0.48513424E+00 0.59679088E+01 0.63925510E+01 0.16650116E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 11 7 0 0 0 -0.16024130E+01 0.20883507E-01 0.32233123E+01 0.35997091E+01 0.51000000E-03 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 -11 7 0 0 0 0.10536443E+00 -0.50601774E+00 0.27445965E+01 0.27928419E+01 0.51000000E-03 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 2 23 7 0 11 13 -0.14970485E+01 -0.48513424E+00 0.59679088E+01 0.63925510E+01 0.16650116E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 1 -11 9 0 0 0 0.10536442E+00 -0.50601769E+00 0.27445962E+01 0.27928416E+01 0.51000000E-03 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 1 11 8 0 0 0 -0.16017105E+01 0.20863360E-01 0.32218964E+01 0.35981284E+01 0.51000000E-03 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 1 22 8 0 0 0 -0.70246172E-03 0.20096726E-04 0.14161816E-02 0.15809575E-02 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 2 -2103 1 0 16 16 0.70661074E+00 0.81156104E+00 0.69735272E+01 0.70980957E+01 0.77133000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 2 2101 2 0 16 16 0.79043780E+00 -0.32642680E+00 0.10585640E+01 0.14790292E+01 0.57933000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 2 92 14 15 17 18 0.14970485E+01 0.48513424E+00 0.80320912E+01 0.85771248E+01 0.25643853E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 2 -2214 16 0 19 20 0.81382620E+00 0.70515618E+00 0.61830559E+01 0.63829315E+01 0.11627878E+01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 1 2212 16 0 0 0 0.68322234E+00 -0.22002195E+00 0.18490353E+01 0.21941934E+01 0.93827000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 1 -2112 17 0 0 0 0.78494059E+00 0.52384336E+00 0.55944336E+01 0.57507411E+01 0.93957000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 1 -211 17 0 0 0 0.28885610E-01 0.18131282E+00 0.58862227E+00 0.63219038E+00 0.13957000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 2 25 - 3 -2212 0 0 0 0 0.00000000E+00 0.00000000E+00 0.14000000E+02 0.14031406E+02 0.93827000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - 3 2212 0 0 0 0 0.00000000E+00 0.00000000E+00 -0.13444107E-16 0.93827000E+00 0.93827000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 - - -... - [stop] - - where the first row has the number of event and the number of particles, and below "N" is the line - number of the event, - - Derived from FairGenerator. -**/ - -#ifndef PND_PYTHIAGENERATOR_H -#define PND_PYTHIAGENERATOR_H - -#ifdef __CLING__ -#define _DLFCN_H_ -#define _DLFCN_H -#endif - -#include <cstdio> // for FILE -#include "FairGenerator.h" // for FairGenerator -#include "Rtypes.h" // for Int_t, Pythia6Generator::Class, Bool_t, etc -class FairPrimaryGenerator; // lines 68-68 - -namespace o2 -{ -namespace eventgen -{ - -class Pythia6Generator : public FairGenerator -{ - - public: - /** Default constructor without arguments should not be used. **/ - Pythia6Generator(); - - /** Standard constructor. - ** @param fileName The input file name - **/ - Pythia6Generator(const char* fileName); - - /** Destructor. **/ - ~Pythia6Generator() override; - - /** Reads on event from the input file and pushes the tracks onto - ** the stack. Abstract method in base class. - ** @param primGen pointer to the CbmrimaryGenerator - **/ - Bool_t ReadEvent(FairPrimaryGenerator* primGen) override; - - void SetVerbose(Int_t verb) { mVerbose = verb; }; - - private: - const Char_t* mFileName; //! Input file Name - FILE* mInputFile; //! File - Int_t mVerbose; //! Verbose Level - - /** Private method CloseInput. Just for convenience. Closes the - ** input file properly. Called from destructor and from ReadEvent. **/ - void CloseInput(); - - /** PDG data base */ - - // TDatabasePDG *mPDG; //! - - ClassDefOverride(Pythia6Generator, 1); -}; - -} // namespace eventgen -} // namespace o2 -#endif diff --git a/Generators/include/Generators/Pythia8Generator.h b/Generators/include/Generators/Pythia8Generator.h deleted file mode 100644 index 9b60415dd5504..0000000000000 --- a/Generators/include/Generators/Pythia8Generator.h +++ /dev/null @@ -1,87 +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. - -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence version 3 (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ -// ------------------------------------------------------------------------- -// ----- M. Al-Turany June 2014 ----- -// ------------------------------------------------------------------------- - -#ifndef PNDP8GENERATOR_H -#define PNDP8GENERATOR_H 1 - -#include "FairGenerator.h" // for FairGenerator -#include "Rtypes.h" // for Double_t, Bool_t, Int_t, etc -#include <memory> - -class FairPrimaryGenerator; -namespace Pythia8 -{ -class Pythia; -class RndmEngine; -} // namespace Pythia8 -namespace o2 -{ -namespace eventgen -{ - -class Pythia8Generator : public FairGenerator -{ - public: - /** default constructor **/ - Pythia8Generator(); - - /** destructor **/ - ~Pythia8Generator() override; - - /** public method ReadEvent **/ - Bool_t ReadEvent(FairPrimaryGenerator*) override; - void SetParameters(const char*); - void Print(); //! - - Bool_t Init() override; //! - - void SetMom(Double_t mom) { mMom = mom; }; - void SetId(Double_t id) { mId = id; }; - void SetHNLId(Int_t id) { mHNL = id; }; - void UseRandom1() - { - mUseRandom1 = kTRUE; - mUseRandom3 = kFALSE; - }; - void UseRandom3() - { - mUseRandom1 = kFALSE; - mUseRandom3 = kTRUE; - }; - void GetPythiaInstance(int); - - private: - std::unique_ptr<Pythia8::Pythia> mPythia; //! - std::unique_ptr<Pythia8::RndmEngine> mRandomEngine; //! - - protected: - Double_t mMom; // proton momentum - Int_t mHNL; // HNL ID - Int_t mId; // target type - Bool_t mUseRandom1; // flag to use TRandom1 - Bool_t mUseRandom3; // flag to use TRandom3 (default) - - ClassDefOverride(Pythia8Generator, 1); -}; - -} // namespace eventgen -} // namespace o2 -#endif /* !PNDP8GENERATOR_H */ diff --git a/Generators/src/Pythia6Generator.cxx b/Generators/src/Pythia6Generator.cxx deleted file mode 100644 index 3a84114b30c22..0000000000000 --- a/Generators/src/Pythia6Generator.cxx +++ /dev/null @@ -1,146 +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. - -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence version 3 (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ -// ------------------------------------------------------------------------- -// ----- M. Al-Turany June 2014 ----- -// ------------------------------------------------------------------------- -// ------------------------------------------------------------------------- -// ----- Pythia6Generator source file ----- -// ----- Created 08/08/08 by S. Spataro ----- -// ------------------------------------------------------------------------- -#include "Generators/Pythia6Generator.h" - -#include "FairPrimaryGenerator.h" - -#include <iostream> -#include <cstdio> - -using std::cout; -using std::endl; -using std::max; -namespace o2 -{ -namespace eventgen -{ - -// ----- Default constructor ------------------------------------------ -Pythia6Generator::Pythia6Generator() = default; -// ------------------------------------------------------------------------ - -// ----- Standard constructor ----------------------------------------- -Pythia6Generator::Pythia6Generator(const char* fileName) - : mFileName(fileName), mInputFile(nullptr), mVerbose(0) -{ - cout << "-I Pythia6Generator: Opening input file " << mFileName << endl; - if ((mInputFile = fopen(mFileName, "r")) == nullptr) { - Fatal("Pythia6Generator", "Cannot open input file."); - } - - // mPDG=TDatabasePDG::Instance(); -} -// ------------------------------------------------------------------------ - -// ----- Destructor --------------------------------------------------- -Pythia6Generator::~Pythia6Generator() -{ - CloseInput(); -} -// ------------------------------------------------------------------------ - -// ----- Public method ReadEvent -------------------------------------- -Bool_t Pythia6Generator::ReadEvent(FairPrimaryGenerator* primGen) -{ - - // Check for input file - if (!mInputFile) { - // if ( ! mInputFile->is_open() ) { - cout << "-E Pythia6Generator: Input file not open!" << endl; - return kFALSE; - } - - // Define event variable to be read from file - Int_t ntracks = 0, eventID = 0, ncols = 0; - - // Define track variables to be read from file - Int_t nLev = 0, pdgID = 0, nM1 = -1, nM2 = -1, nDF = -1, nDL = -1; - Float_t fPx = 0., fPy = 0., fPz = 0., fM = 0., fE = 0.; - Float_t fVx = 0., fVy = 0., fVz = 0., fT = 0.; - - // Read event header line from input file - - Int_t max_nr = 0; - - Text_t buffer[200]; - ncols = fscanf(mInputFile, "%d\t%d", &eventID, &ntracks); - - if (ncols && ntracks > 0) { - - if (mVerbose > 0) - cout << "Event number: " << eventID << "\tNtracks: " << ntracks << endl; - - for (Int_t ll = 0; ll < ntracks; ll++) { - ncols = fscanf(mInputFile, "%d %d %d %d %d %d %f %f %f %f %f %f %f %f %f", &nLev, &pdgID, &nM1, &nM2, &nDF, &nDL, &fPx, &fPy, &fPz, &fE, &fM, &fVx, &fVy, &fVz, &fT); - if (mVerbose > 0) - cout << nLev << "\t" << pdgID << "\t" << nM1 << "\t" << nM2 << "\t" << nDF << "\t" << nDL << "\t" << fPx << "\t" << fPy << "\t" << fPz << "\t" << fE << "\t" << fM << "\t" << fVx << "\t" << fVy << "\t" << fVz << "\t" << fT << endl; - if (nLev == 1) - primGen->AddTrack(pdgID, fPx, fPy, fPz, fVx, fVy, fVz); - } - } else { - cout << "-I Pythia6Generator: End of input file reached " << endl; - CloseInput(); - return kFALSE; - } - - // If end of input file is reached : close it and abort run - if (feof(mInputFile)) { - cout << "-I Pythia6Generator: End of input file reached " << endl; - CloseInput(); - return kFALSE; - } - - /* - cout << "-I Pythia6Generator: Event " << eventID << ", vertex = (" - << vx << "," << vy << "," << vz << ") cm, multiplicity " - << ntracks << endl; - */ - - return kTRUE; -} -// ------------------------------------------------------------------------ - -// ----- Private method CloseInput ------------------------------------ -void Pythia6Generator::CloseInput() -{ - if (mInputFile) { - //if ( mInputFile->is_open() ) { - { - cout << "-I Pythia6Generator: Closing input file " - << mFileName << endl; - // mInputFile->close(); - - fclose(mInputFile); - } - delete mInputFile; - mInputFile = nullptr; - } -} -// ------------------------------------------------------------------------ - -} // namespace eventgen -} // namespace o2 - -ClassImp(o2::eventgen::Pythia6Generator); diff --git a/Generators/src/Pythia8Generator.cxx b/Generators/src/Pythia8Generator.cxx deleted file mode 100644 index 3e6f8a59990a1..0000000000000 --- a/Generators/src/Pythia8Generator.cxx +++ /dev/null @@ -1,196 +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. - -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence version 3 (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ -// ------------------------------------------------------------------------- -// ----- M. Al-Turany June 2014 ----- -// ------------------------------------------------------------------------- - -#include <cmath> -#include "TROOT.h" -#include "Pythia8/Basics.h" // for RndmEngine -#include "Pythia8/Pythia.h" -#include "FairPrimaryGenerator.h" -#include "FairGenerator.h" -#include "TRandom.h" // for TRandom -#include "TRandom1.h" // for TRandom1 -#include "TRandom3.h" // for TRandom3, gRandom - -#include "Generators/Pythia8Generator.h" - -using namespace Pythia8; - -namespace o2 -{ -namespace eventgen -{ - -class PyTr1Rng : public RndmEngine -{ - public: - PyTr1Rng() { mRng = std::make_unique<TRandom1>(gRandom->GetSeed()); }; - ~PyTr1Rng() override = default; - - Double_t flat() override { return mRng->TRandom1::Rndm(); }; - - private: - std::unique_ptr<TRandom1> mRng; //! -}; - -class PyTr3Rng : public RndmEngine -{ - public: - PyTr3Rng() { mRng = std::make_unique<TRandom3>(gRandom->GetSeed()); }; - ~PyTr3Rng() override = default; - - Double_t flat() override { return mRng->TRandom3::Rndm(); }; - - private: - std::unique_ptr<TRandom3> mRng; //! -}; - -// ----- Default constructor ------------------------------------------- -Pythia8Generator::Pythia8Generator() -{ - mUseRandom1 = kFALSE; - mUseRandom3 = kTRUE; - mId = 2212; // proton - mMom = 400; // proton - mHNL = 0; // HNL if set to !=0, for example 9900014, only track - mPythia = std::make_unique<Pythia>(); -} -// ------------------------------------------------------------------------- - -// ----- Default constructor ------------------------------------------- -Bool_t Pythia8Generator::Init() -{ - if (mUseRandom1) { - mRandomEngine = std::make_unique<PyTr1Rng>(); - } - if (mUseRandom3) { - mRandomEngine = std::make_unique<PyTr3Rng>(); - } - mPythia->setRndmEnginePtr(mRandomEngine.get()); - - /** commenting these lines - as they would override external settings **/ - /** - cout<<"Beam Momentum "<<fMom<<endl; - // Set arguments in Settings database. - mPythia.settings.mode("Beams:idA", fId); - mPythia.settings.mode("Beams:idB", 2212); - mPythia.settings.mode("Beams:frameType", 3); - mPythia.settings.parm("Beams:pxA", 0.); - mPythia.settings.parm("Beams:pyA", 0.); - mPythia.settings.parm("Beams:pzA", fMom); - mPythia.settings.parm("Beams:pxB", 0.); - mPythia.settings.parm("Beams:pyB", 0.); - mPythia.settings.parm("Beams:pzB", 0.); - **/ - mPythia->init(); - return kTRUE; -} -// ------------------------------------------------------------------------- - -// ----- Destructor ---------------------------------------------------- -Pythia8Generator::~Pythia8Generator() = default; -// ------------------------------------------------------------------------- - -// ----- Passing the event --------------------------------------------- -Bool_t Pythia8Generator::ReadEvent(FairPrimaryGenerator* cpg) -{ - const double mm2cm = 0.1; - const double clight = 2.997924580e10; //cm/c - Int_t npart = 0; - while (npart == 0) { - mPythia->next(); - for (int i = 0; i < mPythia->event.size(); i++) { - if (mPythia->event[i].isFinal()) { - // only send HNL decay products to G4 - if (mHNL != 0) { - Int_t im = mPythia->event[i].mother1(); - if (mPythia->event[im].id() == mHNL) { - // for the moment, hardcode 110m is maximum decay length - Double_t z = mPythia->event[i].zProd(); - Double_t x = abs(mPythia->event[i].xProd()); - Double_t y = abs(mPythia->event[i].yProd()); - // cout<<"debug HNL decay pos "<<x<<" "<< y<<" "<< z <<endl; - if (z < 11000. && z > 7000. && x < 250. && y < 250.) { - npart++; - } - } - } else { - npart++; - } - }; - }; - // happens if a charm particle being produced which does decay without producing a HNL. Try another event. - // if (npart == 0){ mPythia->event.list();} - }; - // cout<<"debug p8 event 0 " << mPythia->event[0].id()<< " "<< mPythia->event[1].id()<< " " - // << mPythia->event[2].id()<< " "<< npart <<endl; - for (Int_t ii = 0; ii < mPythia->event.size(); ii++) { - Bool_t wanttracking = true; - if (!mPythia->event[ii].isFinal()) - wanttracking = false; - Double_t z = mPythia->event[ii].zProd(); - Double_t x = mPythia->event[ii].xProd(); - Double_t y = mPythia->event[ii].yProd(); - Double_t pz = mPythia->event[ii].pz(); - Double_t px = mPythia->event[ii].px(); - Double_t py = mPythia->event[ii].py(); - Double_t t = mPythia->event[ii].tProd(); - x *= mm2cm; - y *= mm2cm; - z *= mm2cm; - t *= mm2cm / clight; - Double_t e = -9e9; - // handle system entry separately - if (!wanttracking) - e = mPythia->event[ii].e(); - // - printf("AddTrack from Pythia8 %5d \n", (Int_t)mPythia->event[ii].id()); - cpg->AddTrack((Int_t)mPythia->event[ii].id(), px, py, pz, x, y, z, - (Int_t)mPythia->event[ii].mother1(), wanttracking, e, t); - } // particle lloop - - return kTRUE; -} -// ------------------------------------------------------------------------- -void Pythia8Generator::SetParameters(const char* par) -{ - // Set Parameters - mPythia->readString(par); - cout << R"(mPythia->readString(")" << par << R"("))" << endl; -} - -// ------------------------------------------------------------------------- -void Pythia8Generator::Print() -{ - mPythia->settings.listAll(); -} -// ------------------------------------------------------------------------- -void Pythia8Generator::GetPythiaInstance(int arg) -{ - mPythia->particleData.list(arg); - cout << "canDecay " << mPythia->particleData.canDecay(arg) << " " << mPythia->particleData.mayDecay(arg) << endl; -} -// ------------------------------------------------------------------------- - -} // namespace eventgen -} // namespace o2 - -ClassImp(o2::eventgen::Pythia8Generator); From aef366ae6185d3bac4c56693d18f44037fdc0289 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 2 Dec 2020 11:34:12 +0100 Subject: [PATCH 1516/1751] Mark method final since it implements a framework for deriving classes --- Generators/include/Generators/Generator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Generators/include/Generators/Generator.h b/Generators/include/Generators/Generator.h index 9f8d3a23c1085..9d745eb4825cd 100644 --- a/Generators/include/Generators/Generator.h +++ b/Generators/include/Generators/Generator.h @@ -59,7 +59,7 @@ class Generator : public FairGenerator *@param pStack The stack *@return kTRUE if successful, kFALSE if not **/ - Bool_t ReadEvent(FairPrimaryGenerator* primGen) override; + Bool_t ReadEvent(FairPrimaryGenerator* primGen) final; /** setters **/ void setMomentumUnit(double val) { mMomentumUnit = val; }; From cae64389ccf3210c6deeeca278d0fee14db94393 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Wed, 2 Dec 2020 11:36:24 +0100 Subject: [PATCH 1517/1751] Improve event generation starting from O2 kinematics Now all mother relations should be preserved - just as if coming from an original event generator like Pythia8 --- .../include/Generators/GeneratorFromFile.h | 16 +++---- Generators/src/GeneratorFromFile.cxx | 45 +++++++++++-------- run/SimExamples/JustPrimaryKinematics/run.sh | 0 3 files changed, 35 insertions(+), 26 deletions(-) mode change 100644 => 100755 run/SimExamples/JustPrimaryKinematics/run.sh diff --git a/Generators/include/Generators/GeneratorFromFile.h b/Generators/include/Generators/GeneratorFromFile.h index 1c7f3eac878e3..2e2da9c8025e2 100644 --- a/Generators/include/Generators/GeneratorFromFile.h +++ b/Generators/include/Generators/GeneratorFromFile.h @@ -14,6 +14,7 @@ #define ALICEO2_GENERATORFROMFILE_H_ #include "FairGenerator.h" +#include "Generators/Generator.h" class TBranch; class TFile; @@ -60,19 +61,18 @@ class GeneratorFromFile : public FairGenerator /// This class implements a generic FairGenerator which /// reads the particles from an external O2 sim kinematics file. -class GeneratorFromO2Kine : public FairGenerator +class GeneratorFromO2Kine : public o2::eventgen::Generator { public: GeneratorFromO2Kine() = default; GeneratorFromO2Kine(const char* name); - // the FairGenerator interface methods - - /** Generates (or reads) one event and adds the tracks to the - ** injected primary generator instance. - ** @param primGen pointer to the primary FairPrimaryGenerator - **/ - bool ReadEvent(FairPrimaryGenerator* primGen) override; + // the o2 Generator interface methods + bool generateEvent() override + { /* trivial - actual work in importParticles */ + return true; + } + bool importParticles() override; // Set from which event to start void SetStartEvent(int start); diff --git a/Generators/src/GeneratorFromFile.cxx b/Generators/src/GeneratorFromFile.cxx index 2afa5699798e3..afbe1ad109dc6 100644 --- a/Generators/src/GeneratorFromFile.cxx +++ b/Generators/src/GeneratorFromFile.cxx @@ -187,7 +187,7 @@ void GeneratorFromO2Kine::SetStartEvent(int start) } } -Bool_t GeneratorFromO2Kine::ReadEvent(FairPrimaryGenerator* primGen) +bool GeneratorFromO2Kine::importParticles() { // NOTE: This should be usable with kinematics files without secondaries // It might need some adjustment to make it work with secondaries or to continue @@ -200,21 +200,30 @@ Bool_t GeneratorFromO2Kine::ReadEvent(FairPrimaryGenerator* primGen) mEventBranch->SetAddress(&tracks); mEventBranch->GetEntry(mEventCounter); - for (auto& p : *tracks) { - auto pdgid = p.GetPdgCode(); - auto px = p.Px(); - auto py = p.Py(); - auto pz = p.Pz(); - auto vx = p.Vx(); - auto vy = p.Vy(); - auto vz = p.Vz(); - auto parent = p.getMotherTrackId(); - auto e = p.GetEnergy(); - auto tof = p.T(); - auto weight = 1.; // p.GetWeight() ??; - auto wanttracking = p.getToBeDone(); - LOG(DEBUG) << "Putting primary " << pdgid; - primGen->AddTrack(pdgid, px, py, pz, vx, vy, vz, parent, wanttracking, e, tof, weight); + for (auto& t : *tracks) { + // I guess we only want primaries (unless later on we continue a simulation) + if (!t.isPrimary()) { + continue; + } + + auto pdg = t.GetPdgCode(); + auto px = t.Px(); + auto py = t.Py(); + auto pz = t.Pz(); + auto vx = t.Vx(); + auto vy = t.Vy(); + auto vz = t.Vz(); + auto m1 = t.getMotherTrackId(); + auto m2 = t.getSecondMotherTrackId(); + auto d1 = t.getFirstDaughterTrackId(); + auto d2 = t.getLastDaughterTrackId(); + auto e = t.GetEnergy(); + auto vt = t.T(); + auto weight = 1.; // p.GetWeight() ?? + auto wanttracking = t.getToBeDone(); + LOG(DEBUG) << "Putting primary " << pdg; + + mParticles.push_back(TParticle(pdg, wanttracking, m1, m2, d1, d2, px, py, pz, e, vx, vy, vz, vt)); particlecounter++; } mEventCounter++; @@ -224,11 +233,11 @@ Bool_t GeneratorFromO2Kine::ReadEvent(FairPrimaryGenerator* primGen) } LOG(INFO) << "Event generator put " << particlecounter << " on stack"; - return kTRUE; + return true; } else { LOG(ERROR) << "GeneratorFromO2Kine: Ran out of events\n"; } - return kFALSE; + return false; } } // namespace eventgen diff --git a/run/SimExamples/JustPrimaryKinematics/run.sh b/run/SimExamples/JustPrimaryKinematics/run.sh old mode 100644 new mode 100755 From eb66dd352c2858f1074a50bc8b1c934a3985a852 Mon Sep 17 00:00:00 2001 From: Sean <hamiltonthomas@gmail.com> Date: Wed, 23 Sep 2020 10:48:14 +0200 Subject: [PATCH 1518/1751] trd trapsimulator code refactor and unit fix --- .../TRD/include/DataFormatsTRD/LinkRecord.h | 43 +- .../TRD/include/DataFormatsTRD/RawData.h | 3 +- .../TRD/include/DataFormatsTRD/Tracklet64.h | 2 + .../Detectors/TRD/src/DataFormatsTRDLinkDef.h | 1 - DataFormats/Detectors/TRD/src/LinkRecord.cxx | 15 +- DataFormats/Detectors/TRD/src/RawData.cxx | 8 + Detectors/TRD/base/macros/OCDB2CCDB.C | 5 +- .../TRD/base/macros/OCDB2CCDBTrapConfig.C | 8 +- .../include/TRDSimulation/TrapSimulator.h | 97 ++- .../TRD/simulation/src/TRDSimulationLinkDef.h | 5 + .../TRD/simulation/src/TrapSimulator.cxx | 583 +++++++++++------- .../TRDWorkflow/TRDTrapSimulatorSpec.h | 3 +- .../TRD/workflow/src/TRDTrapSimulatorSpec.cxx | 127 ++-- 13 files changed, 576 insertions(+), 324 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h index dccb1a4f73532..0c5db1563b11f 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h @@ -30,19 +30,6 @@ class LinkRecord { using DataRange = o2::dataformats::RangeReference<int>; - struct LinkId { - 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; - }; - }; - }; - public: LinkRecord() = default; LinkRecord(const uint32_t linkid, int firstentry, int nentries) : mDataRange(firstentry, nentries) { mLinkId = linkid; } @@ -52,24 +39,40 @@ class LinkRecord ~LinkRecord() = default; void setLinkId(const uint32_t linkid) { mLinkId = linkid; } - // void setLinkId(const LinkId linkid) { mLinkId = linkid; } 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); } + void setSector(const int sector) { mLinkId |= ((sector << supermodulebs) & supermodulemask); } + void setStack(const int stack) { mLinkId |= ((stack << stackbs) & stackmask); } + void setLayer(const int layer) { mLinkId |= ((layer << layerbs) & layermask); } + void setSide(const int side) { mLinkId |= ((side << sidebs) & sidemask); } + void setSpare(const int spare = 0) { mLinkId |= ((spare << sparebs) & sparemask); } const uint32_t getLinkId() { return mLinkId; } //TODO come backwith a ccdb lookup. const uint32_t getLinkHCID() { return mLinkId & 0x7ff; } // the last 11 bits. - const uint32_t getSector() { return (mLinkId & 0xf800) >> 11; } - const uint32_t getStack() { return (mLinkId & 0x700) >> 8; } - const uint32_t getLayer() { return (mLinkId & 0xe0) >> 5; } - const uint32_t getSide() { return (mLinkId & 0x10) >> 4; } + const uint32_t getSector() { return (mLinkId & supermodulemask) >> supermodulebs; } + const uint32_t getStack() { return (mLinkId & stackmask) >> stackbs; } + const uint32_t getLayer() { return (mLinkId & layermask) >> layerbs; } + const uint32_t getSide() { return (mLinkId & sidemask) >> sidebs; } 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); + // bit masks for the above raw data; + static constexpr uint64_t sparemask = 0x000f; + static constexpr uint64_t sidemask = 0x0010; + static constexpr uint64_t layermask = 0x00e0; + static constexpr uint64_t stackmask = 0x0700; + static constexpr uint64_t supermodulemask = 0xf800; + //bit shifts for the above raw data + static constexpr uint64_t sparebs = 0; + static constexpr uint64_t sidebs = 4; + static constexpr uint64_t layerbs = 5; + static constexpr uint64_t stackbs = 8; + static constexpr uint64_t supermodulebs = 11; private: uint16_t mLinkId; @@ -81,10 +84,8 @@ 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 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 678138301c9d6..b14c8d220c8ad 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -182,7 +182,7 @@ struct TrackletMCMHeader { // \structure TrackletMCMData. // \brief Raw Data of a tracklet, part is how ever in the MCM Header hence both are grouped together in the same file -struct TrackletMCMData { // This is a bad name as part of the tracklet data is in the MCMHeader. +struct TrackletMCMData { union { uint32_t word; struct { @@ -223,6 +223,7 @@ void buildTrackletHCHeaderd(TrackletHCHeader& header, int detector, int rob, int 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); +void buildTrackletMCMData(TrackletMCMData& trackletword, const uint slope, const uint pos, const uint q0, const uint q1, const uint q2); uint32_t unpacklinkinfo(const HalfCRUHeader& cruhead, const uint32_t link, const bool data); uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link); uint32_t getlinkdatasize(const HalfCRUHeader& cruhead, const uint32_t link); diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h index ef4a8f401ed80..fe3ed80fdfba1 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h @@ -58,6 +58,7 @@ class Tracklet64 } ~Tracklet64() = default; + Tracklet64& operator=(const Tracklet64& rhs) = default; //TODO convert to the actual number regarding compliments. // ----- Getters for contents of tracklet word ----- @@ -73,6 +74,7 @@ class Tracklet64 uint64_t buildTrackletWord(uint64_t format, uint64_t hcid, uint64_t padrow, uint64_t col, uint64_t position, uint64_t slope, uint64_t Q2, uint64_t Q1, uint64_t Q0) { + LOG(debug) << "Build tracklet with format:" << format << " hcid:" << hcid << " padrow: " << padrow << " col:" << col << " position:" << position << " slope:" << slope << " Q0:1:2:: " << Q0 << ":" << Q1 << ":" << Q2; mtrackletWord = ((format << formatbs) & formatmask) + ((hcid << hcidbs) & hcidmask) + ((padrow << padrowbs) & padrowmask) + ((col << colbs) & colmask) + ((position << posbs) & posmask) + ((slope << slopebs) & slopemask) + ((Q2 << Q2bs) & Q2mask) + ((Q1 << Q1bs) & Q1mask) + ((Q0 << Q0bs) & Q0mask); return 0; } diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index e21390345f4c7..4fe89c45df5ff 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -16,7 +16,6 @@ #pragma link C++ class o2::trd::TriggerRecord + ; #pragma link C++ class o2::trd::LinkRecord + ; -#pragma link C++ struct o2::trd::LinkRecord::LinkId + ; #pragma link C++ struct o2::trd::HalfCRUHeader + ; #pragma link C++ struct o2::trd::TrackletHCHeader + ; #pragma link C++ struct o2::trd::TrackletMCMHeader + ; diff --git a/DataFormats/Detectors/TRD/src/LinkRecord.cxx b/DataFormats/Detectors/TRD/src/LinkRecord.cxx index e4d75a231fa5a..ba2fb389a903e 100644 --- a/DataFormats/Detectors/TRD/src/LinkRecord.cxx +++ b/DataFormats/Detectors/TRD/src/LinkRecord.cxx @@ -29,17 +29,18 @@ uint32_t LinkRecord::getHalfChamberLinkId(uint32_t detector, uint32_t rob) uint32_t LinkRecord::getHalfChamberLinkId(uint32_t sector, uint32_t stack, uint32_t layer, uint32_t side) { - LinkRecord tmplinkid; - tmplinkid.setLinkId(sector, stack, layer, side); - return tmplinkid.getLinkId(); + LinkRecord a; + a.setLinkId(sector, stack, layer, side); + return a.mLinkId; } void LinkRecord::setLinkId(const uint32_t sector, const uint32_t stack, const uint32_t layer, const uint32_t side) { - mLinkId |= sector << 11; - mLinkId |= stack << 8; - mLinkId |= layer << 5; - mLinkId |= side << 4; + setSector(sector); + setStack(stack); + setLayer(layer); + setSide(side); + setSpare(); } void LinkRecord::printStream(std::ostream& stream) diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index a67094bc98e6f..7668b3a47462a 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -50,6 +50,14 @@ uint16_t buildTRDFeeID(int supermodule, int side, int endpoint) return feeid.word; } +void buildTrackletMCMData(TrackletMCMData& trackletword, const uint slope, const uint pos, const uint q0, const uint q1, const uint q2) +{ + trackletword.slope = slope; + trackletword.pos = pos; + trackletword.pid = q0 | ((q1 & 0xff) << 8); //q2 sits with a bit of q1 in the header pid word. + trackletword.checkbit = 1; +} + uint32_t getlinkerrorflag(const HalfCRUHeader& cruhead, const uint32_t link) { // link is the link you are requesting information on, 0-14 diff --git a/Detectors/TRD/base/macros/OCDB2CCDB.C b/Detectors/TRD/base/macros/OCDB2CCDB.C index ae27dbfafc420..3f2b691370e6c 100644 --- a/Detectors/TRD/base/macros/OCDB2CCDB.C +++ b/Detectors/TRD/base/macros/OCDB2CCDB.C @@ -25,7 +25,7 @@ // alienv enter VO_ALICE@O2::latest-O2-o2,VO_ALICE@AliRoot::latest-O2-o2 // according to my configs, modify as required of course. // - +#if !defined(__CINT__) || defined(__MAKECINT__) #include <iostream> #include <fstream> #include <string> @@ -78,11 +78,12 @@ #include "TRDBase/CalOnlineGainTables.h" #include "TRDBase/FeeParam.h" #include "TRDSimulation/TrapConfig.h" +#include "DataFormatsTRD/Constants.h" +#endif using namespace std; using namespace o2::ccdb; using namespace o2::trd; - // global variables // histograms used for extracting the mean and RMS of calibration parameters diff --git a/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C b/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C index 0121e3d1c4ed2..0b6a5f0bcfe61 100644 --- a/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C +++ b/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C @@ -207,7 +207,7 @@ its all going here unfortunately .... */ vector<std::string> run2confignames = { - /* "cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5505", + "cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5505", "cf_pg-fpnp32_zs-s16-deh_tb24_trkl-b2p-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5585", "cf_pg-fpnp32_zs-s16-deh_tb24_trkl-b5p-fs1e24-ht200-qs0e23s23e22-pidlhc11dv3en-pt100_ptrg.r5766", "cf_pg-fpnp32_zs-s16-deh_tb24_trkl-b0-fs1e24-ht200-qs0e23s23e22-pidlhc11dv3en_ptrg.r5767", @@ -261,7 +261,7 @@ its all going here unfortunately .... "cf_pg-fpnp32_zs-s16-deh_tb26_trkl-b2n-fs1e24-ht200-qs0e23s23e22-pidlhc11dv3en-pt100_ptrg.r5771", "cf_pg-fpnp32_zs-s16-deh_tb24_trkl-b5n-fs1e24-ht200-qs0e23s23e22-pidlhc11dv1-pt100_ptrg.r5762", "cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b0-fs1e24-ht200-qs0e24s24e23-pidlinear_ptrg.r5505", - "cf_pg-fpnp32_zs-s16-deh_tb24_trkl-b0-fs1e24-ht200-qs0e23s23e22-pidlhc11dv1_ptrg.r5762",*/ + "cf_pg-fpnp32_zs-s16-deh_tb24_trkl-b0-fs1e24-ht200-qs0e23s23e22-pidlhc11dv1_ptrg.r5762", "cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"}; // now we loop over these extracting the trapconfing and dumping it into the ccdb. @@ -270,10 +270,10 @@ its all going here unfortunately .... if ((entry = GetCDBentry("TRD/Calib/TrapConfig", 0))) { if ((run2caltrapconfig = (AliTRDCalTrapConfig*)entry->GetObject())) { for (auto const& run2trapconfigname : run2confignames) { - auto o2trapconfig = new TrapConfig(run2trapconfigname); + auto o2trapconfig = new TrapConfig(); run2trapconfig = run2caltrapconfig->Get(run2trapconfigname.c_str()); ParseTrapConfigs(o2trapconfig, run2trapconfig); - // ccdb.storeAsTFileAny(o2trapconfig, "TRD_test/TrapConfig2020/c", metadata, 1, 1670700184549); //upper time chosen into the future else the server simply adds a year + ccdb.storeAsTFileAny(o2trapconfig, "TRD_test/TrapConfig", metadata, 1, 1670700184549); //upper time chosen into the future else the server simply adds a year // cout << "ccdb.storeAsTFileAny(o2trapconfig, Form(\"" << TRDCalBase.c_str() << "/TrapConfig/" << run2trapconfigname.c_str()<< endl; //upper time chosen into the future else the server simply adds a year //AliTRDcalibDB *calibdb=AliTRDcalibDB::Instance(); } diff --git a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h index 76bfd284d3c5f..82ae9bde7795d 100644 --- a/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h +++ b/Detectors/TRD/simulation/include/TRDSimulation/TrapSimulator.h @@ -23,17 +23,14 @@ #include <fstream> #include <gsl/span> -#include "TRDBase/Tracklet.h" #include "TRDBase/FeeParam.h" #include "TRDBase/Digit.h" -#include "TRDBase/Tracklet.h" #include "TRDSimulation/Digitizer.h" -#include "TRDSimulation/TrapConfigHandler.h" //TODO I think i can dump this. #include "TRDSimulation/TrapConfig.h" #include "TRDBase/MCLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" -//#include "DataFormatsTRD/RawData.h" #include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/RawData.h" #include "DataFormatsTRD/Constants.h" class TH2F; @@ -89,12 +86,16 @@ class TrapSimulator tmplabel.clear(); // clear MC Labels sent in from the digits coming in. } mTrackletLabels.clear(); // clear the stored labels. - mTrackletArray.clear(); mTrackletArray64.clear(); + for (auto& trackletdetail : mTrackletDetails) { + trackletdetail.clear(); + } }; - // void setData(int iadc, const std::vector<int>& adc); // set ADC data with array - void setData(int iadc, const ArrayADC& adc, std::vector<o2::MCCompLabel>& labels); // set ADC data with array - //void setData(int iadc, const ArrayADC& adc, gsl::span<o2::MCCompLabel,-1>& labels); // set ADC data with array + // set ADC data with array + // void setData(int iadc, const std::vector<int>& adc); + void setData(int iadc, const ArrayADC& adc, std::vector<o2::MCCompLabel>& labels); + // set ADC data with array + //void setData(int iadc, const ArrayADC& adc, gsl::span<o2::MCCompLabel,-1>& labels); void setBaselines(); // set the baselines as done in setDataByPad which is bypassed due to using setData in line above. void setData(int iadc, int it, int adc); // set ADC data void setDataFromDigitizerAndRun(std::vector<o2::trd::Digit>& data, o2::dataformats::MCTruthContainer<MCLabel>&); // data coming in manually from the the digitizer. @@ -207,7 +208,6 @@ class TrapSimulator static constexpr int mQ2Startbin = 3; // Start range of Q2, for now here. TODO pull from a revised TrapConfig? static constexpr int mQ2Endbin = 5; // End range of Q2, also pull from a revised trapconfig at some point. - std::vector<Tracklet>& getTrackletArray() { return mTrackletArray; } std::vector<Tracklet64>& getTrackletArray64() { return mTrackletArray64; } void getTracklet64s(std::vector<Tracklet64>& TrackletStore); // place the trapsim 64 bit tracklets nto the incoming vector o2::dataformats::MCTruthContainer<o2::MCCompLabel>& getTrackletLabels() { return mTrackletLabels; } @@ -240,9 +240,10 @@ class TrapSimulator mQtot = 0; mYpos = 0; } - }; //mHits[mgkNHitsMC]; - //std::array<Hit, 50> mHits; + }; + std::array<Hit, mgkNHitsMC> mHits{}; // was 100 in the run2 via fgkNHitsMC; + class FilterReg { public: @@ -271,7 +272,7 @@ class TrapSimulator int mNhits; // number of hits unsigned int mQ0; // charge accumulated in first window unsigned int mQ1; // charge accumulated in second window - unsigned int mQ2; // charge accumulated in some other windows TODO find or write the documentation for window3 + unsigned int mQ2; // charge accumulated in third windows currently timebin 3 to 5 unsigned int mSumX; // sum x int mSumY; // sum y unsigned int mSumX2; // sum x**2 @@ -289,8 +290,63 @@ class TrapSimulator mSumY2 = 0; mSumXY = 0; } + void Print() + { + LOG(info) << "FitReg : "; + LOG(info) << "\t Q 0:1:2 : " << mQ0 << ":" << mQ1 << ":" << mQ2; + LOG(info) << "\t SumX:SumY:SumX2:SumY2:SumXY : " << mSumX << ":" << mSumY << ":" << mSumX2 << ":" << mSumY2 << ":" << mSumXY; + } }; std::array<FitReg, constants::NADCMCM> mFitReg{}; + //class to store the tracklet details that are not stored in tracklet64. + //used for later debugging purposes or in depth analysis of some part of tracklet creation or properties. + class TrackletDetail + { + public: + TrackletDetail() = default; + TrackletDetail(float slope, float position, int q0, int q1, int q2, std::array<int, 3> hits, float error) + { + mSlope = slope; + mPosition = position; + mError = error; + mCharges[0] = q0; + mCharges[1] = q1; + mCharges[2] = q2; + mPidHits = hits; + }; + ~TrackletDetail() = default; + std::array<int, 3> mPidHits; // no. of contributing clusters in each pid window. + std::array<int, 3> mCharges; // Q0,Q1,Q2, charges in each pid window. + float mSlope; // tracklet slope + float mPosition; // tracklet offset + float mError; // tracklet error + int mNClusters; // no. of clusters + std::vector<float> mResiduals; //[mNClusters] cluster to tracklet residuals + std::vector<float> mClsCharges; //[mNClusters] cluster charge + void clear() + { + mPidHits[0] = 0; + mPidHits[1] = 0; + mPidHits[2] = 0; + mCharges[0] = 0; + mCharges[1] = 0; + mCharges[2] = 0; + mSlope = 0; + mPosition = 0; + mError = 0; + mNClusters = 0; + mResiduals.clear(); + mClsCharges.clear(); + } + void setHits(std::array<int, 3> hits) { mPidHits = hits; } + + void setClusters(std::vector<float> res, std::vector<float> charges, int nclusters) + { + mResiduals = res; + mClsCharges = charges; + mNClusters = nclusters; + } + }; protected: void setNTimebins(int ntimebins); // allocate data arrays corr. to the no. of timebins @@ -307,9 +363,9 @@ class TrapSimulator std::vector<int> mADCF; // Array with MCM ADC values (Filtered, 12 bit) 2d with dimension mNTimeBin std::array<std::vector<o2::MCCompLabel>, constants::NADCMCM> mADCLabels{}; // MC Labels sent in from the digits coming in. std::vector<unsigned int> mMCMT; // tracklet word for one mcm/trap-chip - std::vector<Tracklet> mTrackletArray; // Array of TRDtrackletMCM which contains MC information in addition to the tracklet word - std::vector<Tracklet64> mTrackletArray64; // Array of TRDtrackletMCM which contains MC information in addition to the tracklet word + std::vector<Tracklet64> mTrackletArray64; // Array of 64 bit tracklets o2::dataformats::MCTruthContainer<o2::MCCompLabel> mTrackletLabels; + std::vector<TrackletDetail> mTrackletDetails; // store additional tracklet information for eventual debug output. std::vector<int> mZSMap; // Zero suppression map (1 dimensional projection) std::array<int, mgkNCPU> mFitPtr{}; // pointer to the tracklet to be calculated by CPU i @@ -317,9 +373,8 @@ class TrapSimulator std::string mTrklBranchName; // name of the tracklet branch to write to // Parameter classes - FeeParam* mFeeParam; // FEE parameters + FeeParam* mFeeParam; // FEE parameters, a singleton TrapConfig* mTrapConfig; // TRAP config - TrapConfigHandler mTrapConfigHandler; // CalOnlineGainTables mGainTable; static const int NOfAdcPerMcm = constants::NADCMCM; @@ -354,12 +409,20 @@ class TrapSimulator static int mgAddBaseline; // add baseline to the ADC values static bool mgStoreClusters; // whether to store all clusters in the tracklets + + bool mdebugStream = false; // whether or not to keep all the additional info for eventual dumping to a tree. + bool mDataIsSet = false; - Calibrations* mCalib; + Calibrations* mCalib; // connection to caiibrations class to pull in info from ccdb. + + std::array<TrackletMCMData, 3> mTracklets; + TrackletMCMHeader mMCMHeader; static constexpr bool debugheaders = false; }; std::ostream& operator<<(std::ostream& os, const TrapSimulator& mcm); +std::ostream& operator<<(std::ostream& os, TrapSimulator::FitReg& fitreg); + } //namespace trd } //namespace o2 #endif diff --git a/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h b/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h index 851660dbdd90c..c95cf85cc2465 100644 --- a/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h +++ b/Detectors/TRD/simulation/src/TRDSimulationLinkDef.h @@ -25,6 +25,11 @@ #pragma link C++ class o2::trd::TrapConfig::TrapDmemWord + ; #pragma link C++ class o2::trd::TrapConfig::TrapRegister + ; #pragma link C++ class o2::trd::TrapSimulator + ; +// dictionaries for the internal classes of TrapSimulator are needed for the debug output +#pragma link C++ class o2::trd::TrapSimulator::TrackletDetail + ; +#pragma link C++ class o2::trd::TrapSimulator::Hit + ; +#pragma link C++ class o2::trd::TrapSimulator::FitReg + ; +#pragma link C++ class o2::trd::TrapSimulator::FilterReg + ; #pragma link C++ class o2::trd::Trap2CRU + ; #pragma link C++ class o2::trd::TRDSimParams + ; diff --git a/Detectors/TRD/simulation/src/TrapSimulator.cxx b/Detectors/TRD/simulation/src/TrapSimulator.cxx index 793a2d3a2ef0f..11d1a0f51b9bc 100644 --- a/Detectors/TRD/simulation/src/TrapSimulator.cxx +++ b/Detectors/TRD/simulation/src/TrapSimulator.cxx @@ -21,7 +21,6 @@ #include "TRDBase/CommonParam.h" #include "TRDBase/Geometry.h" #include "TRDBase/FeeParam.h" -#include "TRDBase/Tracklet.h" #include "TRDBase/CalOnlineGainTables.h" #include "TRDSimulation/TrapConfigHandler.h" #include "TRDSimulation/TrapConfig.h" @@ -50,12 +49,13 @@ #include "TRandom3.h" #include <ostream> #include <fstream> +#include <numeric> using namespace o2::trd; using namespace std; using namespace o2::trd::constants; -#define DEBUGTRAP 1 +#define infoTRAP 1 bool TrapSimulator::mgApplyCut = true; int TrapSimulator::mgAddBaseline = 0; @@ -68,7 +68,6 @@ TrapSimulator::TrapSimulator() { // // TrapSimulator default constructor - // By default, nothing is initialized. // It is necessary to issue init before use. mFitPtr[0] = 0; @@ -86,7 +85,7 @@ void TrapSimulator::init(TrapConfig* trapconfig, int det, int robPos, int mcmPos // memory is allocated in the first initialization // // - LOG(debug4) << " : trap sim is at : 0x" << hex << trapconfig; + LOG(debug) << " : trap sim is at : 0x" << hex << trapconfig; if (!mInitialized) { mFeeParam = FeeParam::instance(); mTrapConfig = trapconfig; @@ -141,6 +140,11 @@ void TrapSimulator::reset() for (auto filterreg : mInternalFilterRegisters) { filterreg.ClearReg(); } + // clear the tracklet detail information. + for (auto trackletdetail : mTrackletDetails) { + trackletdetail.clear(); + } + // Default unread, low active bit mask // Default unread, low active bit mask memset(&mZSMap[0], 0, sizeof(mZSMap[0]) * NADCMCM); memset(&mMCMT[0], 0, sizeof(mMCMT[0]) * mgkMaxTracklets); @@ -316,7 +320,7 @@ void TrapSimulator::printFitRegXml(ostream& os) const void TrapSimulator::printTrackletsXml(ostream& os) const { // print tracklets in XML format - + //TODO FIX this to new format const char* const cmdid{R"(" cmdid="0">)"}; os << "<nginject>" << std::endl; os << "<ack roc=\"" << mDetector << cmdid << std::endl; @@ -326,6 +330,7 @@ void TrapSimulator::printTrackletsXml(ostream& os) const os << " <m mcm=\"" << mMcmPos << "\">" << std::endl; int pid, padrow, slope, offset; + //TODO take care of the 0th being the header, and cpu1,2,3 being 1 to 3 tracklets. for (int cpu = 0; cpu < 4; cpu++) { if (mMCMT[cpu] == 0x10001000) { pid = -1; @@ -632,7 +637,7 @@ bool TrapSimulator::checkInitialized() const // // if (!mInitialized) - // LOG(debug4) << "TrapSimulator is not initialized but function other than Init() is called."; + // LOG(debug) << "TrapSimulator is not initialized but function other than Init() is called."; return mInitialized; } @@ -653,7 +658,7 @@ void TrapSimulator::print(int choice) const return; } - LOG(info) << "MCM " << mMcmPos << " on ROB " << mRobPos << " in detector " << mDetector; + LOG(debug) << "MCM " << mMcmPos << " on ROB " << mRobPos << " in detector " << mDetector; //std::string opt = option; if ((choice & PRINTRAW) != 0 || (choice & PRINTFILTERED) != 0) { @@ -661,16 +666,17 @@ void TrapSimulator::print(int choice) const } if ((choice & PRINTDETECTED) != 0) { - LOG(info) << "Found " << mNHits << " hits:"; + LOG(debug) << "Found " << mNHits << " hits:"; for (int iHit = 0; iHit < mNHits; iHit++) { - LOG(info) << "Hit " << std::setw(3) << iHit << " in timebin " << std::setw(2) << mHits[iHit].mTimebin << ", ADC " << std::setw(2) << mHits[iHit].mChannel << " has charge " << std::setw(3) << mHits[iHit].mQtot << " and position " << mHits[iHit].mYpos; + LOG(debug) << "Hit " << std::setw(3) << iHit << " in timebin " << std::setw(2) << mHits[iHit].mTimebin << ", ADC " << std::setw(2) << mHits[iHit].mChannel << " has charge " << std::setw(3) << mHits[iHit].mQtot << " and position " << mHits[iHit].mYpos; } } if ((choice & PRINTFOUND) != 0) { - LOG(info) << "Found Tracklets:"; - for (int iTrkl = 0; iTrkl < mTrackletArray.size(); iTrkl++) { - LOG(info) << "tracklet " << iTrkl << ": 0x" << hex << std::setw(16) << mTrackletArray[iTrkl].getTrackletWord(); + LOG(debug) << "Found Tracklets:"; + for (int iTrkl = 0; iTrkl < mTrackletArray64.size(); iTrkl++) { + LOG(debug) << "tracklet " << iTrkl << ": 0x" << hex << std::setw(32) << mTrackletArray64[iTrkl].getTrackletWord(); + LOG(debug) << mTrackletArray64[iTrkl]; } } } @@ -688,7 +694,7 @@ void TrapSimulator::draw(int choice, int index) return; } TFile* rootfile = new TFile("trdtrackletplots.root", "UPDATE"); - TCanvas* c1 = new TCanvas(Form("canvas_%i_%i:%i:%i_%i", index, mDetector, mRobPos, mMcmPos, (int)mTrackletArray.size())); + TCanvas* c1 = new TCanvas(Form("canvas_%i_%i:%i:%i_%i", index, mDetector, mRobPos, mMcmPos, (int)mTrackletArray64.size())); TH2F* hist = new TH2F(Form("mcmdata_%i", index), Form("Data of MCM %i on ROB %i in detector %i ", mMcmPos, mRobPos, mDetector), NADCMCM, @@ -739,38 +745,33 @@ void TrapSimulator::draw(int choice, int index) if ((choice & PLOTTRACKLETS) != 0) { TLine* trklLines = new TLine[4]; - LOG(info) << "Tracklet start for index : " << index; - if (mTrackletArray.size() > 0) { - LOG(info) << "Tracklet : for " << mTrackletArray[0].getDetector() << "::" << mTrackletArray[0].getROB() << " : " << mTrackletArray[0].getMCM(); + LOG(debug) << "Tracklet start for index : " << index; + if (mTrackletArray64.size() > 0) { + LOG(debug) << "Tracklet : for " << mTrackletArray64[0].getDetector() << "::" << mTrackletArray64[0].getROB() << " : " << mTrackletArray64[0].getMCM(); } else { - LOG(info) << "Tracklet : for trackletarray size of zero "; + LOG(debug) << "Tracklet : for trackletarray size of zero "; } - for (int iTrkl = 0; iTrkl < mTrackletArray.size(); iTrkl++) { - Tracklet trkl = mTrackletArray[iTrkl]; - float padWidth = 0.635 + 0.03 * (mDetector % 6); - float offset = padWidth / 256. * ((((((mRobPos & 0x1) << 2) + (mMcmPos & 0x3)) * 18) << 8) - ((18 * 4 * 2 - 18 * 2 - 3) << 7)); // revert adding offset in FitTracklet - //TODO replace the 18, 4 3 and 7 with constants for readability + for (int iTrkl = 0; iTrkl < mTrackletArray64.size(); iTrkl++) { + Tracklet64 trkl = mTrackletArray64[iTrkl]; + float position = trkl.getPosition(); int ndrift = mTrapConfig->getDmemUnsigned(mgkDmemAddrNdrift, mDetector, mRobPos, mMcmPos) >> 5; - float slope = 0; - if (ndrift) { - slope = trkl.getdY() * 140e-4 / ndrift; - } + float slope = trkl.getSlope(); int t0 = mTrapConfig->getTrapReg(TrapConfig::kTPFS, mDetector, mRobPos, mMcmPos); int t1 = mTrapConfig->getTrapReg(TrapConfig::kTPFE, mDetector, mRobPos, mMcmPos); - trklLines[iTrkl].SetX1((offset - (trkl.getY() - slope * t0)) / padWidth); // ??? sign? + trklLines[iTrkl].SetX1(position - slope * t0); trklLines[iTrkl].SetY1(t0); - trklLines[iTrkl].SetX2((offset - (trkl.getY() - slope * t1)) / padWidth); // ??? sign? + trklLines[iTrkl].SetX2(position - slope * t1); trklLines[iTrkl].SetY2(t1); trklLines[iTrkl].SetLineColor(2); trklLines[iTrkl].SetLineWidth(2); - LOG(info) << "Tracklet " << iTrkl << ": y = " << trkl.getY() << ", dy = " << (((float)trkl.getdY()) * 140e-4) << " offset : " << offset << "for a det:rob:mcm combo of : " << mDetector << ":" << mRobPos << ":" << mMcmPos; - LOG(info) << "Tracklet " << iTrkl << ": x1,y1,x2,y2 :: " << trklLines[iTrkl].GetX1() << "," << trklLines[iTrkl].GetY1() << "," << trklLines[iTrkl].GetX2() << "," << trklLines[iTrkl].GetY2(); - LOG(info) << "Tracklet " << iTrkl << ": t0 : " << t0 << ", t1 " << t1 << ", padwidth:" << padWidth << ", slope:" << slope << ", ndrift:" << ndrift << " which comes from : " << mTrapConfig->getDmemUnsigned(mgkDmemAddrNdrift, mDetector, mRobPos, mMcmPos) << " shifted 5 to the right "; + LOG(debug) << "Tracklet " << iTrkl << ": y = " << trkl.getPosition() << ", slope = " << (float)trkl.getSlope() << "for a det:rob:mcm combo of : " << mDetector << ":" << mRobPos << ":" << mMcmPos; + LOG(debug) << "Tracklet " << iTrkl << ": x1,y1,x2,y2 :: " << trklLines[iTrkl].GetX1() << "," << trklLines[iTrkl].GetY1() << "," << trklLines[iTrkl].GetX2() << "," << trklLines[iTrkl].GetY2(); + LOG(debug) << "Tracklet " << iTrkl << ": t0 : " << t0 << ", t1 " << t1 << ", slope:" << slope << ", which comes from : " << mTrapConfig->getDmemUnsigned(mgkDmemAddrNdrift, mDetector, mRobPos, mMcmPos) << " shifted 5 to the right "; trklLines[iTrkl].Draw(); } - LOG(info) << "Tracklet end ..."; + LOG(debug) << "Tracklet end ..."; } c1->Write(); rootfile->Close(); @@ -791,20 +792,20 @@ void TrapSimulator::setData(int adc, const ArrayADC& data, std::vector<o2::MCCom return; } - // LOG(info) << "Set Data : Det:Rob:MCM::"<< getDetector() <<":" <<getRobPos()<<":"<<getMcmPos() << " t:"<< mNTimeBin; + // LOG(debug) << "Set Data : Det:Rob:MCM::"<< getDetector() <<":" <<getRobPos()<<":"<<getMcmPos() << " t:"<< mNTimeBin; for (int it = 0; it < mNTimeBin; it++) { mADCR[adc * mNTimeBin + it] = ((int)(data[it]) << mgkAddDigits) + (mgAddBaseline << mgkAddDigits); mADCF[adc * mNTimeBin + it] = ((int)(data[it]) << mgkAddDigits) + (mgAddBaseline << mgkAddDigits); // mADCR[adc * mNTimeBin + it] = (unsigned int)(data[it]); // mADCF[adc * mNTimeBin + it] = (unsigned int)(data[it]); - // LOG(info) << data[it] <<" at "<< adc << "*" << mNTimeBin <<"+"<<it <<"="<< adc*mNTimeBin+it << " with data :"<<mADCR[adc*mNTimeBin+it] << ":" << mADCF[adc*mNTimeBin+it]; + // LOG(debug) << data[it] <<" at "<< adc << "*" << mNTimeBin <<"+"<<it <<"="<< adc*mNTimeBin+it << " with data :"<<mADCR[adc*mNTimeBin+it] << ":" << mADCF[adc*mNTimeBin+it]; } mDataIsSet = true; mADCFilled |= (1 << adc); //for (auto& tmplabel : labels) mADCLabels[adc].push_back(tmplabel); - LOG(debug) << "setting data labels incoming of : " << labels.size() << " with adc of " << adc; + // LOG(debug) << "setting data labels incoming of : " << labels.size() << " with adc of " << adc; mADCLabels[adc] = labels; - LOG(debug) << "setting data labels incoming of : " << labels.size() << " with adc of " << adc << " now mADCLabels[adc] size is : " << mADCLabels[adc].size(); + // LOG(debug) << "setting data labels incoming of : " << labels.size() << " with adc of " << adc << " now mADCLabels[adc] size is : " << mADCLabels[adc].size(); } void TrapSimulator::setData(int adc, int it, int data) @@ -835,12 +836,12 @@ void TrapSimulator::setBaselines() //we now add it by singular ADC, so there are adc channels that never get touched. //this fixes that. - LOG(info) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " for " << mDetector << ":" << mRobPos << ":" << mMcmPos; + LOG(debug) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " for " << mDetector << ":" << mRobPos << ":" << mMcmPos; //loop over all adcs. for (int adc = 0; adc < NADCMCM; adc++) { - LOG(info) << "Setting baselines for adc: " << adc << " of " << mDetector << ":" << mRobPos << ":" << mMcmPos << hex << mADCFilled << " if of : " << (mADCFilled & (1 << adc)); + LOG(debug) << "Setting baselines for adc: " << adc << " of " << mDetector << ":" << mRobPos << ":" << mMcmPos << hex << mADCFilled << " if of : " << (mADCFilled & (1 << adc)); if ((mADCFilled & (1 << adc)) == 0) { // adc is empty by construction of mADCFilled. - LOG(info) << "past if Setting baselines for adc: " << adc << " of " << mDetector << ":" << mRobPos << ":" << mMcmPos; + LOG(debug) << "past if Setting baselines for adc: " << adc << " of " << mDetector << ":" << mRobPos << ":" << mMcmPos; for (int timebin = 0; timebin < mNTimeBin; timebin++) { mADCR[adc * mNTimeBin + timebin] = mTrapConfig->getTrapReg(TrapConfig::kFPNP, mDetector, mRobPos, mMcmPos) + (mgAddBaseline << mgkAddDigits); mADCF[adc * mNTimeBin + timebin] = mTrapConfig->getTrapReg(TrapConfig::kTPFP, mDetector, mRobPos, mMcmPos) + (mgAddBaseline << mgkAddDigits); @@ -924,6 +925,7 @@ int TrapSimulator::packData(std::vector<uint32_t>& rawdata, uint32_t offset) uint32_t wordswritten = 0; // count the 32 bit words written; // std::cout << &raw[offset] << std::endl; // std::cout << raw.data() << std::endl;; + // //TODO query? the mCPU have the packed data, rather use them? TrackletMCMHeader mcmhead; int trackletcount = 0; // TrackletMCMHeader mcmhead; @@ -951,10 +953,8 @@ int TrapSimulator::packData(std::vector<uint32_t>& rawdata, uint32_t offset) break; // all of Q2 and upper 2 bits of Q1. } tracklets[i].checkbit = 1; - uint32_t tmppid = mTrackletArray64[i].getPID() & 0x3fff; - LOG(debug) << "tracklet i " << i << " has pid of 0x" << std::hex << mTrackletArray64[i].getPID() << " and we are going to put in 0x" << std::hex << tmppid; LOG(debug) << mTrackletArray64[i]; - tracklets[i].pid = mTrackletArray64[i].getPID() & 0x3fff; // the bottom 12 bits of the pid + tracklets[i].pid = mTrackletArray64[i].getQ0() & (mTrackletArray64[i].getQ1() << 8); tracklets[i].slope = mTrackletArray64[i].getSlope(); tracklets[i].pos = mTrackletArray64[i].getPosition(); tracklets[i].checkbit = 0; @@ -983,7 +983,7 @@ int TrapSimulator::packData(std::vector<uint32_t>& rawdata, uint32_t offset) //display the headers written if (debugheaders) { - LOG(info) << ">>>>> START DEBUG OUTPUT OF packData trackletcount:-:wordcount" << trackletcount << ":-:" << wordswritten; + LOG(debug) << ">>>>> START info OUTPUT OF packData trackletcount:-:wordcount" << trackletcount << ":-:" << wordswritten; o2::trd::printTrackletMCMHeader(mcmhead); o2::trd::printTrackletMCMData(tracklets[0]); if (trackletcount > 1) { @@ -992,7 +992,7 @@ int TrapSimulator::packData(std::vector<uint32_t>& rawdata, uint32_t offset) if (trackletcount > 2) { o2::trd::printTrackletMCMData(tracklets[2]); } - LOG(info) << "<<<<< END DEBUG OUTPUT OF packData"; + LOG(debug) << "<<<<< END info OUTPUT OF packData"; } //must produce between 2 and 4 words ... 1 and 3 tracklets. // assert(wordswritten<5); @@ -1143,27 +1143,27 @@ void TrapSimulator::filter() // The first filter takes the data from mADCR and // outputs to mADCF. - //LOG(info) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + LOG(debug) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__; // Non-linearity filter not implemented. filterPedestal(); filterGain(); filterTail(); // Crosstalk filter not implemented. - // LOG(info) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + LOG(debug) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__; } void TrapSimulator::filterPedestalInit(int baseline) { // Initializes the pedestal filter assuming that the input has // been constant for a long time (compared to the time constant). - // LOG(info) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + // LOG(debug) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; unsigned short fptc = mTrapConfig->getTrapReg(TrapConfig::kFPTC, mDetector, mRobPos, mMcmPos); // 0..3, 0 - fastest, 3 - slowest for (int adc = 0; adc < NADCMCM; adc++) { mInternalFilterRegisters[adc].mPedAcc = (baseline << 2) * (1 << mgkFPshifts[fptc]); } - // LOG(info) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + // LOG(debug) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; } unsigned short TrapSimulator::filterPedestalNextSample(int adc, int timebin, unsigned short value) @@ -1171,7 +1171,7 @@ unsigned short TrapSimulator::filterPedestalNextSample(int adc, int timebin, uns // Returns the output of the pedestal filter given the input value. // The output depends on the internal registers and, thus, the // history of the filter. - /// LOG(info) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + LOG(debug) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__; unsigned short fpnp = mTrapConfig->getTrapReg(TrapConfig::kFPNP, mDetector, mRobPos, mMcmPos); // 0..511 -> 0..127.75, pedestal at the output unsigned short fptc = mTrapConfig->getTrapReg(TrapConfig::kFPTC, mDetector, mRobPos, mMcmPos); // 0..3, 0 - fastest, 3 - slowest @@ -1189,9 +1189,12 @@ unsigned short TrapSimulator::filterPedestalNextSample(int adc, int timebin, uns mInternalFilterRegisters[adc].mPedAcc = (mInternalFilterRegisters[adc].mPedAcc + correction) & 0x7FFFFFFF; // 31 bits } - // LOG(info) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + // LOG(debug) << "LEAVE: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; if (fpby == 0) { - return value; + LOG(debug) << "LEAVE: (about to)" << __FILE__ << ":" << __func__ << ":" << __LINE__; + if (fpby == 0) { + return value; + } } if (inpAdd <= accumulatorShifted) { @@ -1216,16 +1219,16 @@ void TrapSimulator::filterPedestal() // It has only an effect if previous samples have been fed to // find the pedestal. Currently, the simulation assumes that // the input has been stable for a sufficiently long time. - // LOG(info) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + // LOG(debug) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; for (int iTimeBin = 0; iTimeBin < mNTimeBin; iTimeBin++) { for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { int oldadc = mADCF[iAdc * mNTimeBin + iTimeBin]; mADCF[iAdc * mNTimeBin + iTimeBin] = filterPedestalNextSample(iAdc, iTimeBin, mADCR[iAdc * mNTimeBin + iTimeBin]); - // LOG(info) << "mADCF : time : " << iTimeBin << " adc : " << iAdc << " change : " << oldadc << " -> " << mADCF[iAdc * mNTimeBin + iTimeBin]; + // LOG(debug) << "mADCF : time : " << iTimeBin << " adc : " << iAdc << " change : " << oldadc << " -> " << mADCF[iAdc * mNTimeBin + iTimeBin]; } } - // LOG(info) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; + // LOG(debug) << "BEGIN: " << __FILE__ << ":" << __func__ << ":" << __LINE__ ; } void TrapSimulator::filterGainInit() @@ -1247,7 +1250,7 @@ unsigned short TrapSimulator::filterGainNextSample(int adc, unsigned short value // BEGIN_LATEX O_{i}(t) = #gamma_{i} * I_{i}(t) + a_{i} END_LATEX // The output depends on the internal registers and, thus, the // history of the filter. - // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " with adc = " << adc << " value = " << value; + // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(debug) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " with adc = " << adc << " value = " << value; unsigned short mgby = mTrapConfig->getTrapReg(TrapConfig::kFGBY, mDetector, mRobPos, mMcmPos); // bypass, active low unsigned short mgf = mTrapConfig->getTrapReg(TrapConfig::TrapReg_t(TrapConfig::kFGF0 + adc), mDetector, mRobPos, mMcmPos); // 0x700 + (0 & 0x1ff); @@ -1262,23 +1265,23 @@ unsigned short TrapSimulator::filterGainNextSample(int adc, unsigned short value unsigned int mgfExtended = 0x700 + mgf; // The corr factor which is finally applied has to be extended by 0x700 (hex) or 0.875 (dec) // because fgf=0 correspons to 0.875 and fgf=511 correspons to 1.125 - 2^(-11) // (see TRAP User Manual for details) - //if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " with adc = " << adc << " value = " << value << " Trapconfig values :" << mgby <<":"<<mgf<<":"<<mga<<":"<<mgta<<":"<<mgtb << ":"<< mgfExtended; + //if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(debug) << "ENTER: " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " with adc = " << adc << " value = " << value << " Trapconfig values :" << mgby <<":"<<mgf<<":"<<mga<<":"<<mgta<<":"<<mgtb << ":"<< mgfExtended; unsigned int corr; // corrected value - // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) << "after declaring corr adc = " << adc << " value = " << value; + // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(debug) << "after declaring corr adc = " << adc << " value = " << value; value &= 0xFFF; corr = (value * mgfExtended) >> 11; corr = corr > 0xfff ? 0xfff : corr; - // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr; + // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(debug) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr; corr = addUintClipping(corr, mga, 12); - // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr; + // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(debug) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr; // Update threshold counters // not really useful as they are cleared with every new event if (!((mInternalFilterRegisters[adc].mGainCounterA == 0x3FFFFFF) || (mInternalFilterRegisters[adc].mGainCounterB == 0x3FFFFFF))) // stop when full { - // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr << " mgtb : " << mgtb; + // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(debug) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr << " mgtb : " << mgtb; if (corr >= mgtb) { mInternalFilterRegisters[adc].mGainCounterB++; } else if (corr >= mgta) { @@ -1286,7 +1289,7 @@ unsigned short TrapSimulator::filterGainNextSample(int adc, unsigned short value } } - // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(info) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr << " mgby : " << mgby; + // if(mDetector==75&& mRobPos==5 && mMcmPos==15) LOG(debug) <<__LINE__ << " adc = " << adc << " value = " << value << " corr : " << corr << " mgby : " << mgby; // if (mgby == 1) // return corr; // else @@ -1501,7 +1504,7 @@ void TrapSimulator::addHitToFitreg(int adc, unsigned short timebin, unsigned sho // the tracklet calculation. // In addition to the fit sums in the fit register // - + LOG(debug) << __func__ << " adc : " << adc << " timebin: " << timebin << " qtot: " << qtot << " ypos:" << ypos; if (adc > 24) { LOG(error) << " adc channel into addHitToFitReg is out of bounds for mFitReg : " << adc; } @@ -1528,10 +1531,10 @@ void TrapSimulator::addHitToFitreg(int adc, unsigned short timebin, unsigned sho mFitReg[adc].mSumY += ypos; mFitReg[adc].mSumY2 += ypos * ypos; mFitReg[adc].mSumXY += timebin * ypos; - // LOG(debug) << "fitreg[" << adc << "] in timebin " << timebin << ": X=" << mFitReg[adc].mSumX - // << ", X2=" << mFitReg[adc].mSumX2 << ", N=" << mFitReg[adc].mNhits << ", Y=" - // << mFitReg[adc].mSumY << ", Y2=" << mFitReg[adc].mSumY2 << ", XY=" << mFitReg[adc].mSumXY - // << ", Q0=" << mFitReg[adc].mQ0 << ", Q1=" << mFitReg[adc].mQ1; + LOG(debug) << "fitreg[" << adc << "] in timebin " << timebin << ": X=" << mFitReg[adc].mSumX + << ", X2=" << mFitReg[adc].mSumX2 << ", N=" << mFitReg[adc].mNhits << ", Y=" + << mFitReg[adc].mSumY << ", Y2=" << mFitReg[adc].mSumY2 << ", XY=" << mFitReg[adc].mSumXY + << ", Q0=" << mFitReg[adc].mQ0 << ", Q1=" << mFitReg[adc].mQ1; } // register hits (MC info) @@ -1541,9 +1544,9 @@ void TrapSimulator::addHitToFitreg(int adc, unsigned short timebin, unsigned sho mHits[mNHits].mQtot = qtot; mHits[mNHits].mYpos = ypos; mHits[mNHits].mTimebin = timebin; - // LOG(info) << "in addhit to fit reg labels coming in are of " << labels.size() << " and labels assigned from [mNHits = "<<mNHits<<"] a size of " << mHits[mNHits].mLabels.size(); + //LOG(debug) << "in addhit to fit reg labels coming in are of " << labels.size() << " and labels assigned from [mNHits = "<<mNHits<<"] a size of " << mHits[mNHits].mLabels.size(); // mHits[mNHits].mLabels = labels; - // LOG(info) << "in addhit to fit reg labels coming in are of " << labels.size() << " and labels assigned from [mNHits = "<<mNHits<<"] a size of " << mHits[mNHits].mLabels.size(); + //LOG(debug) << "in addhit to fit reg labels coming in are of " << labels.size() << " and labels assigned from [mNHits = "<<mNHits<<"] a size of " << mHits[mNHits].mLabels.size(); //TODO link to the labels. mNHits++; //.emplace_back(adc, timebin, qtot, ypos); // TODO add label indexes into the labels container for all those labels pertaining to this hit. @@ -1551,7 +1554,7 @@ void TrapSimulator::addHitToFitreg(int adc, unsigned short timebin, unsigned sho LOG(warn) << "no space left to store the MC information for the hit >100 mNHits : " << mNHits; //print( PRINTRAW| PRINTFILTERED); } - // LOG(info) << "added hit of : "<< adc<<":"<< qtot<<":"<< ypos<<":"<< timebin; // TODO add label indexes into the labels container for all those labels pertaining to this hit. + // LOG(debug) << "added hit of : "<< adc<<":"<< qtot<<":"<< ypos<<":"<< timebin; // TODO add label indexes into the labels container for all those labels pertaining to this hit. } void TrapSimulator::calcFitreg() @@ -1571,7 +1574,6 @@ void TrapSimulator::calcFitreg() std::array<unsigned short, 20> qTotal{}; //[19 + 1]; // the last is dummy std::array<unsigned short, 6> marked{}, qMarked{}; unsigned short worse1, worse2; - int debugstop = 1; if (mgStoreClusters) { timebin1 = 0; @@ -1603,7 +1605,7 @@ void TrapSimulator::calcFitreg() // mFitReg.clear(); for (int i = 0; i < mNHits; i++) { - mHits[i].ClearHits(); // do it this way as we dont want to 100 members if we only used 3 .... + mHits[i].ClearHits(); // do it this way as we dont want to zero 150 members if we only used 3 .... } for (timebin = timebin1; timebin < timebin2; timebin++) { @@ -1631,15 +1633,15 @@ void TrapSimulator::calcFitreg() // The accumulated charge is with the pedestal!!! qtotTemp = adcLeft + adcCentral + adcRight; - /* if ((qtotTemp > 130)) { - LOG(info) << "testtree " - << "qtot=" << qtotTemp - << " qleft=" << adcLeft - << " qcent=" << adcCentral - << " qright=" << adcRight - << " for " << mDetector <<":"<<mRobPos<<":"<<mMcmPos << ":adcleft:"<<adcch<<":t"<<timebin; - } - */ + if ((qtotTemp > 130)) { + LOG(debug) << "qtotTemp>130 " + << "qtot=" << qtotTemp + << " qleft=" << adcLeft + << " qcent=" << adcCentral + << " qright=" << adcRight + << " for " << mDetector << ":" << mRobPos << ":" << mMcmPos << ":adcleft:" << adcch << ":t" << timebin; + } + if ((hitQual) && (qtotTemp >= mTrapConfig->getTrapReg(TrapConfig::kTPHT, mDetector, mRobPos, mMcmPos)) && (adcLeft <= adcCentral) && @@ -1652,7 +1654,7 @@ void TrapSimulator::calcFitreg() qTotal[adcch] = 0; //jkl } // if (qTotal[adcch] != 0) - // LOG(info) << "ch " << setw(2) << adcch << " qTotal " << qTotal[adcch]; + // LOG(debug) << "ch " << setw(2) << adcch << " qTotal " << qTotal[adcch]; } fromLeft = -1; @@ -1718,11 +1720,11 @@ void TrapSimulator::calcFitreg() // Now mask the two channels with the smallest charge if (worse1 < 19) { qTotal[worse1] = 0; - //LOG(debug3) << "Kill ch " << worse1; + //LOG(debug) << "Kill ch " << worse1; } if (worse2 < 19) { qTotal[worse2] = 0; - // LOG(debug3) << "Kill ch " << worse2; + // LOG(debug) << "Kill ch " << worse2; } } @@ -1736,9 +1738,9 @@ void TrapSimulator::calcFitreg() // subtract the pedestal TPFP, clipping instead of wrapping int regTPFP = mTrapConfig->getTrapReg(TrapConfig::kTPFP, mDetector, mRobPos, mMcmPos); //TODO put this together with the others as members of trapsim, which is initiliased by det,rob,mcm. - // LOG(info) << "Hit found, time=" << timebin << ", adcch=" << adcch << "/" << adcch + 1 << "/" - // << adcch + 2 << ", adc values=" << adcLeft << "/" << adcCentral << "/" - // << adcRight << ", regTPFP=" << regTPFP << ", TPHT=" << mTrapConfig->getTrapReg(TrapConfig::kTPHT, mDetector, mRobPos, mMcmPos); + LOG(debug) << "Hit found, time=" << timebin << ", adcch=" << adcch << "/" << adcch + 1 << "/" + << adcch + 2 << ", adc values=" << adcLeft << "/" << adcCentral << "/" + << adcRight << ", regTPFP=" << regTPFP << ", TPHT=" << mTrapConfig->getTrapReg(TrapConfig::kTPHT, mDetector, mRobPos, mMcmPos); if (adcLeft < regTPFP) { adcLeft = 0; } else { @@ -1764,39 +1766,47 @@ void TrapSimulator::calcFitreg() if (ypos < 0) { ypos = -ypos; } + //ypos element of [0:128] // make the correction using the position LUT + LOG(debug) << "ypos raw is " << ypos << " adcrigh-adcleft/adccentral " << adcRight << "-" << adcLeft << "/" << adcCentral << "==" << (adcRight - adcLeft) / adcCentral << " 128 * numerator : " << 128 * (adcRight - adcLeft) / adcCentral; + LOG(debug) << "ypos before lut correction : " << ypos; ypos = ypos + mTrapConfig->getTrapReg((TrapConfig::TrapReg_t)(TrapConfig::kTPL00 + (ypos & 0x7F)), mDetector, mRobPos, mMcmPos); if (adcLeft > adcRight) { - ypos = -ypos; + LOG(debug) << "ypos after lut correction : " << ypos; + if (adcLeft > adcRight) { + ypos = -ypos; + } } /* TODO this is left in here as a ref for what was done with labels, its stored externally now figure something out. */ // add the hit to the fitregister // int a=qTotal[adcch] >> mgkAddDigits; - // LOG(info) << "calling addHitToFitreg with :" << adcch << " :: " << timebin << " :: " << hex << qTotal[adcch] << dec << " :: shifted bits :" << 2 << " :: " << ypos; + // LOG(debug) << "calling addHitToFitreg with :" << adcch << " :: " << timebin << " :: " << hex << qTotal[adcch] << dec << " :: shifted bits :" << 2 << " :: " << ypos; // addHitToFitreg(adcch, timebin, qTotal[adcch] >> 2, ypos); - LOG(debug) << __func__ << "ADDING HIT FOR in adclabels : " << mADCLabels[adcch].size() << " with adcch of " << adcch << " qtot : " << qTotal[adcch] << " timebin :" << timebin; + LOG(debug) << __func__ << "ADDING HIT FOR in adclabels : " << mADCLabels[adcch].size() << " with adcch of " << adcch << " qtot : " << qTotal[adcch] << " timebin :" << timebin << " and ypos:" << ypos; addHitToFitreg(adcch, timebin, qTotal[adcch] >> mgkAddDigits, ypos); //, mADCLabels[adcch]); // LOG(debug) << __FILE__ << ":" << __LINE__ << " :: added hit to fit re "; } } } - /* - for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { - if (mFitReg[iAdc].mNhits != 0) { - LOG(debug) << "fitreg[" << iAdc << "]: nHits = " << mFitReg[iAdc].mNhits << "]: sumX = " << mFitReg[iAdc].mSumX << ", sumY = " << mFitReg[iAdc].mSumY << ", sumX2 = " << mFitReg[iAdc].mSumX2 << ", sumY2 = " << mFitReg[iAdc].mSumY2 << ", sumXY = " << mFitReg[iAdc].mSumXY; - } - }*/ + + LOG(debug) << "***** Fit Registers begin"; + for (int iAdc = 0; iAdc < NADCMCM; iAdc++) { + if (mFitReg[iAdc].mNhits != 0) { + LOG(debug) << "fitreg[" << iAdc << "]: nHits = " << mFitReg[iAdc].mNhits << "]: sumX = " << mFitReg[iAdc].mSumX << ", sumY = " << mFitReg[iAdc].mSumY << ", sumX2 = " << mFitReg[iAdc].mSumX2 << ", sumY2 = " << mFitReg[iAdc].mSumY2 << ", sumXY = " << mFitReg[iAdc].mSumXY; + } + } + LOG(debug) << "***** Fit Registers end"; //print(PRINTRAW); LOG(debug) << "LEAVING : " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " :: " << getDetector() << ":" << getRobPos() << ":" << getMcmPos() << " and mNHits : " << mNHits; } void TrapSimulator::trackletSelection() { - // Select up to 4 tracklet candidates from the fit registers + // Select up to 3 tracklet candidates from the fit registers // and assign them to the CPUs. - // LOG(info) << "ENTERING : " << __FILE__ << ":" << __func__ << ":" << __LINE__<<" :: "<< getDetector()<<":"<< getRobPos()<<":"<< getMcmPos(); + LOG(debug) << "ENTERING : " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " :: " << getDetector() << ":" << getRobPos() << ":" << getMcmPos(); unsigned short adcIdx, i, j, ntracks, tmp; std::array<unsigned short, 18> trackletCandch{}; // store the adcch[0] and number of hits[1] for all tracklet candidates std::array<unsigned short, 18> trackletCandhits{}; // store the adcch[0] and number of hits[1] for all tracklet candidates @@ -1807,15 +1817,15 @@ void TrapSimulator::trackletSelection() (mFitReg[adcIdx].mNhits + mFitReg[adcIdx + 1].mNhits >= mTrapConfig->getTrapReg(TrapConfig::kTPCT, mDetector, mRobPos, mMcmPos))) { trackletCandch[ntracks] = adcIdx; trackletCandhits[ntracks] = mFitReg[adcIdx].mNhits + mFitReg[adcIdx + 1].mNhits; - // LOG(info) << ntracks << " " << trackletCandch[ntracks] << " " << trackletCandhits[ntracks]; + // LOG(debug) << ntracks << " " << trackletCandch[ntracks] << " " << trackletCandhits[ntracks]; ntracks++; }; } - // LOG(info) << "Number of track candidates:"<< ntracks; - // for (i = 0; i < ntracks; i++) - // LOG(info) << "TRACKS: " << i << " " << trackletCandch[i] << " " << trackletCandhits[i]; - - if (ntracks > 4) { + LOG(debug) << "Number of track candidates:" << ntracks; + for (i = 0; i < ntracks; i++) { + LOG(debug) << "TRACKS: " << i << " " << trackletCandch[i] << " " << trackletCandhits[i]; + } + if (ntracks > 3) { // primitive sorting according to the number of hits for (j = 0; j < (ntracks - 1); j++) { for (i = j + 1; i < ntracks; i++) { @@ -1831,7 +1841,7 @@ void TrapSimulator::trackletSelection() } } } - ntracks = 4; // cut the rest, 4 is the max + ntracks = 3; // cut the rest, 3 is the max } // else is not necessary to sort @@ -1852,12 +1862,12 @@ void TrapSimulator::trackletSelection() for (i = 0; i < ntracks; i++) { // CPUs with tracklets. mFitPtr[i] = trackletCandch[i]; // pointer to the left channel with tracklet for CPU[i] } - for (i = ntracks; i < 4; i++) { // CPUs without tracklets - mFitPtr[i] = 31; // pointer to the left channel with tracklet for CPU[i] = 31 (invalid) + for (i = ntracks; i < 4; i++) { // CPUs without tracklets + mFitPtr[i] = 31; // pointer to the left channel with tracklet for CPU[i] = 31 (invalid) } - // LOG(info) << "-------------------------------------------- found " << ntracks << " tracklet candidates"; + LOG(debug) << __func__ << " found " << ntracks << " tracklet candidates"; // for (i = 0; i < 4; i++) - // LOG(info) << "fitPtr[" << i << "]: " << mFitPtr[i]; + // LOG(debug) << "fitPtr[" << i << "]: " << mFitPtr[i]; // reject multiple tracklets if (FeeParam::instance()->getRejectMultipleTracklets()) { @@ -1891,13 +1901,14 @@ void TrapSimulator::trackletSelection() // for (i = 0; i < 4; i++) // LOG(debug) << "fitPtr[" << i << "]: " << mFitPtr[i]; } + LOG(debug) << "LEAVING : " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " :: " << getDetector() << ":" << getRobPos() << ":" << getMcmPos() << " with ntracks:" << ntracks; } void TrapSimulator::fitTracklet() { // Perform the actual tracklet fit based on the fit sums // which have been filled in the fit registers. - // LOG(debug) << "ENTERING : " << __FILE__ << ":" << __func__ << ":" << __LINE__<<" :: "<< getDetector()<<":"<< getRobPos()<<":"<< getMcmPos() << " and Tracklet array size is : " << mTrackletArray.size(); + LOG(debug) << "ENTERING : " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " :: " << getDetector() << ":" << getRobPos() << ":" << getMcmPos() << " and Tracklet array size is : " << mTrackletArray64.size(); // parameters in fitred.asm (fit program) int rndAdd = 0; int decPlaces = 5; // must be larger than 1 or change the following code @@ -1912,30 +1923,31 @@ void TrapSimulator::fitTracklet() int padrow = ((mRobPos >> 1) << 2) | (mMcmPos >> 2); int yoffs = (((((mRobPos & 0x1) << 2) + (mMcmPos & 0x3)) * 18) << 8) - ((18 * 4 * 2 - 18 * 2 - 1) << 7); + // TODO we dont need the stuff calculated in fitred.asm because we are now all relative to the mcm ?? check this statement + LOG(debug) << "padrow:" << padrow << " yoffs:" << yoffs << " and rndAdd:" << rndAdd; // add corrections for mis-alignment if (FeeParam::instance()->getUseMisalignCorr()) { - LOG(debug3) << "using mis-alignment correction"; + LOG(debug) << "using mis-alignment correction"; yoffs += (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrYcorr, mDetector, mRobPos, mMcmPos); } yoffs = yoffs << decPlaces; // holds position of ADC channel 1 int layer = mDetector % 6; - unsigned int scaleY = (unsigned int)((0.635 + 0.03 * layer) / (256.0 * 160.0e-4) * shift); - unsigned int scaleD = (unsigned int)((0.635 + 0.03 * layer) / (256.0 * 140.0e-4) * shift); - + unsigned int scaleY = 1; //(unsigned int)((0.635 + 0.03 * layer) / (256.0 * 160.0e-4) * shift); + unsigned int scaleD = 1; //(unsigned int)((0.635 + 0.03 * layer) / (256.0 * 140.0e-4) * shift); + LOG(debug) << "scaleY : " << scaleY << " scaleD=" << scaleD << " shift:" << std::hex << shift << std::dec; int deflCorr = (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCorr, mDetector, mRobPos, mMcmPos); int ndrift = (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrNdrift, mDetector, mRobPos, mMcmPos); // local variables for calculation - long mult, temp, denom; //??? + long mult, temp, denom; unsigned int q0, q1, q2 = 23, pid; // charges in the two windows and total charge - float rawpid, rawz, rawy, rawslope, rawoffset; - float rawslope4trackletword, rawoffset4trackletword; + float rawpid, rawz, rawy, rawslope, rawposition; unsigned short nHits; // number of hits - int slope, offset; // slope and offset of the tracklet + int slope, position; // slope and position of the tracklet int sumX, sumY, sumXY, sumX2; // fit sums from fit registers - int sumY2; // not used in the current TRAP program, now used for error calculation (simulation only) + int sumY2; // not used in the current TRAP program, used for error calculation (simulation only) float fitError, fitSlope, fitOffset; FitReg *fit0, *fit1; // pointers to relevant fit registers @@ -1951,69 +1963,87 @@ void TrapSimulator::fitTracklet() } else { fit0 = &mFitReg[mFitPtr[cpu]]; fit1 = &mFitReg[mFitPtr[cpu] + 1]; // next channel - + // fit0->Print(); + // fit1->Print(); + LOG(debug) << "mult is : " << mult << " and in hex : 0x" << std::hex << mult << std::dec; mult = 1; mult = mult << (32 + decPlaces); mult = -mult; + LOG(debug) << "after mult is : " << mult << " and in hex : 0x" << std::hex << mult << std::dec; // time offset for fit sums const int t0 = FeeParam::instance()->getUseTimeOffset() ? (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrTimeOffset, mDetector, mRobPos, mMcmPos) : 0; - // LOG(info) << "using time offset t0 = " << t0; + LOG(debug) << "using time offset of t0 = " << t0; // Merging nHits = fit0->mNhits + fit1->mNhits; // number of hits sumX = fit0->mSumX + fit1->mSumX; sumX2 = fit0->mSumX2 + fit1->mSumX2; denom = ((long)nHits) * ((long)sumX2) - ((long)sumX) * ((long)sumX); + // set ADC data with array mult = mult / denom; // exactly like in the TRAP program q0 = fit0->mQ0 + fit1->mQ0; q1 = fit0->mQ1 + fit1->mQ1; + q2 = fit0->mQ2 + fit1->mQ2; sumY = fit0->mSumY + fit1->mSumY + 256 * fit1->mNhits; sumXY = fit0->mSumXY + fit1->mSumXY + 256 * fit1->mSumX; sumY2 = fit0->mSumY2 + fit1->mSumY2 + 512 * fit1->mSumY + 256 * 256 * fit1->mNhits; + LOG(debug) << "sumY2 = " << sumY2 << " "; + ; slope = nHits * sumXY - sumX * sumY; + LOG(debug) << "slope = " << slope; //offset = sumX2*sumY - sumX*sumXY - t0 * sumX*sumY + t0 * nHits*sumXY; - offset = sumX2 * sumY - sumX * sumXY; - offset = offset << 5; - offset += t0 * nHits * sumXY - t0 * sumX * sumY; - offset = offset >> 5; + position = sumX2 * sumY - sumX * sumXY; + position = position << 5; + position += t0 * nHits * sumXY - t0 * sumX * sumY; + position = position >> 5; temp = mult * slope; slope = temp >> 32; // take the upper 32 bits slope = -slope; - temp = mult * offset; - offset = temp >> 32; // take the upper 32 bits - - offset = offset + yoffs; - // LOG(info) << "slope = " << slope << ", slope * ndrift = " << slope * ndrift << ", deflCorr: " << deflCorr; - slope = ((slope * ndrift) >> ndriftDp) + deflCorr; - offset = offset - (mFitPtr[cpu] << (8 + decPlaces)); - + temp = mult * position; + position = temp >> 32; // take the upper 32 bits + LOG(debug) << "slope = " << slope; + //slope = slope;//this is here as a reference for what was done in run2 //* ndrift) >> ndriftDp) + deflCorr; + auto oldpos = position; + LOG(debug) << "position = position - (mFitPtr[cpu] << (8 + decPlaces));"; + position = position - (mFitPtr[cpu] << (8 + decPlaces)); + LOG(debug) << "position = " << position << " - " << mFitPtr[cpu] << " << (8+" << decPlaces << ")"; + + LOG(debug) << "position = " << position << " : " << oldpos; + LOG(debug) << "slope before scale of " << scaleD << " is = " << slope; temp = slope; temp = temp * scaleD; slope = (temp >> 32); - rawslope4trackletword = temp; - temp = offset; + LOG(debug) << "slope after scale and shift is = " << slope; + LOG(debug) << "slope = " << slope; + LOG(debug) << "position before scale and shift = " << position; + temp = position; temp = temp * scaleY; - offset = (temp >> 32); - rawoffset4trackletword = temp; + position = (temp >> 32); + LOG(debug) << "position after scale and shift is = " << position; // rounding, like in the TRAP slope = (slope + rndAdd) >> decPlaces; - offset = (offset + rndAdd) >> decPlaces; + position = (position + rndAdd) >> decPlaces; + LOG(debug) << "position = " << position; + LOG(debug) << "slope = " << slope; - // LOG(info) << "Det: " << setw(3) << mDetector << ", ROB: " << mRobPos << ", MCM: " << setw(2) << mMcmPos << setw(-1) << ": deflection: " << slope << ", min: " << (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCutStart + 2 * mFitPtr[cpu], mDetector, mRobPos, mMcmPos) << " max : " << (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCutStart + 1 + 2 * mFitPtr[cpu], mDetector, mRobPos, mMcmPos); + LOG(debug) << "Det: " << setw(3) << mDetector << ", ROB: " << mRobPos << ", MCM: " << setw(2) << mMcmPos << setw(-1) << ": deflection: " << slope << ", min: " << (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCutStart + 2 * mFitPtr[cpu], mDetector, mRobPos, mMcmPos) << " max : " << (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCutStart + 1 + 2 * mFitPtr[cpu], mDetector, mRobPos, mMcmPos); - // LOG(info) << "Fit sums: x = " << sumX << ", X = " << sumX2 << ", y = " << sumY << ", Y = " << sumY2 << ", Z = " << sumXY << ", q0 = " << q0 << ", q1 = " << q1; + LOG(debug) << "Fit sums: x = " << sumX << ", X = " << sumX2 << ", y = " << sumY << ", Y = " << sumY2 << ", Z = " << sumXY << ", q0 = " << q0 << ", q1 = " << q1; fitSlope = (float)(nHits * sumXY - sumX * sumY) / (nHits * sumX2 - sumX * sumX); fitOffset = (float)(sumX2 * sumY - sumX * sumXY) / (nHits * sumX2 - sumX * sumX); + LOG(debug) << "FIT : a:" << fitSlope << " b:" << fitOffset; + LOG(debug) << "FIT for trackletword : a:" << slope << " b:" << position; + float sx = (float)sumX; float sx2 = (float)sumX2; float sy = (float)sumY; @@ -2029,42 +2059,61 @@ void TrapSimulator::fitTracklet() rejected = true; } - // LOG(info) << "slope : " << slope << " getDmemUnsigned " << mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCutStart + 2 * mFitPtr[cpu], mDetector, mRobPos, mMcmPos); + // LOG(debug) << "slope : " << slope << " getDmemUnsigned " << mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCutStart + 2 * mFitPtr[cpu], mDetector, mRobPos, mMcmPos); if (rejected && getApplyCut()) { mMCMT[cpu] = 0x10001000; //??? FeeParam::getTrackletEndmarker(); } else { - if (slope > 63 || slope < -64) { // wrapping in TRAP! - LOG(info) << "Overflow in slope: " << slope << ", tracklet discarded!"; + if (slope > 127 || slope < -127) { // wrapping in TRAP! + LOG(debug) << "Overflow in slope: " << slope << ", tracklet discarded!"; mMCMT[cpu] = 0x10001000; continue; } - slope = slope & 0x7F; // 7 bit - - if (offset > 0xfff || offset < -0xfff) { - LOG(warning) << "Overflow in offset"; + slope = slope & 0xff; // 8 bit + + yoffs = yoffs << decPlaces; // holds position of ADC channel 1 + int layer = mDetector % 6; + unsigned int scaleY = (unsigned int)((0.635 + 0.03 * layer) / (256.0 * 160.0e-4) * shift); + unsigned int scaleD = (unsigned int)((0.635 + 0.03 * layer) / (256.0 * 140.0e-4) * shift); + LOG(debug) << "scaleY : " << scaleY << " scaleD=" << scaleD << " shift:" << std::hex << shift << std::dec; + int deflCorr = (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCorr, mDetector, mRobPos, mMcmPos); + int ndrift = (int)mTrapConfig->getDmemUnsigned(mgkDmemAddrNdrift, mDetector, mRobPos, mMcmPos); + + // local variables for calculation + long mult, temp, denom; + unsigned int q0, q1, q2 = 23, pid; // charges in the two windows and total charge + float rawpid, rawz, rawy, rawslope, rawposition; + float rawslope4trackletword, rawoffset4trackletword; + // unsigned short nHits; // number of hits + int slope, position; // slope and position of the tracklet + int sumX, sumY, sumXY, sumX2; // fit sums from fit registers + int sumY2; // not used in the current TRAP program, used for error calculation (simulation only) + float fitError, fitSlope, fitOffset; + FitReg *fit0, *fit1; // pointers to relevant fit registers + + // const uint32_t OneDivN[32] = { // 2**31/N : exactly like in the TRAP, the simple division here gives the same result! + // 0x00000000, 0x80000000, 0x40000000, 0x2AAAAAA0, 0x20000000, 0x19999990, 0x15555550, 0x12492490, + // 0x10000000, 0x0E38E380, 0x0CCCCCC0, 0x0BA2E8B0, 0x0AAAAAA0, 0x09D89D80, 0x09249240, 0x08888880, + // 0x08000000, 0x07878780, 0x071C71C0, 0x06BCA1A0, 0x06666660, 0x06186180, 0x05D17450, 0x0590B210, + // 0x05555550, 0x051EB850, 0x04EC4EC0, 0x04BDA120, 0x04924920, 0x0469EE50, 0x04444440, 0x04210840}; + + if (position > 0x7ff || position < -0x7ff) { // 11 bits. + LOG(warning) << "Overflow in position with position of " << position << " in hex 0x" << std::hex << position; } - offset = offset & 0x1FFF; // 13 bit - - pid = getPID(q0, q1); - rawpid = pid; - - if (pid > 0xff) { - LOG(warn) << "Overflow in PID"; // was warn - } - pid = pid & 0xFF; // 8 bit, exactly like in the TRAP program + position = position & 0x7ff; // 11 bits // assemble and store the tracklet word - mMCMT[cpu] = (pid << 24) | (padrow << 20) | (slope << 13) | offset; - // pid Z deflection lenght Y + TrackletMCMData trackletword; + buildTrackletMCMData(trackletword, slope, position, q0, q1, q2); + mMCMT[cpu] = trackletword.word; + rawz = padrow; - rawoffset = offset; + rawposition = position; // calculate number of hits and MC label // std::array<int, 3> mcLabel = {-1, -1, -1}; - int nHits0 = 0; - int nHits1 = 0; + std::array<int, 3> nHits{}; // const int maxLabels = 30; // std::array<int, 30> label{}; // up to 30 different labels possible @@ -2082,11 +2131,15 @@ void TrapSimulator::fitTracklet() // counting contributing hits if (mHits[iHit].mTimebin >= mTrapConfig->getTrapReg(TrapConfig::kTPQS0, mDetector, mRobPos, mMcmPos) && mHits[iHit].mTimebin < mTrapConfig->getTrapReg(TrapConfig::kTPQE0, mDetector, mRobPos, mMcmPos)) { - nHits0++; + nHits[0]++; } if (mHits[iHit].mTimebin >= mTrapConfig->getTrapReg(TrapConfig::kTPQS1, mDetector, mRobPos, mMcmPos) && mHits[iHit].mTimebin < mTrapConfig->getTrapReg(TrapConfig::kTPQE1, mDetector, mRobPos, mMcmPos)) { - nHits1++; + nHits[1]++; + } + if (mHits[iHit].mTimebin >= 3 && //TODO this needs to come from trapconfig, its not there yet. + mHits[iHit].mTimebin < 5) { + nHits[2]++; } //TODO nHits2 ???? to correspond to Q2 ??? // @@ -2096,7 +2149,7 @@ void TrapSimulator::fitTracklet() // TODO label calculation only if there is a digitsmanager to get the labels froAm } bool printoutadcs = false; - //TODO these debug statemetns are left in to debug the labels later. + //TODO these info statemetns are left in to info the labels later. LOG(debug) << "adc bitpatterh is " << std::hex << adchitbp << std::dec; for (int i = 0; i < 21; i++) { if (adchitbp & (1 << i)) { @@ -2115,62 +2168,176 @@ void TrapSimulator::fitTracklet() //if(printoutadcs) print(PRINTRAW|PRINTFILTERED); //labels come in via adc, now loop over ADC and see which contribute to the hits. - LOG(debug) << "TrapSim Trackletarray size is : " << mTrackletArray.size() << " :: adding a track at " << mMCMT[cpu] << ":" << mDetector * 2 + mRobPos % 2 << ":" << mRobPos << ":" << mMcmPos << " LABELS size: " << localTrackletLabels.size(); - mTrackletArray.emplace_back(mDetector * 2 + mRobPos % 2, mRobPos, mMcmPos, rawpid, rawslope, rawoffset, rawslope4trackletword, rawoffset4trackletword); + LOG(debug) << "TrapSim Trackletarray size is : " << mTrackletArray64.size() << " :: adding a track at " << mMCMT[cpu] << ":" << mDetector * 2 + mRobPos % 2 << ":" << mRobPos << ":" << mMcmPos << " LABELS size: " << localTrackletLabels.size(); uint32_t format = 0; uint32_t hcid = mDetector * 2 + mRobPos % 2; uint32_t padrow = ((mRobPos >> 1) << 2) | (mMcmPos >> 2); uint32_t col = mFeeParam->getPadColFromADC(mRobPos, mMcmPos, 1); - uint32_t position = rawoffset; + //defined above uint32_t position = ; //uint32_t s - mTrackletArray64.emplace_back(format, hcid, padrow, col, position, slope, q2, q1, q0); - int newtrackposition = mTrackletArray.size() - 1; + mTrackletArray64.emplace_back(format, hcid, padrow, col, position, slope, q0, q1, q2); + if (mdebugStream) { + mTrackletDetails.emplace_back(position, slope, q0, q1, q2, nHits, fitError); + } //mTrackletArray[newtrackposition].setLabel(mcLabel); - mTrackletArray[newtrackposition].setNHits(fit0->mNhits + fit1->mNhits); - mTrackletArray[newtrackposition].setNHits0(nHits0); - mTrackletArray[newtrackposition].setNHits1(nHits1); - mTrackletArray[newtrackposition].setQ0(q0); - mTrackletArray[newtrackposition].setQ1(q1); - mTrackletArray[newtrackposition].setSlope(fitSlope); - mTrackletArray[newtrackposition].setOffset(fitOffset); - mTrackletArray[newtrackposition].setError(TMath::Sqrt(TMath::Abs(fitError) / nHits)); LOG(debug) << "adding elements to mTrackletLabels of size " << mTrackletLabels.getIndexedSize() << "::" << mTrackletLabels.getNElements() << " labels for additional labels vector of :" << localTrackletLabels.size() << " labels"; mTrackletLabels.addElements(mTrackletLabels.getIndexedSize(), localTrackletLabels); LOG(debug) << "elements in mTrackletLabels is size " << mTrackletLabels.getIndexedSize() << "::" << mTrackletLabels.getNElements() << " labels for additional labels vector of :" << localTrackletLabels.size() << " labels"; // store cluster information (if requested) - if (mgStoreClusters) { + if (mgStoreClusters && mdebugStream) { std::vector<float> res(getNumberOfTimeBins()); std::vector<float> qtot(getNumberOfTimeBins()); for (int iTimebin = 0; iTimebin < getNumberOfTimeBins(); ++iTimebin) { res[iTimebin] = 0; qtot[iTimebin] = 0; } - for (int iHit = 0; iHit < mNHits; iHit++) { int timebin = mHits[iHit].mTimebin; // check if hit contributes if (mHits[iHit].mChannel == mFitPtr[cpu]) { - // for (int i=0;i<mNHits;i++) LOG(info) << "mHits.["<<i << "].mTimebin="<< mHits[i].mTimebin; + // for (int i=0;i<mNHits;i++) LOG(debug) << "mHits.["<<i << "].mTimebin="<< mHits[i].mTimebin; res[timebin] = mHits[iHit].mYpos - (fitSlope * timebin + fitOffset); qtot[timebin] = mHits[iHit].mQtot; } else if (mHits[iHit].mChannel == mFitPtr[cpu] + 1) { res[timebin] = mHits[iHit].mYpos + 256 - (fitSlope * timebin + fitOffset); qtot[timebin] = mHits[iHit].mQtot; } - } - mTrackletArray[newtrackposition].setClusters(res, qtot, getNumberOfTimeBins()); - } - //TODO dont leave this commented out ! - if (fitError < 0) { - LOG(warn) << "fit slope: " << fitSlope << ", offset: " << fitOffset << ", error: " << TMath::Sqrt(TMath::Abs(fitError) / nHits); - LOG(info) << "Strange fit error: " << fitError << " from Sx: " << sumX << ", Sy: " << sumY << ", Sxy: " << sumXY << ", Sx2: " << sumX2 << ", Sy2: " << sumY2 << ", nHits: " << nHits; + // LOG(debug) << "slope : " << slope << " getDmemUnsigned " << mTrapConfig->getDmemUnsigned(mgkDmemAddrDeflCutStart + 2 * mFitPtr[cpu], mDetector, mRobPos, mMcmPos); + + if (rejected && getApplyCut()) { + mMCMT[cpu] = 0x10001000; //??? FeeParam::getTrackletEndmarker(); + } else { + if (slope > 127 || slope < -127) { // wrapping in TRAP! + LOG(debug) << "Overflow in slope: " << slope << ", tracklet discarded!"; + mMCMT[cpu] = 0x10001000; + continue; + } + + slope = slope & 0xff; // 8 bit + + if (position > 0x7ff || position < -0x7ff) { // 11 bits. + LOG(warning) << "Overflow in position with position of " << position << " in hex 0x" << std::hex << position; + } + position = position & 0x7ff; // 13 bit + + // assemble and store the tracklet word + TrackletMCMData trackletword; + buildTrackletMCMData(trackletword, slope, position, q0, q1, q2); + mMCMT[cpu] = trackletword.word; + + rawz = padrow; + rawposition = position; + + // calculate number of hits and MC label + // std::array<int, 3> mcLabel = {-1, -1, -1}; + std::array<int, 3> nHits{}; + + // const int maxLabels = 30; + // std::array<int, 30> label{}; // up to 30 different labels possible + // std::array<int, 30> count{}; + // int nLabels = 0; + std::vector<o2::MCCompLabel> localTrackletLabels; + //we have 21 adc so can fit into a 32bit bit pattern. + uint32_t adchitbp = 0; + for (int iHit = 0; iHit < mNHits; iHit++) { + if ((mHits[iHit].mChannel - mFitPtr[cpu] < 0) || + (mHits[iHit].mChannel - mFitPtr[cpu] > 1)) { + continue; + } + + // counting contributing hits + if (mHits[iHit].mTimebin >= mTrapConfig->getTrapReg(TrapConfig::kTPQS0, mDetector, mRobPos, mMcmPos) && + mHits[iHit].mTimebin < mTrapConfig->getTrapReg(TrapConfig::kTPQE0, mDetector, mRobPos, mMcmPos)) { + nHits[0]++; + } + if (mHits[iHit].mTimebin >= mTrapConfig->getTrapReg(TrapConfig::kTPQS1, mDetector, mRobPos, mMcmPos) && + mHits[iHit].mTimebin < mTrapConfig->getTrapReg(TrapConfig::kTPQE1, mDetector, mRobPos, mMcmPos)) { + nHits[1]++; + } + if (mHits[iHit].mTimebin >= 3 && mHits[iHit].mTimebin < 5) { + nHits[2]++; + } + //TODO nHits2 ???? to correspond to Q2 ??? + // + LOG(debug) << "setting bit pattern for chanel : " << mHits[iHit].mChannel << " of hit : " << iHit << std::hex << " bitp before : " << adchitbp << std::dec; + adchitbp |= (1 << mHits[iHit].mChannel); + LOG(debug) << "after setting bit pattern for chanel : " << mHits[iHit].mChannel << " of hit : " << iHit << std::hex << " bitp after : " << adchitbp << std::dec; + // TODO label calculation only if there is a digitsmanager to get the labels froAm + } + bool printoutadcs = false; + //TODO these info statemetns are left in to info the labels later. + LOG(debug) << "adc bitpatterh is " << std::hex << adchitbp << std::dec; + for (int i = 0; i < 21; i++) { + if (adchitbp & (1 << i)) { + LOG(debug) << "adding labels for adc " << i << "adc bitpatterh is " << std::hex << adchitbp << std::dec << " there are : " << mADCLabels[i].size() << " labels"; + + localTrackletLabels.insert(localTrackletLabels.end(), mADCLabels[i].begin(), mADCLabels[i].end()); // append the hit labels to this tracklets temp labels store. + if (mADCLabels[i].size() == 0) { + LOG(debug) << "BECAUSE THERE ARE NO LABELS LETS SEE WHICH ADC's DO HAVE LABELS"; + for (int j = 0; j < 21; j++) { + LOG(debug) << "ADC : " << j << " has " << mADCLabels[j].size() << " labels"; + } + printoutadcs = true; + } + } + } + //if(printoutadcs) print(PRINTRAW|PRINTFILTERED); + //labels come in via adc, now loop over ADC and see which contribute to the hits. + + LOG(debug) << "TrapSim Trackletarray size is : " << mTrackletArray64.size() << " :: adding a track at " << mMCMT[cpu] << ":" << mDetector * 2 + mRobPos % 2 << ":" << mRobPos << ":" << mMcmPos << " LABELS size: " << localTrackletLabels.size(); + uint32_t format = 0; + uint32_t hcid = mDetector * 2 + mRobPos % 2; + uint32_t padrow = ((mRobPos >> 1) << 2) | (mMcmPos >> 2); + uint32_t col = mFeeParam->getPadColFromADC(mRobPos, mMcmPos, 1); + //uint32_t position = rawoffset; + //uint32_t s + mTrackletArray64.emplace_back(format, hcid, padrow, col, position, slope, q0, q1, q2); + if (mdebugStream) { + mTrackletDetails.emplace_back(position, slope, q0, q1, q2, nHits, fitError); + } + //mTrackletArray[newtrackposition].setLabel(mcLabel); + LOG(debug) << "adding elements to mTrackletLabels of size " << mTrackletLabels.getIndexedSize() << "::" << mTrackletLabels.getNElements() << " labels for additional labels vector of :" << localTrackletLabels.size() << " labels"; + mTrackletLabels.addElements(mTrackletLabels.getIndexedSize(), localTrackletLabels); + LOG(debug) << "elements in mTrackletLabels is size " << mTrackletLabels.getIndexedSize() << "::" << mTrackletLabels.getNElements() << " labels for additional labels vector of :" << localTrackletLabels.size() << " labels"; + // store cluster information (if requested) + if (mgStoreClusters && mdebugStream) { + std::vector<float> res(getNumberOfTimeBins()); + std::vector<float> qtot(getNumberOfTimeBins()); + for (int iTimebin = 0; iTimebin < getNumberOfTimeBins(); ++iTimebin) { + res[iTimebin] = 0; + qtot[iTimebin] = 0; + } + for (int iHit = 0; iHit < mNHits; iHit++) { + int timebin = mHits[iHit].mTimebin; + + // check if hit contributes + if (mHits[iHit].mChannel == mFitPtr[cpu]) { + // for (int i=0;i<mNHits;i++) LOG(debug) << "mHits.["<<i << "].mTimebin="<< mHits[i].mTimebin; + res[timebin] = mHits[iHit].mYpos - (fitSlope * timebin + fitOffset); + qtot[timebin] = mHits[iHit].mQtot; + } else if (mHits[iHit].mChannel == mFitPtr[cpu] + 1) { + res[timebin] = mHits[iHit].mYpos + 256 - (fitSlope * timebin + fitOffset); + qtot[timebin] = mHits[iHit].mQtot; + } + } + mTrackletDetails[mTrackletDetails.size() - 1].setClusters(res, qtot, getNumberOfTimeBins()); + // TODO we no longer store clusters in 64bit tracklets, put where? + } + + if (fitError < 0) { + LOG(debug) << "fit slope: " << fitSlope << ", offset: " << fitOffset << ", error: " << TMath::Sqrt(TMath::Abs(fitError) / getNHits()); + + LOG(debug) << "Strange fit error: " << fitError << " from Sx: " << sumX << ", Sy: " << sumY << ", Sxy: " << sumXY << ", Sx2: " << sumX2 << ", Sy2: " << sumY2 << ", nHitssize: " << nHits.size(); + } + } + } } + LOG(debug) << "LEAVING : " << __FILE__ << ":" << __func__ << ":" << __LINE__ << " :: " << getDetector() << ":" << getRobPos() << ":" << getMcmPos() << " and Tracklet array size is : " << mTrackletArray64.size(); } } } - // LOG(info) << "LEAVING : " << __FILE__ << ":" << __func__ << ":" << __LINE__<<" :: "<< getDetector()<<":"<< getRobPos()<<":"<< getMcmPos() << " and Tracklet array size is : " << mTrackletArray.size(); } void TrapSimulator::tracklet() @@ -2182,14 +2349,17 @@ void TrapSimulator::tracklet() if (!mInitialized) { return; } - mTrackletArray.clear(); - + LOG(debug) << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"; + mTrackletArray64.clear(); calcFitreg(); if (mNHits == 0) { return; } trackletSelection(); fitTracklet(); + //print(15); + LOG(debug) << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"; + LOG(debug) << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"; } void TrapSimulator::getTracklet64s(std::vector<Tracklet64>& TrackletStore) @@ -2231,6 +2401,7 @@ void TrapSimulator::getTracklet64s(std::vector<Tracklet64>& TrackletStore) // 16) if >=, clip to TableLength-1 // 17) read from the LUT 8 bits // TODO the new program from Venelin will be different. +// // TODO ask someone, we are taking q0,q1,q2 and sending it back, no pid calculation? int TrapSimulator::getPID(int q0, int q1) { @@ -2242,7 +2413,7 @@ int TrapSimulator::getPID(int q0, int q1) unsigned int nBinsQ0 = mTrapConfig->getDmemUnsigned(mgkDmemAddrLUTnbins, mDetector, mRobPos, mMcmPos); // number of bins in q0 / 4 !! unsigned int pidTotalSize = mTrapConfig->getDmemUnsigned(mgkDmemAddrLUTLength, mDetector, mRobPos, mMcmPos); if (nBinsQ0 == 0 || pidTotalSize == 0) { // make sure we don't run into trouble if the value for Q0 is not configured - return 0; // Q1 not configured is ok for 1D LUT + return 0; // Q1 not configured is ok for 1D LUT } unsigned long corrQ0 = mTrapConfig->getDmemUnsigned(mgkDmemAddrLUTcor0, mDetector, mRobPos, mMcmPos); @@ -2255,7 +2426,7 @@ int TrapSimulator::getPID(int q0, int q1) addrQ0 = (((addrQ0 * q0) >> 16) >> 16); // because addrQ0 = (q0 * corrQ0) >> 32; does not work for unknown reasons if (addrQ0 >= nBinsQ0) { // check for overflow - // LOG(debug3) << "Overflow in q0: " << addrQ0 << "/4 is bigger then " << nBinsQ0; + // LOG(debug) << "Overflow in q0: " << addrQ0 << "/4 is bigger then " << nBinsQ0; addrQ0 = nBinsQ0 - 1; } @@ -2264,7 +2435,7 @@ int TrapSimulator::getPID(int q0, int q1) addr = addrQ0 + nBinsQ0 * addr; // because addr = addrQ0 + nBinsQ0* (((corrQ1*q1)>>32); does not work if (addr >= pidTotalSize) { - // LOG(debug3) << "Overflow in q1. Address " << addr << "/4 is bigger then " << pidTotalSize; + // LOG(debug) << "Overflow in q1. Address " << addr << "/4 is bigger then " << pidTotalSize; addr = pidTotalSize - 1; } @@ -2484,7 +2655,7 @@ bool TrapSimulator::readPackedConfig(TrapConfig* cfg, int hc, unsigned int* data data++; idx++; - LOG(debug3) << "read: 0x" << hex << header; + LOG(debug) << "read: 0x" << hex << header; if (header & 0x01) // single data { @@ -2496,22 +2667,22 @@ bool TrapSimulator::readPackedConfig(TrapConfig* cfg, int hc, unsigned int* data if (header & 0x02) // check if > 16 bits { dataHi = *data; - LOG(debug3) << "read: 0x" << hex << dataHi; + LOG(debug) << "read: 0x" << hex << dataHi; data++; idx++; err += ((dataHi ^ (dat | 1)) & 0xFFFF) != 0; dat = (dataHi & 0xFFFF0000) | dat; } - LOG(debug3) << "addr=0x" << hex << caddr << "(" << cfg->getRegName(cfg->getRegByAddress(caddr)) << ") data=0x" << hex << dat; + LOG(debug) << "addr=0x" << hex << caddr << "(" << cfg->getRegName(cfg->getRegByAddress(caddr)) << ") data=0x" << hex << dat; if (!cfg->poke(caddr, dat, det, rob, mcm)) { - LOG(debug3) << "(single-write): non-existing address 0x" << std::hex << caddr << " containing 0x" << std::hex << header; + LOG(debug) << "(single-write): non-existing address 0x" << std::hex << caddr << " containing 0x" << std::hex << header; } if (idx > size) { - LOG(debug3) << "(single-write): no more data, missing end marker"; + LOG(debug) << "(single-write): no more data, missing end marker"; return -err; } } else { - LOG(debug3) << "(single-write): address 0x" << setw(4) << std::hex << caddr << " => old endmarker?" << std::dec; + LOG(debug) << "(single-write): address 0x" << setw(4) << std::hex << caddr << " => old endmarker?" << std::dec; return err; } } @@ -2541,22 +2712,22 @@ bool TrapSimulator::readPackedConfig(TrapConfig* cfg, int hc, unsigned int* data bitcnt -= bwidth; if (bitcnt < 0) { header = *data; - LOG(debug3) << "read 0x" << setw(8) << std::hex << header << std::dec; + LOG(debug) << "read 0x" << setw(8) << std::hex << header << std::dec; data++; idx++; err += (header & 1); header = header >> 1; bitcnt = 31 - bwidth; } - LOG(debug3) << "addr=0x" << setw(4) << std::hex << caddr << "(" << cfg->getRegName(cfg->getRegByAddress(caddr)) << ") data=0x" << setw(8) << std::hex << (header & msk); + LOG(debug) << "addr=0x" << setw(4) << std::hex << caddr << "(" << cfg->getRegName(cfg->getRegByAddress(caddr)) << ") data=0x" << setw(8) << std::hex << (header & msk); if (!cfg->poke(caddr, header & msk, det, rob, mcm)) { - LOG(debug3) << "(single-write): non-existing address 0x" << setw(4) << std::hex << caddr << " containing 0x" << setw(8) << std::hex << header << std::dec; + LOG(debug) << "(single-write): non-existing address 0x" << setw(4) << std::hex << caddr << " containing 0x" << setw(8) << std::hex << header << std::dec; } caddr += step; header = header >> bwidth; if (idx >= size) { - LOG(debug3) << "(block-write): no end marker! " << idx << " words read"; + LOG(debug) << "(block-write): no end marker! " << idx << " words read"; return -err; } } @@ -2565,20 +2736,20 @@ bool TrapSimulator::readPackedConfig(TrapConfig* cfg, int hc, unsigned int* data case 31: { while (nwords > 0) { header = *data; - LOG(debug3) << "read 0x" << setw(8) << std::hex << header; + LOG(debug) << "read 0x" << setw(8) << std::hex << header; data++; idx++; nwords--; err += (header & 1); - LOG(debug3) << "addr=0x" << hex << setw(4) << caddr << " (" << cfg->getRegName(cfg->getRegByAddress(caddr)) << ") data=0x" << hex << setw(8) << (header >> 1); + LOG(debug) << "addr=0x" << hex << setw(4) << caddr << " (" << cfg->getRegName(cfg->getRegByAddress(caddr)) << ") data=0x" << hex << setw(8) << (header >> 1); if (!cfg->poke(caddr, header >> 1, det, rob, mcm)) { - LOG(debug3) << "(single-write): non-existing address 0x" << setw(4) << std::hex << " containing 0x" << setw(8) << std::hex << header << std::dec; + LOG(debug) << "(single-write): non-existing address 0x" << setw(4) << std::hex << " containing 0x" << setw(8) << std::hex << header << std::dec; } caddr += step; if (idx >= size) { - LOG(debug3) << "no end marker! " << idx << " words read"; + LOG(debug) << "no end marker! " << idx << " words read"; return -err; } } diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h index f4726390e26b0..34d77dc76372a 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrapSimulatorSpec.h @@ -64,8 +64,6 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task bool mDebugRejectedTracklets{false}; bool mEnableOnlineGainCorrection{false}; bool mEnableTrapConfigDump{false}; - bool mFixTriggerRecords{false}; // shift the trigger record due to its being corrupt on coming in. - bool mDumpTriggerRecords{false}; // display the trigger records. std::vector<Tracklet64> mTracklets; // store of found tracklets std::string mTrapConfigName; // the name of the config to be used. std::string mTrapConfigBaseName = "TRD_test/TrapConfig/"; @@ -92,6 +90,7 @@ class TRDDPLTrapSimulatorTask : public o2::framework::Task TrackletHCHeader mTrackletHCHeader; // the current half chamber header, that will be written if a first tracklet is found for this halfchamber. TrapConfig* getTrapConfig(); void loadTrapConfig(); + void loadDefaultTrapConfig(); void setOnlineGainTables(); }; diff --git a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx index 00079d0fce8c9..beee2b7c22c33 100644 --- a/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx @@ -25,6 +25,7 @@ #include <fstream> #include "TChain.h" +#include "TFile.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" @@ -81,15 +82,29 @@ TrapConfig* TRDDPLTrapSimulatorTask::getTrapConfig() // try to load the requested configuration loadTrapConfig(); //calib. - LOG(info) << "using TRAPconfig :\"" << mTrapConfig->getConfigName().c_str() << "\".\"" << mTrapConfig->getConfigVersion().c_str() << "\""; - + if (mTrapConfig->getConfigName() == "" && mTrapConfig->getConfigVersion() == "") { + //some trap configs dont have config name and version set, in those cases, just show the file name used. + LOG(info) << "using TRAPconfig :\"" << mTrapConfigName; + } else { + LOG(info) << "using TRAPconfig :\"" << mTrapConfig->getConfigName().c_str() << "\".\"" << mTrapConfig->getConfigVersion().c_str() << "\""; + } // we still have to load the gain tables // if the gain filter is active return mTrapConfig; } // end of else from if mTrapConfig } - +void TRDDPLTrapSimulatorTask::loadDefaultTrapConfig() +{ + //this loads a trap config from a root file for those times when the ccdb is not around and you want to keep working. + TFile* f; + f = new TFile("DefaultTrapConfig.root"); + mTrapConfig = (o2::trd::TrapConfig*)f->Get("ccdb_object"); + if (mTrapConfig == nullptr) { + LOG(fatal) << "failed to load from ccdb, and attempted to load from disk, you seem to be really out of luck."; + } + // else we have loaded the trap config successfully. +} void TRDDPLTrapSimulatorTask::loadTrapConfig() { // try to load the specified configuration from the CCDB @@ -98,13 +113,14 @@ void TRDDPLTrapSimulatorTask::loadTrapConfig() auto& ccdbmgr = o2::ccdb::BasicCCDBManager::instance(); ccdbmgr.setTimestamp(mRunNumber); - //default is : mTrapConfigName="dcf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"; - mTrapConfigName = "c"; + //default is : mTrapConfigName="cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"; + mTrapConfigName = "c"; //cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"; mTrapConfig = ccdbmgr.get<o2::trd::TrapConfig>("TRD_test/TrapConfig2020/" + mTrapConfigName); if (mTrapConfig == nullptr) { //failed to find or open or connect or something to get the trapconfig from the ccdb. //first check the directory listing. LOG(warn) << " failed to get trapconfig from ccdb with name : " << mTrapConfigName; + loadDefaultTrapConfig(); } else { //TODO figure out how to get the debug level from logger and only do this for debug option to --severity debug (or what ever the command actualy is) if (mEnableTrapConfigDump) { @@ -162,6 +178,7 @@ void TRDDPLTrapSimulatorTask::setOnlineGainTables() void TRDDPLTrapSimulatorTask::init(o2::framework::InitContext& ic) { + LOG(debug) << "entering init"; mFeeParam = FeeParam::instance(); mPrintTrackletOptions = ic.options().get<int>("trd-printtracklets"); mDrawTrackletOptions = ic.options().get<int>("trd-drawtracklets"); @@ -172,9 +189,7 @@ void TRDDPLTrapSimulatorTask::init(o2::framework::InitContext& ic) mOnlineGainTableName = ic.options().get<std::string>("trd-onlinegaintable"); mRunNumber = ic.options().get<int>("trd-runnum"); mEnableTrapConfigDump = ic.options().get<bool>("trd-dumptrapconfig"); - mDumpTriggerRecords = ic.options().get<bool>("trd-dumptriggerrecords"); - mFixTriggerRecords = ic.options().get<bool>("trd-fixtriggerrecord"); - //Connect to CCDB for all things needing access to ccdb. + //Connect to CCDB for all things needing access to ccdb, trapconfig and online gains auto& ccdbmgr = o2::ccdb::BasicCCDBManager::instance(); mCalib = std::make_unique<Calibrations>(); mCalib->setCCDBForSimulation(mRunNumber); @@ -266,82 +281,71 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) // the digits are going to be sorted, we therefore need a copy of the vector rather than an object created // directly on the input data, the output vector however is created directly inside the message // memory thus avoiding copy by snapshot + + /********* + * iNPUTS + ********/ + auto inputDigits = pc.inputs().get<gsl::span<o2::trd::Digit>>("digitinput"); std::vector<o2::trd::Digit> msgDigits(inputDigits.begin(), inputDigits.end()); // auto digits pc.outputs().make<std::vector<o2::trd::Digit>>(Output{"TRD", "TRKDIGITS", 0, Lifetime::Timeframe}, msgDigits.begin(), msgDigits.end()); auto digitMCLabels = pc.inputs().get<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>("labelinput"); - - // auto rawDataOut = pc.outputs().make<char>(Output{"TRD", "RAWDATA", 0, Lifetime::Timeframe}, 1000); //TODO number is just a place holder until we start using it. - o2::dataformats::MCTruthContainer<o2::MCCompLabel> trackletMCLabels; - // the returned object is read-only as it refers directly to the underlying raw input data // need to make a copy because the object might be changed in fixTriggerRecords auto inputTriggerRecords = pc.inputs().get<gsl::span<o2::trd::TriggerRecord>>("triggerrecords"); - // trigger records to index the 64bit tracklets.yy - std::vector<o2::trd::TriggerRecord> triggerRecords(inputTriggerRecords.begin(), inputTriggerRecords.end()); - // trigger records to index the "raw" data - - uint64_t currentTriggerRecord = 0; - for (auto& trig : triggerRecords) { - if (mDumpTriggerRecords) { - LOG(info) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); - } else { - LOG(debug) << "Trigger Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); - } - } - // fix incoming trigger records if requested. - if (mFixTriggerRecords) { - fixTriggerRecords(triggerRecords); - } + /* ***** + * setup data objects + * *****/ + // trigger records to index the 64bit tracklets.yy + std::vector<o2::trd::TriggerRecord> triggerRecords(inputTriggerRecords.begin(), inputTriggerRecords.end()); std::vector<o2::trd::TriggerRecord> trackletTriggerRecords = triggerRecords; // copy over the whole thing but we only really want the bunch crossing info. std::vector<o2::trd::TriggerRecord> rawTriggerRecords = triggerRecords; // as we have the option of having tracklets and/or raw data, we need both triggerrecords. // of course we dont *actually* need it we could simply walk through all the raw data header to header. - mLinkRecords.reserve(1077 * triggerRecords.size()); // worse case scenario is all links for all events. TODO get 1077 from somewhere. + // auto rawDataOut = pc.outputs().make<char>(Output{"TRD", "RAWDATA", 0, Lifetime::Timeframe}, 1000); //TODO number is just a place holder until we start using it. + o2::dataformats::MCTruthContainer<o2::MCCompLabel> trackletMCLabels; + //index of digits, TODO refactor to a digitindex class. + std::vector<unsigned int> msgDigitsIndex(msgDigits.size()); + //set up structures to hold the returning tracklets. + std::vector<Tracklet64> trapTracklets; //vector to store the retrieved tracklets from an trapsim object + std::vector<Tracklet64> trapTrackletsAccum; + std::vector<uint32_t> rawdata; + // trigger records to index the "raw" data + uint64_t currentTriggerRecord = 0; + /* ******* + * reserve sizes + * *******/ + mLinkRecords.reserve(1080 * triggerRecords.size()); // worse case scenario is all links for all events. TODO get 1080 from somewhere. //TODO these must be created directly in the output as done at the top of this run method - std::vector<unsigned int> msgDigitsIndex; - msgDigitsIndex.reserve(msgDigits.size()); - + //msgDigitsIndex.reserve(msgDigits.size()); LOG(debug) << "Read in msgDigits with size of : " << msgDigits.size() << " labels contain : " << digitMCLabels.getNElements() << " with and index size of : " << digitMCLabels.getIndexedSize() << " and triggerrecord count of :" << triggerRecords.size(); - if (digitMCLabels.getIndexedSize() != msgDigits.size()) { LOG(warn) << "Digits and Labels coming into TrapSimulator are of differing sizes, labels will be jibberish. " << digitMCLabels.getIndexedSize() << "!=" << msgDigits.size(); } - //set up structures to hold the returning tracklets. - std::vector<Tracklet64> trapTracklets; //vector to store the retrieved tracklets from an trapsim object - std::vector<Tracklet64> trapTrackletsAccum; - std::vector<uint32_t> rawdata; - trapTracklets.reserve(30); trapTrackletsAccum.reserve(msgDigits.size() / 3); - msgDigitsIndex.reserve(msgDigits.size()); + //msgDigitsIndex.reserve(msgDigits.size()); // worse case scenario is header and single tracklet word, hence 2, for higher tracklet count the factors reduces relative to tracklet count. Remember 3 digits per tracklet. rawdata.reserve(msgDigits.size() * 2); - int count = 0; - //make msgDigitsIndex a simple vector of ascending numbers mapping trivially into the msgDigits vector. - for (int i = 0; i < msgDigits.size(); i++) { - msgDigitsIndex.push_back(i); + //Build the digits index. + // std::iota(msgDigitsIndex.begin(), msgDigitsIndex.end(), static_cast<unsigned int>(0)); + std::generate(msgDigitsIndex.begin(), msgDigitsIndex.end(), [n = 0]() mutable { return n++; }); + int indexcount = 0; + for (auto index : msgDigitsIndex) { + LOG(debug) << indexcount << ":" << index; + } + if (msgDigitsIndex.size() != msgDigits.size()) { + //error condition for sort. + LOG(fatal) << "Cant index digits as index and digits differ in size, this is not permitted. Digits size=" << msgDigits.size() << " and index size=" << msgDigitsIndex.size(); } - LOG(debug) << "msgdigitsindex is " << msgDigitsIndex.size(); - - auto sortstart = std::chrono::high_resolution_clock::now(); //sort the digits array TODO refactor this intoa vector index sort and possibly generalise past merely digits. + auto sortstart = std::chrono::high_resolution_clock::now(); for (auto& trig : triggerRecords) { - LOG(debug) << " sorting from index: " << trig.getFirstEntry() << " till " << trig.getNumberOfObjects() + trig.getFirstEntry(); - LOG(debug) << "pre sort"; - for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) { - LOG(debug) << "i:" << msgDigitsIndex[i]; - } std::stable_sort(std::begin(msgDigitsIndex) + trig.getFirstEntry(), std::begin(msgDigitsIndex) + trig.getNumberOfObjects() + trig.getFirstEntry(), [&msgDigits](auto&& PH1, auto&& PH2) { return digitindexcompare(PH1, PH2, msgDigits); }); - LOG(debug) << "post sort"; - for (int i = msgDigitsIndex[trig.getFirstEntry()]; i < trig.getNumberOfObjects() + trig.getFirstEntry(); i++) { - LOG(debug) << "i:" << i << " = " << msgDigitsIndex[i]; - } - LOG(debug) << "*****************************************************************"; } mSortingTime = std::chrono::high_resolution_clock::now() - sortstart; @@ -357,7 +361,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) LOG(debug) << "Trigger Tracklet Record ; " << trig.getFirstEntry() << " --> " << trig.getNumberOfObjects(); } //print digits to check the sorting. - LOG(info) << " Digits : "; + LOG(debug) << " Digits : "; //for (auto& digit : msgDigits) { for (auto& digitindex : msgDigitsIndex) { Digit digit = msgDigits[digitindex]; @@ -371,8 +375,9 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) << " with ORI# : " << mFeeParam->getORI(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())) << " within SM ori#:" << mFeeParam->getORIinSM(digit.getDetector(), mFeeParam->getROBfromPad(digit.getRow(), digit.getPad())); } + //accounting variables for various things. - //TODO make them class members, i dont want to fiddle right now though. + //TODO make them class members int olddetector = -1; int oldrow = -1; int oldpad = -1; @@ -445,9 +450,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) unsigned long numberofusedtraps = 0; for (int trapcounter = 0; trapcounter < 8; trapcounter++) { unsigned int isinit = mTrapSimulator[trapcounter].checkInitialized(); - LOG(debug) << "Start of trap : " << trapcounter; if (mTrapSimulator[trapcounter].isDataSet()) { //firedtraps - LOG(debug3) << "DataSet on : " << trapcounter; //this one has been filled with data for the now previous pad row. auto trapsimtimerstart = std::chrono::high_resolution_clock::now(); mTrapUsedCounter[trapcounter]++; @@ -498,7 +501,7 @@ void TRDDPLTrapSimulatorTask::run(o2::framework::ProcessingContext& pc) if (mDebugRejectedTracklets) { //&& trapTracklets.size()==0) { mTrapSimulator[trapcounter].draw(7, loopindex); //draw adc when no tracklets are found.A LOG(debug) << "loop index : " << loopindex; - mTrapSimulator[trapcounter].print(1); + //mTrapSimulator[trapcounter].print(1); } if (mPrintTrackletOptions != 0) { mTrapSimulator[trapcounter].print(mPrintTrackletOptions); @@ -633,12 +636,10 @@ o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec() {"trd-trapconfig", VariantType::String, "cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549", {"Name of the trap config from the CCDB default:cf_pg-fpnp32_zs-s16-deh_tb30_trkl-b5n-fs1e24-ht200-qs0e24s24e23-pidlinear-pt100_ptrg.r5549"}}, {"trd-drawtracklets", VariantType::Int, 0, {"Bitpattern of input to TrapSimulator Draw method one histogram per chip not per tracklet, 1=raw,2=hits,4=tracklets, 7 for all"}}, {"trd-printtracklets", VariantType::Int, 0, {"Bitpattern of input to TrapSimulator print method, "}}, - {"trd-fixtriggerrecord", VariantType::Bool, false, {"Fix trigger record alignment, temporary, hence false by default"}}, {"trd-onlinegaincorrection", VariantType::Bool, false, {"Apply online gain calibrations, mostly for back checking to run2 by setting FGBY to 0"}}, {"trd-onlinegaintable", VariantType::String, "Krypton_2015-02", {"Online gain table to be use, names found in CCDB, obviously trd-onlinegaincorrection must be set as well."}}, {"trd-debugrejectedtracklets", VariantType::Bool, false, {"Output all MCM where tracklets were not identified"}}, {"trd-dumptrapconfig", VariantType::Bool, false, {"Dump the selected trap configuration at loading time, to text file"}}, - {"trd-dumptriggerrecords", VariantType::Bool, false, {"Dump the trigger record to the default log output"}}, {"trd-runnum", VariantType::Int, 297595, {"Run number to use to anchor simulation to, defaults to 297595"}}}}; }; From 2ca744c842b4d2128e9124ecfb5150fd67c1c450 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 14:25:50 +0100 Subject: [PATCH 1519/1751] Fix array out of bounds segfault after unexpected end of payload --- Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx index 20f8b16b3651d..38446717e0c79 100644 --- a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx @@ -81,7 +81,7 @@ void AltroDecoder::readChannels() // decode bunches int currentsample = 0; - while (currentsample < currentchannel.getPayloadSize()) { + while (currentsample < currentchannel.getPayloadSize() && bunchwords.size() > currentsample) { int bunchlength = bunchwords[currentsample] - 2, // remove words for bunchlength and starttime starttime = bunchwords[currentsample + 1]; auto& currentbunch = currentchannel.createBunch(bunchlength, starttime); From 57c0ec5ba3831c1c5a459afe360fb7104a5f017b Mon Sep 17 00:00:00 2001 From: Fabio Catalano <fabio.catalano@cern.ch> Date: Thu, 3 Dec 2020 16:13:36 +0100 Subject: [PATCH 1520/1751] Add Dplus analysis variables and update Dplus task histograms (#4797) --- Analysis/Core/include/Analysis/RecoDecay.h | 85 +++++++++++++++++- .../include/Analysis/HFSecondaryVertex.h | 11 +++ Analysis/Tasks/PWGHF/taskDPlus.cxx | 87 +++++++++++-------- 3 files changed, 146 insertions(+), 37 deletions(-) diff --git a/Analysis/Core/include/Analysis/RecoDecay.h b/Analysis/Core/include/Analysis/RecoDecay.h index db22e655a3e4b..d9a8827371d02 100644 --- a/Analysis/Core/include/Analysis/RecoDecay.h +++ b/Analysis/Core/include/Analysis/RecoDecay.h @@ -101,7 +101,7 @@ class RecoDecay } /// Calculates scalar product of vectors. - /// \note Promotes numbers to double before squaring to avoid precision loss in float multiplication. + /// \note Promotes numbers to double to avoid precision loss in float multiplication. /// \param N dimension /// \param vec1,vec2 vectors /// \return scalar product @@ -115,6 +115,19 @@ class RecoDecay return res; } + /// FIXME: probably cross and dot products should be in some utility class + /// Calculates cross product of vectors in three dimensions. + /// \note Promotes numbers to double to avoid precision loss in float multiplication. + /// \param vec1,vec2 vectors + /// \return cross-product vector + template <typename T, typename U> + static array<double, 3> crossProd(const array<T, 3>& vec1, const array<U, 3>& vec2) + { + return array<double, 3>{((double)vec1[1] * (double)vec2[2]) - ((double)vec1[2] * (double)vec2[1]), + ((double)vec1[2] * (double)vec2[0]) - ((double)vec1[0] * (double)vec2[2]), + ((double)vec1[0] * (double)vec2[1]) - ((double)vec1[1] * (double)vec2[0])}; + } + /// Calculates magnitude squared of a vector. /// \param N dimension /// \param vec vector @@ -406,6 +419,76 @@ class RecoDecay return std::sqrt(M2(args...)); } + // Calculation of topological quantities + + /// Calculates impact parameter in the bending plane of the particle w.r.t. a point + /// \param point {x, y, z} position of the point + /// \param posSV {x, y, z} position of the secondary vertex + /// \param mom {x, y, z} particle momentum array + /// \return impact parameter in {x, y} + template <typename T, typename U, typename V> + static double ImpParXY(const T& point, const U& posSV, const array<V, 3>& mom) + { + // Ported from AliAODRecoDecay::ImpParXY + auto flightLineXY = array{posSV[0] - point[0], posSV[1] - point[1]}; + auto k = dotProd(flightLineXY, array{mom[0], mom[1]}) / Pt2(mom); + auto dx = flightLineXY[0] - k * (double)mom[0]; + auto dy = flightLineXY[1] - k * (double)mom[1]; + auto absImpPar = sqrtSumOfSquares(dx, dy); + auto flightLine = array{posSV[0] - point[0], posSV[1] - point[1], posSV[2] - point[2]}; + auto cross = crossProd(mom, flightLine); + return (cross[2] > 0. ? absImpPar : -1. * absImpPar); + } + + /// Calculates the difference between measured and expected track impact parameter + /// normalized to its uncertainty + /// \param decLenXY decay lenght in {x, y} plane + /// \param errDecLenXY error on decay lenght in {x, y} plane + /// \param momMother {x, y, z} or {x, y} candidate momentum array + /// \param impParProng prong impact parameter + /// \param errImpParProng error on prong impact parameter + /// \param momProng {x, y, z} or {x, y} prong momentum array + /// \return normalized difference between expected and observed impact parameter + template <std::size_t N, std::size_t M, typename T, typename U, typename V, typename W, typename X, typename Y> + static double normImpParMeasMinusExpProng(T decLenXY, U errDecLenXY, const array<V, N>& momMother, W impParProng, + X errImpParProng, const array<Y, M>& momProng) + { + // Ported from AliAODRecoDecayHF::Getd0MeasMinusExpProng adding normalization directly in the function + auto sinThetaP = ((double)momProng[0] * (double)momMother[1] - (double)momProng[1] * (double)momMother[0]) / + (Pt(momProng) * Pt(momMother)); + auto diff = impParProng - (double)decLenXY * sinThetaP; + auto errImpParExpProng = (double)errDecLenXY * sinThetaP; + auto errDiff = sqrtSumOfSquares(errImpParProng, errImpParExpProng); + return (errDiff > 0. ? diff / errDiff : 0.); + } + + /// Calculates maximum normalized difference between measured and expected impact parameter of candidate prongs + /// \param posPV {x, y, z} or {x, y} position of primary vertex + /// \param posSV {x, y, z} or {x, y} position of secondary vertex + /// \param errDecLenXY error on decay lenght in {x, y} plane + /// \param momMother {x, y, z} or {x, y} candidate momentum array + /// \param arrImpPar array of prong impact parameters + /// \param arrErrImpPar array of errors on prong impact parameter (same order as arrImpPar) + /// \param momMom array of {x, y, z} or {x, y} prong momenta (same order as arrImpPar) + /// \return maximum normalized difference between expected and observed impact parameters + template <std::size_t N, std::size_t M, std::size_t K, typename T, typename U, typename V, typename W, typename X, + typename Y, typename Z> + static double maxNormalisedDeltaIP(const T& posPV, const U& posSV, V errDecLenXY, const array<W, M>& momMother, + const array<X, N>& arrImpPar, const array<Y, N>& arrErrImpPar, + const array<array<Z, K>, N>& arrMom) + { + auto decLenXY = distanceXY(posPV, posSV); + double maxNormDeltaIP{0.}; + for (auto iProng = 0; iProng < N; ++iProng) { + auto prongNormDeltaIP = normImpParMeasMinusExpProng(decLenXY, errDecLenXY, momMother, arrImpPar[iProng], + arrErrImpPar[iProng], arrMom[iProng]); + if (std::abs(prongNormDeltaIP) > std::abs(maxNormDeltaIP)) { + maxNormDeltaIP = prongNormDeltaIP; + } + } + return maxNormDeltaIP; + } + /// Returns particle mass based on PDG code. /// \param pdg PDG code /// \return particle mass diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h index 58d6a1b9076bc..d3a2dfefe521a 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h @@ -134,6 +134,7 @@ DECLARE_SOA_COLUMN(ErrorDecayLengthXY, errorDecayLengthXY, float); DECLARE_SOA_DYNAMIC_COLUMN(CPA, cpa, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) { return RecoDecay::CPA(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(CPAXY, cpaXY, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float px, float py) { return RecoDecay::CPAXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, array{px, py}); }); DECLARE_SOA_DYNAMIC_COLUMN(Ct, ct, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) { return RecoDecay::Ct(array{px, py, pz}, RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}), m); }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) { return RecoDecay::ImpParXY(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); }); } // namespace hf_cand // specific 2-prong decay properties @@ -146,6 +147,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, [](fl DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array<double, 2>& m, double mTot, int iProng) { return RecoDecay::CosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, [](float impParProng0, float impParProng1) { return RecoDecay::sumOfSquares(impParProng0, impParProng1); }); +DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) { return RecoDecay::maxNormalisedDeltaIP(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, errDlxy, array{pxM, pyM}, array{ip0, ip1}, array{errIp0, errIp1}, array{array{px0, py0}, array{px1, py1}}); }); // MC matching result: // - ±D0ToPiK: D0(bar) → π± K∓ DECLARE_SOA_COLUMN(FlagMCMatchRec, flagMCMatchRec, int8_t); // reconstruction level @@ -236,6 +239,7 @@ DECLARE_SOA_TABLE(HfCandProng2Base, "AOD", "HFCANDP2BASE", hf_cand_prong2::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, hf_cand_prong2::ImpactParameterProduct<hf_cand::ImpactParameter0, hf_cand::ImpactParameter1>, hf_cand_prong2::CosThetaStar<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, + hf_cand_prong2::ImpactParameterProngSqSum<hf_cand::ImpactParameter0, hf_cand::ImpactParameter1>, /* dynamic columns that use candidate momentum components */ hf_cand::Pt<hf_cand_prong2::Px, hf_cand_prong2::Py>, hf_cand::Pt2<hf_cand_prong2::Px, hf_cand_prong2::Py>, @@ -245,6 +249,8 @@ DECLARE_SOA_TABLE(HfCandProng2Base, "AOD", "HFCANDP2BASE", hf_cand::CPA<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, hf_cand::CPAXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py>, hf_cand::Ct<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand::ImpactParameterXY<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, + hf_cand_prong2::MaxNormalisedDeltaIP<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ErrorDecayLengthXY, hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter1, hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PxProng1, hf_cand::PyProng1>, hf_cand::Eta<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, hf_cand::Phi<hf_cand_prong2::Px, hf_cand_prong2::Py>, hf_cand::Y<hf_cand_prong2::Px, hf_cand_prong2::Py, hf_cand_prong2::Pz>, @@ -273,6 +279,8 @@ DECLARE_SOA_EXPRESSION_COLUMN(Py, py, float, 1.f * aod::hf_cand::pyProng0 + 1.f DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1 + 1.f * aod::hf_cand::pzProng2); DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array<double, 3>& m) { return RecoDecay::M2(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, [](float impParProng0, float impParProng1, float impParProng2) { return RecoDecay::sumOfSquares(impParProng0, impParProng1, impParProng2); }); +DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float ip2, float errIp2, float px0, float py0, float px1, float py1, float px2, float py2) { return RecoDecay::maxNormalisedDeltaIP(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, errDlxy, array{pxM, pyM}, array{ip0, ip1, ip2}, array{errIp0, errIp1, errIp2}, array{array{px0, py0}, array{px1, py1}, array{px2, py2}}); }); // MC matching result: // - ±DPlusToPiKPi: D± → π± K∓ π± // - ±LcToPKPi: Λc± → p± K∓ π± @@ -352,6 +360,7 @@ DECLARE_SOA_TABLE(HfCandProng3Base, "AOD", "HFCANDP3BASE", /* dynamic columns */ hf_cand_prong3::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, hf_cand_prong3::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, + hf_cand_prong3::ImpactParameterProngSqSum<hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2>, /* prong 2 */ hf_cand::ImpactParameterNormalised2<hf_cand::ImpactParameter2, hf_cand::ErrorImpactParameter2>, hf_cand::PtProng2<hf_cand::PxProng2, hf_cand::PyProng2>, @@ -366,6 +375,8 @@ DECLARE_SOA_TABLE(HfCandProng3Base, "AOD", "HFCANDP3BASE", hf_cand::CPA<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, hf_cand::CPAXY<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py>, hf_cand::Ct<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand::ImpactParameterXY<collision::PosX, collision::PosY, collision::PosZ, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, + hf_cand_prong3::MaxNormalisedDeltaIP<collision::PosX, collision::PosY, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ErrorDecayLengthXY, hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand::ImpactParameter0, hf_cand::ErrorImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter1, hf_cand::ImpactParameter2, hf_cand::ErrorImpactParameter2, hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PxProng2, hf_cand::PyProng2>, hf_cand::Eta<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, hf_cand::Phi<hf_cand_prong3::Px, hf_cand_prong3::Py>, hf_cand::Y<hf_cand_prong3::Px, hf_cand_prong3::Py, hf_cand_prong3::Pz>, diff --git a/Analysis/Tasks/PWGHF/taskDPlus.cxx b/Analysis/Tasks/PWGHF/taskDPlus.cxx index e422476a556f0..cf2af649c6c49 100644 --- a/Analysis/Tasks/PWGHF/taskDPlus.cxx +++ b/Analysis/Tasks/PWGHF/taskDPlus.cxx @@ -16,6 +16,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Analysis/HFSecondaryVertex.h" #include "Analysis/HFCandidateSelectionTables.h" @@ -26,23 +27,32 @@ using namespace o2::aod::hf_cand_prong3; /// D± analysis task struct TaskDPlus { - OutputObj<TH1F> hmass{TH1F("hmass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 2.1)}; - OutputObj<TH1F> hptcand{TH1F("hptcand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong0{TH1F("hptprong0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong1{TH1F("hptprong1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong2{TH1F("hptprong2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "3-prong candidates;decay length (cm);entries", 200, 0., 2.)}; - OutputObj<TH1F> hdeclengthxy{TH1F("declengthxy", "3-prong candidates;decay length xy (cm);entries", 200, 0., 2.)}; - OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hd0Prong2{TH1F("hd0Prong2", "3-prong candidates;prong 2 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hCt{TH1F("hCt", "3-prong candidates;proper lifetime (D^{#pm}) * #it{c} (cm);entries", 120, -20., 100.)}; - OutputObj<TH1F> hCPA{TH1F("hCPA", "3-prong candidates;cosine of pointing angle;entries", 110, -1.1, 1.1)}; - OutputObj<TH1F> hEta{TH1F("hEta", "3-prong candidates;candidate #it{#eta};entries", 100, -2., 2.)}; - //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "3-prong candidates;selection status;entries", 5, -0.5, 4.5)}; - OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "3-prong candidates;impact parameter error (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "3-prong candidates;decay length error (cm);entries", 100, 0., 1.)}; - OutputObj<TH1F> hDecLenXYErr{TH1F("hDecLenXYErr", "3-prong candidates;decay length xy error (cm);entries", 100, 0., 1.)}; + HistogramRegistry registry{ + "registry", + { + {"hMass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{350, 1.7, 2.05}}}}, + {"hPt", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hEta", "3-prong candidates;candidate #it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, + {"hCt", "3-prong candidates;proper lifetime (D^{#pm}) * #it{c} (cm);entries", {HistType::kTH1F, {{120, -20., 100.}}}}, + {"hDecayLength", "3-prong candidates;decay length (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, + {"hDecayLengthXY", "3-prong candidates;decay length xy (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, + {"hNormalisedDecayLengthXY", "3-prong candidates;norm. decay length xy;entries", {HistType::kTH1F, {{80, 0., 80.}}}}, + {"hCPA", "3-prong candidates;cos. pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hCPAxy", "3-prong candidates;cos. pointing angle xy;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hImpactParameterXY", "3-prong candidates;impact parameter xy (cm);entries", {HistType::kTH1F, {{200, -1., 1.}}}}, + {"hMaxNormalisedDeltaIP", "3-prong candidates;norm. IP;entries", {HistType::kTH1F, {{200, -20., 20.}}}}, + {"hImpactParameterProngSqSum", "3-prong candidates;squared sum of prong imp. par. (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.}}}}, + {"hDecayLengthError", "3-prong candidates;decay length error (cm);entries", {HistType::kTH1F, {{100, 0., 1.}}}}, + {"hDecayLengthXYError", "3-prong candidates;decay length xy error (cm);entries", {HistType::kTH1F, {{100, 0., 1.}}}}, + {"hImpactParameterError", "3-prong candidates;impact parameter error (cm);entries", {HistType::kTH1F, {{100, 0., 1.}}}}, + {"hPtProng0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtProng1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtProng2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hd0Prong0", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hd0Prong1", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hd0Prong2", "3-prong candidates;prong 2 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}} + //{"hSelectionStatus", "3-prong candidates;selection status;entries", {HistType::kTH1F, {{5, -0.5, 4.5}}}} + }}; Configurable<int> d_selectionFlagDPlus{"d_selectionFlagDPlus", 1, "Selection Flag for DPlus"}; @@ -52,25 +62,30 @@ struct TaskDPlus { void process(aod::HfCandProng3 const& candidates) { for (auto& candidate : candidates) { - hmass->Fill(InvMassDPlus(candidate)); - hptcand->Fill(candidate.pt()); - hptprong0->Fill(candidate.ptProng0()); - hptprong1->Fill(candidate.ptProng1()); - hptprong2->Fill(candidate.ptProng2()); - hdeclength->Fill(candidate.decayLength()); - hdeclengthxy->Fill(candidate.decayLengthXY()); - hd0Prong0->Fill(candidate.impactParameter0()); - hd0Prong1->Fill(candidate.impactParameter1()); - hd0Prong2->Fill(candidate.impactParameter2()); - hCt->Fill(CtDPlus(candidate)); - hCPA->Fill(candidate.cpa()); - hEta->Fill(candidate.eta()); - //hselectionstatus->Fill(candidate.isSelDPlus()); - hImpParErr->Fill(candidate.errorImpactParameter0()); - hImpParErr->Fill(candidate.errorImpactParameter1()); - hImpParErr->Fill(candidate.errorImpactParameter2()); - hDecLenErr->Fill(candidate.errorDecayLength()); - hDecLenXYErr->Fill(candidate.errorDecayLengthXY()); + registry.get<TH1>("hMass")->Fill(InvMassDPlus(candidate)); + registry.get<TH1>("hPt")->Fill(candidate.pt()); + registry.get<TH1>("hEta")->Fill(candidate.eta()); + registry.get<TH1>("hCt")->Fill(CtDPlus(candidate)); + registry.get<TH1>("hDecayLength")->Fill(candidate.decayLength()); + registry.get<TH1>("hDecayLengthXY")->Fill(candidate.decayLengthXY()); + registry.get<TH1>("hNormalisedDecayLengthXY")->Fill(candidate.decayLengthXYNormalised()); + registry.get<TH1>("hCPA")->Fill(candidate.cpa()); + registry.get<TH1>("hCPAxy")->Fill(candidate.cpaXY()); + registry.get<TH1>("hImpactParameterXY")->Fill(candidate.impactParameterXY()); + registry.get<TH1>("hMaxNormalisedDeltaIP")->Fill(candidate.maxNormalisedDeltaIP()); + registry.get<TH1>("hImpactParameterProngSqSum")->Fill(candidate.impactParameterProngSqSum()); + registry.get<TH1>("hDecayLengthError")->Fill(candidate.errorDecayLength()); + registry.get<TH1>("hDecayLengthXYError")->Fill(candidate.errorDecayLengthXY()); + registry.get<TH1>("hImpactParameterError")->Fill(candidate.errorImpactParameter0()); + registry.get<TH1>("hImpactParameterError")->Fill(candidate.errorImpactParameter1()); + registry.get<TH1>("hImpactParameterError")->Fill(candidate.errorImpactParameter2()); + registry.get<TH1>("hPtProng0")->Fill(candidate.ptProng0()); + registry.get<TH1>("hPtProng1")->Fill(candidate.ptProng1()); + registry.get<TH1>("hPtProng2")->Fill(candidate.ptProng2()); + registry.get<TH1>("hd0Prong0")->Fill(candidate.impactParameter0()); + registry.get<TH1>("hd0Prong1")->Fill(candidate.impactParameter1()); + registry.get<TH1>("hd0Prong2")->Fill(candidate.impactParameter2()); + //registry.get<TH1>("hSelectionStatus")->Fill(candidate.isSelDPlus()); } } }; From 96b8af65fa919abbde48270106f88449d40d389a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 15:07:20 +0100 Subject: [PATCH 1521/1751] Do throw by default when running out of shared memory in full system test dpl workflow --- prodtests/full-system-test/dpl-workflow.sh | 6 ++++-- prodtests/full-system-test/setenv.sh | 1 + prodtests/full-system-test/start_tmux.sh | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 1883d3ce80aff..ebf96c88d26e4 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -8,11 +8,13 @@ if [ "0$ALIENVLVL" == "0" ]; then alienv --no-refresh load O2/latest fi -ARGS_ALL="--session default --severity $SEVERITY --shm-segment-id $NUMAID --shm-throw-bad-alloc 0 --shm-segment-size $SHMSIZE" - +ARGS_ALL="--session default --severity $SEVERITY --shm-segment-id $NUMAID --shm-segment-size $SHMSIZE" if [ $EXTINPUT == 1 ] || [ $NUMAGPUIDS == 1 ]; then ARGS_ALL+=" --no-cleanup" fi +if [ $SHMTHROW == 0 ]; then + ARGS_ALL+=" --shm-throw-bad-alloc 0" +fi if [ $EXTINPUT == 1 ]; then CMD_X="B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA" diff --git a/prodtests/full-system-test/setenv.sh b/prodtests/full-system-test/setenv.sh index 51833d529cb06..53feeb0f7c5af 100755 --- a/prodtests/full-system-test/setenv.sh +++ b/prodtests/full-system-test/setenv.sh @@ -24,6 +24,7 @@ if [ -z "$NHBPERTF" ]; then export NHBPERTF=128; fi # Time fr if [ -z "$GLOBALDPLOPT" ]; then export GLOBALDPLOPT=; fi # Global DPL workflow options appended at the end if [ -z "$EPNPIPELINES" ]; then export EPNPIPELINES=0; fi # Set default EPN pipeline multiplicities if [ -z "$SEVERITY" ]; then export SEVERITY="info"; fi # Log verbosity +if [ -z "$SHMTHROW" ]; then export SHMTHROW=1; fi # Throw exception when running out of SHM SEVERITY_TPC="info" # overrides severity for the tpc workflow DISABLE_MC="--disable-mc" diff --git a/prodtests/full-system-test/start_tmux.sh b/prodtests/full-system-test/start_tmux.sh index 95db0c7175cd0..da0213621d3be 100755 --- a/prodtests/full-system-test/start_tmux.sh +++ b/prodtests/full-system-test/start_tmux.sh @@ -16,6 +16,7 @@ export NUMAGPUIDS=1 export EXTINPUT=1 export EPNPIPELINES=1 export SYNCMODE=1 +export SHMTHROW=0 if [ $1 == "dd" ]; then export CMD=datadistribution.sh From 4139fb1a4ecc03f5c20cd620292fc1d0ff47af79 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 15:34:35 +0100 Subject: [PATCH 1522/1751] Distinguish between sync and async processing in the mid reco workfllow in the full system test --- prodtests/full-system-test/dpl-workflow.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index ebf96c88d26e4..97a9f99074d7f 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -35,9 +35,11 @@ if [ $SYNCMODE == 1 ]; then CFG_X="fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500" ITS_CONFIG="--configKeyValues $CFG_X" TPC_CONFIG="GPU_global.synchronousProcessing=1;" + MID_CONFIG="--disable-tracking" else ITS_CONFIG= TPC_CONFIG= + MID_CONFIG= fi TPC_CONFIG2= @@ -87,7 +89,7 @@ o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | \ o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC | \ o2-ft0-entropy-encoder-workflow $ARGS_ALL | \ o2-mid-raw-to-digits-workflow $ARGS_ALL | \ -o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC | \ +o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC $MID_CONFIG | \ o2-mid-entropy-encoder-workflow $ARGS_ALL | \ o2-tof-compressor $ARGS_ALL | \ o2-tof-reco-workflow $ARGS_ALL --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output $DISABLE_MC | \ From 7c39df8170e1572fcc5ca59232cf60db96d16b42 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 15:35:29 +0100 Subject: [PATCH 1523/1751] Remove disabling of monitoring message until O2-1887 is fixed --- prodtests/full_system_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index c4faf0d63dc62..27e3897beeece 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -52,7 +52,7 @@ cd qed taskwrapper qedsim.log o2-sim -j $NJOBS -n$NEventsQED -m PIPE ITS MFT FT0 FV0 -g extgen --configKeyValues '"GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-5;QEDGenParam.yMax=6;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;Diamond.width[2]=6."' cd .. -GLOBALDPLOPT="-b --monitoring-backend no-op://" +GLOBALDPLOPT="-b" # --monitoring-backend no-op:// is currently removed due to https://alice.its.cern.ch/jira/browse/O2-1887 taskwrapper sim.log o2-sim -n $NEvents --skipModules ZDC --configKeyValues "Diamond.width[2]=6." -g pythia8hi -j $NJOBS taskwrapper digi.log o2-sim-digitizer-workflow -n $NEvents --simPrefixQED qed/o2sim --qed-x-section-ratio 3735 ${NOMCLABELS} --firstOrbit 0 --firstBC 0 --skipDet TRD --tpc-lanes $((NJOBS < 36 ? NJOBS : 36)) --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} taskwrapper digiTRD.log o2-sim-digitizer-workflow -n $NEvents --simPrefixQED qed/o2sim --qed-x-section-ratio 3735 ${NOMCLABELS} --firstOrbit 0 --firstBC 0 --onlyDet TRD --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} --incontext collisioncontext.root --configKeyValues "TRDSimParams.digithreads=${NJOBS}" From 5f57c48a342463f840b855ae14822d759b56e39a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 15:36:07 +0100 Subject: [PATCH 1524/1751] Add EEMCAL and PHOS to the full system test --- prodtests/full-system-test/dpl-workflow.sh | 6 +++++- prodtests/full_system_test.sh | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 97a9f99074d7f..f324ac4662f51 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -26,7 +26,7 @@ else fi if [ $CREATECTFDICT == 1 ]; then - CMD_DICT="o2-ctf-writer-workflow $ARGS_ALL --output-type dict --save-dict-after 1 --onlyDet ITS,MFT,TPC,TOF,FT0,MID" + CMD_DICT="o2-ctf-writer-workflow $ARGS_ALL --output-type dict --save-dict-after 1 --onlyDet ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS" else CMD_DICT=cat fi @@ -91,6 +91,10 @@ o2-ft0-entropy-encoder-workflow $ARGS_ALL | \ o2-mid-raw-to-digits-workflow $ARGS_ALL | \ o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC $MID_CONFIG | \ o2-mid-entropy-encoder-workflow $ARGS_ALL | \ +o2-phos-reco-workflow $ARGS_ALL --input-type raw --output-type cells | \ +o2-phos-entropy-encoder-workflow $ARGS_ALL |\ +o2-emcal-reco-workflow $ARGS_ALL --input-type raw --output-type cells | \ +o2-emcal-entropy-encoder-workflow $ARGS_ALL |\ o2-tof-compressor $ARGS_ALL | \ o2-tof-reco-workflow $ARGS_ALL --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output $DISABLE_MC | \ o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input | \ diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 27e3897beeece..e6e1feb3feaa7 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -63,6 +63,8 @@ taskwrapper ft0raw.log o2-ft0-digi2raw --file-per-link --configKeyValues '"HBFUt taskwrapper tpcraw.log o2-tpc-digits-to-rawzs --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -i tpcdigits.root -o raw/TPC taskwrapper tofraw.log o2-tof-reco-workflow ${GLOBALDPLOPT} --tof-raw-file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' --output-type raw --tof-raw-outdir raw/TOF taskwrapper midraw.log o2-mid-digits-to-raw-workflow ${GLOBALDPLOPT} --mid-raw-outdir raw/MID --mid-raw-perlink --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' +taskwrapper emcraw.log o2-emcal-rawcreator --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/EMC +taskwrapper phsraw.log o2-phos-digi2raw --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/PHS cat raw/*/*.cfg > rawAll.cfg # We run the workflow in both CPU-only and With-GPU mode @@ -102,7 +104,7 @@ for STAGE in "NOGPU" "WITHGPU"; do walltime=`grep "#walltime" ${logfile}_time | awk '//{print $2}'` echo "walltime_${STAGE},${TAG} value=${walltime}" >> ${METRICFILE} - # memory + # memory maxmem=`awk '/PROCESS MAX MEM/{print $5}' ${logfile}` # in MB avgmem=`awk '/PROCESS AVG MEM/{print $5}' ${logfile}` # in MB echo "maxmem_${STAGE},${TAG} value=${maxmem}" >> ${METRICFILE} From a1d6062f8482d95f7bc9d5c0ae1ddcfb9daa30ff Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 15:49:08 +0100 Subject: [PATCH 1525/1751] Don't fail when running the first stage multiple times due to ctf_dictionary already present --- prodtests/full_system_test.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index e6e1feb3feaa7..ad82c4c5a6737 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -7,7 +7,7 @@ # # Note that this might require a production server to run. # -# This script needs some binary objects (for the moment): +# This script can use additional binary objects which can be optionally provided: # - matbud.root + ITSdictionary.bin # # authors: D. Rohr / S. Wenzel @@ -83,6 +83,7 @@ for STAGE in "NOGPU" "WITHGPU"; do export GPUTYPE=CPU export SYNCMODE=0 export HOSTMEMSIZE=$TPCTRACKERSCRATCHMEMORY + rm -f ctf_dictionary.root fi export SHMSIZE export NTIMEFRAMES From b109c1c51bb7e617675c78086f5971403d7b56c5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 15:57:51 +0100 Subject: [PATCH 1526/1751] Reduce default memory sizes and disable GPU test by default --- prodtests/full_system_test.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index ad82c4c5a6737..e66cac139101c 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -24,8 +24,9 @@ NEventsQED=${NEventsQED:-1000} #35000 for full TF NCPUS=$(getNumberOfPhysicalCPUCores) echo "Found ${NCPUS} physical CPU cores" NJOBS=${NJOBS:-"${NCPUS}"} -SHMSIZE=128000000000 # 128000000000 # Size of shared memory for messages -TPCTRACKERSCRATCHMEMORY=22000000000 +SHMSIZE=${SHMSIZE:-8000000000} # Size of shared memory for messages (use 128 GB for 550 event full TF) +TPCTRACKERSCRATCHMEMORY=${SHMSIZE:-4000000000} # Size of memory allocated by TPC tracker. (Use 24 GB for 550 event full TF) +ENABLE_GPU_TEST=${ENABLE_GPU_TEST:-0} # Run the full system test also on the GPU NTIMEFRAMES=${NTIMEFRAMES:-1} # Number of time frames to process TFDELAY=100 # Delay in seconds between publishing time frames NOMCLABELS="--disable-mc" @@ -68,7 +69,11 @@ taskwrapper phsraw.log o2-phos-digi2raw --file-for link --configKeyValues '"HBF cat raw/*/*.cfg > rawAll.cfg # We run the workflow in both CPU-only and With-GPU mode -for STAGE in "NOGPU" "WITHGPU"; do +STAGES="NOGPU" +if [ $ENABLE_GPU_TEST != "0" ]; then + STAGES+=" WITHGPU" +fi +for STAGE in $STAGES; do ARGS_ALL="--session default" DICTCREATION="" From 8c168fe019078c2f2c3d4153b388c127b96624ad Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Thu, 3 Dec 2020 12:43:02 -0300 Subject: [PATCH 1527/1751] Centrality work towards vertex-Z profiles for CCDB (#4983) --- Analysis/Tasks/multiplicityQa.cxx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Analysis/Tasks/multiplicityQa.cxx b/Analysis/Tasks/multiplicityQa.cxx index e1e031f0e3b2c..eb1c3847dd85a 100644 --- a/Analysis/Tasks/multiplicityQa.cxx +++ b/Analysis/Tasks/multiplicityQa.cxx @@ -7,6 +7,15 @@ // 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. +// +// This code calculates output histograms for centrality calibration +// as well as vertex-Z dependencies of raw variables (either for calibration +// of vtx-Z dependencies or for the calibration of those). +// +// This task is not strictly necessary in a typical analysis workflow, +// except for centrality calibration! The necessary task is the multiplicity +// tables. + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -25,6 +34,12 @@ struct MultiplicityQaTask { OutputObj<TH1F> hMultZNC{TH1F("hMultZNC", "", 600, 0., 240000.)}; OutputObj<TH2F> hMultV0MvsT0M{TH2F("hMultV0MvsT0M", ";V0M;T0M", 200, 0., 50000., 200, 0., 200000.)}; + //For vertex-Z corrections + OutputObj<TProfile> hVtxProfV0M{TProfile("hVtxProfV0M", "", 600, 0., 240000.)}; + OutputObj<TProfile> hVtxProfT0M{TProfile("hVtxProfT0M", "", 10000, 0., 200000.)}; + OutputObj<TProfile> hVtxProfZNA{TProfile("hVtxProfZNA", "", 600, 0., 240000.)}; + OutputObj<TProfile> hVtxProfZNC{TProfile("hVtxProfZNC", "", 600, 0., 240000.)}; + OutputObj<TProfile> hMultNtrackletsVsV0M{TProfile("hMultNtrackletsVsV0M", "", 50000, 0., 50000.)}; Configurable<bool> isMC{"isMC", 0, "0 - data, 1 - MC"}; @@ -56,6 +71,12 @@ struct MultiplicityQaTask { hMultZNC->Fill(col.multZNC()); hMultV0MvsT0M->Fill(col.multV0M(), col.multT0M()); hMultNtrackletsVsV0M->Fill(col.multV0M(), col.multTracklets()); + + //Vertex-Z dependencies + hVtxProfV0M->Fill(col.posZ(), col.multV0M()); + hVtxProfT0M->Fill(col.posZ(), col.multT0M()); + hVtxProfZNA->Fill(col.posZ(), col.multZNA()); + hVtxProfZNC->Fill(col.posZ(), col.multZNC()); } }; From c2e665dd173d5cbe55c00dcfe11c095f1f0159b0 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 3 Dec 2020 16:17:23 +0100 Subject: [PATCH 1528/1751] Update cpulimit.c systcl header is deprecated on linux. Protect include since it's used on APPLE. --- Utilities/Tools/cpulimit/cpulimit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Utilities/Tools/cpulimit/cpulimit.c b/Utilities/Tools/cpulimit/cpulimit.c index 42d7ca2807384..15bf42f6f061b 100644 --- a/Utilities/Tools/cpulimit/cpulimit.c +++ b/Utilities/Tools/cpulimit/cpulimit.c @@ -38,7 +38,9 @@ #include <string.h> #include <sys/stat.h> #include <sys/time.h> +#if defined(__APPLE__) #include <sys/sysctl.h> +#endif #include <sys/resource.h> #include <sys/types.h> #include <sys/wait.h> From 6e54e786bce2516be3269e8c8582fb6b487c3900 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 19:55:31 +0100 Subject: [PATCH 1529/1751] Completely remove the MID reco for synchronous processing --- prodtests/full-system-test/dpl-workflow.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index f324ac4662f51..c2319e857dd59 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -35,11 +35,11 @@ if [ $SYNCMODE == 1 ]; then CFG_X="fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500" ITS_CONFIG="--configKeyValues $CFG_X" TPC_CONFIG="GPU_global.synchronousProcessing=1;" - MID_CONFIG="--disable-tracking" + CMD_MID="cat" else ITS_CONFIG= TPC_CONFIG= - MID_CONFIG= + CMD_MID="o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC" fi TPC_CONFIG2= @@ -89,7 +89,7 @@ o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | \ o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC | \ o2-ft0-entropy-encoder-workflow $ARGS_ALL | \ o2-mid-raw-to-digits-workflow $ARGS_ALL | \ -o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC $MID_CONFIG | \ +$CMD_MID | \ o2-mid-entropy-encoder-workflow $ARGS_ALL | \ o2-phos-reco-workflow $ARGS_ALL --input-type raw --output-type cells | \ o2-phos-entropy-encoder-workflow $ARGS_ALL |\ From 55a67d2c3447563e2091ebf3de424499a69d563a Mon Sep 17 00:00:00 2001 From: matthias-kleiner <48915672+matthias-kleiner@users.noreply.github.com> Date: Thu, 3 Dec 2020 21:18:11 +0100 Subject: [PATCH 1530/1751] Adding classes to calculate the space charge distortions and corrections (#4618) * Adding classes to calculate the space charge distortions and corrections The distortions and corrections can be calculated by using the potential from a 3D histogram or an analytical formula as an input. These classes are much faster and consistent than the old methods located in GPU/TPCSpaceChargeBase. The old folder (GPU/TPCSpaceChargeBase) where all the previous classes were stored are deleted and all other classes and macros which used the old spacecharge classes are modified to be able to use the new spacecharge classes. * moved CGAL includes to base class * moved global objects in NearestNeighbour src file to own class * adding more grid sizes for calculation of distortions/corrections * fixed createResidualDistortionObject.C macro for new space charge classes and moved to space charge folder * clang format * changed macro calculateDistortionsCorrections.C to compile only * fixed z coordinate in distortElectron * removed CGAL package and replaced nearest neighbour searching by approximation of nearest neighbour --- Detectors/TPC/CMakeLists.txt | 1 + Detectors/TPC/reconstruction/CMakeLists.txt | 2 +- .../macro/createTPCSpaceChargeCorrection.C | 174 +- Detectors/TPC/simulation/CMakeLists.txt | 13 +- .../include/TPCSimulation/Digitizer.h | 22 +- .../include/TPCSimulation/SpaceCharge.h | 244 - .../macro/createResidualDistortionObject.C | 251 - Detectors/TPC/simulation/src/Digitizer.cxx | 21 +- Detectors/TPC/simulation/src/SpaceCharge.cxx | 653 -- .../TPC/simulation/src/TPCSimulationLinkDef.h | 2 - Detectors/TPC/spacecharge/CMakeLists.txt | 50 + .../include/TPCSpaceCharge/DataContainer3D.h | 204 + .../include/TPCSpaceCharge/PoissonSolver.h | 488 ++ .../TPCSpaceCharge/PoissonSolverHelpers.h | 88 + .../include/TPCSpaceCharge/RegularGrid3D.h | 245 + .../include/TPCSpaceCharge/SpaceCharge.h | 901 +++ .../TPCSpaceCharge/SpaceChargeHelpers.h | 269 + .../include/TPCSpaceCharge/TriCubic.h | 1592 +++++ .../include/TPCSpaceCharge/Vector.h | 173 + .../include/TPCSpaceCharge/Vector3D.h | 109 + .../macro/calculateDistortionsCorrections.C | 365 ++ .../macro/createResidualDistortionObject.C | 215 + .../TPC/spacecharge/src/PoissonSolver.cxx | 1497 +++++ Detectors/TPC/spacecharge/src/SpaceCharge.cxx | 1251 ++++ .../spacecharge/src/TPCSpacechargeLinkDef.h | 81 + .../test/testO2TPCPoissonSolver.cxx | 240 + GPU/CMakeLists.txt | 3 - .../macro/generateTPCCorrectionNTuple.C | 34 +- .../AliTPC3DCylindricalInterpolator.cxx | 533 -- .../AliTPC3DCylindricalInterpolator.h | 80 - ...iTPC3DCylindricalInterpolatorIrregular.cxx | 1514 ----- ...AliTPC3DCylindricalInterpolatorIrregular.h | 151 - .../AliTPCLookUpTable3DInterpolatorD.cxx | 215 - .../AliTPCLookUpTable3DInterpolatorD.h | 87 - ...TPCLookUpTable3DInterpolatorIrregularD.cxx | 188 - ...liTPCLookUpTable3DInterpolatorIrregularD.h | 102 - .../AliTPCPoissonSolver.cxx | 3031 ---------- GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.h | 219 - .../AliTPCSpaceCharge3DCalc.cxx | 5315 ----------------- .../AliTPCSpaceCharge3DCalc.h | 454 -- GPU/TPCSpaceChargeBase/CMakeLists.txt | 78 - .../TPCSpaceChargeBaseLinkDef.h | 29 - .../ctest/testTPCSpaceChargeBase.cxx | 26 - .../src/TPCDigitizerSpec.cxx | 27 +- 44 files changed, 7889 insertions(+), 13348 deletions(-) delete mode 100644 Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h delete mode 100644 Detectors/TPC/simulation/macro/createResidualDistortionObject.C delete mode 100644 Detectors/TPC/simulation/src/SpaceCharge.cxx create mode 100644 Detectors/TPC/spacecharge/CMakeLists.txt create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/DataContainer3D.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolver.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolverHelpers.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/RegularGrid3D.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceCharge.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceChargeHelpers.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/TriCubic.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector.h create mode 100644 Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector3D.h create mode 100644 Detectors/TPC/spacecharge/macro/calculateDistortionsCorrections.C create mode 100644 Detectors/TPC/spacecharge/macro/createResidualDistortionObject.C create mode 100644 Detectors/TPC/spacecharge/src/PoissonSolver.cxx create mode 100644 Detectors/TPC/spacecharge/src/SpaceCharge.cxx create mode 100644 Detectors/TPC/spacecharge/src/TPCSpacechargeLinkDef.h create mode 100644 Detectors/TPC/spacecharge/test/testO2TPCPoissonSolver.cxx delete mode 100644 GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.cxx delete mode 100644 GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.h delete mode 100644 GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.cxx delete mode 100644 GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.h delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.cxx delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.h delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.cxx delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.h delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.cxx delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.h delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.cxx delete mode 100644 GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.h delete mode 100644 GPU/TPCSpaceChargeBase/CMakeLists.txt delete mode 100644 GPU/TPCSpaceChargeBase/TPCSpaceChargeBaseLinkDef.h delete mode 100644 GPU/TPCSpaceChargeBase/ctest/testTPCSpaceChargeBase.cxx diff --git a/Detectors/TPC/CMakeLists.txt b/Detectors/TPC/CMakeLists.txt index ccc16941d64b3..a07460ecae1c0 100644 --- a/Detectors/TPC/CMakeLists.txt +++ b/Detectors/TPC/CMakeLists.txt @@ -15,3 +15,4 @@ add_subdirectory(simulation) add_subdirectory(monitor) add_subdirectory(workflow) add_subdirectory(qc) +add_subdirectory(spacecharge) diff --git a/Detectors/TPC/reconstruction/CMakeLists.txt b/Detectors/TPC/reconstruction/CMakeLists.txt index e7456f146032a..c97696459ce53 100644 --- a/Detectors/TPC/reconstruction/CMakeLists.txt +++ b/Detectors/TPC/reconstruction/CMakeLists.txt @@ -123,7 +123,7 @@ o2_add_test_root_macro(macro/createTPCSpaceChargeCorrection.C PUBLIC_LINK_LIBRARIES O2::TPCReconstruction O2::CommonConstants O2::CommonUtils - O2::TPCSpaceChargeBase + O2::TPCSpaceCharge LABELS tpc) o2_add_test_root_macro(macro/findKrBoxCluster.C diff --git a/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C b/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C index 7c0c46d1e2a65..afd75f772ab10 100644 --- a/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C +++ b/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C @@ -18,7 +18,7 @@ /eos/user/e/ehellbar/SpaceCharge/data/RUN3/InputSCDensityHistograms Run macro: - root -l -b -q $O2_SRC/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C+\(180,65,65,\"InputSCDensityHistograms_8000events.root\",\"inputSCDensity3D_8000_0\",\"tpctransformSCcorrection.root\"\) + root -l -b -q $O2_SRC/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C+\(\"InputSCDensityHistograms_8000events.root\",\"inputSCDensity3D_8000_0\",\"tpctransformSCcorrection.root\"\) Test macro compilation: .L $O2_SRC/Detectors/TPC/reconstruction/macro/createTPCSpaceChargeCorrection.C+ @@ -31,9 +31,8 @@ #include "TFile.h" #include "TH3.h" #include "TLatex.h" -#include "TMatrixD.h" -#include "AliTPCSpaceCharge3DCalc.h" +#include "TPCSpaceCharge/SpaceCharge.h" #include "CommonConstants/MathConstants.h" #include "CommonUtils/TreeStreamRedirector.h" @@ -43,39 +42,36 @@ using namespace o2; using namespace tpc; using namespace gpu; -std::unique_ptr<AliTPCSpaceCharge3DCalc> spaceCharge = nullptr; +/// \param nPhi number of phi bins of original correction lookup table +/// \param nR number of r bins of original correction lookup table, has to be 2^n + 1 +/// \param nZ number of z bins of original correction lookup table, has to be 2^n + 1 +const int nPhi = 180; +const int nR = 129; +const int nZ = 129; +using SC = o2::tpc::SpaceCharge<double, nZ, nR, nPhi>; +std::unique_ptr<SC> spaceCharge; void getSpaceChargeCorrection(const int roc, const double XYZ[3], double dXdYdZ[3]); -void initSpaceCharge(const int nPhi, const int nR, const int nZ, const int interpolationOrder, - const char* histoFileName, const char* histoName); +void initSpaceCharge(const char* histoFileName, const char* histoName); void DumpFlatObjectToFile(const TPCFastTransform* obj, const char* file); std::unique_ptr<TPCFastTransform> ReadFlatObjectFromFile(const char* file); -void debugInterpolation(utils::TreeStreamRedirector& pcstream, - const o2::gpu::TPCFastTransformGeo& geo, - TPCFastTransform* fastTransform); -void debugGridpoints(utils::TreeStreamRedirector& pcstream, - const o2::gpu::TPCFastTransformGeo& geo, - TPCFastTransform* fastTransform); +void debugInterpolation(utils::TreeStreamRedirector& pcstream, const o2::gpu::TPCFastTransformGeo& geo, TPCFastTransform* fastTransform); +void debugGridpoints(utils::TreeStreamRedirector& pcstream, const o2::gpu::TPCFastTransformGeo& geo, TPCFastTransform* fastTransform); -/// Creates TPCFastTransform object for TPC space-charge correction, stores it in a file and provides a deub tree if requested -/// \param nPhi number of phi bins of original correction lookup table -/// \param nR number of r bins of original correction lookup table, has to be 2^n + 1 -/// \param nZ number of z bins of original correction lookup table, has to be 2^n + 1 +/// Creates TPCFastTransform object for TPC space-charge correction, stores it in a file and provides a debug tree if requested /// \param histoFileName path and name to the root file containing input space-charge density histograms /// \param histoName name of the input space-charge density histogram /// \param outputFileName name of the output file to store the TPCFastTransform object in /// \param debug create debug tree comparing original corrections and spline interpolations from TPCFastTransform (1 = on the spline interpolation grid, 2 = on the original lookup table grid) void createTPCSpaceChargeCorrection( - const int nPhi = 180, const int nR = 65, const int nZ = 65, const char* histoFileName = "InputSCDensityHistograms_10000events.root", const char* histoName = "inputSCDensity3D_10000_avg", const char* outputFileName = "tpctransform.root", const int debug = 0) { - const int interpolationOrder = 2.; - initSpaceCharge(nPhi, nR, nZ, interpolationOrder, histoFileName, histoName); + initSpaceCharge(histoFileName, histoName); TPCFastTransformHelperO2::instance()->setSpaceChargeCorrection(getSpaceChargeCorrection); std::unique_ptr<TPCFastTransform> fastTransform(TPCFastTransformHelperO2::instance()->create(0)); @@ -84,7 +80,7 @@ void createTPCSpaceChargeCorrection( if (debug > 0) { const o2::gpu::TPCFastTransformGeo& geo = fastTransform->getGeometry(); - utils::TreeStreamRedirector pcstream(TString::Format("fastTransformUnitTest_debug%d_gridsize%d-%d-%d_order%d.root", debug, nPhi, nR, nZ, interpolationOrder).Data(), "recreate"); + utils::TreeStreamRedirector pcstream(TString::Format("fastTransformUnitTest_debug%d_gridsize%d-%d-%d.root", debug, nPhi, nR, nZ).Data(), "recreate"); switch (debug) { case 1: debugInterpolation(pcstream, geo, fastTransform.get()); @@ -100,54 +96,35 @@ void createTPCSpaceChargeCorrection( } /// Initialize calculation of original correction lookup tables -/// \param nPhi number of phi bins of original correction lookup table -/// \param nR number of r bins of original correction lookup table, has to be 2^n + 1 -/// \param nZ number of z bins of original correction lookup table, has to be 2^n + 1 -/// \param interpolationOrder interpolation method to use for original correction lookup tables (1 = linear interpolation, 2 = polynomial interpolation of 2nd order, >2 = cubic spline interpolation of higher orders) /// \param histoFileName path and name to the root file containing input space-charge density histograms /// \param histoName name of the input space-charge density histogram -void initSpaceCharge(const int nPhi, const int nR, const int nZ, const int interpolationOrder, - const char* histoFileName, const char* histoName) +void initSpaceCharge(const char* histoFileName, const char* histoName) { // get histogram with space-charge density std::unique_ptr<TFile> histoFile = std::unique_ptr<TFile>(TFile::Open(histoFileName)); std::unique_ptr<TH3> scHisto = std::unique_ptr<TH3>((TH3*)histoFile->Get(histoName)); // initialize space-charge object - spaceCharge = std::make_unique<AliTPCSpaceCharge3DCalc>(nR, nZ, nPhi, interpolationOrder, 3, 0); + spaceCharge = std::make_unique<SC>(); // input charge - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixChargeA = std::make_unique<std::unique_ptr<TMatrixD>[]>(nPhi); - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixChargeC = std::make_unique<std::unique_ptr<TMatrixD>[]>(nPhi); - for (int iphi = 0; iphi < nPhi; ++iphi) { - mMatrixChargeA[iphi] = std::make_unique<TMatrixD>(nR, nZ); - mMatrixChargeC[iphi] = std::make_unique<TMatrixD>(nR, nZ); - } - spaceCharge->GetChargeDensity((TMatrixD**)mMatrixChargeA.get(), (TMatrixD**)mMatrixChargeC.get(), (TH3*)scHisto.get(), nR, nZ, nPhi); - spaceCharge->SetInputSpaceChargeA((TMatrixD**)mMatrixChargeA.get()); - spaceCharge->SetInputSpaceChargeC((TMatrixD**)mMatrixChargeC.get()); + spaceCharge->fillChargeDensityFromHisto(*scHisto.get()); // further parameters - spaceCharge->SetOmegaTauT1T2(0.32, 1.f, 1.f); - spaceCharge->SetCorrectionType(0); // 0: use regular spaced LUTs, 1: use irregular LUTs (not recommended at the time as it is slower and results have to be verified) - spaceCharge->SetIntegrationStrategy(0); // 0: use default integration along drift lines, 1: use fast integration (not recommended at the time as results have to be verified) + spaceCharge->setOmegaTauT1T2(0.32, 1.f, 1.f); - // calculate LUTs - spaceCharge->ForceInitSpaceCharge3DPoissonIntegralDz(nR, nZ, nPhi, 300, 1e-8); + // start calculation of lookup tables (takes some time) + spaceCharge->calculateDistortionsCorrections(Side::A); + spaceCharge->calculateDistortionsCorrections(Side::C); } /// Function to get corrections from original lookup tables -/// \param roc readout chamber index (0 - 71) /// \param XYZ array with x, y and z position /// \param dXdYdZ array with correction dx, dy and dz void getSpaceChargeCorrection(const int roc, const double XYZ[3], double dXdYdZ[3]) { - const float xyzf[3] = {static_cast<float>(XYZ[0]), static_cast<float>(XYZ[1]), static_cast<float>(XYZ[2])}; - float dxdydzf[3] = {0.f, 0.f, 0.f}; - spaceCharge->GetCorrection(xyzf, roc, dxdydzf); - dXdYdZ[0] = static_cast<double>(dxdydzf[0]); - dXdYdZ[1] = static_cast<double>(dxdydzf[1]); - dXdYdZ[2] = static_cast<double>(dxdydzf[2]); + Side side = roc < 18 ? Side::A : Side::C; + spaceCharge->getCorrections(XYZ[0], XYZ[1], XYZ[2], side, dXdYdZ[0], dXdYdZ[1], dXdYdZ[2]); } /// Save TPCFastTransform to a file @@ -203,15 +180,12 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, for (int slice = 0; slice < geo.getNumberOfSlices(); slice += 1) { // for (int slice = 21; slice < 22; slice += 1) { std::cout << "debug slice " << slice << " ... " << std::endl; - const o2::gpu::TPCFastTransformGeo::SliceInfo& sliceInfo = geo.getSliceInfo(slice); for (int row = 0; row < geo.getNumberOfRows(); row++) { - int nPads = geo.getRowInfo(row).maxPad + 1; for (int pad = 0; pad < nPads; pad++) { - for (float time = 0; time < 500; time += 10) { // non-corrected point @@ -232,35 +206,32 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, // the original correction double gxyz[3] = {gx, gy, gz}; double gdC[3] = {0, 0, 0}; - getSpaceChargeCorrection(slice, gxyz, gdC); + Side side = slice < geo.getNumberOfSlicesA() ? Side::A : Side::C; + spaceCharge->getCorrections(gxyz[0], gxyz[1], gxyz[2], side, gdC[0], gdC[1], gdC[2]); float ldxC, ldyC, ldzC; - geo.convGlobalToLocal(slice, gdC[0], gdC[1], gdC[2], ldxC, ldyC, - ldzC); + geo.convGlobalToLocal(slice, gdC[0], gdC[1], gdC[2], ldxC, ldyC, ldzC); - float rC = std::sqrt((gx + gdC[0]) * (gx + gdC[0]) + - (gy + gdC[1]) * (gy + gdC[1])); + float rC = std::sqrt((gx + gdC[0]) * (gx + gdC[0]) + (gy + gdC[1]) * (gy + gdC[1])); // calculate distortion for the xyz0 - float ldD[3] = {0.0, 0.0, 0.0}; - float gdD[3] = {0.0, 0.0, 0.0}; + double ldD[3] = {0.0, 0.0, 0.0}; + double gdD[3] = {0.0, 0.0, 0.0}; float gxyzf[3] = {gx, gy, gz}; - float pointCyl[3] = {r, phi, gz}; + float pointCyl[3] = {gz, r, phi}; double efield[3] = {0.0, 0.0, 0.0}; - double charge = spaceCharge->GetChargeCylAC(pointCyl, slice); - double potential = spaceCharge->GetPotentialCylAC(pointCyl, slice); - spaceCharge->GetElectricFieldCyl(pointCyl, slice, efield); - spaceCharge->GetLocalDistortionCyl(pointCyl, slice, ldD); - spaceCharge->GetDistortion(gxyzf, slice, gdD); + double charge = spaceCharge->getChargeCyl(pointCyl[0], pointCyl[1], pointCyl[2], side); + double potential = spaceCharge->getPotentialCyl(pointCyl[0], pointCyl[1], pointCyl[2], side); + spaceCharge->getElectricFieldsCyl(pointCyl[0], pointCyl[1], pointCyl[2], side, efield[0], efield[1], efield[2]); + spaceCharge->getLocalDistortionsCyl(pointCyl[0], pointCyl[1], pointCyl[2], side, ldD[0], ldD[1], ldD[2]); + spaceCharge->getDistortions(gxyzf[0], gxyzf[1], gxyzf[2], side, gdD[0], gdD[1], gdD[2]); double gD[3] = {gx + gdD[0], gy + gdD[1], gz + gdD[2]}; - float rD = std::sqrt(gD[0] * gD[0] + gD[1] * gD[1]); // correction for the distorted point - double gdDC[3] = {0, 0, 0}; - getSpaceChargeCorrection(slice, gD, gdDC); + spaceCharge->getCorrections(gD[0], gD[1], gD[2], side, gdDC[0], gdDC[1], gdDC[2]); pcstream << "fastTransform" // internal coordinates @@ -313,9 +284,9 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, // << "charge=" << charge << "potential=" << potential - << "Er=" << efield[0] - << "Ephi=" << efield[1] - << "Ez=" << efield[2] + << "Ez=" << efield[0] + << "Er=" << efield[1] + << "Ephi=" << efield[2] << "\n"; } } @@ -327,51 +298,33 @@ void debugInterpolation(utils::TreeStreamRedirector& pcstream, /// \param pcstream output stream /// \param geo TPCFastTransformGeo object /// \param fastTransform TPCFastTransform object -void debugGridpoints(utils::TreeStreamRedirector& pcstream, - const o2::gpu::TPCFastTransformGeo& geo, - TPCFastTransform* fastTransform) +void debugGridpoints(utils::TreeStreamRedirector& pcstream, const o2::gpu::TPCFastTransformGeo& geo, TPCFastTransform* fastTransform) { - int nR = spaceCharge->GetNRRows(); - int nZ = spaceCharge->GetNZColumns(); - int nPhi = spaceCharge->GetNPhiSlices(); - - float deltaR = - (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / - (nR - 1); - float deltaZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZ - 1); - float deltaPhi = o2::constants::math::TwoPI / nPhi; - for (int iside = 0; iside < 2; ++iside) { - + const Side side = iside == 0 ? Side::A : Side::C; for (int iphi = 0; iphi < nPhi; ++iphi) { - float phi = deltaPhi * iphi; - int sector = iside == 0 ? phi / o2::constants::math::TwoPI * 18 - : phi / o2::constants::math::TwoPI * 18 + 18; + float phi = spaceCharge->getPhiVertex(iphi, side); + int sector = iside == 0 ? phi / o2::constants::math::TwoPI * 18 : phi / o2::constants::math::TwoPI * 18 + 18; for (int ir = 0; ir < nR; ++ir) { - float radius = AliTPCPoissonSolver::fgkIFCRadius + deltaR * ir; + float radius = spaceCharge->getRVertex(ir, side); float gx0 = radius * std::cos(phi); float gy0 = radius * std::sin(phi); for (int iz = 0; iz < nZ; ++iz) { - float gz0 = iside == 0 ? deltaZ * iz - : -1 * deltaZ * iz; - + float gz0 = spaceCharge->getZVertex(iz, side); float x0 = 0.f, y0 = 0.f, z0 = 0.f; geo.convGlobalToLocal(sector, gx0, gy0, gz0, x0, y0, z0); if (x0 < geo.getRowInfo(0).x - 0.375) { continue; } - if (x0 >= (geo.getRowInfo(62).x + 0.375) && - x0 < (geo.getRowInfo(63).x - 0.5)) { + if (x0 >= (geo.getRowInfo(62).x + 0.375) && x0 < (geo.getRowInfo(63).x - 0.5)) { continue; } - if (x0 >= (geo.getRowInfo(96).x + 0.5) && - x0 < (geo.getRowInfo(97).x - 0.6)) { + if (x0 >= (geo.getRowInfo(96).x + 0.5) && x0 < (geo.getRowInfo(97).x - 0.6)) { continue; } - if (x0 >= (geo.getRowInfo(126).x + 0.6) && - x0 < (geo.getRowInfo(127).x - 0.75)) { + if (x0 >= (geo.getRowInfo(126).x + 0.6) && x0 < (geo.getRowInfo(127).x - 0.75)) { continue; } if (x0 > (geo.getRowInfo(151).x + 0.75)) { @@ -417,19 +370,18 @@ void debugGridpoints(utils::TreeStreamRedirector& pcstream, double gcorr[3] = {0, 0, 0}; getSpaceChargeCorrection(sector, xyz, gcorr); float lcorr[3]; - geo.convGlobalToLocal(sector, gcorr[0], gcorr[1], gcorr[2], lcorr[0], - lcorr[1], lcorr[2]); + geo.convGlobalToLocal(sector, gcorr[0], gcorr[1], gcorr[2], lcorr[0], lcorr[1], lcorr[2]); float fxyz[3] = {gx0, gy0, gz0}; - float pointCyl[3] = {radius, phi, gz0}; + float pointCyl[3] = {gz0, radius, phi}; double efield[3] = {0.0, 0.0, 0.0}; - float distLocal[3] = {0.0, 0.0, 0.0}; - float dist[3] = {0.0, 0.0, 0.0}; - double charge = spaceCharge->GetChargeCylAC(pointCyl, sector); - double potential = spaceCharge->GetPotentialCylAC(pointCyl, sector); - spaceCharge->GetElectricFieldCyl(pointCyl, sector, efield); - spaceCharge->GetLocalDistortionCyl(pointCyl, sector, distLocal); - spaceCharge->GetDistortion(fxyz, sector, dist); + double distLocal[3] = {0.0, 0.0, 0.0}; + double dist[3] = {0.0, 0.0, 0.0}; + double charge = spaceCharge->getChargeCyl(pointCyl[0], pointCyl[1], pointCyl[2], side); + double potential = spaceCharge->getPotentialCyl(pointCyl[0], pointCyl[1], pointCyl[2], side); + spaceCharge->getElectricFieldsCyl(pointCyl[0], pointCyl[1], pointCyl[2], side, efield[0], efield[1], efield[2]); + spaceCharge->getLocalDistortionsCyl(pointCyl[0], pointCyl[1], pointCyl[2], side, distLocal[0], distLocal[1], distLocal[2]); + spaceCharge->getDistortions(fxyz[0], fxyz[1], fxyz[2], side, dist[0], dist[1], dist[2]); pcstream << "fastTransform" // internal coordinates @@ -472,9 +424,9 @@ void debugGridpoints(utils::TreeStreamRedirector& pcstream, // << "charge=" << charge << "potential=" << potential - << "Er=" << efield[0] - << "Ephi=" << efield[1] - << "Ez=" << efield[2] + << "Ez=" << efield[0] + << "Er=" << efield[1] + << "Ephi=" << efield[2] << "\n"; } } @@ -485,7 +437,7 @@ void debugGridpoints(utils::TreeStreamRedirector& pcstream, /// Make a simple QA plot of the debug stream void makeQAplot() { - TFile f("fastTransformUnitTest_debug1_gridsize180-65-65_order2.root"); + TFile f("fastTransformUnitTest_debug1_gridsize180-129-129.root"); TTree* tree = (TTree*)f.Get("fastTransform"); tree->SetMarkerSize(0.2); tree->SetMarkerStyle(21); diff --git a/Detectors/TPC/simulation/CMakeLists.txt b/Detectors/TPC/simulation/CMakeLists.txt index 1420c3ce08cce..d4d4af7b46702 100644 --- a/Detectors/TPC/simulation/CMakeLists.txt +++ b/Detectors/TPC/simulation/CMakeLists.txt @@ -21,9 +21,8 @@ o2_add_library(TPCSimulation src/PadResponse.cxx src/Point.cxx src/SAMPAProcessing.cxx - src/SpaceCharge.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::SimulationDataFormat - O2::TPCBase O2::TPCSpaceChargeBase + O2::TPCBase O2::TPCSpaceCharge ROOT::Physics) o2_target_root_dictionary(TPCSimulation @@ -38,8 +37,7 @@ o2_target_root_dictionary(TPCSimulation include/TPCSimulation/GEMAmplification.h include/TPCSimulation/PadResponse.h include/TPCSimulation/Point.h - include/TPCSimulation/SAMPAProcessing.h - include/TPCSimulation/SpaceCharge.h) + include/TPCSimulation/SAMPAProcessing.h) o2_add_executable(digits-to-rawzs COMPONENT_NAME tpc @@ -57,13 +55,6 @@ if(BUILD_TESTING) O2::SimulationDataFormat LABELS tpc) - o2_add_test_root_macro(macro/createResidualDistortionObject.C - PUBLIC_LINK_LIBRARIES O2::TPCSpaceChargeBase - O2::CommonUtils - O2::CommonConstants - O2::TPCSimulation - LABELS tpc) - o2_add_test_root_macro(macro/laserTrackGenerator.C PUBLIC_LINK_LIBRARIES FairRoot::Base O2::DataFormatsTPC diff --git a/Detectors/TPC/simulation/include/TPCSimulation/Digitizer.h b/Detectors/TPC/simulation/include/TPCSimulation/Digitizer.h index c0a565857eedd..cb6d74c43555a 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/Digitizer.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/Digitizer.h @@ -18,7 +18,7 @@ #include "TPCSimulation/DigitContainer.h" #include "TPCSimulation/PadResponse.h" #include "TPCSimulation/Point.h" -#include "TPCSimulation/SpaceCharge.h" +#include "TPCSpaceCharge/SpaceCharge.h" #include "TPCBase/Mapper.h" @@ -52,6 +52,8 @@ class DigitContainer; class Digitizer { public: + using SC = SpaceCharge<double, 129, 129, 180>; + /// Default constructor Digitizer() = default; @@ -109,20 +111,24 @@ class Digitizer /// \param nZSlices number of grid points in z, must be (2**N)+1 /// \param nPhiBins number of grid points in phi /// \param nRBins number of grid points in r, must be (2**N)+1 - void setUseSCDistortions(SpaceCharge::SCDistortionType distortionType, const TH3* hisInitialSCDensity, int nRBins, int nPhiBins, int nZSlices); + void setUseSCDistortions(SC::SCDistortionType distortionType, const TH3* hisInitialSCDensity); /// Enable the use of space-charge distortions and provide SpaceCharge object as input /// \param spaceCharge unique pointer to spaceCharge object - void setUseSCDistortions(SpaceCharge* spaceCharge); + void setUseSCDistortions(SC* spaceCharge); + + /// Enable the use of space-charge distortions by providing global distortions and global corrections stored in a ROOT file + /// The storage of the values should be done by the methods provided in the SpaceCharge class + /// \param TFile file containing distortions and corrections + void setUseSCDistortions(TFile& finp); private: - DigitContainer mDigitContainer; ///< Container for the Digits - std::unique_ptr<SpaceCharge> mSpaceCharge; ///< Handler of space-charge distortions - Sector mSector = -1; ///< ID of the currently processed sector - float mEventTime = 0.f; ///< Time of the currently processed event + DigitContainer mDigitContainer; ///< Container for the Digits + std::unique_ptr<SC> mSpaceCharge; ///< Handler of space-charge distortions + Sector mSector = -1; ///< ID of the currently processed sector + float mEventTime = 0.f; ///< Time of the currently processed event // FIXME: whats the reason for hving this static? static bool mIsContinuous; ///< Switch for continuous readout bool mUseSCDistortions = false; ///< Flag to switch on the use of space-charge distortions - ClassDefNV(Digitizer, 1); }; } // namespace tpc diff --git a/Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h b/Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h deleted file mode 100644 index 8b68c733b3766..0000000000000 --- a/Detectors/TPC/simulation/include/TPCSimulation/SpaceCharge.h +++ /dev/null @@ -1,244 +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. - -/// \file SpaceCharge.h -/// \brief Definition of the handler for the ALICE TPC space-charge distortions calculations -/// \author Ernst Hellbär, Goethe-Universität Frankfurt, ernst.hellbar@cern.ch - -/* - * TODO: - * - modifiy TPCSpaceChargeBase classes - * - create light-weight 2D matrix class as matrix containers - * - std::vector<Matrix> instead of TMatrixD** - * - bring to O2 conventions - * - fix constants (more precise values, export into TPCBase/Constants) - * - granularity in r, rphi, z? - * - accumulate and add next slice - * - event based: propagate charge(ievent-1), add charge(ievent) - * - time based: mTime0, mEffectiveTime - * addIons(eventtime, drifttime, r, phi) - * time in us, 50 kHz = <one event / 20 us> - * if (ev.time+dr.time-mTime0 < mLengthTimebin) => add2NextSlice - * if (mLengthTimebin < ev.time+dr.time-mTime0 < mLengthTimebin+100us) add2NextToNextSlice - * - apply updated distortions to ions in NextToNextSlice when space charge is propagated; need to store exact positions (e.g. std::vector<std::vector<float>>)! - * - ion transport along the E field -> Continuity equation - * - Validate results by comparison to single ion transport - * - what about primary ionization? - * - irregular bin sizes in r and rphi - */ - -#ifndef ALICEO2_TPC_SPACECHARGE_H -#define ALICEO2_TPC_SPACECHARGE_H - -#include "AliTPCSpaceCharge3DCalc.h" -#include "DataFormatsTPC/Defs.h" -#include "MathUtils/RandomRing.h" - -class TH3; - -namespace o2 -{ -namespace tpc -{ - -class SpaceCharge -{ - public: - /// Enumerator for setting the space-charge distortion mode - enum class SCDistortionType : int { - SCDistortionsConstant = 0, // space-charge distortions constant over time - SCDistortionsRealistic = 1 // realistic evolution of space-charge distortions over time - }; - - // Constructors - /// Default constructor using a grid size of (129 z bins, 180 phi bins, 129 r bins) - SpaceCharge(); - /// Constructor with grid size specified by user - /// \param nRBins number of grid points in r, must be (2**N)+1 - /// \param nPhiBins number of grid points in phi - /// \param nZSlices number of grid points in z, must be (2**N)+1 - SpaceCharge(int nRBins, int nPhiBins, int nZSlices); - /// Constructor with grid size and interpolation order specified by user - /// \param nRBins number of grid points in r, must be (2**N)+1 - /// \param nPhiBins number of grid points in phi - /// \param nZSlices number of grid points in z, must be (2**N)+1 - /// \param interpolationOrder order used for interpolation of lookup tables - SpaceCharge(int nRBins, int nPhiBins, int nZSlices, int interpolationOrder); - - // Destructor - ~SpaceCharge() = default; - - /// Calculate lookup tables if initial space-charge density is provided - void init(); - - /// Calculate distortion and correction lookup tables using AliTPCSpaceChargeCalc class - /// \return real time for the calculation of the electron lookup tables - float calculateLookupTables(); - /// Update distortion and correction lookup tables by current space-charge density - /// \param eventTime time of current event - /// \return real time for the re-calculation of the electron lookup tables - float updateLookupTables(float eventTime); - - /// Set omega*tau and T1, T2 tensor terms in Langevin-equation solution - /// \param omegaTau omega*tau - /// \param t1 T1 tensor term - /// \param t2 T2 tensor term - void setOmegaTauT1T2(float omegaTau, float t1, float t2); - /// Set an initial space-charge density - /// \param hisSCDensity 3D space-charge density histogram, expected format (phi,r,z) and units C / cm^3 / epsilon0 - void setInitialSpaceChargeDensity(const TH3* hisSCDensity); - /// Add primary ions to space-charge density - /// \param r global radius - /// \param phi global phi position - /// \param z z position - /// \param nIons number of ions - void fillPrimaryIons(double r, double phi, double z, int nIons); - /// Add charge to space-charge density - /// \param r global radius - /// \param phi global phi position - /// \param z z position - /// \param charge charge in C/cm^3/epsilon0 - void fillPrimaryCharge(double r, double phi, double z, float charge); - /// Add ion backflow to space-charge density - /// \param r global radius - /// \param phi global phi position - /// \param side A or C side - /// \param nIons number of ions - void fillIBFIons(double r, double phi, Side side, int nIons); - /// Add ion backflow to space-charge density - /// \param r global radius - /// \param phi global phi position - /// \param side A or C side - /// \param charge charge in C/cm^3/epsilon0 - void fillIBFCharge(double r, double phi, Side side, float charge); - /// Get ion drift vector along electric field - /// \param r global radius - /// \param phi global phi position - /// \param z z position - /// \param dr return drift in radial direction - /// \param drphi return drift in azimuthal (rphi) direction - /// \param dz return drift in z direction - void getIonDrift(Side side, double r, double phi, double z, double& dr, double& drphi, double& dz) const; - /// Propagate space-charge density along electric field by one time slice - void propagateSpaceCharge(); - /// Convert space-charge density to distribution of ions, propagate them along the electric field and convert back to space-charge density - void propagateIons(); - - /// Correct electron position using correction lookup tables - /// \param point 3D coordinates of the electron - void correctElectron(GlobalPosition3D& point); - /// Distort electron position using distortion lookup tables - /// \param point 3D coordinates of the electron - void distortElectron(GlobalPosition3D& point) const; - - /// Interpolate the space-charge density from lookup tables in mLookUpTableCalculator - /// \param point Position at which to calculate the space-charge density - /// \return space-charge density at given point in C/cm^3/epsilon0 - double getChargeDensity(Side side, const GlobalPosition3D& point) const; - /// Get the space-charge density stored in the - /// \param iphi phi bin - /// \param ir r bin - /// \param iz z bin - /// \return space-charge density in given bin in C/cm^3/epsilon0 - float getChargeDensity(Side side, int ir, int iphi, int iz) const; - - /// Set the space-charge distortions model - /// \param distortionType distortion type (constant or realistic) - void setSCDistortionType(SCDistortionType distortionType) { mSCDistortionType = distortionType; } - /// Get the space-charge distortions model - SCDistortionType getSCDistortionType() const { return mSCDistortionType; } - - /// Return the ion drift time for one z bin - double getDriftTimeZSlice() const { return mDriftTimeVoxel; } - double getNPhi() const { return mNPhi; } - double getNR() const { return mNR; } - double getNZ() const { return mNZ; } - double getVoxelSizePhi() const { return mVoxelSizePhi; } - double getVoxelSizeR() const { return mVoxelSizeR; } - double getVoxelSizeZ() const { return mVoxelSizeZ; } - std::vector<double> const& getCoordinatesPhi() const { return mCoordPhi; } - std::vector<double> const& getCoordinatesR() const { return mCoordR; } - std::vector<double> const& getCoordinatesZ() const { return mCoordZ; } - - void setUseIrregularLUTs(int useIrrLUTs); - void setUseFastDistIntegration(int useFastInt); - - void setDistortionLookupTables(TMatrixD** matrixIntDistDrA, TMatrixD** matrixIntDistDrphiA, TMatrixD** matrixIntDistDzA, TMatrixD** matrixIntDistDrC, TMatrixD** matrixIntDistDrphiC, TMatrixD** matrixIntDistDzC); - - private: - /// Allocate memory for data members - void allocateMemory(); - void setVoxelCoordinates(); - - /// Convert amount of ions into charge density C/cm^3/epsilon0 - /// \param nIons number of ions - /// \return space-charge density (C/cm^3/epsilon0) - float ions2Charge(int rBin, int nIons); - - static constexpr float DvDEoverv0 = 0.0025; //!<! v'(E) / v0 = K / (K*E0) for ions, used in dz calculation - static const float sEzField; //!<! nominal drift field - - static constexpr int MaxNZ = 200; //!<! default number of z slices (1 ms slices) - static constexpr int MaxNPhi = 360; //!<! default number of phi bins - static constexpr float DriftLength = 250.; //!<! drift length of the TPC in (cm) - // ion mobility K = 3.0769231 cm^2/(Vs) in Ne-CO2 90-10 published by A. Deisting - // v_drift = K * E = 3.0769231 cm^2/(Vs) * 400 V/cm = 1230.7692 cm/s - // t_drift = 249.7 cm / v_drift = 203 ms - static constexpr float IonDriftTime = 2.02e5; //!<! drift time of ions for one full drift (us) - - const int mInterpolationOrder; ///< order for interpolation of lookup tables: 2==quadratic, >2==cubic spline - - const int mNZ; ///< number of z slices used in lookup tables - const int mNPhi; ///< number of phi bins used in lookup tables - const int mNR; ///< number of r bins used in lookup tables - const double mVoxelSizeZ; ///< length of one z bin (cm) - const double mDriftTimeVoxel; ///< ion drift time for one z slice (us) - const double mVoxelSizePhi; ///< width of one phi bin (radians) - const double mVoxelSizeR; ///< length of one r bin (cm) - - std::vector<double> mCoordZ; ///< vector with coodinates of the z bins - std::vector<double> mCoordPhi; ///< vector with coodinates of the phi bins - std::vector<double> mCoordR; ///< vector with coodinates of the r bins - - bool mUseInitialSCDensity; ///< Flag for the use of an initial space-charge density at the beginning of the simulation - bool mInitLookUpTables; ///< Flag to indicate if lookup tables have been calculated - float mTimeInit; ///< time of last update of lookup tables - SCDistortionType mSCDistortionType; ///< Type of space-charge distortions - - AliTPCSpaceCharge3DCalc mLookUpTableCalculator; ///< object to calculate and store correction and distortion lookup tables - - /// TODO: What are the coordinates of the bins? They are defined in AliTPCSpaceCharge3DCalc::GetChargeDensity and are different from mCoordZ, mCoordPhi, mCoordR used for local ion drift lookup table! Use consistent convention? Lookup table instead of vector? - std::vector<float> mSpaceChargeDensityA; ///< space-charge density on the A side, stored in C/cm^3/epsilon0, z ordering: z=[0,250], [iphi*mNR*mNZ + ir*mNZ + iz] - std::vector<float> mSpaceChargeDensityC; ///< space-charge density on the C side, stored in C/cm^3/epsilon0, z ordering: z=[0,-250], [iphi*mNR*mNZ + ir*mNZ + iz] - - /// Ion drift vectors after time deltaT = mLengthZSlice / v_driftIon - /// nominal E field only in z direction, distortions in r, phi, z due to space charge - /// d = (dr, drphi, mVoxelSizeZ + dz) - /// TODO: Eliminate the need for these matrices as members, they should be owned by AliTPCLookUpTable3DInterpolatorD. AliTPCLookUpTable3DInterpolatorD needs getters for the matrices and the constructor has to be modified. - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixIonDriftZA; //!<! matrix to store ion drift in z direction along E field on A side in cm - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixIonDriftZC; //!<! matrix to store ion drift in z direction along E field on A side in cm - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixIonDriftRPhiA; //!<! matrix to store ion drift in rphi direction along E field on A side in cm - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixIonDriftRPhiC; //!<! matrix to store ion drift in rphi direction along E field on A side in cm - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixIonDriftRA; //!<! matrix to store ion drift in radial direction along E field on A side in cm - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixIonDriftRC; //!<! matrix to store ion drift in radial direction along E field on C side in cm - /// TODO: these lookup tables should be objects? - std::unique_ptr<AliTPCLookUpTable3DInterpolatorD> mLookUpIonDriftA; ///< lookup table for ion drift along E field on A side in cm - std::unique_ptr<AliTPCLookUpTable3DInterpolatorD> mLookUpIonDriftC; ///< lookup table for ion drift along E field on C side in cm - bool mMemoryAllocated; - - math_utils::RandomRing<> mRandomFlat; //!<! Circular random buffer containing flat random values to convert the charge density to a flat ion distribution inside the voxel - - ClassDefNV(SpaceCharge, 1); -}; - -} // namespace tpc -} // namespace o2 - -#endif // ALICEO2_TPC_SPACECHARGE_H diff --git a/Detectors/TPC/simulation/macro/createResidualDistortionObject.C b/Detectors/TPC/simulation/macro/createResidualDistortionObject.C deleted file mode 100644 index 1dcd960a64996..0000000000000 --- a/Detectors/TPC/simulation/macro/createResidualDistortionObject.C +++ /dev/null @@ -1,251 +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. - -/// \file createResidualDistortionObject.C -/// \brief This macro creates a SpaceCharge object with residual distortions from a fluctuating and an average space-charge density histogram and stores it in a file. -/// \author Ernst Hellbär, Goethe-Universität Frankfurt, ernst.hellbar@cern.ch - -#include <cmath> - -#include "TFile.h" -#include "TH3.h" -#include "TMatrixD.h" -#include "TString.h" - -#include "AliTPCSpaceCharge3DCalc.h" -#include "CommonConstants/MathConstants.h" -#include "CommonUtils/TreeStreamRedirector.h" -#include "TPCSimulation/SpaceCharge.h" -#include "MathUtils/Cartesian.h" - -using namespace o2::tpc; - -// function declarations -AliTPCSpaceCharge3DCalc* createSpaceCharge(TH3* hisSCDensity, int bSign, int nR, int nPhi, int nZ); -void fillDistortionLookupMatrices(AliTPCSpaceCharge3DCalc* spaceChargeCalc, AliTPCSpaceCharge3DCalc* spaceChargeCalcAvg, TMatrixD** matrixDistDrA, TMatrixD** matrixDistDrphiA, TMatrixD** matrixDistDzA, TMatrixD** matrixDistDrC, TMatrixD** matrixDistDrphiC, TMatrixD** matrixDistDzC); -void makeDebugTreeResiduals(AliTPCSpaceCharge3DCalc* calcFluc, AliTPCSpaceCharge3DCalc* calcAvg, SpaceCharge* spaceChargeRes); - -/// Create a SpaceCharge object with residual distortions from a fluctuating and an average space-charge density histogram and write it to a file. -/// \param bSign sign of the B-field: -1 = negative, 0 = no B-field, 1 = positive -/// \param nR number of bins in r -/// \param nPhi number of bins in phi -/// \param nZ number of bins in z -/// \param pathToHistoFile path to a file with the fluctuating and average histograms -/// \param histoFlucName name of the fluctuating histogram -/// \param histoAvgName name of the average histogram -void createResidualDistortionObject(int bSign, int nR = 129, int nPhi = 144, int nZ = 129, const char* pathToHistoFile = "InputSCDensityHistograms_8000events.root", const char* histoFlucName = "inputSCDensity3D_8000_0", const char* histoAvgName = "inputSCDensity3D_8000_avg", bool debug = false) -{ - /* - Usage: - root -l -b -q createResidualDistortionObject.C+\(-1,129,144,129,\"InputSCDensityHistograms_8000events.root\",\"inputSCDensity3D_8000_0\",\"inputSCDensity3D_8000_avg\",true\) - */ - TFile* fileHistos = TFile::Open(pathToHistoFile); - auto histoFluc = fileHistos->Get<TH3>(histoFlucName); - auto histoAvg = fileHistos->Get<TH3>(histoAvgName); - - TFile* fileOutput = TFile::Open("ResidualDistortions.root", "recreate"); - - // Calculate fluctuating and average distortion and correction lookup tables - AliTPCSpaceCharge3DCalc* scCalcFluc = createSpaceCharge(histoFluc, bSign, nR, nPhi, nZ); - AliTPCSpaceCharge3DCalc* scCalcAvg = createSpaceCharge(histoAvg, bSign, nR, nPhi, nZ); - - // Create matrices and fill them with residual distortions. Create SpaceCharge object, assign residual distortion matrices to it and store it in the output file. - TMatrixD** matrixResDistDrA = new TMatrixD*[nPhi]; - TMatrixD** matrixResDistDrphiA = new TMatrixD*[nPhi]; - TMatrixD** matrixResDistDzA = new TMatrixD*[nPhi]; - TMatrixD** matrixResDistDrC = new TMatrixD*[nPhi]; - TMatrixD** matrixResDistDrphiC = new TMatrixD*[nPhi]; - TMatrixD** matrixResDistDzC = new TMatrixD*[nPhi]; - for (int iphi = 0; iphi < nPhi; ++iphi) { - matrixResDistDrA[iphi] = new TMatrixD(nR, nZ); - matrixResDistDrphiA[iphi] = new TMatrixD(nR, nZ); - matrixResDistDzA[iphi] = new TMatrixD(nR, nZ); - matrixResDistDrC[iphi] = new TMatrixD(nR, nZ); - matrixResDistDrphiC[iphi] = new TMatrixD(nR, nZ); - matrixResDistDzC[iphi] = new TMatrixD(nR, nZ); - } - fillDistortionLookupMatrices(scCalcFluc, scCalcAvg, matrixResDistDrA, matrixResDistDrphiA, matrixResDistDzA, matrixResDistDrC, matrixResDistDrphiC, matrixResDistDzC); - SpaceCharge spaceChargeRes(nR, nPhi, nZ); - spaceChargeRes.setDistortionLookupTables(matrixResDistDrA, matrixResDistDrphiA, matrixResDistDzA, matrixResDistDrC, matrixResDistDrphiC, matrixResDistDzC); - fileOutput->WriteObject(&spaceChargeRes, "spaceChargeRes"); - - if (debug) { - makeDebugTreeResiduals(scCalcFluc, scCalcAvg, &spaceChargeRes); - } -} - -/// Create AliTPCSpaceCharge3DCalc object from a space-charge density histogram -/// \param hisSCDensity input space-charge density histogram -/// \param bSign sign of the B-field: -1 = negative, 0 = no B-field, 1 = positive -/// \param nR number of bins in r -/// \param nPhi number of bins in phi -/// \param nZ number of bins in z -/// \return pointer to AliTPCSpaceCharge3DCalc object -AliTPCSpaceCharge3DCalc* createSpaceCharge(TH3* hisSCDensity, int bSign, int nR, int nPhi, int nZ) -{ - AliTPCSpaceCharge3DCalc* spaceCharge = new AliTPCSpaceCharge3DCalc(nR, nZ, nPhi, 2, 3, 0); - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixChargeA = std::make_unique<std::unique_ptr<TMatrixD>[]>(nPhi); - std::unique_ptr<std::unique_ptr<TMatrixD>[]> mMatrixChargeC = std::make_unique<std::unique_ptr<TMatrixD>[]>(nPhi); - for (int iphi = 0; iphi < nPhi; ++iphi) { - mMatrixChargeA[iphi] = std::make_unique<TMatrixD>(nR, nZ); - mMatrixChargeC[iphi] = std::make_unique<TMatrixD>(nR, nZ); - } - spaceCharge->GetChargeDensity((TMatrixD**)mMatrixChargeA.get(), (TMatrixD**)mMatrixChargeC.get(), hisSCDensity, nR, nZ, nPhi); - spaceCharge->SetInputSpaceChargeA((TMatrixD**)mMatrixChargeA.get()); - spaceCharge->SetInputSpaceChargeC((TMatrixD**)mMatrixChargeC.get()); - float omegaTau = -0.32 * bSign; - spaceCharge->SetOmegaTauT1T2(omegaTau, 1.f, 1.f); - spaceCharge->SetCorrectionType(0); - spaceCharge->SetIntegrationStrategy(0); - spaceCharge->ForceInitSpaceCharge3DPoissonIntegralDz(nR, nZ, nPhi, 300, 1e-8); - return spaceCharge; -} - -/// Store distortions from spaceChargeCalcFluc in the matrices provided. If providing an object with average space-charge distortions spaceChargeCalcAvg, the residual distortions (dist_fluctuation(xyzTrue) + corr_average(xyzDistorted)) will be stored. -/// \param spaceChargeCalcFluc fluctuating distortions object -/// \param spaceChargeCalcAvg average distortions object -/// \param matrixDistDrA matrix to store radial distortions on the A side -/// \param matrixDistDrphiA matrix to store rphi distortions on the A side -/// \param matrixDistDzA matrix to store z distortions on the A side -/// \param matrixDistDrC matrix to store radial distortions on the C side -/// \param matrixDistDrphiC matrix to store rphi distortions on the C side -/// \param matrixDistDzC matrix to store z distortions on the C side -void fillDistortionLookupMatrices(AliTPCSpaceCharge3DCalc* spaceChargeCalcFluc, AliTPCSpaceCharge3DCalc* spaceChargeCalcAvg, TMatrixD** matrixDistDrA, TMatrixD** matrixDistDrphiA, TMatrixD** matrixDistDzA, TMatrixD** matrixDistDrC, TMatrixD** matrixDistDrphiC, TMatrixD** matrixDistDzC) -{ - const int nR = spaceChargeCalcFluc->GetNRRows(); - const int nPhi = spaceChargeCalcFluc->GetNPhiSlices(); - const int nZ = spaceChargeCalcFluc->GetNZColumns(); - const float mVoxelSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nR - 1); - const float mVoxelSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZ - 1); - const float mVoxelSizePhi = o2::constants::math::TwoPI / nPhi; - - for (int iphi = 0; iphi < nPhi; ++iphi) { - float phi = iphi * mVoxelSizePhi; - - for (int ir = 0; ir < nR; ++ir) { - float r = AliTPCPoissonSolver::fgkIFCRadius + ir * mVoxelSizeR; - - for (int iz = 0; iz < nZ; ++iz) { - float absz = iz * mVoxelSizeZ; - - float xCylA[3] = {r, phi, absz}; - float xCylC[3] = {r, phi, -1 * absz}; - int roc = 0; - float distFlucA[3] = {0.f, 0.f, 0.f}; - float distFlucC[3] = {0.f, 0.f, 0.f}; - - // get fluctuating distortions - spaceChargeCalcFluc->GetDistortionCylAC(xCylA, roc, distFlucA); - spaceChargeCalcFluc->GetDistortionCylAC(xCylC, roc + 18, distFlucC); - float distA[3] = {distFlucA[0], distFlucA[1], distFlucA[2]}; - float distC[3] = {distFlucC[0], distFlucC[1], distFlucC[2]}; - - // get average corrections if provided and add them to the fluctuating distortions - if (spaceChargeCalcAvg) { - float xDistCylA[3] = {xCylA[0] + distFlucA[0], xCylA[1] + distFlucA[1] / xCylA[0], xCylA[2] + distFlucA[2]}; - float xDistCylC[3] = {xCylC[0] + distFlucC[0], xCylC[1] + distFlucC[1] / xCylC[0], xCylC[2] + distFlucC[2]}; - float corrAvgA[3] = {0.f, 0.f, 0.f}; - float corrAvgC[3] = {0.f, 0.f, 0.f}; - spaceChargeCalcAvg->GetCorrectionCylAC(xDistCylA, roc, corrAvgA); - spaceChargeCalcAvg->GetCorrectionCylAC(xDistCylC, roc + 18, corrAvgC); - distA[0] += corrAvgA[0]; - distA[1] += (corrAvgA[1] * xCylA[0] / xDistCylA[0]); - distA[2] += corrAvgA[2]; - distC[0] += corrAvgC[0]; - distC[1] += (corrAvgC[1] * xCylC[0] / xDistCylC[0]); - distC[2] += corrAvgC[2]; - } - - // store (residual) distortions in the matrices - (*matrixDistDrA[iphi])(ir, iz) = distA[0]; - (*matrixDistDrphiA[iphi])(ir, iz) = distA[1]; - (*matrixDistDzA[iphi])(ir, iz) = distA[2]; - (*matrixDistDrC[iphi])(ir, iz) = distC[0]; - (*matrixDistDrphiC[iphi])(ir, iz) = distC[1]; - (*matrixDistDzC[iphi])(ir, iz) = -1 * distC[2]; - } - } - } -} - -/// Calculate and stream residual distortions from spaceChargeRes and from calcFluc and calcAvg for comparison. -/// \param calcFluc AliTPCSpaceCharge3DCalc object with fluctuation distortions -/// \param calcAvg AliTPCSpaceCharge3DCalc object with average distortions -/// \param spaceChargeRes SpaceCharge object with residual distortions -void makeDebugTreeResiduals(AliTPCSpaceCharge3DCalc* calcFluc, AliTPCSpaceCharge3DCalc* calcAvg, SpaceCharge* spaceChargeRes) -{ - const int nR = calcFluc->GetNRRows(); - const int nPhi = calcFluc->GetNPhiSlices(); - const int nZ = calcFluc->GetNZColumns(); - const float mVoxelSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nR - 1); - const float mVoxelSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZ - 1); - const float mVoxelSizePhi = o2::constants::math::TwoPI / nPhi; - - o2::utils::TreeStreamRedirector pcstream("debugResidualDistortions.root", "recreate"); - for (int iside = 0; iside < 2; ++iside) { - int roc = iside == 0 ? 0 : 18; - for (int iphi = 0; iphi < nPhi; ++iphi) { - float phi = iphi * mVoxelSizePhi; - for (int ir = 0; ir < nR; ++ir) { - float r = AliTPCPoissonSolver::fgkIFCRadius + ir * mVoxelSizeR; - float x = r * std::cos(phi); - float y = r * std::sin(phi); - for (int iz = 1; iz < nZ; ++iz) { - float z = iside == 0 ? iz * mVoxelSizeZ : -1 * iz * mVoxelSizeZ; - - GlobalPosition3D posDistRes(x, y, z); - spaceChargeRes->distortElectron(posDistRes); - float xyzDistRes[3] = {posDistRes.x(), posDistRes.y(), posDistRes.z()}; - float distRes[3] = {posDistRes.x() - x, posDistRes.y() - y, posDistRes.z() - z}; - - float xyz[3] = {x, y, z}; - float distFluc[3] = {0.f, 0.f, 0.f}; - calcFluc->GetDistortion(xyz, roc, distFluc); - float xyzDist[3] = {xyz[0] + distFluc[0], xyz[1] + distFluc[1], xyz[2] + distFluc[2]}; - float corrAvg[3] = {0.f, 0.f, 0.f}; - calcAvg->GetCorrection(xyzDist, roc, corrAvg); - float xyzDistResTrue[3] = {xyzDist[0] + corrAvg[0], xyzDist[1] + corrAvg[1], xyzDist[2] + corrAvg[2]}; - float distResTrue[3] = {distFluc[0] + corrAvg[0], distFluc[1] + corrAvg[1], distFluc[2] + corrAvg[2]}; - - pcstream << "debug" - << "iside=" << iside - << "iphi=" << iphi - << "ir=" << ir - << "iz=" << iz - // original position - << "phi=" << phi - << "r=" << r - << "x=" << x - << "y=" << y - << "z=" << z - // position of distorted points - << "xRes=" << xyzDistRes[0] - << "yRes=" << xyzDistRes[1] - << "zRes=" << xyzDistRes[2] - // true position of distorted points - << "xResTrue=" << xyzDistResTrue[0] - << "yResTrue=" << xyzDistResTrue[1] - << "zResTrue=" << xyzDistResTrue[2] - // residual distortions - << "distX=" << distRes[0] - << "distY=" << distRes[1] - << "distZ=" << distRes[2] - // true residual distortions - << "distXTrue=" << distResTrue[0] - << "distYTrue=" << distResTrue[1] - << "distZTrue=" << distResTrue[2] - // - << "\n"; - } - } - } - } - pcstream.Close(); -} \ No newline at end of file diff --git a/Detectors/TPC/simulation/src/Digitizer.cxx b/Detectors/TPC/simulation/src/Digitizer.cxx index 241159f14fe88..c12ecdec9be15 100644 --- a/Detectors/TPC/simulation/src/Digitizer.cxx +++ b/Detectors/TPC/simulation/src/Digitizer.cxx @@ -164,20 +164,33 @@ void Digitizer::flush(std::vector<o2::tpc::Digit>& digits, mDigitContainer.fillOutputContainer(digits, labels, commonModeOutput, mSector, sampaProcessing.getTimeBinFromTime(mEventTime), mIsContinuous, finalFlush); } -void Digitizer::setUseSCDistortions(SpaceCharge::SCDistortionType distortionType, const TH3* hisInitialSCDensity, int nRBins, int nPhiBins, int nZSlices) +void Digitizer::setUseSCDistortions(SC::SCDistortionType distortionType, const TH3* hisInitialSCDensity) { mUseSCDistortions = true; if (!mSpaceCharge) { - mSpaceCharge = std::make_unique<SpaceCharge>(nRBins, nPhiBins, nZSlices); + mSpaceCharge = std::make_unique<SC>(); } mSpaceCharge->setSCDistortionType(distortionType); if (hisInitialSCDensity) { - mSpaceCharge->setInitialSpaceChargeDensity(hisInitialSCDensity); + mSpaceCharge->fillChargeDensityFromHisto(*hisInitialSCDensity); + mSpaceCharge->setUseInitialSCDensity(true); } } -void Digitizer::setUseSCDistortions(SpaceCharge* spaceCharge) +void Digitizer::setUseSCDistortions(SC* spaceCharge) { mUseSCDistortions = true; mSpaceCharge.reset(spaceCharge); } + +void Digitizer::setUseSCDistortions(TFile& finp) +{ + mUseSCDistortions = true; + if (!mSpaceCharge) { + mSpaceCharge = std::make_unique<SC>(); + } + mSpaceCharge->setGlobalDistortionsFromFile(finp, Side::A); + mSpaceCharge->setGlobalDistortionsFromFile(finp, Side::C); + mSpaceCharge->setGlobalCorrectionsFromFile(finp, Side::A); + mSpaceCharge->setGlobalCorrectionsFromFile(finp, Side::C); +} diff --git a/Detectors/TPC/simulation/src/SpaceCharge.cxx b/Detectors/TPC/simulation/src/SpaceCharge.cxx deleted file mode 100644 index 2020d258d2e59..0000000000000 --- a/Detectors/TPC/simulation/src/SpaceCharge.cxx +++ /dev/null @@ -1,653 +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. - -/// \file SpaceCharge.cxx -/// \brief Implementation of the interface for the ALICE TPC space-charge distortions calculations -/// \author Ernst Hellbär, Goethe-Universität Frankfurt, ernst.hellbar@cern.ch - -#include "TGeoGlobalMagField.h" -#include "TH3.h" -#include "TMath.h" -#include "TMatrixD.h" -#include "TStopwatch.h" - -#include "FairLogger.h" - -#include "DataFormatsTPC/Constants.h" -#include "DataFormatsTPC/Defs.h" -#include "Field/MagneticField.h" -#include "MathUtils/Utils.h" -#include "TPCBase/ParameterGas.h" -#include "TPCSimulation/SpaceCharge.h" - -using namespace o2::tpc; -using namespace o2::tpc::constants; -using namespace o2::math_utils; - -const float o2::tpc::SpaceCharge::sEzField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; - -SpaceCharge::SpaceCharge() - : mNZ(MaxNZ), - mNPhi(MaxNPhi), - mNR(MAXGLOBALPADROW), - mVoxelSizeZ(AliTPCPoissonSolver::fgkTPCZ0 / (MaxNZ - 1)), - mDriftTimeVoxel(IonDriftTime / (MaxNZ - 1)), - mVoxelSizePhi(TWOPI / MaxNPhi), - mVoxelSizeR((AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (MAXGLOBALPADROW - 1)), - mCoordZ(MaxNZ), - mCoordPhi(MaxNPhi), - mCoordR(MAXGLOBALPADROW), - mInterpolationOrder(2), - mUseInitialSCDensity(false), - mInitLookUpTables(false), - mMemoryAllocated(false), - mTimeInit(-1), - mSCDistortionType(SpaceCharge::SCDistortionType::SCDistortionsRealistic), - mLookUpTableCalculator(MAXGLOBALPADROW, MaxNZ, MaxNPhi, 2, 3, 0), - mSpaceChargeDensityA(MaxNPhi * MAXGLOBALPADROW * MaxNZ), - mSpaceChargeDensityC(MaxNPhi * MAXGLOBALPADROW * MaxNZ), - mRandomFlat(RandomRing<>::RandomType::Flat) -{ - mLookUpTableCalculator.SetCorrectionType(0); - mLookUpTableCalculator.SetIntegrationStrategy(0); - setVoxelCoordinates(); -} - -SpaceCharge::SpaceCharge(int nRBins, int nPhiBins, int nZSlices) - : mNZ(nZSlices), - mNPhi(nPhiBins), - mNR(nRBins), - mVoxelSizeZ(AliTPCPoissonSolver::fgkTPCZ0 / (nZSlices - 1)), - mDriftTimeVoxel(IonDriftTime / (nZSlices - 1)), - mVoxelSizePhi(TWOPI / nPhiBins), - mVoxelSizeR((AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRBins - 1)), - mCoordZ(nZSlices), - mCoordPhi(nPhiBins), - mCoordR(nRBins), - mInterpolationOrder(2), - mUseInitialSCDensity(false), - mInitLookUpTables(false), - mMemoryAllocated(false), - mTimeInit(-1), - mSCDistortionType(SpaceCharge::SCDistortionType::SCDistortionsRealistic), - mLookUpTableCalculator(nRBins, nZSlices, nPhiBins, 2, 3, 0), - mSpaceChargeDensityA(nPhiBins * nRBins * nZSlices), - mSpaceChargeDensityC(nPhiBins * nRBins * nZSlices), - mRandomFlat(RandomRing<>::RandomType::Flat) -{ - mLookUpTableCalculator.SetCorrectionType(0); - mLookUpTableCalculator.SetIntegrationStrategy(0); - setVoxelCoordinates(); -} - -SpaceCharge::SpaceCharge(int nRBins, int nPhiBins, int nZSlices, int interpolationOrder) - : mNZ(nZSlices), - mNPhi(nPhiBins), - mNR(nRBins), - mVoxelSizeZ(AliTPCPoissonSolver::fgkTPCZ0 / (nZSlices - 1)), - mDriftTimeVoxel(IonDriftTime / (nZSlices - 1)), - mVoxelSizePhi(TWOPI / nPhiBins), - mVoxelSizeR((AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRBins - 1)), - mCoordZ(nZSlices), - mCoordPhi(nPhiBins), - mCoordR(nRBins), - mInterpolationOrder(interpolationOrder), - mUseInitialSCDensity(false), - mInitLookUpTables(false), - mMemoryAllocated(false), - mTimeInit(-1), - mSCDistortionType(SpaceCharge::SCDistortionType::SCDistortionsRealistic), - mLookUpTableCalculator(nRBins, nZSlices, nPhiBins, interpolationOrder, 3, 0), - mSpaceChargeDensityA(nPhiBins * nRBins * nZSlices), - mSpaceChargeDensityC(nPhiBins * nRBins * nZSlices), - mRandomFlat(RandomRing<>::RandomType::Flat) -{ - mLookUpTableCalculator.SetCorrectionType(0); - mLookUpTableCalculator.SetIntegrationStrategy(0); - setVoxelCoordinates(); -} - -void SpaceCharge::setVoxelCoordinates() -{ - for (int iz = 0; iz < mNZ; ++iz) { - mCoordZ[iz] = iz * mVoxelSizeZ; - } - for (int iphi = 0; iphi < mNPhi; ++iphi) { - mCoordPhi[iphi] = iphi * mVoxelSizePhi; - } - for (int ir = 0; ir < mNR; ++ir) { - mCoordR[ir] = AliTPCPoissonSolver::fgkIFCRadius + ir * mVoxelSizeR; - } -} - -void SpaceCharge::allocateMemory() -{ - mMatrixIonDriftZA = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - mMatrixIonDriftRPhiA = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - mMatrixIonDriftRA = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - mMatrixIonDriftZC = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - mMatrixIonDriftRPhiC = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - mMatrixIonDriftRC = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - for (int iphi = 0; iphi < mNPhi; ++iphi) { - mMatrixIonDriftZA[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - mMatrixIonDriftRPhiA[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - mMatrixIonDriftRA[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - mMatrixIonDriftZC[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - mMatrixIonDriftRPhiC[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - mMatrixIonDriftRC[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - } - mLookUpIonDriftA = std::make_unique<AliTPCLookUpTable3DInterpolatorD>(mNR, (TMatrixD**)mMatrixIonDriftRA.get(), mCoordR.data(), mNPhi, (TMatrixD**)mMatrixIonDriftRPhiA.get(), mCoordPhi.data(), mNZ, (TMatrixD**)mMatrixIonDriftZA.get(), mCoordZ.data(), mInterpolationOrder); - mLookUpIonDriftC = std::make_unique<AliTPCLookUpTable3DInterpolatorD>(mNR, (TMatrixD**)mMatrixIonDriftRC.get(), mCoordR.data(), mNPhi, (TMatrixD**)mMatrixIonDriftRPhiC.get(), mCoordPhi.data(), mNZ, (TMatrixD**)mMatrixIonDriftZC.get(), mCoordZ.data(), mInterpolationOrder); - mMemoryAllocated = true; -} - -void SpaceCharge::init() -{ - if (!mInitLookUpTables) { - auto o2field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); - const float bzField = o2field->solenoidField(); // magnetic field in kGauss - /// TODO is there a faster way to get the drift velocity - auto& gasParam = ParameterGas::Instance(); - float vDrift = gasParam.DriftV; // drift velocity in cm/us - /// TODO fix hard coded values (ezField, t1, t2): export to Constants.h or get from somewhere? - const float t1 = 1.; - const float t2 = 1.; - /// TODO use this parameterization or fixed value(s) from Magboltz calculations? - const float omegaTau = -10. * bzField * vDrift / std::abs(sEzField); - setOmegaTauT1T2(omegaTau, t1, t2); - if (mUseInitialSCDensity) { - calculateLookupTables(); - } - } -} - -float SpaceCharge::calculateLookupTables() -{ - // Potential, E field and electron distortion and correction lookup tables - TStopwatch timer; - mLookUpTableCalculator.ForceInitSpaceCharge3DPoissonIntegralDz(mNR, mNZ, mNPhi, 300, 1e-8); - float tRealCalc = static_cast<float>(timer.RealTime()); - - // Lookup tables for local ion drift along E field - if (mSCDistortionType == SCDistortionType::SCDistortionsRealistic) { - if (!mMemoryAllocated) { - allocateMemory(); - } - TMatrixD* matrixDriftZ = nullptr; - TMatrixD* matrixDriftRPhi = nullptr; - TMatrixD* matrixDriftR = nullptr; - for (int iside = 0; iside < 2; ++iside) { - const int sign = 1 - iside * 2; - for (int iphi = 0; iphi < mNPhi; ++iphi) { - const float phi = static_cast<float>(mCoordPhi[iphi]); - if (iside == 0) { - matrixDriftZ = mMatrixIonDriftZA[iphi].get(); - matrixDriftRPhi = mMatrixIonDriftRPhiA[iphi].get(); - matrixDriftR = mMatrixIonDriftRA[iphi].get(); - } else { - matrixDriftZ = mMatrixIonDriftZC[iphi].get(); - matrixDriftRPhi = mMatrixIonDriftRPhiC[iphi].get(); - matrixDriftR = mMatrixIonDriftRC[iphi].get(); - } - int roc = iside == 0 ? o2::math_utils::angle2Sector(phi) : o2::math_utils::angle2Sector(phi) + 18; - for (int ir = 0; ir < mNR; ++ir) { - const float radius = static_cast<float>(mCoordR[ir]); - /// TODO: what is the electric field stored in the LUTs at iz=0 and iz=mNZSlices-1 - for (int iz = 0; iz < mNZ; ++iz) { - const float z = static_cast<float>(mCoordZ[iz]); - float x0[3] = {radius, phi, sign * (z + static_cast<float>(mVoxelSizeZ))}; // iphi, ir, iz+1 - float x1[3] = {radius, phi, sign * z}; // iphi, ir, iz - if (iside == 1) { - x0[2] *= -1; - x1[2] *= -1; - } - double eVector0[3] = {0., 0., 0.}; - double eVector1[3] = {0., 0., 0.}; - mLookUpTableCalculator.GetElectricFieldCyl(x0, roc, eVector0); // returns correct sign for Ez - mLookUpTableCalculator.GetElectricFieldCyl(x1, roc, eVector1); // returns correct sign for Ez - - // drift of ions along E field - (*matrixDriftR)(ir, iz) = -1 * sign * mVoxelSizeZ * 0.5 * (eVector0[0] + eVector1[0]) / (sign * sEzField + eVector0[2]); - (*matrixDriftRPhi)(ir, iz) = -1 * sign * mVoxelSizeZ * 0.5 * (eVector0[1] + eVector1[1]) / (sign * sEzField + eVector0[2]); - (*matrixDriftZ)(ir, iz) = -1 * sign * mVoxelSizeZ + DvDEoverv0 * mVoxelSizeZ * 0.5 * (eVector0[2] + eVector1[2]); - } - } - } - if (iside == 0) { - mLookUpIonDriftA->CopyFromMatricesToInterpolator(); - } else { - mLookUpIonDriftC->CopyFromMatricesToInterpolator(); - } - } - - // TODO: Propagate current SC density along E field by one time bin for next update - // propagateSpaceCharge(); - } - - mInitLookUpTables = true; - return tRealCalc; -} - -float SpaceCharge::updateLookupTables(float eventTime) -{ - // TODO: only update after update time interval - // if (mTimeInit < 0.) { - // mTimeInit = eventTime; // set the time of first initialization - // } - // if (std::abs(eventTime - mTimeInit) < mDriftTimeVoxel) { - // return 0.f; // update only after one time bin has passed - // } - // mTimeInit = eventTime; - - std::unique_ptr<std::unique_ptr<TMatrixD>[]> spaceChargeA = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - std::unique_ptr<std::unique_ptr<TMatrixD>[]> spaceChargeC = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - for (int iphi = 0; iphi < mNPhi; ++iphi) { - spaceChargeA[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - spaceChargeC[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - } - for (int iside = 0; iside < 2; ++iside) { - for (int iphi = 0; iphi < mNPhi; ++iphi) { - TMatrixD& chargeDensity = iside == 0 ? *spaceChargeA[iphi] : *spaceChargeC[iphi]; - for (int ir = 0; ir < mNR; ++ir) { - for (int iz = 0; iz < mNZ; ++iz) { - if (iside == 0) { - chargeDensity(ir, iz) = mSpaceChargeDensityA[iphi * mNR * mNZ + ir * mNZ + iz]; - } else { - chargeDensity(ir, iz) = mSpaceChargeDensityC[iphi * mNR * mNZ + ir * mNZ + iz]; - } - } - } - } - } - mLookUpTableCalculator.SetInputSpaceChargeA((TMatrixD**)spaceChargeA.get()); - mLookUpTableCalculator.SetInputSpaceChargeC((TMatrixD**)spaceChargeC.get()); - float tRealCalc = calculateLookupTables(); - return tRealCalc; -} - -void SpaceCharge::setOmegaTauT1T2(float omegaTau, float t1, float t2) -{ - mLookUpTableCalculator.SetOmegaTauT1T2(omegaTau, t1, t2); -} - -void SpaceCharge::setInitialSpaceChargeDensity(const TH3* hisSCDensity) -{ - std::unique_ptr<std::unique_ptr<TMatrixD>[]> spaceChargeA = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - std::unique_ptr<std::unique_ptr<TMatrixD>[]> spaceChargeC = std::make_unique<std::unique_ptr<TMatrixD>[]>(mNPhi); - for (int iphi = 0; iphi < mNPhi; ++iphi) { - spaceChargeA[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - spaceChargeC[iphi] = std::make_unique<TMatrixD>(mNR, mNZ); - } - mLookUpTableCalculator.GetChargeDensity((TMatrixD**)spaceChargeA.get(), (TMatrixD**)spaceChargeC.get(), hisSCDensity, mNR, mNZ, mNPhi); - for (int iside = 0; iside < 2; ++iside) { - for (int iphi = 0; iphi < mNPhi; ++iphi) { - TMatrixD& chargeDensity = iside == 0 ? *spaceChargeA[iphi] : *spaceChargeC[iphi]; - for (int ir = 0; ir < mNR; ++ir) { - for (int iz = 0; iz < mNZ; ++iz) { - if (iside == 0) { - mSpaceChargeDensityA[iphi * mNR * mNZ + ir * mNZ + iz] = chargeDensity(ir, iz); - } else { - mSpaceChargeDensityC[iphi * mNR * mNZ + ir * mNZ + iz] = chargeDensity(ir, iz); - } - } - } - } - } - mLookUpTableCalculator.SetInputSpaceChargeA((TMatrixD**)spaceChargeA.get()); - mLookUpTableCalculator.SetInputSpaceChargeC((TMatrixD**)spaceChargeC.get()); - mUseInitialSCDensity = true; -} - -void SpaceCharge::fillPrimaryIons(double r, double phi, double z, int nIons) -{ - Side side = z > 0 ? Side::A : Side::C; - double dr = 0.; - double drphi = 0.; - double dz = 0.; - getIonDrift(side, r, phi, z, dr, drphi, dz); - double rdist = r + dr; - double phidist = phi + drphi / r; - double zdist = z + dz; - const int zBin = TMath::BinarySearch(mNZ, mCoordZ.data(), std::abs(zdist)); - const int phiBin = TMath::BinarySearch(mNPhi, mCoordPhi.data(), phidist); - const int rBin = TMath::BinarySearch(mNR, mCoordR.data(), rdist); - /// TODO: protection against ions ending up outside the volume - if (z > 0 && zdist > 0) { - mSpaceChargeDensityA[phiBin * mNR * mNZ + rBin * mNZ + zBin] += ions2Charge(rBin, nIons); - } else if (z < 0 && zdist < 0) { - mSpaceChargeDensityC[phiBin * mNR * mNZ + rBin * mNZ + zBin] += ions2Charge(rBin, nIons); - } -} - -void SpaceCharge::fillPrimaryCharge(double r, double phi, double z, float charge) -{ - Side side = z > 0 ? Side::A : Side::C; - double dr = 0.; - double drphi = 0.; - double dz = 0.; - getIonDrift(side, r, phi, z, dr, drphi, dz); - double rdist = r + dr; - double phidist = phi + drphi / r; - double zdist = z + dz; - const int zBin = TMath::BinarySearch(mNZ, mCoordZ.data(), std::abs(zdist)); - const int phiBin = TMath::BinarySearch(mNPhi, mCoordPhi.data(), phidist); - const int rBin = TMath::BinarySearch(mNR, mCoordR.data(), rdist); - /// TODO: protection against ions ending up outside the volume - if (z > 0 && zdist > 0) { - mSpaceChargeDensityA[phiBin * mNR * mNZ + rBin * mNZ + zBin] += charge; - } else if (z < 0 && zdist < 0) { - mSpaceChargeDensityC[phiBin * mNR * mNZ + rBin * mNZ + zBin] += charge; - } -} - -void SpaceCharge::fillIBFIons(double r, double phi, Side side, int nIons) -{ - const int phiBin = TMath::BinarySearch(mNPhi, mCoordPhi.data(), phi); - const int rBin = TMath::BinarySearch(mNR, mCoordR.data(), r); - const int zBin = mNZ - 1; - /// TODO: distribution of amplification ions instead of placing all of them in one point - /// TODO: protection against ions ending up outside the volume - if (side == Side::A) { - mSpaceChargeDensityA[phiBin * mNR * mNZ + rBin * mNZ + zBin] += ions2Charge(rBin, nIons); - } else { - mSpaceChargeDensityC[phiBin * mNR * mNZ + rBin * mNZ + zBin] += ions2Charge(rBin, nIons); - } -} - -void SpaceCharge::fillIBFCharge(double r, double phi, Side side, float charge) -{ - const int phiBin = TMath::BinarySearch(mNPhi, mCoordPhi.data(), phi); - const int rBin = TMath::BinarySearch(mNR, mCoordR.data(), r); - const int zBin = mNZ - 1; - /// TODO: distribution of amplification ions instead of placing all of them in one point - /// TODO: protection against ions ending up outside the volume - if (side == Side::A) { - mSpaceChargeDensityA[phiBin * mNR * mNZ + rBin * mNZ + zBin] += charge; - } else { - mSpaceChargeDensityC[phiBin * mNR * mNZ + rBin * mNZ + zBin] += charge; - } -} - -void SpaceCharge::propagateSpaceCharge() -{ - // - // Continuity equation, assuming that the charge is conserved: - // delta(rho_0) / delta(t) = - div(flux) = - div(rho_0 * u) = - ( rho_0 * div(u) + u * grad(rho_0) ) - // u: velocity vector of space-charge density - // rho_0: space-charge density at time t0 - // - // - // Calculate the change of the space-charge density rho_0 at time t0 after time delta(t) = mVoxelSizeZ / v_driftIon: - // delta(rho_0) = - ( rho_0 * div(u) + u * grad(rho_0) ) * delta(t) - // = - ( rho_0 * div(d) + d * grad(rho_0) ) - // d: drift vector (dr, dphi, mVoxelSizeZ + dz) - // - // div(d) = 1/r del(r*d_r)/del(r) + 1/r del(d_phi)/del(phi) + del(d_z)/del(z) - // = d_r/r + del(d_r)/del(r) + 1/r del(d_phi)/del(phi) + del(d_z)/del(z) - // - // grad(rho_0) = del(rho_0)/del(r) * e_r + 1/r * del(rho_0)/del(phi) * e_phi + del(rho_0)/del(z) * e_z - // e_i: unit vectors in i = {r, phi, z} direction - // - - // Finite difference interpolation coefficients - const float coeffCent40 = 1.f / 12.f; - const float coeffCent41 = -2.f / 3.f; - const float coeffCent42 = -1.f * coeffCent41; - const float coeffCent43 = -1.f * coeffCent40; - const float coeffFwd30 = -11.f / 6.f; - const float coeffFwd31 = 3.f; - const float coeffFwd32 = -1.5; - const float coeffFwd33 = 1.f / 3.f; - const float coeffFwd20 = -1.5; - const float coeffFwd21 = 2.f; - const float coeffFwd22 = -0.5; - - std::vector<float>* scDensity = nullptr; - TMatrixD** matrixDriftZ = nullptr; - TMatrixD** matrixDriftRPhi = nullptr; - TMatrixD** matrixDriftR = nullptr; - for (int iside = 0; iside < 2; ++iside) { - const int signZ = iside == 0 ? 1 : -1; - if (iside == 0) { - scDensity = &mSpaceChargeDensityA; - matrixDriftZ = (TMatrixD**)mMatrixIonDriftZA.get(); - matrixDriftRPhi = (TMatrixD**)mMatrixIonDriftRPhiA.get(); - matrixDriftR = (TMatrixD**)mMatrixIonDriftRA.get(); - } else { - scDensity = &mSpaceChargeDensityC; - matrixDriftZ = (TMatrixD**)mMatrixIonDriftZC.get(); - matrixDriftRPhi = (TMatrixD**)mMatrixIonDriftRPhiC.get(); - matrixDriftR = (TMatrixD**)mMatrixIonDriftRC.get(); - } - /// TODO: is there a better way than to create a copy for the new SC density? - std::vector<float> newSCDensity(mNPhi * mNR * mNZ); - for (int iphi0 = 0; iphi0 < mNPhi; ++iphi0) { - - for (int ir0 = 0; ir0 < mNR; ++ir0) { - const float r0 = static_cast<float>(mCoordR[ir0]); - - for (int iz0 = 0; iz0 < mNZ; ++iz0) { - - // rho_0 * div(d) - float ddrdr = 0.f; - if (ir0 > 1 && ir0 < mNR - 2) { - ddrdr = (coeffCent40 * (*matrixDriftR[iphi0])(ir0 - 2, iz0) + coeffCent41 * (*matrixDriftR[iphi0])(ir0 - 1, iz0) + coeffCent42 * (*matrixDriftR[iphi0])(ir0 + 1, iz0) + coeffCent43 * (*matrixDriftR[iphi0])(ir0 + 2, iz0)) / static_cast<float>(mVoxelSizeR); - } else if (ir0 < 2) { - ddrdr = (coeffFwd30 * (*matrixDriftR[iphi0])(ir0, iz0) + coeffFwd31 * (*matrixDriftR[iphi0])(ir0 + 1, iz0) + coeffFwd32 * (*matrixDriftR[iphi0])(ir0 + 2, iz0) + coeffFwd33 * (*matrixDriftR[iphi0])(ir0 + 3, iz0)) / static_cast<float>(mVoxelSizeR); - } else if (ir0 > (mNR - 3)) { - ddrdr = -1 * (coeffFwd30 * (*matrixDriftR[iphi0])(ir0, iz0) + coeffFwd31 * (*matrixDriftR[iphi0])(ir0 - 1, iz0) + coeffFwd32 * (*matrixDriftR[iphi0])(ir0 - 2, iz0) + coeffFwd33 * (*matrixDriftR[iphi0])(ir0 - 3, iz0)) / static_cast<float>(mVoxelSizeR); - } - - const int iphiCent0 = iphi0 - 2 + (mNPhi) * (iphi0 < 2); - const int iphiCent1 = iphi0 - 1 + (mNPhi) * (iphi0 < 1); - const int iphiCent3 = iphi0 + 1 - (mNPhi) * (iphi0 > (mNPhi - 2)); - const int iphiCent4 = iphi0 + 2 - (mNPhi) * (iphi0 > (mNPhi - 3)); - const float ddphidphi = (coeffCent40 * (*matrixDriftRPhi[iphiCent0])(ir0, iz0) + coeffCent41 * (*matrixDriftRPhi[iphiCent1])(ir0, iz0) + coeffCent42 * (*matrixDriftRPhi[iphiCent3])(ir0, iz0) + coeffCent43 * (*matrixDriftRPhi[iphiCent4])(ir0, iz0)) / static_cast<float>(mVoxelSizePhi); - - float ddzdz = 0.f; - if (iz0 > 1 && iz0 < mNZ - 2) { - ddzdz = signZ * (coeffCent40 * (*matrixDriftZ[iphi0])(ir0, iz0 - 2) + coeffCent41 * (*matrixDriftZ[iphi0])(ir0, iz0 - 1) + coeffCent42 * (*matrixDriftZ[iphi0])(ir0, iz0 + 1) + coeffCent43 * (*matrixDriftZ[iphi0])(ir0, iz0 + 2)) / static_cast<float>(mVoxelSizeR); - } else if (iz0 == 1 || iz0 == (mNZ - 2)) { - ddzdz = signZ * (-0.5 * (*matrixDriftZ[iphi0])(ir0, iz0 - 1) + 0.5 * (*matrixDriftZ[iphi0])(ir0, iz0 + 1)) / static_cast<float>(mVoxelSizeR); - } else if (iz0 == 0) { - ddzdz = signZ * (coeffFwd20 * (*matrixDriftZ[iphi0])(ir0, iz0) + coeffFwd21 * (*matrixDriftZ[iphi0])(ir0, iz0 + 1) + coeffFwd22 * (*matrixDriftZ[iphi0])(ir0, iz0 + 2)) / static_cast<float>(mVoxelSizeR); - } else if (iz0 == (mNZ - 1)) { - ddzdz = -1 * signZ * (coeffFwd20 * (*matrixDriftZ[iphi0])(ir0, iz0) + coeffFwd21 * (*matrixDriftZ[iphi0])(ir0, iz0 - 1) + coeffFwd22 * (*matrixDriftZ[iphi0])(ir0, iz0 - 2)) / static_cast<float>(mVoxelSizeR); - } - - const float qdivd = (*scDensity)[iphi0 * mNR * mNZ + ir0 * mNZ + iz0] * (((*matrixDriftR[iphi0])(ir0, iz0) + ddphidphi) / r0 + ddrdr + ddzdz); - - // - d * grad(rho_0) = - d_drift * grad(rho_0(x)) + d_dist * grad(rho_0(x+d_drift)) = (charge0 - charge1) + d_dist * grad(rho_0(x-d_drift)) - if (iz0 < (mNZ - 1)) { - const float dr = (*matrixDriftR[iphi0])(ir0, iz0); - const float drphi = (*matrixDriftRPhi[iphi0])(ir0, iz0); - const float dz = (*matrixDriftZ[iphi0])(ir0, iz0) + mVoxelSizeZ * signZ; - - const int ir1 = dr < 0 ? ir0 - 1 * (ir0 == (mNR - 1)) : ir0 - 1 + 1 * (ir0 == 0); - const int ir2 = dr < 0 ? ir0 + 1 - 1 * (ir0 == (mNR - 1)) : ir0 + 1 * (ir0 == 0); - const int iphi1 = drphi < 0 ? iphi0 : iphi0 - 1 + (mNPhi) * (iphi0 == 0); - const int iphi2 = drphi < 0 ? iphi0 + 1 - (mNPhi) * (iphi0 == (mNPhi - 1)) : iphi0; - const int iz1 = dz < 0 ? iz0 + 1 - 1 * (iside == 0) * (iz0 == (mNZ - 2)) : iz0 + 2 * (iside == 1) - 1 * (iside == 1) * (iz0 == (mNZ - 2)); - const int iz2 = dz < 0 ? iz0 + 2 - 2 * (iside == 1) - 1 * (iside == 0) * (iz0 == (mNZ - 2)) : iz0 + 1 - 1 * (iside == 1) * (iz0 == (mNZ - 2)); - - const float dqdr = ((*scDensity)[iphi0 * mNR * mNZ + ir2 * mNZ + (iz0 + 1)] - (*scDensity)[iphi0 * mNR * mNZ + ir1 * mNZ + (iz0 + 1)]) / static_cast<float>(mVoxelSizeR); - const float dqdphi = ((*scDensity)[iphi2 * mNR * mNZ + ir0 * mNZ + (iz0 + 1)] - (*scDensity)[iphi1 * mNR * mNZ + ir0 * mNZ + (iz0 + 1)]) / static_cast<float>(mVoxelSizePhi); - const float dqdz = ((*scDensity)[iphi0 * mNR * mNZ + ir0 * mNZ + iz2] - (*scDensity)[iphi0 * mNR * mNZ + ir0 * mNZ + iz1]) / static_cast<float>(mVoxelSizeZ); - - const float dgradq = dr * dqdr + drphi / r0 * dqdphi + dz * dqdz; - - newSCDensity[iphi0 * mNR * mNZ + ir0 * mNZ + iz0] = (*scDensity)[iphi0 * mNR * mNZ + ir0 * mNZ + (iz0 + 1)] - (qdivd + dgradq); - } else { - newSCDensity[iphi0 * mNR * mNZ + ir0 * mNZ + iz0] = -qdivd; - } - - if (newSCDensity[iphi0 * mNR * mNZ + ir0 * mNZ + iz0] < 0.f) { - newSCDensity[iphi0 * mNR * mNZ + ir0 * mNZ + iz0] = 0.f; - } - } - } - } - (*scDensity).swap(newSCDensity); - } -} - -void SpaceCharge::propagateIons() -{ - std::vector<float>* scDensity = nullptr; - AliTPCLookUpTable3DInterpolatorD* lookUpIonDrift = nullptr; - for (int iside = 0; iside < 2; ++iside) { - const int signZ = iside == 0 ? 1 : -1; - if (iside == 0) { - scDensity = &mSpaceChargeDensityA; - lookUpIonDrift = mLookUpIonDriftA.get(); - } else { - scDensity = &mSpaceChargeDensityC; - lookUpIonDrift = mLookUpIonDriftC.get(); - } - std::vector<float> newSCDensity(mNPhi * mNR * mNZ); - - for (int iphi0 = 0; iphi0 < mNPhi; ++iphi0) { - const double phi0 = static_cast<float>(mCoordPhi[iphi0]); - - for (int ir0 = 0; ir0 < mNR; ++ir0) { - const double r0 = static_cast<float>(mCoordR[ir0]); - const double r1 = r0 + mVoxelSizeR; - - for (int iz0 = 0; iz0 < mNZ; ++iz0) { - const double z0 = mCoordZ[iz0] * signZ; - - const float ionDensity = (*scDensity)[iphi0 * mNR * mNZ + ir0 * mNZ + iz0] * AliTPCPoissonSolver::fgke0 / TMath::Qe(); // #ions / cm^3 - const float nIons = std::round(ionDensity * mVoxelSizeZ * 0.5 * mVoxelSizePhi * (r1 * r1 - r0 * r0)); // absolute #ions in the voxel - - for (int iion = 0; iion < nIons; ++iion) { - double phiIon = phi0 + mRandomFlat.getNextValue() * mVoxelSizePhi; - double rIon = r0 + mRandomFlat.getNextValue() * mVoxelSizeR; - double zIon = z0 + mRandomFlat.getNextValue() * mVoxelSizeZ * signZ; - - double drphi = 0.f; - double dr = 0.f; - double dz = 0.f; - lookUpIonDrift->GetValue(rIon, phiIon, std::abs(zIon), dr, drphi, dz); - float phiIonF = static_cast<float>(phiIon + (drphi / rIon)); - o2::math_utils::bringTo02PiGen(phiIonF); - rIon += dr; - zIon += dz; - - // continue if ion is outside the TPC boundaries in r or z - if (rIon > (mCoordR[mNR - 1] + mVoxelSizeR) || rIon < mCoordR[0]) { - continue; - } - if ((zIon * signZ) > (mCoordZ[mNZ - 1] + mVoxelSizeZ) || (zIon * signZ) < mCoordZ[0]) { - continue; - } - - const int iphiDrift = TMath::BinarySearch(mNPhi, mCoordPhi.data(), static_cast<double>(phiIonF)); - const int irDrift = TMath::BinarySearch(mNR, mCoordR.data(), rIon); - const int izDrift = TMath::BinarySearch(mNZ, mCoordZ.data(), std::abs(zIon)); - newSCDensity[iphiDrift * mNR * mNZ + irDrift * mNZ + izDrift] += ions2Charge(irDrift, 1); - } - } - } - } - (*scDensity).swap(newSCDensity); - } -} - -void SpaceCharge::getIonDrift(Side side, double r, double phi, double z, double& dr, double& drphi, double& dz) const -{ - if (!mInitLookUpTables) { - return; - } - if (side == Side::A) { - mLookUpIonDriftA->GetValue(r, phi, z, dr, drphi, dz); - } else if (side == Side::C) { - mLookUpIonDriftC->GetValue(r, phi, -1 * z, dr, drphi, dz); - } else { - LOG(INFO) << "TPC side undefined! Cannot calculate local ion drift correction..."; - } -} - -void SpaceCharge::correctElectron(GlobalPosition3D& point) -{ - if (!mInitLookUpTables) { - return; - } - const float x[3] = {point.X(), point.Y(), point.Z()}; - float dx[3] = {0.f, 0.f, 0.f}; - float phi = point.phi(); - o2::math_utils::bringTo02PiGen(phi); - int roc = o2::math_utils::angle2Sector(phi); - /// FIXME: which side when z==0? - if (x[2] < 0) { - roc += 18; - } - mLookUpTableCalculator.GetCorrection(x, roc, dx); - point.SetXYZ(x[0] + dx[0], x[1] + dx[1], x[2] + dx[2]); -} - -void SpaceCharge::distortElectron(GlobalPosition3D& point) const -{ - if (!mInitLookUpTables) { - return; - } - const float x[3] = {point.X(), point.Y(), point.Z()}; - float dx[3] = {0.f, 0.f, 0.f}; - float phi = point.phi(); - o2::math_utils::bringTo02PiGen(phi); - int roc = o2::math_utils::angle2Sector(phi); - /// FIXME: which side when z==0? - if (x[2] < 0) { - roc += 18; - } - mLookUpTableCalculator.GetDistortion(x, roc, dx); - point.SetXYZ(x[0] + dx[0], x[1] + dx[1], x[2] + dx[2]); -} - -double SpaceCharge::getChargeDensity(Side side, const GlobalPosition3D& point) const -{ - Float_t x[3] = {point.rho(), point.phi(), point.z()}; - o2::math_utils::bringTo02PiGen(x[1]); - const int roc = side == Side::A ? o2::math_utils::angle2Sector(x[1]) : o2::math_utils::angle2Sector(x[1]) + 18; - return mLookUpTableCalculator.GetChargeCylAC(x, roc); -} - -float SpaceCharge::getChargeDensity(Side side, int ir, int iphi, int iz) const -{ - if (side == Side::A) { - return mSpaceChargeDensityA[iphi * mNR * mNZ + ir * mNZ + iz]; - } else if (side == Side::C) { - return mSpaceChargeDensityC[iphi * mNR * mNZ + ir * mNZ + iz]; - } else { - return -1.f; - } -} - -void SpaceCharge::setUseIrregularLUTs(int useIrrLUTs) -{ - mLookUpTableCalculator.SetCorrectionType(useIrrLUTs); -} - -void SpaceCharge::setUseFastDistIntegration(int useFastInt) -{ - mLookUpTableCalculator.SetIntegrationStrategy(useFastInt); -} - -void SpaceCharge::setDistortionLookupTables(TMatrixD** matrixIntDistDrA, TMatrixD** matrixIntDistDrphiA, TMatrixD** matrixIntDistDzA, TMatrixD** matrixIntDistDrC, TMatrixD** matrixIntDistDrphiC, TMatrixD** matrixIntDistDzC) -{ - mLookUpTableCalculator.SetDistortionLookupTables(matrixIntDistDrA, matrixIntDistDrphiA, matrixIntDistDzA, matrixIntDistDrC, matrixIntDistDrphiC, matrixIntDistDzC); - mInitLookUpTables = true; -} - -float SpaceCharge::ions2Charge(int rBin, int nIons) -{ - float rInner = mCoordR[rBin]; - float rOuter = mCoordR[rBin] + mVoxelSizeR; - return nIons * TMath::Qe() / (mVoxelSizeZ * 0.5 * mVoxelSizePhi * (rOuter * rOuter - rInner * rInner)) / AliTPCPoissonSolver::fgke0; -} diff --git a/Detectors/TPC/simulation/src/TPCSimulationLinkDef.h b/Detectors/TPC/simulation/src/TPCSimulationLinkDef.h index 48edbf58b0277..8a727c250f44d 100644 --- a/Detectors/TPC/simulation/src/TPCSimulationLinkDef.h +++ b/Detectors/TPC/simulation/src/TPCSimulationLinkDef.h @@ -32,8 +32,6 @@ #pragma link C++ class std::vector < o2::tpc::ElementalHit> + ; #pragma link C++ class o2::tpc::HitGroup + ; #pragma link C++ class o2::tpc::SAMPAProcessing + ; -#pragma link C++ class o2::tpc::SpaceCharge + ; -#pragma link C++ enum o2::tpc::SpaceCharge::SCDistortionType + ; #pragma link C++ class std::vector < o2::tpc::HitGroup> + ; diff --git a/Detectors/TPC/spacecharge/CMakeLists.txt b/Detectors/TPC/spacecharge/CMakeLists.txt new file mode 100644 index 0000000000000..a1eb18a71242d --- /dev/null +++ b/Detectors/TPC/spacecharge/CMakeLists.txt @@ -0,0 +1,50 @@ +# 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_library(TPCSpaceCharge + TARGETVARNAME targetName + SOURCES src/SpaceCharge.cxx + src/PoissonSolver.cxx + PUBLIC_LINK_LIBRARIES O2::TPCBase + Vc::Vc + ROOT::Core) + +o2_target_root_dictionary(TPCSpaceCharge + HEADERS include/TPCSpaceCharge/PoissonSolver.h + include/TPCSpaceCharge/SpaceCharge.h + include/TPCSpaceCharge/RegularGrid3D.h + include/TPCSpaceCharge/DataContainer3D.h + include/TPCSpaceCharge/PoissonSolverHelpers.h + include/TPCSpaceCharge/SpaceChargeHelpers.h + include/TPCSpaceCharge/TriCubic.h + include/TPCSpaceCharge/Vector.h + include/TPCSpaceCharge/Vector3D.h + LINKDEF src/TPCSpacechargeLinkDef.h) + +o2_add_test_root_macro(macro/calculateDistortionsCorrections.C + PUBLIC_LINK_LIBRARIES O2::TPCSpaceCharge + LABELS tpc COMPILE_ONLY) + +o2_add_test_root_macro(macro/createResidualDistortionObject.C + PUBLIC_LINK_LIBRARIES O2::TPCSpaceCharge + O2::CommonUtils + LABELS tpc) + +o2_add_test(PoissonSolver + COMPONENT_NAME spacecharge + PUBLIC_LINK_LIBRARIES O2::TPCSpaceCharge + SOURCES test/testO2TPCPoissonSolver.cxx + ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage + LABELS tpc) + +if (OpenMP_CXX_FOUND) + target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) + target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) +endif() diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/DataContainer3D.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/DataContainer3D.h new file mode 100644 index 0000000000000..a641a78598336 --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/DataContainer3D.h @@ -0,0 +1,204 @@ +// 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 DataContainer3D.h +/// \brief This class provides a simple method to store values on a large 3-Dim grid with ROOT io functionality +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Aug 21, 2020 + +#ifndef ALICEO2_TPC_DATACONTAINER3D_H_ +#define ALICEO2_TPC_DATACONTAINER3D_H_ + +#include <memory> +#include "TFile.h" +#include "Rtypes.h" +#include "Framework/Logger.h" +#include <iomanip> + +namespace o2 +{ +namespace tpc +{ + +/// \class DataContainer3D +/// The DataContainer3D class represents a simple method to store values on a large 3-Dim grid with ROOT io functionality. + +/// \tparam DataT the type of data which is used during the calculations +/// \tparam Nx number of values in x direction +/// \tparam Ny number of values in y direction +/// \tparam Nz number of values in z direction +template <typename DataT = double, unsigned int Nx = 129, unsigned int Ny = 129, unsigned int Nz = 180> +struct DataContainer3D { + + ///< default constructor + DataContainer3D() : mData(FN){}; + + /// operator to directly access the values + const DataT& operator[](size_t i) const { return mData[i]; } + DataT& operator[](size_t i) { return mData[i]; } + + const auto& getData() const { return mData; } + auto& getData() { return mData; } + + /// \param ix index in x dimension + /// \param iy index in y dimension + /// \param iz index in z dimension + /// \return returns the stored value + const DataT& operator()(size_t ix, size_t iy, size_t iz) const + { + const size_t ind = getDataIndex(ix, iy, iz); + return mData[ind]; + } + + /// \param ix index in x dimension + /// \param iy index in y dimension + /// \param iz index in z dimension + /// \return returns the stored value + DataT& operator()(size_t ix, size_t iy, size_t iz) + { + const size_t ind = getDataIndex(ix, iy, iz); + return mData[ind]; + } + + /// \param ix index in x dimension + /// \param iy index in y dimension + /// \param iz index in z dimension + /// \return returns the index to the data + static constexpr size_t getDataIndex(const size_t ix, const size_t iy, const size_t iz) + { + const size_t index = ix + Nx * (iy + iz * Ny); + return index; + } + + /// \return returns the number of values stored + static constexpr size_t getNDataPoints() { return FN; } + + /// \return returns the number of x vertices + static constexpr size_t getNX() { return Nx; } + + /// \return returns the number of y vertices + static constexpr size_t getNY() { return Ny; } + + /// \return returns the number of z vertices + static constexpr size_t getNZ() { return Nz; } + + /// write this object to a file + /// \param outf object is written to this file + /// \param name object is saved with this name + int writeToFile(TFile& outf, const char* name = "data") const; + + /// set values from file + bool initFromFile(TFile& inpf, const char* name = "data"); + + /// get pointer to object from file + inline static DataContainer3D<DataT, Nx, Ny, Nz>* loadFromFile(TFile& inpf, const char* name = "data"); + + /// print the matrix + void print() const; + + private: + static constexpr size_t FN{Nx * Ny * Nz}; ///< number of values stored in the container + std::vector<DataT> mData; ///< storage for the data + + ClassDefNV(DataContainer3D, 1) +}; + +/// +/// ======================================================================================================== +/// Inline implementations of some methods +/// ======================================================================================================== +/// + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +int DataContainer3D<DataT, Nx, Ny, Nz>::writeToFile(TFile& outf, const char* name) const +{ + if (outf.IsZombie()) { + LOGP(ERROR, "Failed to write to file: {}", outf.GetName()); + return -1; + } + outf.WriteObjectAny(this, DataContainer3D<DataT, Nx, Ny, Nz>::Class(), name); + return 0; +} + +/// set values from file +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +bool DataContainer3D<DataT, Nx, Ny, Nz>::initFromFile(TFile& inpf, const char* name) +{ + if (inpf.IsZombie()) { + LOGP(ERROR, "Failed to read from file: {}", inpf.GetName()); + return false; + } + DataContainer3D<DataT, Nx, Ny, Nz>* dataCont{nullptr}; + + dataCont = reinterpret_cast<DataContainer3D<DataT, Nx, Ny, Nz>*>(inpf.GetObjectChecked(name, DataContainer3D<DataT, Nx, Ny, Nz>::Class())); + if (!dataCont) { + LOGP(ERROR, "Failed to load {} from {}", name, inpf.GetName()); + return false; + } + mData = dataCont->mData; + return true; +} + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +DataContainer3D<DataT, Nx, Ny, Nz>* DataContainer3D<DataT, Nx, Ny, Nz>::loadFromFile(TFile& inpf, const char* name) +{ + if (inpf.IsZombie()) { + LOGP(ERROR, "Failed to read from file {}", inpf.GetName()); + return nullptr; + } + DataContainer3D<DataT, Nx, Ny, Nz>* dataCont{nullptr}; + + dataCont = reinterpret_cast<DataContainer3D<DataT, Nx, Ny, Nz>*>(inpf.GetObjectChecked(name, DataContainer3D<DataT, Nx, Ny, Nz>::Class())); + if (!dataCont) { + LOGP(ERROR, "Failed to load {} from {}", name, inpf.GetName()); + return nullptr; + } + return dataCont; +} + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +void DataContainer3D<DataT, Nx, Ny, Nz>::print() const +{ + std::stringstream stream; + stream.precision(3); + auto&& w = std::setw(9); + stream << std::endl; + + for (unsigned int iz = 0; iz < Nz; ++iz) { + stream << "z layer: " << iz << "\n"; + // print top x row + stream << "⎡" << w << (*this)(0, 0, iz); + for (unsigned int ix = 1; ix < Nx; ++ix) { + stream << ", " << w << (*this)(ix, 0, iz); + } + stream << " ⎤ \n"; + + for (unsigned int iy = 1; iy < Ny - 1; ++iy) { + stream << "⎢" << w << (*this)(0, iy, iz); + for (unsigned int ix = 1; ix < Nx; ++ix) { + stream << ", " << w << (*this)(ix, iy, iz); + } + stream << " ⎥ \n"; + } + + stream << "⎣" << w << (*this)(0, Ny - 1, iz); + for (unsigned int ix = 1; ix < Nx; ++ix) { + stream << ", " << w << (*this)(ix, Ny - 1, iz); + } + stream << " ⎦ \n \n"; + } + LOGP(info, "{} \n \n", stream.str()); +} + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolver.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolver.h new file mode 100644 index 0000000000000..c708ea88c1fe2 --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolver.h @@ -0,0 +1,488 @@ +// 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 PoissonSolver.h +/// \brief This class provides implementation of Poisson equation +/// solver by MultiGrid Method +/// Original version of this class can be found in AliTPCPoissonSolver.h +/// +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Aug 21, 2020 + +#ifndef ALICEO2_TPC_POISSONSOLVER_H_ +#define ALICEO2_TPC_POISSONSOLVER_H_ + +#include "TPCSpaceCharge/DataContainer3D.h" +#include "TPCSpaceCharge/PoissonSolverHelpers.h" +#include "TPCSpaceCharge/RegularGrid3D.h" +#include "TPCSpaceCharge/Vector3D.h" +#include "CommonConstants/MathConstants.h" + +namespace o2 +{ +namespace tpc +{ + +/// \class PoissonSolver +/// The PoissonSolver class represents methods to solve the poisson equation. +/// Original version with more methods can be found in AliTPCPoissonSolver. +/// Following methods are implemented: poissonSolver3D, poissonSolver3D2D, poissonSolver2D + +/// \tparam DataT the type of data which is used during the calculations +/// \tparam Nr number of vertices in r direction (2^N + 1) +/// \tparam Nz number of vertices in z direction (2^M + 1) +/// \tparam Nphi number of vertices in phi direction +template <typename DataT = double, size_t Nz = 129, size_t Nr = 129, size_t Nphi = 180> +class PoissonSolver +{ + public: + using RegularGrid = RegularGrid3D<DataT, Nz, Nr, Nphi>; + using DataContainer = DataContainer3D<DataT, Nz, Nr, Nphi>; + using Vector = Vector3D<DataT>; + + /// default constructor + PoissonSolver(const RegularGrid& gridProperties) : mGrid3D{gridProperties} {}; + + /// Provides poisson solver in Cylindrical 3D (TPC geometry) + /// + /// Strategy based on parameter settings (mMgParameters)provided + /// * Cascaded multi grid with S.O.R + /// * Geometric MultiGrid + /// * Cycles: V, W, Full + /// * Relaxation: Jacobi, Weighted-Jacobi, Gauss-Seidel + /// * Grid transfer operators: Full, Half + /// * Spectral Methods (TODO) + /// + /// \param matricesV potential in 3D + /// \param matricesCharge charge density in 3D (side effect) + /// \param symmetry symmetry or not + /// + /// \pre Charge density distribution in **matricesCharge** is known and boundary values for **matricesV** are set + /// \post Numerical solution for potential distribution is calculated and stored in each rod at **matricesV** + void poissonSolver3D(DataContainer& matricesV, const DataContainer& matricesCharge, const int symmetry); + + /// Provides poisson solver in 2D + /// + /// Based on the strategy (multi grid) + /// + /// \param matricesV potential in matrix + /// \param matricesCharge charge density in matrix (side effect + void poissonSolver2D(DataContainer& matricesV, const DataContainer& matricesCharge); + + DataT getSpacingZ() const { return mGrid3D.getSpacingX(); } + DataT getSpacingR() const { return mGrid3D.getSpacingY(); } + DataT getSpacingPhi() const { return mGrid3D.getSpacingZ(); } + + static void setConvergenceError(const DataT error) { sConvergenceError = error; } + + static DataT getConvergenceError() { return sConvergenceError; } + + /// get the number of threads used for some of the calculations + static int getNThreads() { return sNThreads; } + + /// set the number of threads used for some of the calculations + static void setNThreads(int nThreads) { sNThreads = nThreads; } + + private: + const RegularGrid& mGrid3D{}; ///< grid properties + inline static DataT sConvergenceError{1e-6}; ///< Error tolerated + static constexpr DataT INVTWOPI = 1. / o2::constants::math::TwoPI; ///< inverse of 2*pi + inline static int sNThreads{4}; ///< number of threads which are used during some of the calculations (increasing this number has no big impact) + + /// Relative error calculation: comparison with exact solution + /// + /// \param matricesCurrentV current potential (numerical solution) + /// \param prevArrayV content from matricesCurrentV from previous iteration + DataT getConvergenceError(const Vector& matricesCurrentV, Vector& prevArrayV) const; + + /// 3D - Solve Poisson's Equation in 3D by MultiGrid with constant phi slices + /// + /// NOTE: In order for this algorithm to work, the number of Nr and Nz must be a power of 2 plus one. + /// The number of Nr and Z Column can be different. + /// + /// R Row == 2**M + 1 + /// Z Column == 2**N + 1 + /// Phi Slice == Arbitrary but greater than 3 + /// + /// Solving: \f$ \nabla^{2}V(r,\phi,z) = - f(r,\phi,z) \f$ + /// + /// Algorithm for MultiGrid Full Cycle (FMG) + /// - Relax on the coarsest grid + /// - Do from coarsest to finest + /// - Interpolate potential from coarse -> fine + /// - Do V-Cycle to the current coarse level to the coarsest + /// - Stop if converged + /// + /// DeltaPhi in Radians + /// \param matricesV potential in 3D matrix \f$ V(r,\phi,z) \f$ + /// \param matricesCharge charge density in 3D matrix (side effect) \f$ - f(r,\phi,z) \f$ + /// \param symmetry symmetry (TODO for symmetry = 1) + // + /// SYMMETRY = 0 if no phi symmetries, and no phi boundary condition + /// = 1 if we have reflection symmetry at the boundaries (eg. sector symmetry or half sector symmetries). + void poissonMultiGrid3D2D(DataContainer& matricesV, const DataContainer& matricesCharge, const int symmetry); + + /// 3D - Solve Poisson's Equation in 3D in all direction by MultiGrid + /// + /// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. + /// The number of nRRow and Z Column can be different. + /// + /// R Row == 2**M + 1 + /// Z Column == 2**N + 1 + /// Phi Slices == Arbitrary but greater than 3 + /// + /// Solving: \f$ \nabla^{2}V(r,\phi,z) = - f(r,\phi,z) \f$ + /// + /// Algorithm for MultiGrid Full Cycle (FMG) + /// - Relax on the coarsest grid + /// - Do from coarsest to finest + /// - Interpolate potential from coarse -> fine + /// - Do V-Cycle to the current coarse level to the coarsest + /// - Stop if converged + /// + /// \param matricesV potential in 3D matrix + /// \param matricesCharge charge density in 3D matrix (side effect) + /// \param symmetry symmetry or not: symmetry = 0 if no phi symmetries, and no phi boundary condition. + /// symmetry = 1 if we have reflection symmetry at the boundaries (eg. sector symmetry or half sector symmetries). + void poissonMultiGrid3D(DataContainer& matricesV, const DataContainer& matricesCharge, const int symmetry); + + /// Solve Poisson's Equation by MultiGrid Technique in 2D (assuming cylindrical symmetry) + /// + /// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. + /// So nRRow == 2**M + 1 and nZColumn == 2**N + 1. The number of nRRow and nZColumn can be different. + /// + /// \param matricesV potential in matrix + /// \param matricesCharge charge density in matrix (side effect + /// \param iPhi phi vertex + void poissonMultiGrid2D(DataContainer& matricesV, const DataContainer& matricesCharge, const int iPhi = 0); + + /// Restrict2D + /// + /// Grid transfer operator, restrict from fine -> coarse grid + /// provide full-half weighting + /// + /// \[ \frac{1}{16}\left( \begin{array}{ccc} + /// 1 & 2 & 1 \\ + /// 2 & 4 & 2 \\ + /// 1 & 2 & 1 \end{array} \right) \] + /// + /// \param matricesCurrentCharge coarse grid (2h) + /// \param residue fine grid (h) + /// \param tnRRow number of vertices in r direction of TPC + /// \param tnZColumn number of vertices in z direction of TPC + /// \param iphi phi vertex + void restrict2D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int iphi) const; + + /// Restriction in 3D + /// + /// Restriction is a map from fine grid (h) to coarse grid (2h) + /// + /// In case of 3D + /// Full weighting: + /// \f[ (R u)_{i,j,k} = \frac{1}{2} u_{2i,2j,2k} + \frac{1}{4} S_{1} + \frac{1}{8} S_{2} + \frac{1}{16} S_{3}\f] + /// + /// + /// Restriction in all direction r-phi-z + /// restriction in phi only if oldPhi == 2*newPhi + /// \param matricesCurrentCharge coarser grid 2h + /// \param residue fine grid h + /// \param tnRRow number of grid in Nr (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 + /// \param tnZColumn number of grid in Nz (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 + /// \param newPhiSlice number of Nphi (in phi-direction) for coarser grid + /// \param oldPhiSlice number of Nphi (in phi-direction) for finer grid + void restrict3D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const; + + /// Restrict Boundary in 3D + /// + /// Pass boundary information to coarse grid + /// + /// \param matricesCurrentCharge coarser grid 2h + /// \param residue fine grid h + /// \param tnRRow number of grid in Nr (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 + /// \param tnZColumn number of grid in Nz (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 + /// \param newPhiSlice number of Nphi (in phi-direction) for coarser grid + /// \param oldPhiSlice number of Nphi (in phi-direction) for finer grid + void restrictBoundary3D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const; + + /// Relaxation operation for multiGrid + /// relaxation used 7 stencil in cylindrical coordinate + /// + /// Using the following equations + /// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ + /// + /// \param matricesCurrentV potential in 3D (matrices of matrix) + /// \param matricesCurrentCharge charge in 3D + /// \param tnRRow number of grid in in r-direction for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 + /// \param tnZColumn number of grid in in z-direction for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 + /// \param iPhi phi vertex + /// \param symmetry is the cylinder has symmetry + /// \param h2 \f$ h_{r}^{2} \f$ + /// \param tempRatioZ ration between grid size in z-direction and r-direction + /// \param coefficient1 coefficients for \f$ V_{x+1,y,z} \f$ + /// \param coefficient2 coefficients for \f$ V_{x-1,y,z} \f$ + /// \param coefficient3 coefficients for z + /// \param coefficient4 coefficients for f(r,\phi,z) + void relax3D(Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const int iPhi, const int symmetry, const DataT h2, const DataT tempRatioZ, + const std::array<DataT, Nr>& coefficient1, const std::array<DataT, Nr>& coefficient2, const std::array<DataT, Nr>& coefficient3, const std::array<DataT, Nr>& coefficient4) const; + + /// Relax2D + /// + /// Relaxation operation for multiGrid + /// relaxation used 5 stencil in cylindrical coordinate + /// + /// Using the following equations + /// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ + /// + /// \param matricesCurrentV potential in 3D (matrices of matrix) + /// \param matricesCurrentCharge charge in 3D + /// \param tnRRow number of vertices in r direction of TPC + /// \param tnZColumn number of vertices in z direction of TPC + /// \param h2 \f$ h_{r}^{2} \f$ + /// \param tempFourth coefficient for h + /// \param tempRatio ratio between grid size in z-direction and r-direction + /// \param coefficient1 coefficient for \f$ V_{x+1,y,z} \f$ + /// \param coefficient2 coefficient for \f$ V_{x-1,y,z} \f$ + void relax2D(Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const DataT h2, const DataT tempFourth, const DataT tempRatio, + std::vector<DataT>& coefficient1, std::vector<DataT>& coefficient2); + + /// Interpolation/Prolongation in 2D + /// + /// Interpolation is a map from coarse grid (h) to fine grid (2h) + /// + /// In case of 2D + /// Full weighting: + /// \f[ (R u)_{i,j,k} = \frac{1}{2} u_{2i,2j,2k} + \frac{1}{4} S_{1} + \frac{1}{8} S_{2} + \frac{1}{16} S_{3}\f] + /// + /// + /// Restriction in all direction r-phi-z + /// \param matricesCurrentV finer grid h + /// \param matricesCurrentVC coarse grid 2h + /// \param tnRRow number of grid in r-direction for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 + /// \param tnZColumn number of grid in z-direction for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 + /// \param iphi phi vertex + void interp2D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int iphi) const; + + /// Interpolation/Prolongation in 3D + /// + /// Interpolation is a map from coarse grid (h) to fine grid (2h) + /// + /// In case of 3D + /// Full weighting: + /// \f[ (R u)_{i,j,k} = \frac{1}{2} u_{2i,2j,2k} + \frac{1}{4} S_{1} + \frac{1}{8} S_{2} + \frac{1}{16} S_{3}\f] + /// + /// + /// Restriction in all direction r-phi-z + /// restriction in phi only if oldPhi == 2*newPhi + /// \param matricesCurrentV finer grid h + /// \param matricesCurrentVC coarse grid 2h + /// \param tnRRow number of vertices in r-direction for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 + /// \param tnZColumn number of vertices in z-direction for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 + /// \param newPhiSlice number of vertices in phi-direction for coarser grid + /// \param oldPhiSlice number of vertices in phi-direction for finer grid + void interp3D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const; + + /// Prolongation with Addition for 3D + /// + /// Interpolation with addition from coarse level (2h) --> fine level (h) + /// + /// Interpolation in all direction r-phi-z + /// Interpolation in phi only if oldPhi == 2*newPhi + /// \param matricesCurrentV fine grid h + /// \param matricesCurrentVC coarse grid 2h + /// \param tnRRow number of vertices in r-direction for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 + /// \param tnZColumn number of vertices in z-direction for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1a + /// \param newPhiSlice number of vertices in phi-direction for coarser grid + /// \param oldPhiSlice number of vertices in phi-direction for finer grid + void addInterp3D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const; + + /// Prolongation with Addition for 2D + /// + /// Interpolation with addition from coarse level (2h) --> fine level (h) + /// + /// Interpolation in all direction r-phi-z + /// \param matricesCurrentV fine grid h + /// \param matricesCurrentVC coarse grid 2h + /// \param tnRRow number of vertices in r-direction for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 + /// \param tnZColumn number of vertices in z-direction for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1a + /// \param tnPhi phi vertices + void addInterp2D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int tnPhi) const; + + /// VCycle 3D2D, V Cycle 3D in multiGrid with constant Nphi + /// fine-->coarsest-->fine, propagating the residue to correct initial guess of V + /// + /// Algorithm: + /// + /// NOTE: In order for this algorithm to work, the number of Nr and Nz must be a power of 2 plus one. + /// The number of Nr and Z Column can be different. + /// + /// R Row == 2**M + 1 + /// Z Column == 2**N + 1 + /// Phi Slice == Arbitrary but greater than 3 + /// + /// DeltaPhi in Radians + /// \param gridFrom finest level of grid + /// \param gridTo coarsest level of grid + /// \param nPre number of smoothing before coarsening + /// \param nPost number of smoothing after coarsening + /// \param ratioZ ratio between square of grid r and grid z (OPTION, recalculate) + /// \param ratioPhi ratio between square of grid r and grid phi (OPTION, recalculate) + /// \param tvArrayV vector of V potential in different grids + /// \param tvCharge vector of charge distribution in different grids + /// \param tvResidue vector of residue calculation in different grids + /// \param coefficient1 coefficient for relaxation (r direction) + /// \param coefficient2 coefficient for relaxation (r direction) + /// \param coefficient3 coefficient for relaxation (ratio r/z) + /// \param coefficient4 coefficient for relaxation (ratio for grid_r) + /// \param inverseCoefficient4 coefficient for relaxation (inverse coefficient4) + void vCycle3D2D(const int symmetry, const int gridFrom, const int gridTo, const int nPre, const int nPost, const DataT ratioZ, const DataT ratioPhi, std::vector<Vector>& tvArrayV, + std::vector<Vector>& tvCharge, std::vector<Vector>& tvResidue, std::array<DataT, Nr>& coefficient1, std::array<DataT, Nr>& coefficient2, std::array<DataT, Nr>& coefficient3, + std::array<DataT, Nr>& coefficient4, std::array<DataT, Nr>& inverseCoefficient4) const; + + /// VCycle 3D, V Cycle in multiGrid, fine-->coarsest-->fine, propagating the residue to correct initial guess of V + /// + /// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. + /// The number of nRRow and Z Column can be different. + /// + /// R Row == 2**M + 1 + /// Z Column == 2**N + 1 + /// Phi Slice == Arbitrary but greater than 3 + /// + /// DeltaPhi in Radians + /// + /// \param symmetry symmetry or not + /// \param gridFrom finest level of grid + /// \param gridTo coarsest level of grid + /// \param nPre number of smoothing before coarsening + /// \param nPost number of smoothing after coarsening + /// \param ratioZ ratio between square of grid r and grid z (OPTION, recalculate) + /// \param tvArrayV vector of V potential in different grids + /// \param tvCharge vector of charge distribution in different grids + /// \param tvResidue vector of residue calculation in different grids + /// \param coefficient1 coefficient for relaxation (r direction) + /// \param coefficient2 coefficient for relaxation (r direction) + /// \param coefficient3 coefficient for relaxation (ratio r/z) + /// \param coefficient4 coefficient for relaxation (ratio for grid_r) + /// \param inverseCoefficient4 coefficient for relaxation (inverse coefficient4) + void vCycle3D(const int symmetry, const int gridFrom, const int gridTo, const int nPre, const int nPost, const DataT ratioZ, std::vector<Vector>& tvArrayV, std::vector<Vector>& tvCharge, + std::vector<Vector>& tvResidue, std::array<DataT, Nr>& coefficient1, std::array<DataT, Nr>& coefficient2, std::array<DataT, Nr>& coefficient3, + std::array<DataT, Nr>& coefficient4, std::array<DataT, Nr>& inverseCoefficient4) const; + + /// V-Cycle 2D + /// + /// Implementation non-recursive V-cycle for 2D + /// + /// Algorithms: + /// + /// \param gridFrom finest level of grid + /// \param gridTo coarsest level of grid + /// \param nPre number of smoothing before coarsening + /// \param nPost number of smoothing after coarsening + /// \param gridSizeR grid size in r direction (OPTION, recalculate) + /// \param ratio ratio between square of grid r and grid z (OPTION, recalculate) + /// \param tvArrayV vector of V potential in different grids + /// \param tvCharge vector of charge distribution in different grids + /// \param tvResidue vector of residue calculation in different grids + void vCycle2D(const int gridFrom, const int gridTo, const int nPre, const int nPost, const DataT gridSizeR, const DataT ratio, std::vector<Vector>& tvArrayV, + std::vector<Vector>& tvCharge, std::vector<Vector>& tvResidue); + + /// W-Cycle 2D + /// + /// Implementation non-recursive W-cycle for 2D + /// + /// Algorithms: + /// + /// \param gridFrom finest level of grid + /// \param gridTo coarsest level of grid + /// \param gamma number of iterations at coarsest level + /// \param nPre number of smoothing before coarsening + /// \param nPost number of smoothing after coarsening + /// \param gridSizeR grid size in r direction (OPTION, recalculate) + /// \param ratio ratio between square of grid r and grid z (OPTION, recalculate) + /// \param tvArrayV vector of V potential in different grids + /// \param tvCharge vector of charge distribution in different grids + /// \param tvResidue vector of residue calculation in different grids + void wCycle2D(const int gridFrom, const int gridTo, const int gamma, const int nPre, const int nPost, const DataT gridSizeR, const DataT ratio, + std::vector<Vector>& tvArrayV, std::vector<Vector>& tvCharge, std::vector<Vector>& tvResidue); + + /// Residue3D + /// + /// Compute residue from V(.) where V(.) is numerical potential and f(.). + /// residue used 7 stencil in cylindrical coordinate + /// + /// Using the following equations + /// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ + /// + /// \param residue residue in 3D (matrices of matrix) + /// \param matricesCurrentV potential in 3D (matrices of matrix) + /// \param matricesCurrentCharge charge in 3D + /// \param tnRRow number of vertices in the r direction of TPC + /// \param tnZColumn number of vertices in z direction of TPC + /// \param tnPhi number of vertices in phi direction of TPC + /// \param symmetry if the cylinder has symmetry + /// \param ih2 \f$ 1/ h_{r}^{2} \f$ + /// \param tempRatioZ ration between grid size in z-direction and r-direction + /// \param coefficient1 coefficient for \f$ V_{x+1,y,z} \f$ + /// \param coefficient2 coefficient for \f$ V_{x-1,y,z} \f$ + /// \param coefficient3 coefficient for z + /// \param inverseCoefficient4 inverse coefficient for f(r,\phi,z) + void residue3D(Vector& residue, const Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const int tnPhi, const int symmetry, const DataT ih2, const DataT tempRatioZ, + const std::array<DataT, Nr>& coefficient1, const std::array<DataT, Nr>& coefficient2, const std::array<DataT, Nr>& coefficient3, const std::array<DataT, Nr>& inverseCoefficient4) const; + + /// Residue2D + /// + /// Compute residue from V(.) where V(.) is numerical potential and f(.). + /// residue used 5 stencil in cylindrical coordinate + /// + /// Using the following equations + /// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ + /// + /// \param residue potential in 2D + /// \param matricesCurrentV potential in 2D + /// \param matricesCurrentCharge charge in 2D + /// \param nRRow number of nRRow in the r direction of TPC + /// \param nZColumn number of nZColumn in z direction of TPC + /// \param ih2 \f$ h_{r}^{2} \f$ + /// \param iTempFourth coefficient for h + /// \param tempRatio ratio between grid size in z-direction and r-direction + /// \param coefficient1 coefficient for \f$ V_{x+1,y,z} \f$ + /// \param coefficient2 coefficient for \f$ V_{x-1,y,z} \f$ + void residue2D(Vector& residue, const Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const DataT ih2, const DataT inverseTempFourth, + const DataT tempRatio, std::vector<DataT>& coefficient1, std::vector<DataT>& coefficient2); + + /// Boundary transfer restrict from fine -> coarse grid + /// + /// \param matricesCurrentCharge coarse grid (2h) + /// \param residue fine grid (h) + /// \param tnRRow number of vertices in the r direction of TPC + /// \param tnZColumn number of vertices in z direction of TPC + /// \param tnPhi phi vertices + void restrictBoundary2D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int tnPhi) const; + + // calculate coefficients + void calcCoefficients(unsigned int from, unsigned int to, const DataT h, const DataT tempRatioZ, const DataT tempRatioPhi, std::array<DataT, Nr>& coefficient1, + std::array<DataT, Nr>& coefficient2, std::array<DataT, Nr>& coefficient3, std::array<DataT, Nr>& coefficient4) const; + + // calculate coefficients for 2D poisson solver + void calcCoefficients2D(unsigned int from, unsigned int to, const DataT h, std::vector<DataT>& coefficient1, std::vector<DataT>& coefficient2) const; + + /// Helper function to check if the integer is equal to a power of two + /// \param i the number + /// \return 1 if it is a power of two, else 0 + bool isPowerOfTwo(const int i) const + { + return ((i > 0) && !(i & (i - 1))); + }; +}; + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolverHelpers.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolverHelpers.h new file mode 100644 index 0000000000000..044a5564e519b --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/PoissonSolverHelpers.h @@ -0,0 +1,88 @@ +// 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 O2TPCPoissonSolverHelpers.h +/// \brief This file provides all the necessary structs which are used in the poisson solver +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Aug 21, 2020 + +#ifndef ALICEO2_TPC_POISSONSOLVERHELPERS_H_ +#define ALICEO2_TPC_POISSONSOLVERHELPERS_H_ + +#include "CommonConstants/MathConstants.h" + +namespace o2 +{ +namespace tpc +{ + +///< Enumeration of Cycles Type +enum class CycleType { + VCycle = 0, ///< V Cycle + WCycle = 1, ///< W Cycle (TODO) + FCycle = 2 ///< Full Cycle +}; + +///< Fine -> Coarse Grid transfer operator types +enum class GridTransferType { + Half = 0, ///< Half weighting + Full = 1, ///< Full weighting +}; + +///< Smoothing (Relax) operator types +enum class RelaxType { + Jacobi = 0, ///< Jacobi (5 Stencil 2D, 7 Stencil 3D_ + WeightedJacobi = 1, ///< (TODO) + GaussSeidel = 2 ///< Gauss Seidel 2D (2 Color, 5 Stencil), 3D (7 Stencil) +}; + +struct MGParameters { ///< Parameters choice for MultiGrid algorithm + inline static bool isFull3D = true; ///< TRUE: full coarsening, FALSE: semi coarsening + inline static CycleType cycleType = CycleType::FCycle; ///< cycleType follow CycleType + inline static GridTransferType gtType = GridTransferType::Full; ///< gtType grid transfer type follow GridTransferType + inline static RelaxType relaxType = RelaxType::GaussSeidel; ///< relaxType follow RelaxType + inline static int nPre = 2; ///< number of iteration for pre smoothing + inline static int nPost = 2; ///< number of iteration for post smoothing + inline static int nMGCycle = 200; ///< number of multi grid cycle (V type) + inline static int maxLoop = 7; ///< the number of tree-deep of multi grid + inline static int gamma = 1; ///< number of iteration at coarsest level !TODO SET TO REASONABLE VALUE! +}; + +template <typename DataT = double> +struct TPCParameters { + static constexpr DataT TPCZ0{249.525}; ///< nominal G1T position + static constexpr DataT IFCRADIUS{83.5}; ///< Mean Radius of the Inner Field Cage ( 82.43 min, 83.70 max) (cm) + static constexpr DataT OFCRADIUS{254.5}; ///< Mean Radius of the Outer Field Cage (252.55 min, 256.45 max) (cm) + static constexpr DataT ZOFFSET{0.2}; ///< Offset from CE: calculate all distortions closer to CE as if at this point + static constexpr DataT DVDE{0.0024}; ///< [cm/V] drift velocity dependency on the E field (from Magboltz for NeCO2N2 at standard environment) + static constexpr DataT EM{-1.602176487e-19 / 9.10938215e-31}; ///< charge/mass in [C/kg] + static constexpr DataT E0{8.854187817e-12}; ///< vacuum permittivity [A·s/(V·m)] + inline static DataT cathodev{-103070.0}; ///< Cathode Voltage [V] (for 400 V/cm) + inline static DataT vg1t{-3260}; ///< GEM 1 Top voltage. (setting with reduced ET1,2,4 = 3.5kV/cm) +}; + +template <typename DataT = double, size_t Nr = 129, size_t Nz = 129, size_t Nphi = 180> +struct GridProperties { + static constexpr DataT RMIN{TPCParameters<DataT>::IFCRADIUS}; ///< min radius + static constexpr DataT ZMIN{0}; ///< min z coordinate + static constexpr DataT PHIMIN{0}; ///< min phi coordinate + static constexpr DataT RMAX{TPCParameters<DataT>::OFCRADIUS}; ///< max radius + static constexpr DataT ZMAX{TPCParameters<DataT>::TPCZ0}; ///< max z coordinate + static constexpr DataT PHIMAX{static_cast<DataT>(o2::constants::math::TwoPI)}; ///< max phi coordinate + static constexpr DataT GRIDSPACINGR{(RMAX - RMIN) / (Nr - 1)}; ///< grid spacing in r direction + static constexpr DataT GRIDSPACINGZ{(ZMAX - ZMIN) / (Nz - 1)}; ///< grid spacing in z direction + static constexpr DataT GRIDSPACINGPHI{PHIMAX / Nphi}; ///< grid spacing in phi direction +}; + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/RegularGrid3D.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/RegularGrid3D.h new file mode 100644 index 0000000000000..f9a5948ece0ad --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/RegularGrid3D.h @@ -0,0 +1,245 @@ +// 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 RegularGrid3D.h +/// \brief Definition of RegularGrid3D class +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> + +#ifndef ALICEO2_TPC_REGULARGRID3D_H_ +#define ALICEO2_TPC_REGULARGRID3D_H_ + +#include "TPCSpaceCharge/Vector.h" +#include "Rtypes.h" // for ClassDefNV + +namespace o2 +{ +namespace tpc +{ + +/// \class RegularGrid3D +/// This class implements basic properties of a regular 3D-Grid like the spacing for each dimension and min and max coordinates. + +/// \tparam DataT the type of data which is used during the calculations +/// \tparam Nx number of vertices in x direction +/// \tparam Ny number of vertices in y direction +/// \tparam Nz number of vertices in z direction +template <typename DataT = double, unsigned int Nx = 129, unsigned int Ny = 129, unsigned int Nz = 180> +struct RegularGrid3D { + + public: + RegularGrid3D(const DataT xmin, const DataT ymin, const DataT zmin, const DataT spacingX, const DataT spacingY, const DataT spacingZ) : mMin{{xmin, ymin, zmin}}, mMax{{xmin + (Nx - 1) * spacingX, ymin + (Ny - 1) * spacingY, zmin + (Nz - 1) * spacingZ}}, mSpacing{{spacingX, spacingY, spacingZ}}, mInvSpacing{{static_cast<DataT>(1 / spacingX), static_cast<DataT>(1 / spacingY), static_cast<DataT>(1 / spacingZ)}} + { + initLists(); + } + + /// \param deltaX delta x index + /// \return returns the delta index (where the data is stored) for given deltaX + int getDeltaXDataIndex(const int deltaX) const { return deltaX; } + + /// \param deltaY delta y index + /// \return returns the delta index (where the data is stored) for given deltaY + int getDeltaYDataIndex(const int deltaY) const { return Nx * deltaY; } + + /// \param deltaZ delta z index + /// \return returns the delta index (where the data is stored) for given deltaZ + int getDeltaZDataIndex(const int deltaZ) const { return deltaZ * Ny * Nx; } + + // same as above + /// \param delta delta index + /// \param dim dimension of interest + /// \return returns the delta index (where the data is stored) for given delta and dim + int getDeltaDataIndex(const int delta, const int dim) const; + + // check if the specified index for given dimension lies in the grid + /// \param index query index + /// \return returns if the index lies in the grid + bool isIndexInGrid(const int index, const unsigned int dim) const { return index < 0 ? false : (index > (sNdim[dim] - 1) ? false : true); } + + /// \param dim dimension of interest + /// \return returns the number of vertices for given dimension for the grid + static constexpr size_t getN(unsigned int dim) { return sNdim[dim]; } + static constexpr size_t getNX() { return sNdim[FX]; } + static constexpr size_t getNY() { return sNdim[FY]; } + static constexpr size_t getNZ() { return sNdim[FZ]; } + + static constexpr unsigned int getDim() { return FDIM; } /// \return returns number of dimensions of the grid (3) + static constexpr unsigned int getFX() { return FX; } /// \return returns the index for dimension x (0) + static constexpr unsigned int getFY() { return FY; } /// \return returns the index for dimension y (1) + static constexpr unsigned int getFZ() { return FZ; } /// \return returns the index for dimension z (2) + + const Vector<DataT, 3>& getGridMin() const { return mMin; } /// \return returns the minimum coordinates of the grid in all dimensions + DataT getGridMinX() const { return mMin[FX]; } /// \return returns the minimum coordinate of the grid in x dimension + DataT getGridMinY() const { return mMin[FY]; } /// \return returns the minimum coordinate of the grid in y dimension + DataT getGridMinZ() const { return mMin[FZ]; } /// \return returns the minimum coordinate of the grid in z dimension + + DataT getGridMaxX() const { return mMax[FX]; } + DataT getGridMaxY() const { return mMax[FY]; } + DataT getGridMaxZ() const { return mMax[FZ]; } + + /// \return returns the inversed spacing of the grid for all dimensions + const Vector<DataT, 3>& getInvSpacing() const { return mInvSpacing; } + DataT getInvSpacingX() const { return mInvSpacing[FX]; } + DataT getInvSpacingY() const { return mInvSpacing[FY]; } + DataT getInvSpacingZ() const { return mInvSpacing[FZ]; } + + DataT getSpacingX() const { return mSpacing[FX]; } + DataT getSpacingY() const { return mSpacing[FY]; } + DataT getSpacingZ() const { return mSpacing[FZ]; } + + // clamp coordinates to the grid (not circular) + /// \param pos query position which will be clamped + /// \return returns clamped coordinate coordinate + DataT clampToGrid(const DataT pos, const unsigned int dim) const; + + // clamp coordinates to the grid (not circular) + /// \param pos relative query position in grid which will be clamped + /// \return returns clamped coordinate coordinate + DataT clampToGridRel(const DataT pos, const unsigned int dim) const; + + // clamp coordinates to the grid circular + /// \param pos query position which will be clamped + /// \return returns clamped coordinate coordinate + DataT clampToGridCircular(DataT pos, const unsigned int dim) const; + + // clamp coordinates to the grid circular + /// \param pos relative query position in grid which will be clamped + /// \return returns clamped coordinate coordinate + DataT clampToGridCircularRel(DataT pos, const unsigned int dim) const; + + void checkStability(Vector<DataT, 3>& relPos, const Vector<int, 3>& circular) const; + + /// \param vertexX in x dimension + /// \return returns the x positon for given vertex + DataT getXVertex(const size_t vertexX) const { return mXVertices[vertexX]; } + + /// \param vertexY in y dimension + /// \return returns the y positon for given vertex + DataT getYVertex(const size_t vertexY) const { return mYVertices[vertexY]; } + + /// \param vertexZ in z dimension + /// \return returns the z positon for given vertex + DataT getZVertex(const size_t vertexZ) const { return mZVertices[vertexZ]; } + + const Vector<DataT, 3>& getMaxIndices() const { return sMaxIndex; } /// get max indices for all dimensions + + DataT getMaxIndexX() const { return sMaxIndex[0]; } /// get max index in x direction + DataT getMaxIndexY() const { return sMaxIndex[1]; } /// get max index in y direction + DataT getMaxIndexZ() const { return sMaxIndex[2]; } /// get max index in z direction + + private: + static constexpr unsigned int FDIM = 3; ///< dimensions of the grid (only 3 supported) + static constexpr unsigned int FX = 0; ///< index for x coordinate + static constexpr unsigned int FY = 1; ///< index for y coordinate + static constexpr unsigned int FZ = 2; ///< index for z coordinate + const Vector<DataT, FDIM> mMin{}; ///< min vertices positions of the grid + const Vector<DataT, FDIM> mMax{}; ///< max vertices positions of the grid + const Vector<DataT, FDIM> mSpacing{}; ///< spacing of the grid + const Vector<DataT, FDIM> mInvSpacing{}; ///< inverse spacing of grid + const inline static Vector<DataT, FDIM> sMaxIndex{{Nx - 1, Ny - 1, Nz - 1}}; ///< max index which is on the grid in all dimensions + inline static Vector<int, FDIM> sNdim{{Nx, Ny, Nz}}; ///< number of vertices for each dimension + DataT mXVertices[Nx]{}; ///< positions of vertices in x direction + DataT mYVertices[Ny]{}; ///< positions of vertices in y direction + DataT mZVertices[Nz]{}; ///< positions of vertices in z direction + + void initLists(); + + ClassDefNV(RegularGrid3D, 1) +}; + +/// +/// ======================================================================================================== +/// Inline implementations of some methods +/// ======================================================================================================== +/// + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +DataT RegularGrid3D<DataT, Nx, Ny, Nz>::clampToGrid(const DataT pos, const unsigned int dim) const +{ + if (mMin[dim] < mMax[dim]) { + if (pos < mMin[dim]) { + return mMin[dim]; + } else if (pos > mMax[dim]) { + return mMax[dim]; + } + } else { + if (pos > mMin[dim]) { + return mMin[dim]; + } else if (pos < mMax[dim]) { + return mMax[dim]; + } + } + return pos; +} + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +DataT RegularGrid3D<DataT, Nx, Ny, Nz>::clampToGridRel(const DataT pos, const unsigned int dim) const +{ + if (pos < 0) { + return 0; + } else if (pos >= sMaxIndex[dim]) { + return sMaxIndex[dim] - 1; // -1 return second last index. otherwise two additional points have to be extrapolated for tricubic interpolation + } + return pos; +} + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +DataT RegularGrid3D<DataT, Nx, Ny, Nz>::clampToGridCircular(DataT pos, const unsigned int dim) const +{ + while (pos < mMin[dim]) { + pos += mMax[dim] - mMin[dim] + mSpacing[dim]; + } + while (pos >= mMax[dim] + mSpacing[dim]) { + pos -= mMax[dim] + mSpacing[dim] - mMin[dim]; + } + return pos; +} + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +DataT RegularGrid3D<DataT, Nx, Ny, Nz>::clampToGridCircularRel(DataT pos, const unsigned int dim) const +{ + while (pos < 0) { + pos += sNdim[dim]; + } + while (pos > sNdim[dim]) { + pos -= sNdim[dim]; + } + if (pos == sNdim[dim]) { + pos = 0; + } + return pos; +} + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +void RegularGrid3D<DataT, Nx, Ny, Nz>::initLists() +{ + for (size_t i = 0; i < Nx; ++i) { + mXVertices[i] = mMin[FX] + i * mSpacing[FX]; + } + for (size_t i = 0; i < Ny; ++i) { + mYVertices[i] = mMin[FY] + i * mSpacing[FY]; + } + for (size_t i = 0; i < Nz; ++i) { + mZVertices[i] = mMin[FZ] + i * mSpacing[FZ]; + } +} + +template <typename DataT, unsigned int Nx, unsigned int Ny, unsigned int Nz> +int RegularGrid3D<DataT, Nx, Ny, Nz>::getDeltaDataIndex(const int delta, const int dim) const +{ + const unsigned int offset[FDIM]{1, Nx, Ny * Nx}; + const int deltaIndex = delta * offset[dim]; + return deltaIndex; +} + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceCharge.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceCharge.h new file mode 100644 index 0000000000000..4d4376b758d2b --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceCharge.h @@ -0,0 +1,901 @@ +// 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 SpaceCharge.h +/// \brief This class contains the algorithms for calculation the distortions and corrections +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Aug 21, 2020 + +#ifndef ALICEO2_TPC_SPACECHARGE_H_ +#define ALICEO2_TPC_SPACECHARGE_H_ + +#include "TPCSpaceCharge/TriCubic.h" +#include "TPCSpaceCharge/PoissonSolver.h" +#include "TPCSpaceCharge/SpaceChargeHelpers.h" +#include "TPCSpaceCharge/RegularGrid3D.h" +#include "TPCSpaceCharge/DataContainer3D.h" + +#include "TPCBase/ParameterGas.h" +#include "Field/MagneticField.h" +#include "TGeoGlobalMagField.h" + +#include "DataFormatsTPC/Defs.h" +#include "Framework/Logger.h" + +// Root includes +#include "TF1.h" /// for numerical intergration only +#include "TH3.h" + +namespace o2 +{ +namespace tpc +{ + +/// \class SpaceCharge +/// this class provides the algorithms for calculating the global distortions and corrections from the space charge density. +/// The calculations can be done by a realistic space charge histogram as an input or by an analytical formula. +/// An example of of the usage can be found in 'macro/calculateDistortionsCorrections.C' + +/// \tparam DataT the data type which is used during the calculations +/// \tparam Nz number of vertices in z direction +/// \tparam Nr number of vertices in r direction +/// \tparam Nphi number of vertices in phi direction +template <typename DataT = double, size_t Nz = 129, size_t Nr = 129, size_t Nphi = 180> +class SpaceCharge +{ + using RegularGrid = RegularGrid3D<DataT, Nz, Nr, Nphi>; + using DataContainer = DataContainer3D<DataT, Nz, Nr, Nphi>; + using GridProp = GridProperties<DataT, Nr, Nz, Nphi>; + using TriCubic = TriCubicInterpolator<DataT, Nz, Nr, Nphi>; + + public: + /// default constructor + SpaceCharge() = default; + + /// Enumerator for setting the space-charge distortion mode + enum class SCDistortionType : int { + SCDistortionsConstant = 0, // space-charge distortions constant over time + SCDistortionsRealistic = 1 // realistic evolution of space-charge distortions over time + }; + + /// numerical integration strategys + enum class IntegrationStrategy { Trapezoidal = 0, ///< trapezoidal integration (https://en.wikipedia.org/wiki/Trapezoidal_rule). straight electron drift line assumed: z0->z1, r0->r0, phi0->phi0 + Simpson = 1, ///< simpon integration. see: https://en.wikipedia.org/wiki/Simpson%27s_rule. straight electron drift line assumed: z0->z1, r0->r0, phi0->phi0 + Root = 2, ///< Root integration. straight electron drift line assumed: z0->z1, r0->r0, phi0->phi0 + SimpsonIterative = 3 ///< simpon integration, but using an iterative method to approximate the drift path. No straight electron drift line assumed: z0->z1, r0->r1, phi0->phi1 + }; + + enum class Type { + Distortions = 0, ///< distortions + Corrections = 1 ///< corrections + }; + + enum class GlobalDistType { + Standard = 0, ///< classical method (start calculation of global distortion at each voxel in the tpc and follow electron drift to readout -slow-) + Fast = 1, ///< interpolation of global corrections (use the global corrections to apply an iterative approach to obtain the global distortions -fast-) + None = 2 ///< dont calculate global distortions + }; + + enum class GlobalDistCorrMethod { + LocalDistCorr, ///< using local dis/corr interpolator for calculation of global distortions/corrections + ElectricalField ///< using electric field for calculation of global distortions/corrections + }; + + /// step 0: set the charge density from TH3 histogram containing the space charge density + /// \param hisSCDensity3D histogram for the space charge density + void fillChargeDensityFromHisto(const TH3& hisSCDensity3D); + + /// step 0: set the charge density from TH3 histogram containing the space charge density + /// \param fInp input file containing a histogram for the space charge density + /// \param name the name of the space charge density histogram in the file + void fillChargeDensityFromFile(TFile& fInp, const char* name); + + /// \param side side of the TPC + /// \param globalDistType the algorithm which is used to calculate the global distortions + /// \param globalDistCorrMethod the setting if local distortions/corrections or the electrical field will be used for the calculation of the global distortions/corrections + void calculateDistortionsCorrections(const o2::tpc::Side side); + + /// step 0: this function fills the internal storage for the charge density using an analytical formula + /// \param formulaStruct struct containing a method to evaluate the density + void setChargeDensityFromFormula(const AnalyticalFields<DataT>& formulaStruct); + + /// step 0: this function fills the boundary of the potential using an analytical formula. The boundary is used in the PoissonSolver. + /// \param formulaStruct struct containing a method to evaluate the potential + void setPotentialBoundaryFromFormula(const AnalyticalFields<DataT>& formulaStruct); + + /// step 0: this function fills the potential using an analytical formula + /// \param formulaStruct struct containing a method to evaluate the potential + void setPotentialFromFormula(const AnalyticalFields<DataT>& formulaStruct); + + /// step 1: use the O2TPCPoissonSolver class to numerically calculate the potential with set space charge density and boundary conditions from potential + /// \param side side of the TPC + /// \param maxIteration maximum number of iterations used in the poisson solver + /// \param stoppingConvergence stopping criterion used in the poisson solver + /// \param symmetry use symmetry or not in the poisson solver + void poissonSolver(const Side side, const int maxIteration = 300, const DataT stoppingConvergence = 1e-6, const int symmetry = 0); + + /// step 2: calculate numerically the electric field from the potential + /// \param side side of the TPC + void calcEField(const Side side); + + /// step 2a: set the electric field from an analytical formula + /// \param formulaStruct struct containing a method to evaluate the electric fields + void setEFieldFromFormula(const AnalyticalFields<DataT>& formulaStruct); + + /// step 3: calculate the local distortions and corrections with an electric field + /// \param type calculate local corrections or local distortions: type = o2::tpc::SpaceCharge<>::Type::Distortions or o2::tpc::SpaceCharge<>::Type::Corrections + /// \param formulaStruct struct containing a method to evaluate the electric field Er, Ez, Ephi (analytical formula or by TriCubic interpolator) + template <typename ElectricFields = AnalyticalFields<DataT>> + void calcLocalDistortionsCorrections(const Type type, const ElectricFields& formulaStruct); + + /// step 4: calculate global corrections by using the electric field or the local corrections + /// \param formulaStruct struct containing a method to evaluate the electric field Er, Ez, Ephi or the local corrections + template <typename Fields = AnalyticalFields<DataT>> + void calcGlobalCorrections(const Fields& formulaStruct); + + /// step 5: calculate global distortions by using the electric field or the local distortions (SLOW) + /// \param formulaStruct struct containing a method to evaluate the electric field Er, Ez, Ephi or the local distortions + template <typename Fields = AnalyticalFields<DataT>> + void calcGlobalDistortions(const Fields& formulaStruct); + + void init(); + + /// step 5: calculate global distortions using the global corrections (FAST) + /// \param globCorr interpolator for global corrections + /// \param maxIter maximum iterations per global distortion + /// \param approachZ when the difference between the desired z coordinate and the position of the global correction is deltaZ, approach the desired z coordinate by deltaZ * \p approachZ. + /// \param approachR when the difference between the desired r coordinate and the position of the global correction is deltaR, approach the desired r coordinate by deltaR * \p approachR. + /// \param approachPhi when the difference between the desired phi coordinate and the position of the global correction is deltaPhi, approach the desired phi coordinate by deltaPhi * \p approachPhi. + /// \param diffCorr if the absolute differences from the interpolated values for the global corrections from the last iteration compared to the current iteration is smaller than this value, set converged to true for current global distortion + void calcGlobalDistWithGlobalCorrIterative(const DistCorrInterpolator<DataT, Nz, Nr, Nphi>& globCorr, const int maxIter = 100, const DataT approachZ = 0.5, const DataT approachR = 0.5, const DataT approachPhi = 0.5, const DataT diffCorr = 1e-6); + + /// get the global correction for given coordinate + /// \param z global z coordinate + /// \param r global r coordinate + /// \param phi global phi coordinate + DataT getChargeCyl(const DataT z, const DataT r, const DataT phi, const Side side) const; + + /// get the global correction for given coordinate + /// \param z global z coordinate + /// \param r global r coordinate + /// \param phi global phi coordinate + DataT getPotentialCyl(const DataT z, const DataT r, const DataT phi, const Side side) const; + + /// get the global correction for given coordinate + /// \param z global z coordinate + /// \param r global r coordinate + /// \param phi global phi coordinate + /// \param eZ returns correction in z direction + /// \param eR returns correction in r direction + /// \param ePhi returns correction in phi direction + void getElectricFieldsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& eZ, DataT& eR, DataT& ePhi) const; + + /// get the global correction for given coordinate + /// \param z global z coordinate + /// \param r global r coordinate + /// \param phi global phi coordinate + /// \param lcorrZ returns local correction in z direction + /// \param lcorrR returns local correction in r direction + /// \param lcorrRPhi returns local correction in rphi direction + void getLocalCorrectionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& lcorrZ, DataT& lcorrR, DataT& lcorrRPhi) const; + + /// get the global correction for given coordinate + /// \param z global z coordinate + /// \param r global r coordinate + /// \param phi global phi coordinate + /// \param corrZ returns correction in z direction + /// \param corrR returns correction in r direction + /// \param corrRPhi returns correction in rphi direction + void getCorrectionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& corrZ, DataT& corrR, DataT& corrRPhi) const; + + /// get the global corrections for given coordinate + /// \param x global x coordinate + /// \param y global y coordinate + /// \param z global z coordinate + /// \param corrX returns corrections in x direction + /// \param corrY returns corrections in y direction + /// \param corrZ returns corrections in z direction + void getCorrections(const DataT x, const DataT y, const DataT z, const Side side, DataT& corrX, DataT& corrY, DataT& corrZ) const; + + /// get the global distortions for given coordinate + /// \param z global z coordinate + /// \param r global r coordinate + /// \param phi global phi coordinate + /// \param ldistZ returns local distortion in z direction + /// \param ldistR returns local distortion in r direction + /// \param ldistRPhi returns local distortion in rphi direction + void getLocalDistortionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& ldistZ, DataT& ldistR, DataT& ldistRPhi) const; + + /// get the global distortions for given coordinate + /// \param z global z coordinate + /// \param r global r coordinate + /// \param phi global phi coordinate + /// \param distZ returns distortion in z direction + /// \param distR returns distortion in r direction + /// \param distRPhi returns distortion in rphi direction + void getDistortionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& distZ, DataT& distR, DataT& distRPhi) const; + + /// get the global distortions for given coordinate + /// \param x global x coordinate + /// \param y global y coordinate + /// \param z global z coordinate + /// \param distX returns distortion in x direction + /// \param distY returns distortion in y direction + /// \param distZ returns distortion in z direction + void getDistortions(const DataT x, const DataT y, const DataT z, const Side side, DataT& distX, DataT& distY, DataT& distZ) const; + + /// convert x and y coordinates from cartesian to the radius in polar coordinates + static DataT getRadiusFromCartesian(const DataT x, const DataT y) { return std::sqrt(x * x + y * y); } + + /// convert x and y coordinates from cartesian to phi in polar coordinates + static DataT getPhiFromCartesian(const DataT x, const DataT y) { return std::atan2(y, x); } + + /// convert radius and phi coordinates from polar coordinates to x cartesian coordinates + static DataT getXFromPolar(const DataT r, const DataT phi) { return r * std::cos(phi); } + + /// convert radius and phi coordinates from polar coordinates to y cartesian coordinate + static DataT getYFromPolar(const DataT r, const DataT phi) { return r * std::sin(phi); } + + /// Correct electron position using correction lookup tables + /// \param point 3D coordinates of the electron + void correctElectron(GlobalPosition3D& point); + + /// Distort electron position using distortion lookup tables + /// \param point 3D coordinates of the electron + void distortElectron(GlobalPosition3D& point) const; + + /// set the distortions directly from a look up table + /// \param distdZ distortions in z direction + /// \param distdR distortions in r direction + /// \param distdRPhi distortions in rphi direction + /// \param side side of the TPC + void setDistortionLookupTables(const DataContainer& distdZ, const DataContainer& distdR, const DataContainer& distdRPhi, const Side side); + + /// set the density, potential, electric fields, local distortions/corrections, global distortions/corrections from a file. Missing objects in the file are ignored. + /// \file file containing the stored values for the density, potential, electric fields, local distortions/corrections, global distortions/corrections + /// \param side side of the TPC + void setFromFile(TFile& file, const Side side); + + /// Get grid spacing in r direction + DataT getGridSpacingR(const Side side) const { return mGrid3D[side].getSpacingY(); } + + /// Get grid spacing in z direction + DataT getGridSpacingZ(const Side side) const { return mGrid3D[side].getSpacingX(); } + + /// Get grid spacing in phi direction + DataT getGridSpacingPhi(const Side side) const { return mGrid3D[side].getSpacingZ(); } + + /// Get constant electric field + static constexpr DataT getEzField(const Side side) { return getSign(side) * (TPCParameters<DataT>::cathodev - TPCParameters<DataT>::vg1t) / TPCParameters<DataT>::TPCZ0; } + + /// Get inner radius of tpc + DataT getRMin(const Side side) const { return mGrid3D[side].getGridMinY(); } + + /// Get min z position which is used during the calaculations + DataT getZMin(const Side side) const { return mGrid3D[side].getGridMinX(); } + + /// Get min phi + DataT getPhiMin(const Side side) const { return mGrid3D[side].getGridMinZ(); } + + /// Get max r + DataT getRMax(const Side side) const { return mGrid3D[side].getGridMaxY(); }; + + /// Get max z + DataT getZMax(const Side side) const { return mGrid3D[side].getGridMaxX(); } + + /// Get max phi + DataT getPhiMax(const Side side) const { return mGrid3D[side].getGridMaxZ(); } + + // get side of TPC for z coordinate TODO rewrite this + static Side getSide(const DataT z) { return ((z >= 0) ? Side::A : Side::C); } + + /// Get the grid object + const RegularGrid& getGrid3D(const Side side) const { return mGrid3D[side]; } + + /// Get struct containing interpolators for the electrical fields + /// \param side side of the TPC + NumericalFields<DataT, Nz, Nr, Nphi> getElectricFieldsInterpolator(const Side side) const; + + /// Get struct containing interpolators for local distortions dR, dZ, dPhi + /// \param side side of the TPC + DistCorrInterpolator<DataT, Nz, Nr, Nphi> getLocalDistInterpolator(const Side side) const; + + /// Get struct containing interpolators for local corrections dR, dZ, dPhi + /// \param side side of the TPC + DistCorrInterpolator<DataT, Nz, Nr, Nphi> getLocalCorrInterpolator(const Side side) const; + + /// Get struct containing interpolators for global distortions dR, dZ, dPhi + /// \param side side of the TPC + DistCorrInterpolator<DataT, Nz, Nr, Nphi> getGlobalDistInterpolator(const Side side) const; + + /// Get struct containing interpolators for global corrections dR, dZ, dPhi + /// \param side side of the TPC + DistCorrInterpolator<DataT, Nz, Nr, Nphi> getGlobalCorrInterpolator(const Side side) const; + + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + /// \return returns local distortion dR for given vertex + DataT getLocalDistR(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mLocalDistdR[side](iz, ir, iphi); } + + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + /// \return returns local distortion dZ for given vertex + DataT getLocalDistZ(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mLocalDistdZ[side](iz, ir, iphi); } + + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + /// \return returns local distortion dRPhi for given vertex + DataT getLocalDistRPhi(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mLocalDistdRPhi[side](iz, ir, iphi); } + + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + /// \return returns local correction dR for given vertex + DataT getLocalCorrR(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mLocalCorrdR[side](iz, ir, iphi); } + + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + /// \return returns local correction dZ for given vertex + DataT getLocalCorrZ(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mLocalCorrdZ[side](iz, ir, iphi); } + + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + /// \return returns local correction dRPhi for given vertex + DataT getLocalCorrRPhi(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mLocalCorrdRPhi[side](iz, ir, iphi); } + + /// Get global distortion dR for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getGlobalDistR(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mGlobalDistdR[side](iz, ir, iphi); } + + /// Get global distortion dZ for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getGlobalDistZ(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mGlobalDistdZ[side](iz, ir, iphi); } + + /// Get global distortion dRPhi for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getGlobalDistRPhi(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mGlobalDistdRPhi[side](iz, ir, iphi); } + + /// Get global correction dR for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getGlobalCorrR(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mGlobalCorrdR[side](iz, ir, iphi); } + + /// Get global correction dZ for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getGlobalCorrZ(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mGlobalCorrdZ[side](iz, ir, iphi); } + + /// Get global correction dRPhi for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getGlobalCorrRPhi(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mGlobalCorrdRPhi[side](iz, ir, iphi); } + + /// Get global electric Field Er for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getEr(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mElectricFieldEr[side](iz, ir, iphi); } + + /// Get global electric Field Ez for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getEz(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mElectricFieldEz[side](iz, ir, iphi); } + + /// Get global electric Field Ephi for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getEphi(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mElectricFieldEphi[side](iz, ir, iphi); } + + /// Get density for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getDensity(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mDensity[side](iz, ir, iphi); } + + /// Get potential for vertex + /// \param vertex in iz dimension + /// \param vertex in ir dimension + /// \param vertex in iphi dimension + /// \param side side of the TPC + DataT getPotential(const size_t iz, const size_t ir, const size_t iphi, const Side side) const { return mPotential[side](iz, ir, iphi); } + + /// Get the step width which is used for the calculation of the correction/distortions in units of the z-bin + static int getStepWidth() { return 1 / sSteps; } + + /// Get phi vertex position for index in phi direction + /// \param indexPhi index in phi direction + DataT getPhiVertex(const size_t indexPhi, const Side side) const { return mGrid3D[side].getZVertex(indexPhi); } + + /// Get r vertex position for index in r direction + /// \param indexR index in r direction + DataT getRVertex(const size_t indexR, const Side side) const { return mGrid3D[side].getYVertex(indexR); } + + /// Get z vertex position for index in z direction + /// \param indexZ index in z direction + DataT getZVertex(const size_t indexZ, const Side side) const { return mGrid3D[side].getXVertex(indexZ); } + + /// \param omegaTau \omega \tau value + /// \param t1 value for t1 see: ??? + /// \param t2 value for t2 see: ??? + void setOmegaTauT1T2(const DataT omegaTau, const DataT t1, const DataT t2) + { + const DataT wt0 = t2 * omegaTau; + mC0 = 1 / (1 + wt0 * wt0); + const DataT wt1 = t1 * omegaTau; + mC1 = wt1 / (1 + wt1 * wt1); + }; + + /// \param c0 coefficient C0 (compare Jim Thomas's notes for definitions) + /// \param c1 coefficient C1 (compare Jim Thomas's notes for definitions) + void setC0C1(const DataT c0, const DataT c1) + { + mC0 = c0; + mC1 = c1; + } + + /// set number of steps used for calculation of distortions/corrections per z bin + /// \param nSteps number of steps per z bin + static void setNStep(const int nSteps) { sSteps = nSteps; } + + static int getNStep() { return sSteps; } + + /// get the number of threads used for some of the calculations + static int getNThreads() { return sNThreads; } + + /// set the number of threads used for some of the calculations + static void setNThreads(const int nThreads) + { + sNThreads = nThreads; + o2::tpc::TriCubicInterpolator<DataT, Nz, Nr, Nphi>::setNThreads(nThreads); + } + + /// set which kind of numerical integration is used for calcution of the integrals int Er/Ez dz, int Ephi/Ez dz, int Ez dz + /// \param strategy numerical integration strategy. see enum IntegrationStrategy for the different types + static void setNumericalIntegrationStrategy(const IntegrationStrategy strategy) { sNumericalIntegrationStrategy = strategy; } + static IntegrationStrategy getNumericalIntegrationStrategy() { return sNumericalIntegrationStrategy; } + + static void setGlobalDistType(const GlobalDistType globalDistType) { sGlobalDistType = globalDistType; } + static GlobalDistType getGlobalDistType() { return sGlobalDistType; } + + static void setGlobalDistCorrMethod(const GlobalDistCorrMethod globalDistCorrMethod) { sGlobalDistCorrCalcMethod = globalDistCorrMethod; } + static GlobalDistCorrMethod getGlobalDistCorrMethod() { return sGlobalDistCorrCalcMethod; } + + static void setSimpsonNIteratives(const int nIter) { sSimpsonNIteratives = nIter; } + static int getSimpsonNIteratives() { return sSimpsonNIteratives; } + + /// Set the space-charge distortions model + /// \param distortionType distortion type (constant or realistic) + static void setSCDistortionType(SCDistortionType distortionType) { sSCDistortionType = distortionType; } + /// Get the space-charge distortions model + static SCDistortionType getSCDistortionType() { return sSCDistortionType; } + + void setUseInitialSCDensity(const bool useInitialSCDensity) { mUseInitialSCDensity = useInitialSCDensity; } + + /// write electric fields to root file + /// \param outf output file where the electrical fields will be written to + /// \side side of the TPC + int dumpElectricFields(TFile& outf, const Side side) const; + + /// set electric field from root file + /// \param inpf input file where the electrical fields are stored + /// \side side of the TPC + void setElectricFieldsFromFile(TFile& inpf, const Side side); + + /// write potential to root file + /// \param outf output file where the potential will be written to + /// \side side of the TPC + int dumpPotential(TFile& outf, const Side side) const { return mPotential[side].writeToFile(outf, Form("potential_side%s", getSideName(side).data())); } + + /// set potential from root file + /// \param inpf input file where the potential is stored + /// \side side of the TPC + void setPotentialFromFile(TFile& inpf, const Side side) { mPotential[side].initFromFile(inpf, Form("potential_side%s", getSideName(side).data())); } + + /// write potential to root file + /// \param outf output file where the charge density will be written to + /// \side side of the TPC + int dumpDensity(TFile& outf, const Side side) const { return mDensity[side].writeToFile(outf, Form("density_side%s", getSideName(side).data())); } + + /// set potential from root file + /// \param inpf input file where the charge density is stored + /// \side side of the TPC + void setDensityFromFile(TFile& inpf, const Side side) { mDensity[side].initFromFile(inpf, Form("density_side%s", getSideName(side).data())); } + + /// write global distortions to root file + /// \param outf output file where the global distortions will be written to + /// \side side of the TPC + int dumpGlobalDistortions(TFile& outf, const Side side) const; + + /// set global distortions from root file + /// \param inpf input file where the global distortions are stored + /// \side side of the TPC + void setGlobalDistortionsFromFile(TFile& inpf, const Side side); + + /// write global corrections to root file + /// \param outf output file where the global corrections will be written to + /// \side side of the TPC + int dumpGlobalCorrections(TFile& outf, const Side side) const; + + /// set global corrections from root file + /// \param inpf input file where the global corrections are stored + /// \side side of the TPC + void setGlobalCorrectionsFromFile(TFile& inpf, const Side side); + + /// write local corrections to root file + /// \param outf output file where the local corrections will be written to + /// \side side of the TPC + int dumpLocalCorrections(TFile& outf, const Side side) const; + + /// set local corrections from root file + /// \param inpf input file where the local corrections are stored + /// \side side of the TPC + void setLocalCorrectionsFromFile(TFile& inpf, const Side side); + + /// write local distortions to root file + /// \param outf output file where the local distortions will be written to + /// \side side of the TPC + int dumpLocalDistortions(TFile& outf, const Side side) const; + + /// set local distortions from root file + /// \param inpf input file where the local distortions are stored + /// \side side of the TPC + void setLocalDistortionsFromFile(TFile& inpf, const Side side); + + /// set z coordinate between min z max z + /// \param posZ z position which will be regulated if needed + DataT regulateZ(const DataT posZ, const Side side) const { return mGrid3D[side].clampToGrid(posZ, 0); } + + /// set r coordinate between 'RMIN - 4 * GRIDSPACINGR' and 'RMAX + 2 * GRIDSPACINGR'. the r coordinate is not clamped to RMIN and RMAX to ensure correct interpolation at the borders of the grid. + DataT regulateR(const DataT posR, const Side side) const; + + /// set phi coordinate between min phi max phi + DataT regulatePhi(const DataT posPhi, const Side side) const { return mGrid3D[side].clampToGridCircular(posPhi, 2); } + + private: + using ASolv = o2::tpc::PoissonSolver<DataT, Nz, Nr, Nphi>; + + inline static int sNThreads{omp_get_max_threads()}; ///< number of threads which are used during the calculations + + inline static IntegrationStrategy sNumericalIntegrationStrategy{IntegrationStrategy::SimpsonIterative}; ///< numerical integration strategy of integration of the E-Field: 0: trapezoidal, 1: Simpson, 2: Root (only for analytical formula case) + inline static int sSimpsonNIteratives{3}; ///< number of iterations which are performed in the iterative simpson calculation of distortions/corrections + inline static int sSteps{1}; ///< during the calculation of the corrections/distortions it is assumed that the electron drifts on a line from deltaZ = z0 -> z1. The value sets the deltaZ width: 1: deltaZ=zBin/1, 5: deltaZ=zBin/5 + inline static GlobalDistType sGlobalDistType{GlobalDistType::Fast}; ///< setting for global distortions: 0: standard method, 1: interpolation of global corrections + inline static GlobalDistCorrMethod sGlobalDistCorrCalcMethod{GlobalDistCorrMethod::LocalDistCorr}; ///< setting for global distortions/corrections: 0: using electric field, 1: using local dis/corr interpolator + inline static SCDistortionType sSCDistortionType{SCDistortionType::SCDistortionsConstant}; ///< Type of space-charge distortions + + DataT mC0 = 0; ///< coefficient C0 (compare Jim Thomas's notes for definitions) + DataT mC1 = 0; ///< coefficient C1 (compare Jim Thomas's notes for definitions) + + static constexpr int FNSIDES = SIDES; ///< number of sides of the TPC + bool mIsEfieldSet[FNSIDES]{}; ///< flag if E-fields are set + bool mIsLocalCorrSet[FNSIDES]{}; ///< flag if local corrections are set + bool mIsLocalDistSet[FNSIDES]{}; ///< flag if local distortions are set + bool mIsGlobalCorrSet[FNSIDES]{}; ///< flag if global corrections are set + bool mIsGlobalDistSet[FNSIDES]{}; ///< flag if global distortions are set + bool mIsChargeSet[FNSIDES]{}; ///< flag if the charge + + bool mUseInitialSCDensity{false}; ///< Flag for the use of an initial space-charge density at the beginning of the simulation + bool mInitLookUpTables{false}; ///< Flag to indicate if lookup tables have been calculated + + const RegularGrid mGrid3D[FNSIDES]{ + {GridProp::ZMIN, GridProp::RMIN, GridProp::PHIMIN, getSign(Side::A) * GridProp::GRIDSPACINGZ, GridProp::GRIDSPACINGR, GridProp::GRIDSPACINGPHI}, + {GridProp::ZMIN, GridProp::RMIN, GridProp::PHIMIN, getSign(Side::C) * GridProp::GRIDSPACINGZ, GridProp::GRIDSPACINGR, GridProp::GRIDSPACINGPHI}}; ///< grid properties + + DataContainer mLocalDistdR[FNSIDES]{}; ///< data storage for local distortions dR + DataContainer mLocalDistdZ[FNSIDES]{}; ///< data storage for local distortions dZ + DataContainer mLocalDistdRPhi[FNSIDES]{}; ///< data storage for local distortions dRPhi + + DataContainer mLocalCorrdR[FNSIDES]{}; ///< data storage for local corrections dR + DataContainer mLocalCorrdZ[FNSIDES]{}; ///< data storage for local corrections dZ + DataContainer mLocalCorrdRPhi[FNSIDES]{}; ///< data storage for local corrections dRPhi + + DataContainer mGlobalDistdR[FNSIDES]{}; ///< data storage for global distortions dR + DataContainer mGlobalDistdZ[FNSIDES]{}; ///< data storage for global distortions dZ + DataContainer mGlobalDistdRPhi[FNSIDES]{}; ///< data storage for global distortions dRPhi + + DataContainer mGlobalCorrdR[FNSIDES]{}; ///< data storage for global corrections dR + DataContainer mGlobalCorrdZ[FNSIDES]{}; ///< data storage for global corrections dZ + DataContainer mGlobalCorrdRPhi[FNSIDES]{}; ///< data storage for global corrections dRPhi + + DataContainer mDensity[FNSIDES]{}; ///< data storage for space charge density + DataContainer mPotential[FNSIDES]{}; ///< data storage for the potential + + DataContainer mElectricFieldEr[FNSIDES]{}; ///< data storage for the electric field Er + DataContainer mElectricFieldEz[FNSIDES]{}; ///< data storage for the electric field Ez + DataContainer mElectricFieldEphi[FNSIDES]{}; ///< data storage for the electric field Ephi + + TriCubic mInterpolatorPotential[FNSIDES]{ + {mPotential[Side::A], mGrid3D[Side::A]}, + {mPotential[Side::C], mGrid3D[Side::C]}}; ///< interpolator for the potenial + + TriCubic mInterpolatorDensity[FNSIDES]{ + {mDensity[Side::A], mGrid3D[Side::A]}, + {mDensity[Side::C], mGrid3D[Side::C]}}; ///< interpolator for the charge + + DistCorrInterpolator<DataT, Nz, Nr, Nphi> mInterpolatorGlobalCorr[FNSIDES]{ + {mGlobalCorrdR[Side::A], mGlobalCorrdZ[Side::A], mGlobalCorrdRPhi[Side::A], mGrid3D[Side::A], Side::A}, + {mGlobalCorrdR[Side::C], mGlobalCorrdZ[Side::C], mGlobalCorrdRPhi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the global corrections + + DistCorrInterpolator<DataT, Nz, Nr, Nphi> mInterpolatorLocalCorr[FNSIDES]{ + {mLocalCorrdR[Side::A], mLocalCorrdZ[Side::A], mLocalCorrdRPhi[Side::A], mGrid3D[Side::A], Side::A}, + {mLocalCorrdR[Side::C], mLocalCorrdZ[Side::C], mLocalCorrdRPhi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the local corrections + + DistCorrInterpolator<DataT, Nz, Nr, Nphi> mInterpolatorGlobalDist[FNSIDES]{ + {mGlobalDistdR[Side::A], mGlobalDistdZ[Side::A], mGlobalDistdRPhi[Side::A], mGrid3D[Side::A], Side::A}, + {mGlobalDistdR[Side::C], mGlobalDistdZ[Side::C], mGlobalDistdRPhi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the global distortions + + DistCorrInterpolator<DataT, Nz, Nr, Nphi> mInterpolatorLocalDist[FNSIDES]{ + {mLocalDistdR[Side::A], mLocalDistdZ[Side::A], mLocalDistdRPhi[Side::A], mGrid3D[Side::A], Side::A}, + {mLocalDistdR[Side::C], mLocalDistdZ[Side::C], mLocalDistdRPhi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the local distortions + + NumericalFields<DataT, Nz, Nr, Nphi> mInterpolatorEField[FNSIDES]{ + {mElectricFieldEr[Side::A], mElectricFieldEz[Side::A], mElectricFieldEphi[Side::A], mGrid3D[Side::A], Side::A}, + {mElectricFieldEr[Side::C], mElectricFieldEz[Side::C], mElectricFieldEphi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the electric fields + + /// rebin the input space charge density histogram to desired binning + /// \param hOrig original histogram + TH3D rebinDensityHisto(const TH3& hOrig) const; + + static int getSign(const Side side) + { + return side == Side::C ? -1 : 1; + } + + /// get inverse spacing in z direction + DataT getInvSpacingZ(const Side side) const { return mGrid3D[side].getInvSpacingX(); } + + /// get inverse spacing in r direction + DataT getInvSpacingR(const Side side) const { return mGrid3D[side].getInvSpacingY(); } + + /// get inverse spacing in phi direction + DataT getInvSpacingPhi(const Side side) const { return mGrid3D[side].getInvSpacingZ(); } + + std::string getSideName(const Side side) const { return side == Side::A ? "A" : "C"; } + + /// calculate distortions or corrections analytical with electric fields + template <typename Fields = AnalyticalFields<DataT>> + void calcDistCorr(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& ddR, DataT& ddPhi, DataT& ddZ, const Fields& formulaStruct, const bool localDistCorr) const; + + /// calculate distortions/corrections using the formulas proposed in https://edms.cern.ch/ui/file/1108138/1/ALICE-INT-2010-016.pdf page 7 + void langevinCylindrical(DataT& ddR, DataT& ddPhi, DataT& ddZ, const DataT radius, const DataT localIntErOverEz, const DataT localIntEPhiOverEz, const DataT localIntDeltaEz) const; + + /// integrate electrical fields using root integration method + template <typename Fields = AnalyticalFields<DataT>> + void integrateEFieldsRoot(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const; + + /// integrate electrical fields using trapezoidal integration method + template <typename Fields = AnalyticalFields<DataT>> + void integrateEFieldsTrapezoidal(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const; + + /// integrate electrical fields using simpson integration method + template <typename Fields = AnalyticalFields<DataT>> + void integrateEFieldsSimpson(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const; + + /// integrate electrical fields using simpson integration method with non straight drift of electrons + template <typename Fields = AnalyticalFields<DataT>> + void integrateEFieldsSimpsonIterative(const DataT p1r, const DataT p2r, const DataT p1phi, const DataT p2phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const; + + /// calculate distortions/corrections using analytical electric fields + void processGlobalDistCorr(const DataT radius, const DataT phi, const DataT z0Tmp, const DataT z1Tmp, DataT& ddR, DataT& ddPhi, DataT& ddZ, const AnalyticalFields<DataT>& formulaStruct) const + { + calcDistCorr(radius, phi, z0Tmp, z1Tmp, ddR, ddPhi, ddZ, formulaStruct, false); + } + + /// calculate distortions/corrections using electric fields from tricubic interpolator + void processGlobalDistCorr(const DataT radius, const DataT phi, const DataT z0Tmp, const DataT z1Tmp, DataT& ddR, DataT& ddPhi, DataT& ddZ, const NumericalFields<DataT, Nz, Nr, Nphi>& formulaStruct) const + { + calcDistCorr(radius, phi, z0Tmp, z1Tmp, ddR, ddPhi, ddZ, formulaStruct, false); + } + + /// calculate distortions/corrections by interpolation of local distortions/corrections + void processGlobalDistCorr(const DataT radius, const DataT phi, const DataT z0Tmp, [[maybe_unused]] const DataT z1Tmp, DataT& ddR, DataT& ddPhi, DataT& ddZ, const DistCorrInterpolator<DataT, Nz, Nr, Nphi>& localDistCorr) const + { + ddR = localDistCorr.evaldR(z0Tmp, radius, phi); + ddZ = localDistCorr.evaldZ(z0Tmp, radius, phi); + ddPhi = localDistCorr.evaldRPhi(z0Tmp, radius, phi) / radius; + } +}; + +/// +/// ======================================================================================================== +/// Inline implementations of some methods +/// ======================================================================================================== +/// + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename Fields> +void SpaceCharge<DataT, Nz, Nr, Nphi>::integrateEFieldsRoot(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const +{ + const DataT ezField = getEzField(formulaStruct.getSide()); + TF1 fErOverEz( + "fErOverEz", [&](double* x, double* p) { (void)p; return static_cast<double>(formulaStruct.evalEr(static_cast<DataT>(x[0]), p1r, p1phi) / (formulaStruct.evalEz(static_cast<DataT>(x[0]), p1r, p1phi) + ezField)); }, p1z, p2z, 1); + localIntErOverEz = static_cast<DataT>(fErOverEz.Integral(p1z, p2z)); + + TF1 fEphiOverEz( + "fEPhiOverEz", [&](double* x, double* p) { (void)p; return static_cast<double>(formulaStruct.evalEphi(static_cast<DataT>(x[0]), p1r, p1phi) / (formulaStruct.evalEz(static_cast<DataT>(x[0]), p1r, p1phi) + ezField)); }, p1z, p2z, 1); + localIntEPhiOverEz = static_cast<DataT>(fEphiOverEz.Integral(p1z, p2z)); + + TF1 fEz( + "fEZOverEz", [&](double* x, double* p) { (void)p; return static_cast<double>(formulaStruct.evalEz(static_cast<DataT>(x[0]), p1r, p1phi) - ezField); }, p1z, p2z, 1); + localIntDeltaEz = getSign(formulaStruct.getSide()) * static_cast<DataT>(fEz.Integral(p1z, p2z)); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename Fields> +void SpaceCharge<DataT, Nz, Nr, Nphi>::integrateEFieldsTrapezoidal(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const +{ + //========trapezoidal rule see: https://en.wikipedia.org/wiki/Trapezoidal_rule ============== + const DataT fielder0 = formulaStruct.evalEr(p1z, p1r, p1phi); + const DataT fieldez0 = formulaStruct.evalEz(p1z, p1r, p1phi); + const DataT fieldephi0 = formulaStruct.evalEphi(p1z, p1r, p1phi); + + const DataT fielder1 = formulaStruct.evalEr(p2z, p1r, p1phi); + const DataT fieldez1 = formulaStruct.evalEz(p2z, p1r, p1phi); + const DataT fieldephi1 = formulaStruct.evalEphi(p2z, p1r, p1phi); + + const DataT ezField = getEzField(formulaStruct.getSide()); + const DataT eZ0 = 1. / (ezField + fieldez0); + const DataT eZ1 = 1. / (ezField + fieldez1); + + const DataT deltaX = 0.5 * (p2z - p1z); + localIntErOverEz = deltaX * (fielder0 * eZ0 + fielder1 * eZ1); + localIntEPhiOverEz = deltaX * (fieldephi0 * eZ0 + fieldephi1 * eZ1); + localIntDeltaEz = getSign(formulaStruct.getSide()) * deltaX * (fieldez0 + fieldez1); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename Fields> +void SpaceCharge<DataT, Nz, Nr, Nphi>::integrateEFieldsSimpson(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const +{ + //==========simpsons rule see: https://en.wikipedia.org/wiki/Simpson%27s_rule ============================= + const DataT fielder0 = formulaStruct.evalEr(p1z, p1r, p1phi); + const DataT fieldez0 = formulaStruct.evalEz(p1z, p1r, p1phi); + const DataT fieldephi0 = formulaStruct.evalEphi(p1z, p1r, p1phi); + + const DataT fielder1 = formulaStruct.evalEr(p2z, p1r, p1phi); + const DataT fieldez1 = formulaStruct.evalEz(p2z, p1r, p1phi); + const DataT fieldephi1 = formulaStruct.evalEphi(p2z, p1r, p1phi); + + const DataT deltaX = p2z - p1z; + const DataT ezField = getEzField(formulaStruct.getSide()); + const DataT xk2N = (p2z - static_cast<DataT>(0.5) * deltaX); + const DataT ezField2 = formulaStruct.evalEz(xk2N, p1r, p1phi); + const DataT ezField2Denominator = 1. / (ezField + ezField2); + const DataT fieldSum2ErOverEz = formulaStruct.evalEr(xk2N, p1r, p1phi) * ezField2Denominator; + const DataT fieldSum2EphiOverEz = formulaStruct.evalEphi(xk2N, p1r, p1phi) * ezField2Denominator; + + const DataT eZ0 = 1. / (ezField + fieldez0); + const DataT eZ1 = 1. / (ezField + fieldez1); + + const DataT deltaXSimpsonSixth = deltaX / 6.; + localIntErOverEz = deltaXSimpsonSixth * (4. * fieldSum2ErOverEz + fielder0 * eZ0 + fielder1 * eZ1); + localIntEPhiOverEz = deltaXSimpsonSixth * (4. * fieldSum2EphiOverEz + fieldephi0 * eZ0 + fieldephi1 * eZ1); + localIntDeltaEz = getSign(formulaStruct.getSide()) * deltaXSimpsonSixth * (4. * ezField2 + fieldez0 + fieldez1); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename Fields> +void SpaceCharge<DataT, Nz, Nr, Nphi>::integrateEFieldsSimpsonIterative(const DataT p1r, const DataT p2r, const DataT p1phi, const DataT p2phi, const DataT p1z, const DataT p2z, DataT& localIntErOverEz, DataT& localIntEPhiOverEz, DataT& localIntDeltaEz, const Fields& formulaStruct) const +{ + //==========simpsons rule see: https://en.wikipedia.org/wiki/Simpson%27s_rule ============================= + const Side side = formulaStruct.getSide(); + const DataT ezField = getEzField(side); + const DataT p2phiSave = regulatePhi(p2phi, side); + + const DataT fielder0 = formulaStruct.evalEr(p1z, p1r, p1phi); + const DataT fieldez0 = formulaStruct.evalEz(p1z, p1r, p1phi); + const DataT fieldephi0 = formulaStruct.evalEphi(p1z, p1r, p1phi); + + const DataT fielder1 = formulaStruct.evalEr(p2z, p2r, p2phiSave); + const DataT fieldez1 = formulaStruct.evalEz(p2z, p2r, p2phiSave); + const DataT fieldephi1 = formulaStruct.evalEphi(p2z, p2r, p2phiSave); + + const DataT eZ0Inv = 1. / (ezField + fieldez0); + const DataT eZ1Inv = 1. / (ezField + fieldez1); + + const DataT pHalfZ = 0.5 * (p1z + p2z); // dont needs to be regulated since p1z and p2z are already regulated + const DataT pHalfPhiSave = regulatePhi(0.5 * (p1phi + p2phi), side); // needs to be regulated since p2phi is not regulated + const DataT pHalfR = 0.5 * (p1r + p2r); + + const DataT ezField2 = formulaStruct.evalEz(pHalfZ, pHalfR, pHalfPhiSave); + const DataT eZHalfInv = 1. / (ezField + ezField2); + const DataT fieldSum2ErOverEz = formulaStruct.evalEr(pHalfZ, pHalfR, pHalfPhiSave); + const DataT fieldSum2EphiOverEz = formulaStruct.evalEphi(pHalfZ, pHalfR, pHalfPhiSave); + + const DataT deltaXSimpsonSixth = (p2z - p1z) / 6; + localIntErOverEz = deltaXSimpsonSixth * (4 * fieldSum2ErOverEz * eZHalfInv + fielder0 * eZ0Inv + fielder1 * eZ1Inv); + localIntEPhiOverEz = deltaXSimpsonSixth * (4 * fieldSum2EphiOverEz * eZHalfInv + fieldephi0 * eZ0Inv + fieldephi1 * eZ1Inv); + localIntDeltaEz = getSign(side) * deltaXSimpsonSixth * (4 * ezField2 + fieldez0 + fieldez1); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename Fields> +void SpaceCharge<DataT, Nz, Nr, Nphi>::calcDistCorr(const DataT p1r, const DataT p1phi, const DataT p1z, const DataT p2z, DataT& ddR, DataT& ddPhi, DataT& ddZ, const Fields& formulaStruct, const bool localDistCorr) const +{ + // see: https://edms.cern.ch/ui/file/1108138/1/ALICE-INT-2010-016.pdf + // needed for calculation of distortions/corrections + DataT localIntErOverEz = 0; // integral_p1z^p2z Er/Ez dz + DataT localIntEPhiOverEz = 0; // integral_p1z^p2z Ephi/Ez dz + DataT localIntDeltaEz = 0; // integral_p1z^p2z Ez dz + + // there are differentnumerical integration strategys implements. for details see each function. + switch (sNumericalIntegrationStrategy) { + case IntegrationStrategy::SimpsonIterative: // iterative simpson integration (should be more precise at least for the analytical E-Field case but takes alot more time than normal simpson integration) + for (int i = 0; i < sSimpsonNIteratives; ++i) { // TODO define a convergence criterion to abort the algorithm earlier for speed up. + const DataT tmpZ = localDistCorr ? (p2z + ddZ) : regulateZ(p2z + ddZ, formulaStruct.getSide()); // dont regulate for local distortions/corrections! (to get same result as using electric field at last/first bin) + integrateEFieldsSimpsonIterative(p1r, p1r + ddR, p1phi, p1phi + ddPhi, p1z, tmpZ, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz, formulaStruct); + langevinCylindrical(ddR, ddPhi, ddZ, (p1r + 0.5 * ddR), localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz); // using the mean radius '(p1r + 0.5 * ddR)' for calculation of distortions/corections + } + break; + case IntegrationStrategy::Simpson: // simpson integration + integrateEFieldsSimpson(p1r, p1phi, p1z, p2z, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz, formulaStruct); + langevinCylindrical(ddR, ddPhi, ddZ, p1r, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz); + break; + case IntegrationStrategy::Trapezoidal: // trapezoidal integration (fastest) + integrateEFieldsTrapezoidal(p1r, p1phi, p1z, p2z, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz, formulaStruct); + langevinCylindrical(ddR, ddPhi, ddZ, p1r, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz); + break; + case IntegrationStrategy::Root: // using integration implemented in ROOT (slow) + integrateEFieldsRoot(p1r, p1phi, p1z, p2z, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz, formulaStruct); + langevinCylindrical(ddR, ddPhi, ddZ, p1r, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz); + break; + default: + LOGP(INFO, "no matching case: Using Simpson"); + integrateEFieldsSimpson(p1r, p1phi, p1z, p2z, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz, formulaStruct); + langevinCylindrical(ddR, ddPhi, ddZ, p1r, localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz); + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::langevinCylindrical(DataT& ddR, DataT& ddPhi, DataT& ddZ, const DataT radius, const DataT localIntErOverEz, const DataT localIntEPhiOverEz, const DataT localIntDeltaEz) const +{ + // calculated distortions/correction with the formula described in https://edms.cern.ch/ui/file/1108138/1/ALICE-INT-2010-016.pdf page 7. + ddR = mC0 * localIntErOverEz + mC1 * localIntEPhiOverEz; + ddPhi = (mC0 * localIntEPhiOverEz - mC1 * localIntErOverEz) / radius; + ddZ = -localIntDeltaEz * TPCParameters<DataT>::DVDE; +} + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceChargeHelpers.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceChargeHelpers.h new file mode 100644 index 0000000000000..6316fd524c283 --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceChargeHelpers.h @@ -0,0 +1,269 @@ +// 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 SpaceChargeHelpers.h +/// \brief This file provides all necesseray classes which are used during the calcution of the distortions and corrections +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Aug 21, 2020 + +#ifndef ALICEO2_TPC_SPACECHARGEHELPERS_H_ +#define ALICEO2_TPC_SPACECHARGEHELPERS_H_ + +#include <functional> +#include <cmath> +#include "TPCSpaceCharge/TriCubic.h" +#include "DataFormatsTPC/Defs.h" + +namespace o2 +{ +namespace tpc +{ + +/// +/// this class contains an analytical description of the space charge, potential and the electric fields. +/// The analytical functions can be used to test the poisson solver and the caluclation of distortions/corrections. +/// +template <typename DataT = double> +class AnalyticalFields +{ + public: + AnalyticalFields(const o2::tpc::Side side = o2::tpc::Side::A) : mSide{side} {}; + + o2::tpc::Side getSide() const { return mSide; } + + void setSide(const o2::tpc::Side side) { mSide = side; } + + /// sets the parameters + void setParameters(const DataT parA, const DataT parB, const DataT parC) + { + mParA = parA; + mParB = parB; + mParC = parC; + } + + /// return parameter A + DataT getParA() const { return mParA; } + + /// return parameter B + DataT getParB() const { return mParB; } + + /// return parameter C + DataT getParC() const { return mParC; } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for electric field Er for given coordinate + DataT evalEr(DataT z, DataT r, DataT phi) const { return mErFunc(z, r, phi); } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for electric field Ez for given coordinate + DataT evalEz(DataT z, DataT r, DataT phi) const { return mEzFunc(z, r, phi); } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for electric field Ephi for given coordinate + DataT evalEphi(DataT z, DataT r, DataT phi) const { return mEphiFunc(z, r, phi); } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for the potential for given coordinate + DataT evalPotential(DataT z, DataT r, DataT phi) const { return mPotentialFunc(z, r, phi); } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for the space charge density for given coordinate + DataT evalDensity(DataT z, DataT r, DataT phi) const { return mDensityFunc(z, r, phi); } + + /// analytical potential + std::function<DataT(DataT, DataT, DataT)> mPotentialFunc = [& mParA = mParA, &mParB = mParB, &mParC = mParC](const DataT z, const DataT r, const DataT phi) { + const DataT zz = std::abs(z); + return -mParA * (std::pow((-r + 254.5 + 83.5), 4) - 338.0 * std::pow((-r + 254.5 + 83.5), 3) + 21250.75 * std::pow((-r + 254.5 + 83.5), 2)) * std::cos(mParB * phi) * std::cos(mParB * phi) * std::exp(-1 * mParC * (zz - 125) * (zz - 125)); + }; + + /// analytical space charge - NOTE: if the space charge density is calculated analytical there would be a - sign in the formula (-mParA) - however since its an e- the sign is flipped (IS THIS CORRECT??? see for minus sign: AliTPCSpaceCharge3DCalc::SetPotentialBoundaryAndChargeFormula)- + std::function<DataT(DataT, DataT, DataT)> mDensityFunc = [& mParA = mParA, &mParB = mParB, &mParC = mParC](const DataT z, const DataT r, const DataT phi) { + const DataT zz = std::abs(z); + return mParA * ((1 / r * 16 * (-3311250 + 90995.5 * r - 570.375 * r * r + r * r * r)) * std::cos(mParB * phi) * std::cos(mParB * phi) * std::exp(-1 * mParC * (zz - 125) * (zz - 125)) + + (std::pow(-r + 254.5 + 83.5, 4) - 338.0 * std::pow(-r + 254.5 + 83.5, 3) + 21250.75 * std::pow(-r + 254.5 + 83.5, 2)) / (r * r) * std::exp(-1 * mParC * (zz - 125) * (zz - 125)) * -2 * mParB * mParB * std::cos(2 * mParB * phi) + + (std::pow(-r + 254.5 + 83.5, 4) - 338.0 * std::pow(-r + 254.5 + 83.5, 3) + 21250.75 * std::pow(-r + 254.5 + 83.5, 2)) * std::cos(mParB * phi) * std::cos(mParB * phi) * 2 * mParC * std::exp(-1 * mParC * (zz - 125) * (zz - 125)) * (2 * mParC * (zz - 125) * (zz - 125) - 1)); + }; + + /// analytical electric field Er + std::function<DataT(DataT, DataT, DataT)> mErFunc = [& mParA = mParA, &mParB = mParB, &mParC = mParC](const DataT z, const DataT r, const DataT phi) { + const DataT zz = std::abs(z); + return mParA * 4 * (r * r * r - 760.5 * r * r + 181991 * r - 1.3245 * std::pow(10, 7)) * std::cos(mParB * phi) * std::cos(mParB * phi) * std::exp(-1 * mParC * (zz - 125) * (zz - 125)); + }; + + /// analytical electric field Ephi + std::function<DataT(DataT, DataT, DataT)> mEphiFunc = [& mParA = mParA, &mParB = mParB, &mParC = mParC](const DataT z, const DataT r, const DataT phi) { + const DataT zz = std::abs(z); + return mParA * (std::pow(-r + 254.5 + 83.5, 4) - 338.0 * std::pow(-r + 254.5 + 83.5, 3) + 21250.75 * (-r + 254.5 + 83.5) * (-r + 254.5 + 83.5)) / r * std::exp(-1 * mParC * (zz - 125) * (zz - 125)) * -mParB * std::sin(2 * mParB * phi); + }; + + /// analytical electric field Ez + std::function<DataT(DataT, DataT, DataT)> mEzFunc = [& mParA = mParA, &mParB = mParB, &mParC = mParC](const DataT z, const DataT r, const DataT phi) { + const DataT zz = std::abs(z); + return mParA * (std::pow(-r + 254.5 + 83.5, 4) - 338.0 * std::pow(-r + 254.5 + 83.5, 3) + 21250.75 * (-r + 254.5 + 83.5) * (-r + 254.5 + 83.5)) * std::cos(mParB * phi) * std::cos(mParB * phi) * -2 * mParC * (zz - 125) * std::exp(-1 * mParC * (zz - 125) * (zz - 125)); + }; + + static constexpr unsigned int getID() { return ID; } + + private: + static constexpr unsigned int ID = 0; ///< needed to distinguish between the differrent classes + DataT mParA{1e-5}; ///< parameter [0] of functions + DataT mParB{0.5}; ///< parameter [1] of functions + DataT mParC{1e-4}; ///< parameter [2] of functions + o2::tpc::Side mSide{o2::tpc::Side::A}; ///< side of the TPC. Since the absolute value is taken during the calculations the choice of the side is arbitrary. +}; + +/// +/// This class gives tricubic interpolation of the electric fields and can be used to calculate the distortions/corrections. +/// The electric fields have to be calculated by the poisson solver or given by the analytical formula. +/// +template <typename DataT = double, size_t Nr = 129, size_t Nz = 129, size_t Nphi = 180> +class NumericalFields +{ + using RegularGrid = o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>; + using DataContainer = o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>; + using TriCubic = o2::tpc::TriCubicInterpolator<DataT, Nz, Nr, Nphi>; + + public: + /// constructor + /// \param dataEr container for the data of the electrical field Er + /// \param dataEz container for the data of the electrical field Ez + /// \param dataEphi container for the data of the electrical field Ephi + /// \param gridProperties properties of the grid + /// \param side side of the tpc + NumericalFields(const DataContainer& dataEr, const DataContainer& dataEz, const DataContainer& dataEphi, const RegularGrid& gridProperties, const o2::tpc::Side side) : mDataEr{dataEr}, mDataEz{dataEz}, mDataEphi{dataEphi}, mGridProperties{gridProperties}, mSide{side} {}; + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for electric field Er for given coordinate + DataT evalEr(DataT z, DataT r, DataT phi) const { return mInterpolatorEr(z, r, phi, mInterpolType); } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for electric field Ez for given coordinate + DataT evalEz(DataT z, DataT r, DataT phi) const { return mInterpolatorEz(z, r, phi, mInterpolType); } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for electric field Ephi for given coordinate + DataT evalEphi(DataT z, DataT r, DataT phi) const { return mInterpolatorEphi(z, r, phi, mInterpolType); } + + o2::tpc::Side getSide() const { return mSide; } + + static constexpr unsigned int getID() { return ID; } + + /// set which kind of TriCubic interpolation algorithm is used + void setInterpolationType(const typename TriCubic::InterpolationType type) { mInterpolType = type; } + + // \return returns which kind of TriCubic interpolation algorithm is used + typename TriCubic::InterpolationType getInterpolationType() const { return mInterpolType; } + + private: + const DataContainer& mDataEr{}; ///< adress to the data container of the grid + const DataContainer& mDataEz{}; ///< adress to the data container of the grid + const DataContainer& mDataEphi{}; ///< adress to the data container of the grid + const RegularGrid& mGridProperties{}; ///< properties of the regular grid + const o2::tpc::Side mSide{}; ///< side of the TPC + + TriCubic mInterpolatorEr{mDataEr, mGridProperties}; ///< TriCubic interpolator of the electric field Er + TriCubic mInterpolatorEz{mDataEz, mGridProperties}; ///< TriCubic interpolator of the electric field Ez + TriCubic mInterpolatorEphi{mDataEphi, mGridProperties}; ///< TriCubic interpolator of the electric field Ephi + typename TriCubic::InterpolationType mInterpolType = TriCubic::InterpolationType::Sparse; ///< type of TriCubic interpolation + static constexpr unsigned int ID = 1; ///< needed to distinguish between the different classes +}; + +/// +/// This class gives tricubic interpolation of the local distortions or corrections. +/// The the local distortions or corrections can be used to calculate the global distortions/corrections. +/// +template <typename DataT = double, size_t Nr = 129, size_t Nz = 129, size_t Nphi = 180> +class DistCorrInterpolator +{ + using RegularGrid = o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>; + using DataContainer = o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>; + using TriCubic = o2::tpc::TriCubicInterpolator<DataT, Nz, Nr, Nphi>; + + public: + /// constructor + /// \param dataDistCorrdR container for the data of the distortions dR + /// \param dataDistCorrdZ container for the data of the distortions dZ + /// \param dataDistCorrdRPhi container for the data of the distortions dPhi + /// \param gridProperties properties of the grid + /// \param side side of the tpc + DistCorrInterpolator(const DataContainer& dataDistCorrdR, const DataContainer& dataDistCorrdZ, const DataContainer& dataDistCorrdRPhi, const RegularGrid& gridProperties, const o2::tpc::Side side) : mDataDistCorrdR{dataDistCorrdR}, mDataDistCorrdZ{dataDistCorrdZ}, mDataDistCorrdRPhi{dataDistCorrdRPhi}, mGridProperties{gridProperties}, mSide{side} {}; + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for the local distortion or correction dR for given coordinate + DataT evaldR(const DataT z, const DataT r, const DataT phi) const + { + return interpolatorDistCorrdR(z, r, phi, mInterpolType); + } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for the local distortion or correction dZ for given coordinate + DataT evaldZ(const DataT z, const DataT r, const DataT phi) const + { + return interpolatorDistCorrdZ(z, r, phi, mInterpolType); + } + + /// \param r r coordinate + /// \param phi phi coordinate + /// \param z z coordinate + /// \return returns the function value for the local distortion or correction dRPhi for given coordinate + DataT evaldRPhi(const DataT z, const DataT r, const DataT phi) const + { + return interpolatorDistCorrdRPhi(z, r, phi, mInterpolType); + } + + o2::tpc::Side getSide() const { return mSide; } + + static constexpr unsigned int getID() { return ID; } + + /// set which kind of TriCubic interpolation algorithm is used + void setInterpolationType(const typename TriCubic::InterpolationType type) { mInterpolType = type; } + + /// \return returns which kind of TriCubic interpolation algorithm is used + typename TriCubic::InterpolationType getInterpolationType() const { return mInterpolType; } + + private: + const DataContainer& mDataDistCorrdR{}; ///< adress to the data container of the grid + const DataContainer& mDataDistCorrdZ{}; ///< adress to the data container of the grid + const DataContainer& mDataDistCorrdRPhi{}; ///< adress to the data container of the grid + const RegularGrid& mGridProperties{}; ///< properties of the regular grid + const o2::tpc::Side mSide{}; ///< side of the TPC. + + TriCubic interpolatorDistCorrdR{mDataDistCorrdR, mGridProperties}; ///< TriCubic interpolator of distortion or correction dR + TriCubic interpolatorDistCorrdZ{mDataDistCorrdZ, mGridProperties}; ///< TriCubic interpolator of distortion or correction dZ + TriCubic interpolatorDistCorrdRPhi{mDataDistCorrdRPhi, mGridProperties}; ///< TriCubic interpolator of distortion or correction dRPhi + typename TriCubic::InterpolationType mInterpolType = TriCubic::InterpolationType::Sparse; ///< type of TriCubic interpolation + static constexpr unsigned int ID = 2; ///< needed to distinguish between the different classes +}; + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/TriCubic.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/TriCubic.h new file mode 100644 index 0000000000000..6cef68f2a1b55 --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/TriCubic.h @@ -0,0 +1,1592 @@ +// 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 TriCubic.h +/// \brief Definition of TriCubic class +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> + +#ifndef ALICEO2_TPC_TRICUBIC_H_ +#define ALICEO2_TPC_TRICUBIC_H_ + +#include "TPCSpaceCharge/Vector.h" +#include "TPCSpaceCharge/RegularGrid3D.h" +#include "TPCSpaceCharge/DataContainer3D.h" + +#if (defined(WITH_OPENMP) || defined(_OPENMP)) && !defined(__CLING__) +#include <omp.h> +#else +static inline int omp_get_thread_num() { return 0; } +static inline int omp_get_max_threads() { return 1; } +#endif + +namespace o2 +{ +namespace tpc +{ + +/// \class TriCubicInterpolator +/// The TriCubic class represents tricubic interpolation on a regular 3-Dim grid. +/// The algorithm which is used is based on the method developed by F. Lekien and J. Marsden and is described +/// in 'Tricubic Interpolation in Three Dimensions (2005)' http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.7835 +/// In this method in a first step 64 coefficients are computed by using a predefined 64*64 matrix. +/// These coefficients have to be computed for each cell in the grid, but are only computed when querying a point in a given cell. +/// The calculated coefficient is then stored for only the last cell and will be reused if the next query point lies in the same cell. +/// +/// Additionally the classical one dimensional approach of interpolating values is implemented. This algorithm is faster when interpolating only a few values inside each cube. +/// +/// periodic boundary conditions are used in phi direction. + +/// void test() +/// { +/// // define the grid: +/// // define number of vertices per dimension +/// const int zvertices = 40; +/// const int rvertices = 40; +/// const int phivertices = 40; +/// +/// // define min range +/// float zmin = 0; +/// float rmin = 0; +/// float phimin = 0; +/// +/// // define spacing between grid vertices +/// float zSpacing = 0.25; +/// float rSpacing = 0.25; +/// float phiSpacing = 2 * M_PI / phivertices; +/// +/// // create grid and datacontainer object +/// o2::tpc::RegularGrid3D<float, zvertices, rvertices, phivertices> grid3D(zmin, rmin, phimin, zSpacing, rSpacing, phiSpacing); +/// o2::tpc::DataContainer3D<float, zvertices, rvertices, phivertices> data3D; +/// +/// // fill the DataContainer3D with some values +/// for (int iz = 0; iz < zvertices; ++iz) { +/// for (int ir = 0; ir < rvertices; ++ir) { +/// for (int iphi = 0; iphi < phivertices; ++iphi) { +/// const float izPos = zSpacing * iz + zmin; +/// const float irPos = rSpacing * ir + rmin; +/// const float iphiPos = phiSpacing * iphi + phimin; +/// data3D(iz, ir, iphi) = std::sin(irPos * izPos / 10.) + std::cos(iphiPos); // some arbitrary function is used here +/// } +/// } +/// } +/// +/// // create tricubic interpolator +/// o2::tpc::TriCubicInterpolator<float, zvertices, rvertices, phivertices> interpolator(data3D, grid3D); +/// +/// // query some values +/// for (float iz = grid3D.getGridMinX(); iz < grid3D.getGridMaxX(); iz += zSpacing / 3.) { +/// for (float ir = grid3D.getGridMinY(); ir < grid3D.getGridMaxY(); ir += rSpacing / 3.) { +/// for (float iphi = grid3D.getGridMinZ() - 2 * phiSpacing; iphi < grid3D.getGridMaxZ() + 2 * phiSpacing; iphi += phiSpacing / 3.) { +/// const float zQuery = iz; +/// const float rQuery = ir; +/// const float phiQuery = iphi; +/// +/// const float interpolatedSparse = interpolator(zQuery, rQuery, phiQuery, o2::tpc::TriCubicInterpolator<float, zvertices, rvertices, phivertices>::InterpolationType::Sparse); +/// const float interpolatedDense = interpolator(zQuery, rQuery, phiQuery, o2::tpc::TriCubicInterpolator<float, zvertices, rvertices, phivertices>::InterpolationType::Dense); +/// const float trueValue = std::sin(rQuery * zQuery / 10.) + std::cos(phiQuery); +/// const float interpolatedDerivative = interpolator(zQuery, rQuery, phiQuery, 1, 1, 0); +/// const float trueDerivative = 1 / 10. * std::cos(rQuery * zQuery / 10.) - rQuery / 10. * std::sin(rQuery * zQuery / 10.) * zQuery / 10.; +/// } +/// } +/// } +/// } + +/// \tparam DataT the type of data which is used during the calculations +/// \tparam Nz number of vertices in r direction +/// \tparam Nr number of vertices in phi direction +/// \tparam Nphi number of vertices in phi direction +template <typename DataT = double, size_t Nz = 129, size_t Nr = 129, size_t Nphi = 180> +class TriCubicInterpolator +{ + using Grid3D = RegularGrid3D<DataT, Nz, Nr, Nphi>; + using DataContainer = DataContainer3D<DataT, Nz, Nr, Nphi>; + using VDataT = Vc::Vector<DataT>; + + public: + /// Constructor for a tricubic interpolator + /// \param gridData struct containing access to the values of the grid + /// \param gridProperties properties of the 3D grid + TriCubicInterpolator(const DataContainer& gridData, const Grid3D& gridProperties) : mGridData{gridData}, mGridProperties{gridProperties} {}; + + enum class ExtrapolationType { + Linear = 0, ///< assume linear dependency at the boundaries of the grid + Parabola = 1, ///< assume parabolic dependency at the boundaries of the grid + }; + + enum class InterpolationType { + Sparse = 0, ///< using one dimensional method of interpolation (fast when interpolating only a few values in one cube in the grid) + Dense = 1, ///< using three dimensional method of interpolation (fast when interpolating a lot values in one cube in the grid) + }; + + // interpolate value at given coordinate + /// \param z z coordinate + /// \param r r coordinate + /// \param phi phi coordinate + /// \param type interpolation algorithm + /// \return returns the interpolated value at given coordinate + DataT operator()(const DataT z, const DataT r, const DataT phi, const InterpolationType type = InterpolationType::Sparse) const + { + if (type == InterpolationType::Sparse) { + return interpolateSparse(z, r, phi); + } else { + const Vector<DataT, FDim> coordinates{{z, r, phi}}; // vector holding the coordinates + const auto relPos = processInp(coordinates, false); // vector containing the relative position to + return interpolateDense(relPos); + } + } + + /// interpolate derivative at given coordinate + /// \param z z coordinate + /// \param r r coordinate + /// \param phi phi coordinate + /// \param derz order of derivative d/dz: derz=1 -> d/dz f(z,r,phi), derz=2 -> d^2/dz^2 f(z,r,phi), derz=3 -> d^3/dz^3 f(z,r,phi) + /// \param derphi order of derivative d/dr: derr=1 -> d/dr f(z,r,phi), derr=2 -> d^2/dr^2 f(z,r,phi), derr=3 -> d^3/dr^3 f(z,r,phi) + /// \param derphi order of derivative d/dphi: derphi=1 -> d/dphi f(z,r,phi), derphi=2 -> d^2/dphi^2 f(z,r,phi), derphi=3 -> d^3/dphi^3 f(z,r,phi) + /// derz=1 and derr=2 -> d/dz * d^2/dr^2 * f(z,r,phi) + /// \return returns the interpolated derivative at given coordinate + DataT operator()(const DataT z, const DataT r, const DataT phi, const size_t derz, const size_t derr, const size_t derphi) const + { + const Vector<DataT, FDim> coordinates{{z, r, phi}}; // vector holding the coordinates + const auto relPos = processInp(coordinates, false); + return evalDerivative(relPos[0], relPos[1], relPos[2], derz, derr, derphi); + } + + /// set which type of extrapolation is used at the grid boundaries (linear or parabol can be used with periodic phi axis and non periodic z and r axis). + /// \param extrapolationType sets type of extrapolation. See enum ExtrapolationType for different types + void setExtrapolationType(const ExtrapolationType extrapolationType) { mExtrapolationType = extrapolationType; } + + /// \return returns the extrapolation technique for missing boundary values + ExtrapolationType getExtrapolationType() const { return mExtrapolationType; } + + /// get the number of threads used for some of the calculations + static int getNThreads() { return sNThreads; } + + /// set the number of threads used for some of the calculations + static void setNThreads(int nThreads) { sNThreads = nThreads; } + + /// \return returns the number of the thread. Each thread should have an individual thread number + int getThreadNum() const { return sThreadnum; } + + /// \return performs a check if the interpolator can be used with maximum number of threads + bool checkThreadSafety() const { return sNThreads <= omp_get_max_threads(); } + + private: + // matrix containing the 'relationship between the derivatives at the corners of the elements and the coefficients' + inline static Vc::Memory<VDataT, 64> sMat[64]{ + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {-3, 3, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, -2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {9, -9, -9, 9, 0, 0, 0, 0, 6, 3, -6, -3, 0, 0, 0, 0, 6, -6, 3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {-6, 6, 6, -6, 0, 0, 0, 0, -3, -3, 3, 3, 0, 0, 0, 0, -4, 4, -2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {-6, 6, 6, -6, 0, 0, 0, 0, -4, -2, 4, 2, 0, 0, 0, 0, -3, 3, -3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, -4, -4, 4, 0, 0, 0, 0, 2, 2, -2, -2, 0, 0, 0, 0, 2, -2, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, -9, -9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, -6, -3, 0, 0, 0, 0, 6, -6, 3, -3, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 6, 6, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, 3, 3, 0, 0, 0, 0, -4, 4, -2, 2, 0, 0, 0, 0, -2, -2, -1, -1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 6, 6, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -2, 4, 2, 0, 0, 0, 0, -3, 3, -3, 3, 0, 0, 0, 0, -2, -1, -2, -1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, -4, -4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, -2, -2, 0, 0, 0, 0, 2, -2, 2, -2, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0}, + {-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {9, -9, 0, 0, -9, 9, 0, 0, 6, 3, 0, 0, -6, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, -6, 0, 0, 3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {-6, 6, 0, 0, 6, -6, 0, 0, -3, -3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 4, 0, 0, -2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, -1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, -9, 0, 0, -9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, -6, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, -6, 0, 0, 3, -3, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 6, 0, 0, 6, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 4, 0, 0, -2, 2, 0, 0, -2, -2, 0, 0, -1, -1, 0, 0}, + {9, 0, -9, 0, -9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0, -6, 0, -3, 0, 6, 0, -6, 0, 3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 9, 0, -9, 0, -9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0, -6, 0, -3, 0, 6, 0, -6, 0, 3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0}, + {-27, 27, 27, -27, 27, -27, -27, 27, -18, -9, 18, 9, 18, 9, -18, -9, -18, 18, -9, 9, 18, -18, 9, -9, -18, 18, 18, -18, -9, 9, 9, -9, -12, -6, -6, -3, 12, 6, 6, 3, -12, -6, 12, 6, -6, -3, 6, 3, -12, 12, -6, 6, -6, 6, -3, 3, -8, -4, -4, -2, -4, -2, -2, -1}, + {18, -18, -18, 18, -18, 18, 18, -18, 9, 9, -9, -9, -9, -9, 9, 9, 12, -12, 6, -6, -12, 12, -6, 6, 12, -12, -12, 12, 6, -6, -6, 6, 6, 6, 3, 3, -6, -6, -3, -3, 6, 6, -6, -6, 3, 3, -3, -3, 8, -8, 4, -4, 4, -4, 2, -2, 4, 4, 2, 2, 2, 2, 1, 1}, + {-6, 0, 6, 0, 6, 0, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, -3, 0, 3, 0, 3, 0, -4, 0, 4, 0, -2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -2, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, -6, 0, 6, 0, 6, 0, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, -3, 0, 3, 0, 3, 0, -4, 0, 4, 0, -2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -2, 0, -1, 0, -1, 0}, + {18, -18, -18, 18, -18, 18, 18, -18, 12, 6, -12, -6, -12, -6, 12, 6, 9, -9, 9, -9, -9, 9, -9, 9, 12, -12, -12, 12, 6, -6, -6, 6, 6, 3, 6, 3, -6, -3, -6, -3, 8, 4, -8, -4, 4, 2, -4, -2, 6, -6, 6, -6, 3, -3, 3, -3, 4, 2, 4, 2, 2, 1, 2, 1}, + {-12, 12, 12, -12, 12, -12, -12, 12, -6, -6, 6, 6, 6, 6, -6, -6, -6, 6, -6, 6, 6, -6, 6, -6, -8, 8, 8, -8, -4, 4, 4, -4, -3, -3, -3, -3, 3, 3, 3, 3, -4, -4, 4, 4, -2, -2, 2, 2, -4, 4, -4, 4, -2, 2, -2, 2, -2, -2, -2, -2, -1, -1, -1, -1}, + {2, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {-6, 6, 0, 0, 6, -6, 0, 0, -4, -2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, -4, 0, 0, -4, 4, 0, 0, 2, 2, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 6, 0, 0, 6, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0, -2, -1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, -4, 0, 0, -4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, + {-6, 0, 6, 0, 6, 0, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, -2, 0, 4, 0, 2, 0, -3, 0, 3, 0, -3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -1, 0, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, -6, 0, 6, 0, 6, 0, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, -2, 0, 4, 0, 2, 0, -3, 0, 3, 0, -3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -1, 0, -2, 0, -1, 0}, + {18, -18, -18, 18, -18, 18, 18, -18, 12, 6, -12, -6, -12, -6, 12, 6, 12, -12, 6, -6, -12, 12, -6, 6, 9, -9, -9, 9, 9, -9, -9, 9, 8, 4, 4, 2, -8, -4, -4, -2, 6, 3, -6, -3, 6, 3, -6, -3, 6, -6, 3, -3, 6, -6, 3, -3, 4, 2, 2, 1, 4, 2, 2, 1}, + {-12, 12, 12, -12, 12, -12, -12, 12, -6, -6, 6, 6, 6, 6, -6, -6, -8, 8, -4, 4, 8, -8, 4, -4, -6, 6, 6, -6, -6, 6, 6, -6, -4, -4, -2, -2, 4, 4, 2, 2, -3, -3, 3, 3, -3, -3, 3, 3, -4, 4, -2, 2, -4, 4, -2, 2, -2, -2, -1, -1, -2, -2, -1, -1}, + {4, 0, -4, 0, -4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, -2, 0, -2, 0, 2, 0, -2, 0, 2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 4, 0, -4, 0, -4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, -2, 0, -2, 0, 2, 0, -2, 0, 2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0}, + {-12, 12, 12, -12, 12, -12, -12, 12, -8, -4, 8, 4, 8, 4, -8, -4, -6, 6, -6, 6, 6, -6, 6, -6, -6, 6, 6, -6, -6, 6, 6, -6, -4, -2, -4, -2, 4, 2, 4, 2, -4, -2, 4, 2, -4, -2, 4, 2, -3, 3, -3, 3, -3, 3, -3, 3, -2, -1, -2, -1, -2, -1, -2, -1}, + {8, -8, -8, 8, -8, 8, 8, -8, 4, 4, -4, -4, -4, -4, 4, 4, 4, -4, 4, -4, -4, 4, -4, 4, 4, -4, -4, 4, 4, -4, -4, 4, 2, 2, 2, 2, -2, -2, -2, -2, 2, 2, -2, -2, 2, 2, -2, -2, 2, -2, 2, -2, 2, -2, 2, -2, 1, 1, 1, 1, 1, 1, 1, 1}}; ///< matrix containing the 'relationship between the derivatives at the corners of the elements and the coefficients' + + inline static Matrix<DataT, 64> sMatrixA{sMat}; ///< this matrix is used for vectorized operations with the 64*64 matrix + static constexpr unsigned int FDim = Grid3D::getDim(); ///< dimensions of the grid + static constexpr unsigned int FZ = Grid3D::getFX(); ///< index for z coordinate + static constexpr unsigned int FR = Grid3D::getFY(); ///< index for r coordinate + static constexpr unsigned int FPHI = Grid3D::getFZ(); ///< index for phi coordinate + const DataContainer& mGridData{}; ///< adress to the data container of the grid + const Grid3D& mGridProperties{}; ///< adress to the properties of the grid + inline static thread_local const size_t sThreadnum{static_cast<size_t>(omp_get_thread_num())}; ///< save for each thread the thread number to get fast access to the correct array + inline static int sNThreads{omp_get_max_threads()}; ///< number of threads the tricubic interpolator can be used with + std::unique_ptr<Vector<DataT, 64>[]> mCoefficients = std::make_unique<Vector<DataT, 64>[]>(sNThreads); ///< coefficients needed to interpolate a value + std::unique_ptr<Vector<DataT, FDim>[]> mLastInd = std::make_unique<Vector<DataT, FDim>[]>(sNThreads); ///< stores the index for the cell, where the coefficients are already evaluated (only the coefficients for the last cell are stored) + std::unique_ptr<bool[]> mInitialized = std::make_unique<bool[]>(sNThreads); ///< sets the flag if the coefficients are evaluated at least once + ExtrapolationType mExtrapolationType = ExtrapolationType::Parabola; ///< sets which type of extrapolation for missing points at boundary is used. Linear and Parabola is only supported for perdiodic phi axis and non periodic z and r axis + + // DEFINITION OF enum GridPos + //======================================================== + // r + // | 6------F---7 + // | / | / | + // | K G YR L H + // | / | / | + // | 2---B------3 | + // | | | | | + // | | 4---|---E--5 + // | C XL / D XR / + // | | I YL | J + // | | / | / + // | 0---A------1 + // |------------------------------- z + // / + // / + // / + // phi + //======================================================== + + enum class GridPos { + None = 27, + InnerVolume = 26, + Edge0 = 0, + Edge1 = 1, + Edge2 = 2, + Edge3 = 3, + Edge4 = 4, + Edge5 = 5, + Edge6 = 6, + Edge7 = 7, + LineA = 8, + LineB = 9, + LineC = 10, + LineD = 11, + LineE = 12, + LineF = 13, + LineG = 14, + LineH = 15, + LineI = 16, + LineJ = 17, + LineK = 18, + LineL = 19, + SideXRight = 20, + SideXLeft = 21, + SideYRight = 22, + SideYLeft = 23, + SideZRight = 24, + SideZLeft = 25 + }; + + void setValues(const int iz, const int ir, const int iphi, DataT cVals[64]) const; + + const Vector<DataT, 3> processInp(const Vector<DataT, 3>& coordinates, const bool sparse = false) const; + + // calculate the coefficients needed for the interpolation using the 64*64 matrix. + // this is the 'slow' part of the code and might be optimized + void calcCoefficients(const unsigned int iz, const unsigned int ir, const unsigned int iphi) const; + + DataT interpolateDense(const Vector<DataT, 3>& pos) const; + + // interpolate value at given coordinate - this method doesnt compute and stores the coefficients and is faster when quering only a few values per cube + /// \param z z coordinate + /// \param r r coordinate + /// \param phi phi coordinate + /// \return returns the interpolated value at given coordinate + DataT interpolateSparse(const DataT z, const DataT r, const DataT phi) const; + + DataT evalDerivative(const DataT dz, const DataT dr, const DataT dphi, const size_t derz, const size_t derr, const size_t derphi) const; + + // for periodic boundary conditions + void getDataIndexCircularArray(const int index0, const int dim, int arr[]) const; + + // for non periodic boundary conditions + void getDataIndexNonCircularArray(const int index0, const int dim, int arr[]) const; + + // this helps to get circular and non circular padding indices + int getRegulatedDelta(const int index0, const int delta, const unsigned int dim, const int offs) const + { + return mGridProperties.isIndexInGrid(index0 + delta, dim) ? delta : offs; + } + + void initInterpolator(const unsigned int iz, const unsigned int ir, const unsigned int iphi) const; + + DataT extrapolation(const DataT valk, const DataT valk1, const DataT valk2) const; + + DataT linearExtrapolation(const DataT valk, const DataT valk1) const; + + DataT parabolExtrapolation(const DataT valk, const DataT valk1, const DataT valk2) const; + + GridPos findPos(const int iz, const int ir, const int iphi) const; + + bool isInInnerVolume(const int iz, const int ir, const int iphi, GridPos& posType) const; + + bool findEdge(const int iz, const int ir, const int iphi, GridPos& posType) const; + + bool findLine(const int iz, const int ir, const int iphi, GridPos& posType) const; + + bool findSide(const int iz, const int ir, const int iphi, GridPos& posType) const; + + bool isSideRight(const int ind, const int dim) const; + + bool isSideLeft(const int ind) const; +}; + +/// +/// ======================================================================================================== +/// Inline implementations +/// ======================================================================================================== +/// + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void TriCubicInterpolator<DataT, Nz, Nr, Nphi>::initInterpolator(const unsigned int iz, const unsigned int ir, const unsigned int iphi) const +{ + calcCoefficients(iz, ir, iphi); + + // store current cell + mInitialized[sThreadnum] = true; + mLastInd[sThreadnum][FZ] = iz; + mLastInd[sThreadnum][FR] = ir; + mLastInd[sThreadnum][FPHI] = iphi; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT TriCubicInterpolator<DataT, Nz, Nr, Nphi>::evalDerivative(const DataT dz, const DataT dr, const DataT dphi, const size_t derz, const size_t derr, const size_t derphi) const +{ + //TODO optimize this + DataT ret{}; + for (size_t i = derz; i < 4; i++) { + for (size_t j = derr; j < 4; j++) { + for (size_t k = derphi; k < 4; k++) { + + const size_t index = i + j * 4 + 16 * k; + DataT cont = mCoefficients[sThreadnum][index] * std::pow(dz, i - derz) * std::pow(dr, j - derr) * std::pow(dphi, k - derphi); + for (size_t w = 0; w < derz; w++) { + cont *= (i - w); + } + for (size_t w = 0; w < derr; w++) { + cont *= (j - w); + } + for (size_t w = 0; w < derphi; w++) { + cont *= (k - w); + } + ret += cont; + } + } + } + const DataT norm = std::pow(mGridProperties.getInvSpacingX(), derz) * std::pow(mGridProperties.getInvSpacingY(), derr) * std::pow(mGridProperties.getInvSpacingZ(), derphi); + return (ret * norm); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT TriCubicInterpolator<DataT, Nz, Nr, Nphi>::extrapolation(const DataT valk, const DataT valk1, const DataT valk2) const +{ + switch (mExtrapolationType) { + case ExtrapolationType::Linear: + default: + return linearExtrapolation(valk, valk1); + break; + case ExtrapolationType::Parabola: + return parabolExtrapolation(valk, valk1, valk2); + break; + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT TriCubicInterpolator<DataT, Nz, Nr, Nphi>::linearExtrapolation(const DataT valk, const DataT valk1) const +{ + const DataT val = 2 * valk - valk1; + return val; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT TriCubicInterpolator<DataT, Nz, Nr, Nphi>::parabolExtrapolation(const DataT valk, const DataT valk1, const DataT valk2) const +{ + const DataT val = 3 * (valk - valk1) + valk2; // legendre polynom with x0=0, x1=1, x2=2 and z=-1 + return val; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void TriCubicInterpolator<DataT, Nz, Nr, Nphi>::calcCoefficients(const unsigned int iz, const unsigned int ir, const unsigned int iphi) const +{ + DataT cVals[64]{}; + setValues(iz, ir, iphi, cVals); + + // needed for first derivative + const Vector<DataT, 24> vecDeriv1A{ + {cVals[22], cVals[23], cVals[26], cVals[27], cVals[38], cVals[39], cVals[42], cVals[43], + cVals[25], cVals[26], cVals[29], cVals[30], cVals[41], cVals[42], cVals[45], cVals[46], + cVals[37], cVals[38], cVals[41], cVals[42], cVals[53], cVals[54], cVals[57], cVals[58]}}; + + const Vector<DataT, 24> vecDeriv1B{ + {cVals[20], cVals[21], cVals[24], cVals[25], cVals[36], cVals[37], cVals[40], cVals[41], + cVals[17], cVals[18], cVals[21], cVals[22], cVals[33], cVals[34], cVals[37], cVals[38], + cVals[5], cVals[6], cVals[9], cVals[10], cVals[21], cVals[22], cVals[25], cVals[26]}}; + + // needed for second derivative + const Vector<DataT, 24> vecDeriv2A{ + {cVals[26], cVals[27], cVals[30], cVals[31], cVals[42], cVals[43], cVals[46], cVals[47], + cVals[38], cVals[39], cVals[42], cVals[43], cVals[54], cVals[55], cVals[58], cVals[59], + cVals[41], cVals[42], cVals[45], cVals[46], cVals[57], cVals[58], cVals[61], cVals[62]}}; + + const Vector<DataT, 24> vecDeriv2B{ + {cVals[24], cVals[25], cVals[28], cVals[29], cVals[40], cVals[41], cVals[44], cVals[45], + cVals[36], cVals[37], cVals[40], cVals[41], cVals[52], cVals[53], cVals[56], cVals[57], + cVals[33], cVals[34], cVals[37], cVals[38], cVals[49], cVals[50], cVals[53], cVals[54]}}; + + const Vector<DataT, 24> vecDeriv2C{ + {cVals[18], cVals[19], cVals[22], cVals[23], cVals[34], cVals[35], cVals[38], cVals[39], + cVals[6], cVals[7], cVals[10], cVals[11], cVals[22], cVals[23], cVals[26], cVals[27], + cVals[9], cVals[10], cVals[13], cVals[14], cVals[25], cVals[26], cVals[29], cVals[30]}}; + + const Vector<DataT, 24> vecDeriv2D{ + {cVals[16], cVals[17], cVals[20], cVals[21], cVals[32], cVals[33], cVals[36], cVals[37], + cVals[4], cVals[5], cVals[8], cVals[9], cVals[20], cVals[21], cVals[24], cVals[25], + cVals[1], cVals[2], cVals[5], cVals[6], cVals[17], cVals[18], cVals[21], cVals[22]}}; + + // needed for third derivative + const Vector<DataT, 8> vecDeriv3A{{cVals[42], cVals[43], cVals[46], cVals[47], cVals[58], cVals[59], cVals[62], cVals[63]}}; + const Vector<DataT, 8> vecDeriv3B{{cVals[40], cVals[41], cVals[44], cVals[45], cVals[56], cVals[57], cVals[60], cVals[61]}}; + const Vector<DataT, 8> vecDeriv3C{{cVals[34], cVals[35], cVals[38], cVals[39], cVals[50], cVals[51], cVals[54], cVals[55]}}; + const Vector<DataT, 8> vecDeriv3D{{cVals[32], cVals[33], cVals[36], cVals[37], cVals[48], cVals[49], cVals[52], cVals[53]}}; + const Vector<DataT, 8> vecDeriv3E{{cVals[10], cVals[11], cVals[14], cVals[15], cVals[26], cVals[27], cVals[30], cVals[31]}}; + const Vector<DataT, 8> vecDeriv3F{{cVals[8], cVals[9], cVals[12], cVals[13], cVals[24], cVals[25], cVals[28], cVals[29]}}; + const Vector<DataT, 8> vecDeriv3G{{cVals[2], cVals[3], cVals[6], cVals[7], cVals[18], cVals[19], cVals[22], cVals[23]}}; + const Vector<DataT, 8> vecDeriv3H{{cVals[0], cVals[1], cVals[4], cVals[5], cVals[16], cVals[17], cVals[20], cVals[21]}}; + + // factor for first derivative + const DataT fac1{0.5}; + const Vector<DataT, 24> vfac1{{fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1, fac1}}; + + // factor for second derivative + const DataT fac2{0.25}; + const Vector<DataT, 24> vfac2{{fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2, fac2}}; + + // factor for third derivative + const DataT fac3{0.125}; + const Vector<DataT, 8> vfac3{{fac3, fac3, fac3, fac3, fac3, fac3, fac3, fac3}}; + + // compute the derivatives + const Vector<DataT, 24> vecDeriv1Res{vfac1 * (vecDeriv1A - vecDeriv1B)}; + const Vector<DataT, 24> vecDeriv2Res{vfac2 * (vecDeriv2A - vecDeriv2B - vecDeriv2C + vecDeriv2D)}; + const Vector<DataT, 8> vecDeriv3Res{vfac3 * (vecDeriv3A - vecDeriv3B - vecDeriv3C + vecDeriv3D - vecDeriv3E + vecDeriv3F + vecDeriv3G - vecDeriv3H)}; + + const Vector<DataT, 64> matrixPar{ + {cVals[21], cVals[22], cVals[25], cVals[26], cVals[37], cVals[38], cVals[41], cVals[42], + vecDeriv1Res[0], vecDeriv1Res[1], vecDeriv1Res[2], vecDeriv1Res[3], vecDeriv1Res[4], vecDeriv1Res[5], vecDeriv1Res[6], vecDeriv1Res[7], vecDeriv1Res[8], vecDeriv1Res[9], vecDeriv1Res[10], + vecDeriv1Res[11], vecDeriv1Res[12], vecDeriv1Res[13], vecDeriv1Res[14], vecDeriv1Res[15], vecDeriv1Res[16], vecDeriv1Res[17], vecDeriv1Res[18], vecDeriv1Res[19], vecDeriv1Res[20], vecDeriv1Res[21], + vecDeriv1Res[22], vecDeriv1Res[23], vecDeriv2Res[0], vecDeriv2Res[1], vecDeriv2Res[2], vecDeriv2Res[3], vecDeriv2Res[4], vecDeriv2Res[5], vecDeriv2Res[6], vecDeriv2Res[7], vecDeriv2Res[8], vecDeriv2Res[9], + vecDeriv2Res[10], vecDeriv2Res[11], vecDeriv2Res[12], vecDeriv2Res[13], vecDeriv2Res[14], vecDeriv2Res[15], vecDeriv2Res[16], vecDeriv2Res[17], vecDeriv2Res[18], vecDeriv2Res[19], vecDeriv2Res[20], + vecDeriv2Res[21], vecDeriv2Res[22], vecDeriv2Res[23], vecDeriv3Res[0], vecDeriv3Res[1], vecDeriv3Res[2], vecDeriv3Res[3], vecDeriv3Res[4], vecDeriv3Res[5], vecDeriv3Res[6], vecDeriv3Res[7]}}; + + // calc coeffiecients + mCoefficients[sThreadnum] = sMatrixA * matrixPar; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT TriCubicInterpolator<DataT, Nz, Nr, Nphi>::interpolateDense(const Vector<DataT, 3>& pos) const +{ + // the formula for evaluating the interpolation is as follows: + // f(z,r,phi) = \sum_{i,j,k=0}^3 a_{ijk} * z^{i} * r^{j} * phi^{k} + // a_{ijk} is stored in mCoefficients[] and are computed in the function calcCoefficientsX() + + const Vector<DataT, FDim> vals0{{1, 1, 1}}; // z^0, r^0, phi^0 + const Vector<DataT, FDim> vals2{pos * pos}; // z^2, r^2, phi^2 + const Vector<DataT, FDim> vals3{vals2 * pos}; // z^3, r^3, phi^3 + + const DataT valX[4]{vals0[FZ], pos[FZ], vals2[FZ], vals3[FZ]}; + const Vector<DataT, 64> vecValX{ + {valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], + valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], + valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], + valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3], valX[0], valX[1], valX[2], valX[3]}}; + + const DataT valY[4]{vals0[FR], pos[FR], vals2[FR], vals3[FR]}; + const Vector<DataT, 64> vecValY{ + {valY[0], valY[0], valY[0], valY[0], valY[1], valY[1], valY[1], valY[1], valY[2], valY[2], valY[2], valY[2], valY[3], valY[3], valY[3], valY[3], + valY[0], valY[0], valY[0], valY[0], valY[1], valY[1], valY[1], valY[1], valY[2], valY[2], valY[2], valY[2], valY[3], valY[3], valY[3], valY[3], + valY[0], valY[0], valY[0], valY[0], valY[1], valY[1], valY[1], valY[1], valY[2], valY[2], valY[2], valY[2], valY[3], valY[3], valY[3], valY[3], + valY[0], valY[0], valY[0], valY[0], valY[1], valY[1], valY[1], valY[1], valY[2], valY[2], valY[2], valY[2], valY[3], valY[3], valY[3], valY[3]}}; + + const DataT valZ[4]{vals0[FPHI], pos[FPHI], vals2[FPHI], vals3[FPHI]}; + const Vector<DataT, 64> vecValZ{ + {valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], valZ[0], + valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], valZ[1], + valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], valZ[2], + valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3], valZ[3]}}; + + // result = f(z,r,phi) = \sum_{i,j,k=0}^3 a_{ijk} * z^{i} * r^{j} * phi^{k} + const DataT result = sum(mCoefficients[sThreadnum] * vecValX * vecValY * vecValZ); + return result; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT TriCubicInterpolator<DataT, Nz, Nr, Nphi>::interpolateSparse(const DataT z, const DataT r, const DataT phi) const +{ + const Vector<DataT, FDim> coordinates{{z, r, phi}}; // vector holding the coordinates + const auto posRel = processInp(coordinates, true); + + DataT cVals[64]{}; + setValues(mLastInd[sThreadnum][FZ], mLastInd[sThreadnum][FR], mLastInd[sThreadnum][FPHI], cVals); + + const Vector<DataT, FDim> vals0{posRel}; + const Vector<DataT, FDim> vals1{vals0 * vals0}; + const Vector<DataT, FDim> vals2{vals0 * vals1}; + + const int nPoints = 4; + const Vector<DataT, nPoints> vecValX{{1, vals0[FZ], vals1[FZ], vals2[FZ]}}; + const Vector<DataT, nPoints> vecValY{{1, vals0[FR], vals1[FR], vals2[FR]}}; + const Vector<DataT, nPoints> vecValZ{{1, vals0[FPHI], vals1[FPHI], vals2[FPHI]}}; + + const Vc::Memory<VDataT, nPoints> matrA[nPoints]{ + {0, -0.5, 1, -0.5}, + {1, 0, -2.5, 1.5}, + {0, 0.5, 2., -1.5}, + {0, 0, -0.5, 0.5}}; + + const Matrix<DataT, nPoints> matrixA{matrA}; + const Vector<DataT, nPoints> vecValXMult{matrixA * vecValX}; + const Vector<DataT, nPoints> vecValYMult{matrixA * vecValY}; + const Vector<DataT, nPoints> vecValZMult{matrixA * vecValZ}; + + DataT result{}; + int ind = 0; + for (int slice = 0; slice < nPoints; ++slice) { + const Vector<DataT, nPoints> vecA{vecValZMult[slice] * vecValYMult}; + for (int row = 0; row < nPoints; ++row) { + const Vector<DataT, nPoints> vecD{{cVals[ind], cVals[++ind], cVals[++ind], cVals[++ind]}}; + ++ind; + result += sum(vecA[row] * vecValXMult * vecD); + } + } + return result; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +const Vector<DataT, 3> TriCubicInterpolator<DataT, Nz, Nr, Nphi>::processInp(const Vector<DataT, 3>& coordinates, const bool sparse) const +{ + Vector<DataT, FDim> posRel{(coordinates - mGridProperties.getGridMin()) * mGridProperties.getInvSpacing()}; // needed for the grid index + posRel[FPHI] = mGridProperties.clampToGridCircularRel(posRel[FPHI], FPHI); + const Vector<DataT, FDim> posRelN{posRel}; + posRel[FZ] = mGridProperties.clampToGridRel(posRel[FZ], FZ); + posRel[FR] = mGridProperties.clampToGridRel(posRel[FR], FR); + + const Vector<DataT, FDim> index{floor(posRel)}; + + if (!sparse && (!mInitialized[sThreadnum] || !(mLastInd[sThreadnum] == index))) { + initInterpolator(index[FZ], index[FR], index[FPHI]); + } else if (sparse) { + mLastInd[sThreadnum][FZ] = index[FZ]; + mLastInd[sThreadnum][FR] = index[FR]; + mLastInd[sThreadnum][FPHI] = index[FPHI]; + mInitialized[sThreadnum] = false; + } + return posRelN - index; +} + +// for perdiodic boundary condition +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void TriCubicInterpolator<DataT, Nz, Nr, Nphi>::getDataIndexCircularArray(const int index0, const int dim, int arr[]) const +{ + const int delta_min1 = getRegulatedDelta(index0, -1, dim, mGridProperties.getN(dim) - 1); + const int delta_plus1 = getRegulatedDelta(index0, +1, dim, 1 - mGridProperties.getN(dim)); + const int delta_plus2 = getRegulatedDelta(index0, +2, dim, 2 - mGridProperties.getN(dim)); + + arr[0] = mGridProperties.getDeltaDataIndex(delta_min1, dim); + arr[1] = mGridProperties.getDeltaDataIndex(delta_plus1, dim); + arr[2] = mGridProperties.getDeltaDataIndex(delta_plus2, dim); +} + +// for non perdiodic boundary condition +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void TriCubicInterpolator<DataT, Nz, Nr, Nphi>::getDataIndexNonCircularArray(const int index0, const int dim, int arr[]) const +{ + const int delta_min1 = getRegulatedDelta(index0, -1, dim, 0); + const int delta_plus1 = getRegulatedDelta(index0, +1, dim, 0); + const int delta_plus2 = getRegulatedDelta(index0, +2, dim, delta_plus1); + + arr[0] = mGridProperties.getDeltaDataIndex(delta_min1, dim); + arr[1] = mGridProperties.getDeltaDataIndex(delta_plus1, dim); + arr[2] = mGridProperties.getDeltaDataIndex(delta_plus2, dim); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +typename TriCubicInterpolator<DataT, Nz, Nr, Nphi>::GridPos TriCubicInterpolator<DataT, Nz, Nr, Nphi>::findPos(const int iz, const int ir, const int iphi) const +{ + GridPos pos = GridPos::None; + if (isInInnerVolume(iz, ir, iphi, pos)) { + return pos; + } + + if (findEdge(iz, ir, iphi, pos)) { + return pos; + } + + if (findLine(iz, ir, iphi, pos)) { + return pos; + } + + if (findSide(iz, ir, iphi, pos)) { + return pos; + } + return GridPos::None; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +bool TriCubicInterpolator<DataT, Nz, Nr, Nphi>::findEdge(const int iz, const int ir, const int iphi, GridPos& posType) const +{ + const int iR = 2; + if (iz == 0 && ir == 0) { + if (iphi == 0) { + posType = GridPos::Edge0; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::Edge4; + return true; + } + } else if (iz == Nz - iR && ir == 0) { + if (iphi == 0) { + posType = GridPos::Edge1; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::Edge5; + return true; + } + } else if (iz == 0 && ir == Nr - iR) { + if (iphi == 0) { + posType = GridPos::Edge2; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::Edge6; + return true; + } + } else if (iz == Nz - iR && ir == Nr - iR) { + if (iphi == 0) { + posType = GridPos::Edge3; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::Edge7; + return true; + } + } + return false; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +bool TriCubicInterpolator<DataT, Nz, Nr, Nphi>::findLine(const int iz, const int ir, const int iphi, GridPos& posType) const +{ + const int iR = 2; + //check line + if (ir == 0) { + if (iphi == 0) { + posType = GridPos::LineA; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::LineE; + return true; + } + if (iz == 0) { + posType = GridPos::LineI; + return true; + } else if (iz == Nz - iR) { + posType = GridPos::LineJ; + return true; + } + } else if (ir == Nr - iR) { + if (iphi == 0) { + posType = GridPos::LineB; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::LineF; + return true; + } + if (iz == 0) { + posType = GridPos::LineK; + return true; + } else if (iz == Nz - iR) { + posType = GridPos::LineL; + return true; + } + } else if (iz == 0) { + if (iphi == 0) { + posType = GridPos::LineC; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::LineG; + return true; + } + } else if (iz == Nz - iR) { + if (iphi == 0) { + posType = GridPos::LineD; + return true; + } else if (iphi == Nphi - iR) { + posType = GridPos::LineH; + return true; + } + } + return false; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +bool TriCubicInterpolator<DataT, Nz, Nr, Nphi>::findSide(const int iz, const int ir, const int iphi, GridPos& posType) const +{ + if (isSideRight(iz, FZ)) { + posType = GridPos::SideXRight; + return true; + } else if (isSideLeft(iz)) { + posType = GridPos::SideXLeft; + return true; + } + if (isSideRight(ir, FR)) { + posType = GridPos::SideYRight; + return true; + } else if (isSideLeft(ir)) { + posType = GridPos::SideYLeft; + return true; + } + if (isSideRight(iphi, FPHI)) { + posType = GridPos::SideZRight; + return true; + } else if (isSideLeft(iphi)) { + posType = GridPos::SideZLeft; + return true; + } + return false; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +bool TriCubicInterpolator<DataT, Nz, Nr, Nphi>::isInInnerVolume(const int iz, const int ir, const int iphi, GridPos& posType) const +{ + if (iz >= 1 && iz < static_cast<int>(Nz - 2) && ir >= 1 && ir < static_cast<int>(Nr - 2) && iphi >= 1 && iphi < static_cast<int>(Nphi - 2)) { + posType = GridPos::InnerVolume; + return true; + } + return false; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +bool TriCubicInterpolator<DataT, Nz, Nr, Nphi>::isSideRight(const int ind, const int dim) const +{ + if (ind == static_cast<int>(mGridProperties.getN(dim) - 2)) { + return true; + } + return false; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +bool TriCubicInterpolator<DataT, Nz, Nr, Nphi>::isSideLeft(const int ind) const +{ + if (ind == 0) { + return true; + } + return false; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void TriCubicInterpolator<DataT, Nz, Nr, Nphi>::setValues(const int iz, const int ir, const int iphi, DataT cVals[64]) const +{ + const GridPos location = findPos(iz, ir, iphi); + const int ii_x_y_z = mGridData.getDataIndex(iz, ir, iphi); + cVals[21] = mGridData[ii_x_y_z]; + + int deltaZ[3]{mGridProperties.getDeltaDataIndex(-1, 0), mGridProperties.getDeltaDataIndex(1, 0), mGridProperties.getDeltaDataIndex(2, 0)}; + int deltaR[3]{mGridProperties.getDeltaDataIndex(-1, 1), mGridProperties.getDeltaDataIndex(1, 1), mGridProperties.getDeltaDataIndex(2, 1)}; + int deltaPhi[3]{}; + getDataIndexCircularArray(iphi, FPHI, deltaPhi); + + const int i0 = 0; + const int i1 = 1; + const int i2 = 2; + + switch (location) { + case GridPos::InnerVolume: + case GridPos::SideZRight: + case GridPos::SideZLeft: + default: { + const int ind[4][4][4]{ + {{ii_x_y_z + deltaPhi[i0] + deltaR[i0] + deltaZ[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0], ind[0][0][2] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0], ind[0][1][2] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0], ind[0][2][2] - deltaZ[i0]}, + {ind[0][2][0] - deltaR[i0], ind[0][3][0] - deltaZ[i0], ind[0][3][1] - deltaZ[i0], ind[0][3][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaR[i0] + deltaZ[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0], ind[1][0][2] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0], ind[1][1][2] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0], ind[1][2][2] - deltaZ[i0]}, + {ind[1][2][0] - deltaR[i0], ind[1][3][0] - deltaZ[i0], ind[1][3][1] - deltaZ[i0], ind[1][3][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaR[i0] + deltaZ[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0], ind[2][0][2] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0], ind[2][1][2] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0], ind[2][2][2] - deltaZ[i0]}, + {ind[2][2][0] - deltaR[i0], ind[2][3][0] - deltaZ[i0], ind[2][3][1] - deltaZ[i0], ind[2][3][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaR[i0] + deltaZ[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0], ind[3][0][2] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0], ind[3][1][2] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0], ind[3][2][2] - deltaZ[i0]}, + {ind[3][2][0] - deltaR[i0], ind[3][3][0] - deltaZ[i0], ind[3][3][1] - deltaZ[i0], ind[3][3][2] - deltaZ[i0]}}}; + + cVals[0] = mGridData[ind[0][0][0]]; + cVals[1] = mGridData[ind[0][0][1]]; + cVals[2] = mGridData[ind[0][0][2]]; + cVals[3] = mGridData[ind[0][0][3]]; + cVals[4] = mGridData[ind[0][1][0]]; + cVals[5] = mGridData[ind[0][1][1]]; + cVals[6] = mGridData[ind[0][1][2]]; + cVals[7] = mGridData[ind[0][1][3]]; + cVals[8] = mGridData[ind[0][2][0]]; + cVals[9] = mGridData[ind[0][2][1]]; + cVals[10] = mGridData[ind[0][2][2]]; + cVals[11] = mGridData[ind[0][2][3]]; + cVals[12] = mGridData[ind[0][3][0]]; + cVals[13] = mGridData[ind[0][3][1]]; + cVals[14] = mGridData[ind[0][3][2]]; + cVals[15] = mGridData[ind[0][3][3]]; + cVals[16] = mGridData[ind[1][0][0]]; + cVals[17] = mGridData[ind[1][0][1]]; + cVals[18] = mGridData[ind[1][0][2]]; + cVals[19] = mGridData[ind[1][0][3]]; + cVals[22] = mGridData[ind[1][1][2]]; + cVals[20] = mGridData[ind[1][1][0]]; + cVals[23] = mGridData[ind[1][1][3]]; + cVals[24] = mGridData[ind[1][2][0]]; + cVals[25] = mGridData[ind[1][2][1]]; + cVals[26] = mGridData[ind[1][2][2]]; + cVals[27] = mGridData[ind[1][2][3]]; + cVals[28] = mGridData[ind[1][3][0]]; + cVals[29] = mGridData[ind[1][3][1]]; + cVals[30] = mGridData[ind[1][3][2]]; + cVals[31] = mGridData[ind[1][3][3]]; + cVals[32] = mGridData[ind[2][0][0]]; + cVals[33] = mGridData[ind[2][0][1]]; + cVals[34] = mGridData[ind[2][0][2]]; + cVals[35] = mGridData[ind[2][0][3]]; + cVals[36] = mGridData[ind[2][1][0]]; + cVals[37] = mGridData[ind[2][1][1]]; + cVals[38] = mGridData[ind[2][1][2]]; + cVals[39] = mGridData[ind[2][1][3]]; + cVals[40] = mGridData[ind[2][2][0]]; + cVals[41] = mGridData[ind[2][2][1]]; + cVals[42] = mGridData[ind[2][2][2]]; + cVals[43] = mGridData[ind[2][2][3]]; + cVals[44] = mGridData[ind[2][3][0]]; + cVals[45] = mGridData[ind[2][3][1]]; + cVals[46] = mGridData[ind[2][3][2]]; + cVals[47] = mGridData[ind[2][3][3]]; + cVals[48] = mGridData[ind[3][0][0]]; + cVals[49] = mGridData[ind[3][0][1]]; + cVals[50] = mGridData[ind[3][0][2]]; + cVals[51] = mGridData[ind[3][0][3]]; + cVals[52] = mGridData[ind[3][1][0]]; + cVals[53] = mGridData[ind[3][1][1]]; + cVals[54] = mGridData[ind[3][1][2]]; + cVals[55] = mGridData[ind[3][1][3]]; + cVals[56] = mGridData[ind[3][2][0]]; + cVals[57] = mGridData[ind[3][2][1]]; + cVals[58] = mGridData[ind[3][2][2]]; + cVals[59] = mGridData[ind[3][2][3]]; + cVals[60] = mGridData[ind[3][3][0]]; + cVals[61] = mGridData[ind[3][3][1]]; + cVals[62] = mGridData[ind[3][3][2]]; + cVals[63] = mGridData[ind[3][3][3]]; + } break; + + case GridPos::SideXRight: + case GridPos::LineD: + case GridPos::LineH: { + const int ind[4][4][3]{ + {{ii_x_y_z + deltaPhi[i0] + deltaR[i0] + deltaZ[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0]}, + {ind[0][2][0] - deltaR[i0], ind[0][3][0] - deltaZ[i0], ind[0][3][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaR[i0] + deltaZ[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0]}, + {ind[1][2][0] - deltaR[i0], ind[1][3][0] - deltaZ[i0], ind[1][3][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaR[i0] + deltaZ[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0]}, + {ind[2][2][0] - deltaR[i0], ind[2][3][0] - deltaZ[i0], ind[2][3][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaR[i0] + deltaZ[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0]}, + {ind[3][2][0] - deltaR[i0], ind[3][3][0] - deltaZ[i0], ind[3][3][1] - deltaZ[i0]}}}; + + cVals[0] = mGridData[ind[0][0][0]]; + cVals[1] = mGridData[ind[0][0][1]]; + cVals[2] = mGridData[ind[0][0][2]]; + cVals[3] = extrapolation(mGridData[ind[0][0][2]], mGridData[ind[0][0][1]], mGridData[ind[0][0][0]]); + cVals[4] = mGridData[ind[0][1][0]]; + cVals[5] = mGridData[ind[0][1][1]]; + cVals[6] = mGridData[ind[0][1][2]]; + cVals[7] = extrapolation(mGridData[ind[0][1][2]], mGridData[ind[0][1][1]], mGridData[ind[0][1][0]]); + cVals[8] = mGridData[ind[0][2][0]]; + cVals[9] = mGridData[ind[0][2][1]]; + cVals[10] = mGridData[ind[0][2][2]]; + cVals[11] = extrapolation(mGridData[ind[0][2][2]], mGridData[ind[0][2][1]], mGridData[ind[0][2][0]]); + cVals[12] = mGridData[ind[0][3][0]]; + cVals[13] = mGridData[ind[0][3][1]]; + cVals[14] = mGridData[ind[0][3][2]]; + cVals[15] = extrapolation(mGridData[ind[0][3][2]], mGridData[ind[0][3][1]], mGridData[ind[0][3][0]]); + cVals[16] = mGridData[ind[1][0][0]]; + cVals[17] = mGridData[ind[1][0][1]]; + cVals[18] = mGridData[ind[1][0][2]]; + cVals[19] = extrapolation(mGridData[ind[1][0][2]], mGridData[ind[1][0][1]], mGridData[ind[1][0][0]]); + cVals[20] = mGridData[ind[1][1][0]]; + cVals[22] = mGridData[ind[1][1][2]]; + cVals[23] = extrapolation(mGridData[ind[1][1][2]], mGridData[ii_x_y_z], mGridData[ind[1][1][0]]); + cVals[24] = mGridData[ind[1][2][0]]; + cVals[25] = mGridData[ind[1][2][1]]; + cVals[26] = mGridData[ind[1][2][2]]; + cVals[27] = extrapolation(mGridData[ind[1][2][2]], mGridData[ind[1][2][1]], mGridData[ind[1][2][0]]); + cVals[28] = mGridData[ind[1][3][0]]; + cVals[29] = mGridData[ind[1][3][1]]; + cVals[30] = mGridData[ind[1][3][2]]; + cVals[31] = extrapolation(mGridData[ind[1][3][2]], mGridData[ind[1][3][1]], mGridData[ind[1][3][0]]); + cVals[32] = mGridData[ind[2][0][0]]; + cVals[33] = mGridData[ind[2][0][1]]; + cVals[34] = mGridData[ind[2][0][2]]; + cVals[35] = extrapolation(mGridData[ind[2][0][2]], mGridData[ind[2][0][1]], mGridData[ind[2][0][0]]); + cVals[36] = mGridData[ind[2][1][0]]; + cVals[37] = mGridData[ind[2][1][1]]; + cVals[38] = mGridData[ind[2][1][2]]; + cVals[39] = extrapolation(mGridData[ind[2][1][2]], mGridData[ind[2][1][1]], mGridData[ind[2][1][0]]); + cVals[40] = mGridData[ind[2][2][0]]; + cVals[41] = mGridData[ind[2][2][1]]; + cVals[42] = mGridData[ind[2][2][2]]; + cVals[43] = extrapolation(mGridData[ind[2][2][2]], mGridData[ind[2][2][1]], mGridData[ind[2][2][0]]); + cVals[44] = mGridData[ind[2][3][0]]; + cVals[45] = mGridData[ind[2][3][1]]; + cVals[46] = mGridData[ind[2][3][2]]; + cVals[47] = extrapolation(mGridData[ind[2][3][2]], mGridData[ind[2][3][1]], mGridData[ind[2][3][0]]); + cVals[48] = mGridData[ind[3][0][0]]; + cVals[49] = mGridData[ind[3][0][1]]; + cVals[50] = mGridData[ind[3][0][2]]; + cVals[52] = mGridData[ind[3][1][0]]; + cVals[51] = extrapolation(mGridData[ind[3][0][2]], mGridData[ind[3][0][1]], mGridData[ind[3][0][0]]); + cVals[53] = mGridData[ind[3][1][1]]; + cVals[54] = mGridData[ind[3][1][2]]; + cVals[55] = extrapolation(mGridData[ind[3][1][2]], mGridData[ind[3][1][1]], mGridData[ind[3][1][0]]); + cVals[56] = mGridData[ind[3][2][0]]; + cVals[57] = mGridData[ind[3][2][1]]; + cVals[58] = mGridData[ind[3][2][2]]; + cVals[59] = extrapolation(mGridData[ind[3][2][2]], mGridData[ind[3][2][1]], mGridData[ind[3][2][0]]); + cVals[60] = mGridData[ind[3][3][0]]; + cVals[61] = mGridData[ind[3][3][1]]; + cVals[62] = mGridData[ind[3][3][2]]; + cVals[63] = extrapolation(mGridData[ind[3][3][2]], mGridData[ind[3][3][1]], mGridData[ind[3][3][0]]); + } break; + + case GridPos::SideYRight: + case GridPos::LineB: + case GridPos::LineF: { + const int ind[4][3][4]{ + {{ii_x_y_z + deltaPhi[i0] + deltaR[i0] + deltaZ[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0], ind[0][0][2] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0], ind[0][1][2] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0], ind[0][2][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaR[i0] + deltaZ[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0], ind[1][0][2] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0], ind[1][1][2] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0], ind[1][2][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaR[i0] + deltaZ[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0], ind[2][0][2] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0], ind[2][1][2] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0], ind[2][2][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaR[i0] + deltaZ[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0], ind[3][0][2] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0], ind[3][1][2] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0], ind[3][2][2] - deltaZ[i0]}}}; + + cVals[0] = mGridData[ind[0][0][0]]; + cVals[1] = mGridData[ind[0][0][1]]; + cVals[2] = mGridData[ind[0][0][2]]; + cVals[3] = mGridData[ind[0][0][3]]; + cVals[4] = mGridData[ind[0][1][0]]; + cVals[5] = mGridData[ind[0][1][1]]; + cVals[6] = mGridData[ind[0][1][2]]; + cVals[7] = mGridData[ind[0][1][3]]; + cVals[8] = mGridData[ind[0][2][0]]; + cVals[9] = mGridData[ind[0][2][1]]; + cVals[10] = mGridData[ind[0][2][2]]; + cVals[11] = mGridData[ind[0][2][3]]; + cVals[12] = extrapolation(mGridData[ind[0][2][0]], mGridData[ind[0][1][0]], mGridData[ind[0][0][0]]); + cVals[13] = extrapolation(mGridData[ind[0][2][1]], mGridData[ind[0][1][1]], mGridData[ind[0][0][1]]); + cVals[14] = extrapolation(mGridData[ind[0][2][2]], mGridData[ind[0][1][2]], mGridData[ind[0][0][2]]); + cVals[15] = extrapolation(mGridData[ind[0][2][3]], mGridData[ind[0][1][3]], mGridData[ind[0][0][3]]); + cVals[16] = mGridData[ind[1][0][0]]; + cVals[17] = mGridData[ind[1][0][1]]; + cVals[18] = mGridData[ind[1][0][2]]; + cVals[19] = mGridData[ind[1][0][3]]; + cVals[20] = mGridData[ind[1][1][0]]; + cVals[22] = mGridData[ind[1][1][2]]; + cVals[23] = mGridData[ind[1][1][3]]; + cVals[24] = mGridData[ind[1][2][0]]; + cVals[25] = mGridData[ind[1][2][1]]; + cVals[26] = mGridData[ind[1][2][2]]; + cVals[27] = mGridData[ind[1][2][3]]; + cVals[28] = extrapolation(mGridData[ind[1][2][0]], mGridData[ind[1][1][0]], mGridData[ind[1][0][0]]); + cVals[29] = extrapolation(mGridData[ind[1][2][1]], mGridData[ii_x_y_z], mGridData[ind[1][0][1]]); + cVals[30] = extrapolation(mGridData[ind[1][2][2]], mGridData[ind[1][1][2]], mGridData[ind[1][0][2]]); + cVals[31] = extrapolation(mGridData[ind[1][2][3]], mGridData[ind[1][1][3]], mGridData[ind[1][0][3]]); + cVals[32] = mGridData[ind[2][0][0]]; + cVals[33] = mGridData[ind[2][0][1]]; + cVals[34] = mGridData[ind[2][0][2]]; + cVals[35] = mGridData[ind[2][0][3]]; + cVals[36] = mGridData[ind[2][1][0]]; + cVals[37] = mGridData[ind[2][1][1]]; + cVals[38] = mGridData[ind[2][1][2]]; + cVals[39] = mGridData[ind[2][1][3]]; + cVals[40] = mGridData[ind[2][2][0]]; + cVals[41] = mGridData[ind[2][2][1]]; + cVals[42] = mGridData[ind[2][2][2]]; + cVals[43] = mGridData[ind[2][2][3]]; + cVals[44] = extrapolation(mGridData[ind[2][2][0]], mGridData[ind[2][1][0]], mGridData[ind[2][0][0]]); + cVals[45] = extrapolation(mGridData[ind[2][2][1]], mGridData[ind[2][1][1]], mGridData[ind[2][0][1]]); + cVals[46] = extrapolation(mGridData[ind[2][2][2]], mGridData[ind[2][1][2]], mGridData[ind[2][0][2]]); + cVals[47] = extrapolation(mGridData[ind[2][2][3]], mGridData[ind[2][1][3]], mGridData[ind[2][0][3]]); + cVals[48] = mGridData[ind[3][0][0]]; + cVals[49] = mGridData[ind[3][0][1]]; + cVals[50] = mGridData[ind[3][0][2]]; + cVals[51] = mGridData[ind[3][0][3]]; + cVals[52] = mGridData[ind[3][1][0]]; + cVals[53] = mGridData[ind[3][1][1]]; + cVals[54] = mGridData[ind[3][1][2]]; + cVals[55] = mGridData[ind[3][1][3]]; + cVals[56] = mGridData[ind[3][2][0]]; + cVals[57] = mGridData[ind[3][2][1]]; + cVals[58] = mGridData[ind[3][2][2]]; + cVals[59] = mGridData[ind[3][2][3]]; + cVals[60] = extrapolation(mGridData[ind[3][2][0]], mGridData[ind[3][1][0]], mGridData[ind[3][0][0]]); + cVals[61] = extrapolation(mGridData[ind[3][2][1]], mGridData[ind[3][1][1]], mGridData[ind[3][0][1]]); + cVals[62] = extrapolation(mGridData[ind[3][2][2]], mGridData[ind[3][1][2]], mGridData[ind[3][0][2]]); + cVals[63] = extrapolation(mGridData[ind[3][2][3]], mGridData[ind[3][1][3]], mGridData[ind[3][0][3]]); + } break; + + case GridPos::SideYLeft: + case GridPos::LineA: + case GridPos::LineE: { + const int ind[4][3][4]{ + {{ii_x_y_z + deltaPhi[i0] + deltaZ[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0], ind[0][0][2] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0], ind[0][1][2] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0], ind[0][2][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaZ[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0], ind[1][0][2] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0], ind[1][1][2] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0], ind[1][2][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaZ[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0], ind[2][0][2] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0], ind[2][1][2] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0], ind[2][2][2] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaZ[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0], ind[3][0][2] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0], ind[3][1][2] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0], ind[3][2][2] - deltaZ[i0]}}}; + + cVals[0] = extrapolation(mGridData[ind[0][0][0]], mGridData[ind[0][1][0]], mGridData[ind[0][2][0]]); + cVals[1] = extrapolation(mGridData[ind[0][0][1]], mGridData[ind[0][1][1]], mGridData[ind[0][2][1]]); + cVals[2] = extrapolation(mGridData[ind[0][0][2]], mGridData[ind[0][1][2]], mGridData[ind[0][2][2]]); + cVals[3] = extrapolation(mGridData[ind[0][0][3]], mGridData[ind[0][1][3]], mGridData[ind[0][2][3]]); + cVals[4] = mGridData[ind[0][0][0]]; + cVals[5] = mGridData[ind[0][0][1]]; + cVals[6] = mGridData[ind[0][0][2]]; + cVals[7] = mGridData[ind[0][0][3]]; + cVals[8] = mGridData[ind[0][1][0]]; + cVals[9] = mGridData[ind[0][1][1]]; + cVals[10] = mGridData[ind[0][1][2]]; + cVals[11] = mGridData[ind[0][1][3]]; + cVals[12] = mGridData[ind[0][2][0]]; + cVals[13] = mGridData[ind[0][2][1]]; + cVals[14] = mGridData[ind[0][2][2]]; + cVals[15] = mGridData[ind[0][2][3]]; + cVals[16] = extrapolation(mGridData[ind[1][0][0]], mGridData[ind[1][1][0]], mGridData[ind[1][2][0]]); + cVals[17] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][1][1]], mGridData[ind[1][2][1]]); + cVals[18] = extrapolation(mGridData[ind[1][0][2]], mGridData[ind[1][1][2]], mGridData[ind[1][2][2]]); + cVals[19] = extrapolation(mGridData[ind[1][0][3]], mGridData[ind[1][1][3]], mGridData[ind[1][2][3]]); + cVals[20] = mGridData[ind[1][0][0]]; + cVals[22] = mGridData[ind[1][0][2]]; + cVals[23] = mGridData[ind[1][0][3]]; + cVals[24] = mGridData[ind[1][1][0]]; + cVals[25] = mGridData[ind[1][1][1]]; + cVals[26] = mGridData[ind[1][1][2]]; + cVals[27] = mGridData[ind[1][1][3]]; + cVals[28] = mGridData[ind[1][2][0]]; + cVals[29] = mGridData[ind[1][2][1]]; + cVals[30] = mGridData[ind[1][2][2]]; + cVals[31] = mGridData[ind[1][2][3]]; + cVals[32] = extrapolation(mGridData[ind[2][0][0]], mGridData[ind[2][1][0]], mGridData[ind[2][2][0]]); + cVals[33] = extrapolation(mGridData[ind[2][0][1]], mGridData[ind[2][1][1]], mGridData[ind[2][2][1]]); + cVals[34] = extrapolation(mGridData[ind[2][0][2]], mGridData[ind[2][1][2]], mGridData[ind[2][2][2]]); + cVals[35] = extrapolation(mGridData[ind[2][0][3]], mGridData[ind[2][1][3]], mGridData[ind[2][2][3]]); + cVals[36] = mGridData[ind[2][0][0]]; + cVals[37] = mGridData[ind[2][0][1]]; + cVals[38] = mGridData[ind[2][0][2]]; + cVals[39] = mGridData[ind[2][0][3]]; + cVals[40] = mGridData[ind[2][1][0]]; + cVals[41] = mGridData[ind[2][1][1]]; + cVals[42] = mGridData[ind[2][1][2]]; + cVals[43] = mGridData[ind[2][1][3]]; + cVals[44] = mGridData[ind[2][2][0]]; + cVals[45] = mGridData[ind[2][2][1]]; + cVals[46] = mGridData[ind[2][2][2]]; + cVals[47] = mGridData[ind[2][2][3]]; + cVals[48] = extrapolation(mGridData[ind[3][0][0]], mGridData[ind[3][1][0]], mGridData[ind[3][2][0]]); + cVals[49] = extrapolation(mGridData[ind[3][0][1]], mGridData[ind[3][1][1]], mGridData[ind[3][2][1]]); + cVals[50] = extrapolation(mGridData[ind[3][0][2]], mGridData[ind[3][1][2]], mGridData[ind[3][2][2]]); + cVals[51] = extrapolation(mGridData[ind[3][0][3]], mGridData[ind[3][1][3]], mGridData[ind[3][2][3]]); + cVals[52] = mGridData[ind[3][0][0]]; + cVals[53] = mGridData[ind[3][0][1]]; + cVals[54] = mGridData[ind[3][0][2]]; + cVals[55] = mGridData[ind[3][0][3]]; + cVals[56] = mGridData[ind[3][1][0]]; + cVals[57] = mGridData[ind[3][1][1]]; + cVals[58] = mGridData[ind[3][1][2]]; + cVals[59] = mGridData[ind[3][1][3]]; + cVals[60] = mGridData[ind[3][2][0]]; + cVals[61] = mGridData[ind[3][2][1]]; + cVals[62] = mGridData[ind[3][2][2]]; + cVals[63] = mGridData[ind[3][2][3]]; + } break; + + case GridPos::SideXLeft: + case GridPos::LineC: + case GridPos::LineG: { + const int ind[4][4][3]{ + {{ii_x_y_z + deltaPhi[i0] + deltaR[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0]}, + {ind[0][2][0] - deltaR[i0], ind[0][3][0] - deltaZ[i0], ind[0][3][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaR[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0]}, + {ind[1][2][0] - deltaR[i0], ind[1][3][0] - deltaZ[i0], ind[1][3][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaR[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0]}, + {ind[2][2][0] - deltaR[i0], ind[2][3][0] - deltaZ[i0], ind[2][3][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaR[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0]}, + {ind[3][2][0] - deltaR[i0], ind[3][3][0] - deltaZ[i0], ind[3][3][1] - deltaZ[i0]}}}; + + cVals[0] = extrapolation(mGridData[ind[0][0][0]], mGridData[ind[0][0][1]], mGridData[ind[0][0][2]]); + cVals[1] = mGridData[ind[0][0][0]]; + cVals[2] = mGridData[ind[0][0][1]]; + cVals[3] = mGridData[ind[0][0][2]]; + cVals[4] = extrapolation(mGridData[ind[0][1][0]], mGridData[ind[0][1][1]], mGridData[ind[0][1][2]]); + cVals[5] = mGridData[ind[0][1][0]]; + cVals[6] = mGridData[ind[0][1][1]]; + cVals[7] = mGridData[ind[0][1][2]]; + cVals[8] = extrapolation(mGridData[ind[0][2][0]], mGridData[ind[0][2][1]], mGridData[ind[0][2][2]]); + cVals[9] = mGridData[ind[0][2][0]]; + cVals[10] = mGridData[ind[0][2][1]]; + cVals[11] = mGridData[ind[0][2][2]]; + cVals[12] = extrapolation(mGridData[ind[0][3][0]], mGridData[ind[0][3][1]], mGridData[ind[0][3][2]]); + cVals[13] = mGridData[ind[0][3][0]]; + cVals[14] = mGridData[ind[0][3][1]]; + cVals[15] = mGridData[ind[0][3][2]]; + cVals[16] = extrapolation(mGridData[ind[1][0][0]], mGridData[ind[1][0][1]], mGridData[ind[1][0][2]]); + cVals[17] = mGridData[ind[1][0][0]]; + cVals[18] = mGridData[ind[1][0][1]]; + cVals[19] = mGridData[ind[1][0][2]]; + cVals[20] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][1][1]], mGridData[ind[1][1][2]]); + cVals[22] = mGridData[ind[1][1][1]]; + cVals[23] = mGridData[ind[1][1][2]]; + cVals[24] = extrapolation(mGridData[ind[1][2][0]], mGridData[ind[1][2][1]], mGridData[ind[1][2][2]]); + cVals[25] = mGridData[ind[1][2][0]]; + cVals[26] = mGridData[ind[1][2][1]]; + cVals[27] = mGridData[ind[1][2][2]]; + cVals[28] = extrapolation(mGridData[ind[1][3][0]], mGridData[ind[1][3][1]], mGridData[ind[1][3][2]]); + cVals[29] = mGridData[ind[1][3][0]]; + cVals[30] = mGridData[ind[1][3][1]]; + cVals[31] = mGridData[ind[1][3][2]]; + cVals[32] = extrapolation(mGridData[ind[2][0][0]], mGridData[ind[2][0][1]], mGridData[ind[2][0][2]]); + cVals[33] = mGridData[ind[2][0][0]]; + cVals[34] = mGridData[ind[2][0][1]]; + cVals[35] = mGridData[ind[2][0][2]]; + cVals[36] = extrapolation(mGridData[ind[2][1][0]], mGridData[ind[2][1][1]], mGridData[ind[2][1][2]]); + cVals[37] = mGridData[ind[2][1][0]]; + cVals[38] = mGridData[ind[2][1][1]]; + cVals[39] = mGridData[ind[2][1][2]]; + cVals[40] = extrapolation(mGridData[ind[2][2][0]], mGridData[ind[2][2][1]], mGridData[ind[2][2][2]]); + cVals[41] = mGridData[ind[2][2][0]]; + cVals[42] = mGridData[ind[2][2][1]]; + cVals[43] = mGridData[ind[2][2][2]]; + cVals[44] = extrapolation(mGridData[ind[2][3][0]], mGridData[ind[2][3][1]], mGridData[ind[2][3][2]]); + cVals[45] = mGridData[ind[2][3][0]]; + cVals[46] = mGridData[ind[2][3][1]]; + cVals[47] = mGridData[ind[2][3][2]]; + cVals[48] = extrapolation(mGridData[ind[3][0][0]], mGridData[ind[3][0][1]], mGridData[ind[3][0][2]]); + cVals[49] = mGridData[ind[3][0][0]]; + cVals[50] = mGridData[ind[3][0][1]]; + cVals[51] = mGridData[ind[3][0][2]]; + cVals[52] = extrapolation(mGridData[ind[3][1][0]], mGridData[ind[3][1][1]], mGridData[ind[3][1][2]]); + cVals[53] = mGridData[ind[3][1][0]]; + cVals[54] = mGridData[ind[3][1][1]]; + cVals[55] = mGridData[ind[3][1][2]]; + cVals[56] = extrapolation(mGridData[ind[3][2][0]], mGridData[ind[3][2][1]], mGridData[ind[3][2][2]]); + cVals[57] = mGridData[ind[3][2][0]]; + cVals[58] = mGridData[ind[3][2][1]]; + cVals[59] = mGridData[ind[3][2][2]]; + cVals[60] = extrapolation(mGridData[ind[3][3][0]], mGridData[ind[3][3][1]], mGridData[ind[3][3][2]]); + cVals[61] = mGridData[ind[3][3][0]]; + cVals[62] = mGridData[ind[3][3][1]]; + cVals[63] = mGridData[ind[3][3][2]]; + } break; + + case GridPos::Edge0: + case GridPos::Edge4: + case GridPos::LineI: { + const int ind[4][3][3]{ + {{ii_x_y_z + deltaPhi[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0]}}, + {{ii_x_y_z, ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0]}}}; + + cVals[0] = extrapolation(mGridData[ind[0][0][0]], mGridData[ind[0][1][1]], mGridData[ind[0][2][2]]); + cVals[1] = extrapolation(mGridData[ind[0][0][0]], mGridData[ind[0][1][0]], mGridData[ind[0][2][0]]); + cVals[2] = extrapolation(mGridData[ind[0][0][1]], mGridData[ind[0][1][1]], mGridData[ind[0][2][1]]); + cVals[3] = extrapolation(mGridData[ind[0][0][2]], mGridData[ind[0][1][2]], mGridData[ind[0][2][2]]); + cVals[4] = extrapolation(mGridData[ind[0][0][0]], mGridData[ind[0][0][1]], mGridData[ind[0][0][2]]); + cVals[5] = mGridData[ind[0][0][0]]; + cVals[6] = mGridData[ind[0][0][1]]; + cVals[7] = mGridData[ind[0][0][2]]; + cVals[8] = extrapolation(mGridData[ind[0][1][0]], mGridData[ind[0][1][1]], mGridData[ind[0][1][2]]); + cVals[9] = mGridData[ind[0][1][0]]; + cVals[10] = mGridData[ind[0][1][1]]; + cVals[11] = mGridData[ind[0][1][2]]; + cVals[12] = extrapolation(mGridData[ind[0][2][0]], mGridData[ind[0][2][1]], mGridData[ind[0][2][2]]); + cVals[13] = mGridData[ind[0][2][0]]; + cVals[14] = mGridData[ind[0][2][1]]; + cVals[15] = mGridData[ind[0][2][2]]; + cVals[16] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][1][1]], mGridData[ind[1][2][2]]); + cVals[17] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][1][0]], mGridData[ind[1][2][0]]); + cVals[18] = extrapolation(mGridData[ind[1][0][1]], mGridData[ind[1][1][1]], mGridData[ind[1][2][1]]); + cVals[19] = extrapolation(mGridData[ind[1][0][2]], mGridData[ind[1][1][2]], mGridData[ind[1][2][2]]); + cVals[20] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][0][1]], mGridData[ind[1][0][2]]); + cVals[22] = mGridData[ind[1][0][1]]; + cVals[23] = mGridData[ind[1][0][2]]; + cVals[24] = extrapolation(mGridData[ind[1][1][0]], mGridData[ind[1][1][1]], mGridData[ind[1][1][2]]); + cVals[25] = mGridData[ind[1][1][0]]; + cVals[26] = mGridData[ind[1][1][1]]; + cVals[27] = mGridData[ind[1][1][2]]; + cVals[28] = extrapolation(mGridData[ind[1][2][0]], mGridData[ind[1][2][1]], mGridData[ind[1][2][2]]); + cVals[29] = mGridData[ind[1][2][0]]; + cVals[30] = mGridData[ind[1][2][1]]; + cVals[31] = mGridData[ind[1][2][2]]; + cVals[32] = extrapolation(mGridData[ind[2][0][0]], mGridData[ind[2][1][1]], mGridData[ind[2][2][2]]); + cVals[33] = extrapolation(mGridData[ind[2][0][0]], mGridData[ind[2][1][0]], mGridData[ind[2][2][0]]); + cVals[34] = extrapolation(mGridData[ind[2][0][1]], mGridData[ind[2][1][1]], mGridData[ind[2][2][1]]); + cVals[35] = extrapolation(mGridData[ind[2][0][2]], mGridData[ind[2][1][2]], mGridData[ind[2][2][2]]); + cVals[36] = extrapolation(mGridData[ind[2][0][0]], mGridData[ind[2][0][1]], mGridData[ind[2][0][2]]); + cVals[37] = mGridData[ind[2][0][0]]; + cVals[38] = mGridData[ind[2][0][1]]; + cVals[39] = mGridData[ind[2][0][2]]; + cVals[40] = extrapolation(mGridData[ind[2][1][0]], mGridData[ind[2][1][1]], mGridData[ind[2][1][2]]); + cVals[41] = mGridData[ind[2][1][0]]; + cVals[42] = mGridData[ind[2][1][1]]; + cVals[43] = mGridData[ind[2][1][2]]; + cVals[44] = extrapolation(mGridData[ind[2][2][0]], mGridData[ind[2][2][1]], mGridData[ind[2][2][2]]); + cVals[45] = mGridData[ind[2][2][0]]; + cVals[46] = mGridData[ind[2][2][1]]; + cVals[47] = mGridData[ind[2][2][2]]; + cVals[48] = extrapolation(mGridData[ind[3][0][0]], mGridData[ind[3][1][1]], mGridData[ind[3][2][2]]); + cVals[49] = extrapolation(mGridData[ind[3][0][0]], mGridData[ind[3][1][0]], mGridData[ind[3][2][0]]); + cVals[50] = extrapolation(mGridData[ind[3][0][1]], mGridData[ind[3][1][1]], mGridData[ind[3][2][1]]); + cVals[51] = extrapolation(mGridData[ind[3][0][2]], mGridData[ind[3][1][2]], mGridData[ind[3][2][2]]); + cVals[52] = extrapolation(mGridData[ind[3][0][0]], mGridData[ind[3][0][1]], mGridData[ind[3][0][2]]); + cVals[53] = mGridData[ind[3][0][0]]; + cVals[54] = mGridData[ind[3][0][1]]; + cVals[55] = mGridData[ind[3][0][2]]; + cVals[56] = extrapolation(mGridData[ind[3][1][0]], mGridData[ind[3][1][1]], mGridData[ind[3][1][2]]); + cVals[57] = mGridData[ind[3][1][0]]; + cVals[58] = mGridData[ind[3][1][1]]; + cVals[59] = mGridData[ind[3][1][2]]; + cVals[60] = extrapolation(mGridData[ind[3][2][0]], mGridData[ind[3][2][1]], mGridData[ind[3][2][2]]); + cVals[61] = mGridData[ind[3][2][0]]; + cVals[62] = mGridData[ind[3][2][1]]; + cVals[63] = mGridData[ind[3][2][2]]; + } break; + + case GridPos::Edge1: + case GridPos::Edge5: + case GridPos::LineJ: { + const int ind[4][3][3]{ + {{ii_x_y_z + deltaPhi[i0] + deltaZ[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaZ[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaZ[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaZ[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0]}}}; + + cVals[0] = extrapolation(mGridData[ind[0][0][0]], mGridData[ind[0][1][0]], mGridData[ind[0][2][0]]); + cVals[1] = extrapolation(mGridData[ind[0][0][1]], mGridData[ind[0][1][1]], mGridData[ind[0][2][1]]); + cVals[2] = extrapolation(mGridData[ind[0][0][1]], mGridData[ind[0][1][0]], mGridData[ind[0][2][0] + deltaZ[i0]]); + cVals[3] = extrapolation(mGridData[ind[0][0][2]], mGridData[ind[0][1][1]], mGridData[ind[0][2][0]]); + cVals[4] = mGridData[ind[0][0][0]]; + cVals[5] = mGridData[ind[0][0][1]]; + cVals[6] = mGridData[ind[0][0][2]]; + cVals[7] = extrapolation(mGridData[ind[0][0][2]], mGridData[ind[0][0][1]], mGridData[ind[0][0][0]]); + cVals[8] = mGridData[ind[0][1][0]]; + cVals[9] = mGridData[ind[0][1][1]]; + cVals[10] = mGridData[ind[0][1][2]]; + cVals[11] = extrapolation(mGridData[ind[0][1][2]], mGridData[ind[0][1][1]], mGridData[ind[0][1][0]]); + cVals[12] = mGridData[ind[0][2][0]]; + cVals[13] = mGridData[ind[0][2][1]]; + cVals[14] = mGridData[ind[0][2][2]]; + cVals[15] = extrapolation(mGridData[ind[0][2][2]], mGridData[ind[0][2][1]], mGridData[ind[0][2][0]]); + cVals[16] = extrapolation(mGridData[ind[1][0][0]], mGridData[ind[1][1][0]], mGridData[ind[1][2][0]]); + cVals[17] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][1][1]], mGridData[ind[1][2][1]]); + cVals[18] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][1][0]], mGridData[ind[1][2][0] + deltaZ[i0]]); + cVals[19] = extrapolation(mGridData[ind[1][0][2]], mGridData[ind[1][1][1]], mGridData[ind[1][2][0]]); + cVals[20] = mGridData[ind[1][0][0]]; + cVals[22] = mGridData[ind[1][0][2]]; + cVals[23] = extrapolation(mGridData[ind[1][0][2]], mGridData[ii_x_y_z], mGridData[ind[1][0][0]]); + cVals[24] = mGridData[ind[1][1][0]]; + cVals[25] = mGridData[ind[1][1][1]]; + cVals[26] = mGridData[ind[1][1][2]]; + cVals[27] = extrapolation(mGridData[ind[1][1][2]], mGridData[ind[1][1][1]], mGridData[ind[1][1][0]]); + cVals[28] = mGridData[ind[1][2][0]]; + cVals[29] = mGridData[ind[1][2][1]]; + cVals[30] = mGridData[ind[1][2][2]]; + cVals[31] = extrapolation(mGridData[ind[1][2][2]], mGridData[ind[1][2][1]], mGridData[ind[1][2][0]]); + cVals[32] = extrapolation(mGridData[ind[2][0][0]], mGridData[ind[2][1][0]], mGridData[ind[2][2][0]]); + cVals[33] = extrapolation(mGridData[ind[2][0][1]], mGridData[ind[2][1][1]], mGridData[ind[2][2][1]]); + cVals[34] = extrapolation(mGridData[ind[2][0][1]], mGridData[ind[2][1][0]], mGridData[ind[2][2][0] + deltaZ[i0]]); + cVals[35] = extrapolation(mGridData[ind[2][0][2]], mGridData[ind[2][1][1]], mGridData[ind[2][2][0]]); + cVals[36] = mGridData[ind[2][0][0]]; + cVals[37] = mGridData[ind[2][0][1]]; + cVals[38] = mGridData[ind[2][0][2]]; + cVals[39] = extrapolation(mGridData[ind[2][0][2]], mGridData[ind[2][0][1]], mGridData[ind[2][0][0]]); + cVals[40] = mGridData[ind[2][1][0]]; + cVals[41] = mGridData[ind[2][1][1]]; + cVals[42] = mGridData[ind[2][1][2]]; + cVals[43] = extrapolation(mGridData[ind[2][1][2]], mGridData[ind[2][1][1]], mGridData[ind[2][1][0]]); + cVals[44] = mGridData[ind[2][2][0]]; + cVals[45] = mGridData[ind[2][2][1]]; + cVals[46] = mGridData[ind[2][2][2]]; + cVals[47] = extrapolation(mGridData[ind[2][2][2]], mGridData[ind[2][2][1]], mGridData[ind[2][2][0]]); + cVals[48] = extrapolation(mGridData[ind[3][0][0]], mGridData[ind[3][1][0]], mGridData[ind[3][2][0]]); + cVals[49] = extrapolation(mGridData[ind[3][0][1]], mGridData[ind[3][1][1]], mGridData[ind[3][2][1]]); + cVals[50] = extrapolation(mGridData[ind[3][0][1]], mGridData[ind[3][1][0]], mGridData[ind[3][2][0] + deltaZ[i0]]); + cVals[51] = extrapolation(mGridData[ind[3][0][2]], mGridData[ind[3][1][1]], mGridData[ind[3][2][0]]); + cVals[52] = mGridData[ind[3][0][0]]; + cVals[53] = mGridData[ind[3][0][1]]; + cVals[54] = mGridData[ind[3][0][2]]; + cVals[55] = extrapolation(mGridData[ind[3][0][2]], mGridData[ind[3][0][1]], mGridData[ind[3][0][0]]); + cVals[56] = mGridData[ind[3][1][0]]; + cVals[57] = mGridData[ind[3][1][1]]; + cVals[58] = mGridData[ind[3][1][2]]; + cVals[59] = extrapolation(mGridData[ind[3][1][2]], mGridData[ind[3][1][1]], mGridData[ind[3][1][0]]); + cVals[60] = mGridData[ind[3][2][0]]; + cVals[61] = mGridData[ind[3][2][1]]; + cVals[62] = mGridData[ind[3][2][2]]; + cVals[63] = extrapolation(mGridData[ind[3][2][2]], mGridData[ind[3][2][1]], mGridData[ind[3][2][0]]); + } break; + + case GridPos::Edge2: + case GridPos::Edge6: + case GridPos::LineK: { + const int ind[4][3][3]{ + {{ii_x_y_z + deltaPhi[i0] + deltaR[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaR[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaR[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaR[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0]}}}; + + cVals[0] = extrapolation(mGridData[ind[0][0][0]], mGridData[ind[0][0][1]], mGridData[ind[0][0][2]]); + cVals[1] = mGridData[ind[0][0][0]]; + cVals[2] = mGridData[ind[0][0][1]]; + cVals[3] = mGridData[ind[0][0][2]]; + cVals[4] = extrapolation(mGridData[ind[0][1][0]], mGridData[ind[0][1][1]], mGridData[ind[0][1][2]]); + cVals[5] = mGridData[ind[0][1][0]]; + cVals[6] = mGridData[ind[0][1][1]]; + cVals[7] = mGridData[ind[0][1][2]]; + cVals[8] = extrapolation(mGridData[ind[0][1][0]], mGridData[ind[0][0][1]], mGridData[ind[0][0][2] + deltaR[i0]]); + cVals[9] = mGridData[ind[0][2][0]]; + cVals[10] = mGridData[ind[0][2][1]]; + cVals[11] = mGridData[ind[0][2][2]]; + cVals[12] = extrapolation(mGridData[ind[0][2][0]], mGridData[ind[0][1][1]], mGridData[ind[0][0][2]]); + cVals[13] = extrapolation(mGridData[ind[0][2][0]], mGridData[ind[0][1][0]], mGridData[ind[0][0][0]]); + cVals[14] = extrapolation(mGridData[ind[0][2][1]], mGridData[ind[0][1][1]], mGridData[ind[0][0][1]]); + cVals[15] = extrapolation(mGridData[ind[0][2][2]], mGridData[ind[0][1][2]], mGridData[ind[0][0][2]]); + cVals[16] = extrapolation(mGridData[ind[1][0][0]], mGridData[ind[1][0][1]], mGridData[ind[1][0][2]]); + cVals[17] = mGridData[ind[1][0][0]]; + cVals[18] = mGridData[ind[1][0][1]]; + cVals[19] = mGridData[ind[1][0][2]]; + cVals[20] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][1][1]], mGridData[ind[1][1][2]]); + cVals[22] = mGridData[ind[1][1][1]]; + cVals[23] = mGridData[ind[1][1][2]]; + cVals[24] = extrapolation(mGridData[ii_x_y_z], mGridData[ind[1][0][1]], mGridData[ind[1][0][2] + deltaR[i0]]); + cVals[25] = mGridData[ind[1][2][0]]; + cVals[26] = mGridData[ind[1][2][1]]; + cVals[27] = mGridData[ind[1][2][2]]; + cVals[28] = extrapolation(mGridData[ind[1][2][0]], mGridData[ind[1][1][1]], mGridData[ind[1][0][2]]); + cVals[29] = extrapolation(mGridData[ind[1][2][0]], mGridData[ii_x_y_z], mGridData[ind[1][0][0]]); + cVals[30] = extrapolation(mGridData[ind[1][2][1]], mGridData[ind[1][1][1]], mGridData[ind[1][0][1]]); + cVals[32] = extrapolation(mGridData[ind[2][0][0]], mGridData[ind[2][0][1]], mGridData[ind[2][0][2]]); + cVals[31] = extrapolation(mGridData[ind[1][2][2]], mGridData[ind[1][1][2]], mGridData[ind[1][0][2]]); + cVals[33] = mGridData[ind[2][0][0]]; + cVals[34] = mGridData[ind[2][0][1]]; + cVals[35] = mGridData[ind[2][0][2]]; + cVals[36] = extrapolation(mGridData[ind[2][1][0]], mGridData[ind[2][1][1]], mGridData[ind[2][1][2]]); + cVals[37] = mGridData[ind[2][1][0]]; + cVals[38] = mGridData[ind[2][1][1]]; + cVals[39] = mGridData[ind[2][1][2]]; + cVals[40] = extrapolation(mGridData[ind[2][1][0]], mGridData[ind[2][0][1]], mGridData[ind[2][0][2] + deltaR[i0]]); + cVals[41] = mGridData[ind[2][2][0]]; + cVals[42] = mGridData[ind[2][2][1]]; + cVals[43] = mGridData[ind[2][2][2]]; + cVals[44] = extrapolation(mGridData[ind[2][2][0]], mGridData[ind[2][1][1]], mGridData[ind[2][0][2]]); + cVals[45] = extrapolation(mGridData[ind[2][2][0]], mGridData[ind[2][1][0]], mGridData[ind[2][0][0]]); + cVals[46] = extrapolation(mGridData[ind[2][2][1]], mGridData[ind[2][1][1]], mGridData[ind[2][0][1]]); + cVals[47] = extrapolation(mGridData[ind[2][2][2]], mGridData[ind[2][1][2]], mGridData[ind[2][0][2]]); + cVals[48] = extrapolation(mGridData[ind[3][0][0]], mGridData[ind[3][0][1]], mGridData[ind[3][0][2]]); + cVals[49] = mGridData[ind[3][0][0]]; + cVals[50] = mGridData[ind[3][0][1]]; + cVals[51] = mGridData[ind[3][0][2]]; + cVals[52] = extrapolation(mGridData[ind[3][1][0]], mGridData[ind[3][1][1]], mGridData[ind[3][1][2]]); + cVals[53] = mGridData[ind[3][1][0]]; + cVals[54] = mGridData[ind[3][1][1]]; + cVals[55] = mGridData[ind[3][1][2]]; + cVals[56] = extrapolation(mGridData[ind[3][1][0]], mGridData[ind[3][0][1]], mGridData[ind[3][0][2] + deltaR[i0]]); + cVals[57] = mGridData[ind[3][2][0]]; + cVals[58] = mGridData[ind[3][2][1]]; + cVals[59] = mGridData[ind[3][2][2]]; + cVals[60] = extrapolation(mGridData[ind[3][2][0]], mGridData[ind[3][1][1]], mGridData[ind[3][0][2]]); + cVals[61] = extrapolation(mGridData[ind[3][2][0]], mGridData[ind[3][1][0]], mGridData[ind[3][0][0]]); + cVals[62] = extrapolation(mGridData[ind[3][2][1]], mGridData[ind[3][1][1]], mGridData[ind[3][0][1]]); + cVals[63] = extrapolation(mGridData[ind[3][2][2]], mGridData[ind[3][1][2]], mGridData[ind[3][0][2]]); + } break; + + case GridPos::Edge3: + case GridPos::Edge7: + case GridPos::LineL: { + const int ind[4][3][3]{ + {{ii_x_y_z + deltaPhi[i0] + deltaR[i0] + deltaZ[i0], ind[0][0][0] - deltaZ[i0], ind[0][0][1] - deltaZ[i0]}, + {ind[0][0][0] - deltaR[i0], ind[0][1][0] - deltaZ[i0], ind[0][1][1] - deltaZ[i0]}, + {ind[0][1][0] - deltaR[i0], ind[0][2][0] - deltaZ[i0], ind[0][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaR[i0] + deltaZ[i0], ind[1][0][0] - deltaZ[i0], ind[1][0][1] - deltaZ[i0]}, + {ind[1][0][0] - deltaR[i0], ind[1][1][0] - deltaZ[i0], ind[1][1][1] - deltaZ[i0]}, + {ind[1][1][0] - deltaR[i0], ind[1][2][0] - deltaZ[i0], ind[1][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i1] + deltaR[i0] + deltaZ[i0], ind[2][0][0] - deltaZ[i0], ind[2][0][1] - deltaZ[i0]}, + {ind[2][0][0] - deltaR[i0], ind[2][1][0] - deltaZ[i0], ind[2][1][1] - deltaZ[i0]}, + {ind[2][1][0] - deltaR[i0], ind[2][2][0] - deltaZ[i0], ind[2][2][1] - deltaZ[i0]}}, + {{ii_x_y_z + deltaPhi[i2] + deltaR[i0] + deltaZ[i0], ind[3][0][0] - deltaZ[i0], ind[3][0][1] - deltaZ[i0]}, + {ind[3][0][0] - deltaR[i0], ind[3][1][0] - deltaZ[i0], ind[3][1][1] - deltaZ[i0]}, + {ind[3][1][0] - deltaR[i0], ind[3][2][0] - deltaZ[i0], ind[3][2][1] - deltaZ[i0]}}}; + + cVals[0] = mGridData[ind[0][0][0]]; + cVals[1] = mGridData[ind[0][0][1]]; + cVals[2] = mGridData[ind[0][0][2]]; + cVals[3] = extrapolation(mGridData[ind[0][0][2]], mGridData[ind[0][0][1]], mGridData[ind[0][0][0]]); + cVals[4] = mGridData[ind[0][1][0]]; + cVals[5] = mGridData[ind[0][1][1]]; + cVals[6] = mGridData[ind[0][1][2]]; + cVals[7] = extrapolation(mGridData[ind[0][1][2]], mGridData[ind[0][1][1]], mGridData[ind[0][1][0]]); + cVals[8] = mGridData[ind[0][2][0]]; + cVals[9] = mGridData[ind[0][2][1]]; + cVals[10] = mGridData[ind[0][2][2]]; + cVals[11] = extrapolation(mGridData[ind[0][2][2]], mGridData[ind[0][2][1]], mGridData[ind[0][2][0]]); + cVals[12] = extrapolation(mGridData[ind[0][2][0]], mGridData[ind[0][1][0]], mGridData[ind[0][0][0]]); + cVals[13] = extrapolation(mGridData[ind[0][2][1]], mGridData[ind[0][1][1]], mGridData[ind[0][0][1]]); + cVals[14] = extrapolation(mGridData[ind[0][2][2]], mGridData[ind[0][1][2]], mGridData[ind[0][0][2]]); + cVals[15] = extrapolation(mGridData[ind[0][2][2]], mGridData[ind[0][1][1]], mGridData[ind[0][0][0]]); + cVals[16] = mGridData[ind[1][0][0]]; + cVals[17] = mGridData[ind[1][0][1]]; + cVals[18] = mGridData[ind[1][0][2]]; + cVals[19] = extrapolation(mGridData[ind[1][0][2]], mGridData[ind[1][0][1]], mGridData[ind[1][0][0]]); + cVals[20] = mGridData[ind[1][1][0]]; + cVals[22] = mGridData[ind[1][1][2]]; + cVals[23] = extrapolation(mGridData[ind[1][1][2]], mGridData[ii_x_y_z], mGridData[ind[1][1][0]]); + cVals[24] = mGridData[ind[1][2][0]]; + cVals[25] = mGridData[ind[1][2][1]]; + cVals[26] = mGridData[ind[1][2][2]]; + cVals[27] = extrapolation(mGridData[ind[1][2][2]], mGridData[ind[1][2][1]], mGridData[ind[1][2][0]]); + cVals[28] = extrapolation(mGridData[ind[1][2][0]], mGridData[ind[1][1][0]], mGridData[ind[1][0][0]]); + cVals[29] = extrapolation(mGridData[ind[1][2][1]], mGridData[ii_x_y_z], mGridData[ind[1][0][1]]); + cVals[30] = extrapolation(mGridData[ind[1][2][2]], mGridData[ind[1][1][2]], mGridData[ind[1][0][2]]); + cVals[31] = extrapolation(mGridData[ind[1][2][2]], mGridData[ind[1][1][1]], mGridData[ind[1][0][0]]); + cVals[32] = mGridData[ind[2][0][0]]; + cVals[33] = mGridData[ind[2][0][1]]; + cVals[34] = mGridData[ind[2][0][2]]; + cVals[35] = extrapolation(mGridData[ind[2][0][2]], mGridData[ind[2][0][1]], mGridData[ind[2][0][0]]); + cVals[36] = mGridData[ind[2][1][0]]; + cVals[37] = mGridData[ind[2][1][1]]; + cVals[38] = mGridData[ind[2][1][2]]; + cVals[39] = extrapolation(mGridData[ind[2][1][2]], mGridData[ind[2][1][1]], mGridData[ind[2][1][0]]); + cVals[40] = mGridData[ind[2][2][0]]; + cVals[41] = mGridData[ind[2][2][1]]; + cVals[42] = mGridData[ind[2][2][2]]; + cVals[43] = extrapolation(mGridData[ind[2][2][2]], mGridData[ind[2][2][1]], mGridData[ind[2][2][0]]); + cVals[44] = extrapolation(mGridData[ind[2][2][0]], mGridData[ind[2][1][0]], mGridData[ind[2][0][0]]); + cVals[45] = extrapolation(mGridData[ind[2][2][1]], mGridData[ind[2][1][1]], mGridData[ind[2][0][1]]); + cVals[46] = extrapolation(mGridData[ind[2][2][2]], mGridData[ind[2][1][2]], mGridData[ind[2][0][2]]); + cVals[47] = extrapolation(mGridData[ind[2][2][2]], mGridData[ind[2][1][1]], mGridData[ind[2][0][0]]); + cVals[48] = mGridData[ind[3][0][0]]; + cVals[49] = mGridData[ind[3][0][1]]; + cVals[50] = mGridData[ind[3][0][2]]; + cVals[51] = extrapolation(mGridData[ind[3][0][2]], mGridData[ind[3][0][1]], mGridData[ind[3][0][0]]); + cVals[52] = mGridData[ind[3][1][0]]; + cVals[53] = mGridData[ind[3][1][1]]; + cVals[54] = mGridData[ind[3][1][2]]; + cVals[55] = extrapolation(mGridData[ind[3][1][2]], mGridData[ind[3][1][1]], mGridData[ind[3][1][0]]); + cVals[56] = mGridData[ind[3][2][0]]; + cVals[57] = mGridData[ind[3][2][1]]; + cVals[58] = mGridData[ind[3][2][2]]; + cVals[59] = extrapolation(mGridData[ind[3][2][2]], mGridData[ind[3][2][1]], mGridData[ind[3][2][0]]); + cVals[60] = extrapolation(mGridData[ind[3][2][0]], mGridData[ind[3][1][0]], mGridData[ind[3][0][0]]); + cVals[61] = extrapolation(mGridData[ind[3][2][1]], mGridData[ind[3][1][1]], mGridData[ind[3][0][1]]); + cVals[62] = extrapolation(mGridData[ind[3][2][2]], mGridData[ind[3][1][2]], mGridData[ind[3][0][2]]); + cVals[63] = extrapolation(mGridData[ind[3][2][2]], mGridData[ind[3][1][1]], mGridData[ind[3][0][0]]); + } break; + } +} + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector.h new file mode 100644 index 0000000000000..a6862291d84dc --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector.h @@ -0,0 +1,173 @@ +// 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 matrix.h +/// \brief Definition of Vector and Matrix class +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> + +#ifndef ALICEO2_TPC_VECTOR_H_ +#define ALICEO2_TPC_VECTOR_H_ + +#include <Vc/Vc> + +namespace o2 +{ +namespace tpc +{ +template <typename DataT = float, size_t N = 64> +class Matrix +{ + using VDataT = Vc::Vector<DataT>; + + public: + /// constructor + /// \param dataMatrix pointer to the data + Matrix(const Vc::Memory<VDataT, N>* dataMatrix) : mDataMatrix(dataMatrix) {} + + const Vc::Memory<VDataT, N>& operator[](size_t i) const { return mDataMatrix[i]; } + + private: + const Vc::Memory<VDataT, N>* mDataMatrix{}; +}; + +template <typename DataT = float, size_t N = 64> +class Vector +{ + using VDataT = Vc::Vector<DataT>; + + public: + /// default constructor + Vector() = default; + + /// constructor + /// \param dataVector data which is assigned to the vector + Vector(const Vc::Memory<VDataT, N>& dataVector) : mDataVector(dataVector) {} + + /// operator access + const DataT operator[](size_t i) const { return mDataVector.scalar(i); } + DataT& operator[](size_t i) { return mDataVector.scalar(i); } + + /// sets the vector with index j + void setVector(const size_t j, const VDataT& vector) { mDataVector.vector(j) = vector; } + + /// \return returns the vector with index j + const VDataT getVector(const size_t j) const { return mDataVector.vector(j); } + + /// \return returns the number of Vc::Vector<DataT> stored in the Vector + size_t getvectorsCount() const { return mDataVector.vectorsCount(); } + + /// \return returns the number of entries stored in the Vector + size_t getentriesCount() const { return mDataVector.entriesCount(); } + + private: + // storage for the data + Vc::Memory<VDataT, N> mDataVector{}; +}; + +template <typename DataT, size_t N> +inline Vector<DataT, N> operator*(const Matrix<DataT, N>& a, const Vector<DataT, N>& b) +{ + using V = Vc::Vector<DataT>; + // resulting vector c + Vector<DataT, N> c; + for (size_t i = 0; i < N; ++i) { + V c_ij{}; + for (size_t j = 0; j < a[i].vectorsCount(); ++j) { + c_ij += a[i].vector(j) * b.getVector(j); + } + c[i] = c_ij.sum(); + } + return c; +} + +template <typename DataT, size_t N> +inline Vector<DataT, N> floor(const Vector<DataT, N>& a) +{ + Vector<DataT, N> c; + for (size_t j = 0; j < a.getvectorsCount(); ++j) { + c.setVector(j, Vc::floor(a.getVector(j))); + } + return c; +} + +template <typename DataT, size_t N> +inline Vector<DataT, N> operator-(const Vector<DataT, N>& a, const Vector<DataT, N>& b) +{ + // resulting matrix c + Vector<DataT, N> c; + for (size_t j = 0; j < a.getvectorsCount(); ++j) { + c.setVector(j, a.getVector(j) - b.getVector(j)); + } + return c; +} + +template <typename DataT, size_t N> +inline Vector<DataT, N> operator+(const Vector<DataT, N>& a, const Vector<DataT, N>& b) +{ + // resulting matrix c + Vector<DataT, N> c; + for (size_t j = 0; j < a.getvectorsCount(); ++j) { + c.setVector(j, a.getVector(j) + b.getVector(j)); + } + return c; +} + +template <typename DataT, size_t N> +inline Vector<DataT, N> operator*(const DataT a, const Vector<DataT, N>& b) +{ + // resulting matrix c + Vector<DataT, N> c; + for (size_t j = 0; j < b.getvectorsCount(); ++j) { + c.setVector(j, a * b.getVector(j)); + } + return c; +} + +// compute the sum of one Vector +template <typename DataT, size_t N> +inline DataT sum(const Vector<DataT, N>& a) +{ + // resulting matrix c + Vc::Vector<DataT> b = a.getVector(0); + for (size_t j = 1; j < a.getvectorsCount(); ++j) { + b += a.getVector(j); + } + return b.sum(); +} + +// multiply each row from a vector with the row from a second vector +template <typename DataT, size_t N> +inline Vector<DataT, N> operator*(const Vector<DataT, N>& a, const Vector<DataT, N>& b) +{ + // resulting matrix c + Vector<DataT, N> c{}; + for (size_t j = 0; j < a.getvectorsCount(); ++j) { + c.setVector(j, a.getVector(j) * b.getVector(j)); + } + return c; +} + +// check if all elements are equal +template <typename DataT, size_t N> +inline bool operator==(const Vector<DataT, N>& a, const Vector<DataT, N>& b) +{ + for (size_t j = 0; j < a.getvectorsCount(); ++j) { + if (any_of(a.getVector(j) != b.getVector(j))) { + return false; + } + } + return true; +} + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector3D.h b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector3D.h new file mode 100644 index 0000000000000..bd00405f1c9a7 --- /dev/null +++ b/Detectors/TPC/spacecharge/include/TPCSpaceCharge/Vector3D.h @@ -0,0 +1,109 @@ +// 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 Vector3D.h +/// \brief this is a simple 3D-matrix class with the possibility to resize the dimensions +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Oct 23, 2020 + +#ifndef ALICEO2_TPC_VECTOR3D_H_ +#define ALICEO2_TPC_VECTOR3D_H_ + +namespace o2 +{ +namespace tpc +{ + +/// this is a simple vector class which is used in the poisson solver class + +/// \tparam DataT the data type of the mStorage which is used during the calculations +template <typename DataT = double> +class Vector3D +{ + public: + /// Constructor for a tricubic interpolator + /// \param nr number of data points in r directions + /// \param nz number of data points in r directions + /// \param nphi number of data points in r directions + Vector3D(const unsigned int nr, const unsigned int nz, const unsigned int nphi) : mNr{nr}, mNz{nz}, mNphi{nphi}, mStorage{nr * nz * nphi} {}; + + /// default constructor + Vector3D() = default; + + /// operator to set the values + DataT& operator()(const unsigned int iR, const unsigned int iZ, const unsigned int iPhi) + { + return mStorage[getIndex(iR, iZ, iPhi)]; + } + + /// operator to read the values + const DataT& operator()(const unsigned int iR, const unsigned int iZ, const unsigned int iPhi) const + { + return mStorage[getIndex(iR, iZ, iPhi)]; + } + + /// operator to directly access the values + DataT& operator[](const unsigned int index) + { + return mStorage[index]; + } + + const DataT& operator[](const unsigned int index) const + { + return mStorage[index]; + } + + /// \param iR index in r direction + /// \param iZ index in z direction + /// \param iPhi index in phi direction + /// \return returns the index for given indices + int getIndex(const unsigned int iR, const unsigned int iZ, const unsigned int iPhi) const + { + return iR + mNr * (iZ + mNz * iPhi); + } + + /// resize the vector + /// \param nr number of data points in r directions + /// \param nz number of data points in r directions + /// \param nphi number of data points in r directions + void resize(const unsigned int nr, const unsigned int nz, const unsigned int nphi) + { + mNr = nr; + mNz = nz; + mNphi = nphi; + mStorage.resize(nr * nz * nphi); + } + + const auto& data() const { return mStorage; } + auto& data() { return mStorage; } + + unsigned int getNr() const { return mNr; } ///< get number of data points in r direction + unsigned int getNz() const { return mNz; } ///< get number of data points in z direction + unsigned int getNphi() const { return mNphi; } ///< get number of data points in phi direction + unsigned int size() const { return mStorage.size; } ///< get number of data points + + auto begin() const { return mStorage.begin(); } + auto begin() { return mStorage.begin(); } + + auto end() const { return mStorage.end(); } + auto end() { return mStorage.end(); } + + private: + unsigned int mNr{}; ///< number of data points in r direction + unsigned int mNz{}; ///< number of data points in z direction + unsigned int mNphi{}; ///< number of data points in phi direction + std::vector<DataT> mStorage{}; ///< vector containing the data +}; + +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/spacecharge/macro/calculateDistortionsCorrections.C b/Detectors/TPC/spacecharge/macro/calculateDistortionsCorrections.C new file mode 100644 index 0000000000000..05a6050a79dda --- /dev/null +++ b/Detectors/TPC/spacecharge/macro/calculateDistortionsCorrections.C @@ -0,0 +1,365 @@ +// g++ -o spacecharge ~/alice/O2/Detectors/TPC/spacecharge/macro/calculateDistortionsCorrections.C -I ~/alice/sw/osx_x86-64/FairLogger/latest/include -L ~/alice/sw/osx_x86-64/FairLogger/latest/lib -I$O2_ROOT/include -L$O2_ROOT/lib -lO2TPCSpacecharge -lO2CommonUtils -std=c++17 -I$ROOTSYS/include -L$ROOTSYS/lib -lCore -L$VC_ROOT/lib -lVc -I$VC_ROOT/include -Xpreprocessor -fopenmp -I/usr/local/include -L/usr/local/lib -lomp -O3 -ffast-math -lFairLogger -lRIO +#include "TPCSpaceCharge/SpaceCharge.h" +#include <iostream> +#include <chrono> +#include <array> +#include "CommonUtils/TreeStreamRedirector.h" + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void calculateDistortionsAnalytical(const int globalEFieldTypeAna = 1, const int globalDistTypeAna = 1, const int eFieldTypeAna = 1, const int usePoissonSolverAna = 1, const int nSteps = 1, const int simpsonIterations = 3, const int nThreads = -1); + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void calculateDistortionsFromHist(const char* path, const char* histoName, const int sides, const int globalEFieldType = 1, const int globalDistType = 1, const int nSteps = 1, const int simpsonIterations = 3, const int nThreads = -1); + +/// \param gridType granularity of the grid +/// \param globalEFieldTypeAna setting for global distortions/corrections: 0: using electric field, 1: using local dis/corr interpolator +/// \param globalDistTypeAna setting for global distortions: 0: standard method, 1: interpolation of global corrections +/// \param eFieldTypeAna setting for electrc field: 0: analytical formula, 1: tricubic interpolator +/// \param usePoissonSolverAna setting for use poisson solver or analytical formula for potential: 0: analytical formula, 1: poisson solver +/// \param nSteps number of which are used for calculation of distortions/corrections per z-bin +/// \param simpsonIterations number of iterations used in the simpson intergration +/// \param nThreads number of threads which are used (if the value is -1 all threads should be used) +void calcDistAna(const int gridType = 0, const int globalEFieldTypeAna = 1, const int globalDistTypeAna = 1, const int eFieldTypeAna = 1, const int usePoissonSolverAna = 1, const int nSteps = 1, const int simpsonIterations = 3, const int nThreads = -1) +{ + if (gridType == 0) { + calculateDistortionsAnalytical<double, 129, 129, 180>(globalEFieldTypeAna, globalDistTypeAna, eFieldTypeAna, usePoissonSolverAna, nSteps, simpsonIterations, nThreads); + } else if (gridType == 1) { + calculateDistortionsAnalytical<double, 65, 65, 180>(globalEFieldTypeAna, globalDistTypeAna, eFieldTypeAna, usePoissonSolverAna, nSteps, simpsonIterations, nThreads); + } else if (gridType == 2) { + calculateDistortionsAnalytical<double, 33, 33, 180>(globalEFieldTypeAna, globalDistTypeAna, eFieldTypeAna, usePoissonSolverAna, nSteps, simpsonIterations, nThreads); + } else if (gridType == 3) { + calculateDistortionsAnalytical<double, 17, 17, 90>(globalEFieldTypeAna, globalDistTypeAna, eFieldTypeAna, usePoissonSolverAna, nSteps, simpsonIterations, nThreads); + } else if (gridType == 4) { + calculateDistortionsAnalytical<double, 257, 257, 180>(globalEFieldTypeAna, globalDistTypeAna, eFieldTypeAna, usePoissonSolverAna, nSteps, simpsonIterations, nThreads); + } +} + +/// \param path path to the root file containing the 3D density histogram +/// \param histoName name of the histogram in the root file +/// \param gridType granularity of the grid +/// \param sides setting which sides will be processed: 0: A- and C-Side, 1: A-Side, 2: C-Side +/// \param globalEFieldType setting for global distortions/corrections: 0: using electric field, 1: using local dis/corr interpolator +/// \param globalDistType setting for global distortions: 0: standard method, 1: interpolation of global corrections +/// \param nSteps number of which are used for calculation of distortions/corrections per z-bin +/// \param simpsonIterations number of iterations used in the simpson intergration +/// \param nThreads number of threads which are used (if the value is -1 all threads should be used) +void calcDistFromHist(const char* path, const char* histoName, const int gridType = 0, const int sides = 0, const int globalEFieldType = 1, const int globalDistType = 1, const int nSteps = 1, const int simpsonIterations = 3, const int nThreads = -1) +{ + if (gridType == 0) { + calculateDistortionsFromHist<double, 129, 129, 180>(path, histoName, sides, globalEFieldType, globalDistType, nSteps, simpsonIterations, nThreads); + } else if (gridType == 1) { + calculateDistortionsFromHist<double, 65, 65, 180>(path, histoName, sides, globalEFieldType, globalDistType, nSteps, simpsonIterations, nThreads); + } else if (gridType == 2) { + calculateDistortionsFromHist<double, 33, 33, 180>(path, histoName, sides, globalEFieldType, globalDistType, nSteps, simpsonIterations, nThreads); + } else if (gridType == 3) { + calculateDistortionsFromHist<double, 17, 17, 90>(path, histoName, sides, globalEFieldType, globalDistType, nSteps, simpsonIterations, nThreads); + } else if (gridType == 4) { + calculateDistortionsFromHist<double, 257, 257, 180>(path, histoName, sides, globalEFieldType, globalDistType, nSteps, simpsonIterations, nThreads); + } else if (gridType == 5) { + calculateDistortionsFromHist<double, 257, 257, 360>(path, histoName, sides, globalEFieldType, globalDistType, nSteps, simpsonIterations, nThreads); + } +} + +/// \param spaceChargeCalc SpaceCharge object in which the calculations are performed +/// \param anaFields struct containing the analytical electric fields potential, space charge +/// \param fileOut output file where the calculated values are stored +/// \param side side of the TPC +/// \param globalEFieldType settings for global distortions/corrections: 0: using electric field for calculation of global distortions/corrections, 1: using local dis/corr interpolator for calculation of global distortions/corrections +/// \param globalDistType settings for global distortions: 0: standard method (start calculation of global distortion at each voxel in the tpc and follow electron drift to readout -slow-), 1: interpolation of global corrections (use the global corrections to apply an iterative approach to obtain the global distortions -fast-) +/// \param eFieldType setting for the electric field: 0: use analytical formula for the eletrical field for all calculations, 1: use the tricubic interpolator for the electric field +/// \param usePoissonSolver use poisson solver to calculate the potential or get the potential from the analytical formula 0: use analytical formula, 1: use poisson solver to calculate the potential (also calculates Efields using the obtained potential) +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void calculateDistortionsCorrectionsAnalytical(o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>& spaceChargeCalc, o2::tpc::AnalyticalFields<DataT> anaFields, const int globalEFieldType, const int eFieldType, const int globalDistType, const int usePoissonSolver) +{ + using timer = std::chrono::high_resolution_clock; + + std::cout << "====== STARTING CALCULATIION OF DISTORTIONS AND CORRECTIONS BY USING A ANALYTICAL FORMULA AS INPUT ======" << std::endl; + std::cout << "bins in z: " << Nz << std::endl; + std::cout << "bins in r: " << Nr << std::endl; + std::cout << "bins in phi: " << Nphi << std::endl; + + const std::array<std::string, 2> sGlobalType{"Electric fields", "local distortion/correction interpolator"}; + std::cout << "calculation of global distortions and corrections are performed by using: " << sGlobalType[globalEFieldType] << std::endl; + + const std::array<std::string, 2> sGlobalDistType{"Standard method", "interpolation of global corrections"}; + std::cout << "calculation of global distortions performed by following method: " << sGlobalDistType[globalDistType] << std::endl; + + const std::array<std::string, 2> sEfieldType{"analytical formula", "tricubic interpolator"}; + std::cout << "Using the E-fields from: " << sEfieldType[eFieldType] << std::endl; + + const std::array<std::string, 2> sUsePoissonSolver{"analytical formula", "poisson solver"}; + std::cout << "Using the Potential from: " << sUsePoissonSolver[usePoissonSolver] << std::endl; + std::cout << std::endl; + + const o2::tpc::Side side = anaFields.getSide(); + spaceChargeCalc.setChargeDensityFromFormula(anaFields); + + auto startTotal = timer::now(); + + if (usePoissonSolver == 1) { + spaceChargeCalc.setPotentialBoundaryFromFormula(anaFields); + auto start = timer::now(); + spaceChargeCalc.poissonSolver(side); + auto stop = timer::now(); + std::chrono::duration<float> time = stop - start; + std::cout << "poissonSolver: " << time.count() << std::endl; + } else { + spaceChargeCalc.setPotentialFromFormula(anaFields); + } + + if (usePoissonSolver == 1) { + auto start = timer::now(); + spaceChargeCalc.calcEField(side); + auto stop = timer::now(); + std::chrono::duration<float> time = stop - start; + std::cout << "electric field calculation: " << time.count() << std::endl; + } else { + spaceChargeCalc.setEFieldFromFormula(anaFields); + } + + const auto numEFields = spaceChargeCalc.getElectricFieldsInterpolator(side); + auto start = timer::now(); + const auto dist = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>::Type::Distortions; + (eFieldType == 1) ? spaceChargeCalc.calcLocalDistortionsCorrections(dist, numEFields) : spaceChargeCalc.calcLocalDistortionsCorrections(dist, anaFields); // local distortion calculation + auto stop = timer::now(); + std::chrono::duration<float> time = stop - start; + std::cout << "local distortions analytical: " << time.count() << std::endl; + + start = timer::now(); + const auto corr = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>::Type::Corrections; + (eFieldType == 1) ? spaceChargeCalc.calcLocalDistortionsCorrections(corr, numEFields) : spaceChargeCalc.calcLocalDistortionsCorrections(corr, anaFields); // local correction calculation + stop = timer::now(); + time = stop - start; + std::cout << "local corrections analytical: " << time.count() << std::endl; + + start = timer::now(); + const auto lCorrInterpolator = spaceChargeCalc.getLocalCorrInterpolator(side); + if (globalEFieldType == 1) { + spaceChargeCalc.calcGlobalCorrections(lCorrInterpolator); + } else if (eFieldType == 1) { + spaceChargeCalc.calcGlobalCorrections(numEFields); + } else { + spaceChargeCalc.calcGlobalCorrections(anaFields); + } + + stop = timer::now(); + time = stop - start; + std::cout << "global corrections analytical: " << time.count() << std::endl; + + start = timer::now(); + const auto lDistInterpolator = spaceChargeCalc.getLocalDistInterpolator(side); + if (globalDistType == 0) { + if (globalEFieldType == 1) { + spaceChargeCalc.calcGlobalDistortions(lDistInterpolator); + } else if (eFieldType == 1) { + spaceChargeCalc.calcGlobalDistortions(numEFields); + } else { + spaceChargeCalc.calcGlobalDistortions(anaFields); + } + } else { + const auto globalCorrInterpolator = spaceChargeCalc.getGlobalCorrInterpolator(side); + spaceChargeCalc.calcGlobalDistWithGlobalCorrIterative(globalCorrInterpolator); + } + stop = timer::now(); + time = stop - start; + std::cout << "global distortions analytical: " << time.count() << std::endl; + + auto stopTotal = timer::now(); + time = stopTotal - startTotal; + std::cout << "====== everything is done. Total Time: " << time.count() << std::endl; + std::cout << std::endl; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void writeToTree(o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>& spaceCharge3D, o2::utils::TreeStreamRedirector& pcstream, const o2::tpc::Side side) +{ + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + for (size_t iR = 0; iR < Nr; ++iR) { + for (size_t iZ = 0; iZ < Nz; ++iZ) { + auto ldistR = spaceCharge3D.getLocalDistR(iZ, iR, iPhi, side); + auto ldistZ = spaceCharge3D.getLocalDistZ(iZ, iR, iPhi, side); + auto ldistRPhi = spaceCharge3D.getLocalDistRPhi(iZ, iR, iPhi, side); + auto lcorrR = spaceCharge3D.getLocalCorrR(iZ, iR, iPhi, side); + auto lcorrZ = spaceCharge3D.getLocalCorrZ(iZ, iR, iPhi, side); + auto lcorrRPhi = spaceCharge3D.getLocalCorrRPhi(iZ, iR, iPhi, side); + + auto distR = spaceCharge3D.getGlobalDistR(iZ, iR, iPhi, side); + auto distZ = spaceCharge3D.getGlobalDistZ(iZ, iR, iPhi, side); + auto distRPhi = spaceCharge3D.getGlobalDistRPhi(iZ, iR, iPhi, side); + auto corrR = spaceCharge3D.getGlobalCorrR(iZ, iR, iPhi, side); + auto corrZ = spaceCharge3D.getGlobalCorrZ(iZ, iR, iPhi, side); + auto corrRPhi = spaceCharge3D.getGlobalCorrRPhi(iZ, iR, iPhi, side); + + // distort then correct + auto radius = spaceCharge3D.getRVertex(iR, side); + auto z = spaceCharge3D.getZVertex(iZ, side); + auto phi = spaceCharge3D.getPhiVertex(iPhi, side); + DataT corrRDistPoint{}; + DataT corrZDistPoint{}; + DataT corrRPhiDistPoint{}; + + const DataT zDistorted = z + distZ; + const DataT radiusDistorted = radius + distR; + const DataT phiDistorted = spaceCharge3D.regulatePhi(phi + distRPhi / radius, side); + spaceCharge3D.getCorrectionsCyl(zDistorted, radiusDistorted, phiDistorted, side, corrZDistPoint, corrRDistPoint, corrRPhiDistPoint); + corrRPhiDistPoint *= radius / radiusDistorted; + + auto eZ = spaceCharge3D.getEz(iZ, iR, iPhi, side); + auto eR = spaceCharge3D.getEr(iZ, iR, iPhi, side); + auto ePhi = spaceCharge3D.getEphi(iZ, iR, iPhi, side); + auto pot = spaceCharge3D.getPotential(iZ, iR, iPhi, side); + auto charge = spaceCharge3D.getDensity(iZ, iR, iPhi, side); + + auto xPos = spaceCharge3D.getXFromPolar(radius, phi); + auto yPos = spaceCharge3D.getYFromPolar(radius, phi); + + int nr = Nr; + int nz = Nz; + int nphi = Nphi; + int iSide = side; + + pcstream << "distortions" + /// numer of bins + << "nR=" << nr + << "nPhi=" << nphi + << "nZ=" << nz + // bin indices + << "ir=" << iR + << "iz=" << iZ + << "iphi=" << iPhi + // coordinates + << "r=" << radius + << "z=" << z + << "x=" << xPos + << "y=" << yPos + << "phi=" << phi + // local distortions + << "ldistR=" << ldistR + << "ldistZ=" << ldistZ + << "ldistRPhi=" << ldistRPhi + // local corrections + << "lcorrR=" << lcorrR + << "lcorrZ=" << lcorrZ + << "lcorrRPhi=" << lcorrRPhi + // global distortions + << "distR=" << distR + << "distZ=" << distZ + << "distRPhi=" << distRPhi + // global corrections + << "corrR=" << corrR + << "corrZ=" << corrZ + << "corrRPhi=" << corrRPhi + // correction after distortion applied (test for consistency) + << "corrRDistortedPoint=" << corrRDistPoint + << "corrRPhiDistortedPoint=" << corrRPhiDistPoint + << "corrZDistortedPoint=" << corrZDistPoint + // electric fields etc. + << "Er=" << eR + << "Ez=" << eZ + << "Ephi=" << ePhi + << "potential=" << pot + << "charge=" << charge + << "side=" << iSide + << "\n"; + } + } + } +} + +/// \param globalEFieldTypeAna setting for global distortions/corrections: 0: using electric field, 1: using local dis/corr interpolator +/// \param globalDistTypeAna setting for global distortions: 0: standard method, 1: interpolation of global corrections +/// \param eFieldTypeAna setting for electrc field: 0: analytical formula, 1: tricubic interpolator +/// \param usePoissonSolverAna setting for use poisson solver or analytical formula for potential: 0: analytical formula, 1: poisson solver +/// \param nSteps number of which are used for calculation of distortions/corrections per z-bin +/// \param simpsonIterations number of iterations used in the simpson intergration +template <typename DataT = double, size_t Nz = 17, size_t Nr = 17, size_t Nphi = 90> +void calculateDistortionsAnalytical(const int globalEFieldTypeAna, const int globalDistTypeAna, const int eFieldTypeAna, const int usePoissonSolverAna, const int nSteps, const int simpsonIterations, const int nThreads) +{ + const auto integrationStrategy = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>::IntegrationStrategy::SimpsonIterative; + o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi> spaceCharge3D; + spaceCharge3D.setOmegaTauT1T2(0.32f, 1, 1); + spaceCharge3D.setNStep(nSteps); + spaceCharge3D.setSimpsonNIteratives(simpsonIterations); + spaceCharge3D.setNumericalIntegrationStrategy(integrationStrategy); + if (nThreads != -1) { + spaceCharge3D.setNThreads(nThreads); + } + + // write to root file + o2::utils::TreeStreamRedirector pcstream(TString::Format("distortions_ana_nR%lu_nZ%lu_nPhi%lu_SimpsonsIter%i.root", Nr, Nz, Nphi, simpsonIterations).Data(), "RECREATE"); + for (int iside = 0; iside < 2; ++iside) { + std::cout << "side: " << iside << std::endl; + o2::tpc::Side side = (iside == 0) ? o2::tpc::Side::A : o2::tpc::Side::C; + o2::tpc::AnalyticalFields<DataT> anaFields(side); + calculateDistortionsCorrectionsAnalytical(spaceCharge3D, anaFields, globalEFieldTypeAna, eFieldTypeAna, globalDistTypeAna, usePoissonSolverAna); + pcstream.GetFile()->cd(); + writeToTree(spaceCharge3D, pcstream, side); + } + + pcstream.GetFile()->cd(); + pcstream.Close(); +} + +/// \param path path to the root file containing the 3D density histogram +/// \param histoName name of the histogram in the root file +/// \param sides setting which sides will be processed: 0: A- and C-Side, 1: A-Side, 2: C-Side +/// \param globalEFieldType setting for global distortions/corrections: 0: using electric field, 1: using local dis/corr interpolator +/// \param globalDistType setting for global distortions: 0: standard method, 1: interpolation of global corrections +/// \param nSteps number of which are used for calculation of distortions/corrections per z-bin +/// \param simpsonIterations number of iterations used in the simpson intergration +template <typename DataT = double, size_t Nz = 17, size_t Nr = 17, size_t Nphi = 90> +void calculateDistortionsFromHist(const char* path, const char* histoName, const int sides, const int globalEFieldType, const int globalDistType, const int nSteps, const int simpsonIterations, const int nThreads) +{ + using SC = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>; + const auto integrationStrategy = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>::IntegrationStrategy::SimpsonIterative; + SC spaceCharge3D; + spaceCharge3D.setOmegaTauT1T2(0.32f, 1, 1); + spaceCharge3D.setNStep(nSteps); + spaceCharge3D.setSimpsonNIteratives(simpsonIterations); + spaceCharge3D.setNumericalIntegrationStrategy(integrationStrategy); + if (nThreads != -1) { + spaceCharge3D.setNThreads(nThreads); + } + + // set density from input file + TFile fileOutSCDensity(path, "READ"); + spaceCharge3D.fillChargeDensityFromFile(fileOutSCDensity, histoName); + fileOutSCDensity.Close(); + + o2::utils::TreeStreamRedirector pcstream(TString::Format("distortions_real_nR%lu_nZ%lu_nPhi%lu_SimpsonsIter%i.root", Nr, Nz, Nphi, simpsonIterations).Data(), "RECREATE"); + int iSideStart = 0; + int iSideEnd = 2; + if (sides == 1) { + // a side only + iSideEnd = 1; + } else if (sides == 2) { + // c side only + iSideStart = 1; + } + for (int iside = iSideStart; iside < iSideEnd; ++iside) { + std::cout << "side: " << iside << std::endl; + o2::tpc::Side side = (iside == 0) ? o2::tpc::Side::A : o2::tpc::Side::C; + const auto distType = globalDistType == 0 ? SC::GlobalDistType::Standard : SC ::GlobalDistType::Fast; + spaceCharge3D.setGlobalDistType(distType); + const auto eType = globalEFieldType == 1 ? SC::GlobalDistCorrMethod::LocalDistCorr : SC::GlobalDistCorrMethod::ElectricalField; + spaceCharge3D.setGlobalDistCorrMethod(eType); + spaceCharge3D.calculateDistortionsCorrections(side); + // write to root file + pcstream.GetFile()->cd(); + writeToTree(spaceCharge3D, pcstream, side); + } + pcstream.GetFile()->cd(); + pcstream.Close(); + + // write global corrections and distortions to file + TFile fOut("spacecharge.root", "RECREATE"); + if (sides != 2) { + spaceCharge3D.dumpGlobalDistortions(fOut, o2::tpc::Side::A); + spaceCharge3D.dumpGlobalCorrections(fOut, o2::tpc::Side::A); + } + if (sides != 1) { + spaceCharge3D.dumpGlobalDistortions(fOut, o2::tpc::Side::C); + spaceCharge3D.dumpGlobalCorrections(fOut, o2::tpc::Side::C); + } + fOut.Close(); +} diff --git a/Detectors/TPC/spacecharge/macro/createResidualDistortionObject.C b/Detectors/TPC/spacecharge/macro/createResidualDistortionObject.C new file mode 100644 index 0000000000000..f3b7d02f0c750 --- /dev/null +++ b/Detectors/TPC/spacecharge/macro/createResidualDistortionObject.C @@ -0,0 +1,215 @@ +// 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 createResidualDistortionObject.C +/// \brief This macro creates a SpaceCharge object with residual distortions from a fluctuating and an average space-charge density histogram and stores it in a file. +/// \author Ernst Hellbär, Goethe-Universität Frankfurt, ernst.hellbar@cern.ch + +#include <cmath> + +#include "TFile.h" +#include "CommonUtils/TreeStreamRedirector.h" +#include "TPCSpaceCharge/SpaceCharge.h" +#include "MathUtils/Cartesian.h" + +using namespace o2::tpc; +using DataT = double; +constexpr int NZ = 129; +constexpr int NR = 129; +constexpr int NPHI = 180; +using DataContainer = DataContainer3D<DataT, NZ, NR, NPHI>; + +// function declarations +void createSpaceCharge(o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& spaceCharge, const char* path, const char* histoName, const int bSign, const int nThreads = -1); +void fillDistortionLookupMatrices(o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& spaceChargeCalcFluc, o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>* spaceChargeCalcAvg, DataContainer matrixDistDr[2], DataContainer matrixDistDrphi[2], DataContainer matrixDistDz[2]); +void makeDebugTreeResiduals(o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& calcFluc, o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& calcAvg, o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& spaceChargeRes); +/// Create a SpaceCharge object with residual distortions from a fluctuating and an average space-charge density histogram and write it to a file. +/// \param bSign sign of the B-field: -1 = negative, 0 = no B-field, 1 = positive +/// \param pathToHistoFile path to a file with the fluctuating and average histograms +/// \param histoFlucName name of the fluctuating histogram +/// \param histoAvgName name of the average histogram +void createResidualDistortionObject(int bSign, const char* pathToHistoFile = "InputSCDensityHistograms_8000events.root", const char* histoFlucName = "inputSCDensity3D_8000_0", const char* histoAvgName = "inputSCDensity3D_8000_avg", const int nThreads = -1, bool debug = false) +{ + /* + Usage: + root -l -b -q createResidualDistortionObject.C+\(-1,\"InputSCDensityHistograms_8000events.root\",\"inputSCDensity3D_8000_0\",\"inputSCDensity3D_8000_avg\",true\) + */ + + // Calculate fluctuating and average distortion and correction lookup tables + o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI> scCalcFluc; + o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI> scCalcAvg; + createSpaceCharge(scCalcFluc, pathToHistoFile, histoFlucName, bSign, nThreads); + createSpaceCharge(scCalcAvg, pathToHistoFile, histoAvgName, bSign, nThreads); + + // Create matrices and fill them with residual distortions. Create SpaceCharge object, assign residual distortion matrices to it and store it in the output file. + DataContainer matrixResDistDr[2]; + DataContainer matrixResDistDrphi[2]; + DataContainer matrixResDistDz[2]; + + fillDistortionLookupMatrices(scCalcFluc, &scCalcAvg, matrixResDistDr, matrixResDistDrphi, matrixResDistDz); + o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI> spaceChargeRes; + spaceChargeRes.setDistortionLookupTables(matrixResDistDz[0], matrixResDistDr[0], matrixResDistDrphi[0], o2::tpc::Side::A); + spaceChargeRes.setDistortionLookupTables(matrixResDistDz[1], matrixResDistDr[1], matrixResDistDrphi[1], o2::tpc::Side::C); + + TFile fileOutput("ResidualDistortions.root", "recreate"); + spaceChargeRes.dumpGlobalDistortions(fileOutput, o2::tpc::Side::A); + spaceChargeRes.dumpGlobalDistortions(fileOutput, o2::tpc::Side::C); + + if (debug) { + makeDebugTreeResiduals(scCalcFluc, scCalcAvg, spaceChargeRes); + } +} + +/// calculate the distortions and corrections from a space-charge density histogram +/// \param spaceCharge input space-charge density object which will be filled +/// \param path path to a file with the histograms +/// \param histoName name of the histogram +/// \param bSign sign of the B-field: -1 = negative, 0 = no B-field, 1 = positive +/// \param nThreads number of threads which are used +void createSpaceCharge(o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& spaceCharge, const char* path, const char* histoName, const int bSign, const int nThreads) +{ + const float omegaTau = -0.32 * bSign; + spaceCharge.setOmegaTauT1T2(omegaTau, 1, 1); + if (nThreads != -1) { + spaceCharge.setNThreads(nThreads); + } + // set density from input file + TFile fileOutSCDensity(path, "READ"); + spaceCharge.fillChargeDensityFromFile(fileOutSCDensity, histoName); + fileOutSCDensity.Close(); + + // calculate the distortions + spaceCharge.calculateDistortionsCorrections(o2::tpc::Side::A); + spaceCharge.calculateDistortionsCorrections(o2::tpc::Side::C); +} + +/// Store distortions from spaceChargeCalcFluc in the matrices provided. If providing an object with average space-charge distortions spaceChargeCalcAvg, the residual distortions (dist_fluctuation(xyzTrue) + corr_average(xyzDistorted)) will be stored. +/// \param spaceChargeCalcFluc fluctuating distortions object +/// \param spaceChargeCalcAvg average distortions object +/// \param matrixDistDr matrix to store radial distortions on the A and C side +/// \param matrixDistDrphi matrix to store rphi distortions on the A and C side +/// \param matrixDistDz matrix to store z distortions on the A and C side +void fillDistortionLookupMatrices(o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& spaceChargeCalcFluc, o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>* spaceChargeCalcAvg, DataContainer matrixDistDr[2], DataContainer matrixDistDrphi[2], DataContainer matrixDistDz[2]) +{ + for (int iside = 0; iside < 2; ++iside) { + o2::tpc::Side side = (iside == 0) ? o2::tpc::Side::A : o2::tpc::Side::C; + for (int iphi = 0; iphi < NPHI; ++iphi) { + const auto phi = spaceChargeCalcFluc.getPhiVertex(iphi, side); + + for (int ir = 0; ir < NR; ++ir) { + const auto r = spaceChargeCalcFluc.getRVertex(ir, side); + + for (int iz = 0; iz < NZ; ++iz) { + const auto z = spaceChargeCalcFluc.getZVertex(iz, side); + + // get fluctuating distortions + DataT distFlucdZ = 0; + DataT distFlucdR = 0; + DataT distFlucdRPhi = 0; + spaceChargeCalcFluc.getDistortionsCyl(z, r, phi, side, distFlucdZ, distFlucdR, distFlucdRPhi); + + // get average corrections if provided and add them to the fluctuating distortions + if (spaceChargeCalcAvg) { + const float zDistorted = z + distFlucdZ; + const float rDistorted = r + distFlucdR; + const float phiDistorted = phi + distFlucdRPhi / r; + DataT corrZDistPoint = 0; + DataT corrRDistPoint = 0; + DataT corrRPhiDistPoint = 0; + spaceChargeCalcAvg->getCorrectionsCyl(zDistorted, rDistorted, phiDistorted, side, corrZDistPoint, corrRDistPoint, corrRPhiDistPoint); + distFlucdZ += corrZDistPoint; + distFlucdR += corrRDistPoint; + distFlucdRPhi += corrRPhiDistPoint * r / rDistorted; + } + + // store (residual) distortions in the matrices + matrixDistDr[iside](ir, iz, iphi) = distFlucdR; + matrixDistDrphi[iside](ir, iz, iphi) = distFlucdRPhi; + matrixDistDz[iside](ir, iz, iphi) = distFlucdZ; + } + } + } + } +} + +/// Calculate and stream residual distortions from spaceChargeRes and from calcFluc and calcAvg for comparison. +/// \param calcFluc space charge object with fluctuation distortions +/// \param calcAvg space charge object with average distortions +/// \param spaceChargeRes space charge object with residual distortions +void makeDebugTreeResiduals(o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& calcFluc, o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& calcAvg, o2::tpc::SpaceCharge<DataT, NZ, NR, NPHI>& spaceChargeRes) +{ + o2::utils::TreeStreamRedirector pcstream("debugResidualDistortions.root", "recreate"); + for (int iside = 0; iside < 2; ++iside) { + o2::tpc::Side side = (iside == 0) ? o2::tpc::Side::A : o2::tpc::Side::C; + for (int iphi = 0; iphi < NPHI; ++iphi) { + auto phi = calcFluc.getPhiVertex(iphi, side); + for (int ir = 0; ir < NR; ++ir) { + auto r = calcFluc.getRVertex(ir, side); + DataT x = r * std::cos(phi); + DataT y = r * std::sin(phi); + for (int iz = 1; iz < NZ; ++iz) { + DataT z = calcFluc.getZVertex(iz, side); + + GlobalPosition3D posDistRes(x, y, z); + spaceChargeRes.distortElectron(posDistRes); + DataT xyzDistRes[3] = {posDistRes.x(), posDistRes.y(), posDistRes.z()}; + DataT distRes[3] = {posDistRes.x() - x, posDistRes.y() - y, posDistRes.z() - z}; + + DataT distFlucX = 0; + DataT distFlucY = 0; + DataT distFlucZ = 0; + calcFluc.getDistortions(x, y, z, side, distFlucX, distFlucY, distFlucZ); + + DataT xDistorted = x + distFlucX; + DataT yDistorted = y + distFlucY; + DataT zDistorted = z + distFlucZ; + + DataT corrAvgX = 0; + DataT corrAvgY = 0; + DataT corrAvgZ = 0; + calcAvg.getCorrections(xDistorted, yDistorted, zDistorted, side, corrAvgX, corrAvgY, corrAvgZ); + DataT xyzDistResTrue[3] = {xDistorted + corrAvgX, yDistorted + corrAvgY, zDistorted + corrAvgZ}; + DataT distResTrue[3] = {distFlucX + corrAvgX, distFlucY + corrAvgY, distFlucZ + corrAvgZ}; + + pcstream << "debug" + << "iside=" << iside + << "iphi=" << iphi + << "ir=" << ir + << "iz=" << iz + // original position + << "phi=" << phi + << "r=" << r + << "x=" << x + << "y=" << y + << "z=" << z + // position of distorted points + << "xRes=" << xyzDistRes[0] + << "yRes=" << xyzDistRes[1] + << "zRes=" << xyzDistRes[2] + // true position of distorted points + << "xResTrue=" << xyzDistResTrue[0] + << "yResTrue=" << xyzDistResTrue[1] + << "zResTrue=" << xyzDistResTrue[2] + // residual distortions + << "distX=" << distRes[0] + << "distY=" << distRes[1] + << "distZ=" << distRes[2] + // true residual distortions + << "distXTrue=" << distResTrue[0] + << "distYTrue=" << distResTrue[1] + << "distZTrue=" << distResTrue[2] + // + << "\n"; + } + } + } + } + pcstream.Close(); +} diff --git a/Detectors/TPC/spacecharge/src/PoissonSolver.cxx b/Detectors/TPC/spacecharge/src/PoissonSolver.cxx new file mode 100644 index 0000000000000..1a52719225b88 --- /dev/null +++ b/Detectors/TPC/spacecharge/src/PoissonSolver.cxx @@ -0,0 +1,1497 @@ +// 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 PoissonSolver.cxx +/// \brief This class provides implementation of Poisson Eq +/// solver by MultiGrid Method +/// +/// +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Aug 21, 2020 + +#include "TPCSpaceCharge/PoissonSolver.h" +#include "Framework/Logger.h" +#include <numeric> +#include <fmt/core.h> + +#ifdef WITH_OPENMP +#include <omp.h> +#endif + +using namespace o2::tpc; + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::poissonSolver3D(DataContainer& matricesV, const DataContainer& matricesCharge, const int symmetry) +{ + if (MGParameters::isFull3D) { + poissonMultiGrid3D(matricesV, matricesCharge, symmetry); + } else { + poissonMultiGrid3D2D(matricesV, matricesCharge, symmetry); + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::poissonSolver2D(DataContainer& matricesV, const DataContainer& matricesCharge) +{ + poissonMultiGrid2D(matricesV, matricesCharge); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::poissonMultiGrid2D(DataContainer& matricesV, const DataContainer& matricesCharge, const int iPhi) +{ + /// Geometry of TPC -- should be use AliTPCParams instead + const DataT gridSpacingR = getSpacingR(); + const DataT gridSpacingZ = getSpacingZ(); + const DataT ratioZ = gridSpacingR * gridSpacingR / (gridSpacingZ * gridSpacingZ); // ratio_{Z} = gridSize_{r} / gridSize_{z} + + int nGridRow = 0; // number grid + int nGridCol = 0; // number grid + + int nnRow = Nr; + while (nnRow >>= 1) { + ++nGridRow; + } + + int nnCol = Nz; + while (nnCol >>= 1) { + ++nGridCol; + } + + //Check that number of Nr and Nz is suitable for multi grid + if (!isPowerOfTwo(Nr - 1)) { + LOGP(ERROR, "PoissonMultiGrid2D: PoissonMultiGrid - Error in the number of Nr. Must be 2**M + 1"); + return; + } + if (!isPowerOfTwo(Nz - 1)) { + LOGP(ERROR, "PoissonMultiGrid2D: PoissonMultiGrid - Error in the number of Nz. Must be 2**N - 1"); + return; + } + + const int nLoop = std::max(nGridRow, nGridCol); // Calculate the number of nLoop for the binary expansion + + LOGP(info, "{}", fmt::format("PoissonMultiGrid2D: nGridRow={}, nGridCol={}, nLoop={}, nMGCycle={}", nGridRow, nGridCol, nLoop, MGParameters::nMGCycle)); + + int iOne = 1; // in/dex + int jOne = 1; // index + int tnRRow = Nr; + int tnZColumn = Nz; + + // Vector for storing multi grid array + std::vector<Vector> tvArrayV(nLoop); // potential <--> error + std::vector<Vector> tvChargeFMG(nLoop); // charge is restricted in full multiGrid + std::vector<Vector> tvCharge(nLoop); // charge <--> residue + std::vector<Vector> tvResidue(nLoop); // residue calculation + + // Allocate memory for temporary grid + for (int count = 1; count <= nLoop; ++count) { + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + // if one just address to matrixV + tvResidue[count - 1].resize(tnRRow, tnZColumn, 1); + tvChargeFMG[count - 1].resize(tnRRow, tnZColumn, 1); + tvArrayV[count - 1].resize(tnRRow, tnZColumn, 1); + tvCharge[count - 1].resize(tnRRow, tnZColumn, 1); + + if (count == 1) { + for (int iphi = iPhi; iphi <= iPhi; ++iphi) { + for (int ir = 0; ir < Nr; ++ir) { + for (int iz = 0; iz < Nz; ++iz) { + tvChargeFMG[count - 1](ir, iz, iphi) = matricesCharge(iz, ir, iphi); + tvCharge[count - 1](ir, iz, iphi) = matricesCharge(iz, ir, iphi); + tvArrayV[count - 1](ir, iz, iphi) = matricesV(iz, ir, iphi); + } + } + } + } else { + restrict2D(tvChargeFMG[count - 1], tvChargeFMG[count - 2], tnRRow, tnZColumn, 0); + } + iOne = 2 * iOne; + jOne = 2 * jOne; + } + + /// full multi grid + if (MGParameters::cycleType == CycleType::FCycle) { + + LOGP(info, "PoissonMultiGrid2D: Do full cycle"); + // FMG + // 1) Relax on the coarsest grid + iOne = iOne * 0.5; + jOne = jOne * 0.5; + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + const DataT h = gridSpacingR * nLoop; + const DataT h2 = h * h; + const DataT tempRatio = ratioZ * iOne * iOne / (jOne * jOne); + const DataT tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); + + std::vector<DataT> coefficient1(tnRRow); + std::vector<DataT> coefficient2(tnRRow); + calcCoefficients2D(1, tnRRow - 1, h, coefficient1, coefficient2); + + relax2D(tvArrayV[nLoop - 1], tvChargeFMG[nLoop - 1], tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, coefficient2); + + // Do VCycle from nLoop H to h + for (int count = nLoop - 2; count >= 0; --count) { + + iOne = iOne * 0.5; + jOne = jOne * 0.5; + + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + interp2D(tvArrayV[count], tvArrayV[count + 1], tnRRow, tnZColumn, iPhi); + + // Copy the relax charge to the tvCharge + tvCharge[count] = tvChargeFMG[count]; //copy + + // Do V cycle + for (int mgCycle = 0; mgCycle < MGParameters::nMGCycle; ++mgCycle) { + vCycle2D(count + 1, nLoop, MGParameters::nPre, MGParameters::nPost, gridSpacingR, ratioZ, tvArrayV, tvCharge, tvResidue); + } + } + } else if (MGParameters::cycleType == CycleType::VCycle) { + // 2. VCycle + LOGP(info, "PoissonMultiGrid2D: Do V cycle"); + + int gridFrom = 1; + int gridTo = nLoop; + + // Do MGCycle + for (int mgCycle = 0; mgCycle < MGParameters::nMGCycle; ++mgCycle) { + vCycle2D(gridFrom, gridTo, MGParameters::nPre, MGParameters::nPost, gridSpacingR, ratioZ, tvArrayV, tvCharge, tvResidue); + } + } else if (MGParameters::cycleType == CycleType::WCycle) { + // 3. W Cycle (TODO:) + int gridFrom = 1; + int gridTo = nLoop; + // Do MGCycle + for (Int_t mgCycle = 0; mgCycle < MGParameters::nMGCycle; mgCycle++) { + wCycle2D(gridFrom, gridTo, MGParameters::gamma, MGParameters::nPre, MGParameters::nPost, gridSpacingR, ratioZ, tvArrayV, tvCharge, tvResidue); + } + } + + // fill output + for (int iphi = iPhi; iphi <= iPhi; ++iphi) { + for (int ir = 0; ir < Nr; ++ir) { + for (int iz = 0; iz < Nz; ++iz) { + matricesV(iz, ir, iphi) = tvArrayV[0](ir, iz, iphi); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::poissonMultiGrid3D2D(DataContainer& matricesV, const DataContainer& matricesCharge, const int symmetry) +{ + LOGP(info, "{}", fmt::format("PoissonMultiGrid3D2D: in Poisson Solver 3D multiGrid semi coarsening Nr={}, cols={}, Nphi={}", Nz, Nr, Nphi)); + + // Check that the number of Nr and Nz is suitable for a binary expansion + if (!isPowerOfTwo((Nr - 1))) { + LOGP(ERROR, "PoissonMultiGrid3D2D: Poisson3DMultiGrid - Error in the number of Nr. Must be 2**M + 1"); + return; + } + if (!isPowerOfTwo((Nz - 1))) { + LOGP(ERROR, "PoissonMultiGrid3D2D: Poisson3DMultiGrid - Error in the number of Nz. Must be 2**N - 1"); + return; + } + if (Nphi <= 3) { + LOGP(ERROR, "PoissonMultiGrid3D2D: Poisson3DMultiGrid - Error in the number of Nphi. Must be larger than 3"); + return; + } + if (Nphi > 1000) { + LOGP(ERROR, "PoissonMultiGrid3D2D: Poisson3D Nphi > 1000 is not allowed (nor wise)"); + return; + } + + const DataT gridSpacingR = getSpacingR(); + const DataT gridSpacingZ = getSpacingZ(); + const DataT gridSpacingPhi = getSpacingPhi(); + const DataT ratioPhi = gridSpacingR * gridSpacingR / (gridSpacingPhi * gridSpacingPhi); // ratio_{phi} = gridSize_{r} / gridSize_{phi} + const DataT ratioZ = gridSpacingR * gridSpacingR / (gridSpacingZ * gridSpacingZ); // ratio_{Z} = gridSize_{r} / gridSize_{z} + + // Solve Poisson's equation in cylindrical coordinates by multiGrid technique + // Allow for different size grid spacing in R and Z directions + int nGridRow = 0; // number grid + int nGridCol = 0; // number grid + int nnRow = Nr; + int nnCol = Nz; + + while (nnRow >>= 1) { + ++nGridRow; + } + while (nnCol >>= 1) { + ++nGridCol; + } + + const int maxVal = std::max(nGridRow, nGridCol); // Calculate the number of nLoop for the binary expansion + const size_t nLoop = (maxVal > MGParameters::maxLoop) ? MGParameters::maxLoop : maxVal; + unsigned int iOne = 1; // index i in gridSize r (original) + unsigned int jOne = 1; // index j in gridSize z (original) + + std::vector<Vector> tvArrayV(nLoop); // potential <--> error + std::vector<Vector> tvChargeFMG(nLoop); // charge is restricted in full multiGrid + std::vector<Vector> tvCharge(nLoop); // charge <--> residue + std::vector<Vector> tvPrevArrayV(nLoop); // error calculation + std::vector<Vector> tvResidue(nLoop); // residue calculation + + for (unsigned int count = 1; count <= nLoop; count++) { + const unsigned int tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + const unsigned int tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + tvResidue[count - 1].resize(tnRRow, tnZColumn, Nphi); + tvPrevArrayV[count - 1].resize(tnRRow, tnZColumn, Nphi); + + // memory for the finest grid is from parameters + tvChargeFMG[count - 1].resize(tnRRow, tnZColumn, Nphi); + tvArrayV[count - 1].resize(tnRRow, tnZColumn, Nphi); + tvCharge[count - 1].resize(tnRRow, tnZColumn, Nphi); + + if (count == 1) { + for (int iphi = 0; iphi < Nphi; ++iphi) { + for (int ir = 0; ir < Nr; ++ir) { + for (int iz = 0; iz < Nz; ++iz) { + tvChargeFMG[count - 1](ir, iz, iphi) = matricesCharge(iz, ir, iphi); + tvArrayV[count - 1](ir, iz, iphi) = matricesV(iz, ir, iphi); + } + } + } + } else { + restrict3D(tvChargeFMG[count - 1], tvChargeFMG[count - 2], tnRRow, tnZColumn, Nphi, Nphi); + restrictBoundary3D(tvArrayV[count - 1], tvArrayV[count - 2], tnRRow, tnZColumn, Nphi, Nphi); + } + iOne = 2 * iOne; // doubling + jOne = 2 * jOne; // doubling + } + + std::array<DataT, Nr> coefficient1{}; // coefficient1(Nr) for storing (1 + h_{r}/2r_{i}) from central differences in r direction + std::array<DataT, Nr> coefficient2{}; // coefficient2(Nr) for storing (1 + h_{r}/2r_{i}) from central differences in r direction + std::array<DataT, Nr> coefficient3{}; // coefficient3(Nr) for storing (1/r_{i}^2) from central differences in phi direction + std::array<DataT, Nr> coefficient4{}; // coefficient4(Nr) for storing 1/2 + std::array<DataT, Nr> inverseCoefficient4{}; // inverse of coefficient4(Nr) + + // Case full multi grid (FMG) + if (MGParameters::cycleType == CycleType::FCycle) { + // 1) Relax on the coarsest grid + iOne = iOne * 0.5; + jOne = jOne * 0.5; + int tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + int tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + const DataT h = getSpacingR() * iOne; + const DataT h2 = h * h; + const DataT iOne2 = iOne * iOne; + const DataT tempRatioPhi = ratioPhi * iOne2; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 + const DataT tempRatioZ = ratioZ * iOne2 / (jOne * jOne); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + + // relax on the coarsest level + relax3D(tvArrayV[nLoop - 1], tvChargeFMG[nLoop - 1], tnRRow, tnZColumn, Nphi, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + + // 2) Do multiGrid v-cycle from coarsest to finest + for (int count = nLoop - 2; count >= 0; --count) { + // move to finer grid + iOne = iOne * 0.5; + jOne = jOne * 0.5; + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + // 2) a) Interpolate potential for h -> 2h (coarse -> fine) + interp3D(tvArrayV[count], tvArrayV[count + 1], tnRRow, tnZColumn, Nphi, Nphi); + + // 2) c) Copy the restricted charge to charge for calculation + tvCharge[count] = tvChargeFMG[count]; //copy + + // 2) c) Do V cycle MGParameters::nMGCycle times at most + for (int mgCycle = 0; mgCycle < MGParameters::nMGCycle; ++mgCycle) { + // Copy the potential to temp array for convergence calculation + tvPrevArrayV[count] = tvArrayV[count]; + + // 2) c) i) Call V cycle from grid count+1 (current fine level) to nLoop (coarsest) + vCycle3D2D(symmetry, count + 1, nLoop, MGParameters::nPre, MGParameters::nPost, ratioZ, ratioPhi, tvArrayV, tvCharge, tvResidue, coefficient1, coefficient2, coefficient3, coefficient4, inverseCoefficient4); + + const DataT convergenceError = getConvergenceError(tvArrayV[count], tvPrevArrayV[count]); + + /// if already converge just break move to finer grid + if (convergenceError <= sConvergenceError) { + break; + } + } + } + } + + // fill output + for (int iphi = 0; iphi < Nphi; ++iphi) { + for (int ir = 0; ir < Nr; ++ir) { + for (int iz = 0; iz < Nz; ++iz) { + matricesV(iz, ir, iphi) = tvArrayV[0](ir, iz, iphi); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::poissonMultiGrid3D(DataContainer& matricesV, const DataContainer& matricesCharge, const int symmetry) +{ + const DataT gridSpacingR = getSpacingR(); + const DataT gridSpacingZ = getSpacingZ(); + const DataT ratioZ = gridSpacingR * gridSpacingR / (gridSpacingZ * gridSpacingZ); // ratio_{Z} = gridSize_{r} / gridSize_{z} + + LOGP(info, "{}", fmt::format("PoissonMultiGrid3D: in Poisson Solver 3D multi grid full coarsening Nr={}, cols={}, Nphi={}", Nr, Nz, Nphi)); + + // Check that the number of Nr and Nz is suitable for a binary expansion + if (!isPowerOfTwo((Nr - 1))) { + LOGP(ERROR, "PoissonMultiGrid3D: Poisson3DMultiGrid - Error in the number of Nr. Must be 2**M + 1"); + return; + } + if (!isPowerOfTwo((Nz - 1))) { + LOGP(ERROR, "PoissonMultiGrid3D: Poisson3DMultiGrid - Error in the number of Nz. Must be 2**N - 1"); + return; + } + if (Nphi <= 3) { + LOGP(ERROR, "PoissonMultiGrid3D: Poisson3DMultiGrid - Error in the number of Nphi. Must be larger than 3"); + return; + } + if (Nphi > 1000) { + LOGP(ERROR, "PoissonMultiGrid3D: Poisson3D Nphi > 1000 is not allowed (nor wise)"); + return; + } + + // Solve Poisson's equation in cylindrical coordinates by multi grid technique + // Allow for different size grid spacing in R and Z directions + int nGridRow = 0; // number grid + int nGridCol = 0; // number grid + int nGridPhi = 0; + + int nnRow = Nr; + while (nnRow >>= 1) { + ++nGridRow; + } + + int nnCol = Nz; + while (nnCol >>= 1) { + ++nGridCol; + } + + int nnPhi = Nphi; + while (nnPhi % 2 == 0) { + ++nGridPhi; + nnPhi *= 0.5; + } + + LOGP(info, "{}", fmt::format("PoissonMultiGrid3D: nGridRow={}, nGridCol={}, nGridPhi={}", nGridRow, nGridCol, nGridPhi)); + const int nLoop = std::max({nGridRow, nGridCol, nGridPhi}); // Calculate the number of nLoop for the binary expansion + + // Vector for storing multi grid array + int iOne = 1; // index i in gridSize r (original) + int jOne = 1; // index j in gridSize z (original) + int kOne = 1; // index k in gridSize phi + int tnRRow = Nr; + int tnZColumn = Nz; + int tPhiSlice = Nphi; + + // 1) Memory allocation for multi grid + std::vector<Vector> tvArrayV(nLoop); // potential <--> error + std::vector<Vector> tvChargeFMG(nLoop); // charge is restricted in full multiGrid + std::vector<Vector> tvCharge(nLoop); // charge <--> residue + std::vector<Vector> tvPrevArrayV(nLoop); // error calculation + std::vector<Vector> tvResidue(nLoop); // residue calculation + + std::array<DataT, Nr> coefficient1{}; // coefficient1(Nr) for storing (1 + h_{r}/2r_{i}) from central differences in r direction + std::array<DataT, Nr> coefficient2{}; // coefficient2(Nr) for storing (1 + h_{r}/2r_{i}) from central differences in r direction + std::array<DataT, Nr> coefficient3{}; // coefficient3(Nr) for storing (1/r_{i}^2) from central differences in phi direction + std::array<DataT, Nr> coefficient4{}; // coefficient4(Nr) for storing 1/2 + std::array<DataT, Nr> inverseCoefficient4{}; // inverse of coefficient4(Nr) + + for (int count = 1; count <= nLoop; ++count) { + // tnRRow,tnZColumn in new grid + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + tPhiSlice = kOne == 1 ? Nphi : Nphi / kOne; + tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; + + // allocate memory for residue + tvResidue[count - 1].resize(tnRRow, tnZColumn, tPhiSlice); + tvPrevArrayV[count - 1].resize(tnRRow, tnZColumn, tPhiSlice); + tvChargeFMG[count - 1].resize(tnRRow, tnZColumn, tPhiSlice); + tvArrayV[count - 1].resize(tnRRow, tnZColumn, tPhiSlice); + tvCharge[count - 1].resize(tnRRow, tnZColumn, tPhiSlice); + + // memory for the finest grid is from parameters + if (count == 1) { + for (int iphi = 0; iphi < Nphi; ++iphi) { + for (int ir = 0; ir < Nr; ++ir) { + for (int iz = 0; iz < Nz; ++iz) { + tvChargeFMG[count - 1](ir, iz, iphi) = matricesCharge(iz, ir, iphi); + tvArrayV[count - 1](ir, iz, iphi) = matricesV(iz, ir, iphi); + } + } + } + tvCharge[count - 1] = tvChargeFMG[count - 1]; + } + iOne = 2 * iOne; // doubling + jOne = 2 * jOne; // doubling + kOne = 2 * kOne; + } + + // Case full multi grid (FMG) + if (MGParameters::cycleType == CycleType::FCycle) { + // Restrict the charge to coarser grid + iOne = 2; + jOne = 2; + kOne = 2; + int otPhiSlice = Nphi; + + // 1) Restrict Charge and Boundary to coarser grid + for (int count = 2; count <= nLoop; ++count) { + // tnRRow,tnZColumn in new grid + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + tPhiSlice = kOne == 1 ? Nphi : Nphi / kOne; + tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; + + LOGP(info, "{}", fmt::format("PoissonMultiGrid3D: Restrict3D, tnRRow={}, tnZColumn={}, newPhiSlice={}, oldPhiSlice={}", tnRRow, tnZColumn, tPhiSlice, otPhiSlice)); + restrict3D(tvChargeFMG[count - 1], tvChargeFMG[count - 2], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); + // copy boundary values of V + restrictBoundary3D(tvArrayV[count - 1], tvArrayV[count - 2], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); + otPhiSlice = tPhiSlice; + + iOne = 2 * iOne; // doubling + jOne = 2 * jOne; // doubling + kOne = 2 * kOne; + } + + // Relax on the coarsest grid + // FMG + // 2) Relax on the coarsest grid + // move to the coarsest + 1 + iOne = iOne * 0.5; + jOne = jOne * 0.5; + kOne = kOne * 0.5; + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + tPhiSlice = kOne == 1 ? Nphi : Nphi / kOne; + tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; + otPhiSlice = tPhiSlice; + + const DataT h = gridSpacingR * iOne; + const DataT h2 = h * h; + const DataT gridSizePhiInv = tPhiSlice * INVTWOPI; // h_{phi} + const DataT tempRatioPhi = h2 * gridSizePhiInv * gridSizePhiInv; // ratio_{phi} = gridSize_{r} / gridSize_{phi} + const DataT tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + + // 3) Relax on the coarsest grid + relax3D(tvArrayV[nLoop - 1], tvChargeFMG[nLoop - 1], tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + + // 4) V Cycle from coarsest to finest + for (int count = nLoop - 2; count >= 0; --count) { + // move to finer grid + std::fill(std::begin(coefficient1), std::end(coefficient1), 0); + std::fill(std::begin(coefficient2), std::end(coefficient2), 0); + std::fill(std::begin(coefficient3), std::end(coefficient3), 0); + std::fill(std::begin(coefficient4), std::end(coefficient4), 0); + std::fill(std::begin(inverseCoefficient4), std::end(inverseCoefficient4), 0); + + iOne = iOne * 0.5; + jOne = jOne * 0.5; + kOne = kOne * 0.5; + + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + tPhiSlice = kOne == 1 ? Nphi : Nphi / kOne; + tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; + + // 4) a) interpolate from 2h --> h grid + interp3D(tvArrayV[count], tvArrayV[count + 1], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); + + // Copy the relax charge to the tvCharge + if (count > 0) { + tvCharge[count] = tvChargeFMG[count]; + } + for (int mgCycle = 0; mgCycle < MGParameters::nMGCycle; ++mgCycle) { + // copy to store previous potential + tvPrevArrayV[count] = tvArrayV[count]; + + vCycle3D(symmetry, count + 1, nLoop, MGParameters::nPre, MGParameters::nPost, ratioZ, tvArrayV, tvCharge, tvResidue, coefficient1, coefficient2, coefficient3, coefficient4, inverseCoefficient4); + + // converge error + const DataT convergenceError = getConvergenceError(tvArrayV[count], tvPrevArrayV[count]); + // if already converge just break move to finer grid + if (convergenceError <= sConvergenceError) { + break; + } + } + // keep old slice information + otPhiSlice = tPhiSlice; + } + } else if (MGParameters::cycleType == CycleType::VCycle) { + // V-cycle + int gridFrom = 1; + int gridTo = nLoop; + + for (int mgCycle = 0; mgCycle < MGParameters::nMGCycle; ++mgCycle) { + // copy to store previous potential + tvPrevArrayV[0] = tvArrayV[0]; + + // Do V Cycle from the coarsest to finest grid + vCycle3D(symmetry, gridFrom, gridTo, MGParameters::nPre, MGParameters::nPost, ratioZ, tvArrayV, tvCharge, tvResidue, coefficient1, coefficient2, coefficient3, coefficient4, inverseCoefficient4); + + // convergence error + const DataT convergenceError = getConvergenceError(tvArrayV[0], tvPrevArrayV[0]); + + // if error already achieved then stop mg iteration + if (convergenceError <= sConvergenceError) { + break; + } + } + } + + // fill output + for (int iphi = 0; iphi < Nphi; ++iphi) { + for (int ir = 0; ir < Nr; ++ir) { + for (int iz = 0; iz < Nz; ++iz) { + matricesV(iz, ir, iphi) = tvArrayV[0](ir, iz, iphi); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::wCycle2D(const int gridFrom, const int gridTo, const int gamma, const int nPre, const int nPost, const DataT gridSizeR, const DataT ratio, + std::vector<Vector>& tvArrayV, std::vector<Vector>& tvCharge, std::vector<Vector>& tvResidue) +{ + int iOne = 1 << (gridFrom - 1); + int jOne = 1 << (gridFrom - 1); + + int tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + int tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + std::vector<DataT> coefficient1(Nr); + std::vector<DataT> coefficient2(Nz); + + // 1) Go to coarsest level + for (int count = gridFrom; count <= gridTo - 2; ++count) { + const DataT h = gridSizeR * iOne; + const DataT h2 = h * h; + const DataT ih2 = 1.0 / h2; + const DataT tempRatio = ratio * iOne * iOne / (jOne * jOne); + const DataT tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); + const DataT inverseTempFourth = 1.0 / tempFourth; + calcCoefficients2D(1, tnRRow - 1, h, coefficient1, coefficient2); + Vector matricesCurrentV = tvArrayV[count - 1]; + Vector matricesCurrentCharge = tvCharge[count - 1]; + Vector residue = tvResidue[count - 1]; + + // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi + for (int jPre = 1; jPre <= nPre; ++jPre) { + relax2D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, coefficient2); + } + + // 2) Residue calculation + residue2D(residue, matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, ih2, inverseTempFourth, tempRatio, coefficient1, coefficient2); + + iOne = 2 * iOne; + jOne = 2 * jOne; + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + matricesCurrentCharge = tvCharge[count]; + matricesCurrentV = tvArrayV[count]; + + //3) Restriction + restrict2D(matricesCurrentCharge, residue, tnRRow, tnZColumn, 0); + } + + // Do V cycle from: gridTo-1 to gridTo gamma times + for (int iGamma = 0; iGamma < gamma; ++iGamma) { + vCycle2D(gridTo - 1, gridTo, nPre, nPost, gridSizeR, ratio, tvArrayV, tvCharge, tvResidue); + } + + // Go to finest grid + for (int count = gridTo - 2; count >= gridFrom; --count) { + iOne = iOne * 0.5; + jOne = jOne * 0.5; + + const DataT h = gridSizeR * iOne; + const DataT h2 = h * h; + const DataT tempRatio = ratio * iOne * iOne / (jOne * jOne); + const DataT tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); + + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + const Vector matricesCurrentCharge = tvCharge[count - 1]; + Vector matricesCurrentV = tvArrayV[count - 1]; + const Vector matricesCurrentVC = tvArrayV[count]; + + // 6) Interpolation/Prolongation + addInterp2D(matricesCurrentV, matricesCurrentVC, tnRRow, tnZColumn, 0); + + calcCoefficients2D(1, tnRRow - 1, h, coefficient1, coefficient2); + + // 7) Post-Smoothing: Gauss-Seidel Relaxation + for (Int_t jPost = 1; jPost <= nPost; ++jPost) { + relax2D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, coefficient2); + } // end post smoothing + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::vCycle2D(const int gridFrom, const int gridTo, const int nPre, const int nPost, const DataT gridSizeR, const DataT ratio, std::vector<Vector>& tvArrayV, + std::vector<Vector>& tvCharge, std::vector<Vector>& tvResidue) +{ + int iOne = 1 << (gridFrom - 1); + int jOne = 1 << (gridFrom - 1); + + int tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + int tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + std::vector<DataT> coefficient1(Nr); + std::vector<DataT> coefficient2(Nz); + + // 1) Go to coarsest level + for (int count = gridFrom; count <= gridTo - 1; ++count) { + const DataT h = gridSizeR * iOne; + const DataT h2 = h * h; + const DataT ih2 = 1.0 / h2; + const DataT tempRatio = ratio * iOne * iOne / (jOne * jOne); + const DataT tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); + const DataT inverseTempFourth = 1.0 / tempFourth; + calcCoefficients2D(1, tnRRow - 1, h, coefficient1, coefficient2); + + for (int jPre = 1; jPre <= nPre; ++jPre) { + relax2D(tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, coefficient2); + } + + // 2) Residue calculation + residue2D(tvResidue[count - 1], tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, ih2, inverseTempFourth, tempRatio, coefficient1, coefficient2); + + iOne = 2 * iOne; + jOne = 2 * jOne; + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + //3) Restriction + restrict2D(tvCharge[count], tvResidue[count - 1], tnRRow, tnZColumn, 0); + + //4) Zeroing coarser V + std::fill(tvArrayV[count].begin(), tvArrayV[count].end(), 0); // is this necessary??? + } + + // 5) coarsest grid + const DataT h = gridSizeR * iOne; + const DataT h2 = h * h; + const DataT tempRatio = ratio * iOne * iOne / (jOne * jOne); + const DataT tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); + calcCoefficients2D(1, tnRRow - 1, h, coefficient1, coefficient2); + + relax2D(tvArrayV[gridTo - 1], tvCharge[gridTo - 1], tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, coefficient2); + + // Go to finest grid + for (int count = gridTo - 1; count >= gridFrom; count--) { + + iOne = iOne * 0.5; + jOne = jOne * 0.5; + + const DataT h = gridSizeR * iOne; + const DataT h2 = h * h; + const DataT tempRatio = ratio * iOne * iOne / (jOne * jOne); + const DataT tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); + + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + // 6) Interpolation/Prolongation + addInterp2D(tvArrayV[count - 1], tvArrayV[count], tnRRow, tnZColumn, 0); + + calcCoefficients2D(1, tnRRow - 1, h, coefficient1, coefficient2); + + // 7) Post-Smoothing: Gauss-Seidel Relaxation + for (int jPost = 1; jPost <= nPost; ++jPost) { + relax2D(tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, coefficient2); + } // end post smoothing + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::vCycle3D2D(const int symmetry, const int gridFrom, const int gridTo, const int nPre, const int nPost, const DataT ratioZ, const DataT ratioPhi, + std::vector<Vector>& tvArrayV, std::vector<Vector>& tvCharge, std::vector<Vector>& tvResidue, std::array<DataT, Nr>& coefficient1, + std::array<DataT, Nr>& coefficient2, std::array<DataT, Nr>& coefficient3, std::array<DataT, Nr>& coefficient4, std::array<DataT, Nr>& inverseCoefficient4) const +{ + int iOne = 1 << (gridFrom - 1); + int jOne = 1 << (gridFrom - 1); + int tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + int tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + for (int count = gridFrom; count <= gridTo - 1; ++count) { + const DataT h = getSpacingR() * iOne; + const DataT h2 = h * h; + const DataT ih2 = 1.0 / h2; + const int iOne2 = iOne * iOne; + const DataT tempRatioPhi = ratioPhi * iOne2; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 + const DataT tempRatioZ = ratioZ * iOne2 / (jOne * jOne); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + for (unsigned int i = 1; i < tnRRow - 1; ++i) { + inverseCoefficient4[i] = 1.0 / coefficient4[i]; + } + + //Info("VCycle3D2D","Before Pre-smoothing"); + // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi + for (int jPre = 1; jPre <= nPre; ++jPre) { + relax3D(tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, Nphi, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + } // end pre smoothing + + // 2) Residue calculation + residue3D(tvResidue[count - 1], tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, Nphi, symmetry, ih2, tempRatioZ, coefficient1, coefficient2, coefficient3, inverseCoefficient4); + + iOne = 2 * iOne; + jOne = 2 * jOne; + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + //3) Restriction + restrict3D(tvCharge[count], tvResidue[count - 1], tnRRow, tnZColumn, Nphi, Nphi); + + //4) Zeroing coarser V + std::fill(tvArrayV[count].begin(), tvArrayV[count].end(), 0); + } + + // coarsest grid + const DataT h = getSpacingR() * iOne; + const DataT h2 = h * h; + + const int iOne2 = iOne * iOne; + const DataT tempRatioPhi = ratioPhi * iOne2; + const DataT tempRatioZ = ratioZ * iOne2 / (jOne * jOne); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + + // 3) Relax on the coarsest grid + relax3D(tvArrayV[gridTo - 1], tvCharge[gridTo - 1], tnRRow, tnZColumn, Nphi, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + + // back to fine + for (int count = gridTo - 1; count >= gridFrom; --count) { + iOne = iOne * 0.5; + jOne = jOne * 0.5; + + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + + const DataT h = getSpacingR() * iOne; + const DataT h2 = h * h; + const int iOne2 = iOne * iOne; + const DataT tempRatioPhi = ratioPhi * iOne2; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 + const DataT tempRatioZ = ratioZ * iOne2 / (jOne * jOne); + + // 4) Interpolation/Prolongation + addInterp3D(tvArrayV[count - 1], tvArrayV[count], tnRRow, tnZColumn, Nphi, Nphi); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + + // 5) Post-Smoothing: Gauss-Seidel Relaxation + for (int jPost = 1; jPost <= nPost; ++jPost) { + relax3D(tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, Nphi, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + } // end post smoothing + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::vCycle3D(const int symmetry, const int gridFrom, const int gridTo, const int nPre, const int nPost, const DataT ratioZ, std::vector<Vector>& tvArrayV, + std::vector<Vector>& tvCharge, std::vector<Vector>& tvResidue, std::array<DataT, Nr>& coefficient1, std::array<DataT, Nr>& coefficient2, std::array<DataT, Nr>& coefficient3, + std::array<DataT, Nr>& coefficient4, std::array<DataT, Nr>& inverseCoefficient4) const +{ + const DataT gridSpacingR = getSpacingR(); + + int iOne = 1 << (gridFrom - 1); + int jOne = 1 << (gridFrom - 1); + int kOne = 1 << (gridFrom - 1); + + int nnPhi = Nphi; + while (nnPhi % 2 == 0) { + nnPhi *= 0.5; + } + + int tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + int tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + int tPhiSlice = kOne == 1 ? Nphi : Nphi / kOne; + tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; + + for (int count = gridFrom; count <= gridTo - 1; ++count) { + const int otPhiSlice = tPhiSlice; + const DataT h = gridSpacingR * iOne; + const DataT h2 = h * h; + const DataT ih2 = 1.0 / h2; + const DataT tempGridSizePhiInv = tPhiSlice * INVTWOPI; // phi now is multiGrid + const DataT tempRatioPhi = h2 * tempGridSizePhiInv * tempGridSizePhiInv; // ratio_{phi} = gridSize_{r} / gridSize_{phi} + const DataT tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + + for (int i = 1; i < tnRRow - 1; ++i) { + inverseCoefficient4[i] = 1.0 / coefficient4[i]; + } + + // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi + for (int jPre = 1; jPre <= nPre; ++jPre) { + relax3D(tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + } // end pre smoothing + + // 2) Residue calculation + residue3D(tvResidue[count - 1], tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, tPhiSlice, symmetry, ih2, tempRatioZ, coefficient1, coefficient2, coefficient3, inverseCoefficient4); + + iOne = 2 * iOne; + jOne = 2 * jOne; + kOne = 2 * kOne; + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + tPhiSlice = Nphi / kOne; + tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; + + //3) Restriction + restrict3D(tvCharge[count], tvResidue[count - 1], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); + + //4) Zeroing coarser V + std::fill(tvArrayV[count].begin(), tvArrayV[count].end(), 0); + } + + // coarsest grid + const DataT h = gridSpacingR * iOne; + const DataT h2 = h * h; + const DataT tempGridSizePhiInv = tPhiSlice * INVTWOPI; // phi now is multiGrid + const DataT tempRatioPhi = h2 * tempGridSizePhiInv * tempGridSizePhiInv; // ratio_{phi} = gridSize_{r} / gridSize_{phi} + const DataT tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + + // 3) Relax on the coarsest grid + relax3D(tvArrayV[gridTo - 1], tvCharge[gridTo - 1], tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + // back to fine + for (int count = gridTo - 1; count >= gridFrom; --count) { + const int otPhiSlice = tPhiSlice; + iOne = iOne * 0.5; + jOne = jOne * 0.5; + kOne = kOne * 0.5; + + tnRRow = iOne == 1 ? Nr : Nr / iOne + 1; + tnZColumn = jOne == 1 ? Nz : Nz / jOne + 1; + tPhiSlice = kOne == 1 ? Nphi : Nphi / kOne; + tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; + + const DataT h = gridSpacingR * iOne; + const DataT h2 = h * h; + const DataT tempGridSizePhiInv = tPhiSlice * INVTWOPI; + const DataT tempRatioPhi = h2 * tempGridSizePhiInv * tempGridSizePhiInv; // ratio_{phi} = gridSize_{r} / gridSize_{phi} + const DataT tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); + + // 4) Interpolation/Prolongation + addInterp3D(tvArrayV[count - 1], tvArrayV[count], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); + + calcCoefficients(1, tnRRow - 1, h, tempRatioZ, tempRatioPhi, coefficient1, coefficient2, coefficient3, coefficient4); + + // 5) Post-Smoothing: Gauss-Seidel Relaxation + for (int jPost = 1; jPost <= nPost; ++jPost) { + relax3D(tvArrayV[count - 1], tvCharge[count - 1], tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, coefficient1, coefficient2, coefficient3, coefficient4); + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::residue2D(Vector& residue, const Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const DataT ih2, const DataT inverseTempFourth, + const DataT tempRatio, std::vector<DataT>& coefficient1, std::vector<DataT>& coefficient2) +{ + const int iPhi = 0; +#pragma omp parallel for num_threads(sNThreads) + for (int i = 1; i < tnRRow - 1; ++i) { + for (int j = 1; j < tnZColumn - 1; ++j) { + residue(i, j, iPhi) = ih2 * (coefficient1[i] * matricesCurrentV(i + 1, j, iPhi) + coefficient2[i] * matricesCurrentV(i - 1, j, iPhi) + tempRatio * (matricesCurrentV(i, j + 1, iPhi) + matricesCurrentV(i, j - 1, iPhi)) - inverseTempFourth * matricesCurrentV(i, j, iPhi)) + matricesCurrentCharge(i, j, iPhi); + } // end cols + } // end nRRow + + //Boundary points. + for (int i = 0; i < tnRRow; ++i) { + residue(i, 0, iPhi) = residue(i, tnZColumn - 1, iPhi) = 0.0; + } + + for (int j = 0; j < tnZColumn; ++j) { + residue(0, j, iPhi) = residue(tnRRow - 1, j, iPhi) = 0.0; + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::residue3D(Vector& residue, const Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const int tnPhi, const int symmetry, + const DataT ih2, const DataT tempRatioZ, const std::array<DataT, Nr>& coefficient1, const std::array<DataT, Nr>& coefficient2, const std::array<DataT, Nr>& coefficient3, const std::array<DataT, Nr>& inverseCoefficient4) const +{ +#pragma omp parallel for num_threads(sNThreads) // parallising this loop is possible - but using more than 2 cores makes it slower - + for (int m = 0; m < tnPhi; ++m) { + int mp1 = m + 1; + int signPlus = 1; + int mm1 = m - 1; + int signMinus = 1; + + // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) + if (symmetry == 1) { + if (mp1 > tnPhi - 1) { + mp1 = tnPhi - 2; + } + if (mm1 < 0) { + mm1 = 1; + } + } + // Anti-symmetry in phi + else if (symmetry == -1) { + if (mp1 > tnPhi - 1) { + mp1 = tnPhi - 2; + signPlus = -1; + } + if (mm1 < 0) { + mm1 = 1; + signMinus = -1; + } + } else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi + if (mp1 > tnPhi - 1) { + mp1 = m + 1 - tnPhi; + } + if (mm1 < 0) { + mm1 = m - 1 + tnPhi; + } + } + + for (int j = 1; j < tnZColumn - 1; ++j) { + for (int i = 1; i < tnRRow - 1; ++i) { + residue(i, j, m) = ih2 * (coefficient2[i] * matricesCurrentV(i - 1, j, m) + tempRatioZ * (matricesCurrentV(i, j - 1, m) + matricesCurrentV(i, j + 1, m)) + coefficient1[i] * matricesCurrentV(i + 1, j, m) + + coefficient3[i] * (signPlus * matricesCurrentV(i, j, mp1) + signMinus * matricesCurrentV(i, j, mm1)) - inverseCoefficient4[i] * matricesCurrentV(i, j, m)) + + matricesCurrentCharge(i, j, m); + } // end cols + } // end Nr + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::interp3D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const +{ + // Do restrict 2 D for each slice + if (newPhiSlice == 2 * oldPhiSlice) { + for (int m = 0; m < newPhiSlice; m += 2) { + // assuming no symmetry + int mm = m * 0.5; + int mmPlus = mm + 1; + int mp1 = m + 1; + + // round + if (mmPlus > oldPhiSlice - 1) { + mmPlus = mm + 1 - oldPhiSlice; + } + if (mp1 > newPhiSlice - 1) { + mp1 = m + 1 - newPhiSlice; + } + + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) = matricesCurrentVC(iHalf, jHalf, mm); + // point on corner lines at phi direction + matricesCurrentV(i, j, mp1) = 0.5 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus)); + } + } + + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) = 0.5 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm)); + // point on corner lines at phi direction + matricesCurrentV(i, j, mp1) = 0.25 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus) + matricesCurrentVC(iHalf, jHalf + 1, mmPlus)); + } + } + + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) = 0.5 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf + 1, jHalf, mm)); + // point on line at phi direction + matricesCurrentV(i, j, mp1) = 0.25 * ((matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus)) + (matricesCurrentVC(iHalf + 1, jHalf, mmPlus) + matricesCurrentVC(iHalf + 1, jHalf, mm))); + } + } + + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) = 0.25 * ((matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm)) + (matricesCurrentVC(iHalf + 1, jHalf, mm) + matricesCurrentVC(iHalf + 1, jHalf + 1, mm))); + // point at the center at phi direction + matricesCurrentV(i, j, mp1) = 0.125 * ((matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus) + matricesCurrentVC(iHalf, jHalf + 1, mmPlus)) + + (matricesCurrentVC(iHalf + 1, jHalf, mm) + matricesCurrentVC(iHalf + 1, jHalf + 1, mm) + matricesCurrentVC(iHalf + 1, jHalf, mmPlus) + matricesCurrentVC(iHalf + 1, jHalf + 1, mmPlus))); + } + } + } + + } else { +#pragma omp parallel for num_threads(sNThreads) // no change + for (int m = 0; m < newPhiSlice; ++m) { + interp2D(matricesCurrentV, matricesCurrentVC, tnRRow, tnZColumn, m); + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::interp2D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int iphi) const +{ + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + matricesCurrentV(i, j, iphi) = matricesCurrentVC(i * 0.5, j * 0.5, iphi); + } + } + + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, iphi) = 0.5 * (matricesCurrentVC(iHalf, jHalf, iphi) + matricesCurrentVC(iHalf, jHalf + 1, iphi)); + } + } + + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, iphi) = 0.5 * (matricesCurrentVC(iHalf, jHalf, iphi) + matricesCurrentVC(iHalf + 1, jHalf, iphi)); + } + } + + // only if full + if (MGParameters::gtType == GridTransferType::Full) { + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, iphi) = 0.25 * (matricesCurrentVC(iHalf, jHalf, iphi) + matricesCurrentVC(iHalf, jHalf + 1, iphi) + matricesCurrentVC(iHalf + 1, jHalf, iphi) + matricesCurrentVC(iHalf + 1, jHalf + 1, iphi)); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::addInterp3D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const +{ + // Do restrict 2 D for each slice + if (newPhiSlice == 2 * oldPhiSlice) { + for (int m = 0; m < newPhiSlice; m += 2) { + // assuming no symmetry + int mm = m * 0.5; + int mmPlus = mm + 1; + int mp1 = m + 1; + + // round + if (mmPlus > (oldPhiSlice)-1) { + mmPlus = mm + 1 - (oldPhiSlice); + } + if (mp1 > (newPhiSlice)-1) { + mp1 = m + 1 - (newPhiSlice); + } + + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) += matricesCurrentVC(iHalf, jHalf, mm); + // point on corner lines at phi direction + matricesCurrentV(i, j, mp1) += 0.5 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus)); + } + } + + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) += 0.5 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm)); + // point on corner lines at phi direction + matricesCurrentV(i, j, mp1) += 0.25 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus) + matricesCurrentVC(iHalf, jHalf + 1, mmPlus)); + } + } + + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) += 0.5 * (matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf + 1, jHalf, mm)); + // point on line at phi direction + matricesCurrentV(i, j, mp1) += 0.25 * ((matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus)) + (matricesCurrentVC(iHalf + 1, jHalf, mmPlus) + matricesCurrentVC(iHalf + 1, jHalf, mm))); + } + } + + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = i * 0.5; + const int jHalf = j * 0.5; + matricesCurrentV(i, j, m) += 0.25 * ((matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm)) + (matricesCurrentVC(iHalf + 1, jHalf, mm) + matricesCurrentVC(iHalf + 1, jHalf + 1, mm))); + // point at the center at phi direction + matricesCurrentV(i, j, mp1) += 0.125 * ((matricesCurrentVC(iHalf, jHalf, mm) + matricesCurrentVC(iHalf, jHalf + 1, mm) + matricesCurrentVC(iHalf, jHalf, mmPlus) + matricesCurrentVC(iHalf, jHalf + 1, mmPlus)) + + (matricesCurrentVC(iHalf + 1, jHalf, mm) + matricesCurrentVC(iHalf + 1, jHalf + 1, mm) + matricesCurrentVC(iHalf + 1, jHalf, mmPlus) + matricesCurrentVC(iHalf + 1, jHalf + 1, mmPlus))); + } + } + } + + } else { +#pragma omp parallel for num_threads(sNThreads) // no change + for (int m = 0; m < newPhiSlice; m++) { + addInterp2D(matricesCurrentV, matricesCurrentVC, tnRRow, tnZColumn, m); + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::addInterp2D(Vector& matricesCurrentV, const Vector& matricesCurrentVC, const int tnRRow, const int tnZColumn, const int tnPhi) const +{ + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + matricesCurrentV(i, j, tnPhi) = matricesCurrentV(i, j, tnPhi) + matricesCurrentVC(i * 0.5, j * 0.5, tnPhi); + } + } + + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 2; i < tnRRow - 1; i += 2) { + const int iHalf = 0.5 * i; + const int jHalf = 0.5 * j; + matricesCurrentV(i, j, tnPhi) = matricesCurrentV(i, j, tnPhi) + 0.5 * (matricesCurrentVC(iHalf, jHalf, tnPhi) + matricesCurrentVC(iHalf, jHalf + 1, tnPhi)); + } + } + + for (int j = 2; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = 0.5 * i; + const int jHalf = 0.5 * j; + matricesCurrentV(i, j, tnPhi) = matricesCurrentV(i, j, tnPhi) + 0.5 * (matricesCurrentVC(iHalf, jHalf, tnPhi) + matricesCurrentVC(iHalf + 1, jHalf, tnPhi)); + } + } + + // only if full + if (MGParameters::gtType == GridTransferType::Full) { + for (int j = 1; j < tnZColumn - 1; j += 2) { + for (int i = 1; i < tnRRow - 1; i += 2) { + const int iHalf = 0.5 * i; + const int jHalf = 0.5 * j; + matricesCurrentV(i, j, tnPhi) = matricesCurrentV(i, j, tnPhi) + 0.25 * (matricesCurrentVC(iHalf, jHalf, tnPhi) + matricesCurrentVC(iHalf, jHalf + 1, tnPhi) + matricesCurrentVC(iHalf + 1, jHalf, tnPhi) + matricesCurrentVC(iHalf + 1, jHalf + 1, tnPhi)); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::relax3D(Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const int iPhi, const int symmetry, const DataT h2, + const DataT tempRatioZ, const std::array<DataT, Nr>& coefficient1, const std::array<DataT, Nr>& coefficient2, const std::array<DataT, Nr>& coefficient3, const std::array<DataT, Nr>& coefficient4) const +{ + // Gauss-Seidel (Read Black} + if (MGParameters::relaxType == RelaxType::GaussSeidel) { + // for each slice + for (int iPass = 1; iPass <= 2; ++iPass) { + const int msw = (iPass % 2) ? 1 : 2; + for (int m = 0; m < iPhi; ++m) { + const int jsw = ((msw + m) % 2) ? 1 : 2; + int mp1 = m + 1; + int signPlus = 1; + int mm1 = m - 1; + int signMinus = 1; + // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) + if (symmetry == 1) { + if (mp1 > iPhi - 1) { + mp1 = iPhi - 2; + } + if (mm1 < 0) { + mm1 = 1; + } + } + // Anti-symmetry in phi + else if (symmetry == -1) { + if (mp1 > iPhi - 1) { + mp1 = iPhi - 2; + signPlus = -1; + } + if (mm1 < 0) { + mm1 = 1; + signMinus = -1; + } + } else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi + if (mp1 > iPhi - 1) { + mp1 = m + 1 - iPhi; + } + if (mm1 < 0) { + mm1 = m - 1 + iPhi; + } + } + int isw = jsw; + for (int j = 1; j < tnZColumn - 1; ++j, isw = 3 - isw) { + for (int i = isw; i < tnRRow - 1; i += 2) { + (matricesCurrentV)(i, j, m) = (coefficient2[i] * (matricesCurrentV)(i - 1, j, m) + tempRatioZ * ((matricesCurrentV)(i, j - 1, m) + (matricesCurrentV)(i, j + 1, m)) + coefficient1[i] * (matricesCurrentV)(i + 1, j, m) + coefficient3[i] * (signPlus * (matricesCurrentV)(i, j, mp1) + signMinus * (matricesCurrentV)(i, j, mm1)) + (h2 * (matricesCurrentCharge)(i, j, m))) * coefficient4[i]; + } // end cols + } // end Nr + } // end phi + } // end sweep + } else if (MGParameters::relaxType == RelaxType::Jacobi) { + // for each slice + for (int m = 0; m < iPhi; ++m) { + int mp1 = m + 1; + int signPlus = 1; + int mm1 = m - 1; + int signMinus = 1; + + // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) + if (symmetry == 1) { + if (mp1 > iPhi - 1) { + mp1 = iPhi - 2; + } + if (mm1 < 0) { + mm1 = 1; + } + } + // Anti-symmetry in phi + else if (symmetry == -1) { + if (mp1 > iPhi - 1) { + mp1 = iPhi - 2; + signPlus = -1; + } + if (mm1 < 0) { + mm1 = 1; + signMinus = -1; + } + } else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi + if (mp1 > iPhi - 1) { + mp1 = m + 1 - iPhi; + } + if (mm1 < 0) { + mm1 = m - 1 + iPhi; + } + } + // Jacobian + for (int j = 1; j < tnZColumn - 1; ++j) { + for (int i = 1; i < tnRRow - 1; ++i) { + (matricesCurrentV)(i, j, m) = (coefficient2[i] * (matricesCurrentV)(i - 1, j, m) + tempRatioZ * ((matricesCurrentV)(i, j - 1, m) + (matricesCurrentV)(i, j + 1, m)) + coefficient1[i] * (matricesCurrentV)(i + 1, j, m) + coefficient3[i] * (signPlus * (matricesCurrentV)(i, j, mp1) + signMinus * (matricesCurrentV)(i, j, mm1)) + (h2 * (matricesCurrentCharge)(i, j, m))) * coefficient4[i]; + } // end cols + } // end Nr + } // end phi + } else { + // Case weighted Jacobi + // TODO + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::relax2D(Vector& matricesCurrentV, const Vector& matricesCurrentCharge, const int tnRRow, const int tnZColumn, const DataT h2, const DataT tempFourth, const DataT tempRatio, + std::vector<DataT>& coefficient1, std::vector<DataT>& coefficient2) +{ + // Gauss-Seidel + const int iPhi = 0; + if (MGParameters::relaxType == RelaxType::GaussSeidel) { + int jsw = 1; + for (int iPass = 1; iPass <= 2; ++iPass, jsw = 3 - jsw) { + int isw = jsw; + for (int j = 1; j < tnZColumn - 1; ++j, isw = 3 - isw) { + for (int i = isw; i < tnRRow - 1; i += 2) { + matricesCurrentV(i, j, iPhi) = tempFourth * (coefficient1[i] * matricesCurrentV(i + 1, j, iPhi) + coefficient2[i] * matricesCurrentV(i - 1, j, iPhi) + + tempRatio * (matricesCurrentV(i, j + 1, iPhi) + matricesCurrentV(i, j - 1, iPhi)) + (h2 * matricesCurrentCharge(i, j, iPhi))); + } // end cols + } // end Nr + } // end pass red-black + } else if (MGParameters::relaxType == RelaxType::Jacobi) { + for (int j = 1; j < tnZColumn - 1; ++j) { + for (int i = 1; i < tnRRow - 1; ++i) { + matricesCurrentV(i, j, iPhi) = tempFourth * (coefficient1[i] * matricesCurrentV(i + 1, j, iPhi) + coefficient2[i] * matricesCurrentV(i - 1, j, iPhi) + + tempRatio * (matricesCurrentV(i, j + 1, iPhi) + matricesCurrentV(i, j - 1, iPhi)) + (h2 * matricesCurrentCharge(i, j, iPhi))); + } // end cols + } // end Nr + } else if (MGParameters::relaxType == RelaxType::WeightedJacobi) { + // Weighted Jacobi + // TODO + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::restrictBoundary3D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const +{ + // in case of full 3d and the Nphi is also coarsening + if (2 * newPhiSlice == oldPhiSlice) { + for (int m = 0, mm = 0; m < newPhiSlice; ++m, mm += 2) { + // for boundary + for (int j = 0, jj = 0; j < tnZColumn; ++j, jj += 2) { + matricesCurrentCharge(0, j, m) = residue(0, jj, mm); + matricesCurrentCharge(tnRRow - 1, j, m) = residue((tnRRow - 1) * 2, jj, mm); + } + + // for boundary + for (int i = 0, ii = 0; i < tnRRow; ++i, ii += 2) { + matricesCurrentCharge(i, 0, m) = residue(ii, 0, mm); + matricesCurrentCharge(i, tnZColumn - 1, m) = residue(ii, (tnZColumn - 1) * 2, mm); + } + } // end phis + } else { + for (int m = 0; m < newPhiSlice; ++m) { + restrictBoundary2D(matricesCurrentCharge, residue, tnRRow, tnZColumn, m); + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::restrictBoundary2D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int tnPhi) const +{ + // for boundary + for (int j = 0, jj = 0; j < tnZColumn; ++j, jj += 2) { + matricesCurrentCharge(0, j, tnPhi) = residue(0, jj, tnPhi); + matricesCurrentCharge(tnRRow - 1, j, tnPhi) = residue((tnRRow - 1) * 2, jj, tnPhi); + } + + // for boundary + for (int i = 0, ii = 0; i < tnRRow; ++i, ii += 2) { + matricesCurrentCharge(i, 0, tnPhi) = residue(ii, 0, tnPhi); + matricesCurrentCharge(i, tnZColumn - 1, tnPhi) = residue(ii, (tnZColumn - 1) * 2, tnPhi); + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::restrict3D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int newPhiSlice, const int oldPhiSlice) const +{ + if (2 * newPhiSlice == oldPhiSlice) { + int mm = 0; + for (int m = 0; m < newPhiSlice; m++, mm += 2) { + // assuming no symmetry + int mp1 = mm + 1; + int mm1 = mm - 1; + + if (mp1 > (oldPhiSlice)-1) { + mp1 = mm + 1 - (oldPhiSlice); + } + if (mm1 < 0) { + mm1 = mm - 1 + (oldPhiSlice); + } + + for (int i = 1, ii = 2; i < tnRRow - 1; ++i, ii += 2) { + for (int j = 1, jj = 2; j < tnZColumn - 1; ++j, jj += 2) { + + // at the same plane + const int iip1 = ii + 1; + const int iim1 = ii - 1; + const int jjp1 = jj + 1; + const int jjm1 = jj - 1; + const DataT s1 = residue(iip1, jj, mm) + residue(iim1, jj, mm) + residue(ii, jjp1, mm) + residue(ii, jjm1, mm) + residue(ii, jj, mp1) + residue(ii, jj, mm1); + + const DataT s2 = (residue(iip1, jjp1, mm) + residue(iip1, jjm1, mm) + residue(iip1, jj, mp1) + residue(iip1, jj, mm1)) + + (residue(iim1, jjm1, mm) + residue(iim1, jjp1, mm) + residue(iim1, jj, mp1) + residue(iim1, jj, mm1)) + + residue(ii, jjm1, mp1) + residue(ii, jjp1, mm1) + residue(ii, jjm1, mm1) + residue(ii, jjp1, mp1); + + const DataT s3 = (residue(iip1, jjp1, mp1) + residue(iip1, jjm1, mp1) + residue(iip1, jjp1, mm1) + residue(iip1, jjm1, mm1)) + + (residue(iim1, jjm1, mm1) + residue(iim1, jjp1, mm1) + residue(iim1, jjm1, mp1) + residue(iim1, jjp1, mp1)); + + matricesCurrentCharge(i, j, m) = 0.125 * residue(ii, jj, mm) + 0.0625 * s1 + 0.03125 * s2 + 0.015625 * s3; + } // end cols + } // end Nr + + // for boundary + for (int j = 0, jj = 0; j < tnZColumn; ++j, jj += 2) { + matricesCurrentCharge(0, j, m) = residue(0, jj, mm); + matricesCurrentCharge(tnRRow - 1, j, m) = residue((tnRRow - 1) * 2, jj, mm); + } + + // for boundary + for (int i = 0, ii = 0; i < tnRRow; ++i, ii += 2) { + matricesCurrentCharge(i, 0, m) = residue(ii, 0, mm); + matricesCurrentCharge(i, tnZColumn - 1, m) = residue(ii, (tnZColumn - 1) * 2, mm); + } + } // end phis + + } else { + for (int m = 0; m < newPhiSlice; ++m) { + restrict2D(matricesCurrentCharge, residue, tnRRow, tnZColumn, m); + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::restrict2D(Vector& matricesCurrentCharge, const Vector& residue, const int tnRRow, const int tnZColumn, const int iphi) const +{ + for (int i = 1, ii = 2; i < tnRRow - 1; ++i, ii += 2) { + for (int j = 1, jj = 2; j < tnZColumn - 1; ++j, jj += 2) { + const int iip1 = ii + 1; + const int iim1 = ii - 1; + const int jjp1 = jj + 1; + const int jjm1 = jj - 1; + if (MGParameters::gtType == GridTransferType::Half) { + // half + matricesCurrentCharge(i, j, iphi) = 0.5 * residue(ii, jj, iphi) + 0.125 * (residue(iip1, jj, iphi) + residue(iim1, jj, iphi) + residue(ii, jjp1, iphi) + residue(ii, jjm1, iphi)); + } else if (MGParameters::gtType == GridTransferType::Full) { + matricesCurrentCharge(i, j, iphi) = 0.25 * residue(ii, jj, iphi) + 0.125 * (residue(iip1, jj, iphi) + residue(iim1, jj, iphi) + residue(ii, jjp1, iphi) + residue(ii, jjm1, iphi)) + + 0.0625 * (residue(iip1, jjp1, iphi) + residue(iim1, jjp1, iphi) + residue(iip1, jjm1, iphi) + residue(iim1, jjm1, iphi)); + } + } // end cols + } // end Nr + // boundary + // for boundary + for (int j = 0, jj = 0; j < tnZColumn; ++j, jj += 2) { + matricesCurrentCharge(0, j, iphi) = residue(0, jj, iphi); + matricesCurrentCharge(tnRRow - 1, j, iphi) = residue((tnRRow - 1) * 2, jj, iphi); + } + // for boundary + for (int i = 0, ii = 0; i < tnRRow; ++i, ii += 2) { + matricesCurrentCharge(i, 0, iphi) = residue(ii, 0, iphi); + matricesCurrentCharge(i, tnZColumn - 1, iphi) = residue(ii, (tnZColumn - 1) * 2, iphi); + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT PoissonSolver<DataT, Nz, Nr, Nphi>::getConvergenceError(const Vector& matricesCurrentV, Vector& prevArrayV) const +{ + std::vector<DataT> errorArr(prevArrayV.getNphi()); + + // subtract the two matrices + std::transform(prevArrayV.begin(), prevArrayV.end(), matricesCurrentV.begin(), prevArrayV.begin(), std::minus<DataT>()); + +#pragma omp parallel for num_threads(sNThreads) // parallising this loop is possible - but using more than 2 cores makes it slower - + for (unsigned int m = 0; m < prevArrayV.getNphi(); ++m) { + // square each entry in the vector and sum them up + const auto phiStep = prevArrayV.getNr() * prevArrayV.getNz(); // number of points in one phi slice + const auto start = prevArrayV.begin() + m * phiStep; + const auto end = start + phiStep; + errorArr[m] = std::inner_product(start, end, start, 0.); // inner product "Sum (matrix[a]*matrix[a])" + } + // return largest error + return *std::max_element(std::begin(errorArr), std::end(errorArr)); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::calcCoefficients(unsigned int from, unsigned int to, const DataT h, const DataT tempRatioZ, const DataT tempRatioPhi, std::array<DataT, Nr>& coefficient1, std::array<DataT, Nr>& coefficient2, std::array<DataT, Nr>& coefficient3, std::array<DataT, Nr>& coefficient4) const +{ + for (unsigned int i = from; i < to; ++i) { + const DataT radiusInv = 1. / (TPCParameters<DataT>::IFCRADIUS + i * h); + const DataT hRadiusTmp = h * 0.5 * radiusInv; + coefficient1[i] = 1.0 + hRadiusTmp; + coefficient2[i] = 1.0 - hRadiusTmp; + coefficient3[i] = tempRatioPhi * radiusInv * radiusInv; + coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void PoissonSolver<DataT, Nz, Nr, Nphi>::calcCoefficients2D(unsigned int from, unsigned int to, const DataT h, std::vector<DataT>& coefficient1, std::vector<DataT>& coefficient2) const +{ + for (int i = from; i < to; ++i) { + DataT radiusInvHalf = h * 0.5 / (TPCParameters<DataT>::IFCRADIUS + i * h); + coefficient1[i] = 1.0 + radiusInvHalf; + coefficient2[i] = 1.0 - radiusInvHalf; + } +} + +template class o2::tpc::PoissonSolver<double, 17, 17, 90>; +template class o2::tpc::PoissonSolver<double, 33, 33, 180>; +template class o2::tpc::PoissonSolver<double, 65, 65, 180>; +template class o2::tpc::PoissonSolver<double, 129, 129, 180>; +template class o2::tpc::PoissonSolver<double, 257, 257, 180>; +template class o2::tpc::PoissonSolver<double, 257, 257, 360>; +template class o2::tpc::PoissonSolver<double, 129, 129, 1>; // for 2D Poisson Solver diff --git a/Detectors/TPC/spacecharge/src/SpaceCharge.cxx b/Detectors/TPC/spacecharge/src/SpaceCharge.cxx new file mode 100644 index 0000000000000..dbe6f8af67120 --- /dev/null +++ b/Detectors/TPC/spacecharge/src/SpaceCharge.cxx @@ -0,0 +1,1251 @@ +// 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 SpaceCharge.cxx +/// \brief Definition of SpaceCharge class +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> +/// \date Aug 21, 2020 + +#include "TPCSpaceCharge/SpaceCharge.h" +#include "fmt/core.h" +#include "Framework/Logger.h" +#include <chrono> + +#ifdef WITH_OPENMP +#include <omp.h> +#endif + +templateClassImp(o2::tpc::SpaceCharge); + +using namespace o2::tpc; + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::calculateDistortionsCorrections(const o2::tpc::Side side) +{ + using timer = std::chrono::high_resolution_clock; + using SC = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>; + if (!mIsChargeSet[side]) { + LOGP(ERROR, "the charge is not set!"); + } + + const std::array<std::string, 2> sglobalType{"local distortion/correction interpolator", "Electric fields"}; + const std::array<std::string, 2> sglobalDistType{"Standard method", "interpolation of global corrections"}; + const std::array<std::string, 2> sideName{"A", "C"}; + + LOGP(info, "====== starting calculation of distortions and corrections for Side {} ======", sideName[side]); + LOGP(info, "Using {} threads", getNThreads()); + + if (getGlobalDistCorrMethod() == SC::GlobalDistCorrMethod::LocalDistCorr) { + LOGP(info, "calculation of global distortions and corrections are performed by using: {}", sglobalType[0]); + } else { + LOGP(info, "calculation of global distortions and corrections are performed by using: {}", sglobalType[1]); + } + + if (getGlobalDistType() == SC::GlobalDistType::Fast) { + LOGP(info, "calculation of global distortions performed by following method: {}", sglobalDistType[1]); + } else if (getGlobalDistType() == SC::GlobalDistType::Standard) { + LOGP(info, "calculation of global distortions performed by following method: {}", sglobalDistType[0]); + } else { + LOGP(info, "skipping calculation of global distortions"); + } + + auto startTotal = timer::now(); + + auto start = timer::now(); + poissonSolver(side); + auto stop = timer::now(); + std::chrono::duration<float> time = stop - start; + LOGP(info, "Poisson Solver time: {}", time.count()); + + start = timer::now(); + calcEField(side); + stop = timer::now(); + time = stop - start; + LOGP(info, "electric field calculation time: {}", time.count()); + + const auto numEFields = getElectricFieldsInterpolator(side); + if (getGlobalDistType() == SC::GlobalDistType::Standard) { + start = timer::now(); + const auto dist = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>::Type::Distortions; + calcLocalDistortionsCorrections(dist, numEFields); // local distortion calculation + stop = timer::now(); + time = stop - start; + LOGP(info, "local distortions time: {}", time.count()); + } else { + LOGP(info, "skipping local distortions (not needed)"); + } + + start = timer::now(); + const auto corr = o2::tpc::SpaceCharge<DataT, Nz, Nr, Nphi>::Type::Corrections; + calcLocalDistortionsCorrections(corr, numEFields); // local correction calculation + stop = timer::now(); + time = stop - start; + LOGP(info, "local corrections time: {}", time.count()); + + start = timer::now(); + const auto lCorrInterpolator = getLocalCorrInterpolator(side); + (getGlobalDistCorrMethod() == SC::GlobalDistCorrMethod::LocalDistCorr) ? calcGlobalCorrections(lCorrInterpolator) : calcGlobalCorrections(numEFields); + stop = timer::now(); + time = stop - start; + LOGP(info, "global corrections time: {}", time.count()); + start = timer::now(); + if (getGlobalDistType() == SC::GlobalDistType::Fast) { + const auto globalCorrInterpolator = getGlobalCorrInterpolator(side); + calcGlobalDistWithGlobalCorrIterative(globalCorrInterpolator); + } else if (getGlobalDistType() == SC::GlobalDistType::Standard) { + const auto lDistInterpolator = getLocalDistInterpolator(side); + (getGlobalDistCorrMethod() == SC::GlobalDistCorrMethod::LocalDistCorr) ? calcGlobalDistortions(lDistInterpolator) : calcGlobalDistortions(numEFields); + } else { + } + + stop = timer::now(); + time = stop - start; + LOGP(info, "global distortions time: {}", time.count()); + + stop = timer::now(); + time = stop - startTotal; + LOGP(info, "everything is done. Total Time: {}", time.count()); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT SpaceCharge<DataT, Nz, Nr, Nphi>::regulateR(const DataT posR, const Side side) const +{ + const DataT minR = getRMin(side) - 4 * getGridSpacingR(side); + if (posR < minR) { + return minR; + } + const DataT maxR = getRMax(side) + 2 * getGridSpacingR(side); + if (posR > maxR) { + return maxR; + } + return posR; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setFromFile(TFile& file, const Side side) +{ + setDensityFromFile(file, side); + setPotentialFromFile(file, side); + setElectricFieldsFromFile(file, side); + setLocalDistortionsFromFile(file, side); + setLocalCorrectionsFromFile(file, side); + setGlobalDistortionsFromFile(file, side); + setGlobalCorrectionsFromFile(file, side); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setChargeDensityFromFormula(const AnalyticalFields<DataT>& formulaStruct) +{ + const Side side = formulaStruct.getSide(); + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex(iR, side); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex(iZ, side); + mDensity[side](iZ, iR, iPhi) = formulaStruct.evalDensity(z, radius, phi); + } + } + } + mIsChargeSet[side] = true; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setPotentialFromFormula(const AnalyticalFields<DataT>& formulaStruct) +{ + const Side side = formulaStruct.getSide(); + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex(iR, side); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex(iZ, side); + mPotential[side](iZ, iR, iPhi) = formulaStruct.evalPotential(z, radius, phi); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setPotentialBoundaryFromFormula(const AnalyticalFields<DataT>& formulaStruct) +{ + const Side side = formulaStruct.getSide(); + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex(iZ, side); + const size_t iR = 0; + const DataT radius = getRVertex(iR, side); + mPotential[side](iZ, iR, iPhi) = formulaStruct.evalPotential(z, radius, phi); + } + } + + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex(iZ, side); + const size_t iR = Nr - 1; + const DataT radius = getRVertex(iR, side); + mPotential[side](iZ, iR, iPhi) = formulaStruct.evalPotential(z, radius, phi); + } + } + + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex(iR, side); + const size_t iZ = 0; + const DataT z = getZVertex(iZ, side); + mPotential[side](iZ, iR, iPhi) = formulaStruct.evalPotential(z, radius, phi); + } + } + + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex(iR, side); + const size_t iZ = Nz - 1; + const DataT z = getZVertex(iZ, side); + mPotential[side](iZ, iR, iPhi) = formulaStruct.evalPotential(z, radius, phi); + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::poissonSolver(const Side side, const int maxIteration, const DataT stoppingConvergence, const int symmetry) +{ + ASolv::setConvergenceError(stoppingConvergence); + ASolv poissonSolver(mGrid3D[0]); + poissonSolver.poissonSolver3D(mPotential[side], mDensity[side], symmetry); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setEFieldFromFormula(const AnalyticalFields<DataT>& formulaStruct) +{ + const Side side = formulaStruct.getSide(); + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + for (size_t iR = 0; iR < Nr; ++iR) { + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT radius = getRVertex(iR, side); + const DataT z = getZVertex(iZ, side); + const DataT phi = getPhiVertex(iPhi, side); + mElectricFieldEr[side](iZ, iR, iPhi) = formulaStruct.evalEr(z, radius, phi); + mElectricFieldEz[side](iZ, iR, iPhi) = formulaStruct.evalEz(z, radius, phi); + mElectricFieldEphi[side](iZ, iR, iPhi) = formulaStruct.evalEphi(z, radius, phi); + } + } + } + mIsEfieldSet[side] = true; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::calcEField(const Side side) +{ +#pragma omp parallel for num_threads(sNThreads) + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const int symmetry = 0; + size_t tmpPlus = iPhi + 1; + int signPlus = 1; + int tmpMinus = static_cast<int>(iPhi - 1); + int signMinus = 1; + if (symmetry == 1 || symmetry == -1) { // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) + if (tmpPlus > Nphi - 1) { + if (symmetry == -1) { + signPlus = -1; + } + tmpPlus = Nphi - 2; + } + if (tmpMinus < 0) { + tmpMinus = 1; // SHOULD IT BE =0? + if (symmetry == -1) { + signMinus = -1; + } + } + } else { // No Symmetries in phi, no boundaries, the calculations is continuous across all phi + if (tmpPlus > Nphi - 1) { + tmpPlus = iPhi + 1 - Nphi; + } + if (tmpMinus < 0) { + tmpMinus = static_cast<int>(iPhi - 1 + Nphi); + } + } + + // for non-boundary V + for (size_t iR = 1; iR < Nr - 1; iR++) { + const DataT radius = getRVertex(iR, side); + for (size_t iZ = 1; iZ < Nz - 1; iZ++) { + mElectricFieldEr[side](iZ, iR, iPhi) = -1 * (mPotential[side](iZ, iR + 1, iPhi) - mPotential[side](iZ, iR - 1, iPhi)) * static_cast<DataT>(0.5) * getInvSpacingR(side); // r direction + mElectricFieldEz[side](iZ, iR, iPhi) = -1 * (mPotential[side](iZ + 1, iR, iPhi) - mPotential[side](iZ - 1, iR, iPhi)) * static_cast<DataT>(0.5) * getInvSpacingZ(side); // z direction + mElectricFieldEphi[side](iZ, iR, iPhi) = -1 * (signPlus * mPotential[side](iZ, iR, tmpPlus) - signMinus * mPotential[side](iZ, iR, tmpMinus)) * static_cast<DataT>(0.5) * getInvSpacingPhi(side) / radius; // phi direction + } + } + + // for boundary-r + for (size_t iZ = 0; iZ < Nz; iZ++) { + mElectricFieldEr[side](iZ, 0, iPhi) = -1 * (-static_cast<DataT>(0.5) * mPotential[side](iZ, 2, iPhi) + 2 * mPotential[side](iZ, 1, iPhi) - static_cast<DataT>(1.5) * mPotential[side](iZ, 0, iPhi)) * getInvSpacingR(side); // forward difference + mElectricFieldEr[side](iZ, Nr - 1, iPhi) = -1 * (static_cast<DataT>(1.5) * mPotential[side](iZ, Nr - 1, iPhi) - 2 * mPotential[side](iZ, Nr - 2, iPhi) + static_cast<DataT>(0.5) * mPotential[side](iZ, Nr - 3, iPhi)) * getInvSpacingR(side); // backward difference + } + + for (size_t iR = 0; iR < Nr; iR += Nr - 1) { + const DataT radius = getRVertex(iR, side); + for (size_t iZ = 1; iZ < Nz - 1; iZ++) { + mElectricFieldEz[side](iZ, iR, iPhi) = -1 * (mPotential[side](iZ + 1, iR, iPhi) - mPotential[side](iZ - 1, iR, iPhi)) * static_cast<DataT>(0.5) * getInvSpacingZ(side); // z direction + mElectricFieldEphi[side](iZ, iR, iPhi) = -1 * (signPlus * mPotential[side](iZ, iR, tmpPlus) - signMinus * mPotential[side](iZ, iR, tmpMinus)) * static_cast<DataT>(0.5) * getInvSpacingPhi(side) / radius; // phi direction + } + } + + // for boundary-z + for (size_t iR = 0; iR < Nr; ++iR) { + mElectricFieldEz[side](0, iR, iPhi) = -1 * (-static_cast<DataT>(0.5) * mPotential[side](2, iR, iPhi) + 2 * mPotential[side](1, iR, iPhi) - static_cast<DataT>(1.5) * mPotential[side](0, iR, iPhi)) * getInvSpacingZ(side); + mElectricFieldEz[side](Nz - 1, iR, iPhi) = -1 * (static_cast<DataT>(1.5) * mPotential[side](Nz - 1, iR, iPhi) - 2 * mPotential[side](Nz - 2, iR, iPhi) + static_cast<DataT>(0.5) * mPotential[side](Nz - 3, iR, iPhi)) * getInvSpacingZ(side); + } + + for (size_t iR = 1; iR < Nr - 1; ++iR) { + const DataT radius = getRVertex(iR, side); + for (size_t iZ = 0; iZ < Nz; iZ += Nz - 1) { + mElectricFieldEr[side](iZ, iR, iPhi) = -1 * (mPotential[side](iZ, iR + 1, iPhi) - mPotential[side](iZ, iR - 1, iPhi)) * static_cast<DataT>(0.5) * getInvSpacingR(side); // r direction + mElectricFieldEphi[side](iZ, iR, iPhi) = -1 * (signPlus * mPotential[side](iZ, iR, tmpPlus) - signMinus * mPotential[side](iZ, iR, tmpMinus)) * static_cast<DataT>(0.5) * getInvSpacingPhi(side) / radius; // phi direction + } + } + + // corner points for EPhi + for (size_t iR = 0; iR < Nr; iR += Nr - 1) { + const DataT radius = getRVertex(iR, side); + for (size_t iZ = 0; iZ < Nz; iZ += Nz - 1) { + mElectricFieldEphi[side](iZ, iR, iPhi) = -1 * (signPlus * mPotential[side](iZ, iR, tmpPlus) - signMinus * mPotential[side](iZ, iR, tmpMinus)) * static_cast<DataT>(0.5) * getInvSpacingPhi(side) / radius; // phi direction + } + } + } + mIsEfieldSet[side] = true; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::calcGlobalDistWithGlobalCorrIterative(const DistCorrInterpolator<DataT, Nz, Nr, Nphi>& globCorr, const int maxIter, const DataT approachZ, const DataT approachR, const DataT approachPhi, const DataT diffCorr) +{ + const Side side = globCorr.getSide(); + +#pragma omp parallel for num_threads(sNThreads) + for (unsigned int iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (unsigned int iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex(iR, side); + for (unsigned int iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex(iZ, side); + + unsigned int nearestiZ = iZ; + unsigned int nearestiR = iR; + unsigned int nearestiPhi = iPhi; + + DataT nearestZ = getZVertex(nearestiZ, side); + DataT nearestR = getRVertex(nearestiR, side); + DataT nearestPhi = getPhiVertex(nearestiPhi, side); + + // + //========================================================================================== + //==== start algorithm: use tricubic upsampling to numerically approach the query point ==== + //========================================================================================== + // + // 1. calculate difference from nearest point to query point with stepwidth factor x + // and approach the new point + // + DataT stepR = (radius - nearestR) * approachR; + DataT stepZ = (z - nearestZ) * approachZ; + DataT stepPhi = (phi - nearestPhi) * approachPhi; + + // needed to check for convergence + DataT lastCorrdR = std::numeric_limits<DataT>::max(); + DataT lastCorrdZ = std::numeric_limits<DataT>::max(); + DataT lastCorrdRPhi = std::numeric_limits<DataT>::max(); + + // interpolated global correction + DataT corrdR = 0; + DataT corrdRPhi = 0; + DataT corrdZ = 0; + + for (int iter = 0; iter < maxIter; ++iter) { + // 2. get new point coordinates + const DataT rCurrPos = getRVertex(nearestiR, side) + stepR; + const DataT zCurrPos = getZVertex(nearestiZ, side) + stepZ; + const DataT phiCurrPos = getPhiVertex(nearestiPhi, side) + stepPhi; + + // interpolate global correction at new point and calculate position of global correction + // corrdR = globCorr.evalSparsedR(zCurrPos, rCurrPos, phiCurrPos); + corrdR = globCorr.evaldR(zCurrPos, rCurrPos, phiCurrPos); + const DataT rNewPos = rCurrPos + corrdR; + + // const DataT corrPhi = globCorr.evalSparsedRPhi(zCurrPos, rCurrPos, phiCurrPos) / rCurrPos; + const DataT corrPhi = globCorr.evaldRPhi(zCurrPos, rCurrPos, phiCurrPos) / rCurrPos; + corrdRPhi = corrPhi * rNewPos; // normalize to new r coordinate + const DataT phiNewPos = phiCurrPos + corrPhi; + + // corrdZ = globCorr.evalSparsedZ(zCurrPos, rCurrPos, phiCurrPos); + corrdZ = globCorr.evaldZ(zCurrPos, rCurrPos, phiCurrPos); + const DataT zNewPos = zCurrPos + corrdZ; + + // approach desired coordinate + stepR += (radius - rNewPos) * approachR; + stepZ += (z - zNewPos) * approachZ; + stepPhi += (phi - phiNewPos) * approachPhi; + + // check for convergence + const DataT diffCorrdR = std::abs(corrdR - lastCorrdR); + const DataT diffCorrdRZ = std::abs(corrdZ - lastCorrdZ); + const DataT diffCorrdRPhi = std::abs(corrdRPhi - lastCorrdRPhi); + + // stop algorithm if converged + if (diffCorrdR < diffCorr && diffCorrdRZ < diffCorr && diffCorrdRPhi < diffCorr) { + break; + } + + lastCorrdR = corrdR; + lastCorrdZ = corrdZ; + lastCorrdRPhi = corrdRPhi; + } + // set global distortions if algorithm converged or iterations exceed max numbers of iterations + mGlobalDistdR[side](iZ, iR, iPhi) = -corrdR; + mGlobalDistdRPhi[side](iZ, iR, iPhi) = -corrdRPhi; + mGlobalDistdZ[side](iZ, iR, iPhi) = -corrdZ; + } + } + } + // set flag that global distortions are set to true + mIsGlobalDistSet[side] = true; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +NumericalFields<DataT, Nz, Nr, Nphi> SpaceCharge<DataT, Nz, Nr, Nphi>::getElectricFieldsInterpolator(const Side side) const +{ + if (!mIsEfieldSet[side]) { + LOGP(warning, "============== E-Fields are not set! ==============\n"); + } + NumericalFields<DataT, Nz, Nr, Nphi> numFields(mElectricFieldEr[side], mElectricFieldEz[side], mElectricFieldEphi[side], mGrid3D[side], side); + return numFields; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DistCorrInterpolator<DataT, Nz, Nr, Nphi> SpaceCharge<DataT, Nz, Nr, Nphi>::getLocalDistInterpolator(const Side side) const +{ + if (!mIsLocalDistSet[side]) { + LOGP(warning, "============== local distortions not set! ==============\n"); + } + DistCorrInterpolator<DataT, Nz, Nr, Nphi> numFields(mLocalDistdR[side], mLocalDistdZ[side], mLocalDistdRPhi[side], mGrid3D[side], side); + return numFields; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DistCorrInterpolator<DataT, Nz, Nr, Nphi> SpaceCharge<DataT, Nz, Nr, Nphi>::getLocalCorrInterpolator(const Side side) const +{ + if (!mIsLocalCorrSet[side]) { + LOGP(warning, "============== local corrections not set! ==============\n"); + } + DistCorrInterpolator<DataT, Nz, Nr, Nphi> numFields(mLocalCorrdR[side], mLocalCorrdZ[side], mLocalCorrdRPhi[side], mGrid3D[side], side); + return numFields; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DistCorrInterpolator<DataT, Nz, Nr, Nphi> SpaceCharge<DataT, Nz, Nr, Nphi>::getGlobalDistInterpolator(const Side side) const +{ + if (!mIsGlobalDistSet[side]) { + LOGP(warning, "============== global distortions not set ==============\n"); + } + DistCorrInterpolator<DataT, Nz, Nr, Nphi> numFields(mGlobalDistdR[side], mGlobalDistdZ[side], mGlobalDistdRPhi[side], mGrid3D[side], side); + return numFields; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DistCorrInterpolator<DataT, Nz, Nr, Nphi> SpaceCharge<DataT, Nz, Nr, Nphi>::getGlobalCorrInterpolator(const Side side) const +{ + if (!mIsGlobalCorrSet[side]) { + LOGP(warning, "============== global corrections not set ==============\n"); + } + DistCorrInterpolator<DataT, Nz, Nr, Nphi> numFields(mGlobalCorrdR[side], mGlobalCorrdZ[side], mGlobalCorrdRPhi[side], mGrid3D[side], side); + return numFields; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +int SpaceCharge<DataT, Nz, Nr, Nphi>::dumpElectricFields(TFile& outf, const Side side) const +{ + if (!mIsEfieldSet[side]) { + LOGP(warning, "============== E-Fields are not set! returning ==============\n"); + return 0; + } + const std::string sideName = getSideName(side); + const int er = mElectricFieldEr[side].writeToFile(outf, fmt::format("fieldEr_side{}", sideName).data()); + const int ez = mElectricFieldEz[side].writeToFile(outf, fmt::format("fieldEz_side{}", sideName).data()); + const int ephi = mElectricFieldEphi[side].writeToFile(outf, fmt::format("fieldEphi_side{}", sideName).data()); + return er + ez + ephi; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setElectricFieldsFromFile(TFile& inpf, const Side side) +{ + const std::string sideName = getSideName(side); + mElectricFieldEr[side].initFromFile(inpf, fmt::format("fieldEr_side{}", sideName).data()); + mElectricFieldEz[side].initFromFile(inpf, fmt::format("fieldEz_side{}", sideName).data()); + mElectricFieldEphi[side].initFromFile(inpf, fmt::format("fieldEphi_side{}", sideName).data()); + mIsEfieldSet[side] = true; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +int SpaceCharge<DataT, Nz, Nr, Nphi>::dumpGlobalDistortions(TFile& outf, const Side side) const +{ + if (!mIsGlobalDistSet[side]) { + LOGP(warning, "============== global distortions are not set! returning ==============\n"); + return 0; + } + const std::string sideName = getSideName(side); + const int er = mGlobalDistdR[side].writeToFile(outf, fmt::format("distR_side{}", sideName).data()); + const int ez = mGlobalDistdZ[side].writeToFile(outf, fmt::format("distZ_side{}", sideName).data()); + const int ephi = mGlobalDistdRPhi[side].writeToFile(outf, fmt::format("distRphi_side{}", sideName).data()); + return er + ez + ephi; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setGlobalDistortionsFromFile(TFile& inpf, const Side side) +{ + mIsGlobalDistSet[side] = true; + const std::string sideName = getSideName(side); + mGlobalDistdR[side].initFromFile(inpf, fmt::format("distR_side{}", sideName).data()); + mGlobalDistdZ[side].initFromFile(inpf, fmt::format("distZ_side{}", sideName).data()); + mGlobalDistdRPhi[side].initFromFile(inpf, fmt::format("distRphi_side{}", sideName).data()); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +int SpaceCharge<DataT, Nz, Nr, Nphi>::dumpGlobalCorrections(TFile& outf, const Side side) const +{ + if (!mIsGlobalCorrSet[side]) { + LOGP(warning, "============== global corrections are not set! returning ==============\n"); + return 0; + } + const std::string sideName = getSideName(side); + const int er = mGlobalCorrdR[side].writeToFile(outf, fmt::format("corrR_side{}", sideName).data()); + const int ez = mGlobalCorrdZ[side].writeToFile(outf, fmt::format("corrZ_side{}", sideName).data()); + const int ephi = mGlobalCorrdRPhi[side].writeToFile(outf, fmt::format("corrRPhi_side{}", sideName).data()); + return er + ez + ephi; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setGlobalCorrectionsFromFile(TFile& inpf, const Side side) +{ + mIsGlobalCorrSet[side] = true; + const std::string sideName = getSideName(side); + mGlobalCorrdR[side].initFromFile(inpf, fmt::format("corrR_side{}", sideName).data()); + mGlobalCorrdZ[side].initFromFile(inpf, fmt::format("corrZ_side{}", sideName).data()); + mGlobalCorrdRPhi[side].initFromFile(inpf, fmt::format("corrRPhi_side{}", sideName).data()); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +int SpaceCharge<DataT, Nz, Nr, Nphi>::dumpLocalCorrections(TFile& outf, const Side side) const +{ + if (!mIsLocalCorrSet[side]) { + LOGP(warning, "============== local corrections are not set! returning ==============\n"); + return 0; + } + const std::string sideName = getSideName(side); + const int lCorrdR = mLocalCorrdR[side].writeToFile(outf, fmt::format("lcorrR_side{}", sideName).data()); + const int lCorrdZ = mLocalCorrdZ[side].writeToFile(outf, fmt::format("lcorrZ_side{}", sideName).data()); + const int lCorrdRPhi = mLocalCorrdRPhi[side].writeToFile(outf, fmt::format("lcorrRPhi_side{}", sideName).data()); + return lCorrdR + lCorrdZ + lCorrdRPhi; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setLocalCorrectionsFromFile(TFile& inpf, const Side side) +{ + const std::string sideName = getSideName(side); + const bool lCorrdR = mLocalCorrdR[side].initFromFile(inpf, fmt::format("lcorrR_side{}", sideName).data()); + const bool lCorrdZ = mLocalCorrdZ[side].initFromFile(inpf, fmt::format("lcorrZ_side{}", sideName).data()); + const bool lCorrdRPhi = mLocalCorrdRPhi[side].initFromFile(inpf, fmt::format("lcorrRPhi_side{}", sideName).data()); + if (lCorrdR && lCorrdZ && lCorrdRPhi) { + mIsLocalCorrSet[side] = true; + } else { + mIsLocalCorrSet[side] = false; + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +int SpaceCharge<DataT, Nz, Nr, Nphi>::dumpLocalDistortions(TFile& outf, const Side side) const +{ + if (!mIsLocalDistSet[side]) { + LOGP(warning, "============== local distortions are not set! returning ==============\n"); + return 0; + } + const std::string sideName = getSideName(side); + const int lDistdR = mLocalDistdR[side].writeToFile(outf, fmt::format("ldistR_side{}", sideName).data()); + const int lDistdZ = mLocalDistdZ[side].writeToFile(outf, fmt::format("ldistZ_side{}", sideName).data()); + const int lDistdRPhi = mLocalDistdRPhi[side].writeToFile(outf, fmt::format("ldistRPhi_side{}", sideName).data()); + return lDistdR + lDistdZ + lDistdRPhi; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setLocalDistortionsFromFile(TFile& inpf, const Side side) +{ + const std::string sideName = getSideName(side); + const bool lDistdR = mLocalDistdR[side].initFromFile(inpf, fmt::format("ldistR_side{}", sideName).data()); + const bool lDistdZ = mLocalDistdZ[side].initFromFile(inpf, fmt::format("ldistZ_side{}", sideName).data()); + const bool lDistdRPhi = mLocalDistdRPhi[side].initFromFile(inpf, fmt::format("ldistRPhi_side{}", sideName).data()); + + if (lDistdR && lDistdZ && lDistdRPhi) { + mIsLocalDistSet[side] = true; + } else { + mIsLocalDistSet[side] = false; + } +} +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::fillChargeDensityFromFile(TFile& fInp, const char* name) +{ + const TH3* hisSCDensity3D = (TH3*)fInp.Get(name); + fillChargeDensityFromHisto(*hisSCDensity3D); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::fillChargeDensityFromHisto(const TH3& hisSCDensity3D) +{ + TH3D hRebin = rebinDensityHisto(hisSCDensity3D); + for (int side = Side::A; side < SIDES; ++side) { + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + for (size_t iR = 0; iR < Nr; ++iR) { + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const size_t zBin = side == Side::A ? Nz + iZ + 1 : Nz - iZ; // TODO CHECK THIS! + mDensity[side](iZ, iR, iPhi) = hRebin.GetBinContent(iPhi, iR, zBin); + } + } + } + mIsChargeSet[side] = true; + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +TH3D SpaceCharge<DataT, Nz, Nr, Nphi>::rebinDensityHisto(const TH3& hOrig) const +{ + TH3D hRebin{}; + + const int nBinsPhiNew = Nphi; + const int nBinsRNew = Nr; + const int nBinsZNew = 2 * Nz; + + const auto phiLow = hOrig.GetXaxis()->GetBinLowEdge(1); + const auto phiUp = hOrig.GetXaxis()->GetBinUpEdge(hOrig.GetNbinsX()); + const auto rLow = hOrig.GetYaxis()->GetBinLowEdge(1); + const auto rUp = hOrig.GetYaxis()->GetBinUpEdge(hOrig.GetNbinsY()); + const auto zLow = hOrig.GetZaxis()->GetBinLowEdge(1); + const auto zUp = hOrig.GetZaxis()->GetBinUpEdge(hOrig.GetNbinsZ()); + hRebin.SetBins(nBinsPhiNew, phiLow, phiUp, nBinsRNew, rLow, rUp, nBinsZNew, zLow, zUp); + + for (int iBinPhi = 1; iBinPhi <= nBinsPhiNew; ++iBinPhi) { + const auto phiLowEdge = hRebin.GetXaxis()->GetBinLowEdge(iBinPhi); + const auto phiUpEdge = hRebin.GetXaxis()->GetBinUpEdge(iBinPhi); + + const int phiLowBinOrig = hOrig.GetXaxis()->FindBin(phiLowEdge); + const int phiUpBinOrig = hOrig.GetXaxis()->FindBin(phiUpEdge); + + // calculate the weights (area of original bin lies in the new bin / binwidthOrig) of the first and last bins + const auto binWidthPhiOrig = hOrig.GetXaxis()->GetBinWidth(phiLowBinOrig); + const auto lowerBinWeightPhi = std::abs(phiLowEdge - hOrig.GetXaxis()->GetBinUpEdge(phiLowBinOrig)) / binWidthPhiOrig; + const auto upperBinWeightPhi = std::abs(phiUpEdge - hOrig.GetXaxis()->GetBinLowEdge(phiUpBinOrig)) / binWidthPhiOrig; + + for (int iBinR = 1; iBinR <= nBinsRNew; ++iBinR) { + const auto rLowEdge = hRebin.GetYaxis()->GetBinLowEdge(iBinR); + const auto rUpEdge = hRebin.GetYaxis()->GetBinUpEdge(iBinR); + + const int rLowBinOrig = hOrig.GetYaxis()->FindBin(rLowEdge); + const int rUpBinOrig = hOrig.GetYaxis()->FindBin(rUpEdge); + + // calculate the weights (area of original bin lies in the new bin / binwidthOrig) of the first and last bins + const auto binWidthROrig = hOrig.GetYaxis()->GetBinWidth(rLowBinOrig); + const auto lowerBinWeightR = std::abs(rLowEdge - hOrig.GetYaxis()->GetBinUpEdge(rLowBinOrig)) / binWidthROrig; + const auto upperBinWeightR = std::abs(rUpEdge - hOrig.GetYaxis()->GetBinLowEdge(rUpBinOrig)) / binWidthROrig; + + for (int iBinZ = 1; iBinZ <= nBinsZNew; ++iBinZ) { + const auto zLowEdge = hRebin.GetZaxis()->GetBinLowEdge(iBinZ); + const auto zUpEdge = hRebin.GetZaxis()->GetBinUpEdge(iBinZ); + const auto zCenter = hRebin.GetZaxis()->GetBinCenter(iBinZ); + + int zLowBinOrig = hOrig.GetZaxis()->FindBin(zLowEdge); + int zUpBinOrig = hOrig.GetZaxis()->FindBin(zUpEdge); + const int currside = getSide(zCenter); // set the side of the current z-bin + // get the side of the lowest and uppest bin from the orig histo + const int sideLowOrig = getSide(hOrig.GetZaxis()->GetBinCenter(zLowBinOrig)); + const int sideUpOrig = getSide(hOrig.GetZaxis()->GetBinCenter(zUpBinOrig)); + + // make bounds/side check of the zLowBinOrig and zUpBinOrig bins. They must be on the same side as the currside!!! + if (currside != sideLowOrig && zLowBinOrig != zUpBinOrig) { + // if the lower bins from the orig histo are not on the same side as the rebinned increase the binnumber until they are on the same side + bool notequal = true; + do { + zLowBinOrig += 1; + if (zLowBinOrig > zUpBinOrig) { + LOGP(WARNING, "SOMETHING WENT WRONG: SETTING BINS TO: {}", zUpBinOrig); + zLowBinOrig = zUpBinOrig; + notequal = false; + } + const int sideTmp = getSide(hOrig.GetZaxis()->GetBinCenter(zLowBinOrig)); + if (sideTmp == currside) { + notequal = false; + } + } while (notequal); + } + + if (currside != sideUpOrig && zLowBinOrig != zUpBinOrig) { + // if the upper bins from the orig histo are not on the same side as the rebinned increase the binnumber until they are on the same side + bool notequal = true; + do { + zUpBinOrig -= 1; + if (zUpBinOrig < zLowBinOrig) { + LOGP(WARNING, "SOMETHING WENT WRONG: SETTING BINS TO: {}", zLowBinOrig); + zUpBinOrig = zLowBinOrig; + notequal = false; + } + const int sideTmp = getSide(hOrig.GetZaxis()->GetBinCenter(zUpBinOrig)); + if (sideTmp == currside) { + notequal = false; + } + } while (notequal); + } + + const auto binWidthZOrig = hOrig.GetZaxis()->GetBinWidth(zLowBinOrig); + const auto lowerBinWeightZ = std::abs(zLowEdge - hOrig.GetZaxis()->GetBinUpEdge(zLowBinOrig)) / binWidthZOrig; + const auto upperBinWeightZ = std::abs(zUpEdge - hOrig.GetZaxis()->GetBinLowEdge(zUpBinOrig)) / binWidthZOrig; + + // get the mean value of the original histogram of the found bin range + DataT sum = 0; + DataT sumW = 0; + for (int iPhi = phiLowBinOrig; iPhi <= phiUpBinOrig; ++iPhi) { + DataT weightPhi = 1; + if (iPhi == phiLowBinOrig) { + weightPhi = lowerBinWeightPhi; + } else if (iPhi == phiUpBinOrig) { + weightPhi = upperBinWeightPhi; + } + + for (int iR = rLowBinOrig; iR <= rUpBinOrig; ++iR) { + DataT weightR = 1; + if (iR == rLowBinOrig) { + weightR = lowerBinWeightR; + } else if (iR == rUpBinOrig) { + weightR = upperBinWeightR; + } + + for (int iZ = zLowBinOrig; iZ <= zUpBinOrig; ++iZ) { + DataT weightZ = 1; + if (iZ == zLowBinOrig) { + weightZ = lowerBinWeightZ; + } else if (iZ == zUpBinOrig) { + weightZ = upperBinWeightZ; + } + const auto val = hOrig.GetBinContent(iPhi, iR, iZ); + // if(val==0){ + // what to do now??? + // } + const auto totalWeight = weightPhi * weightR * weightZ; + sum += val * totalWeight; + sumW += totalWeight; + } + } + } + sum /= sumW; + hRebin.SetBinContent(iBinPhi, iBinR, iBinZ, sum); + } + } + } + return hRebin; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename ElectricFields> +void SpaceCharge<DataT, Nz, Nr, Nphi>::calcLocalDistortionsCorrections(const SpaceCharge<DataT, Nz, Nr, Nphi>::Type type, const ElectricFields& formulaStruct) +{ + const Side side = formulaStruct.getSide(); + // calculate local distortions/corrections for each vertex in the tpc +#pragma omp parallel for num_threads(sNThreads) + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex(iPhi, side); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex(iR, side); + for (size_t iZ = 0; iZ < Nz - 1; ++iZ) { + // set z coordinate depending on distortions or correction calculation + const DataT z0 = type == Type::Corrections ? getZVertex(iZ + 1, side) : getZVertex(iZ, side); + const DataT z1 = type == Type::Corrections ? getZVertex(iZ, side) : getZVertex(iZ + 1, side); + + DataT drTmp = 0; // local distortion dR + DataT dPhiTmp = 0; // local distortion dPhi (multiplication with R has to be done at the end) + DataT dzTmp = 0; // local distortion dZ + + const DataT stepSize = (z1 - z0) / sSteps; // the distortions are calculated by leting the elctron drift this distance in z direction + for (int iter = 0; iter < sSteps; ++iter) { + const DataT z0Tmp = (z0 + iter * stepSize + dzTmp); // starting z position + const DataT z1Tmp = (z0Tmp + stepSize); // electron drifts from z0Tmp to z1Tmp + + DataT ddR = 0; // distortion dR for drift from z0Tmp to z1Tmp + DataT ddPhi = 0; // distortion dPhi for drift from z0Tmp to z1Tmp + DataT ddZ = 0; // distortion dZ for drift from z0Tmp to z1Tmp + + const DataT radiusTmp = regulateR(radius + drTmp, side); // current radial position + const DataT phiTmp = regulatePhi(phi + dPhiTmp, side); // current phi position + + // calculate distortions/corrections + calcDistCorr(radiusTmp, phiTmp, z0Tmp, z1Tmp, ddR, ddPhi, ddZ, formulaStruct, true); + + // add temp distortions to local distortions + drTmp += ddR; + dPhiTmp += ddPhi; + dzTmp += ddZ; + } + + // store local distortions/corrections + switch (type) { + case Type::Corrections: + mLocalCorrdR[side](iZ + 1, iR, iPhi) = drTmp; + mLocalCorrdRPhi[side](iZ + 1, iR, iPhi) = dPhiTmp * radius; + mLocalCorrdZ[side](iZ + 1, iR, iPhi) = dzTmp; + break; + + case Type::Distortions: + mLocalDistdR[side](iZ, iR, iPhi) = drTmp; + mLocalDistdRPhi[side](iZ, iR, iPhi) = dPhiTmp * radius; + mLocalDistdZ[side](iZ, iR, iPhi) = dzTmp; + break; + } + } + //extrapolate local distortion/correction to last/first bin using legendre polynoms with x0=0, x1=1, x2=2 and x=-1. This has to be done to ensure correct interpolation in the last,second last/first,second bin! + switch (type) { + case Type::Corrections: + mLocalCorrdR[side](0, iR, iPhi) = 3 * (mLocalCorrdR[side](1, iR, iPhi) - mLocalCorrdR[side](2, iR, iPhi)) + mLocalCorrdR[side](3, iR, iPhi); + mLocalCorrdRPhi[side](0, iR, iPhi) = 3 * (mLocalCorrdRPhi[side](1, iR, iPhi) - mLocalCorrdRPhi[side](2, iR, iPhi)) + mLocalCorrdRPhi[side](3, iR, iPhi); + mLocalCorrdZ[side](0, iR, iPhi) = 3 * (mLocalCorrdZ[side](1, iR, iPhi) - mLocalCorrdZ[side](2, iR, iPhi)) + mLocalCorrdZ[side](3, iR, iPhi); + break; + + case Type::Distortions: + mLocalDistdR[side](Nz - 1, iR, iPhi) = 3 * (mLocalDistdR[side](Nz - 2, iR, iPhi) - mLocalDistdR[side](Nz - 3, iR, iPhi)) + mLocalDistdR[side](Nz - 4, iR, iPhi); + mLocalDistdRPhi[side](Nz - 1, iR, iPhi) = 3 * (mLocalDistdRPhi[side](Nz - 2, iR, iPhi) - mLocalDistdRPhi[side](Nz - 3, iR, iPhi)) + mLocalDistdRPhi[side](Nz - 4, iR, iPhi); + mLocalDistdZ[side](Nz - 1, iR, iPhi) = 3 * (mLocalDistdZ[side](Nz - 2, iR, iPhi) - mLocalDistdZ[side](Nz - 3, iR, iPhi)) + mLocalDistdZ[side](Nz - 4, iR, iPhi); + break; + } + } + } + switch (type) { + case Type::Corrections: + mIsLocalCorrSet[side] = true; + break; + case Type::Distortions: + mIsLocalDistSet[side] = true; + break; + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename Fields> +void SpaceCharge<DataT, Nz, Nr, Nphi>::calcGlobalDistortions(const Fields& formulaStruct) +{ + const Side side = formulaStruct.getSide(); + const DataT stepSize = formulaStruct.getID() == 2 ? getGridSpacingZ(side) : getGridSpacingZ(side) / sSteps; // if one used local distortions then no smaller stepsize is needed. if electric fields are used then smaller stepsize can be used + // loop over tpc volume and let the electron drift from each vertex to the readout of the tpc +#pragma omp parallel for num_threads(sNThreads) + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi0 = getPhiVertex(iPhi, side); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT r0 = getRVertex(iR, side); + for (size_t iZ = 0; iZ < Nz - 1; ++iZ) { + const DataT z0 = getZVertex(iZ, side); // the electron starts at z0, r0, phi0 + DataT drDist = 0.0; // global distortion dR + DataT dPhiDist = 0.0; // global distortion dPhi (multiplication with R has to be done at the end) + DataT dzDist = 0.0; // global distortion dZ + int iter = 0; + + for (;;) { + const DataT z0Tmp = z0 + dzDist + iter * stepSize; // starting z position + const DataT z1Tmp = regulateZ(z0Tmp + stepSize, side); // electron drifts from z0Tmp to z1Tmp + const DataT radius = regulateR(r0 + drDist, side); // current radial position of the electron + const DataT phi = regulatePhi(phi0 + dPhiDist, side); // current phi position of the electron + + DataT ddR = 0; // distortion dR for drift from z0Tmp to z1Tmp + DataT ddPhi = 0; // distortion dPhi for drift from z0Tmp to z1Tmp + DataT ddZ = 0; // distortion dZ for drift from z0Tmp to z1Tmp + + // get the distortion from interpolation of local distortions or calculate distortions with the electric field + processGlobalDistCorr(radius, phi, z0Tmp, z1Tmp, ddR, ddPhi, ddZ, formulaStruct); + + // if one uses local distortions the interpolated value for the last bin has to be scaled. + // This has to be done because of the interpolated value is defined for a drift length of one z bin, but in the last bin the distance to the readout can be smaller than one z bin. + const bool checkReached = side == Side::A ? z1Tmp >= getZMax(side) : z1Tmp <= getZMax(side); + if (formulaStruct.getID() == 2 && checkReached) { + const DataT fac = std::abs((getZMax(side) - z0Tmp) * getInvSpacingZ(side)); + ddR *= fac; + ddZ *= fac; + ddPhi *= fac; + } + + // add local distortions to global distortions + drDist += ddR; + dPhiDist += ddPhi; + dzDist += ddZ; + + // set loop to exit if the readout is reached and approximate distortion of 'missing' (one never ends exactly on the readout: z1Tmp + ddZ != ZMAX) drift distance. + // approximation is done by the current calculated values of the distortions and scaled linear to the 'missing' distance. + if (checkReached) { + const DataT endPoint = z1Tmp + ddZ; + const DataT deltaZ = getZMax(side) - endPoint; // distance from last point to read out + const DataT diff = endPoint - z0Tmp; + const DataT fac = diff != 0 ? std::abs(deltaZ / diff) : 0; // approximate the distortions for the 'missing' distance deltaZ + drDist += ddR * fac; + dPhiDist += ddPhi * fac; + dzDist += ddZ * fac; + break; + } + ++iter; + } + // store global distortions + mGlobalDistdR[side](iZ, iR, iPhi) = drDist; + mGlobalDistdRPhi[side](iZ, iR, iPhi) = dPhiDist * r0; + mGlobalDistdZ[side](iZ, iR, iPhi) = dzDist; + } + } + } + // set flag that global distortions are set to true + mIsGlobalDistSet[side] = true; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +template <typename Formulas> +void SpaceCharge<DataT, Nz, Nr, Nphi>::calcGlobalCorrections(const Formulas& formulaStruct) +{ + const Side side = formulaStruct.getSide(); + const int iSteps = formulaStruct.getID() == 2 ? 1 : sSteps; // if one used local corrections no step width is needed. since it is already used for calculation of the local corrections + const DataT stepSize = -getGridSpacingZ(side) / iSteps; + // loop over tpc volume and let the electron drift from each vertex to the readout of the tpc +#pragma omp parallel for num_threads(sNThreads) + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi0 = getPhiVertex(iPhi, side); + for (size_t iR = 0; iR < Nr; ++iR) { + + const DataT r0 = getRVertex(iR, side); + DataT drCorr = 0; + DataT dPhiCorr = 0; + DataT dzCorr = 0; + + // start at the readout and follow electron towards central electrode + for (size_t iZ = Nz - 1; iZ >= 1; --iZ) { + const DataT z0 = getZVertex(iZ, side); // the electron starts at z0, r0, phi0 + // flag which is set when the central electrode is reached. if the central electrode is reached the calculation of the global corrections is aborted and the value set is the last calculated value. + bool centralElectrodeReached = false; + for (int iter = 0; iter < iSteps; ++iter) { + if (centralElectrodeReached) { + break; + } + const DataT radius = regulateR(r0 + drCorr, side); // current radial position of the electron + const DataT phi = regulatePhi(phi0 + dPhiCorr, side); // current phi position of the electron + const DataT z0Tmp = z0 + dzCorr + iter * stepSize; // starting z position + const DataT z1Tmp = regulateZ(z0Tmp + stepSize, side); // follow electron from z0Tmp to z1Tmp + DataT ddR = 0; // distortion dR for z0Tmp to z1Tmp + DataT ddPhi = 0; // distortion dPhi for z0Tmp to z1Tmp + DataT ddZ = 0; // distortion dZ for z0Tmp to z1Tmp + + // get the distortion from interpolation of local distortions or calculate distortions with the electric field + processGlobalDistCorr(radius, phi, z0Tmp, z1Tmp, ddR, ddPhi, ddZ, formulaStruct); + + // if one uses local corrections the interpolated value for the first bin has to be scaled. + // This has to be done because of the interpolated value is defined for a drift length of one z bin, but in the first bin the distance to the readout can be smaller than one z bin. + centralElectrodeReached = getSign(side) * z1Tmp <= getZMin(side); + if (formulaStruct.getID() == 2 && centralElectrodeReached) { + const DataT fac = (z0Tmp - getZMin(side)) * getInvSpacingZ(side); + ddR *= fac; + ddZ *= fac; + ddPhi *= fac; + } + + // add local corrections to global corrections + drCorr += ddR; + dPhiCorr += ddPhi; + dzCorr += ddZ; + + // set loop to exit if the central electrode is reached and approximate correction of 'missing' (one never ends exactly on the central electrode: z1Tmp + ddZ != ZMIN) distance. + // approximation is done by the current calculated values of the corrections and scaled linear to the 'missing' distance deltaZ. (NOT TESTED) + if (centralElectrodeReached) { + const DataT endPoint = z1Tmp + ddZ; + const DataT deltaZ = endPoint - getZMin(side); + const DataT diff = z0Tmp - endPoint; + const DataT fac = diff != 0 ? deltaZ / diff : 0; // approximate the distortions for the 'missing' distance deltaZ + drCorr += ddR * fac; + dPhiCorr += ddPhi * fac; + dzCorr += ddZ * fac; + break; + } + } + // store global corrections + mGlobalCorrdR[side](iZ - 1, iR, iPhi) = drCorr; + mGlobalCorrdRPhi[side](iZ - 1, iR, iPhi) = dPhiCorr * r0; + mGlobalCorrdZ[side](iZ - 1, iR, iPhi) = dzCorr; + } + } + } + // set flag that global corrections are set to true + mIsGlobalCorrSet[side] = true; +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::correctElectron(GlobalPosition3D& point) +{ + DataT corrX{}; + DataT corrY{}; + DataT corrZ{}; + const Side side = getSide(point.Z()); + + // get the distortions for input coordinate + getCorrections(point.X(), point.Y(), point.Z(), side, corrX, corrY, corrZ); + + // set distorted coordinates + point.SetXYZ(point.X() + corrX, point.Y() + corrY, point.Y() + corrY); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::distortElectron(GlobalPosition3D& point) const +{ + DataT distX{}; + DataT distY{}; + DataT distZ{}; + const Side side = getSide(point.Z()); + // get the distortions for input coordinate + getDistortions(point.X(), point.Y(), point.Z(), side, distX, distY, distZ); + + // set distorted coordinates + point.SetXYZ(point.X() + distX, point.Y() + distY, point.Z() + distZ); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT SpaceCharge<DataT, Nz, Nr, Nphi>::getChargeCyl(const DataT z, const DataT r, const DataT phi, const Side side) const +{ + return mInterpolatorDensity[side](z, r, phi); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT SpaceCharge<DataT, Nz, Nr, Nphi>::getPotentialCyl(const DataT z, const DataT r, const DataT phi, const Side side) const +{ + return mInterpolatorPotential[side](z, r, phi); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::getElectricFieldsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& eZ, DataT& eR, DataT& ePhi) const +{ + eZ = mInterpolatorEField[side].evalEz(z, r, phi); + eR = mInterpolatorEField[side].evalEr(z, r, phi); + ePhi = mInterpolatorEField[side].evalEphi(z, r, phi); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::getLocalCorrectionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& lcorrZ, DataT& lcorrR, DataT& lcorrRPhi) const +{ + lcorrZ = mInterpolatorLocalCorr[side].evaldZ(z, r, phi); + lcorrR = mInterpolatorLocalCorr[side].evaldR(z, r, phi); + lcorrRPhi = mInterpolatorLocalCorr[side].evaldRPhi(z, r, phi); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::getCorrectionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& corrZ, DataT& corrR, DataT& corrRPhi) const +{ + corrZ = mInterpolatorGlobalCorr[side].evaldZ(z, r, phi); + corrR = mInterpolatorGlobalCorr[side].evaldR(z, r, phi); + corrRPhi = mInterpolatorGlobalCorr[side].evaldRPhi(z, r, phi); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::getCorrections(const DataT x, const DataT y, const DataT z, const Side side, DataT& corrX, DataT& corrY, DataT& corrZ) const +{ + // convert cartesian to polar + const DataT radius = getRadiusFromCartesian(x, y); + const DataT phi = getPhiFromCartesian(x, y); + + DataT corrR{}; + DataT corrRPhi{}; + getCorrectionsCyl(z, radius, phi, side, corrZ, corrR, corrRPhi); + + // Calculate corrected position + const DataT radiusCorr = radius + corrR; + const DataT phiCorr = phi + corrRPhi / radius; + + corrX = getXFromPolar(radiusCorr, phiCorr) - x; // difference between corrected and original x coordinate + corrY = getYFromPolar(radiusCorr, phiCorr) - y; // difference between corrected and original y coordinate +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::getLocalDistortionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& ldistZ, DataT& ldistR, DataT& ldistRPhi) const +{ + ldistZ = mInterpolatorLocalDist[side].evaldZ(z, r, phi); + ldistR = mInterpolatorLocalDist[side].evaldR(z, r, phi); + ldistRPhi = mInterpolatorLocalDist[side].evaldRPhi(z, r, phi); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::getDistortionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& distZ, DataT& distR, DataT& distRPhi) const +{ + distZ = mInterpolatorGlobalDist[side].evaldZ(z, r, phi); + distR = mInterpolatorGlobalDist[side].evaldR(z, r, phi); + distRPhi = mInterpolatorGlobalDist[side].evaldRPhi(z, r, phi); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::getDistortions(const DataT x, const DataT y, const DataT z, const Side side, DataT& distX, DataT& distY, DataT& distZ) const +{ + // convert cartesian to polar + const DataT radius = getRadiusFromCartesian(x, y); + const DataT phi = getPhiFromCartesian(x, y); + + DataT distR{}; + DataT distRPhi{}; + getDistortionsCyl(z, radius, phi, side, distZ, distR, distRPhi); + + // Calculate distorted position + const DataT radiusDist = radius + distR; + const DataT phiDist = phi + distRPhi / radius; + + distX = getXFromPolar(radiusDist, phiDist) - x; // difference between distorted and original x coordinate + distY = getYFromPolar(radiusDist, phiDist) - y; // difference between distorted and original y coordinate +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::init() +{ + using timer = std::chrono::high_resolution_clock; + if (!mInitLookUpTables) { + auto start = timer::now(); + auto o2field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField()); + const float bzField = o2field->solenoidField(); // magnetic field in kGauss + /// TODO is there a faster way to get the drift velocity + auto& gasParam = ParameterGas::Instance(); + float vDrift = gasParam.DriftV; // drift velocity in cm/us + /// TODO fix hard coded values (ezField, t1, t2): export to Constants.h or get from somewhere? + const float t1 = 1.; + const float t2 = 1.; + /// TODO use this parameterization or fixed value(s) from Magboltz calculations? + const float omegaTau = -10. * bzField * vDrift / std::abs(getEzField(Side::A)); + setOmegaTauT1T2(omegaTau, t1, t2); + if (mUseInitialSCDensity) { + LOG(WARNING) << "mUseInitialSCDensity" << mUseInitialSCDensity; + calculateDistortionsCorrections(Side::A); + calculateDistortionsCorrections(Side::C); + mInitLookUpTables = true; + } + auto stop = timer::now(); + std::chrono::duration<float> time = stop - start; + LOGP(info, "Total Time Distortions and Corrections for A and C Side: {}", time.count()); + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void SpaceCharge<DataT, Nz, Nr, Nphi>::setDistortionLookupTables(const DataContainer& distdZ, const DataContainer& distdR, const DataContainer& distdRPhi, const Side side) +{ + mGlobalDistdR[side] = distdR; + mGlobalDistdZ[side] = distdZ; + mGlobalDistdRPhi[side] = distdRPhi; + mIsGlobalDistSet[side] = true; +} + +using DataTD = double; +template class o2::tpc::SpaceCharge<DataTD, 17, 17, 90>; +template class o2::tpc::SpaceCharge<DataTD, 33, 33, 180>; +template class o2::tpc::SpaceCharge<DataTD, 65, 65, 180>; +template class o2::tpc::SpaceCharge<DataTD, 129, 129, 180>; +template class o2::tpc::SpaceCharge<DataTD, 257, 257, 180>; +template class o2::tpc::SpaceCharge<DataTD, 257, 257, 360>; + +// 129*129*180 +using NumFields129D = NumericalFields<DataTD, 129, 129, 180>; +using AnaFields129D = AnalyticalFields<DataTD>; +using DistCorrInterp129D = DistCorrInterpolator<DataTD, 129, 129, 180>; +using O2TPCSpaceCharge3DCalc129D = SpaceCharge<DataTD, 129, 129, 180>; + +template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc129D::Type, const NumFields129D&); +template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc129D::Type, const AnaFields129D&); +template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections(const NumFields129D&); +template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections(const AnaFields129D&); +template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections(const DistCorrInterp129D&); + +template void O2TPCSpaceCharge3DCalc129D::calcGlobalDistortions(const NumFields129D&); +template void O2TPCSpaceCharge3DCalc129D::calcGlobalDistortions(const AnaFields129D&); +template void O2TPCSpaceCharge3DCalc129D::calcGlobalDistortions(const DistCorrInterp129D&); + +// 33*33*180 +using NumFields33D = NumericalFields<DataTD, 33, 33, 180>; +using AnaFields33D = AnalyticalFields<DataTD>; +using DistCorrInterp33D = DistCorrInterpolator<DataTD, 33, 33, 180>; +using O2TPCSpaceCharge3DCalc33D = SpaceCharge<DataTD, 33, 33, 180>; + +template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc33D::Type, const NumFields33D&); +template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc33D::Type, const AnaFields33D&); +template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections(const NumFields33D&); +template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections(const AnaFields33D&); +template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections(const DistCorrInterp33D&); + +template void O2TPCSpaceCharge3DCalc33D::calcGlobalDistortions(const NumFields33D&); +template void O2TPCSpaceCharge3DCalc33D::calcGlobalDistortions(const AnaFields33D&); +template void O2TPCSpaceCharge3DCalc33D::calcGlobalDistortions(const DistCorrInterp33D&); + +// 65*65*180 +using NumFields65D = NumericalFields<DataTD, 65, 65, 180>; +using AnaFields65D = AnalyticalFields<DataTD>; +using DistCorrInterp65D = DistCorrInterpolator<DataTD, 65, 65, 180>; +using O2TPCSpaceCharge3DCalc65D = SpaceCharge<DataTD, 65, 65, 180>; + +template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc65D::Type, const NumFields65D&); +template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc65D::Type, const AnaFields65D&); +template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections(const NumFields65D&); +template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections(const AnaFields65D&); +template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections(const DistCorrInterp65D&); + +template void O2TPCSpaceCharge3DCalc65D::calcGlobalDistortions(const NumFields65D&); +template void O2TPCSpaceCharge3DCalc65D::calcGlobalDistortions(const AnaFields65D&); +template void O2TPCSpaceCharge3DCalc65D::calcGlobalDistortions(const DistCorrInterp65D&); + +// 17*17*90 +using NumFields17D = NumericalFields<DataTD, 17, 17, 90>; +using AnaFields17D = AnalyticalFields<DataTD>; +using DistCorrInterp17D = DistCorrInterpolator<DataTD, 17, 17, 90>; +using O2TPCSpaceCharge3DCalc17D = SpaceCharge<DataTD, 17, 17, 90>; + +template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc17D::Type, const NumFields17D&); +template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc17D::Type, const AnaFields17D&); +template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections(const NumFields17D&); +template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections(const AnaFields17D&); +template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections(const DistCorrInterp17D&); + +template void O2TPCSpaceCharge3DCalc17D::calcGlobalDistortions(const NumFields17D&); +template void O2TPCSpaceCharge3DCalc17D::calcGlobalDistortions(const AnaFields17D&); +template void O2TPCSpaceCharge3DCalc17D::calcGlobalDistortions(const DistCorrInterp17D&); + +// 257*257*180 +using NumFields257D = NumericalFields<DataTD, 257, 257, 180>; +using AnaFields257D = AnalyticalFields<DataTD>; +using DistCorrInterp257D = DistCorrInterpolator<DataTD, 257, 257, 180>; +using O2TPCSpaceCharge3DCalc257D = SpaceCharge<DataTD, 257, 257, 180>; + +template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc257D::Type, const NumFields257D&); +template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc257D::Type, const AnaFields257D&); +template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections(const NumFields257D&); +template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections(const AnaFields257D&); +template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections(const DistCorrInterp257D&); + +template void O2TPCSpaceCharge3DCalc257D::calcGlobalDistortions(const NumFields257D&); +template void O2TPCSpaceCharge3DCalc257D::calcGlobalDistortions(const AnaFields257D&); +template void O2TPCSpaceCharge3DCalc257D::calcGlobalDistortions(const DistCorrInterp257D&); + +// 257*257*360 +using NumFields257360D = NumericalFields<DataTD, 257, 257, 360>; +using AnaFields257360D = AnalyticalFields<DataTD>; +using DistCorrInterp257360D = DistCorrInterpolator<DataTD, 257, 257, 360>; +using O2TPCSpaceCharge3DCalc257360D = SpaceCharge<DataTD, 257, 257, 360>; + +template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc257360D::Type, const NumFields257360D&); +template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc257360D::Type, const AnaFields257360D&); +template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections(const NumFields257360D&); +template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections(const AnaFields257360D&); +template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections(const DistCorrInterp257360D&); + +template void O2TPCSpaceCharge3DCalc257360D::calcGlobalDistortions(const NumFields257360D&); +template void O2TPCSpaceCharge3DCalc257360D::calcGlobalDistortions(const AnaFields257360D&); +template void O2TPCSpaceCharge3DCalc257360D::calcGlobalDistortions(const DistCorrInterp257360D&); diff --git a/Detectors/TPC/spacecharge/src/TPCSpacechargeLinkDef.h b/Detectors/TPC/spacecharge/src/TPCSpacechargeLinkDef.h new file mode 100644 index 0000000000000..1dd77a5bcafd9 --- /dev/null +++ b/Detectors/TPC/spacecharge/src/TPCSpacechargeLinkDef.h @@ -0,0 +1,81 @@ +// 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 TPCSpacechargeLinkDef.h +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ nestedclasses; +#pragma link C++ nestedtypedef; + +#pragma link C++ class o2::tpc::MGParameters + ; +#pragma link C++ class o2::tpc::TPCParameters < double> + ; +#pragma link C++ class o2::tpc::AnalyticalFields < double> + ; + +// 257*257*360 +#pragma link C++ class o2::tpc::RegularGrid3D < double, 257, 257, 360> + ; +#pragma link C++ class o2::tpc::DataContainer3D < double, 257, 257, 360> + ; +#pragma link C++ class o2::tpc::PoissonSolver < double, 257, 257, 360> + ; +#pragma link C++ class o2::tpc::SpaceCharge < double, 257, 257, 360> + ; +#pragma link C++ class o2::tpc::NumericalFields < double, 257, 257, 360> + ; +#pragma link C++ class o2::tpc::DistCorrInterpolator < double, 257, 257, 360> + ; +#pragma link C++ class o2::tpc::GridProperties < double, 257, 257, 360> + ; + +// 257*257*180 +#pragma link C++ class o2::tpc::RegularGrid3D < double, 257, 257, 180> + ; +#pragma link C++ class o2::tpc::DataContainer3D < double, 257, 257, 180> + ; +#pragma link C++ class o2::tpc::PoissonSolver < double, 257, 257, 180> + ; +#pragma link C++ class o2::tpc::SpaceCharge < double, 257, 257, 180> + ; +#pragma link C++ class o2::tpc::NumericalFields < double, 257, 257, 180> + ; +#pragma link C++ class o2::tpc::DistCorrInterpolator < double, 257, 257, 180> + ; +#pragma link C++ class o2::tpc::GridProperties < double, 257, 257, 180> + ; + +// 129*129*180 +#pragma link C++ class o2::tpc::RegularGrid3D < double, 129, 129, 180> + ; +#pragma link C++ class o2::tpc::DataContainer3D < double, 129, 129, 180> + ; +#pragma link C++ class o2::tpc::PoissonSolver < double, 129, 129, 180> + ; +#pragma link C++ class o2::tpc::SpaceCharge < double, 129, 129, 180> + ; +#pragma link C++ class o2::tpc::NumericalFields < double, 129, 129, 180> + ; +#pragma link C++ class o2::tpc::DistCorrInterpolator < double, 129, 129, 180> + ; +#pragma link C++ class o2::tpc::GridProperties < double, 129, 129, 180> + ; + +// 65*65*180 +#pragma link C++ class o2::tpc::RegularGrid3D < double, 65, 65, 180> + ; +#pragma link C++ class o2::tpc::DataContainer3D < double, 65, 65, 180> + ; +#pragma link C++ class o2::tpc::PoissonSolver < double, 65, 65, 180> + ; +#pragma link C++ class o2::tpc::SpaceCharge < double, 65, 65, 180> + ; +#pragma link C++ class o2::tpc::NumericalFields < double, 65, 65, 180> + ; +#pragma link C++ class o2::tpc::DistCorrInterpolator < double, 65, 65, 180> + ; +#pragma link C++ class o2::tpc::GridProperties < double, 65, 65, 180> + ; + +// 33*33*180 +#pragma link C++ class o2::tpc::RegularGrid3D < double, 33, 33, 180> + ; +#pragma link C++ class o2::tpc::DataContainer3D < double, 33, 33, 180> + ; +#pragma link C++ class o2::tpc::PoissonSolver < double, 33, 33, 180> + ; +#pragma link C++ class o2::tpc::SpaceCharge < double, 33, 33, 180> + ; +#pragma link C++ class o2::tpc::NumericalFields < double, 33, 33, 180> + ; +#pragma link C++ class o2::tpc::DistCorrInterpolator < double, 33, 33, 180> + ; +#pragma link C++ class o2::tpc::GridProperties < double, 33, 33, 180> + ; + +// 17*17*90 +#pragma link C++ class o2::tpc::RegularGrid3D < double, 17, 17, 90> + ; +#pragma link C++ class o2::tpc::DataContainer3D < double, 17, 17, 90> + ; +#pragma link C++ class o2::tpc::PoissonSolver < double, 17, 17, 90> + ; +#pragma link C++ class o2::tpc::SpaceCharge < double, 17, 17, 90> + ; +#pragma link C++ class o2::tpc::NumericalFields < double, 17, 17, 90> + ; +#pragma link C++ class o2::tpc::DistCorrInterpolator < double, 17, 17, 90> + ; +#pragma link C++ class o2::tpc::GridProperties < double, 17, 17, 90> + ; + +#endif diff --git a/Detectors/TPC/spacecharge/test/testO2TPCPoissonSolver.cxx b/Detectors/TPC/spacecharge/test/testO2TPCPoissonSolver.cxx new file mode 100644 index 0000000000000..61d615b252d99 --- /dev/null +++ b/Detectors/TPC/spacecharge/test/testO2TPCPoissonSolver.cxx @@ -0,0 +1,240 @@ +// 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 testPoissonSolver.cxx +/// \brief this task tests the poisson solver +/// +/// \author Matthias Kleiner <mkleiner@ikf.uni-frankfurt.de> + +#define BOOST_TEST_MODULE Test TPC O2TPCSpaceCharge3DCalc class +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "TPCSpaceCharge/PoissonSolver.h" +#include "TPCSpaceCharge/SpaceChargeHelpers.h" + +namespace o2 +{ +namespace tpc +{ + +using DataT = double; // using float actually takes alot longer than double (doesnt converge when using float) +static constexpr DataT TOLERANCE = 3; // relative tolerance for 3D (maximum large error is at phi=90 since there the potential is 0!) +static constexpr DataT TOLERANCE2D = 8.5; // relative tolerance for 2D TODO check why the difference between numerical and analyticial is larger than for 3D! +static constexpr DataT ABSTOLERANCE = 0.01; // absolute tolerance is taken at small values near 0 +static constexpr int NR = 129; // grid in r +static constexpr int NZ = 129; // grid in z +static constexpr int NPHI = 180; // grid in phi + +/// Get phi vertex position for index in phi direction +/// \param indexPhi index in phi direction +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT getPhiVertex(const size_t indexPhi, const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>& grid) +{ + return grid.getZVertex(indexPhi); +} + +/// Get r vertex position for index in r direction +/// \param indexR index in r direction +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT getRVertex(const size_t indexR, const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>& grid) +{ + return grid.getYVertex(indexR); +} + +/// Get z vertex position for index in z direction +/// \param indexZ index in z direction +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +DataT getZVertex(const size_t indexZ, const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>& grid) +{ + return grid.getXVertex(indexZ); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void setChargeDensityFromFormula(const AnalyticalFields<DataT>& formulas, const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>& grid, o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>& density) +{ + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex<DataT, Nz, Nr, Nphi>(iPhi, grid); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex<DataT, Nz, Nr, Nphi>(iR, grid); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex<DataT, Nz, Nr, Nphi>(iZ, grid); + density(iZ, iR, iPhi) = formulas.evalDensity(z, radius, phi); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void setPotentialFromFormula(const AnalyticalFields<DataT>& formulas, const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>& grid, o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>& potential) +{ + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex<DataT, Nz, Nr, Nphi>(iPhi, grid); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex<DataT, Nz, Nr, Nphi>(iR, grid); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex<DataT, Nz, Nr, Nphi>(iZ, grid); + potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi); + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void setPotentialBoundaryFromFormula(const AnalyticalFields<DataT>& formulas, const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi>& grid, o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>& potential) +{ + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex<DataT, Nz, Nr, Nphi>(iPhi, grid); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex<DataT, Nz, Nr, Nphi>(iZ, grid); + const size_t iR = 0; + const DataT radius = getRVertex<DataT, Nz, Nr, Nphi>(iR, grid); + potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi); + } + } + + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex<DataT, Nz, Nr, Nphi>(iPhi, grid); + for (size_t iZ = 0; iZ < Nz; ++iZ) { + const DataT z = getZVertex<DataT, Nz, Nr, Nphi>(iZ, grid); + const size_t iR = Nr - 1; + const DataT radius = getRVertex<DataT, Nz, Nr, Nphi>(iR, grid); + potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi); + } + } + + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex<DataT, Nz, Nr, Nphi>(iPhi, grid); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex<DataT, Nz, Nr, Nphi>(iR, grid); + const size_t iZ = 0; + const DataT z = getZVertex<DataT, Nz, Nr, Nphi>(iZ, grid); + potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi); + } + } + + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + const DataT phi = getPhiVertex<DataT, Nz, Nr, Nphi>(iPhi, grid); + for (size_t iR = 0; iR < Nr; ++iR) { + const DataT radius = getRVertex<DataT, Nz, Nr, Nphi>(iR, grid); + const size_t iZ = Nz - 1; + const DataT z = getZVertex<DataT, Nz, Nr, Nphi>(iZ, grid); + potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi); + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void testAlmostEqualArray(o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>& analytical, o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>& numerical) +{ + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + for (size_t iR = 0; iR < Nr; ++iR) { + for (size_t iZ = 0; iZ < Nz; ++iZ) { + if (std::fabs(analytical(iZ, iR, iPhi)) < ABSTOLERANCE) { + BOOST_CHECK_SMALL(numerical(iZ, iR, iPhi) - analytical(iZ, iR, iPhi), ABSTOLERANCE); + } else { + BOOST_CHECK_CLOSE(numerical(iZ, iR, iPhi), analytical(iZ, iR, iPhi), TOLERANCE); + } + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void testAlmostEqualArray2D(o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>& analytical, o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>& numerical) +{ + for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { + for (size_t iR = 0; iR < Nr; ++iR) { + for (size_t iZ = 0; iZ < Nz; ++iZ) { + if (std::fabs(analytical(iZ, iR, iPhi)) < ABSTOLERANCE) { + BOOST_CHECK_SMALL(numerical(iZ, iR, iPhi) - analytical(iZ, iR, iPhi), ABSTOLERANCE); + } else { + BOOST_CHECK_CLOSE(numerical(iZ, iR, iPhi), analytical(iZ, iR, iPhi), TOLERANCE2D); + } + } + } + } +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void poissonSolver3D() +{ + using GridProp = GridProperties<DataT, Nr, Nz, Nphi>; + const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi> grid3D{GridProp::ZMIN, GridProp::RMIN, GridProp::PHIMIN, GridProp::GRIDSPACINGZ, GridProp::GRIDSPACINGR, GridProp::GRIDSPACINGPHI}; + + using DataContainer = o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>; + DataContainer potentialNumerical{}; + DataContainer potentialAnalytical{}; + DataContainer charge{}; + + const o2::tpc::AnalyticalFields<DataT> analyticalFields; + // set the boudnary and charge for numerical poisson solver + setChargeDensityFromFormula<DataT, Nz, Nr, Nphi>(analyticalFields, grid3D, charge); + setPotentialBoundaryFromFormula<DataT, Nz, Nr, Nphi>(analyticalFields, grid3D, potentialNumerical); + + // set analytical potential + setPotentialFromFormula<DataT, Nz, Nr, Nphi>(analyticalFields, grid3D, potentialAnalytical); + + //calculate numerical potential + PoissonSolver<DataT, Nz, Nr, Nphi> poissonSolver(grid3D); + const int symmetry = 0; + poissonSolver.poissonSolver3D(potentialNumerical, charge, symmetry); + + // compare numerical with analytical solution of the potential + testAlmostEqualArray<DataT, Nz, Nr, Nphi>(potentialAnalytical, potentialNumerical); +} + +template <typename DataT, size_t Nz, size_t Nr, size_t Nphi> +void poissonSolver2D() +{ + using GridProp = GridProperties<DataT, Nr, Nz, Nphi>; + const o2::tpc::RegularGrid3D<DataT, Nz, Nr, Nphi> grid3D{GridProp::ZMIN, GridProp::RMIN, GridProp::PHIMIN, GridProp::GRIDSPACINGZ, GridProp::GRIDSPACINGR, GridProp::GRIDSPACINGPHI}; + + using DataContainer = o2::tpc::DataContainer3D<DataT, Nz, Nr, Nphi>; + DataContainer potentialNumerical{}; + DataContainer potentialAnalytical{}; + DataContainer charge{}; + + // set the boudnary and charge for numerical poisson solver + const o2::tpc::AnalyticalFields<DataT> analyticalFields; + setChargeDensityFromFormula<DataT, Nz, Nr, Nphi>(analyticalFields, grid3D, charge); + setPotentialBoundaryFromFormula<DataT, Nz, Nr, Nphi>(analyticalFields, grid3D, potentialNumerical); + + // set analytical potential + setPotentialFromFormula<DataT, Nz, Nr, Nphi>(analyticalFields, grid3D, potentialAnalytical); + + //calculate numerical potential + PoissonSolver<DataT, Nz, Nr, Nphi> poissonSolver(grid3D); + poissonSolver.poissonSolver2D(potentialNumerical, charge); + + // compare numerical with analytical solution of the potential + testAlmostEqualArray2D<DataT, Nz, Nr, Nphi>(potentialAnalytical, potentialNumerical); +} + +BOOST_AUTO_TEST_CASE(PoissonSolver3D_test) +{ + o2::tpc::MGParameters::isFull3D = true; //3D + poissonSolver3D<DataT, NZ, NR, NPHI>(); +} + +BOOST_AUTO_TEST_CASE(PoissonSolver3D2D_test) +{ + o2::tpc::MGParameters::isFull3D = false; // 3D2D + poissonSolver3D<DataT, NZ, NR, NPHI>(); +} + +BOOST_AUTO_TEST_CASE(PoissonSolver2D_test) +{ + const int Nphi = 1; + poissonSolver2D<DataT, NZ, NR, Nphi>(); +} + +} // namespace tpc +} // namespace o2 diff --git a/GPU/CMakeLists.txt b/GPU/CMakeLists.txt index e2ba9741f3508..03b9b7d00427f 100644 --- a/GPU/CMakeLists.txt +++ b/GPU/CMakeLists.txt @@ -21,6 +21,3 @@ add_subdirectory(Common) add_subdirectory(Utils) add_subdirectory(TPCFastTransformation) add_subdirectory(GPUTracking) -if(NOT ALIGPU_BUILD_TYPE STREQUAL "Standalone") - add_subdirectory(TPCSpaceChargeBase) -endif() diff --git a/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C b/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C index 9dfd2a4d271fe..d052e03efe2e7 100644 --- a/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C +++ b/GPU/TPCFastTransformation/macro/generateTPCCorrectionNTuple.C @@ -24,17 +24,22 @@ #include "TH3.h" #include "DataFormatsTPC/Defs.h" -#include "TPCSimulation/SpaceCharge.h" +#include "TPCSpaceCharge/SpaceCharge.h" #include "GPU/TPCFastTransform.h" #include "TPCReconstruction/TPCFastTransformHelperO2.h" #endif -o2::tpc::SpaceCharge* sc = 0; +// define number of bins in r, rphi, z for the lookup tables +// o2::tpc::SpaceCharge<double, nZ, nR, nPhi> +// for valid values see the definitions in TPCSpacechargeLinkDef.h +using SC = o2::tpc::SpaceCharge<double, 129, 129, 180>; +SC* sc = nullptr; + using namespace o2::tpc; using namespace o2::gpu; -void generateTPCCorrectionNTuple() +void generateTPCCorrectionNTuple(const char* path = "InputSCDensityHistograms.root", const char* histoName = "inputSCDensity3D8") { // open file with space-charge density histograms // location: alien:///alice/cern.ch/user/e/ehellbar/TPCSpaceCharge/RUN3/ SCDensityHistograms/InputSCDensityHistograms.root @@ -43,35 +48,30 @@ void generateTPCCorrectionNTuple() // - nPileUpEvents = 0,2,4,6,8,10,12 // - number of events (in units of 1000) contributing to the ion density. 0 = 130000 events, 2 = 2000 events, 4 = 4000 events, etc. // - expected default map with 8000 pileup events: inputSCDensity3D8 - auto mFileSCDensity = std::unique_ptr<TFile>(TFile::Open("InputSCDensityHistograms.root")); + auto mFileSCDensity = std::unique_ptr<TFile>(TFile::Open(path)); if (!mFileSCDensity || !mFileSCDensity->IsOpen()) { std::cout << " input file does not exist!" << std::endl; return; } // get the histogram with the sc density - std::unique_ptr<TH3> mHisSCDensity3D = std::unique_ptr<TH3>((TH3*)mFileSCDensity->Get("inputSCDensity3D8")); + std::unique_ptr<TH3> mHisSCDensity3D = std::unique_ptr<TH3>((TH3*)mFileSCDensity->Get(histoName)); if (!mHisSCDensity3D) { - std::cout << "inputSCDensity3D8 histogramm does not exist!" << std::endl; + std::cout << Form("%s histogramm does not exist!", histoName) << std::endl; return; } - // define number of bins in r, rphi, z for the lookup tables - // nR annd nZ have to be 2^n + 1, nPhi is arbitrary - // expected default for desired precision: 129, 129, 144 (takes a lot of time, you can also us 65 in r and z) - int mNRRows = 129; - int mNZCols = 129; - int mNPhiSlices = 180; - // create space-charge object - sc = new o2::tpc::SpaceCharge(mNRRows, mNPhiSlices, mNZCols); - sc->setInitialSpaceChargeDensity((TH3*)mHisSCDensity3D.get()); + sc = new SC; + sc->setGlobalDistType(SC::GlobalDistType::None); + sc->fillChargeDensityFromHisto(*mHisSCDensity3D.get()); // select constant distortions (over time), realistic distortions changing in time not yet pushed to official code - sc->setSCDistortionType(o2::tpc::SpaceCharge::SCDistortionType::SCDistortionsConstant); + sc->setSCDistortionType(SC::SCDistortionType::SCDistortionsConstant); // gas parameters nor Ne-CO2-N2 90-10-5 sc->setOmegaTauT1T2(0.32, 1, 1); // start calculation of lookup tables (takes some time) - sc->calculateLookupTables(); + sc->calculateDistortionsCorrections(Side::A); + sc->calculateDistortionsCorrections(Side::C); // create TPC transformation to get the TPC geometry diff --git a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.cxx b/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.cxx deleted file mode 100644 index 9fbfa42db6491..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.cxx +++ /dev/null @@ -1,533 +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. - -/// \file AliTPC3DCylindricalInterpolator.cxx -/// \brief Interpolator for cylindrical coordinate -/// this class provides: cubic spline, quadratic and linear interpolation -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Jan 5, 2016 - -#include "TMath.h" -#include "AliTPC3DCylindricalInterpolator.h" - -/// \cond CLASSIMP -ClassImp(AliTPC3DCylindricalInterpolator); -/// \endcond - -/// constructor -/// -AliTPC3DCylindricalInterpolator::AliTPC3DCylindricalInterpolator() -{ - fOrder = 1; - fIsAllocatingLookUp = kFALSE; - fIsInitCubic = kFALSE; -} - -/// destructor -/// -AliTPC3DCylindricalInterpolator::~AliTPC3DCylindricalInterpolator() -{ - delete fValue; - delete fRList; - delete fPhiList; - delete fZList; - if (fIsInitCubic) { - delete fSecondDerZ; - } -} - -/// Get interpolation value on a point in a cylindrical volume -/// -/// \param r position r -/// \param phi position $\phi$ -/// \param z position z -/// -/// \return interpolation value -Double_t AliTPC3DCylindricalInterpolator::GetValue(Double_t r, Double_t phi, Double_t z) const -{ - return InterpolateCylindrical(r, z, phi); -} - -/// Get interpolation value on a point in a cylindrical volume -/// -/// \param r Double_t position r -/// \param phi Double_t position $\phi$ -/// \param z Double_t position z -/// -/// \return interpolation value -Double_t AliTPC3DCylindricalInterpolator::InterpolateCylindrical(Double_t r, Double_t z, Double_t phi) const -{ - Int_t iLow = 0, jLow = 0, m = 0; - Int_t kLow = 0; - Int_t index; - - // tri cubic points - Double_t saveArray[fOrder + 1]; - Double_t savedArray[fOrder + 1]; - Double_t zListM1[fOrder + 1]; - Double_t valueM1[fOrder + 1]; - - Bool_t neg = kFALSE; - - // check phi - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - // search lowest index related to r,z and phi - Search(fNR, fRList, r, iLow); - Search(fNZ, fZList, z, jLow); - Search(fNPhi, fPhiList, phi, kLow); - - // order >= 3 - kLow -= (fOrder / 2); - iLow -= (fOrder / 2); - jLow -= (fOrder / 2); - - // check if out of range - if (iLow < 0) { - iLow = 0; - } - if (jLow < 0) { - jLow = 0; - } - if (kLow < 0) { - kLow = fNPhi + kLow; - } - // check if out of range - if (iLow + fOrder >= fNR - 1) { - iLow = fNR - 1 - fOrder; - } - if (jLow + fOrder >= fNZ - 1) { - jLow = fNZ - 1 - fOrder; - } - - // do for each - for (Int_t k = 0; k < fOrder + 1; k++) { - m = (kLow + k) % fNPhi; - // interpolate - for (Int_t i = iLow; i < iLow + fOrder + 1; i++) { - if (fOrder < 3) { - if (jLow >= 0) { - index = m * (fNZ * fNR) + i * (fNZ) + jLow; - saveArray[i - iLow] = Interpolate(&fZList[jLow], &fValue[index], z); - } else { - index = m * (fNZ * fNR) + i * (fNZ); - zListM1[0] = fZList[0] - (fZList[1] - fZList[0]); - zListM1[1] = fZList[0]; - zListM1[2] = fZList[1]; - valueM1[0] = fValue[index] - (fValue[index + 1] - fValue[index]); - valueM1[1] = fValue[index]; - valueM1[2] = fValue[index + 1]; - saveArray[i - iLow] = Interpolate(&zListM1[0], &valueM1[0], z); - } - - } else { - index = m * (fNZ * fNR) + i * (fNZ); - saveArray[i - iLow] = InterpolateCubicSpline(fZList, &fValue[index], &fSecondDerZ[index], fNZ, fNZ, fNZ, - z, 1); - } - } - savedArray[k] = Interpolate(&fRList[iLow], saveArray, r); - } - return (InterpolatePhi(&fPhiList[0], kLow, fNPhi, savedArray, phi)); -} - -/// Get interpolation for 1 dimension non cyclic -/// -/// \param xArray Double_t[] known position x -/// \param yArray Double_t[] known y = f(x) -/// \param x unknown position -/// -/// \return interpolation value f(x) -Double_t AliTPC3DCylindricalInterpolator::Interpolate(Double_t xArray[], Double_t yArray[], Double_t x) const -{ - Double_t y; - - // if cubic spline - if (fOrder > 2) { - Double_t y2Array[fOrder + 1]; - InitCubicSpline(xArray, yArray, fOrder + 1, y2Array, 1); - y = InterpolateCubicSpline(xArray, yArray, y2Array, fOrder + 1, fOrder + 1, fOrder + 1, x, 1); - } else if (fOrder == 2) { - // Quadratic Interpolation = 2 - y = (x - xArray[1]) * (x - xArray[2]) * yArray[0] / ((xArray[0] - xArray[1]) * (xArray[0] - xArray[2])); - y += (x - xArray[2]) * (x - xArray[0]) * yArray[1] / ((xArray[1] - xArray[2]) * (xArray[1] - xArray[0])); - y += (x - xArray[0]) * (x - xArray[1]) * yArray[2] / ((xArray[2] - xArray[0]) * (xArray[2] - xArray[1])); - } else { - // Linear Interpolation = 1 - y = yArray[0] + (yArray[1] - yArray[0]) * (x - xArray[0]) / (xArray[1] - xArray[0]); - } - return (y); -} - -/// Get interpolation for 1 dimension cyclic -/// -/// \param xArray Double_t[] known position x -/// \param yArray Double_t[] known y = f(x) -/// \param x unknown position -/// -/// \return interpolation value f(x) -Double_t AliTPC3DCylindricalInterpolator::InterpolatePhi( - Double_t xArray[], const Int_t iLow, const Int_t lenX, Double_t yArray[], Double_t x) const -{ - Int_t i0 = iLow; - Double_t xi0 = xArray[iLow]; - Int_t i1 = (iLow + 1) % lenX; - Double_t xi1 = xArray[i1]; - Int_t i2 = (iLow + 2) % lenX; - Double_t xi2 = xArray[i2]; - - if (fOrder <= 2) { - if (xi1 < xi0) { - xi1 = TMath::TwoPi() + xi1; - } - if (xi2 < xi1) { - xi2 = TMath::TwoPi() + xi2; - } - if (x < xi0) { - x = TMath::TwoPi() + x; - } - } - - Double_t y; - if (fOrder > 2) { - Double_t y2Array[fOrder + 1]; - Double_t xArrayTemp[fOrder + 1]; - Double_t dPhi = xArray[1] - xArray[0]; - // make list phi ascending order - for (Int_t i = 0; i < fOrder + 1; i++) { - xArrayTemp[i] = xArray[iLow] + (dPhi * i); - } - if (x < xArrayTemp[0]) { - x = TMath::TwoPi() + x; - } - if (x < xArrayTemp[0] || x > xArrayTemp[fOrder]) { - printf("x (%f) is outside of interpolation box (%f,%f)\n", x, xArrayTemp[0], xArrayTemp[fOrder]); - } - - InitCubicSpline(xArrayTemp, yArray, fOrder + 1, y2Array, 1); - y = InterpolateCubicSpline(xArrayTemp, yArray, y2Array, fOrder + 1, fOrder + 1, fOrder + 1, x, 1); - } else if (fOrder == 2) { // Quadratic Interpolation = 2 - y = (x - xi1) * (x - xi2) * yArray[0] / ((xi0 - xi1) * (xi0 - xi2)); - y += (x - xi2) * (x - xi0) * yArray[1] / ((xi1 - xi2) * (xi1 - xi0)); - y += (x - xi0) * (x - xi1) * yArray[2] / ((xi2 - xi0) * (xi2 - xi1)); - } else { // Li2near Interpolation = 1 - y = yArray[0] + (yArray[1] - yArray[0]) * (x - xi0) / (xi1 - xi0); - } - return (y); -} - -/// Solving cubic splines for system of splines -/// -/// \param xArray Double_t[] known position x -/// \param yArray Double_t[] known y = f(x) -/// \param n Int_t length of splines -/// \param y2Array Double_t[] calculated $d^2Y$ spline (output) -/// \param skip memory offset for xArray -/// -void AliTPC3DCylindricalInterpolator::InitCubicSpline(Double_t* xArray, Double_t* yArray, const Int_t n, Double_t* y2Array, - const Int_t skip) const -{ - Double_t u[n]; - Double_t sig, p, qn, un; - - y2Array[0] = 0.0; - u[0] = 0.0; //natural condition - - for (Int_t i = 1; i <= n - 2; i++) { - sig = (xArray[i] - xArray[i - 1]) / (xArray[i + 1] - xArray[i - 1]); - p = sig * y2Array[(i - 1) * skip] + 2.0; - y2Array[i * skip] = (sig - 1.0) / p; - u[i] = (yArray[(i + 1) * skip] - yArray[i * skip]) / (xArray[i + 1] - xArray[i]) - - (yArray[i * skip] - yArray[(i - 1) * skip]) / (xArray[i] - xArray[i - 1]); - u[i] = (6.0 * u[i] / (xArray[i + 1] - xArray[i - 1]) - sig * u[i - 1]) / p; - } - - qn = un = 0.0; - - y2Array[(n - 1) * skip] = (un - qn * u[n - 2]) / (qn * y2Array[(n - 2) * skip] + 1.0); - for (Int_t k = n - 2; k >= 0; k--) { - y2Array[k * skip] = y2Array[k * skip] * y2Array[(k + 1) * skip] + u[k]; - } -} - -/// Solving cubic splines for system of splines -/// -/// \param xArray Double_t[] known position x -/// \param yArray Double_t[] known y = f(x) -/// \param n Int_t length of splines -/// \param y2Array Double_t[] calculated $d^2Y$ spline (output) -/// \param skip memory offset for xArray -/// -void AliTPC3DCylindricalInterpolator::InitCubicSpline(Double_t* xArray, Double_t* yArray, const Int_t n, Double_t* y2Array, - const Int_t skip, Double_t yp0, Double_t ypn1) const -{ - Double_t u[n]; - Double_t sig, p, qn, un; - - y2Array[0] = 0.0; - u[0] = 0.0; //natural condition - - for (Int_t i = 1; i <= n - 2; i++) { - sig = (xArray[i] - xArray[i - 1]) / (xArray[i + 1] - xArray[i - 1]); - p = sig * y2Array[(i - 1) * skip] + 2.0; - y2Array[i * skip] = (sig - 1.0) / p; - u[i] = (yArray[(i + 1) * skip] - yArray[i * skip]) / (xArray[i + 1] - xArray[i]) - - (yArray[i * skip] - yArray[(i - 1) * skip]) / (xArray[i] - xArray[i - 1]); - u[i] = (6.0 * u[i] / (xArray[i + 1] - xArray[i - 1]) - sig * u[i - 1]) / p; - } - - qn = un = 0.0; - y2Array[(n - 1) * skip] = (un - qn * u[n - 2]) / (qn * y2Array[(n - 2) * skip] + 1.0); - for (Int_t k = n - 2; k >= 0; k--) { - y2Array[k * skip] = y2Array[k * skip] * y2Array[(k + 1) * skip] + u[k]; - } -} - -/// Interpolate initialized cubic spline -/// -/// \param xArray -/// \param yArray -/// \param y2Array -/// \param nxArray -/// \param nyArray -/// \param ny2Array -/// \param x -/// \param skip -/// \return -Double_t AliTPC3DCylindricalInterpolator::InterpolateCubicSpline(Double_t* xArray, Double_t* yArray, Double_t* y2Array, - const Int_t nxArray, const Int_t nyArray, - const Int_t ny2Array, Double_t x, Int_t skip) const -{ - Int_t klo, khi, k; - Float_t h, b, a; - klo = 0; - khi = nxArray - 1; - - while (khi - klo > 1) { - k = (khi + klo) >> 1; - if (xArray[k] > x) { - khi = k; - } else { - klo = k; - } - } - - h = xArray[khi] - xArray[klo]; - - if (TMath::Abs(h) < 1e-10) { - return 0.0; - } - - a = (xArray[khi] - x) / h; - b = (x - xArray[klo]) / h; - - Double_t y = a * yArray[klo] + b * yArray[khi] + - ((a * a * a - a) * y2Array[klo * skip] + (b * b * b - b) * y2Array[khi * skip]) * (h * h) / 6.0; - - return y; -} - -/// init cubic spline for all -/// -void AliTPC3DCylindricalInterpolator::InitCubicSpline() -{ - - Double_t yp0, ypn1; - if (fIsInitCubic != kTRUE) { - fSecondDerZ = new Double_t[fNR * fNZ * fNPhi]; - - // Init at Z direction - for (Int_t m = 0; m < fNPhi; m++) { - for (Int_t i = 0; i < fNR; i++) { - yp0 = (-(11.0 / 6.0) * fValue[(m * (fNZ * fNR) + i * fNZ)] + - (3.0 * fValue[(m * (fNZ * fNR) + i * fNZ) + 1]) - - (1.5 * fValue[(m * (fNZ * fNR) + i * fNZ) + 2]) + - ((1.0 / 3.0) * fValue[(m * (fNZ * fNR) + i * fNZ) + 4])) / - (fZList[1] - fZList[0]); - ypn1 = (-(11.0 / 6.0) * fValue[(m * (fNZ * fNR) + i * fNZ) + (fNZ - 1)] + - (3.0 * fValue[(m * (fNZ * fNR) + i * fNZ) + (fNZ - 2)]) - - (1.5 * fValue[(m * (fNZ * fNR) + i * fNZ) + (fNZ - 3)]) + - ((1.0 / 3.0) * fValue[(m * (fNZ * fNR) + i * fNZ) + (fNZ - 4)])) / - (fZList[0] - fZList[1]); - InitCubicSpline(fZList, &fValue[m * (fNZ * fNR) + i * fNZ], fNZ, - &fSecondDerZ[m * (fNZ * fNR) + i * fNZ], 1); - } - } - - fIsInitCubic = kTRUE; - } -} - -/// Search the nearest grid index position to a Point -/// -/// \param n -/// \param xArray -/// \param x -/// \param low -void AliTPC3DCylindricalInterpolator::Search(Int_t n, const Double_t xArray[], Double_t x, Int_t& low) const -{ - /// Search an ordered table by starting at the most recently used point - - Long_t middle, high; - Int_t ascend = 0, increment = 1; - - if (xArray[n - 1] > xArray[0]) { - ascend = 1; // Ascending ordered table if true - } - if (low < 0 || low > n - 1) { - low = -1; - high = n; - } else { // Ordered Search phase - if ((Int_t)(x > xArray[low]) == ascend) { - if (low == n - 1) { - return; - } - high = low + 1; - while ((Int_t)(x > xArray[high]) == ascend) { - low = high; - increment *= 2; - high = low + increment; - if (high > n - 1) { - high = n; - break; - } - } - } else { - if (low == 0) { - low = -1; - return; - } - high = low - 1; - while ((Int_t)(x < xArray[low]) == ascend) { - high = low; - increment *= 2; - if (increment >= high) { - low = -1; - break; - } else { - low = high - increment; - } - } - } - } - - while ((high - low) != 1) { // Binary Search Phase - middle = (high + low) / 2; - if ((Int_t)(x > xArray[middle]) == ascend) { - low = middle; - } else { - high = middle; - } - } - - if (x > xArray[n - 1]) { - low = n; - } - if (x < xArray[0]) { - low = -1; - } -} - -/// Set the value as interpolation point -/// -/// \param matricesVal TMatrixD** reference value for each point -void AliTPC3DCylindricalInterpolator::SetValue(TMatrixD** matricesVal) -{ - Int_t indexVal1D; - Int_t index1D; - if (!fIsAllocatingLookUp) { - fValue = new Double_t[fNPhi * fNR * fNZ]; - fIsAllocatingLookUp = kTRUE; - } - for (Int_t m = 0; m < fNPhi; m++) { - indexVal1D = m * fNR * fNZ; - TMatrixD* mat = matricesVal[m]; - for (Int_t i = 0; i < fNR; i++) { - index1D = indexVal1D + i * fNZ; - for (Int_t j = 0; j < fNZ; j++) { - fValue[index1D + j] = (*mat)(i, j); - } - } - } -} - -/// Set the value as interpolation point -/// -/// \param matricesVal TMatrixD** reference value for each point -void AliTPC3DCylindricalInterpolator::SetValue(TMatrixD** matricesVal, Int_t iZ) -{ - Int_t indexVal1D; - Int_t index1D; - if (!fIsAllocatingLookUp) { - fValue = new Double_t[fNPhi * fNR * fNZ]; - fIsAllocatingLookUp = kTRUE; - } - for (Int_t m = 0; m < fNPhi; m++) { - indexVal1D = m * fNR * fNZ; - TMatrixD* mat = matricesVal[m]; - for (Int_t i = 0; i < fNR; i++) { - index1D = indexVal1D + i * fNZ; - fValue[index1D + iZ] = (*mat)(i, iZ); - } - } -} - -/// set the position of R -/// -/// \param rList -void AliTPC3DCylindricalInterpolator::SetRList(Double_t* rList) -{ - fRList = new Double_t[fNR]; - for (Int_t i = 0; i < fNR; i++) { - fRList[i] = rList[i]; - } -} - -/// set the position of phi -/// -/// \param phiList -void AliTPC3DCylindricalInterpolator::SetPhiList(Double_t* phiList) -{ - fPhiList = new Double_t[fNPhi]; - for (Int_t i = 0; i < fNPhi; i++) { - fPhiList[i] = phiList[i]; - } -} - -/// Setting z position -/// -/// \param zList -void AliTPC3DCylindricalInterpolator::SetZList(Double_t* zList) -{ - fZList = new Double_t[fNZ]; - for (Int_t i = 0; i < fNZ; i++) { - fZList[i] = zList[i]; - } -} - -/// Setting values from 1D -/// -/// \param valueList -void AliTPC3DCylindricalInterpolator::SetValue(Double_t* valueList) { fValue = valueList; } - -/// Set number of total grid points -void AliTPC3DCylindricalInterpolator::SetNGridPoints() -{ - if (fNR == 0 || fNPhi == 0 || fNZ == 0) { - Error("AliTPC3DCylindricalInterpolator::SetNGridPoints", "Error in calculating total number of grid points! Either nR, nPhi or nZ are zero!"); - } - fNGridPoints = fNR * fNPhi * fNZ; -} \ No newline at end of file diff --git a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.h b/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.h deleted file mode 100644 index 67e01e640dbd4..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolator.h +++ /dev/null @@ -1,80 +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. - -/// \file AliTPC3DCylindricalInterpolator.h -/// \brief Interpolator for cylindrical coordinate -/// this class provides: cubic spline, quadratic and linear interpolation -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Jan 5, 2016 - -#ifndef AliTPC3DCylindricalInterpolator_H -#define AliTPC3DCylindricalInterpolator_H - -#include <TMatrixD.h> - -class AliTPC3DCylindricalInterpolator -{ - public: - AliTPC3DCylindricalInterpolator(); - ~AliTPC3DCylindricalInterpolator(); - Double_t GetValue(Double_t r, Double_t phi, Double_t z) const; - void InitCubicSpline(); - void SetOrder(Int_t order) { fOrder = order; } - void SetNR(Int_t nR) { fNR = nR; } - void SetNPhi(Int_t nPhi) { fNPhi = nPhi; } - void SetNZ(Int_t nZ) { fNZ = nZ; } - void SetNGridPoints(); - void SetRList(Double_t* rList); - void SetPhiList(Double_t* phiList); - void SetZList(Double_t* zList); - void SetValue(Double_t* vList); - void SetValue(TMatrixD** vList); - void SetValue(TMatrixD** vList, Int_t iZ); - - Int_t GetNR() { return fNR; } - Int_t GetNPhi() { return fNPhi; } - Int_t GetNZ() { return fNZ; } - Int_t GetOrder() { return fOrder; } - - Double_t* GetSecondDerZ() { return fSecondDerZ; } - - private: - Int_t fOrder; ///< Order of interpolation, 1 - linear, 2 - quadratic, 3 >= - cubic, - Int_t fNR; ///< Grid size in direction of R - Int_t fNPhi; ///< Grid size in direction of Phi - Int_t fNZ; ///< Grid size in direction of Z - Int_t fNGridPoints; ///< Total number of grid points (needed for streamer) - - Double_t* fValue = nullptr; //[fNGridPoints] Description 3D for storing known values interpolation should be in size fNR*fNPhi*fNZ - Double_t* fRList = nullptr; //[fNR] coordinate in R (cm) (should be increasing) - Double_t* fPhiList = nullptr; //[fNPhi] coordinate in phiList (rad) (should be increasing) 0 <= < 2 pi (cyclic) - Double_t* fZList = nullptr; //[fNZ] coordinate in z list (cm) (should be increasing) - Double_t* fSecondDerZ = nullptr; //[fNGridPoints] store second derivative of cubic interpolation in z direction - - Bool_t fIsAllocatingLookUp; ///< is allocating memory - Bool_t fIsInitCubic; ///< is cubic second derivative already been initialized - - Double_t InterpolatePhi(Double_t xArray[], const Int_t iLow, const Int_t lenX, Double_t yArray[], Double_t x) const; - Double_t InterpolateCylindrical(Double_t r, Double_t z, Double_t phi) const; - Double_t Interpolate(Double_t xArray[], Double_t yArray[], Double_t x) const; - Double_t InterpolateCubicSpline(Double_t* xArray, Double_t* yArray, Double_t* y2Array, const Int_t nxArray, - const Int_t nyArray, const Int_t ny2Array, Double_t x, const Int_t skip) const; - void Search(Int_t n, const Double_t xArray[], Double_t x, Int_t& low) const; - void InitCubicSpline(Double_t* xArray, Double_t* yArray, const Int_t n, Double_t* y2Array, const Int_t skip) const; - void InitCubicSpline(Double_t* xArray, Double_t* yArray, const Int_t n, Double_t* y2Array, const Int_t skip, - Double_t yp0, Double_t ypn1) const; - - /// \cond CLASSIMP - ClassDefNV(AliTPC3DCylindricalInterpolator, 1); - /// \endcond -}; - -#endif diff --git a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.cxx b/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.cxx deleted file mode 100644 index b4d395ceadbaa..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.cxx +++ /dev/null @@ -1,1514 +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. - -/// \file AliTPC3DCylindricalInterpolatorIrregular.cxx -/// \brief Irregular grid interpolator for cylindrical coordinate with r,phi,z different coordinates -/// RBF-based interpolation -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Jan 5, 2016 - -#include "TMath.h" -#include "TVector.h" -#include "TVectorD.h" -#include "TMatrix.h" -#include "TMatrixD.h" -#include "TDecompSVD.h" -#include "AliTPCPoissonSolver.h" -#include "AliTPC3DCylindricalInterpolatorIrregular.h" -#include <cstdlib> - -/// \cond CLASSIMP3 -ClassImp(AliTPC3DCylindricalInterpolatorIrregular); -/// \endcond - -/// constructor -/// -/// \param nRRow -/// \param nZColumn -/// \param nPhiSlice -/// \param rStep -/// \param zStep -/// \param phiStep -/// \param type -AliTPC3DCylindricalInterpolatorIrregular::AliTPC3DCylindricalInterpolatorIrregular( - Int_t nRRow, Int_t nZColumn, Int_t nPhiSlice, Int_t rStep, Int_t zStep, Int_t phiStep, Int_t type) -{ - fOrder = 1; - fIsAllocatingLookUp = kFALSE; - fMinZIndex = 0; - fNR = nRRow; - fNZ = nZColumn; - fNPhi = nPhiSlice; - fNGridPoints = nRRow * nZColumn * nPhiSlice; - - fRBFWeightLookUp = new Int_t[nRRow * nZColumn * nPhiSlice]; - - Int_t nd = rStep * zStep * phiStep; - fStepR = rStep; - fStepZ = zStep; - fStepPhi = phiStep; - fNRBFpoints = nRRow * nZColumn * nPhiSlice * nd; - - fType = type; - fRBFWeight = new Double_t[nRRow * nZColumn * nPhiSlice * nd]; - for (Int_t i = 0; i < nRRow * nZColumn * nPhiSlice; i++) { - fRBFWeightLookUp[i] = 0; - } - - SetKernelType(kRBFInverseMultiQuadratic); -} - -/// constructor -/// -AliTPC3DCylindricalInterpolatorIrregular::AliTPC3DCylindricalInterpolatorIrregular() -{ - fOrder = 1; - fIsAllocatingLookUp = kFALSE; - - fMinZIndex = 0; -} - -/// destructor -/// -AliTPC3DCylindricalInterpolatorIrregular::~AliTPC3DCylindricalInterpolatorIrregular() -{ - - delete fValue; - delete fRList; - delete fPhiList; - delete fZList; - - if (fKDTreeIrregularPoints) { - delete[] fKDTreeIrregularPoints; - delete fKDTreeIrregularRoot; - } - delete[] fRBFWeightLookUp; - delete[] fRBFWeight; -} - -/// irregular grid interpolation with IDW (inverse distance weight) -/// -/// \param r -/// \param z -/// \param phi -/// \param rIndex -/// \param zIndex -/// \param phiIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \return -Double_t - AliTPC3DCylindricalInterpolatorIrregular::Interpolate3DTableCylIDW( - Double_t r, Double_t z, Double_t phi, Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t rStep, Int_t phiStep, - Int_t zStep) -{ - Double_t r0, z0, phi0, d; - Double_t MIN_DIST = 1e-3; - Double_t val = 0.0; - Int_t startPhi = phiIndex - phiStep / 2; - Int_t indexPhi; - Int_t startR = rIndex - rStep / 2; - Int_t startZ = zIndex - zStep / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - if (startR < 0) { - startR = 0; - } - if (startR + rStep >= fNR) { - startR = fNR - rStep; - } - - if (startZ < fMinZIndex) { - startZ = fMinZIndex; - } - if (startZ + zStep >= fNZ) { - startZ = fNZ - zStep; - } - - Int_t index; - Double_t sum_w = 0.0; - Double_t sum_d = 0.0; - Double_t shortest_d = 10000.0; - Int_t new_rIndex = 0; - Int_t new_zIndex = 0; - Int_t new_phiIndex = 0; - - for (Int_t iPhi = startPhi; iPhi < startPhi + phiStep; iPhi++) { - indexPhi = iPhi % fNPhi; - for (Int_t index_r = startR; index_r < startR + rStep; index_r++) { - for (Int_t index_z = startZ; index_z < startZ + zStep; index_z++) { - // check for the closest poInt_t - index = indexPhi * (fNZ * fNR) + index_r * fNZ + index_z; - - r0 = fRList[index]; - z0 = fZList[index]; - phi0 = fPhiList[index]; - - d = Distance(r0, phi0, z0, r, phi, z); - if (d < shortest_d) { - shortest_d = d; - new_rIndex = index_r; - new_phiIndex = indexPhi; - new_zIndex = index_z; - } - } - } - } - - phiStep = 3; - rStep = 3; - startPhi = new_phiIndex - phiStep / 2; - startR = new_rIndex - rStep / 2; - startZ = new_zIndex - zStep / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - if (startR < 0) { - startR = 0; - } - if (startR + rStep >= fNR) { - startR = fNR - rStep; - } - - if (startZ < fMinZIndex) { - startZ = fMinZIndex; - } - if (startZ + zStep >= fNZ) { - startZ = fNZ - zStep; - } - - for (Int_t iPhi = startPhi; iPhi < startPhi + phiStep; iPhi++) { - indexPhi = iPhi % fNPhi; - for (Int_t index_r = startR; index_r < startR + rStep; index_r++) { - for (Int_t index_z = startZ; index_z < startZ + zStep; index_z++) { - // check for the closest poInt_t - index = indexPhi * (fNZ * fNR) + index_r * fNZ + index_z; - - r0 = fRList[indexPhi * (fNR * fNZ) + index_r * fNZ + index_z]; - z0 = fZList[indexPhi * (fNR * fNZ) + index_r * fNZ + index_z]; - phi0 = fPhiList[indexPhi * (fNR * fNZ) + index_r * fNZ + index_z]; - d = Distance(r0, phi0, z0, r, phi, z); - if (d < MIN_DIST) { - return fValue[index]; - } - d = 1.0 / d; - sum_w += (fValue[index] * d * d * d * d); - sum_d += d * d * d * d; - } - } - } - return (sum_w / sum_d); -} - -/// distance in Cyl coordinate -/// -/// \param r0 -/// \param phi0 -/// \param z0 -/// \param r -/// \param phi -/// \param z -/// \return -Double_t - AliTPC3DCylindricalInterpolatorIrregular::Distance(Double_t r0, Double_t phi0, Double_t z0, Double_t r, Double_t phi, - Double_t z) -{ - if (phi < 0) { - phi = TMath::TwoPi() + phi; - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - if (phi0 < 0) { - phi0 = TMath::TwoPi() + phi0; - } - if (phi0 > TMath::TwoPi()) { - phi0 = phi0 - TMath::TwoPi(); - } - - Double_t dPhi = phi - phi0; - if (dPhi > TMath::Pi()) { - dPhi = TMath::TwoPi() - dPhi; - } - if (dPhi < -TMath::Pi()) { - dPhi = TMath::TwoPi() + dPhi; - } - - Double_t ret = r * r + r0 * r0 - 2 * r0 * r * TMath::Cos(dPhi) + (z - z0) * (z - z0); - - return TMath::Sqrt(ret); -} - -/// main operation -/// interpolation by RBF -/// -/// \param r -/// \param z -/// \param phi -/// \param rIndex -/// \param zIndex -/// \param phiIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param radiusRBF0 -/// \return -Double_t - AliTPC3DCylindricalInterpolatorIrregular::Interpolate3DTableCylRBF( - Double_t r, Double_t z, Double_t phi, Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t rStep, Int_t phiStep, - Int_t zStep, Double_t radiusRBF0) -{ - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (fNR - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (fNZ - 1); - const Float_t gridSizePhi = TMath::TwoPi() / fNPhi; - Double_t r0, z0, phi0, d; - Double_t MIN_DIST = 1e-3; - Double_t val = 0.0; - Int_t startPhi = phiIndex - phiStep / 2; - Int_t indexPhi; - Int_t startR = rIndex - rStep / 2; - Int_t startZ = zIndex - zStep / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - if (startR < 0) { - startR = 0; - } - if (startR + rStep >= fNR) { - startR = fNR - rStep; - } - - if (startZ < fMinZIndex) { - startZ = fMinZIndex; - } - if (startZ + zStep >= fNZ) { - startZ = fNZ - zStep; - } - - Int_t index; - Double_t sum_w = 0.0; - Double_t sum_d = 0.0; - Double_t shortest_d = 10000.0; - Int_t new_rIndex = 0; - Int_t new_zIndex = 0; - Int_t new_phiIndex = 0; - - for (Int_t iPhi = startPhi; iPhi < startPhi + phiStep; iPhi++) { - indexPhi = iPhi % fNPhi; - for (Int_t index_r = startR; index_r < startR + rStep; index_r++) { - for (Int_t index_z = startZ; index_z < startZ + zStep; index_z++) { - // check for the closest poInt_t - index = indexPhi * (fNZ * fNR) + index_r * fNZ + index_z; - - r0 = fRList[index]; - z0 = fZList[index]; - phi0 = fPhiList[index]; - - d = Distance(r0, phi0, z0, r, phi, z); - if (d < shortest_d) { - shortest_d = d; - new_rIndex = index_r; - new_phiIndex = indexPhi; - new_zIndex = index_z; - } - } - } - } - - index = new_phiIndex * (fNZ * fNR) + new_rIndex * fNZ + new_zIndex; - phiStep = fStepPhi; - rStep = fStepR; - zStep = fStepZ; - startPhi = new_phiIndex - phiStep / 2; - - startR = new_rIndex - rStep / 2; - startZ = new_zIndex - zStep / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - - if (startR < 0) { - startR = 0; - } - if (startR + rStep >= fNR) { - startR = fNR - rStep; - } - - if (startZ < fMinZIndex) { - startZ = fMinZIndex; - } - if (startZ + zStep >= fNZ) { - startZ = fNZ - zStep; - } - - Double_t* w; - - //Int_t nd = (phiStep-1) + (rStep-1) + (zStep-1) + 1; - Int_t nd = phiStep * rStep * zStep; - - w = new Double_t[nd]; - - Float_t minTemp, minTemp2; - - radiusRBF0 = GetRadius0RBF(new_rIndex, new_phiIndex, new_zIndex); - - if (fType == 1) { - - for (Int_t i = 0; i < nd; i++) { - w[i] = 0.0; - } - GetRBFWeight(new_rIndex, new_zIndex, new_phiIndex, rStep, phiStep, zStep, radiusRBF0, 0, w); - val = InterpRBF(r, phi, z, startR, startPhi, startZ, rStep, phiStep, zStep, radiusRBF0, 0, w); - } else { - GetRBFWeightHalf(new_rIndex, new_zIndex, new_phiIndex, rStep, phiStep, zStep, radiusRBF0, 0, w); - val = InterpRBFHalf(r, phi, z, startR, startPhi, startZ, rStep, phiStep, zStep, radiusRBF0, 0, w); - } - delete[] w; - return val; -} - -/// Search nearest point at grid -/// \param n -/// \param xArray -/// \param offset -/// \param x -/// \param low -void AliTPC3DCylindricalInterpolatorIrregular::Search(Int_t n, Double_t* xArray, Int_t offset, Double_t x, Int_t& low) -{ - /// Search an ordered table by starting at the most recently used poInt_t - - Long_t middle, high; - Int_t ascend = 0, increment = 1; - - if (xArray[(n - 1) * offset] >= xArray[0 * offset]) { - ascend = 1; // Ascending ordered table if true - } - if (low < 0 || low > n - 1) { - low = -1; - high = n; - } else { // Ordered Search phase - if ((Int_t)(x >= xArray[low * offset]) == ascend) { - if (low == n - 1) { - return; - } - high = low + 1; - while ((Int_t)(x >= xArray[high * offset]) == ascend) { - low = high; - increment *= 2; - high = low + increment; - if (high > n - 1) { - high = n; - break; - } - } - } else { - if (low == 0) { - low = -1; - return; - } - high = low - 1; - while ((Int_t)(x < xArray[low * offset]) == ascend) { - high = low; - increment *= 2; - if (increment >= high) { - low = -1; - break; - } else { - low = high - increment; - } - } - } - } - - while ((high - low) != 1) { // Binary Search Phase - middle = (high + low) / 2; - if ((Int_t)(x >= xArray[middle * offset]) == ascend) { - low = middle; - } else { - high = middle; - } - } - - if (x > xArray[n - 1]) { - low = n; - } - if (x < xArray[0]) { - low = -1; - } -} - -/// get value, interpolation with RBF -/// -/// \param r -/// \param phi -/// \param z -/// \param rIndex -/// \param phiIndex -/// \param zIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \return -Double_t AliTPC3DCylindricalInterpolatorIrregular::GetValue( - Double_t r, Double_t phi, Double_t z, Int_t rIndex, Int_t phiIndex, Int_t zIndex, Int_t rStep, Int_t phiStep, - Int_t zStep) -{ - - fMinZIndex = 0; - return Interpolate3DTableCylRBF(r, z, phi, rIndex, zIndex, phiIndex, rStep, phiStep, zStep, 0.0); -} - -/// get value -/// -/// \param r -/// \param phi -/// \param z -/// \param rIndex -/// \param phiIndex -/// \param zIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param minZColumnIndex -/// \return -Double_t AliTPC3DCylindricalInterpolatorIrregular::GetValue( - Double_t r, Double_t phi, Double_t z, Int_t rIndex, Int_t phiIndex, Int_t zIndex, Int_t rStep, Int_t phiStep, - Int_t zStep, Int_t minZColumnIndex) -{ - fMinZIndex = minZColumnIndex; - return Interpolate3DTableCylRBF(r, z, phi, rIndex, zIndex, phiIndex, rStep, phiStep, zStep, 0.0); -} - -// GetValue using searching at KDTree -Double_t AliTPC3DCylindricalInterpolatorIrregular::GetValue( - Double_t r, Double_t phi, Double_t z) -{ - - KDTreeNode n; - n.pR = &r; - n.pPhi = φ - n.pZ = &z; - KDTreeNode* nearest; - Double_t dist; - dist = 100000000.0; - Int_t startIndex = 0; // Z - Int_t dim = 3; // dimenstion - KDTreeNearest(fKDTreeIrregularRoot, &n, startIndex, dim, &nearest, &dist); - return Interpolate3DTableCylRBF(r, z, phi, nearest); -} -/// Set value and distorted point for irregular grid interpolation -/// -/// \param matrixRicesValue -/// \param matrixRicesRPoint -/// \param matrixRicesPhiPoint -/// \param matrixRicesZPoint -void AliTPC3DCylindricalInterpolatorIrregular::SetValue( - TMatrixD** matrixRicesValue, TMatrixD** matrixRicesRPoint, TMatrixD** matrixRicesPhiPoint, - TMatrixD** matrixRicesZPoint) -{ - Int_t indexInner; - Int_t index; - - if (!fIsAllocatingLookUp) { - fValue = new Double_t[fNPhi * fNR * fNZ]; - fRList = new Double_t[fNPhi * fNR * fNZ]; - fPhiList = new Double_t[fNPhi * fNR * fNZ]; - fZList = new Double_t[fNPhi * fNR * fNZ]; - fIsAllocatingLookUp = kTRUE; - } - - for (Int_t m = 0; m < fNPhi; m++) { - indexInner = m * fNR * fNZ; - TMatrixD* mat = matrixRicesValue[m]; - TMatrixD* matrixR = matrixRicesRPoint[m]; - TMatrixD* matrixPhi = matrixRicesPhiPoint[m]; - TMatrixD* matrixZ = matrixRicesZPoint[m]; - - for (Int_t i = 0; i < fNR; i++) { - index = indexInner + i * fNZ; - for (Int_t j = 0; j < fNZ; j++) { - fValue[index + j] = (*mat)(i, j); - - fRList[index + j] = (*matrixR)(i, j); - fPhiList[index + j] = (*matrixPhi)(i, j); - fZList[index + j] = (*matrixZ)(i, j); - } - } - } - // KD Tree is used for look-up a point to irregular grid to find - // closest neughboor point - InitKDTree(); - InitRBFWeight(); -} - -/// init RBF Weights assume value already been set -/// -void AliTPC3DCylindricalInterpolatorIrregular::InitRBFWeight() -{ - - Int_t indexInner; - Int_t rIndex; - Int_t index; - Int_t startR; - Int_t nd; - - const Double_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (fNR - 1); - const Double_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (fNZ - 1); - const Double_t gridSizePhi = TMath::TwoPi() / fNPhi; - - Float_t r0; - Double_t radiusRBF0, minTemp, minTemp2; - - nd = fStepR * fStepPhi * fStepZ; - for (Int_t m = 0; m < fNPhi; m++) { - indexInner = m * fNR * fNZ; - for (Int_t i = 0; i < fNR; i++) { - rIndex = indexInner + i * fNZ; - - startR = i - fStepR / 2; - - if (startR < 0) { - startR = 0; - } - if (startR + fStepR >= fNR) { - startR = fNR - fStepR; - } - - for (Int_t j = 0; j < fNZ; j++) { - index = rIndex + j; - - radiusRBF0 = GetRadius0RBF(i, j, m); - - RBFWeight( - i, - j, - m, - fStepR, - fStepPhi, - fStepZ, - radiusRBF0, - fKernelType, - &fRBFWeight[index * nd]); - fRBFWeightLookUp[index] = 1; - } - } - } -} - -/// Set value and distorted Point -/// -/// \param matrixRicesValue -/// \param matrixRicesRPoint -/// \param matrixRicesPhiPoint -/// \param matrixRicesZPoint -/// \param jy -void AliTPC3DCylindricalInterpolatorIrregular::SetValue( - TMatrixD** matrixRicesValue, TMatrixD** matrixRicesRPoint, TMatrixD** matrixRicesPhiPoint, - TMatrixD** matrixRicesZPoint, - Int_t jy) -{ - Int_t indexInner; - Int_t index; - - if (!fIsAllocatingLookUp) { - fValue = new Double_t[fNPhi * fNR * fNZ]; - fRList = new Double_t[fNPhi * fNR * fNZ]; - fPhiList = new Double_t[fNPhi * fNR * fNZ]; - fZList = new Double_t[fNPhi * fNR * fNZ]; - - fIsAllocatingLookUp = kTRUE; - } - - for (Int_t m = 0; m < fNPhi; m++) { - indexInner = m * fNR * fNZ; - TMatrixD* mat = matrixRicesValue[m]; - TMatrixD* matrixR = matrixRicesRPoint[m]; - TMatrixD* matrixPhi = matrixRicesPhiPoint[m]; - TMatrixD* matrixZ = matrixRicesZPoint[m]; - - for (Int_t i = 0; i < fNR; i++) { - index = indexInner + i * fNZ; - fValue[index + jy] = (*mat)(i, jy); - fRList[index + jy] = (*matrixR)(i, jy); - fPhiList[index + jy] = (*matrixPhi)(i, jy); - fZList[index + jy] = (*matrixZ)(i, jy); - } - } -} - -/// calculate -/// RBFWeight for all points in the interpolation -/// -/// \param rIndex -/// \param zIndex -/// \param phiIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param radius0 -/// \param kernelType -/// \param w -void AliTPC3DCylindricalInterpolatorIrregular::RBFWeight( - Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t rStep, Int_t phiStep, Int_t zStep, Double_t radius0, - Int_t kernelType, Double_t* w) -{ - - Double_t* a; - Int_t i; - Int_t j; - Int_t k; - Int_t ii; - Int_t jj; - Int_t kk; - - Int_t index0, index1; - Int_t indexCyl0, indexCyl1; - Double_t* r; - Double_t* v; - - Double_t phi0; - Double_t z0; - Double_t r0; - - Double_t phi1; - Double_t z1; - Double_t r1; - - Int_t nd = rStep * phiStep * zStep; - - a = new Double_t[nd * nd]; - r = new Double_t[nd]; - v = new Double_t[nd]; - - Int_t startPhi = phiIndex - phiStep / 2; - Int_t indexPhi; - Int_t indexPhi1; - - Int_t startR = rIndex - rStep / 2; - Int_t startZ = zIndex - zStep / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - - if (startR < 0) { - startR = 0; - } - if (startR + rStep >= fNR) { - startR = fNR - rStep; - } - - if (startZ < fMinZIndex) { - startZ = fMinZIndex; - } - if (startZ + zStep >= fNZ) { - startZ = fNZ - zStep; - } - - index0 = 0; - - for (i = startPhi; i < startPhi + phiStep; i++) { - indexPhi = i % fNPhi; - - for (j = startR; j < startR + rStep; j++) { - for (k = startZ; k < startZ + zStep; k++) { - indexCyl0 = indexPhi * fNR * fNZ + j * fNZ + k; - - r0 = fRList[indexCyl0]; - z0 = fZList[indexCyl0]; - phi0 = fPhiList[indexCyl0]; - - index1 = 0; - for (ii = startPhi; ii < startPhi + phiStep; ii++) { - indexPhi1 = ii % fNPhi; - for (jj = startR; jj < startR + rStep; jj++) { - for (kk = startZ; kk < startZ + zStep; kk++) { - indexCyl1 = indexPhi1 * fNR * fNZ + jj * fNZ + kk; - r1 = fRList[indexCyl1]; - z1 = fZList[indexCyl1]; - phi1 = fPhiList[indexCyl1]; - r[index1] = Distance(r0, phi0, z0, r1, phi1, z1); - - index1++; - } - } - } - - Phi(nd, r, radius0, v); - - index1 = 0; - for (ii = startPhi; ii < startPhi + phiStep; ii++) { - indexPhi1 = ii % fNPhi; - for (jj = startR; jj < startR + rStep; jj++) { - for (kk = startZ; kk < startZ + zStep; kk++) { - a[index0 * nd + index1] = v[index1]; - index1++; - } - } - } - w[index0] = fValue[indexCyl0]; - index0++; - } - } - } - - TMatrixD mat_a; - mat_a.Use(nd, nd, a); - TVectorD vec_w; - vec_w.Use(nd, w); - TDecompSVD svd(mat_a); - - svd.Solve(vec_w); - - delete[] a; - delete[] r; - delete[] v; -} - -/// rbf1 -/// \param n -/// \param r -/// \param r0 -/// \param v -void AliTPC3DCylindricalInterpolatorIrregular::rbf1(Int_t n, Double_t r[], Double_t r0, Double_t v[]) -{ - Int_t i; - - for (i = 0; i < n; i++) { - v[i] = sqrt(1 + (r[i] * r[i] + r0 * r0)); - } - return; -} - -/// rbf2 -/// \param n -/// \param r -/// \param r0 -/// \param v - -void AliTPC3DCylindricalInterpolatorIrregular::rbf2(Int_t n, Double_t r[], Double_t r0, Double_t v[]) -{ - Int_t i; - - for (i = 0; i < n; i++) { - v[i] = 1.0 / sqrt(1 + (r[i] * r[i] + r0 * r0)); - } - return; -} - -/// rbf3 -/// \param n -/// \param r -/// \param r0 -/// \param v -void AliTPC3DCylindricalInterpolatorIrregular::rbf3(Int_t n, Double_t r[], Double_t r0, Double_t v[]) -{ - Int_t i; - - for (i = 0; i < n; i++) { - if (r[i] <= 0.0) { - v[i] = 0.0; - } else { - v[i] = r[i] * r[i] * log(r[i] / r0); - } - } - return; -} - -/// rbf4 -/// \param n -/// \param r -/// \param r0 -/// \param v -void AliTPC3DCylindricalInterpolatorIrregular::rbf4(Int_t n, Double_t r[], Double_t r0, Double_t v[]) -{ - Int_t i; - - for (i = 0; i < n; i++) { - v[i] = TMath::Exp(-0.5 * r[i] * r[i] / (r0 * r0)); - } - return; -} - -// RBF based interpolation -// return interpolated value -/// -/// \param r -/// \param phi -/// \param z -/// \param startR -/// \param startPhi -/// \param startZ -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param radius0 -/// \param kernelType -/// \param weight -/// \return -Double_t AliTPC3DCylindricalInterpolatorIrregular::InterpRBF( - Double_t r, Double_t phi, Double_t z, Int_t startR, Int_t startPhi, Int_t startZ, Int_t rStep, Int_t phiStep, - Int_t zStep, Double_t radius0, Int_t kernelType, Double_t* weight) -{ - Double_t interpVal = 0.0; - Double_t r0, z0, phi0; - Double_t* dList; - Double_t* v; - - Int_t indexCyl0, index0, indexPhi; - - Int_t nd = rStep * phiStep * zStep; - - dList = new Double_t[nd]; - v = new Double_t[nd]; - - index0 = 0; - for (Int_t i = startPhi; i < startPhi + phiStep; i++) { - indexPhi = i % fNPhi; - - for (Int_t j = startR; j < startR + rStep; j++) { - for (Int_t k = startZ; k < startZ + zStep; k++) { - - indexCyl0 = indexPhi * fNR * fNZ + j * fNZ + k; - - r0 = fRList[indexCyl0]; - z0 = fZList[indexCyl0]; - phi0 = fPhiList[indexCyl0]; - - dList[index0] = Distance(r, phi, z, r0, phi0, z0); - index0++; - } - } - } - - Phi(nd, dList, radius0, v); - - TVectorD vec_v; - vec_v.Use(nd, v); - - TVectorD vec_w; - vec_w.Use(nd, weight); - - interpVal = vec_v * vec_w; - delete[] v; - delete[] dList; - return interpVal; -} - -// calculate -// RBFWeight for all points in the interpolation -/// -/// \param rIndex -/// \param zIndex -/// \param phiIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param radius0 -/// \param kernelType -/// \param w -void AliTPC3DCylindricalInterpolatorIrregular::GetRBFWeight( - Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t rStep, Int_t phiStep, Int_t zStep, Double_t radius0, - Int_t kernelType, Double_t* w) -{ - - Int_t index = phiIndex * fNR * fNZ + rIndex * fNZ + zIndex; - if (fRBFWeightLookUp[index] == 0) { - RBFWeight(rIndex, zIndex, phiIndex, rStep, phiStep, zStep, radius0, kernelType, w); - - fRBFWeightLookUp[index] = 1; - Int_t nd = rStep * zStep * phiStep; - - for (Int_t i = 0; i < nd; i++) { - fRBFWeight[index * nd + i] = w[i]; - } - } else { - - Int_t ndw = rStep * zStep * phiStep; - - Int_t nd = fStepR * fStepZ * fStepPhi; - Int_t indexWeight = phiIndex * fNR * fNZ * nd + rIndex * fNZ * nd + zIndex * nd; - - for (Int_t i = 0; i < nd; i++) { - w[i] = fRBFWeight[indexWeight + i]; - } - } -} - -// calculate -// RBFWeight for all points in the interpolation -/// -/// \param rIndex -/// \param zIndex -/// \param phiIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param radius0 -/// \param kernelType -/// \param w -void AliTPC3DCylindricalInterpolatorIrregular::GetRBFWeightHalf( - Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t rStep, Int_t phiStep, Int_t zStep, Double_t radius0, - Int_t kernelType, Double_t* w) -{ - - Int_t index = phiIndex * fNR * fNZ + rIndex * fNZ + zIndex; - - if (fRBFWeightLookUp[index] == 0) { - RBFWeightHalf(rIndex, zIndex, phiIndex, rStep, phiStep, zStep, radius0, kernelType, w); - - if ((rStep == fStepR) && (zStep == fStepZ) && (phiStep == fStepPhi) && (zIndex > fMinZIndex + fStepZ)) { - fRBFWeightLookUp[index] = 1; - // copy to lookup - Int_t nd = rStep + zStep + phiStep - 2; - - for (Int_t i = 0; i < nd; i++) { - fRBFWeight[index * nd + i] = w[i]; - } - } - } else { - - //Int_t ndw = rStep*zStep*phiStep; - Int_t nd = rStep + zStep + phiStep - 2; - Int_t indexWeight = phiIndex * fNR * fNZ * nd + rIndex * fNZ * nd + zIndex * nd; - - for (Int_t i = 0; i < nd; i++) { - w[i] = fRBFWeight[indexWeight + i]; - } - } -} - -// calculate -// RBFWeight for all points in the interpolation -// half cubes (not included -/// -/// \param rIndex -/// \param zIndex -/// \param phiIndex -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param radius0 -/// \param kernelType -/// \param w -void AliTPC3DCylindricalInterpolatorIrregular::RBFWeightHalf( - Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t rStep, Int_t phiStep, Int_t zStep, Double_t radius0, - Int_t kernelType, Double_t* w) -{ - Double_t* a; - Int_t i; - Int_t j; - Int_t k; - Int_t ii; - Int_t jj; - Int_t kk; - - Int_t index0, index1; - Int_t indexCyl0, indexCyl1; - Double_t* r; - Double_t* v; - - Double_t phi0; - Double_t z0; - Double_t r0; - - Double_t phi1; - Double_t z1; - Double_t r1; - - Int_t nd = (rStep - 1) + (phiStep - 1) + (zStep - 1) + 1; - - a = new Double_t[nd * nd]; - r = new Double_t[nd]; - v = new Double_t[nd]; - - Int_t startPhi = phiIndex - phiStep / 2; - Int_t indexPhi; - Int_t indexPhi1; - - Int_t startR = rIndex - rStep / 2; - Int_t startZ = zIndex - zStep / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - - if (startR < 0) { - startR = 0; - } - if (startR + rStep >= fNR) { - startR = fNR - rStep; - } - - if (startZ < fMinZIndex) { - startZ = fMinZIndex; - } - if (startZ + zStep >= fNZ) { - startZ = fNZ - zStep; - } - - index0 = 0; - - for (i = startPhi; i < startPhi + phiStep; i++) { - indexPhi = i % fNPhi; - - for (j = startR; j < startR + rStep; j++) { - for (k = startZ; k < startZ + zStep; k++) { - - if ( - (i == (startPhi + phiStep / 2) && j == (startR + rStep / 2)) || - (i == (startPhi + phiStep / 2) && k == (startZ + zStep / 2)) || - (j == (startR + rStep / 2) && k == (startZ + zStep / 2))) { - indexCyl0 = indexPhi * fNR * fNZ + j * fNZ + k; - - r0 = fRList[indexCyl0]; - z0 = fZList[indexCyl0]; - phi0 = fPhiList[indexCyl0]; - - index1 = 0; - for (ii = startPhi; ii < startPhi + phiStep; ii++) { - indexPhi1 = ii % fNPhi; - for (jj = startR; jj < startR + rStep; jj++) { - for (kk = startZ; kk < startZ + zStep; kk++) { - if ( - (ii == (startPhi + phiStep / 2) && jj == (startR + rStep / 2)) || - (ii == (startPhi + phiStep / 2) && kk == (startZ + zStep / 2)) || - (jj == (startR + rStep / 2) && kk == (startZ + zStep / 2))) { - - indexCyl1 = indexPhi1 * fNR * fNZ + jj * fNZ + kk; - r1 = fRList[indexCyl1]; - z1 = fZList[indexCyl1]; - phi1 = fPhiList[indexCyl1]; - - r[index1] = Distance(r0, phi0, z0, r1, phi1, z1); - index1++; - } - } - } - } - - Phi(nd, r, radius0, v); - - index1 = 0; - for (ii = startPhi; ii < startPhi + phiStep; ii++) { - indexPhi1 = ii % fNPhi; - for (jj = startR; jj < startR + rStep; jj++) { - for (kk = startZ; kk < startZ + zStep; kk++) { - if ( - (ii == (startPhi + phiStep / 2) && jj == (startR + rStep / 2)) || - (ii == (startPhi + phiStep / 2) && kk == (startZ + zStep / 2)) || - (jj == (startR + rStep / 2) && kk == (startZ + zStep / 2))) { - a[index0 * nd + index1] = v[index1]; - index1++; - } - } - } - } - - w[index0] = fValue[indexCyl0]; - index0++; - } - } - } - } - - TMatrixD mat_a; - mat_a.Use(nd, nd, a); - TVectorD vec_w; - - vec_w.Use(nd, w); - TDecompSVD svd(mat_a); - - svd.Solve(vec_w); - - delete[] a; - delete[] r; - delete[] v; -} - -// RBF based interpolation -// return interpolated value -// half points -/// -/// \param r -/// \param phi -/// \param z -/// \param startR -/// \param startPhi -/// \param startZ -/// \param rStep -/// \param phiStep -/// \param zStep -/// \param radius0 -/// \param kernelType -/// \param weight -/// \return -Double_t AliTPC3DCylindricalInterpolatorIrregular::InterpRBFHalf( - Double_t r, Double_t phi, Double_t z, Int_t startR, Int_t startPhi, Int_t startZ, Int_t rStep, Int_t phiStep, - Int_t zStep, Double_t radius0, Int_t kernelType, Double_t* weight) -{ - Double_t interpVal = 0.0; - Double_t r0, z0, phi0; - Double_t* dList; - Double_t* v; - - Int_t indexCyl0, index0, indexPhi; - - // Int_t nd = rStep * phiStep * zStep; - Int_t nd = (rStep - 1) + (phiStep - 1) + (zStep - 1) + 1; - - dList = new Double_t[nd]; - v = new Double_t[nd]; - - index0 = 0; - for (Int_t i = startPhi; i < startPhi + phiStep; i++) { - indexPhi = i % fNPhi; - - for (Int_t j = startR; j < startR + rStep; j++) { - for (Int_t k = startZ; k < startZ + zStep; k++) { - if ( - (i == (startPhi + phiStep / 2) && j == (startR + rStep / 2)) || - (i == (startPhi + phiStep / 2) && k == (startZ + zStep / 2)) || - (j == (startR + rStep / 2) && k == (startZ + zStep / 2))) { - - indexCyl0 = indexPhi * fNR * fNZ + j * fNZ + k; - - r0 = fRList[indexCyl0]; - z0 = fZList[indexCyl0]; - phi0 = fPhiList[indexCyl0]; - - dList[index0] = Distance(r, phi, z, r0, phi0, z0); - index0++; - } - } - } - } - - Phi(nd, dList, radius0, v); - - TVectorD vec_v; - vec_v.Use(nd, v); - - TVectorD vec_w; - vec_w.Use(nd, weight); - - interpVal = vec_v * vec_w; - delete[] v; - delete[] dList; - return interpVal; -} - -// set Radius0 -/// -/// \param n -/// \param r -/// \param r0 -/// \param v -void AliTPC3DCylindricalInterpolatorIrregular::Phi(Int_t n, Double_t r[], Double_t r0, Double_t v[]) -{ - - switch (fKernelType) { - case kRBFMultiQuadratic: - rbf1(n, r, r0, v); - break; - case kRBFInverseMultiQuadratic: - rbf2(n, r, r0, v); - break; - case kRBFThinPlateSpline: - rbf3(n, r, r0, v); - break; - case kRBFGaussian: - rbf4(n, r, r0, v); - break; - - default: - rbf1(n, r, r0, v); - break; - } -} - -// -Double_t - AliTPC3DCylindricalInterpolatorIrregular::GetRadius0RBF(const Int_t rIndex, const Int_t phiIndex, const Int_t zIndex) -{ - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (fNR - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (fNZ - 1); - const Float_t gridSizePhi = TMath::TwoPi() / fNPhi; - Int_t startPhi = phiIndex - fStepPhi / 2; - - Int_t startR = rIndex - fStepR / 2; - Int_t startZ = zIndex - fStepZ / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - - if (startR < 0) { - startR = 0; - } - if (startR + fStepR >= fNR) { - startR = fNR - fStepR; - } - - if (startZ < 0) { - startZ = 0; - } - if (startZ + fStepZ >= fNZ) { - startZ = fNZ - fStepZ; - } - - Double_t r0 = AliTPCPoissonSolver::fgkIFCRadius + (startR * gridSizeR); - Double_t phi0 = startPhi * gridSizePhi; - Double_t z0 = startZ * gridSizeZ; - - Double_t r1 = AliTPCPoissonSolver::fgkIFCRadius + (startR * gridSizeR); - Double_t phi1 = (startPhi + 1) * gridSizePhi; - Double_t z1 = (startZ + 1) * gridSizeZ; - - if (fKernelType == kRBFThinPlateSpline) { - r0 = AliTPCPoissonSolver::fgkIFCRadius + ((startR - 1) * gridSizeR); - } else { - r0 = AliTPCPoissonSolver::fgkIFCRadius + (startR * gridSizeR); - } - - return Distance(r0, 0.0, 0.0, r0 + gridSizeR, gridSizePhi, gridSizeR); -} - -// make kdtree for irregular look-up -void AliTPC3DCylindricalInterpolatorIrregular::InitKDTree() -{ - Int_t count = fNR * fNZ * fNPhi; - - fKDTreeIrregularPoints = new KDTreeNode[count]; - - for (Int_t i = 0; i < count; i++) { - fKDTreeIrregularPoints[i].pR = &fRList[i]; - fKDTreeIrregularPoints[i].pZ = &fZList[i]; - fKDTreeIrregularPoints[i].pPhi = &fPhiList[i]; - fKDTreeIrregularPoints[i].index = i; - } - - fKDTreeIrregularRoot = MakeKDTree(fKDTreeIrregularPoints, count, 0, 3); -} - -// create KDTree -AliTPC3DCylindricalInterpolatorIrregular::KDTreeNode* AliTPC3DCylindricalInterpolatorIrregular::MakeKDTree(KDTreeNode* t, Int_t count, Int_t index, Int_t dim) -{ - KDTreeNode* n; - - if (!count) { - return nullptr; - } - if ((n = FindMedian(t, t + count, index))) { - index = (index + 1) % dim; - n->left = MakeKDTree(t, (n - t), index, dim); - n->right = MakeKDTree(n + 1, (t + count) - (n + 1), index, dim); - } - return n; -} - -// find median -AliTPC3DCylindricalInterpolatorIrregular::KDTreeNode* AliTPC3DCylindricalInterpolatorIrregular::FindMedian(KDTreeNode* start, KDTreeNode* end, Int_t index) -{ - if (end <= start) { - return nullptr; - } - if (end == start + 1) { - return start; - } - - KDTreeNode *p, *store, *md = start + (end - start) / 2; - Double_t pivot; - - while (1) { - if (index == 0) { - pivot = *(md->pZ); - } else if (index == 1) { - pivot = *(md->pR); - } else { - pivot = *(md->pPhi); - } - - Swap(md, end - 1); - - for (store = p = start; p < end; p++) { - - if (((index == 0) && (*(p->pZ) < pivot)) || - ((index == 1) && (*(p->pR) < pivot)) || - ((index == 2) && (*(p->pPhi) < pivot))) - - { - if (p != store) { - Swap(p, store); - } - store++; - } - } - Swap(store, end - 1); - - if ((index == 0) && (*(store->pZ) == *(md->pZ))) { - return md; - } - if ((index == 1) && (*(store->pR) == *(md->pR))) { - return md; - } - if ((index == 2) && (*(store->pPhi) == *(md->pPhi))) { - return md; - } - - // if (md->index == store->index) return md; - - if (store > md) { - end = store; - } else { - start = store; - } - } -} - -//swap -void AliTPC3DCylindricalInterpolatorIrregular::Swap(KDTreeNode* x, KDTreeNode* y) -{ - KDTreeNode* tmp = new KDTreeNode; - tmp->pR = x->pR; - tmp->pZ = x->pZ; - tmp->pPhi = x->pPhi; - tmp->index = x->index; - - x->pR = y->pR; - x->pZ = y->pZ; - x->pPhi = y->pPhi; - x->index = y->index; - - y->pR = tmp->pR; - y->pZ = tmp->pZ; - y->pPhi = tmp->pPhi; - y->index = tmp->index; - - delete tmp; -} - -// look for nearest point -void AliTPC3DCylindricalInterpolatorIrregular::KDTreeNearest(KDTreeNode* root, KDTreeNode* nd, Int_t index, Int_t dim, - KDTreeNode** best, Double_t* best_dist) -{ - Double_t d, dx2, dx; - - if (!root) { - return; - } - d = Distance(*(root->pR), *(root->pPhi), *(root->pZ), *(nd->pR), *(nd->pPhi), *(nd->pZ)); - if (index == 0) { - dx = *(root->pZ) - *(nd->pZ); - dx2 = Distance(*(nd->pR), *(nd->pPhi), *(root->pZ), *(nd->pR), *(nd->pPhi), *(nd->pZ)); - } else if (index == 1) { - dx = *(root->pR) - *(nd->pR); - dx2 = Distance(*(root->pR), *(nd->pPhi), *(nd->pZ), *(nd->pR), *(nd->pPhi), *(nd->pZ)); - } else { - dx = *(root->pPhi) - *(nd->pPhi); - dx2 = Distance(*(nd->pR), *(root->pPhi), *(nd->pZ), *(nd->pR), *(nd->pPhi), *(nd->pZ)); - } - - if (!*best || (d < *best_dist)) { - *best_dist = d; - *best = root; - } - - if (!*best_dist) { - return; - } - - if (++index >= dim) { - index = 0; - } - - KDTreeNearest(dx > 0 ? root->left : root->right, nd, index, dim, best, best_dist); - if (dx2 >= *best_dist) { - return; - } - KDTreeNearest(dx > 0 ? root->right : root->left, nd, index, dim, best, best_dist); -} - -// interpolate on the nearest neighbor of irregular grid -Double_t - AliTPC3DCylindricalInterpolatorIrregular::Interpolate3DTableCylRBF( - Double_t r, Double_t z, Double_t phi, KDTreeNode* nearestNode) -{ - Double_t val = 0.0; - Int_t startPhi, startR, startZ; - Int_t phiIndex, rIndex, zIndex; - - phiIndex = nearestNode->index / (fNR * fNZ); - rIndex = (nearestNode->index - (phiIndex * (fNR * fNZ))) / fNZ; - zIndex = nearestNode->index - (phiIndex * (fNR * fNZ) + rIndex * fNZ); - - startPhi = phiIndex - fStepPhi / 2; - startR = rIndex - fStepR / 2; - startZ = zIndex - fStepZ / 2; - - if (startPhi < 0) { - startPhi = fNPhi + startPhi; - } - - if (startR < 0) { - startR = 0; - } - if (startR + fStepR >= fNR) { - startR = fNR - fStepR; - } - - if (startZ < 0) { - startZ = 0; - } - if (startZ + fStepZ >= fNZ) { - startZ = fNZ - fStepZ; - } - Int_t indexPhi; - - Int_t index; - Double_t r0, z0, phi0; - - Int_t rStep = fStepR; - Int_t zStep = fStepZ; - Int_t phiStep = fStepPhi; - - Double_t* w; - - //Int_t nd = (phiStep-1) + (rStep-1) + (zStep-1) + 1; - Int_t nd = fStepPhi * fStepR * fStepZ; - - w = new Double_t[nd]; - - Float_t minTemp, minTemp2; - - Double_t radiusRBF0 = GetRadius0RBF(rIndex, phiIndex, zIndex); - - if (fType == 1) { - - for (Int_t i = 0; i < nd; i++) { - w[i] = 0.0; - } - GetRBFWeight(rIndex, zIndex, phiIndex, rStep, phiStep, zStep, radiusRBF0, 0, w); - val = InterpRBF(r, phi, z, startR, startPhi, startZ, rStep, phiStep, zStep, radiusRBF0, 0, w); - } else { - GetRBFWeightHalf(rIndex, zIndex, phiIndex, rStep, phiStep, zStep, radiusRBF0, 0, w); - val = InterpRBFHalf(r, phi, z, startR, startPhi, startZ, rStep, phiStep, zStep, radiusRBF0, 0, w); - } - delete[] w; - return val; -} diff --git a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.h b/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.h deleted file mode 100644 index 952114b174cd2..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPC3DCylindricalInterpolatorIrregular.h +++ /dev/null @@ -1,151 +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. - -/// \file AliTPC3DCylindricalInterpolatorIrregular.h -/// \brief Irregular grid interpolator for cylindrical coordinate with r,phi,z different coordinates -/// RBF-based interpolation -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Jan 5, 2016 - -#ifndef AliTPC3DCylindricalInterpolatorIrregular_H -#define AliTPC3DCylindricalInterpolatorIrregular_H - -#include "TMatrixD.h" - -class AliTPC3DCylindricalInterpolatorIrregular -{ - public: - AliTPC3DCylindricalInterpolatorIrregular(Int_t nRRow, Int_t nZColumn, Int_t nPhiSlice, Int_t rStep, Int_t zStep, - Int_t phiStep, Int_t intType); - AliTPC3DCylindricalInterpolatorIrregular(); - ~AliTPC3DCylindricalInterpolatorIrregular(); - - Double_t - GetValue(Double_t r, Double_t phi, Double_t z, Int_t rIndex, Int_t phiIndex, Int_t zIndex, Int_t stepR, Int_t stepPhi, - Int_t stepZ); - Double_t - GetValue(Double_t r, Double_t phi, Double_t z, Int_t rIndex, Int_t phiIndex, Int_t zIndex, Int_t stepR, Int_t stepPhi, - Int_t stepZ, Int_t minZColumnIndex); - Double_t GetValue(Double_t r, Double_t phi, Double_t z); - void SetOrder(Int_t order) { fOrder = order; } - - void InitRBFWeight(); - void SetIrregularGridSize(Int_t size) { fIrregularGridSize = size; } - Int_t GetIrregularGridSize() { return fIrregularGridSize; } - void SetKernelType(Int_t kernelType) { fKernelType = kernelType; } - Int_t GetKernelType() { return fKernelType; } - - ///< Enumeration of Poisson Solver Strategy Type - enum RBFKernelType { - kRBFMultiQuadratic = 0, - kRBFInverseMultiQuadratic = 1, - kRBFThinPlateSpline = 2, - kRBFGaussian = 3 - }; - - void SetNR(Int_t nRRow) { fNR = nRRow; } - void SetNPhi(Int_t nPhiSlice) { fNPhi = nPhiSlice; } - void SetNZ(Int_t nZColumn) { fNZ = nZColumn; } - - Int_t GetNR() { return fNR; } - Int_t GetNPhi() { return fNPhi; } - Int_t GetNZ() { return fNZ; } - - void SetRList(Double_t* rList) { fRList = rList; } - void SetPhiList(Double_t* phiList) { fPhiList = phiList; } - void SetZList(Double_t* zList) { fZList = zList; } - - void SetValue(Double_t* value) { fValue = value; } - void - SetValue(TMatrixD** matricesValue, TMatrixD** matricesRPoint, TMatrixD** matricesPhiPoint, TMatrixD** matricesZPoint); - void - SetValue(TMatrixD** matricesValue, TMatrixD** matricesRPoint, TMatrixD** matricesPhiPoint, TMatrixD** matricesZPoint, - Int_t jy); - - struct KDTreeNode { - Double_t* pR; //!<! TODO: fix for streamers - Double_t* pZ; //!<! - Double_t* pPhi; //!<! - Int_t index; - struct KDTreeNode *left, *right; - }; - - private: - Int_t fOrder; ///< Order of interpolation, 1 - linear, 2 - quadratic, 3 - cubic - Int_t fType; ///< 0 INVERSE WEIGHT, 1 RBF FULL, 2 RBF Half - Int_t fKernelType; ///< type kernel RBF 1--5 - Int_t fIrregularGridSize; ///< size when interpolating for irregular grid - Int_t fNR; ///< Grid size in direction of R - Int_t fNPhi; ///< Grid size in direction of Phi - Int_t fNZ; ///< Grid size in direction of Z - Int_t fNGridPoints; ///< Total number of grid points (needed for streamer) - Int_t fNRBFpoints; ///< Total number of points for RBF weights - Int_t fMinZIndex; ///<index z minimal as lower bound - Int_t fStepR; ///< step in R direction for irregular grid - Int_t fStepZ; ///< step in Z direction for irregular grid - Int_t fStepPhi; ///< step in Phi direction for irregular grid - Int_t* fRBFWeightLookUp = nullptr; //[fNGridPoints] weighted look up - - Double_t fRadiusRBF0; ///< Radius RBF0 - Double_t* fValue = nullptr; //[fNGridPoints] 3D for storing known values interpolation should be in size fNR*fNPhi*fNZ - Double_t* fRList = nullptr; //[fNGridPoints] coordinate in R (cm) (should be increasing) in 3D - Double_t* fPhiList = nullptr; //[fNGridPoints] coordinate in phiList (rad) (should be increasing) 0 <= < 2 pi (cyclic) in 3D - Double_t* fZList = nullptr; //[fNGridPoints] coordinate in z list (cm) (should be increasing) in 3D - Double_t* fRBFWeight = nullptr; //[fNRBFpoints] weight for RBF - Bool_t fIsAllocatingLookUp; ///< is allocating memory? - - Double_t Interpolate3DTableCylIDW(Double_t r, Double_t z, Double_t phi, Int_t rIndex, Int_t zIndex, Int_t phiIndex, - Int_t stepR, Int_t stepZ, Int_t stepPhi); - Double_t Interpolate3DTableCylRBF(Double_t r, Double_t z, Double_t phi, Int_t rIndex, Int_t zIndex, Int_t phiIndex, - Int_t stepR, Int_t stepZ, Int_t stepPhi, Double_t radiusRBF0); - Double_t Interpolate3DTableCylRBF(Double_t r, Double_t z, Double_t phi, KDTreeNode* nearestNode); - - void Search(Int_t n, const Double_t xArray[], Double_t x, Int_t& low); - void Search(Int_t n, Double_t* xArray, Int_t offset, Double_t x, Int_t& low); - Double_t Distance(Double_t r0, Double_t phi0, Double_t z0, Double_t r, Double_t phi, Double_t z); - void RBFWeight(Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ, Double_t radius0, - Int_t kernelType, Double_t* weight); - void - GetRBFWeight(Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ, Double_t radius0, - Int_t kernelType, Double_t* weight); - void Phi(Int_t n, Double_t r[], Double_t r0, Double_t v[]); - void rbf1(Int_t n, Double_t r[], Double_t r0, Double_t v[]); - void rbf2(Int_t n, Double_t r[], Double_t r0, Double_t v[]); - void rbf3(Int_t n, Double_t r[], Double_t r0, Double_t v[]); - void rbf4(Int_t n, Double_t r[], Double_t r0, Double_t v[]); - Double_t InterpRBF(Double_t r, Double_t phi, Double_t z, Int_t startR, Int_t startPhi, Int_t startZ, Int_t stepR, - Int_t stepPhi, Int_t stepZ, Double_t radius0, Int_t kernelType, Double_t* weight); - void - RBFWeightHalf(Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ, Double_t radius0, - Int_t kernelType, Double_t* weight); - Double_t InterpRBFHalf(Double_t r, Double_t phi, Double_t z, Int_t startR, Int_t startPhi, Int_t startZ, Int_t stepR, - Int_t stepPhi, Int_t stepZ, Double_t radius0, Int_t kernelType, Double_t* weight); - void GetRBFWeightHalf(Int_t rIndex, Int_t zIndex, Int_t phiIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ, - Double_t radius0, Int_t kernelType, Double_t* weight); - Double_t GetRadius0RBF(const Int_t rIndex, const Int_t phiIndex, const Int_t zIndex); - - KDTreeNode* fKDTreeIrregularPoints = nullptr; //!<![fNGridPoints] to save tree as list - KDTreeNode* fKDTreeIrregularRoot = nullptr; //!<! kdtree root TODO: make this streamable - - void InitKDTree(); - KDTreeNode* MakeKDTree(KDTreeNode* tree, Int_t count, Int_t index, Int_t dimention); - - KDTreeNode* FindMedian(KDTreeNode* startTree, KDTreeNode* endTree, Int_t index); - void Swap(KDTreeNode* x, KDTreeNode* y); - - void KDTreeNearest(KDTreeNode* root, KDTreeNode* nd, Int_t index, Int_t dim, - KDTreeNode** best, Double_t* best_dist); - /// \cond CLASSIMP - ClassDefNV(AliTPC3DCylindricalInterpolatorIrregular, 1); - /// \endcond -}; - -#endif diff --git a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.cxx b/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.cxx deleted file mode 100644 index 10e0837b95699..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.cxx +++ /dev/null @@ -1,215 +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. - -/// \file AliTPCLookUpTable3DInterpolatorD.cxx -/// \brief Wrap up look-up table for correction/distortion integral or derivative (electric field) -/// assume 3 components: r-component, phi-component and z-component -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Mar 4, 2015 - -#include "AliTPCLookUpTable3DInterpolatorD.h" - -/// \cond CLASSIMP3 -ClassImp(AliTPCLookUpTable3DInterpolatorD); -/// \endcond - -/// constructor -AliTPCLookUpTable3DInterpolatorD::AliTPCLookUpTable3DInterpolatorD() -{ - fOrder = 1; - fIsAllocatingLookUp = kFALSE; -} - -/// constructor -/// -/// \param nRRow Int_t size of grid in R direction -/// \param rMin Double_t minimal value of R -/// \param rMax Double_t maximal value of R -/// \param nPhiSlice Int_t size of grid Phi direction -/// \param phiMin Double_t minimal value of Phi -/// \param phiMax Double_t maximal value of Phi -/// \param nZColumn Int_t size of grid Z direction -/// \param zMin Double_t minimal value of Z -/// \param zMax Double_t maximal value of Z - -/** - AliTPCLookUpTable3DInterpolatorD::AliTPCLookUpTable3DInterpolatorD(Int_t nRRow, Double_t rMin, Double_t rMax, - Int_t nPhiSlice, - Double_t phiMin, Double_t phiMax, Int_t nZColumn, - Double_t zMin, Double_t zMax) { - fOrder = 1; - fIsAllocatingLookUp = kTRUE; - - fNR = nRRow; - fNPhi = nPhiSlice; - fNZ = nZColumn; - - fLookUpR = new TMatrixD *[fNPhi]; - fLookUpPhi = new TMatrixD *[fNPhi]; - fLookUpZ = new TMatrixD *[fNPhi]; - - for (Int_t m = 0; m < fNPhi; m++) { - fLookUpR[m] = new TMatrixD(fNR, fNZ); - fLookUpPhi[m] = new TMatrixD(fNR, fNZ); - fLookUpZ[m] = new TMatrixD(fNR, fNZ); - } - - fRList = new Double_t[fNR]; - fPhiList = new Double_t[fNPhi]; - fZList = new Double_t[fNZ]; - - Double_t dR = (rMax - rMin) / fNR; - Double_t dPhi = (phiMax - phiMin) / fNPhi; - Double_t dZ = (zMax - zMin) / fNPhi; - - for (Int_t m = 0; m < fNPhi; m++) fPhiList[m] = phiMin + dPhi * m; - for (Int_t m = 0; m < fNR; m++) fRList[m] = rMin + dR * m; - for (Int_t m = 0; m < fNZ; m++) fZList[m] = zMin + dZ * m; - } - **/ - -/// Constructor -/// -/// \param nRRow Int_t size of grid in R direction -/// \param matricesRValue TMatrixD** values of component R -/// \param rList Double_t* list of position R -/// \param nPhiSlice Int_t size of grid in Phi direction -/// \param matricesPhiValue TMatrixD** values of component Phi -/// \param phiList Double_t* list of position Phi -/// \param nZColumn Int_t size of grid in Z direction -/// \param matricesZValue TMatrixD** values of component Z -/// \param zList Double_t* list of position Z -/// \param order Int_t order of interpolation -AliTPCLookUpTable3DInterpolatorD::AliTPCLookUpTable3DInterpolatorD( - Int_t nRRow, TMatrixD** matricesRValue, Double_t* rList, - Int_t nPhiSlice, TMatrixD** matricesPhiValue, Double_t* phiList, - Int_t nZColumn, TMatrixD** matricesZValue, Double_t* zList, Int_t order) -{ - fIsAllocatingLookUp = kFALSE; - - SetNR(nRRow); - SetLookUpR(matricesRValue); - SetRList(rList); - SetNPhi(nPhiSlice); - SetLookUpPhi(matricesPhiValue); - SetPhiList(phiList); - SetNZ(nZColumn); - SetLookUpZ(matricesZValue); - SetZList(zList); - - fInterpolatorR = new AliTPC3DCylindricalInterpolator(); - fInterpolatorZ = new AliTPC3DCylindricalInterpolator(); - fInterpolatorPhi = new AliTPC3DCylindricalInterpolator(); - - SetOrder(order); - fInterpolatorR->SetNR(nRRow); - fInterpolatorR->SetNZ(nZColumn); - fInterpolatorR->SetNPhi(nPhiSlice); - fInterpolatorR->SetNGridPoints(); - fInterpolatorR->SetRList(rList); - fInterpolatorR->SetZList(zList); - fInterpolatorR->SetPhiList(phiList); - fInterpolatorR->SetOrder(order); - - fInterpolatorZ->SetNR(nRRow); - fInterpolatorZ->SetNZ(nZColumn); - fInterpolatorZ->SetNPhi(nPhiSlice); - fInterpolatorZ->SetNGridPoints(); - fInterpolatorZ->SetRList(rList); - fInterpolatorZ->SetZList(zList); - fInterpolatorZ->SetPhiList(phiList); - fInterpolatorZ->SetOrder(order); - - fInterpolatorPhi->SetNR(nRRow); - fInterpolatorPhi->SetNZ(nZColumn); - fInterpolatorPhi->SetNPhi(nPhiSlice); - fInterpolatorPhi->SetNGridPoints(); - fInterpolatorPhi->SetRList(rList); - fInterpolatorPhi->SetZList(zList); - fInterpolatorPhi->SetPhiList(phiList); - fInterpolatorPhi->SetOrder(order); -} - -/// destructor -AliTPCLookUpTable3DInterpolatorD::~AliTPCLookUpTable3DInterpolatorD() -{ - delete fInterpolatorR; - delete fInterpolatorZ; - delete fInterpolatorPhi; -} - -/// copy from matrices to 1D array for interpolation algorithm -void AliTPCLookUpTable3DInterpolatorD::CopyFromMatricesToInterpolator() -{ - fInterpolatorR->SetValue(fLookUpR); - fInterpolatorZ->SetValue(fLookUpZ); - fInterpolatorPhi->SetValue(fLookUpPhi); - - if (fOrder > 2) { - fInterpolatorR->InitCubicSpline(); - fInterpolatorZ->InitCubicSpline(); - fInterpolatorPhi->InitCubicSpline(); - } -} - -/// copy from matrices to 1D array for interpolation algorithm -void AliTPCLookUpTable3DInterpolatorD::CopyFromMatricesToInterpolator(Int_t iZ) -{ - fInterpolatorR->SetValue(fLookUpR, iZ); - fInterpolatorZ->SetValue(fLookUpZ, iZ); - fInterpolatorPhi->SetValue(fLookUpPhi, iZ); - - // no implementation for cubic spline interpolation -} - -/// get value of 3-components at a P(r,phi,z) -/// -/// \param r Double_t r position -/// \param phi Double_t phi position -/// \param z Double_t z position -/// \param rValue Double_t value of r-component -/// \param phiValue Double_t value of phi-component -/// \param zValue Double_t value of z-component -void AliTPCLookUpTable3DInterpolatorD::GetValue( - Double_t r, Double_t phi, Double_t z, - Double_t& rValue, Double_t& phiValue, Double_t& zValue) const -{ - rValue = fInterpolatorR->GetValue(r, phi, z); - phiValue = fInterpolatorPhi->GetValue(r, phi, z); - zValue = fInterpolatorZ->GetValue(r, phi, z); -} - -/// get value for return value is a Float_t -/// -/// \param r Double_t r position -/// \param phi Double_t phi position -/// \param z Double_t z position -/// \param rValue Float_t value of r-component -/// \param phiValue Float_t value of phi-component -/// \param zValue Float_t value of z-component -void AliTPCLookUpTable3DInterpolatorD::GetValue( - Double_t r, Double_t phi, Double_t z, - Float_t& rValue, Float_t& phiValue, Float_t& zValue) const -{ - rValue = fInterpolatorR->GetValue(r, phi, z); - phiValue = fInterpolatorPhi->GetValue(r, phi, z); - zValue = fInterpolatorZ->GetValue(r, phi, z); -} - -// Set Order of interpolation -// -void AliTPCLookUpTable3DInterpolatorD::SetOrder(Int_t order) -{ - fOrder = order; - fInterpolatorR->SetOrder(order); - fInterpolatorZ->SetOrder(order); - fInterpolatorPhi->SetOrder(order); -} diff --git a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.h b/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.h deleted file mode 100644 index 470a84577a69e..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorD.h +++ /dev/null @@ -1,87 +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. - -/// \file AliTPCLookUpTable3DInterpolatorD.h -/// \brief Wrap up look-up table for correction/distortion integral or derivative (electric field) -/// assume 3 components: r-component, phi-component and z-component -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Mar 4, 2015 - -#ifndef AliTPCLookUpTable3DInterpolatorD_H -#define AliTPCLookUpTable3DInterpolatorD_H - -#include "TMatrixD.h" -#include "AliTPC3DCylindricalInterpolator.h" - -class AliTPCLookUpTable3DInterpolatorD -{ - public: - AliTPCLookUpTable3DInterpolatorD(); - //AliTPCLookUpTable3DInterpolatorD(Int_t nRRow, Double_t rMin, Double_t rMax, Int_t nPhiSlice, Double_t phiMin, Double_t phiMax, Int_t nZColumn , Double_t zMin, Double_t zMax ); - AliTPCLookUpTable3DInterpolatorD(Int_t nRRow, TMatrixD** matricesRValue, Double_t* rList, Int_t nPhiSlice, TMatrixD** matricesPhiValue, Double_t* phiList, Int_t nZColumn, TMatrixD** matricesZValue, Double_t* zList, Int_t order); - ~AliTPCLookUpTable3DInterpolatorD(); - - void SetNR(Int_t nRRow) { fNR = nRRow; } - void SetNPhi(Int_t nPhiSlice) { fNPhi = nPhiSlice; } - void SetNZ(Int_t nZColumn) { fNZ = nZColumn; } - Int_t GetNR() { return fNR; } - Int_t GetNPhi() { return fNPhi; } - Int_t GetNZ() { return fNZ; } - - void SetRList(Double_t* rList) { fRList = rList; } - void SetPhiList(Double_t* phiList) { fPhiList = phiList; } - void SetZList(Double_t* zList) { fZList = zList; } - void SetLookUpR(TMatrixD** matricesRValue) { fLookUpR = matricesRValue; } - void SetLookUpPhi(TMatrixD** matricesPhiValue) { fLookUpPhi = matricesPhiValue; } - void SetLookUpZ(TMatrixD** matricesZValue) { fLookUpZ = matricesZValue; } - void SetOrder(Int_t order); - void GetValue(Double_t r, Double_t phi, Double_t z, Double_t& rValue, Double_t& phiValue, Double_t& zValue) const; - void GetValue(Double_t r, Double_t phi, Double_t z, Float_t& rValue, Float_t& phiValue, Float_t& zValue) const; - void CopyFromMatricesToInterpolator(); - void CopyFromMatricesToInterpolator(Int_t iZ); // copy only iZ - - TMatrixD** GetLookUpR() { return fLookUpR; } - TMatrixD** GetLookUpPhi() { return fLookUpPhi; } - TMatrixD** GetLookUpZ() { return fLookUpZ; } - Double_t* GetRList() { return fRList; } - Double_t* GetPhiList() { return fPhiList; } - Double_t* GetZList() { return fZList; } - - AliTPC3DCylindricalInterpolator* GetInterpolatorR() { return fInterpolatorR; } - AliTPC3DCylindricalInterpolator* GetInterpolatorPhi() { return fInterpolatorPhi; } - AliTPC3DCylindricalInterpolator* GetInterpolatorZ() { return fInterpolatorZ; } - - private: - Int_t fOrder; ///< order of interpolation - Int_t fNR; ///< number of grid in R - Int_t fNPhi; ///< number of grid in Phi - Int_t fNZ; ///< number of grid in Z - - TMatrixD** fLookUpR = nullptr; //!<! Array to store distortion following the drift - TMatrixD** fLookUpPhi = nullptr; //!<! to store distortion following the drift - TMatrixD** fLookUpZ = nullptr; //!<! Array to store distortion following the drift - - AliTPC3DCylindricalInterpolator* fInterpolatorR = nullptr; //-> Interpolator for R component - AliTPC3DCylindricalInterpolator* fInterpolatorPhi = nullptr; //-> Interpolator for Phi component - AliTPC3DCylindricalInterpolator* fInterpolatorZ = nullptr; //-> Interpolator for Z component - - Double_t* fRList = nullptr; //!<! List of R coordinate (regular grid) - Double_t* fPhiList = nullptr; //!<! List of Phi coordinate (regular grid) - Double_t* fZList = nullptr; //!<! List of Z coordinate (regular grid) - - Bool_t fIsAllocatingLookUp; ///< flag for initialization of cubic spline - - /// \cond CLASSIMP - ClassDefNV(AliTPCLookUpTable3DInterpolatorD, 1); - /// \endcond -}; - -#endif diff --git a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.cxx b/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.cxx deleted file mode 100644 index b12c36566941a..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.cxx +++ /dev/null @@ -1,188 +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. - -/// \file AliTPCLookUpTable3DInterpolatorIrregularD.cxx -/// \brief Wrap up look-up table with irregular grid -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Mar 4, 2015 - -#include "AliTPCLookUpTable3DInterpolatorIrregularD.h" - -/// \cond CLASSIMP3 -ClassImp(AliTPCLookUpTable3DInterpolatorIrregularD); -/// \endcond - -/// constructor -AliTPCLookUpTable3DInterpolatorIrregularD::AliTPCLookUpTable3DInterpolatorIrregularD() -{ - fOrder = 1; - fIsAllocatingLookUp = kFALSE; -} - -/// constructor -/// -/// \param nRRow -/// \param matricesRValue -/// \param matricesRPoint -/// \param nPhiSlice -/// \param matricesPhiValue -/// \param matricesPhiPoint -/// \param nZColumn -/// \param matricesZValue -/// \param matricesZPoint -/// \param order -/// \param stepR -/// \param stepZ -/// \param stepPhi -/// \param type -AliTPCLookUpTable3DInterpolatorIrregularD::AliTPCLookUpTable3DInterpolatorIrregularD( - Int_t nRRow, TMatrixD** matricesRValue, TMatrixD** matricesRPoint, Int_t nPhiSlice, TMatrixD** matricesPhiValue, - TMatrixD** matricesPhiPoint, Int_t nZColumn, - TMatrixD** matricesZValue, TMatrixD** matricesZPoint, Int_t order, Int_t stepR, Int_t stepZ, Int_t stepPhi, - Int_t type) -{ - fIsAllocatingLookUp = kFALSE; - - SetNR(nRRow); - SetLookUpR(matricesRValue); - SetRList(matricesRPoint); - SetNPhi(nPhiSlice); - SetLookUpPhi(matricesPhiValue); - SetPhiList(matricesPhiPoint); - SetNZ(nZColumn); - SetLookUpZ(matricesZValue); - SetZList(matricesZPoint); - SetOrder(order); - - fInterpolatorR = new AliTPC3DCylindricalInterpolatorIrregular( - nRRow, nZColumn, nPhiSlice, stepR, stepZ, stepPhi, type); - fInterpolatorZ = new AliTPC3DCylindricalInterpolatorIrregular( - nRRow, nZColumn, nPhiSlice, stepR, stepZ, stepPhi, type); - fInterpolatorPhi = new AliTPC3DCylindricalInterpolatorIrregular( - nRRow, nZColumn, nPhiSlice, stepR, stepZ, stepPhi, type); - - fInterpolatorR->SetNR(nRRow); - fInterpolatorR->SetNZ(nZColumn); - fInterpolatorR->SetNPhi(nPhiSlice); - - fInterpolatorR->SetOrder(order); - fInterpolatorZ->SetNR(nRRow); - fInterpolatorZ->SetNZ(nZColumn); - fInterpolatorZ->SetNPhi(nPhiSlice); - fInterpolatorZ->SetOrder(order); - fInterpolatorPhi->SetNR(nRRow); - fInterpolatorPhi->SetNZ(nZColumn); - fInterpolatorPhi->SetNPhi(nPhiSlice); - fInterpolatorPhi->SetOrder(order); -} - -/// destructor -AliTPCLookUpTable3DInterpolatorIrregularD::~AliTPCLookUpTable3DInterpolatorIrregularD() -{ - delete fInterpolatorR; - delete fInterpolatorZ; - delete fInterpolatorPhi; -} - -/// copy from matrices to the interpolator -void AliTPCLookUpTable3DInterpolatorIrregularD::CopyFromMatricesToInterpolator() -{ - - fInterpolatorR->SetValue(fMatricesRValue, fMatricesRPoint, fMatricesPhiPoint, fMatricesZPoint); - fInterpolatorZ->SetValue(fMatricesZValue, fMatricesRPoint, fMatricesPhiPoint, fMatricesZPoint); - fInterpolatorPhi->SetValue(fMatricesPhiValue, fMatricesRPoint, fMatricesPhiPoint, fMatricesZPoint); -} - -/// -/// \param j -void AliTPCLookUpTable3DInterpolatorIrregularD::CopyFromMatricesToInterpolator(Int_t j) -{ - fInterpolatorR->SetValue(fMatricesRValue, fMatricesRPoint, fMatricesPhiPoint, fMatricesZPoint, j); - fInterpolatorZ->SetValue(fMatricesZValue, fMatricesRPoint, fMatricesPhiPoint, fMatricesZPoint, j); - fInterpolatorPhi->SetValue(fMatricesPhiValue, fMatricesRPoint, fMatricesPhiPoint, fMatricesZPoint, j); -} - -/// Get interpolation -/// \param r -/// \param phi -/// \param z -/// \param rValue -/// \param phiValue -/// \param zValue -/// \param rIndex -/// \param phiIndex -/// \param zIndex -/// \param stepR -/// \param stepPhi -/// \param stepZ -void AliTPCLookUpTable3DInterpolatorIrregularD::GetValue( - Double_t r, Double_t phi, Double_t z, Double_t& rValue, Double_t& phiValue, Double_t& zValue, - Int_t rIndex, Int_t phiIndex, Int_t zIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ) -{ - rValue = fInterpolatorR->GetValue(r, phi, z, rIndex, phiIndex, zIndex, stepR, stepPhi, stepZ); - phiValue = fInterpolatorPhi->GetValue(r, phi, z, rIndex, phiIndex, zIndex, stepR, stepPhi, stepZ); - zValue = fInterpolatorZ->GetValue(r, phi, z, rIndex, phiIndex, zIndex, stepR, stepPhi, stepZ); -} - -/// Interpolation for a point (r,phi,z) -/// -/// \param r -/// \param phi -/// \param z -/// \param rValue -/// \param phiValue -/// \param zValue -/// \param rIndex -/// \param phiIndex -/// \param zIndex -/// \param stepR -/// \param stepPhi -/// \param stepZ -/// \param minZColumnIndex -void AliTPCLookUpTable3DInterpolatorIrregularD::GetValue( - Double_t r, Double_t phi, Double_t z, Double_t& rValue, Double_t& phiValue, Double_t& zValue, Int_t rIndex, - Int_t phiIndex, Int_t zIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ, Int_t minZColumnIndex) -{ - rValue = fInterpolatorR->GetValue(r, phi, z, rIndex, phiIndex, zIndex, stepR, stepPhi, stepZ, minZColumnIndex); - phiValue = fInterpolatorPhi->GetValue(r, phi, z, rIndex, phiIndex, zIndex, stepR, stepPhi, stepZ, minZColumnIndex); - zValue = fInterpolatorZ->GetValue(r, phi, z, rIndex, phiIndex, zIndex, stepR, stepPhi, stepZ, minZColumnIndex); -} - -/// Get interpolation -/// \param r -/// \param phi -/// \param z -/// \param rValue -/// \param phiValue -/// \param zValue -/// \param rIndex -/// \param phiIndex -/// \param zIndex -/// \param startR -/// \param startPhi -/// \param startZ -void AliTPCLookUpTable3DInterpolatorIrregularD::GetValue( - Double_t r, Double_t phi, Double_t z, Float_t& rValue, Float_t& phiValue, Float_t& zValue, Int_t rIndex, - Int_t phiIndex, Int_t zIndex, Int_t startR, Int_t startPhi, Int_t startZ) -{ - rValue = fInterpolatorR->GetValue(r, phi, z, rIndex, phiIndex, zIndex, startR, startPhi, startZ); - phiValue = fInterpolatorPhi->GetValue(r, phi, z, rIndex, phiIndex, zIndex, startR, startPhi, startZ); - zValue = fInterpolatorZ->GetValue(r, phi, z, rIndex, phiIndex, zIndex, startR, startPhi, startZ); -} - -// using kdtree -void AliTPCLookUpTable3DInterpolatorIrregularD::GetValue( - Double_t r, Double_t phi, Double_t z, Double_t& rValue, Double_t& phiValue, Double_t& zValue) -{ - rValue = fInterpolatorR->GetValue(r, phi, z); - phiValue = fInterpolatorPhi->GetValue(r, phi, z); - zValue = fInterpolatorZ->GetValue(r, phi, z); -} diff --git a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.h b/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.h deleted file mode 100644 index f7466360f3f85..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCLookUpTable3DInterpolatorIrregularD.h +++ /dev/null @@ -1,102 +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. - -/// \file AliTPCLookUpTable3DInterpolatorIrregularD.h -/// \brief Wrap up look-up table with irregular grid -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Mar 4, 2015 - -#ifndef AliTPCLookUpTable3DInterpolatorIrregularD_H -#define AliTPCLookUpTable3DInterpolatorIrregularD_H - -#include "TMatrixD.h" -#include "AliTPC3DCylindricalInterpolatorIrregular.h" - -class AliTPCLookUpTable3DInterpolatorIrregularD -{ - public: - void SetNR(Int_t nRRow) { fNR = nRRow; } - void SetNPhi(Int_t nPhiSlice) { fNPhi = nPhiSlice; } - void SetNZ(Int_t nZColumn) { fNZ = nZColumn; } - - Int_t GetNR() { return fNR; } - Int_t GetNPhi() { return fNPhi; } - Int_t GetNZ() { return fNZ; } - - void SetRList(TMatrixD** matricesRPoint) { fMatricesRPoint = matricesRPoint; } - void SetPhiList(TMatrixD** matricesPhiPoint) { fMatricesPhiPoint = matricesPhiPoint; } - void SetZList(TMatrixD** matricesZPoint) { fMatricesZPoint = matricesZPoint; } - - void SetLookUpR(TMatrixD** matricesRValue) { fMatricesRValue = matricesRValue; } - void SetLookUpPhi(TMatrixD** matricesPhiValue) { fMatricesPhiValue = matricesPhiValue; } - void SetLookUpZ(TMatrixD** matricesZValue) { fMatricesZValue = matricesZValue; } - - AliTPCLookUpTable3DInterpolatorIrregularD(); - AliTPCLookUpTable3DInterpolatorIrregularD(Int_t nRRow, TMatrixD** matricesRValue, TMatrixD** r, Int_t nPhiSlice, - TMatrixD** matricesPhiValue, TMatrixD** matricesPhiPoint, Int_t nZColumn, - TMatrixD** matricesZValue, TMatrixD** matricesZPoint, Int_t order, - Int_t stepR, Int_t stepZ, Int_t stepPhi, Int_t type); - - ~AliTPCLookUpTable3DInterpolatorIrregularD(); - - void GetValue(Double_t r, Double_t phi, Double_t z, Double_t& rValue, Double_t& phiValue, Double_t& zValue, Int_t rIndex, - Int_t phiIndex, Int_t zIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ); - void GetValue(Double_t r, Double_t phi, Double_t z, Double_t& rValue, Double_t& phiValue, Double_t& zValue, Int_t rIndex, - Int_t phiIndex, Int_t zIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ, Int_t minZColumnIndex); - void GetValue(Double_t r, Double_t phi, Double_t z, Float_t& rValue, Float_t& phiValue, Float_t& zValue, Int_t rIndex, Int_t phiIndex, - Int_t zIndex, Int_t stepR, Int_t stepPhi, Int_t stepZ); - void GetValue(Double_t r, Double_t phi, Double_t z, Double_t& rValue, Double_t& phiValue, Double_t& zValue); - void SetOrder(Int_t order) { fOrder = order; } - void CopyFromMatricesToInterpolator(); - void CopyFromMatricesToInterpolator(Int_t j); - - Int_t GetIrregularGridSize() { return fInterpolatorR->GetIrregularGridSize(); } - void SetIrregularGridSize(Int_t size) - { - fInterpolatorR->SetIrregularGridSize(size); - fInterpolatorPhi->SetIrregularGridSize(size); - fInterpolatorZ->SetIrregularGridSize(size); - } - void SetKernelType(Int_t kernelType) - { - fInterpolatorR->SetKernelType(kernelType); - fInterpolatorPhi->SetKernelType(kernelType); - fInterpolatorZ->SetKernelType(kernelType); - } - Int_t GetKernelType() { return fInterpolatorR->GetKernelType(); } - - private: - Int_t fOrder; ///< Order of interpolation - Int_t fIrregularGridSize; ///< Size of irregular interpolation neighborhood - Int_t fNR; ///< Number of grid in R - Int_t fNPhi; ///< Number of grid in Phi - Int_t fNZ; ///< Number of grid in Z - - TMatrixD** fMatricesRValue = nullptr; //!<! Matrices to store r-component - TMatrixD** fMatricesPhiValue = nullptr; //!<! Matrices to store phi-component - TMatrixD** fMatricesZValue = nullptr; //!<! Matrices to store z-component - - AliTPC3DCylindricalInterpolatorIrregular* fInterpolatorR = nullptr; //-> Irregular interpolator for R-component - AliTPC3DCylindricalInterpolatorIrregular* fInterpolatorPhi = nullptr; //-> Irregular interpolator for Phi-component - AliTPC3DCylindricalInterpolatorIrregular* fInterpolatorZ = nullptr; //-> Irregular interpolator for Z-component - - TMatrixD** fMatricesRPoint = nullptr; //!<! Matrices to store distorted point (r component) - TMatrixD** fMatricesPhiPoint = nullptr; //!<! Matrices to store distorted point (phi component) - TMatrixD** fMatricesZPoint = nullptr; //!<! Matrices to store distorted point (z component) - - Bool_t fIsAllocatingLookUp; - - /// \cond CLASSIMP - ClassDefNV(AliTPCLookUpTable3DInterpolatorIrregularD, 1); - /// \endcond -}; - -#endif diff --git a/GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.cxx b/GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.cxx deleted file mode 100644 index bf789cedfcb68..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.cxx +++ /dev/null @@ -1,3031 +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. - -/// \file AliTPCPoissonSolver.cxx -/// \brief This class provides implementation of Poisson Eq -/// solver by MultiGrid Method -/// -/// -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Nov 20, 2017 - -#include <TMath.h> -#include "AliTPCPoissonSolver.h" - -/// \cond CLASSIMP -ClassImp(AliTPCPoissonSolver); -/// \endcond - -const Double_t AliTPCPoissonSolver::fgkTPCZ0 = 249.7; ///< nominal gating grid position -const Double_t AliTPCPoissonSolver::fgkIFCRadius = 83.5; ///< radius which renders the "18 rod manifold" best -> compare calc. of Jim Thomas -const Double_t AliTPCPoissonSolver::fgkOFCRadius = 254.5; ///< Mean Radius of the Outer Field Cage (252.55 min, 256.45 max) (cm) -const Double_t AliTPCPoissonSolver::fgkZOffSet = 0.2; ///< Offset from CE: calculate all distortions closer to CE as if at this point -const Double_t AliTPCPoissonSolver::fgkCathodeV = -100000.0; ///< Cathode Voltage (volts) -const Double_t AliTPCPoissonSolver::fgkGG = -70.0; ///< Gating Grid voltage (volts) -const Double_t AliTPCPoissonSolver::fgkdvdE = 0.0024; ///< [cm/V] drift velocity dependency on the E field (from Magboltz for NeCO2N2 at standard environment) -const Double_t AliTPCPoissonSolver::fgkEM = -1.602176487e-19 / 9.10938215e-31; ///< charge/mass in [C/kg] -const Double_t AliTPCPoissonSolver::fgke0 = 8.854187817e-12; ///< vacuum permittivity [A·s/(V·m)] - -Double_t AliTPCPoissonSolver::fgExactErr = 1e-4; -Double_t AliTPCPoissonSolver::fgConvergenceError = 1e-3; - -/// constructor -/// -AliTPCPoissonSolver::AliTPCPoissonSolver() - : TNamed("poisson solver", "solver"), - fErrorConvergenceNorm2{new TVectorD(fMgParameters.nMGCycle)}, - fErrorConvergenceNormInf{new TVectorD(fMgParameters.nMGCycle)}, - fError{new TVectorD(fMgParameters.nMGCycle)} - -{ - // default strategy -} - -/// Constructor -/// \param name name of the object -/// \param title title of the object -AliTPCPoissonSolver::AliTPCPoissonSolver(const char* name, const char* title) - : TNamed(name, title), - fErrorConvergenceNorm2{new TVectorD(fMgParameters.nMGCycle)}, - fErrorConvergenceNormInf{new TVectorD(fMgParameters.nMGCycle)}, - fError{new TVectorD(fMgParameters.nMGCycle)} -{ - /// constructor -} - -/// destructor -AliTPCPoissonSolver::~AliTPCPoissonSolver() -{ - /// virtual destructor - delete[] fExactSolution; - delete fErrorConvergenceNorm2; - delete fErrorConvergenceNormInf; - delete fError; -} - -/// Provides poisson solver in 2D -/// -/// Based on the strategy (relaxation, multi grid or FFT) -/// -/// \param matrixV TMatrixD& potential in matrix -/// \param matrixCharge TMatrixD& charge density in matrix (side effect -/// \param nRRow Int_t number of nRRow in the grid -/// \param nZColumn Int_t number of nZColumn in the grid -/// \param maxIteration Int_t maximum iteration for relaxation method -/// -/// \return A fixed number that has nothing to do with what the function does -void AliTPCPoissonSolver::PoissonSolver2D(TMatrixD& matrixV, TMatrixD& matrixCharge, Int_t nRRow, Int_t nZColumn, - Int_t maxIteration) -{ - switch (fStrategy) { - case kMultiGrid: - PoissonMultiGrid2D(matrixV, matrixCharge, nRRow, nZColumn); - break; - default: - PoissonRelaxation2D(matrixV, matrixCharge, nRRow, nZColumn, maxIteration); - } -} - -/// Provides poisson solver in Cylindrical 3D (TPC geometry) -/// -/// Strategy based on parameter settings (fStrategy and fMgParameters)provided -/// * Cascaded multi grid with S.O.R -/// * Geometric MultiGrid -/// * Cycles: V, W, Full -/// * Relaxation: Jacobi, Weighted-Jacobi, Gauss-Seidel -/// * Grid transfer operators: Full, Half -/// * Spectral Methods (TODO) -/// -/// \param matricesV TMatrixD** potential in 3D matrix -/// \param matricesCharge TMatrixD** charge density in 3D matrix (side effect) -/// \param nRRow Int_t number of nRRow in the r direction of TPC -/// \param nZColumn Int_t number of nZColumn in z direction of TPC -/// \param phiSlice Int_t number of phiSlice in phi direction of T{C -/// \param maxIteration Int_t maximum iteration for relaxation method -/// \param symmetry Int_t symmetry or not -/// -/// \pre Charge density distribution in **matricesCharge** is known and boundary values for **matricesV** are set -/// \post Numerical solution for potential distribution is calculated and stored in each rod at **matricesV** -void AliTPCPoissonSolver::PoissonSolver3D(TMatrixD** matricesV, TMatrixD** matricesCharge, - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, - Int_t symmetry) -{ - switch (fStrategy) { - case kMultiGrid: - if (fMgParameters.isFull3D) { - PoissonMultiGrid3D(matricesV, matricesCharge, nRRow, nZColumn, phiSlice, symmetry); - } else { - PoissonMultiGrid3D2D(matricesV, matricesCharge, nRRow, nZColumn, phiSlice, symmetry); - } - break; - default: - PoissonRelaxation3D(matricesV, matricesCharge, nRRow, nZColumn, phiSlice, maxIteration, symmetry); - } -} - -/// Solve Poisson's Equation by Relaxation Technique in 2D (assuming cylindrical symmetry) -/// -/// Solve Poisson's equation in a cylindrical coordinate system. The matrixV matrix must be filled with the -/// boundary conditions on the first and last nRRow, and the first and last nZColumn. The remainder of the -/// array can be blank or contain a preliminary guess at the solution. The Charge density matrix contains -/// the enclosed spacecharge density at each point. The charge density matrix can be full of zero's if -/// you wish to solve Laplace equation however it should not contain random numbers or you will get -/// random numbers back as a solution. -/// Poisson's equation is solved by iteratively relaxing the matrix to the final solution. In order to -/// speed up the convergence to the best solution, this algorithm does a binary expansion of the solution -/// space. First it solves the problem on a very sparse grid by skipping nRRow and nZColumn in the original -/// matrix. Then it doubles the number of points and solves the problem again. Then it doubles the -/// number of points and solves the problem again. This happens several times until the maximum number -/// of points has been included in the array. -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// So nRRow == 2**M + 1 and nZColumn == 2**N + 1. The number of nRRow and nZColumn can be different. -/// -/// Method for relaxation: S.O.R Weighted Jacobi -/// -/// \param matrixV TMatrixD& potential in matrix -/// \param matrixCharge TMatrixD& charge density in matrix (side effect -/// \param nRRow Int_t number of nRRow in the grid -/// \param nZColumn Int_t number of nZColumn in the grid -/// \param maxIteration Int_t maximum iteration for relaxation method -/// -/// \return A fixed number that has nothing to do with what the function does -/// -/// -/// Original code by Jim Thomas (STAR TPC Collaboration) -void AliTPCPoissonSolver::PoissonRelaxation2D(TMatrixD& matrixV, TMatrixD& matrixCharge, Int_t nRRow, Int_t nZColumn, - Int_t maxIteration) -{ - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t ratio = gridSizeR * gridSizeR / (gridSizeZ * gridSizeZ); - - TMatrixD arrayEr(nRRow, nZColumn); - TMatrixD arrayEz(nRRow, nZColumn); - - //Check that number of nRRow and nZColumn is suitable for a binary expansion - - if (!IsPowerOfTwo(nRRow - 1)) { - Error("PoissonRelaxation2D", "PoissonRelaxation - Error in the number of nRRow. Must be 2**M - 1"); - return; - } - - if (!IsPowerOfTwo(nZColumn - 1)) { - Error("PoissonRelaxation2D", "PoissonRelaxation - Error in the number of nZColumn. Must be 2**N - 1"); - return; - } - - // Solve Poisson's equation in cylindrical coordinates by relaxation technique - // Allow for different size grid spacing in R and Z directions - // Use a binary expansion of the size of the matrix to speed up the solution of the problem - - Int_t iOne = (nRRow - 1) / 4; - Int_t jOne = (nZColumn - 1) / 4; - - // Coarse until nLoop - Int_t nLoop = 1 + (int)(0.5 + TMath::Log2((double)TMath::Max(iOne, jOne))); - - // Loop while the matrix expands & the resolution increases. - for (Int_t count = 0; count < nLoop; count++) { - - Float_t tempGridSizeR = gridSizeR * iOne; - Float_t tempRatio = ratio * iOne * iOne / (jOne * jOne); - Float_t tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); - - // Do this the standard C++ way to avoid gcc extensions for Float_t coefficient1[nRRow] - std::vector<float> coefficient1(nRRow); - std::vector<float> coefficient2(nRRow); - - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - Float_t radius = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - coefficient1[i] = 1.0 + tempGridSizeR / (2 * radius); - coefficient2[i] = 1.0 - tempGridSizeR / (2 * radius); - } - - TMatrixD sumChargeDensity(nRRow, nZColumn); - - // average charge at the coarse point - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - Float_t radius = AliTPCPoissonSolver::fgkIFCRadius + iOne * gridSizeR; - for (Int_t j = jOne; j < nZColumn - 1; j += jOne) { - if (iOne == 1 && jOne == 1) { - sumChargeDensity(i, j) = matrixCharge(i, j); - } else { - // Add up all enclosed charge density contributions within 1/2 unit in all directions - Float_t weight = 0.0; - Float_t sum = 0.0; - sumChargeDensity(i, j) = 0.0; - for (Int_t ii = i - iOne / 2; ii <= i + iOne / 2; ii++) { - for (Int_t jj = j - jOne / 2; jj <= j + jOne / 2; jj++) { - if (ii == i - iOne / 2 || ii == i + iOne / 2 || jj == j - jOne / 2 || jj == j + jOne / 2) { - weight = 0.5; - } else { - weight = 1.0; - } - sumChargeDensity(i, j) += matrixCharge(ii, jj) * weight * radius; - sum += weight * radius; - } - } - sumChargeDensity(i, j) /= sum; - } - sumChargeDensity(i, j) *= tempGridSizeR * tempGridSizeR; // just saving a step later on - } - } - - // Iterate on the current level - for (Int_t k = 1; k <= maxIteration; k++) { - // Solve Poisson's Equation - // Over-relaxation index, must be >= 1 but < 2. Arrange for it to evolve from 2 => 1 - // as iteration increase. - Float_t overRelax = 1.0 + TMath::Sqrt(TMath::Cos((k * TMath::PiOver2()) / maxIteration)); - Float_t overRelaxM1 = overRelax - 1.0; - Float_t overRelaxTemp4, overRelaxCoefficient5; - overRelaxTemp4 = overRelax * tempFourth; - overRelaxCoefficient5 = overRelaxM1 / overRelaxTemp4; - - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - for (Int_t j = jOne; j < nZColumn - 1; j += jOne) { - // S.O.R - // - matrixV(i, j) = (coefficient2[i] * matrixV(i - iOne, j) + tempRatio * (matrixV(i, j - jOne) + matrixV(i, j + jOne)) - overRelaxCoefficient5 * matrixV(i, j) + coefficient1[i] * matrixV(i + iOne, j) + sumChargeDensity(i, j)) * overRelaxTemp4; - } - } - - // if already at maxIteration - // TODO: stop when it converged - if (k == maxIteration) { - - // After full solution is achieved, copy low resolution solution into higher res array - // Interpolate solution - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - for (Int_t j = jOne; j < nZColumn - 1; j += jOne) { - if (iOne > 1) { - matrixV(i + iOne / 2, j) = (matrixV(i + iOne, j) + matrixV(i, j)) / 2; - if (i == iOne) { - matrixV(i - iOne / 2, j) = (matrixV(0, j) + matrixV(iOne, j)) / 2; - } - } - if (jOne > 1) { - matrixV(i, j + jOne / 2) = (matrixV(i, j + jOne) + matrixV(i, j)) / 2; - if (j == jOne) { - matrixV(i, j - jOne / 2) = (matrixV(i, 0) + matrixV(i, jOne)) / 2; - } - } - if (iOne > 1 && jOne > 1) { - matrixV(i + iOne / 2, j + jOne / 2) = (matrixV(i + iOne, j + jOne) + matrixV(i, j)) / 2; - if (i == iOne) { - matrixV(i - iOne / 2, j - jOne / 2) = (matrixV(0, j - jOne) + matrixV(iOne, j)) / 2; - } - if (j == jOne) { - matrixV(i - iOne / 2, j - jOne / 2) = (matrixV(i - iOne, 0) + matrixV(i, jOne)) / 2; - } - // Note that this leaves a point at the upper left and lower right corners uninitialized. - // -> Not a big deal. - } - } - } - } - } - - iOne = iOne / 2; - if (iOne < 1) { - iOne = 1; - } - jOne = jOne / 2; - if (jOne < 1) { - jOne = 1; - } - sumChargeDensity.Clear(); - } -} - -/// Solve Poisson's Equation by MultiGrid Technique in 2D (assuming cylindrical symmetry) -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// So nRRow == 2**M + 1 and nZColumn == 2**N + 1. The number of nRRow and nZColumn can be different. -/// -/// \param matrixV TMatrixD& potential in matrix -/// \param matrixCharge TMatrixD& charge density in matrix (side effect -/// \param nRRow Int_t number of nRRow -/// \param nZColumn Int_t number of nZColumn -/// \param maxIteration Int_t maximum iteration for relaxation method -/// -/// \return A fixed number that has nothing to do with what the function does -void AliTPCPoissonSolver::PoissonMultiGrid2D(TMatrixD& matrixV, TMatrixD& matrixCharge, Int_t nRRow, Int_t nZColumn) -{ - /// Geometry of TPC -- should be use AliTPCParams instead - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t ratio = gridSizeR * gridSizeR / (gridSizeZ * gridSizeZ); - - Int_t nGridRow = 0; // number grid - Int_t nGridCol = 0; // number grid - Int_t nnRow; - Int_t nnCol; - - nnRow = nRRow; - while (nnRow >>= 1) { - nGridRow++; - } - - nnCol = nZColumn; - while (nnCol >>= 1) { - nGridCol++; - } - - //Check that number of nRRow and nZColumn is suitable for multi grid - if (!IsPowerOfTwo(nRRow - 1)) { - Error("PoissonMultiGrid2D", "PoissonMultiGrid - Error in the number of nRRow. Must be 2**M - 1"); - return; - } - if (!IsPowerOfTwo(nZColumn - 1)) { - Error("PoissonMultiGrid2D", "PoissonMultiGrid - Error in the number of nZColumn. Must be 2**N - 1"); - return; - } - - Int_t nLoop = TMath::Max(nGridRow, nGridCol); // Calculate the number of nLoop for the binary expansion - - Info("PoissonMultiGrid2D", "%s", Form("nGridRow=%d, nGridCol=%d, nLoop=%d, nMGCycle=%d", nGridRow, nGridCol, nLoop, fMgParameters.nMGCycle)); - - Float_t h, h2, radius; - Int_t iOne = 1; // in/dex - Int_t jOne = 1; // index - Int_t tnRRow = nRRow, tnZColumn = nZColumn; - Int_t count; - Float_t tempRatio, tempFourth; - - // Vector for storing multi grid array - std::vector<TMatrixD*> tvChargeFMG(nLoop); - std::vector<TMatrixD*> tvArrayV(nLoop); - std::vector<TMatrixD*> tvCharge(nLoop); - std::vector<TMatrixD*> tvResidue(nLoop); - - // Allocate memory for temporary grid - for (count = 1; count <= nLoop; count++) { - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - // if one just address to matrixV - tvResidue[count - 1] = new TMatrixD(tnRRow, tnZColumn); - if (count == 1) { - tvChargeFMG[count - 1] = &matrixCharge; - tvArrayV[count - 1] = &matrixV; - tvCharge[count - 1] = &matrixCharge; - } else { - tvArrayV[count - 1] = new TMatrixD(tnRRow, tnZColumn); - tvCharge[count - 1] = new TMatrixD(tnRRow, tnZColumn); - tvChargeFMG[count - 1] = new TMatrixD(tnRRow, tnZColumn); - Restrict2D(*tvChargeFMG[count - 1], *tvChargeFMG[count - 2], tnRRow, tnZColumn); - } - iOne = 2 * iOne; - jOne = 2 * jOne; - } - - /// full multi grid - if (fMgParameters.cycleType == kFCycle) { - - Info("PoissonMultiGrid2D", "Do full cycle"); - // FMG - // 1) Relax on the coarsest grid - iOne = iOne / 2; - jOne = jOne / 2; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - h = gridSizeR * count; - h2 = h * h; - tempRatio = ratio * iOne * iOne / (jOne * jOne); - tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); - - std::vector<float> coefficient1(tnRRow); - std::vector<float> coefficient2(tnRRow); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - } - - Relax2D(*tvArrayV[nLoop - 1], *tvChargeFMG[nLoop - 1], tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, - coefficient2); - - // Do VCycle from nLoop H to h - for (count = nLoop - 2; count >= 0; count--) { - - iOne = iOne / 2; - jOne = jOne / 2; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - Interp2D(*tvArrayV[count], *tvArrayV[count + 1], tnRRow, tnZColumn); - // Copy the relax charge to the tvCharge - *tvCharge[count] = *tvChargeFMG[count]; //copy - //tvCharge[count]->Print(); - // Do V cycle - - for (Int_t mgCycle = 0; mgCycle < fMgParameters.nMGCycle; mgCycle++) { - - VCycle2D(nRRow, nZColumn, count + 1, nLoop, fMgParameters.nPre, fMgParameters.nPost, gridSizeR, ratio, tvArrayV, - tvCharge, tvResidue); - } - } - } else if (fMgParameters.cycleType == kVCycle) { - // 2. VCycle - Info("PoissonMultiGrid2D", "Do V cycle"); - - Int_t gridFrom = 1; - Int_t gridTo = nLoop; - - // Do MGCycle - for (Int_t mgCycle = 0; mgCycle < fMgParameters.nMGCycle; mgCycle++) { - VCycle2D(nRRow, nZColumn, gridFrom, gridTo, fMgParameters.nPre, fMgParameters.nPost, gridSizeR, ratio, tvArrayV, - tvCharge, tvResidue); - } - } else if (fMgParameters.cycleType == kWCycle) { - - // 3. W Cycle (TODO:) - - Int_t gridFrom = 1; - - //nLoop = nLoop >= 4 ? 4 : nLoop; - - Int_t gridTo = nLoop; - //Int_t gamma = 1; - - // Do MGCycle - for (Int_t mgCycle = 0; mgCycle < fMgParameters.nMGCycle; mgCycle++) { - WCycle2D(nRRow, nZColumn, gridFrom, gridTo, fMgParameters.gamma, fMgParameters.nPre, fMgParameters.nPost, - gridSizeR, ratio, tvArrayV, tvCharge, tvResidue); - } - } - - // Deallocate memory - for (count = nLoop; count >= 1; count--) { - // if one just address to matrixV - if (count > 1) { - delete tvArrayV[count - 1]; - delete tvCharge[count - 1]; - delete tvChargeFMG[count - 1]; - } - delete tvResidue[count - 1]; - } -} - -/// 3D - Solve Poisson's Equation in 3D by Relaxation Technique -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// The number of nRRow and Z Column can be different. -/// -/// R Row == 2**M + 1 -/// Z Column == 2**N + 1 -/// Phi Slice == Arbitrary but greater than 3 -/// -/// DeltaPhi in Radians -/// -/// SYMMETRY = 0 if no phi symmetries, and no phi boundary conditions -/// = 1 if we have reflection symmetry at the boundaries (eg. sector symmetry or half sector symmetries). -/// -/// \param matricesV TMatrixD** potential in 3D matrix -/// \param matricesCharge TMatrixD** charge density in 3D matrix (side effect) -/// \param nRRow Int_t number of nRRow in the r direction of TPC -/// \param nZColumn Int_t number of nZColumn in z direction of TPC -/// \param phiSlice Int_t number of phiSlice in phi direction of T{C -/// \param maxIteration Int_t maximum iteration for relaxation method -/// \param symmetry Int_t symmetry or not -/// -void AliTPCPoissonSolver::PoissonRelaxation3D(TMatrixD** matricesV, TMatrixD** matricesCharge, - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, - Int_t symmetry) -{ - - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t ratioPhi = gridSizeR * gridSizeR / (gridSizePhi * gridSizePhi); - const Float_t ratioZ = gridSizeR * gridSizeR / (gridSizeZ * gridSizeZ); - - Info("PoissonRelaxation3D", "%s", Form("in Poisson Solver 3D relaxation nRRow=%d, cols=%d, phiSlice=%d \n", nRRow, nZColumn, phiSlice)); - // Check that the number of nRRow and nZColumn is suitable for a binary expansion - if (!IsPowerOfTwo((nRRow - 1))) { - Error("PoissonRelaxation3D", "Poisson3DRelaxation - Error in the number of nRRow. Must be 2**M - 1"); - return; - } - if (!IsPowerOfTwo((nZColumn - 1))) { - Error("PoissonRelaxation3D", "Poisson3DRelaxation - Error in the number of nZColumn. Must be 2**N - 1"); - return; - } - if (phiSlice <= 3) { - Error("PoissonRelaxation3D", "Poisson3DRelaxation - Error in the number of phiSlice. Must be larger than 3"); - return; - } - if (phiSlice > 1000) { - Error("PoissonRelaxation3D", "Poisson3D phiSlice > 1000 is not allowed (nor wise) "); - return; - } - - // Solve Poisson's equation in cylindrical coordinates by relaxation technique - // Allow for different size grid spacing in R and Z directions - // Use a binary expansion of the matrix to speed up the solution of the problem - - Int_t nLoop, mPlus, mMinus, signPlus, signMinus; - Int_t iOne = (nRRow - 1) / 4; - Int_t jOne = (nZColumn - 1) / 4; - nLoop = TMath::Max(iOne, jOne); // Calculate the number of nLoop for the binary expansion - nLoop = 1 + (int)(0.5 + TMath::Log2((double)nLoop)); // Solve for N in 2**N - - TMatrixD* matricesSumChargeDensity[1000]; // Create temporary arrays to store low resolution charge arrays - - std::vector<float> coefficient1( - nRRow); // Do this the standard C++ way to avoid gcc extensions for Float_t coefficient1[nRRow] - std::vector<float> coefficient2( - nRRow); // Do this the standard C++ way to avoid gcc extensions for Float_t coefficient1[nRRow] - std::vector<float> coefficient3( - nRRow); // Do this the standard C++ way to avoid gcc extensions for Float_t coefficient1[nRRow] - std::vector<float> coefficient4( - nRRow); // Do this the standard C++ way to avoid gcc extensions for Float_t coefficient1[nRRow] - std::vector<float> overRelaxCoefficient4(nRRow); // Do this the standard C++ way to avoid gcc extensions - std::vector<float> overRelaxCoefficient5(nRRow); // Do this the standard C++ way to avoid gcc extensions - for (Int_t i = 0; i < phiSlice; i++) { - matricesSumChargeDensity[i] = new TMatrixD(nRRow, nZColumn); - } - - ///// Test of Convergence - TMatrixD* prevArrayV[phiSlice]; - - for (Int_t m = 0; m < phiSlice; m++) { - prevArrayV[m] = new TMatrixD(nRRow, nZColumn); - } - ///// - - // START the master loop and do the binary expansion - for (Int_t count = 0; count < nLoop; count++) { - Float_t tempGridSizeR = gridSizeR * iOne; - Float_t tempRatioPhi = ratioPhi * iOne * iOne; - Float_t tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - Float_t radius = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - coefficient1[i] = 1.0 + tempGridSizeR / (2 * radius); - coefficient2[i] = 1.0 - tempGridSizeR / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - - for (Int_t m = 0; m < phiSlice; m++) { - TMatrixD& matrixCharge = *matricesCharge[m]; - TMatrixD& sumChargeDensity = *matricesSumChargeDensity[m]; - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - Float_t radius = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - for (Int_t j = jOne; j < nZColumn - 1; j += jOne) { - if (iOne == 1 && jOne == 1) { - sumChargeDensity(i, j) = matrixCharge(i, j); - } else { // Add up all enclosed charge density contributions within 1/2 unit in all directions - Float_t weight = 0.0; - Float_t sum = 0.0; - sumChargeDensity(i, j) = 0.0; - for (Int_t ii = i - iOne / 2; ii <= i + iOne / 2; ii++) { - for (Int_t jj = j - jOne / 2; jj <= j + jOne / 2; jj++) { - if (ii == i - iOne / 2 || ii == i + iOne / 2 || jj == j - jOne / 2 || jj == j + jOne / 2) { - weight = 0.5; - } else { - weight = 1.0; - } - sumChargeDensity(i, j) += matrixCharge(ii, jj) * weight * radius; - sum += weight * radius; - } - } - sumChargeDensity(i, j) /= sum; - } - sumChargeDensity(i, j) *= tempGridSizeR * tempGridSizeR; // just saving a step later on - } - } - } - - for (Int_t k = 1; k <= maxIteration; k++) { - if (count == nLoop - 1) { - //// Test of Convergence - for (Int_t m = 0; m < phiSlice; m++) { - (*prevArrayV[m]) = (*matricesV[m]); - } - //// - } - - Float_t overRelax = 1.0 + TMath::Sqrt(TMath::Cos((k * TMath::PiOver2()) / maxIteration)); - Float_t overRelaxM1 = overRelax - 1.0; - - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - overRelaxCoefficient4[i] = overRelax * coefficient4[i]; - overRelaxCoefficient5[i] = overRelaxM1 / overRelaxCoefficient4[i]; - } - - for (Int_t m = 0; m < phiSlice; m++) { - mPlus = m + 1; - signPlus = 1; - mMinus = m - 1; - signMinus = 1; - if (symmetry == 1) { // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - } - if (mMinus < 0) { - mMinus = 1; - } - } else if (symmetry == -1) { // Anti-symmetry in phi - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - signPlus = -1; - } - if (mMinus < 0) { - mMinus = 1; - signMinus = -1; - } - } else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi - if (mPlus > phiSlice - 1) { - mPlus = m + 1 - phiSlice; - } - if (mMinus < 0) { - mMinus = m - 1 + phiSlice; - } - } - - TMatrixD& matrixV = *matricesV[m]; - TMatrixD& matrixVP = *matricesV[mPlus]; - TMatrixD& matrixVM = *matricesV[mMinus]; - TMatrixD& sumChargeDensity = *matricesSumChargeDensity[m]; - Double_t* matrixVFast = matrixV.GetMatrixArray(); - Double_t* matrixVPFast = matrixVP.GetMatrixArray(); - Double_t* matrixVMFast = matrixVM.GetMatrixArray(); - Double_t* sumChargeDensityFast = sumChargeDensity.GetMatrixArray(); - - if (fStrategy == kRelaxation) { - // slow implementation - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - for (Int_t j = jOne; j < nZColumn - 1; j += jOne) { - - matrixV(i, j) = (coefficient2[i] * matrixV(i - iOne, j) + tempRatioZ * (matrixV(i, j - jOne) + matrixV(i, j + jOne)) - overRelaxCoefficient5[i] * matrixV(i, j) + coefficient1[i] * matrixV(i + iOne, j) + coefficient3[i] * (signPlus * matrixVP(i, j) + signMinus * matrixVM(i, j)) + sumChargeDensity(i, j)) * overRelaxCoefficient4[i]; - // Note: over-relax the solution at each step. This speeds up the convergence. - } - } - } else { - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - Double_t* matrixVFastI = &(matrixVFast[i * nZColumn]); - Double_t* matrixVPFastI = &(matrixVPFast[i * nZColumn]); - Double_t* matrixVMFastI = &(matrixVMFast[i * nZColumn]); - Double_t* sumChargeDensityFastI = &(sumChargeDensityFast[i * nZColumn]); - - for (Int_t j = jOne; j < nZColumn - 1; j += jOne) { - Double_t /*resSlow*/ resFast; - - resFast = (coefficient2[i] * matrixVFastI[j - nZColumn * iOne] + tempRatioZ * (matrixVFastI[j - jOne] + matrixVFastI[j + jOne]) - overRelaxCoefficient5[i] * matrixVFastI[j] + coefficient1[i] * matrixVFastI[j + nZColumn * iOne] + coefficient3[i] * (signPlus * matrixVPFastI[j] + signMinus * matrixVMFastI[j]) + sumChargeDensityFastI[j]) * overRelaxCoefficient4[i]; - matrixVFastI[j] = resFast; - // Note: over-relax the solution at each step. This speeds up the convergence. - } // end j - } //end i - } // end phi - - // After full solution is achieved, copy low resolution solution into higher res array - if (k == maxIteration) { - for (Int_t i = iOne; i < nRRow - 1; i += iOne) { - for (Int_t j = jOne; j < nZColumn - 1; j += jOne) { - - if (iOne > 1) { - matrixV(i + iOne / 2, j) = (matrixV(i + iOne, j) + matrixV(i, j)) / 2; - if (i == iOne) { - matrixV(i - iOne / 2, j) = (matrixV(0, j) + matrixV(iOne, j)) / 2; - } - } - if (jOne > 1) { - matrixV(i, j + jOne / 2) = (matrixV(i, j + jOne) + matrixV(i, j)) / 2; - if (j == jOne) { - matrixV(i, j - jOne / 2) = (matrixV(i, 0) + matrixV(i, jOne)) / 2; - } - } - if (iOne > 1 && jOne > 1) { - matrixV(i + iOne / 2, j + jOne / 2) = (matrixV(i + iOne, j + jOne) + matrixV(i, j)) / 2; - if (i == iOne) { - matrixV(i - iOne / 2, j - jOne / 2) = (matrixV(0, j - jOne) + matrixV(iOne, j)) / 2; - } - if (j == jOne) { - matrixV(i - iOne / 2, j - jOne / 2) = (matrixV(i - iOne, 0) + matrixV(i, jOne)) / 2; - } - // Note that this leaves a point at the upper left and lower right corners uninitialized. Not a big deal. - } - } - } - } - } - - if (count == nLoop - 1) { - - (*fErrorConvergenceNormInf)(k - 1) = GetConvergenceError(matricesV, prevArrayV, phiSlice); - (*fError)(k - 1) = GetExactError(matricesV, prevArrayV, phiSlice); - - // if error already achieved then stop mg iteration - fIterations = k - 1; - if ((*fErrorConvergenceNormInf)(k - 1) <= fgConvergenceError) { - Info("PoissonRelaxation3D", "%s", Form("Exact Err: %f, Iteration : %d", (*fError)(k - 1), k - 1)); - break; - } - if (k == maxIteration) { - Info("PoissonRelaxation3D", "%s", Form("Exact Err: %f, Iteration : %d", (*fError)(k - 1), k - 1)); - } - } - } - - iOne = iOne / 2; - if (iOne < 1) { - iOne = 1; - } - jOne = jOne / 2; - if (jOne < 1) { - jOne = 1; - } - } - - for (Int_t k = 0; k < phiSlice; k++) { - matricesSumChargeDensity[k]->Delete(); - } - - for (Int_t m = 0; m < phiSlice; m++) { - delete prevArrayV[m]; - } -} - -/// 3D - Solve Poisson's Equation in 3D by MultiGrid with constant phi slices -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// The number of nRRow and Z Column can be different. -/// -/// R Row == 2**M + 1 -/// Z Column == 2**N + 1 -/// Phi Slice == Arbitrary but greater than 3 -/// -/// Solving: \f$ \nabla^{2}V(r,\phi,z) = - f(r,\phi,z) \f$ -/// -/// Algorithm for MultiGrid Full Cycle (FMG) -/// - Relax on the coarsest grid -/// - Do from coarsest to finest -/// - Interpolate potential from coarse -> fine -/// - Do V-Cycle to the current coarse level to the coarsest -/// - Stop if converged -/// -/// DeltaPhi in Radians -/// \param matricesV TMatrixD** potential in 3D matrix \f$ V(r,\phi,z) \f$ -/// \param matricesCharge TMatrixD** charge density in 3D matrix (side effect) \f$ - f(r,\phi,z) \f$ -/// \param nRRow Int_t number of nRRow in the r direction of TPC -/// \param nZColumn Int_t number of nZColumn in z direction of TPC -/// \param phiSlice Int_t number of phiSlice in phi direction of T{C -/// \param maxIteration Int_t maximum iteration for relaxation method (NOT USED) -/// \param symmetry Int_t symmetry (TODO for symmetry = 1) -// -/// SYMMETRY = 0 if no phi symmetries, and no phi boundary condition -/// = 1 if we have reflection symmetry at the boundaries (eg. sector symmetry or half sector symmetries). -/// -void AliTPCPoissonSolver::PoissonMultiGrid3D2D(TMatrixD** matricesV, TMatrixD** matricesCharge, Int_t nRRow, - Int_t nZColumn, Int_t phiSlice, Int_t symmetry) -{ - - const Float_t gridSizeR = - (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); // h_{r} - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; // h_{phi} - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); // h_{z} - const Float_t ratioPhi = - gridSizeR * gridSizeR / (gridSizePhi * gridSizePhi); // ratio_{phi} = gridSize_{r} / gridSize_{phi} - const Float_t ratioZ = gridSizeR * gridSizeR / (gridSizeZ * gridSizeZ); // ratio_{Z} = gridSize_{r} / gridSize_{z} - - // error tolerate - //const Float_t ERR = 1e-8; - Double_t convergenceError; - - Info("PoissonMultiGrid3D2D", "%s", Form("in Poisson Solver 3D multiGrid semi coarsening nRRow=%d, cols=%d, phiSlice=%d \n", nRRow, nZColumn, phiSlice)); - - // Check that the number of nRRow and nZColumn is suitable for a binary expansion - if (!IsPowerOfTwo((nRRow - 1))) { - Error("PoissonMultiGrid3D2D", "Poisson3DMultiGrid - Error in the number of nRRow. Must be 2**M + 1"); - return; - } - if (!IsPowerOfTwo((nZColumn - 1))) { - Error("PoissonMultiGrid3D2D", "Poisson3DMultiGrid - Error in the number of nZColumn. Must be 2**N - 1"); - return; - } - if (phiSlice <= 3) { - Error("PoissonMultiGrid3D2D", "Poisson3DMultiGrid - Error in the number of phiSlice. Must be larger than 3"); - return; - } - if (phiSlice > 1000) { - Error("PoissonMultiGrid3D2D", "Poisson3D phiSlice > 1000 is not allowed (nor wise) "); - return; - } - - // Solve Poisson's equation in cylindrical coordinates by multiGrid technique - // Allow for different size grid spacing in R and Z directions - - Int_t nGridRow = 0; // number grid - Int_t nGridCol = 0; // number grid - Int_t nnRow; - Int_t nnCol; - - nnRow = nRRow; - while (nnRow >>= 1) { - nGridRow++; - } - nnCol = nZColumn; - while (nnCol >>= 1) { - nGridCol++; - } - - Int_t nLoop = TMath::Max(nGridRow, nGridCol); // Calculate the number of nLoop for the binary expansion - nLoop = (nLoop > fMgParameters.maxLoop) ? fMgParameters.maxLoop : nLoop; - Int_t count; - Int_t iOne = 1; // index i in gridSize r (original) - Int_t jOne = 1; // index j in gridSize z (original) - Int_t tnRRow = nRRow, tnZColumn = nZColumn; - std::vector<TMatrixD**> tvChargeFMG(nLoop); // charge is restricted in full multiGrid - std::vector<TMatrixD**> tvArrayV(nLoop); // potential <--> error - std::vector<TMatrixD**> tvCharge(nLoop); // charge <--> residue - std::vector<TMatrixD**> tvResidue(nLoop); // residue calculation - std::vector<TMatrixD**> tvPrevArrayV(nLoop); // error calculation - - for (count = 1; count <= nLoop; count++) { - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tvResidue[count - 1] = new TMatrixD*[phiSlice]; - tvPrevArrayV[count - 1] = new TMatrixD*[phiSlice]; - for (Int_t k = 0; k < phiSlice; k++) { - tvResidue[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - tvPrevArrayV[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - } - - // memory for the finest grid is from parameters - if (count == 1) { - tvChargeFMG[count - 1] = matricesCharge; - tvArrayV[count - 1] = matricesV; - tvCharge[count - 1] = matricesCharge; - } else { - // allocate for coarser grid - tvChargeFMG[count - 1] = new TMatrixD*[phiSlice]; - tvArrayV[count - 1] = new TMatrixD*[phiSlice]; - tvCharge[count - 1] = new TMatrixD*[phiSlice]; - for (Int_t k = 0; k < phiSlice; k++) { - tvArrayV[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - tvCharge[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - tvChargeFMG[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - } - Restrict3D(tvChargeFMG[count - 1], tvChargeFMG[count - 2], tnRRow, tnZColumn, phiSlice, phiSlice); - RestrictBoundary3D(tvArrayV[count - 1], tvArrayV[count - 2], tnRRow, tnZColumn, phiSlice, phiSlice); - } - iOne = 2 * iOne; // doubling - jOne = 2 * jOne; // doubling - } - Float_t h, h2, radius; - Float_t tempRatioPhi, tempRatioZ; - std::vector<float> coefficient1( - nRRow); // coefficient1(nRRow) for storing (1 + h_{r}/2r_{i}) from central differences in r direction - std::vector<float> coefficient2( - nRRow); // coefficient2(nRRow) for storing (1 + h_{r}/2r_{i}) from central differences in r direction - std::vector<float> coefficient3( - nRRow); // coefficient3(nRRow) for storing (1/r_{i}^2) from central differences in phi direction - std::vector<float> coefficient4(nRRow); // coefficient4(nRRow) for storing 1/2 - std::vector<float> inverseCoefficient4(nRRow); // inverse of coefficient4(nRRow) - - // Case full multi grid (FMG) - if (fMgParameters.cycleType == kFCycle) { - - // 1) Relax on the coarsest grid - iOne = iOne / 2; - jOne = jOne / 2; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - h = gridSizeR * iOne; - h2 = h * h; - - tempRatioPhi = ratioPhi * iOne * iOne; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - // relax on the coarsest level - Relax3D(tvArrayV[nLoop - 1], tvChargeFMG[nLoop - 1], tnRRow, tnZColumn, phiSlice, symmetry, h2, tempRatioZ, - coefficient1, - coefficient2, coefficient3, coefficient4); - // 2) Do multiGrid v-cycle from coarsest to finest - for (count = nLoop - 2; count >= 0; count--) { - // move to finer grid - iOne = iOne / 2; - jOne = jOne / 2; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - // 2) a) Interpolate potential for h -> 2h (coarse -> fine) - Interp3D(tvArrayV[count], tvArrayV[count + 1], tnRRow, tnZColumn, phiSlice, phiSlice); - // 2) c) Copy the restricted charge to charge for calculation - for (Int_t m = 0; m < phiSlice; m++) { - *tvCharge[count][m] = *tvChargeFMG[count][m]; //copy - } - // 2) c) Do V cycle fMgParameters.nMGCycle times at most - for (Int_t mgCycle = 0; mgCycle < fMgParameters.nMGCycle; mgCycle++) { - // Copy the potential to temp array for convergence calculation - for (Int_t m = 0; m < phiSlice; m++) { - *tvPrevArrayV[count][m] = *tvArrayV[count][m]; //copy - } - // 2) c) i) Call V cycle from grid count+1 (current fine level) to nLoop (coarsest) - VCycle3D2D(nRRow, nZColumn, phiSlice, symmetry, count + 1, nLoop, fMgParameters.nPre, fMgParameters.nPost, - gridSizeR, ratioZ, ratioPhi, tvArrayV, tvCharge, tvResidue, coefficient1, coefficient2, coefficient3, - coefficient4, inverseCoefficient4); - - convergenceError = GetConvergenceError(tvArrayV[count], tvPrevArrayV[count], phiSlice); - - if (count == 0) { - (*fErrorConvergenceNormInf)(mgCycle) = convergenceError; - (*fError)(mgCycle) = GetExactError(matricesV, tvPrevArrayV[count], phiSlice); - } - /// if already converge just break move to finer grid - if (convergenceError <= fgConvergenceError) { - fIterations = mgCycle + 1; - break; - } - } - } - } // Case V multi grid (VMG) - else if (fMgParameters.cycleType == kVCycle) { - Int_t gridFrom = 1; - Int_t gridTo = nLoop; - // do v cycle fMgParameters.nMGCycle from the coarsest to finest - for (Int_t mgCycle = 0; mgCycle < fMgParameters.nMGCycle; mgCycle++) { - // copy to store previous potential - for (Int_t m = 0; m < phiSlice; m++) { - *tvPrevArrayV[0][m] = *tvArrayV[0][m]; //copy - } - // Do V Cycle for constant phiSlice - VCycle3D2D(nRRow, nZColumn, phiSlice, symmetry, gridFrom, gridTo, fMgParameters.nPre, fMgParameters.nPost, - gridSizeR, ratioZ, ratioPhi, tvArrayV, tvCharge, tvResidue, coefficient1, coefficient2, coefficient3, - coefficient4, inverseCoefficient4); - - // convergence error - convergenceError = GetConvergenceError(tvArrayV[0], tvPrevArrayV[0], phiSlice); - (*fErrorConvergenceNormInf)(mgCycle) = convergenceError; - (*fError)(mgCycle) = GetExactError(matricesV, tvPrevArrayV[0], phiSlice); - - // if error already achieved then stop mg iteration - if (convergenceError <= fgConvergenceError) { - fIterations = mgCycle + 1; - break; - } - } - } - // Deallocate memory - for (count = 1; count <= nLoop; count++) { - delete[] tvResidue[count - 1]; - delete[] tvPrevArrayV[count - 1]; - - if (count > 1) { - delete[] tvChargeFMG[count - 1]; - delete[] tvArrayV[count - 1]; - delete[] tvCharge[count - 1]; - } - } -} - -/// 3D - Solve Poisson's Equation in 3D in all direction by MultiGrid -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// The number of nRRow and Z Column can be different. -/// -/// R Row == 2**M + 1 -/// Z Column == 2**N + 1 -/// Phi Slices == Arbitrary but greater than 3 -/// -/// Solving: \f$ \nabla^{2}V(r,\phi,z) = - f(r,\phi,z) \f$ -/// -/// Algorithm for MultiGrid Full Cycle (FMG) -/// - Relax on the coarsest grid -/// - Do from coarsest to finest -/// - Interpolate potential from coarse -> fine -/// - Do V-Cycle to the current coarse level to the coarsest -/// - Stop if converged -/// -/// DeltaPhi in Radians -/// \param matricesV TMatrixD** potential in 3D matrix -/// \param matricesCharge TMatrixD** charge density in 3D matrix (side effect) -/// \param nRRow Int_t number of nRRow in the r direction of TPC -/// \param nZColumn Int_t number of nZColumn in z direction of TPC -/// \param phiSlice Int_t number of phiSlice in phi direction of T{C -/// \param maxIteration Int_t maximum iteration for relaxation method -/// \param symmetry Int_t symmetry or not -// -/// SYMMETRY = 0 if no phi symmetries, and no phi boundary condition -/// = 1 if we have reflection symmetry at the boundaries (eg. sector symmetry or half sector symmetries). -/// -void AliTPCPoissonSolver::PoissonMultiGrid3D(TMatrixD** matricesV, TMatrixD** matricesCharge, - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t symmetry) -{ - - const Float_t gridSizeR = - (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); // h_{r} - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); // h_{z} - const Float_t ratioZ = gridSizeR * gridSizeR / (gridSizeZ * gridSizeZ); // ratio_{Z} = gridSize_{r} / gridSize_{z} - - Float_t gridSizePhi = TMath::TwoPi() / phiSlice; // h_{phi} - Float_t h, h2, radius; - Float_t tempRatioPhi, tempRatioZ; - - Float_t convergenceError; // Convergence error - - Info("PoissonMultiGrid3D", "%s", Form("in Poisson Solver 3D multi grid full coarsening nRRow=%d, cols=%d, phiSlice=%d \n", nRRow, nZColumn, phiSlice)); - - // Check that the number of nRRow and nZColumn is suitable for a binary expansion - if (!IsPowerOfTwo((nRRow - 1))) { - Error("PoissonMultiGrid3D", "Poisson3DMultiGrid - Error in the number of nRRow. Must be 2**M + 1"); - return; - } - if (!IsPowerOfTwo((nZColumn - 1))) { - Error("PoissonMultiGrid3D", "Poisson3DMultiGrid - Error in the number of nZColumn. Must be 2**N - 1"); - return; - } - if (phiSlice <= 3) { - Error("PoissonMultiGrid3D", "Poisson3DMultiGrid - Error in the number of phiSlice. Must be larger than 3"); - return; - } - if (phiSlice > 1000) { - Error("PoissonMultiGrid3D", "Poisson3D phiSlice > 1000 is not allowed (nor wise) "); - return; - } - - // Solve Poisson's equation in cylindrical coordinates by multi grid technique - // Allow for different size grid spacing in R and Z directions - - Int_t nGridRow = 0; // number grid - Int_t nGridCol = 0; // number grid - Int_t nGridPhi = 0; - - Int_t nnRow; - Int_t nnCol; - Int_t nnPhi; - - nnRow = nRRow; - while (nnRow >>= 1) { - nGridRow++; - } - - nnCol = nZColumn; - while (nnCol >>= 1) { - nGridCol++; - } - - nnPhi = phiSlice; - - while (nnPhi % 2 == 0) { - nGridPhi++; - nnPhi /= 2; - } - - Info("PoissonMultiGrid3D", "%s", Form("nGridRow=%d, nGridCol=%d, nGridPhi=%d", nGridRow, nGridCol, nGridPhi)); - Int_t nLoop = TMath::Max(nGridRow, nGridCol); // Calculate the number of nLoop for the binary expansion - nLoop = TMath::Max(nLoop, nGridPhi); - - // Vector for storing multi grid array - Int_t iOne = 1; // index i in gridSize r (original) - Int_t jOne = 1; // index j in gridSize z (original) - Int_t kOne = 1; // index k in gridSize phi - Int_t tnRRow = nRRow, tnZColumn = nZColumn, tPhiSlice = phiSlice, otPhiSlice; - - // 1) Memory allocation for multi grid - std::vector<TMatrixD**> tvChargeFMG(nLoop); // charge is restricted in full multiGrid - std::vector<TMatrixD**> tvArrayV(nLoop); // potential <--> error - std::vector<TMatrixD**> tvCharge(nLoop); // charge <--> residue - std::vector<TMatrixD**> tvResidue(nLoop); // residue calculation - std::vector<TMatrixD**> tvPrevArrayV(nLoop); // error calculation - - // these vectors for storing the coefficients in smoother - std::vector<float> coefficient1( - nRRow); // coefficient1(nRRow) for storing (1 + h_{r}/2r_{i}) from central differences in r direction - std::vector<float> coefficient2( - nRRow); // coefficient2(nRRow) for storing (1 + h_{r}/2r_{i}) from central differences in r direction - std::vector<float> coefficient3( - nRRow); // coefficient3(nRRow) for storing (1/r_{i}^2) from central differences in phi direction - std::vector<float> coefficient4(nRRow); // coefficient4(nRRow) for storing 1/2 - std::vector<float> inverseCoefficient4(nRRow); // inverse of coefficient4(nRRow) - - for (Int_t count = 1; count <= nLoop; count++) { - - // tnRRow,tnZColumn in new grid - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tPhiSlice = kOne == 1 ? phiSlice : phiSlice / kOne; - tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; - - // allocate memory for residue - tvResidue[count - 1] = new TMatrixD*[tPhiSlice]; - tvPrevArrayV[count - 1] = new TMatrixD*[tPhiSlice]; - for (Int_t k = 0; k < tPhiSlice; k++) { - tvResidue[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - tvPrevArrayV[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - } - - // memory for the finest grid is from parameters - if (count == 1) { - tvChargeFMG[count - 1] = matricesCharge; - tvArrayV[count - 1] = matricesV; - tvCharge[count - 1] = matricesCharge; - } else { - // allocate for coarser grid - tvChargeFMG[count - 1] = new TMatrixD*[tPhiSlice]; - tvArrayV[count - 1] = new TMatrixD*[tPhiSlice]; - tvCharge[count - 1] = new TMatrixD*[tPhiSlice]; - for (Int_t k = 0; k < tPhiSlice; k++) { - tvArrayV[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - tvCharge[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - tvChargeFMG[count - 1][k] = new TMatrixD(tnRRow, tnZColumn); - } - } - iOne = 2 * iOne; // doubling - jOne = 2 * jOne; // doubling - kOne = 2 * kOne; - } - - // Case full multi grid (FMG) - - if (fMgParameters.cycleType == kFCycle) { - // Restrict the charge to coarser grid - iOne = 2; - jOne = 2; - kOne = 2; - otPhiSlice = phiSlice; - - // 1) Restrict Charge and Boundary to coarser grid - for (Int_t count = 2; count <= nLoop; count++) { - // tnRRow,tnZColumn in new grid - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tPhiSlice = kOne == 1 ? phiSlice : phiSlice / kOne; - tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; - - Info("PoissonMultiGrid3D", "%s", Form("Restrict3D, tnRRow=%d, tnZColumn=%d, newPhiSlice=%d, oldPhiSlice=%d\n", tnRRow, tnZColumn, tPhiSlice, otPhiSlice)); - Restrict3D(tvChargeFMG[count - 1], tvChargeFMG[count - 2], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); - // copy boundary values of V - RestrictBoundary3D(tvArrayV[count - 1], tvArrayV[count - 2], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); - otPhiSlice = tPhiSlice; - - iOne = 2 * iOne; // doubling - jOne = 2 * jOne; // doubling - kOne = 2 * kOne; - } - - // Relax on the coarsest grid - // FMG - // 2) Relax on the coarsest grid - - // move to the coarsest + 1 - iOne = iOne / 2; - jOne = jOne / 2; - kOne = kOne / 2; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tPhiSlice = kOne == 1 ? phiSlice : phiSlice / kOne; - tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; - otPhiSlice = tPhiSlice; - - h = gridSizeR * iOne; - h2 = h * h; - gridSizePhi = TMath::TwoPi() / tPhiSlice; // h_{phi} - tempRatioPhi = h * h / (gridSizePhi * gridSizePhi); // ratio_{phi} = gridSize_{r} / gridSize_{phi} - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - // 3) Relax on the coarsest grid - Relax3D(tvArrayV[nLoop - 1], tvChargeFMG[nLoop - 1], tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, - coefficient1, - coefficient2, coefficient3, coefficient4); - - // 4) V Cycle from coarsest to finest - for (Int_t count = nLoop - 2; count >= 0; count--) { - // move to finer grid - coefficient1.clear(); - coefficient2.clear(); - coefficient3.clear(); - coefficient4.clear(); - inverseCoefficient4.clear(); - - iOne = iOne / 2; - jOne = jOne / 2; - kOne = kOne / 2; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tPhiSlice = kOne == 1 ? phiSlice : phiSlice / kOne; - tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; - // 4) a) interpolate from 2h --> h grid - Interp3D(tvArrayV[count], tvArrayV[count + 1], tnRRow, tnZColumn, tPhiSlice, otPhiSlice); - - // Copy the relax charge to the tvCharge - if (count > 0) { - for (Int_t m = 0; m < tPhiSlice; m++) { - *tvCharge[count][m] = *tvChargeFMG[count][m]; //copy - } - } - for (Int_t mgCycle = 0; mgCycle < fMgParameters.nMGCycle; mgCycle++) { - // copy to store previous potential - for (Int_t m = 0; m < tPhiSlice; m++) { - *tvPrevArrayV[count][m] = *tvArrayV[count][m]; //copy - } - - VCycle3D(nRRow, nZColumn, phiSlice, symmetry, count + 1, nLoop, fMgParameters.nPre, fMgParameters.nPost, - gridSizeR, ratioZ, tvArrayV, - tvCharge, tvResidue, coefficient1, coefficient2, coefficient3, coefficient4, inverseCoefficient4); - - /// converge error - convergenceError = GetConvergenceError(tvArrayV[count], tvPrevArrayV[count], tPhiSlice); - //// error counting ///// - if (count == 0) { - (*fErrorConvergenceNormInf)(mgCycle) = convergenceError; - (*fError)(mgCycle) = GetExactError(matricesV, tvPrevArrayV[count], phiSlice); - } - /// if already converge just break move to finer grid - if (convergenceError <= fgConvergenceError) { - fIterations = mgCycle + 1; - break; - } - } - // keep old slice information - otPhiSlice = tPhiSlice; - } - - } else if (fMgParameters.cycleType == kVCycle) { - // V-cycle - Int_t gridFrom = 1; - Int_t gridTo = nLoop; - - for (Int_t mgCycle = 0; mgCycle < fMgParameters.nMGCycle; mgCycle++) { - // copy to store previous potential - for (Int_t m = 0; m < phiSlice; m++) { - *tvPrevArrayV[0][m] = *tvArrayV[0][m]; //copy - } - // Do V Cycle from the coarsest to finest grid - VCycle3D(nRRow, nZColumn, phiSlice, symmetry, gridFrom, gridTo, fMgParameters.nPre, fMgParameters.nPost, - gridSizeR, ratioZ, tvArrayV, tvCharge, tvResidue, - coefficient1, coefficient2, coefficient3, coefficient4, inverseCoefficient4); - // convergence error - convergenceError = GetConvergenceError(tvArrayV[0], tvPrevArrayV[0], phiSlice); - (*fErrorConvergenceNormInf)(mgCycle) = convergenceError; - (*fError)(mgCycle) = GetExactError(matricesV, tvPrevArrayV[0], phiSlice); - // if error already achieved then stop mg iteration - if (convergenceError <= fgConvergenceError) { - //Info("PoissonMultiGrid3D",Form("Exact Err: %f, MG Iteration : %d", (*fError)(mgCycle), mgCycle)); - fIterations = mgCycle + 1; - break; - } - } - } - // deallocate memory for multiGrid - for (Int_t count = 1; count <= nLoop; count++) { - delete[] tvResidue[count - 1]; - delete[] tvPrevArrayV[count - 1]; - if (count > 1) { - delete[] tvChargeFMG[count - 1]; - delete[] tvArrayV[count - 1]; - delete[] tvCharge[count - 1]; - } - } -} - -/// Helper function to check if the integer is equal to a power of two -/// \param i Int_t the number -/// \return 1 if it is a power of two, else 0 -Int_t AliTPCPoissonSolver::IsPowerOfTwo(Int_t i) const -{ - Int_t j = 0; - while (i > 0) { - j += (i & 1); - i = (i >> 1); - } - if (j == 1) { - return (1); // True - } - return (0); // False -} - -/// Relax3D -/// -/// Relaxation operation for multiGrid -/// relaxation used 7 stencil in cylindrical coordinate -/// -/// Using the following equations -/// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ -/// -/// \param matricesCurrentV TMatrixD** potential in 3D (matrices of matrix) -/// \param matricesCurrentCharge TMatrixD** charge in 3D -/// \param nRRow const Int_t number of nRRow in the r direction of TPC -/// \param nZColumn const Int_t number of nZColumn in z direction of TPC -/// \param phiSlice const Int_t number of phiSlice in phi direction of TPC -/// \param symmetry const Int_t is the cylinder has symmetry -/// \param h2 const Float_t \f$ h_{r}^{2} \f$ -/// \param tempRatioZ const Float_t ration between grid size in z-direction and r-direction -/// \param coefficient1 std::vector<float> coefficient for \f$ V_{x+1,y,z} \f$ -/// \param coefficient2 std::vector<float> coefficient for \f$ V_{x-1,y,z} \f$ -/// \param coefficient3 std::vector<float> coefficient for z -/// \param coefficient4 std::vector<float> coefficient for f(r,\phi,z) -/// -void AliTPCPoissonSolver::Relax3D(TMatrixD** matricesCurrentV, TMatrixD** matricesCurrentCharge, const Int_t tnRRow, - const Int_t tnZColumn, - const Int_t phiSlice, const Int_t symmetry, const Float_t h2, - const Float_t tempRatioZ, std::vector<float>& coefficient1, - std::vector<float>& coefficient2, - std::vector<float>& coefficient3, std::vector<float>& coefficient4) -{ - - Int_t mPlus, mMinus, signPlus, signMinus; - TMatrixD* matrixV; - TMatrixD* matrixVP; - TMatrixD* matrixVM; - TMatrixD* arrayCharge; - - // Gauss-Seidel (Read Black} - if (fMgParameters.relaxType == kGaussSeidel) { - // for each slice - Int_t isw, jsw, msw; - msw = 1; - for (Int_t iPass = 1; iPass <= 2; iPass++, msw = 3 - msw) { - jsw = msw; - for (Int_t m = 0; m < phiSlice; m++, jsw = 3 - jsw) { - mPlus = m + 1; - signPlus = 1; - mMinus = m - 1; - signMinus = 1; - // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) - if (symmetry == 1) { - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - } - if (mMinus < 0) { - mMinus = 1; - } - } - // Anti-symmetry in phi - else if (symmetry == -1) { - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - signPlus = -1; - } - if (mMinus < 0) { - mMinus = 1; - signMinus = -1; - } - } else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi - if (mPlus > phiSlice - 1) { - mPlus = m + 1 - phiSlice; - } - if (mMinus < 0) { - mMinus = m - 1 + phiSlice; - } - } - matrixV = matricesCurrentV[m]; - matrixVP = matricesCurrentV[mPlus]; // slice - matrixVM = matricesCurrentV[mMinus]; // slice - arrayCharge = matricesCurrentCharge[m]; - - isw = jsw; - for (Int_t j = 1; j < tnZColumn - 1; j++, isw = 3 - isw) { - for (Int_t i = isw; i < tnRRow - 1; i += 2) { - //Info("Relax3D",Form("Doing slice %d, z=%d, r=%d", m,j,i)); - (*matrixV)(i, j) = (coefficient2[i] * (*matrixV)(i - 1, j) + tempRatioZ * ((*matrixV)(i, j - 1) + (*matrixV)(i, j + 1)) + coefficient1[i] * (*matrixV)(i + 1, j) + coefficient3[i] * (signPlus * (*matrixVP)(i, j) + signMinus * (*matrixVM)(i, j)) + (h2 * (*arrayCharge)(i, j))) * coefficient4[i]; - } // end cols - } // end nRRow - } // end phi - } // end sweep - } else if (fMgParameters.relaxType == kJacobi) { - // for each slice - for (Int_t m = 0; m < phiSlice; m++) { - - mPlus = m + 1; - signPlus = 1; - mMinus = m - 1; - signMinus = 1; - - // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) - if (symmetry == 1) { - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - } - if (mMinus < 0) { - mMinus = 1; - } - } - // Anti-symmetry in phi - else if (symmetry == -1) { - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - signPlus = -1; - } - if (mMinus < 0) { - mMinus = 1; - signMinus = -1; - } - } else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi - if (mPlus > phiSlice - 1) { - mPlus = m + 1 - phiSlice; - } - if (mMinus < 0) { - mMinus = m - 1 + phiSlice; - } - } - - matrixV = matricesCurrentV[m]; - matrixVP = matricesCurrentV[mPlus]; // slice - matrixVM = matricesCurrentV[mMinus]; // slice - arrayCharge = matricesCurrentCharge[m]; - - // Jacobian - for (Int_t j = 1; j < tnZColumn - 1; j++) { - for (Int_t i = 1; i < tnRRow - 1; i++) { - (*matrixV)(i, j) = (coefficient2[i] * (*matrixV)(i - 1, j) + tempRatioZ * ((*matrixV)(i, j - 1) + (*matrixV)(i, j + 1)) + coefficient1[i] * (*matrixV)(i + 1, j) + coefficient3[i] * (signPlus * (*matrixVP)(i, j) + signMinus * (*matrixVM)(i, j)) + (h2 * (*arrayCharge)(i, j))) * coefficient4[i]; - - } // end cols - } // end nRRow - - } // end phi - - } else { - // Case weighted Jacobi - // TODO - } -} - -/// Relax2D -/// -/// Relaxation operation for multiGrid -/// relaxation used 5 stencil in cylindrical coordinate -/// -/// Using the following equations -/// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ -/// -/// \param matricesCurrentV TMatrixD& potential in 3D (matrices of matrix) -/// \param matricesCurrentCharge TMatrixD& charge in 3D -/// \param nRRow const Int_t number of nRRow in the r direction of TPC -/// \param nZColumn const Int_t number of nZColumn in z direction of TPC -/// \param phiSlice const Int_t number of phiSlice in phi direction of TPC -/// \param symmetry const Int_t is the cylinder has symmetry -/// \param h2 const Float_t \f$ h_{r}^{2} \f$ -/// \param tempFourth const Float_t coefficient for h -/// \param tempRatio const Float_t ratio between grid size in z-direction and r-direction -/// \param coefficient1 std::vector<float> coefficient for \f$ V_{x+1,y,z} \f$ -/// \param coefficient2 std::vector<float> coefficient for \f$ V_{x-1,y,z} \f$ -/// -void AliTPCPoissonSolver::Relax2D(TMatrixD& matricesCurrentV, TMatrixD& matricesCurrentCharge, const Int_t tnRRow, - const Int_t tnZColumn, - const Float_t h2, const Float_t tempFourth, const Float_t tempRatio, - std::vector<float>& coefficient1, std::vector<float>& coefficient2) -{ - - // Gauss-Seidel - if (fMgParameters.relaxType == kGaussSeidel) { - - Int_t isw, jsw = 1; - for (Int_t iPass = 1; iPass <= 2; iPass++, jsw = 3 - jsw) { - isw = jsw; - for (Int_t j = 1; j < tnZColumn - 1; j++, isw = 3 - isw) { - for (Int_t i = isw; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = tempFourth * (coefficient1[i] * matricesCurrentV(i + 1, j) + - coefficient2[i] * matricesCurrentV(i - 1, j) + - tempRatio * (matricesCurrentV(i, j + 1) + matricesCurrentV(i, j - 1)) + - (h2 * matricesCurrentCharge(i, j))); - } // end cols - } // end nRRow - } // end pass red-black - } else if (fMgParameters.relaxType == kJacobi) { - for (Int_t j = 1; j < tnZColumn - 1; j++) { - for (Int_t i = 1; i < tnRRow - 1; i++) { - matricesCurrentV(i, j) = tempFourth * (coefficient1[i] * matricesCurrentV(i + 1, j) + - coefficient2[i] * matricesCurrentV(i - 1, j) + tempRatio * (matricesCurrentV(i, j + 1) + matricesCurrentV(i, j - 1)) + - (h2 * matricesCurrentCharge(i, j))); - } // end cols - } // end nRRow - } else if (fMgParameters.relaxType == kWeightedJacobi) { - // Weighted Jacobi - // TODO - } -} - -/// Residue3D -/// -/// Compute residue from V(.) where V(.) is numerical potential and f(.). -/// residue used 7 stencil in cylindrical coordinate -/// -/// Using the following equations -/// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ -/// -/// \param residue TMatrixD** residue in 3D (matrices of matrix) -/// \param matricesCurrentV TMatrixD** potential in 3D (matrices of matrix) -/// \param matricesCurrentCharge TMatrixD** charge in 3D -/// \param nRRow const Int_t number of nRRow in the r direction of TPC -/// \param nZColumn const Int_t number of nZColumn in z direction of TPC -/// \param phiSlice const Int_t number of phiSlice in phi direction of TPC -/// \param symmetry const Int_t is the cylinder has symmetry -/// \param ih2 const Float_t \f$ 1/ h_{r}^{2} \f$ -/// \param tempRatioZ const Float_t ration between grid size in z-direction and r-direction -/// \param coefficient1 std::vector<float> coefficient for \f$ V_{x+1,y,z} \f$ -/// \param coefficient2 std::vector<float> coefficient for \f$ V_{x-1,y,z} \f$ -/// \param coefficient3 std::vector<float> coefficient for z -/// \param inverseCoefficient4 std::vector<float> inverse coefficient for f(r,\phi,z) -/// -void AliTPCPoissonSolver::Residue3D(TMatrixD** residue, TMatrixD** matricesCurrentV, TMatrixD** matricesCurrentCharge, - const Int_t tnRRow, - const Int_t tnZColumn, const Int_t phiSlice, const Int_t symmetry, - const Float_t ih2, - const Float_t tempRatioZ, std::vector<float>& coefficient1, - std::vector<float>& coefficient2, - std::vector<float>& coefficient3, std::vector<float>& inverseCoefficient4) -{ - Int_t mPlus, mMinus, signPlus, signMinus; - for (Int_t m = 0; m < phiSlice; m++) { - - mPlus = m + 1; - signPlus = 1; - mMinus = m - 1; - signMinus = 1; - - // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) - if (symmetry == 1) { - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - } - if (mMinus < 0) { - mMinus = 1; - } - } - // Anti-symmetry in phi - else if (symmetry == -1) { - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - signPlus = -1; - } - if (mMinus < 0) { - mMinus = 1; - signMinus = -1; - } - } else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi - if (mPlus > phiSlice - 1) { - mPlus = m + 1 - phiSlice; - } - if (mMinus < 0) { - mMinus = m - 1 + phiSlice; - } - } - - TMatrixD& arrayResidue = *residue[m]; - TMatrixD& matrixV = *matricesCurrentV[m]; - TMatrixD& matrixVP = *matricesCurrentV[mPlus]; // slice - TMatrixD& matrixVM = *matricesCurrentV[mMinus]; // slice - TMatrixD& arrayCharge = *matricesCurrentCharge[m]; - - for (Int_t j = 1; j < tnZColumn - 1; j++) { - for (Int_t i = 1; i < tnRRow - 1; i++) { - - arrayResidue(i, j) = - ih2 * (coefficient2[i] * matrixV(i - 1, j) + tempRatioZ * (matrixV(i, j - 1) + matrixV(i, j + 1)) + coefficient1[i] * matrixV(i + 1, j) + - coefficient3[i] * (signPlus * matrixVP(i, j) + signMinus * matrixVM(i, j)) - - inverseCoefficient4[i] * matrixV(i, j)) + - arrayCharge(i, j); - - } // end cols - } // end nRRow - - //arrayResidue.Print(); - } -} - -/// Residue2D -/// -/// Compute residue from V(.) where V(.) is numerical potential and f(.). -/// residue used 5 stencil in cylindrical coordinate -/// -/// Using the following equations -/// \f$ U_{i,j,k} = (1 + \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} + (1 - \frac{1}{r_{i}h_{r}}) U_{i+1,j,k} \f$ -/// -/// \param residue TMatrixD& potential in 2D -/// \param matricesCurrentV TMatrixD& potential in 2D -/// \param matricesCurrentCharge TMatrixD& charge in 2D -/// \param nRRow const Int_t number of nRRow in the r direction of TPC -/// \param nZColumn const Int_t number of nZColumn in z direction of TPC -/// \param phiSlice const Int_t number of phiSlice in phi direction of TPC -/// \param symmetry const Int_t is the cylinder has symmetry -/// \param h2 const Float_t \f$ h_{r}^{2} \f$ -/// \param tempFourth const Float_t coefficient for h -/// \param tempRatio const Float_t ratio between grid size in z-direction and r-direction -/// \param coefficient1 std::vector<float> coefficient for \f$ V_{x+1,y,z} \f$ -/// \param coefficient2 std::vector<float> coefficient for \f$ V_{x-1,y,z} \f$ -/// -void AliTPCPoissonSolver::Residue2D(TMatrixD& residue, TMatrixD& matricesCurrentV, TMatrixD& matricesCurrentCharge, - const Int_t tnRRow, - const Int_t tnZColumn, const Float_t ih2, const Float_t inverseTempFourth, - const Float_t tempRatio, std::vector<float>& coefficient1, - std::vector<float>& coefficient2) -{ - for (Int_t i = 1; i < tnRRow - 1; i++) { - for (Int_t j = 1; j < tnZColumn - 1; j++) { - residue(i, j) = ih2 * (coefficient1[i] * matricesCurrentV(i + 1, j) + coefficient2[i] * matricesCurrentV(i - 1, j) + tempRatio * (matricesCurrentV(i, j + 1) + matricesCurrentV(i, j - 1)) - - inverseTempFourth * matricesCurrentV(i, j)) + - matricesCurrentCharge(i, j); - - } // end cols - } // end nRRow - - //Boundary points. - for (Int_t i = 0; i < tnRRow; i++) { - residue(i, 0) = residue(i, tnZColumn - 1) = 0.0; - } - - for (Int_t j = 0; j < tnZColumn; j++) { - residue(0, j) = residue(tnRRow - 1, j) = 0.0; - } -} - -/// Restrict2D -/// -/// Grid transfer operator, restrict from fine -> coarse grid -/// provide full-half weighting -/// -/// \[ \frac{1}{16}\left( \begin{array}{ccc} -/// 1 & 2 & 1 \\ -/// 2 & 4 & 2 \\ -/// 1 & 2 & 1 \end{array} \right) \] -/// -/// \param matricesCurrentCharge TMatrixD& coarse grid (2h) -/// \param residue TMatrixD& fine grid (h) -/// \param nRRow const Int_t number of nRRow in the r direction of TPC -/// \param nZColumn const Int_t number of nZColumn in z direction of TPC -/// -void AliTPCPoissonSolver::Restrict2D(TMatrixD& matricesCurrentCharge, TMatrixD& residue, const Int_t tnRRow, - const Int_t tnZColumn) -{ - - for (Int_t i = 1, ii = 2; i < tnRRow - 1; i++, ii += 2) { - for (Int_t j = 1, jj = 2; j < tnZColumn - 1; j++, jj += 2) { - if (fMgParameters.gtType == kHalf) { - // half - matricesCurrentCharge(i, j) = 0.5 * residue(ii, jj) + - 0.125 * - (residue(ii + 1, jj) + residue(ii - 1, jj) + residue(ii, jj + 1) + - residue(ii, jj - 1)); - - } else - // full - if (fMgParameters.gtType == kFull) { - matricesCurrentCharge(i, j) = 0.25 * residue(ii, jj) + - 0.125 * - (residue(ii + 1, jj) + residue(ii - 1, jj) + residue(ii, jj + 1) + - residue(ii, jj - 1)) + - 0.0625 * - (residue(ii + 1, jj + 1) + residue(ii - 1, jj + 1) + residue(ii + 1, jj - 1) + - residue(ii - 1, jj - 1)); - } - - } // end cols - } // end nRRow - - // boundary - // for boundary - for (Int_t j = 0, jj = 0; j < tnZColumn; j++, jj += 2) { - matricesCurrentCharge(0, j) = residue(0, jj); - matricesCurrentCharge(tnRRow - 1, j) = residue((tnRRow - 1) * 2, jj); - } - - // for boundary - for (Int_t i = 0, ii = 0; i < tnRRow; i++, ii += 2) { - matricesCurrentCharge(i, 0) = residue(ii, 0); - matricesCurrentCharge(i, tnZColumn - 1) = residue(ii, (tnZColumn - 1) * 2); - } -} - -/// RestrictBoundary2D -/// -/// Boundary transfer restrict from fine -> coarse grid -/// -/// \param matricesCurrentCharge TMatrixD& coarse grid (2h) -/// \param residue TMatrixD& fine grid (h) -/// \param nRRow const Int_t number of nRRow in the r direction of TPC -/// \param nZColumn const Int_t number of nZColumn in z direction of TPC -/// -void AliTPCPoissonSolver::RestrictBoundary2D(TMatrixD& matricesCurrentCharge, TMatrixD& residue, const Int_t tnRRow, - const Int_t tnZColumn) -{ - // for boundary - for (Int_t j = 0, jj = 0; j < tnZColumn; j++, jj += 2) { - matricesCurrentCharge(0, j) = residue(0, jj); - matricesCurrentCharge(tnRRow - 1, j) = residue((tnRRow - 1) * 2, jj); - } - - // for boundary - for (Int_t i = 0, ii = 0; i < tnRRow; i++, ii += 2) { - matricesCurrentCharge(i, 0) = residue(ii, 0); - matricesCurrentCharge(i, tnZColumn - 1) = residue(ii, (tnZColumn - 1) * 2); - } -} - -/// Restriction in 3D -/// -/// Restriction is a map from fine grid (h) to coarse grid (2h) -/// -/// In case of 3D -/// Full weighting: -/// \f[ (R u)_{i,j,k} = \frac{1}{2} u_{2i,2j,2k} + \frac{1}{4} S_{1} + \frac{1}{8} S_{2} + \frac{1}{16} S_{3}\f] -/// -/// -/// Restriction in all direction r-phi-z -/// restriction in phi only if oldPhi == 2*newPhi -/// \param matricesCurrentCharge TMatrixD** coarser grid 2h -/// \param residue TMatrixD ** fine grid h -/// \param tnRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param tnZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param newPhiSlice Int_t number of phiSlice (in phi-direction) for coarser grid -/// \param oldPhiSlice Int_t number of phiSlice (in phi-direction) for finer grid -/// -void AliTPCPoissonSolver::Restrict3D(TMatrixD** matricesCurrentCharge, TMatrixD** residue, const Int_t tnRRow, - const Int_t tnZColumn, - const Int_t newPhiSlice, const Int_t oldPhiSlice) -{ - - Double_t s1, s2, s3; - - if (2 * newPhiSlice == oldPhiSlice) { - - Int_t mPlus, mMinus; - Int_t mm = 0; - - for (Int_t m = 0; m < newPhiSlice; m++, mm += 2) { - - // assuming no symmetry - mPlus = mm + 1; - mMinus = mm - 1; - - if (mPlus > (oldPhiSlice)-1) { - mPlus = mm + 1 - (oldPhiSlice); - } - if (mMinus < 0) { - mMinus = mm - 1 + (oldPhiSlice); - } - - TMatrixD& arrayResidue = *residue[mm]; - TMatrixD& arrayResidueP = *residue[mPlus]; - TMatrixD& arrayResidueM = *residue[mMinus]; // slice - TMatrixD& arrayCharge = *matricesCurrentCharge[m]; - - for (Int_t i = 1, ii = 2; i < tnRRow - 1; i++, ii += 2) { - for (Int_t j = 1, jj = 2; j < tnZColumn - 1; j++, jj += 2) { - - // at the same plane - s1 = arrayResidue(ii + 1, jj) + arrayResidue(ii - 1, jj) + arrayResidue(ii, jj + 1) + - arrayResidue(ii, jj - 1) + arrayResidueP(ii, jj) + arrayResidueM(ii, jj); - s2 = (arrayResidue(ii + 1, jj + 1) + arrayResidue(ii + 1, jj - 1) + arrayResidueP(ii + 1, jj) + - arrayResidueM(ii + 1, jj)) + - (arrayResidue(ii - 1, jj - 1) + arrayResidue(ii - 1, jj + 1) + arrayResidueP(ii - 1, jj) + - arrayResidueM(ii - 1, jj)) + - arrayResidueP(ii, jj - 1) + arrayResidueM(ii, jj + 1) + arrayResidueM(ii, jj - 1) + - arrayResidueP(ii, jj + 1); - - s3 = (arrayResidueP(ii + 1, jj + 1) + arrayResidueP(ii + 1, jj - 1) + arrayResidueM(ii + 1, jj + 1) + - arrayResidueM(ii + 1, jj - 1)) + - (arrayResidueM(ii - 1, jj - 1) + arrayResidueM(ii - 1, jj + 1) + arrayResidueP(ii - 1, jj - 1) + - arrayResidueP(ii - 1, jj + 1)); - - arrayCharge(i, j) = 0.125 * arrayResidue(ii, jj) + 0.0625 * s1 + 0.03125 * s2 + 0.015625 * s3; - } // end cols - } // end nRRow - - // for boundary - for (Int_t j = 0, jj = 0; j < tnZColumn; j++, jj += 2) { - arrayCharge(0, j) = arrayResidue(0, jj); - arrayCharge(tnRRow - 1, j) = arrayResidue((tnRRow - 1) * 2, jj); - } - - // for boundary - for (Int_t i = 0, ii = 0; i < tnRRow; i++, ii += 2) { - arrayCharge(i, 0) = arrayResidue(ii, 0); - arrayCharge(i, tnZColumn - 1) = arrayResidue(ii, (tnZColumn - 1) * 2); - } - } // end phis - - } else { - for (int m = 0; m < newPhiSlice; m++) { - Restrict2D(*matricesCurrentCharge[m], *residue[m], tnRRow, tnZColumn); - } - } -} - -/// Restrict Boundary in 3D -/// -/// Pass boundary information to coarse grid -/// -/// \param matricesCurrentCharge TMatrixD** coarser grid 2h -/// \param residue TMatrixD ** fine grid h -/// \param tnRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param tnZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param newPhiSlice Int_t number of phiSlice (in phi-direction) for coarser grid -/// \param oldPhiSlice Int_t number of phiSlice (in phi-direction) for finer grid -/// -void AliTPCPoissonSolver::RestrictBoundary3D(TMatrixD** matricesCurrentCharge, TMatrixD** residue, const Int_t tnRRow, - const Int_t tnZColumn, const Int_t newPhiSlice, const Int_t oldPhiSlice) -{ - - // in case of full 3d and the phiSlice is also coarsening - - if (2 * newPhiSlice == oldPhiSlice) { - - for (Int_t m = 0, mm = 0; m < newPhiSlice; m++, mm += 2) { - - TMatrixD& arrayResidue = *residue[mm]; - TMatrixD& arrayCharge = *matricesCurrentCharge[m]; - // for boundary - for (Int_t j = 0, jj = 0; j < tnZColumn; j++, jj += 2) { - arrayCharge(0, j) = arrayResidue(0, jj); - arrayCharge(tnRRow - 1, j) = arrayResidue((tnRRow - 1) * 2, jj); - } - - // for boundary - for (Int_t i = 0, ii = 0; i < tnRRow; i++, ii += 2) { - arrayCharge(i, 0) = arrayResidue(ii, 0); - arrayCharge(i, tnZColumn - 1) = arrayResidue(ii, (tnZColumn - 1) * 2); - } - } // end phis - } else { - for (int m = 0; m < newPhiSlice; m++) { - RestrictBoundary2D(*matricesCurrentCharge[m], *residue[m], tnRRow, tnZColumn); - } - } -} - -/// Prolongation with Addition for 2D -/// -/// Interpolation with addition from coarse level (2h) --> fine level (h) -/// -/// Interpolation in all direction r-phi-z -/// \param matricesCurrentV TMatrixD& fine grid h -/// \param matricesCurrentVC TMatrixD& coarse grid 2h -/// \param tnRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param tnZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1a -/// -void AliTPCPoissonSolver::AddInterp2D(TMatrixD& matricesCurrentV, TMatrixD& matricesCurrentVC, const Int_t tnRRow, - const Int_t tnZColumn) -{ - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = matricesCurrentV(i, j) + matricesCurrentVC(i / 2, j / 2); - } - } - - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = - matricesCurrentV(i, j) + 0.5 * (matricesCurrentVC(i / 2, j / 2) + matricesCurrentVC(i / 2, j / 2 + 1)); - } - } - - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = - matricesCurrentV(i, j) + 0.5 * (matricesCurrentVC(i / 2, j / 2) + matricesCurrentVC(i / 2 + 1, j / 2)); - } - } - - // only if full - if (fMgParameters.gtType == kFull) { - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = - matricesCurrentV(i, j) + 0.25 * (matricesCurrentVC(i / 2, j / 2) + matricesCurrentVC(i / 2, j / 2 + 1) + matricesCurrentVC(i / 2 + 1, j / 2) + matricesCurrentVC(i / 2 + 1, j / 2 + 1)); - } - } - } -} - -/// Prolongation with Addition for 3D -/// -/// Interpolation with addition from coarse level (2h) --> fine level (h) -/// -/// Interpolation in all direction r-phi-z -/// Interpolation in phi only if oldPhi == 2*newPhi -/// \param matricesCurrentV TMatrixD& fine grid h -/// \param matricesCurrentVC TMatrixD& coarse grid 2h -/// \param tnRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param tnZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1a -/// \param newPhiSlice Int_t number of phiSlice (in phi-direction) for coarser grid -/// \param oldPhiSlice Int_t number of phiSlice (in phi-direction) for finer grid -/// -void AliTPCPoissonSolver::AddInterp3D(TMatrixD** matricesCurrentV, TMatrixD** matricesCurrentVC, const Int_t tnRRow, - const Int_t tnZColumn, - const Int_t newPhiSlice, const Int_t oldPhiSlice) -{ - // Do restrict 2 D for each slice - - //const Float_t h = (AliTPCPoissonSolver::fgkOFCRadius-AliTPCPoissonSolver::fgkIFCRadius) / ((tnRRow-1)/2); // h_{r} - //Float_t radius,ratio; - //std::vector<float> coefficient1((tnRRow-1) / 2 ); // coefficient1(nRRow) for storing (1 + h_{r}/2r_{i}) from central differences in r direction - //std::vector<float> coefficient2((tnRRow-1) / 2); // coefficient2(nRRow) for storing (1 + h_{r}/2r_{i}) from central differences in r direction - - if (newPhiSlice == 2 * oldPhiSlice) { - Int_t mPlus, mmPlus; - Int_t mm = 0; - - for (Int_t m = 0; m < newPhiSlice; m += 2) { - - // assuming no symmetry - mm = m / 2; - mmPlus = mm + 1; - mPlus = m + 1; - - // round - if (mmPlus > (oldPhiSlice)-1) { - mmPlus = mm + 1 - (oldPhiSlice); - } - if (mPlus > (newPhiSlice)-1) { - mPlus = m + 1 - (newPhiSlice); - } - - TMatrixD& fineV = *matricesCurrentV[m]; - TMatrixD& fineVP = *matricesCurrentV[mPlus]; - TMatrixD& coarseV = *matricesCurrentVC[mm]; - TMatrixD& coarseVP = *matricesCurrentVC[mmPlus]; - - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - fineV(i, j) += coarseV(i / 2, j / 2); - // point on corner lines at phi direction - fineVP(i, j) += 0.5 * (coarseV(i / 2, j / 2) + coarseVP(i / 2, j / 2)); - } - } - - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - fineV(i, j) += 0.5 * (coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1)); - // point on corner lines at phi direction - fineVP(i, j) += 0.25 * (coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1) + coarseVP(i / 2, j / 2) + - coarseVP(i / 2, j / 2 + 1)); - } - } - - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - fineV(i, j) += 0.5 * (coarseV(i / 2, j / 2) + coarseV(i / 2 + 1, j / 2)); - - // point on line at phi direction - fineVP(i, j) += 0.25 * ((coarseV(i / 2, j / 2) + coarseVP(i / 2, j / 2)) + - (coarseVP(i / 2 + 1, j / 2) + coarseV(i / 2 + 1, j / 2))); - } - } - - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - fineV(i, j) += 0.25 * ((coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1)) + - (coarseV(i / 2 + 1, j / 2) + coarseV(i / 2 + 1, j / 2 + 1))); - - // point at the center at phi direction - fineVP(i, j) += 0.125 * ((coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1) + coarseVP(i / 2, j / 2) + - coarseVP(i / 2, j / 2 + 1)) + - (coarseV(i / 2 + 1, j / 2) + coarseV(i / 2 + 1, j / 2 + 1) + - coarseVP(i / 2 + 1, j / 2) + coarseVP(i / 2 + 1, j / 2 + 1))); - } - } - } - - } else { - for (int m = 0; m < newPhiSlice; m++) { - AddInterp2D(*matricesCurrentV[m], *matricesCurrentVC[m], tnRRow, tnZColumn); - } - } -} - -/// Interpolation/Prolongation in 3D -/// -/// Interpolation is a map from coarse grid (h) to fine grid (2h) -/// -/// In case of 3D -/// Full weighting: -/// \f[ (R u)_{i,j,k} = \frac{1}{2} u_{2i,2j,2k} + \frac{1}{4} S_{1} + \frac{1}{8} S_{2} + \frac{1}{16} S_{3}\f] -/// -/// -/// Restriction in all direction r-phi-z -/// restriction in phi only if oldPhi == 2*newPhi -/// \param matricesCurrentV TMatrixD** finer grid h -/// \param curArrayCV TMatrixD ** coarse grid 2h -/// \param tnRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param tnZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param newPhiSlice Int_t number of phiSlice (in phi-direction) for coarser grid -/// \param oldPhiSlice Int_t number of phiSlice (in phi-direction) for finer grid -/// -void AliTPCPoissonSolver::Interp3D(TMatrixD** matricesCurrentV, TMatrixD** matricesCurrentVC, const Int_t tnRRow, - const Int_t tnZColumn, - const Int_t newPhiSlice, const Int_t oldPhiSlice) -{ - - // Do restrict 2 D for each slice - if (newPhiSlice == 2 * oldPhiSlice) { - Int_t mPlus, mmPlus; - Int_t mm = 0; - - for (Int_t m = 0; m < newPhiSlice; m += 2) { - - // assuming no symmetry - mm = m / 2; - mmPlus = mm + 1; - mPlus = m + 1; - - // round - if (mmPlus > (oldPhiSlice)-1) { - mmPlus = mm + 1 - (oldPhiSlice); - } - if (mPlus > (newPhiSlice)-1) { - mPlus = m + 1 - (newPhiSlice); - } - - TMatrixD& fineV = *matricesCurrentV[m]; - TMatrixD& fineVP = *matricesCurrentV[mPlus]; - TMatrixD& coarseV = *matricesCurrentVC[mm]; - TMatrixD& coarseVP = *matricesCurrentVC[mmPlus]; - - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - fineV(i, j) = coarseV(i / 2, j / 2); - - // point on corner lines at phi direction - fineVP(i, j) = 0.5 * (coarseV(i / 2, j / 2) + coarseVP(i / 2, j / 2)); - } - } - - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - fineV(i, j) = 0.5 * (coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1)); - - // point on corner lines at phi direction - fineVP(i, j) = 0.25 * (coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1) + coarseVP(i / 2, j / 2) + - coarseVP(i / 2, j / 2 + 1)); - } - } - - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - fineV(i, j) = 0.5 * (coarseV(i / 2, j / 2) + coarseV(i / 2 + 1, j / 2)); - - // point on line at phi direction - fineVP(i, j) = 0.25 * ((coarseV(i / 2, j / 2) + coarseVP(i / 2, j / 2)) + - (coarseVP(i / 2 + 1, j / 2) + coarseV(i / 2 + 1, j / 2))); - } - } - - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - fineV(i, j) = 0.25 * ((coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1)) + - (coarseV(i / 2 + 1, j / 2) + coarseV(i / 2 + 1, j / 2 + 1))); - - // point at the center at phi direction - fineVP(i, j) = 0.125 * ((coarseV(i / 2, j / 2) + coarseV(i / 2, j / 2 + 1) + coarseVP(i / 2, j / 2) + - coarseVP(i / 2, j / 2 + 1)) + - (coarseV(i / 2 + 1, j / 2) + coarseV(i / 2 + 1, j / 2 + 1) + - coarseVP(i / 2 + 1, j / 2) + coarseVP(i / 2 + 1, j / 2 + 1))); - } - } - } - - } else { - for (int m = 0; m < newPhiSlice; m++) { - Interp2D(*matricesCurrentV[m], *matricesCurrentVC[m], tnRRow, tnZColumn); - } - } -} - -/// Interpolation/Prolongation in 2D -/// -/// Interpolation is a map from coarse grid (h) to fine grid (2h) -/// -/// In case of 2D -/// Full weighting: -/// \f[ (R u)_{i,j,k} = \frac{1}{2} u_{2i,2j,2k} + \frac{1}{4} S_{1} + \frac{1}{8} S_{2} + \frac{1}{16} S_{3}\f] -/// -/// -/// Restriction in all direction r-phi-z -/// \param matricesCurrentV TMatrixD** finer grid h -/// \param curArrayCV TMatrixD ** coarse grid 2h -/// \param tnRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param tnZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// -void AliTPCPoissonSolver::Interp2D(TMatrixD& matricesCurrentV, TMatrixD& matricesCurrentVC, const Int_t tnRRow, - const Int_t tnZColumn) -{ - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = matricesCurrentVC(i / 2, j / 2); - } - } - - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 2; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = 0.5 * (matricesCurrentVC(i / 2, j / 2) + matricesCurrentVC(i / 2, j / 2 + 1)); - } - } - - for (Int_t j = 2; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = 0.5 * (matricesCurrentVC(i / 2, j / 2) + matricesCurrentVC(i / 2 + 1, j / 2)); - } - } - - // only if full - if (fMgParameters.gtType == kFull) { - for (Int_t j = 1; j < tnZColumn - 1; j += 2) { - for (Int_t i = 1; i < tnRRow - 1; i += 2) { - matricesCurrentV(i, j) = 0.25 * - (matricesCurrentVC(i / 2, j / 2) + matricesCurrentVC(i / 2, j / 2 + 1) + - matricesCurrentVC(i / 2 + 1, j / 2) + - matricesCurrentVC(i / 2 + 1, j / 2 + 1)); - } - } - } -} - -/// V-Cycle 2D -/// -/// Implementation non-recursive V-cycle for 2D -/// -/// Algorithms: -/// -/// \param nRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param nZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param gridFrom const Int_t finest level of grid -/// \param gridTo const Int_t coarsest level of grid -/// \param nPre const Int_t number of smoothing before coarsening -/// \param nPost const Int_t number of smoothing after coarsening -/// \param gridSizeR const Float_t grid size in r direction (OPTION, recalculate) -/// \param ratio const Float_t ratio between square of grid r and grid z (OPTION, recalculate) -/// \param tvArrayV vector<TMatrixD *> vector of V potential in different grids -/// \param tvCharge vector<TMatrixD *> vector of charge distribution in different grids -/// \param tvResidue vector<TMatrixD *> vector of residue calculation in different grids -/// -void AliTPCPoissonSolver::VCycle2D(const Int_t nRRow, const Int_t nZColumn, const Int_t gridFrom, const Int_t gridTo, - const Int_t nPre, const Int_t nPost, const Float_t gridSizeR, const Float_t ratio, - std::vector<TMatrixD*>& tvArrayV, - std::vector<TMatrixD*>& tvCharge, std::vector<TMatrixD*>& tvResidue) -{ - - Float_t h, h2, ih2, tempRatio, tempFourth, inverseTempFourth, radius; - TMatrixD *matricesCurrentV, *matricesCurrentVC; - TMatrixD* matricesCurrentCharge; - TMatrixD* residue; - Int_t iOne, jOne, tnRRow, tnZColumn, count; - iOne = 1 << (gridFrom - 1); - jOne = 1 << (gridFrom - 1); - - matricesCurrentV = nullptr; - matricesCurrentVC = nullptr; - matricesCurrentCharge = nullptr; - residue = nullptr; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - std::vector<float> coefficient1(nRRow); - std::vector<float> coefficient2(nZColumn); - - // 1) Go to coarsest level - for (count = gridFrom; count <= gridTo - 1; count++) { - h = gridSizeR * iOne; - h2 = h * h; - ih2 = 1.0 / h2; - tempRatio = ratio * iOne * iOne / (jOne * jOne); - tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); - inverseTempFourth = 1.0 / tempFourth; - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - } - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentCharge = tvCharge[count - 1]; - residue = tvResidue[count - 1]; - - // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi - for (Int_t jPre = 1; jPre <= nPre; jPre++) { - Relax2D(*matricesCurrentV, *matricesCurrentCharge, tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, - coefficient2); - } - - // 2) Residue calculation - Residue2D(*residue, *matricesCurrentV, *matricesCurrentCharge, tnRRow, tnZColumn, ih2, inverseTempFourth, tempRatio, - coefficient1, - coefficient2); - - iOne = 2 * iOne; - jOne = 2 * jOne; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - matricesCurrentCharge = tvCharge[count]; - matricesCurrentV = tvArrayV[count]; - - //3) Restriction - Restrict2D(*matricesCurrentCharge, *residue, tnRRow, tnZColumn); - - //4) Zeroing coarser V - matricesCurrentV->Zero(); - } - - // 5) coarsest grid - h = gridSizeR * iOne; - h2 = h * h; - tempRatio = ratio * iOne * iOne / (jOne * jOne); - tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - } - - Relax2D(*matricesCurrentV, *matricesCurrentCharge, tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, - coefficient2); - - // Go to finest grid - for (count = gridTo - 1; count >= gridFrom; count--) { - - iOne = iOne / 2; - jOne = jOne / 2; - - h = gridSizeR * iOne; - h2 = h * h; - ih2 = 1.0 / h2; - tempRatio = ratio * iOne * iOne / (jOne * jOne); - tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); - inverseTempFourth = 1.0 / tempFourth; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - matricesCurrentCharge = tvCharge[count - 1]; - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentVC = tvArrayV[count]; - - // 6) Interpolation/Prolongation - AddInterp2D(*matricesCurrentV, *matricesCurrentVC, tnRRow, tnZColumn); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - } - - // 7) Post-Smoothing: Gauss-Seidel Relaxation - for (Int_t jPost = 1; jPost <= nPost; jPost++) { - Relax2D(*matricesCurrentV, *matricesCurrentCharge, tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, - coefficient2); - } // end post smoothing - - //// DEBUG //// - //Info("VCycle2D",Form("Count %d", count)); - //Info("VCycle2D",Form("Exact Err: %f, MG Iteration : %d", (*fError)(mgCycle), mgCycle)); - //matricesCurrentV->Print(); - //matricesCurrentCharge->Print(); - } -} - -/// W-Cycle 2D -/// -/// Implementation non-recursive W-cycle for 2D -/// -/// Algorithms: -/// -/// \param nRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param nZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param gridFrom const Int_t finest level of grid -/// \param gridTo const Int_t coarsest level of grid -/// \param gamma const Int_t number of iterations at coarsest level -/// \param nPre const Int_t number of smoothing before coarsening -/// \param nPost const Int_t number of smoothing after coarsening -/// \param gridSizeR const Float_t grid size in r direction (OPTION, recalculate) -/// \param ratio const Float_t ratio between square of grid r and grid z (OPTION, recalculate) -/// \param tvArrayV vector<TMatrixD *> vector of V potential in different grids -/// \param tvCharge vector<TMatrixD *> vector of charge distribution in different grids -/// \param tvResidue vector<TMatrixD *> vector of residue calculation in different grids -/// -void AliTPCPoissonSolver::WCycle2D(const Int_t nRRow, const Int_t nZColumn, const Int_t gridFrom, const Int_t gridTo, - const int gamma, - const Int_t nPre, const Int_t nPost, const Float_t gridSizeR, const Float_t ratio, - std::vector<TMatrixD*>& tvArrayV, - std::vector<TMatrixD*>& tvCharge, std::vector<TMatrixD*>& tvResidue) -{ - - Float_t h, h2, ih2, tempRatio, tempFourth, inverseTempFourth, radius; - TMatrixD *matricesCurrentV, *matricesCurrentVC; - TMatrixD* matricesCurrentCharge; - TMatrixD* residue; - Int_t iOne, jOne, tnRRow, tnZColumn, count; - iOne = 1 << (gridFrom - 1); - jOne = 1 << (gridFrom - 1); - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - std::vector<float> coefficient1(nRRow); - std::vector<float> coefficient2(nZColumn); - - // 1) Go to coarsest level - for (count = gridFrom; count <= gridTo - 2; count++) { - h = gridSizeR * iOne; - h2 = h * h; - ih2 = 1.0 / h2; - tempRatio = ratio * iOne * iOne / (jOne * jOne); - tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); - inverseTempFourth = 1.0 / tempFourth; - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - } - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentCharge = tvCharge[count - 1]; - residue = tvResidue[count - 1]; - - // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi - for (Int_t jPre = 1; jPre <= nPre; jPre++) { - Relax2D(*matricesCurrentV, *matricesCurrentCharge, tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, - coefficient2); - } - - // 2) Residue calculation - Residue2D(*residue, *matricesCurrentV, *matricesCurrentCharge, tnRRow, tnZColumn, ih2, inverseTempFourth, tempRatio, - coefficient1, - coefficient2); - - iOne = 2 * iOne; - jOne = 2 * jOne; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - matricesCurrentCharge = tvCharge[count]; - matricesCurrentV = tvArrayV[count]; - - //3) Restriction - Restrict2D(*matricesCurrentCharge, *residue, tnRRow, tnZColumn); - - //4) Zeroing coarser V - matricesCurrentV->Zero(); - } - - // Do V cycle from: gridTo-1 to gridTo gamma times - for (Int_t iGamma = 0; iGamma < gamma; iGamma++) { - VCycle2D(nRRow, nZColumn, gridTo - 1, gridTo, - nPre, nPost, gridSizeR, ratio, tvArrayV, - tvCharge, tvResidue); - } - - // Go to finest grid - for (count = gridTo - 2; count >= gridFrom; count--) { - - iOne = iOne / 2; - jOne = jOne / 2; - - h = gridSizeR * iOne; - h2 = h * h; - ih2 = 1.0 / h2; - tempRatio = ratio * iOne * iOne / (jOne * jOne); - tempFourth = 1.0 / (2.0 + 2.0 * tempRatio); - inverseTempFourth = 1.0 / tempFourth; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - matricesCurrentCharge = tvCharge[count - 1]; - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentVC = tvArrayV[count]; - - // 6) Interpolation/Prolongation - AddInterp2D(*matricesCurrentV, *matricesCurrentVC, tnRRow, tnZColumn); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - } - - // 7) Post-Smoothing: Gauss-Seidel Relaxation - for (Int_t jPost = 1; jPost <= nPost; jPost++) { - Relax2D(*matricesCurrentV, *matricesCurrentCharge, tnRRow, tnZColumn, h2, tempFourth, tempRatio, coefficient1, - coefficient2); - } // end post smoothing - } -} - -/// VCycle 3D2D, V Cycle 3D in multiGrid with constant phiSlice -/// fine-->coarsest-->fine, propagating the residue to correct initial guess of V -/// -/// Algorithm: -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// The number of nRRow and Z Column can be different. -/// -/// R Row == 2**M + 1 -/// Z Column == 2**N + 1 -/// Phi Slice == Arbitrary but greater than 3 -/// -/// DeltaPhi in Radians -/// \param nRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param nZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param gridFrom const Int_t finest level of grid -/// \param gridTo const Int_t coarsest level of grid -/// \param nPre const Int_t number of smoothing before coarsening -/// \param nPost const Int_t number of smoothing after coarsening -/// \param gridSizeR const Float_t grid size in r direction (OPTION, recalculate) -/// \param ratio const Float_t ratio between square of grid r and grid z (OPTION, recalculate) -/// \param tvArrayV vector<TMatrixD *> vector of V potential in different grids -/// \param tvCharge vector<TMatrixD *> vector of charge distribution in different grids -/// \param tvResidue vector<TMatrixD *> vector of residue calculation in different grids -/// \param coefficient1 std::vector<float>& coefficient for relaxation (r direction) -/// \param coefficient2 std::vector<float>& coefficient for relaxation (r direction) -/// \param coefficient3 std::vector<float>& coefficient for relaxation (ratio r/z) -/// \param coefficient4 std::vector<float>& coefficient for relaxation (ratio for grid_r) -/// \param inverseCoefficient4 std::vector<float>& coefficient for relaxation (inverse coefficient4) -/// -void AliTPCPoissonSolver::VCycle3D2D(const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t symmetry, - const Int_t gridFrom, const Int_t gridTo, const Int_t nPre, const Int_t nPost, - const Float_t gridSizeR, const Float_t ratioZ, const Float_t ratioPhi, - std::vector<TMatrixD**>& tvArrayV, std::vector<TMatrixD**>& tvCharge, - std::vector<TMatrixD**>& tvResidue, std::vector<float>& coefficient1, - std::vector<float>& coefficient2, std::vector<float>& coefficient3, - std::vector<float>& coefficient4, - std::vector<float>& inverseCoefficient4) -{ - - Float_t h, h2, ih2, tempRatioZ, tempRatioPhi, radius; - TMatrixD **matricesCurrentV, **matricesCurrentVC; - TMatrixD** matricesCurrentCharge; - TMatrixD** residue; - Int_t iOne, jOne, tnRRow, tnZColumn, count; - - matricesCurrentV = nullptr; - matricesCurrentVC = nullptr; - matricesCurrentCharge = nullptr; - residue = nullptr; - - iOne = 1 << (gridFrom - 1); - jOne = 1 << (gridFrom - 1); - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - for (count = gridFrom; count <= gridTo - 1; count++) { - h = gridSizeR * iOne; - h2 = h * h; - ih2 = 1.0 / h2; - - tempRatioPhi = ratioPhi * iOne * iOne; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - inverseCoefficient4[i] = 1.0 / coefficient4[i]; - } - - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentCharge = tvCharge[count - 1]; - residue = tvResidue[count - 1]; - - //Info("VCycle3D2D","Before Pre-smoothing"); - //matricesCurrentV->Print(); - - // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi - for (Int_t jPre = 1; jPre <= nPre; jPre++) { - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, h2, tempRatioZ, - coefficient1, coefficient2, - coefficient3, coefficient4); - } // end pre smoothing - - // 2) Residue calculation - Residue3D(residue, matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, ih2, tempRatioZ, - coefficient1, - coefficient2, - coefficient3, inverseCoefficient4); - - iOne = 2 * iOne; - jOne = 2 * jOne; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - matricesCurrentCharge = tvCharge[count]; - matricesCurrentV = tvArrayV[count]; - - //3) Restriction - //Restrict2D(*matricesCurrentCharge,*residue,tnRRow,tnZColumn); - Restrict3D(matricesCurrentCharge, residue, tnRRow, tnZColumn, phiSlice, phiSlice); - - //4) Zeroing coarser V - for (Int_t m = 0; m < phiSlice; m++) { - matricesCurrentV[m]->Zero(); - } - } - - // coarsest grid - h = gridSizeR * iOne; - h2 = h * h; - - tempRatioPhi = ratioPhi * iOne * iOne; - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - - // 3) Relax on the coarsest grid - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, h2, tempRatioZ, coefficient1, - coefficient2, - coefficient3, coefficient4); - - // back to fine - for (count = gridTo - 1; count >= gridFrom; count--) { - iOne = iOne / 2; - jOne = jOne / 2; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - h = gridSizeR * iOne; - h2 = h * h; - - tempRatioPhi = ratioPhi * iOne * iOne; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - matricesCurrentCharge = tvCharge[count - 1]; - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentVC = tvArrayV[count]; - - // 4) Interpolation/Prolongation - AddInterp3D(matricesCurrentV, matricesCurrentVC, tnRRow, tnZColumn, phiSlice, phiSlice); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - - // 5) Post-Smoothing: Gauss-Seidel Relaxation - for (Int_t jPost = 1; jPost <= nPost; jPost++) { - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, h2, tempRatioZ, - coefficient1, coefficient2, - coefficient3, coefficient4); - } // end post smoothing - } -} - -/// VCycle 3D, V Cycle in multiGrid, fine-->coarsest-->fine, propagating the residue to correct initial guess of V -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// The number of nRRow and Z Column can be different. -/// -/// R Row == 2**M + 1 -/// Z Column == 2**N + 1 -/// Phi Slice == Arbitrary but greater than 3 -/// -/// DeltaPhi in Radians -/// -/// \param nRRow Int_t number of nRRow in the r direction of TPC -/// \param nZColumn Int_t number of nZColumn in z direction of TPC -/// \param phiSlice Int_t number of phiSlice in phi direction of T{C -/// \param symmetry Int_t symmetry or not -/// \param gridFrom const Int_t finest level of grid -/// \param gridTo const Int_t coarsest level of grid -/// \param nPre const Int_t number of smoothing before coarsening -/// \param nPost const Int_t number of smoothing after coarsening -/// \param gridSizeR const Float_t grid size in r direction (OPTION, recalculate) -/// \param ratioz const Float_t ratio between square of grid r and grid z (OPTION, recalculate) -/// \param tvArrayV vector<TMatrixD *> vector of V potential in different grids -/// \param tvCharge vector<TMatrixD *> vector of charge distribution in different grids -/// \param tvResidue vector<TMatrixD *> vector of residue calculation in different grids -/// \param coefficient1 std::vector<float>& coefficient for relaxation (r direction) -/// \param coefficient2 std::vector<float>& coefficient for relaxation (r direction) -/// \param coefficient3 std::vector<float>& coefficient for relaxation (ratio r/z) -/// \param coefficient4 std::vector<float>& coefficient for relaxation (ratio for grid_r) -/// \param inverseCoefficient4 std::vector<float>& coefficient for relaxation (inverse coefficient4) -/// -void AliTPCPoissonSolver::VCycle3D(const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t symmetry, - const Int_t gridFrom, const Int_t gridTo, - const Int_t nPre, const Int_t nPost, const Float_t gridSizeR, const Float_t ratioZ, - std::vector<TMatrixD**>& tvArrayV, std::vector<TMatrixD**>& tvCharge, - std::vector<TMatrixD**>& tvResidue, - std::vector<float>& coefficient1, std::vector<float>& coefficient2, - std::vector<float>& coefficient3, - std::vector<float>& coefficient4, std::vector<float>& inverseCoefficient4) -{ - - Float_t h, h2, ih2, tempRatioZ, tempRatioPhi, radius, tempGridSizePhi; - TMatrixD **matricesCurrentV, **matricesCurrentVC; - TMatrixD** matricesCurrentCharge; - TMatrixD** residue; - Int_t iOne, jOne, kOne, tnRRow, tnZColumn, tPhiSlice, otPhiSlice, count, nnPhi; - - matricesCurrentV = nullptr; - matricesCurrentVC = nullptr; - matricesCurrentCharge = nullptr; - residue = nullptr; - - iOne = 1 << (gridFrom - 1); - jOne = 1 << (gridFrom - 1); - kOne = 1 << (gridFrom - 1); - - nnPhi = phiSlice; - - while (nnPhi % 2 == 0) { - nnPhi /= 2; - } - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tPhiSlice = kOne == 1 ? phiSlice : phiSlice / kOne; - tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; - - //Info("VCycle3D",Form("Grid information: tnRRow=%d, tcols=%d, tPhiSlice=%d\n", tnRRow,tnZColumn,tPhiSlice)); - - for (count = gridFrom; count <= gridTo - 1; count++) { - otPhiSlice = tPhiSlice; - - h = gridSizeR * iOne; - h2 = h * h; - ih2 = 1.0 / h2; - tempGridSizePhi = TMath::TwoPi() / tPhiSlice; // phi now is multiGrid - - tempRatioPhi = h * h / (tempGridSizePhi * tempGridSizePhi); // ratio_{phi} = gridSize_{r} / gridSize_{phi} - - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - inverseCoefficient4[i] = 1.0 / coefficient4[i]; - } - - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentCharge = tvCharge[count - 1]; - residue = tvResidue[count - 1]; - - //Info("VCycle3D","Before Pre-smoothing"); - //matricesCurrentV->Print(); - - // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi - for (Int_t jPre = 1; jPre <= nPre; jPre++) { - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, - coefficient1, coefficient2, coefficient3, coefficient4); - } // end pre smoothing - - // 2) Residue calculation - - Residue3D(residue, matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, tPhiSlice, symmetry, ih2, tempRatioZ, - coefficient1, coefficient2, coefficient3, inverseCoefficient4); - - iOne = 2 * iOne; - jOne = 2 * jOne; - kOne = 2 * kOne; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tPhiSlice = phiSlice / kOne; - tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; - - matricesCurrentCharge = tvCharge[count]; - matricesCurrentV = tvArrayV[count]; - //3) Restriction - Restrict3D(matricesCurrentCharge, residue, tnRRow, tnZColumn, tPhiSlice, otPhiSlice); - - //4) Zeroing coarser V - for (Int_t m = 0; m < tPhiSlice; m++) { - matricesCurrentV[m]->Zero(); - } - } - - // coarsest grid - h = gridSizeR * iOne; - h2 = h * h; - tempGridSizePhi = TMath::TwoPi() / tPhiSlice; // phi now is multiGrid - - tempRatioPhi = h * h / (tempGridSizePhi * tempGridSizePhi); // ratio_{phi} = gridSize_{r} / gridSize_{phi} - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - - // 3) Relax on the coarsest grid - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, coefficient1, - coefficient2, coefficient3, coefficient4); - - // back to fine - for (count = gridTo - 1; count >= gridFrom; count--) { - otPhiSlice = tPhiSlice; - - iOne = iOne / 2; - jOne = jOne / 2; - kOne = kOne / 2; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - tPhiSlice = kOne == 1 ? phiSlice : phiSlice / kOne; - tPhiSlice = tPhiSlice < nnPhi ? nnPhi : tPhiSlice; - - h = gridSizeR * iOne; - h2 = h * h; - tempGridSizePhi = TMath::TwoPi() / tPhiSlice; // phi now is multiGrid - - tempRatioPhi = h * h / (tempGridSizePhi * tempGridSizePhi); // ratio_{phi} = gridSize_{r} / gridSize_{phi} - - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - matricesCurrentCharge = tvCharge[count - 1]; - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentVC = tvArrayV[count]; - - // 4) Interpolation/Prolongation - - AddInterp3D(matricesCurrentV, matricesCurrentVC, tnRRow, tnZColumn, tPhiSlice, otPhiSlice); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - - // 5) Post-Smoothing: Gauss-Seidel Relaxation - for (Int_t jPost = 1; jPost <= nPost; jPost++) { - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, tPhiSlice, symmetry, h2, tempRatioZ, - coefficient1, coefficient2, - coefficient3, coefficient4); - } - } -} - -/// -/// Set matrix exact solution for relative error calculation -/// -/// \param exactSolution TMatrixD** pointer to exact solution (potential) in 3D -/// \param fPhiSlices const Int_t number of phi slices -/// -void AliTPCPoissonSolver::SetExactSolution(TMatrixD** exactSolution, const Int_t fPhiSlices) -{ - Double_t maxAbs; - fExactSolution = exactSolution; - fExactPresent = kTRUE; - fMaxExact = 0.0; - for (Int_t m = 0; m < fPhiSlices; m++) { - maxAbs = TMath::Max(TMath::Abs((*fExactSolution[m]).Max()), TMath::Abs((*fExactSolution[m]).Min())); - if (maxAbs > fMaxExact) { - fMaxExact = maxAbs; - } - } -} - -/// -/// Relative error calculation: comparison with exact solution -/// -/// \param matricesCurrentV TMatrixD** current potential (numerical solution) -/// \param tempArrayV TMatrixD** temporary matrix for calculating error -/// \param nRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param nZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param phiSlice const Int_t phi slices -/// -Double_t AliTPCPoissonSolver::GetExactError(TMatrixD** matricesCurrentV, TMatrixD** tempArrayV, const Int_t phiSlice) -{ - Double_t error = 0.0; - - if (fExactPresent == kTRUE) { - for (Int_t m = 0; m < phiSlice; m++) { - (*tempArrayV[m]) = (*fExactSolution[m]) - (*matricesCurrentV[m]); - (*tempArrayV[m]) *= 1.0 / GetMaxExact(); - if (tempArrayV[m]->E2Norm() > error) { - error = tempArrayV[m]->E2Norm(); - } - //printf("%f\n",tempArrayV[m]->E2Norm(); - } - } - return error; -} - -/// -/// Relative error calculation: comparison with exact solution -/// -/// \param matricesCurrentV TMatrixD** current potential (numerical solution) -/// \param tempArrayV TMatrixD** temporary matrix for calculating error -/// \param nRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param nZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param phiSlice const Int_t phi slices -/// -Double_t - AliTPCPoissonSolver::GetConvergenceError(TMatrixD** matricesCurrentV, TMatrixD** prevArrayV, const Int_t phiSlice) -{ - Double_t error = 0.0; - - for (Int_t m = 0; m < phiSlice; m++) { - - // absolute - (*prevArrayV[m]) = (*prevArrayV[m]) - (*matricesCurrentV[m]); - - if (prevArrayV[m]->E2Norm() > error) { - error = prevArrayV[m]->E2Norm(); - } - } - return error; -} - -///////////////////// interface for GPU /////////////////// - -/// VCycle 3D2D, V Cycle 3D in multiGrid with constant phiSlice -/// fine-->coarsest-->fine, propagating the residue to correct initial guess of V -/// -/// Algorithm: -/// -/// NOTE: In order for this algorithm to work, the number of nRRow and nZColumn must be a power of 2 plus one. -/// The number of nRRow and Z Column can be different. -/// -/// R Row == 2**M + 1 -/// Z Column == 2**N + 1 -/// Phi Slice == Arbitrary but greater than 3 -/// -/// DeltaPhi in Radians -/// \param nRRow Int_t number of grid in nRRow (in r-direction) for coarser grid should be 2^N + 1, finer grid in 2^{N+1} + 1 -/// \param nZColumn Int_t number of grid in nZColumn (in z-direction) for coarser grid should be 2^M + 1, finer grid in 2^{M+1} + 1 -/// \param gridFrom const Int_t finest level of grid -/// \param gridTo const Int_t coarsest level of grid -/// \param nPre const Int_t number of smoothing before coarsening -/// \param nPost const Int_t number of smoothing after coarsening -/// \param gridSizeR const Float_t grid size in r direction (OPTION, recalculate) -/// \param ratio const Float_t ratio between square of grid r and grid z (OPTION, recalculate) -/// \param tvArrayV vector<TMatrixD *> vector of V potential in different grids -/// \param tvCharge vector<TMatrixD *> vector of charge distribution in different grids -/// \param tvResidue vector<TMatrixD *> vector of residue calculation in different grids -/// \param coefficient1 std::vector<float>& coefficient for relaxation (r direction) -/// \param coefficient2 std::vector<float>& coefficient for relaxation (r direction) -/// \param coefficient3 std::vector<float>& coefficient for relaxation (ratio r/z) -/// \param coefficient4 std::vector<float>& coefficient for relaxation (ratio for grid_r) -/// \param inverseCoefficient4 std::vector<float>& coefficient for relaxation (inverse coefficient4) -/// -void AliTPCPoissonSolver::VCycle3D2DGPU( - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t symmetry, - const Int_t gridFrom, const Int_t gridTo, const Int_t nPre, const Int_t nPost, const Float_t gridSizeR, - const Float_t ratioZ, const Float_t ratioPhi, std::vector<TMatrixD**>& tvArrayV, - std::vector<TMatrixD**>& tvCharge, std::vector<TMatrixD**>& tvResidue, std::vector<float>& coefficient1, - std::vector<float>& coefficient2, std::vector<float>& coefficient3, std::vector<float>& coefficient4, - std::vector<float>& inverseCoefficient4) -{ - Float_t h, h2, ih2, tempRatioZ, tempRatioPhi, radius; - TMatrixD **matricesCurrentV, **matricesCurrentVC; - TMatrixD** matricesCurrentCharge; - TMatrixD** residue; - Int_t iOne, jOne, tnRRow, tnZColumn, count; - - matricesCurrentV = nullptr; - matricesCurrentVC = nullptr; - matricesCurrentCharge = nullptr; - residue = nullptr; - - iOne = 1 << (gridFrom - 1); - jOne = 1 << (gridFrom - 1); - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - for (count = gridFrom; count <= gridTo - 1; count++) { - h = gridSizeR * iOne; - h2 = h * h; - ih2 = 1.0 / h2; - - tempRatioPhi = ratioPhi * iOne * iOne; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - inverseCoefficient4[i] = 1.0 / coefficient4[i]; - } - - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentCharge = tvCharge[count - 1]; - residue = tvResidue[count - 1]; - - //Info("VCycle3D2DGPU","Before Pre-smoothing"); - //matricesCurrentV->Print(); - - // 1) Pre-Smoothing: Gauss-Seidel Relaxation or Jacobi - for (Int_t jPre = 1; jPre <= nPre; jPre++) { - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, h2, tempRatioZ, - coefficient1, coefficient2, - coefficient3, coefficient4); - } // end pre smoothing - - // 2) Residue calculation - Residue3D(residue, matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, ih2, tempRatioZ, - coefficient1, - coefficient2, - coefficient3, inverseCoefficient4); - - iOne = 2 * iOne; - jOne = 2 * jOne; - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - matricesCurrentCharge = tvCharge[count]; - matricesCurrentV = tvArrayV[count]; - - //3) Restriction - //Restrict2D(*matricesCurrentCharge,*residue,tnRRow,tnZColumn); - Restrict3D(matricesCurrentCharge, residue, tnRRow, tnZColumn, phiSlice, phiSlice); - - //4) Zeroing coarser V - for (Int_t m = 0; m < phiSlice; m++) { - matricesCurrentV[m]->Zero(); - } - } - - // coarsest grid - h = gridSizeR * iOne; - h2 = h * h; - - tempRatioPhi = ratioPhi * iOne * iOne; - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - - // 3) Relax on the coarsest grid - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, h2, tempRatioZ, coefficient1, - coefficient2, - coefficient3, coefficient4); - - // back to fine - for (count = gridTo - 1; count >= gridFrom; count--) { - iOne = iOne / 2; - jOne = jOne / 2; - - tnRRow = iOne == 1 ? nRRow : nRRow / iOne + 1; - tnZColumn = jOne == 1 ? nZColumn : nZColumn / jOne + 1; - - h = gridSizeR * iOne; - h2 = h * h; - - tempRatioPhi = ratioPhi * iOne * iOne; // Used tobe divided by ( m_one * m_one ) when m_one was != 1 - tempRatioZ = ratioZ * iOne * iOne / (jOne * jOne); - - matricesCurrentCharge = tvCharge[count - 1]; - matricesCurrentV = tvArrayV[count - 1]; - matricesCurrentVC = tvArrayV[count]; - - // 4) Interpolation/Prolongation - AddInterp3D(matricesCurrentV, matricesCurrentVC, tnRRow, tnZColumn, phiSlice, phiSlice); - - for (Int_t i = 1; i < tnRRow - 1; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * h; - coefficient1[i] = 1.0 + h / (2 * radius); - coefficient2[i] = 1.0 - h / (2 * radius); - coefficient3[i] = tempRatioPhi / (radius * radius); - coefficient4[i] = 0.5 / (1.0 + tempRatioZ + coefficient3[i]); - } - - // 5) Post-Smoothing: Gauss-Seidel Relaxation - for (Int_t jPost = 1; jPost <= nPost; jPost++) { - Relax3D(matricesCurrentV, matricesCurrentCharge, tnRRow, tnZColumn, phiSlice, symmetry, h2, tempRatioZ, - coefficient1, coefficient2, - coefficient3, coefficient4); - } // end post smoothing - } -} diff --git a/GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.h b/GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.h deleted file mode 100644 index 5aead1e7b555c..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCPoissonSolver.h +++ /dev/null @@ -1,219 +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. - -/// \file AliTPCPoissonSolver.h -/// \brief This class provides implementation of Poisson Eq -/// solver by MultiGrid Method -/// -/// -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Nov 20, 2017 - -#ifndef ALITPCPOISSONSOLVER_H -#define ALITPCPOISSONSOLVER_H - -#include <TNamed.h> -#include "TMatrixD.h" -#include "TVectorD.h" - -class AliTPCPoissonSolver : public TNamed -{ - public: - ///< Enumeration of Poisson Solver Strategy Type - enum StrategyType { - kRelaxation = 0, ///< S.O.R Cascaded MultiGrid - kMultiGrid = 1, ///< Geometric MG - kFastRelaxation = 2 ///< Spectral (TODO) - }; - - ///< Enumeration of Cycles Type - enum CycleType { - kVCycle = 0, ///< V Cycle - kWCycle = 1, ///< W Cycle (TODO) - kFCycle = 2 ///< Full Cycle - }; - - ///< Fine -> Coarse Grid transfer operator types - enum GridTransferType { - kHalf = 0, ///< Half weighting - kFull = 1, ///< Full weighting - }; - - ///< Smoothing (Relax) operator types - enum RelaxType { - kJacobi = 0, ///< Jacobi (5 Stencil 2D, 7 Stencil 3D_ - kWeightedJacobi = 1, ///< (TODO) - kGaussSeidel = 2 ///< Gauss Seidel 2D (2 Color, 5 Stencil), 3D (7 Stencil) - }; - - ///< Coarse -> fine operator types (TODO: Interp and Restrict in one packet, just one enumeration) - enum InterpType { - kHalfInterp = 0, ///< Half bi linear interpolation - kFullInterp = 1 ///< Full bi linear interpolation - }; - - ///< Parameters choice for MultiGrid algorithm - struct MGParameters { - Bool_t isFull3D; ///< TRUE: full coarsening, FALSE: semi coarsening - CycleType cycleType; ///< cycleType follow CycleType - GridTransferType gtType; ///< gtType grid transfer type follow GridTransferType - RelaxType relaxType; ///< relaxType follow RelaxType - Int_t gamma; ///< number of iteration at coarsest level - Int_t nPre; ///< number of iteration for pre smoothing - Int_t nPost; ///< number of iteration for post smoothing - Int_t nMGCycle; ///< number of multi grid cycle (V type) - Int_t maxLoop; ///< the number of tree-deep of multi grid - - // default values - MGParameters() - { - isFull3D = kFALSE; - cycleType = kFCycle; - gtType = kFull; // default full - relaxType = kGaussSeidel; // default relaxation method - nPre = 2; - nPost = 2; - nMGCycle = 200; - maxLoop = 6; - } - }; - - AliTPCPoissonSolver(); - AliTPCPoissonSolver(const char* name, const char* title); -#if (defined(__CINT__) || defined(__ROOTCINT__)) && !defined(__CLING__) - ~AliTPCPoissonSolver(); -#else - ~AliTPCPoissonSolver() override; -#endif - void PoissonSolver2D(TMatrixD& matrixV, TMatrixD& chargeDensity, Int_t nRRow, Int_t nZColumn, Int_t maxIterations); - void PoissonSolver3D(TMatrixD** matricesV, TMatrixD** matricesChargeDensities, Int_t nRRow, Int_t nZColumn, - Int_t phiSlice, Int_t maxIterations, Int_t symmetry); - - void SetStrategy(StrategyType strategy) { fStrategy = strategy; } - StrategyType GetStrategy() { return fStrategy; } - - static const Double_t fgkTPCZ0; ///< nominal gating grid position - static const Double_t fgkIFCRadius; ///< Mean Radius of the Inner Field Cage ( 82.43 min, 83.70 max) (cm) - static const Double_t fgkOFCRadius; ///< Mean Radius of the Outer Field Cage (252.55 min, 256.45 max) (cm) - static const Double_t fgkZOffSet; ///< Offset from CE: calculate all distortions closer to CE as if at this point - static const Double_t fgkCathodeV; ///< Cathode Voltage (volts) - static const Double_t fgkGG; ///< Gating Grid voltage (volts) - static const Double_t fgkdvdE; ///< [cm/V] drift velocity dependency on the E field (from Magboltz for NeCO2N2 at standard environment) - static const Double_t fgkEM; ///< charge/mass in [C/kg] - static const Double_t fgke0; ///< vacuum permittivity [A·s/(V·m)] - - static Double_t fgExactErr; ///< Error tolerated - static Double_t fgConvergenceError; ///< Error tolerated - Int_t fIterations; ///< number of maximum iteration - MGParameters fMgParameters; ///< parameters multi grid - - void SetExactSolution(TMatrixD** exactSolution, const Int_t fPhiSlices); - void SetCycleType(AliTPCPoissonSolver::CycleType cycleType) { fMgParameters.cycleType = cycleType; } - - private: - AliTPCPoissonSolver(const AliTPCPoissonSolver&); // not implemented - AliTPCPoissonSolver& operator=(const AliTPCPoissonSolver&); // not implemented - StrategyType fStrategy = kMultiGrid; ///< strategy used default multiGrid - TMatrixD** fExactSolution = nullptr; //!<! Pointer to exact solution - /// TODO: remove pointers? - TVectorD* fErrorConvergenceNorm2; ///< for storing convergence error norm2 - TVectorD* fErrorConvergenceNormInf; ///< for storing convergence error normInf - TVectorD* fError; ///< for storing error - Double_t GetMaxExact() { return fMaxExact; }; - - void PoissonRelaxation2D(TMatrixD& matrixV, TMatrixD& chargeDensity, Int_t nRRow, Int_t nZColumn, - Int_t maxIterations); - void PoissonRelaxation3D(TMatrixD** matricesV, TMatrixD** matricesChargeDensities, Int_t nRRow, - Int_t nZColumn, Int_t phiSlice, Int_t maxIterations, Int_t symmetry); - void PoissonMultiGrid2D(TMatrixD& matrixV, TMatrixD& chargeDensity, Int_t nRRow, Int_t nZColumn); - void PoissonMultiGrid3D2D(TMatrixD** matricesV, TMatrixD** matricesChargeDensities, Int_t nRRow, - Int_t nZColumn, Int_t phiSlice, Int_t symmetry); - void PoissonMultiGrid3D(TMatrixD** matricesV, TMatrixD** matricesChargeDensities, Int_t nRRow, - Int_t nZColumn, Int_t phiSlice, Int_t symmetry); - Int_t IsPowerOfTwo(Int_t i) const; - void Relax2D(TMatrixD& matrixV, TMatrixD& matrixCharge, const Int_t tnRRow, const Int_t tnZColumn, - const Float_t h2, const Float_t tempFourth, const Float_t tempRatio, - std::vector<float>& vectorCoefficient1, - std::vector<float>& vectorCoefficient2); - void Relax3D(TMatrixD** currentMatricesV, TMatrixD** matricesCharge, const Int_t tnRRow, const Int_t tnZColumn, - const Int_t phiSlice, const Int_t symmetry, const Float_t h2, const Float_t tempRatioZ, - std::vector<float>& vectorCoefficient1, std::vector<float>& vectorCoefficient2, - std::vector<float>& vectorCoefficient3, - std::vector<float>& vectorCoefficient4); - void Residue2D(TMatrixD& residue, TMatrixD& matrixV, TMatrixD& matrixCharge, - const Int_t tnRRow, const Int_t tnZColumn, const Float_t ih2, const Float_t iTempFourth, - const Float_t tempRatio, std::vector<float>& vectorCoefficient1, - std::vector<float>& vectorCoefficient2); - void Residue3D(TMatrixD** residue, TMatrixD** currentMatricesV, TMatrixD** matricesCharge, const Int_t tnRRow, - const Int_t tnZColumn, const Int_t phiSlice, const Int_t symmetry, const Float_t ih2, - const Float_t tempRatio, std::vector<float>& vectorCoefficient1, - std::vector<float>& vectorCoefficient2, - std::vector<float>& vectorCoefficient3, std::vector<float>& vectorInverseCoefficient4); - void Restrict2D(TMatrixD& matrixCharge, TMatrixD& residue, const Int_t tnRRow, const Int_t tnZColumn); - void Restrict3D(TMatrixD** matricesCharge, TMatrixD** residue, const Int_t tnRRow, const Int_t tnZColumn, - const Int_t newPhiSlice, const Int_t oldPhiSlice); - void RestrictBoundary2D(TMatrixD& matrixCharge, TMatrixD& residue, const Int_t tnRRow, const Int_t tnZColumn); - void RestrictBoundary3D(TMatrixD** matricesCharge, TMatrixD** residue, const Int_t tnRRow, const Int_t tnZColumn, - const Int_t newPhiSlice, const Int_t oldPhiSlice); - - void AddInterp2D(TMatrixD& matrixV, TMatrixD& matrixVC, const Int_t tnRRow, const Int_t tnZColumn); - void AddInterp3D(TMatrixD** currentMatricesV, TMatrixD** currentMatricesVC, const Int_t tnRRow, const Int_t tnZColumn, - const Int_t newPhiSlice, const Int_t oldPhiSlice); - void Interp2D(TMatrixD& matrixV, TMatrixD& matrixVC, const Int_t tnRRow, const Int_t tnZColumn); - - void Interp3D(TMatrixD** currentMatricesV, TMatrixD** currentMatricesVC, const Int_t tnRRow, const Int_t tnZColumn, - const Int_t newPhiSlice, const Int_t oldPhiSlice); - void VCycle2D(const Int_t nRRow, const Int_t nZColumn, const Int_t gridFrom, const Int_t gridTo, const Int_t nPre, - const Int_t nPost, const Float_t gridSizeR, const Float_t ratio, std::vector<TMatrixD*>& tvArrayV, - std::vector<TMatrixD*>& tvCharge, std::vector<TMatrixD*>& tvResidue); - void WCycle2D(const Int_t nRRow, const Int_t nZColumn, const Int_t gridFrom, const Int_t gridTo, const Int_t gamma, - const Int_t nPre, const Int_t nPost, const Float_t gridSizeR, const Float_t ratio, - std::vector<TMatrixD*>& tvArrayV, - std::vector<TMatrixD*>& tvCharge, std::vector<TMatrixD*>& tvResidue); - void - VCycle3D(const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t symmetry, const Int_t gridFrom, - const Int_t gridTo, const Int_t nPre, const Int_t nPost, const Float_t gridSizeR, const Float_t ratioZ, - std::vector<TMatrixD**>& tvArrayV, std::vector<TMatrixD**>& tvCharge, - std::vector<TMatrixD**>& tvResidue, std::vector<float>& vectorCoefficient1, - std::vector<float>& vectorCoefficient2, - std::vector<float>& vectorCoefficient3, std::vector<float>& vectorCoefficient4, - std::vector<float>& vectorInverseCoefficient4); - void VCycle3D2D(const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t symmetry, - const Int_t gridFrom, const Int_t gridTo, const Int_t nPre, const Int_t nPost, - const Float_t gridSizeR, - const Float_t ratioZ, const Float_t ratioPhi, std::vector<TMatrixD**>& tvArrayV, - std::vector<TMatrixD**>& tvCharge, std::vector<TMatrixD**>& tvResidue, - std::vector<float>& vectorCoefficient1, - std::vector<float>& vectorCoefficient2, std::vector<float>& vectorCoefficient3, - std::vector<float>& vectorCoefficient4, - std::vector<float>& vectorInverseCoefficient4); - void VCycle3D2DGPU(const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t symmetry, - const Int_t gridFrom, const Int_t gridTo, const Int_t nPre, - const Int_t nPost, const Float_t gridSizeR, const Float_t ratioZ, const Float_t ratioPhi, - std::vector<TMatrixD**>& tvArrayV, std::vector<TMatrixD**>& tvCharge, - std::vector<TMatrixD**>& tvResidue, std::vector<float>& vectorCoefficient1, - std::vector<float>& vectorCoefficient2, - std::vector<float>& vectorCoefficient3, std::vector<float>& vectorCoefficient4, - std::vector<float>& vectorInverseCoefficient4); - Double_t GetExactError(TMatrixD** currentMatricesV, TMatrixD** tempArrayV, const Int_t phiSlice); - Double_t GetConvergenceError(TMatrixD** currentMatricesV, TMatrixD** prevArrayV, const Int_t phiSlice); - Double_t fMaxExact; - Bool_t fExactPresent = kFALSE; - /// \cond CLASSIMP -#if defined(ROOT_VERSION_CODE) && ROOT_VERSION_CODE >= ROOT_VERSION(6, 0, 0) - ClassDefOverride(AliTPCPoissonSolver, 5); -#else - ClassDefNV(AliTPCPoissonSolver, 5); -#endif - /// \endcond -}; - -#endif diff --git a/GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.cxx b/GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.cxx deleted file mode 100644 index 14dea14dbc555..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.cxx +++ /dev/null @@ -1,5315 +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. - -/// \file AliTPCSpaceCharge3DCalc.cxx -/// \brief This class provides distortion and correction map with integration following electron drift -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Nov 20, 2017 - -#include "TStopwatch.h" -#include "TMath.h" -#include "AliTPCSpaceCharge3DCalc.h" - -/// \cond CLASSIMP -ClassImp(AliTPCSpaceCharge3DCalc); -/// \endcond - -/// Construction for AliTPCSpaceCharge3DCalc class -/// Default values -/// ~~~ -/// fInterpolationOrder = 5; // interpolation cubic spline with 5 points -/// fNRRows = 129; -/// fNPhiSlices = 180; // the maximum of phi-slices so far = (8 per sector) -/// fNZColumns = 129; // the maximum on column-slices so ~ 2cm slicing -/// ~~~ -AliTPCSpaceCharge3DCalc::AliTPCSpaceCharge3DCalc() -{ - InitAllocateMemory(); -} - -/// Member values from params -/// -/// \param nRRow Int_t number of grid in r direction -/// \param nZColumn Int_t number of grid in z direction -/// \param nPhiSlice Int_t number of grid in \f$ \phi \f$ direction -/// -AliTPCSpaceCharge3DCalc::AliTPCSpaceCharge3DCalc(Int_t nRRow, - Int_t nZColumn, Int_t nPhiSlice) - : fNRRows(nRRow), - fNPhiSlices(nPhiSlice), - fNZColumns(nZColumn) -{ - InitAllocateMemory(); -} - -/// Construction for AliTPCSpaceCharge3DCalc class -/// Member values from params -/// -/// \param nRRow Int_t number of grid in r direction -/// \param nZColumn Int_t number of grid in z direction -/// \param nPhiSlice Int_t number of grid in \f$ \phi \f$ direction -/// \param interpolationOrder Int_t order of interpolation -/// \param strategy Int_t strategy for global distortion -/// \param rbfKernelType Int_t strategy for global distortion -/// -AliTPCSpaceCharge3DCalc::AliTPCSpaceCharge3DCalc( - Int_t nRRow, Int_t nZColumn, Int_t nPhiSlice, Int_t interpolationOrder, - Int_t irregularGridSize, Int_t rbfKernelType) - : fNRRows(nRRow), - fNPhiSlices(nPhiSlice), - fNZColumns(nZColumn), - fInterpolationOrder(interpolationOrder), - fIrregularGridSize(irregularGridSize), - fRBFKernelType(rbfKernelType) -{ - InitAllocateMemory(); -} - -/// Memory allocation for working/output memory -/// -void AliTPCSpaceCharge3DCalc::InitAllocateMemory() -{ - fPoissonSolver = new AliTPCPoissonSolver(); - - fListR = new Double_t[fNRRows]; - fListPhi = new Double_t[fNPhiSlices]; - fListZ = new Double_t[fNZColumns]; - fListZA = new Double_t[fNZColumns]; - fListZC = new Double_t[fNZColumns]; - - // allocate for boundary - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // Int_t len = 2 * fNPhiSlices * (fNZColumns + fNRRows) - (4 * fNPhiSlices); - // fListPotentialBoundaryA = new Double_t[len]; - // fListPotentialBoundaryC = new Double_t[len]; - - Int_t phiSlicesPerSector = fNPhiSlices / kNumSector; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (fNRRows - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (fNZColumns - 1); - const Float_t gridSizePhi = TMath::TwoPi() / fNPhiSlices; - - for (Int_t k = 0; k < fNPhiSlices; k++) { - fListPhi[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < fNRRows; i++) { - fListR[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < fNZColumns; j++) { - fListZ[j] = (j * gridSizeZ); - fListZA[j] = (j * gridSizeZ); - fListZC[j] = (j * gridSizeZ); - } - - fMatrixIntDistDrEzA = new TMatrixD*[fNPhiSlices]; - fMatrixIntDistDPhiREzA = new TMatrixD*[fNPhiSlices]; - fMatrixIntDistDzA = new TMatrixD*[fNPhiSlices]; - - fMatrixIntDistDrEzC = new TMatrixD*[fNPhiSlices]; - fMatrixIntDistDPhiREzC = new TMatrixD*[fNPhiSlices]; - fMatrixIntDistDzC = new TMatrixD*[fNPhiSlices]; - - fMatrixErOverEzA = new TMatrixD*[fNPhiSlices]; - fMatrixEPhiOverEzA = new TMatrixD*[fNPhiSlices]; - fMatrixDeltaEzA = new TMatrixD*[fNPhiSlices]; - - fMatrixErOverEzC = new TMatrixD*[fNPhiSlices]; - fMatrixEPhiOverEzC = new TMatrixD*[fNPhiSlices]; - fMatrixDeltaEzC = new TMatrixD*[fNPhiSlices]; - - fMatrixIntCorrDrEzA = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDPhiREzA = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDzA = new TMatrixD*[fNPhiSlices]; - - fMatrixIntCorrDrEzC = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDPhiREzC = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDzC = new TMatrixD*[fNPhiSlices]; - - fMatrixIntCorrDrEzIrregularA = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDPhiREzIrregularA = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDzIrregularA = new TMatrixD*[fNPhiSlices]; - fMatrixRListIrregularA = new TMatrixD*[fNPhiSlices]; - fMatrixPhiListIrregularA = new TMatrixD*[fNPhiSlices]; - fMatrixZListIrregularA = new TMatrixD*[fNPhiSlices]; - - fMatrixIntCorrDrEzIrregularC = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDPhiREzIrregularC = new TMatrixD*[fNPhiSlices]; - fMatrixIntCorrDzIrregularC = new TMatrixD*[fNPhiSlices]; - fMatrixRListIrregularC = new TMatrixD*[fNPhiSlices]; - fMatrixPhiListIrregularC = new TMatrixD*[fNPhiSlices]; - fMatrixZListIrregularC = new TMatrixD*[fNPhiSlices]; - - fMatrixChargeA = new TMatrixD*[fNPhiSlices]; - fMatrixChargeC = new TMatrixD*[fNPhiSlices]; - fMatrixChargeInverseA = new TMatrixD*[fNPhiSlices]; - fMatrixChargeInverseC = new TMatrixD*[fNPhiSlices]; - fMatrixPotentialA = new TMatrixD*[fNPhiSlices]; - fMatrixPotentialC = new TMatrixD*[fNPhiSlices]; - - for (Int_t k = 0; k < fNPhiSlices; k++) { - - fMatrixIntDistDrEzA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntDistDPhiREzA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntDistDzA[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixIntDistDrEzC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntDistDPhiREzC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntDistDzC[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixIntCorrDrEzA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDPhiREzA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDzA[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixIntCorrDrEzC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDPhiREzC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDzC[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixErOverEzA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixEPhiOverEzA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixDeltaEzA[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixErOverEzC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixEPhiOverEzC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixDeltaEzC[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixIntCorrDrEzIrregularA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDPhiREzIrregularA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDzIrregularA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixRListIrregularA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixPhiListIrregularA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixZListIrregularA[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixIntCorrDrEzIrregularC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDPhiREzIrregularC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixIntCorrDzIrregularC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixRListIrregularC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixPhiListIrregularC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixZListIrregularC[k] = new TMatrixD(fNRRows, fNZColumns); - - fMatrixChargeA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixChargeC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixChargeInverseA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixChargeInverseC[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixPotentialA[k] = new TMatrixD(fNRRows, fNZColumns); - fMatrixPotentialC[k] = new TMatrixD(fNRRows, fNZColumns); - } - - fLookupIntDistA = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, fMatrixIntDistDrEzA, fListR, fNPhiSlices, fMatrixIntDistDPhiREzA, fListPhi, - fNZColumns, fMatrixIntDistDzA, fListZA, fInterpolationOrder); - fLookupIntDistC = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, fMatrixIntDistDrEzC, fListR, fNPhiSlices, fMatrixIntDistDPhiREzC, fListPhi, - fNZColumns, fMatrixIntDistDzC, fListZC, fInterpolationOrder); - fLookupIntCorrA = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, fMatrixIntCorrDrEzA, fListR, fNPhiSlices, fMatrixIntCorrDPhiREzA, fListPhi, - fNZColumns, fMatrixIntCorrDzA, fListZA, fInterpolationOrder); - fLookupIntCorrC = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, fMatrixIntCorrDrEzC, fListR, fNPhiSlices, fMatrixIntCorrDPhiREzC, fListPhi, - fNZColumns, fMatrixIntCorrDzC, fListZC, fInterpolationOrder); - - fLookupIntENoDriftA = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, fMatrixErOverEzA, fListR, fNPhiSlices, fMatrixEPhiOverEzA, fListPhi, - fNZColumns, fMatrixDeltaEzA, fListZA, fInterpolationOrder); - fLookupIntENoDriftC = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, fMatrixErOverEzC, fListR, fNPhiSlices, fMatrixEPhiOverEzC, fListPhi, - fNZColumns, fMatrixDeltaEzC, fListZC, fInterpolationOrder); - fLookupIntCorrIrregularA = - new AliTPCLookUpTable3DInterpolatorIrregularD( - fNRRows, fMatrixIntCorrDrEzIrregularA, fMatrixRListIrregularA, fNPhiSlices, - fMatrixIntCorrDPhiREzIrregularA, fMatrixPhiListIrregularA, fNZColumns, - fMatrixIntCorrDzIrregularA, fMatrixZListIrregularA, 2, GetIrregularGridSize(), - GetIrregularGridSize(), GetIrregularGridSize(), 1); - - fLookupIntCorrIrregularC = - new AliTPCLookUpTable3DInterpolatorIrregularD( - fNRRows, fMatrixIntCorrDrEzIrregularC, fMatrixRListIrregularC, fNPhiSlices, - fMatrixIntCorrDPhiREzIrregularC, fMatrixPhiListIrregularC, fNZColumns, - fMatrixIntCorrDzIrregularC, fMatrixZListIrregularC, 2, GetIrregularGridSize(), - GetIrregularGridSize(), GetIrregularGridSize(), 1); - - fInterpolatorChargeA = new AliTPC3DCylindricalInterpolator(); - fInterpolatorChargeC = new AliTPC3DCylindricalInterpolator(); - fInterpolatorPotentialA = new AliTPC3DCylindricalInterpolator(); - fInterpolatorPotentialC = new AliTPC3DCylindricalInterpolator(); - fInterpolatorInverseChargeA = new AliTPC3DCylindricalInterpolator(); - fInterpolatorInverseChargeC = new AliTPC3DCylindricalInterpolator(); - - fInterpolatorChargeA->SetNR(fNRRows); - fInterpolatorChargeA->SetNZ(fNZColumns); - fInterpolatorChargeA->SetNPhi(fNPhiSlices); - fInterpolatorChargeA->SetNGridPoints(); - fInterpolatorChargeA->SetRList(fListR); - fInterpolatorChargeA->SetZList(fListZA); - fInterpolatorChargeA->SetPhiList(fListPhi); - fInterpolatorChargeA->SetOrder(fInterpolationOrder); - - fInterpolatorChargeC->SetNR(fNRRows); - fInterpolatorChargeC->SetNZ(fNZColumns); - fInterpolatorChargeC->SetNPhi(fNPhiSlices); - fInterpolatorChargeC->SetNGridPoints(); - fInterpolatorChargeC->SetRList(fListR); - fInterpolatorChargeC->SetZList(fListZC); - fInterpolatorChargeC->SetPhiList(fListPhi); - fInterpolatorChargeC->SetOrder(fInterpolationOrder); - - fInterpolatorPotentialA->SetNR(fNRRows); - fInterpolatorPotentialA->SetNZ(fNZColumns); - fInterpolatorPotentialA->SetNPhi(fNPhiSlices); - fInterpolatorPotentialA->SetNGridPoints(); - fInterpolatorPotentialA->SetRList(fListR); - fInterpolatorPotentialA->SetZList(fListZA); - fInterpolatorPotentialA->SetPhiList(fListPhi); - fInterpolatorPotentialA->SetOrder(fInterpolationOrder); - - fInterpolatorPotentialC->SetNR(fNRRows); - fInterpolatorPotentialC->SetNZ(fNZColumns); - fInterpolatorPotentialC->SetNPhi(fNPhiSlices); - fInterpolatorPotentialC->SetNGridPoints(); - fInterpolatorPotentialC->SetRList(fListR); - fInterpolatorPotentialC->SetZList(fListZA); - fInterpolatorPotentialC->SetPhiList(fListPhi); - fInterpolatorPotentialC->SetOrder(fInterpolationOrder); - - fInterpolatorInverseChargeA->SetNR(fNRRows); - fInterpolatorInverseChargeA->SetNZ(fNZColumns); - fInterpolatorInverseChargeA->SetNPhi(fNPhiSlices); - fInterpolatorInverseChargeA->SetNGridPoints(); - fInterpolatorInverseChargeA->SetRList(fListR); - fInterpolatorInverseChargeA->SetZList(fListZA); - fInterpolatorInverseChargeA->SetPhiList(fListPhi); - fInterpolatorInverseChargeA->SetOrder(fInterpolationOrder); - - fInterpolatorInverseChargeC->SetNR(fNRRows); - fInterpolatorInverseChargeC->SetNZ(fNZColumns); - fInterpolatorInverseChargeC->SetNPhi(fNPhiSlices); - fInterpolatorInverseChargeC->SetNGridPoints(); - fInterpolatorInverseChargeC->SetRList(fListR); - fInterpolatorInverseChargeC->SetZList(fListZC); - fInterpolatorInverseChargeC->SetPhiList(fListPhi); - fInterpolatorInverseChargeC->SetOrder(fInterpolationOrder); - - fLookupDistA = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupDistC = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupCorrA = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupCorrC = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupInverseDistA = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupInverseDistC = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupElectricFieldA = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupElectricFieldC = - new AliTPCLookUpTable3DInterpolatorD( - fNRRows, nullptr, fListR, fNPhiSlices, nullptr, fListPhi, fNZColumns, nullptr, fListZA, - fInterpolationOrder); - - fLookupIntCorrIrregularA->SetKernelType(fRBFKernelType); - fLookupIntCorrIrregularC->SetKernelType(fRBFKernelType); -} -/// Destruction for AliTPCSpaceCharge3DCalc -/// Deallocate memory for lookup table and charge distribution -/// -AliTPCSpaceCharge3DCalc::~AliTPCSpaceCharge3DCalc() -{ - - if (fPoissonSolver != nullptr) { - delete fPoissonSolver; - } - - for (Int_t k = 0; k < fNPhiSlices; k++) { - delete fMatrixIntDistDrEzA[k]; - delete fMatrixIntDistDPhiREzA[k]; - delete fMatrixIntDistDzA[k]; - delete fMatrixIntDistDrEzC[k]; - delete fMatrixIntDistDPhiREzC[k]; - delete fMatrixIntDistDzC[k]; - delete fMatrixIntCorrDrEzA[k]; - delete fMatrixIntCorrDPhiREzA[k]; - delete fMatrixIntCorrDzA[k]; - delete fMatrixIntCorrDrEzC[k]; - delete fMatrixIntCorrDPhiREzC[k]; - delete fMatrixIntCorrDzC[k]; - delete fMatrixErOverEzA[k]; - delete fMatrixEPhiOverEzA[k]; - delete fMatrixDeltaEzA[k]; - delete fMatrixErOverEzC[k]; - delete fMatrixEPhiOverEzC[k]; - delete fMatrixDeltaEzC[k]; - delete fMatrixIntCorrDrEzIrregularA[k]; - delete fMatrixIntCorrDPhiREzIrregularA[k]; - delete fMatrixIntCorrDzIrregularA[k]; - delete fMatrixRListIrregularA[k]; - delete fMatrixPhiListIrregularA[k]; - delete fMatrixZListIrregularA[k]; - delete fMatrixIntCorrDrEzIrregularC[k]; - delete fMatrixIntCorrDPhiREzIrregularC[k]; - delete fMatrixIntCorrDzIrregularC[k]; - delete fMatrixRListIrregularC[k]; - delete fMatrixPhiListIrregularC[k]; - delete fMatrixZListIrregularC[k]; - delete fMatrixChargeA[k]; - delete fMatrixChargeC[k]; - delete fMatrixChargeInverseA[k]; - delete fMatrixChargeInverseC[k]; - - delete fMatrixPotentialA[k]; - delete fMatrixPotentialC[k]; - } - delete[] fListR; - delete[] fListPhi; - delete[] fListZ; - delete[] fListZA; - delete[] fListZC; - - delete fLookupIntDistA; - delete fLookupIntDistC; - delete fLookupIntENoDriftA; - delete fLookupIntENoDriftC; - delete fLookupIntCorrA; - delete fLookupIntCorrC; - delete fLookupIntCorrIrregularA; - delete fLookupIntCorrIrregularC; - delete fLookupDistA; - delete fLookupDistC; - delete fLookupInverseDistA; - delete fLookupInverseDistC; - delete fLookupElectricFieldA; - delete fLookupElectricFieldC; - delete fInterpolatorChargeA; - delete fInterpolatorPotentialA; - delete fInterpolatorChargeC; - delete fInterpolatorPotentialC; - delete fInterpolatorInverseChargeA; - delete fInterpolatorInverseChargeC; - - delete fHistogram3DSpaceCharge; - delete fHistogram3DSpaceChargeA; - delete fHistogram3DSpaceChargeC; - - delete fFormulaBoundaryIFCA; - delete fFormulaBoundaryIFCC; - delete fFormulaBoundaryOFCA; - delete fFormulaBoundaryOFCC; - delete fFormulaBoundaryROCA; - delete fFormulaBoundaryROCC; - delete fFormulaBoundaryCE; - - delete fFormulaPotentialV; - delete fFormulaChargeRho; - - delete fFormulaEPhi; - delete fFormulaEr; - delete fFormulaEz; - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // delete[] fListPotentialBoundaryA; - // delete[] fListPotentialBoundaryC; -} - -/// Creating look-up tables of Correction/Distortion by integration following -/// drift line, input from space charge 3d histogram (fSpaceCharge3D) and boundary values are filled with zeroes -/// -/// TODO: provide an interface for setting boundary values -/// -/// The algorithm and implementations of this function is the following: -/// -/// Do for each side A,C -/// -/// 1) Solving \f$ \nabla^2 \Phi(r,\phi,z) = - \rho(r,\phi,z)\f$ -/// ~~~ Calling poisson solver -/// fPoissonSolver->PoissonSolver3D( matricesV, matricesCharge, nRRow, nZColumn, phiSlice, maxIteration, symmetry ) ; -/// ~~~ -/// -/// 2) Get the electric field \f$ \vec{E} = - \nabla \Phi(r,\phi,z) \f$ -/// ~~~ -/// ElectricField( matricesV, matricesEr, matricesEPhi, matricesEz, nRRow, nZColumn, phiSlice, -/// gridSizeR, gridSizePhi ,gridSizeZ,symmetry, AliTPCPoissonSolver::fgkIFCRadius); -/// ~~~ -/// -/// 3) Calculate local distortion and correction, using Langevin formula -/// ~~~ cxx -/// LocalDistCorrDz (matricesEr, matricesEPhi, matricesEz, -/// matricesDistDrDz, matricesDistDPhiRDz, matricesDistDz, -/// matricesCorrDrDz, matricesCorrDPhiRDz, matricesCorrDz, -/// nRRow, nZColumn, phiSlice, gridSizeZ, ezField); -/// ~~~ -/// -/// 4) Integrate distortion by following the drift line -/// -/// 5) Fill look up table for Integral distortion -/// -/// 6) Fill look up table for Integral correction -/// -/// \param nRRow Int_t Number of nRRow in r-direction -/// \param nZColumn Int_t Number of nZColumn in z-direction -/// \param phiSlice Int_t Number of phi slice in \f$ phi \f$ direction -/// \param maxIteration Int_t Maximum iteration for poisson solver -/// \param stoppingConvergence Convergence error stopping condition for poisson solver -/// -/// \post Lookup tables for distortion: -/// ~~~ -/// fLookUpIntDistDrEz,fLookUpIntDistDPhiREz,fLookUpIntDistDz -/// ~~~ -/// and correction: -/// ~~~ -/// fLookUpIntCorrDrEz,fLookUpIntCorrDPhiREz,fLookUpIntCorrDz -/// ~~~ -/// are initialized -/// -void AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz( - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, Double_t stoppingConvergence) -{ - Int_t phiSlicesPerSector = phiSlice / kNumSector; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - const Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm; - - // local variables - Float_t radius0, phi0, z0; - - // memory allocation for temporary matrices: - // potential (boundary values), charge distribution - TMatrixD **matricesV, *matricesCharge[phiSlice]; - TMatrixD *matricesEr[phiSlice], *matricesEPhi[phiSlice], *matricesEz[phiSlice]; - TMatrixD *matricesDistDrDz[phiSlice], *matricesDistDPhiRDz[phiSlice], *matricesDistDz[phiSlice]; - TMatrixD *matricesCorrDrDz[phiSlice], *matricesCorrDPhiRDz[phiSlice], *matricesCorrDz[phiSlice]; - TMatrixD *matricesGDistDrDz[phiSlice], *matricesGDistDPhiRDz[phiSlice], *matricesGDistDz[phiSlice]; - TMatrixD *matricesGCorrDrDz[phiSlice], *matricesGCorrDPhiRDz[phiSlice], *matricesGCorrDz[phiSlice]; - - for (Int_t k = 0; k < phiSlice; k++) { - //matricesV[k] = new TMatrixD(nRRow, nZColumn); - matricesCharge[k] = new TMatrixD(nRRow, nZColumn); - matricesEr[k] = new TMatrixD(nRRow, nZColumn); - matricesEPhi[k] = new TMatrixD(nRRow, nZColumn); - matricesEz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDz[k] = new TMatrixD(nRRow, nZColumn); - } - - // list of point as used in the poisson relaxation and the interpolation (for interpolation) - Double_t rList[nRRow], zList[nZColumn], phiList[phiSlice]; - - // pointer to current TF1 for potential boundary values - TF1* f1BoundaryIFC = nullptr; - TF1* f1BoundaryOFC = nullptr; - TF1* f1BoundaryROC = nullptr; - TStopwatch w; - - for (Int_t k = 0; k < phiSlice; k++) { - phiList[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < nRRow; i++) { - rList[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < nZColumn; j++) { - zList[j] = j * gridSizeZ; - } - - // allocate look up local distortion - AliTPCLookUpTable3DInterpolatorD* lookupLocalDist = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesDistDrDz, rList, phiSlice, matricesDistDPhiRDz, phiList, nZColumn, matricesDistDz, - zList, fInterpolationOrder); - - // allocate look up local correction - AliTPCLookUpTable3DInterpolatorD* lookupLocalCorr = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesCorrDrDz, rList, phiSlice, matricesCorrDPhiRDz, phiList, nZColumn, matricesCorrDz, - zList, fInterpolationOrder); - - // allocate look up for global distortion - AliTPCLookUpTable3DInterpolatorD* lookupGlobalDist = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesGDistDrDz, rList, phiSlice, matricesGDistDPhiRDz, phiList, nZColumn, matricesGDistDz, - zList, fInterpolationOrder); - // allocate look up for global distortion - AliTPCLookUpTable3DInterpolatorD* lookupGlobalCorr = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesGCorrDrDz, rList, phiSlice, matricesGCorrDPhiRDz, phiList, nZColumn, matricesGCorrDz, - zList, fInterpolationOrder); - - // should be set, in another place - const Int_t symmetry = 0; // fSymmetry - - // for irregular - TMatrixD** matricesIrregularDrDz = nullptr; - TMatrixD** matricesIrregularDPhiRDz = nullptr; - TMatrixD** matricesIrregularDz = nullptr; - TMatrixD** matricesPhiIrregular = nullptr; - TMatrixD** matricesRIrregular = nullptr; - TMatrixD** matricesZIrregular = nullptr; - - // for charge - TMatrixD** matricesLookUpCharge = nullptr; - AliTPC3DCylindricalInterpolator* chargeInterpolator = nullptr; - AliTPC3DCylindricalInterpolator* potentialInterpolator = nullptr; - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // Double_t* potentialBoundary = nullptr; - TMatrixD* matrixV; - TMatrixD* matrixCharge; - // for potential - TMatrixD** matricesVPotential; - - Int_t pIndex = 0; - - // do if look up table haven't be initialized - if (!fInitLookUp) { - // initialize for working memory - for (Int_t side = 0; side < 2; side++) { - // zeroing global distortion/correction - for (Int_t k = 0; k < phiSlice; k++) { - matricesDistDrDz[k]->Zero(); - matricesDistDPhiRDz[k]->Zero(); - matricesDistDz[k]->Zero(); - matricesCorrDrDz[k]->Zero(); - matricesCorrDPhiRDz[k]->Zero(); - matricesCorrDz[k]->Zero(); - - matricesGDistDrDz[k]->Zero(); - matricesGDistDPhiRDz[k]->Zero(); - matricesGDistDz[k]->Zero(); - matricesGCorrDrDz[k]->Zero(); - matricesGCorrDPhiRDz[k]->Zero(); - matricesGCorrDz[k]->Zero(); - } - if (side == 0) { - matricesIrregularDrDz = fMatrixIntCorrDrEzIrregularA; - matricesIrregularDPhiRDz = fMatrixIntCorrDPhiREzIrregularA; - matricesIrregularDz = fMatrixIntCorrDzIrregularA; - - matricesPhiIrregular = fMatrixPhiListIrregularA; - matricesRIrregular = fMatrixRListIrregularA; - matricesZIrregular = fMatrixZListIrregularA; - matricesLookUpCharge = fMatrixChargeA; - - matricesV = fMatrixPotentialA; - chargeInterpolator = fInterpolatorChargeA; - potentialInterpolator = fInterpolatorPotentialA; - fLookupDistA->SetLookUpR(matricesDistDrDz); - fLookupDistA->SetLookUpPhi(matricesDistDPhiRDz); - fLookupDistA->SetLookUpZ(matricesDistDz); - fLookupCorrA->SetLookUpR(matricesCorrDrDz); - fLookupCorrA->SetLookUpPhi(matricesCorrDPhiRDz); - fLookupCorrA->SetLookUpZ(matricesCorrDz); - - fLookupElectricFieldA->SetLookUpR(matricesEr); - fLookupElectricFieldA->SetLookUpPhi(matricesEPhi); - fLookupElectricFieldA->SetLookUpZ(matricesEz); - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // potentialBoundary = fListPotentialBoundaryA; - f1BoundaryIFC = fFormulaBoundaryIFCA; - f1BoundaryOFC = fFormulaBoundaryOFCA; - f1BoundaryROC = fFormulaBoundaryROCA; - } else { - matricesIrregularDrDz = fMatrixIntCorrDrEzIrregularC; - matricesIrregularDPhiRDz = fMatrixIntCorrDPhiREzIrregularC; - matricesIrregularDz = fMatrixIntCorrDzIrregularC; - matricesPhiIrregular = fMatrixPhiListIrregularC; - matricesRIrregular = fMatrixRListIrregularC; - matricesZIrregular = fMatrixZListIrregularC; - matricesLookUpCharge = fMatrixChargeC; - matricesV = fMatrixPotentialC; - chargeInterpolator = fInterpolatorChargeC; - potentialInterpolator = fInterpolatorPotentialC; - fLookupDistC->SetLookUpR(matricesDistDrDz); - fLookupDistC->SetLookUpPhi(matricesDistDPhiRDz); - fLookupDistC->SetLookUpZ(matricesDistDz); - fLookupCorrC->SetLookUpR(matricesCorrDrDz); - fLookupCorrC->SetLookUpPhi(matricesCorrDPhiRDz); - fLookupCorrC->SetLookUpZ(matricesCorrDz); - fLookupElectricFieldC->SetLookUpR(matricesEr); - fLookupElectricFieldC->SetLookUpPhi(matricesEPhi); - fLookupElectricFieldC->SetLookUpZ(matricesEz); - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // potentialBoundary = fListPotentialBoundaryC; - f1BoundaryIFC = fFormulaBoundaryIFCC; - f1BoundaryOFC = fFormulaBoundaryOFCC; - f1BoundaryROC = fFormulaBoundaryROCC; - } - - // fill the potential boundary - // guess the initial potential - // fill also charge - //pIndex = 0; - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step = 0: Fill Boundary and Charge Densities")); - for (Int_t k = 0; k < phiSlice; k++) { - phi0 = k * gridSizePhi; - matrixV = matricesV[k]; - matrixCharge = matricesCharge[k]; - for (Int_t i = 0; i < nRRow; i++) { - radius0 = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - for (Int_t j = 0; j < nZColumn; j++) { - z0 = j * gridSizeZ; - (*matrixCharge)(i, j) = chargeInterpolator->GetValue(rList[i], phiList[k], zList[j]); - (*matrixV)(i, j) = 0.0; // fill zeros - - if (fFormulaPotentialV == nullptr) { - // boundary IFC - if (i == 0) { - if (f1BoundaryIFC != nullptr) { - if (TF2* f2BoundaryIFC = dynamic_cast<TF2*>(f1BoundaryIFC)) { - (*matrixV)(i, j) = f2BoundaryIFC->Eval(z0, phi0); - } else { - (*matrixV)(i, j) = f1BoundaryIFC->Eval(z0); - } - } - } - if (i == (nRRow - 1)) { - if (f1BoundaryOFC != nullptr) { - if (TF2* f2BoundaryOFC = dynamic_cast<TF2*>(f1BoundaryOFC)) { - (*matrixV)(i, j) = f2BoundaryOFC->Eval(z0, phi0); - } else { - (*matrixV)(i, j) = f1BoundaryOFC->Eval(z0); - } - } - } - if (j == 0) { - if (fFormulaBoundaryCE) { - if (TF2* f2FormulaBoundaryCE = dynamic_cast<TF2*>(fFormulaBoundaryCE)) { - (*matrixV)(i, j) = f2FormulaBoundaryCE->Eval(radius0, phi0); - } else { - (*matrixV)(i, j) = fFormulaBoundaryCE->Eval(radius0); - } - } - } - if (j == (nZColumn - 1)) { - if (f1BoundaryROC != nullptr) { - if (TF2* f2BoundaryROC = dynamic_cast<TF2*>(f1BoundaryROC)) { - (*matrixV)(i, j) = f2BoundaryROC->Eval(radius0, phi0); - } else { - (*matrixV)(i, j) = f1BoundaryROC->Eval(radius0); - } - } - } - } else { - if ((i == 0) || (i == (nRRow - 1)) || (j == 0) || (j == (nZColumn - 1))) { - (*matrixV)(i, j) = fFormulaPotentialV->Eval(radius0, phi0, z0); - } - } - } - } - } - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 0: Preparing Charge interpolator: %f\n", w.CpuTime())); - AliTPCPoissonSolver::fgConvergenceError = stoppingConvergence; - - //fPoissonSolver->SetStrategy(AliTPCPoissonSolver::kMultiGrid); - //(fPoissonSolver->fMgParameters).cycleType = AliTPCPoissonSolver::kFCycle; - //(fPoissonSolver->fMgParameters).isFull3D = kFALSE; - //(fPoissonSolver->fMgParameters).nMGCycle = maxIteration; - //(fPoissonSolver->fMgParameters).maxLoop = 6; - - w.Start(); - fPoissonSolver->PoissonSolver3D(matricesV, matricesCharge, nRRow, nZColumn, phiSlice, maxIteration, symmetry); - w.Stop(); - - potentialInterpolator->SetValue(matricesV); - potentialInterpolator->InitCubicSpline(); - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 1: Poisson solver: %f\n", w.CpuTime())); - if (side == 0) { - myProfile.poissonSolverTime = w.CpuTime(); - } - if (side == 0) { - myProfile.iteration = fPoissonSolver->fIterations; - } - - w.Start(); - ElectricField(matricesV, - matricesEr, matricesEPhi, matricesEz, nRRow, nZColumn, phiSlice, - gridSizeR, gridSizePhi, gridSizeZ, symmetry, AliTPCPoissonSolver::fgkIFCRadius); - w.Stop(); - - myProfile.electricFieldTime = w.CpuTime(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 2: Electric Field Calculation: %f\n", w.CpuTime())); - w.Start(); - LocalDistCorrDz(matricesEr, matricesEPhi, matricesEz, - matricesDistDrDz, matricesDistDPhiRDz, matricesDistDz, - matricesCorrDrDz, matricesCorrDPhiRDz, matricesCorrDz, - nRRow, nZColumn, phiSlice, gridSizeZ, ezField); - w.Stop(); - myProfile.localDistortionTime = w.CpuTime(); - - // copy to interpolator - if (side == 0) { - lookupLocalDist->CopyFromMatricesToInterpolator(); - lookupLocalCorr->CopyFromMatricesToInterpolator(); - fLookupDistA->CopyFromMatricesToInterpolator(); - fLookupCorrA->CopyFromMatricesToInterpolator(); - fLookupElectricFieldA->CopyFromMatricesToInterpolator(); - } else { - lookupLocalDist->CopyFromMatricesToInterpolator(); - lookupLocalCorr->CopyFromMatricesToInterpolator(); - fLookupDistC->CopyFromMatricesToInterpolator(); - fLookupCorrC->CopyFromMatricesToInterpolator(); - fLookupElectricFieldC->CopyFromMatricesToInterpolator(); - } - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 3: Local distortion and correction: %f\n", w.CpuTime())); - w.Start(); - if (fIntegrationStrategy == kNaive) { - IntegrateDistCorrDriftLineDz( - lookupLocalDist, - matricesGDistDrDz, matricesGDistDPhiRDz, matricesGDistDz, - lookupLocalCorr, - matricesGCorrDrDz, matricesGCorrDPhiRDz, matricesGCorrDz, - matricesIrregularDrDz, matricesIrregularDPhiRDz, matricesIrregularDz, - matricesRIrregular, matricesPhiIrregular, matricesZIrregular, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - } else { - IntegrateDistCorrDriftLineDzWithLookUp( - lookupLocalDist, - matricesGDistDrDz, matricesGDistDPhiRDz, matricesGDistDz, - lookupLocalCorr, - matricesGCorrDrDz, matricesGCorrDPhiRDz, matricesGCorrDz, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - } - - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 4: Global correction/distortion: %f\n", w.CpuTime())); - myProfile.globalDistortionTime = w.CpuTime(); - - //// copy to 1D interpolator ///// - lookupGlobalDist->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - lookupGlobalCorr->CopyFromMatricesToInterpolator(); - } - //// - - w.Stop(); - - if (side == 0) { - - w.Start(); - FillLookUpTable(lookupGlobalDist, - fMatrixIntDistDrEzA, fMatrixIntDistDPhiREzA, fMatrixIntDistDzA, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - if (fCorrectionType == 0) { - FillLookUpTable(lookupGlobalCorr, - fMatrixIntCorrDrEzA, fMatrixIntCorrDPhiREzA, fMatrixIntCorrDzA, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - } - - fLookupIntDistA->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - fLookupIntCorrA->CopyFromMatricesToInterpolator(); - } else { - fLookupIntCorrIrregularA->CopyFromMatricesToInterpolator(); - } - - w.Stop(); - myProfile.interpolationInitTime = w.CpuTime(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 5: Filling up the look up: %f\n", w.CpuTime())); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " A side done"); - } - if (side == 1) { - w.Start(); - FillLookUpTable(lookupGlobalDist, - fMatrixIntDistDrEzC, fMatrixIntDistDPhiREzC, fMatrixIntDistDzC, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - if (fCorrectionType == 0) { - FillLookUpTable(lookupGlobalCorr, - fMatrixIntCorrDrEzC, fMatrixIntCorrDPhiREzC, fMatrixIntCorrDzC, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - } - - fLookupIntDistC->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - fLookupIntCorrC->CopyFromMatricesToInterpolator(); - } else { - fLookupIntCorrIrregularC->CopyFromMatricesToInterpolator(); - } - w.Stop(); - myProfile.interpolationInitTime = w.CpuTime(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " C side done"); - } - } - - fInitLookUp = kTRUE; - } - - // memory de-allocation for temporary matrices - for (Int_t k = 0; k < phiSlice; k++) { - //delete matricesV[k]; - delete matricesCharge[k]; - delete matricesEr[k]; - delete matricesEPhi[k]; - delete matricesEz[k]; - delete matricesDistDrDz[k]; - delete matricesDistDPhiRDz[k]; - delete matricesDistDz[k]; - - delete matricesCorrDrDz[k]; - delete matricesCorrDPhiRDz[k]; - delete matricesCorrDz[k]; - delete matricesGDistDrDz[k]; - delete matricesGDistDPhiRDz[k]; - delete matricesGDistDz[k]; - - delete matricesGCorrDrDz[k]; - delete matricesGCorrDPhiRDz[k]; - delete matricesGCorrDz[k]; - } - delete lookupLocalDist; - delete lookupLocalCorr; - delete lookupGlobalDist; - delete lookupGlobalCorr; -} - -// outdated, to be removed once modifications in aliroot are pushed -/// Creating look-up tables of Correction/Distortion by integration following -/// drift line with known distributions for potential and space charge. -/// -/// -/// \param nRRow Int_t number of grid in row direction -/// \param nZColumn Int_t number of grid in z direction -/// \param phiSlice Int_t number of slices in phi direction -/// \param maxIteration Int_t max iteration for convergence -/// \param stopConvergence Double_t stopping criteria for convergence -/// \param matricesDistDrDzA TMatrixD** local r distortion (output) A side -/// \param matricesDistDPhiRDzA TMatrixD** local r phi distortion (output) A side -/// \param matricesDistDzA TMatrixD** local z distortion (output) A side -/// \param matricesCorrDrDzA TMatrixD** local r correction (output) A side -/// \param matricesCorrDPhiRDzA TMatrixD** local r phi correction (output) A side -/// \param matricesCorrDzA TMatrixD** local z correction (output) A side -/// \param matricesDistDrDzC TMatrixD** local r distortion (output) C side -/// \param matricesDistDPhiRDzC TMatrixD** local r phi distortion (output) C side -/// \param matricesDistDzC TMatrixD** local z distortion (output) C side -/// \param matricesCorrDrDzC TMatrixD** local r phi correction (output) C side -/// \param matricesCorrDPhiRDzC TMatrixD** local r phi correction (output) C side -/// \param matricesCorrDzC TMatrixD** local z correction (output) C side -/// -/// \post Lookup tables for distortion: -/// ~~~ -/// fLookUpIntDistDrEz,fLookUpIntDistDPhiREz,fLookUpIntDistDz -/// ~~~ -/// and correction: -/// ~~~ -/// fLookUpIntCorrDrEz,fLookUpIntCorrDPhiREz,fLookUpIntCorrDz -/// ~~~ -/// are initialized -/// -void AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz( - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, Double_t stopConvergence, - TMatrixD** matricesErA, TMatrixD** matricesEPhiA, TMatrixD** matricesEzA, - TMatrixD** matricesErC, TMatrixD** matricesEPhiC, TMatrixD** matricesEzC, - TMatrixD** matricesDistDrDzA, TMatrixD** matricesDistDPhiRDzA, TMatrixD** matricesDistDzA, - TMatrixD** matricesCorrDrDzA, TMatrixD** matricesCorrDPhiRDzA, TMatrixD** matricesCorrDzA, - TMatrixD** matricesDistDrDzC, TMatrixD** matricesDistDPhiRDzC, TMatrixD** matricesDistDzC, - TMatrixD** matricesCorrDrDzC, TMatrixD** matricesCorrDPhiRDzC, TMatrixD** matricesCorrDzC, - TFormula* intErDzTestFunction, TFormula* intEPhiRDzTestFunction, TFormula* intDzTestFunction) -{ - Int_t phiSlicesPerSector = phiSlice / kNumSector; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - const Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm; - - // local variables - Float_t radius0, phi0, z0; - - // memory allocation for temporary matrices: - // potential (boundary values), charge distribution - TMatrixD *matricesV[phiSlice], *matricesCharge[phiSlice]; - TMatrixD *matricesEr[phiSlice], *matricesEPhi[phiSlice], *matricesEz[phiSlice]; - TMatrixD *matricesDistDrDz[phiSlice], *matricesDistDPhiRDz[phiSlice], *matricesDistDz[phiSlice]; - TMatrixD *matricesCorrDrDz[phiSlice], *matricesCorrDPhiRDz[phiSlice], *matricesCorrDz[phiSlice]; - TMatrixD *matricesGDistDrDz[phiSlice], *matricesGDistDPhiRDz[phiSlice], *matricesGDistDz[phiSlice]; - TMatrixD *matricesGCorrDrDz[phiSlice], *matricesGCorrDPhiRDz[phiSlice], *matricesGCorrDz[phiSlice]; - - for (Int_t k = 0; k < phiSlice; k++) { - matricesV[k] = new TMatrixD(nRRow, nZColumn); - matricesCharge[k] = new TMatrixD(nRRow, nZColumn); - matricesEr[k] = new TMatrixD(nRRow, nZColumn); - matricesEPhi[k] = new TMatrixD(nRRow, nZColumn); - matricesEz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDz[k] = new TMatrixD(nRRow, nZColumn); - } - - // list of point as used in the poisson relaxation and the interpolation (for interpolation) - Double_t rList[nRRow], zList[nZColumn], phiList[phiSlice]; - - // pointer to current TF1 for potential boundary values - TF1* f1BoundaryIFC = nullptr; - TF1* f1BoundaryOFC = nullptr; - TF1* f1BoundaryROC = nullptr; - TStopwatch w; - - for (Int_t k = 0; k < phiSlice; k++) { - phiList[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < nRRow; i++) { - rList[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < nZColumn; j++) { - zList[j] = j * gridSizeZ; - } - - // allocate look up local distortion - AliTPCLookUpTable3DInterpolatorD* lookupLocalDist = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesDistDrDz, rList, phiSlice, matricesDistDPhiRDz, phiList, nZColumn, matricesDistDz, - zList, fInterpolationOrder); - - // allocate look up local correction - AliTPCLookUpTable3DInterpolatorD* lookupLocalCorr = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesCorrDrDz, rList, phiSlice, matricesCorrDPhiRDz, phiList, nZColumn, matricesCorrDz, - zList, fInterpolationOrder); - - // allocate look up for global distortion - AliTPCLookUpTable3DInterpolatorD* lookupGlobalDist = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesGDistDrDz, rList, phiSlice, matricesGDistDPhiRDz, phiList, nZColumn, matricesGDistDz, - zList, fInterpolationOrder); - // allocate look up for global distortion - AliTPCLookUpTable3DInterpolatorD* lookupGlobalCorr = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesGCorrDrDz, rList, phiSlice, matricesGCorrDPhiRDz, phiList, nZColumn, matricesGCorrDz, - zList, fInterpolationOrder); - - // should be set, in another place - const Int_t symmetry = 0; // fSymmetry - - // for irregular - TMatrixD** matricesIrregularDrDz = nullptr; - TMatrixD** matricesIrregularDPhiRDz = nullptr; - TMatrixD** matricesIrregularDz = nullptr; - TMatrixD** matricesPhiIrregular = nullptr; - TMatrixD** matricesRIrregular = nullptr; - TMatrixD** matricesZIrregular = nullptr; - - // for charge - TMatrixD** matricesLookUpCharge = nullptr; - AliTPC3DCylindricalInterpolator* chargeInterpolator = nullptr; - AliTPC3DCylindricalInterpolator* potentialInterpolator = nullptr; - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // Double_t* potentialBoundary = nullptr; - TMatrixD* matrixV; - TMatrixD* matrixCharge; - Int_t pIndex = 0; - - // do if look up table haven't be initialized - if (!fInitLookUp) { - // initialize for working memory - for (Int_t side = 0; side < 2; side++) { - // zeroing global distortion/correction - for (Int_t k = 0; k < phiSlice; k++) { - matricesDistDrDz[k]->Zero(); - matricesDistDPhiRDz[k]->Zero(); - matricesDistDz[k]->Zero(); - matricesCorrDrDz[k]->Zero(); - matricesCorrDPhiRDz[k]->Zero(); - matricesCorrDz[k]->Zero(); - - matricesGDistDrDz[k]->Zero(); - matricesGDistDPhiRDz[k]->Zero(); - matricesGDistDz[k]->Zero(); - matricesGCorrDrDz[k]->Zero(); - matricesGCorrDPhiRDz[k]->Zero(); - matricesGCorrDz[k]->Zero(); - } - if (side == 0) { - matricesIrregularDrDz = fMatrixIntCorrDrEzIrregularA; - matricesIrregularDPhiRDz = fMatrixIntCorrDPhiREzIrregularA; - matricesIrregularDz = fMatrixIntCorrDzIrregularA; - - matricesPhiIrregular = fMatrixPhiListIrregularA; - matricesRIrregular = fMatrixRListIrregularA; - matricesZIrregular = fMatrixZListIrregularA; - matricesLookUpCharge = fMatrixChargeA; - chargeInterpolator = fInterpolatorChargeA; - potentialInterpolator = fInterpolatorPotentialA; - fLookupDistA->SetLookUpR(matricesDistDrDzA); - fLookupDistA->SetLookUpPhi(matricesDistDPhiRDzA); - fLookupDistA->SetLookUpZ(matricesDistDzA); - lookupLocalDist->SetLookUpR(matricesDistDrDzA); - lookupLocalDist->SetLookUpPhi(matricesDistDPhiRDzA); - lookupLocalDist->SetLookUpZ(matricesDistDzA); - - lookupLocalCorr->SetLookUpR(matricesCorrDrDzA); - lookupLocalCorr->SetLookUpPhi(matricesCorrDPhiRDzA); - lookupLocalCorr->SetLookUpZ(matricesCorrDzA); - - fLookupElectricFieldA->SetLookUpR(matricesErA); - fLookupElectricFieldA->SetLookUpPhi(matricesEPhiA); - fLookupElectricFieldA->SetLookUpZ(matricesEzA); - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // potentialBoundary = fListPotentialBoundaryA; - f1BoundaryIFC = fFormulaBoundaryIFCA; - f1BoundaryOFC = fFormulaBoundaryOFCA; - f1BoundaryROC = fFormulaBoundaryROCA; - } else { - matricesIrregularDrDz = fMatrixIntCorrDrEzIrregularC; - matricesIrregularDPhiRDz = fMatrixIntCorrDPhiREzIrregularC; - matricesIrregularDz = fMatrixIntCorrDzIrregularC; - matricesPhiIrregular = fMatrixPhiListIrregularC; - matricesRIrregular = fMatrixRListIrregularC; - matricesZIrregular = fMatrixZListIrregularC; - matricesLookUpCharge = fMatrixChargeC; - chargeInterpolator = fInterpolatorChargeC; - potentialInterpolator = fInterpolatorPotentialC; - fLookupDistC->SetLookUpR(matricesDistDrDzC); - fLookupDistC->SetLookUpPhi(matricesDistDPhiRDzC); - fLookupDistC->SetLookUpZ(matricesDistDzC); - fLookupElectricFieldC->SetLookUpR(matricesErC); - fLookupElectricFieldC->SetLookUpPhi(matricesEPhiC); - fLookupElectricFieldC->SetLookUpZ(matricesEzC); - - lookupLocalDist->SetLookUpR(matricesDistDrDzC); - lookupLocalDist->SetLookUpPhi(matricesDistDPhiRDzC); - lookupLocalDist->SetLookUpZ(matricesDistDzC); - - lookupLocalCorr->SetLookUpR(matricesCorrDrDzC); - lookupLocalCorr->SetLookUpPhi(matricesCorrDPhiRDzC); - lookupLocalCorr->SetLookUpZ(matricesCorrDzC); - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // potentialBoundary = fListPotentialBoundaryC; - f1BoundaryIFC = fFormulaBoundaryIFCC; - f1BoundaryOFC = fFormulaBoundaryOFCC; - f1BoundaryROC = fFormulaBoundaryROCC; - } - - // fill the potential boundary - // guess the initial potential - // fill also charge - //pIndex = 0; - - //Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz","%s",Form("Step = 0: Fill Boundary and Charge Densities")); - for (Int_t k = 0; k < phiSlice; k++) { - phi0 = k * gridSizePhi; - matrixV = matricesV[k]; - matrixCharge = matricesCharge[k]; - for (Int_t i = 0; i < nRRow; i++) { - radius0 = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - for (Int_t j = 0; j < nZColumn; j++) { - z0 = j * gridSizeZ; - (*matrixCharge)(i, j) = chargeInterpolator->GetValue(rList[i], phiList[k], zList[j]); - (*matrixV)(i, j) = fFormulaPotentialV->Eval(radius0, phi0, z0); - } - } - } - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 0: Preparing Charge interpolator: %f\n", w.CpuTime())); - //AliTPCPoissonSolver::fgConvergenceError = stoppingConvergence; - - //fPoissonSolver->SetStrategy(AliTPCPoissonSolver::kMultiGrid); - //(fPoissonSolver->fMgParameters).cycleType = AliTPCPoissonSolver::kFCycle; - //(fPoissonSolver->fMgParameters).isFull3D = kFALSE; - //(fPoissonSolver->fMgParameters).nMGCycle = maxIteration; - //(fPoissonSolver->fMgParameters).maxLoop = 6; - - w.Start(); - //fPoissonSolver->PoissonSolver3D(matricesV, matricesCharge, nRRow, nZColumn, phiSlice, maxIteration, - // symmetry); - w.Stop(); - - potentialInterpolator->SetValue(matricesV); - potentialInterpolator->InitCubicSpline(); - - // copy to interpolator - if (side == 0) { - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 1: Poisson solver: %f\n", w.CpuTime())); - w.Start(); - ElectricField(matricesV, - matricesErA, matricesEPhiA, matricesEzA, nRRow, nZColumn, phiSlice, - gridSizeR, gridSizePhi, gridSizeZ, symmetry, AliTPCPoissonSolver::fgkIFCRadius); - w.Stop(); - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 2: Electric Field Calculation: %f\n", w.CpuTime())); - w.Start(); - LocalDistCorrDz(matricesErA, matricesEPhiA, matricesEzA, - matricesDistDrDzA, matricesDistDPhiRDzA, matricesDistDzA, - matricesCorrDrDzA, matricesCorrDPhiRDzA, matricesCorrDzA, - nRRow, nZColumn, phiSlice, gridSizeZ, ezField); - //LocalDistCorrDz(intErDzTestFunction, intEPhiRDzTestFunction, intDzTestFunction, - // GetEzFormula(), rList, phiList, zList, - // matricesDistDrDzA, matricesDistDPhiRDzA, matricesDistDzA, - // matricesCorrDrDzA, matricesCorrDPhiRDzA, matricesCorrDzA, - // nRRow, nZColumn, phiSlice, gridSizeZ, ezField); - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 3: Local distortion and correction: %f\n", w.CpuTime())); - - lookupLocalDist->CopyFromMatricesToInterpolator(); - lookupLocalCorr->CopyFromMatricesToInterpolator(); - fLookupDistA->CopyFromMatricesToInterpolator(); - fLookupElectricFieldA->CopyFromMatricesToInterpolator(); - } else { - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 1: Poisson solver: %f\n", w.CpuTime())); - w.Start(); - ElectricField(matricesV, - matricesErC, matricesEPhiC, matricesEzC, nRRow, nZColumn, phiSlice, - gridSizeR, gridSizePhi, gridSizeZ, symmetry, AliTPCPoissonSolver::fgkIFCRadius); - w.Stop(); - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 2: Electric Field Calculation: %f\n", w.CpuTime())); - w.Start(); - LocalDistCorrDz(matricesErC, matricesEPhiC, matricesEzC, - matricesDistDrDzC, matricesDistDPhiRDzC, matricesDistDzC, - matricesCorrDrDzC, matricesCorrDPhiRDzC, matricesCorrDzC, - nRRow, nZColumn, phiSlice, gridSizeZ, ezField); - //LocalDistCorrDz(intErDzTestFunction, intEPhiRDzTestFunction, intDzTestFunction, - // GetEzFormula(), rList, phiList, zList, - // matricesDistDrDzC, matricesDistDPhiRDzC, matricesDistDzC, - // matricesCorrDrDzC, matricesCorrDPhiRDzC, matricesCorrDzC, - // nRRow, nZColumn, phiSlice, gridSizeZ, ezField); - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 3: Local distortion and correction: %f\n", w.CpuTime())); - lookupLocalDist->CopyFromMatricesToInterpolator(); - lookupLocalCorr->CopyFromMatricesToInterpolator(); - fLookupDistC->CopyFromMatricesToInterpolator(); - fLookupElectricFieldC->CopyFromMatricesToInterpolator(); - } - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 3: Local distortion and correction: %f\n", w.CpuTime())); - w.Start(); - if (fIntegrationStrategy == kNaive) { - IntegrateDistCorrDriftLineDz( - lookupLocalDist, - matricesGDistDrDz, matricesGDistDPhiRDz, matricesGDistDz, - lookupLocalCorr, - matricesGCorrDrDz, matricesGCorrDPhiRDz, matricesGCorrDz, - matricesIrregularDrDz, matricesIrregularDPhiRDz, matricesIrregularDz, - matricesRIrregular, matricesPhiIrregular, matricesZIrregular, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - } else { - IntegrateDistCorrDriftLineDzWithLookUp( - lookupLocalDist, - matricesGDistDrDz, matricesGDistDPhiRDz, matricesGDistDz, - lookupLocalCorr, - matricesGCorrDrDz, matricesGCorrDPhiRDz, matricesGCorrDz, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - } - - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 4: Global correction/distortion: %f\n", w.CpuTime())); - - //// copy to 1D interpolator ///// - lookupGlobalDist->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - lookupGlobalCorr->CopyFromMatricesToInterpolator(); - } - //// - - w.Start(); - //// copy to 1D interpolator ///// - lookupGlobalDist->CopyFromMatricesToInterpolator(); - lookupGlobalCorr->CopyFromMatricesToInterpolator(); - //// - - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 5: Filling up the look up: %f\n", w.CpuTime())); - - if (side == 0) { - FillLookUpTable(lookupGlobalDist, - fMatrixIntDistDrEzA, fMatrixIntDistDPhiREzA, fMatrixIntDistDzA, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - FillLookUpTable(lookupGlobalCorr, - fMatrixIntCorrDrEzA, fMatrixIntCorrDPhiREzA, fMatrixIntCorrDzA, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - fLookupIntDistA->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - fLookupIntCorrA->CopyFromMatricesToInterpolator(); - } else { - fLookupIntCorrIrregularA->CopyFromMatricesToInterpolator(); - } - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " A side done"); - } - if (side == 1) { - FillLookUpTable(lookupGlobalDist, - fMatrixIntDistDrEzC, fMatrixIntDistDPhiREzC, fMatrixIntDistDzC, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - FillLookUpTable(lookupGlobalCorr, - fMatrixIntCorrDrEzC, fMatrixIntCorrDPhiREzC, fMatrixIntCorrDzC, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - fLookupIntDistC->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - fLookupIntCorrC->CopyFromMatricesToInterpolator(); - } else { - fLookupIntCorrIrregularC->CopyFromMatricesToInterpolator(); - } - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " C side done"); - } - } - - fInitLookUp = kTRUE; - } - - // memory de-allocation for temporary matrices - for (Int_t k = 0; k < phiSlice; k++) { - delete matricesV[k]; - delete matricesCharge[k]; - delete matricesEr[k]; - delete matricesEPhi[k]; - delete matricesEz[k]; - delete matricesDistDrDz[k]; - delete matricesDistDPhiRDz[k]; - delete matricesDistDz[k]; - - delete matricesCorrDrDz[k]; - delete matricesCorrDPhiRDz[k]; - delete matricesCorrDz[k]; - delete matricesGDistDrDz[k]; - delete matricesGDistDPhiRDz[k]; - delete matricesGDistDz[k]; - - delete matricesGCorrDrDz[k]; - delete matricesGCorrDPhiRDz[k]; - delete matricesGCorrDz[k]; - } - delete lookupLocalDist; - delete lookupLocalCorr; - delete lookupGlobalDist; - delete lookupGlobalCorr; -} - -/// Creating look-up tables of Correction/Distortion by integration following -/// drift line with known distributions for potential and space charge. -/// -/// -/// \param nRRow Int_t number of grid in row direction -/// \param nZColumn Int_t number of grid in z direction -/// \param phiSlice Int_t number of slices in phi direction -/// \param maxIteration Int_t max iteration for convergence -/// \param stopConvergence Double_t stopping criteria for convergence -/// \param matricesCorrDzC TMatrixD** local z correction (output) C side -/// \param intErDzTestFunction TFormula* analytic function for closed integration of Er in z direction -/// \param intEPhiRDzTestFunction TFormula* analytic function for closed integration of EPhi in z direction -/// \param intDzTestFunction TFormula* analytic function for closed integration of Ez in z direction -/// -/// \post Lookup tables for distortion: -/// ~~~ -/// fLookUpIntDistDrEz,fLookUpIntDistDPhiREz,fLookUpIntDistDz -/// ~~~ -/// and correction: -/// ~~~ -/// fLookUpIntCorrDrEz,fLookUpIntCorrDPhiREz,fLookUpIntCorrDz -/// ~~~ -/// are initialized -/// -void AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz( - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, Double_t stopConvergence, - TFormula* intErDzTestFunction, TFormula* intEPhiRDzTestFunction, TFormula* intDzTestFunction) -{ - Int_t phiSlicesPerSector = phiSlice / kNumSector; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - const Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm; - - // local variables - Float_t radius0, phi0, z0; - - // memory allocation for temporary matrices: - // potential (boundary values), charge distribution - TMatrixD *matricesV[phiSlice], *matricesCharge[phiSlice]; - TMatrixD *matricesEr[phiSlice], *matricesEPhi[phiSlice], *matricesEz[phiSlice]; - TMatrixD *matricesDistDrDz[phiSlice], *matricesDistDPhiRDz[phiSlice], *matricesDistDz[phiSlice]; - TMatrixD *matricesCorrDrDz[phiSlice], *matricesCorrDPhiRDz[phiSlice], *matricesCorrDz[phiSlice]; - TMatrixD *matricesGDistDrDz[phiSlice], *matricesGDistDPhiRDz[phiSlice], *matricesGDistDz[phiSlice]; - TMatrixD *matricesGCorrDrDz[phiSlice], *matricesGCorrDPhiRDz[phiSlice], *matricesGCorrDz[phiSlice]; - - for (Int_t k = 0; k < phiSlice; k++) { - matricesV[k] = new TMatrixD(nRRow, nZColumn); - matricesCharge[k] = new TMatrixD(nRRow, nZColumn); - matricesEr[k] = new TMatrixD(nRRow, nZColumn); - matricesEPhi[k] = new TMatrixD(nRRow, nZColumn); - matricesEz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesDistDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesCorrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGDistDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDrDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDPhiRDz[k] = new TMatrixD(nRRow, nZColumn); - matricesGCorrDz[k] = new TMatrixD(nRRow, nZColumn); - } - - // list of point as used in the poisson relaxation and the interpolation (for interpolation) - Double_t rList[nRRow], zList[nZColumn], phiList[phiSlice]; - - // pointer to current TF1 for potential boundary values - TF1* f1BoundaryIFC = nullptr; - TF1* f1BoundaryOFC = nullptr; - TF1* f1BoundaryROC = nullptr; - TStopwatch w; - - for (Int_t k = 0; k < phiSlice; k++) { - phiList[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < nRRow; i++) { - rList[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < nZColumn; j++) { - zList[j] = j * gridSizeZ; - } - - // allocate look up local distortion - AliTPCLookUpTable3DInterpolatorD* lookupLocalDist = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesDistDrDz, rList, phiSlice, matricesDistDPhiRDz, phiList, nZColumn, matricesDistDz, - zList, fInterpolationOrder); - - // allocate look up local correction - AliTPCLookUpTable3DInterpolatorD* lookupLocalCorr = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesCorrDrDz, rList, phiSlice, matricesCorrDPhiRDz, phiList, nZColumn, matricesCorrDz, - zList, fInterpolationOrder); - - // allocate look up for global distortion - AliTPCLookUpTable3DInterpolatorD* lookupGlobalDist = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesGDistDrDz, rList, phiSlice, matricesGDistDPhiRDz, phiList, nZColumn, matricesGDistDz, - zList, fInterpolationOrder); - // allocate look up for global distortion - AliTPCLookUpTable3DInterpolatorD* lookupGlobalCorr = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesGCorrDrDz, rList, phiSlice, matricesGCorrDPhiRDz, phiList, nZColumn, matricesGCorrDz, - zList, fInterpolationOrder); - - // should be set, in another place - const Int_t symmetry = 0; // fSymmetry - - // for irregular - TMatrixD** matricesIrregularDrDz = nullptr; - TMatrixD** matricesIrregularDPhiRDz = nullptr; - TMatrixD** matricesIrregularDz = nullptr; - TMatrixD** matricesPhiIrregular = nullptr; - TMatrixD** matricesRIrregular = nullptr; - TMatrixD** matricesZIrregular = nullptr; - - // for charge - TMatrixD** matricesLookUpCharge = nullptr; - AliTPC3DCylindricalInterpolator* chargeInterpolator = nullptr; - AliTPC3DCylindricalInterpolator* potentialInterpolator = nullptr; - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // Double_t* potentialBoundary = nullptr; - TMatrixD* matrixV; - TMatrixD* matrixCharge; - - // do if look up table haven't be initialized - if (!fInitLookUp) { - // initialize for working memory - for (Int_t side = 0; side < 2; side++) { - // zeroing global distortion/correction - for (Int_t k = 0; k < phiSlice; k++) { - matricesDistDrDz[k]->Zero(); - matricesDistDPhiRDz[k]->Zero(); - matricesDistDz[k]->Zero(); - matricesCorrDrDz[k]->Zero(); - matricesCorrDPhiRDz[k]->Zero(); - matricesCorrDz[k]->Zero(); - - matricesGDistDrDz[k]->Zero(); - matricesGDistDPhiRDz[k]->Zero(); - matricesGDistDz[k]->Zero(); - matricesGCorrDrDz[k]->Zero(); - matricesGCorrDPhiRDz[k]->Zero(); - matricesGCorrDz[k]->Zero(); - } - - if (side == 0) { - matricesIrregularDrDz = fMatrixIntCorrDrEzIrregularA; - matricesIrregularDPhiRDz = fMatrixIntCorrDPhiREzIrregularA; - matricesIrregularDz = fMatrixIntCorrDzIrregularA; - - matricesPhiIrregular = fMatrixPhiListIrregularA; - matricesRIrregular = fMatrixRListIrregularA; - matricesZIrregular = fMatrixZListIrregularA; - matricesLookUpCharge = fMatrixChargeA; - - chargeInterpolator = fInterpolatorChargeA; - potentialInterpolator = fInterpolatorPotentialA; - fLookupDistA->SetLookUpR(matricesDistDrDz); - fLookupDistA->SetLookUpPhi(matricesDistDPhiRDz); - fLookupDistA->SetLookUpZ(matricesDistDz); - - fLookupElectricFieldA->SetLookUpR(matricesEr); - fLookupElectricFieldA->SetLookUpPhi(matricesEPhi); - fLookupElectricFieldA->SetLookUpZ(matricesEz); - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // potentialBoundary = fListPotentialBoundaryA; - f1BoundaryIFC = fFormulaBoundaryIFCA; - f1BoundaryOFC = fFormulaBoundaryOFCA; - f1BoundaryROC = fFormulaBoundaryROCA; - } else { - matricesIrregularDrDz = fMatrixIntCorrDrEzIrregularC; - matricesIrregularDPhiRDz = fMatrixIntCorrDPhiREzIrregularC; - matricesIrregularDz = fMatrixIntCorrDzIrregularC; - matricesPhiIrregular = fMatrixPhiListIrregularC; - matricesRIrregular = fMatrixRListIrregularC; - matricesZIrregular = fMatrixZListIrregularC; - matricesLookUpCharge = fMatrixChargeC; - - chargeInterpolator = fInterpolatorChargeC; - potentialInterpolator = fInterpolatorPotentialC; - fLookupDistC->SetLookUpR(matricesDistDrDz); - fLookupDistC->SetLookUpPhi(matricesDistDPhiRDz); - fLookupDistC->SetLookUpZ(matricesDistDz); - fLookupElectricFieldC->SetLookUpR(matricesEr); - fLookupElectricFieldC->SetLookUpPhi(matricesEPhi); - fLookupElectricFieldC->SetLookUpZ(matricesEz); - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // potentialBoundary = fListPotentialBoundaryC; - f1BoundaryIFC = fFormulaBoundaryIFCC; - f1BoundaryOFC = fFormulaBoundaryOFCC; - f1BoundaryROC = fFormulaBoundaryROCC; - } - // fill the potential boundary - // guess the initial potential - // fill also charge - //pIndex = 0; - - //Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz","%s",Form("Step = 0: Fill Boundary and Charge Densities")); - for (Int_t k = 0; k < phiSlice; k++) { - phi0 = k * gridSizePhi; - matrixV = matricesV[k]; - matrixCharge = matricesCharge[k]; - for (Int_t i = 0; i < nRRow; i++) { - radius0 = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - for (Int_t j = 0; j < nZColumn; j++) { - z0 = j * gridSizeZ; - (*matrixCharge)(i, j) = chargeInterpolator->GetValue(rList[i], phiList[k], zList[j]); - (*matrixV)(i, j) = fFormulaPotentialV->Eval(radius0, phi0, z0); - } - } - } - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 0: Preparing Charge interpolator: %f\n", w.CpuTime())); - - potentialInterpolator->SetValue(matricesV); - potentialInterpolator->InitCubicSpline(); - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 1: Poisson solver: %f\n", w.CpuTime())); - w.Start(); - w.Stop(); - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 2: Electric Field Calculation: %f\n", w.CpuTime())); - w.Start(); - w.Stop(); - - // copy to interpolator - LocalDistCorrDz(intErDzTestFunction, intEPhiRDzTestFunction, intDzTestFunction, - GetEzFormula(), rList, phiList, zList, - matricesDistDrDz, matricesDistDPhiRDz, matricesDistDz, - matricesCorrDrDz, matricesCorrDPhiRDz, matricesCorrDz, - nRRow, nZColumn, phiSlice, gridSizeZ, ezField); - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 3: Local distortion and correction: %f\n", w.CpuTime())); - lookupLocalDist->CopyFromMatricesToInterpolator(); - lookupLocalCorr->CopyFromMatricesToInterpolator(); - if (side == 0) { - fLookupDistA->CopyFromMatricesToInterpolator(); - fLookupElectricFieldA->CopyFromMatricesToInterpolator(); - } else { - fLookupDistC->CopyFromMatricesToInterpolator(); - fLookupElectricFieldC->CopyFromMatricesToInterpolator(); - } - - w.Start(); - - IntegrateDistCorrDriftLineDz(intErDzTestFunction, intEPhiRDzTestFunction, intDzTestFunction, GetEzFormula(), ezField, - matricesGDistDrDz, matricesGDistDPhiRDz, matricesGDistDz, - matricesGCorrDrDz, matricesGCorrDPhiRDz, matricesGCorrDz, - matricesIrregularDrDz, matricesIrregularDPhiRDz, matricesIrregularDz, - matricesRIrregular, matricesPhiIrregular, matricesZIrregular, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 4: Global correction/distortion: %f\n", w.CpuTime())); - w.Start(); - - //// copy to 1D interpolator ///// - lookupGlobalDist->CopyFromMatricesToInterpolator(); - lookupGlobalCorr->CopyFromMatricesToInterpolator(); - //// - - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Step 5: Filling up the look up: %f\n", w.CpuTime())); - - if (side == 0) { - FillLookUpTable(lookupGlobalDist, - fMatrixIntDistDrEzA, fMatrixIntDistDPhiREzA, fMatrixIntDistDzA, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - FillLookUpTable(lookupGlobalCorr, - fMatrixIntCorrDrEzA, fMatrixIntCorrDPhiREzA, fMatrixIntCorrDzA, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - fLookupIntDistA->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - fLookupIntCorrA->CopyFromMatricesToInterpolator(); - } else { - fLookupIntCorrIrregularA->CopyFromMatricesToInterpolator(); - } - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " A side done"); - } - if (side == 1) { - FillLookUpTable(lookupGlobalDist, - fMatrixIntDistDrEzC, fMatrixIntDistDPhiREzC, fMatrixIntDistDzC, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - FillLookUpTable(lookupGlobalCorr, - fMatrixIntCorrDrEzC, fMatrixIntCorrDPhiREzC, fMatrixIntCorrDzC, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - - fLookupIntDistC->CopyFromMatricesToInterpolator(); - if (fCorrectionType == 0) { - fLookupIntCorrC->CopyFromMatricesToInterpolator(); - } else { - fLookupIntCorrIrregularC->CopyFromMatricesToInterpolator(); - } - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " C side done"); - } - } - - fInitLookUp = kTRUE; - } - - // memory de-allocation for temporary matrices - for (Int_t k = 0; k < phiSlice; k++) { - delete matricesV[k]; - delete matricesCharge[k]; - delete matricesEr[k]; - delete matricesEPhi[k]; - delete matricesEz[k]; - delete matricesDistDrDz[k]; - delete matricesDistDPhiRDz[k]; - delete matricesDistDz[k]; - - delete matricesCorrDrDz[k]; - delete matricesCorrDPhiRDz[k]; - delete matricesCorrDz[k]; - delete matricesGDistDrDz[k]; - delete matricesGDistDPhiRDz[k]; - delete matricesGDistDz[k]; - - delete matricesGCorrDrDz[k]; - delete matricesGCorrDPhiRDz[k]; - delete matricesGCorrDz[k]; - } - delete lookupLocalDist; - delete lookupLocalCorr; - delete lookupGlobalDist; - delete lookupGlobalCorr; -} -/// Creating look-up tables of Correction/Distortion by linear integration -/// on z line -/// -/// \param nRRow Int_t number of grid in row direction -/// \param nZColumn Int_t number of grid in z direction -/// \param phiSlice Int_t number of slices in phi direction -/// \param maxIteration Int_t max iteration for convergence -/// \param stoppingConvergence Double_t stopping criteria for convergence -/// \post Lookup tables for distortion: -/// ~~~ -/// fLookUpIntDistDrEz,fLookUpIntDistDPhiREz,fLookUpIntDistDz -/// ~~~ fo -/// and correction: -/// ~~~ -/// fLookUpIntCorrDrEz,fLookUpIntCorrDPhiREz,fLookUpIntCorrDz -/// ~~~ -/// are initialized -/// -void AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoisson(Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, - Double_t stoppingConvergence) -{ - // Compute grid size for all direction - Int_t phiSlicesPerSector = phiSlice / kNumSector; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - const Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm; - - // local variables - Float_t radius0, phi0, z0; - - // memory allocation for temporary matrices: - // potential (boundary values), charge distribution - - TMatrixD *matricesV[phiSlice], *matricesCharge[phiSlice]; - TMatrixD *matricesEr[phiSlice], *matricesEPhi[phiSlice], *matricesEz[phiSlice]; - - for (Int_t k = 0; k < phiSlice; k++) { - matricesEr[k] = new TMatrixD(nRRow, nZColumn); - matricesEPhi[k] = new TMatrixD(nRRow, nZColumn); - matricesEz[k] = new TMatrixD(nRRow, nZColumn); - matricesV[k] = new TMatrixD(nRRow, nZColumn); - matricesCharge[k] = new TMatrixD(nRRow, nZColumn); - } - - // list of point as used in the poisson relaxation and the interpolation (for interpolation) - Double_t rList[nRRow], zList[nZColumn], phiList[phiSlice]; - - for (Int_t k = 0; k < phiSlice; k++) { - phiList[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < nRRow; i++) { - rList[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < nZColumn; j++) { - zList[j] = j * gridSizeZ; - } - // should be set, in another place - const Int_t symmetry = 0; - // do if look up table haven't be initialized - if (!fInitLookUp) { - for (Int_t side = 0; side < 2; side++) { - for (Int_t k = 0; k < phiSlice; k++) { - TMatrixD* mV = matricesV[k]; - TMatrixD* mCharge = matricesCharge[k]; - phi0 = phiList[k]; - for (Int_t i = 0; i < nRRow; i++) { - radius0 = rList[i]; - for (Int_t j = 0; j < nZColumn; j++) { - z0 = zList[j]; - if (side == 1) { - z0 = -TMath::Abs(zList[j]); - } - if (fHistogram3DSpaceCharge != nullptr) { - // * Boundary values and charge distribution setup - (*mV)(i, j) = 0.0; - (*mCharge)(i, j) = -1 * InterpolatePhi(fHistogram3DSpaceCharge, phi0, radius0, z0); - } - } - } - } - AliTPCLookUpTable3DInterpolatorD* lookupEField = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, - matricesEr, - rList, phiSlice, - matricesEPhi, - phiList, nZColumn, - matricesEz, - zList, - fInterpolationOrder); - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "Step 1: Solving poisson solver"); - fPoissonSolver->PoissonSolver3D(matricesV, matricesCharge, nRRow, nZColumn, phiSlice, maxIteration, symmetry); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "Step 2: Calculate electric field"); - CalculateEField( - matricesV, - matricesEr, - matricesEPhi, - matricesEz, - nRRow, - nZColumn, - phiSlice, - maxIteration, - symmetry); - lookupEField->CopyFromMatricesToInterpolator(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "Step 3: Fill the look up table"); - - if (side == 0) { - FillLookUpTable(lookupEField, - fMatrixErOverEzA, fMatrixEPhiOverEzA, fMatrixDeltaEzA, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - fLookupIntENoDriftA->CopyFromMatricesToInterpolator(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " A side done"); - } - if (side == 1) { - FillLookUpTable(lookupEField, - fMatrixErOverEzC, fMatrixEPhiOverEzC, fMatrixDeltaEzC, - nRRow, nZColumn, phiSlice, rList, phiList, zList); - fLookupIntENoDriftC->CopyFromMatricesToInterpolator(); - - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", " C side done"); - } - delete lookupEField; - } - fInitLookUp = kTRUE; - } - - for (Int_t k = 0; k < phiSlice; k++) { - delete matricesV[k]; - delete matricesCharge[k]; - delete matricesEr[k]; - delete matricesEPhi[k]; - delete matricesEz[k]; - } -} -/// Force creating look-up table of Correction/Distortion by integration following -/// drift line. -/// -/// \param nRRow Int_t Number of nRRow in r-direction -/// \param nZColumn Int_t Number of nZColumn in z-direction -/// \param phiSlice Int_t Number of phi slices in \f$ phi \f$ direction -/// \param maxIteration Int_t Maximum iteration for poisson solver -/// \param stoppingConvergence Convergence error stopping condition for poisson solver -/// -void AliTPCSpaceCharge3DCalc::ForceInitSpaceCharge3DPoissonIntegralDz(Int_t nRRow, Int_t nZColumn, Int_t phiSlice, - Int_t maxIteration, Double_t stoppingConvergence) -{ - fInitLookUp = kFALSE; - InitSpaceCharge3DPoissonIntegralDz(nRRow, nZColumn, phiSlice, maxIteration, stoppingConvergence); -} -/// Electric field Calculation: -/// -/// -/// \param matricesV -/// \param matricesEr -/// \param matricesEPhi -/// \param matricesEz -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -/// \param gridSizeR -/// \param gridSizePhi -/// \param gridSizeZ -/// \param symmetry -/// \param innerRadius -/// -/// \pre Matrix matricesV is assumed had been calculated by Poisson solver -/// \post Results of E-fields are calculated by measuring gradient at potential distribution -/// -/// -/// * Differentiate potential on all direction (r,z and phi) -/// * Non-boundary -> Central difference (3 stencil) TODO: 5 Stencil -/// -/// \f$ \nabla_{r} V(r_{i},\phi_{j},z_{k}) \approx -( V_{i+1,j,k} - V_{i-1,j,k}) / (2* h_{r}) \f$ -/// -/// \f$ -\nabla_{\phi} V(r_{i},\phi_{j},z_{k}) \approx -( V_{i,j-1,k} - V_{i,j+1,k}) / (2* r_{j} * h_{\phi}) \f$ -/// -/// \f$ -\nabla_{z} V(r_{i},\phi_{j},z_{k}) \approx -( V_{i,j,k+1} - V_{i,j,k-1}) / (2* h_{z}) \f$ -/// -/// ~~~ cxx -/// matrixEr(i,j) = -1 * ( arrayV(i+1,j) - arrayV(i-1,j) ) / (2*gridSizeR); // r direction -/// matrixEz(i,j) = -1 * ( arrayV(i,j+1) - arrayV(i,j-1) ) / (2*gridSizeZ) ; // z direction -/// matrixEPhi(i,j) = -1 * (signPlus * arrayVP(i,j) - signMinus * arrayVM(i,j) ) / (2*radius*gridSizePhi) -/// ~~~ -/// -/// * Boundary -> Forward/Backward difference (3 stencil) TODO: 5 Stencil -/// -/// \f$ -\nabla_{r} V(r_{0},\phi_{j},z_{k}) \approx -( -0.5 V_{2,j,k} + 2 V_{1,j,k} - 1.5 * V_{0,j,k}) / h_{r} \f$ -/// -/// \f$ -\nabla_{r} V(r_{nRRow - 1},\phi_{j},z_{k}) \approx -( 1.5 V_{nRRow-1,j,k} - 2.0 V_{nRRow-2,j,k} + 0.5 V_{nRRow -3,j,k}) / h_{\phi} \f$ -/// -void AliTPCSpaceCharge3DCalc::ElectricField(TMatrixD** matricesV, TMatrixD** matricesEr, TMatrixD** matricesEPhi, - TMatrixD** matricesEz, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, - const Float_t gridSizeR, const Float_t gridSizePhi, - const Float_t gridSizeZ, - const Int_t symmetry, const Float_t innerRadius) -{ - Float_t radius; - Int_t mPlus, mMinus, signPlus, signMinus; - for (Int_t m = 0; m < phiSlice; m++) { - mPlus = m + 1; - signPlus = 1; - mMinus = m - 1; - signMinus = 1; - if (symmetry == 1) { // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - } - if (mMinus < 0) { - mMinus = 1; - } - } else if (symmetry == -1) { // Anti-symmetry in phi - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - signPlus = -1; - } - if (mMinus < 0) { - mMinus = 1; - signMinus = -1; - } - } else { // No Symmetries in phi, no boundaries, the calculations is continuous across all phi - if (mPlus > phiSlice - 1) { - mPlus = m + 1 - phiSlice; - } - if (mMinus < 0) { - mMinus = m - 1 + phiSlice; - } - } - - TMatrixD& arrayVP = *matricesV[mPlus]; - TMatrixD& arrayVM = *matricesV[mMinus]; - TMatrixD& arrayV = *matricesV[m]; - TMatrixD& matrixEr = *matricesEr[m]; - TMatrixD& matrixEz = *matricesEz[m]; - TMatrixD& matrixEPhi = *matricesEPhi[m]; - - // for non-boundary V - for (Int_t i = 1; i < nRRow - 1; i++) { - radius = innerRadius + i * gridSizeR; - for (Int_t j = 1; j < nZColumn - 1; j++) { - matrixEr(i, j) = -1 * (arrayV(i + 1, j) - arrayV(i - 1, j)) / (2 * gridSizeR); // r direction - matrixEz(i, j) = -1 * (arrayV(i, j + 1) - arrayV(i, j - 1)) / (2 * gridSizeZ); // z direction - matrixEPhi(i, j) = -1 * (signPlus * arrayVP(i, j) - signMinus * arrayVM(i, j)) / - (2 * radius * gridSizePhi); // phi direction - } - } - - // for boundary-r - for (Int_t j = 0; j < nZColumn; j++) { - matrixEr(0, j) = -1 * (-0.5 * arrayV(2, j) + 2.0 * arrayV(1, j) - 1.5 * arrayV(0, j)) / - gridSizeR; // forward difference - matrixEr(nRRow - 1, j) = - -1 * (1.5 * arrayV(nRRow - 1, j) - 2.0 * arrayV(nRRow - 2, j) + 0.5 * arrayV(nRRow - 3, j)) / - gridSizeR; // backward difference - } - - for (Int_t i = 0; i < nRRow; i += nRRow - 1) { - radius = innerRadius + i * gridSizeR; - for (Int_t j = 1; j < nZColumn - 1; j++) { - matrixEz(i, j) = -1 * (arrayV(i, j + 1) - arrayV(i, j - 1)) / (2 * gridSizeZ); // z direction - matrixEPhi(i, j) = -1 * (signPlus * arrayVP(i, j) - signMinus * arrayVM(i, j)) / - (2 * radius * gridSizePhi); // phi direction - } - } - - // for boundary-z - for (Int_t i = 0; i < nRRow; i++) { - matrixEz(i, 0) = -1 * (-0.5 * arrayV(i, 2) + 2.0 * arrayV(i, 1) - 1.5 * arrayV(i, 0)) / gridSizeZ; - matrixEz(i, nZColumn - 1) = - -1 * - (1.5 * arrayV(i, nZColumn - 1) - 2.0 * arrayV(i, nZColumn - 2) + 0.5 * arrayV(i, nZColumn - 3)) / - gridSizeZ; - } - - for (Int_t i = 1; i < nRRow - 1; i++) { - radius = innerRadius + i * gridSizeR; - for (Int_t j = 0; j < nZColumn; j += nZColumn - 1) { - matrixEr(i, j) = -1 * (arrayV(i + 1, j) - arrayV(i - 1, j)) / (2 * gridSizeR); // r direction - matrixEPhi(i, j) = -1 * (signPlus * arrayVP(i, j) - signMinus * arrayVM(i, j)) / - (2 * radius * gridSizePhi); // phi direction - } - } - - // corner points for EPhi - for (Int_t i = 0; i < nRRow; i += nRRow - 1) { - radius = innerRadius + i * gridSizeR; - for (Int_t j = 0; j < nZColumn; j += nZColumn - 1) { - matrixEPhi(i, j) = -1 * (signPlus * arrayVP(i, j) - signMinus * arrayVM(i, j)) / - (2 * radius * gridSizePhi); // phi direction - } - } - } -} -/// -/// Local distortion and correction, calculate local distortion/correction -/// based on simplified langevin equation, see internal note ALICE-INT-2010-016. -/// -/// <b> Local Distortion </b> -/// -/// Local distortion is calculated based on formulation in ALICE-INT-2010-016, this function assume that -/// electric field \f$\vec{E}(r_{i},z_{j},\phi_{m})\f$ is provided. -/// -/// First, we calculate integration of the Electric field in z-direction for all direction. -/// Assumption: \f$ z_{0} \f$ is location of CE (Central Electrode) and \f$ z_{nZColumn - 1} \f$ is location of End Plate. -/// -/// This integration is in \f$z\f$ direction we can only use trapezoidal rule. -/// -/// Let suppose we want to calculate local distortion at \f$(r_{i},z_{j},\phi_{m})\f$. -/// Assume \f$\vec{E}(r_{i},z_{j+1},\phi_{m}) \f$ and \f$\vec{E}(r_{i},z_{j},\phi_{m}) \f$ are known, see Figure \ref fig1 (a), -/// -/// \anchor fig1 -/// ![Local Distortion](localdist.png) -/// -/// Than we can calculate definite integrations for each directions in respect of $z$ from \f$ z_{j} \f$ to \f$ z_{j + 1} \f$ as follows: -/// -/// \f$ \int^{z_{j+1}}_{z_{j}} \frac{E_{r}}{E_{z}}(r_{i},z_{j},\phi_{m}) dzDist \approx \frac{-1}{\mathrm{ezField}} \frac{h_{z}}{2.0} \left( E_{r}(r_{i},z_{j},\phi_{m}) + E_{r}(r_{i},z_{j+1},\phi_{m}) \right)\f$ -/// -/// \f$ \int^{z_{j+1}}_{z_{j}} \frac{E_{\phi}}{E_{z}}(r_{i},z_{j},\phi_{m}) dzDist \approx \frac{-1}{\mathrm{ezField}} \frac{h_{z}}{2.0} \left( E_{\phi}(r_{i},z_{j},\phi_{m}) + E_{\phi}(r_{i},z_{j+1},\phi_{m}) \right)\f$ -/// -/// \f$ \int^{z_{j+1}}_{z_{j}} E_{z}(r_{i},z_{j},\phi_{m}) dzDist \approx \frac{h_{z}}{2.0} \left( E_{z}(r_{i},z_{j},\phi_{m}) + E_{z}(r_{i},z_{j+1},\phi_{m}) \right) \f$ -/// -/// Code sample at \ref impllocaldist is an implementation of the local integration of electric field. -/// -/// \anchor impllocaldist -/// ~~~ -/// Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV-AliTPCPoissonSolver::fgkGG)/AliTPCPoissonSolver::fgkTPCZ0; // = Electric Field (V/cm) Magnitude ~ -400 V/cm; -/// -/// localIntErOverEz = (gridSizeZ/2.0)*((*eR)(i,j)+(*eR)(i,j+1))/(ezField + (*eZ)(i,j)) ; -/// localIntEPhiOverEz = (gridSizeZ/2.0)*((*ePhi)(i,j)+(*ePhi)(i,j+1))/(ezField + (*eZ)(i,j)) ; -/// localIntDeltaEz = (gridSizeZ/2.0)*((*eZ)(i,j)+(*eZ)(i,j+1)) ; -/// ~~~ -/// -/// -/// After we have local integrations for electric fields in each direction, -/// local distortion \f$\hat{\delta}(r_{i},z_{j},\phi_{m})\f$ is calculated by simplified Langevin equation (see Figure \ref1 (b) for illustration): -/// -/// \f$ \hat{\delta}_{rE}(r_{i},z_{j},\phi_{m}) = c_{0} \int^{z_{j+1}}_{z_{j}} \frac{E_{r}}{E_{z}} dzDist + c_{1} \int^{z_{j+1}}_{z_{j}} \frac{E_{\phi}}{E_{z}} dzDist \f$ -/// -/// ~~~ -/// (*distDrDz)(i,j) = fC0*localIntErOverEz + fC1*localIntEPhiOverEz; -/// ~~~ -/// -/// \f$ r\hat{\delta}_{\phi E}(r_{i},z_{j},\phi_{m}) = - c_{1} \int^{z_{j+1}}_{z_{j}} \frac{E_{j}}{E_{j}} dzDist + c_{0} \int^{z_{j+1}}_{j_{j}} \frac{E_{\phi}}{E_{z}} dzDist \f$ -/// -/// ~~~ -/// (*distDPhiRDz)(i,j) = fC0*localIntEPhiOverEz - fC1*localIntErOverEz ; -/// ~~~ -/// -/// \f$ \hat{\delta}_{z}(r_{i},z_{j},\phi_{m}) = \int_{z_{j}}^{z_{j+1}} \frac{v^{\prime}(E)}{v_{0}} (E - E_{0}) dzDist\f$ -/// -/// ~~~ -/// (*distDz)(i,j) = localIntDeltaEz*-1*AliTPCPoissonSolver::fgkdvdE; -/// ~~~ -/// -/// Where \f$c_{0}\f$ and \f$c_{1}\f$ are constants (see the ALICE-INT-2010-016 for further details). -/// -/// <b> Local correction </b> -/// -/// Local correction is computed as local distortion where the electric fields are in opposite direction (see Figure \ref fig2 (a)). -/// -/// \anchor fig2 -/// ![Local Correction](localcorr.png) -/// -/// Let suppose we want to calculate local correction at \f$(r_{i},\mathbf{z_{j+1}},\phi_{m})\f$. -/// Assume \f$\vec{E}(r_{i},z_{j+1},\phi_{m}) \f$ and \f$\vec{E}(r_{i},z_{j},\phi_{m}) \f$ are known. -/// -/// Than we can calculate definite integrations for each directions in respect of \f$z\f$ from \f$ z_{j+1} \f$ to \f$ z_{j} \f$ as follows: -/// -/// \f$ \int^{z_{j}}_{z_{j+1}} \frac{E_{r}}{E_{z}}(r_{i},z_{j},\phi_{m}) dzDist \approx -1 * \frac{-1}{\mathrm{ezField}} \frac{h_{z}}{2.0} \left( E_{r}(r_{i},z_{j},\phi_{m}) + E_{r}(r_{i},z_{j+1},\phi_{m}) \right)\f$ -/// -/// \f$ \int^{z_{j}}_{z_{j+1}} \frac{E_{\phi}}{E_{z}}(r_{i},z_{j},\phi_{m}) dzDist \approx -1 * \frac{-1}{\mathrm{ezField}} \frac{h_{z}}{2.0} \left( E_{\phi}(r_{i},z_{j},\phi_{m}) + E_{\phi}(r_{i},z_{j+1},\phi_{m}) \right)\f$ -/// -/// \f$ \int^{z_{j}}_{z_{j+1}} E_{z}(r_{i},z_{j},\phi_{m}) dzDist \approx -1 * \frac{h_{z}}{2.0} \left( E_{z}(r_{i},z_{j},\phi_{m}) + E_{z}(r_{i},z_{j+1},\phi_{m}) \right) \f$ -/// -/// Local correction at \f$\hat{\delta'}(r_{i},\mathbf{z_{j+1}},\phi_{m})\f$ is calculated by simplified Langevin equation (see Figure \ref fig2 (b) for illustration): -/// -/// \f$ \hat{\delta'}_{rE}(r_{i},z_{j+1},\phi_{m}) = c_{0} \int^{z_{j}}_{z_{j+1}} \frac{E_{r}}{E_{z}} dzDist + c_{1} \int^{z_{j-1}}_{z_{j}} \frac{E_{\phi}}{E_{z}} dzDist \f$ -/// -/// \f$ r\hat{\delta'}_{\phi E}(r_{i},z_{j+1},\phi_{m}) = - c_{1} \int^{z_{j}}_{z_{j+1}} \frac{E_{j}}{E_{j}} dzDist + c_{0} \int^{z_{j-1}}_{j_{k}} \frac{E_{\phi}}{E_{z}} dzDist \f$ -/// -/// \f$ \hat{\delta'}_{z}(r_{i},z_{j+1},\phi_{m}) = \int_{z_{j}}^{z_{j+1}} \frac{v^{\prime}(E)}{v_{0}} (E - E_{0}) dzDist\f$ -/// -/// For implementation, we use the fact that -/// -/// \f$ \hat{\delta'}_{rE}(r_{i},z_{j+1},\phi_{m}) = -1 * \hat{\delta}_{rE}(r_{i},z_{j},\phi_{m}) \f$ -/// -/// \f$ r\hat{\delta'}_{\phi E}(r_{i},z_{j+1},\phi_{m}) = -1 * r\hat{\delta}_{\phi E}(r_{i},z_{j},\phi_{m}) \f$ -/// -/// \f$ \hat{\delta'}_{z}(r_{i},z_{j+1},\phi_{m}) = -1 * \hat{\delta}_{z}(r_{i},z_{j},\phi_{m}) \f$ -/// -/// ~~~ -/// (*corrDrDz)(i,j+1) = -1* (*distDrDz)(i,j) ; -/// (*corrDPhiRDz)(i,j+1) = -1* (*distDPhiRDz)(i,j); -/// (*corrDz)(i,j+1) = -1* (*distDz)(i,j); -/// ~~~ -/// -/// \param matricesEr TMatrixD** electric field for \f$r\f$ component -/// \param matricesEPhi TMatrixD** electric field for \f$\phi\f$ component -/// \param matricesEz TMatrixD** electric field for \f$z\f$ component -/// \param matricesDistDrDz TMatrixD** local distortion \f$\hat{\delta}_{r}\f$ -/// \param matricesDistDPhiRDz TMatrixD** local distortion \f$r \hat{\delta}_{\phi}\f$ -/// \param matricesDistDz TMatrixD** local distortion \f$ \hat{\delta}_{z}\f$ -/// \param matricesCorrDrDz TMatrixD** local correction \f$\hat{\delta}_{r}\f$ -/// \param matricesCorrDPhiRDz TMatrixD** local correction \f$r \hat{\delta}_{\phi}\f$ -/// \param matricesCorrDz TMatrixD** local correction \f$ \hat{\delta}_{z}\f$ -/// \param nRRow Int_t Number of nRRow in r-direction -/// \param nZColumn Int_t Number of nZColumn in z-direction -/// \param phiSlice Int_t Number of phi slices in \f$ phi \f$ direction -/// \param gridSizeZ const Float_t grid size in z direction -/// \param ezField const Double_t ezField calculated from the invoking operation -/// -/// \pre matricesEr, matricesEPhi, matrices Ez assume already been calculated -/// \post Local distortion and correction are computed according simplified Langevin equation -/// ~~~ -/// matricesDistDrDz,matricesDistDPhiRDz,matricesDistDz -/// ~~~ -/// and correction: -/// ~~~ -/// matricesCorrDrDz,matricesCorrDPhiRDz,matricesCorrDz -/// ~~~ -/// -void AliTPCSpaceCharge3DCalc::LocalDistCorrDz(TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, - TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, - TMatrixD** matricesDistDz, - TMatrixD** matricesCorrDrDz, TMatrixD** matricesCorrDPhiRDz, - TMatrixD** matricesCorrDz, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Float_t gridSizeZ, - const Double_t ezField) -{ - Float_t localIntErOverEz = 0.0; - Float_t localIntEPhiOverEz = 0.0; - Float_t localIntDeltaEz = 0.0; - TMatrixD* eR; - TMatrixD* ePhi; - TMatrixD* eZ; - TMatrixD* distDrDz; - TMatrixD* distDPhiRDz; - TMatrixD* distDz; - TMatrixD* corrDrDz; - TMatrixD* corrDPhiRDz; - TMatrixD* corrDz; - - // Initialization for j == column-1 integration is 0.0 - for (Int_t m = 0; m < phiSlice; m++) { - distDrDz = matricesDistDrDz[m]; - distDPhiRDz = matricesDistDPhiRDz[m]; - distDz = matricesDistDz[m]; - - corrDrDz = matricesCorrDrDz[m]; - corrDPhiRDz = matricesCorrDPhiRDz[m]; - corrDz = matricesCorrDz[m]; - - for (Int_t i = 0; i < nRRow; i++) { - (*distDrDz)(i, nZColumn - 1) = 0.0; - (*distDPhiRDz)(i, nZColumn - 1) = 0.0; - (*distDz)(i, nZColumn - 1) = 0.0; - - (*corrDrDz)(i, 0) = 0.0; - (*corrDPhiRDz)(i, 0) = 0.0; - (*corrDz)(i, 0) = 0.0; - } - } - - // for this case - // use trapezoidal rule assume no ROC displacement - for (Int_t m = 0; m < phiSlice; m++) { - eR = matricesEr[m]; - ePhi = matricesEPhi[m]; - eZ = matricesEz[m]; - distDrDz = matricesDistDrDz[m]; - distDPhiRDz = matricesDistDPhiRDz[m]; - distDz = matricesDistDz[m]; - - corrDrDz = matricesCorrDrDz[m]; - corrDPhiRDz = matricesCorrDPhiRDz[m]; - corrDz = matricesCorrDz[m]; - - for (Int_t j = 0; j < nZColumn - 1; j++) { - for (Int_t i = 0; i < nRRow; i++) { - double eZ0 = ezField + (*eZ)(i, j); - double eZ1 = ezField + (*eZ)(i, j + 1); - localIntErOverEz = (gridSizeZ * 0.5) * ((*eR)(i, j) / eZ0 + (*eR)(i, j + 1) / eZ1); - localIntEPhiOverEz = (gridSizeZ * 0.5) * ((*ePhi)(i, j) / eZ0 + (*ePhi)(i, j + 1) / eZ1); - localIntDeltaEz = (gridSizeZ * 0.5) * ((*eZ)(i, j) + (*eZ)(i, j + 1)); - - (*distDrDz)(i, j) = fC0 * localIntErOverEz + fC1 * localIntEPhiOverEz; - (*distDPhiRDz)(i, j) = fC0 * localIntEPhiOverEz - fC1 * localIntErOverEz; - (*distDz)(i, j) = localIntDeltaEz * -1 * AliTPCPoissonSolver::fgkdvdE; - - (*corrDrDz)(i, j + 1) = -1 * (*distDrDz)(i, j); - (*corrDPhiRDz)(i, j + 1) = -1 * (*distDPhiRDz)(i, j); - (*corrDz)(i, j + 1) = -1 * (*distDz)(i, j); - } - } - } -} -/// -/// Local distortion and correction, calculate local distortion/correction for known analitics functions -/// based on simplified langevin equation, see internal note ALICE-INT-2010-016. -/// -/// \param matricesEPhi TMatrixD** electric field for \f$\phi\f$ component -/// \param matricesEz TMatrixD** electric field for \f$z\f$ component -/// \param matricesDistDrDz TMatrixD** local distortion \f$\hat{\delta}_{r}\f$ -/// \param matricesDistDPhiRDz TMatrixD** local distortion \f$r \hat{\delta}_{\phi}\f$ -/// \param matricesDistDz TMatrixD** local distortion \f$ \hat{\delta}_{z}\f$ -/// \param matricesCorrDrDz TMatrixD** local correction \f$\hat{\delta}_{r}\f$ -/// \param matricesCorrDPhiRDz TMatrixD** local correction \f$r \hat{\delta}_{\phi}\f$ -/// \param matricesCorrDz TMatrixD** local correction \f$ \hat{\delta}_{z}\f$ -/// \param nRRow Int_t Number of nRRow in r-direction -/// \param nZColumn Int_t Number of nZColumn in z-direction -/// \param phiSlice Int_t Number of phi slices in \f$ phi \f$ direction -/// \param gridSizeZ const Float_t grid size in z direction -/// \param ezField const Double_t ezField calculated from the invoking operation -/// -/// \pre matricesEr, matricesEPhi, matrices Ez assume already been calculated -/// \post Local distortion and correction are computed according simplified Langevin equation -/// ~~~ -/// matricesDistDrDz,matricesDistDPhiRDz,matricesDistDz -/// ~~~ -/// and correction: -/// ~~~ -/// matricesCorrDrDz,matricesCorrDPhiRDz,matricesCorrDz -/// ~~~ -/// -void AliTPCSpaceCharge3DCalc::LocalDistCorrDz(TFormula* intErDzFunction, TFormula* intEPhiRDzFunction, TFormula* intDzFunction, - TFormula* ezFunction, Double_t* rList, Double_t* phiList, Double_t* zList, TMatrixD** matricesDistDrDz, - TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, TMatrixD** matricesCorrDrDz, - TMatrixD** matricesCorrDPhiRDz, TMatrixD** matricesCorrDz, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, const Float_t gridSizeZ, const Double_t ezField) -{ - Float_t localIntErOverEz = 0.0; - Float_t localIntEPhiOverEz = 0.0; - Float_t localIntDeltaEz = 0.0; - TMatrixD* distDrDz; - TMatrixD* distDPhiRDz; - TMatrixD* distDz; - TMatrixD* corrDrDz; - TMatrixD* corrDPhiRDz; - TMatrixD* corrDz; - - Double_t radius, phi, z0, z1; - - // Initialization for j == column-1 integration is 0.0 - for (Int_t m = 0; m < phiSlice; m++) { - distDrDz = matricesDistDrDz[m]; - distDPhiRDz = matricesDistDPhiRDz[m]; - distDz = matricesDistDz[m]; - - corrDrDz = matricesCorrDrDz[m]; - corrDPhiRDz = matricesCorrDPhiRDz[m]; - corrDz = matricesCorrDz[m]; - - for (Int_t i = 0; i < nRRow; i++) { - (*distDrDz)(i, nZColumn - 1) = 0.0; - (*distDPhiRDz)(i, nZColumn - 1) = 0.0; - (*distDz)(i, nZColumn - 1) = 0.0; - - (*corrDrDz)(i, 0) = 0.0; - (*corrDPhiRDz)(i, 0) = 0.0; - (*corrDz)(i, 0) = 0.0; - } - } - - // for this case - // use trapezoidal rule assume no ROC displacement - for (Int_t m = 0; m < phiSlice; m++) { - phi = phiList[m]; - distDrDz = matricesDistDrDz[m]; - distDPhiRDz = matricesDistDPhiRDz[m]; - distDz = matricesDistDz[m]; - - corrDrDz = matricesCorrDrDz[m]; - corrDPhiRDz = matricesCorrDPhiRDz[m]; - corrDz = matricesCorrDz[m]; - - for (Int_t i = 0; i < nRRow; i++) { - radius = rList[i]; - - for (Int_t j = 0; j < nZColumn - 1; j++) { - z0 = zList[j]; - z1 = zList[j + 1]; - - localIntErOverEz = (intErDzFunction->Eval(radius, phi, z1) - intErDzFunction->Eval(radius, phi, z0)) / (ezField + ezFunction->Eval(radius, phi, z0)); - localIntEPhiOverEz = (intEPhiRDzFunction->Eval(radius, phi, z1) - intEPhiRDzFunction->Eval(radius, phi, z0)) / (ezField + ezFunction->Eval(radius, phi, z0)); - localIntDeltaEz = intDzFunction->Eval(radius, phi, z1) - intDzFunction->Eval(radius, phi, z0); - - (*distDrDz)(i, j) = fC0 * localIntErOverEz + fC1 * localIntEPhiOverEz; - (*distDPhiRDz)(i, j) = fC0 * localIntEPhiOverEz - fC1 * localIntErOverEz; - (*distDz)(i, j) = localIntDeltaEz * -1 * AliTPCPoissonSolver::fgkdvdE; - - (*corrDrDz)(i, j + 1) = -1 * (*distDrDz)(i, j); - (*corrDPhiRDz)(i, j + 1) = -1 * (*distDPhiRDz)(i, j); - (*corrDz)(i, j + 1) = -1 * (*distDz)(i, j); - } - } - } -} - -/// IntegrateDistCorrDriftLineDz, integration of local distortion by following electron drift -/// See explanation at LocalDistCorrDz -/// -/// -/// \param matricesEr TMatrixD** electric field for \f$r\f$ component -/// \param matricesEPhi TMatrixD** electric field for \f$\phi\f$ component -/// \param matricesEz TMatrixD** electric field for \f$z\f$ component -/// \param matricesCorrDrDz TMatrixD** local correction \f$\hat{\delta}_{r}\f$ -/// \param matricesCorrDPhiRDz TMatrixD** local correction \f$r \hat{\delta}_{\phi}\f$ -/// \param matricesCorrDz TMatrixD** local correction \f$ \hat{\delta}_{z}\f$ -/// \param nRRow Int_t Number of nRRow in r-direction -/// \param nZColumn Int_t Number of nZColumn in z-direction -/// \param phiSlice Int_t Number of phi slices in \f$ phi \f$ direction -/// \param gridSizeZ const Float_t grid size in z direction -/// \param ezField const Double_t ezField calculate from the invoking operation -/// -/// \pre matricesEr, matricesEPhi, matrices Ez are provided -/// \post Local correction are computed according simplified Langevin equation -/// ~~~ -/// matricesCorrDz,matricesCorrDPhiRDz,matricesDistDz -/// ~~~ -/// -void AliTPCSpaceCharge3DCalc::IntegrateDistCorrDriftLineDz( - AliTPCLookUpTable3DInterpolatorD* lookupLocalDist, - TMatrixD** matricesGDistDrDz, - TMatrixD** matricesGDistDPhiRDz, TMatrixD** matricesGDistDz, - AliTPCLookUpTable3DInterpolatorD* lookupLocalCorr, - TMatrixD** matricesGCorrDrDz, TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, - TMatrixD** matricesGCorrIrregularDrDz, TMatrixD** matricesGCorrIrregularDPhiRDz, - TMatrixD** matricesGCorrIrregularDz, - TMatrixD** matricesRIrregular, TMatrixD** matricesPhiIrregular, TMatrixD** matricesZIrregular, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Double_t* rList, const Double_t* phiList, const Double_t* zList) -{ - - Float_t drDist, dPhi, dzDist, ddR, ddRPhi, ddZ; - Float_t radius0, phi0, z0, radius, phi, z, radiusCorrection; - radiusCorrection = 0.0; - radius = 0.0; - TMatrixD* mDistDrDz; - TMatrixD* mDistDPhiRDz; - TMatrixD* mDistDz; - TMatrixD* mCorrDrDz; - TMatrixD* mCorrDPhiRDz; - TMatrixD* mCorrDz; - TMatrixD* mCorrIrregularDrDz; - TMatrixD* mCorrIrregularDPhiRDz; - TMatrixD* mCorrIrregularDz; - TMatrixD* mRIrregular; - TMatrixD* mPhiIrregular; - TMatrixD* mZIrregular; - Int_t j = nZColumn - 1; - z0 = zList[j]; - - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - mCorrIrregularDrDz = matricesGCorrIrregularDrDz[m]; - mCorrIrregularDPhiRDz = matricesGCorrIrregularDPhiRDz[m]; - mCorrIrregularDz = matricesGCorrIrregularDz[m]; - - mRIrregular = matricesRIrregular[m]; - mPhiIrregular = matricesPhiIrregular[m]; - mZIrregular = matricesZIrregular[m]; - - for (Int_t i = 0; i < nRRow; i++) { - // do from j to 0 - // follow the drift - radius0 = rList[i]; - phi = phi0; - - /// - (*mDistDrDz)(i, j) = 0.; - (*mDistDPhiRDz)(i, j) = 0.; - (*mDistDz)(i, j) = 0.; - - (*mCorrDrDz)(i, j) = 0.; - (*mCorrDPhiRDz)(i, j) = 0.; - (*mCorrDz)(i, j) = 0.; - - //////////////// use irregular grid look up table for correction - if (fCorrectionType == kIrregularInterpolator) { - (*mCorrIrregularDrDz)(i, j) = 0.0; - (*mCorrIrregularDPhiRDz)(i, j) = 0.0; - (*mCorrIrregularDz)(i, j) = -0.0; - - // distorted point - (*mRIrregular)(i, j) = radius0; - (*mPhiIrregular)(i, j) = phi0; - (*mZIrregular)(i, j) = z0; - } - /////////////// - } - } - - // from j one column near end cap - for (j = nZColumn - 2; j >= 0; j--) { - - z0 = zList[j]; - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - mCorrIrregularDrDz = matricesGCorrIrregularDrDz[m]; - mCorrIrregularDPhiRDz = matricesGCorrIrregularDPhiRDz[m]; - mCorrIrregularDz = matricesGCorrIrregularDz[m]; - - mRIrregular = matricesRIrregular[m]; - mPhiIrregular = matricesPhiIrregular[m]; - mZIrregular = matricesZIrregular[m]; - - for (Int_t i = 0; i < nRRow; i++) { - // do from j to 0 - // follow the drift - radius0 = rList[i]; - phi = phi0; - radius = radius0; - - drDist = 0.0; - dPhi = 0.0; - dzDist = 0.0; - - // follow the drift line from z=j --> nZColumn - 1 - for (Int_t jj = j; jj < nZColumn; jj++) { - // interpolation the local distortion for current position - // phi += ddRPhi / radius; - phi = phi0 + dPhi; - radius = radius0 + drDist; - z = zList[jj] + dzDist; - - // regulate phi - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - lookupLocalDist->GetValue(radius, phi, z, ddR, ddRPhi, ddZ); - - // add local distortion - drDist += ddR; - dPhi += (ddRPhi / radius); - dzDist += ddZ; - } - // set the global distortion after following the electron drift - (*mDistDrDz)(i, j) = drDist; - (*mDistDPhiRDz)(i, j) = dPhi * radius0; - (*mDistDz)(i, j) = dzDist; - /////////////// use irregular grid look up table for correction - // set - if (fCorrectionType == kIrregularInterpolator) { - // values should be negative of distortions - (*mCorrIrregularDrDz)(i, j) = -drDist; - (*mCorrIrregularDPhiRDz)(i, j) = -1 * dPhi * (radius0 + drDist); - (*mCorrIrregularDz)(i, j) = -dzDist; - - // distorted point - (*mRIrregular)(i, j) = radius0 + drDist; - (*mPhiIrregular)(i, j) = phi0 + dPhi; - (*mZIrregular)(i, j) = z0 + dzDist; - } - /////////////// - - // put the radius to the original value - if (fCorrectionType == kRegularInterpolator) { - if (j == nZColumn - 2) { - radiusCorrection = radius0; - } - - // get global correction from j+1 - drDist = (*mCorrDrDz)(i, j + 1); - dPhi = (*mCorrDPhiRDz)(i, j + 1) / radius0; - dzDist = (*mCorrDz)(i, j + 1); - - radiusCorrection = radius0 + drDist; - phi = phi0 + dPhi; - z = zList[j + 1] + dzDist; - - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - lookupLocalCorr->GetValue(radiusCorrection, phi, z, ddR, ddRPhi, ddZ); - - drDist += ddR; - dzDist += ddZ; - dPhi += ddRPhi / radiusCorrection; - - (*mCorrDrDz)(i, j) = drDist; - (*mCorrDPhiRDz)(i, j) = dPhi * radius0; - (*mCorrDz)(i, j) = dzDist; - } - } - } - } -} - -// oudated, to be removed once changes in aliroot are pushed -/// follow the drift for exact function -/// -/// \param intDrDzF -/// \param intDPhiDzF -/// \param intDzDzF -/// \param ezField -/// \param matricesGDistDrDz -/// \param matricesGDistDPhiRDz -/// \param matricesGDistDz -/// \param matricesGCorrDrDz -/// \param matricesGCorrDPhiRDz -/// \param matricesGCorrDz -/// \param matricesGCorrIrregularDrDz -/// \param matricesGCorrIrregularDPhiRDz -/// \param matricesGCorrIrregularDz -/// \param matricesRIrregular -/// \param matricesPhiIrregular -/// \param matricesZIrregular -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -/// \param rList -/// \param phiList -/// \param zList -void AliTPCSpaceCharge3DCalc::IntegrateDistCorrDriftLineDz( - TFormula* intDrDzF, TFormula* intDPhiDzF, TFormula* intDzDzF, const Double_t ezField, - TMatrixD** matricesGDistDrDz, TMatrixD** matricesGDistDPhiRDz, TMatrixD** matricesGDistDz, - TMatrixD** matricesGCorrDrDz, TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, - TMatrixD** matricesGCorrIrregularDrDz, TMatrixD** matricesGCorrIrregularDPhiRDz, TMatrixD** matricesGCorrIrregularDz, TMatrixD** matricesRIrregular, - TMatrixD** matricesPhiIrregular, TMatrixD** matricesZIrregular, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, const Double_t* rList, const Double_t* phiList, const Double_t* zList) -{ - Float_t drDist, dPhi, dzDist, ddR, ddRPhi, ddZ; - Float_t radius0, phi0, z0, radius, phi, z, radiusCorrection, z1; - - Float_t localIntErOverEz = 0.0; - Float_t localIntEPhiOverEz = 0.0; - Float_t localIntDeltaEz = 0.0; - // set parameters for function - // hard coded, will be modified after pull at AliRoot - - TFormula* ezF = GetEzFormula(); - radiusCorrection = 0.0; - radius = 0.0; - TMatrixD* mDistDrDz; - TMatrixD* mDistDPhiRDz; - TMatrixD* mDistDz; - TMatrixD* mCorrDrDz; - TMatrixD* mCorrDPhiRDz; - TMatrixD* mCorrDz; - TMatrixD* mCorrIrregularDrDz; - TMatrixD* mCorrIrregularDPhiRDz; - TMatrixD* mCorrIrregularDz; - TMatrixD* mRIrregular; - TMatrixD* mPhiIrregular; - TMatrixD* mZIrregular; - Int_t j = nZColumn - 1; - z0 = zList[j]; - - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - mCorrIrregularDrDz = matricesGCorrIrregularDrDz[m]; - mCorrIrregularDPhiRDz = matricesGCorrIrregularDPhiRDz[m]; - mCorrIrregularDz = matricesGCorrIrregularDz[m]; - - mRIrregular = matricesRIrregular[m]; - mPhiIrregular = matricesPhiIrregular[m]; - mZIrregular = matricesZIrregular[m]; - - for (Int_t i = 0; i < nRRow; i++) { - // follow the drift - radius0 = rList[i]; - phi = phi0; - radius = radius0; - /// - (*mDistDrDz)(i, j) = 0.0; - (*mDistDPhiRDz)(i, j) = 0.0; - (*mDistDz)(i, j) = 0.0; - - //////////////// use irregular grid look up table for correction - // set - (*mCorrIrregularDrDz)(i, j) = 0.0; - (*mCorrIrregularDPhiRDz)(i, j) = 0.0; - (*mCorrIrregularDz)(i, j) = 0.0; - - // distorted point - (*mRIrregular)(i, j) = radius0; - (*mPhiIrregular)(i, j) = phi0; - (*mZIrregular)(i, j) = z0; - /////////////// - } - } - - // from j one column near end cap - for (j = nZColumn - 2; j >= 0; j--) { - - z0 = zList[j]; - - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - mCorrIrregularDrDz = matricesGCorrIrregularDrDz[m]; - mCorrIrregularDPhiRDz = matricesGCorrIrregularDPhiRDz[m]; - mCorrIrregularDz = matricesGCorrIrregularDz[m]; - - mRIrregular = matricesRIrregular[m]; - mPhiIrregular = matricesPhiIrregular[m]; - mZIrregular = matricesZIrregular[m]; - - for (Int_t i = 0; i < nRRow; i++) { - // do from j to 0 - // follow the drift - radius0 = rList[i]; - phi = phi0; - radius = radius0; - - drDist = 0.0; - dPhi = 0.0; - dzDist = 0.0; - ddRPhi = 0.0; - - // follow the drift line from z=j --> nZColumn - 1 - for (Int_t jj = j; jj < nZColumn; jj++) { - // interpolation the local distortion for current position - phi = phi0 + dPhi; - radius = radius0 + drDist; - z = zList[jj] + dzDist; - z1 = z + (zList[j + 1] - zList[j]); - // regulate phi - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - //lookupLocalDist->GetValue(radius, phi, z, ddR, ddRPhi, ddZ); - localIntErOverEz = (intDrDzF->Eval(radius, phi, z1) - intDrDzF->Eval(radius, phi, z)) / (ezField + ezF->Eval(radius, phi, z)); - localIntEPhiOverEz = (intDPhiDzF->Eval(radius, phi, z1) - intDPhiDzF->Eval(radius, phi, z)) / (ezField + ezF->Eval(radius, phi, z)); - localIntDeltaEz = intDzDzF->Eval(radius, phi, z1) - intDzDzF->Eval(radius, phi, z); - - ddR = fC0 * localIntErOverEz + fC1 * localIntEPhiOverEz; - ddRPhi = fC0 * localIntEPhiOverEz - fC1 * localIntErOverEz; - ddZ = -1 * localIntDeltaEz * AliTPCPoissonSolver::fgkdvdE; - - drDist += ddR; - dPhi += (ddRPhi / radius); - dzDist += ddZ; - - // add local distortion - } - // set the global distortion after following the electron drift - (*mDistDrDz)(i, j) = drDist; - (*mDistDPhiRDz)(i, j) = dPhi * radius0; - (*mDistDz)(i, j) = dzDist; - /////////////// use irregular grid look up table for correction - // use oppsite directions of distortion - (*mCorrIrregularDrDz)(i, j) = -drDist; - (*mCorrIrregularDPhiRDz)(i, j) = -dPhi * (radius0 + drDist); - (*mCorrIrregularDz)(i, j) = -dzDist; - - // distorted point - (*mRIrregular)(i, j) = radius0 + drDist; - (*mPhiIrregular)(i, j) = phi0 + dPhi; - (*mZIrregular)(i, j) = z0 + dzDist; - /////////////// - - // put the radius to the original value - if (j == nZColumn - 2) { - radiusCorrection = radius0; - } - - // get global correction from j+1 - drDist = (*mCorrDrDz)(i, j + 1); - dzDist = (*mCorrDz)(i, j + 1); - - radiusCorrection = radius0 + drDist; - dPhi = (*mCorrDPhiRDz)(i, j + 1) / radius0; - //dPhi = (*mCorrDPhiRDz)(i, j + 1) /radiusCorrection; - phi = phi0 + dPhi; - z = zList[j + 1] + dzDist; - z1 = z - (zList[j + 1] - zList[j]); - - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - //lookupLocalCorr->GetValue(radiusCorrection, phi, z, ddR, ddRPhi, ddZ); - localIntErOverEz = (intDrDzF->Eval(radiusCorrection, phi, z1) - intDrDzF->Eval(radiusCorrection, phi, z)) / (ezField + intDzDzF->Eval(radiusCorrection, phi, z)); - localIntEPhiOverEz = (intDPhiDzF->Eval(radiusCorrection, phi, z1) - intDPhiDzF->Eval(radiusCorrection, phi, z)) / (ezField + intDzDzF->Eval(radiusCorrection, phi, z)); - localIntDeltaEz = intDzDzF->Eval(radiusCorrection, phi, z1) - intDzDzF->Eval(radiusCorrection, phi, z); - - ddR = fC0 * localIntErOverEz + fC1 * localIntEPhiOverEz; - ddRPhi = fC0 * localIntEPhiOverEz - fC1 * localIntErOverEz; - ddZ = -1 * localIntDeltaEz * AliTPCPoissonSolver::fgkdvdE; - - drDist += ddR; - dzDist += ddZ; - dPhi += ddRPhi / radiusCorrection; - - (*mCorrDrDz)(i, j) = drDist; - (*mCorrDPhiRDz)(i, j) = dPhi * radius0; - (*mCorrDz)(i, j) = dzDist; - } - } - } -} - -/// follow the drift for exact function -/// -/// \param intDrDzF -/// \param intDPhiDzF -/// \param intDzDzF -/// \param ezField -/// \param matricesGDistDrDz -/// \param matricesGDistDPhiRDz -/// \param matricesGDistDz -/// \param matricesGCorrDrDz -/// \param matricesGCorrDPhiRDz -/// \param matricesGCorrDz -/// \param matricesGCorrIrregularDrDz -/// \param matricesGCorrIrregularDPhiRDz -/// \param matricesGCorrIrregularDz -/// \param matricesRIrregular -/// \param matricesPhiIrregular -/// \param matricesZIrregular -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -/// \param rList -/// \param phiList -/// \param zList -void AliTPCSpaceCharge3DCalc::IntegrateDistCorrDriftLineDz( - TFormula* intDrDzF, TFormula* intDPhiDzF, TFormula* intDzDzF, TFormula* ezF, const Double_t ezField, - TMatrixD** matricesGDistDrDz, TMatrixD** matricesGDistDPhiRDz, TMatrixD** matricesGDistDz, - TMatrixD** matricesGCorrDrDz, TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, - TMatrixD** matricesGCorrIrregularDrDz, TMatrixD** matricesGCorrIrregularDPhiRDz, TMatrixD** matricesGCorrIrregularDz, TMatrixD** matricesRIrregular, - TMatrixD** matricesPhiIrregular, TMatrixD** matricesZIrregular, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, const Double_t* rList, const Double_t* phiList, const Double_t* zList) -{ - - Float_t drDist, dPhi, dzDist, ddR, ddRPhi, ddZ; - Float_t radius0, phi0, z0, radius, phi, z, radiusCorrection, z1; - - Float_t localIntErOverEz = 0.0; - Float_t localIntEPhiOverEz = 0.0; - Float_t localIntDeltaEz = 0.0; - - radiusCorrection = 0.0; - radius = 0.0; - TMatrixD* mDistDrDz; - TMatrixD* mDistDPhiRDz; - TMatrixD* mDistDz; - TMatrixD* mCorrDrDz; - TMatrixD* mCorrDPhiRDz; - TMatrixD* mCorrDz; - TMatrixD* mCorrIrregularDrDz; - TMatrixD* mCorrIrregularDPhiRDz; - TMatrixD* mCorrIrregularDz; - TMatrixD* mRIrregular; - TMatrixD* mPhiIrregular; - TMatrixD* mZIrregular; - Int_t j = nZColumn - 1; - z0 = zList[j]; - - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - mCorrIrregularDrDz = matricesGCorrIrregularDrDz[m]; - mCorrIrregularDPhiRDz = matricesGCorrIrregularDPhiRDz[m]; - mCorrIrregularDz = matricesGCorrIrregularDz[m]; - - mRIrregular = matricesRIrregular[m]; - mPhiIrregular = matricesPhiIrregular[m]; - mZIrregular = matricesZIrregular[m]; - - for (Int_t i = 0; i < nRRow; i++) { - // follow the drift - radius0 = rList[i]; - phi = phi0; - radius = radius0; - /// - (*mDistDrDz)(i, j) = 0.0; - (*mDistDPhiRDz)(i, j) = 0.0; - (*mDistDz)(i, j) = 0.0; - - //////////////// use irregular grid look up table for correction - // set - (*mCorrIrregularDrDz)(i, j) = 0.0; - (*mCorrIrregularDPhiRDz)(i, j) = 0.0; - (*mCorrIrregularDz)(i, j) = 0.0; - - // distorted point - (*mRIrregular)(i, j) = radius0; - (*mPhiIrregular)(i, j) = phi0; - (*mZIrregular)(i, j) = z0; - /////////////// - } - } - - // from j one column near end cap - for (j = nZColumn - 2; j >= 0; j--) { - - z0 = zList[j]; - - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - mCorrIrregularDrDz = matricesGCorrIrregularDrDz[m]; - mCorrIrregularDPhiRDz = matricesGCorrIrregularDPhiRDz[m]; - mCorrIrregularDz = matricesGCorrIrregularDz[m]; - - mRIrregular = matricesRIrregular[m]; - mPhiIrregular = matricesPhiIrregular[m]; - mZIrregular = matricesZIrregular[m]; - - for (Int_t i = 0; i < nRRow; i++) { - // do from j to 0 - // follow the drift - radius0 = rList[i]; - phi = phi0; - radius = radius0; - - drDist = 0.0; - dPhi = 0.0; - dzDist = 0.0; - ddRPhi = 0.0; - - // follow the drift line from z=j --> nZColumn - 1 - for (Int_t jj = j; jj < nZColumn; jj++) { - // interpolation the local distortion for current position - phi = phi0 + dPhi; - radius = radius0 + drDist; - z = zList[jj] + dzDist; - z1 = z + (zList[j + 1] - zList[j]); - // regulate phi - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - //lookupLocalDist->GetValue(radius, phi, z, ddR, ddRPhi, ddZ); - localIntErOverEz = (intDrDzF->Eval(radius, phi, z1) - intDrDzF->Eval(radius, phi, z)) / (ezField + ezF->Eval(radius, phi, z)); - localIntEPhiOverEz = (intDPhiDzF->Eval(radius, phi, z1) - intDPhiDzF->Eval(radius, phi, z)) / (ezField + ezF->Eval(radius, phi, z)); - localIntDeltaEz = intDzDzF->Eval(radius, phi, z1) - intDzDzF->Eval(radius, phi, z); - - ddR = fC0 * localIntErOverEz + fC1 * localIntEPhiOverEz; - ddRPhi = fC0 * localIntEPhiOverEz - fC1 * localIntErOverEz; - ddZ = -1 * localIntDeltaEz * AliTPCPoissonSolver::fgkdvdE; - - drDist += ddR; - dPhi += (ddRPhi / radius); - dzDist += ddZ; - - // add local distortion - } - // set the global distortion after following the electron drift - (*mDistDrDz)(i, j) = drDist; - (*mDistDPhiRDz)(i, j) = dPhi * radius0; - (*mDistDz)(i, j) = dzDist; - /////////////// use irregular grid look up table for correction - // use oppsite directions of distortion - (*mCorrIrregularDrDz)(i, j) = -drDist; - (*mCorrIrregularDPhiRDz)(i, j) = -dPhi * (radius0 + drDist); - (*mCorrIrregularDz)(i, j) = -dzDist; - - // distorted point - (*mRIrregular)(i, j) = radius0 + drDist; - (*mPhiIrregular)(i, j) = phi0 + dPhi; - (*mZIrregular)(i, j) = z0 + dzDist; - /////////////// - - // put the radius to the original value - if (j == nZColumn - 2) { - radiusCorrection = radius0; - } - - // get global correction from j+1 - drDist = (*mCorrDrDz)(i, j + 1); - dzDist = (*mCorrDz)(i, j + 1); - - radiusCorrection = radius0 + drDist; - dPhi = (*mCorrDPhiRDz)(i, j + 1) / radius0; - //dPhi = (*mCorrDPhiRDz)(i, j + 1) /radiusCorrection; - phi = phi0 + dPhi; - z = zList[j + 1] + dzDist; - z1 = z - (zList[j + 1] - zList[j]); - - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - //lookupLocalCorr->GetValue(radiusCorrection, phi, z, ddR, ddRPhi, ddZ); - localIntErOverEz = (intDrDzF->Eval(radiusCorrection, phi, z1) - intDrDzF->Eval(radiusCorrection, phi, z)) / (ezField + intDzDzF->Eval(radiusCorrection, phi, z)); - localIntEPhiOverEz = (intDPhiDzF->Eval(radiusCorrection, phi, z1) - intDPhiDzF->Eval(radiusCorrection, phi, z)) / (ezField + intDzDzF->Eval(radiusCorrection, phi, z)); - localIntDeltaEz = intDzDzF->Eval(radiusCorrection, phi, z1) - intDzDzF->Eval(radiusCorrection, phi, z); - - ddR = fC0 * localIntErOverEz + fC1 * localIntEPhiOverEz; - ddRPhi = fC0 * localIntEPhiOverEz - fC1 * localIntErOverEz; - ddZ = -1 * localIntDeltaEz * AliTPCPoissonSolver::fgkdvdE; // two times? - - drDist += ddR; - dzDist += ddZ; - dPhi += ddRPhi / radiusCorrection; - - (*mCorrDrDz)(i, j) = drDist; - (*mCorrDPhiRDz)(i, j) = dPhi * radius0; - (*mCorrDz)(i, j) = dzDist; - } - } - } -} - -/// See explanation at LocalDistCorrDz -/// -/// -/// \param matricesEr TMatrixD** electric field for \f$r\f$ component -/// \param matricesEPhi TMatrixD** electric field for \f$\phi\f$ component -/// \param matricesEz TMatrixD** electric field for \f$z\f$ component -/// \param matricesCorrDrDz TMatrixD** local correction \f$\hat{\delta}_{r}\f$ -/// \param matricesCorrDPhiRDz TMatrixD** local correction \f$r \hat{\delta}_{\phi}\f$ -/// \param matricesCorrDz TMatrixD** local correction \f$ \hat{\delta}_{z}\f$ -/// \param nRRow Int_t Number of nRRow in r-direction -/// \param nZColumn Int_t Number of nZColumn in z-direction -/// \param phiSlice Int_t Number of phi slices in \f$ phi \f$ direction -/// \param gridSizeZ const Float_t grid size in z direction -/// \param ezField const Double_t ezField calculate from the invoking operation -/// -/// \pre matricesEr, matricesEPhi, matrices Ez are provided -/// \post Local correction are computed according simplified Langevin equation -/// ~~~ -/// matricesCorrDz,matricesCorrDPhiRDz,matricesDistDz -/// ~~~ -void AliTPCSpaceCharge3DCalc::IntegrateDistCorrDriftLineDzWithLookUp(AliTPCLookUpTable3DInterpolatorD* lookupLocalDist, TMatrixD** matricesGDistDrDz, TMatrixD** matricesGDistDPhiRDz, TMatrixD** matricesGDistDz, AliTPCLookUpTable3DInterpolatorD* lookupLocalCorr, TMatrixD** matricesGCorrDrDz, TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, Double_t* rList, Double_t* phiList, Double_t* zList) -{ - - Float_t drDist, dRPhi, dPhi, dzDist, ddR, ddRPhi, ddPhi, ddZ; - Float_t radius0, phi0, z0, radius, phi, z, radiusCorrection; - TMatrixD* mDistDrDz; - TMatrixD* mDistDPhiRDz; - TMatrixD* mDistDz; - TMatrixD* mCorrDrDz; - TMatrixD* mCorrDPhiRDz; - TMatrixD* mCorrDz; - - // allocate look up for temporal - AliTPCLookUpTable3DInterpolatorD* lookupGlobalDistTemp = - new AliTPCLookUpTable3DInterpolatorD( - nRRow, matricesGDistDrDz, rList, phiSlice, matricesGDistDPhiRDz, phiList, nZColumn, matricesGDistDz, - zList, 1); - - Int_t j = nZColumn - 1; - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - for (Int_t i = 0; i < nRRow; i++) { - /// - (*mDistDrDz)(i, j) = 0.0; - (*mDistDPhiRDz)(i, j) = 0.0; - (*mDistDz)(i, j) = 0.0; - - (*mCorrDrDz)(i, j) = 0.0; - (*mCorrDPhiRDz)(i, j) = 0.0; - (*mCorrDz)(i, j) = 0.0; - } - } - - drDist = 0.0; - dRPhi = 0.0; - dPhi = 0.0; - dzDist = 0.0; - // from j one column near end cap - for (j = nZColumn - 2; j >= 0; j--) { - - z0 = zList[j]; - for (Int_t m = 0; m < phiSlice; m++) { - phi0 = phiList[m]; - - mDistDrDz = matricesGDistDrDz[m]; - mDistDPhiRDz = matricesGDistDPhiRDz[m]; - mDistDz = matricesGDistDz[m]; - - // - mCorrDrDz = matricesGCorrDrDz[m]; - mCorrDPhiRDz = matricesGCorrDPhiRDz[m]; - mCorrDz = matricesGCorrDz[m]; - - for (Int_t i = 0; i < nRRow; i++) { - - // do from j to 0 - // follow the drift - radius0 = rList[i]; - - lookupLocalDist->GetValue(radius0, phi0, z0, ddR, ddRPhi, ddZ); - ddPhi = ddRPhi / radius0; - - if (j < nZColumn - 2) { - phi = phi0 + ddPhi; - radius = radius0 + ddR; - z = zList[j + 1] + ddZ; - - lookupGlobalDistTemp->GetValue(radius, phi, z, drDist, dRPhi, dzDist); - dPhi = dRPhi / radius; - } - - (*mDistDrDz)(i, j) = drDist + ddR; - (*mDistDPhiRDz)(i, j) = (dPhi + ddPhi) * radius0; - (*mDistDz)(i, j) = dzDist + ddZ; - - // copy to 1D for being able to interpolate at next step - if (j > 0) { - (*mDistDrDz)(i, j - 1) = drDist + ddR; - (*mDistDPhiRDz)(i, j - 1) = (dPhi + ddPhi) * radius0; - (*mDistDz)(i, j - 1) = dzDist + ddZ; - } - - // get global correction from j+1 - drDist = (*mCorrDrDz)(i, j + 1); - dPhi = (*mCorrDPhiRDz)(i, j + 1) / radius0; - dzDist = (*mCorrDz)(i, j + 1); - - radiusCorrection = radius0 + drDist; - phi = phi0 + dPhi; - z = zList[j + 1] + dzDist; - - while (phi < 0.0) { - phi = TMath::TwoPi() + phi; - } - while (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); - } - - lookupLocalCorr->GetValue(radiusCorrection, phi, z, ddR, ddRPhi, ddZ); - - drDist += ddR; - dzDist += ddZ; - dPhi += (ddRPhi / radiusCorrection); - - (*mCorrDrDz)(i, j) = drDist; - (*mCorrDPhiRDz)(i, j) = dPhi * radius0; - (*mCorrDz)(i, j) = dzDist; - } - } - - lookupGlobalDistTemp->CopyFromMatricesToInterpolator(j); - if (j > 0) { - lookupGlobalDistTemp->CopyFromMatricesToInterpolator(j - 1); - } - } - delete lookupGlobalDistTemp; -} - -/// -/// \param lookupGlobal -/// \param lookupRDz -/// \param lookupPhiRDz -/// \param lookupDz -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -/// \param rList -/// \param phiList -/// \param zList -void AliTPCSpaceCharge3DCalc::FillLookUpTable(AliTPCLookUpTable3DInterpolatorD* lookupGlobal, TMatrixD** lookupRDz, - TMatrixD** lookupPhiRDz, TMatrixD** lookupDz, const Int_t nRRow, - const Int_t nZColumn, const Int_t phiSlice, const Double_t* rList, - const Double_t* phiList, const Double_t* zList) -{ - Double_t r, phi, z; - TMatrixD* mR; - TMatrixD* mPhiR; - TMatrixD* mDz; - - /// * Interpolate basicLookup tables; once for each rod, then sum the results - for (Int_t k = 0; k < fNPhiSlices; k++) { - phi = fListPhi[k]; - - mR = lookupRDz[k]; - mPhiR = lookupPhiRDz[k]; - mDz = lookupDz[k]; - for (Int_t j = 0; j < fNZColumns; j++) { - z = fListZ[j]; // Symmetric solution in Z that depends only on ABS(Z) - - for (Int_t i = 0; i < fNRRows; i++) { - r = fListR[i]; - - lookupGlobal->GetValue(r, phi, z, (*mR)(i, j), (*mPhiR)(i, j), (*mDz)(i, j)); - } - } - } -} -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetDistortionCyl(const Float_t x[], Short_t roc, Float_t dx[]) const -{ - GetDistortionCylAC(x, roc, dx); -} -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetDistortionCylAC(const Float_t x[], Short_t roc, Float_t dx[]) const -{ - if (!fInitLookUp) { - Info("AliTPCSpaceCharge3DCalc::GetDistortionCylAC", "Lookup table was not initialized! Please run AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz(nRRows, nZColumns, nPhiSlices) to perform the initialization. Returning distortion vector (0, 0, 0)."); - for (int i = 0; i < 3; ++i) { - dx[i] = 0.; - } - return; - } - - Float_t dR, dRPhi, dZ; - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < -1e-16) || (sign == -1 && z > -1e-16)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::GetDistortionCylAC", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - fLookupIntDistA->GetValue(r, phi, z, dR, dRPhi, dZ); - } else { - fLookupIntDistC->GetValue(r, phi, -1 * z, dR, dRPhi, dZ); - dZ = -1 * dZ; - } - - dx[0] = fCorrectionFactor * dR; - dx[1] = fCorrectionFactor * dRPhi; - dx[2] = fCorrectionFactor * - dZ; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} -/// Get Correction from irregular table -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetCorrectionCylACIrregular(const Float_t x[], Short_t roc, Float_t dx[]) const -{ - if (!fInitLookUp) { - Info("AliTPCSpaceCharge3DCalc::GetCorrectionCylACIrregular", "Lookup table was not initialized! Please run AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz(nRRows, nZColumns, nPhiSlices) to perform the initialization. Returning correction vector (0, 0, 0)."); - for (int i = 0; i < 3; ++i) { - dx[i] = 0.; - } - return; - } - - Double_t dR, dRPhi, dZ; - Double_t r, phi, z; - Int_t sign; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (fNRRows - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (fNZColumns - 1); - const Float_t gridSizePhi = TMath::TwoPi() / fNPhiSlices; - - r = x[0]; - phi = x[1]; - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < 0) || (sign == -1 && z > 0)) { // just a consistency check - Error("AliTPCSpaceChargeCalc3D::GetCorrectionCylACIrregular", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - // get distortion from irregular table - - if (z > 0) { - fLookupIntCorrIrregularA->GetValue(r, phi, z, dR, dRPhi, dZ); - } else { - fLookupIntCorrIrregularC->GetValue(r, phi, -z, dR, dRPhi, dZ); - dZ = -1 * dZ; - } - - dx[0] = fCorrectionFactor * dR; - dx[1] = fCorrectionFactor * dRPhi; - dx[2] = fCorrectionFactor * - dZ; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} - -/// Get Correction from irregular table -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetCorrectionCylACIrregular(const Float_t x[], Short_t roc, Float_t dx[], const Int_t side) const -{ - if (!fInitLookUp) { - Info("AliTPCSpaceCharge3DCalc::GetCorrectionCylACIrregular", "Lookup table was not initialized! Please run AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz(nRRows, nZColumns, nPhiSlices) to perform the initialization. Returning correction vector (0, 0, 0)."); - for (int i = 0; i < 3; ++i) { - dx[i] = 0.; - } - return; - } - - Double_t dR, dRPhi, dZ; - Double_t r, phi, z; - Int_t sign; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (fNRRows - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (fNZColumns - 1); - const Float_t gridSizePhi = TMath::TwoPi() / fNPhiSlices; - - r = x[0]; - phi = x[1]; - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < 0) || (sign == -1 && z > 0)) { // just a consistency check - Error("AliTPCSpaceChargeCalc3D::GetCorrectionCylACIrregular", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - // get distortion from irregular table - - if (side == 0) { - fLookupIntCorrIrregularA->GetValue(r, phi, z, dR, dRPhi, dZ); - } else { - fLookupIntCorrIrregularC->GetValue(r, phi, -z, dR, dRPhi, dZ); - dZ = -1 * dZ; - } - - dx[0] = fCorrectionFactor * dR; - dx[1] = fCorrectionFactor * dRPhi; - dx[2] = fCorrectionFactor * - dZ; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} - -/// Get correction regular grid by following electron -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetCorrectionCylAC(const Float_t x[], Short_t roc, Float_t dx[]) const -{ - if (!fInitLookUp) { - Info("AliTPCSpaceCharge3DCalc::GetDistortionCylAC", "Lookup table was not initialized! Please run AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz(nRRows, nZColumns, nPhiSlices) to perform the initialization. Returning correction vector (0, 0, 0)."); - for (int i = 0; i < 3; ++i) { - dx[i] = 0.; - } - return; - } - - Float_t dR, dRPhi, dZ; - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < -1e-16) || (sign == -1 && z > -1e-16)) { // just a consistency check - Error("AliTPCSpaceChargeCalc3D::GetCorrectionCylAC", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - fLookupIntCorrA->GetValue(r, phi, z, dR, dRPhi, dZ); - } else { - fLookupIntCorrC->GetValue(r, phi, -z, dR, dRPhi, dZ); - dZ = -1 * dZ; - } - dx[0] = fCorrectionFactor * dR; - dx[1] = fCorrectionFactor * dRPhi; - dx[2] = fCorrectionFactor * - dZ; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} -void AliTPCSpaceCharge3DCalc::GetDistortion(const Float_t x[], Short_t roc, Float_t dx[]) const -{ - Float_t pCyl[3]; // a point in cylindrical coordinate - Float_t dCyl[3]; // distortion - - pCyl[0] = TMath::Sqrt(x[0] * x[0] + x[1] * x[1]); - pCyl[1] = TMath::ATan2(x[1], x[0]); - - // normalize phi - while (pCyl[1] > TMath::Pi()) { - pCyl[1] -= TMath::TwoPi(); - } - while (pCyl[1] < -TMath::Pi()) { - pCyl[1] += TMath::TwoPi(); - } - - pCyl[2] = x[2]; // Create temporary copy of x[2] - - GetDistortionCylAC(pCyl, roc, dCyl); - - // Calculate distorted position - if (pCyl[0] > 0.0) { - //pCyl[0] = pCyl[0] + fCorrectionFactor * dCyl[0]; - pCyl[1] = pCyl[1] + fCorrectionFactor * dCyl[1] / pCyl[0]; - pCyl[0] = pCyl[0] + fCorrectionFactor * dCyl[0]; - } - - dCyl[2] = fCorrectionFactor * dCyl[2]; - - // distortion in x,y and z - dx[0] = (pCyl[0] * TMath::Cos(pCyl[1]) - x[0]); - dx[1] = (pCyl[0] * TMath::Sin(pCyl[1]) - x[1]); - dx[2] = dCyl[2]; -} -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetCorrectionCyl(const Float_t x[], Short_t roc, Float_t dx[]) const -{ - if (fCorrectionType == kRegularInterpolator) { - GetCorrectionCylAC(x, roc, dx); - } else { - GetCorrectionCylACIrregular(x, roc, dx); - } -} -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetCorrection(const Float_t x[], Short_t roc, Float_t dx[]) const -{ - Float_t pCyl[3]; // a point in cylindrical coordinate - Float_t dCyl[3]; // distortion - - pCyl[0] = TMath::Sqrt(x[0] * x[0] + x[1] * x[1]); - pCyl[1] = TMath::ATan2(x[1], x[0]); - pCyl[2] = x[2]; // Create temporary copy of x[2] - - if (fCorrectionType == kRegularInterpolator) { - while (pCyl[1] > TMath::Pi()) { - pCyl[1] -= TMath::TwoPi(); - } - while (pCyl[1] < -TMath::Pi()) { - pCyl[1] += TMath::TwoPi(); - } - - GetCorrectionCylAC(pCyl, roc, dCyl); - } else { - GetCorrectionCylACIrregular(pCyl, roc, dCyl); - } - - // Calculate distorted position - if (pCyl[0] > 0.0) { - //pCyl[0] = pCyl[0] + fCorrectionFactor * dCyl[0]; - pCyl[1] = pCyl[1] + fCorrectionFactor * dCyl[1] / pCyl[0]; - pCyl[0] = pCyl[0] + fCorrectionFactor * dCyl[0]; - } - - dCyl[2] = fCorrectionFactor * dCyl[2]; - - // distortion in x,y and z - dx[0] = (pCyl[0] * TMath::Cos(pCyl[1]) - x[0]); - dx[1] = (pCyl[0] * TMath::Sin(pCyl[1]) - x[1]); - dx[2] = dCyl[2]; -} - -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetCorrection(const Float_t x[], Short_t roc, Float_t dx[], const Int_t side) const -{ - Float_t pCyl[3]; // a point in cylindrical coordinate - Float_t dCyl[3]; // distortion - - pCyl[0] = TMath::Sqrt(x[0] * x[0] + x[1] * x[1]); - pCyl[1] = TMath::ATan2(x[1], x[0]); - pCyl[2] = x[2]; // Create temporary copy of x[2] - - if (fCorrectionType == kRegularInterpolator) { - while (pCyl[1] > TMath::Pi()) { - pCyl[1] -= TMath::TwoPi(); - } - while (pCyl[1] < -TMath::Pi()) { - pCyl[1] += TMath::TwoPi(); - } - - GetCorrectionCylAC(pCyl, roc, dCyl); - } else { - GetCorrectionCylACIrregular(pCyl, roc, dCyl, side); - } - - // Calculate distorted position - if (pCyl[0] > 0.0) { - pCyl[0] = pCyl[0] + fCorrectionFactor * dCyl[0]; - pCyl[1] = pCyl[1] + fCorrectionFactor * dCyl[1] / pCyl[0]; - } - - dCyl[2] = fCorrectionFactor * dCyl[2]; - - // distortion in x,y and z - dx[0] = (pCyl[0] * TMath::Cos(pCyl[1]) - x[0]); - dx[1] = (pCyl[0] * TMath::Sin(pCyl[1]) - x[1]); - dx[2] = dCyl[2]; -} - -/// Use 3D space charge map as an optional input -/// The layout of the input histogram is assumed to be: (phi,r,z) -/// Density histogram is expected to bin in C/m^3 -/// -/// Standard histogram interpolation is used in order to use the density at center of bin -/// -/// \param hisSpaceCharge3D -/// \param norm -void AliTPCSpaceCharge3DCalc::SetInputSpaceCharge(TH3* hisSpaceCharge3D, Double_t norm) -{ - fHistogram3DSpaceCharge = hisSpaceCharge3D; - fInitLookUp = kFALSE; - - Info("AliTPCSpaceCharge3DCalc:SetInputSpaceCharge", "Set Input Space Charge by 3D"); - - Double_t radius0, z0, phi0; - TMatrixD* charge; - for (Int_t iSide = 0; iSide < 2; iSide++) { - for (Int_t k = 0; k < fNPhiSlices; k++) { - if (iSide == 0) { - charge = fMatrixChargeA[k]; - } else { - charge = fMatrixChargeC[k]; - } - - phi0 = fListPhi[k]; - - for (Int_t i = 0; i < fNRRows; i++) { - radius0 = fListR[i]; - - for (Int_t j = 0; j < fNZColumns; j++) { - if (iSide == 0) { - z0 = fListZ[j]; - } else { - z0 = -fListZ[j]; - } - - (*charge)(i, j) = norm * InterpolatePhi(hisSpaceCharge3D, phi0, radius0, z0); - - } // end j - } // end i - } // end phi - } - - fInterpolatorChargeA->SetValue(fMatrixChargeA); - if (fInterpolationOrder > 2) { - fInterpolatorChargeA->InitCubicSpline(); - } - fInterpolatorChargeC->SetValue(fMatrixChargeC); - if (fInterpolationOrder > 2) { - fInterpolatorChargeC->InitCubicSpline(); - } -} - -/// SetInputCharge -/// -/// \param hisSpaceCharge3D TH3* histogram for space charge -/// \param norm Double_t norm/weight -/// \param side Int_t side = 0 => side A, side = 1 => side C -/// -/// side effects: create Charge interpolator -void AliTPCSpaceCharge3DCalc::SetInputSpaceCharge(TH3* hisSpaceCharge3D, Double_t norm, Int_t side) -{ - if (side == 0) { - fHistogram3DSpaceChargeA = hisSpaceCharge3D; - } else { - fHistogram3DSpaceChargeC = hisSpaceCharge3D; - } - - Double_t rMin = hisSpaceCharge3D->GetYaxis()->GetBinCenter(0); - Double_t rMax = hisSpaceCharge3D->GetYaxis()->GetBinUpEdge(hisSpaceCharge3D->GetYaxis()->GetNbins()); - Double_t zMin = hisSpaceCharge3D->GetZaxis()->GetBinCenter(0); - Double_t zMax = hisSpaceCharge3D->GetZaxis()->GetBinCenter(hisSpaceCharge3D->GetZaxis()->GetNbins()); - Double_t radius0, z0, phi0; - TMatrixD* charge; - - for (Int_t k = 0; k < fNPhiSlices; k++) { - if (side == 0) { - charge = fMatrixChargeA[k]; - } else { - charge = fMatrixChargeC[k]; - } - - phi0 = fListPhi[k]; - for (Int_t i = 0; i < fNRRows; i++) { - radius0 = fListR[i]; - for (Int_t j = 0; j < fNZColumns; j++) { - z0 = fListZ[j]; - - if (radius0 > rMin && radius0 < rMax && z0 > zMin && z0 < zMax) { - (*charge)(i, j) = norm * InterpolatePhi(hisSpaceCharge3D, phi0, radius0, z0); - } - } // end j - } // end i - } // end phi - - if (side == 0) { - fInterpolatorChargeA->SetValue(fMatrixChargeA); - fInterpolatorChargeA->InitCubicSpline(); - } else { - fInterpolatorChargeC->SetValue(fMatrixChargeC); - fInterpolatorChargeC->InitCubicSpline(); - } - - fInitLookUp = kFALSE; -} - -/// InterpolationPhi is only used for reading from TH3F (since it is not cylindrical) -/// -/// \param r -/// \param z -/// \return -Double_t AliTPCSpaceCharge3DCalc::InterpolatePhi(const TH3* h3, const Double_t phi, const Double_t r, const Double_t z) -{ - - Int_t ubx = h3->GetXaxis()->FindBin(phi); - if (phi < h3->GetXaxis()->GetBinCenter(ubx)) { - ubx -= 1; - } - Int_t obx = ubx + 1; - Int_t uby = h3->GetYaxis()->FindBin(r); - if (r < h3->GetYaxis()->GetBinCenter(uby)) { - uby -= 1; - } - Int_t oby = uby + 1; - Int_t ubz = h3->GetZaxis()->FindBin(z); - if (z < h3->GetZaxis()->GetBinCenter(ubz)) { - ubz -= 1; - } - Int_t obz = ubz + 1; - - if (uby <= 0 || ubz <= 0 || - oby > h3->GetYaxis()->GetNbins() || obz > h3->GetZaxis()->GetNbins()) { - return 0; - } - - if (ubx <= 0) { - ubx = h3->GetXaxis()->GetNbins(); - } - - if (obx > h3->GetXaxis()->GetNbins()) { - obx = 1; - } - - Double_t xw = h3->GetXaxis()->GetBinCenter(obx) - h3->GetXaxis()->GetBinCenter(ubx); - Double_t yw = h3->GetYaxis()->GetBinCenter(oby) - h3->GetYaxis()->GetBinCenter(uby); - Double_t zw = h3->GetZaxis()->GetBinCenter(obz) - h3->GetZaxis()->GetBinCenter(ubz); - Double_t xd = (phi - h3->GetXaxis()->GetBinCenter(ubx)) / xw; - Double_t yd = (r - h3->GetYaxis()->GetBinCenter(uby)) / yw; - Double_t zd = (z - h3->GetZaxis()->GetBinCenter(ubz)) / zw; - Double_t v[] = {h3->GetBinContent(ubx, uby, ubz), h3->GetBinContent(ubx, uby, obz), - h3->GetBinContent(ubx, oby, ubz), h3->GetBinContent(ubx, oby, obz), - h3->GetBinContent(obx, uby, ubz), h3->GetBinContent(obx, uby, obz), - h3->GetBinContent(obx, oby, ubz), h3->GetBinContent(obx, oby, obz)}; - Double_t i1 = v[0] * (1 - zd) + v[1] * zd; - Double_t i2 = v[2] * (1 - zd) + v[3] * zd; - Double_t j1 = v[4] * (1 - zd) + v[5] * zd; - Double_t j2 = v[6] * (1 - zd) + v[7] * zd; - Double_t w1 = i1 * (1 - yd) + i2 * yd; - Double_t w2 = j1 * (1 - yd) + j2 * yd; - Double_t result = w1 * (1 - xd) + w2 * xd; - return result; -} -/// returns the (input) space charge density at a given point according -/// Note: input in [cm], output in [C/m^3/e0] !! -Float_t AliTPCSpaceCharge3DCalc::GetSpaceChargeDensity(Float_t r, Float_t phi, Float_t z) -{ - while (phi < 0) { - phi += TMath::TwoPi(); - } - while (phi > TMath::TwoPi()) { - phi -= TMath::TwoPi(); - } - - const Int_t order = 1; // - - const Float_t x[] = {r, phi, z}; - Float_t sc = 0; - if (z > -1e-16) { - sc = GetChargeCylAC(x, 0); - } else { - sc = GetChargeCylAC(x, 18); - } - - return sc; -} -/// returns the (input) space charge density at a given point according -/// Note: input in [cm], output in [C/m^3/e0] !! -Float_t AliTPCSpaceCharge3DCalc::GetPotential(Float_t r, Float_t phi, Float_t z) -{ - while (phi < 0) { - phi += TMath::TwoPi(); - } - while (phi > TMath::TwoPi()) { - phi -= TMath::TwoPi(); - } - - const Int_t order = 1; // - - const Float_t x[] = {r, phi, z}; - Float_t v = 0; - if (z > -1e-16) { - v = GetPotentialCylAC(x, 0); - } else { - v = GetPotentialCylAC(x, 18); - } - - return v; -} -/// -/// -/// \param matricesDistDrDz TMatrixD ** matrix of global distortion drDist (r direction) -/// \param matricesDistDPhiRDz TMatrixD ** matrix of global distortion dRPhi (phi r direction) -/// \param matricesDistDz TMatrixD ** matrix of global distortion dzDist (z direction) -/// \param rList Double_t * points of r in the grid (ascending mode) -/// \param zList Double_t * points of z in the grid (ascending mode) -/// \param phiList Double_t * points of phi in the grid (ascending mode) -/// \param nRRow Int_t number of grid in r direction -/// \param nZColumn Int_t number of grid in z direction -/// \param phiSlice Int_t number of grid in phi direction -/// \param nStep Int_t number of step to calculate local dist -/// -void AliTPCSpaceCharge3DCalc::InverseGlobalToLocalDistortionGlobalInvTable( - TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, Double_t* rList, - Double_t* zList, Double_t* phiList, const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Int_t nStep, const Bool_t useCylAC, Int_t stepR, Int_t stepZ, Int_t stepPhi, Int_t type) -{ - Double_t z, phi, r, zAfter, zPrevious, ddR, ddRPhi, ddZ, zl, drDist, dRPhi, dzDist, ddPhi, dPhi, deltaZ, r0, z0, phi0; - Float_t x[3], dx[3], pdx[3]; - Int_t roc; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - TMatrixD* distDrDz; - TMatrixD* distDPhiRDz; - TMatrixD* distDz; - - // correction build up for inverse flow - TMatrixD* corrDrDz; - TMatrixD* corrDPhiRDz; - TMatrixD* corrDz; - TMatrixD* listR; - TMatrixD* listPhi; - TMatrixD* listZ; - TMatrixD* matricesCorrDrDz[phiSlice]; - TMatrixD* matricesCorrDPhiRDz[phiSlice]; - TMatrixD* matricesCorrDz[phiSlice]; - TMatrixD* matricesRList[phiSlice]; - TMatrixD* matricesPhiList[phiSlice]; - TMatrixD* matricesZList[phiSlice]; - - for (Int_t m = 0; m < phiSlice; m++) { - matricesCorrDrDz[m] = new TMatrixD(nRRow, nZColumn); - matricesCorrDPhiRDz[m] = new TMatrixD(nRRow, nZColumn); - matricesCorrDz[m] = new TMatrixD(nRRow, nZColumn); - - matricesRList[m] = new TMatrixD(nRRow, nZColumn); - matricesPhiList[m] = new TMatrixD(nRRow, nZColumn); - matricesZList[m] = new TMatrixD(nRRow, nZColumn); - } - - AliTPCLookUpTable3DInterpolatorIrregularD* lookupInverseCorr = new AliTPCLookUpTable3DInterpolatorIrregularD( - nRRow, matricesCorrDrDz, matricesRList, phiSlice, matricesCorrDPhiRDz, - matricesPhiList, nZColumn, matricesCorrDz, matricesZList, 2, - stepR, stepZ, stepPhi, type); - - lookupInverseCorr->SetKernelType(GetRBFKernelType()); - - for (Int_t k = 0; k < phiSlice; k++) { - distDrDz = matricesDistDrDz[k]; - distDPhiRDz = matricesDistDPhiRDz[k]; - distDz = matricesDistDz[k]; - - listR = matricesRList[k]; - listPhi = matricesPhiList[k]; - listZ = matricesZList[k]; - - for (Int_t i = 0; i < nRRow; i++) { - (*distDrDz)(i, nZColumn - 1) = 0.0; - (*distDPhiRDz)(i, nZColumn - 1) = 0.0; - (*distDz)(i, nZColumn - 1) = 0.0; - - for (Int_t j = 0; j < nZColumn; j++) { - (*listR)(i, j) = rList[i]; - (*listPhi)(i, j) = phiList[k]; - (*listZ)(i, j) = zList[j]; - } - } - } - - // 1) create global correction - deltaZ = (zList[1] - zList[0]); - Int_t iAnchor, kAnchor, zAnchor; - - for (Int_t j = nZColumn - 2; j >= 0; j--) { - - roc = 0; // FIXME - for (Int_t k = 0; k < phiSlice; k++) { - - corrDrDz = matricesCorrDrDz[k]; - corrDPhiRDz = matricesCorrDPhiRDz[k]; - corrDz = matricesCorrDz[k]; - - listR = matricesRList[k]; - listPhi = matricesPhiList[k]; - listZ = matricesZList[k]; - - for (Int_t i = 0; i < nRRow; i++) { - // get global distortion - - r = rList[i]; - phi = phiList[k]; - z = zList[j]; - - drDist = 0.0; - dzDist = 0.0; - dRPhi = 0.0; - - x[0] = r; - x[1] = phi; - x[2] = z; - - if (useCylAC == kTRUE) { - GetDistortionCylAC(x, roc, dx); - } else { - GetDistortionCyl(x, roc, dx); - } - - drDist = dx[0]; - dzDist = dx[2]; - dRPhi = dx[1]; - - r = rList[i]; - phi = phiList[k]; - z = zList[j]; - - (*corrDrDz)(i, j + 1) = -drDist; - (*corrDz)(i, j + 1) = -dzDist; - (*corrDPhiRDz)(i, j + 1) = -dRPhi; - - (*listR)(i, j + 1) = r + drDist; - (*listPhi)(i, j + 1) = phi + dRPhi / r; - (*listZ)(i, j + 1) = z + dzDist; - } - } - lookupInverseCorr->CopyFromMatricesToInterpolator(j + 1); - } - // 2) calculate local distortion - for (Int_t j = nZColumn - 2; j >= 0; j--) { - roc = 0; // FIXME - for (Int_t k = 0; k < phiSlice; k++) { - distDrDz = matricesDistDrDz[k]; - distDPhiRDz = matricesDistDPhiRDz[k]; - distDz = matricesDistDz[k]; - for (Int_t i = 0; i < nRRow; i++) { - // get global distortion - r = rList[i]; - phi = phiList[k]; - z = zList[j]; - drDist = 0.0; - dzDist = 0.0; - dRPhi = 0.0; - - if (j < nZColumn - 2) { - // get global distortion of this point - x[0] = r; - x[1] = phi; - x[2] = z; - if (useCylAC == kTRUE) { - GetDistortionCylAC(x, roc, dx); - } else { - GetDistortionCyl(x, roc, dx); - } - - r0 = r + dx[0]; - z0 = zList[j + 1] + dx[2]; - phi0 = phi + (dx[1] / r); - iAnchor = TMath::FloorNint((r0 - AliTPCPoissonSolver::fgkIFCRadius) / gridSizeR); - kAnchor = TMath::FloorNint(phi0 / gridSizePhi); - zAnchor = TMath::FloorNint(z0 / gridSizeZ); - - if (j > nZColumn - (GetIrregularGridSize() + 2)) { - lookupInverseCorr->GetValue(r0, phi0, z0, drDist, dRPhi, dzDist, iAnchor, kAnchor, zAnchor, - nRRow / 4 + 1, phiSlice / 4 + 1, 1, 0); - } else { - lookupInverseCorr->GetValue(r0, phi0, z0, drDist, dRPhi, dzDist, iAnchor, kAnchor, zAnchor, - nRRow / 4 + 1, phiSlice / 4 + 1, GetIrregularGridSize(), 0); - } - - phi0 = phi0 + ((dRPhi) / r0); - r0 = r0 + (drDist); - z0 += dzDist; - - x[0] = r0; - x[1] = phi0; - x[2] = z0; - - if (phi0 < 0) { - phi0 = TMath::TwoPi() + phi0; - } - if (phi0 > TMath::TwoPi()) { - phi0 = phi0 - TMath::TwoPi(); - } - - if (useCylAC == kTRUE) { - GetDistortionCylAC(x, roc, pdx); - } else { - GetDistortionCyl(x, roc, pdx); - } - - drDist = (dx[0] - pdx[0]); - dzDist = (dx[2] - pdx[2]); - dRPhi = (dx[1] - pdx[1]); - - } else if (j == (nZColumn - 2)) { - - x[0] = r; - x[1] = phi; - x[2] = zList[j]; - if (useCylAC == kTRUE) { - GetDistortionCylAC(x, roc, dx); - } else { - GetDistortionCyl(x, roc, dx); - } - - x[2] = zList[j + 1]; - if (useCylAC == kTRUE) { - GetDistortionCylAC(x, roc, pdx); - } else { - GetDistortionCyl(x, roc, pdx); - } - drDist = (dx[0] - pdx[0]); - dzDist = (dx[2] - pdx[2]); - dRPhi = (dx[1] - pdx[1]); - } - - (*distDrDz)(i, j) = drDist; - (*distDz)(i, j) = dzDist; - (*distDPhiRDz)(i, j) = dRPhi; - } - } - } - - for (Int_t m = 0; m < phiSlice; m++) { - delete matricesCorrDrDz[m]; - delete matricesCorrDPhiRDz[m]; - delete matricesCorrDz[m]; - delete matricesRList[m]; - delete matricesPhiList[m]; - delete matricesZList[m]; - } - delete lookupInverseCorr; -} -/// -/// \param matricesEr -/// \param matricesEPhi -/// \param matricesEz -/// \param matricesInvLocalIntErDz -/// \param matricesInvLocalIntEPhiDz -/// \param matricesInvLocalIntEz -/// \param matricesDistDrDz -/// \param matricesDistDPhiRDz -/// \param matricesDistDz -/// \param rList -/// \param zList -/// \param phiList -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -void AliTPCSpaceCharge3DCalc::InverseLocalDistortionToElectricField( - TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, - TMatrixD** matricesInvLocalIntErDz, TMatrixD** matricesInvLocalIntEPhiDz, - TMatrixD** matricesInvLocalIntEz, TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, - TMatrixD** matricesDistDz, Double_t* rList, Double_t* zList, Double_t* phiList, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice) -{ - // calculate integral - Float_t localIntErOverEz, localIntEPhiOverEz, localIntDeltaEz, z2; - Double_t r; - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm; - - TMatrixD* distDrDz; - TMatrixD* distDz; - TMatrixD* distDPhiRDz; - TMatrixD* tDistDz; - TMatrixD* tDistDPhiRDz; - TMatrixD* tDistDrDz; - Float_t c02c12 = fC0 * fC0 + fC1 * fC1; - - // solve local integration - for (Int_t j = 0; j < nZColumn; j++) { - for (Int_t k = 0; k < phiSlice; k++) { - distDrDz = matricesDistDrDz[k]; - distDz = matricesDistDz[k]; - distDPhiRDz = matricesDistDPhiRDz[k]; - - tDistDrDz = matricesInvLocalIntErDz[k]; - tDistDz = matricesInvLocalIntEz[k]; - tDistDPhiRDz = matricesInvLocalIntEPhiDz[k]; - for (Int_t i = 0; i < nRRow; i++) { - localIntErOverEz = fC0 * (*distDrDz)(i, j) - fC1 * (*distDPhiRDz)(i, j); - localIntErOverEz = localIntErOverEz / (fC0 * fC0 + fC1 * fC1); - localIntEPhiOverEz = ((*distDrDz)(i, j) - (fC0 * localIntErOverEz)) / fC1; - localIntDeltaEz = -1 * (*distDz)(i, j) / AliTPCPoissonSolver::fgkdvdE; // two times? - (*tDistDrDz)(i, j) = localIntErOverEz; - (*tDistDPhiRDz)(i, j) = localIntEPhiOverEz; - (*tDistDz)(i, j) = localIntDeltaEz; - } - } - } - TMatrixD* mEPhi; - TMatrixD* mEr; - TMatrixD* mEz; - - // use central-backward-forward difference for calculating Electric field component - for (Int_t m = 0; m < phiSlice; m++) { - mEPhi = matricesEPhi[m]; - mEr = matricesEr[m]; - mEz = matricesEz[m]; - distDrDz = matricesInvLocalIntErDz[m]; - distDPhiRDz = matricesInvLocalIntEPhiDz[m]; - distDz = matricesInvLocalIntEz[m]; - for (Int_t i = 0; i < nRRow; i++) { - (*mEr)(i, 0) = ((*distDrDz)(i, 0) / gridSizeZ) * -1 * ezField; - (*mEPhi)(i, 0) = ((*distDPhiRDz)(i, 0) / gridSizeZ) * -1 * ezField; - (*mEz)(i, 0) = ((*distDz)(i, 0) / gridSizeZ); - (*mEr)(i, nZColumn - 1) = - ((-0.5 * (*distDrDz)(i, nZColumn - 3) + 1.5 * (*distDrDz)(i, nZColumn - 2)) / gridSizeZ) * ezField; - (*mEPhi)(i, nZColumn - 1) = - ((-0.5 * (*distDPhiRDz)(i, nZColumn - 3) + 1.5 * (*distDPhiRDz)(i, nZColumn - 2)) / gridSizeZ) * - ezField; - (*mEz)(i, nZColumn - 1) = - (-0.5 * (*distDz)(i, nZColumn - 3) + 1.5 * (*distDz)(i, nZColumn - 2)) / gridSizeZ; - } - - for (Int_t i = 0; i < nRRow; i++) { - for (Int_t j = 1; j < nZColumn - 1; j++) { - (*mEr)(i, j) = (((*distDrDz)(i, j) + (*distDrDz)(i, j - 1)) / (2 * gridSizeZ)) * - ezField; // z direction - (*mEPhi)(i, j) = (((*distDPhiRDz)(i, j) + (*distDPhiRDz)(i, j - 1)) / (2 * gridSizeZ)) * - ezField; // z direction - (*mEz)(i, j) = ((*distDz)(i, j) + (*distDz)(i, j - 1)) / (2 * gridSizeZ); // z direction - } - } - } -} -/// Inverse Electric Field to Charge -/// using partial differential -/// -/// \param matricesCharge -/// \param matricesEr -/// \param matricesEPhi -/// \param matricesEz -/// \param rList -/// \param zList -/// \param phiList -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -void AliTPCSpaceCharge3DCalc::InverseElectricFieldToCharge( - TMatrixD** matricesCharge, TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, - Double_t* rList, Double_t* zList, Double_t* phiList, const Int_t nRRow, - const Int_t nZColumn, const Int_t phiSlice) -{ - - Float_t radius; - Double_t drDist, dzDist, dPhi; - Int_t mPlus, mMinus, mPlus2, mMinus2, signPlus, signMinus; - Int_t symmetry = 0; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - - for (Int_t m = 0; m < phiSlice; m++) { - mPlus = m + 1; - signPlus = 1; - mMinus = m - 1; - signMinus = 1; - mPlus2 = m + 2; - mMinus2 = m - 2; - if (symmetry == 1) { // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.) - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - } - if (mMinus < 0) { - mMinus = 1; - } - } else if (symmetry == -1) { // Anti-symmetry in phi - if (mPlus > phiSlice - 1) { - mPlus = phiSlice - 2; - signPlus = -1; - } - if (mMinus < 0) { - mMinus = 1; - signMinus = -1; - } - } else { // No Symmetries in phi, no boundaries, the calculations is continuous across all phi - if (mPlus > phiSlice - 1) { - mPlus = m + 1 - phiSlice; - } - if (mMinus < 0) { - mMinus = m - 1 + phiSlice; - } - if (mPlus2 > phiSlice - 1) { - mPlus2 = m + 2 - phiSlice; - } - if (mMinus2 < 0) { - mMinus2 = m - 2 + phiSlice; - } - } - - TMatrixD& matrixCharge = *matricesCharge[m]; - TMatrixD& matrixEr = *matricesEr[m]; - TMatrixD& matrixEz = *matricesEz[m]; - TMatrixD& matrixEPhi = *matricesEPhi[m]; - TMatrixD& matrixEPhiM = *matricesEPhi[mMinus]; - TMatrixD& matrixEPhiP = *matricesEPhi[mPlus]; - TMatrixD& matrixEPhiM2 = *matricesEPhi[mMinus2]; - TMatrixD& matrixEPhiP2 = *matricesEPhi[mPlus2]; - - // for non-boundary V - for (Int_t i = 2; i < nRRow - 2; i++) { - radius = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - for (Int_t j = 2; j < nZColumn - 2; j++) { - drDist = (-matrixEr(i + 2, j) + 8 * matrixEr(i + 1, j) - 8 * matrixEr(i - 1, j) + matrixEr(i - 2, j)) / - (12 * gridSizeR); // r direction - dzDist = (-matrixEz(i, j + 2) + 8 * matrixEz(i, j + 1) - 8 * matrixEz(i, j - 1) + matrixEz(i, j - 2)) / - (12 * gridSizeZ); // r direction - dPhi = (-matrixEPhiP2(i, j) + 8 * matrixEPhiP(i, j) - 8 * matrixEPhiM(i, j) + matrixEPhiM2(i, j)) / - (12 * gridSizePhi); // phi - - matrixCharge(i, j) = -1 * (matrixEr(i, j) / radius + drDist + dPhi / radius + dzDist); - } - } - - // for boundary in r - for (Int_t j = 2; j < nZColumn - 2; j++) { - - // r near inner radius - // for index r[0] - radius = AliTPCPoissonSolver::fgkIFCRadius; - drDist = (-(11.0 / 6.0) * matrixEr(0, j) + (3.0 * matrixEr(1, j)) - (1.5 * matrixEr(2, j)) + - ((1.0 / 3.0) * matrixEr(3, j))) / - gridSizeR; // forward difference - - // drDist = ( -(1.5)*matrixEr(0,j) + (2.0*matrixEr(1,j)) - (0.5*matrixEr(2,j)) ) / gridSizeR; - - dzDist = (-matrixEz(0, j + 2) + 8 * matrixEz(0, j + 1) - 8 * matrixEz(0, j - 1) + matrixEz(0, j - 2)) / - (12.0 * gridSizeZ); // z direction - dPhi = (-matrixEPhiP2(0, j) + 8 * matrixEPhiP(0, j) - 8 * matrixEPhiM(0, j) + matrixEPhiM2(0, j)) / - (12.0 * gridSizePhi); - - matrixCharge(0, j) = -1 * (matrixEr(0, j) / radius + drDist + dPhi / radius + dzDist); - - // index use central difference 3-point center - radius = AliTPCPoissonSolver::fgkIFCRadius + gridSizeR; - // drDist = (-matrixEr(3,j) +6.0*matrixEr(2,j) - 3.0*matrixEr(1,j) - 2*matrixEr(0,j) ) / (6.0*gridSizeR) ; // forward difference - drDist = (matrixEr(2, j) - matrixEr(0, j)) / (2.0 * gridSizeR); - - dzDist = (-matrixEz(1, j + 2) + 8 * matrixEz(1, j + 1) - 8 * matrixEz(1, j - 1) + matrixEz(1, j - 2)) / - (12 * gridSizeZ); // z direction - dPhi = (-matrixEPhiP2(1, j) + 8 * matrixEPhiP(1, j) - 8 * matrixEPhiM(1, j) + matrixEPhiM2(1, j)) / - (12 * gridSizePhi); - matrixCharge(1, j) = -1 * (matrixEr(1, j) / radius + drDist + dPhi / radius + dzDist); - - // index use central difference 3-point center - radius = AliTPCPoissonSolver::fgkIFCRadius + (nRRow - 2) * gridSizeR; - // drDist = (2.0 * matrixEr(nRRow - 1,j) + 3.0*matrixEr(nRRow - 2,j) - 6.0*matrixEr(nRRow -3,j) + matrixEr(nRRow-4,j) ) / (6.0*gridSizeR) ; - drDist = (matrixEr(nRRow - 1, j) - matrixEr(nRRow - 3, j)) / (2.0 * gridSizeR); - - dzDist = (-matrixEz(nRRow - 2, j + 2) + 8 * matrixEz(nRRow - 2, j + 1) - 8 * matrixEz(nRRow - 2, j - 1) + - matrixEz(nRRow - 2, j - 2)) / - (12 * gridSizeZ); - dPhi = (-matrixEPhiP2(nRRow - 2, j) + 8 * matrixEPhiP(nRRow - 2, j) - 8 * matrixEPhiM(nRRow - 2, j) + - matrixEPhiM2(nRRow - 2, j)) / - (12.0 * gridSizePhi); - matrixCharge(nRRow - 2, j) = -1 * (matrixEr(nRRow - 2, j) / radius + drDist + dPhi / radius + dzDist); - - // index r[nRRow -1] backward difference - radius = AliTPCPoissonSolver::fgkIFCRadius + (nRRow - 1) * gridSizeR; - //drDist = ( 1.5*matrixEr(nRRow-1,j) - 2.0*matrixEr(nRRow-2,j) + 0.5*matrixEr(nRRow-3,j) ) / gridSizeR ; // backward difference - drDist = - (-(11.0 / 6.0) * matrixEr(nRRow - 1, j) + (3.0 * matrixEr(nRRow - 2, j)) - - (1.5 * matrixEr(nRRow - 3, j)) + - ((1.0 / 3.0) * matrixEr(nRRow - 4, j))) / - (-1 * gridSizeR); - - //dzDist = ( matrixEz(nRRow-1,j+1) - matrixEz(nRRow-1,j-1) ) / (2*gridSizeZ) ; // z direction - dzDist = (-matrixEz(nRRow - 1, j + 2) + 8 * matrixEz(nRRow - 1, j + 1) - 8 * matrixEz(nRRow - 1, j - 1) + - matrixEz(nRRow - 1, j - 2)) / - (12 * gridSizeZ); - - dPhi = (-matrixEPhiP2(nRRow - 1, j) + 8 * matrixEPhiP(nRRow - 1, j) - 8 * matrixEPhiM(nRRow - 1, j) + - matrixEPhiM2(nRRow - 1, j)) / - (12 * gridSizePhi); - matrixCharge(nRRow - 1, j) = -1 * (matrixEr(nRRow - 1, j) / radius + drDist + dPhi / radius + dzDist); - } - - // boundary z - for (Int_t i = 2; i < nRRow - 2; i++) { - // z[0] - radius = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - dzDist = (-(11.0 / 6.0) * matrixEz(i, 0) + (3.0 * matrixEz(i, 1)) - (1.5 * matrixEz(i, 2)) + - ((1.0 / 3.0) * matrixEz(i, 3))) / - (1 * gridSizeZ); // forward difference - drDist = (-matrixEr(i + 2, 0) + 8 * matrixEr(i + 1, 0) - 8 * matrixEr(i - 1, 0) + matrixEr(i - 2, 0)) / - (12 * gridSizeR); // z direction - dPhi = (-matrixEPhiP2(i, 0) + 8 * matrixEPhiP(i, 0) - 8 * matrixEPhiM(i, 0) + matrixEPhiM2(i, 0)) / - (12 * gridSizePhi); - matrixCharge(i, 0) = -1 * (matrixEr(i, 0) / radius + drDist + dPhi / radius + dzDist); - - dzDist = (matrixEz(i, 2) - matrixEz(i, 0)) / (2.0 * gridSizeZ); // forward difference - - drDist = (-matrixEr(i + 2, 1) + 8 * matrixEr(i + 1, 1) - 8 * matrixEr(i - 1, 1) + matrixEr(i - 2, 1)) / - (12 * gridSizeR); // z direction - dPhi = (-matrixEPhiP2(i, 1) + 8 * matrixEPhiP(i, 1) - 8 * matrixEPhiM(i, 1) + matrixEPhiM2(i, 1)) / - (12 * gridSizePhi); - matrixCharge(i, 1) = -1 * (matrixEr(i, 1) / radius + drDist + dPhi / radius + dzDist); - - dzDist = (matrixEz(i, nZColumn - 1) - matrixEz(i, nZColumn - 3)) / (2.0 * gridSizeZ); // forward difference - - drDist = (-matrixEr(i + 2, nZColumn - 2) + 8 * matrixEr(i + 1, nZColumn - 2) - - 8 * matrixEr(i - 1, nZColumn - 2) + - matrixEr(i - 2, nZColumn - 2)) / - (12 * gridSizeR); // z direction - dPhi = (-matrixEPhiP2(i, nZColumn - 2) + 8 * matrixEPhiP(i, nZColumn - 2) - - 8 * matrixEPhiM(i, nZColumn - 2) + - matrixEPhiM2(i, nZColumn - 2)) / - (12 * gridSizePhi); - matrixCharge(i, nZColumn - 2) = -1 * (matrixEr(i, nZColumn - 2) / radius + drDist + dPhi / radius + dzDist); - - dzDist = (-(11.0 / 6.0) * matrixEz(i, nZColumn - 1) + (3.0 * matrixEz(i, nZColumn - 2)) - - (1.5 * matrixEz(i, nZColumn - 3)) + ((1.0 / 3.0) * matrixEz(i, nZColumn - 4))) / - (-gridSizeZ); // backward difference - drDist = (-matrixEr(i + 2, nZColumn - 1) + 8 * matrixEr(i + 1, nZColumn - 1) - - 8 * matrixEr(i - 1, nZColumn - 1) + - matrixEr(i - 2, nZColumn - 1)) / - (12 * gridSizeR); // z direction - dPhi = (-matrixEPhiP2(i, nZColumn - 1) + 8 * matrixEPhiP(i, nZColumn - 1) - - 8 * matrixEPhiM(i, nZColumn - 1) + - matrixEPhiM2(i, nZColumn - 1)) / - (12 * gridSizePhi); - matrixCharge(i, nZColumn - 1) = -1 * (matrixEr(i, nZColumn - 1) / radius + drDist + dPhi / radius + dzDist); - } - // for corner points - // corner points for EPhi - radius = AliTPCPoissonSolver::fgkIFCRadius; - drDist = - (-0.5 * matrixEr(2, 0) + 2.0 * matrixEr(1, 0) - 1.5 * matrixEr(0, 0)) / gridSizeR; // forward difference - dzDist = - (-0.5 * matrixEz(0, 2) + 2.0 * matrixEz(0, 1) - 1.5 * matrixEz(0, 0)) / gridSizeZ; // forward difference - dPhi = (-matrixEPhiP2(0, 0) + 8 * matrixEPhiP(0, 0) - 8 * matrixEPhiM(0, 0) + matrixEPhiM2(0, 0)) / - (12 * gridSizePhi); - matrixCharge(0, 0) = -1 * (matrixEr(0, 0) / radius + drDist + dPhi / radius + dzDist); - drDist = - (-0.5 * matrixEr(2, 1) + 2.0 * matrixEr(1, 1) - 1.5 * matrixEr(0, 1)) / gridSizeR; // forward difference - dzDist = (matrixEz(0, 2) - matrixEz(0, 0)) / (2.0 * gridSizeZ); // forward difference - dPhi = (-matrixEPhiP2(0, 1) + 8 * matrixEPhiP(0, 1) - 8 * matrixEPhiM(0, 1) + matrixEPhiM2(0, 1)) / - (12 * gridSizePhi); - matrixCharge(0, 1) = -1 * (matrixEr(0, 1) / radius + drDist + dPhi / radius + dzDist); - drDist = - (-0.5 * matrixEr(2, nZColumn - 2) + 2.0 * matrixEr(1, nZColumn - 2) - 1.5 * matrixEr(0, nZColumn - 2)) / - gridSizeR; // forward difference - dzDist = (2.0 * matrixEz(0, nZColumn - 1) + 3.0 * matrixEz(0, nZColumn - 2) - 6.0 * matrixEz(0, nZColumn - 3) + - matrixEz(0, nZColumn - 4)) / - (6.0 * gridSizeZ); // backward difference - dPhi = (-matrixEPhiP2(0, nZColumn - 2) + 8 * matrixEPhiP(0, nZColumn - 2) - 8 * matrixEPhiM(0, nZColumn - 2) + - matrixEPhiM2(0, nZColumn - 2)) / - (12 * gridSizePhi); - matrixCharge(0, nZColumn - 2) = -1 * (matrixEr(0, nZColumn - 2) / radius + drDist + dPhi / radius + dzDist); - drDist = - (-0.5 * matrixEr(2, nZColumn - 1) + 2.0 * matrixEr(1, nZColumn - 1) - 1.5 * matrixEr(0, nZColumn - 1)) / - gridSizeR; // forward difference - dzDist = (1.5 * matrixEz(0, nZColumn - 1) - 2.0 * matrixEz(0, nZColumn - 2) + 0.5 * matrixEz(0, nZColumn - 3)) / - gridSizeZ; // backward difference - dPhi = (-matrixEPhiP2(0, nZColumn - 1) + 8 * matrixEPhiP(0, nZColumn - 1) - 8 * matrixEPhiM(0, nZColumn - 1) + - matrixEPhiM2(0, nZColumn - 1)) / - (12 * gridSizePhi); - matrixCharge(0, nZColumn - 1) = -1 * (matrixEr(0, nZColumn - 1) / radius + drDist + dPhi / radius + dzDist); - - radius = AliTPCPoissonSolver::fgkIFCRadius + gridSizeR; - drDist = (-matrixEr(3, 0) + 6.0 * matrixEr(2, 0) - 3.0 * matrixEr(1, 0) - 2 * matrixEr(0, 0)) / - (6.0 * gridSizeR); // forward difference - dzDist = - (-0.5 * matrixEz(1, 2) + 2.0 * matrixEz(1, 1) - 1.5 * matrixEz(1, 0)) / gridSizeZ; // forward difference - dPhi = (-matrixEPhiP2(1, 0) + 8 * matrixEPhiP(1, 0) - 8 * matrixEPhiM(1, 0) + matrixEPhiM2(1, 0)) / - (12 * gridSizePhi); - matrixCharge(1, 0) = -1 * (matrixEr(1, 0) / radius + drDist + dPhi / radius + dzDist); - drDist = (-matrixEr(3, 1) + 6.0 * matrixEr(2, 1) - 3.0 * matrixEr(1, 1) - 2 * matrixEr(0, 1)) / - (6.0 * gridSizeR); // forward difference - dzDist = (-matrixEz(1, 3) + 6.0 * matrixEz(1, 2) - 3.0 * matrixEz(1, 1) - 2 * matrixEz(1, 0)) / - (6.0 * gridSizeZ); // forward difference - dPhi = (-matrixEPhiP2(1, 1) + 8 * matrixEPhiP(1, 1) - 8 * matrixEPhiM(1, 1) + matrixEPhiM2(1, 1)) / - (12 * gridSizePhi); - matrixCharge(1, 1) = -1 * (matrixEr(1, 1) / radius + drDist + dPhi / radius + dzDist); - drDist = (-matrixEr(3, nZColumn - 2) + 6.0 * matrixEr(2, nZColumn - 2) - 3.0 * matrixEr(1, nZColumn - 2) - - 2 * matrixEr(0, nZColumn - 2)) / - (6.0 * gridSizeR); // forward difference - dzDist = (2.0 * matrixEz(1, nZColumn - 1) + 3.0 * matrixEz(1, nZColumn - 2) - 6.0 * matrixEz(1, nZColumn - 3) + - matrixEz(1, nZColumn - 4)) / - (6.0 * gridSizeZ); // backward difference - dPhi = (-matrixEPhiP2(1, nZColumn - 2) + 8 * matrixEPhiP(1, nZColumn - 2) - 8 * matrixEPhiM(1, nZColumn - 2) + - matrixEPhiM2(1, nZColumn - 2)) / - (12 * gridSizePhi); - matrixCharge(1, nZColumn - 2) = -1 * (matrixEr(1, nZColumn - 2) / radius + drDist + dPhi / radius + dzDist); - - drDist = (-matrixEr(3, nZColumn - 1) + 6.0 * matrixEr(2, nZColumn - 1) - 3.0 * matrixEr(1, nZColumn - 1) - - 2 * matrixEr(0, nZColumn - 1)) / - (6.0 * gridSizeR); // forward difference - dzDist = (1.5 * matrixEz(1, nZColumn - 1) - 2.0 * matrixEz(1, nZColumn - 2) + 0.5 * matrixEz(1, nZColumn - 3)) / - gridSizeZ; // backward difference - dPhi = (-matrixEPhiP2(1, nZColumn - 1) + 8 * matrixEPhiP(1, nZColumn - 1) - 8 * matrixEPhiM(1, nZColumn - 1) + - matrixEPhiM2(1, nZColumn - 1)) / - (12 * gridSizePhi); - matrixCharge(1, nZColumn - 1) = -1 * (matrixEr(1, nZColumn - 1) / radius + drDist + dPhi / radius + dzDist); - - radius = AliTPCPoissonSolver::fgkIFCRadius + (nRRow - 2) * gridSizeR; - drDist = (2.0 * matrixEr(nRRow - 1, 0) + 3.0 * matrixEr(nRRow - 2, 0) - 6.0 * matrixEr(nRRow - 3, 0) + - matrixEr(nRRow - 4, 0)) / - (6.0 * gridSizeR); // backward difference - dzDist = (-0.5 * matrixEz(nRRow - 2, 2) + 2.0 * matrixEz(nRRow - 2, 1) - 1.5 * matrixEz(nRRow - 2, 0)) / - gridSizeZ; // forward difference - dPhi = (-matrixEPhiP2(nRRow - 2, 0) + 8 * matrixEPhiP(nRRow - 2, 0) - 8 * matrixEPhiM(nRRow - 2, 0) + - matrixEPhiM2(nRRow - 2, 0)) / - (12 * gridSizePhi); - - matrixCharge(nRRow - 2, 0) = -1 * (matrixEr(nRRow - 2, 0) / radius + drDist + dPhi / radius + dzDist); - drDist = (2.0 * matrixEr(nRRow - 1, 1) + 3.0 * matrixEr(nRRow - 2, 1) - 6.0 * matrixEr(nRRow - 3, 1) + - matrixEr(nRRow - 4, 1)) / - (6.0 * gridSizeR); // backward difference - dzDist = (-matrixEz(nRRow - 2, 3) + 6.0 * matrixEz(nRRow - 2, 2) - 3.0 * matrixEz(nRRow - 2, 1) - - 2 * matrixEz(nRRow - 2, 0)) / - (6.0 * gridSizeZ); // forward difference - dPhi = (-matrixEPhiP2(nRRow - 2, 1) + 8 * matrixEPhiP(nRRow - 2, 1) - 8 * matrixEPhiM(nRRow - 2, 1) + - matrixEPhiM2(nRRow - 2, 1)) / - (12 * gridSizePhi); - matrixCharge(nRRow - 2, 1) = -1 * (matrixEr(nRRow - 2, 1) / radius + drDist + dPhi / radius + dzDist); - drDist = (2.0 * matrixEr(nRRow - 1, nZColumn - 2) + 3.0 * matrixEr(nRRow - 2, nZColumn - 2) - - 6.0 * matrixEr(nRRow - 3, nZColumn - 2) + matrixEr(nRRow - 4, nZColumn - 2)) / - (6.0 * gridSizeR); // backward difference - dzDist = (2.0 * matrixEz(nRRow - 2, nZColumn - 1) + 3.0 * matrixEz(nRRow - 2, nZColumn - 2) - - 6.0 * matrixEz(nRRow - 2, nZColumn - 3) + matrixEz(nRRow - 2, nZColumn - 4)) / - (6.0 * gridSizeZ); // backward difference - dPhi = (-matrixEPhiP2(nRRow - 2, nZColumn - 2) + 8 * matrixEPhiP(nRRow - 2, nZColumn - 2) - - 8 * matrixEPhiM(nRRow - 2, nZColumn - 2) + matrixEPhiM2(nRRow - 2, nZColumn - 2)) / - (12 * gridSizePhi); - matrixCharge(nRRow - 2, nZColumn - 2) = - -1 * (matrixEr(nRRow - 2, nZColumn - 2) / radius + drDist + dPhi / radius + dzDist); - drDist = (2.0 * matrixEr(nRRow - 1, nZColumn - 1) + 3.0 * matrixEr(nRRow - 2, nZColumn - 1) - - 6.0 * matrixEr(nRRow - 3, nZColumn - 1) + matrixEr(nRRow - 4, nZColumn - 1)) / - (6.0 * gridSizeR); // backward difference - dzDist = (1.5 * matrixEz(0, nZColumn - 1) - 2.0 * matrixEz(0, nZColumn - 2) + 0.5 * matrixEz(0, nZColumn - 3)) / - gridSizeZ; // backward difference - dPhi = (-matrixEPhiP2(nRRow - 2, nZColumn - 1) + 8 * matrixEPhiP(nRRow - 2, nZColumn - 1) - - 8 * matrixEPhiM(nRRow - 2, nZColumn - 1) + matrixEPhiM2(nRRow - 2, nZColumn - 1)) / - (12 * gridSizePhi); - - matrixCharge(nRRow - 2, nZColumn - 1) = - -1 * (matrixEr(nRRow - 2, nZColumn - 1) / radius + drDist + dPhi / radius + dzDist); - radius = AliTPCPoissonSolver::fgkIFCRadius + (nRRow - 1) * gridSizeR; - drDist = (1.5 * matrixEr(nRRow - 1, 0) - 2.0 * matrixEr(nRRow - 2, 0) + 0.5 * matrixEr(nRRow - 3, 0)) / - gridSizeR; // backward difference - dzDist = (-0.5 * matrixEz(nRRow - 1, 2) + 2.0 * matrixEz(nRRow - 1, 1) - 1.5 * matrixEz(nRRow - 1, 0)) / - gridSizeZ; // forward difference - dPhi = (-matrixEPhiP2(nRRow - 1, 0) + 8 * matrixEPhiP(nRRow - 1, 0) - 8 * matrixEPhiM(nRRow - 1, 0) + - matrixEPhiM2(nRRow - 1, 0)) / - (12 * gridSizePhi); - matrixCharge(nRRow - 1, 0) = -1 * (matrixEr(nRRow - 1, 0) / radius + drDist + dPhi / radius + dzDist); - drDist = (1.5 * matrixEr(nRRow - 1, 1) - 2.0 * matrixEr(nRRow - 2, 1) + 0.5 * matrixEr(nRRow - 3, 1)) / - gridSizeR; // backward difference - dzDist = (-matrixEz(nRRow - 1, 3) + 6.0 * matrixEz(nRRow - 1, 2) - 3.0 * matrixEz(nRRow - 1, 1) - - 2 * matrixEz(nRRow - 1, 0)) / - (6.0 * gridSizeZ); // forward difference - dPhi = (-matrixEPhiP2(nRRow - 1, 1) + 8 * matrixEPhiP(nRRow - 1, 1) - 8 * matrixEPhiM(nRRow - 1, 1) + - matrixEPhiM2(nRRow - 1, 1)) / - (12 * gridSizePhi); - matrixCharge(nRRow - 1, 1) = -1 * (matrixEr(nRRow - 1, 1) / radius + drDist + dPhi / radius + dzDist); - - drDist = (1.5 * matrixEr(nRRow - 1, nZColumn - 2) - 2.0 * matrixEr(nRRow - 2, nZColumn - 2) + - 0.5 * matrixEr(nRRow - 3, nZColumn - 2)) / - gridSizeR; // backward difference - dzDist = (2.0 * matrixEz(nRRow - 1, nZColumn - 1) + 3.0 * matrixEz(nRRow - 1, nZColumn - 2) - - 6.0 * matrixEz(nRRow - 1, nZColumn - 3) + matrixEz(nRRow - 1, nZColumn - 4)) / - (6.0 * gridSizeZ); // backward difference - dPhi = (-matrixEPhiP2(nRRow - 1, nZColumn - 2) + 8 * matrixEPhiP(nRRow - 1, nZColumn - 2) - - 8 * matrixEPhiM(nRRow - 1, nZColumn - 2) + matrixEPhiM2(nRRow - 1, nZColumn - 2)) / - (12 * gridSizePhi); - matrixCharge(nRRow - 1, nZColumn - 2) = - -1 * (matrixEr(nRRow - 1, nZColumn - 2) / radius + drDist + dPhi / radius + dzDist); - - drDist = (1.5 * matrixEr(nRRow - 1, nZColumn - 1) - 2.0 * matrixEr(nRRow - 2, nZColumn - 1) + - 0.5 * matrixEr(nRRow - 3, nZColumn - 1)) / - gridSizeR; // backward difference - dzDist = (1.5 * matrixEz(nRRow - 1, nZColumn - 1) - 2.0 * matrixEz(nRRow - 1, nZColumn - 2) + - 0.5 * matrixEz(nRRow - 1, nZColumn - 3)) / - gridSizeZ; // backward difference - - dPhi = (-matrixEPhiP2(nRRow - 1, nZColumn - 1) + 8 * matrixEPhiP(nRRow - 1, nZColumn - 1) - - 8 * matrixEPhiM(nRRow - 1, nZColumn - 1) + matrixEPhiM2(nRRow - 1, nZColumn - 1)) / - (12 * gridSizePhi); - - matrixCharge(nRRow - 1, nZColumn - 1) = - -1 * (matrixEr(nRRow - 1, nZColumn - 1) / radius + drDist + dPhi / radius + dzDist); - } -} -/// -/// \param matricesCharge -/// \param matricesEr -/// \param matricesEPhi -/// \param matricesEz -/// \param matricesInvLocalIntErDz -/// \param matricesInvLocalIntEPhiDz -/// \param matricesInvLocalEz -/// \param matricesDistDrDz -/// \param matricesDistDPhiRDz -/// \param matricesDistDz -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -/// \param nSize -/// \param useCylAC -/// \param stepR -/// \param stepZ -/// \param stepPhi -/// \param interpType -/// \param inverseType -void AliTPCSpaceCharge3DCalc::InverseDistortionMaps( - TMatrixD** matricesCharge, TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, - TMatrixD** matricesInvLocalIntErDz, TMatrixD** matricesInvLocalIntEPhiDz, TMatrixD** matricesInvLocalEz, - TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t nSize, - const Bool_t useCylAC, Int_t stepR, Int_t stepZ, Int_t stepPhi, Int_t interpType) -{ - // can inverse after lookup table for global distortion been calculated - Double_t* rList = new Double_t[nRRow]; - Double_t* zList = new Double_t[nZColumn]; - Double_t* phiList = new Double_t[phiSlice]; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - - for (Int_t k = 0; k < phiSlice; k++) { - phiList[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < nRRow; i++) { - rList[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < nZColumn; j++) { - zList[j] = (j * gridSizeZ); - } - // memory allocation - if (fInitLookUp) { - // 1) get local distortion - InverseGlobalToLocalDistortionGlobalInvTable(matricesDistDrDz, matricesDistDPhiRDz, matricesDistDz, rList, - zList, phiList, nRRow, nZColumn, phiSlice, nSize, useCylAC, - stepR, stepZ, stepPhi, interpType); - - fLookupInverseDistA->SetLookUpR(matricesDistDrDz); - fLookupInverseDistA->SetLookUpPhi(matricesDistDPhiRDz); - fLookupInverseDistA->SetLookUpZ(matricesDistDz); - fLookupInverseDistA->CopyFromMatricesToInterpolator(); - - // 2) calculate local integral - InverseLocalDistortionToElectricField(matricesEr, matricesEPhi, matricesEz, matricesInvLocalIntErDz, - matricesInvLocalIntEPhiDz, matricesInvLocalEz, - matricesDistDrDz, matricesDistDPhiRDz, matricesDistDz, rList, zList, - phiList, nRRow, nZColumn, phiSlice); - // 3) get potential from electric field assuming zero boundaries - InverseElectricFieldToCharge(matricesCharge, matricesEr, matricesEPhi, matricesEz, rList, zList, phiList, nRRow, - nZColumn, phiSlice); - } - - // copy charge inverse here just for side A (TODO: do for side C) - for (Int_t k = 0; k < phiSlice; k++) { - *(fMatrixChargeInverseA[k]) = *(matricesCharge[k]); - } - fInterpolatorInverseChargeA->SetValue(fMatrixChargeInverseA); - fInterpolatorInverseChargeA->InitCubicSpline(); - - delete[] zList; - delete[] rList; - delete[] phiList; -} -/// CalculateEField (New Version: with reorganization of modules) -/// Calculate E field based on look-up table created by Poisson Solver -/// * Differentiate V(r) and solve for E(r) using special equations for the first and last row -/// * Integrate E(r)/E(z) from point of origin to pad plane -/// * Differentiate V(r) and solve for E(phi) -/// * Integrate E(phi)/E(z) from point of origin to pad plane -/// * Differentiate V(r) and solve for E(z) using special equations for the first and last row -/// * Integrate (E(z)-Ez(ROC)) from point of origin to pad plane -/// -/// \param matricesV TMatrixD** 3D matrix representing calculated potential -/// \param matricesErOverEz TMatrix** 3D matrix representing e-field at Er/Ez -/// \param matricesEPhiOverEz TMatrix** 3D matrix representing e-field at EPhi/Ez -/// \param matricesDeltaZ TMatrix** 3D matrix representing e-field at DeltaZ -/// \param nRRow Int_t number of nRRow (in R direction) -/// \param nZColumn Int_t number of nZColumn (in Z direction) -/// \param phiSlice Int_t number of (phi slices in phi direction) -/// \param symmetry Int_t symmetry? -/// \param rocDisplace rocDisplacement -/// -/// \pre Matrix matricesV is assumed had been calculated by Poisson solver -/// \post Results of Integration and Derivations for E-field calculation are stored in matricesErOverEz, matricesEPhiOverEz, matricesDeltaZ -/// -void AliTPCSpaceCharge3DCalc::CalculateEField( - TMatrixD** matricesV, TMatrixD** matricesErOverEz, TMatrixD** matricesEPhiOverEz, - TMatrixD** matricesDeltaEz, const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Int_t symmetry, Bool_t rocDisplacement) -{ - - const Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - TMatrixD *matricesEr[phiSlice], *matricesEz[phiSlice], *matricesEPhi[phiSlice]; - - //Allocate memory for electric field r,z, phi direction - for (Int_t k = 0; k < phiSlice; k++) { - matricesEr[k] = new TMatrixD(nRRow, nZColumn); - matricesEz[k] = new TMatrixD(nRRow, nZColumn); - matricesEPhi[k] = new TMatrixD(nRRow, nZColumn); - } - - //Differentiate V(r) and solve for E(r) using special equations for the first and last row - TStopwatch w; - w.Start(); - - ElectricField(matricesV, matricesEr, matricesEPhi, matricesEz, nRRow, nZColumn, - phiSlice, gridSizeR, gridSizePhi, gridSizeZ, symmetry, AliTPCPoissonSolver::fgkIFCRadius); - - w.Stop(); - Info("AliTPCSpaceCharge3DCalc::InitSpaceCharge3DPoissonIntegralDz", "%s", Form("Time for calculation E-field CPU = %f s\n", w.CpuTime())); - - //Integrate E(r)/E(z) from point of origin to pad plane - - IntegrateEz(matricesErOverEz, matricesEr, nRRow, nZColumn, phiSlice, ezField); - IntegrateEz(matricesEPhiOverEz, matricesEPhi, nRRow, nZColumn, phiSlice, ezField); - IntegrateEz(matricesDeltaEz, matricesEz, nRRow, nZColumn, phiSlice, -1.0); - - // calculate z distortion from the integrated Delta Ez residuals - // and include the equivalence (Volt to cm) of the ROC shift !! - for (Int_t m = 0; m < phiSlice; m++) { - TMatrixD& arrayV = *matricesV[m]; - TMatrixD& deltaEz = *matricesDeltaEz[m]; - - for (Int_t j = 0; j < nZColumn; j++) { - for (Int_t i = 0; i < nRRow; i++) { - // Scale the Ez distortions with the drift velocity -> delivers cm - deltaEz(i, j) = deltaEz(i, j) * AliTPCPoissonSolver::fgkdvdE; - // ROC Potential in cm equivalent - Double_t dzROCShift = arrayV(i, nZColumn - 1) / ezField; - if (rocDisplacement) { - deltaEz(i, j) = deltaEz(i, j) + dzROCShift; // add the ROC mis alignment - } - } - } - } - // clear the temporary arrays lists - - for (Int_t k = 0; k < phiSlice; k++) { - delete matricesEr[k]; - delete matricesEz[k]; - delete matricesEPhi[k]; - } -} -/// -/// Integrate at z direction Ez for electron drift calculation -/// -/// -/// \param matricesExOverEz TMatrixD** 3D matrix representing ExOverEz -/// \param matricesEx TMatrix** 3D matrix representing e-field at x direction -/// \param nRRow const Int_t number of nRRow (in R direction) -/// \param nZColumn const Int_t number of nZColumn (in Z direction) -/// \param phiSlice const Int_t number of (phiSlice in phi direction) -/// \param ezField const Double_t Electric field in z direction -/// -/// \pre matricesEx is assumed already been calculated by ElectricFieldCalculation -/// \post Matrix matricesExOverEz is calculated by integration of matricesEx -/// -void AliTPCSpaceCharge3DCalc::IntegrateEz( - TMatrixD** matricesExOverEz, TMatrixD** matricesEx, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, const Double_t ezField) -{ - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - for (Int_t m = 0; m < phiSlice; m++) { - TMatrixD& eXoverEz = *matricesExOverEz[m]; - TMatrixD& arrayEx = *matricesEx[m]; - - for (Int_t j = nZColumn - 1; j >= 0; j--) { - for (Int_t i = 0; i < nRRow; i++) { - - /// Calculate integration from int^{0}_{j} (TODO: Split the integration) - if (j < nZColumn - 3) { - eXoverEz(i, j) = eXoverEz(i, j + 2) + - (gridSizeZ / 3.0) * (arrayEx(i, j) + 4 * arrayEx(i, j + 1) + arrayEx(i, j + 2)) / - (-1 * ezField); - } else { - if (j == nZColumn - 3) { - eXoverEz(i, j) = (gridSizeZ / 3.0) * (arrayEx(i, nZColumn - 3) + 4 * arrayEx(i, nZColumn - 2) + arrayEx(i, nZColumn - 1)) / (-1 * ezField); - } - if (j == nZColumn - 2) { - eXoverEz(i, j) = - (gridSizeZ / 3.0) * (1.5 * arrayEx(i, nZColumn - 2) + 1.5 * arrayEx(i, nZColumn - 1)) / - (-1 * ezField); - } - if (j == nZColumn - 1) { - eXoverEz(i, j) = 0.0; - } - } - } - } - } -} -/// GetCorrection from no-drift -/// -/// \param x Float_t point origin -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetCorrectionCylNoDrift(const Float_t x[], const Short_t roc, Float_t dx[]) -{ - /// Calculates the correction due the Space Charge effect within the TPC drift volume - - if (!fInitLookUp) { - Info("AliTPCSpaceCharge3DCalc::", "Lookup table was not initialized! Performing the initialization now ..."); - // InitSpaceCharge3DDistortion(); - return; - } - - Float_t intEr, intEPhi, intDEz; - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi -= TMath::TwoPi(); - } - - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < 0) || (sign == -1 && z > 0)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (sign == -1 && z < 0.0) { - printf("call C side\n"); - fLookupIntENoDriftC->GetValue(r, phi, z, intEr, intEPhi, intDEz); - } else { - fLookupIntENoDriftA->GetValue(r, phi, z, intEr, intEPhi, intDEz); - } - - // Calculate distorted position - if (r > 0.0) { - phi = phi + fCorrectionFactor * (fC0 * intEPhi - fC1 * intEr) / r; - r = r + fCorrectionFactor * (fC0 * intEr + fC1 * intEPhi); - } - Double_t dzDist = intDEz * fCorrectionFactor * AliTPCPoissonSolver::fgkdvdE; - - // Calculate correction in cartesian coordinates - dx[0] = -(r - x[0]); - dx[1] = -(phi - x[1]); - dx[2] = -dzDist; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetDistortionCylNoDrift(const Float_t x[], Short_t roc, Float_t dx[]) -{ - /// This function delivers the distortion values dx in respect to the initial coordinates x - /// roc represents the TPC read out chamber (offline numbering convention) - - GetCorrectionCylNoDrift(x, roc, dx); - for (Int_t j = 0; j < 3; ++j) { - dx[j] = -dx[j]; - } -} -/// inverse for no drift -/// inverse from global distortion to local distortion -/// -/// \param matricesDistDrDz -/// \param matricesDistDPhiRDz -/// \param matricesDistDz -/// \param rList -/// \param zList -/// \param phiList -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -void AliTPCSpaceCharge3DCalc::InverseGlobalToLocalDistortionNoDrift( - TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, - Double_t* rList, Double_t* zList, Double_t* phiList, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice) -{ - - Double_t z, phi, r, zAfter, zPrevious, ddR, ddRPhi, ddZ, drDist, dRPhi, dzDist; - Float_t x[3], dx[3], pdx[3], dxp1[3], dxp2[3]; - Int_t roc; - TMatrixD* distDrDz; - TMatrixD* distDPhiRDz; - TMatrixD* distDz; - - for (Int_t k = 0; k < phiSlice; k++) { - distDrDz = matricesDistDrDz[k]; - distDPhiRDz = matricesDistDPhiRDz[k]; - distDz = matricesDistDz[k]; - for (Int_t i = 0; i < nRRow; i++) { - (*distDrDz)(i, nZColumn - 1) = 0.0; - (*distDPhiRDz)(i, nZColumn - 1) = 0.0; - (*distDz)(i, nZColumn - 1) = 0.0; - } - } - - for (Int_t j = nZColumn - 2; j >= 0; j--) { - roc = 0; // FIXME - for (Int_t k = 0; k < phiSlice; k++) { - - distDrDz = matricesDistDrDz[k]; - distDPhiRDz = matricesDistDPhiRDz[k]; - distDz = matricesDistDz[k]; - for (Int_t i = 0; i < nRRow; i++) { - // get global distortion - - r = rList[i]; - phi = phiList[k]; - z = zList[j]; - zPrevious = zList[j + 1]; - //zAfter = zList[j-1]; - - (*distDrDz)(i, j) = 0.0; - (*distDPhiRDz)(i, j) = 0.0; - (*distDz)(i, j) = 0.0; - drDist = 0.0; - dRPhi = 0.0; - dzDist = 0.0; - - r = rList[i]; - phi = phiList[k]; - z = zList[j]; - - x[0] = r; - x[1] = phi; - x[2] = z; - - GetDistortionCylNoDrift(x, roc, dx); - - //x[0] = x[0] + drDist; - //x[1] = x[1] + dRPhi/r; - x[2] = zPrevious; - - GetDistortionCylNoDrift(x, roc, pdx); - - (*distDrDz)(i, j) = (dx[0] - pdx[0]); - (*distDPhiRDz)(i, j) = (dx[1] - pdx[1]) * r; - (*distDz)(i, j) = (dx[2] - pdx[2]); - } - } - } -} -/// -/// \param matricesCharge -/// \param matricesEr -/// \param matricesEPhi -/// \param matricesEz -/// \param matricesInvLocalIntErDz -/// \param matricesInvLocalIntEPhiDz -/// \param matricesInvLocalEz -/// \param matricesDistDrDz -/// \param matricesDistDPhiRDz -/// \param matricesDistDz -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -void AliTPCSpaceCharge3DCalc::InverseDistortionMapsNoDrift( - TMatrixD** matricesCharge, TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, - TMatrixD** matricesInvLocalIntErDz, TMatrixD** matricesInvLocalIntEPhiDz, TMatrixD** matricesInvLocalEz, - TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice) -{ - // can inverse after lookup table for global distortion been calculated - Double_t* rList = new Double_t[nRRow]; - Double_t* zList = new Double_t[nZColumn]; - Double_t* phiList = new Double_t[phiSlice]; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - - for (Int_t k = 0; k < phiSlice; k++) { - phiList[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < nRRow; i++) { - rList[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < nZColumn; j++) { - zList[j] = (j * gridSizeZ); - } - // memory allocation - if (fInitLookUp) { - // 1) get local distortion - InverseGlobalToLocalDistortionNoDrift(matricesDistDrDz, matricesDistDPhiRDz, matricesDistDz, rList, zList, - phiList, nRRow, nZColumn, phiSlice); - // 2) calculate local integral - InverseLocalDistortionToElectricField(matricesEr, matricesEPhi, matricesEz, matricesInvLocalIntErDz, - matricesInvLocalIntEPhiDz, matricesInvLocalEz, - matricesDistDrDz, matricesDistDPhiRDz, matricesDistDz, rList, zList, - phiList, nRRow, nZColumn, phiSlice); - // 3) get potential from electric field assuming zero boundaries - InverseElectricFieldToCharge(matricesCharge, matricesEr, matricesEPhi, matricesEz, rList, zList, phiList, nRRow, - nZColumn, phiSlice); - } - delete[] zList; - delete[] rList; - delete[] phiList; -} -/// -/// \param matricesChargeA -/// \param matricesChargeC -/// \param spaceChargeHistogram3D -/// \param nRRow -/// \param nZColumn -/// \param phiSlice -void AliTPCSpaceCharge3DCalc::GetChargeDensity( - TMatrixD** matricesChargeA, TMatrixD** matricesChargeC, const TH3* spaceChargeHistogram3D, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice) -{ - Int_t phiSlicesPerSector = phiSlice / kNumSector; - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (nRRow - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (nZColumn - 1); - const Float_t gridSizePhi = TMath::TwoPi() / phiSlice; - const Double_t ezField = (AliTPCPoissonSolver::fgkCathodeV - AliTPCPoissonSolver::fgkGG) / AliTPCPoissonSolver::fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm; - // local variables - Float_t radius0, phi0, z0; - // list of point as used in the poisson relaxation and the interpolation (for interpolation) - Double_t rList[nRRow], zList[nZColumn], phiList[phiSlice]; - for (Int_t k = 0; k < phiSlice; k++) { - phiList[k] = gridSizePhi * k; - } - for (Int_t i = 0; i < nRRow; i++) { - rList[i] = AliTPCPoissonSolver::fgkIFCRadius + i * gridSizeR; - } - for (Int_t j = 0; j < nZColumn; j++) { - zList[j] = j * gridSizeZ; - } - - TMatrixD* mCharge; - for (Int_t side = 0; side < 2; side++) { - for (Int_t k = 0; k < phiSlice; k++) { - if (side == 0) { - mCharge = matricesChargeA[k]; - } else { - mCharge = matricesChargeC[k]; - } - - phi0 = phiList[k]; - for (Int_t i = 0; i < nRRow; i++) { - radius0 = rList[i]; - for (Int_t j = 0; j < nZColumn; j++) { - z0 = zList[j]; - if (side == 1) { - z0 = -TMath::Abs(zList[j]); - } - if (spaceChargeHistogram3D != nullptr) { - (*mCharge)(i, j) = InterpolatePhi(spaceChargeHistogram3D, phi0, radius0, z0); - //InterpolatePhi(spaceChargeHistogram3D,phi0,radius0,z0); - } - } - } - } - } -} -/// -/// \param x -/// \param roc -/// \return -Double_t AliTPCSpaceCharge3DCalc::GetChargeCylAC(const Float_t x[], Short_t roc) const -{ - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < 0) || (sign == -1 && z > 0)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - return fInterpolatorChargeA->GetValue(r, phi, z); - } else { - return fInterpolatorChargeC->GetValue(r, phi, -z); - } -} -/// -/// \param x -/// \param roc -/// \return -Double_t AliTPCSpaceCharge3DCalc::GetPotentialCylAC(const Float_t x[], Short_t roc) const -{ - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < 0) || (sign == -1 && z > 0)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - return fInterpolatorPotentialA->GetValue(r, phi, z); - } else { - return fInterpolatorPotentialC->GetValue(r, phi, -z); - } -} -/// chargeInverse -/// -/// \param x -/// \param roc -/// \return -Double_t AliTPCSpaceCharge3DCalc::GetInverseChargeCylAC(const Float_t x[], Short_t roc) const -{ - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < 0) || (sign == -1 && z > 0)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-6) { - return fInterpolatorInverseChargeA->GetValue(r, phi, z); - } else { - return fInterpolatorInverseChargeC->GetValue(r, phi, z); - } -} - -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetLocalDistortionCyl(const Float_t x[], Short_t roc, Float_t dx[]) -{ - Float_t dR, dRPhi, dZ; - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < -1e-16) || (sign == -1 && z > -1e-16)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - fLookupDistA->GetValue(r, phi, z, dR, dRPhi, dZ); - } else { - fLookupDistC->GetValue(r, phi, -z, dR, dRPhi, dZ); - dZ = -1 * dZ; - } - - dx[0] = fCorrectionFactor * dR; - dx[1] = fCorrectionFactor * dRPhi; - dx[2] = fCorrectionFactor * - dZ; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} - -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetLocalCorrectionCyl(const Float_t x[], Short_t roc, Float_t dx[]) -{ - Float_t dR, dRPhi, dZ; - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < -1e-16) || (sign == -1 && z > -1e-16)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - fLookupCorrA->GetValue(r, phi, z, dR, dRPhi, dZ); - } else { - fLookupCorrC->GetValue(r, phi, -z, dR, dRPhi, dZ); - dZ = -1 * dZ; - } - - dx[0] = fCorrectionFactor * dR; - dx[1] = fCorrectionFactor * dRPhi; - dx[2] = fCorrectionFactor * - dZ; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} - -/// Get Electric field from look up table -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetElectricFieldCyl(const Float_t x[], Short_t roc, Double_t dx[]) -{ - Double_t eR, ePhi, eZ; - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < -1e-16) || (sign == -1 && z > -1e-16)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - fLookupElectricFieldA->GetValue(r, phi, z, eR, ePhi, eZ); - } else { - fLookupElectricFieldC->GetValue(r, phi, -z, eR, ePhi, eZ); - eZ = -1 * eZ; - } - - dx[0] = eR; - dx[1] = ePhi; - dx[2] = eZ; -} - -/// -/// \param x -/// \param roc -/// \param dx -void AliTPCSpaceCharge3DCalc::GetInverseLocalDistortionCyl(const Float_t x[], Short_t roc, Float_t dx[]) -{ - if (!fInitLookUp) { - Info("AliTPCSpaceCharge3DCalc::", "Lookup table was not initialized! Performing the initialization now ..."); - InitSpaceCharge3DPoissonIntegralDz(129, 129, 144, 100, 1e-8); - } - - Float_t dR, dRPhi, dZ; - Double_t r, phi, z; - Int_t sign; - - r = x[0]; - phi = x[1]; - if (phi < 0) { - phi += TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - if (phi > TMath::TwoPi()) { - phi = phi - TMath::TwoPi(); // Table uses phi from 0 to 2*Pi - } - z = x[2]; // Create temporary copy of x[2] - - if ((roc % 36) < 18) { - sign = 1; // (TPC A side) - } else { - sign = -1; // (TPC C side) - } - - if (sign == 1 && z < AliTPCPoissonSolver::fgkZOffSet) { - z = AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if (sign == -1 && z > -AliTPCPoissonSolver::fgkZOffSet) { - z = -AliTPCPoissonSolver::fgkZOffSet; // Protect against discontinuity at CE - } - if ((sign == 1 && z < -1e-16) || (sign == -1 && z > -1e-16)) { // just a consistency check - Error("AliTPCSpaceCharge3DCalc::", "ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!"); - } - - if (z > -1e-16) { - fLookupInverseDistA->GetValue(r, phi, z, dR, dRPhi, dZ); - } else { - fLookupInverseDistC->GetValue(r, phi, -z, dR, dRPhi, dZ); - } - - dx[0] = fCorrectionFactor * dR; - dx[1] = fCorrectionFactor * dRPhi; - dx[2] = fCorrectionFactor * - dZ; // z distortion - (scaled with drift velocity dependency on the Ez field and the overall scaling factor) -} -/// Function for setting Potential Boundary Values and Charge distribution input TFormula -/// -/// \param vTestFunction -/// \param rhoTestFunction -/// -void AliTPCSpaceCharge3DCalc::SetPotentialBoundaryAndChargeFormula(TFormula* vTestFunction, TFormula* rhoTestFunction) -{ - /**** allocate memory for charge ***/ - // we allocate pointer to TMatrixD array to picture 3D (slices), this representation should be revised - // since it is easier for GPU implementation to run for 1D memory - const Float_t gridSizeR = (AliTPCPoissonSolver::fgkOFCRadius - AliTPCPoissonSolver::fgkIFCRadius) / (fNRRows - 1); - const Float_t gridSizeZ = AliTPCPoissonSolver::fgkTPCZ0 / (fNZColumns - 1); - const Float_t gridSizePhi = TMath::TwoPi() / fNPhiSlices; - - fFormulaPotentialV = vTestFunction; - fFormulaChargeRho = rhoTestFunction; - - // grid size for one side - TMatrixD* chargeA; - TMatrixD* chargeC; - Double_t radius0, z0, phi0, z0neg; - Int_t indexB = 0; - for (Int_t k = 0; k < fNPhiSlices; k++) { - chargeA = fMatrixChargeA[k]; - chargeC = fMatrixChargeC[k]; - - phi0 = k * gridSizePhi; - - /// Fill the non-boundary values - for (Int_t i = 0; i < fNRRows; i++) { - radius0 = AliTPCPoissonSolver::fgkIFCRadius + (i * gridSizeR); - for (Int_t j = 0; j < fNZColumns; j++) { - z0 = j * gridSizeZ; - z0neg = -z0; - - (*chargeA)(i, j) = -1.0 * rhoTestFunction->Eval(radius0, phi0, z0); - (*chargeC)(i, j) = -1.0 * rhoTestFunction->Eval(radius0, phi0, z0neg); - - /// TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // if ((i == 0) || (i == fNRRows - 1) || (j == 0) || (j == fNZColumns - 1)) { - // fListPotentialBoundaryA[indexB] = vTestFunction->Eval(radius0, phi0, z0); - // fListPotentialBoundaryC[indexB] = vTestFunction->Eval(radius0, phi0, z0neg); - // indexB++; - // } - - } // end j - } // end i - } // end phi - - fInterpolatorChargeA->SetValue(fMatrixChargeA); - fInterpolatorChargeA->InitCubicSpline(); - fInterpolatorChargeC->SetValue(fMatrixChargeC); - fInterpolatorChargeC->InitCubicSpline(); -} - -/// Set interpolation -void AliTPCSpaceCharge3DCalc::SetInterpolationOrder(Int_t order) -{ - fInterpolationOrder = order; - - fInterpolatorChargeA->SetOrder(fInterpolationOrder); - fInterpolatorChargeC->SetOrder(fInterpolationOrder); - fInterpolatorPotentialA->SetOrder(fInterpolationOrder); - fInterpolatorPotentialC->SetOrder(fInterpolationOrder); - fInterpolatorInverseChargeA->SetOrder(fInterpolationOrder); - fInterpolatorInverseChargeC->SetOrder(fInterpolationOrder); - - fLookupDistA->SetOrder(fInterpolationOrder); - - fLookupDistC->SetOrder(fInterpolationOrder); - - fLookupInverseDistA->SetOrder(fInterpolationOrder); - - fLookupInverseDistC->SetOrder(fInterpolationOrder); - - fLookupElectricFieldA->SetOrder(fInterpolationOrder); - fLookupElectricFieldC->SetOrder(fInterpolationOrder); - fLookupIntDistA->SetOrder(fInterpolationOrder); - fLookupIntDistC->SetOrder(fInterpolationOrder); - fLookupIntCorrA->SetOrder(fInterpolationOrder); - fLookupIntCorrC->SetOrder(fInterpolationOrder); - fLookupIntENoDriftA->SetOrder(fInterpolationOrder); - fLookupIntENoDriftC->SetOrder(fInterpolationOrder); - fLookupIntCorrIrregularA->SetOrder(fInterpolationOrder); - - fLookupIntCorrIrregularC->SetOrder(fInterpolationOrder); -} - -void AliTPCSpaceCharge3DCalc::SetDistortionLookupTables(TMatrixD** matrixIntDistDrA, TMatrixD** matrixIntDistDrphiA, TMatrixD** matrixIntDistDzA, TMatrixD** matrixIntDistDrC, TMatrixD** matrixIntDistDrphiC, TMatrixD** matrixIntDistDzC) -{ - fMatrixIntDistDrEzA = matrixIntDistDrA; - fMatrixIntDistDPhiREzA = matrixIntDistDrphiA; - fMatrixIntDistDzA = matrixIntDistDzA; - fLookupIntDistA->SetLookUpR(fMatrixIntDistDrEzA); - fLookupIntDistA->SetLookUpPhi(fMatrixIntDistDPhiREzA); - fLookupIntDistA->SetLookUpZ(fMatrixIntDistDzA); - fLookupIntDistA->CopyFromMatricesToInterpolator(); - - fMatrixIntDistDrEzC = matrixIntDistDrC; - fMatrixIntDistDPhiREzC = matrixIntDistDrphiC; - fMatrixIntDistDzC = matrixIntDistDzC; - fLookupIntDistC->SetLookUpR(fMatrixIntDistDrEzC); - fLookupIntDistC->SetLookUpPhi(fMatrixIntDistDPhiREzC); - fLookupIntDistC->SetLookUpZ(fMatrixIntDistDzC); - fLookupIntDistC->CopyFromMatricesToInterpolator(); - - fInitLookUp = kTRUE; -} \ No newline at end of file diff --git a/GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.h b/GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.h deleted file mode 100644 index bf686deff2b0f..0000000000000 --- a/GPU/TPCSpaceChargeBase/AliTPCSpaceCharge3DCalc.h +++ /dev/null @@ -1,454 +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. - -/// \file AliTPCSpaceCharge3DCalc.h -/// \brief This class provides distortion and correction map calculation with integration following electron drift -/// TODO: validate distortion z by comparing with exisiting classes -/// -/// \author Rifki Sadikin <rifki.sadikin@cern.ch>, Indonesian Institute of Sciences -/// \date Nov 20, 2017 - -#ifndef ALI_TPC_SPACECHARGE3D_CALC_H -#define ALI_TPC_SPACECHARGE3D_CALC_H - -#include "TF1.h" -#include "TF2.h" -#include "TH3F.h" -#include "TMatrixD.h" - -#include "AliTPCPoissonSolver.h" -#include "AliTPCLookUpTable3DInterpolatorD.h" -#include "AliTPC3DCylindricalInterpolator.h" -#include "AliTPCLookUpTable3DInterpolatorIrregularD.h" -#include "AliTPC3DCylindricalInterpolatorIrregular.h" - -class TFormula; - -class AliTPCSpaceCharge3DCalc -{ - public: - AliTPCSpaceCharge3DCalc(); - AliTPCSpaceCharge3DCalc(Int_t nRRow, Int_t nZColumn, Int_t nPhiSlice); - AliTPCSpaceCharge3DCalc(Int_t nRRow, Int_t nZColumn, Int_t nPhiSlice, - Int_t interpolationOrder, Int_t irregularGridSize, Int_t rbfKernelType); - ~AliTPCSpaceCharge3DCalc(); - void InitSpaceCharge3DPoissonIntegralDz(Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, - Double_t stopConvergence); - - // outdated, to be removed after modifications in aliroot are pushed - void InitSpaceCharge3DPoissonIntegralDz( - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, Double_t stopConvergence, - TMatrixD** matricesErA, TMatrixD** matricesEphiA, TMatrixD** matricesEzA, - TMatrixD** matricesErC, TMatrixD** matricesEphiC, TMatrixD** matricesEzC, - TMatrixD** matricesDistDrDzA, TMatrixD** matricesDistDPhiRDzA, TMatrixD** matricesDistDzA, - TMatrixD** matricesCorrDrDzA, TMatrixD** matricesCorrDPhiRDzA, TMatrixD** matricesCorrDzA, - TMatrixD** matricesDistDrDzC, TMatrixD** matricesDistDPhiRDzC, TMatrixD** matricesDistDzC, - TMatrixD** matricesCorrDrDzC, TMatrixD** matricesCorrDPhiRDzC, TMatrixD** matricesCorrDzC, - TFormula* intErDzTestFunction, TFormula* intEPhiRDzTestFunction, TFormula* intDzTestFunction); - - void InitSpaceCharge3DPoissonIntegralDz( - Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, Double_t stopConvergence, - TFormula* intErDzTestFunction, TFormula* intEPhiRDzTestFunction, TFormula* intDzTestFunction); - - void - InitSpaceCharge3DPoisson(Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, Double_t stopConvergence); - void ForceInitSpaceCharge3DPoissonIntegralDz(Int_t nRRow, Int_t nZColumn, Int_t phiSlice, Int_t maxIteration, - Double_t stopConvergence); - void GetDistortionCyl(const Float_t x[], Short_t roc, Float_t dx[]) const; - void GetDistortionCylAC(const Float_t x[], Short_t roc, Float_t dx[]) const; - void GetCorrectionCyl(const Float_t x[], Short_t roc, Float_t dx[]) const; - void GetCorrectionCylAC(const Float_t x[], Short_t roc, Float_t dx[]) const; - void GetCorrectionCylACIrregular(const Float_t x[], Short_t roc, Float_t dx[]) const; - void GetCorrectionCylACIrregular(const Float_t x[], Short_t roc, Float_t dx[], const Int_t side) const; - void GetDistortion(const Float_t x[], Short_t roc, Float_t dx[]) const; - - void GetCorrection(const Float_t x[], Short_t roc, Float_t dx[]) const; - void GetCorrection(const Float_t x[], Short_t roc, Float_t dx[], const Int_t side) const; - - Double_t GetChargeCylAC(const Float_t x[], Short_t roc) const; - Double_t GetPotentialCylAC(const Float_t x[], Short_t roc) const; - - Double_t GetInverseChargeCylAC(const Float_t x[], Short_t roc) const; - - void SetCorrectionType(Int_t correctionType) { fCorrectionType = correctionType; } - - enum { - kNumSector = 18 - }; - - enum CorrectionType { - kRegularInterpolator = 0, ///< use interpolation with regular interpolator for correction look up table - kIrregularInterpolator = 1, ///< use irregular interpolator for correction look up table - }; - - enum IntegrationStrategy { - kNaive = 0, ///< use interpolation with regular interpolator for correction look up table - kOpt = 1, ///< use irregular interpolator for correction look up table - }; - void SetInputSpaceCharge(TH3* hisSpaceCharge3D, Double_t norm); - void SetInputSpaceCharge(TH3* hisSpaceCharge3D) { SetInputSpaceCharge(hisSpaceCharge3D, 1); } - void SetInputSpaceCharge(TH3* hisSpaceCharge3D, Double_t norm, Int_t side); - void SetInputSpaceCharge(TH3* hisSpaceCharge3D, Int_t side) { SetInputSpaceCharge(hisSpaceCharge3D, 1, side); } - - void SetInputSpaceChargeA(TMatrixD** matricesLookUpCharge) - { - fInterpolatorChargeA->SetValue(matricesLookUpCharge); - fInterpolatorChargeA->InitCubicSpline(); - } - - void SetInputSpaceChargeC(TMatrixD** matricesLookUpCharge) - { - fInterpolatorChargeC->SetValue(matricesLookUpCharge); - fInterpolatorChargeC->InitCubicSpline(); - } - - void SetNRRows(Int_t nRRow) { fNRRows = nRRow; } - - void SetNPhiSlices(Int_t nPhiSlice) { fNPhiSlices = nPhiSlice; } - - void SetNZColumns(Int_t nZColumn) { fNZColumns = nZColumn; } - - Int_t GetNRRows() { return fNRRows; } - - Int_t GetNPhiSlices() { return fNPhiSlices; } - - Int_t GetNZColumns() { return fNZColumns; } - - void SetPoissonSolver(AliTPCPoissonSolver* poissonSolver) - { - if (fPoissonSolver != nullptr) { - delete fPoissonSolver; - } - fPoissonSolver = poissonSolver; - } - - AliTPCPoissonSolver* GetPoissonSolver() { return fPoissonSolver; } - - void SetInterpolationOrder(Int_t order); - - Int_t GetInterpolationOrder() { return fInterpolationOrder; } - - void SetOmegaTauT1T2(Float_t omegaTau, Float_t t1, Float_t t2) - { - const Double_t wt0 = t2 * omegaTau; - fC0 = 1. / (1. + wt0 * wt0); - const Double_t wt1 = t1 * omegaTau; - fC1 = wt1 / (1. + wt1 * wt1); - }; - - void SetC0C1(Float_t c0, Float_t c1) - { - fC0 = c0; - fC1 = c1; - } - - Float_t GetC0() const { return fC0; } - - Float_t GetC1() const { return fC1; } - - void SetCorrectionFactor(Float_t correctionFactor) { fCorrectionFactor = correctionFactor; } - - Float_t GetCorrectionFactor() const { return fCorrectionFactor; } - - void InverseDistortionMaps(TMatrixD** matricesCharge, TMatrixD** matricesEr, TMatrixD** matricesEPhi, - TMatrixD** matricesEz, TMatrixD** matricesInvLocalIntErDz, - TMatrixD**, TMatrixD** matricesInvLocalEz, - TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, const Int_t nStep, - const Bool_t useCylAC, Int_t stepR, Int_t stepZ, Int_t stepPhi, Int_t interpType); - - void InverseDistortionMapsNoDrift(TMatrixD** matricesCharge, TMatrixD** matricesEr, TMatrixD** matricesEPhi, - TMatrixD** matricesEz, TMatrixD** matricesInvLocalIntErDz, - TMatrixD** matricesInvLocalIntEPhiDz, TMatrixD** matricesInvLocalEz, - TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, - TMatrixD** matricesDistDz, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice); - - void GetCorrectionCylNoDrift(const Float_t x[], const Short_t roc, Float_t dx[]); - - void GetDistortionCylNoDrift(const Float_t x[], Short_t roc, Float_t dx[]); - - void InverseGlobalToLocalDistortionNoDrift(TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, - TMatrixD** matricesDistDz, Double_t* rList, Double_t* zList, - Double_t* phiList, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice); - - void GetChargeDensity(TMatrixD** matricesChargeA, TMatrixD** matricesChargeC, const TH3* spaceChargeHistogram3D, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice); - - void GetInverseLocalDistortionCyl(const Float_t x[], Short_t roc, Float_t dx[]); - - void GetLocalDistortionCyl(const Float_t x[], Short_t roc, Float_t dx[]); - - void GetLocalCorrectionCyl(const Float_t x[], Short_t roc, Float_t dx[]); - - void SetIrregularGridSize(Int_t size) { fIrregularGridSize = size; } - - Int_t GetIrregularGridSize() { return fIrregularGridSize; } - - Int_t GetRBFKernelType() { return fRBFKernelType; } - - void SetPotentialBoundaryAndChargeFormula(TFormula* vTestFunction, TFormula* rhoTestFunction); - TFormula* GetPotentialVFormula() const { return fFormulaPotentialV; } - TFormula* GetChargeRhoFormula() const { return fFormulaChargeRho; } - - void SetBoundaryIFCA(TF1* f1) { fFormulaBoundaryIFCA = f1; } - - void SetBoundaryIFCC(TF1* f1) { fFormulaBoundaryIFCC = f1; } - - void SetBoundaryOFCA(TF1* f1) { fFormulaBoundaryOFCA = f1; } - - void SetBoundaryOFCC(TF1* f1) { fFormulaBoundaryOFCC = f1; } - - void SetBoundaryROCA(TF1* f1) { fFormulaBoundaryROCA = f1; } - - void SetBoundaryROCC(TF1* f1) { fFormulaBoundaryROCC = f1; } - - void SetBoundaryCE(TF1* f1) { fFormulaBoundaryCE = f1; } - - void SetElectricFieldFormula(TFormula* formulaEr, TFormula* formulaEPhi, TFormula* formulaEz) - { - fFormulaEr = formulaEr; - fFormulaEPhi = formulaEPhi; - fFormulaEz = formulaEz; - } - TFormula* GetErFormula() const { return fFormulaEr; } - TFormula* GetEPhiFormula() const { return fFormulaEPhi; } - TFormula* GetEzFormula() const { return fFormulaEz; } - - Float_t GetSpaceChargeDensity(Float_t r, Float_t phi, Float_t z); - Float_t GetPotential(Float_t r, Float_t phi, Float_t z); - void GetElectricFieldCyl(const Float_t x[], Short_t roc, Double_t dx[]); - struct Profile { - Double_t poissonSolverTime; - Double_t electricFieldTime; - Double_t localDistortionTime; - Double_t globalDistortionTime; - Double_t interpolationInitTime; - Int_t iteration; - }; - - Profile GetProfile() { return myProfile; } - void SetIntegrationStrategy(Int_t integrationStrategy) { fIntegrationStrategy = integrationStrategy; } - - void SetDistortionLookupTables(TMatrixD** matrixIntDistDrA, TMatrixD** matrixIntDistDrphiA, TMatrixD** matrixIntDistDzA, TMatrixD** matrixIntDistDrC, TMatrixD** matrixIntDistDrphiC, TMatrixD** matrixIntDistDzC); - - private: - Profile myProfile; //!<! - Int_t fNRRows = 129; ///< the maximum on row-slices so far ~ 2cm slicing - Int_t fNPhiSlices = 180; ///< the maximum of phi-slices so far = (8 per sector) - Int_t fNZColumns = 129; ///< the maximum on column-slices so ~ 2cm slicing - Float_t fC0 = 0.f; ///< coefficient C0 (compare Jim Thomas's notes for definitions) - Float_t fC1 = 0.f; ///< coefficient C1 (compare Jim Thomas's notes for definitions) - Float_t fCorrectionFactor = 1.f; ///< Space Charge Correction factor in comparison to initialized - - Bool_t fInitLookUp = kFALSE; ///< flag to check if the Look Up table was created - Double_t* fListR; //[fNRRows] list of r-coordinate of grids - Double_t* fListPhi; //[fNPhiSlices] list of \f$ \phi\f$ -coordinate of grids - Double_t* fListZ; //[fNZColumns] - Double_t* fListZA; //[fNZColumns] list of z-coordinate of grids - Double_t* fListZC; //[fNZColumns] list of z-coordinate of grids - // / TODO: fListPotentialBoundary arrays are never used in the code. Remove? - // Double_t* fListPotentialBoundaryA; //[(fNRRows + fNZColumns) * 2 * fNPhiSlices] - // Double_t* fListPotentialBoundaryC; //[(fNRRows + fNZColumns) * 2 * fNPhiSlices] - - Int_t fCorrectionType = 1; ///< use regular or irregular grid method - Int_t fInterpolationOrder = 5; ///< Order of interpolation (1-> tri linear, 2->Lagrange interpolation order 2, 3> cubic spline) - Int_t fIrregularGridSize = 3; ///< Size of irregular grid cubes for interpolation (min 3) - Int_t fRBFKernelType = 0; ///< RBF kernel type - Int_t fIntegrationStrategy = 0; ///< Strategy for integration - - TMatrixD** fMatrixIntDistDrEzA; //!<! Matrices for storing Global distortion \f$ R \f$ direction for Side A - TMatrixD** fMatrixIntDistDPhiREzA; //!<! Matrices for storing Global \f$ \phi R \f$ Distortion for Side A - TMatrixD** fMatrixIntDistDzA; //!<! Matrices for storing Global \f$ z \f$ Distortion for Side A - - TMatrixD** fMatrixIntDistDrEzC; //!<! Matrices for storing Global \f$ R \f$ direction for Side C - TMatrixD** fMatrixIntDistDPhiREzC; //!<! Matrices for storing Global \f$ \phi R \f$ Distortion for Side C - TMatrixD** fMatrixIntDistDzC; //!<! Matrices for storing Global \f$ z \f$ Distortion for Side C - - TMatrixD** fMatrixErOverEzA; //!<! Matrices for storing Er Over Ez for intermediate value for side A - TMatrixD** fMatrixEPhiOverEzA; //!<! Matrices for storing EPhi Over Ez for intermediate value for side A - TMatrixD** fMatrixDeltaEzA; //!<! Matrices for storing delta Ez for intermediate value for side A - - TMatrixD** fMatrixErOverEzC; //!<! Matrices for storing Er Over Ez for intermediate value for Side C - TMatrixD** fMatrixEPhiOverEzC; //!<! Matrices for storing EPhi Over Ez for intermediate value for Side C - TMatrixD** fMatrixDeltaEzC; //!<! Matrices for storing delta Ez for intermediate value for side A - - TMatrixD** fMatrixIntCorrDrEzA; //!<! Matrices for storing Global \f$ R \f$ correction for side A - TMatrixD** fMatrixIntCorrDPhiREzA; //!<! Matrices for storing Global \f$ \phi R \f$ correction for side A - TMatrixD** fMatrixIntCorrDzA; //!<! Matrices for storing Global \f$ X \f$ correction for side A - - TMatrixD** fMatrixIntCorrDrEzC; //!<! Matrices for storing Global \f$ R \f$ correction for side C - TMatrixD** fMatrixIntCorrDPhiREzC; //!<! Matrices for storing Global \f$ \phi R \f$ correction for side C - TMatrixD** fMatrixIntCorrDzC; //!<! Matrices for storing Global \f$ X \f$ correction for side C - - TMatrixD** fMatrixIntCorrDrEzIrregularA; //!<! Matrices for storing global \f$ R \f$ correction irregular type for side A - TMatrixD** fMatrixIntCorrDPhiREzIrregularA; //!<! Matrices for storing Global \f$ \phi R \f$ correction irregular type for side A - TMatrixD** fMatrixIntCorrDzIrregularA; //!<! Matrices for storing Global \f$ z \f$ correction irregular type for side A - - TMatrixD** fMatrixRListIrregularA; //!<! Matrices for storing distorted \f$ R \f$ side A - TMatrixD** fMatrixPhiListIrregularA; //!<! Matrices for storing distorted \f$ \phi \f$ side A - TMatrixD** fMatrixZListIrregularA; //!<! Matrices for storing distorted \f$ z \f$ side A - - TMatrixD** fMatrixIntCorrDrEzIrregularC; //!<! Matrices for storing Global \f$ R \f$ correction irregular type for side C - TMatrixD** fMatrixIntCorrDPhiREzIrregularC; //!<! Matrices for storing Global \f$ \phi R \f$ correction irregular type for side C - TMatrixD** fMatrixIntCorrDzIrregularC; //!<! Matrices for storing Global \f$ z \f$ correction irregular type for side C - - TMatrixD** fMatrixRListIrregularC; //!<! Matrices for storing distorted \f$ R \f$ side C - TMatrixD** fMatrixPhiListIrregularC; //!<! Matrices for storing distorted \f$ \phi \f$ side C - TMatrixD** fMatrixZListIrregularC; //!<! Matrices for storing distorted \f$ z \f$ side C - - // look up for charge densities - TMatrixD** fMatrixChargeA; //!<! Matrices for storing input charge densities side A - TMatrixD** fMatrixChargeC; //!<! Matrices for storing input charge densities side C - TMatrixD** fMatrixChargeInverseA; //!<! Matrices for storing charge densities from backward algorithm side A - TMatrixD** fMatrixChargeInverseC; //!<! Matrices for storing charge densities from backward algorithm side C - - TMatrixD** fMatrixPotentialA; //!<! Matrices for storing potential side A - TMatrixD** fMatrixPotentialC; //!<! Matrices for storing potential side C - - AliTPC3DCylindricalInterpolator* fInterpolatorChargeA = nullptr; //!<! interpolator for charge densities side A - AliTPC3DCylindricalInterpolator* fInterpolatorChargeC = nullptr; //!<! interpolator for charge densities side C - AliTPC3DCylindricalInterpolator* fInterpolatorPotentialA = nullptr; //!<! interpolator for charge densities side A - AliTPC3DCylindricalInterpolator* fInterpolatorPotentialC = nullptr; //!<! interpolator for charge densities side C - AliTPC3DCylindricalInterpolator* fInterpolatorInverseChargeA = nullptr; //!<! interpolator for inverse charge densities side A - AliTPC3DCylindricalInterpolator* fInterpolatorInverseChargeC = nullptr; //!<! interpolator for inverse charge densities side C - - AliTPCLookUpTable3DInterpolatorD* fLookupIntDistA = nullptr; //-> look-up table for global distortion side A - AliTPCLookUpTable3DInterpolatorD* fLookupIntCorrA = nullptr; //-> look-up table for global correction side A - AliTPCLookUpTable3DInterpolatorD* fLookupIntDistC = nullptr; //-> look-up table for global distortion side C - AliTPCLookUpTable3DInterpolatorD* fLookupIntCorrC = nullptr; //-> look-up table for global correction side C - AliTPCLookUpTable3DInterpolatorIrregularD* fLookupIntCorrIrregularA = nullptr; //!<! look-up table for global correction side A (method irregular) - AliTPCLookUpTable3DInterpolatorIrregularD* fLookupIntCorrIrregularC = nullptr; //!<! look-up table for global correction side C (method irregular) - AliTPCLookUpTable3DInterpolatorD* fLookupIntENoDriftA = nullptr; //!<! look-up table for no drift integration side A - AliTPCLookUpTable3DInterpolatorD* fLookupIntENoDriftC = nullptr; //!<! look-up table for no drift integration side C - AliTPCLookUpTable3DInterpolatorD* fLookupDistA = nullptr; //!<! look-up table for local distortion side A - AliTPCLookUpTable3DInterpolatorD* fLookupDistC = nullptr; //!<! look-up table for local distortion side C - AliTPCLookUpTable3DInterpolatorD* fLookupCorrA = nullptr; //!<! look-up table for local correction side A - AliTPCLookUpTable3DInterpolatorD* fLookupCorrC = nullptr; //!<! look-up table for local correction side C - AliTPCLookUpTable3DInterpolatorD* fLookupInverseDistA = nullptr; //!<! look-up table for local distortion (from inverse) side A - AliTPCLookUpTable3DInterpolatorD* fLookupInverseDistC = nullptr; //!<! look-up table for local distortion (from inverse) side C - - AliTPCLookUpTable3DInterpolatorD* fLookupElectricFieldA = nullptr; //!<! look-up table for electric field side A - AliTPCLookUpTable3DInterpolatorD* fLookupElectricFieldC = nullptr; //!<! look-up table for electric field side C - - TH3* fHistogram3DSpaceCharge = nullptr; //!<! Histogram with the input space charge histogram - used as an optional input - TH3* fHistogram3DSpaceChargeA = nullptr; //!<! Histogram with the input space charge histogram - used as an optional input side A - TH3* fHistogram3DSpaceChargeC = nullptr; //!<! Histogram with the input space charge histogram - used as an optional input side C - TF1* fFormulaBoundaryIFCA = nullptr; //!<! function define boundary values for IFC side A V(z) assuming symmetry in phi and r. - TF1* fFormulaBoundaryIFCC = nullptr; //!<! function define boundary values for IFC side C V(z) assuming symmetry in phi and r. - TF1* fFormulaBoundaryOFCA = nullptr; //!<! function define boundary values for OFC side A V(z) assuming symmetry in phi and r. - TF1* fFormulaBoundaryOFCC = nullptr; //!<! function define boundary values for IFC side C V(z) assuming symmetry in phi and r. - TF1* fFormulaBoundaryROCA = nullptr; //!<! function define boundary values for ROC side A V(r) assuming symmetry in phi and z. - TF1* fFormulaBoundaryROCC = nullptr; //!<! function define boundary values for ROC side V V(t) assuming symmetry in phi and z. - TF1* fFormulaBoundaryCE = nullptr; //!<! function define boundary values for CE V(z) assuming symmetry in phi and z. - - TFormula* fFormulaPotentialV = nullptr; //!<! potential V(r,rho,z) function - TFormula* fFormulaChargeRho = nullptr; //!<! charge density Rho(r,rho,z) function - - // analytic formula for E - TFormula* fFormulaEPhi = nullptr; //!<! ePhi EPhi(r,rho,z) electric field (phi) function - TFormula* fFormulaEr = nullptr; //!<! er Er(r,rho,z) electric field (r) function - TFormula* fFormulaEz = nullptr; //!<! ez Ez(r,rho,z) electric field (z) function - - AliTPCPoissonSolver* fPoissonSolver = nullptr; //!<! Pointer to a poisson solver - - void ElectricField(TMatrixD** matricesV, TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlices, const Float_t gridSizeR, - const Float_t gridSizePhi, const Float_t gridSizeZ, const Int_t symmetry, - const Float_t innerRadius); - - void - LocalDistCorrDz(TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, TMatrixD** matricesDistDrDz, - TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, TMatrixD** matricesCorrDrDz, - TMatrixD** matricesCorrDPhiRDz, TMatrixD** matricesCorrDz, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, const Float_t gridSizeZ, const Double_t ezField); - void - LocalDistCorrDz(TFormula* intErDzFunction, TFormula* intEPhiRDzFunction, TFormula* intDzFunction, TFormula* ezFunction, - Double_t* rList, Double_t* phiList, Double_t* zList, TMatrixD** matricesDistDrDz, - TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, TMatrixD** matricesCorrDrDz, - TMatrixD** matricesCorrDPhiRDz, TMatrixD** matricesCorrDz, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, const Float_t gridSizeZ, const Double_t ezField); - - void IntegrateDistCorrDriftLineDz(AliTPCLookUpTable3DInterpolatorD* lookupLocalDist, TMatrixD** matricesGDistDrDz, - TMatrixD** matricesGDistDPhiRDz, TMatrixD** matricesGDistDz, - AliTPCLookUpTable3DInterpolatorD* lookupLocalCorr, TMatrixD** matricesGCorrDrDz, - TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, - TMatrixD** matricesGCorrIrregularDrDz, TMatrixD** matricesGCorrIrregularDPhiRDz, - TMatrixD** matricesGCorrIrregularDz, - TMatrixD** matricesRIrregular, TMatrixD** matricesPhiIrregular, - TMatrixD** matricesZIrregular, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Double_t* rList, const Double_t* phiList, const Double_t* zList); - - // outdated, to be removed once modifications in aliroot are pushed - void IntegrateDistCorrDriftLineDz( - TFormula* intErDzTestFunction, TFormula* intEPhiRDzTestFunction, TFormula* intDzTestFunction, - const Double_t ezField, TMatrixD** matricesGDistDrDz, TMatrixD** matricesGDistDPhiRDz, - TMatrixD** matricesGDistDz, - TMatrixD** matricesGCorrDrDz, TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, - TMatrixD** matricesGCorrIrregularDrDz, TMatrixD** matricesGCorrIrregularDPhiRDz, - TMatrixD** matricesGCorrIrregularDz, TMatrixD** matricesRIrregular, TMatrixD** matricesPhiIrregular, - TMatrixD** matricesZIrregular, const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Double_t* rList, - const Double_t* phiList, const Double_t* zList); - - void IntegrateDistCorrDriftLineDz( - TFormula* intErDzTestFunction, TFormula* intEPhiRDzTestFunction, TFormula* intDzTestFunction, TFormula* ezF, - const Double_t ezField, TMatrixD** matricesGDistDrDz, TMatrixD** matricesGDistDPhiRDz, - TMatrixD** matricesGDistDz, - TMatrixD** matricesGCorrDrDz, TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, - TMatrixD** matricesGCorrIrregularDrDz, TMatrixD** matricesGCorrIrregularDPhiRDz, - TMatrixD** matricesGCorrIrregularDz, TMatrixD** matricesRIrregular, TMatrixD** matricesPhiIrregular, - TMatrixD** matricesZIrregular, const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Double_t* rList, - const Double_t* phiList, const Double_t* zList); - - void IntegrateDistCorrDriftLineDzWithLookUp(AliTPCLookUpTable3DInterpolatorD* lookupLocalDist, TMatrixD** matricesGDistDrDz, TMatrixD** matricesGDistDPhiRDz, TMatrixD** matricesGDistDz, AliTPCLookUpTable3DInterpolatorD* lookupLocalCorr, TMatrixD** matricesGCorrDrDz, TMatrixD** matricesGCorrDPhiRDz, TMatrixD** matricesGCorrDz, const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, Double_t* rList, Double_t* phiList, Double_t* zList); - - void FillLookUpTable(AliTPCLookUpTable3DInterpolatorD* lookupGlobal, TMatrixD** lookupRDz, TMatrixD** lookupPhiRDz, - TMatrixD** lookupDz, const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice, - const Double_t* rList, const Double_t* phiList, const Double_t* zList); - - Double_t InterpolatePhi(const TH3* h3, const Double_t phi, const Double_t r, const Double_t z); - - void InverseGlobalToLocalDistortionGlobalInvTable(TMatrixD** matricesDistDrDz, TMatrixD** matricesDistDPhiRDz, - TMatrixD** matricesDistDz, Double_t* rList, Double_t* zList, - Double_t* phiList, const Int_t nRRow, const Int_t nZColumn, - const Int_t phiSlice, const Int_t nStep, const Bool_t useCylAC, - Int_t stepR, Int_t stepZ, Int_t stepPhi, Int_t type); - - void InverseLocalDistortionToElectricField(TMatrixD** matricesEr, TMatrixD** matricesEPhi, TMatrixD** matricesEz, - TMatrixD** matricesInvLocalIntErDz, TMatrixD** matricesInvLocalIntEPhiDz, - TMatrixD** matricesInvLocalIntEz, TMatrixD** matricesDistDrDz, - TMatrixD** matricesDistDPhiRDz, TMatrixD** matricesDistDz, - Double_t* rList, Double_t* zList, Double_t* phiList, const Int_t nRRow, - const Int_t nZColumn, const Int_t phiSlice); - - void InverseElectricFieldToCharge(TMatrixD** matricesCharge, TMatrixD** matricesEr, TMatrixD** matricesEPhi, - TMatrixD** matricesEz, Double_t* rList, Double_t* zList, Double_t* phiList, - const Int_t nRRow, const Int_t nZColumn, const Int_t phiSlice); - - void CalculateEField(TMatrixD** matricesV, TMatrixD** matricesErOverEz, TMatrixD** matricesEPhiOverEz, - TMatrixD** matricesDeltaEz, const Int_t nRRow, const Int_t nZColumn, const Int_t nPhiSlice, - const Int_t symmetry, Bool_t rocDisplacement = kFALSE); - - void - IntegrateEz(TMatrixD** matricesExOverEz, TMatrixD** matricesEx, const Int_t nRRow, const Int_t nZColumn, - const Int_t nPhiSlice, const Double_t ezField); - - void InitAllocateMemory(); - - /// \cond CLASSIMP - ClassDefNV(AliTPCSpaceCharge3DCalc, 1); - /// \endcond -}; - -#endif diff --git a/GPU/TPCSpaceChargeBase/CMakeLists.txt b/GPU/TPCSpaceChargeBase/CMakeLists.txt deleted file mode 100644 index 3743bb73ff6d4..0000000000000 --- a/GPU/TPCSpaceChargeBase/CMakeLists.txt +++ /dev/null @@ -1,78 +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. - -set(MODULE TPCSpaceChargeBase) - -set(SRCS - AliTPC3DCylindricalInterpolator.cxx - AliTPC3DCylindricalInterpolatorIrregular.cxx - AliTPCLookUpTable3DInterpolatorD.cxx - AliTPCLookUpTable3DInterpolatorIrregularD.cxx - AliTPCPoissonSolver.cxx - AliTPCSpaceCharge3DCalc.cxx) -string(REPLACE ".cxx" ".h" HDRS_CINT "${SRCS}") - -if(${ALIGPU_BUILD_TYPE} STREQUAL "O2") - o2_add_library(TPCSpaceChargeBase - TARGETVARNAME targetName - PUBLIC_LINK_LIBRARIES ROOT::Matrix ROOT::Hist - PUBLIC_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR} - SOURCES ${SRCS}) - - o2_target_root_dictionary(TPCSpaceChargeBase - HEADERS ${HDRS_CINT} - LINKDEF TPCSpaceChargeBaseLinkDef.h) - - o2_add_test(SpaceChargeBase - SOURCES ctest/testTPCSpaceChargeBase.cxx - COMPONENT_NAME gpu - LABELS gpu - PUBLIC_LINK_LIBRARIES O2::TPCSpaceChargeBase) - - target_compile_definitions(${targetName} PRIVATE GPUCA_O2_LIB) - - install(FILES ${HDRS_CINT} DESTINATION include/GPU) -endif() - -if(${ALIGPU_BUILD_TYPE} STREQUAL "ALIROOT") - add_definitions(-DGPUCA_ALIROOT_LIB) - include_directories(SYSTEM ${ROOT_INCLUDE_DIR}) - include_directories(${AliRoot_SOURCE_DIR}/GPU/TPCSpaceChargeBase) - - # Generate the dictionary - get_directory_property(incdirs INCLUDE_DIRECTORIES) - generate_dictionary("Ali${MODULE}" "TPCSpaceChargeBaseLinkDef.h" - "${HDRS_CINT}" "${incdirs}") - - set(ROOT_DEPENDENCIES Core Hist MathCore Matrix Physics) - - # Generate the ROOT map Dependecies - set(LIBDEPS ${ROOT_DEPENDENCIES}) - generate_rootmap("Ali${MODULE}" "${LIBDEPS}" - "${CMAKE_CURRENT_SOURCE_DIR}/TPCSpaceChargeBaseLinkDef.h") - - # Add a library to the project using the specified source files - add_library_tested(Ali${MODULE} SHARED ${SRCS} G__Ali${MODULE}.cxx) - target_link_libraries(Ali${MODULE} ${LIBDEPS}) - - # Additional compilation flags - set_target_properties(Ali${MODULE} PROPERTIES COMPILE_FLAGS "") - - # System dependent: Modify the way the library is build - if(${CMAKE_SYSTEM} MATCHES Darwin) - set_target_properties(Ali${MODULE} - PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") - endif(${CMAKE_SYSTEM} MATCHES Darwin) - - # Installation - install(TARGETS Ali${MODULE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) - - install(FILES ${HDRS_CINT} DESTINATION include) -endif() diff --git a/GPU/TPCSpaceChargeBase/TPCSpaceChargeBaseLinkDef.h b/GPU/TPCSpaceChargeBase/TPCSpaceChargeBaseLinkDef.h deleted file mode 100644 index 1df5061c43b3b..0000000000000 --- a/GPU/TPCSpaceChargeBase/TPCSpaceChargeBaseLinkDef.h +++ /dev/null @@ -1,29 +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. - -/// \file TPCSpaceChargeBaseLinkDef.h -/// \author Ernst Hellbaer - -#if defined(__CINT__) || defined(__CLING__) - -#pragma link off all globals; -#pragma link off all classes; -#pragma link off all functions; - -#pragma link C++ class AliTPC3DCylindricalInterpolator + ; -#pragma link C++ class AliTPC3DCylindricalInterpolatorIrregular + ; -#pragma link C++ struct AliTPC3DCylindricalInterpolatorIrregular::KDTreeNode + ; -#pragma link C++ class AliTPCLookUpTable3DInterpolatorD + ; -#pragma link C++ class AliTPCLookUpTable3DInterpolatorIrregularD + ; -#pragma link C++ class AliTPCPoissonSolver + ; -#pragma link C++ struct AliTPCPoissonSolver::MGParameters + ; -#pragma link C++ class AliTPCSpaceCharge3DCalc + ; - -#endif diff --git a/GPU/TPCSpaceChargeBase/ctest/testTPCSpaceChargeBase.cxx b/GPU/TPCSpaceChargeBase/ctest/testTPCSpaceChargeBase.cxx deleted file mode 100644 index 8df9e76bfb543..0000000000000 --- a/GPU/TPCSpaceChargeBase/ctest/testTPCSpaceChargeBase.cxx +++ /dev/null @@ -1,26 +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. - -/// \file testTPCSpaceChargeBase.cxx -/// \author Ernst Hellbaer - -#define BOOST_TEST_MODULE Test TPC Space - Charge Base Class -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK - -#include <boost/test/unit_test.hpp> -#include "AliTPCSpaceCharge3DCalc.h" - -/// @brief Basic test if we can create the method class -BOOST_AUTO_TEST_CASE(TPCSpaceChargeBase_test1) -{ - auto spacecharge = new AliTPCSpaceCharge3DCalc; - delete spacecharge; -} diff --git a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx index f35c3b30856d4..23bf4da2201d6 100644 --- a/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TPCDigitizerSpec.cxx @@ -38,6 +38,7 @@ using namespace o2::framework; using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; using DigiGroupRef = o2::dataformats::RangeReference<int, int>; +using SC = o2::tpc::SpaceCharge<double, 129, 129, 180>; namespace o2 { @@ -89,29 +90,14 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer readSpaceCharge.push_back(substr); } if (readSpaceCharge[0].size() != 0) { // use pre-calculated space-charge object - std::unique_ptr<o2::tpc::SpaceCharge> spaceCharge; if (!gSystem->AccessPathName(readSpaceCharge[0].data())) { - auto fileSC = std::unique_ptr<TFile>(TFile::Open(readSpaceCharge[0].data())); - if (fileSC->FindKey(readSpaceCharge[1].data())) { - spaceCharge.reset((o2::tpc::SpaceCharge*)fileSC->Get(readSpaceCharge[1].data())); - } - } - if (spaceCharge.get() != nullptr) { - LOG(INFO) << "Using pre-calculated space-charge object: " << readSpaceCharge[1].data(); - mDigitizer.setUseSCDistortions(spaceCharge.release()); + TFile fileSC(readSpaceCharge[0].data(), "READ"); + mDigitizer.setUseSCDistortions(fileSC); } else { LOG(ERROR) << "Space-charge object or file not found!"; } } else { // create new space-charge object either with empty TPC or an initial space-charge density provided by histogram - o2::tpc::SpaceCharge::SCDistortionType distortionType = useDistortions == 2 ? o2::tpc::SpaceCharge::SCDistortionType::SCDistortionsConstant : o2::tpc::SpaceCharge::SCDistortionType::SCDistortionsRealistic; - auto gridSizeString = ic.options().get<std::string>("gridSize"); - std::vector<int> gridSize; - std::stringstream ss(gridSizeString); - while (ss.good()) { - std::string substr; - getline(ss, substr, ','); - gridSize.push_back(std::stoi(substr)); - } + SC::SCDistortionType distortionType = useDistortions == 2 ? SC::SCDistortionType::SCDistortionsConstant : SC::SCDistortionType::SCDistortionsRealistic; auto inputHistoString = ic.options().get<std::string>("initialSpaceChargeDensity"); std::vector<std::string> inputHisto; std::stringstream ssHisto(inputHistoString); @@ -130,9 +116,9 @@ class TPCDPLDigitizerTask : public BaseDPLDigitizer } if (hisSCDensity.get() != nullptr) { LOG(INFO) << "TPC: Providing initial space-charge density histogram: " << hisSCDensity->GetName(); - mDigitizer.setUseSCDistortions(distortionType, hisSCDensity.get(), gridSize[0], gridSize[1], gridSize[2]); + mDigitizer.setUseSCDistortions(distortionType, hisSCDensity.get()); } else { - if (distortionType == SpaceCharge::SCDistortionType::SCDistortionsConstant) { + if (distortionType == SC::SCDistortionType::SCDistortionsConstant) { LOG(ERROR) << "Input space-charge density histogram or file not found!"; } } @@ -368,7 +354,6 @@ o2::framework::DataProcessorSpec getTPCDigitizerSpec(int channel, bool writeGRP, outputs, AlgorithmSpec{adaptFromTask<TPCDPLDigitizerTask>()}, Options{{"distortionType", VariantType::Int, 0, {"Distortion type to be used. 0 = no distortions (default), 1 = realistic distortions (not implemented yet), 2 = constant distortions"}}, - {"gridSize", VariantType::String, "129,144,129", {"Comma separated list of number of bins in (r,phi,z) for distortion lookup tables (r and z can only be 2**N + 1, N=1,2,3,...)"}}, {"initialSpaceChargeDensity", VariantType::String, "", {"Path to root file containing TH3 with initial space-charge density and name of the TH3 (comma separated)"}}, {"readSpaceCharge", VariantType::String, "", {"Path to root file containing pre-calculated space-charge object and name of the object (comma separated)"}}, {"TPCtriggered", VariantType::Bool, false, {"Impose triggered RO mode (default: continuous)"}}}}; From b3482384939c630d2383e7c05be2a02d207954e6 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Thu, 3 Dec 2020 23:26:29 +0100 Subject: [PATCH 1531/1751] [EMCAL-630] Decrease verbosity of RCU trailer using log framework --- Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index 02edf76d04207..ae8620c5d2ca9 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -104,7 +104,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) o2::emcal::AltroDecoder decoder(rawreader); decoder.decode(); - std::cout << decoder.getRCUTrailer() << std::endl; + LOG(DEBUG) << decoder.getRCUTrailer(); o2::emcal::Mapper map = mMapper->getMappingForDDL(feeID); int iSM = feeID / 2; From 6c91a4e03c04c98126bd51c0667055e66aabbccd Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 3 Dec 2020 21:58:14 +0100 Subject: [PATCH 1532/1751] Fixes for 8 GPU full system test configuration --- prodtests/full-system-test/datadistribution.sh | 2 +- prodtests/full-system-test/dpl-workflow.sh | 2 +- prodtests/full-system-test/raw-reader.sh | 10 ++++++++-- prodtests/full-system-test/start_tmux.sh | 15 ++++++++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/prodtests/full-system-test/datadistribution.sh b/prodtests/full-system-test/datadistribution.sh index 77e0c939006b8..23e4c9be2c4b0 100755 --- a/prodtests/full-system-test/datadistribution.sh +++ b/prodtests/full-system-test/datadistribution.sh @@ -10,7 +10,7 @@ fi export DATADIST_SHM_DELAY=10 export TF_DIR=./raw/timeframe -export TFRATE=$(awk "BEGIN {printf \"%.6f\",1/$NTIMEFRAMES}") +export TFRATE=$(awk "BEGIN {printf \"%.6f\",1/$TFDELAY}") ARGS_ALL="--session default --severity $SEVERITY --shm-segment-size $SHMSIZE --no-cleanup" diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index c2319e857dd59..db01f96c0c12c 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -17,7 +17,7 @@ if [ $SHMTHROW == 0 ]; then fi if [ $EXTINPUT == 1 ]; then - CMD_X="B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA" + CMD_X="B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA;G:EMC/RAWDATA;H:PHS/RAWDATA" CMD_Y="name=readout-proxy,type=pull,method=connect,address=ipc://@stfb-to-dpl$1,transport=shmem,rateLogging=0" CMD_INPUT="o2-dpl-raw-proxy $ARGS_ALL --dataspec $CMD_X --channel-config $CMD_Y" else diff --git a/prodtests/full-system-test/raw-reader.sh b/prodtests/full-system-test/raw-reader.sh index eb3e6f7aba98f..cc17f5d607b95 100755 --- a/prodtests/full-system-test/raw-reader.sh +++ b/prodtests/full-system-test/raw-reader.sh @@ -8,6 +8,12 @@ fi MYDIR="$(dirname $(readlink -f $0))" source $MYDIR/setenv.sh -ARGS_ALL="--session default --severity $SEVERITY --shm-throw-bad-alloc 0 --shm-segment-size $SHMSIZE --no-cleanup" +ARGS_ALL="--session default --severity $SEVERITY --shm-throw-bad-alloc 0 --no-cleanup" +if [ $NUMAGPUIDS == 1 ]; then + TMPSIZE=$(expr $DDSHMSIZE \* 1024 \* 1024) + ARGS_ALL+=" --shm-segment-id 2 --shm-segment-size $TMPSIZE --shm-mlock-segment 1 --shm-zero-segment 1" +else + ARGS_ALL+=" --shm-segment-size $SHMSIZE" +fi -o2-raw-file-reader-workflow $ARGS_ALL --loop $NTIMEFRAMES --delay $TFDELAY --input-conf rawAll.cfg --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF;" --max-tf 0 --raw-channel-config "name=dpl-chan,type=push,method=bind,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0" +o2-raw-file-reader-workflow $ARGS_ALL --loop $NTIMEFRAMES --delay $TFDELAY --input-conf rawAll.cfg --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF;" --max-tf 0 --raw-channel-config "name=dpl-chan,type=push,method=bind,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0" --run diff --git a/prodtests/full-system-test/start_tmux.sh b/prodtests/full-system-test/start_tmux.sh index da0213621d3be..9d90513111f2a 100755 --- a/prodtests/full-system-test/start_tmux.sh +++ b/prodtests/full-system-test/start_tmux.sh @@ -12,21 +12,30 @@ source $MYDIR/setenv.sh export NGPUS=4 export GPUTYPE=HIP export SHMSIZE=$(( 128 << 30 )) +export DDSHMSIZE=$(( 64 << 10 )) +export GPUMEMSIZE=$(( 24 << 30 )) export NUMAGPUIDS=1 export EXTINPUT=1 export EPNPIPELINES=1 export SYNCMODE=1 export SHMTHROW=0 +export SEVERITY=error if [ $1 == "dd" ]; then export CMD=datadistribution.sh else export CMD=raw-reader.sh + export NTIMEFRAMES=1000000 +fi + +if [ ! -f matbud.root -a -f ctf_dictionary.root ]; then + echo matbud.root or ctf_dictionary.root missing + exit 1 fi rm -f /dev/shm/*fmq* tmux \ - new-session "NUMAID=0 numactl --membind 0 --cpunodebind 0 $MYDIR/dpl-workflow.sh" \; \ - split-window "NUMAID=1 numactl --membind 1 --cpunodebind 1 $MYDIR/dpl-workflow.sh" \; \ - split-window "sleep 30; numactl --cpunodebind 0 --interleave=all $MYDIR/$CMD" + new-session "NUMAID=0 numactl --membind 0 --cpunodebind 0 $MYDIR/dpl-workflow.sh; echo END; sleep 1000" \; \ + split-window "sleep 30; NUMAID=1 numactl --membind 1 --cpunodebind 1 $MYDIR/dpl-workflow.sh; echo END; sleep 1000" \; \ + split-window "sleep 60; numactl --interleave=all $MYDIR/$CMD; echo END; sleep 1000" From 34c827888b4109b511f03cb7f63b454cf9c7d88c Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Fri, 4 Dec 2020 09:31:21 +0100 Subject: [PATCH 1533/1751] reworking include directories (#4989) --- Analysis/Core/CMakeLists.txt | 22 +++++++------- .../AnalysisCompositeCut.h | 2 +- .../{Analysis => AnalysisCore}/AnalysisCut.h | 0 .../CorrelationContainer.h | 0 .../HFConfigurables.h | 0 .../{Analysis => AnalysisCore}/HistHelpers.h | 0 .../HistogramManager.h | 0 .../{Analysis => AnalysisCore}/JetFinder.h | 0 .../include/{Analysis => AnalysisCore}/MC.h | 0 .../{Analysis => AnalysisCore}/PairCuts.h | 0 .../{Analysis => AnalysisCore}/RecoDecay.h | 4 +-- .../TrackSelection.h | 0 .../TrackSelectionDefaults.h | 0 .../TriggerAliases.h | 0 .../{Analysis => AnalysisCore}/VarManager.h | 2 +- .../trackUtilities.h | 2 +- Analysis/Core/src/AnalysisCompositeCut.cxx | 2 +- Analysis/Core/src/AnalysisCut.cxx | 2 +- Analysis/Core/src/CorrelationContainer.cxx | 2 +- Analysis/Core/src/HFConfigurables.cxx | 2 +- Analysis/Core/src/HistogramManager.cxx | 2 +- Analysis/Core/src/JetFinder.cxx | 2 +- Analysis/Core/src/TrackSelection.cxx | 2 +- Analysis/Core/src/TriggerAliases.cxx | 2 +- Analysis/Core/src/VarManager.cxx | 2 +- Analysis/DataModel/CMakeLists.txt | 29 +++++-------------- .../CFDerived.h | 2 +- .../Centrality.h | 0 .../EventSelection.h | 2 +- .../HFCandidateSelectionTables.h | 0 .../HFSecondaryVertex.h | 4 +-- .../{Analysis => AnalysisDataModel}/Jet.h | 0 .../Multiplicity.h | 0 .../{ => AnalysisDataModel}/PID/BetheBloch.h | 2 +- .../PID}/DetectorResponse.h | 2 +- .../{ => AnalysisDataModel}/PID/PIDResponse.h | 0 .../{ => AnalysisDataModel}/PID/PIDTOF.h | 2 +- .../{ => AnalysisDataModel}/PID/PIDTPC.h | 2 +- .../PID}/ParamBase.h | 0 .../{ => AnalysisDataModel}/PID/TOFReso.h | 2 +- .../{ => AnalysisDataModel}/PID/TPCReso.h | 2 +- .../ReducedInfoTables.h | 6 ++-- .../StrangenessTables.h | 2 +- .../TrackSelectionTables.h | 0 Analysis/DataModel/src/ParamBase.cxx | 2 +- Analysis/DataModel/src/aodDataModelGraph.cxx | 14 ++++----- Analysis/DataModel/src/handleParamTOFReso.cxx | 2 +- .../src/handleParamTPCBetheBloch.cxx | 4 +-- .../Tasks/ALICE3/alice3-trackselection.cxx | 6 ++-- Analysis/Tasks/PWGCF/correlations.cxx | 10 +++---- Analysis/Tasks/PWGCF/correlationsFiltered.cxx | 10 +++---- Analysis/Tasks/PWGCF/correlationsMixed.cxx | 8 ++--- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 8 ++--- Analysis/Tasks/PWGCF/filterCF.cxx | 8 ++--- Analysis/Tasks/PWGDQ/CutsLibrary.h | 6 ++-- Analysis/Tasks/PWGDQ/HistogramsLibrary.h | 4 +-- Analysis/Tasks/PWGDQ/dileptonEE.cxx | 10 +++---- Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 10 +++---- Analysis/Tasks/PWGDQ/filterPP.cxx | 22 +++++++------- Analysis/Tasks/PWGDQ/tableMaker.cxx | 22 +++++++------- Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx | 22 +++++++------- Analysis/Tasks/PWGDQ/tableMaker_pp.cxx | 22 +++++++------- Analysis/Tasks/PWGDQ/tableReader.cxx | 10 +++---- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 4 +-- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 4 +-- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 4 +-- .../Tasks/PWGHF/HFLcCandidateSelector.cxx | 4 +-- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 8 ++--- Analysis/Tasks/PWGHF/qaTask.cxx | 2 +- Analysis/Tasks/PWGHF/taskD0.cxx | 4 +-- Analysis/Tasks/PWGHF/taskDPlus.cxx | 4 +-- Analysis/Tasks/PWGHF/taskLc.cxx | 4 +-- Analysis/Tasks/PWGJE/jetfinder.cxx | 4 +-- .../Tasks/PWGJE/jetfinderhadronrecoil.cxx | 4 +-- Analysis/Tasks/PWGJE/jetfinderhf.cxx | 8 ++--- Analysis/Tasks/PWGJE/jetsubstructure.cxx | 4 +-- Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx | 2 +- Analysis/Tasks/PWGLF/cascadeconsumer.cxx | 16 +++++----- Analysis/Tasks/PWGLF/cascadefinder.cxx | 18 ++++++------ Analysis/Tasks/PWGLF/cascadeproducer.cxx | 14 ++++----- Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx | 16 +++++----- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 18 ++++++------ Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 14 ++++----- Analysis/Tasks/PWGLF/mcspectraefficiency.cxx | 4 +-- Analysis/Tasks/PWGLF/raacharged.cxx | 10 +++---- Analysis/Tasks/PWGLF/spectraTOF.cxx | 4 +-- Analysis/Tasks/PWGLF/spectraTPC.cxx | 4 +-- Analysis/Tasks/PWGLF/trackchecks.cxx | 10 +++---- Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx | 6 ++-- Analysis/Tasks/PWGUD/upcAnalysis.cxx | 6 ++-- Analysis/Tasks/centralityQa.cxx | 4 +-- Analysis/Tasks/centralityTable.cxx | 4 +-- Analysis/Tasks/eventSelection.cxx | 4 +-- Analysis/Tasks/eventSelectionQa.cxx | 2 +- Analysis/Tasks/multiplicityQa.cxx | 4 +-- Analysis/Tasks/multiplicityTable.cxx | 4 +-- Analysis/Tasks/pidTOF.cxx | 4 +-- Analysis/Tasks/pidTPC.cxx | 4 +-- Analysis/Tasks/reducedEventAnalysis.cxx | 6 ++-- Analysis/Tasks/trackextension.cxx | 6 ++-- Analysis/Tasks/trackqa.cxx | 8 ++--- Analysis/Tasks/trackselection.cxx | 8 ++--- Analysis/Tutorials/src/histHelpersTest.cxx | 2 +- .../Tutorials/src/histogramTrackSelection.cxx | 4 +-- Analysis/Tutorials/src/jetAnalysis.cxx | 2 +- Analysis/Tutorials/src/mcHistograms.cxx | 2 +- 106 files changed, 280 insertions(+), 295 deletions(-) rename Analysis/Core/include/{Analysis => AnalysisCore}/AnalysisCompositeCut.h (97%) rename Analysis/Core/include/{Analysis => AnalysisCore}/AnalysisCut.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/CorrelationContainer.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/HFConfigurables.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/HistHelpers.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/HistogramManager.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/JetFinder.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/MC.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/PairCuts.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/RecoDecay.h (99%) rename Analysis/Core/include/{Analysis => AnalysisCore}/TrackSelection.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/TrackSelectionDefaults.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/TriggerAliases.h (100%) rename Analysis/Core/include/{Analysis => AnalysisCore}/VarManager.h (99%) rename Analysis/Core/include/{Analysis => AnalysisCore}/trackUtilities.h (99%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/CFDerived.h (97%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/Centrality.h (100%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/EventSelection.h (98%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/HFCandidateSelectionTables.h (100%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/HFSecondaryVertex.h (99%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/Jet.h (100%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/Multiplicity.h (100%) rename Analysis/DataModel/include/{ => AnalysisDataModel}/PID/BetheBloch.h (96%) rename Analysis/DataModel/include/{PIDBase => AnalysisDataModel/PID}/DetectorResponse.h (98%) rename Analysis/DataModel/include/{ => AnalysisDataModel}/PID/PIDResponse.h (100%) rename Analysis/DataModel/include/{ => AnalysisDataModel}/PID/PIDTOF.h (99%) rename Analysis/DataModel/include/{ => AnalysisDataModel}/PID/PIDTPC.h (97%) rename Analysis/DataModel/include/{PIDBase => AnalysisDataModel/PID}/ParamBase.h (100%) rename Analysis/DataModel/include/{ => AnalysisDataModel}/PID/TOFReso.h (97%) rename Analysis/DataModel/include/{ => AnalysisDataModel}/PID/TPCReso.h (96%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/ReducedInfoTables.h (98%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/StrangenessTables.h (99%) rename Analysis/DataModel/include/{Analysis => AnalysisDataModel}/TrackSelectionTables.h (100%) diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index f931540f2cb3e..b56c698e27264 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -20,16 +20,16 @@ o2_add_library(AnalysisCore PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisTools) o2_target_root_dictionary(AnalysisCore - HEADERS include/Analysis/CorrelationContainer.h - include/Analysis/TrackSelection.h - include/Analysis/TrackSelectionDefaults.h - include/Analysis/VarManager.h - include/Analysis/HistogramManager.h - include/Analysis/AnalysisCut.h - include/Analysis/AnalysisCompositeCut.h - include/Analysis/TriggerAliases.h - include/Analysis/MC.h - include/Analysis/HFConfigurables.h + HEADERS include/AnalysisCore/CorrelationContainer.h + include/AnalysisCore/TrackSelection.h + include/AnalysisCore/TrackSelectionDefaults.h + include/AnalysisCore/VarManager.h + include/AnalysisCore/HistogramManager.h + include/AnalysisCore/AnalysisCut.h + include/AnalysisCore/AnalysisCompositeCut.h + include/AnalysisCore/TriggerAliases.h + include/AnalysisCore/MC.h + include/AnalysisCore/HFConfigurables.h LINKDEF src/AnalysisCoreLinkDef.h) if(FastJet_FOUND) @@ -38,6 +38,6 @@ o2_add_library(AnalysisJets PUBLIC_LINK_LIBRARIES O2::AnalysisCore FastJet::FastJet FastJet::Contrib) o2_target_root_dictionary(AnalysisJets - HEADERS include/Analysis/JetFinder.h + HEADERS include/AnalysisCore/JetFinder.h LINKDEF src/AnalysisJetsLinkDef.h) endif() diff --git a/Analysis/Core/include/Analysis/AnalysisCompositeCut.h b/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h similarity index 97% rename from Analysis/Core/include/Analysis/AnalysisCompositeCut.h rename to Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h index d794179a394dc..96902e5fe9b72 100644 --- a/Analysis/Core/include/Analysis/AnalysisCompositeCut.h +++ b/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h @@ -16,7 +16,7 @@ #ifndef AnalysisCompositeCut_H #define AnalysisCompositeCut_H -#include "Analysis/AnalysisCut.h" +#include "AnalysisCore/AnalysisCut.h" #include <vector> //_________________________________________________________________________ diff --git a/Analysis/Core/include/Analysis/AnalysisCut.h b/Analysis/Core/include/AnalysisCore/AnalysisCut.h similarity index 100% rename from Analysis/Core/include/Analysis/AnalysisCut.h rename to Analysis/Core/include/AnalysisCore/AnalysisCut.h diff --git a/Analysis/Core/include/Analysis/CorrelationContainer.h b/Analysis/Core/include/AnalysisCore/CorrelationContainer.h similarity index 100% rename from Analysis/Core/include/Analysis/CorrelationContainer.h rename to Analysis/Core/include/AnalysisCore/CorrelationContainer.h diff --git a/Analysis/Core/include/Analysis/HFConfigurables.h b/Analysis/Core/include/AnalysisCore/HFConfigurables.h similarity index 100% rename from Analysis/Core/include/Analysis/HFConfigurables.h rename to Analysis/Core/include/AnalysisCore/HFConfigurables.h diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/AnalysisCore/HistHelpers.h similarity index 100% rename from Analysis/Core/include/Analysis/HistHelpers.h rename to Analysis/Core/include/AnalysisCore/HistHelpers.h diff --git a/Analysis/Core/include/Analysis/HistogramManager.h b/Analysis/Core/include/AnalysisCore/HistogramManager.h similarity index 100% rename from Analysis/Core/include/Analysis/HistogramManager.h rename to Analysis/Core/include/AnalysisCore/HistogramManager.h diff --git a/Analysis/Core/include/Analysis/JetFinder.h b/Analysis/Core/include/AnalysisCore/JetFinder.h similarity index 100% rename from Analysis/Core/include/Analysis/JetFinder.h rename to Analysis/Core/include/AnalysisCore/JetFinder.h diff --git a/Analysis/Core/include/Analysis/MC.h b/Analysis/Core/include/AnalysisCore/MC.h similarity index 100% rename from Analysis/Core/include/Analysis/MC.h rename to Analysis/Core/include/AnalysisCore/MC.h diff --git a/Analysis/Core/include/Analysis/PairCuts.h b/Analysis/Core/include/AnalysisCore/PairCuts.h similarity index 100% rename from Analysis/Core/include/Analysis/PairCuts.h rename to Analysis/Core/include/AnalysisCore/PairCuts.h diff --git a/Analysis/Core/include/Analysis/RecoDecay.h b/Analysis/Core/include/AnalysisCore/RecoDecay.h similarity index 99% rename from Analysis/Core/include/Analysis/RecoDecay.h rename to Analysis/Core/include/AnalysisCore/RecoDecay.h index d9a8827371d02..fb4997040c214 100644 --- a/Analysis/Core/include/Analysis/RecoDecay.h +++ b/Analysis/Core/include/AnalysisCore/RecoDecay.h @@ -649,8 +649,8 @@ class RecoDecay static int getMatchedMCRec(const T& particlesMC, const array<U, N>& arrDaughters, int PDGMother, array<int, N> arrPDGDaughters, bool acceptAntiParticles = false, int8_t* sign = nullptr, int depthMax = 1) { //Printf("MC Rec: Expected mother PDG: %d", PDGMother); - int8_t sgn = 0; // 1 if the expected mother is particle, -1 if antiparticle (w.r.t. PDGMother) - int indexMother = -1; // index of the mother particle + int8_t sgn = 0; // 1 if the expected mother is particle, -1 if antiparticle (w.r.t. PDGMother) + int indexMother = -1; // index of the mother particle std::vector<int> arrAllDaughtersIndex; // vector of indices of all daughters of the mother of the first provided daughter array<int, N> arrDaughtersIndex; // array of indices of provided daughters if (sign) { diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/AnalysisCore/TrackSelection.h similarity index 100% rename from Analysis/Core/include/Analysis/TrackSelection.h rename to Analysis/Core/include/AnalysisCore/TrackSelection.h diff --git a/Analysis/Core/include/Analysis/TrackSelectionDefaults.h b/Analysis/Core/include/AnalysisCore/TrackSelectionDefaults.h similarity index 100% rename from Analysis/Core/include/Analysis/TrackSelectionDefaults.h rename to Analysis/Core/include/AnalysisCore/TrackSelectionDefaults.h diff --git a/Analysis/Core/include/Analysis/TriggerAliases.h b/Analysis/Core/include/AnalysisCore/TriggerAliases.h similarity index 100% rename from Analysis/Core/include/Analysis/TriggerAliases.h rename to Analysis/Core/include/AnalysisCore/TriggerAliases.h diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/AnalysisCore/VarManager.h similarity index 99% rename from Analysis/Core/include/Analysis/VarManager.h rename to Analysis/Core/include/AnalysisCore/VarManager.h index 10681af192486..412d11d79f9f3 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/AnalysisCore/VarManager.h @@ -26,7 +26,7 @@ #include <cmath> #include "Framework/DataTypes.h" -#include "Analysis/TriggerAliases.h" +#include "AnalysisCore/TriggerAliases.h" // TODO: create an array holding these constants for all needed particles or check for a place where these are already defined static const float fgkElectronMass = 0.000511; // GeV diff --git a/Analysis/Core/include/Analysis/trackUtilities.h b/Analysis/Core/include/AnalysisCore/trackUtilities.h similarity index 99% rename from Analysis/Core/include/Analysis/trackUtilities.h rename to Analysis/Core/include/AnalysisCore/trackUtilities.h index 83d38ab54d47b..0017cb1d5cce9 100644 --- a/Analysis/Core/include/Analysis/trackUtilities.h +++ b/Analysis/Core/include/AnalysisCore/trackUtilities.h @@ -18,7 +18,7 @@ #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/Vertex.h" -#include "Analysis/RecoDecay.h" +#include "AnalysisCore/RecoDecay.h" /// Extracts track parameters from a track. template <typename T> diff --git a/Analysis/Core/src/AnalysisCompositeCut.cxx b/Analysis/Core/src/AnalysisCompositeCut.cxx index 9acd248e173af..fc05c54167884 100644 --- a/Analysis/Core/src/AnalysisCompositeCut.cxx +++ b/Analysis/Core/src/AnalysisCompositeCut.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Analysis/AnalysisCompositeCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" ClassImp(AnalysisCompositeCut) diff --git a/Analysis/Core/src/AnalysisCut.cxx b/Analysis/Core/src/AnalysisCut.cxx index 659b9e6c4c7dd..9a3a4475960c9 100644 --- a/Analysis/Core/src/AnalysisCut.cxx +++ b/Analysis/Core/src/AnalysisCut.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Analysis/AnalysisCut.h" +#include "AnalysisCore/AnalysisCut.h" #include <iostream> using std::cout; diff --git a/Analysis/Core/src/CorrelationContainer.cxx b/Analysis/Core/src/CorrelationContainer.cxx index 76940b51aa043..36fe789cba3e6 100644 --- a/Analysis/Core/src/CorrelationContainer.cxx +++ b/Analysis/Core/src/CorrelationContainer.cxx @@ -13,7 +13,7 @@ // // Author: Jan Fiete Grosse-Oetringhaus -#include "Analysis/CorrelationContainer.h" +#include "AnalysisCore/CorrelationContainer.h" #include "Framework/StepTHn.h" #include "Framework/Logger.h" #include "THnSparse.h" diff --git a/Analysis/Core/src/HFConfigurables.cxx b/Analysis/Core/src/HFConfigurables.cxx index fb283c8145718..f1d9351c26563 100644 --- a/Analysis/Core/src/HFConfigurables.cxx +++ b/Analysis/Core/src/HFConfigurables.cxx @@ -11,4 +11,4 @@ // HF Configurable Classes // // Authors: Nima Zardoshti -#include "Analysis/HFConfigurables.h" +#include "AnalysisCore/HFConfigurables.h" diff --git a/Analysis/Core/src/HistogramManager.cxx b/Analysis/Core/src/HistogramManager.cxx index 77e8a8797ad6a..731d12925761a 100644 --- a/Analysis/Core/src/HistogramManager.cxx +++ b/Analysis/Core/src/HistogramManager.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Analysis/HistogramManager.h" +#include "AnalysisCore/HistogramManager.h" #include <iostream> #include <fstream> diff --git a/Analysis/Core/src/JetFinder.cxx b/Analysis/Core/src/JetFinder.cxx index bb9304213b828..f232813d1861b 100644 --- a/Analysis/Core/src/JetFinder.cxx +++ b/Analysis/Core/src/JetFinder.cxx @@ -11,7 +11,7 @@ // jet finder task // // Author: Jochen Klein, Nima Zardoshti -#include "Analysis/JetFinder.h" +#include "AnalysisCore/JetFinder.h" #include "Framework/AnalysisTask.h" /// Sets the jet finding parameters diff --git a/Analysis/Core/src/TrackSelection.cxx b/Analysis/Core/src/TrackSelection.cxx index 5e7ff6fa41fd0..70128b43ed68c 100644 --- a/Analysis/Core/src/TrackSelection.cxx +++ b/Analysis/Core/src/TrackSelection.cxx @@ -12,7 +12,7 @@ // Class for track selection // -#include "Analysis/TrackSelection.h" +#include "AnalysisCore/TrackSelection.h" bool TrackSelection::FulfillsITSHitRequirements(uint8_t itsClusterMap) { diff --git a/Analysis/Core/src/TriggerAliases.cxx b/Analysis/Core/src/TriggerAliases.cxx index d5b69e9bc9a0a..8039cc3bef6d5 100644 --- a/Analysis/Core/src/TriggerAliases.cxx +++ b/Analysis/Core/src/TriggerAliases.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Analysis/TriggerAliases.h" +#include "AnalysisCore/TriggerAliases.h" void TriggerAliases::Print() { diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index 31e20f0e91104..f3706347c8ceb 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Analysis/VarManager.h" +#include "AnalysisCore/VarManager.h" #include <TMath.h> diff --git a/Analysis/DataModel/CMakeLists.txt b/Analysis/DataModel/CMakeLists.txt index bf3f50c8a30a6..9f77bbb2aa502 100644 --- a/Analysis/DataModel/CMakeLists.txt +++ b/Analysis/DataModel/CMakeLists.txt @@ -16,31 +16,16 @@ o2_add_library(AnalysisDataModel o2_target_root_dictionary(AnalysisDataModel - HEADERS include/PIDBase/ParamBase.h - include/PIDBase/DetectorResponse.h - include/PID/PIDTOF.h - include/PID/TOFReso.h - include/PID/PIDTPC.h - include/PID/BetheBloch.h - include/PID/TPCReso.h + HEADERS include/AnalysisDataModel/PID/ParamBase.h + include/AnalysisDataModel/PID/DetectorResponse.h + include/AnalysisDataModel/PID/PIDTOF.h + include/AnalysisDataModel/PID/TOFReso.h + include/AnalysisDataModel/PID/PIDTPC.h + include/AnalysisDataModel/PID/BetheBloch.h + include/AnalysisDataModel/PID/TPCReso.h LINKDEF src/AnalysisDataModelLinkDef.h ) -install(FILES - include/PIDBase/ParamBase.h - include/PIDBase/DetectorResponse.h - DESTINATION - include/PIDBase) - -install(FILES - include/PID/PIDTOF.h - include/PID/TOFReso.h - include/PID/PIDTPC.h - include/PID/BetheBloch.h - include/PID/TPCReso.h - DESTINATION - include/PID) - o2_add_executable(aod-data-model-graph SOURCES src/aodDataModelGraph.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore diff --git a/Analysis/DataModel/include/Analysis/CFDerived.h b/Analysis/DataModel/include/AnalysisDataModel/CFDerived.h similarity index 97% rename from Analysis/DataModel/include/Analysis/CFDerived.h rename to Analysis/DataModel/include/AnalysisDataModel/CFDerived.h index 78fdcdfee505c..71c1f4905b7d3 100644 --- a/Analysis/DataModel/include/Analysis/CFDerived.h +++ b/Analysis/DataModel/include/AnalysisDataModel/CFDerived.h @@ -12,7 +12,7 @@ #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/Centrality.h" +#include "AnalysisDataModel/Centrality.h" namespace o2::aod { diff --git a/Analysis/DataModel/include/Analysis/Centrality.h b/Analysis/DataModel/include/AnalysisDataModel/Centrality.h similarity index 100% rename from Analysis/DataModel/include/Analysis/Centrality.h rename to Analysis/DataModel/include/AnalysisDataModel/Centrality.h diff --git a/Analysis/DataModel/include/Analysis/EventSelection.h b/Analysis/DataModel/include/AnalysisDataModel/EventSelection.h similarity index 98% rename from Analysis/DataModel/include/Analysis/EventSelection.h rename to Analysis/DataModel/include/AnalysisDataModel/EventSelection.h index fee80c47b7094..ffe5af699d1dd 100644 --- a/Analysis/DataModel/include/Analysis/EventSelection.h +++ b/Analysis/DataModel/include/AnalysisDataModel/EventSelection.h @@ -11,7 +11,7 @@ #define O2_ANALYSIS_EVENTSELECTION_H_ #include "Framework/AnalysisDataModel.h" -#include "Analysis/TriggerAliases.h" +#include "AnalysisCore/TriggerAliases.h" namespace o2::aod { diff --git a/Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h b/Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h similarity index 100% rename from Analysis/DataModel/include/Analysis/HFCandidateSelectionTables.h rename to Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h diff --git a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h b/Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h similarity index 99% rename from Analysis/DataModel/include/Analysis/HFSecondaryVertex.h rename to Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h index d3a2dfefe521a..9c452f4c25c28 100644 --- a/Analysis/DataModel/include/Analysis/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h @@ -18,8 +18,8 @@ #define O2_ANALYSIS_HFSECONDARYVERTEX_H_ #include "Framework/AnalysisDataModel.h" -#include "Analysis/RecoDecay.h" -#include "PID/PIDResponse.h" +#include "AnalysisCore/RecoDecay.h" +#include "AnalysisDataModel/PID/PIDResponse.h" namespace o2::aod { diff --git a/Analysis/DataModel/include/Analysis/Jet.h b/Analysis/DataModel/include/AnalysisDataModel/Jet.h similarity index 100% rename from Analysis/DataModel/include/Analysis/Jet.h rename to Analysis/DataModel/include/AnalysisDataModel/Jet.h diff --git a/Analysis/DataModel/include/Analysis/Multiplicity.h b/Analysis/DataModel/include/AnalysisDataModel/Multiplicity.h similarity index 100% rename from Analysis/DataModel/include/Analysis/Multiplicity.h rename to Analysis/DataModel/include/AnalysisDataModel/Multiplicity.h diff --git a/Analysis/DataModel/include/PID/BetheBloch.h b/Analysis/DataModel/include/AnalysisDataModel/PID/BetheBloch.h similarity index 96% rename from Analysis/DataModel/include/PID/BetheBloch.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/BetheBloch.h index 63f670e2bd265..37affbc22e91f 100644 --- a/Analysis/DataModel/include/PID/BetheBloch.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/BetheBloch.h @@ -19,7 +19,7 @@ #define O2_ANALYSIS_PID_BETHEBLOCH_H_ #include "TPCSimulation/Detector.h" -#include "PIDBase/ParamBase.h" +#include "AnalysisDataModel/PID/ParamBase.h" namespace o2::pid::tpc { diff --git a/Analysis/DataModel/include/PIDBase/DetectorResponse.h b/Analysis/DataModel/include/AnalysisDataModel/PID/DetectorResponse.h similarity index 98% rename from Analysis/DataModel/include/PIDBase/DetectorResponse.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/DetectorResponse.h index b5f3fb3a55a00..8e4bd405cd164 100644 --- a/Analysis/DataModel/include/PIDBase/DetectorResponse.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/DetectorResponse.h @@ -29,7 +29,7 @@ // O2 includes #include "ReconstructionDataFormats/PID.h" -#include "PIDBase/ParamBase.h" +#include "AnalysisDataModel/PID/ParamBase.h" namespace o2::pid { diff --git a/Analysis/DataModel/include/PID/PIDResponse.h b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h similarity index 100% rename from Analysis/DataModel/include/PID/PIDResponse.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h diff --git a/Analysis/DataModel/include/PID/PIDTOF.h b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h similarity index 99% rename from Analysis/DataModel/include/PID/PIDTOF.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h index 59a007641476c..a5369f6ede8b3 100644 --- a/Analysis/DataModel/include/PID/PIDTOF.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h @@ -25,7 +25,7 @@ // O2 includes #include "Framework/Logger.h" #include "ReconstructionDataFormats/PID.h" -#include "PIDBase/DetectorResponse.h" +#include "AnalysisDataModel/PID/DetectorResponse.h" namespace o2::pid::tof { diff --git a/Analysis/DataModel/include/PID/PIDTPC.h b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTPC.h similarity index 97% rename from Analysis/DataModel/include/PID/PIDTPC.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/PIDTPC.h index bee121f4bc9d7..9e0e8ef7fa936 100644 --- a/Analysis/DataModel/include/PID/PIDTPC.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTPC.h @@ -25,7 +25,7 @@ // O2 includes #include "Framework/Logger.h" #include "ReconstructionDataFormats/PID.h" -#include "PIDBase/DetectorResponse.h" +#include "AnalysisDataModel/PID/DetectorResponse.h" namespace o2::pid::tpc { diff --git a/Analysis/DataModel/include/PIDBase/ParamBase.h b/Analysis/DataModel/include/AnalysisDataModel/PID/ParamBase.h similarity index 100% rename from Analysis/DataModel/include/PIDBase/ParamBase.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/ParamBase.h diff --git a/Analysis/DataModel/include/PID/TOFReso.h b/Analysis/DataModel/include/AnalysisDataModel/PID/TOFReso.h similarity index 97% rename from Analysis/DataModel/include/PID/TOFReso.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/TOFReso.h index 7cb8745c3e7f3..45cdb6cd7b657 100644 --- a/Analysis/DataModel/include/PID/TOFReso.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/TOFReso.h @@ -21,7 +21,7 @@ // Root includes #include "TMath.h" // O2 includes -#include "PIDBase/ParamBase.h" +#include "AnalysisDataModel/PID/ParamBase.h" namespace o2::pid::tof { diff --git a/Analysis/DataModel/include/PID/TPCReso.h b/Analysis/DataModel/include/AnalysisDataModel/PID/TPCReso.h similarity index 96% rename from Analysis/DataModel/include/PID/TPCReso.h rename to Analysis/DataModel/include/AnalysisDataModel/PID/TPCReso.h index 7ffc1a7f8e3d0..8f6d2171ee277 100644 --- a/Analysis/DataModel/include/PID/TPCReso.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/TPCReso.h @@ -18,7 +18,7 @@ #ifndef O2_ANALYSIS_PID_TPCRESO_H_ #define O2_ANALYSIS_PID_TPCRESO_H_ -#include "PIDBase/ParamBase.h" +#include "AnalysisDataModel/PID/ParamBase.h" namespace o2::pid::tpc { diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/AnalysisDataModel/ReducedInfoTables.h similarity index 98% rename from Analysis/DataModel/include/Analysis/ReducedInfoTables.h rename to Analysis/DataModel/include/AnalysisDataModel/ReducedInfoTables.h index cd047877470c2..837cc7232cf3c 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/AnalysisDataModel/ReducedInfoTables.h @@ -16,9 +16,9 @@ #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/Centrality.h" -#include "Analysis/EventSelection.h" -#include "PID/PIDResponse.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/PID/PIDResponse.h" #include "MathUtils/Utils.h" #include <cmath> diff --git a/Analysis/DataModel/include/Analysis/StrangenessTables.h b/Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h similarity index 99% rename from Analysis/DataModel/include/Analysis/StrangenessTables.h rename to Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h index a56386ef48d3a..5fec469426c39 100644 --- a/Analysis/DataModel/include/Analysis/StrangenessTables.h +++ b/Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h @@ -11,7 +11,7 @@ #define O2_ANALYSIS_STRANGENESSTABLES_H_ #include "Framework/AnalysisDataModel.h" -#include "Analysis/RecoDecay.h" +#include "AnalysisCore/RecoDecay.h" namespace o2::aod { diff --git a/Analysis/DataModel/include/Analysis/TrackSelectionTables.h b/Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h similarity index 100% rename from Analysis/DataModel/include/Analysis/TrackSelectionTables.h rename to Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h diff --git a/Analysis/DataModel/src/ParamBase.cxx b/Analysis/DataModel/src/ParamBase.cxx index a4267eedfcd87..865f566c905e4 100644 --- a/Analysis/DataModel/src/ParamBase.cxx +++ b/Analysis/DataModel/src/ParamBase.cxx @@ -16,7 +16,7 @@ /// These are the basic storage elements to be kept in the CCDB /// -#include "PIDBase/ParamBase.h" +#include "AnalysisDataModel/PID/ParamBase.h" #include "Framework/Logger.h" namespace o2::pid diff --git a/Analysis/DataModel/src/aodDataModelGraph.cxx b/Analysis/DataModel/src/aodDataModelGraph.cxx index 9670ecdae0947..11f70cfb458e9 100644 --- a/Analysis/DataModel/src/aodDataModelGraph.cxx +++ b/Analysis/DataModel/src/aodDataModelGraph.cxx @@ -8,13 +8,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/AnalysisDataModel.h" -#include "Analysis/HFSecondaryVertex.h" -#include "PID/PIDResponse.h" -#include "Analysis/Multiplicity.h" -#include "Analysis/Centrality.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/Jet.h" -#include "Analysis/StrangenessTables.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/Jet.h" +#include "AnalysisDataModel/StrangenessTables.h" #include <fmt/printf.h> #include <map> diff --git a/Analysis/DataModel/src/handleParamTOFReso.cxx b/Analysis/DataModel/src/handleParamTOFReso.cxx index e7ca0b6b7dcc2..2d6c62f72f3f8 100644 --- a/Analysis/DataModel/src/handleParamTOFReso.cxx +++ b/Analysis/DataModel/src/handleParamTOFReso.cxx @@ -19,7 +19,7 @@ #include <boost/program_options.hpp> #include <FairLogger.h> #include "TFile.h" -#include "PID/TOFReso.h" +#include "AnalysisDataModel/PID/TOFReso.h" using namespace o2::pid::tof; namespace bpo = boost::program_options; diff --git a/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx b/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx index 3e542a744f116..cd3d7b33496ba 100644 --- a/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx +++ b/Analysis/DataModel/src/handleParamTPCBetheBloch.cxx @@ -19,8 +19,8 @@ #include <boost/program_options.hpp> #include <FairLogger.h> #include "TFile.h" -#include "PID/BetheBloch.h" -#include "PID/TPCReso.h" +#include "AnalysisDataModel/PID/BetheBloch.h" +#include "AnalysisDataModel/PID/TPCReso.h" using namespace o2::pid::tpc; namespace bpo = boost::program_options; diff --git a/Analysis/Tasks/ALICE3/alice3-trackselection.cxx b/Analysis/Tasks/ALICE3/alice3-trackselection.cxx index 53928e1e4523f..2f35eea40c23b 100644 --- a/Analysis/Tasks/ALICE3/alice3-trackselection.cxx +++ b/Analysis/Tasks/ALICE3/alice3-trackselection.cxx @@ -15,9 +15,9 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/trackUtilities.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisCore/trackUtilities.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index 1986267c1d911..a99ac03f4e78b 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -15,11 +15,11 @@ #include "Framework/StepTHn.h" #include "Framework/HistogramRegistry.h" -#include "Analysis/EventSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/Centrality.h" -#include "Analysis/CorrelationContainer.h" -#include "Analysis/PairCuts.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/CorrelationContainer.h" +#include "AnalysisCore/PairCuts.h" #include <TH1F.h> #include <cmath> diff --git a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx index 6b901f88915e5..6a8549d1ad95d 100644 --- a/Analysis/Tasks/PWGCF/correlationsFiltered.cxx +++ b/Analysis/Tasks/PWGCF/correlationsFiltered.cxx @@ -13,11 +13,11 @@ #include "Framework/ASoAHelpers.h" #include "Framework/StepTHn.h" -#include "Analysis/EventSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/Centrality.h" -#include "Analysis/CorrelationContainer.h" -#include "Analysis/CFDerived.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/CorrelationContainer.h" +#include "AnalysisDataModel/CFDerived.h" #include <TH1F.h> #include <cmath> diff --git a/Analysis/Tasks/PWGCF/correlationsMixed.cxx b/Analysis/Tasks/PWGCF/correlationsMixed.cxx index 529dd9eba04fa..d2197ac895df3 100644 --- a/Analysis/Tasks/PWGCF/correlationsMixed.cxx +++ b/Analysis/Tasks/PWGCF/correlationsMixed.cxx @@ -13,10 +13,10 @@ #include "Framework/ASoAHelpers.h" #include "Framework/StepTHn.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" -#include "Analysis/CorrelationContainer.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/CorrelationContainer.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <TH1F.h> #include <cmath> diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index a75a189dc4318..f076295d2cb7b 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -11,11 +11,11 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" -#include "Analysis/TrackSelection.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/TrackSelection.h" #include "AnalysisConfigurableCuts.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <TROOT.h> #include <TParameter.h> #include <TList.h> diff --git a/Analysis/Tasks/PWGCF/filterCF.cxx b/Analysis/Tasks/PWGCF/filterCF.cxx index 05ef5f3860c83..6f649fe8c32d3 100644 --- a/Analysis/Tasks/PWGCF/filterCF.cxx +++ b/Analysis/Tasks/PWGCF/filterCF.cxx @@ -12,10 +12,10 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/CFDerived.h" -#include "Analysis/EventSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/Centrality.h" +#include "AnalysisDataModel/CFDerived.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/Centrality.h" #include <TH3F.h> diff --git a/Analysis/Tasks/PWGDQ/CutsLibrary.h b/Analysis/Tasks/PWGDQ/CutsLibrary.h index 87423e236ffb9..6775c4aff8e38 100644 --- a/Analysis/Tasks/PWGDQ/CutsLibrary.h +++ b/Analysis/Tasks/PWGDQ/CutsLibrary.h @@ -10,9 +10,9 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include "Analysis/AnalysisCut.h" -#include "Analysis/AnalysisCompositeCut.h" -#include "Analysis/VarManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" +#include "AnalysisCore/VarManager.h" namespace o2::aod { diff --git a/Analysis/Tasks/PWGDQ/HistogramsLibrary.h b/Analysis/Tasks/PWGDQ/HistogramsLibrary.h index 03c7ce56950e2..a888dc05ddccb 100644 --- a/Analysis/Tasks/PWGDQ/HistogramsLibrary.h +++ b/Analysis/Tasks/PWGDQ/HistogramsLibrary.h @@ -10,8 +10,8 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include "Analysis/HistogramManager.h" -#include "Analysis/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/VarManager.h" namespace o2::aod { diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx index ce0557fc76408..fc93b1854afa5 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -14,11 +14,11 @@ #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 "AnalysisDataModel/ReducedInfoTables.h" +#include "AnalysisCore/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" #include <TH1F.h> #include <TMath.h> #include <THashList.h> diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx index b496f88e43cd9..e3b9284a53f8f 100644 --- a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -14,11 +14,11 @@ #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 "AnalysisDataModel/ReducedInfoTables.h" +#include "AnalysisCore/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" #include <TH1F.h> #include <TMath.h> #include <THashList.h> diff --git a/Analysis/Tasks/PWGDQ/filterPP.cxx b/Analysis/Tasks/PWGDQ/filterPP.cxx index f03fde06261c3..1fb77b8e9bff6 100644 --- a/Analysis/Tasks/PWGDQ/filterPP.cxx +++ b/Analysis/Tasks/PWGDQ/filterPP.cxx @@ -14,19 +14,19 @@ #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 "Analysis/TriggerAliases.h" -#include "Analysis/ReducedInfoTables.h" -#include "Analysis/VarManager.h" -#include "Analysis/HistogramManager.h" -#include "Analysis/AnalysisCut.h" -#include "Analysis/AnalysisCompositeCut.h" +#include "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/TriggerAliases.h" +#include "AnalysisDataModel/ReducedInfoTables.h" +#include "AnalysisCore/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" #include "CutsLibrary.h" #include "HistogramsLibrary.h" -#include "PID/PIDResponse.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <TH1F.h> #include <TH2I.h> #include <TMath.h> diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index e839070c3ebcb..4f9eaf2d8a788 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -14,17 +14,17 @@ #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 "Analysis/TriggerAliases.h" -#include "Analysis/ReducedInfoTables.h" -#include "Analysis/VarManager.h" -#include "Analysis/HistogramManager.h" -#include "Analysis/AnalysisCut.h" -#include "Analysis/AnalysisCompositeCut.h" -#include "PID/PIDResponse.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/TriggerAliases.h" +#include "AnalysisDataModel/ReducedInfoTables.h" +#include "AnalysisCore/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <iostream> using std::cout; diff --git a/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx b/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx index d8fdc7b1c0816..9877a5a7f8b7f 100644 --- a/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx @@ -14,17 +14,17 @@ #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 "Analysis/TriggerAliases.h" -#include "Analysis/ReducedInfoTables.h" -#include "Analysis/VarManager.h" -#include "Analysis/HistogramManager.h" -#include "Analysis/AnalysisCut.h" -#include "Analysis/AnalysisCompositeCut.h" -#include "PID/PIDResponse.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/TriggerAliases.h" +#include "AnalysisDataModel/ReducedInfoTables.h" +#include "AnalysisCore/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <iostream> using std::cout; diff --git a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx index 4c9c9dadbb3a4..68175ccbe15ae 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx @@ -14,17 +14,17 @@ #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 "Analysis/TriggerAliases.h" -#include "Analysis/ReducedInfoTables.h" -#include "Analysis/VarManager.h" -#include "Analysis/HistogramManager.h" -#include "Analysis/AnalysisCut.h" -#include "Analysis/AnalysisCompositeCut.h" -#include "PID/PIDResponse.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/TriggerAliases.h" +#include "AnalysisDataModel/ReducedInfoTables.h" +#include "AnalysisCore/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <iostream> using std::cout; diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index d7390dc8e44b1..e3b1899fc681f 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -14,11 +14,11 @@ #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 "AnalysisDataModel/ReducedInfoTables.h" +#include "AnalysisCore/VarManager.h" +#include "AnalysisCore/HistogramManager.h" +#include "AnalysisCore/AnalysisCut.h" +#include "AnalysisCore/AnalysisCompositeCut.h" #include <TH1F.h> #include <TMath.h> #include <THashList.h> diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index a62b5b9c9ce55..ee3a8a9c7d1ba 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -16,8 +16,8 @@ #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/trackUtilities.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisCore/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" using namespace o2; diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index 9ea2145c15e35..a64ff6adfcc89 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -16,8 +16,8 @@ #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/trackUtilities.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisCore/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" using namespace o2; diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index 6d50a5f9d73bf..77c61d0f68d09 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -15,8 +15,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/HFCandidateSelectionTables.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx index fbdb2edb72c57..f2d2b22ad880d 100644 --- a/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx @@ -16,8 +16,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/HFCandidateSelectionTables.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 8fc8e9261a6a6..4e9415435a0a5 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -18,10 +18,10 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "DetectorsVertexing/DCAFitterN.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/trackUtilities.h" -#include "Analysis/HFConfigurables.h" -//#include "Analysis/Centrality.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisCore/trackUtilities.h" +#include "AnalysisCore/HFConfigurables.h" +//#include "AnalysisDataModel/Centrality.h" #include "Framework/HistogramRegistry.h" #include <algorithm> diff --git a/Analysis/Tasks/PWGHF/qaTask.cxx b/Analysis/Tasks/PWGHF/qaTask.cxx index 805eb4b444500..04da7b327d955 100644 --- a/Analysis/Tasks/PWGHF/qaTask.cxx +++ b/Analysis/Tasks/PWGHF/qaTask.cxx @@ -16,7 +16,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/HistogramRegistry.h" -#include "Analysis/trackUtilities.h" +#include "AnalysisCore/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" #include "TH1D.h" diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index cccc6c5f1b08a..8cbd50fcd6556 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -16,8 +16,8 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/HFCandidateSelectionTables.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGHF/taskDPlus.cxx b/Analysis/Tasks/PWGHF/taskDPlus.cxx index cf2af649c6c49..019bed11abe42 100644 --- a/Analysis/Tasks/PWGHF/taskDPlus.cxx +++ b/Analysis/Tasks/PWGHF/taskDPlus.cxx @@ -17,8 +17,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/HFCandidateSelectionTables.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGHF/taskLc.cxx b/Analysis/Tasks/PWGHF/taskLc.cxx index ca721dbc97e9e..2fa3bd1d348e6 100644 --- a/Analysis/Tasks/PWGHF/taskLc.cxx +++ b/Analysis/Tasks/PWGHF/taskLc.cxx @@ -16,8 +16,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/HFCandidateSelectionTables.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFCandidateSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGJE/jetfinder.cxx b/Analysis/Tasks/PWGJE/jetfinder.cxx index c5acbad3493a0..7237557289a4d 100644 --- a/Analysis/Tasks/PWGJE/jetfinder.cxx +++ b/Analysis/Tasks/PWGJE/jetfinder.cxx @@ -20,8 +20,8 @@ #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequenceArea.hh" -#include "Analysis/Jet.h" -#include "Analysis/JetFinder.h" +#include "AnalysisDataModel/Jet.h" +#include "AnalysisCore/JetFinder.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx b/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx index 6e163be961b05..49a7fdff15bc6 100644 --- a/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx +++ b/Analysis/Tasks/PWGJE/jetfinderhadronrecoil.cxx @@ -20,8 +20,8 @@ #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequenceArea.hh" -#include "Analysis/Jet.h" -#include "Analysis/JetFinder.h" +#include "AnalysisDataModel/Jet.h" +#include "AnalysisCore/JetFinder.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGJE/jetfinderhf.cxx b/Analysis/Tasks/PWGJE/jetfinderhf.cxx index 5f6bc347f7528..222113c38efc2 100644 --- a/Analysis/Tasks/PWGJE/jetfinderhf.cxx +++ b/Analysis/Tasks/PWGJE/jetfinderhf.cxx @@ -17,14 +17,14 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Analysis/HFSecondaryVertex.h" -#include "Analysis/HFCandidateSelectionTables.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFCandidateSelectionTables.h" #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequenceArea.hh" -#include "Analysis/Jet.h" -#include "Analysis/JetFinder.h" +#include "AnalysisDataModel/Jet.h" +#include "AnalysisCore/JetFinder.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGJE/jetsubstructure.cxx b/Analysis/Tasks/PWGJE/jetsubstructure.cxx index d50ea4a07c79f..62ea4d2c6a944 100644 --- a/Analysis/Tasks/PWGJE/jetsubstructure.cxx +++ b/Analysis/Tasks/PWGJE/jetsubstructure.cxx @@ -21,8 +21,8 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Analysis/Jet.h" -#include "Analysis/JetFinder.h" +#include "AnalysisDataModel/Jet.h" +#include "AnalysisCore/JetFinder.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx index c95d2d798d03f..6d2a76941dfd4 100644 --- a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx +++ b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx @@ -11,7 +11,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDResponse.h" #include <TH1F.h> #include <TH2F.h> diff --git a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx index 5919010b888c9..5fd84de8d263d 100644 --- a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx @@ -26,13 +26,13 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" -#include "Analysis/trackUtilities.h" -#include "Analysis/StrangenessTables.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" +#include "AnalysisCore/RecoDecay.h" +#include "AnalysisCore/trackUtilities.h" +#include "AnalysisDataModel/StrangenessTables.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" #include <TFile.h> #include <TH2F.h> @@ -44,7 +44,7 @@ #include <cmath> #include <array> #include <cstdlib> -#include "PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; diff --git a/Analysis/Tasks/PWGLF/cascadefinder.cxx b/Analysis/Tasks/PWGLF/cascadefinder.cxx index 4ee368dc41d15..6b23254efb01a 100644 --- a/Analysis/Tasks/PWGLF/cascadefinder.cxx +++ b/Analysis/Tasks/PWGLF/cascadefinder.cxx @@ -31,17 +31,17 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" -#include "Analysis/trackUtilities.h" -#include "PID/PIDResponse.h" -#include "Analysis/StrangenessTables.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" +#include "AnalysisCore/RecoDecay.h" +#include "AnalysisCore/trackUtilities.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/StrangenessTables.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" #include <TFile.h> #include <TLorentzVector.h> diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx index 2b9a7f844ae9b..f0bdda6d11063 100644 --- a/Analysis/Tasks/PWGLF/cascadeproducer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -34,14 +34,14 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" -#include "Analysis/trackUtilities.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/StrangenessTables.h" +#include "AnalysisCore/RecoDecay.h" +#include "AnalysisCore/trackUtilities.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/StrangenessTables.h" #include <TFile.h> #include <TH2F.h> @@ -53,7 +53,7 @@ #include <cmath> #include <array> #include <cstdlib> -#include "PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; diff --git a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx index bd7982a42f063..2fa0ae25839b5 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx @@ -25,13 +25,13 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" -#include "Analysis/trackUtilities.h" -#include "Analysis/StrangenessTables.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" +#include "AnalysisCore/RecoDecay.h" +#include "AnalysisCore/trackUtilities.h" +#include "AnalysisDataModel/StrangenessTables.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" #include <TFile.h> #include <TH2F.h> @@ -43,7 +43,7 @@ #include <cmath> #include <array> #include <cstdlib> -#include "PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index a1b89481d6aaf..a5f80627f1237 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -31,17 +31,17 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" -#include "Analysis/trackUtilities.h" -#include "PID/PIDResponse.h" -#include "Analysis/StrangenessTables.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" +#include "AnalysisCore/RecoDecay.h" +#include "AnalysisCore/trackUtilities.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/StrangenessTables.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" #include <TFile.h> #include <TLorentzVector.h> diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index d8784c85308c3..7dfa491c07cc5 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -34,14 +34,14 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/HFSecondaryVertex.h" +#include "AnalysisDataModel/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" -#include "Analysis/RecoDecay.h" -#include "Analysis/trackUtilities.h" -#include "Analysis/StrangenessTables.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisCore/RecoDecay.h" +#include "AnalysisCore/trackUtilities.h" +#include "AnalysisDataModel/StrangenessTables.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <TFile.h> #include <TH2F.h> @@ -53,7 +53,7 @@ #include <cmath> #include <array> #include <cstdlib> -#include "PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; diff --git a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx index 76ed9f2e9e12b..92a6c8e4217c0 100644 --- a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx +++ b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx @@ -11,9 +11,9 @@ // O2 includes #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/MC.h" +#include "AnalysisCore/MC.h" #include "Framework/ASoAHelpers.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/TrackSelectionTables.h" // ROOT includes #include <TH1F.h> diff --git a/Analysis/Tasks/PWGLF/raacharged.cxx b/Analysis/Tasks/PWGLF/raacharged.cxx index 9f60a86a520bb..f24a5b64e1bb5 100644 --- a/Analysis/Tasks/PWGLF/raacharged.cxx +++ b/Analysis/Tasks/PWGLF/raacharged.cxx @@ -11,11 +11,11 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/MC.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisCore/MC.h" #include <TH1F.h> #include <TParticlePDG.h> #include <TDatabasePDG.h> diff --git a/Analysis/Tasks/PWGLF/spectraTOF.cxx b/Analysis/Tasks/PWGLF/spectraTOF.cxx index 73a12607a8f96..bc3d4b815e562 100644 --- a/Analysis/Tasks/PWGLF/spectraTOF.cxx +++ b/Analysis/Tasks/PWGLF/spectraTOF.cxx @@ -14,8 +14,8 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "PID/PIDResponse.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index f112b42012af1..d7498c9ee6045 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -13,8 +13,8 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "PID/PIDResponse.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/PWGLF/trackchecks.cxx b/Analysis/Tasks/PWGLF/trackchecks.cxx index b8230dec9f549..e22defe105cb3 100644 --- a/Analysis/Tasks/PWGLF/trackchecks.cxx +++ b/Analysis/Tasks/PWGLF/trackchecks.cxx @@ -10,11 +10,11 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/EventSelection.h" -#include "Analysis/MC.h" -#include "Analysis/HistHelpers.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisCore/MC.h" +#include "AnalysisCore/HistHelpers.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" #include <cmath> #include <array> diff --git a/Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx b/Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx index ac949f823fcb5..a3eaf73d4e9d4 100644 --- a/Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx +++ b/Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx @@ -11,9 +11,9 @@ #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 "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" #include <TH1F.h> #include <TH2F.h> #include <cmath> diff --git a/Analysis/Tasks/PWGUD/upcAnalysis.cxx b/Analysis/Tasks/PWGUD/upcAnalysis.cxx index 151d220c485c5..e307feee0594e 100644 --- a/Analysis/Tasks/PWGUD/upcAnalysis.cxx +++ b/Analysis/Tasks/PWGUD/upcAnalysis.cxx @@ -10,9 +10,9 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/EventSelection.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisDataModel/EventSelection.h" #include <TH1D.h> #include <TH2D.h> #include <cmath> diff --git a/Analysis/Tasks/centralityQa.cxx b/Analysis/Tasks/centralityQa.cxx index 7871c2bea6378..f92e4e1792191 100644 --- a/Analysis/Tasks/centralityQa.cxx +++ b/Analysis/Tasks/centralityQa.cxx @@ -10,8 +10,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Centrality.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" #include "TH1F.h" using namespace o2; diff --git a/Analysis/Tasks/centralityTable.cxx b/Analysis/Tasks/centralityTable.cxx index 19dac63be3746..65f2cfaf2368d 100644 --- a/Analysis/Tasks/centralityTable.cxx +++ b/Analysis/Tasks/centralityTable.cxx @@ -10,8 +10,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/Multiplicity.h" -#include "Analysis/Centrality.h" +#include "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/Centrality.h" #include <CCDB/BasicCCDBManager.h> #include "TH1F.h" diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index f0b83b41a3053..67a7504004671 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -22,8 +22,8 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/EventSelection.h" -#include "Analysis/TriggerAliases.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisCore/TriggerAliases.h" #include <CCDB/BasicCCDBManager.h> #include "CommonConstants/LHCConstants.h" diff --git a/Analysis/Tasks/eventSelectionQa.cxx b/Analysis/Tasks/eventSelectionQa.cxx index 95a2d55000c35..76eaeedf9fea6 100644 --- a/Analysis/Tasks/eventSelectionQa.cxx +++ b/Analysis/Tasks/eventSelectionQa.cxx @@ -10,7 +10,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/EventSelection.h" +#include "AnalysisDataModel/EventSelection.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/multiplicityQa.cxx b/Analysis/Tasks/multiplicityQa.cxx index eb1c3847dd85a..ecffbf3077d8e 100644 --- a/Analysis/Tasks/multiplicityQa.cxx +++ b/Analysis/Tasks/multiplicityQa.cxx @@ -19,8 +19,8 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/Multiplicity.h" -#include "Analysis/EventSelection.h" +#include "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" #include "TH1F.h" #include "TH2F.h" diff --git a/Analysis/Tasks/multiplicityTable.cxx b/Analysis/Tasks/multiplicityTable.cxx index bab242d959868..724bb4791b088 100644 --- a/Analysis/Tasks/multiplicityTable.cxx +++ b/Analysis/Tasks/multiplicityTable.cxx @@ -21,8 +21,8 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/EventSelection.h" -#include "Analysis/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Multiplicity.h" #include "iostream" struct MultiplicityTableTaskIndexed { diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index 665f9217f0942..b7b41534485f1 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -15,8 +15,8 @@ #include "Framework/HistogramRegistry.h" #include "ReconstructionDataFormats/Track.h" #include <CCDB/BasicCCDBManager.h> -#include "PID/PIDResponse.h" -#include "PID/PIDTOF.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDTOF.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index b3a8191c022d6..520b8f914f998 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -15,8 +15,8 @@ #include "Framework/HistogramRegistry.h" #include "ReconstructionDataFormats/Track.h" #include <CCDB/BasicCCDBManager.h> -#include "PID/PIDResponse.h" -#include "PID/PIDTPC.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDTPC.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/reducedEventAnalysis.cxx b/Analysis/Tasks/reducedEventAnalysis.cxx index 7403df356a15f..dde7efee16842 100644 --- a/Analysis/Tasks/reducedEventAnalysis.cxx +++ b/Analysis/Tasks/reducedEventAnalysis.cxx @@ -11,9 +11,9 @@ #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 "AnalysisDataModel/Multiplicity.h" +#include "AnalysisDataModel/EventSelection.h" +#include "AnalysisDataModel/Centrality.h" #include <TH1F.h> #include <TH2F.h> #include <TMath.h> diff --git a/Analysis/Tasks/trackextension.cxx b/Analysis/Tasks/trackextension.cxx index 1be057fff8e3b..646a83dbce891 100644 --- a/Analysis/Tasks/trackextension.cxx +++ b/Analysis/Tasks/trackextension.cxx @@ -15,9 +15,9 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/trackUtilities.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisCore/trackUtilities.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 6fa1fbc1a935f..e7f10f1844cc5 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -15,10 +15,10 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Analysis/MC.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionDefaults.h" +#include "AnalysisCore/MC.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisCore/TrackSelectionDefaults.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index a8425576eaaff..baeda9e183a28 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -15,10 +15,10 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionDefaults.h" -#include "Analysis/TrackSelectionTables.h" -#include "Analysis/trackUtilities.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisCore/TrackSelectionDefaults.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "AnalysisCore/trackUtilities.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tutorials/src/histHelpersTest.cxx b/Analysis/Tutorials/src/histHelpersTest.cxx index 8037582e52ccc..34e39bcece9c4 100644 --- a/Analysis/Tutorials/src/histHelpersTest.cxx +++ b/Analysis/Tutorials/src/histHelpersTest.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. #include "Framework/AnalysisTask.h" -#include "Analysis/HistHelpers.h" +#include "AnalysisCore/HistHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/runDataProcessing.h" diff --git a/Analysis/Tutorials/src/histogramTrackSelection.cxx b/Analysis/Tutorials/src/histogramTrackSelection.cxx index ff9430ac962b0..a7e344ffdba03 100644 --- a/Analysis/Tutorials/src/histogramTrackSelection.cxx +++ b/Analysis/Tutorials/src/histogramTrackSelection.cxx @@ -15,8 +15,8 @@ #include <cmath> -#include "Analysis/TrackSelection.h" -#include "Analysis/TrackSelectionTables.h" +#include "AnalysisCore/TrackSelection.h" +#include "AnalysisDataModel/TrackSelectionTables.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tutorials/src/jetAnalysis.cxx b/Analysis/Tutorials/src/jetAnalysis.cxx index bc42f586fa14b..250636e304cb0 100644 --- a/Analysis/Tutorials/src/jetAnalysis.cxx +++ b/Analysis/Tutorials/src/jetAnalysis.cxx @@ -21,7 +21,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Analysis/Jet.h" +#include "AnalysisDataModel/Jet.h" using namespace o2; using namespace o2::framework; diff --git a/Analysis/Tutorials/src/mcHistograms.cxx b/Analysis/Tutorials/src/mcHistograms.cxx index 0f5521a9739ae..1e0d5e4dcc8d6 100644 --- a/Analysis/Tutorials/src/mcHistograms.cxx +++ b/Analysis/Tutorials/src/mcHistograms.cxx @@ -10,7 +10,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Analysis/MC.h" +#include "AnalysisCore/MC.h" #include <TH1F.h> #include <cmath> From 7e7fea8bc0a68009a967faa05b67f5a788042606 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 11:04:45 +0100 Subject: [PATCH 1534/1751] Add gpu reconstruction processing time metric to alibi benchmark --- prodtests/full_system_test.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index e66cac139101c..d3f5d7c2e5858 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -110,6 +110,10 @@ for STAGE in $STAGES; do walltime=`grep "#walltime" ${logfile}_time | awk '//{print $2}'` echo "walltime_${STAGE},${TAG} value=${walltime}" >> ${METRICFILE} + # GPU reconstruction (also in CPU version) processing time + gpurecotime=`grep "tpc-tracker" reco_NOGPU.log | grep -e "Total Wall Time:" | awk '//{printf "%f", $6/1000000}'` + echo "gpurecotime_${STAGE},${TAG} value=${gpurecotime}" >> ${METRICFILE} + # memory maxmem=`awk '/PROCESS MAX MEM/{print $5}' ${logfile}` # in MB avgmem=`awk '/PROCESS AVG MEM/{print $5}' ${logfile}` # in MB From 80a3d27579d77bd9c03aa7104a1663da70df596e Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 4 Dec 2020 11:39:06 +0100 Subject: [PATCH 1535/1751] DPL Analysis: helper to transfer index bindings (#4990) --- Analysis/Tutorials/src/associatedExample.cxx | 4 + Framework/Core/include/Framework/ASoA.h | 77 +++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/Analysis/Tutorials/src/associatedExample.cxx b/Analysis/Tutorials/src/associatedExample.cxx index 19c171fb6fba7..a9f9ccf925747 100644 --- a/Analysis/Tutorials/src/associatedExample.cxx +++ b/Analysis/Tutorials/src/associatedExample.cxx @@ -98,6 +98,10 @@ struct ZTask { for (auto& col : multbin0_10) { auto groupedTracks = tracks.select(aod::track::collisionId == col.globalIndex()); LOGF(INFO, "Collision %d; Ntrk = %d vs %d", col.globalIndex(), col.mult(), groupedTracks.size()); + if (groupedTracks.size() > 0) { + auto track = groupedTracks.begin(); + LOGF(INFO, "Track 0 belongs to collision %d at Z = %f", track.collisionId(), track.collision_as<myCol>().posZ()); + } } LOGF(INFO, "Bin 10-30"); diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 5262f42247f05..e57c7a08eaec8 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -742,12 +742,40 @@ struct RowViewCore : public IP, C... { (CL::setCurrent(current), ...); } + template <typename CL> + auto getCurrent() const + { + return CL::getCurrentRaw(); + } + + template <typename... Cs> + auto getIndexBindingsImpl(framework::pack<Cs...>) const + { + return std::vector<void*>{static_cast<Cs const&>(*this).getCurrentRaw()...}; + } + + auto getIndexBindings() const + { + return getIndexBindingsImpl(external_index_columns_t{}); + } + template <typename... TA> void bindExternalIndices(TA*... current) { (doSetCurrentIndex(external_index_columns_t{}, current), ...); } + template <typename... Cs> + void doSetCurrentIndexRaw(framework::pack<Cs...> p, std::vector<void*>&& ptrs) + { + (Cs::setCurrentRaw(ptrs[framework::has_type_at_v<Cs>(p)]), ...); + } + + void bindExternalIndicesRaw(std::vector<void*>&& ptrs) + { + doSetCurrentIndexRaw(external_index_columns_t{}, std::forward<std::vector<void*>>(ptrs)); + } + private: /// Helper to move to the correct chunk, if needed. /// FIXME: not needed? @@ -848,6 +876,7 @@ class Table using columns = framework::pack<C...>; using column_types = framework::pack<typename C::type...>; using persistent_columns_t = framework::selected_pack<is_persistent_t, C...>; + using external_index_columns_t = framework::selected_pack<is_external_index_t, C...>; template <typename IP, typename Parent, typename... T> struct RowViewBase : public RowViewCore<IP, C...> { @@ -1030,9 +1059,28 @@ class Table mBegin.bindExternalIndices(current...); } + void bindExternalIndicesRaw(std::vector<void*>&& ptrs) + { + mBegin.bindExternalIndicesRaw(std::forward<std::vector<void*>>(ptrs)); + } + + template <typename T, typename... Cs> + void doCopyIndexBindings(framework::pack<Cs...>, T& dest) const + { + dest.bindExternalIndicesRaw(mBegin.getIndexBindings()); + } + + template <typename T> + void copyIndexBindings(T& dest) const + { + doCopyIndexBindings(external_index_columns_t{}, dest); + } + auto select(framework::expressions::Filter&& f) const { - return o2::soa::select(*this, std::forward<framework::expressions::Filter>(f)); + auto t = o2::soa::select(*this, std::forward<framework::expressions::Filter>(f)); + copyIndexBindings(t); + return t; } private: @@ -1300,7 +1348,14 @@ constexpr auto is_binding_compatible_v() } \ return false; \ } \ - binding_t* getCurrent() { return static_cast<binding_t*>(mBinding); } \ + \ + bool setCurrentRaw(void* current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + binding_t* getCurrent() const { return static_cast<binding_t*>(mBinding); } \ + void* getCurrentRaw() const { return mBinding; } \ void* mBinding = nullptr; \ }; \ static const o2::framework::expressions::BindingNode _Getter_##Id { _Label_, \ @@ -1535,6 +1590,7 @@ class FilteredPolicy : public T using originals = originals_pack_t<T>; using table_t = typename T::table_t; using persistent_columns_t = typename T::persistent_columns_t; + using external_index_columns_t = typename T::external_index_columns_t; template <typename P, typename... Os> constexpr static auto make_it(framework::pack<Os...> const&) @@ -1625,6 +1681,23 @@ class FilteredPolicy : public T mFilteredBegin.bindExternalIndices(current...); } + void bindExternalIndicesRaw(std::vector<void*>&& ptrs) + { + mFilteredBegin.bindExternalIndicesRaw(std::forward<std::vector<void*>>(ptrs)); + } + + template <typename T1, typename... Cs> + void doCopyIndexBindings(framework::pack<Cs...>, T1& dest) const + { + dest.bindExternalIndicesRaw(mFilteredBegin.getIndexBindings()); + } + + template <typename T1> + void copyIndexBindings(T1& dest) const + { + doCopyIndexBindings(external_index_columns_t{}, dest); + } + protected: void sumWithSelection(SelectionVector const& selection) { From 91b5537da96ed05152d52b62635b8706f43f5244 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 4 Dec 2020 11:40:29 +0100 Subject: [PATCH 1536/1751] DPL Analysis: nested vector for struct configurable (#4897) --- Analysis/Tutorials/include/Analysis/configurableCut.h | 10 +++++++--- Analysis/Tutorials/src/ConfigurableCutLinkDef.h | 6 +++++- Analysis/Tutorials/src/configurableCut.cxx | 9 +++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h index 76ab55847b0b6..501128a37ae0f 100644 --- a/Analysis/Tutorials/include/Analysis/configurableCut.h +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -18,8 +18,8 @@ class configurableCut { public: - configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true) - : cut{cut_}, state{state_}, option{option_} + configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true, std::vector<float> bins_ = {0.5, 1.5, 2.5}) + : cut{cut_}, state{state_}, option{option_}, bins{bins_} { } @@ -34,12 +34,16 @@ class configurableCut void setOption(bool option_); bool getOption() const; + void setBins(std::vector<float> bins_); + auto getBins() const; + private: float cut; int state; bool option; + std::vector<float> bins; - ClassDef(configurableCut, 3); + ClassDef(configurableCut, 4); }; std::ostream& operator<<(std::ostream& os, configurableCut const& c); diff --git a/Analysis/Tutorials/src/ConfigurableCutLinkDef.h b/Analysis/Tutorials/src/ConfigurableCutLinkDef.h index 0760e732fb45f..4ad2560c106b7 100644 --- a/Analysis/Tutorials/src/ConfigurableCutLinkDef.h +++ b/Analysis/Tutorials/src/ConfigurableCutLinkDef.h @@ -11,5 +11,9 @@ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; - +#pragma link C++ nestedclasses; #pragma link C++ class configurableCut + ; +#pragma link C++ class std::vector < int> + ; +#pragma link C++ class std::vector < float> + ; +#pragma link C++ class std::vector < double> + ; +#pragma link C++ class std::vector < bool> + ; diff --git a/Analysis/Tutorials/src/configurableCut.cxx b/Analysis/Tutorials/src/configurableCut.cxx index 1b52790828268..eb3ac124a2fca 100644 --- a/Analysis/Tutorials/src/configurableCut.cxx +++ b/Analysis/Tutorials/src/configurableCut.cxx @@ -51,3 +51,12 @@ bool configurableCut::getOption() const { return option; } + +void configurableCut::setBins(std::vector<float> bins_) +{ + bins = bins_; +}; +auto configurableCut::getBins() const +{ + return bins; +}; From cc900d75f83c150cf0fb0f4ad0c8f19e7fe1d008 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Fri, 4 Dec 2020 12:22:54 +0100 Subject: [PATCH 1537/1751] DPL: send config as a JSON when possible (#4920) --- Framework/Core/src/DataProcessingDevice.cxx | 39 ++++--------------- Framework/Core/src/DeviceConfigInfo.cxx | 22 ++++------- Framework/Core/test/test_DeviceConfigInfo.cxx | 6 +-- 3 files changed, 19 insertions(+), 48 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 1df540d247856..193e8c51c6f29 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -56,6 +56,7 @@ #include <uv.h> #include <execinfo.h> #include <sstream> +#include <boost/property_tree/json_parser.hpp> using namespace o2::framework; using Key = o2::monitoring::tags::Key; @@ -248,39 +249,15 @@ void DataProcessingDevice::Init() /// Dump the configuration so that we can get it from the driver. for (auto& entry : configStore->store()) { - PropertyTreeHelpers::WalkerFunction printer = [&configStore, topLevel = entry.first](ptree const& parent, ptree::path_type childPath, ptree const& child) { - // FIXME: not clear why we get invoked for the root entry - // and twice for each node. It nevertheless works - // because the net result is that we call twice - // ptree put. - if (childPath.dump() != "") { - LOG(INFO) << "[CONFIG] " << topLevel << "." << childPath.dump() << "=" << child.data() << " 1 " << configStore->provenance(topLevel.c_str()); - } - }; - - auto spec = std::find_if(configStore->specs().begin(), configStore->specs().end(), [&](auto& x) { return x.name == entry.first; }); - if (spec != configStore->specs().end()) { - switch (spec->type) { - case VariantType::ArrayInt: - LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<int>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); - break; - case VariantType::ArrayFloat: - LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<float>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); - break; - case VariantType::ArrayDouble: - LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<double>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); - break; - case VariantType::ArrayBool: - LOG(INFO) << "[CONFIG] " << entry.first << "=" << arrayPrinter<bool>(entry.second) << " 1 " << configStore->provenance(entry.first.c_str()); - break; - default: - LOG(INFO) << "[CONFIG] " << entry.first << "=" << configStore->store().get<std::string>(entry.first) << " 1 " << configStore->provenance(entry.first.c_str()); - PropertyTreeHelpers::traverse(entry.second, printer); - } + std::stringstream ss; + if (entry.second.size() != 0) { + boost::property_tree::json_parser::write_json(ss, configStore->store().get_child(entry.first), false); } else { - LOG(INFO) << "[CONFIG] " << entry.first << "=" << configStore->store().get<std::string>(entry.first) << " 1 " << configStore->provenance(entry.first.c_str()); - PropertyTreeHelpers::traverse(entry.second, printer); + ss << configStore->store().get<std::string>(entry.first) << "\n"; } + auto str = ss.str(); + str.pop_back(); //remove EoL + LOG(INFO) << "[CONFIG] " << entry.first << "=" << str << " 1 " << configStore->provenance(entry.first.c_str()); } mConfigRegistry = std::make_unique<ConfigParamRegistry>(std::move(configStore)); diff --git a/Framework/Core/src/DeviceConfigInfo.cxx b/Framework/Core/src/DeviceConfigInfo.cxx index 3c5360a0c36ad..c5333d5874c12 100644 --- a/Framework/Core/src/DeviceConfigInfo.cxx +++ b/Framework/Core/src/DeviceConfigInfo.cxx @@ -11,8 +11,8 @@ #include "Framework/DeviceConfigInfo.h" #include "Framework/DeviceInfo.h" #include <cstdlib> -#include <regex> #include <string_view> +#include <boost/property_tree/json_parser.hpp> namespace o2::framework { @@ -64,22 +64,16 @@ bool DeviceConfigHelper::processConfig(ParsedConfigMatch& match, auto keyString = std::string(match.beginKey, match.endKey - match.beginKey); auto valueString = std::string(match.beginValue, match.endValue - match.beginValue); auto provenanceString = std::string(match.beginProvenance, match.endProvenance - match.beginProvenance); - std::regex fmatch(R"([ifdb]\[.*\])", std::regex_constants::ECMAScript); - std::regex nmatch(R"((?:(?!=,)|(?!=\[))[+-]?\d+\.?\d*(?:[eE][+-]?\d+)?(?=,|\]))", std::regex_constants::ECMAScript); - auto end = std::sregex_iterator(); - auto fmt = std::sregex_iterator(valueString.begin(), valueString.end(), fmatch); - if (fmt != end) { - boost::property_tree::ptree branch; - auto values = std::sregex_iterator(valueString.begin(), valueString.end(), nmatch); - for (auto v = values; v != end; ++v) { - boost::property_tree::ptree leaf; - leaf.put("", v->str()); - branch.push_back(std::make_pair("", leaf)); - } + boost::property_tree::ptree branch; + std::stringstream ss{valueString}; + try { + boost::property_tree::json_parser::read_json(ss, branch); info.currentConfig.put_child(keyString, branch); - } else { + } catch (boost::exception&) { + // in case it is not a tree but a single value info.currentConfig.put(keyString, valueString); } + info.currentProvenance.put(keyString, provenanceString); return true; } diff --git a/Framework/Core/test/test_DeviceConfigInfo.cxx b/Framework/Core/test/test_DeviceConfigInfo.cxx index 190e131d88548..4533ebfcac79a 100644 --- a/Framework/Core/test/test_DeviceConfigInfo.cxx +++ b/Framework/Core/test/test_DeviceConfigInfo.cxx @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(TestDeviceConfigInfo) BOOST_CHECK_EQUAL(info.currentProvenance.get<std::string>("foo"), "prov"); // Parse an array - configString = "foo[XX:XX:XX][INFO] [CONFIG] array=i[1,2,3,4] 1789372894 prov\n"; + configString = "foo[XX:XX:XX][INFO] [CONFIG] array={\"\":\"1\",\"\":\"2\",\"\":\"3\",\"\":\"4\",\"\":\"5\"} 1789372894 prov\n"; std::string_view configa{configString.data() + 3, configString.size() - 4}; result = DeviceConfigHelper::parseConfig(configa, match); auto valueString = std::string(match.beginValue, match.endValue - match.beginValue); @@ -108,12 +108,12 @@ BOOST_AUTO_TEST_CASE(TestDeviceConfigInfo) BOOST_REQUIRE_EQUAL(result, true); BOOST_CHECK(strncmp(match.beginKey, "array", 5) == 0); BOOST_CHECK_EQUAL(match.timestamp, 1789372894); - BOOST_CHECK(strncmp(match.beginValue, "i[1,2,3,4]", 10) == 0); + BOOST_CHECK(strncmp(match.beginValue, "{\"\":\"1\",\"\":\"2\",\"\":\"3\",\"\":\"4\",\"\":\"5\"}", 35) == 0); BOOST_CHECK(strncmp(match.beginProvenance, "prov", 4) == 0); // Process a given config entry result = DeviceConfigHelper::processConfig(match, info); BOOST_CHECK_EQUAL(result, true); BOOST_CHECK_EQUAL(info.currentProvenance.get<std::string>("array"), "prov"); - BOOST_CHECK_EQUAL(arrayPrinter<int>(info.currentConfig.get_child("array")), "i[1,2,3,4]"); + BOOST_CHECK_EQUAL(arrayPrinter<int>(info.currentConfig.get_child("array")), "i[1,2,3,4,5]"); } From ad10690785ca6ece53a362eb679bb427bff09125 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 10:44:44 +0100 Subject: [PATCH 1538/1751] GPU: Fix codechecker violations --- GPU/Common/GPUCommonAlgorithm.h | 40 +++++++++++++--------- GPU/TPCFastTransformation/SplineHelper.cxx | 3 +- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/GPU/Common/GPUCommonAlgorithm.h b/GPU/Common/GPUCommonAlgorithm.h index 4893eb99a07c2..13b4774d6998f 100644 --- a/GPU/Common/GPUCommonAlgorithm.h +++ b/GPU/Common/GPUCommonAlgorithm.h @@ -114,32 +114,37 @@ GPUdi() I GPUCommonAlgorithm::MedianOf3Select(I f, I l, Cmp cmp) noexcept --l; if (cmp(*f, *m)) { - if (cmp(*m, *l)) + if (cmp(*m, *l)) { return m; - else if (cmp(*f, *l)) + } else if (cmp(*f, *l)) { return l; - else + } else { return f; - } else if (cmp(*f, *l)) + } + } else if (cmp(*f, *l)) { return f; - else if (cmp(*m, *l)) + } else if (cmp(*m, *l)) { return l; - else + } else { return m; + } } template <typename I, typename T, typename Cmp> GPUdi() I GPUCommonAlgorithm::UnguardedPartition(I f, I l, T piv, Cmp cmp) noexcept { do { - while (cmp(*f, piv)) + while (cmp(*f, piv)) { ++f; + } --l; - while (cmp(piv, *l)) + while (cmp(piv, *l)) { --l; + } - if (l <= f) + if (l <= f) { return f; + } IterSwap(f, l); ++f; } while (true); @@ -148,10 +153,9 @@ GPUdi() I GPUCommonAlgorithm::UnguardedPartition(I f, I l, T piv, Cmp cmp) noexc template <typename I, typename Cmp> GPUdi() void GPUCommonAlgorithm::QuickSort(I f, I l, Cmp cmp) noexcept { - if (f == l) - + if (f == l) { return; - + } using IndexType = unsigned short; struct pair { @@ -186,15 +190,19 @@ GPUdi() void GPUCommonAlgorithm::QuickSort(I f, I l, Cmp cmp) noexcept const auto lsz = pp - it0; const auto rsz = it1 - pp; if (lsz < rsz) { - if (rsz > cutoff) + if (rsz > cutoff) { s.emplace(pp - f, it1 - f); - if (lsz > cutoff) + } + if (lsz > cutoff) { s.emplace(it0 - f, pp - f); + } } else { - if (lsz > cutoff) + if (lsz > cutoff) { s.emplace(it0 - f, pp - f); - if (rsz > cutoff) + } + if (rsz > cutoff) { s.emplace(pp - f, it1 - f); + } } } InsertionSort(f, l, cmp); diff --git a/GPU/TPCFastTransformation/SplineHelper.cxx b/GPU/TPCFastTransformation/SplineHelper.cxx index 2275213de3891..320f9cc7ad39d 100644 --- a/GPU/TPCFastTransformation/SplineHelper.cxx +++ b/GPU/TPCFastTransformation/SplineHelper.cxx @@ -351,8 +351,9 @@ void SplineHelper<DataT>::approximateFunction( } // get the knotindexvalue for FParameters: int knotind = pointstoarray(knotindices, numberOfKnots, mXdimensions); - for (int f = 0; f < mFdimensions; f++) + for (int f = 0; f < mFdimensions; f++) { Fparameters[knotind * numberOfParameterTypes * mFdimensions + p * mFdimensions + f] = par[dimension][2 * i * mFdimensions + mFdimensions + f]; ///write derivatives in FParameters + } } } // end for all fknots (for redistribution) From 032b405e8cf102be03195a9d807da7006cf7e701 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 4 Dec 2020 13:20:56 +0100 Subject: [PATCH 1539/1751] DPL: allow configuring FairMQ channels used by DPL (#4995) In particular use it to configure the logging rate. --- .../Framework/ChannelConfigurationPolicy.h | 18 +++---- .../ChannelConfigurationPolicyHelpers.h | 29 +++++------ .../Core/include/Framework/ChannelSpec.h | 15 +++--- .../include/Framework/runDataProcessing.h | 10 ++-- .../Core/src/ChannelConfigurationPolicy.cxx | 15 +++--- .../src/ChannelConfigurationPolicyHelpers.cxx | 49 ++++++++++++------- Framework/Core/src/DeviceSpecHelpers.cxx | 4 +- Framework/Core/test/Mocking.h | 45 +++++++++++++++++ Framework/Core/test/test_DeviceSpec.cxx | 30 ++++++++---- .../Core/test/test_DeviceSpecHelpers.cxx | 5 +- .../Core/test/test_FrameworkDataFlowToDDS.cxx | 4 +- Framework/Core/test/test_Graphviz.cxx | 7 ++- .../Core/test/test_TimeParallelPipelining.cxx | 7 ++- Framework/Core/test/test_WorkflowHelpers.cxx | 25 +--------- 14 files changed, 161 insertions(+), 102 deletions(-) create mode 100644 Framework/Core/test/Mocking.h diff --git a/Framework/Core/include/Framework/ChannelConfigurationPolicy.h b/Framework/Core/include/Framework/ChannelConfigurationPolicy.h index 0fa3be6f1dd86..785a60bb49bf3 100644 --- a/Framework/Core/include/Framework/ChannelConfigurationPolicy.h +++ b/Framework/Core/include/Framework/ChannelConfigurationPolicy.h @@ -7,8 +7,8 @@ // 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_CHANNELCONFIGURATIONPOLICY_H -#define FRAMEWORK_CHANNELCONFIGURATIONPOLICY_H +#ifndef O2_FRAMEWORK_CHANNELCONFIGURATIONPOLICY_H_ +#define O2_FRAMEWORK_CHANNELCONFIGURATIONPOLICY_H_ #include "Framework/ChannelConfigurationPolicyHelpers.h" #include "Framework/ChannelSpec.h" @@ -16,11 +16,11 @@ #include <vector> #include <functional> -namespace o2 -{ -namespace framework +namespace o2::framework { +struct ConfigContext; + /// A ChannelConfigurationPolicy allows the user /// to customise connection method and type /// for a channel created between two devices. @@ -37,10 +37,10 @@ struct ChannelConfigurationPolicy { Helpers::InputChannelModifier modifyInput = nullptr; Helpers::OutputChannelModifier modifyOutput = nullptr; - static std::vector<ChannelConfigurationPolicy> createDefaultPolicies(); + /// Default policies to use, based on the contents of the @configContex content + static std::vector<ChannelConfigurationPolicy> createDefaultPolicies(ConfigContext const& configContext); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif // FRAMEWORK_CHANNELCONFIGURATIONPOLICY_H +#endif // O2_FRAMEWORK_CHANNELCONFIGURATIONPOLICY_H_ diff --git a/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h b/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h index 5703cc3e902b1..ece802e0dd547 100644 --- a/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h +++ b/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h @@ -14,11 +14,13 @@ #include <functional> -namespace o2 -{ -namespace framework +namespace o2::framework { +struct FairMQChannelConfigSpec { + int64_t rateLogging; +}; + /// A set of helpers for common ChannelConfigurationPolicy behaviors struct ChannelConfigurationPolicyHelpers { // TODO: currently we allow matching of the policy only based on @@ -41,24 +43,23 @@ struct ChannelConfigurationPolicyHelpers { // Some trivial modifier which can be used by the policy. /// Makes the passed input channel connect and subscribe - static InputChannelModifier subscribeInput; + static InputChannelModifier subscribeInput(FairMQChannelConfigSpec const& spec); /// Makes the passed output channel bind and subscribe - static OutputChannelModifier publishOutput; + static OutputChannelModifier publishOutput(FairMQChannelConfigSpec const& spec); /// Makes the passed input channel connect and pull - static InputChannelModifier pullInput; + static InputChannelModifier pullInput(FairMQChannelConfigSpec const& spec); /// Makes the passed output channel bind and push - static OutputChannelModifier pushOutput; + static OutputChannelModifier pushOutput(FairMQChannelConfigSpec const& spec); /// Makes the passed input channel connect and request - static InputChannelModifier reqInput; + static InputChannelModifier reqInput(FairMQChannelConfigSpec const& spec); /// Makes the passed output channel bind and reply - static OutputChannelModifier replyOutput; + static OutputChannelModifier replyOutput(FairMQChannelConfigSpec const& spec); /// Makes the passed input channel connect and pair - static InputChannelModifier pairInput; + static InputChannelModifier pairInput(FairMQChannelConfigSpec const& spec); /// Makes the passed output channel bind and pair - static OutputChannelModifier pairOutput; + static OutputChannelModifier pairOutput(FairMQChannelConfigSpec const& spec); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif // FRAMEWORK_CHANNELCONFIGURATIONPOLICY_H +#endif // O2_FRAMEWORK_CHANNELCONFIGURATIONPOLICY_H_ diff --git a/Framework/Core/include/Framework/ChannelSpec.h b/Framework/Core/include/Framework/ChannelSpec.h index 7b9601722edab..d8fcb406c2258 100644 --- a/Framework/Core/include/Framework/ChannelSpec.h +++ b/Framework/Core/include/Framework/ChannelSpec.h @@ -7,14 +7,12 @@ // 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_CHANNELSPEC_H -#define FRAMEWORK_CHANNELSPEC_H +#ifndef O2_FRAMEWORK_CHANNELSPEC_H_ +#define O2_FRAMEWORK_CHANNELSPEC_H_ #include <string> -namespace o2 -{ -namespace framework +namespace o2::framework { /// These map to zeromq connection @@ -50,6 +48,7 @@ struct InputChannelSpec { std::string hostname; unsigned short port; ChannelProtocol protocol = ChannelProtocol::Network; + size_t rateLogging = 60; }; /// This describes an output channel. Output channels are semantically @@ -65,9 +64,9 @@ struct OutputChannelSpec { unsigned short port; size_t listeners; ChannelProtocol protocol = ChannelProtocol::Network; + size_t rateLogging = 60; }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework -#endif // FRAMEWORK_CHANNELSPEC_H +#endif // O2_FRAMEWORK_CHANNELSPEC_H_ diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 853735ff13f52..b9d347d3063e8 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -138,6 +138,8 @@ int main(int argc, char** argv) workflowOptions.push_back(ConfigParamSpec{"aod-writer-ntfmerge", VariantType::Int, -1, {"Number of time frames to merge into one file"}}); workflowOptions.push_back(ConfigParamSpec{"aod-writer-keep", VariantType::String, "", {"Comma separated list of ORIGIN/DESCRIPTION/SUBSPECIFICATION:treename:col1/col2/..:filename"}}); + workflowOptions.push_back(ConfigParamSpec{"fairmq-rate-logging", VariantType::Int, 60, {"Rate logging for FairMQ channels"}}); + workflowOptions.push_back(ConfigParamSpec{"forwarding-policy", VariantType::String, "dangling", @@ -150,10 +152,6 @@ int main(int argc, char** argv) {"Destination for forwarded messages." " file: write to file," " fairmq: send to output proxy"}}); - std::vector<ChannelConfigurationPolicy> channelPolicies; - UserCustomizationsHelper::userDefinedCustomization(channelPolicies, 0); - auto defaultChannelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); - channelPolicies.insert(std::end(channelPolicies), std::begin(defaultChannelPolicies), std::end(defaultChannelPolicies)); std::vector<CompletionPolicy> completionPolicies; UserCustomizationsHelper::userDefinedCustomization(completionPolicies, 0); @@ -178,6 +176,10 @@ int main(int argc, char** argv) for (auto& spec : specs) { UserCustomizationsHelper::userDefinedCustomization(spec.requiredServices, 0); } + std::vector<ChannelConfigurationPolicy> channelPolicies; + UserCustomizationsHelper::userDefinedCustomization(channelPolicies, 0); + auto defaultChannelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(configContext); + channelPolicies.insert(std::end(channelPolicies), std::begin(defaultChannelPolicies), std::end(defaultChannelPolicies)); result = doMain(argc, argv, specs, channelPolicies, completionPolicies, dispatchPolicies, workflowOptions, configContext); } catch (boost::exception& e) { doBoostException(e); diff --git a/Framework/Core/src/ChannelConfigurationPolicy.cxx b/Framework/Core/src/ChannelConfigurationPolicy.cxx index 1e7ad06d89b41..514cdc60f5fd3 100644 --- a/Framework/Core/src/ChannelConfigurationPolicy.cxx +++ b/Framework/Core/src/ChannelConfigurationPolicy.cxx @@ -9,20 +9,19 @@ // or submit itself to any jurisdiction. #include "Framework/ChannelConfigurationPolicy.h" +#include "Framework/ConfigContext.h" -namespace o2 -{ -namespace framework +namespace o2::framework { -std::vector<ChannelConfigurationPolicy> ChannelConfigurationPolicy::createDefaultPolicies() +std::vector<ChannelConfigurationPolicy> ChannelConfigurationPolicy::createDefaultPolicies(ConfigContext const& configContext) { ChannelConfigurationPolicy defaultPolicy; defaultPolicy.match = ChannelConfigurationPolicyHelpers::matchAny; - defaultPolicy.modifyInput = ChannelConfigurationPolicyHelpers::pullInput; - defaultPolicy.modifyOutput = ChannelConfigurationPolicyHelpers::pushOutput; + defaultPolicy.modifyInput = ChannelConfigurationPolicyHelpers::pullInput({configContext.options().get<int>("fairmq-rate-logging")}); + defaultPolicy.modifyOutput = ChannelConfigurationPolicyHelpers::pushOutput({configContext.options().get<int>("fairmq-rate-logging")}); + return {defaultPolicy}; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx b/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx index 3c33d1a612d1f..89dbfbe71f87d 100644 --- a/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx +++ b/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx @@ -13,9 +13,7 @@ #include <string> #include "Framework/ChannelSpec.h" -namespace o2 -{ -namespace framework +namespace o2::framework { ChannelConfigurationPolicyHelpers::PolicyMatcher ChannelConfigurationPolicyHelpers::matchAny = @@ -37,41 +35,58 @@ ChannelConfigurationPolicyHelpers::PolicyMatcher ChannelConfigurationPolicyHelpe return [nameString](std::string const&, std::string const& consumerId) -> bool { return consumerId == nameString; }; } -ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPolicyHelpers::subscribeInput = - [](InputChannelSpec& channel) { +ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPolicyHelpers::subscribeInput(FairMQChannelConfigSpec const& spec) +{ + return [spec](InputChannelSpec& channel) { channel.method = ChannelMethod::Connect; channel.type = ChannelType::Sub; + channel.rateLogging = spec.rateLogging; }; +} -ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPolicyHelpers::publishOutput = - [](OutputChannelSpec& channel) { +ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPolicyHelpers::publishOutput(FairMQChannelConfigSpec const& spec) +{ + return [spec](OutputChannelSpec& channel) { channel.method = ChannelMethod::Bind; channel.type = ChannelType::Pub; + channel.rateLogging = spec.rateLogging; }; +} -ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPolicyHelpers::pullInput = - [](InputChannelSpec& channel) { +ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPolicyHelpers::pullInput(FairMQChannelConfigSpec const& spec) +{ + return [spec](InputChannelSpec& channel) { channel.method = ChannelMethod::Connect; channel.type = ChannelType::Pull; + channel.rateLogging = spec.rateLogging; }; +} -ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPolicyHelpers::pushOutput = - [](OutputChannelSpec& channel) { +ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPolicyHelpers::pushOutput(FairMQChannelConfigSpec const& spec) +{ + return [spec](OutputChannelSpec& channel) { channel.method = ChannelMethod::Bind; channel.type = ChannelType::Push; + channel.rateLogging = spec.rateLogging; }; +} -ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPolicyHelpers::pairInput = - [](InputChannelSpec& channel) { +ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPolicyHelpers::pairInput(FairMQChannelConfigSpec const& spec) +{ + return [spec](InputChannelSpec& channel) { channel.method = ChannelMethod::Connect; channel.type = ChannelType::Pair; + channel.rateLogging = spec.rateLogging; }; +} -ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPolicyHelpers::pairOutput = - [](OutputChannelSpec& channel) { +ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPolicyHelpers::pairOutput(FairMQChannelConfigSpec const& spec) +{ + return [spec](OutputChannelSpec& channel) { channel.method = ChannelMethod::Bind; channel.type = ChannelType::Pair; + channel.rateLogging = spec.rateLogging; }; +} -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 56c1b8cefb743..cb4c76e217373 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -253,7 +253,7 @@ std::string DeviceSpecHelpers::inputChannel2String(const InputChannelSpec& chann result += std::string("type=") + ChannelSpecHelpers::typeAsString(channel.type); result += std::string(",method=") + ChannelSpecHelpers::methodAsString(channel.method); result += std::string(",address=") + ChannelSpecHelpers::channelUrl(channel); - result += std::string(",rateLogging=60"); + result += std::string(",rateLogging=" + std::to_string(channel.rateLogging)); return result; } @@ -268,7 +268,7 @@ std::string DeviceSpecHelpers::outputChannel2String(const OutputChannelSpec& cha result += std::string("type=") + ChannelSpecHelpers::typeAsString(channel.type); result += std::string(",method=") + ChannelSpecHelpers::methodAsString(channel.method); result += std::string(",address=") + ChannelSpecHelpers::channelUrl(channel); - result += std::string(",rateLogging=60"); + result += std::string(",rateLogging=" + std::to_string(channel.rateLogging)); return result; } diff --git a/Framework/Core/test/Mocking.h b/Framework/Core/test/Mocking.h new file mode 100644 index 0000000000000..1e62d8544b10c --- /dev/null +++ b/Framework/Core/test/Mocking.h @@ -0,0 +1,45 @@ +// 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 "test_HelperMacros.h" +#include "Framework/ConfigContext.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/SimpleOptionsRetriever.h" +#include "../src/WorkflowHelpers.h" + +using namespace o2::framework; + +std::unique_ptr<ConfigContext> makeEmptyConfigContext() +{ + // FIXME: Ugly... We need to fix ownership and make sure the ConfigContext + // either owns or shares ownership of the registry. + std::vector<std::unique_ptr<ParamRetriever>> retrievers; + static std::vector<ConfigParamSpec> specs = { + ConfigParamSpec{"forwarding-policy", + VariantType::String, + "dangling", + {""}}, + ConfigParamSpec{"forwarding-destination", + VariantType::String, + "file", + {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}, + ConfigParamSpec{"fairmq-rate-logging", + VariantType::Int, + 60, + {"rateLogging"}}, + }; + specs.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::String, "0", {"rate"}}); + auto store = std::make_unique<ConfigParamStore>(specs, std::move(retrievers)); + store->preload(); + store->activate(); + static ConfigParamRegistry registry(std::move(store)); + auto context = std::make_unique<ConfigContext>(registry, 0, nullptr); + return context; +} diff --git a/Framework/Core/test/test_DeviceSpec.cxx b/Framework/Core/test/test_DeviceSpec.cxx index de73b4c3c6322..78fa8949a97f6 100644 --- a/Framework/Core/test/test_DeviceSpec.cxx +++ b/Framework/Core/test/test_DeviceSpec.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Mocking.h" #include <boost/test/unit_test.hpp> #include "../src/ChannelSpecHelpers.h" #include "../src/DeviceSpecHelpers.h" @@ -40,7 +41,8 @@ WorkflowSpec defineDataProcessing1() BOOST_AUTO_TEST_CASE(TestDeviceSpec1) { auto workflow = defineDataProcessing1(); - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); BOOST_REQUIRE_EQUAL(channelPolicies.empty(), false); BOOST_REQUIRE_EQUAL(completionPolicies.empty(), false); @@ -80,10 +82,11 @@ BOOST_AUTO_TEST_CASE(TestDeviceSpec1PushPull) auto workflow = defineDataProcessing1(); ChannelConfigurationPolicy pushPullPolicy; pushPullPolicy.match = ChannelConfigurationPolicyHelpers::matchAny; - pushPullPolicy.modifyInput = ChannelConfigurationPolicyHelpers::pullInput; - pushPullPolicy.modifyOutput = ChannelConfigurationPolicyHelpers::pushOutput; + pushPullPolicy.modifyInput = ChannelConfigurationPolicyHelpers::pullInput({60}); + pushPullPolicy.modifyOutput = ChannelConfigurationPolicyHelpers::pushOutput({60}); std::vector<ChannelConfigurationPolicy> channelPolicies = {pushPullPolicy}; + auto configContext = makeEmptyConfigContext(); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); BOOST_REQUIRE_EQUAL(channelPolicies.empty(), false); @@ -128,7 +131,8 @@ WorkflowSpec defineDataProcessing2() BOOST_AUTO_TEST_CASE(TestDeviceSpec2) { auto workflow = defineDataProcessing2(); - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<DeviceSpec> devices; @@ -170,7 +174,8 @@ WorkflowSpec defineDataProcessing3() BOOST_AUTO_TEST_CASE(TestDeviceSpec3) { auto workflow = defineDataProcessing3(); - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<DeviceSpec> devices; @@ -218,7 +223,8 @@ WorkflowSpec defineDataProcessing4() BOOST_AUTO_TEST_CASE(TestDeviceSpec4) { auto workflow = defineDataProcessing4(); - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<DeviceSpec> devices; std::vector<ComputingResource> resources{ComputingResourceHelpers::getLocalhostResource()}; @@ -287,7 +293,8 @@ WorkflowSpec defineDataProcessing5() BOOST_AUTO_TEST_CASE(TestTopologyForwarding) { auto workflow = defineDataProcessing5(); - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<DeviceSpec> devices; @@ -404,7 +411,8 @@ BOOST_AUTO_TEST_CASE(TestOutEdgeProcessingHelpers) }; WorkflowSpec workflow = defineDataProcessing7(); - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); std::vector<ComputingResource> resources{ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); @@ -566,7 +574,8 @@ BOOST_AUTO_TEST_CASE(TestTopologyLayeredTimePipeline) { auto workflow = defineDataProcessing7(); std::vector<DeviceSpec> devices; - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<ComputingResource> resources{ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); @@ -690,7 +699,8 @@ BOOST_AUTO_TEST_CASE(TestSimpleWildcard) auto workflow = defineDataProcessing8(); std::vector<ComputingResource> resources{ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); std::vector<DeviceSpec> devices; std::vector<DeviceId> deviceIndex; diff --git a/Framework/Core/test/test_DeviceSpecHelpers.cxx b/Framework/Core/test/test_DeviceSpecHelpers.cxx index df953aab44dca..f7790c3642ab9 100644 --- a/Framework/Core/test/test_DeviceSpecHelpers.cxx +++ b/Framework/Core/test/test_DeviceSpecHelpers.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Mocking.h" #include "Framework/WorkflowSpec.h" #include "Framework/DataProcessorSpec.h" #include "Framework/DeviceExecution.h" @@ -136,8 +137,10 @@ BOOST_AUTO_TEST_CASE(test_prepareArguments) std::vector<ComputingResource> resources = {ComputingResourceHelpers::getLocalhostResource()}; auto rm = std::make_unique<SimpleResourceManager>(resources); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(workflow, - ChannelConfigurationPolicy::createDefaultPolicies(), + channelPolicies, CompletionPolicy::createDefaultPolicies(), deviceSpecs, *rm, "workflow-id"); diff --git a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx index 2b03b3a0cc5e3..4d74400fe15d0 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Mocking.h" #include <boost/test/unit_test.hpp> #include "../src/DDSConfigHelpers.h" #include "../src/DeviceSpecHelpers.h" @@ -69,7 +70,8 @@ BOOST_AUTO_TEST_CASE(TestDDS) { auto workflow = defineDataProcessing(); std::ostringstream ss{""}; - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); std::vector<DeviceSpec> devices; std::vector<ComputingResource> resources{ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); diff --git a/Framework/Core/test/test_Graphviz.cxx b/Framework/Core/test/test_Graphviz.cxx index 262c104714900..3345b7c400e38 100644 --- a/Framework/Core/test/test_Graphviz.cxx +++ b/Framework/Core/test/test_Graphviz.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Mocking.h" #include "../src/ComputingResourceHelpers.h" #include "../src/DeviceSpecHelpers.h" #include "../src/GraphvizHelpers.h" @@ -95,7 +96,8 @@ BOOST_AUTO_TEST_CASE(TestGraphviz) for (auto& device : devices) { BOOST_CHECK(device.id != ""); } - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<ComputingResource> resources = {ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); @@ -133,7 +135,8 @@ BOOST_AUTO_TEST_CASE(TestGraphvizWithPipeline) for (auto& device : devices) { BOOST_CHECK(device.id != ""); } - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<ComputingResource> resources = {ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); diff --git a/Framework/Core/test/test_TimeParallelPipelining.cxx b/Framework/Core/test/test_TimeParallelPipelining.cxx index 07b4113f5faa9..6f9123e5d59db 100644 --- a/Framework/Core/test/test_TimeParallelPipelining.cxx +++ b/Framework/Core/test/test_TimeParallelPipelining.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Mocking.h" #include <boost/test/unit_test.hpp> #include "../src/DeviceSpecHelpers.h" #include "../src/SimpleResourceManager.h" @@ -52,7 +53,8 @@ BOOST_AUTO_TEST_CASE(TimePipeliningSimple) { auto workflow = defineSimplePipelining(); std::vector<DeviceSpec> devices; - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<ComputingResource> resources = {ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); @@ -104,7 +106,8 @@ BOOST_AUTO_TEST_CASE(TimePipeliningFull) { auto workflow = defineDataProcessing(); std::vector<DeviceSpec> devices; - auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto completionPolicies = CompletionPolicy::createDefaultPolicies(); std::vector<ComputingResource> resources = {ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); diff --git a/Framework/Core/test/test_WorkflowHelpers.cxx b/Framework/Core/test/test_WorkflowHelpers.cxx index cd0fe6ddadf5d..174d915b0c8c9 100644 --- a/Framework/Core/test/test_WorkflowHelpers.cxx +++ b/Framework/Core/test/test_WorkflowHelpers.cxx @@ -11,6 +11,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK +#include "Mocking.h" #include "test_HelperMacros.h" #include "Framework/ConfigContext.h" #include "Framework/WorkflowSpec.h" @@ -24,30 +25,6 @@ using namespace o2::framework; -std::unique_ptr<ConfigContext> makeEmptyConfigContext() -{ - // FIXME: Ugly... We need to fix ownership and make sure the ConfigContext - // either owns or shares ownership of the registry. - std::vector<std::unique_ptr<ParamRetriever>> retrievers; - static std::vector<ConfigParamSpec> specs = { - ConfigParamSpec{"forwarding-policy", - VariantType::String, - "dangling", - {""}}, - ConfigParamSpec{"forwarding-destination", - VariantType::String, - "file", - {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}, - }; - specs.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::String, "0", {"rate"}}); - auto store = std::make_unique<ConfigParamStore>(specs, std::move(retrievers)); - store->preload(); - store->activate(); - static ConfigParamRegistry registry(std::move(store)); - auto context = std::make_unique<ConfigContext>(registry, 0, nullptr); - return context; -} - BOOST_AUTO_TEST_CASE(TestVerifyWorkflow) { using namespace o2::framework; From b1911e8be884c6b653d3c38966aee012beb3289f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 09:33:51 +0100 Subject: [PATCH 1540/1751] Add option to suppress FMQ rate logging in full system test --- prodtests/full-system-test/dpl-workflow.sh | 3 +++ prodtests/full-system-test/raw-reader.sh | 7 +++++-- prodtests/full-system-test/setenv.sh | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index db01f96c0c12c..5180b47a397b3 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -15,6 +15,9 @@ fi if [ $SHMTHROW == 0 ]; then ARGS_ALL+=" --shm-throw-bad-alloc 0" fi +if [ $NORATELOG == 1 ]; then + ARGS_ALL+=" --fairmq-rate-logging 0" +fi if [ $EXTINPUT == 1 ]; then CMD_X="B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA;G:EMC/RAWDATA;H:PHS/RAWDATA" diff --git a/prodtests/full-system-test/raw-reader.sh b/prodtests/full-system-test/raw-reader.sh index cc17f5d607b95..466b30bab4a50 100755 --- a/prodtests/full-system-test/raw-reader.sh +++ b/prodtests/full-system-test/raw-reader.sh @@ -8,12 +8,15 @@ fi MYDIR="$(dirname $(readlink -f $0))" source $MYDIR/setenv.sh -ARGS_ALL="--session default --severity $SEVERITY --shm-throw-bad-alloc 0 --no-cleanup" +ARGS_ALL="--session default --shm-throw-bad-alloc 0 --no-cleanup" if [ $NUMAGPUIDS == 1 ]; then TMPSIZE=$(expr $DDSHMSIZE \* 1024 \* 1024) ARGS_ALL+=" --shm-segment-id 2 --shm-segment-size $TMPSIZE --shm-mlock-segment 1 --shm-zero-segment 1" else ARGS_ALL+=" --shm-segment-size $SHMSIZE" fi +if [ $NORATELOG == 1 ]; then + ARGS_ALL+=" --fairmq-rate-logging 0" +fi -o2-raw-file-reader-workflow $ARGS_ALL --loop $NTIMEFRAMES --delay $TFDELAY --input-conf rawAll.cfg --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF;" --max-tf 0 --raw-channel-config "name=dpl-chan,type=push,method=bind,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0" --run +o2-raw-file-reader-workflow $ARGS_ALL --loop $NTIMEFRAMES --delay $TFDELAY --input-conf rawAll.cfg --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF;" --max-tf 0 --raw-channel-config "name=dpl-chan,type=push,method=bind,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0" $GLOBALDPLOPT --run diff --git a/prodtests/full-system-test/setenv.sh b/prodtests/full-system-test/setenv.sh index 53feeb0f7c5af..b42b33d2e8fec 100755 --- a/prodtests/full-system-test/setenv.sh +++ b/prodtests/full-system-test/setenv.sh @@ -25,6 +25,7 @@ if [ -z "$GLOBALDPLOPT" ]; then export GLOBALDPLOPT=; fi # Global if [ -z "$EPNPIPELINES" ]; then export EPNPIPELINES=0; fi # Set default EPN pipeline multiplicities if [ -z "$SEVERITY" ]; then export SEVERITY="info"; fi # Log verbosity if [ -z "$SHMTHROW" ]; then export SHMTHROW=1; fi # Throw exception when running out of SHM +if [ -z "$NORATELOG" ]; then export NORATELOG=1; fi # Disable FairMQ Rate Logging SEVERITY_TPC="info" # overrides severity for the tpc workflow DISABLE_MC="--disable-mc" From 41747c1a96b509c6c39e7a850d11aa24ec0df8bd Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 10:56:59 +0100 Subject: [PATCH 1541/1751] Add documentation for full system test scripts --- prodtests/full-system-test/README.md | 66 ++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 prodtests/full-system-test/README.md diff --git a/prodtests/full-system-test/README.md b/prodtests/full-system-test/README.md new file mode 100644 index 0000000000000..9f918b9b1796d --- /dev/null +++ b/prodtests/full-system-test/README.md @@ -0,0 +1,66 @@ +## Full system test configuration and scripts + +The full system test workflow scripts consist of 3 shell scripts: +* `dpl-workflow.sh` : The main script that runs the dpl-workflow for the reconstruction. + It can read the input either internally, or receive it externally by one of the others. +* `raw-reader.sh` : Runs the `o2-raw-file-reader` to read the raw files as external input to `dpl-workflow.sh`. +* `datadistribution.sh` : Run the `StfBuilder` to read time frame files as external input to `dpl-workflow.sh`. + +One can either run the `dpl-workflow.sh` standalone (with `EXTINPUT=0`) or in parallel with one of the other scripts in separate shells (with `EXTINPUT=1`) + +In addition, there is the shared `setenv.sh` script which sets default configuration options, and there is the additional benchmark script: +* `start_tmux.sh` : This starts the full test in the configuration for the EPN with 2 NUMA domains, 512 GB RAM, 8 GPUs. + It will run tmux with 3 sessions, running twice the `dpl-workflow.sh` and once one of the external input scripts (selected via `dd` and `rr` command line option). + * Please note that `start_tmux.sh` overrides several of the environment options (see below) with the defaults for the EPN. + The only relevant options for `start_tmux.sh` should be `TFDELAY` and `GPUMEMSIZE`. + * Note also that while `dpl-workflow.sh` is a generic flexible script that can be used for actual operation, `start_tmux.sh` is a benchmark script to demonstrate how the full workflow is supposed to run on the EPN. + It is meant for standalone tests and not to really start the actual processing on the EPN. + +The `dpl-workflow.sh` can run both the synchronous and the asynchronous workflow, selected via the `SYNCMODE` option (see below), but note the following constraints. +* By default, it will run the full chain (EPN + FLP parts) such that it can operate as a full standalone benchmark processing simulated raw data. +* In order to run only the EPN part (skipping the steps that will run on the FLP), an `EPNONLY` option will be added later. + +All settings are configured via environment variables. +The default settings (if no env variable is exported) are defined in `setenv.sh` which is sourced by all other scripts. +(Please note that `start_tmux.sh` overrides a couple of options with EPN defaults). +The following options exist (some of the options are not used in all scripts, and might behave slightly differently as noted): +* `NTIMEFRAMES`: Number of time frames to process. + * `dpl-workflow.sh` without `EXTINPUT`: Will replay the timeframe `NTIMEFRAMES` time and then exit. + * `raw-reader.sh` : Will replay the timeframe `NTIMEFRAMES` time and `raw-reader.sh` will exit, the dpl-workflows will keep running. + * Ignored by `datadistribution.sh`, it will always run in an endless loop. +* `TFDELAY`: Delay in seconds between publishing time frames (1 / rate). +* `NGPUS`: Number of GPUs to use, data distributed round-robin. +* `GPUTYPE`: GPU Tracking backend to use, can be CPU / CUDA / HIP / OCL / OCL2. +* `SHMSIZE`: Size of the global shared memory segment. +* `DDSHMSIZE`: Size of shared memory unmanaged region for DataDistribution Input. +* `GPUMEMSIZE`: Size of allocated GPU memory (if GPUTYPE != CPU) +* `HOSTMEMSIZE`: Size of allocated host memory for GPU reconstruction (0 = default). + * For `GPUTYPE = CPU`: TPC Tracking scratch memory size. (Default 0 -> dynamic allocation.) + * Otherwise : Size of page-locked host memory for GPU processing. (Defauls 0 -> 1 GB.) +* `CREATECTFDICT`: Create CTF dictionary. + * 0: Read `ctf_dictionary.root` as input. + * 1: Create `ctf_dictionary.root`. Note that this was already done automatically if the raw data was simulated with `full_system_test.sh`. +* `SYNCMODE`: Run only reconstruction steps of the synchronous reconstruction. +* `NUMAGPUIDS`: NUMAID-aware GPU id selection. Needed for the full EPN configuration with 8 GPUs, 2 NUMA domains, 4 GPUs per domain. + In this configuration, 2 instances of `dpl-workflow.sh` must run in parallel. + To be used in combination with `NUMAID` to select the id per workflow. + `start_tmux.sh` will set up these variables automatically. +* `NUMAID`: SHM segment id to use for shipping data as well as set of GPUs to use (use `0` / `1` for 2 NUMA domains, 0 = GPUS `0` to `NGPUS - 1`, 1 = GPUS `NGPUS` to `2 * NGPUS - 1`) +* 0: Runs all reconstruction steps, of sync and of async reconstruction, using raw data input. +* 1: Runs only the steps of synchronous reconstruction, using raw data input. +* `EXTINPUT`: Receive input from raw FMQ channel instead of running o2-raw-file-reader. + * 0: `dpl-workflow.sh` can run as standalone benchmark, and will read the input itself. + * 1: To be used in combination with either `datadistribution.sh` or `raw-reader.sh` or with another DataDistribution instance. +* `NHBPERTF`: Time frame length (in HBF) +* `GLOBALDPLOPT`: Global DPL workflow options appended to o2-dpl-run. +* `EPNPIPELINES`: Set default EPN pipeline multiplicities. + Normally the workflow will start 1 dpl device per processor. + For some of the CPU parts, this is insufficient to keep step with the GPU processing rate, e.g. one ITS-TPC matcher on the CPU is slower than the TPC tracking on multiple GPUs. + This option adds some multiplicies for CPU processes using DPL's pipeline feature. + The settings were tuned for EPN processing with 8 GPUs. + It is auto-selected by `start-tmux.sh`. +* `SEVERITY`: Log verbosity (e.g. info or error) +* `SHMTHROW`: Throw exception when running out of SHM memory. + It is suggested to leave this enabled (default) on tests on the laptop to get an actual error when it runs out of memory. + This is disabled in `start_tmux.sh`, to avoid breaking the processing while there is a chance that another process might free memory and we can continue. +* `NORATELOG`: Disable FairMQ Rate Logging. From cbce528ea4bb8696a3ceb455c21f22b0efb7643e Mon Sep 17 00:00:00 2001 From: Ivana Hrivnacova <Ivana.Hrivnacova@cern.ch> Date: Fri, 4 Dec 2020 15:26:13 +0100 Subject: [PATCH 1542/1751] Updates in Doxygen: (#5005) - Disabled class diagrams generation in the default Doxygen configuration file and added doxyfile-with-graphs.in with class diagrams generation kept - Added doxygen keywords where missing to avoid low level documentation pages in the top level --- Detectors/DCS/README.md | 4 + Detectors/DCS/testWorkflow/README.md | 4 + Detectors/FIT/README.md | 1 + Detectors/FIT/raw/README.md | 4 + Detectors/README.md | 2 + Detectors/Upgrades/IT3/README.md | 4 + Detectors/Upgrades/PostLS4/IT4/README.md | 4 + Detectors/Upgrades/README.md | 8 +- Utilities/DataSampling/README.md | 4 + Utilities/README.md | 1 + doc/README.md | 1 + doc/doxyfile-with-graphs.in | 313 +++++++++++++++++++++++ doc/doxyfile.in | 4 +- prodtests/full-system-test/README.md | 4 + 14 files changed, 352 insertions(+), 6 deletions(-) create mode 100644 doc/doxyfile-with-graphs.in diff --git a/Detectors/DCS/README.md b/Detectors/DCS/README.md index 13cf1eebe53b2..16a2044e44a3f 100644 --- a/Detectors/DCS/README.md +++ b/Detectors/DCS/README.md @@ -18,3 +18,7 @@ auto dps = o2::dcs::generateRandomDataPoints(patterns,0.0,1200.0); ``` would generate 420 data points. + +<!-- doxy +* \subpage refDetectorsDCStestWorkflow +/doxy --> diff --git a/Detectors/DCS/testWorkflow/README.md b/Detectors/DCS/testWorkflow/README.md index 2c4b879ab56eb..b00847e3f7761 100644 --- a/Detectors/DCS/testWorkflow/README.md +++ b/Detectors/DCS/testWorkflow/README.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refDetectorsDCStestWorkflow testWorkflow +/doxy --> + Local example workflow with local CCDB (running on port 6464) : ```shell diff --git a/Detectors/FIT/README.md b/Detectors/FIT/README.md index 87c8647513541..49ca9ba65e85b 100644 --- a/Detectors/FIT/README.md +++ b/Detectors/FIT/README.md @@ -9,4 +9,5 @@ This is a top page for the FIT detector documentation. <!-- doxy * \subpage refFITbenchmark * \subpage refFITFT0workflow +* \subpage refFITraw /doxy --> diff --git a/Detectors/FIT/raw/README.md b/Detectors/FIT/raw/README.md index dbc0c741e7c41..723ce05581370 100644 --- a/Detectors/FIT/raw/README.md +++ b/Detectors/FIT/raw/README.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refFITraw FIT raw +/doxy --> + # DataBlockBase DataBlockWrapper - wrapper for raw data structures\ There should be three static fields in raw data structs, which defines its "signature":\ diff --git a/Detectors/README.md b/Detectors/README.md index 89114fd394a66..b3d4bdbfc8e83 100644 --- a/Detectors/README.md +++ b/Detectors/README.md @@ -18,6 +18,7 @@ This module contains the following submodules: * \subpage refDetectorsCalibration * \subpage refDetectorsCPV * \subpage refDetectorsCTF +* \subpage refDetectorsDCS * \subpage refDetectorsEMCAL * \subpage refDetectorsDCS * \subpage refDetectorsFIT @@ -29,5 +30,6 @@ This module contains the following submodules: * \subpage refDetectorsTOF * \subpage refDetectorsTPC * \subpage refDetectorsTRD +* \subpage refDetectorsUpgrades * \subpage refDetectorsZDC /doxy --> diff --git a/Detectors/Upgrades/IT3/README.md b/Detectors/Upgrades/IT3/README.md index 3d57a976c41fa..9a4d82a533edb 100644 --- a/Detectors/Upgrades/IT3/README.md +++ b/Detectors/Upgrades/IT3/README.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refDetectorsUpgradesIT3 UpgradesIT3 +/doxy --> + # IT3 Upgraded version of the ITS that includes upgraded truly-cylindrical inner barrel. diff --git a/Detectors/Upgrades/PostLS4/IT4/README.md b/Detectors/Upgrades/PostLS4/IT4/README.md index 672f26326d8e1..02b76227f1a71 100644 --- a/Detectors/Upgrades/PostLS4/IT4/README.md +++ b/Detectors/Upgrades/PostLS4/IT4/README.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refDetectorsUpgradesPostLS4IT4 UpgradesIT4 +/doxy --> + # IT4 At the moment the IT4 name is a placeholder for barrel detector. diff --git a/Detectors/Upgrades/README.md b/Detectors/Upgrades/README.md index c71db05187e1e..ecead5da1a376 100644 --- a/Detectors/Upgrades/README.md +++ b/Detectors/Upgrades/README.md @@ -1,5 +1,5 @@ <!-- doxy -\page refDetectorsITSMFT ITSMFT +\page refDetectorsUpgrades Upgrades /doxy --> # Upgrades @@ -14,6 +14,6 @@ ENABLE_UPGRADES=ON aliBuild build O2 --defaults o2 ``` <!-- doxy -* \subpage refIT3 -* \subpage refPostLS4 -/doxy --> \ No newline at end of file +* \subpage refDetectorsUpgradesIT3 +* \subpage refDetectorsUpgradesPostLS4IT4 +/doxy --> diff --git a/Utilities/DataSampling/README.md b/Utilities/DataSampling/README.md index b417f83beee2c..104890f06ceb8 100644 --- a/Utilities/DataSampling/README.md +++ b/Utilities/DataSampling/README.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refUtilitiesDataSampling Data Sampling +/doxy --> + ## Data Sampling Data Sampling provides a possibility to sample data in DPL workflows based on certain conditions ( 5% randomly, when a 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) or by using dedicated interface methods (for advanced use). diff --git a/Utilities/README.md b/Utilities/README.md index 026a778c559b1..48e1bfbb91473 100644 --- a/Utilities/README.md +++ b/Utilities/README.md @@ -11,6 +11,7 @@ This module contains the following submodules: * \subpage refUtilitiesDataCompression * \subpage refUtilitiesDataFlow +* \subpage refUtilitiesDataSampling * \subpage refUtilitiesMCStepLogger * \subpage refUtilitiesMergers * \subpage refUtilitiesO2Device diff --git a/doc/README.md b/doc/README.md index b699306179b00..68520ab356009 100644 --- a/doc/README.md +++ b/doc/README.md @@ -15,4 +15,5 @@ This module contains the documentation pages. * \subpage refdocDoxygenInstructions * \subpage refdocManPages * \subpage refdocUpgrades +* \subpage refprodtestsfull-system-test /doxy --> diff --git a/doc/doxyfile-with-graphs.in b/doc/doxyfile-with-graphs.in new file mode 100644 index 0000000000000..d60d01d5bcb59 --- /dev/null +++ b/doc/doxyfile-with-graphs.in @@ -0,0 +1,313 @@ +# Doxyfile 1.8.8 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = @PROJECT_NAME@ +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = "@CMAKE_SOURCE_DIR@/doc/images/o2_logo.png" +OUTPUT_DIRECTORY = "@DOC_OUTPUT_DIR@" +CREATE_SUBDIRS = YES +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 2 +ALIASES = +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +TOC_INCLUDE_HEADINGS = 0 +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = YES +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = "@CMAKE_SOURCE_DIR@" +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.cxx *.h *.inl *.md +RECURSIVE = YES +EXCLUDE = .git/ \ + build/ \ + build-dir/ \ + html-docs/ \ + doxygen cmake config gconfig geometry input parameters .svn vis +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = G__* ClassImp build_* +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = @CMAKE_SOURCE_DIR@/doc/scripts/filter_for_doxygen.sh +FILTER_PATTERNS = *.md +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/README.md +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = .git +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = YES +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +DIA_PATH = +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = YES +DOT_NUM_THREADS = 1 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = YES +UML_LIMIT_NUM_FIELDS = 50 +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = svg +INTERACTIVE_SVG = YES +DOT_PATH = "@DOT_PATH@" +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +DOT_GRAPH_MAX_NODES = 100 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = YES +DOT_MULTI_TARGETS = YES +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/doc/doxyfile.in b/doc/doxyfile.in index d60d01d5bcb59..08b7d37770b20 100644 --- a/doc/doxyfile.in +++ b/doc/doxyfile.in @@ -278,10 +278,10 @@ EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES +CLASS_DIAGRAMS = NO DIA_PATH = HIDE_UNDOC_RELATIONS = NO -HAVE_DOT = YES +HAVE_DOT = NO DOT_NUM_THREADS = 1 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 diff --git a/prodtests/full-system-test/README.md b/prodtests/full-system-test/README.md index 9f918b9b1796d..02da768bcc020 100644 --- a/prodtests/full-system-test/README.md +++ b/prodtests/full-system-test/README.md @@ -1,3 +1,7 @@ +<!-- doxy +\page refprodtestsfull-system-test Full system test configuration and scripts +/doxy --> + ## Full system test configuration and scripts The full system test workflow scripts consist of 3 shell scripts: From 648018b1504bda85f481ceb25ed0591f818b9519 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 4 Dec 2020 21:57:49 +0400 Subject: [PATCH 1543/1751] Fix in accounting cached V0 --- Detectors/Vertexing/src/SVertexer.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index b6e8a52e1af05..1287ad4abab01 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -169,7 +169,7 @@ void SVertexer::process(const gsl::span<const PVertex>& vertices, // primary v // check cos of pointing angle float dz = v0pos[2] - pv.getZ(), cosPointingAngle = (prodXY + dz * pV0[2]) / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); if (cosPointingAngle < mMinCosPointingAngle) { - if (ambiguousV0) { + if (!ambiguousV0) { continue; // no need to check this pair wrt other vertices } cosPointingAngle = mMinCosPointingAngle - 1e-6; @@ -203,6 +203,7 @@ void SVertexer::process(const gsl::span<const PVertex>& vertices, // primary v if (cosPointingAngle > v0.getCosPA()) { // reassign v0.setCosPA(cosPointingAngle); v0.setVertexID(iv); + v0sIdx.push_back(*resPair); pvrefs.changeEntriesBy(1); } } From 2b885a2594ff893f16d8bed768179d1256d3fb62 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 4 Dec 2020 22:05:47 +0400 Subject: [PATCH 1544/1751] Check CTFdict existence before trying to load --- Detectors/Base/src/CTFCoderBase.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/Base/src/CTFCoderBase.cxx b/Detectors/Base/src/CTFCoderBase.cxx index a5e7ff0ed92e8..433cafb8f0883 100644 --- a/Detectors/Base/src/CTFCoderBase.cxx +++ b/Detectors/Base/src/CTFCoderBase.cxx @@ -14,6 +14,7 @@ #include "DetectorsCommonDataFormats/CTFHeader.h" #include "DetectorsBase/CTFCoderBase.h" +#include "TSystem.h" using namespace o2::ctf; @@ -34,7 +35,7 @@ bool readFromTree(TTree& tree, const std::string brname, T& dest, int ev = 0) std::unique_ptr<TFile> CTFCoderBase::loadDictionaryTreeFile(const std::string& dictPath, bool mayFail) { TDirectory* curd = gDirectory; - std::unique_ptr<TFile> fileDict(TFile::Open(dictPath.c_str())); + std::unique_ptr<TFile> fileDict(gSystem->AccessPathName(dictPath.c_str()) ? nullptr : TFile::Open(dictPath.c_str())); if (!fileDict || fileDict->IsZombie()) { if (mayFail) { LOG(INFO) << "CTF dictionary file " << dictPath << " for detector " << mDet.getName() << " is absent, will use dictionaries stored in CTF"; From b763b94600491461558ca300566af6c4e4b486f6 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 14:05:33 +0100 Subject: [PATCH 1545/1751] Add option to ctf writer to store both dictionary and ctf or none --- Detectors/CTF/workflow/src/ctf-writer-workflow.cxx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx index 4bac58ca64966..1ff74331c51a2 100644 --- a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx @@ -30,7 +30,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) options.push_back(ConfigParamSpec{"onlyDet", VariantType::String, std::string{DetID::NONE}, {"comma separated list of detectors to accept. Overrides skipDet"}}); options.push_back(ConfigParamSpec{"skipDet", VariantType::String, std::string{DetID::NONE}, {"comma separate list of detectors to skip"}}); options.push_back(ConfigParamSpec{"grpfile", VariantType::String, o2::base::NameConf::getGRPFileName(), {"name of the grp file"}}); - options.push_back(ConfigParamSpec{"output-type", VariantType::String, "ctf", {"output types: ctf (per TF) or dict (create dictionaries)"}}); + options.push_back(ConfigParamSpec{"output-type", VariantType::String, "ctf", {"output types: ctf (per TF) or dict (create dictionaries) or both or none"}}); std::swap(workflowOptions, options); } @@ -52,6 +52,14 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } else if (outmode == "dict") { doCTF = false; doDict = true; + } else if (outmode == "both") { + doCTF = true; + doDict = true; + } else if (outmode == "none") { + doCTF = false; + doDict = false; + } else { + throw std::invalid_argument("Invalid output-type"); } run = grp->getRun(); } From 28c85c0867a0d884fac253d0c8579833417f668a Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 21:45:50 +0100 Subject: [PATCH 1546/1751] Fix another EMCAL out of bounds error --- Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx index 38446717e0c79..6d91dca6f21e5 100644 --- a/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx @@ -81,7 +81,7 @@ void AltroDecoder::readChannels() // decode bunches int currentsample = 0; - while (currentsample < currentchannel.getPayloadSize() && bunchwords.size() > currentsample) { + while (currentsample < currentchannel.getPayloadSize() && bunchwords.size() > currentsample + 2) { int bunchlength = bunchwords[currentsample] - 2, // remove words for bunchlength and starttime starttime = bunchwords[currentsample + 1]; auto& currentbunch = currentchannel.createBunch(bunchlength, starttime); From 378e6bf8c4e19a4bbe9ae54981e987e779f63e37 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 4 Dec 2020 21:55:25 +0100 Subject: [PATCH 1547/1751] DPL: drop "using namespace" at top-level (#5006) --- Framework/Core/include/Framework/ASoA.h | 4 +--- Framework/Core/include/Framework/DataInputDirector.h | 10 +++------- Framework/Core/include/Framework/DataOutputDirector.h | 7 ++----- Framework/Core/test/Mocking.h | 5 ++--- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index e57c7a08eaec8..7fe30dbdafb89 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -27,8 +27,6 @@ #include <cassert> #include <fmt/format.h> -using o2::framework::runtime_error_f; - namespace o2::soa { template <typename... C> @@ -1091,7 +1089,7 @@ class Table auto label = T::columnLabel(); auto index = mTable->schema()->GetAllFieldIndices(label); if (index.empty() == true) { - throw runtime_error_f("Unable to find column with label %s", label); + throw o2::framework::runtime_error_f("Unable to find column with label %s", label); } return mTable->column(index[0]).get(); } else { diff --git a/Framework/Core/include/Framework/DataInputDirector.h b/Framework/Core/include/Framework/DataInputDirector.h index a059dafa8348d..1a7a3e5af5ee1 100644 --- a/Framework/Core/include/Framework/DataInputDirector.h +++ b/Framework/Core/include/Framework/DataInputDirector.h @@ -18,11 +18,8 @@ #include <regex> #include "rapidjson/fwd.h" -namespace o2 +namespace o2::framework { -namespace framework -{ -using namespace rapidjson; struct FileNameHolder { std::string fileName; @@ -130,11 +127,10 @@ struct DataInputDirector { bool mDebugMode = false; bool mAlienSupport = false; - bool readJsonDocument(Document* doc); + bool readJsonDocument(rapidjson::Document* doc); bool isValid(); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif // o2_framework_DataInputDirector_H_INCLUDED diff --git a/Framework/Core/include/Framework/DataOutputDirector.h b/Framework/Core/include/Framework/DataOutputDirector.h index 4cf2fa13ad6b7..edf3cdb0f082f 100644 --- a/Framework/Core/include/Framework/DataOutputDirector.h +++ b/Framework/Core/include/Framework/DataOutputDirector.h @@ -20,9 +20,7 @@ #include "rapidjson/fwd.h" -namespace o2 -{ -namespace framework +namespace o2::framework { using namespace rapidjson; @@ -105,7 +103,6 @@ struct DataOutputDirector { const std::tuple<std::string, std::string, int> memptyanswer = std::make_tuple(std::string(""), std::string(""), -1); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif // o2_framework_DataOutputDirector_H_INCLUDED diff --git a/Framework/Core/test/Mocking.h b/Framework/Core/test/Mocking.h index 1e62d8544b10c..c89b324910fa0 100644 --- a/Framework/Core/test/Mocking.h +++ b/Framework/Core/test/Mocking.h @@ -14,10 +14,9 @@ #include "Framework/SimpleOptionsRetriever.h" #include "../src/WorkflowHelpers.h" -using namespace o2::framework; - -std::unique_ptr<ConfigContext> makeEmptyConfigContext() +std::unique_ptr<o2::framework::ConfigContext> makeEmptyConfigContext() { + using namespace o2::framework; // FIXME: Ugly... We need to fix ownership and make sure the ConfigContext // either owns or shares ownership of the registry. std::vector<std::unique_ptr<ParamRetriever>> retrievers; From b0ba16b6ecf76c4c041e56a792e4b5d4bd64e43e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 14:42:51 +0100 Subject: [PATCH 1548/1751] Bugfix: disable emcal workflow's root output (enabled by default) in full system test --- prodtests/full-system-test/dpl-workflow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 5180b47a397b3..b9fd621567a4f 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -96,7 +96,7 @@ $CMD_MID | \ o2-mid-entropy-encoder-workflow $ARGS_ALL | \ o2-phos-reco-workflow $ARGS_ALL --input-type raw --output-type cells | \ o2-phos-entropy-encoder-workflow $ARGS_ALL |\ -o2-emcal-reco-workflow $ARGS_ALL --input-type raw --output-type cells | \ +o2-emcal-reco-workflow $ARGS_ALL --input-type raw --output-type cells --disable-root-output | \ o2-emcal-entropy-encoder-workflow $ARGS_ALL |\ o2-tof-compressor $ARGS_ALL | \ o2-tof-reco-workflow $ARGS_ALL --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output $DISABLE_MC | \ From c1f05c0d3d0891fcb21fccbb92794e6f0fbe4a88 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 14:43:14 +0100 Subject: [PATCH 1549/1751] Add option to store CTF after full system test --- prodtests/full-system-test/README.md | 1 + prodtests/full-system-test/dpl-workflow.sh | 13 ++++++++----- prodtests/full-system-test/setenv.sh | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/prodtests/full-system-test/README.md b/prodtests/full-system-test/README.md index 02da768bcc020..c5f1f4ff4268e 100644 --- a/prodtests/full-system-test/README.md +++ b/prodtests/full-system-test/README.md @@ -41,6 +41,7 @@ The following options exist (some of the options are not used in all scripts, an * `HOSTMEMSIZE`: Size of allocated host memory for GPU reconstruction (0 = default). * For `GPUTYPE = CPU`: TPC Tracking scratch memory size. (Default 0 -> dynamic allocation.) * Otherwise : Size of page-locked host memory for GPU processing. (Defauls 0 -> 1 GB.) +* `SAVECTF`: Save the CTF to a root file. * `CREATECTFDICT`: Create CTF dictionary. * 0: Read `ctf_dictionary.root` as input. * 1: Create `ctf_dictionary.root`. Note that this was already done automatically if the raw data was simulated with `full_system_test.sh`. diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index b9fd621567a4f..36c534ccba249 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -28,10 +28,13 @@ else CMD_INPUT="o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues $CMD_X --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg" fi -if [ $CREATECTFDICT == 1 ]; then - CMD_DICT="o2-ctf-writer-workflow $ARGS_ALL --output-type dict --save-dict-after 1 --onlyDet ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS" -else - CMD_DICT=cat +CMD_CTF_TYPE="none" +if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 1 ]; then CMD_CTF_TYPE="both"; fi +if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 0 ]; then CMD_CTF_TYPE="dict"; fi +if [ $CREATECTFDICT == 0 ] && [ $SAVECTF == 1 ]; then CMD_CTF_TYPE="ctf"; fi +CMD_CTF="o2-ctf-writer-workflow $ARGS_ALL --output-type $CMD_CTF_TYPE --onlyDet ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS" +if [ $CREATECTFDICT == 1 ] && [ $; then + CMD_CTF+=" --save-dict-after 1" fi if [ $SYNCMODE == 1 ]; then @@ -101,5 +104,5 @@ o2-emcal-entropy-encoder-workflow $ARGS_ALL |\ o2-tof-compressor $ARGS_ALL | \ o2-tof-reco-workflow $ARGS_ALL --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output $DISABLE_MC | \ o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input | \ -$CMD_DICT | \ +$CMD_CTF | \ o2-dpl-run $ARGS_ALL $GLOBALDPLOPT --run diff --git a/prodtests/full-system-test/setenv.sh b/prodtests/full-system-test/setenv.sh index b42b33d2e8fec..6c7d397665607 100755 --- a/prodtests/full-system-test/setenv.sh +++ b/prodtests/full-system-test/setenv.sh @@ -16,6 +16,7 @@ if [ -z "$DDSHMSIZE" ]; then export DDSHMSIZE=$(( 32 << 10 )); fi # Size of if [ -z "$GPUMEMSIZE" ]; then export GPUMEMSIZE=$(( 13 << 30 )); fi # Size of allocated GPU memory (if GPUTYPE != CPU) if [ -z "$HOSTMEMSIZE" ]; then export HOSTMEMSIZE=0; fi # Size of allocated host memory for GPU reconstruction (0 = default) if [ -z "$CREATECTFDICT" ]; then export CREATECTFDICT=0; fi # Create CTF dictionary +if [ -z "$SAVECTF" ]; then export SAVECTF=0; fi # Save the CTF to a ROOT file if [ -z "$SYNCMODE" ]; then export SYNCMODE=0; fi # Run only reconstruction steps of the synchronous reconstruction if [ -z "$NUMAID" ]; then export NUMAID=0; fi # SHM segment id to use for shipping data as well as set of GPUs to use (use 0 / 1 for 2 NUMA domains) if [ -z "$NUMAGPUIDS" ]; then export NUMAGPUIDS=0; fi # NUMAID-aware GPU id selection From 51d8f0e639df252f222744d2d3f602d48e080e08 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 21:20:02 +0100 Subject: [PATCH 1550/1751] Add option to read input from CTF and run asynchronous reconstruction to full system test script --- prodtests/full-system-test/README.md | 2 + prodtests/full-system-test/dpl-workflow.sh | 145 +++++++++++++-------- prodtests/full-system-test/setenv.sh | 14 ++ 3 files changed, 107 insertions(+), 54 deletions(-) diff --git a/prodtests/full-system-test/README.md b/prodtests/full-system-test/README.md index c5f1f4ff4268e..632125811c7a8 100644 --- a/prodtests/full-system-test/README.md +++ b/prodtests/full-system-test/README.md @@ -46,6 +46,7 @@ The following options exist (some of the options are not used in all scripts, an * 0: Read `ctf_dictionary.root` as input. * 1: Create `ctf_dictionary.root`. Note that this was already done automatically if the raw data was simulated with `full_system_test.sh`. * `SYNCMODE`: Run only reconstruction steps of the synchronous reconstruction. + * Note that there is no `ASYNCMODE` but instead the `CTFINPUT` option already enforces asynchronous processing. * `NUMAGPUIDS`: NUMAID-aware GPU id selection. Needed for the full EPN configuration with 8 GPUs, 2 NUMA domains, 4 GPUs per domain. In this configuration, 2 instances of `dpl-workflow.sh` must run in parallel. To be used in combination with `NUMAID` to select the id per workflow. @@ -56,6 +57,7 @@ The following options exist (some of the options are not used in all scripts, an * `EXTINPUT`: Receive input from raw FMQ channel instead of running o2-raw-file-reader. * 0: `dpl-workflow.sh` can run as standalone benchmark, and will read the input itself. * 1: To be used in combination with either `datadistribution.sh` or `raw-reader.sh` or with another DataDistribution instance. +* `CTFINPUT`: Read input from CTF ROOT file. This option is incompatible to EXTINPUT=1. The CTF ROOT file can be stored via SAVECTF=1. * `NHBPERTF`: Time frame length (in HBF) * `GLOBALDPLOPT`: Global DPL workflow options appended to o2-dpl-run. * `EPNPIPELINES`: Set default EPN pipeline multiplicities. diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 36c534ccba249..dc30553d51e33 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -8,6 +8,7 @@ if [ "0$ALIENVLVL" == "0" ]; then alienv --no-refresh load O2/latest fi +# Set general arguments ARGS_ALL="--session default --severity $SEVERITY --shm-segment-id $NUMAID --shm-segment-size $SHMSIZE" if [ $EXTINPUT == 1 ] || [ $NUMAGPUIDS == 1 ]; then ARGS_ALL+=" --no-cleanup" @@ -19,35 +20,26 @@ if [ $NORATELOG == 1 ]; then ARGS_ALL+=" --fairmq-rate-logging 0" fi -if [ $EXTINPUT == 1 ]; then - CMD_X="B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA;G:EMC/RAWDATA;H:PHS/RAWDATA" - CMD_Y="name=readout-proxy,type=pull,method=connect,address=ipc://@stfb-to-dpl$1,transport=shmem,rateLogging=0" - CMD_INPUT="o2-dpl-raw-proxy $ARGS_ALL --dataspec $CMD_X --channel-config $CMD_Y" -else - CMD_X="HBFUtils.nHBFPerTF=$NHBPERTF;" - CMD_INPUT="o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues $CMD_X --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg" -fi - -CMD_CTF_TYPE="none" -if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 1 ]; then CMD_CTF_TYPE="both"; fi -if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 0 ]; then CMD_CTF_TYPE="dict"; fi -if [ $CREATECTFDICT == 0 ] && [ $SAVECTF == 1 ]; then CMD_CTF_TYPE="ctf"; fi -CMD_CTF="o2-ctf-writer-workflow $ARGS_ALL --output-type $CMD_CTF_TYPE --onlyDet ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS" -if [ $CREATECTFDICT == 1 ] && [ $; then - CMD_CTF+=" --save-dict-after 1" -fi - +# Set some individual workflow arguments depending on configuration +TPC_INPUT=zsraw +TPC_OUTPUT=tracks,clusters,disable-writer +TPC_CONFIG= +TPC_CONFIG_KEY= +TOF_INPUT=raw +TOF_OUTPUT=clusters,matching-info +ITS_CONFIG= +ITS_CONFIG_KEY= if [ $SYNCMODE == 1 ]; then - CFG_X="fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500" - ITS_CONFIG="--configKeyValues $CFG_X" - TPC_CONFIG="GPU_global.synchronousProcessing=1;" - CMD_MID="cat" + ITS_CONFIG_KEY+="fastMultConfig.cutMultClusLow=30;fastMultConfig.cutMultClusHigh=2000;fastMultConfig.cutMultVtxHigh=500" + TPC_CONFIG_KEY+=" GPU_global.synchronousProcessing=1;" +fi +if [ $CTFINPUT == 1 ]; then + ITS_CONFIG+=" --async-phase" else - ITS_CONFIG= - TPC_CONFIG= - CMD_MID="o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC" + ITS_CONFIG+=" --entropy-encoding" + TOF_OUTPUT+=",ctf" + TPC_OUTPUT+=",encoded-clusters" fi -TPC_CONFIG2= if [ $GPUTYPE == "HIP" ]; then if [ $NUMAID == 0 ] || [ $NUMAGPUIDS == 0 ]; then @@ -55,23 +47,22 @@ if [ $GPUTYPE == "HIP" ]; then else export TIMESLICEOFFSET=$NGPUS fi - TPC_CONFIG+="GPU_proc.deviceNum=0;GPU_global.mutexMemReg=true;" - CFG_Y="ROCR_VISIBLE_DEVICES={timeslice${TIMESLICEOFFSET}}" - TPC_CONFIG2+=" --environment $CFG_Y" + TPC_CONFIG_KEY+="GPU_proc.deviceNum=0;GPU_global.mutexMemReg=true;" + TPC_CONFIG+=" --environment \"ROCR_VISIBLE_DEVICES={timeslice${TIMESLICEOFFSET}}\"" export HSA_NO_SCRATCH_RECLAIM=1 #export HSA_TOOLS_LIB=/opt/rocm/lib/librocm-debug-agent.so.2 else - TPC_CONFIG+="GPU_proc.deviceNum=-2;" + TPC_CONFIG_KEY+="GPU_proc.deviceNum=-2;" fi if [ $GPUTYPE != "CPU" ]; then - TPC_CONFIG+="GPU_proc.forceMemoryPoolSize=$GPUMEMSIZE;" + TPC_CONFIG_KEY+="GPU_proc.forceMemoryPoolSize=$GPUMEMSIZE;" if [ $HOSTMEMSIZE == "0" ]; then HOSTMEMSIZE=$(( 1 << 30 )) fi fi if [ $HOSTMEMSIZE != "0" ]; then - TPC_CONFIG+="GPU_proc.forceHostMemoryPoolSize=$HOSTMEMSIZE;" + TPC_CONFIG_KEY+="GPU_proc.forceHostMemoryPoolSize=$HOSTMEMSIZE;" fi if [ $EPNPIPELINES == 1 ]; then @@ -84,25 +75,71 @@ else N_ITSDEC=1 fi -$CMD_INPUT | \ -o2-itsmft-stf-decoder-workflow $ARGS_ALL --pipeline its-stf-decoder:$N_ITSDEC | \ -o2-itsmft-stf-decoder-workflow $ARGS_ALL --runmft true | \ -o2-its-reco-workflow $ARGS_ALL --trackerCA $DISABLE_MC --clusters-from-upstream --disable-root-output --entropy-encoding $ITS_CONFIG | \ -o2-itsmft-entropy-encoder-workflow $ARGS_ALL --runmft true | \ -o2-tpc-reco-workflow ${ARGS_ALL/--severity $SEVERITY/--severity $SEVERITY_TPC} --input-type=zsraw $DISABLE_MC --output-type tracks,clusters,encoded-clusters,disable-writer --pipeline tpc-tracker:$NGPUS,tpc-entropy-encoder:$N_TPCENT $TPC_CONFIG2 --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF;GPU_global.deviceType=$GPUTYPE;GPU_proc.debugLevel=0;$TPC_CONFIG" | \ -o2-tpcits-match-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC --pipeline itstpc-track-matcher:$N_TPCITS | \ -o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | \ -o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC | \ -o2-ft0-entropy-encoder-workflow $ARGS_ALL | \ -o2-mid-raw-to-digits-workflow $ARGS_ALL | \ -$CMD_MID | \ -o2-mid-entropy-encoder-workflow $ARGS_ALL | \ -o2-phos-reco-workflow $ARGS_ALL --input-type raw --output-type cells | \ -o2-phos-entropy-encoder-workflow $ARGS_ALL |\ -o2-emcal-reco-workflow $ARGS_ALL --input-type raw --output-type cells --disable-root-output | \ -o2-emcal-entropy-encoder-workflow $ARGS_ALL |\ -o2-tof-compressor $ARGS_ALL | \ -o2-tof-reco-workflow $ARGS_ALL --configKeyValues "HBFUtils.nHBFPerTF=$NHBPERTF" --input-type raw --output-type ctf,clusters,matching-info --disable-root-output $DISABLE_MC | \ -o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input | \ -$CMD_CTF | \ -o2-dpl-run $ARGS_ALL $GLOBALDPLOPT --run +# Input workflow +if [ $CTFINPUT == 1 ]; then + TPC_INPUT=compressed-clusters-ctf + TOF_INPUT=digits + WORKFLOW="o2-ctf-reader-workflow --ctf-input o2_ctf_0000000000.root $ARGS_ALL | " +elif [ $EXTINPUT == 1 ]; then + WORKFLOW="o2-dpl-raw-proxy $ARGS_ALL --dataspec \"B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA;G:EMC/RAWDATA;H:PHS/RAWDATA\" --channel-config \"name=readout-proxy,type=pull,method=connect,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0\" | " +else + WORKFLOW="o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=$NHBPERTF;\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | " +fi + +#Decoder workflows +if [ $CTFINPUT == 0 ]; then + WORKFLOW+="o2-itsmft-stf-decoder-workflow $ARGS_ALL --pipeline its-stf-decoder:$N_ITSDEC | " + WORKFLOW+="o2-itsmft-stf-decoder-workflow $ARGS_ALL --runmft true | " + WORKFLOW+="o2-ft0-flp-dpl-workflow $ARGS_ALL --disable-root-output | " + WORKFLOW+="o2-mid-raw-to-digits-workflow $ARGS_ALL | " + WORKFLOW+="o2-tof-compressor $ARGS_ALL | " +fi + +# Common workflows +WORKFLOW+="o2-its-reco-workflow $ARGS_ALL --trackerCA $DISABLE_MC --clusters-from-upstream --disable-root-output $ITS_CONFIG --configKeyValues \"HBFUtils.nHBFPerTF=128;$ITS_CONFIG_KEY\" | " +WORKFLOW+="o2-tpc-reco-workflow ${ARGS_ALL/--severity $SEVERITY/--severity $SEVERITY_TPC} --input-type=$TPC_INPUT $DISABLE_MC --output-type $TPC_OUTPUT --pipeline tpc-tracker:$NGPUS,tpc-entropy-encoder:$N_TPCENT $TPC_CONFIG --configKeyValues \"HBFUtils.nHBFPerTF=$NHBPERTF;GPU_global.deviceType=$GPUTYPE;GPU_proc.debugLevel=0;$TPC_CONFIG_KEY\" | " +WORKFLOW+="o2-tpcits-match-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC --pipeline itstpc-track-matcher:$N_TPCITS --configKeyValues \"HBFUtils.nHBFPerTF=128;\" | " +WORKFLOW+="o2-ft0-reco-workflow $ARGS_ALL --disable-root-input --disable-root-output $DISABLE_MC --configKeyValues \"HBFUtils.nHBFPerTF=128;\" | " +WORKFLOW+="o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=$NHBPERTF\" --input-type $TOF_INPUT --output-type $TOF_OUTPUT --disable-root-input --disable-root-output $DISABLE_MC | " + +# Workflows disabled in sync mode +if [ $SYNCMODE == 0 ]; then + WORKFLOW+="o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC | " + # WORKFLOW+="o2-mft-reco-workflow $ARGS_ALL --clusters-from-upstream --disable-mc --disable-root-output --configKeyValues \"HBFUtils.nHBFPerTF=128;\" | " # Disabled since currently crashing + WORKFLOW+="o2-primary-vertexing-workflow $ARGS_ALL --disable-mc --disable-root-input --disable-root-output --validate-with-ft0 | " + WORKFLOW+="o2-secondary-vertexing-workflow $ARGS_ALL --disable-root-input --disable-root-output | " +fi + +# Workflows disabled in async mode +if [ $CTFINPUT == 0 ]; then + WORKFLOW+="o2-phos-reco-workflow $ARGS_ALL --input-type raw --output-type cells | " + WORKFLOW+="o2-emcal-reco-workflow $ARGS_ALL --input-type raw --output-type cells --disable-root-output | " + + WORKFLOW+="o2-itsmft-entropy-encoder-workflow $ARGS_ALL --runmft true | " + WORKFLOW+="o2-ft0-entropy-encoder-workflow $ARGS_ALL | " + WORKFLOW+="o2-mid-entropy-encoder-workflow $ARGS_ALL | " + WORKFLOW+="o2-phos-entropy-encoder-workflow $ARGS_ALL | " + WORKFLOW+="o2-emcal-entropy-encoder-workflow $ARGS_ALL | " + + WORKFLOW+="o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input | " + + # Output workflow + CTF_OUTPUT_TYPE="none" + if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 1 ]; then CTF_OUTPUT_TYPE="both"; fi + if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 0 ]; then CTF_OUTPUT_TYPE="dict"; fi + if [ $CREATECTFDICT == 0 ] && [ $SAVECTF == 1 ]; then CTF_OUTPUT_TYPE="ctf"; fi + CMD_CTF="o2-ctf-writer-workflow $ARGS_ALL --output-type $CTF_OUTPUT_TYPE --onlyDet ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS" + if [ $CREATECTFDICT == 1 ] && [ $; then + CMD_CTF+=" --save-dict-after 1" + fi + WORKFLOW+="$CMD_CTF | " +fi + +# DPL run binary +WORKFLOW+="o2-dpl-run $ARGS_ALL $GLOBALDPLOPT --run" + +# Execute the command we have assembled +#echo Running workflow: +#echo $WORKFLOW | sed "s/| */|\n/g" +#echo +eval $WORKFLOW diff --git a/prodtests/full-system-test/setenv.sh b/prodtests/full-system-test/setenv.sh index 6c7d397665607..1e5e4bd5e9aaa 100755 --- a/prodtests/full-system-test/setenv.sh +++ b/prodtests/full-system-test/setenv.sh @@ -21,6 +21,7 @@ if [ -z "$SYNCMODE" ]; then export SYNCMODE=0; fi # Run onl if [ -z "$NUMAID" ]; then export NUMAID=0; fi # SHM segment id to use for shipping data as well as set of GPUs to use (use 0 / 1 for 2 NUMA domains) if [ -z "$NUMAGPUIDS" ]; then export NUMAGPUIDS=0; fi # NUMAID-aware GPU id selection if [ -z "$EXTINPUT" ]; then export EXTINPUT=0; fi # Receive input from raw FMQ channel instead of running o2-raw-file-reader +if [ -z "$CTFINPUT" ]; then export CTFINPUT=0; fi # Read input from CTF (incompatible to EXTINPUT=1) if [ -z "$NHBPERTF" ]; then export NHBPERTF=128; fi # Time frame length (in HBF) if [ -z "$GLOBALDPLOPT" ]; then export GLOBALDPLOPT=; fi # Global DPL workflow options appended at the end if [ -z "$EPNPIPELINES" ]; then export EPNPIPELINES=0; fi # Set default EPN pipeline multiplicities @@ -30,3 +31,16 @@ if [ -z "$NORATELOG" ]; then export NORATELOG=1; fi # Disable SEVERITY_TPC="info" # overrides severity for the tpc workflow DISABLE_MC="--disable-mc" + +if [ $EXTINPUT == 1 ] && [ $CTFINPUT == 1 ]; then + echo EXTINPUT and CTFINPUT are incompatible + exit 1 +fi +if [ $SAVECTF == 1 ] && [ $CTFINPUT == 1 ]; then + echo SAVECTF and CTFINPUT are incompatible + exit 1 +fi +if [ $SYNCMODE == 1 ] && [ $CTFINPUT == 1 ]; then + echo SYNCMODE and CTFINPUT are incompatible + exit 1 +fi From 0931587f16aa983dc43682068eb6d917737991d5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 4 Dec 2020 21:28:01 +0100 Subject: [PATCH 1551/1751] Run also the asynchronous reconstruction in the alibi full system test --- prodtests/full_system_test.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index d3f5d7c2e5858..962b59af816da 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -28,7 +28,7 @@ SHMSIZE=${SHMSIZE:-8000000000} # Size of shared memory for messages (use 128 GB TPCTRACKERSCRATCHMEMORY=${SHMSIZE:-4000000000} # Size of memory allocated by TPC tracker. (Use 24 GB for 550 event full TF) ENABLE_GPU_TEST=${ENABLE_GPU_TEST:-0} # Run the full system test also on the GPU NTIMEFRAMES=${NTIMEFRAMES:-1} # Number of time frames to process -TFDELAY=100 # Delay in seconds between publishing time frames +TFDELAY=${TFDELAY:-100} # Delay in seconds between publishing time frames NOMCLABELS="--disable-mc" # allow skipping @@ -73,6 +73,7 @@ STAGES="NOGPU" if [ $ENABLE_GPU_TEST != "0" ]; then STAGES+=" WITHGPU" fi +STAGES+=" ASYNC" for STAGE in $STAGES; do ARGS_ALL="--session default" @@ -83,11 +84,22 @@ for STAGE in $STAGES; do export GPUMEMSIZE=6000000000 export HOSTMEMSIZE=1000000000 export SYNCMODE=1 + export CTFINPUT=0 + export SAVECTF=0 + elif [[ "$STAGE" = "ASYNC" ]]; then + export CREATECTFDICT=1 + export GPUTYPE=CPU + export SYNCMODE=0 + export HOSTMEMSIZE=$TPCTRACKERSCRATCHMEMORY + export CTFINPUT=1 + export SAVECTF=0 else export CREATECTFDICT=1 export GPUTYPE=CPU export SYNCMODE=0 export HOSTMEMSIZE=$TPCTRACKERSCRATCHMEMORY + export CTFINPUT=0 + export SAVECTF=1 rm -f ctf_dictionary.root fi export SHMSIZE From f2719b52da6bcf90d336f0fea2c0ce2c2462183d Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sat, 5 Dec 2020 09:40:34 +0100 Subject: [PATCH 1552/1751] DPL Analysis: add handlers for nested arrays in struct configurables (#5004) --- .../include/Analysis/configurableCut.h | 2 +- Analysis/Tutorials/src/configurableCut.cxx | 2 +- .../Tutorials/src/configurableObjects.cxx | 33 ++++++---- Framework/Core/src/RootConfigParamHelpers.cxx | 60 +++++++++++++++++-- 4 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h index 501128a37ae0f..0e9deef256856 100644 --- a/Analysis/Tutorials/include/Analysis/configurableCut.h +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -35,7 +35,7 @@ class configurableCut bool getOption() const; void setBins(std::vector<float> bins_); - auto getBins() const; + std::vector<float> getBins() const; private: float cut; diff --git a/Analysis/Tutorials/src/configurableCut.cxx b/Analysis/Tutorials/src/configurableCut.cxx index eb3ac124a2fca..c43b34293e178 100644 --- a/Analysis/Tutorials/src/configurableCut.cxx +++ b/Analysis/Tutorials/src/configurableCut.cxx @@ -56,7 +56,7 @@ void configurableCut::setBins(std::vector<float> bins_) { bins = bins_; }; -auto configurableCut::getBins() const +std::vector<float> configurableCut::getBins() const { return bins; }; diff --git a/Analysis/Tutorials/src/configurableObjects.cxx b/Analysis/Tutorials/src/configurableObjects.cxx index 036379d192d96..6058336feca4e 100644 --- a/Analysis/Tutorials/src/configurableObjects.cxx +++ b/Analysis/Tutorials/src/configurableObjects.cxx @@ -21,30 +21,37 @@ using namespace o2::framework::expressions; /// This task demonstrates how to use configurable to wrap classes /// use it with supplied configuration: "configurableObject.json" +template <typename T> +auto printArray(std::vector<T> const& vec) +{ + std::stringstream ss; + ss << "["; + auto count = 0u; + for (auto& entry : vec) { + ss << entry; + if (count < vec.size() - 1) { + ss << ","; + } + ++count; + } + ss << "]"; + return ss.str(); +} + struct ConfigurableObjectDemo { Configurable<configurableCut> cut{"cut", {0.5, 1, true}, "generic cut"}; MutableConfigurable<configurableCut> mutable_cut{"mutable_cut", {1., 2, false}, "generic cut"}; // note that size is fixed by this declaration - externally supplied vector needs to be the same size! - Configurable<std::vector<int>> array{"array", {1, 2, 3, 4, 5}, "generic array"}; + Configurable<std::vector<int>> array{"array", {0, 0, 0, 0, 0, 0, 0}, "generic array"}; void init(InitContext const&){}; void process(aod::Collision const&, aod::Tracks const& tracks) { LOGF(INFO, "Cut1: %.3f; Cut2: %.3f", cut, mutable_cut); + LOGF(INFO, "Cut1 bins: %s; Cut2 bins: %s", printArray(cut->getBins()), printArray(mutable_cut->getBins())); auto vec = (std::vector<int>)array; - std::stringstream ss; - ss << "["; - auto count = 0u; - for (auto& entry : vec) { - ss << entry; - if (count < vec.size() - 1) { - ss << ","; - } - ++count; - } - ss << "]"; - LOGF(INFO, "Array: %s", ss.str().c_str()); + LOGF(INFO, "Array: %s", printArray(vec).c_str()); for (auto& track : tracks) { if (track.globalIndex() % 500 == 0) { std::string decision1; diff --git a/Framework/Core/src/RootConfigParamHelpers.cxx b/Framework/Core/src/RootConfigParamHelpers.cxx index 6c1cb07efb02c..0a15b3dfd6310 100644 --- a/Framework/Core/src/RootConfigParamHelpers.cxx +++ b/Framework/Core/src/RootConfigParamHelpers.cxx @@ -10,6 +10,7 @@ #include "Framework/RootConfigParamHelpers.h" #include "Framework/ConfigParamSpec.h" +#include "Framework/StringHelpers.h" #include <TClass.h> #include <TDataMember.h> #include <TDataType.h> @@ -35,14 +36,14 @@ bool isString(TDataMember const& dm) // a generic looper of data members of a TClass; calling a callback // reused in various functions below void loopOverMembers(TClass* cl, void* obj, - std::function<void(const TDataMember*, int, int)>&& callback) + std::function<void(TDataMember*, int, int)>&& callback) { auto memberlist = cl->GetListOfDataMembers(); for (int i = 0; i < memberlist->GetEntries(); ++i) { auto dm = (TDataMember*)memberlist->At(i); auto isValidComplex = [dm]() { - return isString(*dm) || dm->IsEnum(); + return isString(*dm) || dm->IsEnum() || dm->IsSTLContainer(); }; // filter out static members for now @@ -70,6 +71,20 @@ void loopOverMembers(TClass* cl, void* obj, } } +namespace +{ +template <typename T> +std::vector<T> extractVector(boost::property_tree::ptree const& tree) +{ + std::vector<T> result(tree.size()); + auto count = 0u; + for (auto& entry : tree) { + result[count++] = entry.second.get_value<T>(); + } + return result; +} +} // namespace + // construct name (in dependence on vector or scalar data and index) std::string getName(const TDataMember* dm, int index, int size) { @@ -83,7 +98,7 @@ std::string getName(const TDataMember* dm, int index, int size) void ptreeToMember(boost::property_tree::ptree const& value, char const* tname, - TDataMember const* dm, + TDataMember* dm, void* ptr) { auto dt = dm->GetDataType(); @@ -150,6 +165,23 @@ void ptreeToMember(boost::property_tree::ptree const& value, } } } + if (dm->IsSTLContainer()) { + auto type = dm->GetTypeName(); + switch (compile_time_hash(type)) { + case compile_time_hash("vector<int>"): + *static_cast<std::vector<int>*>(ptr) = extractVector<int>(value); + return; + case compile_time_hash("vector<float>"): + *static_cast<std::vector<float>*>(ptr) = extractVector<float>(value); + return; + case compile_time_hash("vector<double>"): + *static_cast<std::vector<double>*>(ptr) = extractVector<double>(value); + return; + case compile_time_hash("vector<bool>"): + default: + throw std::runtime_error("Not and int/float/double/bool vector"); + } + } // if we get here none of the above worked if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { *(std::string*)ptr = value.get_value<std::string>(); @@ -158,7 +190,7 @@ void ptreeToMember(boost::property_tree::ptree const& value, } // Convert a DataMember to a ConfigParamSpec -ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember const* dm, void* ptr) +ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void* ptr) { auto dt = dm->GetDataType(); if (dt != nullptr) { @@ -210,6 +242,22 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember const* dm } } } + if (dm->IsSTLContainer()) { + auto type = dm->GetTypeName(); + switch (compile_time_hash(type)) { + case compile_time_hash("vector<int>"): + return ConfigParamSpec{tname, VariantType::ArrayInt, *static_cast<std::vector<int>*>(ptr), {"No help"}}; + case compile_time_hash("vector<float>"): + return ConfigParamSpec{tname, VariantType::ArrayFloat, *static_cast<std::vector<float>*>(ptr), {"No help"}}; + case compile_time_hash("vector<double>"): + return ConfigParamSpec{tname, VariantType::ArrayDouble, *static_cast<std::vector<double>*>(ptr), {"No help"}}; + case compile_time_hash("vector<bool>"): + throw std::runtime_error("bool vector not supported yet"); + // return ConfigParamSpec{tname, VariantType::ArrayBool, *static_cast<std::vector<bool>*>(ptr), {"No help"}}; + default: + throw std::runtime_error("Not and int/float/double/bool vector"); + } + } // if we get here none of the above worked if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { return ConfigParamSpec{tname, VariantType::String, *(std::string*)ptr, {"No help"}}; @@ -226,7 +274,7 @@ std::vector<ConfigParamSpec> { std::vector<ConfigParamSpec> specs; - auto toDataMember = [&mainKey, &specs, obj](const TDataMember* dm, int index, int size) { + auto toDataMember = [&mainKey, &specs, obj](TDataMember* dm, int index, int size) { auto dt = dm->GetDataType(); auto TS = dt ? dt->Size() : 0; char* ptr = ((char*)obj) + dm->GetOffset() + index * TS; @@ -243,7 +291,7 @@ std::vector<ConfigParamSpec> /// using the values in the ptree to override, where appropriate. void RootConfigParamHelpers::fillFromPtree(TClass* cl, void* obj, boost::property_tree::ptree const& pt) { - auto toDataMember = [obj, &pt](const TDataMember* dm, int index, int size) { + auto toDataMember = [obj, &pt](TDataMember* dm, int index, int size) { auto dt = dm->GetDataType(); auto TS = dt ? dt->Size() : 0; char* ptr = ((char*)obj) + dm->GetOffset() + index * TS; From 2be0482de382a90031bf82cf03ae006ff8111993 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Sat, 5 Dec 2020 09:41:31 +0100 Subject: [PATCH 1553/1751] DPL Analysis: table slicing helper (#4999) --- Analysis/Tutorials/src/associatedExample.cxx | 6 +-- Framework/Core/include/Framework/ASoA.h | 46 ++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/Analysis/Tutorials/src/associatedExample.cxx b/Analysis/Tutorials/src/associatedExample.cxx index a9f9ccf925747..30f6adbeb1f95 100644 --- a/Analysis/Tutorials/src/associatedExample.cxx +++ b/Analysis/Tutorials/src/associatedExample.cxx @@ -96,7 +96,7 @@ struct ZTask { LOGF(INFO, "Bin 0-10"); for (auto& col : multbin0_10) { - auto groupedTracks = tracks.select(aod::track::collisionId == col.globalIndex()); + auto groupedTracks = tracks.sliceBy(aod::track::collisionId, col.globalIndex()); LOGF(INFO, "Collision %d; Ntrk = %d vs %d", col.globalIndex(), col.mult(), groupedTracks.size()); if (groupedTracks.size() > 0) { auto track = groupedTracks.begin(); @@ -106,13 +106,13 @@ struct ZTask { LOGF(INFO, "Bin 10-30"); for (auto& col : multbin10_30) { - auto groupedTracks = tracks.select(aod::track::collisionId == col.globalIndex()); + auto groupedTracks = tracks.sliceBy(aod::track::collisionId, col.globalIndex()); LOGF(INFO, "Collision %d; Ntrk = %d vs %d", col.globalIndex(), col.mult(), groupedTracks.size()); } LOGF(INFO, "Bin 30-100"); for (auto& col : multbin30_100) { - auto groupedTracks = tracks.select(aod::track::collisionId == col.globalIndex()); + auto groupedTracks = tracks.sliceBy(aod::track::collisionId, col.globalIndex()); LOGF(INFO, "Collision %d; Ntrk = %d vs %d", col.globalIndex(), col.mult(), groupedTracks.size()); } } diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 7fe30dbdafb89..42193623aa93d 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -23,6 +23,7 @@ #include <arrow/array.h> #include <arrow/util/variant.h> #include <arrow/compute/kernel.h> +#include <arrow/compute/api_aggregate.h> #include <gandiva/selection_vector.h> #include <cassert> #include <fmt/format.h> @@ -864,6 +865,44 @@ auto select(T const& t, framework::expressions::Filter&& f) t.asArrowTable()->schema())); } +namespace +{ +auto getSliceFor(int value, char const* key, std::shared_ptr<arrow::Table> const& input, std::shared_ptr<arrow::Table>& output, uint64_t& offset) +{ + arrow::Datum value_counts; + auto options = arrow::compute::CountOptions::Defaults(); + ARROW_ASSIGN_OR_RAISE(value_counts, + arrow::compute::CallFunction("value_counts", {input->GetColumnByName(key)}, + &options)); + auto pair = static_cast<arrow::StructArray>(value_counts.array()); + auto values = static_cast<arrow::NumericArray<arrow::Int32Type>>(pair.field(0)->data()); + auto counts = static_cast<arrow::NumericArray<arrow::Int64Type>>(pair.field(1)->data()); + + int slice; + for (slice = 0; slice < values.length(); ++slice) { + if (values.Value(slice) == value) { + offset = slice; + output = input->Slice(slice, counts.Value(slice)); + return arrow::Status::OK(); + } + } + output = input->Slice(0, 0); + return arrow::Status::OK(); +} +} // namespace + +template <typename T> +auto sliceBy(T const& t, framework::expressions::BindingNode const& node, int value) +{ + uint64_t offset = 0; + std::shared_ptr<arrow::Table> result = nullptr; + auto status = getSliceFor(value, node.name.c_str(), t.asArrowTable(), result, offset); + if (status.ok()) { + return T({result}, offset); + } + throw std::runtime_error("Failed to slice table"); +} + /// A Table class which observes an arrow::Table and provides /// It is templated on a set of Column / DynamicColumn types. template <typename... C> @@ -1081,6 +1120,13 @@ class Table return t; } + auto sliceBy(framework::expressions::BindingNode const& node, int value) const + { + auto t = o2::soa::sliceBy(*this, node, value); + copyIndexBindings(t); + return t; + } + private: template <typename T> arrow::ChunkedArray* lookupColumn() From eca708b229a927485739779dc8ca9b902863923a Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 5 Dec 2020 12:45:58 +0400 Subject: [PATCH 1554/1751] decrease verbosity of EMCAL RawReaderMemory --- Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx index dcce7d20298d0..6ab48678f475a 100644 --- a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx @@ -95,13 +95,13 @@ void RawReaderMemory::nextPage(bool doResetPayload) // Read header try { mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); - RDHDecoder::printRDH(mRawHeader); + //RDHDecoder::printRDH(mRawHeader); if (RDHDecoder::getOffsetToNext(mRawHeader) == RDHDecoder::getHeaderSize(mRawHeader)) { // No Payload - jump to next rawheader // This will eventually move, depending on whether for events without payload in the SRU we send the RCU trailer mCurrentPosition += RDHDecoder::getHeaderSize(mRawHeader); mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); - RDHDecoder::printRDH(mRawHeader); + //RDHDecoder::printRDH(mRawHeader); } mRawHeaderInitialized = true; } catch (...) { From a425eeaa486040ee4b53abf2a03d374e7351bb6f Mon Sep 17 00:00:00 2001 From: Pietro Cortese <pietro.cortese@cern.ch> Date: Thu, 10 Sep 2020 08:59:15 +0200 Subject: [PATCH 1555/1751] Multiple fixes for ZDC, raw data creation (former PR4658 from P.Cortese) Cleaned up, rebased to dev and squashed --- .../ZDC/include/DataFormatsZDC/RawEventData.h | 94 +++ .../ZDC/include/DataFormatsZDC/RecEvent.h | 2 +- DataFormats/Detectors/ZDC/src/BCData.cxx | 3 +- .../Detectors/ZDC/src/RawEventData.cxx | 50 ++ .../ZDC/base/include/ZDCBase/Constants.h | 2 + .../ZDC/base/include/ZDCBase/ModuleConfig.h | 4 +- Detectors/ZDC/base/src/ModuleConfig.cxx | 10 +- Detectors/ZDC/macro/CreateModuleConfig.C | 4 +- Detectors/ZDC/simulation/CMakeLists.txt | 16 +- .../include/ZDCSimulation/Digitizer.h | 1 - .../include/ZDCSimulation/Digits2Raw.h | 103 +++ Detectors/ZDC/simulation/src/Digitizer.cxx | 22 +- Detectors/ZDC/simulation/src/Digits2Raw.cxx | 704 ++++++++++++++++++ Detectors/ZDC/simulation/src/digi2raw.cxx | 171 +++++ Detectors/ZDC/simulation/src/raw-parser.cxx | 98 +++ 15 files changed, 1266 insertions(+), 18 deletions(-) create mode 100644 DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h create mode 100644 DataFormats/Detectors/ZDC/src/RawEventData.cxx create mode 100644 Detectors/ZDC/simulation/include/ZDCSimulation/Digits2Raw.h create mode 100644 Detectors/ZDC/simulation/src/Digits2Raw.cxx create mode 100644 Detectors/ZDC/simulation/src/digi2raw.cxx create mode 100644 Detectors/ZDC/simulation/src/raw-parser.cxx diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h new file mode 100644 index 0000000000000..f0662d175c2b2 --- /dev/null +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h @@ -0,0 +1,94 @@ +// 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. +// +// DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h + +#ifndef ALICEO2_ZDC_RAWEVENTDATA_H_ +#define ALICEO2_ZDC_RAWEVENTDATA_H_ +#include "CommonDataFormat/InteractionRecord.h" +#include "CommonDataFormat/RangeReference.h" +#include "ZDCBase/Constants.h" +#include <Rtypes.h> +#include <iostream> +#include <gsl/span> + +/// \file RawEventData.h +/// \brief Container of ZDC raw data +/// \author pietro.cortese@cern.ch + +namespace o2 +{ +namespace zdc +{ + +constexpr unsigned short Id_w0 = 0x0; +constexpr unsigned short Id_w1 = 0x1; +constexpr unsigned short Id_w2 = 0x2; +constexpr int NWPerGBTW = 4; + +struct __attribute__((__packed__)) ChannelDataV0 { + // First GBT word + unsigned fixed_0 : 2; + unsigned board : 4; + unsigned ch : 2; + unsigned offset : 16; + unsigned hits : 12; + unsigned bc : 12; + unsigned orbit : 32; + unsigned empty_0 : 16; + unsigned empty_1 : 32; + + // Second GBT word + unsigned fixed_1 : 2; + unsigned error : 2; + unsigned Alice_0 : 1; + unsigned Alice_1 : 1; + unsigned Alice_2 : 1; + unsigned Alice_3 : 1; + unsigned s00 : 12; + unsigned s01 : 12; + unsigned s02 : 12; + unsigned s03 : 12; + unsigned s04 : 12; + unsigned s05 : 12; + unsigned empty_2 : 16; + unsigned empty_3 : 32; + + // Third GBT word + unsigned fixed_2 : 2; + unsigned Hit : 1; + unsigned Auto_m : 1; + unsigned Auto_0 : 1; + unsigned Auto_1 : 1; + unsigned Auto_2 : 1; + unsigned Auto_3 : 1; + unsigned s06 : 12; + unsigned s07 : 12; + unsigned s08 : 12; + unsigned s09 : 12; + unsigned s10 : 12; + unsigned s11 : 12; + unsigned empty_4 : 16; + unsigned empty_5 : 32; +}; + +struct EventData { + union { + UInt_t w[NWPerBc][NWPerGBTW]; + struct ChannelDataV0 f; + } data[NModules][NChPerModule] = {0}; + void print() const; + void reset(); + ClassDefNV(EventData, 1); +}; + +} // namespace zdc +} // namespace o2 +#endif diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h index a21812e8306e7..1b70cb64e731b 100644 --- a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEvent.h @@ -31,7 +31,7 @@ struct RecEvent { o2::InteractionRecord ir; uint32_t flags; /// reconstruction flags - std::array<float, NChannelsZEM> eneregyZEM; /// signal in the electromagnetic ZDCs + std::array<float, NChannelsZEM> energyZEM; /// signal in the electromagnetic ZDCs std::array<float, NChannelsZN> energyZNA; /// reco E in 5 ZNA sectors + sum std::array<float, NChannelsZN> energyZNC; /// reco E in 5 ZNC sectors + sum std::array<float, NChannelsZP> energyZPA; /// reco E in 5 ZPA sectors + sum diff --git a/DataFormats/Detectors/ZDC/src/BCData.cxx b/DataFormats/Detectors/ZDC/src/BCData.cxx index a45d0f2c3da02..b090a7eacb389 100644 --- a/DataFormats/Detectors/ZDC/src/BCData.cxx +++ b/DataFormats/Detectors/ZDC/src/BCData.cxx @@ -16,8 +16,7 @@ using namespace o2::zdc; void BCData::print() const { - ir.print(); - printf("%d channels starting from %d\n", ref.getEntries(), ref.getFirstEntry()); + printf("Orbit %9u bc %4u nch %2d pos %d\n", ir.orbit, ir.bc, ref.getEntries(), ref.getFirstEntry()); printf("Read:"); for (int ic = 0; ic < NDigiChannels; ic++) { if (ic % NChPerModule == 0) { diff --git a/DataFormats/Detectors/ZDC/src/RawEventData.cxx b/DataFormats/Detectors/ZDC/src/RawEventData.cxx new file mode 100644 index 0000000000000..d988b7007da98 --- /dev/null +++ b/DataFormats/Detectors/ZDC/src/RawEventData.cxx @@ -0,0 +1,50 @@ +// 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. +// DataFormats/Detectors/ZDC/src/RawEventData.cxx +#include "DataFormatsZDC/RawEventData.h" + +using namespace o2::zdc; + +//ClassImp(EventData); + +//______________________________________________________________________________ +void EventData::print() const +{ + for (Int_t im = 0; im < o2::zdc::NModules; im++) { + for (Int_t ic = 0; ic < o2::zdc::NChPerModule; ic++) { + if (data[im][ic].f.fixed_0 == Id_w0 && data[im][ic].f.fixed_1 == Id_w1 && data[im][ic].f.fixed_2 == Id_w2) { + // Not empty event + auto f = data[im][ic].f; + // Word 0 + printf("%04x %08x %08x ", data[im][ic].w[0][2], data[im][ic].w[0][1], data[im][ic].w[0][0]); + printf("orbit %-9u bc %-4u hits %-4u offset %+6i Board %2u Ch %1u\n", f.orbit, f.bc, f.hits, f.offset, f.ch, f.board); + // Word 1 + printf("%04x %08x %08x ", data[im][ic].w[1][2], data[im][ic].w[1][1], data[im][ic].w[1][0]); + printf(" %s %s %s %s 0-5 ", f.Alice_0 ? "A0" : " ", f.Alice_1 ? "A1" : " ", f.Alice_2 ? "A2" : " ", f.Alice_3 ? "A3" : " "); + printf(" %5d %5d %5d %5d %5d %5d EC=%u\n", f.s00, f.s01, f.s02, f.s03, f.s04, f.s05, f.error); + // Word 2 + printf("%04x %08x %08x ", data[im][ic].w[2][2], data[im][ic].w[2][1], data[im][ic].w[2][0]); + printf("%s %s %s %s %s %s 6-b ", f.Hit ? "H" : " ", f.Auto_m ? "TM" : " ", f.Auto_0 ? "T0" : " ", f.Auto_1 ? "T1" : " ", f.Auto_2 ? "T2" : " ", f.Auto_3 ? "T3" : " "); + printf(" %5d %5d %5d %5d %5d %5d\n", f.s06, f.s07, f.s08, f.s09, f.s10, f.s11); + } else if (data[im][ic].f.fixed_0 == 0 && data[im][ic].f.fixed_1 == 0 && data[im][ic].f.fixed_2 == 0) { + // Empty channel + } else { + // Wrong data format. Insert warning. + } + } + } +} + +//______________________________________________________________________________ +void EventData::reset() +{ + static constexpr int payloadSize = NModules * NChPerModule * NWPerGBTW * sizeof(UInt_t); + memset((void*)&data[0][0], 0, payloadSize); +} diff --git a/Detectors/ZDC/base/include/ZDCBase/Constants.h b/Detectors/ZDC/base/include/ZDCBase/Constants.h index ce8b42800bb99..c834344b2d071 100644 --- a/Detectors/ZDC/base/include/ZDCBase/Constants.h +++ b/Detectors/ZDC/base/include/ZDCBase/Constants.h @@ -55,9 +55,11 @@ constexpr uint8_t ALICETriggerMask = 0x1; constexpr int NModules = 8; constexpr int NChPerModule = 4; +constexpr int NLinks = NModules * 2; constexpr int NDigiChannels = NModules * NChPerModule; constexpr int NWPerBc = 3; constexpr int MaxTriggerChannels = NChannels; +constexpr int ADCMin = -2048, ADCMax = 2047, ADCRange = 4096; // 12 bit ADC constexpr int MaxTDCValues = 5; // max number of TDC values to store in reconstructed event constexpr int NTDCChannels = 10; // max number of TDC values to store in reconstructed event diff --git a/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h b/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h index 1ffef071f7aa6..10548369121cf 100644 --- a/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h +++ b/Detectors/ZDC/base/include/ZDCBase/ModuleConfig.h @@ -34,12 +34,12 @@ struct Module { static constexpr int MaxChannels = 4, MaxTriggChannels = 2; int id = -1; // not active std::array<int8_t, MaxChannels> channelID = {IdDummy, IdDummy, IdDummy, IdDummy}; - std::array<int16_t, MaxChannels> linkID = {-1, -1, -1, -1}; + std::array<int16_t, MaxChannels> feeID = {-1, -1, -1, -1}; std::array<bool, MaxChannels> readChannel = {false}; std::array<bool, MaxChannels> trigChannel = {false}; std::array<TriggerChannelConfig, MaxChannels> trigChannelConf; - void setChannel(int slot, int8_t chID, int16_t lID, bool read, bool trig = false, int tF = 0, int tL = 0, int tS = 0, int tT = 0); + void setChannel(int slot, int8_t chID, int16_t fID, bool read, bool trig = false, int tF = 0, int tL = 0, int tS = 0, int tT = 0); void print() const; void printCh() const; void printTrig() const; diff --git a/Detectors/ZDC/base/src/ModuleConfig.cxx b/Detectors/ZDC/base/src/ModuleConfig.cxx index ca56b67c426eb..9dbcf6a1ace8c 100644 --- a/Detectors/ZDC/base/src/ModuleConfig.cxx +++ b/Detectors/ZDC/base/src/ModuleConfig.cxx @@ -16,9 +16,9 @@ using namespace o2::zdc; void Module::printCh() const { - printf("Module %d [ChID/LinkID R:T ]", id); + printf("Module %d [ChID/FEEID R:T ]", id); for (int ic = 0; ic < MaxChannels; ic++) { - printf("[%s{%2d}/L%02d %c:%c ]", channelName(channelID[ic]), channelID[ic], linkID[ic], readChannel[ic] ? 'R' : ' ', trigChannel[ic] ? 'T' : ' '); + printf("[%s{%2d}/L%02d %c:%c ]", channelName(channelID[ic]), channelID[ic], feeID[ic], readChannel[ic] ? 'R' : ' ', trigChannel[ic] ? 'T' : ' '); } printf("\n"); } @@ -78,13 +78,13 @@ void Module::check() const } } -void Module::setChannel(int slot, int8_t chID, int16_t lID, bool read, bool trig, int tF, int tL, int tS, int tT) +void Module::setChannel(int slot, int8_t chID, int16_t fID, bool read, bool trig, int tF, int tL, int tS, int tT) { if (slot < 0 || slot >= MaxChannels || chID < 0 || chID > NChannels) { - LOG(FATAL) << "Improper module channel settings" << slot << ' ' << chID << ' ' << lID << ' ' << read << ' ' << trig + LOG(FATAL) << "Improper module channel settings" << slot << ' ' << chID << ' ' << fID << ' ' << read << ' ' << trig << ' ' << tF << ' ' << tL << ' ' << tS << ' ' << tT; } - linkID[slot] = lID; + feeID[slot] = fID; channelID[slot] = chID; readChannel[slot] = read; // In the 2020 firmware implementation, autotrigger bits are computed for each channel diff --git a/Detectors/ZDC/macro/CreateModuleConfig.C b/Detectors/ZDC/macro/CreateModuleConfig.C index d992c10230f01..164a71bb83d1f 100644 --- a/Detectors/ZDC/macro/CreateModuleConfig.C +++ b/Detectors/ZDC/macro/CreateModuleConfig.C @@ -33,9 +33,11 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, //------------------------------------------- // Up to 8 modules with four channels - // setChannel(int slot, int8_t chID, int16_t lID, bool read, bool trig = false, int tF = 0, int tL = 0, int tS = 0, int tT = 0) + // setChannel(int slot, int8_t chID, int16_t fID, bool read, bool trig = false, int tF = 0, int tL = 0, int tS = 0, int tT = 0) // module id must be in the range 0-7 // channel id must be in range 0-3 + // frontend id must be in range 0-15 and identify the pair of channels connected to + // each fibre { modID = 0; auto& module = conf.modules[modID]; diff --git a/Detectors/ZDC/simulation/CMakeLists.txt b/Detectors/ZDC/simulation/CMakeLists.txt index f58348a73e05d..e4dc53138c392 100644 --- a/Detectors/ZDC/simulation/CMakeLists.txt +++ b/Detectors/ZDC/simulation/CMakeLists.txt @@ -10,9 +10,10 @@ o2_add_library(ZDCSimulation SOURCES src/Detector.cxx src/Digitizer.cxx src/SimCondition.cxx - src/ZDCSimParam.cxx src/SpatialPhotonResponse.cxx - PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase - O2::DataFormatsZDC O2::CCDB O2::SimConfig) + src/ZDCSimParam.cxx src/SpatialPhotonResponse.cxx src/Digits2Raw.cxx + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase + O2::DataFormatsZDC O2::CCDB O2::SimConfig + O2::DetectorsRaw O2::Headers) o2_target_root_dictionary(ZDCSimulation HEADERS include/ZDCSimulation/Hit.h @@ -23,3 +24,12 @@ o2_target_root_dictionary(ZDCSimulation include/ZDCSimulation/SpatialPhotonResponse.h) o2_data_file(COPY data DESTINATION Detectors/ZDC/simulation) + +o2_add_executable(digi2raw + COMPONENT_NAME zdc + SOURCES src/digi2raw.cxx + PUBLIC_LINK_LIBRARIES O2::ZDCSimulation + O2::DetectorsRaw + O2::DetectorsCommonDataFormats + O2::CommonUtils + Boost::program_options) diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h index ce717e5a97593..a9d6cf8843556 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Digitizer.h @@ -110,7 +110,6 @@ class Digitizer private: static constexpr int BCCacheMin = -1, BCCacheMax = 5, NBC2Cache = 1 + BCCacheMax - BCCacheMin; - static constexpr int ADCMin = -2048, ADCMax = 2047; // 12 bit ADC std::bitset<NChannels> chanPattern(uint32_t v) const { diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Digits2Raw.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Digits2Raw.h new file mode 100644 index 0000000000000..48b41b73c8c05 --- /dev/null +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Digits2Raw.h @@ -0,0 +1,103 @@ +// 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 Digits2Raw.h +/// \brief converts digits to raw format +/// \author pietro.cortese@cern.ch + +#ifndef ALICEO2_ZDC_DIGITS2RAW_H_ +#define ALICEO2_ZDC_DIGITS2RAW_H_ +#include <string> +#include <bitset> +#include <Rtypes.h> +#include "Headers/RAWDataHeader.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DetectorsRaw/RawFileWriter.h" +#include "DetectorsRaw/HBFUtils.h" +#include "DataFormatsZDC/RawEventData.h" +#include "ZDCBase/ModuleConfig.h" +#include "ZDCSimulation/SimCondition.h" +#include "DataFormatsZDC/BCData.h" +#include "DataFormatsZDC/ChannelData.h" + +namespace o2 +{ +namespace zdc +{ +class Digits2Raw +{ + public: + Digits2Raw() = default; + void emptyBunches(std::bitset<3564>& bunchPattern); /// Prepare list of clean empty bunches for baseline evaluation + void processDigits(const std::string& outDir, const std::string& fileDigitsName); + void setModuleConfig(const ModuleConfig* moduleConfig) { mModuleConfig = moduleConfig; }; + const ModuleConfig* getModuleConfig() { return mModuleConfig; }; + void setSimCondition(const SimCondition* SimCondition) { mSimCondition = SimCondition; }; + const SimCondition* getSimCondition() { return mSimCondition; }; + + o2::raw::RawFileWriter& getWriter() { return mWriter; } + + void setFilePerLink(bool v) { mOutputPerLink = v; } + bool getFilePerLink() const { return mOutputPerLink; } + + void setVerbosity(int v) + { + mVerbosity = v; + mWriter.setVerbosity(v); + } + int getVerbosity() const { return mVerbosity; } + + // void setContinuous(bool v = true) { mIsContinuous = v; } + bool isContinuous() const { return mIsContinuous; } + static void print_gbt_word(const UInt_t* word, const ModuleConfig* moduleConfig = nullptr); + + private: + void setTriggerMask(); + void updatePedestalReference(int bc); + void resetSums(uint32_t orbit); + void resetOutputStructure(UShort_t bc, UInt_t orbit, bool is_dummy); /// Reset output structure not incrementing scalers for dummy bunches + void assignTriggerBits(int ibc, UShort_t bc, UInt_t orbit, bool is_dummy); /// Assign trigger bits + void insertLastBunch(int ibc, uint32_t orbit); /// Insert an empty bunch at last position in orbit + void convertDigits(int ibc); /// Convert digits into raw data + void writeDigits(); /// Writes raw data to file + std::vector<o2::zdc::BCData> mzdcBCData, *mzdcBCDataPtr = &mzdcBCData; + std::vector<o2::zdc::ChannelData> mzdcChData, *mzdcChDataPtr = &mzdcChData; + int mNbc = 0; + BCData mBCD; + EventData mZDC; /// Output structure + bool mIsContinuous = true; /// Continuous (self-triggered) or externally-triggered readout + bool mOutputPerLink = false; /// Split output + const ModuleConfig* mModuleConfig = nullptr; /// Trigger/readout configuration object + const SimCondition* mSimCondition = nullptr; /// Pedestal/noise configuration object + UShort_t mScalers[NModules][NChPerModule] = {0}; /// ZDC orbit scalers + UInt_t mLastOrbit = 0; /// Last processed orbit + uint32_t mTriggerMask = 0; /// Trigger mask from ModuleConfig + std::string mPrintTriggerMask = ""; /// Nice printout of trigger mask + int32_t mNEmpty = -1; /// Number of clean empty bunches for pedestal evaluation + std::array<uint16_t, o2::constants::lhc::LHCMaxBunches> mEmpty = {0}; /// Clean empty bunches along orbit + UInt_t mLastNEmpty = 0; /// Last number of empty bunches used + Double_t mSumPed[NModules][NChPerModule] = {0}; /// Pedestal integrated on clean empty bunches + uint16_t mPed[NModules][NChPerModule] = {0}; /// Current pedestal + + o2::raw::RawFileWriter mWriter{"ZDC"}; + uint32_t mLinkID = 0; + uint16_t mCruID = 0; + uint32_t mEndPointID = 0; + uint64_t mFeeID = 0; + + int mVerbosity = 0; + + ///////////////////////////////////////////////// + ClassDefNV(Digits2Raw, 1); +}; +} // namespace zdc +} // namespace o2 + +#endif diff --git a/Detectors/ZDC/simulation/src/Digitizer.cxx b/Detectors/ZDC/simulation/src/Digitizer.cxx index ae03970780442..536fd5070ba3b 100644 --- a/Detectors/ZDC/simulation/src/Digitizer.cxx +++ b/Detectors/ZDC/simulation/src/Digitizer.cxx @@ -8,6 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "CommonConstants/LHCConstants.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CCDBTimeStampUtils.h" #include "ZDCSimulation/Digitizer.h" @@ -19,11 +20,13 @@ using namespace o2::zdc; +//______________________________________________________________________________ Digitizer::BCCache::BCCache() { memset(&data, 0, NChannels * sizeof(ChannelBCDataF)); } +//______________________________________________________________________________ Digitizer::ModuleConfAux::ModuleConfAux(const Module& md) : id(md.id) { if (md.id < 0 || md.id >= NModules) { @@ -42,6 +45,7 @@ Digitizer::ModuleConfAux::ModuleConfAux(const Module& md) : id(md.id) } } +//______________________________________________________________________________ // this will process hits and fill the digit vector with digits which are finalized void Digitizer::process(const std::vector<o2::zdc::Hit>& hits, std::vector<o2::zdc::BCData>& digitsBC, @@ -98,6 +102,7 @@ void Digitizer::process(const std::vector<o2::zdc::Hit>& hits, } } +//______________________________________________________________________________ void Digitizer::flush(std::vector<o2::zdc::BCData>& digitsBC, std::vector<o2::zdc::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::zdc::MCLabel>& labels) @@ -163,6 +168,7 @@ void Digitizer::flush(std::vector<o2::zdc::BCData>& digitsBC, mCache.erase(mCache.begin(), mCache.end()); } +//______________________________________________________________________________ void Digitizer::generatePedestal() { for (int idet : {ZNA, ZPA, ZNC, ZPC}) { @@ -179,6 +185,7 @@ void Digitizer::generatePedestal() mPedestalBLFluct[IdZEM2] = gRandom->Gaus(0, mSimCondition->channels[IdZEM2].pedestalFluct); } +//______________________________________________________________________________ void Digitizer::digitizeBC(BCCache& bc) { auto& bcdata = bc.data; @@ -230,10 +237,10 @@ void Digitizer::digitizeBC(BCCache& bc) } } } - bc.digitized = true; } +//______________________________________________________________________________ bool Digitizer::triggerBC(int ibc) { // check trigger for the cached BC in the position ibc @@ -293,6 +300,7 @@ bool Digitizer::triggerBC(int ibc) return bcCached.trigChanMask; } +//______________________________________________________________________________ void Digitizer::storeBC(const BCCache& bc, uint32_t chan2Store, std::vector<o2::zdc::BCData>& digitsBC, std::vector<o2::zdc::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::zdc::MCLabel>& labels) @@ -326,6 +334,7 @@ void Digitizer::storeBC(const BCCache& bc, uint32_t chan2Store, } } +//______________________________________________________________________________ void Digitizer::phe2Sample(int nphe, int parID, double timeHit, std::array<o2::InteractionRecord, NBC2Cache> const& cachedIR, int nCachedIR, int channel) { //function to simulate the waveform from no. of photoelectrons seen in a given sample @@ -360,6 +369,7 @@ void Digitizer::phe2Sample(int nphe, int parID, double timeHit, std::array<o2::I } while (++ir < nCachedIR && !stop); } +//______________________________________________________________________________ o2::zdc::Digitizer::BCCache& Digitizer::getCreateBCCache(const o2::InteractionRecord& ir) { if (mCache.empty() || mCache.back() < ir) { @@ -388,6 +398,7 @@ o2::zdc::Digitizer::BCCache& Digitizer::getCreateBCCache(const o2::InteractionRe return mCache.front(); } +//______________________________________________________________________________ o2::zdc::Digitizer::BCCache* Digitizer::getBCCache(const o2::InteractionRecord& ir) { // get pointer on existing cache @@ -399,6 +410,7 @@ o2::zdc::Digitizer::BCCache* Digitizer::getBCCache(const o2::InteractionRecord& return nullptr; } +//______________________________________________________________________________ void Digitizer::init() { if (mCCDBServer.empty()) { @@ -414,6 +426,7 @@ void Digitizer::init() << " BCs will be stored ahead of Trigger"; } +//______________________________________________________________________________ void Digitizer::refreshCCDB() { // fetch ccdb objects. TODO: decide if this stays here or goes to the Spec @@ -437,7 +450,7 @@ void Digitizer::refreshCCDB() if (md.trigChannel[ic] || (md.trigChannelConf[ic].shift > 0 && md.trigChannelConf[ic].threshold > 0)) { const auto& trgChanConf = md.trigChannelConf[ic]; if (trgChanConf.last + trgChanConf.shift + 1 >= NTimeBinsPerBC) { - LOG(FATAL) << "Wrong trigger settings"; + LOG(ERROR) << "Wrong trigger settings"; } mTriggerConfig.emplace_back(trgChanConf); // We insert in the trigger mask only the channels that are actually triggering @@ -457,6 +470,9 @@ void Digitizer::refreshCCDB() mTrigBinMax = trgChanConf.last + trgChanConf.shift; } } + if (md.feeID[ic] < 0 || md.feeID[ic] >= NLinks) { + LOG(ERROR) << "FEEID " << md.feeID[ic] << " not in allowed range [0:" << NLinks << ")"; + } } } else { LOG(FATAL) << "Module id: " << md.id << " is out of range"; @@ -472,7 +488,7 @@ void Digitizer::refreshCCDB() } } -//______________________________________________________________ +//______________________________________________________________________________ void Digitizer::BCCache::print() const { std::bitset<NChannels> tmsk(trigChanMask); diff --git a/Detectors/ZDC/simulation/src/Digits2Raw.cxx b/Detectors/ZDC/simulation/src/Digits2Raw.cxx new file mode 100644 index 0000000000000..029fedb3daad9 --- /dev/null +++ b/Detectors/ZDC/simulation/src/Digits2Raw.cxx @@ -0,0 +1,704 @@ +// 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 <string> +#include <TFile.h> +#include <TTree.h> +#include <TRandom.h> +#include <TMath.h> +#include "ZDCBase/Constants.h" +#include "ZDCBase/ModuleConfig.h" +#include "ZDCSimulation/Digitizer.h" +#include "ZDCSimulation/Digits2Raw.h" +#include "ZDCSimulation/MCLabel.h" +#include "ZDCSimulation/ZDCSimParam.h" +#include "CommonUtils/StringUtils.h" +#include "FairLogger.h" + +using namespace o2::zdc; + +//ClassImp(Digits2Raw); +//______________________________________________________________________________ +void Digits2Raw::processDigits(const std::string& outDir, const std::string& fileDigitsName) +{ + auto& sopt = ZDCSimParam::Instance(); + mIsContinuous = sopt.continuous; + + if (!mModuleConfig) { + LOG(FATAL) << "Missing ModuleConfig configuration object"; + return; + } + + if (!mSimCondition) { + LOG(FATAL) << "Missing SimCondition configuration object"; + return; + } + + if (mNEmpty < 0) { + LOG(FATAL) << "Bunch crossing map is not initialized"; + return; + } + + if (mNEmpty == 0) { + LOG(WARNING) << "Bunch crossing map has zero clean empty bunches"; + } + + setTriggerMask(); + + std::string outd = outDir; + if (outd.back() != '/') { + outd += '/'; + } + + mLinkID = uint32_t(0); + mCruID = uint16_t(0); + mEndPointID = uint32_t(0); + for (int ilink = 0; ilink < NLinks; ilink++) { + mFeeID = uint64_t(ilink); + std::string outFileLink = mOutputPerLink ? o2::utils::concat_string(outd, "zdc_link", std::to_string(ilink), ".raw") : o2::utils::concat_string(outd, "zdc.raw"); + mWriter.registerLink(mFeeID, mCruID, mLinkID, mEndPointID, outFileLink); + } + + std::unique_ptr<TFile> digiFile(TFile::Open(fileDigitsName.c_str())); + if (!digiFile || digiFile->IsZombie()) { + LOG(ERROR) << "Failed to open input digits file " << fileDigitsName; + return; + } + + TTree* digiTree = (TTree*)digiFile->Get("o2sim"); + if (!digiTree) { + LOG(ERROR) << "Failed to get digits tree"; + return; + } + + if (digiTree->GetBranch("ZDCDigitBC")) { + digiTree->SetBranchAddress("ZDCDigitBC", &mzdcBCDataPtr); + } else { + LOG(ERROR) << "Branch ZDCDigitBC is missing"; + return; + } + + if (digiTree->GetBranch("ZDCDigitCh")) { + digiTree->SetBranchAddress("ZDCDigitCh", &mzdcChDataPtr); + } else { + LOG(ERROR) << "Branch ZDCDigitCh is missing"; + return; + } + + digiTree->SetBranchStatus("ZDCDigitLabel*", 0); + + for (int ient = 0; ient < digiTree->GetEntries(); ient++) { + digiTree->GetEntry(ient); + mNbc = mzdcBCData.size(); + LOG(INFO) << "Entry " << ient << " : " << mNbc << " BCs stored"; + for (int ibc = 0; ibc < mNbc; ibc++) { + mBCD = mzdcBCData[ibc]; + convertDigits(ibc); + writeDigits(); + // Detect last event or orbit change and insert last bunch + if (ibc == (mNbc - 1)) { + // For last event we need to close last orbit (if it is needed) + if (mzdcBCData[ibc].ir.bc != 3563) { + insertLastBunch(ibc, mzdcBCData[ibc].ir.orbit); + writeDigits(); + } + } else { + auto this_orbit = mzdcBCData[ibc].ir.orbit; + auto next_orbit = mzdcBCData[ibc + 1].ir.orbit; + // If current bunch is last bunch in the orbit we don't insert it again + if (mzdcBCData[ibc].ir.bc == 3563) { + this_orbit = this_orbit + 1; + } + // We may need to insert more than one orbit + for (auto orbit = this_orbit; orbit < next_orbit; orbit++) { + insertLastBunch(ibc, orbit); + writeDigits(); + } + } + } + } + digiFile->Close(); +} + +//______________________________________________________________________________ +void Digits2Raw::setTriggerMask() +{ + mTriggerMask = 0; + mPrintTriggerMask = ""; + for (Int_t im = 0; im < NModules; im++) { + if (im > 0) { + mPrintTriggerMask += " "; + } + mPrintTriggerMask += std::to_string(im); + mPrintTriggerMask += "["; + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + if (mModuleConfig->modules[im].trigChannel[ic]) { + UInt_t tmask = 0x1 << (im * NChPerModule + ic); + mTriggerMask = mTriggerMask | tmask; + mPrintTriggerMask += "T"; + } else { + mPrintTriggerMask += " "; + } + } + mPrintTriggerMask += "]"; + UInt_t mytmask = mTriggerMask >> (im * NChPerModule); + printf("Trigger mask for module %d 0123 %s%s%s%s\n", im, + mytmask & 0x1 ? "T" : "N", + mytmask & 0x2 ? "T" : "N", + mytmask & 0x4 ? "T" : "N", + mytmask & 0x8 ? "T" : "N"); + } + printf("trigger_mask=0x%08x %s\n", mTriggerMask, mPrintTriggerMask.data()); +} + +//______________________________________________________________________________ +inline void Digits2Raw::resetSums(uint32_t orbit) +{ + for (Int_t im = 0; im < NModules; im++) { + for (Int_t ic = 0; ic < NChPerModule; ic++) { + mScalers[im][ic] = 0; + mSumPed[im][ic] = 0; + mPed[im][ic] = 0; + } + } + mLastOrbit = orbit; + mLastNEmpty = 0; +} + +//______________________________________________________________________________ +inline void Digits2Raw::updatePedestalReference(int bc) +{ + // Compute or update baseline reference + if (mEmpty[bc] > 0 && mEmpty[bc] != mLastNEmpty) { + for (Int_t im = 0; im < NModules; im++) { + for (Int_t ic = 0; ic < NChPerModule; ic++) { + // Identify connected channel + auto id = mModuleConfig->modules[im].channelID[ic]; + auto base_m = mSimCondition->channels[id].pedestal; // Average pedestal + auto base_s = mSimCondition->channels[id].pedestalFluct; // Baseline oscillations + auto base_n = mSimCondition->channels[id].pedestalNoise; // Electronic noise + Double_t deltan = mEmpty[bc] - mLastNEmpty; + // We assume to have a fluctuation every two bunch crossings + // Will need to tune this parameter + Double_t k = 2.; + mSumPed[im][ic] += gRandom->Gaus(12. * deltan * base_m, 12. * k * base_s * TMath::Sqrt(deltan / k)); + // Adding in quadrature the RMS of pedestal electronic noise + mSumPed[im][ic] += gRandom->Gaus(0, base_n * TMath::Sqrt(12. * deltan)); + Double_t myped = TMath::Nint(8. * mSumPed[im][ic] / Double_t(mEmpty[bc]) / 12. + 32768); + if (myped < 0) { + myped = 0; + } + if (myped > 65535) { + myped = 65535; + } + mPed[im][ic] = myped; + } + } + mLastNEmpty = mEmpty[bc]; + } +} + +//______________________________________________________________________________ +inline void Digits2Raw::resetOutputStructure(UShort_t bc, UInt_t orbit, bool is_dummy) +{ + // Increment scalers and reset output structure + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + // Fixed words + mZDC.data[im][ic].w[0][0] = Id_w0; + mZDC.data[im][ic].w[0][1] = 0; + mZDC.data[im][ic].w[0][2] = 0; + mZDC.data[im][ic].w[0][3] = 0; + mZDC.data[im][ic].w[1][0] = Id_w1; + mZDC.data[im][ic].w[1][1] = 0; + mZDC.data[im][ic].w[1][2] = 0; + mZDC.data[im][ic].w[1][3] = 0; + mZDC.data[im][ic].w[2][0] = Id_w2; + mZDC.data[im][ic].w[2][1] = 0; + mZDC.data[im][ic].w[2][2] = 0; + mZDC.data[im][ic].w[2][3] = 0; + // Module and channel numbers + mZDC.data[im][ic].f.board = im; + mZDC.data[im][ic].f.ch = ic; + // Orbit and bunch crossing + mZDC.data[im][ic].f.orbit = orbit; + mZDC.data[im][ic].f.bc = bc; + // If channel is hit in current bunch crossing + if (!is_dummy) { + if (mBCD.triggers & (0x1 << (im * NChPerModule + ic))) { + mScalers[im][ic]++; // increment scalers + mZDC.data[im][ic].f.Hit = 1; // flag bunch crossing + } + } + mZDC.data[im][ic].f.hits = mScalers[im][ic]; + mZDC.data[im][ic].f.offset = mPed[im][ic]; + } + } +} + +//______________________________________________________________________________ +inline void Digits2Raw::assignTriggerBits(int ibc, UShort_t bc, UInt_t orbit, bool is_dummy) +{ + // Triggers refer to the HW trigger conditions (32 possible channels) + // Autotrigger, current bunch crossing + UInt_t triggers_0 = 0; + // Autotrigger and ALICE trigger bits are zero for a dummy bunch crossing + if (!is_dummy) { + triggers_0 = mBCD.triggers; + // ALICE current bunch crossing + if (mBCD.ext_triggers) { + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Alice_0 = 1; + } + } + } + } + + // Next bunch crossings (ALICE and autotrigger) + UInt_t triggers_1 = 0, triggers_2 = 0, triggers_3 = 0, triggers_m = 0; + for (Int_t is = 1; is < 4; is++) { + Int_t ibc_peek = ibc + is; + if (ibc_peek >= mNbc) { + break; + } + const auto& bcd_peek = mzdcBCData[ibc_peek]; + UShort_t bc_peek = bcd_peek.ir.bc; + UInt_t orbit_peek = bcd_peek.ir.orbit; + if (bcd_peek.triggers) { + if (orbit_peek == orbit) { + if ((bc_peek - bc) == 1) { + triggers_1 = bcd_peek.triggers; + if (bcd_peek.ext_triggers) { + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Alice_1 = 1; + } + } + } + } else if ((bc_peek - bc) == 2) { + triggers_2 = bcd_peek.triggers; + if (bcd_peek.ext_triggers) { + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Alice_2 = 1; + } + } + } + } else if ((bc_peek - bc) == 3) { + triggers_3 = bcd_peek.triggers; + if (bcd_peek.ext_triggers) { + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Alice_3 = 1; + } + } + } + break; + } + } else if (orbit_peek == (orbit + 1)) { + if ((bc_peek + 3564 - bc) == 1) { + triggers_1 = bcd_peek.triggers; + if (bcd_peek.ext_triggers) { + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Alice_1 = 1; + } + } + } + } else if ((bc_peek + 3564 - bc) == 2) { + triggers_2 = bcd_peek.triggers; + if (bcd_peek.ext_triggers) { + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Alice_2 = 1; + } + } + } + } else if ((bc_peek + 3564 - bc) == 3) { + triggers_3 = bcd_peek.triggers; + if (bcd_peek.ext_triggers) { + for (UInt_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Alice_3 = 1; + } + } + } + break; + } + } else { + break; + } + } + } + + // Previous bunch crossing just for autotrigger + // For a dummy last bunch crossing previous bunch is the one pointed by ibc + { + Int_t ibc_peek = is_dummy ? ibc : ibc - 1; + if (ibc_peek >= 0) { + const auto& bcd_peek = mzdcBCData[ibc - 1]; + UShort_t bc_peek = bcd_peek.ir.bc; + UInt_t orbit_peek = bcd_peek.ir.orbit; + if (bcd_peek.triggers) { + if (orbit_peek == orbit) { + if ((bc - bc_peek) == 1) { + triggers_m = bcd_peek.triggers; + } + } else if (orbit_peek == (orbit - 1)) { + if (bc == 0 && bc_peek == 3563) { + triggers_m = bcd_peek.triggers; + } + } + } + } + } + + // Assign trigger bits in payload + for (Int_t im = 0; im < NModules; im++) { + UInt_t tmask = (0xf << (im * NChPerModule)) & mTriggerMask; + if (triggers_m & tmask) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Auto_m = 1; + } + } + if (triggers_0 & tmask) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Auto_0 = 1; + } + } + if (triggers_1 & tmask) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Auto_1 = 1; + } + } + if (triggers_2 & tmask) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Auto_2 = 1; + } + } + if (triggers_3 & tmask) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + mZDC.data[im][ic].f.Auto_3 = 1; + } + } + } +} + +//______________________________________________________________________________ +void Digits2Raw::insertLastBunch(int ibc, uint32_t orbit) +{ + + // Orbit and bunch crossing identifiers + UShort_t bc = 3563; + + // Reset scalers at orbit change + if (orbit != mLastOrbit) { + resetSums(orbit); + } + + updatePedestalReference(bc); + + // Dummy bunch -> Do not increment scalers but reset output structure + resetOutputStructure(bc, orbit, true); + + // Compute autotrigger bits and assign ALICE trigger bits + assignTriggerBits(ibc, bc, orbit, true); + + // Insert payload for all channels + for (Int_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + if (mModuleConfig->modules[im].readChannel[ic]) { + auto id = mModuleConfig->modules[im].channelID[ic]; + auto base_m = mSimCondition->channels[id].pedestal; // Average pedestal + auto base_s = mSimCondition->channels[id].pedestalFluct; // Baseline oscillations + auto base_n = mSimCondition->channels[id].pedestalNoise; // Electronic noise + Double_t base = gRandom->Gaus(base_m, base_s); + Int_t is = 0; + Double_t val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s00 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s01 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s02 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s03 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s04 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s05 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s06 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s07 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s08 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s09 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s10 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + is++; + val = base + gRandom->Gaus(0, base_n); + mZDC.data[im][ic].f.s11 = val < ADCMax ? (val > ADCMin ? val : ADCMin) : ADCMax; + } + } + } +} // insertLastBunch + +//______________________________________________________________________________ +void Digits2Raw::convertDigits(int ibc) +{ + + // Orbit and bunch crossing identifiers + UShort_t bc = mBCD.ir.bc; + UInt_t orbit = mBCD.ir.orbit; + + // Reset scalers at orbit change + if (orbit != mLastOrbit) { + resetSums(orbit); + } + + updatePedestalReference(bc); + + // Not a dummy bunch -> Reset output structure and eventually flag hits and increment scalers + resetOutputStructure(bc, orbit, false); + + // Compute autotrigger bits and assign ALICE trigger bits + assignTriggerBits(ibc, bc, orbit, false); + + if (mVerbosity > 0) { + mBCD.print(); + printf("Mask: %s\n", mPrintTriggerMask.data()); + } + + int chEnt = mBCD.ref.getFirstEntry(); + for (int ic = 0; ic < mBCD.ref.getEntries(); ic++) { + const auto& chd = mzdcChData[chEnt++]; + if (mVerbosity > 0) { + chd.print(); + } + UShort_t bc = mBCD.ir.bc; + UInt_t orbit = mBCD.ir.orbit; + // Look for channel ID in digits and store channel (just one copy in output) + // This is a limitation of software but we are not supposed to acquire the + // same signal twice anyway + for (Int_t im = 0; im < NModules; im++) { + for (UInt_t ic = 0; ic < NChPerModule; ic++) { + if (mModuleConfig->modules[im].channelID[ic] == chd.id && + mModuleConfig->modules[im].readChannel[ic]) { + Int_t is = 0; + mZDC.data[im][ic].f.s00 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s01 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s02 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s03 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s04 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s05 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s06 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s07 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s08 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s09 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s10 = chd.data[is]; + is++; + mZDC.data[im][ic].f.s11 = chd.data[is]; + break; + } + } + } + } +} + +//______________________________________________________________________________ +void Digits2Raw::writeDigits() +{ + constexpr static int data_size = sizeof(uint32_t) * NWPerGBTW; + // Local interaction record (true and empty bunches) + o2::InteractionRecord ir(mZDC.data[0][0].f.bc, mZDC.data[0][0].f.orbit); + for (UInt_t im = 0; im < o2::zdc::NModules; im++) { + // Check if module has been filled with data + // N.B. All channels are initialized if module is supposed to be readout + // Trigger bits are the same for all the channels connected to a module + bool TM = mZDC.data[im][0].f.Auto_m; + bool T0 = mZDC.data[im][0].f.Auto_0; + bool T1 = mZDC.data[im][0].f.Auto_1; + bool T2 = mZDC.data[im][0].f.Auto_2; + bool T3 = mZDC.data[im][0].f.Auto_3; + bool A0 = mZDC.data[im][0].f.Alice_0; + bool A1 = mZDC.data[im][0].f.Alice_1; + bool A2 = mZDC.data[im][0].f.Alice_2; + bool A3 = mZDC.data[im][0].f.Alice_3; + bool tcond_continuous = T0 || T1; + bool tcond_triggered = A0 || A1 || (A2 && (T0 || TM)) || (A3 && T0); + bool tcond_last = mZDC.data[im][0].f.bc == 3563; + // Condition to write GBT data + if (tcond_triggered || (mIsContinuous && tcond_continuous) || (mZDC.data[im][0].f.bc == 3563)) { + for (UInt_t ic = 0; ic < o2::zdc::NChPerModule; ic++) { + if (mModuleConfig->modules[im].readChannel[ic]) { + for (Int_t iw = 0; iw < o2::zdc::NWPerBc; iw++) { + gsl::span<char> payload{reinterpret_cast<char*>(&mZDC.data[im][ic].w[iw][0]), data_size}; + mWriter.addData(mFeeID, mCruID, mLinkID, mEndPointID, ir, payload); + } + } + } + } + if (mVerbosity > 1) { + if (tcond_continuous) { + printf("M%d Cont. T0=%d || T1=%d\n", im, T0, T1); + } + if (tcond_triggered) { + printf("M%d Trig. %s A0=%d || A1=%d || (A2=%d && (T0=%d || TM=%d))=%d || (A3=%d && T0=%d )=%d\n", im, mIsContinuous ? "CM" : "TM", A0, A1, A2, T0, TM, A2 && (T0 || TM), A3, T0, A3 && T0); + } + if (mZDC.data[im][0].f.bc == 3563) { + printf("M%d is last BC\n", im); + } + if (tcond_triggered || (mIsContinuous && tcond_continuous) || (mZDC.data[im][0].f.bc == 3563)) { + for (UInt_t ic = 0; ic < o2::zdc::NChPerModule; ic++) { + if (mModuleConfig->modules[im].readChannel[ic]) { + for (Int_t iw = 0; iw < o2::zdc::NWPerBc; iw++) { + print_gbt_word(&mZDC.data[im][ic].w[iw][0], mModuleConfig); + } + } + } + } else { + if (mVerbosity > 2) { + printf("orbit %9u bc %4u M%d SKIP\n", mZDC.data[im][0].f.orbit, mZDC.data[im][0].f.bc, im); + } + } + } + } +} + +//______________________________________________________________________________ +void Digits2Raw::print_gbt_word(const UInt_t* word, const ModuleConfig* moduleConfig) +{ + if (word == nullptr) { + printf("NULL\n"); + return; + } + unsigned __int128 val = word[2]; + val = val << 32; + val = val | word[1]; + val = val << 32; + val = val | word[0]; + static UInt_t last_orbit = 0, last_bc = 0; + + ULong64_t lsb = val; + ULong64_t msb = val >> 64; + UInt_t a = word[0]; + UInt_t b = word[1]; + UInt_t c = word[2]; + //UInt_t d=(msb>>32)&0xffffffff; + //printf("\n%llx %llx ",lsb,msb); + //printf("\n%8x %8x %8x %8x ",d,c,b,a); + if ((a & 0x3) == 0) { + UInt_t myorbit = (val >> 48) & 0xffffffff; + UInt_t mybc = (val >> 36) & 0xfff; + if (myorbit != last_orbit || mybc != last_bc) { + printf("Orbit %9u bc %4u\n", myorbit, mybc); + last_orbit = myorbit; + last_bc = mybc; + } + printf("%04x %08x %08x ", c, b, a); + UInt_t hits = (val >> 24) & 0xfff; + Int_t offset = (lsb >> 8) & 0xffff - 32768; + Float_t foffset = offset / 8.; + UInt_t board = (lsb >> 2) & 0xf; + UInt_t ch = (lsb >> 6) & 0x3; + //printf("orbit %9u bc %4u hits %4u offset %+6i Board %2u Ch %1u", myorbit, mybc, hits, offset, board, ch); + printf("orbit %9u bc %4u hits %4u offset %+8.3f Board %2u Ch %1u", myorbit, mybc, hits, foffset, board, ch); + if (board >= NModules) { + printf(" ERROR with board"); + } + if (ch >= NChPerModule) { + printf(" ERROR with ch"); + } + if (moduleConfig) { + auto id = moduleConfig->modules[board].channelID[ch]; + if (id >= 0 && id < NChannels) { + printf(" %s", ChannelNames[id].data()); + } else { + printf(" error with ch id"); + } + } + } else if ((a & 0x3) == 1) { + printf("%04x %08x %08x ", c, b, a); + printf(" %s %s %s %s ", a & 0x10 ? "A0" : " ", a & 0x20 ? "A1" : " ", a & 0x40 ? "A2" : " ", a & 0x80 ? "A3" : " "); + printf("0-5 "); + Short_t s[6]; + val = val >> 8; + for (Int_t i = 0; i < 6; i++) { + s[i] = val & 0xfff; + if (s[i] > ADCMax) { + s[i] = s[i] - ADCRange; + } + val = val >> 12; + } + printf(" %5d %5d %5d %5d %5d %5d", s[0], s[1], s[2], s[3], s[4], s[5]); + } else if ((a & 0x3) == 2) { + printf("%04x %08x %08x ", c, b, a); + printf("%s %s %s %s %s %s ", a & 0x4 ? "H" : " ", a & 0x8 ? "TM" : " ", a & 0x10 ? "T0" : " ", a & 0x20 ? "T1" : " ", a & 0x40 ? "T2" : " ", a & 0x80 ? "T3" : " "); + printf("6-b "); + Short_t s[6]; + val = val >> 8; + for (Int_t i = 0; i < 6; i++) { + s[i] = val & 0xfff; + if (s[i] > ADCMax) { + s[i] = s[i] - ADCRange; + } + val = val >> 12; + } + printf(" %5d %5d %5d %5d %5d %5d", s[0], s[1], s[2], s[3], s[4], s[5]); + } else if ((a & 0x3) == 3) { + printf("%04x %08x %08x ", c, b, a); + printf("HB "); + } + printf("\n"); +} + +//______________________________________________________________________________ +void Digits2Raw::emptyBunches(std::bitset<3564>& bunchPattern) +{ + const int LHCMaxBunches = o2::constants::lhc::LHCMaxBunches; + mNEmpty = 0; + for (Int_t ib = 0; ib < LHCMaxBunches; ib++) { + Int_t mb = (ib + 31) % LHCMaxBunches; // beam gas from back of calorimeter + Int_t m1 = (ib + 1) % LHCMaxBunches; // previous bunch + Int_t cb = ib; // current bunch crossing + Int_t p1 = (ib - 1) % LHCMaxBunches; // colliding + 1 + Int_t p2 = (ib + 1) % LHCMaxBunches; // colliding + 2 + Int_t p3 = (ib + 1) % LHCMaxBunches; // colliding + 3 + if (bunchPattern[mb] || bunchPattern[m1] || bunchPattern[cb] || bunchPattern[p1] || bunchPattern[p2] || bunchPattern[p3]) { + mEmpty[ib] = mNEmpty; + } else { + mNEmpty++; + mEmpty[ib] = mNEmpty; + } + } + LOG(INFO) << "There are " << mNEmpty << " clean empty bunches"; +} diff --git a/Detectors/ZDC/simulation/src/digi2raw.cxx b/Detectors/ZDC/simulation/src/digi2raw.cxx new file mode 100644 index 0000000000000..ef4c62bd85132 --- /dev/null +++ b/Detectors/ZDC/simulation/src/digi2raw.cxx @@ -0,0 +1,171 @@ +// 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 digi2raw.cxx +/// \author ruben.shahoyan@cern.ch + +#include <boost/program_options.hpp> +#include <TSystem.h> +#include <TFile.h> +#include <TStopwatch.h> +#include "Framework/Logger.h" +#include <string> +#include <iomanip> +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CCDBTimeStampUtils.h" +#include "CommonUtils/StringUtils.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCommonDataFormats/NameConf.h" +#include "DetectorsRaw/HBFUtils.h" +#include "ZDCBase/Constants.h" +#include "ZDCBase/ModuleConfig.h" +#include "DataFormatsZDC/BCData.h" +#include "DataFormatsZDC/ChannelData.h" +#include "ZDCSimulation/Digits2Raw.h" +#include "DataFormatsParameters/GRPObject.h" +#include "SimulationDataFormat/DigitizationContext.h" +#include "SimConfig/DigiParams.h" + +/// MC->raw conversion for ZDC + +namespace bpo = boost::program_options; + +void digi2raw(const std::string& inpName, const std::string& outDir, int verbosity, bool filePerLink, uint32_t rdhV = 4, + const std::string& ccdbHost = "", int superPageSizeInB = 1024 * 1024); + +int main(int argc, char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + "Convert ZDC digits to CRU raw data\n"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + add_option("verbosity,v", bpo::value<int>()->default_value(0), "verbosity level"); + // add_option("input-file,i", bpo::value<std::string>()->default_value(o2::base::NameConf::getDigitsFileName(o2::detectors::DetID::ZDC)),"input ZDC digits file"); // why not used? + add_option("input-file,i", bpo::value<std::string>()->default_value("zdcdigits.root"), "input ZDC digits file"); + add_option("file-per-link,l", bpo::value<bool>()->default_value(false)->implicit_value(true), "create output file per CRU (default: write single file)"); + add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); + add_option("ccdb-url,c", bpo::value<std::string>()->default_value(""), "url of the ccdb repository"); + uint32_t defRDH = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>(); + add_option("rdh-version,r", bpo::value<uint32_t>()->default_value(defRDH), "RDH version to use"); + add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help")) { + std::cout << opt_general << std::endl; + exit(0); + } + + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + o2::conf::ConfigurableParam::updateFromString(vm["configKeyValues"].as<std::string>()); + + std::string ccdb_url = vm["ccdb-url"].as<std::string>(); + auto& dopt = o2::conf::DigiParams::Instance(); + std::string ccdbHost = dopt.ccdb; + if (ccdb_url.length() > 0) { + ccdbHost = ccdb_url; + LOG(INFO) << "CCDB url set to " << ccdb_url; + } + LOG(INFO) << "CCDB url " << ccdbHost; + digi2raw(vm["input-file"].as<std::string>(), + vm["output-dir"].as<std::string>(), + vm["verbosity"].as<int>(), + vm["file-per-link"].as<bool>(), + vm["rdh-version"].as<uint32_t>(), + ccdbHost); + + return 0; +} + +void digi2raw(const std::string& inpName, const std::string& outDir, int verbosity, bool filePerLink, uint32_t rdhV, const std::string& ccdbHost, int superPageSizeInB) +{ + long timeStamp = 0; + //std::string ccdbHost = "http://ccdb-test.cern.ch:8080"; + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); + mgr.setURL(ccdbHost); + if (timeStamp == mgr.getTimestamp()) { + return; + } + mgr.setTimestamp(timeStamp); + auto moduleConfig = mgr.get<o2::zdc::ModuleConfig>(o2::zdc::CCDBPathConfigModule); + if (!moduleConfig) { + LOG(FATAL) << "Cannot module configuratio for timestamp " << timeStamp; + return; + } + LOG(INFO) << "Loaded module configuration for timestamp " << timeStamp; + + auto simCondition = mgr.get<o2::zdc::SimCondition>(o2::zdc::CCDBPathConfigSim); + if (!simCondition) { + LOG(FATAL) << "Cannot get simulation configuration for timestamp " << timeStamp; + return; + } + LOG(INFO) << "Loaded simulation configuration for timestamp " << timeStamp; + simCondition->print(); + + const auto* ctx = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + const auto& bcfill = ctx->getBunchFilling(); + auto bf = ctx->getBunchFilling(); + if (verbosity > 0) { + bf.print(); + } + auto bp = bf.getPattern(); + + TStopwatch swTot; + swTot.Start(); + + o2::zdc::Digits2Raw d2r; + d2r.setFilePerLink(filePerLink); + d2r.setVerbosity(verbosity); + auto& wr = d2r.getWriter(); + std::string inputGRP = o2::base::NameConf::getGRPFileName(); + const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP); + wr.setContinuousReadout(grp->isDetContinuousReadOut(o2::detectors::DetID::ZDC)); // must be set explicitly + wr.setSuperPageSize(superPageSizeInB); + wr.useRDHVersion(rdhV); + + std::string outDirName(outDir); + if (outDirName.back() != '/') { + outDirName += '/'; + } + // if needed, create output directory + if (gSystem->AccessPathName(outDirName.c_str())) { + if (gSystem->mkdir(outDirName.c_str(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outDirName; + } else { + LOG(INFO) << "created output directory " << outDirName; + } + } + + d2r.setModuleConfig(moduleConfig); + d2r.setSimCondition(simCondition); + d2r.emptyBunches(bp); + d2r.setVerbosity(verbosity); + d2r.processDigits(outDirName, inpName); + wr.writeConfFile(wr.getOrigin().str, "RAWDATA", o2::utils::concat_string(outDirName, wr.getOrigin().str, "raw.cfg")); + // + swTot.Stop(); + swTot.Print(); +} diff --git a/Detectors/ZDC/simulation/src/raw-parser.cxx b/Detectors/ZDC/simulation/src/raw-parser.cxx new file mode 100644 index 0000000000000..616a7eaa7ee27 --- /dev/null +++ b/Detectors/ZDC/simulation/src/raw-parser.cxx @@ -0,0 +1,98 @@ +// 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/WorkflowSpec.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/ControlService.h" +#include "Framework/Logger.h" +#include "Framework/ConfigParamSpec.h" +#include "DPLUtils/DPLRawParser.h" +#include "Headers/DataHeader.h" +#include "DataFormatsZDC/RawEventData.h" +#include "ZDCSimulation/Digits2Raw.h" +#include <vector> +#include <sstream> + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back( + ConfigParamSpec{ + "input-spec", VariantType::String, "A:ZDC/RAWDATA", {"selection string input specs"}}); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& config) +{ + printf("Ciao\n"); + WorkflowSpec workflow; + workflow.emplace_back(DataProcessorSpec{ + "zdc-raw-parser", + select(config.options().get<std::string>("input-spec").c_str()), + Outputs{}, + AlgorithmSpec{[](InitContext& setup) { + auto loglevel = setup.options().get<int>("log-level"); + return adaptStateless([loglevel](InputRecord& inputs, DataAllocator& outputs) { + DPLRawParser parser(inputs); + o2::header::DataHeader const* lastDataHeader = nullptr; + std::stringstream rdhprintout; + for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { + // retrieving RDH v4 + auto const* rdh = it.get_if<o2::header::RAWDataHeaderV4>(); + // retrieving the raw pointer of the page + auto const* raw = it.raw(); + // retrieving payload pointer of the page + auto const* payload = it.data(); + // size of payload + size_t payloadSize = it.size(); + // offset of payload in the raw page + size_t offset = it.offset(); + // Note: the following code is only for printing out raw page information + const auto* dh = it.o2DataHeader(); + if (loglevel > 0) { + if (dh != lastDataHeader) { + // print the DataHeader information only for the first part or if we have high verbosity + if (loglevel > 1 || dh->splitPayloadIndex == 0) { + rdhprintout << dh->dataOrigin.as<std::string>() << "/" + << dh->dataDescription.as<std::string>() << "/" + << dh->subSpecification << " "; + // at high verbosity print part number, otherwise only the total number of parts + if (loglevel > 1) { + rdhprintout << "part " + std::to_string(dh->splitPayloadIndex) + " of " + std::to_string(dh->splitPayloadParts); + } else { + rdhprintout << " " + std::to_string(dh->splitPayloadParts) + " part(s)"; + } + rdhprintout << " payload size " << dh->payloadSize << std::endl; + } + if (!rdhprintout.str().empty()) { + LOG(INFO) << rdhprintout.str(); + rdhprintout.str(std::string()); + } + } + if(payload!=0){ + for(Int_t ip=0; ip<payloadSize; ip+=16){ + o2::zdc::Digits2Raw::print_gbt_word((const UInt_t*)&payload[ip]); + } + } + } + lastDataHeader = dh; + } + if (loglevel > 0) { + LOG(INFO) << rdhprintout.str(); + } + }); }}, + Options{ + {"log-level", VariantType::Int, 1, {"Logging level [0-2]"}}}}); + return workflow; +} From 7592bdd8099452875788b3b5100bb2434144f90e Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Sun, 6 Dec 2020 15:28:15 -0300 Subject: [PATCH 1556/1751] Bugfixes, use _as for filters (necessary) (#5009) --- Analysis/Tasks/PWGLF/cascadeconsumer.cxx | 1 - Analysis/Tasks/PWGLF/cascadeproducer.cxx | 50 +++++++++-------- Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx | 1 - Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 1 - Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 56 +++++++++++--------- 5 files changed, 59 insertions(+), 50 deletions(-) diff --git a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx index 5fd84de8d263d..a6ae55727684c 100644 --- a/Analysis/Tasks/PWGLF/cascadeconsumer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeconsumer.cxx @@ -44,7 +44,6 @@ #include <cmath> #include <array> #include <cstdlib> -#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; diff --git a/Analysis/Tasks/PWGLF/cascadeproducer.cxx b/Analysis/Tasks/PWGLF/cascadeproducer.cxx index f0bdda6d11063..eee9c39beb25c 100644 --- a/Analysis/Tasks/PWGLF/cascadeproducer.cxx +++ b/Analysis/Tasks/PWGLF/cascadeproducer.cxx @@ -34,7 +34,6 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "AnalysisDataModel/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "AnalysisCore/RecoDecay.h" @@ -53,7 +52,6 @@ #include <cmath> #include <array> #include <cstdlib> -#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; @@ -99,29 +97,29 @@ struct cascadeprefilterpairs { for (auto& casc : Cascades) { //Single-track properties filter if (tpcrefit) { - if (!(casc.v0().posTrack().flags() & 0x40)) { + if (!(casc.v0_as<o2::aod::V0DataExt>().posTrack_as<FullTracksExt>().trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } - if (!(casc.v0().negTrack().flags() & 0x40)) { + if (!(casc.v0_as<o2::aod::V0DataExt>().negTrack_as<FullTracksExt>().trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } - if (!(casc.bachelor().flags() & 0x40)) { + if (!(casc.bachelor_as<FullTracksExt>().trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } } - if (casc.v0().posTrack().tpcNClsCrossedRows() < mincrossedrows) { + if (casc.v0_as<o2::aod::V0DataExt>().posTrack_as<FullTracksExt>().tpcNClsCrossedRows() < mincrossedrows) { continue; } - if (casc.v0().negTrack().tpcNClsCrossedRows() < mincrossedrows) { + if (casc.v0_as<o2::aod::V0DataExt>().negTrack_as<FullTracksExt>().tpcNClsCrossedRows() < mincrossedrows) { continue; } - if (casc.bachelor().tpcNClsCrossedRows() < mincrossedrows) { + if (casc.bachelor_as<FullTracksExt>().tpcNClsCrossedRows() < mincrossedrows) { continue; } - if (casc.v0().posTrack_as<FullTracksExt>().dcaXY() < dcapostopv) { + if (casc.v0_as<o2::aod::V0DataExt>().posTrack_as<FullTracksExt>().dcaXY() < dcapostopv) { continue; } - if (casc.v0().negTrack_as<FullTracksExt>().dcaXY() < dcanegtopv) { + if (casc.v0_as<o2::aod::V0DataExt>().negTrack_as<FullTracksExt>().dcaXY() < dcanegtopv) { continue; } if (casc.bachelor_as<FullTracksExt>().dcaXY() < dcabachtopv) { @@ -144,7 +142,10 @@ struct cascadeprefilterpairs { if (casc.v0_as<o2::aod::V0DataExt>().dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < dcav0topv) { continue; } - cascgood(casc.v0().globalIndex(), casc.bachelor().globalIndex(), casc.bachelor().collisionId()); + cascgood( + casc.v0_as<o2::aod::V0DataExt>().globalIndex(), + casc.bachelor_as<FullTracksExt>().globalIndex(), + casc.bachelor_as<FullTracksExt>().collisionId()); } } }; @@ -196,9 +197,9 @@ struct cascadeproducer { hCascCandidate->Fill(0.5); //Acquire basic tracks - auto pTrack = getTrackParCov(casc.v0().posTrack()); - auto nTrack = getTrackParCov(casc.v0().negTrack()); - auto bTrack = getTrackParCov(casc.bachelor()); + auto pTrack = getTrackParCov(casc.v0_as<o2::aod::V0DataExt>().posTrack_as<FullTracksExt>()); + auto nTrack = getTrackParCov(casc.v0_as<o2::aod::V0DataExt>().negTrack_as<FullTracksExt>()); + auto bTrack = getTrackParCov(casc.bachelor_as<FullTracksExt>()); if (casc.bachelor().signed1Pt() > 0) { charge = +1; } @@ -251,15 +252,18 @@ struct cascadeproducer { } //end if cascade recoed } //end if v0 recoed //Fill table, please - cascdata(casc.v0().globalIndex(), casc.bachelor().globalIndex(), casc.bachelor().collisionId(), - charge, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], - pvecpos[0], pvecpos[1], pvecpos[2], - pvecneg[0], pvecneg[1], pvecneg[2], - pvecbach[0], pvecbach[1], pvecbach[2], - fitterV0.getChi2AtPCACandidate(), fitterCasc.getChi2AtPCACandidate(), - casc.v0().posTrack_as<FullTracksExt>().dcaXY(), - casc.v0().negTrack_as<FullTracksExt>().dcaXY(), - casc.bachelor_as<FullTracksExt>().dcaXY()); + cascdata( + casc.v0_as<o2::aod::V0DataExt>().globalIndex(), + casc.bachelor_as<FullTracksExt>().globalIndex(), + casc.bachelor_as<FullTracksExt>().collisionId(), + charge, posXi[0], posXi[1], posXi[2], pos[0], pos[1], pos[2], + pvecpos[0], pvecpos[1], pvecpos[2], + pvecneg[0], pvecneg[1], pvecneg[2], + pvecbach[0], pvecbach[1], pvecbach[2], + fitterV0.getChi2AtPCACandidate(), fitterCasc.getChi2AtPCACandidate(), + casc.v0().posTrack_as<FullTracksExt>().dcaXY(), + casc.v0().negTrack_as<FullTracksExt>().dcaXY(), + casc.bachelor_as<FullTracksExt>().dcaXY()); } } }; diff --git a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx index 2fa0ae25839b5..35a5242b1e292 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroconsumer.cxx @@ -43,7 +43,6 @@ #include <cmath> #include <array> #include <cstdlib> -#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index a5f80627f1237..ffc5cd1f14f5f 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -31,7 +31,6 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "AnalysisDataModel/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "AnalysisCore/RecoDecay.h" diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index 7dfa491c07cc5..8095f8810021a 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -34,7 +34,6 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "AnalysisDataModel/HFSecondaryVertex.h" #include "DetectorsVertexing/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" #include "AnalysisCore/RecoDecay.h" @@ -53,7 +52,6 @@ #include <cmath> #include <array> #include <cstdlib> -#include "AnalysisDataModel/PID/PIDResponse.h" #include "Framework/ASoAHelpers.h" using namespace o2; @@ -85,35 +83,41 @@ struct lambdakzeroprefilterpairs { Configurable<int> mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; Configurable<bool> tpcrefit{"tpcrefit", 1, "demand TPC refit"}; + OutputObj<TH1F> hGoodIndices{TH1F("hGoodIndices", "", 4, 0, 4)}; + Produces<aod::V0GoodIndices> v0goodindices; void process(aod::Collision const& collision, aod::V0s const& V0s, soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& V0 : V0s) { + hGoodIndices->Fill(0.5); if (tpcrefit) { - if (!(V0.posTrack().flags() & 0x40)) { + if (!(V0.posTrack_as<FullTracksExt>().trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } - if (!(V0.negTrack().flags() & 0x40)) { + if (!(V0.negTrack_as<FullTracksExt>().trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } } - if (V0.posTrack().tpcNClsCrossedRows() < mincrossedrows) { + hGoodIndices->Fill(1.5); + if (V0.posTrack_as<FullTracksExt>().tpcNClsCrossedRows() < mincrossedrows) { continue; } - if (V0.negTrack().tpcNClsCrossedRows() < mincrossedrows) { + if (V0.negTrack_as<FullTracksExt>().tpcNClsCrossedRows() < mincrossedrows) { continue; } - - if (V0.posTrack_as<FullTracksExt>().dcaXY() < dcapostopv) { + hGoodIndices->Fill(2.5); + if (fabs(V0.posTrack_as<FullTracksExt>().dcaXY()) < dcapostopv) { continue; } - if (V0.negTrack_as<FullTracksExt>().dcaXY() < dcanegtopv) { + if (fabs(V0.negTrack_as<FullTracksExt>().dcaXY()) < dcanegtopv) { continue; } - - v0goodindices(V0.posTrack().globalIndex(), V0.negTrack().globalIndex(), V0.posTrack().collisionId()); + hGoodIndices->Fill(3.5); + v0goodindices(V0.posTrack_as<FullTracksExt>().globalIndex(), + V0.negTrack_as<FullTracksExt>().globalIndex(), + V0.posTrack_as<FullTracksExt>().collisionId()); } } }; @@ -124,7 +128,7 @@ struct lambdakzeroproducer { Produces<aod::V0Data> v0data; OutputObj<TH1F> hEventCounter{TH1F("hEventCounter", "", 1, 0, 1)}; - OutputObj<TH1F> hCascCandidate{TH1F("hCascCandidate", "", 10, 0, 10)}; + OutputObj<TH1F> hV0Candidate{TH1F("hV0Candidate", "", 2, 0, 2)}; //Configurables Configurable<double> d_bz{"d_bz", -5.0, "bz field"}; @@ -162,13 +166,13 @@ struct lambdakzeroproducer { std::array<float, 3> pvec0 = {0.}; std::array<float, 3> pvec1 = {0.}; - hCascCandidate->Fill(0.5); - auto pTrack = getTrackParCov(V0.posTrack()); - auto nTrack = getTrackParCov(V0.negTrack()); + hV0Candidate->Fill(0.5); + + auto pTrack = getTrackParCov(V0.posTrack_as<FullTracksExt>()); + auto nTrack = getTrackParCov(V0.negTrack_as<FullTracksExt>()); int nCand = fitter.process(pTrack, nTrack); if (nCand != 0) { fitter.propagateTracksToVertex(); - hCascCandidate->Fill(2.5); const auto& vtx = fitter.getPCACandidate(); for (int i = 0; i < 3; i++) { pos[i] = vtx[i]; @@ -178,7 +182,7 @@ struct lambdakzeroproducer { } //Apply selections so a skimmed table is created only - if (fitter.getChi2AtPCACandidate() < dcav0dau) { + if (fitter.getChi2AtPCACandidate() > dcav0dau) { continue; } @@ -188,13 +192,17 @@ struct lambdakzeroproducer { continue; } - v0data(V0.posTrack().globalIndex(), V0.negTrack().globalIndex(), V0.negTrack().collisionId(), - pos[0], pos[1], pos[2], - pvec0[0], pvec0[1], pvec0[2], - pvec1[0], pvec1[1], pvec1[2], - fitter.getChi2AtPCACandidate(), - V0.posTrack_as<FullTracksExt>().dcaXY(), - V0.negTrack_as<FullTracksExt>().dcaXY()); + hV0Candidate->Fill(1.5); + v0data( + V0.posTrack_as<FullTracksExt>().globalIndex(), + V0.negTrack_as<FullTracksExt>().globalIndex(), + V0.negTrack_as<FullTracksExt>().collisionId(), + pos[0], pos[1], pos[2], + pvec0[0], pvec0[1], pvec0[2], + pvec1[0], pvec1[1], pvec1[2], + fitter.getChi2AtPCACandidate(), + V0.posTrack_as<FullTracksExt>().dcaXY(), + V0.negTrack_as<FullTracksExt>().dcaXY()); } } }; From 1bb0a2278761bd0b60d9ed77f781847c7f1d8a4c Mon Sep 17 00:00:00 2001 From: Nazar Burmasov <nazar.burmasov@cern.ch> Date: Sun, 6 Dec 2020 21:28:29 +0300 Subject: [PATCH 1557/1751] Small update for the converter (#5002) * Update: configurable TFNumber and collision time wrt to the beginning of BC * Fix for collision time resolution * Fix for collision time * Fix missing declaration of mTFNumber --- .../AODProducerWorkflowSpec.h | 1 + Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 23 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index dea495c5af03a..a094a95ce8be9 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -104,6 +104,7 @@ class AODProducerWorkflowDPL : public Task int mFillTracksITS = 1; int mFillTracksTPC = 1; int mFillTracksITSTPC = 1; + int mTFNumber = -1; TStopwatch mTimer; uint64_t maxGlBC = 0; diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 8f8c6c3048806..b6bef4b60c87d 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -224,6 +224,10 @@ void AODProducerWorkflowDPL::init(InitContext& ic) mFillTracksITS = ic.options().get<int>("fill-tracks-its"); mFillTracksTPC = ic.options().get<int>("fill-tracks-tpc"); mFillTracksITSTPC = ic.options().get<int>("fill-tracks-its-tpc"); + mTFNumber = ic.options().get<int>("aod-timeframe-id"); + if (mTFNumber == -1) { + LOG(INFO) << "TFNumber will be obtained from CCDB"; + } LOG(INFO) << "track filling flags set to: " << "\n ITS = " << mFillTracksITS << "\n TPC = " << mFillTracksTPC << "\n ITSTPC = " << mFillTracksITSTPC; @@ -468,8 +472,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto& cov = vertex.getCov(); auto& timeStamp = vertex.getTimeStamp(); Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // mus to ns - // FIXME: - // should use IRMin and IRMax for globalBC calculation + // TODO: + // use filling scheme to calculate most prob. BC uint64_t globalBC = std::round(tsTimeStamp / o2::constants::lhc::LHCBunchSpacingNS); LOG(DEBUG) << globalBC << " " << tsTimeStamp; @@ -478,6 +482,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) firstVtxGlBC = globalBC; } + // collision timestamp in ns wrt the beginning of collision BC + tsTimeStamp = globalBC * o2::constants::lhc::LHCBunchSpacingNS - tsTimeStamp; int BCid = mGlobBC2BCID.at(globalBC); // TODO: // get real collision time mask @@ -495,8 +501,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) cov[5], vertex.getChi2(), vertex.getNContributors(), - timeStamp.getTimeStamp(), - timeStamp.getTimeStampError(), + tsTimeStamp, + timeStamp.getTimeStampError() * 1E3, collisionTimeMask); auto trackRef = primVer2TRefs[collisionID]; @@ -610,7 +616,11 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) } } - timeFrameNumberBuilder = getTFNumber(firstVtxGlBC, runNumber); + if (mTFNumber == -1) { + timeFrameNumberBuilder = getTFNumber(firstVtxGlBC, runNumber); + } else { + timeFrameNumberBuilder = mTFNumber; + } mTimer.Stop(); } @@ -663,7 +673,8 @@ DataProcessorSpec getAODProducerWorkflowSpec() Options{ ConfigParamSpec{"fill-tracks-its", VariantType::Int, 1, {"Fill ITS tracks into tracks table"}}, ConfigParamSpec{"fill-tracks-tpc", VariantType::Int, 1, {"Fill TPC tracks into tracks table"}}, - ConfigParamSpec{"fill-tracks-its-tpc", VariantType::Int, 1, {"Fill ITS-TPC tracks into tracks table"}}}}; + ConfigParamSpec{"fill-tracks-its-tpc", VariantType::Int, 1, {"Fill ITS-TPC tracks into tracks table"}}, + ConfigParamSpec{"aod-timeframe-id", VariantType::Int, -1, {"Set timeframe number"}}}}; } } // namespace o2::aodproducer From 4e48261aafd630bf7b11c2c66a35d840d12efda6 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Sun, 6 Dec 2020 19:28:48 +0100 Subject: [PATCH 1558/1751] Copying of index bindings (#5000) --- Analysis/Tutorials/src/compatibleBCs.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Analysis/Tutorials/src/compatibleBCs.cxx b/Analysis/Tutorials/src/compatibleBCs.cxx index 05e653fd31465..658e154dd4ed8 100644 --- a/Analysis/Tutorials/src/compatibleBCs.cxx +++ b/Analysis/Tutorials/src/compatibleBCs.cxx @@ -51,7 +51,9 @@ T getCompatibleBCs(aod::Collision const& collision, T const& bcs) LOGF(INFO, "Will consider BC entries from %d to %d", minBCId, maxBCId); - return T{{bcs.asArrowTable()->Slice(minBCId, maxBCId - minBCId + 1)}, (uint64_t)minBCId}; + T slice{{bcs.asArrowTable()->Slice(minBCId, maxBCId - minBCId + 1)}, (uint64_t)minBCId}; + bcs.copyIndexBindings(slice); + return slice; } // Example 1 (academic, because it is not enough to just access the BC table): @@ -82,8 +84,6 @@ struct CompatibleT0V0A { LOGF(INFO, "Vertex with most probable BC %llu and collision time %f +- %f ps", bc.globalBC(), collision.collisionTime(), collision.collisionTimeRes()); auto bcSlice = getCompatibleBCs(collision, bct0s); - // TODO move to getCompatibleBCs - bcSlice.bindExternalIndices(&ft0s, &fv0as); for (auto& bc : bcSlice) { if (bc.has_ft0() && bc.has_fv0a()) { From 7ff4d65589123f1b37bb3097729485a927eaba5f Mon Sep 17 00:00:00 2001 From: Nazar Burmasov <nazar.burmasov@cern.ch> Date: Sun, 6 Dec 2020 21:30:56 +0300 Subject: [PATCH 1559/1751] Update for Run3 subtask (#5016) --- Analysis/Tasks/eventSelection.cxx | 69 +++++++++++++------------------ 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index 67a7504004671..60b11a5729277 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -138,60 +138,48 @@ struct EventSelectionTask { } }; -// helper table and task for BCs<-->FT0s matching -namespace o2::aod -{ -DECLARE_SOA_INDEX_TABLE_USER(SparseBCsFT0s, BCs, "MA_SP_BCS_FT0S", o2::aod::indices::BCId, o2::aod::indices::FT0Id); -} - -struct EventSelectionTaskRun3Helper { - Builds<aod::SparseBCsFT0s> matchedBCsFT0s; - void process(aod::BCs, aod::FT0s) - { - } -}; - struct EventSelectionTaskRun3 { Produces<aod::EvSels> evsel; EvSelParameters par; - void process(aod::Collision const& collision, aod::SparseBCsFT0s const& matchedBCsFT0s, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FT0s const& ft0s, aod::FDDs const& fdds) + void process(aod::Collision const& collision, soa::Join<aod::BCs, aod::Run3MatchedToBCSparse> const& bct0s, aod::Zdcs const& zdcs, aod::FV0As const& fv0as, aod::FT0s const& ft0s, aod::FDDs const& fdds) { - // calculating [minBC, maxBC] range for a collision - int deltaBC = std::ceil(collision.collisionTimeRes() / o2::constants::lhc::LHCBunchSpacingNS * 4); - int64_t colBC = collision.bc().globalBC(); - int64_t maxColBC = colBC + deltaBC; - int64_t minColBC = colBC - deltaBC; - - int64_t minFt0Dist = INT32_MAX; + int64_t ft0Dist; int64_t foundFT0 = -1; float timeA = -999.f; float timeC = -999.f; - // calculating BCID iteration range - int64_t minGlobalBC = bcs.begin().globalBC(); - int64_t maxGlobalBC = bcs.iteratorAt(bcs.size() - 1).globalBC(); - int64_t startIt = minColBC - minGlobalBC; - int64_t endIt = maxColBC - minGlobalBC; - - // iterating only through relevant BCIDs and - // searching for the nearest FT0 - for (int64_t i = startIt; i <= endIt; i++) { - auto matched = matchedBCsFT0s.iteratorAt(i); - if (matched.has_ft0() == false) { - continue; + auto bcIter = collision.bc_as<soa::Join<aod::BCs, aod::Run3MatchedToBCSparse>>(); + + uint64_t apprBC = bcIter.globalBC(); + uint64_t meanBC = apprBC - std::lround(collision.collisionTime() / o2::constants::lhc::LHCBunchSpacingNS); + int deltaBC = std::ceil(collision.collisionTimeRes() / o2::constants::lhc::LHCBunchSpacingNS * 4); + + int moveCount = 0; + while (bcIter != bct0s.end() && bcIter.globalBC() <= meanBC + deltaBC && bcIter.globalBC() >= meanBC - deltaBC) { + if (bcIter.has_ft0()) { + ft0Dist = bcIter.globalBC() - meanBC; + foundFT0 = bcIter.ft0().globalIndex(); + break; + } + ++bcIter; + ++moveCount; + } + + bcIter.moveByIndex(-moveCount); + while (bcIter != bct0s.begin() && bcIter.globalBC() <= meanBC + deltaBC && bcIter.globalBC() >= meanBC - deltaBC) { + --bcIter; + if (bcIter.has_ft0() && (meanBC - bcIter.globalBC()) < ft0Dist) { + foundFT0 = bcIter.ft0().globalIndex(); + break; } - auto bc = bcs.iteratorAt(i); - int64_t ft0BC = bc.globalBC(); - int64_t ft0Dist = abs(ft0BC - colBC); - if (ft0Dist < minFt0Dist) { - minFt0Dist = ft0Dist; - foundFT0 = matched.ft0().globalIndex(); + if ((meanBC - bcIter.globalBC()) >= ft0Dist) { + break; } } - if (minFt0Dist != INT32_MAX) { + if (foundFT0 != -1) { auto ft0 = ft0s.iteratorAt(foundFT0); timeA = ft0.timeA(); timeC = ft0.timeC(); @@ -223,7 +211,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& ctx) return WorkflowSpec{adaptAnalysisTask<EventSelectionTask>("event-selection")}; } else { return WorkflowSpec{ - adaptAnalysisTask<EventSelectionTaskRun3Helper>("event-selection-helper"), adaptAnalysisTask<EventSelectionTaskRun3>("event-selection")}; } } \ No newline at end of file From feb6a0e16709b1ab9b27f9be19515a6fe36bd7f1 Mon Sep 17 00:00:00 2001 From: mkruegerGitHub <mkrueger@ikf.uni-frankfurt.de> Date: Sun, 6 Dec 2020 19:31:35 +0100 Subject: [PATCH 1560/1751] TrackSelection: revert to uint8_t columns (#5015) --- .../include/AnalysisDataModel/TrackSelectionTables.h | 4 ++-- Analysis/Tasks/PWGCF/correlations.cxx | 2 +- Analysis/Tasks/PWGCF/filterCF.cxx | 2 +- Analysis/Tasks/PWGLF/mcspectraefficiency.cxx | 2 +- Analysis/Tasks/PWGLF/spectraTOF.cxx | 2 +- Analysis/Tasks/PWGLF/spectraTPC.cxx | 2 +- Analysis/Tasks/PWGLF/trackchecks.cxx | 2 +- Analysis/Tasks/trackqa.cxx | 2 +- Analysis/Tasks/trackselection.cxx | 4 ++-- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h b/Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h index 4d3dcacf6b707..52e114013a87a 100644 --- a/Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h +++ b/Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h @@ -22,8 +22,8 @@ DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); // Columns to store track filter decisions -DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, bool); -DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, bool); +DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, uint8_t); +DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, uint8_t); } // namespace track DECLARE_SOA_TABLE(TracksExtended, "AOD", "TRACKEXTENDED", track::DcaXY, diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index a99ac03f4e78b..c8c30890c09a5 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -58,7 +58,7 @@ struct CorrelationTask { // 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 == true) || (aod::track::isGlobalTrackSDD == true)); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((aod::track::isGlobalTrack == (uint8_t) true) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); using myTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection>>; // Output definitions diff --git a/Analysis/Tasks/PWGCF/filterCF.cxx b/Analysis/Tasks/PWGCF/filterCF.cxx index 6f649fe8c32d3..7c689f2aca3cc 100644 --- a/Analysis/Tasks/PWGCF/filterCF.cxx +++ b/Analysis/Tasks/PWGCF/filterCF.cxx @@ -34,7 +34,7 @@ struct FilterCF { // Filters and input definitions Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex && aod::cent::centV0M <= 80.0f; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((aod::track::isGlobalTrack == (uint8_t) true) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); OutputObj<TH3F> yields{TH3F("yields", "centrality vs pT vs eta", 100, 0, 100, 40, 0, 20, 100, -2, 2)}; OutputObj<TH3F> etaphi{TH3F("etaphi", "centrality vs eta vs phi", 100, 0, 100, 100, -2, 2, 200, 0, 2 * M_PI)}; diff --git a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx index 92a6c8e4217c0..6033718cf159f 100644 --- a/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx +++ b/Analysis/Tasks/PWGLF/mcspectraefficiency.cxx @@ -104,7 +104,7 @@ struct ReconstructedTask { OutputObj<TH2F> pDiff{TH2F("pDiff", "pDiff;#it{p}_{MC} #it{p}_{Rec} (GeV/#it{c})", 500, -2, 2, PDGBINNING)}; Filter trackAcceptance = (nabs(aod::track::eta) < 0.8f); - Filter trackCuts = ((aod::track::isGlobalTrack == true) || (aod::track::isGlobalTrackSDD == true)); + Filter trackCuts = ((aod::track::isGlobalTrack == (uint8_t) true) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::McTrackLabels, aod::TrackSelection>> const& tracks, diff --git a/Analysis/Tasks/PWGLF/spectraTOF.cxx b/Analysis/Tasks/PWGLF/spectraTOF.cxx index bc3d4b815e562..685c39ba3dc5a 100644 --- a/Analysis/Tasks/PWGLF/spectraTOF.cxx +++ b/Analysis/Tasks/PWGLF/spectraTOF.cxx @@ -49,7 +49,7 @@ struct TOFSpectraTask { Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == true) && (aod::track::tofSignal > 0.f); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true) && (aod::track::tofSignal > 0.f); using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta, aod::TrackSelection>>; void process(TrackCandidates::iterator const& track) { diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index d7498c9ee6045..d85efbf5f1e5b 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -33,7 +33,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; \ Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; \ Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; \ - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == true); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true); #define makelogaxis(h) \ { \ diff --git a/Analysis/Tasks/PWGLF/trackchecks.cxx b/Analysis/Tasks/PWGLF/trackchecks.cxx index e22defe105cb3..cd2cbeb0ec857 100644 --- a/Analysis/Tasks/PWGLF/trackchecks.cxx +++ b/Analysis/Tasks/PWGLF/trackchecks.cxx @@ -240,7 +240,7 @@ struct TrackCheckTaskEvSelTrackSel { //Filters Filter collfilter = nabs(aod::collision::posZ) < cfgCutVZ; - Filter trackfilter = aod::track::isGlobalTrack == true; + Filter trackfilter = aod::track::isGlobalTrack == (uint8_t) true; void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& col, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::TrackSelection, aod::McTrackLabels>>& tracks, diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index e7f10f1844cc5..244ddba0b788b 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -44,7 +44,7 @@ struct TrackQATask { Configurable<int> selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks, 2 = globalTracksSDD"}; - Filter trackFilter = aod::track::isGlobalTrack == true; + Filter trackFilter = aod::track::isGlobalTrack == (uint8_t) true; void init(o2::framework::InitContext&) { diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index baeda9e183a28..263a00d6de117 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -44,8 +44,8 @@ struct TrackSelectionTask { void process(soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& track : tracks) { - filterTable(globalTracks.IsSelected(track), - globalTracksSDD.IsSelected(track)); + filterTable((uint8_t)globalTracks.IsSelected(track), + (uint8_t)globalTracksSDD.IsSelected(track)); } } }; From 287517cf3b64b0ca6ccccd985e0b67d123116f68 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 6 Dec 2020 19:25:46 +0100 Subject: [PATCH 1561/1751] DPL GUI: do coarse culling of device graph Makes it possible to run with large number of nodes, as long as they are scattered enough in the layout. --- Framework/Core/src/FrameworkGUIDevicesGraph.cxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx index 488a77ccc176d..6cd6ea68a91ee 100644 --- a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx +++ b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx @@ -461,6 +461,15 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, ImVec2 node_rect_max = node_rect_min + node->Size; ImVec2 node_rect_title = node_rect_min + ImVec2(node->Size.x, 24); + if (node_rect_min.x > 20 + 2 * NODE_WINDOW_PADDING.x + state.leftPaneSize + graphSize.x) { + ImGui::PopID(); + continue; + } + if (node_rect_min.y > 20 + 2 * NODE_WINDOW_PADDING.y + toolbarSize.y + graphSize.y) { + ImGui::PopID(); + continue; + } + // Display node box draw_list->ChannelsSetCurrent(backgroundLayer); // Background ImGui::SetCursorScreenPos(node_rect_min); From ea311b368219c9641d2142796a8a5ecfd61752ea Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 6 Dec 2020 21:37:47 +0100 Subject: [PATCH 1562/1751] DPL: speedup metricIdxByName Avoid recalculating size over and over again. --- Framework/Core/include/Framework/DeviceMetricsInfo.h | 6 ++++-- Framework/Core/src/DeviceMetricsInfo.cxx | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceMetricsInfo.h b/Framework/Core/include/Framework/DeviceMetricsInfo.h index 229fc48721bba..a9167e1d50a56 100644 --- a/Framework/Core/include/Framework/DeviceMetricsInfo.h +++ b/Framework/Core/include/Framework/DeviceMetricsInfo.h @@ -47,11 +47,12 @@ struct StringMetric { char data[MAX_SIZE]; }; -// Also for the keys it does not make much sense to keep more than 256 chars. +// Also for the keys it does not make much sense to keep more than 247 chars. // They should be nevertheless 0 terminated. struct MetricLabelIndex { - static constexpr size_t MAX_METRIC_LABEL_SIZE = 256 - sizeof(size_t); // Maximum size for a metric name. + static constexpr size_t MAX_METRIC_LABEL_SIZE = 256 - sizeof(size_t) - sizeof(unsigned char); // Maximum size for a metric name. size_t index; + unsigned char size = 0; char label[MAX_METRIC_LABEL_SIZE]; }; @@ -169,6 +170,7 @@ struct DeviceMetricsHelper { strncpy(metricLabelIdx.label, name, MetricLabelIndex::MAX_METRIC_LABEL_SIZE - 1); metricLabelIdx.label[MetricLabelIndex::MAX_METRIC_LABEL_SIZE - 1] = '\0'; metricLabelIdx.index = metrics.metrics.size(); + metricLabelIdx.size = strlen(metricLabelIdx.label); metrics.metricLabelsIdx.push_back(metricLabelIdx); // Add the the actual Metric info to the store diff --git a/Framework/Core/src/DeviceMetricsInfo.cxx b/Framework/Core/src/DeviceMetricsInfo.cxx index 7b4c467fdadbd..9f8721889caf5 100644 --- a/Framework/Core/src/DeviceMetricsInfo.cxx +++ b/Framework/Core/src/DeviceMetricsInfo.cxx @@ -189,6 +189,7 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, auto lastChar = std::min(match.endKey - match.beginKey, (ptrdiff_t)MetricLabelIndex::MAX_METRIC_LABEL_SIZE - 1); memcpy(metricLabelIdx.label, match.beginKey, lastChar); metricLabelIdx.label[lastChar] = '\0'; + metricLabelIdx.size = lastChar; metricLabelIdx.index = info.metrics.size(); info.metricLabelsIdx.insert(mi, metricLabelIdx); // Add the the actual Metric info to the store @@ -261,13 +262,14 @@ bool DeviceMetricsHelper::processMetric(ParsedMetricMatch& match, return true; } -size_t - DeviceMetricsHelper::metricIdxByName(const std::string& name, const DeviceMetricsInfo& info) +size_t DeviceMetricsHelper::metricIdxByName(const std::string& name, const DeviceMetricsInfo& info) { size_t i = 0; while (i < info.metricLabelsIdx.size()) { auto& metricName = info.metricLabelsIdx[i]; - if (metricName.label == name) { + // We check the size first and then the last character because that's + // likely to be different for multi-index metrics + if (metricName.size == name.size() && metricName.label[metricName.size - 1] == name[metricName.size - 1] && memcmp(metricName.label, name.c_str(), metricName.size) == 0) { return metricName.index; } ++i; From a23e53a4fb91e9330b5a2a46f423c05b5c6c349b Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 7 Dec 2020 11:08:21 +0100 Subject: [PATCH 1563/1751] sim_challenge: include new AOD producer workflow * use/test AOD producer workflow in sim-challenge * take out MFT reco for now since crashing * put some more stages under taskwrapper --- prodtests/sim_challenge.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index e7d582f799be7..f7d268c1b252c 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -96,7 +96,7 @@ if [ "$dosim" == "1" ]; then taskwrapper sim.log o2-sim -n"$nev" --configKeyValue "Diamond.width[2]=6." -g "$gener" -e "$engine" $simWorker ##------ extract number of hits - root -q -b -l ${O2_ROOT}/share/macro/analyzeHits.C > hitstats.log + taskwrapper hitstats.log root -q -b -l ${O2_ROOT}/share/macro/analyzeHits.C fi if [ "$dodigi" == "1" ]; then @@ -124,7 +124,7 @@ if [ "$doreco" == "1" ]; then echo "Running MFT reco flow" #needs MFT digitized data - taskwrapper mftreco.log o2-mft-reco-workflow $gloOpt + # taskwrapper mftreco.log o2-mft-reco-workflow $gloOpt echo "Return status of mftreco: $?" echo "Running FT0 reco flow" @@ -149,10 +149,10 @@ if [ "$doreco" == "1" ]; then echo "Running TOF matching QA" #need results of ITSTPC-TOF matching (+ TOF clusters and ITS-TPC tracks) - root -b -q -l $O2_ROOT/share/macro/checkTOFMatching.C 1>tofmatch_qa.log 2>&1 + taskwrapper tofmatch_qa.log root -b -q -l $O2_ROOT/share/macro/checkTOFMatching.C echo "Return status of TOF matching qa: $?" echo "Producing AOD" - taskwrapper aod.log o2-reco-standalone-aod-producer + taskwrapper aod.log o2-aod-producer-workflow --aod-writer-keep dangling --aod-writer-resfile "AO2D" --aod-writer-resmode UPDATE --aod-timeframe-id 1 echo "Return status of AOD production: $?" fi From 80bfe14bdc1e3fdecfc713b4619c350a3cfe1d3a Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sat, 5 Dec 2020 18:09:56 +0400 Subject: [PATCH 1564/1751] Fix: Proper treatment of --disable-mc in PHOS CellConverterSpec --- .../workflow/include/PHOSWorkflow/CellConverterSpec.h | 2 +- Detectors/PHOS/workflow/src/CellConverterSpec.cxx | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Detectors/PHOS/workflow/include/PHOSWorkflow/CellConverterSpec.h b/Detectors/PHOS/workflow/include/PHOSWorkflow/CellConverterSpec.h index b70718f019260..05f3892684125 100644 --- a/Detectors/PHOS/workflow/include/PHOSWorkflow/CellConverterSpec.h +++ b/Detectors/PHOS/workflow/include/PHOSWorkflow/CellConverterSpec.h @@ -75,7 +75,7 @@ class CellConverterSpec : public framework::Task std::vector<Cell> mOutputCells; ///< Container with output cells std::vector<TriggerRecord> mOutputCellTrigRecs; ///< Container with trigger records for output cells o2::dataformats::MCTruthContainer<MCLabel> mOutputTruthCont; ///< output MC labels - std::vector<uint> mOutputTruthMap; ///< output MC labels + std::vector<uint32_t> mOutputTruthMap; ///< output MC labels o2::phos::BadChannelMap* mBadMap = nullptr; ///< Bad channels map }; diff --git a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx index 3d08cc1e8919c..406b66e46df45 100644 --- a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx +++ b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ControlService.h" #include "DataFormatsPHOS/MCLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "CommonDataFormat/InteractionRecord.h" #include "PHOSBase/PHOSSimParams.h" #include "CCDB/CcdbApi.h" @@ -44,11 +45,15 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) auto digits = ctx.inputs().get<std::vector<o2::phos::Digit>>("digits"); auto digitsTR = ctx.inputs().get<std::vector<o2::phos::TriggerRecord>>("digitTriggerRecords"); - auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("digitsmctr"); + gsl::span<const char> labelbuffer; if (mPropagateMC) { + labelbuffer = ctx.inputs().get<gsl::span<char>>("digitsmctr"); + // auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("digitsmctr"); + mOutputTruthCont.clear(); mOutputTruthMap.clear(); } + o2::dataformats::ConstMCTruthContainerView<o2::phos::MCLabel> truthcont(labelbuffer); LOG(INFO) << "[PHOSCellConverter - run] Received " << digits.size() << " digits and " << digitsTR.size() << " TriggerRecords"; //Get TimeStamp from TriggerRecord @@ -100,7 +105,7 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) if (mPropagateMC) { //copy MC info, int iLab = dig.getLabel(); if (iLab > -1) { - mOutputTruthCont.addElements(labelIndex, truthcont->getLabels(iLab)); + mOutputTruthCont.addElements(labelIndex, truthcont.getLabels(iLab)); mOutputTruthMap.emplace_back(icell); //Relate cell index and label index labelIndex++; } @@ -115,8 +120,6 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) //ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthCont); //ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthMap); } - LOG(INFO) << "Finished "; - ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); } o2::framework::DataProcessorSpec o2::phos::reco_workflow::getCellConverterSpec(bool propagateMC) From a42d1013e99bd2bf7216dc4455935b002805e0a6 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 3 Dec 2020 19:31:19 +0400 Subject: [PATCH 1565/1751] use gSystem->Load w/o explicit shlib extension --- Detectors/CTF/test/test_ctf_io_emcal.cxx | 2 +- Detectors/CTF/test/test_ctf_io_mid.cxx | 2 +- Detectors/gconfig/g3libs.C | 2 +- GPU/GPUTracking/Merger/macros/checkPropagation.C | 2 +- GPU/GPUTracking/Merger/macros/fitPolynomialFieldIts.C | 2 +- GPU/GPUTracking/Merger/macros/fitPolynomialFieldTpc.C | 2 +- GPU/GPUTracking/Merger/macros/fitPolynomialFieldTrd.C | 2 +- GPU/GPUTracking/Standalone/tools/createGeo.C | 2 +- GPU/GPUTracking/Standalone/tools/createLUT.C | 2 +- Generators/share/external/GenCosmics.C | 2 +- Generators/share/external/GenCosmicsLoader.C | 2 +- Generators/share/external/QEDLoader.C | 2 +- Generators/share/external/QEDepem.C | 2 +- macro/run_trac_ca_its.C | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Detectors/CTF/test/test_ctf_io_emcal.cxx b/Detectors/CTF/test/test_ctf_io_emcal.cxx index 205efd84f7d49..974ff2f3e1174 100644 --- a/Detectors/CTF/test/test_ctf_io_emcal.cxx +++ b/Detectors/CTF/test/test_ctf_io_emcal.cxx @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(CTFTest) { std::vector<TriggerRecord> triggers; std::vector<Cell> cells; - // gSystem->Load("libO2DetectorsCommonDataFormats.so"); + // gSystem->Load("libO2DetectorsCommonDataFormats"); TStopwatch sw; sw.Start(); o2::InteractionRecord ir(0, 0); diff --git a/Detectors/CTF/test/test_ctf_io_mid.cxx b/Detectors/CTF/test/test_ctf_io_mid.cxx index 94f6c67b087a2..80bd5c098e003 100644 --- a/Detectors/CTF/test/test_ctf_io_mid.cxx +++ b/Detectors/CTF/test/test_ctf_io_mid.cxx @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(CTFTest) // indicated. What it more weird is that for similar tests of other detectors the library is loaded! // Absence of the library leads to complains about the StreamerInfo and eventually segm.faul when appending the // CTH to the tree. For this reason I am loading it here manually - gSystem->Load("libO2DetectorsCommonDataFormats.so"); + gSystem->Load("libO2DetectorsCommonDataFormats"); TStopwatch sw; sw.Start(); o2::InteractionRecord ir(0, 0); diff --git a/Detectors/gconfig/g3libs.C b/Detectors/gconfig/g3libs.C index ce95807d40d08..dc9912ef54f9c 100644 --- a/Detectors/gconfig/g3libs.C +++ b/Detectors/gconfig/g3libs.C @@ -24,7 +24,7 @@ void g3libs() std::cout << "Loading Geant3 libraries ..." << std::endl; if (isLibrary("libdummies")) - gSystem->Load("libdummies.so"); + gSystem->Load("libdummies"); // libdummies.so needed from geant3_+vmc version 0.5 gSystem->Load("libgeant321"); diff --git a/GPU/GPUTracking/Merger/macros/checkPropagation.C b/GPU/GPUTracking/Merger/macros/checkPropagation.C index c4c60b472a58a..7c4315e8a04d6 100644 --- a/GPU/GPUTracking/Merger/macros/checkPropagation.C +++ b/GPU/GPUTracking/Merger/macros/checkPropagation.C @@ -58,7 +58,7 @@ int RecalculateSlice(GPUTPCGMPhysicalTrackModel& t, AliExternalTrackParam& t0, i int checkPropagation() { - // gSystem->Load("libAliHLTTPC.so"); + // gSystem->Load("libAliHLTTPC"); TH1F* hDiff[3] = {0, 0, 0}; diff --git a/GPU/GPUTracking/Merger/macros/fitPolynomialFieldIts.C b/GPU/GPUTracking/Merger/macros/fitPolynomialFieldIts.C index 4b42316c9ab41..a61004ce6f828 100644 --- a/GPU/GPUTracking/Merger/macros/fitPolynomialFieldIts.C +++ b/GPU/GPUTracking/Merger/macros/fitPolynomialFieldIts.C @@ -1,6 +1,6 @@ int fitPolynomialFieldIts() { - gSystem->Load("libAliHLTTPC.so"); + gSystem->Load("libAliHLTTPC"); GPUTPCGMPolynomialField polyField; AliMagF* fld = new AliMagF("Fit", "Fit", 1., 1., AliMagF::k5kG); GPUTPCGMPolynomialFieldManager::FitFieldIts(fld, polyField, 1.); diff --git a/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTpc.C b/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTpc.C index 74e2824215659..7b1424163a6c6 100644 --- a/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTpc.C +++ b/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTpc.C @@ -1,6 +1,6 @@ int fitPolynomialFieldTpc() { - gSystem->Load("libAliHLTTPC.so"); + gSystem->Load("libAliHLTTPC"); GPUTPCGMPolynomialField polyField; AliMagF* fld = new AliMagF("Fit", "Fit", 1., 1., AliMagF::k5kG); GPUTPCGMPolynomialFieldManager::FitFieldTpc(fld, polyField, 10); diff --git a/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTrd.C b/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTrd.C index 03ca5caf05f22..debfba0c34cf0 100644 --- a/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTrd.C +++ b/GPU/GPUTracking/Merger/macros/fitPolynomialFieldTrd.C @@ -1,6 +1,6 @@ int fitPolynomialFieldTrd() { - gSystem->Load("libAliHLTTPC.so"); + gSystem->Load("libAliHLTTPC"); GPUTPCGMPolynomialField polyField; AliMagF* fld = new AliMagF("Fit", "Fit", 1., 1., AliMagF::k5kG); GPUTPCGMPolynomialFieldManager::FitFieldTrd(fld, polyField, 2); diff --git a/GPU/GPUTracking/Standalone/tools/createGeo.C b/GPU/GPUTracking/Standalone/tools/createGeo.C index 81e6ed7e3cbd6..b0837ff2604b4 100644 --- a/GPU/GPUTracking/Standalone/tools/createGeo.C +++ b/GPU/GPUTracking/Standalone/tools/createGeo.C @@ -17,7 +17,7 @@ void createGeo() gm->createClusterMatrixArray(); o2::trd::GeometryFlat gf(*gm); //if (!gf.readMatricesFromFile()) return; // uncomment this line when the matrices dumped from AliRoot should be used - gSystem->Load("libO2GPUTracking.so"); + gSystem->Load("libO2GPUTracking"); GPUReconstruction* rec = GPUReconstruction::CreateInstance(GPUReconstruction::DeviceType::CPU); GPUChainTracking* chain = rec->AddChain<GPUChainTracking>(); chain->SetTRDGeometry(&gf); diff --git a/GPU/GPUTracking/Standalone/tools/createLUT.C b/GPU/GPUTracking/Standalone/tools/createLUT.C index 53534273277c2..ae146c92e4608 100644 --- a/GPU/GPUTracking/Standalone/tools/createLUT.C +++ b/GPU/GPUTracking/Standalone/tools/createLUT.C @@ -10,7 +10,7 @@ using namespace GPUCA_NAMESPACE::gpu; void createLUT() { o2::base::MatLayerCylSet* lut = o2::base::MatLayerCylSet::loadFromFile("matbud.root", "MatBud"); - gSystem->Load("libO2GPUTracking.so"); + gSystem->Load("libO2GPUTracking"); GPUReconstruction* rec = GPUReconstruction::CreateInstance(GPUReconstruction::DeviceType::CPU); GPUChainTracking* chain = rec->AddChain<GPUChainTracking>(); chain->SetMatLUT(lut); diff --git a/Generators/share/external/GenCosmics.C b/Generators/share/external/GenCosmics.C index f8757c2b51a89..417ce670e78f1 100644 --- a/Generators/share/external/GenCosmics.C +++ b/Generators/share/external/GenCosmics.C @@ -11,7 +11,7 @@ //< Macro to run QED background generator, us it as e.g. //< o2-sim -n10000 -m PIPE ITS TPC -g extgen --configKeyValues "GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/GenCosmicsLoader.C" -R__LOAD_LIBRARY(libGeneratorCosmics.so) +R__LOAD_LIBRARY(libGeneratorCosmics) using namespace o2::eventgen; diff --git a/Generators/share/external/GenCosmicsLoader.C b/Generators/share/external/GenCosmicsLoader.C index 3ed746b30ac59..7242a7e2cb9c1 100644 --- a/Generators/share/external/GenCosmicsLoader.C +++ b/Generators/share/external/GenCosmicsLoader.C @@ -20,7 +20,7 @@ FairGenerator* fg = nullptr; FairGenerator* GenCosmicsLoader() { const TString macroName = "GenCosmics"; - gSystem->Load("libGeneratorCosmics.so"); + gSystem->Load("libGeneratorCosmics"); // 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 diff --git a/Generators/share/external/QEDLoader.C b/Generators/share/external/QEDLoader.C index 3ea7297490a7a..2426233316707 100644 --- a/Generators/share/external/QEDLoader.C +++ b/Generators/share/external/QEDLoader.C @@ -17,7 +17,7 @@ FairGenerator* fg = nullptr; FairGenerator* QEDLoader() { const TString macroName = "QEDepem"; - gSystem->Load("libTEPEMGEN.so"); + gSystem->Load("libTEPEMGEN"); // 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 diff --git a/Generators/share/external/QEDepem.C b/Generators/share/external/QEDepem.C index 8c218ffdeb28f..4ed3cdcc444c9 100644 --- a/Generators/share/external/QEDepem.C +++ b/Generators/share/external/QEDepem.C @@ -11,7 +11,7 @@ //< Macro to run QED background generator, us it as e.g. //< o2-sim -n10000 -m PIPE ITS T0 MFT --noemptyevents -g external --configKeyValues "GeneratorExternal.fileName=QEDloader.C" -R__LOAD_LIBRARY(libTEPEMGEN.so) +R__LOAD_LIBRARY(libTEPEMGEN) o2::eventgen::GeneratorTGenerator* QEDepem() { diff --git a/macro/run_trac_ca_its.C b/macro/run_trac_ca_its.C index 04213bbb1946f..431939a9a8c1a 100644 --- a/macro/run_trac_ca_its.C +++ b/macro/run_trac_ca_its.C @@ -60,7 +60,7 @@ void run_trac_ca_its(std::string path = "./", std::string inputGRP = "o2sim_grp.root") { - gSystem->Load("libO2ITStracking.so"); + gSystem->Load("libO2ITStracking"); //std::unique_ptr<GPUReconstruction> rec(GPUReconstruction::CreateInstance()); // std::unique_ptr<GPUReconstruction> rec(GPUReconstruction::CreateInstance("CUDA", true)); // for GPU with CUDA From 6e1039c35e7accd3482f285601010ed333840574 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Tue, 1 Dec 2020 13:42:23 +0100 Subject: [PATCH 1566/1751] MFT: introduce configuration of the tracker --- Detectors/ITSMFT/MFT/tracking/CMakeLists.txt | 6 +- .../MFT/tracking/include/MFTTracking/Cell.h | 2 +- .../tracking/include/MFTTracking/Cluster.h | 2 - .../tracking/include/MFTTracking/Constants.h | 41 +--- .../tracking/include/MFTTracking/IOUtils.h | 3 +- .../include/MFTTracking/IndexTableUtils.h | 53 ------ .../include/MFTTracking/MFTTrackingParam.h | 22 +++ .../tracking/include/MFTTracking/ROframe.h | 6 +- .../tracking/include/MFTTracking/Tracker.h | 25 ++- .../include/MFTTracking/TrackerConfig.h | 82 ++++++++ Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx | 15 -- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 8 +- .../MFT/tracking/src/MFTTrackingLinkDef.h | 1 + Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 180 +++++++++++------- .../ITSMFT/MFT/tracking/src/TrackerConfig.cxx | 113 +++++++++++ .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 14 +- 16 files changed, 373 insertions(+), 200 deletions(-) delete mode 100644 Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IndexTableUtils.h create mode 100644 Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h create mode 100644 Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx diff --git a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt index 1ec7e28dc5ce2..bd38dc6de0270 100644 --- a/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/MFT/tracking/CMakeLists.txt @@ -14,8 +14,9 @@ o2_add_library(MFTTracking src/ROframe.cxx src/Cluster.cxx src/IOUtils.cxx - src/TrackFitter.cxx - src/MFTTrackingParam.cxx + src/TrackFitter.cxx + src/MFTTrackingParam.cxx + src/TrackerConfig.cxx PUBLIC_LINK_LIBRARIES O2::CommonConstants O2::DataFormatsITSMFT O2::SimulationDataFormat @@ -27,4 +28,5 @@ o2_target_root_dictionary(MFTTracking HEADERS include/MFTTracking/TrackCA.h HEADERS include/MFTTracking/TrackFitter.h HEADERS include/MFTTracking/MFTTrackingParam.h + HEADERS include/MFTTracking/TrackerConfig.h LINKDEF src/MFTTrackingLinkDef.h) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h index 90fc28dee34a4..38cac67fac9fc 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h @@ -30,7 +30,7 @@ class Cell final { public: Cell(); - /// layer1, layer2, clsLayer1, clsLayer2, cellId; set level = 1 + /// layer1, layer2, clsInLayer1, clsInLayer2, cellId; set level = 1 Cell(const Int_t, const Int_t, const Int_t, const Int_t, const Int_t); const Int_t getFirstLayerId() const; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h index 7b31d12f5c83b..a6fb4ac8392ad 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cluster.h @@ -17,7 +17,6 @@ #include <array> #include "ReconstructionDataFormats/BaseCluster.h" -#include "MFTTracking/IndexTableUtils.h" #include "GPUCommonDef.h" namespace o2 @@ -37,7 +36,6 @@ struct Cluster : public o2::BaseCluster<float> { sigmaY2{sigY2}, isUsed{false} {}; Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t index); - Cluster(const Int_t layerIndex, const Cluster& other); void setUsed(Bool_t bval) { isUsed = bval; } const Bool_t getUsed() { return isUsed; } diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h index 244746300beaf..4afc191dab535 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h @@ -17,6 +17,7 @@ #include <climits> #include <vector> +#include <array> #include <Rtypes.h> @@ -47,13 +48,6 @@ constexpr std::array<Float_t, LayersNumber> InverseLayerZCoordinate() { return std::array<Float_t, LayersNumber>{-1. / 45.3, -1. / 46.7, -1. / 48.6, -1. / 50.0, -1. / 52.4, -1. / 53.8, -1. / 67.7, -1. / 69.1, -1. / 76.1, -1. / 77.5}; } -constexpr Int_t MinTrackPointsLTF{5}; -constexpr Int_t MinTrackPointsCA{4}; -constexpr Int_t MinTrackStationsLTF{4}; -constexpr Int_t MinTrackStationsCA{4}; -constexpr Int_t MaxTrackPoints{20}; -constexpr Float_t LTFclsRCut{0.0100}; -constexpr Float_t ROADclsRCut{0.0400}; constexpr Int_t MaxCellNeighbours{10}; } // namespace mft @@ -65,38 +59,7 @@ constexpr Float_t RMax{16.0}; constexpr Float_t PhiMin{0.}; constexpr Float_t PhiMax{o2::constants::math::TwoPI}; // [rad] -constexpr Int_t RBins{50}; -constexpr Int_t PhiBins{50}; - -constexpr Int_t RPhiBins{RBins * PhiBins}; - -constexpr Float_t PhiBinSize{(PhiMax - PhiMin) / PhiBins}; -constexpr Float_t RBinSize{(RMax - RMin) / RBins}; - -constexpr Float_t InversePhiBinSize{PhiBins / (PhiMax - PhiMin)}; -constexpr Float_t InverseRBinSize{RBins / (RMax - RMin)}; - -constexpr UChar_t LTFseed2BinWin{3}; -constexpr UChar_t LTFinterBinWin{3}; - -constexpr Int_t getRBinIndex(const Float_t r) -{ - return (Int_t)((r - RMin) * InverseRBinSize); -} - -constexpr Int_t getPhiBinIndex(const Float_t phi) -{ - return (Int_t)((phi - PhiMin) * InversePhiBinSize); -} - -constexpr Int_t getBinIndex(const Int_t rIndex, const Int_t phiIndex) -{ - if (0 <= rIndex && rIndex < RBins && - 0 <= phiIndex && phiIndex < PhiBins) { - return (phiIndex * RBins + rIndex); - } - return -1; -} +constexpr Int_t MaxRPhiBins{100 * 100}; } // namespace index_table } // namespace constants diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h index 99d2b3a15aaf7..d812fae253987 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h @@ -21,6 +21,7 @@ #include <vector> #include <gsl/gsl> +#include "MFTTracking/TrackerConfig.h" #include "MFTTracking/ROframe.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "DataFormatsITSMFT/ROFRecord.h" @@ -56,7 +57,7 @@ constexpr float DefClusError2Col = DefClusErrorCol * DefClusErrorCol; int loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& events, gsl::span<const itsmft::CompClusterExt> clusters, gsl::span<const unsigned char>::iterator& pattIt, const itsmft::TopologyDictionary& dict, - const dataformats::MCTruthContainer<MCCompLabel>* mClsLabels = nullptr); + const dataformats::MCTruthContainer<MCCompLabel>* mClsLabels = nullptr, const o2::mft::TrackerConfig* trkParam = nullptr); } // namespace ioutils } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IndexTableUtils.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IndexTableUtils.h deleted file mode 100644 index 85729dabe08b5..0000000000000 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IndexTableUtils.h +++ /dev/null @@ -1,53 +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. -/// -/// \file IndexTableUtils.h -/// \brief May collect the functions to place clusters into R-Phi bins (to be fixed) -/// - -#ifndef O2_MFT_INDEXTABLEUTILS_H_ -#define O2_MFT_INDEXTABLEUTILS_H_ - -#include <array> -#include <utility> -#include <vector> - -#include "MFTTracking/Constants.h" - -namespace o2 -{ -namespace mft -{ - -namespace index_table_utils -{ -Int_t getRBinIndex(const Int_t, const Float_t); -Int_t getPhiBinIndex(const Float_t); -Int_t getBinIndex(const Int_t, const Int_t); -} // namespace IndexTableUtils - -inline Int_t index_table_utils::getRBinIndex(const Int_t layerIndex, const Float_t rCoordinate) -{ - return -1; -} - -inline Int_t index_table_utils::getPhiBinIndex(const Float_t currentPhi) -{ - return -1; -} - -inline Int_t index_table_utils::getBinIndex(const Int_t rIndex, const Int_t phiIndex) -{ - return -1; -} -} // namespace mft -} // namespace o2 - -#endif /* O2_MFT_INDEXTABLEUTILS_H_ */ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h index c28807bdc959b..af47f2122d629 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/MFTTrackingParam.h @@ -35,6 +35,28 @@ struct MFTTrackingParam : public o2::conf::ConfigurableParamHelper<MFTTrackingPa double MFTRadLength = 1.0; // MFT average material budget within acceptance. Should be 0.041 bool verbose = false; + /// tracking algorithm (LTF and CA) parameters + /// minimum number of points for a LTF track + Int_t MinTrackPointsLTF = 5; + /// minimum number of points for a CA track + Int_t MinTrackPointsCA = 4; + /// minimum number of detector stations for a LTF track + Int_t MinTrackStationsLTF = 4; + /// minimum number of detector stations for a CA track + Int_t MinTrackStationsCA = 4; + /// maximum distance for a cluster to be attached to a seed line (LTF) + Float_t LTFclsRCut = 0.0100; + /// maximum distance for a cluster to be attached to a seed line (CA road) + Float_t ROADclsRCut = 0.0400; + /// number of bins in r-direction + Int_t RBins = 50; + /// number of bins in phi-direction + Int_t PhiBins = 50; + /// RPhi search window bin width for the second point of a seed (LTF and CA) + Int_t LTFseed2BinWin = 3; + /// RPhi search window bin width for the intermediate points + Int_t LTFinterBinWin = 3; + O2ParamDef(MFTTrackingParam, "MFTTracking"); }; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h index b5a5e8696d1db..ec58b82afeca2 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h @@ -52,7 +52,7 @@ class ROframe final const MCCompLabel& getClusterLabels(Int_t layerId, const Int_t clusterId) const { return mClusterLabels[layerId][clusterId]; } - const std::array<std::pair<Int_t, Int_t>, constants::index_table::RPhiBins>& getClusterBinIndexRange(Int_t layerId) const { return mClusterBinIndexRange[layerId]; } + const std::array<std::pair<Int_t, Int_t>, constants::index_table::MaxRPhiBins>& getClusterBinIndexRange(Int_t layerId) const { return mClusterBinIndexRange[layerId]; } const Int_t getClusterExternalIndex(Int_t layerId, const Int_t clusterId) const { return mClusterExternalIndices[layerId][clusterId]; } @@ -89,7 +89,7 @@ class ROframe final std::array<std::vector<Cluster>, constants::mft::LayersNumber> mClusters; std::array<std::vector<MCCompLabel>, constants::mft::LayersNumber> mClusterLabels; std::array<std::vector<Int_t>, constants::mft::LayersNumber> mClusterExternalIndices; - std::array<std::array<std::pair<Int_t, Int_t>, constants::index_table::RPhiBins>, constants::mft::LayersNumber> mClusterBinIndexRange; + std::array<std::array<std::pair<Int_t, Int_t>, constants::index_table::MaxRPhiBins>, constants::mft::LayersNumber> mClusterBinIndexRange; std::vector<TrackLTF> mTracksLTF; std::vector<TrackCA> mTracksCA; std::vector<Road> mRoads; @@ -149,7 +149,7 @@ inline void ROframe::clear() mClusters[iLayer].clear(); mClusterLabels[iLayer].clear(); mClusterExternalIndices[iLayer].clear(); - for (Int_t iBin = 0; iBin < constants::index_table::RPhiBins; ++iBin) { + for (Int_t iBin = 0; iBin < constants::index_table::MaxRPhiBins; ++iBin) { mClusterBinIndexRange[iLayer][iBin] = std::pair<Int_t, Int_t>(0, -1); } } diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index b5764ad749b9c..49c00e24a1177 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -18,6 +18,7 @@ #include "MFTTracking/ROframe.h" #include "MFTTracking/TrackFitter.h" #include "MFTTracking/Cluster.h" +#include "MFTTracking/TrackerConfig.h" #include "MathUtils/Utils.h" #include "MathUtils/Cartesian.h" @@ -26,9 +27,6 @@ #include "SimulationDataFormat/MCTruthContainer.h" #include "DataFormatsParameters/GRPObject.h" -// BV -#include "TStopwatch.h" - namespace o2 { namespace mft @@ -61,8 +59,12 @@ class Tracker void setROFrame(std::uint32_t f) { mROFrame = f; } std::uint32_t getROFrame() const { return mROFrame; } - // BV void initialize(); + const o2::mft::TrackerConfig* getConfig() { return mTrackerConfig.get(); } + void setConfig(const TrackerConfig& conf) + { + mTrackerConfig = std::make_unique<o2::mft::TrackerConfig>(conf); + } private: void findTracks(ROframe&); @@ -95,13 +97,24 @@ class Tracker bool mUseMC = false; - std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::RPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBinsS; - std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::RPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBins; + std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::MaxRPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBinsS; + std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::MaxRPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBins; struct TrackElement { + TrackElement() = default; + TrackElement(Int_t la, Int_t id) + { + layer = la; + idInLayer = id; + }; Int_t layer; Int_t idInLayer; }; + + std::vector<TrackElement> roadPoints; + + /// tracking configuration parameters + std::unique_ptr<o2::mft::TrackerConfig> mTrackerConfig = nullptr; }; //_________________________________________________________________________________________________ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h new file mode 100644 index 0000000000000..35beb443f4365 --- /dev/null +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.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 GeometryTGeo.h +/// \brief Definition of the GeometryTGeo class +/// \author bogdan.vulpescu@clermont.in2p3.fr - adapted from ITS, 21.09.2017 + +#ifndef ALICEO2_MFT_TRACKERCONFIG_H_ +#define ALICEO2_MFT_TRACKERCONFIG_H_ + +#include "MFTTracking/Constants.h" +#include "MFTTracking/MFTTrackingParam.h" + +namespace o2 +{ +namespace mft +{ +class TrackerConfig +{ + public: + TrackerConfig(); + TrackerConfig(const TrackerConfig& conf); + TrackerConfig& operator=(const TrackerConfig& conf); + + void initialize(const MFTTrackingParam& trkParam); + + const Int_t getRBinIndex(const Float_t r) const; + const Int_t getPhiBinIndex(const Float_t phi) const; + const Int_t getBinIndex(const Int_t rIndex, const Int_t phiIndex) const; + + // tracking configuration parameters + Int_t mMinTrackPointsLTF = 5; + Int_t mMinTrackPointsCA = 4; + Int_t mMinTrackStationsLTF = 4; + Int_t mMinTrackStationsCA = 4; + Float_t mLTFclsRCut = 0.0100; + Float_t mROADclsRCut = 0.0400; + Int_t mLTFseed2BinWin = 3; + Int_t mLTFinterBinWin = 3; + Int_t mRBins = 50; + Int_t mPhiBins = 50; + Int_t mRPhiBins = 50 * 50; + Float_t mRBinSize = (constants::index_table::RMax - constants::index_table::RMin) / 50.; + Float_t mPhiBinSize = constants::index_table::PhiMax / 50.; + Float_t mInverseRBinSize = 50. / (constants::index_table::RMax - constants::index_table::RMin); + Float_t mInversePhiBinSize = 50. / constants::index_table::PhiMax; + + private: + + ClassDefNV(TrackerConfig, 1); +}; + +inline const Int_t TrackerConfig::getRBinIndex(const Float_t r) const +{ + return (Int_t)((r - constants::index_table::RMin) * mInverseRBinSize); +} + +inline const Int_t TrackerConfig::getPhiBinIndex(const Float_t phi) const +{ + return (Int_t)((phi - constants::index_table::PhiMin) * mInversePhiBinSize); +} + +inline const Int_t TrackerConfig::getBinIndex(const Int_t rIndex, const Int_t phiIndex) const +{ + if (0 <= rIndex && rIndex < mRBins && + 0 <= phiIndex && phiIndex < mPhiBins) { + return (phiIndex * mRBins + rIndex); + } + return (mRBins * mPhiBins); +} + +} // namespace mft +} // namespace o2 + +#endif diff --git a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx index 5a81fba5d29a8..ac21ab2e30935 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Cluster.cxx @@ -12,7 +12,6 @@ /// #include "MFTTracking/Cluster.h" -#include "MFTTracking/IndexTableUtils.h" #include "MathUtils/Utils.h" #include "MathUtils/Cartesian.h" @@ -35,19 +34,5 @@ Cluster::Cluster(const Float_t x, const Float_t y, const Float_t z, const Int_t o2::math_utils::bringTo02PiGen(phiCoordinate); } -Cluster::Cluster(const Int_t layerIndex, const Cluster& other) - : BaseCluster(1, other.getXYZ()), - phiCoordinate{0.}, - rCoordinate{0.}, - clusterId{other.clusterId}, - indexTableBin{index_table_utils::getBinIndex(index_table_utils::getRBinIndex(layerIndex, rCoordinate), - index_table_utils::getPhiBinIndex(phiCoordinate))} -{ - auto clsPoint2D = math_utils::Point2D<Float_t>(other.getX(), other.getY()); - rCoordinate = clsPoint2D.R(); - phiCoordinate = clsPoint2D.Phi(); - o2::math_utils::bringTo02PiGen(phiCoordinate); -} - } // namespace mft } // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index 4bc5cbb72a854..68ad6fbb7ba22 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -35,7 +35,7 @@ namespace mft { int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, gsl::span<const itsmft::CompClusterExt> clusters, gsl::span<const unsigned char>::iterator& pattIt, const itsmft::TopologyDictionary& dict, - const dataformats::MCTruthContainer<MCCompLabel>* mcLabels) + const dataformats::MCTruthContainer<MCCompLabel>* mcLabels, const o2::mft::TrackerConfig* trkParam) { event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); @@ -72,9 +72,9 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g Float_t rCoord = clsPoint2D.R(); Float_t phiCoord = clsPoint2D.Phi(); o2::math_utils::bringTo02PiGen(phiCoord); - int rBinIndex = constants::index_table::getRBinIndex(rCoord); - int phiBinIndex = constants::index_table::getPhiBinIndex(phiCoord); - int binIndex = constants::index_table::getBinIndex(rBinIndex, phiBinIndex); + int rBinIndex = trkParam->getRBinIndex(rCoord); + int phiBinIndex = trkParam->getPhiBinIndex(phiCoord); + int binIndex = trkParam->getBinIndex(rBinIndex, phiBinIndex); // TODO: Check consistency of sigmaX2 and sigmaY2 event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), phiCoord, rCoord, event.getClustersInLayer(layer).size(), binIndex, sigmaX2, sigmaY2, sensorID); if (mcLabels) { diff --git a/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h b/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h index f5f83773097fb..b409fc2de6379 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h +++ b/Detectors/ITSMFT/MFT/tracking/src/MFTTrackingLinkDef.h @@ -17,6 +17,7 @@ #pragma link C++ class o2::mft::TrackCA + ; #pragma link C++ class std::vector < o2::mft::TrackLTF> + ; #pragma link C++ class std::vector < o2::mft::TrackCA> + ; +#pragma link C++ class o2::mft::TrackerConfig + ; #pragma link C++ class o2::mft::MFTTrackingParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::mft::MFTTrackingParam> + ; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index bf8e7c23f2f11..b873182bd866b 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -28,7 +28,6 @@ namespace mft //_________________________________________________________________________________________________ Tracker::Tracker(bool useMC) : mUseMC{useMC} { - mTrackFitter = std::make_unique<o2::mft::TrackFitter>(); } @@ -51,15 +50,15 @@ void Tracker::initialize() for (Int_t layer1 = 0; layer1 < (constants::mft::LayersNumber - 1); ++layer1) { - for (Int_t iRBin = 0; iRBin < constants::index_table::RBins; ++iRBin) { + for (Int_t iRBin = 0; iRBin < mTrackerConfig.get()->mRBins; ++iRBin) { - r = (iRBin + 0.5) * constants::index_table::RBinSize + constants::index_table::RMin; + r = (iRBin + 0.5) * mTrackerConfig.get()->mRBinSize + constants::index_table::RMin; - for (Int_t iPhiBin = 0; iPhiBin < constants::index_table::PhiBins; ++iPhiBin) { + for (Int_t iPhiBin = 0; iPhiBin < mTrackerConfig.get()->mPhiBins; ++iPhiBin) { - phi = (iPhiBin + 0.5) * constants::index_table::PhiBinSize + constants::index_table::PhiMin; + phi = (iPhiBin + 0.5) * mTrackerConfig.get()->mPhiBinSize + constants::index_table::PhiMin; - binIndex1 = constants::index_table::getBinIndex(iRBin, iPhiBin); + binIndex1 = mTrackerConfig.get()->getBinIndex(iRBin, iPhiBin); x = r * TMath::Cos(phi); y = r * TMath::Sin(phi); @@ -74,43 +73,70 @@ void Tracker::initialize() phi_proj = clsPoint2D.Phi(); o2::math_utils::bringTo02PiGen(phi_proj); - binR_proj = constants::index_table::getRBinIndex(r_proj); - binPhi_proj = constants::index_table::getPhiBinIndex(phi_proj); + binR_proj = mTrackerConfig.get()->getRBinIndex(r_proj); + binPhi_proj = mTrackerConfig.get()->getPhiBinIndex(phi_proj); int binRS, binPhiS; - int binhwS = constants::index_table::LTFseed2BinWin / 2; - for (Int_t iR = 0; iR < constants::index_table::LTFseed2BinWin; ++iR) { - binRS = binR_proj + (iR - binhwS); + + int binwRS = mTrackerConfig.get()->mLTFseed2BinWin; + if (abs(dz) < 1.5) { + binwRS = 3; + } else if (abs(dz) < 5.0) { + binwRS = 3; + } else if (abs(dz) < 10.0) { + binwRS = 3; + } else if (abs(dz) < 15.0) { + binwRS = 3; + } else if (abs(dz) < 20.0) { + binwRS = 3; + } else if (abs(dz) < 25.0) { + binwRS = 3; + } else { + binwRS = 3; + } + int binhwRS = binwRS / 2; + + int binwPhiS = mTrackerConfig.get()->mLTFseed2BinWin; + int binhwPhiS = binwPhiS / 2; + + for (Int_t iR = 0; iR < binwRS; ++iR) { + binRS = binR_proj + (iR - binhwRS); if (binRS < 0) { continue; } - for (Int_t iPhi = 0; iPhi < constants::index_table::LTFseed2BinWin; ++iPhi) { - binPhiS = binPhi_proj + (iPhi - binhwS); + for (Int_t iPhi = 0; iPhi < binwPhiS; ++iPhi) { + binPhiS = binPhi_proj + (iPhi - binhwPhiS); if (binPhiS < 0) { continue; } - binIndex2S = constants::index_table::getBinIndex(binRS, binPhiS); + binIndex2S = mTrackerConfig.get()->getBinIndex(binRS, binPhiS); mBinsS[layer1][layer2 - 1][binIndex1].emplace_back(binIndex2S); } } int binR, binPhi; - int binhw = constants::index_table::LTFinterBinWin / 2; - for (Int_t iR = 0; iR < constants::index_table::LTFinterBinWin; ++iR) { - binR = binR_proj + (iR - binhw); + + int binwR = mTrackerConfig.get()->mLTFinterBinWin; + int binhwR = binwR / 2; + + int binwPhi = mTrackerConfig.get()->mLTFinterBinWin; + int binhwPhi = binwPhi / 2; + + for (Int_t iR = 0; iR < binwR; ++iR) { + binR = binR_proj + (iR - binhwR); if (binR < 0) { continue; } - for (Int_t iPhi = 0; iPhi < constants::index_table::LTFinterBinWin; ++iPhi) { - binPhi = binPhi_proj + (iPhi - binhw); + for (Int_t iPhi = 0; iPhi < binwPhi; ++iPhi) { + binPhi = binPhi_proj + (iPhi - binhwPhi); if (binPhi < 0) { continue; } - binIndex2 = constants::index_table::getBinIndex(binR, binPhi); + binIndex2 = mTrackerConfig.get()->getBinIndex(binR, binPhi); mBins[layer1][layer2 - 1][binIndex1].emplace_back(binIndex2); } } @@ -148,10 +174,10 @@ void Tracker::findTracksLTF(ROframe& event) Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; Int_t extClsIndex; - Float_t dR, dRmin, dRcut = constants::mft::LTFclsRCut; + Float_t dR, dRmin, dRcut = mTrackerConfig.get()->mLTFclsRCut; Bool_t hasDisk[constants::mft::DisksNumber], newPoint, seed; - Int_t clsLayer1, clsLayer2, clsLayer; + Int_t clsInLayer1, clsInLayer2, clsInLayer; Int_t nPoints; TrackElement trackPoints[constants::mft::LayersNumber]; @@ -165,9 +191,9 @@ void Tracker::findTracksLTF(ROframe& event) layer2 = (step == 0) ? (constants::mft::LayersNumber - 1) : (layer2 - 1); step++; - if (layer2 < layer1 + (constants::mft::MinTrackPointsLTF - 1)) { + if (layer2 < layer1 + (mTrackerConfig.get()->mMinTrackPointsLTF - 1)) { ++layer1; - if (layer1 > (constants::mft::LayersNumber - (constants::mft::MinTrackPointsLTF - 1))) { + if (layer1 > (constants::mft::LayersNumber - (mTrackerConfig.get()->mMinTrackPointsLTF - 1))) { break; } step = 0; @@ -179,7 +205,7 @@ void Tracker::findTracksLTF(ROframe& event) if (cluster1.getUsed()) { continue; } - clsLayer1 = it1 - event.getClustersInLayer(layer1).begin(); + clsInLayer1 = it1 - event.getClustersInLayer(layer1).begin(); // loop over the bins in the search window for (auto& binS : mBinsS[layer1][layer2 - 1][cluster1.indexTableBin]) { @@ -191,14 +217,14 @@ void Tracker::findTracksLTF(ROframe& event) if (cluster2.getUsed()) { continue; } - clsLayer2 = it2 - event.getClustersInLayer(layer2).begin(); + clsInLayer2 = it2 - event.getClustersInLayer(layer2).begin(); // start a TrackLTF nPoints = 0; // add the first seed point trackPoints[nPoints].layer = layer1; - trackPoints[nPoints].idInLayer = clsLayer1; + trackPoints[nPoints].idInLayer = clsInLayer1; nPoints++; // intermediate layers @@ -217,7 +243,7 @@ void Tracker::findTracksLTF(ROframe& event) if (cluster.getUsed()) { continue; } - clsLayer = it - event.getClustersInLayer(layer).begin(); + clsInLayer = it - event.getClustersInLayer(layer).begin(); dR = getDistanceToSeed(cluster1, cluster2, cluster); // retain the closest point within a radius dRcut @@ -228,7 +254,7 @@ void Tracker::findTracksLTF(ROframe& event) if (newPoint) { trackPoints[nPoints].layer = layer; - trackPoints[nPoints].idInLayer = clsLayer; + trackPoints[nPoints].idInLayer = clsInLayer; nPoints++; } // retain only the closest point in DistanceToSeed @@ -239,11 +265,11 @@ void Tracker::findTracksLTF(ROframe& event) // add the second seed point trackPoints[nPoints].layer = layer2; - trackPoints[nPoints].idInLayer = clsLayer2; + trackPoints[nPoints].idInLayer = clsInLayer2; nPoints++; // keep only tracks fulfilling the minimum length condition - if (nPoints < constants::mft::MinTrackPointsLTF) { + if (nPoints < mTrackerConfig.get()->mMinTrackPointsLTF) { continue; } for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { @@ -259,7 +285,7 @@ void Tracker::findTracksLTF(ROframe& event) ++nPointDisks; } } - if (nPointDisks < constants::mft::MinTrackStationsLTF) { + if (nPointDisks < mTrackerConfig.get()->mMinTrackStationsLTF) { continue; } @@ -267,11 +293,11 @@ void Tracker::findTracksLTF(ROframe& event) event.addTrackLTF(); for (Int_t point = 0; point < nPoints; ++point) { auto layer = trackPoints[point].layer; - auto clsLayer = trackPoints[point].idInLayer; - Cluster& cluster = event.getClustersInLayer(layer)[clsLayer]; + auto clsInLayer = trackPoints[point].idInLayer; + Cluster& cluster = event.getClustersInLayer(layer)[clsInLayer]; mcCompLabel = mUseMC ? event.getClusterLabels(layer, cluster.clusterId) : MCCompLabel(); extClsIndex = event.getClusterExternalIndex(layer, cluster.clusterId); - event.getCurrentTrackLTF().setPoint(cluster, layer, clsLayer, mcCompLabel, extClsIndex); + event.getCurrentTrackLTF().setPoint(cluster, layer, clsInLayer, mcCompLabel, extClsIndex); // mark the used clusters cluster.setUsed(true); } @@ -299,13 +325,13 @@ void Tracker::findTracksCA(ROframe& event) Int_t roadId, nPointDisks; Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; - Float_t dR, dRcut = constants::mft::ROADclsRCut; + Float_t dR, dRcut = mTrackerConfig.get()->mROADclsRCut; Bool_t hasDisk[constants::mft::DisksNumber]; - Int_t clsLayer1, clsLayer2, clsLayer; + Int_t clsInLayer1, clsInLayer2, clsInLayer; Int_t nPoints; - TrackElement roadPoints[10 * constants::mft::LayersNumber]; + //TrackElement roadPoints[10 * constants::mft::LayersNumber]; roadId = 0; @@ -318,7 +344,7 @@ void Tracker::findTracksCA(ROframe& event) if (cluster1.getUsed()) { continue; } - clsLayer1 = it1 - event.getClustersInLayer(layer1).begin(); + clsInLayer1 = it1 - event.getClustersInLayer(layer1).begin(); // loop over the bins in the search window for (auto& binS : mBinsS[layer1][layer2 - 1][cluster1.indexTableBin]) { @@ -330,15 +356,17 @@ void Tracker::findTracksCA(ROframe& event) if (cluster2.getUsed()) { continue; } - clsLayer2 = it2 - event.getClustersInLayer(layer2).begin(); + clsInLayer2 = it2 - event.getClustersInLayer(layer2).begin(); // start a road - nPoints = 0; + //nPoints = 0; + roadPoints.clear(); // add the first seed point - roadPoints[nPoints].layer = layer1; - roadPoints[nPoints].idInLayer = clsLayer1; - nPoints++; + //roadPoints[nPoints].layer = layer1; + //roadPoints[nPoints].idInLayer = clsInLayer1; + //nPoints++; + roadPoints.emplace_back(layer1, clsInLayer1); for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { @@ -352,28 +380,32 @@ void Tracker::findTracksCA(ROframe& event) if (cluster.getUsed()) { continue; } - clsLayer = it - event.getClustersInLayer(layer).begin(); + clsInLayer = it - event.getClustersInLayer(layer).begin(); dR = getDistanceToSeed(cluster1, cluster2, cluster); // add all points within a radius dRcut if (dR >= dRcut) { continue; } - roadPoints[nPoints].layer = layer; - roadPoints[nPoints].idInLayer = clsLayer; - nPoints++; + + //roadPoints[nPoints].layer = layer; + //roadPoints[nPoints].idInLayer = clsInLayer; + //nPoints++; + roadPoints.emplace_back(layer, clsInLayer); } // end clusters bin intermediate layer } // end intermediate layers } // end binR // add the second seed point - roadPoints[nPoints].layer = layer2; - roadPoints[nPoints].idInLayer = clsLayer2; - nPoints++; + //roadPoints[nPoints].layer = layer2; + //roadPoints[nPoints].idInLayer = clsInLayer2; + //nPoints++; + roadPoints.emplace_back(layer2, clsInLayer2); + nPoints = roadPoints.size(); // keep only roads fulfilling the minimum length condition - if (nPoints < constants::mft::MinTrackPointsCA) { + if (nPoints < mTrackerConfig.get()->mMinTrackPointsCA) { continue; } for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { @@ -389,15 +421,15 @@ void Tracker::findTracksCA(ROframe& event) ++nPointDisks; } } - if (nPointDisks < constants::mft::MinTrackStationsCA) { + if (nPointDisks < mTrackerConfig.get()->mMinTrackStationsCA) { continue; } event.addRoad(); for (Int_t point = 0; point < nPoints; ++point) { auto layer = roadPoints[point].layer; - auto clsLayer = roadPoints[point].idInLayer; - event.getCurrentRoad().setPoint(layer, clsLayer); + auto clsInLayer = roadPoints[point].idInLayer; + event.getCurrentRoad().setPoint(layer, clsInLayer); } event.getCurrentRoad().setRoadId(roadId); ++roadId; @@ -418,7 +450,7 @@ void Tracker::computeCellsInRoad(ROframe& event) { Int_t layer1, layer1min, layer1max, layer2, layer2min, layer2max; Int_t nPtsInLayer1, nPtsInLayer2; - Int_t clsLayer1, clsLayer2; + Int_t clsInLayer1, clsInLayer2; Int_t cellId; Bool_t noCell; @@ -438,7 +470,7 @@ void Tracker::computeCellsInRoad(ROframe& event) for (Int_t point1 = 0; point1 < nPtsInLayer1; ++point1) { - clsLayer1 = road.getClustersIdInLayer(layer1)[point1]; + clsInLayer1 = road.getClustersIdInLayer(layer1)[point1]; layer2 = layer2min; @@ -453,11 +485,11 @@ void Tracker::computeCellsInRoad(ROframe& event) */ for (Int_t point2 = 0; point2 < nPtsInLayer2; ++point2) { - clsLayer2 = road.getClustersIdInLayer(layer2)[point2]; + clsInLayer2 = road.getClustersIdInLayer(layer2)[point2]; noCell = kFALSE; // create a cell - addCellToCurrentRoad(event, layer1, layer2, clsLayer1, clsLayer2, cellId); + addCellToCurrentRoad(event, layer1, layer2, clsInLayer1, clsInLayer2, cellId); } // end points in layer2 ++layer2; @@ -537,6 +569,8 @@ void Tracker::runBackwardInRoad(ROframe& event) Int_t nCells; TrackElement trackCells[constants::mft::LayersNumber - 1]; + //std::vector<TrackElement> trackCells; + //trackCells.reserve(constants::mft::LayersNumber - 1); for (Int_t layer = maxLayer; layer >= minLayer; --layer) { @@ -545,16 +579,18 @@ void Tracker::runBackwardInRoad(ROframe& event) if (road.isCellUsed(layer, cellId)) { continue; } - if (road.getCellLevel(layer, cellId) < (constants::mft::MinTrackPointsCA - 1)) { + if (road.getCellLevel(layer, cellId) < (mTrackerConfig.get()->mMinTrackPointsCA - 1)) { continue; } // start a TrackCA nCells = 0; + //trackCells.clear(); trackCells[nCells].layer = layer; trackCells[nCells].idInLayer = cellId; nCells++; + //trackCells.emplace_back(layer, cellId); // add cells to the new track addCellToNewTrack = kTRUE; @@ -594,11 +630,13 @@ void Tracker::runBackwardInRoad(ROframe& event) if (leftNeighbour != cellRC.getLeftNeighbours().front()) { // delete the last added cell nCells--; + //trackCells.pop_back(); } trackCells[nCells].layer = layerL; trackCells[nCells].idInLayer = cellIdL; nCells++; + //trackCells.emplace_back(layerL, cellIdL); addCellToNewTrack = kTRUE; } @@ -628,7 +666,7 @@ void Tracker::runBackwardInRoad(ROframe& event) } } - if (nPointDisks < constants::mft::MinTrackStationsCA) { + if (nPointDisks < mTrackerConfig.get()->mMinTrackStationsCA) { continue; } @@ -660,14 +698,14 @@ void Tracker::updateCellStatusInRoad(Road& road) } //_________________________________________________________________________________________________ -void Tracker::addCellToCurrentRoad(ROframe& event, const Int_t layer1, const Int_t layer2, const Int_t clsLayer1, const Int_t clsLayer2, Int_t& cellId) +void Tracker::addCellToCurrentRoad(ROframe& event, const Int_t layer1, const Int_t layer2, const Int_t clsInLayer1, const Int_t clsInLayer2, Int_t& cellId) { Road& road = event.getCurrentRoad(); - Cell& cell = road.addCellInLayer(layer1, layer2, clsLayer1, clsLayer2, cellId); + Cell& cell = road.addCellInLayer(layer1, layer2, clsInLayer1, clsInLayer2, cellId); - Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; - Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; + Cluster& cluster1 = event.getClustersInLayer(layer1)[clsInLayer1]; + Cluster& cluster2 = event.getClustersInLayer(layer2)[clsInLayer2]; Float_t coord[6]; coord[0] = cluster1.getX(); @@ -688,11 +726,11 @@ void Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t cellId, RO Road& road = event.getCurrentRoad(); const Cell& cell = road.getCellsInLayer(layer1)[cellId]; const Int_t layer2 = cell.getSecondLayerId(); - const Int_t clsLayer1 = cell.getFirstClusterIndex(); - const Int_t clsLayer2 = cell.getSecondClusterIndex(); + const Int_t clsInLayer1 = cell.getFirstClusterIndex(); + const Int_t clsInLayer2 = cell.getSecondClusterIndex(); - Cluster& cluster1 = event.getClustersInLayer(layer1)[clsLayer1]; - Cluster& cluster2 = event.getClustersInLayer(layer2)[clsLayer2]; + Cluster& cluster1 = event.getClustersInLayer(layer1)[clsInLayer1]; + Cluster& cluster2 = event.getClustersInLayer(layer2)[clsInLayer2]; MCCompLabel mcCompLabel1 = mUseMC ? event.getClusterLabels(layer1, cluster1.clusterId) : MCCompLabel(); MCCompLabel mcCompLabel2 = mUseMC ? event.getClusterLabels(layer2, cluster2.clusterId) : MCCompLabel(); @@ -701,11 +739,11 @@ void Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t cellId, RO if (trackCA.getNumberOfPoints() == 0) { extClsIndex = event.getClusterExternalIndex(layer2, cluster2.clusterId); - trackCA.setPoint(cluster2, layer2, clsLayer2, mcCompLabel2, extClsIndex); + trackCA.setPoint(cluster2, layer2, clsInLayer2, mcCompLabel2, extClsIndex); } extClsIndex = event.getClusterExternalIndex(layer1, cluster1.clusterId); - trackCA.setPoint(cluster1, layer1, clsLayer1, mcCompLabel1, extClsIndex); + trackCA.setPoint(cluster1, layer1, clsInLayer1, mcCompLabel1, extClsIndex); } //_________________________________________________________________________________________________ diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx new file mode 100644 index 0000000000000..d141bbfca6d50 --- /dev/null +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx @@ -0,0 +1,113 @@ +// 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 GeometryTGeo.cxx +/// \brief Implementation of the GeometryTGeo class +/// \author bogdan.vulpescu@clermont.in2p3.fr - adapted from ITS, 21.09.2017 + +#include "MFTTracking/TrackerConfig.h" + +#include <fairlogger/Logger.h> + +//__________________________________________________________________________ +o2::mft::TrackerConfig::TrackerConfig() + : mMinTrackPointsLTF{5}, + mMinTrackPointsCA{4}, + mMinTrackStationsLTF{4}, + mMinTrackStationsCA{4}, + mLTFclsRCut{0.0100}, + mROADclsRCut{0.0400}, + mLTFseed2BinWin{3}, + mLTFinterBinWin{3}, + mRBins{50}, + mPhiBins{50}, + mRPhiBins{50 * 50}, + mRBinSize{(constants::index_table::RMax - constants::index_table::RMin) / 50.}, + mPhiBinSize{(constants::index_table::PhiMax - constants::index_table::PhiMin) / 50.}, + mInverseRBinSize{50. / (constants::index_table::RMax - constants::index_table::RMin)}, + mInversePhiBinSize{50. / (constants::index_table::PhiMax - constants::index_table::PhiMin)} +{ + /// default constructor +} + +//__________________________________________________________________________ +o2::mft::TrackerConfig::TrackerConfig(const TrackerConfig& conf) + : mMinTrackPointsLTF(conf.mMinTrackPointsLTF), + mMinTrackPointsCA(conf.mMinTrackPointsCA), + mMinTrackStationsLTF(conf.mMinTrackStationsLTF), + mMinTrackStationsCA(conf.mMinTrackStationsCA), + mLTFclsRCut(conf.mLTFclsRCut), + mROADclsRCut(conf.mROADclsRCut), + mLTFseed2BinWin(conf.mLTFseed2BinWin), + mLTFinterBinWin(conf.mLTFinterBinWin), + mRBins(conf.mRBins), + mPhiBins(conf.mPhiBins), + mRPhiBins(conf.mRPhiBins), + mRBinSize(conf.mRBinSize), + mPhiBinSize(conf.mPhiBinSize), + mInverseRBinSize(conf.mInverseRBinSize), + mInversePhiBinSize(conf.mInversePhiBinSize) +{ + /// copy constructor +} + +//__________________________________________________________________________ +o2::mft::TrackerConfig& o2::mft::TrackerConfig::operator=(const TrackerConfig& conf) +{ + /// assign constructor + + if (this == &conf) { + return *this; + } + + mMinTrackPointsLTF = conf.mMinTrackPointsLTF; + mMinTrackPointsCA = conf.mMinTrackPointsCA; + mMinTrackStationsLTF = conf.mMinTrackStationsLTF; + mMinTrackStationsCA = conf.mMinTrackStationsCA; + mLTFclsRCut = conf.mLTFclsRCut; + mROADclsRCut = conf.mROADclsRCut; + mLTFseed2BinWin = conf.mLTFseed2BinWin; + mLTFinterBinWin = conf.mLTFinterBinWin; + mRBins = conf.mRBins; + mPhiBins = conf.mPhiBins; + mRPhiBins = conf.mRPhiBins; + mRBinSize = conf.mRBinSize; + mPhiBinSize = conf.mPhiBinSize; + mInverseRBinSize = conf.mInverseRBinSize; + mInversePhiBinSize = conf.mInversePhiBinSize; +} + +//__________________________________________________________________________ +void o2::mft::TrackerConfig::initialize(const MFTTrackingParam& trkParam) +{ + /// initialize from MFTTrackingParam (command line configuration parameters) + + mMinTrackPointsLTF = trkParam.MinTrackPointsLTF; + mMinTrackPointsCA = trkParam.MinTrackPointsCA; + mMinTrackStationsLTF = trkParam.MinTrackStationsLTF; + mMinTrackStationsCA = trkParam.MinTrackStationsCA; + mLTFclsRCut = trkParam.LTFclsRCut; + mROADclsRCut = trkParam.ROADclsRCut; + mLTFseed2BinWin = trkParam.LTFseed2BinWin; + mLTFinterBinWin = trkParam.LTFinterBinWin; + + mRBins = trkParam.RBins; + mPhiBins = trkParam.PhiBins; + mRPhiBins = trkParam.RBins * trkParam.PhiBins; + if (mRPhiBins > constants::index_table::MaxRPhiBins) { + LOG(WARN) << "To many RPhiBins for this configuration!"; + mRPhiBins = constants::index_table::MaxRPhiBins; + mRBins = sqrt(constants::index_table::MaxRPhiBins); + mPhiBins = sqrt(constants::index_table::MaxRPhiBins); + LOG(WARN) << "Using instead RBins " << mRBins << " and PhiBins " << mPhiBins; + } + mRBinSize = (constants::index_table::RMax - constants::index_table::RMin) / mRBins; + mPhiBinSize = (constants::index_table::PhiMax - constants::index_table::PhiMin) / mPhiBins; +} diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index e9a40ba29ac0a..47d7fa837f177 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -12,6 +12,7 @@ #include "MFTWorkflow/TrackerSpec.h" +#include "MFTTracking/TrackerConfig.h" #include "MFTTracking/ROframe.h" #include "MFTTracking/IOUtils.h" #include "MFTTracking/Tracker.h" @@ -57,15 +58,22 @@ void TrackerDPL::init(InitContext& ic) geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2G)); + // tracking configuration parameters + auto& mftTrackingParam = MFTTrackingParam::Instance(); + // create the tracker configuration + const auto& trackerConfig = std::make_unique<o2::mft::TrackerConfig>(); + trackerConfig->initialize(mftTrackingParam); + // create the tracker: set the B-field, the configuration and initialize mTracker = std::make_unique<o2::mft::Tracker>(mUseMC); double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT mTracker->setBz(field->getBz(centerMFT)); + mTracker->setConfig(const_cast<TrackerConfig&>(*trackerConfig.get())); mTracker->initialize(); } else { throw std::runtime_error(o2::utils::concat_string("Cannot retrieve GRP from the ", filename)); } - std::string dictPath = ic.options().get<std::string>("its-dictionary-path"); + std::string dictPath = ic.options().get<std::string>("mft-dictionary-path"); std::string dictFile = o2::base::NameConf::getDictionaryFileName(o2::detectors::DetID::MFT, dictPath, ".bin"); if (o2::base::NameConf::pathExists(dictFile)) { mDict.readBinaryFile(dictFile); @@ -132,7 +140,7 @@ void TrackerDPL::run(ProcessingContext& pc) gsl::span<const unsigned char>::iterator pattIt = patterns.begin(); if (continuous) { for (auto& rof : rofs) { - int nclUsed = ioutils::loadROFrameData(rof, event, compClusters, pattIt, mDict, labels); + int nclUsed = ioutils::loadROFrameData(rof, event, compClusters, pattIt, mDict, labels, (mTracker.get())->getConfig()); if (nclUsed) { event.setROFrameId(roFrame); event.initialize(); @@ -207,7 +215,7 @@ DataProcessorSpec getTrackerSpec(bool useMC) AlgorithmSpec{adaptFromTask<TrackerDPL>(useMC)}, Options{ {"grp-file", VariantType::String, "o2sim_grp.root", {"Name of the output file"}}, - {"its-dictionary-path", VariantType::String, "", {"Path of the cluster-topology dictionary file"}}}}; + {"mft-dictionary-path", VariantType::String, "", {"Path of the cluster-topology dictionary file"}}}}; } } // namespace mft From fde6b3b79a4435bb6e5d97ab9d696368fe297d0e Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Wed, 2 Dec 2020 14:14:21 +0100 Subject: [PATCH 1567/1751] MFT: further optimizations in the tracker --- .../MFT/tracking/include/MFTTracking/Cell.h | 12 +- .../tracking/include/MFTTracking/Constants.h | 4 +- .../tracking/include/MFTTracking/IOUtils.h | 4 +- .../tracking/include/MFTTracking/ROframe.h | 2 +- .../MFT/tracking/include/MFTTracking/Road.h | 26 ++- .../tracking/include/MFTTracking/Tracker.h | 19 +- .../include/MFTTracking/TrackerConfig.h | 13 +- Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx | 8 +- Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 200 ++++++++---------- .../ITSMFT/MFT/tracking/src/TrackerConfig.cxx | 47 ---- .../ITSMFT/MFT/workflow/src/TrackerSpec.cxx | 7 +- 11 files changed, 140 insertions(+), 202 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h index 38cac67fac9fc..4b1a78cbb2f32 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Cell.h @@ -26,7 +26,7 @@ namespace o2 namespace mft { -class Cell final +class Cell { public: Cell(); @@ -131,24 +131,16 @@ inline void Cell::setLevel(const Int_t level) { mLevel = level; } inline void Cell::addRightNeighbour(const Int_t layer, const Int_t clusterId) { - //std::cout << "Cell::addRightNeighbour " << layer << " " << clusterId << std::endl; - try { - mRightNeighbours.at(mNRightNeighbours++) = std::pair<Int_t, Int_t>(layer, clusterId); - } catch (const std::out_of_range& err) { - std::cout << "Maximum number of right neighbours for this cell!" << std::endl; - } - //std::cout << "Cell::addRightNeighbour done..." << std::endl; + mRightNeighbours.at(mNRightNeighbours++) = std::pair<Int_t, Int_t>(layer, clusterId); } inline void Cell::addLeftNeighbour(const Int_t layer, const Int_t clusterId) { - //std::cout << "Cell::addLeftNeighbour " << layer << " " << clusterId << std::endl; try { mLeftNeighbours.at(mNLeftNeighbours++) = std::pair<Int_t, Int_t>(layer, clusterId); } catch (const std::out_of_range& err) { std::cout << "Maximum number of left neighbours for this cell!" << std::endl; } - //std::cout << "Cell::addLeftNeighbour done..." << std::endl; } inline const std::array<std::pair<Int_t, Int_t>, constants::mft::MaxCellNeighbours>& Cell::getLeftNeighbours() const diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h index 4afc191dab535..51ca134d3a204 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Constants.h @@ -48,7 +48,9 @@ constexpr std::array<Float_t, LayersNumber> InverseLayerZCoordinate() { return std::array<Float_t, LayersNumber>{-1. / 45.3, -1. / 46.7, -1. / 48.6, -1. / 50.0, -1. / 52.4, -1. / 53.8, -1. / 67.7, -1. / 69.1, -1. / 76.1, -1. / 77.5}; } -constexpr Int_t MaxCellNeighbours{10}; +constexpr Int_t MaxCellNeighbours{50}; +constexpr Int_t MaxPointsInRoad{100}; +constexpr Int_t MaxCellsInRoad{100}; } // namespace mft namespace index_table diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h index d812fae253987..b11522c6eb496 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/IOUtils.h @@ -21,7 +21,7 @@ #include <vector> #include <gsl/gsl> -#include "MFTTracking/TrackerConfig.h" +#include "MFTTracking/Tracker.h" #include "MFTTracking/ROframe.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "DataFormatsITSMFT/ROFRecord.h" @@ -57,7 +57,7 @@ constexpr float DefClusError2Col = DefClusErrorCol * DefClusErrorCol; int loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& events, gsl::span<const itsmft::CompClusterExt> clusters, gsl::span<const unsigned char>::iterator& pattIt, const itsmft::TopologyDictionary& dict, - const dataformats::MCTruthContainer<MCCompLabel>* mClsLabels = nullptr, const o2::mft::TrackerConfig* trkParam = nullptr); + const dataformats::MCTruthContainer<MCCompLabel>* mClsLabels = nullptr, const o2::mft::Tracker* tracker = nullptr); } // namespace ioutils } // namespace mft diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h index ec58b82afeca2..6ac9e28d00def 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/ROframe.h @@ -39,7 +39,7 @@ namespace mft class TrackCA; class TrackLTF; -class ROframe final +class ROframe { public: ROframe(Int_t ROframeId); diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h index 76efc41e89ac5..ba1471bbc6d8a 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Road.h @@ -23,10 +23,12 @@ namespace o2 namespace mft { -class Road final +class Road { public: - Road(); + Road() { mRoadId = 0; }; + void reset(); + void initialize(); void setPoint(const Int_t layer, const Int_t clusterId) { @@ -64,10 +66,24 @@ class Road final std::array<std::vector<Cell>, (constants::mft::LayersNumber - 1)> mCell; }; -inline Road::Road() - : mRoadId{0} +inline void Road::reset() { - // Nothing to do + Int_t layer; + for (layer = 0; layer < (constants::mft::LayersNumber - 1); ++layer) { + mCell[layer].clear(); + mClusterId[layer].clear(); + } + mClusterId[layer].clear(); +} + +inline void Road::initialize() +{ + Int_t layer; + for (layer = 0; layer < (constants::mft::LayersNumber - 1); ++layer) { + mCell[layer].reserve(constants::mft::MaxCellsInRoad); + mClusterId[layer].reserve(constants::mft::MaxPointsInRoad); + } + mClusterId[layer].reserve(constants::mft::MaxPointsInRoad); } inline const Int_t Road::getNPointsInLayer(Int_t layer) const diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 49c00e24a1177..76f8b0d71a8f6 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -34,7 +34,7 @@ namespace mft class TrackLTF; -class Tracker +class Tracker : public TrackerConfig { public: @@ -60,20 +60,16 @@ class Tracker std::uint32_t getROFrame() const { return mROFrame; } void initialize(); - const o2::mft::TrackerConfig* getConfig() { return mTrackerConfig.get(); } - void setConfig(const TrackerConfig& conf) - { - mTrackerConfig = std::make_unique<o2::mft::TrackerConfig>(conf); - } + void initConfig(const MFTTrackingParam& trkParam); private: void findTracks(ROframe&); void findTracksLTF(ROframe&); void findTracksCA(ROframe&); void computeCellsInRoad(ROframe&); - void runForwardInRoad(ROframe&); + void runForwardInRoad(); void runBackwardInRoad(ROframe&); - void updateCellStatusInRoad(Road&); + void updateCellStatusInRoad(); bool fitTracks(ROframe&); @@ -100,6 +96,7 @@ class Tracker std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::MaxRPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBinsS; std::array<std::array<std::array<std::vector<Int_t>, constants::index_table::MaxRPhiBins>, (constants::mft::LayersNumber - 1)>, (constants::mft::LayersNumber - 1)> mBins; + /// helper to store points of a track candidate struct TrackElement { TrackElement() = default; TrackElement(Int_t la, Int_t id) @@ -111,10 +108,8 @@ class Tracker Int_t idInLayer; }; - std::vector<TrackElement> roadPoints; - - /// tracking configuration parameters - std::unique_ptr<o2::mft::TrackerConfig> mTrackerConfig = nullptr; + /// current road for CA algorithm + Road mRoad; }; //_________________________________________________________________________________________________ diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h index 35beb443f4365..b36de0be1b9b3 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h @@ -24,17 +24,17 @@ namespace mft { class TrackerConfig { - public: + public: TrackerConfig(); - TrackerConfig(const TrackerConfig& conf); - TrackerConfig& operator=(const TrackerConfig& conf); + TrackerConfig(const TrackerConfig& conf) = default; + TrackerConfig& operator=(const TrackerConfig& conf) = default; void initialize(const MFTTrackingParam& trkParam); - + const Int_t getRBinIndex(const Float_t r) const; const Int_t getPhiBinIndex(const Float_t phi) const; const Int_t getBinIndex(const Int_t rIndex, const Int_t phiIndex) const; - + // tracking configuration parameters Int_t mMinTrackPointsLTF = 5; Int_t mMinTrackPointsCA = 4; @@ -53,7 +53,6 @@ class TrackerConfig Float_t mInversePhiBinSize = 50. / constants::index_table::PhiMax; private: - ClassDefNV(TrackerConfig, 1); }; @@ -75,7 +74,7 @@ inline const Int_t TrackerConfig::getBinIndex(const Int_t rIndex, const Int_t ph } return (mRBins * mPhiBins); } - + } // namespace mft } // namespace o2 diff --git a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx index 68ad6fbb7ba22..5d25a724cfa7b 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/IOUtils.cxx @@ -35,7 +35,7 @@ namespace mft { int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, gsl::span<const itsmft::CompClusterExt> clusters, gsl::span<const unsigned char>::iterator& pattIt, const itsmft::TopologyDictionary& dict, - const dataformats::MCTruthContainer<MCCompLabel>* mcLabels, const o2::mft::TrackerConfig* trkParam) + const dataformats::MCTruthContainer<MCCompLabel>* mcLabels, const o2::mft::Tracker* tracker) { event.clear(); GeometryTGeo* geom = GeometryTGeo::Instance(); @@ -72,9 +72,9 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g Float_t rCoord = clsPoint2D.R(); Float_t phiCoord = clsPoint2D.Phi(); o2::math_utils::bringTo02PiGen(phiCoord); - int rBinIndex = trkParam->getRBinIndex(rCoord); - int phiBinIndex = trkParam->getPhiBinIndex(phiCoord); - int binIndex = trkParam->getBinIndex(rBinIndex, phiBinIndex); + int rBinIndex = tracker->getRBinIndex(rCoord); + int phiBinIndex = tracker->getPhiBinIndex(phiCoord); + int binIndex = tracker->getBinIndex(rBinIndex, phiBinIndex); // TODO: Check consistency of sigmaX2 and sigmaY2 event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), phiCoord, rCoord, event.getClustersInLayer(layer).size(), binIndex, sigmaX2, sigmaY2, sensorID); if (mcLabels) { diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index b873182bd866b..da3f2c26f8798 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -39,6 +39,34 @@ void Tracker::setBz(Float_t bz) mTrackFitter->setBz(bz); } +//_________________________________________________________________________________________________ +void Tracker::initConfig(const MFTTrackingParam& trkParam) +{ + /// initialize from MFTTrackingParam (command line configuration parameters) + + mMinTrackPointsLTF = trkParam.MinTrackPointsLTF; + mMinTrackPointsCA = trkParam.MinTrackPointsCA; + mMinTrackStationsLTF = trkParam.MinTrackStationsLTF; + mMinTrackStationsCA = trkParam.MinTrackStationsCA; + mLTFclsRCut = trkParam.LTFclsRCut; + mROADclsRCut = trkParam.ROADclsRCut; + mLTFseed2BinWin = trkParam.LTFseed2BinWin; + mLTFinterBinWin = trkParam.LTFinterBinWin; + + mRBins = trkParam.RBins; + mPhiBins = trkParam.PhiBins; + mRPhiBins = trkParam.RBins * trkParam.PhiBins; + if (mRPhiBins > constants::index_table::MaxRPhiBins) { + LOG(WARN) << "To many RPhiBins for this configuration!"; + mRPhiBins = constants::index_table::MaxRPhiBins; + mRBins = sqrt(constants::index_table::MaxRPhiBins); + mPhiBins = sqrt(constants::index_table::MaxRPhiBins); + LOG(WARN) << "Using instead RBins " << mRBins << " and PhiBins " << mPhiBins; + } + mRBinSize = (constants::index_table::RMax - constants::index_table::RMin) / mRBins; + mPhiBinSize = (constants::index_table::PhiMax - constants::index_table::PhiMin) / mPhiBins; +} + //_________________________________________________________________________________________________ void Tracker::initialize() { @@ -50,15 +78,15 @@ void Tracker::initialize() for (Int_t layer1 = 0; layer1 < (constants::mft::LayersNumber - 1); ++layer1) { - for (Int_t iRBin = 0; iRBin < mTrackerConfig.get()->mRBins; ++iRBin) { + for (Int_t iRBin = 0; iRBin < mRBins; ++iRBin) { - r = (iRBin + 0.5) * mTrackerConfig.get()->mRBinSize + constants::index_table::RMin; + r = (iRBin + 0.5) * mRBinSize + constants::index_table::RMin; - for (Int_t iPhiBin = 0; iPhiBin < mTrackerConfig.get()->mPhiBins; ++iPhiBin) { + for (Int_t iPhiBin = 0; iPhiBin < mPhiBins; ++iPhiBin) { - phi = (iPhiBin + 0.5) * mTrackerConfig.get()->mPhiBinSize + constants::index_table::PhiMin; + phi = (iPhiBin + 0.5) * mPhiBinSize + constants::index_table::PhiMin; - binIndex1 = mTrackerConfig.get()->getBinIndex(iRBin, iPhiBin); + binIndex1 = getBinIndex(iRBin, iPhiBin); x = r * TMath::Cos(phi); y = r * TMath::Sin(phi); @@ -73,30 +101,15 @@ void Tracker::initialize() phi_proj = clsPoint2D.Phi(); o2::math_utils::bringTo02PiGen(phi_proj); - binR_proj = mTrackerConfig.get()->getRBinIndex(r_proj); - binPhi_proj = mTrackerConfig.get()->getPhiBinIndex(phi_proj); + binR_proj = getRBinIndex(r_proj); + binPhi_proj = getPhiBinIndex(phi_proj); int binRS, binPhiS; - int binwRS = mTrackerConfig.get()->mLTFseed2BinWin; - if (abs(dz) < 1.5) { - binwRS = 3; - } else if (abs(dz) < 5.0) { - binwRS = 3; - } else if (abs(dz) < 10.0) { - binwRS = 3; - } else if (abs(dz) < 15.0) { - binwRS = 3; - } else if (abs(dz) < 20.0) { - binwRS = 3; - } else if (abs(dz) < 25.0) { - binwRS = 3; - } else { - binwRS = 3; - } + int binwRS = mLTFseed2BinWin; int binhwRS = binwRS / 2; - int binwPhiS = mTrackerConfig.get()->mLTFseed2BinWin; + int binwPhiS = mLTFseed2BinWin; int binhwPhiS = binwPhiS / 2; for (Int_t iR = 0; iR < binwRS; ++iR) { @@ -111,17 +124,17 @@ void Tracker::initialize() continue; } - binIndex2S = mTrackerConfig.get()->getBinIndex(binRS, binPhiS); + binIndex2S = getBinIndex(binRS, binPhiS); mBinsS[layer1][layer2 - 1][binIndex1].emplace_back(binIndex2S); } } int binR, binPhi; - int binwR = mTrackerConfig.get()->mLTFinterBinWin; + int binwR = mLTFinterBinWin; int binhwR = binwR / 2; - int binwPhi = mTrackerConfig.get()->mLTFinterBinWin; + int binwPhi = mLTFinterBinWin; int binhwPhi = binwPhi / 2; for (Int_t iR = 0; iR < binwR; ++iR) { @@ -136,7 +149,7 @@ void Tracker::initialize() continue; } - binIndex2 = mTrackerConfig.get()->getBinIndex(binR, binPhi); + binIndex2 = getBinIndex(binR, binPhi); mBins[layer1][layer2 - 1][binIndex1].emplace_back(binIndex2); } } @@ -145,6 +158,8 @@ void Tracker::initialize() } // end loop PhiBinIndex } // end loop RBinIndex } // end loop layer1 + + mRoad.initialize(); } //_________________________________________________________________________________________________ @@ -159,7 +174,6 @@ void Tracker::clustersToTracks(ROframe& event, std::ostream& timeBenchmarkOutput //_________________________________________________________________________________________________ void Tracker::findTracks(ROframe& event) { - //computeCells(event); findTracksLTF(event); findTracksCA(event); } @@ -174,7 +188,7 @@ void Tracker::findTracksLTF(ROframe& event) Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; Int_t extClsIndex; - Float_t dR, dRmin, dRcut = mTrackerConfig.get()->mLTFclsRCut; + Float_t dR, dRmin, dRcut = mLTFclsRCut; Bool_t hasDisk[constants::mft::DisksNumber], newPoint, seed; Int_t clsInLayer1, clsInLayer2, clsInLayer; @@ -191,9 +205,9 @@ void Tracker::findTracksLTF(ROframe& event) layer2 = (step == 0) ? (constants::mft::LayersNumber - 1) : (layer2 - 1); step++; - if (layer2 < layer1 + (mTrackerConfig.get()->mMinTrackPointsLTF - 1)) { + if (layer2 < layer1 + (mMinTrackPointsLTF - 1)) { ++layer1; - if (layer1 > (constants::mft::LayersNumber - (mTrackerConfig.get()->mMinTrackPointsLTF - 1))) { + if (layer1 > (constants::mft::LayersNumber - (mMinTrackPointsLTF - 1))) { break; } step = 0; @@ -269,7 +283,7 @@ void Tracker::findTracksLTF(ROframe& event) nPoints++; // keep only tracks fulfilling the minimum length condition - if (nPoints < mTrackerConfig.get()->mMinTrackPointsLTF) { + if (nPoints < mMinTrackPointsLTF) { continue; } for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { @@ -285,7 +299,7 @@ void Tracker::findTracksLTF(ROframe& event) ++nPointDisks; } } - if (nPointDisks < mTrackerConfig.get()->mMinTrackStationsLTF) { + if (nPointDisks < mMinTrackStationsLTF) { continue; } @@ -325,13 +339,13 @@ void Tracker::findTracksCA(ROframe& event) Int_t roadId, nPointDisks; Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; - Float_t dR, dRcut = mTrackerConfig.get()->mROADclsRCut; + Float_t dR, dRcut = mROADclsRCut; Bool_t hasDisk[constants::mft::DisksNumber]; Int_t clsInLayer1, clsInLayer2, clsInLayer; Int_t nPoints; - //TrackElement roadPoints[10 * constants::mft::LayersNumber]; + std::vector<TrackElement> roadPoints; roadId = 0; @@ -359,13 +373,9 @@ void Tracker::findTracksCA(ROframe& event) clsInLayer2 = it2 - event.getClustersInLayer(layer2).begin(); // start a road - //nPoints = 0; roadPoints.clear(); // add the first seed point - //roadPoints[nPoints].layer = layer1; - //roadPoints[nPoints].idInLayer = clsInLayer1; - //nPoints++; roadPoints.emplace_back(layer1, clsInLayer1); for (Int_t layer = (layer1 + 1); layer <= (layer2 - 1); ++layer) { @@ -388,9 +398,6 @@ void Tracker::findTracksCA(ROframe& event) continue; } - //roadPoints[nPoints].layer = layer; - //roadPoints[nPoints].idInLayer = clsInLayer; - //nPoints++; roadPoints.emplace_back(layer, clsInLayer); } // end clusters bin intermediate layer @@ -398,14 +405,11 @@ void Tracker::findTracksCA(ROframe& event) } // end binR // add the second seed point - //roadPoints[nPoints].layer = layer2; - //roadPoints[nPoints].idInLayer = clsInLayer2; - //nPoints++; roadPoints.emplace_back(layer2, clsInLayer2); nPoints = roadPoints.size(); // keep only roads fulfilling the minimum length condition - if (nPoints < mTrackerConfig.get()->mMinTrackPointsCA) { + if (nPoints < mMinTrackPointsCA) { continue; } for (Int_t i = 0; i < (constants::mft::DisksNumber); i++) { @@ -421,21 +425,21 @@ void Tracker::findTracksCA(ROframe& event) ++nPointDisks; } } - if (nPointDisks < mTrackerConfig.get()->mMinTrackStationsCA) { + if (nPointDisks < mMinTrackStationsCA) { continue; } - event.addRoad(); + mRoad.reset(); for (Int_t point = 0; point < nPoints; ++point) { auto layer = roadPoints[point].layer; auto clsInLayer = roadPoints[point].idInLayer; - event.getCurrentRoad().setPoint(layer, clsInLayer); + mRoad.setPoint(layer, clsInLayer); } - event.getCurrentRoad().setRoadId(roadId); + mRoad.setRoadId(roadId); ++roadId; computeCellsInRoad(event); - runForwardInRoad(event); + runForwardInRoad(); runBackwardInRoad(event); } // end clusters in layer2 @@ -454,9 +458,7 @@ void Tracker::computeCellsInRoad(ROframe& event) Int_t cellId; Bool_t noCell; - Road& road = event.getCurrentRoad(); - - road.getLength(layer1min, layer1max); + mRoad.getLength(layer1min, layer1max); --layer1max; for (layer1 = layer1min; layer1 <= layer1max; ++layer1) { @@ -466,26 +468,26 @@ void Tracker::computeCellsInRoad(ROframe& event) layer2min = layer1 + 1; layer2max = std::min(layer1 + (constants::mft::DisksNumber - isDiskFace(layer1)), constants::mft::LayersNumber - 1); - nPtsInLayer1 = road.getNPointsInLayer(layer1); + nPtsInLayer1 = mRoad.getNPointsInLayer(layer1); for (Int_t point1 = 0; point1 < nPtsInLayer1; ++point1) { - clsInLayer1 = road.getClustersIdInLayer(layer1)[point1]; + clsInLayer1 = mRoad.getClustersIdInLayer(layer1)[point1]; layer2 = layer2min; noCell = kTRUE; while (noCell && (layer2 <= layer2max)) { - nPtsInLayer2 = road.getNPointsInLayer(layer2); + nPtsInLayer2 = mRoad.getNPointsInLayer(layer2); /* if (nPtsInLayer2 > 1) { - LOG(INFO) << "BV===== more than one point in road " << road.getRoadId() << " in layer " << layer2 << " : " << nPtsInLayer2 << "\n"; + LOG(INFO) << "BV===== more than one point in road " << mRoad.getRoadId() << " in layer " << layer2 << " : " << nPtsInLayer2 << "\n"; } */ for (Int_t point2 = 0; point2 < nPtsInLayer2; ++point2) { - clsInLayer2 = road.getClustersIdInLayer(layer2)[point2]; + clsInLayer2 = mRoad.getClustersIdInLayer(layer2)[point2]; noCell = kFALSE; // create a cell @@ -499,14 +501,12 @@ void Tracker::computeCellsInRoad(ROframe& event) } //_________________________________________________________________________________________________ -void Tracker::runForwardInRoad(ROframe& event) +void Tracker::runForwardInRoad() { Int_t layerR, layerL, icellR, icellL; Int_t iter = 0; Bool_t levelChange = kTRUE; - Road& road = event.getCurrentRoad(); - while (levelChange) { levelChange = kFALSE; @@ -515,9 +515,9 @@ void Tracker::runForwardInRoad(ROframe& event) // R = right, L = left for (layerL = 0; layerL < (constants::mft::LayersNumber - 2); ++layerL) { - for (icellL = 0; icellL < road.getCellsInLayer(layerL).size(); ++icellL) { + for (icellL = 0; icellL < mRoad.getCellsInLayer(layerL).size(); ++icellL) { - Cell& cellL = road.getCellsInLayer(layerL)[icellL]; + Cell& cellL = mRoad.getCellsInLayer(layerL)[icellL]; layerR = cellL.getSecondLayerId(); @@ -525,16 +525,16 @@ void Tracker::runForwardInRoad(ROframe& event) continue; } - for (icellR = 0; icellR < road.getCellsInLayer(layerR).size(); ++icellR) { + for (icellR = 0; icellR < mRoad.getCellsInLayer(layerR).size(); ++icellR) { - Cell& cellR = road.getCellsInLayer(layerR)[icellR]; + Cell& cellR = mRoad.getCellsInLayer(layerR)[icellR]; if ((cellL.getLevel() == cellR.getLevel()) && getCellsConnect(cellL, cellR)) { if (iter == 1) { - road.addRightNeighbourToCell(layerL, icellL, layerR, icellR); - road.addLeftNeighbourToCell(layerR, icellR, layerL, icellL); + mRoad.addRightNeighbourToCell(layerL, icellL, layerR, icellR); + mRoad.addLeftNeighbourToCell(layerR, icellR, layerL, icellL); } - road.incrementCellLevel(layerR, icellR); + mRoad.incrementCellLevel(layerR, icellR); levelChange = kTRUE; } // end matching cells @@ -542,9 +542,9 @@ void Tracker::runForwardInRoad(ROframe& event) } // end loop cellL } // end loop layer - updateCellStatusInRoad(road); + updateCellStatusInRoad(); - } // end while (step) + } // end while (levelChange) } //_________________________________________________________________________________________________ @@ -561,36 +561,26 @@ void Tracker::runBackwardInRoad(ROframe& event) Int_t nPointDisks; Float_t deviationPrev, deviation; - // start layer Int_t minLayer = 6; Int_t maxLayer = 8; - Road& road = event.getCurrentRoad(); - Int_t nCells; TrackElement trackCells[constants::mft::LayersNumber - 1]; - //std::vector<TrackElement> trackCells; - //trackCells.reserve(constants::mft::LayersNumber - 1); for (Int_t layer = maxLayer; layer >= minLayer; --layer) { - for (cellId = 0; cellId < road.getCellsInLayer(layer).size(); ++cellId) { + for (cellId = 0; cellId < mRoad.getCellsInLayer(layer).size(); ++cellId) { - if (road.isCellUsed(layer, cellId)) { - continue; - } - if (road.getCellLevel(layer, cellId) < (mTrackerConfig.get()->mMinTrackPointsCA - 1)) { + if (mRoad.isCellUsed(layer, cellId) || (mRoad.getCellLevel(layer, cellId) < (mMinTrackPointsCA - 1))) { continue; } // start a TrackCA nCells = 0; - //trackCells.clear(); trackCells[nCells].layer = layer; trackCells[nCells].idInLayer = cellId; nCells++; - //trackCells.emplace_back(layer, cellId); // add cells to the new track addCellToNewTrack = kTRUE; @@ -599,7 +589,7 @@ void Tracker::runBackwardInRoad(ROframe& event) layerRC = trackCells[nCells - 1].layer; cellIdRC = trackCells[nCells - 1].idInLayer; - const Cell& cellRC = road.getCellsInLayer(layerRC)[cellIdRC]; + const Cell& cellRC = mRoad.getCellsInLayer(layerRC)[cellIdRC]; addCellToNewTrack = kFALSE; @@ -612,12 +602,9 @@ void Tracker::runBackwardInRoad(ROframe& event) layerL = leftNeighbour.first; cellIdL = leftNeighbour.second; - const Cell& cellL = road.getCellsInLayer(layerL)[cellIdL]; + const Cell& cellL = mRoad.getCellsInLayer(layerL)[cellIdL]; - if (road.isCellUsed(layerL, cellIdL)) { - continue; - } - if (road.getCellLevel(layerL, cellIdL) != (road.getCellLevel(layerRC, cellIdRC) - 1)) { + if (mRoad.isCellUsed(layerL, cellIdL) || (mRoad.getCellLevel(layerL, cellIdL) != (mRoad.getCellLevel(layerRC, cellIdRC) - 1))) { continue; } @@ -627,16 +614,14 @@ void Tracker::runBackwardInRoad(ROframe& event) deviationPrev = deviation; - if (leftNeighbour != cellRC.getLeftNeighbours().front()) { + if (iLN > 0) { // delete the last added cell nCells--; - //trackCells.pop_back(); } trackCells[nCells].layer = layerL; trackCells[nCells].idInLayer = cellIdL; nCells++; - //trackCells.emplace_back(layerL, cellIdL); addCellToNewTrack = kTRUE; } @@ -651,7 +636,7 @@ void Tracker::runBackwardInRoad(ROframe& event) layerC = trackCells[0].layer; cellIdC = trackCells[0].idInLayer; - const Cell& cellC = event.getCurrentRoad().getCellsInLayer(layerC)[cellIdC]; + const Cell& cellC = mRoad.getCellsInLayer(layerC)[cellIdC]; hasDisk[cellC.getSecondLayerId() / 2] = kTRUE; for (icell = 0; icell < nCells; ++icell) { layerC = trackCells[icell].layer; @@ -666,19 +651,19 @@ void Tracker::runBackwardInRoad(ROframe& event) } } - if (nPointDisks < mTrackerConfig.get()->mMinTrackStationsCA) { + if (nPointDisks < mMinTrackStationsCA) { continue; } // add a new TrackCA - event.addTrackCA(road.getRoadId()); + event.addTrackCA(mRoad.getRoadId()); for (icell = 0; icell < nCells; ++icell) { layerC = trackCells[icell].layer; cellIdC = trackCells[icell].idInLayer; addCellToCurrentTrackCA(layerC, cellIdC, event); - road.setCellUsed(layerC, cellIdC, kTRUE); + mRoad.setCellUsed(layerC, cellIdC, kTRUE); // marked the used clusters - const Cell& cellC = event.getCurrentRoad().getCellsInLayer(layerC)[cellIdC]; + const Cell& cellC = mRoad.getCellsInLayer(layerC)[cellIdC]; event.getClustersInLayer(cellC.getFirstLayerId())[cellC.getFirstClusterIndex()].setUsed(true); event.getClustersInLayer(cellC.getSecondLayerId())[cellC.getSecondClusterIndex()].setUsed(true); } @@ -687,12 +672,14 @@ void Tracker::runBackwardInRoad(ROframe& event) } //_________________________________________________________________________________________________ -void Tracker::updateCellStatusInRoad(Road& road) +void Tracker::updateCellStatusInRoad() { - for (Int_t layer = 0; layer < (constants::mft::LayersNumber - 1); ++layer) { - for (Int_t icell = 0; icell < road.getCellsInLayer(layer).size(); ++icell) { - road.updateCellLevel(layer, icell); - mMaxCellLevel = std::max(mMaxCellLevel, road.getCellLevel(layer, icell)); + Int_t layerMin, layerMax; + mRoad.getLength(layerMin, layerMax); + for (Int_t layer = layerMin; layer < layerMax; ++layer) { + for (Int_t icell = 0; icell < mRoad.getCellsInLayer(layer).size(); ++icell) { + mRoad.updateCellLevel(layer, icell); + mMaxCellLevel = std::max(mMaxCellLevel, mRoad.getCellLevel(layer, icell)); } } } @@ -700,9 +687,7 @@ void Tracker::updateCellStatusInRoad(Road& road) //_________________________________________________________________________________________________ void Tracker::addCellToCurrentRoad(ROframe& event, const Int_t layer1, const Int_t layer2, const Int_t clsInLayer1, const Int_t clsInLayer2, Int_t& cellId) { - Road& road = event.getCurrentRoad(); - - Cell& cell = road.addCellInLayer(layer1, layer2, clsInLayer1, clsInLayer2, cellId); + Cell& cell = mRoad.addCellInLayer(layer1, layer2, clsInLayer1, clsInLayer2, cellId); Cluster& cluster1 = event.getClustersInLayer(layer1)[clsInLayer1]; Cluster& cluster2 = event.getClustersInLayer(layer2)[clsInLayer2]; @@ -723,8 +708,7 @@ void Tracker::addCellToCurrentRoad(ROframe& event, const Int_t layer1, const Int void Tracker::addCellToCurrentTrackCA(const Int_t layer1, const Int_t cellId, ROframe& event) { TrackCA& trackCA = event.getCurrentTrackCA(); - Road& road = event.getCurrentRoad(); - const Cell& cell = road.getCellsInLayer(layer1)[cellId]; + const Cell& cell = mRoad.getCellsInLayer(layer1)[cellId]; const Int_t layer2 = cell.getSecondLayerId(); const Int_t clsInLayer1 = cell.getFirstClusterIndex(); const Int_t clsInLayer2 = cell.getSecondClusterIndex(); diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx index d141bbfca6d50..f1ee9b531a2fa 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx @@ -37,53 +37,6 @@ o2::mft::TrackerConfig::TrackerConfig() /// default constructor } -//__________________________________________________________________________ -o2::mft::TrackerConfig::TrackerConfig(const TrackerConfig& conf) - : mMinTrackPointsLTF(conf.mMinTrackPointsLTF), - mMinTrackPointsCA(conf.mMinTrackPointsCA), - mMinTrackStationsLTF(conf.mMinTrackStationsLTF), - mMinTrackStationsCA(conf.mMinTrackStationsCA), - mLTFclsRCut(conf.mLTFclsRCut), - mROADclsRCut(conf.mROADclsRCut), - mLTFseed2BinWin(conf.mLTFseed2BinWin), - mLTFinterBinWin(conf.mLTFinterBinWin), - mRBins(conf.mRBins), - mPhiBins(conf.mPhiBins), - mRPhiBins(conf.mRPhiBins), - mRBinSize(conf.mRBinSize), - mPhiBinSize(conf.mPhiBinSize), - mInverseRBinSize(conf.mInverseRBinSize), - mInversePhiBinSize(conf.mInversePhiBinSize) -{ - /// copy constructor -} - -//__________________________________________________________________________ -o2::mft::TrackerConfig& o2::mft::TrackerConfig::operator=(const TrackerConfig& conf) -{ - /// assign constructor - - if (this == &conf) { - return *this; - } - - mMinTrackPointsLTF = conf.mMinTrackPointsLTF; - mMinTrackPointsCA = conf.mMinTrackPointsCA; - mMinTrackStationsLTF = conf.mMinTrackStationsLTF; - mMinTrackStationsCA = conf.mMinTrackStationsCA; - mLTFclsRCut = conf.mLTFclsRCut; - mROADclsRCut = conf.mROADclsRCut; - mLTFseed2BinWin = conf.mLTFseed2BinWin; - mLTFinterBinWin = conf.mLTFinterBinWin; - mRBins = conf.mRBins; - mPhiBins = conf.mPhiBins; - mRPhiBins = conf.mRPhiBins; - mRBinSize = conf.mRBinSize; - mPhiBinSize = conf.mPhiBinSize; - mInverseRBinSize = conf.mInverseRBinSize; - mInversePhiBinSize = conf.mInversePhiBinSize; -} - //__________________________________________________________________________ void o2::mft::TrackerConfig::initialize(const MFTTrackingParam& trkParam) { diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 47d7fa837f177..93357ba762838 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -60,14 +60,11 @@ void TrackerDPL::init(InitContext& ic) // tracking configuration parameters auto& mftTrackingParam = MFTTrackingParam::Instance(); - // create the tracker configuration - const auto& trackerConfig = std::make_unique<o2::mft::TrackerConfig>(); - trackerConfig->initialize(mftTrackingParam); // create the tracker: set the B-field, the configuration and initialize mTracker = std::make_unique<o2::mft::Tracker>(mUseMC); double centerMFT[3] = {0, 0, -61.4}; // Field at center of MFT mTracker->setBz(field->getBz(centerMFT)); - mTracker->setConfig(const_cast<TrackerConfig&>(*trackerConfig.get())); + mTracker->initConfig(mftTrackingParam); mTracker->initialize(); } else { throw std::runtime_error(o2::utils::concat_string("Cannot retrieve GRP from the ", filename)); @@ -140,7 +137,7 @@ void TrackerDPL::run(ProcessingContext& pc) gsl::span<const unsigned char>::iterator pattIt = patterns.begin(); if (continuous) { for (auto& rof : rofs) { - int nclUsed = ioutils::loadROFrameData(rof, event, compClusters, pattIt, mDict, labels, (mTracker.get())->getConfig()); + int nclUsed = ioutils::loadROFrameData(rof, event, compClusters, pattIt, mDict, labels, mTracker.get()); if (nclUsed) { event.setROFrameId(roFrame); event.initialize(); From d73308a1b7f62199423a64d0cdfabeb7ca3f8472 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 7 Dec 2020 13:47:34 +0100 Subject: [PATCH 1568/1751] Update sim_challenge.sh re-enable MFT reco --- prodtests/sim_challenge.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/sim_challenge.sh b/prodtests/sim_challenge.sh index f7d268c1b252c..76656450d122e 100755 --- a/prodtests/sim_challenge.sh +++ b/prodtests/sim_challenge.sh @@ -124,7 +124,7 @@ if [ "$doreco" == "1" ]; then echo "Running MFT reco flow" #needs MFT digitized data - # taskwrapper mftreco.log o2-mft-reco-workflow $gloOpt + taskwrapper mftreco.log o2-mft-reco-workflow $gloOpt echo "Return status of mftreco: $?" echo "Running FT0 reco flow" From cba1c8242ec3db9690d04258bd1ee797e02c6ad3 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 3 Dec 2020 15:29:22 +0100 Subject: [PATCH 1569/1751] Remove Pythia8 system and shift all indices by -1 --- Generators/src/GeneratorPythia8.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 344fdb8461fe1..2cc8f44ff156d 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -167,7 +167,7 @@ Bool_t /* loop over particles */ // auto weight = mPythia.info.weight(); // TBD: use weights auto nParticles = event.size(); - for (Int_t iparticle = 0; iparticle < nParticles; iparticle++) { // first particle is system + for (Int_t iparticle = 1; iparticle < nParticles; iparticle++) { // first particle is system auto particle = event[iparticle]; auto pdg = particle.id(); auto st = particle.statusHepMC(); @@ -179,10 +179,10 @@ Bool_t auto vy = particle.yProd(); auto vz = particle.zProd(); auto vt = particle.tProd(); - auto m1 = particle.mother1(); - auto m2 = particle.mother2(); - auto d1 = particle.daughter1(); - auto d2 = particle.daughter2(); + auto m1 = particle.mother1() - 1; + auto m2 = particle.mother2() - 1; + auto d1 = particle.daughter1() - 1; + auto d2 = particle.daughter2() - 1; mParticles.push_back(TParticle(pdg, st, m1, m2, d1, d2, px, py, pz, et, vx, vy, vz, vt)); } From 7acefbbeeba3a6fbe1bc435002daaf94dcb0e027 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 3 Dec 2020 18:36:17 +0100 Subject: [PATCH 1570/1751] Propagate first and second daughters to the Stack --- .../simulation/include/SimulationDataFormat/Stack.h | 4 ++++ DataFormats/simulation/src/Stack.cxx | 11 +++++++++-- Generators/src/PrimaryGenerator.cxx | 12 +++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/Stack.h b/DataFormats/simulation/include/SimulationDataFormat/Stack.h index 585119aa7c1f1..4498f7c3d949e 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/Stack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/Stack.h @@ -88,6 +88,10 @@ class Stack : public FairGenericStack Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz, TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondParentId) override; + void PushTrack(Int_t toBeDone, Int_t parentID, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e, + Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz, + TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondParentId, Int_t daughter1Id, Int_t daughter2Id); + // similar function taking a particle void PushTrack(Int_t toBeDone, TParticle&); diff --git a/DataFormats/simulation/src/Stack.cxx b/DataFormats/simulation/src/Stack.cxx index eb609059725fc..b65eb23f5f972 100644 --- a/DataFormats/simulation/src/Stack.cxx +++ b/DataFormats/simulation/src/Stack.cxx @@ -182,6 +182,13 @@ void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e, Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz, TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondparentId) +{ + PushTrack(toBeDone, parentId, pdgCode, px, py, pz, e, vx, vy, vz, time, polx, poly, polz, proc, ntr, weight, is, secondparentId, -1, -1); +} + +void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e, + Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz, + TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondparentId, Int_t daughter1Id, Int_t daughter2Id) { // printf("Pushing %s toBeDone %5d parentId %5d pdgCode %5d is %5d entries %5d \n", // proc == kPPrimary ? "Primary: " : "Secondary: ", @@ -200,8 +207,8 @@ void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px Int_t trackId = mNumberOfEntriesInParticles; // Set track variable ntr = trackId; - Int_t daughter1Id = -1; - Int_t daughter2Id = -1; + // Int_t daughter1Id = -1; + // Int_t daughter2Id = -1; Int_t iStatus = (proc == kPPrimary) ? is : trackId; TParticle p(pdgCode, iStatus, parentId, secondparentId, daughter1Id, daughter2Id, px, py, pz, e, vx, vy, vz, time); p.SetPolarisation(polx, poly, polz); diff --git a/Generators/src/PrimaryGenerator.cxx b/Generators/src/PrimaryGenerator.cxx index 2e76ac6d9a373..205a65355d51d 100644 --- a/Generators/src/PrimaryGenerator.cxx +++ b/Generators/src/PrimaryGenerator.cxx @@ -14,6 +14,7 @@ #include "Generators/Generator.h" #include "Generators/InteractionDiamondParam.h" #include "SimulationDataFormat/MCEventHeader.h" +#include "SimulationDataFormat/Stack.h" #include "FairLogger.h" #include "FairGenericStack.h" @@ -186,9 +187,14 @@ void PrimaryGenerator::AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t } /** add track to stack **/ - fStack->PushTrack(doTracking, mother1, pdgid, px, py, pz, - e, vx, vy, vz, tof, polx, poly, polz, proc, ntr, - weight, status, mother2); + auto stack = dynamic_cast<o2::data::Stack*>(fStack); + if (!stack) { + LOG(FATAL) << "Stack must be an o2::data:Stack"; + return; // must be the o2 stack + } + stack->PushTrack(doTracking, mother1, pdgid, px, py, pz, + e, vx, vy, vz, tof, polx, poly, polz, proc, ntr, + weight, status, mother2, daughter1, daughter2); fNTracks++; } From c7404dc3292b12338eb061f1dae5b7b02dc3b733 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 3 Dec 2020 18:41:43 +0100 Subject: [PATCH 1571/1751] Allow access all primary particles for selective transport --- .../simulation/include/SimulationDataFormat/Stack.h | 4 ++-- DataFormats/simulation/src/Stack.cxx | 10 +++++----- .../{Selective_Tranport => Selective_Transport}/run.sh | 0 .../sim.ini | 0 .../transportPDG.macro | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) rename run/SimExamples/{Selective_Tranport => Selective_Transport}/run.sh (100%) rename run/SimExamples/{Selective_Tranport => Selective_Transport}/sim.ini (100%) rename run/SimExamples/{Selective_Tranport => Selective_Transport}/transportPDG.macro (54%) diff --git a/DataFormats/simulation/include/SimulationDataFormat/Stack.h b/DataFormats/simulation/include/SimulationDataFormat/Stack.h index 4498f7c3d949e..ff55904d9342c 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/Stack.h +++ b/DataFormats/simulation/include/SimulationDataFormat/Stack.h @@ -225,7 +225,7 @@ class Stack : public FairGenericStack /// update values in the current event header void updateEventStats(); - typedef std::function<bool(const TParticle& p)> TransportFcn; + typedef std::function<bool(const TParticle& p, const std::vector<TParticle>& particles)> TransportFcn; private: /// STL stack (FILO) used to handle the TParticles for tracking @@ -283,7 +283,7 @@ class Stack : public FairGenericStack bool mIsExternalMode = false; // is stack an external factory or directly used inside simulation? - TransportFcn mTransportPrimary = [](const TParticle& p) { return false; }; //! a function to inhibit the tracking of a particle + TransportFcn mTransportPrimary = [](const TParticle& p, const std::vector<TParticle>& particles) { return false; }; //! a function to inhibit the tracking of a particle // storage for track references std::vector<o2::TrackReference>* mTrackRefs = nullptr; //! diff --git a/DataFormats/simulation/src/Stack.cxx b/DataFormats/simulation/src/Stack.cxx index b65eb23f5f972..712de76e400f7 100644 --- a/DataFormats/simulation/src/Stack.cxx +++ b/DataFormats/simulation/src/Stack.cxx @@ -85,15 +85,15 @@ Stack::Stack(Int_t size) LOG(INFO) << param; TransportFcn transportPrimary; if (param.transportPrimary.compare("none") == 0) { - transportPrimary = [](const TParticle& p) { + transportPrimary = [](const TParticle& p, const std::vector<TParticle>& particles) { return false; }; } else if (param.transportPrimary.compare("all") == 0) { - transportPrimary = [](const TParticle& p) { + transportPrimary = [](const TParticle& p, const std::vector<TParticle>& particles) { return true; }; } else if (param.transportPrimary.compare("barrel") == 0) { - transportPrimary = [](const TParticle& p) { + transportPrimary = [](const TParticle& p, const std::vector<TParticle>& particles) { return (std::fabs(p.Eta()) < 2.0); }; } else if (param.transportPrimary.compare("external") == 0) { @@ -108,7 +108,7 @@ Stack::Stack(Int_t size) } if (param.transportPrimaryInvert) { - mTransportPrimary = [transportPrimary](const TParticle& p) { return !transportPrimary; }; + mTransportPrimary = [transportPrimary](const TParticle& p, const std::vector<TParticle>& particles) { return !transportPrimary; }; } else { mTransportPrimary = transportPrimary; } @@ -230,7 +230,7 @@ void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px p.SetBit(ParticleStatus::kKeep); p.SetBit(ParticleStatus::kPrimary); if (toBeDone == 1) { - if (mTransportPrimary(p)) { + if (mTransportPrimary(p, mPrimaryParticles)) { p.SetBit(ParticleStatus::kToBeDone, 1); mNumberOfPrimariesforTracking++; } else { diff --git a/run/SimExamples/Selective_Tranport/run.sh b/run/SimExamples/Selective_Transport/run.sh similarity index 100% rename from run/SimExamples/Selective_Tranport/run.sh rename to run/SimExamples/Selective_Transport/run.sh diff --git a/run/SimExamples/Selective_Tranport/sim.ini b/run/SimExamples/Selective_Transport/sim.ini similarity index 100% rename from run/SimExamples/Selective_Tranport/sim.ini rename to run/SimExamples/Selective_Transport/sim.ini diff --git a/run/SimExamples/Selective_Tranport/transportPDG.macro b/run/SimExamples/Selective_Transport/transportPDG.macro similarity index 54% rename from run/SimExamples/Selective_Tranport/transportPDG.macro rename to run/SimExamples/Selective_Transport/transportPDG.macro index 7e3fa34ceffa1..942d3db4fe43f 100644 --- a/run/SimExamples/Selective_Tranport/transportPDG.macro +++ b/run/SimExamples/Selective_Transport/transportPDG.macro @@ -1,7 +1,7 @@ o2::data::Stack::TransportFcn transportPDG(int pdg = 321) { - return [pdg](const TParticle& p) -> bool { + return [pdg](const TParticle& p, const std::vector<TParticle>& particles) -> bool { return p.GetPdgCode() == pdg; }; } From 8aeb68e3fa4b52923c726df70a7c4d8ebe56bdf5 Mon Sep 17 00:00:00 2001 From: sgorbuno <sergey.gorbunov@fias.uni-frankfurt.de> Date: Wed, 2 Dec 2020 13:57:56 +0000 Subject: [PATCH 1572/1751] bugfix in ND splines --- GPU/TPCFastTransformation/SplineSpec.h | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/GPU/TPCFastTransformation/SplineSpec.h b/GPU/TPCFastTransformation/SplineSpec.h index 2a3fc9f90df4a..00f236940188b 100644 --- a/GPU/TPCFastTransformation/SplineSpec.h +++ b/GPU/TPCFastTransformation/SplineSpec.h @@ -327,31 +327,28 @@ class SplineSpec<DataT, XdimT, YdimT, 0> : public SplineContainer<DataT> DataT S1[maxInterpolations]; DataT D1[maxInterpolations]; - int nrofInterpolations = (1 << (2 * nXdim - 2)) * nYdim; - int nrofKnots = 1 << (nXdim); + int nInterpolations = (1 << (2 * nXdim - 2)) * nYdim; + int nKnots = 1 << (nXdim); for (int d = 0; d < nXdim; d++) { //for every dimension DataT* pointer[4] = {S0, D0, S1, D1}; // pointers for interpolation arrays S0, D0, S1, D1 point to Arraystart - for (int i = 0; i < nrofKnots; i++) { //for every knot - for (int j = 0; j < nrofKnots; j++) { // for every parametertype + for (int i = 0; i < nKnots; i++) { //for every knot + for (int j = 0; j < nKnots; j++) { // for every parametertype int pointernr = 2 * (i % 2) + (j % 2); //to which array should it be delivered for (int k = 0; k < nYdim; k++) { - pointer[pointernr][0] = iParameters[(i * nrofKnots + j) * nYdim + k]; + pointer[pointernr][0] = iParameters[(i * nKnots + j) * nYdim + k]; pointer[pointernr]++; } } // end for j (every parametertype) } // end for i (every knot) const typename Spline1D<DataT>::Knot& knotL = mGrid[d].getKnot(indices[d]); - int Ydim = nrofInterpolations; DataT coordinate = u[d]; - - typedef Spline1DSpec<DataT, 0, YdimT> TGridX; + typedef Spline1DSpec<DataT, 0, 0> TGridX; const TGridX& gridX = *((const TGridX*)&(mGrid[d])); - gridX.interpolateU(Ydim, knotL, S0, D0, S1, D1, coordinate, iParameters); - - nrofInterpolations = nrofInterpolations / 4; - nrofKnots = nrofKnots / 2; + gridX.interpolateU(nInterpolations, knotL, S0, D0, S1, D1, coordinate, iParameters); + nInterpolations /= 4; + nKnots /= 2; } //end d (every dimension) for (int i = 0; i < nYdim; i++) { From 3880176f166e48fa852dc46a8493f645fbe72d19 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 7 Dec 2020 23:48:17 +0100 Subject: [PATCH 1573/1751] DPL: attempt at supporting cloned processors This introduces a --clone <template>:<new-name>[, ...] option which allows duplicating and renaming a given dataprocessor <template>. There is still a few caveats: * It cannot have outputs. * The dpl-config.json needs to mention the <new-name> in order to configure it, options of <template> will not be used. * The workflow.json must include an entry for <new-name>. --- .../include/Framework/runDataProcessing.h | 5 +++ Framework/Core/src/WorkflowHelpers.cxx | 1 + Framework/Core/src/runDataProcessing.cxx | 41 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index b9d347d3063e8..88eda05d03d48 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -102,6 +102,9 @@ class ConfigContext; /// Helper used to customize a workflow pipelining options void overridePipeline(o2::framework::ConfigContext& ctx, std::vector<o2::framework::DataProcessorSpec>& workflow); +/// Helper used to customize a workflow via a template data processor +void overrideCloning(o2::framework::ConfigContext& ctx, std::vector<o2::framework::DataProcessorSpec>& workflow); + // This comes from the framework itself. This way we avoid code duplication. int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& specs, std::vector<o2::framework::ChannelConfigurationPolicy> const& channelPolicies, @@ -127,6 +130,7 @@ int main(int argc, char** argv) UserCustomizationsHelper::userDefinedCustomization(workflowOptions, 0); workflowOptions.push_back(ConfigParamSpec{"readers", VariantType::Int64, 1ll, {"number of parallel readers to use"}}); workflowOptions.push_back(ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}); + workflowOptions.push_back(ConfigParamSpec{"clone", VariantType::String, "", {"clone processors from a template"}}); // options for AOD rate limiting workflowOptions.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::Int64, 0LL, {"Rate limit AOD processing based on memory"}}); @@ -173,6 +177,7 @@ int main(int argc, char** argv) ConfigContext configContext(workflowOptionsRegistry, argc, argv); o2::framework::WorkflowSpec specs = defineDataProcessing(configContext); overridePipeline(configContext, specs); + overrideCloning(configContext, specs); for (auto& spec : specs) { UserCustomizationsHelper::userDefinedCustomization(spec.requiredServices, 0); } diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index fce333dd5171d..8e74c7262d2d2 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -511,6 +511,7 @@ void WorkflowHelpers::constructGraph(const WorkflowSpec& workflow, std::vector<LogicalForwardInfo>& forwardedInputsInfo) { assert(!workflow.empty()); + // This is the state. Oif is the iterator I use for the searches. std::list<LogicalOutputInfo> availableOutputsInfo; auto const& constOutputs = outputs; // const version of the outputs diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 839d7e6648999..da67950c671fd 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1383,6 +1383,47 @@ bool isOutputToPipe() return ((s.st_mode & S_IFIFO) != 0); } +void overrideCloning(ConfigContext& ctx, WorkflowSpec& workflow) +{ + struct CloningSpec { + std::string templateMatcher; + std::string cloneName; + }; + auto s = ctx.options().get<std::string>("clone"); + std::vector<CloningSpec> specs; + std::string delimiter = ","; + + size_t pos = 0; + while (s.empty() == false) { + auto newPos = s.find(delimiter); + auto token = s.substr(0, newPos); + auto split = token.find(":"); + if (split == std::string::npos) { + throw std::runtime_error("bad clone definition. Syntax <template-processor>:<clone-name>"); + } + auto key = token.substr(0, split); + token.erase(0, split + 1); + auto value = token; + specs.push_back({key, value}); + s.erase(0, newPos + (newPos == std::string::npos ? 0 : 1)); + } + if (s.empty() == false && specs.empty() == true) { + throw std::runtime_error("bad pipeline definition. Syntax <processor>:<pipeline>"); + } + + std::vector<DataProcessorSpec> extraSpecs; + for (auto& spec : specs) { + for (auto& processor : workflow) { + if (processor.name == spec.templateMatcher) { + auto clone = processor; + clone.name = spec.cloneName; + extraSpecs.push_back(clone); + } + } + } + workflow.insert(workflow.end(), extraSpecs.begin(), extraSpecs.end()); +} + void overridePipeline(ConfigContext& ctx, WorkflowSpec& workflow) { struct PipelineSpec { From 36fb134608d35c4358ff5080d78bb84708009a10 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <maximiliano.puccio@cern.ch> Date: Mon, 7 Dec 2020 15:23:47 +0100 Subject: [PATCH 1574/1751] Deltaphi cuts above pi do not make sense --- macro/run_trac_alice3.C | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/macro/run_trac_alice3.C b/macro/run_trac_alice3.C index c98e0950c3d2b..1e2df0a2d3f28 100644 --- a/macro/run_trac_alice3.C +++ b/macro/run_trac_alice3.C @@ -78,7 +78,7 @@ void run_trac_alice3(const string hitsFileName = "o2sim_HitsIT4.root") trackParams[0].NLayers = 10; trackParams[0].MinTrackLength = 10; - std::vector<float> LayerRadii = {1.8f, 2.4f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}; + std::vector<float> LayerRadii = {1.8f, 2.8f, 3.8f, 8.0f, 20.0f, 25.0f, 40.0f, 55.f, 80.0f, 100.f}; std::vector<float> LayerZ(10); for (int i{0}; i < 10; ++i) LayerZ[i] = getDetLengthFromEta(1.44, LayerRadii[i]) + 1.; @@ -110,8 +110,8 @@ void run_trac_alice3(const string hitsFileName = "o2sim_HitsIT4.root") memParams[i] = memParams[i - 1]; trackParams[i] = trackParams[i - 1]; // trackParams[i].MinTrackLength -= 2; - trackParams[i].TrackletMaxDeltaPhi *= 3; - trackParams[i].CellMaxDeltaPhi *= 3; + trackParams[i].TrackletMaxDeltaPhi = trackParams[i].TrackletMaxDeltaPhi * 3 > TMath::Pi() ? TMath::Pi() : trackParams[i].TrackletMaxDeltaPhi * 3; + trackParams[i].CellMaxDeltaPhi = trackParams[i].CellMaxDeltaPhi * 3 > TMath::Pi() ? TMath::Pi() : trackParams[i].CellMaxDeltaPhi * 3; trackParams[i].CellMaxDeltaTanLambda *= 3; for (auto& val : trackParams[i].TrackletMaxDeltaZ) val *= 3; From 26bc350faa31a1f3a2124a5970a2dd1415fc3f6d Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Mon, 30 Nov 2020 15:19:08 +0100 Subject: [PATCH 1575/1751] [MCH] added error handler in raw decoder The raw decoder handlers are now grouped in a structure, so that new handlers can be easily added in future if needed. A backward-compatible version of the createPageDecoder has been introduced, to be removed once all code using the O2 decoder will be adapted to use the RawDecoderHandlers structure. Currently handlers for SAMPA data packets and for decoder errors are implemented in the code. The DataDecoder algorithm is also moved into a separate source file, for better readability and easier unit testing. Some initial unit tests for the error handling in the User Logic decoder have been added. --- .../include/MCHRawCommon/SampaCluster.h | 3 + .../MUON/MCH/Raw/Common/src/SampaCluster.cxx | 18 +- Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt | 5 +- .../include/MCHRawDecoder/DataDecoder.h | 82 +++++ ...ChannelHandler.h => DecodedDataHandlers.h} | 16 +- .../include/MCHRawDecoder/ErrorCodes.h | 39 +++ .../include/MCHRawDecoder/PageDecoder.h | 18 +- .../MCH/Raw/Decoder/src/BareElinkDecoder.h | 32 +- .../MUON/MCH/Raw/Decoder/src/BareGBTDecoder.h | 13 +- .../MUON/MCH/Raw/Decoder/src/DataDecoder.cxx | 282 ++++++++++++++++++ .../MUON/MCH/Raw/Decoder/src/PageDecoder.cxx | 49 ++- .../MUON/MCH/Raw/Decoder/src/PayloadDecoder.h | 14 +- .../Raw/Decoder/src/UserLogicElinkDecoder.h | 47 ++- .../Decoder/src/UserLogicEndpointDecoder.h | 39 ++- .../Raw/Decoder/src/testBareElinkDecoder.cxx | 10 +- .../src/testUserLogicEndpointDecoder.cxx | 131 +++++++- Detectors/MUON/MCH/Raw/Tools/rawdump.cxx | 4 +- .../MUON/MCH/Raw/test/testClosureCoDec.cxx | 4 +- .../MUON/MCH/Workflow/src/DataDecoderSpec.cxx | 237 ++------------- 19 files changed, 753 insertions(+), 290 deletions(-) create mode 100644 Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DataDecoder.h rename Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/{SampaChannelHandler.h => DecodedDataHandlers.h} (66%) create mode 100644 Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/ErrorCodes.h create mode 100644 Detectors/MUON/MCH/Raw/Decoder/src/DataDecoder.cxx diff --git a/Detectors/MUON/MCH/Raw/Common/include/MCHRawCommon/SampaCluster.h b/Detectors/MUON/MCH/Raw/Common/include/MCHRawCommon/SampaCluster.h index 28f14f04332c0..b5a4f659d51d8 100644 --- a/Detectors/MUON/MCH/Raw/Common/include/MCHRawCommon/SampaCluster.h +++ b/Detectors/MUON/MCH/Raw/Common/include/MCHRawCommon/SampaCluster.h @@ -67,6 +67,9 @@ struct SampaCluster { /// needed to store this cluster uint16_t nof10BitWords() const; + /// sum returns the total charge in the cluster + uint32_t sum() const; + uint10_t sampaTime; //< 10 bits for a local time stamp uint20_t bunchCrossing; //< 20 bits for bunch crossing counter uint20_t chargeSum; //< 20 bits for a cluster sum diff --git a/Detectors/MUON/MCH/Raw/Common/src/SampaCluster.cxx b/Detectors/MUON/MCH/Raw/Common/src/SampaCluster.cxx index 256a7afc1e863..3ef6cc8e36745 100644 --- a/Detectors/MUON/MCH/Raw/Common/src/SampaCluster.cxx +++ b/Detectors/MUON/MCH/Raw/Common/src/SampaCluster.cxx @@ -65,13 +65,25 @@ uint16_t SampaCluster::nof10BitWords() const if (isClusterSum()) { n10 += 2; // 20 bits (chargesum) } else { - for (auto s : samples) { - ++n10; // 10 bits for each sample - } + n10 += samples.size(); } return n10; } +uint32_t SampaCluster::sum() const +{ + uint32_t tot(0); + if (isClusterSum()) { + tot = chargeSum; + } else { + for (const auto& s : samples) { + tot += s; + } + } + + return tot; +} + std::ostream& operator<<(std::ostream& os, const SampaCluster& sc) { os << fmt::format("ts {:4d} ", sc.sampaTime); diff --git a/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt b/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt index 1c56998c73e51..4241929ec6314 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt +++ b/Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt @@ -9,8 +9,9 @@ # submit itself to any jurisdiction. o2_add_library(MCHRawDecoder - SOURCES src/PageDecoder.cxx src/RDHManip.cxx src/OrbitInfo.cxx - PUBLIC_LINK_LIBRARIES O2::MCHRawCommon O2::MCHRawElecMap O2::DetectorsRaw + SOURCES src/PageDecoder.cxx src/DataDecoder.cxx src/RDHManip.cxx src/OrbitInfo.cxx + PUBLIC_LINK_LIBRARIES O2::MCHRawCommon O2::MCHBase O2::MCHMappingInterface O2::MCHMappingImpl4 O2::MCHRawElecMap + O2::DetectorsRaw PRIVATE_LINK_LIBRARIES O2::MCHRawImplHelpers) if(BUILD_TESTING) diff --git a/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DataDecoder.h b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DataDecoder.h new file mode 100644 index 0000000000000..f28440bcedf77 --- /dev/null +++ b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DataDecoder.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 DataDecoder.h +/// \author Andrea Ferrero +/// +/// \brief Definition of the decoder for the MCH data +/// + +#include <gsl/span> +#include <unordered_set> + +#include "Headers/RDHAny.h" +#include "MCHBase/Digit.h" +#include "MCHRawDecoder/OrbitInfo.h" +#include "MCHRawDecoder/PageDecoder.h" + +namespace o2 +{ +namespace mch +{ +namespace raw +{ + +using RdhHandler = std::function<void(o2::header::RDHAny*)>; + +// custom hash for OrbitInfo objects +struct OrbitInfoHash { + std::size_t operator()(const OrbitInfo& info) const noexcept + { + return std::hash<uint64_t>{}(info.get()); + } +}; + +//_________________________________________________________________ +// +// Data decoder +//_________________________________________________________________ +class DataDecoder +{ + public: + DataDecoder(SampaChannelHandler channelHandler, RdhHandler rdhHandler, std::string mapCRUfile, std::string mapFECfile, bool ds2manu, bool verbose); + + void reset(); + void decodeBuffer(gsl::span<const std::byte> page); + + const std::vector<o2::mch::Digit>& getOutputDigits() const { return mOutputDigits; } + const std::unordered_set<OrbitInfo, OrbitInfoHash>& getOrbits() const { return mOrbits; } + + private: + void initElec2DetMapper(std::string filename); + void initFee2SolarMapper(std::string filename); + void init(); + + Elec2DetMapper mElec2Det{nullptr}; + FeeLink2SolarMapper mFee2Solar{nullptr}; + o2::mch::raw::PageDecoder mDecoder; + size_t mNrdhs{0}; + std::vector<o2::mch::Digit> mOutputDigits; + std::unordered_set<OrbitInfo, OrbitInfoHash> mOrbits; ///< list of orbits in the processed buffer + + SampaChannelHandler mChannelHandler; + std::function<void(o2::header::RDHAny*)> mRdhHandler; + + std::string mMapCRUfile; + std::string mMapFECfile; + + bool mDebug{false}; + bool mDs2manu{false}; +}; + +} // namespace raw +} // namespace mch +} // end namespace o2 diff --git a/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/SampaChannelHandler.h b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DecodedDataHandlers.h similarity index 66% rename from Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/SampaChannelHandler.h rename to Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DecodedDataHandlers.h index 58470c4bc772c..d286e2098ccb1 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/SampaChannelHandler.h +++ b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DecodedDataHandlers.h @@ -8,8 +8,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_MCH_RAW_SAMPA_CHANNEL_HANDLER_H -#define O2_MCH_RAW_SAMPA_CHANNEL_HANDLER_H +#ifndef O2_MCH_DECODED_DATA_HANDLES_H +#define O2_MCH_DECODED_DATA_HANDLES_H #include <functional> @@ -27,6 +27,18 @@ namespace raw using SampaChannelHandler = std::function<void(DsElecId dsId, uint8_t channel, SampaCluster)>; + +/// A SampaChannSampaHeartBeatHandler is a function that takes a chip index and +/// a bunch crossing counter value found in a HeartBeat packet +using SampaErrorHandler = std::function<void(DsElecId dsId, + int8_t chip, + uint32_t error)>; + +struct DecodedDataHandlers { + SampaChannelHandler sampaChannelHandler; + SampaErrorHandler sampaErrorHandler; +}; + } // namespace raw } // namespace mch } // namespace o2 diff --git a/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/ErrorCodes.h b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/ErrorCodes.h new file mode 100644 index 0000000000000..60da703c981f3 --- /dev/null +++ b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/ErrorCodes.h @@ -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. + +#ifndef O2_MCH_RAW_ERROR_CODES_H +#define O2_MCH_RAW_ERROR_CODES_H + +namespace o2 +{ +namespace mch +{ +namespace raw +{ + +enum ErrorCodes { + ErrorParity = 1, // 1 + ErrorHammingCorrectable = 1 << 1, // 2 + ErrorHammingUncorrectable = 1 << 2, // 4 + ErrorBadClusterSize = 1 << 3, // 8 + ErrorBadPacketType = 1 << 4, // 16 + ErrorBadHeartBeatPacket = 1 << 5, // 32 + ErrorBadIncompleteWord = 1 << 6, // 64 + ErrorTruncatedData = 1 << 7, // 128 + ErrorBadELinkID = 1 << 8, // 256 + ErrorBadLinkID = 1 << 9, // 512 + ErrorUnknownLinkID = 1 << 10 // 1024 +}; + +} // namespace raw +} // namespace mch +} // namespace o2 + +#endif diff --git a/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/PageDecoder.h b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/PageDecoder.h index 42abc29c69987..039acaeab6f9e 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/PageDecoder.h +++ b/Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/PageDecoder.h @@ -14,7 +14,7 @@ #include <functional> #include <gsl/span> #include <map> -#include "MCHRawDecoder/SampaChannelHandler.h" +#include "MCHRawDecoder/DecodedDataHandlers.h" #include "MCHRawElecMap/Mapper.h" namespace o2::mch::raw @@ -32,11 +32,11 @@ using RawBuffer = gsl::span<const std::byte>; // // @param rdhBuffer a raw memory buffer containing (at least) one RDH // which information is used to decide which PageDecoder implementation to choose -// @param channelHandler (optional) a callable object that will be called for each -// decoded SampaCluster +// @param decodedDataHandlers a structure with various callable objects (optional) that +/// will be called for each decoded Sampa packet and in case of decoding errors // PageDecoder createPageDecoder(RawBuffer rdhBuffer, - SampaChannelHandler channelHandler); + DecodedDataHandlers decodedDataHandlers); // Same as above but only to be used for special cases, e.g. when // trying to decode test beam data with an electronic mapping that @@ -46,9 +46,17 @@ PageDecoder createPageDecoder(RawBuffer rdhBuffer, // object into a solarId. // PageDecoder createPageDecoder(RawBuffer rdhBuffer, - SampaChannelHandler channelHandler, + DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar); +// Alternative versions of the same functions, taking a SampaChannelHandler as parameter. +[[deprecated("Use createPageDecoder(RawBuffer,DecodedDataHandlers) instead.")]] PageDecoder createPageDecoder(RawBuffer rdhBuffer, + SampaChannelHandler channelHandler); + +[[deprecated("Use createPageDecoder(RawBuffer,DecodedDataHandlers,fee2solar) instead.")]] PageDecoder createPageDecoder(RawBuffer rdhBuffer, + SampaChannelHandler channelHandler, + FeeLink2SolarMapper fee2solar); + // A PageParser loops over the given buffer and apply the given page decoder // to each page. using PageParser = std::function<void(RawBuffer buffer, PageDecoder pageDecoder)>; diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/BareElinkDecoder.h b/Detectors/MUON/MCH/Raw/Decoder/src/BareElinkDecoder.h index 04a455ae9b3ca..84bf6f0b00b92 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/BareElinkDecoder.h +++ b/Detectors/MUON/MCH/Raw/Decoder/src/BareElinkDecoder.h @@ -14,7 +14,7 @@ #include "Assertions.h" #include "MCHRawCommon/DataFormats.h" #include "MCHRawCommon/SampaHeader.h" -#include "MCHRawDecoder/SampaChannelHandler.h" +#include "MCHRawDecoder/DecodedDataHandlers.h" #include <bitset> #include <fmt/format.h> #include <fmt/printf.h> @@ -33,7 +33,7 @@ namespace o2::mch::raw /// /// Bits coming from parts of the GBT words are added to the Elink using the /// append() method and each time a SampaCluster is decoded, -/// it is passed to the SampaChannelHandler for further processing (or none). +/// it is passed to the DecodedDataHandlers for further processing (or none). /// /// \nosubgrouping /// @@ -44,9 +44,9 @@ class BareElinkDecoder /// Constructor. /// \param dsId the (electronic) id of the dual sampa this elink /// is connected to - /// \param sampaChannelHandler a callable that is passed - /// each SampaCluster that will be decoded - BareElinkDecoder(DsElecId dsId, SampaChannelHandler sampaChannelHandler); + /// \param decodedDataHandlers a structure with various callable that + /// handle the Sampa packets and decoding errors + BareElinkDecoder(DsElecId dsId, DecodedDataHandlers decodedDataHandlers); /** @name Main interface */ @@ -104,7 +104,7 @@ class BareElinkDecoder private: DsElecId mDsId; - SampaChannelHandler mSampaChannelHandler; //< The callable that will deal with the SampaCluster objects we decode + DecodedDataHandlers mDecodedDataHandlers; //< The structure with the callables that deal with the Sampa packets and the decoding errors SampaHeader mSampaHeader; //< Current SampaHeader uint64_t mBitBuffer; //< Our internal bit stream buffer /** @name internal global counters @@ -154,9 +154,9 @@ std::string bitBufferString(const std::bitset<50>& bs, int imax) template <typename CHARGESUM> BareElinkDecoder<CHARGESUM>::BareElinkDecoder(DsElecId dsId, - SampaChannelHandler sampaChannelHandler) + DecodedDataHandlers decodedDataHandlers) : mDsId{dsId}, - mSampaChannelHandler{sampaChannelHandler}, + mDecodedDataHandlers{decodedDataHandlers}, mSampaHeader{}, mBitBuffer{}, mNofSync{}, @@ -422,20 +422,20 @@ std::ostream& operator<<(std::ostream& os, const o2::mch::raw::BareElinkDecoder< template <> void BareElinkDecoder<ChargeSumMode>::sendCluster() { - if (mSampaChannelHandler) { - mSampaChannelHandler(mDsId, - channelNumber64(mSampaHeader), - SampaCluster(mTimestamp, mSampaHeader.bunchCrossingCounter(), mClusterSum, mClusterSize)); + SampaChannelHandler handler = mDecodedDataHandlers.sampaChannelHandler; + if (handler) { + handler(mDsId, channelNumber64(mSampaHeader), + SampaCluster(mTimestamp, mSampaHeader.bunchCrossingCounter(), mClusterSum, mClusterSize)); } } template <> void BareElinkDecoder<SampleMode>::sendCluster() { - if (mSampaChannelHandler) { - mSampaChannelHandler(mDsId, - channelNumber64(mSampaHeader), - SampaCluster(mTimestamp, mSampaHeader.bunchCrossingCounter(), mSamples)); + SampaChannelHandler handler = mDecodedDataHandlers.sampaChannelHandler; + if (handler) { + handler(mDsId, channelNumber64(mSampaHeader), + SampaCluster(mTimestamp, mSampaHeader.bunchCrossingCounter(), mSamples)); } mSamples.clear(); } diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/BareGBTDecoder.h b/Detectors/MUON/MCH/Raw/Decoder/src/BareGBTDecoder.h index 2699e7b2b0d4f..f95f4ab6a5899 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/BareGBTDecoder.h +++ b/Detectors/MUON/MCH/Raw/Decoder/src/BareGBTDecoder.h @@ -13,7 +13,7 @@ #include <array> #include "BareElinkDecoder.h" -#include "MCHRawDecoder/SampaChannelHandler.h" +#include "MCHRawDecoder/DecodedDataHandlers.h" #include <gsl/span> #include <fmt/printf.h> #include <fmt/format.h> @@ -40,8 +40,9 @@ class BareGBTDecoder : public PayloadDecoder<BareGBTDecoder<CHARGESUM>> public: /// Constructor. /// \param solarId - /// \param sampaChannelHandler the callable that will handle each SampaCluster - BareGBTDecoder(uint16_t solarId, SampaChannelHandler sampaChannelHandler); + /// \param decodedDataHandlers a structure with various callable that + /// handle the Sampa packets and decoding errors + BareGBTDecoder(uint16_t solarId, DecodedDataHandlers decodedDataHandlers); /** @name Main interface */ @@ -81,10 +82,10 @@ using namespace boost::multiprecision; template <typename CHARGESUM> BareGBTDecoder<CHARGESUM>::BareGBTDecoder(uint16_t solarId, - SampaChannelHandler sampaChannelHandler) - : PayloadDecoder<BareGBTDecoder<CHARGESUM>>(sampaChannelHandler), + DecodedDataHandlers decodedDataHandlers) + : PayloadDecoder<BareGBTDecoder<CHARGESUM>>(decodedDataHandlers), mSolarId{solarId}, - mElinks{impl::makeArray<40>([=](uint8_t i) { return BareElinkDecoder<CHARGESUM>(DsElecId{solarId, static_cast<uint8_t>(i / 5), static_cast<uint8_t>(i % 5)}, sampaChannelHandler); })}, + mElinks{impl::makeArray<40>([=](uint8_t i) { return BareElinkDecoder<CHARGESUM>(DsElecId{solarId, static_cast<uint8_t>(i / 5), static_cast<uint8_t>(i % 5)}, decodedDataHandlers); })}, mNofGbtWordsSeens{0} { } diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/DataDecoder.cxx b/Detectors/MUON/MCH/Raw/Decoder/src/DataDecoder.cxx new file mode 100644 index 0000000000000..68c4482aa1df5 --- /dev/null +++ b/Detectors/MUON/MCH/Raw/Decoder/src/DataDecoder.cxx @@ -0,0 +1,282 @@ +// 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 DataDecoder.cxx +/// \author Andrea Ferrero +/// +/// \brief Implementation of a data processor to run the raw decoding +/// + +#include "MCHRawDecoder/DataDecoder.h" + +#include <fstream> +#include "Headers/RAWDataHeader.h" +#include "DetectorsRaw/RDHUtils.h" +#include "MCHMappingInterface/Segmentation.h" + +namespace o2 +{ +namespace mch +{ +namespace raw +{ + +using namespace o2; +//using namespace o2::framework; +using namespace o2::mch::mapping; +using RDH = o2::header::RDHAny; + +// conversion matrix between the original channels numbering of the RUN2 readout electronics and the final version of the RUN3 DualSAMPA-based readout +static std::array<int, 64> refManu2ds_st345_v5 = { + 63, 62, 61, 60, 59, 57, 56, 53, 51, 50, 47, 45, 44, 41, 38, 35, + 36, 33, 34, 37, 32, 39, 40, 42, 43, 46, 48, 49, 52, 54, 55, 58, + 7, 8, 5, 2, 6, 1, 3, 0, 4, 9, 10, 15, 17, 18, 22, 25, + 31, 30, 29, 28, 27, 26, 24, 23, 20, 21, 16, 19, 12, 14, 11, 13}; + +// conversion matrix between the original channels numbering of the RUN2 readout electronics and the intermediate version of the RUN3 DualSAMPA-based readout +static std::array<int, 64> refManu2ds_st345_v2 = { + 62, 61, 63, 60, 59, 55, 58, 57, 56, 54, 50, 46, 42, 39, 37, 41, + 35, 36, 33, 34, 32, 38, 43, 40, 45, 44, 47, 48, 49, 52, 51, 53, + 7, 6, 5, 4, 2, 3, 1, 0, 9, 11, 13, 15, 17, 19, 21, 23, + 31, 30, 29, 28, 27, 26, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8}; + +#define refManu2ds_st345 refManu2ds_st345_v5 + +// inverse channel conversion matrix +static std::array<int, 64> refDs2manu_st345; + +// function returning the RUN3 DualSAMPA channel number given the original RUN2 channel +static int manu2ds(int i) +{ + return refManu2ds_st345[i]; +} + +// function returning the original RUN2 channel number given the RUN3 DualSAMPA channel +static int ds2manu(int i) +{ + return refDs2manu_st345[i]; +} + +static void patchPage(gsl::span<const std::byte> rdhBuffer, bool verbose) +{ + static int mNrdhs = 0; + auto& rdhAny = *reinterpret_cast<RDH*>(const_cast<std::byte*>(&(rdhBuffer[0]))); + mNrdhs++; + + auto cruId = o2::raw::RDHUtils::getCRUID(rdhAny) & 0xFF; + auto flags = o2::raw::RDHUtils::getCRUID(rdhAny) & 0xFF00; + auto endpoint = o2::raw::RDHUtils::getEndPointID(rdhAny); + uint32_t feeId = cruId * 2 + endpoint + flags; + o2::raw::RDHUtils::setFEEID(rdhAny, feeId); + + if (verbose) { + std::cout << mNrdhs << "--\n"; + o2::raw::RDHUtils::printRDH(rdhAny); + } +}; + +//======================= +// Data decoder + +DataDecoder::DataDecoder(SampaChannelHandler channelHandler, RdhHandler rdhHandler, std::string mapCRUfile, std::string mapFECfile, bool ds2manu, bool verbose) + : mChannelHandler(channelHandler), mRdhHandler(rdhHandler), mMapCRUfile(mapCRUfile), mMapFECfile(mapFECfile), mDs2manu(ds2manu), mDebug(verbose) +{ + init(); +} + +static bool isValidDeID(int deId) +{ + for (auto id : deIdsForAllMCH) { + if (id == deId) { + return true; + } + } + + return false; +} + +void DataDecoder::decodeBuffer(gsl::span<const std::byte> page) +{ + size_t ndigits{0}; + + uint32_t orbit; + + auto channelHandler = [&](DsElecId dsElecId, uint8_t channel, o2::mch::raw::SampaCluster sc) { + if (mChannelHandler) { + mChannelHandler(dsElecId, channel, sc); + } + + if (mDs2manu) { + channel = ds2manu(int(channel)); + } + + uint32_t digitadc = sc.sum(); + + int deId{-1}; + int dsIddet{-1}; + if (auto opt = mElec2Det(dsElecId); opt.has_value()) { + DsDetId dsDetId = opt.value(); + dsIddet = dsDetId.dsId(); + deId = dsDetId.deId(); + } + if (mDebug) { + auto s = asString(dsElecId); + auto ch = fmt::format("{}-CH{:02d}", s, channel); + std::cout << ch << " " + << "deId " << deId << " dsIddet " << dsIddet << std::endl; + } + + if (deId < 0 || dsIddet < 0 || !isValidDeID(deId)) { + return; + } + + int padId = -1; + const Segmentation& segment = segmentation(deId); + + padId = segment.findPadByFEE(dsIddet, int(channel)); + if (mDebug) { + auto s = asString(dsElecId); + auto ch = fmt::format("{}-CH{:02d}", s, channel); + std::cout << ch << " " + << fmt::format("PAD ({:04d} {:04d} {:04d})\tADC {:06d} TIME ({} {} {:02d}) SIZE {} END {}", + deId, dsIddet, padId, digitadc, orbit, sc.bunchCrossing, sc.sampaTime, sc.nofSamples(), (sc.sampaTime + sc.nofSamples() - 1)) + << (((sc.sampaTime + sc.nofSamples() - 1) >= 98) ? " *" : "") << std::endl; + } + + // skip channels not associated to any pad + if (padId < 0) { + return; + } + + Digit::Time time; + time.sampaTime = sc.sampaTime; + time.bunchCrossing = sc.bunchCrossing; + time.orbit = orbit; + + mOutputDigits.emplace_back(o2::mch::Digit(deId, padId, digitadc, time, sc.nofSamples())); + + if (mDebug) { + std::cout << "DIGIT STORED:\nADC " << mOutputDigits.back().getADC() << " DE# " << mOutputDigits.back().getDetID() << " PadId " << mOutputDigits.back().getPadID() << " time " << mOutputDigits.back().getTime().sampaTime << std::endl; + } + ++ndigits; + }; + + const auto dumpDigits = [&](bool bending) { + for (auto d : mOutputDigits) { + if (d.getPadID() < 0) { + continue; + } + const Segmentation& segment = segmentation(d.getDetID()); + bool bend = segment.isBendingPad(d.getPadID()); + if (bending != segment.isBendingPad(d.getPadID())) { + continue; + } + float X = segment.padPositionX(d.getPadID()); + float Y = segment.padPositionY(d.getPadID()); + std::cout << fmt::format(" DE {:4d} PAD {:5d} ADC {:6d} TIME ({} {} {:4d})", + d.getDetID(), d.getPadID(), d.getADC(), d.getTime().orbit, d.getTime().bunchCrossing, d.getTime().sampaTime); + std::cout << fmt::format("\tC {} PAD_XY {:+2.2f} , {:+2.2f}", (bending ? (int)0 : (int)1), X, Y); + std::cout << std::endl; + } + }; + + patchPage(page, mDebug); + + auto& rdhAny = *reinterpret_cast<RDH*>(const_cast<std::byte*>(&(page[0]))); + orbit = o2::raw::RDHUtils::getHeartBeatOrbit(rdhAny); + + if (mRdhHandler) { + mRdhHandler(&rdhAny); + } + + // add orbit to vector if not present yet + mOrbits.emplace(page); + + if (!mDecoder) { + DecodedDataHandlers handlers; + handlers.sampaChannelHandler = channelHandler; + mDecoder = mFee2Solar ? o2::mch::raw::createPageDecoder(page, handlers, mFee2Solar) + : o2::mch::raw::createPageDecoder(page, handlers); + } + mDecoder(page); + + if (mDebug) { + std::cout << "[decodeBuffer] mOutputDigits size: " << mOutputDigits.size() << std::endl; + dumpDigits(true); + dumpDigits(false); + } +}; + +static std::string readFileContent(std::string& filename) +{ + std::string content; + std::string s; + std::ifstream in(filename); + while (std::getline(in, s)) { + content += s; + content += "\n"; + } + std::cout << "readFileContent(" << filename << "):" << std::endl + << content << std::endl; + return content; +}; + +void DataDecoder::initElec2DetMapper(std::string filename) +{ + std::cout << "[initElec2DetMapper] filename=" << filename << std::endl; + if (filename.empty()) { + mElec2Det = createElec2DetMapper<ElectronicMapperGenerated>(); + } else { + ElectronicMapperString::sFecMap = readFileContent(filename); + mElec2Det = createElec2DetMapper<ElectronicMapperString>(); + } +}; + +void DataDecoder::initFee2SolarMapper(std::string filename) +{ + std::cout << "[initFee2SolarMapper] filename=" << filename << std::endl; + if (filename.empty()) { + mFee2Solar = createFeeLink2SolarMapper<ElectronicMapperGenerated>(); + } else { + ElectronicMapperString::sCruMap = readFileContent(filename); + mFee2Solar = createFeeLink2SolarMapper<ElectronicMapperString>(); + } +}; + +//_________________________________________________________________________________________________ +void DataDecoder::init() +{ + mNrdhs = 0; + + for (int i = 0; i < 64; i++) { + for (int j = 0; j < 64; j++) { + if (refManu2ds_st345[j] != i) { + continue; + } + refDs2manu_st345[i] = j; + break; + } + } + + initFee2SolarMapper(mMapCRUfile); + initElec2DetMapper(mMapFECfile); +}; + +//_________________________________________________________________________________________________ +void DataDecoder::reset() +{ + mOutputDigits.clear(); + mOrbits.clear(); +} + +} // namespace raw +} // namespace mch +} // end namespace o2 diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx b/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx index 975360cb98e2d..f3c4032cbaa32 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx +++ b/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx @@ -30,16 +30,16 @@ struct PayloadDecoderImpl { void process(uint32_t, gsl::span<const std::byte>); }; - type operator()(const FeeLinkId& feeLinkId, SampaChannelHandler sampaChannelHandler, FeeLink2SolarMapper fee2solar); + type operator()(const FeeLinkId& feeLinkId, DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar); }; template <typename CHARGESUM> struct PayloadDecoderImpl<UserLogicFormat, CHARGESUM> { using type = UserLogicEndpointDecoder<CHARGESUM>; - type operator()(const FeeLinkId& feeLinkId, SampaChannelHandler sampaChannelHandler, FeeLink2SolarMapper fee2solar) + type operator()(const FeeLinkId& feeLinkId, DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar) { - return std::move(UserLogicEndpointDecoder<CHARGESUM>(feeLinkId.feeId(), fee2solar, sampaChannelHandler)); + return std::move(UserLogicEndpointDecoder<CHARGESUM>(feeLinkId.feeId(), fee2solar, decodedDataHandlers)); } }; @@ -47,13 +47,13 @@ template <typename CHARGESUM> struct PayloadDecoderImpl<BareFormat, CHARGESUM> { using type = BareGBTDecoder<CHARGESUM>; - type operator()(const FeeLinkId& feeLinkId, SampaChannelHandler sampaChannelHandler, FeeLink2SolarMapper fee2solar) + type operator()(const FeeLinkId& feeLinkId, DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar) { auto solarId = fee2solar(feeLinkId); if (!solarId.has_value()) { throw std::logic_error(fmt::format("{} could not get solarId from feelinkid={}\n", __PRETTY_FUNCTION__, feeLinkId)); } - return std::move(BareGBTDecoder<CHARGESUM>(solarId.value(), sampaChannelHandler)); + return std::move(BareGBTDecoder<CHARGESUM>(solarId.value(), decodedDataHandlers)); } }; @@ -61,7 +61,7 @@ template <typename FORMAT, typename CHARGESUM> class PageDecoderImpl { public: - PageDecoderImpl(SampaChannelHandler sampaChannelHandler, FeeLink2SolarMapper fee2solar) : mSampaChannelHandler{sampaChannelHandler}, + PageDecoderImpl(DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar) : mDecodedDataHandlers{decodedDataHandlers}, mFee2SolarMapper(fee2solar) { } @@ -79,25 +79,28 @@ class PageDecoderImpl auto p = mPayloadDecoders.find(feeLinkId); if (p == mPayloadDecoders.end()) { - mPayloadDecoders.emplace(feeLinkId, PayloadDecoderImpl<FORMAT, CHARGESUM>()(feeLinkId, mSampaChannelHandler, mFee2SolarMapper)); + mPayloadDecoders.emplace(feeLinkId, PayloadDecoderImpl<FORMAT, CHARGESUM>()(feeLinkId, mDecodedDataHandlers, mFee2SolarMapper)); p = mPayloadDecoders.find(feeLinkId); } uint32_t orbit = o2::raw::RDHUtils::getHeartBeatOrbit(rdhP); auto rdhSize = o2::raw::RDHUtils::getHeaderSize(rdhP); auto payloadSize = o2::raw::RDHUtils::getMemorySize(rdhP) - rdhSize; - p->second.process(orbit, page.subspan(rdhSize, payloadSize)); + // skip empty payloads, otherwise the orbit jumps are not correctly detected + if (payloadSize > 0) { + p->second.process(orbit, page.subspan(rdhSize, payloadSize)); + } } private: - SampaChannelHandler mSampaChannelHandler; + DecodedDataHandlers mDecodedDataHandlers; FeeLink2SolarMapper mFee2SolarMapper; std::map<FeeLinkId, typename PayloadDecoderImpl<FORMAT, CHARGESUM>::type> mPayloadDecoders; }; } // namespace impl -PageDecoder createPageDecoder(RawBuffer rdhBuffer, SampaChannelHandler channelHandler, FeeLink2SolarMapper fee2solar) +PageDecoder createPageDecoder(RawBuffer rdhBuffer, DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar) { const void* rdhP = reinterpret_cast<const void*>(rdhBuffer.data()); bool ok = o2::raw::RDHUtils::checkRDH(rdhP, true); @@ -108,23 +111,37 @@ PageDecoder createPageDecoder(RawBuffer rdhBuffer, SampaChannelHandler channelHa auto feeId = o2::raw::RDHUtils::getFEEID(rdhP); if (linkId == 15) { if (feeId & impl::CHARGESUM_MASK) { - return impl::PageDecoderImpl<UserLogicFormat, ChargeSumMode>(channelHandler, fee2solar); + return impl::PageDecoderImpl<UserLogicFormat, ChargeSumMode>(decodedDataHandlers, fee2solar); } else { - return impl::PageDecoderImpl<UserLogicFormat, SampleMode>(channelHandler, fee2solar); + return impl::PageDecoderImpl<UserLogicFormat, SampleMode>(decodedDataHandlers, fee2solar); } } else { if (feeId & impl::CHARGESUM_MASK) { - return impl::PageDecoderImpl<BareFormat, ChargeSumMode>(channelHandler, fee2solar); + return impl::PageDecoderImpl<BareFormat, ChargeSumMode>(decodedDataHandlers, fee2solar); } else { - return impl::PageDecoderImpl<BareFormat, SampleMode>(channelHandler, fee2solar); + return impl::PageDecoderImpl<BareFormat, SampleMode>(decodedDataHandlers, fee2solar); } } } -PageDecoder createPageDecoder(RawBuffer rdhBuffer, SampaChannelHandler channelHandler) +PageDecoder createPageDecoder(RawBuffer rdhBuffer, DecodedDataHandlers decodedDataHandlers) { auto fee2solar = createFeeLink2SolarMapper<ElectronicMapperGenerated>(); - return createPageDecoder(rdhBuffer, channelHandler, fee2solar); + return createPageDecoder(rdhBuffer, decodedDataHandlers, fee2solar); +} + +PageDecoder createPageDecoder(RawBuffer rdhBuffer, SampaChannelHandler channelHandler) +{ + DecodedDataHandlers handlers; + handlers.sampaChannelHandler = channelHandler; + return createPageDecoder(rdhBuffer, handlers); +} + +PageDecoder createPageDecoder(RawBuffer rdhBuffer, SampaChannelHandler channelHandler, FeeLink2SolarMapper fee2solar) +{ + DecodedDataHandlers handlers; + handlers.sampaChannelHandler = channelHandler; + return createPageDecoder(rdhBuffer, handlers, fee2solar); } PageParser createPageParser() diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/PayloadDecoder.h b/Detectors/MUON/MCH/Raw/Decoder/src/PayloadDecoder.h index 1b5adddc542cb..78ee061da59ed 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/PayloadDecoder.h +++ b/Detectors/MUON/MCH/Raw/Decoder/src/PayloadDecoder.h @@ -12,7 +12,7 @@ #define O2_MCH_RAW_PAYLOAD_DECODER_H #include "Headers/RAWDataHeader.h" -#include "MCHRawDecoder/SampaChannelHandler.h" +#include "MCHRawDecoder/DecodedDataHandlers.h" #include "MCHRawDecoder/PageDecoder.h" #include <map> #include <cstdlib> @@ -38,9 +38,9 @@ class PayloadDecoder { public: /// Constructs a decoder - /// \param channelHandler the handler that will be called for each - /// piece of sampa data (a SampaCluster, i.e. a part of a time window) - PayloadDecoder(SampaChannelHandler channelHandler); + /// \param decodedDataHandlers decodedDataHandlers a structure with various callable objects that + /// will be called for each decoded Sampa packet and in case of decoding errors + PayloadDecoder(DecodedDataHandlers decodedDataHandlers); /// decode the buffer (=payload only) /// \return the number of bytes used from the buffer @@ -48,12 +48,12 @@ class PayloadDecoder private: uint32_t mOrbit; - SampaChannelHandler mChannelHandler; + DecodedDataHandlers mDecodedDataHandlers; }; template <typename T> -PayloadDecoder<T>::PayloadDecoder(SampaChannelHandler channelHandler) - : mChannelHandler(channelHandler) +PayloadDecoder<T>::PayloadDecoder(DecodedDataHandlers decodedDataHandlers) + : mDecodedDataHandlers(decodedDataHandlers) { } diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicElinkDecoder.h b/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicElinkDecoder.h index f53dac245abbd..9b398a67f869a 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicElinkDecoder.h +++ b/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicElinkDecoder.h @@ -14,7 +14,8 @@ #include "Debug.h" #include "MCHRawCommon/DataFormats.h" #include "MCHRawCommon/SampaHeader.h" -#include "MCHRawDecoder/SampaChannelHandler.h" +#include "MCHRawDecoder/DecodedDataHandlers.h" +#include "MCHRawDecoder/ErrorCodes.h" #include "MCHRawElecMap/DsElecId.h" #include <bitset> #include <fmt/format.h> @@ -32,7 +33,7 @@ template <typename CHARGESUM> class UserLogicElinkDecoder { public: - UserLogicElinkDecoder(DsElecId dsId, SampaChannelHandler sampaChannelHandler); + UserLogicElinkDecoder(DsElecId dsId, DecodedDataHandlers decodedDataHandlers); /// Append 50 bits-worth of data void append(uint64_t data50, uint8_t error); @@ -57,6 +58,8 @@ class UserLogicElinkDecoder template <typename T> friend std::ostream& operator<<(std::ostream& os, const o2::mch::raw::UserLogicElinkDecoder<T>& e); + const DsElecId& dsId() const { return mDsId; } + void clear(); bool hasError() const; bool isHeaderComplete() const { return mHeaderParts.size() == 5; } @@ -69,6 +72,7 @@ class UserLogicElinkDecoder void oneLess10BitWord(); void prepareAndSendCluster(); void sendCluster(const SampaCluster& sc) const; + void sendError(int8_t chip, uint32_t error) const; void setClusterSize(uint10_t value); void setClusterTime(uint10_t value); void setHeaderPart(uint10_t data10); @@ -77,7 +81,7 @@ class UserLogicElinkDecoder private: DsElecId mDsId; - SampaChannelHandler mSampaChannelHandler; + DecodedDataHandlers mDecodedDataHandlers; State mState; std::vector<uint10_t> mSamples{}; std::vector<uint10_t> mHeaderParts{}; @@ -102,8 +106,8 @@ constexpr bool isIncomplete(uint8_t error) template <typename CHARGESUM> UserLogicElinkDecoder<CHARGESUM>::UserLogicElinkDecoder(DsElecId dsId, - SampaChannelHandler sampaChannelHandler) - : mDsId{dsId}, mSampaChannelHandler{sampaChannelHandler}, mState{State::WaitingSync} + DecodedDataHandlers decodedDataHandlers) + : mDsId{dsId}, mDecodedDataHandlers{decodedDataHandlers}, mState{State::WaitingSync} { } @@ -149,10 +153,11 @@ void UserLogicElinkDecoder<CHARGESUM>::append(uint64_t data50, uint8_t error) } } - if (isIncomplete(error) && (i == 5)) { + if (isIncomplete(error) && (i == 5) && (mState != State::WaitingSync)) { #ifdef ULDEBUG debugHeader() << (*this) << " data packet end not found when isIncomplete --> resetting\n"; #endif + sendError(static_cast<int8_t>(mSampaHeader.chipAddress()), static_cast<uint32_t>(ErrorBadIncompleteWord)); reset(); } } // namespace o2::mch::raw @@ -331,7 +336,21 @@ void UserLogicElinkDecoder<CHARGESUM>::sendCluster(const SampaCluster& sc) const channelNumber64(mSampaHeader), o2::mch::raw::asString(sc)); #endif - mSampaChannelHandler(mDsId, channelNumber64(mSampaHeader), sc); + mDecodedDataHandlers.sampaChannelHandler(mDsId, channelNumber64(mSampaHeader), sc); +} + +template <typename CHARGESUM> +void UserLogicElinkDecoder<CHARGESUM>::sendError(int8_t chip, uint32_t error) const +{ +#ifdef ULDEBUG + debugHeader() << (*this) << " --> " + << fmt::format(" calling errorHandler for {} chip {} = {}\n", + o2::mch::raw::asString(mDsId), chip, error); +#endif + SampaErrorHandler handler = mDecodedDataHandlers.sampaErrorHandler; + if (handler) { + handler(mDsId, chip, error); + } } template <typename CHARGESUM> @@ -354,9 +373,11 @@ void UserLogicElinkDecoder<CHARGESUM>::setClusterSize(uint10_t value) mErrorMessage = std::nullopt; if (mClusterSize == 0) { mErrorMessage = "cluster size is zero"; + sendError(static_cast<int8_t>(mSampaHeader.chipAddress()), static_cast<uint32_t>(ErrorBadClusterSize)); } if (checkSize > 0) { mErrorMessage = "number of samples bigger than nof10BitWords"; + sendError(static_cast<int8_t>(mSampaHeader.chipAddress()), static_cast<uint32_t>(ErrorBadClusterSize)); } #ifdef ULDEBUG debugHeader() << (*this) << " --> size=" << mClusterSize << " samples=" << mSamplesToRead << "\n"; @@ -401,7 +422,7 @@ void UserLogicElinkDecoder<CHARGESUM>::setSample(uint10_t sample) template <> void UserLogicElinkDecoder<SampleMode>::prepareAndSendCluster() { - if (mSampaChannelHandler) { + if (mDecodedDataHandlers.sampaChannelHandler) { SampaCluster sc(mClusterTime, mSampaHeader.bunchCrossingCounter(), mSamples); sendCluster(sc); } @@ -414,9 +435,11 @@ void UserLogicElinkDecoder<ChargeSumMode>::prepareAndSendCluster() if (mSamples.size() != 2) { throw std::invalid_argument(fmt::format("expected sample size to be 2 but it is {}", mSamples.size())); } - uint32_t q = (((static_cast<uint32_t>(mSamples[1]) & 0x3FF) << 10) | (static_cast<uint32_t>(mSamples[0]) & 0x3FF)); - SampaCluster sc(mClusterTime, mSampaHeader.bunchCrossingCounter(), q, mClusterSize); - sendCluster(sc); + if (mDecodedDataHandlers.sampaChannelHandler) { + uint32_t q = (((static_cast<uint32_t>(mSamples[1]) & 0x3FF) << 10) | (static_cast<uint32_t>(mSamples[0]) & 0x3FF)); + SampaCluster sc(mClusterTime, mSampaHeader.bunchCrossingCounter(), q, mClusterSize); + sendCluster(sc); + } mSamples.clear(); } @@ -441,7 +464,7 @@ std::ostream& operator<<(std::ostream& os, const o2::mch::raw::UserLogicElinkDec for (auto s : e.mSamples) { os << fmt::format("{:4d} ", s); } - if (!e.mSampaChannelHandler) { + if (!e.mDecodedDataHandlers.sampaChannelHandler) { os << " empty handler "; } diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicEndpointDecoder.h b/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicEndpointDecoder.h index 8eefdf5d3348d..a5a325f72db57 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicEndpointDecoder.h +++ b/Detectors/MUON/MCH/Raw/Decoder/src/UserLogicEndpointDecoder.h @@ -13,7 +13,7 @@ #include <array> #include "UserLogicElinkDecoder.h" -#include "MCHRawDecoder/SampaChannelHandler.h" +#include "MCHRawDecoder/DecodedDataHandlers.h" #include <gsl/span> #include <fmt/printf.h> #include <fmt/format.h> @@ -48,7 +48,7 @@ class UserLogicEndpointDecoder : public PayloadDecoder<UserLogicEndpointDecoder< /// \param sampaChannelHandler the callable that will handle each SampaCluster UserLogicEndpointDecoder(uint16_t feeId, std::function<std::optional<uint16_t>(FeeLinkId id)> fee2SolarMapper, - SampaChannelHandler sampaChannelHandler); + DecodedDataHandlers decodedDataHandlers); /** @name Main interface */ @@ -74,7 +74,7 @@ class UserLogicEndpointDecoder : public PayloadDecoder<UserLogicEndpointDecoder< private: uint16_t mFeeId; std::function<std::optional<uint16_t>(FeeLinkId id)> mFee2SolarMapper; - SampaChannelHandler mChannelHandler; + DecodedDataHandlers mDecodedDataHandlers; std::map<uint16_t, std::array<ElinkDecoder, 40>> mElinkDecoders; int mNofGbtWordsSeens; }; @@ -85,11 +85,11 @@ using namespace boost::multiprecision; template <typename CHARGESUM> UserLogicEndpointDecoder<CHARGESUM>::UserLogicEndpointDecoder(uint16_t feeId, std::function<std::optional<uint16_t>(FeeLinkId id)> fee2SolarMapper, - SampaChannelHandler sampaChannelHandler) - : PayloadDecoder<UserLogicEndpointDecoder<CHARGESUM>>(sampaChannelHandler), + DecodedDataHandlers decodedDataHandlers) + : PayloadDecoder<UserLogicEndpointDecoder<CHARGESUM>>(decodedDataHandlers), mFeeId{feeId}, mFee2SolarMapper{fee2SolarMapper}, - mChannelHandler(sampaChannelHandler), + mDecodedDataHandlers(decodedDataHandlers), mNofGbtWordsSeens{0} { } @@ -123,7 +123,13 @@ size_t UserLogicEndpointDecoder<CHARGESUM>::append(Payload buffer) int gbt = (word >> 59) & 0x1F; if (gbt < 0 || gbt > 11) { - throw fmt::format("warning : out-of-range gbt {} word={:08X}\n", gbt, word); + SampaErrorHandler handler = mDecodedDataHandlers.sampaErrorHandler; + if (handler) { + DsElecId dsId{static_cast<uint16_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0)}; + handler(dsId, -1, ErrorBadLinkID); + } else { + throw fmt::format("warning : out-of-range gbt {} word={:08X}\n", gbt, word); + } } // Get the corresponding decoders array, or allocate it if does not exist yet @@ -136,19 +142,34 @@ size_t UserLogicEndpointDecoder<CHARGESUM>::append(Payload buffer) auto solarId = mFee2SolarMapper(feeLinkId); if (!solarId.has_value()) { - throw std::logic_error(fmt::format("{} Could not get solarId from feeLinkId={}\n", __PRETTY_FUNCTION__, asString(feeLinkId))); + SampaErrorHandler handler = mDecodedDataHandlers.sampaErrorHandler; + if (handler) { + DsElecId dsId{static_cast<uint16_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0)}; + handler(dsId, -1, ErrorUnknownLinkID); + } else { + throw std::logic_error(fmt::format("{} Could not get solarId from feeLinkId={}\n", __PRETTY_FUNCTION__, asString(feeLinkId))); + } } mElinkDecoders.emplace(static_cast<uint16_t>(gbt), impl::makeArray<40>([=](size_t i) { DsElecId dselec{solarId.value(), static_cast<uint8_t>(i / 5), static_cast<uint8_t>(i % 5)}; - return ElinkDecoder(dselec, mChannelHandler); + return ElinkDecoder(dselec, mDecodedDataHandlers); })); d = mElinkDecoders.find(gbt); } // in the 14 MSB(Most Significant Bits) 6 are used to specify the Dual Sampa index (0..39) uint16_t dsid = (word >> 53) & 0x3F; + if (dsid > 39) { + SampaErrorHandler handler = mDecodedDataHandlers.sampaErrorHandler; + if (handler) { + DsElecId dsId{static_cast<uint16_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0)}; + handler(dsId, -1, ErrorBadELinkID); + } else { + throw fmt::format("warning : out-of-range DS ID {} word={:08X}\n", dsid, word); + } + } // bits 50..52 are error bits int8_t error = static_cast<uint8_t>((word >> 50) & 0x7); diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/testBareElinkDecoder.cxx b/Detectors/MUON/MCH/Raw/Decoder/src/testBareElinkDecoder.cxx index e8447c580a14c..4dd218bb18d4a 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/testBareElinkDecoder.cxx +++ b/Detectors/MUON/MCH/Raw/Decoder/src/testBareElinkDecoder.cxx @@ -49,7 +49,9 @@ BOOST_AUTO_TEST_CASE(Decoding10) helper(dsId, channel, sh); }; - BareElinkDecoder<SampleMode> e(DsElecId{0, 0, 0}, hp); + DecodedDataHandlers rh; + rh.sampaChannelHandler = hp; + BareElinkDecoder<SampleMode> e(DsElecId{0, 0, 0}, rh); std::string enc("1100100010000000000011110000001010101010101010101011111010011100000000000010000000000000000000000000100000000000101000000010100000010000100100100000000000101000000000000000000000000100000000001001100000100110001010011000111110100110100000000000101100000000000000000000001100000000001000001000100000101010000010011000001001001000010110000000000011111000000000000000000000001000000000110110010011011001101101100101110110011111011001"); @@ -70,7 +72,9 @@ BOOST_AUTO_TEST_CASE(Decoding20) helper(dsId, channel, sh); }; - BareElinkDecoder<ChargeSumMode> e(DsElecId{0, 0, 0}, hp); + DecodedDataHandlers rh; + rh.sampaChannelHandler = hp; + BareElinkDecoder<ChargeSumMode> e(DsElecId{0, 0, 0}, rh); std::string enc("11001000100000000000111100000010101010101010101010110110100100100000000000100000000000000000000000001000000000001010000010100110000000000000010000100100100000000000101000000000000000000000001000000000001001100010011111100000000000000110100100100000000000101100000000000000000000001000000000001000001010000100101000000000110110100100100000000000111110000000000000000000001000000000001101100111011100001100000000"); for (int i = 0; i < enc.size() - 1; i += 2) { @@ -82,7 +86,7 @@ BOOST_AUTO_TEST_CASE(Decoding20) // same thing but with a decoder without a channel handler // so we don't "see" any packet in this case npackets = 0; - BareElinkDecoder<ChargeSumMode> e2(DsElecId{0, 0, 0}, nullptr); + BareElinkDecoder<ChargeSumMode> e2(DsElecId{0, 0, 0}, DecodedDataHandlers{}); for (int i = 0; i < enc.size() - 1; i += 2) { e2.append(enc[i] == 1, enc[i + 1] == 1); } diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/testUserLogicEndpointDecoder.cxx b/Detectors/MUON/MCH/Raw/Decoder/src/testUserLogicEndpointDecoder.cxx index 80e3e60cf0117..9ceb3cfa92495 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/testUserLogicEndpointDecoder.cxx +++ b/Detectors/MUON/MCH/Raw/Decoder/src/testUserLogicEndpointDecoder.cxx @@ -22,7 +22,7 @@ #include "MCHRawCommon/DataFormats.h" #include "MCHRawCommon/SampaHeader.h" #include "MCHRawDecoder/PageDecoder.h" -#include "MCHRawDecoder/SampaChannelHandler.h" +#include "MCHRawDecoder/DecodedDataHandlers.h" #include "MCHRawEncoderPayload/DataBlock.h" #include "MCHRawEncoderPayload/PayloadEncoder.h" #include "MoveBuffer.h" @@ -33,7 +33,74 @@ #include <iostream> using namespace o2::mch::raw; -using o2::header::RAWDataHeaderV4; + +const uint64_t CruPageOK[] = { + 0x00000A0000124006ul, + 0x000C4C0F00A000A0ul, + 0x010E853D00000570ul, + 0x0000000000000000ul, + 0x0000000000006000ul, + 0x0000000000000000ul, + 0x0000000000000000ul, + 0x0000000000000000ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x3F04ECA103E5Cul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x0000040215C0Dul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x00000C0301004ul, + ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x0000000000400ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1F080CA100E4Dul, + ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x00044C0100001ul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul}; + +const uint64_t CruPageBadClusterSize[] = { + 0x00000A0000124006ul, + 0x000C4C0F00A000A0ul, + 0x010E853D00000570ul, + 0x0000000000000000ul, + 0x0000000000006000ul, + 0x0000000000000000ul, + 0x0000000000000000ul, + 0x0000000000000000ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x3F04ECA103E5Cul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x0000040215C0Eul, // <== the cluster size is increased from 13 (0xD) to 14 (0xE) + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x00000C0301004ul, // now the cluster size does not match anymore with the + ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x0000000000400ul, // number of 10-bit words in the SAMPA header, which will trigger + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul, // a ErrorBadClusterSize error. + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1F080CA100E4Dul, + ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x00044C0100001ul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul}; + +const uint64_t CruPageBadN10bitWords[] = { + 0x00000A0000124006ul, + 0x000C4C0F00A000A0ul, + 0x010E853D00000570ul, + 0x0000000000000000ul, + 0x0000000000006000ul, + 0x0000000000000000ul, + 0x0000000000000000ul, + 0x0000000000000000ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x3F04ECA103E5Cul, + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x0000040215C08ul, // <== the cluster size is decreased from 13 (0xD) to 8 (0x8) + //((0x0200ul<<50)&0xFFFC000000000000ul) + 0x00000C0301004ul, // and one 50-bit word is removed. In this case the cluster + ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x0000000000400ul, // size matches the number of samples in the data, but the + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul, // end of the SAMPA packet arrives too early with respect to + ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1F080CA100E4Dul, // the number of 10-bit words in the SAMPA header. This will + ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x00044C0100001ul, // trigger a ErrorBadIncompleteWord error. + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul, // <== a word is added at the end in order to match the + ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul // payload size in the RDH +}; SampaChannelHandler handlePacket(std::string& result) { @@ -50,6 +117,14 @@ SampaChannelHandler handlePacket(std::string& result) }; } +SampaErrorHandler handleError(std::string& result) +{ + return [&result](DsElecId dsId, int8_t chip, uint32_t error) { + result += fmt::format("{}-chip-{}-error-{}", asString(dsId), chip, error); + result += "\n"; + }; +} + std::vector<std::byte> convertBuffer2PayloadBuffer(gsl::span<const std::byte> buffer, std::optional<size_t> insertSync = std::nullopt) { @@ -89,7 +164,10 @@ std::string decodeBuffer(int feeId, gsl::span<const std::byte> buffer) { std::string results; auto fee2solar = createFeeLink2SolarMapper<ElectronicMapperGenerated>(); - UserLogicEndpointDecoder<CHARGESUM> dec(feeId, fee2solar, handlePacket(results)); + DecodedDataHandlers handlers; + handlers.sampaChannelHandler = handlePacket(results); + handlers.sampaErrorHandler = handleError(results); + UserLogicEndpointDecoder<CHARGESUM> dec(feeId, fee2solar, handlers); dec.append(buffer); return results; } @@ -139,6 +217,27 @@ std::string testPayloadDecode(DsElecId ds1, return decodeBuffer<CHARGESUM>(feeId, payloadBuffer); } +std::string testPayloadDecodeCruPages(gsl::span<const uint64_t> page) +{ + auto solar2feelink = createSolar2FeeLinkMapper<ElectronicMapperGenerated>(); + + const void* rdhP = reinterpret_cast<const void*>(page.data()); + uint16_t feeId = o2::raw::RDHUtils::getFEEID(rdhP); + auto rdhSize = o2::raw::RDHUtils::getHeaderSize(rdhP); + auto payloadSize = o2::raw::RDHUtils::getMemorySize(rdhP) - rdhSize; + + gsl::span<const std::byte> buffer(reinterpret_cast<const std::byte*>(page.data()), page.size() * 8); + gsl::span<const std::byte> payloadBuffer = buffer.subspan(rdhSize, payloadSize); + + const uint16_t CRUID_MASK = 0xFF; + const uint16_t CHARGESUM_MASK = 0x100; + if (feeId & CHARGESUM_MASK) { + return decodeBuffer<ChargeSumMode>(feeId & CRUID_MASK, payloadBuffer); + } else { + return decodeBuffer<SampleMode>(feeId & CRUID_MASK, payloadBuffer); + } +} + BOOST_AUTO_TEST_SUITE(o2_mch_raw) BOOST_AUTO_TEST_SUITE(userlogicdsdecoder) @@ -227,5 +326,31 @@ BOOST_AUTO_TEST_CASE(SyncInTheMiddleChargeSumModeTwoChannels) "S361-J6-DS2-ch-63-ts-346-q-789012-cs-345\n"); } +BOOST_AUTO_TEST_CASE(TestCruPageOK) +{ + gsl::span<const uint64_t> page = CruPageOK; + std::string r = testPayloadDecodeCruPages(page); + BOOST_CHECK_EQUAL(r, + "S81-J0-DS0-ch-42-ts-87-q-2-1-0-4-4-3-3-0-0-1-0-0-0\n" + "S81-J0-DS0-ch-42-ts-0-q-1\n"); +} + +BOOST_AUTO_TEST_CASE(TestCruPageBadClusterSize) +{ + gsl::span<const uint64_t> page = CruPageBadClusterSize; + std::string r = testPayloadDecodeCruPages(page); + BOOST_CHECK_EQUAL(r, + fmt::format("S81-J0-DS0-chip-1-error-{}\nS81-J0-DS0-ch-42-ts-0-q-1\n", ErrorBadClusterSize)); +} + +BOOST_AUTO_TEST_CASE(TestCruPageBadN10bitWords) +{ + gsl::span<const uint64_t> page = CruPageBadN10bitWords; + std::string r = testPayloadDecodeCruPages(page); + BOOST_CHECK_EQUAL(r, + fmt::format("S81-J0-DS0-ch-42-ts-87-q-2-1-0-0-1-0-0-0\nS81-J0-DS0-chip-1-error-{}\nS81-J0-DS0-ch-42-ts-0-q-1\n", + ErrorBadIncompleteWord)); +} + BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END() diff --git a/Detectors/MUON/MCH/Raw/Tools/rawdump.cxx b/Detectors/MUON/MCH/Raw/Tools/rawdump.cxx index 2f5a5a3380647..3b2846c51c4d0 100644 --- a/Detectors/MUON/MCH/Raw/Tools/rawdump.cxx +++ b/Detectors/MUON/MCH/Raw/Tools/rawdump.cxx @@ -177,7 +177,9 @@ std::map<std::string, ChannelStat> rawdump(std::string input, DumpOptions opt) npages++; bytesRead += in.gcount(); if (!decode) { - decode = createPageDecoder(page, channelHandler); + DecodedDataHandlers handlers; + handlers.sampaChannelHandler = channelHandler; + decode = createPageDecoder(page, handlers); } patchPage(buffer); decode(page); diff --git a/Detectors/MUON/MCH/Raw/test/testClosureCoDec.cxx b/Detectors/MUON/MCH/Raw/test/testClosureCoDec.cxx index e5727cdc8acee..08ab1a50947bb 100644 --- a/Detectors/MUON/MCH/Raw/test/testClosureCoDec.cxx +++ b/Detectors/MUON/MCH/Raw/test/testClosureCoDec.cxx @@ -134,7 +134,9 @@ bool testDecode(gsl::span<const std::byte> testBuffer, gsl::span<std::string> ex { std::vector<std::string> result; - auto pageDecoder = createPageDecoder(testBuffer, handlePacketStoreAsVec(result)); + DecodedDataHandlers handlers; + handlers.sampaChannelHandler = handlePacketStoreAsVec(result); + auto pageDecoder = createPageDecoder(testBuffer, handlers); auto parser = createPageParser(); diff --git a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx index e763d202f1d66..b13c9e0b0cb81 100644 --- a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx @@ -8,7 +8,6 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// /// /// \file DatDecoderSpec.cxx /// \author Andrea Ferrero @@ -32,16 +31,16 @@ #include "Framework/Task.h" #include "Framework/WorkflowSpec.h" +#include "Headers/RAWDataHeader.h" +#include "DetectorsRaw/RDHUtils.h" #include "DPLUtils/DPLRawParser.h" + #include "MCHBase/Digit.h" -#include "Headers/RAWDataHeader.h" #include "MCHRawCommon/DataFormats.h" -#include "MCHRawDecoder/OrbitInfo.h" -#include "MCHRawDecoder/PageDecoder.h" +#include "MCHRawDecoder/DataDecoder.h" #include "MCHRawElecMap/Mapper.h" #include "MCHMappingInterface/Segmentation.h" #include "MCHWorkflow/DataDecoderSpec.h" -#include "DetectorsRaw/RDHUtils.h" namespace o2 { @@ -55,190 +54,28 @@ using namespace o2::framework; using namespace o2::mch::mapping; using RDH = o2::header::RDHAny; -std::array<int, 64> refManu2ds_st345 = { - 63, 62, 61, 60, 59, 57, 56, 53, 51, 50, 47, 45, 44, 41, 38, 35, - 36, 33, 34, 37, 32, 39, 40, 42, 43, 46, 48, 49, 52, 54, 55, 58, - 7, 8, 5, 2, 6, 1, 3, 0, 4, 9, 10, 15, 17, 18, 22, 25, - 31, 30, 29, 28, 27, 26, 24, 23, 20, 21, 16, 19, 12, 14, 11, 13}; -std::array<int, 64> refDs2manu_st345; - -int manu2ds(int i) -{ - return refManu2ds_st345[i]; -} - -int ds2manu(int i) -{ - return refDs2manu_st345[i]; -} - -// custom hash can be a standalone function object: -struct OrbitInfoHash { - std::size_t operator()(OrbitInfo const& info) const noexcept - { - return std::hash<uint64_t>{}(info.get()); - } -}; - //======================= // Data decoder class DataDecoderTask { - private: - void decodeBuffer(gsl::span<const std::byte> page, std::vector<o2::mch::Digit>& digits) - { - size_t ndigits{0}; - - uint32_t orbit; - - auto channelHandler = [&](DsElecId dsElecId, uint8_t channel, o2::mch::raw::SampaCluster sc) { - if (mDs2manu) { - channel = ds2manu(int(channel)); - } - if (mPrint) { - auto s = asString(dsElecId); - auto ch = fmt::format("{}-CH{}", s, channel); - std::cout << "dsElecId: " << ch << std::endl; - } - uint32_t digitadc(0); - if (sc.isClusterSum()) { - digitadc = sc.chargeSum; - } else { - for (auto& s : sc.samples) { - digitadc += s; - } - } - - int deId{-1}; - int dsIddet{-1}; - if (auto opt = mElec2Det(dsElecId); opt.has_value()) { - DsDetId dsDetId = opt.value(); - dsIddet = dsDetId.dsId(); - deId = dsDetId.deId(); - } - if (mPrint) { - std::cout << "deId " << deId << " dsIddet " << dsIddet << " channel " << (int)channel << std::endl; - } - - if (deId < 0 || dsIddet < 0) { - return; - } - - int padId = -1; - try { - const Segmentation& segment = segmentation(deId); - padId = segment.findPadByFEE(dsIddet, int(channel)); - if (mPrint) { - std::cout << "DS " << (int)dsElecId.elinkId() << " CHIP " << ((int)channel) / 32 << " CH " << ((int)channel) % 32 << " ADC " << digitadc << " DE# " << deId << " DSid " << dsIddet << " PadId " << padId << std::endl; - } - } catch (const std::exception& e) { - std::cout << "Failed to get padId: " << e.what() << std::endl; - return; - } - - Digit::Time time; - time.sampaTime = sc.sampaTime; - time.bunchCrossing = sc.bunchCrossing; - time.orbit = orbit; - - digits.emplace_back(o2::mch::Digit(deId, padId, digitadc, time, sc.nofSamples())); - - if (mPrint) { - std::cout << "DIGIT STORED:\nADC " << digits.back().getADC() << " DE# " << digits.back().getDetID() << " PadId " << digits.back().getPadID() << " time " << digits.back().getTime().sampaTime << std::endl; - } - ++ndigits; - }; - - const auto patchPage = [&](gsl::span<const std::byte> rdhBuffer) { - auto& rdhAny = *reinterpret_cast<RDH*>(const_cast<std::byte*>(&(rdhBuffer[0]))); - mNrdhs++; - auto cruId = o2::raw::RDHUtils::getCRUID(rdhAny) & 0xFF; - auto flags = o2::raw::RDHUtils::getCRUID(rdhAny) & 0xFF00; - auto endpoint = o2::raw::RDHUtils::getEndPointID(rdhAny); - auto feeId = cruId * 2 + endpoint + flags; - auto linkId = o2::raw::RDHUtils::getLinkID(rdhAny); - o2::raw::RDHUtils::setFEEID(rdhAny, feeId); - orbit = o2::raw::RDHUtils::getHeartBeatOrbit(rdhAny); - if (mPrint) { - std::cout << mNrdhs << "--\n"; - o2::raw::RDHUtils::printRDH(rdhAny); - } - }; - - patchPage(page); - - // add orbit to vector if not present yet - mOrbits.emplace(page); - - if (!mDecoder) { - mDecoder = mFee2Solar ? o2::mch::raw::createPageDecoder(page, channelHandler, mFee2Solar) - : o2::mch::raw::createPageDecoder(page, channelHandler); - } - mDecoder(page); - } - - private: - std::string readFileContent(const std::string& filename) - { - std::string content; - std::string s; - std::ifstream in(filename); - while (std::getline(in, s)) { - content += s; - content += " "; - } - return content; - } - - void initElec2DetMapper(const std::string& filename) - { - if (filename.empty()) { - mElec2Det = createElec2DetMapper<ElectronicMapperGenerated>(); - } else { - ElectronicMapperString::sFecMap = readFileContent(filename); - mElec2Det = createElec2DetMapper<ElectronicMapperString>(); - } - } - - void initFee2SolarMapper(const std::string& filename) - { - if (filename.empty()) { - mFee2Solar = createFeeLink2SolarMapper<ElectronicMapperGenerated>(); - } else { - ElectronicMapperString::sCruMap = readFileContent(filename); - mFee2Solar = createFeeLink2SolarMapper<ElectronicMapperString>(); - } - } - public: //_________________________________________________________________________________________________ void init(framework::InitContext& ic) { - mNrdhs = 0; + SampaChannelHandler channelHandler; + RdhHandler rdhHandler; - for (int i = 0; i < 64; i++) { - for (int j = 0; j < 64; j++) { - if (refManu2ds_st345[j] != i) { - continue; - } - refDs2manu_st345[i] = j; - break; - } - } - - mDs2manu = ic.options().get<bool>("ds2manu"); + auto ds2manu = ic.options().get<bool>("ds2manu"); mPrint = ic.options().get<bool>("print"); - auto mapCRUfile = ic.options().get<std::string>("cru-map"); auto mapFECfile = ic.options().get<std::string>("fec-map"); - initFee2SolarMapper(mapCRUfile); - initElec2DetMapper(mapFECfile); + mDecoder = new DataDecoder(channelHandler, rdhHandler, mapCRUfile, mapFECfile, ds2manu, mPrint); } //_________________________________________________________________________________________________ - void - decodeTF(framework::ProcessingContext& pc, std::vector<o2::mch::Digit>& digits) + // the decodeTF() function processes the the messages generated by the (sub)TimeFrame builder + void decodeTF(framework::ProcessingContext& pc) { // get the input buffer auto& inputs = pc.inputs(); @@ -253,12 +90,13 @@ class DataDecoderTask } gsl::span<const std::byte> buffer(reinterpret_cast<const std::byte*>(raw), sizeof(RDH) + payloadSize); - decodeBuffer(buffer, digits); + mDecoder->decodeBuffer(buffer); } } //_________________________________________________________________________________________________ - void decodeReadout(const o2::framework::DataRef& input, std::vector<o2::mch::Digit>& digits) + // the decodeReadout() function processes the messages generated by o2-mch-cru-page-reader-workflow + void decodeReadout(const o2::framework::DataRef& input) { static int nFrame = 1; // get the input buffer @@ -284,29 +122,12 @@ class DataDecoderTask } gsl::span<const std::byte> buffer(reinterpret_cast<const std::byte*>(raw), payloadSize); - decodeBuffer(buffer, digits); + mDecoder->decodeBuffer(buffer); } //_________________________________________________________________________________________________ void run(framework::ProcessingContext& pc) { - std::vector<o2::mch::Digit> digits; - - mOrbits.clear(); - - decodeTF(pc, digits); - for (auto&& input : pc.inputs()) { - if (input.spec->binding == "readout") { - decodeReadout(input, digits); - } - } - - if (mPrint) { - for (auto d : digits) { - std::cout << " DE# " << d.getDetID() << " PadId " << d.getPadID() << " ADC " << d.getADC() << " time " << d.getTime().sampaTime << std::endl; - } - } - auto createBuffer = [&](auto& vec, size_t& size) { size = vec.empty() ? 0 : sizeof(*(vec.begin())) * vec.size(); char* buf = nullptr; @@ -324,10 +145,25 @@ class DataDecoderTask return buf; }; + mDecoder->reset(); + decodeTF(pc); + for (auto&& input : pc.inputs()) { + if (input.spec->binding == "readout") + decodeReadout(input); + } + + auto& digits = mDecoder->getOutputDigits(); + auto& orbits = mDecoder->getOrbits(); + + if (mPrint) { + for (auto d : digits) { + std::cout << " DE# " << d.getDetID() << " PadId " << d.getPadID() << " ADC " << d.getADC() << " time " << d.getTime().sampaTime << std::endl; + } + } // send the output buffer via DPL size_t digitsSize, orbitsSize; char* digitsBuffer = createBuffer(digits, digitsSize); - char* orbitsBuffer = createBuffer(mOrbits, orbitsSize); + char* orbitsBuffer = createBuffer(orbits, orbitsSize); // create the output message auto freefct = [](void* data, void*) { free(data); }; @@ -336,16 +172,9 @@ class DataDecoderTask } private: - Elec2DetMapper mElec2Det{nullptr}; - FeeLink2SolarMapper mFee2Solar{nullptr}; - o2::mch::raw::PageDecoder mDecoder; - size_t mNrdhs{0}; - std::unordered_set<OrbitInfo, OrbitInfoHash> mOrbits; ///< list of orbits in the processed buffer - - std::ifstream mInputFile{}; ///< input file - bool mDs2manu = false; ///< print convert channel numbering from Run3 to Run1-2 order - bool mPrint = false; ///< print digits -}; // namespace raw + bool mPrint = {false}; + DataDecoder* mDecoder = {nullptr}; +}; //_________________________________________________________________________________________________ o2::framework::DataProcessorSpec getDecodingSpec(std::string inputSpec) From 4db21509fe8a370ff1fadceb7453302b285022f8 Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Wed, 2 Dec 2020 09:33:12 +0100 Subject: [PATCH 1576/1751] [MCH] Fixed clang errors --- Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx | 2 +- Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx b/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx index f3c4032cbaa32..e5c99d99cae7d 100644 --- a/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx +++ b/Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx @@ -26,7 +26,7 @@ uint16_t CHARGESUM_MASK = 0x100; template <typename FORMAT, typename CHARGESUM> struct PayloadDecoderImpl { - using type = struct { + using type = struct PayloadDecoderImplReturnType { void process(uint32_t, gsl::span<const std::byte>); }; diff --git a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx index b13c9e0b0cb81..015849586713a 100644 --- a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx @@ -148,8 +148,9 @@ class DataDecoderTask mDecoder->reset(); decodeTF(pc); for (auto&& input : pc.inputs()) { - if (input.spec->binding == "readout") + if (input.spec->binding == "readout") { decodeReadout(input); + } } auto& digits = mDecoder->getOutputDigits(); From 753b9a229bf9ec0f6ef721227cf0c9b0a78d513e Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Sun, 6 Dec 2020 14:46:23 +0100 Subject: [PATCH 1577/1751] [MCH] triggered CI builds --- Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx index 015849586713a..d39028bebf1dc 100644 --- a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx @@ -15,6 +15,7 @@ /// \brief Implementation of a data processor to run the raw decoding /// + #include <random> #include <iostream> #include <fstream> From b82cdda3ad569f2555b2422faa420cd7653814e9 Mon Sep 17 00:00:00 2001 From: aferrero2707 <aferrero1975@gmail.com> Date: Sun, 6 Dec 2020 16:58:49 +0100 Subject: [PATCH 1578/1751] [MCH] fixed clang format error --- Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx index d39028bebf1dc..015849586713a 100644 --- a/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx @@ -15,7 +15,6 @@ /// \brief Implementation of a data processor to run the raw decoding /// - #include <random> #include <iostream> #include <fstream> From dca327aa1f7e3bfdeb161b4c4508e8db3cadd59b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Dec 2020 11:16:13 +0100 Subject: [PATCH 1579/1751] DPL GUI: add buttons to debug / profile the driver --- Framework/Core/src/FrameworkGUIDebugger.cxx | 49 ++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/Core/src/FrameworkGUIDebugger.cxx index f7a173b0e647e..9d4fd274e7782 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/Core/src/FrameworkGUIDebugger.cxx @@ -8,11 +8,6 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/FrameworkGUIDebugger.h" -#include <algorithm> -#include <iostream> -#include <set> -#include <string> -#include <cinttypes> #include "Framework/ConfigContext.h" #include "Framework/ConfigParamRegistry.h" #include "DebugGUI/imgui.h" @@ -26,6 +21,14 @@ #include "Framework/PaletteHelpers.h" #include "Framework/FrameworkGUIState.h" +#include <fmt/format.h> + +#include <algorithm> +#include <iostream> +#include <set> +#include <string> +#include <cinttypes> + // Simplify debugging template class std::vector<o2::framework::DeviceMetricsInfo>; @@ -734,6 +737,42 @@ void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverContro if (ImGui::Button("SIGCONT all children")) { kill(0, SIGCONT); } + ImGui::SameLine(); + if (ImGui::Button("Debug driver")) { + std::string pidStr = std::to_string(pid); + setenv("O2DEBUGGEDPID", pidStr.c_str(), 1); +#ifdef __APPLE__ + std::string defaultAppleDebugCommand = + "osascript -e 'tell application \"Terminal\" to activate'" + " -e 'tell application \"Terminal\" to do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\")'"; + setenv("O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0); +#else + setenv("O2DPLDEBUG", "xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0); +#endif + int retVal = system(getenv("O2DPLDEBUG")); + (void)retVal; + } + + ImGui::SameLine(); + if (ImGui::Button("Profile")) { + std::string pidStr = std::to_string(pid); + setenv("O2PROFILEDPID", pidStr.c_str(), 1); +#ifdef __APPLE__ + auto defaultAppleProfileCommand = fmt::format( + "osascript -e 'tell application \"Terminal\" to activate'" + " -e 'tell application \"Terminal\" to do script \"xcrun xctrace record --output dpl-profile-{}.trace" + " --time-limit 30s --template Time\\\\ Profiler --attach {} " + " && open dpl-profile-{}.trace && exit\"'" + " && open dpl-driver-profile-{}.trace", + pid, pid, pid, pid); + std::cout << defaultAppleProfileCommand << std::endl; + setenv("O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0); +#else + setenv("O2DPLPROFILE", "xterm -hold -e perf record -a -g -p $O2PROFILEDPID > perf-$O2PROFILEDPID.data &", 0); +#endif + int retVal = system(getenv("O2DPLPROFILE")); + (void)retVal; + } for (size_t i = 0; i < driverInfo.states.size(); ++i) { ImGui::Text("#%lu: %s", i, DriverHelper::stateToString(driverInfo.states[i])); From ee680a78e091c13a018a7dc47467acc9d8e3cb64 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 6 Dec 2020 16:37:05 +0100 Subject: [PATCH 1580/1751] Explicit copy c-tors for DCS data classes --- .../DetectorsDCS/DataPointCompositeObject.h | 32 +++++++++++++++++++ .../DetectorsDCS/DataPointIdentifier.h | 28 ++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h b/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h index c2b5f848bb858..525a74bb9edc3 100644 --- a/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h +++ b/Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h @@ -79,6 +79,19 @@ struct alignas(128) DataPointCompositeObject final { const DataPointIdentifier& id, const DataPointValue& data) noexcept : id(id), data(data) {} + /** + * Copy constructor + */ + DataPointCompositeObject(const DataPointCompositeObject& src) noexcept : DataPointCompositeObject(src.id, src.data) {} + + DataPointCompositeObject& operator=(const DataPointCompositeObject& src) noexcept + { + if (&src != this) { + memcpy(this, &src, sizeof(DataPointCompositeObject)); + } + return *this; + } + /** * Bit-by bit equality comparison of DataPointCompositeObjects. * @@ -278,6 +291,25 @@ template <typename T> T getValue(const DataPointCompositeObject& dpcom); } // namespace dcs + +/// Defining DataPointCompositeObject explicitly as messageable +namespace framework +{ +template <typename T> +struct is_messageable; +template <> +struct is_messageable<o2::dcs::DataPointCompositeObject> : std::true_type { +}; +} // namespace framework + } // namespace o2 +/// Defining DataPointCompositeObject explicitly as copiable +namespace std +{ +template <> +struct is_trivially_copyable<o2::dcs::DataPointCompositeObject> : std::true_type { +}; +} // namespace std + #endif /* O2_DCS_DATAPOINT_COMPOSITE_OBJECT_H */ diff --git a/Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h b/Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h index a5ace31a62e17..258238c69f9b7 100644 --- a/Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h +++ b/Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h @@ -79,6 +79,19 @@ class alignas(64) DataPointIdentifier final ((char*)&pt8)[7] = type; } + /** + * A copy constructor for DataPointIdentifier. + */ + DataPointIdentifier(const DataPointIdentifier& src) noexcept : DataPointIdentifier(src.pt1, src.pt2, src.pt3, src.pt4, src.pt5, src.pt6, src.pt7, src.pt8) {} + + DataPointIdentifier& operator=(const DataPointIdentifier& src) noexcept + { + if (&src != this) { + memcpy(this, &src, sizeof(DataPointIdentifier)); + } + return *this; + } + /** * This stati procedure fills the given DataPointIdentifier object with * the given parameters. @@ -202,6 +215,16 @@ struct DPIDHash { }; } // namespace dcs +/// Defining DataPointIdentifier explicitly as messageable +namespace framework +{ +template <typename T> +struct is_messageable; +template <> +struct is_messageable<o2::dcs::DataPointIdentifier> : std::true_type { +}; +} // namespace framework + } // namespace o2 // specailized std::hash @@ -214,6 +237,11 @@ struct hash<o2::dcs::DataPointIdentifier> { return std::hash<uint64_t>{}(dpid.hash_code()); } }; + +template <> +struct is_trivially_copyable<o2::dcs::DataPointIdentifier> : std::true_type { +}; + } // namespace std #endif /* O2_DCS_DATAPOINT_IDENTIFIER_H */ From 1584aff5222ca91a8f7f0dd4ba4c1971a34ff299 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 6 Dec 2020 16:38:21 +0100 Subject: [PATCH 1581/1751] Remove workaround in DCStoDPLconverter --- Detectors/DCS/testWorkflow/DCStoDPLconverter.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Detectors/DCS/testWorkflow/DCStoDPLconverter.h b/Detectors/DCS/testWorkflow/DCStoDPLconverter.h index abca7b51716c6..8b74f07c3ea26 100644 --- a/Detectors/DCS/testWorkflow/DCStoDPLconverter.h +++ b/Detectors/DCS/testWorkflow/DCStoDPLconverter.h @@ -61,17 +61,14 @@ o2f::InjectorFunction dcs2dpl(std::unordered_map<DPID, o2h::DataDescription>& dp for (size_t i = 0; i < parts.Size(); ++i) { // DCS sends only 1 part, but we should be able to receive more auto nDPCOM = parts.At(i)->GetSize() / sizeof(DPCOM); // number of DPCOM in current part for (size_t j = 0; j < nDPCOM; j++) { - DPCOM src; - memcpy(&src, reinterpret_cast<char*>(parts.At(i)->GetData()) + j * sizeof(DPCOM), sizeof(DPCOM)); - // const auto* src = reinterpret_cast<const DPCOM*>(parts.At(i)->GetData()) + j; + const auto& src = *(reinterpret_cast<const DPCOM*>(parts.At(i)->GetData()) + j); // do we want to check if this DP was requested ? auto mapEl = dpid2group.find(src.id); if (verbose) { LOG(INFO) << "Received DP " << src.id << " (data = " << src.data << "), matched to output-> " << (mapEl == dpid2group.end() ? "none " : mapEl->second.as<std::string>()); } if (mapEl != dpid2group.end()) { - auto& dst = cache[src.id]; // this is needed in case in the 1s window we get a new value for the same DP - memcpy(&dst, &src, sizeof(DPCOM)); + auto& dst = cache[src.id] = src; // this is needed in case in the 1s window we get a new value for the same DP } } } From d2b0c3de371c1c55e3f94ad6675d62f7798f1d1e Mon Sep 17 00:00:00 2001 From: nburmaso <nazar.burmasov@cern.ch> Date: Tue, 8 Dec 2020 17:09:39 +0300 Subject: [PATCH 1582/1751] Fix for MCTruth label checks --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index b6bef4b60c87d..891300b19b611 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -534,16 +534,21 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) // bit 13 -- ITS and TPC labels are not equal // bit 14 -- isNoise() == true // bit 15 -- isFake() == true + // labelID = std::numeric_limits<uint32_t>::max() -- label is not set + + uint32_t labelID; + uint32_t labelITS; + uint32_t labelTPC; + uint16_t labelMask; if (mFillTracksITS) { fillTracksTable(tracksITS, vCollRefsITS, tracksCursor, o2::vertexing::GIndex::Source::ITS); // fTrackType = 1 for (auto& mcTruthITS : tracksITSMCTruth) { - uint32_t labelID = std::numeric_limits<uint32_t>::max(); + labelID = std::numeric_limits<uint32_t>::max(); // TODO: // fill label mask - uint16_t labelMask = 0; - int nEventsITS = mcReader.getNEvents(mcTruthITS.getSourceID()); - if (mcTruthITS.getEventID() < mcReader.getNEvents(mcTruthITS.getSourceID())) { + labelMask = 0; + if (mcTruthITS.isValid()) { labelID = mIDsToIndex.at(std::make_tuple(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); } if (mcTruthITS.isFake()) { @@ -561,12 +566,11 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) if (mFillTracksTPC) { fillTracksTable(tracksTPC, vCollRefsTPC, tracksCursor, o2::vertexing::GIndex::Source::TPC); // fTrackType = 2 for (auto& mcTruthTPC : tracksTPCMCTruth) { - uint32_t labelID = std::numeric_limits<uint32_t>::max(); + labelID = std::numeric_limits<uint32_t>::max(); // TODO: // fill label mask - uint16_t labelMask = 0; - int nEventsTPC = mcReader.getNEvents(mcTruthTPC.getSourceID()); - if (mcTruthTPC.getEventID() < nEventsTPC) { + labelMask = 0; + if (mcTruthTPC.isValid()) { labelID = mIDsToIndex.at(std::make_tuple(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); } if (mcTruthTPC.isFake()) { @@ -586,16 +590,14 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) for (int i = 0; i < tracksITSTPC.size(); i++) { auto& mcTruthITS = tracksITSTPC_ITSMC[i]; auto& mcTruthTPC = tracksITSTPC_TPCMC[i]; - uint32_t labelID = std::numeric_limits<uint32_t>::max(); - uint32_t labelITS = std::numeric_limits<uint32_t>::max(); - uint32_t labelTPC = std::numeric_limits<uint32_t>::max(); + labelID = std::numeric_limits<uint32_t>::max(); + labelITS = std::numeric_limits<uint32_t>::max(); + labelTPC = std::numeric_limits<uint32_t>::max(); // TODO: // fill label mask // currently using label mask to indicate labelITS != labelTPC - uint16_t labelMask = 0; - int nEventsITS = mcReader.getNEvents(mcTruthITS.getSourceID()); - int nEventsTPC = mcReader.getNEvents(mcTruthTPC.getSourceID()); - if (mcTruthITS.getEventID() < nEventsITS && mcTruthTPC.getEventID() < nEventsTPC) { + labelMask = 0; + if (mcTruthITS.isValid() && mcTruthTPC.isValid()) { labelITS = mIDsToIndex.at(std::make_tuple(mcTruthITS.getSourceID(), mcTruthITS.getEventID(), mcTruthITS.getTrackID())); labelTPC = mIDsToIndex.at(std::make_tuple(mcTruthTPC.getSourceID(), mcTruthTPC.getEventID(), mcTruthTPC.getTrackID())); labelID = labelITS; From c71d440c096a3de5bf54e763beb1a725a376d22d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Dec 2020 15:01:30 +0100 Subject: [PATCH 1583/1751] DPL: better error message when DPL_ENABLE_STACKTRACE not set --- Framework/Core/src/runDataProcessing.cxx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index da67950c671fd..14cf34c83f73d 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -812,9 +812,14 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, const o2::f << boost::current_exception_diagnostic_information(true); return 1; } catch (o2::framework::RuntimeErrorRef e) { - LOG(ERROR) << "Unhandled o2::framework::runtime_error reached the top of main, device shutting down. Details follow: \n"; auto& err = o2::framework::error_from_ref(e); - backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); + if (err.maxBacktrace != 0) { + LOG(ERROR) << "Unhandled o2::framework::runtime_error reached the top of main, device shutting down. Details follow: \n"; + backtrace_symbols_fd(err.backtrace, err.maxBacktrace, STDERR_FILENO); + } else { + LOG(ERROR) << "Unhandled o2::framework::runtime_error reached the top of main, device shutting down." + " Recompile with DPL_ENABLE_BACKTRACE=1 to get more information."; + } return 1; } catch (std::exception& e) { LOG(ERROR) << "Unhandled std::exception reached the top of main: " << e.what() << ", device shutting down."; From 8fbf7d0ad0fa369523509d0c697169f0eb2677e2 Mon Sep 17 00:00:00 2001 From: Victor Gonzalez <victor.gonzalez@cern.ch> Date: Tue, 8 Dec 2020 20:05:58 +0100 Subject: [PATCH 1584/1751] Getting prepared for boolean columns (#5025) The internal boolean columns implementation has been changed to mimic the track selection one to easy the transition to actual full support of boolean columns Also the configuration parameters have been moved back to the main output list --- Analysis/Tasks/PWGCF/dptdptcorrelations.cxx | 126 +++++++++----------- 1 file changed, 54 insertions(+), 72 deletions(-) diff --git a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx index f076295d2cb7b..2f11edb496b7f 100644 --- a/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx +++ b/Analysis/Tasks/PWGCF/dptdptcorrelations.cxx @@ -87,10 +87,6 @@ int tracktwocharge = -1; bool processpairs = false; std::string fTaskConfigurationString = "PendingToConfigure"; -/* while we don't have proper bool columnst */ -uint8_t DPTDPT_TRUE = 1; -uint8_t DPTDPT_FALSE = 0; - /// \enum SystemType /// \brief The type of the system under analysis enum SystemType { @@ -230,20 +226,20 @@ bool matchTrackType(aod::TrackData const& track) } } -inline void AcceptTrack(aod::TrackData const& track, uint8_t& asone, uint8_t& astwo) +inline void AcceptTrack(aod::TrackData const& track, bool& asone, bool& astwo) { - asone = DPTDPT_FALSE; - astwo = DPTDPT_FALSE; + asone = false; + astwo = false; /* TODO: incorporate a mask in the scanned tracks table for the rejecting track reason */ if (matchTrackType(track)) { if (ptlow < track.pt() and track.pt() < ptup and etalow < track.eta() and track.eta() < etaup) { if (((track.charge() > 0) and (trackonecharge > 0)) or ((track.charge() < 0) and (trackonecharge < 0))) { - asone = DPTDPT_TRUE; + asone = true; } if (((track.charge() > 0) and (tracktwocharge > 0)) or ((track.charge() < 0) and (tracktwocharge < 0))) { - astwo = DPTDPT_TRUE; + astwo = true; } } } @@ -302,7 +298,6 @@ struct DptDptCorrelationsFilterAnalysisTask { "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsGlobalInfo", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TFolder> fConfOutput{"DptDptCorrelationsGlobalConfiguration", OutputObjHandlingPolicy::AnalysisObject}; Produces<aod::AcceptedEvents> acceptedevents; Produces<aod::ScannedTracks> scannedtracks; @@ -336,21 +331,16 @@ struct DptDptCorrelationsFilterAnalysisTask { /* if the system type is not known at this time, we have to put the initalization somewhere else */ fSystem = getSystemType(); - /* create the configuration folder which will own the task configuration parameters */ - TFolder* fOutputFolder = new TFolder("DptDptCorrelationsGlobalConfigurationFolder", "DptDptCorrelationsGlobalConfigurationFolder"); - fOutputFolder->SetOwner(true); - fConfOutput.setObject(fOutputFolder); - - /* incorporate configuration parameters to the output */ - fOutputFolder->Add(new TParameter<Int_t>("TrackType", cfgTrackType, 'f')); - fOutputFolder->Add(new TParameter<Int_t>("TrackOneCharge", cfgTrackOneCharge, 'f')); - fOutputFolder->Add(new TParameter<Int_t>("TrackTwoCharge", cfgTrackTwoCharge, 'f')); - /* create the output list which will own the task histograms */ TList* fOutputList = new TList(); fOutputList->SetOwner(true); fOutput.setObject(fOutputList); + /* incorporate configuration parameters to the output */ + fOutputList->Add(new TParameter<Int_t>("TrackType", cfgTrackType, 'f')); + fOutputList->Add(new TParameter<Int_t>("TrackOneCharge", cfgTrackOneCharge, 'f')); + fOutputList->Add(new TParameter<Int_t>("TrackTwoCharge", cfgTrackTwoCharge, 'f')); + /* create the histograms */ if (fSystem > kPbp) { fhCentMultB = new TH1F("CentralityB", "Centrality before cut; centrality (%)", 100, 0, 100); @@ -407,10 +397,10 @@ struct DptDptCorrelationsFilterAnalysisTask { // LOGF(INFO,"New collision with %d filtered tracks", ftracks.size()); fhCentMultB->Fill(collision.centV0M()); fhVertexZB->Fill(collision.posZ()); - int acceptedevent = DPTDPT_FALSE; + bool acceptedevent = false; float centormult = -100.0; if (IsEvtSelected(collision, centormult)) { - acceptedevent = DPTDPT_TRUE; + acceptedevent = true; fhCentMultA->Fill(collision.centV0M()); fhVertexZA->Fill(collision.posZ()); // LOGF(INFO,"New accepted collision with %d filtered tracks", ftracks.size()); @@ -430,9 +420,9 @@ struct DptDptCorrelationsFilterAnalysisTask { /* track selection */ /* tricky because the boolean columns issue */ - uint8_t asone, astwo; + bool asone, astwo; AcceptTrack(track, asone, astwo); - if ((asone == DPTDPT_TRUE) or (astwo == DPTDPT_TRUE)) { + if (asone or astwo) { /* the track has been accepted */ fhPtA->Fill(track.pt()); fhEtaA->Fill(track.eta()); @@ -445,14 +435,14 @@ struct DptDptCorrelationsFilterAnalysisTask { fhPtNegA->Fill(track.pt()); } } - scannedtracks(asone, astwo); + scannedtracks((uint8_t)asone, (uint8_t)astwo); } } else { for (auto& track : ftracks) { - scannedtracks(DPTDPT_FALSE, DPTDPT_FALSE); + scannedtracks((uint8_t) false, (uint8_t) false); } } - acceptedevents(acceptedevent, centormult); + acceptedevents((uint8_t)acceptedevent, centormult); } }; @@ -470,13 +460,12 @@ struct DptDptCorrelationsTask { "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; OutputObj<TList> fOutput{"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}; - OutputObj<TFolder> fConfOutput{"DptDptCorrelationsConfiguration", OutputObjHandlingPolicy::AnalysisObject}; - Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); - Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); + Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == (uint8_t) true); + Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == (uint8_t) true) or (aod::dptdptcorrelations::trackacceptedastwo == (uint8_t) true)); - Partition<aod::FilteredTracks> Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE; - Partition<aod::FilteredTracks> Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE; + Partition<aod::FilteredTracks> Tracks1 = aod::dptdptcorrelations::trackacceptedasone == (uint8_t) true; + Partition<aod::FilteredTracks> Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == (uint8_t) true; DptDptCorrelationsTask(float cmmin, float cmmax, @@ -485,21 +474,19 @@ struct DptDptCorrelationsTask { {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}, OutputObj<TList> _fOutput = {"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject}, - OutputObj<TFolder> _fConfOutput = {"DptDptCorrelationsConfiguration", OutputObjHandlingPolicy::AnalysisObject}, - Filter _onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE), - Filter _onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)), - Partition<aod::FilteredTracks> _Tracks1 = aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE, - Partition<aod::FilteredTracks> _Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE) + Filter _onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == (uint8_t) true), + Filter _onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == (uint8_t) true) or (aod::dptdptcorrelations::trackacceptedastwo == (uint8_t) true)), + Partition<aod::FilteredTracks> _Tracks1 = aod::dptdptcorrelations::trackacceptedasone == (uint8_t) true, + Partition<aod::FilteredTracks> _Tracks2 = aod::dptdptcorrelations::trackacceptedastwo == (uint8_t) true) : fCentMultMin(cmmin), fCentMultMax(cmmax), cfgProcessPairs(_cfgProcessPairs), cfgBinning(_cfgBinning), fOutput(_fOutput), - fConfOutput(_fConfOutput), - onlyacceptedevents((aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE) and (aod::dptdptcorrelations::centmult > fCentMultMin) and (aod::dptdptcorrelations::centmult < fCentMultMax)), - onlyacceptedtracks((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)), - Tracks1(aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE), - Tracks2(aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE) + onlyacceptedevents((aod::dptdptcorrelations::eventaccepted == (uint8_t) true) and (aod::dptdptcorrelations::centmult > fCentMultMin) and (aod::dptdptcorrelations::centmult < fCentMultMax)), + onlyacceptedtracks((aod::dptdptcorrelations::trackacceptedasone == (uint8_t) true) or (aod::dptdptcorrelations::trackacceptedastwo == (uint8_t) true)), + Tracks1(aod::dptdptcorrelations::trackacceptedasone == (uint8_t) true), + Tracks2(aod::dptdptcorrelations::trackacceptedastwo == (uint8_t) true) { } @@ -526,35 +513,30 @@ struct DptDptCorrelationsTask { etabinwidth = (etaup - etalow) / float(etabins); phibinwidth = (phiup - philow) / float(phibins); - /* create the configuration folder which will own the task configuration parameters */ - TFolder* fOutputFolder = new TFolder("DptDptCorrelationsConfigurationFolder", "DptDptCorrelationsConfigurationFolder"); - fOutputFolder->SetOwner(true); - fConfOutput.setObject(fOutputFolder); + /* create the output list which will own the task output */ + TList* fOutputList = new TList(); + fOutputList->SetOwner(true); + fOutput.setObject(fOutputList); /* incorporate configuration parameters to the output */ - fOutputFolder->Add(new TParameter<Int_t>("NoBinsVertexZ", zvtxbins, 'f')); - fOutputFolder->Add(new TParameter<Int_t>("NoBinsPt", ptbins, 'f')); - fOutputFolder->Add(new TParameter<Int_t>("NoBinsEta", etabins, 'f')); - fOutputFolder->Add(new TParameter<Int_t>("NoBinsPhi", phibins, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MinVertexZ", zvtxlow, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MaxVertexZ", zvtxup, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MinPt", ptlow, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MaxPt", ptup, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MinEta", etalow, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MaxEta", etaup, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MinPhi", philow, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("MaxPhi", phiup, 'f')); - fOutputFolder->Add(new TParameter<Double_t>("PhiBinShift", phibinshift, 'f')); + fOutputList->Add(new TParameter<Int_t>("NoBinsVertexZ", zvtxbins, 'f')); + fOutputList->Add(new TParameter<Int_t>("NoBinsPt", ptbins, 'f')); + fOutputList->Add(new TParameter<Int_t>("NoBinsEta", etabins, 'f')); + fOutputList->Add(new TParameter<Int_t>("NoBinsPhi", phibins, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinVertexZ", zvtxlow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxVertexZ", zvtxup, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinPt", ptlow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxPt", ptup, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinEta", etalow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxEta", etaup, 'f')); + fOutputList->Add(new TParameter<Double_t>("MinPhi", philow, 'f')); + fOutputList->Add(new TParameter<Double_t>("MaxPhi", phiup, 'f')); + fOutputList->Add(new TParameter<Double_t>("PhiBinShift", phibinshift, 'f')); /* after the parameters dump the proper phi limits are set according to the phi shift */ phiup = phiup - phibinwidth * phibinshift; philow = philow - phibinwidth * phibinshift; - /* create the output list which will own the task histograms */ - TList* fOutputList = new TList(); - fOutputList->SetOwner(true); - fOutput.setObject(fOutputList); - /* create the histograms */ Bool_t oldstatus = TH1::AddDirectoryStatus(); TH1::AddDirectory(kFALSE); @@ -807,13 +789,13 @@ struct TracksAndEventClassificationQA { fSelectedEvents->GetXaxis()->SetBinLabel(2, "Selected events"); } - Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == DPTDPT_TRUE); - Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == DPTDPT_TRUE) or (aod::dptdptcorrelations::trackacceptedastwo == DPTDPT_TRUE)); + Filter onlyacceptedevents = (aod::dptdptcorrelations::eventaccepted == (uint8_t) true); + Filter onlyacceptedtracks = ((aod::dptdptcorrelations::trackacceptedasone == (uint8_t) true) or (aod::dptdptcorrelations::trackacceptedastwo == (uint8_t) true)); void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Cents, aod::AcceptedEvents>>::iterator const& collision, soa::Filtered<soa::Join<aod::Tracks, aod::ScannedTracks>> const& tracks) { - if (collision.eventaccepted() != DPTDPT_TRUE) { + if (collision.eventaccepted() != (uint8_t) true) { fSelectedEvents->Fill(0.5); } else { fSelectedEvents->Fill(1.5); @@ -824,20 +806,20 @@ struct TracksAndEventClassificationQA { int ntracks_one_and_two = 0; int ntracks_none = 0; for (auto& track : tracks) { - if ((track.trackacceptedasone() != DPTDPT_TRUE) and (track.trackacceptedastwo() != DPTDPT_TRUE)) { + if ((track.trackacceptedasone() != (uint8_t) true) and (track.trackacceptedastwo() != (uint8_t) true)) { ntracks_none++; } - if ((track.trackacceptedasone() == DPTDPT_TRUE) and (track.trackacceptedastwo() == DPTDPT_TRUE)) { + if ((track.trackacceptedasone() == (uint8_t) true) and (track.trackacceptedastwo() == (uint8_t) true)) { ntracks_one_and_two++; } - if (track.trackacceptedasone() == DPTDPT_TRUE) { + if (track.trackacceptedasone() == (uint8_t) true) { ntracks_one++; } - if (track.trackacceptedastwo() == DPTDPT_TRUE) { + if (track.trackacceptedastwo() == (uint8_t) true) { ntracks_two++; } } - if (collision.eventaccepted() != DPTDPT_TRUE) { + if (collision.eventaccepted() != (uint8_t) true) { /* control for non selected events */ fTracksOneUnsel->Fill(ntracks_one); fTracksTwoUnsel->Fill(ntracks_two); From 4558beb5aaa5e2873f872507580f486af58148b9 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 7 Dec 2020 16:10:53 +0100 Subject: [PATCH 1585/1751] GPU: Tune some kernel parameters for AMD Vega --- GPU/Common/GPUDefGPUParameters.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 3d5151b0c4d63..43c19f42fa2e2 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -34,7 +34,7 @@ #define GPUCA_LB_GPUTPCCreateSliceData 128 #define GPUCA_LB_GPUTPCStartHitsSorter 1024, 2 #define GPUCA_LB_GPUTPCStartHitsFinder 1024 - #define GPUCA_LB_GPUTPCTrackletConstructor 512, 1 + #define GPUCA_LB_GPUTPCTrackletConstructor 256, 2 #define GPUCA_LB_GPUTPCTrackletSelector 256, 8 #define GPUCA_LB_GPUTPCNeighboursFinder 1024, 1 #define GPUCA_LB_GPUTPCNeighboursCleaner 896 @@ -42,7 +42,7 @@ #define GPUCA_LB_GPUTPCCFDecodeZS 64, 4 #define GPUCA_LB_GPUTPCCFGather 1024, 1 #define GPUCA_LB_GPUTPCGMMergerTrackFit 64, 1 - #define GPUCA_LB_GPUTPCGMMergerFollowLoopers 256, 1, 200 + #define GPUCA_LB_GPUTPCGMMergerFollowLoopers 256, 4, 200 #define GPUCA_LB_GPUTPCGMMergerSliceRefit 256 #define GPUCA_LB_GPUTPCGMMergerUnpackResetIds 256 #define GPUCA_LB_GPUTPCGMMergerUnpackGlobal 256 @@ -68,8 +68,8 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_0 256 #define GPUCA_LB_GPUTPCGMMergerFinalize_1 256 #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 - #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 256 - #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512 + #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 192, 2 + #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 #define GPUCA_LB_COMPRESSION_GATHER 1024 #define GPUCA_LB_CLUSTER_FINDER 512 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 5 @@ -81,7 +81,10 @@ #define GPUCA_MERGER_SPLIT_LOOP_INTERPOLATION 1 #define GPUCA_TRACKLET_SELECTOR_SLICE_COUNT 1 #define GPUCA_NO_ATOMIC_PRECHECK 1 - #define GPUCA_COMP_GATHER_KERNEL 3 + #define GPUCA_DEDX_STORAGE_TYPE unsigned short + #define GPUCA_MERGER_INTERPOLATION_ERROR_TYPE half + #define GPUCA_COMP_GATHER_KERNEL 4 + #define GPUCA_COMP_GATHER_MODE 3 #elif defined(GPUCA_GPUTYPE_AMPERE) #define GPUCA_WARP_SIZE 32 #define GPUCA_THREAD_COUNT 512 From 8e24cc8d19a5facd1e584dc983cc95c084b691c8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Dec 2020 09:58:45 +0100 Subject: [PATCH 1586/1751] DPL: syntactic sugar for --clone <template>:<instance number> --- Framework/Core/src/runDataProcessing.cxx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 14cf34c83f73d..2b79f2ca1f629 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1408,7 +1408,17 @@ void overrideCloning(ConfigContext& ctx, WorkflowSpec& workflow) } auto key = token.substr(0, split); token.erase(0, split + 1); - auto value = token; + size_t error; + std::string value = ""; + try { + auto numValue = std::stoll(token, &error, 10); + if (token[error] != '\0') { + throw std::runtime_error("bad name for clone:" + token); + } + value = key + "_c" + std::to_string(numValue); + } catch (std::invalid_argument& e) { + value = token; + } specs.push_back({key, value}); s.erase(0, newPos + (newPos == std::string::npos ? 0 : 1)); } From acd9e5df901a07c2a88d341267c045106d06f65c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 9 Dec 2020 16:03:05 +0100 Subject: [PATCH 1587/1751] DPL: allow adding suffix to all dataprocessors in a workflow --- Framework/Core/include/Framework/runDataProcessing.h | 7 ++++++- Framework/Core/src/runDataProcessing.cxx | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 88eda05d03d48..d79e67bd42b38 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -105,6 +105,9 @@ void overridePipeline(o2::framework::ConfigContext& ctx, std::vector<o2::framewo /// Helper used to customize a workflow via a template data processor void overrideCloning(o2::framework::ConfigContext& ctx, std::vector<o2::framework::DataProcessorSpec>& workflow); +/// Helper used to customize the workflow via a global suffix. +void overrideSuffix(o2::framework::ConfigContext& ctx, std::vector<o2::framework::DataProcessorSpec>& workflow); + // This comes from the framework itself. This way we avoid code duplication. int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& specs, std::vector<o2::framework::ChannelConfigurationPolicy> const& channelPolicies, @@ -131,6 +134,7 @@ int main(int argc, char** argv) workflowOptions.push_back(ConfigParamSpec{"readers", VariantType::Int64, 1ll, {"number of parallel readers to use"}}); workflowOptions.push_back(ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}); workflowOptions.push_back(ConfigParamSpec{"clone", VariantType::String, "", {"clone processors from a template"}}); + workflowOptions.push_back(ConfigParamSpec{"workflow-suffix", VariantType::String, "", {"suffix to add to all dataprocessors"}}); // options for AOD rate limiting workflowOptions.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::Int64, 0LL, {"Rate limit AOD processing based on memory"}}); @@ -176,8 +180,9 @@ int main(int argc, char** argv) ConfigParamRegistry workflowOptionsRegistry(std::move(workflowOptionsStore)); ConfigContext configContext(workflowOptionsRegistry, argc, argv); o2::framework::WorkflowSpec specs = defineDataProcessing(configContext); - overridePipeline(configContext, specs); overrideCloning(configContext, specs); + overrideSuffix(configContext, specs); + overridePipeline(configContext, specs); for (auto& spec : specs) { UserCustomizationsHelper::userDefinedCustomization(spec.requiredServices, 0); } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 2b79f2ca1f629..d6952d3480f7b 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1388,6 +1388,17 @@ bool isOutputToPipe() return ((s.st_mode & S_IFIFO) != 0); } +void overrideSuffix(ConfigContext& ctx, WorkflowSpec& workflow) +{ + auto suffix = ctx.options().get<std::string>("workflow-suffix"); + if (suffix.empty()) { + return; + } + for (auto& processor : workflow) { + processor.name = processor.name + suffix; + } +} + void overrideCloning(ConfigContext& ctx, WorkflowSpec& workflow) { struct CloningSpec { From 79e18c12539dd7ff9e7cbc976f411954ff172a42 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <maximiliano.puccio@cern.ch> Date: Mon, 7 Dec 2020 10:34:52 +0100 Subject: [PATCH 1588/1751] NFC: Fix codechecker for the ITS GPU code --- .../cuda/include/ITStrackingCUDA/Array.h | 4 +- .../include/ITStrackingCUDA/ClusterLinesGPU.h | 4 +- .../cuda/include/ITStrackingCUDA/Context.h | 4 +- .../include/ITStrackingCUDA/DeviceStoreNV.h | 4 +- .../ITStrackingCUDA/DeviceStoreVertexerGPU.h | 14 ++-- .../ITStrackingCUDA/PrimaryVertexContextNV.h | 56 ++++++------- .../cuda/include/ITStrackingCUDA/Stream.h | 4 +- .../include/ITStrackingCUDA/UniquePointer.h | 4 +- .../cuda/include/ITStrackingCUDA/Utils.h | 4 +- .../cuda/include/ITStrackingCUDA/Vector.h | 4 +- .../ITStrackingCUDA/VertexerTraitsGPU.h | 8 +- .../ITS/tracking/cuda/src/ClusterLinesGPU.cu | 4 +- .../ITSMFT/ITS/tracking/cuda/src/Context.cu | 4 +- .../ITS/tracking/cuda/src/DeviceStoreNV.cu | 12 +-- .../cuda/src/DeviceStoreVertexerGPU.cu | 6 +- .../ITSMFT/ITS/tracking/cuda/src/Stream.cu | 4 +- .../ITS/tracking/cuda/src/TrackerTraitsNV.cu | 74 ++++++++--------- .../ITSMFT/ITS/tracking/cuda/src/Utils.cu | 4 +- .../tracking/cuda/src/VertexerTraitsGPU.cu | 80 +++++++++---------- .../hip/include/ITStrackingHIP/ArrayHIP.h | 4 +- .../include/ITStrackingHIP/ClusterLinesHIP.h | 4 +- .../hip/include/ITStrackingHIP/ContextHIP.h | 4 +- .../ITStrackingHIP/DeviceStoreVertexerHIP.h | 14 ++-- .../hip/include/ITStrackingHIP/StreamHIP.h | 4 +- .../include/ITStrackingHIP/UniquePointerHIP.h | 4 +- .../hip/include/ITStrackingHIP/UtilsHIP.h | 4 +- .../hip/include/ITStrackingHIP/VectorHIP.h | 4 +- .../ITStrackingHIP/VertexerTraitsHIP.h | 12 +-- .../tracking/hip/src/ClusterLinesHIP.hip.cxx | 4 +- .../ITS/tracking/hip/src/ContextHIP.hip.cxx | 4 +- .../hip/src/DeviceStoreVertexerHIP.hip.cxx | 6 +- .../ITS/tracking/hip/src/StreamHIP.hip.cxx | 4 +- .../ITS/tracking/hip/src/UtilsHIP.hip.cxx | 4 +- .../hip/src/VertexerTraitsHIP.hip.cxx | 80 +++++++++---------- .../include/ITStracking/ClusterLines.h | 18 ++--- .../include/ITStracking/Configuration.h | 2 +- .../tracking/include/ITStracking/Constants.h | 4 +- .../include/ITStracking/Definitions.h | 4 +- .../include/ITStracking/IndexTableUtils.h | 2 +- .../include/ITStracking/TrackerTraits.h | 8 +- .../tracking/include/ITStracking/Tracklet.h | 4 +- .../include/ITStracking/VertexerTraits.h | 4 +- Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx | 6 +- .../ITS/tracking/src/PrimaryVertexContext.cxx | 4 +- .../ITS/tracking/src/TrackerTraitsCPU.cxx | 8 +- .../ITS/tracking/src/VertexerTraits.cxx | 6 +- 46 files changed, 262 insertions(+), 262 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Array.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Array.h index f59c9885e97c2..615b1eb3b9d6a 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Array.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Array.h @@ -21,7 +21,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { namespace @@ -64,7 +64,7 @@ struct Array final { T InternalArray[Size]; }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/ClusterLinesGPU.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/ClusterLinesGPU.h index bb77765d6acd3..02dd6902152e6 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/ClusterLinesGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/ClusterLinesGPU.h @@ -22,7 +22,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { struct GPUVertex final { @@ -66,7 +66,7 @@ class ClusterLinesGPU final float mVertex[3]; // cluster centroid position }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 #endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Context.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Context.h index 246dfa76a1979..4ce54b25b2ac4 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Context.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Context.h @@ -23,7 +23,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { struct DeviceProperties final { @@ -62,7 +62,7 @@ class Context final int mDevicesNum; std::vector<DeviceProperties> mDeviceProperties; }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h index 32485259f7980..a70d69d8fdd55 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h @@ -30,7 +30,7 @@ namespace o2 namespace its { -namespace GPU +namespace gpu { class DeviceStoreNV final @@ -131,7 +131,7 @@ GPU_HOST_DEVICE inline float DeviceStoreNV::getRmax(int layer) return mRmax[layer]; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h index 255eb952e96ff..ecbcdc24356d7 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h @@ -35,7 +35,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { enum class TrackletingLayerOrder { @@ -145,7 +145,7 @@ inline std::vector<int> DeviceStoreVertexerGPU::getNFoundTrackletsFromGPU(const std::vector<int> nFoundDuplets; nFoundDuplets.resize(sizes[1]); - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].copyIntoSizedVector(nFoundDuplets); } else { mNFoundDuplets[1].copyIntoSizedVector(nFoundDuplets); @@ -165,7 +165,7 @@ inline std::vector<Tracklet> DeviceStoreVertexerGPU::getRawDupletsFromGPU(const std::vector<int> nFoundDuplets; nFoundDuplets.resize(sizes[1]); - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].copyIntoSizedVector(nFoundDuplets); mDuplets01.copyIntoSizedVector(tmpDuplets); } else { @@ -188,7 +188,7 @@ inline std::vector<Tracklet> DeviceStoreVertexerGPU::getDupletsFromGPU(const Ord nFoundDuplets.resize(sizes[1]); std::vector<Tracklet> shrinkedDuplets; - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].copyIntoSizedVector(nFoundDuplets); mDuplets01.copyIntoSizedVector(tmpDuplets); } else { @@ -244,7 +244,7 @@ inline std::vector<int> DeviceStoreVertexerGPU::getHistogramZFromGPU() inline void DeviceStoreVertexerGPU::updateDuplets(const Order order, std::vector<Tracklet>& duplets) { - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mDuplets01.reset(duplets.data(), static_cast<int>(duplets.size())); } else { mDuplets12.reset(duplets.data(), static_cast<int>(duplets.size())); @@ -253,7 +253,7 @@ inline void DeviceStoreVertexerGPU::updateDuplets(const Order order, std::vector inline void DeviceStoreVertexerGPU::updateFoundDuplets(const Order order, std::vector<int>& nDuplets) { - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].reset(nDuplets.data(), static_cast<int>(nDuplets.size())); } else { mNFoundDuplets[1].reset(nDuplets.data(), static_cast<int>(nDuplets.size())); @@ -296,7 +296,7 @@ inline std::vector<Line> DeviceStoreVertexerGPU::getLinesFromGPU() return lines; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 #endif //O2_ITS_TRACKING_DEVICE_STORE_VERTEXER_GPU_H_ diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h index 0b812088fb302..5eb5b2a459d33 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h @@ -41,87 +41,87 @@ class PrimaryVertexContextNV final : public PrimaryVertexContext void initialise(const MemoryParameters& memParam, const TrackingParameters& trkParam, const std::vector<std::vector<Cluster>>& cl, const std::array<float, 3>& pv, const int iteration) override; - GPU::DeviceStoreNV& getDeviceContext(); - GPU::Array<GPU::Vector<Cluster>, constants::its2::LayersNumber>& getDeviceClusters(); - GPU::Array<GPU::Vector<Tracklet>, constants::its2::TrackletsPerRoad>& getDeviceTracklets(); - GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& getDeviceTrackletsLookupTable(); - GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& getDeviceTrackletsPerClustersTable(); - GPU::Array<GPU::Vector<Cell>, constants::its2::CellsPerRoad>& getDeviceCells(); - GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& getDeviceCellsLookupTable(); - GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& getDeviceCellsPerTrackletTable(); - std::array<GPU::Vector<int>, constants::its2::CellsPerRoad>& getTempTableArray(); - std::array<GPU::Vector<Tracklet>, constants::its2::CellsPerRoad>& getTempTrackletArray(); - std::array<GPU::Vector<Cell>, constants::its2::CellsPerRoad - 1>& getTempCellArray(); + gpu::DeviceStoreNV& getDeviceContext(); + gpu::Array<gpu::Vector<Cluster>, constants::its2::LayersNumber>& getDeviceClusters(); + gpu::Array<gpu::Vector<Tracklet>, constants::its2::TrackletsPerRoad>& getDeviceTracklets(); + gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad>& getDeviceTrackletsLookupTable(); + gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad>& getDeviceTrackletsPerClustersTable(); + gpu::Array<gpu::Vector<Cell>, constants::its2::CellsPerRoad>& getDeviceCells(); + gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad - 1>& getDeviceCellsLookupTable(); + gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad - 1>& getDeviceCellsPerTrackletTable(); + std::array<gpu::Vector<int>, constants::its2::CellsPerRoad>& getTempTableArray(); + std::array<gpu::Vector<Tracklet>, constants::its2::CellsPerRoad>& getTempTrackletArray(); + std::array<gpu::Vector<Cell>, constants::its2::CellsPerRoad - 1>& getTempCellArray(); void updateDeviceContext(); private: - GPU::DeviceStoreNV mGPUContext; - GPU::UniquePointer<GPU::DeviceStoreNV> mGPUContextDevicePointer; - std::array<GPU::Vector<int>, constants::its2::CellsPerRoad> mTempTableArray; - std::array<GPU::Vector<Tracklet>, constants::its2::CellsPerRoad> mTempTrackletArray; - std::array<GPU::Vector<Cell>, constants::its2::CellsPerRoad - 1> mTempCellArray; + gpu::DeviceStoreNV mGPUContext; + gpu::UniquePointer<gpu::DeviceStoreNV> mGPUContextDevicePointer; + std::array<gpu::Vector<int>, constants::its2::CellsPerRoad> mTempTableArray; + std::array<gpu::Vector<Tracklet>, constants::its2::CellsPerRoad> mTempTrackletArray; + std::array<gpu::Vector<Cell>, constants::its2::CellsPerRoad - 1> mTempCellArray; }; -inline GPU::DeviceStoreNV& PrimaryVertexContextNV::getDeviceContext() +inline gpu::DeviceStoreNV& PrimaryVertexContextNV::getDeviceContext() { return *mGPUContextDevicePointer; } -inline GPU::Array<GPU::Vector<Cluster>, constants::its2::LayersNumber>& PrimaryVertexContextNV::getDeviceClusters() +inline gpu::Array<gpu::Vector<Cluster>, constants::its2::LayersNumber>& PrimaryVertexContextNV::getDeviceClusters() { return mGPUContext.getClusters(); } -inline GPU::Array<GPU::Vector<Tracklet>, constants::its2::TrackletsPerRoad>& PrimaryVertexContextNV::getDeviceTracklets() +inline gpu::Array<gpu::Vector<Tracklet>, constants::its2::TrackletsPerRoad>& PrimaryVertexContextNV::getDeviceTracklets() { return mGPUContext.getTracklets(); } -inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceTrackletsLookupTable() +inline gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceTrackletsLookupTable() { return mGPUContext.getTrackletsLookupTable(); } -inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad>& +inline gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceTrackletsPerClustersTable() { return mGPUContext.getTrackletsPerClusterTable(); } -inline GPU::Array<GPU::Vector<Cell>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceCells() +inline gpu::Array<gpu::Vector<Cell>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getDeviceCells() { return mGPUContext.getCells(); } -inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getDeviceCellsLookupTable() +inline gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getDeviceCellsLookupTable() { return mGPUContext.getCellsLookupTable(); } -inline GPU::Array<GPU::Vector<int>, constants::its2::CellsPerRoad - 1>& +inline gpu::Array<gpu::Vector<int>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getDeviceCellsPerTrackletTable() { return mGPUContext.getCellsPerTrackletTable(); } -inline std::array<GPU::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getTempTableArray() +inline std::array<gpu::Vector<int>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getTempTableArray() { return mTempTableArray; } -inline std::array<GPU::Vector<Tracklet>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getTempTrackletArray() +inline std::array<gpu::Vector<Tracklet>, constants::its2::CellsPerRoad>& PrimaryVertexContextNV::getTempTrackletArray() { return mTempTrackletArray; } -inline std::array<GPU::Vector<Cell>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getTempCellArray() +inline std::array<gpu::Vector<Cell>, constants::its2::CellsPerRoad - 1>& PrimaryVertexContextNV::getTempCellArray() { return mTempCellArray; } inline void PrimaryVertexContextNV::updateDeviceContext() { - mGPUContextDevicePointer = GPU::UniquePointer<GPU::DeviceStoreNV>{mGPUContext}; + mGPUContextDevicePointer = gpu::UniquePointer<gpu::DeviceStoreNV>{mGPUContext}; } inline void PrimaryVertexContextNV::initialise(const MemoryParameters& memParam, const TrackingParameters& trkParam, diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Stream.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Stream.h index 52460ad6ff955..f00b5f374c884 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Stream.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Stream.h @@ -21,7 +21,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { class Stream final @@ -39,7 +39,7 @@ class Stream final private: GPUStream mStream; }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h index e82d58f32add2..0b1a4d8667a89 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h @@ -21,7 +21,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { namespace @@ -145,7 +145,7 @@ GPU_HOST_DEVICE const T& UniquePointer<T>::operator*() const noexcept { return PointerTraits::getReference(mDevicePointer); } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h index 5babb15320f6b..71098df75cf2c 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h @@ -22,7 +22,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { namespace Utils @@ -58,7 +58,7 @@ GPUd() int shareToWarp(const int, const int); GPUd() int gpuAtomicAdd(int*, const int); } // namespace Device } // namespace Utils -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h index bf09f269e0449..8bc92e65622ba 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h @@ -28,7 +28,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { template <typename T> @@ -324,7 +324,7 @@ GPU_HOST_DEVICE void Vector<T>::dump() printf("mArrayPointer = %p\nmDeviceSize = %p\nmCapacity = %d\nmIsWeak = %s\n", mArrayPointer, mDeviceSize, mCapacity, mIsWeak ? "true" : "false"); } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h index 4f218e9ada8d4..83573af6e6c31 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h @@ -59,11 +59,11 @@ class VertexerTraitsGPU : public VertexerTraits // GPU-specific getters GPUd() static const int2 getBinsPhiRectWindow(const Cluster&, float maxdeltaphi); - GPUhd() GPU::DeviceStoreVertexerGPU& getDeviceContext(); + GPUhd() gpu::DeviceStoreVertexerGPU& getDeviceContext(); protected: - GPU::DeviceStoreVertexerGPU mStoreVertexerGPU; - GPU::UniquePointer<GPU::DeviceStoreVertexerGPU> mStoreVertexerGPUPtr; + gpu::DeviceStoreVertexerGPU mStoreVertexerGPU; + gpu::UniquePointer<gpu::DeviceStoreVertexerGPU> mStoreVertexerGPUPtr; }; inline GPUd() const int2 VertexerTraitsGPU::getBinsPhiRectWindow(const Cluster& currentCluster, float phiCut) @@ -75,7 +75,7 @@ inline GPUd() const int2 VertexerTraitsGPU::getBinsPhiRectWindow(const Cluster& return int2{phiBinMin, phiBinSpan}; } -inline GPU::DeviceStoreVertexerGPU& VertexerTraitsGPU::getDeviceContext() +inline gpu::DeviceStoreVertexerGPU& VertexerTraitsGPU::getDeviceContext() { return *mStoreVertexerGPUPtr; } diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/ClusterLinesGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/ClusterLinesGPU.cu index 9c1f048292b52..64d861ad16091 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/ClusterLinesGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/ClusterLinesGPU.cu @@ -14,7 +14,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { GPUd() ClusterLinesGPU::ClusterLinesGPU(const Line& firstLine, const Line& secondLine) @@ -129,6 +129,6 @@ GPUd() void ClusterLinesGPU::computeClusterCentroid() mBMatrix[0] * (mAMatrix[1] * mAMatrix[4] - mAMatrix[2] * mAMatrix[3])) / determinant; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu index 633b4c4abf9f1..5cc487a564d9b 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu @@ -77,7 +77,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { using Utils::Host::checkCUDAError; @@ -169,6 +169,6 @@ const DeviceProperties& Context::getDeviceProperties(const int deviceIndex) return mDeviceProperties[deviceIndex]; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu index c0152ab12a8bc..b3a920391eda6 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu @@ -23,7 +23,7 @@ namespace using namespace o2::its; -__device__ void fillIndexTables(GPU::DeviceStoreNV& primaryVertexContext, const int layerIndex) +__device__ void fillIndexTables(o2::its::gpu::DeviceStoreNV& primaryVertexContext, const int layerIndex) { const int currentClusterIndex{static_cast<int>(blockDim.x * blockIdx.x + threadIdx.x)}; @@ -66,7 +66,7 @@ __device__ void fillIndexTables(GPU::DeviceStoreNV& primaryVertexContext, const } } -__device__ void fillTrackletsPerClusterTables(GPU::DeviceStoreNV& primaryVertexContext, const int layerIndex) +__device__ void fillTrackletsPerClusterTables(o2::its::gpu::DeviceStoreNV& primaryVertexContext, const int layerIndex) { const int currentClusterIndex{static_cast<int>(blockDim.x * blockIdx.x + threadIdx.x)}; const int clustersSize{static_cast<int>(primaryVertexContext.getClusters()[layerIndex + 1].size())}; @@ -77,7 +77,7 @@ __device__ void fillTrackletsPerClusterTables(GPU::DeviceStoreNV& primaryVertexC } } -__device__ void fillCellsPerClusterTables(GPU::DeviceStoreNV& primaryVertexContext, const int layerIndex) +__device__ void fillCellsPerClusterTables(o2::its::gpu::DeviceStoreNV& primaryVertexContext, const int layerIndex) { const int totalThreadNum{static_cast<int>(primaryVertexContext.getClusters()[layerIndex + 1].size())}; const int trackletsSize{static_cast<int>(primaryVertexContext.getTracklets()[layerIndex + 1].capacity())}; @@ -92,7 +92,7 @@ __device__ void fillCellsPerClusterTables(GPU::DeviceStoreNV& primaryVertexConte } } -__global__ void fillDeviceStructures(GPU::DeviceStoreNV& primaryVertexContext, const int layerIndex) +__global__ void fillDeviceStructures(o2::its::gpu::DeviceStoreNV& primaryVertexContext, const int layerIndex) { fillIndexTables(primaryVertexContext, layerIndex); @@ -112,7 +112,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { DeviceStoreNV::DeviceStoreNV() @@ -183,6 +183,6 @@ UniquePointer<DeviceStoreNV> DeviceStoreNV::initialise(const float3& primaryVert return gpuContextDevicePointer; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu index 4c113d77e0ffd..3b798132976ab 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu @@ -21,7 +21,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { GPUg() void defaultInitArrayKernel(int* array, const size_t arraySize, const int initValue = 0) { @@ -65,7 +65,7 @@ DeviceStoreVertexerGPU::DeviceStoreVertexerGPU() } mSizes = Vector<int>{constants::its::LayersNumberVertexer}; #endif -} // namespace GPU +} // namespace gpu UniquePointer<DeviceStoreVertexerGPU> DeviceStoreVertexerGPU::initialise(const std::array<std::vector<Cluster>, constants::its::LayersNumberVertexer>& clusters, const std::array<std::array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, @@ -104,6 +104,6 @@ GPUd() const Vector<int>& DeviceStoreVertexerGPU::getIndexTable(const VertexerLa return mIndexTables[1]; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/Stream.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/Stream.cu index 6313bac5157e5..1734a5be7a332 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/Stream.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/Stream.cu @@ -18,7 +18,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { Stream::Stream() @@ -36,6 +36,6 @@ const GPUStream& Stream::get() const return mStream; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu index 7fd97cc71788e..f9e58d6836fe7 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu @@ -42,9 +42,9 @@ using namespace constants::its2; GPU_DEVICE const int4 getBinsRect(const Cluster& currentCluster, const int layerIndex, const float z1, const float z2, float maxdeltaz, float maxdeltaphi) { - const float zRangeMin = gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; + const float zRangeMin = o2::gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; const float phiRangeMin = currentCluster.phiCoordinate - maxdeltaphi; - const float zRangeMax = gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; + const float zRangeMax = o2::gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; if (zRangeMax < -LayersZCoordinate()[layerIndex + 1] || @@ -53,13 +53,13 @@ GPU_DEVICE const int4 getBinsRect(const Cluster& currentCluster, const int layer return getEmptyBinsRect(); } - return int4{gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), + return int4{o2::gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), getPhiBinIndex(phiRangeMin), - gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), + o2::gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), getPhiBinIndex(phiRangeMax)}; } -namespace GPU +namespace gpu { struct StaticTrackingParameters { @@ -129,11 +129,11 @@ __device__ void computeLayerTracklets(DeviceStoreNV& devStore, const int layerIn const Cluster& nextCluster{nextLayerClusters[iNextLayerCluster]}; - const float deltaZ{gpu::GPUCommonMath::Abs( + const float deltaZ{o2::gpu::GPUCommonMath::Abs( tanLambda * (nextCluster.rCoordinate - currentCluster.rCoordinate) + currentCluster.zCoordinate - nextCluster.zCoordinate)}; - const float deltaPhi{gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - nextCluster.phiCoordinate)}; + const float deltaPhi{o2::gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - nextCluster.phiCoordinate)}; - if (deltaZ < kTrkPar.TrackletMaxDeltaZ[layerIndex] && (deltaPhi < kTrkPar.TrackletMaxDeltaPhi || gpu::GPUCommonMath::Abs(deltaPhi - constants::math::TwoPi) < kTrkPar.TrackletMaxDeltaPhi)) { + if (deltaZ < kTrkPar.TrackletMaxDeltaZ[layerIndex] && (deltaPhi < kTrkPar.TrackletMaxDeltaPhi || o2::gpu::GPUCommonMath::Abs(deltaPhi - constants::math::TwoPi) < kTrkPar.TrackletMaxDeltaPhi)) { cooperative_groups::coalesced_group threadGroup = cooperative_groups::coalesced_threads(); int currentIndex{}; @@ -189,14 +189,14 @@ __device__ void computeLayerCells(DeviceStoreNV& devStore, const int layerIndex, iNextLayerTracklet < nextLayerTrackletsNum && devStore.getTracklets()[layerIndex + 1][iNextLayerTracklet].firstClusterIndex == nextLayerClusterIndex; ++iNextLayerTracklet) { const Tracklet& nextTracklet{devStore.getTracklets()[layerIndex + 1][iNextLayerTracklet]}; - const float deltaTanLambda{gpu::GPUCommonMath::Abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; - const float deltaPhi{gpu::GPUCommonMath::Abs(currentTracklet.phiCoordinate - nextTracklet.phiCoordinate)}; + const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; + const float deltaPhi{o2::gpu::GPUCommonMath::Abs(currentTracklet.phiCoordinate - nextTracklet.phiCoordinate)}; - if (deltaTanLambda < kTrkPar.CellMaxDeltaTanLambda && (deltaPhi < kTrkPar.CellMaxDeltaPhi || gpu::GPUCommonMath::Abs(deltaPhi - constants::math::TwoPi) < kTrkPar.CellMaxDeltaPhi)) { + if (deltaTanLambda < kTrkPar.CellMaxDeltaTanLambda && (deltaPhi < kTrkPar.CellMaxDeltaPhi || o2::gpu::GPUCommonMath::Abs(deltaPhi - constants::math::TwoPi) < kTrkPar.CellMaxDeltaPhi)) { const float averageTanLambda{0.5f * (currentTracklet.tanLambda + nextTracklet.tanLambda)}; const float directionZIntersection{-averageTanLambda * firstCellCluster.rCoordinate + firstCellCluster.zCoordinate}; - const float deltaZ{gpu::GPUCommonMath::Abs(directionZIntersection - primaryVertex.z)}; + const float deltaZ{o2::gpu::GPUCommonMath::Abs(directionZIntersection - primaryVertex.z)}; if (deltaZ < kTrkPar.CellMaxDeltaZ[layerIndex]) { @@ -210,20 +210,20 @@ __device__ void computeLayerCells(DeviceStoreNV& devStore, const int layerIndex, float3 cellPlaneNormalVector{math_utils::crossProduct(firstDeltaVector, secondDeltaVector)}; - const float vectorNorm{gpu::GPUCommonMath::Sqrt( + const float vectorNorm{o2::gpu::GPUCommonMath::Sqrt( cellPlaneNormalVector.x * cellPlaneNormalVector.x + cellPlaneNormalVector.y * cellPlaneNormalVector.y + cellPlaneNormalVector.z * cellPlaneNormalVector.z)}; - if (!(vectorNorm < constants::math::FloatMinThreshold || gpu::GPUCommonMath::Abs(cellPlaneNormalVector.z) < constants::math::FloatMinThreshold)) { + if (!(vectorNorm < constants::math::FloatMinThreshold || o2::gpu::GPUCommonMath::Abs(cellPlaneNormalVector.z) < constants::math::FloatMinThreshold)) { const float inverseVectorNorm{1.0f / vectorNorm}; const float3 normalizedPlaneVector{cellPlaneNormalVector.x * inverseVectorNorm, cellPlaneNormalVector.y * inverseVectorNorm, cellPlaneNormalVector.z * inverseVectorNorm}; const float planeDistance{-normalizedPlaneVector.x * (secondCellCluster.xCoordinate - primaryVertex.x) - (normalizedPlaneVector.y * secondCellCluster.yCoordinate - primaryVertex.y) - normalizedPlaneVector.z * secondCellClusterQuadraticRCoordinate}; const float normalizedPlaneVectorQuadraticZCoordinate{normalizedPlaneVector.z * normalizedPlaneVector.z}; - const float cellTrajectoryRadius{gpu::GPUCommonMath::Sqrt( + const float cellTrajectoryRadius{o2::gpu::GPUCommonMath::Sqrt( (1.0f - normalizedPlaneVectorQuadraticZCoordinate - 4.0f * planeDistance * normalizedPlaneVector.z) / (4.0f * normalizedPlaneVectorQuadraticZCoordinate))}; const float2 circleCenter{-0.5f * normalizedPlaneVector.x / normalizedPlaneVector.z, -0.5f * normalizedPlaneVector.y / normalizedPlaneVector.z}; - const float distanceOfClosestApproach{gpu::GPUCommonMath::Abs( - cellTrajectoryRadius - gpu::GPUCommonMath::Sqrt(circleCenter.x * circleCenter.x + circleCenter.y * circleCenter.y))}; + const float distanceOfClosestApproach{o2::gpu::GPUCommonMath::Abs( + cellTrajectoryRadius - o2::gpu::GPUCommonMath::Sqrt(circleCenter.x * circleCenter.x + circleCenter.y * circleCenter.y))}; if (distanceOfClosestApproach <= kTrkPar.CellMaxDCA[layerIndex]) { @@ -303,7 +303,7 @@ __global__ void sortCellsKernel(DeviceStoreNV& devStore, const int layerIndex, } } -} // namespace GPU +} // namespace gpu TrackerTraits* createTrackerTraitsNV() { @@ -324,10 +324,10 @@ void TrackerTraitsNV::computeLayerTracklets() { PrimaryVertexContextNV* primaryVertexContext = static_cast<PrimaryVertexContextNV*>(mPrimaryVertexContext); - // cudaMemcpyToSymbol(GPU::kTrkPar, &mTrkParams, sizeof(TrackingParameters)); + // cudaMemcpyToSymbol(gpu::kTrkPar, &mTrkParams, sizeof(TrackingParameters)); std::array<size_t, constants::its2::CellsPerRoad> tempSize; std::array<int, constants::its2::CellsPerRoad> trackletsNum; - std::array<GPU::Stream, constants::its2::TrackletsPerRoad> streamArray; + std::array<gpu::Stream, constants::its2::TrackletsPerRoad> streamArray; for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad; ++iLayer) { @@ -347,19 +347,19 @@ void TrackerTraitsNV::computeLayerTracklets() for (int iLayer{0}; iLayer < constants::its2::TrackletsPerRoad; ++iLayer) { - const GPU::DeviceProperties& deviceProperties = GPU::Context::getInstance().getDeviceProperties(); + const gpu::DeviceProperties& deviceProperties = gpu::Context::getInstance().getDeviceProperties(); const int clustersNum{static_cast<int>(primaryVertexContext->getClusters()[iLayer].size())}; - dim3 threadsPerBlock{GPU::Utils::Host::getBlockSize(clustersNum, 1, 192)}; - dim3 blocksGrid{GPU::Utils::Host::getBlocksGrid(threadsPerBlock, clustersNum)}; + dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(clustersNum, 1, 192)}; + dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, clustersNum)}; if (iLayer == 0) { - GPU::layerTrackletsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), + gpu::layerTrackletsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), iLayer, primaryVertexContext->getDeviceTracklets()[iLayer].getWeakCopy()); } else { - GPU::layerTrackletsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), + gpu::layerTrackletsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), iLayer, primaryVertexContext->getTempTrackletArray()[iLayer - 1].getWeakCopy()); } @@ -390,10 +390,10 @@ void TrackerTraitsNV::computeLayerTracklets() primaryVertexContext->getDeviceTrackletsLookupTable()[iLayer].get(), primaryVertexContext->getClusters()[iLayer + 1].size(), streamArray[iLayer + 1].get()); - dim3 threadsPerBlock{GPU::Utils::Host::getBlockSize(trackletsNum[iLayer])}; - dim3 blocksGrid{GPU::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; + dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(trackletsNum[iLayer])}; + dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; - GPU::sortTrackletsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer + 1].get()>>>(primaryVertexContext->getDeviceContext(), + gpu::sortTrackletsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer + 1].get()>>>(primaryVertexContext->getDeviceContext(), iLayer + 1, primaryVertexContext->getTempTrackletArray()[iLayer].getWeakCopy()); cudaError_t error = cudaGetLastError(); @@ -416,7 +416,7 @@ void TrackerTraitsNV::computeLayerCells() std::array<size_t, constants::its2::CellsPerRoad - 1> tempSize; std::array<int, constants::its2::CellsPerRoad - 1> trackletsNum; std::array<int, constants::its2::CellsPerRoad - 1> cellsNum; - std::array<GPU::Stream, constants::its2::CellsPerRoad> streamArray; + std::array<gpu::Stream, constants::its2::CellsPerRoad> streamArray; for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad - 1; ++iLayer) { @@ -437,22 +437,22 @@ void TrackerTraitsNV::computeLayerCells() cudaDeviceSynchronize(); for (int iLayer{0}; iLayer < constants::its2::CellsPerRoad; ++iLayer) { - const GPU::DeviceProperties& deviceProperties = GPU::Context::getInstance().getDeviceProperties(); + const gpu::DeviceProperties& deviceProperties = gpu::Context::getInstance().getDeviceProperties(); const int trackletsSize = primaryVertexContext->getDeviceTracklets()[iLayer].getSizeFromDevice(); if (trackletsSize == 0) { continue; } - dim3 threadsPerBlock{GPU::Utils::Host::getBlockSize(trackletsSize)}; - dim3 blocksGrid{GPU::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsSize)}; + dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(trackletsSize)}; + dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsSize)}; if (iLayer == 0) { - GPU::layerCellsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), + gpu::layerCellsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), iLayer, primaryVertexContext->getDeviceCells()[iLayer].getWeakCopy()); } else { - GPU::layerCellsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), + gpu::layerCellsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(primaryVertexContext->getDeviceContext(), iLayer, primaryVertexContext->getTempCellArray()[iLayer - 1].getWeakCopy()); } @@ -482,10 +482,10 @@ void TrackerTraitsNV::computeLayerCells() primaryVertexContext->getDeviceCellsLookupTable()[iLayer].get(), trackletsNum[iLayer], streamArray[iLayer + 1].get()); - dim3 threadsPerBlock{GPU::Utils::Host::getBlockSize(trackletsNum[iLayer])}; - dim3 blocksGrid{GPU::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; + dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(trackletsNum[iLayer])}; + dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; - GPU::sortCellsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer + 1].get()>>>(primaryVertexContext->getDeviceContext(), + gpu::sortCellsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer + 1].get()>>>(primaryVertexContext->getDeviceContext(), iLayer + 1, primaryVertexContext->getTempCellArray()[iLayer].getWeakCopy()); cudaError_t error = cudaGetLastError(); diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu index 5dbe67abe9e51..3872556147b90 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu @@ -70,7 +70,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { void Utils::Host::checkCUDAError(const cudaError_t error, const char* file, const int line) @@ -190,6 +190,6 @@ GPUd() int Utils::Device::gpuAtomicAdd(int* p, const int incrementSize) return atomicAdd(p, incrementSize); } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu index 9b34edeecd800..6e44aecfbf24e 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu @@ -56,9 +56,9 @@ GPU_DEVICE const int4 getBinsRect(const Cluster& currentCluster, const int layer return getEmptyBinsRect(); } - return int4{gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), + return int4{o2::gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), getPhiBinIndex(phiRangeMin), - gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), + o2::gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), getPhiBinIndex(phiRangeMax)}; } @@ -101,7 +101,7 @@ void VertexerTraitsGPU::initialise(ROframe* event) // mStoreVertexerGPUPtr = mStoreVertexerGPU.initialise(mClusters, mIndexTables); } -namespace GPU +namespace gpu { template <typename... Args> @@ -176,7 +176,7 @@ GPUg() void trackleterKernel( const int maxRowClusterIndex{store.getIndexTable(adjacentLayerIndex)[firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1]}; for (size_t iAdjacentCluster{(size_t)firstRowClusterIndex}; iAdjacentCluster < (size_t)maxRowClusterIndex && iAdjacentCluster < nClustersAdjacentLayer; ++iAdjacentCluster) { const Cluster& adjacentCluster = store.getClusters()[static_cast<int>(adjacentLayerIndex)][iAdjacentCluster]; // assign-constructor may be a problem, check - if (gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - adjacentCluster.phiCoordinate) < phiCut) { + if (o2::gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - adjacentCluster.phiCoordinate) < phiCut) { if (storedTracklets < store.getConfig().maxTrackletsPerCluster) { if (layerOrder == TrackletingLayerOrder::fromInnermostToMiddleLayer) { store.getDuplets01().emplace(stride + storedTracklets, iAdjacentCluster, currentClusterIndex, adjacentCluster, currentCluster); @@ -208,8 +208,8 @@ GPUg() void trackletSelectionKernel( int validTracklets{0}; for (int iTracklet12{0}; iTracklet12 < store.getNFoundTracklets(TrackletingLayerOrder::fromMiddleToOuterLayer)[currentClusterIndex]; ++iTracklet12) { for (int iTracklet01{0}; iTracklet01 < store.getNFoundTracklets(TrackletingLayerOrder::fromInnermostToMiddleLayer)[currentClusterIndex] && validTracklets < store.getConfig().maxTrackletsPerCluster; ++iTracklet01) { - const float deltaTanLambda{gpu::GPUCommonMath::Abs(store.getDuplets01()[stride + iTracklet01].tanLambda - store.getDuplets12()[stride + iTracklet12].tanLambda)}; - const float deltaPhi{gpu::GPUCommonMath::Abs(store.getDuplets01()[stride + iTracklet01].phiCoordinate - store.getDuplets12()[stride + iTracklet12].phiCoordinate)}; + const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(store.getDuplets01()[stride + iTracklet01].tanLambda - store.getDuplets12()[stride + iTracklet12].tanLambda)}; + const float deltaPhi{o2::gpu::GPUCommonMath::Abs(store.getDuplets01()[stride + iTracklet01].phiCoordinate - store.getDuplets12()[stride + iTracklet12].phiCoordinate)}; if (deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != store.getConfig().maxTrackletsPerCluster) { assert(store.getDuplets01()[stride + iTracklet01].secondClusterIndex == store.getDuplets12()[stride + iTracklet12].firstClusterIndex); if (!isInitRun) { @@ -276,7 +276,7 @@ GPUg() void computeZCentroidsKernel(DeviceStoreVertexerGPU& store, float tmpX{store.getConfig().histConf.lowHistBoundariesXYZ[0] + store.getTmpVertexPositionBins()[0].key * store.getConfig().histConf.binSizeHistX + store.getConfig().histConf.binSizeHistX / 2}; int sumWX{store.getTmpVertexPositionBins()[0].value}; float wX{tmpX * store.getTmpVertexPositionBins()[0].value}; - for (int iBin{gpu::GPUCommonMath::Max(0, store.getTmpVertexPositionBins()[0].key - binOpeningX)}; iBin < gpu::GPUCommonMath::Min(store.getTmpVertexPositionBins()[0].key + binOpeningX + 1, store.getConfig().histConf.nBinsXYZ[0] - 1); ++iBin) { + for (int iBin{o2::gpu::GPUCommonMath::Max(0, store.getTmpVertexPositionBins()[0].key - binOpeningX)}; iBin < o2::gpu::GPUCommonMath::Min(store.getTmpVertexPositionBins()[0].key + binOpeningX + 1, store.getConfig().histConf.nBinsXYZ[0] - 1); ++iBin) { if (iBin != store.getTmpVertexPositionBins()[0].key) { wX += (store.getConfig().histConf.lowHistBoundariesXYZ[0] + iBin * store.getConfig().histConf.binSizeHistX + store.getConfig().histConf.binSizeHistX / 2) * store.getHistogramXYZ()[0].get()[iBin]; sumWX += store.getHistogramXYZ()[0].get()[iBin]; @@ -285,7 +285,7 @@ GPUg() void computeZCentroidsKernel(DeviceStoreVertexerGPU& store, float tmpY{store.getConfig().histConf.lowHistBoundariesXYZ[1] + store.getTmpVertexPositionBins()[1].key * store.getConfig().histConf.binSizeHistY + store.getConfig().histConf.binSizeHistY / 2}; int sumWY{store.getTmpVertexPositionBins()[1].value}; float wY{tmpY * store.getTmpVertexPositionBins()[1].value}; - for (int iBin{gpu::GPUCommonMath::Max(0, store.getTmpVertexPositionBins()[1].key - binOpeningY)}; iBin < gpu::GPUCommonMath::Min(store.getTmpVertexPositionBins()[1].key + binOpeningY + 1, store.getConfig().histConf.nBinsXYZ[1] - 1); ++iBin) { + for (int iBin{o2::gpu::GPUCommonMath::Max(0, store.getTmpVertexPositionBins()[1].key - binOpeningY)}; iBin < o2::gpu::GPUCommonMath::Min(store.getTmpVertexPositionBins()[1].key + binOpeningY + 1, store.getConfig().histConf.nBinsXYZ[1] - 1); ++iBin) { if (iBin != store.getTmpVertexPositionBins()[1].key) { wY += (store.getConfig().histConf.lowHistBoundariesXYZ[1] + iBin * store.getConfig().histConf.binSizeHistY + store.getConfig().histConf.binSizeHistY / 2) * store.getHistogramXYZ()[1].get()[iBin]; sumWY += store.getHistogramXYZ()[1].get()[iBin]; @@ -317,7 +317,7 @@ GPUg() void computeVertexKernel(DeviceStoreVertexerGPU& store, const int vertInd float ez{0.f}; int sumWZ{store.getTmpVertexPositionBins()[2].value}; float wZ{z * store.getTmpVertexPositionBins()[2].value}; - for (int iBin{gpu::GPUCommonMath::Max(0, store.getTmpVertexPositionBins()[2].key - binOpeningZ)}; iBin < gpu::GPUCommonMath::Min(store.getTmpVertexPositionBins()[2].key + binOpeningZ + 1, store.getConfig().histConf.nBinsXYZ[2] - 1); ++iBin) { + for (int iBin{o2::gpu::GPUCommonMath::Max(0, store.getTmpVertexPositionBins()[2].key - binOpeningZ)}; iBin < o2::gpu::GPUCommonMath::Min(store.getTmpVertexPositionBins()[2].key + binOpeningZ + 1, store.getConfig().histConf.nBinsXYZ[2] - 1); ++iBin) { if (iBin != store.getTmpVertexPositionBins()[2].key) { wZ += (store.getConfig().histConf.lowHistBoundariesXYZ[2] + iBin * store.getConfig().histConf.binSizeHistZ + store.getConfig().histConf.binSizeHistZ / 2) * store.getHistogramXYZ()[2].get()[iBin]; sumWZ += store.getHistogramXYZ()[2].get()[iBin]; @@ -335,7 +335,7 @@ GPUg() void computeVertexKernel(DeviceStoreVertexerGPU& store, const int vertInd } } } -} // namespace GPU +} // namespace gpu void VertexerTraitsGPU::computeTracklets() { @@ -343,17 +343,17 @@ void VertexerTraitsGPU::computeTracklets() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{GPU::Utils::Host::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{GPU::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; - GPU::trackleterKernel<<<blocksGrid, threadsPerBlock>>>( + gpu::trackleterKernel<<<blocksGrid, threadsPerBlock>>>( getDeviceContext(), - GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer, + gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer, mVrtParams.phiCut); - GPU::trackleterKernel<<<blocksGrid, threadsPerBlock>>>( + gpu::trackleterKernel<<<blocksGrid, threadsPerBlock>>>( getDeviceContext(), - GPU::TrackletingLayerOrder::fromMiddleToOuterLayer, + gpu::TrackletingLayerOrder::fromMiddleToOuterLayer, mVrtParams.phiCut); gpuThrowOnError(); @@ -361,8 +361,8 @@ void VertexerTraitsGPU::computeTracklets() #ifdef _ALLOW_DEBUG_TREES_ITS_ if (isDebugFlag(VertexerDebug::CombinatoricsTreeAll)) { mDebugger->fillCombinatoricsTree(mClusters, - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer), - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer), mEvent); } #endif @@ -374,11 +374,11 @@ void VertexerTraitsGPU::computeTrackletMatching() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{GPU::Utils::Host::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{GPU::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; size_t bufferSize = mStoreVertexerGPU.getConfig().tmpCUBBufferSize * sizeof(int); - GPU::trackletSelectionKernel<<<blocksGrid, threadsPerBlock>>>( + gpu::trackletSelectionKernel<<<blocksGrid, threadsPerBlock>>>( getDeviceContext(), true, // isInitRun mVrtParams.tanLambdaCut, @@ -390,7 +390,7 @@ void VertexerTraitsGPU::computeTrackletMatching() mStoreVertexerGPU.getNExclusiveFoundLines().get(), mClusters[1].size()); - GPU::trackletSelectionKernel<<<blocksGrid, threadsPerBlock>>>( + gpu::trackletSelectionKernel<<<blocksGrid, threadsPerBlock>>>( getDeviceContext(), false, // isInitRun mVrtParams.tanLambdaCut, @@ -401,8 +401,8 @@ void VertexerTraitsGPU::computeTrackletMatching() #ifdef _ALLOW_DEBUG_TREES_ITS_ if (isDebugFlag(VertexerDebug::TrackletTreeAll)) { mDebugger->fillTrackletSelectionTree(mClusters, - mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer), - mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer), + mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer), + mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer), mStoreVertexerGPU.getDupletIndicesFromGPU(), mEvent); } @@ -422,15 +422,15 @@ void VertexerTraitsGPU::computeVertices() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{GPU::Utils::Host::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{GPU::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; size_t bufferSize = mStoreVertexerGPU.getConfig().tmpCUBBufferSize * sizeof(int); int nLines = mStoreVertexerGPU.getNExclusiveFoundLines().getElementFromDevice(mClusters[1].size() - 1) + mStoreVertexerGPU.getNFoundLines().getElementFromDevice(mClusters[1].size() - 1); int nCentroids{static_cast<int>(nLines * (nLines - 1) / 2)}; int* histogramXY[2] = {mStoreVertexerGPU.getHistogramXYZ()[0].get(), mStoreVertexerGPU.getHistogramXYZ()[1].get()}; float tmpArrayLow[2] = {mStoreVertexerGPU.getConfig().histConf.lowHistBoundariesXYZ[0], mStoreVertexerGPU.getConfig().histConf.lowHistBoundariesXYZ[1]}; float tmpArrayHigh[2] = {mStoreVertexerGPU.getConfig().histConf.highHistBoundariesXYZ[0], mStoreVertexerGPU.getConfig().histConf.highHistBoundariesXYZ[1]}; - GPU::computeCentroidsKernel<<<blocksGrid, threadsPerBlock>>>(getDeviceContext(), + gpu::computeCentroidsKernel<<<blocksGrid, threadsPerBlock>>>(getDeviceContext(), mVrtParams.histPairCut); cub::DeviceHistogram::MultiHistogramEven<2, 2>(reinterpret_cast<void*>(mStoreVertexerGPU.getCUBTmpBuffer().get()), // d_temp_storage @@ -451,7 +451,7 @@ void VertexerTraitsGPU::computeVertices() histogramXY[1], mStoreVertexerGPU.getTmpVertexPositionBins().get() + 1, mStoreVertexerGPU.getConfig().histConf.nBinsXYZ[0]); - GPU::computeZCentroidsKernel<<<blocksGrid, threadsPerBlock>>>(getDeviceContext(), mVrtParams.histPairCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[0], mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[1]); + gpu::computeZCentroidsKernel<<<blocksGrid, threadsPerBlock>>>(getDeviceContext(), mVrtParams.histPairCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[0], mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[1]); cub::DeviceHistogram::HistogramEven(reinterpret_cast<void*>(mStoreVertexerGPU.getCUBTmpBuffer().get()), // d_temp_storage bufferSize, // temp_storage_bytes mStoreVertexerGPU.getZCentroids().get(), // d_samples @@ -475,9 +475,9 @@ void VertexerTraitsGPU::computeVertices() mStoreVertexerGPU.getConfig().histConf.nBinsXYZ[2] - 1}); } #endif - GPU::computeVertexKernel<<<blocksGrid, 5>>>(getDeviceContext(), iVertex, mVrtParams.clusterContributorsCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[2]); + gpu::computeVertexKernel<<<blocksGrid, 5>>>(getDeviceContext(), iVertex, mVrtParams.clusterContributorsCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[2]); } - std::vector<GPU::GPUVertex> vertices; + std::vector<gpu::GPUVertex> vertices; vertices.resize(mStoreVertexerGPU.getConfig().nMaxVertices); mStoreVertexerGPU.getVertices().copyIntoSizedVector(vertices); @@ -493,23 +493,23 @@ void VertexerTraitsGPU::computeVertices() #ifdef _ALLOW_DEBUG_TREES_ITS_ void VertexerTraitsGPU::computeMCFiltering() { - std::vector<Tracklet> tracklets01 = mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer); - std::vector<Tracklet> tracklets12 = mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer); - std::vector<int> labels01 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer); - std::vector<int> labels12 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer); + std::vector<Tracklet> tracklets01 = mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer); + std::vector<Tracklet> tracklets12 = mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer); + std::vector<int> labels01 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer); + std::vector<int> labels12 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer); VertexerStoreConfigurationGPU tmpGPUConf; const int stride = tmpGPUConf.maxTrackletsPerCluster; filterTrackletsWithMC(tracklets01, tracklets12, labels01, labels12, stride); - mStoreVertexerGPU.updateFoundDuplets(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer, labels01); - mStoreVertexerGPU.updateDuplets(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer, tracklets01); - mStoreVertexerGPU.updateFoundDuplets(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer, labels12); - mStoreVertexerGPU.updateDuplets(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer, tracklets12); + mStoreVertexerGPU.updateFoundDuplets(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer, labels01); + mStoreVertexerGPU.updateDuplets(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer, tracklets01); + mStoreVertexerGPU.updateFoundDuplets(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer, labels12); + mStoreVertexerGPU.updateDuplets(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer, tracklets12); if (isDebugFlag(VertexerDebug::CombinatoricsTreeAll)) { mDebugger->fillCombinatoricsTree(mClusters, - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer), - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer), mEvent); } } diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ArrayHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ArrayHIP.h index e728a0ae7b530..3002c6b68d9b5 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ArrayHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ArrayHIP.h @@ -23,7 +23,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { namespace @@ -66,7 +66,7 @@ struct ArrayHIP final { T InternalArray[Size]; }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ClusterLinesHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ClusterLinesHIP.h index 3a8f92998dc8e..2da251e7919b0 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ClusterLinesHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ClusterLinesHIP.h @@ -23,7 +23,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { struct GPUVertex final { @@ -67,7 +67,7 @@ class ClusterLinesHIP final float mVertex[3]; // cluster centroid position }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 #endif /* O2_ITS_TRACKING_INCLUDE_CLUSTERLINES_HIP_H_ */ \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ContextHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ContextHIP.h index 4b11d7d876a28..5eb74fe85e16b 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ContextHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ContextHIP.h @@ -25,7 +25,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { struct DeviceProperties final { @@ -64,7 +64,7 @@ class ContextHIP final int mDevicesNum; std::vector<DeviceProperties> mDeviceProperties; }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h index 417eb965c8c20..e2bdea5eb3d87 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h @@ -33,7 +33,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { enum class TrackletingLayerOrder { @@ -141,7 +141,7 @@ inline std::vector<int> DeviceStoreVertexerHIP::getNFoundTrackletsFromGPU(const std::vector<int> nFoundDuplets; nFoundDuplets.resize(sizes[1]); - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].copyIntoSizedVector(nFoundDuplets); } else { mNFoundDuplets[1].copyIntoSizedVector(nFoundDuplets); @@ -161,7 +161,7 @@ inline std::vector<Tracklet> DeviceStoreVertexerHIP::getRawDupletsFromGPU(const std::vector<int> nFoundDuplets; nFoundDuplets.resize(sizes[1]); - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].copyIntoSizedVector(nFoundDuplets); mDuplets01.copyIntoSizedVector(tmpDuplets); } else { @@ -184,7 +184,7 @@ inline std::vector<Tracklet> DeviceStoreVertexerHIP::getDupletsFromGPU(const Ord nFoundDuplets.resize(sizes[1]); std::vector<Tracklet> shrinkedDuplets; - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].copyIntoSizedVector(nFoundDuplets); mDuplets01.copyIntoSizedVector(tmpDuplets); } else { @@ -242,7 +242,7 @@ inline std::vector<int> DeviceStoreVertexerHIP::getHistogramZFromGPU() inline void DeviceStoreVertexerHIP::updateDuplets(const Order order, std::vector<Tracklet>& duplets) { - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mDuplets01.reset(duplets.data(), static_cast<int>(duplets.size())); } else { mDuplets12.reset(duplets.data(), static_cast<int>(duplets.size())); @@ -251,7 +251,7 @@ inline void DeviceStoreVertexerHIP::updateDuplets(const Order order, std::vector inline void DeviceStoreVertexerHIP::updateFoundDuplets(const Order order, std::vector<int>& nDuplets) { - if (order == GPU::Order::fromInnermostToMiddleLayer) { + if (order == gpu::Order::fromInnermostToMiddleLayer) { mNFoundDuplets[0].reset(nDuplets.data(), static_cast<int>(nDuplets.size())); } else { mNFoundDuplets[1].reset(nDuplets.data(), static_cast<int>(nDuplets.size())); @@ -291,7 +291,7 @@ inline std::vector<Line> DeviceStoreVertexerHIP::getLinesFromGPU() return lines; } #endif -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 #endif //O2_ITS_TRACKING_INCLUDE_DEVICESTOREVERTEXER_HIP_H_ diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/StreamHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/StreamHIP.h index d0006fd40ace9..0377e20d3e84e 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/StreamHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/StreamHIP.h @@ -21,7 +21,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { class StreamHIP final @@ -39,7 +39,7 @@ class StreamHIP final private: hipStream_t mStream; }; -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UniquePointerHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UniquePointerHIP.h index 444fb9e199390..372e2ee31f19f 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UniquePointerHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UniquePointerHIP.h @@ -22,7 +22,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { namespace @@ -146,7 +146,7 @@ GPUhd() const T& UniquePointer<T>::operator*() const noexcept { return PointerTraits::getReference(mDevicePointer); } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UtilsHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UtilsHIP.h index f536f12529f2f..34434e9ec242c 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UtilsHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UtilsHIP.h @@ -23,7 +23,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { namespace Utils @@ -59,7 +59,7 @@ GPUd() int shareToWarp(const int, const int); GPUd() int gpuAtomicAdd(int*, const int); } // namespace Device } // namespace Utils -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VectorHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VectorHIP.h index 42c69111a9f5f..d7aaa7c3b2a4a 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VectorHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VectorHIP.h @@ -28,7 +28,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { template <typename T> @@ -323,7 +323,7 @@ GPUhd() void VectorHIP<T>::dump() printf("mArrayPointer = %p\nmDeviceSize = %p\nmCapacity = %d\nmIsWeak = %s\n", mArrayPointer, mDeviceSize, mCapacity, mIsWeak ? "true" : "false"); } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h index 6ba9d8e08bb1e..245af2485a55f 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h +++ b/Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h @@ -59,15 +59,15 @@ class VertexerTraitsHIP : public VertexerTraits // GPU-specific getters GPUd() static const int2 getBinsPhiRectWindow(const Cluster&, float maxdeltaphi); - GPUhd() GPU::DeviceStoreVertexerHIP& getDeviceContext(); - GPUhd() GPU::DeviceStoreVertexerHIP* getDeviceContextPtr(); + GPUhd() gpu::DeviceStoreVertexerHIP& getDeviceContext(); + GPUhd() gpu::DeviceStoreVertexerHIP* getDeviceContextPtr(); protected: // #ifdef _ALLOW_DEBUG_TREES_ITS_ // StandaloneDebugger* mDebugger; // #endif - GPU::DeviceStoreVertexerHIP mStoreVertexerGPU; - GPU::UniquePointer<GPU::DeviceStoreVertexerHIP> mStoreVertexerGPUPtr; + gpu::DeviceStoreVertexerHIP mStoreVertexerGPU; + gpu::UniquePointer<gpu::DeviceStoreVertexerHIP> mStoreVertexerGPUPtr; }; GPUdi() const int2 VertexerTraitsHIP::getBinsPhiRectWindow(const Cluster& currentCluster, float phiCut) @@ -79,12 +79,12 @@ GPUdi() const int2 VertexerTraitsHIP::getBinsPhiRectWindow(const Cluster& curren return int2{phiBinMin, phiBinSpan}; } -GPUhdi() GPU::DeviceStoreVertexerHIP& VertexerTraitsHIP::getDeviceContext() +GPUhdi() gpu::DeviceStoreVertexerHIP& VertexerTraitsHIP::getDeviceContext() { return *mStoreVertexerGPUPtr; } -GPUhdi() GPU::DeviceStoreVertexerHIP* VertexerTraitsHIP::getDeviceContextPtr() +GPUhdi() gpu::DeviceStoreVertexerHIP* VertexerTraitsHIP::getDeviceContextPtr() { return mStoreVertexerGPUPtr.get(); } diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/ClusterLinesHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/ClusterLinesHIP.hip.cxx index 79c13119e5e21..00f5788108660 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/ClusterLinesHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/ClusterLinesHIP.hip.cxx @@ -18,7 +18,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { GPUd() ClusterLinesHIP::ClusterLinesHIP(const Line& firstLine, const Line& secondLine) @@ -133,6 +133,6 @@ GPUd() void ClusterLinesHIP::computeClusterCentroid() mBMatrix[0] * (mAMatrix[1] * mAMatrix[4] - mAMatrix[2] * mAMatrix[3])) / determinant; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/ContextHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/ContextHIP.hip.cxx index 0c6744b58b5d5..dc6ea9cb3a08b 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/ContextHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/ContextHIP.hip.cxx @@ -40,7 +40,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { using Utils::HostHIP::checkHIPError; @@ -129,6 +129,6 @@ const DeviceProperties& ContextHIP::getDeviceProperties(const int deviceIndex) return mDeviceProperties[deviceIndex]; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx index b0546b19da72e..de82d3835f7be 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx @@ -21,7 +21,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { GPUg() void defaultInitArrayKernel(int* array, const size_t arraySize, const int initValue = 0) { @@ -65,7 +65,7 @@ DeviceStoreVertexerHIP::DeviceStoreVertexerHIP() } mSizes = VectorHIP<int>{constants::its::LayersNumberVertexer}; #endif -} // namespace GPU +} // namespace gpu UniquePointer<DeviceStoreVertexerHIP> DeviceStoreVertexerHIP::initialise(const std::array<std::vector<Cluster>, constants::its::LayersNumberVertexer>& clusters, const std::array<std::array<int, constants::its2::ZBins * constants::its2::PhiBins + 1>, @@ -105,6 +105,6 @@ GPUd() const VectorHIP<int>& DeviceStoreVertexerHIP::getIndexTable(const Vertexe return mIndexTables[1]; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/StreamHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/StreamHIP.hip.cxx index 50e24c6eb041f..28ab175f155d8 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/StreamHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/StreamHIP.hip.cxx @@ -18,7 +18,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { StreamHIP::StreamHIP() @@ -36,6 +36,6 @@ const hipStream_t& StreamHIP::get() const return mStream; } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/UtilsHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/UtilsHIP.hip.cxx index bd58b7c9c3e0f..da9a149181a60 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/UtilsHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/UtilsHIP.hip.cxx @@ -55,7 +55,7 @@ namespace o2 { namespace its { -namespace GPU +namespace gpu { void Utils::HostHIP::checkHIPError(const hipError_t error, const char* file, const int line) @@ -167,6 +167,6 @@ GPUd() int Utils::DeviceHIP::getLaneIndex() // return atomicAdd(p, incrementSize); // } -} // namespace GPU +} // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx b/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx index b159d3f758935..1fc760a87d639 100644 --- a/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx +++ b/Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx @@ -57,9 +57,9 @@ GPUhd() const int4 getBinsRect(const Cluster& currentCluster, const int layerInd return constants::its2::getEmptyBinsRect(); } - return int4{gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), + return int4{o2::gpu::GPUCommonMath::Max(0, getZBinIndex(layerIndex + 1, zRangeMin)), getPhiBinIndex(phiRangeMin), - gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), + o2::gpu::GPUCommonMath::Min(ZBins - 1, getZBinIndex(layerIndex + 1, zRangeMax)), getPhiBinIndex(phiRangeMax)}; } @@ -101,7 +101,7 @@ void VertexerTraitsHIP::initialise(ROframe* event) // mStoreVertexerGPUPtr = mStoreVertexerGPU.initialise(mClusters, mIndexTables); } -namespace GPU +namespace gpu { template <typename... Args> @@ -176,7 +176,7 @@ GPUg() void trackleterKernel( const int maxRowClusterIndex{store->getIndexTable(adjacentLayerIndex)[firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1]}; for (int iAdjacentCluster{firstRowClusterIndex}; iAdjacentCluster < maxRowClusterIndex && iAdjacentCluster < nClustersAdjacentLayer; ++iAdjacentCluster) { const Cluster& adjacentCluster = store->getClusters()[static_cast<int>(adjacentLayerIndex)][iAdjacentCluster]; // assign-constructor may be a problem, check - if (gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - adjacentCluster.phiCoordinate) < phiCut) { + if (o2::gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - adjacentCluster.phiCoordinate) < phiCut) { if (storedTracklets < store->getConfig().maxTrackletsPerCluster) { if (layerOrder == TrackletingLayerOrder::fromInnermostToMiddleLayer) { store->getDuplets01().emplace(stride + storedTracklets, iAdjacentCluster, currentClusterIndex, adjacentCluster, currentCluster); @@ -208,8 +208,8 @@ GPUg() void trackletSelectionKernel( int validTracklets{0}; for (int iTracklet12{0}; iTracklet12 < store->getNFoundTracklets(TrackletingLayerOrder::fromMiddleToOuterLayer)[currentClusterIndex]; ++iTracklet12) { for (int iTracklet01{0}; iTracklet01 < store->getNFoundTracklets(TrackletingLayerOrder::fromInnermostToMiddleLayer)[currentClusterIndex] && validTracklets < store->getConfig().maxTrackletsPerCluster; ++iTracklet01) { - const float deltaTanLambda{gpu::GPUCommonMath::Abs(store->getDuplets01()[stride + iTracklet01].tanLambda - store->getDuplets12()[stride + iTracklet12].tanLambda)}; - const float deltaPhi{gpu::GPUCommonMath::Abs(store->getDuplets01()[stride + iTracklet01].phiCoordinate - store->getDuplets12()[stride + iTracklet12].phiCoordinate)}; + const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(store->getDuplets01()[stride + iTracklet01].tanLambda - store->getDuplets12()[stride + iTracklet12].tanLambda)}; + const float deltaPhi{o2::gpu::GPUCommonMath::Abs(store->getDuplets01()[stride + iTracklet01].phiCoordinate - store->getDuplets12()[stride + iTracklet12].phiCoordinate)}; if (deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != store->getConfig().maxTrackletsPerCluster) { assert(store->getDuplets01()[stride + iTracklet01].secondClusterIndex == store->getDuplets12()[stride + iTracklet12].firstClusterIndex); if (!isInitRun) { @@ -277,7 +277,7 @@ GPUg() void computeZCentroidsKernel(DeviceStoreVertexerHIP* store, float tmpX{store->getConfig().histConf.lowHistBoundariesXYZ[0] + store->getTmpVertexPositionBins()[0].key * store->getConfig().histConf.binSizeHistX + store->getConfig().histConf.binSizeHistX / 2}; int sumWX{store->getTmpVertexPositionBins()[0].value}; float wX{tmpX * store->getTmpVertexPositionBins()[0].value}; - for (int iBin{gpu::GPUCommonMath::Max(0, store->getTmpVertexPositionBins()[0].key - binOpeningX)}; iBin < gpu::GPUCommonMath::Min(store->getTmpVertexPositionBins()[0].key + binOpeningX + 1, store->getConfig().histConf.nBinsXYZ[0] - 1); ++iBin) { + for (int iBin{o2::gpu::GPUCommonMath::Max(0, store->getTmpVertexPositionBins()[0].key - binOpeningX)}; iBin < o2::gpu::GPUCommonMath::Min(store->getTmpVertexPositionBins()[0].key + binOpeningX + 1, store->getConfig().histConf.nBinsXYZ[0] - 1); ++iBin) { if (iBin != store->getTmpVertexPositionBins()[0].key) { wX += (store->getConfig().histConf.lowHistBoundariesXYZ[0] + iBin * store->getConfig().histConf.binSizeHistX + store->getConfig().histConf.binSizeHistX / 2) * store->getHistogramXYZ()[0].get()[iBin]; sumWX += store->getHistogramXYZ()[0].get()[iBin]; @@ -286,7 +286,7 @@ GPUg() void computeZCentroidsKernel(DeviceStoreVertexerHIP* store, float tmpY{store->getConfig().histConf.lowHistBoundariesXYZ[1] + store->getTmpVertexPositionBins()[1].key * store->getConfig().histConf.binSizeHistY + store->getConfig().histConf.binSizeHistY / 2}; int sumWY{store->getTmpVertexPositionBins()[1].value}; float wY{tmpY * store->getTmpVertexPositionBins()[1].value}; - for (int iBin{gpu::GPUCommonMath::Max(0, store->getTmpVertexPositionBins()[1].key - binOpeningY)}; iBin < gpu::GPUCommonMath::Min(store->getTmpVertexPositionBins()[1].key + binOpeningY + 1, store->getConfig().histConf.nBinsXYZ[1] - 1); ++iBin) { + for (int iBin{o2::gpu::GPUCommonMath::Max(0, store->getTmpVertexPositionBins()[1].key - binOpeningY)}; iBin < o2::gpu::GPUCommonMath::Min(store->getTmpVertexPositionBins()[1].key + binOpeningY + 1, store->getConfig().histConf.nBinsXYZ[1] - 1); ++iBin) { if (iBin != store->getTmpVertexPositionBins()[1].key) { wY += (store->getConfig().histConf.lowHistBoundariesXYZ[1] + iBin * store->getConfig().histConf.binSizeHistY + store->getConfig().histConf.binSizeHistY / 2) * store->getHistogramXYZ()[1].get()[iBin]; sumWY += store->getHistogramXYZ()[1].get()[iBin]; @@ -318,7 +318,7 @@ GPUg() void computeVertexKernel(DeviceStoreVertexerHIP* store, const int vertInd float ez{0.f}; int sumWZ{store->getTmpVertexPositionBins()[2].value}; float wZ{z * store->getTmpVertexPositionBins()[2].value}; - for (int iBin{gpu::GPUCommonMath::Max(0, store->getTmpVertexPositionBins()[2].key - binOpeningZ)}; iBin < gpu::GPUCommonMath::Min(store->getTmpVertexPositionBins()[2].key + binOpeningZ + 1, store->getConfig().histConf.nBinsXYZ[2] - 1); ++iBin) { + for (int iBin{o2::gpu::GPUCommonMath::Max(0, store->getTmpVertexPositionBins()[2].key - binOpeningZ)}; iBin < o2::gpu::GPUCommonMath::Min(store->getTmpVertexPositionBins()[2].key + binOpeningZ + 1, store->getConfig().histConf.nBinsXYZ[2] - 1); ++iBin) { if (iBin != store->getTmpVertexPositionBins()[2].key) { wZ += (store->getConfig().histConf.lowHistBoundariesXYZ[2] + iBin * store->getConfig().histConf.binSizeHistZ + store->getConfig().histConf.binSizeHistZ / 2) * store->getHistogramXYZ()[2].get()[iBin]; sumWZ += store->getHistogramXYZ()[2].get()[iBin]; @@ -336,7 +336,7 @@ GPUg() void computeVertexKernel(DeviceStoreVertexerHIP* store, const int vertInd } } } -} // namespace GPU +} // namespace gpu void VertexerTraitsHIP::computeTracklets() { @@ -344,17 +344,17 @@ void VertexerTraitsHIP::computeTracklets() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{GPU::Utils::HostHIP::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{GPU::Utils::HostHIP::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::Utils::HostHIP::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::Utils::HostHIP::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; - hipLaunchKernelGGL((GPU::trackleterKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, + hipLaunchKernelGGL((gpu::trackleterKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), - GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer, + gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer, mVrtParams.phiCut); - hipLaunchKernelGGL((GPU::trackleterKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, + hipLaunchKernelGGL((gpu::trackleterKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), - GPU::TrackletingLayerOrder::fromMiddleToOuterLayer, + gpu::TrackletingLayerOrder::fromMiddleToOuterLayer, mVrtParams.phiCut); gpuThrowOnError(); @@ -362,8 +362,8 @@ void VertexerTraitsHIP::computeTracklets() #ifdef _ALLOW_DEBUG_TREES_ITS_ if (isDebugFlag(VertexerDebug::CombinatoricsTreeAll)) { mDebugger->fillCombinatoricsTree(mClusters, - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer), - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer), mEvent); } #endif @@ -375,11 +375,11 @@ void VertexerTraitsHIP::computeTrackletMatching() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{GPU::Utils::HostHIP::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{GPU::Utils::HostHIP::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::Utils::HostHIP::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::Utils::HostHIP::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; size_t bufferSize = mStoreVertexerGPU.getConfig().tmpCUBBufferSize * sizeof(int); - hipLaunchKernelGGL((GPU::trackletSelectionKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, + hipLaunchKernelGGL((gpu::trackletSelectionKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), true, // isInitRun mVrtParams.tanLambdaCut, @@ -391,7 +391,7 @@ void VertexerTraitsHIP::computeTrackletMatching() mStoreVertexerGPU.getNExclusiveFoundLines().get(), mClusters[1].size()); - hipLaunchKernelGGL((GPU::trackletSelectionKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, + hipLaunchKernelGGL((gpu::trackletSelectionKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), false, // isInitRun mVrtParams.tanLambdaCut, @@ -402,8 +402,8 @@ void VertexerTraitsHIP::computeTrackletMatching() #ifdef _ALLOW_DEBUG_TREES_ITS_ if (isDebugFlag(VertexerDebug::TrackletTreeAll)) { mDebugger->fillTrackletSelectionTree(mClusters, - mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer), - mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer), + mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer), + mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer), mStoreVertexerGPU.getDupletIndicesFromGPU(), mEvent); } @@ -423,15 +423,15 @@ void VertexerTraitsHIP::computeVertices() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{GPU::Utils::HostHIP::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{GPU::Utils::HostHIP::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::Utils::HostHIP::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::Utils::HostHIP::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; size_t bufferSize = mStoreVertexerGPU.getConfig().tmpCUBBufferSize * sizeof(int); int nLines = mStoreVertexerGPU.getNExclusiveFoundLines().getElementFromDevice(mClusters[1].size() - 1) + mStoreVertexerGPU.getNFoundLines().getElementFromDevice(mClusters[1].size() - 1); int nCentroids{static_cast<int>(nLines * (nLines - 1) / 2)}; int* histogramXY[2] = {mStoreVertexerGPU.getHistogramXYZ()[0].get(), mStoreVertexerGPU.getHistogramXYZ()[1].get()}; float tmpArrayLow[2] = {mStoreVertexerGPU.getConfig().histConf.lowHistBoundariesXYZ[0], mStoreVertexerGPU.getConfig().histConf.lowHistBoundariesXYZ[1]}; float tmpArrayHigh[2] = {mStoreVertexerGPU.getConfig().histConf.highHistBoundariesXYZ[0], mStoreVertexerGPU.getConfig().histConf.highHistBoundariesXYZ[1]}; - hipLaunchKernelGGL((GPU::computeCentroidsKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), + hipLaunchKernelGGL((gpu::computeCentroidsKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), mVrtParams.histPairCut); (void)hipcub::DeviceHistogram::MultiHistogramEven<2, 2>(reinterpret_cast<void*>(mStoreVertexerGPU.getCUBTmpBuffer().get()), // d_temp_storage @@ -454,7 +454,7 @@ void VertexerTraitsHIP::computeVertices() mStoreVertexerGPU.getTmpVertexPositionBins().get() + 1, mStoreVertexerGPU.getConfig().histConf.nBinsXYZ[0]); - hipLaunchKernelGGL((GPU::computeZCentroidsKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), mVrtParams.histPairCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[0], mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[1]); + hipLaunchKernelGGL((gpu::computeZCentroidsKernel), dim3(blocksGrid), dim3(threadsPerBlock), 0, 0, getDeviceContextPtr(), mVrtParams.histPairCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[0], mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[1]); (void)hipcub::DeviceHistogram::HistogramEven(reinterpret_cast<void*>(mStoreVertexerGPU.getCUBTmpBuffer().get()), // d_temp_storage bufferSize, // temp_storage_bytes @@ -480,9 +480,9 @@ void VertexerTraitsHIP::computeVertices() mStoreVertexerGPU.getConfig().histConf.nBinsXYZ[2] - 1}); } #endif - hipLaunchKernelGGL((GPU::computeVertexKernel), dim3(blocksGrid), dim3(5), 0, 0, getDeviceContextPtr(), iVertex, mVrtParams.clusterContributorsCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[2]); + hipLaunchKernelGGL((gpu::computeVertexKernel), dim3(blocksGrid), dim3(5), 0, 0, getDeviceContextPtr(), iVertex, mVrtParams.clusterContributorsCut, mStoreVertexerGPU.getConfig().histConf.binSpanXYZ[2]); } - std::vector<GPU::GPUVertex> vertices; + std::vector<gpu::GPUVertex> vertices; vertices.resize(mStoreVertexerGPU.getConfig().nMaxVertices); mStoreVertexerGPU.getVertices().copyIntoSizedVector(vertices); @@ -498,23 +498,23 @@ void VertexerTraitsHIP::computeVertices() #ifdef _ALLOW_DEBUG_TREES_ITS_ void VertexerTraitsHIP::computeMCFiltering() { - std::vector<Tracklet> tracklets01 = mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer); - std::vector<Tracklet> tracklets12 = mStoreVertexerGPU.getRawDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer); - std::vector<int> labels01 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer); - std::vector<int> labels12 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer); + std::vector<Tracklet> tracklets01 = mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer); + std::vector<Tracklet> tracklets12 = mStoreVertexerGPU.getRawDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer); + std::vector<int> labels01 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer); + std::vector<int> labels12 = mStoreVertexerGPU.getNFoundTrackletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer); VertexerStoreConfigurationGPU tmpGPUConf; const int stride = tmpGPUConf.maxTrackletsPerCluster; filterTrackletsWithMC(tracklets01, tracklets12, labels01, labels12, stride); - mStoreVertexerGPU.updateFoundDuplets(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer, labels01); - mStoreVertexerGPU.updateDuplets(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer, tracklets01); - mStoreVertexerGPU.updateFoundDuplets(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer, labels12); - mStoreVertexerGPU.updateDuplets(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer, tracklets12); + mStoreVertexerGPU.updateFoundDuplets(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer, labels01); + mStoreVertexerGPU.updateDuplets(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer, tracklets01); + mStoreVertexerGPU.updateFoundDuplets(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer, labels12); + mStoreVertexerGPU.updateDuplets(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer, tracklets12); if (isDebugFlag(VertexerDebug::CombinatoricsTreeAll)) { mDebugger->fillCombinatoricsTree(mClusters, - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromInnermostToMiddleLayer), - mStoreVertexerGPU.getDupletsFromGPU(GPU::TrackletingLayerOrder::fromMiddleToOuterLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromInnermostToMiddleLayer), + mStoreVertexerGPU.getDupletsFromGPU(gpu::TrackletingLayerOrder::fromMiddleToOuterLayer), mEvent); } } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h index 16a3446eaf72f..4f1b6c4c8cab1 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h @@ -88,8 +88,8 @@ GPUhdi() Line::Line(const float firstPoint[3], const float secondPoint[3]) cosinesDirector[i] = secondPoint[i] - firstPoint[i]; } - float inverseNorm{1.f / gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + - cosinesDirector[2] * cosinesDirector[2])}; + float inverseNorm{1.f / o2::gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + + cosinesDirector[2] * cosinesDirector[2])}; for (int index{0}; index < 3; ++index) { cosinesDirector[index] *= inverseNorm; @@ -106,8 +106,8 @@ GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, cons cosinesDirector[1] = outerClusters[tracklet.secondClusterIndex].yCoordinate - innerClusters[tracklet.firstClusterIndex].yCoordinate; cosinesDirector[2] = outerClusters[tracklet.secondClusterIndex].zCoordinate - innerClusters[tracklet.firstClusterIndex].zCoordinate; - float inverseNorm{1.f / gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + - cosinesDirector[2] * cosinesDirector[2])}; + float inverseNorm{1.f / o2::gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + + cosinesDirector[2] * cosinesDirector[2])}; for (int index{0}; index < 3; ++index) { cosinesDirector[index] *= inverseNorm; @@ -125,8 +125,8 @@ GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, cons cosinesDirector[1] = outerClusters[tracklet.secondClusterIndex].yCoordinate - innerClusters[tracklet.firstClusterIndex].yCoordinate; cosinesDirector[2] = outerClusters[tracklet.secondClusterIndex].zCoordinate - innerClusters[tracklet.firstClusterIndex].zCoordinate; - float inverseNorm{1.f / gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + - cosinesDirector[2] * cosinesDirector[2])}; + float inverseNorm{1.f / o2::gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + + cosinesDirector[2] * cosinesDirector[2])}; for (int index{0}; index < 3; ++index) cosinesDirector[index] *= inverseNorm; @@ -145,7 +145,7 @@ inline float Line::getDistanceFromPoint(const Line& line, const std::array<float DCASquared += (line.originPoint[i] - point[i] + line.cosinesDirector[i] * cdelta) * (line.originPoint[i] - point[i] + line.cosinesDirector[i] * cdelta); } - return gpu::CAMath::Sqrt(DCASquared); + return o2::gpu::CAMath::Sqrt(DCASquared); } GPUhdi() float Line::getDistanceFromPoint(const Line& line, const float point[3]) @@ -159,7 +159,7 @@ GPUhdi() float Line::getDistanceFromPoint(const Line& line, const float point[3] DCASquared += (line.originPoint[i] - point[i] + line.cosinesDirector[i] * cdelta) * (line.originPoint[i] - point[i] + line.cosinesDirector[i] * cdelta); } - return gpu::CAMath::Sqrt(DCASquared); + return o2::gpu::CAMath::Sqrt(DCASquared); } GPUhdi() float Line::getDCA(const Line& firstLine, const Line& secondLine, const float precision) @@ -178,7 +178,7 @@ GPUhdi() float Line::getDCA(const Line& firstLine, const Line& secondLine, const distance += (secondLine.originPoint[i] - firstLine.originPoint[i]) * normalVector[i]; } if (norm > precision) { - return gpu::CAMath::Abs(distance / gpu::CAMath::Sqrt(norm)); + return o2::gpu::CAMath::Abs(distance / o2::gpu::CAMath::Sqrt(norm)); } else { #if defined(__CUDACC__) || defined(__HIPCC__) float stdOriginPoint[3]; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 671804e39b3b2..0c58a98b17184 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -144,7 +144,7 @@ struct VertexerStoreConfigurationGPU { int maxTrkCap, int maxVert); - // o2::its::GPU::Vector constructor requires signed size for initialisation + // o2::its::gpu::Vector constructor requires signed size for initialisation int tmpCUBBufferSize = 25e5; int maxTrackletsPerCluster = 2e2; int clustersPerLayerCapacity = 4e4; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index a14feb19203dc..02d6121deac6a 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -98,8 +98,8 @@ GPUhdi() int getPhiBinIndex(const float currentPhi) GPUhdi() int getBinIndex(const int zIndex, const int phiIndex) { - return gpu::GPUCommonMath::Min(phiIndex * ZBins + zIndex, - ZBins * PhiBins - 1); + return o2::gpu::GPUCommonMath::Min(phiIndex * ZBins + zIndex, + ZBins * PhiBins - 1); } GPUhdi() constexpr int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index c3f9ca43f2ac0..b54b91801b267 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -65,7 +65,7 @@ #include "ITStrackingCUDA/Array.h" template <typename T, size_t Size> -using GPUArray = o2::its::GPU::Array<T, Size>; +using GPUArray = o2::its::gpu::Array<T, Size>; typedef cudaStream_t GPUStream; @@ -94,7 +94,7 @@ using GPUArray = std::array<T, Size>; #include "ITStrackingCUDA/Array.h" template <typename T, size_t Size> -using GPUArray = o2::its::GPU::Array<T, Size>; +using GPUArray = o2::its::gpu::Array<T, Size>; #endif typedef struct _dummyStream { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h index 034994ca898f5..3f9e85f887896 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h @@ -85,7 +85,7 @@ GPUhdi() int IndexTableUtils::getPhiBinIndex(const float currentPhi) const GPUhdi() int IndexTableUtils::getBinIndex(const int zIndex, const int phiIndex) const { - return gpu::GPUCommonMath::Min(phiIndex * mNzBins + zIndex, mNzBins * mNphiBins - 1); + return o2::gpu::GPUCommonMath::Min(phiIndex * mNzBins + zIndex, mNzBins * mNphiBins - 1); } GPUhdi() int IndexTableUtils::countRowSelectedBins(const int* indexTable, const int phiBinIndex, diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 913cc5dc805ac..249d2ea838d36 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -80,9 +80,9 @@ inline void TrackerTraits::UpdateTrackingParameters(const TrackingParameters& tr inline GPU_DEVICE const int4 TrackerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, const float z1, const float z2, float maxdeltaz, float maxdeltaphi) { - const float zRangeMin = gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; + const float zRangeMin = o2::gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; const float phiRangeMin = currentCluster.phiCoordinate - maxdeltaphi; - const float zRangeMax = gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; + const float zRangeMax = o2::gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; const float phiRangeMax = currentCluster.phiCoordinate + maxdeltaphi; if (zRangeMax < -mTrkParams.LayerZ[layerIndex + 1] || @@ -92,9 +92,9 @@ inline GPU_DEVICE const int4 TrackerTraits::getBinsRect(const Cluster& currentCl } const IndexTableUtils& utils{mPrimaryVertexContext->mIndexTableUtils}; - return int4{gpu::GPUCommonMath::Max(0, utils.getZBinIndex(layerIndex + 1, zRangeMin)), + return int4{o2::gpu::GPUCommonMath::Max(0, utils.getZBinIndex(layerIndex + 1, zRangeMin)), utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMin)), - gpu::GPUCommonMath::Min(mTrkParams.ZBins - 1, utils.getZBinIndex(layerIndex + 1, zRangeMax)), + o2::gpu::GPUCommonMath::Min(mTrkParams.ZBins - 1, utils.getZBinIndex(layerIndex + 1, zRangeMax)), utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMax))}; } } // namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h index e2b39b99efbe3..23f2be272ec5c 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h @@ -51,8 +51,8 @@ GPUdi() Tracklet::Tracklet(const int firstClusterOrderingIndex, const int second secondClusterIndex{secondClusterOrderingIndex}, tanLambda{(firstCluster.zCoordinate - secondCluster.zCoordinate) / (firstCluster.rCoordinate - secondCluster.rCoordinate)}, - phiCoordinate{gpu::GPUCommonMath::ATan2(firstCluster.yCoordinate - secondCluster.yCoordinate, - firstCluster.xCoordinate - secondCluster.xCoordinate)} + phiCoordinate{o2::gpu::GPUCommonMath::ATan2(firstCluster.yCoordinate - secondCluster.yCoordinate, + firstCluster.xCoordinate - secondCluster.xCoordinate)} { // Nothing to do } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index 97e1dcde9cf52..ff657120d0b70 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -231,9 +231,9 @@ GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentCluster, c return getEmptyBinsRect(); } - return int4{gpu::GPUCommonMath::Max(0, utils.getZBinIndex(layerIndex + 1, zRangeMin)), + return int4{o2::gpu::GPUCommonMath::Max(0, utils.getZBinIndex(layerIndex + 1, zRangeMin)), utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMin)), - gpu::GPUCommonMath::Min(utils.getNzBins() - 1, utils.getZBinIndex(layerIndex + 1, zRangeMax)), + o2::gpu::GPUCommonMath::Min(utils.getNzBins() - 1, utils.getZBinIndex(layerIndex + 1, zRangeMax)), utils.getPhiBinIndex(math_utils::getNormalizedPhiCoordinate(phiRangeMax))}; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx b/Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx index 52795b0287246..45eaebb76b54f 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx @@ -33,9 +33,9 @@ Centroid::Centroid(int* indices, float* position) float Centroid::ComputeDistance(const Centroid& c1, const Centroid& c2) { - return gpu::GPUCommonMath::Sqrt((c1.mPosition[0] - c2.mPosition[0]) * (c1.mPosition[0] - c2.mPosition[0]) + - (c1.mPosition[1] - c2.mPosition[1]) * (c1.mPosition[1] - c2.mPosition[1]) + - (c1.mPosition[2] - c2.mPosition[2]) * (c1.mPosition[2] - c2.mPosition[2])); + return o2::gpu::GPUCommonMath::Sqrt((c1.mPosition[0] - c2.mPosition[0]) * (c1.mPosition[0] - c2.mPosition[0]) + + (c1.mPosition[1] - c2.mPosition[1]) * (c1.mPosition[1] - c2.mPosition[1]) + + (c1.mPosition[2] - c2.mPosition[2]) * (c1.mPosition[2] - c2.mPosition[2])); } } // namespace its } // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx index 12e69222e0653..9567162b40376 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx @@ -80,8 +80,8 @@ void PrimaryVertexContext::initialise(const MemoryParameters& memParam, const Tr CA_DEBUGGER(assert(zBin > 0)); h.phi = phi; h.r = math_utils::calculateRCoordinate(x, y); - mMinR[iLayer] = gpu::GPUCommonMath::Min(h.r, mMinR[iLayer]); - mMaxR[iLayer] = gpu::GPUCommonMath::Max(h.r, mMaxR[iLayer]); + mMinR[iLayer] = o2::gpu::GPUCommonMath::Min(h.r, mMinR[iLayer]); + mMaxR[iLayer] = o2::gpu::GPUCommonMath::Max(h.r, mMaxR[iLayer]); h.bin = bin; h.ind = clsPerBin[bin]++; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx index 8dcb743d14e25..456168f74554f 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx @@ -90,13 +90,13 @@ void TrackerTraitsCPU::computeLayerTracklets() continue; } - const float deltaZ{gpu::GPUCommonMath::Abs(tanLambda * (nextCluster.rCoordinate - currentCluster.rCoordinate) + - currentCluster.zCoordinate - nextCluster.zCoordinate)}; - const float deltaPhi{gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - nextCluster.phiCoordinate)}; + const float deltaZ{o2::gpu::GPUCommonMath::Abs(tanLambda * (nextCluster.rCoordinate - currentCluster.rCoordinate) + + currentCluster.zCoordinate - nextCluster.zCoordinate)}; + const float deltaPhi{o2::gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - nextCluster.phiCoordinate)}; if (deltaZ < mTrkParams.TrackletMaxDeltaZ[iLayer] && (deltaPhi < mTrkParams.TrackletMaxDeltaPhi || - gpu::GPUCommonMath::Abs(deltaPhi - constants::math::TwoPi) < mTrkParams.TrackletMaxDeltaPhi)) { + o2::gpu::GPUCommonMath::Abs(deltaPhi - constants::math::TwoPi) < mTrkParams.TrackletMaxDeltaPhi)) { if (iLayer > 0 && primaryVertexContext->getTrackletsLookupTable()[iLayer - 1][iCluster] == constants::its::UnusedIndex) { diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index b407d2059acaf..a8e823c38399f 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -74,7 +74,7 @@ void trackleterKernelSerial( // loop on clusters next layer for (int iNextLayerClusterIndex{firstRowClusterIndex}; iNextLayerClusterIndex < maxRowClusterIndex && iNextLayerClusterIndex < static_cast<int>(clustersNextLayer.size()); ++iNextLayerClusterIndex) { const Cluster& nextCluster{clustersNextLayer[iNextLayerClusterIndex]}; - if (gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - nextCluster.phiCoordinate) < phiCut) { + if (o2::gpu::GPUCommonMath::Abs(currentCluster.phiCoordinate - nextCluster.phiCoordinate) < phiCut) { if (storedTracklets < maxTrackletsPerCluster) { if (pairOfLayers == LAYER0_TO_LAYER1) { Tracklets.emplace_back(iNextLayerClusterIndex, iCurrentLayerClusterIndex, nextCluster, currentCluster); @@ -114,8 +114,8 @@ void trackletSelectionKernelSerial( int validTracklets{0}; for (int iTracklet12{offset12}; iTracklet12 < offset12 + foundTracklets12[iCurrentLayerClusterIndex]; ++iTracklet12) { for (int iTracklet01{offset01}; iTracklet01 < offset01 + foundTracklets01[iCurrentLayerClusterIndex]; ++iTracklet01) { - const float deltaTanLambda{gpu::GPUCommonMath::Abs(tracklets01[iTracklet01].tanLambda - tracklets12[iTracklet12].tanLambda)}; - const float deltaPhi{gpu::GPUCommonMath::Abs(tracklets01[iTracklet01].phiCoordinate - tracklets12[iTracklet12].phiCoordinate)}; + const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(tracklets01[iTracklet01].tanLambda - tracklets12[iTracklet12].tanLambda)}; + const float deltaPhi{o2::gpu::GPUCommonMath::Abs(tracklets01[iTracklet01].phiCoordinate - tracklets12[iTracklet12].phiCoordinate)}; if (deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != maxTracklets) { assert(tracklets01[iTracklet01].secondClusterIndex == tracklets12[iTracklet12].firstClusterIndex); #ifdef _ALLOW_DEBUG_TREES_ITS_ From 53cd0b41a6b3476d3388b39297ec3bfdc14b4a16 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Thu, 10 Dec 2020 09:19:24 +0100 Subject: [PATCH 1589/1751] Moving StepTHn to Framework (#5034) --- Analysis/Core/CMakeLists.txt | 2 +- Framework/AnalysisTools/CMakeLists.txt | 17 ----------------- .../AnalysisTools/src/AnalysisToolsLinkDef.h | 19 ------------------- Framework/CMakeLists.txt | 2 -- Framework/Core/CMakeLists.txt | 2 ++ .../include/Framework/StepTHn.h | 0 .../{AnalysisTools => Core}/src/StepTHn.cxx | 0 .../Core/test/FrameworkCoreTestLinkDef.h | 6 ++++++ 8 files changed, 9 insertions(+), 39 deletions(-) delete mode 100644 Framework/AnalysisTools/CMakeLists.txt delete mode 100644 Framework/AnalysisTools/src/AnalysisToolsLinkDef.h rename Framework/{AnalysisTools => Core}/include/Framework/StepTHn.h (100%) rename Framework/{AnalysisTools => Core}/src/StepTHn.cxx (100%) diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index b56c698e27264..f279a753f0b93 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -17,7 +17,7 @@ o2_add_library(AnalysisCore src/AnalysisCompositeCut.cxx src/TriggerAliases.cxx src/HFConfigurables.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisTools) + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel) o2_target_root_dictionary(AnalysisCore HEADERS include/AnalysisCore/CorrelationContainer.h diff --git a/Framework/AnalysisTools/CMakeLists.txt b/Framework/AnalysisTools/CMakeLists.txt deleted file mode 100644 index 17a188a04298b..0000000000000 --- a/Framework/AnalysisTools/CMakeLists.txt +++ /dev/null @@ -1,17 +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. - -o2_add_library(AnalysisTools - SOURCES src/StepTHn.cxx - PUBLIC_LINK_LIBRARIES O2::Framework) - -o2_target_root_dictionary(AnalysisTools - HEADERS include/Framework/StepTHn.h - LINKDEF src/AnalysisToolsLinkDef.h) diff --git a/Framework/AnalysisTools/src/AnalysisToolsLinkDef.h b/Framework/AnalysisTools/src/AnalysisToolsLinkDef.h deleted file mode 100644 index 368cb36e4b745..0000000000000 --- a/Framework/AnalysisTools/src/AnalysisToolsLinkDef.h +++ /dev/null @@ -1,19 +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. - -#pragma link off all globals; -#pragma link off all classes; -#pragma link off all functions; - -#pragma link C++ class StepTHn + ; -#pragma link C++ class StepTHnT < TArrayF> + ; -#pragma link C++ class StepTHnT < TArrayD> + ; -#pragma link C++ typedef StepTHnF; -#pragma link C++ typedef StepTHnD; diff --git a/Framework/CMakeLists.txt b/Framework/CMakeLists.txt index 17b18bebad581..3edb89db53770 100644 --- a/Framework/CMakeLists.txt +++ b/Framework/CMakeLists.txt @@ -17,5 +17,3 @@ add_subdirectory(Core) add_subdirectory(Utils) add_subdirectory(TestWorkflows) - -add_subdirectory(AnalysisTools) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index badffa9815841..fa4c2fc5fdc5a 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -104,6 +104,7 @@ o2_add_library(Framework src/runDataProcessing.cxx src/ExternalFairMQDeviceProxy.cxx src/HistogramRegistry.cxx + src/StepTHn.cxx test/TestClasses.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src PUBLIC_LINK_LIBRARIES ${DEBUGGUI_TARGET} @@ -132,6 +133,7 @@ o2_add_library(Framework o2_target_root_dictionary(Framework HEADERS test/TestClasses.h + include/Framework/StepTHn.h LINKDEF test/FrameworkCoreTestLinkDef.h) foreach(t diff --git a/Framework/AnalysisTools/include/Framework/StepTHn.h b/Framework/Core/include/Framework/StepTHn.h similarity index 100% rename from Framework/AnalysisTools/include/Framework/StepTHn.h rename to Framework/Core/include/Framework/StepTHn.h diff --git a/Framework/AnalysisTools/src/StepTHn.cxx b/Framework/Core/src/StepTHn.cxx similarity index 100% rename from Framework/AnalysisTools/src/StepTHn.cxx rename to Framework/Core/src/StepTHn.cxx diff --git a/Framework/Core/test/FrameworkCoreTestLinkDef.h b/Framework/Core/test/FrameworkCoreTestLinkDef.h index e7aa30ec99193..9c4de4d65057d 100644 --- a/Framework/Core/test/FrameworkCoreTestLinkDef.h +++ b/Framework/Core/test/FrameworkCoreTestLinkDef.h @@ -18,3 +18,9 @@ #pragma link C++ class o2::test::SimplePODClass + ; #pragma link C++ class std::vector < o2::test::TriviallyCopyable > +; #pragma link C++ class std::vector < o2::test::Polymorphic > +; + +#pragma link C++ class StepTHn + ; +#pragma link C++ class StepTHnT < TArrayF> + ; +#pragma link C++ class StepTHnT < TArrayD> + ; +#pragma link C++ typedef StepTHnF; +#pragma link C++ typedef StepTHnD; From be0e4158a34d5cd9a10285e93a99c1263adfe731 Mon Sep 17 00:00:00 2001 From: Jason Barrella <32719308+jbarrella@users.noreply.github.com> Date: Thu, 10 Dec 2020 14:32:21 +0200 Subject: [PATCH 1590/1751] TRD Tracklet Transformer Workflow (#4790) --- DataFormats/Detectors/TRD/CMakeLists.txt | 3 +- .../DataFormatsTRD/CalibratedTracklet.h | 52 ++++++ .../TRD/include/DataFormatsTRD/Constants.h | 5 + .../Detectors/TRD/src/DataFormatsTRDLinkDef.h | 2 + Detectors/TRD/base/CMakeLists.txt | 4 +- .../include/TRDBase/TrackletTransformer.h | 71 ++++++++ .../TRD/base/src/TrackletTransformer.cxx | 158 ++++++++++++++++++ Detectors/TRD/workflow/CMakeLists.txt | 7 + .../TRDCalibratedTrackletWriterSpec.h | 26 +++ .../TRDWorkflow/TRDTrackletTransformerSpec.h | 36 ++++ .../src/TRDCalibratedTrackletWriterSpec.cxx | 39 +++++ .../src/TRDTrackletTransformerSpec.cxx | 73 ++++++++ .../src/TRDTrackletTransformerWorkflow.cxx | 48 ++++++ 13 files changed, 522 insertions(+), 2 deletions(-) create mode 100644 DataFormats/Detectors/TRD/include/DataFormatsTRD/CalibratedTracklet.h create mode 100644 Detectors/TRD/base/include/TRDBase/TrackletTransformer.h create mode 100644 Detectors/TRD/base/src/TrackletTransformer.cxx create mode 100644 Detectors/TRD/workflow/include/TRDWorkflow/TRDCalibratedTrackletWriterSpec.h create mode 100644 Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletTransformerSpec.h create mode 100644 Detectors/TRD/workflow/src/TRDCalibratedTrackletWriterSpec.cxx create mode 100644 Detectors/TRD/workflow/src/TRDTrackletTransformerSpec.cxx create mode 100644 Detectors/TRD/workflow/src/TRDTrackletTransformerWorkflow.cxx diff --git a/DataFormats/Detectors/TRD/CMakeLists.txt b/DataFormats/Detectors/TRD/CMakeLists.txt index d41cc697843a9..c8e9a8ab4ffdd 100644 --- a/DataFormats/Detectors/TRD/CMakeLists.txt +++ b/DataFormats/Detectors/TRD/CMakeLists.txt @@ -20,4 +20,5 @@ o2_add_library(DataFormatsTRD include/DataFormatsTRD/LinkRecord.h include/DataFormatsTRD/Tracklet64.h include/DataFormatsTRD/RawData.h - include/DataFormatsTRD/Constants.h) + include/DataFormatsTRD/Constants.h + include/DataFormatsTRD/CalibratedTracklet.h) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/CalibratedTracklet.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/CalibratedTracklet.h new file mode 100644 index 0000000000000..8944d4ed610b9 --- /dev/null +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/CalibratedTracklet.h @@ -0,0 +1,52 @@ +// 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_TRD_CALIBRATEDTRACKLET_H +#define O2_TRD_CALIBRATEDTRACKLET_H + +#include "DataFormatsTRD/Tracklet64.h" + +namespace o2 +{ +namespace trd +{ + +// The CalibratedTracklet has been calibrated in x and dy according to a calculated Lorentz Angle and Drift Velocity. +// Tracklet positions in local z direction are reported at the center of the pad-row. +// Pad-tilting correction is performed after tracking. +class CalibratedTracklet : public Tracklet64 +{ + public: + CalibratedTracklet() = default; + CalibratedTracklet(uint64_t trackletWord, float x, float y, float z, float dy) + : Tracklet64(trackletWord), mx(x), my(y), mz(z), mdy(dy){}; + ~CalibratedTracklet() = default; + + float getX() { return mx; } + float getY() { return my; } + float getZ() { return mz; } + float getDy() { return mdy; } + + void setX(float x) { mx = x; } + void setY(float y) { my = y; } + void setZ(float z) { mz = z; } + void setDy(float dy) { mdy = dy; } + + private: + float mx; + float my; + float mz; + float mdy; +}; + +} // namespace trd +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h index 39aa176c0e0a7..6233327914f9e 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Constants.h @@ -40,6 +40,11 @@ constexpr int NROBC1 = 8; // the number of ROBs per C1 chamber constexpr int NADCMCM = 21; // the number of ADC channels per MCM constexpr int NCOLMCM = 18; // the number of pads per MCM +constexpr int NBITSTRKLPOS = 11; // number of bits for position in tracklet64 word +constexpr int NBITSTRKLSLOPE = 8; // number of bits for slope in tracklet64 word +constexpr float GRANULARITYTRKLPOS = 1.f / 75; // granularity of position in tracklet64 word in pad-widths +constexpr float GRANULARITYTRKLSLOPE = 1.f / 1000; // granularity of slope in tracklet64 word in pads/timebin + // OS: Should this not be flexible for example in case of Kr calib? constexpr int TIMEBINS = 30; // the number of time bins diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index 4fe89c45df5ff..2fc0cbc2ee316 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -21,7 +21,9 @@ #pragma link C++ struct o2::trd::TrackletMCMHeader + ; #pragma link C++ struct o2::trd::TrackletMCMData + ; #pragma link C++ class o2::trd::Tracklet64 + ; +#pragma link C++ class o2::trd::CalibratedTracklet + ; #pragma link C++ class std::vector < o2::trd::Tracklet64> + ; +#pragma link C++ class std::vector < o2::trd::CalibratedTracklet> + ; #pragma link C++ class std::vector < o2::trd::TriggerRecord > +; #pragma link C++ class std::vector < o2::trd::LinkRecord > +; diff --git a/Detectors/TRD/base/CMakeLists.txt b/Detectors/TRD/base/CMakeLists.txt index d61d638a63fc4..cf970c5282758 100644 --- a/Detectors/TRD/base/CMakeLists.txt +++ b/Detectors/TRD/base/CMakeLists.txt @@ -29,6 +29,7 @@ o2_add_library(TRDBase src/ChamberNoise.cxx src/CalOnlineGainTables.cxx src/Tracklet.cxx + src/TrackletTransformer.cxx PUBLIC_LINK_LIBRARIES O2::GPUCommon O2::GPUUtils O2::DetectorsCommonDataFormats @@ -63,7 +64,8 @@ o2_target_root_dictionary(TRDBase include/TRDBase/Calibrations.h include/TRDBase/ChamberNoise.h include/TRDBase/CalOnlineGainTables.h - include/TRDBase/Tracklet.h) + include/TRDBase/Tracklet.h + include/TRDBase/TrackletTransformer.h) o2_add_test(DiffusionCoefficient SOURCES test/testTRDDiffusionCoefficient.cxx diff --git a/Detectors/TRD/base/include/TRDBase/TrackletTransformer.h b/Detectors/TRD/base/include/TRDBase/TrackletTransformer.h new file mode 100644 index 0000000000000..80614fb2df6d8 --- /dev/null +++ b/Detectors/TRD/base/include/TRDBase/TrackletTransformer.h @@ -0,0 +1,71 @@ +// 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_TRD_TRACKLETTRANSFORMER_H +#define O2_TRD_TRACKLETTRANSFORMER_H + +#include "TRDBase/Geometry.h" +#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/CalibratedTracklet.h" + +namespace o2 +{ +namespace trd +{ + +class TrackletTransformer +{ + public: + TrackletTransformer(); + ~TrackletTransformer() = default; + + float getXCathode() { return mXCathode; } + float getXAnode() { return mXAnode; } + float getXDrift() { return mXDrift; } + float getXtb0() { return mXtb0; } + + void setXCathode(float x) { mXCathode = x; } + void setXAnode(float x) { mXAnode = x; } + void setXDrift(float x) { mXDrift = x; } + void setXtb0(float x) { mXtb0 = x; } + + void loadPadPlane(int hcid); + + float calculateY(int hcid, int column, int position); + + float calculateZ(int padrow); + + float calculateDy(int slope, double oldLorentzAngle, double lorentzAngle, double driftVRatio); + + float calibrateX(double x, double t0Correction); + + std::array<float, 3> transformL2T(int hcid, std::array<double, 3> spacePoint); + + CalibratedTracklet transformTracklet(Tracklet64 tracklet); + + private: + o2::trd::Geometry* mGeo; + const o2::trd::PadPlane* mPadPlane; + + float mXCathode; + float mXAnode; + float mXDrift; + float mXtb0; + + float mt0Correction; + float mOldLorentzAngle; + float mLorentzAngle; + float mDriftVRatio; +}; + +} // namespace trd +} // namespace o2 + +#endif diff --git a/Detectors/TRD/base/src/TrackletTransformer.cxx b/Detectors/TRD/base/src/TrackletTransformer.cxx new file mode 100644 index 0000000000000..986d57c2426e9 --- /dev/null +++ b/Detectors/TRD/base/src/TrackletTransformer.cxx @@ -0,0 +1,158 @@ +// 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 "DetectorsBase/GeometryManager.h" +#include "TRDBase/TrackletTransformer.h" +#include "TMath.h" + +using namespace o2::trd; +using namespace o2::trd::constants; + +TrackletTransformer::TrackletTransformer() +{ + o2::base::GeometryManager::loadGeometry(); + mGeo = Geometry::instance(); + mGeo->createPadPlaneArray(); + mGeo->createClusterMatrixArray(); + + // 3 cm + mXCathode = mGeo->cdrHght(); + // 2.221 + // mXAnode = mGeo->anodePos(); + // 3.35 + mXAnode = mGeo->cdrHght() + mGeo->camHght() / 2; + // 2.5 + mXDrift = mGeo->cdrHght() - 0.5; + mXtb0 = -100; + + // dummy values for testing. This will change in the future when values are pulled from CCDB + mt0Correction = -0.1; + mOldLorentzAngle = 0.16; + mLorentzAngle = -0.14; + mDriftVRatio = 1.1; +} + +void TrackletTransformer::loadPadPlane(int hcid) +{ + int detector = hcid / 2; + int stack = mGeo->getStack(detector); + int layer = mGeo->getLayer(detector); + mPadPlane = mGeo->getPadPlane(layer, stack); +} + +float TrackletTransformer::calculateY(int hcid, int column, int position) +{ + double padWidth = mPadPlane->getWidthIPad(); + int side = hcid % 2; + + // slightly modified TDP eq 16.1 (appended -1 to the end to account for MCM shared pads) + double pad = float(position - (1 << (NBITSTRKLPOS - 1))) * GRANULARITYTRKLPOS + NCOLMCM * (4 * side + column) + 10.5 - 1; + float y = padWidth * (pad - 72); + + return y; +} + +float TrackletTransformer::calculateZ(int padrow) +{ + double rowPos = mPadPlane->getRowPos(padrow); + double rowWidth = mPadPlane->getRowSize(padrow); + double middleRowPos = mPadPlane->getRowPos(mPadPlane->getNrows() / 2); + + float z = rowPos - rowWidth / 2. - middleRowPos; + + return z; +} + +float TrackletTransformer::calculateDy(int slope, double oldLorentzAngle, double lorentzAngle, double driftVRatio) +{ + double padWidth = mPadPlane->getWidthIPad(); + + // temporary dummy value in cm/microsecond + float vDrift = 1.56; + float driftHeight = mGeo->cdrHght(); + + // dy = slope * nTimeBins * padWidth * GRANULARITYTRKLSLOPE; + // nTimeBins should be number of timebins in drift region. 1 timebin is 100 nanosecond + double rawDy = slope * ((driftHeight / vDrift) / 0.1) * padWidth * GRANULARITYTRKLSLOPE; + + // driftDistance = 3.35 + float driftDistance = mGeo->cdrHght() + mGeo->camHght(); + + float cmSlope = rawDy / driftDistance; + + double calibratedDy = rawDy - (TMath::Tan(lorentzAngle) * driftDistance); + calibratedDy += (TMath::Tan(oldLorentzAngle) * driftDistance * driftVRatio) + cmSlope * (driftDistance * (1 - driftVRatio)); + + // ALTERNATIVE METHOD + + // double x_anode_hit = driftDistance*driftVRatio/cmSlope; + // double y_anode_hit = driftDistance*driftVRatio; + + // double x_Lorentz_drift_hit = TMath::Tan(oldLorentzAngle)*driftDistance*driftVRatio - TMath::Tan(lorentzAngle)*driftDistance; + // double y_Lorentz_drift_hit = driftDistance*driftVRatio - driftDistance; + + // double Delta_x_Lorentz_drift_hit = x_anode_hit - x_Lorentz_drift_hit; + // double Delta_y_Lorentz_drift_hit = y_anode_hit - y_Lorentz_drift_hit; + // double impact_angle_rec = TMath::ATan2(Delta_y_Lorentz_drift_hit,Delta_x_Lorentz_drift_hit); + + // float calibrationShift = TMath::Tan(impact_angle_rec) * driftDistance; + + // LOG(info) << "ORIGINAL: " << calibratedDy; + // LOG(info) << "ALTERNATIVE: " << rawDy + calibrationShift; + + return calibratedDy; +} + +float TrackletTransformer::calibrateX(double x, double t0Correction) +{ + return x += t0Correction; +} + +std::array<float, 3> TrackletTransformer::transformL2T(int hcid, std::array<double, 3> point) +{ + int detector = hcid / 2; + auto transformationMatrix = mGeo->getMatrixT2L(detector); + + ROOT::Math::Impl::Transform3D<double>::Point localPoint(point[0], point[1], point[2]); + auto gobalPoint = transformationMatrix ^ localPoint; + + return {(float)gobalPoint.x(), (float)gobalPoint.y(), (float)gobalPoint.z()}; +} + +CalibratedTracklet TrackletTransformer::transformTracklet(Tracklet64 tracklet) +{ + uint64_t trackletWord = tracklet.getTrackletWord(); + uint64_t hcid = tracklet.getHCID(); + uint64_t padrow = tracklet.getPadRow(); + uint64_t column = tracklet.getColumn(); + // 0-2048 | units:pad-widths | granularity=1/75 (measured from center pad 10) 1024 is 0/center of pad 10 + uint64_t position = tracklet.getPosition(); + // 0-127 | units:pads/timebin | granularity=1/1000 + uint64_t slope = tracklet.getSlope(); + + // calculate raw local chamber space point + loadPadPlane(hcid); + float x = getXDrift(); + float y = calculateY(hcid, column, position); + float z = calculateZ(padrow); + + float dy = calculateDy(slope, mOldLorentzAngle, mLorentzAngle, mDriftVRatio); + float calibratedX = calibrateX(x, mt0Correction); + + std::array<float, 3> sectorSpacePoint = transformL2T(hcid, std::array<double, 3>{x, y, z}); + + LOG(debug) << "x: " << sectorSpacePoint[0] << " | " + << "y: " << sectorSpacePoint[1] << " | " + << "z: " << sectorSpacePoint[2]; + + CalibratedTracklet calibratedTracklet = CalibratedTracklet(trackletWord, sectorSpacePoint[0], sectorSpacePoint[1], sectorSpacePoint[2], dy); + + return calibratedTracklet; +} diff --git a/Detectors/TRD/workflow/CMakeLists.txt b/Detectors/TRD/workflow/CMakeLists.txt index 63f51b35f743b..512ab65af4640 100644 --- a/Detectors/TRD/workflow/CMakeLists.txt +++ b/Detectors/TRD/workflow/CMakeLists.txt @@ -16,9 +16,11 @@ o2_add_library(TRDWorkflow src/TRDDigitWriterSpec.cxx src/TRDDigitReaderSpec.cxx src/TRDTrackletWriterSpec.cxx + src/TRDCalibratedTrackletWriterSpec.cxx src/TRDTrackletReaderSpec.cxx src/TRDTrapRawWriterSpec.cxx src/TRDTrapSimulatorSpec.cxx + src/TRDTrackletTransformerSpec.cxx src/TRDGlobalTrackingSpec.cxx src/TRDTrackWriterSpec.cxx src/TRDTrackingWorkflow.cxx @@ -42,6 +44,11 @@ o2_add_executable(global-tracking SOURCES src/trd-tracking-workflow.cxx PUBLIC_LINK_LIBRARIES O2::TRDWorkflow) +o2_add_executable(tracklet-transformer + COMPONENT_NAME trd + SOURCES src/TRDTrackletTransformerWorkflow.cxx + PUBLIC_LINK_LIBRARIES O2::TRDWorkflow) + if (OpenMP_CXX_FOUND) target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDCalibratedTrackletWriterSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDCalibratedTrackletWriterSpec.h new file mode 100644 index 0000000000000..bf62beed66acf --- /dev/null +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDCalibratedTrackletWriterSpec.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_TRDCALIBRATEDTRACKLETWRITER_H +#define O2_TRDCALIBRATEDTRACKLETWRITER_H + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +namespace trd +{ + +framework::DataProcessorSpec getTRDCalibratedTrackletWriterSpec(); + +} // end namespace trd +} // end namespace o2 + +#endif diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletTransformerSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletTransformerSpec.h new file mode 100644 index 0000000000000..ffbc41f026a37 --- /dev/null +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDTrackletTransformerSpec.h @@ -0,0 +1,36 @@ +// 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/DataProcessorSpec.h" +#include "Framework/Task.h" + +#include "TRDBase/TrackletTransformer.h" + +namespace o2 +{ +namespace trd +{ + +class TRDTrackletTransformerSpec : public o2::framework::Task +{ + public: + // TRDTrackletTransformerSpec(); + // ~TRDTrackletTransformerSpec() override = default; + void init(o2::framework::InitContext& ic) override; + void run(o2::framework::ProcessingContext& pc) override; + + private: + o2::trd::TrackletTransformer mTransformer; +}; + +o2::framework::DataProcessorSpec getTRDTrackletTransformerSpec(); + +} // end namespace trd +} // end namespace o2 diff --git a/Detectors/TRD/workflow/src/TRDCalibratedTrackletWriterSpec.cxx b/Detectors/TRD/workflow/src/TRDCalibratedTrackletWriterSpec.cxx new file mode 100644 index 0000000000000..84cfa12dcb34f --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDCalibratedTrackletWriterSpec.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. + +#include "TRDWorkflow/TRDCalibratedTrackletWriterSpec.h" +#include "DataFormatsTRD/CalibratedTracklet.h" + +#include "DPLUtils/MakeRootTreeWriterSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace trd +{ + +template <typename T> +using BranchDefinition = framework::MakeRootTreeWriterSpec::BranchDefinition<T>; + +o2::framework::DataProcessorSpec getTRDCalibratedTrackletWriterSpec() +{ + using MakeRootTreeWriterSpec = framework::MakeRootTreeWriterSpec; + + return MakeRootTreeWriterSpec("calibrated-tracklet-writer", + "trdcalibratedtracklets.root", + "ctracklets", + 1, + BranchDefinition<std::vector<CalibratedTracklet>>{InputSpec{"ctracklets", "TRD", "CTRACKLETS"}, "CTracklets"})(); + // BranchDefinition<std::vector<o2::trd::TriggerRecord>>{InputSpec{"tracklettrigs", "TRD", "TRKTRGRD"}, "TrackTrg"})(); +}; + +} // end namespace trd +} // end namespace o2 diff --git a/Detectors/TRD/workflow/src/TRDTrackletTransformerSpec.cxx b/Detectors/TRD/workflow/src/TRDTrackletTransformerSpec.cxx new file mode 100644 index 0000000000000..acb441fcd54bf --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDTrackletTransformerSpec.cxx @@ -0,0 +1,73 @@ +// 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 <gsl/span> + +#include "TRDWorkflow/TRDTrackletTransformerSpec.h" + +#include "DataFormatsTRD/TriggerRecord.h" +#include "DataFormatsTRD/Tracklet64.h" +#include "DataFormatsTRD/CalibratedTracklet.h" + +using namespace o2::framework; +using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; + +namespace o2 +{ +namespace trd +{ + +void TRDTrackletTransformerSpec::init(o2::framework::InitContext& ic) +{ + LOG(info) << "initializing tracklet transformer"; +} + +void TRDTrackletTransformerSpec::run(o2::framework::ProcessingContext& pc) +{ + LOG(info) << "running tracklet transformer"; + + auto tracklets = pc.inputs().get<gsl::span<Tracklet64>>("inTracklets"); + // std::vector<TriggerRecord> triggerRec = pc.inputs().get<std::vector<TriggerRecord>>("triggerRecord"); + + std::vector<CalibratedTracklet> calibratedTracklets; + calibratedTracklets.reserve(tracklets.size()); + + // temporary. For testing + // for (int reci=0; reci < triggerRec.size(); reci++) + // { + // LOG(info) << triggerRec[reci].getFirstEntry() << " | " << triggerRec[reci].getNumberOfObjects(); + // } + + LOG(info) << tracklets.size() << " tracklets found!"; + + for (const auto& tracklet : tracklets) { + CalibratedTracklet calibratedTracklet = mTransformer.transformTracklet(tracklet); + calibratedTracklets.push_back(calibratedTracklet); + } + + pc.outputs().snapshot(Output{"TRD", "CTRACKLETS", 0, Lifetime::Timeframe}, calibratedTracklets); +} + +o2::framework::DataProcessorSpec getTRDTrackletTransformerSpec() +{ + LOG(info) << "getting TRDTrackletTransformerSpec"; + return DataProcessorSpec{ + "TRDTRACKLETTRANSFORMER", + Inputs{ + InputSpec{"inTracklets", "TRD", "TRACKLETS", 0}, + // InputSpec{"triggerRecord", "TRD", "TRKTRGRD", 0} + }, + Outputs{OutputSpec{"TRD", "CTRACKLETS", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<TRDTrackletTransformerSpec>()}, + Options{}}; +} + +} //end namespace trd +} //end namespace o2 diff --git a/Detectors/TRD/workflow/src/TRDTrackletTransformerWorkflow.cxx b/Detectors/TRD/workflow/src/TRDTrackletTransformerWorkflow.cxx new file mode 100644 index 0000000000000..fca31bcd222ee --- /dev/null +++ b/Detectors/TRD/workflow/src/TRDTrackletTransformerWorkflow.cxx @@ -0,0 +1,48 @@ +// 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 "TRDWorkflow/TRDTrackletTransformerSpec.h" +#include "TRDWorkflow/TRDCalibratedTrackletWriterSpec.h" +#include "TRDWorkflow/TRDTrackletReaderSpec.h" + +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" + +using namespace o2::framework; + +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{ + "root-in", VariantType::Int, 1, {"enable (1) or disable (0) input from ROOT file"}}); + workflowOptions.push_back(ConfigParamSpec{ + "root-out", VariantType::Int, 1, {"enable (1) or disable (0) output to ROOT file"}}); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + int rootIn = configcontext.options().get<int>("root-in"); + int rootOut = configcontext.options().get<int>("root-out"); + + WorkflowSpec spec; + + if (rootIn) { + spec.emplace_back(o2::trd::getTRDTrackletReaderSpec(0)); + } + + spec.emplace_back(o2::trd::getTRDTrackletTransformerSpec()); + + if (rootOut) { + spec.emplace_back(o2::trd::getTRDCalibratedTrackletWriterSpec()); + } + + return spec; +} From 5a763d13fc55e4427767d60e3da121749b08ea1e Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Thu, 10 Dec 2020 11:24:06 +0100 Subject: [PATCH 1591/1751] Decouple VMC libs from o2-sim This is going back to loading VMC engines as real plugins **while** retaining the advantage of compiling the configuration templates and avoiding ROOT macros execution during startup. This brings the advantage that not all engine libs are loaded at startup simultaneously. --- Detectors/gconfig/CMakeLists.txt | 26 ++++++------ Detectors/gconfig/src/G3Config.cxx | 16 ------- Detectors/gconfig/src/G4Config.cxx | 10 ----- .../gconfig/{SetCuts.h => src/SetCuts.cxx} | 25 ++++++----- Detectors/gconfig/src/SetCuts.h | 19 +++++++++ Detectors/gconfig/src/SimSetup.cxx | 42 +++++++++++++++---- 6 files changed, 77 insertions(+), 61 deletions(-) rename Detectors/gconfig/{SetCuts.h => src/SetCuts.cxx} (79%) create mode 100644 Detectors/gconfig/src/SetCuts.h diff --git a/Detectors/gconfig/CMakeLists.txt b/Detectors/gconfig/CMakeLists.txt index 77281e03b978e..bd7a51dfcfae8 100644 --- a/Detectors/gconfig/CMakeLists.txt +++ b/Detectors/gconfig/CMakeLists.txt @@ -8,20 +8,20 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. +o2_add_library(G3Setup + SOURCES src/G3Config.cxx + PUBLIC_LINK_LIBRARIES MC::Geant3 FairRoot::Base O2::SimulationDataFormat O2::Generators +) + +o2_add_library(G4Setup + SOURCES src/G4Config.cxx + PUBLIC_LINK_LIBRARIES MC::Geant4VMC MC::Geant4 FairRoot::Base O2::SimulationDataFormat O2::Generators ROOT::EGPythia6 +) + o2_add_library(SimSetup - SOURCES src/G3Config.cxx src/G4Config.cxx - src/GlobalProcessCutSimParam.cxx src/SimSetup.cxx - PUBLIC_LINK_LIBRARIES MC::Geant3 - MC::Geant4VMC - MC::Geant4 - O2::SimulationDataFormat - O2::DetectorsPassive - O2::Generators - MC::Pythia6 # this is needed by Geant3 and - # EGPythia6 - ROOT::EGPythia6 # this is needed by Geant4 - # (TPythia6Decayer) - ) + SOURCES src/GlobalProcessCutSimParam.cxx src/SimSetup.cxx src/SetCuts.cxx + PUBLIC_LINK_LIBRARIES O2::CommonUtils O2::DetectorsBase + ) o2_target_root_dictionary(SimSetup HEADERS include/SimSetup/SimSetup.h diff --git a/Detectors/gconfig/src/G3Config.cxx b/Detectors/gconfig/src/G3Config.cxx index 96192c0ca1705..72ee0ef35ab04 100644 --- a/Detectors/gconfig/src/G3Config.cxx +++ b/Detectors/gconfig/src/G3Config.cxx @@ -13,39 +13,23 @@ #include "TGeant3TGeo.h" #include "SimulationDataFormat/Stack.h" #include "SimulationDataFormat/StackParam.h" -#include <iostream> #include "FairLogger.h" #include "FairModule.h" -#include <DetectorsPassive/Cave.h> -#include "DetectorsBase/MaterialManager.h" -#include "SimSetup/GlobalProcessCutSimParam.h" #include "Generators/DecayerPythia8.h" -//using declarations here since SetCuts.C and g3Config.C are included within namespace -// these are needed for SetCuts.C inclusion -using o2::GlobalProcessCutSimParam; -using o2::base::ECut; -using o2::base::EProc; -using o2::base::MaterialManager; -// these are used in g3Config.C -using std::cout; -using std::endl; // these are used in commonConfig.C using o2::eventgen::DecayerPythia8; -#include <SimSetup/SimSetup.h> namespace o2 { namespace g3config { #include "../g3Config.C" -#include "../SetCuts.h" void G3Config() { LOG(INFO) << "Setting up G3 sim from library code"; Config(); - SetCuts(); } } // namespace g3config } // namespace o2 diff --git a/Detectors/gconfig/src/G4Config.cxx b/Detectors/gconfig/src/G4Config.cxx index e6d043d10ef4b..3aac0259f561c 100644 --- a/Detectors/gconfig/src/G4Config.cxx +++ b/Detectors/gconfig/src/G4Config.cxx @@ -17,18 +17,10 @@ #include "TG4RunConfiguration.h" #include "TPythia6Decayer.h" #include "FairModule.h" -#include <DetectorsPassive/Cave.h> -#include "DetectorsBase/MaterialManager.h" -#include "SimSetup/GlobalProcessCutSimParam.h" #include "SimConfig/G4Params.h" #include "Generators/DecayerPythia8.h" //using declarations here since SetCuts.C and g4Config.C are included within namespace -// these are needed for SetCuts.C inclusion -using o2::GlobalProcessCutSimParam; -using o2::base::ECut; -using o2::base::EProc; -using o2::base::MaterialManager; // these are used in g4Config.C using std::cout; using std::endl; @@ -40,13 +32,11 @@ namespace o2 namespace g4config { #include "../g4Config.C" -#include "../SetCuts.h" void G4Config() { LOG(INFO) << "Setting up G4 sim from library code"; Config(); - SetCuts(); } } // namespace g4config } // namespace o2 diff --git a/Detectors/gconfig/SetCuts.h b/Detectors/gconfig/src/SetCuts.cxx similarity index 79% rename from Detectors/gconfig/SetCuts.h rename to Detectors/gconfig/src/SetCuts.cxx index 089f7c8636d2c..edea5655b568f 100644 --- a/Detectors/gconfig/SetCuts.h +++ b/Detectors/gconfig/src/SetCuts.cxx @@ -8,22 +8,19 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/******************************************************************************** - * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * - * * - * This software is distributed under the terms of the * - * GNU Lesser General Public Licence version 3 (LGPL) version 3, * - * copied verbatim in the file "LICENSE" * - ********************************************************************************/ +#include "SetCuts.h" +#include "SimSetup/GlobalProcessCutSimParam.h" +#include "DetectorsBase/MaterialManager.h" +#include "FairLogger.h" -/** Configuration macro for setting common cuts and processes for G3, G4 and Fluka (M. Al-Turany 27.03.2008) - specific cuts and processes to g3 or g4 should be set in the g3Config.C, g4Config.C or flConfig.C +using namespace o2::base; -*/ +namespace o2 +{ void SetCuts() { - cout << "SetCuts Macro: Setting Processes.." << endl; + LOG(INFO) << "Setup global cuts and processes"; // ------>>>> IMPORTANT!!!! // For a correct comparison between GEANE and MC (pull distributions) @@ -38,8 +35,8 @@ void SetCuts() // \note All following settings could also be set in Cave since it is always loaded. // Use MaterialManager to set processes and cuts - auto& mgr = MaterialManager::Instance(); - auto& params = GlobalProcessCutSimParam::Instance(); + auto& mgr = o2::base::MaterialManager::Instance(); + auto& params = o2::GlobalProcessCutSimParam::Instance(); LOG(INFO) << "Set default settings for processes and cuts."; mgr.DefaultProcesses({{EProc::kPAIR, params.PAIR}, /** pair production */ @@ -73,3 +70,5 @@ void SetCuts() LOG(INFO) << "Special process settings are " << settingProc << "."; LOG(INFO) << "Special cut settings are " << settingCut << "."; } + +} // namespace o2 diff --git a/Detectors/gconfig/src/SetCuts.h b/Detectors/gconfig/src/SetCuts.h new file mode 100644 index 0000000000000..c039acde8a60c --- /dev/null +++ b/Detectors/gconfig/src/SetCuts.h @@ -0,0 +1,19 @@ +// 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_SIMSETUP_SETCUTS_H +#define O2_SIMSETUP_SETCUTS_H + +namespace o2 +{ +void SetCuts(); +} + +#endif diff --git a/Detectors/gconfig/src/SimSetup.cxx b/Detectors/gconfig/src/SimSetup.cxx index 8d8af5886a560..ef1cfb644a4c9 100644 --- a/Detectors/gconfig/src/SimSetup.cxx +++ b/Detectors/gconfig/src/SimSetup.cxx @@ -11,27 +11,51 @@ #include <cstring> #include "SimSetup/SimSetup.h" #include "FairLogger.h" +#include "SetCuts.h" +#include <dlfcn.h> +#ifdef NDEBUG +#undef NDEBUG +#endif +#include <cassert> +#include <sstream> namespace o2 { -// forward declarations of functions -namespace g3config -{ -void G3Config(); -} -namespace g4config + +typedef void (*setup_fnc)(); + +void setupFromPlugin(const char* libname, const char* setupfuncname) { -void G4Config(); + LOG(INFO) << "Loading simulation plugin " << libname; + auto libHandle = dlopen(libname, RTLD_NOW); + // try to make the library loading a bit more portable: + if (!libHandle) { + // try appending *.so + std::stringstream stream; + stream << libname << ".so"; + libHandle = dlopen(stream.str().c_str(), RTLD_NOW); + } + if (!libHandle) { + // try appending *.dylib + std::stringstream stream; + stream << libname << ".dylib"; + libHandle = dlopen(stream.str().c_str(), RTLD_NOW); + } + assert(libHandle); + auto setup = (setup_fnc)dlsym(libHandle, setupfuncname); + assert(setup); + setup(); } void SimSetup::setup(const char* engine) { if (strcmp(engine, "TGeant3") == 0) { - g3config::G3Config(); + setupFromPlugin("libO2G3Setup", "_ZN2o28g3config8G3ConfigEv"); } else if (strcmp(engine, "TGeant4") == 0) { - g4config::G4Config(); + setupFromPlugin("libO2G4Setup", "_ZN2o28g4config8G4ConfigEv"); } else { LOG(FATAL) << "Unsupported engine " << engine; } + o2::SetCuts(); } } // namespace o2 From dff136ede78ffbe8ebccb752fbaca16984dff215 Mon Sep 17 00:00:00 2001 From: Andreas Morsch <andreas.morsch@cern.ch> Date: Sat, 28 Nov 2020 10:44:28 +0100 Subject: [PATCH 1592/1751] Support for FLUKA VMC backend in O2 This commit provides support for FLUKA in O2. FLUKA compilation is optional for the moment. This backend can be selected via: ``` o2-sim -e TFluka ... ``` --- DataFormats/simulation/src/Stack.cxx | 4 +- Detectors/gconfig/CMakeLists.txt | 12 ++++ Detectors/gconfig/data/coreFlukaVmc.inp | 29 ++++++++ Detectors/gconfig/src/FlukaConfig.cxx | 70 +++++++++++++++++++ Detectors/gconfig/src/SimSetup.cxx | 2 + dependencies/FindFlukaVMC.cmake | 29 ++++++++ .../O2FindDependenciesFromAliBuild.cmake | 1 + dependencies/O2SimulationDependencies.cmake | 3 + run/O2SimDevice.h | 10 +-- 9 files changed, 150 insertions(+), 10 deletions(-) create mode 100755 Detectors/gconfig/data/coreFlukaVmc.inp create mode 100644 Detectors/gconfig/src/FlukaConfig.cxx create mode 100644 dependencies/FindFlukaVMC.cmake diff --git a/DataFormats/simulation/src/Stack.cxx b/DataFormats/simulation/src/Stack.cxx index 712de76e400f7..41f5f8fd1acd5 100644 --- a/DataFormats/simulation/src/Stack.cxx +++ b/DataFormats/simulation/src/Stack.cxx @@ -77,8 +77,8 @@ Stack::Stack(Int_t size) mIsG4Like(false) { auto vmc = TVirtualMC::GetMC(); - if (vmc && strcmp(vmc->GetName(), "TGeant4") == 0) { - mIsG4Like = true; + if (vmc) { + mIsG4Like = !(vmc->SecondariesAreOrdered()); } auto& param = o2::sim::StackParam::Instance(); diff --git a/Detectors/gconfig/CMakeLists.txt b/Detectors/gconfig/CMakeLists.txt index bd7a51dfcfae8..2ac6f9809633e 100644 --- a/Detectors/gconfig/CMakeLists.txt +++ b/Detectors/gconfig/CMakeLists.txt @@ -18,6 +18,16 @@ o2_add_library(G4Setup PUBLIC_LINK_LIBRARIES MC::Geant4VMC MC::Geant4 FairRoot::Base O2::SimulationDataFormat O2::Generators ROOT::EGPythia6 ) +if (FlukaVMC_FOUND) + message(STATUS "BUILDING WITH FLUKA") + o2_add_library(FLUKASetup + SOURCES src/FlukaConfig.cxx + PUBLIC_LINK_LIBRARIES MC::FlukaVMC FairRoot::Base O2::SimulationDataFormat O2::Generators ROOT::EGPythia6 + ) +else() + message(STATUS "BUILDING WITHOUT FLUKA") +endif (FlukaVMC_FOUND) + o2_add_library(SimSetup SOURCES src/GlobalProcessCutSimParam.cxx src/SimSetup.cxx src/SetCuts.cxx PUBLIC_LINK_LIBRARIES O2::CommonUtils O2::DetectorsBase @@ -49,3 +59,5 @@ o2_add_test_root_macro(g3Config.C o2_add_test_root_macro(g4Config.C PUBLIC_LINK_LIBRARIES O2::SimSetup LABELS simsetup) + +o2_data_file(COPY data DESTINATION Detectors/gconfig/) diff --git a/Detectors/gconfig/data/coreFlukaVmc.inp b/Detectors/gconfig/data/coreFlukaVmc.inp new file mode 100755 index 0000000000000..cb3d48c9ad09f --- /dev/null +++ b/Detectors/gconfig/data/coreFlukaVmc.inp @@ -0,0 +1,29 @@ +GLOBAL 50000. 4.0 +DEFAULTS NEW-DEFA +OPEN 1. OLD +random.dat +GEOBEGIN COMBINAT +GEOEND +* +*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+ +* +EVENTYPE 1.0 +BEAM 7000.0 MUON- +MGNFIELD 10.0 0.001 +SOURCE +*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+ +USERDUMP 200. 37.0 -2.0 1.0 TRAKFILE +START 42000.99999999.0 2.0 +STOP + + + + + + + + + + + + diff --git a/Detectors/gconfig/src/FlukaConfig.cxx b/Detectors/gconfig/src/FlukaConfig.cxx new file mode 100644 index 0000000000000..bdc3fa137f34c --- /dev/null +++ b/Detectors/gconfig/src/FlukaConfig.cxx @@ -0,0 +1,70 @@ +// 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 "FairRunSim.h" +#include "TFluka.h" +#include "SimulationDataFormat/Stack.h" +#include "SimulationDataFormat/StackParam.h" +#include <iostream> +#include "FairLogger.h" +#include "FairModule.h" +#include "Generators/DecayerPythia8.h" +#include "../commonConfig.C" + +// these are used in commonConfig.C +using o2::eventgen::DecayerPythia8; + +namespace o2 +{ +namespace flukaconfig +{ + +void linkFlukaFiles() +{ + // Link here some special Fluka files needed + gSystem->Exec("ln -s $FLUKADATA/neuxsc.bin ."); + gSystem->Exec("ln -s $FLUKADATA/elasct.bin ."); + gSystem->Exec("ln -s $FLUKADATA/gxsect.bin ."); + gSystem->Exec("ln -s $FLUKADATA/nuclear.bin ."); + gSystem->Exec("ln -s $FLUKADATA/sigmapi.bin ."); + gSystem->Exec("ln -s $FLUKADATA/brems_fin.bin ."); + gSystem->Exec("ln -s $FLUKADATA/cohff.bin ."); + gSystem->Exec("ln -s $FLUKADATA/fluodt.dat ."); + gSystem->Exec("ln -s $FLUKADATA/random.dat ."); + // Copy the random seed + gSystem->Exec("cp $FLUKADATA/random.dat old.seed"); + // Give some meaningfull name to the output + gSystem->Exec("ln -s fluka.out fort.11"); + gSystem->Exec("ln -s fluka.err fort.15"); + gSystem->Exec("ln -fs $ALICE_ROOT/TFluka/macro/FlukaConfig.C Config.C"); + gSystem->Exec("ln -fs $O2_ROOT/share/Detectors/gconfig/data/coreFlukaVmc.inp ."); +} + +void Config() +{ + linkFlukaFiles(); + FairRunSim* run = FairRunSim::Instance(); + TString* gModel = run->GetGeoModel(); + TFluka* fluka = new TFluka("C++ Interface to Fluka", 0); + stackSetup(fluka, run); + + // setup decayer + decayerSetup(fluka); + + // ******* FLUKA specific configuration for simulated Runs ******* +} + +void FlukaConfig() +{ + LOG(INFO) << "Setting up FLUKA sim from library code"; + Config(); +} +} // namespace flukaconfig +} // namespace o2 diff --git a/Detectors/gconfig/src/SimSetup.cxx b/Detectors/gconfig/src/SimSetup.cxx index ef1cfb644a4c9..8626abc22a007 100644 --- a/Detectors/gconfig/src/SimSetup.cxx +++ b/Detectors/gconfig/src/SimSetup.cxx @@ -53,6 +53,8 @@ void SimSetup::setup(const char* engine) setupFromPlugin("libO2G3Setup", "_ZN2o28g3config8G3ConfigEv"); } else if (strcmp(engine, "TGeant4") == 0) { setupFromPlugin("libO2G4Setup", "_ZN2o28g4config8G4ConfigEv"); + } else if (strcmp(engine, "TFluka") == 0) { + setupFromPlugin("libO2FLUKASetup", "_ZN2o211flukaconfig11FlukaConfigEv"); } else { LOG(FATAL) << "Unsupported engine " << engine; } diff --git a/dependencies/FindFlukaVMC.cmake b/dependencies/FindFlukaVMC.cmake new file mode 100644 index 0000000000000..eb7f138f3085d --- /dev/null +++ b/dependencies/FindFlukaVMC.cmake @@ -0,0 +1,29 @@ +# 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. + +# use the GEANT4_VMCConfig.cmake provided by the Geant4VMC installation but +# amend the target geant4vmc with the include directories + +find_package(FlukaVMC NO_MODULE) +if(NOT FlukaVMC_FOUND) +return() +endif() + +set_target_properties(flukavmc + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${FlukaVMC_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES + $<TARGET_FILE_DIR:flukavmc>) + +# Promote the imported target to global visibility +# (so we can alias it) +set_target_properties(flukavmc PROPERTIES IMPORTED_GLOBAL TRUE) + +add_library(MC::FlukaVMC ALIAS flukavmc) diff --git a/dependencies/O2FindDependenciesFromAliBuild.cmake b/dependencies/O2FindDependenciesFromAliBuild.cmake index 6cb2795804f6c..2b551a01dc189 100644 --- a/dependencies/O2FindDependenciesFromAliBuild.cmake +++ b/dependencies/O2FindDependenciesFromAliBuild.cmake @@ -154,6 +154,7 @@ function(o2_find_dependencies_from_alibuild) protected_set_root(Geant3 GEANT3) protected_set_root(Geant4 GEANT4) protected_set_root(Geant4VMC GEANT4_VMC) + protected_set_root(FlukaVMC FLUKA_VMC) protected_set_root(VGM vgm) protected_set_root(HepMC HepMC3) diff --git a/dependencies/O2SimulationDependencies.cmake b/dependencies/O2SimulationDependencies.cmake index 6d69d467a024d..e62073d18bc44 100644 --- a/dependencies/O2SimulationDependencies.cmake +++ b/dependencies/O2SimulationDependencies.cmake @@ -63,6 +63,9 @@ set_package_properties(Geant4 find_package(Geant4VMC MODULE) set_package_properties(Geant4VMC PROPERTIES TYPE ${mcPackageRequirement}) +find_package(FlukaVMC MODULE) +set_package_properties(FlukaVMC PROPERTIES TYPE OPTIONAL) + find_package(VGM MODULE) set_package_properties(VGM PROPERTIES TYPE ${mcPackageRequirement}) diff --git a/run/O2SimDevice.h b/run/O2SimDevice.h index 90f8dad60eea3..ddbce28ea8adc 100644 --- a/run/O2SimDevice.h +++ b/run/O2SimDevice.h @@ -188,14 +188,8 @@ class O2SimDevice final : public FairMQDevice << "part " << info.part << "/" << info.nparts; gRandom->SetSeed(chunk->mSubEventInfo.seed); - auto& conf = o2::conf::SimConfig::Instance(); - if (strcmp(conf.getMCEngine().c_str(), "TGeant4") == 0) { - mVMC->ProcessEvent(); - } else { - // for Geant3 at least calling ProcessEvent is not enough - // as some hooks are not called - mVMC->ProcessRun(1); - } + // Process one event + mVMC->ProcessRun(1); FairSystemInfo sysinfo; LOG(INFO) << "TIME-STAMP " << mTimer.RealTime() << "\t"; From 7c5cb174ee1bd9aa1a57ea78b4955cae0cee6332 Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Fri, 11 Dec 2020 08:33:23 +0100 Subject: [PATCH 1593/1751] [ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK (#5045) --- Common/SimConfig/src/SimConfig.cxx | 2 +- .../DetectorsCommonDataFormats/DetID.h | 10 +- .../DetectorsCommonDataFormats/SimTraits.h | 4 +- DataFormats/Detectors/Common/src/DetID.cxx | 2 +- .../Headers/include/Headers/DataHeader.h | 2 +- .../{PostLS4 => ALICE3}/CMakeLists.txt | 2 +- .../IT4 => ALICE3/TRK}/CMakeLists.txt | 0 .../{PostLS4/IT4 => ALICE3/TRK}/README.md | 12 +- .../IT4 => ALICE3/TRK}/base/CMakeLists.txt | 8 +- .../TRK/base/include/TRKBase}/GeometryTGeo.h | 12 +- .../include/TRKBase}/MisalignmentParameter.h | 8 +- .../TRK}/base/src/GeometryTGeo.cxx | 20 +-- .../TRK}/base/src/MisalignmentParameter.cxx | 6 +- .../TRK/base/src/TRKBaseLinkDef.h} | 4 +- .../IT4 => ALICE3/TRK}/macros/CMakeLists.txt | 0 .../TRK}/macros/test/CMakeLists.txt | 0 .../TRK}/simulation/CMakeLists.txt | 18 +- .../TRK}/simulation/data/simcuts.dat | 0 .../include/TRKSimulation}/Detector.h | 32 ++-- .../include/TRKSimulation}/V11Geometry.h | 8 +- .../include/TRKSimulation}/V1Layer.h | 18 +- .../include/TRKSimulation}/V3Layer.h | 32 ++-- .../include/TRKSimulation}/V3Services.h | 16 +- .../TRK}/simulation/src/Detector.cxx | 54 +++--- .../simulation/src/TRKSimulationLinkDef.h} | 12 +- .../TRK}/simulation/src/V11Geometry.cxx | 84 ++++----- .../TRK}/simulation/src/V1Layer.cxx | 156 ++++++++--------- .../TRK}/simulation/src/V3Layer.cxx | 164 +++++++++--------- .../TRK}/simulation/src/V3Services.cxx | 50 +++--- Detectors/Upgrades/CMakeLists.txt | 2 +- Detectors/Upgrades/README.md | 8 +- macro/CMakeLists.txt | 2 +- macro/build_geometry.C | 12 +- macro/run_trac_alice3.C | 4 +- run/CMakeLists.txt | 2 +- run/O2HitMerger.h | 6 +- 36 files changed, 387 insertions(+), 385 deletions(-) rename Detectors/Upgrades/{PostLS4 => ALICE3}/CMakeLists.txt (95%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/CMakeLists.txt (100%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/README.md (65%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/base/CMakeLists.txt (76%) rename Detectors/Upgrades/{PostLS4/IT4/base/include/ITS4Base => ALICE3/TRK/base/include/TRKBase}/GeometryTGeo.h (98%) rename Detectors/Upgrades/{PostLS4/IT4/base/include/ITS4Base => ALICE3/TRK/base/include/TRKBase}/MisalignmentParameter.h (94%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/base/src/GeometryTGeo.cxx (97%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/base/src/MisalignmentParameter.cxx (94%) rename Detectors/Upgrades/{PostLS4/IT4/base/src/ITS4BaseLinkDef.h => ALICE3/TRK/base/src/TRKBaseLinkDef.h} (84%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/macros/CMakeLists.txt (100%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/macros/test/CMakeLists.txt (100%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/simulation/CMakeLists.txt (56%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/simulation/data/simcuts.dat (100%) rename Detectors/Upgrades/{PostLS4/IT4/simulation/include/ITS4Simulation => ALICE3/TRK/simulation/include/TRKSimulation}/Detector.h (94%) rename Detectors/Upgrades/{PostLS4/IT4/simulation/include/ITS4Simulation => ALICE3/TRK/simulation/include/TRKSimulation}/V11Geometry.h (99%) rename Detectors/Upgrades/{PostLS4/IT4/simulation/include/ITS4Simulation => ALICE3/TRK/simulation/include/TRKSimulation}/V1Layer.h (97%) rename Detectors/Upgrades/{PostLS4/IT4/simulation/include/ITS4Simulation => ALICE3/TRK/simulation/include/TRKSimulation}/V3Layer.h (97%) rename Detectors/Upgrades/{PostLS4/IT4/simulation/include/ITS4Simulation => ALICE3/TRK/simulation/include/TRKSimulation}/V3Services.h (95%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/simulation/src/Detector.cxx (97%) rename Detectors/Upgrades/{PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h => ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h} (66%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/simulation/src/V11Geometry.cxx (94%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/simulation/src/V1Layer.cxx (95%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/simulation/src/V3Layer.cxx (96%) rename Detectors/Upgrades/{PostLS4/IT4 => ALICE3/TRK}/simulation/src/V3Services.cxx (98%) diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index 6da06aff849a1..a6f4192949ec1 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -60,7 +60,7 @@ bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& active.clear(); for (int d = DetID::First; d <= DetID::Last; ++d) { #ifdef ENABLE_UPGRADES - if (d != DetID::IT3 && d != DetID::IT4) { + if (d != DetID::IT3 && d != DetID::TRK) { active.emplace_back(DetID::getName(d)); } #else diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h index 39c915b270ec4..fd963354f030d 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h @@ -70,8 +70,8 @@ class DetID static constexpr ID ACO = 15; #ifdef ENABLE_UPGRADES static constexpr ID IT3 = 16; - static constexpr ID IT4 = 17; - static constexpr ID Last = IT4; + static constexpr ID TRK = 17; + static constexpr ID Last = TRK; #else static constexpr ID Last = ACO; ///< if extra detectors added, update this !!! #endif @@ -133,7 +133,7 @@ class DetID static constexpr const char* sDetNames[nDetectors + 1] = ///< defined detector names #ifdef ENABLE_UPGRADES - {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ACO", "IT3", "IT4", nullptr}; + {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ACO", "IT3", "TRK", nullptr}; #else {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ACO", nullptr}; #endif @@ -145,7 +145,7 @@ class DetID math_utils::bit2Mask(ACO) #ifdef ENABLE_UPGRADES , - math_utils::bit2Mask(IT3), math_utils::bit2Mask(IT4) + math_utils::bit2Mask(IT3), math_utils::bit2Mask(TRK) #endif }; @@ -156,7 +156,7 @@ class DetID o2h::gDataOriginMID, o2h::gDataOriginZDC, o2h::gDataOriginFT0, o2h::gDataOriginFV0, o2h::gDataOriginFDD, o2h::gDataOriginACO #ifdef ENABLE_UPGRADES , - o2h::gDataOriginIT3, o2h::gDataOriginIT4 + o2h::gDataOriginIT3, o2h::gDataOriginTRK #endif }; diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h index 3c408b12bef84..018e6c4a54054 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h @@ -90,7 +90,7 @@ class SimTraits #ifdef ENABLE_UPGRADES , /*IT3*/ VS{ "IT3Hit" }, - /*IT4*/ VS{ "IT4Hit" } + /*TRK*/ VS{ "TRKHit" } #endif }; // clang-format on @@ -229,7 +229,7 @@ struct DetIDToHitTypes<o2::detectors::DetID::IT3> { }; template <> -struct DetIDToHitTypes<o2::detectors::DetID::IT4> { +struct DetIDToHitTypes<o2::detectors::DetID::TRK> { using HitType = o2::itsmft::Hit; }; #endif diff --git a/DataFormats/Detectors/Common/src/DetID.cxx b/DataFormats/Detectors/Common/src/DetID.cxx index ac6cb80e7ba12..1706990322a36 100644 --- a/DataFormats/Detectors/Common/src/DetID.cxx +++ b/DataFormats/Detectors/Common/src/DetID.cxx @@ -30,7 +30,7 @@ constexpr DetID::ID DetID::ITS, DetID::TPC, DetID::TRD, DetID::TOF, DetID::PHS, #ifdef ENABLE_UPGRADES constexpr DetID::ID DetID::IT3; -constexpr DetID::ID DetID::IT4; +constexpr DetID::ID DetID::TRK; #endif constexpr int DetID::nDetectors; diff --git a/DataFormats/Headers/include/Headers/DataHeader.h b/DataFormats/Headers/include/Headers/DataHeader.h index 1780e0ebf1607..ea674174997b5 100644 --- a/DataFormats/Headers/include/Headers/DataHeader.h +++ b/DataFormats/Headers/include/Headers/DataHeader.h @@ -637,7 +637,7 @@ constexpr o2::header::DataOrigin gDataOriginTRD{"TRD"}; constexpr o2::header::DataOrigin gDataOriginZDC{"ZDC"}; #ifdef ENABLE_UPGRADES constexpr o2::header::DataOrigin gDataOriginIT3{"IT3"}; -constexpr o2::header::DataOrigin gDataOriginIT4{"IT4"}; +constexpr o2::header::DataOrigin gDataOriginTRK{"TRK"}; #endif //possible data types diff --git a/Detectors/Upgrades/PostLS4/CMakeLists.txt b/Detectors/Upgrades/ALICE3/CMakeLists.txt similarity index 95% rename from Detectors/Upgrades/PostLS4/CMakeLists.txt rename to Detectors/Upgrades/ALICE3/CMakeLists.txt index 031729b79c5ed..c8f381fd9f8ab 100644 --- a/Detectors/Upgrades/PostLS4/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/CMakeLists.txt @@ -8,4 +8,4 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -add_subdirectory(IT4) \ No newline at end of file +add_subdirectory(TRK) \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRK/CMakeLists.txt similarity index 100% rename from Detectors/Upgrades/PostLS4/IT4/CMakeLists.txt rename to Detectors/Upgrades/ALICE3/TRK/CMakeLists.txt diff --git a/Detectors/Upgrades/PostLS4/IT4/README.md b/Detectors/Upgrades/ALICE3/TRK/README.md similarity index 65% rename from Detectors/Upgrades/PostLS4/IT4/README.md rename to Detectors/Upgrades/ALICE3/TRK/README.md index 02b76227f1a71..f35f9d4fe20dc 100644 --- a/Detectors/Upgrades/PostLS4/IT4/README.md +++ b/Detectors/Upgrades/ALICE3/TRK/README.md @@ -1,20 +1,20 @@ <!-- doxy -\page refDetectorsUpgradesPostLS4IT4 UpgradesIT4 +\page refDetectorsUpgradesPostLS4TRK UpgradesTRK /doxy --> -# IT4 -At the moment the IT4 name is a placeholder for barrel detector. +# TRK +At the moment the TRK name is a placeholder for silicon barrel detector. # Run the full simulation -Provided O2 has been compiled with upgrades enabled, it is possible to simulate IT4 geometry within the `o2-sim` executable. +Provided O2 has been compiled with upgrades enabled, it is possible to simulate TRK geometry using the `o2-sim` executable. ## Simulation -IT4 module is enabled via the `-m IT4` parameter. +TRK module is enabled via the `-m TRK` parameter. In case of `PIPE` to be enabled, the size of the beam pipe is automatically scaled to what is foreseen for the upgrades. Typical command to generate MC data: ```bash -o2-sim -m PIPE IT4 [...] +o2-sim -m PIPE TRK [...] ``` ## Reconstruction diff --git a/Detectors/Upgrades/PostLS4/IT4/base/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt similarity index 76% rename from Detectors/Upgrades/PostLS4/IT4/base/CMakeLists.txt rename to Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt index bcf29a286d57c..fdd2f81a51017 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt @@ -8,11 +8,11 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_library(ITS4Base +o2_add_library(TRKBase SOURCES src/MisalignmentParameter.cxx src/GeometryTGeo.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::ITSMFTBase) -o2_target_root_dictionary(ITS4Base - HEADERS include/ITS4Base/GeometryTGeo.h - include/ITS4Base/MisalignmentParameter.h) +o2_target_root_dictionary(TRKBase + HEADERS include/TRKBase/GeometryTGeo.h + include/TRKBase/MisalignmentParameter.h) diff --git a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h similarity index 98% rename from Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h rename to Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h index 104b227f419ea..9c289f5243a54 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h @@ -13,8 +13,8 @@ /// \author cvetan.cheshkov@cern.ch - 15/02/2007 /// \author ruben.shahoyan@cern.ch - adapted to ITSupg 18/07/2012 -#ifndef ALICEO2_ITS4_GEOMETRYTGEO_H_ -#define ALICEO2_ITS4_GEOMETRYTGEO_H_ +#ifndef ALICEO2_TRK_GEOMETRYTGEO_H_ +#define ALICEO2_TRK_GEOMETRYTGEO_H_ #include <TGeoMatrix.h> // for TGeoHMatrix #include <TObject.h> // for TObject @@ -31,7 +31,7 @@ class TGeoPNEntry; namespace o2 { -namespace its4 +namespace trk { /// GeometryTGeo is a simple interface class to TGeoManager. It is used in the simulation /// and reconstruction in order to query the TGeo ITS geometry. @@ -247,7 +247,7 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo static void setITSChipPattern(const char* nm) { sChipName = nm; } static void setITSSensorPattern(const char* nm) { sSensorName = nm; } /// sym name of the layer - static const char* composeSymNameITS4() { return o2::detectors::DetID(o2::detectors::DetID::IT3).getName(); } + static const char* composeSymNameTRK() { return o2::detectors::DetID(o2::detectors::DetID::IT3).getName(); } /// sym name of the layer static const char* composeSymNameLayer(int lr); @@ -345,11 +345,11 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo static std::string sWrapperVolumeName; ///< Wrapper volume name private: - static std::unique_ptr<o2::its4::GeometryTGeo> sInstance; ///< singletone instance + static std::unique_ptr<o2::trk::GeometryTGeo> sInstance; ///< singletone instance ClassDefOverride(GeometryTGeo, 1); // ITS geometry based on TGeo }; -} // namespace its4 +} // namespace trk } // namespace o2 #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/MisalignmentParameter.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/MisalignmentParameter.h similarity index 94% rename from Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/MisalignmentParameter.h rename to Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/MisalignmentParameter.h index 3c4ea1a572c24..9c6c5c1f5bfab 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/include/ITS4Base/MisalignmentParameter.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/MisalignmentParameter.h @@ -11,8 +11,8 @@ /// \file MisalignmentParameter.h /// \brief Definition of the MisalignmentParameter class -#ifndef ALICEO2_ITS4_MISALIGNMENTPARAMETER_H_ -#define ALICEO2_ITS4_MISALIGNMENTPARAMETER_H_ +#ifndef ALICEO2_TRK_MISALIGNMENTPARAMETER_H_ +#define ALICEO2_TRK_MISALIGNMENTPARAMETER_H_ #include "FairParGenericSet.h" // for FairParGenericSet @@ -24,7 +24,7 @@ class FairParamList; namespace o2 { -namespace its4 +namespace trk { class MisalignmentParameter : public FairParGenericSet { @@ -64,7 +64,7 @@ class MisalignmentParameter : public FairParGenericSet ClassDefOverride(MisalignmentParameter, 1); }; -} // namespace its4 +} // namespace trk } // namespace o2 #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx similarity index 97% rename from Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx rename to Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx index 1a12df0555369..e4c7c5447df2d 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx @@ -15,7 +15,7 @@ // ATTENTION: In opposite to old AliITSgeomTGeo, all indices start from 0, not from 1!!! -#include "ITS4Base/GeometryTGeo.h" +#include "TRKBase/GeometryTGeo.h" #include "DetectorsBase/GeometryManager.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "MathUtils/Cartesian.h" @@ -41,14 +41,14 @@ #include <cstring> // for strstr, strlen using namespace TMath; -using namespace o2::its4; +using namespace o2::trk; using namespace o2::detectors; using Segmentation = o2::itsmft::SegmentationAlpide; -ClassImp(o2::its4::GeometryTGeo); +ClassImp(o2::trk::GeometryTGeo); -std::unique_ptr<o2::its4::GeometryTGeo> GeometryTGeo::sInstance; +std::unique_ptr<o2::trk::GeometryTGeo> GeometryTGeo::sInstance; std::string GeometryTGeo::sVolumeName = "ITSV"; ///< Mother volume name std::string GeometryTGeo::sLayerName = "ITSULayer"; ///< Layer name @@ -60,13 +60,13 @@ std::string GeometryTGeo::sSensorName = "ITSUSensor"; ///< Sensor name std::string GeometryTGeo::sWrapperVolumeName = "ITSUWrapVol"; ///< Wrapper volume name //__________________________________________________________________________ -GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : o2::itsmft::GeometryTGeo(DetID::IT3) +GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : o2::itsmft::GeometryTGeo(DetID::TRK) { // default c-tor, if build is true, the structures will be filled and the transform matrices // will be cached if (sInstance) { - LOG(FATAL) << "Invalid use of public constructor: o2::its4::GeometryTGeo instance exists"; - // throw std::runtime_error("Invalid use of public constructor: o2::its4::GeometryTGeo instance exists"); + LOG(FATAL) << "Invalid use of public constructor: o2::trk::GeometryTGeo instance exists"; + // throw std::runtime_error("Invalid use of public constructor: o2::trk::GeometryTGeo instance exists"); } for (int i = MAXLAYERS; i--;) { @@ -82,9 +82,9 @@ void GeometryTGeo::adopt(GeometryTGeo* raw) { // adopt the unique instance from external raw pointer (to be used only to read saved instance from file) if (sInstance) { - LOG(FATAL) << "No adoption: o2::its4::GeometryTGeo instance exists"; + LOG(FATAL) << "No adoption: o2::trk::GeometryTGeo instance exists"; } - sInstance = std::unique_ptr<o2::its4::GeometryTGeo>(raw); + sInstance = std::unique_ptr<o2::trk::GeometryTGeo>(raw); } //__________________________________________________________________________ @@ -240,7 +240,7 @@ bool GeometryTGeo::getChipId(int index, int& lay, int& sta, int& hsta, int& mod, //__________________________________________________________________________ const char* GeometryTGeo::composeSymNameLayer(int lr) { - return Form("%s/%s%d", composeSymNameITS4(), getITSLayerPattern(), lr); + return Form("%s/%s%d", composeSymNameTRK(), getITSLayerPattern(), lr); } //__________________________________________________________________________ diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/MisalignmentParameter.cxx b/Detectors/Upgrades/ALICE3/TRK/base/src/MisalignmentParameter.cxx similarity index 94% rename from Detectors/Upgrades/PostLS4/IT4/base/src/MisalignmentParameter.cxx rename to Detectors/Upgrades/ALICE3/TRK/base/src/MisalignmentParameter.cxx index de5e2886c9688..ba16a754938c9 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/MisalignmentParameter.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/base/src/MisalignmentParameter.cxx @@ -11,13 +11,13 @@ /// \file MisalignmentParameter.cxx /// \brief Implementation of the MisalignmentParameter class -#include "ITS4Base/MisalignmentParameter.h" +#include "TRKBase/MisalignmentParameter.h" #include "FairParamList.h" -using namespace o2::its4; +using namespace o2::trk; -ClassImp(o2::its4::MisalignmentParameter); +ClassImp(o2::trk::MisalignmentParameter); MisalignmentParameter::MisalignmentParameter(const char* name, const char* title, const char* context) : FairParGenericSet(name, title, context), diff --git a/Detectors/Upgrades/PostLS4/IT4/base/src/ITS4BaseLinkDef.h b/Detectors/Upgrades/ALICE3/TRK/base/src/TRKBaseLinkDef.h similarity index 84% rename from Detectors/Upgrades/PostLS4/IT4/base/src/ITS4BaseLinkDef.h rename to Detectors/Upgrades/ALICE3/TRK/base/src/TRKBaseLinkDef.h index ffcb6d02c92fc..c773fbe3e13bb 100644 --- a/Detectors/Upgrades/PostLS4/IT4/base/src/ITS4BaseLinkDef.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/src/TRKBaseLinkDef.h @@ -14,7 +14,7 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class o2::its4::GeometryTGeo; -#pragma link C++ class o2::its4::MisalignmentParameter + ; +#pragma link C++ class o2::trk::GeometryTGeo; +#pragma link C++ class o2::trk::MisalignmentParameter + ; #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/macros/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRK/macros/CMakeLists.txt similarity index 100% rename from Detectors/Upgrades/PostLS4/IT4/macros/CMakeLists.txt rename to Detectors/Upgrades/ALICE3/TRK/macros/CMakeLists.txt diff --git a/Detectors/Upgrades/PostLS4/IT4/macros/test/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRK/macros/test/CMakeLists.txt similarity index 100% rename from Detectors/Upgrades/PostLS4/IT4/macros/test/CMakeLists.txt rename to Detectors/Upgrades/ALICE3/TRK/macros/test/CMakeLists.txt diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt similarity index 56% rename from Detectors/Upgrades/PostLS4/IT4/simulation/CMakeLists.txt rename to Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt index 483884d69a87d..9b99ee26b445c 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt @@ -8,18 +8,18 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -o2_add_library(ITS4Simulation +o2_add_library(TRKSimulation SOURCES src/V11Geometry.cxx src/V1Layer.cxx src/V3Layer.cxx src/Detector.cxx src/V3Services.cxx - PUBLIC_LINK_LIBRARIES O2::ITS4Base O2::ITSMFTSimulation + PUBLIC_LINK_LIBRARIES O2::TRKBase O2::ITSMFTSimulation ROOT::Physics) -o2_target_root_dictionary(ITS4Simulation - HEADERS include/ITS4Simulation/Detector.h - include/ITS4Simulation/V1Layer.h - include/ITS4Simulation/V3Layer.h - include/ITS4Simulation/V11Geometry.h - include/ITS4Simulation/V3Services.h +o2_target_root_dictionary(TRKSimulation + HEADERS include/TRKSimulation/Detector.h + include/TRKSimulation/V1Layer.h + include/TRKSimulation/V3Layer.h + include/TRKSimulation/V11Geometry.h + include/TRKSimulation/V3Services.h ) -o2_data_file(COPY data DESTINATION Detectors/ITS4/simulation) \ No newline at end of file +o2_data_file(COPY data DESTINATION Detectors/TRK/simulation) \ No newline at end of file diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/data/simcuts.dat b/Detectors/Upgrades/ALICE3/TRK/simulation/data/simcuts.dat similarity index 100% rename from Detectors/Upgrades/PostLS4/IT4/simulation/data/simcuts.dat rename to Detectors/Upgrades/ALICE3/TRK/simulation/data/simcuts.dat diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/Detector.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h similarity index 94% rename from Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/Detector.h rename to Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h index 07a34c82af897..e7398594b1ed8 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h @@ -11,8 +11,8 @@ /// \file Detector.h /// \brief Definition of the Detector class -#ifndef ALICEO2_ITS4_DETECTOR_H_ -#define ALICEO2_ITS4_DETECTOR_H_ +#ifndef ALICEO2_TRK_DETECTOR_H_ +#define ALICEO2_TRK_DETECTOR_H_ #include <vector> // for vector #include "DetectorsBase/GeometryManager.h" // for getSensID @@ -42,14 +42,14 @@ class Hit; namespace o2 { -namespace its4 +namespace trk { class GeometryTGeo; } } // namespace o2 namespace o2 { -namespace its4 +namespace trk { class V3Layer; } @@ -57,7 +57,7 @@ class V3Layer; namespace o2 { -namespace its4 +namespace trk { class V3Layer; class V3Services; @@ -88,7 +88,7 @@ class Detector : public o2::base::DetImpl<Detector> /// kFALSE for inactive detectors Detector(Bool_t active); - /// Special version for ITS4: add number on Inner Layers + /// Special version for TRK: add number on Inner Layers Detector(Bool_t active, Int_t nlay); /// Default constructor @@ -159,15 +159,15 @@ class Detector : public o2::base::DetImpl<Detector> // void defineLayerTurbo(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod, Double_t width, Double_t tilt, // Double_t lthick = 0., Double_t dthick = 0., UInt_t detType = 0, Int_t buildFlag = 0) override; - /// Sets the layer parameters for new ITS4 geo + /// Sets the layer parameters for new TRK geo /// \param nlay layer number /// \param r layer radius /// \param zlen layer length /// \param dthick detector thickness (if omitted, defaults to 0) /// \param dettypeID ?? /// \param buildLevel (if 0, all geometry is build, used for material budget studies) - void defineInnerLayerITS4(Int_t nlay, Double_t r, Double_t zlen, - Double_t dthick = 0., UInt_t detType = 0, Int_t buildFlag = 0); + void defineInnerLayerTRK(Int_t nlay, Double_t r, Double_t zlen, + Double_t dthick = 0., UInt_t detType = 0, Int_t buildFlag = 0); /// Gets the layer parameters /// \param nlay layer number @@ -238,7 +238,7 @@ class Detector : public o2::base::DetImpl<Detector> /// Return Chip Volume UID /// \param id volume id - Int_t chipVolUID(Int_t id) const { return o2::base::GeometryManager::getSensID(o2::detectors::DetID::IT4, id); } + Int_t chipVolUID(Int_t id) const { return o2::base::GeometryManager::getSensID(o2::detectors::DetID::TRK, id); } void EndOfEvent() override; @@ -265,7 +265,7 @@ class Detector : public o2::base::DetImpl<Detector> void createOuterBarrel(const Bool_t ob) { mCreateOuterBarrel = ob; }; Bool_t isCreateOuterBarrel() { return mCreateOuterBarrel; }; - o2::its4::GeometryTGeo* mGeometryTGeo; //! access to geometry details + o2::trk::GeometryTGeo* mGeometryTGeo; //! access to geometry details protected: Int_t* mLayerID; //! [sNumberLayers] layer identifier @@ -281,8 +281,8 @@ class Detector : public o2::base::DetImpl<Detector> double mEnergyLoss; //! energy loss } mTrackData; //! - Int_t mNumberOfInnerLayers; //! number of ITS4 inner layers - Int_t mTotalNumberOfLayers; //! total number of ITS4 layers (IB+OB) + Int_t mNumberOfInnerLayers; //! number of TRK inner layers + Int_t mTotalNumberOfLayers; //! total number of TRK layers (IB+OB) Bool_t mCreateOuterBarrel; //! true to create the Outer Barrel Int_t mNumberOfDetectors; @@ -295,7 +295,7 @@ class Detector : public o2::base::DetImpl<Detector> Int_t* mWrapperLayerId; //! Id of wrapper layer to which layer belongs (-1 if not wrapped) Bool_t* mTurboLayer; //! True for "turbo" layers - Bool_t* mITS4Layer; //! True for new ITS4 layers + Bool_t* mTRKLayer; //! True for new TRK layers Double_t* mLayerPhi0; //! Vector of layer's 1st stave phi in lab Double_t* mLayerRadii; //! Vector of layer radii Double_t* mLayerZLen; //! Vector of layer lengths @@ -363,7 +363,7 @@ class Detector : public o2::base::DetImpl<Detector> std::ostream& operator<<(std::ostream& os, Detector& source); std::istream& operator>>(std::istream& os, Detector& source); -} // namespace its4 +} // namespace trk } // namespace o2 #ifdef USESHM @@ -372,7 +372,7 @@ namespace o2 namespace base { template <> -struct UseShm<o2::its4::Detector> { +struct UseShm<o2::trk::Detector> { static constexpr bool value = true; }; } // namespace base diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V11Geometry.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V11Geometry.h similarity index 99% rename from Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V11Geometry.h rename to Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V11Geometry.h index e008c9bffd505..3e73c519cd9c8 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V11Geometry.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V11Geometry.h @@ -11,8 +11,8 @@ /// \file V11Geometry.h /// \brief Definition of the V11Geometry class -#ifndef ALICEO2_ITS4_V11GEOMETRY_H_ -#define ALICEO2_ITS4_V11GEOMETRY_H_ +#ifndef ALICEO2_TRK_V11GEOMETRY_H_ +#define ALICEO2_TRK_V11GEOMETRY_H_ #include <TMath.h> // for DegToRad, Cos, Sin, Tan #include <TObject.h> // for TObject @@ -27,7 +27,7 @@ class TGeoTubeSeg; // lines 14-14 namespace o2 { -namespace its4 +namespace trk { /// This class is a base class for the ITS geometry version 11. It contains common/standard @@ -452,7 +452,7 @@ class V11Geometry : public TObject Int_t mDebug; //! Debug flag/level ClassDefOverride(V11Geometry, 1); // Base class for ITS v11 geometry }; -} // namespace its4 +} // namespace trk } // namespace o2 #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V1Layer.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V1Layer.h similarity index 97% rename from Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V1Layer.h rename to Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V1Layer.h index 33e5e46ea0856..e338cb3a3a837 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V1Layer.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V1Layer.h @@ -8,13 +8,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef ALICEO2_ITS4_UPGRADEV1LAYER_H_ -#define ALICEO2_ITS4_UPGRADEV1LAYER_H_ +#ifndef ALICEO2_TRK_UPGRADEV1LAYER_H_ +#define ALICEO2_TRK_UPGRADEV1LAYER_H_ -#include <TGeoManager.h> // for gGeoManager -#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc -#include "ITS4Simulation/V11Geometry.h" // for V11Geometry -#include "ITS4Simulation/Detector.h" // for Detector, Detector::Model +#include <TGeoManager.h> // for gGeoManager +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc +#include "TRKSimulation/V11Geometry.h" // for V11Geometry +#include "TRKSimulation/Detector.h" // for Detector, Detector::Model class TGeoArb8; @@ -24,7 +24,7 @@ class TGeoVolume; // lines 15-15 namespace o2 { -namespace its4 +namespace trk { /// This class defines the Geometry for the ITS using TGeo. This is a work class used @@ -197,7 +197,7 @@ class V1Layer : public V11Geometry mBuildLevel = buildLevel; } - void setStaveModel(o2::its4::Detector::Model model) + void setStaveModel(o2::trk::Detector::Model model) { mStaveModel = model; } @@ -409,7 +409,7 @@ class V1Layer : public V11Geometry ClassDefOverride(V1Layer, 0); // ITS v1 geometry }; -} // namespace its4 +} // namespace trk } // namespace o2 #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Layer.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Layer.h similarity index 97% rename from Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Layer.h rename to Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Layer.h index c04160e8997ad..2180ebb487b84 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Layer.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Layer.h @@ -13,13 +13,13 @@ /// \author Mario Sitta <sitta@to.infn.it> /// \author Chinorat Kobdaj (kobdaj@g.sut.ac.th) -#ifndef ALICEO2_ITS4_UPGRADEV3LAYER_H_ -#define ALICEO2_ITS4_UPGRADEV3LAYER_H_ +#ifndef ALICEO2_TRK_UPGRADEV3LAYER_H_ +#define ALICEO2_TRK_UPGRADEV3LAYER_H_ -#include <TGeoManager.h> // for gGeoManager -#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc -#include "ITS4Simulation/V11Geometry.h" // for V11Geometry -#include "ITS4Simulation/Detector.h" // for Detector, Detector::Model +#include <TGeoManager.h> // for gGeoManager +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc +#include "TRKSimulation/V11Geometry.h" // for V11Geometry +#include "TRKSimulation/Detector.h" // for Detector, Detector::Model class TGeoXtru; @@ -29,7 +29,7 @@ class TGeoVolume; // lines 15-15 namespace o2 { -namespace its4 +namespace trk { /// This class defines the Geometry for the ITS using TGeo. This is a work class used @@ -64,7 +64,7 @@ class V3Layer : public V11Geometry Bool_t isTurbo() const { return mIsTurbo; }; - Bool_t isITS4() const { return mIsITS4; }; + Bool_t isTRK() const { return mIsTRK; }; Double_t getChipThick() const { return mChipThickness; }; @@ -110,10 +110,10 @@ class V3Layer : public V11Geometry /// Gets the Gamma Conversion Rod X position Double_t getGammaConversionRodXPos(); - /// Sets whether this is a new ITS4 layer - void setIsITS4(const Bool_t its4) { mIsITS4 = its4; }; + /// Sets whether this is a new TRK layer + void setIsTRK(const Bool_t trk) { mIsTRK = trk; }; - /// Sets Module Z length (valid only for new ITS4 layer) + /// Sets Module Z length (valid only for new TRK layer) void setIBModuleZLength(const Double_t z) { mIBModuleZLength = z; }; /// Sets the Stave tilt angle (for turbo layers only) @@ -142,7 +142,7 @@ class V3Layer : public V11Geometry void setBuildLevel(Int_t buildLevel) { mBuildLevel = buildLevel; } - void setStaveModel(o2::its4::Detector::Model model) { mStaveModel = model; } + void setStaveModel(o2::trk::Detector::Model model) { mStaveModel = model; } void setNumberOfInnerLayers(const Int_t n) { mNumberOfInnerLayers = n; }; @@ -163,10 +163,10 @@ class V3Layer : public V11Geometry /// \param motherVolume The TGeoVolume owing the volume structure void createLayerTurbo(TGeoVolume* motherVolume); - /// Creates a new ITS4 Layer and places inside its mother volume + /// Creates a new TRK Layer and places inside its mother volume /// \param motherVolume The TGeoVolume owing the volume structure /// \param mgr The GeoManager (used only to get the proper material) - void createITS4Layer(TGeoVolume* motherVolume, const TGeoManager* mgr = gGeoManager); + void createTRKLayer(TGeoVolume* motherVolume, const TGeoManager* mgr = gGeoManager); /// Computes the inner radius of the air container for the Turbo configuration /// as the radius of either the circle tangent to the stave or the circle @@ -340,7 +340,7 @@ class V3Layer : public V11Geometry UInt_t mChipTypeID; ///< detector type id Bool_t mIsTurbo; ///< True if this layer is a "turbo" layer - Bool_t mIsITS4; ///< True if this layer is a new ITS4 layer + Bool_t mIsTRK; ///< True if this layer is a new TRK layer Int_t mBuildLevel; ///< Used for material studies Detector::Model mStaveModel; ///< The stave model @@ -564,7 +564,7 @@ class V3Layer : public V11Geometry ClassDefOverride(V3Layer, 0); // ITS v3 geometry }; -} // namespace its4 +} // namespace trk } // namespace o2 #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Services.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Services.h similarity index 95% rename from Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Services.h rename to Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Services.h index c1ba390d07c10..58e2c918f7ace 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/include/ITS4Simulation/V3Services.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Services.h @@ -13,13 +13,13 @@ /// \author Mario Sitta <sitta@to.infn.it> /// \author Parinya Namwongsa <parinya.namwongsa@cern.ch> -#ifndef ALICEO2_ITS4_UPGRADEV3SERVICES_H_ -#define ALICEO2_ITS4_UPGRADEV3SERVICES_H_ +#ifndef ALICEO2_TRK_UPGRADEV3SERVICES_H_ +#define ALICEO2_TRK_UPGRADEV3SERVICES_H_ -#include <TGeoManager.h> // for gGeoManager -#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc -#include "ITS4Simulation/V11Geometry.h" // for V11Geometry -#include "ITS4Simulation/Detector.h" // for Detector, Detector::Model +#include <TGeoManager.h> // for gGeoManager +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc +#include "TRKSimulation/V11Geometry.h" // for V11Geometry +#include "TRKSimulation/Detector.h" // for Detector, Detector::Model class TGeoXtru; @@ -29,7 +29,7 @@ class TGeoVolume; namespace o2 { -namespace its4 +namespace trk { /// This class defines the Geometry for the Services of the ITS Upgrade using TGeo. @@ -178,7 +178,7 @@ class V3Services : public V11Geometry ClassDefOverride(V3Services, 0); // ITS v3 support geometry }; -} // namespace its4 +} // namespace trk } // namespace o2 #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx similarity index 97% rename from Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx rename to Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 30dc0658cd6be..06c40781b5696 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -13,10 +13,10 @@ #include "ITSMFTBase/SegmentationAlpide.h" #include "ITSMFTSimulation/Hit.h" -#include "ITS4Base/GeometryTGeo.h" -#include "ITS4Simulation/Detector.h" -#include "ITS4Simulation/V3Layer.h" -#include "ITS4Simulation/V3Services.h" +#include "TRKBase/GeometryTGeo.h" +#include "TRKSimulation/Detector.h" +#include "TRKSimulation/V3Layer.h" +#include "TRKSimulation/V3Services.h" #include "SimulationDataFormat/Stack.h" #include "SimulationDataFormat/TrackReference.h" @@ -51,7 +51,7 @@ using std::endl; using o2::itsmft::Hit; using Segmentation = o2::itsmft::SegmentationAlpide; -using namespace o2::its4; +using namespace o2::trk; float getDetLengthFromEta(const float eta, const float radius) { @@ -59,7 +59,7 @@ float getDetLengthFromEta(const float eta, const float radius) } Detector::Detector() - : o2::base::DetImpl<Detector>("IT4", kTRUE), + : o2::base::DetImpl<Detector>("TRK", kTRUE), mTrackData(), /* mHitStarted(false), @@ -118,8 +118,8 @@ void Detector::configITS(Detector* its) // double dzLr, rLr, phi0, turbo; // int nStaveLr, nModPerStaveLr; - // its->setStaveModelIB(o2::its4::Detector::kIBModel4); - its->setStaveModelOB(o2::its4::Detector::kOBModel2); + // its->setStaveModelIB(o2::trk::Detector::kIBModel4); + its->setStaveModelOB(o2::trk::Detector::kOBModel2); const int kNWrapVol = 3; const double wrpRMin[kNWrapVol] = {2.1, 19.3, 33.32}; @@ -157,19 +157,19 @@ void Detector::configITS(Detector* its) tdr5data.emplace_back(std::array<double, 2>{100.f, getDetLengthFromEta(1.44f, 100.f)}); std::array<float, 10> sensorThicknesses = {50.e-4, 50.e-4, 50.e-4, 50.e-3, 50.e-3, 50.e-3, 50.e-3, 50.e-3, 50.e-3, 50.e-3}; - its->setStaveModelOB(o2::its4::Detector::kOBModel2); + its->setStaveModelOB(o2::trk::Detector::kOBModel2); // its->createOuterBarrel(false); auto idLayer{0}; for (auto& layerData : tdr5data) { - its->defineInnerLayerITS4(idLayer, layerData[0], layerData[1], sensorThicknesses[idLayer], 0, 0); + its->defineInnerLayerTRK(idLayer, layerData[0], layerData[1], sensorThicknesses[idLayer], 0, 0); ++idLayer; } its->createOuterBarrel(false); } Detector::Detector(Bool_t active) - : o2::base::DetImpl<Detector>("IT4", active), + : o2::base::DetImpl<Detector>("TRK", active), mTrackData(), /* mHitStarted(false), @@ -196,7 +196,7 @@ Detector::Detector(Bool_t active) if (mTotalNumberOfLayers > 0) { // if not, we'll Fatal-ize in CreateGeometry for (Int_t j = 0; j < mTotalNumberOfLayers; j++) { - mITS4Layer[j] = kFALSE; + mTRKLayer[j] = kFALSE; mLayerPhi0[j] = 0; mLayerRadii[j] = 0.; mLayerZLen[j] = 0.; @@ -301,7 +301,7 @@ void Detector::createAllArrays() mWrapperLayerId = new Int_t[mTotalNumberOfLayers]; mTurboLayer = new Bool_t[mTotalNumberOfLayers]; - mITS4Layer = new Bool_t[mTotalNumberOfLayers]; + mTRKLayer = new Bool_t[mTotalNumberOfLayers]; mLayerPhi0 = new Double_t[mTotalNumberOfLayers]; mLayerRadii = new Double_t[mTotalNumberOfLayers]; @@ -679,8 +679,8 @@ void Detector::defineLayer(Int_t nlay, double phi0, Double_t r, Int_t nstav, Int mBuildLevel[nlay] = buildLevel; } -void Detector::defineInnerLayerITS4(Int_t nlay, Double_t r, Double_t zlen, - Double_t dthick, UInt_t dettypeID, Int_t buildLevel) +void Detector::defineInnerLayerTRK(Int_t nlay, Double_t r, Double_t zlen, + Double_t dthick, UInt_t dettypeID, Int_t buildLevel) { // Sets the layer parameters // Inputs: @@ -695,7 +695,7 @@ void Detector::defineInnerLayerITS4(Int_t nlay, Double_t r, Double_t zlen, // Return: // none. - LOG(INFO) << "L# " << nlay << " with ITS4 geo R:" << r + LOG(INFO) << "L# " << nlay << " with TRK geo R:" << r << " Dthick:" << dthick << " DetID:" << dettypeID << " B:" << buildLevel; if (nlay >= mTotalNumberOfLayers || nlay < 0) { @@ -704,7 +704,7 @@ void Detector::defineInnerLayerITS4(Int_t nlay, Double_t r, Double_t zlen, } mTurboLayer[nlay] = kFALSE; - mITS4Layer[nlay] = kTRUE; + mTRKLayer[nlay] = kTRUE; mLayerRadii[nlay] = r; mLayerZLen[nlay] = zlen; mDetectorThickness[nlay] = dthick; @@ -806,7 +806,7 @@ TGeoVolume* Detector::createWrapperVolume(Int_t id) break; } - TGeoMedium* medAir = gGeoManager->GetMedium("IT4_AIR$"); + TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$"); char volnam[30]; snprintf(volnam, 29, "%s%d", GeometryTGeo::getITSWrapVolPattern(), id); @@ -847,13 +847,13 @@ void Detector::constructDetectorGeometry() if (mLayerRadii[j] <= 0) { LOG(FATAL) << "Wrong layer radius for layer " << j << "(" << mLayerRadii[j] << ")"; } - if (mStavePerLayer[j] <= 0 && !mITS4Layer[j]) { + if (mStavePerLayer[j] <= 0 && !mTRKLayer[j]) { LOG(FATAL) << "Wrong number of staves for layer " << j << "(" << mStavePerLayer[j] << ")"; } - if (mUnitPerStave[j] <= 0 && !mITS4Layer[j]) { + if (mUnitPerStave[j] <= 0 && !mTRKLayer[j]) { LOG(FATAL) << "Wrong number of chips for layer " << j << "(" << mUnitPerStave[j] << ")"; } - if (mChipThickness[j] < 0 && !mITS4Layer[j]) { + if (mChipThickness[j] < 0 && !mTRKLayer[j]) { LOG(FATAL) << "Wrong chip thickness for layer " << j << "(" << mChipThickness[j] << ")"; } if (mTurboLayer[j] && mStaveWidth[j] <= 0) { @@ -871,7 +871,7 @@ void Detector::constructDetectorGeometry() } } - if (mChipThickness[j] == 0 && !mITS4Layer[j]) { + if (mChipThickness[j] == 0 && !mTRKLayer[j]) { LOG(INFO) << "Chip thickness for layer " << j << " not set, using default"; } } @@ -905,8 +905,8 @@ void Detector::constructDetectorGeometry() mGeometry[j]->setNumberOfInnerLayers(mNumberOfInnerLayers); - if (mITS4Layer[j]) { - mGeometry[j]->setIsITS4(kTRUE); + if (mTRKLayer[j]) { + mGeometry[j]->setIsTRK(kTRUE); mGeometry[j]->setIBModuleZLength(mLayerZLen[j]); } @@ -1078,7 +1078,7 @@ void Detector::createServiceBarrel(const Bool_t innerBarrel, TGeoVolume* dest, c // Double_t phi1 = 180; // Double_t phi2 = 360; - TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("TRK_CarbonFleece$"); if (innerBarrel) { zLenOB = ((TGeoTube*)(dest->GetShape()))->GetDz(); @@ -1113,7 +1113,7 @@ void Detector::addAlignableVolumes() const } TString path = Form("/cave_1/barrel_1/%s_2", GeometryTGeo::getITSVolPattern()); - TString sname = GeometryTGeo::composeSymNameITS4(); + TString sname = GeometryTGeo::composeSymNameTRK(); LOG(DEBUG) << sname << " <-> " << path; @@ -1371,4 +1371,4 @@ std::istream& operator>>(std::istream& is, Detector& r) return is; } -ClassImp(o2::its4::Detector); +ClassImp(o2::trk::Detector); diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h similarity index 66% rename from Detectors/Upgrades/PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h rename to Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h index b880f7208f756..959b89136db28 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/ITS4SimulationLinkDef.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h @@ -14,11 +14,11 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class o2::its4::V11Geometry + ; -#pragma link C++ class o2::its4::V1Layer + ; -#pragma link C++ class o2::its4::V3Layer + ; -#pragma link C++ class o2::its4::V3Services + ; -#pragma link C++ class o2::its4::Detector + ; -#pragma link C++ class o2::base::DetImpl < o2::its4::Detector> + ; +#pragma link C++ class o2::trk::V11Geometry + ; +#pragma link C++ class o2::trk::V1Layer + ; +#pragma link C++ class o2::trk::V3Layer + ; +#pragma link C++ class o2::trk::V3Services + ; +#pragma link C++ class o2::trk::Detector + ; +#pragma link C++ class o2::base::DetImpl < o2::trk::Detector> + ; #endif diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V11Geometry.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V11Geometry.cxx similarity index 94% rename from Detectors/Upgrades/PostLS4/IT4/simulation/src/V11Geometry.cxx rename to Detectors/Upgrades/ALICE3/TRK/simulation/src/V11Geometry.cxx index ce89b44ada297..a341a322ff539 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V11Geometry.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V11Geometry.cxx @@ -11,7 +11,7 @@ /// \file V11Geometry.cxx /// \brief Implementation of the V11Geometry class -#include "ITS4Simulation/V11Geometry.h" +#include "TRKSimulation/V11Geometry.h" #include "FairLogger.h" // for LOG @@ -38,9 +38,9 @@ using std::cin; using std::cout; using std::endl; -using namespace o2::its4; +using namespace o2::trk; -ClassImp(o2::its4::V11Geometry); +ClassImp(o2::trk::V11Geometry); const Double_t V11Geometry::sMicron = 1.0E-4; const Double_t V11Geometry::sMm = 0.10; @@ -392,30 +392,30 @@ void V11Geometry::createDefaultMaterials() Double_t w; // Define some elements - auto* itsH = new TGeoElement("IT4_H", "Hydrogen", 1, 1.00794); - auto* itsHe = new TGeoElement("IT4_He", "Helium", 2, 4.002602); - auto* itsC = new TGeoElement("IT4_C", "Carbon", 6, 12.0107); - auto* itsN = new TGeoElement("IT4_N", "Nitrogen", 7, 14.0067); - auto* itsO = new TGeoElement("IT4_O", "Oxygen", 8, 15.994); - auto* itsF = new TGeoElement("IT4_F", "Florine", 9, 18.9984032); - auto* itsNe = new TGeoElement("IT4_Ne", "Neon", 10, 20.1797); - auto* itsMg = new TGeoElement("IT4_Mg", "Magnesium", 12, 24.3050); - auto* itsAl = new TGeoElement("IT4_Al", "Aluminum", 13, 26981538); - auto* itsSi = new TGeoElement("IT4_Si", "Silicon", 14, 28.0855); - auto* itsP = new TGeoElement("IT4_P", "Phosphorous", 15, 30.973761); - auto* itsS = new TGeoElement("IT4_S", "Sulfur", 16, 32.065); - auto* itsAr = new TGeoElement("IT4_Ar", "Argon", 18, 39.948); - auto* itsTi = new TGeoElement("IT4_Ti", "Titanium", 22, 47.867); - auto* itsCr = new TGeoElement("IT4_Cr", "Chromium", 24, 51.9961); - auto* itsMn = new TGeoElement("IT4_Mn", "Manganese", 25, 54.938049); - auto* itsFe = new TGeoElement("IT4_Fe", "Iron", 26, 55.845); - auto* itsCo = new TGeoElement("IT4_Co", "Cobalt", 27, 58.933200); - auto* itsNi = new TGeoElement("IT4_Ni", "Nickrl", 28, 56.6930); - auto* itsCu = new TGeoElement("IT4_Cu", "Copper", 29, 63.546); - auto* itsZn = new TGeoElement("IT4_Zn", "Zinc", 30, 65.39); - auto* itsKr = new TGeoElement("IT4_Kr", "Krypton", 36, 83.80); - auto* itsMo = new TGeoElement("IT4_Mo", "Molylibdium", 42, 95.94); - auto* itsXe = new TGeoElement("IT4_Xe", "Zeon", 54, 131.293); + auto* itsH = new TGeoElement("TRK_H", "Hydrogen", 1, 1.00794); + auto* itsHe = new TGeoElement("TRK_He", "Helium", 2, 4.002602); + auto* itsC = new TGeoElement("TRK_C", "Carbon", 6, 12.0107); + auto* itsN = new TGeoElement("TRK_N", "Nitrogen", 7, 14.0067); + auto* itsO = new TGeoElement("TRK_O", "Oxygen", 8, 15.994); + auto* itsF = new TGeoElement("TRK_F", "Florine", 9, 18.9984032); + auto* itsNe = new TGeoElement("TRK_Ne", "Neon", 10, 20.1797); + auto* itsMg = new TGeoElement("TRK_Mg", "Magnesium", 12, 24.3050); + auto* itsAl = new TGeoElement("TRK_Al", "Aluminum", 13, 26981538); + auto* itsSi = new TGeoElement("TRK_Si", "Silicon", 14, 28.0855); + auto* itsP = new TGeoElement("TRK_P", "Phosphorous", 15, 30.973761); + auto* itsS = new TGeoElement("TRK_S", "Sulfur", 16, 32.065); + auto* itsAr = new TGeoElement("TRK_Ar", "Argon", 18, 39.948); + auto* itsTi = new TGeoElement("TRK_Ti", "Titanium", 22, 47.867); + auto* itsCr = new TGeoElement("TRK_Cr", "Chromium", 24, 51.9961); + auto* itsMn = new TGeoElement("TRK_Mn", "Manganese", 25, 54.938049); + auto* itsFe = new TGeoElement("TRK_Fe", "Iron", 26, 55.845); + auto* itsCo = new TGeoElement("TRK_Co", "Cobalt", 27, 58.933200); + auto* itsNi = new TGeoElement("TRK_Ni", "Nickrl", 28, 56.6930); + auto* itsCu = new TGeoElement("TRK_Cu", "Copper", 29, 63.546); + auto* itsZn = new TGeoElement("TRK_Zn", "Zinc", 30, 65.39); + auto* itsKr = new TGeoElement("TRK_Kr", "Krypton", 36, 83.80); + auto* itsMo = new TGeoElement("TRK_Mo", "Molylibdium", 42, 95.94); + auto* itsXe = new TGeoElement("TRK_Xe", "Zeon", 54, 131.293); // Start with the Materials since for any one material there // can be defined more than one Medium. @@ -426,7 +426,7 @@ void V11Geometry::createDefaultMaterials() // He 0.000524% (0.00007%), Kr 0.000114% (0.0003%), H2 0.00005% (3.5E-6%), // Xe 0.0000087% (0.00004 %), H2O 0.0% (dry) + trace amounts at the ppm // levels. - auto* itsAir = new TGeoMixture("IT4_Air", 9); + auto* itsAir = new TGeoMixture("TRK_Air", 9); w = 75.47E-2; itsAir->AddElement(itsN, w); // Nitorgen, atomic w = 23.29E-2 + // O2 @@ -453,12 +453,12 @@ void V11Geometry::createDefaultMaterials() itsAir->SetState(TGeoMaterial::kMatStateGas); // Silicone - auto* itsSiDet = new TGeoMaterial("IT4_Si", itsSi, 2.33 * sGCm3); + auto* itsSiDet = new TGeoMaterial("TRK_Si", itsSi, 2.33 * sGCm3); itsSiDet->SetTemperature(15.0 * sCelsius); itsSiDet->SetState(TGeoMaterial::kMatStateSolid); // Epoxy C18 H19 O3 - auto* itsEpoxy = new TGeoMixture("IT4_Epoxy", 3); + auto* itsEpoxy = new TGeoMixture("TRK_Epoxy", 3); itsEpoxy->AddElement(itsC, 18); itsEpoxy->AddElement(itsH, 19); itsEpoxy->AddElement(itsO, 3); @@ -474,7 +474,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsCarbonFiber = new TGeoMixture("IT4_CarbonFiber-M55J", 4); + auto* itsCarbonFiber = new TGeoMixture("TRK_CarbonFiber-M55J", 4); // Assume that the epoxy fill in the space between the fibers and so // no change in the total volume. To compute w, assume 1cm^3 total // volume. @@ -501,7 +501,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsFoam = new TGeoMixture("IT4_Foam", 4); + auto* itsFoam = new TGeoMixture("TRK_Foam", 4); itsFoam->AddElement(itsC, 9); itsFoam->AddElement(itsH, 13); itsFoam->AddElement(itsN, 1); @@ -521,7 +521,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsKapton = new TGeoMixture("IT4_Kapton", 4); + auto* itsKapton = new TGeoMixture("TRK_Kapton", 4); itsKapton->AddElement(itsH, 0.026362); itsKapton->AddElement(itsC, 0.691133); itsKapton->AddElement(itsN, 0.073270); @@ -541,7 +541,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsUpilex = new TGeoMixture("IT4_Upilex", 4); + auto* itsUpilex = new TGeoMixture("TRK_Upilex", 4); itsUpilex->AddElement(itsC, 16); itsUpilex->AddElement(itsH, 6); itsUpilex->AddElement(itsN, 2); @@ -563,7 +563,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsAl6061 = new TGeoMixture("IT4_Al6061", 9); + auto* itsAl6061 = new TGeoMixture("TRK_Al6061", 9); itsAl6061->AddElement(itsCr, 0.000375); itsAl6061->AddElement(itsCu, 0.00275); itsAl6061->AddElement(itsFe, 0.0035); @@ -590,7 +590,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsAl7075 = new TGeoMixture("IT4_Al7075", 9); + auto* itsAl7075 = new TGeoMixture("TRK_Al7075", 9); itsAl7075->AddElement(itsCr, 0.0023); itsAl7075->AddElement(itsCu, 0.016); itsAl7075->AddElement(itsFe, 0.0025); @@ -614,7 +614,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsRuby = new TGeoMixture("IT4_RubySphere", 2); + auto* itsRuby = new TGeoMixture("TRK_RubySphere", 2); itsRuby->AddElement(itsAl, 2); itsRuby->AddElement(itsO, 3); itsRuby->SetTitle("Ruby reference sphere"); @@ -633,7 +633,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsInox304L = new TGeoMixture("IT4_Inox304L", 9); + auto* itsInox304L = new TGeoMixture("TRK_Inox304L", 9); itsInox304L->AddElement(itsC, 0.00015); itsInox304L->AddElement(itsMn, 0.010); itsInox304L->AddElement(itsSi, 0.005); @@ -659,7 +659,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsInox316L = new TGeoMixture("IT4_Inox316L", 9); + auto* itsInox316L = new TGeoMixture("TRK_Inox316L", 9); itsInox316L->AddElement(itsC, 0.00015); itsInox316L->AddElement(itsMn, 0.010); itsInox316L->AddElement(itsSi, 0.005); @@ -688,7 +688,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsPhynox = new TGeoMixture("IT4_Phynox", 7); + auto* itsPhynox = new TGeoMixture("TRK_Phynox", 7); itsPhynox->AddElement(itsC, 0.0015); itsPhynox->AddElement(itsMn, 0.020); itsPhynox->AddElement(itsNi, 0.18); @@ -704,7 +704,7 @@ void V11Geometry::createDefaultMaterials() // G10FR4 // Demineralized Water H2O SDD & SSD Cooling liquid - auto* itsWater = new TGeoMixture("IT4_Water", 2); + auto* itsWater = new TGeoMixture("TRK_Water", 2); itsWater->AddElement(itsH, 2); itsWater->AddElement(itsO, 1); itsWater->SetTitle("ITS Cooling Water"); @@ -721,7 +721,7 @@ void V11Geometry::createDefaultMaterials() </A> */ // End_Html - auto* itsFreon = new TGeoMixture("IT4_SPD_Freon", 2); + auto* itsFreon = new TGeoMixture("TRK_SPD_Freon", 2); itsFreon->AddElement(itsC, 4); itsFreon->AddElement(itsF, 10); itsFreon->SetTitle("ITS SPD 2 phase Cooling freon"); diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V1Layer.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V1Layer.cxx similarity index 95% rename from Detectors/Upgrades/PostLS4/IT4/simulation/src/V1Layer.cxx rename to Detectors/Upgrades/ALICE3/TRK/simulation/src/V1Layer.cxx index 6147ed7467cb7..e190a5390a31f 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V1Layer.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V1Layer.cxx @@ -13,9 +13,9 @@ /// \author Mario Sitta <sitta@to.infn.it> /// \author Chinorat Kobdaj (kobdaj@g.sut.ac.th) -#include "ITS4Simulation/V1Layer.h" -#include "ITS4Base/GeometryTGeo.h" -#include "ITS4Simulation/Detector.h" +#include "TRKSimulation/V1Layer.h" +#include "TRKBase/GeometryTGeo.h" +#include "TRKSimulation/Detector.h" #include "FairLogger.h" // for LOG @@ -36,7 +36,7 @@ class TGeoMedium; using namespace TMath; -using namespace o2::its4; +using namespace o2::trk; // General Parameters const Int_t V1Layer::sNumberOmInnerLayers = 3; @@ -288,7 +288,7 @@ void V1Layer::createLayer(TGeoVolume* motherVolume) // mStaveWidth = mLayerRadius*Tan(alpha); - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSLayerPattern(), mLayerNumber); TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); layerVolume->SetUniqueID(mChipTypeID); @@ -333,7 +333,7 @@ void V1Layer::createLayerTurbo(TGeoVolume* motherVolume) LOG(WARNING) << "Stave tilt angle (" << mStaveTilt << ") greater than 45deg"; } - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSLayerPattern(), mLayerNumber); TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); layerVolume->SetUniqueID(mChipTypeID); layerVolume->SetVisibility(kTRUE); @@ -389,7 +389,7 @@ TGeoVolume* V1Layer::createStave(const TGeoManager* /*mgr*/) // We have all shapes: now create the real volumes - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); // TGeoVolume *staveVol = new TGeoVolume(volumeName, stave, medAir); TGeoVolume* staveVol = new TGeoVolumeAssembly(volumeName); @@ -452,9 +452,9 @@ TGeoVolume* V1Layer::createStaveInnerB(const Double_t xsta, const Double_t ysta, auto* hstave = new TGeoBBox(xmod, ymod, zmod); - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); auto* hstaveVol = new TGeoVolume(volumeName, hstave, medAir); // Finally build it up @@ -479,9 +479,9 @@ TGeoVolume* V1Layer::createModuleInnerB(Double_t xmod, Double_t ymod, Double_t z // Then create the module and populate it with the chips auto* module = new TGeoBBox(xmod, ymod, zmod); - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSModulePattern(), mLayerNumber); auto* modVol = new TGeoVolume(volumeName, module, medAir); // mm (not used) zlen = ((TGeoBBox*)chipVol->GetShape())->GetDZ(); @@ -536,14 +536,14 @@ TGeoVolume* V1Layer::createStaveModelInnerB0(const Double_t xsta, const Double_t const TGeoManager* mgr) { // Materials defined in Detector - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); LOG(INFO) << "################################# pointer :" << medWater; - TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); + TGeoMedium* medM60J3K = mgr->GetMedium("TRK_M60J3K$"); LOG(INFO) << "################################# pointer :" << medM60J3K; - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("TRK_FLEXCABLE$"); // Local parameters Double_t kConeOutRadius = 0.15 / 2; @@ -567,7 +567,7 @@ TGeoVolume* V1Layer::createStaveModelInnerB0(const Double_t xsta, const Double_t LOG(DEBUG1) << "BuildLevel " << mBuildLevel; char volumeName[30]; - snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); Double_t z = 0, y = -0.011 + 0.0150, x = 0; @@ -728,13 +728,13 @@ TGeoVolume* V1Layer::createStaveModelInnerB1(const Double_t xsta, const Double_t const TGeoManager* mgr) { // Materials defined in Detector - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); - TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); + TGeoMedium* medM60J3K = mgr->GetMedium("TRK_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("TRK_FLEXCABLE$"); // Local parameters Double_t kConeOutRadius = 0.15 / 2; @@ -757,7 +757,7 @@ TGeoVolume* V1Layer::createStaveModelInnerB1(const Double_t xsta, const Double_t TGeoVolume* mechStavVol = nullptr; char volumeName[30]; - snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); // detailed structure ++++++++++++++ @@ -932,16 +932,16 @@ TGeoVolume* V1Layer::createStaveModelInnerB21(const Double_t xsta, const Double_ const TGeoManager* mgr) { // Materials defined in Detector - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); - TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); - TGeoMedium* medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); - TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); - TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + TGeoMedium* medM60J3K = mgr->GetMedium("TRK_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("TRK_FLEXCABLE$"); + TGeoMedium* medK13D2U2k = mgr->GetMedium("TRK_K13D2U2k$"); + TGeoMedium* medFGS003 = mgr->GetMedium("TRK_FGS003$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("TRK_CarbonFleece$"); // Local parameters Double_t kConeOutRadius = 0.151384 / 2; @@ -966,7 +966,7 @@ TGeoVolume* V1Layer::createStaveModelInnerB21(const Double_t xsta, const Double_ Int_t loop = (Int_t)(kStaveLength / (2 * kL1)); char volumeName[30]; - snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); Double_t z = 0, y = -(kConeOutRadius + 0.03) + 0.0385, x = 0; @@ -1212,17 +1212,17 @@ TGeoVolume* V1Layer::createStaveModelInnerB22(const Double_t xsta, const Double_ const TGeoManager* mgr) { // Materials defined in Detector - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); - TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); - TGeoMedium* medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); - TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); - TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + TGeoMedium* medM60J3K = mgr->GetMedium("TRK_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("TRK_FLEXCABLE$"); + TGeoMedium* medK13D2U2k = mgr->GetMedium("TRK_K13D2U2k$"); + TGeoMedium* medFGS003 = mgr->GetMedium("TRK_FGS003$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("TRK_CarbonFleece$"); // Local parameters Double_t kConeOutRadius = (0.1024 + 0.0025) / 2; // 0.107/2; @@ -1252,7 +1252,7 @@ TGeoVolume* V1Layer::createStaveModelInnerB22(const Double_t xsta, const Double_ Int_t loop = (Int_t)(kStaveLength / (2 * kL1)); char volumeName[30]; - snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); Double_t z = 0, y = -(2 * kConeOutRadius) + klay1 + klay2 + mSensorThickness / 2 - 0.0004, x = 0; @@ -1519,16 +1519,16 @@ TGeoVolume* V1Layer::createStaveModelInnerB3(const Double_t xsta, const Double_t const TGeoManager* mgr) { // Materials defined in Detector - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); - TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medFlexCable = mgr->GetMedium("IT4_FLEXCABLE$"); - // TGeoMedium *medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); - // TGeoMedium *medFGS003 = mgr->GetMedium("IT4_FGS003$"); - // TGeoMedium *medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + TGeoMedium* medM60J3K = mgr->GetMedium("TRK_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medFlexCable = mgr->GetMedium("TRK_FLEXCABLE$"); + // TGeoMedium *medK13D2U2k = mgr->GetMedium("TRK_K13D2U2k$"); + // TGeoMedium *medFGS003 = mgr->GetMedium("TRK_FGS003$"); + // TGeoMedium *medCarbonFleece = mgr->GetMedium("TRK_CarbonFleece$"); // Local parameters Double_t kConeOutRadius = 0.15 / 2; @@ -1565,7 +1565,7 @@ TGeoVolume* V1Layer::createStaveModelInnerB3(const Double_t xsta, const Double_t Double_t smcSpace = 0.01; char volumeName[30]; - snprintf(volumeName, 30, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), + snprintf(volumeName, 30, "%s%d_StaveStruct", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); // detailed structure ++++++++++++++ @@ -1991,13 +1991,13 @@ TGeoVolume* V1Layer::createStaveModelOuterB0(const TGeoManager* mgr) auto* hstave = new TGeoBBox(xlen, ylen, zlen / 2); // We have all shapes: now create the real volumes - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSModulePattern(), mLayerNumber); auto* modVol = new TGeoVolume(volumeName, module, medAir); modVol->SetVisibility(kTRUE); - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); auto* hstaveVol = new TGeoVolume(volumeName, hstave, medAir); // Finally build it up @@ -2101,13 +2101,13 @@ TGeoVolume* V1Layer::createStaveModelOuterB1(const TGeoManager* mgr) // We have all shapes: now create the real volumes - TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); - TGeoMedium* medCarbon = mgr->GetMedium("IT4_CARBON$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); - TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); - TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); // amec thermasol - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medAluminum = mgr->GetMedium("TRK_ALUMINUM$"); + TGeoMedium* medCarbon = mgr->GetMedium("TRK_CARBON$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("TRK_CarbonFleece$"); + TGeoMedium* medFGS003 = mgr->GetMedium("TRK_FGS003$"); // amec thermasol + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); auto* busAlVol = new TGeoVolume("BusAlVol", busAl, medAluminum); busAlVol->SetLineColor(kCyan); @@ -2174,7 +2174,7 @@ TGeoVolume* V1Layer::createStaveModelOuterB1(const TGeoManager* mgr) fleectubVol->SetFillColor(fleectubVol->GetLineColor()); fleectubVol->SetFillStyle(4000); // 0% transparent - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); auto* halmStaveVol = new TGeoVolume(volumeName, halmStave, medAir); // halmStaveVol->SetLineColor(12); // halmStaveVol->SetFillColor(12); @@ -2320,8 +2320,8 @@ TGeoVolume* V1Layer::createSpaceFrameOuterBDummy(const TGeoManager*) const TGeoVolume* V1Layer::createSpaceFrameOuterB1(const TGeoManager* mgr) { // Materials defined in Detector - TGeoMedium* medCarbon = mgr->GetMedium("IT4_CARBON$"); - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medCarbon = mgr->GetMedium("TRK_CARBON$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); // Local parameters Double_t sframeWidth = sOBSpaceFrameWidth; @@ -2346,7 +2346,7 @@ TGeoVolume* V1Layer::createSpaceFrameOuterB1(const TGeoManager* mgr) zlen = mNumberOfModules * sOBModuleZLength + (mNumberOfModules - 1) * sOBModuleGap; - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); if (gGeoManager->GetVolume(volumeName)) { // Should always be so sframeHeight -= ((TGeoBBox*)gGeoManager->GetVolume(volumeName)->GetShape())->GetDY() * 2; zlen = ((TGeoBBox*)gGeoManager->GetVolume(volumeName)->GetShape())->GetDZ() * 2; @@ -2524,14 +2524,14 @@ TGeoVolume* V1Layer::createChipInnerB(const Double_t xchip, const Double_t ychip auto* sensor = new TGeoBBox(xlen, ylen, zlen); // We have all shapes: now create the real volumes - TGeoMedium* medSi = mgr->GetMedium("IT4_SI$"); + TGeoMedium* medSi = mgr->GetMedium("TRK_SI$"); - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSChipPattern(), mLayerNumber); auto* chipVol = new TGeoVolume(volumeName, chip, medSi); chipVol->SetVisibility(kTRUE); chipVol->SetLineColor(1); - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSSensorPattern(), mLayerNumber); auto* sensVol = new TGeoVolume(volumeName, sensor, medSi); sensVol->SetVisibility(kTRUE); sensVol->SetLineColor(8); @@ -2599,11 +2599,11 @@ TGeoVolume* V1Layer::createModuleOuterB(const TGeoManager* mgr) // We have all shapes: now create the real volumes - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medCarbon = mgr->GetMedium("IT4_CARBON$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medCarbon = mgr->GetMedium("TRK_CARBON$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medAluminum = mgr->GetMedium("TRK_ALUMINUM$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); auto* modPlateVol = new TGeoVolume("CarbonPlateVol", modPlate, medCarbon); modPlateVol->SetLineColor(kMagenta - 8); @@ -2625,7 +2625,7 @@ TGeoVolume* V1Layer::createModuleOuterB(const TGeoManager* mgr) flexKapVol->SetFillColor(flexKapVol->GetLineColor()); flexKapVol->SetFillStyle(4000); // 0% transparent - snprintf(volumeName, 30, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + snprintf(volumeName, 30, "%s%d", o2::trk::GeometryTGeo::getITSModulePattern(), mLayerNumber); auto* modVol = new TGeoVolume(volumeName, module, medAir); modVol->SetVisibility(kTRUE); diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Layer.cxx similarity index 96% rename from Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx rename to Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Layer.cxx index d9840e6ae6b7e..062dd419f26c1 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Layer.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Layer.cxx @@ -13,9 +13,9 @@ /// \author Mario Sitta <sitta@to.infn.it> /// \author Chinorat Kobdaj (kobdaj@g.sut.ac.th) -#include "ITS4Simulation/V3Layer.h" -#include "ITS4Base/GeometryTGeo.h" -#include "ITS4Simulation/Detector.h" +#include "TRKSimulation/V3Layer.h" +#include "TRKBase/GeometryTGeo.h" +#include "TRKSimulation/Detector.h" #include "ITSMFTSimulation/AlpideChip.h" #include "ITSMFTBase/SegmentationAlpide.h" @@ -40,7 +40,7 @@ class TGeoMedium; using namespace TMath; -using namespace o2::its4; +using namespace o2::trk; using namespace o2::itsmft; using AlpideChip = o2::itsmft::AlpideChip; @@ -267,7 +267,7 @@ V3Layer::V3Layer() mNumberOfChips(0), mChipTypeID(0), mIsTurbo(0), - mIsITS4(0), + mIsTRK(0), mBuildLevel(0), mStaveModel(Detector::kIBModelDummy), mAddGammaConv(kFALSE), @@ -296,7 +296,7 @@ V3Layer::V3Layer(Int_t lay, Bool_t turbo, Int_t debug) mNumberOfChips(0), mChipTypeID(0), mIsTurbo(turbo), - mIsITS4(0), + mIsTRK(0), mBuildLevel(0), mStaveModel(Detector::kIBModelDummy), mAddGammaConv(kFALSE), @@ -323,7 +323,7 @@ void V3Layer::createLayer(TGeoVolume* motherVolume) if (mLayerRadius <= 0) { LOG(FATAL) << "Wrong layer radius " << mLayerRadius; } - /* // These checks would fail with new ITS4 geo, let's trust the user here :) + /* // These checks would fail with new TRK geo, let's trust the user here :) if (mNumberOfStaves <= 0) { LOG(FATAL) << "Wrong number of staves " << mNumberOfStaves; } @@ -354,9 +354,9 @@ void V3Layer::createLayer(TGeoVolume* motherVolume) return; } - // If a new ITS4 layer is requested, do it and exit - if (mIsITS4) { - createITS4Layer(motherVolume); + // If a new TRK layer is requested, do it and exit + if (mIsTRK) { + createTRKLayer(motherVolume); return; } @@ -365,7 +365,7 @@ void V3Layer::createLayer(TGeoVolume* motherVolume) // mStaveWidth = mLayerRadius*Tan(alpha); - snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + snprintf(volumeName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSLayerPattern(), mLayerNumber); TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); layerVolume->SetUniqueID(mChipTypeID); @@ -410,7 +410,7 @@ void V3Layer::createLayerTurbo(TGeoVolume* motherVolume) LOG(WARNING) << "Stave tilt angle (" << mStaveTilt << ") greater than 45deg"; } - snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + snprintf(volumeName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSLayerPattern(), mLayerNumber); TGeoVolume* layerVolume = new TGeoVolumeAssembly(volumeName); layerVolume->SetUniqueID(mChipTypeID); layerVolume->SetVisibility(kTRUE); @@ -436,7 +436,7 @@ void V3Layer::createLayerTurbo(TGeoVolume* motherVolume) return; } -void V3Layer::createITS4Layer(TGeoVolume* motherVolume, const TGeoManager* mgr) +void V3Layer::createTRKLayer(TGeoVolume* motherVolume, const TGeoManager* mgr) { Double_t rmin = mLayerRadius; @@ -446,12 +446,12 @@ void V3Layer::createITS4Layer(TGeoVolume* motherVolume, const TGeoManager* mgr) char chipName[nameLen], sensName[nameLen], moduleName[nameLen], hsName[nameLen], staveName[nameLen], layerName[nameLen]; - snprintf(sensName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); - snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); - snprintf(moduleName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); - snprintf(hsName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); - snprintf(staveName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); - snprintf(layerName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSLayerPattern(), mLayerNumber); + snprintf(sensName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + snprintf(chipName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSChipPattern(), mLayerNumber); + snprintf(moduleName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSModulePattern(), mLayerNumber); + snprintf(hsName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(staveName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); + snprintf(layerName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSLayerPattern(), mLayerNumber); TGeoTube* sensor = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); TGeoTube* chip = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); @@ -460,8 +460,8 @@ void V3Layer::createITS4Layer(TGeoVolume* motherVolume, const TGeoManager* mgr) TGeoTube* stave = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); TGeoTube* layer = new TGeoTube(rmin, rmax, mIBModuleZLength / 2); - TGeoMedium* medSi = mgr->GetMedium("IT4_SI$"); - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medSi = mgr->GetMedium("TRK_SI$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi); TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medAir); @@ -529,7 +529,7 @@ TGeoVolume* V3Layer::createStave(const TGeoManager* /*mgr*/) alpha = (360. / (2 * mNumberOfStaves)) * DegToRad(); // The stave - snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); + snprintf(volumeName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); TGeoVolume* staveVol = new TGeoVolumeAssembly(volumeName); staveVol->SetVisibility(kTRUE); staveVol->SetLineColor(2); @@ -597,9 +597,9 @@ TGeoVolume* V3Layer::createStaveInnerB(const TGeoManager* mgr) TGeoBBox* hstave = new TGeoBBox(xmod, ymod, zmod); - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); - snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(volumeName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); TGeoVolume* hstaveVol = new TGeoVolume(volumeName, hstave, medAir); // Finally build it up @@ -626,8 +626,8 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) } // First create the single chip - snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); - snprintf(sensName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + snprintf(chipName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSChipPattern(), mLayerNumber); + snprintf(sensName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSSensorPattern(), mLayerNumber); ymod = 0.5 * mChipThickness; @@ -661,11 +661,11 @@ TGeoVolume* V3Layer::createModuleInnerB(const TGeoManager* mgr) TGeoBBox* module = new TGeoBBox(xtot, ytot, ztot); // Now the volumes - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE_IBFPC$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE_IBFPC$"); - snprintf(volumeName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + snprintf(volumeName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSModulePattern(), mLayerNumber); TGeoVolume* modVol = new TGeoVolume(volumeName, module, medAir); TGeoVolume* glueVol = new TGeoVolume("FPCGlue", glue, medGlue); @@ -763,7 +763,7 @@ void V3Layer::createIBCapacitors(TGeoVolume* modvol, Double_t zchip, Double_t yz if (!capacitor) { TGeoBBox* capsh = new TGeoBBox(sIBFlexCapacitorXWid / 2, sIBFlexCapacitorYHi / 2, sIBFlexCapacitorZLen / 2); - TGeoMedium* medCeramic = mgr->GetMedium("IT4_CERAMIC$"); + TGeoMedium* medCeramic = mgr->GetMedium("TRK_CERAMIC$"); capacitor = new TGeoVolume("IBFPCCapacitor", capsh, medCeramic); capacitor->SetLineColor(kBlack); @@ -864,8 +864,8 @@ TGeoVolume* V3Layer::createIBFPCAlGnd(const Double_t xcable, const Double_t zcab TGeoBBox* aluminum = new TGeoBBox(xcable, sIBFlexCableAlThick / 2, zcable); // Then the volumes - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medAluminum = mgr->GetMedium("TRK_ALUMINUM$"); TGeoVolume* coverlayVol = new TGeoVolume("FPCCoverlayGround", coverlay, medKapton); coverlayVol->SetLineColor(kBlue); @@ -916,8 +916,8 @@ TGeoVolume* V3Layer::createIBFPCAlAnode(const Double_t xcable, const Double_t zc aluminum->DefineSection(1, sIBFlexCableAlThick / 2); // Then the volumes - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medAluminum = mgr->GetMedium("TRK_ALUMINUM$"); TGeoVolume* coverlayVol = new TGeoVolume("FPCCoverlayAnode", coverlay, medKapton); coverlayVol->SetLineColor(kBlue); @@ -1145,19 +1145,19 @@ TGeoVolume* V3Layer::createStaveModelInnerB4(const TGeoManager* mgr) // We have all shapes: now create the real volumes - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); - TGeoMedium* medM55J6K = mgr->GetMedium("IT4_M55J6K$"); - TGeoMedium* medM60J3K = mgr->GetMedium("IT4_M60J3K$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medK13D2U2k = mgr->GetMedium("IT4_K13D2U2k$"); - TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); - TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); + TGeoMedium* medM55J6K = mgr->GetMedium("TRK_M55J6K$"); + TGeoMedium* medM60J3K = mgr->GetMedium("TRK_M60J3K$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medK13D2U2k = mgr->GetMedium("TRK_K13D2U2k$"); + TGeoMedium* medFGS003 = mgr->GetMedium("TRK_FGS003$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("TRK_CarbonFleece$"); const Int_t nameLen = 30; char volname[nameLen]; - snprintf(volname, nameLen, "%s%d_StaveStruct", o2::its4::GeometryTGeo::getITSStavePattern(), mLayerNumber); + snprintf(volname, nameLen, "%s%d_StaveStruct", o2::trk::GeometryTGeo::getITSStavePattern(), mLayerNumber); TGeoVolume* mechStavVol = new TGeoVolume(volname, mechStavSh, medAir); mechStavVol->SetLineColor(12); mechStavVol->SetFillColor(12); @@ -1396,9 +1396,9 @@ void V3Layer::createIBConnectorsASide(const TGeoManager* mgr) Double_t xpos, ypos, zpos; // Gather all material pointers - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); - TGeoMedium* medInox304 = mgr->GetMedium("IT4_INOX304$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("TRK_PEEKCF30$"); + TGeoMedium* medInox304 = mgr->GetMedium("TRK_INOX304$"); // First create all elements // (All measures refer to the blueprint ALIITSUP0051) @@ -1613,8 +1613,8 @@ void V3Layer::createIBConnectorsCSide(const TGeoManager* mgr) Double_t xpos, ypos, zpos; // Gather all material pointers - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("TRK_PEEKCF30$"); // First create all elements // (All measures refer to the blueprint ALIITSUP0051) @@ -2032,14 +2032,14 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) // We have all shapes: now create the real volumes - TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); - TGeoMedium* medK13D2U120 = mgr->GetMedium("IT4_K13D2U120$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medWater = mgr->GetMedium("IT4_WATER$"); - TGeoMedium* medCarbonFleece = mgr->GetMedium("IT4_CarbonFleece$"); - TGeoMedium* medFGS003 = mgr->GetMedium("IT4_FGS003$"); // amec thermasol - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medTungsten = mgr->GetMedium("IT4_TUNGSTEN$"); + TGeoMedium* medAluminum = mgr->GetMedium("TRK_ALUMINUM$"); + TGeoMedium* medK13D2U120 = mgr->GetMedium("TRK_K13D2U120$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medWater = mgr->GetMedium("TRK_WATER$"); + TGeoMedium* medCarbonFleece = mgr->GetMedium("TRK_CarbonFleece$"); + TGeoMedium* medFGS003 = mgr->GetMedium("TRK_FGS003$"); // amec thermasol + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medTungsten = mgr->GetMedium("TRK_TUNGSTEN$"); TGeoVolume* coldPlateVol = new TGeoVolume("ColdPlateVol", coldPlate, medK13D2U120); coldPlateVol->SetLineColor(kYellow - 3); @@ -2110,7 +2110,7 @@ TGeoVolume* V3Layer::createStaveModelOuterB2(const TGeoManager* mgr) gammaConvRodVol->SetFillStyle(4000); // 0% transparent } - snprintf(volname, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); + snprintf(volname, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSHalfStavePattern(), mLayerNumber); TGeoVolume* halfStaveVol = new TGeoVolume(volname, halfStave, medAir); // halfStaveVol->SetLineColor(12); // halfStaveVol->SetFillColor(12); @@ -2273,9 +2273,9 @@ TGeoVolume* V3Layer::createOBPowerBiasBuses(const Double_t zcable, const TGeoMan TGeoBBox* topBB = new TGeoBBox(xcable, sOBBiasBusAlThick / 2, zcable); // Then the volumes - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medAluminum = mgr->GetMedium("IT4_ALUMINUM$"); - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medAluminum = mgr->GetMedium("TRK_ALUMINUM$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); TGeoVolume* gndPBVol = new TGeoVolume("PowerBusGround", gndPB, medAluminum); gndPBVol->SetLineColor(kCyan); @@ -2426,9 +2426,9 @@ void V3Layer::createOBColdPlateConnectorsASide() Double_t xpos, ypos, zpos; // Gather all material pointers - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); - TGeoMedium* medInox304 = mgr->GetMedium("IT4_INOX304$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("TRK_PEEKCF30$"); + TGeoMedium* medInox304 = mgr->GetMedium("TRK_INOX304$"); // First create all elements @@ -2583,8 +2583,8 @@ void V3Layer::createOBColdPlateConnectorsCSide() Double_t xpos, ypos, zpos; // Gather all material pointers - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medPEEK = mgr->GetMedium("TRK_PEEKCF30$"); // First create all elements @@ -2767,7 +2767,7 @@ TGeoVolume* V3Layer::createSpaceFrameOuterB2(const TGeoManager* mgr) // Updated: 20 Jul 2017 Mario Sitta O2 version // - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); TGeoVolume *unitVol[2], *next2EndVol[2], *endVol[2]; Double_t *xtru, *ytru; @@ -2892,9 +2892,9 @@ void V3Layer::createOBSpaceFrameObjects(const TGeoManager* mgr) // // Materials defined in AliITSUv2 - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); - TGeoMedium* medF6151B05M = mgr->GetMedium("IT4_F6151B05M$"); - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); + TGeoMedium* medF6151B05M = mgr->GetMedium("TRK_F6151B05M$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); // Local parameters Double_t halfFrameWidth = sOBSpaceFrameWidth / 2; @@ -3333,7 +3333,7 @@ void V3Layer::createOBSpaceFrameConnector(TGeoVolume* mother, const Double_t ymo // Created: 09 Sep 2019 M. Sitta // Materials defined in AliITSUv2 - TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + TGeoMedium* medPEEK = mgr->GetMedium("TRK_PEEKCF30$"); // Local parameters TString connName, compoShape; @@ -3489,8 +3489,8 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) } // The chip (the same as for IB) - snprintf(chipName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSChipPattern(), mLayerNumber); - snprintf(sensName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSSensorPattern(), mLayerNumber); + snprintf(chipName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSChipPattern(), mLayerNumber); + snprintf(sensName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSSensorPattern(), mLayerNumber); ylen = 0.5 * sOBChipThickness; @@ -3530,9 +3530,9 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) // We have all shapes: now create the real volumes - TGeoMedium* medAir = mgr->GetMedium("IT4_AIR$"); - TGeoMedium* medGlue = mgr->GetMedium("IT4_GLUE$"); - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); + TGeoMedium* medAir = mgr->GetMedium("TRK_AIR$"); + TGeoMedium* medGlue = mgr->GetMedium("TRK_GLUE$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); TGeoVolume* glueFPCVol = new TGeoVolume("GlueFPCVol", glueFPC, medGlue); glueFPCVol->SetLineColor(kBlack); @@ -3549,7 +3549,7 @@ TGeoVolume* V3Layer::createModuleOuterB(const TGeoManager* mgr) flexKapVol->SetFillColor(flexKapVol->GetLineColor()); flexKapVol->SetFillStyle(4000); // 0% transparent - snprintf(volName, nameLen, "%s%d", o2::its4::GeometryTGeo::getITSModulePattern(), mLayerNumber); + snprintf(volName, nameLen, "%s%d", o2::trk::GeometryTGeo::getITSModulePattern(), mLayerNumber); TGeoVolume* modVol = new TGeoVolume(volName, module, medAir); modVol->SetVisibility(kTRUE); @@ -3629,8 +3629,8 @@ TGeoVolume* V3Layer::createOBFPCCuGnd(const Double_t zcable, const TGeoManager* TGeoBBox* copper = new TGeoBBox(xcable, sOBFPCCopperThick / 2, zcable); // Then the volumes - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medCopper = mgr->GetMedium("IT4_COPPER$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medCopper = mgr->GetMedium("TRK_COPPER$"); TGeoVolume* soldmaskVol = new TGeoVolume("FPCGndSolderMask", soldmask, medKapton); soldmaskVol->SetLineColor(kBlue); @@ -3675,8 +3675,8 @@ TGeoVolume* V3Layer::createOBFPCCuSig(const Double_t zcable, const TGeoManager* TGeoBBox* copper = new TGeoBBox(xcable, sOBFPCCopperThick / 2, zcable); // Then the volumes - TGeoMedium* medKapton = mgr->GetMedium("IT4_KAPTON(POLYCH2)$"); - TGeoMedium* medCopper = mgr->GetMedium("IT4_COPPER$"); + TGeoMedium* medKapton = mgr->GetMedium("TRK_KAPTON(POLYCH2)$"); + TGeoMedium* medCopper = mgr->GetMedium("TRK_COPPER$"); TGeoVolume* soldmaskVol = new TGeoVolume("FPCSigSolderMask", soldmask, medKapton); soldmaskVol->SetLineColor(kBlue); diff --git a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Services.cxx similarity index 98% rename from Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx rename to Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Services.cxx index ae775db4f3b96..f7e3362298098 100644 --- a/Detectors/Upgrades/PostLS4/IT4/simulation/src/V3Services.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Services.cxx @@ -13,10 +13,10 @@ /// \author Mario Sitta <sitta@to.infn.it> /// \author Parinya Namwongsa <parinya.namwongsa@cern.ch> -#include "ITS4Simulation/V3Services.h" -#include "ITS4Simulation/V11Geometry.h" -#include "ITS4Base/GeometryTGeo.h" -#include "ITS4Simulation/Detector.h" +#include "TRKSimulation/V3Services.h" +#include "TRKSimulation/V11Geometry.h" +#include "TRKBase/GeometryTGeo.h" +#include "TRKSimulation/Detector.h" #include "ITSMFTSimulation/AlpideChip.h" #include "FairLogger.h" // for LOG @@ -40,7 +40,7 @@ class TGeoMedium; using namespace TMath; -using namespace o2::its4; +using namespace o2::trk; // Parameters const Double_t V3Services::sIBWheelACZdist = 306.0 * sMm; @@ -494,8 +494,8 @@ void V3Services::ibEndWheelSideA(const Int_t iLay, TGeoVolume* endWheel, const T TGeoCompositeShape* stepASh = new TGeoCompositeShape(Form("stepBoxASh%d:stepBoxATr%d-stepPconASh%d", iLay, iLay, iLay)); // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED - TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED + TGeoMedium* medPEEK = mgr->GetMedium("TRK_PEEKCF30$"); TGeoVolume* coneABasisVol = new TGeoVolume(Form("ConeABasis%d", iLay), coneABasisSh, medCarbon); coneABasisVol->SetFillColor(kBlue); @@ -536,7 +536,7 @@ void V3Services::ibEndWheelSideA(const Int_t iLay, TGeoVolume* endWheel, const T // The position of the Steps is given wrt the holes (see eg. ALIITSUP0187) dphi = 180. - sConeAStepHolePhi0[iLay]; - Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(iLay); + Int_t numberOfStaves = o2::trk::GeometryTGeo::Instance()->getNumberOfStaves(iLay); zpos = zref + (static_cast<TGeoBBox*>(stepAVol->GetShape()))->GetDZ(); for (Int_t j = 0; j < numberOfStaves; j++) { Double_t phi = dphi + j * sConeAStepHolePhi[iLay]; @@ -724,8 +724,8 @@ void V3Services::ibEndWheelSideC(const Int_t iLay, TGeoVolume* endWheel, const T TGeoCompositeShape* stepCSh = new TGeoCompositeShape(Form("stepBoxCSh%d:stepBoxCTr%d-stepPconCSh%d", iLay, iLay, iLay)); // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED - TGeoMedium* medPEEK = mgr->GetMedium("IT4_PEEKCF30$"); + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED + TGeoMedium* medPEEK = mgr->GetMedium("TRK_PEEKCF30$"); TGeoVolume* endWheelCVol = new TGeoVolume(Form("EndWheelCBasis%d", iLay), endWheelCSh, medCarbon); endWheelCVol->SetFillColor(kBlue); @@ -742,7 +742,7 @@ void V3Services::ibEndWheelSideC(const Int_t iLay, TGeoVolume* endWheel, const T // The position of the Steps is given wrt the holes (see eg. ALIITSUP0187) dphi = sEndWCStepHolePhi0[iLay]; - Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(iLay); + Int_t numberOfStaves = o2::trk::GeometryTGeo::Instance()->getNumberOfStaves(iLay); zpos += (static_cast<TGeoBBox*>(stepCVol->GetShape()))->GetDZ(); for (Int_t j = 0; j < numberOfStaves; j++) { Double_t phi = dphi + j * sEndWCStepHolePhi[iLay]; @@ -860,8 +860,8 @@ TGeoVolume* V3Services::ibCyssCylinder(const TGeoManager* mgr) TGeoTubeSeg* cyssInnerCylSh = new TGeoTubeSeg(rmin, rmax, zlen, phimin, phimax); // We have all shapes: now create the real volumes - TGeoMedium* medPrepreg = mgr->GetMedium("IT4_F6151B05M$"); - TGeoMedium* medRohacell = mgr->GetMedium("IT4_ROHACELL$"); + TGeoMedium* medPrepreg = mgr->GetMedium("TRK_F6151B05M$"); + TGeoMedium* medRohacell = mgr->GetMedium("TRK_ROHACELL$"); TGeoVolume* cyssOuterCylVol = new TGeoVolume("IBCYSSCylinder", cyssOuterCylSh, medPrepreg); cyssOuterCylVol->SetLineColor(35); @@ -982,8 +982,8 @@ TGeoVolume* V3Services::ibCyssCone(const TGeoManager* mgr) cyssConeFoamSh->DefineSection(4, zlen1, rmin, rmax); // We have all shapes: now create the real volumes - TGeoMedium* medPrepreg = mgr->GetMedium("IT4_F6151B05M$"); - TGeoMedium* medRohacell = mgr->GetMedium("IT4_ROHACELL$"); + TGeoMedium* medPrepreg = mgr->GetMedium("TRK_F6151B05M$"); + TGeoMedium* medRohacell = mgr->GetMedium("TRK_ROHACELL$"); TGeoVolume* cyssConeVol = new TGeoVolume("IBCYSSCone", cyssConeSh, medPrepreg); cyssConeVol->SetLineColor(35); @@ -1197,7 +1197,7 @@ TGeoVolume* V3Services::ibCyssFlangeSideA(const TGeoManager* mgr) TGeoCompositeShape* cyssFlangeASh = new TGeoCompositeShape(cyssFlangeAComposite.Data()); // We have all shapes: now create the real volumes - TGeoMedium* medAlu = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medAlu = mgr->GetMedium("TRK_ALUMINUM$"); TGeoVolume* cyssFlangeAVol = new TGeoVolume("IBCYSSFlangeA", cyssFlangeASh, medAlu); cyssFlangeAVol->SetLineColor(kCyan); @@ -1514,7 +1514,7 @@ TGeoVolume* V3Services::ibCyssFlangeSideC(const TGeoManager* mgr) TGeoCompositeShape* cyssFlangeCSh = new TGeoCompositeShape(cyssFlangeCComposite.Data()); // We have all shapes: now create the real volumes - TGeoMedium* medAlu = mgr->GetMedium("IT4_ALUMINUM$"); + TGeoMedium* medAlu = mgr->GetMedium("TRK_ALUMINUM$"); TGeoVolume* cyssFlangeCVol = new TGeoVolume("IBCYSSFlangeC", cyssFlangeCSh, medAlu); cyssFlangeCVol->SetLineColor(kCyan); @@ -1592,7 +1592,7 @@ void V3Services::obEndWheelSideA(const Int_t iLay, TGeoVolume* mother, const TGe TGeoBBox* shelfSh = new TGeoBBox(xlen / 2, ylen / 2, zlen / 2); // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED Int_t nLay = iLay + sNumberInnerLayers; @@ -1636,7 +1636,7 @@ void V3Services::obEndWheelSideA(const Int_t iLay, TGeoVolume* mother, const TGe mother->AddNode(ringInnerVol, 1, new TGeoTranslation(0, 0, zpos)); // Then the support blocks - Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(nLay); + Int_t numberOfStaves = o2::trk::GeometryTGeo::Instance()->getNumberOfStaves(nLay); Double_t alpha = 360. / numberOfStaves; rmin = sOBWheelShelfRpos[iLay] + shelfSh->GetDY(); @@ -1756,7 +1756,7 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe TGeoBBox* shelfSh = new TGeoBBox(xlen / 2, ylen / 2, zlen / 2); // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED Int_t nLay = iLay + sNumberInnerLayers; @@ -1798,7 +1798,7 @@ void V3Services::mbEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe mother->AddNode(ringOuterVol, 1, new TGeoTranslation(0, 0, -zpos)); // Then the support blocks - Int_t numberOfStaves = o2::its4::GeometryTGeo::Instance()->getNumberOfStaves(nLay); + Int_t numberOfStaves = o2::trk::GeometryTGeo::Instance()->getNumberOfStaves(nLay); Double_t alpha = 360. / numberOfStaves; rmin = sOBWheelShelfRpos[iLay] + shelfSh->GetDY(); @@ -1923,7 +1923,7 @@ void V3Services::obEndWheelSideC(const Int_t iLay, TGeoVolume* mother, const TGe } // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED Int_t nLay = iLay + sNumberInnerLayers + sNumberMiddlLayers; @@ -2063,7 +2063,7 @@ void V3Services::obConeSideA(TGeoVolume* mother, const TGeoManager* mgr) obConeRibSh->DefineSection(1, sOBConeAThickAll); // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED TGeoVolume* obConeVol = new TGeoVolume("OBConeSideA", obConeSh, medCarbon); obConeVol->SetFillColor(kBlue); @@ -2161,7 +2161,7 @@ void V3Services::obConeTraysSideA(TGeoVolume* mother, const TGeoManager* mgr) } // for (j = 0,1) // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED TGeoVolume *obTrayVol[2], *obTrayRibVol[2]; @@ -2315,7 +2315,7 @@ void V3Services::obConeSideC(TGeoVolume* mother, const TGeoManager* mgr) obConeRibSh->DefineSection(1, sOBConeCThickAll); // We have all shapes: now create the real volumes - TGeoMedium* medCarbon = mgr->GetMedium("IT4_M55J6K$"); // TO BE CHECKED + TGeoMedium* medCarbon = mgr->GetMedium("TRK_M55J6K$"); // TO BE CHECKED TGeoVolume* obConeVol = new TGeoVolume("OBConeSideC", obConeSh, medCarbon); obConeVol->SetFillColor(kBlue); diff --git a/Detectors/Upgrades/CMakeLists.txt b/Detectors/Upgrades/CMakeLists.txt index dd42de06dfdbf..c87ff88e6997f 100644 --- a/Detectors/Upgrades/CMakeLists.txt +++ b/Detectors/Upgrades/CMakeLists.txt @@ -10,4 +10,4 @@ message(STATUS "Building detectors for upgrades") add_subdirectory(IT3) -add_subdirectory(PostLS4) \ No newline at end of file +add_subdirectory(ALICE3) \ No newline at end of file diff --git a/Detectors/Upgrades/README.md b/Detectors/Upgrades/README.md index ecead5da1a376..7e31340e67998 100644 --- a/Detectors/Upgrades/README.md +++ b/Detectors/Upgrades/README.md @@ -5,15 +5,17 @@ # Upgrades This is a top page for detectors not included in Run 3 layout. -# Installation -To enable the compilation of this section it is required to prepend the `ENABLE_UPGRADES=ON` to the installation command, for instance: +# Installation +To enable the compilation of this section you need to have the environment variable `ENABLE_UPGRADES=ON` set. +An example for the installation command is: ```bash ENABLE_UPGRADES=ON aliBuild build O2 --defaults o2 ``` +Currently two sections are included: <!-- doxy * \subpage refDetectorsUpgradesIT3 -* \subpage refDetectorsUpgradesPostLS4IT4 +* \subpage refDetectorsUpgradesALICE3TRK /doxy --> diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index 2a7d5c91295dc..f159d724cbb4e 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -115,7 +115,7 @@ if (ENABLE_UPGRADES) O2::TPCSimulation O2::ITSSimulation O2::ITS3Simulation - O2::ITS4Simulation + O2::TRKSimulation O2::MFTSimulation O2::MCHSimulation O2::MIDSimulation diff --git a/macro/build_geometry.C b/macro/build_geometry.C index 8e24bfb5853ee..aaef25e3168a3 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -47,7 +47,7 @@ #ifdef ENABLE_UPGRADES #include <ITS3Simulation/Detector.h> -#include <ITS4Simulation/Detector.h> +#include <TRKSimulation/Detector.h> #endif void finalize_geometry(FairRunSim* run); @@ -127,7 +127,7 @@ void build_geometry(FairRunSim* run = nullptr) // beam pipe if (isActivated("PIPE")) { #ifdef ENABLE_UPGRADES - if (isActivated("IT3") || isActivated("IT4")) { + if (isActivated("IT3") || isActivated("TRK")) { run->AddModule(new o2::passive::Pipe("PIPE", "Beam pipe", 1.6f, 0.05)); } else { run->AddModule(new o2::passive::Pipe("PIPE", "Beam pipe")); @@ -180,10 +180,10 @@ void build_geometry(FairRunSim* run = nullptr) run->AddModule(its3); } - if (isActivated("IT4")) { - // ITS4 - auto its4 = new o2::its4::Detector(true); - run->AddModule(its4); + if (isActivated("TRK")) { + // ALICE 3 TRK + auto trk = new o2::trk::Detector(true); + run->AddModule(trk); } #endif diff --git a/macro/run_trac_alice3.C b/macro/run_trac_alice3.C index 1e2df0a2d3f28..ca5fea1be42bb 100644 --- a/macro/run_trac_alice3.C +++ b/macro/run_trac_alice3.C @@ -51,7 +51,7 @@ float getDetLengthFromEta(const float eta, const float radius) return 10. * (10. + radius * std::cos(2 * std::atan(std::exp(-eta)))); } -void run_trac_alice3(const string hitsFileName = "o2sim_HitsIT4.root") +void run_trac_alice3(const string hitsFileName = "o2sim_HitsTRK.root") { TChain mcTree("o2sim"); @@ -72,7 +72,7 @@ void run_trac_alice3(const string hitsFileName = "o2sim_HitsIT4.root") std::uint32_t roFrame; std::vector<Hit>* hits = nullptr; - itsHits.SetBranchAddress("IT4Hit", &hits); + itsHits.SetBranchAddress("TRKHit", &hits); std::vector<TrackingParameters> trackParams(4); trackParams[0].NLayers = 10; diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index f1e0bfadcaa14..82ff45288bdd6 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -26,7 +26,7 @@ target_link_libraries(allsim O2::HMPIDSimulation O2::ITSSimulation O2::ITS3Simulation - O2::ITS4Simulation + O2::TRKSimulation O2::MCHBase O2::MCHSimulation O2::MFTSimulation diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 36ddc26c5ff24..adc652bf03dc2 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -65,7 +65,7 @@ #ifdef ENABLE_UPGRADES #include <ITS3Simulation/Detector.h> -#include <ITS4Simulation/Detector.h> +#include <TRKSimulation/Detector.h> #endif namespace o2 @@ -742,8 +742,8 @@ void O2HitMerger::initDetInstances() mDetectorInstances[i] = std::move(std::make_unique<o2::its3::Detector>(true)); counter++; } - if (i == DetID::IT4) { - mDetectorInstances[i] = std::move(std::make_unique<o2::its4::Detector>(true)); + if (i == DetID::TRK) { + mDetectorInstances[i] = std::move(std::make_unique<o2::trk::Detector>(true)); counter++; } #endif From a4a49728f4d45decacce1b14cd8129a5bd747844 Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Fri, 11 Dec 2020 06:02:22 -0300 Subject: [PATCH 1594/1751] Change to new TPCrefit check: finders (#5042) * Change to new TPCrefit check: finders * Fix binning typo --- Analysis/Tasks/PWGLF/cascadefinder.cxx | 4 ++-- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 4 ++-- Analysis/Tasks/multiplicityQa.cxx | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Analysis/Tasks/PWGLF/cascadefinder.cxx b/Analysis/Tasks/PWGLF/cascadefinder.cxx index 6b23254efb01a..150aa0780ac0d 100644 --- a/Analysis/Tasks/PWGLF/cascadefinder.cxx +++ b/Analysis/Tasks/PWGLF/cascadefinder.cxx @@ -120,7 +120,7 @@ struct cascadeprefilter { aod::V0DataExt const& V0s) { for (auto& t0 : goodPosTracks) { - if (!(t0.flags() & 0x40)) { + if (!(t0.trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } if (t0.tpcNClsCrossedRows() < mincrossedrows) { @@ -129,7 +129,7 @@ struct cascadeprefilter { cascGoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); } for (auto& t0 : goodNegTracks) { - if (!(t0.flags() & 0x40)) { + if (!(t0.trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } if (t0.tpcNClsCrossedRows() < mincrossedrows) { diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index ffc5cd1f14f5f..00ab268fd1828 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -93,7 +93,7 @@ struct lambdakzeroprefilter { soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { for (auto& t0 : goodPosTracks) { - if (!(t0.flags() & 0x40)) { + if (!(t0.trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } if (t0.tpcNClsCrossedRows() < mincrossedrows) { @@ -102,7 +102,7 @@ struct lambdakzeroprefilter { v0GoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); } for (auto& t0 : goodNegTracks) { - if (!(t0.flags() & 0x40)) { + if (!(t0.trackType() & o2::aod::track::TPCrefit)) { continue; //TPC refit } if (t0.tpcNClsCrossedRows() < mincrossedrows) { diff --git a/Analysis/Tasks/multiplicityQa.cxx b/Analysis/Tasks/multiplicityQa.cxx index ecffbf3077d8e..9a305a7443906 100644 --- a/Analysis/Tasks/multiplicityQa.cxx +++ b/Analysis/Tasks/multiplicityQa.cxx @@ -35,10 +35,10 @@ struct MultiplicityQaTask { OutputObj<TH2F> hMultV0MvsT0M{TH2F("hMultV0MvsT0M", ";V0M;T0M", 200, 0., 50000., 200, 0., 200000.)}; //For vertex-Z corrections - OutputObj<TProfile> hVtxProfV0M{TProfile("hVtxProfV0M", "", 600, 0., 240000.)}; - OutputObj<TProfile> hVtxProfT0M{TProfile("hVtxProfT0M", "", 10000, 0., 200000.)}; - OutputObj<TProfile> hVtxProfZNA{TProfile("hVtxProfZNA", "", 600, 0., 240000.)}; - OutputObj<TProfile> hVtxProfZNC{TProfile("hVtxProfZNC", "", 600, 0., 240000.)}; + OutputObj<TProfile> hVtxProfV0M{TProfile("hVtxProfV0M", "", 150, -15, 15)}; + OutputObj<TProfile> hVtxProfT0M{TProfile("hVtxProfT0M", "", 150, -15, 15)}; + OutputObj<TProfile> hVtxProfZNA{TProfile("hVtxProfZNA", "", 150, -15, 15)}; + OutputObj<TProfile> hVtxProfZNC{TProfile("hVtxProfZNC", "", 150, -15, 15)}; OutputObj<TProfile> hMultNtrackletsVsV0M{TProfile("hMultNtrackletsVsV0M", "", 50000, 0., 50000.)}; From 2f5d1a2222315bba9cb7304fbe9ada6e057d8e56 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Fri, 11 Dec 2020 10:04:28 +0100 Subject: [PATCH 1595/1751] Squashed commit of the following: (#5039) commit 5f95221e7172916cd67cd3d568440ca4bf09b3ec Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Dec 9 16:11:44 2020 +0100 added the composite cut list in the constructor initializer list commit 1fe24d5b8d140f42d83565df17c0a751ddb0dacd Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Dec 9 12:42:33 2020 +0100 clang fixes commit f70f65cc95c715b160687828cad94a7c9a5cd9b5 Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Dec 9 12:41:56 2020 +0100 clang fixes commit 3d13ecee9a83598cc3dd37a5e7e65d4030c96039 Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Dec 9 12:38:07 2020 +0100 Bug fix to allow nested composite cuts (composite cuts of composite cuts); remove duplicate histogram classes from table-reader commit 592862f9e21e156b62f4616f00b98523e04eb155 Merge: 453d9e2cd7 8fbf7d0ad0 Author: Ionut Arsene <iarsene@cern.ch> Date: Tue Dec 8 21:49:51 2020 +0100 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit 453d9e2cd7871b1e9231dd7bf55378393723a15a Merge: f74387c19a da6a51f557 Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Dec 2 10:58:07 2020 +0100 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit f74387c19a20ab7dfa23d7c19d032687aec188e5 Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Nov 25 10:40:04 2020 +0100 checkcode fix commit e4e9c6e13374a33034e3627a37635f5e95f6de7e Author: Ionut Arsene <iarsene@cern.ch> Date: Tue Nov 24 11:05:20 2020 +0100 clang fixes commit 6bbb54b35a359b38a5991186336b0f03ed705242 Author: Ionut Arsene <iarsene@cern.ch> Date: Tue Nov 24 11:01:04 2020 +0100 o2checkcode fixes (namespace naming) commit 513816f1422c7d8e1933d845ba30af2e9e689930 Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Nov 23 17:46:31 2020 +0100 Squashed commit of the following: commit b604a6b951b977e575da71961b2a443a97e0c11a Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Nov 23 17:43:30 2020 +0100 clang fixes commit 781746f8a8086e8ed5b77b925b873f690fe4de04 Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Nov 23 17:25:42 2020 +0100 Squashed commit of the following: commit 9dd23cef2ad9581f4ceec596df5dcb8f08a61e1d Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Nov 23 17:18:12 2020 +0100 First commit of the HistogramsLibrary; updates in various places to use the histogram library commit 937e1c5a973c2c25bbd62696cdd8d5c3c2922772 Merge: db3ae836ee 807d607a9b Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Nov 23 09:46:58 2020 +0100 Updated the call for FillPair() in dileptonMuMu task; solved conflicts Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dqEventFilter2 commit db3ae836eef72145b84c9d8d66a90b567e66bbfb Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Nov 23 09:37:49 2020 +0100 Added a workflow for pp events filtering; Added cuts library commit 338151a2d184891479974aeded726e754cf03517 Merge: 27a75b9b25 aec3bf51e2 Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Nov 23 17:23:04 2020 +0100 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit 27a75b9b254820c190e4bb36600477379960edbc Author: Ionut Arsene <iarsene@cern.ch> Date: Fri Nov 6 12:14:07 2020 +0100 clang fix commit ef8206aa8b18bbabb774964ef42f0cb97cf59b57 Author: Ionut Arsene <iarsene@cern.ch> Date: Fri Nov 6 11:55:56 2020 +0100 Optimizations and small fixes Squashed commit of the following: commit e0ac92b303c6c9dbf4ecadd04a0299d9db566a79 Author: Ionut Arsene <iarsene@cern.ch> Date: Fri Nov 6 11:11:31 2020 +0100 small fix for thr kIsSPDany variable commit 773b845c684d76717f61f5392c3be2567010e4ac Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Nov 5 16:16:59 2020 +0100 Call .reserve() for the muon tables commit 8c7981e7eb092a2f63848d5214f72a99840c1387 Merge: 8a0d37e09a d57067790d Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Nov 5 09:04:48 2020 +0100 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit 8a0d37e09ac8f615a5000a87667e600a36135bd5 Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Nov 5 09:03:45 2020 +0100 clang fixes commit 8eaaf21e08815080c91c428a51353e42b4c073d3 Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Nov 5 08:59:41 2020 +0100 track-selection decisions added to the skimmed track filtering tag commit eab1326d6ed4a5d9ac4dadeabaabf24c0c53cbab Merge: bf202e00f4 a8a9dabd10 Author: Ionut Arsene <iarsene@cern.ch> Date: Fri Oct 30 22:28:34 2020 +0100 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit bf202e00f4da6c419de5b263e04b3ff3a756e304 Author: Ionut Arsene <iarsene@cern.ch> Date: Fri Oct 30 22:13:22 2020 +0100 Partitions added in tableMaker and other optimizations commit 0644b00176c1be2c1a4729c9ca64ed9b8426c917 Merge: 233691d4e5 9b7f1f77a9 Author: Ionut Arsene <iarsene@cern.ch> Date: Tue Oct 20 12:21:23 2020 +0200 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit 233691d4e51d0a454a3f9b2a11e690c997f2da3d Merge: 967c061a93 341158b6c0 Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Oct 14 10:22:15 2020 +0200 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit 967c061a937d7d9e4c3611f9b8dc03166cde17ff Merge: df2aa4e2c9 b60b2ca6a8 Author: Ionut Arsene <iarsene@cern.ch> Date: Mon Oct 12 09:30:23 2020 +0200 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit df2aa4e2c92e93713d081bf324c87679d931af95 Merge: b0cd406ce0 baab712404 Author: Ionut Arsene <iarsene@cern.ch> Date: Fri Oct 9 15:41:33 2020 +0200 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit b0cd406ce03b7e614a19cefe7feaba95daa722c0 Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Oct 8 16:46:36 2020 +0200 removed temporarilly the dilepton-hadron analysis task from workflow commit 32985c20412690d784c6be341dafc8c03cdf440e Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Oct 8 15:39:43 2020 +0200 fixup! Several changes. More variables added in VarManager; TableMaker applies tighter selection track cuts; Output object for histograms changed to take the HistogramManager master histogram list instead of the manager itself. commit 182829a66914168c684ad2fc2259d676cd613f39 Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Oct 8 15:32:08 2020 +0200 Several changes. More variables added in VarManager; TableMaker applies tighter selection track cuts; Output object for histograms changed to take the HistogramManager master histogram list instead of the manager itself. commit 41958878d2a30057130745e35069b36b625a35fa Merge: ddcf87daa8 2a6805b8c6 Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Oct 8 13:18:19 2020 +0200 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit ddcf87daa8bca34e8cee9a93831b33161f5fd444 Merge: 6a637d5a08 d39deb018a Author: Ionut Arsene <iarsene@cern.ch> Date: Wed Oct 7 12:26:45 2020 +0200 Merge branch 'dev' of https://github.com/AliceO2Group/AliceO2 into dev commit 6a637d5a08c46ba7cec9ad8bd493e329177ecaa9 Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Sep 17 18:14:41 2020 +0200 clang commit e0a7d966375578c81909327cacbd20e044ad4aed Author: Ionut Arsene <iarsene@cern.ch> Date: Thu Sep 17 18:13:27 2020 +0200 removed tof and tpc pid response from table maker Co-authored-by: Ionut Arsene <iarsene@cern.ch> --- .../include/AnalysisCore/AnalysisCompositeCut.h | 14 +++++++++++--- Analysis/Core/src/AnalysisCompositeCut.cxx | 15 +++++++++++++-- Analysis/Tasks/PWGDQ/tableReader.cxx | 11 ----------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h b/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h index 96902e5fe9b72..cfa8a95543ed0 100644 --- a/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h +++ b/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h @@ -29,18 +29,26 @@ class AnalysisCompositeCut : public AnalysisCut AnalysisCompositeCut& operator=(const AnalysisCompositeCut& c) = default; ~AnalysisCompositeCut() override; - void AddCut(AnalysisCut* cut) { fCutList.push_back(*cut); }; + void AddCut(AnalysisCut* cut) + { + if (cut->IsA() == AnalysisCompositeCut::Class()) { + fCompositeCutList.push_back(*(AnalysisCompositeCut*)cut); + } else { + fCutList.push_back(*cut); + } + }; bool GetUseAND() const { return fOptionUseAND; } - int GetNCuts() const { return fCutList.size(); } + int GetNCuts() const { return fCutList.size() + fCompositeCutList.size(); } bool IsSelected(float* values) override; protected: bool fOptionUseAND; // true (default): apply AND on all cuts; false: use OR std::vector<AnalysisCut> fCutList; // list of cuts + std::vector<AnalysisCompositeCut> fCompositeCutList; // list of composite cuts - ClassDef(AnalysisCompositeCut, 1); + ClassDef(AnalysisCompositeCut, 2); }; #endif diff --git a/Analysis/Core/src/AnalysisCompositeCut.cxx b/Analysis/Core/src/AnalysisCompositeCut.cxx index fc05c54167884..af7268aec5d12 100644 --- a/Analysis/Core/src/AnalysisCompositeCut.cxx +++ b/Analysis/Core/src/AnalysisCompositeCut.cxx @@ -15,7 +15,8 @@ ClassImp(AnalysisCompositeCut) //____________________________________________________________________________ AnalysisCompositeCut::AnalysisCompositeCut(bool useAND) : AnalysisCut(), fOptionUseAND(useAND), - fCutList() + fCutList(), + fCompositeCutList() { // // default constructor @@ -25,7 +26,8 @@ ClassImp(AnalysisCompositeCut) //____________________________________________________________________________ AnalysisCompositeCut::AnalysisCompositeCut(const char* name, const char* title, bool useAND) : AnalysisCut(name, title), fOptionUseAND(useAND), - fCutList() + fCutList(), + fCompositeCutList() { // // named constructor @@ -50,6 +52,15 @@ bool AnalysisCompositeCut::IsSelected(float* values) } } + for (std::vector<AnalysisCompositeCut>::iterator it = fCompositeCutList.begin(); it < fCompositeCutList.end(); ++it) { + if (fOptionUseAND && !(*it).IsSelected(values)) { + return false; + } + if (!fOptionUseAND && (*it).IsSelected(values)) { + return true; + } + } + if (fOptionUseAND) { return true; } else { diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index e3b1899fc681f..5dec0d394c818 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -593,17 +593,6 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) histMan->AddHistogram(classStr.Data(), "Eta_Phi", "", false, 20, -1.0, 1.0, VarManager::kEta, 100, -8.0, 8.0, VarManager::kPhi); } - 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_Cent", "", false, 125, 0.0, 5.0, VarManager::kMass, 20, 0.0, 20.0, VarManager::kPt, 10, 0.0, 100.0, VarManager::kCentVZERO); From e6eb662bbb097c492762f67fb48a5720cee0c75f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 11 Dec 2020 10:04:40 +0100 Subject: [PATCH 1596/1751] DPL: allow customization of FairMQ channels from command line (#5048) This introduces: * --fairmq-send-buffer-size * --fairmq-recv-buffer-size * --fairmq-ipc-prefix to customize the associated fairmq channels options. Moreover it defaults --fairmq-rate-logging to 0. --- Framework/Core/CMakeLists.txt | 1 + .../ChannelConfigurationPolicyHelpers.h | 7 +- .../Core/include/Framework/ChannelSpec.h | 10 ++- .../Framework/WorkflowCustomizationHelpers.h | 25 +++++++ .../include/Framework/runDataProcessing.h | 35 ++-------- .../Core/src/ChannelConfigurationPolicy.cxx | 10 ++- .../src/ChannelConfigurationPolicyHelpers.cxx | 18 +++++ Framework/Core/src/ChannelSpecHelpers.cxx | 4 +- Framework/Core/src/DeviceSpecHelpers.cxx | 39 +++++------ .../Core/src/WorkflowCustomizationHelpers.cxx | 65 +++++++++++++++++++ Framework/Core/test/Mocking.h | 17 +---- 11 files changed, 157 insertions(+), 74 deletions(-) create mode 100644 Framework/Core/include/Framework/WorkflowCustomizationHelpers.h create mode 100644 Framework/Core/src/WorkflowCustomizationHelpers.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index fa4c2fc5fdc5a..06f5de71e4740 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -98,6 +98,7 @@ o2_add_library(Framework src/Task.cxx src/TextControlService.cxx src/Variant.cxx + src/WorkflowCustomizationHelpers.cxx src/WorkflowHelpers.cxx src/WorkflowSerializationHelpers.cxx src/WorkflowSpec.cxx diff --git a/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h b/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h index ece802e0dd547..4f7df3f87f877 100644 --- a/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h +++ b/Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h @@ -7,8 +7,8 @@ // 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_CHANNELCONFIGURATIONPOLICYHELPERS_H -#define FRAMEWORK_CHANNELCONFIGURATIONPOLICYHELPERS_H +#ifndef O2_FRAMEWORK_CHANNELCONFIGURATIONPOLICYHELPERS_H_ +#define O2_FRAMEWORK_CHANNELCONFIGURATIONPOLICYHELPERS_H_ #include "Framework/ChannelSpec.h" @@ -19,6 +19,9 @@ namespace o2::framework struct FairMQChannelConfigSpec { int64_t rateLogging; + int64_t recvBufferSize; + int64_t sendBufferSize; + std::string ipcPrefix; }; /// A set of helpers for common ChannelConfigurationPolicy behaviors diff --git a/Framework/Core/include/Framework/ChannelSpec.h b/Framework/Core/include/Framework/ChannelSpec.h index d8fcb406c2258..c8d256673aaba 100644 --- a/Framework/Core/include/Framework/ChannelSpec.h +++ b/Framework/Core/include/Framework/ChannelSpec.h @@ -48,7 +48,10 @@ struct InputChannelSpec { std::string hostname; unsigned short port; ChannelProtocol protocol = ChannelProtocol::Network; - size_t rateLogging = 60; + size_t rateLogging = 0; + size_t recvBufferSize = 1000; + size_t sendBufferSize = 1000; + std::string ipcPrefix = "."; }; /// This describes an output channel. Output channels are semantically @@ -64,7 +67,10 @@ struct OutputChannelSpec { unsigned short port; size_t listeners; ChannelProtocol protocol = ChannelProtocol::Network; - size_t rateLogging = 60; + size_t rateLogging = 0; + size_t recvBufferSize = 1000; + size_t sendBufferSize = 1000; + std::string ipcPrefix = "."; }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/WorkflowCustomizationHelpers.h b/Framework/Core/include/Framework/WorkflowCustomizationHelpers.h new file mode 100644 index 0000000000000..edf4758adeb4f --- /dev/null +++ b/Framework/Core/include/Framework/WorkflowCustomizationHelpers.h @@ -0,0 +1,25 @@ +// 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_WORKFLOWCUSTOMIZATIONHELPERS_H_ +#define O2_FRAMEWORK_WORKFLOWCUSTOMIZATIONHELPERS_H_ + +#include "Framework/ConfigParamSpec.h" +#include <vector> + +namespace o2::framework +{ + +struct WorkflowCustomizationHelpers { + static std::vector<ConfigParamSpec> requiredWorkflowOptions(); +}; + +} // namespace o2::framework + +#endif // O2_FRAMEWORK_WORKFLOWCUSTOMIZATIONHELPERS_H_ diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index d79e67bd42b38..3e97f6b4bc575 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -20,6 +20,7 @@ #include "Framework/BoostOptionsRetriever.h" #include "Framework/CustomWorkflowTerminationHook.h" #include "Framework/CommonServices.h" +#include "Framework/WorkflowCustomizationHelpers.h" #include "Framework/Logger.h" #include <unistd.h> @@ -75,6 +76,9 @@ void defaultConfiguration(std::vector<o2::framework::ServiceSpec>& services) services = o2::framework::CommonServices::defaultServices(); } +/// Workflow options which are required by DPL in order to work. +std::vector<o2::framework::ConfigParamSpec> requiredWorkflowOptions(); + void defaultConfiguration(o2::framework::OnWorkflowTerminationHook& hook) { hook = [](const char*) {}; @@ -131,35 +135,8 @@ int main(int argc, char** argv) // The default policy is a catch all pub/sub setup to be consistent with the past. std::vector<o2::framework::ConfigParamSpec> workflowOptions; UserCustomizationsHelper::userDefinedCustomization(workflowOptions, 0); - workflowOptions.push_back(ConfigParamSpec{"readers", VariantType::Int64, 1ll, {"number of parallel readers to use"}}); - workflowOptions.push_back(ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}); - workflowOptions.push_back(ConfigParamSpec{"clone", VariantType::String, "", {"clone processors from a template"}}); - workflowOptions.push_back(ConfigParamSpec{"workflow-suffix", VariantType::String, "", {"suffix to add to all dataprocessors"}}); - - // options for AOD rate limiting - workflowOptions.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::Int64, 0LL, {"Rate limit AOD processing based on memory"}}); - - // options for AOD writer - workflowOptions.push_back(ConfigParamSpec{"aod-writer-json", VariantType::String, "", {"Name of the json configuration file"}}); - workflowOptions.push_back(ConfigParamSpec{"aod-writer-resfile", VariantType::String, "", {"Default name of the output file"}}); - workflowOptions.push_back(ConfigParamSpec{"aod-writer-resmode", VariantType::String, "RECREATE", {"Creation mode of the result files: NEW, CREATE, RECREATE, UPDATE"}}); - workflowOptions.push_back(ConfigParamSpec{"aod-writer-ntfmerge", VariantType::Int, -1, {"Number of time frames to merge into one file"}}); - workflowOptions.push_back(ConfigParamSpec{"aod-writer-keep", VariantType::String, "", {"Comma separated list of ORIGIN/DESCRIPTION/SUBSPECIFICATION:treename:col1/col2/..:filename"}}); - - workflowOptions.push_back(ConfigParamSpec{"fairmq-rate-logging", VariantType::Int, 60, {"Rate logging for FairMQ channels"}}); - - workflowOptions.push_back(ConfigParamSpec{"forwarding-policy", - VariantType::String, - "dangling", - {"Which messages to forward." - " dangling: dangling outputs," - " all: all messages"}}); - workflowOptions.push_back(ConfigParamSpec{"forwarding-destination", - VariantType::String, - "file", - {"Destination for forwarded messages." - " file: write to file," - " fairmq: send to output proxy"}}); + auto requiredWorkflowOptions = WorkflowCustomizationHelpers::requiredWorkflowOptions(); + workflowOptions.insert(std::end(workflowOptions), std::begin(requiredWorkflowOptions), std::end(requiredWorkflowOptions)); std::vector<CompletionPolicy> completionPolicies; UserCustomizationsHelper::userDefinedCustomization(completionPolicies, 0); diff --git a/Framework/Core/src/ChannelConfigurationPolicy.cxx b/Framework/Core/src/ChannelConfigurationPolicy.cxx index 514cdc60f5fd3..3facdf12ed57e 100644 --- a/Framework/Core/src/ChannelConfigurationPolicy.cxx +++ b/Framework/Core/src/ChannelConfigurationPolicy.cxx @@ -17,9 +17,15 @@ namespace o2::framework std::vector<ChannelConfigurationPolicy> ChannelConfigurationPolicy::createDefaultPolicies(ConfigContext const& configContext) { ChannelConfigurationPolicy defaultPolicy; + FairMQChannelConfigSpec spec; + spec.rateLogging = configContext.options().get<int>("fairmq-rate-logging"); + spec.recvBufferSize = configContext.options().get<int>("fairmq-recv-buffer-size"); + spec.sendBufferSize = configContext.options().get<int>("fairmq-send-buffer-size"); + spec.ipcPrefix = configContext.options().get<std::string>("fairmq-ipc-prefix"); + defaultPolicy.match = ChannelConfigurationPolicyHelpers::matchAny; - defaultPolicy.modifyInput = ChannelConfigurationPolicyHelpers::pullInput({configContext.options().get<int>("fairmq-rate-logging")}); - defaultPolicy.modifyOutput = ChannelConfigurationPolicyHelpers::pushOutput({configContext.options().get<int>("fairmq-rate-logging")}); + defaultPolicy.modifyInput = ChannelConfigurationPolicyHelpers::pullInput(spec); + defaultPolicy.modifyOutput = ChannelConfigurationPolicyHelpers::pushOutput(spec); return {defaultPolicy}; } diff --git a/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx b/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx index 89dbfbe71f87d..9169edccd61bb 100644 --- a/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx +++ b/Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx @@ -41,6 +41,9 @@ ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPoli channel.method = ChannelMethod::Connect; channel.type = ChannelType::Sub; channel.rateLogging = spec.rateLogging; + channel.recvBufferSize = spec.recvBufferSize; + channel.recvBufferSize = spec.sendBufferSize; + channel.ipcPrefix = spec.ipcPrefix; }; } @@ -50,6 +53,9 @@ ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPol channel.method = ChannelMethod::Bind; channel.type = ChannelType::Pub; channel.rateLogging = spec.rateLogging; + channel.recvBufferSize = spec.recvBufferSize; + channel.recvBufferSize = spec.sendBufferSize; + channel.ipcPrefix = spec.ipcPrefix; }; } @@ -59,6 +65,9 @@ ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPoli channel.method = ChannelMethod::Connect; channel.type = ChannelType::Pull; channel.rateLogging = spec.rateLogging; + channel.recvBufferSize = spec.recvBufferSize; + channel.recvBufferSize = spec.sendBufferSize; + channel.ipcPrefix = spec.ipcPrefix; }; } @@ -68,6 +77,9 @@ ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPol channel.method = ChannelMethod::Bind; channel.type = ChannelType::Push; channel.rateLogging = spec.rateLogging; + channel.recvBufferSize = spec.recvBufferSize; + channel.recvBufferSize = spec.sendBufferSize; + channel.ipcPrefix = spec.ipcPrefix; }; } @@ -77,6 +89,9 @@ ChannelConfigurationPolicyHelpers::InputChannelModifier ChannelConfigurationPoli channel.method = ChannelMethod::Connect; channel.type = ChannelType::Pair; channel.rateLogging = spec.rateLogging; + channel.recvBufferSize = spec.recvBufferSize; + channel.recvBufferSize = spec.sendBufferSize; + channel.ipcPrefix = spec.ipcPrefix; }; } @@ -86,6 +101,9 @@ ChannelConfigurationPolicyHelpers::OutputChannelModifier ChannelConfigurationPol channel.method = ChannelMethod::Bind; channel.type = ChannelType::Pair; channel.rateLogging = spec.rateLogging; + channel.recvBufferSize = spec.recvBufferSize; + channel.recvBufferSize = spec.sendBufferSize; + channel.ipcPrefix = spec.ipcPrefix; }; } diff --git a/Framework/Core/src/ChannelSpecHelpers.cxx b/Framework/Core/src/ChannelSpecHelpers.cxx index 7c04beecb19ea..5a15a05a7367b 100644 --- a/Framework/Core/src/ChannelSpecHelpers.cxx +++ b/Framework/Core/src/ChannelSpecHelpers.cxx @@ -67,7 +67,7 @@ std::string ChannelSpecHelpers::channelUrl(OutputChannelSpec const& channel) { switch (channel.protocol) { case ChannelProtocol::IPC: - return fmt::format("ipc://{}/{}_{},transport=shmem", getTmpFolder(), channel.hostname, channel.port); + return fmt::format("ipc://{}/{}_{},transport=shmem", channel.ipcPrefix, channel.hostname, channel.port); default: return channel.method == ChannelMethod::Bind ? fmt::format("tcp://*:{}", channel.port) : fmt::format("tcp://{}:{}", channel.hostname, channel.port); @@ -78,7 +78,7 @@ std::string ChannelSpecHelpers::channelUrl(InputChannelSpec const& channel) { switch (channel.protocol) { case ChannelProtocol::IPC: - return fmt::format("ipc://{}/{}_{},transport=shmem", getTmpFolder(), channel.hostname, channel.port); + return fmt::format("ipc://{}/{}_{},transport=shmem", channel.ipcPrefix, channel.hostname, channel.port); default: return channel.method == ChannelMethod::Bind ? fmt::format("tcp://*:{}", channel.port) : fmt::format("tcp://{}:{}", channel.hostname, channel.port); diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index cb4c76e217373..89ed2328e2ca8 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -36,6 +36,7 @@ #include <uv.h> #include <iostream> +#include <fmt/format.h> #include <sys/time.h> #include <sys/resource.h> @@ -245,32 +246,26 @@ struct ExpirationHandlerHelpers { /// FIXME: support shared memory std::string DeviceSpecHelpers::inputChannel2String(const InputChannelSpec& channel) { - std::string result; - - if (!channel.name.empty()) { - result += "name=" + channel.name + ","; - } - result += std::string("type=") + ChannelSpecHelpers::typeAsString(channel.type); - result += std::string(",method=") + ChannelSpecHelpers::methodAsString(channel.method); - result += std::string(",address=") + ChannelSpecHelpers::channelUrl(channel); - result += std::string(",rateLogging=" + std::to_string(channel.rateLogging)); - - return result; + return fmt::format("{}type={},method={},address={},rateLogging={},recvBufferSize={},sendBufferSize={}", + channel.name.empty() ? "" : "name=" + channel.name + ",", + ChannelSpecHelpers::typeAsString(channel.type), + ChannelSpecHelpers::methodAsString(channel.method), + ChannelSpecHelpers::channelUrl(channel), + channel.rateLogging, + channel.recvBufferSize, + channel.sendBufferSize); } std::string DeviceSpecHelpers::outputChannel2String(const OutputChannelSpec& channel) { - std::string result; - - if (!channel.name.empty()) { - result += "name=" + channel.name + ","; - } - result += std::string("type=") + ChannelSpecHelpers::typeAsString(channel.type); - result += std::string(",method=") + ChannelSpecHelpers::methodAsString(channel.method); - result += std::string(",address=") + ChannelSpecHelpers::channelUrl(channel); - result += std::string(",rateLogging=" + std::to_string(channel.rateLogging)); - - return result; + return fmt::format("{}type={},method={},address={},rateLogging={},recvBufferSize={},sendBufferSize={}", + channel.name.empty() ? "" : "name=" + channel.name + ",", + ChannelSpecHelpers::typeAsString(channel.type), + ChannelSpecHelpers::methodAsString(channel.method), + ChannelSpecHelpers::channelUrl(channel), + channel.rateLogging, + channel.recvBufferSize, + channel.sendBufferSize); } void DeviceSpecHelpers::processOutEdgeActions(std::vector<DeviceSpec>& devices, diff --git a/Framework/Core/src/WorkflowCustomizationHelpers.cxx b/Framework/Core/src/WorkflowCustomizationHelpers.cxx new file mode 100644 index 0000000000000..4d187933bce5e --- /dev/null +++ b/Framework/Core/src/WorkflowCustomizationHelpers.cxx @@ -0,0 +1,65 @@ +// 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/WorkflowCustomizationHelpers.h" +#include <string> +#include <cstdlib> +#include <unistd.h> + +namespace +{ +std::string defaultIPCFolder() +{ + /// Find out a place where we can write the sockets + char const* channelPrefix = getenv("TMPDIR"); + if (channelPrefix) { + return std::string(channelPrefix); + } + return access("/tmp", W_OK) == 0 ? "/tmp" : "."; +} +} // namespace + +namespace o2::framework +{ + +std::vector<ConfigParamSpec> WorkflowCustomizationHelpers::requiredWorkflowOptions() +{ + return std::vector<ConfigParamSpec>{{ConfigParamSpec{"readers", VariantType::Int64, 1ll, {"number of parallel readers to use"}}, + ConfigParamSpec{"pipeline", VariantType::String, "", {"override default pipeline size"}}, + ConfigParamSpec{"clone", VariantType::String, "", {"clone processors from a template"}}, + ConfigParamSpec{"workflow-suffix", VariantType::String, "", {"suffix to add to all dataprocessors"}}, + + // options for AOD rate limiting + ConfigParamSpec{"aod-memory-rate-limit", VariantType::Int64, 0LL, {"Rate limit AOD processing based on memory"}}, + + // options for AOD writer + ConfigParamSpec{"aod-writer-json", VariantType::String, "", {"Name of the json configuration file"}}, + ConfigParamSpec{"aod-writer-resfile", VariantType::String, "", {"Default name of the output file"}}, + ConfigParamSpec{"aod-writer-resmode", VariantType::String, "RECREATE", {"Creation mode of the result files: NEW, CREATE, RECREATE, UPDATE"}}, + ConfigParamSpec{"aod-writer-ntfmerge", VariantType::Int, -1, {"Number of time frames to merge into one file"}}, + ConfigParamSpec{"aod-writer-keep", VariantType::String, "", {"Comma separated list of ORIGIN/DESCRIPTION/SUBSPECIFICATION:treename:col1/col2/..:filename"}}, + + ConfigParamSpec{"fairmq-rate-logging", VariantType::Int, 0, {"Rate logging for FairMQ channels"}}, + ConfigParamSpec{"fairmq-recv-buffer-size", VariantType::Int, 1000, {"recvBufferSize option for FairMQ channels"}}, + ConfigParamSpec{"fairmq-send-buffer-size", VariantType::Int, 1000, {"sendBufferSize option for FairMQ channels"}}, + /// Find out a place where we can write the sockets + ConfigParamSpec{"fairmq-ipc-prefix", VariantType::String, defaultIPCFolder(), {"Prefix for FairMQ channels location"}}, + + ConfigParamSpec{"forwarding-policy", VariantType::String, "dangling", {"Which messages to forward." + " dangling: dangling outputs," + " all: all messages"}}, + ConfigParamSpec{"forwarding-destination", + VariantType::String, + "file", + {"Destination for forwarded messages." + " file: write to file," + " fairmq: send to output proxy"}}}}; +} +} // namespace o2::framework diff --git a/Framework/Core/test/Mocking.h b/Framework/Core/test/Mocking.h index c89b324910fa0..8a8577fdbad84 100644 --- a/Framework/Core/test/Mocking.h +++ b/Framework/Core/test/Mocking.h @@ -12,6 +12,7 @@ #include "Framework/WorkflowSpec.h" #include "Framework/DataSpecUtils.h" #include "Framework/SimpleOptionsRetriever.h" +#include "Framework/WorkflowCustomizationHelpers.h" #include "../src/WorkflowHelpers.h" std::unique_ptr<o2::framework::ConfigContext> makeEmptyConfigContext() @@ -20,21 +21,7 @@ std::unique_ptr<o2::framework::ConfigContext> makeEmptyConfigContext() // FIXME: Ugly... We need to fix ownership and make sure the ConfigContext // either owns or shares ownership of the registry. std::vector<std::unique_ptr<ParamRetriever>> retrievers; - static std::vector<ConfigParamSpec> specs = { - ConfigParamSpec{"forwarding-policy", - VariantType::String, - "dangling", - {""}}, - ConfigParamSpec{"forwarding-destination", - VariantType::String, - "file", - {"what to do with dangling outputs. file: write to file, fairmq: send to output proxy"}}, - ConfigParamSpec{"fairmq-rate-logging", - VariantType::Int, - 60, - {"rateLogging"}}, - }; - specs.push_back(ConfigParamSpec{"aod-memory-rate-limit", VariantType::String, "0", {"rate"}}); + static std::vector<ConfigParamSpec> specs = WorkflowCustomizationHelpers::requiredWorkflowOptions(); auto store = std::make_unique<ConfigParamStore>(specs, std::move(retrievers)); store->preload(); store->activate(); From 3390cb7df751fb16a5b8bd3fbeb276ca2c3ad55b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 11 Dec 2020 10:07:34 +0100 Subject: [PATCH 1597/1751] Drop obsolete badge from README (#5051) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 880f581943956..b25c4f680e874 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ [![](http://ali-ci.cern.ch/repo/buildstatus/AliceO2Group/AliceO2/dev/build_O2_o2.svg)](https://ali-ci.cern.ch/repo/logs/AliceO2Group/AliceO2/dev/latest/build_O2_o2/fullLog.txt) [![](http://ali-ci.cern.ch/repo/buildstatus/AliceO2Group/AliceO2/dev/build_o2_macos.svg)](https://ali-ci.cern.ch/repo/logs/AliceO2Group/AliceO2/dev/latest/build_o2_macos/fullLog.txt) [![](http://ali-ci.cern.ch/repo/buildstatus/AliceO2Group/AliceO2/dev/build_o2checkcode_o2.svg)](https://ali-ci.cern.ch/repo/logs/AliceO2Group/AliceO2/dev/latest/build_o2checkcode_o2/fullLog.txt) -[![](http://ali-ci.cern.ch/repo/buildstatus/AliceO2Group/AliceO2/dev/build_O2_o2-dev-fairroot.svg)](https://ali-ci.cern.ch/repo/logs/AliceO2Group/AliceO2/dev/latest/build_O2_o2-dev-fairroot/fullLog.txt) <!-- /// \endcond --> From b983216ed85677717dc1a5af6555c045dfc32a97 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 19:25:25 +0100 Subject: [PATCH 1598/1751] Use value_t instead of double --- DataFormats/Reconstruction/src/TrackParametrization.cxx | 2 +- .../Reconstruction/src/TrackParametrizationWithError.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index ae78900a42cb6..17fd10838210f 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -369,7 +369,7 @@ bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3 x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); + value_t d = std::abs(x * snp - y * csp); if (d > maxD) { return false; } diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index 2d340193251c5..f02b78ff2b05a 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -229,7 +229,7 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); + value_t d = std::abs(x * snp - y * csp); if (d > maxD) { return false; } From d0dde246739d91f9cecfd67da505fdab928fcf82 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 10 Dec 2020 22:35:11 +0100 Subject: [PATCH 1599/1751] Add DAQ SystemID Unloaded --- DataFormats/Headers/include/Headers/DAQID.h | 45 +++++++++++++++++++-- DataFormats/Headers/test/testDAQID.cxx | 4 ++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/DataFormats/Headers/include/Headers/DAQID.h b/DataFormats/Headers/include/Headers/DAQID.h index 96cfb10b98997..4918750ae1818 100644 --- a/DataFormats/Headers/include/Headers/DAQID.h +++ b/DataFormats/Headers/include/Headers/DAQID.h @@ -22,6 +22,9 @@ namespace header { /// Source IDs used by DAQ +constexpr o2::header::DataOrigin gDataOriginUnloaded{"UNL"}; +constexpr o2::header::DataOrigin gDataOriginTST{"TST"}; + class DAQID { @@ -48,6 +51,7 @@ class DAQID static constexpr ID MID = 37; static constexpr ID DCS = 38; static constexpr ID FOC = 39; + static constexpr ID UNLOADED = 255; static constexpr ID MINDAQ = TPC; static constexpr ID MAXDAQ = FOC; @@ -60,7 +64,7 @@ class DAQID static constexpr o2::header::DataOrigin DAQtoO2(ID daq) { - return (daq < MAXDAQ + 1) ? MAP_DAQtoO2[daq] : MAP_DAQtoO2[INVALID]; + return (daq < MAXDAQ + 1) ? MAP_DAQtoO2[daq] : (daq == UNLOADED ? gDataOriginUnloaded : MAP_DAQtoO2[INVALID]); } static constexpr ID O2toDAQ(o2::header::DataOrigin o2orig) @@ -71,7 +75,7 @@ class DAQID private: ID mID = INVALID; - static constexpr o2::header::DataOrigin MAP_DAQtoO2[] = { + static constexpr o2::header::DataOrigin MAP_DAQtoO2[0xff + 1] = { "NIL", "NIL", "NIL", "TPC", "TRD", "TOF", "HMP", "PHS", "CPV", "NIL", @@ -81,11 +85,44 @@ class DAQID "NIL", "TRG", "EMC", "TST", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", - "ITS", "FDD", "FT0", "FV0", "MFT", "MID", "DCS", "FOC"}; + "ITS", "FDD", "FT0", "FV0", "MFT", "MID", "DCS", "FOC", // 39 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 49 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 59 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 69 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 79 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 89 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 99 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 109 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 119 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 129 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 139 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 149 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 159 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 169 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 179 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 189 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 199 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 209 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 219 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 229 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 239 + "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", "NIL", // 249 + "NIL", "NIL", "NIL", "NIL", "NIL", "UNL" // 255 + }; + + static constexpr bool isSameOrigin(o2::header::DataOrigin origin, ID id) + { + for (auto i = sizeof(o2::header::DataOrigin); i--;) { + if (MAP_DAQtoO2[id].str[i] != origin.str[i]) { + return false; + } + } + return true; + } static constexpr ID or2daq(o2::header::DataOrigin origin, ID id) { - return id > MAXDAQ ? INVALID : (origin == MAP_DAQtoO2[id] ? id : or2daq(origin, id + 1)); + return (id > MAXDAQ) ? (isSameOrigin(origin, UNLOADED) ? UNLOADED : INVALID) : (isSameOrigin(origin, id) ? id : or2daq(origin, id + 1)); } }; diff --git a/DataFormats/Headers/test/testDAQID.cxx b/DataFormats/Headers/test/testDAQID.cxx index 49c741011aa50..404eca33d7b19 100644 --- a/DataFormats/Headers/test/testDAQID.cxx +++ b/DataFormats/Headers/test/testDAQID.cxx @@ -23,6 +23,7 @@ using namespace o2::header; BOOST_AUTO_TEST_CASE(DAQIDTEST) { + for (int i = 0; i < DAQID::MAXDAQ + 5; i++) { auto vo2 = DAQID::DAQtoO2(i); auto daq = DAQID::O2toDAQ(vo2); @@ -32,4 +33,7 @@ BOOST_AUTO_TEST_CASE(DAQIDTEST) BOOST_CHECK(i == daq || vo2 == DAQID::DAQtoO2(DAQID::INVALID)); } std::cout << "DAQ INVALID " << int(DAQID::INVALID) << " <-> " << DAQID::DAQtoO2(DAQID::INVALID).str << std::endl; + std::cout << "DAQ UNLOADED " << int(DAQID::UNLOADED) << " <-> " << DAQID::DAQtoO2(DAQID::UNLOADED).str << std::endl; + BOOST_CHECK(DAQID::DAQtoO2(DAQID::UNLOADED) == o2::header::gDataOriginUnloaded); + BOOST_CHECK(DAQID::O2toDAQ(o2::header::gDataOriginUnloaded) == DAQID::UNLOADED); } From c828821bf149922746eaff3093614a9a573d0f0c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 11 Dec 2020 16:52:02 +0100 Subject: [PATCH 1600/1751] Add braces in oneliners of PHOS code --- Detectors/PHOS/reconstruction/run/rawReaderFile.cxx | 5 +++-- Detectors/PHOS/reconstruction/src/AltroDecoder.cxx | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx b/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx index 3de33ebc1d7ee..c264d78ca1cb4 100644 --- a/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx +++ b/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx @@ -94,8 +94,9 @@ int main(int argc, char** argv) while (parser.hasNext()) { parser.next(); // Exclude STU DDLs - if (o2::raw::RDHUtils::getFEEID(parser.getRawHeader()) >= 40) + if (o2::raw::RDHUtils::getFEEID(parser.getRawHeader()) >= 40) { continue; + } o2::phos::AltroDecoder decoder(parser); decoder.decode(); @@ -116,4 +117,4 @@ int main(int argc, char** argv) } reader.setNextTFToRead(++tfID); } -} \ No newline at end of file +} diff --git a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx index e30f4fe8cbf3f..217e5e4e5cc32 100644 --- a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx @@ -103,14 +103,16 @@ void AltroDecoder::readChannels() const RCUTrailer& AltroDecoder::getRCUTrailer() const { - if (!mRCUTrailer.isInitialized()) + if (!mRCUTrailer.isInitialized()) { throw AltroDecoderError::ErrorType_t::RCU_TRAILER_ERROR; // "RCU trailer was not initialized"); + } return mRCUTrailer; } const std::vector<Channel>& AltroDecoder::getChannels() const { - if (!mChannelsInitialized) + if (!mChannelsInitialized) { throw AltroDecoderError::ErrorType_t::CHANNEL_ERROR; // "Channels not initizalized"); + } return mChannels; } From 9d8c8c736f17d354deb68f31327670f9e4aad7cd Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Wed, 9 Dec 2020 09:54:33 +0100 Subject: [PATCH 1601/1751] [ITS] Remove unused classes --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 3 - .../ITS/tracking/include/ITStracking/DBScan.h | 141 ----------- .../ITS/tracking/include/ITStracking/Graph.h | 232 ------------------ Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx | 41 ---- Detectors/ITSMFT/ITS/tracking/src/Graph.cxx | 33 --- .../ITSMFT/ITS/tracking/src/TrackingLinkDef.h | 1 - 6 files changed, 451 deletions(-) delete mode 100644 Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h delete mode 100644 Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h delete mode 100644 Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx delete mode 100644 Detectors/ITSMFT/ITS/tracking/src/Graph.cxx diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 7315b166edf54..6e976bfeb5d02 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -13,8 +13,6 @@ o2_add_library(ITStracking SOURCES src/ClusterLines.cxx src/Cluster.cxx src/ROframe.cxx - src/Graph.cxx - src/DBScan.cxx src/IOUtils.cxx src/Label.cxx src/PrimaryVertexContext.cxx @@ -37,7 +35,6 @@ o2_add_library(ITStracking o2_target_root_dictionary(ITStracking HEADERS include/ITStracking/ClusterLines.h include/ITStracking/Tracklet.h - include/ITStracking/DBScan.h include/ITStracking/TrackingConfigParam.h LINKDEF src/TrackingLinkDef.h) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h deleted file mode 100644 index 1e8d16b42bdea..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h +++ /dev/null @@ -1,141 +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. -/// -/// \file DBScan.h -/// \brief -/// - -#ifndef O2_ITS_TRACKING_DBSCAN_H_ -#define O2_ITS_TRACKING_DBSCAN_H_ - -#include <algorithm> -#include "ITStracking/Graph.h" - -namespace o2 -{ -namespace its -{ - -typedef std::pair<int, unsigned char> State; - -template <typename T> -class DBScan : Graph<T> -{ - public: - DBScan() = delete; - explicit DBScan(const size_t nThreads); - void init(std::vector<T>&, std::function<bool(const T& v1, const T& v2)>); - void classifyVertices(const int); - void classifyVertices(std::function<unsigned char(std::vector<Edge>&)> classFunction); - void classifyVertices(std::function<unsigned char(std::vector<Edge>&)> classFunction, std::function<bool(State&, State&)> sortFunction); - std::vector<State> getStates() const { return mStates; } - std::vector<int> getCores(); - std::vector<std::vector<int>> computeClusters(); - - private: - std::vector<State> mStates; - std::function<unsigned char(std::vector<Edge>&)> mClassFunction; -}; - -template <typename T> -DBScan<T>::DBScan(const size_t nThreads) : Graph<T>(nThreads) -{ -} - -template <typename T> -void DBScan<T>::init(std::vector<T>& vertices, std::function<bool(const T& v1, const T& v2)> discFunction) -{ - this->Graph<T>::init(vertices); - this->Graph<T>::computeEdges(discFunction); -} - -template <typename T> -void DBScan<T>::classifyVertices(const int nContributors) -{ - classifyVertices([nContributors](std::vector<o2::its::Edge>& edges) { return edges.size() == 0 ? 0 : edges.size() >= static_cast<size_t>(nContributors - 1) ? 2 : 1; }, - [](State& s1, State& s2) { return static_cast<int>(s1.second) > static_cast<int>(s2.second); }); -} - -template <typename T> -void DBScan<T>::classifyVertices(std::function<unsigned char(std::vector<Edge>& edges)> classFunction) -{ - mClassFunction = classFunction; - const size_t size = {this->mVertices->size()}; - mStates.resize(size); - - if (!this->isMultiThreading()) { - for (size_t iVertex{0}; iVertex < size; ++iVertex) { - mStates[iVertex] = std::make_pair<int, unsigned char>(iVertex, classFunction(this->getEdges()[iVertex])); - } - } else { - const size_t stride{static_cast<size_t>(std::ceil(this->mVertices->size() / static_cast<size_t>(this->mExecutors.size())))}; - for (size_t iExecutor{0}; iExecutor < this->mExecutors.size(); ++iExecutor) { - // We cannot pass a template function to std::thread(), using lambda instead - this->mExecutors[iExecutor] = std::thread( - [iExecutor, stride, this](const auto& classFunction) { - for (size_t iVertex{iExecutor * stride}; iVertex < stride * (iExecutor + 1) && iVertex < this->mVertices->size(); ++iVertex) { - mStates[iVertex] = std::make_pair<int, unsigned char>(iVertex, classFunction(this->getEdges()[iVertex])); - } - }, - mClassFunction); - } - } - for (auto&& thread : this->mExecutors) { - thread.join(); - } -} - -template <typename T> -void DBScan<T>::classifyVertices(std::function<unsigned char(std::vector<Edge>&)> classFunction, std::function<bool(State&, State&)> sortFunction) -{ - classifyVertices(classFunction); - std::sort(mStates.begin(), mStates.end(), sortFunction); -} - -template <typename T> -std::vector<int> DBScan<T>::getCores() -{ - std::vector<State> cores; - std::vector<int> coreIndices; - std::copy_if(mStates.begin(), mStates.end(), std::back_inserter(cores), [](const State& state) { return state.second == 2; }); - std::transform(cores.begin(), cores.end(), std::back_inserter(coreIndices), [](const State& state) -> int { return state.first; }); - return coreIndices; -} - -template <typename T> -std::vector<std::vector<int>> DBScan<T>::computeClusters() -{ - std::vector<std::vector<int>> clusters; - std::vector<int> cores = getCores(); - std::vector<unsigned char> usedVertices(this->mVertices->size(), false); - - for (size_t core{0}; core < cores.size(); ++core) { - if (!usedVertices[cores[core]]) { - std::vector<unsigned char> clusterFlags = this->getCluster(cores[core]); - std::transform(usedVertices.begin(), usedVertices.end(), clusterFlags.begin(), usedVertices.begin(), std::logical_or<>()); - clusters.emplace_back(std::move(this->getClusterIndices(clusterFlags))); - } - } - return clusters; -} - -struct Centroid final { - Centroid() = default; - Centroid(int* indices, float* position); - void init(); - static float ComputeDistance(const Centroid& c1, const Centroid& c2); - - int mIndices[2]; - float mPosition[3]; -}; - -} // namespace its -} // namespace o2 -#endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h deleted file mode 100644 index d1fca077e29c6..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h +++ /dev/null @@ -1,232 +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. -/// -/// \file Graph.h -/// \brief -/// - -#ifndef TRACKINGITSU_INCLUDE_ALGORITHMS_H_ -#define TRACKINGITSU_INCLUDE_ALGORITHMS_H_ - -#include <array> -#include <cmath> -#include <condition_variable> -#include <functional> -#include <iostream> -#include <mutex> -#include <queue> -#include <thread> -#include <utility> -#include <vector> - -namespace o2 -{ -namespace its -{ - -typedef int Edge; - -class Barrier -{ - public: - explicit Barrier(std::size_t count) : count(count) {} - void Wait(); - - private: - std::mutex mutex; - std::condition_variable condition; - std::size_t count; -}; - -template <typename T> -class Graph -{ - public: - Graph() = delete; - explicit Graph(const size_t nThreads = 1); - void init(std::vector<T>&); - std::vector<unsigned char> getCluster(const int); - std::vector<int> getClusterIndices(const int); - std::vector<int> getClusterIndices(const std::vector<unsigned char> /* , const int*/); - void computeEdges(std::function<bool(const T& v1, const T& v2)>); - std::vector<std::vector<Edge>> getEdges() const { return mEdges; } - char isMultiThreading() const { return mIsMultiThread; } - - std::vector<T>* mVertices = nullptr; // Observer pointer - std::vector<std::thread> mExecutors; // Difficult to pass - - private: - void findVertexEdges(std::vector<Edge>& localEdges, const T& vertex, const size_t vId, const size_t size); - - // Multithread block - size_t mNThreads; - char mIsMultiThread; - - // Common data members - std::function<bool(const T&, const T&)> mLinkFunction; - std::vector<std::vector<Edge>> mEdges; - std::vector<unsigned char> mVisited; -}; - -template <typename T> -Graph<T>::Graph(const size_t nThreads) : mNThreads{nThreads} -{ - mIsMultiThread = nThreads > 1 ? true : false; -} - -template <typename T> -void Graph<T>::init(std::vector<T>& vertices) -{ - - // Graph initialization - mVertices = &vertices; - if (mIsMultiThread) { - mNThreads = std::min(static_cast<const size_t>(std::thread::hardware_concurrency()), mNThreads); - mExecutors.resize(mNThreads); - } - - mEdges.resize(vertices.size()); - mVisited.resize(vertices.size(), false); -} - -template <typename T> -void Graph<T>::computeEdges(std::function<bool(const T& v1, const T& v2)> linkFunction) -{ - mLinkFunction = linkFunction; - int tot_nedges = 0; - const size_t size = {mVertices->size()}; - if (!mIsMultiThread) { - for (size_t iVertex{0}; iVertex < size; ++iVertex) { - findVertexEdges(mEdges[iVertex], (*mVertices)[iVertex], iVertex, size); - tot_nedges += static_cast<int>(mEdges[iVertex].size()); - } - } else { - mNThreads = std::min(static_cast<const size_t>(std::thread::hardware_concurrency()), mNThreads); - mExecutors.resize(mNThreads); - const size_t stride{static_cast<size_t>(std::ceil(mVertices->size() / static_cast<size_t>(mExecutors.size())))}; - for (size_t iExecutor{0}; iExecutor < mExecutors.size(); ++iExecutor) { - // We cannot pass a template function to std::thread(), using lambda instead - mExecutors[iExecutor] = std::thread( - [iExecutor, stride, this](const auto& linkFunction) { - for (size_t iVertex1{iExecutor * stride}; iVertex1 < stride * (iExecutor + 1) && iVertex1 < mVertices->size(); ++iVertex1) { - for (size_t iVertex2{0}; iVertex2 < mVertices->size(); ++iVertex2) { - if (iVertex1 != iVertex2 && linkFunction((*mVertices)[iVertex1], (*mVertices)[iVertex2])) { - mEdges[iVertex1].emplace_back(iVertex2); - } - } - } - }, - mLinkFunction); - } - } - for (auto&& thread : mExecutors) { - thread.join(); - } -} -template <typename T> -void Graph<T>::findVertexEdges(std::vector<Edge>& localEdges, const T& vertex, const size_t vId, const size_t size) -{ - for (size_t iVertex2{0}; iVertex2 < size; ++iVertex2) { - if (vId != iVertex2 && mLinkFunction(vertex, (*mVertices)[iVertex2])) { - localEdges.emplace_back(iVertex2); - } - } -} - -template <typename T> -std::vector<unsigned char> Graph<T>::getCluster(const int vertexId) -{ - // This method uses a BFS algorithm to return all the graph - // vertex ids belonging to a graph - std::vector<int> indices; - std::vector<unsigned char> visited(mVertices->size(), false); - - if (!mIsMultiThread) { - std::queue<int> idQueue; - idQueue.emplace(vertexId); - visited[vertexId] = true; - - // Consume the queue - while (!idQueue.empty()) { - const int id = idQueue.front(); - idQueue.pop(); - for (Edge edge : mEdges[id]) { - if (!visited[edge]) { - idQueue.emplace(edge); - indices.emplace_back(edge); - visited[edge] = true; - } - } - } - } else { - const size_t stride{static_cast<size_t>(std::ceil(static_cast<float>(this->mVertices->size()) / static_cast<size_t>(this->mExecutors.size())))}; - std::vector<unsigned char> frontier(mVertices->size(), false); - std::vector<unsigned char> flags(mVertices->size(), false); - - frontier[vertexId] = true; - int counter{0}; - while (std::any_of(frontier.begin(), frontier.end(), [](const char t) { return t; })) { - flags.resize(mVertices->size(), false); - Barrier barrier(mExecutors.size()); - for (size_t iExecutor{0}; iExecutor < this->mExecutors.size(); ++iExecutor) { - mExecutors[iExecutor] = std::thread( - [&stride, &frontier, &visited, &barrier, &flags, this](const int executorId) { - for (size_t iVertex{executorId * stride}; iVertex < stride * (executorId + 1) && iVertex < this->mVertices->size(); ++iVertex) { - if (frontier[iVertex]) { - flags[iVertex] = true; - frontier[iVertex] = false; - visited[iVertex] = true; - } - } - barrier.Wait(); - for (size_t iVertex{executorId * stride}; iVertex < stride * (executorId + 1) && iVertex < this->mVertices->size(); ++iVertex) { - if (flags[iVertex]) { - for (auto& edge : mEdges[iVertex]) { - if (!visited[edge]) { - frontier[edge] = true; - } - } - } - } - }, - iExecutor); - } - for (auto&& thread : mExecutors) { - thread.join(); - } - } - } - return visited; -} - -template <typename T> -std::vector<int> Graph<T>::getClusterIndices(const std::vector<unsigned char> visited) -{ - // Return a smaller vector only with the int IDs of the vertices belonging to cluster - std::vector<int> indices; - for (size_t iVisited{0}; iVisited < visited.size(); ++iVisited) { - if (visited[iVisited]) { - indices.emplace_back(iVisited); - } - } - return indices; -} - -template <typename T> -std::vector<int> Graph<T>::getClusterIndices(const int vertexId) -{ - std::vector<unsigned char> visited = std::move(getCluster(vertexId)); - return getClusterIndices(visited); -} - -} // namespace its -} // namespace o2 - -#endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx b/Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx deleted file mode 100644 index 45eaebb76b54f..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx +++ /dev/null @@ -1,41 +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. -/// -/// \file DBScan.cxx -/// \brief -/// - -#include "ITStracking/DBScan.h" -#include "ITStracking/Definitions.h" -#include "GPUCommonMath.h" - -namespace o2 -{ -namespace its -{ - -Centroid::Centroid(int* indices, float* position) -{ - for (int i{0}; i < 2; ++i) { - mIndices[i] = indices[i]; - } - for (int i{0}; i < 3; ++i) { - mPosition[i] = position[i]; - } -} - -float Centroid::ComputeDistance(const Centroid& c1, const Centroid& c2) -{ - return o2::gpu::GPUCommonMath::Sqrt((c1.mPosition[0] - c2.mPosition[0]) * (c1.mPosition[0] - c2.mPosition[0]) + - (c1.mPosition[1] - c2.mPosition[1]) * (c1.mPosition[1] - c2.mPosition[1]) + - (c1.mPosition[2] - c2.mPosition[2]) * (c1.mPosition[2] - c2.mPosition[2])); -} -} // namespace its -} // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/Graph.cxx b/Detectors/ITSMFT/ITS/tracking/src/Graph.cxx deleted file mode 100644 index a43b8c036056e..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/src/Graph.cxx +++ /dev/null @@ -1,33 +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. -/// -/// \file Graph.cxx -/// \brief -/// - -#include "ITStracking/Graph.h" - -namespace o2 -{ -namespace its -{ - -void Barrier::Wait() -{ - std::unique_lock<std::mutex> lock(mutex); - if (--count == 0) { - condition.notify_all(); - } else { - condition.wait(lock, [this] { return count == 0; }); - } -} - -} // namespace its -} // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h index afc832a3a6b24..95a586f24d241 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h @@ -16,7 +16,6 @@ #pragma link C++ class o2::its::ClusterLines + ; #pragma link C++ class o2::its::Tracklet + ; -#pragma link C++ class o2::its::Centroid + ; #pragma link C++ class o2::its::VertexerParamConfig + ; #pragma link C++ class o2::conf::ConfigurableParamHelper <o2::its::VertexerParamConfig> + ; From a06746582b79dde1a9c96740404e170e76edf9cc Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Mon, 7 Dec 2020 10:28:40 +0100 Subject: [PATCH 1602/1751] Add fix and chi2 selection --- .../include/ITStracking/Configuration.h | 3 ++ .../tracking/include/ITStracking/Constants.h | 1 + .../tracking/include/ITStracking/Tracker.h | 6 ++- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 39 +++++++++++++------ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 0c58a98b17184..930aa273d3766 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -72,6 +72,9 @@ struct TrackingParameters { /// Neighbour finding cuts std::vector<float> NeighbourMaxDeltaCurvature = {0.008f, 0.0025f, 0.003f, 0.0035f}; std::vector<float> NeighbourMaxDeltaN = {0.002f, 0.0090f, 0.002f, 0.005f}; + /// Fitter parameters + bool UseMatBudLUT = false; + std::array<float, 2> FitIterationMaxChi2 = {o2::constants::math::VeryBig, o2::constants::math::VeryBig}; }; struct MemoryParameters { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index 02d6121deac6a..5f9f22a51e035 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -21,6 +21,7 @@ #endif #include "ITStracking/Definitions.h" +#include "CommonConstants/MathConstants.h" #include "GPUCommonMath.h" #include "GPUCommonDef.h" diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 920ac2f2ae949..9e6f29fcafc41 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -25,6 +25,8 @@ #include <utility> #include "ITStracking/Configuration.h" +#include "DetectorsBase/MatLayerCylSet.h" +#include "CommonConstants/MathConstants.h" #include "ITStracking/Definitions.h" #include "ITStracking/ROframe.h" #include "ITStracking/MathUtils.h" @@ -80,7 +82,8 @@ class Tracker void findCellsNeighbours(int& iteration); void findRoads(int& iteration); void findTracks(const ROframe& ev); - bool fitTrack(const ROframe& event, TrackITSExt& track, int start, int end, int step); + bool fitTrack(const ROframe& event, TrackITSExt& track, int start, int end, int step, + const float chi2cut = o2::constants::math::VeryBig); void traverseCellsTree(const int, const int); void computeRoadsMClabels(const ROframe&); void computeTracksMClabels(const ROframe&); @@ -100,6 +103,7 @@ class Tracker std::uint32_t mROFrame = 0; std::vector<TrackITSExt> mTracks; std::vector<MCCompLabel> mTrackLabels; + o2::base::MatLayerCylSet* mMatLayerCylSet; o2::gpu::GPUChainITS* mRecoChain = nullptr; }; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 721fa617051b5..ab85bc4837f15 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -14,7 +14,6 @@ #include "ITStracking/Tracker.h" -#include "CommonConstants/MathConstants.h" #include "ITStracking/Cell.h" #include "ITStracking/Constants.h" #include "ITStracking/IndexTableUtils.h" @@ -41,6 +40,7 @@ Tracker::Tracker(o2::its::TrackerTraits* traits) mMemParams.resize(1); assert(traits != nullptr); mTraits = traits; + mMatLayerCylSet = o2::base::MatLayerCylSet::loadFromFile(); mPrimaryVertexContext = mTraits->getPrimaryVertexContext(); } @@ -285,14 +285,14 @@ void Tracker::findTracks(const ROframe& event) } CA_DEBUGGER(fitCounters[nClusters - 4]++); temporaryTrack.resetCovariance(); - fitSuccess = fitTrack(event, temporaryTrack, 0, mTrkParams[0].NLayers, 1); + fitSuccess = fitTrack(event, temporaryTrack, 0, mTrkParams[0].NLayers, 1, mTrkParams[0].FitIterationMaxChi2[0]); if (!fitSuccess) { continue; } CA_DEBUGGER(backpropagatedCounters[nClusters - 4]++); temporaryTrack.getParamOut() = temporaryTrack; temporaryTrack.resetCovariance(); - fitSuccess = fitTrack(event, temporaryTrack, mTrkParams[0].NLayers - 1, -1, -1); + fitSuccess = fitTrack(event, temporaryTrack, mTrkParams[0].NLayers - 1, -1, -1, mTrkParams[0].FitIterationMaxChi2[1]); if (!fitSuccess) { continue; } @@ -396,7 +396,7 @@ void Tracker::findTracks(const ROframe& event) #endif } -bool Tracker::fitTrack(const ROframe& event, TrackITSExt& track, int start, int end, int step) +bool Tracker::fitTrack(const ROframe& event, TrackITSExt& track, int start, int end, int step, const float chi2cut) { track.setChi2(0); for (int iLayer{start}; iLayer != end; iLayer += step) { @@ -412,17 +412,34 @@ bool Tracker::fitTrack(const ROframe& event, TrackITSExt& track, int start, int if (!track.propagateTo(trackingHit.xTrackingFrame, getBz())) { return false; } - - track.setChi2(track.getChi2() + - track.getPredictedChi2(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)); + auto predChi2{track.getPredictedChi2(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)}; + if (predChi2 > chi2cut) { + return false; + } + track.setChi2(track.getChi2() + predChi2); if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) { return false; } - const float xx0 = (iLayer > 2) ? 0.008f : 0.003f; // Rough layer thickness - constexpr float radiationLength = 9.36f; // Radiation length of Si [cm] - constexpr float density = 2.33f; // Density of Si [g/cm^3] - if (!track.correctForMaterial(xx0, xx0 * radiationLength * density, true)) { + float xx0 = ((iLayer > 2) ? 0.008f : 0.003f); // Rough layer thickness + float radiationLength = 9.36f; // Radiation length of Si [cm] + float density = 2.33f; // Density of Si [g/cm^3] + float distance = xx0; // Default thickness + + if (mTrkParams[0].UseMatBudLUT) { + if ((iLayer + step) != end) { + const auto cl_0 = mPrimaryVertexContext->getClusters()[iLayer][track.getClusterIndex(iLayer)]; + const auto cl_1 = mPrimaryVertexContext->getClusters()[iLayer + step][track.getClusterIndex(iLayer + step)]; + + distance = std::hypot(cl_0.xCoordinate - cl_1.xCoordinate, cl_0.yCoordinate - cl_1.yCoordinate, cl_0.zCoordinate - cl_1.zCoordinate); + + auto matbud = mMatLayerCylSet->getMatBudget(cl_0.xCoordinate, cl_0.yCoordinate, cl_0.zCoordinate, cl_1.xCoordinate, cl_1.yCoordinate, cl_1.zCoordinate); + xx0 = matbud.meanX2X0; + radiationLength = matbud.length; + density = matbud.meanRho; + } + } + if (!track.correctForMaterial(xx0, ((start < end) ? -1. : 1.) * distance * density, 0.14, false)) { // ~0.14 GeV: mass of charged pion is used by default return false; } } From a487c74504268af5961c5cfe77139d0c0a6ede50 Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Mon, 7 Dec 2020 21:27:55 +0100 Subject: [PATCH 1603/1751] Make load of the LUT optional --- .../ITS/tracking/include/ITStracking/Tracker.h | 5 ++++- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 12 ++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 9e6f29fcafc41..37162676ef71d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -103,7 +103,7 @@ class Tracker std::uint32_t mROFrame = 0; std::vector<TrackITSExt> mTracks; std::vector<MCCompLabel> mTrackLabels; - o2::base::MatLayerCylSet* mMatLayerCylSet; + o2::base::MatLayerCylSet* mMatLayerCylSet = nullptr; o2::gpu::GPUChainITS* mRecoChain = nullptr; }; @@ -111,6 +111,9 @@ inline void Tracker::setParameters(const std::vector<MemoryParameters>& memPars, { mMemParams = memPars; mTrkParams = trkPars; + if (mTrkParams[0].UseMatBudLUT) { + mMatLayerCylSet = o2::base::MatLayerCylSet::loadFromFile(); + } } inline float Tracker::getBz() const diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index ab85bc4837f15..e19952dc1c5ea 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -40,7 +40,6 @@ Tracker::Tracker(o2::its::TrackerTraits* traits) mMemParams.resize(1); assert(traits != nullptr); mTraits = traits; - mMatLayerCylSet = o2::base::MatLayerCylSet::loadFromFile(); mPrimaryVertexContext = mTraits->getPrimaryVertexContext(); } @@ -426,20 +425,21 @@ bool Tracker::fitTrack(const ROframe& event, TrackITSExt& track, int start, int float density = 2.33f; // Density of Si [g/cm^3] float distance = xx0; // Default thickness - if (mTrkParams[0].UseMatBudLUT) { + if (mMatLayerCylSet) { if ((iLayer + step) != end) { const auto cl_0 = mPrimaryVertexContext->getClusters()[iLayer][track.getClusterIndex(iLayer)]; const auto cl_1 = mPrimaryVertexContext->getClusters()[iLayer + step][track.getClusterIndex(iLayer + step)]; - distance = std::hypot(cl_0.xCoordinate - cl_1.xCoordinate, cl_0.yCoordinate - cl_1.yCoordinate, cl_0.zCoordinate - cl_1.zCoordinate); - auto matbud = mMatLayerCylSet->getMatBudget(cl_0.xCoordinate, cl_0.yCoordinate, cl_0.zCoordinate, cl_1.xCoordinate, cl_1.yCoordinate, cl_1.zCoordinate); xx0 = matbud.meanX2X0; - radiationLength = matbud.length; density = matbud.meanRho; + distance = matbud.length; } } - if (!track.correctForMaterial(xx0, ((start < end) ? -1. : 1.) * distance * density, 0.14, false)) { // ~0.14 GeV: mass of charged pion is used by default + // The correctForMaterial should be called with anglecorr==true if the material budget is the "mean budget in vertical direction" and with false if the the estimated budget already accounts for the track inclination. + // Here using !mMatLayerCylSet as its presence triggers update of parameters + + if (!track.correctForMaterial(xx0, ((start < end) ? -1. : 1.) * distance * density, 0.14, !mMatLayerCylSet)) { // ~0.14 GeV: mass of charged pion is used by default return false; } } From c7c204a21b613a811816bdb2fdff3df35b53de71 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 20:24:13 +0100 Subject: [PATCH 1604/1751] GPU: Fix macro name --- .../include/ReconstructionDataFormats/DCA.h | 2 +- .../include/ReconstructionDataFormats/PrimaryVertex.h | 4 ++-- .../include/ReconstructionDataFormats/Vertex.h | 9 ++++++--- DataFormats/Reconstruction/src/DCA.cxx | 4 ++-- DataFormats/Reconstruction/src/PrimaryVertex.cxx | 2 +- DataFormats/Reconstruction/src/Vertex.cxx | 2 +- .../common/include/CommonDataFormat/InteractionRecord.h | 6 +++--- DataFormats/common/src/InteractionRecord.cxx | 2 +- GPU/Common/GPUCommonDef.h | 2 +- 9 files changed, 18 insertions(+), 15 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h index 2b827d5bb740d..ff6c357d4ca9a 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h @@ -16,7 +16,7 @@ #ifndef __OPENCL__ #include <array> #endif -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE #include <iosfwd> #endif diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h index 8d319333a24da..872e7517e8ff6 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h @@ -36,7 +36,7 @@ class PrimaryVertex : public Vertex<TimeStampWithError<float, float>> void setIR(const InteractionRecord& ir) { mIRMin = mIRMax = ir; } bool hasUniqueIR() const { return !mIRMin.isDummy() && (mIRMin == mIRMax); } -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE void print() const; std::string asString() const; #endif @@ -48,7 +48,7 @@ class PrimaryVertex : public Vertex<TimeStampWithError<float, float>> ClassDefNV(PrimaryVertex, 1); }; -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE std::ostream& operator<<(std::ostream& os, const o2::dataformats::PrimaryVertex& v); #endif diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h index 7abcae8423447..f4d798f863868 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h @@ -11,12 +11,15 @@ #ifndef ALICEO2_VERTEX_H #define ALICEO2_VERTEX_H +#include "GPUCommonDef.h" +#include "GPUCommonMath.h" #include <MathUtils/Cartesian.h> + #include "CommonDataFormat/TimeStamp.h" #ifndef __OPENCL__ #include <array> #endif -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE #include <iosfwd> #endif @@ -42,7 +45,7 @@ class VertexBase { } -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE void print() const; std::string asString() const; #endif @@ -144,7 +147,7 @@ class Vertex : public VertexBase ClassDefNV(Vertex, 3); }; -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE std::ostream& operator<<(std::ostream& os, const o2::dataformats::VertexBase& v); #endif diff --git a/DataFormats/Reconstruction/src/DCA.cxx b/DataFormats/Reconstruction/src/DCA.cxx index 925948b2bc127..d840cefc0ccd9 100644 --- a/DataFormats/Reconstruction/src/DCA.cxx +++ b/DataFormats/Reconstruction/src/DCA.cxx @@ -19,7 +19,7 @@ namespace o2 namespace dataformats { -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE std::ostream& operator<<(std::ostream& os, const o2::dataformats::DCA& d) { // stream itself @@ -30,7 +30,7 @@ std::ostream& operator<<(std::ostream& os, const o2::dataformats::DCA& d) void DCA::print() const { -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE std::cout << *this << '\n'; #endif } diff --git a/DataFormats/Reconstruction/src/PrimaryVertex.cxx b/DataFormats/Reconstruction/src/PrimaryVertex.cxx index f94606c2e203a..fb4f7d3b652e5 100644 --- a/DataFormats/Reconstruction/src/PrimaryVertex.cxx +++ b/DataFormats/Reconstruction/src/PrimaryVertex.cxx @@ -18,7 +18,7 @@ namespace o2 namespace dataformats { -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE std::string PrimaryVertex::asString() const { diff --git a/DataFormats/Reconstruction/src/Vertex.cxx b/DataFormats/Reconstruction/src/Vertex.cxx index b6165566e8aa1..f4a98e4223992 100644 --- a/DataFormats/Reconstruction/src/Vertex.cxx +++ b/DataFormats/Reconstruction/src/Vertex.cxx @@ -17,7 +17,7 @@ namespace o2 namespace dataformats { -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE std::string VertexBase::asString() const { diff --git a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h index 841197c2af4ee..7ed2b72b0ccb2 100644 --- a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h +++ b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h @@ -14,7 +14,7 @@ #define ALICEO2_INTERACTIONRECORD_H #include "GPUCommonRtypes.h" -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE #include <iosfwd> #include <cstdint> #endif @@ -246,7 +246,7 @@ struct InteractionRecord { return InteractionRecord(l % o2::constants::lhc::LHCMaxBunches, l / o2::constants::lhc::LHCMaxBunches); } -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE void print() const; std::string asString() const; friend std::ostream& operator<<(std::ostream& stream, InteractionRecord const& ir); @@ -324,7 +324,7 @@ struct InteractionTimeRecord : public InteractionRecord { return !((*this) > other); } -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE void print() const; std::string asString() const; friend std::ostream& operator<<(std::ostream& stream, InteractionTimeRecord const& ir); diff --git a/DataFormats/common/src/InteractionRecord.cxx b/DataFormats/common/src/InteractionRecord.cxx index 4ceb8f957a45c..59962961548b1 100644 --- a/DataFormats/common/src/InteractionRecord.cxx +++ b/DataFormats/common/src/InteractionRecord.cxx @@ -14,7 +14,7 @@ namespace o2 { -#ifndef ALIGPU_GPUCODE +#ifndef GPUCA_ALIGPUCODE std::string InteractionRecord::asString() const { diff --git a/GPU/Common/GPUCommonDef.h b/GPU/Common/GPUCommonDef.h index 1eabbfc6c4b58..3adf1a81c21a8 100644 --- a/GPU/Common/GPUCommonDef.h +++ b/GPU/Common/GPUCommonDef.h @@ -74,7 +74,7 @@ #endif //Set AliRoot / O2 namespace -#if defined(GPUCA_STANDALONE) || (defined(GPUCA_O2_LIB) && !defined(GPUCA_O2_INTERFACE)) || defined(GPUCA_ALIROOT_LIB) || defined(GPUCA_GPULIBRARY) +#if defined(GPUCA_STANDALONE) || (defined(GPUCA_O2_LIB) && !defined(GPUCA_O2_INTERFACE)) || defined(GPUCA_ALIROOT_LIB) || defined(GPUCA_GPULIBRARY) || defined (GPUCA_GPUCODE) #define GPUCA_ALIGPUCODE #endif #ifdef GPUCA_ALIROOT_LIB From 842326871f2d07a887923e41997b87d1deb3c0ab Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 20:31:26 +0100 Subject: [PATCH 1605/1751] GPU: Was missing the GPU annotations for the GPU versions of CartesianND functions... --- .../include/MathUtils/CartesianGPU.h | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/CartesianGPU.h b/Common/MathUtils/include/MathUtils/CartesianGPU.h index 93cc00633dd2d..4ec08e51bc6c2 100644 --- a/Common/MathUtils/include/MathUtils/CartesianGPU.h +++ b/Common/MathUtils/include/MathUtils/CartesianGPU.h @@ -14,6 +14,8 @@ #ifndef ALICEO2_CARTESIANGPU_H #define ALICEO2_CARTESIANGPU_H +#include "GPUCommonDef.h" + namespace o2::math_utils { @@ -21,25 +23,25 @@ namespace detail { template <typename T, int I> struct GPUPoint2D { - GPUPoint2D() = default; - GPUPoint2D(T a, T b) : xx(a), yy(b) {} + GPUdDefault() GPUPoint2D() = default; + GPUd() GPUPoint2D(T a, T b) : xx(a), yy(b) {} + GPUd() float X() const { return xx; } + GPUd() float Y() const { return yy; } + GPUd() float R() const { return o2::gpu::CAMath::Sqrt(xx * xx + yy * yy); } + GPUd() void SetX(float v) { xx = v; } + GPUd() void SetY(float v) { yy = v; } T xx; T yy; - float X() const { return xx; } - float Y() const { return yy; } - float R() const { return o2::gpu::CAMath::Sqrt(xx * xx + yy * yy); } - void SetX(float v) { xx = v; } - void SetY(float v) { yy = v; } }; template <typename T, int I> struct GPUPoint3D : public GPUPoint2D<T, I> { - GPUPoint3D() = default; - GPUPoint3D(T a, T b, T c) : GPUPoint2D<T, I>(a, b), zz(c) {} + GPUdDefault() GPUPoint3D() = default; + GPUd() GPUPoint3D(T a, T b, T c) : GPUPoint2D<T, I>(a, b), zz(c) {} + GPUd() float Z() const { return zz; } + GPUd() float R() const { return o2::gpu::CAMath::Sqrt(GPUPoint2D<T, I>::xx * GPUPoint2D<T, I>::xx + GPUPoint2D<T, I>::yy * GPUPoint2D<T, I>::yy + zz * zz); } + GPUd() void SetZ(float v) { zz = v; } T zz; - float Z() const { return zz; } - float R() const { return o2::gpu::CAMath::Sqrt(GPUPoint2D<T, I>::xx * GPUPoint2D<T, I>::xx + GPUPoint2D<T, I>::yy * GPUPoint2D<T, I>::yy + zz * zz); } - void SetZ(float v) { zz = v; } }; } // namespace detail From 375eaeda89956551d39c6a261ab1887e2d799147 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 20:31:58 +0100 Subject: [PATCH 1606/1751] Make rotateZ / sincos / sector2angle compatible to GPU --- Common/MathUtils/include/MathUtils/Utils.h | 6 +- .../include/MathUtils/detail/CircleXY.h | 9 +- .../include/MathUtils/detail/IntervalXY.h | 109 ++++++++++-------- .../include/MathUtils/detail/trigonometric.h | 46 ++++---- 4 files changed, 91 insertions(+), 79 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index 4b656580d5a5a..0f7b2e16185c8 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -114,17 +114,17 @@ GPUdi() void sincosd(double ang, double& s, double& c) detail::sincos<double>(ang, s, c); } -#ifndef GPUCA_GPUCODE_DEVICE -inline void rotateZ(float xL, float yL, float& xG, float& yG, float snAlp, float csAlp) +GPUdi() void rotateZ(float xL, float yL, float& xG, float& yG, float snAlp, float csAlp) { return detail::rotateZ<float>(xL, yL, xG, yG, snAlp, csAlp); } -inline void rotateZd(double xL, double yL, double& xG, double& yG, double snAlp, double csAlp) +GPUdi() void rotateZd(double xL, double yL, double& xG, double& yG, double snAlp, double csAlp) { return detail::rotateZ<double>(xL, yL, xG, yG, snAlp, csAlp); } +#ifndef GPUCA_GPUCODE_DEVICE inline void rotateZInv(float xG, float yG, float& xL, float& yL, float snAlp, float csAlp) { detail::rotateZInv<float>(xG, yG, xL, yL, snAlp, csAlp); diff --git a/Common/MathUtils/include/MathUtils/detail/CircleXY.h b/Common/MathUtils/include/MathUtils/detail/CircleXY.h index f33f167df68e5..cf740b455441c 100644 --- a/Common/MathUtils/include/MathUtils/detail/CircleXY.h +++ b/Common/MathUtils/include/MathUtils/detail/CircleXY.h @@ -16,6 +16,7 @@ #ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_CIRCLEXY_H_ #define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_CIRCLEXY_H_ +#include "GPUCommonDef.h" #include "GPUCommonRtypes.h" namespace o2 @@ -32,18 +33,18 @@ struct CircleXY { T rC; // circle radius T xC; // x-center T yC; // y-center - CircleXY(T r = T(), T x = T(), T y = T()); - T getCenterD2() const; + GPUd() CircleXY(T r = T(), T x = T(), T y = T()); + GPUd() T getCenterD2() const; ClassDefNV(CircleXY, 2); }; template <typename T> -CircleXY<T>::CircleXY(T r, T x, T y) : rC(std::move(r)), xC(std::move(x)), yC(std::move(y)) +GPUdi() CircleXY<T>::CircleXY(T r, T x, T y) : rC(r), xC(x), yC(y) { } template <typename T> -inline T CircleXY<T>::getCenterD2() const +GPUdi() T CircleXY<T>::getCenterD2() const { return xC * xC + yC * yC; } diff --git a/Common/MathUtils/include/MathUtils/detail/IntervalXY.h b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h index 67d8719a9d3aa..2d77c57f2bb21 100644 --- a/Common/MathUtils/include/MathUtils/detail/IntervalXY.h +++ b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h @@ -16,9 +16,12 @@ #ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_INTERVALXY_H_ #define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_INTERVALXY_H_ +#include "GPUCommonDef.h" #include "GPUCommonRtypes.h" +#ifndef GPUCA_GPUCODE_DEVICE #include <cmath> #include <tuple> +#endif #include "MathUtils/detail/CircleXY.h" @@ -36,30 +39,32 @@ class IntervalXY using value_t = T; ///< 2D interval in lab frame defined by its one edge and signed projection lengths on X,Y axes - IntervalXY(T x = T(), T y = T(), T dx = T(), T dy = T()); - T getX0() const; - T getY0() const; - T& getX0(); - T& getY0(); - T getX1() const; - T getY1() const; - T getDX() const; - T getDY() const; - T& getDX(); - T& getDY(); - - void setX0(T x0); - void setY0(T y0); - void setX1(T x1); - void setY1(T y1); - void setDX(T dx); - void setDY(T dy); - void setEdges(T x0, T y0, T x1, T y1); - - void eval(T t, T& x, T& y) const; + GPUd() IntervalXY(T x = T(), T y = T(), T dx = T(), T dy = T()); + GPUd() T getX0() const; + GPUd() T getY0() const; + GPUd() T& getX0(); + GPUd() T& getY0(); + GPUd() T getX1() const; + GPUd() T getY1() const; + GPUd() T getDX() const; + GPUd() T getDY() const; + GPUd() T& getDX(); + GPUd() T& getDY(); + + GPUd() void setX0(T x0); + GPUd() void setY0(T y0); + GPUd() void setX1(T x1); + GPUd() void setY1(T y1); + GPUd() void setDX(T dx); + GPUd() void setDY(T dy); + GPUd() void setEdges(T x0, T y0, T x1, T y1); + + GPUd() void eval(T t, T& x, T& y) const; +#ifndef GPUCA_GPUCODE_DEVICE std::tuple<T, T> eval(T t) const; +#endif - void getLineCoefs(T& a, T& b, T& c) const; + GPUd() void getLineCoefs(T& a, T& b, T& c) const; /** check if XY interval is seen by the circle. * The tolerance parameter eps is interpreted as a fraction of the interval @@ -69,9 +74,9 @@ class IntervalXY * y = yc + dy*t * with 0<t<1., we acctually check the interval for -eps<t<1+eps */ - bool seenByCircle(const CircleXY<T>& circle, T eps) const; + GPUd() bool seenByCircle(const CircleXY<T>& circle, T eps) const; - bool circleCrossParam(const CircleXY<T>& circle, T& t) const; + GPUd() bool circleCrossParam(const CircleXY<T>& circle, T& t) const; /** * check if XY interval is seen by the line defined by other interval @@ -82,12 +87,12 @@ class IntervalXY * y = yc + dy*t * with 0<t<1., we acctually check the interval for -eps<t<1+eps */ - bool seenByLine(const IntervalXY<T>& other, T eps) const; + GPUd() bool seenByLine(const IntervalXY<T>& other, T eps) const; /** * get crossing parameter of 2 intervals */ - bool lineCrossParam(const IntervalXY<T>& other, T& t) const; + GPUd() bool lineCrossParam(const IntervalXY<T>& other, T& t) const; private: T mX, mY; ///< one of edges @@ -97,100 +102,100 @@ class IntervalXY }; template <typename T> -IntervalXY<T>::IntervalXY(T x, T y, T dx, T dy) : mX(std::move(x)), mY(std::move(y)), mDx(std::move(dx)), mDY(std::move(dy)) +GPUdi() IntervalXY<T>::IntervalXY(T x, T y, T dx, T dy) : mX(x), mY(y), mDx(dx), mDY(dy) { } template <typename T> -inline T IntervalXY<T>::getX0() const +GPUdi() T IntervalXY<T>::getX0() const { return mX; } template <typename T> -inline T IntervalXY<T>::getY0() const +GPUdi() T IntervalXY<T>::getY0() const { return mY; } template <typename T> -inline T& IntervalXY<T>::getX0() +GPUdi() T& IntervalXY<T>::getX0() { return mX; } template <typename T> -inline T& IntervalXY<T>::getY0() +GPUdi() T& IntervalXY<T>::getY0() { return mY; } template <typename T> -inline T IntervalXY<T>::getX1() const +GPUdi() T IntervalXY<T>::getX1() const { return mX + mDx; } template <typename T> -inline T IntervalXY<T>::getY1() const +GPUdi() T IntervalXY<T>::getY1() const { return mY + mDY; } template <typename T> -inline T IntervalXY<T>::getDX() const +GPUdi() T IntervalXY<T>::getDX() const { return mDx; } template <typename T> -inline T IntervalXY<T>::getDY() const +GPUdi() T IntervalXY<T>::getDY() const { return mDY; } template <typename T> -inline T& IntervalXY<T>::getDX() +GPUdi() T& IntervalXY<T>::getDX() { return mDx; } template <typename T> -inline T& IntervalXY<T>::getDY() +GPUdi() T& IntervalXY<T>::getDY() { return mDY; } template <typename T> -inline void IntervalXY<T>::setX0(T x0) +GPUdi() void IntervalXY<T>::setX0(T x0) { mX = x0; } template <typename T> -inline void IntervalXY<T>::setY0(T y0) +GPUdi() void IntervalXY<T>::setY0(T y0) { mY = y0; } template <typename T> -inline void IntervalXY<T>::setX1(T x1) +GPUdi() void IntervalXY<T>::setX1(T x1) { mDx = x1 - mX; } template <typename T> -inline void IntervalXY<T>::setY1(T y1) +GPUdi() void IntervalXY<T>::setY1(T y1) { mDY = y1 - mY; } template <typename T> -inline void IntervalXY<T>::setDX(T dx) +GPUdi() void IntervalXY<T>::setDX(T dx) { mDx = dx; } template <typename T> -inline void IntervalXY<T>::setDY(T dy) +GPUdi() void IntervalXY<T>::setDY(T dy) { mDY = dy; } template <typename T> -inline void IntervalXY<T>::setEdges(T x0, T y0, T x1, T y1) +GPUdi() void IntervalXY<T>::setEdges(T x0, T y0, T x1, T y1) { mX = x0; mY = y0; @@ -198,20 +203,22 @@ inline void IntervalXY<T>::setEdges(T x0, T y0, T x1, T y1) mDY = y1 - y0; } +#ifndef GPUCA_GPUCODE_DEVICE template <typename T> -inline std::tuple<T, T> IntervalXY<T>::eval(T t) const +GPUdi() std::tuple<T, T> IntervalXY<T>::eval(T t) const { return {mX + t * mDx, mY + t * mDY}; } +#endif template <typename T> -inline void IntervalXY<T>::eval(T t, T& x, T& y) const +GPUdi() void IntervalXY<T>::eval(T t, T& x, T& y) const { std::tie(x, y) = eval(t); } template <typename T> -void IntervalXY<T>::getLineCoefs(T& a, T& b, T& c) const +GPUdi() void IntervalXY<T>::getLineCoefs(T& a, T& b, T& c) const { // convert to line parameters in canonical form: a*x+b*y+c = 0 c = mX * mDY - mY * mDx; @@ -230,7 +237,7 @@ void IntervalXY<T>::getLineCoefs(T& a, T& b, T& c) const } template <typename T> -bool IntervalXY<T>::seenByCircle(const CircleXY<T>& circle, T eps) const +GPUdi() bool IntervalXY<T>::seenByCircle(const CircleXY<T>& circle, T eps) const { T dx0 = mX - circle.xC; T dy0 = mY - circle.yC; @@ -251,7 +258,7 @@ bool IntervalXY<T>::seenByCircle(const CircleXY<T>& circle, T eps) const return (d02 - rC2) * (d12 - rC2) < 0; } template <typename T> -bool IntervalXY<T>::circleCrossParam(const CircleXY<T>& circle, T& t) const +GPUdi() bool IntervalXY<T>::circleCrossParam(const CircleXY<T>& circle, T& t) const { const T dx = mX - circle.xC; const T dy = mY - circle.yC; @@ -271,7 +278,7 @@ bool IntervalXY<T>::circleCrossParam(const CircleXY<T>& circle, T& t) const } template <typename T> -bool IntervalXY<T>::seenByLine(const IntervalXY<T>& other, T eps) const +GPUdi() bool IntervalXY<T>::seenByLine(const IntervalXY<T>& other, T eps) const { T a, b, c; // find equation of the line a*x+b*y+c = 0 other.getLineCoefs(a, b, c); @@ -282,7 +289,7 @@ bool IntervalXY<T>::seenByLine(const IntervalXY<T>& other, T eps) const } template <typename T> -bool IntervalXY<T>::lineCrossParam(const IntervalXY<T>& other, T& t) const +GPUdi() bool IntervalXY<T>::lineCrossParam(const IntervalXY<T>& other, T& t) const { // tolerance constexpr float eps = 1.e-9f; diff --git a/Common/MathUtils/include/MathUtils/detail/trigonometric.h b/Common/MathUtils/include/MathUtils/detail/trigonometric.h index aa8a0dc891bb7..36c8eee7e90e4 100644 --- a/Common/MathUtils/include/MathUtils/detail/trigonometric.h +++ b/Common/MathUtils/include/MathUtils/detail/trigonometric.h @@ -16,10 +16,10 @@ #define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_TRIGONOMETRIC_H_ #ifndef GPUCA_GPUCODE_DEVICE -#include <array> #include <cmath> #include <tuple> #endif +#include "GPUCommonArray.h" #include "GPUCommonDef.h" #include "GPUCommonMath.h" #include "CommonConstants/MathConstants.h" @@ -32,7 +32,7 @@ namespace detail { template <typename T> -GPUdi() T to02Pi(T phi) +GPUhdi() T to02Pi(T phi) { T res = phi; // ensure angle in [0:2pi] for the input in [-pi:pi] or [0:pi] @@ -43,7 +43,7 @@ GPUdi() T to02Pi(T phi) } template <typename T> -GPUdi() void bringTo02Pi(T& phi) +GPUhdi() void bringTo02Pi(T& phi) { phi = to02Pi<T>(phi); } @@ -69,7 +69,7 @@ inline void bringTo02PiGen(T& phi) } template <typename T> -inline T toPMPi(T phi) +GPUhdi() T toPMPi(T phi) { T res = phi; // ensure angle in [-pi:pi] for the input in [-pi:pi] or [0:pi] @@ -82,7 +82,7 @@ inline T toPMPi(T phi) } template <typename T> -inline void bringToPMPi(T& phi) +GPUhdi() void bringToPMPi(T& phi) { phi = toPMPi<T>(phi); } @@ -108,13 +108,13 @@ inline void bringToPMPiGen(T& phi) } template <typename T> -GPUdi() void sincos(T ang, GPUgeneric() T& s, GPUgeneric() T& c) +GPUhdi() void sincos(T ang, GPUgeneric() T& s, GPUgeneric() T& c) { return o2::gpu::GPUCommonMath::SinCos(ang, s, c); } template <> -GPUdi() void sincos(double ang, GPUgeneric() double& s, GPUgeneric() double& c) +GPUhdi() void sincos(double ang, GPUgeneric() double& s, GPUgeneric() double& c) { return o2::gpu::GPUCommonMath::SinCosd(ang, s, c); } @@ -138,39 +138,43 @@ inline std::tuple<T, T> rotateZ(T xL, T yL, T snAlp, T csAlp) } template <typename T> -inline std::tuple<T, T> rotateZInv(T xG, T yG, T snAlp, T csAlp) +GPUhdi() std::tuple<T, T> rotateZInv(T xG, T yG, T snAlp, T csAlp) { // inverse 2D rotation of the point by angle alpha (global to local) return rotateZ<T>(xG, yG, -snAlp, csAlp); } -template <typename T> -inline void rotateZ(T xL, T yL, T& xG, T& yG, T snAlp, T csAlp) -{ - std::tie(xG, yG) = rotateZ<T>(xL, yL, snAlp, csAlp); -} +#endif template <typename T> -inline void rotateZ(std::array<T, 3>& xy, T alpha) +GPUhdi() void rotateZ(gpu::gpustd::array<T, 3>& xy, T alpha) { // transforms vector in tracking frame alpha to global frame - auto [sin, cos] = sincos<T>(alpha); + T sin, cos; + sincos<T>(alpha, sin, cos); const T x = xy[0]; xy[0] = x * cos - xy[1] * sin; xy[1] = x * sin + xy[1] * cos; } template <typename T> -inline void rotateZInv(T xG, T yG, T& xL, T& yL, T snAlp, T csAlp) +GPUhdi() void rotateZ(T xL, T yL, T& xG, T& yG, T snAlp, T csAlp) +{ + xG = xL * csAlp - yL * snAlp; + yG = xL * snAlp + yL * csAlp; + ; + // std::tie(xG, yG) = rotateZ<T>(xL, yL, snAlp, csAlp); // must not use std:: - versions on GPU +} + +template <typename T> +GPUhdi() void rotateZInv(T xG, T yG, T& xL, T& yL, T snAlp, T csAlp) { // inverse 2D rotation of the point by angle alpha (global to local) rotateZ<T>(xG, yG, xL, yL, -snAlp, csAlp); } -#endif - template <typename T> -inline int angle2Sector(T phi) +GPUhdi() int angle2Sector(T phi) { // convert angle to sector ID, phi can be either in 0:2pi or -pi:pi convention int sect = phi * o2::constants::math::Rad2Deg / o2::constants::math::SectorSpanDeg; @@ -181,7 +185,7 @@ inline int angle2Sector(T phi) } template <typename T> -inline T sector2Angle(int sect) +GPUhdi() T sector2Angle(int sect) { // convert sector to its angle center, in -pi:pi convention T ang = o2::constants::math::SectorSpanRad * (0.5f + sect); @@ -190,7 +194,7 @@ inline T sector2Angle(int sect) } template <typename T> -inline T angle2Alpha(T phi) +GPUhdi() T angle2Alpha(T phi) { // convert angle to its sector alpha return sector2Angle<T>(angle2Sector<T>(phi)); From 296c38cfd2e871472f43bff6586d3c5fb74e667c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 20:33:44 +0100 Subject: [PATCH 1607/1751] GPU: Add a dummy stream logger implementation for GPU in order not to fail on LOG(...) << ... --- GPU/Common/GPUCommonLogger.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/GPU/Common/GPUCommonLogger.h b/GPU/Common/GPUCommonLogger.h index 6c0c851a1c82c..103d0638f0c53 100644 --- a/GPU/Common/GPUCommonLogger.h +++ b/GPU/Common/GPUCommonLogger.h @@ -20,7 +20,19 @@ #define LOGP(...) #elif defined(GPUCA_GPUCODE_DEVICE) -#define LOG(...) static_assert("LOG(...) << ... unsupported in GPU code"); +#include "GPUCommonDef.h" +namespace o2::gpu::detail +{ +struct DummyLogger { + template <typename... Args> + GPUd() DummyLogger& operator<<(Args... args) + { + return *this; + } +}; +} // namespace o2::gpu::detail +#define LOG(...) o2::gpu::detail::DummyLogger() +//#define LOG(...) static_assert(false, "LOG(...) << ... unsupported in GPU code"); #define LOGF(type, string, ...) \ { \ printf(string "\n", ##__VA_ARGS__); \ From 5d5455e57aa7148d5fbe34d828fdf7494cca81c2 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 20:34:16 +0100 Subject: [PATCH 1608/1751] GPU: Add gpu::gpustd::array to forward std::array on host / mimic as array on GPU --- .../TrackParametrization.h | 14 +++---- .../TrackParametrizationWithError.h | 8 ++-- .../ReconstructionDataFormats/TrackUtils.h | 8 ++-- .../src/TrackParametrization.cxx | 18 ++++----- .../src/TrackParametrizationWithError.cxx | 20 +++++----- GPU/Common/CMakeLists.txt | 1 + GPU/Common/GPUCommonArray.h | 37 +++++++++++++++++++ 7 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 GPU/Common/GPUCommonArray.h diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index d9ffc0be528ce..a1184146c0430 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -28,10 +28,11 @@ #include "GPUCommonDef.h" #include "GPUCommonRtypes.h" #include "GPUCommonMath.h" +#include "GPUCommonArray.h" +#include "GPUROOTCartesianFwd.h" #ifndef __OPENCL__ #include <algorithm> -#include <array> #include <cfloat> #include <cmath> #include <cstring> @@ -50,9 +51,6 @@ #include "ReconstructionDataFormats/TrackUtils.h" -//Forward declarations, since we cannot include the headers if we eventually want to use track.h on GPU -#include "GPUROOTCartesianFwd.h" - namespace o2 { template <typename T> @@ -122,9 +120,9 @@ class TrackParametrization public: using value_t = value_T; - using dim2_t = std::array<value_t, 2>; - using dim3_t = std::array<value_t, 3>; - using params_t = std::array<value_t, kNParams>; + using dim2_t = gpu::gpustd::array<value_t, 2>; + using dim3_t = gpu::gpustd::array<value_t, 3>; + using params_t = gpu::gpustd::array<value_t, kNParams>; static_assert(std::is_floating_point_v<value_t>); @@ -188,7 +186,7 @@ class TrackParametrization math_utils::Point3D<value_t> getXYZGlo() const; void getXYZGlo(dim3_t& xyz) const; bool getPxPyPzGlo(dim3_t& pxyz) const; - bool getPosDirGlo(std::array<value_t, 9>& posdirp) const; + bool getPosDirGlo(gpu::gpustd::array<value_t, 9>& posdirp) const; // methods for track params estimate at other point bool getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index 9910623f25f24..01af5b2cf0cf9 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -37,12 +37,12 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> static_assert(std::is_floating_point_v<value_t>); public: - using covMat_t = std::array<value_t, kCovMatSize>; + using covMat_t = gpu::gpustd::array<value_t, kCovMatSize>; TrackParametrizationWithError(); - TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, const std::array<value_t, kCovMatSize>& cov, int charge = 1); + TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, const covMat_t& cov, int charge = 1); TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, - const std::array<value_t, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); + const gpu::gpustd::array<value_t, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); TrackParametrizationWithError(const TrackParametrizationWithError& src) = default; TrackParametrizationWithError(TrackParametrizationWithError&& src) = default; @@ -70,7 +70,7 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> value_t getCovarElem(int i, int j) const; value_t getDiagError2(int i) const; - bool getCovXYZPxPyPzGlo(std::array<value_t, kLabCovMatSize>& c) const; + bool getCovXYZPxPyPzGlo(gpu::gpustd::array<value_t, kLabCovMatSize>& c) const; void print() const; #ifndef GPUCA_ALIGPUCODE diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h index 1ff1f87489aac..737687b2257bb 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h @@ -17,9 +17,9 @@ #define INCLUDE_RECONSTRUCTIONDATAFORMATS_TRACKUTILS_H_ #include "GPUCommonRtypes.h" +#include "GPUCommonArray.h" #ifndef __OPENCL__ -#include <array> #include <cmath> #endif @@ -33,13 +33,13 @@ namespace track // helper function template <typename value_T = float> value_T BetheBlochSolid(value_T bg, value_T rho = 2.33, value_T kp1 = 0.20, value_T kp2 = 3.00, value_T meanI = 173e-9, - value_T meanZA = 0.49848); + value_T meanZA = 0.49848); template <typename value_T = float> -void g3helx3(value_T qfield, value_T step, std::array<value_T, 7>& vect); +void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect); //____________________________________________________ template <typename value_T> -void g3helx3(value_T qfield, value_T step, std::array<value_T, 7>& vect) +void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect) { /****************************************************************** * * diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index 17fd10838210f..c3a663cc0e84d 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -130,7 +130,7 @@ bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const //____________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getPosDirGlo(std::array<value_t, 9>& posdirp) const +bool TrackParametrization<value_T>::getPosDirGlo(gpu::gpustd::array<value_t, 9>& posdirp) const { // fill vector with lab x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha value_t ptI = std::fabs(getQ2Pt()); @@ -229,7 +229,7 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b step *= std::sqrt(1.f + getTgl() * getTgl()); // // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System - std::array<value_t, 9> vecLab{0.f}; + gpu::gpustd::array<value_t, 9> vecLab{0.f}; if (!getPosDirGlo(vecLab)) { return false; } @@ -248,13 +248,13 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b costet = b[2] / bb; sintet = bt / bb; } - std::array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], - -sinphi * vecLab[0] + cosphi * vecLab[1], - sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], - costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], - -sinphi * vecLab[3] + cosphi * vecLab[4], - sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], - vecLab[6]}; + gpu::gpustd::array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], + -sinphi * vecLab[0] + cosphi * vecLab[1], + sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], + costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], + -sinphi * vecLab[3] + cosphi * vecLab[4], + sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], + vecLab[6]}; // Do the helix step value_t q = getCharge(); diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index f02b78ff2b05a..a52b773b476d4 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -262,7 +262,7 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat //______________________________________________________________ template <typename value_T> TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, - const std::array<value_t, kLabCovMatSize>& cv, int charge, bool sectorAlpha) + const gpu::gpustd::array<value_t, kLabCovMatSize>& cv, int charge, bool sectorAlpha) { // construct track param and covariance from kinematics and lab errors @@ -454,7 +454,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ step *= std::sqrt(1.f + this->getTgl() * this->getTgl()); // // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System - std::array<value_t, 9> vecLab{0.f}; + gpu::gpustd::array<value_t, 9> vecLab{0.f}; if (!this->getPosDirGlo(vecLab)) { return false; } @@ -521,13 +521,13 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ costet = b[2] / bb; sintet = bt / bb; } - std::array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], - -sinphi * vecLab[0] + cosphi * vecLab[1], - sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], - costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], - -sinphi * vecLab[3] + cosphi * vecLab[4], - sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], - vecLab[6]}; + gpu::gpustd::array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2], + -sinphi * vecLab[0] + cosphi * vecLab[1], + sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2], + costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5], + -sinphi * vecLab[3] + cosphi * vecLab[4], + sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5], + vecLab[6]}; // Do the helix step value_t sgn = this->getSign(); @@ -1004,7 +1004,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va //______________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(std::array<value_t, kLabCovMatSize>& cv) const +bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(gpu::gpustd::array<value_t, kLabCovMatSize>& cv) const { //--------------------------------------------------------------------- // This function returns the global covariance matrix of the track params diff --git a/GPU/Common/CMakeLists.txt b/GPU/Common/CMakeLists.txt index f3a8502796a19..57f0f083e9f8f 100644 --- a/GPU/Common/CMakeLists.txt +++ b/GPU/Common/CMakeLists.txt @@ -18,6 +18,7 @@ set(HDRS_INSTALL GPUCommonLogger.h GPUCommonMath.h GPUCommonRtypes.h + GPUCommonArray.h GPUCommonTransform3D.h GPUDef.h GPUDefConstantsAndSettings.h diff --git a/GPU/Common/GPUCommonArray.h b/GPU/Common/GPUCommonArray.h new file mode 100644 index 0000000000000..c70443bfc13a9 --- /dev/null +++ b/GPU/Common/GPUCommonArray.h @@ -0,0 +1,37 @@ +// 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 GPUCommonArray.h +/// \author David Rohr + +#ifndef GPUCOMMONFAIRARRAY_H +#define GPUCOMMONFAIRARRAY_H + +#ifndef GPUCA_GPUCODE_DEVICE +#include <array> +#endif + +#include "GPUCommonDef.h" +namespace o2::gpu::gpustd +{ +#ifdef GPUCA_GPUCODE_DEVICE +template <typename T, size_t N> +struct array { + GPUd() T& operator[](size_t i) { return m_internal_V__[i]; } + GPUd() const T& operator[](size_t i) const { return m_internal_V__[i]; } + T m_internal_V__[N]; +}; +#else +template <typename T, size_t N> +using array = std::array<T, N>; +#endif +} // namespace o2::gpu::gpustd + +#endif From 9e1f3407c502cea666b515e8c04639be15684d54 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 21:22:22 +0100 Subject: [PATCH 1609/1751] Hide all stuff that uses ROOT from GPU compilation --- .../Reconstruction/src/TrackParametrizationWithError.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index a52b773b476d4..23e26b1298122 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -27,10 +27,10 @@ #include "ReconstructionDataFormats/Vertex.h" #include "ReconstructionDataFormats/DCA.h" #include <GPUCommonLogger.h> -#include "Math/SMatrix.h" #ifndef GPUCA_GPUCODE_DEVICE #include <iostream> +#include "Math/SMatrix.h" #endif #ifndef GPUCA_ALIGPUCODE @@ -686,6 +686,8 @@ typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWit return (d * (szz * d - sdz * z) + z * (sdd * z - d * sdz)) / det; } +#ifndef GPUCA_GPUCODE_DEVICE // Disable function relying on ROOT SMatrix on GPU + //______________________________________________ template <typename value_T> void TrackParametrizationWithError<value_T>::buildCombinedCovMatrix(const TrackParametrizationWithError<value_T>& rhs, MatrixDSym5& cov) const @@ -831,6 +833,8 @@ bool TrackParametrizationWithError<value_T>::update(const TrackParametrizationWi return update(rhs, covI); } +#endif + //______________________________________________ template <typename value_T> bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, const dim3_t& cov) From 1476dca803a0ade9fb96d4b65b8e0a62e54cf55d Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 21:25:39 +0100 Subject: [PATCH 1610/1751] Move PID constants from static class member to a namespace, since static constexpr is not supported by GPU --- .../include/ReconstructionDataFormats/PID.h | 105 ++++++++++-------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h index 25f010b20d2e4..ace4dcec33077 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h @@ -24,11 +24,55 @@ namespace track { namespace o2cp = o2::constants::physics; +namespace pid_constants // GPUs currently cannot have static constexpr array members +{ +typedef uint8_t ID; +static constexpr ID NIDsTot = 14; +GPUconstexpr() const char* sNames[NIDsTot + 1] = ///< defined particle names + {"Electron", "Muon", "Pion", "Kaon", "Proton", "Deuteron", "Triton", "He3", "Alpha", + "Pion0", "Photon", "K0", "Lambda", "HyperTriton", + nullptr}; + +GPUconstexpr() const float sMasses[NIDsTot] = ///< defined particle masses + {o2cp::MassElectron, o2cp::MassMuon, o2cp::MassPionCharged, o2cp::MassKaonCharged, + o2cp::MassProton, o2cp::MassDeuteron, o2cp::MassTriton, o2cp::MassHelium3, + o2cp::MassAlpha, o2cp::MassPionNeutral, o2cp::MassPhoton, + o2cp::MassKaonNeutral, o2cp::MassLambda, o2cp::MassHyperTriton}; + +GPUconstexpr() const float sMasses2[NIDsTot] = ///< defined particle masses^2 + {o2cp::MassElectron * o2cp::MassElectron, + o2cp::MassMuon* o2cp::MassMuon, + o2cp::MassPionCharged* o2cp::MassPionCharged, + o2cp::MassKaonCharged* o2cp::MassKaonCharged, + o2cp::MassProton* o2cp::MassProton, + o2cp::MassDeuteron* o2cp::MassDeuteron, + o2cp::MassTriton* o2cp::MassTriton, + o2cp::MassHelium3* o2cp::MassHelium3, + o2cp::MassAlpha* o2cp::MassAlpha, + o2cp::MassPionNeutral* o2cp::MassPionNeutral, + o2cp::MassPhoton* o2cp::MassPhoton, + o2cp::MassKaonNeutral* o2cp::MassKaonNeutral, + o2cp::MassLambda* o2cp::MassLambda, + o2cp::MassHyperTriton* o2cp::MassHyperTriton}; + +GPUconstexpr() const float sMasses2Z[NIDsTot] = ///< defined particle masses / Z + {o2cp::MassElectron, o2cp::MassMuon, + o2cp::MassPionCharged, o2cp::MassKaonCharged, + o2cp::MassProton, o2cp::MassDeuteron, + o2cp::MassTriton, o2cp::MassHelium3 / 2., + o2cp::MassAlpha / 2., + 0, 0, 0, 0, o2cp::MassHyperTriton}; + +GPUconstexpr() const int sCharges[NIDsTot] = ///< defined particle charges + {1, 1, 1, 1, 1, 1, 1, 2, 2, + 0, 0, 0, 0, 1}; +} // namespace pid_constants + class PID { public: // particle identifiers, continuos starting from 0 - typedef uint8_t ID; + typedef pid_constants::ID ID; static constexpr ID Electron = 0; static constexpr ID Muon = 1; @@ -52,7 +96,8 @@ class PID static constexpr ID HyperTriton = 13; static constexpr ID FirstExt = PI0; static constexpr ID LastExt = HyperTriton; - static constexpr ID NIDsTot = LastExt + 1; ///< total number of defined IDs + static constexpr ID NIDsTot = pid_constants::NIDsTot; ///< total number of defined IDs + static_assert(NIDsTot == LastExt + 1, "Incorrect NIDsTot, please update!"); PID() = default; PID(ID id) : mID(id) {} @@ -66,13 +111,18 @@ class PID float getMass() const { return getMass(mID); } float getMass2Z() const { return getMass2Z(mID); } int getCharge() const { return getCharge(mID); } - const char* getName() const { return getName(mID); } - static constexpr const char* getName(ID id) { return sNames[id]; } - static constexpr float getMass(ID id) { return sMasses[id]; } - static constexpr float getMass2(ID id) { return sMasses2[id]; } - static constexpr float getMass2Z(ID id) { return sMasses2Z[id]; } - static constexpr int getCharge(ID id) { return sCharges[id]; } + static float getMass(ID id) { return pid_constants::sMasses[id]; } + static float getMass2(ID id) { return pid_constants::sMasses2[id]; } + static float getMass2Z(ID id) { return pid_constants::sMasses2Z[id]; } + static int getCharge(ID id) { return pid_constants::sCharges[id]; } +#ifndef GPUCA_GPUCODE_DEVICE + const char* getName() const + { + return getName(mID); + } + static const char* getName(ID id) { return pid_constants::sNames[id]; } +#endif private: ID mID = Pion; @@ -88,45 +138,6 @@ class PID return id > LastExt ? id : sameStr(name, sNames[id]) ? id : nameToID(name, id + 1); } - static constexpr const char* sNames[NIDsTot + 1] = ///< defined particle names - {"Electron", "Muon", "Pion", "Kaon", "Proton", "Deuteron", "Triton", "He3", "Alpha", - "Pion0", "Photon", "K0", "Lambda", "HyperTriton", - nullptr}; - - static constexpr const float sMasses[NIDsTot] = ///< defined particle masses - {o2cp::MassElectron, o2cp::MassMuon, o2cp::MassPionCharged, o2cp::MassKaonCharged, - o2cp::MassProton, o2cp::MassDeuteron, o2cp::MassTriton, o2cp::MassHelium3, - o2cp::MassAlpha, o2cp::MassPionNeutral, o2cp::MassPhoton, - o2cp::MassKaonNeutral, o2cp::MassLambda, o2cp::MassHyperTriton}; - - static constexpr const float sMasses2[NIDsTot] = ///< defined particle masses^2 - {o2cp::MassElectron * o2cp::MassElectron, - o2cp::MassMuon* o2cp::MassMuon, - o2cp::MassPionCharged* o2cp::MassPionCharged, - o2cp::MassKaonCharged* o2cp::MassKaonCharged, - o2cp::MassProton* o2cp::MassProton, - o2cp::MassDeuteron* o2cp::MassDeuteron, - o2cp::MassTriton* o2cp::MassTriton, - o2cp::MassHelium3* o2cp::MassHelium3, - o2cp::MassAlpha* o2cp::MassAlpha, - o2cp::MassPionNeutral* o2cp::MassPionNeutral, - o2cp::MassPhoton* o2cp::MassPhoton, - o2cp::MassKaonNeutral* o2cp::MassKaonNeutral, - o2cp::MassLambda* o2cp::MassLambda, - o2cp::MassHyperTriton* o2cp::MassHyperTriton}; - - static constexpr const float sMasses2Z[NIDsTot] = ///< defined particle masses / Z - {o2cp::MassElectron, o2cp::MassMuon, - o2cp::MassPionCharged, o2cp::MassKaonCharged, - o2cp::MassProton, o2cp::MassDeuteron, - o2cp::MassTriton, o2cp::MassHelium3 / 2., - o2cp::MassAlpha / 2., - 0, 0, 0, 0, o2cp::MassHyperTriton}; - - static constexpr const int sCharges[NIDsTot] = ///< defined particle charges - {1, 1, 1, 1, 1, 1, 1, 2, 2, - 0, 0, 0, 0, 1}; - ClassDefNV(PID, 2); }; } // namespace track From ae8838eec8c3148fef407725f69b416251c9ff8f Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 9 Dec 2020 22:56:48 +0100 Subject: [PATCH 1611/1751] GPU: Make TrackPar / TrackParCov compile for GPU --- Common/MathUtils/include/MathUtils/Utils.h | 3 +- .../include/MathUtils/detail/IntervalXY.h | 17 +- .../include/MathUtils/detail/trigonometric.h | 13 +- .../include/ReconstructionDataFormats/DCA.h | 31 +- .../include/ReconstructionDataFormats/PID.h | 41 +-- .../TrackParametrization.h | 298 +++++++++--------- .../TrackParametrizationWithError.h | 154 ++++----- .../ReconstructionDataFormats/TrackUtils.h | 27 +- .../ReconstructionDataFormats/Vertex.h | 106 +++---- DataFormats/Reconstruction/src/DCA.cxx | 4 +- DataFormats/Reconstruction/src/PID.cxx | 5 - .../src/TrackParametrization.cxx | 192 +++++------ .../src/TrackParametrizationWithError.cxx | 206 ++++++------ DataFormats/Reconstruction/src/Vertex.cxx | 2 +- Detectors/Base/src/Propagator.cxx | 2 +- GPU/Common/GPUCommonLogger.h | 16 +- .../Base/GPUReconstructionIncludesDevice.h | 4 + GPU/GPUTracking/Base/cuda/CMakeLists.txt | 1 + GPU/GPUTracking/Base/hip/CMakeLists.txt | 1 + GPU/GPUTracking/Base/opencl2/CMakeLists.txt | 1 + GPU/GPUTracking/Standalone/CMakeLists.txt | 3 + 21 files changed, 580 insertions(+), 547 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index 0f7b2e16185c8..e621226a6614f 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -108,11 +108,12 @@ GPUdi() void sincos(float ang, float& s, float& c) { detail::sincos<float>(ang, s, c); } - +#ifndef __OPENCL__ GPUdi() void sincosd(double ang, double& s, double& c) { detail::sincos<double>(ang, s, c); } +#endif GPUdi() void rotateZ(float xL, float yL, float& xG, float& yG, float snAlp, float csAlp) { diff --git a/Common/MathUtils/include/MathUtils/detail/IntervalXY.h b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h index 2d77c57f2bb21..2a65634ff0778 100644 --- a/Common/MathUtils/include/MathUtils/detail/IntervalXY.h +++ b/Common/MathUtils/include/MathUtils/detail/IntervalXY.h @@ -18,6 +18,7 @@ #include "GPUCommonDef.h" #include "GPUCommonRtypes.h" +#include "GPUCommonMath.h" #ifndef GPUCA_GPUCODE_DEVICE #include <cmath> #include <tuple> @@ -205,7 +206,7 @@ GPUdi() void IntervalXY<T>::setEdges(T x0, T y0, T x1, T y1) #ifndef GPUCA_GPUCODE_DEVICE template <typename T> -GPUdi() std::tuple<T, T> IntervalXY<T>::eval(T t) const +std::tuple<T, T> IntervalXY<T>::eval(T t) const { return {mX + t * mDx, mY + t * mDY}; } @@ -214,7 +215,8 @@ GPUdi() std::tuple<T, T> IntervalXY<T>::eval(T t) const template <typename T> GPUdi() void IntervalXY<T>::eval(T t, T& x, T& y) const { - std::tie(x, y) = eval(t); + x = mX + t * mDx; + y = mY + t * mDY; } template <typename T> @@ -269,11 +271,11 @@ GPUdi() bool IntervalXY<T>::circleCrossParam(const CircleXY<T>& circle, T& t) co if (det < 0.f) { return false; } - det = std::sqrt(det); + det = gpu::CAMath::Sqrt(det); const T t0 = -b - det; const T t1 = -b + det; // select the one closer to [0:1] interval - t = (std::fabs(t0 - 0.5f) < std::fabs(t1 - 0.5f)) ? t0 : t1; + t = (gpu::CAMath::Abs(t0 - 0.5f) < gpu::CAMath::Abs(t1 - 0.5f)) ? t0 : t1; return true; } @@ -282,8 +284,9 @@ GPUdi() bool IntervalXY<T>::seenByLine(const IntervalXY<T>& other, T eps) const { T a, b, c; // find equation of the line a*x+b*y+c = 0 other.getLineCoefs(a, b, c); - const auto [x0, y0] = eval(-eps); - const auto [x1, y1] = eval(1.f + eps); + T x0, y0, x1, y1; + eval(-eps, x0, y0); + eval(1.f + eps, x0, y0); return (a * x0 + b * y0 + c) * (a * x1 + b * y1 + c) < 0; } @@ -296,7 +299,7 @@ GPUdi() bool IntervalXY<T>::lineCrossParam(const IntervalXY<T>& other, T& t) con const T dx = other.getX0() - mX; const T dy = other.getY0() - mY; const T det = -mDx * other.getY0() + mDY * other.getX0(); - if (std::fabs(det) < eps) { + if (gpu::CAMath::Abs(det) < eps) { return false; // parallel } t = (-dx * other.getY0() + dy * other.getX0()) / det; diff --git a/Common/MathUtils/include/MathUtils/detail/trigonometric.h b/Common/MathUtils/include/MathUtils/detail/trigonometric.h index 36c8eee7e90e4..af6eb69274783 100644 --- a/Common/MathUtils/include/MathUtils/detail/trigonometric.h +++ b/Common/MathUtils/include/MathUtils/detail/trigonometric.h @@ -107,17 +107,24 @@ inline void bringToPMPiGen(T& phi) phi = toPMPiGen<T>(phi); } +#ifdef __OPENCL__ // TODO: get rid of that stupid workaround for OpenCL template address spaces template <typename T> -GPUhdi() void sincos(T ang, GPUgeneric() T& s, GPUgeneric() T& c) +GPUhdi() void sincos(T ang, float& s, float& c) +{ + return o2::gpu::GPUCommonMath::SinCos(ang, s, c); +} +#else +template <typename T> +GPUhdi() void sincos(T ang, T& s, T& c) { return o2::gpu::GPUCommonMath::SinCos(ang, s, c); } - template <> -GPUhdi() void sincos(double ang, GPUgeneric() double& s, GPUgeneric() double& c) +GPUhdi() void sincos(double ang, double& s, double& c) { return o2::gpu::GPUCommonMath::SinCosd(ang, s, c); } +#endif #ifndef GPUCA_GPUCODE_DEVICE diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h index ff6c357d4ca9a..ff4167b59fdbb 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h @@ -11,12 +11,11 @@ #ifndef ALICEO2_DCA_H #define ALICEO2_DCA_H +#include "GPUCommonDef.h" #include "GPUCommonRtypes.h" +#include "GPUCommonArray.h" -#ifndef __OPENCL__ -#include <array> -#endif -#ifndef GPUCA_ALIGPUCODE +#ifndef GPUCA_GPUCODE_DEVICE #include <iosfwd> #endif @@ -32,14 +31,14 @@ class DCA { public: - DCA() = default; + GPUdDefault() DCA() = default; - DCA(float y, float z, float syy = 0.f, float syz = 0.f, float szz = 0.f) + GPUd() DCA(float y, float z, float syy = 0.f, float syz = 0.f, float szz = 0.f) { set(y, z, syy, syz, szz); } - void set(float y, float z, float syy, float syz, float szz) + GPUd() void set(float y, float z, float syy, float syz, float szz) { mY = y; mZ = z; @@ -48,30 +47,32 @@ class DCA mCov[2] = szz; } - void set(float y, float z) + GPUd() void set(float y, float z) { mY = y; mZ = z; } - auto getY() const { return mY; } - auto getZ() const { return mZ; } - auto getSigmaY2() const { return mCov[0]; } - auto getSigmaYZ() const { return mCov[1]; } - auto getSigmaZ2() const { return mCov[2]; } - const auto& getCovariance() const { return mCov; } + GPUd() auto getY() const { return mY; } + GPUd() auto getZ() const { return mZ; } + GPUd() auto getSigmaY2() const { return mCov[0]; } + GPUd() auto getSigmaYZ() const { return mCov[1]; } + GPUd() auto getSigmaZ2() const { return mCov[2]; } + GPUd() const auto& getCovariance() const { return mCov; } void print() const; private: float mY = 0.f; float mZ = 0.f; - std::array<float, 3> mCov; ///< s2y, syz, s2z + gpu::gpustd::array<float, 3> mCov; ///< s2y, syz, s2z ClassDefNV(DCA, 1); }; +#ifndef GPUCA_GPUCODE_DEVICE std::ostream& operator<<(std::ostream& os, const DCA& d); +#endif } // namespace dataformats } // namespace o2 diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h index ace4dcec33077..da25dc910e778 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h @@ -15,6 +15,7 @@ #ifndef ALICEO2_track_PID_H_ #define ALICEO2_track_PID_H_ +#include "GPUCommonDef.h" #include "GPUCommonRtypes.h" #include "CommonConstants/PhysicsConstants.h" @@ -99,44 +100,46 @@ class PID static constexpr ID NIDsTot = pid_constants::NIDsTot; ///< total number of defined IDs static_assert(NIDsTot == LastExt + 1, "Incorrect NIDsTot, please update!"); - PID() = default; - PID(ID id) : mID(id) {} - PID(const char* name); - PID(const PID& src) = default; - PID& operator=(const PID& src) = default; + GPUdDefault() PID() = default; + GPUd() PID(ID id) : mID(id) {} + GPUd() PID(const char* name); + GPUdDefault() PID(const PID& src) = default; + GPUdDefault() PID& operator=(const PID& src) = default; - ID getID() const { return mID; } - operator ID() const { return getID(); } + GPUd() ID getID() const { return mID; } + GPUd() operator ID() const { return getID(); } - float getMass() const { return getMass(mID); } - float getMass2Z() const { return getMass2Z(mID); } - int getCharge() const { return getCharge(mID); } + GPUd() float getMass() const { return getMass(mID); } + GPUd() float getMass2Z() const { return getMass2Z(mID); } + GPUd() int getCharge() const { return getCharge(mID); } - static float getMass(ID id) { return pid_constants::sMasses[id]; } - static float getMass2(ID id) { return pid_constants::sMasses2[id]; } - static float getMass2Z(ID id) { return pid_constants::sMasses2Z[id]; } - static int getCharge(ID id) { return pid_constants::sCharges[id]; } + GPUd() static float getMass(ID id) { return pid_constants::sMasses[id]; } + GPUd() static float getMass2(ID id) { return pid_constants::sMasses2[id]; } + GPUd() static float getMass2Z(ID id) { return pid_constants::sMasses2Z[id]; } + GPUd() static int getCharge(ID id) { return pid_constants::sCharges[id]; } #ifndef GPUCA_GPUCODE_DEVICE - const char* getName() const + GPUd() const char* getName() const { return getName(mID); } - static const char* getName(ID id) { return pid_constants::sNames[id]; } + GPUd() static const char* getName(ID id) { return pid_constants::sNames[id]; } #endif private: ID mID = Pion; // are 2 strings equal ? (trick from Giulio) - inline static constexpr bool sameStr(char const* x, char const* y) + GPUdi() static constexpr bool sameStr(char const* x, char const* y) { return !*x && !*y ? true : /* default */ (*x == *y && sameStr(x + 1, y + 1)); } - inline static constexpr ID nameToID(char const* name, ID id) +#ifndef GPUCA_GPUCODE_DEVICE + GPUdi() static constexpr ID nameToID(char const* name, ID id) { - return id > LastExt ? id : sameStr(name, sNames[id]) ? id : nameToID(name, id + 1); + return id > LastExt ? id : sameStr(name, pid_constants::sNames[id]) ? id : nameToID(name, id + 1); } +#endif ClassDefNV(PID, 2); }; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index a1184146c0430..77bd1c372ed80 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -103,14 +103,14 @@ constexpr float kCY2max = 100 * 100, // SigmaY<=100cm kCalcdEdxAuto = -999.f; // value indicating request for dedx calculation // access to covariance matrix by row and column -constexpr int CovarMap[kNParams][kNParams] = {{0, 1, 3, 6, 10}, - {1, 2, 4, 7, 11}, - {3, 4, 5, 8, 12}, - {6, 7, 8, 9, 13}, - {10, 11, 12, 13, 14}}; +GPUconstexpr() int CovarMap[kNParams][kNParams] = {{0, 1, 3, 6, 10}, + {1, 2, 4, 7, 11}, + {3, 4, 5, 8, 12}, + {6, 7, 8, 9, 13}, + {10, 11, 12, 13, 14}}; // access to covariance matrix diagonal elements -constexpr int DiagMap[kNParams] = {0, 2, 5, 9, 14}; +GPUconstexpr() int DiagMap[kNParams] = {0, 2, 5, 9, 14}; constexpr float HugeF = o2::constants::math::VeryBig; @@ -124,100 +124,102 @@ class TrackParametrization using dim3_t = gpu::gpustd::array<value_t, 3>; using params_t = gpu::gpustd::array<value_t, kNParams>; +#ifndef GPUCA_GPUCODE_DEVICE static_assert(std::is_floating_point_v<value_t>); +#endif - TrackParametrization() = default; - TrackParametrization(value_t x, value_t alpha, const params_t& par, int charge = 1); - TrackParametrization(const dim3_t& xyz, const dim3_t& pxpypz, int charge, bool sectorAlpha = true); - TrackParametrization(const TrackParametrization&) = default; - TrackParametrization(TrackParametrization&&) = default; - TrackParametrization& operator=(const TrackParametrization& src) = default; - TrackParametrization& operator=(TrackParametrization&& src) = default; - ~TrackParametrization() = default; - - const value_t* getParams() const; - value_t getParam(int i) const; - value_t getX() const; - value_t getAlpha() const; - value_t getY() const; - value_t getZ() const; - value_t getSnp() const; - value_t getTgl() const; - value_t getQ2Pt() const; - value_t getCharge2Pt() const; - int getAbsCharge() const; - PID getPID() const; - void setPID(const PID pid); + GPUdDefault() TrackParametrization() = default; + GPUd() TrackParametrization(value_t x, value_t alpha, const params_t& par, int charge = 1); + GPUd() TrackParametrization(const dim3_t& xyz, const dim3_t& pxpypz, int charge, bool sectorAlpha = true); + GPUdDefault() TrackParametrization(const TrackParametrization&) = default; + GPUdDefault() TrackParametrization(TrackParametrization&&) = default; + GPUdDefault() TrackParametrization& operator=(const TrackParametrization& src) = default; + GPUdDefault() TrackParametrization& operator=(TrackParametrization&& src) = default; + GPUdDefault() ~TrackParametrization() = default; + + GPUd() const value_t* getParams() const; + GPUd() value_t getParam(int i) const; + GPUd() value_t getX() const; + GPUd() value_t getAlpha() const; + GPUd() value_t getY() const; + GPUd() value_t getZ() const; + GPUd() value_t getSnp() const; + GPUd() value_t getTgl() const; + GPUd() value_t getQ2Pt() const; + GPUd() value_t getCharge2Pt() const; + GPUd() int getAbsCharge() const; + GPUd() PID getPID() const; + GPUd() void setPID(const PID pid); /// calculate cos^2 and cos of track direction in rphi-tracking - value_t getCsp2() const; - value_t getCsp() const; - - void setX(value_t v); - void setParam(value_t v, int i); - void setAlpha(value_t v); - void setY(value_t v); - void setZ(value_t v); - void setSnp(value_t v); - void setTgl(value_t v); - void setQ2Pt(value_t v); - void setAbsCharge(int q); + GPUd() value_t getCsp2() const; + GPUd() value_t getCsp() const; + + GPUd() void setX(value_t v); + GPUd() void setParam(value_t v, int i); + GPUd() void setAlpha(value_t v); + GPUd() void setY(value_t v); + GPUd() void setZ(value_t v); + GPUd() void setSnp(value_t v); + GPUd() void setTgl(value_t v); + GPUd() void setQ2Pt(value_t v); + GPUd() void setAbsCharge(int q); // derived getters - bool getXatLabR(value_t r, value_t& x, value_t bz, DirType dir = DirAuto) const; - void getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY<value_t>& circle) const; - void getCircleParams(value_t bz, o2::math_utils::CircleXY<value_t>& circle, value_t& sna, value_t& csa) const; - void getLineParams(o2::math_utils::IntervalXY<value_t>& line, value_t& sna, value_t& csa) const; - value_t getCurvature(value_t b) const; - int getCharge() const; - int getSign() const; - value_t getPhi() const; - value_t getPhiPos() const; - - value_t getPtInv() const; - value_t getP2Inv() const; - value_t getP2() const; - value_t getPInv() const; - value_t getP() const; - value_t getPt() const; - - value_t getTheta() const; - value_t getEta() const; - math_utils::Point3D<value_t> getXYZGlo() const; - void getXYZGlo(dim3_t& xyz) const; - bool getPxPyPzGlo(dim3_t& pxyz) const; - bool getPosDirGlo(gpu::gpustd::array<value_t, 9>& posdirp) const; + GPUd() bool getXatLabR(value_t r, value_t& x, value_t bz, DirType dir = DirAuto) const; + GPUd() void getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY<value_t>& circle) const; + GPUd() void getCircleParams(value_t bz, o2::math_utils::CircleXY<value_t>& circle, value_t& sna, value_t& csa) const; + GPUd() void getLineParams(o2::math_utils::IntervalXY<value_t>& line, value_t& sna, value_t& csa) const; + GPUd() value_t getCurvature(value_t b) const; + GPUd() int getCharge() const; + GPUd() int getSign() const; + GPUd() value_t getPhi() const; + GPUd() value_t getPhiPos() const; + + GPUd() value_t getPtInv() const; + GPUd() value_t getP2Inv() const; + GPUd() value_t getP2() const; + GPUd() value_t getPInv() const; + GPUd() value_t getP() const; + GPUd() value_t getPt() const; + + GPUd() value_t getTheta() const; + GPUd() value_t getEta() const; + GPUd() math_utils::Point3D<value_t> getXYZGlo() const; + GPUd() void getXYZGlo(dim3_t& xyz) const; + GPUd() bool getPxPyPzGlo(dim3_t& pxyz) const; + GPUd() bool getPosDirGlo(gpu::gpustd::array<value_t, 9>& posdirp) const; // methods for track params estimate at other point - bool getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const; - value_t getZAt(value_t xk, value_t b) const; - value_t getYAt(value_t xk, value_t b) const; - math_utils::Point3D<value_t> getXYZGloAt(value_t xk, value_t b, bool& ok) const; + GPUd() bool getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const; + GPUd() value_t getZAt(value_t xk, value_t b) const; + GPUd() value_t getYAt(value_t xk, value_t b) const; + GPUd() math_utils::Point3D<value_t> getXYZGloAt(value_t xk, value_t b, bool& ok) const; // parameters manipulation - bool correctForELoss(value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); - bool rotateParam(value_t alpha); - bool propagateParamTo(value_t xk, value_t b); - bool propagateParamTo(value_t xk, const dim3_t& b); + GPUd() bool correctForELoss(value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); + GPUd() bool rotateParam(value_t alpha); + GPUd() bool propagateParamTo(value_t xk, value_t b); + GPUd() bool propagateParamTo(value_t xk, const dim3_t& b); - bool propagateParamToDCA(const math_utils::Point3D<value_t>& vtx, value_t b, dim2_t* dca = nullptr, value_t maxD = 999.f); + GPUd() bool propagateParamToDCA(const math_utils::Point3D<value_t>& vtx, value_t b, dim2_t* dca = nullptr, value_t maxD = 999.f); - void invertParam(); + GPUd() void invertParam(); - bool isValid() const; - void invalidate(); + GPUd() bool isValid() const; + GPUd() void invalidate(); - uint16_t getUserField() const; - void setUserField(uint16_t v); + GPUd() uint16_t getUserField() const; + GPUd() void setUserField(uint16_t v); - void printParam() const; + GPUd() void printParam() const; #ifndef GPUCA_ALIGPUCODE std::string asString() const; #endif protected: - void updateParam(value_t delta, int i); - void updateParams(const value_t delta[kNParams]); + GPUd() void updateParam(value_t delta, int i); + GPUd() void updateParams(const value_t delta[kNParams]); private: // @@ -234,100 +236,102 @@ class TrackParametrization //____________________________________________________________ template <typename value_T> -inline TrackParametrization<value_T>::TrackParametrization(value_t x, value_t alpha, const params_t& par, int charge) - : mX{x}, mAlpha{alpha}, mAbsCharge{char(std::abs(charge))} +GPUdi() TrackParametrization<value_T>::TrackParametrization(value_t x, value_t alpha, const params_t& par, int charge) + : mX{x}, mAlpha{alpha}, mAbsCharge{char(gpu::CAMath::Abs(charge))} { // explicit constructor - std::copy(par.begin(), par.end(), mP); + for (int i = 0; i < kNParams; i++) { + mP[i] = par[i]; + } } //____________________________________________________________ template <typename value_T> -inline const typename TrackParametrization<value_T>::value_t* TrackParametrization<value_T>::getParams() const +GPUdi() const typename TrackParametrization<value_T>::value_t* TrackParametrization<value_T>::getParams() const { return mP; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getParam(int i) const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getParam(int i) const { return mP[i]; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getX() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getX() const { return mX; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getAlpha() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getAlpha() const { return mAlpha; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getY() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getY() const { return mP[kY]; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getZ() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getZ() const { return mP[kZ]; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getSnp() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getSnp() const { return mP[kSnp]; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getTgl() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getTgl() const { return mP[kTgl]; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getQ2Pt() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getQ2Pt() const { return mP[kQ2Pt]; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCharge2Pt() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCharge2Pt() const { return mAbsCharge ? mP[kQ2Pt] : 0.f; } //____________________________________________________________ template <typename value_T> -inline int TrackParametrization<value_T>::getAbsCharge() const +GPUdi() int TrackParametrization<value_T>::getAbsCharge() const { return mAbsCharge; } //____________________________________________________________ template <typename value_T> -inline PID TrackParametrization<value_T>::getPID() const +GPUdi() PID TrackParametrization<value_T>::getPID() const { return mPID; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setPID(const PID pid) +GPUdi() void TrackParametrization<value_T>::setPID(const PID pid) { mPID = pid; setAbsCharge(pid.getCharge()); @@ -335,7 +339,7 @@ inline void TrackParametrization<value_T>::setPID(const PID pid) //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp2() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp2() const { const value_t csp2 = (1.f - mP[kSnp]) * (1.f + mP[kSnp]); return csp2 > o2::constants::math::Almost0 ? csp2 : o2::constants::math::Almost0; @@ -343,88 +347,88 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCsp() const { - return std::sqrt(getCsp2()); + return gpu::CAMath::Sqrt(getCsp2()); } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setX(value_t v) +GPUdi() void TrackParametrization<value_T>::setX(value_t v) { mX = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setParam(value_t v, int i) +GPUdi() void TrackParametrization<value_T>::setParam(value_t v, int i) { mP[i] = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setAlpha(value_t v) +GPUdi() void TrackParametrization<value_T>::setAlpha(value_t v) { mAlpha = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setY(value_t v) +GPUdi() void TrackParametrization<value_T>::setY(value_t v) { mP[kY] = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setZ(value_t v) +GPUdi() void TrackParametrization<value_T>::setZ(value_t v) { mP[kZ] = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setSnp(value_t v) +GPUdi() void TrackParametrization<value_T>::setSnp(value_t v) { mP[kSnp] = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setTgl(value_t v) +GPUdi() void TrackParametrization<value_T>::setTgl(value_t v) { mP[kTgl] = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setQ2Pt(value_t v) +GPUdi() void TrackParametrization<value_T>::setQ2Pt(value_t v) { mP[kQ2Pt] = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::setAbsCharge(int q) +GPUdi() void TrackParametrization<value_T>::setAbsCharge(int q) { - mAbsCharge = std::abs(q); + mAbsCharge = gpu::CAMath::Abs(q); } //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY<value_t>& c) const +GPUdi() void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::math_utils::CircleXY<value_t>& c) const { // get circle params in track local frame, for straight line just set to local coordinates c.rC = getCurvature(bz); // treat as straight track if sagitta between the vertex and middle of TPC is below 0.01 cm constexpr value_t MinSagitta = 0.01f, TPCMidR = 160.f, MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR); - if (std::abs(c.rC) > MinCurv) { + if (gpu::CAMath::Abs(c.rC) > MinCurv) { c.rC = 1.f / getCurvature(bz); - value_t sn = getSnp(), cs = std::sqrt((1.f - sn) * (1.f + sn)); + value_t sn = getSnp(), cs = gpu::CAMath::Sqrt((1.f - sn) * (1.f + sn)); c.xC = getX() - sn * c.rC; // center in tracking c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!! - c.rC = std::abs(c.rC); + c.rC = gpu::CAMath::Abs(c.rC); } else { c.rC = 0.f; // signal straight line c.xC = getX(); @@ -434,7 +438,7 @@ inline void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::ma //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_utils::CircleXY<value_t>& c, value_t& sna, value_t& csa) const +GPUdi() void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_utils::CircleXY<value_t>& c, value_t& sna, value_t& csa) const { // get circle params in loc and lab frame, for straight line just set to global coordinates getCircleParamsLoc(bz, c); @@ -444,69 +448,69 @@ inline void TrackParametrization<value_T>::getCircleParams(value_t bz, o2::math_ //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getLineParams(o2::math_utils::IntervalXY<value_t>& ln, value_t& sna, value_t& csa) const +GPUdi() void TrackParametrization<value_T>::getLineParams(o2::math_utils::IntervalXY<value_t>& ln, value_t& sna, value_t& csa) const { // get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t } o2::math_utils::detail::sincos(getAlpha(), sna, csa); o2::math_utils::detail::rotateZ<value_t>(getX(), getY(), ln.getX0(), ln.getY0(), sna, csa); // reference point in global frame - value_t snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + value_t snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); ln.setDX(csp * csa - snp * sna); ln.setDY(snp * csa + csp * sna); } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCurvature(value_t b) const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getCurvature(value_t b) const { return mAbsCharge ? mP[kQ2Pt] * b * o2::constants::math::B2C : 0.; } //____________________________________________________________ template <typename value_T> -inline int TrackParametrization<value_T>::getCharge() const +GPUdi() int TrackParametrization<value_T>::getCharge() const { return getSign() > 0 ? mAbsCharge : -mAbsCharge; } //____________________________________________________________ template <typename value_T> -inline int TrackParametrization<value_T>::getSign() const +GPUdi() int TrackParametrization<value_T>::getSign() const { return mAbsCharge ? (mP[kQ2Pt] > 0.f ? 1 : -1) : 0; } //_______________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhi() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhi() const { // track pt direction phi (in 0:2pi range) - value_t phi = std::asin(getSnp()) + getAlpha(); + value_t phi = gpu::CAMath::ASin(getSnp()) + getAlpha(); math_utils::detail::bringTo02Pi<value_t>(phi); return phi; } //_______________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhiPos() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhiPos() const { // angle of track position (in -pi:pi range) - value_t phi = std::atan2(getY(), getX()) + getAlpha(); + value_t phi = gpu::CAMath::ATan2(getY(), getX()) + getAlpha(); math_utils::detail::bringTo02Pi<value_t>(phi); return phi; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPtInv() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPtInv() const { // return the inverted track pT - const value_t ptInv = std::fabs(mP[kQ2Pt]); + const value_t ptInv = gpu::CAMath::Abs(mP[kQ2Pt]); return (mAbsCharge > 1) ? ptInv / mAbsCharge : ptInv; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2Inv() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2Inv() const { // return the inverted track momentum^2 const value_t p2 = mP[kQ2Pt] * mP[kQ2Pt] / (1.f + getTgl() * getTgl()); @@ -515,7 +519,7 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP2() const { // return the track momentum^2 const value_t p2inv = getP2Inv(); @@ -524,16 +528,16 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPInv() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPInv() const { // return the inverted track momentum^2 - const value_t pInv = std::fabs(mP[kQ2Pt]) / std::sqrt(1.f + getTgl() * getTgl()); + const value_t pInv = gpu::CAMath::Abs(mP[kQ2Pt]) / gpu::CAMath::Sqrt(1.f + getTgl() * getTgl()); return (mAbsCharge > 1) ? pInv / mAbsCharge : pInv; } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getP() const { // return the track momentum const value_t pInv = getPInv(); @@ -542,10 +546,10 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPt() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPt() const { // return the track transverse momentum - value_t ptI = std::fabs(mP[kQ2Pt]); + value_t ptI = gpu::CAMath::Abs(mP[kQ2Pt]); if (mAbsCharge > 1) { ptI /= mAbsCharge; } @@ -554,34 +558,34 @@ inline typename TrackParametrization<value_T>::value_t TrackParametrization<valu //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getTheta() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getTheta() const { - return constants::math::PIHalf - std::atan(mP[3]); + return constants::math::PIHalf - gpu::CAMath::ATan(mP[3]); } //____________________________________________________________ template <typename value_T> -inline typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getEta() const +GPUdi() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getEta() const { - return -std::log(std::tan(0.5f * getTheta())); + return -gpu::CAMath::Log(gpu::CAMath::Tan(0.5f * getTheta())); } //_______________________________________________________ template <typename value_T> -inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGlo() const +GPUdi() math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGlo() const { #ifndef GPUCA_ALIGPUCODE return math_utils::Rotation2D<value_t>(getAlpha())(math_utils::Point3D<value_t>(getX(), getY(), getZ())); #else // mockup on GPU without ROOT float sina, cosa; - o2::gpu::CAMath::SinCos(getAlpha(), sina, cosa); + gpu::CAMath::SinCos(getAlpha(), sina, cosa); return math_utils::Point3D<value_t>(cosa * getX() + sina * getY(), cosa * getY() - sina * getX(), getZ()); #endif } //_______________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const +GPUdi() void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const { // track coordinates in lab frame xyz[0] = getX(); @@ -592,7 +596,7 @@ inline void TrackParametrization<value_T>::getXYZGlo(dim3_t& xyz) const //_______________________________________________________ template <typename value_T> -inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGloAt(value_t xk, value_t b, bool& ok) const +GPUdi() math_utils::Point3D<typename TrackParametrization<value_T>::value_t> TrackParametrization<value_T>::getXYZGloAt(value_t xk, value_t b, bool& ok) const { //---------------------------------------------------------------- // estimate global X,Y,Z in global frame at given X @@ -604,7 +608,7 @@ inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> Trac return math_utils::Rotation2D<value_t>(getAlpha())(math_utils::Point3D<value_t>(xk, y, z)); #else // mockup on GPU without ROOT float sina, cosa; - o2::gpu::CAMath::SinCos(getAlpha(), sina, cosa); + gpu::CAMath::SinCos(getAlpha(), sina, cosa); return math_utils::Point3D<value_t>(cosa * xk + sina * y, cosa * y - sina * xk, z); #endif } else { @@ -614,40 +618,40 @@ inline math_utils::Point3D<typename TrackParametrization<value_T>::value_t> Trac //____________________________________________________________ template <typename value_T> -inline bool TrackParametrization<value_T>::isValid() const +GPUdi() bool TrackParametrization<value_T>::isValid() const { return mX != InvalidX; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::invalidate() +GPUdi() void TrackParametrization<value_T>::invalidate() { mX = InvalidX; } template <typename value_T> -inline uint16_t TrackParametrization<value_T>::getUserField() const +GPUdi() uint16_t TrackParametrization<value_T>::getUserField() const { return mUserField; } template <typename value_T> -inline void TrackParametrization<value_T>::setUserField(uint16_t v) +GPUdi() void TrackParametrization<value_T>::setUserField(uint16_t v) { mUserField = v; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::updateParam(value_t delta, int i) +GPUdi() void TrackParametrization<value_T>::updateParam(value_t delta, int i) { mP[i] += delta; } //____________________________________________________________ template <typename value_T> -inline void TrackParametrization<value_T>::updateParams(const value_t delta[kNParams]) +GPUdi() void TrackParametrization<value_T>::updateParams(const value_t delta[kNParams]) { for (int i = kNParams; i--;) { mP[i] += delta[i]; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index 01af5b2cf0cf9..d6c78eae4f50b 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -34,82 +34,82 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> using typename TrackParametrization<value_T>::dim2_t; using typename TrackParametrization<value_T>::params_t; +#ifndef GPUCA_GPUCODE_DEVICE static_assert(std::is_floating_point_v<value_t>); +#endif public: using covMat_t = gpu::gpustd::array<value_t, kCovMatSize>; - TrackParametrizationWithError(); - TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, const covMat_t& cov, int charge = 1); - TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, + GPUd() TrackParametrizationWithError(); + GPUd() TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, const covMat_t& cov, int charge = 1); + GPUd() TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, const gpu::gpustd::array<value_t, kLabCovMatSize>& cv, int sign, bool sectorAlpha = true); - TrackParametrizationWithError(const TrackParametrizationWithError& src) = default; - TrackParametrizationWithError(TrackParametrizationWithError&& src) = default; - TrackParametrizationWithError& operator=(const TrackParametrizationWithError& src) = default; - TrackParametrizationWithError& operator=(TrackParametrizationWithError&& src) = default; - ~TrackParametrizationWithError() = default; + GPUdDefault() TrackParametrizationWithError(const TrackParametrizationWithError& src) = default; + GPUdDefault() TrackParametrizationWithError(TrackParametrizationWithError&& src) = default; + GPUdDefault() TrackParametrizationWithError& operator=(const TrackParametrizationWithError& src) = default; + GPUdDefault() TrackParametrizationWithError& operator=(TrackParametrizationWithError&& src) = default; + GPUdDefault() ~TrackParametrizationWithError() = default; using TrackParametrization<value_T>::TrackParametrization; - const value_t* getCov() const; - value_t getSigmaY2() const; - value_t getSigmaZY() const; - value_t getSigmaZ2() const; - value_t getSigmaSnpY() const; - value_t getSigmaSnpZ() const; - value_t getSigmaSnp2() const; - value_t getSigmaTglY() const; - value_t getSigmaTglZ() const; - value_t getSigmaTglSnp() const; - value_t getSigmaTgl2() const; - value_t getSigma1PtY() const; - value_t getSigma1PtZ() const; - value_t getSigma1PtSnp() const; - value_t getSigma1PtTgl() const; - value_t getSigma1Pt2() const; - value_t getCovarElem(int i, int j) const; - value_t getDiagError2(int i) const; - - bool getCovXYZPxPyPzGlo(gpu::gpustd::array<value_t, kLabCovMatSize>& c) const; - - void print() const; + GPUd() const value_t* getCov() const; + GPUd() value_t getSigmaY2() const; + GPUd() value_t getSigmaZY() const; + GPUd() value_t getSigmaZ2() const; + GPUd() value_t getSigmaSnpY() const; + GPUd() value_t getSigmaSnpZ() const; + GPUd() value_t getSigmaSnp2() const; + GPUd() value_t getSigmaTglY() const; + GPUd() value_t getSigmaTglZ() const; + GPUd() value_t getSigmaTglSnp() const; + GPUd() value_t getSigmaTgl2() const; + GPUd() value_t getSigma1PtY() const; + GPUd() value_t getSigma1PtZ() const; + GPUd() value_t getSigma1PtSnp() const; + GPUd() value_t getSigma1PtTgl() const; + GPUd() value_t getSigma1Pt2() const; + GPUd() value_t getCovarElem(int i, int j) const; + GPUd() value_t getDiagError2(int i) const; + + GPUd() bool getCovXYZPxPyPzGlo(gpu::gpustd::array<value_t, kLabCovMatSize>& c) const; + + GPUd() void print() const; #ifndef GPUCA_ALIGPUCODE std::string asString() const; #endif // parameters + covmat manipulation - bool rotate(value_t alpha); - bool propagateTo(value_t xk, value_t b); - bool propagateTo(value_t xk, const dim3_t& b); - bool propagateToDCA(const o2::dataformats::VertexBase& vtx, value_t b, o2::dataformats::DCA* dca = nullptr, value_t maxD = 999.f); - void invert(); + GPUd() bool rotate(value_t alpha); + GPUd() bool propagateTo(value_t xk, value_t b); + GPUd() bool propagateTo(value_t xk, const dim3_t& b); + GPUd() bool propagateToDCA(const o2::dataformats::VertexBase& vtx, value_t b, o2::dataformats::DCA* dca = nullptr, value_t maxD = 999.f); + GPUd() void invert(); - value_t getPredictedChi2(const dim2_t& p, const dim3_t& cov) const; + GPUd() value_t getPredictedChi2(const dim2_t& p, const dim3_t& cov) const; template <typename T> - value_t getPredictedChi2(const BaseCluster<T>& p) const; - - value_t getPredictedChi2(const TrackParametrizationWithError& rhs) const; + GPUd() value_t getPredictedChi2(const BaseCluster<T>& p) const; void buildCombinedCovMatrix(const TrackParametrizationWithError& rhs, MatrixDSym5& cov) const; value_t getPredictedChi2(const TrackParametrizationWithError& rhs, MatrixDSym5& covToSet) const; + value_t getPredictedChi2(const TrackParametrizationWithError& rhs) const; bool update(const TrackParametrizationWithError& rhs, const MatrixDSym5& covInv); + bool update(const TrackParametrizationWithError& rhs); - bool update(const dim2_t& p, const dim3_t& cov); + GPUd() bool update(const dim2_t& p, const dim3_t& cov); template <typename T> - bool update(const BaseCluster<T>& p); - - bool update(const TrackParametrizationWithError& rhs); + GPUd() bool update(const BaseCluster<T>& p); - bool correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); + GPUd() bool correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); - void resetCovariance(value_t s2 = 0); - void checkCovariance(); - void setCov(value_t v, int i); + GPUd() void resetCovariance(value_t s2 = 0); + GPUd() void checkCovariance(); + GPUd() void setCov(value_t v, int i); - void updateCov(const value_t delta[kCovMatSize]); - void updateCov(value_t delta, int i); + GPUd() void updateCov(const value_t delta[kCovMatSize]); + GPUd() void updateCov(value_t delta, int i); protected: value_t mC[kCovMatSize] = {0.f}; // 15 covariance matrix elements @@ -119,142 +119,144 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> //__________________________________________________________________________ template <typename value_T> -inline TrackParametrizationWithError<value_T>::TrackParametrizationWithError() : TrackParametrization<value_T>{} +GPUdi() TrackParametrizationWithError<value_T>::TrackParametrizationWithError() : TrackParametrization<value_T>{} { } //__________________________________________________________________________ template <typename value_T> -inline TrackParametrizationWithError<value_T>::TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, - const std::array<value_t, kCovMatSize>& cov, int charge) +GPUdi() TrackParametrizationWithError<value_T>::TrackParametrizationWithError(value_t x, value_t alpha, const params_t& par, + const covMat_t& cov, int charge) : TrackParametrization<value_T>{x, alpha, par, charge} { // explicit constructor - std::copy(cov.begin(), cov.end(), mC); + for (int i = 0; i < kCovMatSize; i++) { + mC[i] = cov[i]; + } } //__________________________________________________________________________ template <typename value_T> -inline const typename TrackParametrizationWithError<value_T>::value_t* TrackParametrizationWithError<value_T>::getCov() const +GPUdi() const typename TrackParametrizationWithError<value_T>::value_t* TrackParametrizationWithError<value_T>::getCov() const { return mC; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaY2() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaY2() const { return mC[kSigY2]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaZY() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaZY() const { return mC[kSigZY]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaZ2() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaZ2() const { return mC[kSigZ2]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnpY() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnpY() const { return mC[kSigSnpY]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnpZ() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnpZ() const { return mC[kSigSnpZ]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnp2() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaSnp2() const { return mC[kSigSnp2]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglY() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglY() const { return mC[kSigTglY]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglZ() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglZ() const { return mC[kSigTglZ]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglSnp() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTglSnp() const { return mC[kSigTglSnp]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTgl2() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigmaTgl2() const { return mC[kSigTgl2]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtY() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtY() const { return mC[kSigQ2PtY]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtZ() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtZ() const { return mC[kSigQ2PtZ]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtSnp() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtSnp() const { return mC[kSigQ2PtSnp]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtTgl() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1PtTgl() const { return mC[kSigQ2PtTgl]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1Pt2() const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getSigma1Pt2() const { return mC[kSigQ2Pt2]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getCovarElem(int i, int j) const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getCovarElem(int i, int j) const { return mC[CovarMap[i][j]]; } //__________________________________________________________________________ template <typename value_T> -inline typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getDiagError2(int i) const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getDiagError2(int i) const { return mC[DiagMap[i]]; } @@ -262,7 +264,7 @@ inline typename TrackParametrizationWithError<value_T>::value_t TrackParametriza //__________________________________________________________________________ template <typename value_T> template <typename T> -typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const BaseCluster<T>& p) const +GPUdi() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const BaseCluster<T>& p) const { const dim2_t pyz = {p.getY(), p.getZ()}; const dim3_t cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; @@ -272,7 +274,7 @@ typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWit //__________________________________________________________________________ template <typename value_T> template <typename T> -bool TrackParametrizationWithError<value_T>::update(const BaseCluster<T>& p) +GPUdi() bool TrackParametrizationWithError<value_T>::update(const BaseCluster<T>& p) { const dim2_t pyz = {p.getY(), p.getZ()}; const dim3_t cov = {p.getSigmaY2(), p.getSigmaYZ(), p.getSigmaZ2()}; @@ -281,21 +283,21 @@ bool TrackParametrizationWithError<value_T>::update(const BaseCluster<T>& p) //__________________________________________________________________________ template <typename value_T> -inline void TrackParametrizationWithError<value_T>::setCov(value_t v, int i) +GPUdi() void TrackParametrizationWithError<value_T>::setCov(value_t v, int i) { mC[i] = v; } //__________________________________________________________________________ template <typename value_T> -inline void TrackParametrizationWithError<value_T>::updateCov(value_t delta, int i) +GPUdi() void TrackParametrizationWithError<value_T>::updateCov(value_t delta, int i) { mC[i] += delta; } //__________________________________________________________________________ template <typename value_T> -inline void TrackParametrizationWithError<value_T>::updateCov(const value_t delta[kCovMatSize]) +GPUdi() void TrackParametrizationWithError<value_T>::updateCov(const value_t delta[kCovMatSize]) { for (int i = kCovMatSize; i--;) { mC[i] += delta[i]; diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h index 737687b2257bb..bfd65642e1b79 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h @@ -32,14 +32,14 @@ namespace track { // helper function template <typename value_T = float> -value_T BetheBlochSolid(value_T bg, value_T rho = 2.33, value_T kp1 = 0.20, value_T kp2 = 3.00, value_T meanI = 173e-9, +GPUd() value_T BetheBlochSolid(value_T bg, value_T rho = 2.33, value_T kp1 = 0.20, value_T kp2 = 3.00, value_T meanI = 173e-9, value_T meanZA = 0.49848); template <typename value_T = float> -void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect); +GPUd() void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect); //____________________________________________________ template <typename value_T> -void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect) +GPUd() void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect) { /****************************************************************** * * @@ -58,8 +58,9 @@ void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect) * vect[7](cm,GeV/c) - input/output x, y, z, px/p, py/p ,pz/p, p * * * ******************************************************************/ - +#ifndef GPUCA_GPUCODE_DEVICE static_assert(std::is_floating_point_v<value_T>); +#endif const int ix = 0, iy = 1, iz = 2, ipx = 3, ipy = 4, ipz = 5, ipp = 6; constexpr value_T kOvSqSix = 0.408248f; // std::sqrt(1./6.); @@ -70,11 +71,11 @@ void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect) value_T tet = rho * step; value_T tsint, sintt, sint, cos1t; - if (std::fabs(tet) > 0.03f) { - sint = std::sin(tet); + if (gpu::CAMath::Abs(tet) > 0.03f) { + sint = gpu::CAMath::Sin(tet); sintt = sint / tet; tsint = (tet - sint) / tet; - value_T t = std::sin(0.5f * tet); + value_T t = gpu::CAMath::Sin(0.5f * tet); cos1t = 2 * t * t / tet; } else { tsint = tet * tet / 6.f; @@ -99,8 +100,8 @@ void g3helx3(value_T qfield, value_T step, gpu::gpustd::array<value_T, 7>& vect) //____________________________________________________ template <typename value_T> -value_T BetheBlochSolid(value_T bg, value_T rho, value_T kp1, value_T kp2, value_T meanI, - value_T meanZA) +GPUd() value_T BetheBlochSolid(value_T bg, value_T rho, value_T kp1, value_T kp2, value_T meanI, + value_T meanZA) { // // This is the parameterization of the Bethe-Bloch formula inspired by Geant. @@ -115,7 +116,9 @@ value_T BetheBlochSolid(value_T bg, value_T rho, value_T kp1, value_T kp2, value // The default values for the kp* parameters are for silicon. // The returned value is in [GeV/(g/cm^2)]. // +#ifndef GPUCA_GPUCODE_DEVICE static_assert(std::is_floating_point_v<value_T>); +#endif constexpr value_T mK = 0.307075e-3f; // [GeV*cm^2/g] constexpr value_T me = 0.511e-3f; // [GeV/c^2] @@ -126,15 +129,15 @@ value_T BetheBlochSolid(value_T bg, value_T rho, value_T kp1, value_T kp2, value //*** Density effect value_T d2 = 0.; - const value_T x = std::log(bg); - const value_T lhwI = std::log(28.816f * 1e-9f * std::sqrt(rho * meanZA) / meanI); + const value_T x = gpu::CAMath::Log(bg); + const value_T lhwI = gpu::CAMath::Log(28.816f * 1e-9f * gpu::CAMath::Sqrt(rho * meanZA) / meanI); if (x > kp2) { d2 = lhwI + x - 0.5f; } else if (x > kp1) { double r = (kp2 - x) / (kp2 - kp1); d2 = lhwI + x - 0.5f + (0.5f - lhwI - kp1) * r * r * r; } - return mK * meanZA * (1 + bg2) / bg2 * (0.5f * std::log(2 * me * bg2 * maxT / (meanI * meanI)) - bg2 / (1 + bg2) - d2); + return mK * meanZA * (1 + bg2) / bg2 * (0.5f * gpu::CAMath::Log(2 * me * bg2 * maxT / (meanI * meanI)) - bg2 / (1 + bg2) - d2); } } // namespace track diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h index f4d798f863868..eb8bf67d5d474 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h @@ -13,13 +13,11 @@ #include "GPUCommonDef.h" #include "GPUCommonMath.h" +#include "GPUCommonArray.h" #include <MathUtils/Cartesian.h> #include "CommonDataFormat/TimeStamp.h" -#ifndef __OPENCL__ -#include <array> -#endif -#ifndef GPUCA_ALIGPUCODE +#ifndef GPUCA_GPUCODE_DEVICE #include <iosfwd> #endif @@ -39,51 +37,51 @@ class VertexBase kCovYZ, kCovZZ }; static constexpr int kNCov = 6; - VertexBase() = default; - ~VertexBase() = default; - VertexBase(const math_utils::Point3D<float>& pos, const std::array<float, kNCov>& cov) : mPos(pos), mCov(cov) + GPUdDefault() VertexBase() = default; + GPUdDefault() ~VertexBase() = default; + GPUd() VertexBase(const math_utils::Point3D<float>& pos, const gpu::gpustd::array<float, kNCov>& cov) : mPos(pos), mCov(cov) { } -#ifndef GPUCA_ALIGPUCODE +#ifndef GPUCA_GPUCODE_DEVICE void print() const; std::string asString() const; #endif // getting the cartesian coordinates and errors - float getX() const { return mPos.X(); } - float getY() const { return mPos.Y(); } - float getZ() const { return mPos.Z(); } - float getSigmaX2() const { return mCov[kCovXX]; } - float getSigmaY2() const { return mCov[kCovYY]; } - float getSigmaZ2() const { return mCov[kCovZZ]; } - float getSigmaXY() const { return mCov[kCovXY]; } - float getSigmaXZ() const { return mCov[kCovXZ]; } - float getSigmaYZ() const { return mCov[kCovYZ]; } - const std::array<float, kNCov>& getCov() const { return mCov; } - - math_utils::Point3D<float> getXYZ() const { return mPos; } - math_utils::Point3D<float>& getXYZ() { return mPos; } - - void setX(float x) { mPos.SetX(x); } - void setY(float y) { mPos.SetY(y); } - void setZ(float z) { mPos.SetZ(z); } - - void setXYZ(float x, float y, float z) + GPUd() float getX() const { return mPos.X(); } + GPUd() float getY() const { return mPos.Y(); } + GPUd() float getZ() const { return mPos.Z(); } + GPUd() float getSigmaX2() const { return mCov[kCovXX]; } + GPUd() float getSigmaY2() const { return mCov[kCovYY]; } + GPUd() float getSigmaZ2() const { return mCov[kCovZZ]; } + GPUd() float getSigmaXY() const { return mCov[kCovXY]; } + GPUd() float getSigmaXZ() const { return mCov[kCovXZ]; } + GPUd() float getSigmaYZ() const { return mCov[kCovYZ]; } + GPUd() const gpu::gpustd::array<float, kNCov>& getCov() const { return mCov; } + + GPUd() math_utils::Point3D<float> getXYZ() const { return mPos; } + GPUd() math_utils::Point3D<float>& getXYZ() { return mPos; } + + GPUd() void setX(float x) { mPos.SetX(x); } + GPUd() void setY(float y) { mPos.SetY(y); } + GPUd() void setZ(float z) { mPos.SetZ(z); } + + GPUd() void setXYZ(float x, float y, float z) { setX(x); setY(y); setZ(z); } - void setPos(const math_utils::Point3D<float>& p) { mPos = p; } - - void setSigmaX2(float v) { mCov[kCovXX] = v; } - void setSigmaY2(float v) { mCov[kCovYY] = v; } - void setSigmaZ2(float v) { mCov[kCovZZ] = v; } - void setSigmaXY(float v) { mCov[kCovXY] = v; } - void setSigmaXZ(float v) { mCov[kCovXZ] = v; } - void setSigmaYZ(float v) { mCov[kCovYZ] = v; } - void setCov(float sxx, float sxy, float syy, float sxz, float syz, float szz) + GPUd() void setPos(const math_utils::Point3D<float>& p) { mPos = p; } + + GPUd() void setSigmaX2(float v) { mCov[kCovXX] = v; } + GPUd() void setSigmaY2(float v) { mCov[kCovYY] = v; } + GPUd() void setSigmaZ2(float v) { mCov[kCovZZ] = v; } + GPUd() void setSigmaXY(float v) { mCov[kCovXY] = v; } + GPUd() void setSigmaXZ(float v) { mCov[kCovXZ] = v; } + GPUd() void setSigmaYZ(float v) { mCov[kCovYZ] = v; } + GPUd() void setCov(float sxx, float sxy, float syy, float sxz, float syz, float szz) { setSigmaX2(sxx); setSigmaY2(syy); @@ -92,11 +90,11 @@ class VertexBase setSigmaXZ(sxz); setSigmaYZ(syz); } - void setCov(const std::array<float, kNCov>& cov) { mCov = cov; } + GPUd() void setCov(const gpu::gpustd::array<float, kNCov>& cov) { mCov = cov; } protected: math_utils::Point3D<float> mPos{0., 0., 0.}; ///< cartesian position - std::array<float, kNCov> mCov{}; ///< errors, see CovElems enum + gpu::gpustd::array<float, kNCov> mCov{}; ///< errors, see CovElems enum ClassDefNV(VertexBase, 1); }; @@ -115,28 +113,28 @@ class Vertex : public VertexBase FlagsMask = 0xffff }; - Vertex() = default; - ~Vertex() = default; - Vertex(const math_utils::Point3D<float>& pos, const std::array<float, kNCov>& cov, ushort nCont, float chi2) + GPUdDefault() Vertex() = default; + GPUdDefault() ~Vertex() = default; + GPUd() Vertex(const math_utils::Point3D<float>& pos, const gpu::gpustd::array<float, kNCov>& cov, ushort nCont, float chi2) : VertexBase(pos, cov), mNContributors(nCont), mChi2(chi2) { } - ushort getNContributors() const { return mNContributors; } - void setNContributors(ushort v) { mNContributors = v; } - void addContributor() { mNContributors++; } + GPUd() ushort getNContributors() const { return mNContributors; } + GPUd() void setNContributors(ushort v) { mNContributors = v; } + GPUd() void addContributor() { mNContributors++; } - ushort getFlags() const { return mBits; } - bool isFlagSet(uint f) const { return mBits & (FlagsMask & f); } - void setFlags(ushort f) { mBits |= FlagsMask & f; } - void resetFrags(ushort f = FlagsMask) { mBits &= ~(FlagsMask & f); } + GPUd() ushort getFlags() const { return mBits; } + GPUd() bool isFlagSet(uint f) const { return mBits & (FlagsMask & f); } + GPUd() void setFlags(ushort f) { mBits |= FlagsMask & f; } + GPUd() void resetFrags(ushort f = FlagsMask) { mBits &= ~(FlagsMask & f); } - void setChi2(float v) { mChi2 = v; } - float getChi2() const { return mChi2; } + GPUd() void setChi2(float v) { mChi2 = v; } + GPUd() float getChi2() const { return mChi2; } - const Stamp& getTimeStamp() const { return mTimeStamp; } - Stamp& getTimeStamp() { return mTimeStamp; } - void setTimeStamp(const Stamp& v) { mTimeStamp = v; } + GPUd() const Stamp& getTimeStamp() const { return mTimeStamp; } + GPUd() Stamp& getTimeStamp() { return mTimeStamp; } + GPUd() void setTimeStamp(const Stamp& v) { mTimeStamp = v; } protected: float mChi2 = 0; ///< chi2 or quality of tracks to vertex attachment @@ -147,7 +145,7 @@ class Vertex : public VertexBase ClassDefNV(Vertex, 3); }; -#ifndef GPUCA_ALIGPUCODE +#ifndef GPUCA_GPUCODE_DEVICE std::ostream& operator<<(std::ostream& os, const o2::dataformats::VertexBase& v); #endif diff --git a/DataFormats/Reconstruction/src/DCA.cxx b/DataFormats/Reconstruction/src/DCA.cxx index d840cefc0ccd9..34d6f714d0feb 100644 --- a/DataFormats/Reconstruction/src/DCA.cxx +++ b/DataFormats/Reconstruction/src/DCA.cxx @@ -19,7 +19,7 @@ namespace o2 namespace dataformats { -#ifndef GPUCA_ALIGPUCODE +#ifndef GPUCA_GPUCODE_DEVICE std::ostream& operator<<(std::ostream& os, const o2::dataformats::DCA& d) { // stream itself @@ -30,7 +30,7 @@ std::ostream& operator<<(std::ostream& os, const o2::dataformats::DCA& d) void DCA::print() const { -#ifndef GPUCA_ALIGPUCODE +#ifndef GPUCA_GPUCODE_DEVICE std::cout << *this << '\n'; #endif } diff --git a/DataFormats/Reconstruction/src/PID.cxx b/DataFormats/Reconstruction/src/PID.cxx index 6b3986de9c7ab..ffe6dab6c778d 100644 --- a/DataFormats/Reconstruction/src/PID.cxx +++ b/DataFormats/Reconstruction/src/PID.cxx @@ -18,11 +18,6 @@ using namespace o2::track; -constexpr const char* PID::sNames[NIDsTot + 1]; -constexpr const float PID::sMasses[NIDsTot]; -constexpr const float PID::sMasses2Z[NIDsTot]; -constexpr const int PID::sCharges[NIDsTot]; - //_______________________________ PID::PID(const char* name) : mID(nameToID(name, First)) { diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index c3a663cc0e84d..d4a9c8ac2da2e 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -26,8 +26,8 @@ #include "ReconstructionDataFormats/TrackParametrization.h" #include "ReconstructionDataFormats/Vertex.h" #include "ReconstructionDataFormats/DCA.h" +#include <MathUtils/Cartesian.h> #include <GPUCommonLogger.h> -#include "Math/SMatrix.h" #ifndef GPUCA_GPUCODE_DEVICE #include <iostream> @@ -37,14 +37,12 @@ #include <fmt/printf.h> #endif -namespace o2 -{ -namespace track -{ +using namespace o2::gpu; +using namespace o2::track; //______________________________________________________________ template <typename value_T> -TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim3_t& pxpypz, int charge, bool sectorAlpha) +GPUd() TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim3_t& pxpypz, int charge, bool sectorAlpha) : mX{0.f}, mAlpha{0.f}, mP{0.f} { // construct track param from kinematics @@ -59,9 +57,9 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; value_t alp = 0; if (sectorAlpha || radPos2 < 1) { - alp = std::atan2(pxpypz[1], pxpypz[0]); + alp = gpu::CAMath::ATan2(pxpypz[1], pxpypz[0]); } else { - alp = std::atan2(xyz[1], xyz[0]); + alp = gpu::CAMath::ATan2(xyz[1], xyz[0]); } if (sectorAlpha) { alp = math_utils::detail::angle2Alpha<value_t>(alp); @@ -70,14 +68,14 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim value_t sn, cs; math_utils::detail::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 - if (std::fabs(sn) < 2 * kSafe) { + if (gpu::CAMath::Abs(sn) < 2 * kSafe) { if (alp > 0) { alp += alp < constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } else { alp += alp > -constants::math::PIHalf ? -2 * kSafe : 2 * kSafe; } math_utils::detail::sincos(alp, sn, cs); - } else if (std::fabs(cs) < 2 * kSafe) { + } else if (gpu::CAMath::Abs(cs) < 2 * kSafe) { if (alp > 0) { alp += alp > constants::math::PIHalf ? 2 * kSafe : -2 * kSafe; } else { @@ -100,12 +98,12 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim mP[kZ] = ver[2]; mP[kSnp] = mom[1] * ptI; mP[kTgl] = mom[2] * ptI; - mAbsCharge = std::abs(charge); + mAbsCharge = gpu::CAMath::Abs(charge); mP[kQ2Pt] = charge ? ptI * charge : ptI; // - if (std::fabs(1 - getSnp()) < kSafe) { + if (gpu::CAMath::Abs(1 - getSnp()) < kSafe) { mP[kSnp] = 1.f - kSafe; // Protection - } else if (std::fabs(-1 - getSnp()) < kSafe) { + } else if (gpu::CAMath::Abs(-1 - getSnp()) < kSafe) { mP[kSnp] = -1.f + kSafe; // Protection } // @@ -113,14 +111,14 @@ TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim //_______________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const +GPUd() bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const { // track momentum - if (std::fabs(getQ2Pt()) < constants::math::Almost0 || std::fabs(getSnp()) > constants::math::Almost1) { + if (gpu::CAMath::Abs(getQ2Pt()) < constants::math::Almost0 || gpu::CAMath::Abs(getSnp()) > constants::math::Almost1) { return false; } value_t cs, sn, pt = getPt(); - value_t r = std::sqrt((1.f - getSnp()) * (1.f + getSnp())); + value_t r = gpu::CAMath::Sqrt((1.f - getSnp()) * (1.f + getSnp())); math_utils::detail::sincos(getAlpha(), sn, cs); pxyz[0] = pt * (r * cs - getSnp() * sn); pxyz[1] = pt * (getSnp() * cs + r * sn); @@ -130,17 +128,17 @@ bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const //____________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getPosDirGlo(gpu::gpustd::array<value_t, 9>& posdirp) const +GPUd() bool TrackParametrization<value_T>::getPosDirGlo(gpu::gpustd::array<value_t, 9>& posdirp) const { // fill vector with lab x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha - value_t ptI = std::fabs(getQ2Pt()); + value_t ptI = gpu::CAMath::Abs(getQ2Pt()); value_t snp = getSnp(); - if (ptI < constants::math::Almost0 || std::fabs(snp) > constants::math::Almost1) { + if (ptI < constants::math::Almost0 || gpu::CAMath::Abs(snp) > constants::math::Almost1) { return false; } value_t &sn = posdirp[7], &cs = posdirp[8]; - value_t csp = std::sqrt((1.f - snp) * (1.f + snp)); - value_t cstht = std::sqrt(1.f + getTgl() * getTgl()); + value_t csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); + value_t cstht = gpu::CAMath::Sqrt(1.f + getTgl() * getTgl()); value_t csthti = 1.f / cstht; math_utils::detail::sincos(getAlpha(), sn, cs); posdirp[0] = getX() * cs - getY() * sn; @@ -155,10 +153,10 @@ bool TrackParametrization<value_T>::getPosDirGlo(gpu::gpustd::array<value_t, 9>& //______________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::rotateParam(value_t alpha) +GPUd() bool TrackParametrization<value_T>::rotateParam(value_t alpha) { // rotate to alpha frame - if (std::fabs(getSnp()) > constants::math::Almost1) { + if (gpu::CAMath::Abs(getSnp()) > constants::math::Almost1) { LOGP(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp()); return false; } @@ -167,7 +165,7 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) // value_t ca = 0, sa = 0; math_utils::detail::sincos(alpha - getAlpha(), sa, ca); - value_t snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision + value_t snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); // Improve precision // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle // direction in local frame is along the X axis if ((csp * ca + snp * sa) < 0) { @@ -176,7 +174,7 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) } // value_t tmp = snp * ca - csp * sa; - if (std::fabs(tmp) > constants::math::Almost1) { + if (gpu::CAMath::Abs(tmp) > constants::math::Almost1) { LOGP(WARNING, "Rotation failed: new snp {:.2f}", tmp); return false; } @@ -190,7 +188,7 @@ bool TrackParametrization<value_T>::rotateParam(value_t alpha) //____________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b) +GPUd() bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b) { //---------------------------------------------------------------- // Extrapolate this track params (w/o cov matrix) to the plane X=xk in the field b[]. @@ -200,11 +198,11 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b //---------------------------------------------------------------- value_t dx = xk - getX(); - if (std::fabs(dx) < constants::math::Almost0) { + if (gpu::CAMath::Abs(dx) < constants::math::Almost0) { return true; } // Do not propagate tracks outside the ALICE detector - if (std::fabs(dx) > 1e5 || std::fabs(getY()) > 1e5 || std::fabs(getZ()) > 1e5) { + if (gpu::CAMath::Abs(dx) > 1e5 || gpu::CAMath::Abs(getY()) > 1e5 || gpu::CAMath::Abs(getZ()) > 1e5) { LOGP(WARNING, "Anomalous track, target X:{:f}", xk); // print(); return false; @@ -212,21 +210,21 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b value_t crv = getCurvature(b[2]); value_t x2r = crv * dx; value_t f1 = getSnp(), f2 = f1 + x2r; - if (std::fabs(f1) > constants::math::Almost1 || std::fabs(f2) > constants::math::Almost1) { + if (gpu::CAMath::Abs(f1) > constants::math::Almost1 || gpu::CAMath::Abs(f2) > constants::math::Almost1) { return false; } - value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (std::fabs(r1) < constants::math::Almost0) { + value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1)); + if (gpu::CAMath::Abs(r1) < constants::math::Almost0) { return false; } - value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (std::fabs(r2) < constants::math::Almost0) { + value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2)); + if (gpu::CAMath::Abs(r2) < constants::math::Almost0) { return false; } value_t dy2dx = (f1 + f2) / (r1 + r2); - value_t step = (std::fabs(x2r) < 0.05f) ? dx * std::fabs(r2 + f2 * dy2dx) // chord - : 2.f * asinf(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc - step *= std::sqrt(1.f + getTgl() * getTgl()); + value_t step = (gpu::CAMath::Abs(x2r) < 0.05f) ? dx * gpu::CAMath::Abs(r2 + f2 * dy2dx) // chord + : 2.f * CAMath::ASin(0.5f * dx * gpu::CAMath::Sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc + step *= gpu::CAMath::Sqrt(1.f + getTgl() * getTgl()); // // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System gpu::gpustd::array<value_t, 9> vecLab{0.f}; @@ -236,13 +234,13 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b // rotate to the system where Bx=By=0. value_t bxy2 = b[0] * b[0] + b[1] * b[1]; - value_t bt = std::sqrt(bxy2); + value_t bt = gpu::CAMath::Sqrt(bxy2); value_t cosphi = 1.f, sinphi = 0.f; if (bt > constants::math::Almost0) { cosphi = b[0] / bt; sinphi = b[1] / bt; } - value_t bb = std::sqrt(bxy2 + b[2] * b[2]); + value_t bb = gpu::CAMath::Sqrt(bxy2 + b[2] * b[2]); value_t costet = 1.f, sintet = 0.f; if (bb > constants::math::Almost0) { costet = b[2] / bb; @@ -280,8 +278,8 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b // Do the final correcting step to the target plane (linear approximation) value_t x = vecLab[0], y = vecLab[1], z = vecLab[2]; - if (std::fabs(dx) > constants::math::Almost0) { - if (std::fabs(vecLab[3]) < constants::math::Almost0) { + if (gpu::CAMath::Abs(dx) > constants::math::Almost0) { + if (gpu::CAMath::Abs(vecLab[3]) < constants::math::Almost0) { return false; } dx = xk - vecLab[0]; @@ -291,7 +289,7 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b } // Calculate the track parameters - t = 1.f / std::sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); + t = 1.f / gpu::CAMath::Sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); mX = x; mP[kY] = y; mP[kZ] = z; @@ -304,7 +302,7 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b //____________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) +GPUd() bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) { //---------------------------------------------------------------- // propagate this track to the plane X=xk (cm) in the field "b" (kG) @@ -312,28 +310,28 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) // distances only (<mm, i.e. misalignment) //---------------------------------------------------------------- value_t dx = xk - getX(); - if (std::fabs(dx) < constants::math::Almost0) { + if (gpu::CAMath::Abs(dx) < constants::math::Almost0) { return true; } - value_t crv = (std::fabs(b) < constants::math::Almost0) ? 0.f : getCurvature(b); + value_t crv = (gpu::CAMath::Abs(b) < constants::math::Almost0) ? 0.f : getCurvature(b); value_t x2r = crv * dx; value_t f1 = getSnp(), f2 = f1 + x2r; - if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { + if ((gpu::CAMath::Abs(f1) > constants::math::Almost1) || (gpu::CAMath::Abs(f2) > constants::math::Almost1)) { return false; } - value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (std::fabs(r1) < constants::math::Almost0) { + value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1)); + if (gpu::CAMath::Abs(r1) < constants::math::Almost0) { return false; } - value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (std::fabs(r2) < constants::math::Almost0) { + value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2)); + if (gpu::CAMath::Abs(r2) < constants::math::Almost0) { return false; } mX = xk; double dy2dx = (f1 + f2) / (r1 + r2); mP[kY] += dx * dy2dx; mP[kSnp] += x2r; - if (std::fabs(x2r) < 0.05f) { + if (gpu::CAMath::Abs(x2r) < 0.05f) { mP[kZ] += dx * (r2 + f2 * dy2dx) * getTgl(); } else { // for small dx/R the linear apporximation of the arc by the segment is OK, @@ -344,7 +342,7 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center // track1 += rot/crv*track3; // - value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. + value_t rot = CAMath::ASin(r1 * f2 - r2 * f1); // more economic version from Yura. if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles if (f2 > 0.f) { rot = constants::math::PI - rot; // @@ -359,32 +357,32 @@ bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b) //_______________________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3D<value_t>& vtx, value_t b, dim2_t* dca, value_t maxD) +GPUd() bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3D<value_t>& vtx, value_t b, dim2_t* dca, value_t maxD) { // propagate track to DCA to the vertex value_t sn, cs, alp = getAlpha(); math_utils::detail::sincos(alp, sn, cs); - value_t x = getX(), y = getY(), snp = getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + value_t x = getX(), y = getY(), snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); value_t xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - value_t d = std::abs(x * snp - y * csp); + value_t d = gpu::CAMath::Abs(x * snp - y * csp); if (d > maxD) { return false; } value_t crv = getCurvature(b); value_t tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1.f - sn) * (1.f + sn)); - cs = (std::abs(tgfv) > constants::math::Almost0) ? sn / tgfv : constants::math::Almost1; + sn = tgfv / gpu::CAMath::Sqrt(1.f + tgfv * tgfv); + cs = gpu::CAMath::Sqrt((1.f - sn) * (1.f + sn)); + cs = (gpu::CAMath::Abs(tgfv) > constants::math::Almost0) ? sn / tgfv : constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; xv = x; auto tmpT(*this); // operate on the copy to recover after the failure - alp += std::asin(sn); + alp += gpu::CAMath::ASin(sn); if (!tmpT.rotateParam(alp) || !tmpT.propagateParamTo(xv, b)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; @@ -401,33 +399,33 @@ bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3 //____________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const +GPUd() bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const { //---------------------------------------------------------------- // estimate Y,Z in tracking frame at given X //---------------------------------------------------------------- value_t dx = xk - getX(); - if (std::fabs(dx) < constants::math::Almost0) { + if (gpu::CAMath::Abs(dx) < constants::math::Almost0) { return true; } value_t crv = getCurvature(b); value_t x2r = crv * dx; value_t f1 = getSnp(), f2 = f1 + x2r; - if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { + if ((gpu::CAMath::Abs(f1) > constants::math::Almost1) || (gpu::CAMath::Abs(f2) > constants::math::Almost1)) { return false; } - value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (std::fabs(r1) < constants::math::Almost0) { + value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1)); + if (gpu::CAMath::Abs(r1) < constants::math::Almost0) { return false; } - value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (std::fabs(r2) < constants::math::Almost0) { + value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2)); + if (gpu::CAMath::Abs(r2) < constants::math::Almost0) { return false; } double dy2dx = (f1 + f2) / (r1 + r2); y = mP[kY] + dx * dy2dx; z = mP[kZ]; - if (std::fabs(x2r) < 0.05f) { + if (gpu::CAMath::Abs(x2r) < 0.05f) { z += dx * (r2 + f2 * dy2dx) * getTgl(); } else { // for small dx/R the linear apporximation of the arc by the segment is OK, @@ -438,7 +436,7 @@ bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, v // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center // track1 += rot/crv*track3; // - value_t rot = asinf(r1 * f2 - r2 * f1); // more economic version from Yura. + value_t rot = CAMath::ASin(r1 * f2 - r2 * f1); // more economic version from Yura. if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles if (f2 > 0.f) { rot = constants::math::PI - rot; // @@ -453,7 +451,7 @@ bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, v //______________________________________________________________ template <typename value_T> -void TrackParametrization<value_T>::invertParam() +GPUd() void TrackParametrization<value_T>::invertParam() { // Transform this track to the local coord. system rotated by 180 deg. mX = -mX; @@ -468,7 +466,7 @@ void TrackParametrization<value_T>::invertParam() //______________________________________________________________ template <typename value_T> -typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getZAt(value_t xk, value_t b) const +GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getZAt(value_t xk, value_t b) const { ///< this method is just an alias for obtaining Z @ X in the tree->Draw() value_t y, z; @@ -477,7 +475,7 @@ typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::g //______________________________________________________________ template <typename value_T> -typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getYAt(value_t xk, value_t b) const +GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getYAt(value_t xk, value_t b) const { ///< this method is just an alias for obtaining Z @ X in the tree->Draw() value_t y, z; @@ -497,7 +495,7 @@ std::string TrackParametrization<value_T>::asString() const //______________________________________________________________ template <typename value_T> -void TrackParametrization<value_T>::printParam() const +GPUd() void TrackParametrization<value_T>::printParam() const { // print parameters #ifndef GPUCA_ALIGPUCODE @@ -507,7 +505,7 @@ void TrackParametrization<value_T>::printParam() const //______________________________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz, track::DirType dir) const +GPUd() bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz, track::DirType dir) const { // Get local X of the track position estimated at the radius lab radius r. // The track curvature is accounted exactly @@ -521,16 +519,16 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz const value_t kEps = 1.e-6; // auto crv = getCurvature(bz); - if (std::fabs(crv) > constants::math::Almost0) { // helix + if (gpu::CAMath::Abs(crv) > constants::math::Almost0) { // helix // get center of the track circle math_utils::CircleXY<value_t> circle; getCircleParamsLoc(bz, circle); - value_t r0 = std::sqrt(circle.getCenterD2()); + value_t r0 = gpu::CAMath::Sqrt(circle.getCenterD2()); if (r0 <= constants::math::Almost0) { return false; // the track is concentric to circle } value_t tR2r0 = 1.f, g = 0.f, tmp = 0.f; - if (std::fabs(circle.rC - r0) > kEps) { + if (gpu::CAMath::Abs(circle.rC - r0) > kEps) { tR2r0 = circle.rC / r0; g = 0.5f * (r * r / (r0 * circle.rC) - tR2r0 - 1.f / tR2r0); tmp = 1.f + g * tR2r0; @@ -543,7 +541,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz if (det < 0.f) { return false; // does not reach raduis r } - det = std::sqrt(det); + det = gpu::CAMath::Sqrt(det); // // the intersection happens in 2 points: {circle.xC+tR*C,circle.yC+tR*S} // with C=f*c0+-|s0|*det and S=f*s0-+c0 sign(s0)*det @@ -551,8 +549,8 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz // x = circle.xC * tmp; value_t y = circle.yC * tmp; - if (std::fabs(circle.yC) > constants::math::Almost0) { // when circle.yC==0 the x,y is unique - value_t dfx = tR2r0 * std::fabs(circle.yC) * det; + if (gpu::CAMath::Abs(circle.yC) > constants::math::Almost0) { // when circle.yC==0 the x,y is unique + value_t dfx = tR2r0 * gpu::CAMath::Abs(circle.yC) * det; value_t dfy = tR2r0 * circle.xC * (circle.yC > 0.f ? det : -det); if (dir == DirAuto) { // chose the one which corresponds to smallest step value_t delta = (x - mX) * dfx - (y - fy) * dfy; // the choice of + in C will lead to smaller step if delta<0 @@ -563,7 +561,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz if (dfeps < -kEps) { return true; } - if (std::fabs(dfeps) < kEps && std::fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? + if (gpu::CAMath::Abs(dfeps) < kEps && gpu::CAMath::Abs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? return mX; } x += dfx + dfx; @@ -580,7 +578,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz if (dfeps < -kEps) { return true; } - if (std::fabs(dfeps) < kEps && std::fabs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? + if (gpu::CAMath::Abs(dfeps) < kEps && gpu::CAMath::Abs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r? return mX; } x -= dfx + dfx; @@ -598,8 +596,8 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz return false; } } - } else { // this is a straight track - if (std::fabs(sn) >= constants::math::Almost1) { // || to Y axis + } else { // this is a straight track + if (gpu::CAMath::Abs(sn) >= constants::math::Almost1) { // || to Y axis value_t det = (r - mX) * (r + mX); if (det < 0.f) { return false; // does not reach raduis r @@ -608,7 +606,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz if (dir == DirAuto) { return true; } - det = std::sqrt(det); + det = gpu::CAMath::Sqrt(det); if (dir == DirOutward) { // along the track direction if (sn > 0.f) { if (fy > det) { @@ -628,12 +626,12 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz return false; // track is against Y axis } } - } else if (std::fabs(sn) <= constants::math::Almost0) { // || to X axis + } else if (gpu::CAMath::Abs(sn) <= constants::math::Almost0) { // || to X axis value_t det = (r - fy) * (r + fy); if (det < 0.f) { return false; // does not reach raduis r } - det = std::sqrt(det); + det = gpu::CAMath::Sqrt(det); if (dir == DirAuto) { x = mX > 0.f ? det : -det; // choose the solution requiring the smalest step return true; @@ -651,13 +649,13 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz } } } else { // general case of straight line - value_t cs = std::sqrt((1.f - sn) * (1.f + sn)); + value_t cs = gpu::CAMath::Sqrt((1.f - sn) * (1.f + sn)); value_t xsyc = mX * sn - fy * cs; value_t det = (r - xsyc) * (r + xsyc); if (det < 0.f) { return false; // does not reach raduis r } - det = std::sqrt(det); + det = gpu::CAMath::Sqrt(det); value_t xcys = mX * cs + fy * sn; value_t t = -xcys; if (dir == DirAuto) { @@ -684,7 +682,7 @@ bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz //______________________________________________ template <typename value_T> -bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, bool anglecorr, value_t dedx) +GPUd() bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, bool anglecorr, value_t dedx) { //------------------------------------------------------------------ // This function corrects the track parameters for the energy loss in crossed material. @@ -702,7 +700,7 @@ bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, if (anglecorr) { value_t csp2 = (1.f - getSnp()) * (1.f + getSnp()); // cos(phi)^2 value_t cst2I = (1.f + getTgl() * getTgl()); // 1/cos(lambda)^2 - value_t angle = std::sqrt(cst2I / (csp2)); + value_t angle = gpu::CAMath::Sqrt(cst2I / (csp2)); xrho *= angle; } @@ -717,15 +715,15 @@ bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, // Calculating the energy loss corrections************************ if ((xrho != 0.f) && (beta2 < 1.f)) { if (dedx < kCalcdEdxAuto + constants::math::Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / std::fabs(mass)); + dedx = BetheBlochSolid(p / gpu::CAMath::Abs(mass)); if (mAbsCharge != 1) { dedx *= mAbsCharge * mAbsCharge; } } value_t dE = dedx * xrho; - value_t e = std::sqrt(e2); - if (std::fabs(dE) > kMaxELossFrac * e) { + value_t e = gpu::CAMath::Sqrt(e2); + if (gpu::CAMath::Abs(dE) > kMaxELossFrac * e) { return false; // 30% energy loss is too much! } value_t eupd = e + dE; @@ -733,14 +731,16 @@ bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, if (pupd2 < kMinP * kMinP) { return false; } - setQ2Pt(getQ2Pt() * p / std::sqrt(pupd2)); + setQ2Pt(getQ2Pt() * p / gpu::CAMath::Sqrt(pupd2)); } return true; } +namespace o2::track +{ template class TrackParametrization<float>; +#ifndef GPUCA_GPUCODE_DEVICE template class TrackParametrization<double>; - -} // namespace track -} // namespace o2 +#endif +} // namespace o2::track diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index 23e26b1298122..fd0e20c0f9f01 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -37,14 +37,12 @@ #include <fmt/printf.h> #endif -namespace o2 -{ -namespace track -{ +using namespace o2::track; +using namespace o2::gpu; //______________________________________________________________ template <typename value_T> -void TrackParametrizationWithError<value_T>::invert() +GPUd() void TrackParametrizationWithError<value_T>::invert() { // Transform this track to the local coord. system rotated by 180 deg. this->invertParam(); @@ -59,27 +57,27 @@ void TrackParametrizationWithError<value_T>::invert() //______________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) +GPUd() bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) { //---------------------------------------------------------------- // propagate this track to the plane X=xk (cm) in the field "b" (kG) //---------------------------------------------------------------- value_t dx = xk - this->getX(); - if (std::fabs(dx) < constants::math::Almost0) { + if (gpu::CAMath::Abs(dx) < constants::math::Almost0) { return true; } value_t crv = this->getCurvature(b); value_t x2r = crv * dx; value_t f1 = this->getSnp(), f2 = f1 + x2r; - if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { + if ((gpu::CAMath::Abs(f1) > constants::math::Almost1) || (gpu::CAMath::Abs(f2) > constants::math::Almost1)) { return false; } - value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (std::fabs(r1) < constants::math::Almost0) { + value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1)); + if (gpu::CAMath::Abs(r1) < constants::math::Almost0) { return false; } - value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (std::fabs(r2) < constants::math::Almost0) { + value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2)); + if (gpu::CAMath::Abs(r2) < constants::math::Almost0) { return false; } this->setX(xk); @@ -87,7 +85,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) value_t dP[kNParams] = {0.f}; dP[kY] = dx * dy2dx; dP[kSnp] = x2r; - if (std::fabs(x2r) < 0.05f) { + if (gpu::CAMath::Abs(x2r) < 0.05f) { dP[kZ] = dx * (r2 + f2 * dy2dx) * this->getTgl(); } else { // for small dx/R the linear apporximation of the arc by the segment is OK, @@ -98,7 +96,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center // mP1 += rot/crv*mP3; // - value_t rot = std::asin(r1 * f2 - r2 * f1); // more economic version from Yura. + value_t rot = gpu::CAMath::ASin(r1 * f2 - r2 * f1); // more economic version from Yura. if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles if (f2 > 0.f) { rot = constants::math::PI - rot; // @@ -164,10 +162,10 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, value_t b) //______________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) +GPUd() bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) { // rotate to alpha frame - if (std::fabs(this->getSnp()) > constants::math::Almost1) { + if (gpu::CAMath::Abs(this->getSnp()) > constants::math::Almost1) { LOGP(WARNING, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", this->getSnp()); return false; } @@ -176,7 +174,7 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) // value_t ca = 0, sa = 0; math_utils::detail::sincos(alpha - this->getAlpha(), sa, ca); - value_t snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); // Improve precision + value_t snp = this->getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); // Improve precision // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle // direction in local frame is along the X axis if ((csp * ca + snp * sa) < 0) { @@ -186,7 +184,7 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) // value_t updSnp = snp * ca - csp * sa; - if (std::fabs(updSnp) > constants::math::Almost1) { + if (gpu::CAMath::Abs(updSnp) > constants::math::Almost1) { LOGP(WARNING, "Rotation failed: new snp {:.2f}", updSnp); return false; } @@ -196,7 +194,7 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) this->setY(-xold * sa + yold * ca); this->setSnp(updSnp); - if (std::fabs(csp) < constants::math::Almost0) { + if (gpu::CAMath::Abs(csp) < constants::math::Almost0) { LOGP(WARNING, "Too small cosine value {:f}", csp); csp = constants::math::Almost0; } @@ -219,32 +217,32 @@ bool TrackParametrizationWithError<value_T>::rotate(value_t alpha) //_______________________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformats::VertexBase& vtx, value_t b, o2::dataformats::DCA* dca, value_t maxD) +GPUd() bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformats::VertexBase& vtx, value_t b, o2::dataformats::DCA* dca, value_t maxD) { // propagate track to DCA to the vertex value_t sn, cs, alp = this->getAlpha(); o2::math_utils::detail::sincos(alp, sn, cs); - value_t x = this->getX(), y = this->getY(), snp = this->getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + value_t x = this->getX(), y = this->getY(), snp = this->getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); value_t xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - value_t d = std::abs(x * snp - y * csp); + value_t d = gpu::CAMath::Abs(x * snp - y * csp); if (d > maxD) { return false; } value_t crv = this->getCurvature(b); value_t tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1.f - sn) * (1.f + sn)); - cs = (std::abs(tgfv) > constants::math::Almost0) ? sn / tgfv : constants::math::Almost1; + sn = tgfv / gpu::CAMath::Sqrt(1.f + tgfv * tgfv); + cs = gpu::CAMath::Sqrt((1.f - sn) * (1.f + sn)); + cs = (gpu::CAMath::Abs(tgfv) > constants::math::Almost0) ? sn / tgfv : constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; xv = x; auto tmpT(*this); // operate on the copy to recover after the failure - alp += std::asin(sn); + alp += gpu::CAMath::ASin(sn); if (!tmpT.rotate(alp) || !tmpT.propagateTo(xv, b)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); @@ -261,7 +259,7 @@ bool TrackParametrizationWithError<value_T>::propagateToDCA(const o2::dataformat //______________________________________________________________ template <typename value_T> -TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, +GPUd() TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3_t& xyz, const dim3_t& pxpypz, const gpu::gpustd::array<value_t, kLabCovMatSize>& cv, int charge, bool sectorAlpha) { // construct track param and covariance from kinematics and lab errors @@ -276,9 +274,9 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1]; value_t alp = 0; if (sectorAlpha || radPos2 < 1) { - alp = std::atan2(pxpypz[1], pxpypz[0]); + alp = gpu::CAMath::ATan2(pxpypz[1], pxpypz[0]); } else { - alp = std::atan2(xyz[1], xyz[0]); + alp = gpu::CAMath::ATan2(xyz[1], xyz[0]); } if (sectorAlpha) { alp = math_utils::detail::angle2Alpha<value_t>(alp); @@ -287,14 +285,14 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 value_t sn, cs; math_utils::detail::sincos(alp, sn, cs); // protection: avoid alpha being too close to 0 or +-pi/2 - if (std::fabs(sn) < 2.f * kSafe) { + if (gpu::CAMath::Abs(sn) < 2.f * kSafe) { if (alp > 0) { alp += alp < constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } else { alp += alp > -constants::math::PIHalf ? -2.f * kSafe : 2.f * kSafe; } math_utils::detail::sincos(alp, sn, cs); - } else if (std::fabs(cs) < 2.f * kSafe) { + } else if (gpu::CAMath::Abs(cs) < 2.f * kSafe) { if (alp > 0) { alp += alp > constants::math::PIHalf ? 2.f * kSafe : -2.f * kSafe; } else { @@ -310,7 +308,7 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 math_utils::detail::rotateZ<value_t>(ver, -alp); math_utils::detail::rotateZ<value_t>(mom, -alp); // - value_t pt = std::sqrt(mom[0] * mom[0] + mom[1] * mom[1]); + value_t pt = gpu::CAMath::Sqrt(mom[0] * mom[0] + mom[1] * mom[1]); value_t ptI = 1.f / pt; this->setX(ver[0]); this->setAlpha(alp); @@ -318,25 +316,25 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 this->setZ(ver[2]); this->setSnp(mom[1] * ptI); // cos(phi) this->setTgl(mom[2] * ptI); // tg(lambda) - this->setAbsCharge(std::abs(charge)); + this->setAbsCharge(gpu::CAMath::Abs(charge)); this->setQ2Pt(charge ? ptI * charge : ptI); // - if (std::fabs(1.f - this->getSnp()) < kSafe) { + if (gpu::CAMath::Abs(1.f - this->getSnp()) < kSafe) { this->setSnp(1.f - kSafe); // Protection - } else if (std::fabs(-1.f - this->getSnp()) < kSafe) { + } else if (gpu::CAMath::Abs(-1.f - this->getSnp()) < kSafe) { this->setSnp(-1.f + kSafe); // Protection } // // Covariance matrix (formulas to be simplified) value_t r = mom[0] * ptI; // cos(phi) - value_t cv34 = std::sqrt(cv[3] * cv[3] + cv[4] * cv[4]); + value_t cv34 = gpu::CAMath::Sqrt(cv[3] * cv[3] + cv[4] * cv[4]); // int special = 0; value_t sgcheck = r * sn + this->getSnp() * cs; - if (std::fabs(sgcheck) > 1 - kSafe) { // special case: lab phi is +-pi/2 + if (gpu::CAMath::Abs(sgcheck) > 1 - kSafe) { // special case: lab phi is +-pi/2 special = 1; sgcheck = sgcheck < 0 ? -1.f : 1.f; - } else if (std::fabs(sgcheck) < kSafe) { + } else if (gpu::CAMath::Abs(sgcheck) < kSafe) { sgcheck = cs < 0 ? -1.0f : 1.0f; special = 2; // special case: lab phi is 0 } @@ -350,29 +348,29 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 if (special == 1) { mC[kSigSnpY] = cv[6] * ptI; mC[kSigSnpZ] = -sgcheck * cv[8] * r * ptI; - mC[kSigSnp2] = std::fabs(cv[9] * r * r * ptI2); + mC[kSigSnp2] = gpu::CAMath::Abs(cv[9] * r * r * ptI2); mC[kSigTglY] = (cv[10] * this->getTgl() - sgcheck * cv[15]) * ptI / r; mC[kSigTglZ] = (cv[17] - sgcheck * cv[12] * this->getTgl()) * ptI; mC[kSigTglSnp] = (-sgcheck * cv[18] + cv[13] * this->getTgl()) * r * ptI2; - mC[kSigTgl2] = std::fabs(cv[20] - 2 * sgcheck * cv[19] * mC[4] + cv[14] * tgl2) * ptI2; + mC[kSigTgl2] = gpu::CAMath::Abs(cv[20] - 2 * sgcheck * cv[19] * mC[4] + cv[14] * tgl2) * ptI2; mC[kSigQ2PtY] = cv[10] * ptI2 / r * charge; mC[kSigQ2PtZ] = -sgcheck * cv[12] * ptI2 * charge; mC[kSigQ2PtSnp] = cv[13] * r * ptI * ptI2 * charge; mC[kSigQ2PtTgl] = (-sgcheck * cv[19] + cv[14] * this->getTgl()) * r * ptI2 * ptI; - mC[kSigQ2Pt2] = std::fabs(cv[14] * ptI2 * ptI2); + mC[kSigQ2Pt2] = gpu::CAMath::Abs(cv[14] * ptI2 * ptI2); } else if (special == 2) { mC[kSigSnpY] = -cv[10] * ptI * cs / sn; mC[kSigSnpZ] = cv[12] * cs * ptI; - mC[kSigSnp2] = std::fabs(cv[14] * cs * cs * ptI2); + mC[kSigSnp2] = gpu::CAMath::Abs(cv[14] * cs * cs * ptI2); mC[kSigTglY] = (sgcheck * cv[6] * this->getTgl() - cv[15]) * ptI / sn; mC[kSigTglZ] = (cv[17] - sgcheck * cv[8] * this->getTgl()) * ptI; mC[kSigTglSnp] = (cv[19] - sgcheck * cv[13] * this->getTgl()) * cs * ptI2; - mC[kSigTgl2] = std::fabs(cv[20] - 2 * sgcheck * cv[18] * this->getTgl() + cv[9] * tgl2) * ptI2; + mC[kSigTgl2] = gpu::CAMath::Abs(cv[20] - 2 * sgcheck * cv[18] * this->getTgl() + cv[9] * tgl2) * ptI2; mC[kSigQ2PtY] = sgcheck * cv[6] * ptI2 / sn * charge; mC[kSigQ2PtZ] = -sgcheck * cv[8] * ptI2 * charge; mC[kSigQ2PtSnp] = -sgcheck * cv[13] * cs * ptI * ptI2 * charge; mC[kSigQ2PtTgl] = (-sgcheck * cv[18] + cv[9] * this->getTgl()) * ptI2 * ptI * charge; - mC[kSigQ2Pt2] = std::fabs(cv[9] * ptI2 * ptI2); + mC[kSigQ2Pt2] = gpu::CAMath::Abs(cv[9] * ptI2 * ptI2); } else { double m00 = -sn; // m10=cs; double m23 = -pt * (sn + this->getSnp() * cs / r), m43 = -pt * pt * (r * cs - this->getSnp() * sn); @@ -396,8 +394,8 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 mC[kSigSnpZ] = (cv[12] * m43 - cv[8] * m44) / (m24 * m43 - m23 * m44); mC[kSigQ2PtZ] = (cv[8] - mC[kSigSnpZ] * m23) / m43; mC[kSigTglZ] = cv[17] / m35 - mC[kSigQ2PtZ] * m45 / m35; - mC[kSigSnp2] = std::fabs((a4 * a3 - a6 * a1) / (a5 * a3 - a6 * a2)); - mC[kSigQ2Pt2] = std::fabs((a1 - a2 * mC[kSigSnp2]) / a3); + mC[kSigSnp2] = gpu::CAMath::Abs((a4 * a3 - a6 * a1) / (a5 * a3 - a6 * a2)); + mC[kSigQ2Pt2] = gpu::CAMath::Abs((a1 - a2 * mC[kSigSnp2]) / a3); mC[kSigQ2PtSnp] = (cv[9] - mC[kSigSnp2] * m23 * m23 - mC[kSigQ2Pt2] * m43 * m43) / m23 / m43; double b1 = cv[18] - mC[kSigQ2PtSnp] * m23 * m45 - mC[kSigQ2Pt2] * m43 * m45; double b2 = m23 * m35; @@ -407,14 +405,14 @@ TrackParametrizationWithError<value_T>::TrackParametrizationWithError(const dim3 double b6 = m44 * m35; mC[kSigTglSnp] = (b4 - b6 * b1 / b3) / (b5 - b6 * b2 / b3); mC[kSigQ2PtTgl] = b1 / b3 - b2 * mC[kSigTglSnp] / b3; - mC[kSigTgl2] = std::fabs((cv[20] - mC[kSigQ2Pt2] * (m45 * m45) - mC[kSigQ2PtTgl] * 2.f * m35 * m45) / (m35 * m35)); + mC[kSigTgl2] = gpu::CAMath::Abs((cv[20] - mC[kSigQ2Pt2] * (m45 * m45) - mC[kSigQ2PtTgl] * 2.f * m35 * m45) / (m35 * m35)); } checkCovariance(); } //____________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_t& b) +GPUd() bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_t& b) { //---------------------------------------------------------------- // Extrapolate this track to the plane X=xk in the field b[]. @@ -424,34 +422,34 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ //---------------------------------------------------------------- value_t dx = xk - this->getX(); - if (std::fabs(dx) < constants::math::Almost0) { + if (gpu::CAMath::Abs(dx) < constants::math::Almost0) { return true; } // Do not propagate tracks outside the ALICE detector - if (std::fabs(dx) > 1e5 || std::fabs(this->getY()) > 1e5 || std::fabs(this->getZ()) > 1e5) { + if (gpu::CAMath::Abs(dx) > 1e5 || gpu::CAMath::Abs(this->getY()) > 1e5 || gpu::CAMath::Abs(this->getZ()) > 1e5) { LOGP(WARNING, "Anomalous track, target X:{:f}", xk); // print(); return false; } - value_t crv = (std::fabs(b[2]) < constants::math::Almost0) ? 0.f : this->getCurvature(b[2]); + value_t crv = (gpu::CAMath::Abs(b[2]) < constants::math::Almost0) ? 0.f : this->getCurvature(b[2]); value_t x2r = crv * dx; value_t f1 = this->getSnp(), f2 = f1 + x2r; - if ((std::fabs(f1) > constants::math::Almost1) || (std::fabs(f2) > constants::math::Almost1)) { + if ((gpu::CAMath::Abs(f1) > constants::math::Almost1) || (gpu::CAMath::Abs(f2) > constants::math::Almost1)) { return false; } - value_t r1 = std::sqrt((1.f - f1) * (1.f + f1)); - if (std::fabs(r1) < constants::math::Almost0) { + value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1)); + if (gpu::CAMath::Abs(r1) < constants::math::Almost0) { return false; } - value_t r2 = std::sqrt((1.f - f2) * (1.f + f2)); - if (std::fabs(r2) < constants::math::Almost0) { + value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2)); + if (gpu::CAMath::Abs(r2) < constants::math::Almost0) { return false; } value_t dy2dx = (f1 + f2) / (r1 + r2); - value_t step = (std::fabs(x2r) < 0.05f) ? dx * std::fabs(r2 + f2 * dy2dx) // chord - : 2.f * std::asin(0.5f * dx * std::sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc - step *= std::sqrt(1.f + this->getTgl() * this->getTgl()); + value_t step = (gpu::CAMath::Abs(x2r) < 0.05f) ? dx * gpu::CAMath::Abs(r2 + f2 * dy2dx) // chord + : 2.f * gpu::CAMath::ASin(0.5f * dx * gpu::CAMath::Sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc + step *= gpu::CAMath::Sqrt(1.f + this->getTgl() * this->getTgl()); // // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System gpu::gpustd::array<value_t, 9> vecLab{0.f}; @@ -509,13 +507,13 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ // Rotate to the system where Bx=By=0. value_t bxy2 = b[0] * b[0] + b[1] * b[1]; - value_t bt = std::sqrt(bxy2); + value_t bt = gpu::CAMath::Sqrt(bxy2); value_t cosphi = 1.f, sinphi = 0.f; if (bt > constants::math::Almost0) { cosphi = b[0] / bt; sinphi = b[1] / bt; } - value_t bb = std::sqrt(bxy2 + b[2] * b[2]); + value_t bb = gpu::CAMath::Sqrt(bxy2 + b[2] * b[2]); value_t costet = 1., sintet = 0.; if (bb > constants::math::Almost0) { costet = b[2] / bb; @@ -553,8 +551,8 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ // Do the final correcting step to the target plane (linear approximation) value_t x = vecLab[0], y = vecLab[1], z = vecLab[2]; - if (std::fabs(dx) > constants::math::Almost0) { - if (std::fabs(vecLab[3]) < constants::math::Almost0) { + if (gpu::CAMath::Abs(dx) > constants::math::Almost0) { + if (gpu::CAMath::Abs(vecLab[3]) < constants::math::Almost0) { return false; } dx = xk - vecLab[0]; @@ -564,7 +562,7 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ } // Calculate the track parameters - t = 1.f / std::sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); + t = 1.f / gpu::CAMath::Sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]); this->setX(x); this->setY(y); this->setZ(z); @@ -577,51 +575,51 @@ bool TrackParametrizationWithError<value_T>::propagateTo(value_t xk, const dim3_ //______________________________________________ template <typename value_T> -void TrackParametrizationWithError<value_T>::checkCovariance() +GPUd() void TrackParametrizationWithError<value_T>::checkCovariance() { // This function forces the diagonal elements of the covariance matrix to be positive. // In case the diagonal element is bigger than the maximal allowed value, it is set to // the limit and the off-diagonal elements that correspond to it are set to zero. - mC[kSigY2] = std::fabs(mC[kSigY2]); + mC[kSigY2] = gpu::CAMath::Abs(mC[kSigY2]); if (mC[kSigY2] > kCY2max) { - value_t scl = std::sqrt(kCY2max / mC[kSigY2]); + value_t scl = gpu::CAMath::Sqrt(kCY2max / mC[kSigY2]); mC[kSigY2] = kCY2max; mC[kSigZY] *= scl; mC[kSigSnpY] *= scl; mC[kSigTglY] *= scl; mC[kSigQ2PtY] *= scl; } - mC[kSigZ2] = std::fabs(mC[kSigZ2]); + mC[kSigZ2] = gpu::CAMath::Abs(mC[kSigZ2]); if (mC[kSigZ2] > kCZ2max) { - value_t scl = std::sqrt(kCZ2max / mC[kSigZ2]); + value_t scl = gpu::CAMath::Sqrt(kCZ2max / mC[kSigZ2]); mC[kSigZ2] = kCZ2max; mC[kSigZY] *= scl; mC[kSigSnpZ] *= scl; mC[kSigTglZ] *= scl; mC[kSigQ2PtZ] *= scl; } - mC[kSigSnp2] = std::fabs(mC[kSigSnp2]); + mC[kSigSnp2] = gpu::CAMath::Abs(mC[kSigSnp2]); if (mC[kSigSnp2] > kCSnp2max) { - value_t scl = std::sqrt(kCSnp2max / mC[kSigSnp2]); + value_t scl = gpu::CAMath::Sqrt(kCSnp2max / mC[kSigSnp2]); mC[kSigSnp2] = kCSnp2max; mC[kSigSnpY] *= scl; mC[kSigSnpZ] *= scl; mC[kSigTglSnp] *= scl; mC[kSigQ2PtSnp] *= scl; } - mC[kSigTgl2] = std::fabs(mC[kSigTgl2]); + mC[kSigTgl2] = gpu::CAMath::Abs(mC[kSigTgl2]); if (mC[kSigTgl2] > kCTgl2max) { - value_t scl = std::sqrt(kCTgl2max / mC[kSigTgl2]); + value_t scl = gpu::CAMath::Sqrt(kCTgl2max / mC[kSigTgl2]); mC[kSigTgl2] = kCTgl2max; mC[kSigTglY] *= scl; mC[kSigTglZ] *= scl; mC[kSigTglSnp] *= scl; mC[kSigQ2PtTgl] *= scl; } - mC[kSigQ2Pt2] = std::fabs(mC[kSigQ2Pt2]); + mC[kSigQ2Pt2] = gpu::CAMath::Abs(mC[kSigQ2Pt2]); if (mC[kSigQ2Pt2] > kC1Pt2max) { - value_t scl = std::sqrt(kC1Pt2max / mC[kSigQ2Pt2]); + value_t scl = gpu::CAMath::Sqrt(kC1Pt2max / mC[kSigQ2Pt2]); mC[kSigQ2Pt2] = kC1Pt2max; mC[kSigQ2PtY] *= scl; mC[kSigQ2PtZ] *= scl; @@ -632,7 +630,7 @@ void TrackParametrizationWithError<value_T>::checkCovariance() //______________________________________________ template <typename value_T> -void TrackParametrizationWithError<value_T>::resetCovariance(value_t s2) +GPUd() void TrackParametrizationWithError<value_T>::resetCovariance(value_t s2) { // Reset the covarince matrix to "something big" double d0(kCY2max), d1(kCZ2max), d2(kCSnp2max), d3(kCTgl2max), d4(kC1Pt2max); @@ -658,7 +656,9 @@ void TrackParametrizationWithError<value_T>::resetCovariance(value_t s2) d4 = kC1Pt2max; } } - memset(mC, 0, kCovMatSize * sizeof(value_t)); + for (int i = 0; i < kCovMatSize; i++) { + mC[i] = 0; + } mC[kSigY2] = d0; mC[kSigZ2] = d1; mC[kSigSnp2] = d2; @@ -668,7 +668,7 @@ void TrackParametrizationWithError<value_T>::resetCovariance(value_t s2) //______________________________________________ template <typename value_T> -typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const dim2_t& p, const dim3_t& cov) const +GPUd() typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWithError<value_T>::getPredictedChi2(const dim2_t& p, const dim3_t& cov) const { // Estimate the chi2 of the space point "p" with the cov. matrix "cov" auto sdd = static_cast<double>(getSigmaY2()) + static_cast<double>(cov[0]); @@ -676,7 +676,7 @@ typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWit auto szz = static_cast<double>(getSigmaZ2()) + static_cast<double>(cov[2]); auto det = sdd * szz - sdz * sdz; - if (std::fabs(det) < constants::math::Almost0) { + if (gpu::CAMath::Abs(det) < constants::math::Almost0) { return constants::math::VeryBig; } @@ -686,7 +686,7 @@ typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWit return (d * (szz * d - sdz * z) + z * (sdd * z - d * sdz)) / det; } -#ifndef GPUCA_GPUCODE_DEVICE // Disable function relying on ROOT SMatrix on GPU +#ifndef GPUCA_GPUCODE // Disable function relying on ROOT SMatrix on GPU //______________________________________________ template <typename value_T> @@ -725,11 +725,11 @@ typename TrackParametrizationWithError<value_T>::value_t TrackParametrizationWit // get chi2 wrt other track, which must be defined at the same parameters X,alpha // Supplied non-initialized covToSet matrix is filled by inverse combined matrix for further use - if (std::abs(this->getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { + if (gpu::CAMath::Abs(this->getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { LOG(ERROR) << "The reference Alpha of the tracks differ: " << this->getAlpha() << " : " << rhs.getAlpha(); return 2.f * HugeF; } - if (std::abs(this->getX() - rhs.getX()) > FLT_EPSILON) { + if (gpu::CAMath::Abs(this->getX() - rhs.getX()) > FLT_EPSILON) { LOG(ERROR) << "The reference X of the tracks differ: " << this->getX() << " : " << rhs.getX(); return 2.f * HugeF; } @@ -758,11 +758,11 @@ bool TrackParametrizationWithError<value_T>::update(const TrackParametrizationWi // update track with other track, the inverted combined cov matrix should be supplied // consider skipping this check, since it is usually already done upstream - if (std::abs(this->getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { + if (gpu::CAMath::Abs(this->getAlpha() - rhs.getAlpha()) > FLT_EPSILON) { LOG(ERROR) << "The reference Alpha of the tracks differ: " << this->getAlpha() << " : " << rhs.getAlpha(); return false; } - if (std::abs(this->getX() - rhs.getX()) > FLT_EPSILON) { + if (gpu::CAMath::Abs(this->getX() - rhs.getX()) > FLT_EPSILON) { LOG(ERROR) << "The reference X of the tracks differ: " << this->getX() << " : " << rhs.getX(); return false; } @@ -837,7 +837,7 @@ bool TrackParametrizationWithError<value_T>::update(const TrackParametrizationWi //______________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, const dim3_t& cov) +GPUd() bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, const dim3_t& cov) { // Update the track parameters with the space point "p" having // the covariance matrix "cov" @@ -853,7 +853,7 @@ bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, const dim3_ double r11 = static_cast<double>(cov[2]) + static_cast<double>(cm11); double det = r00 * r11 - r01 * r01; - if (std::fabs(det) < constants::math::Almost0) { + if (gpu::CAMath::Abs(det) < constants::math::Almost0) { return false; } double detI = 1. / det; @@ -870,7 +870,7 @@ bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, const dim3_ value_t dy = p[kY] - this->getY(), dz = p[kZ] - this->getZ(); value_t dsnp = k20 * dy + k21 * dz; - if (std::fabs(this->getSnp() + dsnp) > constants::math::Almost1) { + if (gpu::CAMath::Abs(this->getSnp() + dsnp) > constants::math::Almost1) { return false; } @@ -908,7 +908,7 @@ bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, const dim3_ //______________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr, value_t dedx) +GPUd() bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr, value_t dedx) { //------------------------------------------------------------------ // This function corrects the track parameters for the crossed material. @@ -933,7 +933,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va value_t cst2I = (1.f + this->getTgl() * this->getTgl()); // 1/cos(lambda)^2 // Apply angle correction, if requested if (anglecorr) { - value_t angle = std::sqrt(cst2I / csp2); + value_t angle = gpu::CAMath::Sqrt(cst2I / csp2); x2x0 *= angle; xrho *= angle; } @@ -946,7 +946,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va // Calculating the multiple scattering corrections****************** value_t cC22(0.f), cC33(0.f), cC43(0.f), cC44(0.f); if (x2x0 != 0.f) { - value_t theta2 = kMSConst2 / (beta2 * p2) * std::fabs(x2x0); + value_t theta2 = kMSConst2 / (beta2 * p2) * gpu::CAMath::Abs(x2x0); if (this->getAbsCharge() != 1) { theta2 *= this->getAbsCharge() * this->getAbsCharge(); } @@ -970,15 +970,15 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va value_t cP4 = 1.f; if ((xrho != 0.f) && (beta2 < 1.f)) { if (dedx < kCalcdEdxAuto + constants::math::Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / std::fabs(mass)); + dedx = BetheBlochSolid(p / gpu::CAMath::Abs(mass)); if (this->getAbsCharge() != 1) { dedx *= this->getAbsCharge() * this->getAbsCharge(); } } value_t dE = dedx * xrho; - value_t e = std::sqrt(e2); - if (std::fabs(dE) > kMaxELossFrac * e) { + value_t e = gpu::CAMath::Sqrt(e2); + if (gpu::CAMath::Abs(dE) > kMaxELossFrac * e) { return false; // 30% energy loss is too much! } value_t eupd = e + dE; @@ -986,11 +986,11 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va if (pupd2 < kMinP * kMinP) { return false; } - cP4 = p / std::sqrt(pupd2); + cP4 = p / gpu::CAMath::Sqrt(pupd2); // // Approximate energy loss fluctuation (M.Ivanov) constexpr value_t knst = 0.07f; // To be tuned. - value_t sigmadE = knst * std::sqrt(std::fabs(dE)) * e / p2 * this->getCharge2Pt(); + value_t sigmadE = knst * gpu::CAMath::Sqrt(gpu::CAMath::Abs(dE)) * e / p2 * this->getCharge2Pt(); cC44 += sigmadE * sigmadE; } @@ -1008,7 +1008,7 @@ bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, va //______________________________________________________________ template <typename value_T> -bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(gpu::gpustd::array<value_t, kLabCovMatSize>& cv) const +GPUd() bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(gpu::gpustd::array<value_t, kLabCovMatSize>& cv) const { //--------------------------------------------------------------------- // This function returns the global covariance matrix of the track params @@ -1022,7 +1022,7 @@ bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(gpu::gpustd::arr // // Results for (nearly) straight tracks are meaningless ! //--------------------------------------------------------------------- - if (std::abs(this->getQ2Pt()) <= constants::math::Almost0 || std::abs(this->getSnp()) > constants::math::Almost1) { + if (gpu::CAMath::Abs(this->getQ2Pt()) <= constants::math::Almost0 || gpu::CAMath::Abs(this->getSnp()) > constants::math::Almost1) { for (int i = 0; i < 21; i++) { cv[i] = 0.; } @@ -1032,7 +1032,7 @@ bool TrackParametrizationWithError<value_T>::getCovXYZPxPyPzGlo(gpu::gpustd::arr auto pt = this->getPt(); value_t sn, cs; o2::math_utils::detail::sincos(this->getAlpha(), sn, cs); - auto r = std::sqrt((1. - this->getSnp()) * (1. + this->getSnp())); + auto r = gpu::CAMath::Sqrt((1. - this->getSnp()) * (1. + this->getSnp())); auto m00 = -sn, m10 = cs; auto m23 = -pt * (sn + this->getSnp() * cs / r), m43 = -pt * pt * (r * cs - this->getSnp() * sn); auto m24 = pt * (cs - this->getSnp() * sn / r), m44 = -pt * pt * (r * sn + this->getSnp() * cs); @@ -1089,7 +1089,7 @@ std::string TrackParametrizationWithError<value_T>::asString() const //______________________________________________________________ template <typename value_T> -void TrackParametrizationWithError<value_T>::print() const +GPUd() void TrackParametrizationWithError<value_T>::print() const { // print parameters #ifndef GPUCA_ALIGPUCODE @@ -1097,8 +1097,10 @@ void TrackParametrizationWithError<value_T>::print() const #endif } +namespace o2::track +{ template class TrackParametrizationWithError<float>; +#ifndef GPUCA_GPUCODE_DEVICE template class TrackParametrizationWithError<double>; - -} // namespace track -} // namespace o2 +#endif +} // namespace o2::track diff --git a/DataFormats/Reconstruction/src/Vertex.cxx b/DataFormats/Reconstruction/src/Vertex.cxx index f4a98e4223992..4c85cbdae24ca 100644 --- a/DataFormats/Reconstruction/src/Vertex.cxx +++ b/DataFormats/Reconstruction/src/Vertex.cxx @@ -17,7 +17,7 @@ namespace o2 namespace dataformats { -#ifndef GPUCA_ALIGPUCODE +#ifndef GPUCA_GPUCODE_DEVICE std::string VertexBase::asString() const { diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index c9e83f16436b4..e778898792b7a 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. #include "DetectorsBase/Propagator.h" -#include <GPUCommonLogger.h> +#include "GPUCommonLogger.h" #include "Field/MagFieldFast.h" #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/Vertex.h" diff --git a/GPU/Common/GPUCommonLogger.h b/GPU/Common/GPUCommonLogger.h index 103d0638f0c53..fc5fa6aac505d 100644 --- a/GPU/Common/GPUCommonLogger.h +++ b/GPU/Common/GPUCommonLogger.h @@ -14,13 +14,9 @@ #ifndef GPUCOMMONFAIRLOGGER_H #define GPUCOMMONFAIRLOGGER_H -#if defined(__OPENCL__) -#define LOG(...) -#define LOGF(...) -#define LOGP(...) - -#elif defined(GPUCA_GPUCODE_DEVICE) #include "GPUCommonDef.h" + +#if defined(GPUCA_GPUCODE_DEVICE) namespace o2::gpu::detail { struct DummyLogger { @@ -31,6 +27,14 @@ struct DummyLogger { } }; } // namespace o2::gpu::detail +#endif + +#if defined(__OPENCL__) +#define LOG(...) o2::gpu::detail::DummyLogger() +#define LOGF(...) +#define LOGP(...) + +#elif defined(GPUCA_GPUCODE_DEVICE) #define LOG(...) o2::gpu::detail::DummyLogger() //#define LOG(...) static_assert(false, "LOG(...) << ... unsupported in GPU code"); #define LOGF(type, string, ...) \ diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h index 2a38c3f5a2ef9..ff17a30c19bd6 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h @@ -58,6 +58,10 @@ using namespace GPUCA_NAMESPACE::gpu; #include "MatLayerCyl.cxx" #include "Ray.cxx" +// O2 track model +#include "TrackParametrization.cxx" +#include "TrackParametrizationWithError.cxx" + // Files for GPU dEdx #include "GPUdEdx.cxx" diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 8ec7ef7ce6b87..36b776e059cd5 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -115,6 +115,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/Detectors/Base/src ${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src + ${CMAKE_SOURCE_DIR}/DataFormats/Reconstruction/src PUBLIC_LINK_LIBRARIES O2::GPUTracking O2::ITStrackingCUDA TARGETVARNAME targetName) diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index 62a171ef7cf28..775b58d6d9198 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -31,6 +31,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") PUBLIC_LINK_LIBRARIES O2::GPUTracking O2::ITStrackingHIP hip::host hip::device hip::hipcub roc::rocthrust PUBLIC_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src ${CMAKE_SOURCE_DIR}/Detectors/Base/src + ${CMAKE_SOURCE_DIR}/DataFormats/Reconstruction/src TARGETVARNAME targetName) target_compile_definitions( diff --git a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt index da8f89a2113e2..7e9593ff45cbe 100644 --- a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt +++ b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt @@ -30,6 +30,7 @@ set(OCL_DEFINECL "-D$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS "-I$<JOIN:$<TARGET_PROPERTY:O2::GPUTracking,INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>" -I${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src -I${CMAKE_SOURCE_DIR}/Detectors/Base/src + -I${CMAKE_SOURCE_DIR}/DataFormats/Reconstruction/src -I${CMAKE_SOURCE_DIR}/Detectors/ITSMFT/ITS/tracking/cuda/include -DGPUCA_GPULIBRARY=OCL2 -D__OPENCLCPP__ diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 04361760182b6..5a3ad4dd18f9e 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -147,6 +147,7 @@ include_directories(${CMAKE_SOURCE_DIR}/TPCClusterFinder ${CMAKE_SOURCE_DIR}/../../../DataFormats/Headers/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/MemoryResources/include ${CMAKE_SOURCE_DIR}/../../../DataFormats/Reconstruction/include + ${CMAKE_SOURCE_DIR}/../../../DataFormats/Reconstruction/src ${CMAKE_SOURCE_DIR}/../../../DataFormats/simulation/include ${CMAKE_SOURCE_DIR}/../../../Detectors/Base/include ${CMAKE_SOURCE_DIR}/../../../Detectors/Base/src @@ -183,6 +184,8 @@ if(CONFIG_O2_EXTENSIONS) ../../../DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx ../../../DataFormats/Reconstruction/src/Vertex.cxx ../../../DataFormats/Reconstruction/src/TrackLTIntegral.cxx + ../../../DataFormats/Reconstruction/src/TrackParametrization.cxx + ../../../DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx ../../../Detectors/TRD/base/src/GeometryBase.cxx ../../../Detectors/Base/src/MatLayerCylSet.cxx ../../../Detectors/Base/src/MatLayerCyl.cxx From 73c10d5edd2b2e51fbe800705680aac374df142c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 11 Dec 2020 21:42:30 +0100 Subject: [PATCH 1612/1751] GPU: Workaround for reoccuring HIP problem parsing host-code during device compilation --- GPU/Common/GPUCommonLogger.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/Common/GPUCommonLogger.h b/GPU/Common/GPUCommonLogger.h index fc5fa6aac505d..5cabc470ad865 100644 --- a/GPU/Common/GPUCommonLogger.h +++ b/GPU/Common/GPUCommonLogger.h @@ -16,12 +16,12 @@ #include "GPUCommonDef.h" -#if defined(GPUCA_GPUCODE_DEVICE) +#if defined(GPUCA_GPUCODE_DEVICE) || defined(__HIPCC__) namespace o2::gpu::detail { struct DummyLogger { template <typename... Args> - GPUd() DummyLogger& operator<<(Args... args) + GPUhd() DummyLogger& operator<<(Args... args) { return *this; } @@ -34,7 +34,7 @@ struct DummyLogger { #define LOGF(...) #define LOGP(...) -#elif defined(GPUCA_GPUCODE_DEVICE) +#elif defined(GPUCA_GPUCODE_DEVICE) || defined(__HIPCC__) #define LOG(...) o2::gpu::detail::DummyLogger() //#define LOG(...) static_assert(false, "LOG(...) << ... unsupported in GPU code"); #define LOGF(type, string, ...) \ From 7090f3e740771130a965c1cbd176568680fc443c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 11 Dec 2020 23:10:26 +0100 Subject: [PATCH 1613/1751] Change more Double_t to float in TrackParCov propagator --- Detectors/Base/src/Propagator.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index e778898792b7a..d22c01f8f918b 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -346,7 +346,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); + float d = std::abs(x * snp - y * csp); if (d > maxD) { return false; } @@ -391,7 +391,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); + float d = std::abs(x * snp - y * csp); if (d > maxD) { return false; } @@ -436,7 +436,7 @@ bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); + float d = std::abs(x * snp - y * csp); if (d > maxD) { return false; } @@ -480,7 +480,7 @@ bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2: x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - Double_t d = std::abs(x * snp - y * csp); + float d = std::abs(x * snp - y * csp); if (d > maxD) { return false; } From 45ce77971a6c169eb8d7a906ef4a75e918f46ad5 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner <matthias.kleiner@cern.ch> Date: Fri, 11 Dec 2020 11:34:04 +0100 Subject: [PATCH 1614/1751] ndsplines: added approximateFunctionBatch function --- GPU/TPCFastTransformation/SplineHelper.cxx | 52 +++++++++++++++++++--- GPU/TPCFastTransformation/SplineHelper.h | 2 +- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/GPU/TPCFastTransformation/SplineHelper.cxx b/GPU/TPCFastTransformation/SplineHelper.cxx index 320f9cc7ad39d..f499f80c07420 100644 --- a/GPU/TPCFastTransformation/SplineHelper.cxx +++ b/GPU/TPCFastTransformation/SplineHelper.cxx @@ -135,7 +135,7 @@ void SplineHelper<DataT>::approximateFunction( //std::vector<DataT> dataPointF(getNumberOfDataPoints() * mFdimensions); //DUMYY VERSION Commented out /* for (int i = 0; i < getNumberOfDataPoints() * mFdimensions; i++) { - dataPointF[i] = 1.; + dataPointF[i] = 1.; } */ /* double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax()); @@ -155,20 +155,60 @@ void SplineHelper<DataT>::approximateFunction( template <typename DataT> void SplineHelper<DataT>::approximateFunctionBatch( DataT* Fparameters, const double xMin[], const double xMax[], - std::function<void(const std::vector<double> x[], std::vector<double> f[/*mFdimensions*/])> F, + std::function<void(const std::vector<double> x[], double f[/*mFdimensions*/])> F, unsigned int batchsize) const { /// Create best-fit spline parameters for a given input function F. /// F calculates values for a batch of points. /// output in Fparameters - // TODO: implement later + double scaleX[mXdimensions]; + for (int i = 0; i < mXdimensions; i++) { + scaleX[i] = (xMax[i] - xMin[i]) / ((double)(mHelpers[i].getSpline().getUmax())); + } - std::vector<double> dataPointF(getNumberOfDataPoints() * mFdimensions); - for (int i = 0; i < getNumberOfDataPoints() * mFdimensions; i++) { - dataPointF[i] = 0.; + const int nrOfAllPoints = getNumberOfDataPoints(); + std::vector<double> dataPointF(nrOfAllPoints * mFdimensions); + + int nrOfPoints[mXdimensions]; + for (int i = 0; i < mXdimensions; i++) { + nrOfPoints[i] = mHelpers[i].getNumberOfDataPoints(); + } + + std::vector<double> x[mXdimensions]; + for (unsigned int iDim = 0; iDim < mXdimensions; ++iDim) { + x[iDim].reserve(batchsize); } + int ibatch = 0; + int index = 0; + for (int d = 0; d < nrOfAllPoints; d++) { // for all DataPoints + int indices[mXdimensions]; + int modoperand = 1; + int divisor = 1; + + // get the DataPoint index + for (int i = 0; i < mXdimensions; i++) { + modoperand *= nrOfPoints[i]; + indices[i] = (int)((d % modoperand) / divisor); + divisor *= nrOfPoints[i]; + // get the respecting u-values: + x[i].emplace_back(xMin[i] + mHelpers[i].getDataPoint(indices[i]).u * scaleX[i]); + } + ++ibatch; + + if (ibatch == batchsize || d == nrOfAllPoints - 1) { + ibatch = 0; + + F(x, &dataPointF[index]); + index = (d + 1) * mFdimensions; + + for (unsigned int iDim = 0; iDim < mXdimensions; ++iDim) { + x[iDim].clear(); + } + } + } // end for all DataPoints d + approximateFunction(Fparameters, dataPointF.data()); } diff --git a/GPU/TPCFastTransformation/SplineHelper.h b/GPU/TPCFastTransformation/SplineHelper.h index fce2ef1aa12e9..6eb0ade996359 100644 --- a/GPU/TPCFastTransformation/SplineHelper.h +++ b/GPU/TPCFastTransformation/SplineHelper.h @@ -74,7 +74,7 @@ class SplineHelper /// approximate std::function, output in Fparameters. F calculates values for a batch of points. void approximateFunctionBatch( DataT* Fparameters, const double xMin[/* mXdimensions */], const double xMax[/* mXdimensions */], - std::function<void(const std::vector<double> x[/* mXdimensions */], std::vector<double> f[/*mFdimensions*/])> F, + std::function<void(const std::vector<double> x[/* mXdimensions */], double f[/*mFdimensions*/])> F, unsigned int batchsize) const; /// approximate a function given as an array of values at data points From 8c6dda0532f83677c02fc50c054e89d28522ea14 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Dec 2020 01:08:22 +0100 Subject: [PATCH 1615/1751] Eliminate mass argument from track mat.corrections and propagation interfaces Since the TrackPar provides its mass via getPID().getMass(), we don't need to pass the mass argument explicitly to track.correctFor... and Propagator.propagetTo... methods. The correctFor... methods will query the mass internally. --- .../include/ReconstructionDataFormats/PID.h | 1 + .../TrackParametrization.h | 2 +- .../TrackParametrizationWithError.h | 2 +- .../src/TrackParametrization.cxx | 15 +++---- .../src/TrackParametrizationWithError.cxx | 12 +++--- .../Base/include/DetectorsBase/Propagator.h | 16 +++---- Detectors/Base/src/Propagator.cxx | 36 +++++++--------- .../include/GlobalTracking/MatchTPCITS.h | 2 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 8 ++-- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 43 ++++++++----------- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 2 +- .../SpacePoints/src/TrackInterpolation.cxx | 8 ++-- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 2 +- .../TRDTracking/GPUTRDInterfaces.h | 2 +- 14 files changed, 68 insertions(+), 83 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h index da25dc910e778..22644a7fec457 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h @@ -110,6 +110,7 @@ class PID GPUd() operator ID() const { return getID(); } GPUd() float getMass() const { return getMass(mID); } + GPUd() float getMass2() const { return getMass2(mID); } GPUd() float getMass2Z() const { return getMass2Z(mID); } GPUd() int getCharge() const { return getCharge(mID); } diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 77bd1c372ed80..62c9801955b05 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -197,7 +197,7 @@ class TrackParametrization GPUd() math_utils::Point3D<value_t> getXYZGloAt(value_t xk, value_t b, bool& ok) const; // parameters manipulation - GPUd() bool correctForELoss(value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); + GPUd() bool correctForELoss(value_t xrho, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); GPUd() bool rotateParam(value_t alpha); GPUd() bool propagateParamTo(value_t xk, value_t b); GPUd() bool propagateParamTo(value_t xk, const dim3_t& b); diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index d6c78eae4f50b..e86a17007e1af 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -102,7 +102,7 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> template <typename T> GPUd() bool update(const BaseCluster<T>& p); - GPUd() bool correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); + GPUd() bool correctForMaterial(value_t x2x0, value_t xrho, bool anglecorr = false, value_t dedx = kCalcdEdxAuto); GPUd() void resetCovariance(value_t s2 = 0); GPUd() void checkCovariance(); diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index d4a9c8ac2da2e..041491b74c12a 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -682,14 +682,13 @@ GPUd() bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, val //______________________________________________ template <typename value_T> -GPUd() bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t mass, bool anglecorr, value_t dedx) +GPUd() bool TrackParametrization<value_T>::correctForELoss(value_t xrho, bool anglecorr, value_t dedx) { //------------------------------------------------------------------ // This function corrects the track parameters for the energy loss in crossed material. // "xrho" - is the product length*density (g/cm^2). // It should be passed as negative when propagating tracks // from the intreaction point to the outside of the central barrel. - // "mass" - the mass of this particle (GeV/c^2). // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly // "anglecorr" - switch for the angular correction //------------------------------------------------------------------ @@ -703,19 +702,15 @@ GPUd() bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t value_t angle = gpu::CAMath::Sqrt(cst2I / (csp2)); xrho *= angle; } - value_t p = getP(); - if (mass < 0) { - p += p; // q=2 particle - } - value_t p2 = p * p, mass2 = mass * mass; - value_t e2 = p2 + mass2; + value_t p2 = p * p; + value_t e2 = p2 + getPID().getMass2(); value_t beta2 = p2 / e2; // Calculating the energy loss corrections************************ if ((xrho != 0.f) && (beta2 < 1.f)) { if (dedx < kCalcdEdxAuto + constants::math::Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / gpu::CAMath::Abs(mass)); + dedx = BetheBlochSolid(p / getPID().getMass()); if (mAbsCharge != 1) { dedx *= mAbsCharge * mAbsCharge; } @@ -727,7 +722,7 @@ GPUd() bool TrackParametrization<value_T>::correctForELoss(value_t xrho, value_t return false; // 30% energy loss is too much! } value_t eupd = e + dE; - value_t pupd2 = eupd * eupd - mass2; + value_t pupd2 = eupd * eupd - getPID().getMass2(); if (pupd2 < kMinP * kMinP) { return false; } diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index fd0e20c0f9f01..6ca0d1c57f180 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -908,7 +908,7 @@ GPUd() bool TrackParametrizationWithError<value_T>::update(const dim2_t& p, cons //______________________________________________ template <typename value_T> -GPUd() bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, value_t xrho, value_t mass, bool anglecorr, value_t dedx) +GPUd() bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x2x0, value_t xrho, bool anglecorr, value_t dedx) { //------------------------------------------------------------------ // This function corrects the track parameters for the crossed material. @@ -916,7 +916,6 @@ GPUd() bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x // "xrho" - is the product length*density (g/cm^2). // It should be passed as negative when propagating tracks // from the intreaction point to the outside of the central barrel. - // "mass" - the mass of this particle (GeV/c^2). // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly // "anglecorr" - switch for the angular correction //------------------------------------------------------------------ @@ -937,10 +936,9 @@ GPUd() bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x x2x0 *= angle; xrho *= angle; } - value_t p = this->getP(); - value_t p2 = p * p, mass2 = mass * mass; - value_t e2 = p2 + mass2; + value_t p2 = p * p; + value_t e2 = p2 + this->getPID().getMass2(); value_t beta2 = p2 / e2; // Calculating the multiple scattering corrections****************** @@ -970,7 +968,7 @@ GPUd() bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x value_t cP4 = 1.f; if ((xrho != 0.f) && (beta2 < 1.f)) { if (dedx < kCalcdEdxAuto + constants::math::Almost1) { // request to calculate dedx on the fly - dedx = BetheBlochSolid(p / gpu::CAMath::Abs(mass)); + dedx = BetheBlochSolid(p / this->getPID().getMass()); if (this->getAbsCharge() != 1) { dedx *= this->getAbsCharge() * this->getAbsCharge(); } @@ -982,7 +980,7 @@ GPUd() bool TrackParametrizationWithError<value_T>::correctForMaterial(value_t x return false; // 30% energy loss is too much! } value_t eupd = e + dE; - value_t pupd2 = eupd * eupd - mass2; + value_t pupd2 = eupd * eupd - this->getPID().getMass2(); if (pupd2 < kMinP * kMinP) { return false; } diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index 861d0f2810ef4..18084df865027 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -59,39 +59,39 @@ class Propagator static constexpr float MAX_SIN_PHI = 0.85f; static constexpr float MAX_STEP = 2.0f; - bool PropagateToXBxByBz(o2::track::TrackParCov& track, float x, float mass = o2::constants::physics::MassPionCharged, + bool PropagateToXBxByBz(o2::track::TrackParCov& track, float x, float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; - bool PropagateToXBxByBz(o2::track::TrackPar& track, float x, float mass = o2::constants::physics::MassPionCharged, + bool PropagateToXBxByBz(o2::track::TrackPar& track, float x, float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; - bool propagateToX(o2::track::TrackParCov& track, float x, float bZ, float mass = o2::constants::physics::MassPionCharged, + bool propagateToX(o2::track::TrackParCov& track, float x, float bZ, float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; - bool propagateToX(o2::track::TrackPar& track, float x, float bZ, float mass = o2::constants::physics::MassPionCharged, + bool propagateToX(o2::track::TrackPar& track, float x, float bZ, float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; bool propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, - float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; bool propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, - float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; bool propagateToDCA(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, - float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; bool propagateToDCABxByBz(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, - float mass = o2::constants::physics::MassPionCharged, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index d22c01f8f918b..52516ee8400fb 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -96,7 +96,7 @@ int Propagator::initFieldFromGRP(const o2::parameters::GRPObject* grp, bool verb #endif //_______________________________________________________________________ -bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, float mass, float maxSnp, float maxStep, +bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, float maxSnp, float maxStep, Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- @@ -105,7 +105,6 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, // taking into account all the three components of the magnetic field // and correcting for the crossed material. // - // mass - mass used in propagation - used for energy loss correction (if <0 then q=2) // maxStep - maximal step for propagation // tofInfo - optional container for track length and PID-dependent TOF integration // @@ -137,7 +136,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, if (matCorr != MatCorrType::USEMatCorrNONE) { auto xyz1 = track.getXYZGlo(); auto mb = getMatBudget(matCorr, xyz0, xyz1); - if (!track.correctForMaterial(mb.meanX2X0, ((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho, mass)) { + if (!track.correctForMaterial(mb.meanX2X0, ((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho)) { return false; } @@ -156,7 +155,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, } //_______________________________________________________________________ -bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, float mass, float maxSnp, float maxStep, +bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, float maxSnp, float maxStep, Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- @@ -165,7 +164,6 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, flo // taking into account all the three components of the magnetic field // and optionally correcting for the e.loss crossed material. // - // mass - mass used in propagation - used for energy loss correction (if <0 then q=2) // maxStep - maximal step for propagation // tofInfo - optional container for track length and PID-dependent TOF integration // @@ -197,7 +195,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, flo if (matCorr != MatCorrType::USEMatCorrNONE) { auto xyz1 = track.getXYZGlo(); auto mb = getMatBudget(matCorr, xyz0, xyz1); - if (!track.correctForELoss(((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho, mass)) { + if (!track.correctForELoss(((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho)) { return false; } if (tofInfo) { @@ -215,7 +213,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, flo } //_______________________________________________________________________ -bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float bZ, float mass, float maxSnp, float maxStep, +bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float bZ, float maxSnp, float maxStep, Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- @@ -224,7 +222,6 @@ bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float // taking into account all the three components of the magnetic field // and correcting for the crossed material. // - // mass - mass used in propagation - used for energy loss correction (if <0 then q=2) // maxStep - maximal step for propagation // tofInfo - optional container for track length and PID-dependent TOF integration // @@ -255,7 +252,7 @@ bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float auto xyz1 = track.getXYZGlo(); auto mb = getMatBudget(matCorr, xyz0, xyz1); // - if (!track.correctForMaterial(mb.meanX2X0, ((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho, mass)) { + if (!track.correctForMaterial(mb.meanX2X0, ((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho)) { return false; } @@ -274,7 +271,7 @@ bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float } //_______________________________________________________________________ -bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, float mass, float maxSnp, float maxStep, +bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, float maxSnp, float maxStep, Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- @@ -283,7 +280,6 @@ bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, // taking into account all the three components of the magnetic field // and correcting for the crossed material. // - // mass - mass used in propagation - used for energy loss correction (if <0 then q=2) // maxStep - maximal step for propagation // tofInfo - optional container for track length and PID-dependent TOF integration // @@ -314,7 +310,7 @@ bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, auto xyz1 = track.getXYZGlo(); auto mb = getMatBudget(matCorr, xyz0, xyz1); // - if (!track.correctForELoss(((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho, mass)) { + if (!track.correctForELoss(((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho)) { return false; } @@ -334,7 +330,7 @@ bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, //_______________________________________________________________________ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, - float mass, float maxStep, Propagator::MatCorrType matCorr, + float maxStep, Propagator::MatCorrType matCorr, o2::dataformats::DCA* dca, o2::track::TrackLTIntegral* tofInfo, int signCorr, float maxD) const { @@ -362,7 +358,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); - if (!tmpT.rotate(alp) || !propagateToX(tmpT, xv, bZ, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { + if (!tmpT.rotate(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); return false; @@ -379,7 +375,7 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac //_______________________________________________________________________ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, - float mass, float maxStep, Propagator::MatCorrType matCorr, + float maxStep, Propagator::MatCorrType matCorr, o2::dataformats::DCA* dca, o2::track::TrackLTIntegral* tofInfo, int signCorr, float maxD) const { @@ -407,7 +403,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); - if (!tmpT.rotate(alp) || !PropagateToXBxByBz(tmpT, xv, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { + if (!tmpT.rotate(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); return false; @@ -424,7 +420,7 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 //_______________________________________________________________________ bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, - float mass, float maxStep, Propagator::MatCorrType matCorr, + float maxStep, Propagator::MatCorrType matCorr, std::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, int signCorr, float maxD) const { @@ -452,7 +448,7 @@ bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); - if (!tmpT.rotateParam(alp) || !propagateToX(tmpT, xv, bZ, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { + if (!tmpT.rotateParam(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; tmpT.printParam(); @@ -468,7 +464,7 @@ bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track //_______________________________________________________________________ bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, - float mass, float maxStep, Propagator::MatCorrType matCorr, + float maxStep, Propagator::MatCorrType matCorr, std::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, int signCorr, float maxD) const { @@ -496,7 +492,7 @@ bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2: auto tmpT(track); // operate on the copy to recover after the failure alp += std::asin(sn); - if (!tmpT.rotateParam(alp) || !PropagateToXBxByBz(tmpT, xv, mass, 0.85, maxStep, matCorr, tofInfo, signCorr)) { + if (!tmpT.rotateParam(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; tmpT.printParam(); diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 0ba1d951e0371..1e13ca9c01b52 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -507,7 +507,7 @@ class MatchTPCITS void refitWinners(bool loopInITS = false); bool refitTrackTPCITSloopITS(int iITS, int& iTPC); bool refitTrackTPCITSloopTPC(int iTPC, int& iITS); - bool refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, float xTgt, int trcID, float timeTB, float m = o2::constants::physics::MassPionCharged) const; + bool refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, float xTgt, int trcID, float timeTB) const; void selectBestMatches(); bool validateTPCMatch(int iTPC); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index f1b84e296de23..9b3d77cddf307 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -885,7 +885,7 @@ void MatchTOF::doMatching(int sec) double reachedPoint = mXRef + istep * step; while (propagateToRefX(trefTrk, reachedPoint, step, intLT) && nStripsCrossedInPropagation <= 2 && reachedPoint < Geo::RMAX) { - // while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trefTrk, mXRef + istep * step, o2::constants::physics::MassPionCharged, MAXSNP, step, 1, &intLT) && nStripsCrossedInPropagation <= 2 && mXRef + istep * step < Geo::RMAX) { + // while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trefTrk, mXRef + istep * step, MAXSNP, step, 1, &intLT) && nStripsCrossedInPropagation <= 2 && mXRef + istep * step < Geo::RMAX) { trefTrk.getXYZGlo(pos); for (int ii = 0; ii < 3; ii++) { // we need to change the type... @@ -1258,7 +1258,7 @@ void MatchTOF::doMatchingForTPC(int sec) } } while (propagateToRefX(trefTrk, reachedPoint, step, intLT) && reachedPoint < Geo::RMAX) { - // while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trefTrk, mXRef + istep * step, o2::constants::physics::MassPionCharged, MAXSNP, step, 1, &intLT) && nStripsCrossedInPropagation <= 2 && mXRef + istep * step < Geo::RMAX) { + // while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trefTrk, mXRef + istep * step, MAXSNP, step, 1, &intLT) && nStripsCrossedInPropagation <= 2 && mXRef + istep * step < Geo::RMAX) { trefTrk.getXYZGlo(pos); for (int ii = 0; ii < 3; ii++) { // we need to change the type... @@ -1550,7 +1550,7 @@ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float st xStart = 50.; } int istep = 1; - bool hasPropagated = o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, xStart + istep * stepInCm, o2::constants::physics::MassPionCharged, MAXSNP, stepInCm, matCorr, &intLT); + bool hasPropagated = o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, xStart + istep * stepInCm, MAXSNP, stepInCm, matCorr, &intLT); while (hasPropagated) { if (trc.getX() > xRef) { refReached = true; // we reached the 371cm reference @@ -1568,7 +1568,7 @@ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float st if (refReached) { break; } - hasPropagated = o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, xStart + istep * stepInCm, o2::constants::physics::MassPionCharged, MAXSNP, stepInCm, matCorr, &intLT); + hasPropagated = o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, xStart + istep * stepInCm, MAXSNP, stepInCm, matCorr, &intLT); } // if (std::abs(trc.getSnp()) > MAXSNP) Printf("propagateToRefX: condition on snp not ok, returning false"); diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 118fb9cd5a5f6..e905e32a21854 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -1221,8 +1221,7 @@ void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector) mITSWork.push_back(mITSWork.back()); // clone the last track defined in given sector auto& trc = mITSWork.back(); if (trc.rotate(o2::math_utils::sector2Angle(sector)) && - o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, XMatchingRef, o2::constants::physics::MassPionCharged, MaxSnp, - 2., MatCorrType::USEMatCorrNONE)) { + o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, XMatchingRef, MaxSnp, 2., MatCorrType::USEMatCorrNONE)) { // TODO: use faster prop here, no 3d field, materials mITSSectIndexCache[sector].push_back(mITSWork.size() - 1); // register track CLONE if (mMCTruthON) { @@ -1241,8 +1240,7 @@ bool MatchTPCITS::propagateToRefX(o2::track::TrackParCov& trc) bool refReached = false; refReached = XMatchingRef < 10.; // RS: tmp, to cover XMatchingRef~0 int trialsLeft = 2; - while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, XMatchingRef, o2::constants::physics::MassPionCharged, - MaxSnp, 2., mUseMatCorrFlag)) { + while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, XMatchingRef, MaxSnp, 2., mUseMatCorrFlag)) { if (refReached) { break; } @@ -1391,8 +1389,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) // note: here we also calculate the L,T integral (in the inward direction, but this is irrelevant) // note: we should eventually use TPC pid in the refit (TODO) // note: since we are at small R, we can use field BZ component at origin rather than 3D field - // !propagator->PropagateToXBxByBz(trfit, x, o2::constants::physics::MassPionCharged, - !propagator->propagateToX(trfit, x, propagator->getNominalBz(), o2::constants::physics::MassPionCharged, + !propagator->propagateToX(trfit, x, propagator->getNominalBz(), MaxSnp, maxStep, mUseMatCorrFlag, &trfit.getLTIntegralOut())) { break; } @@ -1414,7 +1411,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) // we need to update the LTOF integral by the distance to the "primary vertex" const o2::dataformats::VertexBase vtxDummy; // at the moment using dummy vertex: TODO use MeanVertex constraint instead - if (!propagator->propagateToDCA(vtxDummy, trfit, propagator->getNominalBz(), o2::constants::physics::MassPionCharged, + if (!propagator->propagateToDCA(vtxDummy, trfit, propagator->getNominalBz(), maxStep, mUseMatCorrFlag, nullptr, &trfit.getLTIntegralOut())) { LOG(ERROR) << "LTOF integral might be incorrect"; } @@ -1451,7 +1448,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) // TODO: consider propagating in empty space till TPC entrance in large step, and then in more detailed propagation with mat. corrections // propagate to 1st cluster X - if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { + if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { LOG(DEBUG) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1489,7 +1486,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) return false; } } - if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, + if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, 10., MatCorrType::USEMatCorrNONE, &trfit.getLTIntegralOut())) { // no material correction! LOG(DEBUG) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); @@ -1505,7 +1502,7 @@ bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) } // propagate to the outer edge of the TPC, TODO: check outer radius // Note: it is allowed to not reach the requested radius - propagator->PropagateToXBxByBz(tracOut, XTPCOuterRef, o2::constants::physics::MassPionCharged, MaxSnp, + propagator->PropagateToXBxByBz(tracOut, XTPCOuterRef, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut()); // LOG(INFO) << "Refitted with chi2 = " << chi2Out; @@ -1577,8 +1574,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) // note: here we also calculate the L,T integral (in the inward direction, but this is irrelevant) // note: we should eventually use TPC pid in the refit (TODO) // note: since we are at small R, we can use field BZ component at origin rather than 3D field - // !propagator->PropagateToXBxByBz(trfit, x, o2::constants::physics::MassPionCharged, - !propagator->propagateToX(trfit, x, propagator->getNominalBz(), o2::constants::physics::MassPionCharged, + !propagator->propagateToX(trfit, x, propagator->getNominalBz(), MaxSnp, maxStep, mUseMatCorrFlag, &trfit.getLTIntegralOut())) { break; } @@ -1600,7 +1596,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) // we need to update the LTOF integral by the distance to the "primary vertex" const o2::dataformats::VertexBase vtxDummy; // at the moment using dummy vertex: TODO use MeanVertex constraint instead - if (!propagator->propagateToDCA(vtxDummy, trfit, propagator->getNominalBz(), o2::constants::physics::MassPionCharged, + if (!propagator->propagateToDCA(vtxDummy, trfit, propagator->getNominalBz(), maxStep, mUseMatCorrFlag, nullptr, &trfit.getLTIntegralOut())) { LOG(ERROR) << "LTOF integral might be incorrect"; } @@ -1644,7 +1640,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) // TODO: consider propagating in empty space till TPC entrance in large step, and then in more detailed propagation with mat. corrections // propagate to 1st cluster X - if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { + if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { LOG(DEBUG) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); mMatchedTracks.pop_back(); // destroy failed track return false; @@ -1682,7 +1678,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) return false; } } - if (!propagator->PropagateToXBxByBz(tracOut, clsX, o2::constants::physics::MassPionCharged, MaxSnp, + if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, 10., MatCorrType::USEMatCorrNONE, &trfit.getLTIntegralOut())) { // no material correction! LOG(DEBUG) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); @@ -1698,7 +1694,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) } // propagate to the outer edge of the TPC, TODO: check outer radius // Note: it is allowed to not reach the requested radius - propagator->PropagateToXBxByBz(tracOut, XTPCOuterRef, o2::constants::physics::MassPionCharged, MaxSnp, + propagator->PropagateToXBxByBz(tracOut, XTPCOuterRef, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut()); // LOG(INFO) << "Refitted with chi2 = " << chi2Out; @@ -1729,7 +1725,7 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) } //______________________________________________ -bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, float xTgt, int trcID, float timeTB, float m) const +bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, float xTgt, int trcID, float timeTB) const { // inward refit constexpr float TolSNP = 0.99; @@ -1793,7 +1789,7 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo } mTPCTransform->Transform(sectArr[icl], rowArr[icl], clsArr[icl]->getPad(), clsArr[icl]->getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); mTPCClusterParam->GetClusterErrors2(rowArr[icl], clsYZ[1], trcIn.getSnp(), trcIn.getTgl(), clsCov[0], clsCov[2]); - if (!propagator->PropagateToXBxByBz(trcIn, clsX, m, TolSNP, 10., MatCorrType::USEMatCorrNONE)) { // no material correction! + if (!propagator->PropagateToXBxByBz(trcIn, clsX, TolSNP, 10., MatCorrType::USEMatCorrNONE)) { // no material correction! LOG(DEBUG) << "Propagation to cluster at X=" << clsX << " failed, Xtr=" << trcIn.getX() << " snp=" << trcIn.getSnp() << " pT=" << trcIn.getPt(); LOG(DEBUG) << trcIn.asString(); @@ -1808,7 +1804,7 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo } // propagate to the inner edge of the TPC // Note: it is allowed to not reach the requested radius - if (!propagator->PropagateToXBxByBz(trcIn, xTgt, m, MaxSnp, 2., mUseMatCorrFlag)) { + if (!propagator->PropagateToXBxByBz(trcIn, xTgt, MaxSnp, 2., mUseMatCorrFlag)) { LOG(DEBUG) << "Propagation to target X=" << xTgt << " failed, Xtr=" << trcIn.getX() << " snp=" << trcIn.getSnp() << " pT=" << trcIn.getPt(); LOG(DEBUG) << trcIn.asString(); return false; @@ -1837,7 +1833,7 @@ int MatchTPCITS::prepareTPCTracksAfterBurner() // which should be good assumption.... float xTgt; if (!tTPC.getXatLabR(ROuter, xTgt, propagator->getNominalBz(), o2::track::DirInward) || - !propagator->PropagateToXBxByBz(tTPC, xTgt, o2::constants::physics::MassPionCharged, MaxSnp, 2., mUseMatCorrFlag)) { + !propagator->PropagateToXBxByBz(tTPC, xTgt, MaxSnp, 2., mUseMatCorrFlag)) { continue; } mTPCABIndexCache.push_back(iTPC); @@ -2031,7 +2027,7 @@ int MatchTPCITS::checkABSeedFromLr(int lrSeed, int seedID, ABTrackLinksList& lli float xTgt; const auto& lr = mRGHelper.layers[lrTgt]; if (!seed.getXatLabR(lr.rRange.getMax(), xTgt, propagator->getNominalBz(), o2::track::DirInward) || - !propagator->PropagateToXBxByBz(seed, xTgt, o2::constants::physics::MassPionCharged, MaxSnp, 2., mUseMatCorrFlag)) { + !propagator->PropagateToXBxByBz(seed, xTgt, MaxSnp, 2., mUseMatCorrFlag)) { return 0; } auto icCandID = seedLink.icCandID; @@ -2399,7 +2395,7 @@ float MatchTPCITS::correctTPCTrack(o2::track::TrackParCov& trc, const TrackLocTP float xTgt; auto propagator = o2::base::Propagator::Instance(); if (!trc.getXatLabR(r, xTgt, propagator->getNominalBz(), o2::track::DirInward) || - !propagator->PropagateToXBxByBz(trc, xTgt, o2::constants::physics::MassPionCharged, MaxSnp, 2., mUseMatCorrFlag)) { + !propagator->PropagateToXBxByBz(trc, xTgt, MaxSnp, 2., mUseMatCorrFlag)) { return -1; } } @@ -2680,8 +2676,7 @@ void MatchTPCITS::refitABTrack(int ibest) const while (ibest > MinusOne) { const auto& lnk = mABTrackLinks[ibest]; if (!trc.rotate(lnk.getAlpha()) || - !propagator->propagateToX(trc, lnk.getX(), propagator->getNominalBz(), o2::constants::physics::MassPionCharged, - MaxSnp, maxStep, mUseMatCorrFlag, nullptr)) { + !propagator->propagateToX(trc, lnk.getX(), propagator->getNominalBz(), MaxSnp, maxStep, mUseMatCorrFlag, nullptr)) { LOG(WARNING) << "Failed to rotate to " << lnk.getAlpha() << " or propagate to " << lnk.getX(); LOG(WARNING) << trc.asString(); break; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index e19952dc1c5ea..add0998d82bb5 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -439,7 +439,7 @@ bool Tracker::fitTrack(const ROframe& event, TrackITSExt& track, int start, int // The correctForMaterial should be called with anglecorr==true if the material budget is the "mean budget in vertical direction" and with false if the the estimated budget already accounts for the track inclination. // Here using !mMatLayerCylSet as its presence triggers update of parameters - if (!track.correctForMaterial(xx0, ((start < end) ? -1. : 1.) * distance * density, 0.14, !mMatLayerCylSet)) { // ~0.14 GeV: mass of charged pion is used by default + if (!track.correctForMaterial(xx0, ((start < end) ? -1. : 1.) * distance * density, !mMatLayerCylSet)) { // ~0.14 GeV: mass of charged pion is used by default return false; } } diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index c5073c92a5de6..126b03ba589ae 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -192,7 +192,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo LOG(DEBUG) << "Failed to rotate track during first extrapolation"; return false; } - if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], o2::constants::physics::MassPionCharged, mMaxSnp, mMaxStep, mMatCorr)) { + if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mMaxSnp, mMaxStep, mMatCorr)) { LOG(DEBUG) << "Failed on first extrapolation"; return false; } @@ -218,7 +218,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo float clTOFX = clTOF.getX(); std::array<float, 2> clTOFYZ{clTOF.getY(), clTOF.getZ()}; std::array<float, 3> clTOFCov{mSigYZ2TOF, 0.f, mSigYZ2TOF}; // assume no correlation between y and z and equal cluster error sigma^2 = (3cm)^2 / 12 - if (!propagator->PropagateToXBxByBz(trkWork, clTOFX, o2::constants::physics::MassPionCharged, mMaxSnp, mMaxStep, mMatCorr)) { + if (!propagator->PropagateToXBxByBz(trkWork, clTOFX, mMaxSnp, mMaxStep, mMatCorr)) { LOG(DEBUG) << "Failed final propagation to TOF radius"; return false; } @@ -236,7 +236,7 @@ bool TrackInterpolation::interpolateTrackITSTOF(const o2::dataformats::MatchInfo LOG(DEBUG) << "Failed to rotate track during back propagation"; return false; } - if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], o2::constants::physics::MassPionCharged, mMaxSnp, mMaxStep, mMatCorr)) { + if (!propagator->PropagateToXBxByBz(trkWork, param::RowX[iRow], mMaxSnp, mMaxStep, mMatCorr)) { LOG(DEBUG) << "Failed on back propagation"; //printf("trkX(%.2f), clX(%.2f), clY(%.2f), clZ(%.2f), alphaTOF(%.2f)\n", trkWork.getX(), param::RowX[iRow], clTOFYZ[0], clTOFYZ[1], clTOFAlpha); return false; @@ -315,7 +315,7 @@ bool TrackInterpolation::extrapolateTrackITS(const o2::its::TrackITS& trkITS, co if (!trk.rotate(o2::math_utils::sector2Angle(sector))) { return false; } - if (!propagator->PropagateToXBxByBz(trk, x, o2::constants::physics::MassPionCharged, mMaxSnp, mMaxStep, mMatCorr)) { + if (!propagator->PropagateToXBxByBz(trk, x, mMaxSnp, mMaxStep, mMatCorr)) { return false; } TPCClusterResiduals res; diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 0612463158b30..7d86bd11e0f04 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -345,7 +345,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) IgnoreErrors(trk.getSnp()); return -1; } - if (!prop->PropagateToXBxByBz(trk, x, o2::constants::physics::MassPionCharged, GPUCA_MAX_SIN_PHI_LOW)) { + if (!prop->PropagateToXBxByBz(trk, x, GPUCA_MAX_SIN_PHI_LOW)) { IgnoreErrors(trk.getSnp()); return -2; } diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h index 0f40cd142d060..f6d71d93c60f6 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h @@ -200,7 +200,7 @@ class propagatorInterface<o2::base::Propagator> propagatorInterface<o2::base::Propagator>(const propagatorInterface<o2::base::Propagator>&) = delete; propagatorInterface<o2::base::Propagator>& operator=(const propagatorInterface<o2::base::Propagator>&) = delete; - bool propagateToX(float x, float maxSnp, float maxStep) { return mProp->PropagateToXBxByBz(*mParam, x, 0.13957, maxSnp, maxStep); } + bool propagateToX(float x, float maxSnp, float maxStep) { return mProp->PropagateToXBxByBz(*mParam, x, maxSnp, maxStep); } int getPropagatedYZ(float x, float& projY, float& projZ) { return static_cast<int>(mParam->getYZAt(x, mProp->getNominalBz(), projY, projZ)); } void setTrack(trackInterface<o2::dataformats::TrackTPCITS>* trk) { mParam = trk; } From 6fc058538738b031279fccf4d5619e136306d530 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 13 Dec 2020 18:04:05 +0100 Subject: [PATCH 1616/1751] Reject outliers when building ITS/MFT clusters dictionary --- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 26 +++++++++++++------ .../ITSMFT/MFT/macros/test/CheckTopologies.C | 10 ++++++- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index a7e7034e3f66c..51597f8b66709 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -35,7 +35,9 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", std::string hitfile = "o2sim_HitsITS.root", std::string collContextfile = "collisioncontext.root", - std::string inputGeom = "") + std::string inputGeom = "", + float checkOutliers = 2., // reject outliers (MC dX or dZ exceeds row/col span by a factor above the threshold) + float minPtMC = 0.01) // account only MC hits with pT above threshold { const int QEDSourceID = 99; // Clusters from this MC source correspond to QED electrons @@ -57,7 +59,7 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", const o2::steer::DigitizationContext* digContext = nullptr; TStopwatch sw; sw.Start(); - + float minPtMC2 = minPtMC > 0 ? minPtMC * minPtMC : -1; // Geometry o2::base::GeometryManager::loadGeometry(inputGeom); auto gman = o2::its::GeometryTGeo::Instance(); @@ -205,12 +207,20 @@ void CheckTopologies(std::string clusfile = "o2clus_its.root", auto hitEntry = mc2hit.find(key); if (hitEntry != mc2hit.end()) { const auto& hit = (*hitArray)[hitEntry->second]; - auto locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local - auto locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); - locH.SetXYZ(0.5 * (locH.X() + locHsta.X()), 0.5 * (locH.Y() + locHsta.Y()), 0.5 * (locH.Z() + locHsta.Z())); - const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern, false); - dX = locH.X() - locC.X(); - dZ = locH.Z() - locC.Z(); + if (minPtMC < 0.f || hit.GetMomentum().Perp2() > minPtMC2) { + auto locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local + auto locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); + locH.SetXYZ(0.5 * (locH.X() + locHsta.X()), 0.5 * (locH.Y() + locHsta.Y()), 0.5 * (locH.Z() + locHsta.Z())); + const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern, false); + dX = locH.X() - locC.X(); + dZ = locH.Z() - locC.Z(); + if (checkOutliers > 0.) { + if (std::abs(dX) > topology.getRowSpan() * o2::itsmft::SegmentationAlpide::PitchRow * checkOutliers || + std::abs(dZ) > topology.getColumnSpan() * o2::itsmft::SegmentationAlpide::PitchCol * checkOutliers) { // ignore outlier + dX = dZ = BuildTopologyDictionary::IgnoreVal; + } + } + } } else { printf("Failed to find MC hit entry for Tr:%d chipID:%d\n", trID, chipID); lab.print(); diff --git a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C index 87690f85485d7..5b67403432d68 100644 --- a/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C @@ -35,7 +35,9 @@ void CheckTopologies(std::string clusfile = "mftclusters.root", std::string hitfile = "o2sim_HitsMFT.root", std::string collContextfile = "collisioncontext.root", - std::string inputGeom = "") + std::string inputGeom = "", + float checkOutliers = 2. // reject outliers (MC dX or dZ exceeds row/col span by a factor above the threshold) +) { const int QEDSourceID = 99; // Clusters from this MC source correspond to QED electrons @@ -211,6 +213,12 @@ void CheckTopologies(std::string clusfile = "mftclusters.root", const auto locC = o2::itsmft::TopologyDictionary::getClusterCoordinates(cluster, pattern); dX = locH.X() - locC.X(); dZ = locH.Z() - locC.Z(); + if (checkOutliers > 0.) { + if (std::abs(dX) > topology.getRowSpan() * o2::itsmft::SegmentationAlpide::PitchRow * checkOutliers || + std::abs(dZ) > topology.getColumnSpan() * o2::itsmft::SegmentationAlpide::PitchCol * checkOutliers) { // ignore outlier + dX = dZ = BuildTopologyDictionary::IgnoreVal; + } + } } else { printf("Failed to find MC hit entry for Tr:%d chipID:%d\n", trID, chipID); lab.print(); From e5587705d57b6f551228044429fa3fd603d9f733 Mon Sep 17 00:00:00 2001 From: amorsch <andreas.morsch@cern.ch> Date: Mon, 14 Dec 2020 09:01:57 +0100 Subject: [PATCH 1617/1751] TPC drift gas settings in case FLUKA is used (#5059) * TPC drift gas settings in case FLUKA is used --- Detectors/TPC/simulation/src/Detector.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index 41e08eb6d9f77..7e49887f8ede7 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -8,6 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "DetectorsBase/MaterialManager.h" #include "TPCSimulation/Detector.h" #include "TPCSimulation/Point.h" #include "TPCBase/ParameterGas.h" @@ -3078,6 +3079,18 @@ void Detector::defineSensitiveVolumes() // set volume sentive AddSensitiveVolume(v); } + + // Special sensitive volume parameters in case FLUKA is used as transport engine + auto vmc = TVirtualMC::GetMC(); + if (strcmp(vmc->GetName(), "TFluka") == 0) { + LOG(INFO) << "Setting special FLUKA parameters for TPC Driftgas"; + auto& mgr = o2::base::MaterialManager::Instance(); + Int_t index = mgr.getMediumID("TPC", kDriftGas2); + vmc->Gstpar(index, "PRIMIO_E", 20.77); + vmc->Gstpar(index, "PRIMIO_N", 14.35); + vmc->Gstpar(index, "LOSS", 14); + vmc->Gstpar(index, "STRA", 4); + } } Double_t Detector::Gamma(Double_t k) From 49406d6afce8700408a98610c022679fbd6e6c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= <mkrueger@ikf.uni-frankfurt.de> Date: Mon, 14 Dec 2020 09:40:41 +0100 Subject: [PATCH 1618/1751] DPL Analysis: use compile-time hashed histogram names in registry (#5050) --- Analysis/Core/include/AnalysisCore/PairCuts.h | 6 +- Analysis/Tasks/PWGCF/correlations.cxx | 5 +- .../Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx | 68 ++++---- Analysis/Tasks/PWGHF/qaTask.cxx | 72 ++++---- Analysis/Tasks/PWGHF/taskD0.cxx | 54 +++--- Analysis/Tasks/PWGHF/taskDPlus.cxx | 48 +++--- Analysis/Tasks/PWGLF/spectraTOF.cxx | 52 +++--- Analysis/Tasks/PWGLF/spectraTPC.cxx | 114 ++++++++----- Analysis/Tasks/pidTOF.cxx | 126 ++++++++------ Analysis/Tasks/pidTPC.cxx | 121 ++++++++------ Analysis/Tasks/trackqa.cxx | 52 +++--- Analysis/Tutorials/src/histogramRegistry.cxx | 76 ++++----- .../include/Framework/HistogramRegistry.h | 157 +++++++++--------- Framework/Core/src/HistogramRegistry.cxx | 50 +++++- .../Core/test/benchmark_HistogramRegistry.cxx | 2 +- .../Core/test/test_HistogramRegistry.cxx | 22 +-- 16 files changed, 580 insertions(+), 445 deletions(-) diff --git a/Analysis/Core/include/AnalysisCore/PairCuts.h b/Analysis/Core/include/AnalysisCore/PairCuts.h index f8918b3dcdf05..a06ee0e23a717 100644 --- a/Analysis/Core/include/AnalysisCore/PairCuts.h +++ b/Analysis/Core/include/AnalysisCore/PairCuts.h @@ -143,7 +143,7 @@ bool PairCuts::twoTrackCut(T const& track1, T const& track2, int bSign) } if (histogramRegistry != nullptr) { - histogramRegistry->fill("TwoTrackDistancePt_0", deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + histogramRegistry->fill(HIST("TwoTrackDistancePt_0"), deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); } if (dphistarminabs < mTwoTrackDistance && TMath::Abs(deta) < mTwoTrackDistance) { @@ -152,7 +152,7 @@ bool PairCuts::twoTrackCut(T const& track1, T const& track2, int bSign) } if (histogramRegistry != nullptr) { - histogramRegistry->fill("TwoTrackDistancePt_1", deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); + histogramRegistry->fill(HIST("TwoTrackDistancePt_1"), deta, dphistarmin, TMath::Abs(track1.pt() - track2.pt())); } } } @@ -212,7 +212,7 @@ bool PairCuts::conversionCut(T const& track1, T const& track2, Particle conv, do massC = getInvMassSquared(track1, massD1, track2, massD2); if (histogramRegistry != nullptr) { - histogramRegistry->fill("ControlConvResonances", static_cast<int>(conv), massC - massM * massM); + histogramRegistry->fill(HIST("ControlConvResonances"), static_cast<int>(conv), massC - massM * massM); } if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) { diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index c8c30890c09a5..af928954017ae 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -177,11 +177,10 @@ struct CorrelationTask { } // NOTE remove when HistogramRegistry uses constexpr strings for lookup - auto& yields = registry.get<TH3>("yields"); - auto& etaphi = registry.get<TH3>("etaphi"); + auto& yields = registry.get<TH3>(HIST("yields")); + auto& etaphi = registry.get<TH3>(HIST("etaphi")); for (auto& track1 : tracks) { - // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); yields->Fill(centrality, track1.pt(), track1.eta()); diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 4e9415435a0a5..eb15aae86c9cd 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -73,7 +73,7 @@ struct SelectTracks { auto trackPt = track.pt(); if (b_dovalplots) { - registry.get<TH1>("hpt_nocuts")->Fill(trackPt); + registry.get<TH1>(HIST("hpt_nocuts"))->Fill(trackPt); } // pT cut @@ -123,14 +123,14 @@ struct SelectTracks { // fill histograms if (b_dovalplots) { if (status_prong & (1 << 0)) { - registry.get<TH1>("hpt_cuts_2prong")->Fill(trackPt); - registry.get<TH1>("hdcatoprimxy_cuts_2prong")->Fill(dca[0]); - registry.get<TH1>("heta_cuts_2prong")->Fill(trackEta); + registry.get<TH1>(HIST("hpt_cuts_2prong"))->Fill(trackPt); + registry.get<TH1>(HIST("hdcatoprimxy_cuts_2prong"))->Fill(dca[0]); + registry.get<TH1>(HIST("heta_cuts_2prong"))->Fill(trackEta); } if (status_prong & (1 << 1)) { - registry.get<TH1>("hpt_cuts_3prong")->Fill(trackPt); - registry.get<TH1>("hdcatoprimxy_cuts_3prong")->Fill(dca[0]); - registry.get<TH1>("heta_cuts_3prong")->Fill(trackEta); + registry.get<TH1>(HIST("hpt_cuts_3prong"))->Fill(trackPt); + registry.get<TH1>(HIST("hdcatoprimxy_cuts_3prong"))->Fill(dca[0]); + registry.get<TH1>(HIST("heta_cuts_3prong"))->Fill(trackEta); } } @@ -441,25 +441,25 @@ struct HFTrackIndexSkimsCreator { // fill histograms if (b_dovalplots) { - registry.get<TH1>("hvtx2_x")->Fill(secondaryVertex2[0]); - registry.get<TH1>("hvtx2_y")->Fill(secondaryVertex2[1]); - registry.get<TH1>("hvtx2_z")->Fill(secondaryVertex2[2]); + registry.get<TH1>(HIST("hvtx2_x"))->Fill(secondaryVertex2[0]); + registry.get<TH1>(HIST("hvtx2_y"))->Fill(secondaryVertex2[1]); + registry.get<TH1>(HIST("hvtx2_z"))->Fill(secondaryVertex2[2]); arrMom = array{pvec0, pvec1}; for (int n2 = 0; n2 < n2ProngDecays; n2++) { if (isSelected2ProngCand & 1 << n2) { if ((cut2ProngInvMassCandMin[n2] < 0. && cut2ProngInvMassCandMax[n2] <= 0.) || (mass2ProngHypo1[n2] >= cut2ProngInvMassCandMin[n2] && mass2ProngHypo1[n2] < cut2ProngInvMassCandMax[n2])) { mass2ProngHypo1[n2] = RecoDecay::M(arrMom, arr2Mass1[n2]); if (n2 == 0) { - registry.get<TH1>("hmassD0")->Fill(mass2ProngHypo1[n2]); + registry.get<TH1>(HIST("hmassD0"))->Fill(mass2ProngHypo1[n2]); } if (n2 == 1) { - registry.get<TH1>("hmassJpsi")->Fill(mass2ProngHypo1[n2]); + registry.get<TH1>(HIST("hmassJpsi"))->Fill(mass2ProngHypo1[n2]); } } if ((cut2ProngInvMassCandMin[n2] < 0. && cut2ProngInvMassCandMax[n2] <= 0.) || (mass2ProngHypo2[n2] >= cut2ProngInvMassCandMin[n2] && mass2ProngHypo2[n2] < cut2ProngInvMassCandMax[n2])) { mass2ProngHypo2[n2] = RecoDecay::M(arrMom, arr2Mass2[n2]); if (n2 == 0) { - registry.get<TH1>("hmassD0")->Fill(mass2ProngHypo1[n2]); + registry.get<TH1>(HIST("hmassD0"))->Fill(mass2ProngHypo1[n2]); } } } @@ -609,31 +609,31 @@ struct HFTrackIndexSkimsCreator { // fill histograms if (b_dovalplots) { - registry.get<TH1>("hvtx3_x")->Fill(secondaryVertex3[0]); - registry.get<TH1>("hvtx3_y")->Fill(secondaryVertex3[1]); - registry.get<TH1>("hvtx3_z")->Fill(secondaryVertex3[2]); + registry.get<TH1>(HIST("hvtx3_x"))->Fill(secondaryVertex3[0]); + registry.get<TH1>(HIST("hvtx3_y"))->Fill(secondaryVertex3[1]); + registry.get<TH1>(HIST("hvtx3_z"))->Fill(secondaryVertex3[2]); arr3Mom = array{pvec0, pvec1, pvec2}; for (int n3 = 0; n3 < n3ProngDecays; n3++) { if (isSelected3ProngCand & 1 << n3) { if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo1[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo1[n3] < cut3ProngInvMassCandMax[n3])) { mass3ProngHypo1[n3] = RecoDecay::M(arr3Mom, arr3Mass1[n3]); if (n3 == 0) { - registry.get<TH1>("hmassDPlus")->Fill(mass3ProngHypo1[n3]); + registry.get<TH1>(HIST("hmassDPlus"))->Fill(mass3ProngHypo1[n3]); } if (n3 == 1) { - registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo1[n3]); + registry.get<TH1>(HIST("hmassLc"))->Fill(mass3ProngHypo1[n3]); } if (n3 == 2) { - registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo1[n3]); + registry.get<TH1>(HIST("hmassDs"))->Fill(mass3ProngHypo1[n3]); } } if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo2[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo2[n3] < cut3ProngInvMassCandMax[n3])) { mass3ProngHypo2[n3] = RecoDecay::M(arr3Mom, arr3Mass2[n3]); if (n3 == 1) { - registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo2[n3]); + registry.get<TH1>(HIST("hmassLc"))->Fill(mass3ProngHypo2[n3]); } if (n3 == 2) { - registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo2[n3]); + registry.get<TH1>(HIST("hmassDs"))->Fill(mass3ProngHypo2[n3]); } } } @@ -776,31 +776,31 @@ struct HFTrackIndexSkimsCreator { // fill histograms if (b_dovalplots) { - registry.get<TH1>("hvtx3_x")->Fill(secondaryVertex3[0]); - registry.get<TH1>("hvtx3_y")->Fill(secondaryVertex3[1]); - registry.get<TH1>("hvtx3_z")->Fill(secondaryVertex3[2]); + registry.get<TH1>(HIST("hvtx3_x"))->Fill(secondaryVertex3[0]); + registry.get<TH1>(HIST("hvtx3_y"))->Fill(secondaryVertex3[1]); + registry.get<TH1>(HIST("hvtx3_z"))->Fill(secondaryVertex3[2]); arr3Mom = array{pvec0, pvec1, pvec2}; for (int n3 = 0; n3 < n3ProngDecays; n3++) { if (isSelected3ProngCand & 1 << n3) { if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo1[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo1[n3] < cut3ProngInvMassCandMax[n3])) { mass3ProngHypo1[n3] = RecoDecay::M(arr3Mom, arr3Mass1[n3]); if (n3 == 0) { - registry.get<TH1>("hmassDPlus")->Fill(mass3ProngHypo1[n3]); + registry.get<TH1>(HIST("hmassDPlus"))->Fill(mass3ProngHypo1[n3]); } if (n3 == 1) { - registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo1[n3]); + registry.get<TH1>(HIST("hmassLc"))->Fill(mass3ProngHypo1[n3]); } if (n3 == 2) { - registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo1[n3]); + registry.get<TH1>(HIST("hmassDs"))->Fill(mass3ProngHypo1[n3]); } } if ((cut3ProngInvMassCandMin[n3] < 0. && cut3ProngInvMassCandMax[n3] <= 0.) || (mass3ProngHypo2[n3] >= cut3ProngInvMassCandMin[n3] && mass3ProngHypo2[n3] < cut3ProngInvMassCandMax[n3])) { mass3ProngHypo2[n3] = RecoDecay::M(arr3Mom, arr3Mass2[n3]); if (n3 == 1) { - registry.get<TH1>("hmassLc")->Fill(mass3ProngHypo2[n3]); + registry.get<TH1>(HIST("hmassLc"))->Fill(mass3ProngHypo2[n3]); } if (n3 == 2) { - registry.get<TH1>("hmassDs")->Fill(mass3ProngHypo2[n3]); + registry.get<TH1>(HIST("hmassDs"))->Fill(mass3ProngHypo2[n3]); } } } @@ -815,11 +815,11 @@ struct HFTrackIndexSkimsCreator { nCand2 = rowTrackIndexProng2.lastIndex() - nCand2; // number of 2-prong candidates in this collision nCand3 = rowTrackIndexProng3.lastIndex() - nCand3; // number of 3-prong candidates in this collision - registry.get<TH1>("hNTracks")->Fill(nTracks); - registry.get<TH1>("hNCand2Prong")->Fill(nCand2); - registry.get<TH1>("hNCand3Prong")->Fill(nCand3); - registry.get<TH2>("hNCand2ProngVsNTracks")->Fill(nTracks, nCand2); - registry.get<TH2>("hNCand3ProngVsNTracks")->Fill(nTracks, nCand3); + registry.get<TH1>(HIST("hNTracks"))->Fill(nTracks); + registry.get<TH1>(HIST("hNCand2Prong"))->Fill(nCand2); + registry.get<TH1>(HIST("hNCand3Prong"))->Fill(nCand3); + registry.get<TH2>(HIST("hNCand2ProngVsNTracks"))->Fill(nTracks, nCand2); + registry.get<TH2>(HIST("hNCand3ProngVsNTracks"))->Fill(nTracks, nCand3); } }; diff --git a/Analysis/Tasks/PWGHF/qaTask.cxx b/Analysis/Tasks/PWGHF/qaTask.cxx index 04da7b327d955..e6fa820857843 100644 --- a/Analysis/Tasks/PWGHF/qaTask.cxx +++ b/Analysis/Tasks/PWGHF/qaTask.cxx @@ -201,28 +201,28 @@ struct QAGlobalObservables { void process(const o2::aod::Collision& collision, const o2::aod::Tracks& tracks) { eventCount->Fill(0); - histograms.fill("collision/collisionX", collision.posX()); - histograms.fill("collision/collisionY", collision.posY()); - histograms.fill("collision/collisionZ", collision.posZ()); + histograms.fill(HIST("collision/collisionX"), collision.posX()); + histograms.fill(HIST("collision/collisionY"), collision.posY()); + histograms.fill(HIST("collision/collisionZ"), collision.posZ()); int nTracks(0); for (const auto& track : tracks) { nTracks++; } - histograms.fill("multiplicity/numberOfTracks", nTracks); + histograms.fill(HIST("multiplicity/numberOfTracks"), nTracks); // fill covariance variables - histograms.fill("Covariance/xx", collision.covXX()); - histograms.fill("Covariance/xy", collision.covXY()); - histograms.fill("Covariance/xz", collision.covXZ()); - histograms.fill("Covariance/yy", collision.covYY()); - histograms.fill("Covariance/yz", collision.covYZ()); - histograms.fill("Covariance/zz", collision.covZZ()); + histograms.fill(HIST("Covariance/xx"), collision.covXX()); + histograms.fill(HIST("Covariance/xy"), collision.covXY()); + histograms.fill(HIST("Covariance/xz"), collision.covXZ()); + histograms.fill(HIST("Covariance/yy"), collision.covYY()); + histograms.fill(HIST("Covariance/yz"), collision.covYZ()); + histograms.fill(HIST("Covariance/zz"), collision.covZZ()); // fill quality variables - histograms.fill("Quality/Chi2", collision.chi2()); - histograms.fill("Quality/Contributors", collision.numContrib()); + histograms.fill(HIST("Quality/Chi2"), collision.chi2()); + histograms.fill(HIST("Quality/Contributors"), collision.numContrib()); } }; @@ -249,9 +249,9 @@ struct QATrackingKine { void process(const o2::aod::Track& track) { - histos.fill("tracking/eta", track.eta()); - histos.fill("tracking/pt", track.pt()); - histos.fill("tracking/phi", track.phi()); + histos.fill(HIST("tracking/eta"), track.eta()); + histos.fill(HIST("tracking/pt"), track.pt()); + histos.fill(HIST("tracking/phi"), track.phi()); } }; @@ -393,22 +393,22 @@ struct QATrackingResolution { for (const auto& track : tracks) { const double deltaPt = track.label().pt() - track.pt(); - histos.fill("pt/ptDiffMCRec", deltaPt); + histos.fill(HIST("pt/ptDiffMCRec"), deltaPt); const double deltaPtOverPt = deltaPt / track.pt(); - histos.fill("pt/ptResolution", deltaPtOverPt); - histos.fill("pt/ptResolutionVsPt", track.pt(), std::abs(deltaPtOverPt)); - histos.fill("pt/ptResolutionVsEta", track.eta(), std::abs(deltaPtOverPt)); - histos.fill("pt/ptResolutionVsPhi", track.phi(), std::abs(deltaPtOverPt)); + histos.fill(HIST("pt/ptResolution"), deltaPtOverPt); + histos.fill(HIST("pt/ptResolutionVsPt"), track.pt(), std::abs(deltaPtOverPt)); + histos.fill(HIST("pt/ptResolutionVsEta"), track.eta(), std::abs(deltaPtOverPt)); + histos.fill(HIST("pt/ptResolutionVsPhi"), track.phi(), std::abs(deltaPtOverPt)); const double deltaEta = track.label().eta() - track.eta(); - histos.fill("eta/etaDiffMCReco", deltaEta); - histos.fill("eta/etaDiffMCRecoVsEtaMC", deltaEta, track.label().eta()); - histos.fill("eta/etaDiffMCRecoVsEtaReco", deltaEta, track.eta()); + histos.fill(HIST("eta/etaDiffMCReco"), deltaEta); + histos.fill(HIST("eta/etaDiffMCRecoVsEtaMC"), deltaEta, track.label().eta()); + histos.fill(HIST("eta/etaDiffMCRecoVsEtaReco"), deltaEta, track.eta()); const double deltaPhi = track_utils::ConvertPhiRange(track.label().phi() - track.phi()); - histos.fill("phi/phiDiffMCRec", deltaPhi); + histos.fill(HIST("phi/phiDiffMCRec"), deltaPhi); double impactParameterRPhi{-999.}, impactParameterRPhiError{-999.}; double impactParameterZ{-999.}, impactParameterErrorZ{-999.}; @@ -417,21 +417,21 @@ struct QATrackingResolution { track, primaryVertex, impactParameterRPhi, impactParameterRPhiError, impactParameterZ, impactParameterErrorZ); if (propagate) { - histos.fill("impactParameter/impactParameterRPhiVsPt", track.pt(), impactParameterRPhi); - histos.fill("impactParameter/impactParameterRPhiVsEta", track.eta(), impactParameterRPhi); - histos.fill("impactParameter/impactParameterRPhiVsPhi", track.phi(), impactParameterRPhi); + histos.fill(HIST("impactParameter/impactParameterRPhiVsPt"), track.pt(), impactParameterRPhi); + histos.fill(HIST("impactParameter/impactParameterRPhiVsEta"), track.eta(), impactParameterRPhi); + histos.fill(HIST("impactParameter/impactParameterRPhiVsPhi"), track.phi(), impactParameterRPhi); - histos.fill("impactParameter/impactParameterZVsPt", track.pt(), impactParameterZ); - histos.fill("impactParameter/impactParameterZVsEta", track.eta(), impactParameterZ); - histos.fill("impactParameter/impactParameterZVsPhi", track.phi(), impactParameterZ); + histos.fill(HIST("impactParameter/impactParameterZVsPt"), track.pt(), impactParameterZ); + histos.fill(HIST("impactParameter/impactParameterZVsEta"), track.eta(), impactParameterZ); + histos.fill(HIST("impactParameter/impactParameterZVsPhi"), track.phi(), impactParameterZ); - histos.fill("impactParameter/impactParameterErrorRPhiVsPt", track.pt(), impactParameterRPhiError); - histos.fill("impactParameter/impactParameterErrorRPhiVsEta", track.eta(), impactParameterRPhiError); - histos.fill("impactParameter/impactParameterErrorRPhiVsPhi", track.phi(), impactParameterRPhiError); + histos.fill(HIST("impactParameter/impactParameterErrorRPhiVsPt"), track.pt(), impactParameterRPhiError); + histos.fill(HIST("impactParameter/impactParameterErrorRPhiVsEta"), track.eta(), impactParameterRPhiError); + histos.fill(HIST("impactParameter/impactParameterErrorRPhiVsPhi"), track.phi(), impactParameterRPhiError); - histos.fill("impactParameter/impactParameterErrorZVsPt", track.pt(), impactParameterErrorZ); - histos.fill("impactParameter/impactParameterErrorZVsEta", track.eta(), impactParameterErrorZ); - histos.fill("impactParameter/impactParameterErrorZVsPhi", track.phi(), impactParameterErrorZ); + histos.fill(HIST("impactParameter/impactParameterErrorZVsPt"), track.pt(), impactParameterErrorZ); + histos.fill(HIST("impactParameter/impactParameterErrorZVsEta"), track.eta(), impactParameterErrorZ); + histos.fill(HIST("impactParameter/impactParameterErrorZVsPhi"), track.phi(), impactParameterErrorZ); } } } diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index 8cbd50fcd6556..6089c4bf2d6aa 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -69,28 +69,28 @@ struct TaskD0 { continue; } if (candidate.isSelD0() >= d_selectionFlagD0) { - registry.get<TH1>("hmass")->Fill(InvMassD0(candidate)); + registry.get<TH1>(HIST("hmass"))->Fill(InvMassD0(candidate)); } if (candidate.isSelD0bar() >= d_selectionFlagD0bar) { - registry.get<TH1>("hmass")->Fill(InvMassD0bar(candidate)); + registry.get<TH1>(HIST("hmass"))->Fill(InvMassD0bar(candidate)); } - registry.get<TH1>("hptcand")->Fill(candidate.pt()); - registry.get<TH1>("hptprong0")->Fill(candidate.ptProng0()); - registry.get<TH1>("hptprong1")->Fill(candidate.ptProng1()); - registry.get<TH1>("hdeclength")->Fill(candidate.decayLength()); - registry.get<TH1>("hdeclengthxy")->Fill(candidate.decayLengthXY()); - registry.get<TH1>("hd0Prong0")->Fill(candidate.impactParameter0()); - registry.get<TH1>("hd0Prong1")->Fill(candidate.impactParameter1()); - registry.get<TH1>("hd0d0")->Fill(candidate.impactParameterProduct()); - registry.get<TH1>("hCTS")->Fill(CosThetaStarD0(candidate)); - registry.get<TH1>("hCt")->Fill(CtD0(candidate)); - registry.get<TH1>("hCPA")->Fill(candidate.cpa()); - registry.get<TH1>("hEta")->Fill(candidate.eta()); - registry.get<TH1>("hselectionstatus")->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); - registry.get<TH1>("hImpParErr")->Fill(candidate.errorImpactParameter0()); - registry.get<TH1>("hImpParErr")->Fill(candidate.errorImpactParameter1()); - registry.get<TH1>("hDecLenErr")->Fill(candidate.errorDecayLength()); - registry.get<TH1>("hDecLenXYErr")->Fill(candidate.errorDecayLengthXY()); + registry.get<TH1>(HIST("hptcand"))->Fill(candidate.pt()); + registry.get<TH1>(HIST("hptprong0"))->Fill(candidate.ptProng0()); + registry.get<TH1>(HIST("hptprong1"))->Fill(candidate.ptProng1()); + registry.get<TH1>(HIST("hdeclength"))->Fill(candidate.decayLength()); + registry.get<TH1>(HIST("hdeclengthxy"))->Fill(candidate.decayLengthXY()); + registry.get<TH1>(HIST("hd0Prong0"))->Fill(candidate.impactParameter0()); + registry.get<TH1>(HIST("hd0Prong1"))->Fill(candidate.impactParameter1()); + registry.get<TH1>(HIST("hd0d0"))->Fill(candidate.impactParameterProduct()); + registry.get<TH1>(HIST("hCTS"))->Fill(CosThetaStarD0(candidate)); + registry.get<TH1>(HIST("hCt"))->Fill(CtD0(candidate)); + registry.get<TH1>(HIST("hCPA"))->Fill(candidate.cpa()); + registry.get<TH1>(HIST("hEta"))->Fill(candidate.eta()); + registry.get<TH1>(HIST("hselectionstatus"))->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); + registry.get<TH1>(HIST("hImpParErr"))->Fill(candidate.errorImpactParameter0()); + registry.get<TH1>(HIST("hImpParErr"))->Fill(candidate.errorImpactParameter1()); + registry.get<TH1>(HIST("hDecLenErr"))->Fill(candidate.errorDecayLength()); + registry.get<TH1>(HIST("hDecLenXYErr"))->Fill(candidate.errorDecayLengthXY()); } } }; @@ -125,13 +125,13 @@ struct TaskD0MC { continue; } if (std::abs(candidate.flagMCMatchRec()) == D0ToPiK) { - registry.get<TH1>("hPtRecSig")->Fill(candidate.pt()); - registry.get<TH1>("hCPARecSig")->Fill(candidate.cpa()); - registry.get<TH1>("hEtaRecSig")->Fill(candidate.eta()); + registry.get<TH1>(HIST("hPtRecSig"))->Fill(candidate.pt()); + registry.get<TH1>(HIST("hCPARecSig"))->Fill(candidate.cpa()); + registry.get<TH1>(HIST("hEtaRecSig"))->Fill(candidate.eta()); } else { - registry.get<TH1>("hPtRecBg")->Fill(candidate.pt()); - registry.get<TH1>("hCPARecBg")->Fill(candidate.cpa()); - registry.get<TH1>("hEtaRecBg")->Fill(candidate.eta()); + registry.get<TH1>(HIST("hPtRecBg"))->Fill(candidate.pt()); + registry.get<TH1>(HIST("hCPARecBg"))->Fill(candidate.cpa()); + registry.get<TH1>(HIST("hEtaRecBg"))->Fill(candidate.eta()); } } // MC gen. @@ -142,8 +142,8 @@ struct TaskD0MC { continue; } if (std::abs(particle.flagMCMatchGen()) == D0ToPiK) { - registry.get<TH1>("hPtGen")->Fill(particle.pt()); - registry.get<TH1>("hEtaGen")->Fill(particle.eta()); + registry.get<TH1>(HIST("hPtGen"))->Fill(particle.pt()); + registry.get<TH1>(HIST("hEtaGen"))->Fill(particle.eta()); } } } diff --git a/Analysis/Tasks/PWGHF/taskDPlus.cxx b/Analysis/Tasks/PWGHF/taskDPlus.cxx index 019bed11abe42..324ad85c00cfb 100644 --- a/Analysis/Tasks/PWGHF/taskDPlus.cxx +++ b/Analysis/Tasks/PWGHF/taskDPlus.cxx @@ -62,30 +62,30 @@ struct TaskDPlus { void process(aod::HfCandProng3 const& candidates) { for (auto& candidate : candidates) { - registry.get<TH1>("hMass")->Fill(InvMassDPlus(candidate)); - registry.get<TH1>("hPt")->Fill(candidate.pt()); - registry.get<TH1>("hEta")->Fill(candidate.eta()); - registry.get<TH1>("hCt")->Fill(CtDPlus(candidate)); - registry.get<TH1>("hDecayLength")->Fill(candidate.decayLength()); - registry.get<TH1>("hDecayLengthXY")->Fill(candidate.decayLengthXY()); - registry.get<TH1>("hNormalisedDecayLengthXY")->Fill(candidate.decayLengthXYNormalised()); - registry.get<TH1>("hCPA")->Fill(candidate.cpa()); - registry.get<TH1>("hCPAxy")->Fill(candidate.cpaXY()); - registry.get<TH1>("hImpactParameterXY")->Fill(candidate.impactParameterXY()); - registry.get<TH1>("hMaxNormalisedDeltaIP")->Fill(candidate.maxNormalisedDeltaIP()); - registry.get<TH1>("hImpactParameterProngSqSum")->Fill(candidate.impactParameterProngSqSum()); - registry.get<TH1>("hDecayLengthError")->Fill(candidate.errorDecayLength()); - registry.get<TH1>("hDecayLengthXYError")->Fill(candidate.errorDecayLengthXY()); - registry.get<TH1>("hImpactParameterError")->Fill(candidate.errorImpactParameter0()); - registry.get<TH1>("hImpactParameterError")->Fill(candidate.errorImpactParameter1()); - registry.get<TH1>("hImpactParameterError")->Fill(candidate.errorImpactParameter2()); - registry.get<TH1>("hPtProng0")->Fill(candidate.ptProng0()); - registry.get<TH1>("hPtProng1")->Fill(candidate.ptProng1()); - registry.get<TH1>("hPtProng2")->Fill(candidate.ptProng2()); - registry.get<TH1>("hd0Prong0")->Fill(candidate.impactParameter0()); - registry.get<TH1>("hd0Prong1")->Fill(candidate.impactParameter1()); - registry.get<TH1>("hd0Prong2")->Fill(candidate.impactParameter2()); - //registry.get<TH1>("hSelectionStatus")->Fill(candidate.isSelDPlus()); + registry.get<TH1>(HIST("hMass"))->Fill(InvMassDPlus(candidate)); + registry.get<TH1>(HIST("hPt"))->Fill(candidate.pt()); + registry.get<TH1>(HIST("hEta"))->Fill(candidate.eta()); + registry.get<TH1>(HIST("hCt"))->Fill(CtDPlus(candidate)); + registry.get<TH1>(HIST("hDecayLength"))->Fill(candidate.decayLength()); + registry.get<TH1>(HIST("hDecayLengthXY"))->Fill(candidate.decayLengthXY()); + registry.get<TH1>(HIST("hNormalisedDecayLengthXY"))->Fill(candidate.decayLengthXYNormalised()); + registry.get<TH1>(HIST("hCPA"))->Fill(candidate.cpa()); + registry.get<TH1>(HIST("hCPAxy"))->Fill(candidate.cpaXY()); + registry.get<TH1>(HIST("hImpactParameterXY"))->Fill(candidate.impactParameterXY()); + registry.get<TH1>(HIST("hMaxNormalisedDeltaIP"))->Fill(candidate.maxNormalisedDeltaIP()); + registry.get<TH1>(HIST("hImpactParameterProngSqSum"))->Fill(candidate.impactParameterProngSqSum()); + registry.get<TH1>(HIST("hDecayLengthError"))->Fill(candidate.errorDecayLength()); + registry.get<TH1>(HIST("hDecayLengthXYError"))->Fill(candidate.errorDecayLengthXY()); + registry.get<TH1>(HIST("hImpactParameterError"))->Fill(candidate.errorImpactParameter0()); + registry.get<TH1>(HIST("hImpactParameterError"))->Fill(candidate.errorImpactParameter1()); + registry.get<TH1>(HIST("hImpactParameterError"))->Fill(candidate.errorImpactParameter2()); + registry.get<TH1>(HIST("hPtProng0"))->Fill(candidate.ptProng0()); + registry.get<TH1>(HIST("hPtProng1"))->Fill(candidate.ptProng1()); + registry.get<TH1>(HIST("hPtProng2"))->Fill(candidate.ptProng2()); + registry.get<TH1>(HIST("hd0Prong0"))->Fill(candidate.impactParameter0()); + registry.get<TH1>(HIST("hd0Prong1"))->Fill(candidate.impactParameter1()); + registry.get<TH1>(HIST("hd0Prong2"))->Fill(candidate.impactParameter2()); + //registry.get<TH1>(HIST("hSelectionStatus"))->Fill(candidate.isSelDPlus()); } } }; diff --git a/Analysis/Tasks/PWGLF/spectraTOF.cxx b/Analysis/Tasks/PWGLF/spectraTOF.cxx index 685c39ba3dc5a..0f7052c4adb7a 100644 --- a/Analysis/Tasks/PWGLF/spectraTOF.cxx +++ b/Analysis/Tasks/PWGLF/spectraTOF.cxx @@ -24,8 +24,8 @@ using namespace o2::framework::expressions; struct TOFSpectraTask { static constexpr int Np = 9; static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; - static constexpr const char* hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; - static constexpr const char* hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; + static constexpr std::string_view hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr std::string_view hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) @@ -33,8 +33,8 @@ struct TOFSpectraTask { histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); for (int i = 0; i < Np; i++) { - histos.add(hp[i], Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); - histos.add(hpt[i], Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hp[i].data(), Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i].data(), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); } histos.add("electronbeta/hp_El", ";#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); histos.add("electronbeta/hpt_El", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); @@ -44,6 +44,16 @@ struct TOFSpectraTask { histos.add("electronbeta/hp_betasigma_El", ";#it{p} (GeV/#it{c});(#beta - #beta_{e})/#sigma;Tracks", kTH2D, {{100, 0, 20}, {100, -5, 5}}); } + template <std::size_t i, typename T> + void fillParticleHistos(const T& track, const float nsigma[]) + { + if (abs(nsigma[i]) > nsigmacut.value) { + return; + } + histos.fill(HIST(hp[i]), track.p()); + histos.fill(HIST(hpt[i]), track.pt()); + } + Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; @@ -56,23 +66,27 @@ struct TOFSpectraTask { const float nsigma[Np] = {track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl()}; - histos.fill("p/Unselected", track.p()); - histos.fill("pt/Unselected", track.pt()); - for (int i = 0; i < Np; i++) { - if (abs(nsigma[i]) > nsigmacut.value) { - continue; - } - histos.fill(hp[i], track.p()); - histos.fill(hpt[i], track.pt()); - } + histos.fill(HIST("p/Unselected"), track.p()); + histos.fill(HIST("pt/Unselected"), track.pt()); + + fillParticleHistos<0>(track, nsigma); + fillParticleHistos<1>(track, nsigma); + fillParticleHistos<2>(track, nsigma); + fillParticleHistos<3>(track, nsigma); + fillParticleHistos<4>(track, nsigma); + fillParticleHistos<5>(track, nsigma); + fillParticleHistos<6>(track, nsigma); + fillParticleHistos<7>(track, nsigma); + fillParticleHistos<8>(track, nsigma); + // if (TMath::Abs(track.separationbetael() < 1.f)) { - histos.fill("electronbeta/hp_El", track.p()); - histos.fill("electronbeta/hpt_El", track.pt()); - histos.fill("electronbeta/hlength_El", track.length()); - histos.fill("electronbeta/htime_El", track.tofSignal() / 1000); - histos.fill("electronbeta/hp_beta_El", track.p(), track.diffbetael()); - histos.fill("electronbeta/hp_betasigma_El", track.p(), track.separationbetael()); + histos.fill(HIST("electronbeta/hp_El"), track.p()); + histos.fill(HIST("electronbeta/hpt_El"), track.pt()); + histos.fill(HIST("electronbeta/hlength_El"), track.length()); + histos.fill(HIST("electronbeta/htime_El"), track.tofSignal() / 1000); + histos.fill(HIST("electronbeta/hp_beta_El"), track.p(), track.diffbetael()); + histos.fill(HIST("electronbeta/hp_betasigma_El"), track.p(), track.separationbetael()); } } }; diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index d85efbf5f1e5b..84918ed15f349 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -35,26 +35,31 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; \ Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true); -#define makelogaxis(h) \ - { \ - const Int_t nbins = h->GetNbinsX(); \ - double binp[nbins + 1]; \ - double max = h->GetXaxis()->GetBinUpEdge(nbins); \ - double min = h->GetXaxis()->GetBinLowEdge(1); \ - double lmin = TMath::Log10(min); \ - double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); \ - for (int i = 0; i < nbins; i++) { \ - binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); \ - } \ - binp[nbins] = max + 1; \ - h->GetXaxis()->Set(nbins, binp); \ +// FIXME: we should put this function in some common header so it has to be defined only once +template <typename T> +void makelogaxis(T h) +{ + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); +} constexpr int Np = 9; struct TPCSpectraTask { static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; - static constexpr const char* hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; - static constexpr const char* hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; + static constexpr std::string_view hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr std::string_view hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) @@ -62,8 +67,8 @@ struct TPCSpectraTask { histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); for (int i = 0; i < Np; i++) { - histos.add(hp[i], Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); - histos.add(hpt[i], Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hp[i].data(), Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i].data(), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); } } @@ -72,37 +77,62 @@ struct TPCSpectraTask { Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; + template <std::size_t i, typename T> + void fillParticleHistos(const T& track, const float nsigma[]) + { + if (abs(nsigma[i]) > nsigmacut.value) { + return; + } + histos.fill(HIST(hp[i]), track.p()); + histos.fill(HIST(hpt[i]), track.pt()); + } + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>>; void process(TrackCandidates::iterator const& track) { const float nsigma[Np] = {track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl()}; - histos.fill("p/Unselected", track.p()); - histos.fill("pt/Unselected", track.pt()); - for (int i = 0; i < Np; i++) { - if (abs(nsigma[i]) > nsigmacut.value) { - continue; - } - histos.fill(hp[i], track.p()); - histos.fill(hpt[i], track.pt()); - } + histos.fill(HIST("p/Unselected"), track.p()); + histos.fill(HIST("pt/Unselected"), track.pt()); + + fillParticleHistos<0>(track, nsigma); + fillParticleHistos<1>(track, nsigma); + fillParticleHistos<2>(track, nsigma); + fillParticleHistos<3>(track, nsigma); + fillParticleHistos<4>(track, nsigma); + fillParticleHistos<5>(track, nsigma); + fillParticleHistos<6>(track, nsigma); + fillParticleHistos<7>(track, nsigma); + fillParticleHistos<8>(track, nsigma); } }; struct TPCPIDQASignalwTOFTask { static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; - static constexpr const char* htpcsignal[Np] = {"tpcsignal/El", "tpcsignal/Mu", "tpcsignal/Pi", - "tpcsignal/Ka", "tpcsignal/Pr", "tpcsignal/De", - "tpcsignal/Tr", "tpcsignal/He", "tpcsignal/Al"}; + static constexpr std::string_view htpcsignal[Np] = {"tpcsignal/El", "tpcsignal/Mu", "tpcsignal/Pi", + "tpcsignal/Ka", "tpcsignal/Pr", "tpcsignal/De", + "tpcsignal/Tr", "tpcsignal/He", "tpcsignal/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + template <uint8_t i> + void addParticleHistos() + { + histos.add(htpcsignal[i].data(), Form(";#it{p} (GeV/#it{c});TPC Signal;N_{#sigma}^{TPC}(%s)", pT[i]), kTH3D, {{1000, 0.001, 20}, {1000, 0, 1000}, {20, -10, 10}}); + makelogaxis(histos.get<TH3>(HIST(htpcsignal[i]))); + } + void init(o2::framework::InitContext&) { - for (int i = 0; i < Np; i++) { - histos.add(htpcsignal[i], Form(";#it{p} (GeV/#it{c});TPC Signal;N_{#sigma}^{TPC}(%s)", pT[i]), kTH3D, {{1000, 0.001, 20}, {1000, 0, 1000}, {20, -10, 10}}); - makelogaxis(histos.get<TH3>(htpcsignal[i])); - } + addParticleHistos<0>(); + addParticleHistos<1>(); + addParticleHistos<2>(); + addParticleHistos<3>(); + addParticleHistos<4>(); + addParticleHistos<5>(); + addParticleHistos<6>(); + addParticleHistos<7>(); + addParticleHistos<8>(); } // Filters @@ -114,15 +144,15 @@ struct TPCPIDQASignalwTOFTask { { // const float mom = track.p(); const float mom = track.tpcInnerParam(); - histos.fill(htpcsignal[0], mom, track.tpcSignal(), track.tofNSigmaEl()); - histos.fill(htpcsignal[1], mom, track.tpcSignal(), track.tofNSigmaMu()); - histos.fill(htpcsignal[2], mom, track.tpcSignal(), track.tofNSigmaPi()); - histos.fill(htpcsignal[3], mom, track.tpcSignal(), track.tofNSigmaKa()); - histos.fill(htpcsignal[4], mom, track.tpcSignal(), track.tofNSigmaPr()); - histos.fill(htpcsignal[5], mom, track.tpcSignal(), track.tofNSigmaDe()); - histos.fill(htpcsignal[6], mom, track.tpcSignal(), track.tofNSigmaTr()); - histos.fill(htpcsignal[7], mom, track.tpcSignal(), track.tofNSigmaHe()); - histos.fill(htpcsignal[8], mom, track.tpcSignal(), track.tofNSigmaAl()); + histos.fill(HIST(htpcsignal[0]), mom, track.tpcSignal(), track.tofNSigmaEl()); + histos.fill(HIST(htpcsignal[1]), mom, track.tpcSignal(), track.tofNSigmaMu()); + histos.fill(HIST(htpcsignal[2]), mom, track.tpcSignal(), track.tofNSigmaPi()); + histos.fill(HIST(htpcsignal[3]), mom, track.tpcSignal(), track.tofNSigmaKa()); + histos.fill(HIST(htpcsignal[4]), mom, track.tpcSignal(), track.tofNSigmaPr()); + histos.fill(HIST(htpcsignal[5]), mom, track.tpcSignal(), track.tofNSigmaDe()); + histos.fill(HIST(htpcsignal[6]), mom, track.tpcSignal(), track.tofNSigmaTr()); + histos.fill(HIST(htpcsignal[7]), mom, track.tpcSignal(), track.tofNSigmaHe()); + histos.fill(HIST(htpcsignal[8]), mom, track.tpcSignal(), track.tofNSigmaAl()); } }; diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index b7b41534485f1..01b7c3654962f 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -136,16 +136,17 @@ struct pidTOFTaskBeta { }; struct pidTOFTaskQA { + static constexpr int Np = 9; - static constexpr const char* hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", - "expected/Ka", "expected/Pr", "expected/De", - "expected/Tr", "expected/He", "expected/Al"}; - static constexpr const char* hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", - "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", - "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; - static constexpr const char* hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", - "nsigma/Ka", "nsigma/Pr", "nsigma/De", - "nsigma/Tr", "nsigma/He", "nsigma/Al"}; + static constexpr std::string_view hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", + "expected/Ka", "expected/Pr", "expected/De", + "expected/Tr", "expected/He", "expected/Al"}; + static constexpr std::string_view hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", + "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", + "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; + static constexpr std::string_view hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", + "nsigma/Ka", "nsigma/Pr", "nsigma/De", + "nsigma/Tr", "nsigma/He", "nsigma/Al"}; static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; @@ -153,21 +154,39 @@ struct pidTOFTaskQA { Configurable<float> MinP{"MinP", 0.1, "Minimum momentum in range"}; Configurable<float> MaxP{"MaxP", 5, "Maximum momentum in range"}; -#define makelogaxis(h) \ - { \ - const Int_t nbins = h->GetNbinsX(); \ - double binp[nbins + 1]; \ - double max = h->GetXaxis()->GetBinUpEdge(nbins); \ - double min = h->GetXaxis()->GetBinLowEdge(1); \ - if (min <= 0) \ - min = 0.00001; \ - double lmin = TMath::Log10(min); \ - double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); \ - for (int i = 0; i < nbins; i++) { \ - binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); \ - } \ - binp[nbins] = max + 1; \ - h->GetXaxis()->Set(nbins, binp); \ + template <typename T> + void makelogaxis(T h) + { + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); + } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); + } + + template <uint8_t i> + void addParticleHistos() + { + // Exp signal + histos.add(hexpected[i].data(), Form(";#it{p} (GeV/#it{c});t_{exp}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2e6}}); + makelogaxis(histos.get<TH2>(HIST(hexpected[i]))); + + // T-Texp + histos.add(hexpected_diff[i].data(), Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp}(%s))", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {100, -1000, 1000}}); + makelogaxis(histos.get<TH2>(HIST(hexpected_diff[i]))); + + // NSigma + histos.add(hnsigma[i].data(), Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get<TH2>(HIST(hnsigma[i]))); } void init(o2::framework::InitContext&) @@ -176,27 +195,33 @@ struct pidTOFTaskQA { histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", HistType::kTH1F, {{100, -20, 20}}); histos.add("event/colltime", ";Collision time (ps);Entries", HistType::kTH1F, {{100, -2000, 2000}}); histos.add("event/tofsignal", ";#it{p} (GeV/#it{c});TOF Signal", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {10000, 0, 2e6}}); - makelogaxis(histos.get<TH2>("event/tofsignal")); + makelogaxis(histos.get<TH2>(HIST("event/tofsignal"))); histos.add("event/tofbeta", ";#it{p} (GeV/#it{c});TOF #beta", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2}}); - makelogaxis(histos.get<TH2>("event/tofbeta")); - for (int i = 0; i < Np; i++) { - // Exp signal - histos.add(hexpected[i], Form(";#it{p} (GeV/#it{c});t_{exp}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2e6}}); - makelogaxis(histos.get<TH2>(hexpected[i])); - // T-Texp - histos.add(hexpected_diff[i], Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp}(%s))", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {100, -1000, 1000}}); - makelogaxis(histos.get<TH2>(hexpected_diff[i])); - // NSigma - histos.add(hnsigma[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); - makelogaxis(histos.get<TH2>(hnsigma[i])); - } + makelogaxis(histos.get<TH2>(HIST("event/tofbeta"))); + + addParticleHistos<0>(); + addParticleHistos<1>(); + addParticleHistos<2>(); + addParticleHistos<3>(); + addParticleHistos<4>(); + addParticleHistos<5>(); + addParticleHistos<6>(); + addParticleHistos<7>(); + addParticleHistos<8>(); + } + + template <uint8_t i, typename T> + void fillParticleHistos(const T& t, const float tof, const float exp[], const float nsigma[]) + { + histos.fill(HIST(hexpected[i]), t.p(), exp[i]); + histos.fill(HIST(hexpected_diff[i]), t.p(), tof - exp[i]); + histos.fill(HIST(hnsigma[i]), t.p(), nsigma[i]); } -#undef makelogaxis void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) { - histos.fill("event/vertexz", collision.posZ()); - histos.fill("event/colltime", collision.collisionTime()); + histos.fill(HIST("event/vertexz"), collision.posZ()); + histos.fill(HIST("event/colltime"), collision.collisionTime()); for (auto t : tracks) { // @@ -205,23 +230,26 @@ struct pidTOFTaskQA { } const float tof = t.tofSignal() - collision.collisionTime(); // - histos.fill("event/tofsignal", t.p(), t.tofSignal()); - histos.fill("event/tofbeta", t.p(), t.beta()); + histos.fill(HIST("event/tofsignal"), t.p(), t.tofSignal()); + histos.fill(HIST("event/tofbeta"), t.p(), t.beta()); // const float exp[Np] = {t.tofExpSignalEl(), t.tofExpSignalMu(), t.tofExpSignalPi(), t.tofExpSignalKa(), t.tofExpSignalPr(), t.tofExpSignalDe(), t.tofExpSignalTr(), t.tofExpSignalHe(), t.tofExpSignalAl()}; - for (int i = 0; i < Np; i++) { - histos.fill(hexpected[i], t.p(), exp[i]); - histos.fill(hexpected_diff[i], t.p(), tof - exp[i]); - } // const float nsigma[Np] = {t.tofNSigmaEl(), t.tofNSigmaMu(), t.tofNSigmaPi(), t.tofNSigmaKa(), t.tofNSigmaPr(), t.tofNSigmaDe(), t.tofNSigmaTr(), t.tofNSigmaHe(), t.tofNSigmaAl()}; - for (int i = 0; i < Np; i++) { - histos.fill(hnsigma[i], t.p(), nsigma[i]); - } + // + fillParticleHistos<0>(t, tof, exp, nsigma); + fillParticleHistos<1>(t, tof, exp, nsigma); + fillParticleHistos<2>(t, tof, exp, nsigma); + fillParticleHistos<3>(t, tof, exp, nsigma); + fillParticleHistos<4>(t, tof, exp, nsigma); + fillParticleHistos<5>(t, tof, exp, nsigma); + fillParticleHistos<6>(t, tof, exp, nsigma); + fillParticleHistos<7>(t, tof, exp, nsigma); + fillParticleHistos<8>(t, tof, exp, nsigma); } } }; diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index 520b8f914f998..815d666085a3b 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -114,81 +114,108 @@ struct pidTPCTask { struct pidTPCTaskQA { static constexpr int Np = 9; static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; - static constexpr const char* hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", - "expected/Ka", "expected/Pr", "expected/De", - "expected/Tr", "expected/He", "expected/Al"}; - static constexpr const char* hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", - "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", - "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; - static constexpr const char* hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", - "nsigma/Ka", "nsigma/Pr", "nsigma/De", - "nsigma/Tr", "nsigma/He", "nsigma/Al"}; + static constexpr std::string_view hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", + "expected/Ka", "expected/Pr", "expected/De", + "expected/Tr", "expected/He", "expected/Al"}; + static constexpr std::string_view hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", + "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", + "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; + static constexpr std::string_view hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", + "nsigma/Ka", "nsigma/Pr", "nsigma/De", + "nsigma/Tr", "nsigma/He", "nsigma/Al"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; Configurable<int> nBinsP{"nBinsP", 400, "Number of bins for the momentum"}; Configurable<float> MinP{"MinP", 0, "Minimum momentum in range"}; Configurable<float> MaxP{"MaxP", 20, "Maximum momentum in range"}; - void init(o2::framework::InitContext&) + template <typename T> + void makelogaxis(T h) + { + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); + } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); + } + + template <uint8_t i> + void addParticleHistos() { + // Exp signal + histos.add(hexpected[i].data(), Form(";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); + makelogaxis(histos.get<TH2>(HIST(hexpected[i]))); -#define makelogaxis(h) \ - { \ - const Int_t nbins = h->GetNbinsX(); \ - double binp[nbins + 1]; \ - double max = h->GetXaxis()->GetBinUpEdge(nbins); \ - double min = h->GetXaxis()->GetBinLowEdge(1); \ - if (min <= 0) \ - min = 0.00001; \ - double lmin = TMath::Log10(min); \ - double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); \ - for (int i = 0; i < nbins; i++) { \ - binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); \ - } \ - binp[nbins] = max + 1; \ - h->GetXaxis()->Set(nbins, binp); \ + // Signal - Expected signal + histos.add(hexpected_diff[i].data(), Form(";#it{p} (GeV/#it{c});;d#it{E}/d#it{x} - d#it{E}/d#it{x}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, -500, 500}}); + makelogaxis(histos.get<TH2>(HIST(hexpected_diff[i]))); + + // NSigma + histos.add(hnsigma[i].data(), Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get<TH2>(HIST(hnsigma[i]))); } + void init(o2::framework::InitContext&) + { // Event properties histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", kTH1F, {{100, -20, 20}}); histos.add("event/tpcsignal", ";#it{p} (GeV/#it{c});TPC Signal", kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); - makelogaxis(histos.get<TH2>("event/tpcsignal")); - for (int i = 0; i < Np; i++) { - // Exp signal - histos.add(hexpected[i], Form(";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); - makelogaxis(histos.get<TH2>(hexpected[i])); - // Signal - Expected signal - histos.add(hexpected_diff[i], Form(";#it{p} (GeV/#it{c});;d#it{E}/d#it{x} - d#it{E}/d#it{x}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, -500, 500}}); - makelogaxis(histos.get<TH2>(hexpected_diff[i])); - // NSigma - histos.add(hnsigma[i], Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); - makelogaxis(histos.get<TH2>(hnsigma[i])); - } -#undef makelogaxis + makelogaxis(histos.get<TH2>(HIST("event/tpcsignal"))); + + addParticleHistos<0>(); + addParticleHistos<1>(); + addParticleHistos<2>(); + addParticleHistos<3>(); + addParticleHistos<4>(); + addParticleHistos<5>(); + addParticleHistos<6>(); + addParticleHistos<7>(); + addParticleHistos<8>(); + } + + template <uint8_t i, typename T> + void fillParticleHistos(const T& t, const float mom, const float exp[], const float nsigma[]) + { + histos.fill(HIST(hexpected[i]), mom, exp[i]); + histos.fill(HIST(hexpected_diff[i]), mom, t.tpcSignal() - exp[i]); + histos.fill(HIST(hnsigma[i]), t.p(), nsigma[i]); } + void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) { - histos.fill("event/vertexz", collision.posZ()); + histos.fill(HIST("event/vertexz"), collision.posZ()); for (auto t : tracks) { // const float mom = t.p(); const float mom = t.tpcInnerParam(); - histos.fill("event/tpcsignal", mom, t.tpcSignal()); + histos.fill(HIST("event/tpcsignal"), mom, t.tpcSignal()); // const float exp[Np] = {t.tpcExpSignalEl(), t.tpcExpSignalMu(), t.tpcExpSignalPi(), t.tpcExpSignalKa(), t.tpcExpSignalPr(), t.tpcExpSignalDe(), t.tpcExpSignalTr(), t.tpcExpSignalHe(), t.tpcExpSignalAl()}; - for (int i = 0; i < Np; i++) { - histos.fill(hexpected[i], mom, exp[i]); - histos.fill(hexpected_diff[i], mom, t.tpcSignal() - exp[i]); - } // const float nsigma[Np] = {t.tpcNSigmaEl(), t.tpcNSigmaMu(), t.tpcNSigmaPi(), t.tpcNSigmaKa(), t.tpcNSigmaPr(), t.tpcNSigmaDe(), t.tpcNSigmaTr(), t.tpcNSigmaHe(), t.tpcNSigmaAl()}; - for (int i = 0; i < Np; i++) { - histos.fill(hnsigma[i], t.p(), nsigma[i]); - } + // + fillParticleHistos<0>(t, mom, exp, nsigma); + fillParticleHistos<1>(t, mom, exp, nsigma); + fillParticleHistos<2>(t, mom, exp, nsigma); + fillParticleHistos<3>(t, mom, exp, nsigma); + fillParticleHistos<4>(t, mom, exp, nsigma); + fillParticleHistos<5>(t, mom, exp, nsigma); + fillParticleHistos<6>(t, mom, exp, nsigma); + fillParticleHistos<7>(t, mom, exp, nsigma); + fillParticleHistos<8>(t, mom, exp, nsigma); } } }; diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 244ddba0b788b..ea92825718c0b 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -89,44 +89,44 @@ struct TrackQATask { void process(soa::Filtered<soa::Join<aod::FullTracks, aod::TracksExtended, aod::TrackSelection>>::iterator const& track) { // fill kinematic variables - histos.fill("Kine/pt", track.pt()); - histos.fill("Kine/eta", track.eta()); - histos.fill("Kine/phi", track.phi()); + histos.fill(HIST("Kine/pt"), track.pt()); + histos.fill(HIST("Kine/eta"), track.eta()); + histos.fill(HIST("Kine/phi"), track.phi()); // fill track parameters - histos.fill("TrackPar/alpha", track.alpha()); - histos.fill("TrackPar/x", track.x()); - histos.fill("TrackPar/y", track.y()); - histos.fill("TrackPar/z", track.z()); - histos.fill("TrackPar/signed1Pt", track.signed1Pt()); - histos.fill("TrackPar/snp", track.snp()); - histos.fill("TrackPar/tgl", track.tgl()); + histos.fill(HIST("TrackPar/alpha"), track.alpha()); + histos.fill(HIST("TrackPar/x"), track.x()); + histos.fill(HIST("TrackPar/y"), track.y()); + histos.fill(HIST("TrackPar/z"), track.z()); + histos.fill(HIST("TrackPar/signed1Pt"), track.signed1Pt()); + histos.fill(HIST("TrackPar/snp"), track.snp()); + histos.fill(HIST("TrackPar/tgl"), track.tgl()); for (unsigned int i = 0; i < 64; i++) { if (track.flags() & (1 << i)) { - histos.fill("TrackPar/flags", i); + histos.fill(HIST("TrackPar/flags"), i); } } - histos.fill("TrackPar/dcaXY", track.dcaXY()); - histos.fill("TrackPar/dcaZ", track.dcaZ()); - histos.fill("TrackPar/length", track.length()); + histos.fill(HIST("TrackPar/dcaXY"), track.dcaXY()); + histos.fill(HIST("TrackPar/dcaZ"), track.dcaZ()); + histos.fill(HIST("TrackPar/length"), track.length()); // fill ITS variables - histos.fill("ITS/itsNCls", track.itsNCls()); - histos.fill("ITS/itsChi2NCl", track.itsChi2NCl()); + histos.fill(HIST("ITS/itsNCls"), track.itsNCls()); + histos.fill(HIST("ITS/itsChi2NCl"), track.itsChi2NCl()); for (unsigned int i = 0; i < 7; i++) { if (track.itsClusterMap() & (1 << i)) { - histos.fill("ITS/itsHits", i); + histos.fill(HIST("ITS/itsHits"), i); } } // fill TPC variables - histos.fill("TPC/tpcNClsFindable", track.tpcNClsFindable()); - histos.fill("TPC/tpcNClsFound", track.tpcNClsFound()); - histos.fill("TPC/tpcNClsShared", track.tpcNClsShared()); - histos.fill("TPC/tpcNClsCrossedRows", track.tpcNClsCrossedRows()); - histos.fill("TPC/tpcCrossedRowsOverFindableCls", track.tpcCrossedRowsOverFindableCls()); - histos.fill("TPC/tpcFractionSharedCls", track.tpcFractionSharedCls()); - histos.fill("TPC/tpcChi2NCl", track.tpcChi2NCl()); + histos.fill(HIST("TPC/tpcNClsFindable"), track.tpcNClsFindable()); + histos.fill(HIST("TPC/tpcNClsFound"), track.tpcNClsFound()); + histos.fill(HIST("TPC/tpcNClsShared"), track.tpcNClsShared()); + histos.fill(HIST("TPC/tpcNClsCrossedRows"), track.tpcNClsCrossedRows()); + histos.fill(HIST("TPC/tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("TPC/tpcFractionSharedCls"), track.tpcFractionSharedCls()); + histos.fill(HIST("TPC/tpcChi2NCl"), track.tpcChi2NCl()); } }; @@ -138,7 +138,7 @@ struct TrackCutQATask { { cuts.add("single_cut", ";Cut;Tracks", kTH1D, {{ncuts, 0, ncuts}}); for (int i = 0; i < ncuts; i++) { - cuts.get<TH1>("single_cut")->GetXaxis()->SetBinLabel(1 + i, TrackSelection::mCutNames[i].data()); + cuts.get<TH1>(HIST("single_cut"))->GetXaxis()->SetBinLabel(1 + i, TrackSelection::mCutNames[i].data()); } } @@ -146,7 +146,7 @@ struct TrackCutQATask { { for (int i = 0; i < ncuts; i++) { if (selectedTracks.IsSelected(track, static_cast<TrackSelection::TrackCuts>(i))) { - cuts.fill("single_cut", i); + cuts.fill(HIST("single_cut"), i); } } } diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index e32172e286021..8a68e9b93be6e 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -35,8 +35,8 @@ struct ATask { void process(aod::Tracks const& tracks) { for (auto& track : tracks) { - registry.get<TH1>("eta")->Fill(track.eta()); - registry.get<TH1>("phi")->Fill(track.phi()); + registry.get<TH1>(HIST("eta"))->Fill(track.eta()); + registry.get<TH1>(HIST("phi"))->Fill(track.phi()); } } }; @@ -53,8 +53,8 @@ struct BTask { void process(aod::Tracks const& tracks) { - registry.fill<aod::track::Eta>("eta", tracks, aod::track::eta > 0.0f); - registry.fill<aod::track::Pt, aod::track::Pt>("ptToPt", tracks, aod::track::pt < 5.0f); + registry.fill<aod::track::Eta>(HIST("eta"), tracks, aod::track::eta > 0.0f); + registry.fill<aod::track::Pt, aod::track::Pt>(HIST("ptToPt"), tracks, aod::track::pt < 5.0f); } }; @@ -97,30 +97,30 @@ struct CTask { { using namespace aod::track; // does not work with dynamic columns (e.g. Charge, NormalizedPhi) - registry.fill<Eta>("1d", tracks, eta > -0.7f); - registry.fill<Pt, Eta, RawPhi>("3d", tracks, eta > 0.f); - registry.fill<Pt, Eta, RawPhi, P, X>("5d", tracks, pt > 0.15f); - registry.fill<Pt, Eta, RawPhi, P, X, Y, Z>("7d", tracks, pt > 0.15f); - registry.fill<Pt, Eta, RawPhi>("2d-profile", tracks, eta > -0.5f); + registry.fill<Eta>(HIST("1d"), tracks, eta > -0.7f); + registry.fill<Pt, Eta, RawPhi>(HIST("3d"), tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi, P, X>(HIST("5d"), tracks, pt > 0.15f); + registry.fill<Pt, Eta, RawPhi, P, X, Y, Z>(HIST("7d"), tracks, pt > 0.15f); + registry.fill<Pt, Eta, RawPhi>(HIST("2d-profile"), tracks, eta > -0.5f); // fill 4d histogram with weight (column X) - registry.fill<Pt, Eta, RawPhi, Z, X>("4d-weight", tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi, Z, X>(HIST("4d-weight"), tracks, eta > 0.f); - registry.fill<Pt, Eta, RawPhi>("2d-weight", tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi>(HIST("2d-weight"), tracks, eta > 0.f); - registry.fill<Pt, Eta, RawPhi>("1d-profile-weight", tracks, eta > 0.f); + registry.fill<Pt, Eta, RawPhi>(HIST("1d-profile-weight"), tracks, eta > 0.f); for (auto& track : tracks) { - registry.fill("2d", track.eta(), track.pt()); - registry.fill("4d", track.pt(), track.eta(), track.phi(), track.signed1Pt()); - registry.fill("6d", track.pt(), track.eta(), track.phi(), track.snp(), track.tgl(), track.alpha()); - registry.fill("1d-profile", track.pt(), track.eta()); - registry.fill("3d-profile", track.pt(), track.eta(), track.phi(), track.snp()); + registry.fill(HIST("2d"), track.eta(), track.pt()); + registry.fill(HIST("4d"), track.pt(), track.eta(), track.phi(), track.signed1Pt()); + registry.fill(HIST("6d"), track.pt(), track.eta(), track.phi(), track.snp(), track.tgl(), track.alpha()); + registry.fill(HIST("1d-profile"), track.pt(), track.eta()); + registry.fill(HIST("3d-profile"), track.pt(), track.eta(), track.phi(), track.snp()); // fill 3d histogram with weight (2.) - registry.fill("3d-weight", track.pt(), track.eta(), track.phi(), 2.); + registry.fill(HIST("3d-weight"), track.pt(), track.eta(), track.phi(), 2.); - registry.fill("2d-profile-weight", track.pt(), track.eta(), track.phi(), 5.); + registry.fill(HIST("2d-profile-weight"), track.pt(), track.eta(), track.phi(), 5.); } } }; @@ -145,8 +145,8 @@ struct DTask { HistogramConfigSpec defaultParticleHist({HistType::kTHnF, {ptAxis, etaAxis, centAxis, cutAxis}}); spectra.add("myControlHist", "a", kTH2F, {ptAxis, etaAxis}); - spectra.get<TH2>("myControlHist")->GetYaxis()->SetTitle("my-y-axis"); - spectra.get<TH2>("myControlHist")->SetTitle("something meaningful"); + spectra.get<TH2>(HIST("myControlHist"))->GetYaxis()->SetTitle("my-y-axis"); + spectra.get<TH2>(HIST("myControlHist"))->SetTitle("something meaningful"); spectra.add("charged/pions", "Pions", defaultParticleHist); spectra.add("neutral/pions", "Pions", defaultParticleHist); @@ -154,7 +154,7 @@ struct DTask { spectra.add("sigmas", "Sigmas", defaultParticleHist); spectra.add("lambdas", "Lambd", defaultParticleHist); - spectra.get<THn>("lambdas")->SetTitle("Lambdas"); + spectra.get<THn>(HIST("lambdas"))->SetTitle("Lambdas"); etaStudy.add("positive", "A side spectra", kTH1I, {ptAxis}); etaStudy.add("negative", "C side spectra", kTH1I, {ptAxis}); @@ -177,25 +177,25 @@ struct DTask { { using namespace aod::track; - etaStudy.fill<Pt>("positive", tracks, eta > 0.f); - etaStudy.fill<Pt>("negative", tracks, eta < 0.f); + etaStudy.fill<Pt>(HIST("positive"), tracks, eta > 0.f); + etaStudy.fill<Pt>(HIST("negative"), tracks, eta < 0.f); for (auto& track : tracks) { - spectra.fill("myControlHist", track.pt(), track.eta()); - spectra.fill("charged/pions", track.pt(), track.eta(), 50., 0.); - spectra.fill("charged/pions", track.pt(), track.eta(), 50., 0.); - spectra.fill("neutral/pions", track.pt(), track.eta(), 50., 0.); - spectra.fill("one/two/three/four/kaons", track.pt(), track.eta(), 50., 0.); - spectra.fill("sigmas", track.pt(), track.eta(), 50., 0.); - spectra.fill("lambdas", track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("myControlHist"), track.pt(), track.eta()); + spectra.fill(HIST("charged/pions"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("charged/pions"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("neutral/pions"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("one/two/three/four/kaons"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("sigmas"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("lambdas"), track.pt(), track.eta(), 50., 0.); - spectra.fill("before_cuts/hist2", track.pt(), track.eta(), 50., 0.); - spectra.fill("before_cuts/hist2", track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("before_cuts/hist2"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("before_cuts/hist2"), track.pt(), track.eta(), 50., 0.); - spectra.fill("after_cuts/hist2", track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("after_cuts/hist2"), track.pt(), track.eta(), 50., 0.); - spectra.fill("cascades", track.pt(), track.eta(), 50., 0.); - spectra.fill("strange/funny/particles", track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("cascades"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST("strange/funny/particles"), track.pt(), track.eta(), 50., 0.); } } }; @@ -235,8 +235,8 @@ struct FTask { void process(aod::Tracks const& tracks) { for (auto& track : tracks) { - registry.get<TH1>("eta")->Fill(track.eta()); - registry.get<TH1>("phi")->Fill(track.phi()); + registry.get<TH1>(HIST("eta"))->Fill(track.eta()); + registry.get<TH1>(HIST("phi"))->Fill(track.phi()); } } }; diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index bbccb3faad4d5..549313ee345cd 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -21,6 +21,7 @@ #include "Framework/StringHelpers.h" #include "Framework/TableBuilder.h" #include "Framework/RuntimeError.h" +#include "Framework/StepTHn.h" #include <TH1.h> #include <TH2.h> @@ -38,6 +39,8 @@ #include <variant> #include <deque> +#define HIST(name) CONST_STR(name) + namespace o2::framework { // Available root histogram types @@ -161,7 +164,7 @@ struct HistogramConfigSpec { struct HistogramSpec { HistogramSpec(char const* const name_, char const* const title_, HistogramConfigSpec config_, bool callSumw2_ = false) : name(name_), - id(compile_time_hash(name_)), + hash(compile_time_hash(name_)), title(title_), config(config_), callSumw2(callSumw2_) @@ -170,7 +173,7 @@ struct HistogramSpec { HistogramSpec() : name(""), - id(0), + hash(0), config() { } @@ -178,7 +181,7 @@ struct HistogramSpec { HistogramSpec(HistogramSpec&& other) = default; std::string name{}; - uint32_t id{}; + uint32_t hash{}; std::string title{}; HistogramConfigSpec config{}; bool callSumw2{}; // wether or not hist needs heavy error structure produced by Sumw2() @@ -249,7 +252,6 @@ struct HistFactory { if (histSpec.callSumw2) { hist->Sumw2(); } - return hist; } @@ -373,8 +375,9 @@ struct HistFiller { } else if constexpr (validComplexFill) { double tempArray[] = {static_cast<double>(positionAndWeight)...}; double weight{1.}; - if (hist->GetNdimensions() == nArgs - 1) { - weight = tempArray[nArgs - 1]; + constexpr int nArgsMinusOne = nArgs - 1; + if (hist->GetNdimensions() == nArgsMinusOne) { + weight = tempArray[nArgsMinusOne]; } else if (hist->GetNdimensions() != nArgs) { LOGF(FATAL, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName()); } @@ -481,7 +484,24 @@ struct HistFiller { //************************************************************************************************** /** - * Histogram registry that can be used to store and fill histograms of any type. + * Histogram name object for runtime use that provides the associated hash and a first guess for the index in the registry. + */ +//************************************************************************************************** +struct HistName { + constexpr HistName(char const* const name) + : str(name), + hash(compile_time_hash(str)), + idx(hash & 0x1FF) + { + } + char const* const str{}; + const uint32_t hash{}; + const uint32_t idx{}; +}; + +//************************************************************************************************** +/** + * HistogramRegistry that can be used to store and fill histograms of any type. */ //************************************************************************************************** class HistogramRegistry @@ -503,28 +523,30 @@ class HistogramRegistry void addClone(const std::string& source, const std::string& target); // function to query if name is already in use - bool contains(char const* const name) - { - return contains(compile_time_hash(name), name); - } + bool contains(const HistName& histName); // gets the underlying histogram pointer // we cannot automatically infer type here so it has to be explicitly specified // -> get<TH1>(), get<TH2>(), get<TH3>(), get<THn>(), get<THnSparse>(), get<TProfile>(), get<TProfile2D>(), get<TProfile3D>() /// @return the histogram registered with name @a name - template <typename T> - auto& get(char const* const name) - { - if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[getHistIndex(name)])) { - return *histPtr; + template <typename T, typename H> + std::shared_ptr<T>& get(const H& histName) + { + //static_assert(is_const_str<H>::value, R"(Please use compile-time hashed strings for HistogramRegistry access: "histName" -> HIST("histName")!)"); + if constexpr (is_const_str<H>::value) { + if (auto histPtr = std::get_if<std::shared_ptr<T>>(&mRegistryValue[getHistIndex(histName)])) { + return *histPtr; + } else { + throw runtime_error_f(R"(Histogram type specified in get<>(HIST("%s")) does not match the actual type of the histogram!)", histName.str); + } } else { - throw runtime_error("Histogram type specified in get() does not match actual histogram type!"); + throw runtime_error_f(R"(Please use compile-time hashed strings for HistogramRegistry access: "histName" -> HIST("histName")!)"); } } /// @return the histogram registered with name @a name - template <typename T> - auto& operator()(char const* const name) + template <typename T, typename H> + auto& operator()(const H& name) { return get<T>(name); } @@ -550,36 +572,34 @@ class HistogramRegistry TList* operator*(); // fill hist with values - template <typename... Ts> - void fill(char const* const name, Ts&&... positionAndWeight) + template <typename... Ts, typename H> + void fill(const H& histName, Ts&&... positionAndWeight) { - std::visit([&positionAndWeight...](auto&& hist) { HistFiller::fillHistAny(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[getHistIndex(name)]); + //static_assert(is_const_str<H>::value, R"(Please use compile-time hashed strings for HistogramRegistry filling: "histName" -> HIST("histName")!)"); + if constexpr (is_const_str<H>::value) { + std::visit([&positionAndWeight...](auto&& hist) { HistFiller::fillHistAny(hist, std::forward<Ts>(positionAndWeight)...); }, mRegistryValue[getHistIndex(histName)]); + } else { + LOGF(FATAL, R"(Please use compile-time hashed strings for HistogramRegistry filling: "histName" -> HIST("histName")!)"); + } } // fill hist with content of (filtered) table columns - template <typename... Cs, typename T> - void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter) + template <typename... Cs, typename T, typename H> + void fill(const H& histName, const T& table, const o2::framework::expressions::Filter& filter) { - std::visit([&table, &filter](auto&& hist) { HistFiller::fillHistAny<Cs...>(hist, table, filter); }, mRegistryValue[getHistIndex(name)]); + //static_assert(is_const_str<H>::value, R"(Please use compile-time hashed strings for HistogramRegistry filling: "histName" -> HIST("histName")!)"); + if constexpr (is_const_str<H>::value) { + std::visit([&table, &filter](auto&& hist) { HistFiller::fillHistAny<Cs...>(hist, table, filter); }, mRegistryValue[getHistIndex(histName)]); + } else { + LOGF(FATAL, R"(Please use compile-time hashed strings for HistogramRegistry filling: "histName" -> HIST("histName")!)"); + } } // get rough estimate for size of histogram stored in registry - double getSize(char const* const name, double fillFraction = 1.) - { - double size{}; - std::visit([&fillFraction, &size](auto&& hist) { size = HistFiller::getSize(hist, fillFraction); }, mRegistryValue[getHistIndex(name)]); - return size; - } + double getSize(const HistName& histName, double fillFraction = 1.); // get rough estimate for size of all histograms stored in registry - double getSize(double fillFraction = 1.) - { - double size{}; - for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { - std::visit([&fillFraction, &size](auto&& hist) { if(hist) { size += HistFiller::getSize(hist, fillFraction);} }, mRegistryValue[j]); - } - return size; - } + double getSize(double fillFraction = 1.); // print summary of the histograms stored in registry void print(bool showAxisDetails = false); @@ -589,41 +609,39 @@ class HistogramRegistry private: // create histogram from specification and insert it into the registry - void insert(const HistogramSpec& histSpec) + void insert(const HistogramSpec& histSpec); + + // clone an existing histogram and insert it into the registry + template <typename T> + void insertClone(const HistName& histName, const std::shared_ptr<T>& originalHist) { - const uint32_t i = imask(histSpec.id); - for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + for (auto i = 0u; i < MAX_REGISTRY_SIZE; ++i) { TObject* rawPtr = nullptr; - std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(histName.idx + i)]); if (!rawPtr) { - registerName(histSpec.name); - mRegistryKey[imask(j + i)] = histSpec.id; - mRegistryValue[imask(j + i)] = HistFactory::createHistVariant(histSpec); - lookup += j; + registerName(histName.str); + mRegistryKey[imask(histName.idx + i)] = histName.hash; + mRegistryValue[imask(histName.idx + i)] = std::shared_ptr<T>(static_cast<T*>(originalHist->Clone(histName.str))); + lookup += i; return; } } LOGF(FATAL, "Internal array of HistogramRegistry %s is full.", mName); } - // clone an existing histogram and insert it into the registry + // helper function to find the histogram position in the registry template <typename T> - void insertClone(char const* const name, const std::shared_ptr<T>& originalHist) + uint32_t getHistIndex(const T& histName) { - const uint32_t id = compile_time_hash(name); - const uint32_t i = imask(id); - for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { - TObject* rawPtr = nullptr; - std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); - if (!rawPtr) { - registerName(name); - mRegistryKey[imask(j + i)] = id; - mRegistryValue[imask(j + i)] = std::shared_ptr<T>(static_cast<T*>(originalHist->Clone(name))); - lookup += j; - return; + if (O2_BUILTIN_LIKELY(histName.hash == mRegistryKey[histName.idx])) { + return histName.idx; + } + for (auto i = 1u; i < MAX_REGISTRY_SIZE; ++i) { + if (histName.hash == mRegistryKey[imask(histName.idx + i)]) { + return imask(histName.idx + i); } } - LOGF(FATAL, "Internal array of HistogramRegistry %s is full.", mName); + throw runtime_error_f(R"(Could not find histogram "%s" in HistogramRegistry "%s"!)", histName.str, mName.data()); } constexpr uint32_t imask(uint32_t i) const @@ -631,23 +649,6 @@ class HistogramRegistry return i & MASK; } - uint32_t getHistIndex(char const* const name) - { - const uint32_t id = compile_time_hash(name); - const uint32_t i = imask(id); - if (O2_BUILTIN_LIKELY(id == mRegistryKey[i])) { - return i; - } - for (auto j = 1u; j < MAX_REGISTRY_SIZE; ++j) { - if (id == mRegistryKey[imask(j + i)]) { - return imask(j + i); - } - } - throw runtime_error("No matching histogram found in HistogramRegistry!"); - } - - bool contains(const uint32_t id, char const* const name); - // helper function to create resp. find the subList defined by path TList* getSubList(TList* list, std::deque<std::string>& path); diff --git a/Framework/Core/src/HistogramRegistry.cxx b/Framework/Core/src/HistogramRegistry.cxx index b7ec3d9c0060c..7e50b299f0c65 100644 --- a/Framework/Core/src/HistogramRegistry.cxx +++ b/Framework/Core/src/HistogramRegistry.cxx @@ -34,6 +34,24 @@ const std::map<HistType, std::function<HistPtr(const HistogramSpec&)>> HistFacto #undef CALLB +// create histogram from specification and insert it into the registry +void HistogramRegistry::insert(const HistogramSpec& histSpec) +{ + const uint32_t i = imask(histSpec.hash); + for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + TObject* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); + if (!rawPtr) { + registerName(histSpec.name); + mRegistryKey[imask(j + i)] = histSpec.hash; + mRegistryValue[imask(j + i)] = HistFactory::createHistVariant(histSpec); + lookup += j; + return; + } + } + LOGF(FATAL, R"(Internal array of HistogramRegistry "%s" is full.)", mName); +} + void HistogramRegistry::add(const HistogramSpec& histSpec) { insert(histSpec); @@ -79,21 +97,39 @@ void HistogramRegistry::addClone(const std::string& source, const std::string& t } // function to query if name is already in use -bool HistogramRegistry::contains(const uint32_t id, char const* const name) +bool HistogramRegistry::contains(const HistName& histName) { // check for all occurances of the hash auto iter = mRegistryKey.begin(); - while ((iter = std::find(iter, mRegistryKey.end(), id)) != mRegistryKey.end()) { + while ((iter = std::find(iter, mRegistryKey.end(), histName.hash)) != mRegistryKey.end()) { const char* curName = nullptr; std::visit([&](auto&& hist) { if(hist) { curName = hist->GetName(); } }, mRegistryValue[iter - mRegistryKey.begin()]); // if hash is the same, make sure that name is indeed the same - if (strcmp(curName, name) == 0) { + if (strcmp(curName, histName.str) == 0) { return true; } } return false; } +// get rough estimate for size of histogram stored in registry +double HistogramRegistry::getSize(const HistName& histName, double fillFraction) +{ + double size{}; + std::visit([&fillFraction, &size](auto&& hist) { size = HistFiller::getSize(hist, fillFraction); }, mRegistryValue[getHistIndex(histName)]); + return size; +} + +// get rough estimate for size of all histograms stored in registry +double HistogramRegistry::getSize(double fillFraction) +{ + double size{}; + for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + std::visit([&fillFraction, &size](auto&& hist) { if(hist) { size += HistFiller::getSize(hist, fillFraction);} }, mRegistryValue[j]); + } + return size; +} + // print some useful meta-info about the stored histograms void HistogramRegistry::print(bool showAxisDetails) { @@ -150,7 +186,7 @@ void HistogramRegistry::print(bool showAxisDetails) LOGF(INFO, "%s\"%s\"", std::string((int)(0.5 * titleString.size() - (1 + 0.5 * mName.size())), ' '), mName); std::sort(mRegisteredNames.begin(), mRegisteredNames.end()); for (auto& curHistName : mRegisteredNames) { - std::visit(printHistInfo, mRegistryValue[getHistIndex(curHistName.data())]); + std::visit(printHistInfo, mRegistryValue[getHistIndex(HistName{curHistName.data()})]); } std::string totalSizeInfo{}; if (containsSparseHist) { @@ -271,18 +307,18 @@ void HistogramRegistry::registerName(const std::string& name) int depth = path.size(); for (auto& step : path) { if (step.empty()) { - LOGF(FATAL, "Found empty group name in path for histogram %s.", name); + LOGF(FATAL, R"(Found empty group name in path for histogram "%s".)", name); } cumulativeName += step; for (auto& curName : mRegisteredNames) { // there is already a histogram where we want to put a folder or histogram if (cumulativeName == curName) { - LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); + LOGF(FATAL, R"(Histogram name "%s" is not compatible with existing names.)", name); } // for the full new histogram name we need to check that none of the existing histograms already uses this as a group name if (depth == 1) { if (curName.rfind(cumulativeName, 0) == 0 && curName.size() > cumulativeName.size() && curName.at(cumulativeName.size()) == '/') { - LOGF(FATAL, "Histogram name %s is not compatible with existing names.", name); + LOGF(FATAL, R"(Histogram name "%s" is not compatible with existing names.)", name); } } } diff --git a/Framework/Core/test/benchmark_HistogramRegistry.cxx b/Framework/Core/test/benchmark_HistogramRegistry.cxx index 009d7eb35e462..ff870f53e913f 100644 --- a/Framework/Core/test/benchmark_HistogramRegistry.cxx +++ b/Framework/Core/test/benchmark_HistogramRegistry.cxx @@ -36,7 +36,7 @@ static void BM_HashedNameLookup(benchmark::State& state) state.ResumeTiming(); for (auto i = 0; i < nLookups; ++i) { - auto& x = registry.get<TH1>("histo4"); + auto& x = registry.get<TH1>(HIST("histo4")); benchmark::DoNotOptimize(x); } state.counters["Average lookup distance"] = ((double)registry.lookup / (double)(state.range(0))); diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 39d5618392a2d..0cfa8d50b03e4 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -41,19 +41,19 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) }; /// Get histograms by name - BOOST_REQUIRE_EQUAL(registry.get<TH1>("eta")->GetNbinsX(), 100); - BOOST_REQUIRE_EQUAL(registry.get<TH1>("phi")->GetNbinsX(), 102); - BOOST_REQUIRE_EQUAL(registry.get<TH1>("pt")->GetNbinsX(), 1002); - BOOST_REQUIRE_EQUAL(registry.get<TH2>("ptToPt")->GetNbinsX(), 100); - BOOST_REQUIRE_EQUAL(registry.get<TH2>("ptToPt")->GetNbinsY(), 100); + BOOST_REQUIRE_EQUAL(registry.get<TH1>(HIST("eta"))->GetNbinsX(), 100); + BOOST_REQUIRE_EQUAL(registry.get<TH1>(HIST("phi"))->GetNbinsX(), 102); + BOOST_REQUIRE_EQUAL(registry.get<TH1>(HIST("pt"))->GetNbinsX(), 1002); + BOOST_REQUIRE_EQUAL(registry.get<TH2>(HIST("ptToPt"))->GetNbinsX(), 100); + BOOST_REQUIRE_EQUAL(registry.get<TH2>(HIST("ptToPt"))->GetNbinsY(), 100); /// Get a pointer to the histogram - auto histo = registry.get<TH1>("pt").get(); + auto histo = registry.get<TH1>(HIST("pt")).get(); BOOST_REQUIRE_EQUAL(histo->GetNbinsX(), 1002); /// Get registry object from a function auto r = foo(); - auto histo2 = r.get<TH1>("histo").get(); + auto histo2 = r.get<TH1>(HIST("histo")).get(); BOOST_REQUIRE_EQUAL(histo2->GetNbinsX(), 100); } @@ -84,10 +84,10 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryExpressionFill) }; /// Fill histogram with expression and table - registry.fill<test::X>("x", tests, test::x > 3.0f); - BOOST_CHECK_EQUAL(registry.get<TH1>("x")->GetEntries(), 4); + registry.fill<test::X>(HIST("x"), tests, test::x > 3.0f); + BOOST_CHECK_EQUAL(registry.get<TH1>(HIST("x"))->GetEntries(), 4); /// Fill histogram with expression and table - registry.fill<test::X, test::Y>("xy", tests, test::x > 3.0f && test::y > -5.0f); - BOOST_CHECK_EQUAL(registry.get<TH2>("xy")->GetEntries(), 2); + registry.fill<test::X, test::Y>(HIST("xy"), tests, test::x > 3.0f && test::y > -5.0f); + BOOST_CHECK_EQUAL(registry.get<TH2>(HIST("xy"))->GetEntries(), 2); } From 6c56b0ac2910e0c040db1966ff81b86794b7fdc3 Mon Sep 17 00:00:00 2001 From: Nazar Burmasov <nazar.burmasov@cern.ch> Date: Mon, 14 Dec 2020 11:50:20 +0300 Subject: [PATCH 1619/1751] Adding truncation + some minor changes (#5040) --- .../AODProducerWorkflowSpec.h | 37 +++ Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 237 +++++++++++------- 2 files changed, 187 insertions(+), 87 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index a094a95ce8be9..1560217d9ae17 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -105,8 +105,43 @@ class AODProducerWorkflowDPL : public Task int mFillTracksTPC = 1; int mFillTracksITSTPC = 1; int mTFNumber = -1; + int mTruncate = 1; TStopwatch mTimer; + // truncation is enabled by default + uint32_t mCollisionPosition = 0xFFFFFFF0; // 19 bits mantissa + uint32_t mCollisionPositionCov = 0xFFFFE000; // 10 bits mantissa + uint32_t mTrackX = 0xFFFFFFF0; // 19 bits + uint32_t mTrackAlpha = 0xFFFFFFF0; // 19 bits + uint32_t mTrackSnp = 0xFFFFFF00; // 15 bits + uint32_t mTrackTgl = 0xFFFFFF00; // 15 bits + uint32_t mTrack1Pt = 0xFFFFFC00; // 13 bits + uint32_t mTrackCovDiag = 0xFFFFFF00; // 15 bits + uint32_t mTrackCovOffDiag = 0xFFFF0000; // 7 bits + uint32_t mTrackSignal = 0xFFFFFF00; // 15 bits + uint32_t mTrackPosEMCAL = 0xFFFFFF00; // 15 bits + uint32_t mTracklets = 0xFFFFFF00; // 15 bits + uint32_t mMcParticleW = 0xFFFFFFF0; // 19 bits + uint32_t mMcParticlePos = 0xFFFFFFF0; // 19 bits + uint32_t mMcParticleMom = 0xFFFFFFF0; // 19 bits + uint32_t mCaloAmp = 0xFFFFFF00; // 15 bits + uint32_t mCaloTime = 0xFFFFFF00; // 15 bits + uint32_t mMuonTr1P = 0xFFFFFC00; // 13 bits + uint32_t mMuonTrThetaX = 0xFFFFFF00; // 15 bits + uint32_t mMuonTrThetaY = 0xFFFFFF00; // 15 bits + uint32_t mMuonTrZmu = 0xFFFFFFF0; // 19 bits + uint32_t mMuonTrBend = 0xFFFFFFF0; // 19 bits + uint32_t mMuonTrNonBend = 0xFFFFFFF0; // 19 bits + uint32_t mMuonTrCov = 0xFFFF0000; // 7 bits + uint32_t mMuonCl = 0xFFFFFF00; // 15 bits + uint32_t mMuonClErr = 0xFFFF0000; // 7 bits + uint32_t mV0Time = 0xFFFFF000; // 11 bits + uint32_t mFDDTime = 0xFFFFF000; // 11 bits + uint32_t mT0Time = 0xFFFFFF00; // 15 bits + uint32_t mV0Amplitude = 0xFFFFF000; // 11 bits + uint32_t mFDDAmplitude = 0xFFFFF000; // 11 bits + uint32_t mT0Amplitude = 0xFFFFF000; // 11 bits + uint64_t maxGlBC = 0; uint64_t minGlBC = INT64_MAX; @@ -115,6 +150,8 @@ class AODProducerWorkflowDPL : public Task template <typename TracksType, typename TracksCursorType> void fillTracksTable(const TracksType& tracks, std::vector<int>& vCollRefs, const TracksCursorType& tracksCursor, int trackType); + + float TruncateFloatFraction(float x, uint32_t mask); }; /// create a processor spec diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 891300b19b611..1db42b87b195d 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -45,6 +45,17 @@ using namespace o2::framework; namespace o2::aodproducer { +float AODProducerWorkflowDPL::TruncateFloatFraction(float x, uint32_t mask) +{ + union { + float y; + uint32_t iy; + } myu; + myu.y = x; + myu.iy &= mask; + return myu.y; +} + void AODProducerWorkflowDPL::findMinMaxBc(gsl::span<const o2::ft0::RecPoints>& ft0RecPoints, gsl::span<const o2::vertexing::PVertex>& primVertices, const std::vector<o2::InteractionTimeRecord>& mcRecords) { for (auto& ft0RecPoint : ft0RecPoints) { @@ -173,18 +184,18 @@ void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vect tracksCursor(0, collisionID, trackType, - track.getX(), - track.getAlpha(), + TruncateFloatFraction(track.getX(), mTrackX), + TruncateFloatFraction(track.getAlpha(), mTrackAlpha), track.getY(), track.getZ(), - track.getSnp(), - track.getTgl(), - track.getQ2Pt(), - TMath::Sqrt(track.getSigmaY2()), - TMath::Sqrt(track.getSigmaZ2()), - TMath::Sqrt(track.getSigmaSnp2()), - TMath::Sqrt(track.getSigmaTgl2()), - TMath::Sqrt(track.getSigma1Pt2()), + TruncateFloatFraction(track.getSnp(), mTrackSnp), + TruncateFloatFraction(track.getTgl(), mTrackTgl), + TruncateFloatFraction(track.getQ2Pt(), mTrack1Pt), + TruncateFloatFraction(TMath::Sqrt(track.getSigmaY2()), mTrackCovDiag), + TruncateFloatFraction(TMath::Sqrt(track.getSigmaZ2()), mTrackCovDiag), + TruncateFloatFraction(TMath::Sqrt(track.getSigmaSnp2()), mTrackCovDiag), + TruncateFloatFraction(TMath::Sqrt(track.getSigmaTgl2()), mTrackCovDiag), + TruncateFloatFraction(TMath::Sqrt(track.getSigma1Pt2()), mTrackCovDiag), (Char_t)(128. * track.getSigmaZY() / track.getSigmaZ2() / track.getSigmaY2()), (Char_t)(128. * track.getSigmaSnpY() / track.getSigmaSnp2() / track.getSigmaY2()), (Char_t)(128. * track.getSigmaSnpZ() / track.getSigmaSnp2() / track.getSigmaZ2()), @@ -195,7 +206,7 @@ void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vect (Char_t)(128. * track.getSigma1PtZ() / track.getSigma1Pt2() / track.getSigmaZ2()), (Char_t)(128. * track.getSigma1PtSnp() / track.getSigma1Pt2() / track.getSigmaSnp2()), (Char_t)(128. * track.getSigma1PtTgl() / track.getSigma1Pt2() / track.getSigmaTgl2()), - tpcInnerParam, + TruncateFloatFraction(tpcInnerParam, mTrack1Pt), flags, itsClusterMap, tpcNClsFindable, @@ -203,17 +214,17 @@ void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vect tpcNClsFindableMinusCrossedRows, tpcNClsShared, trdPattern, - itsChi2NCl, - tpcChi2NCl, - trdChi2, - tofChi2, - tpcSignal, - trdSignal, - tofSignal, - length, - tofExpMom, - trackEtaEMCAL, - trackPhiEMCAL); + TruncateFloatFraction(itsChi2NCl, mTrackCovOffDiag), + TruncateFloatFraction(tpcChi2NCl, mTrackCovOffDiag), + TruncateFloatFraction(trdChi2, mTrackCovOffDiag), + TruncateFloatFraction(tofChi2, mTrackCovOffDiag), + TruncateFloatFraction(tpcSignal, mTrackSignal), + TruncateFloatFraction(trdSignal, mTrackSignal), + TruncateFloatFraction(tofSignal, mTrackSignal), + TruncateFloatFraction(length, mTrackSignal), + TruncateFloatFraction(tofExpMom, mTrack1Pt), + TruncateFloatFraction(trackEtaEMCAL, mTrackPosEMCAL), + TruncateFloatFraction(trackPhiEMCAL, mTrackPosEMCAL)); } } @@ -228,9 +239,47 @@ void AODProducerWorkflowDPL::init(InitContext& ic) if (mTFNumber == -1) { LOG(INFO) << "TFNumber will be obtained from CCDB"; } - LOG(INFO) << "track filling flags set to: " + LOG(INFO) << "Track filling flags are set to: " << "\n ITS = " << mFillTracksITS << "\n TPC = " << mFillTracksTPC << "\n ITSTPC = " << mFillTracksITSTPC; + mTruncate = ic.options().get<int>("enable-truncation"); + if (mTruncate != 1) { + LOG(INFO) << "Truncation is not used!"; + + mCollisionPosition = 0xFFFFFFFF; + mCollisionPositionCov = 0xFFFFFFFF; + mTrackX = 0xFFFFFFFF; + mTrackAlpha = 0xFFFFFFFF; + mTrackSnp = 0xFFFFFFFF; + mTrackTgl = 0xFFFFFFFF; + mTrack1Pt = 0xFFFFFFFF; + mTrackCovDiag = 0xFFFFFFFF; + mTrackCovOffDiag = 0xFFFFFFFF; + mTrackSignal = 0xFFFFFFFF; + mTrackPosEMCAL = 0xFFFFFFFF; + mTracklets = 0xFFFFFFFF; + mMcParticleW = 0xFFFFFFFF; + mMcParticlePos = 0xFFFFFFFF; + mMcParticleMom = 0xFFFFFFFF; + mCaloAmp = 0xFFFFFFFF; + mCaloTime = 0xFFFFFFFF; + mMuonTr1P = 0xFFFFFFFF; + mMuonTrThetaX = 0xFFFFFFFF; + mMuonTrThetaY = 0xFFFFFFFF; + mMuonTrZmu = 0xFFFFFFFF; + mMuonTrBend = 0xFFFFFFFF; + mMuonTrNonBend = 0xFFFFFFFF; + mMuonTrCov = 0xFFFFFFFF; + mMuonCl = 0xFFFFFFFF; + mMuonClErr = 0xFFFFFFFF; + mV0Time = 0xFFFFFFFF; + mFDDTime = 0xFFFFFFFF; + mT0Time = 0xFFFFFFFF; + mV0Amplitude = 0xFFFFFFFF; + mFDDAmplitude = 0xFFFFFFFF; + mT0Amplitude = 0xFFFFFFFF; + } + mTimer.Reset(); } @@ -310,51 +359,60 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) // TODO: // add real FV0A, FV0C, FDD, ZDC tables instead of dummies - float dummyfv0AmplA[48] = {0.}; + uint64_t dummyBC = 0; + float dummyTime = 0.f; + float dummyFV0AmplA[48] = {0.}; + uint8_t dummyTriggerMask = 0; fv0aCursor(0, - (uint64_t)0, - dummyfv0AmplA, - 0.f, - (uint8_t)0); + dummyBC, + dummyFV0AmplA, + dummyTime, + dummyTriggerMask); - float dummyfv0AmplC[32] = {0.}; + float dummyFV0AmplC[32] = {0.}; fv0cCursor(0, - (uint64_t)0, - dummyfv0AmplC, - 0.f); + dummyBC, + dummyFV0AmplC, + dummyTime); - float dummyfddAmplA[4] = {0.}; - float dummyfddAmplC[4] = {0.}; + float dummyFDDAmplA[4] = {0.}; + float dummyFDDAmplC[4] = {0.}; fddCursor(0, - (uint64_t)0, - dummyfddAmplA, - dummyfddAmplC, - 0.f, - 0.f, - (uint8_t)0); - + dummyBC, + dummyFDDAmplA, + dummyFDDAmplC, + dummyTime, + dummyTime, + dummyTriggerMask); + + float dummyEnergyZEM1 = 0; + float dummyEnergyZEM2 = 0; + float dummyEnergyCommonZNA = 0; + float dummyEnergyCommonZNC = 0; + float dummyEnergyCommonZPA = 0; + float dummyEnergyCommonZPC = 0; float dummyEnergySectorZNA[4] = {0.}; float dummyEnergySectorZNC[4] = {0.}; float dummyEnergySectorZPA[4] = {0.}; float dummyEnergySectorZPC[4] = {0.}; zdcCursor(0, - (uint64_t)0, - 0.f, - 0.f, - 0.f, - 0.f, - 0.f, - 0.f, + dummyBC, + dummyEnergyZEM1, + dummyEnergyZEM2, + dummyEnergyCommonZNA, + dummyEnergyCommonZNC, + dummyEnergyCommonZPA, + dummyEnergyCommonZPC, dummyEnergySectorZNA, dummyEnergySectorZNC, dummyEnergySectorZPA, dummyEnergySectorZPC, - 0.f, - 0.f, - 0.f, - 0.f, - 0.f, - 0.f); + dummyTime, + dummyTime, + dummyTime, + dummyTime, + dummyTime, + dummyTime); // TODO: // figure out collision weight @@ -376,11 +434,11 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) mcCollisionsCursor(0, mGlobBC2BCID.at(globalBC), generatorID, - header.GetX(), - header.GetY(), - header.GetZ(), - time, - mcColWeight, + TruncateFloatFraction(header.GetX(), mCollisionPosition), + TruncateFloatFraction(header.GetY(), mCollisionPosition), + TruncateFloatFraction(header.GetZ(), mCollisionPosition), + TruncateFloatFraction(time, mCollisionPosition), + TruncateFloatFraction(mcColWeight, mCollisionPosition), header.GetB()); } index++; @@ -418,15 +476,15 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) mother1, daughter0, daughter1, - weight, - (float)mcParticle.Px(), - (float)mcParticle.Py(), - (float)mcParticle.Pz(), - (float)mcParticle.GetEnergy(), - (float)mcParticle.Vx(), - (float)mcParticle.Vy(), - (float)mcParticle.Vz(), - (float)mcParticle.T()); + TruncateFloatFraction(weight, mMcParticleW), + TruncateFloatFraction((float)mcParticle.Px(), mMcParticleMom), + TruncateFloatFraction((float)mcParticle.Py(), mMcParticleMom), + TruncateFloatFraction((float)mcParticle.Pz(), mMcParticleMom), + TruncateFloatFraction((float)mcParticle.GetEnergy(), mMcParticleMom), + TruncateFloatFraction((float)mcParticle.Vx(), mMcParticlePos), + TruncateFloatFraction((float)mcParticle.Vy(), mMcParticlePos), + TruncateFloatFraction((float)mcParticle.Vz(), mMcParticlePos), + TruncateFloatFraction((float)mcParticle.T(), mMcParticlePos)); mIDsToIndex[std::make_tuple(sourceID, mcEventID, mcTrackID)] = mcParticlesIndex; mcTrackID++; mcParticlesIndex++; @@ -446,15 +504,19 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) } float aAmplitudesA[96]; float aAmplitudesC[112]; - std::copy(vAmplitudes.begin(), vAmplitudes.begin() + 95, aAmplitudesA); - std::copy(vAmplitudes.begin() + 96, vAmplitudes.end(), aAmplitudesC); + for (int i = 0; i < 96; i++) { + aAmplitudesA[i] = TruncateFloatFraction(vAmplitudes[i], mT0Amplitude); + } + for (int i = 0; i < 112; i++) { + aAmplitudesC[i] = TruncateFloatFraction(vAmplitudes[i + 96], mT0Amplitude); + } uint64_t globalBC = ft0RecPoint.getInteractionRecord().orbit * o2::constants::lhc::LHCMaxBunches + ft0RecPoint.getInteractionRecord().bc; ft0Cursor(0, mGlobBC2BCID.at(globalBC), aAmplitudesA, aAmplitudesC, - ft0RecPoint.getCollisionTimeA() / 1E3, // ps to ns - ft0RecPoint.getCollisionTimeC() / 1E3, // ps to ns + TruncateFloatFraction(ft0RecPoint.getCollisionTimeA() / 1E3, mT0Time), // ps to ns + TruncateFloatFraction(ft0RecPoint.getCollisionTimeC() / 1E3, mT0Time), // ps to ns ft0RecPoint.getTrigger().triggersignals); } @@ -472,8 +534,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto& cov = vertex.getCov(); auto& timeStamp = vertex.getTimeStamp(); Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // mus to ns - // TODO: - // use filling scheme to calculate most prob. BC + // FIXME: + // should use IRMin and IRMax for globalBC calculation uint64_t globalBC = std::round(tsTimeStamp / o2::constants::lhc::LHCBunchSpacingNS); LOG(DEBUG) << globalBC << " " << tsTimeStamp; @@ -490,19 +552,19 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) int collisionTimeMask = 0; collisionsCursor(0, BCid, - vertex.getX(), - vertex.getY(), - vertex.getZ(), - cov[0], - cov[1], - cov[2], - cov[3], - cov[4], - cov[5], - vertex.getChi2(), + TruncateFloatFraction(vertex.getX(), mCollisionPosition), + TruncateFloatFraction(vertex.getY(), mCollisionPosition), + TruncateFloatFraction(vertex.getZ(), mCollisionPosition), + TruncateFloatFraction(cov[0], mCollisionPositionCov), + TruncateFloatFraction(cov[1], mCollisionPositionCov), + TruncateFloatFraction(cov[2], mCollisionPositionCov), + TruncateFloatFraction(cov[3], mCollisionPositionCov), + TruncateFloatFraction(cov[4], mCollisionPositionCov), + TruncateFloatFraction(cov[5], mCollisionPositionCov), + TruncateFloatFraction(vertex.getChi2(), mCollisionPositionCov), vertex.getNContributors(), - tsTimeStamp, - timeStamp.getTimeStampError() * 1E3, + TruncateFloatFraction(tsTimeStamp, mCollisionPosition), + TruncateFloatFraction(timeStamp.getTimeStampError() * 1E3, mCollisionPositionCov), collisionTimeMask); auto trackRef = primVer2TRefs[collisionID]; @@ -676,7 +738,8 @@ DataProcessorSpec getAODProducerWorkflowSpec() ConfigParamSpec{"fill-tracks-its", VariantType::Int, 1, {"Fill ITS tracks into tracks table"}}, ConfigParamSpec{"fill-tracks-tpc", VariantType::Int, 1, {"Fill TPC tracks into tracks table"}}, ConfigParamSpec{"fill-tracks-its-tpc", VariantType::Int, 1, {"Fill ITS-TPC tracks into tracks table"}}, - ConfigParamSpec{"aod-timeframe-id", VariantType::Int, -1, {"Set timeframe number"}}}}; + ConfigParamSpec{"aod-timeframe-id", VariantType::Int, -1, {"Set timeframe number"}}, + ConfigParamSpec{"enable-truncation", VariantType::Int, 1, {"Truncation parameter: 1 -- on (default), != 1 -- off"}}}}; } } // namespace o2::aodproducer From 6f421d5b09ed56aad20e0658eb05dbc334fad2d0 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:09:25 +0100 Subject: [PATCH 1620/1751] Drop untested / unused hough transform code (#5037) --- Utilities/CMakeLists.txt | 5 - Utilities/hough/CMakeLists.txt | 33 ------ Utilities/hough/README.md | 46 --------- Utilities/hough/runHough.cxx | 180 --------------------------------- 4 files changed, 264 deletions(-) delete mode 100644 Utilities/hough/CMakeLists.txt delete mode 100644 Utilities/hough/README.md delete mode 100644 Utilities/hough/runHough.cxx diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 440514c381c6a..1028a895cfe52 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -8,11 +8,6 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -if(ALIROOT) - # FIXME: not tested - add_subdirectory(hough) -endif(ALIROOT) - add_subdirectory(aliceHLTwrapper) add_subdirectory(O2MessageMonitor) add_subdirectory(DataFlow) diff --git a/Utilities/hough/CMakeLists.txt b/Utilities/hough/CMakeLists.txt deleted file mode 100644 index 12c3adcc99d92..0000000000000 --- a/Utilities/hough/CMakeLists.txt +++ /dev/null @@ -1,33 +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. - -set(MODULE_NAME "hough") - -o2_setup(NAME ${MODULE_NAME}) - -set(Exe_Names runHough) - -set(Exe_Source runHough.cxx) - -set(BUCKET_NAME hough_bucket) - -list(LENGTH Exe_Names _length) -math(EXPR _length ${_length}-1) - -foreach(_file RANGE 0 ${_length}) - list(GET Exe_Names ${_file} _name) - list(GET Exe_Source ${_file} _src) - o2_generate_executable(EXE_NAME - ${_name} - SOURCES - ${_src} - BUCKET_NAME - ${BUCKET_NAME}) -endforeach(_file RANGE 0 ${_length}) diff --git a/Utilities/hough/README.md b/Utilities/hough/README.md deleted file mode 100644 index 3d8f44e8ccb43..0000000000000 --- a/Utilities/hough/README.md +++ /dev/null @@ -1,46 +0,0 @@ -<!-- doxy -\page refUtilitieshough Hough Transform -/doxy --> - -# Hough Transform - -This is the groundwork for the Hough Transform algorithm implementation. The runHough executable takes as an argument an event number (i.e. runHough 032) and for the given event it loads all clusters from the corresponding data files. - -### Step by Step installation and execution - -1. The runHough executable depends on the AliRoot HLT libraries. For this, an optional dependency to AliRoot has been added to the AliceO2 framework. To build the executable, the path to the AliRoot installation must be given at configuration time. For example: - - cmake -DCMAKE_INSTALL_PREFIX:PATH=.. -DCMAKE_CXX_FLAGS="-std=c++11" .. -DALIROOT="/opt/alice/external/AliRoot" - -It is important that AliRoot, FairRoot and AliceO2 have been built against the same version of ROOT. To ensure that the prerequisite packages were compiled and installed correctly, the alfaconfig.sh script that is included as part of the FairSoft installation can be used. - -2. Raw data files should be retrieved from AliEn for a given run. The implementation can be tested using the raw files corresponding to run 167808: - - alien-token-init <username> - aliensh - - cd /alice/data/2011/LHC11h/000167808/raw/ - cp 11000167808000.10.root file://tmp - exit - - mv /tmp/11000167808000.10.root raw.root - -Then, the necessary scripts to perform the clusterization for the data should be coppied to the current directory: - - cp ${AliRoot}/HLT/exa/recraw-local.C . - cp ${AliRoot}/HLT/exa/EnableHLTInGRP.C . - cp ${AliceO2}devices/aliceHLTwrapper/macros/hltConfigurations.C . - -Finally, the following commands should executed: - - aliroot -b -q -l hltConfigurations.C recraw-local.C'("raw.root", "raw://", 0, 0, "HLT TPC", "loglevel=0x79 chains=cluster-collection", "local://./OCDB")' - - aliroot -b -q -l EnableHLTInGRP.C'(167808, "local://./OCDB", "local://./OCDB")' - rm galice.root QA.root - aliroot -b -q -l hltConfigurations.C recraw-local.C'("raw.root", "local://OCDB", -1, -1, "HLT", "loglevel=0x79 chains=cluster-collection")' 2>&1 | tee cluster-collection.log - -The result should be a directory, called "emulated-tpc-clusters" that will be the input of runHough. By executing - - runHough 032 - -the executable will load all the clusters from the emulated-tpc-clusters/event032 subdirectory. After the execution, a graphics file "clusters.pdf" will be created in the current directory depicting the coordinates of the loaded clusters. diff --git a/Utilities/hough/runHough.cxx b/Utilities/hough/runHough.cxx deleted file mode 100644 index 5c767e98bcf60..0000000000000 --- a/Utilities/hough/runHough.cxx +++ /dev/null @@ -1,180 +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. - -/// \file runHough.cxx -/// \brief Implementation of a cluster loader -/// \author Charis Kouzinopoulos - -#include "AliHLTTPCTrackGeometry.h" -#include "AliHLTTPCClusterDataFormat.h" -#include "AliHLTTPCSpacePointContainer.h" -#include "AliHLTComponent.h" -#include "AliHLTTPCDefinitions.h" - -#include "TCanvas.h" -#include "TGraph2D.h" - -#include "boost/filesystem.hpp" - -#include <sstream> - -std::unique_ptr<AliHLTTPCSpacePointContainer> spacepoints; -vector<float> clusterCoordinates; - -void drawData(int totalNumberOfClusters, std::string dataFilename) -{ - TCanvas* c1 = new TCanvas("c1", dataFilename.c_str(), 0, 0, 800, 600); - TGraph2D* dt = new TGraph2D(10000); - - for (Int_t i = 0; i < totalNumberOfClusters; i++) { - dt->SetPoint(i, clusterCoordinates[i * 4 + 1], clusterCoordinates[i * 4 + 2], clusterCoordinates[i * 4 + 3]); - } - - // Draw with colored dots - dt->SetMarkerStyle(1); - dt->Draw("pcol"); - - c1->Print("clusters.pdf"); -} - -void printData(int totalNumberOfClusters) -{ - cout << "Cluster ID" << setw(13) << "X coordinate" << setw(13) << "Y coordinate" << setw(13) << "Z coordinate" - << endl; - - for (int i = 0; i < totalNumberOfClusters; i++) { - cout << (AliHLTUInt32_t)clusterCoordinates[i * 4] << setw(13) << clusterCoordinates[i * 4 + 1] << setw(13) - << clusterCoordinates[i * 4 + 2] << setw(13) << clusterCoordinates[i * 4 + 3] << endl; - } -} - -void addDataToCoordinatesVector(AliHLTUInt32_t clusterID, float XCoordinate, float YCoordinate, float ZCoordinate) -{ - clusterCoordinates.push_back((float)clusterID); - clusterCoordinates.push_back(XCoordinate); - clusterCoordinates.push_back(YCoordinate); - clusterCoordinates.push_back(ZCoordinate); -} - -int processData(std::string dataPath, std::string dataType, std::string dataOrigin) -{ - // Open data file for reading - std::ifstream inputData(dataPath.c_str(), std::ifstream::binary); - if (!inputData) { - std::cerr << "Error, cluster data file " << dataPath << " could not be accessed" << endl; - std::exit(1); - } - - // Get length of file - inputData.seekg(0, inputData.end); - int dataLength = inputData.tellg(); - inputData.seekg(0, inputData.beg); - - // Allocate memory and read file to memory - char* inputBuffer = new char[dataLength]; - inputData.read(inputBuffer, dataLength); - inputData.close(); - - // Retrieve the TPC slice and partition from the filename - std::string currentSliceString(dataPath, dataPath.length() - 6, 2); - std::string currentPartitionString(dataPath, dataPath.length() - 2, 2); - - AliHLTUInt8_t currentSlice = std::stoul(currentSliceString, nullptr, 16); - AliHLTUInt8_t currentPartition = std::stoul(currentPartitionString, nullptr, 16); - - // Initialize a cluster point collection - spacepoints = std::unique_ptr<AliHLTTPCSpacePointContainer>(new AliHLTTPCSpacePointContainer); - if (!spacepoints.get()) { - std::cerr << "Error, could not create a space point collection" << endl; - std::exit(1); - } - - // Create an AliHLTComponentBlockData object, fill it with default values and then set its pointer to the data buffer - AliHLTComponentBlockData bd; - AliHLTComponent::FillBlockData(bd); - bd.fPtr = inputBuffer; - bd.fSize = dataLength; - // bd.fDataType=kAliHLTVoidDataType; - AliHLTComponent::SetDataType(bd.fDataType, dataType.c_str(), dataOrigin.c_str()); - bd.fSpecification = kAliHLTVoidDataSpec; - - // Set slice and partition - AliHLTTPCDefinitions::EncodeDataSpecification(currentSlice, currentSlice, currentPartition, currentPartition); - - // Add the AliHLTComponentBlockData object to AliHLTTPCSpacePointContainer - int numberOfClusters = spacepoints->AddInputBlock(&bd); - - // cout << *spacepoints << endl; - - // Retrieve the cluster information from AliHLTTPCSpacePointContainer - std::vector<AliHLTUInt32_t> clusterIDs; - spacepoints->GetClusterIDs(clusterIDs); - - // Append the cluster IDs and their X, Y and Z coordinates to the clusterCoordinates vector - for (vector<AliHLTUInt32_t>::const_iterator element = clusterIDs.begin(); element != clusterIDs.end(); element++) { - AliHLTUInt32_t clusterID = *element; - - addDataToCoordinatesVector(clusterID, spacepoints->GetX(clusterID), spacepoints->GetY(clusterID), - spacepoints->GetZ(clusterID)); - } - - // De-allocate memory space - if (inputBuffer) { - delete[] inputBuffer; - } - inputBuffer = NULL; - - return numberOfClusters; -} - -int main(int argc, char** argv) -{ - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " <event number>" << endl; - std::exit(1); - } - - // Create data path - std::string dataFilename = "emulated-tpc-clusters/event"; - dataFilename += argv[1]; - - boost::filesystem::path dataPath(dataFilename); - boost::filesystem::directory_iterator endIterator; - - typedef std::multimap<std::time_t, boost::filesystem::path> result_set_t; - result_set_t result_set; - - std::string dataType = "CLUSTERS", dataOrigin = "TPC "; - - int totalNumberOfClusters = 0, totalNumberOfDataFiles = 0; - - // Traverse the filesystem and execute processData for each cluster file found - if (boost::filesystem::exists(dataPath) && boost::filesystem::is_directory(dataPath)) { - for (boost::filesystem::directory_iterator directoryIterator(dataPath); directoryIterator != endIterator; - ++directoryIterator) { - if (boost::filesystem::is_regular_file(directoryIterator->status())) { - totalNumberOfClusters += processData(directoryIterator->path().string(), dataType, dataOrigin); - totalNumberOfDataFiles++; - } - } - } else { - std::cerr << "Path " << dataPath.string() << "/ could not be found or does not contain any valid data files" - << endl; - exit(1); - } - - cout << "Added " << totalNumberOfClusters << " clusters from " << totalNumberOfDataFiles << " data files" << endl; - - // printData(totalNumberOfClusters); - - drawData(totalNumberOfClusters, dataFilename); - - return 0; -} From 97d1b2c4960f88f7286778108c41c2b45ebe105a Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 14 Dec 2020 11:16:34 +0100 Subject: [PATCH 1621/1751] DPL Analysis: fix for parsing non-integer arrays in configurables (#5035) --- Framework/Core/src/BoostOptionsRetriever.cxx | 2 +- Framework/Core/src/DataProcessingDevice.cxx | 9 +-- Framework/Core/src/PropertyTreeHelpers.cxx | 11 ++-- Framework/Core/src/RootConfigParamHelpers.cxx | 65 ++++++++++--------- 4 files changed, 45 insertions(+), 42 deletions(-) diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index 8128635a5ccc6..b966c48098511 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -68,7 +68,7 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> const& specs, case VariantType::ArrayFloat: case VariantType::ArrayDouble: case VariantType::ArrayBool: - options = options(name, bpo::value<std::string>()->multitoken()->default_value(spec.defaultValue.asString(), help)); + options = options(name, bpo::value<std::string>()->default_value(spec.defaultValue.asString(), help)); break; case VariantType::Unknown: case VariantType::Empty: diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 193e8c51c6f29..9d4c12b0032b1 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -250,13 +250,14 @@ void DataProcessingDevice::Init() /// Dump the configuration so that we can get it from the driver. for (auto& entry : configStore->store()) { std::stringstream ss; + std::string str; if (entry.second.size() != 0) { - boost::property_tree::json_parser::write_json(ss, configStore->store().get_child(entry.first), false); + boost::property_tree::json_parser::write_json(ss, entry.second, false); + str = ss.str(); + str.pop_back(); //remove EoL } else { - ss << configStore->store().get<std::string>(entry.first) << "\n"; + str = entry.second.get_value<std::string>(); } - auto str = ss.str(); - str.pop_back(); //remove EoL LOG(INFO) << "[CONFIG] " << entry.first << "=" << str << " 1 " << configStore->provenance(entry.first.c_str()); } diff --git a/Framework/Core/src/PropertyTreeHelpers.cxx b/Framework/Core/src/PropertyTreeHelpers.cxx index 4b64081b128a2..71b8e0fc10303 100644 --- a/Framework/Core/src/PropertyTreeHelpers.cxx +++ b/Framework/Core/src/PropertyTreeHelpers.cxx @@ -14,11 +14,11 @@ #include <boost/property_tree/ptree.hpp> #include <boost/program_options/variables_map.hpp> -#include <boost/tokenizer.hpp> #include <boost/lexical_cast.hpp> #include <vector> #include <string> +#include <regex> namespace o2::framework { @@ -98,10 +98,11 @@ std::vector<T> toVector(std::string const& input) std::vector<T> result; //check if the array string has correct array type symbol assert(input[0] == variant_array_symbol<T>::symbol); - //strip type symbol and parentheses - boost::tokenizer<> tokenizer(input.substr(2, input.size() - 3)); - for (auto it = tokenizer.begin(); it != tokenizer.end(); ++it) { - result.push_back(boost::lexical_cast<T>(*it)); + std::regex nmatch(R"((?:(?!=,)|(?!=\[))[+-]?\d+\.?\d*(?:[eE][+-]?\d+)?(?=,|\]))", std::regex_constants::ECMAScript); + auto end = std::sregex_iterator(); + auto values = std::sregex_iterator(input.begin(), input.end(), nmatch); + for (auto v = values; v != end; ++v) { + result.push_back(boost::lexical_cast<T>(v->str())); } return result; } diff --git a/Framework/Core/src/RootConfigParamHelpers.cxx b/Framework/Core/src/RootConfigParamHelpers.cxx index 0a15b3dfd6310..81b6851fd283f 100644 --- a/Framework/Core/src/RootConfigParamHelpers.cxx +++ b/Framework/Core/src/RootConfigParamHelpers.cxx @@ -101,6 +101,24 @@ void ptreeToMember(boost::property_tree::ptree const& value, TDataMember* dm, void* ptr) { + + if (dm->IsSTLContainer()) { + auto type = dm->GetTypeName(); + switch (compile_time_hash(type)) { + case compile_time_hash("vector<int>"): + *static_cast<std::vector<int>*>(ptr) = extractVector<int>(value); + return; + case compile_time_hash("vector<float>"): + *static_cast<std::vector<float>*>(ptr) = extractVector<float>(value); + return; + case compile_time_hash("vector<double>"): + *static_cast<std::vector<double>*>(ptr) = extractVector<double>(value); + return; + case compile_time_hash("vector<bool>"): + default: + throw std::runtime_error("Not and int/float/double/bool vector"); + } + } auto dt = dm->GetDataType(); if (dt != nullptr) { switch (dt->GetType()) { @@ -165,33 +183,32 @@ void ptreeToMember(boost::property_tree::ptree const& value, } } } + // if we get here none of the above worked + if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { + *(std::string*)ptr = value.get_value<std::string>(); + } + throw std::runtime_error("Unable to override value"); +} + +// Convert a DataMember to a ConfigParamSpec +ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void* ptr) +{ if (dm->IsSTLContainer()) { auto type = dm->GetTypeName(); switch (compile_time_hash(type)) { case compile_time_hash("vector<int>"): - *static_cast<std::vector<int>*>(ptr) = extractVector<int>(value); - return; + return ConfigParamSpec{tname, VariantType::ArrayInt, *static_cast<std::vector<int>*>(ptr), {"No help"}}; case compile_time_hash("vector<float>"): - *static_cast<std::vector<float>*>(ptr) = extractVector<float>(value); - return; + return ConfigParamSpec{tname, VariantType::ArrayFloat, *static_cast<std::vector<float>*>(ptr), {"No help"}}; case compile_time_hash("vector<double>"): - *static_cast<std::vector<double>*>(ptr) = extractVector<double>(value); - return; + return ConfigParamSpec{tname, VariantType::ArrayDouble, *static_cast<std::vector<double>*>(ptr), {"No help"}}; case compile_time_hash("vector<bool>"): + throw std::runtime_error("bool vector not supported yet"); + // return ConfigParamSpec{tname, VariantType::ArrayBool, *static_cast<std::vector<bool>*>(ptr), {"No help"}}; default: throw std::runtime_error("Not and int/float/double/bool vector"); } } - // if we get here none of the above worked - if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { - *(std::string*)ptr = value.get_value<std::string>(); - } - throw std::runtime_error("Unable to override value"); -} - -// Convert a DataMember to a ConfigParamSpec -ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void* ptr) -{ auto dt = dm->GetDataType(); if (dt != nullptr) { switch (dt->GetType()) { @@ -242,22 +259,6 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void } } } - if (dm->IsSTLContainer()) { - auto type = dm->GetTypeName(); - switch (compile_time_hash(type)) { - case compile_time_hash("vector<int>"): - return ConfigParamSpec{tname, VariantType::ArrayInt, *static_cast<std::vector<int>*>(ptr), {"No help"}}; - case compile_time_hash("vector<float>"): - return ConfigParamSpec{tname, VariantType::ArrayFloat, *static_cast<std::vector<float>*>(ptr), {"No help"}}; - case compile_time_hash("vector<double>"): - return ConfigParamSpec{tname, VariantType::ArrayDouble, *static_cast<std::vector<double>*>(ptr), {"No help"}}; - case compile_time_hash("vector<bool>"): - throw std::runtime_error("bool vector not supported yet"); - // return ConfigParamSpec{tname, VariantType::ArrayBool, *static_cast<std::vector<bool>*>(ptr), {"No help"}}; - default: - throw std::runtime_error("Not and int/float/double/bool vector"); - } - } // if we get here none of the above worked if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { return ConfigParamSpec{tname, VariantType::String, *(std::string*)ptr, {"No help"}}; From 3f0ac03513451b9b6f752bf2f660e7aa4097349d Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Mon, 14 Dec 2020 07:52:58 -0300 Subject: [PATCH 1622/1751] Fix finder -> problems with partitioning to be checked (#5060) --- Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index 00ab268fd1828..9250dd6a7d1e2 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -82,33 +82,39 @@ struct lambdakzeroprefilter { Configurable<float> dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; Configurable<float> dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; Configurable<int> mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + Configurable<int> tpcrefit{"tpcrefit", 1, "demand TPC refit"}; Produces<aod::V0GoodPosTracks> v0GoodPosTracks; Produces<aod::V0GoodNegTracks> v0GoodNegTracks; - Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodPosTracks = aod::track::signed1Pt > 0.0f && aod::track::dcaXY > dcapostopv; - Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodNegTracks = aod::track::signed1Pt < 0.0f && aod::track::dcaXY < -dcanegtopv; + //still exhibiting issues? To be checked + //Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodPosTracks = aod::track::signed1Pt > 0.0f && aod::track::dcaXY > dcapostopv; + //Partition<soa::Join<aod::FullTracks, aod::TracksExtended>> goodNegTracks = aod::track::signed1Pt < 0.0f && aod::track::dcaXY < -dcanegtopv; void process(aod::Collision const& collision, soa::Join<aod::FullTracks, aod::TracksExtended> const& tracks) { - for (auto& t0 : goodPosTracks) { - if (!(t0.trackType() & o2::aod::track::TPCrefit)) { - continue; //TPC refit + for (auto& t0 : tracks) { + if (tpcrefit) { + if (!(t0.trackType() & o2::aod::track::TPCrefit)) { + continue; //TPC refit + } } if (t0.tpcNClsCrossedRows() < mincrossedrows) { continue; } - v0GoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); - } - for (auto& t0 : goodNegTracks) { - if (!(t0.trackType() & o2::aod::track::TPCrefit)) { - continue; //TPC refit + if (t0.signed1Pt() > 0.0f) { + if (fabs(t0.dcaXY()) < dcapostopv) { + continue; + } + v0GoodPosTracks(t0.globalIndex(), t0.collisionId(), t0.dcaXY()); } - if (t0.tpcNClsCrossedRows() < mincrossedrows) { - continue; + if (t0.signed1Pt() < 0.0f) { + if (fabs(t0.dcaXY()) < dcanegtopv) { + continue; + } + v0GoodNegTracks(t0.globalIndex(), t0.collisionId(), -t0.dcaXY()); } - v0GoodNegTracks(t0.globalIndex(), t0.collisionId(), -t0.dcaXY()); } } }; From a829d8eb900fd60dc213cb01dc90962049a4d649 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Tue, 10 Nov 2020 21:45:22 +0100 Subject: [PATCH 1623/1751] Add function to dumpGBT data per link --- .../include/TPCReconstruction/RawReaderCRU.h | 17 +++-- .../TPC/reconstruction/src/RawReaderCRU.cxx | 69 +++++++++++++++++++ 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h index ef6ca52e2ae3a..90ba8be7adf6e 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h @@ -629,6 +629,9 @@ class RawReaderCRU /// copy single events to another file void copyEvents(const std::vector<uint32_t>& eventNumbers, std::string outputDirectory, std::ios_base::openmode mode = std::ios_base::openmode(0)); + /// write GBT data into separate files per link + void writeGBTDataPerLink(std::string_view outputDirectory, int maxEvents = -1); + /// run a data filling callback function void runADCDataCallback(const ADCRawData& rawData); @@ -764,10 +767,10 @@ inline void GBTFrame::updateSyncCheck(SyncArray& syncArray) // shift in a 1 if the halfword is 0x15 if (mFrameHalfWords[s][hPos] == 0x15) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1) | 1; - // shift in a 0 if the halfword is 0xA + // shift in a 0 if the halfword is 0xA } else if (mFrameHalfWords[s][hPos] == 0xA) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1); - // otherwise reset the register to 0 + // otherwise reset the register to 0 } else { mSyncCheckRegister[s] = 0; } @@ -792,10 +795,10 @@ inline void GBTFrame::updateSyncCheck(bool verbose) // shift in a 1 if the halfword is 0x15 if (mFrameHalfWords[s][hPos] == 0x15) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1) | 1; - // shift in a 0 if the halfword is 0xA + // shift in a 0 if the halfword is 0xA } else if (mFrameHalfWords[s][hPos] == 0xA) { mSyncCheckRegister[s] = (mSyncCheckRegister[s] << 1); - // otherwise reset the register to 0 + // otherwise reset the register to 0 } else { mSyncCheckRegister[s] = 0; } @@ -968,6 +971,12 @@ class RawReaderCRUManager /// copy single events from raw input files to another file static void copyEvents(const std::string_view inputFileNames, const std::vector<uint32_t> eventNumbers, std::string_view outputDirectory, std::ios_base::openmode mode = std::ios_base::openmode(0)); + /// copy single events from raw input files to another file + void writeGBTDataPerLink(std::string_view outputDirectory, int maxEvents = -1); + + /// copy single events from raw input files to another file + static void writeGBTDataPerLink(const std::string_view inputFileNames, std::string_view outputDirectory, int maxEvents = -1); + /// set a callback function void setADCDataCallback(ADCDataCallback function) { mADCDataCallback = function; } diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index 91db830c8b619..079e667760b40 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -842,6 +842,49 @@ void RawReaderCRU::copyEvents(const std::vector<uint32_t>& eventNumbers, std::st } } } + +void RawReaderCRU::writeGBTDataPerLink(std::string_view outputDirectory, int maxEvents) +{ + // open the input file + std::ifstream& file = mFileHandle; + if (!file.is_open()) { + file.open(mInputFileName, std::ifstream::binary); + if (!file.good()) { + throw std::runtime_error("Unable to open or access file " + mInputFileName); + } + } + + // data buffer. Maximum size is 8k + char buffer[8192]; + + // loop over events + for (int eventNumber = 0; eventNumber < getNumberOfEvents(); ++eventNumber) { + if ((maxEvents > -1) && (eventNumber > maxEvents)) { + break; + } + + const auto& linkInfoArray = mManager->mEventSync.getLinkInfoArrayForEvent(eventNumber, mCRU); + + for (int iLink = 0; iLink < MaxNumberOfLinks; ++iLink) { + const auto& linkInfo = linkInfoArray[iLink]; + if (!linkInfo.IsPresent) { + continue; + } + + const int ep = iLink >= 12; + const int link = iLink - (ep)*12; + auto outputFileName = fmt::format("{}/CRU_{:02}_EP_{}_Link_{:02}", outputDirectory.data(), mCRU, ep, link); + std::ofstream outputFile(outputFileName, std::ios_base::binary); + + for (auto packetNumber : linkInfo.PacketPositions) { + const auto& packet = mPacketDescriptorMaps[iLink][packetNumber]; + file.seekg(packet.getPayloadOffset(), file.beg); + file.read(buffer, packet.getPayloadSize()); + outputFile.write(buffer, packet.getPayloadSize()); + } + } + } +} //============================================================================== //===| stream overloads for helper classes |==================================== // @@ -1058,6 +1101,32 @@ void RawReaderCRUManager::copyEvents(const std::string_view inputFileNames, cons manager.copyEvents(eventNumbers, outputDirectory, mode); } +void RawReaderCRUManager::writeGBTDataPerLink(std::string_view outputDirectory, int maxEvents) +{ + init(); + const auto& cruSeen = mEventSync.getCRUSeen(); + + for (size_t iCRU = 0; iCRU < cruSeen.size(); ++iCRU) { + const auto readerNumber = cruSeen[iCRU]; + if (readerNumber >= 0) { + auto& reader = mRawReadersCRU[readerNumber]; + reader->forceCRU(iCRU); + reader->writeGBTDataPerLink(outputDirectory, maxEvents); + } + } +} + +void RawReaderCRUManager::writeGBTDataPerLink(const std::string_view inputFileNames, std::string_view outputDirectory, int maxEvents) +{ + if (gSystem->AccessPathName(outputDirectory.data())) { + gSystem->mkdir(outputDirectory.data(), kTRUE); + } + + RawReaderCRUManager manager; + manager.setupReaders(inputFileNames); + manager.writeGBTDataPerLink(outputDirectory, maxEvents); +} + void RawReaderCRUManager::processEvent(uint32_t eventNumber, EndReaderCallback endReader) { const auto& cruSeen = mEventSync.getCRUSeen(); From fa2dc2e77ce1b2c82056f0ca0a709a2efe81c95f Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Tue, 10 Nov 2020 21:51:54 +0100 Subject: [PATCH 1624/1751] fix meta data entry --- Detectors/TPC/base/include/TPCBase/CDBInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/base/include/TPCBase/CDBInterface.h b/Detectors/TPC/base/include/TPCBase/CDBInterface.h index 476ca0b78a025..3d186e2eb8730 100644 --- a/Detectors/TPC/base/include/TPCBase/CDBInterface.h +++ b/Detectors/TPC/base/include/TPCBase/CDBInterface.h @@ -260,7 +260,7 @@ class CDBStorage void setJIRA(std::string_view jira) { - mMetaData["Intervention"] = jira; + mMetaData["JIRA"] = jira; } void setComment(std::string_view comment) From 4ee1271920fd3be40e70972ad9eff69656333de7 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Tue, 10 Nov 2020 21:53:05 +0100 Subject: [PATCH 1625/1751] Add median per stack, alias for edge pad --- .../TPC/calibration/src/CalibTreeDump.cxx | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/calibration/src/CalibTreeDump.cxx b/Detectors/TPC/calibration/src/CalibTreeDump.cxx index 0f92e2c502518..3dc4709f9b7fc 100644 --- a/Detectors/TPC/calibration/src/CalibTreeDump.cxx +++ b/Detectors/TPC/calibration/src/CalibTreeDump.cxx @@ -219,20 +219,27 @@ void CalibTreeDump::addCalDetObjects(TTree* tree) std::string meanName = fmt::format("{}_mean", name); std::string stdDevName = fmt::format("{}_stdDev", name); std::string medianName = fmt::format("{}_median", name); + std::string median1Name = fmt::format("{}_median1", name); + std::string median2Name = fmt::format("{}_median2", name); + std::string median3Name = fmt::format("{}_median3", name); // ===| branch variables |=== std::vector<float>* data = nullptr; float mean{}; float stdDev{}; - float median{}; + float median[4]{}; // ===| branch definitions |=== TBranch* brMean = tree->Branch(meanName.data(), &mean); TBranch* brStdDev = tree->Branch(stdDevName.data(), &stdDev); - TBranch* brMedian = tree->Branch(medianName.data(), &median); + TBranch* brMedian = tree->Branch(medianName.data(), &median[0]); + TBranch* brMedian1 = tree->Branch(median1Name.data(), &median[1]); + TBranch* brMedian2 = tree->Branch(median2Name.data(), &median[2]); + TBranch* brMedian3 = tree->Branch(median3Name.data(), &median[3]); TBranch* brData = tree->Branch(name.data(), &data); // ===| loop over ROCs and fill |=== + int roc = 0; for (auto& calArray : calDet.getData()) { // ---| set data |--- data = &calArray.getData(); @@ -240,13 +247,22 @@ void CalibTreeDump::addCalDetObjects(TTree* tree) // ---| statistics |--- mean = TMath::Mean(data->begin(), data->end()); stdDev = TMath::StdDev(data->begin(), data->end()); - median = TMath::Median(data->size(), data->data()); + median[0] = median[1] = median[2] = median[3] = TMath::Median(data->size(), data->data()); + if (roc > 35) { + median[1] = TMath::Median(Mapper::getPadsInOROC1(), data->data()); + median[2] = TMath::Median(Mapper::getPadsInOROC2(), data->data() + Mapper::getPadsInOROC1()); + median[3] = TMath::Median(Mapper::getPadsInOROC3(), data->data() + Mapper::getPadsInOROC1() + Mapper::getPadsInOROC2()); + } // ---| filling |--- brData->Fill(); brMean->Fill(); brStdDev->Fill(); brMedian->Fill(); + brMedian1->Fill(); + brMedian2->Fill(); + brMedian3->Fill(); + ++roc; } } } @@ -316,6 +332,8 @@ void CalibTreeDump::setTraceLengths(std::string_view inputFile, std::vector<floa void CalibTreeDump::setDefaultAliases(TTree* tree) { tree->SetAlias("sector", "roc%36"); + tree->SetAlias("padsPerRow", "2*(pad-cpad)"); + tree->SetAlias("isEdgePad", "(pad==0) || (pad==padsPerRow-1)"); tree->SetAlias("rowInSector", "row + (roc>35)*63"); tree->SetAlias("padWidth", "0.4 + (roc > 35) * 0.2"); tree->SetAlias("padHeight", "0.75 + (rowInSector > 62) * 0.25 + (rowInSector > 96) * 0.2 + (rowInSector > 126) * 0.3"); From b160fdd802c32013305ee52c6049d8521e1615ec Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Tue, 10 Nov 2020 21:53:26 +0100 Subject: [PATCH 1626/1751] rework pedestal calibration o move calibratoin workflow from calibration to workflow o Change to task for easier handling o Add more processing options o Add sending of calibration data to be able to store them in CCDB --- Detectors/TPC/calibration/CMakeLists.txt | 5 - .../TPC/calibration/run/calib-pedestal.cxx | 236 ---------------- Detectors/TPC/workflow/CMakeLists.txt | 6 + .../TPCWorkflow/TPCCalibPedestalSpec.h | 261 ++++++++++++++++++ .../TPC/workflow/src/tpc-calib-pedestal.cxx | 72 +++++ 5 files changed, 339 insertions(+), 241 deletions(-) delete mode 100644 Detectors/TPC/calibration/run/calib-pedestal.cxx create mode 100644 Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h create mode 100644 Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx diff --git a/Detectors/TPC/calibration/CMakeLists.txt b/Detectors/TPC/calibration/CMakeLists.txt index 6ecb2524b54cc..2cb2ba2a08347 100644 --- a/Detectors/TPC/calibration/CMakeLists.txt +++ b/Detectors/TPC/calibration/CMakeLists.txt @@ -36,11 +36,6 @@ o2_target_root_dictionary(TPCCalibration include/TPCCalibration/CalibPadGainTracks.h include/TPCCalibration/FastHisto.h) -o2_add_executable(calib-pedestal - COMPONENT_NAME tpc - SOURCES run/calib-pedestal.cxx - PUBLIC_LINK_LIBRARIES O2::TPCCalibration O2::Framework O2::DPLUtils) - o2_add_test_root_macro(macro/comparePedestalsAndNoise.C PUBLIC_LINK_LIBRARIES O2::TPCBase LABELS tpc) diff --git a/Detectors/TPC/calibration/run/calib-pedestal.cxx b/Detectors/TPC/calibration/run/calib-pedestal.cxx deleted file mode 100644 index 0bd23979cb80c..0000000000000 --- a/Detectors/TPC/calibration/run/calib-pedestal.cxx +++ /dev/null @@ -1,236 +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. - -#include <fmt/format.h> -#include "Framework/WorkflowSpec.h" -#include "Framework/DataProcessorSpec.h" -#include "Framework/DataSpecUtils.h" -#include "Framework/ControlService.h" -#include "Framework/Logger.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/CompletionPolicy.h" -#include "Framework/CompletionPolicyHelpers.h" -#include "DPLUtils/RawParser.h" -#include "Headers/DataHeader.h" -#include "CommonUtils/ConfigurableParam.h" -#include "TPCCalibration/CalibPedestal.h" -#include "TPCReconstruction/RawReaderCRU.h" -#include <vector> -#include <string> -#include "DetectorsRaw/RDHUtils.h" - -using namespace o2::framework; -using RDHUtils = o2::raw::RDHUtils; - -// customize the completion policy -void customize(std::vector<o2::framework::CompletionPolicy>& policies) -{ - using o2::framework::CompletionPolicy; - policies.push_back(CompletionPolicyHelpers::defineByName("calib-pedestal", CompletionPolicy::CompletionOp::Consume)); -} - -// we need to add workflow options before including Framework/runDataProcessing -void customize(std::vector<ConfigParamSpec>& workflowOptions) -{ - std::vector<ConfigParamSpec> options{ - {"input-spec", VariantType::String, "A:TPC/RAWDATA", {"selection string input specs"}}, - {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings (e.g.: 'TPCCalibPedestal.FirstTimeBin=10;...')"}}, - {"configFile", VariantType::String, "", {"configuration file for configurable parameters"}}}; - - std::swap(workflowOptions, options); -} - -#include "Framework/runDataProcessing.h" - -using RDH = o2::header::RAWDataHeader; - -void printHeader() -{ - LOGP(debug, "{:>5} {:>4} {:>4} {:>4} {:>3} {:>4} {:>10} {:>5} {:>1} {:>10}", "PkC", "pCnt", "fId", "Mem", "CRU", "GLID", "HBOrbit", "HB BC", "s", "Trg"); -} - -void printRDH(const RDH& rdh) -{ - const int globalLinkID = int(RDHUtils::getLinkID(rdh)) + (((rdh.word1 >> 32) >> 28) * 12); - - LOGP(debug, "{:>5} {:>4} {:>4} {:>4} {:>3} {:>4} {:>10} {:>5} {:>1} {:#010X}", (uint64_t)RDHUtils::getPacketCounter(rdh), (uint64_t)RDHUtils::getPageCounter(rdh), - (uint64_t)RDHUtils::getFEEID(rdh), (uint64_t)RDHUtils::getMemorySize(rdh), (uint64_t)RDHUtils::getCRUID(rdh), (uint64_t)globalLinkID, - (uint64_t)RDHUtils::getHeartBeatOrbit(rdh), (uint64_t)RDHUtils::getHeartBeatBC(rdh), (uint64_t)RDHUtils::getStop(rdh), (uint64_t)RDHUtils::getTriggerType(rdh)); -} - -WorkflowSpec defineDataProcessing(ConfigContext const& config) -{ - using namespace o2::tpc; - - // set up configuration - o2::conf::ConfigurableParam::updateFromFile(config.options().get<std::string>("configFile")); - o2::conf::ConfigurableParam::updateFromString(config.options().get<std::string>("configKeyValues")); - o2::conf::ConfigurableParam::writeINI("o2tpccalibration_configuration.ini"); - - struct ProcessAttributes { - CalibPedestal calibPedestal; - rawreader::RawReaderCRUManager rawReader; - uint32_t lastOrbit{0}; - uint64_t lastTFID{0}; - uint32_t maxEvents{100}; - bool quit{false}; - bool dumped{false}; - }; - - auto initFunction = [](InitContext& ic) { - auto processAttributes = std::make_shared<ProcessAttributes>(); - // set up calibration - // TODO: - // it is a bit ugly to use the RawReaderCRUManager for this is. - // At some point the raw reader code should be cleaned up and modularized - { - auto& pedestal = processAttributes->calibPedestal; - pedestal.init(); // initialize configuration via configKeyValues - processAttributes->rawReader.createReader(""); - processAttributes->rawReader.setADCDataCallback([&pedestal](const PadROCPos& padROCPos, const CRU& cru, const gsl::span<const uint32_t> data) -> Int_t { - Int_t timeBins = pedestal.update(padROCPos, cru, data); - pedestal.setNumberOfProcessedTimeBins(std::max(pedestal.getNumberOfProcessedTimeBins(), size_t(timeBins))); - return timeBins; - }); - processAttributes->maxEvents = static_cast<uint32_t>(ic.options().get<int>("max-events")); - } - - auto processingFct = [processAttributes](ProcessingContext& pc) { - // in case the maximum number of events was reached don't do further processing - if (processAttributes->quit) { - return; - } - - if (pc.inputs().isValid("TFID")) { - auto tfid = pc.inputs().get<uint64_t>("TFID"); - LOGP(info, "TFid: {}", tfid); - processAttributes->lastTFID = tfid; - } - - for (auto& input : pc.inputs()) { - const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(input); - - // ---| only process RAWDATA, there might be a nicer way to do this |--- - if (dh == nullptr || dh->dataDescription != o2::header::gDataDescriptionRawData) { - continue; - } - - // ---| extract hardware information to do the processing |--- - const auto subSpecification = dh->subSpecification; - const auto cruID = subSpecification >> 16; - const auto linkID = ((subSpecification + (subSpecification >> 8)) & 0xFF) - 1; - const auto dataWrapperID = ((subSpecification >> 8) & 0xFF) > 0; - const auto globalLinkID = linkID + dataWrapperID * 12; - - // ---| update hardware information in the reader |--- - auto& reader = processAttributes->rawReader.getReaders()[0]; - reader->forceCRU(cruID); - reader->setLink(globalLinkID); - - LOGP(debug, "Specifier: {}/{}/{}", dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>(), dh->subSpecification); - LOGP(debug, "Payload size: {}", dh->payloadSize); - LOGP(debug, "CRU: {}; linkID: {}; dataWrapperID: {}; globalLinkID: {}", cruID, linkID, dataWrapperID, globalLinkID); - - printHeader(); - - // TODO: exception handling needed? - try { - o2::framework::RawParser parser(input.payload, dh->payloadSize); - - // TODO: it would be better to have external event handling and then moving the event processing functionality to CalibRawBase and RawReader to not repeat it in other places - rawreader::ADCRawData rawData; - rawreader::GBTFrame gFrame; - - auto& calibPedestal = processAttributes->calibPedestal; - - for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { - auto* rdhPtr = it.get_if<o2::header::RAWDataHeader>(); - if (!rdhPtr) { - break; - } - const auto& rdh = *rdhPtr; - printRDH(rdh); - // ===| event handling |=== - // - // really ugly, better treatment required extension in DPL - // events are are detected by close by orbit numbers - // might be possible to change this using the TFID information - // - const auto hbOrbit = RDHUtils::getHeartBeatOrbit(rdhPtr); - const auto lastOrbit = processAttributes->lastOrbit; - - if ((lastOrbit > 0) && (hbOrbit > (lastOrbit + 3))) { - calibPedestal.incrementNEvents(); - LOGP(info, "Number of processed events: {} ({})", calibPedestal.getNumberOfProcessedEvents(), processAttributes->maxEvents); - if (calibPedestal.getNumberOfProcessedEvents() >= processAttributes->maxEvents) { - LOGP(info, "Maximm number of events reached ({}), no more processing will be done", processAttributes->maxEvents); - processAttributes->quit = true; - break; - } - } - - processAttributes->lastOrbit = hbOrbit; - const auto size = it.size(); - auto data = it.data(); - //LOGP(info, "Data size: {}", size); - - int iFrame = 0; - for (int i = 0; i < size; i += 16) { - gFrame.setFrameNumber(iFrame); - gFrame.setPacketNumber(iFrame / 508); - gFrame.readFromMemory(gsl::span<const o2::byte>(data + i, 16)); - - // extract the half words from the 4 32-bit words - gFrame.getFrameHalfWords(); - - // debug output - //if (CHECK_BIT(mDebugLevel, DebugLevel::GBTFrames)) { - //std::cout << gFrame; - //} - - gFrame.getAdcValues(rawData); - gFrame.updateSyncCheck(false); - - ++iFrame; - } - } - - reader->runADCDataCallback(rawData); - } catch (const std::runtime_error& e) { - LOGP(error, "can not create raw parser form input data"); - o2::header::hexDump("payload", input.payload, dh->payloadSize, 64); - LOG(ERROR) << e.what(); - } - } - - // TODO: For the moment simply dump calibration output to file, to check if everything is working as expected - if (processAttributes->quit && !processAttributes->dumped) { - LOGP(info, "Dumping output"); - processAttributes->calibPedestal.analyse(); - processAttributes->calibPedestal.dumpToFile("pedestals.root"); - processAttributes->dumped = true; - //pc.services().get<ControlService>().endOfStream(); - pc.services().get<ControlService>().readyToQuit(QuitRequest::All); - } - }; - - return processingFct; - }; - - WorkflowSpec workflow; - workflow.emplace_back(DataProcessorSpec{ - "calib-pedestal", - select(config.options().get<std::string>("input-spec").c_str()), - Outputs{}, - AlgorithmSpec{initFunction}, - Options{{"max-events", VariantType::Int, 100, {"maximum number of events to process"}}}}); - - return workflow; -} diff --git a/Detectors/TPC/workflow/CMakeLists.txt b/Detectors/TPC/workflow/CMakeLists.txt index 9a7b53474aae2..11fc43759d93e 100644 --- a/Detectors/TPC/workflow/CMakeLists.txt +++ b/Detectors/TPC/workflow/CMakeLists.txt @@ -38,6 +38,12 @@ o2_add_executable(raw-to-digits-workflow SOURCES src/tpc-raw-to-digits-workflow.cxx PUBLIC_LINK_LIBRARIES O2::TPCWorkflow) +o2_add_executable(calib-pedestal + COMPONENT_NAME tpc + SOURCES src/tpc-calib-pedestal.cxx + PUBLIC_LINK_LIBRARIES O2::TPCWorkflow + O2::DetectorsCalibration) + o2_add_test(workflow COMPONENT_NAME tpc LABELS tpc workflow diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h new file mode 100644 index 0000000000000..eef0a19551f61 --- /dev/null +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h @@ -0,0 +1,261 @@ +// 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_CALIBRATION_TPCCALIBPEDESTALSPEC_H +#define O2_CALIBRATION_TPCCALIBPEDESTALSPEC_H + +/// @file TPCCalibPedestalSpec.h +/// @brief TPC Pedestal calibration processor + +#include "DetectorsCalibration/Utils.h" +#include "Framework/Task.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" + +#include "Framework/Logger.h" +#include "Headers/DataHeader.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/CompletionPolicyHelpers.h" +#include "DetectorsCalibration/Utils.h" +#include "DPLUtils/RawParser.h" +#include "Headers/DataHeader.h" +#include "CommonUtils/ConfigurableParam.h" +#include "TPCCalibration/CalibPedestal.h" +#include "TPCReconstruction/RawReaderCRU.h" +#include <vector> +#include <string> +#include "DetectorsRaw/RDHUtils.h" +#include "TPCBase/RDHUtils.h" +#include "TPCBase/CDBInterface.h" +#include "CCDB/CcdbApi.h" + +using namespace o2::framework; +using namespace o2::tpc; +using RDHUtils = o2::raw::RDHUtils; +using clbUtils = o2::calibration::Utils; + +namespace o2 +{ +namespace calibration +{ + +class TPCCalibPedestalDevice : public o2::framework::Task +{ + public: + void init(o2::framework::InitContext& ic) final + { + // set up ADC value filling + mCalibPedestal.init(); // initialize configuration via configKeyValues + mRawReader.createReader(""); + mRawReader.setADCDataCallback([this](const PadROCPos& padROCPos, const CRU& cru, const gsl::span<const uint32_t> data) -> int { + const int timeBins = mCalibPedestal.update(padROCPos, cru, data); + mCalibPedestal.setNumberOfProcessedTimeBins(std::max(mCalibPedestal.getNumberOfProcessedTimeBins(), size_t(timeBins))); + return timeBins; + }); + + mMaxEvents = static_cast<uint32_t>(ic.options().get<int>("max-events")); + mUseOldSubspec = ic.options().get<bool>("use-old-subspec"); + mForceQuit = ic.options().get<bool>("force-quit"); + mDirectFileDump = ic.options().get<bool>("direct-file-dump"); + if (mUseOldSubspec) { + LOGP(info, "Using old subspecification (CruId << 16) | ((LinkId + 1) << (CruEndPoint == 1 ? 8 : 0))"); + } + } + + void run(o2::framework::ProcessingContext& pc) final + { + // in case the maximum number of events was reached don't do further processing + if (mReadyToQuit) { + return; + } + + std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{o2::header::gDataOriginTPC, "RAWDATA"}, Lifetime::Timeframe}}; + + for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) { + const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref); + + // ---| extract hardware information to do the processing |--- + const auto subSpecification = dh->subSpecification; + rdh_utils::FEEIDType feeID = (rdh_utils::FEEIDType)dh->subSpecification; + rdh_utils::FEEIDType cruID, linkID, endPoint; + + if (mUseOldSubspec) { + //---| old definition by Gvozden |--- + cruID = (rdh_utils::FEEIDType)(subSpecification >> 16); + linkID = (rdh_utils::FEEIDType)((subSpecification + (subSpecification >> 8)) & 0xFF) - 1; + endPoint = (rdh_utils::FEEIDType)((subSpecification >> 8) & 0xFF) > 0; + } else { + //---| new definition by David |--- + rdh_utils::getMapping(feeID, cruID, endPoint, linkID); + } + + const auto globalLinkID = linkID + endPoint * 12; + + // ---| update hardware information in the reader |--- + auto& reader = mRawReader.getReaders()[0]; + reader->forceCRU(cruID); + reader->setLink(globalLinkID); + + LOGP(info, "Specifier: {}/{}/{}", dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>(), subSpecification); + LOGP(info, "Payload size: {}", dh->payloadSize); + LOGP(info, "CRU: {}; linkID: {}; endPoint: {}; globalLinkID: {}", cruID, linkID, endPoint, globalLinkID); + + // TODO: exception handling needed? + const gsl::span<const char> raw = pc.inputs().get<gsl::span<char>>(ref); + o2::framework::RawParser parser(raw.data(), raw.size()); + + // TODO: it would be better to have external event handling and then moving the event processing functionality to CalibRawBase and RawReader to not repeat it in other places + rawreader::ADCRawData rawData; + rawreader::GBTFrame gFrame; + + for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { + // debugging stuff + /* + auto* rdhPtr = it.get_if<o2::header::RAWDataHeader>(); + if (!rdhPtr) { + break; + } + const auto& rdh = *rdhPtr; + auto feeID = RDHUtils::getFEEID(rdh); + rdh_utils::FEEIDType cru, link, endPoint; + rdh_utils::getMapping(feeID, cru, endPoint, link); + LOGP(info, "feeID: {} -- CRU: {}; linkID: {}; endPoint: {}", feeID, cru, link, endPoint); + */ + + const auto size = it.size(); + auto data = it.data(); + //LOGP(info, "Data size: {}", size); + + int iFrame = 0; + for (int i = 0; i < size; i += 16) { + gFrame.setFrameNumber(iFrame); + gFrame.setPacketNumber(iFrame / 508); + gFrame.readFromMemory(gsl::span<const o2::byte>(data + i, 16)); + + // extract the half words from the 4 32-bit words + gFrame.getFrameHalfWords(); + + gFrame.getAdcValues(rawData); + gFrame.updateSyncCheck(false); + + ++iFrame; + } + } + + reader->runADCDataCallback(rawData); + } + + mCalibPedestal.incrementNEvents(); + LOGP(info, "Number of processed events: {} ({})", mCalibPedestal.getNumberOfProcessedEvents(), mMaxEvents); + + if ((mCalibPedestal.getNumberOfProcessedEvents() >= mMaxEvents) && !mCalibDumped) { + LOGP(info, "Maximm number of events reached ({}), no more processing will be done", mMaxEvents); + mReadyToQuit = true; + dumpCalibData(); + if (mForceQuit) { + pc.services().get<ControlService>().endOfStream(); + pc.services().get<ControlService>().readyToQuit(QuitRequest::All); + } else { + //pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); + } + } + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + LOGP(info, "endOfStream"); + dumpCalibData(); + sendOutput(ec.outputs()); + ec.services().get<ControlService>().readyToQuit(QuitRequest::Me); + } + + private: + CalibPedestal mCalibPedestal; + rawreader::RawReaderCRUManager mRawReader; + uint32_t mMaxEvents{100}; + bool mReadyToQuit{false}; + bool mCalibDumped{false}; + bool mUseOldSubspec{false}; + bool mForceQuit{false}; + bool mDirectFileDump{false}; + + //____________________________________________________________________________ + void sendOutput(DataAllocator& output) + { + CDBStorage::MetaData_t md; + long timeStart = 0; + long timeEnd = 99999999999999; + + std::array<const CalDet<float>*, 2> data = {&mCalibPedestal.getPedestal(), &mCalibPedestal.getNoise()}; + std::array<CDBType, 2> dataType = {CDBType::CalPedestal, CDBType::CalNoise}; + + for (size_t i = 0; i < data.size(); ++i) { + auto cal = data[i]; + o2::ccdb::CcdbObjectInfo w; + auto image = o2::ccdb::CcdbApi::createObjectImage(cal, &w); + + w.setPath(CDBTypeMap.at(dataType[i])); + w.setStartValidityTimestamp(timeStart); + w.setEndValidityTimestamp(timeEnd); + + LOG(INFO) << "Sending object " << w.getPath() << "/" << w.getFileName() << " of size " << image->size() + << " bytes, valid for " << w.getStartValidityTimestamp() << " : " << w.getEndValidityTimestamp(); + + header::DataHeader::SubSpecificationType subSpec{(header::DataHeader::SubSpecificationType)i}; + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, subSpec}, *image.get()); + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, subSpec}, w); + } + } + + //____________________________________________________________________________ + void dumpCalibData() + { + if (mDirectFileDump && !mCalibDumped) { + LOGP(info, "Dumping output"); + mCalibPedestal.analyse(); + mCalibPedestal.dumpToFile("pedestals.root"); + mCalibDumped = true; + } + } +}; + +} // namespace calibration + +namespace framework +{ + +DataProcessorSpec getTPCCalibPedestalSpec(const std::string inputSpec) +{ + using device = o2::calibration::TPCCalibPedestalDevice; + + std::vector<OutputSpec> outputs; + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload}); + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); + + return DataProcessorSpec{ + "calib-tpc-pedestal", + select(inputSpec.data()), + outputs, + AlgorithmSpec{adaptFromTask<device>()}, + Options{ + {"max-events", VariantType::Int, 100, {"maximum number of events to process"}}, + {"use-old-subspec", VariantType::Bool, false, {"use old subsecifiation definition"}}, + {"force-quit", VariantType::Bool, false, {"force quit after max-events have been reached"}}, + {"direct-file-dump", VariantType::Bool, false, {"directly dump calibration to file"}}, + } // end Options + }; // end DataProcessorSpec +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx b/Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx new file mode 100644 index 0000000000000..77dcaf65b21ad --- /dev/null +++ b/Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx @@ -0,0 +1,72 @@ +// 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 <fmt/format.h> +#include "Framework/WorkflowSpec.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/ControlService.h" +#include "Framework/InputRecordWalker.h" +#include "Framework/Logger.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/CompletionPolicyHelpers.h" +#include "DPLUtils/RawParser.h" +#include "Headers/DataHeader.h" +#include "CommonUtils/ConfigurableParam.h" +#include "TPCCalibration/CalibPedestal.h" +#include "TPCReconstruction/RawReaderCRU.h" +#include <vector> +#include <string> +#include "DetectorsRaw/RDHUtils.h" +#include "TPCBase/RDHUtils.h" +#include "TPCWorkflow/TPCCalibPedestalSpec.h" + +using namespace o2::framework; +using RDHUtils = o2::raw::RDHUtils; + +// customize the completion policy +void customize(std::vector<o2::framework::CompletionPolicy>& policies) +{ + using o2::framework::CompletionPolicy; + policies.push_back(CompletionPolicyHelpers::defineByName("calib-pedestal", CompletionPolicy::CompletionOp::Consume)); +} + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"input-spec", VariantType::String, "A:TPC/RAWDATA", {"selection string input specs"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings (e.g.: 'TPCCalibPedestal.FirstTimeBin=10;...')"}}, + {"configFile", VariantType::String, "", {"configuration file for configurable parameters"}}}; + + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +using RDH = o2::header::RAWDataHeader; + +WorkflowSpec defineDataProcessing(ConfigContext const& config) +{ + using namespace o2::tpc; + + // set up configuration + o2::conf::ConfigurableParam::updateFromFile(config.options().get<std::string>("configFile")); + o2::conf::ConfigurableParam::updateFromString(config.options().get<std::string>("configKeyValues")); + o2::conf::ConfigurableParam::writeINI("o2tpccalibration_configuration.ini"); + + const std::string inputSpec = config.options().get<std::string>("input-spec"); + + WorkflowSpec workflow; + workflow.emplace_back(getTPCCalibPedestalSpec(inputSpec)); + + return workflow; +} From f455e37bbb0d0889bbefa636353b2ccd00872e64 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Thu, 12 Nov 2020 20:51:20 +0100 Subject: [PATCH 1627/1751] Code splitting and cleanup o move common raw data processing function for calibrations to separate file o clean up includes --- Detectors/TPC/workflow/CMakeLists.txt | 7 +- Detectors/TPC/workflow/README.md | 41 ++++++ .../TPCWorkflow/CalibProcessingHelper.h | 36 +++++ .../TPCWorkflow/TPCCalibPedestalSpec.h | 126 ++++-------------- .../workflow/src/CalibProcessingHelper.cxx | 88 ++++++++++++ .../TPC/workflow/src/tpc-calib-pedestal.cxx | 9 +- 6 files changed, 203 insertions(+), 104 deletions(-) create mode 100644 Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h create mode 100644 Detectors/TPC/workflow/src/CalibProcessingHelper.cxx diff --git a/Detectors/TPC/workflow/CMakeLists.txt b/Detectors/TPC/workflow/CMakeLists.txt index 11fc43759d93e..720c31d542017 100644 --- a/Detectors/TPC/workflow/CMakeLists.txt +++ b/Detectors/TPC/workflow/CMakeLists.txt @@ -23,10 +23,12 @@ o2_add_library(TPCWorkflow src/LinkZSToDigitsSpec.cxx src/TPCSectorCompletionPolicy.cxx src/ZSSpec.cxx + src/CalibProcessingHelper.cxx TARGETVARNAME targetName PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsTPC O2::DPLUtils O2::TPCReconstruction - O2::TPCCalibration O2::TPCSimulation) + O2::TPCCalibration O2::TPCSimulation + O2::DetectorsCalibration) o2_add_executable(reco-workflow COMPONENT_NAME tpc @@ -41,8 +43,7 @@ o2_add_executable(raw-to-digits-workflow o2_add_executable(calib-pedestal COMPONENT_NAME tpc SOURCES src/tpc-calib-pedestal.cxx - PUBLIC_LINK_LIBRARIES O2::TPCWorkflow - O2::DetectorsCalibration) + PUBLIC_LINK_LIBRARIES O2::TPCWorkflow) o2_add_test(workflow COMPONENT_NAME tpc diff --git a/Detectors/TPC/workflow/README.md b/Detectors/TPC/workflow/README.md index a7210e008e46c..3a6286756d827 100644 --- a/Detectors/TPC/workflow/README.md +++ b/Detectors/TPC/workflow/README.md @@ -146,3 +146,44 @@ bz= magnetic field * implement configuration from the GRP ## Open questions + +## Calibration workflows + +### Pedestal calibration +#### Options +```bash +--direct-file-dump write final calibration to local root file +--max-events maximum number of events to process +--no-calib-output don't send the calibration data via DPL (required in case the calibration write is not attached) +--use-old-subspec Subspecification is built from RDH like +``` + +#### Runnin with data distribution +In one shell start the data distribution playback, e.g. +```bash +StfBuilder --id builder --data-source-enable --data-source-dir=2020-11-11T14_18_25Z --data-source-rate=100 --dpl-channel-name=dpl-chan --channel-config "name=dpl-chan,type=pair,method=connect,address=ipc:///tmp/stf-builder-dpl-pipe-0,transport=zeromq,rateLogging=1" +``` + +In another shell start the pedestal calibration +```bash +o2-dpl-raw-proxy -b --dataspec "A:TPC/RAWDATA" --channel-config "name=readout-proxy,type=pair,method=bind,address=ipc:///tmp/stf-builder-dpl-pipe-0,transport=zeromq,rateLogging=1" \ +| o2-tpc-calib-pedestal --max-events 5 --direct-file-dump --shm-segment-size $((8<<30)) --no-calib-output --use-old-subspec +``` + +#### Running with raw file playback +Create a raw-reader.cfg e.g. +```bash +i=0; echo "[defaults]"; echo "dataOrigin = TPC"; echo "dataDescription = RAWDATA"; echo; for file in *.raw; do echo "[input-$i]"; echo "dataOrigin = TPC"; echo "dataDescription = RAWDATA"; echo "filePath=$file"; echo; i=$((i+1)); done > raw-reader.cfg +``` + +Then run +```bash +o2-raw-file-reader-workflow --input-conf raw-reader.cfg --nocheck-hbf-per-tf --nocheck-hbf-jump --shm-segment-size $((8<<30)) \ +| o2-tpc-calib-pedestal --max-events 5 --direct-file-dump --shm-segment-size $((8<<30)) --no-calib-output +``` + +#### send data to CCDB +Remove the `--no-calib-output` option and add +```bash +| o2-calibration-ccdb-populator-workflow +``` diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h b/Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h new file mode 100644 index 0000000000000..7c5fd1e182a02 --- /dev/null +++ b/Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h @@ -0,0 +1,36 @@ +// 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_TPC_CalibProcessingHelper_H +#define O2_TPC_CalibProcessingHelper_H + +#include <memory> + +#include "Framework/InputRecord.h" + +using o2::tpc::rawreader::RawReaderCRU; + +namespace o2 +{ +namespace tpc +{ +namespace rawreader +{ +class RawReaderCRU; +} +namespace calib_processing_helper +{ + +void processRawData(o2::framework::InputRecord& inputs, std::unique_ptr<RawReaderCRU>& reader, bool useOldSubspec = false); +} // namespace raw_reader_helper +} // namespace tpc +} // namespace o2 + +#endif diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h index eef0a19551f61..d73fe24fc0dab 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h @@ -14,33 +14,26 @@ /// @file TPCCalibPedestalSpec.h /// @brief TPC Pedestal calibration processor -#include "DetectorsCalibration/Utils.h" +#include <vector> +#include <string> +#include <chrono> + #include "Framework/Task.h" -#include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" -#include "Framework/WorkflowSpec.h" - #include "Framework/Logger.h" +#include "Framework/ConfigParamRegistry.h" + #include "Headers/DataHeader.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/CompletionPolicy.h" -#include "Framework/CompletionPolicyHelpers.h" +#include "CCDB/CcdbApi.h" #include "DetectorsCalibration/Utils.h" -#include "DPLUtils/RawParser.h" -#include "Headers/DataHeader.h" -#include "CommonUtils/ConfigurableParam.h" + +#include "TPCBase/CDBInterface.h" #include "TPCCalibration/CalibPedestal.h" #include "TPCReconstruction/RawReaderCRU.h" -#include <vector> -#include <string> -#include "DetectorsRaw/RDHUtils.h" -#include "TPCBase/RDHUtils.h" -#include "TPCBase/CDBInterface.h" -#include "CCDB/CcdbApi.h" +#include "TPCWorkflow/CalibProcessingHelper.h" using namespace o2::framework; using namespace o2::tpc; -using RDHUtils = o2::raw::RDHUtils; using clbUtils = o2::calibration::Utils; namespace o2 @@ -51,6 +44,8 @@ namespace calibration class TPCCalibPedestalDevice : public o2::framework::Task { public: + TPCCalibPedestalDevice(bool skipCalib) : mSkipCalib(skipCalib) {} + void init(o2::framework::InitContext& ic) final { // set up ADC value filling @@ -78,81 +73,8 @@ class TPCCalibPedestalDevice : public o2::framework::Task return; } - std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{o2::header::gDataOriginTPC, "RAWDATA"}, Lifetime::Timeframe}}; - - for (auto const& ref : InputRecordWalker(pc.inputs(), filter)) { - const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref); - - // ---| extract hardware information to do the processing |--- - const auto subSpecification = dh->subSpecification; - rdh_utils::FEEIDType feeID = (rdh_utils::FEEIDType)dh->subSpecification; - rdh_utils::FEEIDType cruID, linkID, endPoint; - - if (mUseOldSubspec) { - //---| old definition by Gvozden |--- - cruID = (rdh_utils::FEEIDType)(subSpecification >> 16); - linkID = (rdh_utils::FEEIDType)((subSpecification + (subSpecification >> 8)) & 0xFF) - 1; - endPoint = (rdh_utils::FEEIDType)((subSpecification >> 8) & 0xFF) > 0; - } else { - //---| new definition by David |--- - rdh_utils::getMapping(feeID, cruID, endPoint, linkID); - } - - const auto globalLinkID = linkID + endPoint * 12; - - // ---| update hardware information in the reader |--- - auto& reader = mRawReader.getReaders()[0]; - reader->forceCRU(cruID); - reader->setLink(globalLinkID); - - LOGP(info, "Specifier: {}/{}/{}", dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>(), subSpecification); - LOGP(info, "Payload size: {}", dh->payloadSize); - LOGP(info, "CRU: {}; linkID: {}; endPoint: {}; globalLinkID: {}", cruID, linkID, endPoint, globalLinkID); - - // TODO: exception handling needed? - const gsl::span<const char> raw = pc.inputs().get<gsl::span<char>>(ref); - o2::framework::RawParser parser(raw.data(), raw.size()); - - // TODO: it would be better to have external event handling and then moving the event processing functionality to CalibRawBase and RawReader to not repeat it in other places - rawreader::ADCRawData rawData; - rawreader::GBTFrame gFrame; - - for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { - // debugging stuff - /* - auto* rdhPtr = it.get_if<o2::header::RAWDataHeader>(); - if (!rdhPtr) { - break; - } - const auto& rdh = *rdhPtr; - auto feeID = RDHUtils::getFEEID(rdh); - rdh_utils::FEEIDType cru, link, endPoint; - rdh_utils::getMapping(feeID, cru, endPoint, link); - LOGP(info, "feeID: {} -- CRU: {}; linkID: {}; endPoint: {}", feeID, cru, link, endPoint); - */ - - const auto size = it.size(); - auto data = it.data(); - //LOGP(info, "Data size: {}", size); - - int iFrame = 0; - for (int i = 0; i < size; i += 16) { - gFrame.setFrameNumber(iFrame); - gFrame.setPacketNumber(iFrame / 508); - gFrame.readFromMemory(gsl::span<const o2::byte>(data + i, 16)); - - // extract the half words from the 4 32-bit words - gFrame.getFrameHalfWords(); - - gFrame.getAdcValues(rawData); - gFrame.updateSyncCheck(false); - - ++iFrame; - } - } - - reader->runADCDataCallback(rawData); - } + auto& reader = mRawReader.getReaders()[0]; + calib_processing_helper::processRawData(pc.inputs(), reader, mUseOldSubspec); mCalibPedestal.incrementNEvents(); LOGP(info, "Number of processed events: {} ({})", mCalibPedestal.getNumberOfProcessedEvents(), mMaxEvents); @@ -174,7 +96,9 @@ class TPCCalibPedestalDevice : public o2::framework::Task { LOGP(info, "endOfStream"); dumpCalibData(); - sendOutput(ec.outputs()); + if (!mSkipCalib) { + sendOutput(ec.outputs()); + } ec.services().get<ControlService>().readyToQuit(QuitRequest::Me); } @@ -187,12 +111,16 @@ class TPCCalibPedestalDevice : public o2::framework::Task bool mUseOldSubspec{false}; bool mForceQuit{false}; bool mDirectFileDump{false}; + bool mSkipCalib{false}; //____________________________________________________________________________ void sendOutput(DataAllocator& output) { CDBStorage::MetaData_t md; - long timeStart = 0; + + // perhaps should be changed to time of the run + const auto now = std::chrono::system_clock::now(); + long timeStart = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count(); long timeEnd = 99999999999999; std::array<const CalDet<float>*, 2> data = {&mCalibPedestal.getPedestal(), &mCalibPedestal.getNoise()}; @@ -233,19 +161,21 @@ class TPCCalibPedestalDevice : public o2::framework::Task namespace framework { -DataProcessorSpec getTPCCalibPedestalSpec(const std::string inputSpec) +DataProcessorSpec getTPCCalibPedestalSpec(const std::string inputSpec, bool skipCalib) { using device = o2::calibration::TPCCalibPedestalDevice; std::vector<OutputSpec> outputs; - outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload}); - outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); + if (!skipCalib) { + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload}); + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); + } return DataProcessorSpec{ "calib-tpc-pedestal", select(inputSpec.data()), outputs, - AlgorithmSpec{adaptFromTask<device>()}, + AlgorithmSpec{adaptFromTask<device>(skipCalib)}, Options{ {"max-events", VariantType::Int, 100, {"maximum number of events to process"}}, {"use-old-subspec", VariantType::Bool, false, {"use old subsecifiation definition"}}, diff --git a/Detectors/TPC/workflow/src/CalibProcessingHelper.cxx b/Detectors/TPC/workflow/src/CalibProcessingHelper.cxx new file mode 100644 index 0000000000000..bbab31da90957 --- /dev/null +++ b/Detectors/TPC/workflow/src/CalibProcessingHelper.cxx @@ -0,0 +1,88 @@ +// 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/ConcreteDataMatcher.h" +#include "Framework/InputRecordWalker.h" +#include "Framework/Logger.h" + +#include "DPLUtils/RawParser.h" +#include "TPCBase/RDHUtils.h" +#include "TPCReconstruction/RawReaderCRU.h" + +#include "TPCWorkflow/CalibProcessingHelper.h" + +using namespace o2::tpc; +using namespace o2::framework; + +void calib_processing_helper::processRawData(o2::framework::InputRecord& inputs, std::unique_ptr<RawReaderCRU>& reader, bool useOldSubspec) +{ + std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{o2::header::gDataOriginTPC, "RAWDATA"}, Lifetime::Timeframe}}; + + for (auto const& ref : InputRecordWalker(inputs, filter)) { + const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref); + + // ---| extract hardware information to do the processing |--- + const auto subSpecification = dh->subSpecification; + rdh_utils::FEEIDType feeID = (rdh_utils::FEEIDType)dh->subSpecification; + rdh_utils::FEEIDType cruID, linkID, endPoint; + + if (useOldSubspec) { + //---| old definition by Gvozden |--- + cruID = (rdh_utils::FEEIDType)(subSpecification >> 16); + linkID = (rdh_utils::FEEIDType)((subSpecification + (subSpecification >> 8)) & 0xFF) - 1; + endPoint = (rdh_utils::FEEIDType)((subSpecification >> 8) & 0xFF) > 0; + } else { + //---| new definition by David |--- + rdh_utils::getMapping(feeID, cruID, endPoint, linkID); + } + + const auto globalLinkID = linkID + endPoint * 12; + + // ---| update hardware information in the reader |--- + reader->forceCRU(cruID); + reader->setLink(globalLinkID); + + LOGP(info, "Specifier: {}/{}/{}", dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>(), subSpecification); + LOGP(info, "Payload size: {}", dh->payloadSize); + LOGP(info, "CRU: {}; linkID: {}; endPoint: {}; globalLinkID: {}", cruID, linkID, endPoint, globalLinkID); + + // TODO: exception handling needed? + const gsl::span<const char> raw = inputs.get<gsl::span<char>>(ref); + o2::framework::RawParser parser(raw.data(), raw.size()); + + // TODO: it would be better to have external event handling and then moving the event processing functionality to CalibRawBase and RawReader to not repeat it in other places + rawreader::ADCRawData rawData; + rawreader::GBTFrame gFrame; + + for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { + + const auto size = it.size(); + auto data = it.data(); + //LOGP(info, "Data size: {}", size); + + int iFrame = 0; + for (int i = 0; i < size; i += 16) { + gFrame.setFrameNumber(iFrame); + gFrame.setPacketNumber(iFrame / 508); + gFrame.readFromMemory(gsl::span<const o2::byte>(data + i, 16)); + + // extract the half words from the 4 32-bit words + gFrame.getFrameHalfWords(); + + gFrame.getAdcValues(rawData); + gFrame.updateSyncCheck(false); + + ++iFrame; + } + } + + reader->runADCDataCallback(rawData); + } +} diff --git a/Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx b/Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx index 77dcaf65b21ad..ba58c351beaab 100644 --- a/Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx +++ b/Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx @@ -36,7 +36,7 @@ using RDHUtils = o2::raw::RDHUtils; void customize(std::vector<o2::framework::CompletionPolicy>& policies) { using o2::framework::CompletionPolicy; - policies.push_back(CompletionPolicyHelpers::defineByName("calib-pedestal", CompletionPolicy::CompletionOp::Consume)); + policies.push_back(CompletionPolicyHelpers::defineByName("calib-tpc-pedestal", CompletionPolicy::CompletionOp::Consume)); } // we need to add workflow options before including Framework/runDataProcessing @@ -45,7 +45,9 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) std::vector<ConfigParamSpec> options{ {"input-spec", VariantType::String, "A:TPC/RAWDATA", {"selection string input specs"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings (e.g.: 'TPCCalibPedestal.FirstTimeBin=10;...')"}}, - {"configFile", VariantType::String, "", {"configuration file for configurable parameters"}}}; + {"configFile", VariantType::String, "", {"configuration file for configurable parameters"}}, + {"no-calib-output", VariantType::Bool, false, {"skip sending the calibration output"}}, + }; std::swap(workflowOptions, options); } @@ -64,9 +66,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) o2::conf::ConfigurableParam::writeINI("o2tpccalibration_configuration.ini"); const std::string inputSpec = config.options().get<std::string>("input-spec"); + const auto skipCalib = config.options().get<bool>("no-calib-output"); WorkflowSpec workflow; - workflow.emplace_back(getTPCCalibPedestalSpec(inputSpec)); + workflow.emplace_back(getTPCCalibPedestalSpec(inputSpec, skipCalib)); return workflow; } From f810f1a55d510e87a26bf12b4f1e995dc83de6fa Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Sun, 15 Nov 2020 21:33:36 +0100 Subject: [PATCH 1628/1751] rework RawToDigitsSpec --- Detectors/TPC/workflow/README.md | 20 +- .../TPCWorkflow/CalibProcessingHelper.h | 4 +- .../include/TPCWorkflow/RawToDigitsSpec.h | 2 +- .../workflow/src/CalibProcessingHelper.cxx | 9 +- .../TPC/workflow/src/RawToDigitsSpec.cxx | 291 +++++++----------- .../src/tpc-raw-to-digits-workflow.cxx | 16 - 6 files changed, 138 insertions(+), 204 deletions(-) diff --git a/Detectors/TPC/workflow/README.md b/Detectors/TPC/workflow/README.md index 3a6286756d827..85d3fdd4e3c60 100644 --- a/Detectors/TPC/workflow/README.md +++ b/Detectors/TPC/workflow/README.md @@ -158,7 +158,7 @@ bz= magnetic field --use-old-subspec Subspecification is built from RDH like ``` -#### Runnin with data distribution +#### Running with data distribution In one shell start the data distribution playback, e.g. ```bash StfBuilder --id builder --data-source-enable --data-source-dir=2020-11-11T14_18_25Z --data-source-rate=100 --dpl-channel-name=dpl-chan --channel-config "name=dpl-chan,type=pair,method=connect,address=ipc:///tmp/stf-builder-dpl-pipe-0,transport=zeromq,rateLogging=1" @@ -173,7 +173,7 @@ o2-dpl-raw-proxy -b --dataspec "A:TPC/RAWDATA" --channel-config "name=readout-pr #### Running with raw file playback Create a raw-reader.cfg e.g. ```bash -i=0; echo "[defaults]"; echo "dataOrigin = TPC"; echo "dataDescription = RAWDATA"; echo; for file in *.raw; do echo "[input-$i]"; echo "dataOrigin = TPC"; echo "dataDescription = RAWDATA"; echo "filePath=$file"; echo; i=$((i+1)); done > raw-reader.cfg +i=0; echo -e "[defaults]\ndataOrigin = TPC\ndataDescription = RAWDATA\n" > raw-reader.cfg; echo; for file in *.raw; do echo "[input-$i]"; echo "dataOrigin = TPC"; echo "dataDescription = RAWDATA"; echo "filePath=$file"; echo; i=$((i+1)); done >> raw-reader.cfg ``` Then run @@ -182,8 +182,22 @@ o2-raw-file-reader-workflow --input-conf raw-reader.cfg --nocheck-hbf-per-tf -- | o2-tpc-calib-pedestal --max-events 5 --direct-file-dump --shm-segment-size $((8<<30)) --no-calib-output ``` -#### send data to CCDB +#### Send data to CCDB Remove the `--no-calib-output` option and add ```bash | o2-calibration-ccdb-populator-workflow ``` + +## Running the recontruction on GBT raw data +This requires to do zero suppression in the first stage. For this the `DigiDump` class is used, wrapped in an o2 workflow. + +Use either the [DD](#running-with-data-distribution) part or [raw file playback](#running-with-raw-file-playback) from above and add as processor +```bash +| o2-tpc-raw-to-digits-workflow --pedestal-file pedestals.root --configKeyValues "TPCDigitDump.ADCMin=3;TPCDigitDump.NoiseThreshold=3" \ +| o2-tpc-reco-workflow --input-type digitizer --output-type tracks --disable-mc +``` + +To directly dump the digits to file for inspection use for the reco workflow +```bash +| o2-tpc-reco-workflow --input-type digitizer --output-type digits --disable-mc +``` diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h b/Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h index 7c5fd1e182a02..74158f92ee406 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h @@ -28,8 +28,8 @@ class RawReaderCRU; namespace calib_processing_helper { -void processRawData(o2::framework::InputRecord& inputs, std::unique_ptr<RawReaderCRU>& reader, bool useOldSubspec = false); -} // namespace raw_reader_helper +uint64_t processRawData(o2::framework::InputRecord& inputs, std::unique_ptr<RawReaderCRU>& reader, bool useOldSubspec = false); +} // namespace calib_processing_helper } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h index c0e1703ee632f..ffacb3a870af2 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h @@ -26,7 +26,7 @@ namespace tpc /// create a processor spec /// read simulated TPC clusters from file and publish -o2::framework::DataProcessorSpec getRawToDigitsSpec(int channel, const std::string_view inputDef, std::vector<int> const& tpcSectors); +o2::framework::DataProcessorSpec getRawToDigitsSpec(int channel, const std::string inputSpec, std::vector<int> const& tpcSectors); } // end namespace tpc } // end namespace o2 diff --git a/Detectors/TPC/workflow/src/CalibProcessingHelper.cxx b/Detectors/TPC/workflow/src/CalibProcessingHelper.cxx index bbab31da90957..6f42bfa033dcf 100644 --- a/Detectors/TPC/workflow/src/CalibProcessingHelper.cxx +++ b/Detectors/TPC/workflow/src/CalibProcessingHelper.cxx @@ -21,10 +21,12 @@ using namespace o2::tpc; using namespace o2::framework; -void calib_processing_helper::processRawData(o2::framework::InputRecord& inputs, std::unique_ptr<RawReaderCRU>& reader, bool useOldSubspec) +uint64_t calib_processing_helper::processRawData(o2::framework::InputRecord& inputs, std::unique_ptr<RawReaderCRU>& reader, bool useOldSubspec) { std::vector<InputSpec> filter = {{"check", ConcreteDataTypeMatcher{o2::header::gDataOriginTPC, "RAWDATA"}, Lifetime::Timeframe}}; + uint64_t activeSectors = 0; + for (auto const& ref : InputRecordWalker(inputs, filter)) { const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref); @@ -43,6 +45,9 @@ void calib_processing_helper::processRawData(o2::framework::InputRecord& inputs, rdh_utils::getMapping(feeID, cruID, endPoint, linkID); } + uint64_t sector = cruID / 10; + activeSectors |= (0x1 << sector); + const auto globalLinkID = linkID + endPoint * 12; // ---| update hardware information in the reader |--- @@ -85,4 +90,6 @@ void calib_processing_helper::processRawData(o2::framework::InputRecord& inputs, reader->runADCDataCallback(rawData); } + + return activeSectors; } diff --git a/Detectors/TPC/workflow/src/RawToDigitsSpec.cxx b/Detectors/TPC/workflow/src/RawToDigitsSpec.cxx index 69eae838dd275..bc36ab063c59a 100644 --- a/Detectors/TPC/workflow/src/RawToDigitsSpec.cxx +++ b/Detectors/TPC/workflow/src/RawToDigitsSpec.cxx @@ -8,23 +8,25 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/WorkflowSpec.h" +#include <vector> +#include <string> +#include "fmt/format.h" + +#include "Framework/Task.h" #include "Framework/ControlService.h" -#include "Framework/DataProcessorSpec.h" #include "Framework/ConfigParamRegistry.h" -#include "Framework/DataRefUtils.h" -#include "Framework/Lifetime.h" -#include "DPLUtils/RawParser.h" -#include "Headers/DataHeader.h" +#include "Framework/Logger.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/WorkflowSpec.h" + #include "DataFormatsTPC/TPCSectorHeader.h" -#include "DataFormatsTPC/Digit.h" +#include "Headers/DataHeader.h" +#include "CCDB/CcdbApi.h" +#include "DetectorsCalibration/Utils.h" + #include "TPCCalibration/DigitDump.h" #include "TPCReconstruction/RawReaderCRU.h" -#include "TPCWorkflow/RawToDigitsSpec.h" -#include "Framework/Logger.h" -#include <vector> -#include <string> - +#include "TPCWorkflow/CalibProcessingHelper.h" using namespace o2::framework; using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; @@ -33,192 +35,119 @@ namespace o2 namespace tpc { -o2::framework::DataProcessorSpec getRawToDigitsSpec(int channel, const std::string_view inputDef, std::vector<int> const& tpcSectors) +class TPCDigitDumpDevice : public o2::framework::Task { + public: + TPCDigitDumpDevice(const std::vector<int>& sectors) : mSectors(sectors) {} + + void init(o2::framework::InitContext& ic) final + { + // set up ADC value filling + mRawReader.createReader(""); + mDigitDump.init(); + mDigitDump.setInMemoryOnly(); + const auto pedestalFile = ic.options().get<std::string>("pedestal-file"); + LOGP(info, "Setting pedestal file: {}", pedestalFile); + mDigitDump.setPedestalAndNoiseFile(pedestalFile); + + mRawReader.setADCDataCallback([this](const PadROCPos& padROCPos, const CRU& cru, const gsl::span<const uint32_t> data) -> int { + const int timeBins = mDigitDump.update(padROCPos, cru, data); + mDigitDump.setNumberOfProcessedTimeBins(std::max(mDigitDump.getNumberOfProcessedTimeBins(), size_t(timeBins))); + return timeBins; + }); + + mMaxEvents = static_cast<uint32_t>(ic.options().get<int>("max-events")); + mUseOldSubspec = ic.options().get<bool>("use-old-subspec"); + mForceQuit = ic.options().get<bool>("force-quit"); + if (mUseOldSubspec) { + LOGP(info, "Using old subspecification (CruId << 16) | ((LinkId + 1) << (CruEndPoint == 1 ? 8 : 0))"); + } + } - struct ProcessAttributes { - DigitDump digitDump; ///< digits creation class - rawreader::RawReaderCRUManager rawReader; ///< GBT frame decoder - uint32_t lastOrbit{0}; ///< last processed orbit number - uint32_t maxEvents{100}; ///< maximum number of events to process - uint64_t activeSectors{0}; ///< bit mask of active sectors - bool quit{false}; ///< if workflow is ready to quit - std::vector<int> tpcSectors{}; ///< tpc sector configuration - }; - - // ===| stateful initialization |============================================= - // - auto initFunction = [channel, tpcSectors](InitContext& ic) { - // ===| create and set up processing attributes |=== - auto processAttributes = std::make_shared<ProcessAttributes>(); - // set up calibration - { - auto& digitDump = processAttributes->digitDump; - digitDump.init(); - digitDump.setInMemoryOnly(); - const auto pedestalFile = ic.options().get<std::string>("pedestal-file"); - LOGP(info, "Setting pedestal file: {}", pedestalFile); - digitDump.setPedestalAndNoiseFile(pedestalFile); - - processAttributes->rawReader.createReader(""); - processAttributes->rawReader.setADCDataCallback([&digitDump](const PadROCPos& padROCPos, const CRU& cru, const gsl::span<const uint32_t> data) -> Int_t { - Int_t timeBins = digitDump.update(padROCPos, cru, data); - digitDump.setNumberOfProcessedTimeBins(std::max(digitDump.getNumberOfProcessedTimeBins(), size_t(timeBins))); - return timeBins; - }); - processAttributes->maxEvents = static_cast<uint32_t>(ic.options().get<int>("max-events")); - processAttributes->tpcSectors = tpcSectors; + void run(o2::framework::ProcessingContext& pc) final + { + // in case the maximum number of events was reached don't do further processing + if (mReadyToQuit) { + return; } - // ===| data processor |==================================================== - // - auto processingFct = [processAttributes, channel](ProcessingContext& pc) { - if (processAttributes->quit) { - return; - } + auto& reader = mRawReader.getReaders()[0]; + mActiveSectors = calib_processing_helper::processRawData(pc.inputs(), reader, mUseOldSubspec); - // ===| digit snapshot |=== - // - // lambda that snapshots digits to be sent out; - // prepares and attaches header with sector information - // - auto snapshotDigits = [&pc, processAttributes, channel](std::vector<o2::tpc::Digit> const& digits, int sector) { - o2::tpc::TPCSectorHeader header{sector}; - header.activeSectors = processAttributes->activeSectors; - // digit for now are transported per sector, not per lane - // pc.outputs().snapshot(Output{"TPC", "DIGITS", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe, header}, - pc.outputs().snapshot(Output{"TPC", "DIGITS", static_cast<SubSpecificationType>(sector), Lifetime::Timeframe, header}, - const_cast<std::vector<o2::tpc::Digit>&>(digits)); - }; - - // loop over all inputs - for (auto& input : pc.inputs()) { - const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(input); - - // select only RAW data - if (dh->dataDescription != o2::header::gDataDescriptionRawData) { - continue; - } - - // ===| extract electronics mapping information |=== - const auto subSpecification = dh->subSpecification; - const auto cruID = subSpecification >> 16; - const auto linkID = ((subSpecification + (subSpecification >> 8)) & 0xFF) - 1; - const auto dataWrapperID = ((subSpecification >> 8) & 0xFF) > 0; - const auto globalLinkID = linkID + dataWrapperID * 12; - const auto sector = cruID / 10; - - // update active sectors - processAttributes->activeSectors |= (0x1 << sector); - - // set up mapping information for raw reader - auto& reader = processAttributes->rawReader.getReaders()[0]; - reader->forceCRU(cruID); - reader->setLink(globalLinkID); - - LOGP(debug, "Specifier: {}/{}/{}", dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>(), dh->subSpecification); - LOGP(debug, "Payload size: {}", dh->payloadSize); - LOGP(debug, "CRU: {}; linkID: {}; dataWrapperID: {}; globalLinkID: {}", cruID, linkID, dataWrapperID, globalLinkID); - - try { - o2::framework::RawParser parser(input.payload, dh->payloadSize); - - rawreader::ADCRawData rawData; - rawreader::GBTFrame gFrame; - - for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { - auto* rdhPtr = it.get_if<o2::header::RAWDataHeaderV4>(); - if (!rdhPtr) { - break; - } - const auto& rdh = *rdhPtr; - //printRDH(rdh); - - // ===| event handling |=== - // - // really ugly, better treatment requires extension in DPL - // events are are detected by close by orbit numbers - // - const auto hbOrbit = rdh.heartbeatOrbit; - const auto lastOrbit = processAttributes->lastOrbit; - - if ((lastOrbit > 0) && (hbOrbit > (lastOrbit + 3))) { - auto& digitDump = processAttributes->digitDump; - digitDump.incrementNEvents(); - LOGP(info, "Number of processed events: {} ({})", digitDump.getNumberOfProcessedEvents(), processAttributes->maxEvents); - digitDump.sortDigits(); - - // publish digits of all configured sectors - for (auto isector : processAttributes->tpcSectors) { - snapshotDigits(digitDump.getDigits(isector), isector); - } - digitDump.clearDigits(); - - processAttributes->activeSectors = 0; - if (digitDump.getNumberOfProcessedEvents() >= processAttributes->maxEvents) { - LOGP(info, "Maximum number of events reached ({}), no more processing will be done", processAttributes->maxEvents); - processAttributes->quit = true; - pc.services().get<ControlService>().endOfStream(); - //pc.services().get<ControlService>().readyToQuit(QuitRequest::All); - pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); - break; - } - } - - processAttributes->lastOrbit = hbOrbit; - const auto size = it.size(); - auto data = it.data(); - LOGP(debug, "Raw data block payload size: {}", size); - - int iFrame = 0; - for (int i = 0; i < size; i += 16) { - gFrame.setFrameNumber(iFrame); - gFrame.setPacketNumber(iFrame / 508); - gFrame.readFromMemory(gsl::span<const o2::byte>(data + i, 16)); - - // extract the half words from the 4 32-bit words - gFrame.getFrameHalfWords(); - - // debug output - //if (CHECK_BIT(mDebugLevel, DebugLevel::GBTFrames)) { - //std::cout << gFrame; - //} - - gFrame.getAdcValues(rawData); - gFrame.updateSyncCheck(false); - - ++iFrame; - } - } - - reader->runADCDataCallback(rawData); - } catch (const std::runtime_error& e) { - LOG(ERROR) << "can not create raw parser form input data"; - o2::header::hexDump("payload", input.payload, dh->payloadSize, 64); - LOG(ERROR) << e.what(); - } + mDigitDump.incrementNEvents(); + LOGP(info, "Number of processed events: {} ({})", mDigitDump.getNumberOfProcessedEvents(), mMaxEvents); + + snapshotDigits(pc.outputs()); + + if ((mDigitDump.getNumberOfProcessedEvents() >= mMaxEvents)) { + LOGP(info, "Maximm number of events reached ({}), no more processing will be done", mMaxEvents); + mReadyToQuit = true; + if (mForceQuit) { + pc.services().get<ControlService>().endOfStream(); + pc.services().get<ControlService>().readyToQuit(QuitRequest::All); + } else { + //pc.services().get<ControlService>().readyToQuit(QuitRequest::Me); } - }; + } + } - return processingFct; - }; + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + LOGP(info, "endOfStream"); + if (mActiveSectors) { + snapshotDigits(ec.outputs()); + } + ec.services().get<ControlService>().readyToQuit(QuitRequest::Me); + } - std::stringstream id; - id << "TPCDigitizer" << channel; + private: + DigitDump mDigitDump; + rawreader::RawReaderCRUManager mRawReader; + uint32_t mMaxEvents{100}; + bool mReadyToQuit{false}; + bool mCalibDumped{false}; + bool mUseOldSubspec{false}; + bool mForceQuit{false}; + uint64_t mActiveSectors{0}; ///< bit mask of active sectors + std::vector<int> mSectors{}; ///< tpc sector configuration + + //____________________________________________________________________________ + void snapshotDigits(DataAllocator& output) + { + mDigitDump.sortDigits(); + for (auto isector : mSectors) { + o2::tpc::TPCSectorHeader header{isector}; + header.activeSectors = mActiveSectors; + // digit for now are transported per sector, not per lane + output.snapshot(Output{"TPC", "DIGITS", static_cast<SubSpecificationType>(isector), Lifetime::Timeframe, header}, + mDigitDump.getDigits(isector)); + } + mDigitDump.clearDigits(); + mActiveSectors = 0; + } +}; + +DataProcessorSpec getRawToDigitsSpec(int channel, const std::string inputSpec, std::vector<int> const& tpcSectors) +{ + using device = o2::tpc::TPCDigitDumpDevice; - std::vector<OutputSpec> outputs; // define channel by triple of (origin, type id of data to be sent on this channel, subspecification) + std::vector<OutputSpec> outputs; for (auto isector : tpcSectors) { outputs.emplace_back("TPC", "DIGITS", static_cast<SubSpecificationType>(isector), Lifetime::Timeframe); } return DataProcessorSpec{ - id.str().c_str(), - select(inputDef.data()), + fmt::format("TPCDigitizer{}", channel), + select(inputSpec.data()), outputs, - AlgorithmSpec{initFunction}, + AlgorithmSpec{adaptFromTask<device>(tpcSectors)}, Options{ {"max-events", VariantType::Int, 100, {"maximum number of events to process"}}, - {"pedestal-file", VariantType::String, "", {"file with pedestals and noise for zero suppression"}}}}; + {"use-old-subspec", VariantType::Bool, false, {"use old subsecifiation definition"}}, + {"force-quit", VariantType::Bool, false, {"force quit after max-events have been reached"}}, + {"pedestal-file", VariantType::String, "", {"file with pedestals and noise for zero suppression"}}, + } // end Options + }; // end DataProcessorSpec } } // namespace tpc } // namespace o2 diff --git a/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx b/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx index b282a0a2269ce..b1ebf0fc1e8ea 100644 --- a/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx @@ -12,8 +12,6 @@ #include "Framework/WorkflowSpec.h" #include "Framework/DataProcessorSpec.h" #include "Framework/ControlService.h" -#include "Framework/CompletionPolicy.h" -#include "Framework/CompletionPolicyHelpers.h" #include "Framework/Logger.h" #include "Framework/ConfigParamSpec.h" #include "CommonUtils/ConfigurableParam.h" @@ -29,17 +27,6 @@ using namespace o2::framework; -// customize the completion policy -void customize(std::vector<o2::framework::CompletionPolicy>& policies) -{ - // we customize the completion policy for the writer since it should stream immediately - using CompletionPolicy = o2::framework::CompletionPolicy; - using CompletionPolicyHelpers = o2::framework::CompletionPolicyHelpers; - policies.push_back(CompletionPolicyHelpers::defineByName("tpc-cluster-decoder.*", CompletionPolicy::CompletionOp::Consume)); - policies.push_back(CompletionPolicyHelpers::defineByName("tpc-clusterer.*", CompletionPolicy::CompletionOp::Consume)); - policies.push_back(CompletionPolicyHelpers::defineByName("tpc-tracker.*", CompletionPolicy::CompletionOp::Consume)); -} - enum class DecoderType { GBT, ///< GBT frame raw decoding LinkZS ///< Link based zero suppression @@ -126,8 +113,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) recoOuput = tpcRecoOutputType.c_str(); } - auto tpcRecoWorkflow = o2::tpc::reco_workflow::getWorkflow(nullptr, tpcSectors, tpcSectors, false, lanes, "digitizer", recoOuput.data()); - specs.insert(specs.end(), tpcRecoWorkflow.begin(), tpcRecoWorkflow.end()); - return specs; } From 9b53c325ffc797bb7b38dce833070589df6bcf96 Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Sun, 15 Nov 2020 21:34:08 +0100 Subject: [PATCH 1629/1751] Add possibility to dump sync positions to file --- .../include/TPCReconstruction/RawReaderCRU.h | 12 ++- .../TPC/reconstruction/src/RawReaderCRU.cxx | 77 +++++++++++++++---- 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h index 90ba8be7adf6e..f8ba8d82401ea 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h @@ -167,6 +167,10 @@ class SyncPosition /// return half word position uint32_t getHalfWordPosition() const { return mHalfWordPos; }; + uint32_t getFrameNumber() const { return mFrameNum; } + + uint32_t getPacketNumber() const { return mPacketNum; } + /// return if sync was found bool synched() const { return mSyncFound; }; @@ -209,7 +213,7 @@ class GBTFrame /// set syncronisation found for stream /// \param stream stream - bool mSyncFound(int stream) { return mSyncPos[stream].synched(); }; + bool syncFound(int stream) { return mSyncPos[stream].synched(); }; /// get the syncronisation array const SyncArray& getSyncArray() const { return mSyncPos; } @@ -635,6 +639,12 @@ class RawReaderCRU /// run a data filling callback function void runADCDataCallback(const ADCRawData& rawData); + /// set output file prefix + void setOutputFilePrefix(std::string_view prefix) { mOutputFilePrefix = prefix; } + + /// output file prefix + const std::string& getOutputFilePrefix() const { return mOutputFilePrefix; } + //=========================================================================== //===| Nested helper classes |=============================================== // diff --git a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx index 079e667760b40..cf40997ba1d7b 100644 --- a/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx +++ b/Detectors/TPC/reconstruction/src/RawReaderCRU.cxx @@ -337,7 +337,7 @@ int RawReaderCRU::scanFile() }; // debug output - if (CHECK_BIT(mDebugLevel, DebugLevel::RDHDump)) { + if (mVerbosity && CHECK_BIT(mDebugLevel, DebugLevel::RDHDump)) { //std::cout << "Packet " << std::setw(5) << currentPacket << " - Link " << int(linkID) << "\n"; //std::cout << rdh; printHorizontal(rdh); @@ -443,7 +443,7 @@ void RawReaderCRU::findSyncPositions() // TODO: In future there might be more then one sync in the stream // this should be takein into account if (syncFoundForLink(link)) { - if (CHECK_BIT(mDebugLevel, DebugLevel::SyncPositions)) { + if (mVerbosity && CHECK_BIT(mDebugLevel, DebugLevel::SyncPositions)) { std::cout << "Sync positions for link " << link << '\n'; const auto& syncs = mSyncPositions[link]; for (int i = 0; i < syncs.size(); ++i) { @@ -481,12 +481,12 @@ int RawReaderCRU::processPacket(GBTFrame& gFrame, uint32_t startPos, uint32_t si gFrame.getFrameHalfWords(); // debug output - if (CHECK_BIT(mDebugLevel, DebugLevel::GBTFrames)) { + if (mVerbosity && CHECK_BIT(mDebugLevel, DebugLevel::GBTFrames)) { std::cout << gFrame; } gFrame.getAdcValues(rawData); - gFrame.updateSyncCheck(CHECK_BIT(mDebugLevel, DebugLevel::SyncPositions)); + gFrame.updateSyncCheck(mVerbosity && CHECK_BIT(mDebugLevel, DebugLevel::SyncPositions)); if (!(rawData.getNumTimebins() % 16) && (rawData.getNumTimebins() >= mNumTimeBins * 16)) { return 1; } @@ -498,6 +498,8 @@ int RawReaderCRU::processMemory(const std::vector<o2::byte>& data, ADCRawData& r { GBTFrame gFrame; + const bool dumpSyncPositoins = CHECK_BIT(mDebugLevel, DebugLevel::SyncPositions); + // 16 bytes is the size of a GBT frame for (int iFrame = 0; iFrame < data.size() / 16; ++iFrame) { gFrame.setFrameNumber(iFrame); @@ -514,16 +516,35 @@ int RawReaderCRU::processMemory(const std::vector<o2::byte>& data, ADCRawData& r gFrame.getFrameHalfWords(); // debug output - if (CHECK_BIT(mDebugLevel, DebugLevel::GBTFrames)) { + if (mVerbosity && CHECK_BIT(mDebugLevel, DebugLevel::GBTFrames)) { std::cout << gFrame; } gFrame.getAdcValues(rawData); - gFrame.updateSyncCheck(CHECK_BIT(mDebugLevel, DebugLevel::SyncPositions)); + gFrame.updateSyncCheck(mVerbosity && dumpSyncPositoins); if (!(rawData.getNumTimebins() % 16) && (rawData.getNumTimebins() >= mNumTimeBins * 16)) { - return 1; + break; } }; + + if (mDumpTextFiles && dumpSyncPositoins) { + const auto fileName = mOutputFilePrefix + "/LinkPositions.txt"; + std::ofstream file(fileName, std::ofstream::app); + auto& syncPositions = gFrame.getSyncArray(); + + for (int s = 0; s < 5; ++s) { + auto& syncPos = syncPositions[s]; + if (syncPos.synched()) { + file << mEventNumber << "\t" + << mCRU << "\t" + << mLink << "\t" + << s << "\t" + << syncPos.getPacketNumber() << "\t" + << syncPos.getFrameNumber() << "\t" + << syncPos.getHalfWordPosition() << "\n"; + } + } + } return 0; } @@ -646,13 +667,13 @@ int RawReaderCRU::processDataFile() std::string fileName; for (int s = 0; s < 5; s++) { if (mStream == 0x0 or ((mStream >> s) & 0x1) == 0x1) { - if (gFrame.mSyncFound(s) == false) { + if (gFrame.syncFound(s) == false) { std::cout << "No sync found" << std::endl; } // debug output rawData.setOutputStream(s); rawData.setNumTimebins(mNumTimeBins); - if (CHECK_BIT(mDebugLevel, DebugLevel::ADCValues)) { + if (mVerbosity && CHECK_BIT(mDebugLevel, DebugLevel::ADCValues)) { std::cout << rawData << std::endl; }; // write the data to file @@ -787,14 +808,39 @@ void RawReaderCRU::processFile(const std::string_view inputFile, uint32_t timeBi // Instantiate the RawReaderCRU RawReaderCRUManager cruManager; cruManager.setDebugLevel(debugLevel); - RawReaderCRU& rawReaderCRU = cruManager.createReader(inputFile, timeBins, 0, stream, debugLevel, verbosity, outputFilePrefix); + //RawReaderCRU& rawReaderCRU = cruManager.createReader(inputFile, timeBins, 0, stream, debugLevel, verbosity, outputFilePrefix); + cruManager.setupReaders(inputFile, timeBins, debugLevel, verbosity, outputFilePrefix); + for (auto& reader : cruManager.getReaders()) { + reader->mDumpTextFiles = true; + reader->mFillADCdataMap = false; + } cruManager.init(); - rawReaderCRU.mDumpTextFiles = true; - rawReaderCRU.mFillADCdataMap = false; - for (int ievent = 0; ievent < rawReaderCRU.getNumberOfEvents(); ++ievent) { + + if (CHECK_BIT(debugLevel, DebugLevel::SyncPositions)) { + std::string outPrefix = outputFilePrefix.length() ? outputFilePrefix.data() : "./"; + const auto fileName = outPrefix + "/LinkPositions.txt"; + std::ofstream file(fileName, std::ofstream::out); + file << "EventNumber/I" + << ":" + << "CRU" + << ":" + << "Link" + << ":" + << "Stream" + << ":" + << "PacketNumber" + << ":" + << "FrameNumber" + << ":" + << "HalfWordPosition" + << "\n"; + file.close(); + } + + for (int ievent = 0; ievent < cruManager.getNumberOfEvents(); ++ievent) { fmt::print("=============| event {: 5d} |===============\n", ievent); - rawReaderCRU.setEventNumber(ievent); - rawReaderCRU.processLinks(linkMask); + + cruManager.processEvent(ievent); } } @@ -1081,6 +1127,7 @@ void RawReaderCRUManager::setupReaders(const std::string_view inputFileNames, reader.setReaderNumber(mRawReadersCRU.size() - 1); reader.setVerbosity(verbosity); reader.setDebugLevel(debugLevel); + reader.setOutputFilePrefix(outputFilePrefix); O2INFO("Adding file: %s\n", file->GetName()); } } From bafe874edbffcb5c73e1fe8a0403203b4c5b446d Mon Sep 17 00:00:00 2001 From: wiechula <Jens.Wiechula@cern.ch> Date: Mon, 14 Dec 2020 10:32:28 +0100 Subject: [PATCH 1630/1751] Add switch to skip incomplete events, by default process all --- .../include/TPCCalibration/CalibRawBase.h | 3 +++ Detectors/TPC/calibration/macro/runPedestal.C | 18 ++++++++---------- Detectors/TPC/calibration/macro/runPedestal.sh | 6 ++++-- Detectors/TPC/calibration/src/CalibRawBase.cxx | 1 + 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h index 0639335c88bd1..a1f84dee74fc4 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h @@ -129,6 +129,9 @@ class CalibRawBase /// get present event number size_t getPresentEventNumber() const { return mPresentEventNumber; } + /// return number of events + int getNumberOfEvents() const { return mRawReaderCRUManager.getNumberOfEvents(); } + /// check if present event is complete bool isPresentEventComplete() const { return mRawReaderCRUManager.isEventComplete(mPresentEventNumber); } diff --git a/Detectors/TPC/calibration/macro/runPedestal.C b/Detectors/TPC/calibration/macro/runPedestal.C index 80261d0936d0f..47d131b94c62c 100644 --- a/Detectors/TPC/calibration/macro/runPedestal.C +++ b/Detectors/TPC/calibration/macro/runPedestal.C @@ -19,13 +19,14 @@ #include "TPCCalibration/CalibRawBase.h" #endif -void runPedestal(std::vector<std::string_view> fileInfos, TString outputFileName = "", Int_t nevents = 100, Int_t adcMin = 0, Int_t adcMax = 1100, Int_t firstTimeBin = 0, Int_t lastTimeBin = 450, Int_t statisticsType = 0, uint32_t verbosity = 0, uint32_t debugLevel = 0, Int_t firstEvent = 0, Bool_t debugOutput = false) +void runPedestal(std::vector<std::string_view> fileInfos, TString outputFileName = "", Int_t nevents = 100, Int_t adcMin = 0, Int_t adcMax = 1100, Int_t firstTimeBin = 0, Int_t lastTimeBin = 450, Int_t statisticsType = 0, uint32_t verbosity = 0, uint32_t debugLevel = 0, Int_t firstEvent = 0, Bool_t debugOutput = false, Bool_t skipIncomplete = false) { using namespace o2::tpc; CalibPedestal ped; //(PadSubset::Region); ped.setADCRange(adcMin, adcMax); ped.setStatisticsType(StatisticsType(statisticsType)); ped.setTimeBinRange(firstTimeBin, lastTimeBin); + ped.setSkipIncompleteEvents(skipIncomplete); //ped.processEvent(); //ped.resetData(); @@ -35,14 +36,13 @@ void runPedestal(std::vector<std::string_view> fileInfos, TString outputFileName for (const auto& fileInfo : fileInfos) { ped.setupContainers(fileInfo.data(), verbosity, debugLevel); - for (Int_t i = firstEvent; i < firstEvent + nevents; ++i) { + const int neventsFile = ped.getNumberOfEvents(); + printf("number of events in files: %d\n", neventsFile); + int lastEvent = std::min(neventsFile, firstEvent + nevents); + + for (Int_t i = firstEvent; i < lastEvent; ++i) { status = ped.processEvent(i); std::cout << "Processing event " << i << " with status " << int(status) << '\n'; - if (status == CalibRawBase::ProcessStatus::IncompleteEvent) { - continue; - } else if (status != CalibRawBase::ProcessStatus::Ok) { - break; - } } } ped.analyse(); @@ -61,7 +61,6 @@ void runPedestal(std::vector<std::string_view> fileInfos, TString outputFileName debugFile.Append("/"); debugFile.Append("pedestals_debug.root"); TFile f(debugFile, "recreate"); - TObjArray arr(72); for (int i = 0; i < 72; ++i) { const auto& rocPedestal = calibPedestal.getCalArray(i); @@ -70,9 +69,8 @@ void runPedestal(std::vector<std::string_view> fileInfos, TString outputFileName } auto ch = ped.createControlHistogram(ROC(i)); - arr.Add(static_cast<TObject*>(ch)); + ch->Write(); } - arr.Write("histos", TObject::kSingleKey); f.Write(); } std::cout << "To display the pedestals run: root.exe $calibMacroDir/drawNoiseAndPedestal.C'(\"" << outputFileName << "\")'\n"; diff --git a/Detectors/TPC/calibration/macro/runPedestal.sh b/Detectors/TPC/calibration/macro/runPedestal.sh index bb246245d4ade..a36bb53a60d11 100755 --- a/Detectors/TPC/calibration/macro/runPedestal.sh +++ b/Detectors/TPC/calibration/macro/runPedestal.sh @@ -44,12 +44,13 @@ statisticsType=0 verbosity=0 debugLevel=0 writeDebug=0 +skipIncomplete=0 adcMin=0 adcMax=1100 # ===| parse command line options |============================================= -OPTIONS=$(getopt -l "fileInfo:,outputFile:,firstTimeBin:,lastTimeBin:,nevents:,adcMin:,adcMax:,statType:,verbosity:,debugLevel:,writeDebug,help" -o "i:o:t:f:l:n:m:x:s:v:d:wh" -n "runPedestal.sh" -- "$@") +OPTIONS=$(getopt -l "fileInfo:,outputFile:,firstTimeBin:,lastTimeBin:,nevents:,skipIncomplete,adcMin:,adcMax:,statType:,verbosity:,debugLevel:,writeDebug,help" -o "i:o:t:f:l:n:km:x:s:v:d:wh" -n "runPedestal.sh" -- "$@") if [ $? != 0 ] ; then usageAndExit @@ -65,6 +66,7 @@ while true; do -f|--firstTimeBin) firstTimeBin=$2; shift 2;; -l|--lastTimeBin) lastTimeBin=$2; shift 2;; -n|--nevents) nevents=$2; shift 2;; + -k|--skipIncomplete) skipIncomplete=1; shift;; -m|--adcMin) adcMin=$2; shift 2;; -x|--adcMax) adcMax=$2; shift 2;; -s|--statType) statisticsType=$2; shift 2;; @@ -96,6 +98,6 @@ fileInfo=$(echo $fileInfo | sed "s|^|{\"|;s|,|:$lastTimeBin\",\"|g;s|$|\"}|") cmd="" #cmd="valgrind --tool=callgrind --dump-instr=yes --dump-instr=yes" #cmd="perf record -g -o perf.log" -cmd="$cmd root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPedestal.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, $statisticsType, $verbosity, $debugLevel, 0, $writeDebug)'" +cmd="$cmd root.exe -b -q -l -n -x $O2_SRC/Detectors/TPC/calibration/macro/runPedestal.C'($fileInfo,\"$outputFile\", $nevents, $adcMin, $adcMax, $firstTimeBin, $lastTimeBin, $statisticsType, $verbosity, $debugLevel, 0, $writeDebug, $skipIncomplete)'" echo "running: $cmd" eval $cmd diff --git a/Detectors/TPC/calibration/src/CalibRawBase.cxx b/Detectors/TPC/calibration/src/CalibRawBase.cxx index a414cbf1f4934..79328a2110cfd 100644 --- a/Detectors/TPC/calibration/src/CalibRawBase.cxx +++ b/Detectors/TPC/calibration/src/CalibRawBase.cxx @@ -87,6 +87,7 @@ void CalibRawBase::setupContainers(TString fileInfo, uint32_t verbosity, uint32_ printf("Forcing CRU %03d\n", cru); } } + mRawReaderCRUManager.init(); } else if (rorcType == "digits") { TString files = gSystem->GetFromPipe(TString::Format("ls %s", arrDataInfo->At(0)->GetName())); //const int timeBins = static_cast<TObjString*>(arrDataInfo->At(1))->String().Atoi(); From 46995d6fa40cf9336dff0e675e82160e6741ab9b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 14 Dec 2020 17:17:34 +0100 Subject: [PATCH 1631/1751] DPL: push metric with name of the file read --- Framework/Core/src/AODReaderHelpers.cxx | 6 ++++++ Framework/Core/src/runDataProcessing.cxx | 1 + 2 files changed, 7 insertions(+) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 653cd01dbbb24..a563578485fd9 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -326,6 +326,12 @@ AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() t2t.fill(tr); if (info.file) { totalReadCalls += info.file->GetReadCalls() - before; + static std::string currentFileRead = ""; + std::string nextFileRead = info.file->GetPath(); + if (currentFileRead != nextFileRead) { + currentFileRead = nextFileRead; + monitoring.send(Metric{currentFileRead, "aod-file-read-path"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + } } monitoring.send(Metric{(double)ps.GetReadCalls(), "aod-tree-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); delete tr; diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index d6952d3480f7b..1c3b8583b5838 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1300,6 +1300,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, performanceMetrics.push_back("aod-bytes-read-uncompressed"); performanceMetrics.push_back("aod-bytes-read-compressed"); performanceMetrics.push_back("aod-total-read-calls"); + performanceMetrics.push_back("aod-file-read-path"); ResourcesMonitoringHelper::dumpMetricsToJSON(metricsInfos, driverInfo.metrics, deviceSpecs, performanceMetrics); } // This is a clean exit. Before we do so, if required, From 00d2046da98c9b52953c2aa864f4d103d884f467 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 14 Dec 2020 17:17:50 +0100 Subject: [PATCH 1632/1751] DPL: refactor internal details of ResourcesMonitoringHelper No need to expose getter / setters to the outside. --- .../Core/src/ResourcesMonitoringHelper.cxx | 32 +++++++++++++++++ .../Core/src/ResourcesMonitoringHelper.h | 34 ------------------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/Framework/Core/src/ResourcesMonitoringHelper.cxx b/Framework/Core/src/ResourcesMonitoringHelper.cxx index 8aa1600d2eac9..0b6ed333052af 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.cxx +++ b/Framework/Core/src/ResourcesMonitoringHelper.cxx @@ -18,6 +18,38 @@ using namespace o2::framework; +template <typename T> +inline static T retriveValue(T val) +{ + return val; +} + +inline static std::string retriveValue(const std::reference_wrapper<const StringMetric> val) +{ + return std::string(val.get().data); +} + +template <typename T> +boost::property_tree::ptree fillNodeWithValue(const DeviceMetricsInfo& deviceMetrics, + const T& metricsStorage, size_t labelIndex, size_t storageIndex) +{ + + unsigned int loopRange = std::min(deviceMetrics.metrics[labelIndex].filledMetrics, metricsStorage[storageIndex].size()); + boost::property_tree::ptree metricNode; + + for (unsigned int idx = 0; idx < loopRange; ++idx) { + boost::property_tree::ptree values; + values.add("timestamp", deviceMetrics.timestamps[labelIndex][idx]); + if constexpr (std::is_arithmetic_v<T>) { + values.add("value", std::to_string(retriveValue(std::cref(metricsStorage[storageIndex][idx])))); + } else { + values.add("value", retriveValue(std::cref(metricsStorage[storageIndex][idx]))); + } + metricNode.push_back(std::make_pair("", values)); + } + return metricNode; +} + bool ResourcesMonitoringHelper::dumpMetricsToJSON(const std::vector<DeviceMetricsInfo>& metrics, const DeviceMetricsInfo& driverMetrics, const std::vector<DeviceSpec>& specs, diff --git a/Framework/Core/src/ResourcesMonitoringHelper.h b/Framework/Core/src/ResourcesMonitoringHelper.h index 35352fc0eef13..791c475b31d7d 100644 --- a/Framework/Core/src/ResourcesMonitoringHelper.h +++ b/Framework/Core/src/ResourcesMonitoringHelper.h @@ -30,42 +30,8 @@ struct ResourcesMonitoringHelper { std::vector<DeviceSpec> const& specs, std::vector<std::string> const& metricsToDump) noexcept; static bool isResourcesMonitoringEnabled(unsigned short interval) noexcept { return interval > 0; } - - template <typename T> - static boost::property_tree::ptree fillNodeWithValue(const DeviceMetricsInfo& deviceMetrics, - const T& metricsStorage, size_t labelIndex, size_t storageIndex); - - template <typename T> - inline static T retriveValue(T val) - { - return val; - } - inline static std::string retriveValue(const std::reference_wrapper<const StringMetric> val) - { - return std::string(val.get().data); - } }; -template <typename T> -boost::property_tree::ptree ResourcesMonitoringHelper::fillNodeWithValue(const DeviceMetricsInfo& deviceMetrics, - const T& metricsStorage, size_t labelIndex, size_t storageIndex) -{ - - unsigned int loopRange = std::min(deviceMetrics.metrics[labelIndex].filledMetrics, metricsStorage[storageIndex].size()); - boost::property_tree::ptree metricNode; - - for (unsigned int idx = 0; idx < loopRange; ++idx) { - boost::property_tree::ptree values; - values.add("timestamp", deviceMetrics.timestamps[labelIndex][idx]); - if constexpr (std::is_arithmetic_v<T>) { - values.add("value", std::to_string(retriveValue(std::cref(metricsStorage[storageIndex][idx])))); - } else { - values.add("value", retriveValue(std::cref(metricsStorage[storageIndex][idx]))); - } - metricNode.push_back(std::make_pair("", values)); - } - return metricNode; -} } // namespace o2::framework From 2d711f49875c7a5d7f491ebcc1bb927856c81636 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 14 Dec 2020 22:42:12 +0100 Subject: [PATCH 1633/1751] DPL Analysis: add string array Configurable (#5063) --- .../include/Analysis/configurableCut.h | 8 +++++-- Analysis/Tutorials/src/configurableCut.cxx | 10 ++++++++ .../Tutorials/src/configurableObjects.cxx | 1 + .../include/Framework/ConfigParamsHelper.h | 3 ++- Framework/Core/include/Framework/Variant.h | 20 ++++++++++++++++ Framework/Core/src/BoostOptionsRetriever.cxx | 7 +++--- Framework/Core/src/ConfigParamsHelper.cxx | 3 +++ Framework/Core/src/PropertyTreeHelpers.cxx | 24 +++++++++++++++++++ Framework/Core/src/RootConfigParamHelpers.cxx | 12 ++++++++-- Framework/Core/src/Variant.cxx | 3 +++ Framework/Core/test/test_Variants.cxx | 24 +++++++++++++++++++ 11 files changed, 107 insertions(+), 8 deletions(-) diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h index 0e9deef256856..446db71958217 100644 --- a/Analysis/Tutorials/include/Analysis/configurableCut.h +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -18,8 +18,8 @@ class configurableCut { public: - configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true, std::vector<float> bins_ = {0.5, 1.5, 2.5}) - : cut{cut_}, state{state_}, option{option_}, bins{bins_} + configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true, std::vector<float> bins_ = {0.5, 1.5, 2.5}, std::vector<std::string> labels_ = {"l1", "l2", "l3"}) + : cut{cut_}, state{state_}, option{option_}, bins{bins_}, labels{labels_} { } @@ -37,11 +37,15 @@ class configurableCut void setBins(std::vector<float> bins_); std::vector<float> getBins() const; + void setLabels(std::vector<std::string> labels_); + std::vector<std::string> getLabels() const; + private: float cut; int state; bool option; std::vector<float> bins; + std::vector<std::string> labels; ClassDef(configurableCut, 4); }; diff --git a/Analysis/Tutorials/src/configurableCut.cxx b/Analysis/Tutorials/src/configurableCut.cxx index c43b34293e178..eac596e038de1 100644 --- a/Analysis/Tutorials/src/configurableCut.cxx +++ b/Analysis/Tutorials/src/configurableCut.cxx @@ -60,3 +60,13 @@ std::vector<float> configurableCut::getBins() const { return bins; }; + +void configurableCut::setLabels(std::vector<std::string> labels_) +{ + labels = labels_; +} + +std::vector<std::string> configurableCut::getLabels() const +{ + return labels; +} diff --git a/Analysis/Tutorials/src/configurableObjects.cxx b/Analysis/Tutorials/src/configurableObjects.cxx index 6058336feca4e..bc99060e065d5 100644 --- a/Analysis/Tutorials/src/configurableObjects.cxx +++ b/Analysis/Tutorials/src/configurableObjects.cxx @@ -50,6 +50,7 @@ struct ConfigurableObjectDemo { { LOGF(INFO, "Cut1: %.3f; Cut2: %.3f", cut, mutable_cut); LOGF(INFO, "Cut1 bins: %s; Cut2 bins: %s", printArray(cut->getBins()), printArray(mutable_cut->getBins())); + LOGF(INFO, "Cut1 labels: %s; Cut2 labels: %s", printArray(cut->getLabels()), printArray(mutable_cut->getLabels())); auto vec = (std::vector<int>)array; LOGF(INFO, "Array: %s", printArray(vec).c_str()); for (auto& track : tracks) { diff --git a/Framework/Core/include/Framework/ConfigParamsHelper.h b/Framework/Core/include/Framework/ConfigParamsHelper.h index b48fb0291b1e1..02b9c9a56a4c3 100644 --- a/Framework/Core/include/Framework/ConfigParamsHelper.h +++ b/Framework/Core/include/Framework/ConfigParamsHelper.h @@ -118,7 +118,8 @@ struct ConfigParamsHelper { } else if constexpr (V == VariantType::ArrayInt || V == VariantType::ArrayFloat || V == VariantType::ArrayDouble || - V == VariantType::ArrayBool) { + V == VariantType::ArrayBool || + V == VariantType::ArrayString) { auto value = boost::program_options::value<std::string>(); value = value->default_value(spec.defaultValue.asString()); if constexpr (V != VariantType::String) { diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index 7622ef09571c9..20f711987d505 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -36,6 +36,7 @@ enum class VariantType : int { Int = 0, ArrayFloat, ArrayDouble, ArrayBool, + ArrayString, Empty, Unknown }; @@ -66,11 +67,13 @@ DECLARE_VARIANT_TRAIT(int*, ArrayInt); DECLARE_VARIANT_TRAIT(float*, ArrayFloat); DECLARE_VARIANT_TRAIT(double*, ArrayDouble); DECLARE_VARIANT_TRAIT(bool*, ArrayBool); +DECLARE_VARIANT_TRAIT(std::string*, ArrayString); DECLARE_VARIANT_TRAIT(std::vector<int>, ArrayInt); DECLARE_VARIANT_TRAIT(std::vector<float>, ArrayFloat); DECLARE_VARIANT_TRAIT(std::vector<double>, ArrayDouble); DECLARE_VARIANT_TRAIT(std::vector<bool>, ArrayBool); +DECLARE_VARIANT_TRAIT(std::vector<std::string>, ArrayString); template <typename T> struct variant_array_symbol { @@ -97,6 +100,11 @@ struct variant_array_symbol<bool> { constexpr static char symbol = 'b'; }; +template <> +struct variant_array_symbol<std::string> { + constexpr static char symbol = 's'; +}; + template <typename T> inline constexpr VariantType variant_trait_v = variant_trait<T>::value; @@ -121,6 +129,7 @@ DECLARE_VARIANT_TYPE(int*, ArrayInt); DECLARE_VARIANT_TYPE(float*, ArrayFloat); DECLARE_VARIANT_TYPE(double*, ArrayDouble); DECLARE_VARIANT_TYPE(bool*, ArrayBool); +DECLARE_VARIANT_TYPE(std::string*, ArrayString); template <typename S, typename T> struct variant_helper { @@ -217,6 +226,10 @@ class Variant mSize = other.mSize; variant_helper<storage_t, bool*>::set(&mStore, other.get<bool*>(), mSize); return; + case variant_trait_v<std::string*>: + mSize = other.mSize; + variant_helper<storage_t, std::string*>::set(&mStore, other.get<std::string*>(), mSize); + return; default: mStore = other.mStore; mSize = other.mSize; @@ -243,6 +256,8 @@ class Variant case variant_trait_v<bool*>: *reinterpret_cast<bool**>(&(other.mStore)) = nullptr; return; + case variant_trait_v<std::string*>: + *reinterpret_cast<std::string**>(&(other.mStore)) = nullptr; default: return; } @@ -258,6 +273,7 @@ class Variant case variant_trait_v<float*>: case variant_trait_v<double*>: case variant_trait_v<bool*>: + case variant_trait_v<std::string*>: if (reinterpret_cast<void**>(&mStore) != nullptr) { free(*reinterpret_cast<void**>(&mStore)); } @@ -290,6 +306,10 @@ class Variant mSize = other.mSize; variant_helper<storage_t, bool*>::set(&mStore, other.get<bool*>(), mSize); return; + case variant_trait_v<std::string*>: + mSize = other.mSize; + variant_helper<storage_t, std::string*>::set(&mStore, other.get<std::string*>(), mSize); + return; default: mStore = other.mStore; mSize = other.mSize; diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index b966c48098511..efe4f85e933fe 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -30,9 +30,9 @@ namespace o2::framework BoostOptionsRetriever::BoostOptionsRetriever(bool ignoreUnknown, int argc, char** argv) : mDescription{std::make_unique<boost::program_options::options_description>("ALICE O2 Framework - Available options")}, - mIgnoreUnknown{ignoreUnknown}, mArgc{argc}, - mArgv{argv} + mArgv{argv}, + mIgnoreUnknown{ignoreUnknown} { } @@ -68,7 +68,8 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> const& specs, case VariantType::ArrayFloat: case VariantType::ArrayDouble: case VariantType::ArrayBool: - options = options(name, bpo::value<std::string>()->default_value(spec.defaultValue.asString(), help)); + case VariantType::ArrayString: + options = options(name, bpo::value<std::string>()->default_value(spec.defaultValue.asString()), help); break; case VariantType::Unknown: case VariantType::Empty: diff --git a/Framework/Core/src/ConfigParamsHelper.cxx b/Framework/Core/src/ConfigParamsHelper.cxx index 225505734bd4b..a6c29c35e5f9f 100644 --- a/Framework/Core/src/ConfigParamsHelper.cxx +++ b/Framework/Core/src/ConfigParamsHelper.cxx @@ -69,6 +69,9 @@ void ConfigParamsHelper::populateBoostProgramOptions( case VariantType::ArrayBool: addConfigSpecOption<VariantType::ArrayBool>(spec, options); break; + case VariantType::ArrayString: + addConfigSpecOption<VariantType::ArrayString>(spec, options); + break; case VariantType::Unknown: case VariantType::Empty: break; diff --git a/Framework/Core/src/PropertyTreeHelpers.cxx b/Framework/Core/src/PropertyTreeHelpers.cxx index 71b8e0fc10303..0860744dd55dd 100644 --- a/Framework/Core/src/PropertyTreeHelpers.cxx +++ b/Framework/Core/src/PropertyTreeHelpers.cxx @@ -74,6 +74,9 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s case VariantType::ArrayBool: addBranch(key, spec.defaultValue.get<bool*>(), spec.defaultValue.size()); break; + case VariantType::ArrayString: + addBranch(key, spec.defaultValue.get<std::string*>(), spec.defaultValue.size()); + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -106,6 +109,21 @@ std::vector<T> toVector(std::string const& input) } return result; } + +template <> +std::vector<std::string> toVector(std::string const& input) +{ + std::vector<std::string> result; + //check if the array string has correct array type symbol + assert(input[0] == variant_array_symbol<std::string>::symbol); + std::regex smatch(R"((?:(?!=,)|(?!=\[))\w+(?=,|\]))"); + auto end = std::sregex_iterator(); + auto values = std::sregex_iterator(input.begin(), input.end(), smatch); + for (auto v = values; v != end; ++v) { + result.push_back(v->str()); + } + return result; +} } // namespace void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, @@ -171,6 +189,11 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, addBranch(key, v); }; break; + case VariantType::ArrayString: { + auto v = toVector<std::string>(vmap[key].as<std::string>()); + addBranch(key, v); + }; + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -224,6 +247,7 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, case VariantType::ArrayFloat: case VariantType::ArrayDouble: case VariantType::ArrayBool: + case VariantType::ArrayString: pt.put_child(key, *it); break; case VariantType::Unknown: diff --git a/Framework/Core/src/RootConfigParamHelpers.cxx b/Framework/Core/src/RootConfigParamHelpers.cxx index 81b6851fd283f..c73c594782c2b 100644 --- a/Framework/Core/src/RootConfigParamHelpers.cxx +++ b/Framework/Core/src/RootConfigParamHelpers.cxx @@ -115,8 +115,13 @@ void ptreeToMember(boost::property_tree::ptree const& value, *static_cast<std::vector<double>*>(ptr) = extractVector<double>(value); return; case compile_time_hash("vector<bool>"): + throw std::runtime_error("Bool arrays are not implemented yet"); + case compile_time_hash("vector<std::string>"): + case compile_time_hash("vector<string>"): + *static_cast<std::vector<std::string>*>(ptr) = extractVector<std::string>(value); + return; default: - throw std::runtime_error("Not and int/float/double/bool vector"); + throw std::runtime_error("Not an int/float/double/bool vector"); } } auto dt = dm->GetDataType(); @@ -205,8 +210,11 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void case compile_time_hash("vector<bool>"): throw std::runtime_error("bool vector not supported yet"); // return ConfigParamSpec{tname, VariantType::ArrayBool, *static_cast<std::vector<bool>*>(ptr), {"No help"}}; + case compile_time_hash("vector<std::string>"): + case compile_time_hash("vector<string>"): + return ConfigParamSpec{tname, VariantType::ArrayString, *static_cast<std::vector<std::string>*>(ptr), {"No help"}}; default: - throw std::runtime_error("Not and int/float/double/bool vector"); + throw std::runtime_error("Not an int/float/double/bool vector"); } } auto dt = dm->GetDataType(); diff --git a/Framework/Core/src/Variant.cxx b/Framework/Core/src/Variant.cxx index c1f9708bed46b..5f9c60217ffb0 100644 --- a/Framework/Core/src/Variant.cxx +++ b/Framework/Core/src/Variant.cxx @@ -63,6 +63,9 @@ std::ostream& operator<<(std::ostream& oss, Variant const& val) case VariantType::ArrayBool: printArray<bool>(oss, val.get<bool*>(), val.size()); break; + case VariantType::ArrayString: + printArray<std::string>(oss, val.get<std::string*>(), val.size()); + break; case VariantType::Empty: break; default: diff --git a/Framework/Core/test/test_Variants.cxx b/Framework/Core/test/test_Variants.cxx index 0b34a853f8713..11a42487c759b 100644 --- a/Framework/Core/test/test_Variants.cxx +++ b/Framework/Core/test/test_Variants.cxx @@ -105,4 +105,28 @@ BOOST_AUTO_TEST_CASE(VariantTest) for (auto i = 0u; i < fd.size(); ++i) { BOOST_CHECK(farr[i] == (fd.get<float*>())[i]); } + + std::vector<std::string> vstrings{"s1", "s2", "s3"}; + std::string strings[] = {"l1", "l2", "l3"}; + Variant vstr(strings, 3); + Variant vvstr(vstrings); + + BOOST_CHECK(vstr.size() == 3); + BOOST_CHECK(vvstr.size() == 3); + for (auto i = 0u; i < vstr.size(); ++i) { + BOOST_CHECK(strings[i] == (vstr.get<std::string*>())[i]); + } + for (auto i = 0u; i < vvstr.size(); ++i) { + BOOST_CHECK(vstrings[i] == (vvstr.get<std::string*>())[i]); + } + + Variant vsc(vstr); // Copy constructor + Variant vsm(std::move(vstr)); // Move constructor + Variant vscc = vsm; // Copy assignment + for (auto i = 0u; i < vsm.size(); ++i) { + BOOST_CHECK(strings[i] == (vsm.get<std::string*>())[i]); + } + for (auto i = 0u; i < vscc.size(); ++i) { + BOOST_CHECK(strings[i] == (vscc.get<std::string*>())[i]); + } } From 84edc8cf6428fb5e6e7f236bebba29db2b364a0d Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Mon, 14 Dec 2020 22:43:12 +0100 Subject: [PATCH 1634/1751] Using histogram registry fill (#5064) --- Analysis/Tasks/PWGCF/correlations.cxx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Analysis/Tasks/PWGCF/correlations.cxx b/Analysis/Tasks/PWGCF/correlations.cxx index af928954017ae..93c47963c9187 100644 --- a/Analysis/Tasks/PWGCF/correlations.cxx +++ b/Analysis/Tasks/PWGCF/correlations.cxx @@ -176,15 +176,11 @@ struct CorrelationTask { } } - // NOTE remove when HistogramRegistry uses constexpr strings for lookup - auto& yields = registry.get<TH3>(HIST("yields")); - auto& etaphi = registry.get<TH3>(HIST("etaphi")); - for (auto& track1 : tracks) { // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); - yields->Fill(centrality, track1.pt(), track1.eta()); - etaphi->Fill(centrality, track1.eta(), track1.phi()); + registry.fill(HIST("yields"), centrality, track1.pt(), track1.eta()); + registry.fill(HIST("etaphi"), centrality, track1.eta(), track1.phi()); if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.charge() < 0) { continue; From 91bc67a4efc06e824d1270d93e660dcddf58b5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= <mkrueger@ikf.uni-frankfurt.de> Date: Tue, 15 Dec 2020 09:48:18 +0100 Subject: [PATCH 1635/1751] Analysis: extend histogram registry example (#5066) --- Analysis/Tutorials/src/histogramRegistry.cxx | 21 ++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Analysis/Tutorials/src/histogramRegistry.cxx b/Analysis/Tutorials/src/histogramRegistry.cxx index 8a68e9b93be6e..fa79c947733d6 100644 --- a/Analysis/Tutorials/src/histogramRegistry.cxx +++ b/Analysis/Tutorials/src/histogramRegistry.cxx @@ -162,8 +162,6 @@ struct DTask { spectra.add("before_cuts/hist1", "asdf", defaultParticleHist); spectra.add("before_cuts/hist2", "asdf", defaultParticleHist); spectra.add("before_cuts/hist3", "asdf", defaultParticleHist); - spectra.add("before_cuts/hist4", "asdf", defaultParticleHist); - spectra.add("before_cuts/hist5", "asdf", defaultParticleHist); // clone whole category / group spectra.addClone("before_cuts/", "after_cuts/"); @@ -173,6 +171,16 @@ struct DTask { spectra.addClone("neutral/pions", "strange/funny/particles"); } + template <bool mode, typename T> + void fillHistos(const T& track) + { + static constexpr std::string_view subDir[] = {"before_cuts/", "after_cuts/"}; + + spectra.fill(HIST(subDir[mode]) + HIST("hist1"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST(subDir[mode]) + HIST("hist2"), track.pt(), track.eta(), 50., 0.); + spectra.fill(HIST(subDir[mode]) + HIST("hist3"), track.pt(), track.eta(), 50., 0.); + } + void process(aod::Tracks const& tracks) { using namespace aod::track; @@ -189,10 +197,11 @@ struct DTask { spectra.fill(HIST("sigmas"), track.pt(), track.eta(), 50., 0.); spectra.fill(HIST("lambdas"), track.pt(), track.eta(), 50., 0.); - spectra.fill(HIST("before_cuts/hist2"), track.pt(), track.eta(), 50., 0.); - spectra.fill(HIST("before_cuts/hist2"), track.pt(), track.eta(), 50., 0.); - - spectra.fill(HIST("after_cuts/hist2"), track.pt(), track.eta(), 50., 0.); + // fill histograms before and after cuts + fillHistos<false>(track); + if (std::rand() > (RAND_MAX / 2)) { + fillHistos<true>(track); + } spectra.fill(HIST("cascades"), track.pt(), track.eta(), 50., 0.); spectra.fill(HIST("strange/funny/particles"), track.pt(), track.eta(), 50., 0.); From 90f87c485206acdfc6fa6a6de2d5848df88651dd Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 15 Dec 2020 14:33:34 +0100 Subject: [PATCH 1636/1751] Increase the margin of CTF block size to 10KB --- .../Common/include/DetectorsCommonDataFormats/EncodedBlocks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h index db9e0666e2866..1a5c97a25b7e6 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h @@ -775,7 +775,7 @@ void EncodedBlocks<H, N, W>::encode(const S_IT srcBegin, // iterator begin o // case 3: message where entropy coding should be applied if (opt == Metadata::OptStore::EENCODE) { // build symbol statistics - constexpr size_t SizeEstMargin = 1024; + constexpr size_t SizeEstMargin = 10 * 1024; const o2::rans::LiteralEncoder64<STYP>* encoder = reinterpret_cast<const o2::rans::LiteralEncoder64<STYP>*>(encoderExt); std::unique_ptr<o2::rans::LiteralEncoder64<STYP>> encoderLoc; std::unique_ptr<o2::rans::FrequencyTable> frequencies = nullptr; From 8b00c138513cbb05fb31d50825f053be5b0f121c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Kr=C3=BCger?= <mkrueger@ikf.uni-frankfurt.de> Date: Tue, 15 Dec 2020 22:49:39 +0100 Subject: [PATCH 1637/1751] DPL Analysis: make sure each name hash in histogram registry is unique (#5068) --- .../include/Framework/HistogramRegistry.h | 3 ++ Framework/Core/src/HistogramRegistry.cxx | 31 ++++++++++++++----- .../Core/test/test_HistogramRegistry.cxx | 16 ++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 549313ee345cd..d201c5d6f6d5f 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -615,6 +615,7 @@ class HistogramRegistry template <typename T> void insertClone(const HistName& histName, const std::shared_ptr<T>& originalHist) { + validateHash(histName.hash, histName.str); for (auto i = 0u; i < MAX_REGISTRY_SIZE; ++i) { TObject* rawPtr = nullptr; std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(histName.idx + i)]); @@ -629,6 +630,8 @@ class HistogramRegistry LOGF(FATAL, "Internal array of HistogramRegistry %s is full.", mName); } + void validateHash(const uint32_t hash, const char* name); + // helper function to find the histogram position in the registry template <typename T> uint32_t getHistIndex(const T& histName) diff --git a/Framework/Core/src/HistogramRegistry.cxx b/Framework/Core/src/HistogramRegistry.cxx index 7e50b299f0c65..bb19012367fe3 100644 --- a/Framework/Core/src/HistogramRegistry.cxx +++ b/Framework/Core/src/HistogramRegistry.cxx @@ -37,21 +37,33 @@ const std::map<HistType, std::function<HistPtr(const HistogramSpec&)>> HistFacto // create histogram from specification and insert it into the registry void HistogramRegistry::insert(const HistogramSpec& histSpec) { - const uint32_t i = imask(histSpec.hash); - for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + validateHash(histSpec.hash, histSpec.name.data()); + const uint32_t idx = imask(histSpec.hash); + for (auto i = 0u; i < MAX_REGISTRY_SIZE; ++i) { TObject* rawPtr = nullptr; - std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(j + i)]); + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(idx + i)]); if (!rawPtr) { registerName(histSpec.name); - mRegistryKey[imask(j + i)] = histSpec.hash; - mRegistryValue[imask(j + i)] = HistFactory::createHistVariant(histSpec); - lookup += j; + mRegistryKey[imask(idx + i)] = histSpec.hash; + mRegistryValue[imask(idx + i)] = HistFactory::createHistVariant(histSpec); + lookup += i; return; } } LOGF(FATAL, R"(Internal array of HistogramRegistry "%s" is full.)", mName); } +void HistogramRegistry::validateHash(const uint32_t hash, const char* name) +{ + auto it = std::find(mRegistryKey.begin(), mRegistryKey.end(), hash); + if (it != mRegistryKey.end()) { + auto idx = it - mRegistryKey.begin(); + std::string collidingName{}; + std::visit([&](const auto& hist) { collidingName = hist->GetName(); }, mRegistryValue[idx]); + LOGF(FATAL, R"(Hash collision in HistogramRegistry "%s"! Please rename histogram "%s" or "%s".)", mName, name, collidingName); + } +} + void HistogramRegistry::add(const HistogramSpec& histSpec) { insert(histSpec); @@ -201,6 +213,9 @@ void HistogramRegistry::print(bool showAxisDetails) } LOGF(INFO, "%s", std::string(titleString.size(), '='), titleString); LOGF(INFO, "Total: %d histograms, ca. %s", nHistos, totalSizeInfo); + if (lookup) { + LOGF(INFO, "Due to index collisions, histograms were shifted by %d registry slots in total.", lookup); + } LOGF(INFO, "%s", std::string(titleString.size(), '='), titleString); LOGF(INFO, ""); } @@ -211,9 +226,9 @@ TList* HistogramRegistry::operator*() TList* list = new TList(); list->SetName(mName.data()); - for (auto j = 0u; j < MAX_REGISTRY_SIZE; ++j) { + for (auto i = 0u; i < MAX_REGISTRY_SIZE; ++i) { TNamed* rawPtr = nullptr; - std::visit([&](const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[j]); + std::visit([&](const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[i]); if (rawPtr) { std::deque<std::string> path = splitPath(rawPtr->GetName()); std::string name = path.back(); diff --git a/Framework/Core/test/test_HistogramRegistry.cxx b/Framework/Core/test/test_HistogramRegistry.cxx index 0cfa8d50b03e4..d59587c444ad3 100644 --- a/Framework/Core/test/test_HistogramRegistry.cxx +++ b/Framework/Core/test/test_HistogramRegistry.cxx @@ -13,6 +13,7 @@ #include "Framework/HistogramRegistry.h" #include <boost/test/unit_test.hpp> +#include <iostream> using namespace o2; using namespace o2::framework; @@ -55,6 +56,21 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryLookup) auto r = foo(); auto histo2 = r.get<TH1>(HIST("histo")).get(); BOOST_REQUIRE_EQUAL(histo2->GetNbinsX(), 100); + + registry.print(); + + // check that registry behaves correctly when two different names have equal hash: + /* + auto str1 = "Maria has nine red beds."; + auto str2 = "Steven has fifteen white tables."; + BOOST_REQUIRE_EQUAL(compile_time_hash(str1), compile_time_hash(str2)); + try { + registry.add(str1, "", kTH1F, {{20, 0.0f, 10.01f}}); + registry.add(str2, "", kTH1F, {{20, 0.0f, 10.01f}}); + } catch (...) { + std::cout << "Hash collision was detected correctly!" << std::endl; + } + */ } BOOST_AUTO_TEST_CASE(HistogramRegistryExpressionFill) From f04c23dffd4fc9fb191084335663e0f690584490 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Dec 2020 13:19:41 +0100 Subject: [PATCH 1638/1751] DPL: initial support for plugin based algorithms (#5071) These are to be used to decouple workflow specific components from the code itself. For example here we use it to load the the rootFileReader from a separate library. This will allow us to load JAlien only when running an analysis workflow. --- Framework/AnalysisSupport/CMakeLists.txt | 16 +++++ Framework/AnalysisSupport/src/Plugin.cxx | 21 +++++++ Framework/CMakeLists.txt | 2 + .../Core/include/Framework/AlgorithmSpec.h | 12 ++-- Framework/Core/include/Framework/Plugins.h | 61 +++++++++++++++++++ Framework/Core/src/WorkflowHelpers.cxx | 24 +++++++- 6 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 Framework/AnalysisSupport/CMakeLists.txt create mode 100644 Framework/AnalysisSupport/src/Plugin.cxx create mode 100644 Framework/Core/include/Framework/Plugins.h diff --git a/Framework/AnalysisSupport/CMakeLists.txt b/Framework/AnalysisSupport/CMakeLists.txt new file mode 100644 index 0000000000000..68dc3fc6f9b2b --- /dev/null +++ b/Framework/AnalysisSupport/CMakeLists.txt @@ -0,0 +1,16 @@ +# 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. + +# Given GCC 7.3 does not provide std::filesystem we use Boost instead +# Drop this once we move to GCC 8.2+ +o2_add_library(FrameworkAnalysisSupport + SOURCES src/Plugin.cxx + PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src + PUBLIC_LINK_LIBRARIES O2::Framework) diff --git a/Framework/AnalysisSupport/src/Plugin.cxx b/Framework/AnalysisSupport/src/Plugin.cxx new file mode 100644 index 0000000000000..54d4bf5f84d00 --- /dev/null +++ b/Framework/AnalysisSupport/src/Plugin.cxx @@ -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. +#include "Framework/Plugins.h" +#include "Framework/AlgorithmSpec.h" +#include "Framework/AODReaderHelpers.h" + +struct ROOTFileReader : o2::framework::AlgorithmPlugin { + o2::framework::AlgorithmSpec create() override + { + return o2::framework::readers::AODReaderHelpers::rootFileReaderCallback(); + } +}; + +DEFINE_DPL_PLUGIN(ROOTFileReader, CustomAlgorithm); diff --git a/Framework/CMakeLists.txt b/Framework/CMakeLists.txt index 3edb89db53770..90bdaa39685d2 100644 --- a/Framework/CMakeLists.txt +++ b/Framework/CMakeLists.txt @@ -16,4 +16,6 @@ add_subdirectory(Core) add_subdirectory(Utils) +add_subdirectory(AnalysisSupport) + add_subdirectory(TestWorkflows) diff --git a/Framework/Core/include/Framework/AlgorithmSpec.h b/Framework/Core/include/Framework/AlgorithmSpec.h index 49dd495ba0178..bf18576ad2ff2 100644 --- a/Framework/Core/include/Framework/AlgorithmSpec.h +++ b/Framework/Core/include/Framework/AlgorithmSpec.h @@ -18,9 +18,7 @@ #include <functional> -namespace o2 -{ -namespace framework +namespace o2::framework { /// This is the class holding the actual algorithm to be used. Notice that the @@ -88,6 +86,11 @@ struct AlgorithmSpec { ErrorCallback onError = nullptr; }; +/// Helper class for an algorithm which is loaded as a plugin. +struct AlgorithmPlugin { + virtual AlgorithmSpec create() = 0; +}; + template <typename T> struct ContextElementTraits { static decltype(auto) get(ProcessingContext& ctx) @@ -180,7 +183,6 @@ AlgorithmSpec::InitCallback adaptStateful(LAMBDA l) return adaptStatefulF(FFL(l)); } -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif // FRAMEWORK_ALGORITHMSPEC_H diff --git a/Framework/Core/include/Framework/Plugins.h b/Framework/Core/include/Framework/Plugins.h new file mode 100644 index 0000000000000..6a159a7065890 --- /dev/null +++ b/Framework/Core/include/Framework/Plugins.h @@ -0,0 +1,61 @@ +// 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_PLUGINS_H_ +#define O2_FRAMEWORK_PLUGINS_H_ + +#include "Framework/AlgorithmSpec.h" +#include <cstring> + +namespace o2::framework +{ + +enum struct DplPluginKind : int { + // A plugin which can customise the workflow. Needs to return + // an object of kind o2::framework::WorkflowCustomizationService + CustomAlgorithm +}; + +} // namespace o2::framework + +/// An handle for a generic DPL plugin. +/// The handle is returned by the dpl_plugin_callback() +struct DPLPluginHandle { + void* instance; + char const* name; + enum o2::framework::DplPluginKind kind; + DPLPluginHandle* previous; +}; + +#define DEFINE_DPL_PLUGIN(NAME, KIND) \ + extern "C" { \ + DPLPluginHandle* dpl_plugin_callback(DPLPluginHandle* previous) \ + { \ + return new DPLPluginHandle{new NAME{}, strdup(#NAME), o2::framework::DplPluginKind::KIND, previous}; \ + } \ + } + +namespace o2::framework +{ +struct PluginManager { + template <typename T> + static T* getByName(DPLPluginHandle* handle, char const* name) + { + while (handle != nullptr) { + if (strncmp(handle->name, name, strlen(name)) == 0) { + return reinterpret_cast<T*>(handle->instance); + } + handle = handle->previous; + } + return nullptr; + } +}; +} // namespace o2::framework + +#endif // O2_FRAMEWORK_PLUGINS_H_ diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 8e74c7262d2d2..58f6f2842b580 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -20,6 +20,8 @@ #include "Framework/RawDeviceService.h" #include "Framework/StringHelpers.h" #include "Framework/CommonMessageBackends.h" +#include "Framework/ExternalFairMQDeviceProxy.h" +#include "Framework/Plugins.h" #include "Headers/DataHeader.h" #include <algorithm> @@ -258,7 +260,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext static_cast<DataAllocator::SubSpecificationType>(compile_time_hash("internal-dpl-aod-reader")), aodLifetime}}, {}, - readers::AODReaderHelpers::rootFileReaderCallback(), + AlgorithmSpec::dummyAlgorithm(), {ConfigParamSpec{"aod-file", VariantType::String, {"Input AOD file"}}, ConfigParamSpec{"aod-reader-json", VariantType::String, {"json configuration file"}}, ConfigParamSpec{"time-limit", VariantType::Int64, 0ll, {"Maximum run time limit in seconds"}}, @@ -417,6 +419,26 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // add the reader if (aodReader.outputs.empty() == false) { + uv_lib_t supportLib; + int result = 0; +#ifdef __APPLE__ + result = uv_dlopen("libO2FrameworkAnalysisSupport.dylib", &supportLib); +#else + result = uv_dlopen("libO2FrameworkAnalysisSupport.so", &supportLib); +#endif + if (result == -1) { + LOG(ERROR) << uv_dlerror(&supportLib); + } + void* callback = nullptr; + DPLPluginHandle* (*dpl_plugin_callback)(DPLPluginHandle*); + + result = uv_dlsym(&supportLib, "dpl_plugin_callback", (void**)&dpl_plugin_callback); + if (result == -1) { + LOG(ERROR) << uv_dlerror(&supportLib); + } + DPLPluginHandle* pluginInstance = dpl_plugin_callback(nullptr); + AlgorithmPlugin* creator = PluginManager::getByName<AlgorithmPlugin>(pluginInstance, "ROOTFileReader"); + aodReader.algorithm = creator->create(); aodReader.outputs.emplace_back(OutputSpec{"TFN", "TFNumber"}); extraSpecs.push_back(timePipeline(aodReader, ctx.options().get<int64_t>("readers"))); auto concrete = DataSpecUtils::asConcreteDataMatcher(aodReader.inputs[0]); From 6f841a6e3b90441d3602588c52b5fcdc08fb3efc Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Dec 2020 13:20:46 +0100 Subject: [PATCH 1639/1751] DPL: move ROOT file reading completely to the plugin This way we can have the plugin depend on JAlien and not require everyone does. --- Framework/AnalysisSupport/CMakeLists.txt | 1 + .../src/AODJAlienReaderHelpers.cxx | 323 ++++++++++++++++++ .../src/AODJAlienReaderHelpers.h | 28 ++ Framework/AnalysisSupport/src/Plugin.cxx | 4 +- .../Core/include/Framework/AODReaderHelpers.h | 42 --- Framework/Core/src/AODReaderHelpers.cxx | 176 ---------- .../Core/src/AnalysisDataModelHelpers.cxx | 26 -- Framework/Core/src/AnalysisDataModelHelpers.h | 1 - 8 files changed, 354 insertions(+), 247 deletions(-) create mode 100644 Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx create mode 100644 Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h diff --git a/Framework/AnalysisSupport/CMakeLists.txt b/Framework/AnalysisSupport/CMakeLists.txt index 68dc3fc6f9b2b..0f87506224545 100644 --- a/Framework/AnalysisSupport/CMakeLists.txt +++ b/Framework/AnalysisSupport/CMakeLists.txt @@ -12,5 +12,6 @@ # Drop this once we move to GCC 8.2+ o2_add_library(FrameworkAnalysisSupport SOURCES src/Plugin.cxx + src/AODJAlienReaderHelpers.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src PUBLIC_LINK_LIBRARIES O2::Framework) diff --git a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx new file mode 100644 index 0000000000000..acffd4f5de7b8 --- /dev/null +++ b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx @@ -0,0 +1,323 @@ +// 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 "AODJAlienReaderHelpers.h" +#include "Framework/TableTreeHelpers.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/RootTableBuilderHelpers.h" +#include "Framework/AlgorithmSpec.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/CallbackService.h" +#include "Framework/EndOfStreamContext.h" +#include "Framework/DeviceSpec.h" +#include "Framework/RawDeviceService.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/DataInputDirector.h" +#include "Framework/SourceInfoHeader.h" +#include "Framework/ChannelInfo.h" +#include "Framework/Logger.h" + +#include <Monitoring/Monitoring.h> + +#include <ROOT/RDataFrame.hxx> +#include <TGrid.h> +#include <TFile.h> +#include <TTreeCache.h> +#include <TTreePerfStats.h> + +#include <arrow/ipc/reader.h> +#include <arrow/ipc/writer.h> +#include <arrow/io/interfaces.h> +#include <arrow/table.h> +#include <arrow/util/key_value_metadata.h> + +#include <thread> + +using namespace o2; +using namespace o2::aod; + +struct RuntimeWatchdog { + int numberTimeFrames; + uint64_t startTime; + uint64_t lastTime; + double runTime; + uint64_t runTimeLimit; + + RuntimeWatchdog(Long64_t limit) + { + numberTimeFrames = -1; + startTime = uv_hrtime(); + lastTime = startTime; + runTime = 0.; + runTimeLimit = limit; + } + + bool update() + { + numberTimeFrames++; + if (runTimeLimit <= 0) { + return true; + } + + auto nowTime = uv_hrtime(); + + // time spent to process the time frame + double time_spent = numberTimeFrames < 1 ? (double)(nowTime - lastTime) / 1.E9 : 0.; + runTime += time_spent; + lastTime = nowTime; + + return ((double)(lastTime - startTime) / 1.E9 + runTime / (numberTimeFrames + 1)) < runTimeLimit; + } + + void printOut() + { + LOGP(INFO, "RuntimeWatchdog"); + LOGP(INFO, " run time limit: {}", runTimeLimit); + LOGP(INFO, " number of time frames: {}", numberTimeFrames); + LOGP(INFO, " estimated run time per time frame: {}", (numberTimeFrames >= 0) ? runTime / (numberTimeFrames + 1) : 0.); + LOGP(INFO, " estimated total run time: {}", (double)(lastTime - startTime) / 1.E9 + ((numberTimeFrames >= 0) ? runTime / (numberTimeFrames + 1) : 0.)); + } +}; + +template <typename... C> +static constexpr auto columnNamesTrait(framework::pack<C...>) +{ + return std::vector<std::string>{C::columnLabel()...}; +} + +std::vector<std::string> getColumnNames(header::DataHeader dh) +{ + auto description = std::string(dh.dataDescription.str); + auto origin = std::string(dh.dataOrigin.str); + + // get column names + // AOD / RN2 + if (origin == "AOD") { + if (description == "TRACK:PAR") { + return columnNamesTrait(typename StoredTracksMetadata::table_t::persistent_columns_t{}); + } else if (description == "TRACK:PARCOV") { + return columnNamesTrait(typename StoredTracksCovMetadata::table_t::persistent_columns_t{}); + } else if (description == "TRACK:EXTRA") { + return columnNamesTrait(typename TracksExtraMetadata::table_t::persistent_columns_t{}); + } + } + + // default: column names = {} + return std::vector<std::string>({}); +} + +using o2::monitoring::Metric; +using o2::monitoring::Monitoring; +using o2::monitoring::tags::Key; +using o2::monitoring::tags::Value; + +namespace o2::framework::readers +{ +auto setEOSCallback(InitContext& ic) +{ + ic.services().get<CallbackService>().set(CallbackService::Id::EndOfStream, + [](EndOfStreamContext& eosc) { + auto& control = eosc.services().get<ControlService>(); + control.endOfStream(); + control.readyToQuit(QuitRequest::Me); + }); +} + +template <typename O> +static inline auto extractTypedOriginal(ProcessingContext& pc) +{ + ///FIXME: this should be done in invokeProcess() as some of the originals may be compound tables + return O{pc.inputs().get<TableConsumer>(aod::MetadataTrait<O>::metadata::tableLabel())->asArrowTable()}; +} + +template <typename... Os> +static inline auto extractOriginalsTuple(framework::pack<Os...>, ProcessingContext& pc) +{ + return std::make_tuple(extractTypedOriginal<Os>(pc)...); +} + +AlgorithmSpec AODJAlienReaderHelpers::rootFileReaderCallback() +{ + auto callback = AlgorithmSpec{adaptStateful([](ConfigParamRegistry const& options, + DeviceSpec const& spec, + Monitoring& monitoring) { + monitoring.send(Metric{(uint64_t)0, "arrow-bytes-created"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)0, "arrow-messages-created"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)0, "arrow-bytes-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)0, "arrow-messages-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.flushBuffer(); + + if (!options.isSet("aod-file")) { + LOGP(ERROR, "No input file defined!"); + throw std::runtime_error("Processing is stopped!"); + } + + auto filename = options.get<std::string>("aod-file"); + + // create a DataInputDirector + auto didir = std::make_shared<DataInputDirector>(filename); + if (options.isSet("aod-reader-json")) { + auto jsonFile = options.get<std::string>("aod-reader-json"); + if (!didir->readJson(jsonFile)) { + LOGP(ERROR, "Check the JSON document! Can not be properly parsed!"); + } + } + + // get the run time watchdog + auto* watchdog = new RuntimeWatchdog(options.get<int64_t>("time-limit")); + + // selected the TFN input and + // create list of requested tables + header::DataHeader TFNumberHeader; + std::vector<OutputRoute> requestedTables; + std::vector<OutputRoute> routes(spec.outputs); + for (auto route : routes) { + if (DataSpecUtils::partialMatch(route.matcher, header::DataOrigin("TFN"))) { + auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); + TFNumberHeader = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); + } else { + requestedTables.emplace_back(route); + } + } + + auto fileCounter = std::make_shared<int>(0); + auto numTF = std::make_shared<int>(-1); + return adaptStateless([TFNumberHeader, + requestedTables, + fileCounter, + numTF, + watchdog, + didir](Monitoring& monitoring, DataAllocator& outputs, ControlService& control, DeviceSpec const& device) { + // check if RuntimeLimit is reached + if (!watchdog->update()) { + LOGP(INFO, "Run time exceeds run time limit of {} seconds!", watchdog->runTimeLimit); + LOGP(INFO, "Stopping reader {} after time frame {}.", device.inputTimesliceId, watchdog->numberTimeFrames - 1); + monitoring.flushBuffer(); + didir->closeInputFiles(); + control.endOfStream(); + control.readyToQuit(QuitRequest::Me); + return; + } + + // Each parallel reader device.inputTimesliceId reads the files fileCounter*device.maxInputTimeslices+device.inputTimesliceId + // the TF to read is numTF + assert(device.inputTimesliceId < device.maxInputTimeslices); + uint64_t timeFrameNumber = 0; + int fcnt = (*fileCounter * device.maxInputTimeslices) + device.inputTimesliceId; + int ntf = *numTF + 1; + monitoring.send(Metric{(uint64_t)ntf, "tf-sent"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + static int currentFileCounter = -1; + static int filesProcessed = 0; + if (currentFileCounter != *fileCounter) { + currentFileCounter = *fileCounter; + monitoring.send(Metric{(uint64_t)++filesProcessed, "files-opened"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + } + + // loop over requested tables + TTree* tr = nullptr; + bool first = true; + static size_t totalSizeUncompressed = 0; + static size_t totalSizeCompressed = 0; + static size_t totalReadCalls = 0; + + for (auto route : requestedTables) { + + // create header + auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); + auto dh = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); + + // create a TreeToTable object + auto info = didir->getFileFolder(dh, fcnt, ntf); + size_t before = 0; + if (info.file) { + info.file->GetReadCalls(); + } + tr = didir->getDataTree(dh, fcnt, ntf); + if (!tr) { + if (first) { + // check if there is a next file to read + fcnt += device.maxInputTimeslices; + if (didir->atEnd(fcnt)) { + LOGP(INFO, "No input files left to read for reader {}!", device.inputTimesliceId); + didir->closeInputFiles(); + control.endOfStream(); + control.readyToQuit(QuitRequest::Me); + return; + } + // get first folder of next file + ntf = 0; + tr = didir->getDataTree(dh, fcnt, ntf); + if (!tr) { + LOGP(FATAL, "Can not retrieve tree for table {}: fileCounter {}, timeFrame {}", concrete.origin, fcnt, ntf); + throw std::runtime_error("Processing is stopped!"); + } + } else { + LOGP(FATAL, "Can not retrieve tree for table {}: fileCounter {}, timeFrame {}", concrete.origin, fcnt, ntf); + throw std::runtime_error("Processing is stopped!"); + } + } + TTreePerfStats ps("ioperf", tr); + + if (first) { + timeFrameNumber = didir->getTimeFrameNumber(dh, fcnt, ntf); + auto o = Output(TFNumberHeader); + outputs.make<uint64_t>(o) = timeFrameNumber; + } + + // create table output + auto o = Output(dh); + auto& t2t = outputs.make<TreeToTable>(o); + + // add branches to read + // fill the table + + auto colnames = getColumnNames(dh); + if (colnames.size() == 0) { + totalSizeCompressed += tr->GetZipBytes(); + totalSizeUncompressed += tr->GetTotBytes(); + t2t.addAllColumns(tr); + } else { + for (auto& colname : colnames) { + TBranch* branch = tr->GetBranch(colname.c_str()); + totalSizeCompressed += branch->GetZipBytes("*"); + totalSizeUncompressed += branch->GetTotBytes("*"); + t2t.addColumn(colname.c_str()); + } + } + t2t.fill(tr); + if (info.file) { + totalReadCalls += info.file->GetReadCalls() - before; + static std::string currentFileRead = ""; + std::string nextFileRead = info.file->GetPath(); + if (currentFileRead != nextFileRead) { + currentFileRead = nextFileRead; + monitoring.send(Metric{currentFileRead, "aod-file-read-path"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + } + } + monitoring.send(Metric{(double)ps.GetReadCalls(), "aod-tree-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + delete tr; + + first = false; + } + monitoring.send(Metric{(uint64_t)totalSizeUncompressed / 1000, "aod-bytes-read-uncompressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)totalSizeCompressed / 1000, "aod-bytes-read-compressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{(uint64_t)totalReadCalls, "aod-total-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + + // save file number and time frame + *fileCounter = (fcnt - device.inputTimesliceId) / device.maxInputTimeslices; + *numTF = ntf; + }); + })}; + + return callback; +} + +} // namespace o2::framework::readers diff --git a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h new file mode 100644 index 0000000000000..8ef579bd68edf --- /dev/null +++ b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h @@ -0,0 +1,28 @@ +// 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_AODJALIENREADERHELPERS_H_ +#define O2_FRAMEWORK_AODJALIENREADERHELPERS_H_ + +#include "Framework/TableBuilder.h" +#include "Framework/AlgorithmSpec.h" +#include "Framework/Logger.h" +#include <uv.h> + +namespace o2::framework::readers +{ + +struct AODJAlienReaderHelpers { + static AlgorithmSpec rootFileReaderCallback(); +}; + +} // namespace o2::framework::readers + +#endif // O2_FRAMEWORK_AODREADERHELPERS_H_ diff --git a/Framework/AnalysisSupport/src/Plugin.cxx b/Framework/AnalysisSupport/src/Plugin.cxx index 54d4bf5f84d00..1fafab25a956b 100644 --- a/Framework/AnalysisSupport/src/Plugin.cxx +++ b/Framework/AnalysisSupport/src/Plugin.cxx @@ -9,12 +9,12 @@ // or submit itself to any jurisdiction. #include "Framework/Plugins.h" #include "Framework/AlgorithmSpec.h" -#include "Framework/AODReaderHelpers.h" +#include "AODJAlienReaderHelpers.h" struct ROOTFileReader : o2::framework::AlgorithmPlugin { o2::framework::AlgorithmSpec create() override { - return o2::framework::readers::AODReaderHelpers::rootFileReaderCallback(); + return o2::framework::readers::AODJAlienReaderHelpers::rootFileReaderCallback(); } }; diff --git a/Framework/Core/include/Framework/AODReaderHelpers.h b/Framework/Core/include/Framework/AODReaderHelpers.h index f428f46bce6f5..4290f2cccba4b 100644 --- a/Framework/Core/include/Framework/AODReaderHelpers.h +++ b/Framework/Core/include/Framework/AODReaderHelpers.h @@ -19,48 +19,6 @@ namespace o2::framework::readers { -struct RuntimeWatchdog { - int numberTimeFrames; - uint64_t startTime; - uint64_t lastTime; - double runTime; - uint64_t runTimeLimit; - - RuntimeWatchdog(Long64_t limit) - { - numberTimeFrames = -1; - startTime = uv_hrtime(); - lastTime = startTime; - runTime = 0.; - runTimeLimit = limit; - } - - bool update() - { - numberTimeFrames++; - if (runTimeLimit <= 0) { - return true; - } - - auto nowTime = uv_hrtime(); - - // time spent to process the time frame - double time_spent = numberTimeFrames < 1 ? (double)(nowTime - lastTime) / 1.E9 : 0.; - runTime += time_spent; - lastTime = nowTime; - - return ((double)(lastTime - startTime) / 1.E9 + runTime / (numberTimeFrames + 1)) < runTimeLimit; - } - - void printOut() - { - LOGP(INFO, "RuntimeWatchdog"); - LOGP(INFO, " run time limit: {}", runTimeLimit); - LOGP(INFO, " number of time frames: {}", numberTimeFrames); - LOGP(INFO, " estimated run time per time frame: {}", (numberTimeFrames >= 0) ? runTime / (numberTimeFrames + 1) : 0.); - LOGP(INFO, " estimated total run time: {}", (double)(lastTime - startTime) / 1.E9 + ((numberTimeFrames >= 0) ? runTime / (numberTimeFrames + 1) : 0.)); - } -}; struct AODReaderHelpers { static AlgorithmSpec rootFileReaderCallback(); diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index a563578485fd9..266ac4c048814 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -175,180 +175,4 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector<InputSpec> reques }}; } -AlgorithmSpec AODReaderHelpers::rootFileReaderCallback() -{ - auto callback = AlgorithmSpec{adaptStateful([](ConfigParamRegistry const& options, - DeviceSpec const& spec, - Monitoring& monitoring) { - monitoring.send(Metric{(uint64_t)0, "arrow-bytes-created"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - monitoring.send(Metric{(uint64_t)0, "arrow-messages-created"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - monitoring.send(Metric{(uint64_t)0, "arrow-bytes-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - monitoring.send(Metric{(uint64_t)0, "arrow-messages-destroyed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - monitoring.flushBuffer(); - - if (!options.isSet("aod-file")) { - LOGP(ERROR, "No input file defined!"); - throw std::runtime_error("Processing is stopped!"); - } - - auto filename = options.get<std::string>("aod-file"); - - // create a DataInputDirector - auto didir = std::make_shared<DataInputDirector>(filename); - if (options.isSet("aod-reader-json")) { - auto jsonFile = options.get<std::string>("aod-reader-json"); - if (!didir->readJson(jsonFile)) { - LOGP(ERROR, "Check the JSON document! Can not be properly parsed!"); - } - } - - // get the run time watchdog - auto* watchdog = new RuntimeWatchdog(options.get<int64_t>("time-limit")); - - // selected the TFN input and - // create list of requested tables - header::DataHeader TFNumberHeader; - std::vector<OutputRoute> requestedTables; - std::vector<OutputRoute> routes(spec.outputs); - for (auto route : routes) { - if (DataSpecUtils::partialMatch(route.matcher, header::DataOrigin("TFN"))) { - auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); - TFNumberHeader = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); - } else { - requestedTables.emplace_back(route); - } - } - - auto fileCounter = std::make_shared<int>(0); - auto numTF = std::make_shared<int>(-1); - return adaptStateless([TFNumberHeader, - requestedTables, - fileCounter, - numTF, - watchdog, - didir](Monitoring& monitoring, DataAllocator& outputs, ControlService& control, DeviceSpec const& device) { - // check if RuntimeLimit is reached - if (!watchdog->update()) { - LOGP(INFO, "Run time exceeds run time limit of {} seconds!", watchdog->runTimeLimit); - LOGP(INFO, "Stopping reader {} after time frame {}.", device.inputTimesliceId, watchdog->numberTimeFrames - 1); - monitoring.flushBuffer(); - didir->closeInputFiles(); - control.endOfStream(); - control.readyToQuit(QuitRequest::Me); - return; - } - - // Each parallel reader device.inputTimesliceId reads the files fileCounter*device.maxInputTimeslices+device.inputTimesliceId - // the TF to read is numTF - assert(device.inputTimesliceId < device.maxInputTimeslices); - uint64_t timeFrameNumber = 0; - int fcnt = (*fileCounter * device.maxInputTimeslices) + device.inputTimesliceId; - int ntf = *numTF + 1; - monitoring.send(Metric{(uint64_t)ntf, "tf-sent"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - static int currentFileCounter = -1; - static int filesProcessed = 0; - if (currentFileCounter != *fileCounter) { - currentFileCounter = *fileCounter; - monitoring.send(Metric{(uint64_t)++filesProcessed, "files-opened"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - } - - // loop over requested tables - TTree* tr = nullptr; - bool first = true; - static size_t totalSizeUncompressed = 0; - static size_t totalSizeCompressed = 0; - static size_t totalReadCalls = 0; - - for (auto route : requestedTables) { - - // create header - auto concrete = DataSpecUtils::asConcreteDataMatcher(route.matcher); - auto dh = header::DataHeader(concrete.description, concrete.origin, concrete.subSpec); - - // create a TreeToTable object - auto info = didir->getFileFolder(dh, fcnt, ntf); - size_t before = 0; - if (info.file) { - info.file->GetReadCalls(); - } - tr = didir->getDataTree(dh, fcnt, ntf); - if (!tr) { - if (first) { - // check if there is a next file to read - fcnt += device.maxInputTimeslices; - if (didir->atEnd(fcnt)) { - LOGP(INFO, "No input files left to read for reader {}!", device.inputTimesliceId); - didir->closeInputFiles(); - control.endOfStream(); - control.readyToQuit(QuitRequest::Me); - return; - } - // get first folder of next file - ntf = 0; - tr = didir->getDataTree(dh, fcnt, ntf); - if (!tr) { - LOGP(FATAL, "Can not retrieve tree for table {}: fileCounter {}, timeFrame {}", concrete.origin, fcnt, ntf); - throw std::runtime_error("Processing is stopped!"); - } - } else { - LOGP(FATAL, "Can not retrieve tree for table {}: fileCounter {}, timeFrame {}", concrete.origin, fcnt, ntf); - throw std::runtime_error("Processing is stopped!"); - } - } - TTreePerfStats ps("ioperf", tr); - - if (first) { - timeFrameNumber = didir->getTimeFrameNumber(dh, fcnt, ntf); - auto o = Output(TFNumberHeader); - outputs.make<uint64_t>(o) = timeFrameNumber; - } - - // create table output - auto o = Output(dh); - auto& t2t = outputs.make<TreeToTable>(o); - - // add branches to read - // fill the table - - auto colnames = aod::datamodel::getColumnNames(dh); - if (colnames.size() == 0) { - totalSizeCompressed += tr->GetZipBytes(); - totalSizeUncompressed += tr->GetTotBytes(); - t2t.addAllColumns(tr); - } else { - for (auto& colname : colnames) { - TBranch* branch = tr->GetBranch(colname.c_str()); - totalSizeCompressed += branch->GetZipBytes("*"); - totalSizeUncompressed += branch->GetTotBytes("*"); - t2t.addColumn(colname.c_str()); - } - } - t2t.fill(tr); - if (info.file) { - totalReadCalls += info.file->GetReadCalls() - before; - static std::string currentFileRead = ""; - std::string nextFileRead = info.file->GetPath(); - if (currentFileRead != nextFileRead) { - currentFileRead = nextFileRead; - monitoring.send(Metric{currentFileRead, "aod-file-read-path"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - } - } - monitoring.send(Metric{(double)ps.GetReadCalls(), "aod-tree-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - delete tr; - - first = false; - } - monitoring.send(Metric{(uint64_t)totalSizeUncompressed / 1000, "aod-bytes-read-uncompressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - monitoring.send(Metric{(uint64_t)totalSizeCompressed / 1000, "aod-bytes-read-compressed"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - monitoring.send(Metric{(uint64_t)totalReadCalls, "aod-total-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); - - // save file number and time frame - *fileCounter = (fcnt - device.inputTimesliceId) / device.maxInputTimeslices; - *numTF = ntf; - }); - })}; - - return callback; -} - } // namespace o2::framework::readers diff --git a/Framework/Core/src/AnalysisDataModelHelpers.cxx b/Framework/Core/src/AnalysisDataModelHelpers.cxx index b089ebe8f68d0..8a254e70fdcb5 100644 --- a/Framework/Core/src/AnalysisDataModelHelpers.cxx +++ b/Framework/Core/src/AnalysisDataModelHelpers.cxx @@ -40,31 +40,5 @@ std::string getTreeName(header::DataHeader dh) return treeName; } -template <typename... C> -static constexpr auto columnNamesTrait(framework::pack<C...>) -{ - return std::vector<std::string>{C::columnLabel()...}; -} - -std::vector<std::string> getColumnNames(header::DataHeader dh) -{ - auto description = std::string(dh.dataDescription.str); - auto origin = std::string(dh.dataOrigin.str); - - // get column names - // AOD / RN2 - if (origin == "AOD") { - if (description == "TRACK:PAR") { - return columnNamesTrait(typename StoredTracksMetadata::table_t::persistent_columns_t{}); - } else if (description == "TRACK:PARCOV") { - return columnNamesTrait(typename StoredTracksCovMetadata::table_t::persistent_columns_t{}); - } else if (description == "TRACK:EXTRA") { - return columnNamesTrait(typename TracksExtraMetadata::table_t::persistent_columns_t{}); - } - } - - // default: column names = {} - return std::vector<std::string>({}); -} } // namespace o2::aod::datamodel diff --git a/Framework/Core/src/AnalysisDataModelHelpers.h b/Framework/Core/src/AnalysisDataModelHelpers.h index 59f69782c845c..074303e869b8d 100644 --- a/Framework/Core/src/AnalysisDataModelHelpers.h +++ b/Framework/Core/src/AnalysisDataModelHelpers.h @@ -16,6 +16,5 @@ namespace o2::aod::datamodel { std::string getTreeName(header::DataHeader dh); -std::vector<std::string> getColumnNames(header::DataHeader dh); } // namespace o2::aod::datamodel #endif // O2_FRAMEWORK_ANALYSISDATAMODELHELPERS_H_ From 61005342bbdc52978e5b7653c74038f3c757370e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Dec 2020 13:32:19 +0100 Subject: [PATCH 1640/1751] DPL: add (optional) direct dependency on JAliEn to AnalysisSupport This is the groundwork to be able to access TJAlienFile from the reader (without requiring everyone to depend on JAlien). --- Framework/AnalysisSupport/CMakeLists.txt | 7 +- .../src/AODJAlienReaderHelpers.cxx | 12 +- dependencies/FindJAlienROOT.cmake | 33 +++ dependencies/FindXRootD.cmake | 236 ++++++++++++++++++ dependencies/O2Dependencies.cmake | 6 + 5 files changed, 290 insertions(+), 4 deletions(-) create mode 100644 dependencies/FindJAlienROOT.cmake create mode 100644 dependencies/FindXRootD.cmake diff --git a/Framework/AnalysisSupport/CMakeLists.txt b/Framework/AnalysisSupport/CMakeLists.txt index 0f87506224545..ceed68342364c 100644 --- a/Framework/AnalysisSupport/CMakeLists.txt +++ b/Framework/AnalysisSupport/CMakeLists.txt @@ -10,8 +10,13 @@ # Given GCC 7.3 does not provide std::filesystem we use Boost instead # Drop this once we move to GCC 8.2+ + +if(TARGET XRootD::Client) + set(EXTRA_TARGETS XRootD::Client JAliEn::JAliEn) +endif() + o2_add_library(FrameworkAnalysisSupport SOURCES src/Plugin.cxx src/AODJAlienReaderHelpers.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src - PUBLIC_LINK_LIBRARIES O2::Framework) + PUBLIC_LINK_LIBRARIES O2::Framework ${EXTRA_TARGETS}) diff --git a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx index acffd4f5de7b8..bb97107189eac 100644 --- a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx +++ b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx @@ -28,6 +28,9 @@ #include <Monitoring/Monitoring.h> #include <ROOT/RDataFrame.hxx> +#if __has_include(<TJAlienFile.h>) +#include <TJAlienFile.h> +#endif #include <TGrid.h> #include <TFile.h> #include <TTreeCache.h> @@ -237,9 +240,6 @@ AlgorithmSpec AODJAlienReaderHelpers::rootFileReaderCallback() // create a TreeToTable object auto info = didir->getFileFolder(dh, fcnt, ntf); size_t before = 0; - if (info.file) { - info.file->GetReadCalls(); - } tr = didir->getDataTree(dh, fcnt, ntf); if (!tr) { if (first) { @@ -299,6 +299,12 @@ AlgorithmSpec AODJAlienReaderHelpers::rootFileReaderCallback() std::string nextFileRead = info.file->GetPath(); if (currentFileRead != nextFileRead) { currentFileRead = nextFileRead; +#if __has_include(<TJAlienFile.h>) + auto alienFile = dynamic_cast<TJAlienFile*>(info.file); + if (alienFile) { + /// FIXME: get the JAlien stats + } +#endif monitoring.send(Metric{currentFileRead, "aod-file-read-path"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); } } diff --git a/dependencies/FindJAlienROOT.cmake b/dependencies/FindJAlienROOT.cmake new file mode 100644 index 0000000000000..b48e90b40a9b4 --- /dev/null +++ b/dependencies/FindJAlienROOT.cmake @@ -0,0 +1,33 @@ +# 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. +find_path(JALIEN_ROOT_INCLUDE_DIR TJAlienFile.h PATH_SUFFIXES include + PATHS + ${JALIEN_ROOT_ROOT}) + +find_library(JAliEnRoot_LIB JAliEnROOT PATHS ${JALIEN_ROOT_ROOT}/lib) + +if(NOT JALIEN_ROOT_INCLUDE_DIR) + set(JAliEnROOT_FOUND FALSE) + return() +endif() + +set(JAliEnROOT_FOUND TRUE) + +if(NOT TARGET JAliEn::JAliEn) + get_filename_component(libdir ${JAliEnRoot_LIB} DIRECTORY) + add_library(JAliEn::JAliEn INTERFACE IMPORTED) + set_target_properties(JAliEn::JAliEn PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${JALIEN_ROOT_INCLUDE_DIR} + INTERFACE_LINK_LIBRARIES ${JAliEnRoot_LIB} + INTERFACE_LINK_DIRECTORIES ${libdir} + ) +endif() + +mark_as_advanced(JALIEN_ROOT_INCLUDE_DIR) diff --git a/dependencies/FindXRootD.cmake b/dependencies/FindXRootD.cmake new file mode 100644 index 0000000000000..23167369eb781 --- /dev/null +++ b/dependencies/FindXRootD.cmake @@ -0,0 +1,236 @@ +################################################################################ +# Module for locating XRootD. +# +# XROOTD_FOUND +# Indicates whether the library has been found. +# +# XROOTD_INCLUDE_DIRS +# Specifies XRootD include directory. +# +# XROOTD_LIBRARIES +# Specifies XRootD libraries that should be passed to target_link_libararies. +# +# XROOTD_<COMPONENT>_LIBRARIES +# Specifies the libraries of a specific <COMPONENT> +# +# XROOTD_<COMPONENT>_FOUND +# Indicates whether the specified <COMPONENT> was found. +# +# List of components: CLIENT, UTILS, SERVER, POSIX, HTTP and SSI +################################################################################ + + +################################################################################ +# Set XRootD include paths +################################################################################ +FIND_PATH( XROOTD_INCLUDE_DIRS XrdVersion.hh + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES include/xrootd + PATHS /opt/xrootd +) + +IF( NOT "${XROOTD_INCLUDE_DIRS}" STREQUAL "XROOTD_INCLUDE_DIRS-NOTFOUND" ) + SET( XROOTD_FOUND TRUE ) +ENDIF() + +IF( NOT XROOTD_FOUND ) + LIST( APPEND _XROOTD_MISSING_COMPONENTS XROOTD_FOUND ) +ENDIF() + +################################################################################ +# XRootD client libs +# - libXrdCl +################################################################################ +FIND_LIBRARY( XROOTD_CLIENT_LIBRARIES XrdCl + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +IF( NOT "${XROOTD_CLIENT_LIBRARIES}" STREQUAL "XROOTD_CLIENT_LIBRARIES-NOTFOUND" ) + SET( XROOTD_CLIENT_FOUND TRUE ) + LIST( APPEND XROOTD_LIBRARIES ${XROOTD_CLIENT_LIBRARIES} ) +ENDIF() + +IF( XRootD_FIND_REQUIRED_CLIENT AND NOT XROOTD_CLIENT_FOUND ) + MESSAGE( "XRootD client required but not found!" ) + LIST( APPEND _XROOTD_MISSING_COMPONENTS XROOTD_CLIENT_FOUND ) + UNSET( XROOTD_FOUND ) +ENDIF() + +################################################################################ +# XRootD utils libs +# - libXrdUtils +################################################################################ +FIND_LIBRARY( XROOTD_UTILS_LIBRARIES XrdUtils + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +IF( NOT "${XROOTD_UTILS_LIBRARIES}" STREQUAL "XROOTD_UTILS_LIBRARIES-NOTFOUND" ) + SET( XROOTD_UTILS_FOUND TRUE ) + LIST( APPEND XROOTD_LIBRARIES ${XROOTD_UTILS_LIBRARIES} ) +ENDIF() + +IF( XRootD_FIND_REQUIRED_UTILS AND NOT XROOTD_UTILS_FOUND ) + MESSAGE( "XRootD utils required but not found!" ) + LIST( APPEND _XROOTD_MISSING_COMPONENTS XROOTD_UTILS_FOUND ) + UNSET( XROOTD_FOUND ) +ENDIF() + +################################################################################ +# XRootD server libs +# - libXrdServer +################################################################################ +FIND_LIBRARY( XROOTD_SERVER_LIBRARIES XrdServer + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +IF( NOT "${XROOTD_SERVER_LIBRARIES}" STREQUAL "XROOTD_SERVER_LIBRARIES-NOTFOUND" ) + SET( XROOTD_SERVER_FOUND TRUE ) + LIST( APPEND XROOTD_LIBRARIES ${XROOTD_SERVER_LIBRARIES} ) +ENDIF() + +IF( XRootD_FIND_REQUIRED_SERVER AND NOT XROOTD_SERVER_FOUND ) + MESSAGE( "XRootD server required but not found!" ) + LIST( APPEND _XROOTD_MISSING_COMPONENTS XROOTD_SERVER_FOUND ) + UNSET( XROOTD_FOUND ) +ENDIF() + +################################################################################ +# XRootD posix libs +# - libXrdPosix +# - libXrdPosixPreload +################################################################################ +FIND_LIBRARY( XROOTD_POSIX_LIBRARY XrdPosix + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +FIND_LIBRARY( XROOTD_POSIX_PRELOAD_LIBRARY XrdPosixPreload + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +IF( NOT "${XROOTD_POSIX_LIBRARY}" STREQUAL "XROOTD_POSIX_LIBRARY-NOTFOUND" ) + IF( NOT "${XROOTD_POSIX_PRELOAD_LIBRARY}" STREQUAL "XROOTD_POSIX_PRELOAD_LIBRARY-NOTFOUND" ) + SET( XROOTD_POSIX_LIBRARIES ${XROOTD_POSIX_LIBRARY} ${XROOTD_POSIX_PRELOAD_LIBRARY} ) + SET( XROOTD_POSIX_FOUND TRUE ) + LIST( APPEND XROOTD_LIBRARIES ${XROOTD_POSIX_LIBRARIES} ) + ENDIF() +ENDIF() + +IF( XRootD_FIND_REQUIRED_POSIX AND NOT XROOTD_POSIX_FOUND ) + MESSAGE( "XRootD posix required but not found!" ) + LIST( APPEND _XROOTD_MISSING_COMPONENTS XROOTD_POSIX_FOUND ) + UNSET( XROOTD_FOUND ) +ENDIF() + +################################################################################ +# XRootD HTTP (XrdHttp) libs +# - libXrdHtppUtils +################################################################################ +FIND_LIBRARY( XROOTD_HTTP_LIBRARIES XrdHttpUtils + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +IF( NOT "${XROOTD_HTTP_LIBRARIES}" STREQUAL "XROOTD_HTTP_LIBRARIES-NOTFOUND" ) + SET( XROOTD_HTTP_FOUND TRUE ) + LIST( APPEND XROOTD_LIBRARIES ${XROOTD_HTTP_LIBRARIES} ) +ENDIF() + +IF( XRootD_FIND_REQUIRED_HTTP AND NOT XROOTD_HTTP_FOUND ) + MESSAGE( "XRootD http required but not found!" ) + LIST( APPEND _XROOTD_MISSING_COMPONENTS XROOTD_HTTP_FOUND ) + UNSET( XROOTD_FOUND ) +ENDIF() + +################################################################################ +# XRootD SSI libs +# - XrdSsiLib +# - XrdSsiShMap +################################################################################ +FIND_LIBRARY( XROOTD_SSI_LIBRARY XrdSsiLib + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +FIND_LIBRARY( XROOTD_SSI_SHMAP_LIBRARY XrdSsiShMap + HINTS + ${XROOTD_DIR} + $ENV{XROOTD_DIR} + /usr + /opt/xrootd + PATH_SUFFIXES lib lib64 +) + +IF( NOT "${XROOTD_SSI_LIBRARY}" STREQUAL "XROOTD_SSI_LIBRARY-NOTFOUND" ) + IF( NOT "${XROOTD_SSI_SHMAP_LIBRARY}" STREQUAL "XROOTD_SSI_SHMAP_LIBRARY-NOTFOUND" ) + SET( XROOTD_SSI_LIBRARIES ${XROOTD_SSI_LIBRARY} ${XROOTD_SSI_SHMAP_LIBRARY} ) + SET( XROOTD_SSI_FOUND TRUE ) + LIST( APPEND XROOTD_LIBRARIES ${XROOTD_SSI_LIBRARIES} ) + ENDIF() +ENDIF() + +IF( XRootD_FIND_REQUIRED_SSI AND NOT XROOTD_SSI_FOUND ) + MESSAGE( "XRootD ssi required but not found!" ) + LIST (APPEND _XROOTD_MISSING_COMPONENTS XROOTD_SSI_FOUND ) + UNSET( XROOTD_FOUND ) +ENDIF() + +################################################################################ +# Set up the XRootD find module +################################################################################ + +IF( XRootD_FIND_REQUIRED ) + INCLUDE( FindPackageHandleStandardArgs ) + FIND_PACKAGE_HANDLE_STANDARD_ARGS( XRootD + REQUIRED_VARS XROOTD_INCLUDE_DIRS ${_XROOTD_MISSING_COMPONENTS} + ) +ENDIF() + + +if (XROOTD_CLIENT_FOUND) +if(NOT TARGET XRootD::Client) + get_filename_component(libdir ${XROOTD_CLIENT_LIBRARIES} DIRECTORY) + add_library(XRootD::Client INTERFACE IMPORTED) + set_target_properties(XRootD::Client PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${XROOTD_INCLUDE_DIRS} + INTERFACE_LINK_LIBRARIES ${XROOTD_CLIENT_LIBRARIES} + INTERFACE_LINK_DIRECTORIES ${libdir} + ) +endif() +endif() diff --git a/dependencies/O2Dependencies.cmake b/dependencies/O2Dependencies.cmake index 93cc13d58df3e..b1e751a46ff79 100644 --- a/dependencies/O2Dependencies.cmake +++ b/dependencies/O2Dependencies.cmake @@ -103,6 +103,12 @@ set_package_properties(RapidJSON PROPERTIES TYPE REQUIRED) find_package(CURL) set_package_properties(CURL PROPERTIES TYPE REQUIRED) +find_package(JAliEnROOT MODULE) +set_package_properties(JAliEnROOT PROPERTIES TYPE RECOMMENDED) + +find_package(XRootD MODULE) +set_package_properties(XRootD PROPERTIES TYPE RECOMMENDED) + # MC specific packages message(STATUS "Input BUILD_SIMULATION=${BUILD_SIMULATION}") include("${CMAKE_CURRENT_LIST_DIR}/O2SimulationDependencies.cmake") From 953e0deb4624fa9a7f522522d7ffb0adb8acb43a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 15 Dec 2020 21:42:00 +0100 Subject: [PATCH 1641/1751] Do not compile OpenGL examples on macOS --- Framework/Core/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 06f5de71e4740..63c7e46765808 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -258,12 +258,14 @@ endforeach() # #####################################################@ if (TARGET AliceO2::DebugGUI) +if (NOT APPLE) set (DEBUG_GUI_TESTS_WORKFLOW CustomGUIGL CustomGUISokol SimpleTracksED ) endif() +endif() foreach(w BoostSerializedProcessing @@ -307,10 +309,12 @@ if (TARGET AliceO2::DebugGUI) # environment assertion fired X11: The DISPLAY environment variable is missing # glfw-3.2.1/src/window.c:579: glfwGetFramebufferSize: Assertion `window != # ((void *)0)' failed. +if(NOT APPLE) set_property(TEST test_Framework_test_SimpleTracksED PROPERTY DISABLED TRUE) set_property(TEST test_Framework_test_CustomGUIGL PROPERTY DISABLED TRUE) set_property(TEST test_Framework_test_CustomGUISokol PROPERTY DISABLED TRUE) endif() +endif() # TODO: investigate the problem and re-enable set_property(TEST test_Framework_test_BoostSerializedProcessing From 8e8510123206bfc7a34d742e12237227e89706cd Mon Sep 17 00:00:00 2001 From: manso <manso@clermont.in2p3.fr> Date: Sun, 13 Dec 2020 16:53:53 +0100 Subject: [PATCH 1642/1751] Update of water and air cooling --- Detectors/ITSMFT/MFT/base/src/HalfCone.cxx | 366 +++++++++++++++--- .../ITSMFT/MFT/base/src/HeatExchanger.cxx | 116 ++++-- .../ITSMFT/MFT/base/src/PowerSupplyUnit.cxx | 4 +- 3 files changed, 389 insertions(+), 97 deletions(-) diff --git a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx index 458c8f4465065..7b101838470e8 100644 --- a/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HalfCone.cxx @@ -14,22 +14,23 @@ /// \Carlos csoncco@pucp.edu.pe /// \date 01/07/2020 -#include "TGeoManager.h" -#include "TGeoMatrix.h" -#include "TGeoManager.h" +#include "TGeoBBox.h" +#include "TGeoBoolNode.h" #include "TGeoCompositeShape.h" -#include "TGeoShape.h" #include "TGeoCone.h" -#include "TGeoVolume.h" +#include "TGeoManager.h" #include "TGeoMaterial.h" +#include "TGeoMatrix.h" #include "TGeoMedium.h" -#include "TGeoTube.h" +#include "TGeoShape.h" #include "TGeoTrd1.h" -#include "TMath.h" +#include "TGeoTube.h" +#include "TGeoVolume.h" #include "TGeoXtru.h" +#include "TMath.h" -#include "MFTBase/HalfCone.h" #include "MFTBase/Constants.h" +#include "MFTBase/HalfCone.h" using namespace o2::mft; @@ -528,7 +529,7 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) Double_t high_bord = 1.355; // 13.5 Double_t ang_in_bord = 0; Double_t ang_fin_bord = 90; - // TGeoRotation *rot_bord1 = new TGeoRotation("rot_bord1", ang_in_1hole + // TGeoRotation* rot_bord1 = new TGeoRotation("rot_bord1", ang_in_1hole // +0.0167,0,0); TGeoRotation* rot1_bord1 = new TGeoRotation("rot1_bord1", 14.8, 0, 0); rot1_bord1->RegisterYourself(); @@ -1771,7 +1772,8 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) HalfConeVolume->AddNode(frame_back, 6, c_final); // HalfConeVolume->AddNode(colonne_mb, 7, c_final); // - //========================== Mother Boards ========================================= + //========================== Mother Boards + //========================================= // ============= MotherBoard 0 and 1 Double_t mMB0cu[3]; @@ -1794,15 +1796,22 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) auto* MotherBoard0 = new TGeoVolumeAssembly(Form("MotherBoard0_H%d", half)); // 4 layers - TGeoVolume* vMB0cu = gGeoManager->MakeBox("vMB0cu", mCu, mMB0cu[0] / 2, mMB0cu[1] / 2, mMB0cu[2] / 2); - TGeoVolume* vMB0fr4 = gGeoManager->MakeBox("vMB0fr4", mFR4, mMB0cu[0] / 2, mMB0fr4 / 2, mMB0cu[2] / 2); - TGeoVolume* vMB0pol = gGeoManager->MakeBox("vMB0pol", mPol, mMB0cu[0] / 2, mMB0pol / 2, mMB0cu[2] / 2); - TGeoVolume* vMB0epo = gGeoManager->MakeBox("vMB0epo", mEpo, mMB0cu[0] / 2, mMB0epo / 2, mMB0cu[2] / 2); + TGeoVolume* vMB0cu = gGeoManager->MakeBox("vMB0cu", mCu, mMB0cu[0] / 2, + mMB0cu[1] / 2, mMB0cu[2] / 2); + TGeoVolume* vMB0fr4 = gGeoManager->MakeBox("vMB0fr4", mFR4, mMB0cu[0] / 2, + mMB0fr4 / 2, mMB0cu[2] / 2); + TGeoVolume* vMB0pol = gGeoManager->MakeBox("vMB0pol", mPol, mMB0cu[0] / 2, + mMB0pol / 2, mMB0cu[2] / 2); + TGeoVolume* vMB0epo = gGeoManager->MakeBox("vMB0epo", mEpo, mMB0cu[0] / 2, + mMB0epo / 2, mMB0cu[2] / 2); // Screws = Head + Thread - TGeoVolume* vMB0screwH = gGeoManager->MakeTube("vMB0screwH", mInox, 0.0, 0.7 / 2, 0.35 / 2); // tete - TGeoVolume* vMB0screwT = gGeoManager->MakeTube("vMB0screwT", mInox, 0.0, 0.4 / 2, 1.2 / 2); // filetage + TGeoVolume* vMB0screwH = gGeoManager->MakeTube("vMB0screwH", mInox, 0.0, + 0.7 / 2, 0.35 / 2); // tete + TGeoVolume* vMB0screwT = gGeoManager->MakeTube("vMB0screwT", mInox, 0.0, + 0.4 / 2, 1.2 / 2); // filetage // Insert Sertitec - TGeoVolume* vMB0serti = gGeoManager->MakeTube("vMB0serti", mInox, 0.16 / 2, 0.556 / 2, 0.15 / 2); // tete + TGeoVolume* vMB0serti = gGeoManager->MakeTube("vMB0serti", mInox, 0.16 / 2, + 0.556 / 2, 0.15 / 2); // tete vMB0cu->SetLineColor(kRed); vMB0fr4->SetLineColor(kBlack); @@ -1820,31 +1829,46 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) if (half == 1) { signe = +1; } - auto* t_MB0fr4 = new TGeoTranslation("translation_fr4", 0.0, signe * (mMB0fr4 + mMB0cu[1]) / 2, 0.0); + auto* t_MB0fr4 = new TGeoTranslation("translation_fr4", 0.0, + signe * (mMB0fr4 + mMB0cu[1]) / 2, 0.0); t_MB0fr4->RegisterYourself(); MotherBoard0->AddNode(vMB0fr4, 1, t_MB0fr4); - auto* t_MB0pol = new TGeoTranslation("translation_pol", 0.0, signe * (mMB0fr4 + (mMB0cu[1] + mMB0pol) / 2), 0.0); + auto* t_MB0pol = + new TGeoTranslation("translation_pol", 0.0, + signe * (mMB0fr4 + (mMB0cu[1] + mMB0pol) / 2), 0.0); t_MB0pol->RegisterYourself(); MotherBoard0->AddNode(vMB0pol, 1, t_MB0pol); - auto* t_MB0epo = new TGeoTranslation("translation_epo", 0.0, signe * (mMB0fr4 + mMB0pol + (mMB0cu[1] + mMB0epo) / 2), 0.0); + auto* t_MB0epo = new TGeoTranslation( + "translation_epo", 0.0, + signe * (mMB0fr4 + mMB0pol + (mMB0cu[1] + mMB0epo) / 2), 0.0); t_MB0epo->RegisterYourself(); MotherBoard0->AddNode(vMB0epo, 1, t_MB0epo); auto* r_MB0screw = new TGeoRotation("rotation_vMB0screw", 0, 90, 0); - auto* t_MB0screwH1 = new TGeoCombiTrans(mMB0cu[0] / 2 - 1.65, - signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.35) / 2), 0.0, r_MB0screw); + auto* t_MB0screwH1 = new TGeoCombiTrans( + mMB0cu[0] / 2 - 1.65, + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.35) / 2), 0.0, + r_MB0screw); t_MB0screwH1->RegisterYourself(); - auto* t_MB0screwT1 = new TGeoCombiTrans(mMB0cu[0] / 2 - 1.65, -signe * (mMB0cu[1] + 1.2) / 2, 0.0, r_MB0screw); + auto* t_MB0screwT1 = new TGeoCombiTrans( + mMB0cu[0] / 2 - 1.65, -signe * (mMB0cu[1] + 1.2) / 2, 0.0, r_MB0screw); t_MB0screwT1->RegisterYourself(); - auto* t_MB0screwH2 = new TGeoCombiTrans(-(mMB0cu[0] / 2 - 1.65), - signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.35) / 2), 0.0, r_MB0screw); + auto* t_MB0screwH2 = new TGeoCombiTrans( + -(mMB0cu[0] / 2 - 1.65), + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.35) / 2), 0.0, + r_MB0screw); t_MB0screwH2->RegisterYourself(); - auto* t_MB0screwT2 = new TGeoCombiTrans(-(mMB0cu[0] / 2 - 1.65), -signe * (mMB0cu[1] + 1.2) / 2, 0.0, r_MB0screw); + auto* t_MB0screwT2 = new TGeoCombiTrans( + -(mMB0cu[0] / 2 - 1.65), -signe * (mMB0cu[1] + 1.2) / 2, 0.0, r_MB0screw); t_MB0screwT2->RegisterYourself(); - auto* t_MB0serti1 = new TGeoCombiTrans(mMB0cu[0] / 2 - 2.65, - signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.153) / 2), 0.0, r_MB0screw); + auto* t_MB0serti1 = new TGeoCombiTrans( + mMB0cu[0] / 2 - 2.65, + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.153) / 2), 0.0, + r_MB0screw); t_MB0serti1->RegisterYourself(); - auto* t_MB0serti2 = new TGeoCombiTrans(-(mMB0cu[0] / 2 - 2.65), - signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.153) / 2), 0.0, r_MB0screw); + auto* t_MB0serti2 = new TGeoCombiTrans( + -(mMB0cu[0] / 2 - 2.65), + signe * (mMB0fr4 + mMB0pol + mMB0epo + (mMB0cu[1] + 0.153) / 2), 0.0, + r_MB0screw); t_MB0serti2->RegisterYourself(); MotherBoard0->AddNode(vMB0screwH, 1, t_MB0screwH1); MotherBoard0->AddNode(vMB0screwT, 1, t_MB0screwT1); @@ -1856,7 +1880,9 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) // Positioning the board auto* t_MB0 = new TGeoTranslation("translation_MB0", 0.0, tyMB0, tzMB0); t_MB0->RegisterYourself(); - auto* t_MB1 = new TGeoTranslation("translation_MB1", 0.0, tyMB0, tzMB0 - 3.3); // 3.3 cm is the interdistance between disk 0 and 1 + auto* t_MB1 = new TGeoTranslation( + "translation_MB1", 0.0, tyMB0, + tzMB0 - 3.3); // 3.3 cm is the interdistance between disk 0 and 1 t_MB1->RegisterYourself(); auto* r_MB0 = new TGeoRotation("rotation_MB0", 0.0, 0.0, 0.0); r_MB0->RegisterYourself(); @@ -1868,12 +1894,17 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) HalfConeVolume->AddNode(MotherBoard0, 1, p_MB0); HalfConeVolume->AddNode(MotherBoard0, 1, p_MB1); - auto* MotherBoard0_1 = new TGeoVolumeAssembly(Form("MotherBoard0_1_H%d", half)); + auto* MotherBoard0_1 = + new TGeoVolumeAssembly(Form("MotherBoard0_1_H%d", half)); // 4 layers - TGeoVolume* vMB0cu_1 = gGeoManager->MakeBox("vMB0cu_1", mCu, 18.0 / 2, mMB0cu[1] / 2, 1.2 / 2); - TGeoVolume* vMB0fr4_1 = gGeoManager->MakeBox("vMB0fr4_1", mFR4, 18.0 / 2, mMB0fr4 / 2, 1.2 / 2); - TGeoVolume* vMB0pol_1 = gGeoManager->MakeBox("vMB0pol_1", mPol, 18.0 / 2, mMB0pol / 2, 1.2 / 2); - TGeoVolume* vMB0epo_1 = gGeoManager->MakeBox("vMB0epo_1", mEpo, 18.0 / 2, mMB0epo / 2, 1.2 / 2); + TGeoVolume* vMB0cu_1 = + gGeoManager->MakeBox("vMB0cu_1", mCu, 18.0 / 2, mMB0cu[1] / 2, 1.2 / 2); + TGeoVolume* vMB0fr4_1 = + gGeoManager->MakeBox("vMB0fr4_1", mFR4, 18.0 / 2, mMB0fr4 / 2, 1.2 / 2); + TGeoVolume* vMB0pol_1 = + gGeoManager->MakeBox("vMB0pol_1", mPol, 18.0 / 2, mMB0pol / 2, 1.2 / 2); + TGeoVolume* vMB0epo_1 = + gGeoManager->MakeBox("vMB0epo_1", mEpo, 18.0 / 2, mMB0epo / 2, 1.2 / 2); vMB0cu_1->SetLineColor(kRed); vMB0fr4_1->SetLineColor(kBlack); vMB0pol_1->SetLineColor(kGreen); @@ -1899,21 +1930,34 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) mMB2epo = 0.0075; // 75 microns auto* MotherBoard2 = new TGeoVolumeAssembly(Form("MotherBoard2_H%d", half)); // 4 layers - TGeoVolume* vMB2cu = gGeoManager->MakeTrd1("vMB2cu", mCu, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2cu[2] / 2, mMB2cu[3] / 2); - TGeoVolume* vMB2fr4 = gGeoManager->MakeTrd1("vMB2fr4", mFR4, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2fr4 / 2, mMB2cu[3] / 2); - TGeoVolume* vMB2pol = gGeoManager->MakeTrd1("vMB2pol", mPol, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2pol / 2, mMB2cu[3] / 2); - TGeoVolume* vMB2epo = gGeoManager->MakeTrd1("vMB2epo", mEpo, mMB2cu[0] / 2, mMB2cu[1] / 2, mMB2epo / 2, mMB2cu[3] / 2); + TGeoVolume* vMB2cu = + gGeoManager->MakeTrd1("vMB2cu", mCu, mMB2cu[0] / 2, mMB2cu[1] / 2, + mMB2cu[2] / 2, mMB2cu[3] / 2); + TGeoVolume* vMB2fr4 = + gGeoManager->MakeTrd1("vMB2fr4", mFR4, mMB2cu[0] / 2, mMB2cu[1] / 2, + mMB2fr4 / 2, mMB2cu[3] / 2); + TGeoVolume* vMB2pol = + gGeoManager->MakeTrd1("vMB2pol", mPol, mMB2cu[0] / 2, mMB2cu[1] / 2, + mMB2pol / 2, mMB2cu[3] / 2); + TGeoVolume* vMB2epo = + gGeoManager->MakeTrd1("vMB2epo", mEpo, mMB2cu[0] / 2, mMB2cu[1] / 2, + mMB2epo / 2, mMB2cu[3] / 2); vMB2cu->SetLineColor(kRed); vMB2fr4->SetLineColor(kBlack); vMB2pol->SetLineColor(kGreen); vMB2epo->SetLineColor(kBlue); - auto* t_MB2fr4 = new TGeoTranslation("translation_fr4", 0.0, signe * (mMB2fr4 + mMB2cu[2]) / 2, 0.0); + auto* t_MB2fr4 = new TGeoTranslation("translation_fr4", 0.0, + signe * (mMB2fr4 + mMB2cu[2]) / 2, 0.0); t_MB2fr4->RegisterYourself(); - auto* t_MB2pol = new TGeoTranslation("translation_pol", 0.0, signe * (mMB2fr4 + (mMB2cu[2] + mMB2pol) / 2), 0.0); + auto* t_MB2pol = + new TGeoTranslation("translation_pol", 0.0, + signe * (mMB2fr4 + (mMB2cu[2] + mMB2pol) / 2), 0.0); t_MB2pol->RegisterYourself(); - auto* t_MB2epo = new TGeoTranslation("translation_epo", 0.0, signe * (mMB2fr4 + mMB2pol + (mMB2cu[2] + mMB2epo) / 2), 0.0); + auto* t_MB2epo = new TGeoTranslation( + "translation_epo", 0.0, + signe * (mMB2fr4 + mMB2pol + (mMB2cu[2] + mMB2epo) / 2), 0.0); t_MB2epo->RegisterYourself(); MotherBoard2->AddNode(vMB2cu, 1); @@ -1921,9 +1965,12 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) MotherBoard2->AddNode(vMB2pol, 1, t_MB2pol); MotherBoard2->AddNode(vMB2epo, 1, t_MB2epo); for (Float_t i = -1; i < 3; i++) { - auto* t_MB2serti1 = new TGeoTranslation("translationMB2serti1", 8.5, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + auto* t_MB2serti1 = new TGeoTranslation( + "translationMB2serti1", 8.5, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); t_MB2serti1->RegisterYourself(); - auto* t_MB2serti2 = new TGeoTranslation("translationMB2serti2", -8.5, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + auto* t_MB2serti2 = + new TGeoTranslation("translationMB2serti2", -8.5, + -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); t_MB2serti2->RegisterYourself(); auto* p_MB2serti1 = new TGeoCombiTrans(*t_MB2serti1, *r_MB0screw); p_MB2serti1->RegisterYourself(); @@ -1934,9 +1981,12 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) } for (Float_t i = -2; i < 1; i++) { - auto* t_MB2serti3 = new TGeoTranslation("translationMB2serti3", 0.7, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + auto* t_MB2serti3 = new TGeoTranslation( + "translationMB2serti3", 0.7, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); t_MB2serti3->RegisterYourself(); - auto* t_MB2serti4 = new TGeoTranslation("translationMB2serti4", -0.7, -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); + auto* t_MB2serti4 = + new TGeoTranslation("translationMB2serti4", -0.7, + -signe * (mMB2cu[2] + 0.153) / 2, 1.3 * i); t_MB2serti4->RegisterYourself(); auto* p_MB2serti3 = new TGeoCombiTrans(*t_MB2serti3, *r_MB0screw); p_MB2serti3->RegisterYourself(); @@ -1947,11 +1997,15 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) } for (Float_t i = -2; i < 2; i++) { - auto* t_MB2serti5 = new TGeoTranslation("translationMB2serti5", 7.0 * i + 3.5, -signe * (mMB2cu[2] + 0.153) / 2, -2.5); + auto* t_MB2serti5 = + new TGeoTranslation("translationMB2serti5", 7.0 * i + 3.5, + -signe * (mMB2cu[2] + 0.153) / 2, -2.5); t_MB2serti5->RegisterYourself(); auto* p_MB2serti5 = new TGeoCombiTrans(*t_MB2serti5, *r_MB0screw); p_MB2serti5->RegisterYourself(); - auto* t_MB2serti6 = new TGeoTranslation("translationMB2serti6", 7.0 * i + 3.5, -signe * (mMB2cu[2] + 0.153) / 2, -3.5); + auto* t_MB2serti6 = + new TGeoTranslation("translationMB2serti6", 7.0 * i + 3.5, + -signe * (mMB2cu[2] + 0.153) / 2, -3.5); t_MB2serti6->RegisterYourself(); auto* p_MB2serti6 = new TGeoCombiTrans(*t_MB2serti6, *r_MB0screw); p_MB2serti6->RegisterYourself(); @@ -1959,22 +2013,224 @@ TGeoVolumeAssembly* HalfCone::createHalfCone(Int_t half) MotherBoard2->AddNode(vMB0serti, 1, p_MB2serti6); } // Connector board of MB0 on MB2 - auto* t_MotherBoard0_1 = new TGeoTranslation("translation_MB0_1", 0.0, -signe * (-0.5), 3.5); + auto* t_MotherBoard0_1 = + new TGeoTranslation("translation_MB0_1", 0.0, -signe * (-0.5), 3.5); t_MotherBoard0_1->RegisterYourself(); - auto* t_MotherBoard0_2 = new TGeoTranslation("translation_MB0_2", 0.0, -signe * (-0.5), 1.5); + auto* t_MotherBoard0_2 = + new TGeoTranslation("translation_MB0_2", 0.0, -signe * (-0.5), 1.5); t_MotherBoard0_2->RegisterYourself(); MotherBoard2->AddNode(MotherBoard0_1, 1, t_MotherBoard0_1); MotherBoard2->AddNode(MotherBoard0_1, 1, t_MotherBoard0_2); // Positioning the board - auto* t_MotherBoard2 = new TGeoTranslation("translation_MB2", 0.0, - -signe * (-20.52 + mMB2fr4 + mMB2pol + mMB2epo + 2.2 * TMath::Sin(19.0)), - -62.8 + 2.2 * TMath::Cos(19.0)); + auto* t_MotherBoard2 = new TGeoTranslation( + "translation_MB2", 0.0, + -signe * (-20.52 + mMB2fr4 + mMB2pol + mMB2epo + 2.2 * TMath::Sin(19.0)), + -62.8 + 2.2 * TMath::Cos(19.0)); t_MotherBoard2->RegisterYourself(); - auto* r_MotherBoard2 = new TGeoRotation("rotation_MB2", 0.0, -signe * (-19.0), 0.0); + auto* r_MotherBoard2 = + new TGeoRotation("rotation_MB2", 0.0, -signe * (-19.0), 0.0); r_MotherBoard2->RegisterYourself(); auto* p_MB2 = new TGeoCombiTrans(*t_MotherBoard2, *r_MotherBoard2); p_MB2->RegisterYourself(); HalfConeVolume->AddNode(MotherBoard2, 1, p_MB2); + + //======================== Air ventilation ========================== + TGeoMedium* mVentilation = gGeoManager->GetMedium("MFT_Polypropylene$"); + // Bottom + TGeoSubtraction* vent_subB1; + Float_t lB1 = 5.5; // half length + Float_t xB1 = 0.3; + Float_t yB1 = 0.4; + auto* ventB1 = new TGeoBBox(Form("ventB1_H%d", half), xB1, yB1, lB1); + auto* ventB1_int = + new TGeoBBox(Form("ventB1_int_H%d", half), 0.2, 0.3, lB1 + 0.0001); + vent_subB1 = new TGeoSubtraction(ventB1, ventB1_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalB1 = + new TGeoCompositeShape(Form("vent_finalB1_H%d", half), vent_subB1); + auto* vent_B1 = + new TGeoVolume(Form("ventB1_H%d", half), vent_finalB1, mVentilation); + vent_B1->SetLineColor(kGray); + auto* t_airB1 = new TGeoTranslation("t_airB1", signe * (15.3 - xB1), + -8.75 - yB1 - 0.1, -45.570 - lB1); + t_airB1->RegisterYourself(); + auto* r_airB1 = new TGeoRotation("r_airB1", 0.0, 0.0, 0.0); + r_airB1->RegisterYourself(); + auto* p_airB1 = new TGeoCombiTrans(*t_airB1, *r_airB1); + p_airB1->RegisterYourself(); + HalfConeVolume->AddNode(vent_B1, 1, p_airB1); + + TGeoSubtraction* vent_subB2; + Float_t lB2 = 10.6; // half length + auto* ventB2 = new TGeoBBox(Form("ventB2_H%d", half), yB1, xB1, lB2); + auto* ventB2_int = + new TGeoBBox(Form("ventB2_int_H%d", half), 0.3, 0.2, lB2 + 0.0001); + vent_subB2 = new TGeoSubtraction(ventB2, ventB2_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalB2 = + new TGeoCompositeShape(Form("vent_finalB2_H%d", half), vent_subB2); + auto* vent_B2 = + new TGeoVolume(Form("ventB2_H%d", half), vent_finalB2, mVentilation); + vent_B2->SetLineColor(kGray); + Float_t theta = -signe * 32.; + Float_t phi = signe * 23.; + Float_t thetaRad = theta * TMath::Pi() / 180.; + Float_t phiRad = phi * TMath::Pi() / 180.; + auto* r_airB2 = new TGeoRotation("r_airB2", 90.0 - phi, theta, 0.); + r_airB2->RegisterYourself(); + Float_t XairB2 = + signe * + (15.3 + lB2 * TMath::Sin(TMath::Abs(thetaRad) * TMath::Cos(phiRad))); + Float_t YairB2 = + -8.75 - 2 * yB1 + TMath::Sin(phiRad) * TMath::Sin(thetaRad) * lB2 + 0.2; + Float_t ZairB2 = -45.570 - 2 * lB1 - TMath::Cos(thetaRad) * lB2 - 0.2; + auto* t_airB2 = new TGeoTranslation("t_airB2", XairB2, YairB2, ZairB2); + t_airB2->RegisterYourself(); + auto* p_airB2 = new TGeoCombiTrans(*t_airB2, *r_airB2); + p_airB2->RegisterYourself(); + HalfConeVolume->AddNode(vent_B2, 1, p_airB2); + + TGeoSubtraction* vent_subB3; + Float_t lB3 = 4.8; // half length + auto* ventB3 = new TGeoBBox(Form("ventB3_H%d", half), yB1, xB1, lB3); + auto* ventB3_int = + new TGeoBBox(Form("ventB3_int_H%d", half), 0.3, 0.2, lB3 + 0.0001); + vent_subB3 = new TGeoSubtraction(ventB3, ventB3_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalB3 = + new TGeoCompositeShape(Form("vent_finalB3_H%d", half), vent_subB3); + auto* vent_B3 = + new TGeoVolume(Form("ventB3_H%d", half), vent_finalB3, mVentilation); + vent_B3->SetLineColor(kGray); + auto* r_airB3 = new TGeoRotation("r_airB3", 90.0 - phi, theta, 0.); + r_airB3->RegisterYourself(); + Float_t XairB3 = + signe * + (15.3 + + (2 * lB2 - lB3) * TMath::Sin(TMath::Abs(thetaRad) * TMath::Cos(phiRad)) - + xB1); + Float_t YairB3 = -8.75 - 2 * yB1 + + TMath::Sin(phiRad) * TMath::Sin(thetaRad) * (2 * lB2 - lB3) + + 0.2 - 1.9 * yB1; + Float_t ZairB3 = + -45.570 - 2 * lB1 - TMath::Cos(thetaRad) * (2 * lB2 - lB3) - 0.2; + + auto* t_airB3 = new TGeoTranslation("t_airB3", XairB3, YairB3, ZairB3); + + t_airB3->RegisterYourself(); + auto* p_airB3 = new TGeoCombiTrans(*t_airB3, *r_airB3); + p_airB3->RegisterYourself(); + HalfConeVolume->AddNode(vent_B3, 1, p_airB3); + + TGeoSubtraction* vent_subB4; + Float_t lB4 = 4.5; // half length + Float_t xB4 = 0.3; + Float_t yB4 = 0.8; + auto* ventB4 = new TGeoBBox(Form("ventB4_H%d", half), yB4, xB4, lB4); + auto* ventB4_int = + new TGeoBBox(Form("ventB4_int_H%d", half), 0.7, 0.2, lB4 + 0.0001); + vent_subB4 = new TGeoSubtraction(ventB4, ventB4_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalB4 = + new TGeoCompositeShape(Form("vent_finalB4_H%d", half), vent_subB4); + auto* vent_B4 = + new TGeoVolume(Form("ventB3_H%d", half), vent_finalB4, mVentilation); + vent_B4->SetLineColor(kGray); + auto* r_airB4 = + new TGeoRotation("r_airB4", 90.0 - signe * 25., -signe * 5, 0.); + r_airB4->RegisterYourself(); + auto* t_airB4 = new TGeoTranslation( + "t_airB4", + XairB2 + + signe * (lB2 * TMath::Sin(TMath::Abs(thetaRad) * TMath::Cos(phiRad)) + + 0.4), + YairB2 + TMath::Sin(phiRad) * TMath::Sin(thetaRad) * lB2 - 0.6, + ZairB3 - TMath::Cos(thetaRad) * lB2 * 0.965); + t_airB4->RegisterYourself(); + auto* p_airB4 = new TGeoCombiTrans(*t_airB4, *r_airB4); + p_airB4->RegisterYourself(); + HalfConeVolume->AddNode(vent_B4, 1, p_airB4); + + // Top + TGeoSubtraction* vent_subT1; + auto* ventT1 = new TGeoBBox(Form("ventT1_H%d", half), xB1, yB1, lB1); + auto* ventT1_int = + new TGeoBBox(Form("ventT1_int_H%d", half), 0.2, 0.3, lB1 + 0.0001); + vent_subT1 = new TGeoSubtraction(ventB1, ventB1_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalT1 = + new TGeoCompositeShape(Form("vent_finalT1_H%d", half), vent_subT1); + auto* vent_T1 = + new TGeoVolume(Form("ventT1_H%d", half), vent_finalT1, mVentilation); + vent_T1->SetLineColor(kGray); + auto* t_airT1 = new TGeoTranslation("t_airT1", signe * (15.3 - xB1), + -(-8.75 - yB1 - 0.1), -45.570 - lB1); + t_airB1->RegisterYourself(); + auto* r_airT1 = new TGeoRotation("r_airT1", 0.0, 0.0, 0.0); + r_airT1->RegisterYourself(); + auto* p_airT1 = new TGeoCombiTrans(*t_airT1, *r_airT1); + p_airT1->RegisterYourself(); + HalfConeVolume->AddNode(vent_T1, 1, p_airT1); + + TGeoSubtraction* vent_subT2; + auto* ventT2 = new TGeoBBox(Form("ventT2_H%d", half), yB1, xB1, lB2); + auto* ventT2_int = + new TGeoBBox(Form("ventT2_int_H%d", half), 0.3, 0.2, lB2 + 0.0001); + vent_subT2 = new TGeoSubtraction(ventT2, ventT2_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalT2 = + new TGeoCompositeShape(Form("vent_finalT2_H%d", half), vent_subT2); + auto* vent_T2 = + new TGeoVolume(Form("ventT2_H%d", half), vent_finalT2, mVentilation); + vent_T2->SetLineColor(kGray); + theta = -signe * 32.; + phi = signe * 23.; + thetaRad = theta * TMath::Pi() / 180.; + phiRad = phi * TMath::Pi() / 180.; + auto* r_airT2 = new TGeoRotation("r_airT2", 90.0 - phi, -theta, 0.); + r_airT2->RegisterYourself(); + auto* t_airT2 = new TGeoTranslation("t_airT2", -XairB2, -YairB2, ZairB2); + t_airT2->RegisterYourself(); + auto* p_airT2 = new TGeoCombiTrans(*t_airT2, *r_airT2); + p_airT2->RegisterYourself(); + HalfConeVolume->AddNode(vent_T2, 1, p_airT2); + + TGeoSubtraction* vent_subT3; + auto* ventT3 = new TGeoBBox(Form("ventT3_H%d", half), yB1, xB1, lB3); + auto* ventT3_int = + new TGeoBBox(Form("ventT3_int_H%d", half), 0.3, 0.2, lB3 + 0.0001); + vent_subT3 = new TGeoSubtraction(ventT3, ventT3_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalT3 = + new TGeoCompositeShape(Form("vent_finalT3_H%d", half), vent_subT3); + auto* vent_T3 = + new TGeoVolume(Form("ventT3_H%d", half), vent_finalT3, mVentilation); + vent_T3->SetLineColor(kGray); + auto* r_airT3 = new TGeoRotation("r_airT3", 90.0 - phi, -theta, 0.); + r_airT3->RegisterYourself(); + auto* t_airT3 = new TGeoTranslation("t_airT3", -XairB3, -YairB3, ZairB3); + t_airT3->RegisterYourself(); + auto* p_airT3 = new TGeoCombiTrans(*t_airT3, *r_airT3); + p_airT3->RegisterYourself(); + HalfConeVolume->AddNode(vent_T3, 1, p_airT3); + + TGeoSubtraction* vent_subT4; + auto* ventT4 = new TGeoBBox(Form("ventT4_H%d", half), yB4, xB4, lB4); + auto* ventT4_int = + new TGeoBBox(Form("ventT4_int_H%d", half), 0.7, 0.2, lB4 + 0.0001); + vent_subT4 = new TGeoSubtraction(ventT4, ventT4_int, nullptr, nullptr); + TGeoCompositeShape* vent_finalT4 = + new TGeoCompositeShape(Form("vent_finalT4_H%d", half), vent_subT4); + auto* vent_T4 = + new TGeoVolume(Form("ventT4_H%d", half), vent_finalT4, mVentilation); + vent_T4->SetLineColor(kGray); + auto* r_airT4 = + new TGeoRotation("r_airT4", 90.0 - signe * 25., signe * 5, 0.); + r_airT4->RegisterYourself(); + auto* t_airT4 = new TGeoTranslation( + "t_airT4", + -(XairB2 + + signe * (lB2 * TMath::Sin(TMath::Abs(thetaRad) * TMath::Cos(phiRad)) + + 0.4)), + -(YairB2 + TMath::Sin(phiRad) * TMath::Sin(thetaRad) * lB2 - 0.6), + ZairB3 - TMath::Cos(thetaRad) * lB2 * 0.965); + t_airT4->RegisterYourself(); + auto* p_airT4 = new TGeoCombiTrans(*t_airT4, *r_airT4); + p_airT4->RegisterYourself(); + HalfConeVolume->AddNode(vent_T4, 1, p_airT4); //=================================================================== return HalfConeVolume; } diff --git a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx index 334073c572f4a..a42bd352d99d0 100644 --- a/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx +++ b/Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx @@ -3739,13 +3739,13 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) if (disk == 0 || disk == 1 || disk == 2) { auto* mCoolingPipe1 = new TGeoVolumeAssembly(Form("cooling_pipe1_H%d", half)); if (disk == 0) { - length1 = 1.3; + length1 = 5.3; } if (disk == 1) { - length1 = 0.87; + length1 = 4.87; } if (disk == 2) { - length1 = 0.45; + length1 = 4.45; } rin = 0.25 / 2; rout = 0.4 / 2; @@ -3763,13 +3763,13 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) transfoTorus1->RegisterYourself(); if (disk == 0) { - length2 = 7.9; + length2 = 13.2; } if (disk == 1) { - length2 = 4.1; + length2 = 9.7; } if (disk == 2) { - length2 = 0.2; + length2 = 6.1; } TGeoVolume* Tube2 = gGeoManager->MakeTube(Form("Tube2_H%d_D%d", half, disk), mPipe, rin, rout, length2 / 2); TGeoVolume* TubeW2 = gGeoManager->MakeTube(Form("TubeW2_H%d_D%d", half, disk), mWater, 0., rin, length2 / 2); @@ -3791,13 +3791,13 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Float_t length3; if (disk == 0) { - length3 = 4.18; + length3 = 3.9; } if (disk == 1) { - length3 = 4.10; + length3 = 3.85; } if (disk == 2) { - length3 = 4.54; + length3 = 4.25; } TGeoVolume* Tube3 = gGeoManager->MakeTube(Form("Tube3_H%d_D%d", half, disk), mPipe, rin, rout, length3 / 2); TGeoVolume* TubeW3 = gGeoManager->MakeTube(Form("TubeW3_H%d_D%d", half, disk), mWater, 0., rin, length3 / 2); @@ -3806,28 +3806,31 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) TGeoCombiTrans* transfoTube3 = new TGeoCombiTrans(-length2 - radius2 - radius1, -radius2 - length3 / 2, length1 / 2 + radius1, rTube3); transfoTube3->RegisterYourself(); - Float_t length4 = 14.0; // one single pipe instead of 3 pipes coming from the 3 first disks + Float_t length4 = 10.; //12.5; // one single pipe instead of 3 pipes coming from the 3 first disks Float_t rin4 = 0.216; Float_t rout4 = 0.346; TGeoVolume* Tube4 = gGeoManager->MakeTube(Form("Tube4_H%d_D%d", half, disk), mPipe, rin4, rout4, length4 / 2); TGeoVolume* TubeW4 = gGeoManager->MakeTube(Form("TubeW4_H%d_D%d", half, disk), mWater, 0., rin4, length4 / 2); - Float_t theta4 = 8.0; // angle from the "horizontal" plane x,z - Float_t phi4 = 47.0; // "azimutal" angle + Float_t theta4 = 19.; // horizontal plane angle + Float_t phi4 = 37; // vertical plane angle TGeoRotation* rTube4 = new TGeoRotation("rotationTube4", 90.0 + theta4, 90.0 + phi4, 0.0); rTube4->RegisterYourself(); // next line, the x and z axis are reversed in the location... - TGeoCombiTrans* transfoTube4 = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.5, -radius2 - length3 / 2 - 2.95, length1 / 2 + radius1 + 3.80, rTube4); + Float_t xTube4 = length1 / 2. + radius1 + TMath::Cos(theta4 * TMath::DegToRad()) * TMath::Sin(phi4 * TMath::DegToRad()) * length4 / 2 * 0.8; + Float_t yTube4 = -radius2 - length3 - TMath::Sin(theta4 * TMath::DegToRad()) * length4 / 2 * 0.8 - 0.2; + Float_t zTube4 = -radius1 - length2 - radius2 - TMath::Cos(theta4 * TMath::DegToRad()) * TMath::Cos(phi4 * TMath::DegToRad()) * length4 / 2 * 0.8; + TGeoCombiTrans* transfoTube4 = new TGeoCombiTrans(zTube4, yTube4 - 0.2, xTube4 - 0.1, rTube4); transfoTube4->RegisterYourself(); - Float_t length5 = 16.5; // one single pipe instead of 3 pipes coming from the 3 first disks + Float_t length5 = 13.; //14.5; // one single pipe instead of 5 pipes Double_t theta = 180. * TMath::Pi() / 180.; Double_t phi = 0. * TMath::Pi() / 180.; Double_t nlow[3]; nlow[0] = TMath::Sin(theta) * TMath::Cos(phi); nlow[1] = TMath::Sin(theta) * TMath::Sin(phi); nlow[2] = TMath::Cos(theta); - theta = 36. * TMath::Pi() / 180.; - phi = 270. * TMath::Pi() / 180.; + theta = 15. * TMath::Pi() / 180.; + phi = -90. * TMath::Pi() / 180.; Double_t nhi[3]; nhi[0] = TMath::Sin(theta) * TMath::Cos(phi); nhi[1] = TMath::Sin(theta) * TMath::Sin(phi); @@ -3836,13 +3839,14 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Float_t rout5 = 0.447; TGeoVolume* Tube5 = gGeoManager->MakeCtub(Form("Tube5_H%d_D%d", half, disk), mPipe, rin5, rout5, length5 / 2, 0., 360., nlow[0], nlow[1], nlow[2], nhi[0], nhi[1], nhi[2]); TGeoVolume* TubeW5 = gGeoManager->MakeCtub(Form("TubeW5_H%d_D%d", half, disk), mWater, 0., rin5, length5 / 2, 0., 360., nlow[0], nlow[1], nlow[2], nhi[0], nhi[1], nhi[2]); - Float_t theta5 = 11.0; // angle from the "horizontal" plane x,z - Float_t phi5 = 9.0; // "azimutal" angle + Float_t theta5 = 8.5; // angle from the "horizontal" plane x,z + Float_t phi5 = 12.5; // "azimutal" angle TGeoRotation* rTube5 = new TGeoRotation("rotationTube5", 90.0 + theta5, 90.0 + phi5, 0.0); rTube5->RegisterYourself(); - TGeoCombiTrans* transfoTube5 = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.4 - TMath::Cos(phi4 * TMath::DegToRad()) * length4 / 2 - TMath::Cos(phi5 * TMath::DegToRad()) * length5 / 2, - -radius2 - length3 / 2 - 2.6 - TMath::Sin(theta4 * TMath::DegToRad()) * length4 / 2 - TMath::Sin(theta5 * TMath::DegToRad()) * length5 / 2, - length1 / 2 + radius1 + 3.8 + TMath::Sin(phi4 * TMath::DegToRad()) * length4 / 2 + TMath::Sin(phi5 * TMath::DegToRad()) * length5 / 2, rTube5); + Float_t xTube5 = xTube4 + TMath::Cos(theta4 * TMath::DegToRad()) * TMath::Sin(phi4 * TMath::DegToRad()) * length4 / 2 + TMath::Cos(theta5 * TMath::DegToRad()) * TMath::Sin(phi5 * TMath::DegToRad()) * length5 / 2 * 1.03; + Float_t yTube5 = yTube4 - TMath::Sin(theta4 * TMath::DegToRad()) * length4 / 2 - TMath::Sin(theta5 * TMath::DegToRad()) * length5 / 2 * 1.03 + 0.2; + Float_t zTube5 = zTube4 - TMath::Cos(theta4 * TMath::DegToRad()) * TMath::Cos(phi4 * TMath::DegToRad()) * length4 / 2 - TMath::Cos(theta5 * TMath::DegToRad()) * TMath::Cos(phi5 * TMath::DegToRad()) * length5 / 2 * 1.03; + TGeoCombiTrans* transfoTube5 = new TGeoCombiTrans(zTube5, yTube5, xTube5, rTube5); transfoTube5->RegisterYourself(); Tube1->SetLineColor(kGray); @@ -3852,6 +3856,9 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Tube3->SetLineColor(kGray); Tube4->SetLineColor(kGray); Tube5->SetLineColor(kGray); + TubeW3->SetLineColor(kBlue); + TubeW4->SetLineColor(kBlue); + TubeW5->SetLineColor(kBlue); mCoolingPipe1->AddNode(Tube1, 1, tTube1); mCoolingPipe1->AddNode(Torus1, 1, transfoTorus1); @@ -3874,14 +3881,18 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) //----------------------------------------------------------------- auto* mCoolingPipe2 = new TGeoVolumeAssembly(Form("cooling_pipe2_H%d_D%d", half, disk)); TGeoVolume* Tube1p = gGeoManager->MakeTube(Form("Tube1p_H%d_D%d", half, disk), mPipe, rin, rout, length1 / 2); - TGeoVolume* Torus1p = gGeoManager->MakeTorus(Form("Torus1p_H%d_D%d", half, disk), mPipe, radius1, rin, rout, 0., 90.); - TGeoVolume* Tube2p = gGeoManager->MakeTube(Form("Tube2p_H%d_D%d", half, disk), mPipe, rin, rout, length2 / 2); - TGeoVolume* Torus2p = gGeoManager->MakeTorus(Form("Torus2p_H%d_D%d", half, disk), mPipe, radius2, rin, rout, 0., 90.); - TGeoVolume* Tube3p = gGeoManager->MakeTube(Form("Tube3p_H%d_D%d", half, disk), mPipe, rin, rout, length3 / 2); TGeoVolume* TubeW1p = gGeoManager->MakeTube(Form("TubeW1p_H%d_D%d", half, disk), mWater, 0., rin, length1 / 2); + + TGeoVolume* Torus1p = gGeoManager->MakeTorus(Form("Torus1p_H%d_D%d", half, disk), mPipe, radius1, rin, rout, 0., 90.); TGeoVolume* TorusW1p = gGeoManager->MakeTorus(Form("TorusW1p_H%d_D%d", half, disk), mWater, radius1, 0., rin, 0., 90.); + + TGeoVolume* Tube2p = gGeoManager->MakeTube(Form("Tube2p_H%d_D%d", half, disk), mPipe, rin, rout, length2 / 2); TGeoVolume* TubeW2p = gGeoManager->MakeTube(Form("TubeW2p_H%d_D%d", half, disk), mWater, 0., rin, length2 / 2); + + TGeoVolume* Torus2p = gGeoManager->MakeTorus(Form("Torus2p_H%d_D%d", half, disk), mPipe, radius2, rin, rout, 0., 90.); TGeoVolume* TorusW2p = gGeoManager->MakeTorus(Form("TorusW2p_H%d_D%d", half, disk), mWater, radius2, 0., rin, 0., 90.); + + TGeoVolume* Tube3p = gGeoManager->MakeTube(Form("Tube3p_H%d_D%d", half, disk), mPipe, rin, rout, length3 / 2); TGeoVolume* TubeW3p = gGeoManager->MakeTube(Form("TubeW3p_H%d_D%d", half, disk), mWater, 0., rin, length3 / 2); TGeoRotation* rTorus2p = new TGeoRotation("rotationTorus2p", 180.0, 0.0, 0.0); @@ -3892,7 +3903,8 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) transfoTube3p->RegisterYourself(); TGeoRotation* rTube4p = new TGeoRotation(Form("rotationTube4p_H%d_D%d", half, disk), 90.0 - theta4, phi4 - 90.0, 0.0); rTube4p->RegisterYourself(); - TGeoCombiTrans* transfoTube4p = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.5, radius2 + length3 / 2 + 2.95, length1 / 2 + radius1 + 3.80, rTube4p); + + TGeoCombiTrans* transfoTube4p = new TGeoCombiTrans(zTube4, -yTube4 + 0.2, xTube4 - 0.1, rTube4p); transfoTube4p->RegisterYourself(); Tube1p->SetLineColor(kGray); @@ -3900,6 +3912,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Tube2p->SetLineColor(kGray); Torus2p->SetLineColor(kGray); Tube3p->SetLineColor(kGray); + TubeW3p->SetLineColor(kBlue); mCoolingPipe2->AddNode(Tube1p, 1, tTube1); mCoolingPipe2->AddNode(Torus1p, 1, transfoTorus1); @@ -3911,30 +3924,37 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) mCoolingPipe2->AddNode(TubeW2p, 1, transfoTube2); mCoolingPipe2->AddNode(TorusW2p, 1, transfoTorus2p); mCoolingPipe2->AddNode(TubeW3p, 1, transfoTube3p); + if (disk == 0) { - mCoolingPipe2->AddNode(Tube4, 1, transfoTube4p); + + TGeoVolume* Tube4p = gGeoManager->MakeTube(Form("Tube4p_H%d_D%d", half, disk), mPipe, rin4, rout4, length4 / 2); + TGeoVolume* TubeW4p = gGeoManager->MakeTube(Form("TubeW4p_H%d_D%d", half, disk), mWater, 0., rin4, length4 / 2); + Tube4p->SetLineColor(kGray); + TubeW4p->SetLineColor(kBlue); + + mCoolingPipe2->AddNode(Tube4p, 1, transfoTube4p); + mCoolingPipe2->AddNode(TubeW4p, 1, transfoTube4p); theta = 180. * TMath::Pi() / 180.; phi = 0. * TMath::Pi() / 180.; nlow[0] = TMath::Sin(theta) * TMath::Cos(phi); nlow[1] = TMath::Sin(theta) * TMath::Sin(phi); nlow[2] = TMath::Cos(theta); - theta = -36. * TMath::Pi() / 180.; + theta = -15. * TMath::Pi() / 180.; phi = 270. * TMath::Pi() / 180.; nhi[0] = TMath::Sin(theta) * TMath::Cos(phi); nhi[1] = TMath::Sin(theta) * TMath::Sin(phi); nhi[2] = TMath::Cos(theta); TGeoVolume* Tube5p = gGeoManager->MakeCtub(Form("Tube5p_H%d_D%d", half, disk), mPipe, rin5, rout5, length5 / 2, 0., 360., nlow[0], nlow[1], nlow[2], nhi[0], nhi[1], nhi[2]); - Float_t theta5 = 11.0; // angle from the "horizontal" plane x,z - Float_t phi5 = 9.0; // "azimutal" angle + TGeoVolume* TubeW5p = gGeoManager->MakeCtub(Form("TubeW5p_H%d_D%d", half, disk), mWater, 0., rin5, length5 / 2, 0., 360., nlow[0], nlow[1], nlow[2], nhi[0], nhi[1], nhi[2]); TGeoRotation* rTube5p = new TGeoRotation("rotationTube5p", -90.0 - theta5, -(90.0 + phi5), 0.0); rTube5p->RegisterYourself(); TGeoCombiTrans* transfoTube5p; - transfoTube5p = new TGeoCombiTrans(-length2 - radius2 - radius1 - 3.4 - TMath::Cos(phi4 * TMath::DegToRad()) * length4 / 2 - TMath::Cos(phi5 * TMath::DegToRad()) * length5 / 2, - radius2 + length3 / 2 + 2.6 + TMath::Sin(theta4 * TMath::DegToRad()) * length4 / 2 + TMath::Sin(theta5 * TMath::DegToRad()) * length5 / 2, - length1 / 2 + radius1 + 3.8 + TMath::Sin(phi4 * TMath::DegToRad()) * length4 / 2 + TMath::Sin(phi5 * TMath::DegToRad()) * length5 / 2, rTube5p); + transfoTube5p = new TGeoCombiTrans(zTube5, -yTube5, xTube5, rTube5p); transfoTube5p->RegisterYourself(); Tube5p->SetLineColor(kGray); + TubeW5p->SetLineColor(kBlue); mCoolingPipe2->AddNode(Tube5p, 1, transfoTube5p); + mCoolingPipe2->AddNode(TubeW5p, 1, transfoTube5p); } TGeoCombiTrans* transfoCoolingPipe1 = nullptr; TGeoCombiTrans* transfoCoolingPipe2 = nullptr; @@ -3951,6 +3971,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) mHalfDisk->AddNode(mCoolingPipe1, 1, transfoCoolingPipe1); mHalfDisk->AddNode(mCoolingPipe2, 1, transfoCoolingPipe2); } + //================================================================= //================================================================= if (disk == 3) { @@ -3958,10 +3979,12 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) auto* mCoolingPipe3 = new TGeoVolumeAssembly(Form("cooling_pipe3_H%d_D%d", half, disk)); Float_t length1_3 = 2.; TGeoVolume* Tube1_3 = gGeoManager->MakeTube(Form("Tube1_3_H%d_D%d", half, disk), mPipe, rin, rout, length1_3 / 2); + TGeoVolume* TubeW1_3 = gGeoManager->MakeTube(Form("TubeW1_3_H%d_D%d", half, disk), mWater, 0., rin, length1_3 / 2); TGeoTranslation* tTube1_3 = new TGeoTranslation(0.0, 0.0, 0.0); tTube1_3->RegisterYourself(); Float_t radius1_3 = 0.4; TGeoVolume* Torus1_3 = gGeoManager->MakeTorus(Form("Torus1_3_H%d_D%d", half, disk), mPipe, radius1_3, rin, rout, 0., 90.); + TGeoVolume* TorusW1_3 = gGeoManager->MakeTorus(Form("TorusW1_3_H%d_D%d", half, disk), mWater, radius1_3, 0., rin, 0., 90.); TGeoRotation* rTorus1_3 = new TGeoRotation("rotationTorus1_3", 90.0, 90.0, 0.0); rTorus1_3->RegisterYourself(); TGeoCombiTrans* transfoTorus1_3 = new TGeoCombiTrans(0.0, -radius1_3, length1_3 / 2, rTorus1_3); @@ -3969,14 +3992,16 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Float_t length2_3; if (disk == 3) { - length2_3 = 9.89; + length2_3 = 10.4; } TGeoVolume* Tube2_3 = gGeoManager->MakeTube(Form("Tube2_3_H%d_D%d", half, disk), mPipe, rin, rout, length2_3 / 2); + TGeoVolume* TubeW2_3 = gGeoManager->MakeTube(Form("TubeW2_3_H%d_D%d", half, disk), mWater, 0., rin, length2_3 / 2); TGeoRotation* rTube2_3 = new TGeoRotation("rotationTube2_3", 180.0, 90.0, 90.0); rTube2_3->RegisterYourself(); TGeoCombiTrans* transfoTube2_3 = new TGeoCombiTrans(0., -length2_3 / 2 - radius1_3, length1_3 / 2 + radius1_3, rTube2_3); transfoTube2_3->RegisterYourself(); TGeoVolume* Torus2_3 = gGeoManager->MakeTorus(Form("Torus2_3_H%d_D%d", half, disk), mPipe, radius1_3, rin, rout, 0., 90.); + TGeoVolume* TorusW2_3 = gGeoManager->MakeTorus(Form("TorusW2_3_H%d_D%d", half, disk), mWater, radius1_3, 0., rin, 0., 90.); TGeoRotation* rTorus2_3 = new TGeoRotation("rotationTorus2_3", 90.0, 90.0, 180.0); rTorus2_3->RegisterYourself(); TGeoCombiTrans* transfoTorus2_3 = new TGeoCombiTrans(0.0, -length2_3 - radius1_3, length1_3 / 2 + radius1_3 + radius1_3, rTorus2_3); @@ -3984,9 +4009,10 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Float_t length3_3; if (disk == 3) { - length3_3 = 4.73; + length3_3 = 4.4; } TGeoVolume* Tube3_3 = gGeoManager->MakeTube(Form("Tube3_3_H%d_D%d", half, disk), mPipe, rin, rout, length3_3 / 2); + TGeoVolume* TubeW3_3 = gGeoManager->MakeTube(Form("TubeW3_3_H%d_D%d", half, disk), mWater, 0., rin, length3_3 / 2); TGeoRotation* rTube3_3 = new TGeoRotation("rotationTube3_3", 0.0, 0.0, 0.0); rTube3_3->RegisterYourself(); TGeoCombiTrans* transfoTube3_3 = new TGeoCombiTrans(0., -length2_3 - radius1_3 - radius1_3, length1_3 / 2 + radius1_3 + radius1_3 + length3_3 / 2, rTube3_3); @@ -3997,15 +4023,21 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Tube2_3->SetLineColor(kGray); Torus2_3->SetLineColor(kGray); Tube3_3->SetLineColor(kGray); + TubeW3_3->SetLineColor(kBlue); mCoolingPipe3->AddNode(Tube1_3, 1, tTube1_3); mCoolingPipe3->AddNode(Torus1_3, 1, transfoTorus1_3); mCoolingPipe3->AddNode(Tube2_3, 1, transfoTube2_3); mCoolingPipe3->AddNode(Torus2_3, 1, transfoTorus2_3); mCoolingPipe3->AddNode(Tube3_3, 1, transfoTube3_3); + mCoolingPipe3->AddNode(TubeW1_3, 1, tTube1_3); + mCoolingPipe3->AddNode(TorusW1_3, 1, transfoTorus1_3); + mCoolingPipe3->AddNode(TubeW2_3, 1, transfoTube2_3); + mCoolingPipe3->AddNode(TorusW2_3, 1, transfoTorus2_3); + mCoolingPipe3->AddNode(TubeW3_3, 1, transfoTube3_3); TGeoCombiTrans* transfoCoolingPipe3_3 = nullptr; - TGeoRotation* rotation3_3 = new TGeoRotation("rotation3_3", 90., 90., 80.); + TGeoRotation* rotation3_3 = new TGeoRotation("rotation3_3", 90., 90., 76.); rotation3_3->RegisterYourself(); transfoCoolingPipe3_3 = new TGeoCombiTrans(17. + length1_3 / 2, 0.75, 0.0, rotation3_3); @@ -4028,6 +4060,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Tube2p_3->SetLineColor(kGray); Torus2p_3->SetLineColor(kGray); Tube3p_3->SetLineColor(kGray); + TubeW3p_3->SetLineColor(kBlue); mCoolingPipe4->AddNode(Tube1p_3, 1, tTube1_3); mCoolingPipe4->AddNode(Torus1p_3, 1, transfoTorus1_3); @@ -4041,7 +4074,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) mCoolingPipe4->AddNode(TubeW3p_3, 1, transfoTube3_3); TGeoCombiTrans* transfoCoolingPipe4_3 = nullptr; - TGeoRotation* rotation4_3 = new TGeoRotation("rotation4_3", 90., 90., -80.); + TGeoRotation* rotation4_3 = new TGeoRotation("rotation4_3", 90., 90., -76.); rotation4_3->RegisterYourself(); transfoCoolingPipe4_3 = new TGeoCombiTrans(17. + length1_3 / 2, -0.75, 0.0, rotation4_3); transfoCoolingPipe4_3->RegisterYourself(); @@ -4049,6 +4082,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) mHalfDisk->AddNode(mCoolingPipe3, 1, transfoCoolingPipe3_3); mHalfDisk->AddNode(mCoolingPipe4, 1, transfoCoolingPipe4_3); } + //================================================================= if (disk == 4) { // One diagonal side @@ -4069,10 +4103,10 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Float_t length2_4; if (disk == 4) { - length2_4 = 10.57; + length2_4 = 10.8; } TGeoVolume* Tube2_4 = gGeoManager->MakeTube("Tube2_4", mPipe, rin, rout, length2_4 / 2); - TGeoVolume* TubeW2_4 = gGeoManager->MakeTube("TubeW2_4", mPipe, 0., rin, length2_4 / 2); + TGeoVolume* TubeW2_4 = gGeoManager->MakeTube("TubeW2_4", mWater, 0., rin, length2_4 / 2); TGeoRotation* rTube2_4 = new TGeoRotation("rotationTube2_4", 180.0, 90.0, 90.0); rTube2_4->RegisterYourself(); TGeoCombiTrans* transfoTube2_4 = new TGeoCombiTrans(0., -length2_4 / 2 - radius1_4, length1_4 / 2 + radius1_4, rTube2_4); @@ -4087,7 +4121,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Float_t length3_4; if (disk == 4) { - length3_4 = 5.41; + length3_4 = 5.2; } TGeoVolume* Tube3_4 = gGeoManager->MakeTube(Form("Tube3_4_H%d_D%d", half, disk), mPipe, rin, rout, length3_4 / 2); TGeoVolume* TubeW3_4 = gGeoManager->MakeTube(Form("TubeW3_4_H%d_D%d", half, disk), mWater, 0., rin, length3_4 / 2); @@ -4101,6 +4135,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Tube2_4->SetLineColor(kGray); Torus2_4->SetLineColor(kGray); Tube3_4->SetLineColor(kGray); + TubeW3_4->SetLineColor(kBlue); mCoolingPipe3->AddNode(Tube1_4, 1, tTube1_4); mCoolingPipe3->AddNode(Torus1_4, 1, transfoTorus1_4); @@ -4136,6 +4171,7 @@ void HeatExchanger::createCoolingPipes(Int_t half, Int_t disk) Tube2p_4->SetLineColor(kGray); Torus2p_4->SetLineColor(kGray); Tube3p_4->SetLineColor(kGray); + TubeW3p_4->SetLineColor(kBlue); mCoolingPipe4->AddNode(Tube1p_4, 1, tTube1_4); mCoolingPipe4->AddNode(Torus1p_4, 1, transfoTorus1_4); diff --git a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx index 3d03a37899054..efa230c97e14d 100644 --- a/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx +++ b/Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx @@ -403,7 +403,7 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() TGeoCombiTrans* combtrans_water_torus_left3 = new TGeoCombiTrans("combtrans_water_torus_left3", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2 + water_pipe_side_position_radius, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - 2 * water_pipe_straight_tube_side2_length, -water_pipe_side_position_radius, rotate_water_torus_left3); combtrans_water_torus_left3->RegisterYourself(); - Float_t water_pipe_straight_tube_side3_length = 6; + Float_t water_pipe_straight_tube_side3_length = 5; TGeoTubeSeg* pipe_straight_tube_left3 = new TGeoTubeSeg("pipe_straight_tube_left3", water_pipe_inner_radius, water_pipe_outer_radius, water_pipe_straight_tube_side3_length, 0, 360); TGeoRotation* rotate_water_straight_tube_left3 = new TGeoRotation("rotate_water_straight_tube_left3", 0, 0, 0); TGeoCombiTrans* combtrans_water_straight_tube_side_left3 = new TGeoCombiTrans("combtrans_water_straight_tube_side_left3", +(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) + water_pipe_straight_tube_side1_length * 2 + water_pipe_side_position_radius, @@ -416,7 +416,7 @@ TGeoVolumeAssembly* PowerSupplyUnit::create() -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - 2 * water_pipe_straight_tube_side2_length, -water_pipe_side_position_radius, rotate_water_torus_rigth3); combtrans_water_torus_rigth3->RegisterYourself(); - TGeoTubeSeg* pipe_straight_tube_rigth3 = new TGeoTubeSeg("pipe_straight_tube_rigth3", 0, water_pipe_inner_radius, water_pipe_straight_tube_side3_length, 0, 360); + TGeoTubeSeg* pipe_straight_tube_rigth3 = new TGeoTubeSeg("pipe_straight_tube_rigth3", water_pipe_inner_radius, water_pipe_outer_radius, water_pipe_straight_tube_side3_length, 0, 360); TGeoRotation* rotate_water_straight_tube_rigth3 = new TGeoRotation("rotate_water_straight_tube_rigth3", 0, 0, 0); TGeoCombiTrans* combtrans_water_straight_tube_side_rigth3 = new TGeoCombiTrans("combtrans_water_straight_tube_side_rigth3", -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Cos((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - water_pipe_straight_tube_side1_length * 2 - water_pipe_side_position_radius, -(water_pipe_main_position_radius + water_pipe_side_position_radius) * TMath::Sin((90 - water_pipe_side_angle) * TMath::Pi() / 180.) - 2 * water_pipe_straight_tube_side2_length - water_pipe_side_position_radius, -water_pipe_straight_tube_side3_length - water_pipe_side_position_radius, rotate_water_straight_tube_rigth3); From 0fe332f79c6aca092b2299c5d203e973cf269987 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli <Chiara.Zampolli@cern.ch> Date: Thu, 10 Dec 2020 16:02:10 +0100 Subject: [PATCH 1643/1751] TOF DCS Processor Adding processing of LV info (FEAC). Processing also HV Configuring DPs for TOF either from CCDB or by hand. Macro included to create CCDB entry Preparing CCDB update Writing to CCDB Some updates and improvements more in the README, for LHCphase, ChannelOffset, TimeSlewing formatting of README formatting of README clang-format clang again update README add macro makeCCDBEntryForDCS.C to tests including algorithm shuffle instead of random_shuffle fix for macro test (hopefully) Fix for test Now it should work! Making CI happy from PR review turning test into executable typo fixed clang again clang --- Detectors/DCS/CMakeLists.txt | 6 + Detectors/DCS/src/DataPointGenerator.cxx | 16 +- Detectors/DCS/src/DetectorsDCSLinkDef.h | 1 + .../testWorkflow/DCSRandomDataGeneratorSpec.h | 68 ++- .../DCS/testWorkflow/dcs-sim-workflow.cxx | 35 ++ Detectors/TOF/CMakeLists.txt | 1 + Detectors/TOF/base/include/TOFBase/Geo.h | 1 + Detectors/TOF/base/src/Geo.cxx | 29 + Detectors/TOF/calibration/CMakeLists.txt | 12 +- .../include/TOFCalibration/TOFDCSProcessor.h | 160 +++++ .../TOF/calibration/macros/CMakeLists.txt | 15 + .../macros/makeCCDBEntryForDCS.cxx | 52 ++ .../calibration/src/TOFCalibrationLinkDef.h | 5 + .../TOF/calibration/src/TOFDCSProcessor.cxx | 561 ++++++++++++++++++ .../TOF/calibration/testWorkflow/README.md | 94 +++ .../testWorkflow/TOFDCSDataProcessorSpec.h | 176 ++++++ .../testWorkflow/tof-dcs-data-workflow.cxx | 41 ++ 17 files changed, 1256 insertions(+), 17 deletions(-) create mode 100644 Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx create mode 100644 Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h create mode 100644 Detectors/TOF/calibration/macros/CMakeLists.txt create mode 100644 Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx create mode 100644 Detectors/TOF/calibration/src/TOFDCSProcessor.cxx create mode 100644 Detectors/TOF/calibration/testWorkflow/README.md create mode 100644 Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h create mode 100644 Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx diff --git a/Detectors/DCS/CMakeLists.txt b/Detectors/DCS/CMakeLists.txt index 82e52dc169480..83da3d6cdc4bf 100644 --- a/Detectors/DCS/CMakeLists.txt +++ b/Detectors/DCS/CMakeLists.txt @@ -59,6 +59,12 @@ o2_add_executable( PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) +o2_add_executable( + sim-workflow + COMPONENT_NAME dcs + SOURCES testWorkflow/dcs-sim-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsDCS) + if(OpenMP_CXX_FOUND) target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) diff --git a/Detectors/DCS/src/DataPointGenerator.cxx b/Detectors/DCS/src/DataPointGenerator.cxx index 062d996452798..b0b64b550985a 100644 --- a/Detectors/DCS/src/DataPointGenerator.cxx +++ b/Detectors/DCS/src/DataPointGenerator.cxx @@ -13,6 +13,7 @@ #include "DetectorsDCS/DataPointCreator.h" #include "DetectorsDCS/DataPointCompositeObject.h" #include "DetectorsDCS/StringUtils.h" +#include "Framework/Logger.h" #include <fmt/format.h> #include <random> #include <utility> @@ -23,16 +24,27 @@ namespace { std::pair<uint32_t, uint16_t> getDate(const std::string& refDate) { + uint32_t seconds; if (refDate.empty()) { auto current = std::time(nullptr); auto t = std::localtime(¤t); - uint32_t seconds = mktime(t); + seconds = mktime(t); } else { std::tm t{}; std::istringstream ss(refDate); ss >> std::get_time(&t, "%Y-%b-%d %H:%M:%S"); - seconds = mktime(&t); + if (ss.fail()) { // let's see if it was passed as a TDatime + std::tm tt{}; + std::istringstream sss(refDate); + sss >> std::get_time(&tt, "%a %b %d %H:%M:%S %Y"); + if (sss.fail()) { + LOG(ERROR) << "We cannot parse the date"; + } + seconds = mktime(&tt); + } else { + seconds = mktime(&t); + } } uint16_t msec = 5; return std::make_pair(seconds, msec); diff --git a/Detectors/DCS/src/DetectorsDCSLinkDef.h b/Detectors/DCS/src/DetectorsDCSLinkDef.h index da9a282797cba..c5233fb26feef 100644 --- a/Detectors/DCS/src/DetectorsDCSLinkDef.h +++ b/Detectors/DCS/src/DetectorsDCSLinkDef.h @@ -21,5 +21,6 @@ #pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue> + ; #pragma link C++ function o2::dcs::expandAlias(const std::string&); #pragma link C++ function o2::dcs::expandAliases(const std::vector<std::string>&); +#pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, std::string> + ; #endif diff --git a/Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h b/Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h index 9874df180c2dc..51f09c2d7570d 100644 --- a/Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h +++ b/Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h @@ -18,9 +18,11 @@ #include "Framework/DeviceSpec.h" #include "Framework/Logger.h" #include "Framework/Task.h" +#include <TDatime.h> #include <random> #include <variant> #include <string> +#include <algorithm> using namespace o2::framework; @@ -54,9 +56,18 @@ using HintType = std::variant<DataPointHint<double>, std::vector<int> generateIntegers(size_t size, int min, int max) { std::uniform_int_distribution<int> distribution(min, max); - std::mt19937 generator; - std::vector<int> data(size); - std::generate(data.begin(), data.end(), [&]() { return distribution(generator); }); + std::mt19937 generator(std::random_device{}()); + std::vector<int> data; + while (data.size() != size) { + data.emplace_back(distribution(generator)); + std::sort(begin(data), end(data)); + auto last = std::unique(begin(data), end(data)); // make sure we do not duplicate + data.erase(last, end(data)); + } + std::shuffle(begin(data), end(data), generator); + for (auto i = 0; i < data.size(); ++i) { + LOG(INFO) << "Generating randomly DP at index " << data[i]; + } return data; } @@ -68,12 +79,20 @@ std::vector<int> generateIntegers(size_t size, int min, int max) * @returns a vector of DataPointCompositeObjects */ std::vector<o2::dcs::DataPointCompositeObject> generate(const std::vector<HintType> hints, - float fraction = 1.0) + float fraction = 1.0, + uint64_t tfid = 0) { std::vector<o2::dcs::DataPointCompositeObject> dataPoints; - auto GenerateVisitor = [](const auto& t) { - return o2::dcs::generateRandomDataPoints({t.aliasPattern}, t.minValue, t.maxValue); + TDatime d; + auto dsec = d.Convert(); + dsec += tfid; + d.Set(dsec); + + std::string refDate = d.AsString(); + + auto GenerateVisitor = [refDate](const auto& t) { + return o2::dcs::generateRandomDataPoints({t.aliasPattern}, t.minValue, t.maxValue, refDate); }; for (const auto& hint : hints) { @@ -84,7 +103,8 @@ std::vector<o2::dcs::DataPointCompositeObject> generate(const std::vector<HintTy } if (fraction < 1.0) { auto indices = generateIntegers(fraction * dataPoints.size(), 0, dataPoints.size() - 1); - auto tmp = dataPoints; + std::vector<o2::dcs::DataPointCompositeObject> tmp; + tmp.swap(dataPoints); dataPoints.clear(); for (auto i : indices) { dataPoints.push_back(tmp[i]); @@ -114,11 +134,29 @@ class DCSRandomDataGenerator : public o2::framework::Task mMaxCyclesNoFullMap = ic.options().get<int64_t>("max-cycles-no-full-map"); // create the list of DataPointHints to be used by the generator - mDataPointHints.emplace_back(DataPointHint<char>{"TestChar_0", 'A', 'z'}); + // each detector should create his own when running the tests + + /*mDataPointHints.emplace_back(DataPointHint<char>{"TestChar_0", 'A', 'z'}); mDataPointHints.emplace_back(DataPointHint<double>{"TestDouble_[0..3]", 0, 1700}); mDataPointHints.emplace_back(DataPointHint<int32_t>{"TestInt_[0..50000{:d}]", 0, 1234}); mDataPointHints.emplace_back(DataPointHint<bool>{"TestBool_[00..03]", 0, 1}); mDataPointHints.emplace_back(DataPointHint<std::string>{"TestString_0", "ABC", "ABCDEF"}); + */ + // for TOF + // for test, we use less DPs that official ones + mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_vp_[00..02]", 0, 50.}); + mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_vn_[00..02]", 0, 50.}); + mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_ip_[00..02]", 0, 50.}); + mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_in_[00..02]", 0, 50.}); + mTOFDataPointHints.emplace_back(DataPointHint<int32_t>{"TOF_FEACSTATUS_[00..01]", 0, 255}); + mTOFDataPointHints.emplace_back(DataPointHint<int32_t>{"TOF_HVSTATUS_SM[00..01]MOD[0..1]", 0, 524287}); + // for TOF, official list + //mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_vp_[00..89]", 0, 50.}); + //mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_vn_[00..89]", 0, 50.}); + //mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_ip_[00..89]", 0, 50.}); + //mTOFDataPointHints.emplace_back(DataPointHint<double>{"tof_hv_in_[00..89]", 0, 50.}); + //mTOFDataPointHints.emplace_back(DataPointHint<int32_t>{"TOF_FEACSTATUS_[00..71]", 0, 255}); + //mTOFDataPointHints.emplace_back(DataPointHint<int32_t>{"TOF_HVSTATUS_SM[00..17]MOD[0..4]", 0, 524287}); } void run(o2::framework::ProcessingContext& pc) final @@ -135,12 +173,13 @@ class DCSRandomDataGenerator : public o2::framework::Task // fraction is one if we generate FBI (Full Buffer Image) float fraction = (generateFBI ? 1.0 : mDeltaFraction); - auto dpcoms = generate(mDataPointHints, fraction); + TDatime d; + auto dpcoms = generate(mDataPointHints, fraction, tfid); + auto tofdpcoms = generate(mTOFDataPointHints, fraction, tfid); - // the output must always get both FBI and Delta, but one of them is empty. - std::vector<o2::dcs::DataPointCompositeObject> empty; - pc.outputs().snapshot(Output{"DCS", "DATAPOINTS", 0, Lifetime::Timeframe}, generateFBI ? dpcoms : empty); - pc.outputs().snapshot(Output{"DCS", "DATAPOINTSdelta", 0, Lifetime::Timeframe}, generateFBI ? empty : dpcoms); + LOG(INFO) << "***************** TF " << tfid << " has generated " << tofdpcoms.size() << " DPs for TOF"; + pc.outputs().snapshot(Output{"DCS", "DATAPOINTS", 0, Lifetime::Timeframe}, dpcoms); + pc.outputs().snapshot(Output{"DCS", "TOFDATAPOINTS", 0, Lifetime::Timeframe}, tofdpcoms); mTFs++; } @@ -150,6 +189,7 @@ class DCSRandomDataGenerator : public o2::framework::Task uint64_t mMaxCyclesNoFullMap; float mDeltaFraction; std::vector<HintType> mDataPointHints; + std::vector<HintType> mTOFDataPointHints; }; } // namespace @@ -159,7 +199,7 @@ DataProcessorSpec getDCSRandomDataGeneratorSpec() return DataProcessorSpec{ "dcs-random-data-generator", Inputs{}, - Outputs{{{"outputDCS"}, "DCS", "DATAPOINTS"}, {{"outputDCSdelta"}, "DCS", "DATAPOINTSdelta"}}, + Outputs{{{"outputDCS"}, "DCS", "DATAPOINTS"}, {{"outputDCSTOF"}, "DCS", "TOFDATAPOINTS"}}, AlgorithmSpec{adaptFromTask<DCSRandomDataGenerator>()}, Options{ {"max-timeframes", VariantType::Int64, 99999999999ll, {"max TimeFrames to generate"}}, diff --git a/Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx b/Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx new file mode 100644 index 0000000000000..b378578105ebf --- /dev/null +++ b/Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx @@ -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. + +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "Framework/TypeTraits.h" +#include <unordered_map> +#include "Framework/DataProcessorSpec.h" +#include "DCSRandomDataGeneratorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getDCSRandomDataGeneratorSpec()); + return specs; +} diff --git a/Detectors/TOF/CMakeLists.txt b/Detectors/TOF/CMakeLists.txt index 7ac94855f7b2d..3afd67c327f02 100644 --- a/Detectors/TOF/CMakeLists.txt +++ b/Detectors/TOF/CMakeLists.txt @@ -15,5 +15,6 @@ add_subdirectory(reconstruction) add_subdirectory(compression) if(BUILD_TESTING) add_subdirectory(prototyping) + add_subdirectory(calibration/macros) endif() add_subdirectory(workflow) diff --git a/Detectors/TOF/base/include/TOFBase/Geo.h b/Detectors/TOF/base/include/TOFBase/Geo.h index 66dcc3feea9e8..f98be5d4d012d 100644 --- a/Detectors/TOF/base/include/TOFBase/Geo.h +++ b/Detectors/TOF/base/include/TOFBase/Geo.h @@ -43,6 +43,7 @@ class Geo static void getPos(Int_t* det, Float_t* pos); static void getVolumePath(const Int_t* ind, Char_t* path); static Int_t getStripNumberPerSM(Int_t iplate, Int_t istrip); + static void getStripAndModule(Int_t iStripPerSM, Int_t& iplate, Int_t& istrip); // Return the module and strip per module corresponding to the strip number per SM static Float_t getAngles(Int_t iplate, Int_t istrip) { return ANGLES[iplate][istrip]; } static Float_t getHeights(Int_t iplate, Int_t istrip) { return HEIGHTS[iplate][istrip]; } diff --git a/Detectors/TOF/base/src/Geo.cxx b/Detectors/TOF/base/src/Geo.cxx index 79c12f697d934..6bad7895f0c09 100644 --- a/Detectors/TOF/base/src/Geo.cxx +++ b/Detectors/TOF/base/src/Geo.cxx @@ -723,3 +723,32 @@ Int_t Geo::getIndexFromEquipment(Int_t icrate, Int_t islot, Int_t ichain, Int_t { return 0; // to be implemented } + +void Geo::getStripAndModule(Int_t iStripPerSM, Int_t& iplate, Int_t& istrip) +{ + // + // Convert the serial number of the TOF strip number iStripPerSM [0,90] + // in module number iplate [0,4] and strip number istrip [0,14/18]. + // Copied from AliRoot TOF::AliTOFGeometry + // + + if (iStripPerSM < 0 || iStripPerSM >= NSTRIPC + NSTRIPB + NSTRIPA + NSTRIPB + NSTRIPC) { + iplate = -1; + istrip = -1; + } else if (iStripPerSM < NSTRIPC) { + iplate = 0; + istrip = iStripPerSM; + } else if (iStripPerSM >= NSTRIPC && iStripPerSM < NSTRIPC + NSTRIPB) { + iplate = 1; + istrip = iStripPerSM - NSTRIPC; + } else if (iStripPerSM >= NSTRIPC + NSTRIPB && iStripPerSM < NSTRIPC + NSTRIPB + NSTRIPA) { + iplate = 2; + istrip = iStripPerSM - NSTRIPC - NSTRIPB; + } else if (iStripPerSM >= NSTRIPC + NSTRIPB + NSTRIPA && iStripPerSM < NSTRIPC + NSTRIPB + NSTRIPA + NSTRIPB) { + iplate = 3; + istrip = iStripPerSM - NSTRIPC - NSTRIPB - NSTRIPA; + } else if (iStripPerSM >= NSTRIPC + NSTRIPB + NSTRIPA + NSTRIPB && iStripPerSM < NSTRIPC + NSTRIPB + NSTRIPA + NSTRIPB + NSTRIPC) { + iplate = 4; + istrip = iStripPerSM - NSTRIPC - NSTRIPB - NSTRIPA - NSTRIPB; + } +} diff --git a/Detectors/TOF/calibration/CMakeLists.txt b/Detectors/TOF/calibration/CMakeLists.txt index 75c7ce9d792a8..fc969a2108616 100644 --- a/Detectors/TOF/calibration/CMakeLists.txt +++ b/Detectors/TOF/calibration/CMakeLists.txt @@ -15,9 +15,11 @@ o2_add_library(TOFCalibration src/LHCClockCalibrator.cxx src/TOFChannelCalibrator.cxx src/TOFCalibCollector.cxx + src/TOFDCSProcessor.cxx PUBLIC_LINK_LIBRARIES O2::DataFormatsTOF O2::TOFBase O2::CCDB O2::DetectorsCalibration + O2::DetectorsDCS ROOT::Minuit ms_gsl::ms_gsl) @@ -28,7 +30,8 @@ o2_target_root_dictionary(TOFCalibration include/TOFCalibration/LHCClockCalibrator.h include/TOFCalibration/TOFChannelCalibrator.h include/TOFCalibration/TOFCalibCollector.h - include/TOFCalibration/CollectCalibInfoTOF.h) + include/TOFCalibration/CollectCalibInfoTOF.h + include/TOFCalibration/TOFDCSProcessor.h) o2_add_executable(data-generator-workflow @@ -73,3 +76,10 @@ o2_add_executable(tof-collect-calib-workflow PUBLIC_LINK_LIBRARIES O2::Framework O2::TOFCalibration O2::DetectorsCalibration) + +o2_add_executable(tof-dcs-workflow + COMPONENT_NAME calibration + SOURCES testWorkflow/tof-dcs-data-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::TOFCalibration + O2::DetectorsDCS) diff --git a/Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h b/Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h new file mode 100644 index 0000000000000..120e08a24ab49 --- /dev/null +++ b/Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h @@ -0,0 +1,160 @@ +// 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 DETECTOR_TOFDCSPROCESSOR_H_ +#define DETECTOR_TOFDCSPROCESSOR_H_ + +#include <memory> +#include <Rtypes.h> +#include <unordered_map> +#include <deque> +#include <numeric> +#include "Framework/Logger.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DeliveryType.h" +#include "CCDB/CcdbObjectInfo.h" +#include "CommonUtils/MemFileHelper.h" +#include "CCDB/CcdbApi.h" +#include <gsl/gsl> +#include "TOFBase/Geo.h" + +/// @brief Class to process DCS data points + +namespace o2 +{ +namespace tof +{ + +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; +using DPCOM = o2::dcs::DataPointCompositeObject; + +struct TOFDCSinfo { + std::pair<uint64_t, double> firstValue; // first value seen by the TOF DCS processor + std::pair<uint64_t, double> lastValue; // last value seen by the TOF DCS processor + std::pair<uint64_t, double> midValue; // mid value seen by the TOF DCS processor + std::pair<uint64_t, double> maxChange; // maximum variation seen by the TOF DCS processor + TOFDCSinfo() + { + firstValue = std::make_pair(0, -999999999); + lastValue = std::make_pair(0, -999999999); + midValue = std::make_pair(0, -999999999); + maxChange = std::make_pair(0, -999999999); + } + void makeEmpty() + { + firstValue.first = lastValue.first = midValue.first = maxChange.first = 0; + firstValue.second = lastValue.second = midValue.second = maxChange.second = -999999999; + } + void print() const; + + ClassDefNV(TOFDCSinfo, 1); +}; + +struct TOFFEACinfo { + std::array<int32_t, 6> stripInSM = {-1, -1, -1, -1, -1, -1}; + int32_t firstPadX = -1; + int32_t lastPadX = -1; +}; + +class TOFDCSProcessor +{ + + public: + using TFType = uint64_t; + using CcdbObjectInfo = o2::ccdb::CcdbObjectInfo; + using DQDoubles = std::deque<double>; + + static constexpr int NFEACS = 8; + + TOFDCSProcessor() = default; + ~TOFDCSProcessor() = default; + + void init(const std::vector<DPID>& pids); + + //int process(const std::vector<DPCOM>& dps); + int process(const gsl::span<const DPCOM> dps); + int processDP(const DPCOM& dpcom); + virtual uint64_t processFlags(uint64_t flag, const char* pid); + + void finalize(); + void getStripsConnectedToFEAC(int nDDL, int nFEAC, TOFFEACinfo& info) const; + void updateFEACCCDB(); + void updateHVCCDB(); + + const CcdbObjectInfo& getccdbDPsInfo() const { return mccdbDPsInfo; } + CcdbObjectInfo& getccdbDPsInfo() { return mccdbDPsInfo; } + const std::unordered_map<DPID, TOFDCSinfo>& getTOFDPsInfo() const { return mTOFDCS; } + + const CcdbObjectInfo& getccdbLVInfo() const { return mccdbLVInfo; } + CcdbObjectInfo& getccdbLVInfo() { return mccdbLVInfo; } + const std::bitset<Geo::NCHANNELS>& getLVStatus() const { return mFeac; } + const bool isLVUpdated() const { return mUpdateFeacStatus; } + + const CcdbObjectInfo& getccdbHVInfo() const { return mccdbHVInfo; } + CcdbObjectInfo& getccdbHVInfo() { return mccdbHVInfo; } + const std::bitset<Geo::NCHANNELS>& getHVStatus() const { return mHV; } + const bool isHVUpdated() const { return mUpdateHVStatus; } + + template <typename T> + void prepareCCDBobjectInfo(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, + const std::map<std::string, std::string>& md); + + void setTF(TFType tf) { mTF = tf; } + void useVerboseMode() { mVerbose = true; } + + private: + std::unordered_map<DPID, TOFDCSinfo> mTOFDCS; // this is the object that will go to the CCDB + std::unordered_map<DPID, bool> mPids; // contains all PIDs for the processor, the bool + // will be true if the DP was processed at least once + std::unordered_map<DPID, std::vector<DPVAL>> mDpsdoublesmap; // this is the map that will hold the DPs for the + // double type (voltages and currents) + + std::array<std::array<TOFFEACinfo, NFEACS>, Geo::kNDDL> mFeacInfo; // contains the strip/pad info per FEAC + std::array<std::bitset<8>, Geo::kNDDL> mPrevFEACstatus; // previous FEAC status + std::bitset<Geo::NCHANNELS> mFeac; // bitset with feac status per channel + bool mUpdateFeacStatus = false; // whether to update the FEAC status in CCDB or not + std::bitset<Geo::NCHANNELS> mHV; // bitset with HV status per channel + std::array<std::array<std::bitset<19>, Geo::NSECTORS>, Geo::NPLATES> mPrevHVstatus; // previous HV status + bool mUpdateHVStatus = false; // whether to update the HV status in CCDB or not + CcdbObjectInfo mccdbDPsInfo; + CcdbObjectInfo mccdbLVInfo; + CcdbObjectInfo mccdbHVInfo; + TFType mStartTF; // TF index for processing of first processed TF, used to store CCDB object + TFType mTF = 0; // TF index for processing, used to store CCDB object + bool mStartTFset = false; + + bool mVerbose = false; + + ClassDefNV(TOFDCSProcessor, 0); +}; + +template <typename T> +void TOFDCSProcessor::prepareCCDBobjectInfo(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, + const std::map<std::string, std::string>& md) +{ + + // prepare all info to be sent to CCDB for object obj + auto clName = o2::utils::MemFileHelper::getClassName(obj); + auto flName = o2::ccdb::CcdbApi::generateFileName(clName); + info.setPath(path); + info.setObjectType(clName); + info.setFileName(flName); + info.setStartValidityTimestamp(tf); + info.setEndValidityTimestamp(99999999999999); + info.setMetaData(md); +} + +} // namespace tof +} // namespace o2 + +#endif diff --git a/Detectors/TOF/calibration/macros/CMakeLists.txt b/Detectors/TOF/calibration/macros/CMakeLists.txt new file mode 100644 index 0000000000000..47348b684982f --- /dev/null +++ b/Detectors/TOF/calibration/macros/CMakeLists.txt @@ -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. + +o2_add_test( + make-CCDB-Entry-For-DCS + SOURCES makeCCDBEntryForDCS.cxx + COMPONENT_NAME tof + PUBLIC_LINK_LIBRARIES O2::DetectorsDCS O2::CCDB) diff --git a/Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx b/Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx new file mode 100644 index 0000000000000..e7d07c858dd9e --- /dev/null +++ b/Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx @@ -0,0 +1,52 @@ +// 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 <vector> +#include <string> +#include "TFile.h" +#include "CCDB/CcdbApi.h" +#include "DetectorsDCS/AliasExpander.h" +#include "DetectorsDCS/DeliveryType.h" +#include "DetectorsDCS/DataPointIdentifier.h" + +#include <unordered_map> +#include <chrono> + +using DPID = o2::dcs::DataPointIdentifier; + +int main(int argc, char* argv[]) //const std::string url = "http://localhost:8080") +{ + + std::string url(argv[0]); + // macro to populate CCDB for TOF with the configuration for DCS + std::unordered_map<DPID, std::string> dpid2DataDesc; + std::vector<std::string> aliases = {"tof_hv_vp_[00..89]", "tof_hv_vn_[00..89]", "tof_hv_ip_[00..89]", "tof_hv_in_[00..89]"}; + std::vector<std::string> aliasesInt = {"TOF_FEACSTATUS_[00..71]", "TOF_HVSTATUS_SM[00..01]MOD[0..1]"}; + std::vector<std::string> expaliases = o2::dcs::expandAliases(aliases); + std::vector<std::string> expaliasesInt = o2::dcs::expandAliases(aliasesInt); + + DPID dpidtmp; + for (size_t i = 0; i < expaliases.size(); ++i) { + DPID::FILL(dpidtmp, expaliases[i], o2::dcs::DeliveryType::RAW_DOUBLE); + dpid2DataDesc[dpidtmp] = "TOFDATAPOINTS"; + } + for (size_t i = 0; i < expaliasesInt.size(); ++i) { + DPID::FILL(dpidtmp, expaliasesInt[i], o2::dcs::DeliveryType::RAW_INT); + dpid2DataDesc[dpidtmp] = "TOFDATAPOINTS"; + } + + o2::ccdb::CcdbApi api; + api.init(url); // or http://localhost:8080 for a local installation + std::map<std::string, std::string> md; + long ts = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); + api.storeAsTFileAny(&dpid2DataDesc, "TOF/DCSconfig", md, ts); + + return 0; +} diff --git a/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h b/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h index 9b7043720f9f0..cdfabd09f3ae7 100644 --- a/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h +++ b/Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h @@ -33,4 +33,9 @@ #pragma link C++ class o2::calibration::TimeSlot < o2::tof::TOFCalibInfoSlot> + ; #pragma link C++ class o2::calibration::TimeSlotCalibration < o2::dataformats::CalibInfoTOF, o2::tof::TOFCalibInfoSlot> + ; +#pragma link C++ class std::bitset < o2::tof::Geo::NCHANNELS> + ; +#pragma link C++ struct std::pair < uint64_t, double> + ; +#pragma link C++ struct o2::tof::TOFDCSinfo + ; +#pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, o2::tof::TOFDCSinfo> + ; + #endif diff --git a/Detectors/TOF/calibration/src/TOFDCSProcessor.cxx b/Detectors/TOF/calibration/src/TOFDCSProcessor.cxx new file mode 100644 index 0000000000000..9908076fd1a69 --- /dev/null +++ b/Detectors/TOF/calibration/src/TOFDCSProcessor.cxx @@ -0,0 +1,561 @@ +// 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 <TOFCalibration/TOFDCSProcessor.h> +#include "Rtypes.h" +#include <deque> +#include <string> +#include <algorithm> +#include <iterator> +#include <cstring> +#include <bitset> + +using namespace o2::tof; +using namespace o2::dcs; + +using DeliveryType = o2::dcs::DeliveryType; +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; + +ClassImp(o2::tof::TOFDCSinfo); + +void TOFDCSinfo::print() const +{ + LOG(INFO) << "First Value: timestamp = " << firstValue.first << ", value = " << firstValue.second; + LOG(INFO) << "Last Value: timestamp = " << lastValue.first << ", value = " << lastValue.second; + LOG(INFO) << "Mid Value: timestamp = " << midValue.first << ", value = " << midValue.second; + LOG(INFO) << "Max Change: timestamp = " << maxChange.first << ", value = " << maxChange.second; +} + +//__________________________________________________________________ + +void TOFDCSProcessor::init(const std::vector<DPID>& pids) +{ + // fill the array of the DPIDs that will be used by TOF + // pids should be provided by CCDB + + for (const auto& it : pids) { + mPids[it] = false; + mTOFDCS[it].makeEmpty(); + } + + for (int iddl = 0; iddl < Geo::kNDDL; ++iddl) { + for (int ifeac = 0; ifeac < NFEACS; ++ifeac) { + getStripsConnectedToFEAC(iddl, ifeac, mFeacInfo[iddl][ifeac]); + } + } +} + +//__________________________________________________________________ + +int TOFDCSProcessor::process(const gsl::span<const DPCOM> dps) +{ + + // first we check which DPs are missing - if some are, it means that + // the delta map was sent + if (mVerbose) { + LOG(INFO) << "\n\n\nProcessing new TF\n-----------------"; + } + if (!mStartTFset) { + mStartTF = mTF; + mStartTFset = true; + } + + std::unordered_map<DPID, DPVAL> mapin; + for (auto& it : dps) { + mapin[it.id] = it.data; + } + for (auto& it : mPids) { + const auto& el = mapin.find(it.first); + if (el == mapin.end()) { + LOG(DEBUG) << "DP " << it.first << " not found in map"; + } else { + LOG(DEBUG) << "DP " << it.first << " found in map"; + } + } + + mUpdateFeacStatus = false; // by default, we do not foresee a new entry in the CCDB for the FEAC + mUpdateHVStatus = false; // by default, we do not foresee a new entry in the CCDB for the HV + + // now we process all DPs, one by one + for (const auto& it : dps) { + // we process only the DPs defined in the configuration + const auto& el = mPids.find(it.id); + if (el == mPids.end()) { + LOG(INFO) << "DP " << it.id << " not found in TOFDCSProcessor, we will not process it"; + continue; + } + processDP(it); + mPids[it.id] = true; + } + + if (mUpdateFeacStatus) { + updateFEACCCDB(); + } + + if (mUpdateHVStatus) { + updateHVCCDB(); + } + + return 0; +} + +//__________________________________________________________________ + +int TOFDCSProcessor::processDP(const DPCOM& dpcom) +{ + + // processing single DP + + auto& dpid = dpcom.id; + const auto& type = dpid.get_type(); + auto& val = dpcom.data; + if (mVerbose) { + if (type == RAW_DOUBLE) { + LOG(INFO); + LOG(INFO) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue<double>(dpcom); + } else if (type == RAW_INT) { + LOG(INFO); + LOG(INFO) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue<int32_t>(dpcom); + } + } + auto flags = val.get_flags(); + if (processFlags(flags, dpid.get_alias()) == 0) { + // now I need to access the correct element + if (type == RAW_DOUBLE) { + // for these DPs, we will store the first, last, mid value, plus the value where the maximum variation occurred + auto& dvect = mDpsdoublesmap[dpid]; + LOG(DEBUG) << "mDpsdoublesmap[dpid].size() = " << dvect.size(); + auto etime = val.get_epoch_time(); + if (dvect.size() == 0 || + etime != dvect.back().get_epoch_time()) { // we check + // that we did not get the + // same timestamp as the + // latest one + dvect.push_back(val); + } + } + + if (type == RAW_INT) { + // for these DPs, we need some processing + if (std::strstr(dpid.get_alias(), "FEACSTATUS") != nullptr) { // DP is FEACSTATUS + std::string aliasStr(dpid.get_alias()); + // extracting DDL number (regex is quite slow, using this way) + const auto offs = std::strlen("TOF_FEACSTATUS_"); + std::size_t const nn = aliasStr.find_first_of("0123456789", offs); + std::size_t const mm = aliasStr.find_first_not_of("0123456789", nn); + std::string ddlStr = aliasStr.substr(nn, mm != std::string::npos ? mm - nn : mm); + auto iddl = std::stoi(ddlStr); + std::bitset<8> feacstatus(o2::dcs::getValue<int32_t>(dpcom)); + if (mVerbose) { + LOG(INFO) << "DDL: " << iddl << ": Prev FEAC = " << mPrevFEACstatus[iddl] << ", new = " << feacstatus; + } + if (feacstatus == mPrevFEACstatus[iddl]) { + if (mVerbose) { + LOG(INFO) << "Same FEAC status as before, we do nothing"; + } + return 0; + } + if (mVerbose) { + LOG(INFO) << "Something changed in LV for DDL " << iddl << ", we need to check what"; + } + mUpdateFeacStatus = true; + int plate = -1, strip = -1; + int det[5] = {iddl / 4, -1, -1, -1, -1}; + for (auto ifeac = 0; ifeac < NFEACS; ++ifeac) { // we have one bit per FEAC + auto singlefeacstatus = feacstatus[ifeac]; + for (int istrip = 0; istrip < 6; ++istrip) { + if (mFeacInfo[iddl][ifeac].stripInSM[istrip] == -1) { + continue; + } + for (int ipadz = 0; ipadz < Geo::NPADZ; ++ipadz) { + for (int ipadx = mFeacInfo[iddl][ifeac].firstPadX; ipadx <= mFeacInfo[iddl][ifeac].lastPadX; ++ipadx) { + Geo::getStripAndModule(mFeacInfo[iddl][ifeac].stripInSM[istrip], plate, strip); + det[1] = plate; + det[2] = strip; + det[3] = ipadz; + det[4] = ipadx; + int channelIdx = Geo::getIndex(det); + if (mFeac[channelIdx] != singlefeacstatus) { + mFeac[channelIdx] = singlefeacstatus; + } + } + } + } + } // end loop on FEACs + if (mVerbose) { + LOG(INFO) << "Updating previous FEAC status for DDL " << iddl; + } + mPrevFEACstatus[iddl] = feacstatus; + } // end processing current DP, when it is of type FEACSTATUS + + if (std::strstr(dpid.get_alias(), "HVSTATUS") != nullptr) { // DP is HVSTATUS + std::string aliasStr(dpid.get_alias()); + // extracting SECTOR and PLATE number (regex is quite slow, using this way) + const auto offs = std::strlen("TOF_HVSTATUS_SM"); + std::size_t const nn = aliasStr.find_first_of("0123456789", offs); + std::size_t const mm = aliasStr.find_first_not_of("0123456789", nn); + std::size_t const oo = aliasStr.find_first_of("0123456789", mm); + std::size_t const pp = aliasStr.find_first_not_of("0123456789", oo); + std::string sectorStr = aliasStr.substr(nn, mm != std::string::npos ? mm - nn : mm); + auto isect = std::stoi(sectorStr); + std::string plateStr = aliasStr.substr(oo, pp != std::string::npos ? pp - oo : pp); + auto iplat = std::stoi(plateStr); + std::bitset<19> hvstatus(o2::dcs::getValue<int32_t>(dpcom)); + if (mVerbose) { + LOG(INFO) << "Sector: " << isect << ", plate = " << iplat << ": Prev HV = " + << mPrevHVstatus[iplat][isect] << ", new = " << hvstatus; + } + if (hvstatus == mPrevHVstatus[iplat][isect]) { + if (mVerbose) { + LOG(INFO) << "Same HV status as before, we do nothing"; + } + return 0; + } + if (mVerbose) { + LOG(INFO) << "Something changed in HV for Sect " << isect << " and plate " + << iplat << ", we need to check what"; + } + mUpdateHVStatus = true; + int det[5] = {isect, iplat, -1, -1, -1}; + auto nStrips = (iplat == 2 ? Geo::NSTRIPA : (iplat == 0 || iplat == 4) ? Geo::NSTRIPC : Geo::NSTRIPB); + for (auto istrip = 0; istrip < nStrips; ++istrip) { + auto singlestripHV = hvstatus[istrip]; + for (int ipadz = 0; ipadz < Geo::NPADZ; ++ipadz) { + for (int ipadx = 0; ipadx < Geo::NPADX; ++ipadx) { + det[2] = istrip; + det[3] = ipadz; + det[4] = ipadx; + int channelIdx = Geo::getIndex(det); + if (mHV[channelIdx] != singlestripHV) { + mHV[channelIdx] = singlestripHV; + } + } + } + } // end loop on strips + if (mVerbose) { + LOG(INFO) << "Updating previous HV status for Sector: " << isect << ", plate = " << iplat; + } + mPrevHVstatus[iplat][isect] = hvstatus; + } //end processing current DP, when it is of type HVSTATUS + } + } + return 0; +} + +//______________________________________________________________________ + +uint64_t TOFDCSProcessor::processFlags(const uint64_t flags, const char* pid) +{ + + // function to process the flag. the return code zero means that all is fine. + // anything else means that there was an issue + + // for now, I don't know how to use the flags, so I do nothing + + if (flags & DataPointValue::KEEP_ALIVE_FLAG) { + LOG(DEBUG) << "KEEP_ALIVE_FLAG active for DP " << pid; + } + if (flags & DataPointValue::END_FLAG) { + LOG(DEBUG) << "END_FLAG active for DP " << pid; + } + if (flags & DataPointValue::FBI_FLAG) { + LOG(DEBUG) << "FBI_FLAG active for DP " << pid; + } + if (flags & DataPointValue::NEW_FLAG) { + LOG(DEBUG) << "NEW_FLAG active for DP " << pid; + } + if (flags & DataPointValue::DIRTY_FLAG) { + LOG(DEBUG) << "DIRTY_FLAG active for DP " << pid; + } + if (flags & DataPointValue::TURN_FLAG) { + LOG(DEBUG) << "TURN_FLAG active for DP " << pid; + } + if (flags & DataPointValue::WRITE_FLAG) { + LOG(DEBUG) << "WRITE_FLAG active for DP " << pid; + } + if (flags & DataPointValue::READ_FLAG) { + LOG(DEBUG) << "READ_FLAG active for DP " << pid; + } + if (flags & DataPointValue::OVERWRITE_FLAG) { + LOG(DEBUG) << "OVERWRITE_FLAG active for DP " << pid; + } + if (flags & DataPointValue::VICTIM_FLAG) { + LOG(DEBUG) << "VICTIM_FLAG active for DP " << pid; + } + if (flags & DataPointValue::DIM_ERROR_FLAG) { + LOG(DEBUG) << "DIM_ERROR_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_DPID_FLAG) { + LOG(DEBUG) << "BAD_DPID_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_FLAGS_FLAG) { + LOG(DEBUG) << "BAD_FLAGS_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_TIMESTAMP_FLAG) { + LOG(DEBUG) << "BAD_TIMESTAMP_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_PAYLOAD_FLAG) { + LOG(DEBUG) << "BAD_PAYLOAD_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_FBI_FLAG) { + LOG(DEBUG) << "BAD_FBI_FLAG active for DP " << pid; + } + + return 0; +} + +//______________________________________________________________________ + +void TOFDCSProcessor::finalize() +{ + + // here we create the object to then be sent to CCDB + LOG(INFO) << "Finalizing"; + union Converter { + uint64_t raw_data; + double double_value; + } converter0, converter1; + + for (const auto& it : mPids) { + const auto& type = it.first.get_type(); + if (type == o2::dcs::RAW_DOUBLE) { + auto& tofdcs = mTOFDCS[it.first]; + if (it.second == true) { // we processed the DP at least 1x + auto& dpvect = mDpsdoublesmap[it.first]; + tofdcs.firstValue.first = dpvect[0].get_epoch_time(); + converter0.raw_data = dpvect[0].payload_pt1; + tofdcs.firstValue.second = converter0.double_value; + tofdcs.lastValue.first = dpvect.back().get_epoch_time(); + converter0.raw_data = dpvect.back().payload_pt1; + tofdcs.lastValue.second = converter0.double_value; + // now I will look for the max change + if (dpvect.size() > 1) { + auto deltatime = dpvect.back().get_epoch_time() - dpvect[0].get_epoch_time(); + if (deltatime < 60000) { + // if we did not cover at least 1 minute, + // max variation is defined as the difference between first and last value + converter0.raw_data = dpvect[0].payload_pt1; + converter1.raw_data = dpvect.back().payload_pt1; + double delta = std::abs(converter0.double_value - converter1.double_value); + tofdcs.maxChange.first = deltatime; // is it ok to do like this, as in Run 2? + tofdcs.maxChange.second = delta; + } else { + for (auto i = 0; i < dpvect.size() - 1; ++i) { + for (auto j = i + 1; j < dpvect.size(); ++j) { + auto deltatime = dpvect[j].get_epoch_time() - dpvect[i].get_epoch_time(); + if (deltatime >= 60000) { // we check every min; epoch_time in ms + converter0.raw_data = dpvect[i].payload_pt1; + converter1.raw_data = dpvect[j].payload_pt1; + double delta = std::abs(converter0.double_value - converter1.double_value); + if (delta > tofdcs.maxChange.second) { + tofdcs.maxChange.first = deltatime; // is it ok to do like this, as in Run 2? + tofdcs.maxChange.second = delta; + } + } + } + } + } + // mid point + auto midIdx = dpvect.size() / 2 - 1; + tofdcs.midValue.first = dpvect[midIdx].get_epoch_time(); + converter0.raw_data = dpvect[midIdx].payload_pt1; + tofdcs.midValue.second = converter0.double_value; + } else { + tofdcs.maxChange.first = dpvect[0].get_epoch_time(); + converter0.raw_data = dpvect[0].payload_pt1; + tofdcs.maxChange.second = converter0.double_value; + tofdcs.midValue.first = dpvect[0].get_epoch_time(); + converter0.raw_data = dpvect[0].payload_pt1; + tofdcs.midValue.second = converter0.double_value; + } + } + if (mVerbose) { + LOG(INFO) << "PID = " << it.first.get_alias(); + tofdcs.print(); + } + } + } + std::map<std::string, std::string> md; + prepareCCDBobjectInfo(mTOFDCS, mccdbDPsInfo, "TOF/DCSDPs", mStartTF, md); + + return; +} + +//______________________________________________________________________ + +void TOFDCSProcessor::updateFEACCCDB() +{ + + // we need to update a CCDB for the FEAC status --> let's prepare the CCDBInfo + + if (mVerbose) { + LOG(INFO) << "At least one FEAC changed status --> we will update CCDB"; + } + std::map<std::string, std::string> md; + prepareCCDBobjectInfo(mFeac, mccdbLVInfo, "TOF/LVStatus", mTF, md); + return; +} + +//______________________________________________________________________ + +void TOFDCSProcessor::updateHVCCDB() +{ + + // we need to update a CCDB for the HV status --> let's prepare the CCDBInfo + + if (mVerbose) { + LOG(INFO) << "At least one HV changed status --> we will update CCDB"; + } + std::map<std::string, std::string> md; + prepareCCDBobjectInfo(mHV, mccdbHVInfo, "TOF/HVStatus", mTF, md); + return; +} + +//_______________________________________________________________________ + +void TOFDCSProcessor::getStripsConnectedToFEAC(int nDDL, int nFEAC, TOFFEACinfo& info) const +{ + + // + // Taken from AliRoot/TOF/AliTOFLvHvDataPoints.cxx + // + // FEAC-strip mapping: + // return the strips and first PadX numbers + // connected to the FEAC number nFEAC in the crate number nDDL + // + + switch (nDDL % 4) { + case 0: + info.firstPadX = 0; + info.lastPadX = Geo::NPADX / 2 - 1; + + if (nFEAC <= 2) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC; + } + } else if (nFEAC == 3) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC; + } + } else if (nFEAC == 4) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 1; + } + } else if (nFEAC == 5) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 1; + } + } else if (nFEAC == 6) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 2; + } + } else if (nFEAC == 7) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 2; + } + } + + break; + case 1: + info.firstPadX = Geo::NPADX / 2; + info.lastPadX = Geo::NPADX - 1; + + if (nFEAC <= 2) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC; + } + } else if (nFEAC == 3) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC; + } + } else if (nFEAC == 4) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 1; + } + } else if (nFEAC == 5) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 1; + } + } else if (nFEAC == 6) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 1; + } + } else if (nFEAC == 7) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = ii + 6 * nFEAC - 2; + } + } + + break; + case 2: + info.firstPadX = Geo::NPADX / 2; + info.lastPadX = Geo::NPADX - 1; + + if (nFEAC <= 2) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC); + } + } else if (nFEAC == 3) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC); + } + } else if (nFEAC == 4) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 1); + } + } else if (nFEAC == 5) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 1); + } + } else if (nFEAC == 6) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 2); + } + } else if (nFEAC == 7) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 2); + } + } + + break; + case 3: + info.firstPadX = 0; + info.lastPadX = Geo::NPADX / 2 - 1; + + if (nFEAC <= 2) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC); + } + } else if (nFEAC == 3) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC); + } + } else if (nFEAC == 4) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 1); + } + } else if (nFEAC == 5) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 1); + } + } else if (nFEAC == 6) { + for (int ii = 0; ii < 5; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 1); + } + } else if (nFEAC == 7) { + for (int ii = 0; ii < 6; ++ii) { + info.stripInSM[ii] = 90 - (ii + 6 * nFEAC - 2); + } + } + + break; + } +} diff --git a/Detectors/TOF/calibration/testWorkflow/README.md b/Detectors/TOF/calibration/testWorkflow/README.md new file mode 100644 index 0000000000000..3b902da31a6da --- /dev/null +++ b/Detectors/TOF/calibration/testWorkflow/README.md @@ -0,0 +1,94 @@ +<!-- doxy +\page refDetectorsTOFtestWorkflow testWorkflow +/doxy --> + +# TOF calibration workflows + +## DCS DP processing: + +Local example workflow with local CCDB (running on port 8080) : + +This will read the list of DPs to be associated to TOF from CCDB (remove +`--use-ccdb-to-configure` if you don't want this, but use hardcoded +aliases. You can specify the path of CCDB also with `--ccdb-path`. +YOu can also specify to run in verbose mode (`--use-verbose-mode`) + +```shell +o2-dcs-sim-workflow --max-timeframes 3 --delta-fraction 0.5 -b | +o2-calibration-tof-dcs-workflow --use-ccdb-to-configure -b | +o2-calibration-ccdb-populator-workflow --ccdb-path="http://localhost:8080" -b +``` +To populate locally a DCS entry for the configuration, run the: + +`O2/Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.C` + +macro. + + +## LHC phase: + +This will process the LHC phase simulated by the Generator workflow + +```shell +LHC phase +o2-calibration-data-generator-workflow --lanes 10 --mean-latency 100000 --max-timeframes 500 | +o2-calibration-lhc-clockphase-workflow --tf-per-slot 20 | +o2-calibration-ccdb-populator-workflow --ccdb-path localhost:8080 +``` + +## TOF channel calibration: + +To obtain the TOF channel offsets (at end of processing). Input from simulation, but is should work if attached to reco+calib flow + +* simulating reading from ccdb, and using it, with "-b", in "test" mode --> to use this, we need an appropriate CCDB object in the CCDB + +```shell +o2-calibration-data-generator-workflow --lanes 10 --mean-latency 100000 --max-timeframes 500 --do-TOF-channel-calib --do-TOF-channel-calib-in-test-mode -b | +o2-testworkflows-tof-dummy-ccdb -b | +o2-calibration-tof-channel-calib-workflow --min-entries 50 --do-TOF-channel-calib-in-test-mode --use-ccdb -b | +o2-calibration-ccdb-populator-workflow --ccdb-path localhost:8080 -b +``` + +* simulating reading from ccdb, but not using it, with "-b", in "test" mode --> to use this, we need an appropriate CCDB object in the CCDB + +``` +o2-calibration-data-generator-workflow --lanes 10 --mean-latency 100000 --max-timeframes 500 --do-TOF-channel-calib --do-TOF-channel-calib-in-test-mode -b | +o2-testworkflows-tof-dummy-ccdb -b +| o2-calibration-tof-channel-calib-workflow --min-entries 50 --do-TOF-channel-calib-in-test-mode -b +| o2-calibration-ccdb-populator-workflow --ccdb-path localhost:8080 -b +``` + +* Using the workflow that has both LHCclockPhase and TOFChannelCalib; for now I can enable only one, or the CCDB populator will not work + +```shell +o2-calibration-data-generator-workflow --lanes 10 --mean-latency 100000 --max-timeframes 500 --do-TOF-channel-calib --do-TOF-channel-calib-in-test-mode -b | +o2-calibration-tof-dummy-ccdb-for-calib -b | +o2-calibration-tof-calib-workflow --do-channel-offset --min-entries 50 --do-TOF-channel-calib-in-test-mode -b | +o2-calibration-ccdb-populator-workflow --ccdb-path localhost:8080 -b +``` +* same as above, enabling CCDB + +```shell +o2-calibration-data-generator-workflow --lanes 10 --mean-latency 100000 --max-timeframes 500 --do-TOF-channel-calib --do-TOF-channel-calib-in-test-mode -b | +o2-calibration-tof-dummy-ccdb-for-calib -b | +o2-calibration-tof-calib-workflow --do-channel-offset --use-ccdb --min-entries 50 --do-TOF-channel-calib-in-test-mode -b | +o2-calibration-ccdb-populator-workflow --ccdb-path localhost:8080 -b +``` + +## TimeSlewing: + +For Time Slewing. Will save the Time Slewing information in files when a certain condition is reached. A post-processing +should then take care of extracting the CCDB + +* test mode: + +``` shell +o2-calibration-data-generator-workflow --lanes 10 --mean-latency 100000 --max-timeframes 10 -b | +o2-calibration-tof-collect-calib-workflow --tf-sending-policy --running-in-test-mode -b + +* non-test but simplified (using option "is-max-number-hits-to-fill-tree-absolute"): + +```shell +o2-calibration-data-generator-workflow --lanes 10 --mean-latency 100000 --max-timeframes 10 -b | +o2-calibration-tof-collect-calib-workflow --max-number-hits-to-fill-tree 300 --is-max-number-hits-to-fill-tree-absolute -b +``` \ No newline at end of file diff --git a/Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h b/Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h new file mode 100644 index 0000000000000..bf31e0397b40c --- /dev/null +++ b/Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h @@ -0,0 +1,176 @@ +// 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_TOF_DATAPROCESSOR_H +#define O2_TOF_DATAPROCESSOR_H + +/// @file DCSTOFDataProcessorSpec.h +/// @brief TOF Processor for DCS Data Points + +#include <unistd.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/DeliveryType.h" +#include "DetectorsDCS/AliasExpander.h" +#include "TOFCalibration/TOFDCSProcessor.h" +#include "DetectorsCalibration/Utils.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/DeviceSpec.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; +using DPCOM = o2::dcs::DataPointCompositeObject; +using namespace o2::ccdb; +using CcdbManager = o2::ccdb::BasicCCDBManager; +using clbUtils = o2::calibration::Utils; + +class TOFDCSDataProcessor : public o2::framework::Task +{ + public: + void init(o2::framework::InitContext& ic) final + { + + std::vector<DPID> vect; + bool useCCDBtoConfigure = ic.options().get<bool>("use-ccdb-to-configure"); + if (useCCDBtoConfigure) { + LOG(INFO) << "Configuring via CCDB"; + std::string ccdbpath = ic.options().get<std::string>("ccdb-path"); + auto& mgr = CcdbManager::instance(); + mgr.setURL(ccdbpath); + CcdbApi api; + api.init(mgr.getURL()); + long ts = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); + std::unordered_map<DPID, std::string>* dpid2DataDesc = mgr.getForTimeStamp<std::unordered_map<DPID, std::string>>("TOF/DCSconfig", ts); + for (auto& i : *dpid2DataDesc) { + vect.push_back(i.first); + } + } else { + LOG(INFO) << "Configuring via hardcoded strings"; + std::vector<std::string> aliases = {"tof_hv_vp_[00..89]", "tof_hv_vn_[00..89]", "tof_hv_ip_[00..89]", "tof_hv_in_[00..89]"}; + std::vector<std::string> aliasesInt = {"TOF_FEACSTATUS_[00..71]"}; + std::vector<std::string> expaliases = o2::dcs::expandAliases(aliases); + std::vector<std::string> expaliasesInt = o2::dcs::expandAliases(aliasesInt); + for (const auto& i : expaliases) { + vect.emplace_back(i, o2::dcs::RAW_DOUBLE); + } + for (const auto& i : expaliasesInt) { + vect.emplace_back(i, o2::dcs::RAW_INT); + } + } + + LOG(INFO) << "Listing Data Points for TOF:"; + for (auto& i : vect) { + LOG(INFO) << i; + } + + mProcessor = std::make_unique<o2::tof::TOFDCSProcessor>(); + bool useVerboseMode = ic.options().get<bool>("use-verbose-mode"); + LOG(INFO) << " ************************* Verbose?" << useVerboseMode; + if (useVerboseMode) { + mProcessor->useVerboseMode(); + } + mProcessor->init(vect); + } + + void run(o2::framework::ProcessingContext& pc) final + { + auto tfid = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime; + auto dps = pc.inputs().get<gsl::span<DPCOM>>("input"); + mProcessor->setTF(tfid); + mProcessor->process(dps); + sendOutput(pc.outputs()); + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + mProcessor->finalize(); + sendOutput(ec.outputs()); + const auto& payload = mProcessor->getTOFDPsInfo(); + auto& info = mProcessor->getccdbDPsInfo(); + auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); + LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + ec.outputs().snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); + ec.outputs().snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); + } + + private: + std::unique_ptr<TOFDCSProcessor> mProcessor; + + //________________________________________________________________ + void sendOutput(DataAllocator& output) + { + // extract CCDB infos and calibration objects, convert it to TMemFile and send them to the output + + if (mProcessor->isLVUpdated()) { + const auto& payload = mProcessor->getLVStatus(); + auto& info = mProcessor->getccdbLVInfo(); + auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); + LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); + } + if (mProcessor->isHVUpdated()) { + const auto& payload = mProcessor->getHVStatus(); + auto& info = mProcessor->getccdbHVInfo(); + auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); + LOG(INFO) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload, 0}, *image.get()); + output.snapshot(Output{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo, 0}, info); + } + } + +}; // end class +} // namespace tof + +namespace framework +{ + +DataProcessorSpec getTOFDCSDataProcessorSpec() +{ + + using clbUtils = o2::calibration::Utils; + + std::vector<OutputSpec> outputs; + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBPayload}); + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCLB, clbUtils::gDataDescriptionCLBInfo}); + + return DataProcessorSpec{ + "tof-dcs-data-processor", + Inputs{{"input", "DCS", "TOFDATAPOINTS"}}, + outputs, + AlgorithmSpec{adaptFromTask<o2::tof::TOFDCSDataProcessor>()}, + Options{{"ccdb-path", VariantType::String, "http://localhost:8080", {"Path to CCDB"}}, + {"use-ccdb-to-configure", VariantType::Bool, false, {"Use CCDB to configure"}}, + {"use-verbose-mode", VariantType::Bool, false, {"Use verbose mode"}}}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx b/Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx new file mode 100644 index 0000000000000..29826c1b66505 --- /dev/null +++ b/Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx @@ -0,0 +1,41 @@ +// 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 "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "Framework/TypeTraits.h" +#include <unordered_map> +namespace o2::framework +{ +template <> +struct has_root_dictionary<std::unordered_map<o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue>, void> : std::true_type { +}; +} // namespace o2::framework +#include "Framework/DataProcessorSpec.h" +#include "TOFDCSDataProcessorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getTOFDCSDataProcessorSpec()); + return specs; +} From cdb8943c3d5662ddf495bb7bbd39219a31321d75 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 17 Dec 2020 20:04:52 +0100 Subject: [PATCH 1644/1751] Tmp.fix in TrackParCov c-tor from Cartesian cov.matrix Avoid div. by 0 in case of neutral track. Math to check --- .../Reconstruction/src/TrackParametrizationWithError.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index 6ca0d1c57f180..3afb44d38edf6 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -377,9 +377,11 @@ GPUd() TrackParametrizationWithError<value_T>::TrackParametrizationWithError(con double m24 = pt * (cs - this->getSnp() * sn / r), m44 = -pt * pt * (r * sn + this->getSnp() * cs); double m35 = pt, m45 = -pt * pt * this->getTgl(); // - m43 *= charge; - m44 *= charge; - m45 *= charge; + if (charge) { // RS: this is a hack, proper treatment to be implemented + m43 *= charge; + m44 *= charge; + m45 *= charge; + } // double a1 = cv[13] - cv[9] * (m23 * m44 + m43 * m24) / m23 / m43; double a2 = m23 * m24 - m23 * (m23 * m44 + m43 * m24) / m43; From c2f6fbe33568155c6edf04bf3a62e34283f8ea1c Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Thu, 17 Dec 2020 20:10:40 +0100 Subject: [PATCH 1645/1751] Parent TrackPar/Cov creator for DCAFitterN --- .../include/DetectorsVertexing/DCAFitterN.h | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h index 3353526becf93..bfc6f7978ed7f 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h @@ -126,6 +126,12 @@ class DCAFitterN return mCandTr[mOrder[cand]][i]; } + ///< create parent track param with errors for decay vertex + o2::track::TrackParCov createParentTrackParCov(int cand = 0, bool sectorAlpha = true) const; + + ///< create parent track param w/o errors for decay vertex + o2::track::TrackPar createParentTrackPar(int cand = 0, bool sectorAlpha = true) const; + ///< calculate on the fly track param (no cov mat) at candidate, check isValid to make sure propagation was successful o2::track::TrackPar getTrackParamAtPCA(int i, int cand = 0) const; @@ -878,6 +884,64 @@ void DCAFitterN<N, Args...>::print() const LOG(INFO) << "Discard candidates for : Rvtx > " << getMaxR() << " DZ between tracks > " << mMaxDZIni; } +//___________________________________________________________________ +template <int N, typename... Args> +o2::track::TrackParCov DCAFitterN<N, Args...>::createParentTrackParCov(int cand, bool sectorAlpha) const +{ + const auto& trP = getTrack(0, cand); + const auto& trN = getTrack(1, cand); + const auto& wvtx = getPCACandidate(cand); + std::array<float, 21> covV = {0.}; + std::array<float, 3> pvecV = {0.}; + int q = 0; + for (int it = 0; it < N; it++) { + const auto& trc = getTrack(it, cand); + std::array<float, 3> pvecT = {0.}; + std::array<float, 21> covT = {0.}; + trc.getPxPyPzGlo(pvecT); + trc.getCovXYZPxPyPzGlo(covT); + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covV[MomInd[i]] += covT[MomInd[i]]; + } + for (int i = 0; i < 3; i++) { + pvecV[i] += pvecT[i]; + } + q += trc.getCharge(); + } + auto covVtxV = calcPCACovMatrix(cand); + covV[0] = covVtxV(0, 0); + covV[1] = covVtxV(1, 0); + covV[2] = covVtxV(1, 1); + covV[3] = covVtxV(2, 0); + covV[4] = covVtxV(2, 1); + covV[5] = covVtxV(2, 2); + const std::array<float, 3> vertex = {(float)wvtx[0], (float)wvtx[1], (float)wvtx[2]}; + return std::move(o2::track::TrackParCov(vertex, pvecV, covV, q, sectorAlpha)); +} + +//___________________________________________________________________ +template <int N, typename... Args> +o2::track::TrackPar DCAFitterN<N, Args...>::createParentTrackPar(int cand, bool sectorAlpha) const +{ + const auto& trP = getTrack(0, cand); + const auto& trN = getTrack(1, cand); + const auto& wvtx = getPCACandidate(cand); + std::array<float, 3> pvecV = {0.}; + int q = 0; + for (int it = 0; it < N; it++) { + const auto& trc = getTrack(it, cand); + std::array<float, 3> pvecT = {0.}; + trc.getPxPyPzGlo(pvecT); + for (int i = 0; i < 3; i++) { + pvecV[i] += pvecT[i]; + } + q += trc.getCharge(); + } + const std::array<float, 3> vertex = {(float)wvtx[0], (float)wvtx[1], (float)wvtx[2]}; + return std::move(o2::track::TrackPar(vertex, pvecV, q, sectorAlpha)); +} + using DCAFitter2 = DCAFitterN<2, o2::track::TrackParCov>; using DCAFitter3 = DCAFitterN<3, o2::track::TrackParCov>; From e2112a5463dc38916c16a93b49cf1b961800322e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 17 Dec 2020 23:26:14 +0100 Subject: [PATCH 1646/1751] Fix FindJAliEnROOT.cmake name --- dependencies/{FindJAlienROOT.cmake => FindJAliEnROOT.cmake} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dependencies/{FindJAlienROOT.cmake => FindJAliEnROOT.cmake} (100%) diff --git a/dependencies/FindJAlienROOT.cmake b/dependencies/FindJAliEnROOT.cmake similarity index 100% rename from dependencies/FindJAlienROOT.cmake rename to dependencies/FindJAliEnROOT.cmake From c91759083808dfe122a7afa9b3aa7efb41350ae7 Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Thu, 17 Dec 2020 18:09:26 +0100 Subject: [PATCH 1647/1751] Add --configKeyValue for MB LUT --- .../ITS/tracking/include/ITStracking/Tracker.h | 16 +++++++++++++--- .../include/ITStracking/TrackingConfigParam.h | 10 ++++++++-- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 10 ++++++++++ .../ITS/tracking/src/TrackingConfigParam.cxx | 4 +++- .../ITSMFT/ITS/tracking/src/TrackingLinkDef.h | 3 +++ .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 4 +++- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 37162676ef71d..78fc6064750f9 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -65,12 +65,15 @@ class Tracker std::vector<TrackITSExt>& getTracks(); auto& getTrackLabels() { return mTrackLabels; } + bool isMatLUT(); void clustersToTracks(const ROframe&, std::ostream& = std::cout); void setROFrame(std::uint32_t f) { mROFrame = f; } std::uint32_t getROFrame() const { return mROFrame; } void setParameters(const std::vector<MemoryParameters>&, const std::vector<TrackingParameters>&); + void initMatBudLUTFromFile(); + void getGlobalConfiguration(); private: track::TrackParCov buildTrackSeed(const Cluster& cluster1, const Cluster& cluster2, const Cluster& cluster3, @@ -111,9 +114,6 @@ inline void Tracker::setParameters(const std::vector<MemoryParameters>& memPars, { mMemParams = memPars; mTrkParams = trkPars; - if (mTrkParams[0].UseMatBudLUT) { - mMatLayerCylSet = o2::base::MatLayerCylSet::loadFromFile(); - } } inline float Tracker::getBz() const @@ -126,6 +126,16 @@ inline void Tracker::setBz(float bz) mBz = bz; } +inline void Tracker::initMatBudLUTFromFile() +{ + mMatLayerCylSet = o2::base::MatLayerCylSet::loadFromFile(); +} + +inline bool Tracker::isMatLUT() +{ + return mMatLayerCylSet; +} + template <typename... T> void Tracker::initialisePrimaryVertexContext(T&&... args) { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index eec5b41210e2b..deed8732f6ebd 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -19,7 +19,6 @@ namespace o2 namespace its { -class VertexingParameters; struct VertexerParamConfig : public o2::conf::ConfigurableParamHelper<VertexerParamConfig> { // geometrical cuts @@ -36,7 +35,14 @@ struct VertexerParamConfig : public o2::conf::ConfigurableParamHelper<VertexerPa O2ParamDef(VertexerParamConfig, "ITSVertexerParam"); }; -// VertexerParamConfig VertexerParamConfig::sInstance; +struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper<TrackerParamConfig> { + + // Use lookup table for mat. budget + bool useMatBudLUT = false; + + O2ParamDef(TrackerParamConfig, "ITSCATrackerParam"); +}; + } // namespace its } // namespace o2 #endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index add0998d82bb5..baacef4a26514 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -20,6 +20,7 @@ #include "ITStracking/Tracklet.h" #include "ITStracking/TrackerTraits.h" #include "ITStracking/TrackerTraitsCPU.h" +#include "ITStracking/TrackingConfigParam.h" #include "ReconstructionDataFormats/Track.h" #include <cassert> @@ -653,5 +654,14 @@ track::TrackParCov Tracker::buildTrackSeed(const Cluster& cluster1, const Cluste s2 * fy * cy, 0.f, s2 * cy * cy}); } +void Tracker::getGlobalConfiguration() +{ + auto& tc = o2::its::TrackerParamConfig::Instance(); + + if (tc.useMatBudLUT) { + initMatBudLUTFromFile(); + } +} + } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx index bcea094aab68b..c903b41843b1e 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx @@ -16,7 +16,9 @@ namespace o2 namespace its { static auto& sVertexerParamITS = o2::its::VertexerParamConfig::Instance(); +static auto& sCATrackerParamITS = o2::its::TrackerParamConfig::Instance(); -O2ParamImpl(o2::its::VertexerParamConfig) +O2ParamImpl(o2::its::VertexerParamConfig); +O2ParamImpl(o2::its::TrackerParamConfig); } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h index 95a586f24d241..80450e158932a 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h @@ -20,4 +20,7 @@ #pragma link C++ class o2::its::VertexerParamConfig + ; #pragma link C++ class o2::conf::ConfigurableParamHelper <o2::its::VertexerParamConfig> + ; +#pragma link C++ class o2::its::TrackerParamConfig + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper <o2::its::TrackerParamConfig> + ; + #endif diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 7f29a4bb0e0cb..166f04419044b 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -79,7 +79,9 @@ void TrackerDPL::init(InitContext& ic) LOG(INFO) << "Initializing tracker in async. phase reconstruction with " << trackParams.size() << " passes"; } mVertexer->getGlobalConfiguration(); - // mVertexer->dumpTraits(); + mTracker->getGlobalConfiguration(); + LOG(INFO) << Form("%ssing lookup table for material budget approximation", (mTracker->isMatLUT() ? "U" : "Not u")); + double origD[3] = {0., 0., 0.}; mTracker->setBz(field->getBz(origD)); } else { From 04738cb4b924bebcc199c93dc259402f2a3aef71 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 18 Dec 2020 10:19:14 +0100 Subject: [PATCH 1648/1751] DPL: Use JAliEn:JAliEn rather than XRootD::Client to enable support --- Framework/AnalysisSupport/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/AnalysisSupport/CMakeLists.txt b/Framework/AnalysisSupport/CMakeLists.txt index ceed68342364c..f4eab0b534731 100644 --- a/Framework/AnalysisSupport/CMakeLists.txt +++ b/Framework/AnalysisSupport/CMakeLists.txt @@ -11,7 +11,7 @@ # Given GCC 7.3 does not provide std::filesystem we use Boost instead # Drop this once we move to GCC 8.2+ -if(TARGET XRootD::Client) +if(TARGET JAliEn::JAliEn) set(EXTRA_TARGETS XRootD::Client JAliEn::JAliEn) endif() From 743159485614ec35a3fa973d2c5de5c1e20df036 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Fri, 18 Dec 2020 18:34:44 +0100 Subject: [PATCH 1649/1751] MFT: fix lanes mapping for decoding commissionning data and for working also with MC, both MFT and ITS --- Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx | 4 +--- .../ITSMFTReconstruction/ChipMappingITS.h | 3 +++ .../ITSMFTReconstruction/ChipMappingMFT.h | 14 ++++++++++++-- .../common/reconstruction/src/ChipMappingMFT.cxx | 4 +++- .../common/simulation/src/MC2RawEncoder.cxx | 16 ++++++++-------- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx b/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx index 4158628616e16..d7ccb8e6e50eb 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx @@ -228,7 +228,6 @@ void setupLinks(o2::itsmft::MC2RawEncoder<MAP>& m2r, std::string_view outDir, st int ruID = nRUtot++; bool accept = !(ruSW < m2r.getRUSWMin() || ruSW > m2r.getRUSWMax()); // ignored RUs ? - int accL = 0; if (accept) { m2r.getCreateRUDecode(ruSW); // create RU container nRU++; @@ -237,12 +236,11 @@ void setupLinks(o2::itsmft::MC2RawEncoder<MAP>& m2r, std::string_view outDir, st uint32_t lanes = mp.getCablesOnRUType(ru.ruInfo->ruType); // lanes patter of this RU ru.links[0] = m2r.addGBTLink(); auto link = m2r.getGBTLink(ru.links[0]); - link->lanes = lanes & ((0x1 << lnkAs) - 1) << (accL); + link->lanes = lanes; link->idInCRU = linkID; link->cruID = cruIDtmp * 100 + o2::detectors::DetID::MFT; link->feeID = mp.RUSW2FEEId(ruSW); link->endPointID = 0; // 0 or 1 - accL += lnkAs; // register the link in the writer, if not done here, its data will be dumped to common default file //printf("Register link: FeeID 0x%02x , CRU ID 0x%x , link ID %2d \n", link->feeID, link->cruID, link->idInCRU); //printf("RU SW: %2d HW: 0x%02x Type: %2d %s \n", ruSW, ruHW, ruType, outFileLink.data()); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h index feafb6298bf23..3090224312f34 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h @@ -172,6 +172,9 @@ class ChipMappingITS ///< convert HW cable ID to SW ID for given RU type (see ChipOnRUInfo.cableSW explanation) uint8_t cableHW2SW(uint8_t ruType, uint8_t hwid) const { return mCableHW2SW[ruType][hwid]; } + ///< convert cable iterator ID to the position on the ActiveLanes word in the GBT.header for given RU type; MFT lanes position compatible + uint8_t cablePos(uint8_t ruType, uint8_t id) const { return id; } + ///< get number of chips served by single cable on given RU type int getNChipsPerCable(int ruType) { return NChipsPerCableSB[ruType]; } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h index e87c5b44be6c2..9232ff0df8419 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h @@ -108,6 +108,9 @@ class ChipMappingMFT ///< convert HW cable ID to SW ID for give RU type uint8_t cableHW2SW(uint8_t ruType, uint8_t hwid) const { return mCableHW2SW[ruType][hwid]; } + ///< convert cable iterator ID to its position on the ActiveLanes word in the GBT.header for given RU type + uint8_t cablePos(uint8_t ruType, uint8_t id) const { return mCablePos[ruType][id]; } + ///< get chip global SW ID from chipID on module, cable SW ID and stave (RU) info uint16_t getGlobalChipID(uint16_t chOnModuleHW, int cableHW, const RUInfo& ruInfo) const { @@ -198,8 +201,14 @@ class ChipMappingMFT static constexpr std::int16_t getRUDetectorField() { return 0x0; } - ///< get pattern of lanes on the RU served by a given RU type - Int_t getCablesOnRUType(Int_t ruType) const { return (0x1 << NChipsOnRUType[ruType]) - 1; } + uint32_t getCablesOnRUType(Int_t ruType) const + { + uint32_t pattern = 0; + for (Int_t i = 0; i < NRUCables; i++) { + pattern |= (0x1 << mCableHW2Pos[ruType][i]); + } + return pattern; + } ///< get info on sw RU const RUInfo* getRUInfoSW(int ruSW) const { return &mRUInfo[ruSW]; } @@ -277,6 +286,7 @@ class ChipMappingMFT std::vector<uint8_t> mCableHW2SW[NRUs]; ///< table of cables HW to SW conversion for each RU type std::vector<uint8_t> mCableHW2Pos[NRUs]; ///< table of cables positions in the ActiveLanes mask for each RU type + std::vector<uint8_t> mCablePos[NRUs]; ///< reverse table of cables positions in the ActiveLanes mask for each RU type std::vector<uint8_t> mCableHWFirstChip[NRUs]; ///< 1st chip of module (relative to the 1st chip of the stave) served by each cable std::array<std::vector<uint16_t>, NRUs> mRUGlobalChipID; diff --git a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx index 5f777fc8c3faf..b59a1ca99b26a 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx @@ -1652,6 +1652,7 @@ ChipMappingMFT::ChipMappingMFT() mChipInfoEntryRU[iRU] = ctrChip; mCableHW2SW[iRU].resize(NRUCables, 0xff); mCableHW2Pos[iRU].resize(NRUCables, 0xff); + mCablePos[iRU].resize(NRUCables, 0xff); mCableHWFirstChip[iRU].resize(NRUCables, 0xff); } else { if ((layer != curLayer) || (zone != curZone) || (half != curHalf)) { @@ -1676,10 +1677,11 @@ ChipMappingMFT::ChipMappingMFT() chInfo.cableHW = ChipConnectorCable[chInfo.moduleHW][chInfo.chipOnModuleSW]; chInfo.cableSW = chipOnRU; - chInfo.cableHWPos = chipOnRU; + chInfo.cableHWPos = chInfo.cableHW; chInfo.chipOnCable = 0; + mCablePos[iRU][chInfo.id] = chInfo.cableHWPos; mCableHW2Pos[iRU][chInfo.cableHW] = chInfo.cableHWPos; mCableHW2SW[iRU][chInfo.cableHW] = chInfo.cableSW; mCableHWFirstChip[iRU][chInfo.cableHW] = 0; diff --git a/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx b/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx index adee01a9a9c34..d7e97d515ca39 100644 --- a/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx +++ b/Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx @@ -180,8 +180,8 @@ void MC2RawEncoder<Mapping>::fillGBTLinks(RUDecodeData& ru) // estimate real payload size in GBT words int nPayLoadWordsNeeded = 0; // number of payload words filled to link buffer (RDH not included) for current IR for (int icab = ru.nCables; icab--;) { // calculate number of GBT words per link - if ((link->lanes & (0x1 << icab))) { - int nb = ru.cableData[icab].getSize(); + if ((link->lanes & (0x1 << mMAP.cablePos(ru.ruInfo->ruType, icab)))) { + int nb = ru.cableData[mMAP.cablePos(ru.ruInfo->ruType, icab)].getSize(); nPayLoadWordsNeeded += nb ? 1 + (nb - 1) / 9 : 0; // single GBT word carries at most 9 payload bytes } } @@ -195,8 +195,8 @@ void MC2RawEncoder<Mapping>::fillGBTLinks(RUDecodeData& ru) while (hasData) { hasData = false; for (int icab = 0; icab < ru.nCables; icab++) { - if ((link->lanes & (0x1 << icab))) { - auto& cableData = ru.cableData[icab]; + if ((link->lanes & (0x1 << mMAP.cablePos(ru.ruInfo->ruType, icab)))) { + auto& cableData = ru.cableData[mMAP.cablePos(ru.ruInfo->ruType, icab)]; int nb = cableData.getUnusedSize(); if (!nb) { continue; // write 80b word only if there is something to write @@ -204,10 +204,10 @@ void MC2RawEncoder<Mapping>::fillGBTLinks(RUDecodeData& ru) if (nb > 9) { nb = 9; } - int gbtWordStart = link->data.getSize(); // beginning of the current GBT word in the link - link->data.addFast(cableData.getPtr(), nb); // fill payload of cable - link->data.addFast(zero16, GBTPaddedWordLength - nb); // fill the rest of the GBT word by 0 - link->data[gbtWordStart + 9] = mMAP.getGBTHeaderRUType(ru.ruInfo->ruType, ru.cableHWID[icab]); // set cable flag + int gbtWordStart = link->data.getSize(); // beginning of the current GBT word in the link + link->data.addFast(cableData.getPtr(), nb); // fill payload of cable + link->data.addFast(zero16, GBTPaddedWordLength - nb); // fill the rest of the GBT word by 0 + link->data[gbtWordStart + 9] = mMAP.getGBTHeaderRUType(ru.ruInfo->ruType, ru.cableHWID[mMAP.cablePos(ru.ruInfo->ruType, icab)]); // set cable flag cableData.setPtr(cableData.getPtr() + nb); hasData = true; } // storing data of single cable From bbb9823c8f7f378556a75676d9ca3ca5e8942cc6 Mon Sep 17 00:00:00 2001 From: ddobrigk <david.dobrigkeit.chinellato@cern.ch> Date: Sat, 19 Dec 2020 19:20:44 -0300 Subject: [PATCH 1650/1751] Add X at minimum to v0data table (#5084) --- .../DataModel/include/AnalysisDataModel/StrangenessTables.h | 3 +++ Analysis/Tasks/PWGLF/lambdakzerofinder.cxx | 1 + Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 1 + 3 files changed, 5 insertions(+) diff --git a/Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h b/Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h index 5fec469426c39..46701b83488f6 100644 --- a/Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h +++ b/Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h @@ -23,6 +23,8 @@ DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, FullTracks, "fNegTrackID" DECLARE_SOA_INDEX_COLUMN(Collision, collision); //General V0 properties: position, momentum +DECLARE_SOA_COLUMN(PosX, posX, float); +DECLARE_SOA_COLUMN(NegX, negX, float); DECLARE_SOA_COLUMN(PxPos, pxpos, float); DECLARE_SOA_COLUMN(PyPos, pypos, float); DECLARE_SOA_COLUMN(PzPos, pzpos, float); @@ -68,6 +70,7 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, float, 1.f * aod::v0data::pzpos + 1.f * ao DECLARE_SOA_TABLE(V0Data, "AOD", "V0DATA", o2::soa::Index<>, v0data::PosTrackId, v0data::NegTrackId, v0data::CollisionId, + v0data::PosX, v0data::NegX, v0data::X, v0data::Y, v0data::Z, v0data::PxPos, v0data::PyPos, v0data::PzPos, v0data::PxNeg, v0data::PyNeg, v0data::PzNeg, diff --git a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx index 9250dd6a7d1e2..f71b9347bc3b4 100644 --- a/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzerofinder.cxx @@ -194,6 +194,7 @@ struct lambdakzerofinder { lNCand++; v0data(t0.globalIndex(), t1.globalIndex(), t0.collisionId(), + fitter.getTrack(0).getX(), fitter.getTrack(1).getX(), pos[0], pos[1], pos[2], pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index 8095f8810021a..475f88d72113f 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -197,6 +197,7 @@ struct lambdakzeroproducer { V0.posTrack_as<FullTracksExt>().globalIndex(), V0.negTrack_as<FullTracksExt>().globalIndex(), V0.negTrack_as<FullTracksExt>().collisionId(), + fitter.getTrack(0).getX(), fitter.getTrack(1).getX(), pos[0], pos[1], pos[2], pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], From 1be7b8cf5f8e9fd80deca83aae8eb413bd006715 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu <Bogdan.Vulpescu@clermont.in2p3.fr> Date: Tue, 15 Dec 2020 12:52:28 +0100 Subject: [PATCH 1651/1751] MFT: eliminate sqrt where possible --- .../tracking/include/MFTTracking/Tracker.h | 10 +++++----- .../include/MFTTracking/TrackerConfig.h | 2 ++ Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx | 20 +++++++++---------- .../ITSMFT/MFT/tracking/src/TrackerConfig.cxx | 4 ++++ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h index 76f8b0d71a8f6..e67ec732334f8 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h @@ -117,7 +117,7 @@ inline const Float_t Tracker::getDistanceToSeed(const Cluster& cluster1, const C { // the seed is between "cluster1" and "cluster2" and cuts the plane // of the "cluster" at a distance dR from it - Float_t dxSeed, dySeed, dzSeed, invdzSeed, dz, dR, xSeed, ySeed; + Float_t dxSeed, dySeed, dzSeed, invdzSeed, dz, dR2, xSeed, ySeed; dxSeed = cluster2.getX() - cluster1.getX(); dySeed = cluster2.getY() - cluster1.getY(); dzSeed = cluster2.getZ() - cluster1.getZ(); @@ -125,8 +125,8 @@ inline const Float_t Tracker::getDistanceToSeed(const Cluster& cluster1, const C invdzSeed = dz / dzSeed; xSeed = cluster1.getX() + dxSeed * invdzSeed; ySeed = cluster1.getY() + dySeed * invdzSeed; - dR = std::sqrt((cluster.getX() - xSeed) * (cluster.getX() - xSeed) + (cluster.getY() - ySeed) * (cluster.getY() - ySeed)); - return dR; + dR2 = (cluster.getX() - xSeed) * (cluster.getX() - xSeed) + (cluster.getY() - ySeed) * (cluster.getY() - ySeed); + return dR2; } //_________________________________________________________________________________________________ @@ -165,9 +165,9 @@ inline const Bool_t Tracker::getCellsConnect(const Cell& cell1, const Cell& cell Float_t cell2y1 = cell2.getY1(); Float_t dx = cell1x2 - cell2x1; Float_t dy = cell1y2 - cell2y1; - Float_t dr = std::sqrt(dx * dx + dy * dy); + Float_t dr2 = dx * dx + dy * dy; - if (dr > constants::mft::Resolution) { + if (dr2 > (constants::mft::Resolution * constants::mft::Resolution)) { return kFALSE; } return kTRUE; diff --git a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h index b36de0be1b9b3..8b75506dd5c21 100644 --- a/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h +++ b/Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h @@ -41,7 +41,9 @@ class TrackerConfig Int_t mMinTrackStationsLTF = 4; Int_t mMinTrackStationsCA = 4; Float_t mLTFclsRCut = 0.0100; + Float_t mLTFclsR2Cut = 0.0100 * 0.0100; Float_t mROADclsRCut = 0.0400; + Float_t mROADclsR2Cut = 0.0400 * 0.0400; Int_t mLTFseed2BinWin = 3; Int_t mLTFinterBinWin = 3; Int_t mRBins = 50; diff --git a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx index da3f2c26f8798..1fe47aa36e96a 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx @@ -188,7 +188,7 @@ void Tracker::findTracksLTF(ROframe& event) Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; Int_t extClsIndex; - Float_t dR, dRmin, dRcut = mLTFclsRCut; + Float_t dR2, dR2min, dR2cut = mLTFclsR2Cut; Bool_t hasDisk[constants::mft::DisksNumber], newPoint, seed; Int_t clsInLayer1, clsInLayer2, clsInLayer; @@ -247,7 +247,7 @@ void Tracker::findTracksLTF(ROframe& event) newPoint = kTRUE; // loop over the bins in the search window - dRmin = dRcut; + dR2min = dR2cut; for (auto& bin : mBins[layer1][layer - 1][cluster1.indexTableBin]) { getBinClusterRange(event, layer, bin, clsMinIndex, clsMaxIndex); @@ -259,12 +259,12 @@ void Tracker::findTracksLTF(ROframe& event) } clsInLayer = it - event.getClustersInLayer(layer).begin(); - dR = getDistanceToSeed(cluster1, cluster2, cluster); - // retain the closest point within a radius dRcut - if (dR >= dRmin) { + dR2 = getDistanceToSeed(cluster1, cluster2, cluster); + // retain the closest point within a radius dR2cut + if (dR2 >= dR2min) { continue; } - dRmin = dR; + dR2min = dR2; if (newPoint) { trackPoints[nPoints].layer = layer; @@ -339,7 +339,7 @@ void Tracker::findTracksCA(ROframe& event) Int_t roadId, nPointDisks; Int_t binR_proj, binPhi_proj, bin; Int_t binIndex, clsMinIndex, clsMaxIndex, clsMinIndexS, clsMaxIndexS; - Float_t dR, dRcut = mROADclsRCut; + Float_t dR2, dR2cut = mROADclsR2Cut; Bool_t hasDisk[constants::mft::DisksNumber]; Int_t clsInLayer1, clsInLayer2, clsInLayer; @@ -392,9 +392,9 @@ void Tracker::findTracksCA(ROframe& event) } clsInLayer = it - event.getClustersInLayer(layer).begin(); - dR = getDistanceToSeed(cluster1, cluster2, cluster); - // add all points within a radius dRcut - if (dR >= dRcut) { + dR2 = getDistanceToSeed(cluster1, cluster2, cluster); + // add all points within a radius dR2cut + if (dR2 >= dR2cut) { continue; } diff --git a/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx b/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx index f1ee9b531a2fa..af0384b308ad1 100644 --- a/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx +++ b/Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx @@ -23,7 +23,9 @@ o2::mft::TrackerConfig::TrackerConfig() mMinTrackStationsLTF{4}, mMinTrackStationsCA{4}, mLTFclsRCut{0.0100}, + mLTFclsR2Cut{0.0100 * 0.0100}, mROADclsRCut{0.0400}, + mROADclsR2Cut{0.0400 * 0.0400}, mLTFseed2BinWin{3}, mLTFinterBinWin{3}, mRBins{50}, @@ -47,7 +49,9 @@ void o2::mft::TrackerConfig::initialize(const MFTTrackingParam& trkParam) mMinTrackStationsLTF = trkParam.MinTrackStationsLTF; mMinTrackStationsCA = trkParam.MinTrackStationsCA; mLTFclsRCut = trkParam.LTFclsRCut; + mLTFclsR2Cut = mLTFclsRCut * mLTFclsRCut; mROADclsRCut = trkParam.ROADclsRCut; + mROADclsR2Cut = mROADclsRCut * mROADclsRCut; mLTFseed2BinWin = trkParam.LTFseed2BinWin; mLTFinterBinWin = trkParam.LTFinterBinWin; From ea5fd7cadfbca09ac1848032b73fa439950bfcf8 Mon Sep 17 00:00:00 2001 From: AllaMaevskaya <Alla.Maevskaya@cern.ch> Date: Tue, 22 Dec 2020 22:07:33 +0100 Subject: [PATCH 1652/1751] real LUT in CCDB (#5089) * real LUT * printout --- DataFormats/Detectors/FIT/FT0/CMakeLists.txt | 2 + .../FT0/include/DataFormatsFT0/LookUpTable.h | 123 +++++++++- .../FT0/include/DataFormatsFT0/RawEventData.h | 2 +- .../FIT/FT0/src/DataFormatsFT0LinkDef.h | 2 + .../FIT/FT0/base/files/FT0ChannelsTable.txt | 225 ++++++++++++++++++ .../FIT/FT0/base/files/Sim2DataChannels.txt | 2 + .../FIT/FT0/base/include/FT0Base/Geometry.h | 2 + Detectors/FIT/FT0/base/src/Geometry.cxx | 4 +- .../FT0/raw/include/FT0Raw/RawReaderFT0Base.h | 6 +- Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx | 4 +- .../include/FT0Reconstruction/ReadRaw.h | 15 +- .../FIT/FT0/reconstruction/src/ReadRaw.cxx | 4 +- Detectors/FIT/FT0/simulation/CMakeLists.txt | 2 + .../include/FT0Simulation/Detector.h | 6 +- .../include/FT0Simulation/Digits2Raw.h | 15 +- Detectors/FIT/FT0/simulation/src/Detector.cxx | 38 ++- .../FIT/FT0/simulation/src/Digits2Raw.cxx | 58 +++-- Detectors/FIT/macros/CMakeLists.txt | 3 + Detectors/FIT/macros/uploadLookUpTable.C | 71 ++++++ 19 files changed, 513 insertions(+), 71 deletions(-) create mode 100644 Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt create mode 100644 Detectors/FIT/FT0/base/files/Sim2DataChannels.txt create mode 100644 Detectors/FIT/macros/uploadLookUpTable.C diff --git a/DataFormats/Detectors/FIT/FT0/CMakeLists.txt b/DataFormats/Detectors/FIT/FT0/CMakeLists.txt index 58699a2cd95a3..ed0399a72d9cb 100644 --- a/DataFormats/Detectors/FIT/FT0/CMakeLists.txt +++ b/DataFormats/Detectors/FIT/FT0/CMakeLists.txt @@ -18,6 +18,8 @@ o2_add_library(DataFormatsFT0 PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::SimulationDataFormat + O2::CCDB + O2::DetectorsCalibration O2::FT0Base) o2_target_root_dictionary(DataFormatsFT0 diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h index de6aeb8ae653e..7ecf86dcf2333 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h @@ -19,10 +19,21 @@ // Look Up Table FT0 ////////////////////////////////////////////// +#include "CCDB/BasicCCDBManager.h" + #include <Rtypes.h> #include <cassert> +#include <exception> #include <iostream> +#include <fstream> +#include <stdexcept> #include <tuple> +#include <TSystem.h> +#include <cstdlib> +#include <map> +#include <string_view> +#include <vector> + namespace o2 { namespace ft0 @@ -33,15 +44,54 @@ struct Topo { ClassDefNV(Topo, 1); }; +// enum class Side : char { A, C }; +// struct PM { +// Side side; +// uint8_t PM_num, PM_channel; +// }; + +struct HVchannel { + enum class HVBoard : uint8_t { NA, + A_out, + A_in, + C_up, + C_down, + C_mid }; + uint8_t channel; + Topo pm; + HVBoard HV_board; + uint8_t HV_channel; + std::string MCP_SN; + std::string HV_cabel; + std::string signal_cable; + + ClassDefNV(HVchannel, 1); +}; + inline bool operator<(Topo const& a, Topo const& b) { return (a.mPM < b.mPM || (a.mPM == b.mPM && a.mMCP < b.mMCP)); } +inline o2::ft0::Topo read_Topo(std::string_view str) +{ + assert(str.substr(0, 2) == "PM" && str[4] == '/' && str[5] == 'C' && str[6] == 'h'); + char side = str[2]; + uint8_t pm_num = str[3] - '0'; + uint8_t pm_ch = (str[7] - '0') * 10 + (str[8] - '0') - 1; + assert(side == 'A' || side == 'C'); + if (str.substr(0, 4) == "PMA9") { + pm_num = 18; + } + return Topo{(side == 'C' ? 8 : 0) + pm_num, pm_ch}; +} + class LookUpTable { + using CcdbManager = o2::ccdb::BasicCCDBManager; + using CcdbApi = o2::ccdb::CcdbApi; static constexpr int NUMBER_OF_MCPs = 12; - static constexpr int NUMBER_OF_PMs = 18; + static constexpr int NUMBER_OF_PMs = 19; public: /// @@ -58,8 +108,11 @@ class LookUpTable channel; } } - + LookUpTable() = default; ~LookUpTable() = default; + + HVchannel mHVchannel; + void printFullMap() const { for (size_t channel = 0; channel < mTopoVector.size(); ++channel) { @@ -77,8 +130,14 @@ class LookUpTable return mInvTopo[getIdx(link, mcp)]; } - int getLink(int channel) const { return mTopoVector[channel].mPM; } - int getMCP(int channel) const { return mTopoVector[channel].mMCP; } + int getLink(int channel) const + { + return mTopoVector[channel].mPM; + } + int getMCP(int channel) const + { + return mTopoVector[channel].mMCP; + } static o2::ft0::LookUpTable linear() { @@ -91,23 +150,67 @@ class LookUpTable return o2::ft0::LookUpTable{lut_data}; } + static o2::ft0::LookUpTable readTableFile() + { + std::string inputDir; + const char* aliceO2env = std::getenv("O2_ROOT"); + if (aliceO2env) { + inputDir = aliceO2env; + } + inputDir += "/share/Detectors/FT0/files/"; + + std::string lutPath = inputDir + "FT0ChannelsTable.txt"; + lutPath = gSystem->ExpandPathName(lutPath.data()); // Expand $(ALICE_ROOT) into real system path + + std::ifstream infile; + infile.open(lutPath.c_str()); + + std::vector<o2::ft0::Topo> lut_data(NUMBER_OF_MCPs * NUMBER_OF_PMs - 8); + std::string comment; // dummy, used just to read 4 first lines and move the cursor to the 5th, otherwise unused + if (!getline(infile, comment)) { // first comment line + /* std::cout << "Error opening ascii file (it is probably a folder!): " << filename.c_str() << std::endl; */ + throw std::runtime_error("Error reading lookup table"); + } + int channel; + std::string pm, pm_channel, hv_board, hv_channel, mcp_sn, hv_cable, signal_cable; + std::getline(infile, pm); // skip one line + while (infile >> channel >> pm >> pm_channel >> hv_board >> hv_channel >> mcp_sn >> hv_cable >> signal_cable) { + lut_data[channel] = read_Topo(pm_channel); + } + return o2::ft0::LookUpTable{lut_data}; + } + static o2::ft0::LookUpTable readTable() + { + + std::vector<o2::ft0::Topo> lut_data; + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); + mgr.setURL("http://ccdb-test.cern.ch:8080"); + auto hvch = mgr.get<std::vector<o2::ft0::HVchannel>>("FT0/LookUpTable"); + size_t max = 0; + for (auto const& chan : *hvch) + if (max < chan.channel) + max = chan.channel; + lut_data.resize(max + 1); + for (auto const& chan : *hvch) { + o2::ft0::Topo topo = chan.pm; + lut_data[chan.channel] = topo; + } + return o2::ft0::LookUpTable{lut_data}; + } + private: std::vector<Topo> mTopoVector; std::vector<int> mInvTopo; static int getIdx(int link, int mcp) { - if (mcp >= NUMBER_OF_MCPs) { - std::cout << " !!! MCP number > max NUMBER_OF_MCPs " << mcp << " data will be skipped " << std::endl; - return -1; - } - //assert(mcp < NUMBER_OF_MCPs); + assert(mcp < NUMBER_OF_MCPs); return link * NUMBER_OF_MCPs + mcp; } static int getLinkFromIdx(int idx) { return idx / NUMBER_OF_MCPs; } static int getMCPFromIdx(int idx) { return idx % NUMBER_OF_MCPs; } - ClassDefNV(LookUpTable, 1); + ClassDefNV(LookUpTable, 2); }; } // namespace ft0 diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h index d163157e57ae1..ccb322a35dab6 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h @@ -32,7 +32,7 @@ namespace ft0 { constexpr int Nchannels_FT0 = 208; constexpr int Nchannels_PM = 12; -constexpr int NPMs = 19; +constexpr int NPMs = 20; constexpr size_t sizeWord = 16; struct EventHeader { diff --git a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h index 752734fdbf382..616436b76d0f9 100644 --- a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h +++ b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h @@ -43,6 +43,8 @@ #pragma link C++ class o2::ft0::EventHeader + ; #pragma link C++ class o2::ft0::EventData + ; #pragma link C++ class o2::ft0::Topo + ; +#pragma link C++ class o2::ft0::HVchannel + ; +#pragma link C++ class vector < o2::ft0::HVchannel> + ; #pragma link C++ class o2::ft0::CTFHeader + ; #pragma link C++ class o2::ft0::CompressedDigits + ; diff --git a/Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt b/Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt new file mode 100644 index 0000000000000..924e4b1c09f87 --- /dev/null +++ b/Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt @@ -0,0 +1,225 @@ +channel# PM PM_channel HV_board HV_channel MCP_S/N HV_cable signal_cable +0 A0 PMA0/Ch01 A-Out HVAO/04 ???? FTA-D2 FTA-D2-? +1 A0 PMA0/Ch02 A-Out HVAO/04 ???? FTA-D2 FTA-D2-? +2 A0 PMA0/Ch03 A-Out HVAO/04 ???? FTA-D2 FTA-D2-? +3 A0 PMA0/Ch04 A-Out HVAO/04 ???? FTA-D2 FTA-D2-? +4 A0 PMA0/Ch05 A-Out HVAO/03 ???? FTA-D1 FTA-D1-? +5 A0 PMA0/Ch06 A-Out HVAO/03 ???? FTA-D1 FTA-D1-? +6 A0 PMA0/Ch07 A-Out HVAO/03 ???? FTA-D1 FTA-D1-? +7 A0 PMA0/Ch08 A-Out HVAO/03 ???? FTA-D1 FTA-D1-? +8 A0 PMA0/Ch09 A-Out HVAO/08 ???? FTA-E1 FTA-E1-? +9 A0 PMA0/Ch10 A-Out HVAO/08 ???? FTA-E1 FTA-E1-? +10 A0 PMA0/Ch11 A-Out HVAO/08 ???? FTA-E1 FTA-E1-? +11 A0 PMA0/Ch12 A-Out HVAO/08 ???? FTA-E1 FTA-E1-? +12 A1 PMA1/Ch01 A-Out HVAO/05 ???? FTA-D3 FTA-D3-? +13 A1 PMA1/Ch02 A-Out HVAO/05 ???? FTA-D3 FTA-D3-? +14 A1 PMA1/Ch03 A-Out HVAO/05 ???? FTA-D3 FTA-D3-? +15 A1 PMA1/Ch04 A-Out HVAO/05 ???? FTA-D3 FTA-D3-? +16 A1 PMA1/Ch05 A-Out HVAO/09 ???? FTA-E2 FTA-E2-? +17 A1 PMA1/Ch06 A-Out HVAO/09 ???? FTA-E2 FTA-E2-? +18 A1 PMA1/Ch07 A-Out HVAO/09 ???? FTA-E2 FTA-E2-? +19 A1 PMA1/Ch08 A-Out HVAO/09 ???? FTA-E2 FTA-E2-? +20 A1 PMA1/Ch09 A-Out HVAO/10 ???? FTA-E3 FTA-E3-? +21 A1 PMA1/Ch10 A-Out HVAO/10 ???? FTA-E3 FTA-E3-? +22 A1 PMA1/Ch11 A-Out HVAO/10 ???? FTA-E3 FTA-E3-? +23 A1 PMA1/Ch12 A-Out HVAO/10 ???? FTA-E3 FTA-E3-? +24 A2 PMA2/Ch01 A-Out HVAO/06 ???? FTA-D4 FTA-D4-? +25 A2 PMA2/Ch02 A-Out HVAO/06 ???? FTA-D4 FTA-D4-? +26 A2 PMA2/Ch03 A-Out HVAO/06 ???? FTA-D4 FTA-D4-? +27 A2 PMA2/Ch04 A-Out HVAO/06 ???? FTA-D4 FTA-D4-? +28 A2 PMA2/Ch05 A-Out HVAO/11 ???? FTA-E4 FTA-E4-? +29 A2 PMA2/Ch06 A-Out HVAO/11 ???? FTA-E4 FTA-E4-? +30 A2 PMA2/Ch07 A-Out HVAO/11 ???? FTA-E4 FTA-E4-? +31 A2 PMA2/Ch08 A-Out HVAO/11 ???? FTA-E4 FTA-E4-? +32 A2 PMA2/Ch09 A-Out HVAO/12 ???? FTA-E5 FTA-E5-? +33 A2 PMA2/Ch10 A-Out HVAO/12 ???? FTA-E5 FTA-E5-? +34 A2 PMA2/Ch11 A-Out HVAO/12 ???? FTA-E5 FTA-E5-? +35 A2 PMA2/Ch12 A-Out HVAO/12 ???? FTA-E5 FTA-E5-? +36 A3 PMA3/Ch01 A-Out HVAO/01 ???? FTA-C4 FTA-C4-? +37 A3 PMA3/Ch02 A-Out HVAO/01 ???? FTA-C4 FTA-C4-? +38 A3 PMA3/Ch03 A-Out HVAO/01 ???? FTA-C4 FTA-C4-? +39 A3 PMA3/Ch04 A-Out HVAO/01 ???? FTA-C4 FTA-C4-? +40 A3 PMA3/Ch05 A-Out HVAO/07 ???? FTA-D5 FTA-D5-? +41 A3 PMA3/Ch06 A-Out HVAO/07 ???? FTA-D5 FTA-D5-? +42 A3 PMA3/Ch07 A-Out HVAO/07 ???? FTA-D5 FTA-D5-? +43 A3 PMA3/Ch08 A-Out HVAO/07 ???? FTA-D5 FTA-D5-? +44 A3 PMA3/Ch09 A-Out HVAO/02 ???? FTA-C5 FTA-C5-? +45 A3 PMA3/Ch10 A-Out HVAO/02 ???? FTA-C5 FTA-C5-? +46 A3 PMA3/Ch11 A-Out HVAO/02 ???? FTA-C5 FTA-C5-? +47 A3 PMA3/Ch12 A-Out HVAO/02 ???? FTA-C5 FTA-C5-? +48 A4 PMA4/Ch01 A-In HVAI/09 ???? FTA-B4 FTA-B4-? +49 A4 PMA4/Ch02 A-In HVAI/09 ???? FTA-B4 FTA-B4-? +50 A4 PMA4/Ch03 A-In HVAI/09 ???? FTA-B4 FTA-B4-? +51 A4 PMA4/Ch04 A-In HVAI/09 ???? FTA-B4 FTA-B4-? +52 A4 PMA4/Ch05 A-In HVAI/10 ???? FTA-B5 FTA-B5-? +53 A4 PMA4/Ch06 A-In HVAI/10 ???? FTA-B5 FTA-B5-? +54 A4 PMA4/Ch07 A-In HVAI/10 ???? FTA-B5 FTA-B5-? +55 A4 PMA4/Ch08 A-In HVAI/10 ???? FTA-B5 FTA-B5-? +56 A4 PMA4/Ch09 A-In HVAI/05 ???? FTA-A5 FTA-A5-? +57 A4 PMA4/Ch10 A-In HVAI/05 ???? FTA-A5 FTA-A5-? +58 A4 PMA4/Ch11 A-In HVAI/05 ???? FTA-A5 FTA-A5-? +59 A4 PMA4/Ch12 A-In HVAI/05 ???? FTA-A5 FTA-A5-? +60 A5 PMA5/Ch01 A-In HVAI/08 ???? FTA-B3 FTA-B3-? +61 A5 PMA5/Ch02 A-In HVAI/08 ???? FTA-B3 FTA-B3-? +62 A5 PMA5/Ch03 A-In HVAI/08 ???? FTA-B3 FTA-B3-? +63 A5 PMA5/Ch04 A-In HVAI/08 ???? FTA-B3 FTA-B3-? +64 A5 PMA5/Ch05 A-In HVAI/04 ???? FTA-A4 FTA-A4-? +65 A5 PMA5/Ch06 A-In HVAI/04 ???? FTA-A4 FTA-A4-? +66 A5 PMA5/Ch07 A-In HVAI/04 ???? FTA-A4 FTA-A4-? +67 A5 PMA5/Ch08 A-In HVAI/04 ???? FTA-A4 FTA-A4-? +68 A5 PMA5/Ch09 A-In HVAI/03 ???? FTA-A3 FTA-A3-? +69 A5 PMA5/Ch10 A-In HVAI/03 ???? FTA-A3 FTA-A3-? +70 A5 PMA5/Ch11 A-In HVAI/03 ???? FTA-A3 FTA-A3-? +71 A5 PMA5/Ch12 A-In HVAI/03 ???? FTA-A3 FTA-A3-? +72 A6 PMA6/Ch01 A-In HVAI/07 ???? FTA-B2 FTA-B2-? +73 A6 PMA6/Ch02 A-In HVAI/07 ???? FTA-B2 FTA-B2-? +74 A6 PMA6/Ch03 A-In HVAI/07 ???? FTA-B2 FTA-B2-? +75 A6 PMA6/Ch04 A-In HVAI/07 ???? FTA-B2 FTA-B2-? +76 A6 PMA6/Ch05 A-In HVAI/02 ???? FTA-A2 FTA-A2-? +77 A6 PMA6/Ch06 A-In HVAI/02 ???? FTA-A2 FTA-A2-? +78 A6 PMA6/Ch07 A-In HVAI/02 ???? FTA-A2 FTA-A2-? +79 A6 PMA6/Ch08 A-In HVAI/02 ???? FTA-A2 FTA-A2-? +80 A6 PMA6/Ch09 A-In HVAI/01 ???? FTA-A1 FTA-A1-? +81 A6 PMA6/Ch10 A-In HVAI/01 ???? FTA-A1 FTA-A1-? +82 A6 PMA6/Ch11 A-In HVAI/01 ???? FTA-A1 FTA-A1-? +83 A6 PMA6/Ch12 A-In HVAI/01 ???? FTA-A1 FTA-A1-? +84 A7 PMA7/Ch01 A-In HVAI/12 ???? FTA-C2 FTA-C2-? +85 A7 PMA7/Ch02 A-In HVAI/12 ???? FTA-C2 FTA-C2-? +86 A7 PMA7/Ch03 A-In HVAI/12 ???? FTA-C2 FTA-C2-? +87 A7 PMA7/Ch04 A-In HVAI/12 ???? FTA-C2 FTA-C2-? +88 A7 PMA7/Ch05 A-In HVAI/06 ???? FTA-B1 FTA-B1-? +89 A7 PMA7/Ch06 A-In HVAI/06 ???? FTA-B1 FTA-B1-? +90 A7 PMA7/Ch07 A-In HVAI/06 ???? FTA-B1 FTA-B1-? +91 A7 PMA7/Ch08 A-In HVAI/06 ???? FTA-B1 FTA-B1-? +92 A7 PMA7/Ch09 A-In HVAI/11 ???? FTA-C1 FTA-C1-? +93 A7 PMA7/Ch10 A-In HVAI/11 ???? FTA-C1 FTA-C1-? +94 A7 PMA7/Ch11 A-In HVAI/11 ???? FTA-C1 FTA-C1-? +95 A7 PMA7/Ch12 A-In HVAI/11 ???? FTA-C1 FTA-C1-? +96 C0 PMC0/Ch01 C-Up HVCU/04 2119 FTC-B3 FTC-B3-2 +97 C0 PMC0/Ch02 C-Up HVCU/04 2119 FTC-B3 FTC-B3-1 +98 C0 PMC0/Ch03 C-Up HVCU/04 2119 FTC-B3 FTC-B3-3 +99 C0 PMC0/Ch04 C-Up HVCU/04 2119 FTC-B3 FTC-B3-4 +100 C0 PMC0/Ch05 C-Up HVCU/02 2147 FTC-A3 FTC-A3-2 +101 C0 PMC0/Ch06 C-Up HVCU/02 2147 FTC-A3 FTC-A3-1 +102 C0 PMC0/Ch07 C-Up HVCU/02 2147 FTC-A3 FTC-A3-3 +103 C0 PMC0/Ch08 C-Up HVCU/02 2147 FTC-A3 FTC-A3-4 +104 C0 PMC0/Ch09 C-Up HVCU/01 2129 FTC-A2 FTC-A2-2 +105 C0 PMC0/Ch10 C-Up HVCU/01 2129 FTC-A2 FTC-A2-1 +106 C0 PMC0/Ch11 C-Up HVCU/01 2129 FTC-A2 FTC-A2-3 +107 C0 PMC0/Ch12 C-Up HVCU/01 2129 FTC-A2 FTC-A2-4 +108 C1 PMC1/Ch01 C-Up HVCU/06 2123 FTC-C2 FTC-C2-1 +109 C1 PMC1/Ch02 C-Up HVCU/06 2123 FTC-C2 FTC-C2-2 +110 C1 PMC1/Ch03 C-Up HVCU/06 2123 FTC-C2 FTC-C2-4 +111 C1 PMC1/Ch04 C-Up HVCU/06 2123 FTC-C2 FTC-C2-3 +112 C1 PMC1/Ch05 C-Up HVCU/05 2127 FTC-C1 FTC-C1-1 +113 C1 PMC1/Ch06 C-Up HVCU/05 2127 FTC-C1 FTC-C1-2 +114 C1 PMC1/Ch07 C-Up HVCU/05 2127 FTC-C1 FTC-C1-4 +115 C1 PMC1/Ch08 C-Up HVCU/05 2127 FTC-C1 FTC-C1-3 +116 C1 PMC1/Ch09 C-Up HVCU/03 2118 FTC-B1 FTC-B1-2 +117 C1 PMC1/Ch10 C-Up HVCU/03 2118 FTC-B1 FTC-B1-3 +118 C1 PMC1/Ch11 C-Up HVCU/03 2118 FTC-B1 FTC-B1-1 +119 C1 PMC1/Ch12 C-Up HVCU/03 2118 FTC-B1 FTC-B1-4 +120 C2 PMC2/Ch01 C-Up HVCU/08 2128 FTC-D2 FTC-D2-4 +121 C2 PMC2/Ch02 C-Up HVCU/08 2128 FTC-D2 FTC-D2-3 +122 C2 PMC2/Ch03 C-Up HVCU/08 2128 FTC-D2 FTC-D2-1 +123 C2 PMC2/Ch04 C-Up HVCU/08 2128 FTC-D2 FTC-D2-2 +124 C2 PMC2/Ch05 C-Up HVCU/07 2145 FTC-D1 FTC-D1-4 +125 C2 PMC2/Ch06 C-Up HVCU/07 2145 FTC-D1 FTC-D1-3 +126 C2 PMC2/Ch07 C-Up HVCU/07 2145 FTC-D1 FTC-D1-1 +127 C2 PMC2/Ch08 C-Up HVCU/07 2145 FTC-D1 FTC-D1-2 +128 C2 PMC2/Ch09 C-Up HVCU/09 2125 FTC-E1 FTC-E1-2 +129 C2 PMC2/Ch10 C-Up HVCU/09 2125 FTC-E1 FTC-E1-1 +130 C2 PMC2/Ch11 C-Up HVCU/09 2125 FTC-E1 FTC-E1-3 +131 C2 PMC2/Ch12 C-Up HVCU/09 2125 FTC-E1 FTC-E1-4 +132 C3 PMC3/Ch01 C-Up HVCU/10 2130 FTC-E3 FTC-E3-1 +133 C3 PMC3/Ch02 C-Up HVCU/10 2130 FTC-E3 FTC-E3-2 +134 C3 PMC3/Ch03 C-Up HVCU/10 2130 FTC-E3 FTC-E3-4 +135 C3 PMC3/Ch04 C-Up HVCU/10 2130 FTC-E3 FTC-E3-3 +136 C3 PMC3/Ch05 C-Up HVCU/12 2149 FTC-F3 FTC-F3-1 +137 C3 PMC3/Ch06 C-Up HVCU/12 2149 FTC-F3 FTC-F3-2 +138 C3 PMC3/Ch07 C-Up HVCU/12 2149 FTC-F3 FTC-F3-4 +139 C3 PMC3/Ch08 C-Up HVCU/12 2149 FTC-F3 FTC-F3-3 +140 C3 PMC3/Ch09 C-Up HVCU/11 2134 FTC-F2 FTC-F2-1 +141 C3 PMC3/Ch10 C-Up HVCU/11 2134 FTC-F2 FTC-F2-2 +142 C3 PMC3/Ch11 C-Up HVCU/11 2134 FTC-F2 FTC-F2-4 +143 C3 PMC3/Ch12 C-Up HVCU/11 2134 FTC-F2 FTC-F2-3 +144 C4 PMC4/Ch01 C-Down HVCD/09 2137 FTC-E4 FTC-E4-2 +145 C4 PMC4/Ch02 C-Down HVCD/09 2137 FTC-E4 FTC-E4-1 +146 C4 PMC4/Ch03 C-Down HVCD/09 2137 FTC-E4 FTC-E4-3 +147 C4 PMC4/Ch04 C-Down HVCD/09 2137 FTC-E4 FTC-E4-4 +148 C4 PMC4/Ch05 C-Down HVCD/11 2152 FTC-F4 FTC-F4-2 +149 C4 PMC4/Ch06 C-Down HVCD/11 2152 FTC-F4 FTC-F4-1 +150 C4 PMC4/Ch07 C-Down HVCD/11 2152 FTC-F4 FTC-F4-3 +151 C4 PMC4/Ch08 C-Down HVCD/11 2152 FTC-F4 FTC-F4-4 +152 C4 PMC4/Ch09 C-Down HVCD/12 2142 FTC-F5 FTC-F5-2 +153 C4 PMC4/Ch10 C-Down HVCD/12 2142 FTC-F5 FTC-F5-1 +154 C4 PMC4/Ch11 C-Down HVCD/12 2142 FTC-F5 FTC-F5-3 +155 C4 PMC4/Ch12 C-Down HVCD/12 2142 FTC-F5 FTC-F5-4 +156 C5 PMC5/Ch01 C-Down HVCD/07 2157 FTC-D5 FTC-D5-1 +157 C5 PMC5/Ch02 C-Down HVCD/07 2157 FTC-D5 FTC-D5-2 +158 C5 PMC5/Ch03 C-Down HVCD/07 2157 FTC-D5 FTC-D5-4 +159 C5 PMC5/Ch04 C-Down HVCD/07 2157 FTC-D5 FTC-D5-3 +160 C5 PMC5/Ch05 C-Down HVCD/08 2167 FTC-D6 FTC-D6-1 +161 C5 PMC5/Ch06 C-Down HVCD/08 2167 FTC-D6 FTC-D6-2 +162 C5 PMC5/Ch07 C-Down HVCD/08 2167 FTC-D6 FTC-D6-4 +163 C5 PMC5/Ch08 C-Down HVCD/08 2167 FTC-D6 FTC-D6-3 +164 C5 PMC5/Ch09 C-Down HVCD/10 2165 FTC-E6 FTC-E6-2 +165 C5 PMC5/Ch10 C-Down HVCD/10 2165 FTC-E6 FTC-E6-3 +166 C5 PMC5/Ch11 C-Down HVCD/10 2165 FTC-E6 FTC-E6-1 +167 C5 PMC5/Ch12 C-Down HVCD/10 2165 FTC-E6 FTC-E6-4 +168 C6 PMC6/Ch01 C-Down HVCD/05 2148 FTC-C5 FTC-C5-4 +169 C6 PMC6/Ch02 C-Down HVCD/05 2148 FTC-C5 FTC-C5-3 +170 C6 PMC6/Ch03 C-Down HVCD/05 2148 FTC-C5 FTC-C5-1 +171 C6 PMC6/Ch04 C-Down HVCD/05 2148 FTC-C5 FTC-C5-2 +172 C6 PMC6/Ch05 C-Down HVCD/06 2162 FTC-C6 FTC-C6-4 +173 C6 PMC6/Ch06 C-Down HVCD/06 2162 FTC-C6 FTC-C6-3 +174 C6 PMC6/Ch07 C-Down HVCD/06 2162 FTC-C6 FTC-C6-1 +175 C6 PMC6/Ch08 C-Down HVCD/06 2162 FTC-C6 FTC-C6-2 +176 C6 PMC6/Ch09 C-Down HVCD/04 2144 FTC-B6 FTC-B6-2 +177 C6 PMC6/Ch10 C-Down HVCD/04 2144 FTC-B6 FTC-B6-1 +178 C6 PMC6/Ch11 C-Down HVCD/04 2144 FTC-B6 FTC-B6-3 +179 C6 PMC6/Ch12 C-Down HVCD/04 2144 FTC-B6 FTC-B6-4 +180 C7 PMC7/Ch01 C-Down HVCD/03 2136 FTC-B4 FTC-B4-1 +181 C7 PMC7/Ch02 C-Down HVCD/03 2136 FTC-B4 FTC-B4-2 +182 C7 PMC7/Ch03 C-Down HVCD/03 2136 FTC-B4 FTC-B4-4 +183 C7 PMC7/Ch04 C-Down HVCD/03 2136 FTC-B4 FTC-B4-3 +184 C7 PMC7/Ch05 C-Down HVCD/01 2151 FTC-A4 FTC-A4-1 +185 C7 PMC7/Ch06 C-Down HVCD/01 2151 FTC-A4 FTC-A4-2 +186 C7 PMC7/Ch07 C-Down HVCD/01 2151 FTC-A4 FTC-A4-4 +187 C7 PMC7/Ch08 C-Down HVCD/01 2151 FTC-A4 FTC-A4-3 +188 C7 PMC7/Ch09 C-Down HVCD/02 2141 FTC-A5 FTC-A5-1 +189 C7 PMC7/Ch10 C-Down HVCD/02 2141 FTC-A5 FTC-A5-2 +190 C7 PMC7/Ch11 C-Down HVCD/02 2141 FTC-A5 FTC-A5-4 +191 C7 PMC7/Ch12 C-Down HVCD/02 2141 FTC-A5 FTC-A5-3 +192 C8 PMC8/Ch01 C-Mid HVCM/01 2121 FTC-B2 FTC-B2-2 +193 C8 PMC8/Ch02 C-Mid HVCM/01 2121 FTC-B2 FTC-B2-3 +194 C8 PMC8/Ch03 C-Mid HVCM/01 2121 FTC-B2 FTC-B2-1 +195 C8 PMC8/Ch04 C-Mid HVCM/01 2121 FTC-B2 FTC-B2-4 +196 C8 PMC8/Ch05 C-Mid HVCM/02 2133 FTC-E2 FTC-E2-1 +197 C8 PMC8/Ch06 C-Mid HVCM/02 2133 FTC-E2 FTC-E2-2 +198 C8 PMC8/Ch07 C-Mid HVCM/02 2133 FTC-E2 FTC-E2-4 +199 C8 PMC8/Ch08 C-Mid HVCM/02 2133 FTC-E2 FTC-E2-3 +200 C8 PMC8/Ch09 N/A N/A N/A N/A N/A +201 C8 PMC8/Ch10 N/A N/A N/A N/A N/A +202 C8 PMC8/Ch11 N/A N/A N/A N/A N/A +203 C8 PMC8/Ch12 N/A N/A N/A N/A N/A +204 C9 PMC9/Ch01 C-Mid HVCM/03 2158 FTC-E5 FTC-E5-2 +205 C9 PMC9/Ch02 C-Mid HVCM/03 2158 FTC-E5 FTC-E5-3 +206 C9 PMC9/Ch03 C-Mid HVCM/03 2158 FTC-E5 FTC-E5-1 +207 C9 PMC9/Ch04 C-Mid HVCM/03 2158 FTC-E5 FTC-E5-4 +208 C9 PMC9/Ch05 C-Mid HVCM/04 2143 FTC-B5 FTC-B5-1 +209 C9 PMC9/Ch06 C-Mid HVCM/04 2143 FTC-B5 FTC-B5-2 +210 C9 PMC9/Ch07 C-Mid HVCM/04 2143 FTC-B5 FTC-B5-4 +211 C9 PMC9/Ch08 C-Mid HVCM/04 2143 FTC-B5 FTC-B5-3 +212 C9 PMC9/Ch09 N/A N/A N/A N/A N/A +213 C9 PMC9/Ch10 N/A N/A N/A N/A N/A +214 C9 PMC9/Ch11 N/A N/A N/A N/A N/A +215 C9 PMC9/Ch12 N/A N/A N/A N/A N/A +216 A9 PMA9/Ch01 C-Mid HVCM/12 ???? FT0-LCS FTA-LCS +217 A9 PMA9/Ch02 C-Mid HVCM/12 ???? FT0-LCS FTA-LCS-H +218 A9 PMA9/Ch03 C-Mid HVCM/12 ???? FT0-LCS FTC-LCS +219 A9 PMA9/Ch04 C-Mid HVCM/12 ???? FT0-LCS FTC-LCS-H + + + + diff --git a/Detectors/FIT/FT0/base/files/Sim2DataChannels.txt b/Detectors/FIT/FT0/base/files/Sim2DataChannels.txt new file mode 100644 index 0000000000000..fe8a1bb709f95 --- /dev/null +++ b/Detectors/FIT/FT0/base/files/Sim2DataChannels.txt @@ -0,0 +1,2 @@ +82 83 80 81 89 91 88 90 93 95 92 94 4 6 5 7 8 10 9 11 78 79 76 77 74 75 72 73 85 87 84 86 0 2 1 3 16 17 18 19 71 70 69 68 63 62 61 60 12 13 14 15 20 21 22 23 67 66 65 64 51 49 50 48 38 36 39 37 25 24 27 26 29 28 31 30 59 57 58 56 55 53 54 52 46 44 47 45 42 40 43 41 33 32 35 34 117 119 116 118 113 115 112 114 124 126 125 127 128 130 129 131 106 107 104 105 193 195 192 194 109 111 108 110 120 122 121 123 196 197 198 199 140 141 142 143 102 103 100 101 98 99 96 97 132 133 134 135 136 137 138 139 187 186 185 184 183 182 181 180 145 144 147 146 148 149 151 150 191 190 189 188 211 210 209 208 171 169 170 168 158 156 159 157 205 204 207 205 153 152 155 154 179 177 178 176 175 173 174 172 162 160 163 161 166 164 167 165 + diff --git a/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h b/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h index 9d405806424e6..f5fb4f9b7ba9d 100644 --- a/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h +++ b/Detectors/FIT/FT0/base/include/FT0Base/Geometry.h @@ -16,6 +16,7 @@ #include <Rtypes.h> #include <TVector3.h> + namespace o2 { namespace ft0 @@ -36,6 +37,7 @@ class Geometry /// TVector3 centerMCP(int imcp) { return mMCP[imcp]; } + static constexpr int Nchannels = 208; // number od channels static constexpr int NCellsA = 24; // number of radiatiors on A side static constexpr int NCellsC = 28; // number of radiatiors on C side static constexpr float ZdetA = 335; // number of radiatiors on A side diff --git a/Detectors/FIT/FT0/base/src/Geometry.cxx b/Detectors/FIT/FT0/base/src/Geometry.cxx index 6d30591501427..9dd83e33af0e9 100644 --- a/Detectors/FIT/FT0/base/src/Geometry.cxx +++ b/Detectors/FIT/FT0/base/src/Geometry.cxx @@ -10,9 +10,11 @@ #include <iomanip> //#include <TVector3.h> #include "FT0Base/Geometry.h" - +#include "TSystem.h" #include <FairLogger.h> #include <sstream> +#include <string> +#include <iostream> ClassImp(o2::ft0::Geometry); diff --git a/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h b/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h index 213d869782df2..810bcad5d60fd 100644 --- a/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h +++ b/Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h @@ -50,15 +50,15 @@ class RawReaderFT0Base : public RawReaderBase<DigitBlockFT0type> //deserialize payload to raw data blocks and proccesss them to digits void process(int linkID, gsl::span<const uint8_t> payload) { - if (0 <= linkID && linkID < 18) { + if (0 <= linkID && linkID < 19) { //PM data proccessing RawReaderBaseType::template processBinaryData<DataBlockPMtype>(payload, linkID); - } else if (linkID == 18) { + } else if (linkID == 19) { //TCM data proccessing RawReaderBaseType::template processBinaryData<DataBlockTCMtype>(payload, linkID); } else { //put here code in case of bad rdh.linkID value - LOG(INFO) << "WARNING! WRONG LINK ID!"; + LOG(INFO) << "WARNING! WRONG LINK ID! " << linkID; return; } diff --git a/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx index 710ebee6249a2..0fdb98bed5ca1 100644 --- a/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx +++ b/Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx @@ -12,6 +12,6 @@ using namespace o2::ft0; int DigitBlockFT0::sEventID = 0; -o2::ft0::LookUpTable DigitBlockFT0::sLookupTable = o2::ft0::LookUpTable::linear(); +o2::ft0::LookUpTable DigitBlockFT0::sLookupTable = o2::ft0::LookUpTable::readTable(); int DigitBlockFT0ext::sEventID = 0; -o2::ft0::LookUpTable DigitBlockFT0ext::sLookupTable = o2::ft0::LookUpTable::linear(); +o2::ft0::LookUpTable DigitBlockFT0ext::sLookupTable = o2::ft0::LookUpTable::readTable(); diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h index 84185564bb6a5..8b4620c443711 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h @@ -42,8 +42,8 @@ class ReadRaw { static constexpr int Nchannels_FT0 = 208; static constexpr int Nchannels_PM = 12; - static constexpr int NPMs = 19; - static constexpr int LinkTCM = 18; + static constexpr int NPMs = 20; + static constexpr int LinkTCM = 19; static constexpr float MV_2_Nchannels = 2.2857143; //7 mV ->16channels static constexpr float CFD_NS_2_Nchannels = 76.804916; //1000.(ps)/13.02(channel); //static constexpr int GBTWORDSIZE = 80; //real size @@ -57,17 +57,6 @@ class ReadRaw void readData(const std::string fileRaw, const o2::ft0::LookUpTable& lut); void writeDigits(const std::string fileDecodeData); void close(); - static o2::ft0::LookUpTable linear() - { - std::vector<o2::ft0::Topo> lut_data(Nchannels_PM * NPMs); - for (int link = 0; link < NPMs; ++link) { - for (int mcp = 0; mcp < Nchannels_PM; ++mcp) { - lut_data[link * Nchannels_PM + mcp] = o2::ft0::Topo{link, mcp}; - } - } - - return o2::ft0::LookUpTable{lut_data}; - } private: std::ifstream mFileDest; diff --git a/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx b/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx index bd72a9f5a7625..451d211690ec6 100644 --- a/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx +++ b/Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx @@ -73,7 +73,7 @@ ReadRaw::ReadRaw(const std::string fileRaw, std::string fileDataOut) << "file to read " << fileRaw.data() << " file to write " << fileDataOut.data(); mFileDest.exceptions(std::ios_base::failbit | std::ios_base::badbit); mFileDest.open(fileRaw, std::fstream::in | std::fstream::binary); - o2::ft0::LookUpTable lut{o2::ft0::ReadRaw::linear()}; + o2::ft0::LookUpTable lut{LookUpTable::readTable()}; ReadRaw::readData(fileRaw.c_str(), lut); ReadRaw::writeDigits(fileDataOut.data()); } @@ -131,7 +131,7 @@ void ReadRaw::readData(const std::string fileRaw, const o2::ft0::LookUpTable& lu digit.setInteractionRecord(intrec); } chDgDataArr = &digitIter->second.getChDgData(); //&mDigitsTemp.getChDgData(); - if (link == 18) { + if (link == LinkTCM) { mFileDest.read(reinterpret_cast<char*>(&mTCMdata), sizeof(mTCMdata)); pos += sizeof(mTCMdata); digitIter->second.setTriggers(Bool_t(mTCMdata.orA), Bool_t(mTCMdata.orC), Bool_t(mTCMdata.vertex), Bool_t(mTCMdata.sCen), Bool_t(mTCMdata.cen), uint8_t(mTCMdata.nChanA), uint8_t(mTCMdata.nChanC), int32_t(mTCMdata.amplA), int32_t(mTCMdata.amplC), int16_t(mTCMdata.timeA), int16_t(mTCMdata.timeC)); diff --git a/Detectors/FIT/FT0/simulation/CMakeLists.txt b/Detectors/FIT/FT0/simulation/CMakeLists.txt index 918a248854d24..23dc494992eab 100644 --- a/Detectors/FIT/FT0/simulation/CMakeLists.txt +++ b/Detectors/FIT/FT0/simulation/CMakeLists.txt @@ -17,6 +17,8 @@ o2_add_library(FT0Simulation O2::FT0Base O2::DataFormatsFT0 O2::DetectorsRaw + O2::CCDB + O2::DetectorsCalibration O2::Headers) o2_target_root_dictionary(FT0Simulation HEADERS diff --git a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h index 9eea2415300ee..aade6f60fb974 100644 --- a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h +++ b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h @@ -109,6 +109,8 @@ class Detector : public o2::base::DetImpl<Detector> /// \param istream *is The input stream void Read(std::istream* is); + void DefineSim2LUTindex(); + private: /// copy constructor (used in MT) Detector(const Detector& rhs); @@ -152,7 +154,9 @@ class Detector : public o2::base::DetImpl<Detector> int mTrackIdTop; int mTrackIdMCPtop; //TEMPORARY - ClassDefOverride(Detector, 2); + int mSim2LUT[Geometry::Nchannels]; + + ClassDefOverride(Detector, 3); }; // Input and output function for standard C++ input/output. diff --git a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h index 4a4b4cabd3f15..8e36a59433cea 100644 --- a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h +++ b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h @@ -42,8 +42,8 @@ class Digits2Raw static constexpr int Nchannels_FT0 = 208; static constexpr int Nchannels_PM = 12; - static constexpr int LinkTCM = 18; - static constexpr int NPMs = 19; + static constexpr int LinkTCM = 19; + static constexpr int NPMs = 20; static constexpr int GBTWordSize = 128; // with padding static constexpr int Max_Page_size = 8192; @@ -56,17 +56,6 @@ class Digits2Raw const o2::ft0::LookUpTable& lut, o2::InteractionRecord const& mIntRecord); - static o2::ft0::LookUpTable linear() - { - std::vector<o2::ft0::Topo> lut_data(Nchannels_PM * (NPMs - 1)); - for (int link = 0; link < NPMs - 1; ++link) { - for (int mcp = 0; mcp < Nchannels_PM; ++mcp) { - lut_data[link * Nchannels_PM + mcp] = o2::ft0::Topo{link, mcp}; - } - } - - return o2::ft0::LookUpTable{lut_data}; - } o2::raw::RawFileWriter& getWriter() { return mWriter; } void setFilePerLink(bool v) { mOutputPerLink = v; } diff --git a/Detectors/FIT/FT0/simulation/src/Detector.cxx b/Detectors/FIT/FT0/simulation/src/Detector.cxx index 6becdfbf2866c..c5b0845be484d 100644 --- a/Detectors/FIT/FT0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FT0/simulation/src/Detector.cxx @@ -183,6 +183,8 @@ void Detector::ConstructGeometry() tr[itr] = new TGeoTranslation(nameTr.Data(), xa[itr], ya[itr], z); tr[itr]->RegisterYourself(); stlinA->AddNode(ins, itr, tr[itr]); + LOG(INFO) << " detID " + << " " << itr << " x " << xa[itr] << " y " << ya[itr]; } TGeoRotation* rot[Geometry::NCellsC]; @@ -205,12 +207,10 @@ void Detector::ConstructGeometry() // com[itr-Geometry::NCellsA] = new TGeoCombiTrans(tr[itr],rot[itr-Geometry::NCellsA]); com[ic] = new TGeoCombiTrans(xc2[ic], yc2[ic], (zc2[ic] - 80), rot[ic]); - std::cout << ic << " " << xc2[ic] << " " << yc2[ic] << std::endl; TGeoHMatrix hm = *com[ic]; TGeoHMatrix* ph = new TGeoHMatrix(hm); stlinC->AddNode(ins, itr, ph); } - TGeoVolume* alice = gGeoManager->GetVolume("barrel"); alice->AddNode(stlinA, 1, new TGeoTranslation(0, 30., zdetA)); TGeoRotation* rotC = new TGeoRotation("rotC", 90., 0., 90., 90., 180., 0.); @@ -225,6 +225,7 @@ void Detector::ConstructOpGeometry() LOG(DEBUG) << "Creating FIT optical geometry properties"; DefineOpticalProperties(); + DefineSim2LUTindex(); } //_________________________________________ @@ -273,13 +274,10 @@ void Detector::SetOneMCP(TGeoVolume* ins) topref->AddNode(top, 1, new TGeoTranslation(0, 0, 0)); float xinv = -ptop[0] - prfv[0]; topref->AddNode(rfv, 1, new TGeoTranslation(xinv, 0, 0)); - printf(" GEOGEO refv %f , 0,0 \n", xinv); xinv = ptop[0] + prfv[0]; topref->AddNode(rfv, 2, new TGeoTranslation(xinv, 0, 0)); - printf(" GEOGEO refv %f , 0,0 \n", xinv); float yinv = -ptop[1] - prfh[1]; topref->AddNode(rfh, 1, new TGeoTranslation(0, yinv, 0)); - printf(" GEOGEO refh , 0, %f, 0 \n", yinv); yinv = ptop[1] + prfh[1]; topref->AddNode(rfh, 2, new TGeoTranslation(0, yinv, 0)); // zin = -ptop[2] - ptopblack[2]; @@ -296,6 +294,7 @@ void Detector::SetOneMCP(TGeoVolume* ins) ins->AddNode(topref, ntops, new TGeoTranslation(xin, yin, z)); z += ptopref[2] + 2. * pmcptopglass[2] + preg[2]; ins->AddNode(cat, ntops, new TGeoTranslation(xin, yin, z)); + LOG(INFO) << " n " << ntops << " x " << xin << " y " << yin; } } //Al top @@ -351,7 +350,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) fMC->CurrentVolOffID(1, mcp); float time = fMC->TrackTime() * 1.0e9; //time from seconds to ns int trackID = stack->GetCurrentTrackNumber(); - int detID = 4 * mcp + quadrant - 1; + int detID = mSim2LUT[4 * mcp + quadrant - 1]; float etot = fMC->Etot(); int iPart = fMC->TrackPid(); float enDep = fMC->Edep(); @@ -640,3 +639,30 @@ Int_t Detector::ReadOptProperties(const std::string filePath) LOG(INFO) << "Optical properties taken from the file: " << filePath.c_str() << " Number of lines read: " << iLine; return 0; } + +void Detector::DefineSim2LUTindex() +{ + // Path of the LookUp table + std::string inputDir; + const char* aliceO2env = std::getenv("O2_ROOT"); + if (aliceO2env) { + inputDir = aliceO2env; + } + inputDir += "/share/Detectors/FT0/files/"; + + std::string indPath = inputDir + "Sim2DataChannels.txt"; + indPath = gSystem->ExpandPathName(indPath.data()); // Expand $(ALICE_ROOT) into real system path + + std::ifstream infile; + infile.open(indPath.data()); + LOG(INFO) << " file open " << indPath.data(); + // Check if file is opened correctly + if (infile.fail() == true) { + LOG(ERROR) << "Error opening ascii file (it is probably a folder!): " << indPath.c_str(); + } + int fromfile; + for (int iind = 0; iind < Geometry::Nchannels; iind++) { + infile >> fromfile; + mSim2LUT[iind] = fromfile; + } +} diff --git a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx index d564780137f2e..a518b580897cc 100644 --- a/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx @@ -46,8 +46,11 @@ Continueous mode : for only bunches with data at least in 1 channel. #include "DetectorsRaw/HBFUtils.h" #include "DetectorsRaw/RawFileWriter.h" #include "CommonUtils/StringUtils.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" #include <Framework/Logger.h> #include <TStopwatch.h> +#include <TSystem.h> #include <cassert> #include <fstream> #include <vector> @@ -58,6 +61,7 @@ Continueous mode : for only bunches with data at least in 1 channel. #include <gsl/span> using namespace o2::ft0; +using CcdbManager = o2::ccdb::BasicCCDBManager; ClassImp(Digits2Raw); @@ -72,8 +76,25 @@ void Digits2Raw::readDigits(const std::string& outDir, const std::string& fileDi { LOG(INFO) << "**********Digits2Raw::convertDigits" << std::endl; - o2::ft0::LookUpTable lut{o2::ft0::Digits2Raw::linear()}; - LOG(DEBUG) << " ##### LookUp set "; + /* + std::string inputDir; + const char* aliceO2env = std::getenv("O2_ROOT"); + if (aliceO2env) { + inputDir = aliceO2env; + } + inputDir += "/share/Detectors/FT0/files/"; + + std::string lutPath = inputDir + "FT0ChannelsTable.txt"; + lutPath = gSystem->ExpandPathName(lutPath.data()); // Expand $(ALICE_ROOT) into real system path + + std::ifstream infile; + infile.open(lutPath.c_str()); + if (!infile.is_open()) { + LOG(ERROR) << "!!!! no LUT"; + } + */ + o2::ft0::LookUpTable lut{o2::ft0::LookUpTable::readTable()}; + LOG(INFO) << " ##### LookUp set "; std::string outd = outDir; if (outd.back() != '/') { @@ -149,7 +170,7 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, oldlink = nlink; mRawEventData.mEventHeader = makeGBTHeader(nlink, intRecord); nchannels = 0; - // LOG(INFO) << " switch to new link " << nlink; + LOG(DEBUG) << " switch to new link " << nlink; } auto& newData = mRawEventData.mEventData[nchannels]; bool isAside = (pmchannels[ich].ChId < 96); @@ -196,22 +217,21 @@ void Digits2Raw::convertDigits(o2::ft0::Digit bcdigits, tcmdata.amplC = ampC; tcmdata.timeA = mTriggers.timeA; tcmdata.timeC = mTriggers.timeC; - if (mVerbosity > 0) { - LOG(INFO) << " triggers read " - << " time A " << mTriggers.timeA << " time C " << mTriggers.timeC - << " amp A " << ampA << " amp C " << ampC - << " N A " << int(mTriggers.nChanA) << " N C " << int(mTriggers.nChanC) - << " trig " - << " ver " << mTriggers.getVertex() << " A " << mTriggers.getOrA() << " C " << mTriggers.getOrC(); - - LOG(INFO) << "TCMdata" - << " time A " << tcmdata.timeA << " time C " << tcmdata.timeC - << " amp A " << tcmdata.amplA << " amp C " << tcmdata.amplC - << " N A " << int(tcmdata.nChanA) << " N C " << int(tcmdata.nChanC) - << " trig " - << " ver " << tcmdata.vertex << " A " << tcmdata.orA << " C " << tcmdata.orC - << " size " << sizeof(tcmdata); - } + LOG(DEBUG) << " TCM triggers read " + << " time A " << mTriggers.timeA << " time C " << mTriggers.timeC + << " amp A " << ampA << " amp C " << ampC + << " N A " << int(mTriggers.nChanA) << " N C " << int(mTriggers.nChanC) + << " trig " + << " ver " << mTriggers.getVertex() << " A " << mTriggers.getOrA() << " C " << mTriggers.getOrC(); + + LOG(DEBUG) << "TCMdata" + << " time A " << tcmdata.timeA << " time C " << tcmdata.timeC + << " amp A " << tcmdata.amplA << " amp C " << tcmdata.amplC + << " N A " << int(tcmdata.nChanA) << " N C " << int(tcmdata.nChanC) + << " trig " + << " ver " << tcmdata.vertex << " A " << tcmdata.orA << " C " << tcmdata.orC + << " size " << sizeof(tcmdata); + auto data = mRawEventData.to_vector(1); mLinkID = uint32_t(LinkTCM); mFeeID = uint64_t(LinkTCM); diff --git a/Detectors/FIT/macros/CMakeLists.txt b/Detectors/FIT/macros/CMakeLists.txt index 8dd4aa662d117..7912e34aae684 100644 --- a/Detectors/FIT/macros/CMakeLists.txt +++ b/Detectors/FIT/macros/CMakeLists.txt @@ -14,6 +14,9 @@ o2_add_test_root_macro(readFT0hits.C o2_add_test_root_macro(readFT0digits.C PUBLIC_LINK_LIBRARIES O2::DataFormatsFT0 LABELS fit) +o2_add_test_root_macro(uploadLookUpTable.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsFT0 + LABELS fit) o2_add_test_root_macro(FT0digits2raw.C PUBLIC_LINK_LIBRARIES O2::FT0Simulation O2::DataFormatsFT0 diff --git a/Detectors/FIT/macros/uploadLookUpTable.C b/Detectors/FIT/macros/uploadLookUpTable.C new file mode 100644 index 0000000000000..b00dc587532a4 --- /dev/null +++ b/Detectors/FIT/macros/uploadLookUpTable.C @@ -0,0 +1,71 @@ +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include <DataFormatsFT0/LookUpTable.h> +#include <cstdlib> +#include <vector> +#include <fstream> +#include <iostream> +#include <map> +#include <string_view> + +o2::ft0::HVchannel::HVBoard readHVBoard(std::string_view str); +o2::ft0::Topo read_Topo(std::string_view str); + +void uploadLookUpTable() +{ + using o2::ccdb::BasicCCDBManager; + using o2::ccdb::CcdbApi; + + // std::ifstream f{filename.data()}; + std::ifstream f{"FT0ChannelsTable.txt"}; + int channel; + std::string pm, pm_channel, hv_board, hv_channel, mcp_sn, hv_cable, signal_cable; + std::vector<o2::ft0::HVchannel> table; + std::getline(f, pm); // skip one line + while (f >> channel >> pm >> pm_channel >> hv_board >> hv_channel >> mcp_sn >> hv_cable >> signal_cable) { + o2::ft0::HVchannel chan; + chan.channel = channel; + assert(std::string_view(pm_channel).substr(2, 2) == pm); + chan.pm = read_Topo(pm_channel); + chan.HV_board = readHVBoard(hv_board); + chan.MCP_SN = mcp_sn; + chan.HV_cabel = hv_cable; + chan.signal_cable = signal_cable; + table.emplace_back(chan); + } + CcdbApi api; + std::map<std::string, std::string> metadata; // can be empty + api.init("http://ccdb-test.cern.ch:8080/"); // or http://localhost:8080 for a local installation + // store abitrary user object in strongly typed manner + api.storeAsTFileAny(&table, "FT0/LookUpTable", metadata); +} + +o2::ft0::HVchannel::HVBoard readHVBoard(std::string_view str) +{ + using HVBoard = o2::ft0::HVchannel::HVBoard; + if (str == "N/A") + return HVBoard::NA; + else if (str == "A-Out") + return HVBoard::A_out; + else if (str == "A-In") + return HVBoard::A_in; + else if (str == "C-Up") + return HVBoard::C_up; + else if (str == "C-Down") + return HVBoard::C_down; + else if (str == "C-Mid") + return HVBoard::C_mid; + else { + std::cerr << "Unknown HVBoard " << str << "\n"; + std::abort(); + } +} +o2::ft0::Topo read_Topo(std::string_view str) +{ + assert(str.substr(0, 2) == "PM" && str[4] == '/' && str[5] == 'C' && str[6] == 'h'); + char side = str[2]; + uint8_t pm_num = str[3] - '0'; + uint8_t pm_ch = (str[7] - '0') * 10 + (str[8] - '0'); + assert(side == 'A' || side == 'C'); + return {(side == 'C' ? 10 : 0) + pm_num, pm_ch}; +} From 9cb10c085ec1cbf3f742b7f13262cd94d2f54d82 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 18 Dec 2020 15:26:39 +0100 Subject: [PATCH 1653/1751] Executable for chunk large raw-data files allows to split single or group of large (with many TFs) raw data files to chunks each containing at most N TFs. One can also change the grouping of the output files: e.g.: o2-raw-file-split --detect-tf0 --input-conf raw.cfg -n 10 -o split/ch --file-for cru will regroup the data in 10 chunks per output file in split/ch_0 ... split/ch_N directories and creating a single output file per CRU. The configuration file split/ch_X/<DET>raw.cfg will be created for every chunk --- Detectors/Raw/CMakeLists.txt | 6 + .../Raw/include/DetectorsRaw/RawFileWriter.h | 2 + Detectors/Raw/src/RawFileWriter.cxx | 3 +- Detectors/Raw/src/rawfileSplit.cxx | 211 ++++++++++++++++++ 4 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 Detectors/Raw/src/rawfileSplit.cxx diff --git a/Detectors/Raw/CMakeLists.txt b/Detectors/Raw/CMakeLists.txt index cda1bf6fd01a1..2c3e0258c8147 100644 --- a/Detectors/Raw/CMakeLists.txt +++ b/Detectors/Raw/CMakeLists.txt @@ -35,12 +35,18 @@ o2_add_executable(file-check PUBLIC_LINK_LIBRARIES O2::DetectorsRaw Boost::program_options) +o2_add_executable(file-split + COMPONENT_NAME raw + SOURCES src/rawfileSplit.cxx + PUBLIC_LINK_LIBRARIES O2::DetectorsRaw) + o2_add_executable(file-reader-workflow COMPONENT_NAME raw SOURCES src/rawfile-reader-workflow.cxx src/RawFileReaderWorkflow.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsRaw) + o2_add_test(HBFUtils PUBLIC_LINK_LIBRARIES O2::DetectorsRaw O2::Steer diff --git a/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h b/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h index 89de7974f4b6f..8b011feba7435 100644 --- a/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h +++ b/Detectors/Raw/include/DetectorsRaw/RawFileWriter.h @@ -240,6 +240,8 @@ class RawFileWriter return it->first; } + OutputFile& getOutputFileForLink(const LinkData& lnk) { return mFName2File[lnk.fileName]; } + int getSuperPageSize() const { return mSuperPageSize; } void setSuperPageSize(int nbytes); diff --git a/Detectors/Raw/src/RawFileWriter.cxx b/Detectors/Raw/src/RawFileWriter.cxx index b8a60d55ab682..d11832a52852e 100644 --- a/Detectors/Raw/src/RawFileWriter.cxx +++ b/Detectors/Raw/src/RawFileWriter.cxx @@ -613,8 +613,7 @@ void RawFileWriter::LinkData::fillEmptyHBHs(const IR& ir, bool dataAdded) std::string RawFileWriter::LinkData::describe() const { std::stringstream ss; - ss << "Link SubSpec=0x" << std::hex << std::setw(8) << std::setfill('0') - << RDHUtils::getSubSpec(rdhCopy) << std::dec + ss << "Link SubSpec=0x" << std::hex << std::setw(8) << std::setfill('0') << subspec << std::dec << '(' << std::setw(3) << int(RDHUtils::getCRUID(rdhCopy)) << ':' << std::setw(2) << int(RDHUtils::getLinkID(rdhCopy)) << ':' << int(RDHUtils::getEndPointID(rdhCopy)) << ") feeID=0x" << std::hex << std::setw(4) << std::setfill('0') << RDHUtils::getFEEID(rdhCopy); return ss.str(); diff --git a/Detectors/Raw/src/rawfileSplit.cxx b/Detectors/Raw/src/rawfileSplit.cxx new file mode 100644 index 0000000000000..4e5e8f2adfafe --- /dev/null +++ b/Detectors/Raw/src/rawfileSplit.cxx @@ -0,0 +1,211 @@ +// 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 rawfileCheck.h +/// @author ruben.shahoyan@cern.ch +/// @brief Checker for raw data conformity with CRU format + +#include "DetectorsRaw/RawFileReader.h" +#include "DetectorsRaw/RawFileWriter.h" +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/StringUtils.h" +#include "Framework/Logger.h" +#include <TStopwatch.h> +#include <boost/program_options.hpp> +#include <iostream> +#include <string> +#include <vector> +#include <TSystem.h> + +namespace bpo = boost::program_options; + +using namespace o2::raw; + +int main(int argc, char* argv[]) +{ + RawFileReader reader; + std::vector<std::string> fnames; + std::string config, configKeyValues; + bpo::variables_map vm; + bpo::options_description descOpt("Options"); + auto desc_add_option = descOpt.add_options(); + desc_add_option("help,h", "print this help message."); + desc_add_option("input-conf,c", bpo::value(&config)->default_value(""), "read input from configuration file"); + desc_add_option("max-tf,m", bpo::value<uint32_t>()->default_value(0xffffffff), " ID to read (counts from 0)"); + desc_add_option("verbosity,v", bpo::value<int>()->default_value(reader.getVerbosity()), "1: long report, 2 or 3: print or dump all RDH"); + desc_add_option("spsize,s", bpo::value<int>()->default_value(reader.getNominalSPageSize()), "nominal super-page size in bytes"); + desc_add_option("buffer-size,b", bpo::value<size_t>()->default_value(reader.getNominalSPageSize()), "buffer size for files preprocessing"); + desc_add_option("detect-tf0", "autodetect HBFUtils start Orbit/BC from 1st TF seen"); + desc_add_option("rorc", "impose RORC as default detector mode"); + desc_add_option("tfs-per-chunk,n", bpo::value<uint32_t>()->default_value(0xffffffff), " number of output TFs per chunk"); + desc_add_option("output-dir-prefix,o", bpo::value<std::string>()->default_value("./chunk"), "output directory prefix for raw data chunk (chunk ID will be added)"); + desc_add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,cru,link"); + + desc_add_option("configKeyValues", bpo::value(&configKeyValues)->default_value(""), "semicolon separated key=value strings"); + for (int i = 0; i < RawFileReader::NErrorsDefined; i++) { + auto ei = RawFileReader::ErrTypes(i); + desc_add_option(RawFileReader::nochk_opt(ei).c_str(), RawFileReader::nochk_expl(ei).c_str()); + } + + bpo::options_description hiddenOpt("hidden"); + hiddenOpt.add_options()("files", bpo::value(&fnames)->composing(), ""); + + bpo::options_description fullOpt("cmd"); + fullOpt.add(descOpt).add(hiddenOpt); + + bpo::positional_options_description posOpt; + posOpt.add("files", -1); + + auto printHelp = [&](std::ostream& stream) { + stream << "Usage: " << argv[0] << " [options] file0 [... fileN]" << std::endl; + stream << descOpt << std::endl; + stream << " (input files are optional if config file was provided)" << std::endl; + }; + + try { + bpo::store(bpo::command_line_parser(argc, argv) + .options(fullOpt) + .positional(posOpt) + .allow_unregistered() + .run(), + vm); + bpo::notify(vm); + if (argc == 1 || vm.count("help") || (fnames.empty() && config.empty())) { + printHelp(std::cout); + return 0; + } + o2::conf::ConfigurableParam::updateFromString(configKeyValues); + } catch (const bpo::error& e) { + std::cerr << e.what() << "\n\n"; + std::cerr << "Error parsing command line arguments\n"; + printHelp(std::cerr); + return -1; + } + + RawFileReader::RDH rdh; + LOG(INFO) << "RawDataHeader v" << int(rdh.version) << " is assumed"; + + RawFileReader::ReadoutCardType rocard = vm.count("rorc") ? RawFileReader::ReadoutCardType::RORC : RawFileReader::ReadoutCardType::CRU; + + reader.setVerbosity(vm["verbosity"].as<int>()); + reader.setNominalSPageSize(vm["spsize"].as<int>()); + reader.setMaxTFToRead(vm["max-tf"].as<uint32_t>()); + reader.setBufferSize(vm["buffer-size"].as<size_t>()); + reader.setDefaultReadoutCardType(rocard); + reader.setTFAutodetect(vm.count("detect-tf0") ? RawFileReader::FirstTFDetection::Pending : RawFileReader::FirstTFDetection::Disabled); + + std::string_view fileFor = vm["file-for"].as<std::string>(); + + uint32_t errmap = 0; + for (int i = RawFileReader::NErrorsDefined; i--;) { + auto ei = RawFileReader::ErrTypes(i); + if (RawFileReader::ErrCheckDefaults[i]) { + errmap |= 0x1 << i; + } + if (vm.count(RawFileReader::nochk_opt(ei).c_str())) { // toggle + errmap ^= 0x1 << i; + } + LOG(INFO) << ((errmap & (0x1 << i)) ? "apply " : "ignore") << " check for " << RawFileReader::ErrNames[i].data(); + } + + if (!config.empty()) { + auto inp = RawFileReader::parseInput(config); + reader.loadFromInputsMap(inp); + } + + for (int i = 0; i < fnames.size(); i++) { + reader.addFile(fnames[i]); + } + + TStopwatch sw; + sw.Start(); + + reader.setCheckErrors(errmap); + reader.init(); + + sw.Print(); + int maxTFPerChunk = vm["tfs-per-chunk"].as<uint32_t>(); + std::string outDirPrefix = vm["output-dir-prefix"].as<std::string>(), outDir = ""; + int ntf = reader.getNTimeFrames(); + int nlinks = reader.getNLinks(); + std::vector<RawFileReader::PartStat> partsSP; + std::vector<char> buffer; + std::unique_ptr<RawFileWriter> writer; + int chunkID = -1; + + for (int itf = 0; itf < ntf; itf++) { + reader.setNextTFToRead(itf); + bool reinitWriter = false; + if ((itf % maxTFPerChunk) == 0) { + reinitWriter = true; + chunkID++; + } + for (int il = 0; il < nlinks; il++) { + auto& link = reader.getLink(il); + if (!link.rewindToTF(itf)) { + continue; // this link has no data for wanted TF + } + int nParts = link.getNextTFSuperPagesStat(partsSP); + for (int ip = 0; ip < nParts; ip++) { + buffer.resize(partsSP[ip].size); + auto bread = link.readNextSuperPage(buffer.data(), &partsSP[ip]); + if (bread != partsSP[ip].size) { + LOG(ERROR) << "Link " << il << " read " << bread << " bytes instead of " << partsSP[ip].size << " expected in TF=" << itf << " part=" << ip; + } + + if (reinitWriter) { + if (writer) { // generate config for previous chunk + writer->writeConfFile(writer->getOrigin().str, "RAWDATA", o2::utils::concat_string(outDir, '/', writer->getOrigin().str, "raw.cfg")); + } + outDir = o2::utils::concat_string(outDirPrefix, "_", std::to_string(chunkID)); + if (gSystem->AccessPathName(outDir.data())) { + if (gSystem->mkdir(outDir.data(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outDir; + } else { + LOG(INFO) << "created output directory " << outDir; + } + } + writer = std::make_unique<RawFileWriter>(link.origin, link.cruDetector); + writer->useRDHVersion(RDHUtils::getVersion(link.rdhl)); + reinitWriter = false; + } + if (!writer->isLinkRegistered(RDHUtils::getSubSpec(RDHUtils::getCRUID(link.rdhl), RDHUtils::getLinkID(link.rdhl), RDHUtils::getEndPointID(link.rdhl), RDHUtils::getFEEID(link.rdhl)))) { // register the output link + std::string outFileName; + + if (fileFor == "all") { // single file for all links + outFileName = o2::utils::concat_string(outDir, "/", fileFor, ".raw"); + } else if (fileFor == "cru") { + outFileName = o2::utils::concat_string(outDir, "/", fileFor, "_", std::to_string(RDHUtils::getCRUID(link.rdhl)), ".raw"); + } else if (fileFor == "link") { + outFileName = o2::utils::concat_string(outDir, "/", fileFor, + "_", std::to_string(RDHUtils::getLinkID(link.rdhl)), + "_cru", std::to_string(RDHUtils::getCRUID(link.rdhl)), + "_ep", std::to_string(RDHUtils::getEndPointID(link.rdhl)), + "_feeid", std::to_string(RDHUtils::getFEEID(link.rdhl)), ".raw"); + } else { + throw std::runtime_error("invalid option provided for file grouping"); + } + + writer->registerLink(link.rdhl, outFileName); + } + + auto& linkW = writer->getLinkWithSubSpec(link.rdhl); + auto& outF = writer->getOutputFileForLink(linkW); + outF.write(buffer.data(), bread); + } + } + } + if (writer) { // generate config for previous chunk + writer->writeConfFile(writer->getOrigin().str, "RAWDATA", o2::utils::concat_string(outDir, '/', writer->getOrigin().str, "raw.cfg")); + } + writer.reset(); + + return 0; +} From fcffd999fd58bfc41ca78add94ff2acbd88a4484 Mon Sep 17 00:00:00 2001 From: cortesep <57937610+cortesep@users.noreply.github.com> Date: Wed, 23 Dec 2020 22:37:53 +0100 Subject: [PATCH 1654/1751] ZDC Workflow to inspect raw data (#5092) * Moving raw-parser.cxx * Simple checks on raw data * Missing file * Plot appearance * clang-format * clang-format * Correct return values * Corrections after code review * clang-format --- DataFormats/Detectors/ZDC/CMakeLists.txt | 4 +- .../ZDC/include/DataFormatsZDC/RawEventData.h | 12 +- .../Detectors/ZDC/src/RawEventData.cxx | 7 + Detectors/ZDC/CMakeLists.txt | 1 + Detectors/ZDC/base/src/ModuleConfig.cxx | 6 + Detectors/ZDC/raw/CMakeLists.txt | 31 +++ Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h | 40 +++ Detectors/ZDC/raw/src/DumpRaw.cxx | 249 ++++++++++++++++++ Detectors/ZDC/raw/src/ZDCRawLinkDef.h | 17 ++ .../{simulation => raw}/src/raw-parser.cxx | 10 +- Detectors/ZDC/simulation/CMakeLists.txt | 2 +- Detectors/ZDC/simulation/src/Digitizer.cxx | 2 +- Detectors/ZDC/simulation/src/digi2raw.cxx | 2 +- 13 files changed, 372 insertions(+), 11 deletions(-) create mode 100644 Detectors/ZDC/raw/CMakeLists.txt create mode 100644 Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h create mode 100644 Detectors/ZDC/raw/src/DumpRaw.cxx create mode 100644 Detectors/ZDC/raw/src/ZDCRawLinkDef.h rename Detectors/ZDC/{simulation => raw}/src/raw-parser.cxx (93%) diff --git a/DataFormats/Detectors/ZDC/CMakeLists.txt b/DataFormats/Detectors/ZDC/CMakeLists.txt index a5c1fec2c14c4..b36feed39b580 100644 --- a/DataFormats/Detectors/ZDC/CMakeLists.txt +++ b/DataFormats/Detectors/ZDC/CMakeLists.txt @@ -9,7 +9,7 @@ # submit itself to any jurisdiction. o2_add_library(DataFormatsZDC - SOURCES src/ChannelData.cxx src/BCData.cxx src/RecEvent.cxx + SOURCES src/ChannelData.cxx src/BCData.cxx src/RecEvent.cxx src/RawEventData.cxx src/OrbitRawData.cxx src/OrbitRecData.cxx PUBLIC_LINK_LIBRARIES O2::CommonConstants O2::CommonDataFormat O2::ZDCBase ROOT::MathCore FairRoot::Base @@ -18,4 +18,4 @@ o2_add_library(DataFormatsZDC o2_target_root_dictionary(DataFormatsZDC HEADERS include/DataFormatsZDC/BCData.h include/DataFormatsZDC/ChannelData.h include/DataFormatsZDC/RecEvent.h include/DataFormatsZDC/OrbitRawData.h - include/DataFormatsZDC/OrbitRecData.h) + include/DataFormatsZDC/OrbitRecData.h include/DataFormatsZDC/RawEventData.h) diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h index f0662d175c2b2..e96a0e95f59f6 100644 --- a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h @@ -31,6 +31,7 @@ namespace zdc constexpr unsigned short Id_w0 = 0x0; constexpr unsigned short Id_w1 = 0x1; constexpr unsigned short Id_w2 = 0x2; +constexpr unsigned short Id_wn = 0x3; constexpr int NWPerGBTW = 4; struct __attribute__((__packed__)) ChannelDataV0 { @@ -79,11 +80,14 @@ struct __attribute__((__packed__)) ChannelDataV0 { unsigned empty_5 : 32; }; +union EventChData { + UInt_t w[NWPerBc][NWPerGBTW]; + struct ChannelDataV0 f; + void reset(); +}; + struct EventData { - union { - UInt_t w[NWPerBc][NWPerGBTW]; - struct ChannelDataV0 f; - } data[NModules][NChPerModule] = {0}; + EventChData data[NModules][NChPerModule] = {0}; void print() const; void reset(); ClassDefNV(EventData, 1); diff --git a/DataFormats/Detectors/ZDC/src/RawEventData.cxx b/DataFormats/Detectors/ZDC/src/RawEventData.cxx index d988b7007da98..06155e310e2e8 100644 --- a/DataFormats/Detectors/ZDC/src/RawEventData.cxx +++ b/DataFormats/Detectors/ZDC/src/RawEventData.cxx @@ -14,6 +14,13 @@ using namespace o2::zdc; //ClassImp(EventData); +//______________________________________________________________________________ +void EventChData::reset() +{ + static constexpr int payloadSize = NWPerGBTW * sizeof(UInt_t); + memset((void*)&w[0][0], 0, payloadSize); +} + //______________________________________________________________________________ void EventData::print() const { diff --git a/Detectors/ZDC/CMakeLists.txt b/Detectors/ZDC/CMakeLists.txt index 364119694abdb..97eac3feb0cc2 100644 --- a/Detectors/ZDC/CMakeLists.txt +++ b/Detectors/ZDC/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(base) add_subdirectory(simulation) add_subdirectory(macro) +add_subdirectory(raw) diff --git a/Detectors/ZDC/base/src/ModuleConfig.cxx b/Detectors/ZDC/base/src/ModuleConfig.cxx index 9dbcf6a1ace8c..f0b0157e14a6b 100644 --- a/Detectors/ZDC/base/src/ModuleConfig.cxx +++ b/Detectors/ZDC/base/src/ModuleConfig.cxx @@ -14,6 +14,7 @@ using namespace o2::zdc; +//______________________________________________________________________________ void Module::printCh() const { printf("Module %d [ChID/FEEID R:T ]", id); @@ -23,6 +24,7 @@ void Module::printCh() const printf("\n"); } +//______________________________________________________________________________ void Module::printTrig() const { printf("Trigger conf %d: ", id); @@ -37,6 +39,7 @@ void Module::printTrig() const printf("\n"); } +//______________________________________________________________________________ void Module::print() const { printCh(); @@ -58,6 +61,7 @@ void ModuleConfig::print() const } } +//______________________________________________________________________________ void ModuleConfig::check() const { for (const auto& md : modules) { @@ -65,6 +69,7 @@ void ModuleConfig::check() const } } +//______________________________________________________________________________ void Module::check() const { // make sure that the channel has <= 2 triggers @@ -78,6 +83,7 @@ void Module::check() const } } +//______________________________________________________________________________ void Module::setChannel(int slot, int8_t chID, int16_t fID, bool read, bool trig, int tF, int tL, int tS, int tT) { if (slot < 0 || slot >= MaxChannels || chID < 0 || chID > NChannels) { diff --git a/Detectors/ZDC/raw/CMakeLists.txt b/Detectors/ZDC/raw/CMakeLists.txt new file mode 100644 index 0000000000000..64027eadc6d35 --- /dev/null +++ b/Detectors/ZDC/raw/CMakeLists.txt @@ -0,0 +1,31 @@ +# 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_library(ZDCRaw + SOURCES src/DumpRaw.cxx src/raw-parser.cxx + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase O2::ZDCSimulation + O2::DataFormatsZDC O2::CCDB O2::SimConfig O2::DPLUtils + O2::DetectorsRaw O2::Headers) + + +o2_target_root_dictionary(ZDCRaw + HEADERS include/ZDCRaw/DumpRaw.h) + +o2_add_executable(raw-parser + COMPONENT_NAME zdc + SOURCES src/raw-parser.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DPLUtils + O2::ZDCSimulation + O2::ZDCRaw + O2::DetectorsRaw + O2::DetectorsCommonDataFormats + O2::CommonUtils) + diff --git a/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h b/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h new file mode 100644 index 0000000000000..165d57d4bc9f4 --- /dev/null +++ b/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h @@ -0,0 +1,40 @@ +#include <TH1.h> +#include <TH2.h> +#include "ZDCBase/Constants.h" +#include "ZDCSimulation/ZDCSimParam.h" +#include "DataFormatsZDC/RawEventData.h" +#ifndef ALICEO2_ZDC_DUMPRAW_H_ +#define ALICEO2_ZDC_DUMPRAW_H_ +namespace o2 +{ +namespace zdc +{ +class DumpRaw +{ + public: + DumpRaw() = default; + void init(); + int process(const EventData& ev); + int process(const EventChData& ch); + int processWord(const UInt_t* word); + int getHPos(uint32_t board, uint32_t ch); + void write(); + void setVerbosity(int v) + { + mVerbosity = v; + } + int getVerbosity() const { return mVerbosity; } + + private: + void setStat(TH1* h); + int mVerbosity = 1; + TH1* mBaseline[NDigiChannels] = {0}; + TH1* mCounts[NDigiChannels] = {0}; + TH2* mSignal[NDigiChannels] = {0}; + TH2* mBunch[NDigiChannels] = {0}; + EventChData mCh; +}; +} // namespace zdc +} // namespace o2 + +#endif diff --git a/Detectors/ZDC/raw/src/DumpRaw.cxx b/Detectors/ZDC/raw/src/DumpRaw.cxx new file mode 100644 index 0000000000000..dbca59386494d --- /dev/null +++ b/Detectors/ZDC/raw/src/DumpRaw.cxx @@ -0,0 +1,249 @@ +#include <TROOT.h> +#include <TPad.h> +#include <TString.h> +#include <TStyle.h> +#include <TPaveStats.h> +#include "ZDCRaw/DumpRaw.h" +#include "CommonConstants/LHCConstants.h" +#include "ZDCSimulation/Digits2Raw.h" +#include "FairLogger.h" + +using namespace o2::zdc; + +void DumpRaw::setStat(TH1* h) +{ + TString hn = h->GetName(); + h->Draw(); + gPad->Update(); + TPaveStats* st = (TPaveStats*)h->GetListOfFunctions()->FindObject("stats"); + st->SetFillStyle(1001); + st->SetBorderSize(1); + if (hn.BeginsWith("hp")) { + st->SetOptStat(111111); + st->SetX1NDC(0.1); + st->SetX2NDC(0.3); + st->SetY1NDC(0.640); + st->SetY2NDC(0.9); + } else if (hn.BeginsWith("hc")) { + st->SetOptStat(1111); + st->SetX1NDC(0.799); + st->SetX2NDC(0.999); + st->SetY1NDC(0.829); + st->SetY2NDC(0.999); + } else if (hn.BeginsWith("hs") || hn.BeginsWith("hb")) { + st->SetOptStat(11); + st->SetX1NDC(0.799); + st->SetX2NDC(0.9995); + st->SetY1NDC(0.904); + st->SetY2NDC(0.999); + } +} + +void DumpRaw::init() +{ + gROOT->SetBatch(); + auto& sopt = ZDCSimParam::Instance(); + int nbx = (sopt.nBCAheadTrig + 1) * NTimeBinsPerBC; + Double_t xmin = -sopt.nBCAheadTrig * NTimeBinsPerBC - 0.5; + Double_t xmax = NTimeBinsPerBC - 0.5; + for (UInt_t i = 0; i < NDigiChannels; i++) { + uint32_t imod = i / NChPerModule; + uint32_t ich = i % NChPerModule; + if (mBaseline[i]) { + mBaseline[i]->Reset(); + } else { + TString hname = TString::Format("hp%d%d", imod, ich); + TString htit = TString::Format("Baseline mod. %d ch. %d;Average orbit baseline", imod, ich); + //mBaseline[i]=new TH1F(hname,htit,ADCRange,ADCMin-0.5,ADCMax+0.5); + mBaseline[i] = new TH1F(hname, htit, 16378, -0.125, ADCMax + 0.125); + } + if (mCounts[i]) { + mCounts[i]->Reset(); + } else { + TString hname = TString::Format("hc%d%d", imod, ich); + TString htit = TString::Format("Counts mod. %d ch. %d; Orbit hits", imod, ich); + mCounts[i] = new TH1F(hname, htit, o2::constants::lhc::LHCMaxBunches + 1, -0.5, o2::constants::lhc::LHCMaxBunches + 0.5); + } + if (mSignal[i]) { + mSignal[i]->Reset(); + } else { + TString hname = TString::Format("hs%d%d", imod, ich); + TString htit = TString::Format("Signal mod. %d ch. %d; Sample; ADC", imod, ich); + mSignal[i] = new TH2F(hname, htit, nbx, xmin, xmax, ADCRange, ADCMin - 0.5, ADCMax + 0.5); + } + if (mBunch[i]) { + mBunch[i]->Reset(); + } else { + TString hname = TString::Format("hb%d%d", imod, ich); + TString htit = TString::Format("Bunch mod. %d ch. %d; Sample; ADC", imod, ich); + mBunch[i] = new TH2F(hname, htit, 100, -0.5, 99.5, 36, -35.5, 0.5); + } + } + // Word id not present in payload + mCh.f.fixed_0 = Id_wn; + mCh.f.fixed_1 = Id_wn; + mCh.f.fixed_2 = Id_wn; +} + +void DumpRaw::write() +{ + TFile* f = new TFile("ZDCDumpRaw.root", "recreate"); + if (f->IsZombie()) { + LOG(FATAL) << "Cannot write to file " << f->GetName(); + return; + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mBunch[i] && mBunch[i]->GetEntries() > 0) { + setStat(mBunch[i]); + mBunch[i]->Write(); + } + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mBaseline[i] && mBaseline[i]->GetEntries() > 0) { + setStat(mBaseline[i]); + mBaseline[i]->Write(); + } + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mCounts[i] && mCounts[i]->GetEntries() > 0) { + setStat(mCounts[i]); + mCounts[i]->Write(); + } + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mSignal[i] && mSignal[i]->GetEntries() > 0) { + setStat(mSignal[i]); + mSignal[i]->Write(); + } + } + f->Close(); +} + +inline int DumpRaw::getHPos(uint32_t board, uint32_t ch) +{ + int ih = board * 4 + ch; + if (ih < NDigiChannels) { + return ih; + } else { + LOG(ERROR) << "Wrong ih " << ih << " board " << board << " ch " << ch; + return -1; + } +} + +int DumpRaw::processWord(const UInt_t* word) +{ + if (word == 0) { + printf("NULL\n"); + return 1; + } + if ((word[0] & 0x3) == Id_w0) { + for (Int_t iw = 0; iw < NWPerGBTW; iw++) { + mCh.w[0][iw] = word[iw]; + } + } else if ((word[0] & 0x3) == Id_w1) { + if (mCh.f.fixed_0 == Id_w0) { + for (Int_t iw = 0; iw < NWPerGBTW; iw++) { + mCh.w[1][iw] = word[iw]; + } + } else { + LOG(ERROR) << "Wrong word sequence"; + mCh.f.fixed_0 = Id_wn; + mCh.f.fixed_1 = Id_wn; + mCh.f.fixed_2 = Id_wn; + } + } else if ((word[0] & 0x3) == Id_w2) { + if (mCh.f.fixed_0 == Id_w0 && mCh.f.fixed_1 == Id_w1) { + for (Int_t iw = 0; iw < NWPerGBTW; iw++) { + mCh.w[2][iw] = word[iw]; + } + process(mCh); + } else { + LOG(ERROR) << "Wrong word sequence"; + } + mCh.f.fixed_0 = Id_wn; + mCh.f.fixed_1 = Id_wn; + mCh.f.fixed_2 = Id_wn; + } else { + // Word not present in payload + LOG(FATAL) << "Event format error"; + return 1; + } + return 0; +} + +int DumpRaw::process(const EventChData& ch) +{ + static constexpr int last_bc = o2::constants::lhc::LHCMaxBunches - 1; + // Not empty event + auto f = ch.f; + int ih = getHPos(f.board, f.ch); + if (mVerbosity > 0) { + for (Int_t iw = 0; iw < NWPerBc; iw++) { + Digits2Raw::print_gbt_word(ch.w[iw]); + } + } + UShort_t us[12]; + Short_t s[12]; + us[0] = f.s00; + us[1] = f.s01; + us[2] = f.s02; + us[3] = f.s03; + us[4] = f.s04; + us[5] = f.s05; + us[6] = f.s06; + us[7] = f.s07; + us[8] = f.s08; + us[9] = f.s09; + us[10] = f.s10; + us[11] = f.s11; + for (Int_t i = 0; i < 12; i++) { + if (us[i] > ADCMax) { + s[i] = us[i] - ADCRange; + } else { + s[i] = us[i]; + } + //printf("%d %u %d\n",i,us[i],s[i]); + } + if (f.Alice_3) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i - 36., Double_t(s[i])); + } + if (f.Alice_2) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i - 24., Double_t(s[i])); + } + if (f.Alice_1 || f.Auto_1) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i - 12., Double_t(s[i])); + } + if (f.Alice_0 || f.Auto_0) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i + 0., Double_t(s[i])); + Double_t bc_d = UInt_t(f.bc / 100); + Double_t bc_m = UInt_t(f.bc % 100); + mBunch[ih]->Fill(bc_m, -bc_d); + } + if (f.bc == last_bc) { + Int_t offset = f.offset - 32768; + Double_t foffset = offset / 8.; + mBaseline[ih]->Fill(foffset); + mCounts[ih]->Fill(f.hits); + } + return 0; +} + +int DumpRaw::process(const EventData& ev) +{ + for (Int_t im = 0; im < NModules; im++) { + for (Int_t ic = 0; ic < NChPerModule; ic++) { + if (ev.data[im][ic].f.fixed_0 == Id_w0 && ev.data[im][ic].f.fixed_1 == Id_w1 && ev.data[im][ic].f.fixed_2 == Id_w2) { + process(ev.data[im][ic]); + } else if (ev.data[im][ic].f.fixed_0 == 0 && ev.data[im][ic].f.fixed_1 == 0 && ev.data[im][ic].f.fixed_2 == 0) { + // Empty channel + } else { + LOG(ERROR) << "Data format error"; + } + } + } + return 0; +} diff --git a/Detectors/ZDC/raw/src/ZDCRawLinkDef.h b/Detectors/ZDC/raw/src/ZDCRawLinkDef.h new file mode 100644 index 0000000000000..71519a02a652e --- /dev/null +++ b/Detectors/ZDC/raw/src/ZDCRawLinkDef.h @@ -0,0 +1,17 @@ +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#endif diff --git a/Detectors/ZDC/simulation/src/raw-parser.cxx b/Detectors/ZDC/raw/src/raw-parser.cxx similarity index 93% rename from Detectors/ZDC/simulation/src/raw-parser.cxx rename to Detectors/ZDC/raw/src/raw-parser.cxx index 616a7eaa7ee27..b2c65d71776c2 100644 --- a/Detectors/ZDC/simulation/src/raw-parser.cxx +++ b/Detectors/ZDC/raw/src/raw-parser.cxx @@ -18,6 +18,7 @@ #include "Headers/DataHeader.h" #include "DataFormatsZDC/RawEventData.h" #include "ZDCSimulation/Digits2Raw.h" +#include "ZDCRaw/DumpRaw.h" #include <vector> #include <sstream> @@ -44,7 +45,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) AlgorithmSpec{[](InitContext& setup) { auto loglevel = setup.options().get<int>("log-level"); return adaptStateless([loglevel](InputRecord& inputs, DataAllocator& outputs) { - DPLRawParser parser(inputs); + o2::zdc::DumpRaw zdc_dr; + zdc_dr.init(); + zdc_dr.setVerbosity(loglevel); + DPLRawParser parser(inputs); o2::header::DataHeader const* lastDataHeader = nullptr; std::stringstream rdhprintout; for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { @@ -82,7 +86,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) } if(payload!=0){ for(Int_t ip=0; ip<payloadSize; ip+=16){ - o2::zdc::Digits2Raw::print_gbt_word((const UInt_t*)&payload[ip]); + //o2::zdc::Digits2Raw::print_gbt_word((const UInt_t*)&payload[ip]); + zdc_dr.processWord((const UInt_t*)&payload[ip]); } } } @@ -91,6 +96,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) if (loglevel > 0) { LOG(INFO) << rdhprintout.str(); } + zdc_dr.write(); }); }}, Options{ {"log-level", VariantType::Int, 1, {"Logging level [0-2]"}}}}); diff --git a/Detectors/ZDC/simulation/CMakeLists.txt b/Detectors/ZDC/simulation/CMakeLists.txt index e4dc53138c392..e96e992eca329 100644 --- a/Detectors/ZDC/simulation/CMakeLists.txt +++ b/Detectors/ZDC/simulation/CMakeLists.txt @@ -11,7 +11,7 @@ o2_add_library(ZDCSimulation SOURCES src/Detector.cxx src/Digitizer.cxx src/SimCondition.cxx src/ZDCSimParam.cxx src/SpatialPhotonResponse.cxx src/Digits2Raw.cxx - PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase O2::DataFormatsZDC O2::CCDB O2::SimConfig O2::DetectorsRaw O2::Headers) diff --git a/Detectors/ZDC/simulation/src/Digitizer.cxx b/Detectors/ZDC/simulation/src/Digitizer.cxx index 536fd5070ba3b..ab34933392945 100644 --- a/Detectors/ZDC/simulation/src/Digitizer.cxx +++ b/Detectors/ZDC/simulation/src/Digitizer.cxx @@ -471,7 +471,7 @@ void Digitizer::refreshCCDB() } } if (md.feeID[ic] < 0 || md.feeID[ic] >= NLinks) { - LOG(ERROR) << "FEEID " << md.feeID[ic] << " not in allowed range [0:" << NLinks << ")"; + LOG(FATAL) << "FEEID " << md.feeID[ic] << " not in allowed range [0:" << NLinks << ")"; } } } else { diff --git a/Detectors/ZDC/simulation/src/digi2raw.cxx b/Detectors/ZDC/simulation/src/digi2raw.cxx index ef4c62bd85132..8d06d3993051c 100644 --- a/Detectors/ZDC/simulation/src/digi2raw.cxx +++ b/Detectors/ZDC/simulation/src/digi2raw.cxx @@ -57,7 +57,7 @@ int main(int argc, char** argv) add_option("input-file,i", bpo::value<std::string>()->default_value("zdcdigits.root"), "input ZDC digits file"); add_option("file-per-link,l", bpo::value<bool>()->default_value(false)->implicit_value(true), "create output file per CRU (default: write single file)"); add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); - add_option("ccdb-url,c", bpo::value<std::string>()->default_value(""), "url of the ccdb repository"); + add_option("ccdb-url,o", bpo::value<std::string>()->default_value(""), "url of the ccdb repository"); uint32_t defRDH = o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>(); add_option("rdh-version,r", bpo::value<uint32_t>()->default_value(defRDH), "RDH version to use"); add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); From 9d75196a36953f5483b0f02822198c3388c92349 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 23 Dec 2020 12:25:20 +0100 Subject: [PATCH 1655/1751] GPU: Some work towards making the o2 propagator work on GPU --- .../TrackLTIntegral.h | 31 +++---- .../Reconstruction/src/TrackLTIntegral.cxx | 9 +- .../Base/include/DetectorsBase/Propagator.h | 87 ++++++++++--------- Detectors/Base/src/Propagator.cxx | 58 ++++++------- 4 files changed, 100 insertions(+), 85 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h index 75efa94113ed1..a022717d553df 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h @@ -15,7 +15,8 @@ #ifndef ALICEO2_TRACK_LTINTEGRAL_H_ #define ALICEO2_TRACK_LTINTEGRAL_H_ -#include <Rtypes.h> +#include "GPUCommonRtypes.h" +#include "GPUCommonDef.h" #include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" @@ -27,17 +28,17 @@ namespace track class TrackLTIntegral { public: - TrackLTIntegral() = default; - TrackLTIntegral(const TrackLTIntegral& stc) = default; - ~TrackLTIntegral() = default; + GPUdDefault() TrackLTIntegral() = default; + GPUdDefault() TrackLTIntegral(const TrackLTIntegral& stc) = default; + GPUdDefault() ~TrackLTIntegral() = default; - static constexpr int getNTOFs() { return o2::track::PID::NIDs; } + GPUd() static constexpr int getNTOFs() { return o2::track::PID::NIDs; } - float getL() const { return mL; } - float getX2X0() const { return mX2X0; } - float getTOF(int id) const { return mT[id]; } + GPUd() float getL() const { return mL; } + GPUd() float getX2X0() const { return mX2X0; } + GPUd() float getTOF(int id) const { return mT[id]; } - void clear() + GPUd() void clear() { mL = 0.f; mX2X0 = 0.f; @@ -46,14 +47,14 @@ class TrackLTIntegral } } - void addStep(float dL, const TrackPar& track); - void addX2X0(float d) { mX2X0 += d; } + GPUd() void addStep(float dL, const TrackPar& track); + GPUd() void addX2X0(float d) { mX2X0 += d; } - void setL(float l) { mL = l; } - void setX2X0(float x) { mX2X0 = x; } - void setTOF(float t, int id) { mT[id] = t; } + GPUd() void setL(float l) { mL = l; } + GPUd() void setX2X0(float x) { mX2X0 = x; } + GPUd() void setTOF(float t, int id) { mT[id] = t; } - void print() const; + GPUd() void print() const; private: float mL = 0.; // length in cm diff --git a/DataFormats/Reconstruction/src/TrackLTIntegral.cxx b/DataFormats/Reconstruction/src/TrackLTIntegral.cxx index bbb4461c47a26..2a680eea1293f 100644 --- a/DataFormats/Reconstruction/src/TrackLTIntegral.cxx +++ b/DataFormats/Reconstruction/src/TrackLTIntegral.cxx @@ -10,22 +10,27 @@ #include "ReconstructionDataFormats/TrackLTIntegral.h" #include "CommonConstants/PhysicsConstants.h" + +#ifndef GPUCA_GPUCODE_DEVICE #include <cmath> +#endif using namespace o2::track; //_____________________________________________________ -void TrackLTIntegral::print() const +GPUd() void TrackLTIntegral::print() const { +#ifndef GPUCA_GPUCODE_DEVICE printf("L(cm): %6.2f, X2X0: %5.3f TOF(ps): ", getL(), getX2X0()); for (int i = 0; i < getNTOFs(); i++) { printf(" %7.1f |", getTOF(i)); } printf("\n"); +#endif } //_____________________________________________________ -void TrackLTIntegral::addStep(float dL, const TrackPar& track) +GPUd() void TrackLTIntegral::addStep(float dL, const TrackPar& track) { ///< add step in cm to integrals mL += dL; diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index 18084df865027..c882bbb127b9e 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -15,13 +15,18 @@ #ifndef ALICEO2_BASE_PROPAGATOR_ #define ALICEO2_BASE_PROPAGATOR_ -#include <string> +#include "GPUCommonRtypes.h" +#include "GPUCommonArray.h" #include "CommonConstants/PhysicsConstants.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/TrackLTIntegral.h" #include "DetectorsBase/MatLayerCylSet.h" +#ifndef GPUCA_GPUCODE +#include <string> +#endif + namespace o2 { namespace parameters @@ -50,50 +55,44 @@ class Propagator USEMatCorrLUT }; // flag to use LUT for material queries (user must provide a pointer - static Propagator* Instance() - { - static Propagator instance; - return &instance; - } - static constexpr float MAX_SIN_PHI = 0.85f; static constexpr float MAX_STEP = 2.0f; - bool PropagateToXBxByBz(o2::track::TrackParCov& track, float x, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; + GPUd() bool PropagateToXBxByBz(o2::track::TrackParCov& track, float x, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; - bool PropagateToXBxByBz(o2::track::TrackPar& track, float x, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; + GPUd() bool PropagateToXBxByBz(o2::track::TrackPar& track, float x, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; - bool propagateToX(o2::track::TrackParCov& track, float x, float bZ, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; + GPUd() bool propagateToX(o2::track::TrackParCov& track, float x, float bZ, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; - bool propagateToX(o2::track::TrackPar& track, float x, float bZ, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; + GPUd() bool propagateToX(o2::track::TrackPar& track, float x, float bZ, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; - bool propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, - int signCorr = 0, float maxD = 999.f) const; + GPUd() bool propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, + int signCorr = 0, float maxD = 999.f) const; - bool propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, - int signCorr = 0, float maxD = 999.f) const; + GPUd() bool propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, + int signCorr = 0, float maxD = 999.f) const; - bool propagateToDCA(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, - int signCorr = 0, float maxD = 999.f) const; + GPUd() bool propagateToDCA(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + gpu::gpustd::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, + int signCorr = 0, float maxD = 999.f) const; - bool propagateToDCABxByBz(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, - std::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, - int signCorr = 0, float maxD = 999.f) const; + GPUd() bool propagateToDCABxByBz(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + gpu::gpustd::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, + int signCorr = 0, float maxD = 999.f) const; Propagator(Propagator const&) = delete; Propagator(Propagator&&) = delete; @@ -101,19 +100,29 @@ class Propagator Propagator& operator=(Propagator&&) = delete; // Bz at the origin - float getNominalBz() const { return mBz; } + GPUd() float getNominalBz() const { return mBz; } - void setMatLUT(const o2::base::MatLayerCylSet* lut) { mMatLUT = lut; } - const o2::base::MatLayerCylSet* getMatLUT() const { return mMatLUT; } + GPUd() void setMatLUT(const o2::base::MatLayerCylSet* lut) { mMatLUT = lut; } + GPUd() const o2::base::MatLayerCylSet* getMatLUT() const { return mMatLUT; } + +#ifndef GPUCA_GPUCODE + static Propagator* Instance() + { + static Propagator instance; + return &instance; + } static int initFieldFromGRP(const o2::parameters::GRPObject* grp, bool verbose = false); static int initFieldFromGRP(const std::string grpFileName, std::string grpName = "GRP", bool verbose = false); +#endif private: +#ifndef GPUCA_GPUCODE Propagator(); ~Propagator() = default; +#endif - MatBudget getMatBudget(MatCorrType corrType, const o2::math_utils::Point3D<float>& p0, const o2::math_utils::Point3D<float>& p1) const; + GPUd() MatBudget getMatBudget(MatCorrType corrType, const o2::math_utils::Point3D<float>& p0, const o2::math_utils::Point3D<float>& p1) const; const o2::field::MagFieldFast* mField = nullptr; ///< External fast field (barrel only for the moment) float mBz = 0; // nominal field diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 52516ee8400fb..2ad4ebb335d34 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -96,8 +96,8 @@ int Propagator::initFieldFromGRP(const o2::parameters::GRPObject* grp, bool verb #endif //_______________________________________________________________________ -bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, float maxSnp, float maxStep, - Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const +GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, float maxSnp, float maxStep, + Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- // @@ -117,7 +117,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, signCorr = -dir; // sign of eloss correction is not imposed } - std::array<float, 3> b; + gpu::gpustd::array<float, 3> b; while (std::abs(dx) > Epsilon) { auto step = std::min(std::abs(dx), maxStep); if (dir < 0) { @@ -125,7 +125,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, } auto x = track.getX() + step; auto xyz0 = track.getXYZGlo(); - mField->Field(xyz0, b.data()); + mField->Field(xyz0, &b[0]); if (!track.propagateTo(x, b)) { return false; @@ -155,8 +155,8 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float xToGo, } //_______________________________________________________________________ -bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, float maxSnp, float maxStep, - Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const +GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, float maxSnp, float maxStep, + Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- // @@ -176,7 +176,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, flo signCorr = -dir; // sign of eloss correction is not imposed } - std::array<float, 3> b; + gpu::gpustd::array<float, 3> b; while (std::abs(dx) > Epsilon) { auto step = std::min(std::abs(dx), maxStep); if (dir < 0) { @@ -184,7 +184,7 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, flo } auto x = track.getX() + step; auto xyz0 = track.getXYZGlo(); - mField->Field(xyz0, b.data()); + mField->Field(xyz0, &b[0]); if (!track.propagateParamTo(x, b)) { return false; @@ -213,8 +213,8 @@ bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xToGo, flo } //_______________________________________________________________________ -bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float bZ, float maxSnp, float maxStep, - Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const +GPUd() bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float bZ, float maxSnp, float maxStep, + Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- // @@ -271,8 +271,8 @@ bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, float } //_______________________________________________________________________ -bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, float maxSnp, float maxStep, - Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const +GPUd() bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, float maxSnp, float maxStep, + Propagator::MatCorrType matCorr, o2::track::TrackLTIntegral* tofInfo, int signCorr) const { //---------------------------------------------------------------- // @@ -329,10 +329,10 @@ bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, float bZ, } //_______________________________________________________________________ -bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, - float maxStep, Propagator::MatCorrType matCorr, - o2::dataformats::DCA* dca, o2::track::TrackLTIntegral* tofInfo, - int signCorr, float maxD) const +GPUd() bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, + float maxStep, Propagator::MatCorrType matCorr, + o2::dataformats::DCA* dca, o2::track::TrackLTIntegral* tofInfo, + int signCorr, float maxD) const { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); @@ -374,10 +374,10 @@ bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::trac } //_______________________________________________________________________ -bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, - float maxStep, Propagator::MatCorrType matCorr, - o2::dataformats::DCA* dca, o2::track::TrackLTIntegral* tofInfo, - int signCorr, float maxD) const +GPUd() bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, + float maxStep, Propagator::MatCorrType matCorr, + o2::dataformats::DCA* dca, o2::track::TrackLTIntegral* tofInfo, + int signCorr, float maxD) const { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); @@ -419,10 +419,10 @@ bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2 } //_______________________________________________________________________ -bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, - float maxStep, Propagator::MatCorrType matCorr, - std::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, - int signCorr, float maxD) const +GPUd() bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, + float maxStep, Propagator::MatCorrType matCorr, + gpu::gpustd::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, + int signCorr, float maxD) const { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); @@ -463,10 +463,10 @@ bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2::track } //_______________________________________________________________________ -bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, - float maxStep, Propagator::MatCorrType matCorr, - std::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, - int signCorr, float maxD) const +GPUd() bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, + float maxStep, Propagator::MatCorrType matCorr, + gpu::gpustd::array<float, 2>* dca, o2::track::TrackLTIntegral* tofInfo, + int signCorr, float maxD) const { // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); @@ -507,7 +507,7 @@ bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& vtx, o2: } //____________________________________________________________ -MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, const math_utils::Point3D<float>& p0, const math_utils::Point3D<float>& p1) const +GPUd() MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, const math_utils::Point3D<float>& p0, const math_utils::Point3D<float>& p1) const { #ifndef GPUCA_STANDALONE if (corrType == MatCorrType::USEMatCorrTGeo) { From 1e6f07a5cedb4bf5ae43b36be76e0e3a98a285a1 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 23 Dec 2020 12:16:43 +0100 Subject: [PATCH 1656/1751] GPU: Exclude ITS Tracking / Vertexing parts from run time compilation --- GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h index ff17a30c19bd6..ece919daa8a90 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h @@ -95,13 +95,13 @@ using namespace GPUCA_NAMESPACE::gpu; // Files for ITS Track Fit #include "GPUITSFitterKernels.cxx" -#if !defined(GPUCA_O2_LIB) && defined(__HIPCC__) && !defined(GPUCA_NO_ITS_TRAITS) +#if !defined(GPUCA_O2_LIB) && defined(__HIPCC__) && !defined(GPUCA_NO_ITS_TRAITS) && !defined(GPUCA_GPUCODE_GENRTC) #include "VertexerTraitsHIP.hip.cxx" #include "ContextHIP.hip.cxx" #include "DeviceStoreVertexerHIP.hip.cxx" #include "ClusterLinesHIP.hip.cxx" #include "UtilsHIP.hip.cxx" -#elif !defined(GPUCA_O2_LIB) && defined(__CUDACC__) && !defined(GPUCA_NO_ITS_TRAITS) +#elif !defined(GPUCA_O2_LIB) && defined(__CUDACC__) && !defined(GPUCA_NO_ITS_TRAITS) && !defined(GPUCA_GPUCODE_GENRTC) #include "TrackerTraitsNV.cu" #include "VertexerTraitsGPU.cu" #include "Context.cu" From 7f9d9f8bc9c2bd75e1c5a20712c411bf3a904a4c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 24 Dec 2020 18:55:48 +0100 Subject: [PATCH 1657/1751] GPU: Add option to o2 propagator to optionally use GPU PolynomialField instead of normal o2 MagFieldFast --- Detectors/Base/CMakeLists.txt | 8 ++++-- .../Base/include/DetectorsBase/Propagator.h | 11 +++++++- Detectors/Base/src/Propagator.cxx | 28 ++++++++++++++++--- .../Merger/GPUTPCGMPolynomialField.h | 2 +- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Detectors/Base/CMakeLists.txt b/Detectors/Base/CMakeLists.txt index 5d0b031415a4c..dda6c34f843a1 100644 --- a/Detectors/Base/CMakeLists.txt +++ b/Detectors/Base/CMakeLists.txt @@ -16,7 +16,7 @@ o2_add_library(DetectorsBase src/MatLayerCyl.cxx src/MatLayerCylSet.cxx src/Ray.cxx - src/DCAFitter.cxx + src/DCAFitter.cxx src/BaseDPLDigitizer.cxx src/CTFCoderBase.cxx PUBLIC_LINK_LIBRARIES FairRoot::Base @@ -29,8 +29,10 @@ o2_add_library(DetectorsBase O2::Framework FairMQ::FairMQ O2::DataFormatsParameters - O2::SimConfig - ROOT::VMC) + O2::SimConfig + ROOT::VMC + PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/GPU/GPUTracking/Merger # Must not link to avoid cyclic dependency + ) o2_target_root_dictionary(DetectorsBase HEADERS include/DetectorsBase/Detector.h diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index c882bbb127b9e..8a85455d251bb 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -44,6 +44,11 @@ namespace field class MagFieldFast; } +namespace gpu +{ +class GPUTPCGMPolynomialField; +} + namespace base { class Propagator @@ -104,6 +109,8 @@ class Propagator GPUd() void setMatLUT(const o2::base::MatLayerCylSet* lut) { mMatLUT = lut; } GPUd() const o2::base::MatLayerCylSet* getMatLUT() const { return mMatLUT; } + GPUd() void setGPUField(const o2::gpu::GPUTPCGMPolynomialField* field) { mGPUField = field; } + GPUd() const o2::gpu::GPUTPCGMPolynomialField* getGPUField() const { return mGPUField; } #ifndef GPUCA_GPUCODE static Propagator* Instance() @@ -123,11 +130,13 @@ class Propagator #endif GPUd() MatBudget getMatBudget(MatCorrType corrType, const o2::math_utils::Point3D<float>& p0, const o2::math_utils::Point3D<float>& p1) const; + GPUd() void getFiedXYZ(const math_utils::Point3D<float> xyz, float* bxyz) const; const o2::field::MagFieldFast* mField = nullptr; ///< External fast field (barrel only for the moment) float mBz = 0; // nominal field - const o2::base::MatLayerCylSet* mMatLUT = nullptr; // externally set LUT + const o2::base::MatLayerCylSet* mMatLUT = nullptr; // externally set LUT + const o2::gpu::GPUTPCGMPolynomialField* mGPUField = nullptr; // externally set GPU Field ClassDef(Propagator, 0); }; diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 2ad4ebb335d34..fb2d81bfca657 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -10,13 +10,17 @@ #include "DetectorsBase/Propagator.h" #include "GPUCommonLogger.h" -#include "Field/MagFieldFast.h" +#include "GPUTPCGMPolynomialField.h" #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/Vertex.h" using namespace o2::base; -#ifndef GPUCA_STANDALONE +#if !defined(GPUCA_GPUCODE) +#include "Field/MagFieldFast.h" // Don't use this on the GPU +#endif + +#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE) #include "Field/MagneticField.h" #include "DataFormatsParameters/GRPObject.h" #include "DetectorsBase/GeometryManager.h" @@ -125,7 +129,7 @@ GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float } auto x = track.getX() + step; auto xyz0 = track.getXYZGlo(); - mField->Field(xyz0, &b[0]); + getFiedXYZ(xyz0, &b[0]); if (!track.propagateTo(x, b)) { return false; @@ -184,7 +188,7 @@ GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xTo } auto x = track.getX() + step; auto xyz0 = track.getXYZGlo(); - mField->Field(xyz0, &b[0]); + getFiedXYZ(xyz0, &b[0]); if (!track.propagateParamTo(x, b)) { return false; @@ -516,3 +520,19 @@ GPUd() MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, cons #endif return mMatLUT->getMatBudget(p0.X(), p0.Y(), p0.Z(), p1.X(), p1.Y(), p1.Z()); } + +GPUd() void Propagator::getFiedXYZ(const math_utils::Point3D<float> xyz, float* bxyz) const +{ + if (mGPUField) { +#if defined(GPUCA_GPUCODE_DEVICE) && defined(GPUCA_HAS_GLOBAL_SYMBOL_CONSTANT_MEM) + const auto* f = &GPUCA_CONSMEM.param.polynomialField; // Access directly from constant memory on GPU (copied here to avoid complicated header dependencies) +#else + const auto* f = mGPUField; +#endif + f->GetField(xyz.X(), xyz.Y(), xyz.Z(), bxyz); + } else { +#ifndef GPUCA_GPUCODE + mField->Field(xyz, bxyz); // Must not call the host-only function in GPU compilation +#endif + } +} diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h b/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h index 674bd8092a789..f31dd05d9618e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h @@ -14,7 +14,7 @@ #ifndef GPUTPCGMPOLYNOMIALFIELD_H #define GPUTPCGMPOLYNOMIALFIELD_H -#include "GPUTPCDef.h" +#include "GPUCommonDef.h" namespace GPUCA_NAMESPACE { From 5040415d901c213e47b1ff69c618dc3d7440fc62 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 24 Dec 2020 20:24:52 +0100 Subject: [PATCH 1658/1751] GPU: Fix the compilation of the o2 propagator on GPU --- .../Reconstruction/src/TrackLTIntegral.cxx | 8 +- Detectors/Base/src/Propagator.cxx | 76 ++++++++++--------- .../Merger/GPUTPCGMPolynomialField.h | 12 +-- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/DataFormats/Reconstruction/src/TrackLTIntegral.cxx b/DataFormats/Reconstruction/src/TrackLTIntegral.cxx index 2a680eea1293f..3f7b39624ab8b 100644 --- a/DataFormats/Reconstruction/src/TrackLTIntegral.cxx +++ b/DataFormats/Reconstruction/src/TrackLTIntegral.cxx @@ -10,12 +10,10 @@ #include "ReconstructionDataFormats/TrackLTIntegral.h" #include "CommonConstants/PhysicsConstants.h" - -#ifndef GPUCA_GPUCODE_DEVICE -#include <cmath> -#endif +#include "GPUCommonMath.h" using namespace o2::track; +using namespace o2::gpu; //_____________________________________________________ GPUd() void TrackLTIntegral::print() const @@ -38,7 +36,7 @@ GPUd() void TrackLTIntegral::addStep(float dL, const TrackPar& track) float dTns = dL * 1000.f / o2::constants::physics::LightSpeedCm2NS; // time change in ps for beta = 1 particle for (int id = 0; id < getNTOFs(); id++) { float m2z = o2::track::PID::getMass2Z(id); - float betaInv = std::sqrt(1.f + m2z * m2z * p2); + float betaInv = CAMath::Sqrt(1.f + m2z * m2z * p2); mT[id] += dTns * betaInv; } } diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index fb2d81bfca657..2e26615b1c9e2 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -10,11 +10,13 @@ #include "DetectorsBase/Propagator.h" #include "GPUCommonLogger.h" +#include "GPUCommonMath.h" #include "GPUTPCGMPolynomialField.h" #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/Vertex.h" using namespace o2::base; +using namespace o2::gpu; #if !defined(GPUCA_GPUCODE) #include "Field/MagFieldFast.h" // Don't use this on the GPU @@ -122,8 +124,8 @@ GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float } gpu::gpustd::array<float, 3> b; - while (std::abs(dx) > Epsilon) { - auto step = std::min(std::abs(dx), maxStep); + while (CAMath::Abs(dx) > Epsilon) { + auto step = CAMath::Min(CAMath::Abs(dx), maxStep); if (dir < 0) { step = -step; } @@ -134,7 +136,7 @@ GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackParCov& track, float if (!track.propagateTo(x, b)) { return false; } - if (maxSnp > 0 && std::abs(track.getSnp()) >= maxSnp) { + if (maxSnp > 0 && CAMath::Abs(track.getSnp()) >= maxSnp) { return false; } if (matCorr != MatCorrType::USEMatCorrNONE) { @@ -181,8 +183,8 @@ GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xTo } gpu::gpustd::array<float, 3> b; - while (std::abs(dx) > Epsilon) { - auto step = std::min(std::abs(dx), maxStep); + while (CAMath::Abs(dx) > Epsilon) { + auto step = CAMath::Min(CAMath::Abs(dx), maxStep); if (dir < 0) { step = -step; } @@ -193,7 +195,7 @@ GPUd() bool Propagator::PropagateToXBxByBz(o2::track::TrackPar& track, float xTo if (!track.propagateParamTo(x, b)) { return false; } - if (maxSnp > 0 && std::abs(track.getSnp()) >= maxSnp) { + if (maxSnp > 0 && CAMath::Abs(track.getSnp()) >= maxSnp) { return false; } if (matCorr != MatCorrType::USEMatCorrNONE) { @@ -238,8 +240,8 @@ GPUd() bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, signCorr = -dir; // sign of eloss correction is not imposed } - while (std::abs(dx) > Epsilon) { - auto step = std::min(std::abs(dx), maxStep); + while (CAMath::Abs(dx) > Epsilon) { + auto step = CAMath::Min(CAMath::Abs(dx), maxStep); if (dir < 0) { step = -step; } @@ -249,7 +251,7 @@ GPUd() bool Propagator::propagateToX(o2::track::TrackParCov& track, float xToGo, if (!track.propagateTo(x, bZ)) { return false; } - if (maxSnp > 0 && std::abs(track.getSnp()) >= maxSnp) { + if (maxSnp > 0 && CAMath::Abs(track.getSnp()) >= maxSnp) { return false; } if (matCorr != MatCorrType::USEMatCorrNONE) { @@ -296,8 +298,8 @@ GPUd() bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, fl signCorr = -dir; // sign of eloss correction is not imposed } - while (std::abs(dx) > Epsilon) { - auto step = std::min(std::abs(dx), maxStep); + while (CAMath::Abs(dx) > Epsilon) { + auto step = CAMath::Min(CAMath::Abs(dx), maxStep); if (dir < 0) { step = -step; } @@ -307,7 +309,7 @@ GPUd() bool Propagator::propagateToX(o2::track::TrackPar& track, float xToGo, fl if (!track.propagateParamTo(x, bZ)) { return false; } - if (maxSnp > 0 && std::abs(track.getSnp()) >= maxSnp) { + if (maxSnp > 0 && CAMath::Abs(track.getSnp()) >= maxSnp) { return false; } if (matCorr != MatCorrType::USEMatCorrNONE) { @@ -341,27 +343,27 @@ GPUd() bool Propagator::propagateToDCA(const o2::dataformats::VertexBase& vtx, o // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); o2::math_utils::sincos(alp, sn, cs); - float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = CAMath::Sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - float d = std::abs(x * snp - y * csp); + float d = CAMath::Abs(x * snp - y * csp); if (d > maxD) { return false; } float crv = track.getCurvature(bZ); float tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; + sn = tgfv / CAMath::Sqrt(1.f + tgfv * tgfv); + cs = CAMath::Sqrt((1. - sn) * (1. + sn)); + cs = (CAMath::Abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; xv = x; auto tmpT(track); // operate on the copy to recover after the failure - alp += std::asin(sn); + alp += CAMath::ASin(sn); if (!tmpT.rotate(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); @@ -386,27 +388,27 @@ GPUd() bool Propagator::propagateToDCABxByBz(const o2::dataformats::VertexBase& // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); o2::math_utils::sincos(alp, sn, cs); - float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = CAMath::Sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ(); x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - float d = std::abs(x * snp - y * csp); + float d = CAMath::Abs(x * snp - y * csp); if (d > maxD) { return false; } float crv = track.getCurvature(mBz); float tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; + sn = tgfv / CAMath::Sqrt(1.f + tgfv * tgfv); + cs = CAMath::Sqrt((1. - sn) * (1. + sn)); + cs = (CAMath::Abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; xv = x; auto tmpT(track); // operate on the copy to recover after the failure - alp += std::asin(sn); + alp += CAMath::ASin(sn); if (!tmpT.rotate(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: "; tmpT.print(); @@ -431,27 +433,27 @@ GPUd() bool Propagator::propagateToDCA(const math_utils::Point3D<float>& vtx, o2 // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); o2::math_utils::sincos(alp, sn, cs); - float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = CAMath::Sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - float d = std::abs(x * snp - y * csp); + float d = CAMath::Abs(x * snp - y * csp); if (d > maxD) { return false; } float crv = track.getCurvature(bZ); float tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; + sn = tgfv / CAMath::Sqrt(1.f + tgfv * tgfv); + cs = CAMath::Sqrt((1. - sn) * (1. + sn)); + cs = (CAMath::Abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; xv = x; auto tmpT(track); // operate on the copy to recover after the failure - alp += std::asin(sn); + alp += CAMath::ASin(sn); if (!tmpT.rotateParam(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; @@ -475,27 +477,27 @@ GPUd() bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& v // propagate track to DCA to the vertex float sn, cs, alp = track.getAlpha(); o2::math_utils::sincos(alp, sn, cs); - float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = std::sqrt((1.f - snp) * (1.f + snp)); + float x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = CAMath::Sqrt((1.f - snp) * (1.f + snp)); float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z(); x -= xv; y -= yv; //Estimate the impact parameter neglecting the track curvature - float d = std::abs(x * snp - y * csp); + float d = CAMath::Abs(x * snp - y * csp); if (d > maxD) { return false; } float crv = track.getCurvature(mBz); float tgfv = -(crv * x - snp) / (crv * y + csp); - sn = tgfv / std::sqrt(1.f + tgfv * tgfv); - cs = std::sqrt((1. - sn) * (1. + sn)); - cs = (std::abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; + sn = tgfv / CAMath::Sqrt(1.f + tgfv * tgfv); + cs = CAMath::Sqrt((1. - sn) * (1. + sn)); + cs = (CAMath::Abs(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1; x = xv * cs + yv * sn; yv = -xv * sn + yv * cs; xv = x; auto tmpT(track); // operate on the copy to recover after the failure - alp += std::asin(sn); + alp += CAMath::ASin(sn); if (!tmpT.rotateParam(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) { LOG(WARNING) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: "; @@ -513,7 +515,7 @@ GPUd() bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& v //____________________________________________________________ GPUd() MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, const math_utils::Point3D<float>& p0, const math_utils::Point3D<float>& p1) const { -#ifndef GPUCA_STANDALONE +#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE) if (corrType == MatCorrType::USEMatCorrTGeo) { return GeometryManager::meanMaterialBudget(p0, p1); } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h b/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h index f31dd05d9618e..d334cc7ca2563 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h +++ b/GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h @@ -44,13 +44,13 @@ class GPUTPCGMPolynomialField GPUdi() float GetNominalBz() const { return mNominalBz; } - GPUd() void GetField(float x, float y, float z, float B[3]) const; + GPUd() void GetField(float x, float y, float z, float* B) const; GPUd() float GetFieldBz(float x, float y, float z) const; - GPUd() void GetFieldTrd(float x, float y, float z, float B[3]) const; + GPUd() void GetFieldTrd(float x, float y, float z, float* B) const; GPUd() float GetFieldTrdBz(float x, float y, float z) const; - GPUd() void GetFieldIts(float x, float y, float z, float B[3]) const; + GPUd() void GetFieldIts(float x, float y, float z, float* B) const; GPUd() float GetFieldItsBz(float x, float y, float z) const; void Print() const; @@ -164,7 +164,7 @@ GPUdi() void GPUTPCGMPolynomialField::GetPolynomsTpc(float x, float y, float z, f[9] = z * z; } -GPUdi() void GPUTPCGMPolynomialField::GetField(float x, float y, float z, float B[3]) const +GPUdi() void GPUTPCGMPolynomialField::GetField(float x, float y, float z, float* B) const { const float* fBxS = &mTpcBx[1]; const float* fByS = &mTpcBy[1]; @@ -220,7 +220,7 @@ GPUdi() void GPUTPCGMPolynomialField::GetPolynomsTrd(float x, float y, float z, f[19] = z * zz; } -GPUdi() void GPUTPCGMPolynomialField::GetFieldTrd(float x, float y, float z, float B[3]) const +GPUdi() void GPUTPCGMPolynomialField::GetFieldTrd(float x, float y, float z, float* B) const { float f[NTRDM]; GetPolynomsTrd(x, y, z, f); @@ -266,7 +266,7 @@ GPUdi() void GPUTPCGMPolynomialField::GetPolynomsIts(float x, float y, float z, */ } -GPUdi() void GPUTPCGMPolynomialField::GetFieldIts(float x, float y, float z, float B[3]) const +GPUdi() void GPUTPCGMPolynomialField::GetFieldIts(float x, float y, float z, float* B) const { const float* fBxS = &mItsBx[1]; const float* fByS = &mItsBy[1]; From 74ef1a94c25b826db989d47bd11ab72bf1d1a3bb Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Wed, 23 Dec 2020 12:25:33 +0100 Subject: [PATCH 1659/1751] GPU: Enable the o2 propagator when compiling for GPU --- GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h index ece919daa8a90..6ae8c9119c467 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h @@ -61,6 +61,8 @@ using namespace GPUCA_NAMESPACE::gpu; // O2 track model #include "TrackParametrization.cxx" #include "TrackParametrizationWithError.cxx" +#include "Propagator.cxx" +#include "TrackLTIntegral.cxx" // Files for GPU dEdx #include "GPUdEdx.cxx" From f28e5f04a067d87ae95bcf7728bab277f262f02b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 25 Dec 2020 11:50:22 +0100 Subject: [PATCH 1660/1751] TPC Tracking: Workaround for 0-cluster tracks --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 10 ++++++++++ GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 1 + 2 files changed, 11 insertions(+) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 8f9a52ab3e55c..4130ac3f60651 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -164,6 +164,16 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* for (char cside = 0; cside < 2; cside++) { for (int i = 0; i < nTracks; i++) { if (tracks[i].OK() && tracks[i].CSide() == cside) { + bool hasCl = false; + for (int j = 0; j < tracks[i].NClusters(); j++) { + if (!((trackClusters[tracks[i].FirstClusterRef() + j].state & flagsReject) || (ptrs.mergedTrackHitAttachment[trackClusters[tracks[i].FirstClusterRef() + j].num] & flagsRequired) != flagsRequired)) { + hasCl = true; + break; + } + } + if (!hasCl) { + continue; + } trackSort[tmp++] = {i, tracks[i].GetParam().GetTZOffset()}; auto ncl = tracks[i].NClusters(); clBuff += ncl + (ncl + 1) / 2; // actual N clusters to store will be less diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index b81abd9b52cf6..024981340509d 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -329,6 +329,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(const GPUTPCGMMerger* GPUrestrict() merger, if (!(N + NTolerated >= GPUCA_TRACKLET_SELECTOR_MIN_HITS(mP[4]) && 2 * NTolerated <= CAMath::Max(10, N) && CheckNumericalQuality(covYYUpd))) { return (false); // TODO: NTolerated should never become that large, check what is going wrong! } + // TODO: we have looping tracks here with 0 accepted clusters in the primary leg. In that case we should refit the track using only the primary leg. if (dEdxOut) { dEdx.computedEdx(*dEdxOut, param); From 4dd515e2c4b9c8c50c2e0f3980b742e1faccc617 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 27 Dec 2020 01:38:00 +0100 Subject: [PATCH 1661/1751] DPL: use RawDeviceService to sleep in example FairMQ still has issues with system sleep... --- Framework/TestWorkflows/src/o2DiamondWorkflow.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx index eb1099cdbb7a9..34f5f8bfafe01 100644 --- a/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx +++ b/Framework/TestWorkflows/src/o2DiamondWorkflow.cxx @@ -10,6 +10,8 @@ #include "Framework/ConfigParamSpec.h" #include "Framework/CompletionPolicyHelpers.h" #include "Framework/DeviceSpec.h" +#include "Framework/RawDeviceService.h" +#include <FairMQDevice.h> #include <InfoLogger/InfoLogger.hxx> #include <chrono> @@ -57,8 +59,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& specs) {OutputSpec{{"a1"}, "TST", "A1"}, OutputSpec{{"a2"}, "TST", "A2"}}, AlgorithmSpec{adaptStateless( - [](DataAllocator& outputs, InfoLogger& logger) { - std::this_thread::sleep_for(std::chrono::seconds(rand() % 2)); + [](DataAllocator& outputs, InfoLogger& logger, RawDeviceService& device) { + device.device()->WaitFor(std::chrono::seconds(rand() % 2)); auto& aData = outputs.make<int>(OutputRef{"a1"}, 1); auto& bData = outputs.make<int>(OutputRef{"a2"}, 1); logger.log("This goes to infologger"); From 00a24b0fc8f12d1e4ec96e95cba9a57de9e09f27 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 27 Dec 2020 13:04:48 +0100 Subject: [PATCH 1662/1751] GPU: Make more headers compatible to GPU --- .../TPC/include/DataFormatsTPC/TrackTPC.h | 85 ++++++++++--------- .../include/CommonDataFormat/RangeReference.h | 53 ++++++------ 2 files changed, 70 insertions(+), 68 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h index d26d00b979ff6..0b0ddb49f774c 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h @@ -11,6 +11,7 @@ #ifndef ALICEO2_TPC_TRACKTPC #define ALICEO2_TPC_TRACKTPC +#include "GPUCommonDef.h" #include "ReconstructionDataFormats/Track.h" #include "CommonDataFormat/RangeReference.h" #include "DataFormatsTPC/ClusterNative.h" @@ -40,42 +41,42 @@ class TrackTPC : public o2::track::TrackParCov using o2::track::TrackParCov::TrackParCov; // inherit /// Default constructor - TrackTPC() = default; + GPUdDefault() TrackTPC() = default; /// Destructor - ~TrackTPC() = default; - - unsigned short getFlags() const { return mFlags; } - unsigned short getClustersSideInfo() const { return mFlags & HasBothSidesClusters; } - bool hasASideClusters() const { return mFlags & HasASideClusters; } - bool hasCSideClusters() const { return mFlags & HasCSideClusters; } - bool hasBothSidesClusters() const { return (mFlags & (HasASideClusters | HasCSideClusters)) == (HasASideClusters | HasCSideClusters); } - bool hasASideClustersOnly() const { return (mFlags & HasBothSidesClusters) == HasASideClusters; } - bool hasCSideClustersOnly() const { return (mFlags & HasBothSidesClusters) == HasCSideClusters; } - - void setHasASideClusters() { mFlags |= HasASideClusters; } - 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. - 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; } - void setTime0(float v) { mTime0 = v; } - void setChi2(float v) { mChi2 = v; } - void setOuterParam(o2::track::TrackParCov&& v) { mOuterParam = v; } - const ClusRef& getClusterRef() const { return mClustersReference; } - void shiftFirstClusterRef(int dif) { mClustersReference.setFirstEntry(dif + mClustersReference.getFirstEntry()); } - int getNClusters() const { return mClustersReference.getEntries(); } - int getNClusterReferences() const { return getNClusters(); } - void setClusterRef(uint32_t entry, uint16_t ncl) { mClustersReference.set(entry, ncl); } + GPUdDefault() ~TrackTPC() = default; + + GPUd() unsigned short getFlags() const { return mFlags; } + GPUd() unsigned short getClustersSideInfo() const { return mFlags & HasBothSidesClusters; } + GPUd() bool hasASideClusters() const { return mFlags & HasASideClusters; } + GPUd() bool hasCSideClusters() const { return mFlags & HasCSideClusters; } + GPUd() bool hasBothSidesClusters() const { return (mFlags & (HasASideClusters | HasCSideClusters)) == (HasASideClusters | HasCSideClusters); } + GPUd() bool hasASideClustersOnly() const { return (mFlags & HasBothSidesClusters) == HasASideClusters; } + GPUd() bool hasCSideClustersOnly() const { return (mFlags & HasBothSidesClusters) == HasCSideClusters; } + + GPUd() void setHasASideClusters() { mFlags |= HasASideClusters; } + GPUd() void setHasCSideClusters() { mFlags |= HasCSideClusters; } + + GPUd() float getTime0() const { return mTime0; } ///< Reference time of the track, i.e. t-bins of a primary track with eta=0. + GPUd() float getDeltaTBwd() const { return mDeltaTBwd; } ///< max possible decrement to getTimeVertex + GPUd() float getDeltaTFwd() const { return mDeltaTFwd; } ///< max possible increment to getTimeVertex + GPUd() void setDeltaTBwd(float t) { mDeltaTBwd = t; } ///< set max possible decrement to getTimeVertex + GPUd() void setDeltaTFwd(float t) { mDeltaTFwd = t; } ///< set max possible increment to getTimeVertex + + GPUd() float getChi2() const { return mChi2; } + GPUd() const o2::track::TrackParCov& getOuterParam() const { return mOuterParam; } + GPUd() void setTime0(float v) { mTime0 = v; } + GPUd() void setChi2(float v) { mChi2 = v; } + GPUd() void setOuterParam(o2::track::TrackParCov&& v) { mOuterParam = v; } + GPUd() const ClusRef& getClusterRef() const { return mClustersReference; } + GPUd() void shiftFirstClusterRef(int dif) { mClustersReference.setFirstEntry(dif + mClustersReference.getFirstEntry()); } + GPUd() int getNClusters() const { return mClustersReference.getEntries(); } + GPUd() int getNClusterReferences() const { return getNClusters(); } + GPUd() void setClusterRef(uint32_t entry, uint16_t ncl) { mClustersReference.set(entry, ncl); } template <class T> - static inline void getClusterReference(T& clinfo, int nCluster, - uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex, const ClusRef& ref) + GPUd() static inline void getClusterReference(T& clinfo, int nCluster, + uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex, const ClusRef& ref) { // data for given tracks starts at clinfo[ ref.getFirstEntry() ], // 1st ref.getEntries() cluster indices are stored as uint32_t @@ -90,15 +91,15 @@ class TrackTPC : public o2::track::TrackParCov } template <class T> - inline void getClusterReference(T& clinfo, int nCluster, - uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex) const + GPUd() inline void getClusterReference(T& clinfo, int nCluster, + uint8_t& sectorIndex, uint8_t& rowIndex, uint32_t& clusterIndex) const { getClusterReference<T>(clinfo, nCluster, sectorIndex, rowIndex, clusterIndex, mClustersReference); } template <class T> - static inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, - const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex, const ClusRef& ref) + GPUd() static inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, + const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex, const ClusRef& ref) { uint32_t clusterIndex; getClusterReference<T>(clinfo, nCluster, sectorIndex, rowIndex, clusterIndex, ref); @@ -106,22 +107,22 @@ class TrackTPC : public o2::track::TrackParCov } template <class T> - inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, - const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex) const + GPUd() inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, + const o2::tpc::ClusterNativeAccess& clusters, uint8_t& sectorIndex, uint8_t& rowIndex) const { return getCluster<T>(clinfo, nCluster, clusters, sectorIndex, rowIndex, mClustersReference); } template <class T> - inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, - const o2::tpc::ClusterNativeAccess& clusters) const + GPUd() inline const o2::tpc::ClusterNative& getCluster(T& clinfo, int nCluster, + const o2::tpc::ClusterNativeAccess& clusters) const { uint8_t sectorIndex, rowIndex; return (getCluster<T>(clinfo, nCluster, clusters, sectorIndex, rowIndex)); } - const dEdxInfo& getdEdx() const { return mdEdx; } - void setdEdx(const dEdxInfo& v) { mdEdx = v; } + GPUd() const dEdxInfo& getdEdx() const { return mdEdx; } + GPUd() void setdEdx(const dEdxInfo& v) { mdEdx = v; } private: float mTime0 = 0.f; ///< Reference Z of the track assumed for the vertex, scaled with pseudo diff --git a/DataFormats/common/include/CommonDataFormat/RangeReference.h b/DataFormats/common/include/CommonDataFormat/RangeReference.h index 1b2e77b229867..ae230bf324b4f 100644 --- a/DataFormats/common/include/CommonDataFormat/RangeReference.h +++ b/DataFormats/common/include/CommonDataFormat/RangeReference.h @@ -16,6 +16,7 @@ #define ALICEO2_RANGEREFERENCE_H #include "GPUCommonRtypes.h" +#include "GPUCommonDef.h" namespace o2 { @@ -27,22 +28,22 @@ template <typename FirstEntry = int, typename NElem = int> class RangeReference { public: - RangeReference(FirstEntry ent, NElem n) { set(ent, n); } - RangeReference(const RangeReference<FirstEntry, NElem>& src) = default; - RangeReference() = default; - ~RangeReference() = default; - void set(FirstEntry ent, NElem n) + GPUd() RangeReference(FirstEntry ent, NElem n) { set(ent, n); } + GPUdDefault() RangeReference(const RangeReference<FirstEntry, NElem>& src) = default; + GPUdDefault() RangeReference() = default; + GPUdDefault() ~RangeReference() = default; + GPUd() void set(FirstEntry ent, NElem n) { mFirstEntry = ent; mEntries = n; } - void clear() { set(0, 0); } - FirstEntry getFirstEntry() const { return mFirstEntry; } - NElem getEntries() const { return mEntries; } - void setFirstEntry(FirstEntry ent) { mFirstEntry = ent; } - void setEntries(NElem n) { mEntries = n; } - void changeEntriesBy(NElem inc) { mEntries += inc; } - bool operator==(const RangeReference& other) const + GPUd() void clear() { set(0, 0); } + GPUd() FirstEntry getFirstEntry() const { return mFirstEntry; } + GPUd() NElem getEntries() const { return mEntries; } + GPUd() void setFirstEntry(FirstEntry ent) { mFirstEntry = ent; } + GPUd() void setEntries(NElem n) { mEntries = n; } + GPUd() void changeEntriesBy(NElem inc) { mEntries += inc; } + GPUd() bool operator==(const RangeReference& other) const { return mFirstEntry == other.mFirstEntry && mEntries == other.mEntries; } @@ -58,34 +59,34 @@ class RangeReference template <int NBitsN> class RangeRefComp { - using Base = std::uint32_t; + using Base = unsigned int; private: static constexpr int NBitsTotal = sizeof(Base) * 8; static constexpr Base MaskN = ((0x1 << NBitsN) - 1); static constexpr Base MaskR = (~Base(0)) & (~MaskN); Base mData = 0; ///< packed 1st entry reference + N entries - void sanityCheck() + GPUd() void sanityCheck() { static_assert(NBitsN < NBitsTotal, "NBitsN too large"); } public: - RangeRefComp(int ent, int n) { set(ent, n); } - RangeRefComp() = default; - RangeRefComp(const RangeRefComp& src) = default; - void set(int ent, int n) + GPUd() RangeRefComp(int ent, int n) { set(ent, n); } + GPUdDefault() RangeRefComp() = default; + GPUdDefault() RangeRefComp(const RangeRefComp& src) = default; + GPUd() void set(int ent, int n) { mData = (Base(ent) << NBitsN) + (Base(n) & MaskN); } - static constexpr Base getMaxFirstEntry() { return MaskR >> NBitsN; } - static constexpr Base getMaxEntries() { return MaskN; } - int getFirstEntry() const { return mData >> NBitsN; } - int getEntries() const { return mData & ((0x1 << NBitsN) - 1); } - void setFirstEntry(int ent) { mData = (Base(ent) << NBitsN) | (mData & MaskN); } - void setEntries(int n) { mData = (mData & MaskR) | (Base(n) & MaskN); } - void changeEntriesBy(int inc) { setEntries(getEntries() + inc); } - bool operator==(const RangeRefComp& other) const + GPUd() static constexpr Base getMaxFirstEntry() { return MaskR >> NBitsN; } + GPUd() static constexpr Base getMaxEntries() { return MaskN; } + GPUd() int getFirstEntry() const { return mData >> NBitsN; } + GPUd() int getEntries() const { return mData & ((0x1 << NBitsN) - 1); } + GPUd() void setFirstEntry(int ent) { mData = (Base(ent) << NBitsN) | (mData & MaskN); } + GPUd() void setEntries(int n) { mData = (mData & MaskR) | (Base(n) & MaskN); } + GPUd() void changeEntriesBy(int inc) { setEntries(getEntries() + inc); } + GPUd() bool operator==(const RangeRefComp& other) const { return mData == other.mData; } From a7d1de4d2fb5bcebb91e4f52fe10524eff7b34d6 Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Tue, 15 Dec 2020 19:10:34 +0100 Subject: [PATCH 1663/1751] Add track dumping in standalone debugger --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 3 +- .../include/ITStracking/Definitions.h | 2 +- .../include/ITStracking/StandaloneDebugger.h | 75 ++++++++++++++++++- .../tracking/include/ITStracking/Tracker.h | 8 ++ .../ITS/tracking/src/StandaloneDebugger.cxx | 23 +++++- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 16 +++- .../ITSMFT/ITS/tracking/src/TrackingLinkDef.h | 2 +- 7 files changed, 120 insertions(+), 9 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 6e976bfeb5d02..2062b1621a4f5 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -17,7 +17,7 @@ o2_add_library(ITStracking src/Label.cxx src/PrimaryVertexContext.cxx src/Road.cxx - # src/StandaloneDebugger.cxx + src/StandaloneDebugger.cxx src/Tracker.cxx src/TrackerTraitsCPU.cxx src/TrackingConfigParam.cxx @@ -36,6 +36,7 @@ o2_target_root_dictionary(ITStracking HEADERS include/ITStracking/ClusterLines.h include/ITStracking/Tracklet.h include/ITStracking/TrackingConfigParam.h + include/ITStracking/StandaloneDebugger.h LINKDEF src/TrackingLinkDef.h) if(CUDA_ENABLED) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index b54b91801b267..2b8de64b7f682 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -21,7 +21,7 @@ #include <array> #endif -//#define CA_DEBUG +#define CA_DEBUG #ifdef CA_DEBUG #define CA_DEBUGGER(x) x diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h index 6693d13f93d90..9e9bd940af6fd 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h @@ -15,21 +15,91 @@ #ifndef O2_ITS_STANDALONE_DEBUGGER_H_ #define O2_ITS_STANDALONE_DEBUGGER_H_ +#include <string> +#include <iterator> + +// Tracker +#include "DataFormatsITS/TrackITS.h" +#include "ITStracking/ROframe.h" + namespace o2 { -class MCCompLabel; +// class MCCompLabel; namespace utils { class TreeStreamRedirector; } +// namespace its +// { +// class TrackITSExt; +// } + namespace its { class Tracklet; class Line; class ROframe; +class ClusterLines; + +using constants::its::UnusedIndex; + +struct FakeTrackInfo { + public: + FakeTrackInfo(); + FakeTrackInfo(const ROframe& event, TrackITSExt& track) : isFake{false}, isAmbiguousId{false}, mainLabel{UnusedIndex, UnusedIndex, UnusedIndex, false} + { + occurrences.clear(); + for (size_t iCluster{0}; iCluster < 7; ++iCluster) { + int extIndex = track.getClusterIndex(iCluster); + o2::MCCompLabel mcLabel = event.getClusterLabels(iCluster, extIndex); + bool found = false; + + for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) { + std::pair<o2::MCCompLabel, int>& occurrence = occurrences[iOcc]; + if (mcLabel == occurrence.first) { + ++occurrence.second; + found = true; + } + } + if (!found) { + occurrences.emplace_back(mcLabel, 1); + } + } + if (occurrences.size() > 1) { + isFake = true; + } + std::sort(std::begin(occurrences), std::end(occurrences), [](auto e1, auto e2) { + return e1.second > e2.second; + }); + mainLabel = occurrences[0].first; + + for (auto iOcc{1}; iOcc < occurrences.size(); ++iOcc) { + if (occurrences[iOcc].second == occurrences[0].second) { + isAmbiguousId = true; + break; + } + } + for (auto iCluster{0}; iCluster < TrackITSExt::MaxClusters; ++iCluster) { + int extIndex = track.getClusterIndex(iCluster); + o2::MCCompLabel lbl = event.getClusterLabels(iCluster, extIndex); + if (lbl == mainLabel && occurrences[0].second > 1 && !lbl.isNoise()) { // if 7 fake clusters -> occurrences[0].second = 1 + clusStatuses[iCluster] = 1; + } else { + clusStatuses[iCluster] = 0; + ++nFakeClusters; + } + } + } + std::vector<std::pair<MCCompLabel, int>> occurrences; + MCCompLabel mainLabel; + std::array<int, 7> clusStatuses = {-1, -1, -1, -1, -1, -1, -1}; + bool isFake; + bool isAmbiguousId; + int nFakeClusters = 0; +}; class StandaloneDebugger { @@ -59,6 +129,9 @@ class StandaloneDebugger void fillXYZHistogramTree(std::array<std::vector<int>, 3>, const std::array<int, 3>); void fillVerticesInfoTree(float x, float y, float z, int size, int rId, int eId, float pur); + // Tracker debug utilities + void dumpTrackToBranchWithInfo(const ROframe event, o2::its::TrackITSExt track, std::string branchName); + static int getBinIndex(const float, const int, const float, const float); private: diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 78fc6064750f9..76c5acd946066 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -38,6 +38,10 @@ #include "Framework/Logger.h" +#ifdef CA_DEBUG +#include "ITStracking/StandaloneDebugger.h" +#endif + namespace o2 { namespace gpu @@ -108,6 +112,10 @@ class Tracker std::vector<MCCompLabel> mTrackLabels; o2::base::MatLayerCylSet* mMatLayerCylSet = nullptr; o2::gpu::GPUChainITS* mRecoChain = nullptr; + +#ifdef CA_DEBUG + StandaloneDebugger* mDebugger; +#endif }; inline void Tracker::setParameters(const std::vector<MemoryParameters>& memPars, const std::vector<TrackingParameters>& trkPars) diff --git a/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx b/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx index 7a7b495946db0..c5da51811ee84 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx @@ -12,14 +12,15 @@ /// \brief /// \author matteo.concas@cern.ch -#include <string> -#include <iterator> + #include "ITStracking/Cluster.h" #include "ITStracking/Tracklet.h" #include "ITStracking/ClusterLines.h" #include "CommonUtils/TreeStreamRedirector.h" -#include "ITStracking/ROframe.h" #include "ITStracking/StandaloneDebugger.h" + + + #include "TH1I.h" #include "TMath.h" @@ -257,5 +258,21 @@ int StandaloneDebugger::getBinIndex(const float value, const int size, const flo return std::distance(divisions.begin(), TMath::BinarySearch(divisions.begin(), divisions.end(), value)); } +// Tracker +void StandaloneDebugger::dumpTrackToBranchWithInfo(ROframe event, o2::its::TrackITSExt track, + std::string branchName) +{ + // FakeTrackInfo t{event, track}; + + (*mTreeStream) + << branchName.data() + << track + << "\n"; + + // (*mTreeStream) + // << "TracksInfo" + // << tInfo + // << "\n"; +} } // namespace its } // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index baacef4a26514..8c1a32f8041a7 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -39,12 +39,21 @@ Tracker::Tracker(o2::its::TrackerTraits* traits) /// Initialise standard configuration with 1 iteration mTrkParams.resize(1); mMemParams.resize(1); - assert(traits != nullptr); + assert(mTracks != nullptr); mTraits = traits; mPrimaryVertexContext = mTraits->getPrimaryVertexContext(); +#ifdef CA_DEBUG + mDebugger = new StandaloneDebugger("dbg_ITSTrackerCPU.root"); +#endif } - +#ifdef CA_DEBUG +Tracker::~Tracker() +{ + delete mDebugger; +} +#else Tracker::~Tracker() = default; +#endif void Tracker::clustersToTracks(const ROframe& event, std::ostream& timeBenchmarkOutputStream) { @@ -293,6 +302,9 @@ void Tracker::findTracks(const ROframe& event) temporaryTrack.getParamOut() = temporaryTrack; temporaryTrack.resetCovariance(); fitSuccess = fitTrack(event, temporaryTrack, mTrkParams[0].NLayers - 1, -1, -1, mTrkParams[0].FitIterationMaxChi2[1]); +#ifdef CA_DEBUG + mDebugger->dumpTrackToBranchWithInfo(event, temporaryTrack, "testBranch"); +#endif if (!fitSuccess) { continue; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h index 80450e158932a..385cec4ef8450 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h @@ -18,7 +18,7 @@ #pragma link C++ class o2::its::Tracklet + ; #pragma link C++ class o2::its::VertexerParamConfig + ; -#pragma link C++ class o2::conf::ConfigurableParamHelper <o2::its::VertexerParamConfig> + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::its::VertexerParamConfig> + ; #pragma link C++ class o2::its::TrackerParamConfig + ; #pragma link C++ class o2::conf::ConfigurableParamHelper <o2::its::TrackerParamConfig> + ; From c1d61924b1bf3999cbb8006150a92b8693bd9089 Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Wed, 16 Dec 2020 21:08:48 +0100 Subject: [PATCH 1664/1751] Add TrackDebugInfo into treestream --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 1 + .../tracking/include/ITStracking/Cluster.h | 3 + .../include/ITStracking/Definitions.h | 2 +- .../include/ITStracking/StandaloneDebugger.h | 60 +++++++++++++------ .../ITS/tracking/src/StandaloneDebugger.cxx | 18 +++--- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 2 +- 6 files changed, 56 insertions(+), 30 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 2062b1621a4f5..85faf7d5f69bd 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -35,6 +35,7 @@ o2_add_library(ITStracking o2_target_root_dictionary(ITStracking HEADERS include/ITStracking/ClusterLines.h include/ITStracking/Tracklet.h + include/ITStracking/Cluster.h include/ITStracking/TrackingConfigParam.h include/ITStracking/StandaloneDebugger.h LINKDEF src/TrackingLinkDef.h) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h index 9c2d7b7fe9f40..3a5a1e478f39d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h @@ -19,6 +19,7 @@ #include <array> #endif +#include "GPUCommonRtypes.h" #include "ITStracking/Definitions.h" #include "ITStracking/MathUtils.h" @@ -43,6 +44,8 @@ struct Cluster final { float rCoordinate; // = -999.f; int clusterId; // = -1; int indexTableBinIndex; // = -1; + + ClassDefNV(Cluster, 1); }; struct TrackingFrameInfo { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index 2b8de64b7f682..96ee27299dad1 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -21,7 +21,7 @@ #include <array> #endif -#define CA_DEBUG +// #define CA_DEBUG #ifdef CA_DEBUG #define CA_DEBUGGER(x) x diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h index 9e9bd940af6fd..91ea41151e781 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h @@ -20,23 +20,17 @@ // Tracker #include "DataFormatsITS/TrackITS.h" +#include "ITStracking/PrimaryVertexContext.h" #include "ITStracking/ROframe.h" namespace o2 { -// class MCCompLabel; - namespace utils { class TreeStreamRedirector; } -// namespace its -// { -// class TrackITSExt; -// } - namespace its { class Tracklet; @@ -46,14 +40,21 @@ class ClusterLines; using constants::its::UnusedIndex; +template <int numClusters = TrackITSExt::MaxClusters> struct FakeTrackInfo { public: FakeTrackInfo(); - FakeTrackInfo(const ROframe& event, TrackITSExt& track) : isFake{false}, isAmbiguousId{false}, mainLabel{UnusedIndex, UnusedIndex, UnusedIndex, false} + FakeTrackInfo(PrimaryVertexContext* pvc, const ROframe& event, TrackITSExt& track, bool storeClusters) : isFake{false}, isAmbiguousId{false}, mainLabel{UnusedIndex, UnusedIndex, UnusedIndex, false} { occurrences.clear(); - for (size_t iCluster{0}; iCluster < 7; ++iCluster) { + for (auto& c : clusStatuses) { + c = -1; + } + for (size_t iCluster{0}; iCluster < numClusters; ++iCluster) { int extIndex = track.getClusterIndex(iCluster); + if (extIndex == -1) { + continue; + } o2::MCCompLabel mcLabel = event.getClusterLabels(iCluster, extIndex); bool found = false; @@ -62,12 +63,14 @@ struct FakeTrackInfo { if (mcLabel == occurrence.first) { ++occurrence.second; found = true; + break; } } if (!found) { occurrences.emplace_back(mcLabel, 1); } } + // LOG(WARN) << "Qui 1"; if (occurrences.size() > 1) { isFake = true; } @@ -75,31 +78,54 @@ struct FakeTrackInfo { return e1.second > e2.second; }); mainLabel = occurrences[0].first; - - for (auto iOcc{1}; iOcc < occurrences.size(); ++iOcc) { + // LOG(WARN) << "Qui 2"; + for (size_t iOcc{1}; iOcc < occurrences.size(); ++iOcc) { if (occurrences[iOcc].second == occurrences[0].second) { isAmbiguousId = true; break; } } - for (auto iCluster{0}; iCluster < TrackITSExt::MaxClusters; ++iCluster) { + // LOG(WARN) << "Qui 3"; + for (size_t iCluster{0}; iCluster < numClusters; ++iCluster) { int extIndex = track.getClusterIndex(iCluster); + if (extIndex == -1) { + continue; + } o2::MCCompLabel lbl = event.getClusterLabels(iCluster, extIndex); - if (lbl == mainLabel && occurrences[0].second > 1 && !lbl.isNoise()) { // if 7 fake clusters -> occurrences[0].second = 1 + if (lbl == mainLabel && occurrences[0].second > 1 && !lbl.isNoise()) { // if we have MaxClusters fake clusters -> occurrences[0].second = 1 clusStatuses[iCluster] = 1; } else { clusStatuses[iCluster] = 0; ++nFakeClusters; } } + // LOG(WARN) << "Qui 3.5"; + if (storeClusters) { + for (auto iCluster{0}; iCluster < numClusters; ++iCluster) { + const int index = track.getClusterIndex(iCluster); + if (index != constants::its::UnusedIndex) { + clusters[iCluster] = pvc->getClusters()[iCluster][track.getClusterIndex(iCluster)]; + } + // LOG(WARN) << "Qui 3.5.1"; + // LOG(WARN) << "\t iCLuster " << iCluster; + // LOG(WARN) << "\t getClusterIndex(iCluster) " << track.getClusterIndex(iCluster); + // LOG(WARN) << "\t externalIndex " << event.getClusterExternalIndex(iCluster, track.getClusterIndex(iCluster)); + } + } + // LOG(WARN) << "Qui 4"; } - std::vector<std::pair<MCCompLabel, int>> occurrences; + + // Data + std::vector<std::pair<MCCompLabel, int>> + occurrences; MCCompLabel mainLabel; - std::array<int, 7> clusStatuses = {-1, -1, -1, -1, -1, -1, -1}; + std::array<int, numClusters> clusStatuses; + std::array<o2::its::Cluster, numClusters> clusters; bool isFake; bool isAmbiguousId; int nFakeClusters = 0; -}; + ClassDefNV(FakeTrackInfo, 1); +}; // namespace its class StandaloneDebugger { @@ -130,7 +156,7 @@ class StandaloneDebugger void fillVerticesInfoTree(float x, float y, float z, int size, int rId, int eId, float pur); // Tracker debug utilities - void dumpTrackToBranchWithInfo(const ROframe event, o2::its::TrackITSExt track, std::string branchName); + void dumpTrackToBranchWithInfo(std::string branchName, o2::its::TrackITSExt track, const ROframe event, PrimaryVertexContext* pvc, const bool dumpClusters = false); static int getBinIndex(const float, const int, const float, const float); diff --git a/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx b/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx index c5da51811ee84..32625e1ed643d 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx @@ -12,15 +12,12 @@ /// \brief /// \author matteo.concas@cern.ch - #include "ITStracking/Cluster.h" #include "ITStracking/Tracklet.h" #include "ITStracking/ClusterLines.h" #include "CommonUtils/TreeStreamRedirector.h" #include "ITStracking/StandaloneDebugger.h" - - #include "TH1I.h" #include "TMath.h" @@ -259,20 +256,19 @@ int StandaloneDebugger::getBinIndex(const float value, const int size, const flo } // Tracker -void StandaloneDebugger::dumpTrackToBranchWithInfo(ROframe event, o2::its::TrackITSExt track, - std::string branchName) +void StandaloneDebugger::dumpTrackToBranchWithInfo(std::string branchName, o2::its::TrackITSExt track, const ROframe event, PrimaryVertexContext* pvc, const bool dumpClusters) { - // FakeTrackInfo t{event, track}; + FakeTrackInfo<7> t{pvc, event, track, dumpClusters}; (*mTreeStream) << branchName.data() << track << "\n"; - - // (*mTreeStream) - // << "TracksInfo" - // << tInfo - // << "\n"; + + (*mTreeStream) + << "TracksInfo" + << t + << "\n"; } } // namespace its } // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 8c1a32f8041a7..05530bd514fa0 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -303,7 +303,7 @@ void Tracker::findTracks(const ROframe& event) temporaryTrack.resetCovariance(); fitSuccess = fitTrack(event, temporaryTrack, mTrkParams[0].NLayers - 1, -1, -1, mTrkParams[0].FitIterationMaxChi2[1]); #ifdef CA_DEBUG - mDebugger->dumpTrackToBranchWithInfo(event, temporaryTrack, "testBranch"); + mDebugger->dumpTrackToBranchWithInfo("testBranch", temporaryTrack, event, mPrimaryVertexContext, true); #endif if (!fitSuccess) { continue; From 29db127daf27f4f4864e54a96cd2caca4f4abdce Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Thu, 17 Dec 2020 10:59:03 +0100 Subject: [PATCH 1665/1751] Add TrackingInfo to debug tree --- .../ITS/tracking/include/ITStracking/Cluster.h | 2 ++ .../tracking/include/ITStracking/Definitions.h | 2 +- .../include/ITStracking/StandaloneDebugger.h | 17 +++++++---------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h index 3a5a1e478f39d..7a64698998b37 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h @@ -59,6 +59,8 @@ struct TrackingFrameInfo { float alphaTrackingFrame; GPUArray<float, 2> positionTrackingFrame = {-1., -1.}; GPUArray<float, 3> covarianceTrackingFrame = {999., 999., 999.}; + + ClassDefNV(TrackingFrameInfo, 1); }; } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index 96ee27299dad1..2b8de64b7f682 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -21,7 +21,7 @@ #include <array> #endif -// #define CA_DEBUG +#define CA_DEBUG #ifdef CA_DEBUG #define CA_DEBUGGER(x) x diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h index 91ea41151e781..2b360a706aa28 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h @@ -70,7 +70,7 @@ struct FakeTrackInfo { occurrences.emplace_back(mcLabel, 1); } } - // LOG(WARN) << "Qui 1"; + if (occurrences.size() > 1) { isFake = true; } @@ -78,14 +78,14 @@ struct FakeTrackInfo { return e1.second > e2.second; }); mainLabel = occurrences[0].first; - // LOG(WARN) << "Qui 2"; + for (size_t iOcc{1}; iOcc < occurrences.size(); ++iOcc) { if (occurrences[iOcc].second == occurrences[0].second) { isAmbiguousId = true; break; } } - // LOG(WARN) << "Qui 3"; + for (size_t iCluster{0}; iCluster < numClusters; ++iCluster) { int extIndex = track.getClusterIndex(iCluster); if (extIndex == -1) { @@ -99,20 +99,15 @@ struct FakeTrackInfo { ++nFakeClusters; } } - // LOG(WARN) << "Qui 3.5"; if (storeClusters) { for (auto iCluster{0}; iCluster < numClusters; ++iCluster) { const int index = track.getClusterIndex(iCluster); if (index != constants::its::UnusedIndex) { - clusters[iCluster] = pvc->getClusters()[iCluster][track.getClusterIndex(iCluster)]; + clusters[iCluster] = pvc->getClusters()[iCluster][index]; + trackingFrameInfos[iCluster] = event.getTrackingFrameInfoOnLayer(iCluster).at(index); } - // LOG(WARN) << "Qui 3.5.1"; - // LOG(WARN) << "\t iCLuster " << iCluster; - // LOG(WARN) << "\t getClusterIndex(iCluster) " << track.getClusterIndex(iCluster); - // LOG(WARN) << "\t externalIndex " << event.getClusterExternalIndex(iCluster, track.getClusterIndex(iCluster)); } } - // LOG(WARN) << "Qui 4"; } // Data @@ -121,6 +116,8 @@ struct FakeTrackInfo { MCCompLabel mainLabel; std::array<int, numClusters> clusStatuses; std::array<o2::its::Cluster, numClusters> clusters; + std::array<o2::its::TrackingFrameInfo, numClusters> trackingFrameInfos; + bool isFake; bool isAmbiguousId; int nFakeClusters = 0; From f8a5ae41f18c9496d63a02e16a5e99658a0b34ff Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 29 Dec 2020 09:07:01 +0100 Subject: [PATCH 1666/1751] Drop bad assert mTracks is a `std::vector`, so you cannot check it against nullptr. --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 05530bd514fa0..ff42caa5086c9 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -39,7 +39,6 @@ Tracker::Tracker(o2::its::TrackerTraits* traits) /// Initialise standard configuration with 1 iteration mTrkParams.resize(1); mMemParams.resize(1); - assert(mTracks != nullptr); mTraits = traits; mPrimaryVertexContext = mTraits->getPrimaryVertexContext(); #ifdef CA_DEBUG From 8e1a57b5973f510335b89c3d26f2cdadfc3089a7 Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Mon, 28 Dec 2020 11:58:54 +0100 Subject: [PATCH 1667/1751] [EMCAL-675] Handling of pages without trailer In the new version of the raw format the trailer will be only on the last page. In order to be compatible with both version the last trailer word is checked for bit 30 (trailer marker), in case it found the trailer is decoded and chopped from the page as it is re-encoded when the multi-page payload is combined. Otherwise the full payload is added to the multi-page buffer. This works for single and multi-page payload and therefore consequently for the old and new raw format. --- .../reconstruction/src/RawReaderMemory.cxx | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx index 6ab48678f475a..6340cb30b9964 100644 --- a/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx +++ b/Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx @@ -113,18 +113,30 @@ void RawReaderMemory::nextPage(bool doResetPayload) } else { mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + mCurrentPosition + RDHDecoder::getHeaderSize(mRawHeader), RDHDecoder::getMemorySize(mRawHeader) - RDHDecoder::getHeaderSize(mRawHeader))); - // Read off and chop trailer + // Read off and chop trailer (if required) // - // Every page gets a trailer. The trailers from the single pages need to be removed. - // There will be a combined trailer which keeps the sum of the payloads for all trailers. - // This will be appended to the chopped payload. - auto trailer = RCUTrailer::constructFromPayloadWords(mRawBuffer.getDataWords()); - if (!mCurrentTrailer.isInitialized()) { - mCurrentTrailer = trailer; + // In case every page gets a trailer (intermediate format). The trailers from the single + // pages need to be removed. There will be a combined trailer which keeps the sum of the + // payloads for all trailers. This will be appended to the chopped payload. + // + // Trailer only at the last page (new format): Only last page gets trailer. The trailer is + // also chopped from the payload as it will be added later again. + auto lastword = *(mRawBuffer.getDataWords().rbegin()); + gsl::span<const uint32_t> payloadWithoutTrailer; + if (lastword >> 30 == 3) { + // lastword is a trailer word + // decode trailer and chop + auto trailer = RCUTrailer::constructFromPayloadWords(mRawBuffer.getDataWords()); + if (!mCurrentTrailer.isInitialized()) { + mCurrentTrailer = trailer; + } else { + mCurrentTrailer.setPayloadSize(mCurrentTrailer.getPayloadSize() + trailer.getPayloadSize()); + } + payloadWithoutTrailer = gsl::span<const uint32_t>(mRawBuffer.getDataWords().data(), mRawBuffer.getDataWords().size() - trailer.getTrailerSize()); } else { - mCurrentTrailer.setPayloadSize(mCurrentTrailer.getPayloadSize() + trailer.getPayloadSize()); + // Not a trailer word = copy page as it is + payloadWithoutTrailer = mRawBuffer.getDataWords(); // No trailer to be chopped } - gsl::span<const uint32_t> payloadWithoutTrailer(mRawBuffer.getDataWords().data(), mRawBuffer.getDataWords().size() - trailer.getTrailerSize()); mRawPayload.appendPayloadWords(payloadWithoutTrailer); mRawPayload.increasePageCount(); From 716307c516e667975af1fc8e1de2f37f0047f94f Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 25 Dec 2020 14:32:32 +0100 Subject: [PATCH 1668/1751] Fix in MCEventLabel::getIDOnly --- .../simulation/include/SimulationDataFormat/MCEventLabel.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h b/DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h index 4ff57f2be253e..170aa89470979 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h @@ -34,6 +34,8 @@ class MCEventLabel static constexpr uint32_t MaskEvID = (0x1 << nbitsEvID) - 1; // Mask to extract MC source ID static constexpr uint32_t MaskSrcID = (0x1 << nbitsSrcID) - 1; + // Mask to extract MC source and event ID only + static constexpr uint32_t MaskSrcEvID = MaskSrcID | MaskEvID; // Mask to extract MC correct contribution weight static constexpr uint32_t MaskCorrW = (0x1 << nbitsCorrW) - 1; static constexpr float WeightNorm = 1. / float(MaskCorrW); @@ -53,7 +55,7 @@ class MCEventLabel uint32_t getRawValue() const { return mLabel; } // get only combined identifier, discarding weight info - uint32_t getIDOnly() const { return mLabel & (0x1 << (nbitsEvID + nbitsSrcID)); } + uint32_t getIDOnly() const { return mLabel & MaskSrcEvID; } // compare bool compare(const MCEventLabel& other, bool strict = false) const From 6b1dd66b587ae9abb6bac2e5368154156c3209ea Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 22 Dec 2020 18:11:29 +0100 Subject: [PATCH 1669/1751] Use DBSCAN for Time-Z clustering in PVertexing + debris reduction --- .../include/DetectorsVertexing/PVertexer.h | 12 +- .../DetectorsVertexing/PVertexerHelpers.h | 22 +- .../DetectorsVertexing/PVertexerParams.h | 13 +- Detectors/Vertexing/src/PVertexer.cxx | 250 +++++++++--------- 4 files changed, 166 insertions(+), 131 deletions(-) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index 443571c0f7a0b..971614f518081 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -80,7 +80,7 @@ class PVertexer bool getValidateWithFT0() const { return mValidateWithFT0; } auto& getTracksPool() const { return mTracksPool; } - auto& getTimeClusters() const { return mTimesClusters; } + auto& getTimeZClusters() const { return mTimeZClusters; } auto& getSortedTrackIndices() const { return mSortedTrackID; } auto& getMeanVertex() const { return mMeanVertex; } @@ -92,7 +92,6 @@ class PVertexer float estimateScale2() { - float minrange = std::min(mPVParams->zHistoBinSize, mPVParams->minZSeedRange); auto sc = mPVParams->zHistoBinSize * mPVParams->zHistoBinSize * mTukey2I / (mStatZErr.getMean() * mStatZErr.getMean()); return sc; } @@ -108,11 +107,12 @@ class PVertexer void applyConstraint(VertexSeed& vtxSeed) const; bool upscaleSigma(VertexSeed& vtxSeed) const; void createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC); - void clusterizeTimeBruteForce(float margin = 0.1, float cut = 25); - void clusterizeTime(float binSize = 0.1, float maxTDist = 0.6); int findVertices(const VertexingInput& input, std::vector<PVertex>& vertices, std::vector<int>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs); std::pair<int, int> getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const; + int dbscan_RangeQuery(int idxs, std::vector<int>& cand, const std::vector<int>& status); + void dbscan_clusterize(); + o2::BunchFilling mBunchFilling; std::array<int16_t, o2::constants::lhc::LHCMaxBunches> mClosestBunchAbove; // closest filled bunch from above std::array<int16_t, o2::constants::lhc::LHCMaxBunches> mClosestBunchBelow; // closest filled bunch from below @@ -123,7 +123,9 @@ class PVertexer o2::math_utils::StatAccumulator mStatTErr; std::vector<TrackVF> mTracksPool; ///< tracks in internal representation used for vertexing std::vector<int> mSortedTrackID; ///< indices of tracks sorted in time - std::vector<TimeCluster> mTimesClusters; ///< set of time clusters + std::vector<TimeZCluster> mTimeZClusters; ///< set of time clusters + std::vector<int> mClusterTrackIDs; ///< IDs of tracks making the clusters + float mBz = 0.; ///< mag.field at beam line bool mValidateWithFT0 = false; ///< require vertex validation with FT0 (if available) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h index a9f022aac7b53..a38bf5ff37531 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h @@ -116,6 +116,23 @@ struct TrackVF { return z + tgL * (vx * cosAlp + vy * sinAlp - x); } + // weighted distance^2 to other track (accounting for own errors only) + float getDist2(const TrackVF& o) const + { + auto dtnorm2 = (timeEst.getTimeStamp() - o.timeEst.getTimeStamp()) / timeEst.getTimeStampError(); + auto dz = z - o.z; + return dtnorm2 + dz * dz * sig2ZI; + } + + // weighted distance^2 to other track (accounting for both track errors errors only) + float getDist2Sym(const TrackVF& o) const + { + auto dt = timeEst.getTimeStamp() - o.timeEst.getTimeStamp(); + auto dz = z - o.z; + float dte2 = o.timeEst.getTimeStampError() * o.timeEst.getTimeStampError() + timeEst.getTimeStampError() * timeEst.getTimeStampError(); + return dt / dte2 + dz * dz / (1. / sig2ZI + 1. / o.sig2ZI); + } + float getResiduals(const PVertex& vtx, float& dy, float& dz) const { // get residuals (Y and Z DCA in track frame) and calculate chi2 @@ -139,7 +156,6 @@ struct TrackVF { }; struct VertexingInput { - gsl::span<TrackVF> tracks; gsl::span<int> idRange; TimeEst timeEst{0, -1.}; // negative error means don't use time info float scaleSigma2 = 10; @@ -227,7 +243,7 @@ struct SeedHisto { } }; -struct TimeCluster { +struct TimeZCluster { TimeEst timeEst; int first = -1; int last = -1; @@ -275,7 +291,7 @@ struct TimeCluster { } } - void merge(TimeCluster& c) + void merge(TimeZCluster& c) { if (c.first < last) { first = c.first; diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h index fdaa52873dc1e..22e6d18a5bc43 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -25,8 +25,19 @@ namespace vertexing struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParams> { static constexpr float kDefTukey = 5.0f; ///< def.value for tukey constant + // DBSCAN clustering settings + float dbscanMaxDist2 = 9.; ///< distance^2 cut (eps^2). + float dbscanDeltaT = 10.; ///< abs. time difference cut + float dbscanAdaptCoef = 0.1; ///< adapt dbscan minPts for each cluster as minPts=max(minPts, currentSize*dbscanAdaptCoef). + + int maxVerticesPerCluster = 1; ///< max vertices per time-z cluster to look for + int maxTrialsPerCluster = 3; ///< max unsucessful trials for vertex search per vertex + + // track selection + float dcaTolerance = 1.3; ///< consider tracks within this abs DCA to mean vertex + float pullIniCut = 9; ///< cut on pull (n^2 sigma) on dca to mean vertex + // parameters - float minZSeedRange = 0.5; ///< min proximity of Zseed which should be covered by 1st iteration float zHistoRange = 20.; ///< +-range of the Zseed histo float zHistoBinSize = 0.5; ///< size of the Zseed histo bin float tukey = kDefTukey; ///< 1./[Tukey parameter]^2 diff --git a/Detectors/Vertexing/src/PVertexer.cxx b/Detectors/Vertexing/src/PVertexer.cxx index 9bddad9bed829..8226e59e0b47c 100644 --- a/Detectors/Vertexing/src/PVertexer.cxx +++ b/Detectors/Vertexing/src/PVertexer.cxx @@ -19,6 +19,7 @@ #include "Math/SVector.h" #include <numeric> #include <unordered_map> +#include <TStopwatch.h> using namespace o2::vertexing; @@ -31,18 +32,17 @@ int PVertexer::process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span std::vector<PVertex>& vertices, std::vector<GIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs) { createTracksPool(tracksITSTPC); - - //clusterizeTimeBruteForce(); - clusterizeTime(); + dbscan_clusterize(); std::vector<PVertex> verticesLoc; std::vector<int> vertexTrackIDsLoc; std::vector<V2TRef> v2tRefsLoc; std::vector<float> validationTimes; - for (auto tc : mTimesClusters) { + for (auto tc : mTimeZClusters) { VertexingInput inp; - inp.idRange = gsl::span<int>((int*)&mSortedTrackID[tc.first], tc.count); + // inp.idRange = gsl::span<int>((int*)&mSortedTrackID[tc.first], tc.count); + inp.idRange = gsl::span<int>((int*)&mClusterTrackIDs[tc.first], tc.count); inp.scaleSigma2 = 3. * estimateScale2(); inp.timeEst = tc.timeEst; findVertices(inp, verticesLoc, vertexTrackIDsLoc, v2tRefsLoc); @@ -131,20 +131,22 @@ int PVertexer::findVertices(const VertexingInput& input, std::vector<PVertex>& v if (seedHisto.nFilled < mPVParams->minTracksPerVtx) { return nfound; } - - while (1) { + LOG(DEBUG) << "New cluster: times: " << mTracksPool[input.idRange[0]].timeEst.getTimeStamp() << " : " << mTracksPool[input.idRange[ntr - 1]].timeEst.getTimeStamp() << " nfound " << nfound << " of " << ntr; // RSTMP + int nTrials = 0; + while (nfound < mPVParams->maxVerticesPerCluster && nTrials < mPVParams->maxTrialsPerCluster) { int peakBin = seedHisto.findHighestPeakBin(); // find next seed if (!seedHisto.isValidBin(peakBin)) { break; } float zv = seedHisto.getBinCenter(peakBin); - LOG(DEBUG) << "Seeding with Z=" << zv << " bin " << peakBin; + LOG(DEBUG) << "Seeding with Z=" << zv << " bin " << peakBin << " on trial " << nTrials << " for vertex " << nfound; PVertex vtx; vtx.setXYZ(mMeanVertex.getX(), mMeanVertex.getY(), zv); vtx.setTimeStamp(input.timeEst); if (findVertex(input, vtx)) { finalizeVertex(input, vtx, vertices, v2tRefs, vertexTrackIDs, seedHisto); nfound++; + nTrials = 0; } else { // suppress failed seeding bin and its proximities auto delta = std::sqrt(vtx.getChi2()) * mStatZErr.getMean() * getTukey(); // largest scale used will be transferred as chi2 int proximity = delta * seedHisto.binSizeInv; @@ -154,6 +156,7 @@ int PVertexer::findVertices(const VertexingInput& input, std::vector<PVertex>& v for (int i = bmin; i < bmax; i++) { seedHisto.discardBin(i); } + nTrials++; } } return nfound; @@ -324,7 +327,6 @@ bool PVertexer::solveVertex(VertexSeed& vtxSeed) const vtxSeed.setChi2((vtxSeed.getNContributors() - vtxSeed.wghSum) / vtxSeed.scaleSig2ITuk2I); // calculate chi^2 auto newScale = vtxSeed.wghChi2 / vtxSeed.wghSum; LOG(DEBUG) << "Solve: wghChi2=" << vtxSeed.wghChi2 << " wghSum=" << vtxSeed.wghSum << " -> scale= " << newScale << " old scale " << vtxSeed.scaleSigma2 << " prevScale: " << vtxSeed.scaleSigma2Prev; - //vtxSeed.print(); vtxSeed.setScale(newScale < mPVParams->minScale2 ? mPVParams->minScale2 : newScale, mTukey2I); return true; } @@ -466,14 +468,13 @@ void PVertexer::createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC) mTracksPool.reserve(ntGlo); // check all containers float vtxErr2 = 0.5 * (mMeanVertex.getSigmaX2() + mMeanVertex.getSigmaY2()); - float dcaToler = 1.0 + 3. * std::sqrt(vtxErr2); // RS FIXME tolerance should be a parameter float pullIniCut = 9.; // RS FIXME pullIniCut should be a parameter o2d::DCA dca; for (uint32_t i = 0; i < ntGlo; i++) { o2::track::TrackParCov trc = tracksITSTPC[i]; - if (!trc.propagateToDCA(mMeanVertex, mBz, &dca, dcaToler) || - dca.getY() * dca.getY() / (dca.getSigmaY2() + vtxErr2) > pullIniCut) { + if (!trc.propagateToDCA(mMeanVertex, mBz, &dca, mPVParams->dcaTolerance) || + dca.getY() * dca.getY() / (dca.getSigmaY2() + vtxErr2) > mPVParams->pullIniCut) { continue; } auto& tvf = mTracksPool.emplace_back(trc, tracksITSTPC[i].getTimeMUS(), i, 0); @@ -500,115 +501,6 @@ void PVertexer::createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC) auto tMax = mTracksPool[mSortedTrackID.back()].timeEst.getTimeStamp(); } -//___________________________________________________________________ -void PVertexer::clusterizeTimeBruteForce(float margin, float cut) -{ - std::vector<TimeCluster> tclist; - mTimesClusters.clear(); - auto* vtxT = &tclist.emplace_back(); - int ntr = mSortedTrackID.size(); - for (int i = 0; i < ntr; i++) { - int icur = mSortedTrackID[i]; - const auto& trc = mTracksPool[icur]; - if (!vtxT->isCompatible(trc.timeEst, margin, cut)) { - if (vtxT->count < mPVParams->minTracksPerVtx) { - vtxT->clear(); - } else { - vtxT = &tclist.emplace_back(); - } - } - vtxT->addTrack(i, trc.timeEst); - } - if (tclist.back().count < mPVParams->minTracksPerVtx) { - tclist.pop_back(); - } - // final sort in decreasing multiplicity - std::vector<int> tcselSort(tclist.size()); - std::iota(tcselSort.begin(), tcselSort.end(), 0); - - std::sort(tcselSort.begin(), tcselSort.end(), [&tclist](int i, int j) { return tclist[i].count > tclist[j].count; }); - mTimesClusters.reserve(tcselSort.size()); - for (auto i : tcselSort) { - if (tclist[i].count >= mPVParams->minTracksPerVtx) { - mTimesClusters.push_back(tclist[i]); - auto& tc = mTimesClusters.back(); - // tc.print(); - } - } -} - -//___________________________________________________________________ -void PVertexer::clusterizeTime(float binSize, float maxTDist) -{ - // moving average density - std::vector<int> tclistIdx, tcselSort; - std::vector<TimeCluster> tclist; - mTimesClusters.clear(); - - int ntr = mTracksPool.size(), first = 0, last = 0, count = 1; - float tfirst = mTracksPool[mSortedTrackID[first]].timeEst.getTimeStamp(), tlast = tfirst, tMean = tfirst; - for (int i = 1; i < ntr; i++) { - if (mTracksPool[mSortedTrackID[i]].timeEst.getTimeStamp() - tfirst < binSize) { - last = i; - tlast = mTracksPool[mSortedTrackID[last]].timeEst.getTimeStamp(); - tMean += tlast; - count++; - } else { - tclist.emplace_back(TimeCluster{{tMean / count, 0.}, first, last, count}); - first = last = i; - tMean = tfirst = mTracksPool[mSortedTrackID[last]].timeEst.getTimeStamp(); - count = 1; - } - } - tMean += mTracksPool[mSortedTrackID[last]].timeEst.getTimeStamp(); - tclist.emplace_back(TimeCluster{{tMean / count, 0.}, first, last, count}); - - int ncl = tclist.size(); - tclistIdx.resize(ncl); - tcselSort.reserve(ncl); - std::iota(tclistIdx.begin(), tclistIdx.end(), 0); - std::sort(tclistIdx.begin(), tclistIdx.end(), [&tclist](int i, int j) { return tclist[i].count > tclist[j].count; }); - - for (auto it : tclistIdx) { - auto& best = tclist[it]; - if (!best.count) { - continue; // already merged - } - // check if it can absorm neighbours - int iBef = it, iAft = it; - bool merged; - do { - merged = false; - if (--iBef >= 0) { - if (tclist[iBef].count && best.isCompatible(tclist[iBef].timeEst, 0, maxTDist)) { - best.merge(tclist[iBef]); - merged = true; - } else { - iBef = -1; // don't check those before - } - } - if (++iAft < ncl) { - if (tclist[iAft].count && best.isCompatible(tclist[iAft].timeEst, 0, maxTDist)) { - best.merge(tclist[iAft]); - merged = true; - } else { - iAft = ncl; // don't check those after - } - } - } while (merged); - if (best.count > 1) { // RS FIXME - tcselSort.push_back(it); - } - } - // final sort in decreasing multiplicity - std::sort(tcselSort.begin(), tcselSort.end(), [&tclist](int i, int j) { return tclist[i].count > tclist[j].count; }); - mTimesClusters.reserve(tcselSort.size()); - for (auto i : tcselSort) { - mTimesClusters.push_back(tclist[i]); - // mTimesClusters.back().print(); - } -} - //___________________________________________________________________ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, const std::vector<PVertex> vertices, const std::vector<o2::dataformats::VtxTrackIndex> vertexTrackIDs, const std::vector<V2TRef> v2tRefs, @@ -649,7 +541,7 @@ void PVertexer::createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::spa if (!lITS.isSet() || !lTPC.isSet()) { break; } - if (lITS.getTrackID() == lITS.getTrackID() && lITS.getEventID() == lTPC.getEventID() && lITS.getSourceID() == lTPC.getSourceID()) { + if (lITS.getTrackID() == lTPC.getTrackID() && lITS.getEventID() == lTPC.getEventID() && lITS.getSourceID() == lTPC.getSourceID()) { labelOccurenceCorr[{lITS.getEventID(), lITS.getSourceID(), 0.}]++; } else { labelOccurenceITS[{lITS.getEventID(), lITS.getSourceID(), 0.}]++; @@ -748,3 +640,117 @@ bool PVertexer::setCompatibleIR(PVertex& vtx) vtx.setIRMax(irMax); return irMax >= irMin; } + +//___________________________________________________________________ +int PVertexer::dbscan_RangeQuery(int id, std::vector<int>& cand, const std::vector<int>& status) +{ + // find neighbours for dbscan cluster core point candidate + // Since we use asymmetric distance definition, is it bit more complex than simple search within chi2 proximity + int nFound = 0; + const auto& tI = mTracksPool[mSortedTrackID[id]]; + int ntr = mTracksPool.size(); + + auto procPnt = [this, &tI, &status, &cand, &nFound, id](int idN) { + const auto& tL = this->mTracksPool[this->mSortedTrackID[idN]]; + if (std::abs(tI.timeEst.getTimeStamp() - tL.timeEst.getTimeStamp()) > this->mPVParams->dbscanDeltaT) { + return -1; + } + auto statN = status[idN], stat = status[id]; + if (statN >= 0 && (stat < 0 || (stat >= 0 && statN != stat))) { // do not consider as a neighbour if already added to other cluster + return 0; + } + auto dist2 = tL.getDist2(tI); + if (dist2 < this->mPVParams->dbscanMaxDist2) { + nFound++; + if (statN < 0) { + cand.push_back(idN); // no point in adding for check already assigned point + } + } + return 1; + }; + int idL = id; + while (--idL >= 0) { // index in time decreasing direction + if (procPnt(idL) < 0) { + break; + } + } + int idU = id; + while (++idU < ntr) { // index in time increasing direction + if (procPnt(idU) < 0) { + break; + } + } + return nFound; +} + +//_____________________________________________________ +void PVertexer::dbscan_clusterize() +{ + const int UNDEF = -2, NOISE = -1; + int ntr = mSortedTrackID.size(); + std::vector<std::vector<int>> clusters; + std::vector<int> status(ntr, UNDEF); + TStopwatch timer; + int clID = -1; + + std::vector<int> nbVec; + for (int it = 0; it < ntr; it++) { + if (status[it] != UNDEF) { + continue; + } + nbVec.clear(); + auto nnb0 = dbscan_RangeQuery(it, nbVec, status); + int minNeighbours = mPVParams->minTracksPerVtx - 1; + if (nnb0 < minNeighbours) { + status[it] = NOISE; // noise + continue; + } + if (nnb0 > minNeighbours) { + minNeighbours = std::max(minNeighbours, int(nnb0 * mPVParams->dbscanAdaptCoef)); + } + status[it] = ++clID; + auto& clusVec = clusters.emplace_back(1, it); // new cluster + + for (int j = 0; j < nnb0; j++) { + int jt = nbVec[j]; + auto statjt = status[jt]; + if (statjt >= 0) { + continue; + } + status[jt] = clID; + clusVec.push_back(jt); + if (statjt == NOISE) { // was border point, no check for being core point is needed + continue; + } + int ncurr = nbVec.size(); + if (clusVec.size() > minNeighbours) { + minNeighbours = std::max(minNeighbours, int(clusVec.size() * mPVParams->dbscanAdaptCoef)); + } + auto nnb1 = dbscan_RangeQuery(jt, nbVec, status); + if (nnb1 < minNeighbours) { + nbVec.resize(ncurr); // not a core point, reset the seeds pool to the state before RangeQuery + } else { + nnb0 = ncurr; // core point, its neighbours need to be checked + } + } + } + + mTimeZClusters.clear(); + mClusterTrackIDs.reserve(ntr); + for (const auto& clus : clusters) { + if (clus.size() < mPVParams->minTracksPerVtx) { + continue; + } + int first = mClusterTrackIDs.size(); + float tMean = 0; + for (const auto tid : clus) { + mClusterTrackIDs.push_back(mSortedTrackID[tid]); + tMean += mTracksPool[mClusterTrackIDs.back()].timeEst.getTimeStamp(); + } + int last = int(mClusterTrackIDs.size()); + int count = last - first; + mTimeZClusters.emplace_back(TimeZCluster{{tMean / count, 0.}, first, --last, count}); + } + timer.Stop(); + LOG(INFO) << "Found " << mTimeZClusters.size() << " clusters from DBSCAN out of " << clusters.size() << " seeds in " << timer.CpuTime() << " CPU s"; +} From fbb78e810ffcc66bbb9a406a8a3328841befbe92 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 10:27:56 +0100 Subject: [PATCH 1670/1751] Add workflow to generate CHANGELOG (#5106) For now it's not associated to a release. --- .github/workflows/reports.yml | 126 ++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 .github/workflows/reports.yml diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml new file mode 100644 index 0000000000000..17102316e0570 --- /dev/null +++ b/.github/workflows/reports.yml @@ -0,0 +1,126 @@ +name: Automatically create CHANGELOG for O2 releases + +on: + push: + workflow_dispatch: + schedule: + - cron: '0 0 * * *' + +jobs: + build: + runs-on: macOS-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + - uses: actions/cache@v2 + name: Configure pip caching + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - uses: octokit/graphql-action@v2.x + id: get_latest_o2_releases + with: + query: | + { + repository(name: "AliceO2", owner: "AliceO2Group") { + releases(last:14) { + edges { + node { + tagName + publishedAt + } + } + } + } + } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: octokit/graphql-action@v2.x + id: get_latest_o2_prs + with: + query: | + { + repository(name: "AliceO2", owner: "AliceO2Group") { + pullRequests(last: 100) { + edges { + node { + state + mergedAt + title + number + author { + login + } + files(last: 100) { + edges { + node { + path + } + } + } + } + } + } + } + } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Update Changelog + run: | + mkdir -p doc/data + # We create new files once per month, mostly so that + # we can keep the query results small. It does not + # matter if we get results from different months, + # as what matters is how we merge them. + CURRENT_MONTH=`date +%Y-%m` + cat <<\EOF > doc/data/${CURRENT_MONTH}-o2_releases.json + ${{ steps.get_latest_o2_releases.outputs.data }} + EOF + cat <<\EOF > doc/data/${CURRENT_MONTH}-o2_prs.json + ${{ steps.get_latest_o2_prs.outputs.data }} + EOF + # FIXME: this should really be one second after the last release + # being published + MERGED_AFTER=`date -v -14d +%Y-%m-%d` + + # Here we convert all the json files to per subsystem + # logs, using the MERGED_AFTER date to further filter them. + # Notice we can have duplicates in each file, + # as they will be removed in the next iteration. + # FIXME: it's probably enough to iterate on the last two + # months, at least for bi-weekly releases. + for f in doc/data/*_prs.json; do + for x in Algorithm Analysis Common DataFormats Detectors EventVisualisation Examples Framework Generators Steer Testing Utilities; do + cat doc/data/o2_prs.json | jq ".repository.pullRequests.edges[].node | select(.files.edges[].node.path | test(\"$x\")) | del(.files) | select(.state == \"MERGED\" and .mergedAt >= \"${MERGED_AFTER}\")" > /tmp/$x_prs.json + if [ ! X`jq -s length /tmp/$x_prs.json` = X0 ]; then + cat $f | jq -r '"- [#\(.number)](https://github.com/AliceO2Group/AliceO2/pull/\(.number)) \(.mergedAt | split("T")[0]): \(.title) by [@\(.author.login)](https://github.com/\(.author.login))"' | sort -u >> /tmp/$x_prs.md + fi + done + done + # Here we do the merging by iterating on the subsystems adding + # an header for each and removing the duplicates. + cat << EOF > CHANGELOG.md + # Changes since ${MERGED_AFTER} + + EOF + + for x in Algorithm Analysis Common DataFormats Detectors EventVisualisation Examples Framework Generators Steer Testing Utilities; do + cat << EOF >> CHANGELOG.md + ## Changes in $x + EOF + cat /tmp/$x_prs.md | sort -k3 | uniq >> CHANGELOG.md + done + - name: Commit and push if changed + run: |- + git add CHANGELOG.md doc/data + git diff + git config --global user.email "github-action-bot@example.com" + git config --global user.name "GitHub Action Bot" + git commit -m "Updated README" -a || echo "No changes to commit" + git push From 3f85d6558181fbd0e25fe42dc7571d514dc10ae6 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 10:51:48 +0100 Subject: [PATCH 1671/1751] Fix changelog generation (#5107) --- .github/workflows/reports.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 17102316e0570..92594ed8f4ac9 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -97,9 +97,9 @@ jobs: # months, at least for bi-weekly releases. for f in doc/data/*_prs.json; do for x in Algorithm Analysis Common DataFormats Detectors EventVisualisation Examples Framework Generators Steer Testing Utilities; do - cat doc/data/o2_prs.json | jq ".repository.pullRequests.edges[].node | select(.files.edges[].node.path | test(\"$x\")) | del(.files) | select(.state == \"MERGED\" and .mergedAt >= \"${MERGED_AFTER}\")" > /tmp/$x_prs.json + cat $f | jq ".repository.pullRequests.edges[].node | select(.files.edges[].node.path | test(\"$x\")) | del(.files) | select(.state == \"MERGED\" and .mergedAt >= \"${MERGED_AFTER}\")" > /tmp/$x_prs.json if [ ! X`jq -s length /tmp/$x_prs.json` = X0 ]; then - cat $f | jq -r '"- [#\(.number)](https://github.com/AliceO2Group/AliceO2/pull/\(.number)) \(.mergedAt | split("T")[0]): \(.title) by [@\(.author.login)](https://github.com/\(.author.login))"' | sort -u >> /tmp/$x_prs.md + cat /tmp/$x_prs.json | jq -r '"- [#\(.number)](https://github.com/AliceO2Group/AliceO2/pull/\(.number)) \(.mergedAt | split("T")[0]): \(.title) by [@\(.author.login)](https://github.com/\(.author.login))"' | sort -u >> /tmp/$x_prs.md fi done done From e1ff68c8e9d63abf04a5ec2fa924fa28dfde44ad Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:09:45 +0100 Subject: [PATCH 1672/1751] Update reports.yml --- .github/workflows/reports.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 92594ed8f4ac9..590fef3da85b3 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -73,6 +73,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update Changelog run: | + set -x mkdir -p doc/data # We create new files once per month, mostly so that # we can keep the query results small. It does not From 84a0e52df6d8b2caa3e3a13007a89f356be09c44 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:17:43 +0100 Subject: [PATCH 1673/1751] Fix CHANGELOG generation (#5108) --- .github/workflows/reports.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 590fef3da85b3..47388195511e6 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -98,9 +98,9 @@ jobs: # months, at least for bi-weekly releases. for f in doc/data/*_prs.json; do for x in Algorithm Analysis Common DataFormats Detectors EventVisualisation Examples Framework Generators Steer Testing Utilities; do - cat $f | jq ".repository.pullRequests.edges[].node | select(.files.edges[].node.path | test(\"$x\")) | del(.files) | select(.state == \"MERGED\" and .mergedAt >= \"${MERGED_AFTER}\")" > /tmp/$x_prs.json - if [ ! X`jq -s length /tmp/$x_prs.json` = X0 ]; then - cat /tmp/$x_prs.json | jq -r '"- [#\(.number)](https://github.com/AliceO2Group/AliceO2/pull/\(.number)) \(.mergedAt | split("T")[0]): \(.title) by [@\(.author.login)](https://github.com/\(.author.login))"' | sort -u >> /tmp/$x_prs.md + cat $f | jq ".repository.pullRequests.edges[].node | select(.files.edges[].node.path | test(\"$x\")) | del(.files) | select(.state == \"MERGED\" and .mergedAt >= \"${MERGED_AFTER}\")" > /tmp/${x}_prs.json + if [ ! X`jq -s length /tmp/${x}_prs.json` = X0 ]; then + cat /tmp/${x}_prs.json | jq -r '"- [#\(.number)](https://github.com/AliceO2Group/AliceO2/pull/\(.number)) \(.mergedAt | split("T")[0]): \(.title) by [@\(.author.login)](https://github.com/\(.author.login))"' | sort -u >> /tmp/${x}_prs.md fi done done @@ -115,7 +115,7 @@ jobs: cat << EOF >> CHANGELOG.md ## Changes in $x EOF - cat /tmp/$x_prs.md | sort -k3 | uniq >> CHANGELOG.md + cat /tmp/${x}_prs.md | sort -k3 | uniq >> CHANGELOG.md done - name: Commit and push if changed run: |- From 47d1a6ae00c9925b9045b8202871de2bc0448ea7 Mon Sep 17 00:00:00 2001 From: DelloStritto <47105254+DelloStritto@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:29:30 +0100 Subject: [PATCH 1674/1751] Update of the Lc->pKpi selector and task (#5013) --- .../HFCandidateSelectionTables.h | 5 +- .../AnalysisDataModel/HFSecondaryVertex.h | 10 +- .../Tasks/PWGHF/HFCandidateCreator2Prong.cxx | 3 +- .../Tasks/PWGHF/HFCandidateCreator3Prong.cxx | 3 +- .../Tasks/PWGHF/HFD0CandidateSelector.cxx | 2 +- .../Tasks/PWGHF/HFLcCandidateSelector.cxx | 110 +++++++----- Analysis/Tasks/PWGHF/taskLc.cxx | 167 +++++++++++++----- 7 files changed, 202 insertions(+), 98 deletions(-) diff --git a/Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h b/Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h index c8d231a401fae..429acaf5e1879 100644 --- a/Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h +++ b/Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h @@ -25,9 +25,10 @@ namespace o2::aod { namespace hf_selcandidate_lc { -DECLARE_SOA_COLUMN(IsSelLc, isSelLc, int); +DECLARE_SOA_COLUMN(IsSelLcpKpi, isSelLcpKpi, int); +DECLARE_SOA_COLUMN(IsSelLcpiKp, isSelLcpiKp, int); } // namespace hf_selcandidate_lc -DECLARE_SOA_TABLE(HFSelLcCandidate, "AOD", "HFSELLCCAND", hf_selcandidate_lc::IsSelLc); +DECLARE_SOA_TABLE(HFSelLcCandidate, "AOD", "HFSELLCCAND", hf_selcandidate_lc::IsSelLcpKpi, hf_selcandidate_lc::IsSelLcpiKp); } // namespace o2::aod #endif // O2_ANALYSIS_HFCANDIDATESELECTIONTABLES_H_ diff --git a/Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h b/Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h index 9c452f4c25c28..a45c184044966 100644 --- a/Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h +++ b/Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h @@ -234,6 +234,7 @@ DECLARE_SOA_TABLE(HfCandProng2Base, "AOD", "HFCANDP2BASE", hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_track_index::Index0Id, hf_track_index::Index1Id, + hf_track_index::HFflag, /* dynamic columns */ hf_cand_prong2::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, hf_cand_prong2::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1>, @@ -340,10 +341,16 @@ auto ELc(const T& candidate) } template <typename T> -auto InvMassLc(const T& candidate) +auto InvMassLcpKpi(const T& candidate) { return candidate.m(array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); } + +template <typename T> +auto InvMassLcpiKp(const T& candidate) +{ + return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kProton)}); +} } // namespace hf_cand_prong3 // 3-prong decay candidate table @@ -357,6 +364,7 @@ DECLARE_SOA_TABLE(HfCandProng3Base, "AOD", "HFCANDP3BASE", hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, hf_track_index::Index0Id, hf_track_index::Index1Id, hf_track_index::Index2Id, + hf_track_index::HFflag, /* dynamic columns */ hf_cand_prong3::M<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, hf_cand_prong3::M2<hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2>, diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index ee3a8a9c7d1ba..6f6863ac2e77e 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -115,7 +115,8 @@ struct HFCandidateCreator2Prong { pvec1[0], pvec1[1], pvec1[2], impactParameter0.getY(), impactParameter1.getY(), std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), - rowTrackIndexProng2.index0Id(), rowTrackIndexProng2.index1Id()); + rowTrackIndexProng2.index0Id(), rowTrackIndexProng2.index1Id(), + rowTrackIndexProng2.hfflag()); // fill histograms if (b_dovalplots) { diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx index a64ff6adfcc89..3053da869fb9f 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx @@ -121,7 +121,8 @@ struct HFCandidateCreator3Prong { pvec2[0], pvec2[1], pvec2[2], impactParameter0.getY(), impactParameter1.getY(), impactParameter2.getY(), std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), std::sqrt(impactParameter2.getSigmaY2()), - rowTrackIndexProng3.index0Id(), rowTrackIndexProng3.index1Id(), rowTrackIndexProng3.index2Id()); + rowTrackIndexProng3.index0Id(), rowTrackIndexProng3.index1Id(), rowTrackIndexProng3.index2Id(), + rowTrackIndexProng3.hfflag()); // fill histograms if (b_dovalplots) { diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx index 77c61d0f68d09..59d11b4291eac 100644 --- a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -177,7 +177,7 @@ struct HFD0CandidateSelector { } } - if (TMath::Abs(trackPion.pt()) < TMath::Abs(cuts[pTBin][4]) || TMath::Abs(trackKaon.pt()) < TMath::Abs(cuts[pTBin][3])) { + if (trackPion.pt() < cuts[pTBin][4] || trackKaon.pt() < cuts[pTBin][3]) { return false; //cut on daughter pT } if (TMath::Abs(trackPion.dcaPrim0()) > cuts[pTBin][6] || TMath::Abs(trackKaon.dcaPrim0()) > cuts[pTBin][5]) { diff --git a/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx index f2d2b22ad880d..d4fe99f1cb21f 100644 --- a/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx +++ b/Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx @@ -11,7 +11,7 @@ /// \file HFD0CandidateSelector.cxx /// \brief Lc->pKpi selection task. /// -/// \author Luigi Dello Stritto <luigi.dellostritto@cern.ch>, CERN +/// \author Luigi Dello Stritto <luigi.dello.stritto@cern.ch>, University and INFN SALERNO /// \author Nima Zardoshti <nima.zardoshti@cern.ch>, CERN #include "Framework/runDataProcessing.h" @@ -27,19 +27,18 @@ static const int npTBins = 10; static const int nCutVars = 8; //temporary until 2D array in configurable is solved - then move to json //m ptp ptk ptpi DCA sigmavtx dlenght cosp -constexpr double cuts[npTBins][nCutVars] = {{0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* pt<1 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 1<pt<2 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 2<pt<3 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 3<pt<4 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 4<pt<5 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 5<pt<6 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 6<pt<8 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 8<pt<12 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}, /* 12<pt<24 */ - {0.5, 0.2, 0.2, 0.2, 0.05, 0.09, 0.005, 0.}}; /* 24<pt<36 */ +constexpr double cuts[npTBins][nCutVars] = {{0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* pt<1 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 1<pt<2 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 2<pt<3 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 3<pt<4 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 4<pt<5 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 5<pt<6 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 6<pt<8 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 8<pt<12 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}, /* 12<pt<24 */ + {0.400, 0.4, 0.4, 0.4, 0.05, 0.09, 0.005, 0.}}; /* 24<pt<36 */ /// Struct for applying Lc selection cuts - struct HFLcCandidateSelector { Produces<aod::HFSelLcCandidate> hfSelLcCandidate; @@ -107,15 +106,16 @@ struct HFLcCandidateSelector { if (candpT < d_pTCandMin || candpT >= d_pTCandMax) { return false; //check that the candidate pT is within the analysis range } + if (hfCandProng3.cpa() <= cuts[pTBin][7]) { return false; //cosine of pointing angle } - // if (hfCandProng3.dca() > cuts[pTBin][4]) return false; //candidate DCA - if (hfCandProng3.chi2PCA() > cuts[pTBin][5]) { //candidate DCA + + /* if (hfCandProng3.chi2PCA() > cuts[pTBin][5]) { //candidate DCA return false; - } + }*/ - if (hfCandProng3.decayLength() * hfCandProng3.decayLength() < cuts[pTBin][6] * cuts[pTBin][6]) { + if (hfCandProng3.decayLength() <= cuts[pTBin][6]) { return false; } return true; @@ -126,7 +126,6 @@ struct HFLcCandidateSelector { /// \param trackProton is the track with the proton hypothesis /// \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 <typename T1, typename T2> bool selectionTopolConjugate(const T1& hfCandProng3, const T2& trackProton, const T2& trackKaon, const T2& trackPion) @@ -138,18 +137,19 @@ struct HFLcCandidateSelector { return false; } - //invariant mass cut - if (TMath::Abs(InvMassLc(hfCandProng3) - RecoDecay::getMassPDG(4122)) > cuts[pTBin][0]) { - return false; - } - - if (TMath::Abs(trackProton.pt()) < TMath::Abs(cuts[pTBin][1]) || TMath::Abs(trackKaon.pt()) < TMath::Abs(cuts[pTBin][2]) || TMath::Abs(trackPion.pt()) < TMath::Abs(cuts[pTBin][3])) { + if (trackProton.pt() < cuts[pTBin][1] || trackKaon.pt() < cuts[pTBin][2] || trackPion.pt() < cuts[pTBin][3]) { return false; //cut on daughter pT } - /* if (TMath::Sqrt( trackProton.dcaPrim0()*trackProton.dcaPrim0() + trackKaon.dcaPrim0()*trackKaon.dcaPrim0() + trackPion.dcaPrim0()*trackPion.dcaPrim0() ) > cuts[pTBin][5]) { - return false; //cut on daughter dca - need to add secondary vertex constraint here - }*/ + if (trackProton.globalIndex() == hfCandProng3.index0Id()) { + if (TMath::Abs(InvMassLcpKpi(hfCandProng3) - RecoDecay::getMassPDG(4122)) > cuts[pTBin][0]) { + return false; + } + } else { + if (TMath::Abs(InvMassLcpiKp(hfCandProng3) - RecoDecay::getMassPDG(4122)) > cuts[pTBin][0]) { + return false; + } + } return true; } @@ -190,9 +190,9 @@ struct HFLcCandidateSelector { template <typename T> bool selectionPIDTPC(const T& track, int nPDG, int nSigmaCut) { - double nSigma = 100.0; //arbitarily large value + double nSigma = 1.0; //arbitarily large value nPDG = TMath::Abs(nPDG); - if (nPDG == 2212) { + /* if (nPDG == 2212) { nSigma = track.tpcNSigmaPr(); } else if (nPDG == 321) { nSigma = track.tpcNSigmaKa(); @@ -200,7 +200,7 @@ struct HFLcCandidateSelector { nSigma = track.tpcNSigmaPi(); } else { return false; - } + }*/ return nSigma < nSigmaCut; } @@ -213,9 +213,9 @@ struct HFLcCandidateSelector { template <typename T> bool selectionPIDTOF(const T& track, int nPDG, int nSigmaCut) { - double nSigma = 100.0; //arbitarily large value + double nSigma = 1.; //arbitarily large value nPDG = TMath::Abs(nPDG); - if (nPDG == 2212) { + /* if (nPDG == 2212) { nSigma = track.tofNSigmaPr(); } else if (nPDG == 321) { nSigma = track.tofNSigmaKa(); @@ -223,7 +223,7 @@ struct HFLcCandidateSelector { nSigma = track.tofNSigmaPi(); } else { return false; - } + }*/ return nSigma < nSigmaCut; } @@ -279,18 +279,27 @@ struct HFLcCandidateSelector { void process(aod::HfCandProng3 const& hfCandProng3s, aod::BigTracksPID const& tracks) { - int statusLc; // final selection flag : 0-rejected 1-accepted - bool topolLc; + int statusLcpKpi, statusLcpiKp; // final selection flag : 0-rejected 1-accepted + bool topolLcpKpi, topolLcpiKp; int pidLc, proton, kaonMinus, pionPlus; for (auto& hfCandProng3 : hfCandProng3s) { //looping over 3 prong candidates - auto trackPos1 = hfCandProng3.index0_as<aod::BigTracksPID>(); //positive daughter - auto trackNeg1 = hfCandProng3.index1_as<aod::BigTracksPID>(); //negative daughter - auto trackPos2 = hfCandProng3.index2_as<aod::BigTracksPID>(); //positive daughter + statusLcpKpi = 0; + statusLcpiKp = 0; + int LcFlag = hfCandProng3.hfflag(); - statusLc = 0; - topolLc = true; + if (!(LcFlag & 1 << 1)) { + hfSelLcCandidate(statusLcpKpi, statusLcpiKp); + continue; + } + + auto trackPos1 = hfCandProng3.index0_as<aod::BigTracksPID>(); //positive daughter (negative for the antiparticles) + auto trackNeg1 = hfCandProng3.index1_as<aod::BigTracksPID>(); //negative daughter (positive for the antiparticles) + auto trackPos2 = hfCandProng3.index2_as<aod::BigTracksPID>(); //positive daughter (negative for the antiparticles) + + topolLcpKpi = true; + topolLcpiKp = true; pidLc = -1; proton = -1; kaonMinus = -1; @@ -298,7 +307,7 @@ struct HFLcCandidateSelector { // daughter track validity selection if (!daughterSelection(trackPos1) || !daughterSelection(trackNeg1) || !daughterSelection(trackPos2)) { - hfSelLcCandidate(statusLc); + hfSelLcCandidate(statusLcpKpi, statusLcpiKp); continue; } @@ -306,15 +315,17 @@ struct HFLcCandidateSelector { //conjugate independent topological selection if (!selectionTopol(hfCandProng3)) { - hfSelLcCandidate(statusLc); + hfSelLcCandidate(statusLcpKpi, statusLcpiKp); continue; } //conjugate dependent toplogical selection for Lc - topolLc = selectionTopolConjugate(hfCandProng3, trackPos1, trackNeg1, trackPos2); - if (!topolLc) { - hfSelLcCandidate(statusLc); + topolLcpKpi = selectionTopolConjugate(hfCandProng3, trackPos1, trackNeg1, trackPos2); + topolLcpiKp = selectionTopolConjugate(hfCandProng3, trackPos2, trackNeg1, trackPos1); + + if (!topolLcpKpi && !topolLcpiKp) { + hfSelLcCandidate(statusLcpKpi, statusLcpiKp); continue; } @@ -330,15 +341,18 @@ struct HFLcCandidateSelector { } if (pidLc == 0) { - hfSelLcCandidate(statusLc); + hfSelLcCandidate(statusLcpKpi, statusLcpiKp); continue; } - if ((pidLc == -1 || pidLc == 1) && topolLc) { - statusLc = 1; //identified as Lc + if ((pidLc == -1 || pidLc == 1) && topolLcpKpi) { + statusLcpKpi = 1; //identified as Lc + } + if ((pidLc == -1 || pidLc == 1) && topolLcpiKp) { + statusLcpiKp = 1; //identified as Lc } - hfSelLcCandidate(statusLc); + hfSelLcCandidate(statusLcpKpi, statusLcpiKp); } } }; diff --git a/Analysis/Tasks/PWGHF/taskLc.cxx b/Analysis/Tasks/PWGHF/taskLc.cxx index 2fa3bd1d348e6..ebf91b37889d0 100644 --- a/Analysis/Tasks/PWGHF/taskLc.cxx +++ b/Analysis/Tasks/PWGHF/taskLc.cxx @@ -8,14 +8,15 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file taskDPlus.cxx -/// \brief D± analysis task +/// \file taskLc.cxx +/// \brief Lc± analysis task /// \note Extended from taskD0 /// +/// \author Luigi Dello Stritto <luigi.dello.stritto@cern.ch>, University and INFN SALERNO /// \author Vít Kučera <vit.kucera@cern.ch>, CERN -#include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "AnalysisDataModel/HFSecondaryVertex.h" #include "AnalysisDataModel/HFCandidateSelectionTables.h" @@ -24,61 +25,139 @@ using namespace o2::framework; using namespace o2::aod::hf_cand_prong3; using namespace o2::framework::expressions; -/// Lc+ analysis task +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + ConfigParamSpec optionDoMC{"doMC", VariantType::Bool, false, {"Fill MC histograms."}}; + workflowOptions.push_back(optionDoMC); +} + +#include "Framework/runDataProcessing.h" + +/// Lc± analysis task struct TaskLc { - OutputObj<TH1F> hmass{TH1F("hmass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 3.1)}; - OutputObj<TH1F> hptcand{TH1F("hptcand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong0{TH1F("hptprong0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong1{TH1F("hptprong1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hptprong2{TH1F("hptprong2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; - OutputObj<TH1F> hdeclength{TH1F("declength", "3-prong candidates;decay length (cm);entries", 200, 0., 2.)}; - OutputObj<TH1F> hd0Prong0{TH1F("hd0Prong0", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hd0Prong1{TH1F("hd0Prong1", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hd0Prong2{TH1F("hd0Prong2", "3-prong candidates;prong 2 DCAxy to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hCt{TH1F("hCt", "3-prong candidates;proper lifetime (D^{#pm}) * #it{c} (cm);entries", 120, -20., 100.)}; - OutputObj<TH1F> hCPA{TH1F("hCPA", "3-prong candidates;cosine of pointing angle;entries", 110, -1.1, 1.1)}; - OutputObj<TH1F> hEta{TH1F("hEta", "3-prong candidates;candidate #it{#eta};entries", 100, -2., 2.)}; - //OutputObj<TH1F> hselectionstatus{TH1F("selectionstatus", "3-prong candidates;selection status;entries", 5, -0.5, 4.5)}; - OutputObj<TH1F> hImpParErr{TH1F("hImpParErr", "3-prong candidates;impact parameter error (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hDecLenErr{TH1F("hDecLenErr", "3-prong candidates;decay length error (cm);entries", 100, 0., 1.)}; - //OutputObj<TH1F> hdca{TH1F("hdca", "3-prong candidates;prongs DCA to prim. vertex (cm);entries", 100, -1., 1.)}; - OutputObj<TH1F> hdca2{TH1F("hdca2", "3-prong candidates;prongs DCA to sec. vertex (cm);entries", 100, 0., 1.)}; + HistogramRegistry registry{ + "registry", + {{"hmass", "3-prong candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}, + {"hptcand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hptprong0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hptprong1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hptprong2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hdeclength", "3-prong candidates;decay length (cm);entries", {HistType::kTH1F, {{400, -2., 2.}}}}, + {"hd0Prong0", "3-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hd0Prong1", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hd0Prong2", "3-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hCt", "3-prong candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH1F, {{120, -20., 100.}}}}, + {"hCPA", "3-prong candidates;cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hEta", "3-prong candidates;candidate #it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, + {"hselectionstatus", "3-prong candidates;selection status;entries", {HistType::kTH1F, {{5, -0.5, 4.5}}}}, + {"hImpParErr", "3-prong candidates;impact parameter error (cm);entries", {HistType::kTH1F, {{100, -1., 1.}}}}, + {"hDecLenErr", "3-prong candidates;decay length error (cm);entries", {HistType::kTH1F, {{100, 0., 1.}}}}, + {"hdca2", "3-prong candidates;prong DCA to sec. vertex (cm);entries", {HistType::kTH1F, {{100, 0., 1.}}}}}}; Configurable<int> d_selectionFlagLc{"d_selectionFlagLc", 1, "Selection Flag for Lc"}; + Configurable<double> cutEtaCandMax{"cutEtaCandMax", -1., "max. cand. pseudorapidity"}; - Filter filterSelectCandidates = (aod::hf_selcandidate_lc::isSelLc >= d_selectionFlagLc); + Filter filterSelectCandidates = (aod::hf_selcandidate_lc::isSelLcpKpi >= d_selectionFlagLc || aod::hf_selcandidate_lc::isSelLcpiKp >= d_selectionFlagLc); //void process(aod::HfCandProng3 const& candidates) void process(soa::Filtered<soa::Join<aod::HfCandProng3, aod::HFSelLcCandidate>> const& candidates) { for (auto& candidate : candidates) { - if (candidate.isSelLc() >= d_selectionFlagLc) { - hmass->Fill(InvMassLc(candidate)); + /* if (candidate.pt()>5){ + continue;}*/ + if (cutEtaCandMax >= 0. && std::abs(candidate.eta()) > cutEtaCandMax) { + //Printf("Candidate: eta rejection: %g", candidate.eta()); + continue; + } + if (candidate.isSelLcpKpi() >= d_selectionFlagLc) { + registry.get<TH1>("hmass")->Fill(InvMassLcpKpi(candidate)); + } + if (candidate.isSelLcpiKp() >= d_selectionFlagLc) { + registry.get<TH1>("hmass")->Fill(InvMassLcpiKp(candidate)); + } + registry.get<TH1>("hptcand")->Fill(candidate.pt()); + registry.get<TH1>("hptprong0")->Fill(candidate.ptProng0()); + registry.get<TH1>("hptprong1")->Fill(candidate.ptProng1()); + registry.get<TH1>("hptprong2")->Fill(candidate.ptProng2()); + registry.get<TH1>("hdeclength")->Fill(candidate.decayLength()); + registry.get<TH1>("hd0Prong0")->Fill(candidate.impactParameter0()); + registry.get<TH1>("hd0Prong1")->Fill(candidate.impactParameter1()); + registry.get<TH1>("hd0Prong2")->Fill(candidate.impactParameter2()); + registry.get<TH1>("hCt")->Fill(CtLc(candidate)); + registry.get<TH1>("hCPA")->Fill(candidate.cpa()); + registry.get<TH1>("hEta")->Fill(candidate.eta()); + registry.get<TH1>("hselectionstatus")->Fill(candidate.isSelLcpKpi()); + registry.get<TH1>("hselectionstatus")->Fill(candidate.isSelLcpiKp()); + registry.get<TH1>("hImpParErr")->Fill(candidate.errorImpactParameter0()); + registry.get<TH1>("hImpParErr")->Fill(candidate.errorImpactParameter1()); + registry.get<TH1>("hImpParErr")->Fill(candidate.errorImpactParameter2()); + registry.get<TH1>("hDecLenErr")->Fill(candidate.errorDecayLength()); + registry.get<TH1>("hDecLenErr")->Fill(candidate.chi2PCA()); + } + } +}; + +/// Fills MC histograms. +struct TaskLcMC { + HistogramRegistry registry{ + "registry", + {{"hPtRecSig", "3-prong candidates (rec. matched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtRecBg", "3-prong candidates (rec. unmatched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hPtGen", "3-prong candidates (gen. matched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, + {"hCPARecSig", "3-prong candidates (rec. matched);cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hCPARecBg", "3-prong candidates (rec. unmatched);cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}}, + {"hEtaRecSig", "3-prong candidates (rec. matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, + {"hEtaRecBg", "3-prong candidates (rec. unmatched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, + {"hEtaGen", "3-prong candidates (gen. matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}}}; + + Configurable<int> d_selectionFlagLc{"d_selectionFlagLc", 1, "Selection Flag for Lc"}; + Configurable<int> d_selectionFlagLcbar{"d_selectionFlagLcbar", 1, "Selection Flag for Lcbar"}; + Configurable<double> cutEtaCandMax{"cutEtaCandMax", -1., "max. cand. pseudorapidity"}; + + Filter filterSelectCandidates = (aod::hf_selcandidate_lc::isSelLcpKpi >= d_selectionFlagLc || aod::hf_selcandidate_lc::isSelLcpiKp >= d_selectionFlagLc); + + void process(soa::Filtered<soa::Join<aod::HfCandProng3, aod::HFSelLcCandidate, aod::HfCandProng3MCRec>> const& candidates, + soa::Join<aod::McParticles, aod::HfCandProng3MCGen> const& particlesMC) + { + // MC rec. + //Printf("MC Candidates: %d", candidates.size()); + for (auto& candidate : candidates) { + if (cutEtaCandMax >= 0. && std::abs(candidate.eta()) > cutEtaCandMax) { + //Printf("MC Rec.: eta rejection: %g", candidate.eta()); + continue; + } + if (std::abs(candidate.flagMCMatchRec()) == LcToPKPi) { + registry.get<TH1>("hPtRecSig")->Fill(candidate.pt()); + registry.get<TH1>("hCPARecSig")->Fill(candidate.cpa()); + registry.get<TH1>("hEtaRecSig")->Fill(candidate.eta()); + } else { + registry.get<TH1>("hPtRecBg")->Fill(candidate.pt()); + registry.get<TH1>("hCPARecBg")->Fill(candidate.cpa()); + registry.get<TH1>("hEtaRecBg")->Fill(candidate.eta()); + } + } + // MC gen. + //Printf("MC Particles: %d", particlesMC.size()); + for (auto& particle : particlesMC) { + if (cutEtaCandMax >= 0. && std::abs(particle.eta()) > cutEtaCandMax) { + //Printf("MC Gen.: eta rejection: %g", particle.eta()); + continue; + } + if (std::abs(particle.flagMCMatchGen()) == LcToPKPi) { + registry.get<TH1>("hPtGen")->Fill(particle.pt()); + registry.get<TH1>("hEtaGen")->Fill(particle.eta()); } - hptcand->Fill(candidate.pt()); - hptprong0->Fill(candidate.ptProng0()); - hptprong1->Fill(candidate.ptProng1()); - hptprong2->Fill(candidate.ptProng2()); - hdeclength->Fill(candidate.decayLength()); - hd0Prong0->Fill(candidate.impactParameter0()); - hd0Prong1->Fill(candidate.impactParameter1()); - hd0Prong2->Fill(candidate.impactParameter2()); - hCt->Fill(CtLc(candidate)); - hCPA->Fill(candidate.cpa()); - hEta->Fill(candidate.eta()); - //hselectionstatus->Fill(candidate.isSelLc()); - hImpParErr->Fill(candidate.errorImpactParameter0()); - hImpParErr->Fill(candidate.errorImpactParameter1()); - hImpParErr->Fill(candidate.errorImpactParameter2()); - hDecLenErr->Fill(candidate.errorDecayLength()); - // hdca->Fill(candidate.dca()); - hdca2->Fill(candidate.chi2PCA()); } } }; -WorkflowSpec defineDataProcessing(ConfigContext const&) +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ + WorkflowSpec workflow{ adaptAnalysisTask<TaskLc>("hf-task-lc")}; + const bool doMC = cfgc.options().get<bool>("doMC"); + if (doMC) { + workflow.push_back(adaptAnalysisTask<TaskLcMC>("hf-task-lc-mc")); + } + return workflow; } From 7b38fb1c3396955f9f48e63d7395ffd30ab48897 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:34:20 +0100 Subject: [PATCH 1675/1751] Fix CHANGELOG generation (#5109) --- .github/workflows/reports.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 47388195511e6..9769fae03a1ca 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -86,12 +86,12 @@ jobs: cat <<\EOF > doc/data/${CURRENT_MONTH}-o2_prs.json ${{ steps.get_latest_o2_prs.outputs.data }} EOF - # FIXME: this should really be one second after the last release + # FIXME: this should really be one second after the last release # being published MERGED_AFTER=`date -v -14d +%Y-%m-%d` - # Here we convert all the json files to per subsystem - # logs, using the MERGED_AFTER date to further filter them. + # Here we convert all the json files to per subsystem + # logs, using the MERGED_AFTER date to further filter them. # Notice we can have duplicates in each file, # as they will be removed in the next iteration. # FIXME: it's probably enough to iterate on the last two @@ -104,17 +104,12 @@ jobs: fi done done - # Here we do the merging by iterating on the subsystems adding + # Here we do the merging by iterating on the subsystems adding # an header for each and removing the duplicates. - cat << EOF > CHANGELOG.md - # Changes since ${MERGED_AFTER} - - EOF - + printf "# Changes since ${MERGED_AFTER}\n\n" > CHANGELOG.md for x in Algorithm Analysis Common DataFormats Detectors EventVisualisation Examples Framework Generators Steer Testing Utilities; do - cat << EOF >> CHANGELOG.md - ## Changes in $x - EOF + [ ! -f /tmp/${x}_prs.md ] && continue + printf "## Changes in $x\n\n" >> CHANGELOG.md cat /tmp/${x}_prs.md | sort -k3 | uniq >> CHANGELOG.md done - name: Commit and push if changed From 4108378df8e294abbdc4474b2df403b3cad2cb68 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:41:08 +0100 Subject: [PATCH 1676/1751] Update reports.yml --- .github/workflows/reports.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 9769fae03a1ca..ebf534d7040f5 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -119,4 +119,4 @@ jobs: git config --global user.email "github-action-bot@example.com" git config --global user.name "GitHub Action Bot" git commit -m "Updated README" -a || echo "No changes to commit" - git push + git push origin HEAD:changelog From b63c535e9297a236ea26744665ab69027f7ac75d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:42:05 +0100 Subject: [PATCH 1677/1751] Update reports.yml --- .github/workflows/reports.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index ebf534d7040f5..f4882f7ffd0a2 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -119,4 +119,4 @@ jobs: git config --global user.email "github-action-bot@example.com" git config --global user.name "GitHub Action Bot" git commit -m "Updated README" -a || echo "No changes to commit" - git push origin HEAD:changelog + git push origin HEAD:changelog -f From e26cb7c6c78e536e7d1c70c8bf696860a0205ef3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:46:10 +0100 Subject: [PATCH 1678/1751] Updated CHANGELOG (#5110) Co-authored-by: GitHub Action Bot <github-action-bot@example.com> --- CHANGELOG.md | 33 + doc/data/2021-01-o2_prs.json | 4548 +++++++++++++++++++++++++++++ doc/data/2021-01-o2_releases.json | 32 + 3 files changed, 4613 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 doc/data/2021-01-o2_prs.json create mode 100644 doc/data/2021-01-o2_releases.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000..bbd7a1ec66215 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changes since 2020-12-21 + +## Changes in Analysis + +- [#5013](https://github.com/AliceO2Group/AliceO2/pull/5013) 2021-01-04: PWGHF: Update of the Lc->pKpi selector and task by [@DelloStritto](https://github.com/DelloStritto) +## Changes in Common + +- [#5100](https://github.com/AliceO2Group/AliceO2/pull/5100) 2020-12-28: GPU: Make more headers compatible to GPU by [@davidrohr](https://github.com/davidrohr) +## Changes in DataFormats + +- [#5089](https://github.com/AliceO2Group/AliceO2/pull/5089) 2020-12-22: real LUT in CCDB by [@AllaMaevskaya](https://github.com/AllaMaevskaya) +- [#5092](https://github.com/AliceO2Group/AliceO2/pull/5092) 2020-12-23: ZDC Workflow to inspect raw data by [@cortesep](https://github.com/cortesep) +- [#5094](https://github.com/AliceO2Group/AliceO2/pull/5094) 2020-12-24: GPU: Some work towards making the o2 propagator work on GPU by [@davidrohr](https://github.com/davidrohr) +- [#5096](https://github.com/AliceO2Group/AliceO2/pull/5096) 2020-12-25: Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU by [@davidrohr](https://github.com/davidrohr) +- [#5100](https://github.com/AliceO2Group/AliceO2/pull/5100) 2020-12-28: GPU: Make more headers compatible to GPU by [@davidrohr](https://github.com/davidrohr) +- [#5104](https://github.com/AliceO2Group/AliceO2/pull/5104) 2021-01-04: Use DBSCAN for Time-Z clustering in PVertexing, debris reduction by [@shahor02](https://github.com/shahor02) +## Changes in Detectors + +- [#5091](https://github.com/AliceO2Group/AliceO2/pull/5091) 2020-12-22: MFT: eliminate sqrt where possible by [@bovulpes](https://github.com/bovulpes) +- [#5089](https://github.com/AliceO2Group/AliceO2/pull/5089) 2020-12-22: real LUT in CCDB by [@AllaMaevskaya](https://github.com/AllaMaevskaya) +- [#5083](https://github.com/AliceO2Group/AliceO2/pull/5083) 2020-12-23: Executable for chunk large raw-data files by [@shahor02](https://github.com/shahor02) +- [#5092](https://github.com/AliceO2Group/AliceO2/pull/5092) 2020-12-23: ZDC Workflow to inspect raw data by [@cortesep](https://github.com/cortesep) +- [#5094](https://github.com/AliceO2Group/AliceO2/pull/5094) 2020-12-24: GPU: Some work towards making the o2 propagator work on GPU by [@davidrohr](https://github.com/davidrohr) +- [#5096](https://github.com/AliceO2Group/AliceO2/pull/5096) 2020-12-25: Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU by [@davidrohr](https://github.com/davidrohr) +- [#5097](https://github.com/AliceO2Group/AliceO2/pull/5097) 2020-12-25: TPC Tracking: Workaround for 0-cluster tracks by [@davidrohr](https://github.com/davidrohr) +- [#5100](https://github.com/AliceO2Group/AliceO2/pull/5100) 2020-12-28: GPU: Make more headers compatible to GPU by [@davidrohr](https://github.com/davidrohr) +- [#5069](https://github.com/AliceO2Group/AliceO2/pull/5069) 2020-12-28: [WIP][ITS-tracking] Add track dumping in standalone debugger by [@mconcas](https://github.com/mconcas) +- [#5102](https://github.com/AliceO2Group/AliceO2/pull/5102) 2020-12-29: Drop bad assert by [@ktf](https://github.com/ktf) +- [#5101](https://github.com/AliceO2Group/AliceO2/pull/5101) 2020-12-29: [EMCAL-675] Handling of pages without trailer by [@mfasDa](https://github.com/mfasDa) +- [#5104](https://github.com/AliceO2Group/AliceO2/pull/5104) 2021-01-04: Use DBSCAN for Time-Z clustering in PVertexing, debris reduction by [@shahor02](https://github.com/shahor02) +## Changes in Framework + +- [#5098](https://github.com/AliceO2Group/AliceO2/pull/5098) 2020-12-27: DPL: use RawDeviceService to sleep in example by [@ktf](https://github.com/ktf) diff --git a/doc/data/2021-01-o2_prs.json b/doc/data/2021-01-o2_prs.json new file mode 100644 index 0000000000000..0d7c8e832e295 --- /dev/null +++ b/doc/data/2021-01-o2_prs.json @@ -0,0 +1,4548 @@ +{ + "repository": { + "pullRequests": { + "edges": [ + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-04T20:48:12Z", + "title": "Fix another EMCAL out of bounds error", + "number": 5010, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-04T21:32:52Z", + "title": "Add storing CTF / Reading input from CTF / Run asynchronous reconstruction to full system test", + "number": 5011, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "prodtests/full-system-test/README.md" + } + }, + { + "node": { + "path": "prodtests/full-system-test/dpl-workflow.sh" + } + }, + { + "node": { + "path": "prodtests/full-system-test/setenv.sh" + } + }, + { + "node": { + "path": "prodtests/full_system_test.sh" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-05T08:49:46Z", + "title": "decrease verbosity of EMCAL RawReaderMemory", + "number": 5012, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T10:29:31Z", + "title": "PWGHF: Update of the Lc->pKpi selector and task", + "number": 5013, + "author": { + "login": "DelloStritto" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + } + }, + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskLc.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-07T12:13:47Z", + "title": "Fix: Proper treatment of --disable-mc in PHOS CellConverterSpec", + "number": 5014, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/CellConverterSpec.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/CellConverterSpec.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-06T18:31:36Z", + "title": "TrackSelection: revert to uint8_t columns", + "number": 5015, + "author": { + "login": "mario-krueger" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGCF/correlations.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGCF/filterCF.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/mcspectraefficiency.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/spectraTOF.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/spectraTPC.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/trackchecks.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/trackqa.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/trackselection.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-06T18:30:57Z", + "title": "Update for Run3 subtask", + "number": 5016, + "author": { + "login": "nburmaso" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/eventSelection.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-08T13:53:29Z", + "title": "Fixes for DCS->DPL proxy", + "number": 5017, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h" + } + }, + { + "node": { + "path": "Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h" + } + }, + { + "node": { + "path": "Detectors/DCS/testWorkflow/DCStoDPLconverter.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-07T07:52:40Z", + "title": "DPL: improve startup performance", + "number": 5018, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/include/Framework/DeviceMetricsInfo.h" + } + }, + { + "node": { + "path": "Framework/Core/src/DeviceMetricsInfo.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/FrameworkGUIDevicesGraph.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-10T08:12:27Z", + "title": "NFC: Fix codechecker for the ITS GPU code", + "number": 5019, + "author": { + "login": "mpuccio" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Array.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/ClusterLinesGPU.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Context.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Stream.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/ClusterLinesGPU.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/Stream.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ArrayHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ClusterLinesHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ContextHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/StreamHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UniquePointerHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UtilsHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VectorHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/src/ClusterLinesHIP.hip.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/src/ContextHIP.hip.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/src/StreamHIP.hip.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/src/UtilsHIP.hip.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T23:02:08Z", + "title": "[ITS-ntracker] Add material budget fix and chi2 selection", + "number": 5020, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-07T10:12:59Z", + "title": "sim_challenge: include new AOD producer workflow", + "number": 5021, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ + { + "node": { + "path": "prodtests/sim_challenge.sh" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "[WIP] trd raw data flp and epn", + "number": 5022, + "author": { + "login": "bazinski" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h" + } + }, + { + "node": { + "path": "DataFormats/Detectors/TRD/src/LinkRecord.cxx" + } + }, + { + "node": { + "path": "DataFormats/Detectors/TRD/src/RawData.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/include/TRDRaw/CompressedRawReader.h" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/include/TRDRaw/ConfigEvenParser.h" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/include/TRDRaw/CruCompressorTask.h" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/include/TRDRaw/CruRawReader.h" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/include/TRDRaw/DigitsParser.h" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/include/TRDRaw/EpnDataReaderTask.h" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/include/TRDRaw/TrackletsParser.h" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/CompressedRawReader.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/CruCompressor.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/CruCompressorTask.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/CruRawReader.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/DigitsParser.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/EpnDataReader.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/EpnDataReaderTask.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/raw/src/TrackletsParser.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/simulation/src/Trap2CRU.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/simulation/src/TrapSimulator.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/simulation/src/trap2raw.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/workflow/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-08T09:36:15Z", + "title": "Deltaphi cuts above pi do not make sense", + "number": 5023, + "author": { + "login": "mpuccio" + }, + "files": { + "edges": [ + { + "node": { + "path": "macro/run_trac_alice3.C" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-09T13:52:19Z", + "title": "GPU: Tune some kernel parameters for AMD Vega", + "number": 5024, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "GPU/Common/GPUDefGPUParameters.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-08T19:05:59Z", + "title": "Getting prepared for boolean columns", + "number": 5025, + "author": { + "login": "victor-gonzalez" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/PWGCF/dptdptcorrelations.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Convert collision time to ps in TOF PID response", + "number": 5026, + "author": { + "login": "njacazio" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/pidTOF.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-08T08:21:19Z", + "title": "DPL: attempt at supporting cloned processors", + "number": 5027, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/include/Framework/runDataProcessing.h" + } + }, + { + "node": { + "path": "Framework/Core/src/WorkflowHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/runDataProcessing.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-09T14:56:44Z", + "title": "DPL: syntactic sugar for --clone <template>:<instance number>", + "number": 5028, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/src/runDataProcessing.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-08T12:58:36Z", + "title": "DPL GUI: add buttons to debug / profile the driver", + "number": 5029, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/src/FrameworkGUIDebugger.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-08T17:47:53Z", + "title": "DPL: better error message when DPL_ENABLE_STACKTRACE not set", + "number": 5030, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/src/runDataProcessing.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-08T15:10:36Z", + "title": "Fix for MCTruth label checks", + "number": 5031, + "author": { + "login": "nburmaso" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Drop initial prototype of dataflow setup", + "number": 5032, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Utilities/CMakeLists.txt" + } + }, + { + "node": { + "path": "Utilities/DataFlow/CMakeLists.txt" + } + }, + { + "node": { + "path": "Utilities/DataFlow/doc/o2-subframebuilder-device.1.in" + } + }, + { + "node": { + "path": "Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in" + } + }, + { + "node": { + "path": "Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/PayloadMerger.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/SubframeUtils.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/TimeframeParser.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/CreateSetup.py" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/confBasicSetup.json" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/confComplexSetup.json" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/confComplexSetup2.json" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/confFakeTimeframe.json" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/startBasicSetup.sh" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/startComplexSetup.sh" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/startComplexSetup2.sh" + } + }, + { + "node": { + "path": "Utilities/DataFlow/run/startTimeframeExample.sh" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/EPNReceiverDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/FLPSenderDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/FakeTimeframeBuilder.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/HeartbeatSampler.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/SubframeBuilderDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/TimeframeParser.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/TimeframeReaderDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/TimeframeValidationTool.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/TimeframeValidatorDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/TimeframeWriterDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runEPNReceiver.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runFLPSender.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runHeartbeatSampler.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runSubframeBuilderDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runTimeframeReaderDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/src/runTimeframeWriterDevice.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/test/test_PayloadMerger01.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/test/test_SubframeUtils01.cxx" + } + }, + { + "node": { + "path": "Utilities/DataFlow/test/test_TimeframeParser.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T16:10:58Z", + "title": "[ITS] Remove unused classes", + "number": 5033, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Graph.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-10T08:19:25Z", + "title": "Moving StepTHn to Framework", + "number": 5034, + "author": { + "login": "jgrosseo" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Core/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/AnalysisTools/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/AnalysisTools/src/AnalysisToolsLinkDef.h" + } + }, + { + "node": { + "path": "Framework/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/StepTHn.h" + } + }, + { + "node": { + "path": "Framework/Core/src/StepTHn.cxx" + } + }, + { + "node": { + "path": "Framework/Core/test/FrameworkCoreTestLinkDef.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T10:16:35Z", + "title": "DPL Analysis: fix for parsing non-integer arrays in configurables", + "number": 5035, + "author": { + "login": "aalkin" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/src/BoostOptionsRetriever.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/DataProcessingDevice.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/PropertyTreeHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/RootConfigParamHelpers.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T17:26:02Z", + "title": "First version of pedestal calibration workflow raw data -> ccdb", + "number": 5036, + "author": { + "login": "wiechula" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/TPC/base/include/TPCBase/CDBInterface.h" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/macro/runPedestal.C" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/macro/runPedestal.sh" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/run/calib-pedestal.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/src/CalibRawBase.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/src/CalibTreeDump.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h" + } + }, + { + "node": { + "path": "Detectors/TPC/reconstruction/src/RawReaderCRU.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/README.md" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/CalibProcessingHelper.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/RawToDigitsSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T09:09:26Z", + "title": "Drop untested / unused hough transform code", + "number": 5037, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Utilities/CMakeLists.txt" + } + }, + { + "node": { + "path": "Utilities/hough/CMakeLists.txt" + } + }, + { + "node": { + "path": "Utilities/hough/README.md" + } + }, + { + "node": { + "path": "Utilities/hough/runHough.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-09T17:05:42Z", + "title": "DPL: allow adding suffix to all dataprocessors in a workflow", + "number": 5038, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/include/Framework/runDataProcessing.h" + } + }, + { + "node": { + "path": "Framework/Core/src/runDataProcessing.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T09:04:29Z", + "title": "Fixed bug for nested AnalysisCompositeCuts; removed duplicated histogram classes from TableReader", + "number": 5039, + "author": { + "login": "iarsene" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h" + } + }, + { + "node": { + "path": "Analysis/Core/src/AnalysisCompositeCut.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGDQ/tableReader.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T08:50:21Z", + "title": "Adding truncation + some minor changes", + "number": 5040, + "author": { + "login": "nburmaso" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h" + } + }, + { + "node": { + "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T10:36:58Z", + "title": "Use value_t instead of double", + "number": 5041, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T09:02:23Z", + "title": "Change to new TPCrefit check: finders", + "number": 5042, + "author": { + "login": "ddobrigk" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/PWGLF/cascadefinder.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/multiplicityQa.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-12T08:55:06Z", + "title": "Make TrackPar(Cov) compatible to GPU", + "number": 5043, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "Common/MathUtils/include/MathUtils/CartesianGPU.h" + } + }, + { + "node": { + "path": "Common/MathUtils/include/MathUtils/Utils.h" + } + }, + { + "node": { + "path": "Common/MathUtils/include/MathUtils/detail/CircleXY.h" + } + }, + { + "node": { + "path": "Common/MathUtils/include/MathUtils/detail/IntervalXY.h" + } + }, + { + "node": { + "path": "Common/MathUtils/include/MathUtils/detail/trigonometric.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/DCA.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/PID.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/PrimaryVertex.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/Vertex.cxx" + } + }, + { + "node": { + "path": "DataFormats/common/include/CommonDataFormat/InteractionRecord.h" + } + }, + { + "node": { + "path": "DataFormats/common/src/InteractionRecord.cxx" + } + }, + { + "node": { + "path": "Detectors/Base/src/Propagator.cxx" + } + }, + { + "node": { + "path": "GPU/Common/CMakeLists.txt" + } + }, + { + "node": { + "path": "GPU/Common/GPUCommonArray.h" + } + }, + { + "node": { + "path": "GPU/Common/GPUCommonDef.h" + } + }, + { + "node": { + "path": "GPU/Common/GPUCommonLogger.h" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/cuda/CMakeLists.txt" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/hip/CMakeLists.txt" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/opencl2/CMakeLists.txt" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Standalone/CMakeLists.txt" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-10T13:55:19Z", + "title": "Decouple VMC libs from o2-sim", + "number": 5044, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/gconfig/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/gconfig/src/G3Config.cxx" + } + }, + { + "node": { + "path": "Detectors/gconfig/src/G4Config.cxx" + } + }, + { + "node": { + "path": "Detectors/gconfig/src/SetCuts.cxx" + } + }, + { + "node": { + "path": "Detectors/gconfig/src/SetCuts.h" + } + }, + { + "node": { + "path": "Detectors/gconfig/src/SimSetup.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T07:33:24Z", + "title": "[ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK", + "number": 5045, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ + { + "node": { + "path": "Common/SimConfig/src/SimConfig.cxx" + } + }, + { + "node": { + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h" + } + }, + { + "node": { + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h" + } + }, + { + "node": { + "path": "DataFormats/Detectors/Common/src/DetID.cxx" + } + }, + { + "node": { + "path": "DataFormats/Headers/include/Headers/DataHeader.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/README.md" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/MisalignmentParameter.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/base/src/MisalignmentParameter.cxx" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/base/src/TRKBaseLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/macros/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/macros/test/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/data/simcuts.dat" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V11Geometry.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V1Layer.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Layer.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Services.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V11Geometry.cxx" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V1Layer.cxx" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Layer.cxx" + } + }, + { + "node": { + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Services.cxx" + } + }, + { + "node": { + "path": "Detectors/Upgrades/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Upgrades/README.md" + } + }, + { + "node": { + "path": "macro/CMakeLists.txt" + } + }, + { + "node": { + "path": "macro/build_geometry.C" + } + }, + { + "node": { + "path": "macro/run_trac_alice3.C" + } + }, + { + "node": { + "path": "run/CMakeLists.txt" + } + }, + { + "node": { + "path": "run/O2HitMerger.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-10T20:31:15Z", + "title": "Support for FLUKA VMC backend in O2", + "number": 5046, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/simulation/src/Stack.cxx" + } + }, + { + "node": { + "path": "Detectors/gconfig/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/gconfig/data/coreFlukaVmc.inp" + } + }, + { + "node": { + "path": "Detectors/gconfig/src/FlukaConfig.cxx" + } + }, + { + "node": { + "path": "Detectors/gconfig/src/SimSetup.cxx" + } + }, + { + "node": { + "path": "dependencies/FindFlukaVMC.cmake" + } + }, + { + "node": { + "path": "dependencies/O2FindDependenciesFromAliBuild.cmake" + } + }, + { + "node": { + "path": "dependencies/O2SimulationDependencies.cmake" + } + }, + { + "node": { + "path": "run/O2SimDevice.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-16T22:10:35Z", + "title": "TOF DCS Processor", + "number": 5047, + "author": { + "login": "chiarazampolli" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/DCS/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/DCS/src/DataPointGenerator.cxx" + } + }, + { + "node": { + "path": "Detectors/DCS/src/DetectorsDCSLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h" + } + }, + { + "node": { + "path": "Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx" + } + }, + { + "node": { + "path": "Detectors/TOF/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TOF/base/include/TOFBase/Geo.h" + } + }, + { + "node": { + "path": "Detectors/TOF/base/src/Geo.cxx" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/macros/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/src/TOFDCSProcessor.cxx" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/testWorkflow/README.md" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T09:04:41Z", + "title": "DPL: allow customization of FairMQ channels from command line", + "number": 5048, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/ChannelSpec.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/WorkflowCustomizationHelpers.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/runDataProcessing.h" + } + }, + { + "node": { + "path": "Framework/Core/src/ChannelConfigurationPolicy.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/ChannelSpecHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/DeviceSpecHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/WorkflowCustomizationHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/test/Mocking.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T15:53:21Z", + "title": "Add DAQ SystemID Unloaded [O2-1918]", + "number": 5049, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Headers/include/Headers/DAQID.h" + } + }, + { + "node": { + "path": "DataFormats/Headers/test/testDAQID.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T08:40:42Z", + "title": "DPL Analysis: use compile-time hashed histogram names in registry", + "number": 5050, + "author": { + "login": "mario-krueger" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Core/include/AnalysisCore/PairCuts.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGCF/correlations.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/qaTask.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskD0.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskDPlus.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/spectraTOF.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/spectraTPC.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/pidTOF.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/pidTPC.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/trackqa.cxx" + } + }, + { + "node": { + "path": "Analysis/Tutorials/src/histogramRegistry.cxx" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/HistogramRegistry.h" + } + }, + { + "node": { + "path": "Framework/Core/src/HistogramRegistry.cxx" + } + }, + { + "node": { + "path": "Framework/Core/test/benchmark_HistogramRegistry.cxx" + } + }, + { + "node": { + "path": "Framework/Core/test/test_HistogramRegistry.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T09:07:35Z", + "title": "Drop obsolete badge", + "number": 5051, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "README.md" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF: do not merge yet: Add efficiency and fix impact parameter calculation", + "number": 5052, + "author": { + "login": "hzanoli" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/PWGHF/qaTask.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-12T12:41:53Z", + "title": "ndsplines: added approximateFunctionBatch function", + "number": 5053, + "author": { + "login": "matthias-kleiner" + }, + "files": { + "edges": [ + { + "node": { + "path": "GPU/TPCFastTransformation/SplineHelper.cxx" + } + }, + { + "node": { + "path": "GPU/TPCFastTransformation/SplineHelper.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T15:54:24Z", + "title": "Add braces in oneliners of PHOS code", + "number": 5054, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-12T08:55:30Z", + "title": "Change more Double_t to float in TrackParCov propagator", + "number": 5055, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/Base/src/Propagator.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-13T13:05:53Z", + "title": "Eliminate mass argument from track mat.corrections and propagation interfaces", + "number": 5056, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + } + }, + { + "node": { + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + } + }, + { + "node": { + "path": "Detectors/Base/src/Propagator.cxx" + } + }, + { + "node": { + "path": "Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h" + } + }, + { + "node": { + "path": "Detectors/GlobalTracking/src/MatchTOF.cxx" + } + }, + { + "node": { + "path": "Detectors/GlobalTracking/src/MatchTPCITS.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-16T18:17:59Z", + "title": "Update of water and air cooling", + "number": 5057, + "author": { + "login": "frmanso" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/MFT/base/src/HalfCone.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-13T20:42:36Z", + "title": "Reject outliers when building ITS/MFT clusters dictionary", + "number": 5058, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T08:01:58Z", + "title": "TPC drift gas settings in case FLUKA is used", + "number": 5059, + "author": { + "login": "amorsch" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/TPC/simulation/src/Detector.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T10:52:58Z", + "title": "Fix finder -> problems with partitioning to be checked", + "number": 5060, + "author": { + "login": "ddobrigk" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "CLOSED", + "mergedAt": null, + "title": "A ROOT serializable key-value store", + "number": 5061, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ + { + "node": { + "path": "Common/Utils/CMakeLists.txt" + } + }, + { + "node": { + "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" + } + }, + { + "node": { + "path": "Common/Utils/src/CommonUtilsLinkDef.h" + } + }, + { + "node": { + "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" + } + }, + { + "node": { + "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "[WIP][ITS-tracking] Extend smoother to n-dimensional tracking", + "number": 5062, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T21:42:12Z", + "title": "DPL Analysis: add string array Configurable", + "number": 5063, + "author": { + "login": "aalkin" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tutorials/include/Analysis/configurableCut.h" + } + }, + { + "node": { + "path": "Analysis/Tutorials/src/configurableCut.cxx" + } + }, + { + "node": { + "path": "Analysis/Tutorials/src/configurableObjects.cxx" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/ConfigParamsHelper.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/Variant.h" + } + }, + { + "node": { + "path": "Framework/Core/src/BoostOptionsRetriever.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/ConfigParamsHelper.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/PropertyTreeHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/RootConfigParamHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/Variant.cxx" + } + }, + { + "node": { + "path": "Framework/Core/test/test_Variants.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T21:43:13Z", + "title": "Using histogram registry fill", + "number": 5064, + "author": { + "login": "jgrosseo" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/PWGCF/correlations.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T19:43:17Z", + "title": "DPL: add file read name metric", + "number": 5065, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/src/AODReaderHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/ResourcesMonitoringHelper.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/ResourcesMonitoringHelper.h" + } + }, + { + "node": { + "path": "Framework/Core/src/runDataProcessing.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-15T08:48:19Z", + "title": "Analysis: extend histogram registry example", + "number": 5066, + "author": { + "login": "mario-krueger" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tutorials/src/histogramRegistry.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-15T13:38:12Z", + "title": "Increase the margin of CTF block size to 10KB", + "number": 5067, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-15T21:49:40Z", + "title": "DPL Analysis: make sure each hash in histogram registry is unique", + "number": 5068, + "author": { + "login": "mario-krueger" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/include/Framework/HistogramRegistry.h" + } + }, + { + "node": { + "path": "Framework/Core/src/HistogramRegistry.cxx" + } + }, + { + "node": { + "path": "Framework/Core/test/test_HistogramRegistry.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-28T13:55:03Z", + "title": "[WIP][ITS-tracking] Add track dumping in standalone debugger", + "number": 5069, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "TRD tracklet calculation in TrapSimulator", + "number": 5070, + "author": { + "login": "martenole" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h" + } + }, + { + "node": { + "path": "Detectors/TRD/macros/convertRun2ToRun3Digits.C" + } + }, + { + "node": { + "path": "Detectors/TRD/simulation/src/TrapSimulator.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-16T12:19:42Z", + "title": "DPL: initial support for plugin based algorithms", + "number": 5071, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/AnalysisSupport/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/AnalysisSupport/src/Plugin.cxx" + } + }, + { + "node": { + "path": "Framework/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/AlgorithmSpec.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/Plugins.h" + } + }, + { + "node": { + "path": "Framework/Core/src/WorkflowHelpers.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "A ROOT serializable key-value store", + "number": 5072, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ + { + "node": { + "path": "Common/Utils/CMakeLists.txt" + } + }, + { + "node": { + "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" + } + }, + { + "node": { + "path": "Common/Utils/src/CommonUtilsLinkDef.h" + } + }, + { + "node": { + "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" + } + }, + { + "node": { + "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-16T16:28:44Z", + "title": "DPL: allow decoupling from JAlien and retrieve JAlienFile, if available", + "number": 5073, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/AnalysisSupport/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h" + } + }, + { + "node": { + "path": "Framework/AnalysisSupport/src/Plugin.cxx" + } + }, + { + "node": { + "path": "Framework/Core/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/AODReaderHelpers.h" + } + }, + { + "node": { + "path": "Framework/Core/src/AODReaderHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/AnalysisDataModelHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/AnalysisDataModelHelpers.h" + } + }, + { + "node": { + "path": "dependencies/FindJAlienROOT.cmake" + } + }, + { + "node": { + "path": "dependencies/FindXRootD.cmake" + } + }, + { + "node": { + "path": "dependencies/O2Dependencies.cmake" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": " Initial version of EMCAL Correction Task", + "number": 5074, + "author": { + "login": "raymondEhlers" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/CMakeLists.txt" + } + }, + { + "node": { + "path": "Analysis/Tasks/emcalCorrectionTask.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "CLOSED", + "mergedAt": null, + "title": "Jpsi task and candidate selection", + "number": 5075, + "author": { + "login": "zhangbiao-phy" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + } + }, + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-17T22:44:51Z", + "title": "[ITS][ntracker-workflow] Add --configKeyValue for MB LUT", + "number": 5076, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-17T19:07:38Z", + "title": "Tmp.fix in TrackParCov c-tor from Cartesian cov.matrix", + "number": 5077, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-17T22:22:35Z", + "title": "Parent TrackPar/Cov creator for DCAFitterN", + "number": 5078, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-17T22:27:23Z", + "title": "Fix FindJAliEnROOT.cmake name", + "number": 5079, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "dependencies/FindJAliEnROOT.cmake" + } + } + ] + } + } + }, + { + "node": { + "state": "CLOSED", + "mergedAt": null, + "title": "Jpsi task and candidate selection", + "number": 5080, + "author": { + "login": "zhangbiao-phy" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + } + }, + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-18T20:32:10Z", + "title": "DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support", + "number": 5081, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/AnalysisSupport/CMakeLists.txt" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Fill PDG code database before event generation", + "number": 5082, + "author": { + "login": "mpuccio" + }, + "files": { + "edges": [ + { + "node": { + "path": "Generators/src/GeneratorFactory.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-23T00:45:23Z", + "title": "Executable for chunk large raw-data files", + "number": 5083, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/Raw/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Raw/include/DetectorsRaw/RawFileWriter.h" + } + }, + { + "node": { + "path": "Detectors/Raw/src/RawFileWriter.cxx" + } + }, + { + "node": { + "path": "Detectors/Raw/src/rawfileSplit.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-19T22:20:45Z", + "title": "Add X at minimum to v0data table", + "number": 5084, + "author": { + "login": "ddobrigk" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF: Jpsi to e+e- task and candidate selection for HF", + "number": 5085, + "author": { + "login": "zhangbiao-phy" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + } + }, + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Use Dynamic columns for the expected PID signals", + "number": 5086, + "author": { + "login": "njacazio" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/pidTOF.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/pidTPC.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Bugfix in digits->raw->cell chain", + "number": 5087, + "author": { + "login": "peressounko" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/PHOS/base/include/PHOSBase/Mapping.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/base/src/Mapping.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/base/src/RCUTrailer.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/simulation/src/Digitizer.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/simulation/src/RawWriter.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/CellConverterSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/ClusterizerSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/PublisherSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-19T14:01:47Z", + "title": "MFT: fix lanes mapping for decoding commissionning data and for worki…", + "number": 5088, + "author": { + "login": "bovulpes" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-22T21:07:34Z", + "title": "real LUT in CCDB", + "number": 5089, + "author": { + "login": "AllaMaevskaya" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/FIT/FT0/CMakeLists.txt" + } + }, + { + "node": { + "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h" + } + }, + { + "node": { + "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h" + } + }, + { + "node": { + "path": "DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/base/files/Sim2DataChannels.txt" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/base/include/FT0Base/Geometry.h" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/base/src/Geometry.cxx" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/simulation/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/simulation/src/Detector.cxx" + } + }, + { + "node": { + "path": "Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx" + } + }, + { + "node": { + "path": "Detectors/FIT/macros/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/FIT/macros/uploadLookUpTable.C" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Add skeleton for DDbar analysis", + "number": 5090, + "author": { + "login": "ginnocen" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFDDbar_corr.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-22T21:06:19Z", + "title": "MFT: eliminate sqrt where possible", + "number": 5091, + "author": { + "login": "bovulpes" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx" + } + }, + { + "node": { + "path": "Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-23T21:37:54Z", + "title": "ZDC Workflow to inspect raw data", + "number": 5092, + "author": { + "login": "cortesep" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/ZDC/CMakeLists.txt" + } + }, + { + "node": { + "path": "DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h" + } + }, + { + "node": { + "path": "DataFormats/Detectors/ZDC/src/RawEventData.cxx" + } + }, + { + "node": { + "path": "Detectors/ZDC/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/ZDC/base/src/ModuleConfig.cxx" + } + }, + { + "node": { + "path": "Detectors/ZDC/raw/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h" + } + }, + { + "node": { + "path": "Detectors/ZDC/raw/src/DumpRaw.cxx" + } + }, + { + "node": { + "path": "Detectors/ZDC/raw/src/ZDCRawLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/ZDC/raw/src/raw-parser.cxx" + } + }, + { + "node": { + "path": "Detectors/ZDC/simulation/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/ZDC/simulation/src/Digitizer.cxx" + } + }, + { + "node": { + "path": "Detectors/ZDC/simulation/src/digi2raw.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-24T13:43:32Z", + "title": "GPU: Exclude ITS Tracking / Vertexing parts from run time compilation", + "number": 5093, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-24T13:43:15Z", + "title": "GPU: Some work towards making the o2 propagator work on GPU", + "number": 5094, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" + } + }, + { + "node": { + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + } + }, + { + "node": { + "path": "Detectors/Base/src/Propagator.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Draft HFMCValidation Heavy Flavour Monte Carlo validation", + "number": 5095, + "author": { + "login": "apalasciano" + }, + "files": { + "edges": [ + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFMCMatchingValidation.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-25T12:29:48Z", + "title": "Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU", + "number": 5096, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" + } + }, + { + "node": { + "path": "Detectors/Base/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + } + }, + { + "node": { + "path": "Detectors/Base/src/Propagator.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-25T12:43:43Z", + "title": "TPC Tracking: Workaround for 0-cluster tracks", + "number": 5097, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/TPC/reconstruction/src/GPUCATracking.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-27T08:29:55Z", + "title": "DPL: use RawDeviceService to sleep in example", + "number": 5098, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/TestWorkflows/src/o2DiamondWorkflow.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "DPL: move GUI to a plugin", + "number": 5099, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/DataProcessorInfo.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/DebugGUI.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/DriverControl.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/DriverInfo.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/Plugins.h" + } + }, + { + "node": { + "path": "Framework/Core/src/DeviceSpecHelpers.h" + } + }, + { + "node": { + "path": "Framework/Core/src/DriverControl.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/DriverInfo.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/FrameworkDummyDebugger.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/WorkflowHelpers.h" + } + }, + { + "node": { + "path": "Framework/Core/src/WorkflowSerializationHelpers.h" + } + }, + { + "node": { + "path": "Framework/Core/src/runDataProcessing.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.h" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDebugger.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDebugger.h" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.h" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.h" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/FrameworkGUIState.h" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/NoDebugGUI.h" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/PaletteHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/PaletteHelpers.h" + } + }, + { + "node": { + "path": "Framework/GUISupport/src/Plugin.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/test/test_CustomGUIGL.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/test/test_CustomGUISokol.cxx" + } + }, + { + "node": { + "path": "Framework/GUISupport/test/test_SimpleTracksED.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-28T10:37:16Z", + "title": "GPU: Make more headers compatible to GPU", + "number": 5100, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h" + } + }, + { + "node": { + "path": "DataFormats/common/include/CommonDataFormat/RangeReference.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-29T19:17:29Z", + "title": "[EMCAL-675] Handling of pages without trailer", + "number": 5101, + "author": { + "login": "mfasDa" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-29T09:49:03Z", + "title": "Drop bad assert", + "number": 5102, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "CTP Data structures development", + "number": 5103, + "author": { + "login": "lietava" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/CTP/CTPRawData.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T08:36:57Z", + "title": "Use DBSCAN for Time-Z clustering in PVertexing, debris reduction", + "number": 5104, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h" + } + }, + { + "node": { + "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h" + } + }, + { + "node": { + "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h" + } + }, + { + "node": { + "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h" + } + }, + { + "node": { + "path": "Detectors/Vertexing/src/PVertexer.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Disable CA_DEBUG in ITS Tracking", + "number": 5105, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T09:27:57Z", + "title": "Add workflow to generate CHANGELOG", + "number": 5106, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": ".github/workflows/reports.yml" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T09:51:49Z", + "title": "Fix changelog generation", + "number": 5107, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": ".github/workflows/reports.yml" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T10:17:44Z", + "title": "Fix CHANGELOG generation", + "number": 5108, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": ".github/workflows/reports.yml" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T10:34:21Z", + "title": "Fix CHANGELOG generation", + "number": 5109, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": ".github/workflows/reports.yml" + } + } + ] + } + } + } + ] + } + } +} diff --git a/doc/data/2021-01-o2_releases.json b/doc/data/2021-01-o2_releases.json new file mode 100644 index 0000000000000..26c8a2e6983f9 --- /dev/null +++ b/doc/data/2021-01-o2_releases.json @@ -0,0 +1,32 @@ +{ + "repository": { + "releases": { + "edges": [ + { + "node": { + "tagName": "O2-1.0.0", + "publishedAt": "2018-11-21T13:41:46Z" + } + }, + { + "node": { + "tagName": "v1.2.0", + "publishedAt": "2020-02-25T09:10:00Z" + } + }, + { + "node": { + "tagName": "v1.3.0", + "publishedAt": "2020-09-22T07:21:04Z" + } + }, + { + "node": { + "tagName": "v20.49", + "publishedAt": "2020-12-11T16:12:56Z" + } + } + ] + } + } +} From b33f6ec22df8355d7489f099994dc5db9a7f41a4 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 4 Jan 2021 10:13:03 +0100 Subject: [PATCH 1679/1751] Disable CA_DEBUG in ITS Tracking --- Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index 2b8de64b7f682..b54b91801b267 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -21,7 +21,7 @@ #include <array> #endif -#define CA_DEBUG +//#define CA_DEBUG #ifdef CA_DEBUG #define CA_DEBUGGER(x) x From 809fcfab2b0d95fa40aedc416e8c7468b9e4a9c3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 17:39:29 +0100 Subject: [PATCH 1680/1751] DPL: drop unneeded include statements (#5113) cstdio should never be exposed in headers as it bloats. --- Framework/Core/include/Framework/DataProcessingHeader.h | 1 - Framework/Core/include/Framework/SourceInfoHeader.h | 1 - Framework/Foundation/include/Framework/Pack.h | 1 - 3 files changed, 3 deletions(-) diff --git a/Framework/Core/include/Framework/DataProcessingHeader.h b/Framework/Core/include/Framework/DataProcessingHeader.h index 0627cf8887d6d..313c9598bcbf8 100644 --- a/Framework/Core/include/Framework/DataProcessingHeader.h +++ b/Framework/Core/include/Framework/DataProcessingHeader.h @@ -13,7 +13,6 @@ #include "Headers/DataHeader.h" #include <cstdint> -#include <cstdio> #include <memory> #include <cassert> #include <chrono> diff --git a/Framework/Core/include/Framework/SourceInfoHeader.h b/Framework/Core/include/Framework/SourceInfoHeader.h index cc024d69e2b66..ba870b270987e 100644 --- a/Framework/Core/include/Framework/SourceInfoHeader.h +++ b/Framework/Core/include/Framework/SourceInfoHeader.h @@ -14,7 +14,6 @@ #include "Framework/ChannelInfo.h" #include <cstdint> -#include <cstdio> #include <memory> #include <cassert> diff --git a/Framework/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index 59282108fb434..c14f65e6bda8e 100644 --- a/Framework/Foundation/include/Framework/Pack.h +++ b/Framework/Foundation/include/Framework/Pack.h @@ -12,7 +12,6 @@ #include <cstddef> #include <utility> -#include <cstdio> namespace o2::framework { From 24d3e043c64da726cdd8af76d566854d603f75ac Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 4 Jan 2021 19:52:57 +0100 Subject: [PATCH 1681/1751] DPL: move GUI to a plugin (#5099) This moves the whole GUI implementation to an on demand plugin which will be loaded only if we are not in batch mode. This will both save memory (30MB PSS, in my tests) and speedup startup when running in batch mode. --- Framework/CMakeLists.txt | 2 + Framework/Core/CMakeLists.txt | 36 +---------- .../Framework}/DataProcessorInfo.h | 0 Framework/Core/include/Framework/DebugGUI.h | 40 ++++++++++++ .../Framework}/DriverControl.h | 2 +- .../{src => include/Framework}/DriverInfo.h | 0 Framework/Core/include/Framework/Plugins.h | 5 +- Framework/Core/src/DeviceSpecHelpers.h | 2 +- Framework/Core/src/DriverControl.cxx | 2 +- Framework/Core/src/DriverInfo.cxx | 2 +- Framework/Core/src/FrameworkDummyDebugger.cxx | 38 ----------- Framework/Core/src/WorkflowHelpers.h | 2 +- .../Core/src/WorkflowSerializationHelpers.h | 9 +-- Framework/Core/src/runDataProcessing.cxx | 57 ++++++++++++----- Framework/GUISupport/CMakeLists.txt | 63 +++++++++++++++++++ .../src/FrameworkGUIDataRelayerUsage.cxx | 0 .../src}/FrameworkGUIDataRelayerUsage.h | 0 .../src/FrameworkGUIDebugger.cxx | 14 ++--- .../src}/FrameworkGUIDebugger.h | 15 ++--- .../src/FrameworkGUIDeviceInspector.cxx | 2 +- .../src/FrameworkGUIDeviceInspector.h | 0 .../src/FrameworkGUIDevicesGraph.cxx | 17 ++--- .../src}/FrameworkGUIDevicesGraph.h | 18 ++---- .../src}/FrameworkGUIState.h | 0 .../Framework => GUISupport/src}/NoDebugGUI.h | 0 .../src/PaletteHelpers.cxx | 2 +- .../src}/PaletteHelpers.h | 0 Framework/GUISupport/src/Plugin.cxx | 49 +++++++++++++++ .../test/test_CustomGUIGL.cxx | 0 .../test/test_CustomGUISokol.cxx | 0 .../test/test_SimpleTracksED.cxx | 0 31 files changed, 235 insertions(+), 142 deletions(-) rename Framework/Core/{src => include/Framework}/DataProcessorInfo.h (100%) create mode 100644 Framework/Core/include/Framework/DebugGUI.h rename Framework/Core/{src => include/Framework}/DriverControl.h (98%) rename Framework/Core/{src => include/Framework}/DriverInfo.h (100%) delete mode 100644 Framework/Core/src/FrameworkDummyDebugger.cxx create mode 100644 Framework/GUISupport/CMakeLists.txt rename Framework/{Core => GUISupport}/src/FrameworkGUIDataRelayerUsage.cxx (100%) rename Framework/{Core/include/Framework => GUISupport/src}/FrameworkGUIDataRelayerUsage.h (100%) rename Framework/{Core => GUISupport}/src/FrameworkGUIDebugger.cxx (99%) rename Framework/{Core/include/Framework => GUISupport/src}/FrameworkGUIDebugger.h (85%) rename Framework/{Core => GUISupport}/src/FrameworkGUIDeviceInspector.cxx (99%) rename Framework/{Core => GUISupport}/src/FrameworkGUIDeviceInspector.h (100%) rename Framework/{Core => GUISupport}/src/FrameworkGUIDevicesGraph.cxx (97%) rename Framework/{Core/include/Framework => GUISupport/src}/FrameworkGUIDevicesGraph.h (78%) rename Framework/{Core/include/Framework => GUISupport/src}/FrameworkGUIState.h (100%) rename Framework/{Core/include/Framework => GUISupport/src}/NoDebugGUI.h (100%) rename Framework/{Core => GUISupport}/src/PaletteHelpers.cxx (98%) rename Framework/{Core/include/Framework => GUISupport/src}/PaletteHelpers.h (100%) create mode 100644 Framework/GUISupport/src/Plugin.cxx rename Framework/{Core => GUISupport}/test/test_CustomGUIGL.cxx (100%) rename Framework/{Core => GUISupport}/test/test_CustomGUISokol.cxx (100%) rename Framework/{Core => GUISupport}/test/test_SimpleTracksED.cxx (100%) diff --git a/Framework/CMakeLists.txt b/Framework/CMakeLists.txt index 90bdaa39685d2..362968ede706a 100644 --- a/Framework/CMakeLists.txt +++ b/Framework/CMakeLists.txt @@ -18,4 +18,6 @@ add_subdirectory(Utils) add_subdirectory(AnalysisSupport) +add_subdirectory(GUISupport) + add_subdirectory(TestWorkflows) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 63c7e46765808..84e2d22b88bb7 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -8,15 +8,6 @@ # granted to it by virtue of its status as an Intergovernmental Organization or # submit itself to any jurisdiction. -if (TARGET AliceO2::DebugGUI) - set(GUI_SOURCES src/FrameworkGUIDebugger.cxx src/FrameworkGUIDevicesGraph.cxx - src/FrameworkGUIDeviceInspector.cxx - src/FrameworkGUIDataRelayerUsage.cxx src/PaletteHelpers.cxx) - set(DEBUGGUI_TARGET AliceO2::DebugGUI) -else() - set(GUI_SOURCES src/FrameworkDummyDebugger.cxx) -endif() - # Given GCC 7.3 does not provide std::filesystem we use Boost instead # Drop this once we move to GCC 8.2+ # if (NOT __APPLE__) @@ -26,7 +17,6 @@ endif() o2_add_library(Framework SOURCES src/AODReaderHelpers.cxx src/ASoA.cxx - ${GUI_SOURCES} src/AnalysisHelpers.cxx src/AnalysisDataModelHelpers.cxx src/BoostOptionsRetriever.cxx @@ -108,8 +98,7 @@ o2_add_library(Framework src/StepTHn.cxx test/TestClasses.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src - PUBLIC_LINK_LIBRARIES ${DEBUGGUI_TARGET} - AliceO2::Common + PUBLIC_LINK_LIBRARIES AliceO2::Common AliceO2::Configuration AliceO2::InfoLogger AliceO2::Monitoring @@ -257,16 +246,6 @@ endforeach() # #####################################################@ -if (TARGET AliceO2::DebugGUI) -if (NOT APPLE) -set (DEBUG_GUI_TESTS_WORKFLOW - CustomGUIGL - CustomGUISokol - SimpleTracksED - ) -endif() -endif() - foreach(w BoostSerializedProcessing CallbackService @@ -288,7 +267,6 @@ foreach(w SingleDataSource Task ExternalFairMQDeviceWorkflow - ${DEBUG_GUI_TESTS_WORKFLOW} ) o2_add_test(${w} NAME test_Framework_test_${w} SOURCES test/test_${w}.cxx @@ -304,18 +282,6 @@ endforeach() # part. [WARN] Incoming data is already obsolete, not relaying. set_property(TEST test_Framework_test_DanglingInputs PROPERTY DISABLED TRUE) -if (TARGET AliceO2::DebugGUI) -# TODO: investigate the problem with the two unit tests, maybe setup of the CI -# environment assertion fired X11: The DISPLAY environment variable is missing -# glfw-3.2.1/src/window.c:579: glfwGetFramebufferSize: Assertion `window != -# ((void *)0)' failed. -if(NOT APPLE) -set_property(TEST test_Framework_test_SimpleTracksED PROPERTY DISABLED TRUE) -set_property(TEST test_Framework_test_CustomGUIGL PROPERTY DISABLED TRUE) -set_property(TEST test_Framework_test_CustomGUISokol PROPERTY DISABLED TRUE) -endif() -endif() - # TODO: investigate the problem and re-enable set_property(TEST test_Framework_test_BoostSerializedProcessing PROPERTY DISABLED TRUE) diff --git a/Framework/Core/src/DataProcessorInfo.h b/Framework/Core/include/Framework/DataProcessorInfo.h similarity index 100% rename from Framework/Core/src/DataProcessorInfo.h rename to Framework/Core/include/Framework/DataProcessorInfo.h diff --git a/Framework/Core/include/Framework/DebugGUI.h b/Framework/Core/include/Framework/DebugGUI.h new file mode 100644 index 0000000000000..d2344671a300e --- /dev/null +++ b/Framework/Core/include/Framework/DebugGUI.h @@ -0,0 +1,40 @@ +// 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_DEBUGUIINTERFACE_H_ +#define O2_FRAMEWORK_DEBUGUIINTERFACE_H_ + +#include "Framework/DeviceInfo.h" +#include "Framework/DeviceSpec.h" +#include "Framework/DeviceControl.h" +#include "Framework/DataProcessorInfo.h" +#include "Framework/DeviceMetricsInfo.h" +#include "Framework/DriverInfo.h" +#include "Framework/DriverControl.h" + +#include <functional> +#include <vector> + +namespace o2::framework +{ +/// Plugin interface for DPL GUIs. +struct DebugGUI { + virtual std::function<void(void)> getGUIDebugger(std::vector<o2::framework::DeviceInfo> const& infos, + std::vector<o2::framework::DeviceSpec> const& devices, + std::vector<o2::framework::DataProcessorInfo> const& metadata, + std::vector<o2::framework::DeviceMetricsInfo> const& metricsInfos, + o2::framework::DriverInfo const& driverInfo, + std::vector<o2::framework::DeviceControl>& controls, + o2::framework::DriverControl& driverControl) = 0; + virtual void* initGUI(char const* windowTitle) = 0; + virtual bool pollGUI(void* context, std::function<void(void)> guiCallback) = 0; + virtual void disposeGUI() = 0; +}; +} // namespace o2::framework +#endif // O2_FRAMEWORK_DEBUGUIINTERFACE_H_ diff --git a/Framework/Core/src/DriverControl.h b/Framework/Core/include/Framework/DriverControl.h similarity index 98% rename from Framework/Core/src/DriverControl.h rename to Framework/Core/include/Framework/DriverControl.h index 606e1c8ef6bff..b9ac9f303d41e 100644 --- a/Framework/Core/src/DriverControl.h +++ b/Framework/Core/include/Framework/DriverControl.h @@ -13,7 +13,7 @@ #include <functional> #include <vector> -#include "DriverInfo.h" +#include "Framework/DriverInfo.h" #include "Framework/DataProcessorSpec.h" #include "Framework/DeviceSpec.h" #include "Framework/DeviceExecution.h" diff --git a/Framework/Core/src/DriverInfo.h b/Framework/Core/include/Framework/DriverInfo.h similarity index 100% rename from Framework/Core/src/DriverInfo.h rename to Framework/Core/include/Framework/DriverInfo.h diff --git a/Framework/Core/include/Framework/Plugins.h b/Framework/Core/include/Framework/Plugins.h index 6a159a7065890..eaa15703d94f1 100644 --- a/Framework/Core/include/Framework/Plugins.h +++ b/Framework/Core/include/Framework/Plugins.h @@ -19,7 +19,10 @@ namespace o2::framework enum struct DplPluginKind : int { // A plugin which can customise the workflow. Needs to return // an object of kind o2::framework::WorkflowCustomizationService - CustomAlgorithm + CustomAlgorithm, + // A plugin which implements a ImGUI GUI. Needs to return an + // object of the kind o2::framework::DebugGUIImpl + DebugGUIImpl }; } // namespace o2::framework diff --git a/Framework/Core/src/DeviceSpecHelpers.h b/Framework/Core/src/DeviceSpecHelpers.h index f3c69f8863c0c..244f6ddab3c1a 100644 --- a/Framework/Core/src/DeviceSpecHelpers.h +++ b/Framework/Core/src/DeviceSpecHelpers.h @@ -22,8 +22,8 @@ #include "Framework/AlgorithmSpec.h" #include "Framework/ConfigParamSpec.h" #include "Framework/OutputRoute.h" +#include "Framework/DataProcessorInfo.h" #include "ResourceManager.h" -#include "DataProcessorInfo.h" #include "WorkflowHelpers.h" #include <boost/program_options.hpp> diff --git a/Framework/Core/src/DriverControl.cxx b/Framework/Core/src/DriverControl.cxx index e36ec3c49c0c4..9ff709f28c8a7 100644 --- a/Framework/Core/src/DriverControl.cxx +++ b/Framework/Core/src/DriverControl.cxx @@ -7,4 +7,4 @@ // 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 "DriverControl.h" +#include "Framework/DriverControl.h" diff --git a/Framework/Core/src/DriverInfo.cxx b/Framework/Core/src/DriverInfo.cxx index 8df33b8452a83..5d12c9b098ca2 100644 --- a/Framework/Core/src/DriverInfo.cxx +++ b/Framework/Core/src/DriverInfo.cxx @@ -7,4 +7,4 @@ // 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 "DriverInfo.h" +#include "Framework/DriverInfo.h" diff --git a/Framework/Core/src/FrameworkDummyDebugger.cxx b/Framework/Core/src/FrameworkDummyDebugger.cxx deleted file mode 100644 index 0520e260cf071..0000000000000 --- a/Framework/Core/src/FrameworkDummyDebugger.cxx +++ /dev/null @@ -1,38 +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. -#include "DataProcessorInfo.h" -#include "Framework/FrameworkGUIDebugger.h" - -#include <algorithm> -#include <vector> - -namespace o2 -{ -namespace framework -{ -namespace gui -{ -// Dummy function in case we want to build without debugger. -std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos, - std::vector<DeviceSpec> const& devices, - std::vector<DataProcessorInfo> const& metadata, - std::vector<DeviceMetricsInfo> const& metricsInfos, - DriverInfo const& driverInfo, - std::vector<DeviceControl>& controls, - DriverControl& driverControl) -{ - return []() {}; -} - -void showNodeGraph(bool* opened) {} - -} // namespace gui -} // namespace framework -} // namespace o2 diff --git a/Framework/Core/src/WorkflowHelpers.h b/Framework/Core/src/WorkflowHelpers.h index c673b1e9940b0..f7ffde511c415 100644 --- a/Framework/Core/src/WorkflowHelpers.h +++ b/Framework/Core/src/WorkflowHelpers.h @@ -15,7 +15,7 @@ #include "Framework/ForwardRoute.h" #include "Framework/WorkflowSpec.h" #include "Framework/DataOutputDirector.h" -#include "DataProcessorInfo.h" +#include "Framework/DataProcessorInfo.h" #include <cstddef> #include <vector> diff --git a/Framework/Core/src/WorkflowSerializationHelpers.h b/Framework/Core/src/WorkflowSerializationHelpers.h index 671c14ef60dd7..1d9bd7fa8f904 100644 --- a/Framework/Core/src/WorkflowSerializationHelpers.h +++ b/Framework/Core/src/WorkflowSerializationHelpers.h @@ -11,14 +11,12 @@ #define O2_FRAMEWORK_CORE_WORKFLOWSERIALIZATIONHELPERS_H_ #include "Framework/DataProcessorSpec.h" -#include "DataProcessorInfo.h" +#include "Framework/DataProcessorInfo.h" #include <iosfwd> #include <vector> -namespace o2 -{ -namespace framework +namespace o2::framework { struct WorkflowSerializationHelpers { @@ -30,7 +28,6 @@ struct WorkflowSerializationHelpers { std::vector<DataProcessorInfo> const& metadata); }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif // O2_FRAMEWORK_CORE_WORKFLOWSERIALIZATIONHELPERS_H_ diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 1c3b8583b5838..54b1aa7bf78b4 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -15,14 +15,7 @@ #include "Framework/ConfigContext.h" #include "Framework/DataProcessingDevice.h" #include "Framework/DataProcessorSpec.h" -#if __has_include(<DebugGUI/DebugGUI.h>) -#include <DebugGUI/DebugGUI.h> -#else -// the DebugGUI is in a separate package and is optional for O2, -// we include a header implementing GUI interface dummy methods -#pragma message "Building DPL without Debug GUI" -#include "Framework/NoDebugGUI.h" -#endif +#include "Framework/Plugins.h" #include "Framework/DeviceControl.h" #include "Framework/DeviceExecution.h" #include "Framework/DeviceInfo.h" @@ -30,7 +23,7 @@ #include "Framework/DeviceConfigInfo.h" #include "Framework/DeviceSpec.h" #include "Framework/DeviceState.h" -#include "Framework/FrameworkGUIDebugger.h" +#include "Framework/DebugGUI.h" #include "Framework/LocalRootFileService.h" #include "Framework/LogParsingHelpers.h" #include "Framework/Logger.h" @@ -43,15 +36,15 @@ #include "Framework/CallbackService.h" #include "Framework/WorkflowSpec.h" #include "Framework/Monitoring.h" +#include "Framework/DataProcessorInfo.h" +#include "Framework/DriverInfo.h" +#include "Framework/DriverControl.h" #include "ComputingResourceHelpers.h" #include "DataProcessingStatus.h" #include "DDSConfigHelpers.h" #include "O2ControlHelpers.h" #include "DeviceSpecHelpers.h" -#include "DriverControl.h" -#include "DriverInfo.h" -#include "DataProcessorInfo.h" #include "GraphvizHelpers.h" #include "PropertyTreeHelpers.h" #include "SimpleResourceManager.h" @@ -841,6 +834,7 @@ struct GuiCallbackContext { uint64_t frameLast; float* frameLatency; float* frameCost; + DebugGUI* plugin; void* window; bool* guiQuitRequested; std::function<void(void)> callback; @@ -849,9 +843,12 @@ struct GuiCallbackContext { void gui_callback(uv_timer_s* ctx) { GuiCallbackContext* gui = reinterpret_cast<GuiCallbackContext*>(ctx->data); + if (gui->plugin == nullptr) { + return; + } uint64_t frameStart = uv_hrtime(); uint64_t frameLatency = frameStart - gui->frameLast; - *(gui->guiQuitRequested) = (pollGUI(gui->window, gui->callback) == false); + *(gui->guiQuitRequested) = (gui->plugin->pollGUI(gui->window, gui->callback) == false); uint64_t frameEnd = uv_hrtime(); *(gui->frameCost) = (frameEnd - frameStart) / 1000000; *(gui->frameLatency) = frameLatency / 1000000; @@ -892,12 +889,39 @@ int runStateMachine(DataProcessorSpecs const& workflow, auto resourceManager = std::make_unique<SimpleResourceManager>(resources); + DebugGUI* debugGUI = nullptr; void* window = nullptr; - decltype(gui::getGUIDebugger(infos, deviceSpecs, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl)) debugGUICallback; + decltype(debugGUI->getGUIDebugger(infos, deviceSpecs, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl)) debugGUICallback; // An empty frameworkId means this is the driver, so we initialise the GUI if (driverInfo.batch == false && frameworkId.empty()) { - window = initGUI("O2 Framework debug GUI"); + auto initDebugGUI = []() -> DebugGUI* { + uv_lib_t supportLib; + int result = 0; + #ifdef __APPLE__ + result = uv_dlopen("libO2FrameworkGUISupport.dylib", &supportLib); + #else + result = uv_dlopen("libO2FrameworkGUISupport.so", &supportLib); + #endif + if (result == -1) { + LOG(ERROR) << uv_dlerror(&supportLib); + return nullptr; + } + void* callback = nullptr; + DPLPluginHandle* (*dpl_plugin_callback)(DPLPluginHandle*); + + result = uv_dlsym(&supportLib, "dpl_plugin_callback", (void**)&dpl_plugin_callback); + if (result == -1) { + LOG(ERROR) << uv_dlerror(&supportLib); + return nullptr; + } + DPLPluginHandle* pluginInstance = dpl_plugin_callback(nullptr); + return PluginManager::getByName<DebugGUI>(pluginInstance, "ImGUIDebugGUI"); + }; + debugGUI = initDebugGUI(); + if (debugGUI) { + window = debugGUI->initGUI("O2 Framework debug GUI"); + } } if (driverInfo.batch == false && window == nullptr && frameworkId.empty()) { LOG(WARN) << "Could not create GUI. Switching to batch mode. Do you have GLFW on your system?"; @@ -920,6 +944,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, } GuiCallbackContext guiContext; + guiContext.plugin = debugGUI; guiContext.frameLast = uv_hrtime(); guiContext.frameLatency = &driverInfo.frameLatency; guiContext.frameCost = &driverInfo.frameCost; @@ -1125,7 +1150,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, // because getGUIDebugger actually recreates the GUI state. if (window) { uv_timer_stop(&gui_timer); - guiContext.callback = gui::getGUIDebugger(infos, deviceSpecs, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl); + guiContext.callback = debugGUI->getGUIDebugger(infos, deviceSpecs, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl); guiContext.window = window; gui_timer.data = &guiContext; uv_timer_start(&gui_timer, gui_callback, 0, 20); diff --git a/Framework/GUISupport/CMakeLists.txt b/Framework/GUISupport/CMakeLists.txt new file mode 100644 index 0000000000000..e5ed0613edb4f --- /dev/null +++ b/Framework/GUISupport/CMakeLists.txt @@ -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. + +# Given GCC 7.3 does not provide std::filesystem we use Boost instead +# Drop this once we move to GCC 8.2+ + +if (TARGET AliceO2::DebugGUI) + set(GUI_SOURCES src/FrameworkGUIDebugger.cxx src/FrameworkGUIDevicesGraph.cxx + src/FrameworkGUIDeviceInspector.cxx + src/FrameworkGUIDataRelayerUsage.cxx src/PaletteHelpers.cxx) + set(EXTRA_TARGETS AliceO2::DebugGUI) +else() + set(GUI_SOURCES src/FrameworkDummyDebugger.cxx) +endif() + +o2_add_library(FrameworkGUISupport + SOURCES src/Plugin.cxx + ${GUI_SOURCES} + PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src + PUBLIC_LINK_LIBRARIES O2::Framework ${EXTRA_TARGETS}) + +if (TARGET AliceO2::DebugGUI) +if (NOT APPLE) +set (DEBUG_GUI_TESTS_WORKFLOW + CustomGUIGL + CustomGUISokol + SimpleTracksED + ) +endif() +endif() + +foreach(w + ${DEBUG_GUI_TESTS_WORKFLOW} + ) + o2_add_test(${w} NAME test_Framework_test_${w} + SOURCES test/test_${w}.cxx + COMPONENT_NAME Framework + LABELS framework workflow + PUBLIC_LINK_LIBRARIES O2::Framework AliceO2::DebugGUI + TIMEOUT 30 + NO_BOOST_TEST + COMMAND_LINE_ARGS ${DPL_WORKFLOW_TESTS_EXTRA_OPTIONS} --run --shm-segment-size 20000000) +endforeach() + +if (TARGET AliceO2::DebugGUI) +# TODO: investigate the problem with the two unit tests, maybe setup of the CI +# environment assertion fired X11: The DISPLAY environment variable is missing +# glfw-3.2.1/src/window.c:579: glfwGetFramebufferSize: Assertion `window != +# ((void *)0)' failed. +if(NOT APPLE) +set_property(TEST test_Framework_test_SimpleTracksED PROPERTY DISABLED TRUE) +set_property(TEST test_Framework_test_CustomGUIGL PROPERTY DISABLED TRUE) +set_property(TEST test_Framework_test_CustomGUISokol PROPERTY DISABLED TRUE) +endif() +endif() + diff --git a/Framework/Core/src/FrameworkGUIDataRelayerUsage.cxx b/Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.cxx similarity index 100% rename from Framework/Core/src/FrameworkGUIDataRelayerUsage.cxx rename to Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.cxx diff --git a/Framework/Core/include/Framework/FrameworkGUIDataRelayerUsage.h b/Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.h similarity index 100% rename from Framework/Core/include/Framework/FrameworkGUIDataRelayerUsage.h rename to Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.h diff --git a/Framework/Core/src/FrameworkGUIDebugger.cxx b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx similarity index 99% rename from Framework/Core/src/FrameworkGUIDebugger.cxx rename to Framework/GUISupport/src/FrameworkGUIDebugger.cxx index 9d4fd274e7782..a0e9f97a9122a 100644 --- a/Framework/Core/src/FrameworkGUIDebugger.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx @@ -7,19 +7,19 @@ // 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/FrameworkGUIDebugger.h" +#include "FrameworkGUIDebugger.h" #include "Framework/ConfigContext.h" #include "Framework/ConfigParamRegistry.h" #include "DebugGUI/imgui.h" #include "DebugGUI/implot.h" #include "DebugGUI/imgui_extras.h" -#include "DriverControl.cxx" -#include "DriverInfo.cxx" +#include "Framework/DriverControl.h" +#include "Framework/DriverInfo.h" #include "FrameworkGUIDeviceInspector.h" -#include "Framework/FrameworkGUIDevicesGraph.h" -#include "Framework/FrameworkGUIDataRelayerUsage.h" -#include "Framework/PaletteHelpers.h" -#include "Framework/FrameworkGUIState.h" +#include "FrameworkGUIDevicesGraph.h" +#include "FrameworkGUIDataRelayerUsage.h" +#include "PaletteHelpers.h" +#include "FrameworkGUIState.h" #include <fmt/format.h> diff --git a/Framework/Core/include/Framework/FrameworkGUIDebugger.h b/Framework/GUISupport/src/FrameworkGUIDebugger.h similarity index 85% rename from Framework/Core/include/Framework/FrameworkGUIDebugger.h rename to Framework/GUISupport/src/FrameworkGUIDebugger.h index 20cb8d1671e07..0788169177a68 100644 --- a/Framework/Core/include/Framework/FrameworkGUIDebugger.h +++ b/Framework/GUISupport/src/FrameworkGUIDebugger.h @@ -7,10 +7,10 @@ // 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_FRAMEWORKGUIDEBUGGER_H_ -#define FRAMEWORK_FRAMEWORKGUIDEBUGGER_H_ +#ifndef O2_FRAMEWORK_FRAMEWORKGUIDEBUGGER_H_ +#define O2_FRAMEWORK_FRAMEWORKGUIDEBUGGER_H_ -#include "DataProcessorInfo.h" +#include "Framework/DataProcessorInfo.h" #include "Framework/DeviceControl.h" #include "Framework/DeviceInfo.h" #include "Framework/DeviceMetricsInfo.h" @@ -19,9 +19,7 @@ #include <functional> #include <vector> -namespace o2 -{ -namespace framework +namespace o2::framework { class DriverInfo; @@ -38,6 +36,5 @@ std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos, std::vector<DeviceControl>& controls, DriverControl& driverControl); } // namespace gui -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_FRAMEWORKGUIDEBUGGER_H +} // namespace o2::framework +#endif // O2_FRAMEWORK_FRAMEWORKGUIDEBUGGER_H_ diff --git a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx b/Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx similarity index 99% rename from Framework/Core/src/FrameworkGUIDeviceInspector.cxx rename to Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx index 8322ed1b87d6e..d5ff824070799 100644 --- a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx @@ -9,7 +9,7 @@ // or submit itself to any jurisdiction. #include "FrameworkGUIDeviceInspector.h" -#include "DataProcessorInfo.h" +#include "Framework/DataProcessorInfo.h" #include "Framework/DeviceControl.h" #include "Framework/DeviceSpec.h" diff --git a/Framework/Core/src/FrameworkGUIDeviceInspector.h b/Framework/GUISupport/src/FrameworkGUIDeviceInspector.h similarity index 100% rename from Framework/Core/src/FrameworkGUIDeviceInspector.h rename to Framework/GUISupport/src/FrameworkGUIDeviceInspector.h diff --git a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx similarity index 97% rename from Framework/Core/src/FrameworkGUIDevicesGraph.cxx rename to Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx index 6cd6ea68a91ee..ecb3587d3d915 100644 --- a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx @@ -7,24 +7,19 @@ // 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/FrameworkGUIDevicesGraph.h" -#include "Framework/FrameworkGUIDataRelayerUsage.h" -#include "Framework/FrameworkGUIState.h" +#include "FrameworkGUIDevicesGraph.h" +#include "FrameworkGUIDataRelayerUsage.h" +#include "FrameworkGUIState.h" +#include "PaletteHelpers.h" #include "Framework/DeviceSpec.h" #include "Framework/DeviceInfo.h" #include "Framework/LogParsingHelpers.h" -#include "Framework/PaletteHelpers.h" #include "Framework/Logger.h" #include "FrameworkGUIDeviceInspector.h" #include "Framework/Logger.h" #include "../src/WorkflowHelpers.h" #include "DebugGUI/imgui.h" -#if __has_include("DebugGUI/icons_font_awesome.h") -#include "DebugGUI/icons_font_awesome.h" -#else -#define ICON_FA_EXCLAMATION_CIRCLE "(Errors!)" -#define ICON_FA_EXCLAMATION_TRIANGLE "(Warnings!)" -#endif +#include <DebugGUI/icons_font_awesome.h> #include <algorithm> #include <cmath> #include <vector> @@ -232,7 +227,7 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, int groupId = 0; auto metadatum = std::find_if(metadata.begin(), metadata.end(), - [& name = spec.name](DataProcessorInfo const& info) { return info.name == name; }); + [&name = spec.name](DataProcessorInfo const& info) { return info.name == name; }); for (size_t gi = 0; gi < groupList.Size; ++gi) { if (metadatum == metadata.end()) { diff --git a/Framework/Core/include/Framework/FrameworkGUIDevicesGraph.h b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.h similarity index 78% rename from Framework/Core/include/Framework/FrameworkGUIDevicesGraph.h rename to Framework/GUISupport/src/FrameworkGUIDevicesGraph.h index 7842fcdec2343..31c86c7e57140 100644 --- a/Framework/Core/include/Framework/FrameworkGUIDevicesGraph.h +++ b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.h @@ -7,21 +7,17 @@ // 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_FRAMEWORKGUIDEVICEGRAPH_H_ -#define FRAMEWORK_FRAMEWORKGUIDEVICEGRAPH_H_ +#ifndef O2_FRAMEWORK_FRAMEWORKGUIDEVICEGRAPH_H_ +#define O2_FRAMEWORK_FRAMEWORKGUIDEVICEGRAPH_H_ -#include "../../src/DataProcessorInfo.h" +#include "Framework/DataProcessorInfo.h" #include "Framework/DeviceSpec.h" #include "Framework/DeviceInfo.h" #include "Framework/DeviceMetricsInfo.h" #include <vector> -namespace o2 -{ -namespace framework -{ -namespace gui +namespace o2::framework::gui { class WorkspaceGUIState; @@ -33,8 +29,6 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, std::vector<DeviceControl>& controls, std::vector<DeviceMetricsInfo> const& metricsInfos); -} // namespace gui -} // namespace framework -} // namespace o2 +} // namespace o2::framework::gui -#endif // FRAMEWORK_FRAMEWORKGUIDEVICEGRAPH_H_ +#endif // O2_FRAMEWORK_FRAMEWORKGUIDEVICEGRAPH_H_ diff --git a/Framework/Core/include/Framework/FrameworkGUIState.h b/Framework/GUISupport/src/FrameworkGUIState.h similarity index 100% rename from Framework/Core/include/Framework/FrameworkGUIState.h rename to Framework/GUISupport/src/FrameworkGUIState.h diff --git a/Framework/Core/include/Framework/NoDebugGUI.h b/Framework/GUISupport/src/NoDebugGUI.h similarity index 100% rename from Framework/Core/include/Framework/NoDebugGUI.h rename to Framework/GUISupport/src/NoDebugGUI.h diff --git a/Framework/Core/src/PaletteHelpers.cxx b/Framework/GUISupport/src/PaletteHelpers.cxx similarity index 98% rename from Framework/Core/src/PaletteHelpers.cxx rename to Framework/GUISupport/src/PaletteHelpers.cxx index 57405823bce57..5a0bf13f385b7 100644 --- a/Framework/Core/src/PaletteHelpers.cxx +++ b/Framework/GUISupport/src/PaletteHelpers.cxx @@ -7,7 +7,7 @@ // 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/PaletteHelpers.h" +#include "PaletteHelpers.h" namespace o2 { diff --git a/Framework/Core/include/Framework/PaletteHelpers.h b/Framework/GUISupport/src/PaletteHelpers.h similarity index 100% rename from Framework/Core/include/Framework/PaletteHelpers.h rename to Framework/GUISupport/src/PaletteHelpers.h diff --git a/Framework/GUISupport/src/Plugin.cxx b/Framework/GUISupport/src/Plugin.cxx new file mode 100644 index 0000000000000..067e90e81ab00 --- /dev/null +++ b/Framework/GUISupport/src/Plugin.cxx @@ -0,0 +1,49 @@ +// 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. +#if __has_include(<DebugGUI/DebugGUI.h>) +#include <DebugGUI/DebugGUI.h> +#else +#pragma message "Building DPL without Debug GUI" +#include "NoDebugGUI.h" +#endif + +#include "Framework/Plugins.h" +#include "Framework/DebugGUI.h" +#include "FrameworkGUIDebugger.h" + +using namespace o2::framework; + +struct ImGUIDebugGUI : o2::framework::DebugGUI { + std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos, + std::vector<DeviceSpec> const& devices, + std::vector<DataProcessorInfo> const& metadata, + std::vector<DeviceMetricsInfo> const& metricsInfos, + DriverInfo const& driverInfo, + std::vector<DeviceControl>& controls, + DriverControl& driverControl) override + { + return o2::framework::gui::getGUIDebugger(infos, devices, metadata, metricsInfos, driverInfo, controls, driverControl); + } + + void* initGUI(char const* windowTitle) override + { + return o2::framework::initGUI(windowTitle); + } + bool pollGUI(void* context, std::function<void(void)> guiCallback) override + { + return o2::framework::pollGUI(context, guiCallback); + } + void disposeGUI() override + { + o2::framework::disposeGUI(); + } +}; + +DEFINE_DPL_PLUGIN(ImGUIDebugGUI, DebugGUIImpl); diff --git a/Framework/Core/test/test_CustomGUIGL.cxx b/Framework/GUISupport/test/test_CustomGUIGL.cxx similarity index 100% rename from Framework/Core/test/test_CustomGUIGL.cxx rename to Framework/GUISupport/test/test_CustomGUIGL.cxx diff --git a/Framework/Core/test/test_CustomGUISokol.cxx b/Framework/GUISupport/test/test_CustomGUISokol.cxx similarity index 100% rename from Framework/Core/test/test_CustomGUISokol.cxx rename to Framework/GUISupport/test/test_CustomGUISokol.cxx diff --git a/Framework/Core/test/test_SimpleTracksED.cxx b/Framework/GUISupport/test/test_SimpleTracksED.cxx similarity index 100% rename from Framework/Core/test/test_SimpleTracksED.cxx rename to Framework/GUISupport/test/test_SimpleTracksED.cxx From 9446c8d6da4cc7c671dfdf7847556e1e3381c4bb Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 4 Jan 2021 16:56:51 +0100 Subject: [PATCH 1682/1751] GPU: Suppress some debug messages --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 2 +- GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx | 2 +- GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index addaf5fa869ad..52066afae40c6 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -613,7 +613,7 @@ size_t GPUReconstructionCUDABackend::TransferMemoryInternal(GPUMemoryResource* r } return 0; } - if (mProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3 && (strcmp(res->Name(), "ErrorCodes") || mProcessingSettings.debugLevel >= 4)) { GPUInfo("Copying to %s: %s - %lld bytes", toGPU ? "GPU" : "Host", res->Name(), (long long int)res->Size()); } return GPUMemCpy(dst, src, res->Size(), stream, toGPU, ev, evList, nEvents); diff --git a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx index 98b8882d6b81f..432c6ccbf4419 100644 --- a/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx +++ b/GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx @@ -478,7 +478,7 @@ size_t GPUReconstructionHIPBackend::TransferMemoryInternal(GPUMemoryResource* re } return 0; } - if (mProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3 && (strcmp(res->Name(), "ErrorCodes") || mProcessingSettings.debugLevel >= 4)) { GPUInfo("Copying to %s: %s - %lld bytes", toGPU ? "GPU" : "Host", res->Name(), (long long int)res->Size()); } return GPUMemCpy(dst, src, res->Size(), stream, toGPU, ev, evList, nEvents); diff --git a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx index 15b6076b4b4e8..69fd3d5bba07e 100644 --- a/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx +++ b/GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx @@ -392,7 +392,7 @@ size_t GPUReconstructionOCL::TransferMemoryInternal(GPUMemoryResource* res, int } return 0; } - if (mProcessingSettings.debugLevel >= 3) { + if (mProcessingSettings.debugLevel >= 3 && (strcmp(res->Name(), "ErrorCodes") || mProcessingSettings.debugLevel >= 4)) { GPUInfo("Copying to %s: %s - %lld bytes", toGPU ? "GPU" : "Host", res->Name(), (long long int)res->Size()); } return GPUMemCpy(dst, src, res->Size(), stream, toGPU, ev, evList, nEvents); From 4c65d478ee4be49535ef34a00c2f72579e31a303 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 4 Jan 2021 18:14:06 +0100 Subject: [PATCH 1683/1751] GPU: Store merged track ptrs in correct place in GPU constant memory --- .../GPUTPCCompressionKernels.cxx | 21 +++++++++---------- GPU/GPUTracking/Global/GPUChainTracking.cxx | 9 ++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx index 9fc65c2c9d506..734681c163a4e 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx @@ -14,7 +14,6 @@ #include "GPUTPCCompressionKernels.h" #include "GPUConstantMem.h" #include "GPUO2DataTypes.h" -#include "GPUTPCGMMerger.h" #include "GPUParam.h" #include "GPUCommonAlgorithm.h" #include "GPUTPCCompressionTrackModel.h" @@ -27,16 +26,16 @@ using namespace o2::tpc; template <> GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0attached>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) { - const GPUTPCGMMerger& GPUrestrict() merger = processors.tpcMerger; - const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = processors.ioPtrs.clustersNative; + const GPUTrackingInOutPointers& GPUrestrict() ioPtrs = processors.ioPtrs; + const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = ioPtrs.clustersNative; GPUTPCCompression& GPUrestrict() compressor = processors.tpcCompressor; const GPUParam& GPUrestrict() param = processors.param; char lastLeg = 0; int myTrack = 0; - for (unsigned int i = get_global_id(0); i < (unsigned int)merger.NOutputTracks(); i += get_global_size(0)) { + for (unsigned int i = get_global_id(0); i < ioPtrs.nMergedTracks; i += get_global_size(0)) { GPUbarrierWarp(); - const GPUTPCGMMergedTrack& GPUrestrict() trk = merger.OutputTracks()[i]; + const GPUTPCGMMergedTrack& GPUrestrict() trk = ioPtrs.mergedTracks[i]; if (!trk.OK()) { continue; } @@ -47,13 +46,13 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step0at GPUTPCCompressionTrackModel track; float zOffset = 0; for (int k = trk.NClusters() - 1; k >= 0; k--) { - const GPUTPCGMMergedTrackHit& GPUrestrict() hit = merger.Clusters()[trk.FirstClusterRef() + k]; + const GPUTPCGMMergedTrackHit& GPUrestrict() hit = ioPtrs.mergedTrackHits[trk.FirstClusterRef() + k]; if (hit.state & GPUTPCGMMergedTrackHit::flagReject) { continue; } int hitId = hit.num; - int attach = merger.ClusterAttachment()[hitId]; + int attach = ioPtrs.mergedTrackHitAttachment[hitId]; if ((attach & gputpcgmmergertypes::attachTrackMask) != i) { continue; // Main attachment to different track } @@ -179,8 +178,8 @@ GPUd() bool GPUTPCCompressionKernels::GPUTPCCompressionKernels_Compare<3>::opera template <> GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1unattached>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) { - const GPUTPCGMMerger& GPUrestrict() merger = processors.tpcMerger; - const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = processors.ioPtrs.clustersNative; + const GPUTrackingInOutPointers& GPUrestrict() ioPtrs = processors.ioPtrs; + const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = ioPtrs.clustersNative; GPUTPCCompression& GPUrestrict() compressor = processors.tpcCompressor; GPUParam& GPUrestrict() param = processors.param; unsigned int* sortBuffer = smem.sortBuffer; @@ -207,7 +206,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un if (compressor.mClusterStatus[idx]) { break; } - int attach = merger.ClusterAttachment()[idx]; + int attach = ioPtrs.mergedTrackHitAttachment[idx]; bool unattached = attach == 0; if (unattached) { @@ -219,7 +218,7 @@ GPUdii() void GPUTPCCompressionKernels::Thread<GPUTPCCompressionKernels::step1un break; } int id = attach & gputpcgmmergertypes::attachTrackMask; - auto& trk = merger.OutputTracks()[id]; + auto& trk = ioPtrs.mergedTracks[id]; if (CAMath::Abs(trk.GetParam().GetQPt()) > processors.param.rec.tpcRejectQPt || trk.MergedLooper()) { break; } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 265c08efd9473..55e26c31d8133 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -2084,6 +2084,15 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) mIOPtrs.nMergedTrackHits = Merger.NOutputTrackClusters(); mIOPtrs.mergedTrackHitAttachment = Merger.ClusterAttachment(); mIOPtrs.mergedTrackHitStates = Merger.ClusterStateExt(); + if (doGPU) { + processorsShadow()->ioPtrs.mergedTracks = MergerShadow.OutputTracks(); + processorsShadow()->ioPtrs.nMergedTracks = Merger.NOutputTracks(); + processorsShadow()->ioPtrs.mergedTrackHits = MergerShadow.Clusters(); + processorsShadow()->ioPtrs.nMergedTrackHits = Merger.NOutputTrackClusters(); + processorsShadow()->ioPtrs.mergedTrackHitAttachment = MergerShadow.ClusterAttachment(); + processorsShadow()->ioPtrs.mergedTrackHitStates = MergerShadow.ClusterStateExt(); + WriteToConstantMemory(RecoStep::TPCMerging, (char*)&processors()->ioPtrs - (char*)processors(), &processorsShadow()->ioPtrs, sizeof(processorsShadow()->ioPtrs), 0); + } if (GetProcessingSettings().debugLevel >= 2) { GPUInfo("TPC Merger Finished (output clusters %d / input clusters %d)", Merger.NOutputTrackClusters(), Merger.NClusters()); From 585bc0f91c4daeae7107d7da973b4e1e22cd9f58 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Mon, 4 Jan 2021 22:44:27 +0100 Subject: [PATCH 1684/1751] Default mat.corr. is with LUT, fall-back to TGeo if LUT is not set --- .../Base/include/DetectorsBase/Propagator.h | 16 ++++++++-------- Detectors/Base/src/Propagator.cxx | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index 8a85455d251bb..c9b71b0d123a6 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -64,38 +64,38 @@ class Propagator static constexpr float MAX_STEP = 2.0f; GPUd() bool PropagateToXBxByBz(o2::track::TrackParCov& track, float x, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; GPUd() bool PropagateToXBxByBz(o2::track::TrackPar& track, float x, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; GPUd() bool propagateToX(o2::track::TrackParCov& track, float x, float bZ, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; GPUd() bool propagateToX(o2::track::TrackPar& track, float x, float bZ, - float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxSnp = MAX_SIN_PHI, float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0) const; GPUd() bool propagateToDCA(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, float bZ, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; GPUd() bool propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, o2::track::TrackParCov& track, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, o2::dataformats::DCA* dcaInfo = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; GPUd() bool propagateToDCA(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, float bZ, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, gpu::gpustd::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; GPUd() bool propagateToDCABxByBz(const o2::math_utils::Point3D<float>& vtx, o2::track::TrackPar& track, - float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrTGeo, + float maxStep = MAX_STEP, MatCorrType matCorr = MatCorrType::USEMatCorrLUT, gpu::gpustd::array<float, 2>* dca = nullptr, o2::track::TrackLTIntegral* tofInfo = nullptr, int signCorr = 0, float maxD = 999.f) const; diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 2e26615b1c9e2..951f014052b80 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -516,7 +516,7 @@ GPUd() bool Propagator::propagateToDCABxByBz(const math_utils::Point3D<float>& v GPUd() MatBudget Propagator::getMatBudget(Propagator::MatCorrType corrType, const math_utils::Point3D<float>& p0, const math_utils::Point3D<float>& p1) const { #if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE) - if (corrType == MatCorrType::USEMatCorrTGeo) { + if (corrType == MatCorrType::USEMatCorrTGeo || !mMatLUT) { return GeometryManager::meanMaterialBudget(p0, p1); } #endif From 7ed4626d08b997f7ac0c0f57a90990be96924ff1 Mon Sep 17 00:00:00 2001 From: Raymond Ehlers <raymond.ehlers@gmail.com> Date: Tue, 5 Jan 2021 00:41:45 -0800 Subject: [PATCH 1685/1751] Initial version of EMCAL Correction Task (#5074) --- .../include/AnalysisDataModel/EMCALClusters.h | 36 ++++ Analysis/Tasks/CMakeLists.txt | 5 + Analysis/Tasks/emcalCorrectionTask.cxx | 198 ++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h create mode 100644 Analysis/Tasks/emcalCorrectionTask.cxx diff --git a/Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h b/Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h new file mode 100644 index 0000000000000..a75ad1f8ca00b --- /dev/null +++ b/Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h @@ -0,0 +1,36 @@ +// 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. + +// Table definitions for EMCAL analysis clusters +// +// Author: Raymond Ehlers + +#pragma once + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace emcalcluster +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(M02, m02, float); +} // namespace emcalcluster + +DECLARE_SOA_TABLE(EMCALClusters, "AOD", "EMCALCLUSTERS", + o2::soa::Index<>, emcalcluster::CollisionId, emcalcluster::Energy, + emcalcluster::Eta, emcalcluster::Phi, emcalcluster::M02); + +using EMCALCluster = EMCALClusters::iterator; + +} // namespace o2::aod diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 662a3090d1ec0..3381c8457c3ef 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -87,3 +87,8 @@ o2_add_dpl_workflow(weak-decay-indices SOURCES weakDecayIndices.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(emcal-correction-task + SOURCES emcalCorrectionTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsBase O2::EMCALBase O2::EMCALReconstruction + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/emcalCorrectionTask.cxx b/Analysis/Tasks/emcalCorrectionTask.cxx new file mode 100644 index 0000000000000..dfba6072ae069 --- /dev/null +++ b/Analysis/Tasks/emcalCorrectionTask.cxx @@ -0,0 +1,198 @@ +// 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. + +// EMCAL Correction Task +// +// Author: Raymond Ehlers + +#include <cmath> + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" + +#include "DetectorsBase/GeometryManager.h" + +#include "AnalysisDataModel/EMCALClusters.h" + +#include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/Constants.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "EMCALBase/Geometry.h" +#include "EMCALBase/ClusterFactory.h" +#include "EMCALReconstruction/Clusterizer.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct EmcalCorrectionTask { + Produces<o2::aod::EMCALClusters> clusters; + + // Options for the clusterization + // 1 corresponds to EMCAL cells based on the Run2 definition. + Configurable<int> selectedCellType{"selectedCellType", 1, "EMCAL Cell type"}; + Configurable<double> seedEnergy{"seedEnergy", 0.1, "Clusterizer seed energy."}; + Configurable<double> minCellEnergy{"minCellEnergy", 0.05, "Clusterizer minimum cell energy."}; + // TODO: Check this range, especially after change to the conversion... + Configurable<double> timeCut{"timeCut", 10000, "Cell time cut"}; + Configurable<double> timeMin{"timeMin", 0, "Min cell time"}; + Configurable<double> timeMax{"timeMax", 10000, "Max cell time"}; + Configurable<bool> enableEnergyGradientCut{"enableEnergyGradientCut", true, "Enable energy gradient cut."}; + Configurable<double> gradientCut{"gradientCut", 0.03, "Clusterizer energy gradient cut."}; + + // Clusterizer and related + // Apparently streaming these objects really doesn't work, and causes problems for setting up the workflow. + // So we use unique_ptr and define them below. + std::unique_ptr<o2::emcal::Clusterizer<o2::emcal::Cell>> mClusterizer; + std::unique_ptr<o2::emcal::ClusterFactory<o2::emcal::Cell>> mClusterFactory; + // Cells and clusters + std::vector<o2::emcal::Cell> mEmcalCells; + std::vector<o2::emcal::AnalysisCluster> mAnalysisClusters; + + // QA + // NOTE: This is not comprehensive. + OutputObj<TH1F> hCellE{"hCellE"}; + OutputObj<TH1I> hCellTowerID{"hCellTowerID"}; + OutputObj<TH2F> hCellEtaPhi{"hCellEtaPhi"}; + OutputObj<TH2I> hCellRowCol{"hCellRowCol"}; + OutputObj<TH1F> hClusterE{"hClusterE"}; + OutputObj<TH2F> hClusterEtaPhi{"hClusterEtaPhi"}; + + void init(InitContext const&) + { + LOG(DEBUG) << "Start init!"; + // NOTE: The geometry manager isn't necessary just to load the EMCAL geometry. + // However, it _is_ necessary for loading the misalignment matrices as of September 2020 + // Eventually, those matrices will be moved to the CCDB, but it's not yet ready. + // FIXME: Hardcoded for run 2 + o2::base::GeometryManager::loadGeometry(); // for generating full clusters + LOG(DEBUG) << "After load geometry!"; + o2::emcal::Geometry* geometry = o2::emcal::Geometry::GetInstanceFromRunNumber(223409); + if (!geometry) { + LOG(ERROR) << "Failure accessing geometry"; + } + + // Setup clusterizer + LOG(DEBUG) << "Init clusterizer!"; + mClusterizer = decltype(mClusterizer)(new o2::emcal::Clusterizer<o2::emcal::Cell>()); + mClusterizer->initialize(timeCut, timeMin, timeMax, gradientCut, enableEnergyGradientCut, seedEnergy, minCellEnergy); + mClusterizer->setGeometry(geometry); + LOG(DEBUG) << "Done with clusterizer. Setup cluster factory."; + // Setup cluster factory. + mClusterFactory = decltype(mClusterFactory)(new o2::emcal::ClusterFactory<o2::emcal::Cell>()); + LOG(DEBUG) << "Completed init!"; + + // Setup QA hists. + hCellE.setObject(new TH1F("hCellE", "hCellE", 200, 0.0, 100)); + hCellTowerID.setObject(new TH1I("hCellTowerID", "hCellTowerID", 20000, 0, 20000)); + hCellEtaPhi.setObject(new TH2F("hCellEtaPhi", "hCellEtaPhi", 160, -0.8, 0.8, 72, 0, 2 * 3.14159)); + // NOTE: Reversed column and row because it's more natural for presentatin. + hCellRowCol.setObject(new TH2I("hCellRowCol", "hCellRowCol;Column;Row", 97, 0, 97, 600, 0, 600)); + hClusterE.setObject(new TH1F("hClusterE", "hClusterE", 200, 0.0, 100)); + hClusterEtaPhi.setObject(new TH2F("hClusterEtaPhi", "hClusterEtaPhi", 160, -0.8, 0.8, 72, 0, 2 * 3.14159)); + } + + //void process(aod::Collision const& collision, soa::Filtered<aod::Tracks> const& fullTracks, aod::Calos const& cells) + //void process(aod::Collision const& collision, aod::Tracks const& tracks, aod::Calos const& cells) + //void process(aod::BCs const& bcs, aod::Collision const& collision, aod::Calos const& cells) + // Appears to need the BC to be accessed to be available in the collision table... + void process(aod::Collision const& collision, aod::Calos const& cells, aod::BCs const& bcs) + { + LOG(DEBUG) << "Starting process."; + // Convert aod::Calo to o2::emcal::Cell which can be used with the clusterizer. + // In particular, we need to filter only EMCAL cells. + mEmcalCells.clear(); + for (auto& cell : cells) { + if (cell.caloType() != selectedCellType || cell.bc() != collision.bc()) { + //LOG(DEBUG) << "Rejected"; + continue; + } + //LOG(DEBUG) << "Cell E: " << cell.getEnergy(); + //LOG(DEBUG) << "Cell E: " << cell; + + mEmcalCells.emplace_back(o2::emcal::Cell( + cell.cellNumber(), + cell.amplitude(), + cell.time(), + o2::emcal::intToChannelType(cell.cellType()))); + } + + // Cell QA + // For convenience, use the clusterizer stored geometry to get the eta-phi + for (auto& cell : mEmcalCells) { + hCellE->Fill(cell.getEnergy()); + hCellTowerID->Fill(cell.getTower()); + auto res = mClusterizer->getGeometry()->EtaPhiFromIndex(cell.getTower()); + hCellEtaPhi->Fill(std::get<0>(res), std::get<1>(res)); + res = mClusterizer->getGeometry()->GlobalRowColFromIndex(cell.getTower()); + // NOTE: Reversed column and row because it's more natural for presentatin. + hCellRowCol->Fill(std::get<1>(res), std::get<0>(res)); + } + + // TODO: Helpful for now, but should be removed. + LOG(DEBUG) << "Converted EMCAL cells"; + for (auto& cell : mEmcalCells) { + LOG(DEBUG) << cell.getTower() << ": E: " << cell.getEnergy() << ", time: " << cell.getTimeStamp() << ", type: " << cell.getType(); + } + + LOG(INFO) << "Converted cells. Contains: " << mEmcalCells.size() << ". Originally " << cells.size() << ". About to run clusterizer."; + + // Run the clusterizer + mClusterizer->findClusters(mEmcalCells); + LOG(DEBUG) << "Found clusters."; + auto emcalClusters = mClusterizer->getFoundClusters(); + auto emcalClustersInputIndices = mClusterizer->getFoundClustersInputIndices(); + LOG(DEBUG) << "Retrieved results. About to setup cluster factory."; + + // Convert to analysis clusters. + // First, the cluster factory requires cluster and cell information in order to build the clusters. + mAnalysisClusters.clear(); + mClusterFactory->reset(); + mClusterFactory->setClustersContainer(*emcalClusters); + mClusterFactory->setCellsContainer(mEmcalCells); + mClusterFactory->setCellsIndicesContainer(*emcalClustersInputIndices); + LOG(DEBUG) << "Cluster factory set up."; + + // Convert to analysis clusters. + for (int icl = 0; icl < mClusterFactory->getNumberOfClusters(); icl++) { + auto analysisCluster = mClusterFactory->buildCluster(icl); + mAnalysisClusters.emplace_back(analysisCluster); + } + LOG(DEBUG) << "Converted to analysis clusters."; + + // Store the clusters in the table + clusters.reserve(mAnalysisClusters.size()); + for (const auto& cluster : mAnalysisClusters) { + // Determine the cluster eta, phi, correcting for the vertex position. + auto pos = cluster.getGlobalPosition(); + pos = pos - math_utils::Point3D<float>{collision.posX(), collision.posY(), collision.posZ()}; + // Normalize the vector and rescale by energy. + pos /= (cluster.E() / std::sqrt(pos.Mag2())); + + // We have our necessary properties. Now we store outputs + //LOG(DEBUG) << "Cluster E: " << cluster.E(); + clusters(collision, cluster.E(), pos.Eta(), pos.Phi(), cluster.getM02()); + //if (cluster.E() < 0.300) { + // continue; + //} + hClusterE->Fill(cluster.E()); + hClusterEtaPhi->Fill(pos.Eta(), pos.Phi()); + } + LOG(DEBUG) << "Done with process."; + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask<EmcalCorrectionTask>("emcal-correction-task")}; +} From 43e8fdfe0eaf474619cfa57420718323ef1a4647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Tue, 5 Jan 2021 10:00:05 +0100 Subject: [PATCH 1686/1751] Convert collision time to ps (#5026) --- .../DataModel/include/AnalysisDataModel/PID/PIDTOF.h | 10 +++++----- Analysis/Tasks/pidTOF.cxx | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h index a5369f6ede8b3..5b1d43848c9d3 100644 --- a/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h @@ -41,17 +41,17 @@ class Beta Beta() = default; ~Beta() = default; - /// Computes the beta of a track given a length, a time measurement and an event time + /// Computes the beta of a track given a length, a time measurement and an event time (in ps) static float GetBeta(const float length, const float tofSignal, const float collisionTime); /// Gets the beta for the track of interest - float GetBeta(const Coll& col, const Trck& trk) const { return GetBeta(trk.length(), trk.tofSignal(), col.collisionTime()); } + float GetBeta(const Coll& col, const Trck& trk) const { return GetBeta(trk.length(), trk.tofSignal(), col.collisionTime() * 1000.f); } /// Computes the expected uncertainty on the beta measurement static float GetExpectedSigma(const float& length, const float& tofSignal, const float& collisionTime, const float& time_reso); /// Gets the expected uncertainty on the beta measurement of the track of interest - float GetExpectedSigma(const Coll& col, const Trck& trk) const { return GetExpectedSigma(trk.length(), trk.tofSignal(), col.collisionTime(), mExpectedResolution); } + float GetExpectedSigma(const Coll& col, const Trck& trk) const { return GetExpectedSigma(trk.length(), trk.tofSignal(), col.collisionTime() * 1000.f, mExpectedResolution); } /// Gets the expected beta for a given mass hypothesis (no energy loss taken into account) static float GetExpectedSignal(const float& mom, const float& mass); @@ -113,7 +113,7 @@ class ExpTimes float GetExpectedSigma(const DetectorResponse& response, const Coll& col, const Trck& trk) const; /// Gets the number of sigmas with respect the expected time - float GetSeparation(const DetectorResponse& response, const Coll& col, const Trck& trk) const { return (trk.tofSignal() - col.collisionTime() - GetExpectedSignal(col, trk)) / GetExpectedSigma(response, col, trk); } + float GetSeparation(const DetectorResponse& response, const Coll& col, const Trck& trk) const { return (trk.tofSignal() - col.collisionTime() * 1000.f - GetExpectedSignal(col, trk)) / GetExpectedSigma(response, col, trk); } }; //_________________________________________________________________________ @@ -131,7 +131,7 @@ float ExpTimes<Coll, Trck, id>::GetExpectedSigma(const DetectorResponse& respons if (trk.tofSignal() <= 0) { return -999.f; } - const float x[4] = {trk.p(), trk.tofSignal(), col.collisionTimeRes(), o2::track::PID::getMass2Z(id)}; + const float x[4] = {trk.p(), trk.tofSignal(), col.collisionTimeRes() * 1000.f, o2::track::PID::getMass2Z(id)}; return response(response.kSigma, x); // return response(response.kSigma, const Coll& col, const Trck& trk, id); } diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index 01b7c3654962f..dfd01389fb2a7 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -220,15 +220,16 @@ struct pidTOFTaskQA { void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) { + const float collisionTime_ps = collision.collisionTime() * 1000.f; histos.fill(HIST("event/vertexz"), collision.posZ()); - histos.fill(HIST("event/colltime"), collision.collisionTime()); + histos.fill(HIST("event/colltime"), collisionTime_ps); for (auto t : tracks) { // if (t.tofSignal() < 0) { // Skipping tracks without TOF continue; } - const float tof = t.tofSignal() - collision.collisionTime(); + const float tof = t.tofSignal() - collisionTime_ps; // histos.fill(HIST("event/tofsignal"), t.p(), t.tofSignal()); histos.fill(HIST("event/tofbeta"), t.p(), t.beta()); From 6486cf7853a8fae89c399ff1630aa7c230467f58 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 4 Jan 2021 18:40:27 +0100 Subject: [PATCH 1687/1751] GPU: Bugfix, shadow calibObject pointers were not initialized correctly --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 55e26c31d8133..6dc2068dc50af 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -388,6 +388,7 @@ int GPUChainTracking::Init() } #endif TransferMemoryResourceLinkToGPU(RecoStep::NoRecoStep, mFlatObjectsShadow.mMemoryResFlat); + memcpy((void*)&processorsShadow()->calibObjects, (void*)&mFlatObjectsDevice.mCalibObjects, sizeof(mFlatObjectsDevice.mCalibObjects)); WriteToConstantMemory(RecoStep::NoRecoStep, (char*)&processors()->calibObjects - (char*)processors(), &mFlatObjectsDevice.mCalibObjects, sizeof(mFlatObjectsDevice.mCalibObjects), -1); // First initialization, for users not using RunChain processorsShadow()->errorCodes.setMemory(mInputsShadow->mErrorCodes); WriteToConstantMemory(RecoStep::NoRecoStep, (char*)&processors()->errorCodes - (char*)processors(), &processorsShadow()->errorCodes, sizeof(processorsShadow()->errorCodes), -1); From 8bb935c1bdbaa116057e0995909ca4fae9b3a178 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sun, 27 Dec 2020 13:05:14 +0100 Subject: [PATCH 1688/1751] GPU: Make the tpc refit runable on the GPU --- .../Base/include/DetectorsBase/Propagator.h | 1 + Detectors/Base/src/Propagator.cxx | 5 +- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 15 ++-- GPU/Common/GPUDefGPUParameters.h | 6 ++ GPU/GPUTracking/Base/GPUConstantMem.h | 2 + GPU/GPUTracking/Base/GPUDataTypes.h | 4 +- GPU/GPUTracking/Base/GPUO2DataTypes.h | 1 + GPU/GPUTracking/Base/GPUO2FakeClasses.h | 3 + GPU/GPUTracking/Base/GPUParam.cxx | 21 ++++++ GPU/GPUTracking/Base/GPUParam.h | 9 +++ GPU/GPUTracking/Base/GPUReconstructionCPU.h | 1 + .../Base/GPUReconstructionIncludesDevice.h | 4 ++ .../Base/GPUReconstructionKernels.h | 27 +++---- GPU/GPUTracking/Base/GPUSettingsList.h | 1 + GPU/GPUTracking/CMakeLists.txt | 3 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 57 +++++++++++---- GPU/GPUTracking/Global/GPUChainTracking.h | 3 + GPU/GPUTracking/Interface/GPUO2Interface.cxx | 1 + GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 70 ++++++++++--------- GPU/GPUTracking/Refit/GPUTrackingRefit.h | 8 +-- .../Refit/GPUTrackingRefitKernel.cxx | 41 +++++++++++ .../Refit/GPUTrackingRefitKernel.h | 39 +++++++++++ GPU/GPUTracking/Standalone/standalone.cxx | 10 +++ 23 files changed, 261 insertions(+), 71 deletions(-) create mode 100644 GPU/GPUTracking/Refit/GPUTrackingRefitKernel.cxx create mode 100644 GPU/GPUTracking/Refit/GPUTrackingRefitKernel.h diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index c9b71b0d123a6..72fa4032847b6 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -111,6 +111,7 @@ class Propagator GPUd() const o2::base::MatLayerCylSet* getMatLUT() const { return mMatLUT; } GPUd() void setGPUField(const o2::gpu::GPUTPCGMPolynomialField* field) { mGPUField = field; } GPUd() const o2::gpu::GPUTPCGMPolynomialField* getGPUField() const { return mGPUField; } + GPUd() void setBz(float bz) { mBz = bz; } #ifndef GPUCA_GPUCODE static Propagator* Instance() diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 951f014052b80..098d3bc440376 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -98,7 +98,10 @@ int Propagator::initFieldFromGRP(const o2::parameters::GRPObject* grp, bool verb } return 0; } - +#elif !defined(GPUCA_GPUCODE) +Propagator::Propagator() +{ +} // empty dummy constructor for standalone benchmark #endif //_______________________________________________________________________ diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 297b436e4c2d3..86833d421a0a8 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -39,6 +39,9 @@ #include "TPCdEdxCalibrationSplines.h" #include "DPLUtils/DPLRawParser.h" #include "DetectorsBase/MatLayerCylSet.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsCommonDataFormats/NameConf.h" #include "DetectorsRaw/HBFUtils.h" #include "TPCBase/RDHUtils.h" #include "GPUO2InterfaceConfiguration.h" @@ -127,7 +130,9 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config tracker = std::make_unique<GPUCATracking>(); // Create configuration object and fill settings - const auto grp = o2::parameters::GRPObject::loadFrom("o2sim_grp.root"); + const auto grp = o2::parameters::GRPObject::loadFrom(o2::base::NameConf::getGRPFileName()); + o2::base::GeometryManager::loadGeometry(); + o2::base::Propagator::initFieldFromGRP(o2::base::NameConf::getGRPFileName()); if (grp) { config.configEvent.solenoidBz = 5.00668f * grp->getL3Current() / 30000.; config.configEvent.continuousMaxTimeBin = grp->isDetContinuousReadOut(o2::detectors::DetID::TPC) ? -1 : 0; // Number of timebins in timeframe if continuous, 0 otherwise @@ -216,15 +221,16 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config if (config.configCalib.fastTransform == nullptr) { throw std::invalid_argument("GPUCATracking: initialization of the TPC transformation failed"); } + if (confParam.matLUTFile.size()) { config.configCalib.matLUT = o2::base::MatLayerCylSet::loadFromFile(confParam.matLUTFile.c_str(), "MatBud"); } + if (confParam.dEdxFile.size()) { processAttributes->dEdxSplines.reset(new TPCdEdxCalibrationSplines(confParam.dEdxFile.c_str())); } else { processAttributes->dEdxSplines.reset(new TPCdEdxCalibrationSplines); } - config.configCalib.dEdxSplines = processAttributes->dEdxSplines.get(); if (boost::filesystem::exists(confParam.gainCalibFile)) { @@ -239,9 +245,10 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config } config.configCalib.tpcPadGain = processAttributes->tpcPadGainCalib.get(); + config.configCalib.o2Propagator = Propagator::Instance(); + // Sample code what needs to be done for the TRD Geometry, when we extend this to TRD tracking. - /*o2::base::GeometryManager::loadGeometry(); - o2::trd::Geometry gm; + /* o2::trd::Geometry gm; gm.createPadPlaneArray(); gm.createClusterMatrixArray(); std::unique_ptr<o2::trd::GeometryFlat> gf(gm); diff --git a/GPU/Common/GPUDefGPUParameters.h b/GPU/Common/GPUDefGPUParameters.h index 43c19f42fa2e2..19ca5e8df42ba 100644 --- a/GPU/Common/GPUDefGPUParameters.h +++ b/GPU/Common/GPUDefGPUParameters.h @@ -345,6 +345,12 @@ #ifndef GPUCA_LB_GPUTPCStartHitsSorter #define GPUCA_LB_GPUTPCStartHitsSorter 256 #endif + #ifndef GPUCA_LB_GPUTrackingRefitKernel_mode0asGPU + #define GPUCA_LB_GPUTrackingRefitKernel_mode0asGPU 256 + #endif + #ifndef GPUCA_LB_GPUTrackingRefitKernel_mode1asTrackParCov + #define GPUCA_LB_GPUTrackingRefitKernel_mode1asTrackParCov 256 + #endif #define GPUCA_GET_THREAD_COUNT(...) GPUCA_M_FIRST(__VA_ARGS__) #else // The following defaults are needed to compile the host code diff --git a/GPU/GPUTracking/Base/GPUConstantMem.h b/GPU/GPUTracking/Base/GPUConstantMem.h index d498be62793b1..a216413b9d324 100644 --- a/GPU/GPUTracking/Base/GPUConstantMem.h +++ b/GPU/GPUTracking/Base/GPUConstantMem.h @@ -47,6 +47,7 @@ class GPUTRDTracker_t #include "GPUTPCCompression.h" #include "GPUITSFitter.h" #include "GPUTPCClusterFinder.h" +#include "GPUTrackingRefit.h" #else #include "GPUO2FakeClasses.h" #endif @@ -71,6 +72,7 @@ struct GPUConstantMem { GPUTRDTrackerGPU trdTracker; GPUTPCClusterFinder tpcClusterer[GPUCA_NSLICES]; GPUITSFitter itsFitter; + GPUTrackingRefitProcessor trackingRefit; GPUTrackingInOutPointers ioPtrs; GPUCalibObjectsConst calibObjects; GPUErrors errorCodes; diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index c948f43e8bbe0..6612f77ee229c 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -48,6 +48,7 @@ namespace o2 class MCCompLabel; namespace base { +class Propagator; class MatLayerCylSet; } // namespace base namespace trd @@ -136,7 +137,7 @@ class GPUDataTypes TPCRaw = 64 }; #ifdef GPUCA_NOCOMPAT_ALLOPENCL - static constexpr const char* const RECO_STEP_NAMES[] = {"TPC Transformation", "TPC Sector Tracking", "TPC Track Merging and Fit", "TPC Compression", "TRD Tracking", "ITS Tracking", "TPC dEdx Computation", "TPC Cluster Finding", "TPC Decompression"}; + static constexpr const char* const RECO_STEP_NAMES[] = {"TPC Transformation", "TPC Sector Tracking", "TPC Track Merging and Fit", "TPC Compression", "TRD Tracking", "ITS Tracking", "TPC dEdx Computation", "TPC Cluster Finding", "TPC Decompression", "Global Refit"}; static constexpr const char* const GENERAL_STEP_NAMES[] = {"Prepare", "QA"}; typedef bitfield<RecoStep, unsigned int> RecoStepField; typedef bitfield<InOutType, unsigned int> InOutTypeField; @@ -176,6 +177,7 @@ struct GPUCalibObjectsTemplate { typename S<o2::trd::GeometryFlat>::type* trdGeometry = nullptr; typename S<TPCdEdxCalibrationSplines>::type* dEdxSplines = nullptr; typename S<TPCPadGainCalib>::type* tpcPadGain = nullptr; + typename S<o2::base::Propagator>::type* o2Propagator = nullptr; }; typedef GPUCalibObjectsTemplate<DefaultPtr> GPUCalibObjects; typedef GPUCalibObjectsTemplate<ConstPtr> GPUCalibObjectsConst; diff --git a/GPU/GPUTracking/Base/GPUO2DataTypes.h b/GPU/GPUTracking/Base/GPUO2DataTypes.h index 40d814e6a764d..66a53883cb8fc 100644 --- a/GPU/GPUTracking/Base/GPUO2DataTypes.h +++ b/GPU/GPUTracking/Base/GPUO2DataTypes.h @@ -20,6 +20,7 @@ #include "DataFormatsTPC/ClusterNative.h" #include "DataFormatsTPC/Digit.h" #include "DetectorsBase/MatLayerCylSet.h" +#include "DetectorsBase/Propagator.h" #include "TRDBase/GeometryFlat.h" #else #include "GPUO2FakeClasses.h" diff --git a/GPU/GPUTracking/Base/GPUO2FakeClasses.h b/GPU/GPUTracking/Base/GPUO2FakeClasses.h index 68c592366fd76..5449549c2a25e 100644 --- a/GPU/GPUTracking/Base/GPUO2FakeClasses.h +++ b/GPU/GPUTracking/Base/GPUO2FakeClasses.h @@ -102,6 +102,9 @@ class GPUTPCCompression class GPUTPCClusterFinder { }; +class GPUTrackingRefitProcessor +{ +}; struct GPUTPCCFChainContext { }; #ifndef __OPENCL__ diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index a338bc8202a6b..c8292f65fcfe8 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -27,6 +27,9 @@ using namespace GPUCA_NAMESPACE::gpu; #endif #include <cstring> #include <tuple> +#ifdef HAVE_O2HEADERS +#include "DetectorsBase/Propagator.h" +#endif #include "utils/qconfigrtc.h" @@ -244,3 +247,21 @@ std::string GPUParamRTC::generateRTCCode(const GPUParam& param, bool useConstexp static_assert(alignof(GPUCA_NAMESPACE::gpu::GPUParam) == alignof(GPUCA_NAMESPACE::gpu::GPUSettingsRec)); static_assert(alignof(GPUCA_NAMESPACE::gpu::GPUParam) == alignof(GPUCA_NAMESPACE::gpu::GPUSettingsParam)); static_assert(sizeof(GPUCA_NAMESPACE::gpu::GPUParam) - sizeof(GPUCA_NAMESPACE::gpu::GPUParamRTC) == sizeof(GPUCA_NAMESPACE::gpu::GPUSettingsRec) + sizeof(GPUCA_NAMESPACE::gpu::GPUSettingsParam) - sizeof(GPUCA_NAMESPACE::gpu::gpu_rtc::GPUSettingsRec) - sizeof(GPUCA_NAMESPACE::gpu::gpu_rtc::GPUSettingsParam)); + +o2::base::Propagator* GPUParam::GetDefaultO2Propagator(bool useGPUField) const +{ + o2::base::Propagator* prop = nullptr; +#ifdef HAVE_O2HEADERS + if (useGPUField == false) { + throw std::runtime_error("o2 propagator withouzt gpu field unsupported"); + } + prop = o2::base::Propagator::Instance(); + if (useGPUField) { + prop->setGPUField(&polynomialField); + prop->setBz(polynomialField.GetNominalBz()); + } +#else + throw std::runtime_error("o2 propagator unsupported"); +#endif + return prop; +} diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index c1dc43d392e0b..031cc8b78eee6 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -21,6 +21,14 @@ #include "GPUTPCGeometry.h" #include "GPUTPCGMPolynomialField.h" +namespace o2 +{ +namespace base +{ +class Propagator; +} // namespace base +} // namespace o2 + namespace GPUCA_NAMESPACE { namespace gpu @@ -63,6 +71,7 @@ struct GPUParam : public internal::GPUParam_t<GPUSettingsRec, GPUSettingsParam> void SetDefaults(const GPUSettingsEvent* e, const GPUSettingsRec* r = nullptr, const GPUSettingsProcessing* p = nullptr, const GPURecoStepConfiguration* w = nullptr); void UpdateEventSettings(const GPUSettingsEvent* e, const GPUSettingsProcessing* p = nullptr); void LoadClusterErrors(bool Print = 0); + o2::base::Propagator* GetDefaultO2Propagator(bool useGPUField = false) const; #endif GPUd() float Alpha(int iSlice) const diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.h b/GPU/GPUTracking/Base/GPUReconstructionCPU.h index 8b0bc183d70a1..3b9866f361f0e 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.h +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.h @@ -39,6 +39,7 @@ #include "GPUTPCConvertKernel.h" #include "GPUTPCCompressionKernels.h" #include "GPUTPCClusterFinderKernels.h" +#include "GPUTrackingRefitKernel.h" #endif namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h index 6ae8c9119c467..f05f120c1b18b 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h @@ -97,6 +97,10 @@ using namespace GPUCA_NAMESPACE::gpu; // Files for ITS Track Fit #include "GPUITSFitterKernels.cxx" +// Files for Refit +#include "GPUTrackingRefit.cxx" +#include "GPUTrackingRefitKernel.cxx" + #if !defined(GPUCA_O2_LIB) && defined(__HIPCC__) && !defined(GPUCA_NO_ITS_TRAITS) && !defined(GPUCA_GPUCODE_GENRTC) #include "VertexerTraitsHIP.hip.cxx" #include "ContextHIP.hip.cxx" diff --git a/GPU/GPUTracking/Base/GPUReconstructionKernels.h b/GPU/GPUTracking/Base/GPUReconstructionKernels.h index 904b798debb6d..c300714ccf3a0 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionKernels.h +++ b/GPU/GPUTracking/Base/GPUReconstructionKernels.h @@ -69,25 +69,26 @@ GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered32 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered64 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, buffered128 ), (simple), (), ()) GPUCA_KRNL_LB((GPUTPCCompressionGatherKernels, multiBlock ), (simple), (), ()) - GPUCA_KRNL_LB((GPUTPCCFCheckPadBaseline ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillIndexMap ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillFromDigits ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, findFragmentStart ), (single), (, char setPositions), (, setPositions)) +GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillIndexMap ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, fillFromDigits ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFChargeMapFiller, findFragmentStart ), (single), (, char setPositions), (, setPositions)) GPUCA_KRNL_LB((GPUTPCCFPeakFinder ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, noiseSuppression ), (single), (), ()) -GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, updatePeaks ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, noiseSuppression ), (single), (), ()) +GPUCA_KRNL_LB((GPUTPCCFNoiseSuppression, updatePeaks ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFDeconvolution ), (single), (), ()) GPUCA_KRNL_LB((GPUTPCCFClusterizer ), (single), (, char onlyMC), (, onlyMC)) -GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, setRowOffsets ), (single), (), ()) -GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, flatten ), (single), (, GPUPtr1(GPUTPCLinearLabels*, out)), (, GPUPtr2(GPUTPCLinearLabels*, out))) -GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanStart ), (single), (, int iBuf, int stage), (, iBuf, stage)) -GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanUp ), (single), (, int iBuf, int nElems), (, iBuf, nElems)) -GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanTop ), (single), (, int iBuf, int nElems), (, iBuf, nElems)) -GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanDown ), (single), (, int iBuf, unsigned int offset, int nElems), (, iBuf, offset, nElems)) -GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, compactDigits ), (single), (, int iBuf, int stage, GPUPtr1(ChargePos*, in), GPUPtr1(ChargePos*, out)), (, iBuf, stage, GPUPtr2(ChargePos*, in), GPUPtr2(ChargePos*, out))) +GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, setRowOffsets ), (single), (), ()) +GPUCA_KRNL(( GPUTPCCFMCLabelFlattener, flatten ), (single), (, GPUPtr1(GPUTPCLinearLabels*, out)), (, GPUPtr2(GPUTPCLinearLabels*, out))) +GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanStart ), (single), (, int iBuf, int stage), (, iBuf, stage)) +GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanUp ), (single), (, int iBuf, int nElems), (, iBuf, nElems)) +GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanTop ), (single), (, int iBuf, int nElems), (, iBuf, nElems)) +GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, scanDown ), (single), (, int iBuf, unsigned int offset, int nElems), (, iBuf, offset, nElems)) +GPUCA_KRNL_LB((GPUTPCCFStreamCompaction, compactDigits ), (single), (, int iBuf, int stage, GPUPtr1(ChargePos*, in), GPUPtr1(ChargePos*, out)), (, iBuf, stage, GPUPtr2(ChargePos*, in), GPUPtr2(ChargePos*, out))) GPUCA_KRNL_LB((GPUTPCCFDecodeZS ), (single), (, int firstHBF), (, firstHBF)) GPUCA_KRNL_LB((GPUTPCCFGather ), (single), (, GPUPtr1(o2::tpc::ClusterNative*, dest)), (, GPUPtr2(o2::tpc::ClusterNative*, dest))) +GPUCA_KRNL_LB((GPUTrackingRefitKernel, mode0asGPU ), (simple), (), ()) +GPUCA_KRNL_LB((GPUTrackingRefitKernel, mode1asTrackParCov ), (simple), (), ()) #endif #endif // clang-format on diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 6b385d6d97c56..146996d50a245 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -85,6 +85,7 @@ AddOptionRTC(loopInterpolationInExtraPass, char, -1, "", 0, "Perform loop interp AddOptionRTC(mergerReadFromTrackerDirectly, char, 1, "", 0, "Forward data directly from tracker to merger on GPU") AddOptionRTC(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") AddOptionRTC(trdStopTrkAfterNMissLy, unsigned char, 6, "", 0, "Abandon track following after N layers without a TRD match") +AddOptionRTC(trackingRefitGPUModel, char, 1, "", 0, "Use GPU track model for the Global Track Refit") AddCustomCPP(void SetMinTrackPt(float v) { MaxTrackQPt = v > 0.001 ? (1. / v) : (1. / 0.001); }) AddVariable(dummyRTC, float, 0.f) // Ensure non empty struct and proper alignment even if all normal members are constexpr AddHelp("help", 'h') diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 434cff83d29ba..7f340f56467e2 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -175,7 +175,8 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) TPCClusterFinder/GPUTPCCFGather.cxx TPCClusterFinder/TPCPadGainCalib.cxx dEdx/TPCdEdxCalibrationSplines.cxx - Refit/GPUTrackingRefit.cxx) + Refit/GPUTrackingRefit.cxx + Refit/GPUTrackingRefitKernel.cxx) set(SRCS_NO_H ${SRCS_NO_H} TPCClusterFinder/GPUTPCClusterFinderDump.cxx) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 6dc2068dc50af..863bc98e878b2 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -125,6 +125,9 @@ void GPUChainTracking::RegisterPermanentMemoryAndProcessors() mRec->RegisterGPUProcessor(&processors()->tpcClusterer[i], GetRecoStepsGPU() & RecoStep::TPCClusterFinding); } } + if (GetRecoSteps() & RecoStep::Refit) { + mRec->RegisterGPUProcessor(&processors()->trackingRefit, GetRecoStepsGPU() & RecoStep::Refit); + } #endif #ifdef GPUCA_KERNEL_DEBUGGER_OUTPUT mRec->RegisterGPUProcessor(&processors()->debugOutput, true); @@ -162,6 +165,9 @@ void GPUChainTracking::RegisterGPUProcessors() mRec->RegisterGPUDeviceProcessor(&processorsShadow()->tpcClusterer[i], &processors()->tpcClusterer[i]); } } + if (GetRecoStepsGPU() & RecoStep::Refit) { + mRec->RegisterGPUDeviceProcessor(&processorsShadow()->trackingRefit, &processors()->trackingRefit); + } #endif #ifdef GPUCA_KERNEL_DEBUGGER_OUTPUT mRec->RegisterGPUDeviceProcessor(&processorsShadow()->debugOutput, &processors()->debugOutput); @@ -259,6 +265,10 @@ bool GPUChainTracking::ValidateSteps() GPUError("Cannot run gain calibration without calibration object"); return false; } + if ((GetRecoSteps() & GPUDataTypes::RecoStep::Refit) && !param().rec.trackingRefitGPUModel && (processors()->calibObjects.o2Propagator == nullptr || processors()->calibObjects.matLUT == nullptr)) { + GPUError("Cannot run refit with o2 track model without o2 propagator"); + return false; + } return true; } @@ -386,6 +396,12 @@ int GPUChainTracking::Init() if (processors()->calibObjects.tpcPadGain) { memcpy((void*)mFlatObjectsShadow.mCalibObjects.tpcPadGain, (const void*)processors()->calibObjects.tpcPadGain, sizeof(*processors()->calibObjects.tpcPadGain)); } + if (processors()->calibObjects.o2Propagator) { + memcpy((void*)mFlatObjectsShadow.mCalibObjects.o2Propagator, (const void*)processors()->calibObjects.o2Propagator, sizeof(*processors()->calibObjects.o2Propagator)); + mFlatObjectsShadow.mCalibObjects.o2Propagator->setGPUField(&processorsDevice()->param.polynomialField); + mFlatObjectsShadow.mCalibObjects.o2Propagator->setBz(param().polynomialField.GetNominalBz()); + mFlatObjectsShadow.mCalibObjects.o2Propagator->setMatLUT(mFlatObjectsShadow.mCalibObjects.matLUT); + } #endif TransferMemoryResourceLinkToGPU(RecoStep::NoRecoStep, mFlatObjectsShadow.mMemoryResFlat); memcpy((void*)&processorsShadow()->calibObjects, (void*)&mFlatObjectsDevice.mCalibObjects, sizeof(mFlatObjectsDevice.mCalibObjects)); @@ -455,7 +471,9 @@ void* GPUChainTracking::GPUTrackingFlatObjects::SetPointersFlatObjects(void* mem if (mChainTracking->GetTRDGeometry()) { computePointerWithAlignment(mem, mCalibObjects.trdGeometry, 1); } - + if (mChainTracking->GetO2Propagator()) { + computePointerWithAlignment(mem, mCalibObjects.o2Propagator, 1); + } #endif return mem; } @@ -2394,22 +2412,24 @@ int GPUChainTracking::DoTRDGPUTracking() int GPUChainTracking::RunRefit() { #ifdef HAVE_O2HEADERS - GPUTrackingRefit re; - re.SetPtrsFromGPUConstantMem(processorsShadow()); - re.SetPropagatorDefault(); - for (unsigned int i = 0; i < mIOPtrs.nMergedTracks; i++) { - if (mIOPtrs.mergedTracks[i].OK()) { - printf("\nRefitting track %d\n", i); - GPUTPCGMMergedTrack t = mIOPtrs.mergedTracks[i]; - int retval = re.RefitTrackAsGPU(t, false, true); - printf("Refit error code: %d\n", retval); + bool doGPU = GetRecoStepsGPU() & RecoStep::Refit; + GPUTrackingRefitProcessor& Refit = processors()->trackingRefit; + GPUTrackingRefitProcessor& RefitShadow = doGPU ? processorsShadow()->trackingRefit : Refit; - printf("\nRefitting track TrackParCov %d\n", i); - t = mIOPtrs.mergedTracks[i]; - retval = re.RefitTrackAsTrackParCov(t, false, true); - printf("Refit error code: %d\n", retval); - } + const auto& threadContext = GetThreadContext(); + SetupGPUProcessor(&Refit, false); + RefitShadow.SetPtrsFromGPUConstantMem(processorsShadow(), doGPU ? &processorsDevice()->param : nullptr); + RefitShadow.SetPropagator(doGPU ? processorsShadow()->calibObjects.o2Propagator : GetO2Propagator()); + RefitShadow.mPTracks = (doGPU ? processorsShadow() : processors())->tpcMerger.OutputTracks(); + WriteToConstantMemory(RecoStep::Refit, (char*)&processors()->trackingRefit - (char*)processors(), &RefitShadow, sizeof(RefitShadow), 0); + //TransferMemoryResourcesToGPU(RecoStep::Refit, &Refit, 0); + if (param().rec.trackingRefitGPUModel) { + runKernel<GPUTrackingRefitKernel, GPUTrackingRefitKernel::mode0asGPU>(GetGrid(mIOPtrs.nMergedTracks, 0), krnlRunRangeNone); + } else { + runKernel<GPUTrackingRefitKernel, GPUTrackingRefitKernel::mode1asTrackParCov>(GetGrid(mIOPtrs.nMergedTracks, 0), krnlRunRangeNone); } + //TransferMemoryResourcesToHost(RecoStep::Refit, &Refit, 0); + SynchronizeStream(0); #endif return 0; } @@ -2658,3 +2678,10 @@ void GPUChainTracking::ClearErrorCodes() } TransferMemoryResourceLinkToGPU(RecoStep::NoRecoStep, mInputsHost->mResourceErrorCodes, 0); } + +void GPUChainTracking::SetDefaultO2PropagatorForGPU() +{ + o2::base::Propagator* prop = param().GetDefaultO2Propagator(true); + prop->setMatLUT(processors()->calibObjects.matLUT); + SetO2Propagator(prop); +} diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index 3d93cb85a080d..a757e3598934a 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -156,6 +156,7 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega const TPCdEdxCalibrationSplines* GetdEdxSplines() const { return processors()->calibObjects.dEdxSplines; } const o2::base::MatLayerCylSet* GetMatLUT() const { return processors()->calibObjects.matLUT; } const GPUTRDGeometry* GetTRDGeometry() const { return (GPUTRDGeometry*)processors()->calibObjects.trdGeometry; } + const o2::base::Propagator* GetO2Propagator() const { return processors()->calibObjects.o2Propagator; } void SetTPCFastTransform(std::unique_ptr<TPCFastTransform>&& tpcFastTransform); void SetdEdxSplines(std::unique_ptr<TPCdEdxCalibrationSplines>&& dEdxSplines); void SetMatLUT(std::unique_ptr<o2::base::MatLayerCylSet>&& lut); @@ -165,6 +166,8 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void SetdEdxSplines(const TPCdEdxCalibrationSplines* dEdxSplines) { processors()->calibObjects.dEdxSplines = dEdxSplines; } void SetMatLUT(const o2::base::MatLayerCylSet* lut) { processors()->calibObjects.matLUT = lut; } void SetTRDGeometry(const o2::trd::GeometryFlat* geo) { processors()->calibObjects.trdGeometry = geo; } + void SetO2Propagator(const o2::base::Propagator* prop) { processors()->calibObjects.o2Propagator = prop; } + void SetDefaultO2PropagatorForGPU(); void LoadClusterErrors(); void SetOutputControlCompressedClusters(GPUOutputControl* v) { mOutputCompressedClusters = v; } void SetOutputControlClustersNative(GPUOutputControl* v) { mOutputClustersNative = v; } diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index d5df395ed5d21..40ea66aa7157e 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -57,6 +57,7 @@ int GPUTPCO2Interface::Initialize(const GPUO2InterfaceConfiguration& config) mChain->SetdEdxSplines(mConfig->configCalib.dEdxSplines); mChain->SetMatLUT(mConfig->configCalib.matLUT); mChain->SetTRDGeometry(mConfig->configCalib.trdGeometry); + mChain->SetO2Propagator(mConfig->configCalib.o2Propagator); if (mConfig->configInterface.outputToExternalBuffers) { mOutputCompressedClusters.reset(new GPUOutputControl); mChain->SetOutputControlCompressedClusters(mOutputCompressedClusters.get()); diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 7d86bd11e0f04..ba9f9d735c965 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -24,14 +24,14 @@ #include "DetectorsBase/Propagator.h" #include "DataFormatsTPC/TrackTPC.h" #include "GPUParam.inc" +#include "GPUCommonArray.h" +#include "GPUParam.h" using namespace GPUCA_NAMESPACE::gpu; using namespace o2::track; using namespace o2::base; using namespace o2::tpc; -static constexpr float kDeg2Rad = M_PI / 180.f; -static constexpr float kSectAngle = 2 * M_PI / 18.f; static constexpr int kIGNORE_ENDS = 3; #define IgnoreErrors(SNP) \ @@ -45,6 +45,7 @@ static constexpr int kIGNORE_ENDS = 3; } // End IgnoreErrors +#ifndef GPUCA_GPUCODE void GPUTrackingRefitProcessor::InitializeProcessor() {} void GPUTrackingRefitProcessor::RegisterMemoryAllocation() @@ -55,6 +56,7 @@ void GPUTrackingRefitProcessor::RegisterMemoryAllocation() void GPUTrackingRefitProcessor::SetMaxData(const GPUTrackingInOutPointers& io) { } +#endif namespace { @@ -71,7 +73,7 @@ struct refitTrackTypes<TrackParCov> { } // anonymous namespace template <> -void GPUTrackingRefit::initProp<GPUTPCGMPropagator>(GPUTPCGMPropagator& prop) +GPUd() void GPUTrackingRefit::initProp<GPUTPCGMPropagator>(GPUTPCGMPropagator& prop) { prop.SetMaterialTPC(); prop.SetMaxSinPhi(GPUCA_MAX_SIN_PHI); @@ -83,17 +85,17 @@ void GPUTrackingRefit::initProp<GPUTPCGMPropagator>(GPUTPCGMPropagator& prop) } template <> -void GPUTrackingRefit::initProp<const Propagator*>(const Propagator*& prop) +GPUd() void GPUTrackingRefit::initProp<const Propagator*>(const Propagator*& prop) { prop = mPpropagator; } template <class T, class S, class U> -void GPUTrackingRefit::convertTrack(T& trk, const S& trkX, U& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack(T& trk, const S& trkX, U& prop, float* chi2) { trk = trkX; } -static void convertTrackParam(GPUTPCGMTrackParam& trk, const TrackParCov& trkX) +GPUd() static void convertTrackParam(GPUTPCGMTrackParam& trk, const TrackParCov& trkX) { for (int i = 0; i < 5; i++) { trk.Par()[i] = trkX.getParams()[i]; @@ -103,7 +105,7 @@ static void convertTrackParam(GPUTPCGMTrackParam& trk, const TrackParCov& trkX) } trk.X() = trkX.getX(); } -static void convertTrackParam(TrackParCov& trk, const GPUTPCGMTrackParam& trkX) +GPUd() static void convertTrackParam(TrackParCov& trk, const GPUTPCGMTrackParam& trkX) { for (int i = 0; i < 5; i++) { trk.setParam(trkX.GetPar()[i], i); @@ -115,20 +117,20 @@ static void convertTrackParam(TrackParCov& trk, const GPUTPCGMTrackParam& trkX) } // Generic template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackParCov& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackParCov& trkX, GPUTPCGMPropagator& prop, float* chi2) { convertTrackParam(trk, trkX); prop.SetTrack(&trk, trkX.getAlpha()); } template <> -void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackParCov& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackParCov& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { convertTrackParam(trk, trkX); trk.setAlpha(prop.GetAlpha()); } // GPUTPCGMMergedTrack input template <> -void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Propagator*>(TrackParCov& trk, const GPUTPCGMMergedTrack& trkX, const Propagator*& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Propagator*>(TrackParCov& trk, const GPUTPCGMMergedTrack& trkX, const Propagator*& prop, float* chi2) { initProp(prop); convertTrackParam(trk, trkX.GetParam()); @@ -136,62 +138,62 @@ void GPUTrackingRefit::convertTrack<TrackParCov, GPUTPCGMMergedTrack, const Prop *chi2 = trkX.GetParam().GetChi2(); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, TrackParCov, const Propagator*>(GPUTPCGMMergedTrack& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, TrackParCov, const Propagator*>(GPUTPCGMMergedTrack& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) { convertTrackParam(trk.Param(), trkX); trk.SetAlpha(trkX.getAlpha()); trk.Param().SetChi2(*chi2); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTPCGMMergedTrack, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTPCGMMergedTrack& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTPCGMMergedTrack, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTPCGMMergedTrack& trkX, GPUTPCGMPropagator& prop, float* chi2) { initProp(prop); trk = trkX.GetParam(); prop.SetTrack(&trk, trkX.GetAlpha()); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTPCGMMergedTrack& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTPCGMMergedTrack, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTPCGMMergedTrack& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { trk.SetParam(trkX); trk.SetAlpha(prop.GetAlpha()); } // TrackTPC input template <> -void GPUTrackingRefit::convertTrack<TrackParCov, TrackTPC, const Propagator*>(TrackParCov& trk, const TrackTPC& trkX, const Propagator*& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<TrackParCov, TrackTPC, const Propagator*>(TrackParCov& trk, const TrackTPC& trkX, const Propagator*& prop, float* chi2) { initProp(prop); convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop, nullptr); *chi2 = trkX.getChi2(); } template <> -void GPUTrackingRefit::convertTrack<TrackTPC, TrackParCov, const Propagator*>(TrackTPC& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<TrackTPC, TrackParCov, const Propagator*>(TrackTPC& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) { convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX, prop, nullptr); trk.setChi2(*chi2); } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackTPC, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackTPC& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, TrackTPC, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const TrackTPC& trkX, GPUTPCGMPropagator& prop, float* chi2) { initProp(prop); convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX, prop, nullptr); trk.SetChi2(trkX.getChi2()); } template <> -void GPUTrackingRefit::convertTrack<TrackTPC, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackTPC& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<TrackTPC, GPUTPCGMTrackParam, GPUTPCGMPropagator>(TrackTPC& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk, trkX, prop, nullptr); trk.setChi2(trkX.GetChi2()); } // TrackParCovWithArgs input template <> -void GPUTrackingRefit::convertTrack<TrackParCov, GPUTrackingRefit::TrackParCovWithArgs, const Propagator*>(TrackParCov& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, const Propagator*& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<TrackParCov, GPUTrackingRefit::TrackParCovWithArgs, const Propagator*>(TrackParCov& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, const Propagator*& prop, float* chi2) { initProp(prop); convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk, trkX.trk, prop, nullptr); *chi2 = trkX.chi2 ? *trkX.chi2 : 0.f; } template <> -void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, TrackParCov, const Propagator*>(GPUTrackingRefit::TrackParCovWithArgs& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, TrackParCov, const Propagator*>(GPUTrackingRefit::TrackParCovWithArgs& trk, const TrackParCov& trkX, const Propagator*& prop, float* chi2) { convertTrack<TrackParCov, TrackParCov, const Propagator*>(trk.trk, trkX, prop, nullptr); if (trk.chi2) { @@ -199,14 +201,14 @@ void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, Track } } template <> -void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTPCGMTrackParam, GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMPropagator>(GPUTPCGMTrackParam& trk, const GPUTrackingRefit::TrackParCovWithArgs& trkX, GPUTPCGMPropagator& prop, float* chi2) { initProp(prop); convertTrack<GPUTPCGMTrackParam, TrackParCov, GPUTPCGMPropagator>(trk, trkX.trk, prop, nullptr); trk.SetChi2(trkX.chi2 ? *trkX.chi2 : 0.f); } template <> -void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTrackingRefit::TrackParCovWithArgs& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) +GPUd() void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMTrackParam, GPUTPCGMPropagator>(GPUTrackingRefit::TrackParCovWithArgs& trk, const GPUTPCGMTrackParam& trkX, GPUTPCGMPropagator& prop, float* chi2) { convertTrack<TrackParCov, GPUTPCGMTrackParam, GPUTPCGMPropagator>(trk.trk, trkX, prop, chi2); if (trk.chi2) { @@ -214,12 +216,13 @@ void GPUTrackingRefit::convertTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTP } } -static const float* getPar(const GPUTPCGMTrackParam& trk) { return trk.GetPar(); } -static const float* getPar(const TrackParCov& trk) { return trk.getParams(); } +GPUd() static const float* getPar(const GPUTPCGMTrackParam& trk) { return trk.GetPar(); } +GPUd() static const float* getPar(const TrackParCov& trk) { return trk.getParams(); } template <class T, class S> GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) { +#ifndef __OPENCL__ CADEBUG(int ii; printf("\nRefitting track\n")); typename refitTrackTypes<S>::propagator prop; S trk; @@ -354,8 +357,8 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) TrackParCovChi2 = 0.f; } CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[0] - y, trk.getParams()[1] - z, sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); - std::array<float, 2> p = {y, z}; - std::array<float, 3> c = {0, 0, 0}; + gpu::gpustd::array<float, 2> p = {y, z}; + gpu::gpustd::array<float, 3> c = {0, 0, 0}; mPparam->GetClusterErrors2(currentRow, z, getPar(trk)[2], getPar(trk)[3], c[0], c[2]); mPparam->UpdateClusterError2ByState(clusterState, c[0], c[2]); TrackParCovChi2 += trk.getPredictedChi2(p, c); @@ -376,6 +379,8 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) trk.NormalizeAlpha(alpha); prop.SetAlpha(alpha); } else if constexpr (std::is_same<S, TrackParCov>::value) { + static constexpr float kDeg2Rad = M_PI / 180.f; + static constexpr float kSectAngle = 2 * M_PI / 18.f; if (mPparam->rec.TrackReferenceX <= 500) { if (prop->PropagateToXBxByBz(trk, mPparam->rec.TrackReferenceX)) { if (CAMath::Abs(trk.getY()) > trk.getX() * CAMath::Tan(kSectAngle / 2.f)) { @@ -391,6 +396,9 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) convertTrack(trkX, trk, prop, &TrackParCovChi2); return nFitted; +#else + return 0; // TODO: Fixme, implement std::isSame for opencl +#endif } template GPUd() int GPUTrackingRefit::RefitTrack<GPUTPCGMMergedTrack, TrackParCov>(GPUTPCGMMergedTrack& trk, bool outward, bool resetCov); @@ -400,20 +408,18 @@ template GPUd() int GPUTrackingRefit::RefitTrack<TrackTPC, GPUTPCGMTrackParam>(T template GPUd() int GPUTrackingRefit::RefitTrack<GPUTrackingRefit::TrackParCovWithArgs, TrackParCov>(GPUTrackingRefit::TrackParCovWithArgs& trk, bool outward, bool resetCov); template GPUd() int GPUTrackingRefit::RefitTrack<GPUTrackingRefit::TrackParCovWithArgs, GPUTPCGMTrackParam>(GPUTrackingRefit::TrackParCovWithArgs& trk, bool outward, bool resetCov); -void GPUTrackingRefit::SetPtrsFromGPUConstantMem(const GPUConstantMem* v) +#ifndef GPUCA_GPUCODE +void GPUTrackingRefit::SetPtrsFromGPUConstantMem(const GPUConstantMem* v, MEM_CONSTANT(GPUParam) * p) { mPclusterState = v->ioPtrs.mergedTrackHitStates; mPclusterNative = v->ioPtrs.clustersNative; mPtrackHits = v->ioPtrs.mergedTrackHits; mPfastTransform = v->calibObjects.fastTransform; - mPparam = &v->param; + mPparam = p ? p : &v->param; } void GPUTrackingRefit::SetPropagatorDefault() { -#ifndef GPUCA_STANDALONE - mPpropagator = Propagator::Instance(); -#else - throw std::runtime_error("unsupported"); -#endif + mPpropagator = mPparam->GetDefaultO2Propagator(false); } +#endif diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.h b/GPU/GPUTracking/Refit/GPUTrackingRefit.h index 7dbc710beeecc..72f3ab69adf3f 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.h +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.h @@ -16,7 +16,6 @@ #include "GPUDef.h" #include "GPUProcessor.h" -#include <tuple> namespace o2::dataformats { @@ -55,7 +54,7 @@ class GPUTrackingRefit { public: void SetClusterStateArray(const unsigned char* v) { mPclusterState = v; } - void SetPtrsFromGPUConstantMem(const GPUConstantMem* v); + void SetPtrsFromGPUConstantMem(const GPUConstantMem* v, MEM_CONSTANT(GPUParam) * p = nullptr); void SetPropagator(const o2::base::Propagator* v) { mPpropagator = v; } void SetPropagatorDefault(); void SetClusterNative(const o2::tpc::ClusterNativeAccess* v) { mPclusterNative = v; } @@ -98,9 +97,9 @@ class GPUTrackingRefit template <class T, class S> GPUd() int RefitTrack(T& trk, bool outward, bool resetCov); template <class T, class S, class U> - void convertTrack(T& trk, const S& trkX, U& prop, float* chi2); + GPUd() void convertTrack(T& trk, const S& trkX, U& prop, float* chi2); template <class U> - void initProp(U& prop); + GPUd() void initProp(U& prop); }; class GPUTrackingRefitProcessor : public GPUTrackingRefit, public GPUProcessor @@ -111,6 +110,7 @@ class GPUTrackingRefitProcessor : public GPUTrackingRefit, public GPUProcessor void RegisterMemoryAllocation(); void SetMaxData(const GPUTrackingInOutPointers& io); #endif + GPUTPCGMMergedTrack* mPTracks = nullptr; }; } // namespace o2::gpu diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefitKernel.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefitKernel.cxx new file mode 100644 index 0000000000000..de4f94aa586c3 --- /dev/null +++ b/GPU/GPUTracking/Refit/GPUTrackingRefitKernel.cxx @@ -0,0 +1,41 @@ +// 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 GPUTrackingRefitKernel.cxx +/// \author David Rohr + +#include "GPUTrackingRefitKernel.h" +#include "GPUTrackingRefit.h" + +using namespace GPUCA_NAMESPACE::gpu; + +template <int I> +GPUdii() void GPUTrackingRefitKernel::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors) +{ + auto& refit = processors.trackingRefit; + for (unsigned int i = get_global_id(0); i < processors.ioPtrs.nMergedTracks; i += get_global_size(0)) { + if (refit.mPTracks[i].OK()) { + GPUTPCGMMergedTrack trk = refit.mPTracks[i]; + int retval; + if constexpr (I == mode0asGPU) { + retval = refit.RefitTrackAsGPU(trk, false, true); + } else if constexpr (I == mode1asTrackParCov) { + retval = refit.RefitTrackAsTrackParCov(trk, false, true); + } + if (retval > 0) { + refit.mPTracks[i] = trk; + } else { + refit.mPTracks[i].SetOK(false); + } + } + } +} +template GPUd() void GPUTrackingRefitKernel::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); +template GPUd() void GPUTrackingRefitKernel::Thread<1>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefitKernel.h b/GPU/GPUTracking/Refit/GPUTrackingRefitKernel.h new file mode 100644 index 0000000000000..4b2e5fdc16b6c --- /dev/null +++ b/GPU/GPUTracking/Refit/GPUTrackingRefitKernel.h @@ -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 GPUTrackingRefitKernel.h +/// \author David Rohr + +#ifndef GPUTRACKINGREFITKERNEL_H +#define GPUTRACKINGREFITKERNEL_H + +#include "GPUGeneralKernels.h" +#include "GPUConstantMem.h" + +namespace o2::gpu +{ + +class GPUTrackingRefitKernel : public GPUKernelTemplate +{ + public: + GPUhdi() CONSTEXPR static GPUDataTypes::RecoStep GetRecoStep() { return GPUDataTypes::RecoStep::TPCCompression; } + + enum K : int { + mode0asGPU = 0, + mode1asTrackParCov = 1, + }; + + template <int iKernel = defaultKernel> + GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); +}; + +} // namespace o2::gpu + +#endif diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index d589ab09a803c..d859367c2490e 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -445,6 +445,16 @@ int SetupReconstruction() } } +#ifdef HAVE_O2HEADERS + chainTracking->SetDefaultO2PropagatorForGPU(); + if (configStandalone.testSyncAsync) { + chainTrackingAsync->SetDefaultO2PropagatorForGPU(); + } + if (configStandalone.proc.doublePipeline) { + chainTrackingPipeline->SetDefaultO2PropagatorForGPU(); + } +#endif + if (rec->Init()) { printf("Error initializing GPUReconstruction!\n"); return 1; From dfada64300effb9475ec28e36d19b2d901c413a8 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 4 Jan 2021 20:21:59 +0100 Subject: [PATCH 1689/1751] GPU: Simplify application of gain correction --- GPU/GPUTracking/Base/GPUConstantMem.h | 7 ------- GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx | 2 +- GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUConstantMem.h b/GPU/GPUTracking/Base/GPUConstantMem.h index a216413b9d324..8372eaa7a9582 100644 --- a/GPU/GPUTracking/Base/GPUConstantMem.h +++ b/GPU/GPUTracking/Base/GPUConstantMem.h @@ -135,13 +135,6 @@ GPUdi() void GPUProcessor::raiseError(unsigned int code, unsigned int param1, un GetConstantMem()->errorCodes.raiseError(code, param1, param2, param3); } -#if defined(GPUCA_NOCOMPAT_ALLCINT) && (!defined(GPUCA_GPULIBRARY) || !defined(GPUCA_ALIROOT_LIB)) && defined(HAVE_O2HEADERS) -GPUd() float GPUTPCClusterFinder::getGainCorrection(tpccf::Row row, tpccf::Pad pad) const -{ - return GetConstantMem()->calibObjects.tpcPadGain->getGainCorrection(mISlice, row, pad); -} -#endif - } // namespace gpu } // namespace GPUCA_NAMESPACE diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx index 1b17d0a8d0ffa..ae9d5ab3fda0c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx @@ -170,7 +170,7 @@ GPUdii() void GPUTPCCFDecodeZS::decode(GPUTPCClusterFinder& clusterer, GPUShared positions[nDigitsTmp++] = pos; if (inFragment) { float q = float(byte & mask) * decodeBitsFactor; - q *= clusterer.getGainCorrection(row, pad); + q *= clusterer.GetConstantMem()->calibObjects.tpcPadGain->getGainCorrection(slice, row, pad); chargeMap[pos] = PackedCharge(q); } pad++; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index 944c2be4de71c..d48f1e5d453c4 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -138,7 +138,6 @@ class GPUTPCClusterFinder : public GPUProcessor short mZSOffsetId = -1; short mOutputId = -1; - GPUdi() float getGainCorrection(tpccf::Row, tpccf::Pad) const; GPUdi() const GPUTPCGeometry* getGeometry() const; #ifndef GPUCA_GPUCODE From 02cf0845a5c17778183cbb7e26c67c207cc7860e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 4 Jan 2021 21:33:57 +0100 Subject: [PATCH 1690/1751] GPU: Enable matLut with GPU Track Model in Track Refit --- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 2 ++ GPU/GPUTracking/Refit/GPUTrackingRefit.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index ba9f9d735c965..809bc6929f16e 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -82,6 +82,7 @@ GPUd() void GPUTrackingRefit::initProp<GPUTPCGMPropagator>(GPUTPCGMPropagator& p prop.SetFitInProjections(mPparam->rec.fitInProjections != 0); prop.SetPropagateBzOnly(false); prop.SetPolynomialField(&mPparam->polynomialField); + prop.SetMatLUT(mPmatLUT); } template <> @@ -415,6 +416,7 @@ void GPUTrackingRefit::SetPtrsFromGPUConstantMem(const GPUConstantMem* v, MEM_CO mPclusterNative = v->ioPtrs.clustersNative; mPtrackHits = v->ioPtrs.mergedTrackHits; mPfastTransform = v->calibObjects.fastTransform; + mPmatLUT = v->calibObjects.matLUT; mPparam = p ? p : &v->param; } diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.h b/GPU/GPUTracking/Refit/GPUTrackingRefit.h index 72f3ab69adf3f..0a8970dabaf6c 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.h +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.h @@ -31,6 +31,7 @@ using TrackParCov = TrackParametrizationWithError<float>; namespace o2::base { class Propagator; +class MatLayerCylSet; } // namespace o2::base namespace o2::tpc { @@ -89,6 +90,7 @@ class GPUTrackingRefit private: const unsigned char* mPclusterState = nullptr; // Ptr to shared cluster state const o2::base::Propagator* mPpropagator = nullptr; // Ptr to propagator for TrackParCov track model + const o2::base::MatLayerCylSet* mPmatLUT = nullptr; // Ptr to material LUT const o2::tpc::ClusterNativeAccess* mPclusterNative = nullptr; // Ptr to cluster native access structure const GPUTPCGMMergedTrackHit* mPtrackHits = nullptr; // Ptr to hits for GPUTPCGMMergedTrack tracks const unsigned int* mPtrackHitReferences = nullptr; // Ptr to hits for TrackTPC tracks From a80dfaf8964ee47c645698833be4e5186ded8678 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Mon, 4 Jan 2021 20:53:50 +0100 Subject: [PATCH 1691/1751] GPU: Add option for the GPU backend to use nested OpenMP loops for better parallelism --- GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 13 ++++++++++++- GPU/GPUTracking/Base/GPUReconstructionCPU.h | 4 ++++ GPU/GPUTracking/Base/GPUSettingsList.h | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 6 ++++-- GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx | 2 +- 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index 4e1b6fc41a7fd..4b002d2c9e478 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -72,7 +72,8 @@ int GPUReconstructionCPUBackend::runKernelBackend(krnlSetup& _xyz, const Args&.. unsigned int num = y.num == 0 || y.num == -1 ? 1 : y.num; for (unsigned int k = 0; k < num; k++) { if (mProcessingSettings.ompKernels) { - GPUCA_OPENMP(parallel for num_threads(mProcessingSettings.ompThreads)) + int ompThreads = mProcessingSettings.ompKernels == 2 ? ((mProcessingSettings.ompThreads + mNestedLoopOmpFactor - 1) / mNestedLoopOmpFactor) : mProcessingSettings.ompThreads; + GPUCA_OPENMP(parallel for num_threads(ompThreads)) for (unsigned int iB = 0; iB < x.nBlocks; iB++) { typename T::GPUSharedMemory smem; T::template Thread<I>(x.nBlocks, 1, iB, 0, smem, T::Processor(*mHostConstantMem)[y.start + k], args...); @@ -344,3 +345,13 @@ unsigned int GPUReconstructionCPU::getNextTimerId() static std::atomic<unsigned int> id{0}; return id.fetch_add(1); } + +unsigned int GPUReconstructionCPU::SetAndGetNestedLoopOmpFactor(bool condition, unsigned int max) +{ + if (condition && mProcessingSettings.ompKernels != 1) { + mNestedLoopOmpFactor = mProcessingSettings.ompKernels == 2 ? std::max<unsigned int>(max, mProcessingSettings.ompThreads) : mProcessingSettings.ompThreads; + } else { + mNestedLoopOmpFactor = 1; + } + return mNestedLoopOmpFactor; +} diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.h b/GPU/GPUTracking/Base/GPUReconstructionCPU.h index 3b9866f361f0e..201c6d0f85ee2 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.h +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.h @@ -57,6 +57,7 @@ class GPUReconstructionCPUBackend : public GPUReconstruction int runKernelBackend(krnlSetup& _xyz, const Args&... args); template <class T, int I> krnlProperties getKernelPropertiesBackend(); + unsigned int mNestedLoopOmpFactor = 1; }; template <class T> @@ -148,6 +149,9 @@ class GPUReconstructionCPU : public GPUReconstructionKernels<GPUReconstructionCP HighResTimer& getRecoStepTimer(RecoStep step) { return mTimersRecoSteps[getRecoStepNum(step)].timerTotal; } HighResTimer& getGeneralStepTimer(GeneralStep step) { return mTimersGeneralSteps[getGeneralStepNum(step)]; } + void SetNestedLoopOmpFactor(unsigned int f) { mNestedLoopOmpFactor = f; } + unsigned int SetAndGetNestedLoopOmpFactor(bool condition, unsigned int max); + protected: struct GPUProcessorProcessors : public GPUProcessor { GPUConstantMem* mProcessorsProc = nullptr; diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 146996d50a245..f4c9e54c7f56c 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -121,7 +121,7 @@ AddOption(mergerSortTracks, int, -1, "", 0, "Sort track indizes for GPU track fi AddOption(tpcCompressionGatherMode, int, -1, "", 0, "TPC Compressed Clusters Gather Mode (0: DMA transfer gather gpu to host, 1: serial DMA to host and gather by copy on CPU, 2. gather via GPU kernal DMA access, 3. gather on GPU via kernel, dma afterwards") AddOption(tpcCompressionGatherModeKernel, int, -1, "", 0, "TPC Compressed Clusters Gather Mode Kernel (0: unbufferd, 1-3: buffered, 4: multi-block)") AddOption(runMC, bool, false, "", 0, "Process MC labels") -AddOption(ompKernels, bool, true, "", 0, "Parallelize with OMP inside kernels instead of over slices") +AddOption(ompKernels, unsigned char, 2, "", 0, "Parallelize with OMP inside kernels instead of over slices, 2 for nested parallelization over TPC sectors and inside kernels") AddOption(doublePipeline, bool, false, "", 0, "Double pipeline mode") AddOption(prefetchTPCpageScan, int, 0, "", 0, "Prefetch Data for TPC page scan in CPU cache") AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 863bc98e878b2..b6ba7214cb89e 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1536,7 +1536,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() int streamMap[NSLICES]; bool error = false; - GPUCA_OPENMP(parallel for if(!(doGPU || GetProcessingSettings().ompKernels)) num_threads(GetProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel for if(!doGPU && GetProcessingSettings().ompKernels != 1) num_threads(mRec->SetAndGetNestedLoopOmpFactor(!doGPU, NSLICES))) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { if (mRec->GetDeviceType() == GPUReconstruction::DeviceType::HIP) { SynchronizeGPU(); // BUG: Workaround for probable bug in AMD runtime, crashes randomly if not synchronized here @@ -1649,6 +1649,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() DoDebugAndDump(RecoStep::TPCSliceTracking, 512, trk, &GPUTPCTracker::DumpTrackHits, *mDebugFile); } } + mRec->SetNestedLoopOmpFactor(1); if (error) { return (3); } @@ -1813,7 +1814,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } } else { mSliceSelectorReady = NSLICES; - GPUCA_OPENMP(parallel for if(!(doGPU || GetProcessingSettings().ompKernels)) num_threads(GetProcessingSettings().ompThreads)) + GPUCA_OPENMP(parallel for if(!doGPU && GetProcessingSettings().ompKernels != 1) num_threads(mRec->SetAndGetNestedLoopOmpFactor(!doGPU, NSLICES))) for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { if (param().rec.GlobalTracking) { GlobalTracking(iSlice, 0); @@ -1822,6 +1823,7 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() WriteOutput(iSlice, 0); } } + mRec->SetNestedLoopOmpFactor(1); } if (param().rec.GlobalTracking && GetProcessingSettings().debugLevel >= 3) { diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx index 2573fdf702f79..b339cf2666ebc 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx @@ -106,7 +106,7 @@ void* GPUTPCTracker::SetPointersCommon(void* mem) void GPUTPCTracker::RegisterMemoryAllocation() { AllocateAndInitializeLate(); - bool reuseCondition = !mRec->GetProcessingSettings().keepDisplayMemory && mRec->GetProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetProcessingSettings().ompKernels || mRec->GetProcessingSettings().ompThreads == 1); + bool reuseCondition = !mRec->GetProcessingSettings().keepDisplayMemory && mRec->GetProcessingSettings().trackletSelectorInPipeline && ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCSliceTracking) || mRec->GetProcessingSettings().ompKernels == 1 || mRec->GetProcessingSettings().ompThreads == 1); GPUMemoryReuse reLinks{reuseCondition, GPUMemoryReuse::REUSE_1TO1, GPUMemoryReuse::TrackerDataLinks, (unsigned short)(mISlice % mRec->GetProcessingSettings().nStreams)}; mMemoryResLinks = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataLinks, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK, "TPCSliceLinks", reLinks); mMemoryResSliceScratch = mRec->RegisterMemoryAllocation(this, &GPUTPCTracker::SetPointersDataScratch, GPUMemoryResource::MEMORY_SCRATCH | GPUMemoryResource::MEMORY_STACK | GPUMemoryResource::MEMORY_CUSTOM, "TPCSliceScratch"); From af7005ca96cf0f596ed125f9373e1f9227625b17 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 5 Jan 2021 15:19:34 +0100 Subject: [PATCH 1692/1751] Allow forcing by hand last release tag (#5123) --- .github/workflows/reports.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index f4882f7ffd0a2..9fc80962a03d5 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -3,6 +3,11 @@ name: Automatically create CHANGELOG for O2 releases on: push: workflow_dispatch: + inputs: + LAST_RELEASE_DATE: + description: 'Time of the last release' + required: true + default: '' schedule: - cron: '0 0 * * *' @@ -88,7 +93,8 @@ jobs: EOF # FIXME: this should really be one second after the last release # being published - MERGED_AFTER=`date -v -14d +%Y-%m-%d` + LAST_RELEASE="${{ github.event.inputs.LAST_RELEASE_DATE }}" + MERGED_AFTER=${LAST_RELEASE:-$(date -v -14d +%Y-%m-%d)} # Here we convert all the json files to per subsystem # logs, using the MERGED_AFTER date to further filter them. From e9cfe1f622628d5673916e3fa773d1af0ef87a8b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 5 Jan 2021 15:37:38 +0100 Subject: [PATCH 1693/1751] Updated README (#5119) Co-authored-by: GitHub Action Bot <github-action-bot@example.com> --- CHANGELOG.md | 63 +- doc/data/2021-01-o2_prs.json | 3464 ++++++++++++++++------------------ 2 files changed, 1708 insertions(+), 1819 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbd7a1ec66215..699ba2a1893d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,39 @@ -# Changes since 2020-12-21 +# Changes since 2020-12-11 +## Changes in Algorithm + +- [#5071](https://github.com/AliceO2Group/AliceO2/pull/5071) 2020-12-16: DPL: initial support for plugin based algorithms by [@ktf](https://github.com/ktf) ## Changes in Analysis -- [#5013](https://github.com/AliceO2Group/AliceO2/pull/5013) 2021-01-04: PWGHF: Update of the Lc->pKpi selector and task by [@DelloStritto](https://github.com/DelloStritto) +- [#5042](https://github.com/AliceO2Group/AliceO2/pull/5042) 2020-12-11: Change to new TPCrefit check: finders by [@ddobrigk](https://github.com/ddobrigk) +- [#5039](https://github.com/AliceO2Group/AliceO2/pull/5039) 2020-12-11: Fixed bug for nested AnalysisCompositeCuts; removed duplicated histogram classes from TableReader by [@iarsene](https://github.com/iarsene) +- [#5063](https://github.com/AliceO2Group/AliceO2/pull/5063) 2020-12-14: DPL Analysis: add string array Configurable by [@aalkin](https://github.com/aalkin) +- [#5050](https://github.com/AliceO2Group/AliceO2/pull/5050) 2020-12-14: DPL Analysis: use compile-time hashed histogram names in registry by [@mario-krueger](https://github.com/mario-krueger) +- [#5060](https://github.com/AliceO2Group/AliceO2/pull/5060) 2020-12-14: Fix finder -> problems with partitioning to be checked by [@ddobrigk](https://github.com/ddobrigk) +- [#5064](https://github.com/AliceO2Group/AliceO2/pull/5064) 2020-12-14: Using histogram registry fill by [@jgrosseo](https://github.com/jgrosseo) +- [#5066](https://github.com/AliceO2Group/AliceO2/pull/5066) 2020-12-15: Analysis: extend histogram registry example by [@mario-krueger](https://github.com/mario-krueger) +- [#5073](https://github.com/AliceO2Group/AliceO2/pull/5073) 2020-12-16: DPL: allow decoupling from JAlien and retrieve JAlienFile, if available by [@ktf](https://github.com/ktf) +- [#5071](https://github.com/AliceO2Group/AliceO2/pull/5071) 2020-12-16: DPL: initial support for plugin based algorithms by [@ktf](https://github.com/ktf) +- [#5081](https://github.com/AliceO2Group/AliceO2/pull/5081) 2020-12-18: DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support by [@ktf](https://github.com/ktf) +- [#5084](https://github.com/AliceO2Group/AliceO2/pull/5084) 2020-12-19: Add X at minimum to v0data table by [@ddobrigk](https://github.com/ddobrigk) +- [#5074](https://github.com/AliceO2Group/AliceO2/pull/5074) 2021-01-05: Initial version of EMCAL Correction Task by [@raymondEhlers](https://github.com/raymondEhlers) +- [#5026](https://github.com/AliceO2Group/AliceO2/pull/5026) 2021-01-05: Convert collision time to ps in TOF PID response by [@njacazio](https://github.com/njacazio) ## Changes in Common +- [#5045](https://github.com/AliceO2Group/AliceO2/pull/5045) 2020-12-11: [ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK by [@mconcas](https://github.com/mconcas) +- [#5043](https://github.com/AliceO2Group/AliceO2/pull/5043) 2020-12-12: Make TrackPar(Cov) compatible to GPU by [@davidrohr](https://github.com/davidrohr) +- [#5067](https://github.com/AliceO2Group/AliceO2/pull/5067) 2020-12-15: Increase the margin of CTF block size to 10KB by [@shahor02](https://github.com/shahor02) - [#5100](https://github.com/AliceO2Group/AliceO2/pull/5100) 2020-12-28: GPU: Make more headers compatible to GPU by [@davidrohr](https://github.com/davidrohr) +- [#5116](https://github.com/AliceO2Group/AliceO2/pull/5116) 2021-01-05: Global (currently TPC only) refit on GPU using either GPU or TrackParCov track model by [@davidrohr](https://github.com/davidrohr) ## Changes in DataFormats +- [#5049](https://github.com/AliceO2Group/AliceO2/pull/5049) 2020-12-11: Add DAQ SystemID Unloaded [O2-1918] by [@shahor02](https://github.com/shahor02) +- [#5041](https://github.com/AliceO2Group/AliceO2/pull/5041) 2020-12-11: Use value_t instead of double by [@davidrohr](https://github.com/davidrohr) +- [#5045](https://github.com/AliceO2Group/AliceO2/pull/5045) 2020-12-11: [ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK by [@mconcas](https://github.com/mconcas) +- [#5043](https://github.com/AliceO2Group/AliceO2/pull/5043) 2020-12-12: Make TrackPar(Cov) compatible to GPU by [@davidrohr](https://github.com/davidrohr) +- [#5056](https://github.com/AliceO2Group/AliceO2/pull/5056) 2020-12-13: Eliminate mass argument from track mat.corrections and propagation interfaces by [@shahor02](https://github.com/shahor02) +- [#5067](https://github.com/AliceO2Group/AliceO2/pull/5067) 2020-12-15: Increase the margin of CTF block size to 10KB by [@shahor02](https://github.com/shahor02) +- [#5077](https://github.com/AliceO2Group/AliceO2/pull/5077) 2020-12-17: Tmp.fix in TrackParCov c-tor from Cartesian cov.matrix by [@shahor02](https://github.com/shahor02) - [#5089](https://github.com/AliceO2Group/AliceO2/pull/5089) 2020-12-22: real LUT in CCDB by [@AllaMaevskaya](https://github.com/AllaMaevskaya) - [#5092](https://github.com/AliceO2Group/AliceO2/pull/5092) 2020-12-23: ZDC Workflow to inspect raw data by [@cortesep](https://github.com/cortesep) - [#5094](https://github.com/AliceO2Group/AliceO2/pull/5094) 2020-12-24: GPU: Some work towards making the o2 propagator work on GPU by [@davidrohr](https://github.com/davidrohr) @@ -16,6 +42,22 @@ - [#5104](https://github.com/AliceO2Group/AliceO2/pull/5104) 2021-01-04: Use DBSCAN for Time-Z clustering in PVertexing, debris reduction by [@shahor02](https://github.com/shahor02) ## Changes in Detectors +- [#5054](https://github.com/AliceO2Group/AliceO2/pull/5054) 2020-12-11: Add braces in oneliners of PHOS code by [@shahor02](https://github.com/shahor02) +- [#5045](https://github.com/AliceO2Group/AliceO2/pull/5045) 2020-12-11: [ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK by [@mconcas](https://github.com/mconcas) +- [#5033](https://github.com/AliceO2Group/AliceO2/pull/5033) 2020-12-11: [ITS] Remove unused classes by [@mconcas](https://github.com/mconcas) +- [#5055](https://github.com/AliceO2Group/AliceO2/pull/5055) 2020-12-12: Change more Double_t to float in TrackParCov propagator by [@davidrohr](https://github.com/davidrohr) +- [#5043](https://github.com/AliceO2Group/AliceO2/pull/5043) 2020-12-12: Make TrackPar(Cov) compatible to GPU by [@davidrohr](https://github.com/davidrohr) +- [#5056](https://github.com/AliceO2Group/AliceO2/pull/5056) 2020-12-13: Eliminate mass argument from track mat.corrections and propagation interfaces by [@shahor02](https://github.com/shahor02) +- [#5058](https://github.com/AliceO2Group/AliceO2/pull/5058) 2020-12-13: Reject outliers when building ITS/MFT clusters dictionary by [@shahor02](https://github.com/shahor02) +- [#5040](https://github.com/AliceO2Group/AliceO2/pull/5040) 2020-12-14: Adding truncation + some minor changes by [@nburmaso](https://github.com/nburmaso) +- [#5036](https://github.com/AliceO2Group/AliceO2/pull/5036) 2020-12-14: First version of pedestal calibration workflow raw data -> ccdb by [@wiechula](https://github.com/wiechula) +- [#5059](https://github.com/AliceO2Group/AliceO2/pull/5059) 2020-12-14: TPC drift gas settings in case FLUKA is used by [@amorsch](https://github.com/amorsch) +- [#5067](https://github.com/AliceO2Group/AliceO2/pull/5067) 2020-12-15: Increase the margin of CTF block size to 10KB by [@shahor02](https://github.com/shahor02) +- [#5047](https://github.com/AliceO2Group/AliceO2/pull/5047) 2020-12-16: TOF DCS Processor by [@chiarazampolli](https://github.com/chiarazampolli) +- [#5057](https://github.com/AliceO2Group/AliceO2/pull/5057) 2020-12-16: Update of water and air cooling by [@frmanso](https://github.com/frmanso) +- [#5078](https://github.com/AliceO2Group/AliceO2/pull/5078) 2020-12-17: Parent TrackPar/Cov creator for DCAFitterN by [@shahor02](https://github.com/shahor02) +- [#5076](https://github.com/AliceO2Group/AliceO2/pull/5076) 2020-12-17: [ITS][ntracker-workflow] Add --configKeyValue for MB LUT by [@mconcas](https://github.com/mconcas) +- [#5088](https://github.com/AliceO2Group/AliceO2/pull/5088) 2020-12-19: MFT: fix lanes mapping for decoding commissionning data and for worki… by [@bovulpes](https://github.com/bovulpes) - [#5091](https://github.com/AliceO2Group/AliceO2/pull/5091) 2020-12-22: MFT: eliminate sqrt where possible by [@bovulpes](https://github.com/bovulpes) - [#5089](https://github.com/AliceO2Group/AliceO2/pull/5089) 2020-12-22: real LUT in CCDB by [@AllaMaevskaya](https://github.com/AllaMaevskaya) - [#5083](https://github.com/AliceO2Group/AliceO2/pull/5083) 2020-12-23: Executable for chunk large raw-data files by [@shahor02](https://github.com/shahor02) @@ -27,7 +69,24 @@ - [#5069](https://github.com/AliceO2Group/AliceO2/pull/5069) 2020-12-28: [WIP][ITS-tracking] Add track dumping in standalone debugger by [@mconcas](https://github.com/mconcas) - [#5102](https://github.com/AliceO2Group/AliceO2/pull/5102) 2020-12-29: Drop bad assert by [@ktf](https://github.com/ktf) - [#5101](https://github.com/AliceO2Group/AliceO2/pull/5101) 2020-12-29: [EMCAL-675] Handling of pages without trailer by [@mfasDa](https://github.com/mfasDa) +- [#5118](https://github.com/AliceO2Group/AliceO2/pull/5118) 2021-01-04: Default mat.corr. is with LUT, fall-back to TGeo if LUT is not set by [@shahor02](https://github.com/shahor02) +- [#5105](https://github.com/AliceO2Group/AliceO2/pull/5105) 2021-01-04: Disable CA_DEBUG in ITS Tracking by [@davidrohr](https://github.com/davidrohr) - [#5104](https://github.com/AliceO2Group/AliceO2/pull/5104) 2021-01-04: Use DBSCAN for Time-Z clustering in PVertexing, debris reduction by [@shahor02](https://github.com/shahor02) +- [#5116](https://github.com/AliceO2Group/AliceO2/pull/5116) 2021-01-05: Global (currently TPC only) refit on GPU using either GPU or TrackParCov track model by [@davidrohr](https://github.com/davidrohr) ## Changes in Framework +- [#5048](https://github.com/AliceO2Group/AliceO2/pull/5048) 2020-12-11: DPL: allow customization of FairMQ channels from command line by [@ktf](https://github.com/ktf) +- [#5063](https://github.com/AliceO2Group/AliceO2/pull/5063) 2020-12-14: DPL Analysis: add string array Configurable by [@aalkin](https://github.com/aalkin) +- [#5035](https://github.com/AliceO2Group/AliceO2/pull/5035) 2020-12-14: DPL Analysis: fix for parsing non-integer arrays in configurables by [@aalkin](https://github.com/aalkin) +- [#5050](https://github.com/AliceO2Group/AliceO2/pull/5050) 2020-12-14: DPL Analysis: use compile-time hashed histogram names in registry by [@mario-krueger](https://github.com/mario-krueger) +- [#5065](https://github.com/AliceO2Group/AliceO2/pull/5065) 2020-12-14: DPL: add file read name metric by [@ktf](https://github.com/ktf) +- [#5068](https://github.com/AliceO2Group/AliceO2/pull/5068) 2020-12-15: DPL Analysis: make sure each hash in histogram registry is unique by [@mario-krueger](https://github.com/mario-krueger) +- [#5073](https://github.com/AliceO2Group/AliceO2/pull/5073) 2020-12-16: DPL: allow decoupling from JAlien and retrieve JAlienFile, if available by [@ktf](https://github.com/ktf) +- [#5071](https://github.com/AliceO2Group/AliceO2/pull/5071) 2020-12-16: DPL: initial support for plugin based algorithms by [@ktf](https://github.com/ktf) +- [#5081](https://github.com/AliceO2Group/AliceO2/pull/5081) 2020-12-18: DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support by [@ktf](https://github.com/ktf) - [#5098](https://github.com/AliceO2Group/AliceO2/pull/5098) 2020-12-27: DPL: use RawDeviceService to sleep in example by [@ktf](https://github.com/ktf) +- [#5113](https://github.com/AliceO2Group/AliceO2/pull/5113) 2021-01-04: DPL: drop unneeded include statements by [@ktf](https://github.com/ktf) +- [#5099](https://github.com/AliceO2Group/AliceO2/pull/5099) 2021-01-04: DPL: move GUI to a plugin by [@ktf](https://github.com/ktf) +## Changes in Utilities + +- [#5037](https://github.com/AliceO2Group/AliceO2/pull/5037) 2020-12-14: Drop untested / unused hough transform code by [@ktf](https://github.com/ktf) diff --git a/doc/data/2021-01-o2_prs.json b/doc/data/2021-01-o2_prs.json index 0d7c8e832e295..ad8de47895c57 100644 --- a/doc/data/2021-01-o2_prs.json +++ b/doc/data/2021-01-o2_prs.json @@ -5,9 +5,9 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-04T20:48:12Z", - "title": "Fix another EMCAL out of bounds error", - "number": 5010, + "mergedAt": "2020-12-09T13:52:19Z", + "title": "GPU: Tune some kernel parameters for AMD Vega", + "number": 5024, "author": { "login": "davidrohr" }, @@ -15,7 +15,7 @@ "edges": [ { "node": { - "path": "Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx" + "path": "GPU/Common/GPUDefGPUParameters.h" } } ] @@ -25,32 +25,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-04T21:32:52Z", - "title": "Add storing CTF / Reading input from CTF / Run asynchronous reconstruction to full system test", - "number": 5011, + "mergedAt": "2020-12-08T19:05:59Z", + "title": "Getting prepared for boolean columns", + "number": 5025, "author": { - "login": "davidrohr" + "login": "victor-gonzalez" }, "files": { "edges": [ { "node": { - "path": "prodtests/full-system-test/README.md" - } - }, - { - "node": { - "path": "prodtests/full-system-test/dpl-workflow.sh" - } - }, - { - "node": { - "path": "prodtests/full-system-test/setenv.sh" - } - }, - { - "node": { - "path": "prodtests/full_system_test.sh" + "path": "Analysis/Tasks/PWGCF/dptdptcorrelations.cxx" } } ] @@ -60,17 +45,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-05T08:49:46Z", - "title": "decrease verbosity of EMCAL RawReaderMemory", - "number": 5012, + "mergedAt": "2021-01-05T09:00:05Z", + "title": "Convert collision time to ps in TOF PID response", + "number": 5026, "author": { - "login": "shahor02" + "login": "njacazio" }, "files": { "edges": [ { "node": { - "path": "Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx" + "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/pidTOF.cxx" } } ] @@ -80,47 +70,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T10:29:31Z", - "title": "PWGHF: Update of the Lc->pKpi selector and task", - "number": 5013, + "mergedAt": "2020-12-08T08:21:19Z", + "title": "DPL: attempt at supporting cloned processors", + "number": 5027, "author": { - "login": "DelloStritto" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" - } - }, - { - "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx" + "path": "Framework/Core/include/Framework/runDataProcessing.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx" + "path": "Framework/Core/src/WorkflowHelpers.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/taskLc.cxx" + "path": "Framework/Core/src/runDataProcessing.cxx" } } ] @@ -130,22 +100,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-07T12:13:47Z", - "title": "Fix: Proper treatment of --disable-mc in PHOS CellConverterSpec", - "number": 5014, + "mergedAt": "2020-12-09T14:56:44Z", + "title": "DPL: syntactic sugar for --clone <template>:<instance number>", + "number": 5028, "author": { - "login": "shahor02" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/CellConverterSpec.h" - } - }, - { - "node": { - "path": "Detectors/PHOS/workflow/src/CellConverterSpec.cxx" + "path": "Framework/Core/src/runDataProcessing.cxx" } } ] @@ -155,57 +120,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-06T18:31:36Z", - "title": "TrackSelection: revert to uint8_t columns", - "number": 5015, + "mergedAt": "2020-12-08T12:58:36Z", + "title": "DPL GUI: add buttons to debug / profile the driver", + "number": 5029, "author": { - "login": "mario-krueger" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/TrackSelectionTables.h" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGCF/correlations.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGCF/filterCF.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/mcspectraefficiency.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/spectraTOF.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/spectraTPC.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/trackchecks.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/trackqa.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/trackselection.cxx" + "path": "Framework/Core/src/FrameworkGUIDebugger.cxx" } } ] @@ -215,17 +140,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-06T18:30:57Z", - "title": "Update for Run3 subtask", - "number": 5016, + "mergedAt": "2020-12-08T17:47:53Z", + "title": "DPL: better error message when DPL_ENABLE_STACKTRACE not set", + "number": 5030, "author": { - "login": "nburmaso" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/eventSelection.cxx" + "path": "Framework/Core/src/runDataProcessing.cxx" } } ] @@ -235,27 +160,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-08T13:53:29Z", - "title": "Fixes for DCS->DPL proxy", - "number": 5017, + "mergedAt": "2020-12-08T15:10:36Z", + "title": "Fix for MCTruth label checks", + "number": 5031, "author": { - "login": "shahor02" + "login": "nburmaso" }, "files": { "edges": [ { "node": { - "path": "Detectors/DCS/include/DetectorsDCS/DataPointCompositeObject.h" - } - }, - { - "node": { - "path": "Detectors/DCS/include/DetectorsDCS/DataPointIdentifier.h" - } - }, - { - "node": { - "path": "Detectors/DCS/testWorkflow/DCStoDPLconverter.h" + "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" } } ] @@ -264,10 +179,10 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-07T07:52:40Z", - "title": "DPL: improve startup performance", - "number": 5018, + "state": "OPEN", + "mergedAt": null, + "title": "Drop initial prototype of dataflow setup", + "number": 5032, "author": { "login": "ktf" }, @@ -275,262 +190,242 @@ "edges": [ { "node": { - "path": "Framework/Core/include/Framework/DeviceMetricsInfo.h" + "path": "Utilities/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/DeviceMetricsInfo.cxx" + "path": "Utilities/DataFlow/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/FrameworkGUIDevicesGraph.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-10T08:12:27Z", - "title": "NFC: Fix codechecker for the ITS GPU code", - "number": 5019, - "author": { - "login": "mpuccio" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Array.h" + "path": "Utilities/DataFlow/doc/o2-subframebuilder-device.1.in" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/ClusterLinesGPU.h" + "path": "Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Context.h" + "path": "Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreNV.h" + "path": "Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/DeviceStoreVertexerGPU.h" + "path": "Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/PrimaryVertexContextNV.h" + "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Stream.h" + "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h" + "path": "Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h" + "path": "Utilities/DataFlow/include/DataFlow/PayloadMerger.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h" + "path": "Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h" + "path": "Utilities/DataFlow/include/DataFlow/SubframeUtils.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/ClusterLinesGPU.cu" + "path": "Utilities/DataFlow/include/DataFlow/TimeframeParser.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu" + "path": "Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu" + "path": "Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu" + "path": "Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/Stream.cu" + "path": "Utilities/DataFlow/run/CreateSetup.py" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu" + "path": "Utilities/DataFlow/run/confBasicSetup.json" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu" + "path": "Utilities/DataFlow/run/confComplexSetup.json" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu" + "path": "Utilities/DataFlow/run/confComplexSetup2.json" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ArrayHIP.h" + "path": "Utilities/DataFlow/run/confFakeTimeframe.json" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ClusterLinesHIP.h" + "path": "Utilities/DataFlow/run/startBasicSetup.sh" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/ContextHIP.h" + "path": "Utilities/DataFlow/run/startComplexSetup.sh" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/DeviceStoreVertexerHIP.h" + "path": "Utilities/DataFlow/run/startComplexSetup2.sh" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/StreamHIP.h" + "path": "Utilities/DataFlow/run/startTimeframeExample.sh" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UniquePointerHIP.h" + "path": "Utilities/DataFlow/src/EPNReceiverDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/UtilsHIP.h" + "path": "Utilities/DataFlow/src/FLPSenderDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VectorHIP.h" + "path": "Utilities/DataFlow/src/FakeTimeframeBuilder.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/include/ITStrackingHIP/VertexerTraitsHIP.h" + "path": "Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/src/ClusterLinesHIP.hip.cxx" + "path": "Utilities/DataFlow/src/HeartbeatSampler.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/src/ContextHIP.hip.cxx" + "path": "Utilities/DataFlow/src/SubframeBuilderDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/src/DeviceStoreVertexerHIP.hip.cxx" + "path": "Utilities/DataFlow/src/TimeframeParser.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/src/StreamHIP.hip.cxx" + "path": "Utilities/DataFlow/src/TimeframeReaderDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/src/UtilsHIP.hip.cxx" + "path": "Utilities/DataFlow/src/TimeframeValidationTool.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/hip/src/VertexerTraitsHIP.hip.cxx" + "path": "Utilities/DataFlow/src/TimeframeValidatorDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h" + "path": "Utilities/DataFlow/src/TimeframeWriterDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h" + "path": "Utilities/DataFlow/src/runEPNReceiver.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h" + "path": "Utilities/DataFlow/src/runFLPSender.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + "path": "Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h" + "path": "Utilities/DataFlow/src/runHeartbeatSampler.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h" + "path": "Utilities/DataFlow/src/runSubframeBuilderDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h" + "path": "Utilities/DataFlow/src/runTimeframeReaderDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h" + "path": "Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx" + "path": "Utilities/DataFlow/src/runTimeframeWriterDevice.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/PrimaryVertexContext.cxx" + "path": "Utilities/DataFlow/test/test_PayloadMerger01.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackerTraitsCPU.cxx" + "path": "Utilities/DataFlow/test/test_SubframeUtils01.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx" + "path": "Utilities/DataFlow/test/test_TimeframeParser.cxx" } } ] @@ -540,9 +435,9 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T23:02:08Z", - "title": "[ITS-ntracker] Add material budget fix and chi2 selection", - "number": 5020, + "mergedAt": "2020-12-11T16:10:58Z", + "title": "[ITS] Remove unused classes", + "number": 5033, "author": { "login": "mconcas" }, @@ -550,42 +445,32 @@ "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h" + "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-07T10:12:59Z", - "title": "sim_challenge: include new AOD producer workflow", - "number": 5021, - "author": { - "login": "sawenzel" - }, - "files": { - "edges": [ + }, + { + "node": { + "path": "Detectors/ITSMFT/ITS/tracking/src/Graph.cxx" + } + }, { "node": { - "path": "prodtests/sim_challenge.sh" + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" } } ] @@ -594,178 +479,198 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "[WIP] trd raw data flp and epn", - "number": 5022, + "state": "MERGED", + "mergedAt": "2020-12-10T08:19:25Z", + "title": "Moving StepTHn to Framework", + "number": 5034, "author": { - "login": "bazinski" + "login": "jgrosseo" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/TRD/src/LinkRecord.cxx" - } - }, - { - "node": { - "path": "DataFormats/Detectors/TRD/src/RawData.cxx" + "path": "Analysis/Core/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TRD/CMakeLists.txt" + "path": "Framework/AnalysisTools/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TRD/raw/CMakeLists.txt" + "path": "Framework/AnalysisTools/src/AnalysisToolsLinkDef.h" } }, { "node": { - "path": "Detectors/TRD/raw/include/TRDRaw/CompressedRawReader.h" + "path": "Framework/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TRD/raw/include/TRDRaw/ConfigEvenParser.h" + "path": "Framework/Core/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TRD/raw/include/TRDRaw/CruCompressorTask.h" + "path": "Framework/Core/include/Framework/StepTHn.h" } }, { "node": { - "path": "Detectors/TRD/raw/include/TRDRaw/CruRawReader.h" + "path": "Framework/Core/src/StepTHn.cxx" } }, { "node": { - "path": "Detectors/TRD/raw/include/TRDRaw/DigitsParser.h" + "path": "Framework/Core/test/FrameworkCoreTestLinkDef.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T10:16:35Z", + "title": "DPL Analysis: fix for parsing non-integer arrays in configurables", + "number": 5035, + "author": { + "login": "aalkin" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/TRD/raw/include/TRDRaw/EpnDataReaderTask.h" + "path": "Framework/Core/src/BoostOptionsRetriever.cxx" } }, { "node": { - "path": "Detectors/TRD/raw/include/TRDRaw/TrackletsParser.h" + "path": "Framework/Core/src/DataProcessingDevice.cxx" } }, { "node": { - "path": "Detectors/TRD/raw/src/CompressedRawReader.cxx" + "path": "Framework/Core/src/PropertyTreeHelpers.cxx" } }, { "node": { - "path": "Detectors/TRD/raw/src/CruCompressor.cxx" + "path": "Framework/Core/src/RootConfigParamHelpers.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T17:26:02Z", + "title": "First version of pedestal calibration workflow raw data -> ccdb", + "number": 5036, + "author": { + "login": "wiechula" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/TPC/base/include/TPCBase/CDBInterface.h" } }, { "node": { - "path": "Detectors/TRD/raw/src/CruCompressorTask.cxx" + "path": "Detectors/TPC/calibration/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TRD/raw/src/CruRawReader.cxx" + "path": "Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h" } }, { "node": { - "path": "Detectors/TRD/raw/src/DigitsParser.cxx" + "path": "Detectors/TPC/calibration/macro/runPedestal.C" } }, { "node": { - "path": "Detectors/TRD/raw/src/EpnDataReader.cxx" + "path": "Detectors/TPC/calibration/macro/runPedestal.sh" } }, { "node": { - "path": "Detectors/TRD/raw/src/EpnDataReaderTask.cxx" + "path": "Detectors/TPC/calibration/run/calib-pedestal.cxx" } }, { "node": { - "path": "Detectors/TRD/raw/src/TrackletsParser.cxx" + "path": "Detectors/TPC/calibration/src/CalibRawBase.cxx" } }, { "node": { - "path": "Detectors/TRD/simulation/src/Trap2CRU.cxx" + "path": "Detectors/TPC/calibration/src/CalibTreeDump.cxx" } }, { "node": { - "path": "Detectors/TRD/simulation/src/TrapSimulator.cxx" + "path": "Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h" } }, { "node": { - "path": "Detectors/TRD/simulation/src/trap2raw.cxx" + "path": "Detectors/TPC/reconstruction/src/RawReaderCRU.cxx" } }, { "node": { - "path": "Detectors/TRD/workflow/CMakeLists.txt" + "path": "Detectors/TPC/workflow/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx" + "path": "Detectors/TPC/workflow/README.md" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-08T09:36:15Z", - "title": "Deltaphi cuts above pi do not make sense", - "number": 5023, - "author": { - "login": "mpuccio" - }, - "files": { - "edges": [ + }, { "node": { - "path": "macro/run_trac_alice3.C" + "path": "Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-09T13:52:19Z", - "title": "GPU: Tune some kernel parameters for AMD Vega", - "number": 5024, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ + }, { "node": { - "path": "GPU/Common/GPUDefGPUParameters.h" + "path": "Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/CalibProcessingHelper.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/RawToDigitsSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx" } } ] @@ -775,42 +680,32 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-08T19:05:59Z", - "title": "Getting prepared for boolean columns", - "number": 5025, + "mergedAt": "2020-12-14T09:09:26Z", + "title": "Drop untested / unused hough transform code", + "number": 5037, "author": { - "login": "victor-gonzalez" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGCF/dptdptcorrelations.cxx" + "path": "Utilities/CMakeLists.txt" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Convert collision time to ps in TOF PID response", - "number": 5026, - "author": { - "login": "njacazio" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h" + "path": "Utilities/hough/CMakeLists.txt" } }, { "node": { - "path": "Analysis/Tasks/pidTOF.cxx" + "path": "Utilities/hough/README.md" + } + }, + { + "node": { + "path": "Utilities/hough/runHough.cxx" } } ] @@ -820,9 +715,9 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-08T08:21:19Z", - "title": "DPL: attempt at supporting cloned processors", - "number": 5027, + "mergedAt": "2020-12-09T17:05:42Z", + "title": "DPL: allow adding suffix to all dataprocessors in a workflow", + "number": 5038, "author": { "login": "ktf" }, @@ -833,11 +728,6 @@ "path": "Framework/Core/include/Framework/runDataProcessing.h" } }, - { - "node": { - "path": "Framework/Core/src/WorkflowHelpers.cxx" - } - }, { "node": { "path": "Framework/Core/src/runDataProcessing.cxx" @@ -850,17 +740,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-09T14:56:44Z", - "title": "DPL: syntactic sugar for --clone <template>:<instance number>", - "number": 5028, + "mergedAt": "2020-12-11T09:04:29Z", + "title": "Fixed bug for nested AnalysisCompositeCuts; removed duplicated histogram classes from TableReader", + "number": 5039, "author": { - "login": "ktf" + "login": "iarsene" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h" + } + }, + { + "node": { + "path": "Analysis/Core/src/AnalysisCompositeCut.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGDQ/tableReader.cxx" } } ] @@ -870,17 +770,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-08T12:58:36Z", - "title": "DPL GUI: add buttons to debug / profile the driver", - "number": 5029, + "mergedAt": "2020-12-14T08:50:21Z", + "title": "Adding truncation + some minor changes", + "number": 5040, "author": { - "login": "ktf" + "login": "nburmaso" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/src/FrameworkGUIDebugger.cxx" + "path": "Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h" + } + }, + { + "node": { + "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" } } ] @@ -890,17 +795,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-08T17:47:53Z", - "title": "DPL: better error message when DPL_ENABLE_STACKTRACE not set", - "number": 5030, + "mergedAt": "2020-12-11T10:36:58Z", + "title": "Use value_t instead of double", + "number": 5041, "author": { - "login": "ktf" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + } + }, + { + "node": { + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" } } ] @@ -910,17 +820,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-08T15:10:36Z", - "title": "Fix for MCTruth label checks", - "number": 5031, + "mergedAt": "2020-12-11T09:02:23Z", + "title": "Change to new TPCrefit check: finders", + "number": 5042, "author": { - "login": "nburmaso" + "login": "ddobrigk" }, "files": { "edges": [ { "node": { - "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" + "path": "Analysis/Tasks/PWGLF/cascadefinder.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/multiplicityQa.cxx" } } ] @@ -929,388 +849,403 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Drop initial prototype of dataflow setup", - "number": 5032, + "state": "MERGED", + "mergedAt": "2020-12-12T08:55:06Z", + "title": "Make TrackPar(Cov) compatible to GPU", + "number": 5043, "author": { - "login": "ktf" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Utilities/CMakeLists.txt" + "path": "Common/MathUtils/include/MathUtils/CartesianGPU.h" } }, { "node": { - "path": "Utilities/DataFlow/CMakeLists.txt" + "path": "Common/MathUtils/include/MathUtils/Utils.h" } }, { "node": { - "path": "Utilities/DataFlow/doc/o2-subframebuilder-device.1.in" + "path": "Common/MathUtils/include/MathUtils/detail/CircleXY.h" } }, { "node": { - "path": "Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in" + "path": "Common/MathUtils/include/MathUtils/detail/IntervalXY.h" } }, { "node": { - "path": "Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in" + "path": "Common/MathUtils/include/MathUtils/detail/trigonometric.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/PayloadMerger.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/SubframeUtils.h" + "path": "DataFormats/Reconstruction/src/DCA.cxx" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeParser.h" + "path": "DataFormats/Reconstruction/src/PID.cxx" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h" + "path": "DataFormats/Reconstruction/src/PrimaryVertex.cxx" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h" + "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h" + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" } }, { "node": { - "path": "Utilities/DataFlow/run/CreateSetup.py" + "path": "DataFormats/Reconstruction/src/Vertex.cxx" } }, { "node": { - "path": "Utilities/DataFlow/run/confBasicSetup.json" + "path": "DataFormats/common/include/CommonDataFormat/InteractionRecord.h" } }, { "node": { - "path": "Utilities/DataFlow/run/confComplexSetup.json" + "path": "DataFormats/common/src/InteractionRecord.cxx" } }, { "node": { - "path": "Utilities/DataFlow/run/confComplexSetup2.json" + "path": "Detectors/Base/src/Propagator.cxx" } }, { "node": { - "path": "Utilities/DataFlow/run/confFakeTimeframe.json" + "path": "GPU/Common/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/run/startBasicSetup.sh" + "path": "GPU/Common/GPUCommonArray.h" } }, { "node": { - "path": "Utilities/DataFlow/run/startComplexSetup.sh" + "path": "GPU/Common/GPUCommonDef.h" } }, { "node": { - "path": "Utilities/DataFlow/run/startComplexSetup2.sh" + "path": "GPU/Common/GPUCommonLogger.h" } }, { "node": { - "path": "Utilities/DataFlow/run/startTimeframeExample.sh" + "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" } }, { "node": { - "path": "Utilities/DataFlow/src/EPNReceiverDevice.cxx" + "path": "GPU/GPUTracking/Base/cuda/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/FLPSenderDevice.cxx" + "path": "GPU/GPUTracking/Base/hip/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/FakeTimeframeBuilder.cxx" + "path": "GPU/GPUTracking/Base/opencl2/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx" + "path": "GPU/GPUTracking/Standalone/CMakeLists.txt" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-10T13:55:19Z", + "title": "Decouple VMC libs from o2-sim", + "number": 5044, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/gconfig/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/HeartbeatSampler.cxx" + "path": "Detectors/gconfig/src/G3Config.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/SubframeBuilderDevice.cxx" + "path": "Detectors/gconfig/src/G4Config.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeParser.cxx" + "path": "Detectors/gconfig/src/SetCuts.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeReaderDevice.cxx" + "path": "Detectors/gconfig/src/SetCuts.h" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeValidationTool.cxx" + "path": "Detectors/gconfig/src/SimSetup.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T07:33:24Z", + "title": "[ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK", + "number": 5045, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ + { + "node": { + "path": "Common/SimConfig/src/SimConfig.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeValidatorDevice.cxx" + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeWriterDevice.cxx" + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h" } }, { "node": { - "path": "Utilities/DataFlow/src/runEPNReceiver.cxx" + "path": "DataFormats/Detectors/Common/src/DetID.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/runFLPSender.cxx" + "path": "DataFormats/Headers/include/Headers/DataHeader.h" } }, { "node": { - "path": "Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx" + "path": "Detectors/Upgrades/ALICE3/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/runHeartbeatSampler.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/runSubframeBuilderDevice.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/README.md" } }, { "node": { - "path": "Utilities/DataFlow/src/runTimeframeReaderDevice.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h" } }, { "node": { - "path": "Utilities/DataFlow/src/runTimeframeWriterDevice.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/MisalignmentParameter.h" } }, { "node": { - "path": "Utilities/DataFlow/test/test_PayloadMerger01.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx" } }, { "node": { - "path": "Utilities/DataFlow/test/test_SubframeUtils01.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/base/src/MisalignmentParameter.cxx" } }, { "node": { - "path": "Utilities/DataFlow/test/test_TimeframeParser.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/base/src/TRKBaseLinkDef.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T16:10:58Z", - "title": "[ITS] Remove unused classes", - "number": 5033, - "author": { - "login": "mconcas" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/TRK/macros/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h" + "path": "Detectors/Upgrades/ALICE3/TRK/macros/test/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/data/simcuts.dat" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Graph.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V11Geometry.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-10T08:19:25Z", - "title": "Moving StepTHn to Framework", - "number": 5034, - "author": { - "login": "jgrosseo" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Analysis/Core/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V1Layer.h" } }, { "node": { - "path": "Framework/AnalysisTools/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Layer.h" } }, { "node": { - "path": "Framework/AnalysisTools/src/AnalysisToolsLinkDef.h" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Services.h" } }, { "node": { - "path": "Framework/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx" } }, { "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h" } }, { "node": { - "path": "Framework/Core/include/Framework/StepTHn.h" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V11Geometry.cxx" } }, { "node": { - "path": "Framework/Core/src/StepTHn.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V1Layer.cxx" } }, { "node": { - "path": "Framework/Core/test/FrameworkCoreTestLinkDef.h" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Layer.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T10:16:35Z", - "title": "DPL Analysis: fix for parsing non-integer arrays in configurables", - "number": 5035, - "author": { - "login": "aalkin" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/Core/src/BoostOptionsRetriever.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Services.cxx" } }, { "node": { - "path": "Framework/Core/src/DataProcessingDevice.cxx" + "path": "Detectors/Upgrades/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/PropertyTreeHelpers.cxx" + "path": "Detectors/Upgrades/README.md" } }, { "node": { - "path": "Framework/Core/src/RootConfigParamHelpers.cxx" + "path": "macro/CMakeLists.txt" + } + }, + { + "node": { + "path": "macro/build_geometry.C" + } + }, + { + "node": { + "path": "macro/run_trac_alice3.C" + } + }, + { + "node": { + "path": "run/CMakeLists.txt" + } + }, + { + "node": { + "path": "run/O2HitMerger.h" } } ] @@ -1320,142 +1255,157 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T17:26:02Z", - "title": "First version of pedestal calibration workflow raw data -> ccdb", - "number": 5036, + "mergedAt": "2020-12-10T20:31:15Z", + "title": "Support for FLUKA VMC backend in O2", + "number": 5046, "author": { - "login": "wiechula" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "Detectors/TPC/base/include/TPCBase/CDBInterface.h" + "path": "DataFormats/simulation/src/Stack.cxx" } }, { "node": { - "path": "Detectors/TPC/calibration/CMakeLists.txt" + "path": "Detectors/gconfig/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h" + "path": "Detectors/gconfig/data/coreFlukaVmc.inp" } }, { "node": { - "path": "Detectors/TPC/calibration/macro/runPedestal.C" + "path": "Detectors/gconfig/src/FlukaConfig.cxx" } }, { "node": { - "path": "Detectors/TPC/calibration/macro/runPedestal.sh" + "path": "Detectors/gconfig/src/SimSetup.cxx" } }, { "node": { - "path": "Detectors/TPC/calibration/run/calib-pedestal.cxx" + "path": "dependencies/FindFlukaVMC.cmake" } }, { "node": { - "path": "Detectors/TPC/calibration/src/CalibRawBase.cxx" + "path": "dependencies/O2FindDependenciesFromAliBuild.cmake" } }, { "node": { - "path": "Detectors/TPC/calibration/src/CalibTreeDump.cxx" + "path": "dependencies/O2SimulationDependencies.cmake" } }, { "node": { - "path": "Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h" + "path": "run/O2SimDevice.h" } - }, - { - "node": { - "path": "Detectors/TPC/reconstruction/src/RawReaderCRU.cxx" + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-16T22:10:35Z", + "title": "TOF DCS Processor", + "number": 5047, + "author": { + "login": "chiarazampolli" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/DCS/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TPC/workflow/CMakeLists.txt" + "path": "Detectors/DCS/src/DataPointGenerator.cxx" } }, { "node": { - "path": "Detectors/TPC/workflow/README.md" + "path": "Detectors/DCS/src/DetectorsDCSLinkDef.h" } }, { "node": { - "path": "Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h" + "path": "Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h" } }, { "node": { - "path": "Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h" + "path": "Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx" } }, { "node": { - "path": "Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h" + "path": "Detectors/TOF/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TPC/workflow/src/CalibProcessingHelper.cxx" + "path": "Detectors/TOF/base/include/TOFBase/Geo.h" } }, { "node": { - "path": "Detectors/TPC/workflow/src/RawToDigitsSpec.cxx" + "path": "Detectors/TOF/base/src/Geo.cxx" } }, { "node": { - "path": "Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx" + "path": "Detectors/TOF/calibration/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx" + "path": "Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T09:09:26Z", - "title": "Drop untested / unused hough transform code", - "number": 5037, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Utilities/CMakeLists.txt" + "path": "Detectors/TOF/calibration/macros/CMakeLists.txt" } }, { "node": { - "path": "Utilities/hough/CMakeLists.txt" + "path": "Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx" } }, { "node": { - "path": "Utilities/hough/README.md" + "path": "Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h" } }, { "node": { - "path": "Utilities/hough/runHough.cxx" + "path": "Detectors/TOF/calibration/src/TOFDCSProcessor.cxx" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/testWorkflow/README.md" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h" + } + }, + { + "node": { + "path": "Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx" } } ] @@ -1465,9 +1415,9 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-09T17:05:42Z", - "title": "DPL: allow adding suffix to all dataprocessors in a workflow", - "number": 5038, + "mergedAt": "2020-12-11T09:04:41Z", + "title": "DPL: allow customization of FairMQ channels from command line", + "number": 5048, "author": { "login": "ktf" }, @@ -1475,92 +1425,57 @@ "edges": [ { "node": { - "path": "Framework/Core/include/Framework/runDataProcessing.h" + "path": "Framework/Core/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T09:04:29Z", - "title": "Fixed bug for nested AnalysisCompositeCuts; removed duplicated histogram classes from TableReader", - "number": 5039, - "author": { - "login": "iarsene" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h" + "path": "Framework/Core/include/Framework/ChannelSpec.h" } }, { "node": { - "path": "Analysis/Core/src/AnalysisCompositeCut.cxx" + "path": "Framework/Core/include/Framework/WorkflowCustomizationHelpers.h" } }, { "node": { - "path": "Analysis/Tasks/PWGDQ/tableReader.cxx" + "path": "Framework/Core/include/Framework/runDataProcessing.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T08:50:21Z", - "title": "Adding truncation + some minor changes", - "number": 5040, - "author": { - "login": "nburmaso" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h" + "path": "Framework/Core/src/ChannelConfigurationPolicy.cxx" } }, { "node": { - "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" + "path": "Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T10:36:58Z", - "title": "Use value_t instead of double", - "number": 5041, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ + }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + "path": "Framework/Core/src/ChannelSpecHelpers.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + "path": "Framework/Core/src/DeviceSpecHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/src/WorkflowCustomizationHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/Core/test/Mocking.h" } } ] @@ -1570,27 +1485,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T09:02:23Z", - "title": "Change to new TPCrefit check: finders", - "number": 5042, + "mergedAt": "2020-12-11T15:53:21Z", + "title": "Add DAQ SystemID Unloaded [O2-1918]", + "number": 5049, "author": { - "login": "ddobrigk" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGLF/cascadefinder.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + "path": "DataFormats/Headers/include/Headers/DAQID.h" } }, { "node": { - "path": "Analysis/Tasks/multiplicityQa.cxx" + "path": "DataFormats/Headers/test/testDAQID.cxx" } } ] @@ -1600,162 +1510,132 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-12T08:55:06Z", - "title": "Make TrackPar(Cov) compatible to GPU", - "number": 5043, + "mergedAt": "2020-12-14T08:40:42Z", + "title": "DPL Analysis: use compile-time hashed histogram names in registry", + "number": 5050, "author": { - "login": "davidrohr" + "login": "mario-krueger" }, "files": { "edges": [ { "node": { - "path": "Common/MathUtils/include/MathUtils/CartesianGPU.h" + "path": "Analysis/Core/include/AnalysisCore/PairCuts.h" } }, { "node": { - "path": "Common/MathUtils/include/MathUtils/Utils.h" + "path": "Analysis/Tasks/PWGCF/correlations.cxx" } }, { "node": { - "path": "Common/MathUtils/include/MathUtils/detail/CircleXY.h" + "path": "Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx" } }, { "node": { - "path": "Common/MathUtils/include/MathUtils/detail/IntervalXY.h" + "path": "Analysis/Tasks/PWGHF/qaTask.cxx" } }, { "node": { - "path": "Common/MathUtils/include/MathUtils/detail/trigonometric.h" + "path": "Analysis/Tasks/PWGHF/taskD0.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h" + "path": "Analysis/Tasks/PWGHF/taskDPlus.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" + "path": "Analysis/Tasks/PWGLF/spectraTOF.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h" + "path": "Analysis/Tasks/PWGLF/spectraTPC.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" + "path": "Analysis/Tasks/pidTOF.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" + "path": "Analysis/Tasks/pidTPC.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h" + "path": "Analysis/Tasks/trackqa.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h" + "path": "Analysis/Tutorials/src/histogramRegistry.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/src/DCA.cxx" + "path": "Framework/Core/include/Framework/HistogramRegistry.h" } }, { "node": { - "path": "DataFormats/Reconstruction/src/PID.cxx" + "path": "Framework/Core/src/HistogramRegistry.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/src/PrimaryVertex.cxx" + "path": "Framework/Core/test/benchmark_HistogramRegistry.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + "path": "Framework/Core/test/test_HistogramRegistry.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-11T09:07:35Z", + "title": "Drop obsolete badge", + "number": 5051, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + "path": "README.md" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF: do not merge yet: Add efficiency and fix impact parameter calculation", + "number": 5052, + "author": { + "login": "hzanoli" + }, + "files": { + "edges": [ { "node": { - "path": "DataFormats/Reconstruction/src/Vertex.cxx" - } - }, - { - "node": { - "path": "DataFormats/common/include/CommonDataFormat/InteractionRecord.h" - } - }, - { - "node": { - "path": "DataFormats/common/src/InteractionRecord.cxx" - } - }, - { - "node": { - "path": "Detectors/Base/src/Propagator.cxx" - } - }, - { - "node": { - "path": "GPU/Common/CMakeLists.txt" - } - }, - { - "node": { - "path": "GPU/Common/GPUCommonArray.h" - } - }, - { - "node": { - "path": "GPU/Common/GPUCommonDef.h" - } - }, - { - "node": { - "path": "GPU/Common/GPUCommonLogger.h" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Base/cuda/CMakeLists.txt" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Base/hip/CMakeLists.txt" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Base/opencl2/CMakeLists.txt" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Standalone/CMakeLists.txt" + "path": "Analysis/Tasks/PWGHF/qaTask.cxx" } } ] @@ -1765,42 +1645,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-10T13:55:19Z", - "title": "Decouple VMC libs from o2-sim", - "number": 5044, + "mergedAt": "2020-12-12T12:41:53Z", + "title": "ndsplines: added approximateFunctionBatch function", + "number": 5053, "author": { - "login": "sawenzel" + "login": "matthias-kleiner" }, "files": { "edges": [ { "node": { - "path": "Detectors/gconfig/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/G3Config.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/G4Config.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/SetCuts.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/SetCuts.h" + "path": "GPU/TPCFastTransformation/SplineHelper.cxx" } }, { "node": { - "path": "Detectors/gconfig/src/SimSetup.cxx" + "path": "GPU/TPCFastTransformation/SplineHelper.h" } } ] @@ -1810,192 +1670,127 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T07:33:24Z", - "title": "[ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK", - "number": 5045, + "mergedAt": "2020-12-11T15:54:24Z", + "title": "Add braces in oneliners of PHOS code", + "number": 5054, "author": { - "login": "mconcas" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Common/SimConfig/src/SimConfig.cxx" - } - }, - { - "node": { - "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/Common/src/DetID.cxx" - } - }, - { - "node": { - "path": "DataFormats/Headers/include/Headers/DataHeader.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/README.md" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/MisalignmentParameter.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/src/MisalignmentParameter.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/src/TRKBaseLinkDef.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/macros/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/macros/test/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/data/simcuts.dat" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V11Geometry.h" + "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" } }, { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V1Layer.h" + "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-12T08:55:30Z", + "title": "Change more Double_t to float in TrackParCov propagator", + "number": 5055, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Layer.h" + "path": "Detectors/Base/src/Propagator.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-13T13:05:53Z", + "title": "Eliminate mass argument from track mat.corrections and propagation interfaces", + "number": 5056, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Services.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" } }, { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" } }, { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" } }, { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V11Geometry.cxx" + "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" } }, { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V1Layer.cxx" + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" } }, { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Layer.cxx" + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" } }, { "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Services.cxx" + "path": "Detectors/Base/src/Propagator.cxx" } }, { "node": { - "path": "Detectors/Upgrades/CMakeLists.txt" + "path": "Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h" } }, { "node": { - "path": "Detectors/Upgrades/README.md" + "path": "Detectors/GlobalTracking/src/MatchTOF.cxx" } }, { "node": { - "path": "macro/CMakeLists.txt" + "path": "Detectors/GlobalTracking/src/MatchTPCITS.cxx" } }, { "node": { - "path": "macro/build_geometry.C" + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" } }, { "node": { - "path": "macro/run_trac_alice3.C" + "path": "Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx" } }, { "node": { - "path": "run/CMakeLists.txt" + "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.cxx" } }, { "node": { - "path": "run/O2HitMerger.h" + "path": "GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h" } } ] @@ -2005,57 +1800,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-10T20:31:15Z", - "title": "Support for FLUKA VMC backend in O2", - "number": 5046, + "mergedAt": "2020-12-16T18:17:59Z", + "title": "Update of water and air cooling", + "number": 5057, "author": { - "login": "sawenzel" + "login": "frmanso" }, "files": { "edges": [ { "node": { - "path": "DataFormats/simulation/src/Stack.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/gconfig/data/coreFlukaVmc.inp" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/FlukaConfig.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/SimSetup.cxx" - } - }, - { - "node": { - "path": "dependencies/FindFlukaVMC.cmake" - } - }, - { - "node": { - "path": "dependencies/O2FindDependenciesFromAliBuild.cmake" + "path": "Detectors/ITSMFT/MFT/base/src/HalfCone.cxx" } }, { "node": { - "path": "dependencies/O2SimulationDependencies.cmake" + "path": "Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx" } }, { "node": { - "path": "run/O2SimDevice.h" + "path": "Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx" } } ] @@ -2065,97 +1830,152 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-16T22:10:35Z", - "title": "TOF DCS Processor", - "number": 5047, + "mergedAt": "2020-12-13T20:42:36Z", + "title": "Reject outliers when building ITS/MFT clusters dictionary", + "number": 5058, "author": { - "login": "chiarazampolli" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Detectors/DCS/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/DCS/src/DataPointGenerator.cxx" + "path": "Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C" } }, { "node": { - "path": "Detectors/DCS/src/DetectorsDCSLinkDef.h" + "path": "Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T08:01:58Z", + "title": "TPC drift gas settings in case FLUKA is used", + "number": 5059, + "author": { + "login": "amorsch" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h" + "path": "Detectors/TPC/simulation/src/Detector.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-14T10:52:58Z", + "title": "Fix finder -> problems with partitioning to be checked", + "number": 5060, + "author": { + "login": "ddobrigk" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx" + "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "CLOSED", + "mergedAt": null, + "title": "A ROOT serializable key-value store", + "number": 5061, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/TOF/CMakeLists.txt" + "path": "Common/Utils/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TOF/base/include/TOFBase/Geo.h" + "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" } }, { "node": { - "path": "Detectors/TOF/base/src/Geo.cxx" + "path": "Common/Utils/src/CommonUtilsLinkDef.h" } }, { "node": { - "path": "Detectors/TOF/calibration/CMakeLists.txt" + "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" } }, { "node": { - "path": "Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h" + "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "[WIP][ITS-tracking] Extend smoother to n-dimensional tracking", + "number": 5062, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/TOF/calibration/macros/CMakeLists.txt" + "path": "DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h" } }, { "node": { - "path": "Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h" } }, { "node": { - "path": "Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" } }, { "node": { - "path": "Detectors/TOF/calibration/src/TOFDCSProcessor.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h" } }, { "node": { - "path": "Detectors/TOF/calibration/testWorkflow/README.md" + "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" } }, { "node": { - "path": "Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h" + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" } }, { "node": { - "path": "Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx" + "path": "Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx" } } ] @@ -2165,67 +1985,67 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T09:04:41Z", - "title": "DPL: allow customization of FairMQ channels from command line", - "number": 5048, + "mergedAt": "2020-12-14T21:42:12Z", + "title": "DPL Analysis: add string array Configurable", + "number": 5063, "author": { - "login": "ktf" + "login": "aalkin" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "Analysis/Tutorials/include/Analysis/configurableCut.h" } }, { "node": { - "path": "Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h" + "path": "Analysis/Tutorials/src/configurableCut.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/ChannelSpec.h" + "path": "Analysis/Tutorials/src/configurableObjects.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/WorkflowCustomizationHelpers.h" + "path": "Framework/Core/include/Framework/ConfigParamsHelper.h" } }, { "node": { - "path": "Framework/Core/include/Framework/runDataProcessing.h" + "path": "Framework/Core/include/Framework/Variant.h" } }, { "node": { - "path": "Framework/Core/src/ChannelConfigurationPolicy.cxx" + "path": "Framework/Core/src/BoostOptionsRetriever.cxx" } }, { "node": { - "path": "Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx" + "path": "Framework/Core/src/ConfigParamsHelper.cxx" } }, { "node": { - "path": "Framework/Core/src/ChannelSpecHelpers.cxx" + "path": "Framework/Core/src/PropertyTreeHelpers.cxx" } }, { "node": { - "path": "Framework/Core/src/DeviceSpecHelpers.cxx" + "path": "Framework/Core/src/RootConfigParamHelpers.cxx" } }, { "node": { - "path": "Framework/Core/src/WorkflowCustomizationHelpers.cxx" + "path": "Framework/Core/src/Variant.cxx" } }, { "node": { - "path": "Framework/Core/test/Mocking.h" + "path": "Framework/Core/test/test_Variants.cxx" } } ] @@ -2235,22 +2055,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T15:53:21Z", - "title": "Add DAQ SystemID Unloaded [O2-1918]", - "number": 5049, + "mergedAt": "2020-12-14T21:43:13Z", + "title": "Using histogram registry fill", + "number": 5064, "author": { - "login": "shahor02" + "login": "jgrosseo" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Headers/include/Headers/DAQID.h" - } - }, - { - "node": { - "path": "DataFormats/Headers/test/testDAQID.cxx" + "path": "Analysis/Tasks/PWGCF/correlations.cxx" } } ] @@ -2260,112 +2075,157 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T08:40:42Z", - "title": "DPL Analysis: use compile-time hashed histogram names in registry", - "number": 5050, + "mergedAt": "2020-12-14T19:43:17Z", + "title": "DPL: add file read name metric", + "number": 5065, "author": { - "login": "mario-krueger" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Analysis/Core/include/AnalysisCore/PairCuts.h" + "path": "Framework/Core/src/AODReaderHelpers.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGCF/correlations.cxx" + "path": "Framework/Core/src/ResourcesMonitoringHelper.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx" + "path": "Framework/Core/src/ResourcesMonitoringHelper.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/qaTask.cxx" + "path": "Framework/Core/src/runDataProcessing.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-15T08:48:19Z", + "title": "Analysis: extend histogram registry example", + "number": 5066, + "author": { + "login": "mario-krueger" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/taskD0.cxx" + "path": "Analysis/Tutorials/src/histogramRegistry.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-15T13:38:12Z", + "title": "Increase the margin of CTF block size to 10KB", + "number": 5067, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/taskDPlus.cxx" + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-15T21:49:40Z", + "title": "DPL Analysis: make sure each hash in histogram registry is unique", + "number": 5068, + "author": { + "login": "mario-krueger" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tasks/PWGLF/spectraTOF.cxx" + "path": "Framework/Core/include/Framework/HistogramRegistry.h" } }, { "node": { - "path": "Analysis/Tasks/PWGLF/spectraTPC.cxx" + "path": "Framework/Core/src/HistogramRegistry.cxx" } }, { "node": { - "path": "Analysis/Tasks/pidTOF.cxx" + "path": "Framework/Core/test/test_HistogramRegistry.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-28T13:55:03Z", + "title": "[WIP][ITS-tracking] Add track dumping in standalone debugger", + "number": 5069, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tasks/pidTPC.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" } }, { "node": { - "path": "Analysis/Tasks/trackqa.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h" } }, { "node": { - "path": "Analysis/Tutorials/src/histogramRegistry.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" } }, { "node": { - "path": "Framework/Core/include/Framework/HistogramRegistry.h" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h" } }, { "node": { - "path": "Framework/Core/src/HistogramRegistry.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" } }, { "node": { - "path": "Framework/Core/test/benchmark_HistogramRegistry.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" } }, { "node": { - "path": "Framework/Core/test/test_HistogramRegistry.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T09:07:35Z", - "title": "Drop obsolete badge", - "number": 5051, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "README.md" + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" } } ] @@ -2376,41 +2236,26 @@ "node": { "state": "OPEN", "mergedAt": null, - "title": "PWGHF: do not merge yet: Add efficiency and fix impact parameter calculation", - "number": 5052, + "title": "TRD tracklet calculation in TrapSimulator", + "number": 5070, "author": { - "login": "hzanoli" + "login": "martenole" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/qaTask.cxx" + "path": "DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-12T12:41:53Z", - "title": "ndsplines: added approximateFunctionBatch function", - "number": 5053, - "author": { - "login": "matthias-kleiner" - }, - "files": { - "edges": [ + }, { "node": { - "path": "GPU/TPCFastTransformation/SplineHelper.cxx" + "path": "Detectors/TRD/macros/convertRun2ToRun3Digits.C" } }, { "node": { - "path": "GPU/TPCFastTransformation/SplineHelper.h" + "path": "Detectors/TRD/simulation/src/TrapSimulator.cxx" } } ] @@ -2420,42 +2265,42 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T15:54:24Z", - "title": "Add braces in oneliners of PHOS code", - "number": 5054, + "mergedAt": "2020-12-16T12:19:42Z", + "title": "DPL: initial support for plugin based algorithms", + "number": 5071, "author": { - "login": "shahor02" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" + "path": "Framework/AnalysisSupport/CMakeLists.txt" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" + "path": "Framework/AnalysisSupport/src/Plugin.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-12T08:55:30Z", - "title": "Change more Double_t to float in TrackParCov propagator", - "number": 5055, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ + }, + { + "node": { + "path": "Framework/CMakeLists.txt" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/AlgorithmSpec.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/Plugins.h" + } + }, { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Framework/Core/src/WorkflowHelpers.cxx" } } ] @@ -2464,113 +2309,113 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-13T13:05:53Z", - "title": "Eliminate mass argument from track mat.corrections and propagation interfaces", - "number": 5056, + "state": "OPEN", + "mergedAt": null, + "title": "A ROOT serializable key-value store", + "number": 5072, "author": { - "login": "shahor02" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" + "path": "Common/Utils/CMakeLists.txt" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" + "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" } }, { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" + "path": "Common/Utils/src/CommonUtilsLinkDef.h" } }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-16T16:28:44Z", + "title": "DPL: allow decoupling from JAlien and retrieve JAlienFile, if available", + "number": 5073, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + "path": "Framework/AnalysisSupport/CMakeLists.txt" } }, { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" } }, { "node": { - "path": "Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h" + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h" } }, { "node": { - "path": "Detectors/GlobalTracking/src/MatchTOF.cxx" + "path": "Framework/AnalysisSupport/src/Plugin.cxx" } }, { "node": { - "path": "Detectors/GlobalTracking/src/MatchTPCITS.cxx" + "path": "Framework/Core/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Framework/Core/include/Framework/AODReaderHelpers.h" } }, { "node": { - "path": "Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx" + "path": "Framework/Core/src/AODReaderHelpers.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.cxx" + "path": "Framework/Core/src/AnalysisDataModelHelpers.cxx" } }, { "node": { - "path": "GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h" + "path": "Framework/Core/src/AnalysisDataModelHelpers.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-16T18:17:59Z", - "title": "Update of water and air cooling", - "number": 5057, - "author": { - "login": "frmanso" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/ITSMFT/MFT/base/src/HalfCone.cxx" + "path": "dependencies/FindJAlienROOT.cmake" } }, { "node": { - "path": "Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx" + "path": "dependencies/FindXRootD.cmake" } }, { "node": { - "path": "Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx" + "path": "dependencies/O2Dependencies.cmake" } } ] @@ -2580,42 +2425,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-13T20:42:36Z", - "title": "Reject outliers when building ITS/MFT clusters dictionary", - "number": 5058, + "mergedAt": "2021-01-05T08:41:46Z", + "title": " Initial version of EMCAL Correction Task", + "number": 5074, "author": { - "login": "shahor02" + "login": "raymondEhlers" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C" + "path": "Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h" } }, { "node": { - "path": "Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C" + "path": "Analysis/Tasks/CMakeLists.txt" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T08:01:58Z", - "title": "TPC drift gas settings in case FLUKA is used", - "number": 5059, - "author": { - "login": "amorsch" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/TPC/simulation/src/Detector.cxx" + "path": "Analysis/Tasks/emcalCorrectionTask.cxx" } } ] @@ -2624,58 +2454,43 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T10:52:58Z", - "title": "Fix finder -> problems with partitioning to be checked", - "number": 5060, + "state": "CLOSED", + "mergedAt": null, + "title": "Jpsi task and candidate selection", + "number": 5075, "author": { - "login": "ddobrigk" + "login": "zhangbiao-phy" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" } - } - ] - } - } - }, - { - "node": { - "state": "CLOSED", - "mergedAt": null, - "title": "A ROOT serializable key-value store", - "number": 5061, - "author": { - "login": "sawenzel" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Common/Utils/CMakeLists.txt" + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" } }, { "node": { - "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" } }, { "node": { - "path": "Common/Utils/src/CommonUtilsLinkDef.h" + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" } }, { "node": { - "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" + "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" } }, { "node": { - "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" + "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" } } ] @@ -2684,10 +2499,10 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "[WIP][ITS-tracking] Extend smoother to n-dimensional tracking", - "number": 5062, + "state": "MERGED", + "mergedAt": "2020-12-17T22:44:51Z", + "title": "[ITS][ntracker-workflow] Add --configKeyValue for MB LUT", + "number": 5076, "author": { "login": "mconcas" }, @@ -2695,32 +2510,32 @@ "edges": [ { "node": { - "path": "DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h" + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx" } } ] @@ -2730,67 +2545,122 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T21:42:12Z", - "title": "DPL Analysis: add string array Configurable", - "number": 5063, + "mergedAt": "2020-12-17T19:07:38Z", + "title": "Tmp.fix in TrackParCov c-tor from Cartesian cov.matrix", + "number": 5077, "author": { - "login": "aalkin" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tutorials/include/Analysis/configurableCut.h" - } - }, - { - "node": { - "path": "Analysis/Tutorials/src/configurableCut.cxx" + "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-17T22:22:35Z", + "title": "Parent TrackPar/Cov creator for DCAFitterN", + "number": 5078, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tutorials/src/configurableObjects.cxx" + "path": "Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-17T22:27:23Z", + "title": "Fix FindJAliEnROOT.cmake name", + "number": 5079, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/include/Framework/ConfigParamsHelper.h" + "path": "dependencies/FindJAliEnROOT.cmake" } - }, + } + ] + } + } + }, + { + "node": { + "state": "CLOSED", + "mergedAt": null, + "title": "Jpsi task and candidate selection", + "number": 5080, + "author": { + "login": "zhangbiao-phy" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/include/Framework/Variant.h" + "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" } }, { "node": { - "path": "Framework/Core/src/BoostOptionsRetriever.cxx" + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" } }, { "node": { - "path": "Framework/Core/src/ConfigParamsHelper.cxx" + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/PropertyTreeHelpers.cxx" + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" } }, { "node": { - "path": "Framework/Core/src/RootConfigParamHelpers.cxx" + "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" } }, { "node": { - "path": "Framework/Core/src/Variant.cxx" + "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-18T20:32:10Z", + "title": "DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support", + "number": 5081, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/test/test_Variants.cxx" + "path": "Framework/AnalysisSupport/CMakeLists.txt" } } ] @@ -2799,18 +2669,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T21:43:13Z", - "title": "Using histogram registry fill", - "number": 5064, + "state": "OPEN", + "mergedAt": null, + "title": "Fill PDG code database before event generation", + "number": 5082, "author": { - "login": "jgrosseo" + "login": "mpuccio" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGCF/correlations.cxx" + "path": "Generators/src/GeneratorFactory.cxx" } } ] @@ -2820,32 +2690,32 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T19:43:17Z", - "title": "DPL: add file read name metric", - "number": 5065, + "mergedAt": "2020-12-23T00:45:23Z", + "title": "Executable for chunk large raw-data files", + "number": 5083, "author": { - "login": "ktf" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/src/AODReaderHelpers.cxx" + "path": "Detectors/Raw/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/ResourcesMonitoringHelper.cxx" + "path": "Detectors/Raw/include/DetectorsRaw/RawFileWriter.h" } }, { "node": { - "path": "Framework/Core/src/ResourcesMonitoringHelper.h" + "path": "Detectors/Raw/src/RawFileWriter.cxx" } }, { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "Detectors/Raw/src/rawfileSplit.cxx" } } ] @@ -2855,17 +2725,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-15T08:48:19Z", - "title": "Analysis: extend histogram registry example", - "number": 5066, + "mergedAt": "2020-12-19T22:20:45Z", + "title": "Add X at minimum to v0data table", + "number": 5084, "author": { - "login": "mario-krueger" + "login": "ddobrigk" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tutorials/src/histogramRegistry.cxx" + "path": "Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx" } } ] @@ -2874,18 +2754,43 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-15T13:38:12Z", - "title": "Increase the margin of CTF block size to 10KB", - "number": 5067, + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF: Jpsi to e+e- task and candidate selection for HF", + "number": 5085, "author": { - "login": "shahor02" + "login": "zhangbiao-phy" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h" + "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + } + }, + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" } } ] @@ -2894,28 +2799,28 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-15T21:49:40Z", - "title": "DPL Analysis: make sure each hash in histogram registry is unique", - "number": 5068, + "state": "OPEN", + "mergedAt": null, + "title": "Use Dynamic columns for the expected PID signals", + "number": 5086, "author": { - "login": "mario-krueger" + "login": "njacazio" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/include/Framework/HistogramRegistry.h" + "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h" } }, { "node": { - "path": "Framework/Core/src/HistogramRegistry.cxx" + "path": "Analysis/Tasks/pidTOF.cxx" } }, { "node": { - "path": "Framework/Core/test/test_HistogramRegistry.cxx" + "path": "Analysis/Tasks/pidTPC.cxx" } } ] @@ -2924,83 +2829,123 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-28T13:55:03Z", - "title": "[WIP][ITS-tracking] Add track dumping in standalone debugger", - "number": 5069, + "state": "OPEN", + "mergedAt": null, + "title": "Bugfix in digits->raw->cell chain", + "number": 5087, "author": { - "login": "mconcas" + "login": "peressounko" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + "path": "Detectors/PHOS/base/include/PHOSBase/Mapping.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h" + "path": "Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + "path": "Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h" + "path": "Detectors/PHOS/base/src/Mapping.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + "path": "Detectors/PHOS/base/src/RCUTrailer.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "TRD tracklet calculation in TrapSimulator", - "number": 5070, - "author": { - "login": "martenole" - }, - "files": { - "edges": [ + }, { "node": { - "path": "DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h" + "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" } }, { "node": { - "path": "Detectors/TRD/macros/convertRun2ToRun3Digits.C" + "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" } }, { "node": { - "path": "Detectors/TRD/simulation/src/TrapSimulator.cxx" + "path": "Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/simulation/src/Detector.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/simulation/src/Digitizer.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/simulation/src/RawWriter.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/CellConverterSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/ClusterizerSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/PublisherSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx" } } ] @@ -3010,157 +2955,147 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-16T12:19:42Z", - "title": "DPL: initial support for plugin based algorithms", - "number": 5071, + "mergedAt": "2020-12-19T14:01:47Z", + "title": "MFT: fix lanes mapping for decoding commissionning data and for worki…", + "number": 5088, "author": { - "login": "ktf" + "login": "bovulpes" }, "files": { "edges": [ { "node": { - "path": "Framework/AnalysisSupport/CMakeLists.txt" + "path": "Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx" } }, { "node": { - "path": "Framework/AnalysisSupport/src/Plugin.cxx" + "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h" } }, { "node": { - "path": "Framework/CMakeLists.txt" + "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h" } }, { "node": { - "path": "Framework/Core/include/Framework/AlgorithmSpec.h" + "path": "Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/Plugins.h" + "path": "Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2020-12-22T21:07:34Z", + "title": "real LUT in CCDB", + "number": 5089, + "author": { + "login": "AllaMaevskaya" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/FIT/FT0/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/WorkflowHelpers.cxx" + "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "A ROOT serializable key-value store", - "number": 5072, - "author": { - "login": "sawenzel" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Common/Utils/CMakeLists.txt" + "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h" } }, { "node": { - "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" + "path": "DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h" } }, { "node": { - "path": "Common/Utils/src/CommonUtilsLinkDef.h" + "path": "Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt" } }, { "node": { - "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" + "path": "Detectors/FIT/FT0/base/files/Sim2DataChannels.txt" } }, { "node": { - "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" + "path": "Detectors/FIT/FT0/base/include/FT0Base/Geometry.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-16T16:28:44Z", - "title": "DPL: allow decoupling from JAlien and retrieve JAlienFile, if available", - "number": 5073, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/AnalysisSupport/CMakeLists.txt" + "path": "Detectors/FIT/FT0/base/src/Geometry.cxx" } }, { "node": { - "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" + "path": "Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h" } }, { "node": { - "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h" + "path": "Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx" } }, { "node": { - "path": "Framework/AnalysisSupport/src/Plugin.cxx" + "path": "Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h" } }, { "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/AODReaderHelpers.h" + "path": "Detectors/FIT/FT0/simulation/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/AODReaderHelpers.cxx" + "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h" } }, { "node": { - "path": "Framework/Core/src/AnalysisDataModelHelpers.cxx" + "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h" } }, { "node": { - "path": "Framework/Core/src/AnalysisDataModelHelpers.h" + "path": "Detectors/FIT/FT0/simulation/src/Detector.cxx" } }, { "node": { - "path": "dependencies/FindJAlienROOT.cmake" + "path": "Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx" } }, { "node": { - "path": "dependencies/FindXRootD.cmake" + "path": "Detectors/FIT/macros/CMakeLists.txt" } }, { "node": { - "path": "dependencies/O2Dependencies.cmake" + "path": "Detectors/FIT/macros/uploadLookUpTable.C" } } ] @@ -3171,26 +3106,21 @@ "node": { "state": "OPEN", "mergedAt": null, - "title": " Initial version of EMCAL Correction Task", - "number": 5074, + "title": "Add skeleton for DDbar analysis", + "number": 5090, "author": { - "login": "raymondEhlers" + "login": "ginnocen" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h" - } - }, - { - "node": { - "path": "Analysis/Tasks/CMakeLists.txt" + "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" } }, { "node": { - "path": "Analysis/Tasks/emcalCorrectionTask.cxx" + "path": "Analysis/Tasks/PWGHF/HFDDbar_corr.cxx" } } ] @@ -3199,43 +3129,33 @@ }, { "node": { - "state": "CLOSED", - "mergedAt": null, - "title": "Jpsi task and candidate selection", - "number": 5075, + "state": "MERGED", + "mergedAt": "2020-12-22T21:06:19Z", + "title": "MFT: eliminate sqrt where possible", + "number": 5091, "author": { - "login": "zhangbiao-phy" + "login": "bovulpes" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" - } - }, - { - "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + "path": "Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + "path": "Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx" } } ] @@ -3245,147 +3165,77 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-17T22:44:51Z", - "title": "[ITS][ntracker-workflow] Add --configKeyValue for MB LUT", - "number": 5076, + "mergedAt": "2020-12-23T21:37:54Z", + "title": "ZDC Workflow to inspect raw data", + "number": 5092, "author": { - "login": "mconcas" + "login": "cortesep" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + "path": "DataFormats/Detectors/ZDC/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h" + "path": "DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "DataFormats/Detectors/ZDC/src/RawEventData.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx" + "path": "Detectors/ZDC/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + "path": "Detectors/ZDC/base/src/ModuleConfig.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-17T19:07:38Z", - "title": "Tmp.fix in TrackParCov c-tor from Cartesian cov.matrix", - "number": 5077, - "author": { - "login": "shahor02" - }, - "files": { - "edges": [ - { - "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-17T22:22:35Z", - "title": "Parent TrackPar/Cov creator for DCAFitterN", - "number": 5078, - "author": { - "login": "shahor02" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h" + "path": "Detectors/ZDC/raw/CMakeLists.txt" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-17T22:27:23Z", - "title": "Fix FindJAliEnROOT.cmake name", - "number": 5079, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "dependencies/FindJAliEnROOT.cmake" + "path": "Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h" } - } - ] - } - } - }, - { - "node": { - "state": "CLOSED", - "mergedAt": null, - "title": "Jpsi task and candidate selection", - "number": 5080, - "author": { - "login": "zhangbiao-phy" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + "path": "Detectors/ZDC/raw/src/DumpRaw.cxx" } }, { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + "path": "Detectors/ZDC/raw/src/ZDCRawLinkDef.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "Detectors/ZDC/raw/src/raw-parser.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + "path": "Detectors/ZDC/simulation/CMakeLists.txt" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + "path": "Detectors/ZDC/simulation/src/Digitizer.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + "path": "Detectors/ZDC/simulation/src/digi2raw.cxx" } } ] @@ -3395,37 +3245,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-18T20:32:10Z", - "title": "DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support", - "number": 5081, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ - { - "node": { - "path": "Framework/AnalysisSupport/CMakeLists.txt" - } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Fill PDG code database before event generation", - "number": 5082, + "mergedAt": "2020-12-24T13:43:32Z", + "title": "GPU: Exclude ITS Tracking / Vertexing parts from run time compilation", + "number": 5093, "author": { - "login": "mpuccio" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Generators/src/GeneratorFactory.cxx" + "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" } } ] @@ -3435,32 +3265,32 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-23T00:45:23Z", - "title": "Executable for chunk large raw-data files", - "number": 5083, + "mergedAt": "2020-12-24T13:43:15Z", + "title": "GPU: Some work towards making the o2 propagator work on GPU", + "number": 5094, "author": { - "login": "shahor02" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Detectors/Raw/CMakeLists.txt" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h" } }, { "node": { - "path": "Detectors/Raw/include/DetectorsRaw/RawFileWriter.h" + "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" } }, { "node": { - "path": "Detectors/Raw/src/RawFileWriter.cxx" + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" } }, { "node": { - "path": "Detectors/Raw/src/rawfileSplit.cxx" + "path": "Detectors/Base/src/Propagator.cxx" } } ] @@ -3469,28 +3299,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-19T22:20:45Z", - "title": "Add X at minimum to v0data table", - "number": 5084, + "state": "OPEN", + "mergedAt": null, + "title": "Draft HFMCValidation Heavy Flavour Monte Carlo validation", + "number": 5095, "author": { - "login": "ddobrigk" + "login": "apalasciano" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx" + "path": "Analysis/Tasks/PWGHF/HFMCMatchingValidation.cxx" } } ] @@ -3499,43 +3319,43 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "PWGHF: Jpsi to e+e- task and candidate selection for HF", - "number": 5085, + "state": "MERGED", + "mergedAt": "2020-12-25T12:29:48Z", + "title": "Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU", + "number": 5096, "author": { - "login": "zhangbiao-phy" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" } }, { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + "path": "Detectors/Base/CMakeLists.txt" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + "path": "Detectors/Base/src/Propagator.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + "path": "GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h" } } ] @@ -3544,28 +3364,23 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Use Dynamic columns for the expected PID signals", - "number": 5086, + "state": "MERGED", + "mergedAt": "2020-12-25T12:43:43Z", + "title": "TPC Tracking: Workaround for 0-cluster tracks", + "number": 5097, "author": { - "login": "njacazio" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h" - } - }, - { - "node": { - "path": "Analysis/Tasks/pidTOF.cxx" + "path": "Detectors/TPC/reconstruction/src/GPUCATracking.cxx" } }, { "node": { - "path": "Analysis/Tasks/pidTPC.cxx" + "path": "GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx" } } ] @@ -3574,268 +3389,188 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Bugfix in digits->raw->cell chain", - "number": 5087, + "state": "MERGED", + "mergedAt": "2020-12-27T08:29:55Z", + "title": "DPL: use RawDeviceService to sleep in example", + "number": 5098, "author": { - "login": "peressounko" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/PHOS/base/include/PHOSBase/Mapping.h" - } - }, - { - "node": { - "path": "Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h" - } - }, - { - "node": { - "path": "Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h" - } - }, - { - "node": { - "path": "Detectors/PHOS/base/src/Mapping.cxx" - } - }, - { - "node": { - "path": "Detectors/PHOS/base/src/RCUTrailer.cxx" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx" + "path": "Framework/TestWorkflows/src/o2DiamondWorkflow.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T18:52:58Z", + "title": "DPL: move GUI to a plugin", + "number": 5099, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h" + "path": "Framework/CMakeLists.txt" } }, { "node": { - "path": "Detectors/PHOS/simulation/src/Digitizer.cxx" + "path": "Framework/Core/CMakeLists.txt" } }, { "node": { - "path": "Detectors/PHOS/simulation/src/RawWriter.cxx" + "path": "Framework/Core/include/Framework/DataProcessorInfo.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h" + "path": "Framework/Core/include/Framework/DebugGUI.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h" + "path": "Framework/Core/include/Framework/DriverControl.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/CellConverterSpec.cxx" + "path": "Framework/Core/include/Framework/DriverInfo.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/ClusterizerSpec.cxx" + "path": "Framework/Core/include/Framework/Plugins.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/PublisherSpec.cxx" + "path": "Framework/Core/src/DeviceSpecHelpers.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-19T14:01:47Z", - "title": "MFT: fix lanes mapping for decoding commissionning data and for worki…", - "number": 5088, - "author": { - "login": "bovulpes" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx" + "path": "Framework/Core/src/DriverControl.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h" + "path": "Framework/Core/src/DriverInfo.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h" + "path": "Framework/Core/src/FrameworkDummyDebugger.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx" + "path": "Framework/Core/src/WorkflowHelpers.h" } }, { "node": { - "path": "Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-22T21:07:34Z", - "title": "real LUT in CCDB", - "number": 5089, - "author": { - "login": "AllaMaevskaya" - }, - "files": { - "edges": [ - { - "node": { - "path": "DataFormats/Detectors/FIT/FT0/CMakeLists.txt" + "path": "Framework/Core/src/WorkflowSerializationHelpers.h" } }, { "node": { - "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h" + "path": "Framework/Core/src/runDataProcessing.cxx" } }, { "node": { - "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h" + "path": "Framework/GUISupport/CMakeLists.txt" } }, { "node": { - "path": "DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h" + "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt" + "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.h" } }, { "node": { - "path": "Detectors/FIT/FT0/base/files/Sim2DataChannels.txt" + "path": "Framework/GUISupport/src/FrameworkGUIDebugger.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/base/include/FT0Base/Geometry.h" + "path": "Framework/GUISupport/src/FrameworkGUIDebugger.h" } }, { "node": { - "path": "Detectors/FIT/FT0/base/src/Geometry.cxx" + "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h" + "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.h" } }, { "node": { - "path": "Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx" + "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h" + "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.h" } }, { "node": { - "path": "Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx" + "path": "Framework/GUISupport/src/FrameworkGUIState.h" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/CMakeLists.txt" + "path": "Framework/GUISupport/src/NoDebugGUI.h" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h" + "path": "Framework/GUISupport/src/PaletteHelpers.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h" + "path": "Framework/GUISupport/src/PaletteHelpers.h" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/src/Detector.cxx" + "path": "Framework/GUISupport/src/Plugin.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx" + "path": "Framework/GUISupport/test/test_CustomGUIGL.cxx" } }, { "node": { - "path": "Detectors/FIT/macros/CMakeLists.txt" + "path": "Framework/GUISupport/test/test_CustomGUISokol.cxx" } }, { "node": { - "path": "Detectors/FIT/macros/uploadLookUpTable.C" + "path": "Framework/GUISupport/test/test_SimpleTracksED.cxx" } } ] @@ -3844,23 +3579,23 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Add skeleton for DDbar analysis", - "number": 5090, + "state": "MERGED", + "mergedAt": "2020-12-28T10:37:16Z", + "title": "GPU: Make more headers compatible to GPU", + "number": 5100, "author": { - "login": "ginnocen" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFDDbar_corr.cxx" + "path": "DataFormats/common/include/CommonDataFormat/RangeReference.h" } } ] @@ -3870,32 +3605,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-22T21:06:19Z", - "title": "MFT: eliminate sqrt where possible", - "number": 5091, + "mergedAt": "2020-12-29T19:17:29Z", + "title": "[EMCAL-675] Handling of pages without trailer", + "number": 5101, "author": { - "login": "bovulpes" + "login": "mfasDa" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx" + "path": "Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx" } } ] @@ -3905,77 +3625,157 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-23T21:37:54Z", - "title": "ZDC Workflow to inspect raw data", - "number": 5092, + "mergedAt": "2020-12-29T09:49:03Z", + "title": "Drop bad assert", + "number": 5102, "author": { - "login": "cortesep" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/ZDC/CMakeLists.txt" - } - }, - { - "node": { - "path": "DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/ZDC/src/RawEventData.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "CTP Data structures development", + "number": 5103, + "author": { + "login": "lietava" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ZDC/CMakeLists.txt" + "path": "DataFormats/Detectors/CTP/CTPRawData.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T08:36:57Z", + "title": "Use DBSCAN for Time-Z clustering in PVertexing, debris reduction", + "number": 5104, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ZDC/base/src/ModuleConfig.cxx" + "path": "DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h" } }, { "node": { - "path": "Detectors/ZDC/raw/CMakeLists.txt" + "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h" } }, { "node": { - "path": "Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h" + "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h" } }, { "node": { - "path": "Detectors/ZDC/raw/src/DumpRaw.cxx" + "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h" } }, { "node": { - "path": "Detectors/ZDC/raw/src/ZDCRawLinkDef.h" + "path": "Detectors/Vertexing/src/PVertexer.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T11:22:50Z", + "title": "Disable CA_DEBUG in ITS Tracking", + "number": 5105, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ZDC/raw/src/raw-parser.cxx" + "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T09:27:57Z", + "title": "Add workflow to generate CHANGELOG", + "number": 5106, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ZDC/simulation/CMakeLists.txt" + "path": ".github/workflows/reports.yml" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T09:51:49Z", + "title": "Fix changelog generation", + "number": 5107, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ZDC/simulation/src/Digitizer.cxx" + "path": ".github/workflows/reports.yml" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-04T10:17:44Z", + "title": "Fix CHANGELOG generation", + "number": 5108, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ZDC/simulation/src/digi2raw.cxx" + "path": ".github/workflows/reports.yml" } } ] @@ -3985,17 +3785,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-24T13:43:32Z", - "title": "GPU: Exclude ITS Tracking / Vertexing parts from run time compilation", - "number": 5093, + "mergedAt": "2021-01-04T10:34:21Z", + "title": "Fix CHANGELOG generation", + "number": 5109, "author": { - "login": "davidrohr" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + "path": ".github/workflows/reports.yml" } } ] @@ -4005,32 +3805,57 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-24T13:43:15Z", - "title": "GPU: Some work towards making the o2 propagator work on GPU", - "number": 5094, + "mergedAt": "2021-01-04T10:46:11Z", + "title": "Update CHANGELOG", + "number": 5110, "author": { - "login": "davidrohr" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h" + "path": "CHANGELOG.md" } }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" + "path": "doc/data/2021-01-o2_prs.json" } }, { "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + "path": "doc/data/2021-01-o2_releases.json" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Rdev tof updates", + "number": 5111, + "author": { + "login": "preghenella" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/TOF/compression/src/tof-compressed-analysis.cxx" } }, { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Detectors/TOF/compression/src/tof-compressed-inspector.cxx" + } + }, + { + "node": { + "path": "Detectors/TOF/workflow/src/CompressedInspectorTask.cxx" } } ] @@ -4039,18 +3864,18 @@ }, { "node": { - "state": "OPEN", + "state": "CLOSED", "mergedAt": null, - "title": "Draft HFMCValidation Heavy Flavour Monte Carlo validation", - "number": 5095, + "title": "Drop cstdio include in GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx", + "number": 5112, "author": { - "login": "apalasciano" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/HFMCMatchingValidation.cxx" + "path": "GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx" } } ] @@ -4060,42 +3885,67 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-25T12:29:48Z", - "title": "Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU", - "number": 5096, + "mergedAt": "2021-01-04T16:39:30Z", + "title": "DPL: drop unneeded include statements", + "number": 5113, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ + { + "node": { + "path": "Framework/Core/include/Framework/DataProcessingHeader.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/SourceInfoHeader.h" + } + }, + { + "node": { + "path": "Framework/Foundation/include/Framework/Pack.h" + } + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Rdev evgen updates", + "number": 5114, "author": { - "login": "davidrohr" + "login": "preghenella" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" - } - }, - { - "node": { - "path": "Detectors/Base/CMakeLists.txt" + "path": "Generators/include/Generators/Generator.h" } }, { "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + "path": "Generators/include/Generators/GeneratorHepMC.h" } }, { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Generators/include/Generators/GeneratorPythia8.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + "path": "Generators/include/Generators/GeneratorTGenerator.h" } }, { "node": { - "path": "GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h" + "path": "Generators/src/GeneratorPythia8.cxx" } } ] @@ -4105,9 +3955,9 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-25T12:43:43Z", - "title": "TPC Tracking: Workaround for 0-cluster tracks", - "number": 5097, + "mergedAt": "2021-01-04T18:56:01Z", + "title": "Some minor improvements for GPU code", + "number": 5115, "author": { "login": "davidrohr" }, @@ -4115,32 +3965,27 @@ "edges": [ { "node": { - "path": "Detectors/TPC/reconstruction/src/GPUCATracking.cxx" + "path": "GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu" } }, { "node": { - "path": "GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx" + "path": "GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-27T08:29:55Z", - "title": "DPL: use RawDeviceService to sleep in example", - "number": 5098, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/TestWorkflows/src/o2DiamondWorkflow.cxx" + "path": "GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" } } ] @@ -4149,168 +3994,178 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "DPL: move GUI to a plugin", - "number": 5099, + "state": "MERGED", + "mergedAt": "2021-01-05T09:40:39Z", + "title": "Global (currently TPC only) refit on GPU using either GPU or TrackParCov track model", + "number": 5116, "author": { - "login": "ktf" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Framework/CMakeLists.txt" - } - }, - { - "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" } }, { "node": { - "path": "Framework/Core/include/Framework/DataProcessorInfo.h" + "path": "Detectors/Base/src/Propagator.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/DebugGUI.h" + "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/DriverControl.h" + "path": "GPU/Common/GPUDefGPUParameters.h" } }, { "node": { - "path": "Framework/Core/include/Framework/DriverInfo.h" + "path": "GPU/GPUTracking/Base/GPUConstantMem.h" } }, { "node": { - "path": "Framework/Core/include/Framework/Plugins.h" + "path": "GPU/GPUTracking/Base/GPUDataTypes.h" } }, { "node": { - "path": "Framework/Core/src/DeviceSpecHelpers.h" + "path": "GPU/GPUTracking/Base/GPUO2DataTypes.h" } }, { "node": { - "path": "Framework/Core/src/DriverControl.cxx" + "path": "GPU/GPUTracking/Base/GPUO2FakeClasses.h" } }, { "node": { - "path": "Framework/Core/src/DriverInfo.cxx" + "path": "GPU/GPUTracking/Base/GPUParam.cxx" } }, { "node": { - "path": "Framework/Core/src/FrameworkDummyDebugger.cxx" + "path": "GPU/GPUTracking/Base/GPUParam.h" } }, { "node": { - "path": "Framework/Core/src/WorkflowHelpers.h" + "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.h" } }, { "node": { - "path": "Framework/Core/src/WorkflowSerializationHelpers.h" + "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" } }, { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "GPU/GPUTracking/Base/GPUReconstructionKernels.h" } }, { "node": { - "path": "Framework/GUISupport/CMakeLists.txt" + "path": "GPU/GPUTracking/Base/GPUSettingsList.h" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.cxx" + "path": "GPU/GPUTracking/CMakeLists.txt" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.h" + "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDebugger.cxx" + "path": "GPU/GPUTracking/Global/GPUChainTracking.h" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDebugger.h" + "path": "GPU/GPUTracking/Interface/GPUO2Interface.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx" + "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.h" + "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.h" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx" + "path": "GPU/GPUTracking/Refit/GPUTrackingRefitKernel.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.h" + "path": "GPU/GPUTracking/Refit/GPUTrackingRefitKernel.h" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIState.h" + "path": "GPU/GPUTracking/Standalone/standalone.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/NoDebugGUI.h" + "path": "GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/PaletteHelpers.cxx" + "path": "GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-05T09:41:01Z", + "title": "GPU: Add option for the GPU backend to use nested OpenMP loops for better parallelism", + "number": 5117, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/GUISupport/src/PaletteHelpers.h" + "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/Plugin.cxx" + "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.h" } }, { "node": { - "path": "Framework/GUISupport/test/test_CustomGUIGL.cxx" + "path": "GPU/GPUTracking/Base/GPUSettingsList.h" } }, { "node": { - "path": "Framework/GUISupport/test/test_CustomGUISokol.cxx" + "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" } }, { "node": { - "path": "Framework/GUISupport/test/test_SimpleTracksED.cxx" + "path": "GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx" } } ] @@ -4320,22 +4175,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-28T10:37:16Z", - "title": "GPU: Make more headers compatible to GPU", - "number": 5100, + "mergedAt": "2021-01-04T21:48:17Z", + "title": "Default mat.corr. is with LUT, fall-back to TGeo if LUT is not set", + "number": 5118, "author": { - "login": "davidrohr" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h" + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" } }, { "node": { - "path": "DataFormats/common/include/CommonDataFormat/RangeReference.h" + "path": "Detectors/Base/src/Propagator.cxx" } } ] @@ -4344,18 +4199,23 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-29T19:17:29Z", - "title": "[EMCAL-675] Handling of pages without trailer", - "number": 5101, + "state": "OPEN", + "mergedAt": null, + "title": "Updated CHANGELOG", + "number": 5119, "author": { - "login": "mfasDa" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx" + "path": "CHANGELOG.md" + } + }, + { + "node": { + "path": "doc/data/2021-01-o2_prs.json" } } ] @@ -4364,18 +4224,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-29T09:49:03Z", - "title": "Drop bad assert", - "number": 5102, + "state": "OPEN", + "mergedAt": null, + "title": "Correctly use object passed to MID decoder constructor", + "number": 5120, "author": { - "login": "ktf" + "login": "dstocco" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/MUON/MID/Raw/src/Decoder.cxx" } } ] @@ -4386,16 +4246,21 @@ "node": { "state": "OPEN", "mergedAt": null, - "title": "CTP Data structures development", - "number": 5103, + "title": "Match all subspecs unless one subspec is passed explicitely", + "number": 5121, "author": { - "login": "lietava" + "login": "dstocco" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/CTP/CTPRawData.h" + "path": "Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h" + } + }, + { + "node": { + "path": "Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx" } } ] @@ -4404,118 +4269,83 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T08:36:57Z", - "title": "Use DBSCAN for Time-Z clustering in PVertexing, debris reduction", - "number": 5104, + "state": "OPEN", + "mergedAt": null, + "title": "Fix codechecker violations", + "number": 5122, "author": { - "login": "shahor02" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h" + "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h" } }, { "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h" + "path": "Detectors/PHOS/base/src/Mapping.cxx" } }, { "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h" + "path": "Detectors/PHOS/reconstruction/src/Bunch.cxx" } }, { "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h" + "path": "Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx" } }, { "node": { - "path": "Detectors/Vertexing/src/PVertexer.cxx" + "path": "Detectors/PHOS/reconstruction/src/Channel.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Disable CA_DEBUG in ITS Tracking", - "number": 5105, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + "path": "Detectors/PHOS/reconstruction/src/RawBuffer.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T09:27:57Z", - "title": "Add workflow to generate CHANGELOG", - "number": 5106, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": ".github/workflows/reports.yml" + "path": "Detectors/PHOS/reconstruction/src/RawPayload.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T09:51:49Z", - "title": "Fix changelog generation", - "number": 5107, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": ".github/workflows/reports.yml" + "path": "Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T10:17:44Z", - "title": "Fix CHANGELOG generation", - "number": 5108, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": ".github/workflows/reports.yml" + "path": "Detectors/ZDC/raw/src/DumpRaw.cxx" + } + }, + { + "node": { + "path": "Detectors/ZDC/raw/src/raw-parser.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h" + } + }, + { + "node": { + "path": "Utilities/Tools/cpulimit/cpulimit.c" + } + }, + { + "node": { + "path": "Utilities/Tools/cpulimit/list.c" } } ] @@ -4525,9 +4355,9 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T10:34:21Z", - "title": "Fix CHANGELOG generation", - "number": 5109, + "mergedAt": "2021-01-05T14:19:35Z", + "title": "Allow forcing by hand last release tag", + "number": 5123, "author": { "login": "ktf" }, From 1d46947f2ed2809af504c869bb6210f8f6cf86f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Tue, 5 Jan 2021 17:42:13 +0100 Subject: [PATCH 1694/1751] Use Dynamic columns for the expected PID signals (#5086) --- .../AnalysisDataModel/PID/PIDResponse.h | 78 +++++++++++------ Analysis/Tasks/pidTOF.cxx | 83 ++++++++----------- Analysis/Tasks/pidTPC.cxx | 82 +++++++----------- 3 files changed, 120 insertions(+), 123 deletions(-) diff --git a/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h index aaf6143cc35b7..9b9395e084a85 100644 --- a/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h @@ -43,15 +43,15 @@ DECLARE_SOA_DYNAMIC_COLUMN(DiffBetaEl, diffbetael, [](float beta, float expbetae namespace pidtof { // Expected times -DECLARE_SOA_COLUMN(TOFExpSignalEl, tofExpSignalEl, float); -DECLARE_SOA_COLUMN(TOFExpSignalMu, tofExpSignalMu, float); -DECLARE_SOA_COLUMN(TOFExpSignalPi, tofExpSignalPi, float); -DECLARE_SOA_COLUMN(TOFExpSignalKa, tofExpSignalKa, float); -DECLARE_SOA_COLUMN(TOFExpSignalPr, tofExpSignalPr, float); -DECLARE_SOA_COLUMN(TOFExpSignalDe, tofExpSignalDe, float); -DECLARE_SOA_COLUMN(TOFExpSignalTr, tofExpSignalTr, float); -DECLARE_SOA_COLUMN(TOFExpSignalHe, tofExpSignalHe, float); -DECLARE_SOA_COLUMN(TOFExpSignalAl, tofExpSignalAl, float); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffEl, tofExpSignalDiffEl, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffMu, tofExpSignalDiffMu, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffPi, tofExpSignalDiffPi, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffKa, tofExpSignalDiffKa, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffPr, tofExpSignalDiffPr, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffDe, tofExpSignalDiffDe, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffTr, tofExpSignalDiffTr, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffHe, tofExpSignalDiffHe, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffAl, tofExpSignalDiffAl, [](float nsigma, float sigma) { return nsigma * sigma; }); // Expected sigma DECLARE_SOA_COLUMN(TOFExpSigmaEl, tofExpSigmaEl, float); DECLARE_SOA_COLUMN(TOFExpSigmaMu, tofExpSigmaMu, float); @@ -82,22 +82,37 @@ DECLARE_SOA_TABLE(pidRespTOFbeta, "AOD", "pidRespTOFbeta", DiffBetaEl<Beta, ExpBetaEl>); using namespace pidtof; DECLARE_SOA_TABLE(pidRespTOF, "AOD", "pidRespTOF", - TOFExpSignalEl, TOFExpSignalMu, TOFExpSignalPi, TOFExpSignalKa, TOFExpSignalPr, TOFExpSignalDe, TOFExpSignalTr, TOFExpSignalHe, TOFExpSignalAl, - TOFExpSigmaEl, TOFExpSigmaMu, TOFExpSigmaPi, TOFExpSigmaKa, TOFExpSigmaPr, TOFExpSigmaDe, TOFExpSigmaTr, TOFExpSigmaHe, TOFExpSigmaAl, - TOFNSigmaEl, TOFNSigmaMu, TOFNSigmaPi, TOFNSigmaKa, TOFNSigmaPr, TOFNSigmaDe, TOFNSigmaTr, TOFNSigmaHe, TOFNSigmaAl); + // Expected signals + TOFExpSignalDiffEl<TOFNSigmaEl, TOFExpSigmaEl>, + TOFExpSignalDiffMu<TOFNSigmaMu, TOFExpSigmaMu>, + TOFExpSignalDiffPi<TOFNSigmaPi, TOFExpSigmaPi>, + TOFExpSignalDiffKa<TOFNSigmaKa, TOFExpSigmaKa>, + TOFExpSignalDiffPr<TOFNSigmaPr, TOFExpSigmaPr>, + TOFExpSignalDiffDe<TOFNSigmaDe, TOFExpSigmaDe>, + TOFExpSignalDiffTr<TOFNSigmaTr, TOFExpSigmaTr>, + TOFExpSignalDiffHe<TOFNSigmaHe, TOFExpSigmaHe>, + TOFExpSignalDiffAl<TOFNSigmaAl, TOFExpSigmaAl>, + // Expected sigma + TOFExpSigmaEl, TOFExpSigmaMu, TOFExpSigmaPi, + TOFExpSigmaKa, TOFExpSigmaPr, TOFExpSigmaDe, + TOFExpSigmaTr, TOFExpSigmaHe, TOFExpSigmaAl, + // NSigma + TOFNSigmaEl, TOFNSigmaMu, TOFNSigmaPi, + TOFNSigmaKa, TOFNSigmaPr, TOFNSigmaDe, + TOFNSigmaTr, TOFNSigmaHe, TOFNSigmaAl); namespace pidtpc { // Expected signals -DECLARE_SOA_COLUMN(TPCExpSignalEl, tpcExpSignalEl, float); -DECLARE_SOA_COLUMN(TPCExpSignalMu, tpcExpSignalMu, float); -DECLARE_SOA_COLUMN(TPCExpSignalPi, tpcExpSignalPi, float); -DECLARE_SOA_COLUMN(TPCExpSignalKa, tpcExpSignalKa, float); -DECLARE_SOA_COLUMN(TPCExpSignalPr, tpcExpSignalPr, float); -DECLARE_SOA_COLUMN(TPCExpSignalDe, tpcExpSignalDe, float); -DECLARE_SOA_COLUMN(TPCExpSignalTr, tpcExpSignalTr, float); -DECLARE_SOA_COLUMN(TPCExpSignalHe, tpcExpSignalHe, float); -DECLARE_SOA_COLUMN(TPCExpSignalAl, tpcExpSignalAl, float); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffEl, tpcExpSignalDiffEl, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffMu, tpcExpSignalDiffMu, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffPi, tpcExpSignalDiffPi, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffKa, tpcExpSignalDiffKa, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffPr, tpcExpSignalDiffPr, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffDe, tpcExpSignalDiffDe, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffTr, tpcExpSignalDiffTr, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffHe, tpcExpSignalDiffHe, [](float nsigma, float sigma) { return nsigma * sigma; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffAl, tpcExpSignalDiffAl, [](float nsigma, float sigma) { return nsigma * sigma; }); // Expected sigma DECLARE_SOA_COLUMN(TPCExpSigmaEl, tpcExpSigmaEl, float); DECLARE_SOA_COLUMN(TPCExpSigmaMu, tpcExpSigmaMu, float); @@ -122,9 +137,24 @@ DECLARE_SOA_COLUMN(TPCNSigmaAl, tpcNSigmaAl, float); using namespace pidtpc; DECLARE_SOA_TABLE(pidRespTPC, "AOD", "pidRespTPC", - TPCExpSignalEl, TPCExpSignalMu, TPCExpSignalPi, TPCExpSignalKa, TPCExpSignalPr, TPCExpSignalDe, TPCExpSignalTr, TPCExpSignalHe, TPCExpSignalAl, - TPCExpSigmaEl, TPCExpSigmaMu, TPCExpSigmaPi, TPCExpSigmaKa, TPCExpSigmaPr, TPCExpSigmaDe, TPCExpSigmaTr, TPCExpSigmaHe, TPCExpSigmaAl, - TPCNSigmaEl, TPCNSigmaMu, TPCNSigmaPi, TPCNSigmaKa, TPCNSigmaPr, TPCNSigmaDe, TPCNSigmaTr, TPCNSigmaHe, TPCNSigmaAl); + // Expected signals + TPCExpSignalDiffEl<TPCNSigmaEl, TPCExpSigmaEl>, + TPCExpSignalDiffMu<TPCNSigmaMu, TPCExpSigmaMu>, + TPCExpSignalDiffPi<TPCNSigmaPi, TPCExpSigmaPi>, + TPCExpSignalDiffKa<TPCNSigmaKa, TPCExpSigmaKa>, + TPCExpSignalDiffPr<TPCNSigmaPr, TPCExpSigmaPr>, + TPCExpSignalDiffDe<TPCNSigmaDe, TPCExpSigmaDe>, + TPCExpSignalDiffTr<TPCNSigmaTr, TPCExpSigmaTr>, + TPCExpSignalDiffHe<TPCNSigmaHe, TPCExpSigmaHe>, + TPCExpSignalDiffAl<TPCNSigmaAl, TPCExpSigmaAl>, + // Expected sigma + TPCExpSigmaEl, TPCExpSigmaMu, TPCExpSigmaPi, + TPCExpSigmaKa, TPCExpSigmaPr, TPCExpSigmaDe, + TPCExpSigmaTr, TPCExpSigmaHe, TPCExpSigmaAl, + // NSigma + TPCNSigmaEl, TPCNSigmaMu, TPCNSigmaPi, + TPCNSigmaKa, TPCNSigmaPr, TPCNSigmaDe, + TPCNSigmaTr, TPCNSigmaHe, TPCNSigmaAl); } // namespace o2::aod diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index dfd01389fb2a7..63e0ee7ccd197 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -65,7 +65,7 @@ struct pidTOFTask { } } - void process(Coll const& collision, Trks const& tracks) + void process(Trks const& tracks) { constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Electron> resp_Electron = tof::ExpTimes<Coll, Trks::iterator, PID::Electron>(); constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Muon> resp_Muon = tof::ExpTimes<Coll, Trks::iterator, PID::Muon>(); @@ -79,33 +79,24 @@ struct pidTOFTask { tofpid.reserve(tracks.size()); for (auto const& trk : tracks) { - tofpid(resp_Electron.GetExpectedSignal(collision, trk), - resp_Muon.GetExpectedSignal(collision, trk), - resp_Pion.GetExpectedSignal(collision, trk), - resp_Kaon.GetExpectedSignal(collision, trk), - resp_Proton.GetExpectedSignal(collision, trk), - resp_Deuteron.GetExpectedSignal(collision, trk), - resp_Triton.GetExpectedSignal(collision, trk), - resp_Helium3.GetExpectedSignal(collision, trk), - resp_Alpha.GetExpectedSignal(collision, trk), - resp_Electron.GetExpectedSigma(resp, collision, trk), - resp_Muon.GetExpectedSigma(resp, collision, trk), - resp_Pion.GetExpectedSigma(resp, collision, trk), - resp_Kaon.GetExpectedSigma(resp, collision, trk), - resp_Proton.GetExpectedSigma(resp, collision, trk), - resp_Deuteron.GetExpectedSigma(resp, collision, trk), - resp_Triton.GetExpectedSigma(resp, collision, trk), - resp_Helium3.GetExpectedSigma(resp, collision, trk), - resp_Alpha.GetExpectedSigma(resp, collision, trk), - resp_Electron.GetSeparation(resp, collision, trk), - resp_Muon.GetSeparation(resp, collision, trk), - resp_Pion.GetSeparation(resp, collision, trk), - resp_Kaon.GetSeparation(resp, collision, trk), - resp_Proton.GetSeparation(resp, collision, trk), - resp_Deuteron.GetSeparation(resp, collision, trk), - resp_Triton.GetSeparation(resp, collision, trk), - resp_Helium3.GetSeparation(resp, collision, trk), - resp_Alpha.GetSeparation(resp, collision, trk)); + tofpid(resp_Electron.GetExpectedSigma(resp, trk.collision(), trk), + resp_Muon.GetExpectedSigma(resp, trk.collision(), trk), + resp_Pion.GetExpectedSigma(resp, trk.collision(), trk), + resp_Kaon.GetExpectedSigma(resp, trk.collision(), trk), + resp_Proton.GetExpectedSigma(resp, trk.collision(), trk), + resp_Deuteron.GetExpectedSigma(resp, trk.collision(), trk), + resp_Triton.GetExpectedSigma(resp, trk.collision(), trk), + resp_Helium3.GetExpectedSigma(resp, trk.collision(), trk), + resp_Alpha.GetExpectedSigma(resp, trk.collision(), trk), + resp_Electron.GetSeparation(resp, trk.collision(), trk), + resp_Muon.GetSeparation(resp, trk.collision(), trk), + resp_Pion.GetSeparation(resp, trk.collision(), trk), + resp_Kaon.GetSeparation(resp, trk.collision(), trk), + resp_Proton.GetSeparation(resp, trk.collision(), trk), + resp_Deuteron.GetSeparation(resp, trk.collision(), trk), + resp_Triton.GetSeparation(resp, trk.collision(), trk), + resp_Helium3.GetSeparation(resp, trk.collision(), trk), + resp_Alpha.GetSeparation(resp, trk.collision(), trk)); } } }; @@ -211,11 +202,11 @@ struct pidTOFTaskQA { } template <uint8_t i, typename T> - void fillParticleHistos(const T& t, const float tof, const float exp[], const float nsigma[]) + void fillParticleHistos(const T& t, const float tof, const float exp_diff, const float nsigma) { - histos.fill(HIST(hexpected[i]), t.p(), exp[i]); - histos.fill(HIST(hexpected_diff[i]), t.p(), tof - exp[i]); - histos.fill(HIST(hnsigma[i]), t.p(), nsigma[i]); + histos.fill(HIST(hexpected[i]), t.p(), tof - exp_diff); + histos.fill(HIST(hexpected_diff[i]), t.p(), exp_diff); + histos.fill(HIST(hnsigma[i]), t.p(), nsigma); } void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTOF, aod::pidRespTOFbeta> const& tracks) @@ -229,28 +220,22 @@ struct pidTOFTaskQA { if (t.tofSignal() < 0) { // Skipping tracks without TOF continue; } + const float tof = t.tofSignal() - collisionTime_ps; + // histos.fill(HIST("event/tofsignal"), t.p(), t.tofSignal()); histos.fill(HIST("event/tofbeta"), t.p(), t.beta()); // - const float exp[Np] = {t.tofExpSignalEl(), t.tofExpSignalMu(), t.tofExpSignalPi(), - t.tofExpSignalKa(), t.tofExpSignalPr(), t.tofExpSignalDe(), - t.tofExpSignalTr(), t.tofExpSignalHe(), t.tofExpSignalAl()}; - // - const float nsigma[Np] = {t.tofNSigmaEl(), t.tofNSigmaMu(), t.tofNSigmaPi(), - t.tofNSigmaKa(), t.tofNSigmaPr(), t.tofNSigmaDe(), - t.tofNSigmaTr(), t.tofNSigmaHe(), t.tofNSigmaAl()}; - // - fillParticleHistos<0>(t, tof, exp, nsigma); - fillParticleHistos<1>(t, tof, exp, nsigma); - fillParticleHistos<2>(t, tof, exp, nsigma); - fillParticleHistos<3>(t, tof, exp, nsigma); - fillParticleHistos<4>(t, tof, exp, nsigma); - fillParticleHistos<5>(t, tof, exp, nsigma); - fillParticleHistos<6>(t, tof, exp, nsigma); - fillParticleHistos<7>(t, tof, exp, nsigma); - fillParticleHistos<8>(t, tof, exp, nsigma); + fillParticleHistos<0>(t, tof, t.tofExpSignalDiffEl(), t.tofNSigmaEl()); + fillParticleHistos<1>(t, tof, t.tofExpSignalDiffMu(), t.tofNSigmaMu()); + fillParticleHistos<2>(t, tof, t.tofExpSignalDiffPi(), t.tofNSigmaPi()); + fillParticleHistos<3>(t, tof, t.tofExpSignalDiffKa(), t.tofNSigmaKa()); + fillParticleHistos<4>(t, tof, t.tofExpSignalDiffPr(), t.tofNSigmaPr()); + fillParticleHistos<5>(t, tof, t.tofExpSignalDiffDe(), t.tofNSigmaDe()); + fillParticleHistos<6>(t, tof, t.tofExpSignalDiffTr(), t.tofNSigmaTr()); + fillParticleHistos<7>(t, tof, t.tofExpSignalDiffHe(), t.tofNSigmaHe()); + fillParticleHistos<8>(t, tof, t.tofExpSignalDiffAl(), t.tofNSigmaAl()); } } }; diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index 815d666085a3b..bfa007e44bd8c 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -65,7 +65,7 @@ struct pidTPCTask { } } - void process(Coll const& collision, Trks const& tracks) + void process(Trks const& tracks) { constexpr tpc::ELoss<Coll, Trks::iterator, PID::Electron> resp_Electron = tpc::ELoss<Coll, Trks::iterator, PID::Electron>(); constexpr tpc::ELoss<Coll, Trks::iterator, PID::Muon> resp_Muon = tpc::ELoss<Coll, Trks::iterator, PID::Muon>(); @@ -79,34 +79,24 @@ struct pidTPCTask { tpcpid.reserve(tracks.size()); for (auto const& trk : tracks) { - tpcpid( - resp_Electron.GetExpectedSignal(resp, collision, trk), - resp_Muon.GetExpectedSignal(resp, collision, trk), - resp_Pion.GetExpectedSignal(resp, collision, trk), - resp_Kaon.GetExpectedSignal(resp, collision, trk), - resp_Proton.GetExpectedSignal(resp, collision, trk), - resp_Deuteron.GetExpectedSignal(resp, collision, trk), - resp_Triton.GetExpectedSignal(resp, collision, trk), - resp_Helium3.GetExpectedSignal(resp, collision, trk), - resp_Alpha.GetExpectedSignal(resp, collision, trk), - resp_Electron.GetExpectedSigma(resp, collision, trk), - resp_Muon.GetExpectedSigma(resp, collision, trk), - resp_Pion.GetExpectedSigma(resp, collision, trk), - resp_Kaon.GetExpectedSigma(resp, collision, trk), - resp_Proton.GetExpectedSigma(resp, collision, trk), - resp_Deuteron.GetExpectedSigma(resp, collision, trk), - resp_Triton.GetExpectedSigma(resp, collision, trk), - resp_Helium3.GetExpectedSigma(resp, collision, trk), - resp_Alpha.GetExpectedSigma(resp, collision, trk), - resp_Electron.GetSeparation(resp, collision, trk), - resp_Muon.GetSeparation(resp, collision, trk), - resp_Pion.GetSeparation(resp, collision, trk), - resp_Kaon.GetSeparation(resp, collision, trk), - resp_Proton.GetSeparation(resp, collision, trk), - resp_Deuteron.GetSeparation(resp, collision, trk), - resp_Triton.GetSeparation(resp, collision, trk), - resp_Helium3.GetSeparation(resp, collision, trk), - resp_Alpha.GetSeparation(resp, collision, trk)); + tpcpid(resp_Electron.GetExpectedSigma(resp, trk.collision(), trk), + resp_Muon.GetExpectedSigma(resp, trk.collision(), trk), + resp_Pion.GetExpectedSigma(resp, trk.collision(), trk), + resp_Kaon.GetExpectedSigma(resp, trk.collision(), trk), + resp_Proton.GetExpectedSigma(resp, trk.collision(), trk), + resp_Deuteron.GetExpectedSigma(resp, trk.collision(), trk), + resp_Triton.GetExpectedSigma(resp, trk.collision(), trk), + resp_Helium3.GetExpectedSigma(resp, trk.collision(), trk), + resp_Alpha.GetExpectedSigma(resp, trk.collision(), trk), + resp_Electron.GetSeparation(resp, trk.collision(), trk), + resp_Muon.GetSeparation(resp, trk.collision(), trk), + resp_Pion.GetSeparation(resp, trk.collision(), trk), + resp_Kaon.GetSeparation(resp, trk.collision(), trk), + resp_Proton.GetSeparation(resp, trk.collision(), trk), + resp_Deuteron.GetSeparation(resp, trk.collision(), trk), + resp_Triton.GetSeparation(resp, trk.collision(), trk), + resp_Helium3.GetSeparation(resp, trk.collision(), trk), + resp_Alpha.GetSeparation(resp, trk.collision(), trk)); } } }; @@ -183,11 +173,11 @@ struct pidTPCTaskQA { } template <uint8_t i, typename T> - void fillParticleHistos(const T& t, const float mom, const float exp[], const float nsigma[]) + void fillParticleHistos(const T& t, const float mom, const float exp_diff, const float nsigma) { - histos.fill(HIST(hexpected[i]), mom, exp[i]); - histos.fill(HIST(hexpected_diff[i]), mom, t.tpcSignal() - exp[i]); - histos.fill(HIST(hnsigma[i]), t.p(), nsigma[i]); + histos.fill(HIST(hexpected[i]), mom, t.tpcSignal() - exp_diff); + histos.fill(HIST(hexpected_diff[i]), mom, exp_diff); + histos.fill(HIST(hnsigma[i]), t.p(), nsigma); } void process(aod::Collision const& collision, soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC> const& tracks) @@ -199,23 +189,15 @@ struct pidTPCTaskQA { const float mom = t.tpcInnerParam(); histos.fill(HIST("event/tpcsignal"), mom, t.tpcSignal()); // - const float exp[Np] = {t.tpcExpSignalEl(), t.tpcExpSignalMu(), t.tpcExpSignalPi(), - t.tpcExpSignalKa(), t.tpcExpSignalPr(), t.tpcExpSignalDe(), - t.tpcExpSignalTr(), t.tpcExpSignalHe(), t.tpcExpSignalAl()}; - // - const float nsigma[Np] = {t.tpcNSigmaEl(), t.tpcNSigmaMu(), t.tpcNSigmaPi(), - t.tpcNSigmaKa(), t.tpcNSigmaPr(), t.tpcNSigmaDe(), - t.tpcNSigmaTr(), t.tpcNSigmaHe(), t.tpcNSigmaAl()}; - // - fillParticleHistos<0>(t, mom, exp, nsigma); - fillParticleHistos<1>(t, mom, exp, nsigma); - fillParticleHistos<2>(t, mom, exp, nsigma); - fillParticleHistos<3>(t, mom, exp, nsigma); - fillParticleHistos<4>(t, mom, exp, nsigma); - fillParticleHistos<5>(t, mom, exp, nsigma); - fillParticleHistos<6>(t, mom, exp, nsigma); - fillParticleHistos<7>(t, mom, exp, nsigma); - fillParticleHistos<8>(t, mom, exp, nsigma); + fillParticleHistos<0>(t, mom, t.tpcExpSignalDiffEl(), t.tpcNSigmaEl()); + fillParticleHistos<1>(t, mom, t.tpcExpSignalDiffMu(), t.tpcNSigmaMu()); + fillParticleHistos<2>(t, mom, t.tpcExpSignalDiffPi(), t.tpcNSigmaPi()); + fillParticleHistos<3>(t, mom, t.tpcExpSignalDiffKa(), t.tpcNSigmaKa()); + fillParticleHistos<4>(t, mom, t.tpcExpSignalDiffPr(), t.tpcNSigmaPr()); + fillParticleHistos<5>(t, mom, t.tpcExpSignalDiffDe(), t.tpcNSigmaDe()); + fillParticleHistos<6>(t, mom, t.tpcExpSignalDiffTr(), t.tpcNSigmaTr()); + fillParticleHistos<7>(t, mom, t.tpcExpSignalDiffHe(), t.tpcNSigmaHe()); + fillParticleHistos<8>(t, mom, t.tpcExpSignalDiffAl(), t.tpcNSigmaAl()); } } }; From 943f549cae4c9804701382ca2ecbdd08eb3b74ac Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 30 Nov 2020 20:49:49 +0100 Subject: [PATCH 1695/1751] A ROOT serializable key-value store Basically a container mapping a string key to arbitrary values. A bit like boost-property (tree) but ROOT serializable. This may be useful in various circumenstances, for instance to assemble various CCDB objects into a single aggregate to reduce the number of CCDB files/entries. A new quality is that one can serialize ordinary POD types under a key which is not possible in ROOT by default (hard to serialize a simple double under a file key). --- Common/Utils/CMakeLists.txt | 11 +- .../RootSerializableKeyValueStore.h | 225 ++++++++++++++++++ Common/Utils/src/CommonUtilsLinkDef.h | 3 + .../src/RootSerializableKeyValueStore.cxx | 13 + .../testRootSerializableKeyValueStore.cxx | 116 +++++++++ 5 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h create mode 100644 Common/Utils/src/RootSerializableKeyValueStore.cxx create mode 100644 Common/Utils/test/testRootSerializableKeyValueStore.cxx diff --git a/Common/Utils/CMakeLists.txt b/Common/Utils/CMakeLists.txt index 6d1e55db08166..8e12f538f3c99 100644 --- a/Common/Utils/CMakeLists.txt +++ b/Common/Utils/CMakeLists.txt @@ -12,7 +12,7 @@ o2_add_library(CommonUtils SOURCES src/TreeStream.cxx src/TreeStreamRedirector.cxx src/RootChain.cxx src/CompStream.cxx src/ShmManager.cxx src/ValueMonitor.cxx - src/ConfigurableParamHelper.cxx src/ConfigurableParam.cxx + src/ConfigurableParamHelper.cxx src/ConfigurableParam.cxx src/RootSerializableKeyValueStore.cxx PUBLIC_LINK_LIBRARIES ROOT::Hist ROOT::Tree Boost::iostreams O2::CommonDataFormat O2::Headers FairLogger::FairLogger) @@ -28,7 +28,8 @@ o2_target_root_dictionary(CommonUtils include/CommonUtils/MemFileHelper.h include/CommonUtils/ConfigurableParam.h include/CommonUtils/ConfigurableParamHelper.h - include/CommonUtils/ConfigurationMacroHelper.h) + include/CommonUtils/ConfigurationMacroHelper.h + include/CommonUtils/RootSerializableKeyValueStore.h) o2_add_test(TreeStream COMPONENT_NAME CommonUtils @@ -54,6 +55,12 @@ o2_add_test(ValueMonitor SOURCES test/testValueMonitor.cxx PUBLIC_LINK_LIBRARIES O2::CommonUtils) +o2_add_test(PropertyMapIO + COMPONENT_NAME CommonUtils + LABELS utils + SOURCES test/testRootSerializableKeyValueStore.cxx + PUBLIC_LINK_LIBRARIES O2::CommonUtils) + o2_add_test(MemFileHelper COMPONENT_NAME CommonUtils LABELS utils diff --git a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h new file mode 100644 index 0000000000000..7df307954bf46 --- /dev/null +++ b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h @@ -0,0 +1,225 @@ +// 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_ROOTSERKEYVALUESTORE_H +#define ALICEO2_ROOTSERKEYVALUESTORE_H + +#include <map> +#include <string> +#include <TClass.h> +#include <Rtypes.h> +#include <typeinfo> +#include <typeindex> +#include <TBufferFile.h> +#include <type_traits> + +namespace o2 +{ +namespace utils +{ + +/// A ROOT serializable container mapping a key (string) to an object of arbitrary type. +/// +/// The container allows to group objects in heterogeneous type in a key-value container. +/// The container can be ROOT serialized which adds on-top of existing solutions such as boost::property_tree. +/// This may be useful in various circumenstances, for +/// instance to assemble various CCDB objects into a single aggregate to reduce the number of CCDB files/entries. +class RootSerializableKeyValueStore +{ + public: + /// Structure encapsulating the stored information: raw buffers and attached type information (combination of type_index_hash and TClass information) + struct SerializedInfo { + void* objptr = nullptr; //! pointer to existing object in memory + Int_t N = 0; + char* bufferptr = nullptr; //[N] pointer to serialized buffer + + // we use the TClass and/or the type_index_hash for type idendification + TClass* cl = nullptr; + std::string typeinfo_name; // typeinfo name that can be used to store type if TClass not available (for PODs!) + ClassDefNV(SerializedInfo, 1); + }; + + enum class GetState { + kOK, + kNOSUCHKEY, + kWRONGTYPE, + kNOTCLASS + }; + + RootSerializableKeyValueStore() = default; + + /// Putting a value (and overrides previous entries) + /// T needs to be trivial non-pointer type or a type having a ROOT TClass instance + template <typename T> + void put(std::string const& key, T const& value) + { + remove_entry(key); + GetState s; + return put_impl(key, value, s, int{}); + } + + /// returns object pointer for this key or nullptr if error or does not exist. + template <typename T> + const T* get(std::string const& key) const + { + GetState s; + return get_impl<T>(key, s, int{}); + } + + /// returns object pointer for this key or nullptr if error or does not exist; state is set with meaningful error code + template <typename T> + const T* get(std::string const& key, GetState& state) const + { + return get_impl<T>(key, state, int{}); + } + + /// get interface returning a const reference instead of pointer; Error handling/detection is done via the state argument; + /// Beware: In case of errors, a default object is returned. + template <typename T> + const T& getRef(std::string const& key, GetState& state) const + { + auto ptr = get_impl<T>(key, state, int{}); + if (ptr) { + return *ptr; + } else { + static T t = T(); + // in case of error we return a default object + return t; + } + } + + /// checks if a key exists + bool has(std::string const& key) const + { + return mStore.find(key) != mStore.end(); + } + + /// clear the store + void clear() + { + mStore.clear(); + } + + private: + std::map<std::string, SerializedInfo*> mStore; + + // generic implementation for put relying on TClass + template <typename T> + void put_impl(std::string const& key, T const& value, GetState& state, ...) + { + // make sure we have a TClass for this + // if there is a TClass, we'll use ROOT serialization to encode into the buffer + auto ptr = new T(value); + auto cl = TClass::GetClass(typeid(value)); + if (!cl) { + state = GetState::kNOTCLASS; + return; + } + char* bufferptr = nullptr; + TBufferFile buff(TBuffer::kWrite); + buff.WriteObjectAny(ptr, cl); + int N = buff.Length(); + bufferptr = new char[N]; + memcpy(bufferptr, buff.Buffer(), sizeof(char) * N); + + auto name = std::type_index(typeid(value)).name(); + mStore.insert(std::pair<std::string, SerializedInfo*>(key, new SerializedInfo{(void*)ptr, N, (char*)bufferptr, cl, name})); + } + + // implementation for put for trivial types + template <typename T, typename std::enable_if<std::is_trivial<T>::value, T>::type* = nullptr> + void put_impl(std::string const& key, T const& value, GetState& state, int) + { + // we forbid pointers + static_assert(!std::is_pointer<T>::value); + // serialization of trivial types is easy (not based on ROOT) + auto ptr = new T(value); + int N = sizeof(T); + auto bufferptr = new char[N]; + memcpy(bufferptr, (char*)ptr, sizeof(char) * N); + + auto name = std::type_index(typeid(value)).name(); + mStore.insert(std::pair<std::string, SerializedInfo*>(key, new SerializedInfo{(void*)ptr, N, (char*)bufferptr, nullptr, name})); + } + + // generic implementation for get relying on TClass + template <typename T> + const T* get_impl(std::string const& key, GetState& state, ...) const + { + state = GetState::kOK; + auto iter = mStore.find(key); + if (iter != mStore.end()) { + auto value = iter->second; + auto cl = TClass::GetClass(typeid(T)); + if (!cl) { + state = GetState::kNOTCLASS; + return nullptr; + } + if (value->cl && strcmp(cl->GetName(), value->cl->GetName()) == 0) { + // if there is a (cached) object pointer ... we return it + if (value->objptr) { + return (T*)value->objptr; + } + // do this only once and cache instance into value.objptr + TBufferFile buff(TBuffer::kRead, value->N, value->bufferptr, false, nullptr); + buff.Reset(); + auto instance = (T*)buff.ReadObjectAny(cl); + value->objptr = instance; + return (T*)value->objptr; + } else { + state = GetState::kWRONGTYPE; + return nullptr; + } + } + state = GetState::kNOSUCHKEY; + return nullptr; + } + + // implementation for standard POD types + template <typename T, typename std::enable_if<std::is_trivial<T>::value, T>::type* = nullptr> + const T* get_impl(std::string const& key, GetState& state, int) const + { + state = GetState::kOK; + auto iter = mStore.find(key); + if (iter != mStore.end()) { + auto value = iter->second; + if (strcmp(std::type_index(typeid(T)).name(), value->typeinfo_name.c_str()) == 0) { + // if there is a (cached) object pointer ... we return it + if (value->objptr) { + return (T*)value->objptr; + } + value->objptr = (T*)value->bufferptr; + return (T*)value->objptr; + } else { + state = GetState::kWRONGTYPE; + return nullptr; + } + } + state = GetState::kNOSUCHKEY; + return nullptr; + } + + // removes a previous entry + void remove_entry(std::string const& key) + { + auto iter = mStore.find(key); + if (iter != mStore.end()) { + delete iter->second; + mStore.erase(iter); + } + } + + ClassDefNV(RootSerializableKeyValueStore, 1); +}; + +} // namespace utils +} // namespace o2 + +#endif diff --git a/Common/Utils/src/CommonUtilsLinkDef.h b/Common/Utils/src/CommonUtilsLinkDef.h index 2dc1ac8ab97ec..921b848ca72e8 100644 --- a/Common/Utils/src/CommonUtilsLinkDef.h +++ b/Common/Utils/src/CommonUtilsLinkDef.h @@ -19,5 +19,8 @@ #pragma link C++ class o2::utils::RootChain + ; #pragma link C++ class o2::utils::RngHelper; #pragma link C++ class o2::utils::MemFileHelper + ; +#pragma link C++ class o2::utils::RootSerializableKeyValueStore::SerializedInfo + ; +#pragma link C++ class map < string, o2::utils::RootSerializableKeyValueStore::SerializedInfo*> + ; +#pragma link C++ class o2::utils::RootSerializableKeyValueStore + ; #endif diff --git a/Common/Utils/src/RootSerializableKeyValueStore.cxx b/Common/Utils/src/RootSerializableKeyValueStore.cxx new file mode 100644 index 0000000000000..d035378001dcc --- /dev/null +++ b/Common/Utils/src/RootSerializableKeyValueStore.cxx @@ -0,0 +1,13 @@ +// 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 "CommonUtils/RootSerializableKeyValueStore.h" + +using namespace o2::utils; diff --git a/Common/Utils/test/testRootSerializableKeyValueStore.cxx b/Common/Utils/test/testRootSerializableKeyValueStore.cxx new file mode 100644 index 0000000000000..96b2f9a1b5fb6 --- /dev/null +++ b/Common/Utils/test/testRootSerializableKeyValueStore.cxx @@ -0,0 +1,116 @@ +// 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. + +#define BOOST_TEST_MODULE Test RootSerKeyValueStore +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "CommonUtils/RootSerializableKeyValueStore.h" +#include <TMemFile.h> +#include <TH1F.h> +#include <vector> +#include <iostream> +#include <TClass.h> + +using namespace o2; +using namespace o2::utils; + +BOOST_AUTO_TEST_CASE(write_read_test) +{ + RootSerializableKeyValueStore s; + + // put POD some stuff + double x = 1.1; + s.put("x", x); + s.put("i", 110); + + // put some complex classes (need dictionary) + std::string str = "hello"; + s.put("str", str); + + // this should fail compiling: + // const char* text = "foo"; + // s.put("cstr", text); + + TH1F h1("th1name", "th1name", 100, 0, 99); + h1.FillRandom("gaus", 10000); + s.put("h1", h1); + + // check basic assumption that typeinfo name is unique for basic types + BOOST_CHECK(strcmp(std::type_index(typeid(double*)).name(), "Pd") == 0); + BOOST_CHECK(strcmp(std::type_index(typeid(int)).name(), "i") == 0); + BOOST_CHECK(strcmp(std::type_index(typeid(unsigned int)).name(), "j") == 0); + BOOST_CHECK(strcmp(std::type_index(typeid(char)).name(), "c") == 0); + BOOST_CHECK(strcmp(std::type_index(typeid(char*)).name(), "Pc") == 0); + BOOST_CHECK(strcmp(std::type_index(typeid(unsigned char)).name(), "h") == 0); + + // check assumption that for more complicated types the TClass name is unique + // (the std::type_index is not standardized) + BOOST_CHECK(strcmp(TClass::GetClass(typeid(std::vector<double>))->GetName(), "vector<double>") == 0); + + // retrieve + BOOST_CHECK(s.get<std::string>("str")->compare(str) == 0); + BOOST_CHECK(*(s.get<double>("x")) == x); + BOOST_CHECK(s.has("x")); + BOOST_CHECK(!s.has("x_does_not_exist")); + + // retrieve with state/error information + using ErrorState = RootSerializableKeyValueStore::GetState; + ErrorState state; + { + auto r1 = s.get<std::string>("str", state); + BOOST_CHECK(state == ErrorState::kOK); + auto returnedstring = s.getRef<std::string>("str", state); + BOOST_CHECK(state == ErrorState::kOK); + BOOST_CHECK(returnedstring.compare(str) == 0); + + auto r2 = s.get<int>("str", state); + BOOST_CHECK(r2 == nullptr); + BOOST_CHECK(state == ErrorState::kWRONGTYPE); + auto r3 = s.get<int>("str2", state); + BOOST_CHECK(state == ErrorState::kNOSUCHKEY); + BOOST_CHECK(r3 == nullptr); + + auto r4 = s.get<TH1F>("non-existend-histogram", state); + BOOST_CHECK(state == ErrorState::kNOSUCHKEY); + } + + // put something twice + s.put<int>("twice", 10); + s.put<int>("twice", 7); + BOOST_CHECK(*(s.get<int>("twice")) == 7); + + std::cerr << "TESTING FILE IO\n"; + TMemFile f("tmp.root", "RECREATE"); + f.WriteObject(&s, "map"); + + RootSerializableKeyValueStore* s2 = nullptr; + f.GetObject("map", s2); + BOOST_CHECK(s2 != nullptr); + if (s2) { + auto t1 = s2->get<double>("x"); + BOOST_CHECK(t1 != nullptr); + BOOST_CHECK(t1 && *(t1) == x); + + auto i1 = s2->get<int>("i"); + BOOST_CHECK(i1 != nullptr); + BOOST_CHECK(i1 && *(i1) == 110); + + auto t2 = s2->get<std::string>("str"); + BOOST_CHECK(t2 && t2->compare(str) == 0); + + auto t3 = s2->get<std::string>("str"); + BOOST_CHECK(t3 && t3->compare(str) == 0); + + auto histo = s2->get<TH1F>("h1"); + BOOST_CHECK(histo); + } + f.Close(); +} From 52b2c762b5011a470cbc403f339011d73ddc40a5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 5 Jan 2021 19:25:38 +0100 Subject: [PATCH 1696/1751] DPL: do not compile GUISupport if AliceO2::DebugGUI is not found (#5124) --- Framework/CMakeLists.txt | 3 +++ Framework/GUISupport/CMakeLists.txt | 23 ++++++----------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Framework/CMakeLists.txt b/Framework/CMakeLists.txt index 362968ede706a..ca1aa9cf05b33 100644 --- a/Framework/CMakeLists.txt +++ b/Framework/CMakeLists.txt @@ -18,6 +18,9 @@ add_subdirectory(Utils) add_subdirectory(AnalysisSupport) +# Build the GUI support only if we have DebugGUI +if (TARGET AliceO2::DebugGUI) add_subdirectory(GUISupport) +endif() add_subdirectory(TestWorkflows) diff --git a/Framework/GUISupport/CMakeLists.txt b/Framework/GUISupport/CMakeLists.txt index e5ed0613edb4f..b04d078c7f7dd 100644 --- a/Framework/GUISupport/CMakeLists.txt +++ b/Framework/GUISupport/CMakeLists.txt @@ -10,23 +10,16 @@ # Given GCC 7.3 does not provide std::filesystem we use Boost instead # Drop this once we move to GCC 8.2+ - -if (TARGET AliceO2::DebugGUI) - set(GUI_SOURCES src/FrameworkGUIDebugger.cxx src/FrameworkGUIDevicesGraph.cxx - src/FrameworkGUIDeviceInspector.cxx - src/FrameworkGUIDataRelayerUsage.cxx src/PaletteHelpers.cxx) - set(EXTRA_TARGETS AliceO2::DebugGUI) -else() - set(GUI_SOURCES src/FrameworkDummyDebugger.cxx) -endif() - o2_add_library(FrameworkGUISupport SOURCES src/Plugin.cxx - ${GUI_SOURCES} + src/FrameworkGUIDebugger.cxx + src/FrameworkGUIDevicesGraph.cxx + src/FrameworkGUIDeviceInspector.cxx + src/FrameworkGUIDataRelayerUsage.cxx + src/PaletteHelpers.cxx PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src - PUBLIC_LINK_LIBRARIES O2::Framework ${EXTRA_TARGETS}) + PUBLIC_LINK_LIBRARIES O2::Framework AliceO2::DebugGUI) -if (TARGET AliceO2::DebugGUI) if (NOT APPLE) set (DEBUG_GUI_TESTS_WORKFLOW CustomGUIGL @@ -34,7 +27,6 @@ set (DEBUG_GUI_TESTS_WORKFLOW SimpleTracksED ) endif() -endif() foreach(w ${DEBUG_GUI_TESTS_WORKFLOW} @@ -49,7 +41,6 @@ foreach(w COMMAND_LINE_ARGS ${DPL_WORKFLOW_TESTS_EXTRA_OPTIONS} --run --shm-segment-size 20000000) endforeach() -if (TARGET AliceO2::DebugGUI) # TODO: investigate the problem with the two unit tests, maybe setup of the CI # environment assertion fired X11: The DISPLAY environment variable is missing # glfw-3.2.1/src/window.c:579: glfwGetFramebufferSize: Assertion `window != @@ -59,5 +50,3 @@ set_property(TEST test_Framework_test_SimpleTracksED PROPERTY DISABLED TRUE) set_property(TEST test_Framework_test_CustomGUIGL PROPERTY DISABLED TRUE) set_property(TEST test_Framework_test_CustomGUISokol PROPERTY DISABLED TRUE) endif() -endif() - From 77556966ae3002282efb2d23976398761f22b86e Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 5 Jan 2021 14:37:31 +0100 Subject: [PATCH 1697/1751] Fix codechecker violations --- .../FT0/include/DataFormatsFT0/LookUpTable.h | 6 ++-- Detectors/PHOS/base/src/Mapping.cxx | 3 +- Detectors/PHOS/reconstruction/src/Bunch.cxx | 3 +- .../PHOS/reconstruction/src/CaloRawFitter.cxx | 12 ++++--- Detectors/PHOS/reconstruction/src/Channel.cxx | 12 ++++--- .../PHOS/reconstruction/src/RawBuffer.cxx | 6 ++-- .../PHOS/reconstruction/src/RawPayload.cxx | 6 ++-- Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h | 18 ++++++++--- Detectors/ZDC/raw/src/DumpRaw.cxx | 22 ++++++++++--- Detectors/ZDC/raw/src/raw-parser.cxx | 20 ++++++------ .../Base/cuda/GPUReconstructionCUDA.h | 2 +- .../Base/cuda/GPUReconstructionCUDAIncludes.h | 2 +- Utilities/Tools/cpulimit/cpulimit.c | 32 ++++++++++--------- Utilities/Tools/cpulimit/list.c | 2 +- 14 files changed, 94 insertions(+), 52 deletions(-) diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h index 7ecf86dcf2333..bc8c7684474f9 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h @@ -187,9 +187,11 @@ class LookUpTable mgr.setURL("http://ccdb-test.cern.ch:8080"); auto hvch = mgr.get<std::vector<o2::ft0::HVchannel>>("FT0/LookUpTable"); size_t max = 0; - for (auto const& chan : *hvch) - if (max < chan.channel) + for (auto const& chan : *hvch) { + if (max < chan.channel) { max = chan.channel; + } + } lut_data.resize(max + 1); for (auto const& chan : *hvch) { o2::ft0::Topo topo = chan.pm; diff --git a/Detectors/PHOS/base/src/Mapping.cxx b/Detectors/PHOS/base/src/Mapping.cxx index 24468b1c56830..d380c58f66006 100644 --- a/Detectors/PHOS/base/src/Mapping.cxx +++ b/Detectors/PHOS/base/src/Mapping.cxx @@ -90,8 +90,9 @@ Mapping::ErrorStatus Mapping::setMapping() for (short m = 0; m < 4; m++) { //modules for (short i = 0; i < 4; i++) { //RCU - if (m == 0 && (i < 2)) + if (m == 0 && (i < 2)) { continue; //half of module: only RCU 2,3 + } short numberOfChannels = 0; short maxHWAddress = 0; diff --git a/Detectors/PHOS/reconstruction/src/Bunch.cxx b/Detectors/PHOS/reconstruction/src/Bunch.cxx index 898efa85db74a..9c0a483f5a0f0 100644 --- a/Detectors/PHOS/reconstruction/src/Bunch.cxx +++ b/Detectors/PHOS/reconstruction/src/Bunch.cxx @@ -13,6 +13,7 @@ using namespace o2::phos; void Bunch::initFromRange(gsl::span<uint16_t> adcs) { - for (auto adcval : adcs) + for (auto adcval : adcs) { mADC.emplace_back(adcval); + } } \ No newline at end of file diff --git a/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx b/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx index 3b78eae95be70..a393d7328c006 100644 --- a/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx +++ b/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx @@ -112,8 +112,9 @@ CaloRawFitter::FitStatus CaloRawFitter::evalKLevel(const Bunch& b) //const ushor mMaxSample = a; nMax = 0; } - if (a == mMaxSample) + if (a == mMaxSample) { nMax++; + } //check if there is a spike if (app >= 0 && ap >= 0) { spike |= (2 * ap - (a + app) > 2 * kSpikeThreshold); @@ -130,15 +131,17 @@ CaloRawFitter::FitStatus CaloRawFitter::evalKLevel(const Bunch& b) //const ushor return kSpike; } - if (mMaxSample > 900 && nMax > 2) + if (mMaxSample > 900 && nMax > 2) { overflow = true; + } float pedestal = 0; if (mPedSubtract) { if (nPed > 0) { pedRMS = (pedRMS - pedMean * pedMean / nPed) / nPed; - if (pedRMS > 0.) + if (pedRMS > 0.) { pedRMS = sqrt(pedRMS); + } pedestal = pedMean / nPed; } else { mAmp.push_back(0); @@ -149,8 +152,9 @@ CaloRawFitter::FitStatus CaloRawFitter::evalKLevel(const Bunch& b) //const ushor } amp -= pedestal; - if (amp < kBaseLine) + if (amp < kBaseLine) { amp = 0; + } //Evaluate time time = b.getStartTime() - 2; diff --git a/Detectors/PHOS/reconstruction/src/Channel.cxx b/Detectors/PHOS/reconstruction/src/Channel.cxx index a621cb3b97966..8bd68a7feff91 100644 --- a/Detectors/PHOS/reconstruction/src/Channel.cxx +++ b/Detectors/PHOS/reconstruction/src/Channel.cxx @@ -13,29 +13,33 @@ using namespace o2::phos; int Channel::getBranchIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return ((mHardwareAddress >> 11) & 0x1); } int Channel::getFECIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return ((mHardwareAddress >> 7) & 0xF); } Int_t Channel::getAltroIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return ((mHardwareAddress >> 4) & 0x7); } Int_t Channel::getChannelIndex() const { - if (mHardwareAddress == -1) + if (mHardwareAddress == -1) { throw HardwareAddressError(); + } return (mHardwareAddress & 0xF); } diff --git a/Detectors/PHOS/reconstruction/src/RawBuffer.cxx b/Detectors/PHOS/reconstruction/src/RawBuffer.cxx index 1172aebd70894..8df5d66998ad1 100644 --- a/Detectors/PHOS/reconstruction/src/RawBuffer.cxx +++ b/Detectors/PHOS/reconstruction/src/RawBuffer.cxx @@ -61,14 +61,16 @@ void RawBuffer::readFromMemoryBuffer(const gsl::span<const char> rawmemory) uint32_t RawBuffer::getWord(int index) const { - if (index >= mNDataWords) + if (index >= mNDataWords) { throw std::runtime_error("Index out of range"); + } return mDataWords[index]; } uint32_t RawBuffer::getNextDataWord() { - if (!hasNext()) + if (!hasNext()) { throw std::runtime_error("No more data words in buffer"); + } return mDataWords[mCurrentDataWord++]; } diff --git a/Detectors/PHOS/reconstruction/src/RawPayload.cxx b/Detectors/PHOS/reconstruction/src/RawPayload.cxx index 2bb2b08d86dcb..5818b4e124054 100644 --- a/Detectors/PHOS/reconstruction/src/RawPayload.cxx +++ b/Detectors/PHOS/reconstruction/src/RawPayload.cxx @@ -15,14 +15,16 @@ using namespace o2::phos; RawPayload::RawPayload(gsl::span<const uint32_t> payloadwords, int numpages) : mPayloadWords(payloadwords.size()), mNumberOfPages(numpages) { - for (auto word : payloadwords) + for (auto word : payloadwords) { mPayloadWords.emplace_back(word); + } } void RawPayload::appendPayloadWords(const gsl::span<const uint32_t> payloadwords) { - for (auto word : payloadwords) + for (auto word : payloadwords) { mPayloadWords.emplace_back(word); + } } void RawPayload::reset() diff --git a/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h b/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h index 165d57d4bc9f4..167b54f4b480e 100644 --- a/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h +++ b/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h @@ -1,3 +1,13 @@ +// 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 <TH1.h> #include <TH2.h> #include "ZDCBase/Constants.h" @@ -28,10 +38,10 @@ class DumpRaw private: void setStat(TH1* h); int mVerbosity = 1; - TH1* mBaseline[NDigiChannels] = {0}; - TH1* mCounts[NDigiChannels] = {0}; - TH2* mSignal[NDigiChannels] = {0}; - TH2* mBunch[NDigiChannels] = {0}; + TH1* mBaseline[NDigiChannels] = {nullptr}; + TH1* mCounts[NDigiChannels] = {nullptr}; + TH2* mSignal[NDigiChannels] = {nullptr}; + TH2* mBunch[NDigiChannels] = {nullptr}; EventChData mCh; }; } // namespace zdc diff --git a/Detectors/ZDC/raw/src/DumpRaw.cxx b/Detectors/ZDC/raw/src/DumpRaw.cxx index dbca59386494d..c139f74cdfaf8 100644 --- a/Detectors/ZDC/raw/src/DumpRaw.cxx +++ b/Detectors/ZDC/raw/src/DumpRaw.cxx @@ -1,3 +1,13 @@ +// 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 <TROOT.h> #include <TPad.h> #include <TString.h> @@ -205,20 +215,24 @@ int DumpRaw::process(const EventChData& ch) //printf("%d %u %d\n",i,us[i],s[i]); } if (f.Alice_3) { - for (Int_t i = 0; i < 12; i++) + for (Int_t i = 0; i < 12; i++) { mSignal[ih]->Fill(i - 36., Double_t(s[i])); + } } if (f.Alice_2) { - for (Int_t i = 0; i < 12; i++) + for (Int_t i = 0; i < 12; i++) { mSignal[ih]->Fill(i - 24., Double_t(s[i])); + } } if (f.Alice_1 || f.Auto_1) { - for (Int_t i = 0; i < 12; i++) + for (Int_t i = 0; i < 12; i++) { mSignal[ih]->Fill(i - 12., Double_t(s[i])); + } } if (f.Alice_0 || f.Auto_0) { - for (Int_t i = 0; i < 12; i++) + for (Int_t i = 0; i < 12; i++) { mSignal[ih]->Fill(i + 0., Double_t(s[i])); + } Double_t bc_d = UInt_t(f.bc / 100); Double_t bc_m = UInt_t(f.bc % 100); mBunch[ih]->Fill(bc_m, -bc_d); diff --git a/Detectors/ZDC/raw/src/raw-parser.cxx b/Detectors/ZDC/raw/src/raw-parser.cxx index b2c65d71776c2..888d3e4d167e1 100644 --- a/Detectors/ZDC/raw/src/raw-parser.cxx +++ b/Detectors/ZDC/raw/src/raw-parser.cxx @@ -46,9 +46,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) auto loglevel = setup.options().get<int>("log-level"); return adaptStateless([loglevel](InputRecord& inputs, DataAllocator& outputs) { o2::zdc::DumpRaw zdc_dr; - zdc_dr.init(); - zdc_dr.setVerbosity(loglevel); - DPLRawParser parser(inputs); + zdc_dr.init(); + zdc_dr.setVerbosity(loglevel); + DPLRawParser parser(inputs); o2::header::DataHeader const* lastDataHeader = nullptr; std::stringstream rdhprintout; for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { @@ -84,19 +84,19 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) rdhprintout.str(std::string()); } } - if(payload!=0){ - for(Int_t ip=0; ip<payloadSize; ip+=16){ - //o2::zdc::Digits2Raw::print_gbt_word((const UInt_t*)&payload[ip]); - zdc_dr.processWord((const UInt_t*)&payload[ip]); - } - } + if (payload != nullptr) { + for (Int_t ip = 0; ip < payloadSize; ip += 16) { + //o2::zdc::Digits2Raw::print_gbt_word((const UInt_t*)&payload[ip]); + zdc_dr.processWord((const UInt_t*)&payload[ip]); + } + } } lastDataHeader = dh; } if (loglevel > 0) { LOG(INFO) << rdhprintout.str(); } - zdc_dr.write(); + zdc_dr.write(); }); }}, Options{ {"log-level", VariantType::Int, 1, {"Logging level [0-2]"}}}}); diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h index 5997a88d8c224..d3188865df4b6 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h @@ -44,7 +44,7 @@ class GPUReconstructionCUDABackend : public GPUReconstructionDeviceBase { public: GPUThreadContextCUDA(GPUReconstructionCUDAInternals* context); - virtual ~GPUThreadContextCUDA(); + ~GPUThreadContextCUDA() override; private: GPUReconstructionCUDAInternals* mContext = nullptr; diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h index 449a4d889585f..cecac16ffd628 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h @@ -14,7 +14,7 @@ #ifndef O2_GPU_GPURECONSTRUCTIONCUDAINCLUDES_H #define O2_GPU_GPURECONSTRUCTIONCUDAINCLUDES_H -#include <stdint.h> +#include <cstdint> #include <cuda_runtime.h> #include <cuda.h> #include <cooperative_groups.h> diff --git a/Utilities/Tools/cpulimit/cpulimit.c b/Utilities/Tools/cpulimit/cpulimit.c index 15bf42f6f061b..e7c801496ba3d 100644 --- a/Utilities/Tools/cpulimit/cpulimit.c +++ b/Utilities/Tools/cpulimit/cpulimit.c @@ -144,10 +144,10 @@ static void increase_priority() { priority--; } if (priority != old_priority) { - if (verbose) printf("Priority changed to %d\n", priority); + if (verbose) { printf("Priority changed to %d\n", priority); } } else { - if (verbose) printf("Warning: Cannot change priority. Run as root or renice for best results.\n"); + if (verbose) { printf("Warning: Cannot change priority. Run as root or renice for best results.\n"); } } } @@ -174,7 +174,7 @@ int get_pid_max() //read /proc/sys/kernel/pid_max static char buffer[1024]; FILE *fd = fopen("/proc/sys/kernel/pid_max", "r"); - if (fd==NULL) return -1; + if (fd==NULL) { return -1; } if (fgets(buffer, sizeof(buffer), fd)==NULL) { fclose(fd); return -1; @@ -216,7 +216,7 @@ void limit_process(pid_t pid, double limit, int include_children) //build the family init_process_group(&pgroup, pid, include_children); - if (verbose) printf("Members in the process group owned by %d: %d\n", pgroup.target_pid, pgroup.proclist->count); + if (verbose) { printf("Members in the process group owned by %d: %d\n", pgroup.target_pid, pgroup.proclist->count); } //rate at which we are keeping active the processes (range 0-1) //1 means that the process are using all the twork slice @@ -225,7 +225,7 @@ void limit_process(pid_t pid, double limit, int include_children) update_process_group(&pgroup); if (pgroup.proclist->count==0) { - if (verbose) printf("No more processes.\n"); + if (verbose) { printf("No more processes.\n"); } break; } @@ -239,7 +239,7 @@ void limit_process(pid_t pid, double limit, int include_children) if (proc->cpu_usage < 0) { continue; } - if (pcpu < 0) pcpu = 0; + if (pcpu < 0) { pcpu = 0; } pcpu += proc->cpu_usage; } @@ -258,10 +258,12 @@ void limit_process(pid_t pid, double limit, int include_children) tsleep.tv_nsec = TIME_SLOT * 1000 - twork.tv_nsec; if (verbose) { - if (c%200==0) + if (c%200==0) { printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n"); - if (c%10==0 && c>0) + } + if (c%10==0 && c>0) { printf("%0.2lf%%\t%6ld us\t%6ld us\t%0.2lf%%\n", pcpu*100, twork.tv_nsec/1000, tsleep.tv_nsec/1000, workingrate*100); + } } //resume processes @@ -272,7 +274,7 @@ void limit_process(pid_t pid, double limit, int include_children) struct process *proc = (struct process*)(node->data); if (kill(proc->pid,SIGCONT) != 0) { //process is dead, remove it from family - if (verbose) fprintf(stderr, "SIGCONT failed. Process %d dead!\n", proc->pid); + if (verbose) { fprintf(stderr, "SIGCONT failed. Process %d dead!\n", proc->pid); } //remove process from group delete_node(pgroup.proclist, node); remove_process(&pgroup, proc->pid); @@ -301,7 +303,7 @@ void limit_process(pid_t pid, double limit, int include_children) struct process *proc = (struct process*)(node->data); if (kill(proc->pid,SIGSTOP)!=0) { //process is dead, remove it from family - if (verbose) fprintf(stderr, "SIGSTOP failed. Process %d dead!\n", proc->pid); + if (verbose) { fprintf(stderr, "SIGSTOP failed. Process %d dead!\n", proc->pid); } //remove process from group delete_node(pgroup.proclist, node); remove_process(&pgroup, proc->pid); @@ -427,7 +429,7 @@ int main(int argc, char **argv) { signal(SIGTERM, quit); //print the number of available cpu - if (verbose) printf("%d cpu detected\n", NCPU); + if (verbose) { printf("%d cpu detected\n", NCPU); } if (command_mode) { int i; @@ -435,7 +437,7 @@ int main(int argc, char **argv) { const char *cmd = argv[optind]; //command line arguments char **cmd_args = (char**)malloc((argc-optind + 1) * sizeof(char*)); - if (cmd_args==NULL) exit(2); + if (cmd_args==NULL) { exit(2); } for (i=0; i<argc-optind; i++) { cmd_args[i] = argv[i+optind]; } @@ -474,7 +476,7 @@ int main(int argc, char **argv) { waitpid(child, &status_process, 0); waitpid(limiter, &status_limiter, 0); if (WIFEXITED(status_process)) { - if (verbose) printf("Process %d terminated with exit status %d\n", child, (int)WEXITSTATUS(status_process)); + if (verbose) { printf("Process %d terminated with exit status %d\n", child, (int)WEXITSTATUS(status_process)); } exit(WEXITSTATUS(status_process)); } printf("Process %d terminated abnormally\n", child); @@ -482,7 +484,7 @@ int main(int argc, char **argv) { } else { //limiter code - if (verbose) printf("Limiting process %d\n",child); + if (verbose) { printf("Limiting process %d\n",child); } limit_process(child, limit, include_children); exit(0); } @@ -524,7 +526,7 @@ int main(int argc, char **argv) { //control limit_process(pid, limit, include_children); } - if (lazy) break; + if (lazy) { break; } sleep(2); }; diff --git a/Utilities/Tools/cpulimit/list.c b/Utilities/Tools/cpulimit/list.c index 2a78358a994a6..2ac36708d4a08 100644 --- a/Utilities/Tools/cpulimit/list.c +++ b/Utilities/Tools/cpulimit/list.c @@ -102,7 +102,7 @@ struct list_node *xlocate_node(struct list *l,void *elem,int offset,int length) struct list_node *tmp; tmp=l->first; while(tmp!=NULL) { - if(!memcmp((char*)tmp->data+offset,elem,length==0?l->keysize:length)) return (tmp); + if(!memcmp((char*)tmp->data+offset,elem,length==0?l->keysize:length)) { return (tmp); } tmp=tmp->next; } return EMPTYLIST; From 4d235b30e4015e138702065baac1b464a614cb23 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Mon, 4 Jan 2021 13:24:46 +0100 Subject: [PATCH 1698/1751] Pass input descriptor for TOF compressed analysis task from cmdl --- Detectors/TOF/compression/src/tof-compressed-analysis.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Detectors/TOF/compression/src/tof-compressed-analysis.cxx b/Detectors/TOF/compression/src/tof-compressed-analysis.cxx index 4f194448841dc..905dbe1f93e9b 100644 --- a/Detectors/TOF/compression/src/tof-compressed-analysis.cxx +++ b/Detectors/TOF/compression/src/tof-compressed-analysis.cxx @@ -24,6 +24,8 @@ using namespace o2::framework; // including Framework/runDataProcessing void customize(std::vector<ConfigParamSpec>& workflowOptions) { + auto inputDesc = ConfigParamSpec{"tof-compressed-analysis-input-desc", VariantType::String, "CRAWDATA", {"Input specs description string"}}; + workflowOptions.push_back(inputDesc); } #include "Framework/runDataProcessing.h" // the main driver @@ -31,9 +33,11 @@ void customize(std::vector<ConfigParamSpec>& workflowOptions) /// This function hooks up the the workflow specifications into the DPL driver. WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + auto inputDesc = cfgc.options().get<std::string>("tof-compressed-analysis-input-desc"); + return WorkflowSpec{ DataProcessorSpec{"compressed-analysis", - select("x:TOF/CRAWDATA"), + select(std::string("x:TOF/" + inputDesc).c_str()), Outputs{}, AlgorithmSpec(adaptFromTask<o2::tof::CompressedAnalysisTask>()), Options{ From 10a62f792206c3197666ecfe312fdfd0a070c962 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Mon, 4 Jan 2021 13:26:35 +0100 Subject: [PATCH 1699/1751] Minor updates to compressed inspector task --- .../TOF/compression/src/tof-compressed-inspector.cxx | 3 ++- Detectors/TOF/workflow/src/CompressedInspectorTask.cxx | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx index 654858b3b264a..e32d078c8836e 100644 --- a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx +++ b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx @@ -52,7 +52,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) Outputs{}, algoSpec, Options{ - {"tof-compressed-inspector-filename", VariantType::String, "inspector.root", {"Name of the inspector output file"}}}}); + {"tof-compressed-inspector-filename", VariantType::String, "inspector.root", {"Name of the inspector output file"}}, + {"tof-compressed-inspector-decoder-verbose", VariantType::Bool, false, {"Decode in verbose mode"}}}}); return workflow; } diff --git a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx index 5c8629363cf3c..bebb1a8908641 100644 --- a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx @@ -36,6 +36,9 @@ void CompressedInspectorTask<RDH>::init(InitContext& ic) { LOG(INFO) << "CompressedInspector init"; auto filename = ic.options().get<std::string>("tof-compressed-inspector-filename"); + auto verbose = ic.options().get<bool>("tof-compressed-inspector-decoder-verbose"); + + DecoderBaseT<RDH>::setDecoderVerbose(verbose); /** open file **/ if (mFile && mFile->IsOpen()) { @@ -62,6 +65,8 @@ void CompressedInspectorTask<RDH>::init(InitContext& ic) mHistos1D["errorBit"] = new TH1F("hErrorBit", ";TDC error bit", 15, 0., 15.); mHistos2D["error"] = new TH2F("hError", ";slot;TDC", 24, 1., 13., 15, 0., 15.); mHistos2D["test"] = new TH2F("hTest", ";slot;TDC", 24, 1., 13., 15, 0., 15.); + mHistos2D["crateBC"] = new TH2F("hCrateBC", ";crate;BC", 72, 0., 72., 4096, 0., 4096.); + mHistos2D["crateOrbit"] = new TH2F("hCrateOrbit", ";crate;orbit", 72, 0., 72., 4096, 0., 4096.); auto finishFunction = [this]() { LOG(INFO) << "CompressedInspector finish"; @@ -110,6 +115,9 @@ void CompressedInspectorTask<RDH>::run(ProcessingContext& pc) template <typename RDH> void CompressedInspectorTask<RDH>::headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) { + mHistos2D["crateBC"]->Fill(crateHeader->drmID, crateHeader->bunchID); + mHistos2D["crateOrbit"]->Fill(crateHeader->drmID, crateOrbit->orbitID % 4096); + for (int ibit = 0; ibit < 11; ++ibit) { if (crateHeader->slotPartMask & (1 << ibit)) { mHistos2D["slotPartMask"]->Fill(crateHeader->drmID, ibit + 2); From 3034b64d8884e12c49b841849b4b2e04e96ef866 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 6 Jan 2021 11:24:08 +0100 Subject: [PATCH 1700/1751] DPL: add helper to printout current state (#5126) --- Framework/Core/include/Framework/DriverInfo.h | 4 ++++ Framework/Core/src/DriverInfo.cxx | 19 +++++++++++++++++ .../GUISupport/src/FrameworkGUIDebugger.cxx | 21 +------------------ 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Framework/Core/include/Framework/DriverInfo.h b/Framework/Core/include/Framework/DriverInfo.h index 2b2d4b0c8cfbc..d1df4a78c416c 100644 --- a/Framework/Core/include/Framework/DriverInfo.h +++ b/Framework/Core/include/Framework/DriverInfo.h @@ -142,6 +142,10 @@ struct DriverInfo { bool noSHMCleanup; }; +struct DriverInfoHelper { + static char const* stateToString(enum DriverState state); +}; + } // namespace o2::framework #endif // O2_FRAMEWORK_DRIVERINFO_H_ diff --git a/Framework/Core/src/DriverInfo.cxx b/Framework/Core/src/DriverInfo.cxx index 5d12c9b098ca2..37989f6df0ee7 100644 --- a/Framework/Core/src/DriverInfo.cxx +++ b/Framework/Core/src/DriverInfo.cxx @@ -8,3 +8,22 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/DriverInfo.h" + +char const* o2::framework::DriverInfoHelper::stateToString(enum DriverState state) +{ + static const char* names[static_cast<int>(DriverState::LAST)] = { + "INIT", // + "SCHEDULE", // + "RUNNING", // + "REDEPLOY_GUI", // + "QUIT_REQUESTED", // + "HANDLE_CHILDREN", // + "EXIT", // + "UNKNOWN", // + "PERFORM_CALLBACKS", // + "MATERIALISE_WORKFLOW", // + "IMPORT_CURRENT_WORKFLOW", // + "DO_CHILD" // + }; + return names[static_cast<int>(state)]; +} diff --git a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx index a0e9f97a9122a..cf5e380ffe07d 100644 --- a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx @@ -691,25 +691,6 @@ void popWindowColorDueToStatus() ImGui::PopStyleVar(1); } -struct DriverHelper { - static char const* stateToString(enum DriverState state) - { - static const char* names[static_cast<int>(DriverState::LAST)] = { - "INIT", // - "SCHEDULE", // - "RUNNING", // - "GUI", // - "REDEPLOY_GUI", // - "QUIT_REQUESTED", // - "HANDLE_CHILDREN", // - "EXIT", // - "UNKNOWN" // - "PERFORM_CALLBACKS" // - }; - return names[static_cast<int>(state)]; - } -}; - /// Display information window about the driver /// and its state. void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverControl) @@ -775,7 +756,7 @@ void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverContro } for (size_t i = 0; i < driverInfo.states.size(); ++i) { - ImGui::Text("#%lu: %s", i, DriverHelper::stateToString(driverInfo.states[i])); + ImGui::Text("#%lu: %s", i, DriverInfoHelper::stateToString(driverInfo.states[i])); } ImGui::End(); From c8953a1d7f36c3acfddf9023deaa43ba50055dc2 Mon Sep 17 00:00:00 2001 From: peressounko <Dmitri.Peressounko@Cern.ch> Date: Wed, 6 Jan 2021 14:05:58 +0300 Subject: [PATCH 1701/1751] Bugfix in digits->raw->cell chain (#5087) * MC labels treating fixed * Default file name set * raw digit creation fix * CarryOver and look fix * unique_ptr used * carryOver method restored to avoid RCU trailer splitting, time conversion sec-ns fixed Co-authored-by: Dmitri Peresunko <Dmitri.Peresunko@cern.ch> --- .../PHOS/base/include/PHOSBase/Mapping.h | 19 +-- .../base/include/PHOSBase/PHOSSimParams.h | 14 +- .../PHOS/base/include/PHOSBase/RCUTrailer.h | 23 ++++ Detectors/PHOS/base/src/Mapping.cxx | 10 +- Detectors/PHOS/base/src/RCUTrailer.cxx | 5 + .../include/PHOSReconstruction/AltroDecoder.h | 5 +- .../include/PHOSReconstruction/RawPayload.h | 2 +- .../PHOSReconstruction/RawReaderMemory.h | 9 -- .../PHOS/reconstruction/run/rawReaderFile.cxx | 6 +- .../PHOS/reconstruction/src/AltroDecoder.cxx | 29 ++--- .../PHOS/reconstruction/src/CaloRawFitter.cxx | 10 +- .../reconstruction/src/RawReaderMemory.cxx | 77 +++-------- .../include/PHOSSimulation/RawWriter.h | 38 ++---- Detectors/PHOS/simulation/src/Detector.cxx | 2 +- Detectors/PHOS/simulation/src/Digitizer.cxx | 22 ++-- Detectors/PHOS/simulation/src/RawWriter.cxx | 121 ++++++++---------- .../include/PHOSWorkflow/ClusterizerSpec.h | 5 +- .../PHOSWorkflow/RawToCellConverterSpec.h | 6 +- .../PHOS/workflow/src/CellConverterSpec.cxx | 24 ++-- .../PHOS/workflow/src/ClusterizerSpec.cxx | 51 +++++--- Detectors/PHOS/workflow/src/PublisherSpec.cxx | 2 +- .../workflow/src/RawToCellConverterSpec.cxx | 48 +++++-- 22 files changed, 267 insertions(+), 261 deletions(-) diff --git a/Detectors/PHOS/base/include/PHOSBase/Mapping.h b/Detectors/PHOS/base/include/PHOSBase/Mapping.h index f298728a3217d..ea3b5a9080871 100644 --- a/Detectors/PHOS/base/include/PHOSBase/Mapping.h +++ b/Detectors/PHOS/base/include/PHOSBase/Mapping.h @@ -38,9 +38,10 @@ class Mapping kWrongAbsId, kWrongCaloFlag, kNotInitialized }; - static constexpr short NCHANNELS = 14337; ///< Number of channels starting from 1 - static constexpr short NHWPERDDL = 2048; ///< Number of HW addressed per DDL - static constexpr short NDDL = 14; ///< Total number of DDLs + static constexpr short NCHANNELS = 14337; ///< Number of channels starting from 1 + static constexpr short NHWPERDDL = 2048; ///< Number of HW addressed per DDL + static constexpr short NMaxHWAddress = 3929; ///< Maximal HW address (size of array) + static constexpr short NDDL = 14; ///< Total number of DDLs enum CaloFlag { kHighGain, kLowGain, @@ -69,12 +70,12 @@ class Mapping ErrorStatus constructAbsToHWMatrix(); private: - std::string mPath = ""; ///< path to mapping files - bool mInitialized = false; ///< If conversion tables created - bool mInvInitialized = false; ///< If inverse conversion tables created - short mAbsId[NDDL][NHWPERDDL] = {0}; ///< Conversion table (ddl,branch,fec,chip,channel) to absId - CaloFlag mCaloFlag[NDDL][NHWPERDDL] = {kTRU}; ///< Conversion table (ddl,branch,fec,chip,channel) to absId - short mAbsToHW[NCHANNELS][3][2] = {0}; ///< Conversion table (AbsId,caloFlag) to pair (ddl, hw address) + std::string mPath = ""; ///< path to mapping files + bool mInitialized = false; ///< If conversion tables created + bool mInvInitialized = false; ///< If inverse conversion tables created + short mAbsId[NDDL][NMaxHWAddress] = {0}; ///< Conversion table (ddl,branch,fec,chip,channel) to absId + CaloFlag mCaloFlag[NDDL][NMaxHWAddress] = {kTRU}; ///< Conversion table (ddl,branch,fec,chip,channel) to absId + short mAbsToHW[NCHANNELS][3][2] = {0}; ///< Conversion table (AbsId,caloFlag) to pair (ddl, hw address) ClassDefNV(Mapping, 1); }; // End of Mapping diff --git a/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h b/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h index 3fc9478608242..c777d13bbd8af 100644 --- a/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h +++ b/Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h @@ -35,7 +35,7 @@ struct PHOSSimParams : public o2::conf::ConfigurableParamHelper<PHOSSimParams> { bool mApplyNonLinearity = false; ///< Apply energy non-linearity in digitization bool mApplyDigitization = false; ///< Apply energy digitization in digitization float mAPDNoise = 0.005; ///< RMS of APD noise - float mDigitThreshold = 2.5; ///< minimal energy to keep digit in ADC counts + float mDigitThreshold = 2.; ///< minimal energy to keep digit in ADC counts float mADCwidth = 0.005; ///< width of ADC channel in GeV float mTOFa = 0.5e-9; ///< constant term of TOF resolution float mTOFb = 1.e-9; ///< stohastic term of TOF resolution @@ -43,7 +43,7 @@ struct PHOSSimParams : public o2::conf::ConfigurableParamHelper<PHOSSimParams> { float mCellNonLineaityB = 0.109; ///< Energy scale of cel non-linearity float mCellNonLineaityC = 1.; ///< Overall calibration - float mZSthreshold = 2.5; ///< Zero Suppression threshold + short mZSthreshold = 1; ///< Zero Suppression threshold float mTimeResolutionA = 2.; ///< Time resolution parameter A (in ns) float mTimeResolutionB = 2.; ///< Time resolution parameter B (in ns/GeV) float mTimeResThreshold = 0.5; ///< threshold for time resolution calculation (in GeV) @@ -51,14 +51,18 @@ struct PHOSSimParams : public o2::conf::ConfigurableParamHelper<PHOSSimParams> { float mMaxNoiseTime = 2000.; ///< minimum time in noise channels (in ns) //Parameters used in Raw simulation - float mSampleDecayTime = 0.047619048; ///< Time parameter in Gamma2 function (1/tau, 100.e-9/2.1e-6) + float mSampleDecayTime = 0.091; ///< Time parameter in Gamma2 function (1/tau, 100.e-9/2.1e-6) // //Parameters used in raw data reconstruction + short mSpikeThreshold = 100; ///< Single spike >100 ADC channels + short mBaseLine = 0; ///< + short mPreSamples = 2; ///< number of pre-samples readout before sample (if no pedestal subtrauction) + short mMCOverflow = 970; ///< Overflow level for MC simulations: 1023-(pedestal~50) + float mTimeTick = 100.; ///< ns to PHOS digitization step conversion + // bool mSubtractPedestal = false ; ///< subtract pedestals // bool mCreateSampleQualityOutput = false ; ///< Create stream of sample quality // bool mApplyBadMap = false ; ///< Apply bad map in sample fitting - // short mZeroSuppression = 5; ///< Zero suppression in ADC counts - // short mMaxSampleLength = 35; ///< Maximal length of sample // short mChiMinCut = 0 ; ///< Minimal cut on sample quality // short mChiMaxCut = 1000; ///< Maximal cut on sample quality // std::string mFitterVersion = "default"; ///< version of raw fitter to be used diff --git a/Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h b/Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h index 67ac6374685d1..566ab1141a328 100644 --- a/Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h +++ b/Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h @@ -23,6 +23,27 @@ namespace o2 namespace phos { +union ChannelHeader { + uint32_t mDataWord; + struct { + uint32_t mHardwareAddress : 16; ///< Bits 0 - 15: Hardware address + uint32_t mPayloadSize : 10; ///< Bits 16 - 25: Payload size + uint32_t mZero1 : 3; ///< Bits 26 - 28: zeroed + uint32_t mBadChannel : 1; ///< Bit 29: Bad channel status + uint32_t mMark : 1; ///< Bits 30 - 30: Mark header + }; +}; + +union CaloBunchWord { + uint32_t mDataWord; + struct { + uint32_t mWord2 : 10; ///< Bits 0 - 9 : Word 2 + uint32_t mWord1 : 10; ///< Bits 10 - 19 : Word 1 + uint32_t mWord0 : 10; ///< Bits 20 - 29 : Word 0 + uint32_t mZero : 2; ///< Bits 30 - 31 : zeroed + }; +}; + /// \class RCUTrailer /// \brief Information stored in the RCU trailer /// \ingroup PHOSbase @@ -74,6 +95,8 @@ class RCUTrailer /// \brief Constructor RCUTrailer() = default; + RCUTrailer(const gsl::span<const uint32_t> payloadwords); + /// \brief destructor ~RCUTrailer() = default; diff --git a/Detectors/PHOS/base/src/Mapping.cxx b/Detectors/PHOS/base/src/Mapping.cxx index d380c58f66006..4c2e914431408 100644 --- a/Detectors/PHOS/base/src/Mapping.cxx +++ b/Detectors/PHOS/base/src/Mapping.cxx @@ -35,7 +35,7 @@ Mapping::ErrorStatus Mapping::hwToAbsId(short ddl, short hwAddr, short& absId, C if (ddl < 0 || ddl > 14) { return kWrongDDL; } - if (hwAddr < 0 || hwAddr >= NHWPERDDL) { + if (hwAddr < 0 || hwAddr >= NMaxHWAddress) { return kWrongHWAddress; } @@ -115,6 +115,10 @@ Mapping::ErrorStatus Mapping::setMapping() LOG(FATAL) << "Syntax of mapping file " << p << "/Mod" << m << "RCU" << i << ".data is wrong: no maxHWAddress"; return kNotInitialized; } + if (maxHWAddress > NMaxHWAddress) { + LOG(FATAL) << "Maximal HW address in file " << maxHWAddress << "larger than array size " << NMaxHWAddress << "for /Mod" << m << "RCU" << i << ".data is wrong: no maxHWAddress"; + return kNotInitialized; + } for (short ich = 0; ich < numberOfChannels; ich++) { // 1792 = 2*896 channels connected to each RCU int hwAddress; @@ -137,6 +141,10 @@ Mapping::ErrorStatus Mapping::setMapping() return kNotInitialized; } + if (caloFlag == 2) { //TODO!!!! TRU mapping not known yet + continue; + } + //convert ddl, col,raw caloFlag to AbsId // Converts the absolute numbering into the following array // relid[0] = PHOS Module number diff --git a/Detectors/PHOS/base/src/RCUTrailer.cxx b/Detectors/PHOS/base/src/RCUTrailer.cxx index 0c841f7f767b7..5fbef81c6c62f 100644 --- a/Detectors/PHOS/base/src/RCUTrailer.cxx +++ b/Detectors/PHOS/base/src/RCUTrailer.cxx @@ -16,6 +16,11 @@ using namespace o2::phos; +RCUTrailer::RCUTrailer(const gsl::span<const uint32_t> payloadwords) +{ + constructFromRawPayload(payloadwords); +} + void RCUTrailer::reset() { mRCUId = -1; diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h index b2a68b40f740f..42e4f7a2d6cc1 100644 --- a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h @@ -100,9 +100,8 @@ class AltroDecoder AltroDecoderError::ErrorType_t decode(); /// \brief Get reference to the RCU trailer object - /// \return const reference to the RCU trailer - /// \throw AltroDecoderError with type RCU_TRAILER_ERROR if the RCU trailer was not initialized - const RCUTrailer& getRCUTrailer() const; + /// \return reference to the RCU trailers vector + const RCUTrailer& getRCUTrailer() const { return mRCUTrailer; } /// \brief Get the reference to the channel container /// \return Reference to the channel container diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h index 05089de373b96..8340d9dd66bcc 100644 --- a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h @@ -74,7 +74,7 @@ class RawPayload /// \brief Get the size of the payload /// \return Size of the payload - int getPayloadSize() const { return mPayloadWords.size() * sizeof(uint32_t); } + int getPayloadSize() const { return mPayloadWords.size(); } private: std::vector<uint32_t> mPayloadWords; ///< Payload words (excluding raw header) diff --git a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h index 937410a3a9a2a..30f4852603639 100644 --- a/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h +++ b/Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h @@ -60,15 +60,6 @@ class RawReaderMemory /// it should not be called directly by the user. void nextPage(bool resetPayload = true); - /// \brief Read page with a given index - /// \param page Index of the page to be decoded - /// \throw RawDecodingError if the page cannot be read or header or payload cannot be deocded - /// - /// The reader will try to read the page with a certain index. In - /// case the page cannot be decoded (page index outside range, - /// decoding of header or payload failed), and excpetion is raised. - void readPage(int page); - /// \brief access to the raw header of the current page /// \return Raw header of the current page /// \throw RawDecodingError with HEADER_INVALID if the header was not decoded diff --git a/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx b/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx index c264d78ca1cb4..e2a7d78f0207e 100644 --- a/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx +++ b/Detectors/PHOS/reconstruction/run/rawReaderFile.cxx @@ -100,8 +100,10 @@ int main(int argc, char** argv) o2::phos::AltroDecoder decoder(parser); decoder.decode(); - std::cout << decoder.getRCUTrailer() << std::endl; - for (auto& chan : decoder.getChannels()) { + auto& rcu = decoder.getRCUTrailer(); + auto& channellist = decoder.getChannels(); + std::cout << rcu << std::endl; + for (auto& chan : channellist) { std::cout << "Hw address: " << chan.getHardwareAddress() << std::endl; for (auto& bunch : chan.getBunches()) { std::cout << "BunchLength: " << int(bunch.getBunchLength()) << std::endl; diff --git a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx index 217e5e4e5cc32..181d90107d010 100644 --- a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx @@ -12,6 +12,7 @@ #include "InfoLogger/InfoLogger.hxx" #include "PHOSReconstruction/AltroDecoder.h" #include "PHOSReconstruction/RawReaderMemory.h" +#include "PHOSReconstruction/RawDecodingError.h" #include "DetectorsRaw/RDHUtils.h" #include <FairLogger.h> @@ -46,9 +47,9 @@ AltroDecoderError::ErrorType_t AltroDecoder::decode() void AltroDecoder::readRCUTrailer() { try { - auto payloadwordsOrig = mRawReader.getPayload().getPayloadWords(); - gsl::span<const uint32_t> payloadwords(payloadwordsOrig.data(), payloadwordsOrig.size()); - mRCUTrailer.constructFromRawPayload(payloadwords); + auto payloadwords = mRawReader.getPayload().getPayloadWords(); + gsl::span<const uint32_t> tmp(payloadwords.data(), payloadwords.size()); + mRCUTrailer.constructFromRawPayload(tmp); } catch (RCUTrailer::Error& e) { throw e; } @@ -64,13 +65,18 @@ void AltroDecoder::readChannels() mChannels.clear(); int currentpos = 0; auto& buffer = mRawReader.getPayload().getPayloadWords(); - while (currentpos < buffer.size() - mRCUTrailer.getTrailerSize()) { + + int payloadend = mRCUTrailer.getPayloadSize(); + while (currentpos < payloadend) { auto currentword = buffer[currentpos++]; - if (currentword >> 30 != 1) { + ChannelHeader header = {currentword}; + + if (header.mMark != 1) { + LOG(ERROR) << "Channel header mark not found"; continue; } // starting a new channel - mChannels.emplace_back(currentword & 0xFFF, (currentword >> 16) & 0x3FF); + mChannels.emplace_back(int(header.mHardwareAddress), int(header.mPayloadSize)); auto& currentchannel = mChannels.back(); /// decode all words for channel int numberofwords = (currentchannel.getPayloadSize() + 2) / 3; @@ -101,18 +107,9 @@ void AltroDecoder::readChannels() mChannelsInitialized = true; } -const RCUTrailer& AltroDecoder::getRCUTrailer() const -{ - if (!mRCUTrailer.isInitialized()) { - throw AltroDecoderError::ErrorType_t::RCU_TRAILER_ERROR; // "RCU trailer was not initialized"); - } - return mRCUTrailer; -} - const std::vector<Channel>& AltroDecoder::getChannels() const { - if (!mChannelsInitialized) { + if (!mChannelsInitialized) throw AltroDecoderError::ErrorType_t::CHANNEL_ERROR; // "Channels not initizalized"); - } return mChannels; } diff --git a/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx b/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx index a393d7328c006..05a418a28ddb3 100644 --- a/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx +++ b/Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx @@ -14,9 +14,9 @@ #include "FairLogger.h" #include <gsl/span> -// ROOT sytem #include "PHOSReconstruction/Bunch.h" #include "PHOSReconstruction/CaloRawFitter.h" +#include "PHOSBase/PHOSSimParams.h" using namespace o2::phos; @@ -84,9 +84,9 @@ CaloRawFitter::FitStatus CaloRawFitter::evalKLevel(const Bunch& b) //const ushor return kEmptyBunch; } - const short kSpikeThreshold = 100; //Single spike >100 ADC channels - const float kBaseLine = 1.0; //TODO: set from config - const int kPreSamples = 10; //TODO: set from config + const short kSpikeThreshold = o2::phos::PHOSSimParams::Instance().mSpikeThreshold; + const short kBaseLine = o2::phos::PHOSSimParams::Instance().mBaseLine; + const short kPreSamples = o2::phos::PHOSSimParams::Instance().mPreSamples; float pedMean = 0; float pedRMS = 0; @@ -166,7 +166,7 @@ CaloRawFitter::FitStatus CaloRawFitter::evalKLevel(const Bunch& b) //const ushor mAmp.push_back(amp); mTime.push_back(time); mOverflow.push_back(false); - return kNoTime; //use estimated time + return kOK; //use estimated time } // Find index posK (kLevel is a level of "timestamp" point Tk): diff --git a/Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx b/Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx index f7e9c47bd8e89..99c48aff52d7c 100644 --- a/Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx +++ b/Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx @@ -53,6 +53,10 @@ void RawReaderMemory::init() void RawReaderMemory::next() { + //Reads pages till RCU trailer found + //Several 8kB pages can be concatenated + //RCU trailer expected at the end of payload + //but not at the end of each page mRawPayload.reset(); mCurrentTrailer.reset(); bool isDataTerminated = false; @@ -84,8 +88,11 @@ void RawReaderMemory::next() } // Check if the data continues } while (!isDataTerminated); - // add combined trailer to payload - mRawPayload.appendPayloadWords(mCurrentTrailer.encode()); + try { + mCurrentTrailer.constructFromPayloadWords(mRawBuffer.getDataWords()); + } catch (...) { + throw RawDecodingError::ErrorType_t::HEADER_DECODING; + } } void RawReaderMemory::nextPage(bool doResetPayload) @@ -98,10 +105,12 @@ void RawReaderMemory::nextPage(bool doResetPayload) } mRawHeaderInitialized = false; mPayloadInitialized = false; - // Read header + + // Read RDH header try { mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); - if (RDHDecoder::getOffsetToNext(mRawHeader) == RDHDecoder::getHeaderSize(mRawHeader)) { + while (RDHDecoder::getOffsetToNext(mRawHeader) == RDHDecoder::getHeaderSize(mRawHeader) && + mCurrentPosition < mRawMemoryBuffer.size()) { // No Payload - jump to next rawheader // This will eventually move, depending on whether for events without payload in the SRU we send the RCU trailer mCurrentPosition += RDHDecoder::getHeaderSize(mRawHeader); @@ -114,65 +123,17 @@ void RawReaderMemory::nextPage(bool doResetPayload) if (mCurrentPosition + RDHDecoder::getMemorySize(mRawHeader) > mRawMemoryBuffer.size()) { // Payload incomplete throw RawDecodingError::ErrorType_t::PAYLOAD_DECODING; - } else { - mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + mCurrentPosition + RDHDecoder::getHeaderSize(mRawHeader), RDHDecoder::getMemorySize(mRawHeader) - RDHDecoder::getHeaderSize(mRawHeader))); - - // Read off and chop trailer - // - // Every page gets a trailer. The trailers from the single pages need to be removed. - // There will be a combined trailer which keeps the sum of the payloads for all trailers. - // This will be appended to the chopped payload. - int tralersize = 0; - if (!mCurrentTrailer.isInitialized()) { - try { - mCurrentTrailer.constructFromPayloadWords(mRawBuffer.getDataWords()); - } catch (...) { - throw RawDecodingError::ErrorType_t::HEADER_DECODING; - } - tralersize = mCurrentTrailer.getTrailerSize(); - } else { - RCUTrailer trailer; - try { - trailer.constructFromPayloadWords(mRawBuffer.getDataWords()); - } catch (...) { - throw RawDecodingError::ErrorType_t::HEADER_INVALID; - } - - mCurrentTrailer.setPayloadSize(mCurrentTrailer.getPayloadSize() + trailer.getPayloadSize()); - tralersize = trailer.getTrailerSize(); - } + } - gsl::span<const uint32_t> payloadWithoutTrailer(mRawBuffer.getDataWords().data(), mRawBuffer.getDataWords().size() - tralersize); + mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + mCurrentPosition + RDHDecoder::getHeaderSize(mRawHeader), + RDHDecoder::getMemorySize(mRawHeader) - RDHDecoder::getHeaderSize(mRawHeader))); + gsl::span<const uint32_t> payloadWithoutTrailer(mRawBuffer.getDataWords().data(), mRawBuffer.getNDataWords()); + mRawPayload.appendPayloadWords(payloadWithoutTrailer); + mRawPayload.increasePageCount(); - mRawPayload.appendPayloadWords(payloadWithoutTrailer); - mRawPayload.increasePageCount(); - } mCurrentPosition += RDHDecoder::getOffsetToNext(mRawHeader); /// Assume fixed 8 kB page size } -void RawReaderMemory::readPage(int page) -{ - int currentposition = 8192 * page; - if (currentposition >= mRawMemoryBuffer.size()) { - throw RawDecodingError::ErrorType_t::PAGE_NOTFOUND; - } - mRawHeaderInitialized = false; - mPayloadInitialized = false; - // Read header - try { - mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); - mRawHeaderInitialized = true; - } catch (...) { - throw RawDecodingError::ErrorType_t::HEADER_DECODING; - } - if (currentposition + RDHDecoder::getHeaderSize(mRawHeader) + RDHDecoder::getMemorySize(mRawHeader) >= mRawMemoryBuffer.size()) { - // Payload incomplete - throw RawDecodingError::ErrorType_t::PAYLOAD_DECODING; - } else { - mRawBuffer.readFromMemoryBuffer(gsl::span<const char>(mRawMemoryBuffer.data() + currentposition + RDHDecoder::getHeaderSize(mRawHeader), RDHDecoder::getMemorySize(mRawHeader))); - } -} - const o2::header::RDHAny& RawReaderMemory::getRawHeader() const { if (!mRawHeaderInitialized) { diff --git a/Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h b/Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h index 194d0d29d25c4..2ed3a643599c9 100644 --- a/Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h +++ b/Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h @@ -27,6 +27,7 @@ #include "DataFormatsPHOS/Digit.h" #include "DataFormatsPHOS/TriggerRecord.h" #include "PHOSCalib/CalibParams.h" +#include "PHOSBase/RCUTrailer.h" namespace o2 { @@ -34,9 +35,10 @@ namespace o2 namespace phos { -static constexpr short kNPHOSSAMPLES = 15; ///< Maximal number of samples in altro -static constexpr short kOVERFLOW = 970; ///< Overflow level: 1023-pedestal~50 -static constexpr float kPHOSTIMETICK = 100.e-9; ///< PHOS sampling time step +static constexpr short kNPHOSSAMPLES = 30; ///< Maximal number of samples in altro +static constexpr short kNPRESAMPLES = 2; ///< Number of pre-samples in altro +static constexpr short kOVERFLOW = 970; ///< Overflow level: 1023-pedestal~50 +static constexpr float kPHOSTIMETICK = 100.; ///< PHOS sampling time step in ns (hits/digits keep time in ns) struct AltroBunch { int mStarttime; @@ -48,27 +50,6 @@ struct SRUDigitContainer { std::map<short, std::vector<o2::phos::Digit*>> mChannels; }; -union ChannelHeader { - uint32_t mDataWord; - struct { - uint32_t mHardwareAddress : 16; ///< Bits 0 - 15: Hardware address - uint32_t mPayloadSize : 10; ///< Bits 16 - 25: Payload size - uint32_t mZero1 : 3; ///< Bits 26 - 28: zeroed - uint32_t mBadChannel : 1; ///< Bit 29: Bad channel status - uint32_t mZero2 : 2; ///< Bits 30 - 31: zeroed - }; -}; - -union CaloBunchWord { - uint32_t mDataWord; - struct { - uint32_t mWord2 : 10; ///< Bits 0 - 9 : Word 2 - uint32_t mWord1 : 10; ///< Bits 10 - 19 : Word 1 - uint32_t mWord0 : 10; ///< Bits 20 - 29 : Word 0 - uint32_t mZero : 2; ///< Bits 30 - 31 : zeroed - }; -}; - class RawWriter { public: @@ -94,22 +75,21 @@ class RawWriter std::vector<char>& trailer, std::vector<char>& header) const; protected: - void createRawBunches(const std::vector<o2::phos::Digit*>& digits, std::vector<o2::phos::AltroBunch>& bunchHG, + void createRawBunches(short absId, const std::vector<o2::phos::Digit*>& digits, std::vector<o2::phos::AltroBunch>& bunchHG, std::vector<o2::phos::AltroBunch>& bunchLG, bool& isLGFilled); - std::vector<int> encodeBunchData(const std::vector<int>& data); + std::vector<uint32_t> encodeBunchData(const std::vector<uint32_t>& data); void fillGamma2(float amp, float time, short* samples); // std::tuple<int, int, int> getOnlineID(int towerID); // std::tuple<int, int> getLinkAssignment(int ddlID); - ChannelHeader createChannelHeader(int hardwareAddress, int payloadSize); std::vector<char> createRCUTrailer(int payloadsize, int feca, int fecb, double timesample, double l1phase); private: FileFor_t mFileFor = FileFor_t::kFullDet; ///< Granularity of the output files std::string mOutputLocation = "./"; ///< Rawfile name - std::unique_ptr<o2::phos::Mapping> mMapping; ///< Mapping handler - const CalibParams* mCalibParams = nullptr; ///< PHOS calibration + std::unique_ptr<Mapping> mMapping; ///< Mapping handler + std::unique_ptr<const CalibParams> mCalibParams; ///< PHOS calibration gsl::span<o2::phos::Digit> mDigits; ///< Digits input vector - must be in digitized format including the time response std::vector<SRUDigitContainer> mSRUdata; ///< Internal helper of digits assigned to SRUs std::unique_ptr<o2::raw::RawFileWriter> mRawWriter; ///< Raw writer diff --git a/Detectors/PHOS/simulation/src/Detector.cxx b/Detectors/PHOS/simulation/src/Detector.cxx index 8a64841d18cc9..a6309ccaf092e 100644 --- a/Detectors/PHOS/simulation/src/Detector.cxx +++ b/Detectors/PHOS/simulation/src/Detector.cxx @@ -205,7 +205,7 @@ Bool_t Detector::ProcessHits(FairVolume* v) fMC->TrackPosition(posX, posY, posZ); fMC->TrackMomentum(momX, momY, momZ, energy); Double_t estart = fMC->Etot(); - Double_t time = fMC->TrackTime() * 1.e+9; // time in ns?? To be consistent with EMCAL + Double_t time = fMC->TrackTime() * 1.e+9; // time in ns mCurrentHit = addHit(superParent, detID, math_utils::Point3D<float>(posX, posY, posZ), math_utils::Vector3D<float>(momX, momY, momZ), estart, time, lostenergy); diff --git a/Detectors/PHOS/simulation/src/Digitizer.cxx b/Detectors/PHOS/simulation/src/Digitizer.cxx index 7f85fb83d06ba..d516d7cc80b31 100644 --- a/Detectors/PHOS/simulation/src/Digitizer.cxx +++ b/Detectors/PHOS/simulation/src/Digitizer.cxx @@ -183,14 +183,18 @@ void Digitizer::process(const std::vector<Hit>* hitsBg, const std::vector<Hit>* energy = uncalibrate(energy, absId); - if (energy < o2::phos::PHOSSimParams::Instance().mZSthreshold) { + if (energy <= o2::phos::PHOSSimParams::Instance().mDigitThreshold) { continue; } - digit.setAmplitude(energy); - digit.setHighGain(energy < 1024); //10bit ADC - + digit.setHighGain(energy < o2::phos::PHOSSimParams::Instance().mMCOverflow); //10bit ADC + if (digit.isHighGain()) { + digit.setAmplitude(energy); + } else { + float hglgratio = mCalibParams->getHGLGRatio(absId); + digit.setAmplitude(energy / hglgratio); + } if (o2::phos::PHOSSimParams::Instance().mApplyTimeResolution) { - digit.setTimeStamp(uncalibrateT(timeResolution(digit.getTimeStamp(), energy), absId, digit.isHighGain())); + digit.setTime(uncalibrateT(timeResolution(digit.getTime(), energy), absId, digit.isHighGain())); } digits.push_back(digit); @@ -201,8 +205,8 @@ void Digitizer::process(const std::vector<Hit>* hitsBg, const std::vector<Hit>* // Simulate noise float energy = simulateNoiseEnergy(absId); energy = uncalibrate(energy, absId); - float time = simulateNoiseTime(); - if (energy > o2::phos::PHOSSimParams::Instance().mZSthreshold) { + if (energy > o2::phos::PHOSSimParams::Instance().mDigitThreshold) { + float time = simulateNoiseTime(); digits.emplace_back(absId, energy, time, -1); // current AbsId, energy, random time, no primary } } @@ -225,13 +229,14 @@ float Digitizer::uncalibrate(const float e, const int absId) if (calib > 0) { return floor(e / calib); } else { - return 0; // TODO apply de-calibration from OCDB + return 0; } } //_______________________________________________________________________ float Digitizer::uncalibrateT(const float time, const int absId, bool isHighGain) { // Decalibrate EMC digit, i.e. transform from energy to ADC counts a factor read from CDB + // note time in seconds if (isHighGain) { return time + mCalibParams->getHGTimeCalib(absId); } else { @@ -242,6 +247,7 @@ float Digitizer::uncalibrateT(const float time, const int absId, bool isHighGain float Digitizer::timeResolution(const float time, const float e) { // apply time resolution + // time measured in seconds float timeResolution = o2::phos::PHOSSimParams::Instance().mTimeResolutionA + o2::phos::PHOSSimParams::Instance().mTimeResolutionB / diff --git a/Detectors/PHOS/simulation/src/RawWriter.cxx b/Detectors/PHOS/simulation/src/RawWriter.cxx index a17c00886240c..f31c0832b2fdb 100644 --- a/Detectors/PHOS/simulation/src/RawWriter.cxx +++ b/Detectors/PHOS/simulation/src/RawWriter.cxx @@ -13,7 +13,6 @@ #include <fmt/core.h> #include <gsl/span> #include <TSystem.h> -#include "PHOSBase/RCUTrailer.h" #include "PHOSSimulation/RawWriter.h" #include "PHOSBase/PHOSSimParams.h" #include "CCDB/CcdbApi.h" @@ -28,7 +27,7 @@ void RawWriter::init() // initialize mapping if (!mMapping) { - mMapping = std::unique_ptr<o2::phos::Mapping>(new o2::phos::Mapping()); + mMapping = std::make_unique<o2::phos::Mapping>(); if (!mMapping) { LOG(ERROR) << "Failed to initialize mapping"; } @@ -64,7 +63,7 @@ void RawWriter::digitsToRaw(gsl::span<o2::phos::Digit> digitsbranch, gsl::span<o { if (!mCalibParams) { if (o2::phos::PHOSSimParams::Instance().mCCDBPath.compare("localtest") == 0) { - mCalibParams = new CalibParams(1); // test default calibration + mCalibParams = std::make_unique<CalibParams>(1); // test default calibration LOG(INFO) << "[RawWriter] No reading calibration from ccdb requested, set default"; } else { LOG(INFO) << "[RawWriter] getting calibration object from ccdb"; @@ -76,7 +75,7 @@ void RawWriter::digitsToRaw(gsl::span<o2::phos::Digit> digitsbranch, gsl::span<o // if(tr!=triggerbranch.end()){ // eventTime = (*tr).getBCData().getTimeNS() ; // } - mCalibParams = ccdb.retrieveFromTFileAny<o2::phos::CalibParams>("PHOS/Calib", metadata, eventTime); + // mCalibParams = ccdb.retrieveFromTFileAny<o2::phos::CalibParams>("PHOS/Calib", metadata, eventTime); if (!mCalibParams) { LOG(FATAL) << "[RawWriter] can not get calibration object from ccdb"; } @@ -115,7 +114,7 @@ bool RawWriter::processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, co } // Create and fill DMA pages for each channel - std::vector<int> rawbunches; + std::vector<uint32_t> rawbunches; std::vector<char> payload; std::vector<AltroBunch> rawbunchesHG, rawbunchesLG; @@ -125,15 +124,13 @@ bool RawWriter::processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, co for (auto ch = srucont->mChannels.cbegin(); ch != srucont->mChannels.cend(); ch++) { // Find out hardware address of the channel - bool isLGfilled = 0; - createRawBunches(ch->second, rawbunchesHG, rawbunchesLG, isLGfilled); + createRawBunches(ch->first, ch->second, rawbunchesHG, rawbunchesLG, isLGfilled); short hwAddrHG; //High gain always filled if (mMapping->absIdTohw(ch->first, 0, ddl, hwAddrHG) != o2::phos::Mapping::kOK) { LOG(ERROR) << "Wrong AbsId" << ch->first; } - rawbunches.clear(); for (auto& bunch : rawbunchesHG) { rawbunches.push_back(bunch.mADCs.size() + 2); @@ -142,17 +139,19 @@ bool RawWriter::processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, co rawbunches.push_back(adc); } } - if (!rawbunches.size()) { + if (rawbunches.size() == 0) { continue; } - auto encodedbunches = encodeBunchData(rawbunches); - auto chanhead = createChannelHeader(hwAddrHG, rawbunches.size()); - char* chanheadwords = reinterpret_cast<char*>(&chanhead); - + ChannelHeader chanhead = {0}; + chanhead.mHardwareAddress = hwAddrHG; + chanhead.mPayloadSize = rawbunches.size(); + chanhead.mMark = 1; //mark channel header + char* chanheadwords = reinterpret_cast<char*>(&chanhead.mDataWord); for (int iword = 0; iword < sizeof(ChannelHeader) / sizeof(char); iword++) { payload.emplace_back(chanheadwords[iword]); } + char* channelwords = reinterpret_cast<char*>(encodedbunches.data()); for (auto iword = 0; iword < encodedbunches.size() * sizeof(int) / sizeof(char); iword++) { payload.emplace_back(channelwords[iword]); @@ -165,7 +164,7 @@ bool RawWriter::processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, co } rawbunches.clear(); - for (auto& bunch : rawbunchesHG) { + for (auto& bunch : rawbunchesLG) { rawbunches.push_back(bunch.mADCs.size() + 2); rawbunches.push_back(bunch.mStarttime); for (auto adc : bunch.mADCs) { @@ -174,8 +173,12 @@ bool RawWriter::processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, co } encodedbunches = encodeBunchData(rawbunches); - chanhead = createChannelHeader(hwAddrLG, encodedbunches.size() * 3 - 2); - chanheadwords = reinterpret_cast<char*>(&chanhead); + ChannelHeader chanheadLG = {0}; + chanheadLG.mHardwareAddress = hwAddrLG; + chanheadLG.mPayloadSize = rawbunches.size(); + chanheadLG.mMark = 1; //mark channel header + + chanheadwords = reinterpret_cast<char*>(&chanheadLG.mDataWord); for (int iword = 0; iword < sizeof(ChannelHeader) / sizeof(char); iword++) { payload.emplace_back(chanheadwords[iword]); } @@ -202,28 +205,21 @@ bool RawWriter::processTrigger(const gsl::span<o2::phos::Digit> digitsbranch, co return true; } -void RawWriter::createRawBunches(const std::vector<o2::phos::Digit*>& channelDigits, std::vector<o2::phos::AltroBunch>& bunchHG, +void RawWriter::createRawBunches(short absId, const std::vector<o2::phos::Digit*>& channelDigits, std::vector<o2::phos::AltroBunch>& bunchHG, std::vector<o2::phos::AltroBunch>& bunchLG, bool& isLGFilled) { isLGFilled = false; short samples[kNPHOSSAMPLES] = {0}; - float hglgratio = 16.; + float hglgratio = mCalibParams->getHGLGRatio(absId); for (auto dig : channelDigits) { //Convert energy and time to ADC counts and time ticks - float ampADC = dig->getAmplitude() / mCalibParams->getGain(dig->getAbsId()); - if (ampADC > kOVERFLOW) { //High Gain in saturation, fill also Low Gain + float ampADC = dig->getAmplitude(); // Digits amplitude already in ADC channels + if (ampADC > o2::phos::PHOSSimParams::Instance().mMCOverflow) { //High Gain in saturation, fill also Low Gain isLGFilled = true; } - float timeTicks = dig->getTimeStamp(); - //If LowGain will be used, apply LG time decalibration (HG will be omitted in this case in rec.) - if (isLGFilled) { - timeTicks += mCalibParams->getLGTimeCalib(dig->getAbsId()); - hglgratio = mCalibParams->getHGLGRatio(dig->getAbsId()); - } else { - timeTicks += mCalibParams->getHGTimeCalib(dig->getAbsId()); - } - timeTicks /= kPHOSTIMETICK; + float timeTicks = dig->getTime(); //time in ns + timeTicks /= o2::phos::PHOSSimParams::Instance().mTimeTick; //time in PHOS ticks //Add to current sample contribution from digit fillGamma2(ampADC, timeTicks, samples); } @@ -233,9 +229,9 @@ void RawWriter::createRawBunches(const std::vector<o2::phos::Digit*>& channelDig bunchHG.clear(); AltroBunch currentBunch; //Note reverse time order - for (int i = kNPHOSSAMPLES - 1; i--;) { + for (int i = kNPHOSSAMPLES; i--;) { if (samples[i] > zs) { - currentBunch.mADCs.emplace_back(std::min(kOVERFLOW, samples[i])); + currentBunch.mADCs.emplace_back(std::min(o2::phos::PHOSSimParams::Instance().mMCOverflow, samples[i])); } else { //end of sample? if (currentBunch.mADCs.size()) { currentBunch.mStarttime = i + 1; @@ -244,12 +240,16 @@ void RawWriter::createRawBunches(const std::vector<o2::phos::Digit*>& channelDig } } } + if (currentBunch.mADCs.size()) { + bunchHG.push_back(currentBunch); + currentBunch.mADCs.clear(); + } if (isLGFilled) { bunchLG.clear(); currentBunch.mADCs.clear(); - for (int i = kNPHOSSAMPLES - 1; i--;) { + for (int i = kNPHOSSAMPLES; i--;) { if (samples[i] > zs * hglgratio) { - currentBunch.mADCs.emplace_back(std::min(kOVERFLOW, short(samples[i] / hglgratio))); + currentBunch.mADCs.emplace_back(std::min(o2::phos::PHOSSimParams::Instance().mMCOverflow, short(samples[i] / hglgratio))); } else { //end of sample? if (currentBunch.mADCs.size()) { currentBunch.mStarttime = i + 1; @@ -258,6 +258,9 @@ void RawWriter::createRawBunches(const std::vector<o2::phos::Digit*>& channelDig } } } + if (currentBunch.mADCs.size()) { + bunchLG.push_back(currentBunch); + } } } @@ -265,17 +268,20 @@ void RawWriter::fillGamma2(float amp, float time, short* samples) { //Simulate Gamma2 signal added to current sample in PHOS float alpha = o2::phos::PHOSSimParams::Instance().mSampleDecayTime; - + amp += 0.5; //rounding err for (int i = 0; i < kNPHOSSAMPLES; i++) { - float x = alpha * (i - time); + if (i - o2::phos::PHOSSimParams::Instance().mPreSamples < time) { + continue; + } + float x = alpha * (i - o2::phos::PHOSSimParams::Instance().mPreSamples - time); float y = 0.25 * amp * x * x * std::exp(2. - x); //0.25*exp(-2) normalization to unity samples[i] += short(y); } } -std::vector<int> RawWriter::encodeBunchData(const std::vector<int>& data) +std::vector<uint32_t> RawWriter::encodeBunchData(const std::vector<uint32_t>& data) { - std::vector<int> encoded; + std::vector<uint32_t> encoded; CaloBunchWord currentword; currentword.mDataWord = 0; int wordnumber = 0; @@ -305,16 +311,6 @@ std::vector<int> RawWriter::encodeBunchData(const std::vector<int>& data) return encoded; } -ChannelHeader RawWriter::createChannelHeader(int hardwareAddress, int payloadSize) -{ - ChannelHeader header; - header.mDataWord = 0; - header.mHardwareAddress = hardwareAddress; - header.mPayloadSize = payloadSize; - header.mZero2 = 1; //mark channel header - return header; -} - std::vector<char> RawWriter::createRCUTrailer(int payloadsize, int feca, int fecb, double timesample, double l1phase) { RCUTrailer trailer; @@ -333,32 +329,15 @@ int RawWriter::carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> const char* ptr, int maxSize, int splitID, std::vector<char>& trailer, std::vector<char>& header) const { - int offs = ptr - &data[0]; // offset wrt the head of the payload - // make sure ptr and end of the suggested block are within the payload - assert(offs >= 0 && size_t(offs + maxSize) <= data.size()); - - // Read trailer template from the end of payload - gsl::span<const uint32_t> payloadwords(reinterpret_cast<const uint32_t*>(data.data()), data.size() / sizeof(uint32_t)); - auto rcutrailer = RCUTrailer::constructFromPayloadWords(payloadwords); - int sizeNoTrailer = maxSize - rcutrailer.getTrailerSize() * sizeof(uint32_t); - // calculate payload size for RCU trailer: - // assume actualsize is in byte - // Payload size is defined as the number of 32-bit payload words - // -> actualSize to be converted to size of 32 bit words - auto payloadsize = sizeNoTrailer / sizeof(uint32_t); - rcutrailer.setPayloadSize(payloadsize); - auto trailerwords = rcutrailer.encode(); - trailer.resize(trailerwords.size() * sizeof(uint32_t)); - memcpy(trailer.data(), trailerwords.data(), trailer.size()); - // Size to return differs between intermediate pages and last page - // - intermediate page: Size of the trailer needs to be removed as the trailer gets appended - // - last page: Size of the trailer needs to be included as the trailer gets replaced - int bytesLeft = data.size() - (ptr - &data[0]); - bool lastPage = bytesLeft <= maxSize; + constexpr int phosTrailerSize = 36; + int offs = ptr - &data[0]; // offset wrt the head of the payload + assert(offs >= 0 && size_t(offs + maxSize) <= data.size()); // make sure ptr and end of the suggested block are within the payload + int leftBefore = data.size() - offs; // payload left before this splitting + int leftAfter = leftBefore - maxSize; // what would be left after the suggested splitting int actualSize = maxSize; - if (!lastPage) { - actualSize = sizeNoTrailer; + if (leftAfter && leftAfter <= phosTrailerSize) { // avoid splitting the trailer or writing only it. + actualSize -= (phosTrailerSize - leftAfter) + 4; // (as we work with int, not char in decoding) } return actualSize; } diff --git a/Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h b/Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h index bd9e08a75049d..1268511c9c6e5 100644 --- a/Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h +++ b/Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h @@ -39,7 +39,7 @@ class ClusterizerSpec : public framework::Task { public: /// \brief Constructor - ClusterizerSpec(bool propagateMC) : framework::Task(), mPropagateMC(propagateMC) {} + ClusterizerSpec(bool propagateMC, bool scanDigits) : framework::Task(), mPropagateMC(propagateMC), mUseDigits(scanDigits) {} /// \brief Destructor ~ClusterizerSpec() override = default; @@ -57,7 +57,8 @@ class ClusterizerSpec : public framework::Task void run(framework::ProcessingContext& ctx) final; private: - bool mPropagateMC = false; ///< Switch whether to process MC true labels + bool mPropagateMC = false; ///< Switch whether to process MC true labels + bool mUseDigits = false; o2::phos::Clusterer mClusterizer; ///< Clusterizer object std::vector<o2::phos::Cluster> mOutputClusters; std::vector<o2::phos::TriggerRecord> mOutputClusterTrigRecs; diff --git a/Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h b/Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h index 9afc397c98464..9244c4fd339ca 100644 --- a/Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h +++ b/Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h @@ -15,6 +15,7 @@ #include "DataFormatsPHOS/Cell.h" #include "DataFormatsPHOS/TriggerRecord.h" #include "PHOSBase/Mapping.h" +#include "PHOSCalib/CalibParams.h" #include "PHOSReconstruction/CaloRawFitter.h" #include "PHOSReconstruction/RawReaderError.h" @@ -64,8 +65,9 @@ class RawToCellConverterSpec : public framework::Task bool mFillChi2 = false; ///< Fill output with quality of samples bool mCombineGHLG = true; ///< Combine or not HG and LG channels (def: combine, LED runs: not combine) bool mPedestalRun = false; ///< Analyze pedestal run (calculate pedestal mean and RMS) - std::unique_ptr<o2::phos::Mapping> mMapping = nullptr; ///!<! Mapping - std::unique_ptr<o2::phos::CaloRawFitter> mRawFitter; ///!<! Raw fitter + std::unique_ptr<Mapping> mMapping; ///< Mapping + std::unique_ptr<CalibParams> mCalibParams; ///!<! PHOS calibration + std::unique_ptr<CaloRawFitter> mRawFitter; ///!<! Raw fitter std::vector<o2::phos::Cell> mOutputCells; ///< Container with output cells std::vector<o2::phos::TriggerRecord> mOutputTriggerRecords; ///< Container with output cells std::vector<o2::phos::RawReaderError> mOutputHWErrors; ///< Errors occured in reading data diff --git a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx index 406b66e46df45..224f61b998a68 100644 --- a/Detectors/PHOS/workflow/src/CellConverterSpec.cxx +++ b/Detectors/PHOS/workflow/src/CellConverterSpec.cxx @@ -45,16 +45,13 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) auto digits = ctx.inputs().get<std::vector<o2::phos::Digit>>("digits"); auto digitsTR = ctx.inputs().get<std::vector<o2::phos::TriggerRecord>>("digitTriggerRecords"); - gsl::span<const char> labelbuffer; + std::unique_ptr<const o2::dataformats::MCTruthContainer<o2::phos::MCLabel>> truthcont(nullptr); if (mPropagateMC) { - labelbuffer = ctx.inputs().get<gsl::span<char>>("digitsmctr"); - // auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("digitsmctr"); - + truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("digitsmctr"); mOutputTruthCont.clear(); mOutputTruthMap.clear(); } - o2::dataformats::ConstMCTruthContainerView<o2::phos::MCLabel> truthcont(labelbuffer); - LOG(INFO) << "[PHOSCellConverter - run] Received " << digits.size() << " digits and " << digitsTR.size() << " TriggerRecords"; + LOG(INFO) << "[PHOSCellConverter - run] Received " << digits.size() << " digits and " << digitsTR.size() << " TriggerRecords" << truthcont->getNElements() << " MC labels"; //Get TimeStamp from TriggerRecord if (!mBadMap) { @@ -101,24 +98,25 @@ void CellConverterSpec::run(framework::ProcessingContext& ctx) // chantype = ChannelType_t::TRU; mOutputCells.emplace_back(dig.getAbsId(), dig.getAmplitude(), dig.getTime(), chantype); - icell++; if (mPropagateMC) { //copy MC info, int iLab = dig.getLabel(); if (iLab > -1) { - mOutputTruthCont.addElements(labelIndex, truthcont.getLabels(iLab)); + mOutputTruthCont.addElements(labelIndex, truthcont->getLabels(iLab)); mOutputTruthMap.emplace_back(icell); //Relate cell index and label index labelIndex++; } } + icell++; } mOutputCellTrigRecs.emplace_back(tr.getBCData(), indexStart, mOutputCells.size()); } - LOG(INFO) << "[PHOSCellConverter - run] Writing " << mOutputCells.size() << " cells and " << mOutputCellTrigRecs.size() << " Trig Records "; + LOG(INFO) << "[PHOSCellConverter - run] Writing " << mOutputCells.size() << " cells, " << mOutputCellTrigRecs.size() << " Trig Records " << mOutputTruthCont.getNElements() << " PHOS labels "; + ; ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLS", 0, o2::framework::Lifetime::Timeframe}, mOutputCells); ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLTRIGREC", 0, o2::framework::Lifetime::Timeframe}, mOutputCellTrigRecs); if (mPropagateMC) { - //ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthCont); - //ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthMap); + ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthCont); + ctx.outputs().snapshot(o2::framework::Output{"PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthMap); } } @@ -132,8 +130,8 @@ o2::framework::DataProcessorSpec o2::phos::reco_workflow::getCellConverterSpec(b outputs.emplace_back("PHS", "CELLTRIGREC", 0, o2::framework::Lifetime::Timeframe); if (propagateMC) { inputs.emplace_back("digitsmctr", "PHS", "DIGITSMCTR", 0, o2::framework::Lifetime::Timeframe); - //outputs.emplace_back("PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe); - //outputs.emplace_back("PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("PHS", "CELLSMCTR", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("PHS", "CELLSMCMAP", 0, o2::framework::Lifetime::Timeframe); } return o2::framework::DataProcessorSpec{"PHOSCellConverterSpec", inputs, diff --git a/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx b/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx index 6c20378e450a6..0ce66fc2d9928 100644 --- a/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx +++ b/Detectors/PHOS/workflow/src/ClusterizerSpec.cxx @@ -27,7 +27,8 @@ void ClusterizerSpec::init(framework::InitContext& ctx) void ClusterizerSpec::run(framework::ProcessingContext& ctx) { - if (ctx.inputs().isValid("digits")) { + printf("CellCLusterizerSpec: Run \n"); + if (mUseDigits) { LOG(DEBUG) << "PHOSClusterizer - run on digits called"; auto dataref = ctx.inputs().get("digits"); @@ -42,30 +43,46 @@ void ClusterizerSpec::run(framework::ProcessingContext& ctx) // results in [7968:PHOSClusterizerSpec]: [20:51:44][ERROR] Exception caught: Inconsistent serialization method for extracting span auto digits = ctx.inputs().get<std::vector<o2::phos::Digit>>("digits"); auto digitsTR = ctx.inputs().get<std::vector<o2::phos::TriggerRecord>>("digitTriggerRecords"); - - // auto digitsTR = ctx.inputs().get<std::vector<o2::phos::TriggerRecord>>("digitTriggerRecords"); LOG(DEBUG) << "[PHOSClusterizer - run] Received " << digitsTR.size() << " TR, running clusterizer ..."; - auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("digitsmctr"); - mClusterizer.process(digits, digitsTR, truthcont.get(), &mOutputClusters, &mOutputClusterTrigRecs, &mOutputTruthCont); // Find clusters on digits (pass by ref) + // const o2::dataformats::MCTruthContainer<MCLabel>* truthcont=nullptr; + // if(mPropagateMC){ + // truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("digitsmctr"); + // } + // mClusterizer.process(digits, digitsTR, truthcont.get(), &mOutputClusters, &mOutputClusterTrigRecs, &mOutputTruthCont); // Find clusters on digits (pass by ref) } else { LOG(DEBUG) << "PHOSClusterizer - run run on cells called"; - auto dataref = ctx.inputs().get("cells"); - auto const* phosheader = o2::framework::DataRefUtils::getHeader<o2::phos::PHOSBlockHeader*>(dataref); - if (!phosheader->mHasPayload) { - LOG(DEBUG) << "[PHOSClusterizer - run] No more cells" << std::endl; - ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); - return; - } + // auto dataref = ctx.inputs().get("cells"); + // auto const* phosheader = o2::framework::DataRefUtils::getHeader<o2::phos::PHOSBlockHeader*>(dataref); + // if (!phosheader->mHasPayload) { + // LOG(DEBUG) << "[PHOSClusterizer - run] No more cells" << std::endl; + // ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); + // return; + // } auto cells = ctx.inputs().get<gsl::span<o2::phos::Cell>>("cells"); LOG(DEBUG) << "[PHOSClusterizer - run] Received " << cells.size() << " cells, running clusterizer ..."; auto cellsTR = ctx.inputs().get<gsl::span<o2::phos::TriggerRecord>>("cellTriggerRecords"); - auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("cellsmctr"); - auto truthmap = ctx.inputs().get<gsl::span<uint>>("cellssmcmap"); - mClusterizer.processCells(cells, cellsTR, truthcont.get(), truthmap, &mOutputClusters, &mOutputClusterTrigRecs, &mOutputTruthCont); // Find clusters on digits (pass by ref) + printf("-------------Cells------------\n"); + for (auto cTR : cellsTR) { + printf("new Event \n"); + int firstCellInEvent = cTR.getFirstEntry(); + int lastCellInEvent = firstCellInEvent + cTR.getNumberOfObjects(); + for (int i = firstCellInEvent; i < lastCellInEvent; i++) { + Cell c = cells[i]; + printf("cell[%d]: absId=%d, amp=%f, Time=%e \n", i, c.getAbsId(), c.getEnergy(), c.getTime()); + } + } + + // const o2::dataformats::MCTruthContainer<MCLabel>* truthcont=nullptr; + // gsl::span<const unsigned int> mcmap ; + // if(mPropagateMC){ + // truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::phos::MCLabel>*>("cellsmctr"); + // truthmap = ctx.inputs().get<gsl::span<uint>>("cellssmcmap"); + // } + // mClusterizer.processCells(cells, cellsTR, truthcont.get(), truthmap, &mOutputClusters, &mOutputClusterTrigRecs, &mOutputTruthCont); // Find clusters on digits (pass by ref) } LOG(DEBUG) << "[PHOSClusterizer - run] Writing " << mOutputClusters.size() << " clusters, " << mOutputClusterTrigRecs.size() << "TR and " << mOutputTruthCont.getIndexedSize() << " Labels"; @@ -96,7 +113,7 @@ o2::framework::DataProcessorSpec o2::phos::reco_workflow::getClusterizerSpec(boo return o2::framework::DataProcessorSpec{"PHOSClusterizerSpec", inputs, outputs, - o2::framework::adaptFromTask<o2::phos::reco_workflow::ClusterizerSpec>(propagateMC)}; + o2::framework::adaptFromTask<o2::phos::reco_workflow::ClusterizerSpec>(propagateMC, true)}; } o2::framework::DataProcessorSpec o2::phos::reco_workflow::getCellClusterizerSpec(bool propagateMC) @@ -119,5 +136,5 @@ o2::framework::DataProcessorSpec o2::phos::reco_workflow::getCellClusterizerSpec return o2::framework::DataProcessorSpec{"PHOSClusterizerSpec", inputs, outputs, - o2::framework::adaptFromTask<o2::phos::reco_workflow::ClusterizerSpec>(propagateMC)}; + o2::framework::adaptFromTask<o2::phos::reco_workflow::ClusterizerSpec>(propagateMC, false)}; } diff --git a/Detectors/PHOS/workflow/src/PublisherSpec.cxx b/Detectors/PHOS/workflow/src/PublisherSpec.cxx index 574a447552ab0..a170eb8aa73fd 100644 --- a/Detectors/PHOS/workflow/src/PublisherSpec.cxx +++ b/Detectors/PHOS/workflow/src/PublisherSpec.cxx @@ -163,7 +163,7 @@ o2::framework::DataProcessorSpec getPublisherSpec(PublisherConf const& config, b {createOutputSpecs()}, o2::framework::AlgorithmSpec(initFunction), o2::framework::Options{ - {"infile", o2::framework::VariantType::String, "", {"Name of the input file"}}, + {"infile", o2::framework::VariantType::String, "phosdigits.root", {"Name of the input file"}}, {"treename", o2::framework::VariantType::String, config.defaultTreeName.c_str(), {"Name of input tree"}}, {dtb.option.c_str(), o2::framework::VariantType::String, dtb.defval.c_str(), {dtb.help.c_str()}}, {dttrb.option.c_str(), o2::framework::VariantType::String, dttrb.defval.c_str(), {dttrb.help.c_str()}}, diff --git a/Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx b/Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx index 3c4ff13a388fc..4951c4d8bcd48 100644 --- a/Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx @@ -17,7 +17,9 @@ #include "DataFormatsPHOS/TriggerRecord.h" #include "DetectorsRaw/RDHUtils.h" #include "Framework/InputRecordWalker.h" +#include "CCDB/CcdbApi.h" #include "PHOSBase/Mapping.h" +#include "PHOSBase/PHOSSimParams.h" #include "PHOSReconstruction/Bunch.h" #include "PHOSReconstruction/CaloRawFitter.h" #include "PHOSReconstruction/AltroDecoder.h" @@ -41,6 +43,27 @@ void RawToCellConverterSpec::init(framework::InitContext& ctx) } } + if (!mCalibParams) { + if (o2::phos::PHOSSimParams::Instance().mCCDBPath.compare("localtest") == 0) { + mCalibParams = std::make_unique<CalibParams>(1); // test default calibration + LOG(INFO) << "[RawToCellConverterSpec] No reading calibration from ccdb requested, set default"; + } else { + LOG(INFO) << "[RawToCellConverterSpec] getting calibration object from ccdb"; + o2::ccdb::CcdbApi ccdb; + std::map<std::string, std::string> metadata; + ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation + // auto tr = triggerbranch.begin(); + double eventTime = -1; + // if(tr!=triggerbranch.end()){ + // eventTime = (*tr).getBCData().getTimeNS() ; + // } + // mCalibParams = ccdb.retrieveFromTFileAny<o2::phos::CalibParams>("PHOS/Calib", metadata, eventTime); + if (!mCalibParams) { + LOG(FATAL) << "[RawToCellConverterSpec] can not get calibration object from ccdb"; + } + } + } + auto fitmethod = ctx.options().get<std::string>("fitmethod"); if (fitmethod == "default") { LOG(INFO) << "Using default raw fitter"; @@ -70,7 +93,7 @@ void RawToCellConverterSpec::init(framework::InitContext& ctx) void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) { // Cache cells from bunch crossings as the component reads timeframes from many links consecutively - std::map<o2::InteractionRecord, std::shared_ptr<std::vector<o2::phos::Cell>>> cellBuffer; // Internal cell buffer + std::map<o2::InteractionRecord, std::shared_ptr<std::vector<o2::phos::Cell>>> cellBuffer; // Internal cell buffer/ int firstEntry = 0; mOutputHWErrors.clear(); if (mFillChi2) { @@ -80,6 +103,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) for (const auto& rawData : framework::InputRecordWalker(ctx.inputs())) { o2::phos::RawReaderMemory rawreader(o2::framework::DataRefUtils::as<const char>(rawData)); + // loop over all the DMA pages while (rawreader.hasNext()) { try { @@ -126,12 +150,12 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) char e = (char)err; mOutputHWErrors.emplace_back(ddl, 16, e); //assign general header errors to non-existing FEE 16 } - // Loop over all the channels - for (auto& chan : decoder.getChannels()) { - + auto& rcu = decoder.getRCUTrailer(); + auto& channellist = decoder.getChannels(); + // Loop over all the channels for this RCU + for (auto& chan : channellist) { short absId; Mapping::CaloFlag caloFlag; - short fee; char e2 = CheckHWAddress(ddl, chan.getHardwareAddress(), fee); if (e2) { @@ -145,6 +169,9 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) } if (caloFlag != Mapping::kTRU) { //HighGain or LowGain CaloRawFitter::FitStatus fitResults = mRawFitter->evaluate(chan.getBunches()); + if (fitResults == CaloRawFitter::FitStatus::kNoTime) { + mOutputHWErrors.emplace_back(ddl, fee, (char)5); //Time evaluation error occured + } if (mFillChi2) { for (int is = 0; is < mRawFitter->getNsamples(); is++) { if (!mRawFitter->isOverflow(is)) { //Overflow is will show wrong chi2 @@ -155,11 +182,16 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) } } } - if (fitResults == CaloRawFitter::FitStatus::kOK) { + if (fitResults == CaloRawFitter::FitStatus::kOK || fitResults == CaloRawFitter::FitStatus::kNoTime) { //TODO: which results should be accepted? full configurable list for (int is = 0; is < mRawFitter->getNsamples(); is++) { - if (!mRawFitter->isOverflow(is) || caloFlag != o2::phos::Mapping::kHighGain) { //do not use HighGain if sample saturated. In LG special fitting is used - currentCellContainer->emplace_back(absId, mRawFitter->getAmp(is), mRawFitter->getTime(is), (ChannelType_t)caloFlag); + if (caloFlag == Mapping::kHighGain && !mRawFitter->isOverflow(is)) { + currentCellContainer->emplace_back(absId, mRawFitter->getAmp(is), + mRawFitter->getTime(is) * o2::phos::PHOSSimParams::Instance().mTimeTick, (ChannelType_t)caloFlag); + } + if (caloFlag == Mapping::kLowGain) { + currentCellContainer->emplace_back(absId, mRawFitter->getAmp(is), + mRawFitter->getTime(is) * o2::phos::PHOSSimParams::Instance().mTimeTick, (ChannelType_t)caloFlag); } } } From d89052b68a070ef22bbdc6f4c45b1ecfdd9f9f6f Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Wed, 6 Jan 2021 15:40:53 +0000 Subject: [PATCH 1702/1751] Fix nCand=0 case (#5125) --- Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx index 475f88d72113f..5ccbc145a4d0d 100644 --- a/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx +++ b/Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx @@ -179,6 +179,8 @@ struct lambdakzeroproducer { } fitter.getTrack(0).getPxPyPzGlo(pvec0); fitter.getTrack(1).getPxPyPzGlo(pvec1); + } else { + continue; } //Apply selections so a skimmed table is created only From 86251f703ad7b39da8b0e3b63566056944a2183e Mon Sep 17 00:00:00 2001 From: dstocco <dstocco@users.noreply.github.com> Date: Wed, 6 Jan 2021 17:08:47 +0100 Subject: [PATCH 1703/1751] Match all subspecs unless one subspec is passed explicitely (#5121) --- .../include/MIDWorkflow/RawDecoderSpec.h | 3 +- .../MUON/MID/Workflow/src/RawDecoderSpec.cxx | 29 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h index 84fca6bccc5d7..f662d10681eb1 100644 --- a/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h +++ b/Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h @@ -26,7 +26,8 @@ namespace o2 namespace mid { framework::DataProcessorSpec getRawDecoderSpec(bool isDebugMode = false); -framework::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, size_t subSpec = 0); +framework::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay); +framework::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, header::DataHeader::SubSpecificationType subSpec); } // namespace mid } // namespace o2 diff --git a/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx b/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx index 307620db2fad3..2b83d571e56fe 100644 --- a/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx +++ b/Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx @@ -86,22 +86,33 @@ class RawDecoderDeviceDPL unsigned int mNROFs{0}; /// Total number of processed ROFs }; -of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode) -{ - return getRawDecoderSpec(isDebugMode, FEEIdConfig(), CrateMasks(), ElectronicsDelay(), 0); -} - -of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, size_t subSpec) +of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, const std::vector<of::InputSpec>& inputSpecs, o2::header::DataHeader::SubSpecificationType subSpecType) { - header::DataHeader::SubSpecificationType subSpecType(subSpec); - std::vector<of::InputSpec> inputSpecs{of::InputSpec{"mid_raw", of::ConcreteDataTypeMatcher{header::gDataOriginMID, header::gDataDescriptionRawData}, of::Lifetime::Timeframe}}; std::vector<of::OutputSpec> outputSpecs{of::OutputSpec{header::gDataOriginMID, "DECODED", subSpecType, of::Lifetime::Timeframe}, of::OutputSpec{header::gDataOriginMID, "DECODEDROF", subSpecType, of::Lifetime::Timeframe}}; - return of::DataProcessorSpec{ "MIDRawDecoder", {inputSpecs}, {outputSpecs}, of::adaptFromTask<o2::mid::RawDecoderDeviceDPL>(isDebugMode, feeIdConfig, crateMasks, electronicsDelay, subSpecType)}; } + +of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode) +{ + return getRawDecoderSpec(isDebugMode, FEEIdConfig(), CrateMasks(), ElectronicsDelay()); +} + +of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay) +{ + std::vector<of::InputSpec> inputSpecs{{"mid_raw", of::ConcreteDataTypeMatcher{header::gDataOriginMID, header::gDataDescriptionRawData}, of::Lifetime::Timeframe}}; + header::DataHeader::SubSpecificationType subSpec{0}; + return getRawDecoderSpec(isDebugMode, FEEIdConfig(), CrateMasks(), ElectronicsDelay(), inputSpecs, subSpec); +} + +of::DataProcessorSpec getRawDecoderSpec(bool isDebugMode, const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay, header::DataHeader::SubSpecificationType subSpec) +{ + std::vector<of::InputSpec> inputSpecs{{"mid_raw", header::gDataOriginMID, header::gDataDescriptionRawData, subSpec, o2::framework::Lifetime::Timeframe}}; + + return getRawDecoderSpec(isDebugMode, feeIdConfig, crateMasks, electronicsDelay, inputSpecs, subSpec); +} } // namespace mid } // namespace o2 From d821aa32c615b5134e90bd2d346c40c6402eb31f Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Mon, 4 Jan 2021 14:48:45 +0100 Subject: [PATCH 1704/1751] Allow external (public) use of generator routines --- Generators/include/Generators/Generator.h | 14 ++++++++++---- Generators/include/Generators/GeneratorHepMC.h | 8 ++++---- Generators/include/Generators/GeneratorPythia8.h | 8 ++++---- .../include/Generators/GeneratorTGenerator.h | 8 ++++---- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Generators/include/Generators/Generator.h b/Generators/include/Generators/Generator.h index 9d745eb4825cd..2cf881a4b0e03 100644 --- a/Generators/include/Generators/Generator.h +++ b/Generators/include/Generators/Generator.h @@ -61,6 +61,10 @@ class Generator : public FairGenerator **/ Bool_t ReadEvent(FairPrimaryGenerator* primGen) final; + /** methods to override **/ + virtual Bool_t generateEvent() = 0; + virtual Bool_t importParticles() = 0; + /** setters **/ void setMomentumUnit(double val) { mMomentumUnit = val; }; void setEnergyUnit(double val) { mEnergyUnit = val; }; @@ -71,6 +75,12 @@ class Generator : public FairGenerator void addTrigger(Trigger trigger) { mTriggers.push_back(trigger); }; void addDeepTrigger(DeepTrigger trigger) { mDeepTriggers.push_back(trigger); }; + /** getters **/ + const std::vector<TParticle>& getParticles() const { return mParticles; }; //! + + /** other **/ + void clearParticles() { mParticles.clear(); }; + /** notification methods **/ virtual void notifyEmbedding(const FairMCEventHeader* mcHeader){}; @@ -80,10 +90,6 @@ class Generator : public FairGenerator /** operator= **/ Generator& operator=(const Generator&); - /** methods to override **/ - virtual Bool_t generateEvent() = 0; - virtual Bool_t importParticles() = 0; - /** methods that can be overridded **/ virtual void updateHeader(FairMCEventHeader* eventHeader){}; diff --git a/Generators/include/Generators/GeneratorHepMC.h b/Generators/include/Generators/GeneratorHepMC.h index cca39d7d2f02e..f479111bc9f67 100644 --- a/Generators/include/Generators/GeneratorHepMC.h +++ b/Generators/include/Generators/GeneratorHepMC.h @@ -54,6 +54,10 @@ class GeneratorHepMC : public Generator /** Initialize the generator if needed **/ Bool_t Init() override; + /** methods to override **/ + Bool_t generateEvent() override; + Bool_t importParticles() override; + /** setters **/ void setVersion(Int_t val) { mVersion = val; }; void setFileName(std::string val) { mFileName = val; }; @@ -64,10 +68,6 @@ class GeneratorHepMC : public Generator /** operator= **/ GeneratorHepMC& operator=(const GeneratorHepMC&); - /** methods to override **/ - Bool_t generateEvent() override; - Bool_t importParticles() override; - /** methods **/ #ifdef GENERATORS_WITH_HEPMC3_DEPRECATED const HepMC::FourVector getBoostedVector(const HepMC::FourVector& vector, Double_t boost); diff --git a/Generators/include/Generators/GeneratorPythia8.h b/Generators/include/Generators/GeneratorPythia8.h index c743c931aefc9..96db63d7d8bd8 100644 --- a/Generators/include/Generators/GeneratorPythia8.h +++ b/Generators/include/Generators/GeneratorPythia8.h @@ -38,6 +38,10 @@ class GeneratorPythia8 : public Generator /** Initialize the generator if needed **/ Bool_t Init() override; + /** methods to override **/ + Bool_t generateEvent() override; + Bool_t importParticles() override { return importParticles(mPythia.event); }; + /** setters **/ void setConfig(std::string val) { mConfig = val; }; void setHooksFileName(std::string val) { mHooksFileName = val; }; @@ -61,10 +65,6 @@ class GeneratorPythia8 : public Generator /** operator= **/ GeneratorPythia8& operator=(const GeneratorPythia8&); - /** methods to override **/ - Bool_t generateEvent() override; - Bool_t importParticles() override { return importParticles(mPythia.event); }; - /** methods that can be overridded **/ void updateHeader(FairMCEventHeader* eventHeader) override; diff --git a/Generators/include/Generators/GeneratorTGenerator.h b/Generators/include/Generators/GeneratorTGenerator.h index 72dfe17a4a003..54e257aede20e 100644 --- a/Generators/include/Generators/GeneratorTGenerator.h +++ b/Generators/include/Generators/GeneratorTGenerator.h @@ -37,6 +37,10 @@ class GeneratorTGenerator : public Generator /** destructor **/ ~GeneratorTGenerator() override; + /** methods to override **/ + Bool_t generateEvent() override; + Bool_t importParticles() override; + /** setters **/ void setTGenerator(TGenerator* val) { mTGenerator = val; }; const TGenerator* getTGenerator() const { return mTGenerator; } @@ -49,10 +53,6 @@ class GeneratorTGenerator : public Generator /** operator= **/ GeneratorTGenerator& operator=(const GeneratorTGenerator&); - /** methods to override **/ - Bool_t generateEvent() override; - Bool_t importParticles() override; - /** TGenerator interface **/ TGenerator* mTGenerator; TClonesArray* mCloneParticles; From b2c615871ac204b14d0c79e44773ea2d5e02b78d Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Mon, 4 Jan 2021 14:50:09 +0100 Subject: [PATCH 1705/1751] Added functions to compute Ncoll, Npart and Nremn in Pythia8 --- .../include/Generators/GeneratorPythia8.h | 22 +++ Generators/src/GeneratorPythia8.cxx | 146 ++++++++++++++++++ 2 files changed, 168 insertions(+) diff --git a/Generators/include/Generators/GeneratorPythia8.h b/Generators/include/Generators/GeneratorPythia8.h index 96db63d7d8bd8..d61b011d00095 100644 --- a/Generators/include/Generators/GeneratorPythia8.h +++ b/Generators/include/Generators/GeneratorPythia8.h @@ -59,6 +59,24 @@ class GeneratorPythia8 : public Generator bool readString(std::string val) { return mPythia.readString(val, true); }; bool readFile(std::string val) { return mPythia.readFile(val, true); }; + /** utilities **/ + void getNcoll(int& nColl) + { + getNcoll(mPythia.info, nColl); + }; + void getNpart(int& nPart) + { + getNpart(mPythia.info, nPart); + }; + void getNpart(int& nProtonProj, int& nNeutronProj, int& nProtonTarg, int& nNeutronTarg) + { + getNpart(mPythia.info, nProtonProj, nNeutronProj, nProtonTarg, nNeutronTarg); + }; + void getNremn(int& nProtonProj, int& nNeutronProj, int& nProtonTarg, int& nNeutronTarg) + { + getNremn(mPythia.event, nProtonProj, nNeutronProj, nProtonTarg, nNeutronTarg); + }; + protected: /** copy constructor **/ GeneratorPythia8(const GeneratorPythia8&); @@ -73,6 +91,10 @@ class GeneratorPythia8 : public Generator /** utilities **/ void selectFromAncestor(int ancestor, Pythia8::Event& inputEvent, Pythia8::Event& outputEvent); + void getNcoll(const Pythia8::Info& info, int& nColl); + void getNpart(const Pythia8::Info& info, int& nPart); + void getNpart(const Pythia8::Info& info, int& nProtonProj, int& nNeutronProj, int& nProtonTarg, int& nNeutronTarg); + void getNremn(const Pythia8::Event& event, int& nProtonProj, int& nNeutronProj, int& nProtonTarg, int& nNeutronTarg); /** Pythia8 **/ Pythia8::Pythia mPythia; //! diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 2cc8f44ff156d..5022c437d5630 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -250,6 +250,152 @@ void GeneratorPythia8::selectFromAncestor(int ancestor, Pythia8::Event& inputEve } } +/*****************************************************************/ + +void GeneratorPythia8::getNcoll(const Pythia8::Info& info, int& nColl) +{ + + /** compute number of collisions from sub-collision information **/ + +#if PYTHIA_VERSION_INTEGER < 8300 + auto hiinfo = info.hiinfo; +#else + auto hiinfo = info.hiInfo; +#endif + + nColl = 0; + + if (!hiinfo) { + return; + } + + // loop over sub-collisions + auto scptr = hiinfo->subCollisionsPtr(); + for (auto sc : *scptr) { + + // wounded nucleon flag in projectile/target + auto pW = sc.proj->status() == Pythia8::Nucleon::ABS; // according to C.Bierlich this should be == Nucleon::ABS + auto tW = sc.targ->status() == Pythia8::Nucleon::ABS; + + // increase number of collisions if both are wounded + if (pW && tW) { + nColl++; + } + } +} + +/*****************************************************************/ + +void GeneratorPythia8::getNpart(const Pythia8::Info& info, int& nPart) +{ + + /** compute number of participants as the sum of all participants nucleons **/ + + int nProtonProj, nNeutronProj, nProtonTarg, nNeutronTarg; + getNpart(info, nProtonProj, nNeutronProj, nProtonTarg, nNeutronTarg); + nPart = nProtonProj + nNeutronProj + nProtonTarg + nNeutronTarg; +} + +/*****************************************************************/ + +void GeneratorPythia8::getNpart(const Pythia8::Info& info, int& nProtonProj, int& nNeutronProj, int& nProtonTarg, int& nNeutronTarg) +{ + + /** compute number of participants from sub-collision information **/ + +#if PYTHIA_VERSION_INTEGER < 8300 + auto hiinfo = info.hiinfo; +#else + auto hiinfo = info.hiInfo; +#endif + + nProtonProj = nNeutronProj = nProtonTarg = nNeutronTarg = 0; + if (!hiinfo) { + return; + } + + // keep track of wounded nucleons + std::vector<Pythia8::Nucleon*> projW; + std::vector<Pythia8::Nucleon*> targW; + + // loop over sub-collisions + auto scptr = hiinfo->subCollisionsPtr(); + for (auto sc : *scptr) { + + // wounded nucleon flag in projectile/target + auto pW = sc.proj->status() == Pythia8::Nucleon::ABS || sc.proj->status() == Pythia8::Nucleon::DIFF; // according to C.Bierlich this should be == Nucleon::ABS || Nucleon::DIFF + auto tW = sc.targ->status() == Pythia8::Nucleon::ABS || sc.targ->status() == Pythia8::Nucleon::DIFF; + + // increase number of wounded projectile nucleons if not yet in the wounded vector + if (pW && std::find(projW.begin(), projW.end(), sc.proj) == projW.end()) { + projW.push_back(sc.proj); + if (sc.proj->id() == 2212) { + nProtonProj++; + } else if (sc.proj->id() == 2112) { + nNeutronProj++; + } + } + + // increase number of wounded target nucleons if not yet in the wounded vector + if (tW && std::find(targW.begin(), targW.end(), sc.targ) == targW.end()) { + targW.push_back(sc.targ); + if (sc.targ->id() == 2212) { + nProtonTarg++; + } else if (sc.targ->id() == 2112) { + nNeutronTarg++; + } + } + } +} + +/*****************************************************************/ + +void GeneratorPythia8::getNremn(const Pythia8::Event& event, int& nProtonProj, int& nNeutronProj, int& nProtonTarg, int& nNeutronTarg) +{ + + /** compute number of spectators from the nuclear remnant of the beams **/ + + // reset + nProtonProj = nNeutronProj = nProtonTarg = nNeutronTarg = 0; + auto nNucRem = 0; + + // particle loop + auto nparticles = event.size(); + for (int ipa = 0; ipa < nparticles; ++ipa) { + const auto particle = event[ipa]; + auto pdg = particle.id(); + + // nuclear remnants have pdg code = ±10LZZZAAA9 + if (pdg < 1000000000) + continue; // must be nucleus + if (pdg % 10 != 9) + continue; // first digit must be 9 + nNucRem++; + + // extract A, Z and L from pdg code + pdg /= 10; + auto A = pdg % 1000; + pdg /= 1000; + auto Z = pdg % 1000; + pdg /= 1000; + auto L = pdg % 10; + + if (particle.pz() > 0.) { + nProtonProj = Z; + nNeutronProj = A - Z; + } + if (particle.pz() < 0.) { + nProtonTarg = Z; + nNeutronTarg = A - Z; + } + + } // end of particle loop + + if (nNucRem > 2) { + LOG(WARNING) << " GeneratorPythia8: found more than two nuclear remnants (weird)"; + } +} + /*****************************************************************/ /*****************************************************************/ From 1e8ccbc82beecb659188efb9b7e23fc2e99c4ba3 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio <maximiliano.puccio@cern.ch> Date: Fri, 18 Dec 2020 12:45:19 +0100 Subject: [PATCH 1706/1751] Fill PDG code database before event generation --- Generators/src/GeneratorFactory.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Generators/src/GeneratorFactory.cxx b/Generators/src/GeneratorFactory.cxx index 5f95a117f0320..798d97f567f1c 100644 --- a/Generators/src/GeneratorFactory.cxx +++ b/Generators/src/GeneratorFactory.cxx @@ -32,6 +32,7 @@ #include <Generators/GeneratorHepMCParam.h> #endif #include <Generators/BoxGunParam.h> +#include <Generators/PDG.h> #include <Generators/TriggerParticle.h> #include <Generators/TriggerExternalParam.h> #include <Generators/TriggerParticleParam.h> @@ -77,6 +78,7 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair /** generators **/ + o2::PDG::addParticlesToPdgDataBase(); auto genconfig = conf.getGenerator(); if (genconfig.compare("boxgen") == 0) { // a simple "box" generator configurable via BoxGunparam From a915434af5974ee53ab25a33beb5b0249f519bef Mon Sep 17 00:00:00 2001 From: dstocco <dstocco@users.noreply.github.com> Date: Wed, 6 Jan 2021 21:41:45 +0100 Subject: [PATCH 1707/1751] Correctly use object passed to MID decoder constructor (#5120) --- Detectors/MUON/MID/Raw/src/Decoder.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/MUON/MID/Raw/src/Decoder.cxx b/Detectors/MUON/MID/Raw/src/Decoder.cxx index 146f6c543a3ac..f29d4cb4dde88 100644 --- a/Detectors/MUON/MID/Raw/src/Decoder.cxx +++ b/Detectors/MUON/MID/Raw/src/Decoder.cxx @@ -73,7 +73,7 @@ std::unique_ptr<Decoder> createDecoder(const o2::header::RDHAny& rdh, bool isDeb { /// Creates the decoder from the RDH info bool isBare = (o2::raw::RDHUtils::getLinkID(rdh) != raw::sUserLogicLinkID); - return std::make_unique<Decoder>(isDebugMode, isBare, electronicsDelay, crateMasks); + return std::make_unique<Decoder>(isDebugMode, isBare, electronicsDelay, crateMasks, feeIdConfig); } std::unique_ptr<Decoder> createDecoder(const o2::header::RDHAny& rdh, bool isDebugMode, const char* electronicsDelayFile, const char* crateMasksFile, const char* feeIdConfigFile) { From c24f761b0256da79b4f0e249fff2be1cca919164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= <njacazio@users.noreply.github.com> Date: Thu, 7 Jan 2021 08:41:07 +0100 Subject: [PATCH 1708/1751] Subscribe PID tasks to collisions (#5127) - TOF Beta computation on by default --- Analysis/Tasks/pidTOF.cxx | 24 ++++++++++++------------ Analysis/Tasks/pidTPC.cxx | 22 +++++++++++----------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Analysis/Tasks/pidTOF.cxx b/Analysis/Tasks/pidTOF.cxx index 63e0ee7ccd197..9966c9011d2e2 100644 --- a/Analysis/Tasks/pidTOF.cxx +++ b/Analysis/Tasks/pidTOF.cxx @@ -28,7 +28,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) { std::vector<ConfigParamSpec> options{ {"add-qa", VariantType::Int, 0, {"Produce TOF PID QA histograms"}}, - {"add-beta", VariantType::Int, 0, {"Produce TOF Beta table"}}}; + {"add-beta", VariantType::Int, 1, {"Produce TOF Beta table"}}}; std::swap(workflowOptions, options); } @@ -36,7 +36,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) struct pidTOFTask { using Trks = soa::Join<aod::Tracks, aod::TracksExtra>; - using Coll = aod::Collision; + using Coll = aod::Collisions; Produces<aod::pidRespTOF> tofpid; DetectorResponse resp; Service<o2::ccdb::BasicCCDBManager> ccdb; @@ -65,17 +65,17 @@ struct pidTOFTask { } } - void process(Trks const& tracks) + void process(Coll const& collisions, Trks const& tracks) { - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Electron> resp_Electron = tof::ExpTimes<Coll, Trks::iterator, PID::Electron>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Muon> resp_Muon = tof::ExpTimes<Coll, Trks::iterator, PID::Muon>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Pion> resp_Pion = tof::ExpTimes<Coll, Trks::iterator, PID::Pion>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Kaon> resp_Kaon = tof::ExpTimes<Coll, Trks::iterator, PID::Kaon>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Proton> resp_Proton = tof::ExpTimes<Coll, Trks::iterator, PID::Proton>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Deuteron> resp_Deuteron = tof::ExpTimes<Coll, Trks::iterator, PID::Deuteron>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Triton> resp_Triton = tof::ExpTimes<Coll, Trks::iterator, PID::Triton>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Helium3> resp_Helium3 = tof::ExpTimes<Coll, Trks::iterator, PID::Helium3>(); - constexpr tof::ExpTimes<Coll, Trks::iterator, PID::Alpha> resp_Alpha = tof::ExpTimes<Coll, Trks::iterator, PID::Alpha>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Electron> resp_Electron = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Electron>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Muon> resp_Muon = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Muon>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Pion> resp_Pion = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Pion>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Kaon> resp_Kaon = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Kaon>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Proton> resp_Proton = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Proton>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Deuteron> resp_Deuteron = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Deuteron>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Triton> resp_Triton = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Triton>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Helium3> resp_Helium3 = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Helium3>(); + constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Alpha> resp_Alpha = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Alpha>(); tofpid.reserve(tracks.size()); for (auto const& trk : tracks) { diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index bfa007e44bd8c..d94e45954b03d 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -35,7 +35,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) struct pidTPCTask { using Trks = soa::Join<aod::Tracks, aod::TracksExtra>; - using Coll = aod::Collision; + using Coll = aod::Collisions; Produces<aod::pidRespTPC> tpcpid; DetectorResponse resp; Service<o2::ccdb::BasicCCDBManager> ccdb; @@ -65,17 +65,17 @@ struct pidTPCTask { } } - void process(Trks const& tracks) + void process(Coll const& collisions, Trks const& tracks) { - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Electron> resp_Electron = tpc::ELoss<Coll, Trks::iterator, PID::Electron>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Muon> resp_Muon = tpc::ELoss<Coll, Trks::iterator, PID::Muon>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Pion> resp_Pion = tpc::ELoss<Coll, Trks::iterator, PID::Pion>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Kaon> resp_Kaon = tpc::ELoss<Coll, Trks::iterator, PID::Kaon>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Proton> resp_Proton = tpc::ELoss<Coll, Trks::iterator, PID::Proton>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Deuteron> resp_Deuteron = tpc::ELoss<Coll, Trks::iterator, PID::Deuteron>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Triton> resp_Triton = tpc::ELoss<Coll, Trks::iterator, PID::Triton>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Helium3> resp_Helium3 = tpc::ELoss<Coll, Trks::iterator, PID::Helium3>(); - constexpr tpc::ELoss<Coll, Trks::iterator, PID::Alpha> resp_Alpha = tpc::ELoss<Coll, Trks::iterator, PID::Alpha>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Electron> resp_Electron = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Electron>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Muon> resp_Muon = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Muon>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Pion> resp_Pion = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Pion>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Kaon> resp_Kaon = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Kaon>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Proton> resp_Proton = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Proton>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Deuteron> resp_Deuteron = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Deuteron>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Triton> resp_Triton = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Triton>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Helium3> resp_Helium3 = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Helium3>(); + constexpr tpc::ELoss<Coll::iterator, Trks::iterator, PID::Alpha> resp_Alpha = tpc::ELoss<Coll::iterator, Trks::iterator, PID::Alpha>(); tpcpid.reserve(tracks.size()); for (auto const& trk : tracks) { From 8dfa98d9095ff389b5fe6c2fbd31185d9cff4fce Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Wed, 6 Jan 2021 19:29:57 +0100 Subject: [PATCH 1709/1751] Fix codechecker --- .../include/ITStrackingCUDA/TrackerTraitsNV.h | 2 +- .../include/ITStrackingCUDA/UniquePointer.h | 6 +-- .../cuda/include/ITStrackingCUDA/Utils.h | 10 ++--- .../cuda/include/ITStrackingCUDA/Vector.h | 40 +++++++++---------- .../ITStrackingCUDA/VertexerTraitsGPU.h | 4 +- .../ITSMFT/ITS/tracking/cuda/src/Context.cu | 2 +- .../ITS/tracking/cuda/src/DeviceStoreNV.cu | 9 ++--- .../cuda/src/DeviceStoreVertexerGPU.cu | 4 +- .../ITS/tracking/cuda/src/TrackerTraitsNV.cu | 22 +++++----- .../ITSMFT/ITS/tracking/cuda/src/Utils.cu | 34 ++++++++-------- .../tracking/cuda/src/VertexerTraitsGPU.cu | 14 +++---- 11 files changed, 73 insertions(+), 74 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h index cba3765ebb86e..b7bac25a170dd 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/TrackerTraitsNV.h @@ -30,7 +30,7 @@ class TrackerTraitsNV : public TrackerTraits { public: TrackerTraitsNV(); - virtual ~TrackerTraitsNV(); + ~TrackerTraitsNV() override; void computeLayerCells() final; void computeLayerTracklets() final; diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h index 0b1a4d8667a89..74ff53865f36d 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/UniquePointer.h @@ -81,8 +81,8 @@ UniquePointer<T>::UniquePointer(const T& ref) { try { - Utils::Host::gpuMalloc(reinterpret_cast<void**>(&mDevicePointer), sizeof(T)); - Utils::Host::gpuMemcpyHostToDevice(mDevicePointer, &ref, sizeof(T)); + utils::host::gpuMalloc(reinterpret_cast<void**>(&mDevicePointer), sizeof(T)); + utils::host::gpuMemcpyHostToDevice(mDevicePointer, &ref, sizeof(T)); } catch (...) { @@ -118,7 +118,7 @@ void UniquePointer<T>::destroy() { if (mDevicePointer != nullptr) { - Utils::Host::gpuFree(mDevicePointer); + utils::host::gpuFree(mDevicePointer); } } diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h index 71098df75cf2c..54dacb9217207 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Utils.h @@ -25,10 +25,10 @@ namespace its namespace gpu { -namespace Utils +namespace utils { -namespace Host +namespace host { #ifdef __CUDACC__ @@ -49,14 +49,14 @@ void gpuMemcpyHostToDeviceAsync(void*, const void*, int, Stream&); void gpuMemcpyDeviceToHost(void*, const void*, int); // void gpuStartProfiler(); // void gpuStopProfiler(); -} // namespace Host +} // namespace host -namespace Device +namespace device { GPUd() int getLaneIndex(); GPUd() int shareToWarp(const int, const int); GPUd() int gpuAtomicAdd(int*, const int); -} // namespace Device +} // namespace device } // namespace Utils } // namespace gpu } // namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h index 8bc92e65622ba..5e7d58f253eb5 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/Vector.h @@ -15,7 +15,7 @@ #ifndef TRAKINGITSU_INCLUDE_GPU_VECTOR_H_ #define TRAKINGITSU_INCLUDE_GPU_VECTOR_H_ -#include <assert.h> +#include <cassert> #include <new> #include <type_traits> #include <vector> @@ -100,17 +100,17 @@ Vector<T>::Vector(const T* const source, const int size, const int initialSize) if (size > 0) { try { - Utils::Host::gpuMalloc(reinterpret_cast<void**>(&mArrayPointer), size * sizeof(T)); - Utils::Host::gpuMalloc(reinterpret_cast<void**>(&mDeviceSize), sizeof(int)); + utils::host::gpuMalloc(reinterpret_cast<void**>(&mArrayPointer), size * sizeof(T)); + utils::host::gpuMalloc(reinterpret_cast<void**>(&mDeviceSize), sizeof(int)); if (source != nullptr) { - Utils::Host::gpuMemcpyHostToDevice(mArrayPointer, source, size * sizeof(T)); - Utils::Host::gpuMemcpyHostToDevice(mDeviceSize, &size, sizeof(int)); + utils::host::gpuMemcpyHostToDevice(mArrayPointer, source, size * sizeof(T)); + utils::host::gpuMemcpyHostToDevice(mDeviceSize, &size, sizeof(int)); } else { - Utils::Host::gpuMemcpyHostToDevice(mDeviceSize, &initialSize, sizeof(int)); + utils::host::gpuMemcpyHostToDevice(mDeviceSize, &initialSize, sizeof(int)); } } catch (...) { @@ -179,7 +179,7 @@ template <typename T> int Vector<T>::getSizeFromDevice() const { int size; - Utils::Host::gpuMemcpyDeviceToHost(&size, mDeviceSize, sizeof(int)); + utils::host::gpuMemcpyDeviceToHost(&size, mDeviceSize, sizeof(int)); return size; } @@ -187,7 +187,7 @@ int Vector<T>::getSizeFromDevice() const template <typename T> void Vector<T>::resize(const int size) { - Utils::Host::gpuMemcpyHostToDevice(mDeviceSize, &size, sizeof(int)); + utils::host::gpuMemcpyHostToDevice(mDeviceSize, &size, sizeof(int)); } template <typename T> @@ -201,21 +201,21 @@ void Vector<T>::reset(const T* const source, const int size, const int initialSi { if (size > mCapacity) { if (mArrayPointer != nullptr) { - Utils::Host::gpuFree(mArrayPointer); + utils::host::gpuFree(mArrayPointer); } - Utils::Host::gpuMalloc(reinterpret_cast<void**>(&mArrayPointer), size * sizeof(T)); + utils::host::gpuMalloc(reinterpret_cast<void**>(&mArrayPointer), size * sizeof(T)); mCapacity = size; } if (source != nullptr) { - Utils::Host::gpuMemcpyHostToDevice(mArrayPointer, source, size * sizeof(T)); - Utils::Host::gpuMemcpyHostToDevice(mDeviceSize, &size, sizeof(int)); + utils::host::gpuMemcpyHostToDevice(mArrayPointer, source, size * sizeof(T)); + utils::host::gpuMemcpyHostToDevice(mDeviceSize, &size, sizeof(int)); } else { if (mDeviceSize == nullptr) { - Utils::Host::gpuMalloc(reinterpret_cast<void**>(&mDeviceSize), sizeof(int)); + utils::host::gpuMalloc(reinterpret_cast<void**>(&mDeviceSize), sizeof(int)); } - Utils::Host::gpuMemcpyHostToDevice(mDeviceSize, &initialSize, sizeof(int)); + utils::host::gpuMemcpyHostToDevice(mDeviceSize, &initialSize, sizeof(int)); } } @@ -228,7 +228,7 @@ void Vector<T>::copyIntoVector(std::vector<T>& destinationVector, const int size try { hostPrimitivePointer = static_cast<T*>(malloc(size * sizeof(T))); - Utils::Host::gpuMemcpyDeviceToHost(hostPrimitivePointer, mArrayPointer, size * sizeof(T)); + utils::host::gpuMemcpyDeviceToHost(hostPrimitivePointer, mArrayPointer, size * sizeof(T)); destinationVector = std::move(std::vector<T>(hostPrimitivePointer, hostPrimitivePointer + size)); @@ -246,7 +246,7 @@ void Vector<T>::copyIntoVector(std::vector<T>& destinationVector, const int size template <typename T> void Vector<T>::copyIntoSizedVector(std::vector<T>& destinationVector) { - Utils::Host::gpuMemcpyDeviceToHost(destinationVector.data(), mArrayPointer, destinationVector.size() * sizeof(T)); + utils::host::gpuMemcpyDeviceToHost(destinationVector.data(), mArrayPointer, destinationVector.size() * sizeof(T)); } template <typename T> @@ -254,12 +254,12 @@ inline void Vector<T>::destroy() { if (mArrayPointer != nullptr) { - Utils::Host::gpuFree(mArrayPointer); + utils::host::gpuFree(mArrayPointer); } if (mDeviceSize != nullptr) { - Utils::Host::gpuFree(mDeviceSize); + utils::host::gpuFree(mDeviceSize); } } @@ -291,7 +291,7 @@ template <typename T> GPU_HOST inline T Vector<T>::getElementFromDevice(const int index) const { T element; - Utils::Host::gpuMemcpyDeviceToHost(&element, mArrayPointer + index, sizeof(T)); + utils::host::gpuMemcpyDeviceToHost(&element, mArrayPointer + index, sizeof(T)); return element; } @@ -305,7 +305,7 @@ GPU_DEVICE inline int Vector<T>::size() const template <typename T> GPU_DEVICE int Vector<T>::extend(const int sizeIncrement) const { - const int startIndex = Utils::Device::gpuAtomicAdd(mDeviceSize, sizeIncrement); + const int startIndex = utils::device::gpuAtomicAdd(mDeviceSize, sizeIncrement); assert(size() <= mCapacity); return startIndex; diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h index 83573af6e6c31..8ae1b578cc261 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/cuda/include/ITStrackingCUDA/VertexerTraitsGPU.h @@ -44,10 +44,10 @@ class VertexerTraitsGPU : public VertexerTraits public: #ifdef _ALLOW_DEBUG_TREES_ITS_ VertexerTraitsGPU(); - virtual ~VertexerTraitsGPU(); + ~VertexerTraitsGPU() override; #else VertexerTraitsGPU(); - virtual ~VertexerTraitsGPU() = default; + ~VertexerTraitsGPU() = default; #endif void initialise(ROframe*) override; void computeTracklets() override; diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu index 5cc487a564d9b..ef73009aa38e7 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/Context.cu @@ -80,7 +80,7 @@ namespace its namespace gpu { -using Utils::Host::checkCUDAError; +using utils::host::checkCUDAError; Context::Context(bool dumpDevices) { diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu index b3a920391eda6..a6c5a259be63c 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreNV.cu @@ -115,10 +115,7 @@ namespace its namespace gpu { -DeviceStoreNV::DeviceStoreNV() -{ - // Nothing to do -} +DeviceStoreNV::DeviceStoreNV() = default; UniquePointer<DeviceStoreNV> DeviceStoreNV::initialise(const float3& primaryVertex, const std::array<std::vector<Cluster>, constants::its2::LayersNumber>& clusters, @@ -163,8 +160,8 @@ UniquePointer<DeviceStoreNV> DeviceStoreNV::initialise(const float3& primaryVert const int nextLayerClustersNum = static_cast<int>(clusters[iLayer + 1].size()); - dim3 threadsPerBlock{Utils::Host::getBlockSize(nextLayerClustersNum)}; - dim3 blocksGrid{Utils::Host::getBlocksGrid(threadsPerBlock, nextLayerClustersNum)}; + dim3 threadsPerBlock{utils::host::getBlockSize(nextLayerClustersNum)}; + dim3 blocksGrid{utils::host::getBlocksGrid(threadsPerBlock, nextLayerClustersNum)}; fillDeviceStructures<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer].get()>>>(*gpuContextDevicePointer, iLayer); diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu index 3b798132976ab..0830ff6d2b529 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/DeviceStoreVertexerGPU.cu @@ -83,8 +83,8 @@ UniquePointer<DeviceStoreVertexerGPU> DeviceStoreVertexerGPU::initialise(const s mIndexTables[0].reset(indexTables[0].data(), static_cast<int>(indexTables[0].size())); mIndexTables[1].reset(indexTables[2].data(), static_cast<int>(indexTables[2].size())); - const dim3 threadsPerBlock{Utils::Host::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{utils::host::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{utils::host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; UniquePointer<DeviceStoreVertexerGPU> deviceStoreVertexerPtr{*this}; diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu index f9e58d6836fe7..48bb31053c875 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/TrackerTraitsNV.cu @@ -349,8 +349,8 @@ void TrackerTraitsNV::computeLayerTracklets() const gpu::DeviceProperties& deviceProperties = gpu::Context::getInstance().getDeviceProperties(); const int clustersNum{static_cast<int>(primaryVertexContext->getClusters()[iLayer].size())}; - dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(clustersNum, 1, 192)}; - dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, clustersNum)}; + dim3 threadsPerBlock{gpu::utils::host::getBlockSize(clustersNum, 1, 192)}; + dim3 blocksGrid{gpu::utils::host::getBlocksGrid(threadsPerBlock, clustersNum)}; if (iLayer == 0) { @@ -390,8 +390,8 @@ void TrackerTraitsNV::computeLayerTracklets() primaryVertexContext->getDeviceTrackletsLookupTable()[iLayer].get(), primaryVertexContext->getClusters()[iLayer + 1].size(), streamArray[iLayer + 1].get()); - dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(trackletsNum[iLayer])}; - dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; + dim3 threadsPerBlock{gpu::utils::host::getBlockSize(trackletsNum[iLayer])}; + dim3 blocksGrid{gpu::utils::host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; gpu::sortTrackletsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer + 1].get()>>>(primaryVertexContext->getDeviceContext(), iLayer + 1, primaryVertexContext->getTempTrackletArray()[iLayer].getWeakCopy()); @@ -442,8 +442,8 @@ void TrackerTraitsNV::computeLayerCells() if (trackletsSize == 0) { continue; } - dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(trackletsSize)}; - dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsSize)}; + dim3 threadsPerBlock{gpu::utils::host::getBlockSize(trackletsSize)}; + dim3 blocksGrid{gpu::utils::host::getBlocksGrid(threadsPerBlock, trackletsSize)}; if (iLayer == 0) { @@ -482,8 +482,8 @@ void TrackerTraitsNV::computeLayerCells() primaryVertexContext->getDeviceCellsLookupTable()[iLayer].get(), trackletsNum[iLayer], streamArray[iLayer + 1].get()); - dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(trackletsNum[iLayer])}; - dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; + dim3 threadsPerBlock{gpu::utils::host::getBlockSize(trackletsNum[iLayer])}; + dim3 blocksGrid{gpu::utils::host::getBlocksGrid(threadsPerBlock, trackletsNum[iLayer])}; gpu::sortCellsKernel<<<blocksGrid, threadsPerBlock, 0, streamArray[iLayer + 1].get()>>>(primaryVertexContext->getDeviceContext(), iLayer + 1, primaryVertexContext->getTempCellArray()[iLayer].getWeakCopy()); @@ -508,13 +508,15 @@ void TrackerTraitsNV::computeLayerCells() if (iLayer == 0) { cellsSize = primaryVertexContext->getDeviceCells()[iLayer].getSizeFromDevice(); - if (cellsSize == 0) + if (cellsSize == 0) { continue; + } } else { cellsSize = cellsNum[iLayer - 1]; - if (cellsSize == 0) + if (cellsSize == 0) { continue; + } primaryVertexContext->getDeviceCellsLookupTable()[iLayer - 1].copyIntoVector( primaryVertexContext->getCellsLookupTable()[iLayer - 1], trackletsNum[iLayer - 1]); } diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu index 3872556147b90..26720b80e9193 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/Utils.cu @@ -73,7 +73,7 @@ namespace its namespace gpu { -void Utils::Host::checkCUDAError(const cudaError_t error, const char* file, const int line) +void utils::host::checkCUDAError(const cudaError_t error, const char* file, const int line) { if (error != cudaSuccess) { @@ -86,18 +86,18 @@ void Utils::Host::checkCUDAError(const cudaError_t error, const char* file, cons } } -dim3 Utils::Host::getBlockSize(const int colsNum) +dim3 utils::host::getBlockSize(const int colsNum) { return getBlockSize(colsNum, 1); } -dim3 Utils::Host::getBlockSize(const int colsNum, const int rowsNum) +dim3 utils::host::getBlockSize(const int colsNum, const int rowsNum) { const DeviceProperties& deviceProperties = Context::getInstance().getDeviceProperties(); return getBlockSize(colsNum, rowsNum, deviceProperties.cudaCores / deviceProperties.maxBlocksPerSM); } -dim3 Utils::Host::getBlockSize(const int colsNum, const int rowsNum, const int maxThreadsPerBlock) +dim3 utils::host::getBlockSize(const int colsNum, const int rowsNum, const int maxThreadsPerBlock) { const DeviceProperties& deviceProperties = Context::getInstance().getDeviceProperties(); int xThreads = max(min(colsNum, deviceProperties.maxThreadsDim.x), 1); @@ -119,59 +119,59 @@ dim3 Utils::Host::getBlockSize(const int colsNum, const int rowsNum, const int m return dim3{static_cast<unsigned int>(xThreads), static_cast<unsigned int>(yThreads)}; } -dim3 Utils::Host::getBlocksGrid(const dim3& threadsPerBlock, const int rowsNum) +dim3 utils::host::getBlocksGrid(const dim3& threadsPerBlock, const int rowsNum) { return getBlocksGrid(threadsPerBlock, rowsNum, 1); } -dim3 Utils::Host::getBlocksGrid(const dim3& threadsPerBlock, const int rowsNum, const int colsNum) +dim3 utils::host::getBlocksGrid(const dim3& threadsPerBlock, const int rowsNum, const int colsNum) { return dim3{1 + (rowsNum - 1) / threadsPerBlock.x, 1 + (colsNum - 1) / threadsPerBlock.y}; } -void Utils::Host::gpuMalloc(void** p, const int size) +void utils::host::gpuMalloc(void** p, const int size) { checkCUDAError(cudaMalloc(p, size), __FILE__, __LINE__); } -void Utils::Host::gpuFree(void* p) +void utils::host::gpuFree(void* p) { checkCUDAError(cudaFree(p), __FILE__, __LINE__); } -void Utils::Host::gpuMemset(void* p, int value, int size) +void utils::host::gpuMemset(void* p, int value, int size) { checkCUDAError(cudaMemset(p, value, size), __FILE__, __LINE__); } -void Utils::Host::gpuMemcpyHostToDevice(void* dst, const void* src, int size) +void utils::host::gpuMemcpyHostToDevice(void* dst, const void* src, int size) { checkCUDAError(cudaMemcpy(dst, src, size, cudaMemcpyHostToDevice), __FILE__, __LINE__); } -void Utils::Host::gpuMemcpyHostToDeviceAsync(void* dst, const void* src, int size, Stream& stream) +void utils::host::gpuMemcpyHostToDeviceAsync(void* dst, const void* src, int size, Stream& stream) { checkCUDAError(cudaMemcpyAsync(dst, src, size, cudaMemcpyHostToDevice, stream.get()), __FILE__, __LINE__); } -void Utils::Host::gpuMemcpyDeviceToHost(void* dst, const void* src, int size) +void utils::host::gpuMemcpyDeviceToHost(void* dst, const void* src, int size) { checkCUDAError(cudaMemcpy(dst, src, size, cudaMemcpyDeviceToHost), __FILE__, __LINE__); } -// void Utils::Host::gpuStartProfiler() +// void utils::host::gpuStartProfiler() // { // checkCUDAError(cudaProfilerStart(), __FILE__, __LINE__); // } -// void Utils::Host::gpuStopProfiler() +// void utils::host::gpuStopProfiler() // { // checkCUDAError(cudaProfilerStop(), __FILE__, __LINE__); // } -GPUd() int Utils::Device::getLaneIndex() +GPUd() int utils::device::getLaneIndex() { uint32_t laneIndex; asm volatile("mov.u32 %0, %%laneid;" @@ -179,13 +179,13 @@ GPUd() int Utils::Device::getLaneIndex() return static_cast<int>(laneIndex); } -GPUd() int Utils::Device::shareToWarp(const int value, const int laneIndex) +GPUd() int utils::device::shareToWarp(const int value, const int laneIndex) { cooperative_groups::coalesced_group threadGroup = cooperative_groups::coalesced_threads(); return threadGroup.shfl(value, laneIndex); } -GPUd() int Utils::Device::gpuAtomicAdd(int* p, const int incrementSize) +GPUd() int utils::device::gpuAtomicAdd(int* p, const int incrementSize) { return atomicAdd(p, incrementSize); } diff --git a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu index 6e44aecfbf24e..336465f6a8ddf 100644 --- a/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/cuda/src/VertexerTraitsGPU.cu @@ -15,7 +15,7 @@ #include <iostream> #include <sstream> #include <array> -#include <assert.h> +#include <cassert> #ifndef GPUCA_GPUCODE_GENRTC #include <cub/cub.cuh> @@ -343,8 +343,8 @@ void VertexerTraitsGPU::computeTracklets() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::utils::host::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::utils::host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; gpu::trackleterKernel<<<blocksGrid, threadsPerBlock>>>( getDeviceContext(), @@ -374,8 +374,8 @@ void VertexerTraitsGPU::computeTrackletMatching() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::utils::host::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::utils::host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; size_t bufferSize = mStoreVertexerGPU.getConfig().tmpCUBBufferSize * sizeof(int); gpu::trackletSelectionKernel<<<blocksGrid, threadsPerBlock>>>( @@ -422,8 +422,8 @@ void VertexerTraitsGPU::computeVertices() std::cout << "\t\tno clusters on layer 1. Returning.\n"; return; } - const dim3 threadsPerBlock{gpu::Utils::Host::getBlockSize(mClusters[1].capacity())}; - const dim3 blocksGrid{gpu::Utils::Host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; + const dim3 threadsPerBlock{gpu::utils::host::getBlockSize(mClusters[1].capacity())}; + const dim3 blocksGrid{gpu::utils::host::getBlocksGrid(threadsPerBlock, mClusters[1].capacity())}; size_t bufferSize = mStoreVertexerGPU.getConfig().tmpCUBBufferSize * sizeof(int); int nLines = mStoreVertexerGPU.getNExclusiveFoundLines().getElementFromDevice(mClusters[1].size() - 1) + mStoreVertexerGPU.getNFoundLines().getElementFromDevice(mClusters[1].size() - 1); int nCentroids{static_cast<int>(nLines * (nLines - 1) / 2)}; From 00954d0cf943909774f2d889cd6736547062822d Mon Sep 17 00:00:00 2001 From: Matteo Concas <matteo.concas@cern.ch> Date: Wed, 6 Jan 2021 19:35:24 +0100 Subject: [PATCH 1710/1751] Fix Clang warnings --- Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx index a51e30edd2117..d152499f74f1b 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx @@ -171,8 +171,8 @@ ClusterLines::ClusterLines(const int firstLabel, const Line& firstLine, const in computeClusterCentroid(); // RMS2 - mRMS2 = std::move(Line::getDCAComponents(firstLine, mVertex)); - const std::array<float, 6> tmpRMS2Line2 = std::move(Line::getDCAComponents(secondLine, mVertex)); + mRMS2 = Line::getDCAComponents(firstLine, mVertex); + const std::array<float, 6> tmpRMS2Line2 = Line::getDCAComponents(secondLine, mVertex); std::transform(mRMS2.begin(), mRMS2.end(), tmpRMS2Line2.begin(), mRMS2.begin(), [&](const float a, const float b) { return a + (b - a) / mLabels.size(); }); // AvgDistance2 From 6bbd1685393032189b7e96befd1c21f547c51a16 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 7 Jan 2021 10:14:30 +0100 Subject: [PATCH 1711/1751] GPU: Disable some ROCm CMake warnings --- dependencies/FindO2GPU.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index f552ba605c055..3a3d7c05aaa9e 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -167,6 +167,8 @@ if(ENABLE_HIP) find_package(hipcub) find_package(rocprim) find_package(rocthrust) + set(ROCM_WARN_TOOLCHAIN_VAR OFF CACHE BOOL "" FORCE) + set(ROCM_ERROR_TOOLCHAIN_VAR OFF CACHE BOOL "" FORCE) if(ENABLE_HIP STREQUAL "AUTO") set_package_properties(hip PROPERTIES TYPE OPTIONAL) set_package_properties(hipcub PROPERTIES TYPE OPTIONAL) From 8c6aa7b35dbc368ac05cc7ff22001aff94b15698 Mon Sep 17 00:00:00 2001 From: swenzel <sandro.wenzel@cern.ch> Date: Thu, 7 Jan 2021 15:51:57 +0100 Subject: [PATCH 1712/1751] RootSerializableKeyValueStore: Add print function --- .../CommonUtils/RootSerializableKeyValueStore.h | 3 +++ Common/Utils/src/RootSerializableKeyValueStore.cxx | 10 ++++++++++ .../Utils/test/testRootSerializableKeyValueStore.cxx | 2 ++ 3 files changed, 15 insertions(+) diff --git a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h index 7df307954bf46..31fba2f1c2b62 100644 --- a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h +++ b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h @@ -107,6 +107,9 @@ class RootSerializableKeyValueStore mStore.clear(); } + /// print list of keys and type information + void print() const; + private: std::map<std::string, SerializedInfo*> mStore; diff --git a/Common/Utils/src/RootSerializableKeyValueStore.cxx b/Common/Utils/src/RootSerializableKeyValueStore.cxx index d035378001dcc..6a5979bcd052d 100644 --- a/Common/Utils/src/RootSerializableKeyValueStore.cxx +++ b/Common/Utils/src/RootSerializableKeyValueStore.cxx @@ -9,5 +9,15 @@ // or submit itself to any jurisdiction. #include "CommonUtils/RootSerializableKeyValueStore.h" +#include <iostream> using namespace o2::utils; + +void RootSerializableKeyValueStore::print() const +{ + for (auto& p : mStore) { + const auto& key = p.first; + const auto info = p.second; + std::cout << "key: " << key << " of-type: " << info->typeinfo_name << "\n"; + } +} \ No newline at end of file diff --git a/Common/Utils/test/testRootSerializableKeyValueStore.cxx b/Common/Utils/test/testRootSerializableKeyValueStore.cxx index 96b2f9a1b5fb6..3629a9e360db0 100644 --- a/Common/Utils/test/testRootSerializableKeyValueStore.cxx +++ b/Common/Utils/test/testRootSerializableKeyValueStore.cxx @@ -111,6 +111,8 @@ BOOST_AUTO_TEST_CASE(write_read_test) auto histo = s2->get<TH1F>("h1"); BOOST_CHECK(histo); + + s2->print(); } f.Close(); } From ba836b3b920047fafc837a99751d3924eec1995d Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 8 Jan 2021 20:00:27 +0100 Subject: [PATCH 1713/1751] Do not invoke FIT-reader with --use-fit in raw data input mode since in raw mode the FT0 recpoints must be provided by upstream devices --- .../tofworkflow/src/tof-reco-workflow.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx index 7e053e518f18b..054eb3d7ab1b6 100644 --- a/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx @@ -206,7 +206,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } } - if (useFIT) { + if (useFIT && !disableRootInput) { specs.emplace_back(o2::ft0::getRecPointReaderSpec(useMC)); } From b0d11080d0d894fc793fe93d8fcd2abce5852cba Mon Sep 17 00:00:00 2001 From: Alla Maevskaya <Alla.Maevskaya@cern.ch> Date: Wed, 6 Jan 2021 18:18:14 +0300 Subject: [PATCH 1714/1751] trigger inputs --- .../FIT/FT0/include/DataFormatsFT0/Digit.h | 17 +++++++++++++++++ .../FIT/FT0/src/DataFormatsFT0LinkDef.h | 2 ++ .../include/FT0Simulation/Digitizer.h | 4 ++++ Detectors/FIT/FT0/simulation/src/Digitizer.cxx | 12 ++++++++---- .../DigitizerWorkflow/src/FT0DigitWriterSpec.h | 3 ++- .../DigitizerWorkflow/src/FT0DigitizerSpec.cxx | 7 +++++-- 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h index 1abe2b60fe19d..d1877271b1bed 100644 --- a/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h +++ b/DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h @@ -83,6 +83,22 @@ struct Triggers { ClassDefNV(Triggers, 1); }; +struct DetTrigInput { + o2::InteractionRecord mIntRecord; // bc/orbit of the intpur + std::bitset<5> mInputs; // pattern of inputs. + DetTrigInput() = default; + DetTrigInput(const o2::InteractionRecord& iRec, Bool_t isA, Bool_t isC, Bool_t isVrtx, Bool_t isCnt, Bool_t isSCnt) + : mIntRecord(iRec), + mInputs((isA << Triggers::bitA) | + (isC << Triggers::bitC) | + (isVrtx << Triggers::bitVertex) | + (isCnt << Triggers::bitCen) | + (isSCnt << Triggers::bitSCen)) + { + } + ClassDefNV(DetTrigInput, 1); +}; + struct Digit { o2::dataformats::RangeReference<int, int> ref; Triggers mTriggers; // pattern of triggers in this BC @@ -114,6 +130,7 @@ struct Digit { void setStatusFlag(EEventStatus bit, bool value) { mEventStatus |= (value << bit); }; bool getStatusFlag(EEventStatus bit) const { return bool(mEventStatus << bit); } uint8_t getEventStatusWord() const { return mEventStatus; } + ClassDefNV(Digit, 5); }; diff --git a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h index 616436b76d0f9..3d480d5d96976 100644 --- a/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h +++ b/DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h @@ -19,12 +19,14 @@ #pragma link C++ class o2::ft0::DigitsTemp + ; #pragma link C++ class o2::ft0::ChannelData + ; #pragma link C++ class o2::ft0::Triggers + ; +#pragma link C++ class o2::ft0::DetTrigInput + ; #pragma link C++ class o2::ft0::TriggersExt + ; #pragma link C++ class vector < o2::ft0::ChannelData> + ; #pragma link C++ class vector < o2::ft0::Digit> + ; #pragma link C++ class vector < o2::ft0::DigitExt> + ; #pragma link C++ class vector < o2::ft0::DigitsTemp> + ; #pragma link C++ class vector < o2::ft0::Triggers> + ; +#pragma link C++ class vector < o2::ft0::DetTrigInput> + ; #pragma link C++ class vector < o2::ft0::TriggersExt> + ; #pragma link C++ class o2::ft0::RecPoints + ; diff --git a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h index faf0576122531..b3900e66cba07 100644 --- a/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h +++ b/Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h @@ -45,12 +45,15 @@ class Digitizer void process(const std::vector<o2::ft0::HitType>* hits, std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& label); void flush(std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& label); void flush_all(std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& label); void initParameters(); void printParameters() const; @@ -150,6 +153,7 @@ class Digitizer void storeBC(BCCache& bc, std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& labels); ClassDefNV(Digitizer, 1); diff --git a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx index 3cde3b5b42ef6..e2cc4180bfe04 100644 --- a/Detectors/FIT/FT0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FT0/simulation/src/Digitizer.cxx @@ -150,13 +150,14 @@ double Digitizer::measure_amplitude(const std::vector<float>& times) const void Digitizer::process(const std::vector<o2::ft0::HitType>* hits, std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& label) { ; //Calculating signal time, amplitude in mean_time +- time_gate -------------- LOG(DEBUG) << " process firstBCinDeque " << firstBCinDeque << " mIntRecord " << mIntRecord; if (firstBCinDeque != mIntRecord) { - flush(digitsBC, digitsCh, label); + flush(digitsBC, digitsCh, digitsTrig, label); } Int_t parent = -10; @@ -189,6 +190,7 @@ void Digitizer::process(const std::vector<o2::ft0::HitType>* hits, void Digitizer::storeBC(BCCache& bc, std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& labels) { if (bc.hits.empty()) { @@ -266,8 +268,8 @@ void Digitizer::storeBC(BCCache& bc, if (nStored > 0) { triggers.setTriggers(is_A, is_C, isVertex, is_Central, is_SemiCentral, int8_t(n_hit_A), int8_t(n_hit_C), amplA, amplC, timeA, timeC); - digitsBC.emplace_back(first, nStored, firstBCinDeque, triggers, mEventID - 1); + digitsTrig.emplace_back(firstBCinDeque, is_A, is_C, isVertex, is_Central, is_SemiCentral); size_t const nBC = digitsBC.size(); for (auto const& lbl : bc.labels) { labels.addElement(nBC - 1, lbl); @@ -286,13 +288,14 @@ void Digitizer::storeBC(BCCache& bc, //------------------------------------------------------------------------ void Digitizer::flush(std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& labels) { assert(firstBCinDeque <= mIntRecord); while (firstBCinDeque < mIntRecord && !mCache.empty()) { - storeBC(mCache.front(), digitsBC, digitsCh, labels); + storeBC(mCache.front(), digitsBC, digitsCh, digitsTrig, labels); mCache.pop_front(); ++firstBCinDeque; } @@ -301,13 +304,14 @@ void Digitizer::flush(std::vector<o2::ft0::Digit>& digitsBC, void Digitizer::flush_all(std::vector<o2::ft0::Digit>& digitsBC, std::vector<o2::ft0::ChannelData>& digitsCh, + std::vector<o2::ft0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>& labels) { assert(firstBCinDeque <= mIntRecord); ++mEventID; while (!mCache.empty()) { - storeBC(mCache.front(), digitsBC, digitsCh, labels); + storeBC(mCache.front(), digitsBC, digitsCh, digitsTrig, labels); mCache.pop_front(); ++firstBCinDeque; } diff --git a/Steer/DigitizerWorkflow/src/FT0DigitWriterSpec.h b/Steer/DigitizerWorkflow/src/FT0DigitWriterSpec.h index 8ac752f065083..35fd476eccfbf 100644 --- a/Steer/DigitizerWorkflow/src/FT0DigitWriterSpec.h +++ b/Steer/DigitizerWorkflow/src/FT0DigitWriterSpec.h @@ -39,10 +39,11 @@ o2::framework::DataProcessorSpec getFT0DigitWriterSpec(bool mctruth) 1, BranchDefinition<std::vector<o2::ft0::Digit>>{InputSpec{"digitBCinput", "FT0", "DIGITSBC"}, "FT0DIGITSBC"}, BranchDefinition<std::vector<o2::ft0::ChannelData>>{InputSpec{"digitChinput", "FT0", "DIGITSCH"}, "FT0DIGITSCH"}, + BranchDefinition<std::vector<o2::ft0::DetTrigInput>>{InputSpec{"digitTrinput", "FT0", "TRIGGERINPUT"}, "TRIGGERINPUT"}, BranchDefinition<o2::dataformats::MCTruthContainer<o2::ft0::MCLabel>>{InputSpec{"labelinput", "FT0", "DIGITSMCTR"}, "FT0DIGITSMCTR", mctruth ? 1 : 0})(); } } // namespace ft0 } // end namespace o2 -#endif /* STEER_DIGITIZERWORKFLOW_ITSMFTDIGITWRITER_H_ */ +#endif /* STEER_DIGITIZERWORKFLOW_FT0DIGITWRITER_H_ */ diff --git a/Steer/DigitizerWorkflow/src/FT0DigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/FT0DigitizerSpec.cxx index 7f63d80c95333..e248bc8506cf4 100644 --- a/Steer/DigitizerWorkflow/src/FT0DigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/FT0DigitizerSpec.cxx @@ -101,15 +101,16 @@ class FT0DPLDigitizerTask : public o2::base::BaseDPLDigitizer // call actual digitization procedure mDigitizer.setEventID(part.entryID); mDigitizer.setSrcID(part.sourceID); - mDigitizer.process(&hits, mDigitsBC, mDigitsCh, labels); + mDigitizer.process(&hits, mDigitsBC, mDigitsCh, mDigitsTrig, labels); } } } - mDigitizer.flush_all(mDigitsBC, mDigitsCh, labels); + mDigitizer.flush_all(mDigitsBC, mDigitsCh, mDigitsTrig, labels); // send out to next stage pc.outputs().snapshot(Output{"FT0", "DIGITSBC", 0, Lifetime::Timeframe}, mDigitsBC); pc.outputs().snapshot(Output{"FT0", "DIGITSCH", 0, Lifetime::Timeframe}, mDigitsCh); + pc.outputs().snapshot(Output{"FT0", "TRIGGERINPUT", 0, Lifetime::Timeframe}, mDigitsTrig); if (pc.outputs().isAllowed({"FT0", "DIGITSMCTR", 0})) { pc.outputs().snapshot(Output{"FT0", "DIGITSMCTR", 0, Lifetime::Timeframe}, labels); } @@ -128,6 +129,7 @@ class FT0DPLDigitizerTask : public o2::base::BaseDPLDigitizer bool mFinished = false; std::vector<o2::ft0::ChannelData> mDigitsCh; std::vector<o2::ft0::Digit> mDigitsBC; + std::vector<o2::ft0::DetTrigInput> mDigitsTrig; Bool_t mContinuous = kFALSE; ///< flag to do continuous simulation double mFairTimeUnitInNS = 1; ///< Fair time unit in ns @@ -153,6 +155,7 @@ o2::framework::DataProcessorSpec getFT0DigitizerSpec(int channel, bool mctruth) std::vector<OutputSpec> outputs; outputs.emplace_back("FT0", "DIGITSBC", 0, Lifetime::Timeframe); outputs.emplace_back("FT0", "DIGITSCH", 0, Lifetime::Timeframe); + outputs.emplace_back("FT0", "TRIGGERINPUT", 0, Lifetime::Timeframe); if (mctruth) { outputs.emplace_back("FT0", "DIGITSMCTR", 0, Lifetime::Timeframe); } From 1238ad770f79fdd4db6014671454b96315d2122b Mon Sep 17 00:00:00 2001 From: Markus Fasel <markus.fasel@cern.ch> Date: Fri, 8 Jan 2021 17:23:54 +0100 Subject: [PATCH 1715/1751] [EMCAL-677] Propagate trigger bits from RDH to TriggerRecord - Add field for trigger bits in trigger record - Propagate trigger bits from from RDH to new field in TriggerRecord - Set trigger bits to physics trigger in simulation - Propagate trigger bits from TriggerRecord to raw data in RawWriter --- .../EMCAL/include/DataFormatsEMCAL/TriggerRecord.h | 11 ++++++++--- DataFormats/Detectors/EMCAL/src/TriggerRecord.cxx | 3 ++- Detectors/EMCAL/simulation/src/RawWriter.cxx | 2 +- .../EMCAL/workflow/src/RawToCellConverterSpec.cxx | 6 +++++- Steer/DigitizerWorkflow/CMakeLists.txt | 1 + Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx | 3 ++- 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h index e2656f6bcca71..336cf3b45071c 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h @@ -11,6 +11,7 @@ #ifndef ALICEO2_EMCAL_TRIGGERRECORD_H #define ALICEO2_EMCAL_TRIGGERRECORD_H +#include <cstdint> #include <iosfwd> #include "Rtypes.h" #include "CommonDataFormat/InteractionRecord.h" @@ -35,24 +36,28 @@ class TriggerRecord public: TriggerRecord() = default; - TriggerRecord(const BCData& bunchcrossing, int firstentry, int nentries) : mBCData(bunchcrossing), mDataRange(firstentry, nentries) {} + TriggerRecord(const BCData& bunchcrossing, int firstentry, int nentries) : mBCData(bunchcrossing), mDataRange(firstentry, nentries), mTriggerBits(0) {} + TriggerRecord(const BCData& bunchcrossing, uint32_t triggerbits, int firstentry, int nentries) : TriggerRecord(bunchcrossing, firstentry, nentries) { mTriggerBits = triggerbits; } ~TriggerRecord() = default; void setBCData(const BCData& data) { mBCData = data; } + void setTriggerBits(uint32_t triggerbits) { mTriggerBits = triggerbits; } void setDataRange(int firstentry, int nentries) { mDataRange.set(firstentry, nentries); } void setIndexFirstObject(int firstentry) { mDataRange.setFirstEntry(firstentry); } void setNumberOfObjects(int nentries) { mDataRange.setEntries(nentries); } const BCData& getBCData() const { return mBCData; } BCData& getBCData() { return mBCData; } + uint32_t getTriggerBits() const { return mTriggerBits; } int getNumberOfObjects() const { return mDataRange.getEntries(); } int getFirstEntry() const { return mDataRange.getFirstEntry(); } void printStream(std::ostream& stream) const; private: - BCData mBCData; /// Bunch crossing data of the trigger - DataRange mDataRange; /// Index of the triggering event (event index and first entry in the container) + BCData mBCData; /// Bunch crossing data of the trigger + DataRange mDataRange; /// Index of the triggering event (event index and first entry in the container) + uint32_t mTriggerBits; /// Trigger bits as from the Raw Data Header ClassDefNV(TriggerRecord, 1); }; diff --git a/DataFormats/Detectors/EMCAL/src/TriggerRecord.cxx b/DataFormats/Detectors/EMCAL/src/TriggerRecord.cxx index 2890cfb5ce185..50cfdafe69694 100644 --- a/DataFormats/Detectors/EMCAL/src/TriggerRecord.cxx +++ b/DataFormats/Detectors/EMCAL/src/TriggerRecord.cxx @@ -8,6 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include <bitset> #include <iostream> #include "DataFormatsEMCAL/TriggerRecord.h" @@ -19,7 +20,7 @@ namespace emcal void TriggerRecord::printStream(std::ostream& stream) const { - stream << "Data for bc " << getBCData().bc << ", orbit " << getBCData().orbit << ", starting from entry " << getFirstEntry() << " with " << getNumberOfObjects() << " objects"; + stream << "Data for bc " << getBCData().bc << ", orbit " << getBCData().orbit << ", Triggers " << std::bitset<sizeof(mTriggerBits) * 8>(mTriggerBits) << ", starting from entry " << getFirstEntry() << " with " << getNumberOfObjects() << " objects"; } std::ostream& operator<<(std::ostream& stream, const TriggerRecord& trg) diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index cafe1f64c57a6..484dd76d6edae 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -168,7 +168,7 @@ bool RawWriter::processTrigger(const o2::emcal::TriggerRecord& trg) 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, trg.getBCData(), payload); + mRawWriter->addData(ddlid, crorc, link, 0, trg.getBCData(), payload, false, trg.getTriggerBits()); } std::cout << "Done" << std::endl; return true; diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index ae8620c5d2ca9..e8bddb7f752d6 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -67,6 +67,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) // Cache cells from for bunch crossings as the component reads timeframes from many links consecutively std::map<o2::InteractionRecord, std::shared_ptr<std::vector<o2::emcal::Cell>>> cellBuffer; // Internal cell buffer + std::map<o2::InteractionRecord, uint32_t> triggerBuffer; int firstEntry = 0; for (const auto& rawData : framework::InputRecordWalker(ctx.inputs())) { @@ -83,6 +84,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) auto triggerBC = o2::raw::RDHUtils::getTriggerBC(header); auto triggerOrbit = o2::raw::RDHUtils::getTriggerOrbit(header); auto feeID = o2::raw::RDHUtils::getFEEID(header); + auto triggerbits = o2::raw::RDHUtils::getTriggerType(header); o2::InteractionRecord currentIR(triggerBC, triggerOrbit); std::shared_ptr<std::vector<o2::emcal::Cell>> currentCellContainer; @@ -90,6 +92,8 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) if (found == cellBuffer.end()) { currentCellContainer = std::make_shared<std::vector<o2::emcal::Cell>>(); cellBuffer[currentIR] = currentCellContainer; + // also add trigger bits + triggerBuffer[currentIR] = triggerbits; } else { currentCellContainer = found->second; } @@ -143,7 +147,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) mOutputCells.clear(); mOutputTriggerRecords.clear(); for (auto [bc, cells] : cellBuffer) { - mOutputTriggerRecords.emplace_back(bc, mOutputCells.size(), cells->size()); + mOutputTriggerRecords.emplace_back(bc, triggerBuffer[bc], mOutputCells.size(), cells->size()); if (cells->size()) { // Sort cells according to cell ID std::sort(cells->begin(), cells->end(), [](o2::emcal::Cell& lhs, o2::emcal::Cell& rhs) { return lhs.getTower() < rhs.getTower(); }); diff --git a/Steer/DigitizerWorkflow/CMakeLists.txt b/Steer/DigitizerWorkflow/CMakeLists.txt index b210068b113d9..ac32458d355b7 100644 --- a/Steer/DigitizerWorkflow/CMakeLists.txt +++ b/Steer/DigitizerWorkflow/CMakeLists.txt @@ -31,6 +31,7 @@ o2_add_executable(digitizer-workflow src/TOFDigitizerSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::Steer + O2::CommonConstants O2::EMCALSimulation O2::FT0Simulation O2::FV0Simulation diff --git a/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx index 30cf2d36ec786..ab7478b66a16d 100644 --- a/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "EMCALDigitizerSpec.h" +#include "CommonConstants/Triggers.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" #include "Framework/DataProcessorSpec.h" @@ -128,7 +129,7 @@ void DigitizerSpec::run(framework::ProcessingContext& ctx) std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(mAccumulatedDigits)); labelAccum.mergeAtBack(mLabels); LOG(INFO) << "Have " << mAccumulatedDigits.size() << " digits "; - triggers.emplace_back(timesview[trigID], indexStart, mDigits.size()); + triggers.emplace_back(timesview[trigID], o2::trigger::PhT, indexStart, mDigits.size()); indexStart = mAccumulatedDigits.size(); mDigits.clear(); mLabels.clear(); From 536a218a4960f21b526ae53488e17280b8861f91 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 8 Jan 2021 20:01:37 +0100 Subject: [PATCH 1716/1751] Add and use explicit setters for TrackPar and TrackParCov --- .../TrackParametrization.h | 13 +++++++++++++ .../TrackParametrizationWithError.h | 11 +++++++++++ Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 14 ++++++-------- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 62c9801955b05..f5aa90ceb8101 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -137,6 +137,7 @@ class TrackParametrization GPUdDefault() TrackParametrization& operator=(TrackParametrization&& src) = default; GPUdDefault() ~TrackParametrization() = default; + GPUd() void set(value_t x, value_t alpha, const params_t& par, int charge = 1); GPUd() const value_t* getParams() const; GPUd() value_t getParam(int i) const; GPUd() value_t getX() const; @@ -245,6 +246,18 @@ GPUdi() TrackParametrization<value_T>::TrackParametrization(value_t x, value_t a } } +//____________________________________________________________ +template <typename value_T> +GPUdi() void TrackParametrization<value_T>::set(value_t x, value_t alpha, const params_t& par, int charge) +{ + mX = x; + mAlpha = alpha; + mAbsCharge = char(gpu::CAMath::Abs(charge)); + for (int i = 0; i < kNParams; i++) { + mP[i] = par[i]; + } +} + //____________________________________________________________ template <typename value_T> GPUdi() const typename TrackParametrization<value_T>::value_t* TrackParametrization<value_T>::getParams() const diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h index e86a17007e1af..9f92ddd731ef9 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h @@ -53,6 +53,7 @@ class TrackParametrizationWithError : public TrackParametrization<value_T> GPUdDefault() ~TrackParametrizationWithError() = default; using TrackParametrization<value_T>::TrackParametrization; + GPUd() void set(value_t x, value_t alpha, const params_t& par, const covMat_t& cov, int charge = 1); GPUd() const value_t* getCov() const; GPUd() value_t getSigmaY2() const; GPUd() value_t getSigmaZY() const; @@ -135,6 +136,16 @@ GPUdi() TrackParametrizationWithError<value_T>::TrackParametrizationWithError(va } } +//__________________________________________________________________________ +template <typename value_T> +GPUdi() void TrackParametrizationWithError<value_T>::set(value_t x, value_t alpha, const params_t& par, const covMat_t& cov, int charge) +{ + TrackParametrization<value_T>::set(x, alpha, par, charge); + for (int i = 0; i < kCovMatSize; i++) { + mC[i] = cov[i]; + } +} + //__________________________________________________________________________ template <typename value_T> GPUdi() const typename TrackParametrizationWithError<value_T>::value_t* TrackParametrizationWithError<value_T>::getCov() const diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index 4130ac3f60651..c1b2bfc62ec83 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -202,15 +202,13 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* const int i = trackSort[iTmp].first; labelAssigner->reset(); - oTrack = - TrackTPC(tracks[i].GetParam().GetX(), tracks[i].GetAlpha(), - {tracks[i].GetParam().GetY(), tracks[i].GetParam().GetZ(), tracks[i].GetParam().GetSinPhi(), - tracks[i].GetParam().GetDzDs(), tracks[i].GetParam().GetQPt()}, - {tracks[i].GetParam().GetCov(0), tracks[i].GetParam().GetCov(1), tracks[i].GetParam().GetCov(2), + oTrack.set(tracks[i].GetParam().GetX(), tracks[i].GetAlpha(), + {tracks[i].GetParam().GetY(), tracks[i].GetParam().GetZ(), tracks[i].GetParam().GetSinPhi(), tracks[i].GetParam().GetDzDs(), tracks[i].GetParam().GetQPt()}, + {tracks[i].GetParam().GetCov(0), + tracks[i].GetParam().GetCov(1), tracks[i].GetParam().GetCov(2), tracks[i].GetParam().GetCov(3), tracks[i].GetParam().GetCov(4), tracks[i].GetParam().GetCov(5), - tracks[i].GetParam().GetCov(6), tracks[i].GetParam().GetCov(7), tracks[i].GetParam().GetCov(8), - tracks[i].GetParam().GetCov(9), tracks[i].GetParam().GetCov(10), tracks[i].GetParam().GetCov(11), - tracks[i].GetParam().GetCov(12), tracks[i].GetParam().GetCov(13), tracks[i].GetParam().GetCov(14)}); + tracks[i].GetParam().GetCov(6), tracks[i].GetParam().GetCov(7), tracks[i].GetParam().GetCov(8), tracks[i].GetParam().GetCov(9), + tracks[i].GetParam().GetCov(10), tracks[i].GetParam().GetCov(11), tracks[i].GetParam().GetCov(12), tracks[i].GetParam().GetCov(13), tracks[i].GetParam().GetCov(14)}); oTrack.setChi2(tracks[i].GetParam().GetChi2()); auto& outerPar = tracks[i].OuterParam(); From 636d82aa739321ebc88028d940947c65c72f6133 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 8 Jan 2021 20:05:51 +0100 Subject: [PATCH 1717/1751] Method to fill standalone shared clusters map --- .../Interface/GPUO2InterfaceRefit.cxx | 30 ++++++++++++------- .../Interface/GPUO2InterfaceRefit.h | 5 +++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx index e406532c81719..f3b7e871cdbf0 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx @@ -20,7 +20,24 @@ using namespace o2::gpu; using namespace o2::tpc; -GPUTPCO2InterfaceRefit::GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const TPCFastTransform* trans, float bz, const TPCClRefElem* trackRef, const unsigned char* sharedmap, std::vector<o2::tpc::TrackTPC>* trks, o2::base::Propagator* p) : mRefit(), mParam(new GPUParam) +void GPUTPCO2InterfaceRefit::fillSharedClustersMap(const ClusterNativeAccess* cl, const gsl::span<const TrackTPC> trks, const TPCClRefElem* trackRef, unsigned char* shmap) +{ + if (!cl || !shmap) { + throw std::runtime_error("Must provide clusters access and preallocated recepient for shared map"); + } + memset(shmap, 0, sizeof(char) * cl->nClustersTotal); + for (unsigned int i = 0; i < trks.size(); i++) { + for (unsigned int j = 0; j < trks[i].getNClusterReferences(); j++) { + size_t idx = &trks[i].getCluster(trackRef, j, *cl) - cl->clustersLinear; + shmap[idx] = shmap[idx] ? 2 : 1; + } + } + for (unsigned int i = 0; i < cl->nClustersTotal; i++) { + shmap[i] = (shmap[i] > 1 ? GPUTPCGMMergedTrackHit::flagShared : 0) | cl->clustersLinear[i].getFlags(); + } +} + +GPUTPCO2InterfaceRefit::GPUTPCO2InterfaceRefit(const ClusterNativeAccess* cl, const TPCFastTransform* trans, float bz, const TPCClRefElem* trackRef, const unsigned char* sharedmap, const std::vector<TrackTPC>* trks, o2::base::Propagator* p) : mRefit(), mParam(new GPUParam) { if (sharedmap == nullptr && trks == nullptr) { throw std::runtime_error("Must provide either shared cluster map or vector of tpc tracks to build the map"); @@ -28,16 +45,7 @@ GPUTPCO2InterfaceRefit::GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAcces if (sharedmap == nullptr) { mSharedMap.resize(cl->nClustersTotal); sharedmap = mSharedMap.data(); - std::fill(mSharedMap.begin(), mSharedMap.end(), 0); - for (unsigned int i = 0; i < (*trks).size(); i++) { - for (unsigned int j = 0; j < (*trks)[i].getNClusterReferences(); j++) { - size_t idx = &(*trks)[i].getCluster(trackRef, j, *cl) - cl->clustersLinear; - mSharedMap[idx] = mSharedMap[idx] ? 2 : 1; - } - } - for (unsigned int i = 0; i < cl->nClustersTotal; i++) { - mSharedMap[i] = (mSharedMap[i] > 1 ? GPUTPCGMMergedTrackHit::flagShared : 0) | cl->clustersLinear[i].getFlags(); - } + fillSharedClustersMap(cl, *trks, trackRef, mSharedMap.data()); } mParam->SetDefaults(bz); diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index 8126290e198b2..5e7e5327549d4 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -28,6 +28,7 @@ #include "GPUTrackingRefit.h" #include <memory> #include <vector> +#include <gsl/span> namespace o2::tpc { @@ -45,7 +46,7 @@ class GPUTPCO2InterfaceRefit // - Either the shared cluster map (sharedmap) or the vector of tpc tracks (trks) to build the shared cluster map internally // - o2::base::Propagator (p) in case RefitTrackAsTrackParCov is to be used - GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const TPCFastTransform* trans, float bz, const o2::tpc::TPCClRefElem* trackRef, const unsigned char* sharedmap = nullptr, std::vector<o2::tpc::TrackTPC>* trks = nullptr, o2::base::Propagator* p = nullptr); + GPUTPCO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const TPCFastTransform* trans, float bz, const o2::tpc::TPCClRefElem* trackRef, const unsigned char* sharedmap = nullptr, const std::vector<o2::tpc::TrackTPC>* trks = nullptr, o2::base::Propagator* p = nullptr); ~GPUTPCO2InterfaceRefit(); int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false) { return mRefit.RefitTrackAsGPU(trk, outward, resetCov); } @@ -56,6 +57,8 @@ class GPUTPCO2InterfaceRefit void setTrackReferenceX(float v); void setIgnoreErrorsAtTrackEnds(bool v) { mRefit.mIgnoreErrorsOnTrackEnds = v; } + static void fillSharedClustersMap(const o2::tpc::ClusterNativeAccess* cl, const gsl::span<const o2::tpc::TrackTPC> trks, const o2::tpc::TPCClRefElem* trackRef, unsigned char* shmap); + private: GPUTrackingRefit mRefit; std::unique_ptr<GPUParam> mParam; From 605cc349fe52793c1c31108aad38a614eb811150 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Fri, 8 Jan 2021 20:06:39 +0100 Subject: [PATCH 1718/1751] Use GPUTPCO2InterfaceRefit for TPC-ITS matches refit --- .../Base/include/DetectorsBase/Propagator.h | 6 +- .../include/GlobalTracking/MatchTPCITS.h | 12 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 416 +++--------------- 3 files changed, 75 insertions(+), 359 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index 72fa4032847b6..174fc69f59240 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -124,15 +124,15 @@ class Propagator static int initFieldFromGRP(const std::string grpFileName, std::string grpName = "GRP", bool verbose = false); #endif + GPUd() MatBudget getMatBudget(MatCorrType corrType, const o2::math_utils::Point3D<float>& p0, const o2::math_utils::Point3D<float>& p1) const; + GPUd() void getFiedXYZ(const math_utils::Point3D<float> xyz, float* bxyz) const; + private: #ifndef GPUCA_GPUCODE Propagator(); ~Propagator() = default; #endif - GPUd() MatBudget getMatBudget(MatCorrType corrType, const o2::math_utils::Point3D<float>& p0, const o2::math_utils::Point3D<float>& p1) const; - GPUd() void getFiedXYZ(const math_utils::Point3D<float> xyz, float* bxyz) const; - const o2::field::MagFieldFast* mField = nullptr; ///< External fast field (barrel only for the moment) float mBz = 0; // nominal field diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 1e13ca9c01b52..c4fa56f08429c 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -45,6 +45,7 @@ #include "DataFormatsTPC/ClusterNativeHelper.h" #include "ITSReconstruction/RecoGeomHelper.h" #include "TPCFastTransform.h" +#include "GPUO2InterfaceRefit.h" #include "GlobalTracking/MatchTPCITSParams.h" #include "CommonDataFormat/FlatHisto2D.h" @@ -484,7 +485,7 @@ class MatchTPCITS #endif private: - void updateTPCTimeDependentParams(); + void updateTimeDependentParams(); int findLaddersToCheckBOn(int ilr, int lad0, const o2::math_utils::CircleXYf_t& circle, float errYFrac, std::array<int, MaxLadderCand>& lad2Check) const; @@ -504,9 +505,8 @@ class MatchTPCITS void doMatching(int sec); - void refitWinners(bool loopInITS = false); - bool refitTrackTPCITSloopITS(int iITS, int& iTPC); - bool refitTrackTPCITSloopTPC(int iTPC, int& iITS); + void refitWinners(); + bool refitTrackTPCITS(int iTPC, int& iITS); bool refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, float xTgt, int trcID, float timeTB) const; void selectBestMatches(); @@ -607,6 +607,7 @@ class MatchTPCITS bool mFieldON = true; ///< flag for field ON/OFF bool mCosmics = false; ///< flag cosmics mode bool mMCTruthON = false; ///< flag availability of MC truth + float mBz = 0; ///< nominal Bz o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF @@ -641,6 +642,7 @@ class MatchTPCITS float mTPCBin2Z = 0.; ///< conversion coeff from TPC time-bin to Z float mNTPCBinsFullDrift = 0.; ///< max time bin for full drift float mTPCZMax = 0.; ///< max drift length + float mTPCmeanX0Inv = 1. / 31850.; ///< TPC gas 1/X0 float mMinTPCTrackPtInv = 999.; ///< cutoff on TPC track inverse pT float mMinITSTrackPtInv = 999.; ///< cutoff on ITS track inverse pT @@ -650,6 +652,8 @@ class MatchTPCITS std::unique_ptr<TPCTransform> mTPCTransform; ///< TPC cluster transformation std::unique_ptr<o2::gpu::GPUParam> mTPCClusterParam; ///< TPC clusters error param + std::unique_ptr<o2::gpu::GPUTPCO2InterfaceRefit> mTPCRefitter; ///< TPC refitter used for TPC tracks refit during the reconstruction + std::vector<unsigned char> mTPCRefitterShMap; o2::BunchFilling mBunchFilling; std::array<int16_t, o2::constants::lhc::LHCMaxBunches> mClosestBunchAbove; // closest filled bunch from above diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index e905e32a21854..2f528a3ca4d9e 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -247,7 +247,8 @@ void MatchTPCITS::run() if (!mInitDone) { LOG(FATAL) << "init() was not done yet"; } - updateTPCTimeDependentParams(); + + updateTimeDependentParams(); ProcInfo_t procInfoStart, procInfoStop; gSystem->GetProcInfo(&procInfoStart); @@ -345,12 +346,6 @@ void MatchTPCITS::init() std::unique_ptr<TPCTransform> fastTransform = (o2::tpc::TPCFastTransformHelperO2::instance()->create(0)); mTPCTransform = std::move(fastTransform); mTPCClusterParam = std::make_unique<o2::gpu::GPUParam>(); - mTPCClusterParam->SetDefaults(o2::base::Propagator::Instance()->getNominalBz()); // TODO this may change - auto bz = std::abs(o2::base::Propagator::Instance()->getNominalBz()); - mFieldON = bz > 0.01; - - mMinTPCTrackPtInv = (mFieldON && mParams->minTPCTrackR > 0) ? 1. / std::abs(mParams->minTPCTrackR * bz * o2::constants::math::B2C) : 999.; - mMinITSTrackPtInv = (mFieldON && mParams->minITSTrackR > 0) ? 1. / std::abs(mParams->minITSTrackR * bz * o2::constants::math::B2C) : 999.; if (mVDriftCalibOn) { float maxDTgl = std::min(0.02f, mParams->maxVDriftUncertainty) * mParams->maxTglForVDriftCalib; @@ -377,9 +372,9 @@ void MatchTPCITS::init() } //______________________________________________ -void MatchTPCITS::updateTPCTimeDependentParams() +void MatchTPCITS::updateTimeDependentParams() { - ///< update parameters depending on TPC drift properties + ///< update parameters depending on time (once per TF) auto& gasParam = o2::tpc::ParameterGas::Instance(); auto& elParam = o2::tpc::ParameterElectronics::Instance(); auto& detParam = o2::tpc::ParameterDetector::Instance(); @@ -400,6 +395,22 @@ void MatchTPCITS::updateTPCTimeDependentParams() mTPCVDrift0Inv = 1. / mTPCVDrift0; mNTPCBinsFullDrift = mTPCZMax * mZ2TPCBin; mTPCTimeEdgeTSafeMargin = z2TPCBin(mParams->safeMarginTPCTimeEdge); + + mBz = o2::base::Propagator::Instance()->getNominalBz(); + mTPCClusterParam->SetDefaults(mBz); // TODO this may change + mFieldON = std::abs(mBz) > 0.01; + + mMinTPCTrackPtInv = (mFieldON && mParams->minTPCTrackR > 0) ? 1. / std::abs(mParams->minTPCTrackR * mBz * o2::constants::math::B2C) : 999.; + mMinITSTrackPtInv = (mFieldON && mParams->minITSTrackR > 0) ? 1. / std::abs(mParams->minITSTrackR * mBz * o2::constants::math::B2C) : 999.; + + // RSTODO: do we need to recreate it? It should be enough to add/use setters in GPUTPCO2InterfaceRefit + mTPCRefitterShMap.resize(mTPCClusterIdxStruct->nClustersTotal); + o2::gpu::GPUTPCO2InterfaceRefit::fillSharedClustersMap(mTPCClusterIdxStruct, mTPCTracksArray, mTPCTrackClusIdx.data(), mTPCRefitterShMap.data()); + mTPCRefitter = std::make_unique<o2::gpu::GPUTPCO2InterfaceRefit>(mTPCClusterIdxStruct, mTPCTransform.get(), mBz, mTPCTrackClusIdx.data(), mTPCRefitterShMap.data(), nullptr, o2::base::Propagator::Instance()); + + o2::math_utils::Point3D<float> p0(90., 1., 1), p1(90., 100., 100.); + auto matbd = o2::base::Propagator::Instance()->getMatBudget(mParams->matCorr, p0, p1); + mTPCmeanX0Inv = matbd.meanX2X0 / matbd.length; } //______________________________________________ @@ -1308,224 +1319,25 @@ void MatchTPCITS::print() const } //______________________________________________ -void MatchTPCITS::refitWinners(bool loopInITS) +void MatchTPCITS::refitWinners() { ///< refit winning tracks mTimer[SWRefit].Start(false); LOG(INFO) << "Refitting winner matches"; mWinnerChi2Refit.resize(mITSWork.size(), -1.f); - if (loopInITS) { - int iTPC = 0; // will be ignored - for (int iITS = 0; iITS < (int)mITSWork.size(); iITS++) { - if (!refitTrackTPCITSloopITS(iITS, iTPC)) { - continue; - } - mWinnerChi2Refit[iITS] = mMatchedTracks.back().getChi2Refit(); - } - } else { - int iITS; - for (int iTPC = 0; iTPC < (int)mTPCWork.size(); iTPC++) { - if (!refitTrackTPCITSloopTPC(iTPC, iITS)) { - continue; - } - mWinnerChi2Refit[iITS] = mMatchedTracks.back().getChi2Refit(); + int iITS; + for (int iTPC = 0; iTPC < (int)mTPCWork.size(); iTPC++) { + if (!refitTrackTPCITS(iTPC, iITS)) { + continue; } + mWinnerChi2Refit[iITS] = mMatchedTracks.back().getChi2Refit(); } - /* - */ - // flush last tracks mTimer[SWRefit].Stop(); } //______________________________________________ -bool MatchTPCITS::refitTrackTPCITSloopITS(int iITS, int& iTPC) -{ - ///< refit in inward direction the pair of TPC and ITS tracks - - const float maxStep = 2.f; // max propagation step (TODO: tune) - - const auto& tITS = mITSWork[iITS]; - if (isDisabledITS(tITS)) { - return false; // no match - } - const auto& itsMatchRec = mMatchRecordsITS[tITS.matchID]; - iTPC = itsMatchRec.partnerID; - const auto& tTPC = mTPCWork[iTPC]; - const auto& itsTrOrig = mITSTracksArray[tITS.sourceID]; // currently we store clusterIDs in the track - - mMatchedTracks.emplace_back(tTPC, tITS); // create a copy of TPC track at xRef - auto& trfit = mMatchedTracks.back(); - // in continuos mode the Z of TPC track is meaningless, unless it is CE crossing - // track (currently absent, TODO) - if (!mCompareTracksDZ) { - trfit.setZ(tITS.getZ()); // fix the seed Z - } - auto dzCorr = trfit.getZ() - tTPC.getZ(); - float deltaT = dzCorr * mZ2TPCBin; // time correction in time-bins - - // refit TPC track inward into the ITS - int nclRefit = 0, ncl = itsTrOrig.getNumberOfClusters(); - float chi2 = 0.f; - auto geom = o2::its::GeometryTGeo::Instance(); - auto propagator = o2::base::Propagator::Instance(); - // NOTE: the ITS cluster index is stored wrt 1st cluster of relevant ROF, while here we extract clusters from the - // buffer for the whole TF. Therefore, we should shift the index by the entry of the ROF's 1st cluster in the global cluster buffer - int clusIndOffs = mITSClusterROFRec[tITS.roFrame].getFirstEntry(); - int clEntry = itsTrOrig.getFirstClusterEntry(); - - float addErr2 = 0; - // extra error on tgl due to the assumed vdrift uncertainty - if (mVDriftCalibOn) { - addErr2 = tITS.getParam(o2::track::kTgl) * mParams->maxVDriftUncertainty; - addErr2 *= addErr2; - trfit.updateCov(addErr2, o2::track::kSigTgl2); - } - - for (int icl = 0; icl < ncl; icl++) { - const auto& clus = mITSClustersArray[clusIndOffs + mITSTrackClusIdx[clEntry++]]; - float alpha = geom->getSensorRefAlpha(clus.getSensorID()), x = clus.getX(); - if (!trfit.rotate(alpha) || - // note: here we also calculate the L,T integral (in the inward direction, but this is irrelevant) - // note: we should eventually use TPC pid in the refit (TODO) - // note: since we are at small R, we can use field BZ component at origin rather than 3D field - !propagator->propagateToX(trfit, x, propagator->getNominalBz(), - MaxSnp, maxStep, mUseMatCorrFlag, &trfit.getLTIntegralOut())) { - break; - } - chi2 += trfit.getPredictedChi2(clus); - if (!trfit.update(clus)) { - break; - } - nclRefit++; - } - if (nclRefit != ncl) { - printf("FAILED after ncl=%d\n", nclRefit); - printf("its was: "); - tITS.print(); - printf("tpc was: "); - tTPC.print(); - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - - // we need to update the LTOF integral by the distance to the "primary vertex" - const o2::dataformats::VertexBase vtxDummy; // at the moment using dummy vertex: TODO use MeanVertex constraint instead - if (!propagator->propagateToDCA(vtxDummy, trfit, propagator->getNominalBz(), - maxStep, mUseMatCorrFlag, nullptr, &trfit.getLTIntegralOut())) { - LOG(ERROR) << "LTOF integral might be incorrect"; - } - - /// precise time estimate - auto tpcTrOrig = mTPCTracksArray[tTPC.sourceID]; - float timeTB = getTPCTrackCorrectedTimeBin(tpcTrOrig, deltaT); - // convert time in timebins to time in microseconds - float time = timeTB * mTPCTBinMUS; - // estimate the error on time - float timeErr = std::sqrt(tITS.getSigmaZ2() + tTPC.getSigmaZ2()) * mTPCVDrift0Inv; - - // outward refit - auto& tracOut = trfit.getParamOut(); // this track is already at the matching reference X - { - if (mVDriftCalibOn) { - tracOut.updateCov(addErr2, o2::track::kSigTgl2); - } - int icl = tpcTrOrig.getNClusterReferences() - 1; - uint8_t sector, prevsector, row, prevrow; - uint32_t clusterIndexInRow; - std::array<float, 2> clsYZ; - std::array<float, 3> clsCov = {}; - float clsX; - - const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); - mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); - // rotate to 1 cluster's sector - if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - // TODO: consider propagating in empty space till TPC entrance in large step, and then in more detailed propagation with mat. corrections - - // propagate to 1st cluster X - if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { - LOG(DEBUG) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - // - mTPCClusterParam->GetClusterErrors2(row, clsYZ[1], tracOut.getSnp(), tracOut.getTgl(), clsCov[0], clsCov[2]); - // - float chi2Out = tracOut.getPredictedChi2(clsYZ, clsCov); - if (!tracOut.update(clsYZ, clsCov)) { - LOG(WARNING) << "Update failed at 1st cluster, chi2 =" << chi2Out; - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - prevrow = row; - prevsector = sector; - - for (; icl--;) { - const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); - if (row <= prevrow) { - LOG(DEBUG) << "New row/sect " << int(row) << '/' << int(sector) << " is <= the previous " << int(prevrow) - << '/' << int(prevsector) << " TrackID: " << tTPC.sourceID << " Pt:" << tracOut.getPt(); - if (row < prevrow) { - break; - } else { - continue; // just skip duplicate clusters - } - } - prevrow = row; - mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); - if (prevsector != sector) { - prevsector = sector; - if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - } - if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, - 10., MatCorrType::USEMatCorrNONE, &trfit.getLTIntegralOut())) { // no material correction! - LOG(DEBUG) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" - << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - chi2Out += tracOut.getPredictedChi2(clsYZ, clsCov); - if (!tracOut.update(clsYZ, clsCov)) { - LOG(DEBUG) << "Update failed at cluster " << icl << ", chi2 =" << chi2Out; - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - } - // propagate to the outer edge of the TPC, TODO: check outer radius - // Note: it is allowed to not reach the requested radius - propagator->PropagateToXBxByBz(tracOut, XTPCOuterRef, MaxSnp, - 10., mUseMatCorrFlag, &trfit.getLTIntegralOut()); - - // LOG(INFO) << "Refitted with chi2 = " << chi2Out; - } - - trfit.setChi2Match(itsMatchRec.chi2); - trfit.setChi2Refit(chi2); - trfit.setTimeMUS(time, timeErr); - trfit.setRefTPC(tTPC.sourceID); - trfit.setRefITS(tITS.sourceID); - - if (mMCTruthON) { // store MC info - mOutITSLabels.emplace_back(mITSLblWork[iITS]); - mOutTPCLabels.emplace_back(mTPCLblWork[iTPC]); - } - - // trfit.print(); // DBG - - return true; -} - -//______________________________________________ -bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) +bool MatchTPCITS::refitTrackTPCITS(int iTPC, int& iITS) { ///< refit in inward direction the pair of TPC and ITS tracks @@ -1617,87 +1429,47 @@ bool MatchTPCITS::refitTrackTPCITSloopTPC(int iTPC, int& iITS) float timeErr = std::sqrt(tITS.getSigmaZ2() + tTPC.getSigmaZ2()) * mTPCVDrift0Inv; // outward refit - auto& tracOut = trfit.getParamOut(); // this track is already at the matching reference X + auto& tracOut = trfit.getParamOut(); // this is a clone of ITS outward track already at the matching reference X + auto& tofL = trfit.getLTIntegralOut(); + { - if (mVDriftCalibOn) { - tracOut.updateCov(addErr2, o2::track::kSigTgl2); - } - int icl = tpcTrOrig.getNClusterReferences() - 1; - uint8_t sector, prevsector, row, prevrow; - uint32_t clusterIndexInRow; - std::array<float, 2> clsYZ; - std::array<float, 3> clsCov = {}; - float clsX; - - const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); - mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime() - timeTB, clsX, clsYZ[0], clsYZ[1]); - // rotate to 1 cluster's sector - if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; + float xtogo = 0; + if (!tracOut.getXatLabR(XTPCInnerRef, xtogo, mBz, o2::track::DirOutward) || + !propagator->PropagateToXBxByBz(tracOut, xtogo, MaxSnp, 10., mUseMatCorrFlag, &tofL)) { + LOG(DEBUG) << "Propagation to inner TPC boundary X=" << xtogo << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); mMatchedTracks.pop_back(); // destroy failed track return false; } - // TODO: consider propagating in empty space till TPC entrance in large step, and then in more detailed propagation with mat. corrections - - // propagate to 1st cluster X - if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, 10., mUseMatCorrFlag, &trfit.getLTIntegralOut())) { - LOG(DEBUG) << "Propagation to 1st cluster at X=" << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp(); - mMatchedTracks.pop_back(); // destroy failed track - return false; + if (mVDriftCalibOn) { + tracOut.updateCov(addErr2, o2::track::kSigTgl2); } - // - mTPCClusterParam->GetClusterErrors2(row, clsYZ[1], tracOut.getSnp(), tracOut.getTgl(), clsCov[0], clsCov[2]); - // - float chi2Out = tracOut.getPredictedChi2(clsYZ, clsCov); - if (!tracOut.update(clsYZ, clsCov)) { - LOG(WARNING) << "Update failed at 1st cluster, chi2 =" << chi2Out; + float chi2Out = 0; + auto posStart = tracOut.getXYZGlo(); + int retVal = mTPCRefitter->RefitTrackAsTrackParCov(tracOut, tpcTrOrig.getClusterRef(), timeTB, &chi2Out, true, false); // outward refit + if (retVal < 0) { + LOG(DEBUG) << "Refit failed"; mMatchedTracks.pop_back(); // destroy failed track return false; } - prevrow = row; - prevsector = sector; - - for (; icl--;) { - const auto& cl = tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sector, row); - if (row <= prevrow) { - LOG(DEBUG) << "New row/sect " << int(row) << '/' << int(sector) << " is <= the previous " << int(prevrow) - << '/' << int(prevsector) << " TrackID: " << tTPC.sourceID << " Pt:" << tracOut.getPt(); - if (row < prevrow) { - break; - } else { - continue; // just skip duplicate clusters - } - } - prevrow = row; - mTPCTransform->Transform(sector, row, cl.getPad(), cl.getTime() - timeTB, clsX, clsYZ[0], clsYZ[1]); - if (prevsector != sector) { - prevsector = sector; - if (!tracOut.rotate(o2::math_utils::sector2Angle(sector % 18))) { - LOG(DEBUG) << "Rotation to sector " << int(sector % 18) << " failed"; - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - } - if (!propagator->PropagateToXBxByBz(tracOut, clsX, MaxSnp, - 10., MatCorrType::USEMatCorrNONE, &trfit.getLTIntegralOut())) { // no material correction! - LOG(DEBUG) << "Propagation to cluster " << icl << " (of " << tpcTrOrig.getNClusterReferences() << ") at X=" - << clsX << " failed, Xtr=" << tracOut.getX() << " snp=" << tracOut.getSnp() << " pT=" << tracOut.getPt(); - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - chi2Out += tracOut.getPredictedChi2(clsYZ, clsCov); - if (!tracOut.update(clsYZ, clsCov)) { - LOG(DEBUG) << "Update failed at cluster " << icl << ", chi2 =" << chi2Out; - mMatchedTracks.pop_back(); // destroy failed track - return false; - } - } - // propagate to the outer edge of the TPC, TODO: check outer radius - // Note: it is allowed to not reach the requested radius - propagator->PropagateToXBxByBz(tracOut, XTPCOuterRef, MaxSnp, - 10., mUseMatCorrFlag, &trfit.getLTIntegralOut()); - - // LOG(INFO) << "Refitted with chi2 = " << chi2Out; + auto posEnd = tracOut.getXYZGlo(); + // account path integrals + float dX = posEnd.x() - posStart.x(), dY = posEnd.y() - posStart.y(), dZ = posEnd.z() - posStart.z(), d2XY = dX * dX + dY * dY; + if (mFieldON) { // circular arc = 2*R*asin(dXY/2R) + float b[3]; + o2::math_utils::Point3D<float> posAv(0.5 * (posEnd.x() + posStart.x()), 0.5 * (posEnd.y() + posStart.y()), 0.5 * (posEnd.z() + posStart.z())); + propagator->getFiedXYZ(posAv, b); + float curvH = std::abs(0.5f * tracOut.getCurvature(b[2])), arcXY = 1. / curvH * std::asin(curvH * std::sqrt(d2XY)); + d2XY = arcXY * arcXY; + } + auto lInt = std::sqrt(d2XY + dZ * dZ); + tofL.addStep(lInt, tracOut); + tofL.addX2X0(lInt * mTPCmeanX0Inv); + propagator->PropagateToXBxByBz(tracOut, XTPCOuterRef, MaxSnp, 10., mUseMatCorrFlag, &tofL); + /* + LOG(INFO) << "TPC " << iTPC << " ITS " << iITS << " Refitted with chi2 = " << chi2Out; + tracOut.print(); + tofL.print(); + */ } trfit.setChi2Match(tpcMatchRec.chi2); @@ -1731,77 +1503,17 @@ bool MatchTPCITS::refitTPCInward(o2::track::TrackParCov& trcIn, float& chi2, flo constexpr float TolSNP = 0.99; const auto& tpcTrOrig = mTPCTracksArray[trcID]; - constexpr int MaxClus = 2 * 152 + 1; // TODO - std::array<const o2::tpc::ClusterNative*, MaxClus> clsArr; - std::array<uint8_t, MaxClus> sectArr; - std::array<uint8_t, MaxClus> rowArr; - // select clusters to use - int iclPrev = 0, nclAcc = 0, icl = tpcTrOrig.getNClusterReferences(); - // the innermost cluster is last one - clsArr[nclAcc] = &tpcTrOrig.getCluster(mTPCTrackClusIdx, --icl, *mTPCClusterIdxStruct, sectArr[nclAcc], rowArr[nclAcc]); - nclAcc++; - for (; icl--;) { - clsArr[nclAcc] = &tpcTrOrig.getCluster(mTPCTrackClusIdx, icl, *mTPCClusterIdxStruct, sectArr[nclAcc], rowArr[nclAcc]); - if (rowArr[iclPrev] < rowArr[nclAcc] || // row grows - (rowArr[iclPrev] == rowArr[nclAcc] && sectArr[iclPrev] == sectArr[nclAcc])) { // split clusters? - iclPrev = nclAcc++; - } else { - break; // discard looping part - } - } - // now selected clusters span from inner to outer rows - - std::array<float, 2> clsYZ; - std::array<float, 3> clsCov = {}; - float clsX; trcIn = tpcTrOrig.getOuterParam(); - trcIn.resetCovariance(); - trcIn.setCov(tpcTrOrig.getQ2Pt() * tpcTrOrig.getQ2Pt(), o2::track::kSigQ2Pt2); // 100% error of the *original track inner param* chi2 = 0; - icl = nclAcc - 1; - - // printf("RowsSpan: %d %d | %d clusters of %d\n", rowArr[0], rowArr[icl], nclAcc, tpcTrOrig.getNClusterReferences()); // tmp auto propagator = o2::base::Propagator::Instance(); - mTPCTransform->Transform(sectArr[icl], rowArr[icl], clsArr[icl]->getPad(), clsArr[icl]->getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); - mTPCClusterParam->GetClusterErrors2(rowArr[icl], clsYZ[1], trcIn.getSnp(), trcIn.getTgl(), clsCov[0], clsCov[2]); - uint8_t sectCurr = sectArr[icl]; - if (!trcIn.rotate(o2::math_utils::sector2Angle(sectCurr % 18))) { - LOG(DEBUG) << "Rotation to sector " << int(sectCurr % 18) << " failed"; - return false; - } - trcIn.setX(clsX); - trcIn.setY(clsYZ[0]); - trcIn.setZ(clsYZ[1]); - if (!trcIn.update(clsYZ, clsCov)) { - LOG(WARNING) << "Update failed at cluster " << icl << ", chi2 =" << chi2; + int retVal = mTPCRefitter->RefitTrackAsTrackParCov(trcIn, tpcTrOrig.getClusterRef(), timeTB, &chi2, false, true); // inward refit with matrix reset + if (retVal < 0) { + LOG(WARNING) << "Refit failed"; LOG(WARNING) << trcIn.asString(); return false; } - for (; icl--;) { - if (sectArr[icl] != sectCurr) { - sectCurr = sectArr[icl]; - if (!trcIn.rotate(o2::math_utils::sector2Angle(sectCurr % 18))) { - LOG(DEBUG) << "Rotation to sector " << int(sectCurr % 18) << " failed"; - LOG(DEBUG) << trcIn.asString(); - return false; - } - } - mTPCTransform->Transform(sectArr[icl], rowArr[icl], clsArr[icl]->getPad(), clsArr[icl]->getTime(), clsX, clsYZ[0], clsYZ[1], timeTB); - mTPCClusterParam->GetClusterErrors2(rowArr[icl], clsYZ[1], trcIn.getSnp(), trcIn.getTgl(), clsCov[0], clsCov[2]); - if (!propagator->PropagateToXBxByBz(trcIn, clsX, TolSNP, 10., MatCorrType::USEMatCorrNONE)) { // no material correction! - LOG(DEBUG) << "Propagation to cluster at X=" - << clsX << " failed, Xtr=" << trcIn.getX() << " snp=" << trcIn.getSnp() << " pT=" << trcIn.getPt(); - LOG(DEBUG) << trcIn.asString(); - return false; - } - chi2 += trcIn.getPredictedChi2(clsYZ, clsCov); - if (!trcIn.update(clsYZ, clsCov)) { - LOG(WARNING) << "Update failed at cluster " << icl << ", chi2 =" << chi2; - LOG(WARNING) << trcIn.asString(); - return false; - } - } + // // propagate to the inner edge of the TPC // Note: it is allowed to not reach the requested radius if (!propagator->PropagateToXBxByBz(trcIn, xTgt, MaxSnp, 2., mUseMatCorrFlag)) { From 97403171c59f0bd73550378bf0f648056701959b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 8 Jan 2021 17:09:10 +0100 Subject: [PATCH 1719/1751] GPU: Fix finding fmt in standalone benchmark build --- GPU/GPUTracking/Standalone/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 5a3ad4dd18f9e..d85292225ff27 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -106,7 +106,7 @@ if(CONFIG_O2_EXTENSIONS) endif() if(CONFIG_FMT) - find_package(fmt REQUIRED) + find_package(fmt REQUIRED HINTS $ENV{FMT_ROOT}) else() add_definitions(-DGPUCA_NO_FMT) endif() From d8eae014cd30f700698746ad11077c809b8fea3b Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 8 Jan 2021 17:16:42 +0100 Subject: [PATCH 1720/1751] GPU: Should be hidden for all GPU device code not only OpenCL --- .../include/ReconstructionDataFormats/TrackParametrization.h | 2 +- .../include/ReconstructionDataFormats/TrackUtils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index f5aa90ceb8101..64eb2d3847d31 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -31,7 +31,7 @@ #include "GPUCommonArray.h" #include "GPUROOTCartesianFwd.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <algorithm> #include <cfloat> #include <cmath> diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h index bfd65642e1b79..30e4495b140db 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h @@ -19,7 +19,7 @@ #include "GPUCommonRtypes.h" #include "GPUCommonArray.h" -#ifndef __OPENCL__ +#ifndef GPUCA_GPUCODE_DEVICE #include <cmath> #endif From bbf50971ffa45981055d95d6ab9fc2ddc22e97e7 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 8 Jan 2021 19:55:31 +0100 Subject: [PATCH 1721/1751] GPU: Fix alignment of GPUParamRTC --- GPU/GPUTracking/Base/GPUParam.cxx | 2 ++ GPU/GPUTracking/Base/GPUSettingsList.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index c8292f65fcfe8..b7adba5efb4e4 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -17,6 +17,7 @@ #include "GPUCommonMath.h" #include "GPUTPCGMPolynomialFieldManager.h" #include "GPUDataTypes.h" +#include "GPUConstantMem.h" using namespace GPUCA_NAMESPACE::gpu; @@ -247,6 +248,7 @@ std::string GPUParamRTC::generateRTCCode(const GPUParam& param, bool useConstexp static_assert(alignof(GPUCA_NAMESPACE::gpu::GPUParam) == alignof(GPUCA_NAMESPACE::gpu::GPUSettingsRec)); static_assert(alignof(GPUCA_NAMESPACE::gpu::GPUParam) == alignof(GPUCA_NAMESPACE::gpu::GPUSettingsParam)); static_assert(sizeof(GPUCA_NAMESPACE::gpu::GPUParam) - sizeof(GPUCA_NAMESPACE::gpu::GPUParamRTC) == sizeof(GPUCA_NAMESPACE::gpu::GPUSettingsRec) + sizeof(GPUCA_NAMESPACE::gpu::GPUSettingsParam) - sizeof(GPUCA_NAMESPACE::gpu::gpu_rtc::GPUSettingsRec) - sizeof(GPUCA_NAMESPACE::gpu::gpu_rtc::GPUSettingsParam)); +static_assert(sizeof(GPUParam) % alignof(GPUConstantMem) == 0 && sizeof(GPUParamRTC) % alignof(GPUConstantMem) == 0, "Size of both GPUParam and of GPUParamRTC must be a multiple of the alignmeent of GPUConstantMem"); o2::base::Propagator* GPUParam::GetDefaultO2Propagator(bool useGPUField) const { diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index f4c9e54c7f56c..3d43ec7118887 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -87,7 +87,7 @@ AddOptionRTC(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit AddOptionRTC(trdStopTrkAfterNMissLy, unsigned char, 6, "", 0, "Abandon track following after N layers without a TRD match") AddOptionRTC(trackingRefitGPUModel, char, 1, "", 0, "Use GPU track model for the Global Track Refit") AddCustomCPP(void SetMinTrackPt(float v) { MaxTrackQPt = v > 0.001 ? (1. / v) : (1. / 0.001); }) -AddVariable(dummyRTC, float, 0.f) // Ensure non empty struct and proper alignment even if all normal members are constexpr +AddVariable(dummyRTC, void*, nullptr) // Ensure non empty struct and proper alignment even if all normal members are constexpr AddHelp("help", 'h') EndConfig() @@ -343,7 +343,7 @@ AddVariableRTC(dodEdx, char, 0) // Do dEdx computation AddVariableRTC(earlyTpcTransform, char, 0) // do Early TPC transformation AddVariableRTC(debugLevel, char, 0) // Debug level AddVariableRTC(continuousMaxTimeBin, int, 0) // Max time bin for continuous tracking -AddVariable(dummyRTC, float, 0.f) // Ensure non empty struct and proper alignment even if all normal members are constexpr +AddVariable(dummyRTC, void*, nullptr) // Ensure non empty struct and proper alignment even if all normal members are constexpr EndConfig() EndNamespace() // gpu From 2922ce18e112916a5ee208f730da05336015d5ee Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Fri, 8 Jan 2021 21:31:42 +0100 Subject: [PATCH 1722/1751] GPU: Do not compile dEdx splines with OpenCL1 --- GPU/GPUTracking/dEdx/GPUdEdx.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/dEdx/GPUdEdx.h b/GPU/GPUTracking/dEdx/GPUdEdx.h index b3d2406171984..ac7a45db63101 100644 --- a/GPU/GPUTracking/dEdx/GPUdEdx.h +++ b/GPU/GPUTracking/dEdx/GPUdEdx.h @@ -19,7 +19,7 @@ #include "GPUCommonMath.h" #include "GPUParam.h" #include "GPUdEdxInfo.h" -#ifdef HAVE_O2HEADERS +#if defined(HAVE_O2HEADERS) && !defined(GPUCA_OPENCL1) #include "TPCdEdxCalibrationSplines.h" #endif @@ -27,7 +27,7 @@ namespace GPUCA_NAMESPACE { namespace gpu { -#ifndef HAVE_O2HEADERS +#if !defined(HAVE_O2HEADERS) || defined(GPUCA_OPENCL1) class GPUdEdx { @@ -156,7 +156,7 @@ GPUdi() void GPUdEdx::fillSubThreshold(int padRow, const GPUParam& GPUrestrict() mNSubThresh++; } -#endif // !HAVE_O2HEADERS +#endif // !HAVE_O2HEADERS || __OPENCL1__ } // namespace gpu } // namespace GPUCA_NAMESPACE From b5dc383151bc6e7c7404154b3ca32454c74cc4b5 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Thu, 7 Jan 2021 10:14:30 +0100 Subject: [PATCH 1723/1751] GPU: Disable CMake warnings already earlier --- dependencies/FindO2GPU.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 3a3d7c05aaa9e..3677bc9080249 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -163,12 +163,12 @@ if(ENABLE_HIP) if(EXISTS "${HIP_PATH}") get_filename_component(hip_ROOT "${HIP_PATH}" ABSOLUTE) + set(ROCM_WARN_TOOLCHAIN_VAR OFF CACHE BOOL "" FORCE) + set(ROCM_ERROR_TOOLCHAIN_VAR OFF CACHE BOOL "" FORCE) find_package(hip) find_package(hipcub) find_package(rocprim) find_package(rocthrust) - set(ROCM_WARN_TOOLCHAIN_VAR OFF CACHE BOOL "" FORCE) - set(ROCM_ERROR_TOOLCHAIN_VAR OFF CACHE BOOL "" FORCE) if(ENABLE_HIP STREQUAL "AUTO") set_package_properties(hip PROPERTIES TYPE OPTIONAL) set_package_properties(hipcub PROPERTIES TYPE OPTIONAL) From 4037cd782f84d7feb29d635a99f452a67a3f0541 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner <matthias.kleiner@cern.ch> Date: Wed, 6 Jan 2021 16:23:21 +0100 Subject: [PATCH 1724/1751] bugfix in SpaceCharge distortion class --- Detectors/TPC/spacecharge/src/SpaceCharge.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/spacecharge/src/SpaceCharge.cxx b/Detectors/TPC/spacecharge/src/SpaceCharge.cxx index dbe6f8af67120..9c881d28d327f 100644 --- a/Detectors/TPC/spacecharge/src/SpaceCharge.cxx +++ b/Detectors/TPC/spacecharge/src/SpaceCharge.cxx @@ -613,8 +613,8 @@ void SpaceCharge<DataT, Nz, Nr, Nphi>::fillChargeDensityFromHisto(const TH3& his for (size_t iPhi = 0; iPhi < Nphi; ++iPhi) { for (size_t iR = 0; iR < Nr; ++iR) { for (size_t iZ = 0; iZ < Nz; ++iZ) { - const size_t zBin = side == Side::A ? Nz + iZ + 1 : Nz - iZ; // TODO CHECK THIS! - mDensity[side](iZ, iR, iPhi) = hRebin.GetBinContent(iPhi, iR, zBin); + const size_t zBin = side == Side::A ? Nz + iZ + 1 : Nz - iZ; + mDensity[side](iZ, iR, iPhi) = hRebin.GetBinContent(iPhi + 1, iR + 1, zBin); } } } From 1668597cfd89f3c90121d188df30b57b801c3781 Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Sun, 10 Jan 2021 15:51:30 +0100 Subject: [PATCH 1725/1751] Fix: increment EMCAL TriggerRecord class version --- .../Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h index 336cf3b45071c..6f3c59dcf5f85 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h @@ -59,7 +59,7 @@ class TriggerRecord DataRange mDataRange; /// Index of the triggering event (event index and first entry in the container) uint32_t mTriggerBits; /// Trigger bits as from the Raw Data Header - ClassDefNV(TriggerRecord, 1); + ClassDefNV(TriggerRecord, 2); }; std::ostream& operator<<(std::ostream& stream, const TriggerRecord& trg); @@ -68,4 +68,4 @@ std::ostream& operator<<(std::ostream& stream, const TriggerRecord& trg); } // namespace o2 -#endif \ No newline at end of file +#endif From 9de7c3092939776748803905e4607f6a5fde4e20 Mon Sep 17 00:00:00 2001 From: Anton Alkin <anton.alkin@cern.ch> Date: Mon, 11 Jan 2021 09:05:41 +0100 Subject: [PATCH 1726/1751] Introduced 2d arrays in Variant (#5132) --- .../include/Analysis/configurableCut.h | 16 ++- Analysis/Tutorials/src/configurableCut.cxx | 31 +++-- .../Tutorials/src/configurableObjects.cxx | 35 ++++-- Framework/Core/include/Framework/Array2D.h | 112 +++++++++++++++++ .../include/Framework/ConfigParamRegistry.h | 27 +++- .../include/Framework/ConfigParamsHelper.h | 7 +- Framework/Core/include/Framework/Variant.h | 21 +++- Framework/Core/src/BoostOptionsRetriever.cxx | 5 +- Framework/Core/src/ConfigParamsHelper.cxx | 26 ++-- Framework/Core/src/DataProcessingDevice.cxx | 21 ---- Framework/Core/src/PropertyTreeHelpers.cxx | 115 +++++++++++++++--- Framework/Core/src/RootConfigParamHelpers.cxx | 92 ++++++++++---- Framework/Core/src/Variant.cxx | 35 +++++- Framework/Core/test/test_Variants.cxx | 75 ++++++++++-- 14 files changed, 501 insertions(+), 117 deletions(-) create mode 100644 Framework/Core/include/Framework/Array2D.h diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h index 446db71958217..55be646f6a8a6 100644 --- a/Analysis/Tutorials/include/Analysis/configurableCut.h +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -11,15 +11,21 @@ #ifndef CONFIGURABLECUT_H #define CONFIGURABLECUT_H +#include "Framework/Array2D.h" #include <iosfwd> #include <Rtypes.h> #include <TMath.h> +static constexpr double default_matrix[3][3] = {{1.1, 1.2, 1.3}, {2.1, 2.2, 2.3}, {3.1, 3.2, 3.3}}; + class configurableCut { public: - configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true, std::vector<float> bins_ = {0.5, 1.5, 2.5}, std::vector<std::string> labels_ = {"l1", "l2", "l3"}) - : cut{cut_}, state{state_}, option{option_}, bins{bins_}, labels{labels_} + configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true, + std::vector<float> bins_ = {0.5, 1.5, 2.5}, + std::vector<std::string> labels_ = {"l1", "l2", "l3"}, + o2::framework::Array2D<double> cuts_ = {&default_matrix[0][0], 3, 3}) + : cut{cut_}, state{state_}, option{option_}, bins{bins_}, labels{labels_}, cuts{cuts_} { } @@ -40,14 +46,18 @@ class configurableCut void setLabels(std::vector<std::string> labels_); std::vector<std::string> getLabels() const; + void setCuts(o2::framework::Array2D<double> cuts_); + o2::framework::Array2D<double> getCuts() const; + private: float cut; int state; bool option; std::vector<float> bins; std::vector<std::string> labels; + o2::framework::Array2D<double> cuts; - ClassDef(configurableCut, 4); + ClassDef(configurableCut, 5); }; std::ostream& operator<<(std::ostream& os, configurableCut const& c); diff --git a/Analysis/Tutorials/src/configurableCut.cxx b/Analysis/Tutorials/src/configurableCut.cxx index eac596e038de1..dc3b4b4fe928c 100644 --- a/Analysis/Tutorials/src/configurableCut.cxx +++ b/Analysis/Tutorials/src/configurableCut.cxx @@ -11,6 +11,12 @@ #include "Analysis/configurableCut.h" #include <iostream> +std::ostream& operator<<(std::ostream& os, configurableCut const& c) +{ + os << "Cut value: " << c.getCut() << "; state: " << c.getState(); + return os; +} + bool configurableCut::method(float arg) const { return arg > cut; @@ -26,12 +32,6 @@ float configurableCut::getCut() const return cut; } -std::ostream& operator<<(std::ostream& os, configurableCut const& c) -{ - os << "Cut value: " << c.getCut() << "; state: " << c.getState(); - return os; -} - void configurableCut::setState(int state_) { state = state_; @@ -54,19 +54,30 @@ bool configurableCut::getOption() const void configurableCut::setBins(std::vector<float> bins_) { - bins = bins_; -}; + bins = std::move(bins_); +} + std::vector<float> configurableCut::getBins() const { return bins; -}; +} void configurableCut::setLabels(std::vector<std::string> labels_) { - labels = labels_; + labels = std::move(labels_); } std::vector<std::string> configurableCut::getLabels() const { return labels; } + +void configurableCut::setCuts(o2::framework::Array2D<double> cuts_) +{ + cuts = std::move(cuts_); +} + +o2::framework::Array2D<double> configurableCut::getCuts() const +{ + return cuts; +} diff --git a/Analysis/Tutorials/src/configurableObjects.cxx b/Analysis/Tutorials/src/configurableObjects.cxx index bc99060e065d5..e28f71bb0713b 100644 --- a/Analysis/Tutorials/src/configurableObjects.cxx +++ b/Analysis/Tutorials/src/configurableObjects.cxx @@ -25,25 +25,41 @@ template <typename T> auto printArray(std::vector<T> const& vec) { std::stringstream ss; - ss << "["; - auto count = 0u; - for (auto& entry : vec) { - ss << entry; - if (count < vec.size() - 1) { - ss << ","; - } - ++count; + ss << "[" << vec[0]; + for (auto i = 1u; i < vec.size(); ++i) { + ss << ", " << vec[i]; } ss << "]"; return ss.str(); } +template <typename T> +auto printMatrix(Array2D<T> const& m) +{ + std::stringstream ss; + ss << "[[" << m(0, 0); + for (auto i = 1u; i < m.cols; ++i) { + ss << "," << m(0, i); + } + for (auto i = 1u; i < m.rows; ++i) { + ss << "], [" << m(i, 0); + for (auto j = 1u; j < m.cols; ++j) { + ss << "," << m(i, j); + } + } + ss << "]]"; + return ss.str(); +} + +static constexpr float defaultm[3][4] = {{1.1, 1.2, 1.3, 1.4}, {2.1, 2.2, 2.3, 2.4}, {3.1, 3.2, 3.3, 3.4}}; + struct ConfigurableObjectDemo { Configurable<configurableCut> cut{"cut", {0.5, 1, true}, "generic cut"}; MutableConfigurable<configurableCut> mutable_cut{"mutable_cut", {1., 2, false}, "generic cut"}; // note that size is fixed by this declaration - externally supplied vector needs to be the same size! Configurable<std::vector<int>> array{"array", {0, 0, 0, 0, 0, 0, 0}, "generic array"}; + Configurable<Array2D<float>> vmatrix{"matrix", {&defaultm[0][0], 3, 4}, "generic matrix"}; void init(InitContext const&){}; void process(aod::Collision const&, aod::Tracks const& tracks) @@ -53,7 +69,8 @@ struct ConfigurableObjectDemo { LOGF(INFO, "Cut1 labels: %s; Cut2 labels: %s", printArray(cut->getLabels()), printArray(mutable_cut->getLabels())); auto vec = (std::vector<int>)array; LOGF(INFO, "Array: %s", printArray(vec).c_str()); - for (auto& track : tracks) { + LOGF(INFO, "Matrix: %s", printMatrix((Array2D<float>)vmatrix)); + for (auto const& track : tracks) { if (track.globalIndex() % 500 == 0) { std::string decision1; std::string decision2; diff --git a/Framework/Core/include/Framework/Array2D.h b/Framework/Core/include/Framework/Array2D.h new file mode 100644 index 0000000000000..438818ce3aa51 --- /dev/null +++ b/Framework/Core/include/Framework/Array2D.h @@ -0,0 +1,112 @@ +// 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 FRAMEWORK_ARRAY2D_H +#define FRAMEWORK_ARRAY2D_H +#include <cstdint> +#include <vector> + +namespace o2::framework +{ +// matrix-like wrapper for std::vector +// has no range checks +template <typename T> +struct Array2D { + using element_t = T; + + Array2D(T const* data_, uint32_t r, uint32_t c) + : rows{r}, cols{c} + { + data = new T[rows * cols]; + for (auto i = 0U; i < rows; ++i) { + for (auto j = 0U; j < cols; ++j) { + data[i * cols + j] = *(data_ + (i * cols + j)); + } + } + } + Array2D(std::vector<T> data_, uint32_t r, uint32_t c) + : rows{r}, cols{c} + { + data = new T[rows * cols]; + for (auto i = 0U; i < rows; ++i) { + for (auto j = 0U; j < cols; ++j) { + data[i * cols + j] = data_[i * cols + j]; + } + } + } + + Array2D(Array2D<T> const& other) + : rows{other.rows}, + cols{other.cols} + { + data = new T[rows * cols]; + for (auto i = 0U; i < rows; ++i) { + for (auto j = 0U; j < cols; ++j) { + data[i * cols + j] = *(other.data + (i * cols + j)); + } + } + } + + Array2D(Array2D<T>&& other) + : rows{other.rows}, + cols{other.cols} + { + data = other.data; + other.data = nullptr; + other.rows = 0; + other.cols = 0; + } + + Array2D& operator=(Array2D<T> const& other) + { + this->rows = other.rows; + this->cols = other.cols; + data = new T[rows * cols]; + for (auto i = 0U; i < rows; ++i) { + for (auto j = 0U; j < cols; ++j) { + data[i * cols + j] = *(other.data + (i * cols + j)); + } + } + return *this; + } + + Array2D& operator=(Array2D<T>&& other) + { + this->rows = other.rows; + this->cols = other.cols; + data = other.data; + other.data = nullptr; + other.rows = 0; + other.cols = 0; + return *this; + } + + ~Array2D() + { + if (data != nullptr) { + delete[] data; + } + } + + T operator()(uint32_t y, uint32_t x) const + { + return data[y * cols + x]; + } + T* operator[](uint32_t y) const + { + return data + y * cols; + } + + T* data = nullptr; + uint32_t rows = 0; + uint32_t cols = 0; +}; +} // namespace o2::framework + +#endif // FRAMEWORK_ARRAY2D_H diff --git a/Framework/Core/include/Framework/ConfigParamRegistry.h b/Framework/Core/include/Framework/ConfigParamRegistry.h index 8cfa0ee864028..9f75b51172730 100644 --- a/Framework/Core/include/Framework/ConfigParamRegistry.h +++ b/Framework/Core/include/Framework/ConfigParamRegistry.h @@ -25,7 +25,7 @@ namespace o2::framework namespace { template <typename T> -std::vector<T> extractVector(boost::property_tree::ptree& tree) +std::vector<T> extractVector(boost::property_tree::ptree const& tree) { std::vector<T> result(tree.size()); auto count = 0u; @@ -34,6 +34,29 @@ std::vector<T> extractVector(boost::property_tree::ptree& tree) } return result; } + +template <typename T> +o2::framework::Array2D<T> extractMatrix(boost::property_tree::ptree const& tree) +{ + std::vector<T> cache; + uint32_t nrows = tree.size(); + uint32_t ncols = 0; + bool first = true; + auto irow = 0u; + for (auto& row : tree) { + if (first) { + ncols = row.second.size(); + first = false; + } + auto icol = 0u; + for (auto& entry : row.second) { + cache.push_back(entry.second.get_value<T>()); + ++icol; + } + ++irow; + } + return o2::framework::Array2D<T>{cache, nrows, ncols}; +} } // namespace class ConfigParamStore; @@ -80,6 +103,8 @@ class ConfigParamRegistry return std::string_view{mStore->store().get<std::string>(key)}; } else if constexpr (is_base_of_template<std::vector, T>::value) { return extractVector<typename T::value_type>(mStore->store().get_child(key)); + } else if constexpr (is_base_of_template<o2::framework::Array2D, T>::value) { + return extractMatrix<typename T::element_t>(mStore->store().get_child(key)); } else if constexpr (std::is_same_v<T, boost::property_tree::ptree>) { return mStore->store().get_child(key); } else if constexpr (std::is_constructible_v<T, boost::property_tree::ptree>) { diff --git a/Framework/Core/include/Framework/ConfigParamsHelper.h b/Framework/Core/include/Framework/ConfigParamsHelper.h index 02b9c9a56a4c3..36c5463e0857e 100644 --- a/Framework/Core/include/Framework/ConfigParamsHelper.h +++ b/Framework/Core/include/Framework/ConfigParamsHelper.h @@ -34,7 +34,7 @@ struct ConfigParamsHelper { /// all options which are found in the vetos are skipped static bool dpl2BoostOptions(const std::vector<ConfigParamSpec>& spec, options_description& options, - options_description vetos = options_description()); + boost::program_options::options_description vetos = options_description()); /// populate boost program options for a complete workflow template <typename ContainerType> @@ -119,7 +119,10 @@ struct ConfigParamsHelper { V == VariantType::ArrayFloat || V == VariantType::ArrayDouble || V == VariantType::ArrayBool || - V == VariantType::ArrayString) { + V == VariantType::ArrayString || + V == VariantType::MatrixInt || + V == VariantType::MatrixFloat || + V == VariantType::MatrixDouble) { auto value = boost::program_options::value<std::string>(); value = value->default_value(spec.defaultValue.asString()); if constexpr (V != VariantType::String) { diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index 20f711987d505..4fba20c8a4f70 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -11,6 +11,7 @@ #define FRAMEWORK_VARIANT_H #include "Framework/RuntimeError.h" +#include "Framework/Array2D.h" #include <type_traits> #include <cstring> #include <cstdint> @@ -21,9 +22,7 @@ #include <vector> #include <string> -namespace o2 -{ -namespace framework +namespace o2::framework { enum class VariantType : int { Int = 0, @@ -37,6 +36,9 @@ enum class VariantType : int { Int = 0, ArrayDouble, ArrayBool, ArrayString, + MatrixInt, + MatrixFloat, + MatrixDouble, Empty, Unknown }; @@ -75,6 +77,10 @@ DECLARE_VARIANT_TRAIT(std::vector<double>, ArrayDouble); DECLARE_VARIANT_TRAIT(std::vector<bool>, ArrayBool); DECLARE_VARIANT_TRAIT(std::vector<std::string>, ArrayString); +DECLARE_VARIANT_TRAIT(Array2D<int>, MatrixInt); +DECLARE_VARIANT_TRAIT(Array2D<float>, MatrixFloat); +DECLARE_VARIANT_TRAIT(Array2D<double>, MatrixDouble); + template <typename T> struct variant_array_symbol { constexpr static char symbol = 'u'; @@ -131,6 +137,10 @@ DECLARE_VARIANT_TYPE(double*, ArrayDouble); DECLARE_VARIANT_TYPE(bool*, ArrayBool); DECLARE_VARIANT_TYPE(std::string*, ArrayString); +DECLARE_VARIANT_TYPE(Array2D<int>, MatrixInt); +DECLARE_VARIANT_TYPE(Array2D<float>, MatrixFloat); +DECLARE_VARIANT_TYPE(Array2D<double>, MatrixDouble); + template <typename S, typename T> struct variant_helper { static void set(S* store, T value) { *(reinterpret_cast<T*>(store)) = value; } @@ -170,7 +180,7 @@ struct variant_helper<S, std::string> { /// Variant for configuration parameter storage. Owns stored data. class Variant { - using storage_t = std::aligned_union<8, int, int64_t, const char*, float, double, bool, int*, float*, double*, bool*>::type; + using storage_t = std::aligned_union<8, int, int64_t, const char*, float, double, bool, int*, float*, double*, bool*, Array2D<int>, Array2D<float>, Array2D<double>>::type; public: Variant(VariantType type = VariantType::Unknown) : mType{type}, mSize{1} {} @@ -355,7 +365,6 @@ class Variant size_t mSize = 1; }; -} // namespace framework -} // namespace o2 +} // namespace o2::framework #endif diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index efe4f85e933fe..8a8da9cb68202 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -41,7 +41,7 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> const& specs, boost::property_tree::ptree& provenance) { auto options = mDescription->add_options(); - for (auto& spec : specs) { + for (const auto& spec : specs) { const char* name = spec.name.c_str(); const char* help = spec.help.c_str(); // FIXME: propagate default value? @@ -69,6 +69,9 @@ void BoostOptionsRetriever::update(std::vector<ConfigParamSpec> const& specs, case VariantType::ArrayDouble: case VariantType::ArrayBool: case VariantType::ArrayString: + case VariantType::MatrixInt: + case VariantType::MatrixFloat: + case VariantType::MatrixDouble: options = options(name, bpo::value<std::string>()->default_value(spec.defaultValue.asString()), help); break; case VariantType::Unknown: diff --git a/Framework/Core/src/ConfigParamsHelper.cxx b/Framework/Core/src/ConfigParamsHelper.cxx index a6c29c35e5f9f..690ee53d11284 100644 --- a/Framework/Core/src/ConfigParamsHelper.cxx +++ b/Framework/Core/src/ConfigParamsHelper.cxx @@ -17,9 +17,7 @@ namespace bpo = boost::program_options; -namespace o2 -{ -namespace framework +namespace o2::framework { /// this creates the boost program options description from the ConfigParamSpec @@ -30,9 +28,9 @@ void ConfigParamsHelper::populateBoostProgramOptions( bpo::options_description vetos) { auto proxy = options.add_options(); - for (auto& spec : specs) { + for (auto const& spec : specs) { // skip everything found in the veto definition - if (vetos.find_nothrow(spec.name, false)) { + if (vetos.find_nothrow(spec.name, false) != nullptr) { continue; } @@ -72,6 +70,15 @@ void ConfigParamsHelper::populateBoostProgramOptions( case VariantType::ArrayString: addConfigSpecOption<VariantType::ArrayString>(spec, options); break; + case VariantType::MatrixInt: + addConfigSpecOption<VariantType::MatrixInt>(spec, options); + break; + case VariantType::MatrixFloat: + addConfigSpecOption<VariantType::MatrixFloat>(spec, options); + break; + case VariantType::MatrixDouble: + addConfigSpecOption<VariantType::MatrixDouble>(spec, options); + break; case VariantType::Unknown: case VariantType::Empty: break; @@ -89,11 +96,11 @@ bool ConfigParamsHelper::dpl2BoostOptions(const std::vector<ConfigParamSpec>& sp for (const auto& configSpec : spec) { // skip everything found in the veto definition try { - if (vetos.find_nothrow(configSpec.name, false)) { + if (vetos.find_nothrow(configSpec.name, false) != nullptr) { continue; } } catch (boost::program_options::ambiguous_option& e) { - for (auto& alternative : e.alternatives()) { + for (auto const& alternative : e.alternatives()) { std::cerr << alternative << std::endl; } throw; @@ -105,7 +112,7 @@ bool ConfigParamsHelper::dpl2BoostOptions(const std::vector<ConfigParamSpec>& sp if (configSpec.type != VariantType::Bool) { if (configSpec.defaultValue.type() != VariantType::Empty) { options.add_options()(configSpec.name.c_str(), - bpo::value<std::string>()->default_value(defaultValue.str().c_str()), + bpo::value<std::string>()->default_value(defaultValue.str()), configSpec.help.c_str()); } else { options.add_options()(configSpec.name.c_str(), @@ -128,5 +135,4 @@ bool ConfigParamsHelper::dpl2BoostOptions(const std::vector<ConfigParamSpec>& sp return haveOption; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 9d4c12b0032b1..04cebf5d94b4a 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -177,27 +177,6 @@ void on_socket_polled(uv_poll_t* poller, int status, int events) // We do nothing, all the logic for now stays in DataProcessingDevice::doRun() } -namespace -{ -template <typename T> -std::string arrayPrinter(boost::property_tree::ptree const& tree) -{ - std::stringstream ss; - int size = tree.size(); - int count = 0; - ss << variant_array_symbol<T>::symbol << "["; - for (auto& element : tree) { - ss << element.second.get_value<T>(); - if (count < size - 1) { - ss << ","; - } - ++count; - } - ss << "]"; - return ss.str(); -} -} // namespace - /// This takes care of initialising the device from its specification. In /// particular it needs to: /// diff --git a/Framework/Core/src/PropertyTreeHelpers.cxx b/Framework/Core/src/PropertyTreeHelpers.cxx index 0860744dd55dd..8c90458c31fa4 100644 --- a/Framework/Core/src/PropertyTreeHelpers.cxx +++ b/Framework/Core/src/PropertyTreeHelpers.cxx @@ -27,7 +27,7 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s boost::property_tree::ptree& pt, boost::property_tree::ptree& provenance) { - auto addBranch = [&](std::string key, auto* values, size_t size) { + auto addBranch = [&](std::string const& key, auto* values, size_t size) { boost::property_tree::ptree branch; for (auto i = 0u; i < size; ++i) { boost::property_tree::ptree leaf; @@ -37,8 +37,22 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s pt.put_child(key, branch); }; - for (auto& spec : schema) { - std::string key = spec.name.substr(0, spec.name.find(",")); + auto addSubTree = [&](std::string const& key, auto const& m) { + boost::property_tree::ptree subtree; + for (auto i = 0u; i < m.rows; ++i) { + boost::property_tree::ptree branch; + for (auto j = 0u; j < m.cols; ++j) { + boost::property_tree::ptree leaf; + leaf.put("", m(i, j)); + branch.push_back(std::make_pair("", leaf)); + } + subtree.push_back(std::make_pair("", branch)); + } + pt.put_child(key, subtree); + }; + + for (auto const& spec : schema) { + std::string key = spec.name.substr(0, spec.name.find(',')); try { if (spec.defaultValue.type() == VariantType::Empty) { continue; @@ -77,6 +91,15 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s case VariantType::ArrayString: addBranch(key, spec.defaultValue.get<std::string*>(), spec.defaultValue.size()); break; + case VariantType::MatrixInt: + addSubTree(key, spec.defaultValue.get<Array2D<int>>()); + break; + case VariantType::MatrixFloat: + addSubTree(key, spec.defaultValue.get<Array2D<float>>()); + break; + case VariantType::MatrixDouble: + addSubTree(key, spec.defaultValue.get<Array2D<double>>()); + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -84,7 +107,7 @@ void PropertyTreeHelpers::populateDefaults(std::vector<ConfigParamSpec> const& s } provenance.put(key, "default"); } catch (std::runtime_error& re) { - throw re; + throw; } catch (std::exception& e) { throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")"); } catch (...) { @@ -101,10 +124,10 @@ std::vector<T> toVector(std::string const& input) std::vector<T> result; //check if the array string has correct array type symbol assert(input[0] == variant_array_symbol<T>::symbol); - std::regex nmatch(R"((?:(?!=,)|(?!=\[))[+-]?\d+\.?\d*(?:[eE][+-]?\d+)?(?=,|\]))", std::regex_constants::ECMAScript); + std::regex nmatch(R"((?:(?!=,)|(?!=\[))[+-]?\d+\.?\d*(?:[eE][+-]?\d+)?(?=,|\]))"); auto end = std::sregex_iterator(); auto values = std::sregex_iterator(input.begin(), input.end(), nmatch); - for (auto v = values; v != end; ++v) { + for (auto& v = values; v != end; ++v) { result.push_back(boost::lexical_cast<T>(v->str())); } return result; @@ -124,6 +147,38 @@ std::vector<std::string> toVector(std::string const& input) } return result; } + +template <typename T> +Array2D<T> toMatrix(std::string const& input) +{ + std::vector<T> cache; + assert(input[0] == variant_array_symbol<T>::symbol); + std::regex mrows(R"(\[[^\[\]]+\])"); + std::regex marray(R"((?:(?!=,)|(?!=\[))[+-]?\d+\.?\d*(?:[eE][+-]?\d+)?(?=,|\]))"); + auto end = std::sregex_iterator(); + auto rows = std::sregex_iterator(input.begin(), input.end(), mrows); + uint32_t nrows = 0; + uint32_t ncols = 0; + bool first = true; + for (auto& row = rows; row != end; ++row) { + auto str = row->str(); + auto values = std::sregex_iterator(str.begin(), str.end(), marray); + if (first) { + ncols = 0; + } + for (auto& v = values; v != end; ++v) { + cache.push_back(boost::lexical_cast<T>(v->str())); + if (first) { + ++ncols; + } + } + if (first) { + first = false; + } + ++nrows; + } + return Array2D<T>{cache, nrows, ncols}; +} } // namespace void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, @@ -131,7 +186,7 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, boost::program_options::variables_map const& vmap, boost::property_tree::ptree& provenance) { - auto addBranch = [&](std::string key, auto vector) { + auto addBranch = [&](std::string const& key, auto vector) { boost::property_tree::ptree branch; for (auto i = 0u; i < vector.size(); ++i) { boost::property_tree::ptree leaf; @@ -141,9 +196,23 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, pt.put_child(key, branch); }; - for (auto& spec : schema) { + auto addSubTree = [&](std::string const& key, auto m) { + boost::property_tree::ptree subtree; + for (auto i = 0u; i < m.rows; ++i) { + boost::property_tree::ptree branch; + for (auto j = 0u; j < m.cols; ++j) { + boost::property_tree::ptree leaf; + leaf.put("", m(i, j)); + branch.push_back(std::make_pair("", leaf)); + } + subtree.push_back(std::make_pair("", branch)); + } + pt.put_child(key, subtree); + }; + + for (auto const& spec : schema) { // strip short version to get the correct key - std::string key = spec.name.substr(0, spec.name.find(",")); + std::string key = spec.name.substr(0, spec.name.find(',')); if (vmap.count(key) == 0) { continue; } @@ -162,7 +231,7 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, pt.put(key, vmap[key].as<double>()); break; case VariantType::String: - if (auto v = boost::any_cast<std::string>(&vmap[key].value())) { + if (auto const* v = boost::any_cast<std::string>(&vmap[key].value())) { pt.put(key, *v); } break; @@ -194,6 +263,21 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, addBranch(key, v); }; break; + case VariantType::MatrixInt: { + auto m = toMatrix<int>(vmap[key].as<std::string>()); + addSubTree(key, m); + }; + break; + case VariantType::MatrixFloat: { + auto m = toMatrix<float>(vmap[key].as<std::string>()); + addSubTree(key, m); + }; + break; + case VariantType::MatrixDouble: { + auto m = toMatrix<double>(vmap[key].as<std::string>()); + addSubTree(key, m); + }; + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -201,7 +285,7 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, } provenance.put(key, "fairmq"); } catch (std::runtime_error& re) { - throw re; + throw; } catch (std::exception& e) { throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")"); } catch (...) { @@ -216,9 +300,9 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, boost::property_tree::ptree& provenance, std::string const& provenanceLabel) { - for (auto& spec : schema) { + for (auto const& spec : schema) { // strip short version to get the correct key - std::string key = spec.name.substr(0, spec.name.find(",")); + std::string key = spec.name.substr(0, spec.name.find(',')); auto it = in.get_child_optional(key); if (!it) { continue; @@ -248,6 +332,9 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, case VariantType::ArrayDouble: case VariantType::ArrayBool: case VariantType::ArrayString: + case VariantType::MatrixInt: + case VariantType::MatrixFloat: + case VariantType::MatrixDouble: pt.put_child(key, *it); break; case VariantType::Unknown: @@ -257,7 +344,7 @@ void PropertyTreeHelpers::populate(std::vector<ConfigParamSpec> const& schema, } provenance.put(key, provenanceLabel); } catch (std::runtime_error& re) { - throw re; + throw; } catch (std::exception& e) { throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")"); } catch (...) { diff --git a/Framework/Core/src/RootConfigParamHelpers.cxx b/Framework/Core/src/RootConfigParamHelpers.cxx index c73c594782c2b..20fc32e88ffd8 100644 --- a/Framework/Core/src/RootConfigParamHelpers.cxx +++ b/Framework/Core/src/RootConfigParamHelpers.cxx @@ -38,12 +38,16 @@ bool isString(TDataMember const& dm) void loopOverMembers(TClass* cl, void* obj, std::function<void(TDataMember*, int, int)>&& callback) { - auto memberlist = cl->GetListOfDataMembers(); + auto* memberlist = cl->GetListOfDataMembers(); for (int i = 0; i < memberlist->GetEntries(); ++i) { - auto dm = (TDataMember*)memberlist->At(i); + auto* dm = (TDataMember*)memberlist->At(i); auto isValidComplex = [dm]() { - return isString(*dm) || dm->IsEnum() || dm->IsSTLContainer(); + auto typehash = compile_time_hash(dm->GetTypeName()); + return isString(*dm) || dm->IsEnum() || dm->IsSTLContainer() || + (typehash == compile_time_hash("o2::framework::Array2D<int>")) || + (typehash == compile_time_hash("o2::framework::Array2D<float>")) || + (typehash == compile_time_hash("o2::framework::Array2D<double>")); }; // filter out static members for now @@ -77,12 +81,35 @@ template <typename T> std::vector<T> extractVector(boost::property_tree::ptree const& tree) { std::vector<T> result(tree.size()); - auto count = 0u; - for (auto& entry : tree) { + auto count = 0U; + for (auto const& entry : tree) { result[count++] = entry.second.get_value<T>(); } return result; } + +template <typename T> +Array2D<T> extractMatrix(boost::property_tree::ptree const& tree) +{ + std::vector<T> cache; + uint32_t nrows = tree.size(); + uint32_t ncols = 0; + bool first = true; + auto irow = 0u; + for (auto const& row : tree) { + if (first) { + ncols = row.second.size(); + first = false; + } + auto icol = 0u; + for (auto const& entry : row.second) { + cache.push_back(entry.second.get_value<T>()); + ++icol; + } + ++irow; + } + return Array2D<T>{cache, nrows, ncols}; +} } // namespace // construct name (in dependence on vector or scalar data and index) @@ -101,10 +128,9 @@ void ptreeToMember(boost::property_tree::ptree const& value, TDataMember* dm, void* ptr) { - + auto typehash = compile_time_hash(dm->GetTypeName()); if (dm->IsSTLContainer()) { - auto type = dm->GetTypeName(); - switch (compile_time_hash(type)) { + switch (typehash) { case compile_time_hash("vector<int>"): *static_cast<std::vector<int>*>(ptr) = extractVector<int>(value); return; @@ -123,8 +149,20 @@ void ptreeToMember(boost::property_tree::ptree const& value, default: throw std::runtime_error("Not an int/float/double/bool vector"); } + } else { + switch (typehash) { + case compile_time_hash("o2::framework::Array2D<int>"): + *static_cast<Array2D<int>*>(ptr) = extractMatrix<int>(value); + return; + case compile_time_hash("o2::framework::Array2D<float>"): + *static_cast<Array2D<float>*>(ptr) = extractMatrix<float>(value); + return; + case compile_time_hash("o2::framework::Array2D<double>"): + *static_cast<Array2D<double>*>(ptr) = extractMatrix<double>(value); + return; + } } - auto dt = dm->GetDataType(); + auto* dt = dm->GetDataType(); if (dt != nullptr) { switch (dt->GetType()) { case kChar_t: { @@ -163,10 +201,7 @@ void ptreeToMember(boost::property_tree::ptree const& value, *(float*)ptr = value.get_value<float>(); return; } - case kDouble_t: { - *(double*)ptr = value.get_value<double>(); - return; - } + case kDouble_t: case kDouble32_t: { *(double*)ptr = value.get_value<double>(); return; @@ -189,7 +224,7 @@ void ptreeToMember(boost::property_tree::ptree const& value, } } // if we get here none of the above worked - if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { + if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string") == 0) { *(std::string*)ptr = value.get_value<std::string>(); } throw std::runtime_error("Unable to override value"); @@ -198,9 +233,9 @@ void ptreeToMember(boost::property_tree::ptree const& value, // Convert a DataMember to a ConfigParamSpec ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void* ptr) { + auto typehash = compile_time_hash(dm->GetTypeName()); if (dm->IsSTLContainer()) { - auto type = dm->GetTypeName(); - switch (compile_time_hash(type)) { + switch (typehash) { case compile_time_hash("vector<int>"): return ConfigParamSpec{tname, VariantType::ArrayInt, *static_cast<std::vector<int>*>(ptr), {"No help"}}; case compile_time_hash("vector<float>"): @@ -216,8 +251,17 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void default: throw std::runtime_error("Not an int/float/double/bool vector"); } + } else { + switch (typehash) { + case compile_time_hash("o2::framework::Array2D<int>"): + return ConfigParamSpec{tname, VariantType::MatrixInt, *static_cast<Array2D<int>*>(ptr), {"No help"}}; + case compile_time_hash("o2::framework::Array2D<float>"): + return ConfigParamSpec{tname, VariantType::MatrixFloat, *static_cast<Array2D<float>*>(ptr), {"No help"}}; + case compile_time_hash("o2::framework::Array2D<double>"): + return ConfigParamSpec{tname, VariantType::MatrixDouble, *static_cast<Array2D<double>*>(ptr), {"No help"}}; + } } - auto dt = dm->GetDataType(); + auto* dt = dm->GetDataType(); if (dt != nullptr) { switch (dt->GetType()) { case kChar_t: { @@ -247,9 +291,7 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void case kFloat_t: { return ConfigParamSpec{tname, VariantType::Float, *(float*)ptr, {"No help"}}; } - case kDouble_t: { - return ConfigParamSpec{tname, VariantType::Double, *(double*)ptr, {"No help"}}; - } + case kDouble_t: case kDouble32_t: { return ConfigParamSpec{tname, VariantType::Double, *(double*)ptr, {"No help"}}; } @@ -268,7 +310,7 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void } } // if we get here none of the above worked - if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) { + if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string") == 0) { return ConfigParamSpec{tname, VariantType::String, *(std::string*)ptr, {"No help"}}; } throw std::runtime_error("Cannot use " + std::string(tname)); @@ -284,8 +326,8 @@ std::vector<ConfigParamSpec> std::vector<ConfigParamSpec> specs; auto toDataMember = [&mainKey, &specs, obj](TDataMember* dm, int index, int size) { - auto dt = dm->GetDataType(); - auto TS = dt ? dt->Size() : 0; + auto* dt = dm->GetDataType(); + auto TS = dt != nullptr ? dt->Size() : 0; char* ptr = ((char*)obj) + dm->GetOffset() + index * TS; const std::string name = mainKey + "." + getName(dm, index, size); @@ -301,8 +343,8 @@ std::vector<ConfigParamSpec> void RootConfigParamHelpers::fillFromPtree(TClass* cl, void* obj, boost::property_tree::ptree const& pt) { auto toDataMember = [obj, &pt](TDataMember* dm, int index, int size) { - auto dt = dm->GetDataType(); - auto TS = dt ? dt->Size() : 0; + auto* dt = dm->GetDataType(); + auto TS = dt != nullptr ? dt->Size() : 0; char* ptr = ((char*)obj) + dm->GetOffset() + index * TS; const std::string name = getName(dm, index, size); auto it = pt.get_child_optional(name); diff --git a/Framework/Core/src/Variant.cxx b/Framework/Core/src/Variant.cxx index 5f9c60217ffb0..20a650327b41d 100644 --- a/Framework/Core/src/Variant.cxx +++ b/Framework/Core/src/Variant.cxx @@ -20,11 +20,29 @@ template <typename T> void printArray(std::ostream& oss, T* array, size_t size) { oss << variant_array_symbol<T>::symbol << "["; - for (auto i = 0u; i < size; ++i) { - oss << array[i]; - if (i < size - 1) { - oss << ","; + oss << array[0]; + for (auto i = 1U; i < size; ++i) { + oss << ", " << array[i]; + } + oss << "]"; +} + +template <typename T> +void printMatrix(std::ostream& oss, Array2D<T> m) +{ + oss << variant_array_symbol<T>::symbol << "[["; + oss << m(0, 0); + for (auto j = 1U; j < m.cols; ++j) { + oss << ", " << m(0, j); + } + oss << "]"; + for (auto i = 1U; i < m.rows; ++i) { + oss << ", ["; + oss << m(i, 0); + for (auto j = 1U; j < m.cols; ++j) { + oss << ", " << m(i, j); } + oss << "]"; } oss << "]"; } @@ -66,6 +84,15 @@ std::ostream& operator<<(std::ostream& oss, Variant const& val) case VariantType::ArrayString: printArray<std::string>(oss, val.get<std::string*>(), val.size()); break; + case VariantType::MatrixInt: + printMatrix<int>(oss, val.get<Array2D<int>>()); + break; + case VariantType::MatrixFloat: + printMatrix<float>(oss, val.get<Array2D<float>>()); + break; + case VariantType::MatrixDouble: + printMatrix<double>(oss, val.get<Array2D<double>>()); + break; case VariantType::Empty: break; default: diff --git a/Framework/Core/test/test_Variants.cxx b/Framework/Core/test/test_Variants.cxx index 11a42487c759b..b2a85045c5e10 100644 --- a/Framework/Core/test/test_Variants.cxx +++ b/Framework/Core/test/test_Variants.cxx @@ -20,10 +20,34 @@ using namespace o2::framework; bool unknown_type(RuntimeErrorRef const& ref) { - auto& err = error_from_ref(ref); + auto const& err = error_from_ref(ref); return strcmp(err.what, "Mismatch between types") == 0; } +BOOST_AUTO_TEST_CASE(MatrixTest) +{ + float m[3][4] = {{0.1, 0.2, 0.3, 0.4}, {0.5, 0.6, 0.7, 0.8}, {0.9, 1.0, 1.1, 1.2}}; + Array2D mm(&m[0][0], 3, 4); + for (auto i = 0U; i < 3; ++i) { + for (auto j = 0U; j < 4; ++j) { + BOOST_CHECK(mm(i, j) == m[i][j]); + } + } + std::vector<float> v = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2}; + Array2D mv(v, 3, 4); + for (auto i = 0U; i < 3; ++i) { + for (auto j = 0U; j < 4; ++j) { + BOOST_CHECK(mm(i, j) == v[i * 4 + j]); + } + } + for (auto i = 0U; i < 3; ++i) { + auto const& vv = mm[i]; + for (auto j = 0u; j < 4; ++j) { + BOOST_CHECK(vv[j] == mm(i, j)); + } + } +} + BOOST_AUTO_TEST_CASE(VariantTest) { std::ostringstream ss{}; @@ -71,19 +95,19 @@ BOOST_AUTO_TEST_CASE(VariantTest) BOOST_CHECK(viarr.size() == 5); BOOST_CHECK(viarr.get<int*>() != iarr); - for (auto i = 0u; i < viarr.size(); ++i) { + for (auto i = 0U; i < viarr.size(); ++i) { BOOST_CHECK(iarr[i] == (viarr.get<int*>())[i]); } BOOST_CHECK(vfarr.size() == 6); BOOST_CHECK(vfarr.get<float*>() != farr); - for (auto i = 0u; i < vfarr.size(); ++i) { + for (auto i = 0U; i < vfarr.size(); ++i) { BOOST_CHECK(farr[i] == (vfarr.get<float*>())[i]); } BOOST_CHECK(vdvec.size() == dvec.size()); BOOST_CHECK(vdvec.get<double*>() != dvec.data()); - for (auto i = 0u; i < dvec.size(); ++i) { + for (auto i = 0U; i < dvec.size(); ++i) { BOOST_CHECK(dvec[i] == (vdvec.get<double*>())[i]); } @@ -94,15 +118,15 @@ BOOST_AUTO_TEST_CASE(VariantTest) BOOST_CHECK(vfarr.get<float*>() == nullptr); BOOST_CHECK(fb.get<float*>() != farr); - for (auto i = 0u; i < fb.size(); ++i) { + for (auto i = 0U; i < fb.size(); ++i) { BOOST_CHECK(farr[i] == (fb.get<float*>())[i]); } BOOST_CHECK(fc.get<float*>() != farr); - for (auto i = 0u; i < fc.size(); ++i) { + for (auto i = 0U; i < fc.size(); ++i) { BOOST_CHECK(farr[i] == (fc.get<float*>())[i]); } BOOST_CHECK(fd.get<float*>() != farr); - for (auto i = 0u; i < fd.size(); ++i) { + for (auto i = 0U; i < fd.size(); ++i) { BOOST_CHECK(farr[i] == (fd.get<float*>())[i]); } @@ -113,20 +137,49 @@ BOOST_AUTO_TEST_CASE(VariantTest) BOOST_CHECK(vstr.size() == 3); BOOST_CHECK(vvstr.size() == 3); - for (auto i = 0u; i < vstr.size(); ++i) { + for (auto i = 0U; i < vstr.size(); ++i) { BOOST_CHECK(strings[i] == (vstr.get<std::string*>())[i]); } - for (auto i = 0u; i < vvstr.size(); ++i) { + for (auto i = 0U; i < vvstr.size(); ++i) { BOOST_CHECK(vstrings[i] == (vvstr.get<std::string*>())[i]); } Variant vsc(vstr); // Copy constructor Variant vsm(std::move(vstr)); // Move constructor Variant vscc = vsm; // Copy assignment - for (auto i = 0u; i < vsm.size(); ++i) { + for (auto i = 0U; i < vsm.size(); ++i) { BOOST_CHECK(strings[i] == (vsm.get<std::string*>())[i]); } - for (auto i = 0u; i < vscc.size(); ++i) { + for (auto i = 0U; i < vscc.size(); ++i) { BOOST_CHECK(strings[i] == (vscc.get<std::string*>())[i]); } + + float m[3][4] = {{0.1, 0.2, 0.3, 0.4}, {0.5, 0.6, 0.7, 0.8}, {0.9, 1.0, 1.1, 1.2}}; + Array2D mm(&m[0][0], 3, 4); + Variant vmm(mm); + auto const& mmc = vmm.get<Array2D<float>>(); + for (auto i = 0U; i < 3; ++i) { + for (auto j = 0U; j < 4; ++j) { + BOOST_CHECK(mmc(i, j) == mm(i, j)); + } + } + + Variant vmmc(vmm); // Copy constructor + Variant vmmm(std::move(vmm)); // Move constructor + Variant vmma = vmmm; // Copy assignment + auto const& mmc2 = vmmc.get<Array2D<float>>(); + for (auto i = 0U; i < 3; ++i) { + for (auto j = 0U; j < 4; ++j) { + BOOST_CHECK(mmc2(i, j) == mm(i, j)); + } + } + auto const& mmc3 = vmma.get<Array2D<float>>(); + for (auto i = 0U; i < 3; ++i) { + for (auto j = 0U; j < 4; ++j) { + BOOST_CHECK(mmc3(i, j) == mm(i, j)); + } + } + std::stringstream ssm; + ssm << vmma; + BOOST_CHECK(ssm.str() == "f[[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8], [0.9, 1, 1.1, 1.2]]"); } From ee1014a9bbeb2941ec73266c84d762b09aa14dc3 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 9 Jan 2021 22:34:03 +0100 Subject: [PATCH 1727/1751] GPU: Do not crash processing MC labels when events are only dumped but not processed --- Detectors/TPC/reconstruction/src/GPUCATracking.cxx | 9 +++++---- GPU/GPUTracking/Interface/GPUO2Interface.cxx | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx index c1b2bfc62ec83..c764e68674db9 100644 --- a/Detectors/TPC/reconstruction/src/GPUCATracking.cxx +++ b/Detectors/TPC/reconstruction/src/GPUCATracking.cxx @@ -150,14 +150,15 @@ int GPUCATracking::runTracking(GPUO2InterfaceIOPtrs* data, GPUInterfaceOutputs* data->clusters = ptrs.clustersNative; } data->compressedClusters = ptrs.tpcCompressedClusters; - const GPUTPCGMMergedTrack* tracks = ptrs.mergedTracks; - int nTracks = ptrs.nMergedTracks; - const GPUTPCGMMergedTrackHit* trackClusters = ptrs.mergedTrackHits; - if (retVal) { + if (retVal || mTrackingCAO2Interface->getConfig().configInterface.dumpEvents >= 2) { return retVal; } + const GPUTPCGMMergedTrack* tracks = ptrs.mergedTracks; + int nTracks = ptrs.nMergedTracks; + const GPUTPCGMMergedTrackHit* trackClusters = ptrs.mergedTrackHits; + std::vector<std::pair<int, float>> trackSort(nTracks); int tmp = 0, tmp2 = 0; uint32_t clBuff = 0; diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index 40ea66aa7157e..67005037a4b44 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -99,8 +99,8 @@ int GPUTPCO2Interface::RunTracking(GPUTrackingInOutPointers* data, GPUInterfaceO if (!mInitialized) { return (1); } - static int nEvent = 0; if (mConfig->configInterface.dumpEvents) { + static int nEvent = 0; mChain->ClearIOPointers(); mChain->mIOPtrs.clustersNative = data->clustersNative; mChain->mIOPtrs.tpcPackedDigits = data->tpcPackedDigits; @@ -112,6 +112,7 @@ int GPUTPCO2Interface::RunTracking(GPUTrackingInOutPointers* data, GPUInterfaceO if (nEvent == 0) { mRec->DumpSettings(); } + nEvent++; if (mConfig->configInterface.dumpEvents >= 2) { return 0; } @@ -168,7 +169,6 @@ int GPUTPCO2Interface::RunTracking(GPUTrackingInOutPointers* data, GPUInterfaceO } *data = mChain->mIOPtrs; - nEvent++; return 0; } From 729880bc4db194e958fd9f8f39c49932c40589bf Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Sat, 9 Jan 2021 22:34:28 +0100 Subject: [PATCH 1728/1751] GPU: Fix computation of number of OMP threads to use --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 2 ++ GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index 86833d421a0a8..e3d7795fc6b0e 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -302,6 +302,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config if (processAttributes->readyToQuit) { return; } + printf("RUN PROCESSING\n"); auto cput = timer.CpuTime(); timer.Start(false); auto& parser = processAttributes->parser; @@ -633,6 +634,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config outputRegions.clusterLabels.allocator = [&clustersMCBuffer](size_t size) -> void* { return &clustersMCBuffer; }; } + printf("RUN TRACKING\n"); int retVal = tracker->runTracking(&ptrs, &outputRegions); if (processAttributes->suppressOutput) { return; diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index 4b002d2c9e478..e82f45c5a307d 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -71,8 +71,11 @@ int GPUReconstructionCPUBackend::runKernelBackend(krnlSetup& _xyz, const Args&.. } unsigned int num = y.num == 0 || y.num == -1 ? 1 : y.num; for (unsigned int k = 0; k < num; k++) { - if (mProcessingSettings.ompKernels) { - int ompThreads = mProcessingSettings.ompKernels == 2 ? ((mProcessingSettings.ompThreads + mNestedLoopOmpFactor - 1) / mNestedLoopOmpFactor) : mProcessingSettings.ompThreads; + int ompThreads = mProcessingSettings.ompKernels ? (mProcessingSettings.ompKernels == 2 ? ((mProcessingSettings.ompThreads + mNestedLoopOmpFactor - 1) / mNestedLoopOmpFactor) : mProcessingSettings.ompThreads) : 1; + if (ompThreads > 1) { + if (mProcessingSettings.debugLevel >= 5) { + printf("Running %d ompThreads\n", ompThreads); + } GPUCA_OPENMP(parallel for num_threads(ompThreads)) for (unsigned int iB = 0; iB < x.nBlocks; iB++) { typename T::GPUSharedMemory smem; @@ -349,9 +352,12 @@ unsigned int GPUReconstructionCPU::getNextTimerId() unsigned int GPUReconstructionCPU::SetAndGetNestedLoopOmpFactor(bool condition, unsigned int max) { if (condition && mProcessingSettings.ompKernels != 1) { - mNestedLoopOmpFactor = mProcessingSettings.ompKernels == 2 ? std::max<unsigned int>(max, mProcessingSettings.ompThreads) : mProcessingSettings.ompThreads; + mNestedLoopOmpFactor = mProcessingSettings.ompKernels == 2 ? std::min<unsigned int>(max, mProcessingSettings.ompThreads) : mProcessingSettings.ompThreads; } else { mNestedLoopOmpFactor = 1; } + if (mProcessingSettings.debugLevel >= 5) { + printf("Running %d OMP threads in outer loop\n", mNestedLoopOmpFactor); + } return mNestedLoopOmpFactor; } From ec380d943b9f95d9c6b85653b8a0dd2d1e811b61 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 7 Jan 2021 15:39:00 +0100 Subject: [PATCH 1729/1751] Add strings and function to retrieve verbose error message --- .../RootSerializableKeyValueStore.h | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h index 31fba2f1c2b62..a4dda395d593b 100644 --- a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h +++ b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h @@ -47,10 +47,23 @@ class RootSerializableKeyValueStore }; enum class GetState { - kOK, - kNOSUCHKEY, - kWRONGTYPE, - kNOTCLASS + kOK = 0, + kNOSUCHKEY = 1, + kWRONGTYPE = 2, + kNOTCLASS = 3 + }; + + private: + static constexpr const char* GetStateString[4] = { + "ok", + "no such key", + "wrong type", + "no TClass"}; + + public: + static const char* getStateString(GetState state) + { + return (int)state < 4 ? GetStateString[(int)state] : nullptr; }; RootSerializableKeyValueStore() = default; From 6715af56180728339889bcb15a7abdc5dc8a6829 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 7 Jan 2021 15:39:59 +0100 Subject: [PATCH 1730/1751] Make use of the serialisable key-value store to store/retrieve arbitrary information of the MC event --- .../SimulationDataFormat/MCEventHeader.h | 33 +++++++++++++++++++ DataFormats/simulation/src/MCEventHeader.cxx | 4 ++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h b/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h index 42844cb8c9894..3af79fb360737 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h @@ -15,7 +15,9 @@ #include "FairMCEventHeader.h" #include "SimulationDataFormat/MCEventStats.h" +#include "CommonUtils/RootSerializableKeyValueStore.h" #include <string> +#include <Framework/Logger.h> namespace o2 { @@ -42,6 +44,36 @@ class MCEventHeader : public FairMCEventHeader void setEmbeddingEventIndex(Int_t value) { mEmbeddingEventIndex = value; }; int getEmbeddedIndex() const { return mEmbeddingEventIndex; } + /** methods to handle stored information **/ + + void clearInfo() + { + mEventInfo.clear(); + }; + + template <typename T> + void putInfo(std::string const& key, T const& value) + { + mEventInfo.put<T>(key, value); + }; + + bool hasInfo(std::string const& key) const + { + return mEventInfo.has(key); + } + + template <typename T> + const T& getInfo(std::string const& key, bool& isvalid) const + { + o2::utils::RootSerializableKeyValueStore::GetState state; + auto& ref = mEventInfo.getRef<T>(key, state); + isvalid = (state == o2::utils::RootSerializableKeyValueStore::GetState::kOK); + if (!isvalid) { + LOG(WARNING) << "problem retrieving info '" << key << "': " << o2::utils::RootSerializableKeyValueStore::getStateString(state); + } + return ref; + }; + /** methods **/ virtual void Reset(); @@ -54,6 +86,7 @@ class MCEventHeader : public FairMCEventHeader // store a view global properties that this event // had in the current simulation (which can be used quick filtering/searching) MCEventStats mEventStats{}; + o2::utils::RootSerializableKeyValueStore mEventInfo; ClassDefOverride(MCEventHeader, 2); diff --git a/DataFormats/simulation/src/MCEventHeader.cxx b/DataFormats/simulation/src/MCEventHeader.cxx index 7991e3078c9ea..0d32dc18d019c 100644 --- a/DataFormats/simulation/src/MCEventHeader.cxx +++ b/DataFormats/simulation/src/MCEventHeader.cxx @@ -25,9 +25,11 @@ void MCEventHeader::Reset() { /** reset **/ + FairMCEventHeader::Reset(); + + clearInfo(); mEmbeddingFileName.clear(); mEmbeddingEventIndex = 0; - FairMCEventHeader::Reset(); } /*****************************************************************/ From fe228d8fcaf8dc6f79711a2a87d9cc1736373858 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 7 Jan 2021 15:45:24 +0100 Subject: [PATCH 1731/1751] Generator protocol to updateHeader and notifyEmbedding needs to use o2::dataformat::MCEventHeader --- Generators/include/Generators/Generator.h | 12 +++++++++--- Generators/include/Generators/GeneratorPythia8.h | 2 +- Generators/src/Generator.cxx | 9 ++++++++- Generators/src/GeneratorPythia8.cxx | 4 ++-- .../Adaptive_Pythia8/adaptive_pythia8.macro | 2 +- run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro | 2 +- .../HF_Embedding_Pythia8/GeneratorHF.macro | 2 +- run/SimExamples/Signal_ImpactB/signal_impactb.macro | 2 +- 8 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Generators/include/Generators/Generator.h b/Generators/include/Generators/Generator.h index 2cf881a4b0e03..0d62b05a03d1a 100644 --- a/Generators/include/Generators/Generator.h +++ b/Generators/include/Generators/Generator.h @@ -18,7 +18,13 @@ #include "Generators/Trigger.h" #include <vector> -class FairMCEventHeader; +namespace o2 +{ +namespace dataformats +{ +class MCEventHeader; +} +} // namespace o2 namespace o2 { @@ -82,7 +88,7 @@ class Generator : public FairGenerator void clearParticles() { mParticles.clear(); }; /** notification methods **/ - virtual void notifyEmbedding(const FairMCEventHeader* mcHeader){}; + virtual void notifyEmbedding(const o2::dataformats::MCEventHeader* eventHeader){}; protected: /** copy constructor **/ @@ -91,7 +97,7 @@ class Generator : public FairGenerator Generator& operator=(const Generator&); /** methods that can be overridded **/ - virtual void updateHeader(FairMCEventHeader* eventHeader){}; + virtual void updateHeader(o2::dataformats::MCEventHeader* eventHeader){}; /** internal methods **/ Bool_t addTracks(FairPrimaryGenerator* primGen); diff --git a/Generators/include/Generators/GeneratorPythia8.h b/Generators/include/Generators/GeneratorPythia8.h index d61b011d00095..1369d531cc129 100644 --- a/Generators/include/Generators/GeneratorPythia8.h +++ b/Generators/include/Generators/GeneratorPythia8.h @@ -84,7 +84,7 @@ class GeneratorPythia8 : public Generator GeneratorPythia8& operator=(const GeneratorPythia8&); /** methods that can be overridded **/ - void updateHeader(FairMCEventHeader* eventHeader) override; + void updateHeader(o2::dataformats::MCEventHeader* eventHeader) override; /** internal methods **/ Bool_t importParticles(Pythia8::Event& event); diff --git a/Generators/src/Generator.cxx b/Generators/src/Generator.cxx index 21a1916a7a337..edb627c2909c9 100644 --- a/Generators/src/Generator.cxx +++ b/Generators/src/Generator.cxx @@ -13,6 +13,7 @@ #include "Generators/Generator.h" #include "Generators/Trigger.h" #include "Generators/PrimaryGenerator.h" +#include "SimulationDataFormat/MCEventHeader.h" #include "FairPrimaryGenerator.h" #include "FairLogger.h" #include <cmath> @@ -89,7 +90,13 @@ Bool_t } /** update header **/ - updateHeader(primGen->GetEvent()); + auto header = primGen->GetEvent(); + auto o2header = dynamic_cast<o2::dataformats::MCEventHeader*>(header); + if (!header) { + LOG(FATAL) << "MC event header is not a 'o2::dataformats::MCEventHeader' object"; + return kFALSE; + } + updateHeader(o2header); /** success **/ return kTRUE; diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 5022c437d5630..605acaf59e489 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -15,7 +15,7 @@ #include "CommonUtils/ConfigurationMacroHelper.h" #include "FairLogger.h" #include "TParticle.h" -#include "FairMCEventHeader.h" +#include "SimulationDataFormat/MCEventHeader.h" #include "Pythia8/HIUserHooks.h" #include "TSystem.h" @@ -192,7 +192,7 @@ Bool_t /*****************************************************************/ -void GeneratorPythia8::updateHeader(FairMCEventHeader* eventHeader) +void GeneratorPythia8::updateHeader(o2::dataformats::MCEventHeader* eventHeader) { /** update header **/ diff --git a/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro b/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro index f0088e2f58313..b126c0fcfccc6 100644 --- a/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro +++ b/run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro @@ -16,7 +16,7 @@ public: // update the number of events to be generated // according to background primaries and formula - void notifyEmbedding(const FairMCEventHeader *bkgHeader) override { + void notifyEmbedding(const o2::dataformats::MCEventHeader *bkgHeader) override { auto nPrimaries = bkgHeader->GetNPrim(); mEvents = mFormula.Eval(nPrimaries); }; diff --git a/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro b/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro index 0d231d1decdc4..09d39f4378527 100644 --- a/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro +++ b/run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro @@ -76,7 +76,7 @@ public: return o2::eventgen::GeneratorTGenerator::generateEvent(); } - void updateHeader(FairMCEventHeader* eventHeader) { + void updateHeader(o2::dataformats::MCEventHeader* eventHeader) { auto theAMPT = (TAmpt *)mGenAMPT->GetMC(); auto impactB = theAMPT->GetHINT1(19); auto evPlane = theAMPT->GetReactionPlaneAngle(); diff --git a/run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro b/run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro index 249d9de05221c..7c6674deb0de5 100644 --- a/run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro +++ b/run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro @@ -28,7 +28,7 @@ public: // for each event in case we are in embedding mode. // We use it to setup the number of signal events // to be generated and to be embedded on the background. - void notifyEmbedding(const FairMCEventHeader *bkgHeader) override { + void notifyEmbedding(const o2::dataformats::MCEventHeader *bkgHeader) override { mEvents = mFormula.Eval(bkgHeader->GetB()); std::cout << " --- notify embedding: impact parameter is " << bkgHeader->GetB() << ", generating " << mEvents << " signal events " << std::endl; }; diff --git a/run/SimExamples/Signal_ImpactB/signal_impactb.macro b/run/SimExamples/Signal_ImpactB/signal_impactb.macro index 5a25c318b3e55..902ca7b84bf1d 100644 --- a/run/SimExamples/Signal_ImpactB/signal_impactb.macro +++ b/run/SimExamples/Signal_ImpactB/signal_impactb.macro @@ -28,7 +28,7 @@ public: // update the number of particles to be generated // according to impact parameter and formula - void notifyEmbedding(const FairMCEventHeader *bkgHeader) override { + void notifyEmbedding(const o2::dataformats::MCEventHeader *bkgHeader) override { auto b = bkgHeader->GetB(); mNSignals = mFormula.Eval(b); std::cout << " --- notify embedding: b = " << b << ", nparticles = " << mNSignals << std::endl; From a0da596fb70058e9fc997ae0864858c42b08a269 Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 7 Jan 2021 15:45:56 +0100 Subject: [PATCH 1732/1751] Populate event header with information of the current Pythia8 event --- Generators/src/GeneratorPythia8.cxx | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 605acaf59e489..c4704e2090969 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -196,15 +196,37 @@ void GeneratorPythia8::updateHeader(o2::dataformats::MCEventHeader* eventHeader) { /** update header **/ + eventHeader->putInfo<std::string>("generator", "pythia8"); + eventHeader->putInfo<int>("version", PYTHIA_VERSION_INTEGER); + #if PYTHIA_VERSION_INTEGER < 8300 auto hiinfo = mPythia.info.hiinfo; #else auto hiinfo = mPythia.info.hiInfo; #endif - /** set impact parameter if in heavy-ion mode **/ if (hiinfo) { + /** set impact parameter **/ eventHeader->SetB(hiinfo->b()); + eventHeader->putInfo<double>("Bimpact", hiinfo->b()); + /** set Ncoll, Npart and Nremn **/ + int nColl, nPart; + int nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg; + int nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg; + getNcoll(nColl); + getNpart(nPart); + getNpart(nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg); + getNremn(nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg); + eventHeader->putInfo<int>("Ncoll", nColl); + eventHeader->putInfo<int>("Npart", nPart); + eventHeader->putInfo<int>("Npart_proj_p", nPartProtonProj); + eventHeader->putInfo<int>("Npart_proj_n", nPartNeutronProj); + eventHeader->putInfo<int>("Npart_targ_p", nPartProtonTarg); + eventHeader->putInfo<int>("Npart_targ_n", nPartNeutronTarg); + eventHeader->putInfo<int>("Nremn_proj_p", nRemnProtonProj); + eventHeader->putInfo<int>("Nremn_proj_n", nRemnNeutronProj); + eventHeader->putInfo<int>("Nremn_targ_p", nRemnProtonTarg); + eventHeader->putInfo<int>("Nremn_targ_n", nRemnNeutronTarg); } } From 100a2343b546bdfd5f14c8bbe76021968dabaf0b Mon Sep 17 00:00:00 2001 From: Roberto Preghenella <preghenella@bo.infn.it> Date: Thu, 7 Jan 2021 17:04:06 +0100 Subject: [PATCH 1733/1751] Add example to show how to add custom information to event header --- Generators/src/GeneratorPythia8.cxx | 6 ++- doc/DetectorSimulation.md | 1 + .../Custom_EventInfo/generator.macro | 42 +++++++++++++++++++ .../Custom_EventInfo/pythia8_inel.cfg | 11 +++++ .../Custom_EventInfo/read_event_info.macro | 31 ++++++++++++++ run/SimExamples/Custom_EventInfo/run.sh | 23 ++++++++++ run/SimExamples/Custom_EventInfo/sim.ini | 6 +++ run/SimExamples/README.md | 1 + 8 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 run/SimExamples/Custom_EventInfo/generator.macro create mode 100644 run/SimExamples/Custom_EventInfo/pythia8_inel.cfg create mode 100644 run/SimExamples/Custom_EventInfo/read_event_info.macro create mode 100755 run/SimExamples/Custom_EventInfo/run.sh create mode 100644 run/SimExamples/Custom_EventInfo/sim.ini diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index c4704e2090969..54a4a4e6fd0d8 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -388,10 +388,12 @@ void GeneratorPythia8::getNremn(const Pythia8::Event& event, int& nProtonProj, i auto pdg = particle.id(); // nuclear remnants have pdg code = ±10LZZZAAA9 - if (pdg < 1000000000) + if (pdg < 1000000000) { continue; // must be nucleus - if (pdg % 10 != 9) + } + if (pdg % 10 != 9) { continue; // first digit must be 9 + } nNucRem++; // extract A, Z and L from pdg code diff --git a/doc/DetectorSimulation.md b/doc/DetectorSimulation.md index 246ebc34a7894..978bcd6b51005 100644 --- a/doc/DetectorSimulation.md +++ b/doc/DetectorSimulation.md @@ -460,5 +460,6 @@ Other helpful resources are the scripts used for regression testing in [prodtest | [HepMC_STARlight](../run/SimExamples/HepMC_STARlight) | Simple example showing **generator configuration** that runs a standalone `STARlight` generation that couples to the `o2` via a `HepMC` file | | [Jet_Embedding_Pythia](../run/SimExamples/Jet_Embedding_Pythia8) | Complex example showing **generator configuration**, **digitization embedding**, **MCTrack access** | | [Selective_Transport](../run/SimExamples/Selective_Transport) | Simple example showing how to run simulation transporting only a custumisable set of particles | +| [Custom_EventInfo](../run/SimExamples/Custom_EventInfo) | Simple example showing how to add custom information to the MC event header | | [sim_challenge.sh](../prodtests/sim_challenge.sh) | Basic example doing a **simple transport, digitization, reconstruction pipeline** on the full dectector. All stages use parallelism. | | [sim_performance.sh](../prodtests/sim_performance_test.sh) | Basic example for serial transport and linearized digitization sequence (one detector after the other). Serves as standard performance candle. | diff --git a/run/SimExamples/Custom_EventInfo/generator.macro b/run/SimExamples/Custom_EventInfo/generator.macro new file mode 100644 index 0000000000000..62be63a47d9ad --- /dev/null +++ b/run/SimExamples/Custom_EventInfo/generator.macro @@ -0,0 +1,42 @@ +class Generator : public o2::eventgen::GeneratorPythia8 { + +public: + + Generator() = default; + ~Generator() = default; + + /** static functions that define the information + stored in the header (key and data type) + and provide a mean to retrieve it + **/ + + static void setXsection(o2::dataformats::MCEventHeader* head, double val) { head->putInfo<double>("Xsection", val); }; + static double getXsection(o2::dataformats::MCEventHeader* head, bool& isvalid) { return head->getInfo<double>("Xsection", isvalid); }; + + static void setXsectionErr(o2::dataformats::MCEventHeader* head, double val) { head->putInfo<double>("Xsection_err", val); }; + static double getXsectionErr(o2::dataformats::MCEventHeader* head, bool& isvalid) { return head->getInfo<double>("Xsection_err", isvalid); }; + + static void setNmpi(o2::dataformats::MCEventHeader* head, int val) { head->putInfo<int>("Nmpi", val); }; + static int getNmpi(o2::dataformats::MCEventHeader* head, bool& isvalid) { return head->getInfo<int>("Nmpi", isvalid); }; + +private: + + void updateHeader(o2::dataformats::MCEventHeader* head) final { + + // call original function + o2::eventgen::GeneratorPythia8::updateHeader(head); + + // store cross-section and Nmpi + setXsection(head, mPythia.info.sigmaGen()); + setXsectionErr(head, mPythia.info.sigmaErr()); + setNmpi(head, mPythia.info.nMPI()); + + }; + +}; + +FairGenerator* +generator() +{ + return new Generator; +} diff --git a/run/SimExamples/Custom_EventInfo/pythia8_inel.cfg b/run/SimExamples/Custom_EventInfo/pythia8_inel.cfg new file mode 100644 index 0000000000000..fdea3cc091984 --- /dev/null +++ b/run/SimExamples/Custom_EventInfo/pythia8_inel.cfg @@ -0,0 +1,11 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 14000. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 0.001 diff --git a/run/SimExamples/Custom_EventInfo/read_event_info.macro b/run/SimExamples/Custom_EventInfo/read_event_info.macro new file mode 100644 index 0000000000000..bc2378e58ca0f --- /dev/null +++ b/run/SimExamples/Custom_EventInfo/read_event_info.macro @@ -0,0 +1,31 @@ +#include "generator.macro" + +void +read_event_info(const char *fname) +{ + + auto fin = TFile::Open(fname); + auto tin = (TTree*)fin->Get("o2sim"); + auto head = new o2::dataformats::MCEventHeader; + tin->SetBranchAddress("MCEventHeader.", &head); + + bool isvalid; + + for (int iev = 0; iev < tin->GetEntries(); ++iev) { + + tin->GetEntry(iev); + + std::cout << " ---------------" << std::endl; + auto Xsection = Generator::getXsection(head, isvalid); + if (isvalid) + std::cout << " Xsection = " << Xsection << std::endl; + auto XsectionErr = Generator::getXsectionErr(head, isvalid); + if (isvalid) + std::cout << " XsectionErr = " << XsectionErr << std::endl; + auto Nmpi = Generator::getNmpi(head, isvalid); + if (isvalid) + std::cout << " Nmpi = " << Nmpi << std::endl; + + } + +} diff --git a/run/SimExamples/Custom_EventInfo/run.sh b/run/SimExamples/Custom_EventInfo/run.sh new file mode 100755 index 0000000000000..77f14f8d7e3f0 --- /dev/null +++ b/run/SimExamples/Custom_EventInfo/run.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# +# This is a simulation example showing how to run simulation with Pythia8 +# with an external generator that adds custom information to the event header +# +# + +set -x + +MODULES="PIPE ITS TPC" +EVENTS=100 +NWORKERS=8 + +### generate some events with the external generator that will +### provide some custom information in the event header + +o2-sim -j ${NWORKERS} -n ${EVENTS} -g external -m ${MODULES} \ + --configFile sim.ini > log 2>&1 + +### read the kinematics to print the custom information stored by +### the external generator that we ran before + +root -b -q -l "read_event_info.macro(\"o2sim_Kine.root\")" diff --git a/run/SimExamples/Custom_EventInfo/sim.ini b/run/SimExamples/Custom_EventInfo/sim.ini new file mode 100644 index 0000000000000..708adffd2e11b --- /dev/null +++ b/run/SimExamples/Custom_EventInfo/sim.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=generator.macro +funcName=generator() + +[GeneratorPythia8] +config=pythia8_inel.cfg diff --git a/run/SimExamples/README.md b/run/SimExamples/README.md index 59edafc399c0d..7423842b46d16 100644 --- a/run/SimExamples/README.md +++ b/run/SimExamples/README.md @@ -17,4 +17,5 @@ * \subpage refrunSimExamplesForceDecay_Lambda_Neutron_Dalitz * \subpage refrunSimExamplesJustPrimaryKinematics * \subpage refrunSimExamplesSelective_Transport +* \subpage refrunSimExamplesCustom_EventInfo /doxy --> From 47bb2dd6c63962da345d0ff507ef06bd6fb8ebe4 Mon Sep 17 00:00:00 2001 From: peressounko <Dmitri.Peressounko@Cern.ch> Date: Tue, 12 Jan 2021 02:32:10 +0300 Subject: [PATCH 1734/1751] CPV raw writing and reconstruction (#5129) * CPV raw writing and reconstruction * return value fixed * default constructor, code checker * ctf_test added * clang * ctf io test * Erange in test fixed * explicit abs argument * Protection against corrupted channel header added * braces added Co-authored-by: Dmitri Peresunko <Dmitri.Peresunko@cern.ch> --- DataFormats/Detectors/CPV/CMakeLists.txt | 4 +- .../CPV/include/DataFormatsCPV/CTF.h | 57 ++++ .../CPV/include/DataFormatsCPV/Cluster.h | 64 ++++- .../CPV/include/DataFormatsCPV/Digit.h | 12 +- .../CPV/include/DataFormatsCPV/RawFormats.h | 63 +++++ DataFormats/Detectors/CPV/src/CTF.cxx | 15 ++ .../Detectors/CPV/src/DataFormatsCPVLinkDef.h | 4 + DataFormats/Detectors/CPV/src/Digit.cxx | 2 +- Detectors/CPV/base/CMakeLists.txt | 9 +- .../CPV/base/include/CPVBase/CPVSimParams.h | 6 +- Detectors/CPV/base/include/CPVBase/Geometry.h | 35 ++- .../CPV/base/include/CPVBase/RCUTrailer.h | 186 +++++++++++++ Detectors/CPV/base/src/Geometry.cxx | 79 ++++-- Detectors/CPV/base/src/RCUTrailer.cxx | 249 ++++++++++++++++++ .../calib/include/CPVCalib/BadChannelMap.h | 14 +- .../CPV/calib/include/CPVCalib/CalibParams.h | 12 +- Detectors/CPV/calib/src/BadChannelMap.cxx | 10 +- Detectors/CPV/calib/src/CalibParams.cxx | 8 +- Detectors/CPV/reconstruction/CMakeLists.txt | 13 +- .../include/CPVReconstruction/CTFCoder.h | 152 +++++++++++ .../include/CPVReconstruction/CTFHelper.h | 193 ++++++++++++++ .../include/CPVReconstruction/Clusterer.h | 21 +- .../include/CPVReconstruction/RawDecoder.h | 121 +++++++++ .../CPVReconstruction/RawReaderMemory.h | 123 +++++++++ .../src/CPVReconstructionLinkDef.h | 2 + Detectors/CPV/reconstruction/src/CTFCoder.cxx | 76 ++++++ .../CPV/reconstruction/src/CTFHelper.cxx | 15 ++ .../CPV/reconstruction/src/Clusterer.cxx | 99 +++---- .../CPV/reconstruction/src/RawDecoder.cxx | 171 ++++++++++++ .../reconstruction/src/RawReaderMemory.cxx | 142 ++++++++++ Detectors/CPV/simulation/CMakeLists.txt | 24 +- .../include/CPVSimulation/RawWriter.h | 91 +++++++ .../CPV/simulation/src/CPVSimulationLinkDef.h | 1 + Detectors/CPV/simulation/src/Detector.cxx | 8 +- Detectors/CPV/simulation/src/RawCreator.cxx | 108 ++++++++ Detectors/CPV/simulation/src/RawWriter.cxx | 169 ++++++++++++ Detectors/CPV/workflow/CMakeLists.txt | 18 +- .../include/CPVWorkflow/EntropyDecoderSpec.h | 47 ++++ .../include/CPVWorkflow/EntropyEncoderSpec.h | 47 ++++ .../CPVWorkflow/RawToDigitConverterSpec.h | 81 ++++++ .../CPV/workflow/src/ClusterizerSpec.cxx | 34 ++- .../CPV/workflow/src/EntropyDecoderSpec.cxx | 79 ++++++ .../CPV/workflow/src/EntropyEncoderSpec.cxx | 79 ++++++ .../workflow/src/RawToDigitConverterSpec.cxx | 212 +++++++++++++++ Detectors/CPV/workflow/src/RecoWorkflow.cxx | 174 +++++------- .../workflow/src/entropy-encoder-workflow.cxx | 39 +++ Detectors/CTF/CMakeLists.txt | 10 +- Detectors/CTF/test/test_ctf_io_cpv.cxx | 127 +++++++++ Detectors/CTF/workflow/CMakeLists.txt | 3 + Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 8 + Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 3 + .../CTF/workflow/src/ctf-reader-workflow.cxx | 4 + Detectors/PHOS/base/src/RCUTrailer.cxx | 5 +- .../PHOS/reconstruction/src/AltroDecoder.cxx | 7 +- .../src/SimpleDigitizerWorkflow.cxx | 2 +- 55 files changed, 3044 insertions(+), 293 deletions(-) create mode 100644 DataFormats/Detectors/CPV/include/DataFormatsCPV/CTF.h create mode 100644 DataFormats/Detectors/CPV/include/DataFormatsCPV/RawFormats.h create mode 100644 DataFormats/Detectors/CPV/src/CTF.cxx create mode 100644 Detectors/CPV/base/include/CPVBase/RCUTrailer.h create mode 100644 Detectors/CPV/base/src/RCUTrailer.cxx create mode 100644 Detectors/CPV/reconstruction/include/CPVReconstruction/CTFCoder.h create mode 100644 Detectors/CPV/reconstruction/include/CPVReconstruction/CTFHelper.h create mode 100644 Detectors/CPV/reconstruction/include/CPVReconstruction/RawDecoder.h create mode 100644 Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h create mode 100644 Detectors/CPV/reconstruction/src/CTFCoder.cxx create mode 100644 Detectors/CPV/reconstruction/src/CTFHelper.cxx create mode 100644 Detectors/CPV/reconstruction/src/RawDecoder.cxx create mode 100644 Detectors/CPV/reconstruction/src/RawReaderMemory.cxx create mode 100644 Detectors/CPV/simulation/include/CPVSimulation/RawWriter.h create mode 100644 Detectors/CPV/simulation/src/RawCreator.cxx create mode 100644 Detectors/CPV/simulation/src/RawWriter.cxx create mode 100644 Detectors/CPV/workflow/include/CPVWorkflow/EntropyDecoderSpec.h create mode 100644 Detectors/CPV/workflow/include/CPVWorkflow/EntropyEncoderSpec.h create mode 100644 Detectors/CPV/workflow/include/CPVWorkflow/RawToDigitConverterSpec.h create mode 100644 Detectors/CPV/workflow/src/EntropyDecoderSpec.cxx create mode 100644 Detectors/CPV/workflow/src/EntropyEncoderSpec.cxx create mode 100644 Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx create mode 100644 Detectors/CPV/workflow/src/entropy-encoder-workflow.cxx create mode 100644 Detectors/CTF/test/test_ctf_io_cpv.cxx diff --git a/DataFormats/Detectors/CPV/CMakeLists.txt b/DataFormats/Detectors/CPV/CMakeLists.txt index acd427dca151e..408c28eeea50c 100644 --- a/DataFormats/Detectors/CPV/CMakeLists.txt +++ b/DataFormats/Detectors/CPV/CMakeLists.txt @@ -13,6 +13,7 @@ o2_add_library(DataFormatsCPV src/Digit.cxx src/Cluster.cxx src/TriggerRecord.cxx + src/CTF.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::MathUtils @@ -25,4 +26,5 @@ o2_target_root_dictionary(DataFormatsCPV HEADERS include/DataFormatsCPV/CPVBlockHeader.h include/DataFormatsCPV/Digit.h include/DataFormatsCPV/Cluster.h - include/DataFormatsCPV/TriggerRecord.h) + include/DataFormatsCPV/TriggerRecord.h + include/DataFormatsCPV/CTF.h) diff --git a/DataFormats/Detectors/CPV/include/DataFormatsCPV/CTF.h b/DataFormats/Detectors/CPV/include/DataFormatsCPV/CTF.h new file mode 100644 index 0000000000000..55ed73bd7895a --- /dev/null +++ b/DataFormats/Detectors/CPV/include/DataFormatsCPV/CTF.h @@ -0,0 +1,57 @@ +// 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 CTF.h +/// \author ruben.shahoyan@cern.ch +/// \brief Definitions for CPV CTF data + +#ifndef O2_CPV_CTF_H +#define O2_CPV_CTF_H + +#include <vector> +#include <Rtypes.h> +#include "DetectorsCommonDataFormats/EncodedBlocks.h" +#include "DataFormatsCPV/TriggerRecord.h" +#include "DataFormatsCPV/Cluster.h" + +namespace o2 +{ +namespace cpv +{ + +/// Header for a single CTF +struct CTFHeader { + uint32_t nTriggers = 0; /// number of triggers + uint32_t nClusters = 0; /// number of referred cells + uint32_t firstOrbit = 0; /// orbit of 1st trigger + uint16_t firstBC = 0; /// bc of 1st trigger + + ClassDefNV(CTFHeader, 1); +}; + +/// wrapper for the Entropy-encoded triggers and cells of the TF +struct CTF : public o2::ctf::EncodedBlocks<CTFHeader, 7, uint32_t> { + + static constexpr size_t N = getNBlocks(); + enum Slots { BLC_bcIncTrig, + BLC_orbitIncTrig, + BLC_entriesTrig, + BLC_posX, + BLC_posZ, + BLC_energy, + BLC_status + }; + ClassDefNV(CTF, 1); +}; + +} // namespace cpv +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/CPV/include/DataFormatsCPV/Cluster.h b/DataFormats/Detectors/CPV/include/DataFormatsCPV/Cluster.h index 1aa9908db17dc..433d64353970c 100644 --- a/DataFormats/Detectors/CPV/include/DataFormatsCPV/Cluster.h +++ b/DataFormats/Detectors/CPV/include/DataFormatsCPV/Cluster.h @@ -21,11 +21,27 @@ class Geometry; /// \class Cluster /// \brief Contains CPV cluster parameters +constexpr float kMinX = -72.32; // Minimal coordinate in X direction +constexpr float kStepX = 0.0025; // digitization step in X direction +constexpr float kMinZ = -63.3; // Minimal coordinate in Z direction +constexpr float kStepZ = 0.002; // digitization step in Z direction +constexpr float kStepE = 1.; // Amplitude digitization step + class Cluster { + union CluStatus { + uint8_t mBits; + struct { + uint8_t multiplicity : 5; // Pad multiplicty, bits 0-4 + uint8_t module : 2; // module number, bits 5-6 + uint8_t unfolded : 1; // unfolded bit, bit 7 + }; + }; + public: Cluster() = default; + Cluster(char mult, char mod, char exMax, float x, float z, float e) : mMulDigit(mult), mModule(mod), mNExMax(exMax), mLocalPosX(x), mLocalPosZ(z), mEnergy(e) {} Cluster(const Cluster& clu) = default; ~Cluster() = default; @@ -42,13 +58,6 @@ class Cluster void setEnergy(float e) { mEnergy = e; } float getEnergy() const { return mEnergy; } - void getPosition(float& posX, float& posY, float& posZ) const - { - posX = mPosX; - posX = mPosY; - posZ = mPosZ; - } - void getLocalPosition(float& posX, float& posZ) const { posX = mLocalPosX; @@ -58,24 +67,51 @@ class Cluster // 0: was no unfolging, -1: unfolding failed char getModule() const { return mModule; } // CPV module of a current cluster - int getLabel() const { return mLabel; } //Index in MCContainer entry - void setLabel(int l) { mLabel = l; } - // 0: was no unfolging, -1: unfolding failed void setNExMax(char nmax = 1) { mNExMax = nmax; } char getNExMax() const { return mNExMax; } // Number of maxima found in cluster in unfolding: // 0: was no unfolging, -1: unfolding failed + // raw access for CTF encoding + uint16_t getPackedPosX() const { return uint16_t((mLocalPosX - kMinX) / kStepX); } + void setPackedPosX(uint16_t v) { mLocalPosX = kMinX + kStepX * v; } + + uint16_t getPackedPosZ() const { return uint16_t((mLocalPosZ - kMinZ) / kStepZ); } + void setPackedPosZ(uint16_t v) { mLocalPosZ = kMinZ + kStepZ * v; } + + uint8_t getPackedEnergy() const { return uint8_t(std::min(255, int(mEnergy / kStepE))); } + void setPackedEnergy(uint16_t v) { mEnergy = v * kStepE; } + + uint8_t getPackedClusterStatus() const + { + CluStatus s = {0}; + s.multiplicity = mMulDigit; + s.module = mModule; + s.unfolded = mNExMax > 1; + return s.mBits; + } + void setPackedClusterStatus(uint8_t v) + { + CluStatus s = {v}; + mMulDigit = s.multiplicity; + mModule = s.module; + mNExMax = s.unfolded ? 1 : 2; + } + + void setPacked(uint16_t posX, uint16_t posZ, uint8_t en, uint8_t status) + { + setPackedPosX(posX); + setPackedPosZ(posZ); + setPackedEnergy(en); + setPackedClusterStatus(status); + } + protected: char mMulDigit = 0; ///< Digit nultiplicity char mModule = 0; ///< Module number char mNExMax = -1; ///< number of (Ex-)maxima before unfolding - int mLabel = -1; ///< Ref to entry in MCTruthContainer with list of labels float mLocalPosX = 0.; ///< Center of gravity position in local module coordunates (phi direction) float mLocalPosZ = 0.; ///< Center of gravity position in local module coordunates (z direction) - float mPosX = 0.; ///< Center of gravity position in global coordinates - float mPosY = 0.; ///< Center of gravity position in global coordinates - float mPosZ = 0.; ///< Center of gravity position in global coordinates float mEnergy = 0.; ///< full energy of a cluster ClassDefNV(Cluster, 1); diff --git a/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h b/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h index 15eaf170e521b..8c5f83ea6c964 100644 --- a/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h +++ b/DataFormats/Detectors/CPV/include/DataFormatsCPV/Digit.h @@ -36,7 +36,7 @@ class Digit : public DigitBase /// \brief Main Digit constructor /// \param cell absId of a cell, amplitude energy deposited in a cell, time time measured in cell, label label of a /// particle in case of MC \return constructed Digit - Digit(short cell, float amplitude, int label); + Digit(unsigned short cell, float amplitude, int label); /// \brief Digit constructor from Hit /// \param CPV Hit @@ -93,8 +93,8 @@ class Digit : public DigitBase Digit& operator+=(const Digit& other); // /// \brief Absolute sell id - short getAbsId() const { return mAbsId; } - void setAbsId(short cellId) { mAbsId = cellId; } + unsigned short getAbsId() const { return mAbsId; } + void setAbsId(unsigned short cellId) { mAbsId = cellId; } /// \brief Energy deposited in a cell float getAmplitude() const { return mAmplitude; } @@ -109,9 +109,9 @@ class Digit : public DigitBase private: // friend class boost::serialization::access; - short mAbsId = 0; ///< pad index (absolute pad ID) - int mLabel = -1; ///< Index of the corresponding entry/entries in the MC label array - float mAmplitude = 0; ///< Amplitude + unsigned short mAbsId = 0; ///< pad index (absolute pad ID) + int mLabel = -1; ///< Index of the corresponding entry/entries in the MC label array + float mAmplitude = 0; ///< Amplitude ClassDefNV(Digit, 2); }; diff --git a/DataFormats/Detectors/CPV/include/DataFormatsCPV/RawFormats.h b/DataFormats/Detectors/CPV/include/DataFormatsCPV/RawFormats.h new file mode 100644 index 0000000000000..b1d3b4677d30d --- /dev/null +++ b/DataFormats/Detectors/CPV/include/DataFormatsCPV/RawFormats.h @@ -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. + +#ifndef ALICEO2_CPV_RAWFORMATS_H +#define ALICEO2_CPV_RAWFORMATS_H + +namespace o2 +{ + +namespace cpv +{ + +union PadWord { + uint32_t mDataWord; + struct { + uint32_t charge : 11; ///< Bits 0 - 10 : charge + uint32_t address : 6; ///< Bits 12 - 17 : address (0..47) + uint32_t dilogic : 4; ///< Bits 18 - 21 : dilogic (1..10) + uint32_t row : 6; ///< Bits 22 - 26 : raw (1..24) + uint32_t zero : 1; ///< Bits 27 - 27 : zeroed so we can distinguish it from the EoE + }; +}; + +union EoEWord { + uint32_t mDataWord; + struct { + uint32_t nword : 7; ///< Bits 0 - 6 : word counter (0...47) + uint32_t en : 11; ///< Bits 7 - 17 : event number -- not used + uint32_t dilogic : 4; ///< Bits 18 - 21 : dilogic (1..10) + uint32_t row : 6; ///< Bits 22 - 26 : raw (1..24) + uint32_t checkbit : 1; ///< Bits 27 - 27 : bit 27 is always 1 by definition of EoE + }; +}; + +union SegMarkerWord { + uint32_t mDataWord; + struct { + uint32_t row : 8; ///< Bits 0 - 7 : segment 0,1,2 charge + uint32_t nwords : 12; ///< Bits 8 - 19 : number of words in the segment + uint32_t marker : 12; ///< Bits 20 - 31: ab0 the segment marker word + }; +}; + +union RowMarkerWord { + uint32_t mDataWord; + struct { + uint32_t marker : 16; ///< Bits 0,15); //the marker word + uint32_t nwords : 16; ///< Bits 16 - 31 : number of words written after row marker (digits and EoE) + }; +}; + +} // namespace cpv + +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/CPV/src/CTF.cxx b/DataFormats/Detectors/CPV/src/CTF.cxx new file mode 100644 index 0000000000000..cd082fe17df8e --- /dev/null +++ b/DataFormats/Detectors/CPV/src/CTF.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 <stdexcept> +#include <cstring> +#include "DataFormatsCPV/CTF.h" + +using namespace o2::cpv; diff --git a/DataFormats/Detectors/CPV/src/DataFormatsCPVLinkDef.h b/DataFormats/Detectors/CPV/src/DataFormatsCPVLinkDef.h index 7b08dd67ba51f..6313759502591 100644 --- a/DataFormats/Detectors/CPV/src/DataFormatsCPVLinkDef.h +++ b/DataFormats/Detectors/CPV/src/DataFormatsCPVLinkDef.h @@ -22,4 +22,8 @@ #pragma link C++ class std::vector < o2::cpv::Cluster> + ; #pragma link C++ class std::vector < o2::cpv::TriggerRecord> + ; +#pragma link C++ struct o2::cpv::CTFHeader + ; +#pragma link C++ struct o2::cpv::CTF + ; +#pragma link C++ class o2::ctf::EncodedBlocks < o2::cpv::CTFHeader, 7, uint32_t> + ; + #endif diff --git a/DataFormats/Detectors/CPV/src/Digit.cxx b/DataFormats/Detectors/CPV/src/Digit.cxx index a2e211b167fda..b0968d45d6bb9 100644 --- a/DataFormats/Detectors/CPV/src/Digit.cxx +++ b/DataFormats/Detectors/CPV/src/Digit.cxx @@ -17,7 +17,7 @@ using namespace o2::cpv; ClassImp(Digit); -Digit::Digit(short absId, float amplitude, int label) +Digit::Digit(unsigned short absId, float amplitude, int label) : DigitBase(0), mAmplitude(amplitude), mAbsId(absId), mLabel(label) { } diff --git a/Detectors/CPV/base/CMakeLists.txt b/Detectors/CPV/base/CMakeLists.txt index e3ad172022a44..40286d5f9f733 100644 --- a/Detectors/CPV/base/CMakeLists.txt +++ b/Detectors/CPV/base/CMakeLists.txt @@ -9,9 +9,14 @@ # submit itself to any jurisdiction. o2_add_library(CPVBase - SOURCES src/Geometry.cxx src/Hit.cxx src/CPVSimParams.cxx + SOURCES src/Geometry.cxx + src/Hit.cxx + src/CPVSimParams.cxx + src/RCUTrailer.cxx PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat) o2_target_root_dictionary(CPVBase HEADERS include/CPVBase/Geometry.h - include/CPVBase/Hit.h include/CPVBase/CPVSimParams.h) + include/CPVBase/Hit.h + include/CPVBase/CPVSimParams.h + include/CPVBase/RCUTrailer.h) diff --git a/Detectors/CPV/base/include/CPVBase/CPVSimParams.h b/Detectors/CPV/base/include/CPVBase/CPVSimParams.h index 501902c0ff518..bc827cb64a5f0 100644 --- a/Detectors/CPV/base/include/CPVBase/CPVSimParams.h +++ b/Detectors/CPV/base/include/CPVBase/CPVSimParams.h @@ -39,14 +39,14 @@ struct CPVSimParams : public o2::conf::ConfigurableParamHelper<CPVSimParams> { //Parameters used in electronic noise calculation and thresholds (Digitizer) bool mApplyDigitization = true; ///< if energy digitization should be applied - float mZSthreshold = 0.005; ///< Zero Suppression threshold + float mZSthreshold = 0.01; ///< Zero Suppression threshold float mADCWidth = 0.005; ///< Widht of ADC channel used for energy digitization - float mNoise = 0.03; ///< charge noise in one pad + float mNoise = 0.01; ///< charge noise in one pad float mCoeffToNanoSecond = 1.e+9; ///< Conversion for time units float mSortingDelta = 0.1; ///< used in sorting clusters inverse sorting band in cm //Parameters used in clusterization - float mDigitMinEnergy = 0.005; ///< Minimal amplitude of a digit to be used in cluster + float mDigitMinEnergy = 0.01; ///< Minimal amplitude of a digit to be used in cluster float mClusteringThreshold = 0.050; ///< Seed digit minimal amplitude float mUnfogingEAccuracy = 1.e-3; ///< Accuracy of energy calculation in unfoding prosedure (GeV) float mUnfogingXZAccuracy = 1.e-1; ///< Accuracy of position calculation in unfolding procedure (cm) diff --git a/Detectors/CPV/base/include/CPVBase/Geometry.h b/Detectors/CPV/base/include/CPVBase/Geometry.h index 922d1d5064097..99df0860473ef 100644 --- a/Detectors/CPV/base/include/CPVBase/Geometry.h +++ b/Detectors/CPV/base/include/CPVBase/Geometry.h @@ -28,6 +28,22 @@ class Geometry static constexpr short kNumberOfCPVPadsZ = 60; static constexpr float kCPVPadSizePhi = 1.13; static constexpr float kCPVPadSizeZ = 2.1093; + //for hwaddress + static constexpr short kNPAD = 48; + static constexpr short kNDilogic = 10; + static constexpr short kNRow = 16; + static constexpr short kNDDL = 4; + + /// Available numbering schems: + /// relative pad coordinates + /// relId[3]={Module, phi col, z row} where Module=1..3, phi col=0..127, z row=0..59 + /// Absolute pad coordunate + /// absId=0..128*60*3=23040 + /// Raw addresses: + /// DDL corresponds to one module: ddl=Module-1 + /// each module consist of 16 columns of width 8 pads: row=0..15 + /// Each column consists of 10 dilogics (in z direction) dilogic=0...9 + /// Ecah dilogic contains 8*6 pads: hwaddress=0...48 /// /// Default constructor. @@ -55,7 +71,7 @@ class Geometry // = 1 are neighbour // = 2 are not neighbour but do not continue searching // =-1 are not neighbour, continue searching, but do not look before d2 next time - static int areNeighbours(short absId1, short absId2); + static short areNeighbours(unsigned short absId1, unsigned short absId2); /// /// \return AbsId index of the CPV cell @@ -64,14 +80,17 @@ class Geometry /// \param strip: strip number // \param cell: cell in strip number /// - static short relToAbsId(char moduleNumber, int iphi, int iz); - static bool absToRelNumbering(short absId, short* relid); - static char absIdToModule(short absId); - static void absIdToRelPosInModule(short absId, float& x, float& z); - static bool relToAbsNumbering(const short* relId, short& absId); + static unsigned short relToAbsId(short moduleNumber, short iphi, short iz); + static bool absToRelNumbering(unsigned short absId, short* relid); + static short absIdToModule(unsigned short absId); + static void absIdToRelPosInModule(unsigned short absId, float& x, float& z); + static bool relToAbsNumbering(const short* relId, unsigned short& absId); + + static void hwaddressToAbsId(short ddl, short row, short dilogic, short hw, unsigned short& absId); + static void absIdToHWaddress(unsigned short absId, short& ddl, short& row, short& dilogic, short& hw); - static int getTotalNPads() { return kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ * 3; } - static bool IsPadExists(short absId) + static unsigned short getTotalNPads() { return kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ * 4; } + static bool IsPadExists(unsigned short absId) { return absId > 0 && absId <= getTotalNPads(); } // TODO: evaluate from real geometry diff --git a/Detectors/CPV/base/include/CPVBase/RCUTrailer.h b/Detectors/CPV/base/include/CPVBase/RCUTrailer.h new file mode 100644 index 0000000000000..d6f8967c108e9 --- /dev/null +++ b/Detectors/CPV/base/include/CPVBase/RCUTrailer.h @@ -0,0 +1,186 @@ +// 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_CPV_RCUTRAILER_H +#define ALICEO2_CPV_RCUTRAILER_H + +#include <exception> +#include <iosfwd> +#include <string> +#include <cstdint> +#include <gsl/span> +#include "Rtypes.h" + +namespace o2 +{ + +namespace cpv +{ + +/// \class RCUTrailer +/// \brief Information stored in the RCU trailer +/// \ingroup CPVbase +/// +/// The RCU trailer can be found at the end of +/// the payload and contains general information +/// sent by the SRU. +class RCUTrailer +{ + public: + /// \class Error + /// \brief Error handling of the + class Error : public std::exception + { + public: + /// \enum ErrorType_t + /// \brief Error codes for different error types + enum class ErrorType_t { + DECODING_INVALID, ///< Invalid words during decoding + SIZE_INVALID, ///< Invalid trailer size + SAMPLINGFREQ_INVALID, ///< Invalid sampling frequency + L1PHASE_INVALID ///< Invalid L1 phase + }; + + /// \brief Constructor + /// \param errtype Code of the error type + /// \param message corresponding error message + /// + /// Initializing the error with error code and message. + /// To be called when the exception is raised. + Error(ErrorType_t errtype, const char* message) : mErrorType(errtype), mErrorMessage(message) {} + + /// \brief Destructor + ~Error() noexcept override = default; + + /// \brief Access to the error message + /// \return Error message related to the exception type + const char* what() const noexcept override { return mErrorMessage.data(); } + + /// \brief Access to error code + /// \return Error code of the exception type + ErrorType_t getErrorType() const noexcept { return mErrorType; } + + private: + ErrorType_t mErrorType; ///< Type of the error + std::string mErrorMessage; ///< Error Message + }; + + /// \brief Constructor + RCUTrailer() = default; + + /// \brief destructor + ~RCUTrailer() = default; + + /// \brief Reset the RCU trailer + /// + /// Setting all values to 0 + void reset(); + + /// \brief Prints the contents of the RCU trailer data + /// \param stream stream the trailer has to be put on + void printStream(std::ostream& stream) const; + + /// \brief Decode RCU trailer from the 32-bit words in the raw buffer + /// \param buffer Raw buffer from which to read the trailer + /// + /// Read the RCU trailer according to the RCU formware version + /// specified in CDH. + void constructFromRawPayload(const gsl::span<const char> payload); + + unsigned int getFECErrorsA() const { return mFECERRA; } + unsigned int getFECErrorsB() const { return mFECERRB; } + unsigned short getErrorsG2() const { return mERRREG2; } + unsigned int getErrorsG3() const { return mERRREG3; } + unsigned short getActiveFECsA() const { return mActiveFECsA; } + unsigned short getActiveFECsB() const { return mActiveFECsB; } + unsigned int getAltroCFGReg1() const { return mAltroCFG1; } + unsigned int getAltroCFGReg2() const { return mAltroCFG2; } + int getRCUID() const { return mRCUId; } + unsigned int getTrailerSize() const { return mTrailerSize; } + unsigned int getPayloadSize() const { return mPayloadSize; } + unsigned char getFirmwareVersion() const { return mFirmwareVersion; } + + unsigned short getNumberOfChannelAddressMismatch() const { return (mERRREG3 & 0xFFF); } + unsigned short getNumberOfChannelLengthMismatch() const { return ((mERRREG3 >> 12) & 0x1FFF); } + unsigned char getBaselineCorrection() const { return mAltroCFG1 & 0xF; } + bool getPolarity() const { return (mAltroCFG1 >> 4) & 0x1; } + unsigned char getNumberOfPresamples() const { return (mAltroCFG1 >> 5) & 0x3; } + unsigned char getNumberOfPostsamples() const { return (mAltroCFG1 >> 7) & 0xF; } + bool hasSecondBaselineCorr() const { return (mAltroCFG1 >> 11) & 0x1; } + unsigned char getGlitchFilter() const { return (mAltroCFG1 >> 12) & 0x3; } + unsigned char getNumberOfNonZeroSuppressedPostsamples() const { return (mAltroCFG1 >> 14) & 0x7; } + unsigned char getNumberOfNonZeroSuppressedPresamples() const { return (mAltroCFG1 >> 17) & 0x3; } + bool hasZeroSuppression() const { return (mAltroCFG1 >> 19) & 0x1; } + bool getNumberOfAltroBuffers() const { return (mAltroCFG2 >> 24) & 0x1; } + unsigned char getNumberOfPretriggerSamples() const { return (mAltroCFG2 >> 20) & 0xF; } + unsigned short getNumberOfSamplesPerChannel() const { return (mAltroCFG2 >> 10) & 0x3FF; } + bool isSparseReadout() const { return (mAltroCFG2 >> 9) & 0x1; } + + /// \brief Access to the sampling time + /// \return Sampling time in seconds. + /// \throw Error if the RCU trailer was not properly initializied + double getTimeSample() const; + + /// \brief set time sample + /// \param timesample Time sample (in ns) + void setTimeSample(double timesample); + + /// \brief Access to the L1 phase + /// \return L1 phase w.r.t to the LHC clock + double getL1Phase() const; + + /// \brief Set the L1 phase + /// \param l1phase L1 phase (in ns) + void setL1Phase(double l1phase); + + void setFECErrorsA(unsigned int value) { mFECERRA = value; } + void setFECErrorsB(unsigned int value) { mFECERRB = value; } + void setErrorsG2(unsigned short value) { mERRREG2 = value; } + void setErrorsG3(unsigned int value) { mERRREG3 = value; } + void setActiveFECsA(unsigned short value) { mActiveFECsA = value; } + void setActiveFECsB(unsigned short value) { mActiveFECsB = value; } + void setAltroCFGReg1(unsigned int value) { mAltroCFG1 = value; } + void setAltroCFGReg2(unsigned int value) { mAltroCFG2 = value; } + void setFirmwareVersion(unsigned char version) { mFirmwareVersion = version; } + void setPayloadSize(unsigned int size) { mPayloadSize = size; } + + /// \brief checlks whether the RCU trailer is initialzied + /// \return True if the trailer is initialized, false otherwise + bool isInitialized() const { return mIsInitialized; } + + std::vector<uint32_t> encode() const; + + static RCUTrailer constructFromPayloadWords(const gsl::span<const uint32_t> payloadwords); + static RCUTrailer constructFromPayload(const gsl::span<const char> payload); + + private: + int mRCUId = -1; ///< current RCU identifier + unsigned char mFirmwareVersion = 0; ///< RCU firmware version + unsigned int mTrailerSize = 0; ///< Size of the trailer (in number of 32 bit words) + unsigned int mPayloadSize = 0; ///< Size of the payload (in nunber of 32 bit words) + unsigned int mFECERRA = 0; ///< contains errors related to ALTROBUS transactions + unsigned int mFECERRB = 0; ///< contains errors related to ALTROBUS transactions + unsigned short mERRREG2 = 0; ///< contains errors related to ALTROBUS transactions or trailer of ALTRO channel block + unsigned int mERRREG3 = 0; ///< contains number of altro channels skipped due to an address mismatch + unsigned short mActiveFECsA = 0; ///< bit pattern of active FECs in branch A + unsigned short mActiveFECsB = 0; ///< bit pattern of active FECs in branch B + unsigned int mAltroCFG1 = 0; ///< ALTROCFG1 register + unsigned int mAltroCFG2 = 0; ///< ALTROCFG2 and ALTROIF register + bool mIsInitialized = false; ///< Flag whether RCU trailer is initialized for the given raw event + + ClassDefNV(RCUTrailer, 1); +}; + +std::ostream& operator<<(std::ostream& stream, const RCUTrailer& trailer); + +} // namespace cpv + +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/CPV/base/src/Geometry.cxx b/Detectors/CPV/base/src/Geometry.cxx index f80c0387183a8..f9f27f57ffdb9 100644 --- a/Detectors/CPV/base/src/Geometry.cxx +++ b/Detectors/CPV/base/src/Geometry.cxx @@ -9,39 +9,40 @@ // or submit itself to any jurisdiction. #include "CPVBase/Geometry.h" +#include "FairLogger.h" using namespace o2::cpv; ClassImp(Geometry); -short Geometry::relToAbsId(char moduleNumber, int iphi, int iz) +unsigned short Geometry::relToAbsId(short moduleNumber, short iphi, short iz) { //converts module number, phi and z coordunates to absId - return kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ * (moduleNumber - 1) + kNumberOfCPVPadsZ * (iz - 1) + iphi; + return kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ * (moduleNumber - 1) + kNumberOfCPVPadsZ * iz + iphi; } -bool Geometry::absToRelNumbering(short absId, short* relid) +bool Geometry::absToRelNumbering(unsigned short absId, short* relid) { // Converts the absolute numbering into the following array // relid[0] = CPV Module number 1:fNModules // relid[1] = Column number inside a CPV module (Phi coordinate) // relid[2] = Row number inside a CPV module (Z coordinate) - short nCPV = kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ; - relid[0] = (absId - 1) / nCPV + 1; + const short nCPV = kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ; + relid[0] = absId / nCPV + 1; absId -= (relid[0] - 1) * nCPV; - relid[2] = absId / kNumberOfCPVPadsZ + 1; - relid[1] = absId - (relid[2] - 1) * kNumberOfCPVPadsZ; + relid[1] = absId / kNumberOfCPVPadsZ; + relid[2] = absId % kNumberOfCPVPadsZ; return true; } -char Geometry::absIdToModule(short absId) +short Geometry::absIdToModule(unsigned short absId) { - return 1 + (absId - 1) / (kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ); + return 1 + absId / (kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ); } -int Geometry::areNeighbours(short absId1, short absId2) +short Geometry::areNeighbours(unsigned short absId1, unsigned short absId2) { // Gives the neighbourness of two digits = 0 are not neighbour but continue searching @@ -80,23 +81,69 @@ int Geometry::areNeighbours(short absId1, short absId2) } return 0; } -void Geometry::absIdToRelPosInModule(short absId, float& x, float& z) +void Geometry::absIdToRelPosInModule(unsigned short absId, float& x, float& z) { //Calculate from absId of a cell its position in module short relid[3]; absToRelNumbering(absId, relid); - x = (relid[1] - kNumberOfCPVPadsPhi / 2 - 0.5) * kCPVPadSizePhi; - z = (relid[2] - kNumberOfCPVPadsZ / 2 - 0.5) * kCPVPadSizeZ; + x = (relid[1] - kNumberOfCPVPadsPhi / 2 + 0.5) * kCPVPadSizePhi; + z = (relid[2] - kNumberOfCPVPadsZ / 2 + 0.5) * kCPVPadSizeZ; } -bool Geometry::relToAbsNumbering(const short* relId, short& absId) +bool Geometry::relToAbsNumbering(const short* relId, unsigned short& absId) { absId = (relId[0] - 1) * kNumberOfCPVPadsPhi * kNumberOfCPVPadsZ + // the offset of PHOS modules - (relId[2] - 1) * kNumberOfCPVPadsZ + // the offset along phi - relId[1]; // the offset along z + relId[1] * kNumberOfCPVPadsZ + // the offset along phi + relId[2]; // the offset along z return true; } +void Geometry::hwaddressToAbsId(short ddl, short row, short dilog, short hw, unsigned short& absId) +{ + + short relid[3] = {short(ddl + 1), short(8 * row + hw % 8), short(6 * dilog + hw / 8)}; + + relToAbsNumbering(relid, absId); +} + +void Geometry::absIdToHWaddress(unsigned short absId, short& ddl, short& row, short& dilogic, short& hw) +{ + // Convert absId to hw address + // Arguments: w32,ddl,row,dilogic,address where to write the results + + short relid[3]; + absToRelNumbering(absId, relid); + + ddl = relid[0] - 1; // DDL# 0..2 + row = relid[1] / 8; // row# 0..16 + dilogic = relid[2] / 6; // Dilogic# 0..10 + hw = relid[1] % 8 + 8 * (relid[2] % 6); // Address 0..47 + + if (hw < 0 || hw > kNPAD) { + LOG(ERROR) << "Wrong hw address: hw=" << hw << " > kNPAD=" << kNPAD; + hw = 0; + dilogic = 0; + row = 0; + ddl = 0; + return; + } + if (dilogic < 0 || dilogic > kNDilogic) { + LOG(ERROR) << "Wrong dilogic address: dilogic=" << dilogic << " > kNDilogic=" << kNDilogic; + hw = 0; + dilogic = 0; + row = 0; + ddl = 0; + return; + } + if (row < 0 || row > kNRow) { + LOG(ERROR) << "Wrong row address: row=" << row << " > kNRow=" << kNRow; + hw = 0; + dilogic = 0; + row = 0; + ddl = 0; + return; + } +} diff --git a/Detectors/CPV/base/src/RCUTrailer.cxx b/Detectors/CPV/base/src/RCUTrailer.cxx new file mode 100644 index 0000000000000..a7c8e075a2065 --- /dev/null +++ b/Detectors/CPV/base/src/RCUTrailer.cxx @@ -0,0 +1,249 @@ +// 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 <cfloat> +#include <cmath> +#include <iostream> +#include <fmt/format.h> +#include "CommonConstants/LHCConstants.h" +#include "CPVBase/RCUTrailer.h" + +using namespace o2::cpv; + +void RCUTrailer::reset() +{ + mRCUId = -1; + mFirmwareVersion = 0; + mTrailerSize = 0; + mPayloadSize = 0; + mFECERRA = 0; + mFECERRB = 0; + mERRREG2 = 0; + mERRREG3 = 0; + mActiveFECsA = 0; + mActiveFECsB = 0; + mAltroCFG1 = 0; + mAltroCFG2 = 0; + mIsInitialized = false; +} + +void RCUTrailer::constructFromRawPayload(const gsl::span<const char> payloadwords) +{ + + // Code below assumes uint32_t span instead of current char!!!!!! + // reset(); + // int index = payloadwords.size(); + // auto word = payloadwords[--index]; + // if ((word >> 30) != 3) { + // throw Error(Error::ErrorType_t::DECODING_INVALID, "Last RCU trailer word not found!"); + // } + // mFirmwareVersion = (word >> 16) & 0xFF; + + // mRCUId = (int)((word >> 7) & 0x1FF); + // int trailerSize = (word & 0x7F); + + // if (trailerSize < 2) { + // throw Error(Error::ErrorType_t::SIZE_INVALID, fmt::format("Invalid trailer size found (%d bytes) !", trailerSize * 4).data()); + // } + // mTrailerSize = trailerSize; + + // trailerSize -= 2; // Cut first and last trailer words as they are handled separately + // for (; trailerSize > 0; trailerSize--) { + // word = payloadwords[--index]; + // if ((word >> 30) != 2) { + // std::cerr << "Missing RCU trailer identifier pattern!\n"; + // continue; + // } + // int parCode = (word >> 26) & 0xF; + // int parData = word & 0x3FFFFFF; + // switch (parCode) { + // case 1: + // // ERR_REG1 + // mFECERRA = ((parData >> 13) & 0x1FFF) << 7; + // mFECERRB = ((parData & 0x1FFF)) << 7; + // break; + // case 2: + // // ERR_REG2 + // mERRREG2 = parData & 0x1FF; + // break; + // case 3: + // // ERR_REG3 + // mERRREG3 = parData & 0x1FFFFFF; + // break; + // case 4: + // // FEC_RO_A + // mActiveFECsA = parData & 0xFFFF; + // break; + // case 5: + // // FEC_RO_B + // mActiveFECsB = parData & 0xFFFF; + // break; + // case 6: + // // RDO_CFG1 + // mAltroCFG1 = parData & 0xFFFFF; + // break; + // case 7: + // // RDO_CFG2 + // mAltroCFG2 = parData & 0x1FFFFFF; + // break; + // default: + // std::cerr << "Undefined parameter code " << parCode << ", ignore it !\n"; + // break; + // } + // } + // mPayloadSize = payloadwords[--index] & 0x3FFFFFF; + mIsInitialized = true; +} + +double RCUTrailer::getTimeSample() const +{ + unsigned char fq = (mAltroCFG2 >> 5) & 0xF; + double tSample; + switch (fq) { + case 0: + // 20 MHz + tSample = 2.0; + break; + case 1: + // 10 Mhz + tSample = 4.0; + break; + case 2: + // 5 MHz + tSample = 8.; + break; + default: + throw Error(Error::ErrorType_t::SAMPLINGFREQ_INVALID, fmt::format("Invalid sampling frequency value %d !", int(fq)).data()); + } + + return tSample * o2::constants::lhc::LHCBunchSpacingNS * 1.e-9; +} + +void RCUTrailer::setTimeSample(double timesample) +{ + int fq = 0; + if (std::abs(timesample - 50) < DBL_EPSILON) { + fq = 0; + } else if (std::abs(timesample - 100) < DBL_EPSILON) { + fq = 1; + } else if (std::abs(timesample - 200) < DBL_EPSILON) { + fq = 2; + } else { + throw Error(Error::ErrorType_t::SAMPLINGFREQ_INVALID, fmt::format("invalid time sample: %f", timesample).data()); + } + mAltroCFG2 = (mAltroCFG2 & 0x1F) | fq << 5; +} + +double RCUTrailer::getL1Phase() const +{ + double tSample = getTimeSample(), + phase = ((double)(mAltroCFG2 & 0x1F)) * o2::constants::lhc::LHCBunchSpacingNS * 1.e-9; + if (phase >= tSample) { + throw Error(Error::ErrorType_t::L1PHASE_INVALID, fmt::format("Invalid L1 trigger phase (%e s (phase) >= %e s (sampling time)) !", phase, tSample).data()); + } + return phase; +} + +void RCUTrailer::setL1Phase(double l1phase) +{ + int phase = l1phase / 25.; + mAltroCFG2 = (mAltroCFG2 & 0x1E0) | phase; +} + +std::vector<uint32_t> RCUTrailer::encode() const +{ + std::vector<uint32_t> encoded; + encoded.emplace_back(mPayloadSize | 2 << 30); + encoded.emplace_back(mAltroCFG2 | 7 << 26 | 2 << 30); + encoded.emplace_back(mAltroCFG1 | 6 << 26 | 2 << 30); + encoded.emplace_back(mActiveFECsB | 5 << 26 | 2 << 30); + encoded.emplace_back(mActiveFECsA | 4 << 26 | 2 << 30); + encoded.emplace_back(mERRREG3 | 3 << 26 | 2 << 30); + encoded.emplace_back(mERRREG2 | 2 << 26 | 2 << 30); + encoded.emplace_back(mFECERRB >> 7 | (mFECERRA >> 7) << 13 | 1 << 26 | 2 << 30); + + uint32_t lasttrailerword = 3 << 30 | mFirmwareVersion << 16 | mRCUId << 7 | (encoded.size() + 1); + encoded.emplace_back(lasttrailerword); + + return encoded; +} + +void RCUTrailer::printStream(std::ostream& stream) const +{ + std::vector<std::string> errors; + double timesample = -1., l1phase = -1.; + try { + timesample = getTimeSample(); + } catch (Error& e) { + errors.push_back(e.what()); + } + try { + l1phase = getL1Phase(); + } catch (Error& e) { + errors.push_back(e.what()); + } + + stream << "RCU trailer (Format version 2):\n" + << "==================================================\n" + << "RCU ID: " << mRCUId << "\n" + << "Firmware version: " << int(mFirmwareVersion) << "\n" + << "Trailer size: " << mTrailerSize << "\n" + << "Payload size: " << mPayloadSize << "\n" + << "FECERRA: 0x" << std::hex << mFECERRA << "\n" + << "FECERRB: 0x" << std::hex << mFECERRB << "\n" + << "ERRREG2: 0x" << std::hex << mERRREG2 << "\n" + << "#channels skipped due to address mismatch: " << std::dec << getNumberOfChannelAddressMismatch() << "\n" + << "#channels skipped due to bad block length: " << std::dec << getNumberOfChannelLengthMismatch() << "\n" + << "Active FECs (branch A): 0x" << std::hex << mActiveFECsA << "\n" + << "Active FECs (branch B): 0x" << std::hex << mActiveFECsB << "\n" + << "Baseline corr: 0x" << std::hex << int(getBaselineCorrection()) << "\n" + << "Number of presamples: " << std::dec << int(getNumberOfPresamples()) << "\n" + << "Number of postsamples: " << std::dec << int(getNumberOfPostsamples()) << "\n" + << "Second baseline corr: " << (hasSecondBaselineCorr() ? "yes" : "no") << "\n" + << "GlitchFilter: " << std::dec << int(getGlitchFilter()) << "\n" + << "Number of non-ZS postsamples: " << std::dec << int(getNumberOfNonZeroSuppressedPostsamples()) << "\n" + << "Number of non-ZS presamples: " << std::dec << int(getNumberOfNonZeroSuppressedPresamples()) << "\n" + << "Number of ALTRO buffers: " << std::dec << getNumberOfAltroBuffers() << "\n" + << "Number of pretrigger samples: " << std::dec << int(getNumberOfPretriggerSamples()) << "\n" + << "Number of samples per channel: " << std::dec << getNumberOfSamplesPerChannel() << "\n" + << "Sparse readout: " << (isSparseReadout() ? "yes" : "no") << "\n" + << "AltroCFG1: 0x" << std::hex << mAltroCFG1 << "\n" + << "AltroCFG2: 0x" << std::hex << mAltroCFG2 << "\n" + << "Sampling time: " << std::scientific << timesample << " s\n" + << "L1 Phase: " << std::scientific << l1phase << " s\n" + << std::dec << std::fixed; + if (errors.size()) { + stream << "Errors: \n" + << "-------------------------------------------------\n"; + for (const auto& e : errors) { + stream << e << "\n"; + } + } + stream << "==================================================\n"; +} + +RCUTrailer RCUTrailer::constructFromPayloadWords(const gsl::span<const uint32_t> payloadwords) +{ + RCUTrailer result; + auto tmp = gsl::span<const char>(reinterpret_cast<const char*>(payloadwords.data()), payloadwords.size() * sizeof(uint32_t)); + result.constructFromRawPayload(tmp); + return result; +} +RCUTrailer RCUTrailer::constructFromPayload(const gsl::span<const char> payloadwords) +{ + RCUTrailer result; + result.constructFromRawPayload(payloadwords); + return result; +} + +std::ostream& o2::cpv::operator<<(std::ostream& stream, const o2::cpv::RCUTrailer& trailer) +{ + trailer.printStream(stream); + return stream; +} diff --git a/Detectors/CPV/calib/include/CPVCalib/BadChannelMap.h b/Detectors/CPV/calib/include/CPVCalib/BadChannelMap.h index 54f69a0d0e596..d2ba63f23346f 100644 --- a/Detectors/CPV/calib/include/CPVCalib/BadChannelMap.h +++ b/Detectors/CPV/calib/include/CPVCalib/BadChannelMap.h @@ -59,7 +59,7 @@ class BadChannelMap BadChannelMap() = default; /// \brief Constructur used to build test bad map - BadChannelMap(int test); + BadChannelMap(short test); /// \brief Destructor ~BadChannelMap() = default; @@ -93,20 +93,20 @@ class BadChannelMap /// Only bad or warm cells are added to the container. In case /// the mask type is GOOD_CELL, the entry is removed from the /// container if present before, otherwise the cell is ignored. - void addBadChannel(short channelID) { mBadCells.set(channelID); } //set bit to true + void addBadChannel(unsigned short channelID) { mBadCells.set(channelID); } //set bit to true /// \brief Mark channel as good /// \param channelID Absolute ID of the channel /// /// Setting channel as good. - void setChannelGood(short channelID) { mBadCells.set(channelID, false); } + void setChannelGood(unsigned short channelID) { mBadCells.set(channelID, false); } /// \brief Get the status of a certain cell /// \param channelID channel for which to obtain the channel status /// \return true if good channel /// /// Provide the mask status of a cell. - bool isChannelGood(short channelID) const { return !mBadCells.test(channelID); } + bool isChannelGood(unsigned short channelID) const { return !mBadCells.test(channelID); } /// \brief Convert map into 2D histogram representation /// \param mod Module number @@ -117,7 +117,7 @@ class BadChannelMap /// - 0: GOOD_CELL /// - 1: BAD_CELL /// Attention: It is responsibility of user to create/delete histogram - void getHistogramRepresentation(char mod, TH2* h) const; + void getHistogramRepresentation(short mod, TH2* h) const; /// \brief Print bad channels on a given stream /// \param stream Stream on which the bad channel map is printed on @@ -131,8 +131,8 @@ class BadChannelMap void PrintStream(std::ostream& stream) const; private: - static constexpr short NCHANNELS = 28673; ///< Number of channels starting from 1 (4*128*56+1 - std::bitset<NCHANNELS> mBadCells; ///< Container for bad cells, 1 means bad sell + static constexpr unsigned short NCHANNELS = 30720; ///< Number of channels in modules 1-4 starting from 0 (4*128*60) + std::bitset<NCHANNELS> mBadCells; ///< Container for bad cells, 1 means bad sell ClassDefNV(BadChannelMap, 1); }; diff --git a/Detectors/CPV/calib/include/CPVCalib/CalibParams.h b/Detectors/CPV/calib/include/CPVCalib/CalibParams.h index aa9f6ff27e898..dc598c18c65ab 100644 --- a/Detectors/CPV/calib/include/CPVCalib/CalibParams.h +++ b/Detectors/CPV/calib/include/CPVCalib/CalibParams.h @@ -36,7 +36,7 @@ class CalibParams CalibParams() = default; /// \brief Constructor for tests - CalibParams(int test); + CalibParams(short test); /// \brief Destructor ~CalibParams() = default; @@ -44,22 +44,22 @@ class CalibParams /// \brief Get High Gain energy calibration coefficients /// \param cellID Absolute ID of cell /// \return high gain energy calibration coefficient of the cell - float getGain(short cellID) const { return mGainCalib[cellID]; } + float getGain(unsigned short cellID) const { return mGainCalib[cellID]; } /// \brief Set High Gain energy calibration coefficient /// \param cellID Absolute ID of cell /// \param c is the calibration coefficient - void setGain(short cellID, float c) { mGainCalib[cellID] = c; } + void setGain(unsigned short cellID, float c) { mGainCalib[cellID] = c; } /// \brief Set High Gain energy calibration coefficients for one module in the form of 2D histogram /// \param 2D(64,56) histogram with calibration coefficients /// \param module number /// \return Is successful - bool setGain(TH2* h, char module); + bool setGain(TH2* h, short module); private: - static constexpr short NCHANNELS = 28673; ///< Number of channels starting from 1 - std::array<float, NCHANNELS> mGainCalib; ///< Container for the gain calibration coefficients + static constexpr unsigned short NCHANNELS = 30720; ///< Number of channels starting from 1 + std::array<float, NCHANNELS> mGainCalib; ///< Container for the gain calibration coefficients ClassDefNV(CalibParams, 1); }; diff --git a/Detectors/CPV/calib/src/BadChannelMap.cxx b/Detectors/CPV/calib/src/BadChannelMap.cxx index 92bf6f77f2cb1..0e545574b16bc 100644 --- a/Detectors/CPV/calib/src/BadChannelMap.cxx +++ b/Detectors/CPV/calib/src/BadChannelMap.cxx @@ -19,13 +19,13 @@ using namespace o2::cpv; -BadChannelMap::BadChannelMap(int /*dummy*/) +BadChannelMap::BadChannelMap(short /*dummy*/) { //Mark few channels as bad for test peurposes for (short i = 0; i < 60; i++) { //module 2 - short channelID = 3584 + i * 57; + unsigned short channelID = 3584 + i * 57; mBadCells.set(channelID); channelID = 3640 + i * 55; mBadCells.set(channelID); @@ -33,7 +33,7 @@ BadChannelMap::BadChannelMap(int /*dummy*/) for (short i = 0; i < 16; i++) { //module 3 - int channelID = 8972 + i * 57; + unsigned short channelID = 8972 + i * 57; mBadCells.set(channelID); channelID = 8092 + i * 57; mBadCells.set(channelID); @@ -44,7 +44,7 @@ BadChannelMap::BadChannelMap(int /*dummy*/) } } -void BadChannelMap::getHistogramRepresentation(char module, TH2* h) const +void BadChannelMap::getHistogramRepresentation(short module, TH2* h) const { if (!h) { LOG(ERROR) << "provide histogram to be filled"; @@ -60,7 +60,7 @@ void BadChannelMap::getHistogramRepresentation(char module, TH2* h) const h->Reset(); short relid[3] = {module, 1, 1}; - short absId; + unsigned short absId; for (short ix = 1; ix <= MAXX; ix++) { relid[1] = ix; for (short iz = 1; iz <= MAXZ; iz++) { diff --git a/Detectors/CPV/calib/src/CalibParams.cxx b/Detectors/CPV/calib/src/CalibParams.cxx index f7de1a259f88a..c2ee2487e5fca 100644 --- a/Detectors/CPV/calib/src/CalibParams.cxx +++ b/Detectors/CPV/calib/src/CalibParams.cxx @@ -19,13 +19,13 @@ using namespace o2::cpv; -CalibParams::CalibParams(int /*dummy*/) +CalibParams::CalibParams(short /*dummy*/) { //produce reasonable objest for test purposes - mGainCalib.fill(0.005); + mGainCalib.fill(0.01); } -bool CalibParams::setGain(TH2* h, char module) +bool CalibParams::setGain(TH2* h, short module) { const short MAXX = 128, MAXZ = 56; @@ -40,7 +40,7 @@ bool CalibParams::setGain(TH2* h, char module) } short relid[3] = {module, 1, 1}; - short absId; + unsigned short absId; for (short ix = 1; ix <= MAXX; ix++) { relid[1] = ix; for (short iz = 1; iz <= MAXZ; iz++) { diff --git a/Detectors/CPV/reconstruction/CMakeLists.txt b/Detectors/CPV/reconstruction/CMakeLists.txt index a7c66754ad5f4..ba63c292f58d8 100644 --- a/Detectors/CPV/reconstruction/CMakeLists.txt +++ b/Detectors/CPV/reconstruction/CMakeLists.txt @@ -11,11 +11,20 @@ o2_add_library(CPVReconstruction SOURCES src/Clusterer.cxx src/FullCluster.cxx + src/RawDecoder.cxx + src/RawReaderMemory.cxx + src/CTFCoder.cxx + src/CTFHelper.cxx PUBLIC_LINK_LIBRARIES O2::CPVBase O2::CPVCalib O2::DataFormatsCPV - AliceO2::InfoLogger) + O2::DetectorsRaw + AliceO2::InfoLogger + O2::rANS + ms_gsl::ms_gsl) o2_target_root_dictionary(CPVReconstruction HEADERS include/CPVReconstruction/Clusterer.h - include/CPVReconstruction/FullCluster.h) + include/CPVReconstruction/FullCluster.h + include/CPVReconstruction/RawReaderMemory.h + include/CPVReconstruction/RawDecoder.h) diff --git a/Detectors/CPV/reconstruction/include/CPVReconstruction/CTFCoder.h b/Detectors/CPV/reconstruction/include/CPVReconstruction/CTFCoder.h new file mode 100644 index 0000000000000..79b9a0f228289 --- /dev/null +++ b/Detectors/CPV/reconstruction/include/CPVReconstruction/CTFCoder.h @@ -0,0 +1,152 @@ +// 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 CTFCoder.h +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of CPV data + +#ifndef O2_CPV_CTFCODER_H +#define O2_CPV_CTFCODER_H + +#include <algorithm> +#include <iterator> +#include <string> +#include <array> +#include "DataFormatsCPV/CTF.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/CTFCoderBase.h" +#include "rANS/rans.h" +#include "CPVReconstruction/CTFHelper.h" + +class TTree; + +namespace o2 +{ +namespace cpv +{ + +class CTFCoder : public o2::ctf::CTFCoderBase +{ + public: + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::CPV) {} + ~CTFCoder() = default; + + /// entropy-encode data to buffer with CTF + template <typename VEC> + void encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cluster>& cluData); + + /// entropy decode data from buffer with CTF + template <typename VTRG, typename VCLUSTER> + void decode(const CTF::base& ec, VTRG& trigVec, VCLUSTER& cluVec); + + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); + + private: + void appendToTree(TTree& tree, CTF& ec); + void readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Cluster>& cluVec); +}; + +/// entropy-encode clusters to buffer with CTF +template <typename VEC> +void CTFCoder::encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cluster>& cluData) +{ + using MD = o2::ctf::Metadata::OptStore; + // what to do which each field: see o2::ctd::Metadata explanation + constexpr MD optField[CTF::getNBlocks()] = { + MD::EENCODE, // BLC_bcIncTrig + MD::EENCODE, // BLC_orbitIncTrig + MD::EENCODE, // BLC_entriesTrig + MD::EENCODE, // BLC_posX + MD::EENCODE, // BLC_posZ + MD::EENCODE, // BLC_energy + MD::EENCODE // BLC_status + }; + + CTFHelper helper(trigData, cluData); + + // book output size with some margin + auto szIni = sizeof(CTFHeader) + helper.getSize() / 4; // will be autoexpanded if needed + buff.resize(szIni); + + auto ec = CTF::create(buff); + using ECB = CTF::base; + + ec->setHeader(helper.createHeader()); + ec->getANSHeader().majorVersion = 0; + ec->getANSHeader().minorVersion = 1; + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec +#define ENCODECPV(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); + // clang-format off + ENCODECPV(helper.begin_bcIncTrig(), helper.end_bcIncTrig(), CTF::BLC_bcIncTrig, 0); + ENCODECPV(helper.begin_orbitIncTrig(), helper.end_orbitIncTrig(), CTF::BLC_orbitIncTrig, 0); + ENCODECPV(helper.begin_entriesTrig(), helper.end_entriesTrig(), CTF::BLC_entriesTrig, 0); + + ENCODECPV(helper.begin_posX(), helper.end_posX(), CTF::BLC_posX, 0); + ENCODECPV(helper.begin_posZ(), helper.end_posZ(), CTF::BLC_posZ, 0); + ENCODECPV(helper.begin_energy(), helper.end_energy(), CTF::BLC_energy, 0); + ENCODECPV(helper.begin_status(), helper.end_status(), CTF::BLC_status, 0); + // clang-format on + CTF::get(buff.data())->print(getPrefix()); +} + +/// decode entropy-encoded clusters to standard compact clusters +template <typename VTRG, typename VCLUSTER> +void CTFCoder::decode(const CTF::base& ec, VTRG& trigVec, VCLUSTER& cluVec) +{ + auto header = ec.getHeader(); + ec.print(getPrefix()); + std::vector<uint16_t> bcInc, entries, posX, posZ; + std::vector<uint32_t> orbitInc; + std::vector<uint8_t> energy, status; + +#define DECODECPV(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) + // clang-format off + DECODECPV(bcInc, CTF::BLC_bcIncTrig); + DECODECPV(orbitInc, CTF::BLC_orbitIncTrig); + DECODECPV(entries, CTF::BLC_entriesTrig); + DECODECPV(posX, CTF::BLC_posX); + DECODECPV(posZ, CTF::BLC_posZ); + DECODECPV(energy, CTF::BLC_energy); + DECODECPV(status, CTF::BLC_status); + // clang-format on + // + trigVec.clear(); + cluVec.clear(); + trigVec.reserve(header.nTriggers); + status.reserve(header.nClusters); + + uint32_t firstEntry = 0, cluCount = 0; + o2::InteractionRecord ir(header.firstBC, header.firstOrbit); + + Cluster clu; + for (uint32_t itrig = 0; itrig < header.nTriggers; itrig++) { + // restore TrigRecord + if (orbitInc[itrig]) { // non-0 increment => new orbit + ir.bc = bcInc[itrig]; // bcInc has absolute meaning + ir.orbit += orbitInc[itrig]; + } else { + ir.bc += bcInc[itrig]; + } + + firstEntry = cluVec.size(); + for (uint16_t ic = 0; ic < entries[itrig]; ic++) { + clu.setPacked(posX[cluCount], posZ[cluCount], energy[cluCount], status[cluCount]); + cluVec.emplace_back(clu); + cluCount++; + } + trigVec.emplace_back(ir, firstEntry, entries[itrig]); + } + assert(cluCount == header.nClusters); +} + +} // namespace cpv +} // namespace o2 + +#endif // O2_CPV_CTFCODER_H diff --git a/Detectors/CPV/reconstruction/include/CPVReconstruction/CTFHelper.h b/Detectors/CPV/reconstruction/include/CPVReconstruction/CTFHelper.h new file mode 100644 index 0000000000000..32652e5610e31 --- /dev/null +++ b/Detectors/CPV/reconstruction/include/CPVReconstruction/CTFHelper.h @@ -0,0 +1,193 @@ +// 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 CTFHelper.h +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for CPV CTF creation + +#ifndef O2_CPV_CTF_HELPER_H +#define O2_CPV_CTF_HELPER_H + +#include "DataFormatsCPV/CTF.h" +#include <gsl/span> + +namespace o2 +{ +namespace cpv +{ + +class CTFHelper +{ + + public: + CTFHelper(const gsl::span<const TriggerRecord>& trgData, const gsl::span<const Cluster>& cluData) + : mTrigData(trgData), mCluData(cluData) {} + + CTFHeader createHeader() + { + CTFHeader h{uint32_t(mTrigData.size()), uint32_t(mCluData.size()), 0, 0}; + if (mTrigData.size()) { + h.firstOrbit = mTrigData[0].getBCData().orbit; + h.firstBC = mTrigData[0].getBCData().bc; + } + return h; + } + + size_t getSize() const { return mTrigData.size() * sizeof(TriggerRecord) + mCluData.size() * sizeof(Cluster); } + + //>>> =========================== ITERATORS ======================================== + + template <typename I, typename D, typename T> + class _Iter + { + public: + using difference_type = int64_t; + using value_type = T; + using pointer = const T*; + using reference = const T&; + using iterator_category = std::random_access_iterator_tag; + + _Iter(const gsl::span<const D>& data, bool end = false) : mData(data), mIndex(end ? data.size() : 0){}; + _Iter() = default; + + const I& operator++() + { + ++mIndex; + return (I&)(*this); + } + + const I& operator--() + { + mIndex--; + return (I&)(*this); + } + + difference_type operator-(const I& other) const { return mIndex - other.mIndex; } + + difference_type operator-(size_t idx) const { return mIndex - idx; } + + const I& operator-(size_t idx) + { + mIndex -= idx; + return (I&)(*this); + } + + bool operator!=(const I& other) const { return mIndex != other.mIndex; } + bool operator==(const I& other) const { return mIndex == other.mIndex; } + bool operator>(const I& other) const { return mIndex > other.mIndex; } + bool operator<(const I& other) const { return mIndex < other.mIndex; } + + protected: + gsl::span<const D> mData{}; + size_t mIndex = 0; + }; + + //_______________________________________________ + // BC difference wrt previous if in the same orbit, otherwise the abs.value. + // For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_bcIncTrig : public _Iter<Iter_bcIncTrig, TriggerRecord, uint16_t> + { + public: + using _Iter<Iter_bcIncTrig, TriggerRecord, uint16_t>::_Iter; + value_type operator*() const + { + if (mIndex) { + if (mData[mIndex].getBCData().orbit == mData[mIndex - 1].getBCData().orbit) { + return mData[mIndex].getBCData().bc - mData[mIndex - 1].getBCData().bc; + } else { + return mData[mIndex].getBCData().bc; + } + } + return 0; + } + }; + + //_______________________________________________ + // Orbit difference wrt previous. For the very 1st entry return 0 (diff wrt 1st BC in the CTF header) + class Iter_orbitIncTrig : public _Iter<Iter_orbitIncTrig, TriggerRecord, uint32_t> + { + public: + using _Iter<Iter_orbitIncTrig, TriggerRecord, uint32_t>::_Iter; + value_type operator*() const { return mIndex ? mData[mIndex].getBCData().orbit - mData[mIndex - 1].getBCData().orbit : 0; } + }; + + //_______________________________________________ + // Number of cells for trigger + class Iter_entriesTrig : public _Iter<Iter_entriesTrig, TriggerRecord, uint16_t> + { + public: + using _Iter<Iter_entriesTrig, TriggerRecord, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getNumberOfObjects(); } + }; + + //_______________________________________________ + class Iter_posX : public _Iter<Iter_posX, Cluster, uint16_t> + { + public: + using _Iter<Iter_posX, Cluster, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedPosX(); } + }; + + //_______________________________________________ + class Iter_posZ : public _Iter<Iter_posZ, Cluster, uint16_t> + { + public: + using _Iter<Iter_posZ, Cluster, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedPosZ(); } + }; + + //_______________________________________________ + class Iter_energy : public _Iter<Iter_energy, Cluster, uint16_t> + { + public: + using _Iter<Iter_energy, Cluster, uint16_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedEnergy(); } + }; + + //_______________________________________________ + class Iter_status : public _Iter<Iter_status, Cluster, uint8_t> + { + public: + using _Iter<Iter_status, Cluster, uint8_t>::_Iter; + value_type operator*() const { return mData[mIndex].getPackedClusterStatus(); } + }; + + //<<< =========================== ITERATORS ======================================== + + Iter_bcIncTrig begin_bcIncTrig() const { return Iter_bcIncTrig(mTrigData, false); } + Iter_bcIncTrig end_bcIncTrig() const { return Iter_bcIncTrig(mTrigData, true); } + + Iter_orbitIncTrig begin_orbitIncTrig() const { return Iter_orbitIncTrig(mTrigData, false); } + Iter_orbitIncTrig end_orbitIncTrig() const { return Iter_orbitIncTrig(mTrigData, true); } + + Iter_entriesTrig begin_entriesTrig() const { return Iter_entriesTrig(mTrigData, false); } + Iter_entriesTrig end_entriesTrig() const { return Iter_entriesTrig(mTrigData, true); } + + Iter_posX begin_posX() const { return Iter_posX(mCluData, false); } + Iter_posX end_posX() const { return Iter_posX(mCluData, true); } + + Iter_posZ begin_posZ() const { return Iter_posZ(mCluData, false); } + Iter_posZ end_posZ() const { return Iter_posZ(mCluData, true); } + + Iter_energy begin_energy() const { return Iter_energy(mCluData, false); } + Iter_energy end_energy() const { return Iter_energy(mCluData, true); } + + Iter_status begin_status() const { return Iter_status(mCluData, false); } + Iter_status end_status() const { return Iter_status(mCluData, true); } + + private: + const gsl::span<const o2::cpv::TriggerRecord> mTrigData; + const gsl::span<const o2::cpv::Cluster> mCluData; +}; + +} // namespace cpv +} // namespace o2 + +#endif diff --git a/Detectors/CPV/reconstruction/include/CPVReconstruction/Clusterer.h b/Detectors/CPV/reconstruction/include/CPVReconstruction/Clusterer.h index cb0269312ef69..591d5f75d13c4 100644 --- a/Detectors/CPV/reconstruction/include/CPVReconstruction/Clusterer.h +++ b/Detectors/CPV/reconstruction/include/CPVReconstruction/Clusterer.h @@ -33,36 +33,29 @@ class Clusterer void initialize(); void process(gsl::span<const Digit> digits, gsl::span<const TriggerRecord> dtr, - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* dmc, - std::vector<Cluster>* clusters, std::vector<TriggerRecord>* rigRec, + const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& dmc, + std::vector<Cluster>* clusters, std::vector<TriggerRecord>* trigRec, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* cluMC); void makeClusters(gsl::span<const Digit> digits); void evalCluProperties(gsl::span<const Digit> digits, std::vector<Cluster>* clusters, - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* dmc, + const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& dmc, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* cluMC); float responseShape(float dx, float dz); // Parameterization of EM shower + void propagateMC(bool toRun = true) { mRunMC = toRun; } void makeUnfoldings(gsl::span<const Digit> digits); // Find and unfold clusters with few local maxima void unfoldOneCluster(FullCluster& iniClu, char nMax, gsl::span<int> digitId, gsl::span<const Digit> digits); - protected: - //Calibrate Amplitude - inline float calibrate(float amp, short absId) { return amp * mCalibParams->getGain(absId); } - //Test Bad map - inline bool isBadChannel(short absId) { return (!mBadMap->isChannelGood(absId)); } - protected: static constexpr short NLMMax = 10; ///< maximal number of local maxima in cluster - const CalibParams* mCalibParams = nullptr; //! Calibration coefficients - const BadChannelMap* mBadMap = nullptr; //! Calibration coefficients - - std::vector<FullCluster> mClusters; ///< internal vector of clusters + bool mRunMC = false; ///< Process MC info int mFirstDigitInEvent; ///< Range of digits from one event int mLastDigitInEvent; ///< Range of digits from one event - std::vector<Digit> mDigits; ///< vector of trancient digits for cell processing + std::vector<FullCluster> mClusters; ///< internal vector of clusters + std::vector<Digit> mDigits; ///< vector of transient digits for cell processing std::vector<std::vector<float>> meInClusters = std::vector<std::vector<float>>(10, std::vector<float>(NLMMax)); std::vector<std::vector<float>> mfij = std::vector<std::vector<float>>(10, std::vector<float>(NLMMax)); diff --git a/Detectors/CPV/reconstruction/include/CPVReconstruction/RawDecoder.h b/Detectors/CPV/reconstruction/include/CPVReconstruction/RawDecoder.h new file mode 100644 index 0000000000000..9adfd45848a4d --- /dev/null +++ b/Detectors/CPV/reconstruction/include/CPVReconstruction/RawDecoder.h @@ -0,0 +1,121 @@ +// 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_CPV_RAWDECODER_H +#define ALICEO2_CPV_RAWDECODER_H + +#include <iosfwd> +#include <gsl/span> +#include <string> +#include "CPVBase/RCUTrailer.h" +#include "DataFormatsCPV/Digit.h" +#include "CPVReconstruction/RawReaderMemory.h" +class Digits; + +namespace o2 +{ +namespace cpv +{ + +class RawDecoderError +{ + public: + RawDecoderError() = default; //Constructors for vector::emplace_back methods + RawDecoderError(short l, short r, short d, short p, RawErrorType_t e) : Ddl(l), Row(r), Dilogic(d), Pad(p), errortype(e) {} + RawDecoderError(const RawDecoderError& e) = default; + ~RawDecoderError() = default; + + short Ddl; + short Row; + short Dilogic; + short Pad; + RawErrorType_t errortype; + ClassDefNV(RawDecoderError, 1); +}; + +union AddressCharge { + uint32_t mDataWord; + struct { + uint32_t Address : 18; ///< Bits 0 - 17 : Address + uint32_t Charge : 14; ///< Bits 18 - 32 : charge + }; +}; + +/// \class RawDecoder +/// \brief Decoder of the ALTRO data in the raw page +/// \ingroup CPVreconstruction +/// \author Dmitri Peresunko +/// \since Dec, 2020 +/// +/// This is a base class for reading raw data digits. + +class RawDecoder +{ + public: + /// \brief Constructor + /// \param reader Raw reader instance to be decoded + RawDecoder(RawReaderMemory& reader); + + /// \brief Destructor + ~RawDecoder() = default; + + /// \brief Decode the ALTRO stream + /// \throw RawDecoderError if the RCUTrailer or ALTRO payload cannot be decoded + /// + /// Decoding and checking the RCUTtrailer and + /// all channels and bunches in the ALTRO stream. + /// After successfull decoding the Decoder can provide + /// a reference to the RCU trailer and a vector + /// with the decoded chanenels, each containing + /// its bunches. + RawErrorType_t decode(); + + /// \brief Get reference to the RCU trailer object + /// \return const reference to the RCU trailer + const RCUTrailer& getRCUTrailer() const; + + /// \brief Get the reference to the digits container + /// \return Reference to the digits container + const std::vector<uint32_t>& getDigits() const; + + /// \brief Get the reference to the list of decoding errors + /// \return Reference to the list of decoding errors + const std::vector<o2::cpv::RawDecoderError>& getErrors() const { return mErrors; } + + protected: + /// \brief Read RCU trailer for the current event in the raw buffer + RawErrorType_t readRCUTrailer(); + + /// \brief Read channels for the current event in the raw buffer + RawErrorType_t readChannels(); + + private: + /// \brief run checks on the RCU trailer + /// \throw Error if the RCU trailer has inconsistencies + /// + /// Performing various consistency checks on the RCU trailer + /// In case of failure an exception is thrown. + void checkRCUTrailer(); + + void addDigit(uint32_t padWord, short ddl); + + RawReaderMemory& mRawReader; ///< underlying raw reader + RCUTrailer mRCUTrailer; ///< RCU trailer + std::vector<uint32_t> mDigits; ///< vector of channels in the raw stream + std::vector<RawDecoderError> mErrors; ///< vector of decoding errors + bool mChannelsInitialized = false; ///< check whether the channels are initialized + + ClassDefNV(RawDecoder, 1); +}; + +} // namespace cpv + +} // namespace o2 + +#endif diff --git a/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h b/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h new file mode 100644 index 0000000000000..5492fc12086a3 --- /dev/null +++ b/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h @@ -0,0 +1,123 @@ +// 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_CPV_RAWREADERMEMORY_H +#define ALICEO2_CPV_RAWREADERMEMORY_H + +#include <gsl/span> +#include <Rtypes.h> + +#include "CPVBase/RCUTrailer.h" +#include "Headers/RAWDataHeader.h" +#include "Headers/RDHAny.h" + +namespace o2 +{ + +namespace cpv +{ + +enum RawErrorType_t { + kOK, ///< NoError + kNO_PAYLOAD, ///< No payload per ddl + kHEADER_DECODING, + kPAGE_NOTFOUND, + kPAYLOAD_DECODING, + kHEADER_INVALID, + kRCU_TRAILER_ERROR, ///< RCU trailer cannot be decoded or invalid + kRCU_VERSION_ERROR, ///< RCU trailer version not matching with the version in the raw header + kRCU_TRAILER_SIZE_ERROR, ///< RCU trailer size length + kSEGMENT_HEADER_ERROR, + kROW_HEADER_ERROR, + kEOE_HEADER_ERROR, + kPADERROR, + kPadAddress +}; + +/// \class RawReaderMemory +/// \brief Reader for raw data produced by the Readout application in in-memory format +/// \ingroup CPVreconstruction +/// \author Dmitri Peresunko after Markus Fasel +/// \since Sept. 25, 2020 +/// +/// +class RawReaderMemory +{ + public: + /// \brief Constructor + RawReaderMemory(const gsl::span<const char> rawmemory); + + /// \brief Destructor + ~RawReaderMemory() = default; + + /// \brief set new raw memory chunk + /// \param rawmemory New raw memory chunk + void setRawMemory(const gsl::span<const char> rawmemory); + + /// \brief Read next payload from the stream + /// + /// Read the next pages until the stop bit is found. + RawErrorType_t next(); + + /// \brief Read the next page from the stream (single DMA page) + /// \param resetPayload If true the raw payload is reset + /// \throw Error if the page cannot be read or header or payload cannot be deocded + /// + /// Function reading a single DMA page from the stream. It is called + /// inside the next() function for reading payload from multiple DMA + /// pages. As the function cannot handle payload from multiple pages + /// it should not be called directly by the user. + RawErrorType_t nextPage(); + + /// \brief access to the raw header of the current page + /// \return Raw header of the current page + const o2::header::RDHAny& getRawHeader() const { return mRawHeader; } + + /// \brief access to the full raw payload (single or multiple DMA pages) + /// \return Raw Payload of the data until the stop bit is received. + const std::vector<uint32_t>& getPayload() const { return mRawPayload; } + + /// \brief Return size of the payload + /// \return size of the payload + int getPayloadSize() const { return mRawPayload.size(); } + + /// \brief get the size of the file in bytes + /// \return size of the file in byte + int getFileSize() const noexcept { return mRawMemoryBuffer.size(); } + + /// \brief check if more pages are available in the raw file + /// \return true if there is a next page + bool hasNext() const { return mCurrentPosition < mRawMemoryBuffer.size(); } + + protected: + /// \brief Initialize the raw stream + /// + /// Rewind stream to the first entry + void init(); + + o2::header::RDHAny decodeRawHeader(const void* headerwords); + + private: + gsl::span<const char> mRawMemoryBuffer; ///< Memory block with multiple DMA pages + o2::header::RDHAny mRawHeader; ///< Raw header + std::vector<uint32_t> mRawPayload; ///< Raw payload (can consist of multiple pages) + RCUTrailer mCurrentTrailer; ///< RCU trailer + uint64_t mTrailerPayloadWords = 0; ///< Payload words in common trailer + int mCurrentPosition = 0; ///< Current page in file + bool mRawHeaderInitialized = false; ///< RDH for current page initialized + bool mPayloadInitialized = false; ///< Payload for current page initialized + + ClassDefNV(RawReaderMemory, 1); +}; + +} // namespace cpv + +} // namespace o2 + +#endif diff --git a/Detectors/CPV/reconstruction/src/CPVReconstructionLinkDef.h b/Detectors/CPV/reconstruction/src/CPVReconstructionLinkDef.h index 98a55d8446614..76d1bc00c7ae6 100644 --- a/Detectors/CPV/reconstruction/src/CPVReconstructionLinkDef.h +++ b/Detectors/CPV/reconstruction/src/CPVReconstructionLinkDef.h @@ -16,5 +16,7 @@ #pragma link C++ class o2::cpv::Clusterer + ; #pragma link C++ class o2::cpv::FullCluster + ; +#pragma link C++ class o2::cpv::RawReaderMemory + ; +#pragma link C++ class o2::cpv::RawDecoder + ; #endif diff --git a/Detectors/CPV/reconstruction/src/CTFCoder.cxx b/Detectors/CPV/reconstruction/src/CTFCoder.cxx new file mode 100644 index 0000000000000..df9d4f6292ee3 --- /dev/null +++ b/Detectors/CPV/reconstruction/src/CTFCoder.cxx @@ -0,0 +1,76 @@ +// 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 CTFCoder.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief class for entropy encoding/decoding of CPV data + +#include "CPVReconstruction/CTFCoder.h" +#include "CommonUtils/StringUtils.h" +#include <TTree.h> + +using namespace o2::cpv; + +///___________________________________________________________________________________ +// Register encoded data in the tree (Fill is not called, will be done by caller) +void CTFCoder::appendToTree(TTree& tree, CTF& ec) +{ + ec.appendToTree(tree, mDet.getName()); +} + +///___________________________________________________________________________________ +// extract and decode data from the tree +void CTFCoder::readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Cluster>& cluVec) +{ + assert(entry >= 0 && entry < tree.GetEntries()); + CTF ec; + ec.readFromTree(tree, mDet.getName(), entry); + decode(ec, trigVec, cluVec); +} + +///________________________________ +void CTFCoder::createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op) +{ + bool mayFail = true; // RS FIXME if the dictionary file is not there, do not produce exception + auto buff = readDictionaryFromFile<CTF>(dictPath, mayFail); + if (!buff.size()) { + if (mayFail) { + return; + } + throw std::runtime_error("Failed to create CTF dictionaty"); + } + const auto* ctf = CTF::get(buff.data()); + + auto getFreq = [ctf](CTF::Slots slot) -> o2::rans::FrequencyTable { + o2::rans::FrequencyTable ft; + auto bl = ctf->getBlock(slot); + auto md = ctf->getMetadata(slot); + ft.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min, md.max); + return std::move(ft); + }; + auto getProbBits = [ctf](CTF::Slots slot) -> int { + return ctf->getMetadata(slot).probabilityBits; + }; + + // just to get types + uint16_t bcInc = 0, entries = 0, cluPosX = 0, cluPosZ = 0; + uint32_t orbitInc = 0; + uint8_t energy = 0, status = 0; +#define MAKECODER(part, slot) createCoder<decltype(part)>(op, getFreq(slot), getProbBits(slot), int(slot)) + // clang-format off + MAKECODER(bcInc, CTF::BLC_bcIncTrig); + MAKECODER(orbitInc, CTF::BLC_orbitIncTrig); + MAKECODER(entries, CTF::BLC_entriesTrig); + MAKECODER(cluPosX, CTF::BLC_posX); + MAKECODER(cluPosZ, CTF::BLC_posZ); + MAKECODER(energy, CTF::BLC_energy); + MAKECODER(status, CTF::BLC_status); + // clang-format on +} diff --git a/Detectors/CPV/reconstruction/src/CTFHelper.cxx b/Detectors/CPV/reconstruction/src/CTFHelper.cxx new file mode 100644 index 0000000000000..9954f5a8d0a1b --- /dev/null +++ b/Detectors/CPV/reconstruction/src/CTFHelper.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. + +/// \file CTFHelper.cxx +/// \author ruben.shahoyan@cern.ch +/// \brief Helper for CPV CTF creation + +#include "CPVReconstruction/CTFHelper.h" diff --git a/Detectors/CPV/reconstruction/src/Clusterer.cxx b/Detectors/CPV/reconstruction/src/Clusterer.cxx index 5af836e70d79e..edd427f29d4da 100644 --- a/Detectors/CPV/reconstruction/src/Clusterer.cxx +++ b/Detectors/CPV/reconstruction/src/Clusterer.cxx @@ -32,19 +32,21 @@ void Clusterer::initialize() mFirstDigitInEvent = 0; mLastDigitInEvent = -1; } + //____________________________________________________________________________ void Clusterer::process(gsl::span<const Digit> digits, gsl::span<const TriggerRecord> dtr, - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* dmc, + const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& dmc, std::vector<Cluster>* clusters, std::vector<TriggerRecord>* trigRec, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* cluMC) { clusters->clear(); //final out list of clusters trigRec->clear(); - if (cluMC) { + if (mRunMC) { cluMC->clear(); } for (const auto& tr : dtr) { + mFirstDigitInEvent = tr.getFirstEntry(); mLastDigitInEvent = mFirstDigitInEvent + tr.getNumberOfObjects(); int indexStart = clusters->size(); @@ -52,36 +54,14 @@ void Clusterer::process(gsl::span<const Digit> digits, gsl::span<const TriggerRe LOG(DEBUG) << "Starting clusteriztion digits from " << mFirstDigitInEvent << " to " << mLastDigitInEvent; - if (!mBadMap) { - if (o2::cpv::CPVSimParams::Instance().mCCDBPath.compare("localtest") == 0) { - mBadMap = new BadChannelMap(1); // test default map - mCalibParams = new CalibParams(1); //test calibration map - LOG(INFO) << "No reading BadMap/Calibration from ccdb requested, set default"; - } else { - LOG(INFO) << "Getting BadMap object from ccdb"; - o2::ccdb::CcdbApi ccdb; - std::map<std::string, std::string> metadata; // do we want to store any meta data? - ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation - long bcTime = 1; //TODO!!! Convert BC time to time o2::InteractionRecord bcTime = digitsTR.front().getBCData() ; - mBadMap = ccdb.retrieveFromTFileAny<o2::cpv::BadChannelMap>("CPV/BadMap", metadata, bcTime); - mCalibParams = ccdb.retrieveFromTFileAny<o2::cpv::CalibParams>("CPV/Calib", metadata, bcTime); - if (!mBadMap) { - LOG(FATAL) << "[CPVClusterer - run] can not get Bad Map"; - } - if (!mCalibParams) { - LOG(FATAL) << "[CPVClusterer - run] can not get CalibParams"; - } - } - } - // Collect digits to clusters makeClusters(digits); - // Unfold overlapped clusters - // Split clusters with several local maxima if necessary - if (o2::cpv::CPVSimParams::Instance().mUnfoldClusters) { - makeUnfoldings(digits); - } + // // Unfold overlapped clusters + // // Split clusters with several local maxima if necessary + // if (o2::cpv::CPVSimParams::Instance().mUnfoldClusters) { + // makeUnfoldings(digits); + // } // Calculate properties of collected clusters (Local position, energy, disp etc.) evalCluProperties(digits, clusters, dmc, cluMC); @@ -97,59 +77,51 @@ void Clusterer::makeClusters(gsl::span<const Digit> digits) // A cluster is defined as a list of neighbour digits // Mark all digits as unused yet - const int maxNDigits = 12546; // There is no digits more than in CPV modules ;) - bool digitsUsed[maxNDigits]; - memset(digitsUsed, 0, sizeof(bool) * maxNDigits); + const int maxNDigits = 23040; // There is no digits more than in CPV modules ;) + std::bitset<maxNDigits> digitsUsed; ///< Container for bad cells, 1 means bad sell + digitsUsed.reset(); int iFirst = mFirstDigitInEvent; // first index of digit which potentially can be a part of cluster for (int i = iFirst; i < mLastDigitInEvent; i++) { - if (digitsUsed[i - mFirstDigitInEvent]) { + if (digitsUsed.test(i - mFirstDigitInEvent)) { continue; } const Digit& digitSeed = digits[i]; - float digitSeedEnergy = calibrate(digitSeed.getAmplitude(), digitSeed.getAbsId()); - if (isBadChannel(digitSeed.getAbsId())) { - digitSeedEnergy = 0.; - } + float digitSeedEnergy = digitSeed.getAmplitude(); //already calibrated digits if (digitSeedEnergy < o2::cpv::CPVSimParams::Instance().mDigitMinEnergy) { continue; } // is this digit so energetic that start cluster? - FullCluster* clu = nullptr; - int iDigitInCluster = 0; - if (digitSeedEnergy > o2::cpv::CPVSimParams::Instance().mClusteringThreshold) { - // start new cluster - mClusters.emplace_back(digitSeed.getAbsId(), digitSeedEnergy, digitSeed.getLabel()); - clu = &(mClusters.back()); - - digitsUsed[i - mFirstDigitInEvent] = true; - iDigitInCluster = 1; - } else { + if (digitSeedEnergy < o2::cpv::CPVSimParams::Instance().mClusteringThreshold) { continue; } + // start new cluster + mClusters.emplace_back(digitSeed.getAbsId(), digitSeedEnergy, digitSeed.getLabel()); + FullCluster& clu = mClusters.back(); + digitsUsed.set(i - mFirstDigitInEvent, true); + int iDigitInCluster = 1; + // Now scan remaining digits in list to find neigbours of our seed int index = 0; while (index < iDigitInCluster) { // scan over digits already in cluster - short digitSeedAbsId = clu->getDigitAbsId(index); + short digitSeedAbsId = clu.getDigitAbsId(index); index++; - for (Int_t j = iFirst; j < mLastDigitInEvent; j++) { - if (digitsUsed[j - mFirstDigitInEvent]) { + bool runLoop = true; + for (Int_t j = iFirst; runLoop && (j < mLastDigitInEvent); j++) { + if (digitsUsed.test(j - mFirstDigitInEvent)) { continue; // look through remaining digits } - const Digit* digitN = &(digits[j]); - float digitNEnergy = calibrate(digitN->getAmplitude(), digitN->getAbsId()); - if (isBadChannel(digitN->getAbsId())) { //remove digit - digitNEnergy = 0.; - } + const Digit& digitN = digits[j]; + float digitNEnergy = digitN.getAmplitude(); //Already calibrated digits! if (digitNEnergy < o2::cpv::CPVSimParams::Instance().mDigitMinEnergy) { continue; } // call (digit,digitN) in THAT oder !!!!! - Int_t ineb = Geometry::areNeighbours(digitSeedAbsId, digitN->getAbsId()); + Int_t ineb = Geometry::areNeighbours(digitSeedAbsId, digitN.getAbsId()); switch (ineb) { case -1: // too early (e.g. previous module), do not look before j at subsequent passes iFirst = j; @@ -157,12 +129,13 @@ void Clusterer::makeClusters(gsl::span<const Digit> digits) case 0: // not a neighbour break; case 1: // are neighbours - clu->addDigit(digitN->getAbsId(), digitNEnergy, digitN->getLabel()); + clu.addDigit(digitN.getAbsId(), digitNEnergy, digitN.getLabel()); iDigitInCluster++; - digitsUsed[j - mFirstDigitInEvent] = true; + digitsUsed.set(j - mFirstDigitInEvent, true); break; case 2: // too far from each other default: + runLoop = false; break; } // switch } @@ -340,7 +313,7 @@ void Clusterer::unfoldOneCluster(FullCluster& iniClu, char nMax, gsl::span<int> //____________________________________________________________________________ void Clusterer::evalCluProperties(gsl::span<const Digit> digits, std::vector<Cluster>* clusters, - const o2::dataformats::MCTruthContainer<o2::MCCompLabel>* dmc, + const o2::dataformats::MCTruthContainer<o2::MCCompLabel>& dmc, o2::dataformats::MCTruthContainer<o2::MCCompLabel>* cluMC) { @@ -349,9 +322,10 @@ void Clusterer::evalCluProperties(gsl::span<const Digit> digits, std::vector<Clu } int labelIndex = 0; - if (cluMC) { + if (mRunMC) { labelIndex = cluMC->getIndexedSize(); } + auto clu = mClusters.begin(); while (clu != mClusters.end()) { @@ -370,7 +344,7 @@ void Clusterer::evalCluProperties(gsl::span<const Digit> digits, std::vector<Clu if (clu->getEnergy() > 1.e-4) { //Non-empty cluster clusters->emplace_back(*clu); - if (cluMC) { //Handle labels + if (mRunMC) { //Handle labels //Calculate list of primaries //loop over entries in digit MCTruthContainer const std::vector<FullCluster::CluElement>* vl = clu->getElementList(); @@ -381,7 +355,7 @@ void Clusterer::evalCluProperties(gsl::span<const Digit> digits, std::vector<Clu ++ll; continue; } - gsl::span<const o2::MCCompLabel> spDigList = dmc->getLabels(i); + gsl::span<const o2::MCCompLabel> spDigList = dmc.getLabels(i); gsl::span<o2::MCCompLabel> spCluList = cluMC->getLabels(labelIndex); //get updated list auto digL = spDigList.begin(); while (digL != spDigList.end()) { @@ -401,7 +375,6 @@ void Clusterer::evalCluProperties(gsl::span<const Digit> digits, std::vector<Clu } ++ll; } - clusters->back().setLabel(labelIndex); labelIndex++; } // Work with MC } diff --git a/Detectors/CPV/reconstruction/src/RawDecoder.cxx b/Detectors/CPV/reconstruction/src/RawDecoder.cxx new file mode 100644 index 0000000000000..18937c0e8ea31 --- /dev/null +++ b/Detectors/CPV/reconstruction/src/RawDecoder.cxx @@ -0,0 +1,171 @@ +// 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 <FairLogger.h> +#include "CPVReconstruction/RawReaderMemory.h" +#include "CPVReconstruction/RawDecoder.h" +#include "DataFormatsCPV/RawFormats.h" +#include "InfoLogger/InfoLogger.hxx" +#include "DetectorsRaw/RDHUtils.h" +#include "CPVBase/Geometry.h" + +using namespace o2::cpv; + +RawDecoder::RawDecoder(RawReaderMemory& reader) : mRawReader(reader), + mRCUTrailer(), + mChannelsInitialized(false) +{ +} + +RawErrorType_t RawDecoder::decode() +{ + + auto& header = mRawReader.getRawHeader(); + short ddl = o2::raw::RDHUtils::getFEEID(header); + mDigits.clear(); + + auto payloadwords = mRawReader.getPayload(); + if (payloadwords.size() == 0) { + mErrors.emplace_back(ddl, 0, 0, 0, kNO_PAYLOAD); //add error + LOG(ERROR) << "Empty payload for DDL=" << ddl; + return kNO_PAYLOAD; + } + + // if(readRCUTrailer()!=kOK){ + // LOG(ERROR) << "can not read RCU trailer for DDL " << ddl ; + // return kRCU_TRAILER_ERROR; + // } + + return readChannels(); +} + +RawErrorType_t RawDecoder::readRCUTrailer() +{ + gsl::span<const char> payload(reinterpret_cast<const char*>(mRawReader.getPayload().data()), mRawReader.getPayload().size() * sizeof(uint32_t)); + mRCUTrailer.constructFromRawPayload(payload); + return kOK; +} + +RawErrorType_t RawDecoder::readChannels() +{ + mChannelsInitialized = false; + auto& header = mRawReader.getRawHeader(); + short ddl = o2::raw::RDHUtils::getFEEID(header); //Current fee/ddl + + auto& payloadwords = mRawReader.getPayload(); + //start reading from the end + auto currentWord = payloadwords.rbegin(); + while (currentWord != payloadwords.rend()) { + SegMarkerWord sw = {*currentWord++}; //first get value, then increment + if (sw.marker != 2736) { //error + mErrors.emplace_back(ddl, 17, 2, 0, kSEGMENT_HEADER_ERROR); //add error for non-existing row + //try adding this as padWord + addDigit(sw.mDataWord, ddl); + continue; + } + short nSegWords = sw.nwords; + short currentRow = sw.row; + short nEoE = 0; + while (nSegWords > 0 && currentWord != payloadwords.rend()) { + EoEWord ew = {*currentWord++}; + nSegWords--; + if (ew.checkbit != 1) { //error + LOG(ERROR) << " error EoE, ddl" << ddl << " row " << currentRow; + mErrors.emplace_back(ddl, currentRow, 11, 0, kEOE_HEADER_ERROR); //add error + //try adding this as padWord + addDigit(ew.mDataWord, ddl); + continue; + } + nEoE++; + short nEoEwords = ew.nword; + short currentDilogic = ew.dilogic; + if (ew.row != currentRow) { + LOG(ERROR) << "Row in EoE=" << ew.row << " != expected row " << currentRow; + mErrors.emplace_back(ddl, currentRow, currentDilogic, 0, kEOE_HEADER_ERROR); //add error + //try adding this as padWord + addDigit(ew.mDataWord, ddl); + continue; + } + if (currentDilogic < 0 || currentDilogic > 10) { + LOG(ERROR) << "wrong Dilogic in EoE=" << currentDilogic; + mErrors.emplace_back(ddl, currentRow, currentDilogic, 0, kEOE_HEADER_ERROR); //add error + //try adding this as padWord + addDigit(ew.mDataWord, ddl); + continue; + } + while (nEoEwords > 0 && currentWord != payloadwords.rend()) { + PadWord pad = {*currentWord++}; + nEoEwords--; + nSegWords--; + if (pad.zero != 0) { + LOG(ERROR) << "bad pad, word=" << pad.mDataWord; + mErrors.emplace_back(ddl, currentRow, currentDilogic, 49, kPADERROR); //add error and skip word + continue; + } + //check paw/pad indexes + if (pad.row != currentRow || pad.dilogic != currentDilogic) { + LOG(ERROR) << "RawPad " << pad.row << " != currentRow=" << currentRow << "dilogicPad=" << pad.dilogic << "!= currentDilogic=" << currentDilogic; + mErrors.emplace_back(ddl, short(pad.row), short(pad.dilogic), short(pad.address), kPadAddress); //add error and skip word + //do not skip, try adding using info from pad + } + addDigit(pad.mDataWord, ddl); + } //pads in EoE + if (nEoE % 10 == 0) { // kNDilogic = 10; ///< Number of dilogic per row + if (currentWord != payloadwords.rend()) { //Read row HEader + RowMarkerWord rw = {*currentWord++}; + nSegWords--; + currentRow--; + if (rw.marker != 13992) { + LOG(ERROR) << "Error in row marker:" << rw.marker << "row header word=" << rw.mDataWord; + mErrors.emplace_back(ddl, currentRow, 11, 0, kPadAddress); //add error and skip word + //try adding digit assuming this is pad word + addDigit(rw.mDataWord, ddl); + } + } + } + } // in Segment + } + mChannelsInitialized = true; + return kOK; +} + +const RCUTrailer& RawDecoder::getRCUTrailer() const +{ + if (!mRCUTrailer.isInitialized()) { + LOG(ERROR) << "RCU trailer not initialized"; + } + return mRCUTrailer; +} + +const std::vector<uint32_t>& RawDecoder::getDigits() const +{ + if (!mChannelsInitialized) { + LOG(ERROR) << "Channels not initialized"; + } + return mDigits; +} + +void RawDecoder::addDigit(uint32_t w, short ddl) +{ + + PadWord pad = {w}; + if (pad.zero != 0) { + return; + } + short rowPad = pad.row; + short dilogicPad = pad.dilogic; + short hw = pad.address; + unsigned short absId; + o2::cpv::Geometry::hwaddressToAbsId(ddl, rowPad, dilogicPad, hw, absId); + + AddressCharge ac = {0}; + ac.Address = absId; + ac.Charge = pad.charge; + mDigits.push_back(ac.mDataWord); +} \ No newline at end of file diff --git a/Detectors/CPV/reconstruction/src/RawReaderMemory.cxx b/Detectors/CPV/reconstruction/src/RawReaderMemory.cxx new file mode 100644 index 0000000000000..701130be7ff27 --- /dev/null +++ b/Detectors/CPV/reconstruction/src/RawReaderMemory.cxx @@ -0,0 +1,142 @@ +// 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 <sstream> +#include <string> +#include "FairLogger.h" +#include "CPVReconstruction/RawReaderMemory.h" +#include "DetectorsRaw/RDHUtils.h" + +using namespace o2::cpv; + +using RDHDecoder = o2::raw::RDHUtils; + +RawReaderMemory::RawReaderMemory(gsl::span<const char> rawmemory) : mRawMemoryBuffer(rawmemory) +{ + init(); +} + +void RawReaderMemory::setRawMemory(const gsl::span<const char> rawmemory) +{ + mRawMemoryBuffer = rawmemory; + init(); +} + +o2::header::RDHAny RawReaderMemory::decodeRawHeader(const void* payloadwords) +{ + auto headerversion = RDHDecoder::getVersion(payloadwords); + if (headerversion == 4) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV4*>(payloadwords)); + } else if (headerversion == 5) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV5*>(payloadwords)); + } else if (headerversion == 6) { + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV6*>(payloadwords)); + } + LOG(ERROR) << "Unknown RDH version"; + return o2::header::RDHAny(*reinterpret_cast<const o2::header::RAWDataHeaderV6*>(payloadwords)); + ; +} + +void RawReaderMemory::init() +{ + mCurrentPosition = 0; + mRawHeaderInitialized = false; + mPayloadInitialized = false; +} + +RawErrorType_t RawReaderMemory::next() +{ + mRawPayload.clear(); + mCurrentTrailer.reset(); + bool isDataTerminated = false; + do { + RawErrorType_t e = nextPage(); + if (e != RawErrorType_t::kOK) { + return e; + } + if (hasNext()) { + auto nextheader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + // check continuing payload based on the bc/orbit ID + auto currentbc = RDHDecoder::getTriggerBC(mRawHeader), + nextbc = RDHDecoder::getTriggerBC(nextheader); + auto currentorbit = RDHDecoder::getTriggerOrbit(mRawHeader), + nextorbit = RDHDecoder::getTriggerOrbit(nextheader); + if (currentbc != nextbc || currentorbit != nextorbit) { + isDataTerminated = true; + } else { + auto nextpagecounter = RDHDecoder::getPageCounter(nextheader); + if (nextpagecounter == 0) { + isDataTerminated = true; + } else { + isDataTerminated = false; + } + } + } else { + isDataTerminated = true; + } + // Check if the data continues + } while (!isDataTerminated); + try { + mCurrentTrailer.constructFromPayloadWords(mRawPayload); + } catch (...) { + return RawErrorType_t::kHEADER_DECODING; + } + return RawErrorType_t::kOK; +} + +RawErrorType_t RawReaderMemory::nextPage() +{ + if (!hasNext()) { + return RawErrorType_t::kPAGE_NOTFOUND; + } + mRawHeaderInitialized = false; + mPayloadInitialized = false; + + // Read RDH header + try { + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + while (RDHDecoder::getOffsetToNext(mRawHeader) == RDHDecoder::getHeaderSize(mRawHeader) && + mCurrentPosition < mRawMemoryBuffer.size()) { + // No Payload - jump to next rawheader + // This will eventually move, depending on whether for events without payload in the SRU we send the RCU trailer + mCurrentPosition += RDHDecoder::getHeaderSize(mRawHeader); + mRawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition); + } + mRawHeaderInitialized = true; + } catch (...) { + return RawErrorType_t::kHEADER_DECODING; + } + if (mCurrentPosition + RDHDecoder::getMemorySize(mRawHeader) > mRawMemoryBuffer.size()) { + // Payload incomplete + return RawErrorType_t::kPAYLOAD_DECODING; + } + + auto tmp = reinterpret_cast<const uint32_t*>(mRawMemoryBuffer.data()); + int start = (mCurrentPosition + RDHDecoder::getHeaderSize(mRawHeader)) / sizeof(uint32_t); + int end = start + (RDHDecoder::getMemorySize(mRawHeader) - RDHDecoder::getHeaderSize(mRawHeader)) / sizeof(uint32_t); + for (auto iword = start; iword < end; iword++) { + mRawPayload.push_back(tmp[iword]); + } + + mCurrentPosition += RDHDecoder::getOffsetToNext(mRawHeader); /// Assume fixed 8 kB page size + /* + mCurrentTrailer.setPayloadSize(mCurrentTrailer.getPayloadSize() + trailer.getPayloadSize()); + tralersize = trailer.getTrailerSize(); + } + + gsl::span<const uint32_t> payloadWithoutTrailer(mRawBuffer.getDataWords().data(), mRawBuffer.getDataWords().size() - tralersize); + + mRawPayload.appendPayloadWords(payloadWithoutTrailer); + mRawPayload.increasePageCount(); + } + mCurrentPosition += RDHDecoder::getOffsetToNext(mRawHeader); /// Assume fixed 8 kB page size +*/ + return RawErrorType_t::kOK; +} diff --git a/Detectors/CPV/simulation/CMakeLists.txt b/Detectors/CPV/simulation/CMakeLists.txt index 5d96c06ae79e0..dd2b803aa3f4d 100644 --- a/Detectors/CPV/simulation/CMakeLists.txt +++ b/Detectors/CPV/simulation/CMakeLists.txt @@ -9,11 +9,27 @@ # submit itself to any jurisdiction. o2_add_library(CPVSimulation - SOURCES src/Detector.cxx src/GeometryParams.cxx - src/Digitizer.cxx - PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::CPVBase O2::DataFormatsCPV O2::CPVCalib O2::CCDB) + SOURCES src/Detector.cxx + src/GeometryParams.cxx + src/Digitizer.cxx + src/RawWriter.cxx + PUBLIC_LINK_LIBRARIES O2::DetectorsBase + O2::DataFormatsCPV + O2::CPVBase + O2::CPVCalib + O2::CCDB + O2::SimConfig + O2::SimulationDataFormat + O2::Headers + O2::DetectorsRaw) o2_target_root_dictionary(CPVSimulation HEADERS include/CPVSimulation/Detector.h include/CPVSimulation/GeometryParams.h - include/CPVSimulation/Digitizer.h) + include/CPVSimulation/Digitizer.h + include/CPVSimulation/RawWriter.h) +o2_add_executable(digi2raw + COMPONENT_NAME cpv + PUBLIC_LINK_LIBRARIES O2::CPVSimulation + SOURCES src/RawCreator.cxx) + diff --git a/Detectors/CPV/simulation/include/CPVSimulation/RawWriter.h b/Detectors/CPV/simulation/include/CPVSimulation/RawWriter.h new file mode 100644 index 0000000000000..6d990fb4c375c --- /dev/null +++ b/Detectors/CPV/simulation/include/CPVSimulation/RawWriter.h @@ -0,0 +1,91 @@ +// 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_CPV_RAWWRITER_H +#define ALICEO2_CPV_RAWWRITER_H + +#include <gsl/span> + +#include <array> +#include <fstream> +#include <memory> +#include <string> +#include <map> +#include <vector> + +#include "Rtypes.h" + +#include "DetectorsRaw/RawFileWriter.h" +#include "DataFormatsCPV/Digit.h" +#include "DataFormatsCPV/TriggerRecord.h" +#include "CPVCalib/CalibParams.h" + +namespace o2 +{ + +namespace cpv +{ + +static constexpr short kNDDL = 4; ///< Total number of DDLs +static constexpr short kNPAD = 48; ///< Nuber of pads per dilogic +static constexpr short kNDilogic = 10; ///< Number of dilogic per row +static constexpr short kNRow = 16; ///< number of rows per dddl + +struct padCharge { + short charge; + short pad; + padCharge() : charge(0), pad(0) {} + padCharge(short a, short b) : charge(a), + pad(b) + { + } //for std::vector::emplace_back functionality +}; + +class RawWriter +{ + public: + enum class FileFor_t { + kFullDet, + kLink + }; + RawWriter() = default; + RawWriter(const char* outputdir) { setOutputLocation(outputdir); } + ~RawWriter() = default; + + o2::raw::RawFileWriter& getWriter() const { return *mRawWriter; } + + void setOutputLocation(const char* outputdir) { mOutputLocation = outputdir; } + void setFileFor(FileFor_t filefor) { mFileFor = filefor; } + + void init(); + void digitsToRaw(gsl::span<o2::cpv::Digit> digits, gsl::span<o2::cpv::TriggerRecord> triggers); + bool processTrigger(const gsl::span<o2::cpv::Digit> digitsbranch, const o2::cpv::TriggerRecord& trg); + + int carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data, + const char* ptr, int maxSize, int splitID, + std::vector<char>& trailer, std::vector<char>& header) const; + + private: + std::vector<padCharge> mPadCharge[kNDDL][kNRow][kNDilogic]; ///< list of signals per event + FileFor_t mFileFor = FileFor_t::kFullDet; ///< Granularity of the output files + std::string mOutputLocation = "./"; ///< Rawfile name + std::unique_ptr<CalibParams> mCalibParams; ///< CPV calibration + std::vector<uint32_t> mPayload; ///< Payload to be written + gsl::span<o2::cpv::Digit> mDigits; ///< Digits input vector - must be in digitized format including the time response + std::unique_ptr<o2::raw::RawFileWriter> mRawWriter; ///< Raw writer + + ClassDefNV(RawWriter, 1); +}; + +} // namespace cpv + +} // namespace o2 + +#endif diff --git a/Detectors/CPV/simulation/src/CPVSimulationLinkDef.h b/Detectors/CPV/simulation/src/CPVSimulationLinkDef.h index 1c9ff59953133..a2e865e038991 100644 --- a/Detectors/CPV/simulation/src/CPVSimulationLinkDef.h +++ b/Detectors/CPV/simulation/src/CPVSimulationLinkDef.h @@ -18,5 +18,6 @@ #pragma link C++ class o2::cpv::GeometryParams + ; #pragma link C++ class o2::base::DetImpl < o2::cpv::Detector> + ; #pragma link C++ class o2::cpv::Digitizer + ; +#pragma link C++ class o2::cpv::RawWriter + ; #endif diff --git a/Detectors/CPV/simulation/src/Detector.cxx b/Detectors/CPV/simulation/src/Detector.cxx index a6df5ae4806f6..3a857759abd98 100644 --- a/Detectors/CPV/simulation/src/Detector.cxx +++ b/Detectors/CPV/simulation/src/Detector.cxx @@ -249,15 +249,15 @@ Bool_t Detector::ProcessHits(FairVolume* v) int ixcell = (int)xcell; float zc = zcell - izcell - 0.5; float xc = xcell - ixcell - 0.5; - for (int iz = 1; iz <= cpvparam.mNgamz; iz++) { + for (int iz = 0; iz < cpvparam.mNgamz; iz++) { int kzg = izcell + iz - nz3; - if (kzg <= 0 || kzg > cpvparam.mnCellZ) { + if (kzg < 0 || kzg >= cpvparam.mnCellZ) { continue; } float zg = (float)(iz - nz3) - zc; - for (int ix = 1; ix <= cpvparam.mNgamx; ix++) { + for (int ix = 0; ix < cpvparam.mNgamx; ix++) { int kxg = ixcell + ix - nx3; - if (kxg <= 0 || kxg > cpvparam.mnCellX) { + if (kxg < 0 || kxg >= cpvparam.mnCellX) { continue; } float xg = (float)(ix - nx3) - xc; diff --git a/Detectors/CPV/simulation/src/RawCreator.cxx b/Detectors/CPV/simulation/src/RawCreator.cxx new file mode 100644 index 0000000000000..89a8352f3193b --- /dev/null +++ b/Detectors/CPV/simulation/src/RawCreator.cxx @@ -0,0 +1,108 @@ +// 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 <memory> +#include <string> +#include <vector> +#include "Framework/Logger.h" + +#include <boost/program_options.hpp> + +#include <TFile.h> +#include <TTree.h> +#include <TTreeReader.h> +#include <TSystem.h> + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/StringUtils.h" +#include "DataFormatsCPV/Digit.h" +#include "DataFormatsCPV/TriggerRecord.h" +#include "CPVBase/Geometry.h" +#include "CPVSimulation/RawWriter.h" + +namespace bpo = boost::program_options; + +int main(int argc, const char** argv) +{ + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + " <cmds/options>\n" + " Tool will encode cpv raw data from input file\n" + "Commands / Options"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + add_option("verbose,v", bpo::value<uint32_t>()->default_value(0), "Select verbosity level [0 = no output]"); + add_option("input-file,i", bpo::value<std::string>()->default_value("cpvdigits.root"), "Specifies digit input file."); + add_option("file-for,f", bpo::value<std::string>()->default_value("all"), "single file per: all,link"); + add_option("output-dir,o", bpo::value<std::string>()->default_value("./"), "output directory for raw data"); + add_option("debug,d", bpo::value<uint32_t>()->default_value(0), "Select debug output level [0 = no debug output]"); + add_option("configKeyValues", bpo::value<std::string>()->default_value(""), "comma-separated configKeyValues"); + + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + + if (vm.count("help") || argc == 1) { + std::cout << opt_general << std::endl; + exit(0); + } + + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + + o2::conf::ConfigurableParam::updateFromString(vm["configKeyValues"].as<std::string>()); + + auto digitfilename = vm["input-file"].as<std::string>(), + outputdir = vm["output-dir"].as<std::string>(), + filefor = vm["file-for"].as<std::string>(); + + // if needed, create output directory + if (gSystem->AccessPathName(outputdir.c_str())) { + if (gSystem->mkdir(outputdir.c_str(), kTRUE)) { + LOG(FATAL) << "could not create output directory " << outputdir; + } else { + LOG(INFO) << "created output directory " << outputdir; + } + } + + std::unique_ptr<TFile> digitfile(TFile::Open(digitfilename.data(), "READ")); + auto treereader = std::make_unique<TTreeReader>(static_cast<TTree*>(digitfile->Get("o2sim"))); + TTreeReaderValue<std::vector<o2::cpv::Digit>> digitbranch(*treereader, "CPVDigit"); + TTreeReaderValue<std::vector<o2::cpv::TriggerRecord>> triggerbranch(*treereader, "CPVDigitTrigRecords"); + + o2::cpv::RawWriter::FileFor_t granularity = o2::cpv::RawWriter::FileFor_t::kFullDet; + if (filefor == "all") { + granularity = o2::cpv::RawWriter::FileFor_t::kFullDet; + } else if (filefor == "link") { + granularity = o2::cpv::RawWriter::FileFor_t::kLink; + } + + o2::cpv::RawWriter rawwriter; + rawwriter.setOutputLocation(outputdir.data()); + rawwriter.setFileFor(granularity); + rawwriter.init(); + + // Loop over all entries in the tree, where each tree entry corresponds to a time frame + for (auto en : *treereader) { + rawwriter.digitsToRaw(*digitbranch, *triggerbranch); + } + rawwriter.getWriter().writeConfFile("CPV", "RAWDATA", o2::utils::concat_string(outputdir, "/CPVraw.cfg")); +} diff --git a/Detectors/CPV/simulation/src/RawWriter.cxx b/Detectors/CPV/simulation/src/RawWriter.cxx new file mode 100644 index 0000000000000..1bcc660004ff3 --- /dev/null +++ b/Detectors/CPV/simulation/src/RawWriter.cxx @@ -0,0 +1,169 @@ +// 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 "FairLogger.h" + +#include <fmt/core.h> +#include <gsl/span> +#include <TSystem.h> +#include "DataFormatsCPV/RawFormats.h" +#include "CPVSimulation/RawWriter.h" +#include "CPVBase/CPVSimParams.h" +#include "CPVBase/RCUTrailer.h" +#include "CPVBase/Geometry.h" +#include "CCDB/CcdbApi.h" + +using namespace o2::cpv; + +void RawWriter::init() +{ + mRawWriter = std::make_unique<o2::raw::RawFileWriter>(o2::header::gDataOriginCPV, false); + mRawWriter->setCarryOverCallBack(this); + mRawWriter->setApplyCarryOverToLastPage(true); + + // Set output file and register link + std::string rawfilename = mOutputLocation; + rawfilename += "/cpv.raw"; + + for (int ddl = 0; ddl < kNDDL; ddl++) { + short crorc = 0, link = ddl; + mRawWriter->registerLink(ddl, crorc, link, 0, rawfilename.data()); + } +} + +void RawWriter::digitsToRaw(gsl::span<o2::cpv::Digit> digitsbranch, gsl::span<o2::cpv::TriggerRecord> triggerbranch) +{ + if (!mCalibParams) { + if (o2::cpv::CPVSimParams::Instance().mCCDBPath.compare("localtest") == 0) { + mCalibParams = std::make_unique<o2::cpv::CalibParams>(1); // test default calibration + LOG(INFO) << "[RawWriter] No reading calibration from ccdb requested, set default"; + } else { + LOG(INFO) << "[RawWriter] getting calibration object from ccdb"; + o2::ccdb::CcdbApi ccdb; + std::map<std::string, std::string> metadata; + ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation + auto tr = triggerbranch.begin(); + double eventTime = -1; + // if(tr!=triggerbranch.end()){ + // eventTime = (*tr).getBCData().getTimeNS() ; + // } + //add copy constructor if necessary + // mCalibParams = std::make_unique<o2::cpv::CalibParams>(ccdb.retrieveFromTFileAny<o2::cpv::CalibParams>("CPV/Calib", metadata, eventTime)); + if (!mCalibParams) { + LOG(FATAL) << "[RawWriter] can not get calibration object from ccdb"; + } + } + } + + for (auto trg : triggerbranch) { + processTrigger(digitsbranch, trg); + } +} + +bool RawWriter::processTrigger(const gsl::span<o2::cpv::Digit> digitsbranch, const o2::cpv::TriggerRecord& trg) +{ + + //Array used to sort properly digits + for (int i = kNDDL; i--;) { + for (int j = kNRow; j--;) { + for (int k = kNDilogic; k--;) { + mPadCharge[i][j][k].clear(); + } + } + } + + for (auto& dig : gsl::span(digitsbranch.data() + trg.getFirstEntry(), trg.getNumberOfObjects())) { + short absId = dig.getAbsId(); + short ddl, dilogic, row, hwAddr; + o2::cpv::Geometry::absIdToHWaddress(absId, ddl, row, dilogic, hwAddr); + + //Convert Amp to ADC counts + short charge = dig.getAmplitude() / mCalibParams->getGain(absId); + if (charge > 2047) { + charge = 2047; + } + mPadCharge[ddl][row][dilogic].emplace_back(charge, hwAddr); + } + + //Do through DLLs and fill raw words in proper order + for (int ddl = 0; ddl < kNDDL; ddl++) { + mPayload.clear(); + //write empty header, later will be updated ? + + int nwInSegment = 0; + int posRowMarker = 0; + for (int row = 0; row < kNRow; row++) { + //reserve place for row header + mPayload.emplace_back(uint32_t(0)); + posRowMarker = mPayload.size() - 1; + nwInSegment++; + int nwRow = 0; + for (Int_t dilogic = 0; dilogic < kNDilogic; dilogic++) { + int nPad = 0; + for (padCharge& pc : mPadCharge[ddl][row][dilogic]) { + PadWord currentword = {0}; + currentword.charge = pc.charge; + currentword.address = pc.pad; + currentword.dilogic = dilogic; + currentword.row = row; + mPayload.push_back(currentword.mDataWord); + nwInSegment++; + nPad++; + nwRow++; + } + EoEWord we = {0}; + we.nword = nPad; + we.dilogic = dilogic; + we.row = row; + we.checkbit = 1; + mPayload.push_back(we.mDataWord); + nwInSegment++; + nwRow++; + } + if (row % 8 == 7) { + SegMarkerWord w = {0}; + w.row = row; + w.nwords = nwInSegment; + w.marker = 2736; + mPayload.push_back(w.mDataWord); + nwInSegment = 0; + nwRow++; + } + //Now we know number of words, update rawMarker + RowMarkerWord wr = {0}; + wr.marker = 13992; + wr.nwords = nwRow - 1; + mPayload[posRowMarker] = wr.mDataWord; + } + + // register output data + LOG(DEBUG1) << "Adding payload with size " << mPayload.size() << " (" << mPayload.size() / 4 << " ALTRO words)"; + + short crorc = 0, link = ddl; + mRawWriter->addData(ddl, crorc, link, 0, trg.getBCData(), gsl::span<char>(reinterpret_cast<char*>(mPayload.data()), mPayload.size() * sizeof(uint32_t))); + } + return true; +} +int RawWriter::carryOverMethod(const header::RDHAny* rdh, const gsl::span<char> data, + const char* ptr, int maxSize, int splitID, + std::vector<char>& trailer, std::vector<char>& header) const +{ + + constexpr int phosTrailerSize = 36; + int offs = ptr - &data[0]; // offset wrt the head of the payload + assert(offs >= 0 && size_t(offs + maxSize) <= data.size()); // make sure ptr and end of the suggested block are within the payload + int leftBefore = data.size() - offs; // payload left before this splitting + int leftAfter = leftBefore - maxSize; // what would be left after the suggested splitting + int actualSize = maxSize; + if (leftAfter && leftAfter <= phosTrailerSize) { // avoid splitting the trailer or writing only it. + actualSize -= (phosTrailerSize - leftAfter) + 4; // (as we work with int, not char in decoding) + } + return actualSize; +} diff --git a/Detectors/CPV/workflow/CMakeLists.txt b/Detectors/CPV/workflow/CMakeLists.txt index ec8736c8cc89b..8b6a4e6657690 100644 --- a/Detectors/CPV/workflow/CMakeLists.txt +++ b/Detectors/CPV/workflow/CMakeLists.txt @@ -13,10 +13,24 @@ o2_add_library(CPVWorkflow src/PublisherSpec.cxx src/ClusterizerSpec.cxx src/DigitsPrinterSpec.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsCPV - O2::DPLUtils O2::CPVBase O2::CPVCalib O2::CPVSimulation O2::CPVReconstruction O2::Algorithm) + src/RawToDigitConverterSpec.cxx + src/EntropyEncoderSpec.cxx + src/EntropyDecoderSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DataFormatsCPV + O2::DPLUtils + O2::CPVBase + O2::CPVCalib + O2::CPVSimulation + O2::CPVReconstruction + O2::Algorithm) o2_add_executable(reco-workflow COMPONENT_NAME cpv SOURCES src/cpv-reco-workflow.cxx PUBLIC_LINK_LIBRARIES O2::CPVWorkflow) + +o2_add_executable(entropy-encoder-workflow + COMPONENT_NAME cpv + SOURCES src/entropy-encoder-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::CPVWorkflow) diff --git a/Detectors/CPV/workflow/include/CPVWorkflow/EntropyDecoderSpec.h b/Detectors/CPV/workflow/include/CPVWorkflow/EntropyDecoderSpec.h new file mode 100644 index 0000000000000..7f23f832667d0 --- /dev/null +++ b/Detectors/CPV/workflow/include/CPVWorkflow/EntropyDecoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyDecoderSpec.h +/// @brief Convert CTF (EncodedBlocks) to CPV digit/channels strean + +#ifndef O2_CPV_ENTROPYDECODER_SPEC +#define O2_CPV_ENTROPYDECODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "CPVReconstruction/CTFCoder.h" +#include <TStopwatch.h> + +namespace o2 +{ +namespace cpv +{ + +class EntropyDecoderSpec : public o2::framework::Task +{ + public: + EntropyDecoderSpec(); + ~EntropyDecoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::cpv::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyDecoderSpec(); + +} // namespace cpv +} // namespace o2 + +#endif diff --git a/Detectors/CPV/workflow/include/CPVWorkflow/EntropyEncoderSpec.h b/Detectors/CPV/workflow/include/CPVWorkflow/EntropyEncoderSpec.h new file mode 100644 index 0000000000000..f7543b856e77f --- /dev/null +++ b/Detectors/CPV/workflow/include/CPVWorkflow/EntropyEncoderSpec.h @@ -0,0 +1,47 @@ +// 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 EntropyEncoderSpec.h +/// @brief Convert CPV data to CTF (EncodedBlocks) + +#ifndef O2_CPV_ENTROPYENCODER_SPEC +#define O2_CPV_ENTROPYENCODER_SPEC + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include <TStopwatch.h> +#include "CPVReconstruction/CTFCoder.h" + +namespace o2 +{ +namespace cpv +{ + +class EntropyEncoderSpec : public o2::framework::Task +{ + public: + EntropyEncoderSpec(); + ~EntropyEncoderSpec() override = default; + void run(o2::framework::ProcessingContext& pc) final; + void init(o2::framework::InitContext& ic) final; + void endOfStream(o2::framework::EndOfStreamContext& ec) final; + + private: + o2::cpv::CTFCoder mCTFCoder; + TStopwatch mTimer; +}; + +/// create a processor spec +framework::DataProcessorSpec getEntropyEncoderSpec(); + +} // namespace cpv +} // namespace o2 + +#endif diff --git a/Detectors/CPV/workflow/include/CPVWorkflow/RawToDigitConverterSpec.h b/Detectors/CPV/workflow/include/CPVWorkflow/RawToDigitConverterSpec.h new file mode 100644 index 0000000000000..78764982c9ebe --- /dev/null +++ b/Detectors/CPV/workflow/include/CPVWorkflow/RawToDigitConverterSpec.h @@ -0,0 +1,81 @@ +// 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 <vector> + +#include "Framework/DataProcessorSpec.h" +#include "Framework/Task.h" +#include "DataFormatsCPV/Digit.h" +#include "DataFormatsCPV/TriggerRecord.h" +#include "CPVCalib/CalibParams.h" +#include "CPVCalib/BadChannelMap.h" +#include "CPVReconstruction/RawDecoder.h" + +namespace o2 +{ + +namespace cpv +{ + +namespace reco_workflow +{ + +/// \class RawToDigitConverterSpec +/// \brief Coverter task for Raw data to CPV cells +/// \author Dmitri Peresunko NRC KI +/// \since Sept., 2020 +/// +class RawToDigitConverterSpec : public framework::Task +{ + public: + /// \brief Constructor + /// \param propagateMC If true the MCTruthContainer is propagated to the output + RawToDigitConverterSpec() : framework::Task(){}; + + /// \brief Destructor + ~RawToDigitConverterSpec() override = default; + + /// \brief Initializing the RawToDigitConverterSpec + /// \param ctx Init context + void init(framework::InitContext& ctx) final; + + /// \brief Run conversion of raw data to cells + /// \param ctx Processing context + /// + /// The following branches are linked: + /// Input RawData: {"ROUT", "RAWDATA", 0, Lifetime::Timeframe} + /// Output cells: {"CPV", "CELLS", 0, Lifetime::Timeframe} + /// Output cells trigger record: {"CPV", "CELLSTR", 0, Lifetime::Timeframe} + /// Output HW errors: {"CPV", "RAWHWERRORS", 0, Lifetime::Timeframe} + void run(framework::ProcessingContext& ctx) final; + + protected: + /// \brief simple check of HW address + char CheckHWAddress(short ddl, short hwAddress, short& fee); + + private: + int mDDL = 15; + std::unique_ptr<CalibParams> mCalibParams; ///< CPV calibration + std::unique_ptr<BadChannelMap> mBadMap; ///< BadMap + std::vector<Digit> mOutputDigits; ///< Container with output cells + std::vector<TriggerRecord> mOutputTriggerRecords; ///< Container with output cells + std::vector<RawDecoderError> mOutputHWErrors; ///< Errors occured in reading data +}; + +/// \brief Creating DataProcessorSpec for the CPV Cell Converter Spec +/// +/// Refer to RawToDigitConverterSpec::run for input and output specs +o2::framework::DataProcessorSpec getRawToDigitConverterSpec(); + +} // namespace reco_workflow + +} // namespace cpv + +} // namespace o2 diff --git a/Detectors/CPV/workflow/src/ClusterizerSpec.cxx b/Detectors/CPV/workflow/src/ClusterizerSpec.cxx index 88d79e6bbeca9..7a6ab4cde247f 100644 --- a/Detectors/CPV/workflow/src/ClusterizerSpec.cxx +++ b/Detectors/CPV/workflow/src/ClusterizerSpec.cxx @@ -23,41 +23,37 @@ void ClusterizerSpec::init(framework::InitContext& ctx) // Initialize clusterizer and link geometry mClusterizer.initialize(); + mClusterizer.propagateMC(mPropagateMC); } void ClusterizerSpec::run(framework::ProcessingContext& ctx) { - if (ctx.inputs().isValid("digits")) { - LOG(DEBUG) << "CPVClusterizer - run on digits called"; + LOG(INFO) << "Start run "; + LOG(DEBUG) << "CPVClusterizer - run on digits called"; + auto digits = ctx.inputs().get<gsl::span<Digit>>("digits"); + // auto digitsTR = ctx.inputs().get<std::span<TriggerRecord>>("digitTriggerRecords"); //TODO:: Why span does not work??? + // auto digits = ctx.inputs().get<std::vector<o2::cpv::Digit>>("digits"); + auto digitsTR = ctx.inputs().get<std::vector<o2::cpv::TriggerRecord>>("digitTriggerRecords"); - auto dataref = ctx.inputs().get("digits"); - auto const* cpvheader = o2::framework::DataRefUtils::getHeader<o2::cpv::CPVBlockHeader*>(dataref); - if (!cpvheader->mHasPayload) { - LOG(DEBUG) << "[CPVClusterizer - run] No more digits" << std::endl; - ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); - return; - } + // printf("CluSpec: digits=%d, TR=%d \n",digits.size(),digitsTR.size()) ; - // auto digits = ctx.inputs().get<gsl::span<o2::cpv::Digit>>("digits"); - auto digits = ctx.inputs().get<std::vector<o2::cpv::Digit>>("digits"); - auto digitsTR = ctx.inputs().get<std::vector<o2::cpv::TriggerRecord>>("digitTriggerRecords"); - - LOG(DEBUG) << "[CPVClusterizer - run] Received " << digitsTR.size() << " TR, running clusterizer ..."; - auto truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("digitsmctr"); - mClusterizer.process(digits, digitsTR, truthcont.get(), &mOutputClusters, &mOutputClusterTrigRecs, &mOutputTruthCont); // Find clusters on digits (pass by ref) + LOG(DEBUG) << "[CPVClusterizer - run] Received " << digitsTR.size() << " TR, running clusterizer ..."; + std::unique_ptr<const o2::dataformats::MCTruthContainer<MCCompLabel>> truthcont; + if (mPropagateMC) { + truthcont = ctx.inputs().get<o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>("digitsmctr"); } - LOG(DEBUG) << "[CPVClusterizer - run] Writing " << mOutputClusters.size() << " clusters, " << mOutputClusterTrigRecs.size() << "TR and " << mOutputTruthCont.getIndexedSize() << " Labels"; + mClusterizer.process(digits, digitsTR, *truthcont, &mOutputClusters, &mOutputClusterTrigRecs, &mOutputTruthCont); // Find clusters on digits (pass by ref) + ctx.outputs().snapshot(o2::framework::Output{"CPV", "CLUSTERS", 0, o2::framework::Lifetime::Timeframe}, mOutputClusters); ctx.outputs().snapshot(o2::framework::Output{"CPV", "CLUSTERTRIGRECS", 0, o2::framework::Lifetime::Timeframe}, mOutputClusterTrigRecs); if (mPropagateMC) { ctx.outputs().snapshot(o2::framework::Output{"CPV", "CLUSTERTRUEMC", 0, o2::framework::Lifetime::Timeframe}, mOutputTruthCont); } - LOG(INFO) << "Finished "; + LOG(INFO) << "Finished, wrote " << mOutputClusters.size() << " clusters, " << mOutputClusterTrigRecs.size() << "TR and " << mOutputTruthCont.getIndexedSize() << " Labels"; ctx.services().get<o2::framework::ControlService>().endOfStream(); ctx.services().get<o2::framework::ControlService>().readyToQuit(framework::QuitRequest::Me); } - o2::framework::DataProcessorSpec o2::cpv::reco_workflow::getClusterizerSpec(bool propagateMC) { std::vector<o2::framework::InputSpec> inputs; diff --git a/Detectors/CPV/workflow/src/EntropyDecoderSpec.cxx b/Detectors/CPV/workflow/src/EntropyDecoderSpec.cxx new file mode 100644 index 0000000000000..1b696185f7dbd --- /dev/null +++ b/Detectors/CPV/workflow/src/EntropyDecoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyDecoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "CPVWorkflow/EntropyDecoderSpec.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace cpv +{ + +EntropyDecoderSpec::EntropyDecoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("cpv-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Decoder); + } +} + +void EntropyDecoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + + auto buff = pc.inputs().get<gsl::span<o2::ctf::BufferType>>("ctf"); + + auto& triggers = pc.outputs().make<std::vector<TriggerRecord>>(OutputRef{"triggers"}); + auto& clusters = pc.outputs().make<std::vector<Cluster>>(OutputRef{"clusters"}); + + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + const auto ctfImage = o2::cpv::CTF::getImage(buff.data()); + mCTFCoder.decode(ctfImage, triggers, clusters); + + mTimer.Stop(); + LOG(INFO) << "Decoded " << clusters.size() << " CPV clusters in " << triggers.size() << " triggers in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "CPV Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyDecoderSpec() +{ + std::vector<OutputSpec> outputs{ + OutputSpec{{"triggers"}, "CPV", "CLUSTERTRIGRECS", 0, Lifetime::Timeframe}, + OutputSpec{{"clusters"}, "CPV", "CLUSTERS", 0, Lifetime::Timeframe}}; + + return DataProcessorSpec{ + "cpv-entropy-decoder", + Inputs{InputSpec{"ctf", "CPV", "CTFDATA", 0, Lifetime::Timeframe}}, + outputs, + AlgorithmSpec{adaptFromTask<EntropyDecoderSpec>()}, + Options{{"cpv-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF decoding dictionary"}}}}; +} + +} // namespace cpv +} // namespace o2 diff --git a/Detectors/CPV/workflow/src/EntropyEncoderSpec.cxx b/Detectors/CPV/workflow/src/EntropyEncoderSpec.cxx new file mode 100644 index 0000000000000..95588b1f45e77 --- /dev/null +++ b/Detectors/CPV/workflow/src/EntropyEncoderSpec.cxx @@ -0,0 +1,79 @@ +// 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 EntropyEncoderSpec.cxx + +#include <vector> + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "CPVWorkflow/EntropyEncoderSpec.h" +#include "DetectorsCommonDataFormats/DetID.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace cpv +{ + +EntropyEncoderSpec::EntropyEncoderSpec() +{ + mTimer.Stop(); + mTimer.Reset(); +} + +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +{ + std::string dictPath = ic.options().get<std::string>("cpv-ctf-dictionary"); + if (!dictPath.empty() && dictPath != "none") { + mCTFCoder.createCoders(dictPath, o2::ctf::CTFCoderBase::OpType::Encoder); + } +} + +void EntropyEncoderSpec::run(ProcessingContext& pc) +{ + auto cput = mTimer.CpuTime(); + mTimer.Start(false); + auto triggers = pc.inputs().get<gsl::span<TriggerRecord>>("triggers"); + auto clusters = pc.inputs().get<gsl::span<Cluster>>("clusters"); + + auto& buffer = pc.outputs().make<std::vector<o2::ctf::BufferType>>(Output{"CPV", "CTFDATA", 0, Lifetime::Timeframe}); + mCTFCoder.encode(buffer, triggers, clusters); + auto eeb = CTF::get(buffer.data()); // cast to container pointer + eeb->compactify(); // eliminate unnecessary padding + buffer.resize(eeb->size()); // shrink buffer to strictly necessary size + // eeb->print(); + mTimer.Stop(); + LOG(INFO) << "Created encoded data of size " << eeb->size() << " for CPV in " << mTimer.CpuTime() - cput << " s"; +} + +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +{ + LOGF(INFO, "CPV Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", + mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); +} + +DataProcessorSpec getEntropyEncoderSpec() +{ + std::vector<InputSpec> inputs; + inputs.emplace_back("triggers", "CPV", "CLUSTERTRIGRECS", 0, Lifetime::Timeframe); + inputs.emplace_back("clusters", "CPV", "CLUSTERS", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "cpv-entropy-encoder", + inputs, + Outputs{{"CPV", "CTFDATA", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask<EntropyEncoderSpec>()}, + Options{{"cpv-ctf-dictionary", VariantType::String, "ctf_dictionary.root", {"File of CTF encoding dictionary"}}}}; +} + +} // namespace cpv +} // namespace o2 diff --git a/Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx b/Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx new file mode 100644 index 0000000000000..219e19ccb6248 --- /dev/null +++ b/Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx @@ -0,0 +1,212 @@ +// 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 <string> +#include "FairLogger.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "Framework/InputRecordWalker.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" +#include "DataFormatsCPV/CPVBlockHeader.h" +#include "DataFormatsCPV/TriggerRecord.h" +#include "DetectorsRaw/RDHUtils.h" +#include "CPVReconstruction/RawDecoder.h" +#include "CPVWorkflow/RawToDigitConverterSpec.h" +#include "CCDB/CcdbApi.h" +#include "CPVBase/CPVSimParams.h" +#include "CPVBase/Geometry.h" + +using namespace o2::cpv::reco_workflow; + +void RawToDigitConverterSpec::init(framework::InitContext& ctx) +{ + mDDL = ctx.options().get<int>("DDL"); + LOG(DEBUG) << "Initialize converter "; +} + +void RawToDigitConverterSpec::run(framework::ProcessingContext& ctx) +{ + // Cache digits from bunch crossings as the component reads timeframes from many links consecutively + std::map<o2::InteractionRecord, std::shared_ptr<std::vector<o2::cpv::Digit>>> digitBuffer; // Internal digit buffer + int firstEntry = 0; + mOutputHWErrors.clear(); + + if (!mCalibParams) { + if (o2::cpv::CPVSimParams::Instance().mCCDBPath.compare("localtest") == 0) { + mCalibParams = std::make_unique<o2::cpv::CalibParams>(1); // test default calibration + LOG(INFO) << "No reading calibration from ccdb requested, set default"; + } else { + LOG(INFO) << "Getting calibration object from ccdb"; + //TODO: configuring ccdb address from config file, readign proper calibration/BadMap and updateing if necessary + o2::ccdb::CcdbApi ccdb; + std::map<std::string, std::string> metadata; + ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation + // auto tr = triggerbranch.begin(); + // double eventTime = -1; + // if(tr!=triggerbranch.end()){ + // eventTime = (*tr).getBCData().getTimeNS() ; + // } + // mCalibParams = ccdb.retrieveFromTFileAny<o2::cpv::CalibParams>("CPV/Calib", metadata, eventTime); + // if (!mCalibParams) { + // LOG(FATAL) << "Can not get calibration object from ccdb"; + // } + } + } + + if (!mBadMap) { + if (o2::cpv::CPVSimParams::Instance().mCCDBPath.compare("localtest") == 0) { + mBadMap = std::make_unique<o2::cpv::BadChannelMap>(1); // test default calibration + LOG(INFO) << "No reading bad map from ccdb requested, set default"; + } else { + LOG(INFO) << "Getting bad map object from ccdb"; + o2::ccdb::CcdbApi ccdb; + std::map<std::string, std::string> metadata; + ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation + // auto tr = triggerbranch.begin(); + // double eventTime = -1; + // if(tr!=triggerbranch.end()){ + // eventTime = (*tr).getBCData().getTimeNS() ; + // } + // mBadMap = ccdb.retrieveFromTFileAny<o2::cpv::BadChannelMap>("CPV/BadMap", metadata, eventTime); + // if (!mBadMap) { + // LOG(FATAL) << "Can not get bad map object from ccdb"; + // } + } + } + + for (const auto& rawData : framework::InputRecordWalker(ctx.inputs())) { + + // enum RawErrorType_t { + // kOK, ///< NoError + // kNO_PAYLOAD, ///< No payload per ddl + // kHEADER_DECODING, + // kPAGE_NOTFOUND, + // kPAYLOAD_DECODING, + // kHEADER_INVALID, + // kRCU_TRAILER_ERROR, ///< RCU trailer cannot be decoded or invalid + // kRCU_VERSION_ERROR, ///< RCU trailer version not matching with the version in the raw header + // kRCU_TRAILER_SIZE_ERROR, ///< RCU trailer size length + // kSEGMENT_HEADER_ERROR, + // kROW_HEADER_ERROR, + // kEOE_HEADER_ERROR, + // kPADERROR, + // kPadAddress + // }; + + o2::cpv::RawReaderMemory rawreader(o2::framework::DataRefUtils::as<const char>(rawData)); + // loop over all the DMA pages + while (rawreader.hasNext()) { + try { + rawreader.next(); + } catch (RawErrorType_t e) { + LOG(ERROR) << "Raw decoding error " << (int)e; + //add error list + mOutputHWErrors.emplace_back(5, 0, 0, 0, e); //Put general errors to non-existing DDL5 + //if problem in header, abandon this page + if (e == RawErrorType_t::kPAGE_NOTFOUND || + e == RawErrorType_t::kHEADER_DECODING || + e == RawErrorType_t::kHEADER_INVALID) { + break; + } + //if problem in payload, try to continue + continue; + } + auto& header = rawreader.getRawHeader(); + auto triggerBC = o2::raw::RDHUtils::getTriggerBC(header); + auto triggerOrbit = o2::raw::RDHUtils::getTriggerOrbit(header); + auto ddl = o2::raw::RDHUtils::getFEEID(header); + ddl -= mDDL; + + o2::InteractionRecord currentIR(triggerBC, triggerOrbit); + std::shared_ptr<std::vector<o2::cpv::Digit>> currentDigitContainer; + auto found = digitBuffer.find(currentIR); + if (found == digitBuffer.end()) { + currentDigitContainer = std::make_shared<std::vector<o2::cpv::Digit>>(); + digitBuffer[currentIR] = currentDigitContainer; + } else { + currentDigitContainer = found->second; + } + // + if (ddl > o2::cpv::Geometry::kNDDL) { //only 4 correct DDLs + LOG(ERROR) << "DDL=" << ddl; + mOutputHWErrors.emplace_back(6, ddl, 0, 0, kHEADER_INVALID); //Add non-existing DDL as DDL 5 + continue; //skip STU ddl + } + // use the altro decoder to decode the raw data, and extract the RCU trailer + o2::cpv::RawDecoder decoder(rawreader); + RawErrorType_t err = decoder.decode(); + + if (err != kOK) { + //TODO handle severe errors + //TODO: probably careful conversion of decoder errors to Fitter errors? + mOutputHWErrors.emplace_back(ddl, 1, 0, 0, err); //assign general header errors to non-existing FEE 16 + } + // Loop over all the channels + for (uint32_t adch : decoder.getDigits()) { + AddressCharge ac = {adch}; + unsigned short absId = ac.Address; + //test bad map + if (mBadMap->isChannelGood(absId)) { + if (ac.Charge > o2::cpv::CPVSimParams::Instance().mZSthreshold) { + float amp = mCalibParams->getGain(absId) * ac.Charge; + currentDigitContainer->emplace_back(absId, amp, -1); + } + } + } + //Check and send list of hwErrors + for (auto& er : decoder.getErrors()) { + mOutputHWErrors.push_back(er); + } + } //RawReader::hasNext + } + + // Loop over BCs, sort digits with increasing digit ID and write to output containers + mOutputDigits.clear(); + mOutputTriggerRecords.clear(); + for (auto [bc, digits] : digitBuffer) { + int prevDigitSize = mOutputDigits.size(); + if (digits->size()) { + // Sort digits according to digit ID + std::sort(digits->begin(), digits->end(), [](o2::cpv::Digit& lhs, o2::cpv::Digit& rhs) { return lhs.getAbsId() < rhs.getAbsId(); }); + + for (auto digit : *digits) { + mOutputDigits.push_back(digit); + } + } + + mOutputTriggerRecords.emplace_back(bc, prevDigitSize, mOutputDigits.size() - prevDigitSize); + } + digitBuffer.clear(); + + LOG(INFO) << "[CPVRawToDigitConverter - run] Writing " << mOutputDigits.size() << " digits ..."; + ctx.outputs().snapshot(o2::framework::Output{"CPV", "DIGITS", 0, o2::framework::Lifetime::Timeframe}, mOutputDigits); + ctx.outputs().snapshot(o2::framework::Output{"CPV", "DIGITTRIGREC", 0, o2::framework::Lifetime::Timeframe}, mOutputTriggerRecords); + ctx.outputs().snapshot(o2::framework::Output{"CPV", "RAWHWERRORS", 0, o2::framework::Lifetime::Timeframe}, mOutputHWErrors); +} + +o2::framework::DataProcessorSpec o2::cpv::reco_workflow::getRawToDigitConverterSpec() +{ + std::vector<o2::framework::InputSpec> inputs; + inputs.emplace_back("RAWDATA", o2::framework::ConcreteDataTypeMatcher{"CPV", "RAWDATA"}, o2::framework::Lifetime::Timeframe); + + std::vector<o2::framework::OutputSpec> outputs; + outputs.emplace_back("CPV", "DIGITS", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("CPV", "DIGITTRIGREC", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("CPV", "RAWHWERRORS", 0, o2::framework::Lifetime::Timeframe); + + return o2::framework::DataProcessorSpec{"CPVRawToDigitConverterSpec", + inputs, // o2::framework::select("A:CPV/RAWDATA"), + outputs, + o2::framework::adaptFromTask<o2::cpv::reco_workflow::RawToDigitConverterSpec>(), + o2::framework::Options{ + {"pedestal", o2::framework::VariantType::String, "off", {"Analyze as pedestal run on/off"}}, + {"DDL", o2::framework::VariantType::String, "0", {"DDL id to read"}}, + }}; +} diff --git a/Detectors/CPV/workflow/src/RecoWorkflow.cxx b/Detectors/CPV/workflow/src/RecoWorkflow.cxx index 82bc452753350..f46a9614b5e37 100644 --- a/Detectors/CPV/workflow/src/RecoWorkflow.cxx +++ b/Detectors/CPV/workflow/src/RecoWorkflow.cxx @@ -24,8 +24,8 @@ #include "DataFormatsCPV/TriggerRecord.h" #include "CPVWorkflow/RecoWorkflow.h" #include "CPVWorkflow/ClusterizerSpec.h" -#include "CPVWorkflow/DigitsPrinterSpec.h" #include "CPVWorkflow/PublisherSpec.h" +#include "CPVWorkflow/RawToDigitConverterSpec.h" //#include "CPVWorkflow/RawWriterSpec.h" #include "Framework/DataSpecUtils.h" #include "SimulationDataFormat/MCTruthContainer.h" @@ -83,21 +83,29 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, // specs.emplace_back(o2::cpv::reco_workflow::getRawWriterSpec()); // } - if (inputType == InputType::Digits) { - specs.emplace_back(o2::cpv::getPublisherSpec(PublisherConf{ - "cpv-digit-reader", - "o2sim", - {"digitbranch", "CPVDigit", "Digit branch"}, - {"digittrigger", "CPVDigitTrigRecords", "TrigRecords branch"}, - {"mcbranch", "CPVDigitMCTruth", "MC label branch"}, - o2::framework::OutputSpec{"CPV", "DIGITS"}, - o2::framework::OutputSpec{"CPV", "DIGITTRIGREC"}, - o2::framework::OutputSpec{"CPV", "DIGITSMCTR"}}, - propagateMC)); - - if (enableDigitsPrinter) { - specs.emplace_back(o2::cpv::reco_workflow::getPhosDigitsPrinterSpec()); + if (inputType == InputType::Raw) { + //no explicit raw reader + + if (isEnabled(OutputType::Digits)) { + specs.emplace_back(o2::cpv::reco_workflow::getRawToDigitConverterSpec()); } + } + + if (inputType == InputType::Digits) { + // specs.emplace_back(o2::cpv::getPublisherSpec(PublisherConf{ + // "cpv-digit-reader", + // "o2sim", + // {"digitbranch", "CPVDigit", "Digit branch"}, + // {"digittrigger", "CPVDigitTrigRecords", "TrigRecords branch"}, + // {"mcbranch", "CPVDigitMCTruth", "MC label branch"}, + // o2::framework::OutputSpec{"CPV", "DIGITS"}, + // o2::framework::OutputSpec{"CPV", "DIGITTRIGREC"}, + // o2::framework::OutputSpec{"CPV", "DIGITSMCTR"}}, + // propagateMC)); + + // if (enableDigitsPrinter) { + // specs.emplace_back(o2::cpv::reco_workflow::getDigitsPrinterSpec()); + // } if (isEnabled(OutputType::Clusters)) { // add clusterizer @@ -110,104 +118,56 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, // } } - // check if the process is ready to quit - // this is decided upon the meta information in the CPV block header, the operation is set - // value kNoPayload in case of no data or no operation - // see also PublisherSpec.cxx - // in this workflow, the EOD is sent after the last real data, and all inputs will receive EOD, - // so it is enough to check on the first occurence - // FIXME: this will be changed once DPL can propagate control events like EOD - auto checkReady = [](o2::framework::DataRef const& ref) { - auto const* cpvheader = o2::framework::DataRefUtils::getHeader<o2::cpv::CPVBlockHeader*>(ref); - // sector number -1 indicates end-of-data - if (cpvheader != nullptr) { - // indicate normal processing if not ready and skip if ready - if (!cpvheader->mHasPayload) { - return std::make_tuple(o2::framework::MakeRootTreeWriterSpec::TerminationCondition::Action::SkipProcessing, true); - } - } - return std::make_tuple(o2::framework::MakeRootTreeWriterSpec::TerminationCondition::Action::DoProcessing, false); - }; - - // auto makeWriterSpec = [propagateMC, checkReady](const char* processName, - // const char* defaultFileName, - // const char* defaultTreeName, - // bool createMCMap, - // auto&& databranch, - // auto&& datatrbranch, - // auto&& mcbranch=nullptr, - // auto&& mcmapbranch=nullptr) { - // // depending on the MC propagation flag, the RootTreeWriter spec is created with two - // // or one branch definition - // if (propagateMC) { - // if(createMCMap){ - // return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, - // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - // std::move(databranch), - // std::move(datatrbranch), - // std::move(mcbranch), - // std::move(mcmapbranch))); + // // check if the process is ready to quit + // // this is decided upon the meta information in the CPV block header, the operation is set + // // value kNoPayload in case of no data or no operation + // // see also PublisherSpec.cxx + // // in this workflow, the EOD is sent after the last real data, and all inputs will receive EOD, + // // so it is enough to check on the first occurence + // // FIXME: this will be changed once DPL can propagate control events like EOD + // auto checkReady = [](o2::framework::DataRef const& ref) { + // auto const* cpvheader = o2::framework::DataRefUtils::getHeader<o2::cpv::CPVBlockHeader*>(ref); + // // sector number -1 indicates end-of-data + // if (cpvheader != nullptr) { + // // indicate normal processing if not ready and skip if ready + // if (!cpvheader->mHasPayload) { + // return std::make_tuple(o2::framework::MakeRootTreeWriterSpec::TerminationCondition::Action::SkipProcessing, true); // } - // else{ - // return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, - // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - // std::move(databranch), - // std::move(datatrbranch), - // std::move(mcbranch))); - // } - // } - // else{ - // return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, - // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - // std::move(databranch), - // std::move(datatrbranch))); // } + // return std::make_tuple(o2::framework::MakeRootTreeWriterSpec::TerminationCondition::Action::DoProcessing, false); // }; - // if (isEnabled(OutputType::Raw)) { - // using RawOutputType = std::vector<o2::cpv::Raw>; - // specs.push_back(makeWriterSpec("cpv-raw-writer", - // inputType == InputType::Digits ? "cpv-raw.root" : "cpvrawcells.root", - // "o2sim", - // BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "CPV", "RAW", 0}, - // "CPVRaw", - // "raw-branch-name"}, - // BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "CPV", "RAWMCTR", 0}, - // "CPVRawMCTruth", - // "rawmc-branch-name"})()); - // } + // if (isEnabled(OutputType::Digits)) { + // using DigitOutputType = std::vector<o2::cpv::Digit>; + // using DTROutputType = std::vector<o2::cpv::TriggerRecord>; - if (isEnabled(OutputType::Digits)) { - using DigitOutputType = std::vector<o2::cpv::Digit>; - using DTROutputType = std::vector<o2::cpv::TriggerRecord>; - - specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("cpv-digits-writer", "cpvdigits.root", "o2sim", - -1, - o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "CPV", "DIGITS", 0}, - "CPVDigit", - "digit-branch-name"}, - BranchDefinition<DTROutputType>{o2::framework::InputSpec{"data", "CPV", "DIGITTRIGREC", 0}, - "CPVDigTR", - "digittr-branch-name"}, - BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "CPV", "DIGITSMCTR", 0}, - "CPVDigitMCTruth", - "digitmc-branch-name"})()); - } + // specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("cpv-digits-writer", "cpvdigits.root", "o2sim", + // -1, + // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, + // BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "CPV", "DIGITS", 0}, + // "CPVDigit", + // "digit-branch-name"}, + // BranchDefinition<DTROutputType>{o2::framework::InputSpec{"data", "CPV", "DIGITTRIGREC", 0}, + // "CPVDigTR", + // "digittr-branch-name"}, + // BranchDefinition<MCLabelContainer>{o2::framework::InputSpec{"mc", "CPV", "DIGITSMCTR", 0}, + // "CPVDigitMCTruth", + // "digitmc-branch-name"})()); + // } - if (isEnabled(OutputType::Clusters)) { - specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("cpv-clusters-writer", "cpvclusters.root", "o2sim", -1, - o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, - BranchDefinition<std::vector<o2::cpv::Cluster>>{o2::framework::InputSpec{"data", "CPV", "CLUSTERS", 0}, - "CPVCluster", - "cluster-branch-name"}, - BranchDefinition<std::vector<o2::cpv::TriggerRecord>>{o2::framework::InputSpec{"datatr", "CPV", "CLUSTERTRIGRECS", 0}, - "CPVClusTR", - "clustertr-branch-name"}, - BranchDefinition<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>{o2::framework::InputSpec{"mc", "CPV", "CLUSTERTRUEMC", 0}, - "CPVClusMC", - "clustermc-branch-name"})()); - } + // if (isEnabled(OutputType::Clusters)) { + // specs.emplace_back(o2::framework::MakeRootTreeWriterSpec("cpv-clusters-writer", "cpvclusters.root", "o2sim", -1, + // o2::framework::MakeRootTreeWriterSpec::TerminationCondition{checkReady}, + // BranchDefinition<std::vector<o2::cpv::Cluster>>{o2::framework::InputSpec{"data", "CPV", "CLUSTERS", 0}, + // "CPVCluster", + // "cluster-branch-name"}, + // BranchDefinition<std::vector<o2::cpv::TriggerRecord>>{o2::framework::InputSpec{"datatr", "CPV", "CLUSTERTRIGRECS", 0}, + // "CPVClusTR", + // "clustertr-branch-name"}, + // BranchDefinition<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>{o2::framework::InputSpec{"mc", "CPV", "CLUSTERTRUEMC", 0}, + // "CPVClusMC", + // "clustermc-branch-name"})()); + // } return std::move(specs); } diff --git a/Detectors/CPV/workflow/src/entropy-encoder-workflow.cxx b/Detectors/CPV/workflow/src/entropy-encoder-workflow.cxx new file mode 100644 index 0000000000000..5c43f8af68991 --- /dev/null +++ b/Detectors/CPV/workflow/src/entropy-encoder-workflow.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. + +#include "CPVWorkflow/EntropyEncoderSpec.h" +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/ConfigParamSpec.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + // option allowing to set parameters + std::vector<ConfigParamSpec> options{ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec wf; + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(cfgc.options().get<std::string>("configKeyValues")); + wf.emplace_back(o2::cpv::getEntropyEncoderSpec()); + return wf; +} diff --git a/Detectors/CTF/CMakeLists.txt b/Detectors/CTF/CMakeLists.txt index 4daff377c664c..5565515a769fe 100644 --- a/Detectors/CTF/CMakeLists.txt +++ b/Detectors/CTF/CMakeLists.txt @@ -76,8 +76,16 @@ o2_add_test(emcal o2_add_test(phos PUBLIC_LINK_LIBRARIES O2::CTFWorkflow - O2::DataFormatsEMCAL + O2::DataFormatsPHOS O2::PHOSReconstruction SOURCES test/test_ctf_io_phos.cxx COMPONENT_NAME ctf LABELS ctf) + +o2_add_test(cpv + PUBLIC_LINK_LIBRARIES O2::CTFWorkflow + O2::DataFormatsCPV + O2::CPVReconstruction + SOURCES test/test_ctf_io_cpv.cxx + COMPONENT_NAME ctf + LABELS ctf) diff --git a/Detectors/CTF/test/test_ctf_io_cpv.cxx b/Detectors/CTF/test/test_ctf_io_cpv.cxx new file mode 100644 index 0000000000000..b60131e60c851 --- /dev/null +++ b/Detectors/CTF/test/test_ctf_io_cpv.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. + +#define BOOST_TEST_MODULE Test CPVCTFIO +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> +#include "DetectorsCommonDataFormats/NameConf.h" +#include "CPVReconstruction/CTFCoder.h" +#include "DataFormatsCPV/CTF.h" +#include "Framework/Logger.h" +#include <TFile.h> +#include <TRandom.h> +#include <TStopwatch.h> +#include <TSystem.h> +#include <cstring> + +using namespace o2::cpv; + +BOOST_AUTO_TEST_CASE(CTFTest) +{ + std::vector<TriggerRecord> triggers; + std::vector<Cluster> clusters; + TStopwatch sw; + sw.Start(); + o2::InteractionRecord ir(0, 0); + Cluster clu; + for (int irof = 0; irof < 1000; irof++) { + ir += 1 + gRandom->Integer(200); + + auto start = clusters.size(); + int n = 1 + gRandom->Poisson(100); + for (int i = n; i--;) { + char mult = gRandom->Integer(30); + char mod = 1 + gRandom->Integer(3); + char exMax = gRandom->Integer(3); + float x = 72.3 * 2. * (gRandom->Rndm() - 0.5); + float z = 63.3 * 2. * (gRandom->Rndm() - 0.5); + float e = 254. * gRandom->Rndm(); + clusters.emplace_back(mult, mod, exMax, x, z, e); + } + triggers.emplace_back(ir, start, clusters.size() - start); + } + + sw.Start(); + std::vector<o2::ctf::BufferType> vec; + { + CTFCoder coder; + coder.encode(vec, triggers, clusters); // compress + } + sw.Stop(); + LOG(INFO) << "Compressed in " << sw.CpuTime() << " s"; + + // writing + { + sw.Start(); + auto* ctfImage = o2::cpv::CTF::get(vec.data()); + TFile flOut("test_ctf_cpv.root", "recreate"); + TTree ctfTree(std::string(o2::base::NameConf::CTFTREENAME).c_str(), "O2 CTF tree"); + ctfImage->print(); + ctfImage->appendToTree(ctfTree, "CPV"); + ctfTree.Write(); + sw.Stop(); + LOG(INFO) << "Wrote to tree in " << sw.CpuTime() << " s"; + } + + // reading + vec.clear(); + LOG(INFO) << "Start reading from tree "; + { + sw.Start(); + TFile flIn("test_ctf_cpv.root"); + std::unique_ptr<TTree> tree((TTree*)flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str())); + BOOST_CHECK(tree); + o2::cpv::CTF::readFromTree(vec, *(tree.get()), "CPV"); + sw.Stop(); + LOG(INFO) << "Read back from tree in " << sw.CpuTime() << " s"; + } + + std::vector<TriggerRecord> triggersD; + std::vector<Cluster> clustersD; + + sw.Start(); + const auto ctfImage = o2::cpv::CTF::getImage(vec.data()); + { + CTFCoder coder; + coder.decode(ctfImage, triggersD, clustersD); // decompress + } + sw.Stop(); + LOG(INFO) << "Decompressed in " << sw.CpuTime() << " s"; + + BOOST_CHECK(triggersD.size() == triggers.size()); + BOOST_CHECK(clustersD.size() == clusters.size()); + LOG(INFO) << " BOOST_CHECK triggersD.size() " << triggersD.size() << " triggers.size() " << triggers.size() + << " BOOST_CHECK(clustersD.size() " << clustersD.size() << " clusters.size()) " << clusters.size(); + + for (size_t i = 0; i < triggers.size(); i++) { + const auto& dor = triggers[i]; + const auto& ddc = triggersD[i]; + LOG(DEBUG) << " Orig.TriggerRecord " << i << " " << dor.getBCData() << " " << dor.getFirstEntry() << " " << dor.getNumberOfObjects(); + LOG(DEBUG) << " Deco.TriggerRecord " << i << " " << ddc.getBCData() << " " << ddc.getFirstEntry() << " " << ddc.getNumberOfObjects(); + + BOOST_CHECK(dor.getBCData() == ddc.getBCData()); + BOOST_CHECK(dor.getNumberOfObjects() == ddc.getNumberOfObjects()); + BOOST_CHECK(dor.getFirstEntry() == dor.getFirstEntry()); + } + + for (size_t i = 0; i < clusters.size(); i++) { + const auto& cor = clusters[i]; + const auto& cdc = clustersD[i]; + BOOST_CHECK(cor.getMultiplicity() == cdc.getMultiplicity()); + BOOST_CHECK(cor.getModule() == cdc.getModule()); + BOOST_CHECK(TMath::Abs(cor.getEnergy() - cdc.getEnergy()) < 1.); + float xCor, zCor, xCdc, zCdc; + cor.getLocalPosition(xCor, zCor); + cdc.getLocalPosition(xCdc, zCdc); + BOOST_CHECK(TMath::Abs(xCor - xCdc) < 0.004); + BOOST_CHECK(TMath::Abs(zCor - zCdc) < 0.004); + } +} diff --git a/Detectors/CTF/workflow/CMakeLists.txt b/Detectors/CTF/workflow/CMakeLists.txt index 1bb7896c3dd2c..efc519308a0ac 100644 --- a/Detectors/CTF/workflow/CMakeLists.txt +++ b/Detectors/CTF/workflow/CMakeLists.txt @@ -20,6 +20,8 @@ o2_add_library(CTFWorkflow O2::DataFormatsFV0 O2::DataFormatsFDD O2::DataFormatsMID + O2::DataFormatsPHOS + O2::DataFormatsCPV O2::DataFormatsParameters O2::ITSMFTWorkflow O2::TPCWorkflow @@ -30,6 +32,7 @@ o2_add_library(CTFWorkflow O2::MIDWorkflow O2::EMCALWorkflow O2::PHOSWorkflow + O2::CPVWorkflow O2::Algorithm O2::CommonUtils) diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 1021128026b1f..740c335622808 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -32,6 +32,7 @@ #include "DataFormatsMID/CTF.h" #include "DataFormatsEMCAL/CTF.h" #include "DataFormatsPHOS/CTF.h" +#include "DataFormatsCPV/CTF.h" #include "Algorithm/RangeTokenizer.h" using namespace o2::framework; @@ -181,6 +182,13 @@ void CTFReaderSpec::run(ProcessingContext& pc) setFirstTFOrbit(det.getName()); } + det = DetID::CPV; + if (detsTF[det]) { + auto& bufVec = pc.outputs().make<std::vector<o2::ctf::BufferType>>({det.getName()}, sizeof(o2::cpv::CTF)); + o2::cpv::CTF::readFromTree(bufVec, *(tree.get()), det.getName()); + setFirstTFOrbit(det.getName()); + } + mTimer.Stop(); LOG(INFO) << "Read CTF " << inputFile << " in " << mTimer.CpuTime() - cput << " s"; diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index fefaa596bb84b..dafa122b38d41 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -29,6 +29,7 @@ #include "DataFormatsMID/CTF.h" #include "DataFormatsEMCAL/CTF.h" #include "DataFormatsPHOS/CTF.h" +#include "DataFormatsCPV/CTF.h" using namespace o2::framework; @@ -106,6 +107,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) processDet<o2::mid::CTF>(pc, DetID::MID, header, treeOut.get()); processDet<o2::emcal::CTF>(pc, DetID::EMC, header, treeOut.get()); processDet<o2::phos::CTF>(pc, DetID::PHS, header, treeOut.get()); + processDet<o2::cpv::CTF>(pc, DetID::CPV, header, treeOut.get()); mTimer.Stop(); @@ -177,6 +179,7 @@ void CTFWriterSpec::storeDictionaries() storeDictionary<o2::mid::CTF>(DetID::MID, header); storeDictionary<o2::emcal::CTF>(DetID::EMC, header); storeDictionary<o2::phos::CTF>(DetID::PHS, header); + storeDictionary<o2::cpv::CTF>(DetID::CPV, header); // close remnants if (mDictTreeOut) { closeDictionaryTreeAndFile(header); diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index b99922a7d02ac..14c552470b370 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -29,6 +29,7 @@ #include "MIDWorkflow/EntropyDecoderSpec.h" #include "EMCALWorkflow/EntropyDecoderSpec.h" #include "PHOSWorkflow/EntropyDecoderSpec.h" +#include "CPVWorkflow/EntropyDecoderSpec.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -100,6 +101,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets[DetID::PHS]) { specs.push_back(o2::phos::getEntropyDecoderSpec()); } + if (dets[DetID::CPV]) { + specs.push_back(o2::cpv::getEntropyDecoderSpec()); + } return std::move(specs); } diff --git a/Detectors/PHOS/base/src/RCUTrailer.cxx b/Detectors/PHOS/base/src/RCUTrailer.cxx index 5fbef81c6c62f..6295023ecbf53 100644 --- a/Detectors/PHOS/base/src/RCUTrailer.cxx +++ b/Detectors/PHOS/base/src/RCUTrailer.cxx @@ -11,6 +11,7 @@ #include <cmath> #include <iostream> #include <fmt/format.h> +#include "FairLogger.h" #include "CommonConstants/LHCConstants.h" #include "PHOSBase/RCUTrailer.h" @@ -60,7 +61,7 @@ void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payload for (; trailerSize > 0; trailerSize--) { word = payloadwords[--index]; if ((word >> 30) != 2) { - std::cerr << "Missing RCU trailer identifier pattern!\n"; + LOG(ERROR) << "Missing RCU trailer identifier pattern!"; continue; } int parCode = (word >> 26) & 0xF; @@ -96,7 +97,7 @@ void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payload mAltroCFG2 = parData & 0x1FFFFFF; break; default: - std::cerr << "Undefined parameter code " << parCode << ", ignore it !\n"; + LOG(ERROR) << "Undefined parameter code " << parCode << ", ignore it !"; break; } } diff --git a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx index 181d90107d010..5547ececcd2f0 100644 --- a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx @@ -80,6 +80,10 @@ void AltroDecoder::readChannels() auto& currentchannel = mChannels.back(); /// decode all words for channel int numberofwords = (currentchannel.getPayloadSize() + 2) / 3; + if (numberofwords > payloadend - currentpos) { + LOG(ERROR) << "Channel payload " << numberofwords << " larger than left in total " << payloadend - currentpos; + continue; + } std::vector<uint16_t> bunchwords; for (int iword = 0; iword < numberofwords; iword++) { currentword = buffer[currentpos++]; @@ -109,7 +113,8 @@ void AltroDecoder::readChannels() const std::vector<Channel>& AltroDecoder::getChannels() const { - if (!mChannelsInitialized) + if (!mChannelsInitialized) { throw AltroDecoderError::ErrorType_t::CHANNEL_ERROR; // "Channels not initizalized"); + } return mChannels; } diff --git a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx index 4bde26c686859..27b67d7d7f2e6 100644 --- a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx +++ b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx @@ -576,7 +576,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // the CPV part if (isEnabled(o2::detectors::DetID::CPV)) { detList.emplace_back(o2::detectors::DetID::CPV); - // connect the PHOS digitization + // connect the CPV digitization specs.emplace_back(o2::cpv::getCPVDigitizerSpec(fanoutsize++, mctruth)); // add PHOS writer specs.emplace_back(o2::cpv::getCPVDigitWriterSpec(mctruth)); From 5b2bb0dfe736418b490d3e170afac44f5e84501c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Mon, 11 Jan 2021 14:01:11 +0100 Subject: [PATCH 1735/1751] embedding_pileup_check: don't assume 'view' label format --- macro/analyzeDigitLabels.C | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/macro/analyzeDigitLabels.C b/macro/analyzeDigitLabels.C index 19fc2d6129403..fddee682f9fb1 100644 --- a/macro/analyzeDigitLabels.C +++ b/macro/analyzeDigitLabels.C @@ -4,6 +4,8 @@ #include "TString.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include "DataFormatsPHOS/MCLabel.h" #include "DataFormatsFT0/MCLabel.h" #include "DataFormatsFDD/MCLabel.h" @@ -78,17 +80,30 @@ void analyse(TTree* tr, const char* brname, Accumulator& prop) if (!br) { return; } + auto classname = br->GetClassName(); auto entries = br->GetEntries(); - o2::dataformats::IOMCTruthContainerView* io2 = nullptr; - br->SetAddress(&io2); + if (strcmp("IOMCTruthContainerView", classname) == 0) { + o2::dataformats::IOMCTruthContainerView* io2 = nullptr; + br->SetAddress(&io2); - for (int i = 0; i < entries; ++i) { - br->GetEntry(i); - o2::dataformats::ConstMCTruthContainer<LabelType> labels; - io2->copyandflatten(labels); + for (int i = 0; i < entries; ++i) { + br->GetEntry(i); + o2::dataformats::ConstMCTruthContainer<LabelType> labels; + io2->copyandflatten(labels); - for (int i = 0; i < (int)labels.getIndexedSize(); ++i) { - prop.addLabels(labels.getLabels(i)); + for (int i = 0; i < (int)labels.getIndexedSize(); ++i) { + prop.addLabels(labels.getLabels(i)); + } + } + } else { + // standard MC truth container + o2::dataformats::MCTruthContainer<LabelType>* labels = nullptr; + br->SetAddress(&labels); + for (int i = 0; i < entries; ++i) { + br->GetEntry(i); + for (int i = 0; i < (int)labels->getIndexedSize(); ++i) { + prop.addLabels(labels->getLabels(i)); + } } } }; From 9a6b849535ea64d3c04762c5b52912d3659ef92a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 12 Jan 2021 08:59:13 +0100 Subject: [PATCH 1736/1751] Drop initial prototype of dataflow setup (#5032) --- Utilities/CMakeLists.txt | 1 - Utilities/DataFlow/CMakeLists.txt | 87 ----- .../doc/o2-subframebuilder-device.1.in | 48 --- .../doc/o2-timeframe-reader-device.1.in | 29 -- .../doc/o2-timeframe-writer-device.1.in | 29 -- .../include/DataFlow/EPNReceiverDevice.h | 68 ---- .../include/DataFlow/FLPSenderDevice.h | 72 ---- .../include/DataFlow/FakeTimeframeBuilder.h | 37 -- .../DataFlow/FakeTimeframeGeneratorDevice.h | 48 --- .../include/DataFlow/HeartbeatSampler.h | 70 ---- .../DataFlow/include/DataFlow/PayloadMerger.h | 131 ------- .../include/DataFlow/SubframeBuilderDevice.h | 139 ------- .../DataFlow/include/DataFlow/SubframeUtils.h | 50 --- .../include/DataFlow/TimeframeParser.h | 36 -- .../include/DataFlow/TimeframeReaderDevice.h | 50 --- .../DataFlow/TimeframeValidatorDevice.h | 45 --- .../include/DataFlow/TimeframeWriterDevice.h | 59 --- Utilities/DataFlow/run/CreateSetup.py | 200 ---------- Utilities/DataFlow/run/confBasicSetup.json | 97 ----- Utilities/DataFlow/run/confComplexSetup.json | 132 ------- Utilities/DataFlow/run/confComplexSetup2.json | 345 ------------------ Utilities/DataFlow/run/confFakeTimeframe.json | 72 ---- Utilities/DataFlow/run/startBasicSetup.sh | 13 - Utilities/DataFlow/run/startComplexSetup.sh | 24 -- Utilities/DataFlow/run/startComplexSetup2.sh | 36 -- .../DataFlow/run/startTimeframeExample.sh | 4 - Utilities/DataFlow/src/EPNReceiverDevice.cxx | 184 ---------- Utilities/DataFlow/src/FLPSenderDevice.cxx | 101 ----- .../DataFlow/src/FakeTimeframeBuilder.cxx | 119 ------ .../src/FakeTimeframeGeneratorDevice.cxx | 92 ----- Utilities/DataFlow/src/HeartbeatSampler.cxx | 59 --- .../DataFlow/src/SubframeBuilderDevice.cxx | 149 -------- Utilities/DataFlow/src/TimeframeParser.cxx | 204 ----------- .../DataFlow/src/TimeframeReaderDevice.cxx | 69 ---- .../DataFlow/src/TimeframeValidationTool.cxx | 65 ---- .../DataFlow/src/TimeframeValidatorDevice.cxx | 152 -------- .../DataFlow/src/TimeframeWriterDevice.cxx | 96 ----- Utilities/DataFlow/src/runEPNReceiver.cxx | 41 --- Utilities/DataFlow/src/runFLPSender.cxx | 36 -- .../src/runFakeTimeframeGeneratorDevice.cxx | 34 -- .../DataFlow/src/runHeartbeatSampler.cxx | 32 -- .../DataFlow/src/runSubframeBuilderDevice.cxx | 50 --- .../DataFlow/src/runTimeframeReaderDevice.cxx | 33 -- .../src/runTimeframeValidatorDevice.cxx | 29 -- .../DataFlow/src/runTimeframeWriterDevice.cxx | 45 --- .../DataFlow/test/test_PayloadMerger01.cxx | 83 ----- .../DataFlow/test/test_SubframeUtils01.cxx | 59 --- .../DataFlow/test/test_TimeframeParser.cxx | 60 --- 48 files changed, 3714 deletions(-) delete mode 100644 Utilities/DataFlow/CMakeLists.txt delete mode 100644 Utilities/DataFlow/doc/o2-subframebuilder-device.1.in delete mode 100644 Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in delete mode 100644 Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in delete mode 100644 Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h delete mode 100644 Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h delete mode 100644 Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h delete mode 100644 Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.h delete mode 100644 Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h delete mode 100644 Utilities/DataFlow/include/DataFlow/PayloadMerger.h delete mode 100644 Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h delete mode 100644 Utilities/DataFlow/include/DataFlow/SubframeUtils.h delete mode 100644 Utilities/DataFlow/include/DataFlow/TimeframeParser.h delete mode 100644 Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h delete mode 100644 Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h delete mode 100644 Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h delete mode 100755 Utilities/DataFlow/run/CreateSetup.py delete mode 100644 Utilities/DataFlow/run/confBasicSetup.json delete mode 100644 Utilities/DataFlow/run/confComplexSetup.json delete mode 100644 Utilities/DataFlow/run/confComplexSetup2.json delete mode 100644 Utilities/DataFlow/run/confFakeTimeframe.json delete mode 100755 Utilities/DataFlow/run/startBasicSetup.sh delete mode 100755 Utilities/DataFlow/run/startComplexSetup.sh delete mode 100755 Utilities/DataFlow/run/startComplexSetup2.sh delete mode 100755 Utilities/DataFlow/run/startTimeframeExample.sh delete mode 100644 Utilities/DataFlow/src/EPNReceiverDevice.cxx delete mode 100644 Utilities/DataFlow/src/FLPSenderDevice.cxx delete mode 100644 Utilities/DataFlow/src/FakeTimeframeBuilder.cxx delete mode 100644 Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx delete mode 100644 Utilities/DataFlow/src/HeartbeatSampler.cxx delete mode 100644 Utilities/DataFlow/src/SubframeBuilderDevice.cxx delete mode 100644 Utilities/DataFlow/src/TimeframeParser.cxx delete mode 100644 Utilities/DataFlow/src/TimeframeReaderDevice.cxx delete mode 100644 Utilities/DataFlow/src/TimeframeValidationTool.cxx delete mode 100644 Utilities/DataFlow/src/TimeframeValidatorDevice.cxx delete mode 100644 Utilities/DataFlow/src/TimeframeWriterDevice.cxx delete mode 100644 Utilities/DataFlow/src/runEPNReceiver.cxx delete mode 100644 Utilities/DataFlow/src/runFLPSender.cxx delete mode 100644 Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx delete mode 100644 Utilities/DataFlow/src/runHeartbeatSampler.cxx delete mode 100644 Utilities/DataFlow/src/runSubframeBuilderDevice.cxx delete mode 100644 Utilities/DataFlow/src/runTimeframeReaderDevice.cxx delete mode 100644 Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx delete mode 100644 Utilities/DataFlow/src/runTimeframeWriterDevice.cxx delete mode 100644 Utilities/DataFlow/test/test_PayloadMerger01.cxx delete mode 100644 Utilities/DataFlow/test/test_SubframeUtils01.cxx delete mode 100644 Utilities/DataFlow/test/test_TimeframeParser.cxx diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 1028a895cfe52..eb91bcfe5ac0a 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -10,7 +10,6 @@ add_subdirectory(aliceHLTwrapper) add_subdirectory(O2MessageMonitor) -add_subdirectory(DataFlow) add_subdirectory(DataSampling) add_subdirectory(Publishers) add_subdirectory(DataCompression) diff --git a/Utilities/DataFlow/CMakeLists.txt b/Utilities/DataFlow/CMakeLists.txt deleted file mode 100644 index 05e9e26bd0c31..0000000000000 --- a/Utilities/DataFlow/CMakeLists.txt +++ /dev/null @@ -1,87 +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. - -# the bucket contains the following dependencies - common_boost_bucket - Base - -# Headers - O2device - dl the 'dl' dependency is needed as the device -# boilerplate code in runSimpleMQStateMachine.h uses dlopen etc. Probably this -# hidden dependency can be avoided by including the to some compiled FairMQ -# library - -o2_add_library(DataFlow - SOURCES src/FakeTimeframeBuilder.cxx - src/FakeTimeframeGeneratorDevice.cxx - src/HeartbeatSampler.cxx - src/SubframeBuilderDevice.cxx - src/TimeframeParser.cxx - src/TimeframeReaderDevice.cxx - src/TimeframeValidatorDevice.cxx - src/TimeframeWriterDevice.cxx - src/EPNReceiverDevice.cxx - src/FLPSenderDevice.cxx - PUBLIC_LINK_LIBRARIES O2::Headers O2::TimeFrame FairMQ::FairMQ - O2::Device) - -o2_target_man_page(DataFlow NAME o2-timeframe-reader-device) -o2_target_man_page(DataFlow NAME o2-timeframe-writer-device) -o2_target_man_page(DataFlow NAME o2-subframebuilder-device) - -o2_add_executable(fake-timeframegenerator-device - SOURCES src/runFakeTimeframeGeneratorDevice - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(heartbeat-sampler - SOURCES src/runHeartbeatSampler - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(subframebuilder-device - SOURCES src/runSubframeBuilderDevice - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(timeframe-reader-device - SOURCES src/runTimeframeReaderDevice - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(timeframe-validator-device - SOURCES src/runTimeframeValidatorDevice - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(timeframe-writer-device - SOURCES src/runTimeframeWriterDevice - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(epn-receiver-device - SOURCES src/runEPNReceiver - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(flp-sender-device - SOURCES src/runFLPSender - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_executable(timeframe-validation-tool - SOURCES src/TimeframeValidationTool - PUBLIC_LINK_LIBRARIES O2::DataFlow) - -o2_add_test(TimeframeParser - SOURCES test/test_TimeframeParser - PUBLIC_LINK_LIBRARIES O2::DataFlow - COMPONENT_NAME dataflow - LABELS utils) - -o2_add_test(SubframeUtils01 - SOURCES test/test_SubframeUtils01 - PUBLIC_LINK_LIBRARIES O2::DataFlow - COMPONENT_NAME dataflow - LABELS utils) - -o2_add_test(PayloadMerger01 - SOURCES test/test_PayloadMerger01 - PUBLIC_LINK_LIBRARIES O2::DataFlow - COMPONENT_NAME dataflow - LABELS utils) diff --git a/Utilities/DataFlow/doc/o2-subframebuilder-device.1.in b/Utilities/DataFlow/doc/o2-subframebuilder-device.1.in deleted file mode 100644 index 653053997d842..0000000000000 --- a/Utilities/DataFlow/doc/o2-subframebuilder-device.1.in +++ /dev/null @@ -1,48 +0,0 @@ -.\" Manpage for o2-subframebuilder-device. -.TH AliceO2 1 "12 May 2017" "1.0" "o2-subframebuilder-device man page" - -.SH NAME - -o2-subframebuilder-device - aggregate HBF in input as a single STF - -.SH SYNOPSIS - -o2-subframebuilder-device [options] - -.SH DESCRIPTION - -o2-subframebuilder-device will take in input a number of HeartBeat Frames -(HBF) and merge them in a single STF, with a policy defined by the -passed options. - -.SH OPTIONS - ---self-triggered Time frame duration - -.TP 5 - ---in-chan-name [NAME] Name of the input channel - -.TP 5 - ---out-chan-name [NAME] Name of the output channel - -.TP 5 - ---detector-name [NAME] Name of detector as data source - -.TP 5 - ---flp-id arg [NAME] ID of the FLP used as data source - -.TP 5 - ---strip-hbf Strip HeartBeatHeader (HBH) & HeartBeatTrailer (HBT) from each HBF - -.SH SEE ALSO - -FLPSenderDEvice(1), o2-epn-receiver-device(1), o2-heartbeat-sampler(1), TimeframeValidator(1) - -.SH BUGS - -Lots of bugs diff --git a/Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in b/Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in deleted file mode 100644 index bdf460cadc976..0000000000000 --- a/Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in +++ /dev/null @@ -1,29 +0,0 @@ -.\" Manpage for o2-timeframe-reader-device. -.TH man 1 "12 May 2017" "1.0" "o2-timeframe-reader-device man page" - -.SH NAME - -o2-timeframe-reader-device - read a timeframe from disk - -.SH SYNOPSIS - -o2-timeframe-reader-device --input-file [FILE] - -.SH DESCRIPTION - -o2-timeframe-reader-device will read a Timeframe from the FILE on disk and streams it -via FairMQ - -.SH OPTIONS - -.TP 5 - ---input-file [FILE] the file to be streamed - -.SH SEE ALSO - -o2-timeframe-writer-device(1) - -.SH BUGS - -Lots of bugs diff --git a/Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in b/Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in deleted file mode 100644 index a4828d9f12d41..0000000000000 --- a/Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in +++ /dev/null @@ -1,29 +0,0 @@ -.\" Manpage for o2-timeframe-writer-device. -.TH man 1 "12 May 2017" "1.0" "o2-timeframe-writer-device man page" - -.SH NAME - -o2-timeframe-writer-device - writes a timeframe to disk - -.SH SYNOPSIS - -o2-timeframe-writer-device --input-file [FILE] - -.SH DESCRIPTION - -o2-timeframe-writer-device will receive a Timeframe from FairMQ transport and stream -it via FairMQ. - -.SH OPTIONS - -.TP 5 - ---output-file [FILE] the file where to stream results - -.SH SEE ALSO - -o2-timeframe-reader-device(1) - -.SH BUGS - -Lots of bugs diff --git a/Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h b/Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h deleted file mode 100644 index f13fc8cd88585..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h +++ /dev/null @@ -1,68 +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. - -#ifndef ALICEO2_DEVICES_EPNRECEIVER_H_ -#define ALICEO2_DEVICES_EPNRECEIVER_H_ - -#include <string> -#include <unordered_map> -#include <unordered_set> -#include <chrono> - -#include <FairMQDevice.h> - -namespace o2 -{ -namespace devices -{ - -/// Container for (sub-)timeframes - -struct TFBuffer { - FairMQParts parts; - std::chrono::steady_clock::time_point start; - std::chrono::steady_clock::time_point end; -}; - -/// Receives sub-timeframes from the flpSenders and merges these into full timeframes. - -class EPNReceiverDevice final : public FairMQDevice -{ - public: - EPNReceiverDevice() = default; - ~EPNReceiverDevice() final = default; - void InitTask() final; - - /// Prints the contents of the timeframe container - void PrintBuffer(const std::unordered_map<uint16_t, TFBuffer>& buffer) const; - - /// Discared incomplete timeframes after \p fBufferTimeoutInMs. - void DiscardIncompleteTimeframes(); - - protected: - /// Overloads the Run() method of FairMQDevice - void Run() override; - - std::unordered_map<uint16_t, TFBuffer> mTimeframeBuffer; ///< Stores (sub-)timeframes - std::unordered_set<uint16_t> mDiscardedSet; ///< Set containing IDs of dropped timeframes - - int mNumFLPs = 0; ///< Number of flpSenders - int mBufferTimeoutInMs = 5000; ///< Time after which incomplete timeframes are dropped - int mTestMode = 0; ///< Run the device in test mode (only syncSampler+flpSender+epnReceiver) - - std::string mInChannelName = ""; - std::string mOutChannelName = ""; - std::string mAckChannelName = ""; -}; - -} // namespace devices -} // namespace o2 - -#endif diff --git a/Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h b/Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h deleted file mode 100644 index 08cda323677b9..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h +++ /dev/null @@ -1,72 +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. - -#ifndef ALICEO2_DEVICES_FLPSENDER_H_ -#define ALICEO2_DEVICES_FLPSENDER_H_ - -#include <string> -#include <queue> -#include <unordered_map> -#include <chrono> - -#include <FairMQDevice.h> - -namespace o2 -{ -namespace devices -{ - -/// Sends sub-timframes to epnReceivers -/// -/// Sub-timeframes are received from the previous step (or generated in test-mode) -/// and are sent to epnReceivers. Target epnReceiver is determined from the timeframe ID: -/// targetEpnReceiver = timeframeId % numEPNs (numEPNs is same for every flpSender, although some may be inactive). - -class FLPSenderDevice final : public FairMQDevice -{ - public: - /// Default constructor - FLPSenderDevice() = default; - - /// Default destructor - ~FLPSenderDevice() final = default; - - protected: - /// Overloads the InitTask() method of FairMQDevice - void InitTask() final; - - /// Overloads the Run() method of FairMQDevice - void Run() final; - - private: - /// Sends the "oldest" element from the sub-timeframe container - void sendFrontData(); - - std::queue<FairMQParts> mSTFBuffer; ///< Buffer for sub-timeframes - std::queue<std::chrono::steady_clock::time_point> mArrivalTime; ///< Stores arrival times of sub-timeframes - - int mNumEPNs = 0; ///< Number of epnReceivers - unsigned int mIndex = 0; ///< Index of the flpSender among other flpSenders - unsigned int mSendOffset = 0; ///< Offset for staggering output - unsigned int mSendDelay = 8; ///< Delay for staggering output - - int mEventSize = 10000; ///< Size of the sub-timeframe body (only for test mode) - int mTestMode = false; ///< Run the device in test mode (only syncSampler+flpSender+epnReceiver) - uint16_t mTimeFrameId; - - std::string mInChannelName = ""; - std::string mOutChannelName = ""; - int mLastTimeframeId = -1; -}; - -} // namespace devices -} // namespace o2 - -#endif diff --git a/Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h b/Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h deleted file mode 100644 index 87e72cc0df998..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h +++ /dev/null @@ -1,37 +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. - -#ifndef DATAFLOW_FAKETIMEFRAMEBUILDER_H_ -#define DATAFLOW_FAKETIMEFRAMEBUILDER_H_ - -#include "Headers/DataHeader.h" -#include <vector> -#include <memory> -#include <functional> - -namespace o2 -{ -namespace data_flow -{ - -struct FakeTimeframeSpec { - const char* origin; - const char* dataDescription; - std::function<void(char*, size_t)> bufferFiller; - size_t bufferSize; -}; - -/** Generate a timeframe from the provided specification - */ -std::unique_ptr<char[]> fakeTimeframeGenerator(std::vector<FakeTimeframeSpec>& specs, std::size_t& totalSize); - -} // namespace data_flow -} // namespace o2 -#endif /* DATAFLOW_FAKETIMEFRAMEBUILDER_H_ */ diff --git a/Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.h b/Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.h deleted file mode 100644 index 5c25ec45f7394..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.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. - -#ifndef ALICEO2_FAKE_TIMEFRAME_GENERATOR_H_ -#define ALICEO2_FAKE_TIMEFRAME_GENERATOR_H_ - -#include "O2Device/O2Device.h" - -namespace o2 -{ -namespace data_flow -{ - -/// A device which writes to file the timeframes. -class FakeTimeframeGeneratorDevice : public base::O2Device -{ - public: - static constexpr const char* OptionKeyOutputChannelName = "output-channel-name"; - static constexpr const char* OptionKeyMaxTimeframes = "max-timeframes"; - - /// Default constructor - FakeTimeframeGeneratorDevice(); - - /// Default destructor - ~FakeTimeframeGeneratorDevice() override = default; - - void InitTask() final; - - protected: - /// Overloads the ConditionalRun() method of FairMQDevice - bool ConditionalRun() final; - - std::string mOutChannelName; - size_t mMaxTimeframes; - size_t mTimeframeCount; -}; - -} // namespace data_flow -} // namespace o2 - -#endif diff --git a/Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h b/Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h deleted file mode 100644 index a6bf6dce79ff6..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h +++ /dev/null @@ -1,70 +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. - -//-*- Mode: C++ -*- - -#ifndef HEARTBEATSAMPLER_H -#define HEARTBEATSAMPLER_H - -// @file HeartbeatSampler.h -// @author Matthias Richter -// @since 2017-02-03 -// @brief Heartbeat sampler device - -#include "Headers/DataHeader.h" -#include "Headers/HeartbeatFrame.h" -#include "O2Device/O2Device.h" -#include <string> - -namespace o2 -{ -namespace data_flow -{ - -/// @class HeartbeatSampler -/// @brief A sampler for heartbeat triggers -/// -/// The device is going to be used in an emulation of the reader -/// processes on the FLP -/// The heartbeat triggers are sent out with constant frequency, the -/// period in nano seconds can be configured by option --period -/// -/// TODO: the class can evolve to a general clock sampler device with -/// configurable period, even randomly distributed -class HeartbeatSampler final : public base::O2Device -{ - public: - typedef o2::base::O2Message O2Message; - - static constexpr const char* OptionKeyOutputChannelName = "out-chan-name"; - static constexpr const char* OptionKeyPeriod = "period"; - - HeartbeatSampler() = default; - ~HeartbeatSampler() final = default; - - protected: - /// overloading the InitTask() method of FairMQDevice - void InitTask() final; - - /// overloading ConditionalRun method of FairMQDevice - bool ConditionalRun() final; - - private: - /// publishing period (configurable) - uint32_t mPeriod = 1000000000; - /// name of the (configurable) - std::string mOutputChannelName = "output"; - /// number of elapsed periods - int mCount = 0; -}; - -} // namespace data_flow -}; // namespace o2 -#endif diff --git a/Utilities/DataFlow/include/DataFlow/PayloadMerger.h b/Utilities/DataFlow/include/DataFlow/PayloadMerger.h deleted file mode 100644 index 81c4544a5f717..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/PayloadMerger.h +++ /dev/null @@ -1,131 +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. -#ifndef PAYLOAD_MERGER_H -#define PAYLOAD_MERGER_H - -#include <map> -#include <cstdint> -#include <vector> -#include <functional> -#include <cstring> - -#include <fairmq/FairMQMessage.h> - -namespace o2 -{ -namespace dataflow -{ -/// Helper class that given a set of FairMQMessage, merges (part of) their -/// payload into a separate memory area. -/// -/// - Append multiple messages via the aggregate method -/// - Finalise buffer creation with the finalise call. -template <typename ID> -class PayloadMerger -{ - public: - using MergeableId = ID; - using MessageMap = std::multimap<MergeableId, std::unique_ptr<FairMQMessage>>; - using PayloadExtractor = std::function<size_t(char**, char*, size_t)>; - using IdExtractor = std::function<MergeableId(std::unique_ptr<FairMQMessage>&)>; - using MergeCompletionCheker = std::function<bool(MergeableId, MessageMap&)>; - - /// Helper class to merge FairMQMessages sharing a user defined class of equivalence, - /// specified by @makeId. Completeness of the class of equivalence can be asserted by - /// the @checkIfComplete policy. It's also possible to specify a user defined way of - /// extracting the parts of the payload to be merged via the extractPayload method. - PayloadMerger(IdExtractor makeId, - MergeCompletionCheker checkIfComplete, - PayloadExtractor extractPayload = fullPayloadExtractor) - : mMakeId{makeId}, - mCheckIfComplete{checkIfComplete}, - mExtractPayload{extractPayload} - { - } - - /// Aggregates @payload to all the ones with the same id. - /// @return the id extracted from the payload via the constructor - /// specified id policy (mMakeId callback). - MergeableId aggregate(std::unique_ptr<FairMQMessage>& payload) - { - auto id = mMakeId(payload); - mPartsMap.emplace(std::make_pair(id, std::move(payload))); - return id; - } - - /// This merges a set of messages sharing the same id @id to a unique buffer - /// @out, so that it can be either consumed or sent as a message itself. - /// The decision on whether the merge must happen is done by the constructor - /// specified policy mCheckIfComplete which can, for example, decide - /// to merge when a certain number of subparts are reached. - /// Merging at the moment requires an extra copy, but in principle this could - /// be easily extended to support scatter - gather. - size_t finalise(char** out, MergeableId& id) - { - *out = nullptr; - if (mCheckIfComplete(id, mPartsMap) == false) { - return 0; - } - // If we are here, it means we can send the messages that belong - // to some predefined class of equivalence, identified by the MERGEABLE_ID, - // to the receiver. This is done by the following process: - // - // - Extract what we actually want to send (this might be data embedded inside the message itself) - // - Calculate the aggregate size of all the payloads. - // - Copy all the parts into a final payload - // - Create the header part - // - Create the payload part - // - Send - std::vector<std::pair<char*, size_t>> parts; - - size_t sum = 0; - auto range = mPartsMap.equal_range(id); - for (auto hi = range.first, he = range.second; hi != he; ++hi) { - std::unique_ptr<FairMQMessage>& payload = hi->second; - std::pair<char*, size_t> part; - part.second = mExtractPayload(&part.first, reinterpret_cast<char*>(payload->GetData()), payload->GetSize()); - parts.push_back(part); - sum += part.second; - } - - auto* payload = new char[sum](); - size_t offset = 0; - for (auto& part : parts) { - // Right now this does a copy. In principle this could be done with some sort of - // vectorized I/O - memcpy(payload + offset, part.first, part.second); - offset += part.second; - } - - mPartsMap.erase(id); - *out = payload; - return sum; - } - - // Helper method which leaves the payload untouched - static int64_t fullPayloadExtractor(char** payload, - char* buffer, - size_t bufferSize) - { - *payload = buffer; - return bufferSize; - } - - private: - IdExtractor mMakeId; - MergeCompletionCheker mCheckIfComplete; - PayloadExtractor mExtractPayload; - - MessageMap mPartsMap; -}; -} // namespace dataflow -} // namespace o2 - -#endif // PAYLOAD_MERGER_H diff --git a/Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h b/Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h deleted file mode 100644 index 0eda40bf51d0f..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h +++ /dev/null @@ -1,139 +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. - -//-*- Mode: C++ -*- - -#ifndef SUBFRAMEBUILDERDEVICE_H -#define SUBFRAMEBUILDERDEVICE_H - -/// @file SubframeBuilderDevice.h -/// @author Giulio Eulisse, Matthias Richter, Sandro Wenzel -/// @since 2017-02-07 -/// @brief Demonstrator device for a subframe builder - -#include "Headers/DataHeader.h" -#include "Headers/HeartbeatFrame.h" -#include "O2Device/O2Device.h" -#include "DataFlow/PayloadMerger.h" -#include "DataFlow/SubframeUtils.h" -#include <cstring> -#include <map> - -class FairMQParts; - -namespace o2 -{ -namespace data_flow -{ - -/// @class SubframeBuilderDevice -/// A demonstrator device for building of sub timeframes -/// -/// The scheme in the demonstrator chain assumes multiple data publishers -/// for different input chains of the CRU. The output of these publishers -/// is assembled to a sub timeframe by this device. -/// -/// The device implements the high-level API of the FairMQDevice -/// run loop. The registered method is called once per message -/// which is in itself a multipart message. It;s parts are passed -/// with a FairMQParts object. Not yet clear if this approach is -/// suited for the frame builder as it needs the data from multiple -/// channels with the same channel name. Depends on the validity of -/// the message data. Very likely the message parts are no longer -/// valid after leaving the handler method. But one could apply a -/// scheme with unique pointers and move semantics -/// -/// The duration should be with respect to a time constant, which in -/// itself needs to be configurable, now the time constant is -/// hard-coded microseconds -class SubframeBuilderDevice final : public base::O2Device -{ - public: - using O2Message = o2::base::O2Message; - using SubframeId = o2::dataflow::SubframeId; - using Merger = dataflow::PayloadMerger<SubframeId>; - - static constexpr const char* OptionKeyInputChannelName = "in-chan-name"; - static constexpr const char* OptionKeyOutputChannelName = "out-chan-name"; - static constexpr const char* OptionKeyOrbitDuration = "orbit-duration"; - static constexpr const char* OptionKeyOrbitsPerTimeframe = "orbits-per-timeframe"; - static constexpr const char* OptionKeyInDataFile = "indatafile-name"; - static constexpr const char* OptionKeyDetector = "detector-name"; - static constexpr const char* OptionKeyFLPId = "flp-id"; - static constexpr const char* OptionKeyStripHBF = "strip-hbf"; - - // TODO: this is just a first mockup, remove it - // Default start time for all the producers is 8/4/1977 - // Timeframe start time will be ((N * duration) + start time) where - // N is the incremental number of timeframes being sent out. - // TODO: replace this with a unique Heartbeat from a common device. - static constexpr uint32_t DefaultOrbitDuration = 88924; - static constexpr uint32_t DefaultOrbitsPerTimeframe = 256; - static constexpr uint64_t DefaultHeartbeatStart = 229314600000000000LL; - - /// Default constructor - SubframeBuilderDevice(); - - /// Default destructor - ~SubframeBuilderDevice() final; - - protected: - /// overloading the InitTask() method of FairMQDevice - void InitTask() final; - - /// data handling method to be registered as handler in the - /// FairMQDevice API method OnData - /// The device base class handles the state loop in the RUNNING - /// state and calls the handler when receiving a message on one channel - /// The multiple parts included in one message are provided in the - /// FairMQParts object. - bool HandleData(FairMQParts& msgParts, int /*index*/); - - /// Build the frame and send it - /// For the moment a simple mockup composing a DataHeader and adding it - /// to the multipart message together with the SubframeMetadata as payload - bool BuildAndSendFrame(FairMQParts& parts); - - private: - uint32_t mOrbitsPerTimeframe; - // FIXME: lookup the actual value - uint32_t mOrbitDuration; - std::string mInputChannelName = ""; - std::string mOutputChannelName = ""; - size_t mFLPId = 0; - bool mStripHBF = false; - std::unique_ptr<Merger> mMerger; - - uint64_t mHeartbeatStart = DefaultHeartbeatStart; - - template <typename T> - size_t fakeHBHPayloadHBT(char** buffer, std::function<void(T&, int)> filler, int numOfElements) - { - // LOG(INFO) << "SENDING TPC PAYLOAD\n"; - auto payloadSize = sizeof(header::HeartbeatHeader) + sizeof(T) * numOfElements + sizeof(header::HeartbeatTrailer); - *buffer = new char[payloadSize]; - auto* hbh = reinterpret_cast<header::HeartbeatHeader*>(*buffer); - assert(payloadSize > 0); - assert(payloadSize - sizeof(header::HeartbeatTrailer) > 0); - auto* hbt = reinterpret_cast<header::HeartbeatTrailer*>(payloadSize - sizeof(header::HeartbeatTrailer)); - - T* payload = reinterpret_cast<T*>(*buffer + sizeof(header::HeartbeatHeader)); - for (int i = 0; i < numOfElements; ++i) { - new (payload + i) T; - // put some random toy time stamp to each cluster - filler(payload[i], i); - } - return payloadSize; - } -}; - -} // namespace data_flow -}; // namespace o2 -#endif diff --git a/Utilities/DataFlow/include/DataFlow/SubframeUtils.h b/Utilities/DataFlow/include/DataFlow/SubframeUtils.h deleted file mode 100644 index 69b5f3d4a6c24..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/SubframeUtils.h +++ /dev/null @@ -1,50 +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. -#ifndef DATAFLOW_SUBFRAMEUTILS_H -#define DATAFLOW_SUBFRAMEUTILS_H - -#include <tuple> -#include <cstddef> -#include "Headers/HeartbeatFrame.h" - -namespace o2 -{ -namespace dataflow -{ - -int64_t extractDetectorPayloadStrip(char** payload, char* buffer, size_t bufferSize) -{ - *payload = buffer + sizeof(o2::header::HeartbeatHeader); - return bufferSize - sizeof(o2::header::HeartbeatHeader) - sizeof(o2::header::HeartbeatTrailer); -} - -struct SubframeId { - size_t timeframeId; - size_t socketId; - - // operator needed for the equal_range algorithm/ multimap method - bool operator<(const SubframeId& rhs) const - { - return std::tie(timeframeId, socketId) < std::tie(rhs.timeframeId, rhs.socketId); - } -}; - -SubframeId makeIdFromHeartbeatHeader(const header::HeartbeatHeader& header, size_t socketId, size_t orbitsPerTimeframe) -{ - SubframeId id = { - .timeframeId = header.orbit / orbitsPerTimeframe, - .socketId = socketId}; - return id; -} - -} /* namespace dataflow */ -} /* namespace o2 */ - -#endif // DATAFLOW_SUBFRAMEUTILS_H diff --git a/Utilities/DataFlow/include/DataFlow/TimeframeParser.h b/Utilities/DataFlow/include/DataFlow/TimeframeParser.h deleted file mode 100644 index 590982c1dfb04..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/TimeframeParser.h +++ /dev/null @@ -1,36 +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. - -#ifndef TIMEFRAME_PARSER_H_ -#define TIMEFRAME_PARSER_H_ - -#include <iosfwd> -#include <functional> - -class FairMQParts; - -namespace o2 -{ -namespace data_flow -{ - -/// An helper function which takes a std::istream pointing -/// to a naively persisted timeframe and pumps its parts to -/// FairMQParts, ready to be shipped via FairMQ. -void streamTimeframe(std::istream& stream, - std::function<void(FairMQParts& parts, char* buffer, size_t size)> onAddPart, - std::function<void(FairMQParts& parts)> onSend); - -void streamTimeframe(std::ostream& stream, FairMQParts& parts); - -} // namespace data_flow -} // namespace o2 - -#endif // TIMEFRAME_PARSER_H diff --git a/Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h b/Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h deleted file mode 100644 index f4359b6f21142..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h +++ /dev/null @@ -1,50 +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. - -#ifndef ALICEO2_TIMEFRAME_READER_H_ -#define ALICEO2_TIMEFRAME_READER_H_ - -#include "O2Device/O2Device.h" -#include <fstream> - -namespace o2 -{ -namespace data_flow -{ - -/// A device which writes to file the timeframes. -class TimeframeReaderDevice : public base::O2Device -{ - public: - static constexpr const char* OptionKeyOutputChannelName = "output-channel-name"; - static constexpr const char* OptionKeyInputFileName = "input-file"; - - /// Default constructor - TimeframeReaderDevice(); - - /// Default destructor - ~TimeframeReaderDevice() override = default; - - void InitTask() final; - - protected: - /// Overloads the ConditionalRun() method of FairMQDevice - bool ConditionalRun() final; - - std::string mOutChannelName; - std::string mInFileName; - std::fstream mFile; - std::vector<std::string> mSeen; -}; - -} // namespace data_flow -} // namespace o2 - -#endif diff --git a/Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h b/Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h deleted file mode 100644 index 453b0ea669d5b..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h +++ /dev/null @@ -1,45 +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. - -#ifndef ALICEO2_TIMEFRAMEVALIDATOR_H_ -#define ALICEO2_TIMEFRAMEVALIDATOR_H_ - -#include "O2Device/O2Device.h" - -namespace o2 -{ -namespace data_flow -{ - -/// A validating device for time frame data (coming from EPN) -class TimeframeValidatorDevice : public base::O2Device -{ - public: - static constexpr const char* OptionKeyInputChannelName = "input-channel-name"; - - /// Default constructor - TimeframeValidatorDevice(); - - /// Default destructor - ~TimeframeValidatorDevice() override = default; - - void InitTask() final; - - protected: - /// Overloads the Run() method of FairMQDevice - void Run() final; - - std::string mInChannelName; -}; - -} // namespace data_flow -} // namespace o2 - -#endif diff --git a/Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h b/Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h deleted file mode 100644 index 73fceed644d48..0000000000000 --- a/Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h +++ /dev/null @@ -1,59 +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. - -#ifndef ALICEO2_TIMEFRAME_WRITER_DEVICE_H_ -#define ALICEO2_TIMEFRAME_WRITER_DEVICE_H_ - -#include "O2Device/O2Device.h" -#include <fstream> - -namespace o2 -{ -namespace data_flow -{ - -/// A device which writes to file the timeframes. -class TimeframeWriterDevice : public base::O2Device -{ - public: - static constexpr const char* OptionKeyInputChannelName = "input-channel-name"; - static constexpr const char* OptionKeyOutputFileName = "output-file"; - static constexpr const char* OptionKeyMaxTimeframesPerFile = "max-timeframes-per-file"; - static constexpr const char* OptionKeyMaxFileSize = "max-file-size"; - static constexpr const char* OptionKeyMaxFiles = "max-files"; - - /// Default constructor - TimeframeWriterDevice(); - - /// Default destructor - ~TimeframeWriterDevice() override = default; - - void InitTask() final; - - /// The PostRun will trigger saving the file to disk - void PostRun() final; - - protected: - /// Overloads the Run() method of FairMQDevice - void Run() final; - - std::string mInChannelName; - std::string mOutFileName; - std::fstream mFile; - size_t mMaxTimeframes; - size_t mMaxFileSize; - size_t mMaxFiles; - size_t mFileCount; -}; - -} // namespace data_flow -} // namespace o2 - -#endif diff --git a/Utilities/DataFlow/run/CreateSetup.py b/Utilities/DataFlow/run/CreateSetup.py deleted file mode 100755 index 0ebe8f8f38a82..0000000000000 --- a/Utilities/DataFlow/run/CreateSetup.py +++ /dev/null @@ -1,200 +0,0 @@ -#!/usr/bin/python -# a very simple python script to -# create and scale a topology/conf + runfile for a variable list of -# HeartbeatSampler + DataPublisher + ... + FLP + EPN -# author: S. Wenzel -#FIXME: decide whether to config for xterm or tmux - -import json - -NumFLP = 2 -NumDP = NumFLP # in principle we could have different number of data publishers -NumEPN = 4 -EPNStartSocket = 6000 -HeartbeatSocket = 5000 -HeartbeatBaseName = "o2-heartbeat-sampler" -EPNBaseName = "epnReceiver" -SFBStartSocket = 5500 -FLPStartSocket = 4000 -ValidatorStartSocket = 7000 -FLPBaseName = "flpSender" -DPBaseName = "o2-datapublisher-device" -SFBBaseName = "subframeBuilder" -tcpbase = "tcp://127.0.0.1:" -detectors = ["TPC","ITS"] -datadescription = ["TPCCLUSTER", "ITSRAW"] - -configfilename = "customconfig.json" -runscriptfilename = "customrunscript.sh" - -# some potentially reusable API to construct devices -def initDevice(name): - device = {} - device["id"] = name - device["channels"] = [] # empty list for device - return device - -# creates one channel; empty sockets -def initChannel(name, type, connect): - channel = {} - channel["name"] = name - channel["type"] = type - channel["method"] = connect - channel["sockets"] = [] - return channel - -def initAddress(url): - return {"address":url} - -def addChannel(device, channel): - device["channels"].append(channel) - -def addAddress(channel, address): - channel["sockets"].append(address) - -# adds a custom key:value pair to a dictionary -def addPair(element, key, value): - element[key]=value - -# code describing our devices follows - -def writeOneDP(id): - device = initDevice(DPBaseName+str(id)) - inchannel = initChannel("input","sub","connect") - addAddress(inchannel, initAddress(tcpbase + str(HeartbeatSocket))) - outchannel = initChannel("output","pub","bind") - addAddress(outchannel, initAddress(tcpbase + str(SFBStartSocket + id))) - addPair(outchannel, "sndBufSize", "10") - addChannel(device, inchannel) - addChannel(device, outchannel) - return device - -def writeOneSFB(id): - device = initDevice(SFBBaseName + str(id)) - # the input channel - inchannel = initChannel("input", "sub", "connect") - addAddress(inchannel, initAddress(tcpbase + str(SFBStartSocket+id))) - addPair(inchannel, "sndBufSize", "10") - # the output channel - outchannel = initChannel("output", "pub", "bind") - addAddress(outchannel, initAddress(tcpbase + str(FLPStartSocket+id))) - addPair(outchannel, "sndBufSize", "10") - addChannel(device,inchannel) - addChannel(device,outchannel) - return device - -def writeHBSamplerDevice(): - device = initDevice(HeartbeatBaseName) - outchannel = initChannel("output", "pub", "bind") - addAddress(outchannel, initAddress(tcpbase + str(HeartbeatSocket))) - addChannel(device, outchannel) - return device - -# write timeframeValidator -def writeTFV(): - device = initDevice("timeframeValidator") - channel = initChannel("input", "sub", "connect") - addAddress(channel, initAddress(tcpbase + str(ValidatorStartSocket))) - addChannel(device, channel) - return device - -# write single flp device -def writeOneFLP(id): - device = initDevice(FLPBaseName + str(id)) - inchannel = initChannel("input","sub","connect") - addAddress(inchannel, initAddress(tcpbase + str(FLPStartSocket+id))) - outchannel = initChannel("output", "push", "connect") - # write all EPN addresses - for i in range(0,NumEPN): - addAddress(outchannel, initAddress(tcpbase + str(EPNStartSocket+i))) - addChannel(device, inchannel) - addChannel(device, outchannel) - return device - -def writeOneEPN(id): - # write a single EPN device - device = initDevice(EPNBaseName + str(id)) - inchannel = initChannel("input", "pull", "bind") - addAddress(inchannel, initAddress(tcpbase + str(EPNStartSocket+id))) - # the ack channel - ackchannel = initChannel("ack", "push", "connect") - addAddress(ackchannel, initAddress("tcp://127.0.0.1:5990")) - addPair(ackchannel, "ratelogging", "0") - # the output channel (time frame validator) - outchannel = initChannel("output", "pub", "bind") - addAddress(outchannel, initAddress(tcpbase + str(ValidatorStartSocket))) - addChannel(device, inchannel) - addChannel(device, ackchannel) - addChannel(device, outchannel) - return device - -def addFLPDevices(devicelist): - for i in range(0,NumFLP): - devicelist.append(writeOneDP(i)) - devicelist.append(writeOneSFB(i)) - devicelist.append(writeOneFLP(i)) - -def addEPNDevices(devicelist): - for i in range(0,NumEPN): - devicelist.append(writeOneEPN(i)) - -def getConf(): - conf = {} - conf["fairMQOptions"] = {"devices" : []} - devicelist = conf["fairMQOptions"]["devices"] - # append all the the devices to this list - addFLPDevices(devicelist) - addEPNDevices(devicelist) - devicelist.append(writeTFV()) - devicelist.append(writeHBSamplerDevice()) - return conf - -def writeJSONConf(): - print "creating JOSN config " + configfilename - with open(configfilename, 'w') as f: - f.write(json.dumps(getConf())) - -def writeRunScript(): - xtermcommand = "xterm -hold -e " - dumpstring = [] - # treat data publishers - for i in range(0, NumDP): - # we might need to give information about detector to DP as well - command = "o2-datapublisher-device --id DataPublisherDevice" + str(i) - command += " --data-description " + datadescription[i%2] - command += " --mq-config " + configfilename + " --in-chan-name input --out-chan-name output &" - dumpstring.append(xtermcommand + command) - - # treat sfbdevices - for i in range(0, NumFLP): - command = "o2-subframebuilder-device --id subframeBuilder" + str(i) - command += " --mq-config " + configfilename + " --detector " + detectors[i%2] + " &" - dumpstring.append(xtermcommand + command) - # treat flpSender - for i in range(0, NumFLP): - flpCommand = "flpSender --id flpSender" + str(i) - flpCommand += " --mq-config " + configfilename + " --in-chan-name input" - flpCommand += " --out-chan-name output --num-epns " + str(NumEPN) + " --flp-index " + str(i) - flpCommand += "&" - dumpstring.append(xtermcommand + flpCommand) - # treat EPN receiver - for i in range(0, NumEPN): - epnCommand = "epnReceiver --id epnReceiver" + str(i) - epnCommand += " --mq-config " + configfilename + " --in-chan-name input --out-chan-name output" - epnCommand += " --num-flps " + str(NumFLP) + "&" - dumpstring.append(xtermcommand + epnCommand) - # treat timeFrameValidator - command = "o2-timeframe-validator-device --id timeframeValidator --mq-config " + configfilename + " customconfig.json --input-channel-name input &" - dumpstring.append(xtermcommand + command) - - # treat heartbeatsampler - command = "o2-heartbeat-sampler --id heartbeatSampler --mq-config " + configfilename + " --out-chan-name output &" - dumpstring.append(xtermcommand + command) - - print "creating runscript " + runscriptfilename - with open(runscriptfilename, 'w') as f: - f.write('\n'.join(dumpstring)) - -if __name__ == '__main__': - writeJSONConf() - writeRunScript() diff --git a/Utilities/DataFlow/run/confBasicSetup.json b/Utilities/DataFlow/run/confBasicSetup.json deleted file mode 100644 index 4fe1a1c633d61..0000000000000 --- a/Utilities/DataFlow/run/confBasicSetup.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "fairMQOptions": - { - "devices": - [ - { - "id": "subframeBuilder", - "channels": - [ - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5550" } - ], - "sndBufSize": "10" - }] - }, - - { - "id": "flpSender", - "channels": - [{ - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5550" } - ], - "rcvBufSize": "10" - }, - { - "name": "output", - "type": "push", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5570" } - ], - "sndBufSize": "10" - }] - }, - - { - "id": "epnReceiver", - "channels": - [ - { - "name": "input", - "type": "pull", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5570"} - ], - "sndBufSize": "10" - }, - { - "name": "ack", - "type": "push", - "method": "connect", - "address": "tcp://127.0.0.1:5990", - "rateLogging": "0" - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "address": "tcp://127.0.0.1:5580", - "sndBufSize": "10" - } - ] - }, - - { - "id": "timeframeValidator", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5580"} - ], - "sndBufSize": "10" - } - ] - } - - ] - } -} diff --git a/Utilities/DataFlow/run/confComplexSetup.json b/Utilities/DataFlow/run/confComplexSetup.json deleted file mode 100644 index cbb69fb7434ce..0000000000000 --- a/Utilities/DataFlow/run/confComplexSetup.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "fairMQOptions": - { - "devices": - [ - { - "id": "subframeBuilderTPC", - "channels": - [ - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5550" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "flpSenderTPC", - "channels": - [{ - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5550" } - ], - "rcvBufSize": "10" - }, - { - "name": "output", - "type": "push", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5570" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "subframeBuilderITS", - "channels": - [ - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5551" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "flpSenderITS", - "channels": - [{ - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5551" } - ], - "rcvBufSize": "10" - }, - { - "name": "output", - "type": "push", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5570" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "epnReceiver", - "channels": - [ - { - "name": "input", - "type": "pull", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5570"} - ], - "sndBufSize": "10" - }, - { - "name": "ack", - "type": "push", - "method": "connect", - "address": "tcp://127.0.0.1:5990", - "rateLogging": "0" - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "address": "tcp://127.0.0.1:5580", - "sndBufSize": "10" - } - ] - }, - { - "id": "timeframeValidator", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5580"} - ], - "sndBufSize": "10" - } - ] - } - ] - } -} diff --git a/Utilities/DataFlow/run/confComplexSetup2.json b/Utilities/DataFlow/run/confComplexSetup2.json deleted file mode 100644 index 3c527d7616713..0000000000000 --- a/Utilities/DataFlow/run/confComplexSetup2.json +++ /dev/null @@ -1,345 +0,0 @@ -{ - "fairMQOptions": - { - "devices": - [ - { - "id": "heartbeatSampler", - "channels": - [ - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5450" } - ], - "sndBufSize": "10" - } - ] - }, - { - "id": "DataPublisherDeviceTPC", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets":[ - {"address": "tcp://127.0.0.1:5450"} - ] - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:6550" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "DataPublisherDeviceITS", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets":[ - {"address": "tcp://127.0.0.1:5450"} - ] - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:7550" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "subframeBuilderTPC", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets":[ - {"address": "tcp://127.0.0.1:6550"} - ] - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5550" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "flpSenderTPC", - "channels": - [ - { - "name": "input-channel-name", - "type": "sub", - "method": "connect", - "sockets":[ - {"address": "tcp://127.0.0.1:5450"} - ] - }, - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5550" } - ], - "rcvBufSize": "10" - }, - { - "name": "output", - "type": "push", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5570" }, - { "address": "tcp://127.0.0.1:5571" }, - { "address": "tcp://127.0.0.1:5572" }, - { "address": "tcp://127.0.0.1:5573" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "subframeBuilderITS", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets":[ - {"address": "tcp://127.0.0.1:7550"} - ] - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5551" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "flpSenderITS", - "channels": - [{ - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5551" } - ], - "rcvBufSize": "10" - }, - { - "name": "output", - "type": "push", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5570" }, - { "address": "tcp://127.0.0.1:5571" }, - { "address": "tcp://127.0.0.1:5572" }, - { "address": "tcp://127.0.0.1:5573" } - ], - "sndBufSize": "10" - }] - }, - { - "id": "epnReceiver1", - "channels": - [ - { - "name": "input", - "type": "pull", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5570"} - ], - "sndBufSize": "10" - }, - { - "name": "ack", - "type": "push", - "method": "connect", - "address": "tcp://127.0.0.1:5990", - "rateLogging": "0" - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "address": "tcp://127.0.0.1:5580", - "sndBufSize": "10" - } - ] - }, -{ - "id": "epnReceiver1", - "channels": - [ - { - "name": "input", - "type": "pull", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5570"} - ], - "sndBufSize": "10" - }, - { - "name": "ack", - "type": "push", - "method": "connect", - "address": "tcp://127.0.0.1:5990", - "rateLogging": "0" - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "address": "tcp://127.0.0.1:5580", - "sndBufSize": "10" - } - ] - }, - { - "id": "epnReceiver2", - "channels": - [ - { - "name": "input", - "type": "pull", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5571"} - ], - "sndBufSize": "10" - }, - { - "name": "ack", - "type": "push", - "method": "connect", - "address": "tcp://127.0.0.1:5990", - "rateLogging": "0" - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "address": "tcp://127.0.0.1:5580", - "sndBufSize": "10" - } - ] - }, - { - "id": "epnReceiver3", - "channels": - [ - { - "name": "input", - "type": "pull", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5572"} - ], - "sndBufSize": "10" - }, - { - "name": "ack", - "type": "push", - "method": "connect", - "address": "tcp://127.0.0.1:5990", - "rateLogging": "0" - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "address": "tcp://127.0.0.1:5580", - "sndBufSize": "10" - } - ] - }, -{ - "id": "epnReceiver4", - "channels": - [ - { - "name": "input", - "type": "pull", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5573"} - ], - "sndBufSize": "10" - }, - { - "name": "ack", - "type": "push", - "method": "connect", - "address": "tcp://127.0.0.1:5990", - "rateLogging": "0" - }, - { - "name": "output", - "type": "pub", - "method": "bind", - "address": "tcp://127.0.0.1:5580", - "sndBufSize": "10" - } - ] - }, - { - "id": "timeframeValidator", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5580"} - ], - "sndBufSize": "10" - } - ] - } - ] - } -} diff --git a/Utilities/DataFlow/run/confFakeTimeframe.json b/Utilities/DataFlow/run/confFakeTimeframe.json deleted file mode 100644 index ae1f686087f25..0000000000000 --- a/Utilities/DataFlow/run/confFakeTimeframe.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "fairMQOptions": - { - "devices": - [ - { - "id": "FakeTimeframeGeneratorDevice", - "channels": - [ - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://*:5550" } - ], - "sndBufSize": "10" - } - ] - }, - { - "id": "TimeframeWriterDevice", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5550"} - ], - "sndBufSize": "10" - } - ] - }, - { - "id": "TimeframeReaderDevice", - "channels": - [ - { - "name": "output", - "type": "pub", - "method": "bind", - "sockets": - [ - { "address": "tcp://127.0.0.1:5551"} - ], - "sndBufSize": "10" - } - ] - }, - { - "id": "TimeframeValidatorDevice", - "channels": - [ - { - "name": "input", - "type": "sub", - "method": "connect", - "sockets": - [ - { "address": "tcp://127.0.0.1:5551"} - ], - "sndBufSize": "10" - } - ] - } - ] - } -} diff --git a/Utilities/DataFlow/run/startBasicSetup.sh b/Utilities/DataFlow/run/startBasicSetup.sh deleted file mode 100755 index e69106eab5dc5..0000000000000 --- a/Utilities/DataFlow/run/startBasicSetup.sh +++ /dev/null @@ -1,13 +0,0 @@ -# simple start script to lauch a basic setup -# Prerequisites: -# - expects the configuration file to be in the working directory -# - O2 bin and lib set n the shell environment - - -xterm -geometry 80x25+0+0 -hold -e epnReceiver --id epnReceiver --mq-config confBasicSetup.json --in-chan-name input --out-chan-name output --num-flps 1 & - -xterm -geometry 80x25+500+0 -hold -e flpSender --id flpSender --mq-config confBasicSetup.json --in-chan-name input --out-chan-name output --num-epns 1 & - -xterm -geometry 80x25+1000+0 -hold -e o2-subframebuilder-device --id subframeBuilder --mq-config confBasicSetup.json --self-triggered & - -xterm -geometry 80x25+1500+0 -hold -e o2-timeframe-validator-device --id timeframeValidator --mq-config confBasicSetup.json --input-channel-name input & diff --git a/Utilities/DataFlow/run/startComplexSetup.sh b/Utilities/DataFlow/run/startComplexSetup.sh deleted file mode 100755 index 6280269be5d16..0000000000000 --- a/Utilities/DataFlow/run/startComplexSetup.sh +++ /dev/null @@ -1,24 +0,0 @@ -# simple start script to launch a more complex setup -# with 2 data publishers (inside subframebuilder) + 2 attached flpSenders -# Prerequisites: -# - expects the configuration file to be in the working directory -# - O2 bin and lib set n the shell environment - - -# we have just one epn and 2 flps -xterm -geometry 80x25+0+0 -hold -e epnReceiver --id epnReceiver --mq-config confComplexSetup.json --in-chan-name input --out-chan-name output --num-flps 2 & - -# this is the flp for TPC -xterm -geometry 80x25+500+0 -hold -e flpSender --id flpSenderTPC --mq-config confComplexSetup.json --in-chan-name input --out-chan-name output --num-epns 1 --flp-index 0 & - -# this is the flp for ITS -xterm -geometry 80x25+800+0 -hold -e flpSender --id flpSenderITS --mq-config confComplexSetup.json --in-chan-name input --out-chan-name output --num-epns 1 --flp-index 1 & - -# this is the subtimeframe publisher for TPC -xterm -geometry 80x25+0+500 -hold -e o2-subframebuilder-device --id subframeBuilderTPC --mq-config confComplexSetup.json --self-triggered --detector TPC & - -# this is the subtimeframe publisher for ITS -xterm -geometry 80x25+500+500 -hold -e o2-subframebuilder-device --id subframeBuilderITS --mq-config confComplexSetup.json --self-triggered --detector ITS & - -# consumer and validator of the full EPN time frame -xterm -geometry 80x25+800+500 -hold -e o2-timeframe-validator-device --id timeframeValidator --mq-config confComplexSetup.json --input-channel-name input & diff --git a/Utilities/DataFlow/run/startComplexSetup2.sh b/Utilities/DataFlow/run/startComplexSetup2.sh deleted file mode 100755 index a0c343658ad8a..0000000000000 --- a/Utilities/DataFlow/run/startComplexSetup2.sh +++ /dev/null @@ -1,36 +0,0 @@ -# simple start script to launch a more complex setup -# with 2 data publishers (inside subframebuilder) + 2 attached flpSenders + 4 EPNS -# Prerequisites: -# - expects the configuration file to be in the working directory -# - O2 bin and lib set n the shell environment - -# it would be nice having a script that generates the configuration file for N FLP and M EPNS - -# Start one HBSampler device -xterm -geometry 80x25+0+0 -hold -e o2-heartbeat-sampler --id heartbeatSampler --mq-config confComplexSetup2.json --out-chan-name output & - -# Data publishers -xterm -geometry 80x25+500+0 -hold -e o2-datapublisher-device --id DataPublisherDeviceTPC --mq-config confComplexSetup2.json --in-chan-name input --out-chan-name output --data-description TPCCLUSTER & -xterm -geometry 80x25+500+400 -hold -e o2-datapublisher-device --id DataPublisherDeviceITS --mq-config confComplexSetup2.json --in-chan-name input --out-chan-name output --data-description ITSRAW & - - -# this is the subtimeframe publisher for TPC -xterm -geometry 80x25+1000+0 -hold -e o2-subframebuilder-device --id subframeBuilderTPC --mq-config confComplexSetup2.json --detector TPC & - -# this is the subtimeframe publisher for ITS -xterm -geometry 80x25+1000+400 -hold -e o2-subframebuilder-device --id subframeBuilderITS --mq-config confComplexSetup2.json --detector ITS & - -# this is the flp for TPC -xterm -geometry 80x25+1500+0 -hold -e o2-flp-sender-device --id flpSenderTPC --mq-config confComplexSetup2.json --in-chan-name input --out-chan-name output --num-epns 4 --flp-index 0 & - -# this is the flp for ITS -xterm -geometry 80x25+1500+400 -hold -e o2-flp-sender-device --id flpSenderITS --mq-config confComplexSetup2.json --in-chan-name input --out-chan-name output --num-epns 4 --flp-index 1 & - -# we have 4 epn and 2 flps -xterm -geometry 80x25+2000+0 -hold -e o2-epn-receiver-device --id epnReceiver1 --mq-config confComplexSetup2.json --buffer-timeout 10000 --in-chan-name input --out-chan-name output --num-flps 2 & -xterm -geometry 80x25+2000+400 -hold -e o2-epn-receiver-device --id epnReceiver2 --mq-config confComplexSetup2.json --buffer-timeout 10000 --in-chan-name input --out-chan-name output --num-flps 2 & -xterm -geometry 80x25+2000+800 -hold -e o2-epn-receiver-device --id epnReceiver3 --mq-config confComplexSetup2.json --buffer-timeout 10000 --in-chan-name input --out-chan-name output --num-flps 2 & -xterm -geometry 80x25+2000+1200 -hold -e o2-epn-receiver-device --id epnReceiver4 --mq-config confComplexSetup2.json --buffer-timeout 10000 --in-chan-name input --out-chan-name output --num-flps 2 & - -# consumer and validator of the full EPN time frame -xterm -geometry 80x25+2000+500 -hold -e o2-timeframe-validator-device --id timeframeValidator --mq-config confComplexSetup2.json --input-channel-name input & diff --git a/Utilities/DataFlow/run/startTimeframeExample.sh b/Utilities/DataFlow/run/startTimeframeExample.sh deleted file mode 100755 index f9c108825cc3a..0000000000000 --- a/Utilities/DataFlow/run/startTimeframeExample.sh +++ /dev/null @@ -1,4 +0,0 @@ -xterm -geometry 80x25+0+0 -hold -e FakeTimeframeGeneratorDevice --id FakeTimeframeGeneratorDevice --mq-config confFakeTimeframe.json --output-channel-name output & -xterm -geometry 80x25+0+0 -hold -e o2-timeframe-writer-device --id TimeframeWriterDevice --mq-config confFakeTimeframe.json --input-channel-name input --max-timeframes 1 --output-file data.o2tf & -#xterm -geometry 80x25+0+0 -hold -e o2-timeframe-reader-device --id TimeframeReaderDevice --mq-config confFakeTimeframe.json --input-file data.o2tf --output-channel-name output & -#xterm -geometry 80x25+0+0 -hold -e o2-timeframe-validator-device --id TimeframeValidatorDevice --mq-config confFakeTimeframe.json --input-channel-name input & diff --git a/Utilities/DataFlow/src/EPNReceiverDevice.cxx b/Utilities/DataFlow/src/EPNReceiverDevice.cxx deleted file mode 100644 index 9424bd58d9f25..0000000000000 --- a/Utilities/DataFlow/src/EPNReceiverDevice.cxx +++ /dev/null @@ -1,184 +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. - -#include <cstddef> // size_t -#include <fstream> // writing to file (DEBUG) -#include <cstring> -#include <iomanip> - -#include <FairMQLogger.h> -#include <options/FairMQProgOptions.h> - -#include "DataFlow/EPNReceiverDevice.h" -#include "Headers/DataHeader.h" -#include "Headers/SubframeMetadata.h" -#include "O2Device/Compatibility.h" -#include "TimeFrame/TimeFrame.h" - -#include <iomanip> - -using namespace std; -using namespace std::chrono; -using namespace o2::devices; -using SubframeMetadata = o2::data_flow::SubframeMetadata; -using TPCTestPayload = o2::data_flow::TPCTestPayload; -using TPCTestCluster = o2::data_flow::TPCTestCluster; -using IndexElement = o2::dataformats::IndexElement; - -void EPNReceiverDevice::InitTask() -{ - mNumFLPs = GetConfig()->GetValue<int>("num-flps"); - mBufferTimeoutInMs = GetConfig()->GetValue<int>("buffer-timeout"); - mTestMode = GetConfig()->GetValue<int>("test-mode"); - mInChannelName = GetConfig()->GetValue<string>("in-chan-name"); - mOutChannelName = GetConfig()->GetValue<string>("out-chan-name"); - mAckChannelName = GetConfig()->GetValue<string>("ack-chan-name"); -} - -void EPNReceiverDevice::PrintBuffer(const unordered_map<uint16_t, TFBuffer>& buffer) const -{ - string header = "===== "; - - for (int i = 1; i <= mNumFLPs; ++i) { - stringstream out; - out << i % 10; - header += out.str(); - //i > 9 ? header += " " : header += " "; - } - LOG(INFO) << header; - - for (auto& it : buffer) { - string stars = ""; - for (unsigned int j = 1; j <= (it.second).parts.Size(); ++j) { - stars += "*"; - } - LOG(INFO) << setw(4) << it.first << ": " << stars; - } -} - -void EPNReceiverDevice::DiscardIncompleteTimeframes() -{ - auto it = mTimeframeBuffer.begin(); - - while (it != mTimeframeBuffer.end()) { - if (duration_cast<milliseconds>(steady_clock::now() - (it->second).start).count() > mBufferTimeoutInMs) { - LOG(WARN) << "Timeframe #" << it->first << " incomplete after " << mBufferTimeoutInMs << " milliseconds, discarding"; - mDiscardedSet.insert(it->first); - mTimeframeBuffer.erase(it++); - LOG(WARN) << "Number of discarded timeframes: " << mDiscardedSet.size(); - } else { - // LOG(INFO) << "Timeframe #" << it->first << " within timeout, buffering..."; - ++it; - } - } -} - -void EPNReceiverDevice::Run() -{ - uint16_t id = 0; // holds the timeframe id of the currently arrived sub-timeframe. - - FairMQChannel& ackOutChannel = fChannels.at(mAckChannelName).at(0); - - // Simple multi timeframe index - using TimeframeId = int; - using FlpId = int; - std::multimap<TimeframeId, IndexElement> index; - std::multimap<TimeframeId, FlpId> flpIds; - - while (compatibility::FairMQ13<FairMQDevice>::IsRunning(this)) { - FairMQParts subtimeframeParts; - if (Receive(subtimeframeParts, mInChannelName, 0, 100) <= 0) { - continue; - } - - assert(subtimeframeParts.Size() >= 2); - - const auto* dh = o2::header::get<header::DataHeader*>(subtimeframeParts.At(0)->GetData()); - assert(strncmp(dh->dataDescription.str, "SUBTIMEFRAMEMD", 16) == 0); - SubframeMetadata* sfm = reinterpret_cast<SubframeMetadata*>(subtimeframeParts.At(1)->GetData()); - id = o2::data_flow::timeframeIdFromTimestamp(sfm->startTime, sfm->duration); - auto flpId = sfm->flpIndex; - - if (mDiscardedSet.find(id) == mDiscardedSet.end()) { - if (mTimeframeBuffer.find(id) == mTimeframeBuffer.end()) { - // if this is the first part with this ID, save the receive time. - mTimeframeBuffer[id].start = steady_clock::now(); - } - flpIds.insert(std::make_pair(id, flpId)); - LOG(INFO) << "Timeframe ID " << id << " for startTime " << sfm->startTime << "\n"; - // If the received ID has not previously been discarded, store - // the data part in the buffer For the moment we just concatenate - // the subtimeframes and add an index for their description at - // the end. Given every second part is a data header we skip - // every two parts to populate the index. Moreover we know that - // the SubframeMetadata is always in the second part, so we can - // extract the flpId from there. - for (size_t i = 0; i < subtimeframeParts.Size(); ++i) { - if (i % 2 == 0) { - const auto* adh = o2::header::get<header::DataHeader*>(subtimeframeParts.At(i)->GetData()); - auto ie = std::make_pair(*adh, index.count(id) * 2); - index.insert(std::make_pair(id, ie)); - } - mTimeframeBuffer[id].parts.AddPart(move(subtimeframeParts.At(i))); - } - } else { - // if received ID has been previously discarded. - LOG(WARN) << "Received part from an already discarded timeframe with id " << id; - } - - if (flpIds.count(id) == mNumFLPs) { - LOG(INFO) << "Timeframe " << id << " complete. Publishing.\n"; - o2::header::DataHeader tih; - std::vector<IndexElement> flattenedIndex; - - tih.dataDescription = o2::header::DataDescription("TIMEFRAMEINDEX"); - tih.dataOrigin = o2::header::DataOrigin("EPN"); - tih.subSpecification = 0; - tih.payloadSize = index.count(id) * sizeof(flattenedIndex.front()); - void* indexData = malloc(tih.payloadSize); - auto indexRange = index.equal_range(id); - for (auto ie = indexRange.first; ie != indexRange.second; ++ie) { - flattenedIndex.push_back(ie->second); - } - memcpy(indexData, flattenedIndex.data(), tih.payloadSize); - - mTimeframeBuffer[id].parts.AddPart(NewSimpleMessage(tih)); - mTimeframeBuffer[id].parts.AddPart(NewMessage( - indexData, tih.payloadSize, - [](void* data, void* hint) { free(data); }, nullptr)); - // LOG(INFO) << "Collected all parts for timeframe #" << id; - // when all parts are collected send then to the output channel - Send(mTimeframeBuffer[id].parts, mOutChannelName); - LOG(INFO) << "Index count for " << id << " " << index.count(id) << "\n"; - index.erase(id); - LOG(INFO) << "Index count for " << id << " " << index.count(id) << "\n"; - flpIds.erase(id); - - if (mTestMode > 0) { - // Send an acknowledgement back to the sampler to measure the round trip time - unique_ptr<FairMQMessage> ack(NewMessage(sizeof(uint16_t))); - memcpy(ack->GetData(), &id, sizeof(uint16_t)); - - if (ackOutChannel.Send(ack, 0) <= 0) { - LOG(ERROR) << "Could not send acknowledgement without blocking"; - } - } - - mTimeframeBuffer.erase(id); - } - - // LOG(WARN) << "Buffer size: " << fTimeframeBuffer.size(); - - // Check if any incomplete timeframes in the buffer are older than - // timeout period, and discard them if they are - // QUESTION: is this really what we want to do? - DiscardIncompleteTimeframes(); - } -} diff --git a/Utilities/DataFlow/src/FLPSenderDevice.cxx b/Utilities/DataFlow/src/FLPSenderDevice.cxx deleted file mode 100644 index cc37be574bb6d..0000000000000 --- a/Utilities/DataFlow/src/FLPSenderDevice.cxx +++ /dev/null @@ -1,101 +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. - -#include <cstdint> -#include <cassert> - -#include <FairMQLogger.h> -#include <FairMQMessage.h> -#include <options/FairMQProgOptions.h> - -#include "Headers/DataHeader.h" -#include "Headers/SubframeMetadata.h" -#include "DataFlow/FLPSenderDevice.h" -#include "O2Device/Compatibility.h" - -using namespace std; -using namespace std::chrono; -using namespace o2::devices; -using SubframeMetadata = o2::data_flow::SubframeMetadata; - -void FLPSenderDevice::InitTask() -{ - mIndex = GetConfig()->GetValue<int>("flp-index"); - mEventSize = GetConfig()->GetValue<int>("event-size"); - mNumEPNs = GetConfig()->GetValue<int>("num-epns"); - mTestMode = GetConfig()->GetValue<int>("test-mode"); - mSendOffset = GetConfig()->GetValue<int>("send-offset"); - mSendDelay = GetConfig()->GetValue<int>("send-delay"); - mInChannelName = GetConfig()->GetValue<string>("in-chan-name"); - mOutChannelName = GetConfig()->GetValue<string>("out-chan-name"); -} - -void FLPSenderDevice::Run() -{ - // base buffer, to be copied from for every timeframe body (zero-copy) - FairMQMessagePtr baseMsg(NewMessage(mEventSize)); - - // store the channel reference to avoid traversing the map on every loop iteration - //FairMQChannel& dataInChannel = fChannels.at(fInChannelName).at(0); - - while (compatibility::FairMQ13<FairMQDevice>::IsRunning(this)) { - // - Get the SubtimeframeMetadata - // - Add the current FLP id to the SubtimeframeMetadata - // - Forward to the EPN the whole subtimeframe - FairMQParts subtimeframeParts; - if (Receive(subtimeframeParts, mInChannelName, 0, 100) <= 0) { - continue; - } - - assert(subtimeframeParts.Size() != 0); - assert(subtimeframeParts.Size() >= 2); - const auto* dh = o2::header::get<header::DataHeader*>(subtimeframeParts.At(0)->GetData()); - assert(strncmp(dh->dataDescription.str, "SUBTIMEFRAMEMD", 16) == 0); - - SubframeMetadata* sfm = reinterpret_cast<SubframeMetadata*>(subtimeframeParts.At(1)->GetData()); - sfm->flpIndex = mIndex; - - mArrivalTime.push(steady_clock::now()); - mSTFBuffer.push(move(subtimeframeParts)); - - // if offset is 0 - send data out without staggering. - assert(mSTFBuffer.size() > 0); - - if (mSendOffset == 0 && mSTFBuffer.size() > 0) { - sendFrontData(); - } else if (mSTFBuffer.size() > 0) { - if (duration_cast<milliseconds>(steady_clock::now() - mArrivalTime.front()).count() >= (mSendDelay * mSendOffset)) { - sendFrontData(); - } else { - // LOG(INFO) << "buffering..."; - } - } - } -} - -inline void FLPSenderDevice::sendFrontData() -{ - SubframeMetadata* sfm = static_cast<SubframeMetadata*>(mSTFBuffer.front().At(1)->GetData()); - uint16_t currentTimeframeId = o2::data_flow::timeframeIdFromTimestamp(sfm->startTime, sfm->duration); - if (mLastTimeframeId != -1) { - if (currentTimeframeId == mLastTimeframeId) { - LOG(ERROR) << "Sent same consecutive timeframe ids\n"; - } - } - mLastTimeframeId = currentTimeframeId; - - // for which EPN is the message? - int direction = currentTimeframeId % mNumEPNs; - if (Send(mSTFBuffer.front(), mOutChannelName, direction, 0) < 0) { - LOG(ERROR) << "Failed to queue sub-timeframe #" << currentTimeframeId << " to EPN[" << direction << "]"; - } - mSTFBuffer.pop(); - mArrivalTime.pop(); -} diff --git a/Utilities/DataFlow/src/FakeTimeframeBuilder.cxx b/Utilities/DataFlow/src/FakeTimeframeBuilder.cxx deleted file mode 100644 index 66bcc4fbcea08..0000000000000 --- a/Utilities/DataFlow/src/FakeTimeframeBuilder.cxx +++ /dev/null @@ -1,119 +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. - -#include "DataFlow/FakeTimeframeBuilder.h" -#include "TimeFrame/TimeFrame.h" -#include "Headers/DataHeader.h" -#include <string> -#include <vector> -#include <functional> -#include <cstring> - -using DataHeader = o2::header::DataHeader; -using DataDescription = o2::header::DataDescription; -using DataOrigin = o2::header::DataOrigin; -using IndexElement = o2::dataformats::IndexElement; - -namespace -{ -o2::header::DataDescription lookupDataDescription(const char* key) -{ - if (strcmp(key, "RAWDATA") == 0) { - return o2::header::gDataDescriptionRawData; - } else if (strcmp(key, "CLUSTERS") == 0) { - return o2::header::gDataDescriptionClusters; - } else if (strcmp(key, "TRACKS") == 0) { - return o2::header::gDataDescriptionTracks; - } else if (strcmp(key, "CONFIG") == 0) { - return o2::header::gDataDescriptionConfig; - } else if (strcmp(key, "INFO") == 0) { - return o2::header::gDataDescriptionInfo; - } - return o2::header::gDataDescriptionInvalid; -} - -o2::header::DataOrigin lookupDataOrigin(const char* key) -{ - if (strcmp(key, "TPC") == 0) { - return o2::header::gDataOriginTPC; - } - if (strcmp(key, "TRD") == 0) { - return o2::header::gDataOriginTRD; - } - if (strcmp(key, "TOF") == 0) { - return o2::header::gDataOriginTOF; - } - if (strcmp(key, "ITS") == 0) { - return o2::header::gDataOriginITS; - } - return o2::header::gDataOriginInvalid; -} - -} // namespace - -namespace o2 -{ -namespace data_flow -{ - -std::unique_ptr<char[]> fakeTimeframeGenerator(std::vector<FakeTimeframeSpec>& specs, std::size_t& totalSize) -{ - // Calculate the total size of your timeframe. This is - // given by: - // - N*The size of the data header (this should actually depend on the - // kind of data as different dataDescriptions will probably have - // different headers). - // - Sum_N(The size of the buffer_i) - // - The size of the index header - // - N*sizeof(dataheader) - // Assuming all the data header - size_t sizeOfHeaders = specs.size() * sizeof(DataHeader); - size_t sizeOfBuffers = 0; - for (auto&& spec : specs) { - sizeOfBuffers += spec.bufferSize; - } - size_t sizeOfIndexHeader = sizeof(DataHeader); - size_t sizeOfIndex = sizeof(IndexElement) * specs.size(); - totalSize = sizeOfHeaders + sizeOfBuffers + sizeOfIndexHeader + sizeOfIndex; - - // Add the actual - data - auto buffer = std::make_unique<char[]>(totalSize); - char* bi = buffer.get(); - std::vector<IndexElement> headers; - int count = 0; - for (auto&& spec : specs) { - IndexElement el; - el.first.dataDescription = lookupDataDescription(spec.dataDescription); - el.first.dataOrigin = lookupDataOrigin(spec.origin); - el.first.payloadSize = spec.bufferSize; - el.first.headerSize = sizeof(el.first); - el.second = count++; - // Let's zero at least the header... - memset(bi, 0, sizeof(el.first)); - memcpy(bi, &el, sizeof(el.first)); - headers.push_back(el); - bi += sizeof(el.first); - spec.bufferFiller(bi, spec.bufferSize); - bi += spec.bufferSize; - } - - // Add the index - DataHeader index; - index.dataDescription = DataDescription("TIMEFRAMEINDEX"); - index.dataOrigin = DataOrigin("FKE"); - index.headerSize = sizeOfIndexHeader; - index.payloadSize = sizeOfIndex; - memcpy(bi, &index, sizeof(index)); - memcpy(bi + sizeof(index), headers.data(), headers.size() * sizeof(IndexElement)); - return std::move(buffer); -} - -} // namespace data_flow -} // namespace o2 diff --git a/Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx b/Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx deleted file mode 100644 index 81c07bcc82f5c..0000000000000 --- a/Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx +++ /dev/null @@ -1,92 +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. - -#include <cstring> - -#include "DataFlow/FakeTimeframeGeneratorDevice.h" -#include "DataFlow/FakeTimeframeBuilder.h" -#include "DataFlow/TimeframeParser.h" -#include "Headers/SubframeMetadata.h" -#include "Headers/DataHeader.h" -#include <options/FairMQProgOptions.h> -#include <vector> - -using DataHeader = o2::header::DataHeader; - -namespace -{ -struct OneShotReadBuf : public std::streambuf { - OneShotReadBuf(char* s, std::size_t n) - { - setg(s, s, s + n); - } -}; -} // namespace -namespace o2 -{ -namespace data_flow -{ - -FakeTimeframeGeneratorDevice::FakeTimeframeGeneratorDevice() - : O2Device{}, mOutChannelName{}, mMaxTimeframes{}, mTimeframeCount{0} -{ -} - -void FakeTimeframeGeneratorDevice::InitTask() -{ - mOutChannelName = GetConfig()->GetValue<std::string>(OptionKeyOutputChannelName); - mMaxTimeframes = GetConfig()->GetValue<size_t>(OptionKeyMaxTimeframes); -} - -bool FakeTimeframeGeneratorDevice::ConditionalRun() -{ - auto addPartFn = [this](FairMQParts& parts, char* buffer, size_t size) { - parts.AddPart(this->NewMessage( - buffer, - size, - [](void* data, void* hint) { delete[](char*) data; }, - nullptr)); - }; - auto sendFn = [this](FairMQParts& parts) { this->Send(parts, this->mOutChannelName); }; - auto zeroFiller = [](char* b, size_t s) { memset(b, 0, s); }; - - std::vector<o2::data_flow::FakeTimeframeSpec> specs = { - {.origin = "TPC", - .dataDescription = "CLUSTERS", - .bufferFiller = zeroFiller, - .bufferSize = 1000}, - {.origin = "ITS", - .dataDescription = "CLUSTERS", - .bufferFiller = zeroFiller, - .bufferSize = 500}}; - - try { - size_t totalSize; - auto buffer = fakeTimeframeGenerator(specs, totalSize); - OneShotReadBuf osrb(buffer.get(), totalSize); - std::istream s(&osrb); - - streamTimeframe(s, - addPartFn, - sendFn); - } catch (std::runtime_error& e) { - LOG(ERROR) << e.what() << "\n"; - } - - mTimeframeCount++; - - if (mTimeframeCount < mMaxTimeframes) { - return true; - } - return false; -} - -} // namespace data_flow -} // namespace o2 diff --git a/Utilities/DataFlow/src/HeartbeatSampler.cxx b/Utilities/DataFlow/src/HeartbeatSampler.cxx deleted file mode 100644 index d960a5941d9c9..0000000000000 --- a/Utilities/DataFlow/src/HeartbeatSampler.cxx +++ /dev/null @@ -1,59 +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. - -// @file HeartbeatSampler.h -// @author Matthias Richter -// @since 2017-02-03 -// @brief Heartbeat sampler device - -#include <thread> // this_thread::sleep_for -#include <chrono> - -#include "DataFlow/HeartbeatSampler.h" -#include "Headers/HeartbeatFrame.h" -#include <options/FairMQProgOptions.h> - -void o2::data_flow::HeartbeatSampler::InitTask() -{ - mPeriod = GetConfig()->GetValue<uint32_t>(OptionKeyPeriod); - mOutputChannelName = GetConfig()->GetValue<std::string>(OptionKeyOutputChannelName); -} - -bool o2::data_flow::HeartbeatSampler::ConditionalRun() -{ - std::this_thread::sleep_for(std::chrono::nanoseconds(mPeriod)); - - o2::header::HeartbeatStatistics hbfPayload; - - o2::header::DataHeader dh; - dh.dataDescription = o2::header::gDataDescriptionHeartbeatFrame; - dh.dataOrigin = o2::header::DataOrigin("SMPL"); - dh.subSpecification = 0; - dh.payloadSize = sizeof(hbfPayload); - - // Note: the block type of both header an trailer members of the envelope - // structure are autmatically initialized to the appropriate block type - // and size '1' (i.e. only one 64bit word) - o2::header::HeartbeatFrameEnvelope specificHeader; - specificHeader.header.orbit = mCount; - specificHeader.trailer.hbAccept = 1; - - O2Message outgoing; - - // build multipart message from header and payload - o2::base::addDataBlock(outgoing, {dh, specificHeader}, NewSimpleMessage(hbfPayload)); - - // send message - Send(outgoing, mOutputChannelName.c_str()); - outgoing.fParts.clear(); - - mCount++; - return true; -} diff --git a/Utilities/DataFlow/src/SubframeBuilderDevice.cxx b/Utilities/DataFlow/src/SubframeBuilderDevice.cxx deleted file mode 100644 index adad827e04a1f..0000000000000 --- a/Utilities/DataFlow/src/SubframeBuilderDevice.cxx +++ /dev/null @@ -1,149 +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. - -/// @file SubframeBuilderDevice.cxx -/// @author Giulio Eulisse, Matthias Richter, Sandro Wenzel -/// @since 2017-02-07 -/// @brief Demonstrator device for a subframe builder - -#include <thread> // this_thread::sleep_for -#include <chrono> -#include <functional> - -#include "DataFlow/SubframeBuilderDevice.h" -#include "DataFlow/SubframeUtils.h" -#include "Headers/SubframeMetadata.h" -#include "Headers/HeartbeatFrame.h" -#include "Headers/DataHeader.h" -#include <options/FairMQProgOptions.h> - -using HeartbeatHeader = o2::header::HeartbeatHeader; -using HeartbeatTrailer = o2::header::HeartbeatTrailer; -using DataHeader = o2::header::DataHeader; -using SubframeId = o2::dataflow::SubframeId; - -o2::data_flow::SubframeBuilderDevice::SubframeBuilderDevice() - : O2Device() -{ -} - -o2::data_flow::SubframeBuilderDevice::~SubframeBuilderDevice() = default; - -void o2::data_flow::SubframeBuilderDevice::InitTask() -{ - mOrbitDuration = GetConfig()->GetValue<uint32_t>(OptionKeyOrbitDuration); - mOrbitsPerTimeframe = GetConfig()->GetValue<uint32_t>(OptionKeyOrbitsPerTimeframe); - mInputChannelName = GetConfig()->GetValue<std::string>(OptionKeyInputChannelName); - mOutputChannelName = GetConfig()->GetValue<std::string>(OptionKeyOutputChannelName); - mFLPId = GetConfig()->GetValue<size_t>(OptionKeyFLPId); - mStripHBF = GetConfig()->GetValue<bool>(OptionKeyStripHBF); - - LOG(INFO) << "Obtaining data from DataPublisher\n"; - // Now that we have all the information lets create the policies to do the - // payload extraction and merging and create the actual PayloadMerger. - - // We extract the timeframeId from the number of orbits. - // FIXME: handle multiple socket ids - Merger::IdExtractor makeId = [this](std::unique_ptr<FairMQMessage>& msg) -> SubframeId { - HeartbeatHeader* hbh = reinterpret_cast<HeartbeatHeader*>(msg->GetData()); - SubframeId id = {.timeframeId = hbh->orbit / this->mOrbitsPerTimeframe, - .socketId = 0}; - return id; - }; - - // We extract the payload differently depending on wether we want to strip - // the header or not. - Merger::PayloadExtractor payloadExtractor = [this](char** out, char* in, size_t inSize) -> size_t { - if (!this->mStripHBF) { - return Merger::fullPayloadExtractor(out, in, inSize); - } - return o2::dataflow::extractDetectorPayloadStrip(out, in, inSize); - }; - - // Whether a given timeframe is complete depends on how many orbits per - // timeframe we want. - Merger::MergeCompletionCheker checkIfComplete = - [this](Merger::MergeableId id, Merger::MessageMap& map) { - return map.count(id) < this->mOrbitsPerTimeframe; - }; - - mMerger.reset(new Merger(makeId, checkIfComplete, payloadExtractor)); - OnData(mInputChannelName.c_str(), &o2::data_flow::SubframeBuilderDevice::HandleData); -} - -bool o2::data_flow::SubframeBuilderDevice::BuildAndSendFrame(FairMQParts& inParts) -{ - auto id = mMerger->aggregate(inParts.At(1)); - - char** outBuffer; - size_t outSize = mMerger->finalise(outBuffer, id); - // In this case we do not have enough subtimeframes for id, - // so we simply return. - if (outSize == 0) { - return true; - } - // If we reach here, it means we do have enough subtimeframes. - - // top level subframe header, the DataHeader is going to be used with - // description "SUBTIMEFRAMEMD" - // this should be defined in a common place, and also the origin - // the origin can probably name a detector identifier, but not sure if - // all CRUs of a FLP in all cases serve a single detector - o2::header::DataHeader dh; - dh.dataDescription = o2::header::DataDescription("SUBTIMEFRAMEMD"); - dh.dataOrigin = o2::header::DataOrigin("FLP"); - dh.subSpecification = mFLPId; - dh.payloadSize = sizeof(SubframeMetadata); - - DataHeader payloadheader(*o2::header::get<DataHeader*>((byte*)inParts.At(0)->GetData())); - - // subframe meta information as payload - SubframeMetadata md; - // id is really the first orbit in the timeframe. - md.startTime = id.timeframeId * mOrbitsPerTimeframe * static_cast<uint64_t>(mOrbitDuration); - md.duration = mOrbitDuration * mOrbitsPerTimeframe; - LOG(INFO) << "Start time for subframe (" << md.startTime << ", " - << md.duration - << ")"; - - // Add the metadata about the merged subtimeframes - // FIXME: do we really need this? - O2Message outgoing; - o2::base::addDataBlock(outgoing, dh, NewSimpleMessage(md)); - - // Add the actual merged payload. - o2::base::addDataBlock(outgoing, payloadheader, - NewMessage( - *outBuffer, outSize, - [](void* data, void* hint) { delete[] reinterpret_cast<char*>(hint); }, *outBuffer)); - // send message - Send(outgoing, mOutputChannelName.c_str()); - // FIXME: do we actually need this? outgoing should go out of scope - outgoing.fParts.clear(); - - return true; -} - -bool o2::data_flow::SubframeBuilderDevice::HandleData(FairMQParts& msgParts, int /*index*/) -{ - // loop over header payload pairs in the incoming multimessage - // for each pair - // - check timestamp - // - create new subtimeframe if none existing where the timestamp of the data fits - // - add pair to the corresponding subtimeframe - - // check for completed subtimeframes and send all completed frames - // the builder does not implement the routing to the EPN, this is done in the - // specific FLP-EPN setup - // to fit into the simple emulation of event/frame ids in the flpSender the order of - // subtimeframes needs to be preserved - BuildAndSendFrame(msgParts); - return true; -} diff --git a/Utilities/DataFlow/src/TimeframeParser.cxx b/Utilities/DataFlow/src/TimeframeParser.cxx deleted file mode 100644 index 4e3cc4f2001b8..0000000000000 --- a/Utilities/DataFlow/src/TimeframeParser.cxx +++ /dev/null @@ -1,204 +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. - -/// @file TimeframeValidatorDevice.cxx -/// @author Giulio Eulisse, Matthias Richter, Sandro Wenzel -/// @since 2017-02-07 -/// @brief Validator device for a full time frame - -#include <thread> // this_thread::sleep_for -#include <chrono> -#include <cstring> - -#include "DataFlow/TimeframeParser.h" -#include "Headers/SubframeMetadata.h" -#include "Headers/DataHeader.h" -#include "TimeFrame/TimeFrame.h" - -#include <options/FairMQProgOptions.h> -#include <FairMQParts.h> - -using DataHeader = o2::header::DataHeader; -using DataDescription = o2::header::DataDescription; -using IndexElement = o2::dataformats::IndexElement; - -namespace o2 -{ -namespace data_flow -{ - -// Possible states for the parsing of a timeframe -// PARSE_BEGIN_STREAM -> -enum ParsingState { - PARSE_BEGIN_STREAM = 0, - PARSE_BEGIN_TIMEFRAME, - PARSE_BEGIN_PAIR, - PARSE_DATA_HEADER, - PARSE_CONCRETE_HEADER, - PARSE_PAYLOAD, - PARSE_END_PAIR, - PARSE_END_TIMEFRAME, - PARSE_END_STREAM, - ERROR -}; - -struct StreamingState { - StreamingState() = default; - - ParsingState state = PARSE_BEGIN_STREAM; - bool hasDataHeader = false; - bool hasConcreteHeader = false; - void* payloadBuffer = nullptr; - void* headerBuffer = nullptr; - DataHeader dh; // The current DataHeader being parsed -}; - -void streamTimeframe(std::istream& stream, - std::function<void(FairMQParts& parts, char* buffer, size_t size)> onAddPart, - std::function<void(FairMQParts& parts)> onSend) -{ - FairMQParts parts; - StreamingState state; - assert(state.state == PARSE_BEGIN_STREAM); - while (true) { - switch (state.state) { - case PARSE_BEGIN_STREAM: - LOG(INFO) << "In PARSE_BEGIN_STREAM\n"; - state.state = PARSE_BEGIN_TIMEFRAME; - break; - case PARSE_BEGIN_TIMEFRAME: - LOG(INFO) << "In PARSE_BEGIN_TIMEFRAME\n"; - state.state = PARSE_BEGIN_PAIR; - break; - case PARSE_BEGIN_PAIR: - LOG(INFO) << "In PARSE_BEGIN_PAIR\n"; - state.state = PARSE_DATA_HEADER; - state.hasDataHeader = false; - state.payloadBuffer = nullptr; - state.headerBuffer = nullptr; - break; - case PARSE_DATA_HEADER: - LOG(INFO) << "In PARSE_DATA_HEADER\n"; - if (state.hasDataHeader) { - throw std::runtime_error("DataHeader already present."); - } else if (state.payloadBuffer) { - throw std::runtime_error("Unexpected payload."); - } - LOG(INFO) << "Reading dataheader of " << sizeof(state.dh) << " bytes\n"; - stream.read(reinterpret_cast<char*>(&state.dh), sizeof(state.dh)); - // If we have a TIMEFRAMEINDEX part and we find the eof, we are done. - if (stream.eof()) { - throw std::runtime_error("Premature end of stream"); - } - - // Otherwise we move to the state which is responsible for parsing the - // kind of header. - state.state = PARSE_CONCRETE_HEADER; - break; - case PARSE_CONCRETE_HEADER: - LOG(INFO) << "In PARSE_CONCRETE_HEADER\n"; - if (state.headerBuffer) { - throw std::runtime_error("File has two consecutive headers"); - } - if (state.dh.headerSize < sizeof(DataHeader)) { - std::ostringstream str; - str << "Bad header size. Should be greater then " - << sizeof(DataHeader) - << ". Found " << state.dh.headerSize << "\n"; - throw std::runtime_error(str.str()); - } - // We get the full header size and read the rest of the header - state.headerBuffer = malloc(state.dh.headerSize); - memcpy(state.headerBuffer, &state.dh, sizeof(state.dh)); - LOG(INFO) << "Reading rest of the header of " << state.dh.headerSize - sizeof(state.dh) << " bytes\n"; - stream.read(reinterpret_cast<char*>(state.headerBuffer) + sizeof(state.dh), - state.dh.headerSize - sizeof(state.dh)); - // Handle the case the file was truncated. - if (stream.eof()) { - throw std::runtime_error("Unexpected end of file"); - } - onAddPart(parts, reinterpret_cast<char*>(state.headerBuffer), state.dh.headerSize); - // Move to parse the payload - state.state = PARSE_PAYLOAD; - break; - case PARSE_PAYLOAD: - LOG(INFO) << "In PARSE_PAYLOAD\n"; - if (state.payloadBuffer) { - throw std::runtime_error("File has two consecutive payloads"); - } - state.payloadBuffer = new char[state.dh.payloadSize]; - LOG(INFO) << "Reading payload of " << state.dh.payloadSize << " bytes\n"; - stream.read(reinterpret_cast<char*>(state.payloadBuffer), state.dh.payloadSize); - if (stream.eof()) { - throw std::runtime_error("Unexpected end of file"); - } - onAddPart(parts, reinterpret_cast<char*>(state.payloadBuffer), state.dh.payloadSize); - state.state = PARSE_END_PAIR; - break; - case PARSE_END_PAIR: - LOG(INFO) << "In PARSE_END_PAIR\n"; - state.state = state.dh == DataDescription("TIMEFRAMEINDEX") ? PARSE_END_TIMEFRAME : PARSE_BEGIN_PAIR; - break; - case PARSE_END_TIMEFRAME: - LOG(INFO) << "In PARSE_END_TIMEFRAME\n"; - onSend(parts); - // Check if we have more. If not, we can declare success. - stream.peek(); - if (stream.eof()) { - state.state = PARSE_END_STREAM; - } else { - state.state = PARSE_BEGIN_TIMEFRAME; - } - break; - case PARSE_END_STREAM: - return; - break; - default: - break; - } - } -} - -void streamTimeframe(std::ostream& stream, FairMQParts& parts) -{ - if (parts.Size() < 2) { - throw std::runtime_error("Expecting at least 2 parts\n"); - } - - auto indexHeader = o2::header::get<DataHeader*>(parts.At(parts.Size() - 2)->GetData()); - // FIXME: Provide iterator pair API for the index - // Index should really be something which provides an - // iterator pair API so that we can sort / find / lower_bound - // easily. Right now we simply use it a C-style array. - auto index = reinterpret_cast<IndexElement*>(parts.At(parts.Size() - 1)->GetData()); - - LOG(INFO) << "This time frame has " << parts.Size() << " parts.\n"; - auto indexEntries = indexHeader->payloadSize / sizeof(IndexElement); - if (indexHeader->dataDescription != DataDescription("TIMEFRAMEINDEX")) { - throw std::runtime_error("Could not find a valid index header\n"); - } - LOG(INFO) << indexHeader->dataDescription.str << "\n"; - LOG(INFO) << "This time frame has " << indexEntries << "entries in the index.\n"; - if ((indexEntries * 2 + 2) != (parts.Size())) { - std::stringstream err; - err << "Mismatched index and received parts. Expected " - << (parts.Size() - 2 * 2) << " found " << indexEntries; - throw std::runtime_error(err.str()); - } - - LOG(INFO) << "Everything is fine with received timeframe\n"; - for (size_t i = 0; i < parts.Size(); ++i) { - stream.write(reinterpret_cast<const char*>(parts.At(i)->GetData()), - parts.At(i)->GetSize()); - } -} - -} // namespace data_flow -} // namespace o2 diff --git a/Utilities/DataFlow/src/TimeframeReaderDevice.cxx b/Utilities/DataFlow/src/TimeframeReaderDevice.cxx deleted file mode 100644 index 5113838bb0a5a..0000000000000 --- a/Utilities/DataFlow/src/TimeframeReaderDevice.cxx +++ /dev/null @@ -1,69 +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. - -#include <cstring> - -#include "DataFlow/TimeframeReaderDevice.h" -#include "DataFlow/TimeframeParser.h" -#include "Headers/SubframeMetadata.h" -#include "Headers/DataHeader.h" -#include <options/FairMQProgOptions.h> - -using DataHeader = o2::header::DataHeader; - -namespace o2 -{ -namespace data_flow -{ - -TimeframeReaderDevice::TimeframeReaderDevice() - : O2Device{}, mOutChannelName{}, mFile{} -{ -} - -void TimeframeReaderDevice::InitTask() -{ - mOutChannelName = GetConfig()->GetValue<std::string>(OptionKeyOutputChannelName); - mInFileName = GetConfig()->GetValue<std::string>(OptionKeyInputFileName); - mSeen.clear(); -} - -bool TimeframeReaderDevice::ConditionalRun() -{ - auto addPartFn = [this](FairMQParts& parts, char* buffer, size_t size) { - parts.AddPart(this->NewMessage( - buffer, - size, - [](void* data, void* hint) { delete[](char*) data; }, - nullptr)); - }; - auto sendFn = [this](FairMQParts& parts) { this->Send(parts, this->mOutChannelName); }; - - // FIXME: For the moment we support a single file. This should really be a glob. We - // should also have a strategy for watching directories. - std::vector<std::string> files; - files.push_back(mInFileName); - for (auto&& fn : files) { - mFile.open(fn, std::ofstream::in | std::ofstream::binary); - try { - streamTimeframe(mFile, - addPartFn, - sendFn); - } catch (std::runtime_error& e) { - LOG(ERROR) << e.what() << "\n"; - } - mSeen.push_back(fn); - } - - return false; -} - -} // namespace data_flow -} // namespace o2 diff --git a/Utilities/DataFlow/src/TimeframeValidationTool.cxx b/Utilities/DataFlow/src/TimeframeValidationTool.cxx deleted file mode 100644 index b3f1168006fc6..0000000000000 --- a/Utilities/DataFlow/src/TimeframeValidationTool.cxx +++ /dev/null @@ -1,65 +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. - -#include "DataFlow/TimeframeParser.h" -#include "fairmq/FairMQParts.h" -#include "Framework/Logger.h" -#include <vector> -#include <string> -#include <cctype> -#include <cstdio> -#include <cstdlib> -#include <unistd.h> -#include <fstream> - -// A simple tool which verifies timeframe files -int main(int argc, char** argv) -{ - int c; - opterr = 0; - - while ((c = getopt(argc, argv, "")) != -1) { - switch (c) { - case '?': - if (isprint(optopt)) { - fprintf(stderr, "Unknown option `-%c'.\n", optopt); - } else { - fprintf(stderr, - "Unknown option character `\\x%x'.\n", - optopt); - } - return 1; - default: - abort(); - } - } - - std::vector<std::string> filenames; - for (size_t index = optind; index < argc; index++) { - filenames.emplace_back(std::string(argv[index])); - } - - for (auto&& fn : filenames) { - LOG(INFO) << "Processing file" << fn << "\n"; - std::ifstream s(fn); - FairMQParts parts; - auto onAddParts = [](FairMQParts& p, char* buffer, size_t size) { - }; - auto onSend = [](FairMQParts& p) { - }; - - try { - o2::data_flow::streamTimeframe(s, onAddParts, onSend); - } catch (std::runtime_error& e) { - LOG(ERROR) << e.what() << std::endl; - exit(1); - } - } -} diff --git a/Utilities/DataFlow/src/TimeframeValidatorDevice.cxx b/Utilities/DataFlow/src/TimeframeValidatorDevice.cxx deleted file mode 100644 index 4f62bc621ef46..0000000000000 --- a/Utilities/DataFlow/src/TimeframeValidatorDevice.cxx +++ /dev/null @@ -1,152 +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. - -/// @file TimeframeValidatorDevice.cxx -/// @author Giulio Eulisse, Matthias Richter, Sandro Wenzel -/// @since 2017-02-07 -/// @brief Validator device for a full time frame - -#include <thread> // this_thread::sleep_for -#include <chrono> - -#include "DataFlow/TimeframeValidatorDevice.h" -#include "TimeFrame/TimeFrame.h" -#include "Headers/SubframeMetadata.h" -#include "Headers/DataHeader.h" -#include "O2Device/Compatibility.h" - -#include <options/FairMQProgOptions.h> - -using DataHeader = o2::header::DataHeader; -using DataOrigin = o2::header::DataOrigin; -using DataDescription = o2::header::DataDescription; -using IndexElement = o2::dataformats::IndexElement; - -o2::data_flow::TimeframeValidatorDevice::TimeframeValidatorDevice() - : O2Device(), mInChannelName() -{ -} - -void o2::data_flow::TimeframeValidatorDevice::InitTask() -{ - mInChannelName = GetConfig()->GetValue<std::string>(OptionKeyInputChannelName); -} - -void o2::data_flow::TimeframeValidatorDevice::Run() -{ - while (compatibility::FairMQ13<FairMQDevice>::IsRunning(this)) { - FairMQParts timeframeParts; - if (Receive(timeframeParts, mInChannelName, 0, 100) <= 0) { - continue; - } - - if (timeframeParts.Size() < 2) { - LOG(ERROR) << "Expecting at least 2 parts\n"; - } - - auto indexHeader = o2::header::get<header::DataHeader*>(timeframeParts.At(timeframeParts.Size() - 2)->GetData()); - // FIXME: Provide iterator pair API for the index - // Index should really be something which provides an - // iterator pair API so that we can sort / find / lower_bound - // easily. Right now we simply use it a C-style array. - auto index = reinterpret_cast<IndexElement*>(timeframeParts.At(timeframeParts.Size() - 1)->GetData()); - - // TODO: fill this with checks on time frame - LOG(INFO) << "This time frame has " << timeframeParts.Size() << " parts.\n"; - auto indexEntries = indexHeader->payloadSize / sizeof(DataHeader); - if (indexHeader->dataDescription != DataDescription("TIMEFRAMEINDEX")) { - LOG(ERROR) << "Could not find a valid index header\n"; - } - LOG(INFO) << indexHeader->dataDescription.str << "\n"; - LOG(INFO) << "This time frame has " << indexEntries << "entries in the index.\n"; - if ((indexEntries * 2 + 2) != (timeframeParts.Size())) { - LOG(ERROR) << "Mismatched index and received parts\n"; - } - - // - Use the index to find out if we have TPC data - // - Get the part with the TPC data - // - Validate TPCCluster dummy data - // - Validate ITSRaw dummy data - int tpcIndex = -1; - int itsIndex = -1; - - for (int ii = 0; ii < indexEntries; ++ii) { - IndexElement& ie = index[ii]; - assert(ie.second >= 0); - LOG(DEBUG) << ie.first.dataDescription.str << " " - << ie.first.dataOrigin.str << std::endl; - if ((ie.first.dataOrigin == header::gDataOriginTPC) && (ie.first.dataDescription == header::gDataDescriptionClusters)) { - tpcIndex = ie.second; - } - if ((ie.first.dataOrigin == header::gDataOriginITS) && (ie.first.dataDescription == header::gDataDescriptionClusters)) { - itsIndex = ie.second; - } - } - - if (tpcIndex < 0) { - LOG(ERROR) << "Could not find expected TPC payload\n"; - continue; - } - if (itsIndex < 0) { - LOG(ERROR) << "Could not find expected ITS payload\n"; - continue; - } - LOG(DEBUG) << "TPC Index " << tpcIndex << "\n"; - LOG(DEBUG) << "ITS Index " << itsIndex << "\n"; - - // Data header it at position - 1 - auto tpcHeader = reinterpret_cast<DataHeader*>(timeframeParts.At(tpcIndex)->GetData()); - if ((tpcHeader->dataDescription != header::gDataDescriptionClusters) || - (tpcHeader->dataOrigin != header::gDataOriginTPC)) { - LOG(ERROR) << "Wrong data description. Expecting TPC - CLUSTERS, found " - << tpcHeader->dataOrigin.str << " - " - << tpcHeader->dataDescription.str << "\n"; - continue; - } - auto tpcPayload = reinterpret_cast<TPCTestCluster*>(timeframeParts.At(tpcIndex + 1)->GetData()); - if (tpcHeader->payloadSize % sizeof(TPCTestCluster)) { - LOG(ERROR) << "TPC - CLUSTERS Size Mismatch\n"; - } - auto numOfClusters = tpcHeader->payloadSize / sizeof(TPCTestCluster); - for (size_t ci = 0; ci < numOfClusters; ++ci) { - TPCTestCluster& cluster = tpcPayload[ci]; - if (cluster.z != 1.5) { - LOG(ERROR) << "TPC Data mismatch. Expecting z = 1.5 got " << cluster.z << "\n"; - break; - } - if (cluster.timeStamp != ci) { - LOG(ERROR) << "TPC Data mismatch. Expecting " << ci << " got " << cluster.timeStamp << "\n"; - break; - } - } - - // Data header it at position - 1 - auto itsHeader = reinterpret_cast<DataHeader*>(timeframeParts.At(itsIndex)->GetData()); - if ((itsHeader->dataDescription != header::gDataDescriptionClusters) || (itsHeader->dataOrigin != header::gDataOriginITS)) { - LOG(ERROR) << "Wrong data description. Expecting ITS - CLUSTERS, found " - << itsHeader->dataOrigin.str << " - " << itsHeader->dataDescription.str << "\n"; - continue; - } - auto itsPayload = reinterpret_cast<ITSRawData*>(timeframeParts.At(itsIndex + 1)->GetData()); - if (itsHeader->payloadSize % sizeof(ITSRawData)) { - LOG(ERROR) << "ITS - CLUSTERS Size Mismatch.\n"; - } - numOfClusters = itsHeader->payloadSize / sizeof(ITSRawData); - for (size_t ci = 0; ci < numOfClusters; ++ci) { - ITSRawData& cluster = itsPayload[ci]; - if (cluster.timeStamp != ci) { - LOG(ERROR) << "ITS Data mismatch. Expecting " << ci - << " got " << cluster.timeStamp << "\n"; - break; - } - } - LOG(INFO) << "Everything is fine with received timeframe\n"; - } -} diff --git a/Utilities/DataFlow/src/TimeframeWriterDevice.cxx b/Utilities/DataFlow/src/TimeframeWriterDevice.cxx deleted file mode 100644 index 151ac59424880..0000000000000 --- a/Utilities/DataFlow/src/TimeframeWriterDevice.cxx +++ /dev/null @@ -1,96 +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. - -/// @file TimeframeValidatorDevice.cxx -/// @author Giulio Eulisse, Matthias Richter, Sandro Wenzel -/// @since 2017-02-07 -/// @brief Validator device for a full time frame - -#include <thread> // this_thread::sleep_for -#include <chrono> - -#include "DataFlow/TimeframeWriterDevice.h" -#include "DataFlow/TimeframeParser.h" -#include "TimeFrame/TimeFrame.h" -#include "Headers/SubframeMetadata.h" -#include "Headers/DataHeader.h" -#include "O2Device/Compatibility.h" - -#include <options/FairMQProgOptions.h> -#include <boost/filesystem.hpp> - -using DataHeader = o2::header::DataHeader; -using IndexElement = o2::dataformats::IndexElement; - -namespace o2 -{ -namespace data_flow -{ - -TimeframeWriterDevice::TimeframeWriterDevice() - : O2Device{}, mInChannelName{}, mFile{}, mMaxTimeframes{}, mMaxFileSize{}, mMaxFiles{}, mFileCount{0} -{ -} - -void TimeframeWriterDevice::InitTask() -{ - mInChannelName = GetConfig()->GetValue<std::string>(OptionKeyInputChannelName); - mOutFileName = GetConfig()->GetValue<std::string>(OptionKeyOutputFileName); - mMaxTimeframes = GetConfig()->GetValue<size_t>(OptionKeyMaxTimeframesPerFile); - mMaxFileSize = GetConfig()->GetValue<size_t>(OptionKeyMaxFileSize); - mMaxFiles = GetConfig()->GetValue<size_t>(OptionKeyMaxFiles); -} - -void TimeframeWriterDevice::Run() -{ - boost::filesystem::path p(mOutFileName); - size_t streamedTimeframes = 0; - bool needsNewFile = true; - while (compatibility::FairMQ13<FairMQDevice>::IsRunning(this) && mFileCount < mMaxFiles) { - // In case we need to process more than one file, - // the filename is split in basename and extension - // and we call the files `<basename><count>.<extension>`. - if (needsNewFile) { - std::string filename = mOutFileName; - if (mMaxFiles > 1) { - std::string base_path(mOutFileName, 0, mOutFileName.find_last_of(".")); - std::string extension(mOutFileName, mOutFileName.find_last_of(".")); - filename = base_path + std::to_string(mFileCount) + extension; - } - LOG(INFO) << "Opening " << filename << " for output\n"; - mFile.open(filename.c_str(), std::ofstream::out | std::ofstream::binary); - needsNewFile = false; - } - - FairMQParts timeframeParts; - if (Receive(timeframeParts, mInChannelName, 0, 100) <= 0) { - continue; - } - - streamTimeframe(mFile, timeframeParts); - if ((mFile.tellp() > mMaxFileSize) || (streamedTimeframes++ > mMaxTimeframes)) { - mFile.flush(); - mFile.close(); - mFileCount++; - needsNewFile = true; - } - } -} - -void TimeframeWriterDevice::PostRun() -{ - if (mFile.is_open()) { - mFile.flush(); - mFile.close(); - } -} - -} // namespace data_flow -} // namespace o2 diff --git a/Utilities/DataFlow/src/runEPNReceiver.cxx b/Utilities/DataFlow/src/runEPNReceiver.cxx deleted file mode 100644 index b4681116052df..0000000000000 --- a/Utilities/DataFlow/src/runEPNReceiver.cxx +++ /dev/null @@ -1,41 +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. - -/** - * runEPNReceiver.cxx - * - * @since 2013-01-21 - * @author D. Klein, A. Rybalchenko, M. Al-Turany, C. Kouzinopoulos - */ - -#include "runFairMQDevice.h" -#include "DataFlow/EPNReceiverDevice.h" - -#include <string> - -namespace bpo = boost::program_options; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - ("buffer-timeout", bpo::value<int>()->default_value(1000), "Buffer timeout in milliseconds") - ("num-flps", bpo::value<int>()->required(), "Number of FLPs") - ("test-mode", bpo::value<int>()->default_value(0), "Run in test mode") - ("in-chan-name", bpo::value<std::string>()->default_value("stf2"), "Name of the input channel (sub-time frames)") - ("out-chan-name", bpo::value<std::string>()->default_value("tf"), "Name of the output channel (time frames)") - ("ack-chan-name", bpo::value<std::string>()->default_value("ack"), "Name of the acknowledgement channel"); - // clang-format on -} - -FairMQDevice* getDevice(const FairMQProgOptions& config) -{ - return new o2::devices::EPNReceiverDevice(); -} diff --git a/Utilities/DataFlow/src/runFLPSender.cxx b/Utilities/DataFlow/src/runFLPSender.cxx deleted file mode 100644 index ed2b94d648954..0000000000000 --- a/Utilities/DataFlow/src/runFLPSender.cxx +++ /dev/null @@ -1,36 +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. - -#include "runFairMQDevice.h" -#include "DataFlow/FLPSenderDevice.h" - -#include <string> - -namespace bpo = boost::program_options; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - ("flp-index", bpo::value<int>()->default_value(0), "FLP Index (for debugging in test mode)") - ("event-size", bpo::value<int>()->default_value(1000), "Event size in bytes (test mode)") - ("num-epns", bpo::value<int>()->required(), "Number of EPNs") - ("test-mode", bpo::value<int>()->default_value(0), "Run in test mode") - ("send-offset", bpo::value<int>()->default_value(0), "Offset for staggered sending") - ("send-delay", bpo::value<int>()->default_value(8), "Delay for staggered sending") - ("in-chan-name", bpo::value<std::string>()->default_value("stf1"), "Name of the input channel (sub-time frames)") - ("out-chan-name", bpo::value<std::string>()->default_value("stf2"), "Name of the output channel (sub-time frames)"); - // clang-format on -} - -FairMQDevice* getDevice(const FairMQProgOptions& config) -{ - return new o2::devices::FLPSenderDevice(); -} diff --git a/Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx b/Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx deleted file mode 100644 index 755cf2b8f111f..0000000000000 --- a/Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx +++ /dev/null @@ -1,34 +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. - -#include "runFairMQDevice.h" -#include "DataFlow/FakeTimeframeGeneratorDevice.h" -#include <vector> - -namespace bpo = boost::program_options; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - (o2::data_flow::FakeTimeframeGeneratorDevice::OptionKeyOutputChannelName, - bpo::value<std::string>()->default_value("output"), - "Name of the output channel"); - options.add_options() - (o2::data_flow::FakeTimeframeGeneratorDevice::OptionKeyMaxTimeframes, - bpo::value<std::string>()->default_value("1"), - "Number of timeframes to generate"); - // clang-format on -} - -FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) -{ - return new o2::data_flow::FakeTimeframeGeneratorDevice(); -} diff --git a/Utilities/DataFlow/src/runHeartbeatSampler.cxx b/Utilities/DataFlow/src/runHeartbeatSampler.cxx deleted file mode 100644 index e5fcd7b12c6b2..0000000000000 --- a/Utilities/DataFlow/src/runHeartbeatSampler.cxx +++ /dev/null @@ -1,32 +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. - -#include "runFairMQDevice.h" -#include "DataFlow/HeartbeatSampler.h" - -namespace bpo = boost::program_options; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - (o2::data_flow::HeartbeatSampler::OptionKeyPeriod, - bpo::value<uint32_t>()->default_value(1000000000), - "sampling period") - (o2::data_flow::HeartbeatSampler::OptionKeyOutputChannelName, - bpo::value<std::string>()->default_value("output"), - "Name of the output channel"); - // clang-format on -} - -FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) -{ - return new o2::data_flow::HeartbeatSampler(); -} diff --git a/Utilities/DataFlow/src/runSubframeBuilderDevice.cxx b/Utilities/DataFlow/src/runSubframeBuilderDevice.cxx deleted file mode 100644 index 1c26bf66d6e5f..0000000000000 --- a/Utilities/DataFlow/src/runSubframeBuilderDevice.cxx +++ /dev/null @@ -1,50 +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. - -#include "runFairMQDevice.h" -#include "DataFlow/SubframeBuilderDevice.h" - -namespace bpo = boost::program_options; - -constexpr uint32_t o2::data_flow::SubframeBuilderDevice::DefaultOrbitDuration; -constexpr uint32_t o2::data_flow::SubframeBuilderDevice::DefaultOrbitsPerTimeframe; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - (o2::data_flow::SubframeBuilderDevice::OptionKeyOrbitDuration, - bpo::value<uint32_t>()->default_value(o2::data_flow::SubframeBuilderDevice::DefaultOrbitDuration), - "Orbit duration") - (o2::data_flow::SubframeBuilderDevice::OptionKeyOrbitsPerTimeframe, - bpo::value<uint32_t>()->default_value(o2::data_flow::SubframeBuilderDevice::DefaultOrbitsPerTimeframe), - "Orbits per timeframe") - (o2::data_flow::SubframeBuilderDevice::OptionKeyInputChannelName, - bpo::value<std::string>()->default_value("input"), - "Name of the input channel") - (o2::data_flow::SubframeBuilderDevice::OptionKeyOutputChannelName, - bpo::value<std::string>()->default_value("output"), - "Name of the output channel") - (o2::data_flow::SubframeBuilderDevice::OptionKeyDetector, - bpo::value<std::string>()->default_value("TPC"), - "Name of detector as data source") - (o2::data_flow::SubframeBuilderDevice::OptionKeyFLPId, - bpo::value<size_t>()->default_value(0), - "ID of the FLP used as data source") - (o2::data_flow::SubframeBuilderDevice::OptionKeyStripHBF, - bpo::bool_switch()->default_value(false), - "Strip HBH & HBT from each HBF"); - // clang-format on -} - -FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) -{ - return new o2::data_flow::SubframeBuilderDevice(); -} diff --git a/Utilities/DataFlow/src/runTimeframeReaderDevice.cxx b/Utilities/DataFlow/src/runTimeframeReaderDevice.cxx deleted file mode 100644 index 57574a0dd7811..0000000000000 --- a/Utilities/DataFlow/src/runTimeframeReaderDevice.cxx +++ /dev/null @@ -1,33 +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. - -#include "runFairMQDevice.h" -#include "DataFlow/TimeframeReaderDevice.h" - -namespace bpo = boost::program_options; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - (o2::data_flow::TimeframeReaderDevice::OptionKeyOutputChannelName, - bpo::value<std::string>()->default_value("output"), - "Name of the output channel"); - options.add_options() - (o2::data_flow::TimeframeReaderDevice::OptionKeyInputFileName, - bpo::value<std::string>()->default_value("data.o2tf"), - "Name of the input file"); - // clang-format on -} - -FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) -{ - return new o2::data_flow::TimeframeReaderDevice(); -} diff --git a/Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx b/Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx deleted file mode 100644 index 34b5e90d46e69..0000000000000 --- a/Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx +++ /dev/null @@ -1,29 +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. - -#include "runFairMQDevice.h" -#include "DataFlow/TimeframeValidatorDevice.h" - -namespace bpo = boost::program_options; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - (o2::data_flow::TimeframeValidatorDevice::OptionKeyInputChannelName, - bpo::value<std::string>()->default_value("input"), - "Name of the input channel"); - // clang-format on -} - -FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) -{ - return new o2::data_flow::TimeframeValidatorDevice(); -} diff --git a/Utilities/DataFlow/src/runTimeframeWriterDevice.cxx b/Utilities/DataFlow/src/runTimeframeWriterDevice.cxx deleted file mode 100644 index 112c0cb3f8be1..0000000000000 --- a/Utilities/DataFlow/src/runTimeframeWriterDevice.cxx +++ /dev/null @@ -1,45 +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. - -#include "runFairMQDevice.h" -#include "DataFlow/TimeframeWriterDevice.h" - -namespace bpo = boost::program_options; - -void addCustomOptions(bpo::options_description& options) -{ - // clang-format off - options.add_options() - (o2::data_flow::TimeframeWriterDevice::OptionKeyInputChannelName, - bpo::value<std::string>()->default_value("input"), - "Name of the input channel"); - options.add_options() - (o2::data_flow::TimeframeWriterDevice::OptionKeyOutputFileName, - bpo::value<std::string>()->default_value("data.o2tf"), - "Name of the input channel"); - options.add_options() - (o2::data_flow::TimeframeWriterDevice::OptionKeyMaxFiles, - bpo::value<size_t>()->default_value(1), - "Maximum number of files to write"); - options.add_options() - (o2::data_flow::TimeframeWriterDevice::OptionKeyMaxTimeframesPerFile, - bpo::value<size_t>()->default_value(1), - "Maximum number of timeframes per file"); - options.add_options() - (o2::data_flow::TimeframeWriterDevice::OptionKeyMaxFileSize, - bpo::value<size_t>()->default_value(-1), - "Maximum size per file"); - // clang-format on -} - -FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) -{ - return new o2::data_flow::TimeframeWriterDevice(); -} diff --git a/Utilities/DataFlow/test/test_PayloadMerger01.cxx b/Utilities/DataFlow/test/test_PayloadMerger01.cxx deleted file mode 100644 index 40cc1e252a84c..0000000000000 --- a/Utilities/DataFlow/test/test_PayloadMerger01.cxx +++ /dev/null @@ -1,83 +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. -#define BOOST_TEST_MODULE Test Utilities DataFlowTest -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK - -#include <boost/test/unit_test.hpp> - -#include <iostream> -#include <memory> -#include "DataFlow/PayloadMerger.h" -#include "DataFlow/FakeTimeframeBuilder.h" -#include "DataFlow/TimeframeParser.h" -#include "DataFlow/SubframeUtils.h" -#include "fairmq/FairMQTransportFactory.h" -#include "fairmq/FairMQParts.h" - -using SubframeId = o2::dataflow::SubframeId; -using HeartbeatHeader = o2::header::HeartbeatHeader; -using HeartbeatTrailer = o2::header::HeartbeatTrailer; - -SubframeId fakeAddition(o2::dataflow::PayloadMerger<SubframeId>& merger, - std::shared_ptr<FairMQTransportFactory>& transport, - int64_t orbit) -{ - // Create a message - // - // We set orbit to be always the same and the actual contents to be 127 - static size_t dummyMessageSize = 1000; - auto msg = transport->CreateMessage(dummyMessageSize); - char* b = reinterpret_cast<char*>(msg->GetData()) + sizeof(HeartbeatHeader); - for (size_t i = 0; i < (dummyMessageSize - sizeof(HeartbeatHeader)); ++i) { - b[i] = orbit; - } - b[0] = 127; - HeartbeatHeader* header = reinterpret_cast<HeartbeatHeader*>(msg->GetData()); - header->orbit = orbit; - return merger.aggregate(msg); -} - -BOOST_AUTO_TEST_CASE(PayloadMergerTest) -{ - auto zmq = FairMQTransportFactory::CreateTransportFactory("zeromq"); - - // Needs three subtimeframes to merge them - auto checkIfComplete = [](SubframeId id, o2::dataflow::PayloadMerger<SubframeId>::MessageMap& m) -> bool { - return m.count(id) >= 3; - }; - - // Id is given by the orbit, 2 orbits per timeframe - auto makeId = [](std::unique_ptr<FairMQMessage>& msg) { - auto header = reinterpret_cast<o2::header::HeartbeatHeader const*>(msg->GetData()); - return o2::dataflow::makeIdFromHeartbeatHeader(*header, 0, 2); - }; - - o2::dataflow::PayloadMerger<SubframeId> merger(makeId, checkIfComplete, o2::dataflow::extractDetectorPayloadStrip); - char* finalBuf = new char[3000]; - size_t finalSize = 0; - auto id = fakeAddition(merger, zmq, 1); - finalSize = merger.finalise(&finalBuf, id); - BOOST_CHECK(finalSize == 0); // Not enough parts, not merging yet. - id = fakeAddition(merger, zmq, 1); - finalSize = merger.finalise(&finalBuf, id); - BOOST_CHECK(finalSize == 0); // Not enough parts, not merging yet. - id = fakeAddition(merger, zmq, 2); - finalSize = merger.finalise(&finalBuf, id); - BOOST_CHECK(finalSize == 0); // Different ID, not merging yet. - id = fakeAddition(merger, zmq, 1); - finalSize = merger.finalise(&finalBuf, id); - BOOST_CHECK(finalSize); // Now we merge! - size_t partSize = (1000 - sizeof(HeartbeatHeader) - sizeof(HeartbeatTrailer)); - BOOST_CHECK(finalSize == 3 * partSize); // This should be the calculated size - for (size_t i = 0; i < finalSize; ++i) { - BOOST_CHECK(finalBuf[i] == ((i % partSize) == 0 ? 127 : 1)); - } -} diff --git a/Utilities/DataFlow/test/test_SubframeUtils01.cxx b/Utilities/DataFlow/test/test_SubframeUtils01.cxx deleted file mode 100644 index 32605f9075808..0000000000000 --- a/Utilities/DataFlow/test/test_SubframeUtils01.cxx +++ /dev/null @@ -1,59 +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. - -#define BOOST_TEST_MODULE Test Utilities DataFlowTest -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK - -#include "DataFlow/SubframeUtils.h" -#include <boost/test/unit_test.hpp> -#include <iostream> - -BOOST_AUTO_TEST_CASE(SubframeUtils01) -{ - o2::dataflow::SubframeId a; - a.timeframeId = 0; - a.socketId = 1; - o2::dataflow::SubframeId b; - b.timeframeId = 1; - b.socketId = 0; - BOOST_CHECK(a < b); - char* buf = new char[1000]; - memset(buf, 126, 1000); - for (size_t i = sizeof(o2::header::HeartbeatHeader); i < 1000 - sizeof(o2::header::HeartbeatHeader); ++i) { - buf[i] = 0; - } - BOOST_CHECK(buf[0] == 126); - BOOST_CHECK(buf[sizeof(o2::header::HeartbeatHeader)] == 0); - BOOST_CHECK(buf[sizeof(o2::header::HeartbeatHeader) - 1] == 126); - char* realPayload = nullptr; - size_t realSize = o2::dataflow::extractDetectorPayloadStrip(&realPayload, buf, 1000); - BOOST_CHECK(realPayload != nullptr); - BOOST_CHECK(realSize == 1000 - sizeof(o2::header::HeartbeatHeader) - sizeof(o2::header::HeartbeatTrailer)); - BOOST_CHECK(realPayload == buf + sizeof(o2::header::HeartbeatHeader)); - BOOST_CHECK(realPayload[0] == 0); - - o2::header::HeartbeatHeader header1; - header1.orbit = 0; - o2::header::HeartbeatHeader header2; - header2.orbit = 255; - o2::header::HeartbeatHeader header3; - header3.orbit = 256; - - auto id1 = o2::dataflow::makeIdFromHeartbeatHeader(header1, 1, 256); - auto id2 = o2::dataflow::makeIdFromHeartbeatHeader(header2, 1, 256); - auto id3 = o2::dataflow::makeIdFromHeartbeatHeader(header3, 1, 256); - BOOST_CHECK(!(id1 < id2)); // Maybe we should provide an == operator - BOOST_CHECK(!(id2 < id1)); - BOOST_CHECK(id1 < id3); - BOOST_CHECK(id2 < id3); - BOOST_CHECK(id1.timeframeId == 0); - BOOST_CHECK(id3.timeframeId == 1); -} diff --git a/Utilities/DataFlow/test/test_TimeframeParser.cxx b/Utilities/DataFlow/test/test_TimeframeParser.cxx deleted file mode 100644 index 37e6f5af09c36..0000000000000 --- a/Utilities/DataFlow/test/test_TimeframeParser.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. - -#include "DataFlow/TimeframeParser.h" -#include "DataFlow/FakeTimeframeBuilder.h" -#include "Headers/DataHeader.h" -#include "Framework/Logger.h" -#include <FairMQParts.h> -#include <istream> -#include <cstdlib> - -struct OneShotReadBuf : public std::streambuf { - OneShotReadBuf(char* s, std::size_t n) - { - setg(s, s, s + n); - } -}; - -using DataHeader = o2::header::DataHeader; - -int main(int argc, char** argv) -{ - // Construct a dummy timeframe. - // Stream it and get the parts - FairMQParts parts; - auto onAddParts = [](FairMQParts& p, char* buffer, size_t size) { - LOG(INFO) << "Adding part to those to be sent.\n"; - }; - auto onSend = [](FairMQParts& p) { - LOG(INFO) << "Everything OK. Sending parts\n"; - }; - - // Prepare a test timeframe to be streamed - auto zeroFiller = [](char* b, size_t s) { memset(b, 0, s); }; - std::vector<o2::data_flow::FakeTimeframeSpec> specs = { - {.origin = "TPC", - .dataDescription = "CLUSTERS", - .bufferFiller = zeroFiller, - .bufferSize = 1000}}; - - size_t testBufferSize; - auto testBuffer = fakeTimeframeGenerator(specs, testBufferSize); - - OneShotReadBuf osrb(testBuffer.get(), testBufferSize); - std::istream s(&osrb); - - try { - o2::data_flow::streamTimeframe(s, onAddParts, onSend); - } catch (std::runtime_error& e) { - LOG(ERROR) << e.what() << std::endl; - exit(1); - } -} From 5beaf6a0caeb7088137fd5a7df9e92e6c36533f4 Mon Sep 17 00:00:00 2001 From: Maciej Slupecki <maciej.slupecki@gmail.com> Date: Mon, 11 Jan 2021 15:06:05 +0100 Subject: [PATCH 1737/1751] [FV0] Trigger inputs --- .../FIT/FV0/include/DataFormatsFV0/BCData.h | 28 +++++++++++++++---- .../FIT/FV0/src/DataFormatsFV0LinkDef.h | 2 ++ .../include/FV0Simulation/Digitizer.h | 9 ++++-- .../FIT/FV0/simulation/src/Digitizer.cxx | 28 +++++++++++++------ .../src/FV0DigitWriterSpec.h | 3 +- .../src/FV0DigitizerSpec.cxx | 7 +++-- 6 files changed, 58 insertions(+), 19 deletions(-) diff --git a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h index 9843afb2c9393..3025273b09f99 100644 --- a/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h +++ b/DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h @@ -15,6 +15,7 @@ #include "CommonDataFormat/RangeReference.h" #include <Rtypes.h> #include <gsl/span> +#include <bitset> /// \file BCData.h /// \brief Class to describe fired triggered and/or stored channels for the BC and to refer to channel data @@ -29,9 +30,10 @@ class ChannelData; struct Triggers { enum { bitMinBias, - bitMinBiasInner, - bitMinBiasOuter, - bitHighMult + bitMinBiasInner, // experimental + bitMinBiasOuter, // experimental + bitHighMult, + bitDummy // non-defined yet, placeholder }; uint8_t triggerSignals = 0; // V0 trigger signals int8_t nChanA = 0; // number of fired channels [A side] @@ -50,9 +52,9 @@ struct Triggers { bool getIsMinBiasOuter() const { return (triggerSignals & (1 << bitMinBiasOuter)) != 0; } bool getIsHighMult() const { return (triggerSignals & (1 << bitHighMult)) != 0; } - void setTriggers(Bool_t isMinBias, Bool_t isMinBiasInner, Bool_t isMinBiasOuter, Bool_t isHighMult, int8_t chanA, int32_t amplASum) + void setTriggers(Bool_t isMinBias, Bool_t isMinBiasInner, Bool_t isMinBiasOuter, Bool_t isHighMult, Bool_t isDummy, int8_t chanA, int32_t amplASum) { - triggerSignals = (isMinBias << bitMinBias) | (isMinBiasInner << bitMinBiasInner) | (isMinBiasOuter << bitMinBiasOuter) | (isHighMult << bitHighMult); + triggerSignals = (isMinBias << bitMinBias) | (isMinBiasInner << bitMinBiasInner) | (isMinBiasOuter << bitMinBiasOuter) | (isHighMult << bitHighMult) | (isDummy << bitDummy); nChanA = chanA; amplA = amplASum; } @@ -60,6 +62,22 @@ struct Triggers { ClassDefNV(Triggers, 1); }; +struct DetTrigInput { + o2::InteractionRecord mIntRecord; // bc/orbit of the intpur + std::bitset<5> mInputs; // pattern of inputs. + DetTrigInput() = default; + DetTrigInput(const o2::InteractionRecord& iRec, Bool_t isMb, Bool_t isMbIn, Bool_t isMbOut, Bool_t isHm, Bool_t isDummy) + : mIntRecord(iRec), + mInputs((isMb << Triggers::bitMinBias) | + (isMbIn << Triggers::bitMinBiasInner) | + (isMbOut << Triggers::bitMinBiasOuter) | + (isHm << Triggers::bitHighMult) | + (isDummy << Triggers::bitDummy)) + { + } + ClassDefNV(DetTrigInput, 1); +}; + struct BCData { /// we are going to refer to at most 48 channels, so 6 bits for the number of channels and 26 for the reference o2::dataformats::RangeRefComp<6> ref; diff --git a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h index b22a7f68daecb..ae77b276b8399 100644 --- a/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h +++ b/DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h @@ -21,8 +21,10 @@ #pragma link C++ class o2::fv0::ChannelData + ; #pragma link C++ class o2::fv0::BCData + ; #pragma link C++ class o2::fv0::Triggers + ; +#pragma link C++ class o2::fv0::DetTrigInput + ; #pragma link C++ class std::vector < o2::fv0::ChannelData> + ; #pragma link C++ class std::vector < o2::fv0::Triggers> + ; +#pragma link C++ class std::vector < o2::fv0::DetTrigInput> + ; #pragma link C++ class std::vector < o2::fv0::BCData> + ; #pragma link C++ class o2::fv0::RawEventData + ; diff --git a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h index c03614b0d5ecd..0eba60c97bab3 100644 --- a/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h +++ b/Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h @@ -54,10 +54,12 @@ class Digitizer void setInteractionRecord(const InteractionTimeRecord& ir) { mIntRecord = ir; } void process(const std::vector<o2::fv0::Hit>& hits, std::vector<o2::fv0::BCData>& digitsBC, - std::vector<o2::fv0::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels); + std::vector<o2::fv0::ChannelData>& digitsCh, std::vector<o2::fv0::DetTrigInput>& digitsTrig, + o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels); void flush(std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv0::ChannelData>& digitsCh, + std::vector<o2::fv0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels); const InteractionRecord& getInteractionRecord() const { return mIntRecord; } @@ -102,7 +104,10 @@ class Digitizer BCCache& setBCCache(const o2::InteractionRecord& ir); BCCache* getBCCache(const o2::InteractionRecord& ir); - void storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv0::ChannelData>& digitsCh, + void storeBC(const BCCache& bc, + std::vector<o2::fv0::BCData>& digitsBC, + std::vector<o2::fv0::ChannelData>& digitsCh, + std::vector<o2::fv0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels); std::array<std::vector<Float_t>, Constants::nFv0Channels> mPmtChargeVsTime; // Charge time series aka analogue signal pulse from PM diff --git a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx index 406d9a15c6a17..c8cd42e29145d 100644 --- a/Detectors/FIT/FV0/simulation/src/Digitizer.cxx +++ b/Detectors/FIT/FV0/simulation/src/Digitizer.cxx @@ -62,11 +62,14 @@ void Digitizer::init() LOG(INFO) << "V0Digitizer::init -> finished"; } -void Digitizer::process(const std::vector<o2::fv0::Hit>& hits, std::vector<o2::fv0::BCData>& digitsBC, - std::vector<o2::fv0::ChannelData>& digitsCh, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels) +void Digitizer::process(const std::vector<o2::fv0::Hit>& hits, + std::vector<o2::fv0::BCData>& digitsBC, + std::vector<o2::fv0::ChannelData>& digitsCh, + std::vector<o2::fv0::DetTrigInput>& digitsTrig, + o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels) { LOG(INFO) << "[FV0] Digitizer::process(): begin with " << hits.size() << " hits"; - flush(digitsBC, digitsCh, labels); // flush cached signal which cannot be affect by new event + flush(digitsBC, digitsCh, digitsTrig, labels); // flush cached signal which cannot be affect by new event std::vector<int> hitIdx(hits.size()); std::iota(std::begin(hitIdx), std::end(hitIdx), 0); @@ -171,7 +174,9 @@ void Digitizer::createPulse(float mipFraction, int parID, const double hitTime, } } -void Digitizer::flush(std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv0::ChannelData>& digitsCh, +void Digitizer::flush(std::vector<o2::fv0::BCData>& digitsBC, + std::vector<o2::fv0::ChannelData>& digitsCh, + std::vector<o2::fv0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels) { int nCached = mCache.size(); @@ -180,7 +185,7 @@ void Digitizer::flush(std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv } for (auto bc : mCache) { if (mIntRecord.differenceInBC(bc) > NBC2Cache) { // Build events those are separated by NBC2Cache BCs from current BC - storeBC(bc, digitsBC, digitsCh, labels); + storeBC(bc, digitsBC, digitsCh, digitsTrig, labels); mCache.pop_front(); } else { return; @@ -188,7 +193,10 @@ void Digitizer::flush(std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv } } -void Digitizer::storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsBC, std::vector<o2::fv0::ChannelData>& digitsCh, +void Digitizer::storeBC(const BCCache& bc, + std::vector<o2::fv0::BCData>& digitsBC, + std::vector<o2::fv0::ChannelData>& digitsCh, + std::vector<o2::fv0::DetTrigInput>& digitsTrig, o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>& labels) { @@ -229,16 +237,18 @@ void Digitizer::storeBC(const BCCache& bc, std::vector<o2::fv0::BCData>& digitsB totalChargeAllRing *= DP::INV_CHARGE_PER_ADC; //LOG(INFO)<<"Total charge ADC " <<totalChargeAllRing ; ///Triggers for FV0 - bool isMinBias, isMinBiasInner, isMinBiasOuter, isHighMult; + bool isMinBias, isMinBiasInner, isMinBiasOuter, isHighMult, isDummy; isMinBias = nStored > 0; isMinBiasInner = nSignalInner > 0; //ring 1,2 and 3 isMinBiasOuter = nSignalOuter > 0; //ring 4 and 5 isHighMult = totalChargeAllRing > FV0DigParam::Instance().adcChargeHighMultTh; + isDummy = false; Triggers triggers; - triggers.setTriggers(isMinBias, isMinBiasInner, isMinBiasOuter, isHighMult, nStored, totalChargeAllRing); - int nBC = digitsBC.size(); + triggers.setTriggers(isMinBias, isMinBiasInner, isMinBiasOuter, isHighMult, isDummy, nStored, totalChargeAllRing); digitsBC.emplace_back(first, nStored, bc, triggers); + digitsTrig.emplace_back(bc, isMinBias, isMinBiasInner, isMinBiasOuter, isHighMult, isDummy); + int nBC = digitsBC.size(); for (const auto& lbl : bc.labels) { labels.addElement(nBC, lbl); } diff --git a/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h b/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h index 842e4c947da0d..460392b544980 100644 --- a/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h +++ b/Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h @@ -38,10 +38,11 @@ o2::framework::DataProcessorSpec getFV0DigitWriterSpec(bool mctruth = true) 1, BranchDefinition<std::vector<o2::fv0::BCData>>{InputSpec{"digitBCinput", "FV0", "DIGITSBC"}, "FV0DigitBC"}, BranchDefinition<std::vector<o2::fv0::ChannelData>>{InputSpec{"digitChinput", "FV0", "DIGITSCH"}, "FV0DigitCh"}, + BranchDefinition<std::vector<o2::fv0::DetTrigInput>>{InputSpec{"digitTrinput", "FV0", "TRIGGERINPUT"}, "TRIGGERINPUT"}, BranchDefinition<o2::dataformats::MCTruthContainer<o2::fv0::MCLabel>>{InputSpec{"labelinput", "FV0", "DIGITLBL"}, "FV0DigitLabels", mctruth ? 1 : 0})(); } } // namespace fv0 } // end namespace o2 -#endif /* STEER_DIGITIZERWORKFLOW_ITSMFTDIGITWRITER_H_ */ +#endif /* STEER_DIGITIZERWORKFLOW_FV0DIGITWRITER_H_ */ diff --git a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx index 5d2c651f5e492..c009774cc7eed 100644 --- a/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx @@ -87,7 +87,7 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer // call actual digitization procedure mDigitizer.setEventId(part.entryID); mDigitizer.setSrcId(part.sourceID); - mDigitizer.process(hits, mDigitsBC, mDigitsCh, mLabels); + mDigitizer.process(hits, mDigitsBC, mDigitsCh, mDigitsTrig, mLabels); } LOG(INFO) << "[FV0] Has " << mDigitsBC.size() << " BC elements, " << mDigitsCh.size() << " mDigitsCh elements"; } @@ -95,7 +95,7 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer o2::InteractionTimeRecord terminateIR; terminateIR.orbit = 0xffffffff; // supply IR in the infinite future to flush all cached BC mDigitizer.setInteractionRecord(terminateIR); - mDigitizer.flush(mDigitsBC, mDigitsCh, mLabels); + mDigitizer.flush(mDigitsBC, mDigitsCh, mDigitsTrig, mLabels); // here we have all digits and we can send them to consumer (aka snapshot it onto output) LOG(INFO) << "FV0: Sending " << mDigitsBC.size() << " digitsBC and " << mDigitsCh.size() << " digitsCh."; @@ -103,6 +103,7 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer // send out to next stage pc.outputs().snapshot(Output{"FV0", "DIGITSBC", 0, Lifetime::Timeframe}, mDigitsBC); pc.outputs().snapshot(Output{"FV0", "DIGITSCH", 0, Lifetime::Timeframe}, mDigitsCh); + pc.outputs().snapshot(Output{"FV0", "TRIGGERINPUT", 0, Lifetime::Timeframe}, mDigitsTrig); if (pc.outputs().isAllowed({"FV0", "DIGITLBL", 0})) { pc.outputs().snapshot(Output{"FV0", "DIGITLBL", 0, Lifetime::Timeframe}, mLabels); } @@ -120,6 +121,7 @@ class FV0DPLDigitizerTask : public o2::base::BaseDPLDigitizer std::vector<TChain*> mSimChains; std::vector<o2::fv0::ChannelData> mDigitsCh; std::vector<o2::fv0::BCData> mDigitsBC; + std::vector<o2::fv0::DetTrigInput> mDigitsTrig; o2::dataformats::MCTruthContainer<o2::fv0::MCLabel> mLabels; // labels which get filled // RS: at the moment using hardcoded flag for continuous readout @@ -137,6 +139,7 @@ o2::framework::DataProcessorSpec getFV0DigitizerSpec(int channel, bool mctruth) std::vector<OutputSpec> outputs; outputs.emplace_back("FV0", "DIGITSBC", 0, Lifetime::Timeframe); outputs.emplace_back("FV0", "DIGITSCH", 0, Lifetime::Timeframe); + outputs.emplace_back("FV0", "TRIGGERINPUT", 0, Lifetime::Timeframe); if (mctruth) { outputs.emplace_back("FV0", "DIGITLBL", 0, Lifetime::Timeframe); } From 145b6f623e7c0134dab1b836b88f3866dcf0c1d9 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 12 Jan 2021 10:23:23 +0100 Subject: [PATCH 1738/1751] Small fixes --- Utilities/Tools/jobutils.sh | 2 +- run/o2sim_parallel.cxx | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index d5d9239accee6..cbdab6c9e0b43 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -146,7 +146,7 @@ taskwrapper() { finalcommand="TIME=\"#walltime %e\" ${O2_ROOT}/share/scripts/monitor-mem.sh ${TIMECOMMAND} './${SCRIPTNAME}'" fi echo "Running: ${finalcommand}" > ${logfile} - eval ${finalcommand} >> ${logfile} 2>&1 & disown + eval ${finalcommand} >> ${logfile} 2>&1 & #can't disown here since we want to retrieve exit status later on # THE NEXT PART IS THE SUPERVISION PART # get the PID diff --git a/run/o2sim_parallel.cxx b/run/o2sim_parallel.cxx index 91b9a02affade..1c2971511af4d 100644 --- a/run/o2sim_parallel.cxx +++ b/run/o2sim_parallel.cxx @@ -100,6 +100,10 @@ int checkresult() // easy check: see if we have number of entries in output tree == number of events asked std::string filename = o2::base::NameConf::getMCKinematicsFileName(conf.getOutPrefix().c_str()); TFile f(filename.c_str(), "OPEN"); + if (f.IsZombie()) { + LOG(WARN) << "Kinematics file corrupted or does not exist"; + return 1; + } auto tr = static_cast<TTree*>(f.Get("o2sim")); if (!tr) { errors++; From a2e47b3f4e4e8b405f0124330e0e53cb0e632bc3 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 12 Jan 2021 10:44:40 +0100 Subject: [PATCH 1739/1751] Revert "Populate event header with information of the current Pythia8 event" This reverts commit a0da596fb70058e9fc997ae0864858c42b08a269. We observed a failure in parallel simulation caused by this commit. Will be re-enabled once underlying bug is fixed. --- Generators/src/GeneratorPythia8.cxx | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 54a4a4e6fd0d8..751002d132c3e 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -196,37 +196,15 @@ void GeneratorPythia8::updateHeader(o2::dataformats::MCEventHeader* eventHeader) { /** update header **/ - eventHeader->putInfo<std::string>("generator", "pythia8"); - eventHeader->putInfo<int>("version", PYTHIA_VERSION_INTEGER); - #if PYTHIA_VERSION_INTEGER < 8300 auto hiinfo = mPythia.info.hiinfo; #else auto hiinfo = mPythia.info.hiInfo; #endif + /** set impact parameter if in heavy-ion mode **/ if (hiinfo) { - /** set impact parameter **/ eventHeader->SetB(hiinfo->b()); - eventHeader->putInfo<double>("Bimpact", hiinfo->b()); - /** set Ncoll, Npart and Nremn **/ - int nColl, nPart; - int nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg; - int nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg; - getNcoll(nColl); - getNpart(nPart); - getNpart(nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg); - getNremn(nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg); - eventHeader->putInfo<int>("Ncoll", nColl); - eventHeader->putInfo<int>("Npart", nPart); - eventHeader->putInfo<int>("Npart_proj_p", nPartProtonProj); - eventHeader->putInfo<int>("Npart_proj_n", nPartNeutronProj); - eventHeader->putInfo<int>("Npart_targ_p", nPartProtonTarg); - eventHeader->putInfo<int>("Npart_targ_n", nPartNeutronTarg); - eventHeader->putInfo<int>("Nremn_proj_p", nRemnProtonProj); - eventHeader->putInfo<int>("Nremn_proj_n", nRemnNeutronProj); - eventHeader->putInfo<int>("Nremn_targ_p", nRemnProtonTarg); - eventHeader->putInfo<int>("Nremn_targ_n", nRemnNeutronTarg); } } From 27a8e79407761be60131b40bb493cdc3a03d8502 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene <Ionut.Cristian.Arsene@cern.ch> Date: Tue, 12 Jan 2021 15:31:50 +0100 Subject: [PATCH 1740/1751] PWGDQ utility classes moved from AnalysisCore to Analysis/Tasks/PWGDQ (#5138) --- Analysis/CMakeLists.txt | 1 + Analysis/Core/CMakeLists.txt | 8 -- Analysis/Core/src/AnalysisCoreLinkDef.h | 4 - Analysis/PWGDQ/CMakeLists.txt | 25 ++++ .../include/PWGDQCore}/AnalysisCompositeCut.h | 6 +- .../include/PWGDQCore}/AnalysisCut.h | 0 .../include/PWGDQCore}/CutsLibrary.h | 6 +- .../include/PWGDQCore}/HistogramManager.h | 0 .../include/PWGDQCore}/HistogramsLibrary.h | 4 +- .../include/PWGDQCore}/VarManager.h | 0 .../src/AnalysisCompositeCut.cxx | 2 +- Analysis/{Core => PWGDQ}/src/AnalysisCut.cxx | 6 +- .../{Core => PWGDQ}/src/HistogramManager.cxx | 2 +- .../PWGDQ => PWGDQ/src}/PWGDQCoreLinkDef.h | 5 + Analysis/{Core => PWGDQ}/src/VarManager.cxx | 2 +- Analysis/Tasks/PWGDQ/CMakeLists.txt | 30 ++-- Analysis/Tasks/PWGDQ/dileptonEE.cxx | 8 +- Analysis/Tasks/PWGDQ/dileptonMuMu.cxx | 8 +- Analysis/Tasks/PWGDQ/filterPP.cxx | 12 +- Analysis/Tasks/PWGDQ/tableMaker.cxx | 8 +- Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx | 8 +- Analysis/Tasks/PWGDQ/tableMaker_pp.cxx | 8 +- Analysis/Tasks/PWGDQ/tableReader.cxx | 8 +- Analysis/Tasks/reducedEventAnalysis.cxx | 135 ------------------ 24 files changed, 89 insertions(+), 207 deletions(-) create mode 100644 Analysis/PWGDQ/CMakeLists.txt rename Analysis/{Core/include/AnalysisCore => PWGDQ/include/PWGDQCore}/AnalysisCompositeCut.h (88%) rename Analysis/{Core/include/AnalysisCore => PWGDQ/include/PWGDQCore}/AnalysisCut.h (100%) rename Analysis/{Tasks/PWGDQ => PWGDQ/include/PWGDQCore}/CutsLibrary.h (97%) rename Analysis/{Core/include/AnalysisCore => PWGDQ/include/PWGDQCore}/HistogramManager.h (100%) rename Analysis/{Tasks/PWGDQ => PWGDQ/include/PWGDQCore}/HistogramsLibrary.h (99%) rename Analysis/{Core/include/AnalysisCore => PWGDQ/include/PWGDQCore}/VarManager.h (100%) rename Analysis/{Core => PWGDQ}/src/AnalysisCompositeCut.cxx (98%) rename Analysis/{Core => PWGDQ}/src/AnalysisCut.cxx (92%) rename Analysis/{Core => PWGDQ}/src/HistogramManager.cxx (99%) rename Analysis/{Tasks/PWGDQ => PWGDQ/src}/PWGDQCoreLinkDef.h (76%) rename Analysis/{Core => PWGDQ}/src/VarManager.cxx (99%) delete mode 100644 Analysis/Tasks/reducedEventAnalysis.cxx diff --git a/Analysis/CMakeLists.txt b/Analysis/CMakeLists.txt index 5f5ec9b76515e..da1c87a32b0b3 100644 --- a/Analysis/CMakeLists.txt +++ b/Analysis/CMakeLists.txt @@ -12,3 +12,4 @@ add_subdirectory(Core) add_subdirectory(DataModel) add_subdirectory(Tasks) add_subdirectory(Tutorials) +add_subdirectory(PWGDQ) diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index f279a753f0b93..f8e732ee91b70 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -11,10 +11,6 @@ o2_add_library(AnalysisCore SOURCES src/CorrelationContainer.cxx src/TrackSelection.cxx - src/VarManager.cxx - src/HistogramManager.cxx - src/AnalysisCut.cxx - src/AnalysisCompositeCut.cxx src/TriggerAliases.cxx src/HFConfigurables.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel) @@ -23,10 +19,6 @@ o2_target_root_dictionary(AnalysisCore HEADERS include/AnalysisCore/CorrelationContainer.h include/AnalysisCore/TrackSelection.h include/AnalysisCore/TrackSelectionDefaults.h - include/AnalysisCore/VarManager.h - include/AnalysisCore/HistogramManager.h - include/AnalysisCore/AnalysisCut.h - include/AnalysisCore/AnalysisCompositeCut.h include/AnalysisCore/TriggerAliases.h include/AnalysisCore/MC.h include/AnalysisCore/HFConfigurables.h diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index c550c9a41d98a..18e2437504797 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -16,8 +16,4 @@ #pragma link C++ class TrackSelection + ; #pragma link C++ class TriggerAliases + ; -#pragma link C++ class VarManager + ; -#pragma link C++ class HistogramManager + ; -#pragma link C++ class AnalysisCut + ; -#pragma link C++ class AnalysisCompositeCut + ; #pragma link C++ class HFTrackIndexSkimsCreatorConfigs + ; diff --git a/Analysis/PWGDQ/CMakeLists.txt b/Analysis/PWGDQ/CMakeLists.txt new file mode 100644 index 0000000000000..06ba6b261cd49 --- /dev/null +++ b/Analysis/PWGDQ/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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_library(PWGDQCore + SOURCES src/VarManager.cxx + src/HistogramManager.cxx + src/AnalysisCut.cxx + src/AnalysisCompositeCut.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore) + +o2_target_root_dictionary(PWGDQCore + HEADERS include/PWGDQCore/AnalysisCut.h + include/PWGDQCore/AnalysisCompositeCut.h + include/PWGDQCore/VarManager.h + include/PWGDQCore/HistogramManager.h + include/PWGDQCore/CutsLibrary.h + include/PWGDQCore/HistogramsLibrary.h + LINKDEF src/PWGDQCoreLinkDef.h) diff --git a/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h b/Analysis/PWGDQ/include/PWGDQCore/AnalysisCompositeCut.h similarity index 88% rename from Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h rename to Analysis/PWGDQ/include/PWGDQCore/AnalysisCompositeCut.h index cfa8a95543ed0..5da1b34dd5811 100644 --- a/Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h +++ b/Analysis/PWGDQ/include/PWGDQCore/AnalysisCompositeCut.h @@ -16,7 +16,7 @@ #ifndef AnalysisCompositeCut_H #define AnalysisCompositeCut_H -#include "AnalysisCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCut.h" #include <vector> //_________________________________________________________________________ @@ -44,8 +44,8 @@ class AnalysisCompositeCut : public AnalysisCut bool IsSelected(float* values) override; protected: - bool fOptionUseAND; // true (default): apply AND on all cuts; false: use OR - std::vector<AnalysisCut> fCutList; // list of cuts + bool fOptionUseAND; // true (default): apply AND on all cuts; false: use OR + std::vector<AnalysisCut> fCutList; // list of cuts std::vector<AnalysisCompositeCut> fCompositeCutList; // list of composite cuts ClassDef(AnalysisCompositeCut, 2); diff --git a/Analysis/Core/include/AnalysisCore/AnalysisCut.h b/Analysis/PWGDQ/include/PWGDQCore/AnalysisCut.h similarity index 100% rename from Analysis/Core/include/AnalysisCore/AnalysisCut.h rename to Analysis/PWGDQ/include/PWGDQCore/AnalysisCut.h diff --git a/Analysis/Tasks/PWGDQ/CutsLibrary.h b/Analysis/PWGDQ/include/PWGDQCore/CutsLibrary.h similarity index 97% rename from Analysis/Tasks/PWGDQ/CutsLibrary.h rename to Analysis/PWGDQ/include/PWGDQCore/CutsLibrary.h index 6775c4aff8e38..4b34844464934 100644 --- a/Analysis/Tasks/PWGDQ/CutsLibrary.h +++ b/Analysis/PWGDQ/include/PWGDQCore/CutsLibrary.h @@ -10,9 +10,9 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" -#include "AnalysisCore/VarManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" +#include "PWGDQCore/VarManager.h" namespace o2::aod { diff --git a/Analysis/Core/include/AnalysisCore/HistogramManager.h b/Analysis/PWGDQ/include/PWGDQCore/HistogramManager.h similarity index 100% rename from Analysis/Core/include/AnalysisCore/HistogramManager.h rename to Analysis/PWGDQ/include/PWGDQCore/HistogramManager.h diff --git a/Analysis/Tasks/PWGDQ/HistogramsLibrary.h b/Analysis/PWGDQ/include/PWGDQCore/HistogramsLibrary.h similarity index 99% rename from Analysis/Tasks/PWGDQ/HistogramsLibrary.h rename to Analysis/PWGDQ/include/PWGDQCore/HistogramsLibrary.h index a888dc05ddccb..361bb3fea9edc 100644 --- a/Analysis/Tasks/PWGDQ/HistogramsLibrary.h +++ b/Analysis/PWGDQ/include/PWGDQCore/HistogramsLibrary.h @@ -10,8 +10,8 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/VarManager.h" namespace o2::aod { diff --git a/Analysis/Core/include/AnalysisCore/VarManager.h b/Analysis/PWGDQ/include/PWGDQCore/VarManager.h similarity index 100% rename from Analysis/Core/include/AnalysisCore/VarManager.h rename to Analysis/PWGDQ/include/PWGDQCore/VarManager.h diff --git a/Analysis/Core/src/AnalysisCompositeCut.cxx b/Analysis/PWGDQ/src/AnalysisCompositeCut.cxx similarity index 98% rename from Analysis/Core/src/AnalysisCompositeCut.cxx rename to Analysis/PWGDQ/src/AnalysisCompositeCut.cxx index af7268aec5d12..160131d9c74f0 100644 --- a/Analysis/Core/src/AnalysisCompositeCut.cxx +++ b/Analysis/PWGDQ/src/AnalysisCompositeCut.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "AnalysisCore/AnalysisCompositeCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" ClassImp(AnalysisCompositeCut) diff --git a/Analysis/Core/src/AnalysisCut.cxx b/Analysis/PWGDQ/src/AnalysisCut.cxx similarity index 92% rename from Analysis/Core/src/AnalysisCut.cxx rename to Analysis/PWGDQ/src/AnalysisCut.cxx index 9a3a4475960c9..e6ba9a44abada 100644 --- a/Analysis/Core/src/AnalysisCut.cxx +++ b/Analysis/PWGDQ/src/AnalysisCut.cxx @@ -8,11 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "AnalysisCore/AnalysisCut.h" - -#include <iostream> -using std::cout; -using std::endl; +#include "PWGDQCore/AnalysisCut.h" ClassImp(AnalysisCut); diff --git a/Analysis/Core/src/HistogramManager.cxx b/Analysis/PWGDQ/src/HistogramManager.cxx similarity index 99% rename from Analysis/Core/src/HistogramManager.cxx rename to Analysis/PWGDQ/src/HistogramManager.cxx index 731d12925761a..eaef3413f6f41 100644 --- a/Analysis/Core/src/HistogramManager.cxx +++ b/Analysis/PWGDQ/src/HistogramManager.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "AnalysisCore/HistogramManager.h" +#include "PWGDQCore/HistogramManager.h" #include <iostream> #include <fstream> diff --git a/Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h b/Analysis/PWGDQ/src/PWGDQCoreLinkDef.h similarity index 76% rename from Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h rename to Analysis/PWGDQ/src/PWGDQCoreLinkDef.h index d2769ae13ba53..170a8b7a38bab 100644 --- a/Analysis/Tasks/PWGDQ/PWGDQCoreLinkDef.h +++ b/Analysis/PWGDQ/src/PWGDQCoreLinkDef.h @@ -11,3 +11,8 @@ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; + +#pragma link C++ class VarManager + ; +#pragma link C++ class HistogramManager + ; +#pragma link C++ class AnalysisCut + ; +#pragma link C++ class AnalysisCompositeCut + ; diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/PWGDQ/src/VarManager.cxx similarity index 99% rename from Analysis/Core/src/VarManager.cxx rename to Analysis/PWGDQ/src/VarManager.cxx index f3706347c8ceb..adfb2face737c 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/PWGDQ/src/VarManager.cxx @@ -8,7 +8,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "AnalysisCore/VarManager.h" +#include "PWGDQCore/VarManager.h" #include <TMath.h> diff --git a/Analysis/Tasks/PWGDQ/CMakeLists.txt b/Analysis/Tasks/PWGDQ/CMakeLists.txt index fa46f30e0675c..e5de4e409c570 100644 --- a/Analysis/Tasks/PWGDQ/CMakeLists.txt +++ b/Analysis/Tasks/PWGDQ/CMakeLists.txt @@ -1,42 +1,44 @@ -o2_add_library(PWGDQCore - SOURCES - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore) - -o2_target_root_dictionary(PWGDQCore - HEADERS CutsLibrary.h HistogramsLibrary.h - LINKDEF PWGDQCoreLinkDef.h) +# 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(table-maker SOURCES tableMaker.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore O2::PWGDQCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(table-reader SOURCES tableReader.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore O2::PWGDQCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(dilepton-ee SOURCES dileptonEE.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore O2::PWGDQCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(dilepton-mumu SOURCES dileptonMuMu.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore O2::PWGDQCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(table-maker-pp SOURCES tableMaker_pp.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore O2::PWGDQCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(dq-filter-pp SOURCES filterPP.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore O2::PWGDQCore COMPONENT_NAME Analysis) o2_add_dpl_workflow(table-maker-muon-pp SOURCES tableMakerMuon_pp.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore O2::PWGDQCore COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx index fc93b1854afa5..d0784a184af11 100644 --- a/Analysis/Tasks/PWGDQ/dileptonEE.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -15,10 +15,10 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "AnalysisDataModel/ReducedInfoTables.h" -#include "AnalysisCore/VarManager.h" -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" +#include "PWGDQCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" #include <TH1F.h> #include <TMath.h> #include <THashList.h> diff --git a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx index e3b9284a53f8f..b63321b201daf 100644 --- a/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx +++ b/Analysis/Tasks/PWGDQ/dileptonMuMu.cxx @@ -15,10 +15,10 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "AnalysisDataModel/ReducedInfoTables.h" -#include "AnalysisCore/VarManager.h" -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" +#include "PWGDQCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" #include <TH1F.h> #include <TMath.h> #include <THashList.h> diff --git a/Analysis/Tasks/PWGDQ/filterPP.cxx b/Analysis/Tasks/PWGDQ/filterPP.cxx index 1fb77b8e9bff6..5b5c3573f8838 100644 --- a/Analysis/Tasks/PWGDQ/filterPP.cxx +++ b/Analysis/Tasks/PWGDQ/filterPP.cxx @@ -19,12 +19,12 @@ #include "AnalysisDataModel/Centrality.h" #include "AnalysisCore/TriggerAliases.h" #include "AnalysisDataModel/ReducedInfoTables.h" -#include "AnalysisCore/VarManager.h" -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" -#include "CutsLibrary.h" -#include "HistogramsLibrary.h" +#include "PWGDQCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" +#include "PWGDQCore/CutsLibrary.h" +#include "PWGDQCore/HistogramsLibrary.h" #include "AnalysisDataModel/PID/PIDResponse.h" #include "AnalysisDataModel/TrackSelectionTables.h" #include <TH1F.h> diff --git a/Analysis/Tasks/PWGDQ/tableMaker.cxx b/Analysis/Tasks/PWGDQ/tableMaker.cxx index 4f9eaf2d8a788..03f6a2a6eaffb 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker.cxx @@ -19,10 +19,10 @@ #include "AnalysisDataModel/Centrality.h" #include "AnalysisCore/TriggerAliases.h" #include "AnalysisDataModel/ReducedInfoTables.h" -#include "AnalysisCore/VarManager.h" -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" +#include "PWGDQCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" #include "AnalysisDataModel/PID/PIDResponse.h" #include "AnalysisDataModel/TrackSelectionTables.h" #include <iostream> diff --git a/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx b/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx index 9877a5a7f8b7f..ea4b779414549 100644 --- a/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx @@ -19,10 +19,10 @@ #include "AnalysisDataModel/Centrality.h" #include "AnalysisCore/TriggerAliases.h" #include "AnalysisDataModel/ReducedInfoTables.h" -#include "AnalysisCore/VarManager.h" -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" +#include "PWGDQCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" #include "AnalysisDataModel/PID/PIDResponse.h" #include "AnalysisDataModel/TrackSelectionTables.h" #include <iostream> diff --git a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx index 68175ccbe15ae..6f4603193b33a 100644 --- a/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx +++ b/Analysis/Tasks/PWGDQ/tableMaker_pp.cxx @@ -19,10 +19,10 @@ #include "AnalysisDataModel/Centrality.h" #include "AnalysisCore/TriggerAliases.h" #include "AnalysisDataModel/ReducedInfoTables.h" -#include "AnalysisCore/VarManager.h" -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" +#include "PWGDQCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" #include "AnalysisDataModel/PID/PIDResponse.h" #include "AnalysisDataModel/TrackSelectionTables.h" #include <iostream> diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index 5dec0d394c818..e1123d058ed2e 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -15,10 +15,10 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "AnalysisDataModel/ReducedInfoTables.h" -#include "AnalysisCore/VarManager.h" -#include "AnalysisCore/HistogramManager.h" -#include "AnalysisCore/AnalysisCut.h" -#include "AnalysisCore/AnalysisCompositeCut.h" +#include "PWGDQCore/VarManager.h" +#include "PWGDQCore/HistogramManager.h" +#include "PWGDQCore/AnalysisCut.h" +#include "PWGDQCore/AnalysisCompositeCut.h" #include <TH1F.h> #include <TMath.h> #include <THashList.h> diff --git a/Analysis/Tasks/reducedEventAnalysis.cxx b/Analysis/Tasks/reducedEventAnalysis.cxx deleted file mode 100644 index dde7efee16842..0000000000000 --- a/Analysis/Tasks/reducedEventAnalysis.cxx +++ /dev/null @@ -1,135 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "AnalysisDataModel/Multiplicity.h" -#include "AnalysisDataModel/EventSelection.h" -#include "AnalysisDataModel/Centrality.h" -#include <TH1F.h> -#include <TH2F.h> -#include <TMath.h> -#include "TVector3.h" -#include "TLorentzVector.h" -#include <cmath> -#include <vector> - -const float gkMass = 0.0005; - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -// This is a very simple example showing how to create an histogram -// FIXME: this should really inherit from AnalysisTask but -// we need GCC 7.4+ for that - -struct InvMassAnalysis { - // needs to be initialized with a label or an obj - // when adding an object to OutputObj later, the object name will be - // *reset* to OutputObj label - needed for correct placement in the output file - OutputObj<TH1F> centV0M{TH1F("centV0M", "centrality V0", 100, 0.0, 100.0)}; - OutputObj<TH1F> vtxZ{TH1F("vtxZ", "vtx Z", 200, -20.0, 20.0)}; - - OutputObj<TH1F> ptH{TH1F("pt", "pt", 100, -0.01, 10.01)}; - OutputObj<TH2F> ptCorr{TH2F("ptToPt", "ptToPt", 100, -0.01, 10.01, 100, -0.01, 10.01)}; - OutputObj<TH2F> tpcDedx{TH2F("tpcDedx", "TPC de/dx", 100, 0.0, 10.0, 100, 0.0, 200.0)}; - OutputObj<TH1I> itsHits{TH1I("itsHits", "ITS hits per layer", 6, -0.5, 5.5)}; - OutputObj<TH2I> itsHitsVsPt{TH2I("itsHitsVsPt", "ITS hits per layer", 6, -0.5, 5.5, 100, 0.0, 10.0)}; - OutputObj<TH1I> itsChi2{TH1I("itsChi2", "ITS chi2", 100, 0.0, 20.0)}; - OutputObj<TH1I> tpcChi2{TH1I("tpcChi2", "TPC chi2", 100, 0.0, 10.0)}; - OutputObj<TH1I> tpcCls{TH1I("tpcCls", "TPC clusters", 160, 0.0, 160.0)}; - OutputObj<TH1I> flagsHist{TH1I("flagsHist", "Flags", 64, -0.5, 63.5)}; - OutputObj<TH1F> invMassPM{TH1F("invMassPM", "Invariant mass, SEPM", 125, 0.0, 5.0)}; - OutputObj<TH1F> invMassPP{TH1F("invMassPP", "Invariant mass, SEPP", 125, 0.0, 5.0)}; - OutputObj<TH1F> invMassMM{TH1F("invMassMM", "Invariant mass, SEMM", 125, 0.0, 5.0)}; - OutputObj<TH2F> invMassVsPt{TH2F("invMassVsPt", "Invariant mass", 125, 0.0, 5.0, 10, 0.0, 10.0)}; - OutputObj<TH2F> invMassVsCentrality{TH2F("invMassVsCentrality", "Invariant mass", 125, 0.0, 5.0, 10, 0.0, 100.0)}; - OutputObj<TH1F> trZ{"trZ", OutputObjHandlingPolicy::QAObject}; - //Configurable<float> ptlow{"ptlow", 1.0f, "Lower pT limit"}; - //Configurable<float> pthigh{"pthigh", 1.0f, "Higher pT limit"}; - - float ptlow = 1.0; - float pthigh = 5.0; - Filter ptFilter = ((1.0f / aod::track::signed1Pt > ptlow) && (1.0f / aod::track::signed1Pt < pthigh)) || ((1.0f / aod::track::signed1Pt > -1.0f * pthigh) && (1.0f / aod::track::signed1Pt < -1.0f * ptlow)); - //Filter spdAnyFilter = (aod::track::itsClusterMap & (uint8_t(1)<<0)) || (aod::track::itsClusterMap & (uint8_t(1)<<1)); - float dedxLow = 75.0; - float dedxHigh = 90.0; - Filter dedxFilter = (aod::track::tpcSignal > dedxLow) && (aod::track::tpcSignal < dedxHigh); - float tpcChi2Max = 4.0; - float itsChi2Max = 36; - Filter qualityFilter = (aod::track::tpcChi2NCl < tpcChi2Max) && (aod::track::itsChi2NCl < itsChi2Max); - - void init(InitContext const&) - { - trZ.setObject(new TH1F("Z", "Z", 100, -10., 10.)); - } - - void process(soa::Join<aod::Collisions, aod::EvSels, aod::Cents>::iterator collision, soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra>> const& tracks) - { - - if (!collision.sel7()) - return; - - centV0M->Fill(collision.centV0M()); - vtxZ->Fill(collision.posZ()); - - for (auto& track : tracks) { - //if (track.pt() < ptlow) - // continue; - ptH->Fill(track.pt()); - trZ->Fill(track.z()); - itsChi2->Fill(track.itsChi2NCl()); - for (int i = 0; i < 6; i++) { - if (track.itsClusterMap() & (uint8_t(1) << i)) - itsHits->Fill(i); - if (track.itsClusterMap() & (uint8_t(1) << i)) - itsHitsVsPt->Fill(i, track.pt()); - } - tpcDedx->Fill(track.tpcInnerParam(), track.tpcSignal()); - tpcChi2->Fill(track.tpcChi2NCl()); - tpcCls->Fill(track.tpcNClsFound()); - for (int i = 0; i < 64; i++) { - if (track.flags() & (uint64_t(1) << i)) - flagsHist->Fill(i); - } - } - for (auto& [t0, t1] : combinations(tracks, tracks)) { - ptCorr->Fill(t0.pt(), t1.pt()); - if (!((t0.itsClusterMap() & (uint8_t(1) << 0)) || (t0.itsClusterMap() & (uint8_t(1) << 1)))) - continue; - if (!((t1.itsClusterMap() & (uint8_t(1) << 0)) || (t1.itsClusterMap() & (uint8_t(1) << 1)))) - continue; - - TLorentzVector p1, p2, p; - p1.SetXYZM(t0.px(), t0.py(), t0.pz(), gkMass); - p2.SetXYZM(t1.px(), t1.py(), t1.pz(), gkMass); - p = p1 + p2; - - if (t0.charge() * t1.charge() < 0) { - invMassPM->Fill(p.M()); - invMassVsPt->Fill(p.M(), p.Pt()); - invMassVsCentrality->Fill(p.M(), collision.centV0M()); - } else { - if (t0.charge() > 0) - invMassPP->Fill(p.M()); - if (t0.charge() < 0) - invMassMM->Fill(p.M()); - } - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const&) -{ - return WorkflowSpec{ - adaptAnalysisTask<InvMassAnalysis>("InvMassAnalysis")}; -} From a02851622d597ecf1ece391296ab5e7fa09c0d0b Mon Sep 17 00:00:00 2001 From: shahoian <ruben.shahoyan@cern.ch> Date: Tue, 12 Jan 2021 12:23:31 +0100 Subject: [PATCH 1741/1751] Avoid 2D params in SVertexer configurable params --- .../include/DetectorsVertexing/SVertexerParams.h | 14 +++++--------- Detectors/Vertexing/src/SVertexer.cxx | 12 ++++++------ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h index 96ac7cfde2f14..32cd94034b994 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h @@ -50,16 +50,12 @@ struct SVertexerParams : public o2::conf::ConfigurableParamHelper<SVertexerParam float minRfromMeanVertex = 0.5; ///< min radial distance of V0 from beam line (mean vertex) float maxDCAXYfromMeanVertex = 0.2; ///< min DCA of V0 from beam line (mean vertex) float minCosPointingAngle = 0.8; + // cuts on different PID params - float pidCuts[NPIDV0][NPIDParams] = { - // - {0.001, 20, 0.6, 0.}, // Photon - {0.003, 20, 0.07, 0.5}, // K0 - {0.001, 20, 0.07, 0.5}, // Lambda - {0.001, 20, 0.07, 0.5}, // AntiLambda - {0.0025, 14, 0.07, 0.5}, // HyperTriton - {0.0025, 14, 0.07, 0.5} // AntiHyperTriton - }; + float pidCutsPhoton[NPIDParams] = {0.001, 20, 0.60, 0.0}; // Photon + float pidCutsK0[NPIDParams] = {0.003, 20, 0.07, 0.5}; // K0 + float pidCutsLambda[NPIDParams] = {0.001, 20, 0.07, 0.5}; // Lambda + float pidCutsHTriton[NPIDParams] = {0.0025, 14, 0.07, 0.5}; // HyperTriton O2ParamDef(SVertexerParams, "svertexer"); }; diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index 1287ad4abab01..d89f8706717e4 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -39,12 +39,12 @@ void SVertexer::init() auto bz = o2::base::Propagator::Instance()->getNominalBz(); mFitter2Prong.setBz(bz); // - mV0Hyps[SVertexerParams::Photon].set(PID::Photon, PID::Electron, PID::Electron, mSVParams->pidCuts[SVertexerParams::Photon], bz); - mV0Hyps[SVertexerParams::K0].set(PID::K0, PID::Pion, PID::Pion, mSVParams->pidCuts[SVertexerParams::K0], bz); - mV0Hyps[SVertexerParams::Lambda].set(PID::Lambda, PID::Proton, PID::Pion, mSVParams->pidCuts[SVertexerParams::Lambda], bz); - mV0Hyps[SVertexerParams::AntiLambda].set(PID::Lambda, PID::Pion, PID::Proton, mSVParams->pidCuts[SVertexerParams::AntiLambda], bz); - mV0Hyps[SVertexerParams::HyperTriton].set(PID::HyperTriton, PID::Helium3, PID::Pion, mSVParams->pidCuts[SVertexerParams::HyperTriton], bz); - mV0Hyps[SVertexerParams::AntiHyperTriton].set(PID::HyperTriton, PID::Pion, PID::Helium3, mSVParams->pidCuts[SVertexerParams::AntiHyperTriton], bz); + mV0Hyps[SVertexerParams::Photon].set(PID::Photon, PID::Electron, PID::Electron, mSVParams->pidCutsPhoton, bz); + mV0Hyps[SVertexerParams::K0].set(PID::K0, PID::Pion, PID::Pion, mSVParams->pidCutsK0, bz); + mV0Hyps[SVertexerParams::Lambda].set(PID::Lambda, PID::Proton, PID::Pion, mSVParams->pidCutsLambda, bz); + mV0Hyps[SVertexerParams::AntiLambda].set(PID::Lambda, PID::Pion, PID::Proton, mSVParams->pidCutsLambda, bz); + mV0Hyps[SVertexerParams::HyperTriton].set(PID::HyperTriton, PID::Helium3, PID::Pion, mSVParams->pidCutsHTriton, bz); + mV0Hyps[SVertexerParams::AntiHyperTriton].set(PID::HyperTriton, PID::Pion, PID::Helium3, mSVParams->pidCutsHTriton, bz); // } From 3ebc445a6a6cb1fb0ec800b0d6d4bcf86547cb13 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 12 Jan 2021 14:42:56 +0100 Subject: [PATCH 1742/1751] Add CPV to full system test --- prodtests/full-system-test/dpl-workflow.sh | 11 +++++++---- prodtests/full_system_test.sh | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index dc30553d51e33..b2863cbff7178 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -81,7 +81,7 @@ if [ $CTFINPUT == 1 ]; then TOF_INPUT=digits WORKFLOW="o2-ctf-reader-workflow --ctf-input o2_ctf_0000000000.root $ARGS_ALL | " elif [ $EXTINPUT == 1 ]; then - WORKFLOW="o2-dpl-raw-proxy $ARGS_ALL --dataspec \"B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA;G:EMC/RAWDATA;H:PHS/RAWDATA\" --channel-config \"name=readout-proxy,type=pull,method=connect,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0\" | " + WORKFLOW="o2-dpl-raw-proxy $ARGS_ALL --dataspec \"B:TPC/RAWDATA;C:ITS/RAWDATA;D:TOF/RAWDATA;D:MFT/RAWDATA;E:FT0/RAWDATA;F:MID/RAWDATA;G:EMC/RAWDATA;H:PHS/RAWDATA;I:CPV/RAWDATA\" --channel-config \"name=readout-proxy,type=pull,method=connect,address=ipc://@stfb-to-dpl,transport=shmem,rateLogging=0\" | " else WORKFLOW="o2-raw-file-reader-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF=$NHBPERTF;\" --delay $TFDELAY --loop $NTIMEFRAMES --max-tf 0 --input-conf rawAll.cfg | " fi @@ -112,13 +112,16 @@ fi # Workflows disabled in async mode if [ $CTFINPUT == 0 ]; then - WORKFLOW+="o2-phos-reco-workflow $ARGS_ALL --input-type raw --output-type cells | " - WORKFLOW+="o2-emcal-reco-workflow $ARGS_ALL --input-type raw --output-type cells --disable-root-output | " + WORKFLOW+="o2-phos-reco-workflow $ARGS_ALL --input-type raw --output-type cells $DISABLE_MC | " + WORKFLOW+="o2-cpv-reco-workflow $ARGS_ALL --input-type raw --output-type digits $DISABLE_MC | " + WORKFLOW+="o2-cpv-reco-workflow $ARGS_ALL --input-type digits --output-type clusters $DISABLE_MC | " + WORKFLOW+="o2-emcal-reco-workflow $ARGS_ALL --input-type raw --output-type cells --disable-root-output $DISABLE_MC | " WORKFLOW+="o2-itsmft-entropy-encoder-workflow $ARGS_ALL --runmft true | " WORKFLOW+="o2-ft0-entropy-encoder-workflow $ARGS_ALL | " WORKFLOW+="o2-mid-entropy-encoder-workflow $ARGS_ALL | " WORKFLOW+="o2-phos-entropy-encoder-workflow $ARGS_ALL | " + WORKFLOW+="o2-cpv-entropy-encoder-workflow $ARGS_ALL | " WORKFLOW+="o2-emcal-entropy-encoder-workflow $ARGS_ALL | " WORKFLOW+="o2-tpc-scdcalib-interpolation-workflow $ARGS_ALL --disable-root-output --disable-root-input | " @@ -128,7 +131,7 @@ if [ $CTFINPUT == 0 ]; then if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 1 ]; then CTF_OUTPUT_TYPE="both"; fi if [ $CREATECTFDICT == 1 ] && [ $SAVECTF == 0 ]; then CTF_OUTPUT_TYPE="dict"; fi if [ $CREATECTFDICT == 0 ] && [ $SAVECTF == 1 ]; then CTF_OUTPUT_TYPE="ctf"; fi - CMD_CTF="o2-ctf-writer-workflow $ARGS_ALL --output-type $CTF_OUTPUT_TYPE --onlyDet ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS" + CMD_CTF="o2-ctf-writer-workflow $ARGS_ALL --output-type $CTF_OUTPUT_TYPE --onlyDet ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV" if [ $CREATECTFDICT == 1 ] && [ $; then CMD_CTF+=" --save-dict-after 1" fi diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 962b59af816da..b3cdd6512b737 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -66,6 +66,7 @@ taskwrapper tofraw.log o2-tof-reco-workflow ${GLOBALDPLOPT} --tof-raw-file-for l taskwrapper midraw.log o2-mid-digits-to-raw-workflow ${GLOBALDPLOPT} --mid-raw-outdir raw/MID --mid-raw-perlink --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' taskwrapper emcraw.log o2-emcal-rawcreator --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/EMC taskwrapper phsraw.log o2-phos-digi2raw --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/PHS +taskwrapper cpvraw.log o2-cpv-digi2raw --file-for link --configKeyValues '"HBFUtils.nHBFPerTF=128;HBFUtils.orbitFirst=0"' -o raw/CPV cat raw/*/*.cfg > rawAll.cfg # We run the workflow in both CPU-only and With-GPU mode From 5c670969bbff4fcfae64b69bc2a8c3d96d6b8b7c Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 12 Jan 2021 14:43:26 +0100 Subject: [PATCH 1743/1751] Reenable MFT reco in full system test (async part) since it is no longer crashing --- prodtests/full-system-test/dpl-workflow.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index b2863cbff7178..551e82ed829e6 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -105,8 +105,8 @@ WORKFLOW+="o2-tof-reco-workflow $ARGS_ALL --configKeyValues \"HBFUtils.nHBFPerTF # Workflows disabled in sync mode if [ $SYNCMODE == 0 ]; then WORKFLOW+="o2-mid-reco-workflow $ARGS_ALL --disable-root-output $DISABLE_MC | " - # WORKFLOW+="o2-mft-reco-workflow $ARGS_ALL --clusters-from-upstream --disable-mc --disable-root-output --configKeyValues \"HBFUtils.nHBFPerTF=128;\" | " # Disabled since currently crashing - WORKFLOW+="o2-primary-vertexing-workflow $ARGS_ALL --disable-mc --disable-root-input --disable-root-output --validate-with-ft0 | " + WORKFLOW+="o2-mft-reco-workflow $ARGS_ALL --clusters-from-upstream $DISABLE_MC --disable-root-output --configKeyValues \"HBFUtils.nHBFPerTF=128;\" | " + WORKFLOW+="o2-primary-vertexing-workflow $ARGS_ALL $DISABLE_MC --disable-root-input --disable-root-output --validate-with-ft0 | " WORKFLOW+="o2-secondary-vertexing-workflow $ARGS_ALL --disable-root-input --disable-root-output | " fi From c5796e2efddfa3d3b9b95e2b270dc7ad82901c81 Mon Sep 17 00:00:00 2001 From: David Rohr <drohr@jwdt.org> Date: Tue, 12 Jan 2021 14:43:42 +0100 Subject: [PATCH 1744/1751] Fix typo in setting ulimits of full system test --- prodtests/full-system-test/setenv.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full-system-test/setenv.sh b/prodtests/full-system-test/setenv.sh index 1e5e4bd5e9aaa..fb8332b52c95c 100755 --- a/prodtests/full-system-test/setenv.sh +++ b/prodtests/full-system-test/setenv.sh @@ -1,7 +1,7 @@ #!/bin/bash # Make sure we can open sufficiently many files / allocate enough memory -ulimit -n 4096 || ulimit -l unlimited || ulimit -m unlimited || ulimit -l unlimited +ulimit -n 4096 && ulimit -l unlimited && ulimit -m unlimited && ulimit -l unlimited if [ $? != 0 ]; then echo Error setting ulimits exit 1 From 69fabaf6aa998eeac9ccb6750431a9458c320fa2 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel <sandro.wenzel@cern.ch> Date: Tue, 12 Jan 2021 14:22:54 +0100 Subject: [PATCH 1745/1751] o2-sim: Better signal propagation; small fix in jobutils --- Utilities/Tools/jobutils.sh | 6 ++++-- run/o2sim_parallel.cxx | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Utilities/Tools/jobutils.sh b/Utilities/Tools/jobutils.sh index cbdab6c9e0b43..84ae6552a26eb 100644 --- a/Utilities/Tools/jobutils.sh +++ b/Utilities/Tools/jobutils.sh @@ -46,10 +46,12 @@ o2_cleanup_shm_files() { } # Function to find out all the (recursive) child processes starting from a parent PID. -# The output includes includes the parent -# output is saved in child_pid_list +# The output includes the parent childprocs() { local parent=$1 + if [ ! "$2" ]; then + child_pid_list="" + fi if [ "$parent" ] ; then child_pid_list="$child_pid_list $parent" for childpid in $(pgrep -P ${parent}); do diff --git a/run/o2sim_parallel.cxx b/run/o2sim_parallel.cxx index 1c2971511af4d..670704e51dc73 100644 --- a/run/o2sim_parallel.cxx +++ b/run/o2sim_parallel.cxx @@ -118,12 +118,18 @@ int checkresult() return errors; } +std::vector<int> gChildProcesses; // global vector of child pids + // signal handler for graceful exit void sighandler(int signal) { if (signal == SIGINT || signal == SIGTERM) { - LOG(INFO) << "signal caught ... clean up and exit"; + LOG(INFO) << "o2-sim driver: Signal caught ... clean up and exit"; cleanup(); + // forward signal to all children + for (auto& pid : gChildProcesses) { + kill(pid, signal); + } exit(0); } } @@ -346,7 +352,7 @@ int main(int argc, char* argv[]) } return r; } else { - childpids.push_back(pid); + gChildProcesses.push_back(pid); close(pipe_serverdriver_fd[1]); std::cout << "Spawning particle server on PID " << pid << "; Redirect output to " << getServerLogName() << "\n"; launchThreadMonitoringEvents(pipe_serverdriver_fd[0], "DISTRIBUTING EVENT : "); @@ -380,7 +386,7 @@ int main(int argc, char* argv[]) "worker", "--mq-config", localconfig.c_str(), "--severity", "info", (char*)nullptr); return 0; } else { - childpids.push_back(pid); + gChildProcesses.push_back(pid); std::cout << "Spawning sim worker " << id << " on PID " << pid << "; Redirect output to " << workerlogss.str() << "\n"; } @@ -409,13 +415,13 @@ int main(int argc, char* argv[]) return 0; } else { std::cout << "Spawning hit merger on PID " << pid << "; Redirect output to " << getMergerLogName() << "\n"; - childpids.push_back(pid); + gChildProcesses.push_back(pid); close(pipe_mergerdriver_fd[1]); launchThreadMonitoringEvents(pipe_mergerdriver_fd[0], "EVENT FINISHED : "); } // wait on merger (which when exiting completes the workflow) - auto mergerpid = childpids.back(); + auto mergerpid = gChildProcesses.back(); int status, cpid; // wait just blocks and waits until any child returns; but we make sure to wait until merger is here @@ -426,8 +432,8 @@ int main(int argc, char* argv[]) } // we bring down all processes if one of them aborts if (WTERMSIG(status) == SIGABRT) { - for (auto p : childpids) { - kill(p, SIGABRT); + for (auto p : gChildProcesses) { + kill(p, SIGTERM); } cleanup(); LOG(FATAL) << "ABORTING DUE TO ABORT IN COMPONENT"; @@ -438,7 +444,7 @@ int main(int argc, char* argv[]) LOG(INFO) << "Simulation process took " << timer.RealTime() << " s"; // make sure the rest shuts down - for (auto p : childpids) { + for (auto p : gChildProcesses) { if (p != mergerpid) { LOG(DEBUG) << "SHUTTING DOWN CHILD PROCESS " << p; kill(p, SIGTERM); From b56fc6bf2b1b2f34806ff415ad3eca8a7eae713c Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 12 Jan 2021 20:08:57 +0100 Subject: [PATCH 1746/1751] add alien SE (#5160) --- .../AnalysisSupport/src/AODJAlienReaderHelpers.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx index bb97107189eac..327358e2424ec 100644 --- a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx +++ b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx @@ -299,13 +299,19 @@ AlgorithmSpec AODJAlienReaderHelpers::rootFileReaderCallback() std::string nextFileRead = info.file->GetPath(); if (currentFileRead != nextFileRead) { currentFileRead = nextFileRead; + std::string monitoringInfo(currentFileRead); + monitoringInfo += ","; + monitoringInfo += std::to_string(info.file->GetSize()); #if __has_include(<TJAlienFile.h>) auto alienFile = dynamic_cast<TJAlienFile*>(info.file); if (alienFile) { - /// FIXME: get the JAlien stats + monitoringInfo += ","; + monitoringInfo += alienFile->GetSE(); } #endif - monitoring.send(Metric{currentFileRead, "aod-file-read-path"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + monitoring.send(Metric{monitoringInfo, "aod-file-read-info"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); + LOGP(INFO, "File read info: {}", monitoringInfo); + // TODO extend to publish at the end of the file (or on each TF?) the sizes read *per file* } } monitoring.send(Metric{(double)ps.GetReadCalls(), "aod-tree-read-calls"}.addTag(Key::Subsystem, monitoring::tags::Value::DPL)); From 03f01e210268736b39c9060e3750f4cc4c66c8e0 Mon Sep 17 00:00:00 2001 From: swenzel <sandro.wenzel@cern.ch> Date: Tue, 12 Jan 2021 17:57:04 +0100 Subject: [PATCH 1747/1751] O2HitMerger: Use non-owning MCEventHeader Avoiding a problem observed when moving MCEventheaders that include some info fields. This also avoids un unnessary copy. Minor addition to MCEventHeader API: add function to print the Info field. --- .../include/SimulationDataFormat/MCEventHeader.h | 6 ++++++ run/O2HitMerger.h | 12 ++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h b/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h index 3af79fb360737..2a0338828ac17 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h @@ -74,6 +74,12 @@ class MCEventHeader : public FairMCEventHeader return ref; }; + /// prints a summary of info keys/types attached to this header + void printInfo() const + { + mEventInfo.print(); + } + /** methods **/ virtual void Reset(); diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index adc652bf03dc2..2b90119ea2715 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -551,7 +551,7 @@ class O2HitMerger : public FairMQDevice std::vector<int> nprimaries; // collecting primary particles in each subevent std::vector<int> nsubevents; // collecting of subevent numbers - std::unique_ptr<o2::dataformats::MCEventHeader> eventheader; // The event header + o2::dataformats::MCEventHeader* eventheader = nullptr; // The event header // the MC labels (trackID) for hits o2::data::SubEventInfo* info = nullptr; @@ -562,9 +562,9 @@ class O2HitMerger : public FairMQDevice trackoffsets.emplace_back(info->npersistenttracks); nprimaries.emplace_back(info->nprimarytracks); nsubevents.emplace_back(info->part); + info->mMCEventHeader.printInfo(); if (eventheader == nullptr) { - eventheader = std::unique_ptr<dataformats::MCEventHeader>( - new dataformats::MCEventHeader(info->mMCEventHeader)); + eventheader = &info->mMCEventHeader; } else { eventheader->getMCEventStats().add(info->mMCEventHeader.getMCEventStats()); } @@ -580,9 +580,9 @@ class O2HitMerger : public FairMQDevice } // put the event headers into the new TTree - o2::dataformats::MCEventHeader* headerptr = eventheader.get(); - auto headerbr = o2::base::getOrMakeBranch(*mOutTree, "MCEventHeader.", &headerptr); - headerbr->SetAddress(&headerptr); + eventheader->printInfo(); + auto headerbr = o2::base::getOrMakeBranch(*mOutTree, "MCEventHeader.", &eventheader); + headerbr->SetAddress(&eventheader); headerbr->Fill(); headerbr->ResetAddress(); From 35ca9e49f7d352288fcba48366e1f43bb7a8f511 Mon Sep 17 00:00:00 2001 From: swenzel <sandro.wenzel@cern.ch> Date: Tue, 12 Jan 2021 16:53:12 +0100 Subject: [PATCH 1748/1751] Revert "Revert "Populate event header with information of the current Pythia8 event"" This reverts commit a2e47b3f4e4e8b405f0124330e0e53cb0e632bc3. --- Generators/src/GeneratorPythia8.cxx | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Generators/src/GeneratorPythia8.cxx b/Generators/src/GeneratorPythia8.cxx index 751002d132c3e..54a4a4e6fd0d8 100644 --- a/Generators/src/GeneratorPythia8.cxx +++ b/Generators/src/GeneratorPythia8.cxx @@ -196,15 +196,37 @@ void GeneratorPythia8::updateHeader(o2::dataformats::MCEventHeader* eventHeader) { /** update header **/ + eventHeader->putInfo<std::string>("generator", "pythia8"); + eventHeader->putInfo<int>("version", PYTHIA_VERSION_INTEGER); + #if PYTHIA_VERSION_INTEGER < 8300 auto hiinfo = mPythia.info.hiinfo; #else auto hiinfo = mPythia.info.hiInfo; #endif - /** set impact parameter if in heavy-ion mode **/ if (hiinfo) { + /** set impact parameter **/ eventHeader->SetB(hiinfo->b()); + eventHeader->putInfo<double>("Bimpact", hiinfo->b()); + /** set Ncoll, Npart and Nremn **/ + int nColl, nPart; + int nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg; + int nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg; + getNcoll(nColl); + getNpart(nPart); + getNpart(nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg); + getNremn(nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg); + eventHeader->putInfo<int>("Ncoll", nColl); + eventHeader->putInfo<int>("Npart", nPart); + eventHeader->putInfo<int>("Npart_proj_p", nPartProtonProj); + eventHeader->putInfo<int>("Npart_proj_n", nPartNeutronProj); + eventHeader->putInfo<int>("Npart_targ_p", nPartProtonTarg); + eventHeader->putInfo<int>("Npart_targ_n", nPartNeutronTarg); + eventHeader->putInfo<int>("Nremn_proj_p", nRemnProtonProj); + eventHeader->putInfo<int>("Nremn_proj_n", nRemnNeutronProj); + eventHeader->putInfo<int>("Nremn_targ_p", nRemnProtonTarg); + eventHeader->putInfo<int>("Nremn_targ_n", nRemnNeutronTarg); } } From 20e0039d695f89b3514c9b72aa7672ae3b0a5f21 Mon Sep 17 00:00:00 2001 From: nzardosh <nima.zardoshti@cern.ch> Date: Thu, 14 Jan 2021 19:29:15 +0100 Subject: [PATCH 1749/1751] start of Derived data for spectraTPC --- Analysis/Tasks/CMakeLists.txt | 1 + .../Tasks/SkimmingTutorials/CMakeLists.txt | 25 ++++ .../SkimmingTutorials/DataModel/LFDerived.h | 37 ++++++ Analysis/Tasks/SkimmingTutorials/LFDerived.h | 38 ++++++ .../SkimmingTutorials/spectraTPCAnalyser.cxx | 110 +++++++++++++++++ .../SkimmingTutorials/spectraTPCProvider.cxx | 61 ++++++++++ .../SkimmingTutorials/spectraTPCReference.cxx | 112 ++++++++++++++++++ Common/MathUtils/include/MathUtils/Utils.h | 2 + .../include/MathUtils/detail/TypeTruncation.h | 47 ++++++++ 9 files changed, 433 insertions(+) create mode 100644 Analysis/Tasks/SkimmingTutorials/CMakeLists.txt create mode 100644 Analysis/Tasks/SkimmingTutorials/DataModel/LFDerived.h create mode 100644 Analysis/Tasks/SkimmingTutorials/LFDerived.h create mode 100644 Analysis/Tasks/SkimmingTutorials/spectraTPCAnalyser.cxx create mode 100644 Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx create mode 100644 Analysis/Tasks/SkimmingTutorials/spectraTPCReference.cxx create mode 100644 Common/MathUtils/include/MathUtils/detail/TypeTruncation.h diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 3381c8457c3ef..eb42e55c516ff 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory(PWGJE) add_subdirectory(PWGLF) add_subdirectory(PWGUD) add_subdirectory(ALICE3) +add_subdirectory(SkimmingTutorials) o2_add_dpl_workflow(trackextension diff --git a/Analysis/Tasks/SkimmingTutorials/CMakeLists.txt b/Analysis/Tasks/SkimmingTutorials/CMakeLists.txt new file mode 100644 index 0000000000000..fc409b4efb12c --- /dev/null +++ b/Analysis/Tasks/SkimmingTutorials/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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(tpcspectra-task-skim-reference + SOURCES spectraTPCReference.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(tpcspectra-task-skim-provider + SOURCES spectraTPCProvider.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(tpcspectra-task-skim-analyser + SOURCES spectraTPCAnalyser.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/SkimmingTutorials/DataModel/LFDerived.h b/Analysis/Tasks/SkimmingTutorials/DataModel/LFDerived.h new file mode 100644 index 0000000000000..27c19e854a3e0 --- /dev/null +++ b/Analysis/Tasks/SkimmingTutorials/DataModel/LFDerived.h @@ -0,0 +1,37 @@ +// 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_LFDERIVED_H +#define O2_ANALYSIS_LFDERIVED_H + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +//DECLARE_SOA_TABLE(LFCollisions, "AOD", "LFCOLLISION", o2::soa::Index<>, +// o2::aod::bc::RunNumber, o2::aod::collision::PosZ); +//using LFCollision = LFCollisions::iterator; + +namespace lftrack +{ +//DECLARE_SOA_INDEX_COLUMN(LFCollision, lfCollision); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(P, p, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(TPCNSigma, tpcNSigma, float[9]); +} // namespace lftrack +DECLARE_SOA_TABLE(LFTracks, "AOD", "LFTRACK", o2::soa::Index<>, + //lftrack::LFCollisionId, + lftrack::Pt, lftrack::P, lftrack::Eta, + lftrack::TPCNSigma); +using LFTrack = LFTracks::iterator; +} // namespace o2::aod + +#endif // O2_ANALYSIS_LFDERIVED_H diff --git a/Analysis/Tasks/SkimmingTutorials/LFDerived.h b/Analysis/Tasks/SkimmingTutorials/LFDerived.h new file mode 100644 index 0000000000000..b122888acd74b --- /dev/null +++ b/Analysis/Tasks/SkimmingTutorials/LFDerived.h @@ -0,0 +1,38 @@ +// 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 Nima Zardoshti <nima.zardoshti@cern.ch>, CERN +#ifndef O2_ANALYSIS_LFDERIVED_H +#define O2_ANALYSIS_LFDERIVED_H + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +//DECLARE_SOA_TABLE(LFCollisions, "AOD", "LFCOLLISION", o2::soa::Index<>, +// o2::aod::bc::RunNumber, o2::aod::collision::PosZ); +//using LFCollision = LFCollisions::iterator; + +namespace lftrack +{ +//DECLARE_SOA_INDEX_COLUMN(LFCollision, lfCollision); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(P, p, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(TPCNSigma, tpcNSigma, float[9]); +} // namespace lftrack +DECLARE_SOA_TABLE(LFTracks, "AOD", "LFTRACK", o2::soa::Index<>, + //lftrack::LFCollisionId, + lftrack::Pt, lftrack::P, lftrack::Eta, + lftrack::TPCNSigma); +using LFTrack = LFTracks::iterator; +} // namespace o2::aod + +#endif // O2_ANALYSIS_LFDERIVED_H diff --git a/Analysis/Tasks/SkimmingTutorials/spectraTPCAnalyser.cxx b/Analysis/Tasks/SkimmingTutorials/spectraTPCAnalyser.cxx new file mode 100644 index 0000000000000..58ea028b15150 --- /dev/null +++ b/Analysis/Tasks/SkimmingTutorials/spectraTPCAnalyser.cxx @@ -0,0 +1,110 @@ +// 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 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "DataModel/LFDerived.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"add-tof-histos", VariantType::Int, 0, {"Generate TPC with TOF histograms"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +// FIXME: we should put this function in some common header so it has to be defined only once +template <typename T> +void makelogaxis(T h) +{ + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); + } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); +} + +constexpr int Np = 9; +struct TPCSpectraAnalyserTask { + + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr std::string_view hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr std::string_view hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + for (int i = 0; i < Np; i++) { + histos.add(hp[i].data(), Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i].data(), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + } + } + + Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; + Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + + template <std::size_t i, typename T> + void fillParticleHistos(const T& track, const float nsigma[]) + { + if (abs(nsigma[i]) > nsigmacut.value) { + return; + } + histos.fill(HIST(hp[i]), track.p()); + histos.fill(HIST(hpt[i]), track.pt()); + } + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; //collision filters not doing anything now? + Filter trackFilter = nabs(aod::lftrack::eta) < cfgCutEta; + + void process(soa::Filtered<aod::LFTracks>::iterator const& track) + { + auto nsigma = track.tpcNSigma(); + histos.fill(HIST("p/Unselected"), track.p()); + histos.fill(HIST("pt/Unselected"), track.pt()); + + fillParticleHistos<0>(track, nsigma); + fillParticleHistos<1>(track, nsigma); + fillParticleHistos<2>(track, nsigma); + fillParticleHistos<3>(track, nsigma); + fillParticleHistos<4>(track, nsigma); + fillParticleHistos<5>(track, nsigma); + fillParticleHistos<6>(track, nsigma); + fillParticleHistos<7>(track, nsigma); + fillParticleHistos<8>(track, nsigma); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask<TPCSpectraAnalyserTask>("tpcspectra-task-skim-analyser")}; + return workflow; +} diff --git a/Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx b/Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx new file mode 100644 index 0000000000000..52da096723fdc --- /dev/null +++ b/Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx @@ -0,0 +1,61 @@ +// Copyright CERN and copyright holders of ALICE Ohttps://en.wikipedia.org/wiki/Single-precision_floating-point_format2. 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 Nima Zardoshti <nima.zardoshti@cern.ch>, CERN + +// O2 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" +#include "MathUtils/Utils.h" +#include "DataModel/LFDerived.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::math_utils::detail; + +#include "Framework/runDataProcessing.h" + +struct TPCSpectraProviderTask { + + //Produces<aod::LFCollisions> outputCollisions; //currently it seems in the spectraTPC task no loop over the collision is made. Leave this here in case it will be added + Produces<aod::LFTracks> outputTracks; + + //Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable<float> trackEtaCut{"trackEtaCut", 0.9f, "Eta range for tracks"}; + + //Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < trackEtaCut) && (aod::track::isGlobalTrack == (uint8_t) true); + + Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; //can we add an upper limit? + + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>>; + void process(TrackCandidates::iterator const& track) + { + uint32_t pNsigma = 0xFFFFFF00; //15 bit precision for Nsigma + float nsigma[9] = {truncateFloatFraction(track.tpcNSigmaEl(), pNsigma), truncateFloatFraction(track.tpcNSigmaMu(), pNsigma), + truncateFloatFraction(track.tpcNSigmaPi(), pNsigma), truncateFloatFraction(track.tpcNSigmaKa(), pNsigma), + truncateFloatFraction(track.tpcNSigmaPr(), pNsigma), truncateFloatFraction(track.tpcNSigmaDe(), pNsigma), + truncateFloatFraction(track.tpcNSigmaTr(), pNsigma), truncateFloatFraction(track.tpcNSigmaHe(), pNsigma), + truncateFloatFraction(track.tpcNSigmaAl(), pNsigma)}; //the significance needs to be discussed + + //outputTracks(outputCollisions.lastIndex(), track.pt(), track.p(), track.eta(), nsigma); + outputTracks(track.pt(), track.p(), track.eta(), nsigma); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + WorkflowSpec workflow{adaptAnalysisTask<TPCSpectraProviderTask>("tpcspectra-task-skim-provider")}; + return workflow; +} diff --git a/Analysis/Tasks/SkimmingTutorials/spectraTPCReference.cxx b/Analysis/Tasks/SkimmingTutorials/spectraTPCReference.cxx new file mode 100644 index 0000000000000..f9d6305756734 --- /dev/null +++ b/Analysis/Tasks/SkimmingTutorials/spectraTPCReference.cxx @@ -0,0 +1,112 @@ +// 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 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions) +{ + std::vector<ConfigParamSpec> options{ + {"add-tof-histos", VariantType::Int, 0, {"Generate TPC with TOF histograms"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +// FIXME: we should put this function in some common header so it has to be defined only once +template <typename T> +void makelogaxis(T h) +{ + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); + } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); +} + +constexpr int Np = 9; +struct TPCSpectraReferenceTask { + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr std::string_view hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr std::string_view hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + for (int i = 0; i < Np; i++) { + histos.add(hp[i].data(), Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i].data(), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + } + } + + //Defining filters and input + Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true); + + Configurable<float> nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; + + template <std::size_t i, typename T> + void fillParticleHistos(const T& track, const float nsigma[]) + { + if (abs(nsigma[i]) > nsigmacut.value) { + return; + } + histos.fill(HIST(hp[i]), track.p()); + histos.fill(HIST(hpt[i]), track.pt()); + } + + using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidRespTPC, aod::TrackSelection>>; + void process(TrackCandidates::iterator const& track) + { + const float nsigma[Np] = {track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), + track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tpcNSigmaDe(), + track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl()}; + histos.fill(HIST("p/Unselected"), track.p()); + histos.fill(HIST("pt/Unselected"), track.pt()); + + fillParticleHistos<0>(track, nsigma); + fillParticleHistos<1>(track, nsigma); + fillParticleHistos<2>(track, nsigma); + fillParticleHistos<3>(track, nsigma); + fillParticleHistos<4>(track, nsigma); + fillParticleHistos<5>(track, nsigma); + fillParticleHistos<6>(track, nsigma); + fillParticleHistos<7>(track, nsigma); + fillParticleHistos<8>(track, nsigma); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask<TPCSpectraReferenceTask>("tpcspectra-task-skim-reference")}; + return workflow; +} diff --git a/Common/MathUtils/include/MathUtils/Utils.h b/Common/MathUtils/include/MathUtils/Utils.h index e621226a6614f..d23933cc5ba0f 100644 --- a/Common/MathUtils/include/MathUtils/Utils.h +++ b/Common/MathUtils/include/MathUtils/Utils.h @@ -18,6 +18,7 @@ #include "MathUtils/detail/bitOps.h" #include "MathUtils/detail/StatAccumulator.h" #include "MathUtils/detail/trigonometric.h" +#include "MathUtils/detail/TypeTruncation.h" namespace o2 { @@ -221,6 +222,7 @@ using detail::StatAccumulator; using detail::bit2Mask; using detail::numberOfBitsSet; +using detail::truncateFloatFraction; } // namespace math_utils } // namespace o2 diff --git a/Common/MathUtils/include/MathUtils/detail/TypeTruncation.h b/Common/MathUtils/include/MathUtils/detail/TypeTruncation.h new file mode 100644 index 0000000000000..96cfb94bde876 --- /dev/null +++ b/Common/MathUtils/include/MathUtils/detail/TypeTruncation.h @@ -0,0 +1,47 @@ +// 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 TypeTruncation.h +/// \brief +/// \author Nima Zardoshti <nima.zardoshti@cern.ch>, CERN (copied from AliPhysics implementation by Peter Hristov) + +#ifndef MATHUTILS_INCLUDE_MATHUTILS_DETAIL_TYPETRUNCATION_H_ +#define MATHUTILS_INCLUDE_MATHUTILS_DETAIL_TYPETRUNCATION_H_ + +#ifndef GPUCA_GPUCODE_DEVICE +#include <cstdint> +#endif + +namespace o2 +{ +namespace math_utils +{ +namespace detail +{ + +static float truncateFloatFraction(float x, uint32_t mask = 0xFFFFFF00) +{ + // Mask the less significant bits in the float fraction (1 bit sign, 8 bits exponent, 23 bits fraction), see + // https://en.wikipedia.org/wiki/Single-precision_floating-point_format + // mask 0xFFFFFF00 means 23 - 8 = 15 bits in the fraction + union { + float y; + uint32_t iy; + } myu; + myu.y = x; + myu.iy &= mask; + return myu.y; +} + +} // namespace detail +} // namespace math_utils +} // namespace o2 + +#endif /* MATHUTILS_INCLUDE_MATHUTILS_DETAIL_TYPETRUNCATION_H_ */ From 8de50bb5cd336005f5461d41ee029284c2ef6245 Mon Sep 17 00:00:00 2001 From: jgrosseo <jgrosseo@cern.ch> Date: Tue, 19 Jan 2021 20:08:07 +0100 Subject: [PATCH 1750/1751] Update spectraTPCProvider.cxx --- Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx b/Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx index 52da096723fdc..4c4b8ca7914de 100644 --- a/Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx +++ b/Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx @@ -1,4 +1,4 @@ -// Copyright CERN and copyright holders of ALICE Ohttps://en.wikipedia.org/wiki/Single-precision_floating-point_format2. This software is +// 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". // From 5d3fc84a17539b043134dd83f5cf437c9cbc60d9 Mon Sep 17 00:00:00 2001 From: GitHub Action Bot <github-action-bot@example.com> Date: Tue, 19 Jan 2021 19:08:48 +0000 Subject: [PATCH 1751/1751] Updated README --- CHANGELOG.md | 176 +- doc/data/2021-01-o2_prs.json | 3462 ++++++++++++----------------- doc/data/2021-01-o2_releases.json | 6 + 3 files changed, 1554 insertions(+), 2090 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 699ba2a1893d3..2e2670cb1e803 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,92 +1,110 @@ -# Changes since 2020-12-11 +# Changes since 2021-01-05 -## Changes in Algorithm - -- [#5071](https://github.com/AliceO2Group/AliceO2/pull/5071) 2020-12-16: DPL: initial support for plugin based algorithms by [@ktf](https://github.com/ktf) ## Changes in Analysis -- [#5042](https://github.com/AliceO2Group/AliceO2/pull/5042) 2020-12-11: Change to new TPCrefit check: finders by [@ddobrigk](https://github.com/ddobrigk) -- [#5039](https://github.com/AliceO2Group/AliceO2/pull/5039) 2020-12-11: Fixed bug for nested AnalysisCompositeCuts; removed duplicated histogram classes from TableReader by [@iarsene](https://github.com/iarsene) -- [#5063](https://github.com/AliceO2Group/AliceO2/pull/5063) 2020-12-14: DPL Analysis: add string array Configurable by [@aalkin](https://github.com/aalkin) -- [#5050](https://github.com/AliceO2Group/AliceO2/pull/5050) 2020-12-14: DPL Analysis: use compile-time hashed histogram names in registry by [@mario-krueger](https://github.com/mario-krueger) -- [#5060](https://github.com/AliceO2Group/AliceO2/pull/5060) 2020-12-14: Fix finder -> problems with partitioning to be checked by [@ddobrigk](https://github.com/ddobrigk) -- [#5064](https://github.com/AliceO2Group/AliceO2/pull/5064) 2020-12-14: Using histogram registry fill by [@jgrosseo](https://github.com/jgrosseo) -- [#5066](https://github.com/AliceO2Group/AliceO2/pull/5066) 2020-12-15: Analysis: extend histogram registry example by [@mario-krueger](https://github.com/mario-krueger) -- [#5073](https://github.com/AliceO2Group/AliceO2/pull/5073) 2020-12-16: DPL: allow decoupling from JAlien and retrieve JAlienFile, if available by [@ktf](https://github.com/ktf) -- [#5071](https://github.com/AliceO2Group/AliceO2/pull/5071) 2020-12-16: DPL: initial support for plugin based algorithms by [@ktf](https://github.com/ktf) -- [#5081](https://github.com/AliceO2Group/AliceO2/pull/5081) 2020-12-18: DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support by [@ktf](https://github.com/ktf) -- [#5084](https://github.com/AliceO2Group/AliceO2/pull/5084) 2020-12-19: Add X at minimum to v0data table by [@ddobrigk](https://github.com/ddobrigk) -- [#5074](https://github.com/AliceO2Group/AliceO2/pull/5074) 2021-01-05: Initial version of EMCAL Correction Task by [@raymondEhlers](https://github.com/raymondEhlers) -- [#5026](https://github.com/AliceO2Group/AliceO2/pull/5026) 2021-01-05: Convert collision time to ps in TOF PID response by [@njacazio](https://github.com/njacazio) +- [#5138](https://github.com/AliceO2Group/AliceO2/pull/5138) 2021-01-12: PWGDQ utility classes moved from AnalysisCore to Analysis/Tasks/PWGDQ by [@iarsene](https://github.com/iarsene) +- [#5160](https://github.com/AliceO2Group/AliceO2/pull/5160) 2021-01-12: add alien SE by [@jgrosseo](https://github.com/jgrosseo) +- [#5155](https://github.com/AliceO2Group/AliceO2/pull/5155) 2021-01-13: Add multiplicity distribution task by [@jgrosseo](https://github.com/jgrosseo) +- [#5177](https://github.com/AliceO2Group/AliceO2/pull/5177) 2021-01-13: AliEn metrics by [@jgrosseo](https://github.com/jgrosseo) +- [#5158](https://github.com/AliceO2Group/AliceO2/pull/5158) 2021-01-13: use filters by [@jgrosseo](https://github.com/jgrosseo) +- [#5174](https://github.com/AliceO2Group/AliceO2/pull/5174) 2021-01-14: Add histrogram register and track selection by [@lbariogl](https://github.com/lbariogl) +- [#5183](https://github.com/AliceO2Group/AliceO2/pull/5183) 2021-01-14: Adding opening and run time metrics by [@jgrosseo](https://github.com/jgrosseo) +- [#5195](https://github.com/AliceO2Group/AliceO2/pull/5195) 2021-01-15: fix for 2 readers and 1 input file by [@jgrosseo](https://github.com/jgrosseo) +- [#5200](https://github.com/AliceO2Group/AliceO2/pull/5200) 2021-01-16: PWGHF changing default preselection values for hyperloop by [@nzardosh](https://github.com/nzardosh) +- [#5150](https://github.com/AliceO2Group/AliceO2/pull/5150) 2021-01-16: PWGHF: fix of the histogram registry in the Lc task by [@DelloStritto](https://github.com/DelloStritto) +- [#5205](https://github.com/AliceO2Group/AliceO2/pull/5205) 2021-01-18: Change task names, move initializers by [@ddobrigk](https://github.com/ddobrigk) +- [#5204](https://github.com/AliceO2Group/AliceO2/pull/5204) 2021-01-18: PWGHF: Use pre-selections for Dplus by [@fcatalan92](https://github.com/fcatalan92) +- [#5210](https://github.com/AliceO2Group/AliceO2/pull/5210) 2021-01-18: small bug (re)fix, tpc momentum for dedx instead pvtx by [@akalweit](https://github.com/akalweit) +- [#5182](https://github.com/AliceO2Group/AliceO2/pull/5182) 2021-01-19: Add split tables per particle species in PID response by [@njacazio](https://github.com/njacazio) +- [#5223](https://github.com/AliceO2Group/AliceO2/pull/5223) 2021-01-19: PWGHF : syncing decays in the preselection with enums used for MC by [@nzardosh](https://github.com/nzardosh) +- [#5206](https://github.com/AliceO2Group/AliceO2/pull/5206) 2021-01-19: TableMaker task updated to use configurables for system type, event and track selections by [@iarsene](https://github.com/iarsene) ## Changes in Common -- [#5045](https://github.com/AliceO2Group/AliceO2/pull/5045) 2020-12-11: [ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK by [@mconcas](https://github.com/mconcas) -- [#5043](https://github.com/AliceO2Group/AliceO2/pull/5043) 2020-12-12: Make TrackPar(Cov) compatible to GPU by [@davidrohr](https://github.com/davidrohr) -- [#5067](https://github.com/AliceO2Group/AliceO2/pull/5067) 2020-12-15: Increase the margin of CTF block size to 10KB by [@shahor02](https://github.com/shahor02) -- [#5100](https://github.com/AliceO2Group/AliceO2/pull/5100) 2020-12-28: GPU: Make more headers compatible to GPU by [@davidrohr](https://github.com/davidrohr) -- [#5116](https://github.com/AliceO2Group/AliceO2/pull/5116) 2021-01-05: Global (currently TPC only) refit on GPU using either GPU or TrackParCov track model by [@davidrohr](https://github.com/davidrohr) +- [#5134](https://github.com/AliceO2Group/AliceO2/pull/5134) 2021-01-08: RootSerializableKeyValueStore: Add print function by [@sawenzel](https://github.com/sawenzel) +- [#5133](https://github.com/AliceO2Group/AliceO2/pull/5133) 2021-01-11: Populate MC event header with information from current Pythia8 event by [@preghenella](https://github.com/preghenella) +- [#5178](https://github.com/AliceO2Group/AliceO2/pull/5178) 2021-01-13: Fixes in entropy compression memory management by [@shahor02](https://github.com/shahor02) +- [#5184](https://github.com/AliceO2Group/AliceO2/pull/5184) 2021-01-14: Update CommonUtilsLinkDef.h by [@sawenzel](https://github.com/sawenzel) +- [#5199](https://github.com/AliceO2Group/AliceO2/pull/5199) 2021-01-15: (O2-1203) [CTF] use merging/splitting iterators during CTF ecoding/decoding for TPC by [@MichaelLettrich](https://github.com/MichaelLettrich) +- [#5203](https://github.com/AliceO2Group/AliceO2/pull/5203) 2021-01-17: DPL: move driver communication to a separate Service by [@ktf](https://github.com/ktf) +- [#5228](https://github.com/AliceO2Group/AliceO2/pull/5228) 2021-01-19: o2-sim: Make configfile prefixed with correct name by [@sawenzel](https://github.com/sawenzel) ## Changes in DataFormats -- [#5049](https://github.com/AliceO2Group/AliceO2/pull/5049) 2020-12-11: Add DAQ SystemID Unloaded [O2-1918] by [@shahor02](https://github.com/shahor02) -- [#5041](https://github.com/AliceO2Group/AliceO2/pull/5041) 2020-12-11: Use value_t instead of double by [@davidrohr](https://github.com/davidrohr) -- [#5045](https://github.com/AliceO2Group/AliceO2/pull/5045) 2020-12-11: [ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK by [@mconcas](https://github.com/mconcas) -- [#5043](https://github.com/AliceO2Group/AliceO2/pull/5043) 2020-12-12: Make TrackPar(Cov) compatible to GPU by [@davidrohr](https://github.com/davidrohr) -- [#5056](https://github.com/AliceO2Group/AliceO2/pull/5056) 2020-12-13: Eliminate mass argument from track mat.corrections and propagation interfaces by [@shahor02](https://github.com/shahor02) -- [#5067](https://github.com/AliceO2Group/AliceO2/pull/5067) 2020-12-15: Increase the margin of CTF block size to 10KB by [@shahor02](https://github.com/shahor02) -- [#5077](https://github.com/AliceO2Group/AliceO2/pull/5077) 2020-12-17: Tmp.fix in TrackParCov c-tor from Cartesian cov.matrix by [@shahor02](https://github.com/shahor02) -- [#5089](https://github.com/AliceO2Group/AliceO2/pull/5089) 2020-12-22: real LUT in CCDB by [@AllaMaevskaya](https://github.com/AllaMaevskaya) -- [#5092](https://github.com/AliceO2Group/AliceO2/pull/5092) 2020-12-23: ZDC Workflow to inspect raw data by [@cortesep](https://github.com/cortesep) -- [#5094](https://github.com/AliceO2Group/AliceO2/pull/5094) 2020-12-24: GPU: Some work towards making the o2 propagator work on GPU by [@davidrohr](https://github.com/davidrohr) -- [#5096](https://github.com/AliceO2Group/AliceO2/pull/5096) 2020-12-25: Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU by [@davidrohr](https://github.com/davidrohr) -- [#5100](https://github.com/AliceO2Group/AliceO2/pull/5100) 2020-12-28: GPU: Make more headers compatible to GPU by [@davidrohr](https://github.com/davidrohr) -- [#5104](https://github.com/AliceO2Group/AliceO2/pull/5104) 2021-01-04: Use DBSCAN for Time-Z clustering in PVertexing, debris reduction by [@shahor02](https://github.com/shahor02) +- [#5135](https://github.com/AliceO2Group/AliceO2/pull/5135) 2021-01-08: Add trigger inputs branch by [@AllaMaevskaya](https://github.com/AllaMaevskaya) +- [#5139](https://github.com/AliceO2Group/AliceO2/pull/5139) 2021-01-08: [EMCAL-677] Propagate trigger bits from RDH to TriggerRecord by [@mfasDa](https://github.com/mfasDa) +- [#5142](https://github.com/AliceO2Group/AliceO2/pull/5142) 2021-01-09: Several unrelated fixes in GPU code by [@davidrohr](https://github.com/davidrohr) +- [#5141](https://github.com/AliceO2Group/AliceO2/pull/5141) 2021-01-09: Use GPUTPCO2InterfaceRefit for TPC-ITS matches refit + misc fixes. by [@shahor02](https://github.com/shahor02) +- [#5144](https://github.com/AliceO2Group/AliceO2/pull/5144) 2021-01-10: Fix: increment EMCAL TriggerRecord class version by [@shahor02](https://github.com/shahor02) +- [#5133](https://github.com/AliceO2Group/AliceO2/pull/5133) 2021-01-11: Populate MC event header with information from current Pythia8 event by [@preghenella](https://github.com/preghenella) +- [#5163](https://github.com/AliceO2Group/AliceO2/pull/5163) 2021-01-12: Bring back info treatment in MCEventHeader by [@sawenzel](https://github.com/sawenzel) +- [#5147](https://github.com/AliceO2Group/AliceO2/pull/5147) 2021-01-12: [FV0][O2-1849] Trigger inputs for CTP simulation by [@mslupeck](https://github.com/mslupeck) +- [#5178](https://github.com/AliceO2Group/AliceO2/pull/5178) 2021-01-13: Fixes in entropy compression memory management by [@shahor02](https://github.com/shahor02) +- [#5199](https://github.com/AliceO2Group/AliceO2/pull/5199) 2021-01-15: (O2-1203) [CTF] use merging/splitting iterators during CTF ecoding/decoding for TPC by [@MichaelLettrich](https://github.com/MichaelLettrich) +- [#5192](https://github.com/AliceO2Group/AliceO2/pull/5192) 2021-01-15: FT0 LUT prepared as Singleton for DigitBlockFT0 usage by [@afurs](https://github.com/afurs) +- [#5226](https://github.com/AliceO2Group/AliceO2/pull/5226) 2021-01-19: Bugfix: WorkflowHelper.h was not installled by [@davidrohr](https://github.com/davidrohr) +- [#5227](https://github.com/AliceO2Group/AliceO2/pull/5227) 2021-01-19: Check for selective primary transport also in case of parallel sim by [@preghenella](https://github.com/preghenella) +- [#5216](https://github.com/AliceO2Group/AliceO2/pull/5216) 2021-01-19: TPC Workflow: Move cluster / digit reading from tpc tracking spec into a helper by [@davidrohr](https://github.com/davidrohr) +- [#5228](https://github.com/AliceO2Group/AliceO2/pull/5228) 2021-01-19: o2-sim: Make configfile prefixed with correct name by [@sawenzel](https://github.com/sawenzel) ## Changes in Detectors -- [#5054](https://github.com/AliceO2Group/AliceO2/pull/5054) 2020-12-11: Add braces in oneliners of PHOS code by [@shahor02](https://github.com/shahor02) -- [#5045](https://github.com/AliceO2Group/AliceO2/pull/5045) 2020-12-11: [ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK by [@mconcas](https://github.com/mconcas) -- [#5033](https://github.com/AliceO2Group/AliceO2/pull/5033) 2020-12-11: [ITS] Remove unused classes by [@mconcas](https://github.com/mconcas) -- [#5055](https://github.com/AliceO2Group/AliceO2/pull/5055) 2020-12-12: Change more Double_t to float in TrackParCov propagator by [@davidrohr](https://github.com/davidrohr) -- [#5043](https://github.com/AliceO2Group/AliceO2/pull/5043) 2020-12-12: Make TrackPar(Cov) compatible to GPU by [@davidrohr](https://github.com/davidrohr) -- [#5056](https://github.com/AliceO2Group/AliceO2/pull/5056) 2020-12-13: Eliminate mass argument from track mat.corrections and propagation interfaces by [@shahor02](https://github.com/shahor02) -- [#5058](https://github.com/AliceO2Group/AliceO2/pull/5058) 2020-12-13: Reject outliers when building ITS/MFT clusters dictionary by [@shahor02](https://github.com/shahor02) -- [#5040](https://github.com/AliceO2Group/AliceO2/pull/5040) 2020-12-14: Adding truncation + some minor changes by [@nburmaso](https://github.com/nburmaso) -- [#5036](https://github.com/AliceO2Group/AliceO2/pull/5036) 2020-12-14: First version of pedestal calibration workflow raw data -> ccdb by [@wiechula](https://github.com/wiechula) -- [#5059](https://github.com/AliceO2Group/AliceO2/pull/5059) 2020-12-14: TPC drift gas settings in case FLUKA is used by [@amorsch](https://github.com/amorsch) -- [#5067](https://github.com/AliceO2Group/AliceO2/pull/5067) 2020-12-15: Increase the margin of CTF block size to 10KB by [@shahor02](https://github.com/shahor02) -- [#5047](https://github.com/AliceO2Group/AliceO2/pull/5047) 2020-12-16: TOF DCS Processor by [@chiarazampolli](https://github.com/chiarazampolli) -- [#5057](https://github.com/AliceO2Group/AliceO2/pull/5057) 2020-12-16: Update of water and air cooling by [@frmanso](https://github.com/frmanso) -- [#5078](https://github.com/AliceO2Group/AliceO2/pull/5078) 2020-12-17: Parent TrackPar/Cov creator for DCAFitterN by [@shahor02](https://github.com/shahor02) -- [#5076](https://github.com/AliceO2Group/AliceO2/pull/5076) 2020-12-17: [ITS][ntracker-workflow] Add --configKeyValue for MB LUT by [@mconcas](https://github.com/mconcas) -- [#5088](https://github.com/AliceO2Group/AliceO2/pull/5088) 2020-12-19: MFT: fix lanes mapping for decoding commissionning data and for worki… by [@bovulpes](https://github.com/bovulpes) -- [#5091](https://github.com/AliceO2Group/AliceO2/pull/5091) 2020-12-22: MFT: eliminate sqrt where possible by [@bovulpes](https://github.com/bovulpes) -- [#5089](https://github.com/AliceO2Group/AliceO2/pull/5089) 2020-12-22: real LUT in CCDB by [@AllaMaevskaya](https://github.com/AllaMaevskaya) -- [#5083](https://github.com/AliceO2Group/AliceO2/pull/5083) 2020-12-23: Executable for chunk large raw-data files by [@shahor02](https://github.com/shahor02) -- [#5092](https://github.com/AliceO2Group/AliceO2/pull/5092) 2020-12-23: ZDC Workflow to inspect raw data by [@cortesep](https://github.com/cortesep) -- [#5094](https://github.com/AliceO2Group/AliceO2/pull/5094) 2020-12-24: GPU: Some work towards making the o2 propagator work on GPU by [@davidrohr](https://github.com/davidrohr) -- [#5096](https://github.com/AliceO2Group/AliceO2/pull/5096) 2020-12-25: Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU by [@davidrohr](https://github.com/davidrohr) -- [#5097](https://github.com/AliceO2Group/AliceO2/pull/5097) 2020-12-25: TPC Tracking: Workaround for 0-cluster tracks by [@davidrohr](https://github.com/davidrohr) -- [#5100](https://github.com/AliceO2Group/AliceO2/pull/5100) 2020-12-28: GPU: Make more headers compatible to GPU by [@davidrohr](https://github.com/davidrohr) -- [#5069](https://github.com/AliceO2Group/AliceO2/pull/5069) 2020-12-28: [WIP][ITS-tracking] Add track dumping in standalone debugger by [@mconcas](https://github.com/mconcas) -- [#5102](https://github.com/AliceO2Group/AliceO2/pull/5102) 2020-12-29: Drop bad assert by [@ktf](https://github.com/ktf) -- [#5101](https://github.com/AliceO2Group/AliceO2/pull/5101) 2020-12-29: [EMCAL-675] Handling of pages without trailer by [@mfasDa](https://github.com/mfasDa) -- [#5118](https://github.com/AliceO2Group/AliceO2/pull/5118) 2021-01-04: Default mat.corr. is with LUT, fall-back to TGeo if LUT is not set by [@shahor02](https://github.com/shahor02) -- [#5105](https://github.com/AliceO2Group/AliceO2/pull/5105) 2021-01-04: Disable CA_DEBUG in ITS Tracking by [@davidrohr](https://github.com/davidrohr) -- [#5104](https://github.com/AliceO2Group/AliceO2/pull/5104) 2021-01-04: Use DBSCAN for Time-Z clustering in PVertexing, debris reduction by [@shahor02](https://github.com/shahor02) -- [#5116](https://github.com/AliceO2Group/AliceO2/pull/5116) 2021-01-05: Global (currently TPC only) refit on GPU using either GPU or TrackParCov track model by [@davidrohr](https://github.com/davidrohr) +- [#5135](https://github.com/AliceO2Group/AliceO2/pull/5135) 2021-01-08: Add trigger inputs branch by [@AllaMaevskaya](https://github.com/AllaMaevskaya) +- [#5140](https://github.com/AliceO2Group/AliceO2/pull/5140) 2021-01-08: Fix: do not invoke FIT recpoints reader with --use-fit in raw data input mode by [@shahor02](https://github.com/shahor02) +- [#5139](https://github.com/AliceO2Group/AliceO2/pull/5139) 2021-01-08: [EMCAL-677] Propagate trigger bits from RDH to TriggerRecord by [@mfasDa](https://github.com/mfasDa) +- [#5141](https://github.com/AliceO2Group/AliceO2/pull/5141) 2021-01-09: Use GPUTPCO2InterfaceRefit for TPC-ITS matches refit + misc fixes. by [@shahor02](https://github.com/shahor02) +- [#5144](https://github.com/AliceO2Group/AliceO2/pull/5144) 2021-01-10: Fix: increment EMCAL TriggerRecord class version by [@shahor02](https://github.com/shahor02) +- [#5143](https://github.com/AliceO2Group/AliceO2/pull/5143) 2021-01-11: Fixes for OMP and for dumping events for the standalone benchmark by [@davidrohr](https://github.com/davidrohr) +- [#5153](https://github.com/AliceO2Group/AliceO2/pull/5153) 2021-01-12: Avoid 2D params in SVertexer configurable params by [@shahor02](https://github.com/shahor02) +- [#5147](https://github.com/AliceO2Group/AliceO2/pull/5147) 2021-01-12: [FV0][O2-1849] Trigger inputs for CTP simulation by [@mslupeck](https://github.com/mslupeck) +- [#5164](https://github.com/AliceO2Group/AliceO2/pull/5164) 2021-01-13: Allow multiple test workflows with non-overlapping TF-ids by [@shahor02](https://github.com/shahor02) +- [#5178](https://github.com/AliceO2Group/AliceO2/pull/5178) 2021-01-13: Fixes in entropy compression memory management by [@shahor02](https://github.com/shahor02) +- [#5175](https://github.com/AliceO2Group/AliceO2/pull/5175) 2021-01-13: GPU: remove leftover debug messages by [@davidrohr](https://github.com/davidrohr) +- [#5179](https://github.com/AliceO2Group/AliceO2/pull/5179) 2021-01-13: Work towards getting the TPC Tracking QA run standalone from a tracks ROOT file by [@davidrohr](https://github.com/davidrohr) +- [#5185](https://github.com/AliceO2Group/AliceO2/pull/5185) 2021-01-14: Add TPC QC histograms for (limited) monitoring of cluster rejection on the fly while processing without MC information by [@davidrohr](https://github.com/davidrohr) +- [#5180](https://github.com/AliceO2Group/AliceO2/pull/5180) 2021-01-14: Do not encode TDC errors to compressed output stream by [@preghenella](https://github.com/preghenella) +- [#5181](https://github.com/AliceO2Group/AliceO2/pull/5181) 2021-01-14: Standalone TPC Tracking QA (independent from o2-tpc-reco-workflow) by [@davidrohr](https://github.com/davidrohr) +- [#5199](https://github.com/AliceO2Group/AliceO2/pull/5199) 2021-01-15: (O2-1203) [CTF] use merging/splitting iterators during CTF ecoding/decoding for TPC by [@MichaelLettrich](https://github.com/MichaelLettrich) +- [#5192](https://github.com/AliceO2Group/AliceO2/pull/5192) 2021-01-15: FT0 LUT prepared as Singleton for DigitBlockFT0 usage by [@afurs](https://github.com/afurs) +- [#5187](https://github.com/AliceO2Group/AliceO2/pull/5187) 2021-01-15: Fix: remap RootTreeWriter branches only once by [@shahor02](https://github.com/shahor02) +- [#5202](https://github.com/AliceO2Group/AliceO2/pull/5202) 2021-01-16: [EMCAL-630] Store result of the raw fit as energy by [@mfasDa](https://github.com/mfasDa) +- [#5186](https://github.com/AliceO2Group/AliceO2/pull/5186) 2021-01-17: GPU: Add option to tpc-reco-workflow to ship shared cluster map created during tracking by [@davidrohr](https://github.com/davidrohr) +- [#5208](https://github.com/AliceO2Group/AliceO2/pull/5208) 2021-01-18: TPC-ITS matching will use tpc-reco-workflow or on-the-fly created shared cl.map by [@shahor02](https://github.com/shahor02) +- [#5198](https://github.com/AliceO2Group/AliceO2/pull/5198) 2021-01-18: small improvement in fake track rejection by [@pillot](https://github.com/pillot) +- [#5226](https://github.com/AliceO2Group/AliceO2/pull/5226) 2021-01-19: Bugfix: WorkflowHelper.h was not installled by [@davidrohr](https://github.com/davidrohr) +- [#5216](https://github.com/AliceO2Group/AliceO2/pull/5216) 2021-01-19: TPC Workflow: Move cluster / digit reading from tpc tracking spec into a helper by [@davidrohr](https://github.com/davidrohr) +- [#5225](https://github.com/AliceO2Group/AliceO2/pull/5225) 2021-01-19: [EMCAL-630] Fix assignment of energy and time by [@mfasDa](https://github.com/mfasDa) +- [#5228](https://github.com/AliceO2Group/AliceO2/pull/5228) 2021-01-19: o2-sim: Make configfile prefixed with correct name by [@sawenzel](https://github.com/sawenzel) +- [#5221](https://github.com/AliceO2Group/AliceO2/pull/5221) 2021-01-19: refactor TRD digit class by [@bazinski](https://github.com/bazinski) +## Changes in Examples + +- [#5133](https://github.com/AliceO2Group/AliceO2/pull/5133) 2021-01-11: Populate MC event header with information from current Pythia8 event by [@preghenella](https://github.com/preghenella) ## Changes in Framework -- [#5048](https://github.com/AliceO2Group/AliceO2/pull/5048) 2020-12-11: DPL: allow customization of FairMQ channels from command line by [@ktf](https://github.com/ktf) -- [#5063](https://github.com/AliceO2Group/AliceO2/pull/5063) 2020-12-14: DPL Analysis: add string array Configurable by [@aalkin](https://github.com/aalkin) -- [#5035](https://github.com/AliceO2Group/AliceO2/pull/5035) 2020-12-14: DPL Analysis: fix for parsing non-integer arrays in configurables by [@aalkin](https://github.com/aalkin) -- [#5050](https://github.com/AliceO2Group/AliceO2/pull/5050) 2020-12-14: DPL Analysis: use compile-time hashed histogram names in registry by [@mario-krueger](https://github.com/mario-krueger) -- [#5065](https://github.com/AliceO2Group/AliceO2/pull/5065) 2020-12-14: DPL: add file read name metric by [@ktf](https://github.com/ktf) -- [#5068](https://github.com/AliceO2Group/AliceO2/pull/5068) 2020-12-15: DPL Analysis: make sure each hash in histogram registry is unique by [@mario-krueger](https://github.com/mario-krueger) -- [#5073](https://github.com/AliceO2Group/AliceO2/pull/5073) 2020-12-16: DPL: allow decoupling from JAlien and retrieve JAlienFile, if available by [@ktf](https://github.com/ktf) -- [#5071](https://github.com/AliceO2Group/AliceO2/pull/5071) 2020-12-16: DPL: initial support for plugin based algorithms by [@ktf](https://github.com/ktf) -- [#5081](https://github.com/AliceO2Group/AliceO2/pull/5081) 2020-12-18: DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support by [@ktf](https://github.com/ktf) -- [#5098](https://github.com/AliceO2Group/AliceO2/pull/5098) 2020-12-27: DPL: use RawDeviceService to sleep in example by [@ktf](https://github.com/ktf) -- [#5113](https://github.com/AliceO2Group/AliceO2/pull/5113) 2021-01-04: DPL: drop unneeded include statements by [@ktf](https://github.com/ktf) -- [#5099](https://github.com/AliceO2Group/AliceO2/pull/5099) 2021-01-04: DPL: move GUI to a plugin by [@ktf](https://github.com/ktf) +- [#5160](https://github.com/AliceO2Group/AliceO2/pull/5160) 2021-01-12: add alien SE by [@jgrosseo](https://github.com/jgrosseo) +- [#5177](https://github.com/AliceO2Group/AliceO2/pull/5177) 2021-01-13: AliEn metrics by [@jgrosseo](https://github.com/jgrosseo) +- [#5165](https://github.com/AliceO2Group/AliceO2/pull/5165) 2021-01-13: DPL utils: allow customising output-proxy by [@ktf](https://github.com/ktf) +- [#5168](https://github.com/AliceO2Group/AliceO2/pull/5168) 2021-01-13: DPL: increase max size of string metrics to 256 bytes by [@ktf](https://github.com/ktf) +- [#5183](https://github.com/AliceO2Group/AliceO2/pull/5183) 2021-01-14: Adding opening and run time metrics by [@jgrosseo](https://github.com/jgrosseo) +- [#5159](https://github.com/AliceO2Group/AliceO2/pull/5159) 2021-01-14: fix to allow iteratorAt on filtered tables by [@jgrosseo](https://github.com/jgrosseo) +- [#5189](https://github.com/AliceO2Group/AliceO2/pull/5189) 2021-01-15: DPL: add `--forwarding-policy none` to help message by [@ktf](https://github.com/ktf) +- [#5187](https://github.com/AliceO2Group/AliceO2/pull/5187) 2021-01-15: Fix: remap RootTreeWriter branches only once by [@shahor02](https://github.com/shahor02) +- [#5195](https://github.com/AliceO2Group/AliceO2/pull/5195) 2021-01-15: fix for 2 readers and 1 input file by [@jgrosseo](https://github.com/jgrosseo) +- [#5203](https://github.com/AliceO2Group/AliceO2/pull/5203) 2021-01-17: DPL: move driver communication to a separate Service by [@ktf](https://github.com/ktf) +- [#5229](https://github.com/AliceO2Group/AliceO2/pull/5229) 2021-01-19: raw-parser logs DataHeader and DataProcessingHeader info by [@shahor02](https://github.com/shahor02) +## Changes in Generators + +- [#5133](https://github.com/AliceO2Group/AliceO2/pull/5133) 2021-01-11: Populate MC event header with information from current Pythia8 event by [@preghenella](https://github.com/preghenella) +- [#5163](https://github.com/AliceO2Group/AliceO2/pull/5163) 2021-01-12: Bring back info treatment in MCEventHeader by [@sawenzel](https://github.com/sawenzel) +- [#5152](https://github.com/AliceO2Group/AliceO2/pull/5152) 2021-01-12: Revert "Populate event header with information of the current Pythia8… by [@sawenzel](https://github.com/sawenzel) +## Changes in Steer + +- [#5135](https://github.com/AliceO2Group/AliceO2/pull/5135) 2021-01-08: Add trigger inputs branch by [@AllaMaevskaya](https://github.com/AllaMaevskaya) +- [#5139](https://github.com/AliceO2Group/AliceO2/pull/5139) 2021-01-08: [EMCAL-677] Propagate trigger bits from RDH to TriggerRecord by [@mfasDa](https://github.com/mfasDa) +- [#5147](https://github.com/AliceO2Group/AliceO2/pull/5147) 2021-01-12: [FV0][O2-1849] Trigger inputs for CTP simulation by [@mslupeck](https://github.com/mslupeck) +- [#5187](https://github.com/AliceO2Group/AliceO2/pull/5187) 2021-01-15: Fix: remap RootTreeWriter branches only once by [@shahor02](https://github.com/shahor02) ## Changes in Utilities -- [#5037](https://github.com/AliceO2Group/AliceO2/pull/5037) 2020-12-14: Drop untested / unused hough transform code by [@ktf](https://github.com/ktf) +- [#5151](https://github.com/AliceO2Group/AliceO2/pull/5151) 2021-01-12: Small fixes by [@sawenzel](https://github.com/sawenzel) +- [#5156](https://github.com/AliceO2Group/AliceO2/pull/5156) 2021-01-12: o2-sim: Better signal propagation; small fix in jobutils by [@sawenzel](https://github.com/sawenzel) +- [#5169](https://github.com/AliceO2Group/AliceO2/pull/5169) 2021-01-13: jobutils: exit workflows on first task error by [@sawenzel](https://github.com/sawenzel) +- [#5172](https://github.com/AliceO2Group/AliceO2/pull/5172) 2021-01-14: Fix o2_add_dpl_workflow on Ubuntu and some other systems by [@davidrohr](https://github.com/davidrohr) +- [#5199](https://github.com/AliceO2Group/AliceO2/pull/5199) 2021-01-15: (O2-1203) [CTF] use merging/splitting iterators during CTF ecoding/decoding for TPC by [@MichaelLettrich](https://github.com/MichaelLettrich) +- [#5196](https://github.com/AliceO2Group/AliceO2/pull/5196) 2021-01-15: small fix in jobutils by [@sawenzel](https://github.com/sawenzel) diff --git a/doc/data/2021-01-o2_prs.json b/doc/data/2021-01-o2_prs.json index ad8de47895c57..57cb126d02555 100644 --- a/doc/data/2021-01-o2_prs.json +++ b/doc/data/2021-01-o2_prs.json @@ -5,427 +5,372 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-09T13:52:19Z", - "title": "GPU: Tune some kernel parameters for AMD Vega", - "number": 5024, + "mergedAt": "2021-01-11T08:46:01Z", + "title": "Populate MC event header with information from current Pythia8 event", + "number": 5133, "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ - { - "node": { - "path": "GPU/Common/GPUDefGPUParameters.h" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-08T19:05:59Z", - "title": "Getting prepared for boolean columns", - "number": 5025, - "author": { - "login": "victor-gonzalez" - }, - "files": { - "edges": [ - { - "node": { - "path": "Analysis/Tasks/PWGCF/dptdptcorrelations.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-05T09:00:05Z", - "title": "Convert collision time to ps in TOF PID response", - "number": 5026, - "author": { - "login": "njacazio" + "login": "preghenella" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDTOF.h" + "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" } }, { "node": { - "path": "Analysis/Tasks/pidTOF.cxx" + "path": "DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-08T08:21:19Z", - "title": "DPL: attempt at supporting cloned processors", - "number": 5027, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/Core/include/Framework/runDataProcessing.h" + "path": "DataFormats/simulation/src/MCEventHeader.cxx" } }, { "node": { - "path": "Framework/Core/src/WorkflowHelpers.cxx" + "path": "Generators/include/Generators/Generator.h" } }, { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "Generators/include/Generators/GeneratorPythia8.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-09T14:56:44Z", - "title": "DPL: syntactic sugar for --clone <template>:<instance number>", - "number": 5028, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "Generators/src/Generator.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-08T12:58:36Z", - "title": "DPL GUI: add buttons to debug / profile the driver", - "number": 5029, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/Core/src/FrameworkGUIDebugger.cxx" + "path": "Generators/src/GeneratorPythia8.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-08T17:47:53Z", - "title": "DPL: better error message when DPL_ENABLE_STACKTRACE not set", - "number": 5030, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "doc/DetectorSimulation.md" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-08T15:10:36Z", - "title": "Fix for MCTruth label checks", - "number": 5031, - "author": { - "login": "nburmaso" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" + "path": "run/SimExamples/Adaptive_Pythia8/adaptive_pythia8.macro" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Drop initial prototype of dataflow setup", - "number": 5032, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Utilities/CMakeLists.txt" + "path": "run/SimExamples/AliRoot_AMPT/aliroot_ampt.macro" } }, { "node": { - "path": "Utilities/DataFlow/CMakeLists.txt" + "path": "run/SimExamples/Custom_EventInfo/generator.macro" } }, { "node": { - "path": "Utilities/DataFlow/doc/o2-subframebuilder-device.1.in" + "path": "run/SimExamples/Custom_EventInfo/pythia8_inel.cfg" } }, { "node": { - "path": "Utilities/DataFlow/doc/o2-timeframe-reader-device.1.in" + "path": "run/SimExamples/Custom_EventInfo/read_event_info.macro" } }, { "node": { - "path": "Utilities/DataFlow/doc/o2-timeframe-writer-device.1.in" + "path": "run/SimExamples/Custom_EventInfo/run.sh" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/EPNReceiverDevice.h" + "path": "run/SimExamples/Custom_EventInfo/sim.ini" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/FLPSenderDevice.h" + "path": "run/SimExamples/HF_Embedding_Pythia8/GeneratorHF.macro" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeBuilder.h" + "path": "run/SimExamples/README.md" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/FakeTimeframeGeneratorDevice.h" + "path": "run/SimExamples/Signal_ImpactB/signal_impactb.macro" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-08T08:24:42Z", + "title": "RootSerializableKeyValueStore: Add print function", + "number": 5134, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ { "node": { - "path": "Utilities/DataFlow/include/DataFlow/HeartbeatSampler.h" + "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/PayloadMerger.h" + "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/SubframeBuilderDevice.h" + "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-08T19:51:25Z", + "title": "Add trigger inputs branch ", + "number": 5135, + "author": { + "login": "AllaMaevskaya" + }, + "files": { + "edges": [ { "node": { - "path": "Utilities/DataFlow/include/DataFlow/SubframeUtils.h" + "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/Digit.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeParser.h" + "path": "DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeReaderDevice.h" + "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Digitizer.h" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeValidatorDevice.h" + "path": "Detectors/FIT/FT0/simulation/src/Digitizer.cxx" } }, { "node": { - "path": "Utilities/DataFlow/include/DataFlow/TimeframeWriterDevice.h" + "path": "Steer/DigitizerWorkflow/src/FT0DigitWriterSpec.h" } }, { "node": { - "path": "Utilities/DataFlow/run/CreateSetup.py" + "path": "Steer/DigitizerWorkflow/src/FT0DigitizerSpec.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "CLOSED", + "mergedAt": null, + "title": "Analysis/Task/PWGDQ: update dileptonEE.cxx", + "number": 5136, + "author": { + "login": "dsekihat" + }, + "files": { + "edges": [ { "node": { - "path": "Utilities/DataFlow/run/confBasicSetup.json" + "path": "Analysis/Tasks/PWGDQ/dileptonEE.cxx" } }, { "node": { - "path": "Utilities/DataFlow/run/confComplexSetup.json" + "path": "Analysis/Tasks/PWGDQ/tableMaker.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Prototype for background-on-signal filtering for ITS digitization (WIP)", + "number": 5137, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ { "node": { - "path": "Utilities/DataFlow/run/confComplexSetup2.json" + "path": "DataFormats/simulation/include/SimulationDataFormat/DigitizationContext.h" } }, { "node": { - "path": "Utilities/DataFlow/run/confFakeTimeframe.json" + "path": "Steer/DigitizerWorkflow/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/run/startBasicSetup.sh" + "path": "Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx" } }, { "node": { - "path": "Utilities/DataFlow/run/startComplexSetup.sh" + "path": "dependencies/O2Dependencies.cmake" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-12T14:31:51Z", + "title": "PWGDQ utility classes moved from AnalysisCore to Analysis/Tasks/PWGDQ", + "number": 5138, + "author": { + "login": "iarsene" + }, + "files": { + "edges": [ { "node": { - "path": "Utilities/DataFlow/run/startComplexSetup2.sh" + "path": "Analysis/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/run/startTimeframeExample.sh" + "path": "Analysis/Core/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/EPNReceiverDevice.cxx" + "path": "Analysis/Core/src/AnalysisCoreLinkDef.h" } }, { "node": { - "path": "Utilities/DataFlow/src/FLPSenderDevice.cxx" + "path": "Analysis/PWGDQ/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/FakeTimeframeBuilder.cxx" + "path": "Analysis/PWGDQ/include/PWGDQCore/AnalysisCompositeCut.h" } }, { "node": { - "path": "Utilities/DataFlow/src/FakeTimeframeGeneratorDevice.cxx" + "path": "Analysis/PWGDQ/include/PWGDQCore/AnalysisCut.h" } }, { "node": { - "path": "Utilities/DataFlow/src/HeartbeatSampler.cxx" + "path": "Analysis/PWGDQ/include/PWGDQCore/CutsLibrary.h" } }, { "node": { - "path": "Utilities/DataFlow/src/SubframeBuilderDevice.cxx" + "path": "Analysis/PWGDQ/include/PWGDQCore/HistogramManager.h" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeParser.cxx" + "path": "Analysis/PWGDQ/include/PWGDQCore/HistogramsLibrary.h" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeReaderDevice.cxx" + "path": "Analysis/PWGDQ/include/PWGDQCore/VarManager.h" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeValidationTool.cxx" + "path": "Analysis/PWGDQ/src/AnalysisCompositeCut.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeValidatorDevice.cxx" + "path": "Analysis/PWGDQ/src/AnalysisCut.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/TimeframeWriterDevice.cxx" + "path": "Analysis/PWGDQ/src/HistogramManager.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/runEPNReceiver.cxx" + "path": "Analysis/PWGDQ/src/PWGDQCoreLinkDef.h" } }, { "node": { - "path": "Utilities/DataFlow/src/runFLPSender.cxx" + "path": "Analysis/PWGDQ/src/VarManager.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/runFakeTimeframeGeneratorDevice.cxx" + "path": "Analysis/Tasks/PWGDQ/CMakeLists.txt" } }, { "node": { - "path": "Utilities/DataFlow/src/runHeartbeatSampler.cxx" + "path": "Analysis/Tasks/PWGDQ/dileptonEE.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/runSubframeBuilderDevice.cxx" + "path": "Analysis/Tasks/PWGDQ/dileptonMuMu.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/runTimeframeReaderDevice.cxx" + "path": "Analysis/Tasks/PWGDQ/filterPP.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/runTimeframeValidatorDevice.cxx" + "path": "Analysis/Tasks/PWGDQ/tableMaker.cxx" } }, { "node": { - "path": "Utilities/DataFlow/src/runTimeframeWriterDevice.cxx" + "path": "Analysis/Tasks/PWGDQ/tableMakerMuon_pp.cxx" } }, { "node": { - "path": "Utilities/DataFlow/test/test_PayloadMerger01.cxx" + "path": "Analysis/Tasks/PWGDQ/tableMaker_pp.cxx" } }, { "node": { - "path": "Utilities/DataFlow/test/test_SubframeUtils01.cxx" + "path": "Analysis/Tasks/PWGDQ/tableReader.cxx" } }, { "node": { - "path": "Utilities/DataFlow/test/test_TimeframeParser.cxx" + "path": "Analysis/Tasks/reducedEventAnalysis.cxx" } } ] @@ -435,42 +380,42 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T16:10:58Z", - "title": "[ITS] Remove unused classes", - "number": 5033, + "mergedAt": "2021-01-08T20:28:09Z", + "title": "[EMCAL-677] Propagate trigger bits from RDH to TriggerRecord", + "number": 5139, "author": { - "login": "mconcas" + "login": "mfasDa" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + "path": "DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/DBScan.h" + "path": "DataFormats/Detectors/EMCAL/src/TriggerRecord.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Graph.h" + "path": "Detectors/EMCAL/simulation/src/RawWriter.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/DBScan.cxx" + "path": "Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Graph.cxx" + "path": "Steer/DigitizerWorkflow/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + "path": "Steer/DigitizerWorkflow/src/EMCALDigitizerSpec.cxx" } } ] @@ -480,52 +425,72 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-10T08:19:25Z", - "title": "Moving StepTHn to Framework", - "number": 5034, + "mergedAt": "2021-01-08T19:22:37Z", + "title": "Fix: do not invoke FIT recpoints reader with --use-fit in raw data input mode", + "number": 5140, "author": { - "login": "jgrosseo" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Analysis/Core/CMakeLists.txt" + "path": "Detectors/GlobalTrackingWorkflow/tofworkflow/src/tof-reco-workflow.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-09T00:15:28Z", + "title": "Use GPUTPCO2InterfaceRefit for TPC-ITS matches refit + misc fixes.", + "number": 5141, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" } }, { "node": { - "path": "Framework/AnalysisTools/CMakeLists.txt" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" } }, { "node": { - "path": "Framework/AnalysisTools/src/AnalysisToolsLinkDef.h" + "path": "Detectors/Base/include/DetectorsBase/Propagator.h" } }, { "node": { - "path": "Framework/CMakeLists.txt" + "path": "Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h" } }, { "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "Detectors/GlobalTracking/src/MatchTPCITS.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/StepTHn.h" + "path": "Detectors/TPC/reconstruction/src/GPUCATracking.cxx" } }, { "node": { - "path": "Framework/Core/src/StepTHn.cxx" + "path": "GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx" } }, { "node": { - "path": "Framework/Core/test/FrameworkCoreTestLinkDef.h" + "path": "GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h" } } ] @@ -535,32 +500,47 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T10:16:35Z", - "title": "DPL Analysis: fix for parsing non-integer arrays in configurables", - "number": 5035, + "mergedAt": "2021-01-09T08:45:20Z", + "title": "Several unrelated fixes in GPU code", + "number": 5142, "author": { - "login": "aalkin" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/src/BoostOptionsRetriever.cxx" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" } }, { "node": { - "path": "Framework/Core/src/DataProcessingDevice.cxx" + "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Base/GPUParam.cxx" } }, { "node": { - "path": "Framework/Core/src/PropertyTreeHelpers.cxx" + "path": "GPU/GPUTracking/Base/GPUSettingsList.h" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Standalone/CMakeLists.txt" + } + }, + { + "node": { + "path": "GPU/GPUTracking/dEdx/GPUdEdx.h" } }, { "node": { - "path": "Framework/Core/src/RootConfigParamHelpers.cxx" + "path": "dependencies/FindO2GPU.cmake" } } ] @@ -570,107 +550,32 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T17:26:02Z", - "title": "First version of pedestal calibration workflow raw data -> ccdb", - "number": 5036, + "mergedAt": "2021-01-11T08:44:21Z", + "title": "Fixes for OMP and for dumping events for the standalone benchmark", + "number": 5143, "author": { - "login": "wiechula" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Detectors/TPC/base/include/TPCBase/CDBInterface.h" + "path": "Detectors/TPC/reconstruction/src/GPUCATracking.cxx" } }, { "node": { - "path": "Detectors/TPC/calibration/CMakeLists.txt" + "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" } }, { "node": { - "path": "Detectors/TPC/calibration/include/TPCCalibration/CalibRawBase.h" + "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.cxx" } }, { "node": { - "path": "Detectors/TPC/calibration/macro/runPedestal.C" - } - }, - { - "node": { - "path": "Detectors/TPC/calibration/macro/runPedestal.sh" - } - }, - { - "node": { - "path": "Detectors/TPC/calibration/run/calib-pedestal.cxx" - } - }, - { - "node": { - "path": "Detectors/TPC/calibration/src/CalibRawBase.cxx" - } - }, - { - "node": { - "path": "Detectors/TPC/calibration/src/CalibTreeDump.cxx" - } - }, - { - "node": { - "path": "Detectors/TPC/reconstruction/include/TPCReconstruction/RawReaderCRU.h" - } - }, - { - "node": { - "path": "Detectors/TPC/reconstruction/src/RawReaderCRU.cxx" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/README.md" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/include/TPCWorkflow/CalibProcessingHelper.h" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/include/TPCWorkflow/RawToDigitsSpec.h" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/src/CalibProcessingHelper.cxx" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/src/RawToDigitsSpec.cxx" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/src/tpc-calib-pedestal.cxx" - } - }, - { - "node": { - "path": "Detectors/TPC/workflow/src/tpc-raw-to-digits-workflow.cxx" + "path": "GPU/GPUTracking/Interface/GPUO2Interface.cxx" } } ] @@ -680,32 +585,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T09:09:26Z", - "title": "Drop untested / unused hough transform code", - "number": 5037, + "mergedAt": "2021-01-10T14:53:05Z", + "title": "Fix: increment EMCAL TriggerRecord class version", + "number": 5144, "author": { - "login": "ktf" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Utilities/CMakeLists.txt" - } - }, - { - "node": { - "path": "Utilities/hough/CMakeLists.txt" - } - }, - { - "node": { - "path": "Utilities/hough/README.md" - } - }, - { - "node": { - "path": "Utilities/hough/runHough.cxx" + "path": "DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/TriggerRecord.h" } } ] @@ -715,22 +605,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-09T17:05:42Z", - "title": "DPL: allow adding suffix to all dataprocessors in a workflow", - "number": 5038, + "mergedAt": "2021-01-12T07:48:46Z", + "title": "embedding_pileup_check: don't assume 'view' label format", + "number": 5145, "author": { - "login": "ktf" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/include/Framework/runDataProcessing.h" - } - }, - { - "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "macro/analyzeDigitLabels.C" } } ] @@ -739,108 +624,48 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T09:04:29Z", - "title": "Fixed bug for nested AnalysisCompositeCuts; removed duplicated histogram classes from TableReader", - "number": 5039, + "state": "OPEN", + "mergedAt": null, + "title": "Change Tau0 max to 10 mm in Pythia8 configurations", + "number": 5146, "author": { - "login": "iarsene" + "login": "preghenella" }, "files": { "edges": [ { "node": { - "path": "Analysis/Core/include/AnalysisCore/AnalysisCompositeCut.h" + "path": "Generators/share/egconfig/pythia8_hf.cfg" } }, { "node": { - "path": "Analysis/Core/src/AnalysisCompositeCut.cxx" + "path": "Generators/share/egconfig/pythia8_hi.cfg" } }, { "node": { - "path": "Analysis/Tasks/PWGDQ/tableReader.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T08:50:21Z", - "title": "Adding truncation + some minor changes", - "number": 5040, - "author": { - "login": "nburmaso" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h" + "path": "Generators/share/egconfig/pythia8_inel.cfg" } }, { "node": { - "path": "Detectors/AOD/src/AODProducerWorkflowSpec.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T10:36:58Z", - "title": "Use value_t instead of double", - "number": 5041, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ - { - "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" + "path": "run/SimExamples/Adaptive_Pythia8/pythia8_inel.cfg" } }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T09:02:23Z", - "title": "Change to new TPCrefit check: finders", - "number": 5042, - "author": { - "login": "ddobrigk" - }, - "files": { - "edges": [ - { - "node": { - "path": "Analysis/Tasks/PWGLF/cascadefinder.cxx" + "path": "run/SimExamples/Custom_EventInfo/pythia8_inel.cfg" } }, { "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + "path": "run/SimExamples/HF_Embedding_Pythia8/pythia8_ccbar.template" } }, { "node": { - "path": "Analysis/Tasks/multiplicityQa.cxx" + "path": "run/SimExamples/Jet_Embedding_Pythia8/pythia8_hard.cfg" } } ] @@ -850,562 +675,117 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-12T08:55:06Z", - "title": "Make TrackPar(Cov) compatible to GPU", - "number": 5043, + "mergedAt": "2021-01-12T10:53:10Z", + "title": "[FV0][O2-1849] Trigger inputs for CTP simulation", + "number": 5147, "author": { - "login": "davidrohr" + "login": "mslupeck" }, "files": { "edges": [ { "node": { - "path": "Common/MathUtils/include/MathUtils/CartesianGPU.h" - } - }, - { - "node": { - "path": "Common/MathUtils/include/MathUtils/Utils.h" - } - }, - { - "node": { - "path": "Common/MathUtils/include/MathUtils/detail/CircleXY.h" - } - }, - { - "node": { - "path": "Common/MathUtils/include/MathUtils/detail/IntervalXY.h" - } - }, - { - "node": { - "path": "Common/MathUtils/include/MathUtils/detail/trigonometric.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/DCA.cxx" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/PID.cxx" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/PrimaryVertex.cxx" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/Vertex.cxx" - } - }, - { - "node": { - "path": "DataFormats/common/include/CommonDataFormat/InteractionRecord.h" - } - }, - { - "node": { - "path": "DataFormats/common/src/InteractionRecord.cxx" - } - }, - { - "node": { - "path": "Detectors/Base/src/Propagator.cxx" - } - }, - { - "node": { - "path": "GPU/Common/CMakeLists.txt" - } - }, - { - "node": { - "path": "GPU/Common/GPUCommonArray.h" - } - }, - { - "node": { - "path": "GPU/Common/GPUCommonDef.h" - } - }, - { - "node": { - "path": "GPU/Common/GPUCommonLogger.h" + "path": "DataFormats/Detectors/FIT/FV0/include/DataFormatsFV0/BCData.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + "path": "DataFormats/Detectors/FIT/FV0/src/DataFormatsFV0LinkDef.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/cuda/CMakeLists.txt" + "path": "Detectors/FIT/FV0/simulation/include/FV0Simulation/Digitizer.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/hip/CMakeLists.txt" + "path": "Detectors/FIT/FV0/simulation/src/Digitizer.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/opencl2/CMakeLists.txt" + "path": "Steer/DigitizerWorkflow/src/FV0DigitWriterSpec.h" } }, { "node": { - "path": "GPU/GPUTracking/Standalone/CMakeLists.txt" + "path": "Steer/DigitizerWorkflow/src/FV0DigitizerSpec.cxx" } } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-10T13:55:19Z", - "title": "Decouple VMC libs from o2-sim", - "number": 5044, - "author": { - "login": "sawenzel" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/gconfig/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/G3Config.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/G4Config.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/SetCuts.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/SetCuts.h" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/SimSetup.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T07:33:24Z", - "title": "[ALICE3] Rename PostLS4 and IT4 to ALICE3 and TRK", - "number": 5045, - "author": { - "login": "mconcas" - }, - "files": { - "edges": [ - { - "node": { - "path": "Common/SimConfig/src/SimConfig.cxx" - } - }, - { - "node": { - "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/Common/src/DetID.cxx" - } - }, - { - "node": { - "path": "DataFormats/Headers/include/Headers/DataHeader.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/README.md" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/MisalignmentParameter.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/src/MisalignmentParameter.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/base/src/TRKBaseLinkDef.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/macros/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/macros/test/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/data/simcuts.dat" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V11Geometry.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V1Layer.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Layer.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/V3Services.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKSimulationLinkDef.h" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V11Geometry.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V1Layer.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Layer.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/V3Services.cxx" - } - }, - { - "node": { - "path": "Detectors/Upgrades/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Upgrades/README.md" - } - }, - { - "node": { - "path": "macro/CMakeLists.txt" - } - }, - { - "node": { - "path": "macro/build_geometry.C" - } - }, - { - "node": { - "path": "macro/run_trac_alice3.C" - } - }, - { - "node": { - "path": "run/CMakeLists.txt" - } - }, - { - "node": { - "path": "run/O2HitMerger.h" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-10T20:31:15Z", - "title": "Support for FLUKA VMC backend in O2", - "number": 5046, - "author": { - "login": "sawenzel" - }, - "files": { - "edges": [ - { - "node": { - "path": "DataFormats/simulation/src/Stack.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/gconfig/data/coreFlukaVmc.inp" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/FlukaConfig.cxx" - } - }, - { - "node": { - "path": "Detectors/gconfig/src/SimSetup.cxx" - } - }, - { - "node": { - "path": "dependencies/FindFlukaVMC.cmake" - } - }, - { - "node": { - "path": "dependencies/O2FindDependenciesFromAliBuild.cmake" - } - }, - { - "node": { - "path": "dependencies/O2SimulationDependencies.cmake" - } - }, - { - "node": { - "path": "run/O2SimDevice.h" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-16T22:10:35Z", - "title": "TOF DCS Processor", - "number": 5047, - "author": { - "login": "chiarazampolli" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/DCS/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/DCS/src/DataPointGenerator.cxx" - } - }, - { - "node": { - "path": "Detectors/DCS/src/DetectorsDCSLinkDef.h" - } - }, - { - "node": { - "path": "Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h" - } - }, - { - "node": { - "path": "Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx" - } - }, + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "[ALICE 3] Add separate class to describe A3 beam pipe + 12-layer A3 layout", + "number": 5148, + "author": { + "login": "mconcas" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/TOF/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TOF/base/include/TOFBase/Geo.h" + "path": "Detectors/Upgrades/ALICE3/Passive/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TOF/base/src/Geo.cxx" + "path": "Detectors/Upgrades/ALICE3/Passive/include/A3DetectorsPassive/A3PassiveBase.h" } }, { "node": { - "path": "Detectors/TOF/calibration/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/Passive/include/A3DetectorsPassive/A3Pipe.h" } }, { "node": { - "path": "Detectors/TOF/calibration/include/TOFCalibration/TOFDCSProcessor.h" + "path": "Detectors/Upgrades/ALICE3/Passive/src/A3PassiveBase.cxx" } }, { "node": { - "path": "Detectors/TOF/calibration/macros/CMakeLists.txt" + "path": "Detectors/Upgrades/ALICE3/Passive/src/A3PassiveLinkDef.h" } }, { "node": { - "path": "Detectors/TOF/calibration/macros/makeCCDBEntryForDCS.cxx" + "path": "Detectors/Upgrades/ALICE3/Passive/src/A3Pipe.cxx" } }, { "node": { - "path": "Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h" } }, { "node": { - "path": "Detectors/TOF/calibration/src/TOFDCSProcessor.cxx" + "path": "Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx" } }, { "node": { - "path": "Detectors/TOF/calibration/testWorkflow/README.md" + "path": "macro/CMakeLists.txt" } }, { "node": { - "path": "Detectors/TOF/calibration/testWorkflow/TOFDCSDataProcessorSpec.h" + "path": "macro/build_geometry.C" } }, { "node": { - "path": "Detectors/TOF/calibration/testWorkflow/tof-dcs-data-workflow.cxx" + "path": "run/CMakeLists.txt" } } ] @@ -1414,10 +794,10 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-11T09:04:41Z", - "title": "DPL: allow customization of FairMQ channels from command line", - "number": 5048, + "state": "OPEN", + "mergedAt": null, + "title": "DPL: workaround Ubuntu libc bug", + "number": 5149, "author": { "login": "ktf" }, @@ -1425,57 +805,102 @@ "edges": [ { "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "Framework/Core/include/Framework/Lifetime.h" } }, { "node": { - "path": "Framework/Core/include/Framework/ChannelConfigurationPolicyHelpers.h" + "path": "Framework/Core/src/CommonMessageBackends.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/ChannelSpec.h" + "path": "Framework/Core/src/DataProcessingDevice.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/WorkflowCustomizationHelpers.h" + "path": "Framework/Core/src/DeviceSpecHelpers.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/runDataProcessing.h" + "path": "Framework/Core/src/runDataProcessing.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-16T18:37:32Z", + "title": "PWGHF: fix of the histogram registry in the Lc task", + "number": 5150, + "author": { + "login": "DelloStritto" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/src/ChannelConfigurationPolicy.cxx" + "path": "Analysis/Tasks/PWGHF/taskD0.cxx" } }, { "node": { - "path": "Framework/Core/src/ChannelConfigurationPolicyHelpers.cxx" + "path": "Analysis/Tasks/PWGHF/taskDPlus.cxx" } }, { "node": { - "path": "Framework/Core/src/ChannelSpecHelpers.cxx" + "path": "Analysis/Tasks/PWGHF/taskLc.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-12T12:12:42Z", + "title": "Small fixes", + "number": 5151, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/src/DeviceSpecHelpers.cxx" + "path": "Utilities/Tools/jobutils.sh" } }, { "node": { - "path": "Framework/Core/src/WorkflowCustomizationHelpers.cxx" + "path": "run/o2sim_parallel.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-12T12:13:05Z", + "title": "Revert \"Populate event header with information of the current Pythia8…", + "number": 5152, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/test/Mocking.h" + "path": "Generators/src/GeneratorPythia8.cxx" } } ] @@ -1485,9 +910,9 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T15:53:21Z", - "title": "Add DAQ SystemID Unloaded [O2-1918]", - "number": 5049, + "mergedAt": "2021-01-12T14:57:36Z", + "title": "Avoid 2D params in SVertexer configurable params", + "number": 5153, "author": { "login": "shahor02" }, @@ -1495,12 +920,12 @@ "edges": [ { "node": { - "path": "DataFormats/Headers/include/Headers/DAQID.h" + "path": "Detectors/Vertexing/include/DetectorsVertexing/SVertexerParams.h" } }, { "node": { - "path": "DataFormats/Headers/test/testDAQID.cxx" + "path": "Detectors/Vertexing/src/SVertexer.cxx" } } ] @@ -1509,20 +934,35 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T08:40:42Z", - "title": "DPL Analysis: use compile-time hashed histogram names in registry", - "number": 5050, + "state": "CLOSED", + "mergedAt": null, + "title": "DPL: publish aod-file-read-path metric", + "number": 5154, "author": { - "login": "mario-krueger" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Analysis/Core/include/AnalysisCore/PairCuts.h" + "path": "Framework/Core/src/runDataProcessing.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-13T08:03:14Z", + "title": "Add multiplicity distribution task", + "number": 5155, + "author": { + "login": "jgrosseo" + }, + "files": { + "edges": [ { "node": { "path": "Analysis/Tasks/PWGCF/correlations.cxx" @@ -1530,72 +970,72 @@ }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGHF/qaTask.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGHF/taskD0.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGHF/taskDPlus.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/spectraTOF.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/PWGLF/spectraTPC.cxx" - } - }, - { - "node": { - "path": "Analysis/Tasks/pidTOF.cxx" + "path": "Analysis/Tasks/PWGCF/filterCF.cxx" } }, { "node": { - "path": "Analysis/Tasks/pidTPC.cxx" + "path": "Analysis/Tutorials/CMakeLists.txt" } }, { "node": { - "path": "Analysis/Tasks/trackqa.cxx" + "path": "Analysis/Tutorials/src/multiplicityEventTrackSelection.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-12T17:22:43Z", + "title": "o2-sim: Better signal propagation; small fix in jobutils", + "number": 5156, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tutorials/src/histogramRegistry.cxx" + "path": "Utilities/Tools/jobutils.sh" } }, { "node": { - "path": "Framework/Core/include/Framework/HistogramRegistry.h" + "path": "run/o2sim_parallel.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-12T15:22:29Z", + "title": "Add CPV raw generation, reco, entropy encoding to full system test scripts", + "number": 5157, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/src/HistogramRegistry.cxx" + "path": "prodtests/full-system-test/dpl-workflow.sh" } }, { "node": { - "path": "Framework/Core/test/benchmark_HistogramRegistry.cxx" + "path": "prodtests/full-system-test/setenv.sh" } }, { "node": { - "path": "Framework/Core/test/test_HistogramRegistry.cxx" + "path": "prodtests/full_system_test.sh" } } ] @@ -1605,17 +1045,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T09:07:35Z", - "title": "Drop obsolete badge", - "number": 5051, + "mergedAt": "2021-01-13T15:22:25Z", + "title": "use filters", + "number": 5158, "author": { - "login": "ktf" + "login": "jgrosseo" }, "files": { "edges": [ { "node": { - "path": "README.md" + "path": "Analysis/Tasks/PWGUD/CMakeLists.txt" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGUD/upcAnalysis.cxx" } } ] @@ -1624,18 +1069,18 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "PWGHF: do not merge yet: Add efficiency and fix impact parameter calculation", - "number": 5052, + "state": "MERGED", + "mergedAt": "2021-01-14T12:10:30Z", + "title": "fix to allow iteratorAt on filtered tables", + "number": 5159, "author": { - "login": "hzanoli" + "login": "jgrosseo" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/qaTask.cxx" + "path": "Framework/Core/include/Framework/ASoA.h" } } ] @@ -1645,22 +1090,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-12T12:41:53Z", - "title": "ndsplines: added approximateFunctionBatch function", - "number": 5053, + "mergedAt": "2021-01-12T19:08:58Z", + "title": "add alien SE", + "number": 5160, "author": { - "login": "matthias-kleiner" + "login": "jgrosseo" }, "files": { "edges": [ { "node": { - "path": "GPU/TPCFastTransformation/SplineHelper.cxx" - } - }, - { - "node": { - "path": "GPU/TPCFastTransformation/SplineHelper.h" + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" } } ] @@ -1670,22 +1110,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-11T15:54:24Z", - "title": "Add braces in oneliners of PHOS code", - "number": 5054, + "mergedAt": "2021-01-15T14:58:15Z", + "title": "DPL: do not mask errors when generating workflows", + "number": 5161, "author": { - "login": "shahor02" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" - } - }, - { - "node": { - "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" + "path": "cmake/O2AddWorkflow.cmake" } } ] @@ -1694,18 +1129,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-12T08:55:30Z", - "title": "Change more Double_t to float in TrackParCov propagator", - "number": 5055, + "state": "OPEN", + "mergedAt": null, + "title": "DPL: protect against non-existing AnalysisPlugin", + "number": 5162, "author": { - "login": "davidrohr" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Framework/Core/src/WorkflowHelpers.cxx" } } ] @@ -1715,82 +1150,57 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-13T13:05:53Z", - "title": "Eliminate mass argument from track mat.corrections and propagation interfaces", - "number": 5056, + "mergedAt": "2021-01-12T20:05:09Z", + "title": "Bring back info treatment in MCEventHeader", + "number": 5163, "author": { - "login": "shahor02" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrization.cxx" - } - }, - { - "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" - } - }, - { - "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" - } - }, - { - "node": { - "path": "Detectors/Base/src/Propagator.cxx" - } - }, - { - "node": { - "path": "Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h" - } - }, - { - "node": { - "path": "Detectors/GlobalTracking/src/MatchTOF.cxx" + "path": "DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h" } }, { "node": { - "path": "Detectors/GlobalTracking/src/MatchTPCITS.cxx" + "path": "Generators/src/GeneratorPythia8.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "run/O2HitMerger.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-13T08:30:48Z", + "title": "Allow multiple test workflows with non-overlapping TF-ids", + "number": 5164, + "author": { + "login": "shahor02" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx" + "path": "Detectors/TOF/calibration/testWorkflow/DataGeneratorSpec.h" } }, { "node": { - "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.cxx" + "path": "Detectors/TOF/calibration/testWorkflow/README.md" } }, { "node": { - "path": "GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h" + "path": "Detectors/TOF/calibration/testWorkflow/data-generator-workflow.cxx" } } ] @@ -1800,27 +1210,37 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-16T18:17:59Z", - "title": "Update of water and air cooling", - "number": 5057, + "mergedAt": "2021-01-13T10:43:43Z", + "title": "DPL utils: allow customising output-proxy", + "number": 5165, "author": { - "login": "frmanso" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/MFT/base/src/HalfCone.cxx" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/MFT/base/src/HeatExchanger.cxx" + "path": "Framework/Utils/src/dpl-output-proxy.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "CLOSED", + "mergedAt": null, + "title": "DPL examples: add monitoring usage to diamond example", + "number": 5166, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ITSMFT/MFT/base/src/PowerSupplyUnit.cxx" + "path": "Framework/TestWorkflows/src/o2DiamondWorkflow.cxx" } } ] @@ -1829,23 +1249,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-13T20:42:36Z", - "title": "Reject outliers when building ITS/MFT clusters dictionary", - "number": 5058, + "state": "CLOSED", + "mergedAt": null, + "title": "Use o2_add_executable for DataSampling standalone workflow", + "number": 5167, "author": { - "login": "shahor02" + "login": "knopers8" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/MFT/macros/test/CheckTopologies.C" + "path": "Utilities/DataSampling/CMakeLists.txt" } } ] @@ -1855,17 +1270,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T08:01:58Z", - "title": "TPC drift gas settings in case FLUKA is used", - "number": 5059, + "mergedAt": "2021-01-13T12:09:56Z", + "title": "DPL: increase max size of string metrics to 256 bytes", + "number": 5168, "author": { - "login": "amorsch" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Detectors/TPC/simulation/src/Detector.cxx" + "path": "Framework/Core/include/Framework/DeviceMetricsInfo.h" + } + }, + { + "node": { + "path": "Framework/Core/test/test_DeviceMetricsInfo.cxx" } } ] @@ -1875,17 +1295,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T10:52:58Z", - "title": "Fix finder -> problems with partitioning to be checked", - "number": 5060, + "mergedAt": "2021-01-13T15:09:37Z", + "title": "jobutils: exit workflows on first task error", + "number": 5169, "author": { - "login": "ddobrigk" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + "path": "Utilities/Tools/jobutils.sh" } } ] @@ -1894,38 +1314,18 @@ }, { "node": { - "state": "CLOSED", - "mergedAt": null, - "title": "A ROOT serializable key-value store", - "number": 5061, + "state": "MERGED", + "mergedAt": "2021-01-15T08:15:54Z", + "title": "Create a PR with new CHANGELOG entries", + "number": 5170, "author": { - "login": "sawenzel" + "login": "TimoWilken" }, "files": { "edges": [ { "node": { - "path": "Common/Utils/CMakeLists.txt" - } - }, - { - "node": { - "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" - } - }, - { - "node": { - "path": "Common/Utils/src/CommonUtilsLinkDef.h" - } - }, - { - "node": { - "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" - } - }, - { - "node": { - "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" + "path": ".github/workflows/reports.yml" } } ] @@ -1936,116 +1336,101 @@ "node": { "state": "OPEN", "mergedAt": null, - "title": "[WIP][ITS-tracking] Extend smoother to n-dimensional tracking", - "number": 5062, + "title": "[DCS][TOF] Make the data point random generator more reusable.", + "number": 5171, "author": { - "login": "mconcas" + "login": "aphecetche" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h" + "path": "Detectors/DCS/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/PrimaryVertexContext.h" + "path": "Detectors/DCS/testWorkflow/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + "path": "Detectors/DCS/testWorkflow/DCSRandomDataGeneratorSpec.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h" + "path": "Detectors/DCS/testWorkflow/README.md" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" + "path": "Detectors/DCS/testWorkflow/dcs-sim-workflow.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/DCS/testWorkflow/include/DCStestWorkflow/DCSRandomDataGeneratorSpec.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx" + "path": "Detectors/DCS/testWorkflow/src/DCSConsumerSpec.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T21:42:12Z", - "title": "DPL Analysis: add string array Configurable", - "number": 5063, - "author": { - "login": "aalkin" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Analysis/Tutorials/include/Analysis/configurableCut.h" + "path": "Detectors/DCS/testWorkflow/src/DCSDataGeneratorSpec.h" } }, { "node": { - "path": "Analysis/Tutorials/src/configurableCut.cxx" + "path": "Detectors/DCS/testWorkflow/src/DCSDataProcessorSpec.h" } }, { "node": { - "path": "Analysis/Tutorials/src/configurableObjects.cxx" + "path": "Detectors/DCS/testWorkflow/src/DCSRandomDataGeneratorSpec.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/ConfigParamsHelper.h" + "path": "Detectors/DCS/testWorkflow/src/DCStoDPLconverter.h" } }, { "node": { - "path": "Framework/Core/include/Framework/Variant.h" + "path": "Detectors/DCS/testWorkflow/src/dcs-data-client-workflow.cxx" } }, { "node": { - "path": "Framework/Core/src/BoostOptionsRetriever.cxx" + "path": "Detectors/DCS/testWorkflow/src/dcs-data-workflow.cxx" } }, { "node": { - "path": "Framework/Core/src/ConfigParamsHelper.cxx" + "path": "Detectors/DCS/testWorkflow/src/dcs-proxy.cxx" } }, { "node": { - "path": "Framework/Core/src/PropertyTreeHelpers.cxx" + "path": "Detectors/DCS/testWorkflow/src/dcs-random-data-workflow.cxx" } }, { "node": { - "path": "Framework/Core/src/RootConfigParamHelpers.cxx" + "path": "Detectors/TOF/calibration/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/Variant.cxx" + "path": "Detectors/TOF/calibration/testWorkflow/README.md" } }, { "node": { - "path": "Framework/Core/test/test_Variants.cxx" + "path": "Detectors/TOF/calibration/testWorkflow/tof-dcs-sim-workflow.cxx" } } ] @@ -2055,17 +1440,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-14T21:43:13Z", - "title": "Using histogram registry fill", - "number": 5064, + "mergedAt": "2021-01-14T08:48:50Z", + "title": "Fix o2_add_dpl_workflow on Ubuntu and some other systems", + "number": 5172, "author": { - "login": "jgrosseo" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGCF/correlations.cxx" + "path": "Utilities/DataSampling/CMakeLists.txt" + } + }, + { + "node": { + "path": "cmake/O2AddWorkflow.cmake" } } ] @@ -2074,33 +1464,43 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-14T19:43:17Z", - "title": "DPL: add file read name metric", - "number": 5065, + "state": "CLOSED", + "mergedAt": null, + "title": "Update nuclei task", + "number": 5173, "author": { - "login": "ktf" + "login": "lbariogl" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/src/AODReaderHelpers.cxx" - } - }, - { - "node": { - "path": "Framework/Core/src/ResourcesMonitoringHelper.cxx" + "path": "Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx" } }, { "node": { - "path": "Framework/Core/src/ResourcesMonitoringHelper.h" + "path": "Generators/src/GeneratorPythia8.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-14T13:20:11Z", + "title": "Add histrogram register and track selection", + "number": 5174, + "author": { + "login": "lbariogl" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx" } } ] @@ -2110,17 +1510,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-15T08:48:19Z", - "title": "Analysis: extend histogram registry example", - "number": 5066, + "mergedAt": "2021-01-13T12:18:33Z", + "title": "GPU: remove leftover debug messages", + "number": 5175, "author": { - "login": "mario-krueger" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tutorials/src/histogramRegistry.cxx" + "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" } } ] @@ -2130,17 +1530,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-15T13:38:12Z", - "title": "Increase the margin of CTF block size to 10KB", - "number": 5067, + "mergedAt": "2021-01-13T12:34:24Z", + "title": "GPU: Fix memory buffer scaling factor when memory allocation strategy is auto", + "number": 5176, "author": { - "login": "shahor02" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h" + "path": "GPU/GPUTracking/Interface/GPUO2Interface.cxx" } } ] @@ -2150,27 +1550,37 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-15T21:49:40Z", - "title": "DPL Analysis: make sure each hash in histogram registry is unique", - "number": 5068, + "mergedAt": "2021-01-13T20:54:43Z", + "title": "AliEn metrics", + "number": 5177, "author": { - "login": "mario-krueger" + "login": "jgrosseo" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/include/Framework/HistogramRegistry.h" + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" + } + }, + { + "node": { + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h" + } + }, + { + "node": { + "path": "Framework/Core/include/Framework/DataInputDirector.h" } }, { "node": { - "path": "Framework/Core/src/HistogramRegistry.cxx" + "path": "Framework/Core/src/DataInputDirector.cxx" } }, { "node": { - "path": "Framework/Core/test/test_HistogramRegistry.cxx" + "path": "Framework/Core/src/runDataProcessing.cxx" } } ] @@ -2180,52 +1590,52 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-28T13:55:03Z", - "title": "[WIP][ITS-tracking] Add track dumping in standalone debugger", - "number": 5069, + "mergedAt": "2021-01-13T23:16:02Z", + "title": "Fixes in entropy compression memory management", + "number": 5178, "author": { - "login": "mconcas" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/CMakeLists.txt" + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h" + "path": "Detectors/CPV/reconstruction/include/CPVReconstruction/CTFCoder.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + "path": "Detectors/EMCAL/reconstruction/include/EMCALReconstruction/CTFCoder.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/StandaloneDebugger.h" + "path": "Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + "path": "Detectors/MUON/MID/CTF/include/MIDCTF/CTFCoder.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/StandaloneDebugger.cxx" + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/CTFCoder.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/TOF/reconstruction/src/CTFCoder.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + "path": "Detectors/TPC/reconstruction/src/CTFCoder.cxx" } } ] @@ -2234,73 +1644,73 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "TRD tracklet calculation in TrapSimulator", - "number": 5070, + "state": "MERGED", + "mergedAt": "2021-01-13T20:50:20Z", + "title": "Work towards getting the TPC Tracking QA run standalone from a tracks ROOT file", + "number": 5179, "author": { - "login": "martenole" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/TRD/include/DataFormatsTRD/Tracklet64.h" + "path": "Detectors/TPC/qc/include/TPCQC/Tracking.h" } }, { "node": { - "path": "Detectors/TRD/macros/convertRun2ToRun3Digits.C" + "path": "Detectors/TPC/qc/src/Tracking.cxx" } }, { "node": { - "path": "Detectors/TRD/simulation/src/TrapSimulator.cxx" + "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-16T12:19:42Z", - "title": "DPL: initial support for plugin based algorithms", - "number": 5071, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Framework/AnalysisSupport/CMakeLists.txt" + "path": "GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx" } }, { "node": { - "path": "Framework/AnalysisSupport/src/Plugin.cxx" + "path": "GPU/GPUTracking/Interface/GPUO2InterfaceQA.h" } }, { "node": { - "path": "Framework/CMakeLists.txt" + "path": "GPU/GPUTracking/Standalone/qa/GPUQA.cxx" } }, { "node": { - "path": "Framework/Core/include/Framework/AlgorithmSpec.h" + "path": "GPU/GPUTracking/Standalone/qa/GPUQA.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-14T08:52:06Z", + "title": "Do not encode TDC errors to compressed output stream", + "number": 5180, + "author": { + "login": "preghenella" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/include/Framework/Plugins.h" + "path": "Detectors/TOF/compression/src/Compressor.cxx" } }, { "node": { - "path": "Framework/Core/src/WorkflowHelpers.cxx" + "path": "Detectors/TOF/workflow/src/CompressedDecodingTask.cxx" } } ] @@ -2309,38 +1719,33 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "A ROOT serializable key-value store", - "number": 5072, + "state": "MERGED", + "mergedAt": "2021-01-14T08:48:11Z", + "title": "Standalone TPC Tracking QA (independent from o2-tpc-reco-workflow)", + "number": 5181, "author": { - "login": "sawenzel" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Common/Utils/CMakeLists.txt" - } - }, - { - "node": { - "path": "Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h" + "path": "Detectors/TPC/workflow/CMakeLists.txt" } }, { "node": { - "path": "Common/Utils/src/CommonUtilsLinkDef.h" + "path": "Detectors/TPC/workflow/include/TPCWorkflow/TrackReaderSpec.h" } }, { "node": { - "path": "Common/Utils/src/RootSerializableKeyValueStore.cxx" + "path": "Detectors/TPC/workflow/src/TrackReaderWorkflow.cxx" } }, { "node": { - "path": "Common/Utils/test/testRootSerializableKeyValueStore.cxx" + "path": "GPU/GPUTracking/Standalone/qa/GPUQA.cxx" } } ] @@ -2350,72 +1755,62 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-16T16:28:44Z", - "title": "DPL: allow decoupling from JAlien and retrieve JAlienFile, if available", - "number": 5073, + "mergedAt": "2021-01-19T08:31:06Z", + "title": "Add split tables per particle species in PID response", + "number": 5182, "author": { - "login": "ktf" + "login": "njacazio" }, "files": { "edges": [ { "node": { - "path": "Framework/AnalysisSupport/CMakeLists.txt" - } - }, - { - "node": { - "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" - } - }, - { - "node": { - "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h" + "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h" } }, { "node": { - "path": "Framework/AnalysisSupport/src/Plugin.cxx" + "path": "Analysis/Tasks/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "Analysis/Tasks/PWGLF/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/include/Framework/AODReaderHelpers.h" + "path": "Analysis/Tasks/PWGLF/spectraTOF.cxx" } }, { "node": { - "path": "Framework/Core/src/AODReaderHelpers.cxx" + "path": "Analysis/Tasks/PWGLF/spectraTOF_split.cxx" } }, { "node": { - "path": "Framework/Core/src/AnalysisDataModelHelpers.cxx" + "path": "Analysis/Tasks/PWGLF/spectraTPC.cxx" } }, { "node": { - "path": "Framework/Core/src/AnalysisDataModelHelpers.h" + "path": "Analysis/Tasks/PWGLF/spectraTPC_split.cxx" } }, { "node": { - "path": "dependencies/FindJAlienROOT.cmake" + "path": "Analysis/Tasks/pidTOF_split.cxx" } }, { "node": { - "path": "dependencies/FindXRootD.cmake" + "path": "Analysis/Tasks/pidTPC.cxx" } }, { "node": { - "path": "dependencies/O2Dependencies.cmake" + "path": "Analysis/Tasks/pidTPC_split.cxx" } } ] @@ -2425,27 +1820,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-05T08:41:46Z", - "title": " Initial version of EMCAL Correction Task", - "number": 5074, + "mergedAt": "2021-01-14T18:31:31Z", + "title": "Adding opening and run time metrics", + "number": 5183, "author": { - "login": "raymondEhlers" + "login": "jgrosseo" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/EMCALClusters.h" + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" } }, { "node": { - "path": "Analysis/Tasks/CMakeLists.txt" + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.h" } }, { "node": { - "path": "Analysis/Tasks/emcalCorrectionTask.cxx" + "path": "Framework/Core/include/Framework/DeviceMetricsInfo.h" } } ] @@ -2454,43 +1849,53 @@ }, { "node": { - "state": "CLOSED", - "mergedAt": null, - "title": "Jpsi task and candidate selection", - "number": 5075, + "state": "MERGED", + "mergedAt": "2021-01-14T13:23:32Z", + "title": "Update CommonUtilsLinkDef.h", + "number": 5184, "author": { - "login": "zhangbiao-phy" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" - } - }, - { - "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + "path": "Common/Utils/src/CommonUtilsLinkDef.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-14T19:20:50Z", + "title": "Add TPC QC histograms for (limited) monitoring of cluster rejection on the fly while processing without MC information", + "number": 5185, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + "path": "GPU/GPUTracking/Base/GPUSettingsList.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + "path": "GPU/GPUTracking/Standalone/qa/GPUQA.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + "path": "GPU/GPUTracking/Standalone/qa/GPUQA.h" } } ] @@ -2500,102 +1905,77 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-17T22:44:51Z", - "title": "[ITS][ntracker-workflow] Add --configKeyValue for MB LUT", - "number": 5076, + "mergedAt": "2021-01-17T19:22:53Z", + "title": "GPU: Add option to tpc-reco-workflow to ship shared cluster map created during tracking", + "number": 5186, "author": { - "login": "mconcas" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h" + "path": "Detectors/TPC/workflow/include/TPCWorkflow/CATrackerSpec.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h" + "path": "Detectors/TPC/workflow/include/TPCWorkflow/RecoWorkflow.h" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx" + "path": "Detectors/TPC/workflow/src/RecoWorkflow.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h" + "path": "Detectors/TPC/workflow/src/tpc-reco-workflow.cxx" } }, { "node": { - "path": "Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx" + "path": "GPU/GPUTracking/Base/GPUSettingsList.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-17T19:07:38Z", - "title": "Tmp.fix in TrackParCov c-tor from Cartesian cov.matrix", - "number": 5077, - "author": { - "login": "shahor02" - }, - "files": { - "edges": [ + }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx" + "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-17T22:22:35Z", - "title": "Parent TrackPar/Cov creator for DCAFitterN", - "number": 5078, - "author": { - "login": "shahor02" - }, - "files": { - "edges": [ + }, + { + "node": { + "path": "GPU/GPUTracking/Global/GPUChainTracking.h" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Interface/GPUO2Interface.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Interface/GPUO2Interface.h" + } + }, { "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/DCAFitterN.h" + "path": "GPU/GPUTracking/Interface/GPUO2InterfaceConfiguration.h" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-17T22:27:23Z", - "title": "Fix FindJAliEnROOT.cmake name", - "number": 5079, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "dependencies/FindJAliEnROOT.cmake" + "path": "GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx" + } + }, + { + "node": { + "path": "GPU/GPUTracking/Merger/GPUTPCGMMerger.h" } } ] @@ -2604,43 +1984,43 @@ }, { "node": { - "state": "CLOSED", - "mergedAt": null, - "title": "Jpsi task and candidate selection", - "number": 5080, + "state": "MERGED", + "mergedAt": "2021-01-15T20:28:42Z", + "title": "Fix: remap RootTreeWriter branches only once", + "number": 5187, "author": { - "login": "zhangbiao-phy" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + "path": "Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx" } }, { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + "path": "Detectors/TPC/workflow/src/RecoWorkflow.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "Detectors/TRD/workflow/src/TRDDigitWriterSpec.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + "path": "Framework/Utils/include/DPLUtils/RootTreeWriter.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + "path": "Steer/DigitizerWorkflow/src/FDDDigitWriterSpec.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + "path": "Steer/DigitizerWorkflow/src/TPCDigitRootWriterSpec.cxx" } } ] @@ -2650,17 +2030,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-18T20:32:10Z", - "title": "DPL: Use JAliEn::JAliEn rather than XRootD::Client to enable support", - "number": 5081, + "mergedAt": "2021-01-15T10:11:13Z", + "title": "The following changelog has been automatically generated.", + "number": 5188, "author": { - "login": "ktf" + "login": "github-actions" }, "files": { "edges": [ { "node": { - "path": "Framework/AnalysisSupport/CMakeLists.txt" + "path": "CHANGELOG.md" + } + }, + { + "node": { + "path": "doc/data/2021-01-o2_prs.json" + } + }, + { + "node": { + "path": "doc/data/2021-01-o2_releases.json" } } ] @@ -2669,18 +2059,18 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Fill PDG code database before event generation", - "number": 5082, + "state": "MERGED", + "mergedAt": "2021-01-15T12:36:18Z", + "title": "DPL: add `--forwarding-policy none` to help message", + "number": 5189, "author": { - "login": "mpuccio" + "login": "ktf" }, "files": { "edges": [ { "node": { - "path": "Generators/src/GeneratorFactory.cxx" + "path": "Framework/Core/src/WorkflowCustomizationHelpers.cxx" } } ] @@ -2689,33 +2079,48 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-23T00:45:23Z", - "title": "Executable for chunk large raw-data files", - "number": 5083, + "state": "OPEN", + "mergedAt": null, + "title": "fix CCDB publication time stamp, add draw from CCDB", + "number": 5190, "author": { - "login": "shahor02" + "login": "wiechula" }, "files": { "edges": [ { "node": { - "path": "Detectors/Raw/CMakeLists.txt" + "path": "Detectors/TPC/calibration/macro/drawNoiseAndPedestal.C" } }, { "node": { - "path": "Detectors/Raw/include/DetectorsRaw/RawFileWriter.h" + "path": "Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPedestalSpec.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "The following changelog has been automatically generated.", + "number": 5191, + "author": { + "login": "github-actions" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/Raw/src/RawFileWriter.cxx" + "path": "CHANGELOG.md" } }, { "node": { - "path": "Detectors/Raw/src/rawfileSplit.cxx" + "path": "doc/data/2021-01-o2_prs.json" } } ] @@ -2725,27 +2130,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-19T22:20:45Z", - "title": "Add X at minimum to v0data table", - "number": 5084, + "mergedAt": "2021-01-15T17:56:16Z", + "title": "FT0 LUT prepared as Singleton for DigitBlockFT0 usage", + "number": 5192, "author": { - "login": "ddobrigk" + "login": "afurs" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/StrangenessTables.h" + "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h" } }, { "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" + "path": "Detectors/FIT/FT0/raw/include/FT0Raw/DigitBlockFT0.h" } }, { "node": { - "path": "Analysis/Tasks/PWGLF/lambdakzeroproducer.cxx" + "path": "Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx" } } ] @@ -2756,41 +2161,41 @@ "node": { "state": "OPEN", "mergedAt": null, - "title": "PWGHF: Jpsi to e+e- task and candidate selection for HF", - "number": 5085, + "title": "TOFFEElight processing", + "number": 5193, "author": { - "login": "zhangbiao-phy" + "login": "chiarazampolli" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFCandidateSelectionTables.h" + "path": "Detectors/TOF/calibration/CMakeLists.txt" } }, { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + "path": "Detectors/TOF/calibration/include/TOFCalibration/TOFFEElightConfig.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "Detectors/TOF/calibration/include/TOFCalibration/TOFFEElightReader.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + "path": "Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFJpsiCandidateSelector.cxx" + "path": "Detectors/TOF/calibration/src/TOFFEElightConfig.cxx" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/taskJpsi.cxx" + "path": "Detectors/TOF/calibration/src/TOFFEElightReader.cxx" } } ] @@ -2799,28 +2204,63 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Use Dynamic columns for the expected PID signals", - "number": 5086, + "state": "MERGED", + "mergedAt": "2021-01-15T15:45:47Z", + "title": "GPU: Put reasonable max time bin for triggered TPC data", + "number": 5194, "author": { - "login": "njacazio" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h" + "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" } }, { "node": { - "path": "Analysis/Tasks/pidTOF.cxx" + "path": "GPU/GPUTracking/TPCClusterFinder/clusterFinderDefs.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-15T23:22:58Z", + "title": "fix for 2 readers and 1 input file", + "number": 5195, + "author": { + "login": "jgrosseo" + }, + "files": { + "edges": [ { "node": { - "path": "Analysis/Tasks/pidTPC.cxx" + "path": "Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-15T14:17:20Z", + "title": "small fix in jobutils", + "number": 5196, + "author": { + "login": "sawenzel" + }, + "files": { + "edges": [ + { + "node": { + "path": "Utilities/Tools/jobutils.sh" } } ] @@ -2831,121 +2271,161 @@ "node": { "state": "OPEN", "mergedAt": null, - "title": "Bugfix in digits->raw->cell chain", - "number": 5087, + "title": "Fixed memory leak in DataContainer3D", + "number": 5197, "author": { - "login": "peressounko" + "login": "matthias-kleiner" + }, + "files": { + "edges": [ + { + "node": { + "path": "Detectors/TPC/spacecharge/include/TPCSpaceCharge/DataContainer3D.h" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-18T08:12:30Z", + "title": "small improvement in fake track rejection", + "number": 5198, + "author": { + "login": "pillot" }, "files": { "edges": [ { "node": { - "path": "Detectors/PHOS/base/include/PHOSBase/Mapping.h" + "path": "Detectors/MUON/MCH/Tracking/README.md" } }, { "node": { - "path": "Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h" + "path": "Detectors/MUON/MCH/Tracking/include/MCHTracking/Track.h" } }, { "node": { - "path": "Detectors/PHOS/base/include/PHOSBase/RCUTrailer.h" + "path": "Detectors/MUON/MCH/Tracking/src/Track.cxx" } }, { "node": { - "path": "Detectors/PHOS/base/src/Mapping.cxx" + "path": "Detectors/MUON/MCH/Tracking/src/TrackFinder.cxx" } }, { "node": { - "path": "Detectors/PHOS/base/src/RCUTrailer.cxx" + "path": "Detectors/MUON/MCH/Tracking/src/TrackFinderOriginal.cxx" + } + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-15T23:14:55Z", + "title": "(O2-1203) [CTF] use merging/splitting iterators during CTF ecoding/decoding for TPC ", + "number": 5199, + "author": { + "login": "MichaelLettrich" + }, + "files": { + "edges": [ + { + "node": { + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/EncodedBlocks.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/AltroDecoder.h" + "path": "DataFormats/Detectors/TPC/include/DataFormatsTPC/CTF.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawPayload.h" + "path": "Detectors/Base/include/DetectorsBase/CTFCoderBase.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/RawReaderMemory.h" + "path": "Detectors/CTF/test/test_ctf_io_tpc.cxx" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/run/rawReaderFile.cxx" + "path": "Detectors/TPC/reconstruction/include/TPCReconstruction/CTFCoder.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/AltroDecoder.cxx" + "path": "Detectors/TPC/reconstruction/src/CTFCoder.cxx" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx" + "path": "Utilities/rANS/benchmarks/bench_ransCombinedIterator.cxx" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/RawReaderMemory.cxx" + "path": "Utilities/rANS/include/rANS/Decoder.h" } }, { "node": { - "path": "Detectors/PHOS/simulation/include/PHOSSimulation/RawWriter.h" + "path": "Utilities/rANS/include/rANS/DedupDecoder.h" } }, { "node": { - "path": "Detectors/PHOS/simulation/src/Detector.cxx" + "path": "Utilities/rANS/include/rANS/DedupEncoder.h" } }, { "node": { - "path": "Detectors/PHOS/simulation/src/Digitizer.cxx" + "path": "Utilities/rANS/include/rANS/Encoder.h" } }, { "node": { - "path": "Detectors/PHOS/simulation/src/RawWriter.cxx" + "path": "Utilities/rANS/include/rANS/LiteralDecoder.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/ClusterizerSpec.h" + "path": "Utilities/rANS/include/rANS/LiteralEncoder.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/include/PHOSWorkflow/RawToCellConverterSpec.h" + "path": "Utilities/rANS/include/rANS/internal/Decoder.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/CellConverterSpec.cxx" + "path": "Utilities/rANS/include/rANS/internal/Encoder.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/ClusterizerSpec.cxx" + "path": "Utilities/rANS/include/rANS/internal/helper.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/PublisherSpec.cxx" + "path": "Utilities/rANS/include/rANS/utils/CombinedIterator.h" } }, { "node": { - "path": "Detectors/PHOS/workflow/src/RawToCellConverterSpec.cxx" + "path": "Utilities/rANS/test/test_ransCombinedIterator.cxx" } } ] @@ -2955,37 +2435,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-19T14:01:47Z", - "title": "MFT: fix lanes mapping for decoding commissionning data and for worki…", - "number": 5088, + "mergedAt": "2021-01-16T09:08:23Z", + "title": "PWGHF changing default preselection values for hyperloop", + "number": 5200, "author": { - "login": "bovulpes" + "login": "nzardosh" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx" + "path": "Analysis/Core/include/AnalysisCore/HFConfigurables.h" } }, { "node": { - "path": "Detectors/ITSMFT/common/simulation/src/MC2RawEncoder.cxx" + "path": "Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx" } } ] @@ -2994,168 +2459,138 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-22T21:07:34Z", - "title": "real LUT in CCDB", - "number": 5089, + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF, RecoDecay: Add gen. level pT of matched D0 candidates.", + "number": 5201, "author": { - "login": "AllaMaevskaya" + "login": "vkucera" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/FIT/FT0/CMakeLists.txt" - } - }, - { - "node": { - "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/RawEventData.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/FIT/FT0/src/DataFormatsFT0LinkDef.h" - } - }, - { - "node": { - "path": "Detectors/FIT/FT0/base/files/FT0ChannelsTable.txt" - } - }, - { - "node": { - "path": "Detectors/FIT/FT0/base/files/Sim2DataChannels.txt" + "path": "Analysis/Core/CMakeLists.txt" } }, { "node": { - "path": "Detectors/FIT/FT0/base/include/FT0Base/Geometry.h" + "path": "Analysis/Core/include/AnalysisCore/RecoDecay.h" } }, { "node": { - "path": "Detectors/FIT/FT0/base/src/Geometry.cxx" + "path": "Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/raw/include/FT0Raw/RawReaderFT0Base.h" + "path": "Analysis/Tasks/PWGHF/taskD0.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-16T16:06:35Z", + "title": "[EMCAL-630] Store result of the raw fit as energy", + "number": 5202, + "author": { + "login": "mfasDa" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/FIT/FT0/raw/src/DigitBlockFT0.cxx" + "path": "Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-17T19:28:52Z", + "title": "DPL: move driver communication to a separate Service", + "number": 5203, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/ReadRaw.h" + "path": "Framework/Core/CMakeLists.txt" } }, { "node": { - "path": "Detectors/FIT/FT0/reconstruction/src/ReadRaw.cxx" + "path": "Framework/Core/include/Framework/CommonServices.h" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/CMakeLists.txt" + "path": "Framework/Core/include/Framework/ControlService.h" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Detector.h" + "path": "Framework/Core/include/Framework/DriverClient.h" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/include/FT0Simulation/Digits2Raw.h" + "path": "Framework/Core/include/Framework/TextControlService.h" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/src/Detector.cxx" + "path": "Framework/Core/src/CommonServices.cxx" } }, { "node": { - "path": "Detectors/FIT/FT0/simulation/src/Digits2Raw.cxx" + "path": "Framework/Core/src/ControlService.cxx" } }, { "node": { - "path": "Detectors/FIT/macros/CMakeLists.txt" + "path": "Framework/Core/src/TextDriverClient.cxx" } }, { "node": { - "path": "Detectors/FIT/macros/uploadLookUpTable.C" - } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Add skeleton for DDbar analysis", - "number": 5090, - "author": { - "login": "ginnocen" - }, - "files": { - "edges": [ - { - "node": { - "path": "Analysis/Tasks/PWGHF/CMakeLists.txt" + "path": "Framework/Core/src/TextDriverClient.h" } }, { "node": { - "path": "Analysis/Tasks/PWGHF/HFDDbar_corr.cxx" + "path": "Framework/Core/src/runDataProcessing.cxx" } } ] } } }, - { - "node": { - "state": "MERGED", - "mergedAt": "2020-12-22T21:06:19Z", - "title": "MFT: eliminate sqrt where possible", - "number": 5091, - "author": { - "login": "bovulpes" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/Tracker.h" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/MFT/tracking/include/MFTTracking/TrackerConfig.h" - } - }, - { - "node": { - "path": "Detectors/ITSMFT/MFT/tracking/src/Tracker.cxx" - } - }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-18T12:37:28Z", + "title": "PWGHF: Use pre-selections for Dplus", + "number": 5204, + "author": { + "login": "fcatalan92" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ITSMFT/MFT/tracking/src/TrackerConfig.cxx" + "path": "Analysis/Tasks/PWGHF/taskDPlus.cxx" } } ] @@ -3165,77 +2600,82 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-23T21:37:54Z", - "title": "ZDC Workflow to inspect raw data", - "number": 5092, + "mergedAt": "2021-01-18T08:09:01Z", + "title": "Change task names, move initializers", + "number": 5205, "author": { - "login": "cortesep" + "login": "ddobrigk" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/ZDC/CMakeLists.txt" - } - }, - { - "node": { - "path": "DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h" - } - }, - { - "node": { - "path": "DataFormats/Detectors/ZDC/src/RawEventData.cxx" + "path": "Analysis/Tasks/PWGLF/CMakeLists.txt" } }, { "node": { - "path": "Detectors/ZDC/CMakeLists.txt" + "path": "Analysis/Tasks/PWGLF/cascadeanalysis.cxx" } }, { "node": { - "path": "Detectors/ZDC/base/src/ModuleConfig.cxx" + "path": "Analysis/Tasks/PWGLF/cascadebuilder.cxx" } }, { "node": { - "path": "Detectors/ZDC/raw/CMakeLists.txt" + "path": "Analysis/Tasks/PWGLF/cascadefinder.cxx" } }, { "node": { - "path": "Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h" + "path": "Analysis/Tasks/PWGLF/lambdakzeroanalysis.cxx" } }, { "node": { - "path": "Detectors/ZDC/raw/src/DumpRaw.cxx" + "path": "Analysis/Tasks/PWGLF/lambdakzerobuilder.cxx" } }, { "node": { - "path": "Detectors/ZDC/raw/src/ZDCRawLinkDef.h" + "path": "Analysis/Tasks/PWGLF/lambdakzerofinder.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-19T08:55:29Z", + "title": "TableMaker task updated to use configurables for system type, event and track selections", + "number": 5206, + "author": { + "login": "iarsene" + }, + "files": { + "edges": [ { "node": { - "path": "Detectors/ZDC/raw/src/raw-parser.cxx" + "path": "Analysis/PWGDQ/include/PWGDQCore/HistogramsLibrary.h" } }, { "node": { - "path": "Detectors/ZDC/simulation/CMakeLists.txt" + "path": "Analysis/PWGDQ/include/PWGDQCore/VarManager.h" } }, { "node": { - "path": "Detectors/ZDC/simulation/src/Digitizer.cxx" + "path": "Analysis/PWGDQ/src/VarManager.cxx" } }, { "node": { - "path": "Detectors/ZDC/simulation/src/digi2raw.cxx" + "path": "Analysis/Tasks/PWGDQ/tableMaker.cxx" } } ] @@ -3244,18 +2684,28 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-24T13:43:32Z", - "title": "GPU: Exclude ITS Tracking / Vertexing parts from run time compilation", - "number": 5093, + "state": "OPEN", + "mergedAt": null, + "title": "[O2-1805] add BUILD_ANALYSIS cmake option (default ON)", + "number": 5207, "author": { - "login": "davidrohr" + "login": "aphecetche" }, "files": { "edges": [ { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + "path": "CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/CMakeLists.txt" + } + }, + { + "node": { + "path": "cmake/O2DefineOptions.cmake" } } ] @@ -3265,32 +2715,47 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-24T13:43:15Z", - "title": "GPU: Some work towards making the o2 propagator work on GPU", - "number": 5094, + "mergedAt": "2021-01-18T01:47:12Z", + "title": "TPC-ITS matching will use tpc-reco-workflow or on-the-fly created shared cl.map ", + "number": 5208, "author": { - "login": "davidrohr" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackLTIntegral.h" + "path": "Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h" + } + }, + { + "node": { + "path": "Detectors/GlobalTracking/src/MatchTPCITS.cxx" } }, { "node": { - "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" + "path": "Detectors/GlobalTrackingWorkflow/src/MatchTPCITSWorkflow.cxx" } }, { "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + "path": "Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h" } }, { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx" } } ] @@ -3299,18 +2764,18 @@ }, { "node": { - "state": "OPEN", + "state": "CLOSED", "mergedAt": null, - "title": "Draft HFMCValidation Heavy Flavour Monte Carlo validation", - "number": 5095, + "title": "small bugfix in nuclex code", + "number": 5209, "author": { - "login": "apalasciano" + "login": "akalweit" }, "files": { "edges": [ { "node": { - "path": "Analysis/Tasks/PWGHF/HFMCMatchingValidation.cxx" + "path": "Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx" } } ] @@ -3320,42 +2785,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-25T12:29:48Z", - "title": "Add possibility to use the GPUPolynomialField in the O2 propagator and make the O2 propagator compile on GPU", - "number": 5096, + "mergedAt": "2021-01-18T07:33:56Z", + "title": "small bug (re)fix, tpc momentum for dedx instead pvtx", + "number": 5210, "author": { - "login": "davidrohr" + "login": "akalweit" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Reconstruction/src/TrackLTIntegral.cxx" - } - }, - { - "node": { - "path": "Detectors/Base/CMakeLists.txt" - } - }, - { - "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" - } - }, - { - "node": { - "path": "Detectors/Base/src/Propagator.cxx" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Merger/GPUTPCGMPolynomialField.h" + "path": "Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx" } } ] @@ -3365,22 +2805,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2020-12-25T12:43:43Z", - "title": "TPC Tracking: Workaround for 0-cluster tracks", - "number": 5097, + "mergedAt": "2021-01-18T07:22:47Z", + "title": "o2-sim: Use vmc->ProcessEvent for Geant4", + "number": 5211, "author": { - "login": "davidrohr" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "Detectors/TPC/reconstruction/src/GPUCATracking.cxx" - } - }, - { - "node": { - "path": "GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx" + "path": "run/O2SimDevice.h" } } ] @@ -3389,18 +2824,23 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-27T08:29:55Z", - "title": "DPL: use RawDeviceService to sleep in example", - "number": 5098, + "state": "CLOSED", + "mergedAt": null, + "title": "[CMake][Generators] doBuildSimulation variable was intended to be local only", + "number": 5212, "author": { - "login": "ktf" + "login": "aphecetche" }, "files": { "edges": [ { "node": { - "path": "Framework/TestWorkflows/src/o2DiamondWorkflow.cxx" + "path": "Generators/CMakeLists.txt" + } + }, + { + "node": { + "path": "dependencies/O2SimulationDependencies.cmake" } } ] @@ -3410,167 +2850,227 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T18:52:58Z", - "title": "DPL: move GUI to a plugin", - "number": 5099, + "mergedAt": "2021-01-18T13:12:24Z", + "title": "Limit number of OMP TPC workers for small events", + "number": 5213, "author": { - "login": "ktf" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": "Framework/CMakeLists.txt" + "path": "GPU/GPUTracking/Base/GPUReconstruction.cxx" } }, { "node": { - "path": "Framework/Core/CMakeLists.txt" + "path": "GPU/GPUTracking/Base/GPUReconstruction.h" } }, { "node": { - "path": "Framework/Core/include/Framework/DataProcessorInfo.h" + "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.h" } }, { "node": { - "path": "Framework/Core/include/Framework/DebugGUI.h" + "path": "GPU/GPUTracking/Base/GPUSettingsList.h" } }, { "node": { - "path": "Framework/Core/include/Framework/DriverControl.h" + "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Add tables for the compressed Nsigma values", + "number": 5214, + "author": { + "login": "njacazio" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/include/Framework/DriverInfo.h" + "path": "Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h" } }, { "node": { - "path": "Framework/Core/include/Framework/Plugins.h" + "path": "Analysis/Tasks/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/DeviceSpecHelpers.h" + "path": "Analysis/Tasks/PWGLF/CMakeLists.txt" } }, { "node": { - "path": "Framework/Core/src/DriverControl.cxx" + "path": "Analysis/Tasks/PWGLF/spectraTOF_tiny.cxx" } }, { "node": { - "path": "Framework/Core/src/DriverInfo.cxx" + "path": "Analysis/Tasks/PWGLF/spectraTPC_tiny.cxx" } }, { "node": { - "path": "Framework/Core/src/FrameworkDummyDebugger.cxx" + "path": "Analysis/Tasks/pidTOF_tiny.cxx" } }, { "node": { - "path": "Framework/Core/src/WorkflowHelpers.h" + "path": "Analysis/Tasks/pidTPC_tiny.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-18T09:32:17Z", + "title": "Only run reports.yml in AliceO2Group/AliceO2", + "number": 5215, + "author": { + "login": "TimoWilken" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/src/WorkflowSerializationHelpers.h" + "path": ".github/workflows/reports.yml" } - }, + } + ] + } + } + }, + { + "node": { + "state": "MERGED", + "mergedAt": "2021-01-19T08:45:42Z", + "title": "TPC Workflow: Move cluster / digit reading from tpc tracking spec into a helper", + "number": 5216, + "author": { + "login": "davidrohr" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/Core/src/runDataProcessing.cxx" + "path": "DataFormats/Detectors/TPC/include/DataFormatsTPC/ClusterNativeHelper.h" } }, { "node": { - "path": "Framework/GUISupport/CMakeLists.txt" + "path": "DataFormats/Detectors/TPC/include/DataFormatsTPC/WorkflowHelper.h" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.cxx" + "path": "DataFormats/Detectors/TPC/src/WorkflowHelper.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDataRelayerUsage.h" + "path": "Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDebugger.cxx" + "path": "Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDebugger.h" + "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx" + "path": "Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDeviceInspector.h" + "path": "Detectors/TPC/workflow/src/RecoWorkflow.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx" + "path": "Detectors/TPC/workflow/src/ZSSpec.cxx" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Setting up Skimming Tasks - spectraTPC", + "number": 5217, + "author": { + "login": "nzardosh" + }, + "files": { + "edges": [ { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIDevicesGraph.h" + "path": "Analysis/Tasks/CMakeLists.txt" } }, { "node": { - "path": "Framework/GUISupport/src/FrameworkGUIState.h" + "path": "Analysis/Tasks/SkimmingTutorials/CMakeLists.txt" } }, { "node": { - "path": "Framework/GUISupport/src/NoDebugGUI.h" + "path": "Analysis/Tasks/SkimmingTutorials/DataModel/LFDerived.h" } }, { "node": { - "path": "Framework/GUISupport/src/PaletteHelpers.cxx" + "path": "Analysis/Tasks/SkimmingTutorials/LFDerived.h" } }, { "node": { - "path": "Framework/GUISupport/src/PaletteHelpers.h" + "path": "Analysis/Tasks/SkimmingTutorials/spectraTPCAnalyser.cxx" } }, { "node": { - "path": "Framework/GUISupport/src/Plugin.cxx" + "path": "Analysis/Tasks/SkimmingTutorials/spectraTPCProvider.cxx" } }, { "node": { - "path": "Framework/GUISupport/test/test_CustomGUIGL.cxx" + "path": "Analysis/Tasks/SkimmingTutorials/spectraTPCReference.cxx" } }, { "node": { - "path": "Framework/GUISupport/test/test_CustomGUISokol.cxx" + "path": "Common/MathUtils/include/MathUtils/Utils.h" } }, { "node": { - "path": "Framework/GUISupport/test/test_SimpleTracksED.cxx" + "path": "Common/MathUtils/include/MathUtils/detail/TypeTruncation.h" } } ] @@ -3579,23 +3079,38 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-28T10:37:16Z", - "title": "GPU: Make more headers compatible to GPU", - "number": 5100, + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF: Adding flag selection in the hadron tasks", + "number": 5218, "author": { - "login": "davidrohr" + "login": "DelloStritto" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h" + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFLcCandidateSelector.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/taskD0.cxx" } }, { "node": { - "path": "DataFormats/common/include/CommonDataFormat/RangeReference.h" + "path": "Analysis/Tasks/PWGHF/taskLc.cxx" } } ] @@ -3604,18 +3119,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-29T19:17:29Z", - "title": "[EMCAL-675] Handling of pages without trailer", - "number": 5101, + "state": "OPEN", + "mergedAt": null, + "title": "First version of ALICE3toAO2D macro", + "number": 5219, "author": { - "login": "mfasDa" + "login": "ddobrigk" }, "files": { "edges": [ { "node": { - "path": "Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx" + "path": "macro/ALICE3/ALICE3toAO2D.C" } } ] @@ -3624,18 +3139,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2020-12-29T09:49:03Z", - "title": "Drop bad assert", - "number": 5102, + "state": "OPEN", + "mergedAt": null, + "title": "SpaceCharge: added function to set the density and potential directly", + "number": 5220, "author": { - "login": "ktf" + "login": "matthias-kleiner" }, "files": { "edges": [ { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx" + "path": "Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceCharge.h" } } ] @@ -3644,18 +3159,53 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "CTP Data structures development", - "number": 5103, + "state": "MERGED", + "mergedAt": "2021-01-19T15:36:52Z", + "title": "refactor TRD digit class", + "number": 5221, "author": { - "login": "lietava" + "login": "bazinski" }, "files": { "edges": [ { "node": { - "path": "DataFormats/Detectors/CTP/CTPRawData.h" + "path": "Detectors/TRD/base/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/TRD/base/include/TRDBase/Digit.h" + } + }, + { + "node": { + "path": "Detectors/TRD/base/include/TRDBase/FeeParam.h" + } + }, + { + "node": { + "path": "Detectors/TRD/base/src/Digit.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/base/src/FeeParam.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/base/src/TRDBaseLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/TRD/simulation/src/Digitizer.cxx" + } + }, + { + "node": { + "path": "Detectors/TRD/workflow/src/TRDTrapSimulatorSpec.cxx" } } ] @@ -3664,58 +3214,78 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T08:36:57Z", - "title": "Use DBSCAN for Time-Z clustering in PVertexing, debris reduction", - "number": 5104, + "state": "OPEN", + "mergedAt": null, + "title": "introduce MCH ROFRecord.h + modify tracking workflows to process several ROF per TF", + "number": 5222, "author": { - "login": "shahor02" + "login": "pillot" }, "files": { "edges": [ { "node": { - "path": "DataFormats/simulation/include/SimulationDataFormat/MCEventLabel.h" + "path": "DataFormats/Detectors/MUON/MCH/CMakeLists.txt" + } + }, + { + "node": { + "path": "DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/ROFRecord.h" + } + }, + { + "node": { + "path": "DataFormats/Detectors/MUON/MCH/src/DataFormatsMCHLinkDef.h" + } + }, + { + "node": { + "path": "Detectors/MUON/MCH/Workflow/CMakeLists.txt" + } + }, + { + "node": { + "path": "Detectors/MUON/MCH/Workflow/README.md" + } + }, + { + "node": { + "path": "Detectors/MUON/MCH/Workflow/src/ClusterSamplerSpec.cxx" } }, { "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h" + "path": "Detectors/MUON/MCH/Workflow/src/TrackAtVertexSpec.cxx" } }, { "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerHelpers.h" + "path": "Detectors/MUON/MCH/Workflow/src/TrackFinderOriginalSpec.cxx" } }, { "node": { - "path": "Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h" + "path": "Detectors/MUON/MCH/Workflow/src/TrackFinderSpec.cxx" } }, { "node": { - "path": "Detectors/Vertexing/src/PVertexer.cxx" + "path": "Detectors/MUON/MCH/Workflow/src/TrackFitterSpec.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T11:22:50Z", - "title": "Disable CA_DEBUG in ITS Tracking", - "number": 5105, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ + }, + { + "node": { + "path": "Detectors/MUON/MCH/Workflow/src/TrackSamplerSpec.cxx" + } + }, + { + "node": { + "path": "Detectors/MUON/MCH/Workflow/src/TrackSinkSpec.cxx" + } + }, { "node": { - "path": "Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h" + "path": "Detectors/MUON/MCH/Workflow/src/VertexSamplerSpec.cxx" } } ] @@ -3725,17 +3295,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T09:27:57Z", - "title": "Add workflow to generate CHANGELOG", - "number": 5106, + "mergedAt": "2021-01-19T07:51:53Z", + "title": "PWGHF : syncing decays in the preselection with enums used for MC", + "number": 5223, "author": { - "login": "ktf" + "login": "nzardosh" }, "files": { "edges": [ { "node": { - "path": ".github/workflows/reports.yml" + "path": "Analysis/Core/include/AnalysisCore/HFConfigurables.h" + } + }, + { + "node": { + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx" } } ] @@ -3744,18 +3324,28 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T09:51:49Z", - "title": "Fix changelog generation", - "number": 5107, + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF: Shift decay type values to allow usage in arrays and bitmaps.", + "number": 5224, "author": { - "login": "ktf" + "login": "vkucera" }, "files": { "edges": [ { "node": { - "path": ".github/workflows/reports.yml" + "path": "Analysis/DataModel/include/AnalysisDataModel/HFSecondaryVertex.h" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx" + } + }, + { + "node": { + "path": "Analysis/Tasks/PWGHF/HFCandidateCreator3Prong.cxx" } } ] @@ -3765,17 +3355,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T10:17:44Z", - "title": "Fix CHANGELOG generation", - "number": 5108, + "mergedAt": "2021-01-19T09:18:17Z", + "title": "[EMCAL-630] Fix assignment of energy and time", + "number": 5225, "author": { - "login": "ktf" + "login": "mfasDa" }, "files": { "edges": [ { "node": { - "path": ".github/workflows/reports.yml" + "path": "Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx" } } ] @@ -3785,17 +3375,17 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T10:34:21Z", - "title": "Fix CHANGELOG generation", - "number": 5109, + "mergedAt": "2021-01-19T14:04:52Z", + "title": "Bugfix: WorkflowHelper.h was not installled", + "number": 5226, "author": { - "login": "ktf" + "login": "davidrohr" }, "files": { "edges": [ { "node": { - "path": ".github/workflows/reports.yml" + "path": "DataFormats/Detectors/TPC/CMakeLists.txt" } } ] @@ -3805,27 +3395,27 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T10:46:11Z", - "title": "Update CHANGELOG", - "number": 5110, + "mergedAt": "2021-01-19T16:07:16Z", + "title": "Check for selective primary transport also in case of parallel sim", + "number": 5227, "author": { - "login": "ktf" + "login": "preghenella" }, "files": { "edges": [ { "node": { - "path": "CHANGELOG.md" + "path": "DataFormats/simulation/include/SimulationDataFormat/MCTrack.h" } }, { "node": { - "path": "doc/data/2021-01-o2_prs.json" + "path": "DataFormats/simulation/include/SimulationDataFormat/Stack.h" } }, { "node": { - "path": "doc/data/2021-01-o2_releases.json" + "path": "DataFormats/simulation/src/Stack.cxx" } } ] @@ -3834,48 +3424,28 @@ }, { "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Rdev tof updates", - "number": 5111, + "state": "MERGED", + "mergedAt": "2021-01-19T13:19:49Z", + "title": "o2-sim: Make configfile prefixed with correct name", + "number": 5228, "author": { - "login": "preghenella" + "login": "sawenzel" }, "files": { "edges": [ { "node": { - "path": "Detectors/TOF/compression/src/tof-compressed-analysis.cxx" + "path": "DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/NameConf.h" } }, { "node": { - "path": "Detectors/TOF/compression/src/tof-compressed-inspector.cxx" + "path": "doc/DetectorSimulation.md" } }, { "node": { - "path": "Detectors/TOF/workflow/src/CompressedInspectorTask.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "CLOSED", - "mergedAt": null, - "title": "Drop cstdio include in GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx", - "number": 5112, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ - { - "node": { - "path": "GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx" + "path": "macro/o2sim.C" } } ] @@ -3885,27 +3455,22 @@ { "node": { "state": "MERGED", - "mergedAt": "2021-01-04T16:39:30Z", - "title": "DPL: drop unneeded include statements", - "number": 5113, + "mergedAt": "2021-01-19T18:31:34Z", + "title": "raw-parser logs DataHeader and DataProcessingHeader info", + "number": 5229, "author": { - "login": "ktf" + "login": "shahor02" }, "files": { "edges": [ { "node": { - "path": "Framework/Core/include/Framework/DataProcessingHeader.h" - } - }, - { - "node": { - "path": "Framework/Core/include/Framework/SourceInfoHeader.h" + "path": "Framework/Utils/include/DPLUtils/DPLRawParser.h" } }, { "node": { - "path": "Framework/Foundation/include/Framework/Pack.h" + "path": "Framework/Utils/src/raw-parser.cxx" } } ] @@ -3916,436 +3481,311 @@ "node": { "state": "OPEN", "mergedAt": null, - "title": "Rdev evgen updates", - "number": 5114, + "title": "Pileup and calibration DA for PHOS and CPV", + "number": 5230, "author": { - "login": "preghenella" + "login": "peressounko" }, "files": { "edges": [ { "node": { - "path": "Generators/include/Generators/Generator.h" + "path": "DataFormats/Detectors/PHOS/include/DataFormatsPHOS/Cluster.h" } }, { "node": { - "path": "Generators/include/Generators/GeneratorHepMC.h" + "path": "DataFormats/Detectors/PHOS/src/Cluster.cxx" } }, { "node": { - "path": "Generators/include/Generators/GeneratorPythia8.h" + "path": "Detectors/CPV/base/include/CPVBase/CPVSimParams.h" } }, { "node": { - "path": "Generators/include/Generators/GeneratorTGenerator.h" + "path": "Detectors/CPV/base/include/CPVBase/Geometry.h" } }, { "node": { - "path": "Generators/src/GeneratorPythia8.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T18:56:01Z", - "title": "Some minor improvements for GPU code", - "number": 5115, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ - { - "node": { - "path": "GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu" + "path": "Detectors/CPV/calib/CMakeLists.txt" } }, { "node": { - "path": "GPU/GPUTracking/Base/hip/GPUReconstructionHIP.hip.cxx" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/CMakeLists.txt" } }, { "node": { - "path": "GPU/GPUTracking/Base/opencl-common/GPUReconstructionOCL.cxx" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/include/CPVCalibWorkflow/CPVBadMapCalibDevice.h" } }, { "node": { - "path": "GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.cxx" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/include/CPVCalibWorkflow/CPVGainCalibDevice.h" } }, { "node": { - "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-05T09:40:39Z", - "title": "Global (currently TPC only) refit on GPU using either GPU or TrackParCov track model", - "number": 5116, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/include/CPVCalibWorkflow/CPVPedestalCalibDevice.h" } }, { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/src/CPVBadMapCalibDevice.cxx" } }, { "node": { - "path": "Detectors/TPC/workflow/src/CATrackerSpec.cxx" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/src/CPVGainCalibDevice.cxx" } }, { "node": { - "path": "GPU/Common/GPUDefGPUParameters.h" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/src/CPVPedestalCalibDevice.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUConstantMem.h" + "path": "Detectors/CPV/calib/CPVCalibWorkflow/src/cpv-calib-workflow.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUDataTypes.h" + "path": "Detectors/CPV/calib/include/CPVCalib/CalibParams.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUO2DataTypes.h" + "path": "Detectors/CPV/calib/include/CPVCalib/Pedestals.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUO2FakeClasses.h" + "path": "Detectors/CPV/calib/src/Pedestals.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUParam.cxx" + "path": "Detectors/CPV/simulation/include/CPVSimulation/Digitizer.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUParam.h" + "path": "Detectors/CPV/simulation/include/CPVSimulation/RawWriter.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.h" + "path": "Detectors/CPV/simulation/src/Detector.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionIncludesDevice.h" + "path": "Detectors/CPV/simulation/src/Digitizer.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionKernels.h" + "path": "Detectors/CPV/workflow/src/RecoWorkflow.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUSettingsList.h" + "path": "Detectors/PHOS/base/files/alignment.root" } }, { "node": { - "path": "GPU/GPUTracking/CMakeLists.txt" + "path": "Detectors/PHOS/base/include/PHOSBase/Geometry.h" } }, { "node": { - "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" + "path": "Detectors/PHOS/base/include/PHOSBase/PHOSSimParams.h" } }, { "node": { - "path": "GPU/GPUTracking/Global/GPUChainTracking.h" + "path": "Detectors/PHOS/base/src/Geometry.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Interface/GPUO2Interface.cxx" + "path": "Detectors/PHOS/calib/CMakeLists.txt" } }, { "node": { - "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.cxx" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/CMakeLists.txt" } }, { "node": { - "path": "GPU/GPUTracking/Refit/GPUTrackingRefit.h" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/include/PHOSCalibWorkflow/PHOSCalibCollector.h" } }, { "node": { - "path": "GPU/GPUTracking/Refit/GPUTrackingRefitKernel.cxx" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/include/PHOSCalibWorkflow/PHOSCalibCollectorSpec.h" } }, { "node": { - "path": "GPU/GPUTracking/Refit/GPUTrackingRefitKernel.h" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/include/PHOSCalibWorkflow/PHOSHGLGRatioCalibDevice.h" } }, { "node": { - "path": "GPU/GPUTracking/Standalone/standalone.cxx" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/include/PHOSCalibWorkflow/PHOSPedestalCalibDevice.h" } }, { "node": { - "path": "GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/src/PHOSCalibCollector.cxx" } }, { "node": { - "path": "GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-05T09:41:01Z", - "title": "GPU: Add option for the GPU backend to use nested OpenMP loops for better parallelism", - "number": 5117, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ - { - "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.cxx" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/src/PHOSCalibCollectorSpec.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUReconstructionCPU.h" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/src/PHOSCalibWorkflowLinkDef.h" } }, { "node": { - "path": "GPU/GPUTracking/Base/GPUSettingsList.h" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/src/PHOSHGLGRatioCalibDevice.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Global/GPUChainTracking.cxx" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/src/PHOSPedestalCalibDevice.cxx" } }, { "node": { - "path": "GPU/GPUTracking/SliceTracker/GPUTPCTracker.cxx" - } - } - ] - } - } - }, - { - "node": { - "state": "MERGED", - "mergedAt": "2021-01-04T21:48:17Z", - "title": "Default mat.corr. is with LUT, fall-back to TGeo if LUT is not set", - "number": 5118, - "author": { - "login": "shahor02" - }, - "files": { - "edges": [ - { - "node": { - "path": "Detectors/Base/include/DetectorsBase/Propagator.h" + "path": "Detectors/PHOS/calib/PHOSCalibWorkflow/src/phos-calib-workflow.cxx" } }, { "node": { - "path": "Detectors/Base/src/Propagator.cxx" + "path": "Detectors/PHOS/calib/include/PHOSCalib/BadChannelMap.h" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Updated CHANGELOG", - "number": 5119, - "author": { - "login": "ktf" - }, - "files": { - "edges": [ + }, { "node": { - "path": "CHANGELOG.md" + "path": "Detectors/PHOS/calib/include/PHOSCalib/CalibParams.h" } }, { "node": { - "path": "doc/data/2021-01-o2_prs.json" + "path": "Detectors/PHOS/calib/include/PHOSCalib/Pedestals.h" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Correctly use object passed to MID decoder constructor", - "number": 5120, - "author": { - "login": "dstocco" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/MUON/MID/Raw/src/Decoder.cxx" + "path": "Detectors/PHOS/calib/src/BadChannelMap.cxx" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Match all subspecs unless one subspec is passed explicitely", - "number": 5121, - "author": { - "login": "dstocco" - }, - "files": { - "edges": [ + }, { "node": { - "path": "Detectors/MUON/MID/Workflow/include/MIDWorkflow/RawDecoderSpec.h" + "path": "Detectors/PHOS/calib/src/CalibParams.cxx" } }, { "node": { - "path": "Detectors/MUON/MID/Workflow/src/RawDecoderSpec.cxx" + "path": "Detectors/PHOS/calib/src/PHOSCalibLinkDef.h" } - } - ] - } - } - }, - { - "node": { - "state": "OPEN", - "mergedAt": null, - "title": "Fix codechecker violations", - "number": 5122, - "author": { - "login": "davidrohr" - }, - "files": { - "edges": [ + }, { "node": { - "path": "DataFormats/Detectors/FIT/FT0/include/DataFormatsFT0/LookUpTable.h" + "path": "Detectors/PHOS/calib/src/Pedestals.cxx" } }, { "node": { - "path": "Detectors/PHOS/base/src/Mapping.cxx" + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/CaloRawFitter.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/Bunch.cxx" + "path": "Detectors/PHOS/reconstruction/include/PHOSReconstruction/FullCluster.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/CaloRawFitter.cxx" + "path": "Detectors/PHOS/reconstruction/src/FullCluster.cxx" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/Channel.cxx" + "path": "Detectors/PHOS/reconstruction/src/PHOSReconstructionLinkDef.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/RawBuffer.cxx" + "path": "Detectors/PHOS/simulation/include/PHOSSimulation/Digitizer.h" } }, { "node": { - "path": "Detectors/PHOS/reconstruction/src/RawPayload.cxx" + "path": "Detectors/PHOS/simulation/src/Digitizer.cxx" } }, { "node": { - "path": "Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h" + "path": "Steer/DigitizerWorkflow/src/CPVDigitizerSpec.cxx" } }, { "node": { - "path": "Detectors/ZDC/raw/src/DumpRaw.cxx" + "path": "Steer/DigitizerWorkflow/src/CPVDigitizerSpec.h" } }, { "node": { - "path": "Detectors/ZDC/raw/src/raw-parser.cxx" + "path": "Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.cxx" } }, { "node": { - "path": "GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h" + "path": "Steer/DigitizerWorkflow/src/PHOSDigitizerSpec.h" } - }, + } + ] + } + } + }, + { + "node": { + "state": "OPEN", + "mergedAt": null, + "title": "Make sure benchmark::benchmark stays optional (O2-1973)", + "number": 5231, + "author": { + "login": "ktf" + }, + "files": { + "edges": [ { "node": { - "path": "GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h" + "path": "Framework/Utils/CMakeLists.txt" } }, { "node": { - "path": "Utilities/Tools/cpulimit/cpulimit.c" + "path": "Utilities/Mergers/CMakeLists.txt" } }, { "node": { - "path": "Utilities/Tools/cpulimit/list.c" + "path": "Utilities/rANS/CMakeLists.txt" } } ] @@ -4354,18 +3794,18 @@ }, { "node": { - "state": "MERGED", - "mergedAt": "2021-01-05T14:19:35Z", - "title": "Allow forcing by hand last release tag", - "number": 5123, + "state": "OPEN", + "mergedAt": null, + "title": "PWGHF : further restricitng HF preselection for hyperloop testing", + "number": 5232, "author": { - "login": "ktf" + "login": "nzardosh" }, "files": { "edges": [ { "node": { - "path": ".github/workflows/reports.yml" + "path": "Analysis/Core/include/AnalysisCore/HFConfigurables.h" } } ] diff --git a/doc/data/2021-01-o2_releases.json b/doc/data/2021-01-o2_releases.json index 26c8a2e6983f9..fe7288db28373 100644 --- a/doc/data/2021-01-o2_releases.json +++ b/doc/data/2021-01-o2_releases.json @@ -25,6 +25,12 @@ "tagName": "v20.49", "publishedAt": "2020-12-11T16:12:56Z" } + }, + { + "node": { + "tagName": "v21.01", + "publishedAt": "2021-01-05T16:47:05Z" + } } ] }